summaryrefslogtreecommitdiffstats
path: root/private/ole32
diff options
context:
space:
mode:
Diffstat (limited to 'private/ole32')
-rw-r--r--private/ole32/cairobld.mk51
-rw-r--r--private/ole32/changes.txt96
-rw-r--r--private/ole32/chicago.inc37
-rw-r--r--private/ole32/com/accctrl/acext.h52
-rw-r--r--private/ole32/com/accctrl/acpickl.acf9
-rw-r--r--private/ole32/com/accctrl/acpickl.idl84
-rw-r--r--private/ole32/com/accctrl/acsrv.cxx264
-rw-r--r--private/ole32/com/accctrl/caccctrl.cxx5905
-rw-r--r--private/ole32/com/accctrl/caccctrl.h407
-rw-r--r--private/ole32/com/accctrl/cache.cxx550
-rw-r--r--private/ole32/com/accctrl/cache.h159
-rw-r--r--private/ole32/com/accctrl/daytona/makefile10
-rw-r--r--private/ole32/com/accctrl/daytona/makefile.inc1
-rw-r--r--private/ole32/com/accctrl/daytona/sources72
-rw-r--r--private/ole32/com/accctrl/dirs40
-rw-r--r--private/ole32/com/accctrl/makeidl.inc24
-rw-r--r--private/ole32/com/class/alocdbg.cxx731
-rw-r--r--private/ole32/com/class/bestfit.hxx450
-rw-r--r--private/ole32/com/class/cerror.cxx1236
-rw-r--r--private/ole32/com/class/classmap.hxx253
-rw-r--r--private/ole32/com/class/cocrguid.cxx89
-rw-r--r--private/ole32/com/class/compapi.cxx2542
-rw-r--r--private/ole32/com/class/compobj.cxx1879
-rw-r--r--private/ole32/com/class/cspytbl.cxx350
-rw-r--r--private/ole32/com/class/cspytbl.hxx57
-rw-r--r--private/ole32/com/class/daytona/compob32.src626
-rw-r--r--private/ole32/com/class/daytona/makefile10
-rw-r--r--private/ole32/com/class/daytona/makefile.inc1
-rw-r--r--private/ole32/com/class/daytona/sources78
-rw-r--r--private/ole32/com/class/dirs38
-rw-r--r--private/ole32/com/class/filelist.mk119
-rw-r--r--private/ole32/com/class/fixheap.hxx113
-rw-r--r--private/ole32/com/class/longpath.cxx544
-rw-r--r--private/ole32/com/class/makefile25
-rw-r--r--private/ole32/com/class/memapi.cxx1549
-rw-r--r--private/ole32/com/class/ole1guid.cxx284
-rw-r--r--private/ole32/com/class/ole1guid.h21
-rw-r--r--private/ole32/com/class/perfmnce.cxx286
-rw-r--r--private/ole32/com/class/tls.cxx366
-rw-r--r--private/ole32/com/class/tracelog.cxx490
-rw-r--r--private/ole32/com/coll/array_fv.ctt85
-rw-r--r--private/ole32/com/coll/array_fv.cxx342
-rw-r--r--private/ole32/com/coll/daytona/makefile10
-rw-r--r--private/ole32/com/coll/daytona/sources77
-rw-r--r--private/ole32/com/coll/dirs38
-rw-r--r--private/ole32/com/coll/filelist.mk54
-rw-r--r--private/ole32/com/coll/makefile24
-rw-r--r--private/ole32/com/coll/map_fkv.ctt76
-rw-r--r--private/ole32/com/coll/map_kv.cxx565
-rw-r--r--private/ole32/com/coll/map_skv.ctt76
-rw-r--r--private/ole32/com/coll/plex.cxx50
-rw-r--r--private/ole32/com/coll/sources.inc3
-rw-r--r--private/ole32/com/dcomidl/daytona/makefile10
-rw-r--r--private/ole32/com/dcomidl/daytona/makefile.inc4
-rw-r--r--private/ole32/com/dcomidl/daytona/sources69
-rw-r--r--private/ole32/com/dcomidl/dirs37
-rw-r--r--private/ole32/com/dcomidl/dscm.idl126
-rw-r--r--private/ole32/com/dcomidl/empty.cxx5
-rw-r--r--private/ole32/com/dcomidl/filelist.mk90
-rw-r--r--private/ole32/com/dcomidl/getif.idl44
-rw-r--r--private/ole32/com/dcomidl/host.idl33
-rw-r--r--private/ole32/com/dcomidl/irot.acf24
-rw-r--r--private/ole32/com/dcomidl/irot.idl108
-rw-r--r--private/ole32/com/dcomidl/makefil014
-rw-r--r--private/ole32/com/dcomidl/makefile27
-rw-r--r--private/ole32/com/dcomidl/makeidl.inc117
-rw-r--r--private/ole32/com/dcomidl/multqi.idl49
-rw-r--r--private/ole32/com/dcomidl/objsrv.acf17
-rw-r--r--private/ole32/com/dcomidl/objsrv.idl85
-rw-r--r--private/ole32/com/dcomidl/oleprv.h17
-rw-r--r--private/ole32/com/dcomidl/oleprv.idl19
-rw-r--r--private/ole32/com/dcomidl/scm.acf20
-rw-r--r--private/ole32/com/dcomidl/scm.idl119
-rw-r--r--private/ole32/com/dcomidl/sources.inc3
-rw-r--r--private/ole32/com/dcomrem/callctrl.cxx1820
-rw-r--r--private/ole32/com/dcomrem/callctrl.hxx525
-rw-r--r--private/ole32/com/dcomrem/chancont.cxx1098
-rw-r--r--private/ole32/com/dcomrem/chancont.hxx171
-rw-r--r--private/ole32/com/dcomrem/channelb.cxx2665
-rw-r--r--private/ole32/com/dcomrem/channelb.hxx259
-rw-r--r--private/ole32/com/dcomrem/chock.cxx974
-rw-r--r--private/ole32/com/dcomrem/chock.hxx173
-rw-r--r--private/ole32/com/dcomrem/coapi.cxx773
-rw-r--r--private/ole32/com/dcomrem/daytona/makefile10
-rw-r--r--private/ole32/com/dcomrem/daytona/sources87
-rw-r--r--private/ole32/com/dcomrem/dirs37
-rw-r--r--private/ole32/com/dcomrem/filelist.mk58
-rw-r--r--private/ole32/com/dcomrem/hash.cxx432
-rw-r--r--private/ole32/com/dcomrem/hash.hxx277
-rw-r--r--private/ole32/com/dcomrem/idtable.cxx625
-rw-r--r--private/ole32/com/dcomrem/idtable.hxx88
-rw-r--r--private/ole32/com/dcomrem/ipidtbl.cxx1502
-rw-r--r--private/ole32/com/dcomrem/ipidtbl.hxx485
-rw-r--r--private/ole32/com/dcomrem/ipmrshl.cxx652
-rw-r--r--private/ole32/com/dcomrem/locks.cxx75
-rw-r--r--private/ole32/com/dcomrem/locks.hxx48
-rw-r--r--private/ole32/com/dcomrem/makefile24
-rw-r--r--private/ole32/com/dcomrem/mapdwp.hxx108
-rw-r--r--private/ole32/com/dcomrem/marshal.cxx4974
-rw-r--r--private/ole32/com/dcomrem/marshal.hxx388
-rw-r--r--private/ole32/com/dcomrem/orpc_dbg.c643
-rw-r--r--private/ole32/com/dcomrem/orpc_dbg.h219
-rw-r--r--private/ole32/com/dcomrem/pgalloc.cxx317
-rw-r--r--private/ole32/com/dcomrem/pgalloc.hxx96
-rw-r--r--private/ole32/com/dcomrem/remoteu.cxx710
-rw-r--r--private/ole32/com/dcomrem/remoteu.hxx93
-rw-r--r--private/ole32/com/dcomrem/resolver.cxx2959
-rw-r--r--private/ole32/com/dcomrem/resolver.hxx269
-rw-r--r--private/ole32/com/dcomrem/riftbl.cxx567
-rw-r--r--private/ole32/com/dcomrem/riftbl.hxx79
-rw-r--r--private/ole32/com/dcomrem/rpcspy.hxx204
-rw-r--r--private/ole32/com/dcomrem/security.cxx3060
-rw-r--r--private/ole32/com/dcomrem/security.hxx239
-rw-r--r--private/ole32/com/dcomrem/service.cxx818
-rw-r--r--private/ole32/com/dcomrem/service.hxx33
-rw-r--r--private/ole32/com/dcomrem/stdid.cxx1378
-rw-r--r--private/ole32/com/dcomrem/stdid.hxx143
-rw-r--r--private/ole32/com/dcomrem/stream.cxx605
-rw-r--r--private/ole32/com/dcomrem/stream.hxx94
-rw-r--r--private/ole32/com/dcomrem/threads.cxx340
-rw-r--r--private/ole32/com/dcomrem/threads.hxx190
-rw-r--r--private/ole32/com/dde/client/cnct_tbl.cxx182
-rw-r--r--private/ole32/com/dde/client/cnct_tbl.h27
-rw-r--r--private/ole32/com/dde/client/daytona/makefile10
-rw-r--r--private/ole32/com/dde/client/daytona/sources85
-rw-r--r--private/ole32/com/dde/client/ddechc.cxx89
-rw-r--r--private/ole32/com/dde/client/ddechc.hxx115
-rw-r--r--private/ole32/com/dde/client/ddecnvrt.cxx348
-rw-r--r--private/ole32/com/dde/client/ddedo.cxx951
-rw-r--r--private/ole32/com/dde/client/ddeioc.cxx209
-rw-r--r--private/ole32/com/dde/client/ddemnker.cxx511
-rw-r--r--private/ole32/com/dde/client/ddeoo.cxx770
-rw-r--r--private/ole32/com/dde/client/ddeproxy.cxx2884
-rw-r--r--private/ole32/com/dde/client/ddeproxy.h730
-rw-r--r--private/ole32/com/dde/client/ddestg.cxx529
-rw-r--r--private/ole32/com/dde/client/ddewnd.cxx361
-rw-r--r--private/ole32/com/dde/client/ddeworkr.cxx1331
-rw-r--r--private/ole32/com/dde/client/dirs37
-rw-r--r--private/ole32/com/dde/client/modallp.cxx315
-rw-r--r--private/ole32/com/dde/client/packmnkr.cxx333
-rw-r--r--private/ole32/com/dde/client/packmnkr.h63
-rw-r--r--private/ole32/com/dde/client/trgt_dev.h19
-rw-r--r--private/ole32/com/dde/dirs36
-rw-r--r--private/ole32/com/dde/server/daytona/makefile10
-rw-r--r--private/ole32/com/dde/server/daytona/sources86
-rw-r--r--private/ole32/com/dde/server/ddeadv.cxx132
-rw-r--r--private/ole32/com/dde/server/ddeatoms.h42
-rw-r--r--private/ole32/com/dde/server/ddedebug.h99
-rw-r--r--private/ole32/com/dde/server/ddeerr.h78
-rw-r--r--private/ole32/com/dde/server/ddeint.h181
-rw-r--r--private/ole32/com/dde/server/ddepack.h20
-rw-r--r--private/ole32/com/dde/server/ddesink.cxx251
-rw-r--r--private/ole32/com/dde/server/ddesite.cxx89
-rw-r--r--private/ole32/com/dde/server/ddesrvr.cxx757
-rw-r--r--private/ole32/com/dde/server/ddesrvr.h26
-rw-r--r--private/ole32/com/dde/server/ddeutils.cxx1013
-rw-r--r--private/ole32/com/dde/server/dirs37
-rw-r--r--private/ole32/com/dde/server/doc.cxx1653
-rw-r--r--private/ole32/com/dde/server/item.cxx1210
-rw-r--r--private/ole32/com/dde/server/item2.cxx1405
-rw-r--r--private/ole32/com/dde/server/itemutil.cxx516
-rw-r--r--private/ole32/com/dde/server/itemutil.h14
-rw-r--r--private/ole32/com/dde/server/srvr.cxx2497
-rw-r--r--private/ole32/com/dde/server/srvr.h656
-rw-r--r--private/ole32/com/dde/server/srvrmain.cxx253
-rw-r--r--private/ole32/com/debug/assert.cxx97
-rw-r--r--private/ole32/com/debug/daytona/makefile10
-rw-r--r--private/ole32/com/debug/daytona/sources65
-rw-r--r--private/ole32/com/debug/dirs38
-rw-r--r--private/ole32/com/debug/filelist.mk55
-rw-r--r--private/ole32/com/debug/makefile24
-rw-r--r--private/ole32/com/debug/valid.cxx102
-rw-r--r--private/ole32/com/dirs50
-rw-r--r--private/ole32/com/idl/classf_c.sav295
-rw-r--r--private/ole32/com/idl/classf_s.sav255
-rw-r--r--private/ole32/com/idl/daytona/makefile10
-rw-r--r--private/ole32/com/idl/daytona/makefile.inc5
-rw-r--r--private/ole32/com/idl/daytona/sources66
-rw-r--r--private/ole32/com/idl/dirs36
-rw-r--r--private/ole32/com/idl/drot.acf10
-rw-r--r--private/ole32/com/idl/drot.idl46
-rw-r--r--private/ole32/com/idl/empty.cxx5
-rw-r--r--private/ole32/com/idl/filelist.mk90
-rw-r--r--private/ole32/com/idl/getif.acf10
-rw-r--r--private/ole32/com/idl/getif.idl50
-rw-r--r--private/ole32/com/idl/ichnl.acf37
-rw-r--r--private/ole32/com/idl/ichnl.idl116
-rw-r--r--private/ole32/com/idl/iface.idl176
-rw-r--r--private/ole32/com/idl/irot.acf30
-rw-r--r--private/ole32/com/idl/irot.idl105
-rw-r--r--private/ole32/com/idl/makefil014
-rw-r--r--private/ole32/com/idl/makefile27
-rw-r--r--private/ole32/com/idl/makeidl.inc91
-rw-r--r--private/ole32/com/idl/objsrv.acf13
-rw-r--r--private/ole32/com/idl/objsrv.idl57
-rw-r--r--private/ole32/com/idl/osrot.acf10
-rw-r--r--private/ole32/com/idl/osrot.idl74
-rw-r--r--private/ole32/com/idl/scm.acf32
-rw-r--r--private/ole32/com/idl/scm.idl171
-rw-r--r--private/ole32/com/idl/sources.inc3
-rw-r--r--private/ole32/com/inc/allguid.cxx170
-rw-r--r--private/ole32/com/inc/array_fv.h73
-rw-r--r--private/ole32/com/inc/array_id.h79
-rw-r--r--private/ole32/com/inc/assrtdlg.h9
-rw-r--r--private/ole32/com/inc/callinfo.h61
-rw-r--r--private/ole32/com/inc/cevent.cxx129
-rw-r--r--private/ole32/com/inc/cevent.hxx119
-rw-r--r--private/ole32/com/inc/clskey.hxx167
-rw-r--r--private/ole32/com/inc/compname.cxx94
-rw-r--r--private/ole32/com/inc/compname.hxx112
-rw-r--r--private/ole32/com/inc/comsrgt.hxx163
-rw-r--r--private/ole32/com/inc/daytona/makefile10
-rw-r--r--private/ole32/com/inc/daytona/sources83
-rw-r--r--private/ole32/com/inc/dbgpopup.cxx105
-rw-r--r--private/ole32/com/inc/dbgpopup.hxx65
-rw-r--r--private/ole32/com/inc/dirs38
-rw-r--r--private/ole32/com/inc/exttbl.cxx245
-rw-r--r--private/ole32/com/inc/exttbl.hxx199
-rw-r--r--private/ole32/com/inc/filelist.mk68
-rw-r--r--private/ole32/com/inc/guidmap.cxx225
-rw-r--r--private/ole32/com/inc/guidmap.hxx373
-rw-r--r--private/ole32/com/inc/longname.h33
-rw-r--r--private/ole32/com/inc/makefile24
-rw-r--r--private/ole32/com/inc/malloc.hxx21
-rw-r--r--private/ole32/com/inc/map_dwp.h66
-rw-r--r--private/ole32/com/inc/map_gp.h66
-rw-r--r--private/ole32/com/inc/map_sp.h67
-rw-r--r--private/ole32/com/inc/memdebug.hxx55
-rw-r--r--private/ole32/com/inc/ole2int.h383
-rw-r--r--private/ole32/com/inc/olecom.h56
-rw-r--r--private/ole32/com/inc/olereg.h32
-rw-r--r--private/ole32/com/inc/olespy.hxx66
-rw-r--r--private/ole32/com/inc/pathkey.cxx89
-rw-r--r--private/ole32/com/inc/pathkey.hxx143
-rw-r--r--private/ole32/com/inc/pattbl.cxx599
-rw-r--r--private/ole32/com/inc/pattbl.hxx265
-rw-r--r--private/ole32/com/inc/psctbl.cxx349
-rw-r--r--private/ole32/com/inc/psctbl.hxx438
-rw-r--r--private/ole32/com/inc/psctbl2.cxx1797
-rw-r--r--private/ole32/com/inc/psctbl2.hxx476
-rw-r--r--private/ole32/com/inc/rotdata.cxx242
-rw-r--r--private/ole32/com/inc/rotdata.hxx80
-rw-r--r--private/ole32/com/inc/rothelp.cxx125
-rw-r--r--private/ole32/com/inc/rothelp.hxx168
-rw-r--r--private/ole32/com/inc/rpcbind.hxx291
-rw-r--r--private/ole32/com/inc/scmmem.hxx53
-rw-r--r--private/ole32/com/inc/scmstart.hxx69
-rw-r--r--private/ole32/com/inc/secdes.hxx62
-rw-r--r--private/ole32/com/inc/shrtbl.hxx310
-rw-r--r--private/ole32/com/inc/shrtblc.cxx172
-rw-r--r--private/ole32/com/inc/shrtbls.cxx275
-rw-r--r--private/ole32/com/inc/skiplist.cxx600
-rw-r--r--private/ole32/com/inc/skiplist.hxx670
-rw-r--r--private/ole32/com/inc/sklist.cxx103
-rw-r--r--private/ole32/com/inc/sklist.hxx334
-rw-r--r--private/ole32/com/inc/smbasep.hxx30
-rw-r--r--private/ole32/com/inc/smblock.cxx321
-rw-r--r--private/ole32/com/inc/smblock.hxx262
-rw-r--r--private/ole32/com/inc/smcreate.cxx235
-rw-r--r--private/ole32/com/inc/smcreate.hxx44
-rw-r--r--private/ole32/com/inc/smmutex.cxx103
-rw-r--r--private/ole32/com/inc/smmutex.hxx205
-rw-r--r--private/ole32/com/inc/smstack.cxx175
-rw-r--r--private/ole32/com/inc/smstack.hxx290
-rw-r--r--private/ole32/com/inc/sources.inc2
-rw-r--r--private/ole32/com/inc/thread.hxx175
-rw-r--r--private/ole32/com/inc/tracelog.hxx181
-rw-r--r--private/ole32/com/inc/xmit.cxx302
-rw-r--r--private/ole32/com/inc/xmit.hxx180
-rw-r--r--private/ole32/com/inc/xstring.cxx184
-rw-r--r--private/ole32/com/moniker/cmonimp.h730
-rw-r--r--private/ole32/com/moniker/dfspath.hxx148
-rw-r--r--private/ole32/com/moniker/filemon.hxx399
-rw-r--r--private/ole32/com/moniker2/cantimon.cxx788
-rw-r--r--private/ole32/com/moniker2/cantimon.hxx79
-rw-r--r--private/ole32/com/moniker2/cbasemon.cxx251
-rw-r--r--private/ole32/com/moniker2/cbasemon.hxx107
-rw-r--r--private/ole32/com/moniker2/cbindctx.cxx610
-rw-r--r--private/ole32/com/moniker2/cbindctx.hxx75
-rw-r--r--private/ole32/com/moniker2/ccompmon.cxx3428
-rw-r--r--private/ole32/com/moniker2/ccompmon.hxx178
-rw-r--r--private/ole32/com/moniker2/cfactory.cxx589
-rw-r--r--private/ole32/com/moniker2/cfactory.hxx89
-rw-r--r--private/ole32/com/moniker2/cfilemon.cxx6709
-rw-r--r--private/ole32/com/moniker2/cfilemon.hxx296
-rw-r--r--private/ole32/com/moniker2/citemmon.cxx2055
-rw-r--r--private/ole32/com/moniker2/citemmon.hxx125
-rw-r--r--private/ole32/com/moniker2/classmon.cxx1336
-rw-r--r--private/ole32/com/moniker2/classmon.hxx182
-rw-r--r--private/ole32/com/moniker2/cmarshal.cxx225
-rw-r--r--private/ole32/com/moniker2/cmarshal.hxx51
-rw-r--r--private/ole32/com/moniker2/cmonimp.cxx2255
-rw-r--r--private/ole32/com/moniker2/cptrmon.cxx1188
-rw-r--r--private/ole32/com/moniker2/cptrmon.hxx88
-rw-r--r--private/ole32/com/moniker2/daytona/makefile10
-rw-r--r--private/ole32/com/moniker2/daytona/sources79
-rw-r--r--private/ole32/com/moniker2/dirs38
-rw-r--r--private/ole32/com/moniker2/extents.cxx475
-rw-r--r--private/ole32/com/moniker2/extents.hxx175
-rw-r--r--private/ole32/com/moniker2/filelist.mk48
-rw-r--r--private/ole32/com/moniker2/makefile24
-rw-r--r--private/ole32/com/moniker2/mkparse.cxx161
-rw-r--r--private/ole32/com/moniker2/mnk.h106
-rw-r--r--private/ole32/com/moniker2/shellink.hxx65
-rw-r--r--private/ole32/com/objact/actapi.cxx1373
-rw-r--r--private/ole32/com/objact/cobjact.cxx1452
-rw-r--r--private/ole32/com/objact/coscm.cxx1535
-rw-r--r--private/ole32/com/objact/coscm.hxx928
-rw-r--r--private/ole32/com/objact/daytona/makefile10
-rw-r--r--private/ole32/com/objact/daytona/sources76
-rw-r--r--private/ole32/com/objact/dirs38
-rw-r--r--private/ole32/com/objact/distname.cxx422
-rw-r--r--private/ole32/com/objact/dllapi.cxx161
-rw-r--r--private/ole32/com/objact/dllcache.cxx4060
-rw-r--r--private/ole32/com/objact/dllcache.hxx418
-rw-r--r--private/ole32/com/objact/dllhost.cxx676
-rw-r--r--private/ole32/com/objact/dllhost.hxx114
-rw-r--r--private/ole32/com/objact/filelist.mk60
-rw-r--r--private/ole32/com/objact/hobjact.cxx652
-rw-r--r--private/ole32/com/objact/makefile24
-rw-r--r--private/ole32/com/objact/objact.hxx274
-rw-r--r--private/ole32/com/objact/remapi.cxx524
-rw-r--r--private/ole32/com/objact/rrace.hxx23
-rw-r--r--private/ole32/com/objact/smstg.cxx129
-rw-r--r--private/ole32/com/objact/smstg.hxx179
-rw-r--r--private/ole32/com/objact/sobjact.cxx780
-rw-r--r--private/ole32/com/objact/sobjact.hxx133
-rw-r--r--private/ole32/com/objact/treat.cxx152
-rw-r--r--private/ole32/com/objact/treat.hxx129
-rw-r--r--private/ole32/com/precomp2.inc20
-rw-r--r--private/ole32/com/remote/callcont.cxx506
-rw-r--r--private/ole32/com/remote/callcont.hxx231
-rw-r--r--private/ole32/com/remote/callmain.cxx1858
-rw-r--r--private/ole32/com/remote/callmain.hxx505
-rw-r--r--private/ole32/com/remote/chancont.cxx1363
-rw-r--r--private/ole32/com/remote/chancont.hxx299
-rw-r--r--private/ole32/com/remote/channelb.cxx2708
-rw-r--r--private/ole32/com/remote/channelb.hxx369
-rw-r--r--private/ole32/com/remote/coapi.cxx1318
-rw-r--r--private/ole32/com/remote/daytona/makefile10
-rw-r--r--private/ole32/com/remote/daytona/sources88
-rw-r--r--private/ole32/com/remote/dd.cxx95
-rw-r--r--private/ole32/com/remote/dd.hxx374
-rw-r--r--private/ole32/com/remote/dde/client/cnct_tbl.cxx182
-rw-r--r--private/ole32/com/remote/dde/client/cnct_tbl.h27
-rw-r--r--private/ole32/com/remote/dde/client/daytona/makefile10
-rw-r--r--private/ole32/com/remote/dde/client/daytona/sources83
-rw-r--r--private/ole32/com/remote/dde/client/ddechc.cxx265
-rw-r--r--private/ole32/com/remote/dde/client/ddechc.hxx135
-rw-r--r--private/ole32/com/remote/dde/client/ddecnvrt.cxx348
-rw-r--r--private/ole32/com/remote/dde/client/ddedo.cxx954
-rw-r--r--private/ole32/com/remote/dde/client/ddeioc.cxx213
-rw-r--r--private/ole32/com/remote/dde/client/ddemnker.cxx527
-rw-r--r--private/ole32/com/remote/dde/client/ddeoo.cxx770
-rw-r--r--private/ole32/com/remote/dde/client/ddeproxy.cxx2899
-rw-r--r--private/ole32/com/remote/dde/client/ddeproxy.h608
-rw-r--r--private/ole32/com/remote/dde/client/ddestg.cxx535
-rw-r--r--private/ole32/com/remote/dde/client/ddewnd.cxx363
-rw-r--r--private/ole32/com/remote/dde/client/ddeworkr.cxx1331
-rw-r--r--private/ole32/com/remote/dde/client/dirs37
-rw-r--r--private/ole32/com/remote/dde/client/modallp.cxx201
-rw-r--r--private/ole32/com/remote/dde/client/packmnkr.cxx273
-rw-r--r--private/ole32/com/remote/dde/client/packmnkr.h63
-rw-r--r--private/ole32/com/remote/dde/client/trgt_dev.h19
-rw-r--r--private/ole32/com/remote/dde/dirs36
-rw-r--r--private/ole32/com/remote/dde/server/daytona/makefile10
-rw-r--r--private/ole32/com/remote/dde/server/daytona/sources83
-rw-r--r--private/ole32/com/remote/dde/server/ddeadv.cxx132
-rw-r--r--private/ole32/com/remote/dde/server/ddeatoms.h42
-rw-r--r--private/ole32/com/remote/dde/server/ddedebug.h99
-rw-r--r--private/ole32/com/remote/dde/server/ddeerr.h78
-rw-r--r--private/ole32/com/remote/dde/server/ddeint.h179
-rw-r--r--private/ole32/com/remote/dde/server/ddepack.h20
-rw-r--r--private/ole32/com/remote/dde/server/ddesink.cxx251
-rw-r--r--private/ole32/com/remote/dde/server/ddesite.cxx89
-rw-r--r--private/ole32/com/remote/dde/server/ddesrvr.cxx839
-rw-r--r--private/ole32/com/remote/dde/server/ddesrvr.h26
-rw-r--r--private/ole32/com/remote/dde/server/ddeutils.cxx1015
-rw-r--r--private/ole32/com/remote/dde/server/dirs37
-rw-r--r--private/ole32/com/remote/dde/server/doc.cxx1680
-rw-r--r--private/ole32/com/remote/dde/server/item.cxx1210
-rw-r--r--private/ole32/com/remote/dde/server/item2.cxx1400
-rw-r--r--private/ole32/com/remote/dde/server/itemutil.cxx516
-rw-r--r--private/ole32/com/remote/dde/server/itemutil.h14
-rw-r--r--private/ole32/com/remote/dde/server/srvr.cxx2369
-rw-r--r--private/ole32/com/remote/dde/server/srvr.h522
-rw-r--r--private/ole32/com/remote/dde/server/srvrmain.cxx388
-rw-r--r--private/ole32/com/remote/dirs36
-rw-r--r--private/ole32/com/remote/endpnt.cxx1109
-rw-r--r--private/ole32/com/remote/endpnt.hxx340
-rw-r--r--private/ole32/com/remote/filelist.mk58
-rw-r--r--private/ole32/com/remote/idtable.cxx653
-rw-r--r--private/ole32/com/remote/idtable.hxx72
-rw-r--r--private/ole32/com/remote/imchnl.cxx990
-rw-r--r--private/ole32/com/remote/ipmrshl.cxx659
-rw-r--r--private/ole32/com/remote/islocalp.cxx243
-rw-r--r--private/ole32/com/remote/islocalp.hxx104
-rw-r--r--private/ole32/com/remote/makefile24
-rw-r--r--private/ole32/com/remote/mapdwp.hxx108
-rw-r--r--private/ole32/com/remote/notify.cxx171
-rw-r--r--private/ole32/com/remote/orpc_dbg.c644
-rw-r--r--private/ole32/com/remote/orpc_dbg.h219
-rw-r--r--private/ole32/com/remote/remhdlr.cxx1645
-rw-r--r--private/ole32/com/remote/remhdlr.hxx463
-rw-r--r--private/ole32/com/remote/rpchelp.cxx88
-rw-r--r--private/ole32/com/remote/rpchelp.hxx56
-rw-r--r--private/ole32/com/remote/rpcspy.hxx204
-rw-r--r--private/ole32/com/remote/service.cxx1839
-rw-r--r--private/ole32/com/remote/service.hxx678
-rw-r--r--private/ole32/com/remote/sichnl.cxx918
-rw-r--r--private/ole32/com/remote/sichnl.hxx111
-rw-r--r--private/ole32/com/remote/stdid.cxx2288
-rw-r--r--private/ole32/com/remote/threads.cxx335
-rw-r--r--private/ole32/com/remote/threads.hxx190
-rw-r--r--private/ole32/com/rot/access.cxx293
-rw-r--r--private/ole32/com/rot/access.hxx77
-rw-r--r--private/ole32/com/rot/caller.cxx187
-rw-r--r--private/ole32/com/rot/caller.hxx74
-rw-r--r--private/ole32/com/rot/crot.cxx2137
-rw-r--r--private/ole32/com/rot/crot.hxx627
-rw-r--r--private/ole32/com/rot/crothint.cxx75
-rw-r--r--private/ole32/com/rot/crothint.hxx124
-rw-r--r--private/ole32/com/rot/daytona/makefile10
-rw-r--r--private/ole32/com/rot/daytona/sources70
-rw-r--r--private/ole32/com/rot/dbag.hxx225
-rw-r--r--private/ole32/com/rot/dirs38
-rw-r--r--private/ole32/com/rot/epid.cxx168
-rw-r--r--private/ole32/com/rot/epid.hxx58
-rw-r--r--private/ole32/com/rot/filelist.mk61
-rw-r--r--private/ole32/com/rot/getif.cxx1154
-rw-r--r--private/ole32/com/rot/hrotrpc.cxx70
-rw-r--r--private/ole32/com/rot/hrotrpc.hxx78
-rw-r--r--private/ole32/com/rot/makefile23
-rw-r--r--private/ole32/com/rot/mshif.hxx312
-rw-r--r--private/ole32/com/rot/safeif.hxx55
-rw-r--r--private/ole32/com/rot/scmrotif.hxx61
-rw-r--r--private/ole32/com/surrogat/filelist.mk53
-rw-r--r--private/ole32/com/surrogat/loadcls.cxx455
-rw-r--r--private/ole32/com/surrogat/loadcls.hxx434
-rw-r--r--private/ole32/com/surrogat/makefile18
-rw-r--r--private/ole32/com/surrogat/oleinit.hxx85
-rw-r--r--private/ole32/com/surrogat/surrogat.cxx427
-rw-r--r--private/ole32/com/util/daytona/makefile10
-rw-r--r--private/ole32/com/util/daytona/sources73
-rw-r--r--private/ole32/com/util/dirs38
-rw-r--r--private/ole32/com/util/exports.cxx793
-rw-r--r--private/ole32/com/util/filelist.mk61
-rw-r--r--private/ole32/com/util/ifnames.cxx886
-rw-r--r--private/ole32/com/util/info.cxx62
-rw-r--r--private/ole32/com/util/makefile24
-rw-r--r--private/ole32/com/util/olespy.cxx582
-rw-r--r--private/ole32/com/util/spyclnt.cxx301
-rw-r--r--private/ole32/com/util/spyclnt.hxx13
-rw-r--r--private/ole32/com/util/stkclip.cxx142
-rw-r--r--private/ole32/com/util/stkswtch.cxx672
-rw-r--r--private/ole32/com/util/task.cxx75
-rw-r--r--private/ole32/com/util/time.cxx415
-rw-r--r--private/ole32/com/util/utexcept.cxx55
-rw-r--r--private/ole32/com/util/utils.cxx44
-rw-r--r--private/ole32/com/util/utstream.cxx209
-rw-r--r--private/ole32/com/util/w32new.cxx47
-rw-r--r--private/ole32/com/util/widewrap.cxx2068
-rw-r--r--private/ole32/com/wx86grpa/daytona/makefile10
-rw-r--r--private/ole32/com/wx86grpa/daytona/sources68
-rw-r--r--private/ole32/com/wx86grpa/dirs37
-rw-r--r--private/ole32/com/wx86grpa/makefile23
-rw-r--r--private/ole32/com/wx86grpa/wx86grpa.cxx482
-rw-r--r--private/ole32/common/assert.cxx419
-rw-r--r--private/ole32/common/buffer.cxx121
-rw-r--r--private/ole32/common/buffer.hxx190
-rw-r--r--private/ole32/common/ccompapi.cxx250
-rw-r--r--private/ole32/common/comsrgt.cxx18
-rw-r--r--private/ole32/common/cruntime/crt0dat.c518
-rw-r--r--private/ole32/common/cruntime/crt0init.c70
-rw-r--r--private/ole32/common/cruntime/crt32.def34
-rw-r--r--private/ole32/common/cruntime/cruntime.h277
-rw-r--r--private/ole32/common/cruntime/cruntime.inc826
-rw-r--r--private/ole32/common/cruntime/ctype.c163
-rw-r--r--private/ole32/common/cruntime/daytona/dummy.c1
-rw-r--r--private/ole32/common/cruntime/daytona/i386/atlssup.asm15
-rw-r--r--private/ole32/common/cruntime/daytona/makefile6
-rw-r--r--private/ole32/common/cruntime/daytona/sources69
-rw-r--r--private/ole32/common/cruntime/daytona/tlssup.c52
-rw-r--r--private/ole32/common/cruntime/dirs37
-rw-r--r--private/ole32/common/cruntime/dllcrt0.c207
-rw-r--r--private/ole32/common/cruntime/i386/chkstk.asm126
-rw-r--r--private/ole32/common/cruntime/i386/llshr.asm91
-rw-r--r--private/ole32/common/cruntime/internal.h359
-rw-r--r--private/ole32/common/cruntime/isctype.c116
-rw-r--r--private/ole32/common/cruntime/mlock.c206
-rw-r--r--private/ole32/common/cruntime/mm.inc38
-rw-r--r--private/ole32/common/cruntime/nlsdata1.c23
-rw-r--r--private/ole32/common/cruntime/nlsdata2.c24
-rw-r--r--private/ole32/common/cruntime/onexit.c137
-rw-r--r--private/ole32/common/cruntime/os2dll.h131
-rw-r--r--private/ole32/common/cruntime/process.h244
-rw-r--r--private/ole32/common/cruntime/purevirt.c43
-rw-r--r--private/ole32/common/cruntime/qsort.c329
-rw-r--r--private/ole32/common/cruntime/setlocal.h44
-rw-r--r--private/ole32/common/cruntime/strtol.c224
-rw-r--r--private/ole32/common/cruntime/tidtable.c126
-rw-r--r--private/ole32/common/cruntime/xtow.c55
-rw-r--r--private/ole32/common/daytona/makefile10
-rw-r--r--private/ole32/common/daytona/sources79
-rw-r--r--private/ole32/common/dirs39
-rw-r--r--private/ole32/common/dprintf.c15
-rw-r--r--private/ole32/common/dprintf.h33
-rw-r--r--private/ole32/common/dynload.cxx656
-rw-r--r--private/ole32/common/eqguid.cxx54
-rw-r--r--private/ole32/common/oleprint.cxx650
-rw-r--r--private/ole32/common/oleprint.hxx74
-rw-r--r--private/ole32/common/olescm.cxx367
-rw-r--r--private/ole32/common/olesem.cxx175
-rw-r--r--private/ole32/common/oletype.cxx1359
-rw-r--r--private/ole32/common/outfuncs.c323
-rw-r--r--private/ole32/common/outfuncs.h25
-rw-r--r--private/ole32/common/output.c964
-rw-r--r--private/ole32/common/printf.c17
-rw-r--r--private/ole32/common/printf.h248
-rw-r--r--private/ole32/common/proto.h15
-rw-r--r--private/ole32/common/sprintf.c13
-rw-r--r--private/ole32/common/sym.hxx128
-rw-r--r--private/ole32/common/trace.cxx563
-rw-r--r--private/ole32/common/w4io.h49
-rw-r--r--private/ole32/common/wsprintf.c14
-rw-r--r--private/ole32/daytona.inc72
-rw-r--r--private/ole32/dbgexts/daytona/makefile6
-rw-r--r--private/ole32/dbgexts/daytona/sources112
-rw-r--r--private/ole32/dbgexts/dchannel.cxx152
-rw-r--r--private/ole32/dbgexts/dchannel.h39
-rw-r--r--private/ole32/dbgexts/dclscach.cxx370
-rw-r--r--private/ole32/dbgexts/dclscach.h109
-rw-r--r--private/ole32/dbgexts/dclsinfo.cxx607
-rw-r--r--private/ole32/dbgexts/ddllcach.cxx232
-rw-r--r--private/ole32/dbgexts/ddllcach.h99
-rw-r--r--private/ole32/dbgexts/derror.cxx135
-rw-r--r--private/ole32/dbgexts/dfileext.cxx158
-rw-r--r--private/ole32/dbgexts/dfilepat.cxx162
-rw-r--r--private/ole32/dbgexts/dinfolvl.cxx320
-rw-r--r--private/ole32/dbgexts/dinfolvl.h53
-rw-r--r--private/ole32/dbgexts/dipid.cxx341
-rw-r--r--private/ole32/dbgexts/dipid.h107
-rw-r--r--private/ole32/dbgexts/dirs38
-rw-r--r--private/ole32/dbgexts/dmoniker.cxx931
-rw-r--r--private/ole32/dbgexts/dmoniker.h215
-rw-r--r--private/ole32/dbgexts/doxid.cxx261
-rw-r--r--private/ole32/dbgexts/dpsclsid.cxx334
-rw-r--r--private/ole32/dbgexts/drot.cxx322
-rw-r--r--private/ole32/dbgexts/drot.h160
-rw-r--r--private/ole32/dbgexts/dshrdmem.h179
-rw-r--r--private/ole32/dbgexts/dstdid.cxx186
-rw-r--r--private/ole32/dbgexts/dstdid.h55
-rw-r--r--private/ole32/dbgexts/dtreatas.cxx142
-rw-r--r--private/ole32/dbgexts/dtreatas.h14
-rw-r--r--private/ole32/dbgexts/dvtbl.cxx131
-rw-r--r--private/ole32/dbgexts/ole.def29
-rw-r--r--private/ole32/dbgexts/ole.h107
-rw-r--r--private/ole32/dbgexts/ole.rc11
-rw-r--r--private/ole32/dbgexts/oleexts.cxx1145
-rw-r--r--private/ole32/dbgexts/util.cxx543
-rw-r--r--private/ole32/dcom95/docs/dcom95.docbin0 -> 33280 bytes
-rw-r--r--private/ole32/dcom95/lib/readme.txt6
-rw-r--r--private/ole32/dcom95/mstools/readme.txt4
-rw-r--r--private/ole32/dcomss/dcomss.h99
-rw-r--r--private/ole32/dcomss/dcomtest/makefile7
-rw-r--r--private/ole32/dcomss/dcomtest/makefile.inc33
-rw-r--r--private/ole32/dcomss/dcomtest/ortest.c1521
-rw-r--r--private/ole32/dcomss/dcomtest/sources56
-rw-r--r--private/ole32/dcomss/dcomtest/umisc.cxx384
-rw-r--r--private/ole32/dcomss/dcomtest/umisc.h57
-rw-r--r--private/ole32/dcomss/dcomtest/uor.acf5
-rw-r--r--private/ole32/dcomss/dcomtest/uor.idl31
-rw-r--r--private/ole32/dcomss/dcomtest/uor.rc10
-rw-r--r--private/ole32/dcomss/dirs30
-rw-r--r--private/ole32/dcomss/objex/blist.cxx136
-rw-r--r--private/ole32/dcomss/objex/blist.hxx127
-rw-r--r--private/ole32/dcomss/objex/callid.cxx113
-rw-r--r--private/ole32/dcomss/objex/callid.hxx35
-rw-r--r--private/ole32/dcomss/objex/coid.hxx138
-rw-r--r--private/ole32/dcomss/objex/coxid.hxx123
-rw-r--r--private/ole32/dcomss/objex/cset.hxx148
-rw-r--r--private/ole32/dcomss/objex/daytona/makefile7
-rw-r--r--private/ole32/dcomss/objex/daytona/sources45
-rw-r--r--private/ole32/dcomss/objex/dirs28
-rw-r--r--private/ole32/dcomss/objex/gentable.cxx429
-rw-r--r--private/ole32/dcomss/objex/gentable.hxx116
-rw-r--r--private/ole32/dcomss/objex/idtable.hxx208
-rw-r--r--private/ole32/dcomss/objex/list.hxx180
-rw-r--r--private/ole32/dcomss/objex/locks.cxx148
-rw-r--r--private/ole32/dcomss/objex/locks.hxx137
-rw-r--r--private/ole32/dcomss/objex/manager.cxx1877
-rw-r--r--private/ole32/dcomss/objex/mid.cxx143
-rw-r--r--private/ole32/dcomss/objex/mid.hxx208
-rw-r--r--private/ole32/dcomss/objex/misc.cxx695
-rw-r--r--private/ole32/dcomss/objex/misc.hxx46
-rw-r--r--private/ole32/dcomss/objex/objex.cxx506
-rw-r--r--private/ole32/dcomss/objex/or.h130
-rw-r--r--private/ole32/dcomss/objex/or.hxx153
-rw-r--r--private/ole32/dcomss/objex/orclnt.cxx799
-rw-r--r--private/ole32/dcomss/objex/orsvr.cxx714
-rw-r--r--private/ole32/dcomss/objex/plist.cxx107
-rw-r--r--private/ole32/dcomss/objex/plist.hxx125
-rw-r--r--private/ole32/dcomss/objex/process.cxx1180
-rw-r--r--private/ole32/dcomss/objex/process.hxx192
-rw-r--r--private/ole32/dcomss/objex/refobj.hxx70
-rw-r--r--private/ole32/dcomss/objex/shrmem/client/clt.cxx227
-rw-r--r--private/ole32/dcomss/objex/shrmem/client/makefile1
-rw-r--r--private/ole32/dcomss/objex/shrmem/client/sources109
-rw-r--r--private/ole32/dcomss/objex/shrmem/daytona.inc39
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/base.hxx240
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/callid.cxx113
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/callid.hxx35
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/daytona/makefile1
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/daytona/resolver.def37
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/daytona/sources99
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/dbg.cxx54
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/dbg.hxx110
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/detach.hxx4
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/dirs28
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/dsa.cxx126
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/dsa.hxx312
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/epts.c461
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/gentable.cxx269
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/gentable.hxx297
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/globals.cxx378
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/globals.hxx90
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/iface.cxx346
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/linklist.cxx173
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/linklist.hxx389
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/manager.cxx766
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/mid.cxx398
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/mid.hxx331
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/misc.cxx189
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/misc.hxx120
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/mutex.cxx104
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/mutex.hxx239
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/objex.cxx402
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/oxid.cxx521
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/oxid.hxx437
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/process.cxx453
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/process.hxx283
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/refobj.hxx82
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.cxx202
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.hxx38
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/set.hxx104
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/string.cxx685
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/string.hxx159
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcom95/time.hxx113
-rw-r--r--private/ole32/dcomss/objex/shrmem/dcomss.h81
-rw-r--r--private/ole32/dcomss/objex/shrmem/dirs32
-rw-r--r--private/ole32/dcomss/objex/shrmem/intor.hxx26
-rw-r--r--private/ole32/dcomss/objex/shrmem/makefil043
-rw-r--r--private/ole32/dcomss/objex/shrmem/or.h139
-rw-r--r--private/ole32/dcomss/objex/shrmem/or.hxx160
-rw-r--r--private/ole32/dcomss/objex/shrmem/server/makefile1
-rw-r--r--private/ole32/dcomss/objex/shrmem/server/serv.cxx303
-rw-r--r--private/ole32/dcomss/objex/shrmem/server/sources109
-rw-r--r--private/ole32/dcomss/objex/shrmem/smemor.hxx127
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/daytona/makefile1
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/daytona/sources64
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/dfdbg.cxx744
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/dirs27
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/fastlock.cxx433
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/simplell.cxx128
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/simplell.hxx180
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/smalloc.cxx1185
-rw-r--r--private/ole32/dcomss/objex/shrmem/stg/smalloc.hxx850
-rw-r--r--private/ole32/dcomss/objex/shrmem/test.acf3
-rw-r--r--private/ole32/dcomss/objex/shrmem/test.idl40
-rw-r--r--private/ole32/dcomss/objex/soid.hxx142
-rw-r--r--private/ole32/dcomss/objex/sources.inc43
-rw-r--r--private/ole32/dcomss/objex/soxid.hxx115
-rw-r--r--private/ole32/dcomss/objex/sset.hxx282
-rw-r--r--private/ole32/dcomss/objex/string.cxx683
-rw-r--r--private/ole32/dcomss/objex/string.hxx131
-rw-r--r--private/ole32/dcomss/objex/time.hxx108
-rw-r--r--private/ole32/dcomss/objex/token.cxx249
-rw-r--r--private/ole32/dcomss/objex/token.hxx96
-rw-r--r--private/ole32/dcomss/objex/worker.cxx411
-rw-r--r--private/ole32/dcomss/olescm/array_fv.cxx304
-rw-r--r--private/ole32/dcomss/olescm/atbits.hxx361
-rw-r--r--private/ole32/dcomss/olescm/clckpath.cxx99
-rw-r--r--private/ole32/dcomss/olescm/clckpath.hxx65
-rw-r--r--private/ole32/dcomss/olescm/cls.cxx3942
-rw-r--r--private/ole32/dcomss/olescm/cls.hxx858
-rw-r--r--private/ole32/dcomss/olescm/clsdata.cxx1582
-rw-r--r--private/ole32/dcomss/olescm/clsdata.hxx500
-rw-r--r--private/ole32/dcomss/olescm/daytona/makefile10
-rw-r--r--private/ole32/dcomss/olescm/daytona/sources96
-rw-r--r--private/ole32/dcomss/olescm/dbgprt.cxx156
-rw-r--r--private/ole32/dcomss/olescm/dbgprt.hxx45
-rw-r--r--private/ole32/dcomss/olescm/dfsext.cxx140
-rw-r--r--private/ole32/dcomss/olescm/dirs38
-rw-r--r--private/ole32/dcomss/olescm/dscmif.cxx315
-rw-r--r--private/ole32/dcomss/olescm/headers.cxx48
-rw-r--r--private/ole32/dcomss/olescm/init.cxx1448
-rw-r--r--private/ole32/dcomss/olescm/init.hxx30
-rw-r--r--private/ole32/dcomss/olescm/net.cxx71
-rw-r--r--private/ole32/dcomss/olescm/port.cxx280
-rw-r--r--private/ole32/dcomss/olescm/port.hxx374
-rw-r--r--private/ole32/dcomss/olescm/remact.cxx980
-rw-r--r--private/ole32/dcomss/olescm/remact.hxx128
-rw-r--r--private/ole32/dcomss/olescm/remactif.cxx244
-rw-r--r--private/ole32/dcomss/olescm/rotif.cxx650
-rw-r--r--private/ole32/dcomss/olescm/rotif.hxx30
-rw-r--r--private/ole32/dcomss/olescm/rpcalloc.cxx64
-rw-r--r--private/ole32/dcomss/olescm/scm.hxx283
-rw-r--r--private/ole32/dcomss/olescm/scm_afv.h73
-rw-r--r--private/ole32/dcomss/olescm/scmhash.cxx337
-rw-r--r--private/ole32/dcomss/olescm/scmhash.hxx301
-rw-r--r--private/ole32/dcomss/olescm/scmif.cxx1077
-rw-r--r--private/ole32/dcomss/olescm/scmlock.hxx130
-rw-r--r--private/ole32/dcomss/olescm/scmpre.inc15
-rw-r--r--private/ole32/dcomss/olescm/scmrot.cxx1019
-rw-r--r--private/ole32/dcomss/olescm/scmrot.hxx524
-rw-r--r--private/ole32/dcomss/olescm/scmsvc.cxx332
-rw-r--r--private/ole32/dcomss/olescm/secdesc.cxx282
-rw-r--r--private/ole32/dcomss/olescm/secdesc.h41
-rw-r--r--private/ole32/dcomss/olescm/srothint.cxx78
-rw-r--r--private/ole32/dcomss/olescm/srothint.hxx82
-rw-r--r--private/ole32/dcomss/olescm/srvreg.cxx826
-rw-r--r--private/ole32/dcomss/olescm/srvreg.hxx199
-rw-r--r--private/ole32/dcomss/wrapper/daytona/makefile7
-rw-r--r--private/ole32/dcomss/wrapper/daytona/rpcss.prf279
-rw-r--r--private/ole32/dcomss/wrapper/daytona/sources49
-rw-r--r--private/ole32/dcomss/wrapper/dcomss.rc10
-rw-r--r--private/ole32/dcomss/wrapper/dirs28
-rw-r--r--private/ole32/dcomss/wrapper/epts.c740
-rw-r--r--private/ole32/dcomss/wrapper/sources.inc42
-rw-r--r--private/ole32/dcomss/wrapper/start.cxx382
-rw-r--r--private/ole32/dirs57
-rw-r--r--private/ole32/dll/daytona/makefile10
-rw-r--r--private/ole32/dll/daytona/makefile.inc1
-rw-r--r--private/ole32/dll/daytona/ole32.prf1777
-rw-r--r--private/ole32/dll/daytona/sources121
-rw-r--r--private/ole32/dll/dcopy_c.curbin0 -> 326 bytes
-rw-r--r--private/ole32/dll/default.icobin0 -> 766 bytes
-rw-r--r--private/ole32/dll/dirs38
-rw-r--r--private/ole32/dll/dlink_c.curbin0 -> 326 bytes
-rw-r--r--private/ole32/dll/dmove_c.curbin0 -> 326 bytes
-rw-r--r--private/ole32/dll/dnone_c.curbin0 -> 326 bytes
-rw-r--r--private/ole32/dll/ole.icobin0 -> 766 bytes
-rw-r--r--private/ole32/dll/ole2w32.rc25
-rw-r--r--private/ole32/dll/ole32.def523
-rw-r--r--private/ole32/dll/scopy_c.curbin0 -> 326 bytes
-rw-r--r--private/ole32/dll/slink_c.curbin0 -> 326 bytes
-rw-r--r--private/ole32/dll/smove_c.curbin0 -> 326 bytes
-rw-r--r--private/ole32/dll/sources.inc9
-rw-r--r--private/ole32/dllhost/cdllsrv.cxx112
-rw-r--r--private/ole32/dllhost/cdllsrv.hxx55
-rw-r--r--private/ole32/dllhost/cmonitor.cxx35
-rw-r--r--private/ole32/dllhost/cmonitor.hxx48
-rw-r--r--private/ole32/dllhost/csrgt.cxx158
-rw-r--r--private/ole32/dllhost/csrgt.hxx70
-rw-r--r--private/ole32/dllhost/daytona/makefile33
-rw-r--r--private/ole32/dllhost/daytona/sources87
-rw-r--r--private/ole32/dllhost/dirs43
-rw-r--r--private/ole32/dllhost/dllhost.rc10
-rw-r--r--private/ole32/dllhost/libtable.cxx413
-rw-r--r--private/ole32/dllhost/libtable.hxx152
-rw-r--r--private/ole32/dllhost/srgtfact.cxx401
-rw-r--r--private/ole32/dllhost/srgtfact.hxx119
-rw-r--r--private/ole32/dllhost/surrogat.cxx321
-rw-r--r--private/ole32/dllhost/surrogat.hxx36
-rw-r--r--private/ole32/filelist.mk27
-rw-r--r--private/ole32/ih/alocdbg.h108
-rw-r--r--private/ole32/ih/chicole.reg380
-rw-r--r--private/ole32/ih/clsctx.hxx31
-rw-r--r--private/ole32/ih/ddesrvr.h24
-rw-r--r--private/ole32/ih/debug.h316
-rw-r--r--private/ole32/ih/dragopt.h163
-rw-r--r--private/ole32/ih/exports.hxx211
-rw-r--r--private/ole32/ih/getif.hxx32
-rw-r--r--private/ole32/ih/hkldinp.h100
-rw-r--r--private/ole32/ih/hklogevt.h34
-rw-r--r--private/ole32/ih/hkole32.h284
-rw-r--r--private/ole32/ih/hkole32x.h134
-rw-r--r--private/ole32/ih/hkoleobj.h71
-rw-r--r--private/ole32/ih/hkregkey.h76
-rw-r--r--private/ole32/ih/hkunkex.h31
-rw-r--r--private/ole32/ih/ictsguid.h108
-rw-r--r--private/ole32/ih/itrkmnk.hxx49
-rw-r--r--private/ole32/ih/map_kv.h116
-rw-r--r--private/ole32/ih/map_up.h66
-rw-r--r--private/ole32/ih/memapi.hxx190
-rw-r--r--private/ole32/ih/nt1ole.reg576
-rw-r--r--private/ole32/ih/nt2ole.reg780
-rw-r--r--private/ole32/ih/ole1cls.h148
-rw-r--r--private/ole32/ih/ole2com.h1001
-rw-r--r--private/ole32/ih/ole2sp.h411
-rw-r--r--private/ole32/ih/ole2ver.h15
-rw-r--r--private/ole32/ih/olecoll.h27
-rw-r--r--private/ole32/ih/olepfn.hxx39
-rw-r--r--private/ole32/ih/olerem.h165
-rw-r--r--private/ole32/ih/olesem.hxx305
-rw-r--r--private/ole32/ih/oletemp.h6
-rw-r--r--private/ole32/ih/osift.hxx29
-rw-r--r--private/ole32/ih/perfmnce.hxx119
-rw-r--r--private/ole32/ih/plex.h28
-rw-r--r--private/ole32/ih/privguid.h239
-rw-r--r--private/ole32/ih/privoa.h59
-rw-r--r--private/ole32/ih/resource.h10
-rw-r--r--private/ole32/ih/rothint.hxx124
-rw-r--r--private/ole32/ih/stkswtch.h200
-rw-r--r--private/ole32/ih/thkreg.h27
-rw-r--r--private/ole32/ih/thunkapi.hxx142
-rw-r--r--private/ole32/ih/tls.h367
-rw-r--r--private/ole32/ih/tlschico.h514
-rw-r--r--private/ole32/ih/trace.hxx206
-rw-r--r--private/ole32/ih/userapis.h76
-rw-r--r--private/ole32/ih/utils.h1560
-rw-r--r--private/ole32/ih/utstream.h205
-rw-r--r--private/ole32/ih/valid.h323
-rw-r--r--private/ole32/ih/verole.h5
-rw-r--r--private/ole32/ih/widewrap.h783
-rw-r--r--private/ole32/ih/wx86grpa.hxx80
-rw-r--r--private/ole32/ilib/compob32.def636
-rw-r--r--private/ole32/ilib/daytona/makefile10
-rw-r--r--private/ole32/ilib/daytona/makefile.inc17
-rw-r--r--private/ole32/ilib/daytona/sources63
-rw-r--r--private/ole32/ilib/depend.mk35
-rw-r--r--private/ole32/ilib/dirs38
-rw-r--r--private/ole32/ilib/filelist.mk59
-rw-r--r--private/ole32/ilib/makefile35
-rw-r--r--private/ole32/ilib/ole232xx.def415
-rw-r--r--private/ole32/ilib/ole2pr32.def28
-rw-r--r--private/ole32/ilib/pass0.mk13
-rw-r--r--private/ole32/ilib/readme.txt6
-rw-r--r--private/ole32/ilib/storag32.def115
-rw-r--r--private/ole32/ilib/uuidole.cxx15
-rw-r--r--private/ole32/makefile28
-rw-r--r--private/ole32/ole232/advise/daholder.cpp1479
-rw-r--r--private/ole32/ole232/advise/daytona/makefile10
-rw-r--r--private/ole32/ole232/advise/daytona/sources78
-rw-r--r--private/ole32/ole232/advise/depend.mk60
-rw-r--r--private/ole32/ole232/advise/dirs38
-rw-r--r--private/ole32/ole232/advise/filelist.mk50
-rw-r--r--private/ole32/ole232/advise/makefile26
-rw-r--r--private/ole32/ole232/advise/oaholder.cpp1002
-rw-r--r--private/ole32/ole232/advise/sources.inc1
-rw-r--r--private/ole32/ole232/base/api.cpp2430
-rw-r--r--private/ole32/ole232/base/create.cpp4803
-rw-r--r--private/ole32/ole232/base/daytona/makefile10
-rw-r--r--private/ole32/ole232/base/daytona/sources82
-rw-r--r--private/ole32/ole232/base/depend.mk165
-rw-r--r--private/ole32/ole232/base/dirs38
-rw-r--r--private/ole32/ole232/base/filelist.mk49
-rw-r--r--private/ole32/ole232/base/lockbyte.cpp259
-rw-r--r--private/ole32/ole232/base/makefile26
-rw-r--r--private/ole32/ole232/base/memstm.cpp3515
-rw-r--r--private/ole32/ole232/base/ole2.cpp577
-rw-r--r--private/ole32/ole232/base/privstm.cpp1476
-rw-r--r--private/ole32/ole232/cache/cachenod.cpp2444
-rw-r--r--private/ole32/ole232/cache/dacache.cpp645
-rw-r--r--private/ole32/ole232/cache/daytona/makefile10
-rw-r--r--private/ole32/ole232/cache/daytona/sources78
-rw-r--r--private/ole32/ole232/cache/depend.mk91
-rw-r--r--private/ole32/ole232/cache/dirs38
-rw-r--r--private/ole32/ole232/cache/filelist.mk51
-rw-r--r--private/ole32/ole232/cache/makefile26
-rw-r--r--private/ole32/ole232/cache/olecache.cpp6339
-rw-r--r--private/ole32/ole232/clipbrd/clipapi.cpp3722
-rw-r--r--private/ole32/ole232/clipbrd/clipbrd.cpp3815
-rw-r--r--private/ole32/ole232/clipbrd/clipdata.cpp5544
-rw-r--r--private/ole32/ole232/clipbrd/clipdata.h207
-rw-r--r--private/ole32/ole232/clipbrd/daytona/makefile10
-rw-r--r--private/ole32/ole232/clipbrd/daytona/sources77
-rw-r--r--private/ole32/ole232/clipbrd/depend.mk36
-rw-r--r--private/ole32/ole232/clipbrd/dirs38
-rw-r--r--private/ole32/ole232/clipbrd/filelist.mk48
-rw-r--r--private/ole32/ole232/clipbrd/makefile26
-rw-r--r--private/ole32/ole232/debug/cdebug.cpp1226
-rw-r--r--private/ole32/ole232/debug/daytona/makefile10
-rw-r--r--private/ole32/ole232/debug/daytona/sources79
-rw-r--r--private/ole32/ole232/debug/dbgdump.cpp1310
-rw-r--r--private/ole32/ole232/debug/debapi.cxx26
-rw-r--r--private/ole32/ole232/debug/depend.mk39
-rw-r--r--private/ole32/ole232/debug/dirs38
-rw-r--r--private/ole32/ole232/debug/dstream.cpp758
-rw-r--r--private/ole32/ole232/debug/filelist.mk53
-rw-r--r--private/ole32/ole232/debug/makefile26
-rw-r--r--private/ole32/ole232/dirs46
-rw-r--r--private/ole32/ole232/doc/autolink.txt154
-rw-r--r--private/ole32/ole232/doc/olesize.txt94
-rw-r--r--private/ole32/ole232/doc/preraid.txt87
-rw-r--r--private/ole32/ole232/doc/tracegrm.txt137
-rw-r--r--private/ole32/ole232/drag/daytona/makefile10
-rw-r--r--private/ole32/ole232/drag/daytona/sources77
-rw-r--r--private/ole32/ole232/drag/depend.mk35
-rw-r--r--private/ole32/ole232/drag/dirs38
-rw-r--r--private/ole32/ole232/drag/dmsgfltr.h88
-rw-r--r--private/ole32/ole232/drag/drag.cpp2514
-rw-r--r--private/ole32/ole232/drag/filelist.mk49
-rw-r--r--private/ole32/ole232/drag/ido.cpp1501
-rw-r--r--private/ole32/ole232/drag/makefile26
-rw-r--r--private/ole32/ole232/filelist.mk88
-rw-r--r--private/ole32/ole232/inc/cachenod.h229
-rw-r--r--private/ole32/ole232/inc/clipbrd.h185
-rw-r--r--private/ole32/ole232/inc/create.h76
-rw-r--r--private/ole32/ole232/inc/dacache.h135
-rw-r--r--private/ole32/ole232/inc/daholder.h179
-rw-r--r--private/ole32/ole232/inc/daytona/makefile10
-rw-r--r--private/ole32/ole232/inc/daytona/sources65
-rw-r--r--private/ole32/ole232/inc/dbgdump.h136
-rw-r--r--private/ole32/ole232/inc/dbgexts.h35
-rw-r--r--private/ole32/ole232/inc/dirs38
-rw-r--r--private/ole32/ole232/inc/drag.h433
-rw-r--r--private/ole32/ole232/inc/dstream.h162
-rw-r--r--private/ole32/ole232/inc/emf.h166
-rw-r--r--private/ole32/ole232/inc/empty.cxx26
-rw-r--r--private/ole32/ole232/inc/enumgen.h180
-rw-r--r--private/ole32/ole232/inc/fetcenum.h9
-rw-r--r--private/ole32/ole232/inc/gen.h104
-rw-r--r--private/ole32/ole232/inc/le2int.h664
-rw-r--r--private/ole32/ole232/inc/map_dwdw.h69
-rw-r--r--private/ole32/ole232/inc/map_lp.h69
-rw-r--r--private/ole32/ole232/inc/map_uhw.h69
-rw-r--r--private/ole32/ole232/inc/memstm.h390
-rw-r--r--private/ole32/ole232/inc/mf.h177
-rw-r--r--private/ole32/ole232/inc/oaholder.h116
-rw-r--r--private/ole32/ole232/inc/olecache.h554
-rw-r--r--private/ole32/ole232/inc/olepres.h73
-rw-r--r--private/ole32/ole232/inc/ostm2stg.h374
-rw-r--r--private/ole32/ole232/inc/qd2gdi.h152
-rw-r--r--private/ole32/ole232/inc/reterr.h67
-rw-r--r--private/ole32/ole232/inc/sources.inc2
-rw-r--r--private/ole32/ole232/inplace/daytona/makefile10
-rw-r--r--private/ole32/ole232/inplace/daytona/sources76
-rw-r--r--private/ole32/ole232/inplace/depend.mk33
-rw-r--r--private/ole32/ole232/inplace/dirs38
-rw-r--r--private/ole32/ole232/inplace/filelist.mk49
-rw-r--r--private/ole32/ole232/inplace/inplace.cpp2875
-rw-r--r--private/ole32/ole232/inplace/inplace.h151
-rw-r--r--private/ole32/ole232/inplace/makefile26
-rw-r--r--private/ole32/ole232/makefile25
-rw-r--r--private/ole32/ole232/ole.mk10
-rw-r--r--private/ole32/ole232/ole1/daytona/makefile10
-rw-r--r--private/ole32/ole232/ole1/daytona/sources78
-rw-r--r--private/ole32/ole232/ole1/ddecnvrt.cpp351
-rw-r--r--private/ole32/ole232/ole1/depend.mk34
-rw-r--r--private/ole32/ole232/ole1/dirs38
-rw-r--r--private/ole32/ole232/ole1/filelist.mk49
-rw-r--r--private/ole32/ole232/ole1/makefile26
-rw-r--r--private/ole32/ole232/ole1/ostm2stg.cpp5818
-rw-r--r--private/ole32/ole232/precomp2.inc21
-rw-r--r--private/ole32/ole232/stdimpl/clthndlr.cpp1157
-rw-r--r--private/ole32/ole232/stdimpl/clthndlr.h198
-rw-r--r--private/ole32/ole232/stdimpl/daytona/makefile10
-rw-r--r--private/ole32/ole232/stdimpl/daytona/sources82
-rw-r--r--private/ole32/ole232/stdimpl/defcf.cpp582
-rw-r--r--private/ole32/ole232/stdimpl/defcf.h67
-rw-r--r--private/ole32/ole232/stdimpl/defhndlr.cpp6112
-rw-r--r--private/ole32/ole232/stdimpl/defhndlr.h338
-rw-r--r--private/ole32/ole232/stdimpl/deflink.cpp7776
-rw-r--r--private/ole32/ole232/stdimpl/deflink.h302
-rw-r--r--private/ole32/ole232/stdimpl/defsrv.cpp585
-rw-r--r--private/ole32/ole232/stdimpl/defutil.cpp317
-rw-r--r--private/ole32/ole232/stdimpl/defutil.h46
-rw-r--r--private/ole32/ole232/stdimpl/depend.mk279
-rw-r--r--private/ole32/ole232/stdimpl/dirs38
-rw-r--r--private/ole32/ole232/stdimpl/emf.cpp1729
-rw-r--r--private/ole32/ole232/stdimpl/filelist.mk57
-rw-r--r--private/ole32/ole232/stdimpl/gen.cpp1908
-rw-r--r--private/ole32/ole232/stdimpl/handler.cpp197
-rw-r--r--private/ole32/ole232/stdimpl/handler.hxx126
-rw-r--r--private/ole32/ole232/stdimpl/icon.cpp2302
-rw-r--r--private/ole32/ole232/stdimpl/icon.h63
-rw-r--r--private/ole32/ole232/stdimpl/makefile26
-rw-r--r--private/ole32/ole232/stdimpl/mf.cpp2304
-rw-r--r--private/ole32/ole232/stdimpl/olereg.cpp667
-rw-r--r--private/ole32/ole232/stdimpl/oleregpv.h38
-rw-r--r--private/ole32/ole232/stdimpl/oregfmt.cpp2001
-rw-r--r--private/ole32/ole232/stdimpl/oregverb.cpp1254
-rw-r--r--private/ole32/ole232/stdimpl/srvhndlr.cpp1671
-rw-r--r--private/ole32/ole232/stdimpl/srvhndlr.h370
-rw-r--r--private/ole32/ole232/util/convert.cpp1209
-rw-r--r--private/ole32/ole232/util/daytona/makefile10
-rw-r--r--private/ole32/ole232/util/daytona/sources83
-rw-r--r--private/ole32/ole232/util/depend.mk237
-rw-r--r--private/ole32/ole232/util/dirs38
-rw-r--r--private/ole32/ole232/util/filelist.mk54
-rw-r--r--private/ole32/ole232/util/global.cpp821
-rw-r--r--private/ole32/ole232/util/info.cpp65
-rw-r--r--private/ole32/ole232/util/makefile26
-rw-r--r--private/ole32/ole232/util/map_kv.cpp666
-rw-r--r--private/ole32/ole232/util/ole2util.cpp1105
-rw-r--r--private/ole32/ole232/util/plex.cpp53
-rw-r--r--private/ole32/ole232/util/utils.cpp2726
-rw-r--r--private/ole32/ole232/util/utstream.cpp986
-rw-r--r--private/ole32/olecnfg/clshive.c310
-rw-r--r--private/ole32/olecnfg/main.c374
-rw-r--r--private/ole32/olecnfg/makefile6
-rw-r--r--private/ole32/olecnfg/olecnfg.c996
-rw-r--r--private/ole32/olecnfg/olecnfg.h121
-rw-r--r--private/ole32/olecnfg/olecnfg.rc50
-rw-r--r--private/ole32/olecnfg/sid.c255
-rw-r--r--private/ole32/olecnfg/sources74
-rw-r--r--private/ole32/olecnfg/treemgmt.c882
-rw-r--r--private/ole32/olecnfg/uenv.h26
-rw-r--r--private/ole32/olecnv32/api.c499
-rw-r--r--private/ole32/olecnv32/api.h155
-rw-r--r--private/ole32/olecnv32/bufio.c394
-rw-r--r--private/ole32/olecnv32/bufio.h49
-rw-r--r--private/ole32/olecnv32/cache.c1161
-rw-r--r--private/ole32/olecnv32/cache.h154
-rw-r--r--private/ole32/olecnv32/daytona/makefile10
-rw-r--r--private/ole32/olecnv32/daytona/makefile.inc1
-rw-r--r--private/ole32/olecnv32/daytona/olecnv32.src35
-rw-r--r--private/ole32/olecnv32/daytona/sources83
-rw-r--r--private/ole32/olecnv32/dirs40
-rw-r--r--private/ole32/olecnv32/error.c74
-rw-r--r--private/ole32/olecnv32/error.h56
-rw-r--r--private/ole32/olecnv32/filesys.h89
-rw-r--r--private/ole32/olecnv32/gdiprim.c4080
-rw-r--r--private/ole32/olecnv32/gdiprim.h257
-rw-r--r--private/ole32/olecnv32/getdata.c932
-rw-r--r--private/ole32/olecnv32/getdata.h109
-rw-r--r--private/ole32/olecnv32/headers.c29
-rw-r--r--private/ole32/olecnv32/olecnv32.rc13
-rw-r--r--private/ole32/olecnv32/qd2gdi.h181
-rw-r--r--private/ole32/olecnv32/qdcoment.i62
-rw-r--r--private/ole32/olecnv32/qdopcode.i252
-rw-r--r--private/ole32/olecnv32/quickdrw.c2659
-rw-r--r--private/ole32/olecnv32/quickdrw.h192
-rw-r--r--private/ole32/olecnv32/readme.txt10
-rw-r--r--private/ole32/olecnv32/toolbox.h168
-rw-r--r--private/ole32/oledbg/daytona/makefile6
-rw-r--r--private/ole32/oledbg/daytona/oledbg.def11
-rw-r--r--private/ole32/oledbg/daytona/sources51
-rw-r--r--private/ole32/oledbg/dirs38
-rw-r--r--private/ole32/oledbg/oledbg.cxx525
-rw-r--r--private/ole32/oledbg/oledbg.h40
-rw-r--r--private/ole32/oledbg/sources.inc1
-rw-r--r--private/ole32/oleprx32/dirs38
-rw-r--r--private/ole32/oleprx32/idl/daytona/makefile6
-rw-r--r--private/ole32/oleprx32/idl/daytona/makefile.inc65
-rw-r--r--private/ole32/oleprx32/idl/daytona/mega.idl26
-rw-r--r--private/ole32/oleprx32/idl/daytona/sources49
-rw-r--r--private/ole32/oleprx32/idl/dirs37
-rw-r--r--private/ole32/oleprx32/makefil015
-rw-r--r--private/ole32/oleprx32/proxy/bstr.cxx224
-rw-r--r--private/ole32/oleprx32/proxy/call_as.c3003
-rw-r--r--private/ole32/oleprx32/proxy/daytona/makefile6
-rw-r--r--private/ole32/oleprx32/proxy/daytona/sources39
-rw-r--r--private/ole32/oleprx32/proxy/dirs26
-rw-r--r--private/ole32/oleprx32/proxy/dlldatax.c13
-rw-r--r--private/ole32/oleprx32/proxy/mega.h28
-rw-r--r--private/ole32/oleprx32/proxy/oleprx32.def34
-rw-r--r--private/ole32/oleprx32/proxy/stdrpc.hxx66
-rw-r--r--private/ole32/oleprx32/proxy/transmit.cxx4246
-rw-r--r--private/ole32/oleprx32/proxy/transmit.h154
-rw-r--r--private/ole32/oleprx32/wdt/daytona/makefile6
-rw-r--r--private/ole32/oleprx32/wdt/daytona/sources43
-rw-r--r--private/ole32/oleprx32/wdt/dirs25
-rw-r--r--private/ole32/oleprx32/wdt/stdrpc.hxx66
-rw-r--r--private/ole32/oleprx32/wdt/transmit.h82
-rw-r--r--private/ole32/oleprx32/wdt/usermrsh.h76
-rw-r--r--private/ole32/oleprx32/wdt/wdt.cxx1881
-rw-r--r--private/ole32/oleprx32/wdt/wdt32.def63
-rw-r--r--private/ole32/oleprx32/wdt/wdtp.h118
-rw-r--r--private/ole32/olethunk/bin16/makefile16
-rw-r--r--private/ole32/olethunk/bin16/ole2disp.map3045
-rw-r--r--private/ole32/olethunk/bin16/ole2disp.symbin0 -> 46356 bytes
-rw-r--r--private/ole32/olethunk/bin16/ole2disp.txt6
-rw-r--r--private/ole32/olethunk/bin16/ole2nls.map652
-rw-r--r--private/ole32/olethunk/bin16/ole2nls.symbin0 -> 7412 bytes
-rw-r--r--private/ole32/olethunk/bin16/stdole.tlbbin0 -> 5532 bytes
-rw-r--r--private/ole32/olethunk/bin16/typelib.map2363
-rw-r--r--private/ole32/olethunk/bin16/typelib.symbin0 -> 45060 bytes
-rw-r--r--private/ole32/olethunk/daytona/dirs29
-rw-r--r--private/ole32/olethunk/daytona/makefil011
-rw-r--r--private/ole32/olethunk/debnot/assert.cxx252
-rw-r--r--private/ole32/olethunk/debnot/daytona/makefile23
-rw-r--r--private/ole32/olethunk/debnot/daytona/sources33
-rw-r--r--private/ole32/olethunk/debnot/dirs36
-rw-r--r--private/ole32/olethunk/debnot/dprintf.c19
-rw-r--r--private/ole32/olethunk/debnot/dprintf.h33
-rw-r--r--private/ole32/olethunk/debnot/output.c806
-rw-r--r--private/ole32/olethunk/debnot/printf.h261
-rw-r--r--private/ole32/olethunk/debnot/sprintf.c17
-rw-r--r--private/ole32/olethunk/debnot/w4io.h59
-rw-r--r--private/ole32/olethunk/debnot/win16.mk24
-rw-r--r--private/ole32/olethunk/debnot/win32/makefile6
-rw-r--r--private/ole32/olethunk/debnot/win32/sources45
-rw-r--r--private/ole32/olethunk/dirs41
-rw-r--r--private/ole32/olethunk/h/apilist.hxx118
-rw-r--r--private/ole32/olethunk/h/call32.hxx34
-rw-r--r--private/ole32/olethunk/h/interop.hxx266
-rw-r--r--private/ole32/olethunk/h/io16.h25
-rw-r--r--private/ole32/olethunk/h/obj16.hxx151
-rw-r--r--private/ole32/olethunk/h/stksw.hxx59
-rw-r--r--private/ole32/olethunk/h/wow16fn.h62
-rw-r--r--private/ole32/olethunk/h/wow32fn.h92
-rw-r--r--private/ole32/olethunk/makefil030
-rw-r--r--private/ole32/olethunk/ole16/coll/array_fv.cxx312
-rw-r--r--private/ole32/olethunk/ole16/coll/makefile36
-rw-r--r--private/ole32/olethunk/ole16/coll/map_kv.cxx536
-rw-r--r--private/ole32/olethunk/ole16/coll/plex.cxx47
-rw-r--r--private/ole32/olethunk/ole16/compobj/assrtdlg.h9
-rw-r--r--private/ole32/olethunk/ole16/compobj/call32.cxx1313
-rw-r--r--private/ole32/olethunk/ole16/compobj/clstub16.cxx109
-rw-r--r--private/ole32/olethunk/ole16/compobj/comdthk.c800
-rw-r--r--private/ole32/olethunk/ole16/compobj/comguid.cxx20
-rw-r--r--private/ole32/olethunk/ole16/compobj/comlocal.cxx1276
-rw-r--r--private/ole32/olethunk/ole16/compobj/comlocal.hxx35
-rw-r--r--private/ole32/olethunk/ole16/compobj/compobj.cxx355
-rw-r--r--private/ole32/olethunk/ole16/compobj/compobj.def236
-rw-r--r--private/ole32/olethunk/ole16/compobj/compobj.rc49
-rw-r--r--private/ole32/olethunk/ole16/compobj/cpkt.cxx461
-rw-r--r--private/ole32/olethunk/ole16/compobj/dlltable.cxx285
-rw-r--r--private/ole32/olethunk/ole16/compobj/dlltable.h40
-rw-r--r--private/ole32/olethunk/ole16/compobj/etask.cxx337
-rw-r--r--private/ole32/olethunk/ole16/compobj/go1632pr.cxx230
-rw-r--r--private/ole32/olethunk/ole16/compobj/go1632pr.hxx22
-rw-r--r--private/ole32/olethunk/ole16/compobj/headers.cxx21
-rw-r--r--private/ole32/olethunk/ole16/compobj/makefile76
-rw-r--r--private/ole32/olethunk/ole16/compobj/memctx.cxx109
-rw-r--r--private/ole32/olethunk/ole16/compobj/rpc16.cxx379
-rw-r--r--private/ole32/olethunk/ole16/compobj/rpc16.hxx138
-rw-r--r--private/ole32/olethunk/ole16/compobj/stdalloc.cxx493
-rw-r--r--private/ole32/olethunk/ole16/compobj/valid.cxx200
-rw-r--r--private/ole32/olethunk/ole16/daytona/makefile49
-rw-r--r--private/ole32/olethunk/ole16/daytona/sources33
-rw-r--r--private/ole32/olethunk/ole16/dirs37
-rw-r--r--private/ole32/olethunk/ole16/inc/array_fv.h74
-rw-r--r--private/ole32/olethunk/ole16/inc/assert.h35
-rw-r--r--private/ole32/olethunk/ole16/inc/cderr.h48
-rw-r--r--private/ole32/olethunk/ole16/inc/cmacros.inc1410
-rw-r--r--private/ole32/olethunk/ole16/inc/cmacs.h72
-rw-r--r--private/ole32/olethunk/ole16/inc/cobjps.h69
-rw-r--r--private/ole32/olethunk/ole16/inc/coguid.h65
-rw-r--r--private/ole32/olethunk/ole16/inc/commdlg.h318
-rw-r--r--private/ole32/olethunk/ole16/inc/compobj.h1031
-rw-r--r--private/ole32/olethunk/ole16/inc/cosegs.h2
-rw-r--r--private/ole32/olethunk/ole16/inc/ctype.h116
-rw-r--r--private/ole32/olethunk/ole16/inc/ddesegs.h2
-rw-r--r--private/ole32/olethunk/ole16/inc/debnot.h685
-rw-r--r--private/ole32/olethunk/ole16/inc/debug.h306
-rw-r--r--private/ole32/olethunk/ole16/inc/dlgs.h201
-rw-r--r--private/ole32/olethunk/ole16/inc/dos.h330
-rw-r--r--private/ole32/olethunk/ole16/inc/dvobj.h480
-rw-r--r--private/ole32/olethunk/ole16/inc/enumfetc.h13
-rw-r--r--private/ole32/olethunk/ole16/inc/etask.hxx69
-rw-r--r--private/ole32/olethunk/ole16/inc/initguid.h38
-rw-r--r--private/ole32/olethunk/ole16/inc/limits.h44
-rw-r--r--private/ole32/olethunk/ole16/inc/lrpcmon.h18
-rw-r--r--private/ole32/olethunk/ole16/inc/malloc.h159
-rw-r--r--private/ole32/olethunk/ole16/inc/map_htsk.h69
-rw-r--r--private/ole32/olethunk/ole16/inc/map_kv.h109
-rw-r--r--private/ole32/olethunk/ole16/inc/math.h303
-rw-r--r--private/ole32/olethunk/ole16/inc/memctx.hxx16
-rw-r--r--private/ole32/olethunk/ole16/inc/memory.h75
-rw-r--r--private/ole32/olethunk/ole16/inc/moniker.h248
-rw-r--r--private/ole32/olethunk/ole16/inc/monsegs.h2
-rw-r--r--private/ole32/olethunk/ole16/inc/ole1cls.h141
-rw-r--r--private/ole32/olethunk/ole16/inc/ole2.h1336
-rw-r--r--private/ole32/olethunk/ole16/inc/ole2anac.h91
-rw-r--r--private/ole32/olethunk/ole16/inc/ole2dbg.h19
-rw-r--r--private/ole32/olethunk/ole16/inc/ole2int.h550
-rw-r--r--private/ole32/olethunk/ole16/inc/ole2segs.h2
-rw-r--r--private/ole32/olethunk/ole16/inc/ole2sp.h346
-rw-r--r--private/ole32/olethunk/ole16/inc/ole2ui.h918
-rw-r--r--private/ole32/olethunk/ole16/inc/ole2ver.h4
-rw-r--r--private/ole32/olethunk/ole16/inc/olecoll.h73
-rw-r--r--private/ole32/olethunk/ole16/inc/oleguid.h80
-rw-r--r--private/ole32/olethunk/ole16/inc/olemem.h59
-rw-r--r--private/ole32/olethunk/ole16/inc/olerem.h523
-rw-r--r--private/ole32/olethunk/ole16/inc/olestd.h837
-rw-r--r--private/ole32/olethunk/ole16/inc/plex.h28
-rw-r--r--private/ole32/olethunk/ole16/inc/privguid.h60
-rw-r--r--private/ole32/olethunk/ole16/inc/prxsegs.h1
-rw-r--r--private/ole32/olethunk/ole16/inc/reterr.h44
-rw-r--r--private/ole32/olethunk/ole16/inc/scode.h283
-rw-r--r--private/ole32/olethunk/ole16/inc/shellapi.h88
-rw-r--r--private/ole32/olethunk/ole16/inc/stdarg.h52
-rw-r--r--private/ole32/olethunk/ole16/inc/stdio.h338
-rw-r--r--private/ole32/olethunk/ole16/inc/stdlib.h263
-rw-r--r--private/ole32/olethunk/ole16/inc/storage.h457
-rw-r--r--private/ole32/olethunk/ole16/inc/string.h167
-rw-r--r--private/ole32/olethunk/ole16/inc/taskmap.h8
-rw-r--r--private/ole32/olethunk/ole16/inc/tchar.h555
-rw-r--r--private/ole32/olethunk/ole16/inc/testmess.h52
-rw-r--r--private/ole32/olethunk/ole16/inc/toolhelp.h469
-rw-r--r--private/ole32/olethunk/ole16/inc/utils.h182
-rw-r--r--private/ole32/olethunk/ole16/inc/utstream.h19
-rw-r--r--private/ole32/olethunk/ole16/inc/valid.h81
-rw-r--r--private/ole32/olethunk/ole16/inc/ver.h255
-rw-r--r--private/ole32/olethunk/ole16/inc/verinfo.h23
-rw-r--r--private/ole32/olethunk/ole16/inc/windows.h5373
-rw-r--r--private/ole32/olethunk/ole16/lib/makefile18
-rw-r--r--private/ole32/olethunk/ole16/makefil038
-rw-r--r--private/ole32/olethunk/ole16/makefile.inc358
-rw-r--r--private/ole32/olethunk/ole16/ole2/cdebug.cxx1044
-rw-r--r--private/ole32/olethunk/ole16/ole2/default.icobin0 -> 766 bytes
-rw-r--r--private/ole32/olethunk/ole16/ole2/dragcopy.curbin0 -> 326 bytes
-rw-r--r--private/ole32/olethunk/ole16/ole2/draglink.curbin0 -> 326 bytes
-rw-r--r--private/ole32/olethunk/ole16/ole2/dragmove.curbin0 -> 326 bytes
-rw-r--r--private/ole32/olethunk/ole16/ole2/dragnone.curbin0 -> 326 bytes
-rw-r--r--private/ole32/olethunk/ole16/ole2/headers.cxx22
-rw-r--r--private/ole32/olethunk/ole16/ole2/icon.cxx1465
-rw-r--r--private/ole32/olethunk/ole16/ole2/icon.h64
-rw-r--r--private/ole32/olethunk/ole16/ole2/inplace.cxx224
-rw-r--r--private/ole32/olethunk/ole16/ole2/inplace.h114
-rw-r--r--private/ole32/olethunk/ole16/ole2/lockbyte.cxx120
-rw-r--r--private/ole32/olethunk/ole16/ole2/makefile77
-rw-r--r--private/ole32/olethunk/ole16/ole2/memstm.cxx1330
-rw-r--r--private/ole32/olethunk/ole16/ole2/memstm.h228
-rw-r--r--private/ole32/olethunk/ole16/ole2/mondthk.c451
-rw-r--r--private/ole32/olethunk/ole16/ole2/ole2.cxx108
-rw-r--r--private/ole32/olethunk/ole16/ole2/ole2.def183
-rw-r--r--private/ole32/olethunk/ole16/ole2/ole2.rc42
-rw-r--r--private/ole32/olethunk/ole16/ole2/ole2dthk.c1803
-rw-r--r--private/ole32/olethunk/ole16/ole2/ole2guid.cxx22
-rw-r--r--private/ole32/olethunk/ole16/ole2/ole2lcl.cxx727
-rw-r--r--private/ole32/olethunk/ole16/ole2/ole2splt.cxx271
-rw-r--r--private/ole32/olethunk/ole16/ole2/scrlcopy.curbin0 -> 326 bytes
-rw-r--r--private/ole32/olethunk/ole16/ole2/scrllink.curbin0 -> 326 bytes
-rw-r--r--private/ole32/olethunk/ole16/ole2/scrlmove.curbin0 -> 326 bytes
-rw-r--r--private/ole32/olethunk/ole16/storage/headers.cxx21
-rw-r--r--private/ole32/olethunk/ole16/storage/makefile44
-rw-r--r--private/ole32/olethunk/ole16/storage/stgdthk.c307
-rw-r--r--private/ole32/olethunk/ole16/storage/storage.c87
-rw-r--r--private/ole32/olethunk/ole16/storage/storage.def49
-rw-r--r--private/ole32/olethunk/ole16/storage/storage.rc33
-rw-r--r--private/ole32/olethunk/ole16/tools/c1.err1029
-rw-r--r--private/ole32/olethunk/ole16/tools/c23.err95
-rw-r--r--private/ole32/olethunk/ole16/tools/cl.def62
-rw-r--r--private/ole32/olethunk/ole16/tools/cl.err41
-rw-r--r--private/ole32/olethunk/ole16/tools/cl.msg126
-rw-r--r--private/ole32/olethunk/ole16/tools/interop.reg118
-rw-r--r--private/ole32/olethunk/ole16/tools/ole1632.bat93
-rw-r--r--private/ole32/olethunk/ole16/tools/rcqq.err334
-rw-r--r--private/ole32/olethunk/ole16/utest/basic/base16.cxx41
-rw-r--r--private/ole32/olethunk/ole16/utest/basic/base16.def7
-rw-r--r--private/ole32/olethunk/ole16/utest/basic/makefile35
-rw-r--r--private/ole32/olethunk/ole16/utest/triv/makefile34
-rw-r--r--private/ole32/olethunk/ole16/utest/triv/triv.cxx60
-rw-r--r--private/ole32/olethunk/ole16/utest/triv/triv.def7
-rw-r--r--private/ole32/olethunk/olethk32/alias.cxx405
-rw-r--r--private/ole32/olethunk/olethk32/alias.hxx163
-rw-r--r--private/ole32/olethunk/olethk32/apinot.cxx990
-rw-r--r--private/ole32/olethunk/olethk32/apinot.hxx25
-rw-r--r--private/ole32/olethunk/olethk32/cthkmgr.cxx3031
-rw-r--r--private/ole32/olethunk/olethk32/cthkmgr.hxx243
-rw-r--r--private/ole32/olethunk/olethk32/daytona/makefile6
-rw-r--r--private/ole32/olethunk/olethk32/daytona/olethk32.def27
-rw-r--r--private/ole32/olethunk/olethk32/daytona/sources103
-rw-r--r--private/ole32/olethunk/olethk32/dbgapi.cxx127
-rw-r--r--private/ole32/olethunk/olethk32/dbgint.cxx682
-rw-r--r--private/ole32/olethunk/olethk32/dbginv.hxx26
-rw-r--r--private/ole32/olethunk/olethk32/dbgitbl.cxx82
-rw-r--r--private/ole32/olethunk/olethk32/dirs40
-rw-r--r--private/ole32/olethunk/olethk32/dllentry.cxx56
-rw-r--r--private/ole32/olethunk/olethk32/fntomthd.cxx2082
-rw-r--r--private/ole32/olethunk/olethk32/freelist.cxx468
-rw-r--r--private/ole32/olethunk/olethk32/freelist.hxx65
-rw-r--r--private/ole32/olethunk/olethk32/headers.cxx59
-rw-r--r--private/ole32/olethunk/olethk32/heap.cxx63
-rw-r--r--private/ole32/olethunk/olethk32/ichannel.cxx49
-rw-r--r--private/ole32/olethunk/olethk32/iidtothi.cxx79
-rw-r--r--private/ole32/olethunk/olethk32/inv16.cxx608
-rw-r--r--private/ole32/olethunk/olethk32/inv16.hxx21
-rw-r--r--private/ole32/olethunk/olethk32/inv32.cxx496
-rw-r--r--private/ole32/olethunk/olethk32/map_dwp.h66
-rw-r--r--private/ole32/olethunk/olethk32/map_kv.cxx540
-rw-r--r--private/ole32/olethunk/olethk32/map_kv.h116
-rw-r--r--private/ole32/olethunk/olethk32/map_kv.hxx114
-rw-r--r--private/ole32/olethunk/olethk32/mmodel.cxx232
-rw-r--r--private/ole32/olethunk/olethk32/mmodel.hxx88
-rw-r--r--private/ole32/olethunk/olethk32/nest.hxx32
-rw-r--r--private/ole32/olethunk/olethk32/olethk32.cxx616
-rw-r--r--private/ole32/olethunk/olethk32/olethk32.hxx31
-rw-r--r--private/ole32/olethunk/olethk32/olethk32.rc14
-rw-r--r--private/ole32/olethunk/olethk32/plex.cxx45
-rw-r--r--private/ole32/olethunk/olethk32/plex.h30
-rw-r--r--private/ole32/olethunk/olethk32/stalloc.cxx397
-rw-r--r--private/ole32/olethunk/olethk32/stalloc.hxx113
-rw-r--r--private/ole32/olethunk/olethk32/struct16.hxx91
-rw-r--r--private/ole32/olethunk/olethk32/tc1632.cxx323
-rw-r--r--private/ole32/olethunk/olethk32/the.hxx21
-rw-r--r--private/ole32/olethunk/olethk32/thi.hxx73
-rw-r--r--private/ole32/olethunk/olethk32/thkmgr.cxx536
-rw-r--r--private/ole32/olethunk/olethk32/thkmgr.hxx40
-rw-r--r--private/ole32/olethunk/olethk32/thop.hxx241
-rw-r--r--private/ole32/olethunk/olethk32/thop16.cxx4114
-rw-r--r--private/ole32/olethunk/olethk32/thop32.cxx3959
-rw-r--r--private/ole32/olethunk/olethk32/thopapi.hxx37
-rw-r--r--private/ole32/olethunk/olethk32/thopiint.cxx83
-rw-r--r--private/ole32/olethunk/olethk32/thopint.hxx39
-rw-r--r--private/ole32/olethunk/olethk32/thopsapi.cxx427
-rw-r--r--private/ole32/olethunk/olethk32/thopsint.cxx1313
-rw-r--r--private/ole32/olethunk/olethk32/thoputil.cxx4547
-rw-r--r--private/ole32/olethunk/olethk32/thoputil.hxx216
-rw-r--r--private/ole32/olethunk/olethk32/thtblapi.cxx125
-rw-r--r--private/ole32/olethunk/olethk32/thtblint.cxx508
-rw-r--r--private/ole32/olethunk/olethk32/tlsthk.cxx171
-rw-r--r--private/ole32/olethunk/olethk32/tlsthk.hxx85
-rw-r--r--private/ole32/olethunk/olethk32/vtblapi.cxx123
-rw-r--r--private/ole32/olethunk/olethk32/vtblifn.cxx766
-rw-r--r--private/ole32/olethunk/olethk32/vtblint.cxx678
-rw-r--r--private/ole32/olethunk/thc/readme.txt34
-rw-r--r--private/ole32/olethunk/thc/thc/depend.mk32
-rw-r--r--private/ole32/olethunk/thc/thc/filelist.mk20
-rw-r--r--private/ole32/olethunk/thc/thc/gen.c1785
-rw-r--r--private/ole32/olethunk/thc/thc/gen.h86
-rw-r--r--private/ole32/olethunk/thc/thc/grammar.y338
-rw-r--r--private/ole32/olethunk/thc/thc/lexer.l104
-rw-r--r--private/ole32/olethunk/thc/thc/main.c66
-rw-r--r--private/ole32/olethunk/thc/thc/main.h9
-rw-r--r--private/ole32/olethunk/thc/thc/makefil014
-rw-r--r--private/ole32/olethunk/thc/thc/makefile6
-rw-r--r--private/ole32/olethunk/thc/thc/myypars.c164
-rw-r--r--private/ole32/olethunk/thc/thc/op.c26
-rw-r--r--private/ole32/olethunk/thc/thc/op.h10
-rw-r--r--private/ole32/olethunk/thc/thc/skeleton.flx852
-rw-r--r--private/ole32/olethunk/thc/thc/sources75
-rw-r--r--private/ole32/olethunk/thc/thc/special.c1283
-rw-r--r--private/ole32/olethunk/thc/thc/special.h16
-rw-r--r--private/ole32/olethunk/thc/thc/split.cmd51
-rw-r--r--private/ole32/olethunk/thc/thc/type.c347
-rw-r--r--private/ole32/olethunk/thc/thc/type.h97
-rw-r--r--private/ole32/olethunk/thc/thpp/cobjps.h69
-rw-r--r--private/ole32/olethunk/thc/thpp/coguid.h65
-rw-r--r--private/ole32/olethunk/thc/thpp/compobj.h971
-rw-r--r--private/ole32/olethunk/thc/thpp/config.h106
-rw-r--r--private/ole32/olethunk/thc/thpp/depend.mk11
-rw-r--r--private/ole32/olethunk/thc/thpp/dvobj.h480
-rw-r--r--private/ole32/olethunk/thc/thpp/extens.h202
-rw-r--r--private/ole32/olethunk/thc/thpp/filelist.mk4
-rw-r--r--private/ole32/olethunk/thc/thpp/initguid.h38
-rw-r--r--private/ole32/olethunk/thc/thpp/main.c5
-rw-r--r--private/ole32/olethunk/thc/thpp/makefile2
-rw-r--r--private/ole32/olethunk/thc/thpp/moniker.h248
-rw-r--r--private/ole32/olethunk/thc/thpp/ole1cls.h141
-rw-r--r--private/ole32/olethunk/thc/thpp/ole2.h1336
-rw-r--r--private/ole32/olethunk/thc/thpp/ole2dbg.h19
-rw-r--r--private/ole32/olethunk/thc/thpp/ole2ver.h5
-rw-r--r--private/ole32/olethunk/thc/thpp/oleguid.h80
-rw-r--r--private/ole32/olethunk/thc/thpp/scode.h283
-rw-r--r--private/ole32/olethunk/thc/thpp/storage.h457
-rw-r--r--private/ole32/olethunk/thc/thpp/valid.h72
-rw-r--r--private/ole32/olethunk/thc/thsplit/depend.mk11
-rw-r--r--private/ole32/olethunk/thc/thsplit/filelist.mk10
-rw-r--r--private/ole32/olethunk/thc/thsplit/makefile9
-rw-r--r--private/ole32/olethunk/thc/thsplit/thsplit.c92
-rw-r--r--private/ole32/olethunk/tools/clschk/classchk.cxx1114
-rw-r--r--private/ole32/olethunk/tools/clschk/classchk.h21
-rw-r--r--private/ole32/olethunk/tools/clschk/makefile6
-rw-r--r--private/ole32/olethunk/tools/clschk/sources25
-rw-r--r--private/ole32/olethunk/tools/infolvl/infolvl.cxx159
-rw-r--r--private/ole32/olethunk/tools/infolvl/makefile6
-rw-r--r--private/ole32/olethunk/tools/infolvl/sources12
-rw-r--r--private/ole32/olethunk/tools/rotdump/makefile6
-rw-r--r--private/ole32/olethunk/tools/rotdump/rotdump.cxx126
-rw-r--r--private/ole32/olethunk/tools/rotdump/sources24
-rw-r--r--private/ole32/olethunk/tools/upknown/makefile6
-rw-r--r--private/ole32/olethunk/tools/upknown/sources12
-rw-r--r--private/ole32/olethunk/tools/upknown/upknown.c179
-rw-r--r--private/ole32/olethunk/tools/zapknown/makefile6
-rw-r--r--private/ole32/olethunk/tools/zapknown/sources12
-rw-r--r--private/ole32/olethunk/tools/zapknown/zapknown.c62
-rw-r--r--private/ole32/olethunk/utest/simple/makefile121
-rw-r--r--private/ole32/olethunk/utest/simple/simple.c202
-rw-r--r--private/ole32/olethunk/utest/simple/simple.def28
-rw-r--r--private/ole32/olethunk/utest/simple/simple.h8
-rw-r--r--private/ole32/olethunk/utest/simple/simple.rc21
-rw-r--r--private/ole32/oleui/clspsht.cpp1081
-rw-r--r--private/ole32/oleui/clspsht.h75
-rw-r--r--private/ole32/oleui/cnfgdlg.h38
-rw-r--r--private/ole32/oleui/cnfgpsht.cpp159
-rw-r--r--private/ole32/oleui/cnfgpsht.h69
-rw-r--r--private/ole32/oleui/creg.cpp550
-rw-r--r--private/ole32/oleui/creg.h51
-rw-r--r--private/ole32/oleui/cstrings.cpp311
-rw-r--r--private/ole32/oleui/cstrings.h67
-rw-r--r--private/ole32/oleui/datapkt.cpp343
-rw-r--r--private/ole32/oleui/datapkt.h141
-rw-r--r--private/ole32/oleui/daytona/makefile6
-rw-r--r--private/ole32/oleui/daytona/sources101
-rw-r--r--private/ole32/oleui/dcomcnfg.cpp20
-rw-r--r--private/ole32/oleui/dcomcnfg.rc4
-rw-r--r--private/ole32/oleui/dirs36
-rw-r--r--private/ole32/oleui/locppg.cpp706
-rw-r--r--private/ole32/oleui/locppg.h212
-rw-r--r--private/ole32/oleui/newsrvr.cpp81
-rw-r--r--private/ole32/oleui/newsrvr.h55
-rw-r--r--private/ole32/oleui/olecnfg.cpp117
-rw-r--r--private/ole32/oleui/olecnfg.h53
-rw-r--r--private/ole32/oleui/olecnfg.hlpbin0 -> 16684 bytes
-rw-r--r--private/ole32/oleui/olecnfg.hpj56
-rw-r--r--private/ole32/oleui/olecnfg.icobin0 -> 1078 bytes
-rw-r--r--private/ole32/oleui/olecnfg.mak1983
-rw-r--r--private/ole32/oleui/olecnfg.rc564
-rw-r--r--private/ole32/oleui/olecnfg.rtf73
-rw-r--r--private/ole32/oleui/oleui.cpp6
-rw-r--r--private/ole32/oleui/oleui.rc4
-rw-r--r--private/ole32/oleui/res/olecnfg.icobin0 -> 1078 bytes
-rw-r--r--private/ole32/oleui/res/olecnfg.rc213
-rw-r--r--private/ole32/oleui/resource.h154
-rw-r--r--private/ole32/oleui/srvppg.cpp993
-rw-r--r--private/ole32/oleui/srvppg.h184
-rw-r--r--private/ole32/oleui/stdafx.cpp7
-rw-r--r--private/ole32/oleui/stdafx.h25
-rw-r--r--private/ole32/oleui/types.h45
-rw-r--r--private/ole32/oleui/util.cpp2085
-rw-r--r--private/ole32/oleui/util.h230
-rw-r--r--private/ole32/oleui/version.txt50
-rw-r--r--private/ole32/oleui/virtreg.cpp783
-rw-r--r--private/ole32/oleui/virtreg.h137
-rw-r--r--private/ole32/stdclass/dirs4
-rw-r--r--private/ole32/stdclass/stdclass.cxx290
-rw-r--r--private/ole32/stg/async/chicago.inc32
-rw-r--r--private/ole32/stg/async/cruntime.cxx201
-rw-r--r--private/ole32/stg/async/daytona.inc60
-rw-r--r--private/ole32/stg/async/debug/assert.cxx421
-rw-r--r--private/ole32/stg/async/debug/daytona/makefile10
-rw-r--r--private/ole32/stg/async/debug/daytona/sources68
-rw-r--r--private/ole32/stg/async/debug/dirs37
-rw-r--r--private/ole32/stg/async/debug/dprintf.c15
-rw-r--r--private/ole32/stg/async/debug/dprintf.h33
-rw-r--r--private/ole32/stg/async/debug/eqguid.cxx54
-rw-r--r--private/ole32/stg/async/debug/output.c964
-rw-r--r--private/ole32/stg/async/debug/printf.c17
-rw-r--r--private/ole32/stg/async/debug/printf.h245
-rw-r--r--private/ole32/stg/async/debug/sprintf.c13
-rw-r--r--private/ole32/stg/async/debug/w4io.h49
-rw-r--r--private/ole32/stg/async/debug/wsprintf.c14
-rw-r--r--private/ole32/stg/async/dfsetup/dfsetup.cxx40
-rw-r--r--private/ole32/stg/async/dfsetup/dfsetup.rc19
-rw-r--r--private/ole32/stg/async/dfsetup/makefile10
-rw-r--r--private/ole32/stg/async/dfsetup/sources108
-rw-r--r--private/ole32/stg/async/dfsetup/sources.inc1
-rw-r--r--private/ole32/stg/async/dftool/dftool.cxx51
-rw-r--r--private/ole32/stg/async/dftool/dftool.rc19
-rw-r--r--private/ole32/stg/async/dftool/makefile10
-rw-r--r--private/ole32/stg/async/dftool/sources108
-rw-r--r--private/ole32/stg/async/dftool/sources.inc1
-rw-r--r--private/ole32/stg/async/dirs41
-rw-r--r--private/ole32/stg/async/docfile/astg.hxx83
-rw-r--r--private/ole32/stg/async/docfile/astghead.cxx41
-rw-r--r--private/ole32/stg/async/docfile/asyncapi.cxx331
-rw-r--r--private/ole32/stg/async/docfile/asyncapi.hxx38
-rw-r--r--private/ole32/stg/async/docfile/asyncerr.hxx26
-rw-r--r--private/ole32/stg/async/docfile/asyncstg.def47
-rw-r--r--private/ole32/stg/async/docfile/asyncver.h23
-rw-r--r--private/ole32/stg/async/docfile/daytona/makefile10
-rw-r--r--private/ole32/stg/async/docfile/daytona/makefile.inc37
-rw-r--r--private/ole32/stg/async/docfile/daytona/sources78
-rw-r--r--private/ole32/stg/async/docfile/dirs41
-rw-r--r--private/ole32/stg/async/docfile/filebyte.hxx80
-rw-r--r--private/ole32/stg/async/docfile/filelkb.cxx723
-rw-r--r--private/ole32/stg/async/docfile/filllkb.cxx905
-rw-r--r--private/ole32/stg/async/docfile/filllkb.hxx162
-rw-r--r--private/ole32/stg/async/docfile/iconn.idl76
-rw-r--r--private/ole32/stg/async/docfile/sources.inc1
-rw-r--r--private/ole32/stg/async/docfile/stgconn.cxx650
-rw-r--r--private/ole32/stg/async/docfile/stgwrap.cxx1873
-rw-r--r--private/ole32/stg/async/docfile/stgwrap.hxx465
-rw-r--r--private/ole32/stg/async/docfile/sweeper.chi/makefile10
-rw-r--r--private/ole32/stg/async/docfile/sweeper.chi/sources93
-rw-r--r--private/ole32/stg/async/docfile/sweeper.day/makefile10
-rw-r--r--private/ole32/stg/async/docfile/sweeper.day/sources102
-rw-r--r--private/ole32/stg/async/h/error.hxx33
-rw-r--r--private/ole32/stg/async/h/valid.h188
-rw-r--r--private/ole32/stg/async/idl/dirs37
-rw-r--r--private/ole32/stg/async/idl/ifill.idl50
-rw-r--r--private/ole32/stg/async/idl/ilay.idl48
-rw-r--r--private/ole32/stg/async/idl/intfy.idl32
-rw-r--r--private/ole32/stg/async/idl/sources.inc1
-rw-r--r--private/ole32/stg/async/layout/layapi.cxx86
-rw-r--r--private/ole32/stg/async/layout/laylkb.cxx773
-rw-r--r--private/ole32/stg/async/layout/laylkb.hxx138
-rw-r--r--private/ole32/stg/async/layout/layout.cxx1012
-rw-r--r--private/ole32/stg/async/layout/layout.def45
-rw-r--r--private/ole32/stg/async/layout/layout.hxx53
-rw-r--r--private/ole32/stg/async/layout/layout.rc19
-rw-r--r--private/ole32/stg/async/layout/layouter.cxx116
-rw-r--r--private/ole32/stg/async/layout/layouter.hxx72
-rw-r--r--private/ole32/stg/async/layout/layouthd.cxx48
-rw-r--r--private/ole32/stg/async/layout/layouthd.hxx20
-rw-r--r--private/ole32/stg/async/layout/layscrpt.cxx657
-rw-r--r--private/ole32/stg/async/layout/laywrap.cxx540
-rw-r--r--private/ole32/stg/async/layout/laywrap.hxx236
-rw-r--r--private/ole32/stg/async/layout/makefile10
-rw-r--r--private/ole32/stg/async/layout/mapfile.cxx229
-rw-r--r--private/ole32/stg/async/layout/mapfile.hxx78
-rw-r--r--private/ole32/stg/async/layout/sources113
-rw-r--r--private/ole32/stg/async/layout/sources.inc1
-rw-r--r--private/ole32/stg/async/layout/test/daytona/makefile10
-rw-r--r--private/ole32/stg/async/layout/test/daytona/sources48
-rw-r--r--private/ole32/stg/async/layout/test/dirs22
-rw-r--r--private/ole32/stg/async/layout/test/laytest.cxx282
-rw-r--r--private/ole32/stg/async/layout/test/pch.cxx25
-rw-r--r--private/ole32/stg/async/layout/test/scripts.hxx159
-rw-r--r--private/ole32/stg/async/layout/test/test.docbin0 -> 458240 bytes
-rw-r--r--private/ole32/stg/async/layout/test/tutils.cxx546
-rw-r--r--private/ole32/stg/async/layout/test/tutils.hxx89
-rw-r--r--private/ole32/stg/async/layoutui/cklayout.cxx333
-rw-r--r--private/ole32/stg/async/layoutui/daytona/makefile10
-rw-r--r--private/ole32/stg/async/layoutui/daytona/sources91
-rw-r--r--private/ole32/stg/async/layoutui/laymain.cxx23
-rw-r--r--private/ole32/stg/async/layoutui/layouthd.hxx21
-rw-r--r--private/ole32/stg/async/layoutui/layoutui.cxx1351
-rw-r--r--private/ole32/stg/async/layoutui/layoutui.hxx183
-rw-r--r--private/ole32/stg/async/layoutui/layoutui.rc120
-rw-r--r--private/ole32/stg/async/layoutui/makefile10
-rw-r--r--private/ole32/stg/async/layoutui/olesite.cxx69
-rw-r--r--private/ole32/stg/async/layoutui/resource.h63
-rw-r--r--private/ole32/stg/async/layoutui/sources113
-rw-r--r--private/ole32/stg/async/layoutui/sources.inc1
-rw-r--r--private/ole32/stg/async/test/astgtest.cxx883
-rw-r--r--private/ole32/stg/async/test/daytona/makefile10
-rw-r--r--private/ole32/stg/async/test/daytona/sources56
-rw-r--r--private/ole32/stg/async/test/dirs24
-rw-r--r--private/ole32/stg/async/test/notify.hxx119
-rw-r--r--private/ole32/stg/async/test/pch.cxx26
-rw-r--r--private/ole32/stg/async/test/tutils.cxx316
-rw-r--r--private/ole32/stg/async/test/tutils.hxx84
-rw-r--r--private/ole32/stg/common/assert.cxx239
-rw-r--r--private/ole32/stg/common/daytona/makefile1
-rw-r--r--private/ole32/stg/common/daytona/sources83
-rw-r--r--private/ole32/stg/common/depend.mk116
-rw-r--r--private/ole32/stg/common/depend.mk365
-rw-r--r--private/ole32/stg/common/depend.mk924
-rw-r--r--private/ole32/stg/common/dirs37
-rw-r--r--private/ole32/stg/common/dprintf.c19
-rw-r--r--private/ole32/stg/common/dprintf.h28
-rw-r--r--private/ole32/stg/common/filelist.mk15
-rw-r--r--private/ole32/stg/common/makefile20
-rw-r--r--private/ole32/stg/common/output.c803
-rw-r--r--private/ole32/stg/common/printf.h241
-rw-r--r--private/ole32/stg/common/sprintf.c17
-rw-r--r--private/ole32/stg/common/w4io.h54
-rw-r--r--private/ole32/stg/dflibs.mk38
-rw-r--r--private/ole32/stg/dfms.mk30
-rw-r--r--private/ole32/stg/dirs45
-rw-r--r--private/ole32/stg/dll/daytona/makefile1
-rw-r--r--private/ole32/stg/dll/daytona/makefile.inc1
-rw-r--r--private/ole32/stg/dll/daytona/sources85
-rw-r--r--private/ole32/stg/dll/daytona/storag32.src115
-rw-r--r--private/ole32/stg/dll/dirs38
-rw-r--r--private/ole32/stg/dll/dummy.c3
-rw-r--r--private/ole32/stg/docfile/cdocfile.cxx574
-rw-r--r--private/ole32/stg/docfile/chinst.cxx266
-rw-r--r--private/ole32/stg/docfile/daytona/makefile1
-rw-r--r--private/ole32/stg/docfile/daytona/sources105
-rw-r--r--private/ole32/stg/docfile/debug.cxx773
-rw-r--r--private/ole32/stg/docfile/depend.mk11437
-rw-r--r--private/ole32/stg/docfile/depend.mk31177
-rw-r--r--private/ole32/stg/docfile/depend.mk9896
-rw-r--r--private/ole32/stg/docfile/dfbasis.cxx67
-rw-r--r--private/ole32/stg/docfile/dffuncs.cxx228
-rw-r--r--private/ole32/stg/docfile/dfhead.cxx66
-rw-r--r--private/ole32/stg/docfile/dfiter.cxx116
-rw-r--r--private/ole32/stg/docfile/dfname.cxx63
-rw-r--r--private/ole32/stg/docfile/dfstream.cxx135
-rw-r--r--private/ole32/stg/docfile/dfxact.cxx173
-rw-r--r--private/ole32/stg/docfile/dirs38
-rw-r--r--private/ole32/stg/docfile/entry.cxx81
-rw-r--r--private/ole32/stg/docfile/fastlock.cxx436
-rw-r--r--private/ole32/stg/docfile/filelist.mk46
-rw-r--r--private/ole32/stg/docfile/freelist.cxx104
-rw-r--r--private/ole32/stg/docfile/funcs.cxx722
-rw-r--r--private/ole32/stg/docfile/makefile20
-rw-r--r--private/ole32/stg/docfile/mem.cxx1133
-rw-r--r--private/ole32/stg/docfile/pdffuncs.cxx155
-rw-r--r--private/ole32/stg/docfile/publicdf.cxx1976
-rw-r--r--private/ole32/stg/docfile/rpubdf.cxx853
-rw-r--r--private/ole32/stg/docfile/segdf.hxx160
-rw-r--r--private/ole32/stg/docfile/smalloc.cxx1184
-rw-r--r--private/ole32/stg/docfile/sngprop.cxx238
-rw-r--r--private/ole32/stg/docfile/tests/based.cxx24
-rw-r--r--private/ole32/stg/docfile/tests/casein.cxx78
-rw-r--r--private/ole32/stg/docfile/tests/cmtovr.cxx46
-rw-r--r--private/ole32/stg/docfile/tests/copyto.cxx51
-rw-r--r--private/ole32/stg/docfile/tests/cpy.cxx40
-rw-r--r--private/ole32/stg/docfile/tests/delonr.cxx87
-rw-r--r--private/ole32/stg/docfile/tests/depend.cxx15
-rw-r--r--private/ole32/stg/docfile/tests/depend.mk1131
-rw-r--r--private/ole32/stg/docfile/tests/depend.mk3145
-rw-r--r--private/ole32/stg/docfile/tests/depend.mk956
-rw-r--r--private/ole32/stg/docfile/tests/dfgc.cxx49
-rw-r--r--private/ole32/stg/docfile/tests/dftct.cxx412
-rw-r--r--private/ole32/stg/docfile/tests/dfxact.cxx77
-rw-r--r--private/ole32/stg/docfile/tests/dnmwrite.cxx105
-rw-r--r--private/ole32/stg/docfile/tests/drect.cxx122
-rw-r--r--private/ole32/stg/docfile/tests/exe.def19
-rw-r--r--private/ole32/stg/docfile/tests/exe.mk40
-rw-r--r--private/ole32/stg/docfile/tests/failcmt.cxx172
-rw-r--r--private/ole32/stg/docfile/tests/imultip.cxx78
-rw-r--r--private/ole32/stg/docfile/tests/itermod.cxx135
-rw-r--r--private/ole32/stg/docfile/tests/iterrev.cxx33
-rw-r--r--private/ole32/stg/docfile/tests/lk.cxx104
-rw-r--r--private/ole32/stg/docfile/tests/lkb.cxx647
-rw-r--r--private/ole32/stg/docfile/tests/marsrev.cxx104
-rw-r--r--private/ole32/stg/docfile/tests/memt.cxx79
-rw-r--r--private/ole32/stg/docfile/tests/mthrd.cxx78
-rw-r--r--private/ole32/stg/docfile/tests/multimod.cxx98
-rw-r--r--private/ole32/stg/docfile/tests/multip.cxx99
-rw-r--r--private/ole32/stg/docfile/tests/nmake.cmd33
-rw-r--r--private/ole32/stg/docfile/tests/nomem.cxx28
-rw-r--r--private/ole32/stg/docfile/tests/nowrite.cxx45
-rw-r--r--private/ole32/stg/docfile/tests/oord.cxx38
-rw-r--r--private/ole32/stg/docfile/tests/open.cxx82
-rw-r--r--private/ole32/stg/docfile/tests/opentm.cxx17
-rw-r--r--private/ole32/stg/docfile/tests/oprop.cxx622
-rw-r--r--private/ole32/stg/docfile/tests/pch.cxx20
-rw-r--r--private/ole32/stg/docfile/tests/pp.cxx54
-rw-r--r--private/ole32/stg/docfile/tests/priority.cxx51
-rw-r--r--private/ole32/stg/docfile/tests/prop.cxx955
-rw-r--r--private/ole32/stg/docfile/tests/propcopy.cxx180
-rw-r--r--private/ole32/stg/docfile/tests/readtm.cxx241
-rw-r--r--private/ole32/stg/docfile/tests/readtmd.cxx82
-rw-r--r--private/ole32/stg/docfile/tests/readtmm.cxx145
-rw-r--r--private/ole32/stg/docfile/tests/readtmw.cxx89
-rw-r--r--private/ole32/stg/docfile/tests/rest.cxx68
-rw-r--r--private/ole32/stg/docfile/tests/reverted.cxx109
-rw-r--r--private/ole32/stg/docfile/tests/ropen.cxx65
-rw-r--r--private/ole32/stg/docfile/tests/safep.cxx121
-rw-r--r--private/ole32/stg/docfile/tests/setdbg.cxx29
-rw-r--r--private/ole32/stg/docfile/tests/settime.cxx48
-rw-r--r--private/ole32/stg/docfile/tests/size.cxx57
-rw-r--r--private/ole32/stg/docfile/tests/smp.cxx17
-rw-r--r--private/ole32/stg/docfile/tests/stmdny.cxx46
-rw-r--r--private/ole32/stg/docfile/tests/switch.cxx78
-rw-r--r--private/ole32/stg/docfile/tests/timest.cxx89
-rw-r--r--private/ole32/stg/docfile/tests/tsupp.cxx253
-rw-r--r--private/ole32/stg/docfile/tests/tsupp.hxx41
-rw-r--r--private/ole32/stg/docfile/tests/tutils.cxx485
-rw-r--r--private/ole32/stg/docfile/tests/tutils.hxx124
-rw-r--r--private/ole32/stg/docfile/tests/xact.cxx147
-rw-r--r--private/ole32/stg/docfile/tlsets.cxx165
-rw-r--r--private/ole32/stg/docfile/tset.cxx91
-rw-r--r--private/ole32/stg/docfile/ulist.cxx397
-rw-r--r--private/ole32/stg/docfile/wdffuncs.cxx173
-rw-r--r--private/ole32/stg/docfile/wdfiter.cxx289
-rw-r--r--private/ole32/stg/docfile/wdfstrm.cxx189
-rw-r--r--private/ole32/stg/docfile/wdfxact.cxx589
-rw-r--r--private/ole32/stg/docfile/wdocfile.cxx781
-rw-r--r--private/ole32/stg/drt/daytona/makefile1
-rw-r--r--private/ole32/stg/drt/daytona/sources92
-rw-r--r--private/ole32/stg/drt/depend.mk182
-rw-r--r--private/ole32/stg/drt/depend.mk3102
-rw-r--r--private/ole32/stg/drt/depend.mk964
-rw-r--r--private/ole32/stg/drt/dirs38
-rw-r--r--private/ole32/stg/drt/drt.cxx291
-rw-r--r--private/ole32/stg/drt/drt.def19
-rw-r--r--private/ole32/stg/drt/drt.hxx103
-rw-r--r--private/ole32/stg/drt/drtguid.cxx25
-rw-r--r--private/ole32/stg/drt/filelist.mk101
-rw-r--r--private/ole32/stg/drt/headers.cxx35
-rw-r--r--private/ole32/stg/drt/ilb.cxx422
-rw-r--r--private/ole32/stg/drt/ilb.hxx69
-rw-r--r--private/ole32/stg/drt/illeg.cxx145
-rw-r--r--private/ole32/stg/drt/illeg.hxx21
-rw-r--r--private/ole32/stg/drt/makefile20
-rw-r--r--private/ole32/stg/drt/strlist.cxx148
-rw-r--r--private/ole32/stg/drt/strlist.hxx49
-rw-r--r--private/ole32/stg/drt/tests.cxx793
-rw-r--r--private/ole32/stg/drt/tests.hxx31
-rw-r--r--private/ole32/stg/drt/util.cxx517
-rw-r--r--private/ole32/stg/drt/util.hxx44
-rw-r--r--private/ole32/stg/drt/wrap.cxx684
-rw-r--r--private/ole32/stg/drt/wrap.hxx377
-rw-r--r--private/ole32/stg/exp/ascii.cxx795
-rw-r--r--private/ole32/stg/exp/ascii.hxx40
-rw-r--r--private/ole32/stg/exp/astgconn.cxx606
-rw-r--r--private/ole32/stg/exp/astgconn.hxx181
-rw-r--r--private/ole32/stg/exp/cntxlist.cxx111
-rw-r--r--private/ole32/stg/exp/context.cxx153
-rw-r--r--private/ole32/stg/exp/daytona/makefile1
-rw-r--r--private/ole32/stg/exp/daytona/sources98
-rw-r--r--private/ole32/stg/exp/depend.mk11312
-rw-r--r--private/ole32/stg/exp/depend.mk3904
-rw-r--r--private/ole32/stg/exp/depend.mk9652
-rw-r--r--private/ole32/stg/exp/dfguid.cxx24
-rw-r--r--private/ole32/stg/exp/dfunmfct.cxx570
-rw-r--r--private/ole32/stg/exp/dfunmfct.hxx155
-rw-r--r--private/ole32/stg/exp/dirs38
-rw-r--r--private/ole32/stg/exp/dllentry.c59
-rw-r--r--private/ole32/stg/exp/docfile.cxx1141
-rw-r--r--private/ole32/stg/exp/expdf.cxx3079
-rw-r--r--private/ole32/stg/exp/expdf.hxx306
-rw-r--r--private/ole32/stg/exp/exphead.cxx59
-rw-r--r--private/ole32/stg/exp/expiter.cxx494
-rw-r--r--private/ole32/stg/exp/expiter.hxx92
-rw-r--r--private/ole32/stg/exp/exppiter.cxx432
-rw-r--r--private/ole32/stg/exp/exppiter.hxx92
-rw-r--r--private/ole32/stg/exp/expprop.cxx1542
-rw-r--r--private/ole32/stg/exp/exppset.cxx233
-rw-r--r--private/ole32/stg/exp/exppsi.cxx382
-rw-r--r--private/ole32/stg/exp/exppsi.hxx89
-rw-r--r--private/ole32/stg/exp/expst.cxx2300
-rw-r--r--private/ole32/stg/exp/expst.hxx251
-rw-r--r--private/ole32/stg/exp/filelist.mk53
-rw-r--r--private/ole32/stg/exp/filest.cxx954
-rw-r--r--private/ole32/stg/exp/filest16.cxx1732
-rw-r--r--private/ole32/stg/exp/filest32.cxx1918
-rw-r--r--private/ole32/stg/exp/lock.cxx776
-rw-r--r--private/ole32/stg/exp/makefile20
-rw-r--r--private/ole32/stg/exp/marshl.cxx1111
-rw-r--r--private/ole32/stg/exp/marshl.hxx107
-rw-r--r--private/ole32/stg/exp/mrshlist.cxx117
-rw-r--r--private/ole32/stg/exp/mrshlist.hxx148
-rw-r--r--private/ole32/stg/exp/nmidmap.cxx164
-rw-r--r--private/ole32/stg/exp/nmidmap.hxx150
-rw-r--r--private/ole32/stg/exp/peiter.cxx171
-rw-r--r--private/ole32/stg/exp/peiter.hxx73
-rw-r--r--private/ole32/stg/exp/props.cxx225
-rw-r--r--private/ole32/stg/exp/ptrcache.cxx94
-rw-r--r--private/ole32/stg/exp/resource.cxx669
-rw-r--r--private/ole32/stg/exp/resource.hxx145
-rw-r--r--private/ole32/stg/exp/seekptr.cxx43
-rw-r--r--private/ole32/stg/exp/seekptr.hxx127
-rw-r--r--private/ole32/stg/exp/segexp.hxx218
-rw-r--r--private/ole32/stg/exp/storage.cxx611
-rw-r--r--private/ole32/stg/exp/time16.cxx58
-rw-r--r--private/ole32/stg/exp/time16.hxx21
-rw-r--r--private/ole32/stg/exp/time32.cxx40
-rw-r--r--private/ole32/stg/fsstg/accstg.cxx1051
-rw-r--r--private/ole32/stg/fsstg/api.cxx835
-rw-r--r--private/ole32/stg/fsstg/daytona/makefile1
-rw-r--r--private/ole32/stg/fsstg/daytona/sources58
-rw-r--r--private/ole32/stg/fsstg/depend.mk741
-rw-r--r--private/ole32/stg/fsstg/dirs36
-rw-r--r--private/ole32/stg/fsstg/dirstg.cxx868
-rw-r--r--private/ole32/stg/fsstg/dirstg.hxx138
-rw-r--r--private/ole32/stg/fsstg/dsenm.cxx264
-rw-r--r--private/ole32/stg/fsstg/dsenm.hxx110
-rw-r--r--private/ole32/stg/fsstg/filelist.mk26
-rw-r--r--private/ole32/stg/fsstg/filstg.cxx1083
-rw-r--r--private/ole32/stg/fsstg/filstg.hxx136
-rw-r--r--private/ole32/stg/fsstg/filstm.cxx965
-rw-r--r--private/ole32/stg/fsstg/fsenm.cxx326
-rw-r--r--private/ole32/stg/fsstg/fsenm.hxx83
-rw-r--r--private/ole32/stg/fsstg/headers.cxx44
-rw-r--r--private/ole32/stg/fsstg/makefile23
-rw-r--r--private/ole32/stg/fsstg/ntenm.cxx424
-rw-r--r--private/ole32/stg/fsstg/ntlkb.cxx496
-rw-r--r--private/ole32/stg/fsstg/ntsupp.cxx1243
-rw-r--r--private/ole32/stg/fsstg/omarshal.cxx764
-rw-r--r--private/ole32/stg/fsstg/overlap.cxx110
-rw-r--r--private/ole32/stg/fsstg/stgsupp.cxx252
-rw-r--r--private/ole32/stg/fsstg/stgutil.cxx762
-rw-r--r--private/ole32/stg/fsstg/utest/fstest.cxx465
-rw-r--r--private/ole32/stg/fsstg/utest/idirtest.cxx324
-rw-r--r--private/ole32/stg/fsstg/utest/makefile11
-rw-r--r--private/ole32/stg/fsstg/utest/pch.cxx26
-rw-r--r--private/ole32/stg/fsstg/utest/sources46
-rw-r--r--private/ole32/stg/fsstg/utest/tutils.cxx356
-rw-r--r--private/ole32/stg/fsstg/utest/tutils.hxx84
-rw-r--r--private/ole32/stg/h/accstg.hxx164
-rw-r--r--private/ole32/stg/h/async.hxx30
-rw-r--r--private/ole32/stg/h/cache.hxx106
-rw-r--r--private/ole32/stg/h/cdocfile.hxx188
-rw-r--r--private/ole32/stg/h/chinst.hxx92
-rw-r--r--private/ole32/stg/h/cntxlist.hxx181
-rw-r--r--private/ole32/stg/h/cntxtid.hxx28
-rw-r--r--private/ole32/stg/h/context.hxx953
-rw-r--r--private/ole32/stg/h/dblink.hxx126
-rw-r--r--private/ole32/stg/h/debug.hxx44
-rw-r--r--private/ole32/stg/h/df32.hxx268
-rw-r--r--private/ole32/stg/h/dfbasis.hxx607
-rw-r--r--private/ole32/stg/h/dfdeb.hxx75
-rw-r--r--private/ole32/stg/h/dfentry.hxx95
-rw-r--r--private/ole32/stg/h/dfexcept.hxx69
-rw-r--r--private/ole32/stg/h/dffuncs.hxx328
-rw-r--r--private/ole32/stg/h/dfmem.hxx160
-rw-r--r--private/ole32/stg/h/dfmsp.hxx745
-rw-r--r--private/ole32/stg/h/dfname.hxx83
-rw-r--r--private/ole32/stg/h/dfrlist.hxx27
-rw-r--r--private/ole32/stg/h/dfver.h5
-rw-r--r--private/ole32/stg/h/difat.hxx191
-rw-r--r--private/ole32/stg/h/dir.hxx420
-rw-r--r--private/ole32/stg/h/dirfunc.hxx524
-rw-r--r--private/ole32/stg/h/dl.hxx385
-rw-r--r--private/ole32/stg/h/docfilep.hxx278
-rw-r--r--private/ole32/stg/h/entry.hxx249
-rw-r--r--private/ole32/stg/h/error.hxx33
-rw-r--r--private/ole32/stg/h/fat.hxx705
-rw-r--r--private/ole32/stg/h/filelkb.hxx50
-rw-r--r--private/ole32/stg/h/filest.hxx677
-rw-r--r--private/ole32/stg/h/filstm.hxx120
-rw-r--r--private/ole32/stg/h/freelist.hxx143
-rw-r--r--private/ole32/stg/h/funcs.hxx38
-rw-r--r--private/ole32/stg/h/handle.hxx491
-rw-r--r--private/ole32/stg/h/header.hxx333
-rw-r--r--private/ole32/stg/h/infs.hxx42
-rw-r--r--private/ole32/stg/h/lock.hxx38
-rw-r--r--private/ole32/stg/h/logfile.hxx52
-rw-r--r--private/ole32/stg/h/msf.hxx959
-rw-r--r--private/ole32/stg/h/msffunc.hxx435
-rw-r--r--private/ole32/stg/h/ntenm.hxx104
-rw-r--r--private/ole32/stg/h/ntlkb.hxx104
-rw-r--r--private/ole32/stg/h/ntsupp.hxx80
-rw-r--r--private/ole32/stg/h/ole.hxx72
-rw-r--r--private/ole32/stg/h/omarshal.hxx246
-rw-r--r--private/ole32/stg/h/overlap.hxx99
-rw-r--r--private/ole32/stg/h/page.hxx727
-rw-r--r--private/ole32/stg/h/pbstream.hxx448
-rw-r--r--private/ole32/stg/h/pdocfile.hxx148
-rw-r--r--private/ole32/stg/h/props.hxx66
-rw-r--r--private/ole32/stg/h/psstream.hxx70
-rw-r--r--private/ole32/stg/h/ptrcache.hxx130
-rw-r--r--private/ole32/stg/h/publicdf.hxx823
-rw-r--r--private/ole32/stg/h/ref.hxx198
-rw-r--r--private/ole32/stg/h/refilb.hxx59
-rw-r--r--private/ole32/stg/h/revert.hxx96
-rw-r--r--private/ole32/stg/h/rpubdf.hxx95
-rw-r--r--private/ole32/stg/h/safedecl.hxx32
-rw-r--r--private/ole32/stg/h/segh.hxx68
-rw-r--r--private/ole32/stg/h/sinklist.hxx198
-rw-r--r--private/ole32/stg/h/smalloc.hxx866
-rw-r--r--private/ole32/stg/h/sngprop.hxx73
-rw-r--r--private/ole32/stg/h/sstream.hxx249
-rw-r--r--private/ole32/stg/h/stgprops.hxx48
-rw-r--r--private/ole32/stg/h/stgstm.hxx112
-rw-r--r--private/ole32/stg/h/stgutil.hxx123
-rw-r--r--private/ole32/stg/h/storagep.h31
-rw-r--r--private/ole32/stg/h/tlsets.hxx145
-rw-r--r--private/ole32/stg/h/tset.hxx225
-rw-r--r--private/ole32/stg/h/tstream.hxx310
-rw-r--r--private/ole32/stg/h/ulist.hxx492
-rw-r--r--private/ole32/stg/h/vect.hxx156
-rw-r--r--private/ole32/stg/h/vectfunc.hxx265
-rw-r--r--private/ole32/stg/h/w4wchar.h71
-rw-r--r--private/ole32/stg/h/wdocfile.hxx491
-rw-r--r--private/ole32/stg/makefile90
-rw-r--r--private/ole32/stg/msf/cache.cxx897
-rw-r--r--private/ole32/stg/msf/daytona/makefile1
-rw-r--r--private/ole32/stg/msf/daytona/sources95
-rw-r--r--private/ole32/stg/msf/depend.mk1787
-rw-r--r--private/ole32/stg/msf/depend.mk3648
-rw-r--r--private/ole32/stg/msf/depend.mk9449
-rw-r--r--private/ole32/stg/msf/difat.cxx1190
-rw-r--r--private/ole32/stg/msf/dir.cxx1450
-rw-r--r--private/ole32/stg/msf/dirp.cxx921
-rw-r--r--private/ole32/stg/msf/dirs38
-rw-r--r--private/ole32/stg/msf/dl.cxx1200
-rw-r--r--private/ole32/stg/msf/fat.cxx3562
-rw-r--r--private/ole32/stg/msf/filelist.mk33
-rw-r--r--private/ole32/stg/msf/header.cxx117
-rw-r--r--private/ole32/stg/msf/makefile21
-rw-r--r--private/ole32/stg/msf/mread.hxx420
-rw-r--r--private/ole32/stg/msf/msf.cxx493
-rw-r--r--private/ole32/stg/msf/msfhead.cxx41
-rw-r--r--private/ole32/stg/msf/msfnew.cxx38
-rw-r--r--private/ole32/stg/msf/mstream.cxx2230
-rw-r--r--private/ole32/stg/msf/page.cxx1174
-rw-r--r--private/ole32/stg/msf/pbstream.cxx974
-rw-r--r--private/ole32/stg/msf/refilb.cxx194
-rw-r--r--private/ole32/stg/msf/reftest.cxx533
-rw-r--r--private/ole32/stg/msf/segmsf.hxx234
-rw-r--r--private/ole32/stg/msf/sstream.cxx1320
-rw-r--r--private/ole32/stg/msf/tstream.cxx1275
-rw-r--r--private/ole32/stg/msf/vect.cxx744
-rw-r--r--private/ole32/stg/msf/wep.cxx34
-rw-r--r--private/ole32/stg/ofsstg/depend.mk758
-rw-r--r--private/ole32/stg/ofsstg/dirs36
-rw-r--r--private/ole32/stg/ofsstg/filelist.mk28
-rw-r--r--private/ole32/stg/ofsstg/headers.cxx50
-rw-r--r--private/ole32/stg/ofsstg/makefile23
-rw-r--r--private/ole32/stg/ofsstg/odirdir.cxx1025
-rw-r--r--private/ole32/stg/ofsstg/odirdir.hxx305
-rw-r--r--private/ole32/stg/ofsstg/odirstg.cxx1121
-rw-r--r--private/ole32/stg/ofsstg/odirstg.hxx157
-rw-r--r--private/ole32/stg/ofsstg/odocstg.cxx1445
-rw-r--r--private/ole32/stg/ofsstg/odocstg.hxx181
-rw-r--r--private/ole32/stg/ofsstg/odocstm.cxx1087
-rw-r--r--private/ole32/stg/ofsstg/odocstm.hxx165
-rw-r--r--private/ole32/stg/ofsstg/odsenm.cxx284
-rw-r--r--private/ole32/stg/ofsstg/odsenm.hxx110
-rw-r--r--private/ole32/stg/ofsstg/ofilstg.cxx1116
-rw-r--r--private/ole32/stg/ofsstg/ofilstg.hxx134
-rw-r--r--private/ole32/stg/ofsstg/ofscs.cxx1016
-rw-r--r--private/ole32/stg/ofsstg/ofscs.hxx140
-rw-r--r--private/ole32/stg/ofsstg/ofsenm.cxx326
-rw-r--r--private/ole32/stg/ofsstg/ofsenm.hxx81
-rw-r--r--private/ole32/stg/ofsstg/ofspenm.cxx288
-rw-r--r--private/ole32/stg/ofsstg/ofspenm.hxx89
-rw-r--r--private/ole32/stg/ofsstg/ofsps.cxx178
-rw-r--r--private/ole32/stg/ofsstg/ofsps.hxx70
-rw-r--r--private/ole32/stg/ofsstg/ofspse.cxx291
-rw-r--r--private/ole32/stg/ofsstg/ofspse.hxx88
-rw-r--r--private/ole32/stg/ofsstg/ofspstg.cxx417
-rw-r--r--private/ole32/stg/ofsstg/ofspstg.hxx103
-rw-r--r--private/ole32/stg/ofsstg/ostgsupp.cxx1163
-rw-r--r--private/ole32/stg/ofsstg/ostgsupp.hxx35
-rw-r--r--private/ole32/stg/ofsstg/prstg.cxx67
-rw-r--r--private/ole32/stg/ofsstg/prstg.hxx158
-rw-r--r--private/ole32/stg/ofsstg/utest/depend.mk91
-rw-r--r--private/ole32/stg/ofsstg/utest/dirs22
-rw-r--r--private/ole32/stg/ofsstg/utest/filelist.mk23
-rw-r--r--private/ole32/stg/ofsstg/utest/makefile12
-rw-r--r--private/ole32/stg/ofsstg/utest/ofstest.cxx594
-rw-r--r--private/ole32/stg/ofsstg/utest/pch.cxx24
-rw-r--r--private/ole32/stg/ofsstg/utest/tutils.cxx356
-rw-r--r--private/ole32/stg/ofsstg/utest/tutils.hxx84
-rw-r--r--private/ole32/stg/ofsstg/utest2/dirs35
-rw-r--r--private/ole32/stg/ofsstg/utest2/ofstest.cxx350
-rw-r--r--private/ole32/stg/ofsstg/utest2/pch.cxx24
-rw-r--r--private/ole32/stg/ofsstg/utest2/tsupp.cxx253
-rw-r--r--private/ole32/stg/ofsstg/utest2/tsupp.hxx41
-rw-r--r--private/ole32/stg/ofsstg/utest2/tutils.cxx485
-rw-r--r--private/ole32/stg/ofsstg/utest2/tutils.hxx124
-rw-r--r--private/ole32/stg/ofsstg/variant.cxx742
-rw-r--r--private/ole32/stg/ole2flat/coguid.h65
-rw-r--r--private/ole32/stg/ole2flat/compobj.h1059
-rw-r--r--private/ole32/stg/ole2flat/dvobj.h480
-rw-r--r--private/ole32/stg/ole2flat/initguid.h38
-rw-r--r--private/ole32/stg/ole2flat/moniker.h248
-rw-r--r--private/ole32/stg/ole2flat/ole2.h1342
-rw-r--r--private/ole32/stg/ole2flat/oleguid.h80
-rw-r--r--private/ole32/stg/ole2flat/scode.h283
-rw-r--r--private/ole32/stg/ole2flat/storage.h457
-rw-r--r--private/ole32/stg/ole2flat/valid.h72
-rw-r--r--private/ole32/stg/ole2flat/verinfo.h22
-rw-r--r--private/ole32/stg/ole2h/coguid.h52
-rw-r--r--private/ole32/stg/ole2h/compobj.h1025
-rw-r--r--private/ole32/stg/ole2h/initguid.h38
-rw-r--r--private/ole32/stg/ole2h/scode.h281
-rw-r--r--private/ole32/stg/ole2h/storage.h452
-rw-r--r--private/ole32/stg/ole2h/valid.h72
-rw-r--r--private/ole32/stg/ole2h/verinfo.h22
-rw-r--r--private/ole32/stg/props/cfmapstm.cxx766
-rw-r--r--private/ole32/stg/props/cfmapstm.hxx102
-rw-r--r--private/ole32/stg/props/daytona/makefile1
-rw-r--r--private/ole32/stg/props/daytona/sources55
-rw-r--r--private/ole32/stg/props/debtrace.hxx15
-rw-r--r--private/ole32/stg/props/dirs18
-rw-r--r--private/ole32/stg/props/iprop/call_as.c633
-rw-r--r--private/ole32/stg/props/iprop/dllmain.cxx517
-rw-r--r--private/ole32/stg/props/iprop/iprop.def15
-rw-r--r--private/ole32/stg/props/iprop/iprop.r18
-rw-r--r--private/ole32/stg/props/iprop/iprop.rc16
-rw-r--r--private/ole32/stg/props/iprop/ipropidl.idl579
-rw-r--r--private/ole32/stg/props/iprop/makefile10
-rw-r--r--private/ole32/stg/props/iprop/makefile.inc41
-rw-r--r--private/ole32/stg/props/iprop/oaidl.h3843
-rw-r--r--private/ole32/stg/props/iprop/oaidl.idl1651
-rw-r--r--private/ole32/stg/props/iprop/objbase.h594
-rw-r--r--private/ole32/stg/props/iprop/objidl.h7741
-rw-r--r--private/ole32/stg/props/iprop/objidl.idl1745
-rw-r--r--private/ole32/stg/props/iprop/oleauto.h683
-rw-r--r--private/ole32/stg/props/iprop/oleidl.h4916
-rw-r--r--private/ole32/stg/props/iprop/privoa.cxx154
-rw-r--r--private/ole32/stg/props/iprop/prstg_ca.c685
-rw-r--r--private/ole32/stg/props/iprop/prstg_ca.h67
-rw-r--r--private/ole32/stg/props/iprop/rpcbase.h34
-rw-r--r--private/ole32/stg/props/iprop/sources90
-rw-r--r--private/ole32/stg/props/iprop/unknwn.h325
-rw-r--r--private/ole32/stg/props/iprop/unknwn.idl76
-rw-r--r--private/ole32/stg/props/iprop/wtypes.h848
-rw-r--r--private/ole32/stg/props/iprop/wtypes.idl729
-rw-r--r--private/ole32/stg/props/issues.txt21
-rw-r--r--private/ole32/stg/props/ntdllmac.hxx187
-rw-r--r--private/ole32/stg/props/ntprop.cxx409
-rw-r--r--private/ole32/stg/props/ntpropb.cxx2377
-rw-r--r--private/ole32/stg/props/pch.cxx102
-rw-r--r--private/ole32/stg/props/propapi.cxx573
-rw-r--r--private/ole32/stg/props/propdbg.hxx68
-rw-r--r--private/ole32/stg/props/prophdr.hxx20
-rw-r--r--private/ole32/stg/props/propstg.cxx3661
-rw-r--r--private/ole32/stg/props/propstg.hxx838
-rw-r--r--private/ole32/stg/props/propstm.cxx7971
-rw-r--r--private/ole32/stg/props/propvar.cxx3264
-rw-r--r--private/ole32/stg/props/prpsetup/makefile10
-rw-r--r--private/ole32/stg/props/prpsetup/makefile.inc44
-rw-r--r--private/ole32/stg/props/prpsetup/prpsetup.cxx612
-rw-r--r--private/ole32/stg/props/prpsetup/prpsetup.rc17
-rw-r--r--private/ole32/stg/props/prpsetup/sources91
-rw-r--r--private/ole32/stg/props/psetstg.cxx1583
-rw-r--r--private/ole32/stg/props/psetstg.hxx297
-rw-r--r--private/ole32/stg/props/reserved.cxx236
-rw-r--r--private/ole32/stg/props/reserved.hxx183
-rw-r--r--private/ole32/stg/props/stgvarb.cxx1206
-rw-r--r--private/ole32/stg/props/utest/chresult.hxx118
-rw-r--r--private/ole32/stg/props/utest/cpropvar.cxx573
-rw-r--r--private/ole32/stg/props/utest/cpropvar.hxx811
-rw-r--r--private/ole32/stg/props/utest/daytona/makefile10
-rw-r--r--private/ole32/stg/props/utest/daytona/makefile.inc5
-rw-r--r--private/ole32/stg/props/utest/daytona/sources49
-rw-r--r--private/ole32/stg/props/utest/dirs2
-rw-r--r--private/ole32/stg/props/utest/open.cxx213
-rw-r--r--private/ole32/stg/props/utest/pch.cxx220
-rw-r--r--private/ole32/stg/props/utest/propdump.cxx1453
-rw-r--r--private/ole32/stg/props/utest/propmshl.cxx409
-rw-r--r--private/ole32/stg/props/utest/propmshl.hxx63
-rw-r--r--private/ole32/stg/props/utest/proptest.cxx2035
-rw-r--r--private/ole32/stg/props/utest/proptest.hxx558
-rw-r--r--private/ole32/stg/props/utest/proptest.rc9
-rw-r--r--private/ole32/stg/props/utest/prstgsrv.hxx179
-rw-r--r--private/ole32/stg/props/utest/pstgserv/daytona/makefile10
-rw-r--r--private/ole32/stg/props/utest/pstgserv/daytona/sources47
-rw-r--r--private/ole32/stg/props/utest/pstgserv/dirs2
-rw-r--r--private/ole32/stg/props/utest/pstgserv/main.cxx20
-rw-r--r--private/ole32/stg/props/utest/pstgserv/proxstub/daytona/makefile10
-rw-r--r--private/ole32/stg/props/utest/pstgserv/proxstub/daytona/makefile.inc29
-rw-r--r--private/ole32/stg/props/utest/pstgserv/proxstub/daytona/sources38
-rw-r--r--private/ole32/stg/props/utest/pstgserv/proxstub/dirs2
-rw-r--r--private/ole32/stg/props/utest/pstgserv/proxstub/dllmain.cxx12
-rw-r--r--private/ole32/stg/props/utest/pstgserv/proxstub/proxstub.rc9
-rw-r--r--private/ole32/stg/props/utest/pstgserv/proxstub/pstgserv.def5
-rw-r--r--private/ole32/stg/props/utest/pstgserv/proxstub/pstgserv.idl20
-rw-r--r--private/ole32/stg/props/utest/pstgserv/pssclass.cxx225
-rw-r--r--private/ole32/stg/props/utest/pstgserv/pssclass.hxx90
-rw-r--r--private/ole32/stg/props/utest/pstgserv/pstgserv.cxx129
-rw-r--r--private/ole32/stg/props/utest/pstgserv/pstgserv.hxx42
-rw-r--r--private/ole32/stg/props/utest/pstgserv/pstgserv.icobin0 -> 1078 bytes
-rw-r--r--private/ole32/stg/props/utest/pstgserv/pstgserv.rc50
-rw-r--r--private/ole32/stg/props/utest/pstgserv/pstgserv.rc213
-rw-r--r--private/ole32/stg/props/utest/pstgserv/pstgserv.reg7
-rw-r--r--private/ole32/stg/props/utest/pstgserv/resource.h21
-rw-r--r--private/ole32/stg/props/utest/rtlstub.cxx783
-rw-r--r--private/ole32/stg/props/utest/testcase.cxx5165
-rw-r--r--private/ole32/stg/props/utest/testdoc.cxx421
-rw-r--r--private/ole32/stg/props/utest/testdoc.docbin0 -> 6656 bytes
-rw-r--r--private/ole32/stg/props/utils.cxx1191
-rw-r--r--private/ole32/stg/props/utils.hxx143
-rw-r--r--private/ole32/stg/ref/ascii.cxx488
-rw-r--r--private/ole32/stg/ref/ascii.hxx23
-rw-r--r--private/ole32/stg/ref/cdocfile.cxx388
-rw-r--r--private/ole32/stg/ref/chinst.cxx219
-rw-r--r--private/ole32/stg/ref/depend.mk438
-rw-r--r--private/ole32/stg/ref/dffuncs.cxx160
-rw-r--r--private/ole32/stg/ref/dfhead.cxx31
-rw-r--r--private/ole32/stg/ref/dfiter.cxx50
-rw-r--r--private/ole32/stg/ref/dfstream.cxx108
-rw-r--r--private/ole32/stg/ref/difat.cxx439
-rw-r--r--private/ole32/stg/ref/dir.cxx1045
-rw-r--r--private/ole32/stg/ref/dirp.cxx871
-rw-r--r--private/ole32/stg/ref/docfile.cxx262
-rw-r--r--private/ole32/stg/ref/entry.cxx44
-rw-r--r--private/ole32/stg/ref/expdf.cxx1511
-rw-r--r--private/ole32/stg/ref/expdf.hxx206
-rw-r--r--private/ole32/stg/ref/exphead.cxx29
-rw-r--r--private/ole32/stg/ref/expiter.cxx333
-rw-r--r--private/ole32/stg/ref/expiter.hxx76
-rw-r--r--private/ole32/stg/ref/expst.cxx916
-rw-r--r--private/ole32/stg/ref/expst.hxx124
-rw-r--r--private/ole32/stg/ref/fat.cxx1414
-rw-r--r--private/ole32/stg/ref/funcs.cxx352
-rw-r--r--private/ole32/stg/ref/h/cdocfile.hxx130
-rw-r--r--private/ole32/stg/ref/h/chinst.hxx81
-rw-r--r--private/ole32/stg/ref/h/dfentry.hxx34
-rw-r--r--private/ole32/stg/ref/h/dfexcept.hxx37
-rw-r--r--private/ole32/stg/ref/h/dffuncs.hxx112
-rw-r--r--private/ole32/stg/ref/h/dfmsp.hxx365
-rw-r--r--private/ole32/stg/ref/h/dfver.h3
-rw-r--r--private/ole32/stg/ref/h/difat.hxx131
-rw-r--r--private/ole32/stg/ref/h/dir.hxx358
-rw-r--r--private/ole32/stg/ref/h/dirfunc.hxx409
-rw-r--r--private/ole32/stg/ref/h/docfilep.hxx40
-rw-r--r--private/ole32/stg/ref/h/entry.hxx148
-rw-r--r--private/ole32/stg/ref/h/error.hxx31
-rw-r--r--private/ole32/stg/ref/h/fat.hxx417
-rw-r--r--private/ole32/stg/ref/h/funcs.hxx73
-rw-r--r--private/ole32/stg/ref/h/handle.hxx402
-rw-r--r--private/ole32/stg/ref/h/header.hxx276
-rw-r--r--private/ole32/stg/ref/h/lock.hxx24
-rw-r--r--private/ole32/stg/ref/h/msf.hxx512
-rw-r--r--private/ole32/stg/ref/h/msffunc.hxx311
-rw-r--r--private/ole32/stg/ref/h/msfiter.hxx96
-rw-r--r--private/ole32/stg/ref/h/ole.hxx57
-rw-r--r--private/ole32/stg/ref/h/page.hxx552
-rw-r--r--private/ole32/stg/ref/h/pbstream.hxx274
-rw-r--r--private/ole32/stg/ref/h/pdocfile.hxx110
-rw-r--r--private/ole32/stg/ref/h/piter.hxx35
-rw-r--r--private/ole32/stg/ref/h/psstream.hxx49
-rw-r--r--private/ole32/stg/ref/h/pubiter.hxx120
-rw-r--r--private/ole32/stg/ref/h/publicdf.hxx478
-rw-r--r--private/ole32/stg/ref/h/ref.hxx194
-rw-r--r--private/ole32/stg/ref/h/refilb.hxx57
-rw-r--r--private/ole32/stg/ref/h/revert.hxx84
-rw-r--r--private/ole32/stg/ref/h/rpubdf.hxx49
-rw-r--r--private/ole32/stg/ref/h/sstream.hxx200
-rw-r--r--private/ole32/stg/ref/h/storage.h433
-rw-r--r--private/ole32/stg/ref/h/storagep.h29
-rw-r--r--private/ole32/stg/ref/h/vect.hxx146
-rw-r--r--private/ole32/stg/ref/h/vectfunc.hxx239
-rw-r--r--private/ole32/stg/ref/h/wchar.h62
-rw-r--r--private/ole32/stg/ref/header.cxx93
-rw-r--r--private/ole32/stg/ref/iter.cxx157
-rw-r--r--private/ole32/stg/ref/iter.hxx48
-rw-r--r--private/ole32/stg/ref/lock.cxx313
-rw-r--r--private/ole32/stg/ref/logfile.hxx2
-rw-r--r--private/ole32/stg/ref/makefile109
-rw-r--r--private/ole32/stg/ref/mread.hxx259
-rw-r--r--private/ole32/stg/ref/msf.cxx289
-rw-r--r--private/ole32/stg/ref/msfhead.cxx20
-rw-r--r--private/ole32/stg/ref/msfiter.cxx138
-rw-r--r--private/ole32/stg/ref/mstream.cxx1006
-rw-r--r--private/ole32/stg/ref/page.cxx554
-rw-r--r--private/ole32/stg/ref/pbstream.cxx221
-rw-r--r--private/ole32/stg/ref/pdffuncs.cxx79
-rw-r--r--private/ole32/stg/ref/peiter.cxx103
-rw-r--r--private/ole32/stg/ref/peiter.hxx76
-rw-r--r--private/ole32/stg/ref/pubiter.cxx231
-rw-r--r--private/ole32/stg/ref/publicdf.cxx772
-rw-r--r--private/ole32/stg/ref/refilb.cxx190
-rw-r--r--private/ole32/stg/ref/reftest.cxx549
-rw-r--r--private/ole32/stg/ref/rpubdf.cxx245
-rw-r--r--private/ole32/stg/ref/seekptr.cxx32
-rw-r--r--private/ole32/stg/ref/seekptr.hxx113
-rw-r--r--private/ole32/stg/ref/sstream.cxx710
-rw-r--r--private/ole32/stg/ref/storage.cxx173
-rw-r--r--private/ole32/stg/ref/storage.def7
-rw-r--r--private/ole32/stg/ref/time16.cxx25
-rw-r--r--private/ole32/stg/ref/time16.hxx19
-rw-r--r--private/ole32/stg/ref/vect.cxx456
-rw-r--r--private/ole32/stg/ref/wcscat.c77
-rw-r--r--private/ole32/stg/ref/wcslen.c39
-rw-r--r--private/ole32/stg/ref/wcsnicmp.c64
-rw-r--r--private/ole32/stg/segments.asm72
-rw-r--r--private/ole32/stg/setole2.mk35
-rw-r--r--private/ole32/stg/simp/daytona/makefile1
-rw-r--r--private/ole32/stg/simp/daytona/sources82
-rw-r--r--private/ole32/stg/simp/dfnlist.hxx107
-rw-r--r--private/ole32/stg/simp/dirs38
-rw-r--r--private/ole32/stg/simp/makefile21
-rw-r--r--private/ole32/stg/simp/simpdf.cxx76
-rw-r--r--private/ole32/stg/simp/simpdf.hxx248
-rw-r--r--private/ole32/stg/simp/simphead.cxx39
-rw-r--r--private/ole32/stg/simp/simpstg.cxx1187
-rw-r--r--private/ole32/stg/simp/simpstm.cxx925
-rw-r--r--private/ole32/stg/simp/simpstm.hxx151
-rw-r--r--private/ole32/stg/storage.def59
-rw-r--r--private/ole32/stg/utils/chkdsk/chkdsk.cxx374
-rw-r--r--private/ole32/stg/utils/chkdsk/chkdsk.def21
-rw-r--r--private/ole32/stg/utils/chkdsk/chkdsk.hxx116
-rw-r--r--private/ole32/stg/utils/chkdsk/depend.mk916
-rw-r--r--private/ole32/stg/utils/chkdsk/makefile106
-rw-r--r--private/ole32/stg/utils/compob32/compob32.cxx162
-rw-r--r--private/ole32/stg/utils/compob32/compob32.def27
-rw-r--r--private/ole32/stg/utils/compob32/depend.mk369
-rw-r--r--private/ole32/stg/utils/compob32/dllentry.c33
-rw-r--r--private/ole32/stg/utils/compob32/makefile24
-rw-r--r--private/ole32/stg/utils/compob32/pch.cxx13
-rw-r--r--private/ole32/stg/utils/df2t/depend.mk158
-rw-r--r--private/ole32/stg/utils/df2t/depend.mk919
-rw-r--r--private/ole32/stg/utils/df2t/df2t.cxx696
-rw-r--r--private/ole32/stg/utils/df2t/df2t.def21
-rw-r--r--private/ole32/stg/utils/df2t/makefile28
-rw-r--r--private/ole32/stg/utils/df2t/read.me13
-rw-r--r--private/ole32/stg/utils/df2t/w4ctsupp.cxx589
-rw-r--r--private/ole32/stg/utils/df2t/w4ctsupp.hxx172
-rw-r--r--private/ole32/stg/utils/fail/depend.mk961
-rw-r--r--private/ole32/stg/utils/fail/fail.cxx2666
-rw-r--r--private/ole32/stg/utils/fail/headers.cxx28
-rw-r--r--private/ole32/stg/utils/fail/makefile27
-rw-r--r--private/ole32/stg/utils/fail/sift.cxx143
-rw-r--r--private/ole32/stg/utils/fail/sift.def19
-rw-r--r--private/ole32/stg/utils/fail/sift.hxx125
-rw-r--r--private/ole32/stg/utils/fail/supp.cxx193
-rw-r--r--private/ole32/stg/utils/makefile21
-rw-r--r--private/ole32/stg/utils/stgview/daytona/makefile1
-rw-r--r--private/ole32/stg/utils/stgview/daytona/sources87
-rw-r--r--private/ole32/stg/utils/stgview/depend.mk134
-rw-r--r--private/ole32/stg/utils/stgview/depend.mk919
-rw-r--r--private/ole32/stg/utils/stgview/dirs38
-rw-r--r--private/ole32/stg/utils/stgview/makefile21
-rw-r--r--private/ole32/stg/utils/stgview/stgview.cxx411
-rw-r--r--private/ole32/stg/utils/stgview/stgview.def21
-rw-r--r--private/ole32/stg/utils/util.mk80
-rw-r--r--private/ole32/stg/wclib/depend.mk32
-rw-r--r--private/ole32/stg/wclib/dirs36
-rw-r--r--private/ole32/stg/wclib/filelist.mk34
-rw-r--r--private/ole32/stg/wclib/makefile23
-rw-r--r--private/ole32/stg/wclib/wcschr.c44
-rw-r--r--private/ole32/stg/wclib/wcscmp.c54
-rw-r--r--private/ole32/stg/wclib/wcscpy.c41
-rw-r--r--private/ole32/stg/wclib/wcsicmp.c77
-rw-r--r--private/ole32/stg/wclib/wcslen.c42
-rw-r--r--private/ole32/stg/wclib/wcsncmp.c52
-rw-r--r--private/ole32/stg/wclib/wcsnicmp.c63
-rw-r--r--private/ole32/stg/wclib/wcsrchr.c49
-rw-r--r--private/ole32/stg/wclib/wcstr.h51
-rw-r--r--private/ole32/stg/xact/coord.cxx1694
-rw-r--r--private/ole32/stg/xact/coord.hxx207
-rw-r--r--private/ole32/stg/xact/dirs37
-rw-r--r--private/ole32/stg/xact/enlist.cxx564
-rw-r--r--private/ole32/stg/xact/enlist.hxx68
-rw-r--r--private/ole32/stg/xact/xact.cxx24
-rw-r--r--private/ole32/stg/xact/xact.hxx47
-rw-r--r--private/ole32/stg/xact/xactdisp.cxx383
-rw-r--r--private/ole32/stg/xact/xactdisp.hxx64
-rw-r--r--private/ole32/stg/xact/xactenum.cxx679
-rw-r--r--private/ole32/stg/xact/xactenum.hxx98
-rw-r--r--private/ole32/stg/xact/xacthead.cxx23
-rw-r--r--private/ole32/stg/xact/xactlist.hxx223
2190 files changed, 756159 insertions, 0 deletions
diff --git a/private/ole32/cairobld.mk b/private/ole32/cairobld.mk
new file mode 100644
index 000000000..babbe476c
--- /dev/null
+++ b/private/ole32/cairobld.mk
@@ -0,0 +1,51 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ cairobld.mk
+
+Abstract:
+
+ This file is included from all of the cairo sources files. It
+ is handy for doing things like turning off precompiled headers
+ to get around compiler bugs, and other such global activities.
+
+Notes:
+
+ We define _OLE32_ so that when building ole32.dll we don't have
+ DECLSPEC_IMPORT defined (see objbase.h)
+
+ BUGBUG: BillMo: remove NEWPROPS before checkin.
+
+!ENDIF
+
+CAIRO_PRODUCT=1
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -D_TRACKLINK_=1 \
+ -DNOEXCEPTIONS \
+ -DINC_OLE2 \
+ -DFLAT \
+ -DWIN32=300 \
+ -D_CAIRO_=300 \
+ -DCAIROLE_DISTRIBUTED \
+ -DNEWPROPS \
+ -DDCOM \
+ -DMSWMSG \
+ -DDCOM_SECURITY
+
+# DECLSPEC_IMPORT control (see objbase.h)
+!if "$(MINORCOMP)"=="com" || "$(MINORCOMP)"=="stg" || "$(MINORCOMP)"=="ole232" || "$(MINORCOMP)"=="propset"
+C_DEFINES= \
+ $(C_DEFINES) \
+ -D_OLE32_
+!endif
+
+BLDCRT= 1
+
+USE_CRTDLL= 1
+
+GPCH_BUILD=cairo
diff --git a/private/ole32/changes.txt b/private/ole32/changes.txt
new file mode 100644
index 000000000..24e5a1dbc
--- /dev/null
+++ b/private/ole32/changes.txt
@@ -0,0 +1,96 @@
+32-bit OLE External Change Log
+
+The intent of this change history is to allow us to give more detailed
+information on what has changed to our customers whenever we make an
+external drop. You only need to add an entry if your delta changes
+something that an external customer would want to know. Please include
+the following information:
+
+date email-name raid # platform (Daytona, Chicago, Cairo, all)
+brief description
+
+===============================================================================
+04/07/94 CraigWi all
+The stubmgr (ID/RH) now calls IExternalConnection for the addition and
+subtraction of strong connections.
+
+03/21/94 CraigWi all
+We now addref the pointer held by the stubmgr (ID/RH). That is, the first
+sentence of the next paragraph has been reversed.
+
+02/25/94 CraigWi all
+Differences with 16bit OLE: CoMarshalInterface table weak does not addref the
+object; there must always be a strong connection or a real addref'd pointer
+to hold the object alive. IPersist is no longer used to determine the clsid
+of the handler. IStdMarshalInfo::GetClassForHandler is the only way this
+is provided. For the time being, all IAdviseSink calls are synchronous;
+this changes the order of calls in shutdown cases; all IAdviseSink methods
+will be made asynchronous later.
+
+Class-specific handlers are now functional (i.e.,
+IStdMarshalInfo::GetClassForHandler is called and that clsid determines
+the clsid of the handler on the receiving end).
+
+CoUninitialize releases all external connections; rundowns were supposed to
+do that, but the RPC runtime didn't work correctly.
+
+02/17/94 AlexT all
+1) CoBuildVersion will now return the daily build number (starting around 701)
+ as the low word. This can be used to determine which build of 32-bit OLE
+ you are using.
+2) I removed OleGetMalloc (which was exported via the .src files but not
+ listed in any public headers).
+3) I also removed OleBuildVersion and aliased it to CoBuildVersion. If you
+ use OleBuildVersion, you will need to relink your apps with ole32.lib to
+ get the alias correctly (no backwards compatibility issues since we
+ haven't shipped 32-bit OLE yet).
+
+02/05/94 Rickhi all
+1) Provided option to start an OLE server under a debugger. This replaces the
+now defunct 'Image File Execution Options" lost in retail Nt. Instructions for
+doing so are as follows:
+
+ create key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\scm
+ and under it create a value: 'Debugger : REG_SZ : ntsd -G'
+ (or specify whatever debugger and options you want eg windbg)
+
+ create key HKEY_CLASSES_ROOT\CLSID\{your favorite class guid}\Debug
+ and under it create a nameless value: ' : REG_SZ : Y'
+
+ Y or y means the server will start under the debugger. Any other value
+ means it will not start under the debugger.
+
+02/03/94 Rickhi all
+1) Removed obsolete APIs CoCreateCriticialSection & friends
+2) Export IIDFromString and StringFromIID
+
+01/31/94 Rickhi all
+1) Improved support for transmitting STGMEDIUM, HBITMAP, HMETAFILEPICT
+
+01/13/94 Ricksa all
+1) Fix class start up timeout problem
+2) Fix server name problem (that they need to be unique within 6 characters)
+3) Fix multi-process start up race in oleinitialize
+4) Removed SCM window
+
+01/07/94 Ricksa all
+1) Add new ROT implementation
+2) SCM updates class DB based on registry changes
+3) Treat as cache updated based on registry changes
+4) Class start up races fixed
+
+12/16/93 Ricksa all
+Fixed bug with single use class registration and added support for
+REGCLS_MULTI_SEPARATE.
+
+12/16/93 ChrisWe - all
+Fixed several UNICODE handling bugs in internal utilities in ole232.dll that
+were preventing clipboard operations from working.
+
+12/16/93 ChrisWe - Daytona, Cairo
+Fixed several UNICODE handling bugs in OleStd utilities in olestd.c in
+the ole2 samples, which were preventing some functionality in the samples
+from working.
+
+12/13/93 alext - Daytona (x86 only)
+First public drop
diff --git a/private/ole32/chicago.inc b/private/ole32/chicago.inc
new file mode 100644
index 000000000..aac21225c
--- /dev/null
+++ b/private/ole32/chicago.inc
@@ -0,0 +1,37 @@
+# This is the global include file for the daytona version of CairOLE.
+# It is included by all project sources files.
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DFLAT \
+ -DWIN32=200 \
+ -D_CHICAGO_=200 \
+ -DINC_OLE2 \
+ -DNOEXCEPTIONS \
+ -DCAIROLE_DOWNLEVEL \
+ -DSTRICT \
+ -DNEWPROPS \
+ -DMSWMSG \
+ -DASYNC \
+ $(TRACELOG)
+
+# DECLSPEC_IMPORT control (see objbase.h)
+!if "$(MINORCOMP)"=="com" || "$(MINORCOMP)"=="stg" || "$(MINORCOMP)"=="ole232" || \
+ "$(MINORCOMP)"=="common" || "$(MINORCOMP)"=="proxy"
+C_DEFINES= \
+ $(C_DEFINES) \
+ -D_OLE32_ \
+ -D_OLE32PRIV_
+!endif
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+USE_NOLIBS=1
+
+CHICAGO_PRODUCT=1
+
+NTLIBCPATH=$(_WINBASE)\Dev\Tools\Lego\Lib
+
+GPCH_BUILD=chicago
+
+NTLEGO=1
diff --git a/private/ole32/com/accctrl/acext.h b/private/ole32/com/accctrl/acext.h
new file mode 100644
index 000000000..b182effd0
--- /dev/null
+++ b/private/ole32/com/accctrl/acext.h
@@ -0,0 +1,52 @@
+//+-------------------------------------------------------------------
+//
+// File: acext.h
+//
+// Copyright (C) Microsoft Corporation, 1996 - 1996.
+//
+// Contents: Definitions shared by access control implementation
+//
+//--------------------------------------------------------------------
+
+// Variables imported from the acsrv module
+extern IMalloc *g_pIMalloc; // Cached pointer to memory allocator
+extern ULONG g_ulHeaderSize;
+extern UINT g_uiCodePage; // Code page used for Chicago string converion
+
+#ifdef _CHICAGO_
+extern DWORD g_dwProcessID; // Current process ID of the DLL
+#endif
+
+// Define the set of access mask supported
+// Memory management functions local to the server
+extern void * LocalMemAlloc(ULONG);
+extern void LocalMemFree(void *);
+#ifdef _CHICAGO_
+extern SHORT FoolstrcmpiW(LPWSTR, LPWSTR);
+#endif
+
+// A table can be used to store mask in a more elegant manner
+// COM_RIGHTS_EXECUTE is defined in objbase.h
+
+#ifndef COM_RIGHTS_EXECUTE
+#define COM_RIGHTS_EXECUTE 0x00000001
+#endif
+#define COM_RIGHTS_ALL (COM_RIGHTS_EXECUTE)
+
+//#ifdef _CHICAGO_
+#define CHICAGO_RIGHTS_EXECUTE ACCESS_EXEC
+#define CHICAGO_RIGHTS_ALL (CHICAGO_RIGHTS_EXECUTE)
+//#else
+#define NT_RIGHTS_EXECUTE (COM_RIGHTS_EXECUTE)
+#define NT_RIGHTS_ALL (NT_RIGHTS_EXECUTE)
+//#endif
+
+// Define the stream version code
+#define STREAM_VERSION 0x00000001
+
+// A GUID string containing the braces and dashes
+// but no null character at the end has exactly
+// 38 characters.
+#define GUID_SIZE 38
+
+
diff --git a/private/ole32/com/accctrl/acpickl.acf b/private/ole32/com/accctrl/acpickl.acf
new file mode 100644
index 000000000..664d05714
--- /dev/null
+++ b/private/ole32/com/accctrl/acpickl.acf
@@ -0,0 +1,9 @@
+[
+explicit_handle
+]
+interface AccCntrlPickle
+{
+typedef [encode, decode] STREAM_HEADER;
+typedef [encode, decode] STREAM_ACE;
+typedef [encode, decode] STREAM_ACL;
+}
diff --git a/private/ole32/com/accctrl/acpickl.idl b/private/ole32/com/accctrl/acpickl.idl
new file mode 100644
index 000000000..d0d8b9b35
--- /dev/null
+++ b/private/ole32/com/accctrl/acpickl.idl
@@ -0,0 +1,84 @@
+[
+uuid (52c0e9e2-c0c0-11cf-aeec-00aa0044fb89),
+version(1.0),
+pointer_default(unique)
+]
+interface AccCntrlPickle
+{
+
+import "unknwn.idl";
+#pragma midl_echo("#ifndef UNICODE")
+#pragma midl_echo("#define UNICODE")
+#pragma midl_echo("#else")
+#pragma midl_echo("#define UNICODE_IS_DEFINED")
+#pragma midl_echo("#endif")
+#pragma midl_echo("#ifndef __ACCESS_CONTROL__")
+#pragma midl_echo("#define __ACCESS_CONTROL__")
+#include "accctrl.h";
+#pragma midl_echo("#endif")
+#pragma midl_echo("#ifndef UNICODE_IS_DEFINED")
+#pragma midl_echo("#undef UNICODE")
+#pragma midl_echo("#endif")
+
+// Since the midl compiler doesn't like the syntax in ntseapi.h, I have to
+// redefine the following two structures using slighlty different names.
+// Type casting may be needed in the source code assign the SID to the pSID
+// field in the STREAM_ACE structure.
+typedef struct tagSSID_IDENTIFIER_AUTHORITY{
+ UCHAR Value[6];
+} SSID_IDENTIFIER_AUTHORITY;
+
+
+typedef struct tagSTREAM_SID
+{
+ UCHAR Revision;
+ UCHAR SubAuthorityCount;
+ SSID_IDENTIFIER_AUTHORITY IdentifierAuthority;
+ [size_is(SubAuthorityCount)]ULONG SubAuthority[*];
+}STREAM_SID, *PSTREAM_SID;
+
+// The following structure describes what an ACE should look like
+// in persistent form. Notice that the following structure doesn't
+// contain all the fields in the EXPLICIT_ACCESS structure defined in
+// sdk\inc\accctrl.h. Right now, the amount of information maintained inside
+// this structure is kept at a minimal, should additional fields be required
+// in the future, converters can be created to transform different versions
+// stream ACEs based on the version code in the header.
+typedef struct tagSTREAM_ACE
+{
+ DWORD grfAccessPermissions;
+ ACCESS_MODE grfAccessMode;
+ TRUSTEE_TYPE TrusteeType;
+ TRUSTEE_FORM TrusteeForm;
+ LPWSTR pTrusteeName;
+ PSTREAM_SID pSID;
+} STREAM_ACE;
+
+
+// The STREAM_ACL structure describes the persistent form of the ACL.
+// The current version of the structure can only support the DENY_ACCESS mode
+// ACEs and the GRANT_ACCESS mode ACEs. SET_ACCESS mode ACEs can supported
+// by adding ulNumOfSetEntries field to the structure.
+typedef struct tagSTREAM_ACL
+{
+ ULONG ulNumOfDenyEntries;
+ ULONG ulNumOfGrantEntries;
+ [ size_is(ulNumOfDenyEntries + ulNumOfGrantEntries)]
+ STREAM_ACE *pACL;
+} STREAM_ACL;
+
+// The STREAM_HEADER structure is placed before the encoded STREAM_ACL structure
+// when the client invokes the IPersistStream::Save method of the CImpAccessControl
+// class. This structure contains the encoded size of the STREAM_ACL structure so that
+// the IPersistStream method knowns how many bytes to read from the stream when
+// the ACL is reloaded. The STREAM_HEADER structure also contains the
+// version code of the STREAM_ACL which allows cnoverters to be made if either the
+// STREAM_ACL or STREAM_ACE structure is expanded in the future.
+typedef struct tagSTREAM_HEADER
+{
+ ULONG ulStreamVersion;
+ ULONG ulPickledSize;
+} STREAM_HEADER;
+
+
+} // AccCntrlPickle
diff --git a/private/ole32/com/accctrl/acsrv.cxx b/private/ole32/com/accctrl/acsrv.cxx
new file mode 100644
index 000000000..ad414e357
--- /dev/null
+++ b/private/ole32/com/accctrl/acsrv.cxx
@@ -0,0 +1,264 @@
+//+---------------------------------------------------------------------------
+//
+// File: acsrv.cxx
+//
+// Description: This file contains code to initialize the access control
+// globals
+//
+// Functions: InitializeAccessControl
+//
+//+---------------------------------------------------------------------------
+
+#include "ole2int.h"
+#include <windows.h>
+#include <oleext.h>
+#include <stdio.h>
+
+#ifdef _CHICAGO_
+#include "svrapi.h" // NetAccessDel
+#endif
+#include "acpickl.h" //
+#include "cache.h" //
+#include "caccctrl.h" // Declaration of COAccessControl class factory
+
+// Global variables
+BOOL g_bInitialized = FALSE; // Module initialization flag
+IMalloc *g_pIMalloc; // Cache a pointer to the task allocator for
+
+CRITICAL_SECTION g_ServerLock;
+#ifdef _CHICAGO_
+DWORD g_dwProcessID; // Current process ID.
+UINT g_uiCodePage; // Code page to use for converting
+ // more efficient memory allocation.
+#endif
+ULONG g_ulHeaderSize; // Since the encoded size of the header
+ // is frequently used by the CImpAccessControl
+ // methods, I just make it a one time
+ // initialized global value.
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: InitializeAccessControl
+//
+// Summary: This function performs per-process initialization
+// The major bulk of module initialization
+// code has been moved to ComGetClassObject to avoid circular module
+// initialization dependency. Right now, the function will only
+// initialize a critical section
+//
+// Args:
+//
+// Modifies: CRITICAL_SECTIOn g_ServerLock - This CRITICAL_SECTION object is
+// used to prevent simultaneous
+// initialization of the module in
+// ComGetClassObj. g_cServerLock is
+// destroyed when the
+// UninitializeAccessControl is
+// called.
+//
+// Return: BOOL - This function should always S_OK.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+HRESULT InitializeAccessControl()
+{
+ InitializeCriticalSection(&g_ServerLock);
+
+ return S_OK;
+}
+
+/****************************************************************************
+
+ Function: UninitializeAccessControl
+
+ Summary: Cleans up this module.
+
+****************************************************************************/
+void UninitializeAccessControl()
+{
+ // If the module is unloaded after it is initialized,
+ // then make sure that the task memory allocator pointer
+ // is freed.
+ if(g_bInitialized)
+ {
+ g_pIMalloc->Release();
+ }
+ // The g_ServerLock CRITICAL_SECTION object should always
+ // be destroyed.
+ DeleteCriticalSection(&g_ServerLock);
+}
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: ComDllGetClassObject
+//
+// Summary: This function is called by COM to get the class factory of
+// COAccessControl object. Also within this function is a sequence
+// for initializing the module which is invoked the first time
+// ComDllGetClassObject is called. All threads that call this function
+// will be blocked by the g_ServerLock CRITICAL_SECTION object until
+// the first thread that arrives has completed the module initialization
+// sequence.
+//
+// Args: REFCLSID rclsid [in] - Class identifier of the object that the
+// caller wants to obtain a class factory for.
+// This function will only accept
+// CLSID_COAccessControl_DCOM.
+// REFIID riid [in] - The id of the interface that the client want
+// from the class factory.
+// PPVOID ppv [out] - The classs factory interface pointer returned
+// to the client.
+//
+// Modifies: g_ProcessID - The current processID of the Dll module. This
+// process ID is used by CImpAccessControl object to
+// compose filename.
+//
+// g_HeaderSize - Size of the STREAM_HEAEDER structure when it is
+// encoded into
+// Chicago only:
+// g_uiCodePage - The console code page that is currently in use.
+// This code page is used for translating Unicode
+// string to ANSI string on Chicago.
+//
+// Return: HRESULT - CLASS_E_CLASSNOTAVAILABLE: Class object required by the
+// caller was not supported by
+// this server.
+// supported by this server.
+// - ERROR_DLL_INIT_FAILED: The function failed to create
+// a message encoding handle and thus
+// abort the
+// - E_OUTOFMEMORY: Could not create new class factory object
+// because the system is out of memory.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+HRESULT ComDllGetClassObject
+(
+REFCLSID rclsid,
+REFIID riid,
+LPVOID *ppv
+)
+{
+ HRESULT hr = CLASS_E_CLASSNOTAVAILABLE; // Function return code
+ IUnknown *pCob = NULL; // IUnknown pointer to the newly
+ // created class factory object.
+
+ EnterCriticalSection(&g_ServerLock);
+ if(g_bInitialized == FALSE)
+ {
+
+#ifdef _CHICAGO_
+
+ ULONG ulStrLen; // Length of the Windows path
+ CHAR *pcszStrPtr; // This pointer is used to point
+ // to the end of the Windows path,
+ // so that the filename can be
+ // easily attached after the Windows
+ // path.
+ CHAR pcszPathName[MAX_PATH]; // This character array is for storing
+ // the full path name of the files
+ // to search for and the files to be
+ // deleted.
+ WIN32_FIND_DATAA FindFileData; // This structure contains information
+ // a file that is found by the FindFirstFile
+ // and the FindNextFile functions. Only the
+ // file name in the structure is used in the
+ // following segment of code.
+ HANDLE SearchHandle; // This handle is used for searching files
+ // with names that matches a certain pattern.
+ CHAR *pcszCompose;
+
+ // Clean up any temporary files left over
+ // from a previous instance of COAccessControl
+ // that was not shut down properly due to a system crash
+ g_dwProcessID = GetCurrentProcessId();
+
+ // Compose the pathname for searching
+ // Notice that the format of the filename is <Windows path>\<ProcessID>_<UUID>.tmp
+ ulStrLen = GetWindowsDirectoryA(pcszPathName, MAX_PATH);
+ pcszStrPtr = pcszPathName + ulStrLen;
+
+ // We are interested in files with process IDs prefix that matches
+ // the current process ID. Since the current segment of code will only be
+ // executed the first time a process is started up, the files with
+ // a prefix that matches the current processID found now must be
+ // be left over from a crashed COM IAccessCOntrol object.
+ pcszCompose = pcszStrPtr;
+ *(pcszCompose++) = '\\';
+ _ultoa( g_dwProcessID, pcszCompose, 16 );
+ pcszCompose += strlen( pcszCompose );
+ strcat( pcszCompose, "*.tmp" );
+
+ SearchHandle = FindFirstFileA(pcszPathName, &FindFileData);
+ if (SearchHandle != INVALID_HANDLE_VALUE)
+ {
+ // While we can still find files with a matching file name,
+ // we
+ do
+ {
+ strcpy( &pcszStrPtr[1], FindFileData.cFileName );
+ DeleteFileA(pcszPathName);
+ NetAccessDel(NULL, pcszPathName);
+ } while (FindNextFileA(SearchHandle, &FindFileData));
+
+ // Release the file search handle
+ FindClose(SearchHandle);
+ } // if
+
+ // Get the console code page for trustee name conversion
+ g_uiCodePage = GetConsoleCP();
+
+
+#endif
+ // Cache a pointer to the task memory allocator
+ // This pointer is used by the global functions LocalMemAlloc,
+ // LocalMemFree, midl_user_allocate, and midl_user_free.
+ CoGetMalloc(MEMCTX_TASK, &g_pIMalloc);
+
+
+ // The following segment of code is for computing the encoded size of
+ // StTREAM_HEADER structure.
+ RPC_STATUS status;
+ CHAR DummyBuffer[64];
+ ULONG ulEncodedSize;
+ STREAM_HEADER DummyHeader;
+ handle_t PickleHandle;
+ CHAR *pEncodingBuffer;
+
+ pEncodingBuffer = (CHAR *)(((ULONG)DummyBuffer + 8) & ~7);
+ if(status = (MesEncodeFixedBufferHandleCreate( pEncodingBuffer
+ , 56
+ , &ulEncodedSize
+ , &PickleHandle)) != RPC_S_OK )
+ {
+ ComDebOut((DEB_COMPOBJ, "MesEncodeFixedBufferHandelCreate failed with return code %x.\n", status));
+ LeaveCriticalSection(&g_ServerLock);
+ return E_FAIL;
+ }
+
+ STREAM_HEADER_Encode(PickleHandle, &DummyHeader);
+ g_ulHeaderSize = ulEncodedSize;
+ MesHandleFree(PickleHandle);
+
+ // Set server initialization flag
+ g_bInitialized = TRUE;
+
+ }
+ LeaveCriticalSection(&g_ServerLock);
+
+ // This DLL only support the COleDs_AccessControl object
+ if (IsEqualGUID(CLSID_DCOMAccessControl, rclsid))
+ {
+ hr = E_OUTOFMEMORY;
+ pCob = new CFAccessControl();
+ }
+
+ if (pCob != NULL)
+ {
+ hr = pCob->QueryInterface(riid, ppv);
+ if (FAILED(hr))
+ {
+ pCob->Release();
+ }
+
+ }
+ return hr;
+
+} // ComDllGetClassObject
+
+
diff --git a/private/ole32/com/accctrl/caccctrl.cxx b/private/ole32/com/accctrl/caccctrl.cxx
new file mode 100644
index 000000000..d51154113
--- /dev/null
+++ b/private/ole32/com/accctrl/caccctrl.cxx
@@ -0,0 +1,5905 @@
+//+---------------------------------------------------------------------------
+//
+// File: caccctrl.cxx
+//
+// Copyright (c) 1996-1996, Microsoft Corp. All rights reserved.
+//
+// Description: This file contains the method definitions of the DCOM
+// IAccessControl implementation classes
+//
+// Classes: COAccessControl - This is the implementation component of DCOM
+// IAccessControl. For aggregation support, the
+// COAccessControl component is implemented as a
+// nested class containing the CImpAccessControl
+// class. The COAccessControl object itself
+// contains a non-delegating implementation of
+// IUknown that exposed the IUnknown, IPersist,
+// IPersistStream, and the IAccessControl
+// interfaces.
+// CImpAccessControl - This is the class nested within the
+// COAccessControl component class. It
+// contains the implementation of IAccessControl
+// and IPersistStream and an implementation
+// of IUnknown that always delegates the call
+// to the controlling unknown.
+// CFAccessControl - The class factory for manufacturing COAccessControl
+// objects.
+//
+// CODEWORK:
+// Use PrivMemAllow everywhere.
+// Always check m_bInitialized before argument validation.
+//
+//+---------------------------------------------------------------------------
+#include "ole2int.h"
+#include <windows.h>
+#include <objbase.h>
+#include <stdio.h>
+
+#ifdef _CHICAGO_
+#include <svrapi.h> // 16-bit LAN Manager NetAccess API
+#endif
+
+#include "oleext.h" // IAccessControl interface definition
+#include "Cache.h" // Effective permissions cache
+#include "acpickl.h" // Pickling support
+#include "caccctrl.h" // COAccessControl, CImpAccessControl and CFAccessControl
+ // class declarations.
+
+// External variables
+#include "acext.h"
+
+#ifndef _CHICAGO_
+GENERIC_MAPPING gDummyMapping = {0,0,0,0};
+PRIVILEGE_SET gDummyPrivilege = {1,0};
+SID gEveryone = {1,1,SECURITY_WORLD_SID_AUTHORITY,
+ SECURITY_WORLD_RID};
+SID gSystem = {1,1,SECURITY_NT_AUTHORITY,
+ SECURITY_LOCAL_SYSTEM_RID};
+#else
+const SHORT EXTRA_ACES = 5;
+#endif
+
+// Internal function prototypes, please see the function headers for details
+void AddACEToStreamACL (STREAM_ACE *, PCB *);
+void CleanAllMemoryResources (ACL_DESCRIPTOR *, PCB *);
+void CleanUpStreamACL (STREAM_ACL *pStreamACL);
+HRESULT EnlargeStreamACL (PCB *, ULONG);
+void FreePicklingBuff (PCB *);
+BOOL IsValidAccessMask (DWORD);
+void *LocalMemAlloc (ULONG);
+void LocalMemFree (void *);
+HRESULT MapStreamACLToAccessList (PCB *, PACTRL_ACCESSW *);
+HRESULT ResizePicklingBuff (PCB *, ULONG);
+HRESULT ValidateTrusteeString (LPWSTR);
+HRESULT ValidateTrustee (PTRUSTEE_W);
+HRESULT ValidateAccessCheckClient (PTRUSTEE_W);
+HRESULT ValidateAndTransformAccReqList(PACTRL_ACCESSW ,STREAM_ACE **, void **, ULONG *, ULONG *, ULONG *);
+
+#ifdef _CHICAGO_
+void AddACEToACLImage (access_list_2 *, ULONG, ACL_DESCRIPTOR *);
+HRESULT AllocACLImage (ACL_IMAGE *, SHORT);
+void CleanFileResource (ACL_IMAGE *);
+void CleanUpACLImage (ACL_IMAGE *);
+HRESULT ComputeEffectiveAccess (LPWSTR,DWORD *, ACL_DESCRIPTOR *);
+void DeleteACEFromACLImage (CHAR *, ACL_IMAGE *);
+BOOL DeleteACEFromStreamACL (PTRUSTEE_W, ULONG, PCB *);
+HRESULT EnsureACLImage (ACL_IMAGE *, ULONG);
+HRESULT GenerateFile (LPTSTR *);
+HRESULT MapStreamACLToChicagoACL (STREAM_ACE *, ACL_IMAGE *, SHORT);
+HRESULT ReadACLFromStream (IStream *, PCB *);
+SHORT StandardMaskToLANManagerMask (DWORD *, USHORT *);
+HRESULT ValidateAndFixStreamACL (STREAM_ACL *);
+HRESULT WStringToMBString (LPWSTR, CHAR **);
+#else
+HRESULT ComputeEffectiveAccess (ACL_DESCRIPTOR *, STREAM_ACL *, HANDLE, DWORD *);
+BOOL DeleteACEFromStreamACL (PTRUSTEE_W, ULONG, ACL_DESCRIPTOR *, PCB *);
+HRESULT GetSIDFromName (PSID *, LPWSTR, TRUSTEE_TYPE *);
+HRESULT GetNameFromSID (LPWSTR *, PSID, TRUSTEE_TYPE *);
+HRESULT InitSecDescInACLDesc (ACL_DESCRIPTOR *);
+void NTMaskToStandardMask (ACCESS_MASK *, DWORD *);
+HRESULT PutStreamACLIntoSecDesc (STREAM_ACL *, ACL_DESCRIPTOR *);
+HRESULT ReadACLFromStream (IStream *, PCB *, ACL_DESCRIPTOR *);
+void StandardMaskToNTMask (DWORD *, ACCESS_MASK *);
+HRESULT ValidateAndFixStreamACL (STREAM_ACL *, ULONG *, ULONG *);
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// CFAccessControl methods (Class Factory)
+//////////////////////////////////////////////////////////////////////////////
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CFAccessControl::CFAccessControl , public
+//
+// Summary: Contructor of CFAccessControl. This function initializes the
+// object's reference count to zero.
+//
+// Args: void
+//
+// Modifies: m_cRefs.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+CFAccessControl::CFAccessControl(void)
+{
+ m_cRefs = 0;
+} // CFAccessControl::CFAccessControl
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CFAccessControl::~CFAccessControl , public
+//
+// Summary: Destructor for CFAccessControl. This function does nothing at the
+// moment.
+//
+// Args: void
+//
+// Modifies:
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+CFAccessControl::~CFAccessControl(void)
+{
+ return;
+} // CFAccessControl::~CFAccessControl
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CFAccessControl::QueryInterface() , public
+//
+// Summary: This function queries the CFAccessControl object itself
+// for an interface pointer and returns it to the caller.
+// Note that *ppv will be set to NULL if the fucntion fails
+// to retrieve an interface pointer for the caller.
+//
+// Args: [in] REFIID riid - Reference to the identifier of the interface
+// that the client wants.
+// [out] void **ppv - Address of the interface pointer returned by
+// this function. The space for storing the returned
+// pointer should be allocated by the caller.
+//
+// Modifies: m_cRefs - The object's reference count will be incremented
+// if the function can provide the requested interface
+// pointer.
+//
+// Return: HRESULT - S_OK: Succeeded
+// - E_NOINTERFACE: The requested interface is not supported
+// by the .
+// - E_INVALIDARG: ppv was NULL
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+CFAccessControl::QueryInterface
+(
+REFIID riid,
+void **ppv
+)
+{
+
+ // Checks for really foolish mistake made by the
+ // client like passing in a NULLpointer as the
+ // address of the returned interface pointer.
+ if (ppv == NULL)
+ {
+ return E_INVALIDARG;
+ } // if
+
+ // The CFAccessControl object only supports the
+ // IUnknown interface and the IClassFactory interface.
+ if (IsEqualGUID(riid, IID_IUnknown) ||
+ IsEqualGUID(riid, IID_IClassFactory ))
+ {
+ // Since CFAccessControl doesn't inherit from multiple
+ // virtual classes, no type casting on the returned
+ // interface pointer is required.
+ *ppv = this;
+ // Obeys the COM reference counting rule by calling AddRef
+ // on the output pointer.
+ ((IUnknown *)(*ppv))->AddRef();
+ return S_OK;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ } // if
+
+} // CFAccessControl::QueryInterface
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CFAccessControl::AddRef(), public
+//
+// Summary: This function increments the CFAccessControl object
+// reference count by one. All modifications of the object's reference
+// count must be made thread-safe by using the InterlockedIncrement
+// and the InterlockedDecrement functions.
+//
+// Args: void
+//
+// Modifies: m_cRefs.
+//
+// Return: ULONG
+// New reference count of the object. This number may not be accurate in a
+// multi-threaded environment.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(ULONG)
+CFAccessControl::AddRef
+(
+void
+)
+{
+ ULONG cRefs = m_cRefs + 1;
+ InterlockedIncrement(&m_cRefs);
+ return cRefs;
+
+} // CFAccessControl::AddRef
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CFAccessControl::Release(), public
+//
+// Summary: This function decrements the CFAccessControl object reference
+// count and deletes the object when the reference count drops to
+// zero. After the deletion of the object, this function will
+// also decrement the object count of the server. Modification
+// of object reference count and object count must be made
+// thread-safe by using the InterlockedIncrement or InterlockedDecrement
+// functions
+//
+// Args: void
+//
+// Modifies: m_cRefs.
+//
+// Return: ULONG
+// New reference count of the object. This number may not be accurate
+// in a multi-threaded environment.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(ULONG)
+CFAccessControl::Release
+(
+void
+)
+{
+ ULONG cRefs = m_cRefs - 1;
+ if(InterlockedDecrement(&m_cRefs) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ else
+ {
+ return cRefs;
+ }
+
+} // CFAccessControl::Release
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CFAccessControl::CreateInstance(), public
+//
+// Summary: This function creates an instance of the CAccesControl object
+// and returns a requested interface pointer to the object. If the
+// caller of this method intends to aggregate with the COAccessControl
+// component, it will pass it's IUnknown pointer to this method which
+// will in turn be passed into the COAccessControl contructor.
+// Owing to the fact that the COAccessControl object supports
+// aggregation, and COM rules dictate that a client must only ask for
+// the IUnknown interface at creation of an aggregatable object,
+// the caller must pass in IID_IUnknown as the riid parameter,
+// otherwise this call will fail and return E_INVALIDARG.
+//
+// Args: IUnknown *pUnkOuter [in] - IUnknown pointer to the controlling object which
+// can be NULL if the COAccessControl object is not
+// created as part of an aggregate.
+// REFIID riid [in] - Reference to the identifier of the interface that
+// the client has requested.
+// void **ppv [out] - Reference to the interface pointer to be returned to
+// the caller.
+//
+// Return: HRESULT -S_OK: Succeeded.
+// E_INVALIDARG: ppv is NULL, or the client ask for an interface
+// other than IUnknown
+// E_OUTOFMEMORY: Not enough memory to create new object.
+// E_NOINTERFACE: The interface requested by the client
+// was not supported by the COM IAccessControl
+// object.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+
+STDMETHODIMP_(HRESULT)
+CFAccessControl::CreateInstance
+(
+IUnknown *pUnkOuter,
+REFIID riid,
+void **ppv
+)
+{
+ HRESULT hr;
+ COAccessControl *pAccessControl = NULL;
+
+ if(ppv == NULL)
+ {
+ return E_INVALIDARG;
+ } // if
+
+ *ppv = NULL;
+
+ // Since COAccessControl is designed to support
+ // aggregation, the client has to ask for
+ // the IUnknown pointer the first time the
+ // COAccessControl object is created as part
+ // of an aggregate.
+ if(!IsEqualGUID(IID_IUnknown, riid) && pUnkOuter != NULL)
+ {
+ return E_INVALIDARG;
+ } // if
+
+ pAccessControl = new COAccessControl;
+ if(!pAccessControl)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ {
+ if(FAILED(hr = pAccessControl->Init(pUnkOuter)))
+ {
+ delete pAccessControl;
+ return hr;
+ } // if
+ } // if
+
+ if(FAILED(hr = pAccessControl->QueryInterface(riid, ppv)))
+ {
+ delete pAccessControl;
+ }
+
+ return hr;
+} // CFAccessControl::CreateInstance
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CFAccessControl::LockServer() , public
+//
+// Summary: This function either increases of decreases the server lock count.
+//
+// Args: BOOL fLock [in] - This flag tells the function whether to increment or
+// decrement the server lock count.
+// TRUE - Increment the server lock count.
+// FALSE - Decrement the server lock count.
+// The server can be unloaded if the server lock count
+// and the object count are both zero.
+//
+// Return: S_OK: This function cannot fail.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+
+STDMETHODIMP_(HRESULT)
+CFAccessControl::LockServer
+(
+BOOL fLock
+)
+{
+ return S_OK;
+} // CFAccessControl::LockServer
+
+//////////////////////////////////////////////////////////////////////////////
+// COAccessControl methods
+//////////////////////////////////////////////////////////////////////////////
+
+// Constructor, destructor
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::COAccessControl(), public
+//
+// Summary: Object constructor. This function sets the object's reference count
+// to zero.
+//
+// Args: void
+//
+// Modifies: m_cRefs
+//
+// Return: void
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+COAccessControl::COAccessControl
+(
+void
+)
+{
+ // Set object reference count to zero
+ m_cRefs = 0;
+ m_ImpObj = NULL;
+ return;
+
+} // COAccessControl::COAccessControl
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::Init(), public
+//
+// Summary: COAccessControl initialization method. Notice that this function
+// initialize the COAccessControl object in a sense different from
+// that of COAccessControl::Load. COAccessControl::Load initializes
+// COAccessControl
+//
+// Args: IUnknown pUnkOuter - Pointer to the controlling object. This pointer
+// can be NULL if the COAccessControl object
+// is not part of an aggregate.
+//
+// Modifies: m_ImpObj
+//
+// Return: void
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::Init
+(
+IUnknown *pUnkOuter
+)
+{
+
+ // Initialize inner object
+ m_ImpObj = new CImpAccessControl(this, pUnkOuter);
+ if(m_ImpObj == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+ else
+ {
+ return m_ImpObj->Load( NULL );
+ }
+
+} // COAccessControl::Init
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::~COAccessControl(), public
+//
+// Summary: Object destructor. This function does nothing at the moment.
+//
+// Args: void
+//
+// Return: void
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+COAccessControl::~COAccessControl
+(
+void
+)
+{
+ // Destroy inner object
+ delete m_ImpObj;
+ return;
+} // COAccessControl::~COAccessControl
+
+// IUnknown methods
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::QueryInterface() , public
+//
+// Summary: This function queries the COAccessControl object for an
+// interface pointer for the caller.
+//
+// Args: [in] REFIID riid - Reference to the identifier of the interface
+// that the client wants.
+// [out] void **ppv - Interface pointer returned.
+//
+// Modifies: m_cRefs.
+//
+// Return: HRESULT - S_OK: Succeeded.
+// - E_NOINTERFACE: The requested interface is not supported.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+
+STDMETHODIMP_(HRESULT)
+COAccessControl::QueryInterface
+(
+REFIID riid,
+void **ppv
+)
+{
+
+ HRESULT hr = E_NOINTERFACE;
+
+ // Since the CImpAccessControl class inherits from multiple
+ // virtual classes, it is important that the interface pointer
+ // returned is type cast properly.
+ if (IsEqualGUID(riid, IID_IUnknown))
+ {
+ *ppv = (IUnknown *)this;
+ }
+ else if (IsEqualGUID(riid, IID_IPersist))
+ {
+ *ppv = (IPersist *)m_ImpObj;
+ }
+ else if (IsEqualGUID(riid, IID_IPersistStream))
+ {
+ *ppv = (IPersistStream *)m_ImpObj;
+ }
+ else if (IsEqualGUID(riid, IID_IAccessControl))
+ {
+ *ppv = (IAccessControl *)m_ImpObj;
+ }
+ else
+ {
+ *ppv = NULL;
+ }
+
+ if(*ppv != NULL)
+ {
+
+ // Obey COM reference counting rules, call
+ // AddRef on the interface pointer returned.
+ ((IUnknown *)(*ppv))->AddRef();
+ hr = S_OK;
+ }
+ return hr;
+
+} // COAccessControl::QueryInterface
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::AddRef(), public
+//
+// Summary: Increments the COAccessControl object reference count.
+//
+// Args: void
+//
+// Modifies: m_cRefs.
+//
+// Return: ULONG
+// New reference count of the object.
+//
+// Remark: The modification of m_cRefs is made thread-safe by using the
+// InterlockedIncrement function.
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(ULONG)
+COAccessControl::AddRef
+(
+void
+)
+{
+ ULONG cRefs = m_cRefs + 1;
+ InterlockedIncrement(&m_cRefs);
+ return cRefs;
+} // COAccessControl::AddRef
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::Release(), public
+//
+// Summary: Decrements the COAccessControl object reference count and deletes
+// the object when the reference drops to zero. After the object itself
+// is destroyed, this function will also decrement the server's object
+// count. Modification of object's reference count and the server's
+// object count must be made thread-safe by using the
+// InterlockedIncrement and the InterlockedDecrement functions.
+//
+// Args: void
+//
+// Modifies: m_cRefs.
+//
+// Return: ULONG
+// New reference count of the object. This number may not be accurate
+// in a multithreaded environment.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(ULONG)
+COAccessControl::Release
+(
+void
+)
+{
+ ULONG cRefs = m_cRefs - 1;
+ if(InterlockedDecrement(&m_cRefs) == 0)
+ {
+ // self-destruct
+ delete this;
+ return 0;
+ }
+ else
+ {
+ return cRefs;
+ }
+
+} // COAccessControl::Release
+
+//////////////////////////////////////////////////////////////////////////////
+// CImpAccessControl
+//////////////////////////////////////////////////////////////////////////////
+
+// Constructor, destructor
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::CImpAccessControl, public
+//
+// Summary: Object contructor. This function is responsible for initializing
+// the initialization flag and the dirty flag to false, setting
+// the object's two major structures, the ACL descriptor and the
+// pickling control block, to NULL, and initializing the object's
+// outer unknown pointer to point to the appropriate object depending
+// on whether the COAccessControl object is part of an aggregate.
+//
+// Args: IUnknown *pBackPtr [in] - IUnknown pointer to the outer object ie.
+// the COAccessControl control that contains
+// the current CImpAccessControl object.
+// IUnknown *pUnkOuter [in] - IUnknown pointer to the controlling unknown
+// which is NULL if the COAccessControl object
+// is not part of an aggregation.
+//
+// Modifies: m_bDirty, m_bInitialized, m_pUnkOuter, m_ACLDesc, m_pcb
+//
+// Return: void
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+
+COAccessControl::CImpAccessControl::CImpAccessControl
+(
+IUnknown *pBackPtr,
+IUnknown *pUnkOuter
+)
+{
+ m_pUnkOuter = (pUnkOuter == NULL) ? pBackPtr : pUnkOuter;
+ m_bInitialized = FALSE;
+ m_bDirty = FALSE;
+ // Initialize the structures within the object...
+ memset(&m_ACLDesc, 0, sizeof(ACL_DESCRIPTOR));
+ memset(&m_pcb, 0, sizeof(PCB));
+
+ InitializeCriticalSection(&m_ACLLock);
+ return;
+} // COAccessControl::CImpAccessControl::CImpAccessControl
+
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::~CImpAccessControl(), public
+//
+// Summary: Object destructor. This function releases all the memory allocated
+// for an initialized CImpAccessControl object and destroys the
+// critical section object for guarding the internal from concurrent
+// access.
+//
+// Args: void
+//
+// Modifies: m_ACLDesc, m_pcb.
+//
+// Return: void
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+COAccessControl::CImpAccessControl::~CImpAccessControl
+(
+void
+)
+{
+ if(m_bInitialized)
+ {
+#ifdef _CHICAGO_
+ CleanFileResource(&(m_ACLDesc.DenyACL));
+ CleanFileResource(&(m_ACLDesc.GrantACL));
+#endif
+ CleanAllMemoryResources(&m_ACLDesc, &m_pcb);
+ } // if
+ DeleteCriticalSection(&m_ACLLock);
+} //COAccessControl::CImpAccessControl:~CImpAccessControl
+
+// IUnknown methods
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::QueryInterface(), public
+//
+// Summary: This function simply delegates the QueryInterface call to the
+// outer unknown's QueryInterface method.
+//
+// Args: REFIID riif [in] - Reference to the interface identifier that signifies
+// the interface that the client wanted.
+//
+//
+// Return: HRESULT - See outer unknown implementation for details.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::QueryInterface
+(
+REFIID riid,
+void **ppv
+)
+{
+ return m_pUnkOuter->QueryInterface(riid, ppv);
+} // COAccessControl:CImpAccessControl::QueryInterface
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::AddRef(), public
+//
+// Summary: This function simply delegates the AddRef call to the outer unknown's
+// AddRef method.
+//
+// Args: void
+//
+// Modifies: Outer unknown reference count.
+//
+// Return: HRESULT - See outer unknown implementation for details
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(ULONG)
+COAccessControl::CImpAccessControl::AddRef
+(
+void
+)
+{
+ // AddRef of the outer object must be thread-safe
+ return m_pUnkOuter->AddRef();
+} // COAccessControl::CImpAccessControl::AddRef
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::Release(), public
+//
+// Summary: This function simply delegates the Release call to the outer unknown's
+// Release method.
+//
+// Args: void
+//
+// Modifies: Outer unknown reference count
+//
+// Return: ULONG - See outer unknown implementation for details.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(ULONG)
+COAccessControl::CImpAccessControl::Release
+(
+void
+)
+{
+ // Release of the outer object must be thread safe
+ return m_pUnkOuter->Release();
+} // COAccessControl::CImpAccessControl::Release
+
+// IPersist method
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::GetClassID(), public
+//
+// Summary: This function returns the class id of the COAccessControl component.
+// pClassID must be pointing to a valid memory block big enough to
+// hold the returned class ID.
+//
+// Args: CLSID *pCLSID [out] - Pointer to the returned CLSID.
+//
+// Modifies: Nothing
+//
+// Return: HRESULT - E_INVALIDARG: pClassID == NULL.
+// S_OK: Succeeded.
+// CO_E_ACNOTINITIALIZED: This method was called before
+// the DCOM IAccessControl object
+// was initialized by the Load method.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::GetClassID
+(
+CLSID *pClassID
+)
+{
+ if (pClassID == NULL)
+ {
+ return E_INVALIDARG;
+ } // if
+ *pClassID = CLSID_DCOMAccessControl;
+ return S_OK;
+} // COAccessControl::CImpAccessControl::GetClassID
+
+// IPersistStream methods
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::IsDirty(), public
+//
+// Summary: This function returns TRUE if the object has been modified since
+// the last time it was saved and FALSE otherwise.
+//
+// Args: void.
+//
+// Return: HRESULT - S_OK: The object has changed since the last save.
+// S_FALSE: The object has not changed since the last save.
+// CO_E_ACNOTINITIALIZED: This method was called before
+// the DCOM IAccessControl object
+// was initialized by the Load method.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::IsDirty
+(
+void
+)
+{
+ if(!m_bInitialized)
+ return CO_E_ACNOTINITIALIZED;
+
+ return (m_bDirty? S_OK:S_FALSE);
+} // COAccessControl::CimpAccessControl::IsDirty
+
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::Load(), public
+//
+// Summary: This function is the initialization method of CImpAccessControl
+// and it must be called before any non-IUnknown methods.
+//
+// Args: IStream *pStm [in] - Interface pointer to a stream object from which
+// access control data is loaded into the object.
+// The seek pointer of the stream should be at the
+// beginning of the stream header.
+// If pStm is NULL, this function will initialize
+// an empty DCOM IAccessControl object.
+//
+// Modifies: m_ACLDesc, m_pcb
+//
+// Return: HRESULT - S_OK: Succeeded.
+// E_INVALIDARG: This method will return E_INVALIDARG if
+// either
+// a) the ACL in the stream provided by the
+// user contains an invalid access mask, or
+// b) one of STREAM_ACE structure in the ACL
+// provided by the user contains a null
+// pTrusteeName pointer.
+// E_OUTOFMEMORY: The system ran out of memory for some
+// crucial operation.
+// CO_E_FAILEDTOGETWINDIR: (Windows 95 only)Unable to obtain
+// the Windows directory.
+// CO_E_PATHTOOLONG: (Windows 95 only)The path generated by
+// the GenerateFile function was longer
+// than the system's limit.
+// CO_E_FAILEDTOGENUUID: (Windows 95 only)Unable to generate
+// a uuid using the UuidCreate funciton.
+// CO_E_FAILEDTOCREATEFILE: (Windows 95 only)Unable to create
+// a dummy file.
+// CO_E_FAILEDTOCLOSEHANDLE: Unable to close a serialization
+// handle.
+// CO_E_SETSERLHNDLFAILED: Unable to (re)set a serialization
+// handle.
+// CO_E_EXCEEDSYSACLLIMIT: The number of ACEs in the ACL
+// provided by the user exceeded the
+// limit imposed by the system that
+// is loading the ACL. On Windows 95,
+// the system can handle 32767
+// ACTRL_ACCESS_DENIED ACEs and 32767
+// ACTRL_ACCESS_ALLOWED ACEs. On Windows NT,
+// the system can only handle 32767
+// ACTRL_ACCESS_DENIED and ACTRL_ACCESS_ALLOWED ACEs
+// combined.
+// CO_E_ACESINWRONGORDER: Not all ACTRL_ACCESS_DENIED ACEs in the ACL
+// provided by the user were arranged
+// in front of the ACTRL_ACCESS_ALLOWED ACEs.
+// CO_E_WRONGTRUSTEENAMESYNTAX: The ACL provided by the user
+// contained a trustee name
+// string that didn't conform
+// to the <Domain>\<Account>
+// syntax.
+// CO_E_INVALIDSID: (Windows NT only)The ACL provided by the
+// user contained an invalid security
+// identifier.
+// CO_E_LOOKUPACCNAMEFAILED: (Window NT only) The system call,
+// LookupAccountName, failed. The
+// user can call GetLastError to
+// obtain extended error information.
+// CO_E_NOMATCHINGSIDFOUND: (Windows NT only) At least one of
+// the trustee name in the ACL provided
+// by the user had no corresponding
+// security identifier.
+// CO_E_CONVERSIONFAILED: (Windows 95 only) WideCharToMultiByte
+// failed.
+//
+// CO_E_FAILEDTOOPENPROCESSTOKEN: (Windows NT only)The system
+// call, OpenProcessToken,
+// failed. The user can get
+// extended information by
+// calling GetLastError.
+// CO_E_FAILEDTOGETTOKENINFO: (Windows Nt only)The system call,
+// GetTokenInformation, failed.
+// The user can call GetLastError to
+// get extended error information.
+// CO_E_DECODEFAILED: Unable to decode the ACL in the
+// IStream object.
+// CO_E_INCOMPATIBLESTREAMVERSION: The version code in the
+// stream header was not
+// supported by this version
+// of IAccessControl.
+// Error codes from IStream::Read - See the Win32 SDK
+// documentation for detail descriptions of the following
+// error codes.
+// STG_E_ACCESSDENIED:
+// STG_E_INVALIDPOINTER:
+// STG_E_REVERTED:
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::Load
+(
+IStream *pStm
+)
+{
+
+ HRESULT hr; // Function return code
+ ACL_DESCRIPTOR ACLDescBackup; // Backup of the original ACL descriptor in the object
+ PCB PCBBackup; // Backup of the original PCB in the object.
+#ifdef _CHICAGO_
+ SHORT sNumOfDenyEntries = 0; // Number of deny entries in the stream
+ SHORT sNumOfGrantEntries = 0; // Number of grant entries in the stream
+ CHAR *pszDenyFilename; // Name of the deny ACL dummy file
+ CHAR *pszGrantFilename; // Name of the grant ACL dummy file
+#endif
+
+ // There are too much things happening in this
+ // function so I'll simply lock the whole thing
+ EnterCriticalSection(&m_ACLLock);
+
+ // Take a snapshot of the old ACL so that if anything goes wrong, I can restore to the
+ // old configuration
+ memcpy(&PCBBackup, &m_pcb, sizeof(PCB));
+ memcpy(&ACLDescBackup,&m_ACLDesc,sizeof(ACL_DESCRIPTOR));
+
+ // Set the original ACL descritpor and the PCB to NULL just to be save
+ memset(&m_ACLDesc, 0, sizeof(ACL_DESCRIPTOR));
+ memset(&m_pcb, 0, sizeof(PCB));
+
+#ifdef _CHICAGO_
+ // Generate new dummy files if this is the first time the object
+ // is initialized, reuse the old ones otherwise
+ if (m_bInitialized)
+ {
+ pszDenyFilename = ACLDescBackup.DenyACL.pACL->acc1_resource_name;
+ pszGrantFilename = ACLDescBackup.GrantACL.pACL->acc1_resource_name;
+ } // if
+ else
+ {
+ if (FAILED(hr = GenerateFile(&pszDenyFilename)))
+ {
+ goto Error;
+ } // if
+
+ if (FAILED(hr = GenerateFile(&pszGrantFilename)))
+ {
+ goto Error;
+ } // if
+ } // if
+#endif
+
+ if (pStm != NULL)
+ {
+
+ // Read the ACL in the stream into the pickle control block
+#ifdef _CHICAGO_
+ if(FAILED(hr = ReadACLFromStream(pStm, &m_pcb)))
+#else
+ if(FAILED(hr = ReadACLFromStream(pStm, &m_pcb, &m_ACLDesc)))
+#endif
+ {
+#ifndef _CHICAGO_
+ if(hr != CO_E_NOMATCHINGSIDFOUND && hr != CO_E_LOOKUPACCNAMEFAILED)
+ {
+#endif
+ goto Error;
+#ifndef _CHICAGO_
+ } // if
+#endif
+ }
+
+ }
+ else
+ {
+
+ if (FAILED(hr = EnlargeStreamACL(&m_pcb, 10)))
+ {
+ goto Error;
+ }
+ m_pcb.ulBytesUsed = sizeof(STREAM_ACL)
+ + sizeof(STREAM_ACE)
+ + 256;
+ m_pcb.bPickled = FALSE;
+ if (FAILED(hr = ResizePicklingBuff(&m_pcb, m_pcb.ulBytesUsed + 800)))
+ {
+ goto Error;
+ }
+
+
+ } // if (pStm != NULL)
+ m_pcb.ulNumOfStreamACEs = m_pcb.StreamACL.ulNumOfDenyEntries
+ + m_pcb.StreamACL.ulNumOfGrantEntries;
+
+#ifdef _CHICAGO_
+ // Allocate memory for the two ACL images
+ // NT ACL that contains more than 32767 may be too large to fit
+ // into the LAN Manager ACL
+ sNumOfDenyEntries = (SHORT)(m_pcb.StreamACL.ulNumOfDenyEntries);
+ hr = AllocACLImage(&(m_ACLDesc.DenyACL), sNumOfDenyEntries + EXTRA_ACES);
+ if (FAILED(hr))
+ {
+ goto Error;
+ } // if
+ m_ACLDesc.DenyACL.pACL->acc1_count = sNumOfDenyEntries;
+ m_ACLDesc.DenyACL.pACL->acc1_resource_name = pszDenyFilename;
+
+ // NT ACL that contains more than 32767 may be too large to fit
+ // into the LAN Manager ACL
+ sNumOfGrantEntries = (SHORT)(m_pcb.StreamACL.ulNumOfGrantEntries);
+ hr = AllocACLImage(&(m_ACLDesc.GrantACL), sNumOfGrantEntries + EXTRA_ACES);
+ if (FAILED(hr))
+ {
+ goto Error;
+ } // if
+ m_ACLDesc.GrantACL.pACL->acc1_count = sNumOfGrantEntries;
+ m_ACLDesc.GrantACL.pACL->acc1_resource_name = pszGrantFilename;
+
+
+ // Map Stream ACL to Chicago ACL
+ if(FAILED(hr = MapStreamACLToChicagoACL( m_pcb.StreamACL.pACL
+ , &(m_ACLDesc.DenyACL)
+ , sNumOfDenyEntries)))
+ {
+ goto Error;
+ } // if
+
+ if(FAILED(hr = MapStreamACLToChicagoACL( m_pcb.StreamACL.pACL
+ + sNumOfDenyEntries
+ , &(m_ACLDesc.GrantACL)
+ , sNumOfGrantEntries)))
+ {
+ goto Error;
+ } // if
+
+ m_ACLDesc.DenyACL.bDirtyACL = TRUE;
+ m_ACLDesc.GrantACL.bDirtyACL = TRUE;
+
+#else
+
+ if(FAILED(hr = InitSecDescInACLDesc(&m_ACLDesc)))
+ {
+ goto Error;
+ } // if
+
+#endif
+ // Create a new pickling handle for the new ACL
+ if (MesEncodeFixedBufferHandleCreate( m_pcb.pPicklingBuff
+ , m_pcb.ulPicklingBuffSize
+ , &(m_pcb.ulBytesUsed)
+ , &(m_pcb.PickleHandle)) != RPC_S_OK)
+ {
+ hr = CO_E_SETSERLHNDLFAILED;
+ goto Error;
+ } // if
+
+ m_pcb.bDirtyHandle = FALSE;
+
+ if(m_bInitialized)
+ {
+ CleanAllMemoryResources(&ACLDescBackup, &PCBBackup);
+#ifdef _CHICAGO_
+ m_Cache.FlushCache();
+#else
+ m_CacheString.FlushCache();
+ m_CacheSID.FlushCache();
+#endif
+ }
+ else
+ {
+ m_bInitialized = TRUE;
+ } // if
+ // Set dirty flag to false
+ m_bDirty = FALSE;
+
+ LeaveCriticalSection(&m_ACLLock);
+ return S_OK;
+
+// Error handling code
+Error:
+#ifdef _CHICAGO_
+
+ // Cleanup the ACL images
+ if (m_ACLDesc.GrantACL.pACL != NULL)
+ {
+ CleanUpACLImage(&(m_ACLDesc.GrantACL));
+ }
+
+ if (m_ACLDesc.DenyACL.pACL != NULL)
+ {
+ CleanUpACLImage(&(m_ACLDesc.DenyACL));
+ }
+
+ // Destroy all the generated files if the
+ // object has been initialized before
+ if (!m_bInitialized)
+ {
+ if (pszGrantFilename != NULL)
+ {
+ DeleteFileA(pszGrantFilename);
+ LocalMemFree(pszGrantFilename);
+ } // if
+
+ if (pszDenyFilename != NULL)
+ {
+ DeleteFileA(pszDenyFilename);
+ LocalMemFree(pszDenyFilename);
+ } // if
+ } // if
+#endif
+
+ // Cleanup the stream ACL
+ if(m_pcb.StreamACL.pACL != NULL)
+ {
+ CleanUpStreamACL(&(m_pcb.StreamACL));
+ }// if
+
+ // Release the decoding handle
+ if (m_pcb.PickleHandle != NULL)
+ {
+ MesHandleFree(m_pcb.PickleHandle);
+ } // if
+
+ // Release the pickling buffer
+ if (m_pcb.pPicklingBuff != NULL)
+ {
+ FreePicklingBuff(&m_pcb);
+ } // if
+
+ // Restore the old ACL
+ memcpy(&m_pcb, &PCBBackup, sizeof(PCB));
+ memcpy(&m_ACLDesc, &ACLDescBackup, sizeof(ACL_DESCRIPTOR));
+ LeaveCriticalSection(&m_ACLLock);
+ return hr;
+
+} // COAccessControl::CImpAccessControl::Load
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::Save(), public
+//
+// Summary: This function saves the object's ACL to a user provided stream.
+//
+// Args: IStream *pStm [in,out] - Pointer to a user provided stream object.
+// BOOL fClearDirty [in] - Flag indicating whether the object should clear
+// its dirty flag after the save.
+//
+// Modifies: m_bDirty
+//
+// Return: HRESULT - S_OK: Succeeded.
+// CO_E_ACNOTINITIALIZED: This method was called before
+// the DCOM IAccessControl object
+// was initialized by the Load method.
+// E_INVALIDARG: pStm was NULL.
+// CO_E_SETSERLHNDLFAILED - Failed to (re)set serializtion
+// handle.
+// Error codes that can be returned by the write operation.
+// See Win32 SDK help for details
+// STG_E_MEDIUMFULL
+// STG_E_ACCESSDENIED
+// STG_E_CANTSAVE
+// STG_E_INVALIDPOINTER
+// STG_E_REVERTED
+// STG_E_WRITEFAULT
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::Save
+(
+IStream *pStm,
+BOOL fClearDirty
+)
+{
+ HRESULT hr = S_OK;
+ handle_t HeaderHandle;
+ CHAR HeaderBuffer[64];
+ CHAR *pHeaderBuffPtr;
+ STREAM_HEADER StreamHeader;
+ LARGE_INTEGER liOffset;
+ ULONG ulEncodedSize;
+
+ if(!m_bInitialized)
+ return CO_E_ACNOTINITIALIZED;
+
+ if (pStm == NULL)
+ {
+ return E_INVALIDARG;
+ } // if
+
+ // Other threads shouldn't mess with the object
+ // when the object is saving its state
+
+ EnterCriticalSection(&m_ACLLock);
+
+ if (m_pcb.bDirtyHandle)
+ {
+
+ if (MesBufferHandleReset( m_pcb.PickleHandle
+ , MES_FIXED_BUFFER_HANDLE
+ , MES_ENCODE
+ , &(m_pcb.pPicklingBuff)
+ , m_pcb.ulPicklingBuffSize
+ , &(m_pcb.ulBytesUsed)) != RPC_S_OK)
+
+ {
+ hr = CO_E_SETSERLHNDLFAILED;
+ goto Error;
+ } // if
+
+ m_pcb.bDirtyHandle = FALSE;
+
+ } // if
+
+ if (!(m_pcb.bPickled))
+ {
+ // Encode the STREAM_ACL structure into the pickling buffer
+ STREAM_ACL_Encode(m_pcb.PickleHandle, &(m_pcb.StreamACL));
+ m_pcb.bPickled = TRUE;
+ m_pcb.bDirtyHandle = TRUE;
+ } // if
+
+ pHeaderBuffPtr = (CHAR *)(((ULONG)HeaderBuffer + 8) & ~7);
+
+ // Create encoding handle
+ if (MesEncodeFixedBufferHandleCreate( pHeaderBuffPtr
+ , 56
+ , &ulEncodedSize
+ , &HeaderHandle ) != RPC_S_OK)
+ {
+ hr = CO_E_SETSERLHNDLFAILED;
+ goto Error;
+ } // if
+
+
+ StreamHeader.ulStreamVersion = STREAM_VERSION;
+ StreamHeader.ulPickledSize = m_pcb.ulBytesUsed;
+
+ STREAM_HEADER_Encode(HeaderHandle, &StreamHeader);
+
+ MesHandleFree(HeaderHandle);
+
+ if(FAILED(hr = pStm->Write(pHeaderBuffPtr, ulEncodedSize, NULL)))
+ {
+ goto Error;
+ } // if
+
+ // Write encoded buffer to stream
+ hr = pStm->Write(m_pcb.pPicklingBuff, m_pcb.ulBytesUsed, NULL);
+ if (FAILED(hr))
+ {
+ goto Error;
+ } // if
+
+ // Reset the object's dirty flag if the user say so
+ if (fClearDirty)
+ {
+ m_bDirty = FALSE;
+ } // if
+
+Error:
+ LeaveCriticalSection(&m_ACLLock);
+ return hr;
+
+} // COAccessControl::CImpAccessControl::Save
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::GetSizeMax(), public
+//
+// Summary: This function returns the number of bytes required to store the
+// object's ACL to a stream. Notice that only the lower 32-bit of the
+// the ULARGE_INTEGER *pcbSize is used.
+//
+// Args: ULARGE_INTEGER *pcbSize [in] - Number of bytes required to store the
+// object's ACL.
+//
+// Return: HRESULT - S_OK: Succeeded.
+// CO_E_ACNOTINITIALIZED: This method was called before
+// the DCOM IAccessControl object
+// was initialized by the Load method.
+// CO_E_SETSERLHNDLFAILED: Failed to reset the serialization
+// handle.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::GetSizeMax
+(
+ULARGE_INTEGER *pcbSize
+)
+{
+ HRESULT hr = S_OK;
+ STREAM_HEADER StreamHeader;
+
+ if(!m_bInitialized)
+ return CO_E_ACNOTINITIALIZED;
+ if (pcbSize == NULL)
+ return E_INVALIDARG;
+
+ EnterCriticalSection(&m_ACLLock);
+ if (m_pcb.bDirtyHandle)
+ {
+
+ if (MesBufferHandleReset( m_pcb.PickleHandle
+ , MES_FIXED_BUFFER_HANDLE
+ , MES_ENCODE
+ , &(m_pcb.pPicklingBuff)
+ , m_pcb.ulPicklingBuffSize
+ , &(m_pcb.ulBytesUsed)) != RPC_S_OK)
+
+ {
+ hr = CO_E_SETSERLHNDLFAILED;
+ goto Error;
+ } // if
+
+ m_pcb.bDirtyHandle = FALSE;
+
+ } // if
+
+ if (!(m_pcb.bPickled))
+ {
+ STREAM_ACL_Encode(m_pcb.PickleHandle, &(m_pcb.StreamACL));
+ m_pcb.bPickled = TRUE;
+ m_pcb.bDirtyHandle = TRUE;
+
+ } // if
+
+ pcbSize->HighPart = 0;
+ pcbSize->LowPart = m_pcb.ulBytesUsed + g_ulHeaderSize;
+
+Error:
+ LeaveCriticalSection(&m_ACLLock);
+ return hr;
+} // COAccessControl::CImpAccessControl::GetSizeMax
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::GrantAccessRights()
+//
+// Args:
+// PACTRL_ACCESSW [in] - The array of ACTRL_ACCCESS_ENTRY structures to
+// be processed.
+// Modifies: m_ACLDesc, m_bDirty
+//
+// Return: HRESULT - S_OK: Succeeded.
+// CO_E_ACNOTINITIALIZED: This method was called before
+// the DCOM IAccessControl object
+// was initialized by the Load method.
+// E_INVALIDARG: This method will return E_INVALIDARG if
+// one of the following is true:
+// 1) One of the access mask specfied by the user is
+// invalid.
+// 2) The pMultipleTrustee field in one of the user
+// specified TRUSTEE_W structure is not NULL.
+// 3) The MultipleTrusteeOPeration field in one of the
+// user specified TRUSTEE_W structure is not
+// NO_MULTIPLE_TRUSTEE.
+// 4) The TrusteeType field in one of the user specified
+// TRUSTEE_W structure has the value TRUSTEE_IS_UNKNOWN.
+// 5) (On Windows 95 only) The TrusteeForm field in one
+// of the user specified TRUSTEE_W structure has
+// the value TRUSTEE_IS_SID.
+// E_OUTOFMEMORY: The system ran out of memory for some
+// crucial operations.
+// CO_E_WRONGTRUSTEENAMESYNTAX: One of the trustee name
+// specified by the client didn't conform to the
+// <Domain>\<Account> syntax.
+// CO_E_INVALIDSID: One of the security identifiers
+// specified by the client was invalid.
+// CO_E_NOMATCHINGNAMEFOUND: No matching account name
+// could be found for one of the security identifiers
+// specified by the client.
+// CO_E_LOOKUPACCSIDFAILED: The system function,
+// LookupAccountSID, failed during the reprocessing
+// of the ACL. The client can call GetLastError to
+// obtain extended error inforamtion.
+// CO_E_NOMATCHINGSIDFOUND: No matching security identifier
+// could be found for one of the
+// trustee name specified by the
+// client.
+// CO_E_LOOKUPACCNAMEFAILED: The system function,
+// LookupAccountName, failed during the reprocessing
+// of the ACL. The client can call GetLastError
+// to obtain extended error information.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::GrantAccessRights
+(
+PACTRL_ACCESSW pAccessList
+)
+{
+
+ STREAM_ACE *pStreamACEReqs; // Pointer to an array
+ // of stream ACEs
+ // converted from the
+ // access request list
+ ULONG ulEstPickledSize;
+ HRESULT hr = S_OK;
+ void *pACEReqs;
+ ULONG cGrant;
+ ULONG cDeny;
+
+ if(!m_bInitialized)
+ return CO_E_ACNOTINITIALIZED;
+
+ if (FAILED(hr = ValidateAndTransformAccReqList( pAccessList
+ , &pStreamACEReqs
+ , &pACEReqs
+ , &ulEstPickledSize
+ , &cGrant
+ , &cDeny )))
+ {
+ return hr;
+ } // if
+
+ EnterCriticalSection(&m_ACLLock);
+
+ hr = AddAccessList( pStreamACEReqs, pACEReqs, ulEstPickledSize, cGrant,
+ cDeny );
+
+ LeaveCriticalSection(&m_ACLLock);
+
+ CleanupAccessList( FAILED(hr), pStreamACEReqs, pACEReqs, cGrant, cDeny );
+ return hr;
+
+} // COAccessControl::CImpAccessControl::GrantAccessRights
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+//
+// Method: COAccessControl::CImpAccessControl::CleanupAccessList()
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(void)
+COAccessControl::CImpAccessControl::CleanupAccessList
+(
+BOOL fReleaseAll,
+STREAM_ACE *pStreamACEReqs,
+void *pvACEReqs,
+ULONG cGrant,
+ULONG cDeny
+)
+{
+ ULONG cCount;
+ ULONG i;
+#ifdef _CHICAGO_
+ access_list_2 *pACEReqs = (access_list_2 *) pvACEReqs;
+ access_list_2 *pACE; // Pointer for stepping through
+ // the LAN Manager ACL in the ACLimage
+#endif
+ STREAM_ACE *pStreamACEReqsPtr; // Pointer for stepping
+ // through the array of
+ // access requests
+ // transformed into
+ // STREAM_ACE structures
+
+ if (fReleaseAll)
+ {
+ cCount = cGrant + cDeny;
+ pStreamACEReqsPtr = pStreamACEReqs;
+#ifdef _CHICAGO_
+ pACE = pACEReqs;
+#endif
+ for (i = 0; i < cCount; i++, pStreamACEReqsPtr++)
+ {
+ midl_user_free(pStreamACEReqsPtr->pTrusteeName);
+#ifdef _CHICAGO_
+ LocalMemFree(pACE->acl2_ugname);
+ pACE++;
+#else
+ midl_user_free(pStreamACEReqsPtr->pSID);
+#endif
+
+ } // for
+ }
+ LocalMemFree(pStreamACEReqs);
+#ifdef _CHICAGO_
+ LocalMemFree(pACEReqs);
+#endif
+}
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+//
+// Method: COAccessControl::CImpAccessControl::AddAccessList()
+//
+// Notes: This function assumes that the access list has been validated. It
+// Can only fail if it runs out of memory. In all failure conditions
+// the object's state is unchanged. The caller must take the lock.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::AddAccessList
+(
+STREAM_ACE *pStreamACEReqs,
+void *pvACEReqs,
+ULONG ulEstPickledSize,
+ULONG cGrant,
+ULONG cDeny
+)
+{
+
+ ULONG i; // Loop counters
+ STREAM_ACE *pStreamACEReqsPtr; // Pointer for stepping
+ // through the array of
+ // access requests
+ // transformed into
+ // STREAM_ACE structures
+ HRESULT hr = S_OK;
+ ULONG cCount;
+#ifdef _CHICAGO_
+ access_list_2 *pACEReqs = (access_list_2 *) pvACEReqs;
+ access_list_2 *pACE; // Pointer for stepping through
+ // the LAN Manager ACL in the ACLimage
+#endif
+
+ // Extend the stream ACL, the ACL image and the pickling
+ // buffer to accomodate the new entries
+ cCount = cGrant + cDeny;
+ if(FAILED(hr = EnlargeStreamACL( &m_pcb
+ , m_pcb.ulNumOfStreamACEs
+ + cCount)))
+ {
+ return hr;
+ } // if
+
+ if(FAILED(hr = ResizePicklingBuff( &m_pcb, m_pcb.ulBytesUsed
+ + ulEstPickledSize
+ + 800)))
+ {
+ return hr;
+ } // if
+ m_pcb.ulBytesUsed += ulEstPickledSize;
+
+#ifdef _CHICAGO_
+ if (FAILED(hr = EnsureACLImage(&m_ACLDesc.GrantACL, cGrant)))
+ {
+ return hr;
+ } // if
+ if (FAILED(hr = EnsureACLImage(&m_ACLDesc.DenyACL, cDeny)))
+ {
+ return hr;
+ } // if
+ pACE = pACEReqs;
+
+#endif
+
+ for ( pStreamACEReqsPtr = pStreamACEReqs,i = 0
+ ; i < cCount
+ ; i++
+#ifdef _CHICAGO_
+ , pACE++
+#endif
+ , pStreamACEReqsPtr++)
+ {
+
+
+#ifdef _CHICAGO_
+ AddACEToACLImage(pACE, pStreamACEReqsPtr->grfAccessMode, &m_ACLDesc);
+#else
+ m_ACLDesc.ulSIDSize += GetLengthSid(pStreamACEReqsPtr->pSID);
+#endif
+ AddACEToStreamACL(pStreamACEReqsPtr, &m_pcb);
+
+ } // for
+
+ // fixing up the cache
+#ifdef _CHICAGO_
+ m_Cache.FlushCache();
+#else
+ m_CacheString.FlushCache();
+ m_CacheSID.FlushCache();
+#endif
+
+ // Re-compute the encoded size of the stream ACL
+ m_pcb.bPickled = FALSE;
+ m_bDirty = TRUE;
+#ifdef _CHICAGO_
+ if (cGrant != 0)
+ m_ACLDesc.GrantACL.bDirtyACL = TRUE;
+ if (cDeny != 0)
+ m_ACLDesc.DenyACL.bDirtyACL = TRUE;
+#else
+ m_ACLDesc.bDirtyACL = TRUE;
+#endif
+ return S_OK;
+
+} // COAccessControl::CImpAccessControl::GrantAccessRights
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::SetOwner(), public
+//
+// Summary: This method is not implemented at this moment
+//
+// Args:
+//
+// Modifies:
+//
+// Return: HRESULT - This method will always return E_NOTIMPL.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::SetOwner
+(
+PTRUSTEEW pOwner,
+PTRUSTEEW pGroup
+)
+{
+ return E_NOTIMPL;
+} // COAccessControl::CimpAccessControl::SetOwner
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::SetAccessRights(), public
+//
+// Summary: This function replace the internal ACL with an array of
+// ACTRL_ACCESS_ENTRY structures provided by the caller of this method.
+// Note that this function does not literally replace the internal
+// ACL, instead it will map the array of ACTTRL_ACCESS_ENTRY structures
+// into the internal representation of an ACL.
+// This function will also merge entries with the same access mode
+// and trustee name together into one internal ACE.
+//
+// Args:
+// PACTRL_ACCESSW [in] - The array of ACTRL_ACCCESS_ENTRY structures to
+// be processed.
+//
+// Modifies: m_ACLDesc, m_bDirty, m_pcb
+//
+// Return: HRESULT - S_OK: Succeeded.
+// E_INVALIDARG: This method will return E_INVALIDARG if one of
+// the following is true:
+// 1) pExplicitAccessList is a NULL pointer.
+// 2) Inside one of the ACTRL_ACCESS_ENTRY structures specified
+// by the client, either
+// i) the grfAccessPermissions field contained an invalid
+// access mask, or
+// ii) the grfAccessMode field was neither ACTRL_ACCESS_ALLOWED
+// nor ACTRL_ACCESS_DENIED, or
+// iii) the grfInheritace field was not NO_INHERITANCE or
+// iv) the pMultipleTrustee field in the TRUSTEE_W structure
+// was not NULL, or
+// v) the MultipleTrusteeOperation field in the TRUSTEE_W
+// structure was not NO_MULTIPLE_TRUSTEE, or
+// vi) the TrusteeType field in the TRUSTEE_Wstructure was
+// TRUSTEE_IS_UNKNOWN, or
+// vii) the ptstrNameFiled in the TRUSTEE_W structure was
+// NULL, or
+// On Windows 95 only:
+// viii) the TrusteeForm field inside the TRUSTEE_W
+// structure was TRUSTEE_IS_SID.
+// E_OUTOFMEMORY: The system ran out of memory for crucial
+// operation.
+// CO_E_ACNOTINITIALIZED: The DCOM IAccessCOntrol object was
+// not initialized by the load method
+// before this method is called.
+// CO_E_WRONGTRUSTEENAMESYNTAX: The trustee name in the
+// TRUSTEE_W structure inside one of the ACTRL_ACCESS_ENTRY
+// structure specified by the client didn't conform to the
+// <Domain>\<Account> syntax.
+// CO_E_INVALIDSID: The security identifier in the TRUSTEE_W
+// structure inside one of the ACTRL_ACCESS_ENTRY
+// structure specified by the client was
+// invalid.
+// (The following error codes are for Windows NT only)
+// CO_E_NOMATCHINGNAMEFOUND: No matching account name
+// could be found for one of the security identifiers
+// specified by the client.
+// CO_E_LOOKUPACCSIDFAILED: The system function,
+// LookupAccountSID, failed during the reprocessing
+// of the ACL. The client can call GetLastError to
+// obtain extended error inforamtion.
+// CO_E_NOMATCHINGSIDFOUND: No matching security identifier
+// could be found for one of the
+// trustee name specified by the
+// client.
+// CO_E_LOOKUPACCNAMEFAILED: The system function,
+// LookupAccountName, failed during the reprocessing
+// of the ACL. The client can call GetLastError to
+// obtain extended error information.
+//
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::SetAccessRights
+(
+PACTRL_ACCESSW pAccessList
+)
+{
+ ACL_DESCRIPTOR ACLDescBackup; // Backup copy of the object's
+ // original ACL descriptor
+ PCB pcbBackup; // Backup copy of the object's
+ // original pickle control
+ // block
+ STREAM_ACE *pStreamACEReqs; // Pointer to an array
+ // of stream ACEs
+ // converted from the
+ // access request list
+ ULONG ulEstPickledSize;
+ HRESULT hr = S_OK;
+ void *pACEReqs;
+ ULONG cGrant;
+ ULONG cDeny;
+
+ if(!m_bInitialized)
+ return CO_E_ACNOTINITIALIZED;
+
+ if (FAILED(hr = ValidateAndTransformAccReqList( pAccessList
+ , &pStreamACEReqs
+ , &pACEReqs
+ , &ulEstPickledSize
+ , &cGrant
+ , &cDeny )))
+ {
+ return hr;
+ } // if
+
+ EnterCriticalSection(&m_ACLLock);
+
+ // Take a snapshot of the old ACL descriptor and the old PCB
+ memcpy(&ACLDescBackup, &m_ACLDesc, sizeof(ACL_DESCRIPTOR));
+ memset(&m_ACLDesc, 0, sizeof(ACL_DESCRIPTOR));
+
+ memcpy(&pcbBackup, &m_pcb, sizeof(PCB));
+ memset(&m_pcb, 0, sizeof(PCB));
+
+ // Try to add the new entries.
+ hr = AddAccessList( pStreamACEReqs, pACEReqs, ulEstPickledSize, cGrant,
+ cDeny );
+
+ // If successful, move some resources from the backup
+ if (SUCCEEDED(hr))
+ {
+#ifdef _CHICAGO_
+ // Reuse the old dummy file name
+ m_ACLDesc.DenyACL.pACL->acc1_resource_name =
+ ACLDescBackup.DenyACL.pACL->acc1_resource_name;
+ m_ACLDesc.GrantACL.pACL->acc1_resource_name =
+ ACLDescBackup.GrantACL.pACL->acc1_resource_name;
+#else
+ memcpy(&(m_ACLDesc.SecDesc),&(ACLDescBackup.SecDesc), sizeof(SECURITY_DESCRIPTOR));
+ ACLDescBackup.SecDesc.Owner = NULL;
+ ACLDescBackup.SecDesc.Group = NULL;
+ m_ACLDesc.bDirtyACL = TRUE;
+#endif
+ m_pcb.PickleHandle = pcbBackup.PickleHandle;
+ pcbBackup.PickleHandle = NULL;
+
+ // Free the old ACL descriptor and PCB
+ CleanAllMemoryResources(&ACLDescBackup, &pcbBackup);
+ }
+
+ // Restore the orignal ACL and PCB
+ else
+ {
+ // Free the new ACL descriptor and PCB
+ CleanAllMemoryResources(&m_ACLDesc, &m_pcb);
+
+ memcpy(&m_ACLDesc, &ACLDescBackup, sizeof(ACL_DESCRIPTOR));
+ memcpy(&m_pcb, &pcbBackup, sizeof(PCB));
+ }
+ LeaveCriticalSection(&m_ACLLock);
+
+ CleanupAccessList( FAILED(hr), pStreamACEReqs, pACEReqs, cGrant, cDeny );
+ return hr;
+
+} // COAccessControl::CImpAccessControl::SetAccessRights
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::RevokeAccessRights()
+// , public
+//
+// Summary: This function removes all ACEs (both ACTRL_ACCESS_ALLOWED mode and
+// ACTRL_ACCESS_DENIED mode entries) associated with the list of of trustees
+// listed in pTrustee from the object's internal ACL.
+//
+// Args:
+// LPWSTR lpProperty [in] - Property name, must be NULL.
+// ULONG cCount [in] - Number of trustee to be revoked from the
+// ACL.
+// TRUSTEE_W pTrustee [in] - A list of trustees to be revoked.
+//
+// Return: HRESULT - S_OK: Succeeded.
+// CO_E_ACNOTINITIALIZED
+// E_INVALIDARG: Either pTrustee was NULL, or cCount was
+// zero, or one of the following was true
+// about at least one of the TRUSTEE_W structure
+// specified by the user:
+//
+// 1) The value of the pMultipleTrustee field in the TRUSTEE_W
+// structure was not NULL.
+// 2) The value of the MultipleTrusteeOperation field in the
+// TRUSTEE_W structure was not NO_MULTIPLE_TRUSTEE.
+// 3) The value of the TrusteeType field in the TRUSTEE_W
+// structure was TRUSTEE_IS_UNKNOWN.
+// 4) The value of the ptstrName field in the TRUSTEE_W structure
+// was NULL.
+// On Windows 95 only:
+// 5) The value of the TrusteeForm field in the TRUSTEE_W structure
+// was TRUSTEE_IS_SID.
+// CO_E_WORNGTRUSTEENAMESYNTAX: At least one of the TRUSTEE_W
+// structures specified by the
+// user contained a trustee name
+// that did not conform to the
+// <Domain>/<Account Name>
+// syntax.
+// CO_E_INVALIDSID: At least one of the TRUSTEE_W structures
+// specified by the user contained an invalid
+// security identifier.
+// E_OUTOFMEMORY: There was not enough memory for allocating
+// a string conversion buffer.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::RevokeAccessRights
+(
+LPWSTR lpProperty,
+ULONG cCount,
+TRUSTEE_W pTrustee[]
+)
+{
+ BOOL bDeleted = FALSE; // This flag indicates if any entry is
+ // removed from theACL.
+ ULONG i; // Loop counter
+ HRESULT hr; // Function return code
+ TRUSTEE_W *pLocalTrustee; // Pointer for traversing the list of
+ // trustees.
+#ifdef _CHICAGO_
+ ULONG ulStrLen; // Length of the trustee string in
+ // multibyte characters
+ ULONG ulMaxLen = 0; // Maximum length of all the trustee names
+ // converted into multibyte strings.
+ CHAR *pcszTrusteeName; // Pointer to trustee name in multibyte
+ // characters.
+#endif
+
+
+ if(!m_bInitialized)
+ return CO_E_ACNOTINITIALIZED;
+
+ if (cCount == 0 || lpProperty != NULL)
+ {
+ return E_INVALIDARG;
+ } // if
+
+
+ // The following loop validates the TRUSTEE_W structures
+ // specified by the user. On Windows 95, this function
+ // will also determine the length of the longest trustee
+ // name in multibyte characters.
+ pLocalTrustee = pTrustee;
+ for (i = 0; i < cCount; i++, pLocalTrustee++)
+ {
+
+ if(FAILED(hr = ValidateTrustee(pLocalTrustee)))
+ {
+ return hr;
+ } // if
+
+#ifdef _CHICAGO_
+ ulStrLen = WideCharToMultiByte( g_uiCodePage
+ , WC_COMPOSITECHECK | WC_SEPCHARS
+ , pLocalTrustee->ptstrName
+ , -1
+ , NULL
+ , NULL
+ , NULL
+ , NULL );
+ if (ulStrLen > ulMaxLen)
+ {
+ ulMaxLen = ulStrLen;
+ } //if
+#endif
+ } // for
+
+#ifdef _CHICAGO_
+
+ // Allocate a buffer for converting Unicode trustee name into
+ // multibyte trustee name. An extra 5 bytes is allocated for
+ // extra safety.
+ ulMaxLen += 5;
+ pcszTrusteeName = (CHAR *)LocalMemAlloc(ulMaxLen);
+ if(pcszTrusteeName == NULL)
+ {
+ return E_OUTOFMEMORY;
+ } // if
+#endif
+
+ EnterCriticalSection(&m_ACLLock);
+
+
+ pLocalTrustee = pTrustee;
+ for (i = 0; i < cCount ; i++, pLocalTrustee++)
+ {
+#ifdef _CHICAGO_
+ ulStrLen = WideCharToMultiByte ( g_uiCodePage
+ , WC_COMPOSITECHECK | WC_SEPCHARS
+ , pLocalTrustee->ptstrName
+ , -1
+ , pcszTrusteeName
+ , ulMaxLen
+ , NULL
+ , NULL);
+ pcszTrusteeName[ulStrLen] = '\0';
+#endif
+ if (DeleteACEFromStreamACL( pLocalTrustee
+ , ACTRL_ACCESS_DENIED
+#ifndef _CHICAGO_
+ , &m_ACLDesc
+#endif
+ , &m_pcb))
+ {
+#ifdef _CHICAGO_
+ DeleteACEFromACLImage( pcszTrusteeName
+ , &(m_ACLDesc.DenyACL));
+ m_ACLDesc.DenyACL.bDirtyACL = TRUE;
+#endif
+ bDeleted = TRUE;
+ } // if
+
+ if (DeleteACEFromStreamACL( pLocalTrustee
+ , ACTRL_ACCESS_ALLOWED
+#ifndef _CHICAGO_
+ , &m_ACLDesc
+#endif
+ , &m_pcb))
+ {
+#ifdef _CHICAGO_
+ DeleteACEFromACLImage( pcszTrusteeName
+ , &(m_ACLDesc.GrantACL));
+ m_ACLDesc.GrantACL.bDirtyACL = TRUE;
+#endif
+ bDeleted = TRUE;
+ } // if
+
+ } // for
+
+ if (bDeleted)
+ {
+ m_bDirty = TRUE;
+#ifndef _CHICAGO_
+ m_ACLDesc.bDirtyACL = TRUE;
+#endif
+ // Fix up the cache
+#ifdef _CHICAGO_
+ m_Cache.FlushCache();
+#else
+ m_CacheString.FlushCache();
+ m_CacheSID.FlushCache();
+#endif
+ m_pcb.bPickled = FALSE;
+ } // if
+
+#ifdef _CHICAGO_
+ LocalMemFree(pcszTrusteeName);
+#endif
+
+ LeaveCriticalSection(&m_ACLLock);
+
+ return S_OK;
+
+} // COAccessControl::CImpAccessControl::RevokeAccessRights
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::IsAccessAllowed(), public
+//
+// Summary: This function performs access checking for the client.
+// Only the execute permission is supported at this moment and the
+// the trustee specified by the client must be the client itself.
+//
+// Args:
+// TRUSTEE *pTrustee [in] - Pointer to the trustee to
+// perform access check for.
+// LPWSTR lpProperty [in] - Must be NULL.
+// ACCESS_RIGHTS AccessRights [in] - A bit mask representing the set
+// of permissions the client wants
+// to check.
+// BOOL *pfAccessAllowed [out] - Set TRUE only if trustee has
+// requested access.
+//
+// Common on both Windows 95 and Windows NT:
+// Return: HRESULT - S_OK: Succeeded, and the requested access was granted to
+// the trustee.
+// CO_E_ACNOTINITIALIZED: The COM IAccessControl object
+// was not initialized before
+// this method was called.
+// E_ACCESSDENIED: The requested access was denied
+// from the trustee.
+// E_INVALIDARG: Either one of the following was true:
+//
+// 1) The value of the pMultipleTrustee field in the TRUSTEE_W
+// structure was not NULL.
+// 2) The value of the MultipleTrusteeOperation field in the
+// TRUSTEE_W structure was not NO_MULTIPLE_TRUSTEE.
+// 3) The value of the TrusteeType field in the TRUSTEE_W
+// structure was TRUSTEE_IS_UNKNOWN.
+// 4) The value of the ptstrName field in the TRUSTEE_W structure
+// was NULL.
+//
+// CO_E_TRUSTEEDOESNTMATCHCLIENT: The trustee specified by the
+// client was not the current
+// ORPC client.
+// CO_E_WRONGTRUSTEENAMESYNTAX: The trustee name inside the
+// TRUSTEE_W structure specified
+// by the user is not of the
+// form <Domain>\<Account Name>.
+// CO_E_FAILEDTOQUERYCLIENTBLANKET: Unable to query for the
+// client's security blanket.
+// E_UNEXPECTED: This function should not return E_UNEXPECTED
+// under all circumstances.
+//
+//
+// On Windows 95
+// Return: HRESULT - E_INVALIDARG: In addition to the four cases stated above,
+// E_INVALIDARG will be returned if the
+// TrusteeForm field of the TRUSTEE_W structure
+// pointed to by the pTrustee parameter is
+// TRUSTEE_IS_SID.
+// CO_E_NETACCESSAPIFAILED: Either the NetAccessAdd API or
+// the NetAccessDel APi returned
+// an error code in
+// ComputeEffectiveAccess.
+// CO_E_CONVERSIONFAILED: WideCharToMultiByte returned zero.
+// The caller can get extended error
+// information by calling GetLastError.
+// E_OUTOFMEMORY: Either there was not enough memory to
+// convert the Unicode trustee name into a
+// multibyte string in
+// ValidateAccessCheckClient of there
+// was not enough memory to do the same in
+// ComputeEffectiveAccess.
+// On Windows NT:
+// CO_E_FAILEDTOGETSECCTX: Failed to obtain an IServerSecurity
+// pointer to the current server
+// security context.
+// CO_E_FAILEDTOIMPERSONATE: The GetEffAccUsingSID/Name was
+// unable to impersonate
+// the client who calls this
+// function.
+// CO_E_FAILEDOPENTHREADTOKEN: The GetEffAccUsingSID/Name
+// method was unable to open the
+// access token assciated
+// with the current thread. The
+// client of this method can
+// call GetLastError to get
+// extended error information.
+// CO_E_FAILEDTOGETTOKENINFO: The GetEffAccUsingSID/Name
+// method was unable to obtain
+// obtain information from the
+// access token associated with
+// the current thread. The client
+// of this method can call
+// GetLastError to get extended
+// error information.
+// CO_E_ACCESSCHECKFAILED: The system function, AccessCheck,
+// returned FALSE in
+// ComputeEffectiveAccess. The
+// caller of this method can call
+// GetLastError to obtain extended
+// error information.
+// CO_E_INVALIDSID: At least one of the TRUSTEE_W structures
+// specified by the user contained an invalid
+// security identifier.
+// CO_E_FAILEDTOSETDACL: SetSecurityDescriptorDacl returned
+// false inside PutStreamACLIntoSecDesc.
+// The client of this method can call
+// GetLastError to get extended error
+// information.
+// E_OUTOFMEMORY: The system ran out of memory for mapping the
+// DCOM IAccessControl object's STREAM_ACL
+// structure to an NT ACL or the system
+// could not allocate memory for the TOKEN_USER
+// structure returned by GetTokenInformation.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::IsAccessAllowed
+(
+TRUSTEE_W *pTrustee,
+LPWSTR lpProperty,
+ACCESS_RIGHTS AccessRights,
+BOOL *pfAccessAllowed
+)
+{
+ DWORD dwPermissions = 0;
+ HRESULT hr;
+
+ // Initialize access allowed to FALSE.
+ if (pfAccessAllowed == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ *pfAccessAllowed = FALSE;
+
+ // Validate the arguments.
+ if (!IsValidAccessMask(AccessRights) ||
+ lpProperty != NULL)
+ {
+ return E_INVALIDARG;
+ } // if
+ if (FAILED(hr = ValidateAccessCheckClient(pTrustee)))
+ {
+ return hr;
+ } // if
+
+ if(!m_bInitialized)
+ return CO_E_ACNOTINITIALIZED;
+
+#ifdef _CHICAGO_
+ EnterCriticalSection(&m_ACLLock);
+ if (!m_Cache.LookUpEntry(pTrustee->ptstrName, &dwPermissions))
+ {
+ if(FAILED(hr = ComputeEffectiveAccess( pTrustee->ptstrName
+ , &dwPermissions
+ , &m_ACLDesc)))
+ {
+ LeaveCriticalSection(&m_ACLLock);
+ return hr;
+ } // if
+ m_Cache.WriteEntry(pTrustee->ptstrName, dwPermissions);
+ } // if
+
+ LeaveCriticalSection(&m_ACLLock);
+#else
+
+ if (pTrustee->TrusteeForm == TRUSTEE_IS_NAME)
+ hr = GetEffAccRightsUsingName( pTrustee->ptstrName
+ , &dwPermissions );
+ else
+ hr = GetEffAccRightsUsingSID( (PSID)(pTrustee->ptstrName)
+ , &dwPermissions );
+
+ if(FAILED(hr))
+ {
+ return hr;
+ }
+#endif
+
+ // Indicate failure by setting pfAccessAllowed.
+ if ((dwPermissions & AccessRights) == AccessRights)
+ {
+ *pfAccessAllowed = TRUE;
+ }
+ return S_OK;
+
+} // COAccessControl::CImpAccessControl::IsAccessAllowed
+
+#ifndef _CHICAGO_
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::GetEffAccRightsUsingName, Private
+//
+// Summary: Given a Unicode string representing the name of a user, this
+// function computes the effective access permission that the
+// specified user has on the secured object. Notice that the current
+// implementation of this mehtod linits the trustee specified by the
+// client to be the name of the same client calling this method.
+//
+// Args: LPWSTR pwszTrusteeName [in] - Pointer to a Unicode string
+// representing the user whose effective
+// access permissions on the secured object
+// is about to be determined by this
+// method. Notice that this parameter must
+// specify the name of the client calling
+// this function.
+// DWORD *pdwRights [out] - Address of an access mask representing the
+// set of effective access rights the user
+// specified by the pwszTrusteeName parameter
+// has on the secured object.
+//
+// Return: HRESULT - S_OK: Succeeded.
+// CO_E_FAILEDTOGETSECCTX: Failed to obtain an IServerSecurity
+// pointer to the current server
+// security context.
+// CO_E_FAILEDTOIMPERSONATE: This method was unable to
+// impersonate the client who calls
+// this function.
+// CO_E_FAILEDOPENTHREADTOKEN: This method was unable to
+// open the access token assciated
+// with the current thread. The
+// client of this method can call
+// GetLastError to get extended
+// error information.
+// CO_E_FAILEDTOGETTOKENINFO: This method was unable to obtain
+// obtain information from the
+// access token associated with
+// the current thread. The client
+// of this method can call
+// GetLAstError to get extended
+// error information.
+// CO_E_FAILEDTOQUERYCLIENTBLANKET: Failed to query for the
+// client's security blanket.
+// CO_E_ACCESSCHECKFAILED: The system function, AccessCheck,
+// returned FALSE in
+// ComputeEffectiveAccess. The
+// caller of this method can call
+// GetLastError to obtain extended
+// error information.
+// CO_E_FAILEDTOSETDACL: SetSecurityDescriptorDacl returned
+// false inside PutStreamACLIntoSecDesc.
+// The client of this method can call
+// GetLastError to get extended error
+// information.
+// E_OUTOFMEMORY: The system ran out of memory for mapping the
+// DCOM IAccessControl object's STREAM_ACL
+// structure to an NT ACL or the system
+// could not allocate memory for the TOKEN_USER
+// structure returned by GetTokenInformation.
+//
+// Remarks: It is neccessary for this method to impersonate the client
+// in order to obtain the client's access token for access checking.
+// This method is designed in such a way that if the server has already
+// been impersonating the client, this method will not perform
+// impersonation and it will obtain the currrent thread's access token
+// directly. On the other hand, if the server wasn't impersonating the
+// client before this method is called, this method will perform the
+// impersonation before opening the access token associated with
+// current thread. In either one of the forementioned cases, this method
+// will retain the impersonation status of the server after it has
+// finished its own processing. Ie. if the server is impersonating the
+// client before this method is called, the server will still be
+// impersonating the client after this method has finished processing
+// and vice versa.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::GetEffAccRightsUsingName
+(
+LPWSTR pwszTrusteeName,
+DWORD *pdwRights
+)
+{
+ IServerSecurity *pSSec; // Current security call context
+ HRESULT hr = S_OK; // Result handle
+ BOOL bIsImpersonating; // This flag indicates whether the
+ // server is impersonating the client
+ // when the function is called
+ HANDLE TokenHandle; // Handle to the client's access
+ // token
+ HANDLE ThreadHandle; // Handle to the current thread.
+ // This is used for obtaining the access
+ // token associated with the current
+ // thread.
+ TOKEN_USER *pClientInfo; // Pointer to the TOKEN_USER structure
+ // returned by GetTokenInformation.
+ DWORD dwInfoLength; // Size of the TOKEN_USER structure
+ // returned by GetTokenInformation.
+
+ // Set the handles to invalid values and pointers to null
+ TokenHandle = INVALID_HANDLE_VALUE;
+ ThreadHandle = INVALID_HANDLE_VALUE;
+ pClientInfo = NULL;
+ pSSec = NULL;
+ bIsImpersonating = TRUE;
+
+ // Call get call context to obtain an IServerSecurity
+ // pointer corresponding to the call context of the
+ // current thread.
+
+ if(FAILED(CoGetCallContext( IID_IServerSecurity
+ , (void **)&pSSec)))
+ {
+ return CO_E_FAILEDTOGETSECCTX;
+ } // if
+
+ EnterCriticalSection(&m_ACLLock);
+
+ if(!m_CacheString.LookUpEntry(pwszTrusteeName, pdwRights))
+ {
+
+ // Check if the server has been impersonating the client already
+ // and impersonate the client if not
+ if(!(bIsImpersonating = pSSec->IsImpersonating()))
+ {
+ if(FAILED(hr = pSSec->ImpersonateClient()))
+ {
+ hr = CO_E_FAILEDTOIMPERSONATE;
+ goto Error;
+ } // if
+ } // if
+
+ // Get the current thread handle. The handle
+ // is going to be used in the OpenThreadToken function.
+ ThreadHandle = GetCurrentThread();
+
+ // Open the current thread token, it should be the
+ // access token of the client.
+ if(!OpenThreadToken( ThreadHandle
+ , TOKEN_READ
+ , TRUE
+ , &TokenHandle))
+ {
+ hr = CO_E_FAILEDTOOPENTHREADTOKEN;
+ goto Error;
+ } // hr
+
+ // Get the SID from the access token for cache lookup
+ GetTokenInformation( TokenHandle
+ , TokenUser
+ , pClientInfo
+ , 0
+ , &dwInfoLength );
+ DWORD dwLastError;
+ dwLastError = GetLastError();
+ if (dwLastError == ERROR_INSUFFICIENT_BUFFER)
+ {
+ // Allocate buffer for token information
+ pClientInfo = (TOKEN_USER *)LocalMemAlloc(dwInfoLength);
+ if ( pClientInfo == NULL )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } // if
+
+ if(!GetTokenInformation( TokenHandle
+ , TokenUser
+ , pClientInfo
+ , dwInfoLength
+ , &dwInfoLength ))
+ {
+ hr = CO_E_FAILEDTOGETTOKENINFO;
+ goto Error;
+ } // if
+ }
+ else
+ {
+ hr = CO_E_FAILEDTOGETTOKENINFO;
+ } // if
+
+ // Use the SID inside ClientInfo to lookup the
+ // the effective access rights in the cache
+ if(!(m_CacheSID.LookUpEntry(pClientInfo->User.Sid, pdwRights)))
+ {
+ // Perform access checking
+ if(FAILED(hr = ComputeEffectiveAccess( &m_ACLDesc
+ , &(m_pcb.StreamACL)
+ , TokenHandle
+ , pdwRights)) < 0)
+ {
+ goto Error;
+ } // if
+ m_CacheSID.WriteEntry(((TOKEN_USER *)pClientInfo)->User.Sid, *pdwRights);
+ }
+
+ // Write the effective access permissions to the string cache
+ m_CacheString.WriteEntry(pwszTrusteeName, *pdwRights);
+
+ } // if
+
+Error:
+ // Free the user info structure
+ if (pClientInfo != NULL)
+ {
+ LocalMemFree(pClientInfo);
+ }
+
+ // Release the token handle
+ if (TokenHandle != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(TokenHandle);
+ }
+
+ // Restore the impersonation status
+ if(!bIsImpersonating)
+ {
+ pSSec->RevertToSelf();
+ } // if
+
+ // Release the IServerSecurity pointer
+ if (pSSec != NULL)
+ {
+ pSSec->Release();
+ } // if
+
+ // There is no need to free the thread handle
+ // because it is a pseudo handle
+ LeaveCriticalSection(&m_ACLLock);
+ return hr;
+
+} // COAccessControl::CImpAccessControl:GetEffAccRightsUsingName
+
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::GetEffAccRightsUsingSID, private
+//
+// Summary: Given a security identifier of a user, this function computes the
+// effective access rights the user has on the object secured by the
+// current DCOM IAccessControl implementation object. Notice that
+// the current implementation of this mehtod limits the security
+// identifier to be the one that corresponds to the client that calls
+// this function.
+//
+// Args: PSID pSID [in] - Pointer to a security identifier of a user whose
+// effective permissions on the secured object are
+// computed upon the client's request. Notice that
+// this security identifier must be the security
+// identifier of the client who calls this function
+// in the current implementation.
+// DWORD *pdwRights [out] - Address of the access mask representing the
+// effective permissions that the user specified
+// by the pSID parameter has on the secured
+// object.
+//
+// Return: HRESULT - S_OK: Succeeded.
+// CO_E_FAILEDTOGETSECCTX: Failed to obtain an IServerSecurity
+// pointer to the current server
+// security context.
+// CO_E_FAILEDTOIMPERSONET: This method was unable to
+// impersonate the client who calls
+// this function.
+// CO_E_FAILEDOPENTHREADTOKEN: This method was unable to
+// open the access token assciated
+// with the current thread. The
+// client of this method can call
+// GetLastError to get extended
+// error information.
+// CO_E_FAILEDTOGETTOKENINFO: This method was unable to obtain
+// obtain information from the
+// access token associated with
+// the current thread. The client
+// of this method can call
+// GetLAstError to get extended
+// error information.
+// CO_E_ACCESSCHECKFAILED: The system function, AccessCheck,
+// returned FALSE in
+// ComputeEffectiveAccess. The
+// caller of this method can call
+// GetLastError to obtain extended
+// error information.
+// CO_E_FAILEDTOSETDACL: SetSecurityDescriptorDacl returned
+// false inside PutStreamACLIntoSecDesc.
+// The client of this method can call
+// GetLastError to get extended error
+// information.
+// E_OUTOFMEMORY: The system ran out of memory for mapping the
+// DCOM IAccessControl object's STREAM_ACL
+// structure to an NT ACL or the system could
+// not allocate memory for the TOKEN_USEr
+// structure returned by GetTokenInformation.
+//
+// Remarks: It is neccessary for this method to impersonate the client
+// in order to obtain the client's access token for access checking.
+// This method is designed in such a way that if the server has already
+// been impersonating the client, this method will not perform
+// impersonation and it will obtain the currrent thread's access token
+// directly. On the other hand, if the server wasn't impersonating the
+// client before this method is called, this method will perform the
+// impersonation before opening the access token associated with
+// current thread. In either one of the forementioned cases, this
+// method will retain the impersonation status of the server after it
+// has finished its own processing. Ie. if the server is impersonating
+// the client before this method is called, the server will still be
+// impersonating the client after this method has finished processing
+// and vice versa.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::GetEffAccRightsUsingSID
+(
+PSID pSID,
+DWORD *pdwRights
+)
+{
+ IServerSecurity *pSSec; // Current security call context
+ HRESULT hr; // Result handle
+ BOOL bIsImpersonating; // This flag indicates whether the
+ // server is impersonating the client
+ // when the function is called
+ HANDLE TokenHandle; // Handle to the client's access
+ // token
+ TOKEN_USER *pClientInfo; // Pointer to a TOKEN_USER structure.
+ // This structure should contain the
+ // security identifier of the current
+ // client.
+ DWORD dwInfoLength; // Size of the TOKEN_USER info structure
+ // returned by GetTokenInfo.
+ LPWSTR pwszClientName; // Pointer to the name of the client in
+ // Unicode.
+ BOOL fSuccess;
+
+ // Set the handles to invalid values and pointers to null
+ TokenHandle = INVALID_HANDLE_VALUE;
+ pClientInfo = NULL;
+ pSSec = NULL;
+
+ // Call get call context to obtain an IServerSecurity
+ // pointer corresponding to the call context of the
+ // current thread.
+
+ if(FAILED(hr = CoGetCallContext( IID_IServerSecurity
+ , (void **)&pSSec)))
+ {
+ hr = CO_E_FAILEDTOGETSECCTX;
+ goto Error;
+ } // if
+
+ // Check if the server is impersonating the client.
+ // If not, this function would do the impersonation.
+ if(!(bIsImpersonating = pSSec->IsImpersonating()))
+ {
+ if(FAILED(hr = pSSec->ImpersonateClient()))
+ {
+ hr = CO_E_FAILEDTOIMPERSONATE;
+ goto Error;
+ }
+ } // if
+
+ // Call OpenThreadToken to obtain the access token.
+ // The access token should belong to the DCOM client
+ fSuccess = OpenThreadToken( GetCurrentThread()
+ , TOKEN_READ
+ , TRUE
+ , &TokenHandle);
+
+ // Restore the impersonation status
+ if(!bIsImpersonating)
+ {
+ pSSec->RevertToSelf();
+ } // if
+
+ if (!fSuccess)
+ {
+ hr = CO_E_FAILEDTOOPENTHREADTOKEN;
+ goto Error;
+ } // if
+
+ // Call GetTokenInformation to obtain the SID inside
+ // the access token.
+ GetTokenInformation( TokenHandle
+ , TokenUser
+ , pClientInfo
+ , 0
+ , &dwInfoLength);
+ if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ pClientInfo = (TOKEN_USER *)LocalMemAlloc(dwInfoLength);
+ if (pClientInfo == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } // if
+
+ if(!GetTokenInformation( TokenHandle
+ , TokenUser
+ , pClientInfo
+ , dwInfoLength
+ , &dwInfoLength))
+ {
+ hr = CO_E_FAILEDTOGETTOKENINFO;
+ goto Error;
+ } // if
+
+ }
+ else
+ {
+ hr = CO_E_FAILEDTOGETTOKENINFO;
+ goto Error;
+ } // if
+
+ // Check to see if the trustee provided is same as the
+ // current client. If not, return CO_E_TRUSTEEDOESNTMATCHCLIENT.
+ if(!EqualSid(pClientInfo->User.Sid, pSID))
+ {
+ hr = CO_E_TRUSTEEDOESNTMATCHCLIENT;
+ goto Error;
+ } // if
+
+ EnterCriticalSection(&m_ACLLock);
+ if(!m_CacheSID.LookUpEntry(pSID, pdwRights))
+ {
+ // Call QueryBlanket to obtain the client name.
+ if (FAILED(hr = pSSec->QueryBlanket( NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , (void **)&pwszClientName
+ , NULL)))
+ {
+ hr = CO_E_FAILEDTOQUERYCLIENTBLANKET;
+ goto Error2;
+ } // if
+
+
+ // Use the client name to lookup the effective
+ // access permissions
+ if(!m_CacheString.LookUpEntry(pwszClientName, pdwRights))
+ {
+ // Has to call ComputeEffectiveAccessRights
+ if(FAILED(hr = ComputeEffectiveAccess( &m_ACLDesc
+ , &(m_pcb.StreamACL)
+ , TokenHandle
+ , pdwRights)))
+ {
+ goto Error2;
+ } // if
+ m_CacheString.WriteEntry( pwszClientName
+ , *pdwRights);
+
+ } //if
+ m_CacheSID.WriteEntry(pSID, *pdwRights);
+ } // if
+
+ hr = S_OK;
+Error2:
+ LeaveCriticalSection(&m_ACLLock);
+Error:
+ // Free the user info structure
+ if (pClientInfo != NULL)
+ {
+ LocalMemFree(pClientInfo);
+ }
+
+ // Release the token handle
+ if (TokenHandle != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(TokenHandle);
+ }
+
+ // Release the IServerSecurity pointer
+ if (pSSec != NULL)
+ {
+ pSSec->Release();
+ } // if
+
+ // There is no need to free the thread handle
+ // because it is a pseudo handle
+ return hr;
+
+} // COAccessControl::CImpAccessControl::GetEffAccRightsUsingSID
+#endif
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: COAccessControl::CImpAccessControl::GetAllAccessRights(), public
+//
+// Summary: This function returns an array of ACTRL_ACCESS_ENTRY structures which
+// represents the ACL that belongs to the secured object. Notice
+// that memory is allocated by the callee for the array of
+// structures and the trustee string within each
+// structure. The client of this method must call
+// CoTaskMemFree to free those memory blocks when they are no longer
+// in use. Notice that in a multi-threaded environment, the array
+// returned may not accurately represent the object's ACL by
+// the time the caller receives it.
+//
+// Return: HRESULT - S_OK: Succeeded.
+// E_OUTOFMEMORY: Not enough memory to allocate the
+// ACTRL_ACCESS_ENTRY array to be return.
+// E_INVALIDARG: If one of the arguments passed in is NULL
+// CO_E_ACNOTINITIALIZED: The DCOM IAccessControl implementation
+// object was not initialized properly
+// by the load method before this method
+// was called.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+STDMETHODIMP_(HRESULT)
+COAccessControl::CImpAccessControl::GetAllAccessRights
+(
+LPWSTR lpProperty,
+PACTRL_ACCESSW *ppAccessList,
+PTRUSTEEW *ppOwner,
+PTRUSTEEW *ppGroup
+)
+{
+ HRESULT hr = S_OK;
+
+ if(!m_bInitialized)
+ return CO_E_ACNOTINITIALIZED;
+
+ // Validate the arguments
+ if (lpProperty != NULL || ppAccessList == NULL)
+ {
+ return E_INVALIDARG;
+ } // if
+
+ if (ppOwner != NULL)
+ {
+ *ppOwner = NULL;
+ }
+ if (ppGroup != NULL)
+ {
+ *ppGroup = NULL;
+ }
+
+ EnterCriticalSection(&m_ACLLock);
+
+ hr = MapStreamACLToAccessList( &m_pcb, ppAccessList );
+
+ LeaveCriticalSection(&m_ACLLock);
+ return hr;
+} // COAccessControl::CImpAccessControl::GetAllAccessRights
+
+//////////////////////////////////////////////////////////////////////////////
+// Miscellaneous utility functions
+//////////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////
+// functions that are common on both platform
+//////////////////////////////////////////////////////////////////////////////
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: ResizePicklingBuff
+//
+// Summary: This function resize the pickling buffer within a pickling
+// control block. Note that this function doesn't copy the content
+// in the old buffer over to the new buffer.
+//
+// Args: PCB *ppcb [in,out] - Pointer to the pickling control block
+// that contains the pickling buffer to be resized.
+// ULONG ulBytesRequired [in] - Number of bytes required in the new
+// pickling buffer.
+//
+// Return: HRESULT - S_OK: Success.
+// E_OUTOFMEMORY: Out of memory.
+//
+// Called by: COAccessControl::CImpAccessControl::Load
+// AddACEToACL
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT ResizePicklingBuff
+(
+PCB *ppcb,
+ULONG ulBytesRequired
+)
+{
+ CHAR *pNewTruePointer;
+
+ if (ulBytesRequired > ppcb->ulPicklingBuffSize)
+ {
+ pNewTruePointer = (CHAR *)LocalMemAlloc((ulBytesRequired + 7));
+ // At most 7 more bytes are needed to align the pickling buffer
+ if (pNewTruePointer == NULL)
+ {
+ return E_OUTOFMEMORY;
+ } // if
+
+ LocalMemFree(ppcb->pTruePicklingBuff);
+
+ ppcb->pTruePicklingBuff = pNewTruePointer;
+ // 8-byte align the pickling buffer
+ ppcb->pPicklingBuff = (char *)(((ULONG)(pNewTruePointer + 7))&~7);
+ ppcb->ulPicklingBuffSize = ulBytesRequired;
+ ppcb->bDirtyHandle = TRUE;
+ } // if
+ return S_OK;
+} // ResizePicklingBuff
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: FreePicklingBuff
+//
+// Summary: This function releases the memmory allocated for a pickling
+// buffer.
+//
+// Args: PCB *ppcb [in] - Pickling control block that contains the pickling
+// buffer to be released
+//
+// Return: void
+//
+// Called by: CleanAllMemoryResources
+// COAccessControl::CImpAccessControl::Load
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+void FreePicklingBuff
+(
+PCB *ppcb
+)
+{
+ LocalMemFree(ppcb->pTruePicklingBuff);
+ ppcb->pPicklingBuff = NULL;
+ ppcb->pTruePicklingBuff = NULL;
+ ppcb->ulPicklingBuffSize = 0;
+
+} // FreePicklingBuff
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: EnlargeStreamACL
+//
+// Summary: This function reallocates the stream ACE array inside a pickle
+// control block to a bigger memory block in order to accomodate the
+// the extra number of stream ACEs needed by the user.
+//
+// Args: PCB *ppcb [in] - Pickle control block containing the stream ACE array
+// to be resized.
+//
+// Return: HRESULT - S_OK: Success
+// E_OUTOFMEMORY: Out of memory
+//
+// Called by: AddACEToACL
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT EnlargeStreamACL
+(
+PCB *ppcb,
+ULONG ulNumOfEntries
+)
+{
+ ULONG ulNewSize;
+ ULONG ulOldSize;
+ STREAM_ACE *pNewStreamACL;
+
+ if (ulNumOfEntries + ppcb->ulNumOfStreamACEs > ppcb->ulMaxNumOfStreamACEs)
+ {
+ ulNewSize = ppcb->ulMaxNumOfStreamACEs + ulNumOfEntries;
+
+ pNewStreamACL = (STREAM_ACE *)midl_user_allocate((ulNewSize + 10)
+ * sizeof(STREAM_ACE));
+ if (pNewStreamACL == NULL)
+ {
+ return E_OUTOFMEMORY;
+ } // if
+
+ if (ppcb->StreamACL.pACL != NULL)
+ {
+ memcpy( pNewStreamACL
+ , ppcb->StreamACL.pACL
+ , ppcb->ulNumOfStreamACEs * sizeof(STREAM_ACE));
+ midl_user_free(ppcb->StreamACL.pACL);
+ } // if
+
+ ppcb->ulMaxNumOfStreamACEs = ulNewSize;
+ ppcb->StreamACL.pACL = pNewStreamACL;
+ } // if
+
+ return S_OK;
+} // EnlargeStreamACL
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: ReadACLFromStream
+//
+// Summary: This function reads an ACL from an IStream object into the
+// STREAM_ACL struture of an pickle control block.
+//
+// Args: IStream *pStm [in] - Pointer to an IStream object containing
+// an ACL.
+// PCB *ppcb [in,out] - Pointer to a PCB structure containing the
+// STREAM_ACL into which the ACL in the IStream
+// object is going to be decoded.
+//
+// Return: HRESULT - S_OK: Success.
+// E_OUTOFMEMORY: The system ran out of memory for some
+// crucial operation.
+// CO_E_SETSERLHNDLFAILED: Unable to (re)set a serialization
+// handle.
+// CO_E_DECODEFAILED: Unable to decode the ACL in the
+// IStream object.
+// CO_E_INCOMPATIBLESTREAMVERSION: The version code in the
+// stream header was not
+// supported by this version
+// of IAccessControl.
+// CO_E_FAILEDTOCLOSEHANDLE: Unable to close a serialization
+// handle.
+// CO_E_EXCEEDSYSACLLIMIT: The number of ACEs in the ACL
+// provided by the user exceeded the
+// limit imposed by the system that
+// is loading the ACL. On Windows 95,
+// the system can handle 32767
+// ACTRL_ACCESS_DENIED ACEs and 32767
+// ACTRL_ACCESS_ALLOWED ACEs. On Windows NT,
+// the system can only handle 32767
+// ACTRL_ACCESS_DENIED and ACTRL_ACCESS_ALLOWED ACEs
+// combined.
+// E_INVALIDARG: This method will return E_INVALIDARG if
+// either
+// a) the ACL in the stream provided by the
+// user contains an invalid access mask, or
+// b) one of STREAM_ACE structure in the ACL
+// provided by the user contains a null
+// pTrusteeName pointer.
+// CO_E_ACESINWRONGORDER: Not all ACTRL_ACCESS_DENIED ACEs in the ACL
+// provided by the user were arranged
+// in front of the ACTRL_ACCESS_ALLOWED ACEs.
+// CO_E_WRONGTRUSTEENAMESYNTAX: The ACL provided by the user
+// contained a trustee name
+// string that didn't conform
+// to the <Domain>\<Account>
+// syntax.
+// CO_E_LOOKUPACCNAMEFAILED: (Window NT only) The system call,
+// LookupAccountName, failed. The user can
+// call GetLastError to obtain extended error
+// information.
+// CO_E_NOMATCHINGSIDFOUND: No matching security identifier
+// could be found for one of the
+// trustee name specified by the
+// client.
+//
+// Called by: COAccessControl:CImpAccessControl::Load
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT ReadACLFromStream
+(
+IStream *pStm,
+PCB *ppcb
+#ifndef _CHICAGO_
+,ACL_DESCRIPTOR *pACLDesc
+#endif
+)
+{
+ HRESULT hr = S_OK;
+ ULONG ulBuffSize = 0;
+ STREAM_HEADER StreamHeader;
+#ifndef _CHICAGO_
+ ULONG ulTotalSIDSize;
+ ULONG ulEstAdditionalSIDSize;
+#endif
+
+ if (FAILED(hr = ResizePicklingBuff(ppcb, g_ulHeaderSize)))
+ {
+ return hr;
+ } // if
+
+ // Set up fixed buffer decoding handle
+ if ( MesDecodeBufferHandleCreate( ppcb->pPicklingBuff
+ , g_ulHeaderSize
+ , &(ppcb->PickleHandle)) != RPC_S_OK )
+ {
+ return CO_E_SETSERLHNDLFAILED;
+ } // if
+
+ if (FAILED(hr = pStm->Read((void *)(ppcb->pPicklingBuff), g_ulHeaderSize, NULL)))
+ {
+ return hr;
+ } // if
+
+ // Decode the stream header
+ RpcTryExcept
+ {
+ STREAM_HEADER_Decode(ppcb->PickleHandle, &StreamHeader);
+ }
+ RpcExcept(1)
+ {
+ return CO_E_DECODEFAILED;
+ }
+ RpcEndExcept
+
+ if (StreamHeader.ulStreamVersion != STREAM_VERSION)
+ {
+ return CO_E_INCOMPATIBLESTREAMVERSION;
+ } // if
+
+ ulBuffSize = StreamHeader.ulPickledSize;
+
+ // Allocate a buffer that is big enough to hold the
+ // the stream
+ if (FAILED(hr = ResizePicklingBuff(ppcb, ulBuffSize + 800)))
+ {
+ return hr;
+ } // if
+
+ if(FAILED(hr = pStm->Read((void *)(ppcb->pPicklingBuff), ulBuffSize, NULL)))
+ {
+ return hr;
+ } // if
+
+ // Re-create a decoding handle
+ if (MesBufferHandleReset( ppcb->PickleHandle
+ , MES_FIXED_BUFFER_HANDLE
+ , MES_DECODE
+ , &(ppcb->pPicklingBuff)
+ , ppcb->ulPicklingBuffSize
+ , &(ppcb->ulBytesUsed)) != RPC_S_OK)
+ {
+ return CO_E_SETSERLHNDLFAILED;
+ } // if
+
+ // Decode the stream content into the stream ACL
+ RpcTryExcept
+ {
+ STREAM_ACL_Decode(ppcb->PickleHandle, &(ppcb->StreamACL));
+ }
+ RpcExcept(1)
+ {
+ return CO_E_DECODEFAILED;
+ }
+ RpcEndExcept
+
+ ppcb->ulBytesUsed = ulBuffSize;
+
+ // Free the decoding handle
+ hr = MesHandleFree(ppcb->PickleHandle);
+ ppcb->PickleHandle = NULL;
+ if (hr != RPC_S_OK)
+ {
+ return CO_E_FAILEDTOCLOSEHANDLE;
+ } // if
+
+ ppcb->bPickled = TRUE;
+
+ // Validate the stream ACL
+#ifdef _CHICAGO_
+ if(FAILED(hr = ValidateAndFixStreamACL(&(ppcb->StreamACL))))
+#else
+ if(FAILED(hr = ValidateAndFixStreamACL( &(ppcb->StreamACL)
+ , &ulTotalSIDSize
+ , &ulEstAdditionalSIDSize)))
+#endif
+ {
+ if((hr != CO_E_NOMATCHINGSIDFOUND) && (hr != CO_E_LOOKUPACCNAMEFAILED))
+ {
+ return hr;
+ } // if
+ } // if
+
+#ifndef _CHICAGO_
+ // Windows NT, the size of the ACL may have changed after
+ // fixing the stream ACL so we may have to reallocate the
+ // pickling buffer
+ if (ulEstAdditionalSIDSize > 0)
+ {
+ if(FAILED(hr = ResizePicklingBuff( ppcb
+ , ppcb->ulBytesUsed
+ + ulEstAdditionalSIDSize
+ + 800)))
+ {
+ return hr;
+ } // if
+ ppcb->bPickled = FALSE;
+ } // if
+
+ pACLDesc->ulSIDSize = ulTotalSIDSize;
+
+#endif
+ return hr;
+} // ReadACLFromStream
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: AddACEToStreamACL
+//
+// Summary: This function inserts a STREAM_ACE structure into an existing
+// STREAM_ACE array in a PCB structure. This function assumes that
+// the STREAM_ACL inside the pcb is large enough to hold the new entry.
+//
+// Args: STREAM_ACE *pStreamACE [in] - Pointer to the StreamACE structure to be added
+//
+// PCB *ppcb [in,out] - Pointer to the pickle control block that contains
+// the stream ACL to which the new stream ACE is added.
+//
+// Return: void
+//
+// Called by: COAccessControl:CImpAccessControl::GrantAccessRights
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+void AddACEToStreamACL
+(
+STREAM_ACE *pStreamACE,
+PCB *ppcb
+)
+{
+ STREAM_ACE *pLastEntry; // Pointer to the last ACE with the specified
+ // access mode
+ STREAM_ACE *pInsertionPoint; // Pointer to STREAM_ACE slot in the STREAM_ACE
+ // array that the new STREAM_ACE structure will be
+ // inserted.
+
+ pLastEntry = ppcb->StreamACL.pACL
+ + ppcb->ulNumOfStreamACEs;
+ if (pStreamACE->grfAccessMode == ACTRL_ACCESS_DENIED)
+ {
+ pInsertionPoint = ppcb->StreamACL.pACL
+ + ppcb->StreamACL.ulNumOfDenyEntries;
+ memcpy(pLastEntry, pInsertionPoint, sizeof(STREAM_ACE));
+ ppcb->StreamACL.ulNumOfDenyEntries++;
+ }
+ else
+ {
+ pInsertionPoint = pLastEntry;
+ ppcb->StreamACL.ulNumOfGrantEntries++;
+ }
+
+ memcpy(pInsertionPoint, pStreamACE, sizeof(STREAM_ACE));
+ ppcb->ulNumOfStreamACEs++;
+
+} // AddACEToStreamACL
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: IsValidAccessMask
+//
+// Summary: This function checks if an access permission mask provided by
+// the user is valid or not.
+//
+// Args: DWORD stdmask [in] - Standard mask to be validated.
+//
+// Return: BOOL - TRUE: The mask is valid
+// FALSE: Otherwise
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+BOOL IsValidAccessMask
+(
+DWORD stdmask
+)
+{
+ return ((stdmask & ~COM_RIGHTS_ALL) ? FALSE : TRUE);
+} // IsValidAccessMask
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: DeleteACEFromStreamACL
+//
+// Summary: This function remove all the ACEs that matches the input trustee
+// name from the stream ACL.
+//
+// Args: LPWSTR pTrustee [in] - Pointer to the trustee string that identifies
+// the ACE to be removed from the stream ACL.
+// ULONG AccessMode [in] - Access mode of the entry that the
+// the caller is interested in removing.
+// SID_TRUSTEE *pSIDTrustee [out] - (Windows NT only) Pointer to
+// a SID_TRUSTEE structure. This structure is used to pass
+// out the string name and the SID of first ACE removed from
+// the STREAM_ACL. These two pieces of information are
+// used by the caller to update the cache and the
+// caller must free the memory for the SID and
+// trustee name afterwards.
+// PCB *ppcb [in,out] - Pointer to the pickle control block which
+// contains a STREAM_ACL structure.
+//
+// Return: BOOL FALSE: Successful completion of the operation but the trustee
+// could not be found in the relevant portion of the
+// STREAM_ACE array inside the STREAM_ACL structure.
+// TRUE: Successful completion of the operation. All the
+// ACEs that have a matching trustee name from the
+// relevant portion of STREAM_ACE array.
+//
+// Called by: COAccessControl::CImpAccessControl::RevokeAccessRights.
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+BOOL DeleteACEFromStreamACL
+(
+PTRUSTEE_W pTrustee,
+ULONG AccessMode,
+#ifndef _CHICAGO_
+ACL_DESCRIPTOR *pACLDesc,
+#endif
+PCB *ppcb
+)
+{
+ ULONG i; // Loop counter
+ STREAM_ACE *pStreamACE; // Pointer for traversing the array
+ // of STREAM_ACE structures inside the
+ // STREAM_ACL structure of the pickle control block.
+ STREAM_ACE *pLastEntry; // Pointer to the 'last' ACE with the
+ // the specified access mode.
+ ULONG *pulNumOfEntries; // The total number of ACEs in the STREAM_ACL
+ // structure with the specified
+ // acces mode.
+ BOOL bResult = FALSE; // Internal function return code.
+
+ switch (AccessMode)
+ {
+ case ACTRL_ACCESS_DENIED:
+ pulNumOfEntries = &(ppcb->StreamACL.ulNumOfDenyEntries);
+ pStreamACE = ppcb->StreamACL.pACL;
+ break;
+ case ACTRL_ACCESS_ALLOWED:
+ pulNumOfEntries = &(ppcb->StreamACL.ulNumOfGrantEntries);
+ pStreamACE = ppcb->StreamACL.pACL
+ + ppcb->StreamACL.ulNumOfDenyEntries;
+ break;
+ } // switch
+
+ pLastEntry = ppcb->StreamACL.pACL
+ + ppcb->StreamACL.ulNumOfGrantEntries
+ + ppcb->StreamACL.ulNumOfDenyEntries - 1;
+
+ for (i = 0; i < *pulNumOfEntries ; i++ )
+ {
+
+ // The following while loop is necessary to handle
+ // cases where the matching STREAM_ACEs are bunched
+ // up at the 'end' of the relevant portion of the
+ // STREAM_ACE array.
+#ifdef _CHICAGO_
+ while( (i < *pulNumOfEntries) &&
+ (lstrcmpiW( pTrustee->ptstrName
+ , pStreamACE->pTrusteeName) == 0))
+
+#else
+ while( (i < *pulNumOfEntries) &&
+ (((pTrustee->TrusteeForm == TRUSTEE_IS_NAME) &&
+ (lstrcmpiW( pTrustee->ptstrName
+ , pStreamACE->pTrusteeName) == 0)) ||
+ ((pTrustee->TrusteeForm == TRUSTEE_IS_SID) &&
+ (pStreamACE->pSID != NULL &&
+ EqualSid( (PSID)(pTrustee->ptstrName)
+ , (PSID)(pStreamACE->pSID))))))
+#endif
+ {
+ (*pulNumOfEntries)--;
+ ppcb->ulNumOfStreamACEs--;
+#ifndef _CHICAGO_
+ if (pStreamACE->pSID != NULL)
+ {
+ pACLDesc->ulSIDSize -= GetLengthSid(pStreamACE->pSID);
+ midl_user_free(pStreamACE->pSID);
+ } // if
+#endif
+ midl_user_free(pStreamACE->pTrusteeName);
+ switch(AccessMode)
+ {
+ case ACTRL_ACCESS_DENIED:
+ if (i < (*pulNumOfEntries))
+ {
+ memcpy( pStreamACE
+ , ppcb->StreamACL.pACL + *pulNumOfEntries
+ , sizeof(STREAM_ACE));
+ } // if
+ memcpy( ppcb->StreamACL.pACL + *pulNumOfEntries
+ , pLastEntry
+ , sizeof(STREAM_ACE));
+
+ break;
+ case ACTRL_ACCESS_ALLOWED:
+ if (i < (*pulNumOfEntries))
+ {
+ memcpy(pStreamACE, pLastEntry, sizeof(STREAM_ACE));
+ } // if
+ break;
+ } // switch
+
+ memset(pLastEntry, 0, sizeof(STREAM_ACE));
+ pLastEntry--;
+ bResult = TRUE;
+ } // while
+ pStreamACE++;
+ } // for
+ return bResult;
+
+} // DeleteACEFromStreamACL
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: MapStreamACLToAccessList
+//
+// Summary: This function maps a stream ACL to an array of
+// ACTRL_ACCESS_ENTRY structures. This function allocates all
+// memory needed for the output access list. It cleans up all
+// memory in case of error.
+//
+// Return: HRESULT S_OK: Succeeded
+// E_OUTOFMEMORY: The system ran out of memory for allocating
+// the trustee identifiers to be returned.
+//
+// Called by: COAccessControl::CImpAccessControl::GetAllAccessRights
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT MapStreamACLToAccessList
+(
+PCB *ppcb,
+PACTRL_ACCESSW *ppAccessList
+)
+{
+ PACTRL_ACCESSW pAccessList;
+ PACTRL_PROPERTY_ENTRYW pProperty;
+ PACTRL_ACCESS_ENTRY_LISTW pEntryList;
+ PACTRL_ACCESS_ENTRYW pEntry;
+ PACTRL_ACCESS_ENTRYW pCurrEntry;
+ char *pTrusteeName;
+
+ STREAM_ACE *pStreamACEsPtr; // Pointer for stepping through
+ // the stream ACL
+ ULONG i = 0;
+ LPWSTR pwszName; // Pointer to the trustee name
+ // inside the stream ACE of the
+ // current iteration
+ ULONG ulNumOfEntries; // Total number of stream ACEs to map
+ ULONG ulSize;
+
+ // Compute the amount of memory needed for the trustee names and sids.
+ ulNumOfEntries = ppcb->ulNumOfStreamACEs;
+ pStreamACEsPtr = ppcb->StreamACL.pACL;
+ ulSize = 0;
+ for (i = 0; i < ulNumOfEntries; i++)
+ {
+#ifndef _CHICAGO_
+ if(pStreamACEsPtr->TrusteeForm == TRUSTEE_IS_NAME)
+ {
+#endif
+ ulSize += (lstrlenW(pStreamACEsPtr->pTrusteeName) + 1) *
+ sizeof(WCHAR);
+#ifndef _CHICAGO_
+ }
+ else
+ {
+ ulSize += GetLengthSid((PISID)pStreamACEsPtr->pSID);
+ } // if
+#endif
+ pStreamACEsPtr++;
+ } // for
+
+ // Allocate memory for everything
+ ulSize += sizeof(ACTRL_ACCESSW) + sizeof(ACTRL_PROPERTY_ENTRYW) +
+ sizeof(ACTRL_ACCESS_ENTRY_LISTW) +
+ sizeof(ACTRL_ACCESS_ENTRYW) * ulNumOfEntries;
+ pAccessList = (PACTRL_ACCESSW) LocalMemAlloc( ulSize );
+ if (pAccessList == NULL)
+ {
+ *ppAccessList = NULL;
+ return E_OUTOFMEMORY;
+ }
+ pProperty = (PACTRL_PROPERTY_ENTRYW) (pAccessList + 1);
+ pEntryList = (PACTRL_ACCESS_ENTRY_LISTW) (pProperty + 1);
+ if (ulNumOfEntries != 0)
+ {
+ pEntry = (PACTRL_ACCESS_ENTRYW) (pEntryList + 1);
+ pTrusteeName = (char *) (pEntry + ulNumOfEntries);
+ }
+ else
+ {
+ pEntry = NULL;
+ }
+
+ // Initialize the top three levels of structures.
+ pAccessList->cEntries = 1;
+ pAccessList->pPropertyAccessList = pProperty;
+ pProperty->lpProperty = NULL;
+ pProperty->pAccessEntryList = pEntryList;
+ pProperty->fListFlags = 0;
+ pEntryList->cEntries = ulNumOfEntries;
+ pEntryList->pAccessList = pEntry;
+
+ pCurrEntry = pEntry;
+ pStreamACEsPtr = ppcb->StreamACL.pACL;
+ for (i = 0; i < ulNumOfEntries; i++)
+ {
+ pwszName = pStreamACEsPtr->pTrusteeName;
+
+ // On Windows 95, the only form of trustee identifier supported is
+ // a Unicode string while a security identifier or a Unicode string
+ // can be used to specify a trustee on Windows NT.
+#ifndef _CHICAGO_
+ if(pStreamACEsPtr->TrusteeForm == TRUSTEE_IS_NAME)
+ {
+#endif
+ ulSize = (lstrlenW(pwszName) + 1) * sizeof(WCHAR);
+ memcpy( pTrusteeName, pwszName, ulSize );
+#ifndef _CHICAGO_
+ }
+ else
+ {
+ ulSize = GetLengthSid((PISID)pStreamACEsPtr->pSID);
+ CopySid(ulSize, (PSID)pTrusteeName, pStreamACEsPtr->pSID);
+ } // if
+#endif
+ pCurrEntry->Trustee.ptstrName = (WCHAR *) pTrusteeName;
+ pCurrEntry->Trustee.TrusteeType = pStreamACEsPtr->TrusteeType;
+ pCurrEntry->Trustee.TrusteeForm = pStreamACEsPtr->TrusteeForm;
+ pCurrEntry->Trustee.pMultipleTrustee = NULL; // Not supported
+ pCurrEntry->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; // Not supported
+ pCurrEntry->Access = pStreamACEsPtr->grfAccessPermissions;
+ pCurrEntry->ProvSpecificAccess = 0;
+ pCurrEntry->Inheritance = NO_INHERITANCE; // Not supported
+ pCurrEntry->lpInheritProperty = NULL;
+ pCurrEntry->fAccessFlags = pStreamACEsPtr->grfAccessMode;
+ pTrusteeName += ulSize;
+ pStreamACEsPtr++;
+ pCurrEntry++;
+ } // for
+
+ *ppAccessList = pAccessList;
+ return S_OK;
+} // MapStreamACLToAccessList
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: CleanAllMemoryResources()
+//
+// Summary: This function frees all the memory allocated for an initialized
+// COAccessControl object. On Windows 95, this function will release
+// all the memory allocated for the ACL_DESCRIPTOR structure except
+// for the two resource name in the LAN Manager ACL embedded in the
+// ACL_DESCRIPTOR structure. The idea behind such an arrange is to
+// reuse existing resource as much as possible so that performanace
+// can be improved.
+//
+// Args: ACL_DESCRIPTOR *pACLDesc [in,out] - This structure describes
+// how DCOM IAccessControl implementaion object packages
+// platform specific ACL.
+// PCB *ppcb [in,out] - The pickling control block owned by the
+// same object.
+//
+// Return: void
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+void CleanAllMemoryResources
+(
+ACL_DESCRIPTOR *pACLDesc,
+PCB *ppcb
+)
+{
+ // Clean up old Stream ACL
+ FreePicklingBuff(ppcb);
+ MesHandleFree(ppcb->PickleHandle);
+ CleanUpStreamACL(&(ppcb->StreamACL));
+
+ // Cleanup the ACL images
+#ifdef _CHICAGO_
+ CleanUpACLImage(&(pACLDesc->DenyACL));
+ CleanUpACLImage(&(pACLDesc->GrantACL));
+#else
+ LocalMemFree(pACLDesc->pACLBuffer);
+ LocalMemFree(pACLDesc->SecDesc.Owner);
+ LocalMemFree(pACLDesc->SecDesc.Group);
+#endif
+
+} // CleanAllMemoryResources
+
+#ifdef _CHICAGO_
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: ComputeEffectiveAccess, Chicago version
+//
+// Summary: Given the trustee name, and the ACL descritpor, this function
+// computes the effective access rights that a the trustee has.
+//
+// Args: LPWSTR pTrustee [in] - Pointer to a NULL terminated Unicode string
+// that represents the trustee.
+// DWORD *pEffectiveRights [out] - Reference to a 32-bit bit mask that
+// represents the set of access rights
+// the trustee has.
+// ACL_DESCRIPTOR *pACLDesc [in] - Platform dependent representation
+// of the ACL.
+//
+// Return: HRESULT - S_OK: Succeeded.
+// E_OUTOFMEMORY: Not enough memory to transform the Unicode
+// trustee string to a multibyte string.
+// CO_E_CONVERSIONFAILED: WideCharToMultiByte returned
+// error. The user can call
+// GetLastError to get extended
+// error information.
+// CO_E_NETACCESSAPIFAILED: One one the NetAccess functions
+// called in this function
+// returned an error code.
+//
+// Called by: COAccessControl::CImpAccessControl::IsAccessAllowed
+// COAccessControl::CImpAccessControl::GetEffectiveAccessRights
+//
+// Notes: NetAccessAdd on some machines adds "*" when you call with a list
+// with no entries.
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT ComputeEffectiveAccess
+(
+LPWSTR pTrustee,
+DWORD *pEffectivePermissions,
+ACL_DESCRIPTOR *pACLDesc
+)
+{
+ CHAR *pName;
+ API_RET_TYPE uReturnCode;
+ CHAR *pResource;
+ access_info_1 *pACLHeader;
+ USHORT uResult;
+ HRESULT hr = S_OK;
+
+ if(FAILED(hr = WStringToMBString(pTrustee, &pName)))
+ {
+ return hr;
+ }
+ // Start checking from the list of deny entries
+
+ // See if the deny mode list is dirty, and update the registry if necessary
+ pACLHeader = pACLDesc->DenyACL.pACL;
+ pResource = pACLHeader->acc1_resource_name;
+
+ // Skip this if the ACL is empty.
+ if (pACLHeader->acc1_count != 0)
+ {
+ if (pACLDesc->DenyACL.bDirtyACL)
+ {
+ NetAccessDel(NULL, pResource);
+
+ // Notice that NetAccessAdd puts data into the registry
+ if( NERR_Success != NetAccessAdd( NULL
+ , 2
+ , (char *)pACLHeader
+ , sizeof(access_info_1)
+ + pACLHeader->acc1_count
+ * sizeof(access_list_2)))
+ {
+ hr = CO_E_NETACCESSAPIFAILED;
+ goto Error;
+ } // if
+ pACLDesc->DenyACL.bDirtyACL = FALSE;
+ } // if
+
+ if ( NERR_Success != NetAccessCheck( NULL
+ , pName
+ , pResource
+ , CHICAGO_RIGHTS_EXECUTE
+ , &uResult) )
+ {
+ hr = CO_E_NETACCESSAPIFAILED;
+ goto Error;
+ } // if
+
+ // Negate the result of access checking on the deny list.
+ // I.e. if the result is positive, the user is explicitly denied
+ // access to the object.
+
+ if (uResult == 0)
+ {
+ *pEffectivePermissions = 0; // hard coded to zero
+ LocalMemFree(pName);
+ return S_OK;
+ } // if
+ }
+
+ // If the previous result is negative, we have to
+ // move on to see if the user is granted access through
+ // the grant ACL.
+ pACLHeader = pACLDesc->GrantACL.pACL;
+ pResource = pACLHeader->acc1_resource_name;
+
+ // If there are no Allow ACEs, deny access.
+ if (pACLHeader->acc1_count == 0)
+ {
+ *pEffectivePermissions = 0; // hard coded to zero
+ LocalMemFree(pName);
+ return S_OK;
+ } // if
+
+ // See if the grant mode list is dirty and update the registry if necessary
+ if (pACLDesc->GrantACL.bDirtyACL)
+ {
+ NetAccessDel(NULL, pResource);
+
+ if( NERR_Success != NetAccessAdd( NULL
+ , 2
+ , (char *)pACLHeader
+ , sizeof(access_info_1)
+ + pACLHeader->acc1_count
+ * sizeof(access_list_2)))
+ {
+ hr = CO_E_NETACCESSAPIFAILED;
+ goto Error;
+ } // if
+ pACLDesc->GrantACL.bDirtyACL = FALSE;
+ } // if
+
+ if ( NERR_Success != NetAccessCheck( NULL
+ , pName
+ , pResource
+ , CHICAGO_RIGHTS_EXECUTE
+ , &uResult) )
+ {
+ hr = CO_E_NETACCESSAPIFAILED;
+ goto Error;
+ } // if
+
+ if (uResult == 0)
+ {
+ *pEffectivePermissions = COM_RIGHTS_EXECUTE;
+ }
+ else
+ {
+ *pEffectivePermissions = 0;
+ } // if
+
+
+Error:
+ LocalMemFree(pName);
+ return hr;
+
+} // ComputeEffectiveAccess
+#else
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: ComputeEffectiveAccess, NT version
+//
+// Summary: Given a handle to an access token representing a user, an
+// ACL_DESCRIPTOR structure and a STREAM_ACL structure , this function
+// will compute the effective access permissions that the user
+// represented by the access token has.
+//
+// Args: ACL_DESCRIPTOR *pACLDesc [in,out] - Pointer to the NT version of the
+// ACL_DESCRIPTOR structure. Thsi structure should contain
+// a buffer for the NT ACL structure, a NT security
+// descriptor, a control flag and size information.
+// STREAM_ACL *pStreamACL [in] - It may be the case that the STREAM_ACL
+// structure of an DCOM IAccessControl implementation object
+// has not been mapped into the security descriptor's dacl
+// inside the ACL_DESCRIPTOR, so it is necessary that object
+// that calls this function to pass in its STREAM_ACL
+// structure. In fact, this is only place where a STREAM_ACL
+// will be mapped into a dacl.
+// HANDLE TokenHandle [in] - This should be the access token of the
+// user that the caller wants to compute the effective access
+// permissions for.
+// DWORD *pdwRights [out] - Address of the effective access permissions
+// that the user corresponding to the
+// access token specified in the TokenHandle
+// has on the secured object.
+//
+// Return: HRESULT - S_OK: Succeeded.
+// E_OUTOFMEMORY: The system ran out of memory for
+// allocating the NT ACL.
+// CO_E_FAILEDTOSETDACL: SetSecurityDescriptorDacl returned
+// false inside PutStreamACLIntoSecDesc.
+// The client of this method can call
+// GetLastError to get extended error
+// information.
+// CO_E_ACCESSCHECKFAILED: The system function, AccessCheck,
+// returned FALSE in
+// ComputeEffectiveAccess. The
+// caller of this method can call
+// GetLastError to obtain extended
+// error information.
+//
+//
+// Called by: COAccessControl:CImpAccessControl:GetEffAccRightsUsingName
+// COAccessControl:CImpAccessControl:GetEffAccRightsUsingSID
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT ComputeEffectiveAccess
+(
+ACL_DESCRIPTOR *pACLDesc,
+STREAM_ACL *pStreamACL,
+HANDLE TokenHandle,
+DWORD *pdwRights
+)
+{
+ HRESULT hr = S_OK;
+ ACCESS_MASK AccessMaskOut = 0; // Access mask returned by
+ // AccessCheck
+ ACCESS_MASK AccessMaskIn = 0; // Access permissions to check for
+ BOOL bAccessStatus; // Access checking status.
+ // TRUE - Access granted.
+ // FALSE - Access denied.
+ // This function doesn't really care
+ // about this result, all it wants
+ // is the set the of permissions
+ // that a user effectively has.
+ DWORD dwSetLen; // Length of the privilege set.
+
+ dwSetLen = sizeof(gDummyPrivilege);
+
+ // If the ACL has not been set into the security
+ // security inside the ACL descriptor, do so now.
+ if (pACLDesc->bDirtyACL)
+ {
+ if(FAILED(hr = PutStreamACLIntoSecDesc( pStreamACL
+ , pACLDesc)))
+ {
+ return hr;
+ } // if
+
+ } // if
+
+ // Call access check
+ if(!AccessCheck( &(pACLDesc->SecDesc)
+ , TokenHandle
+ , NT_RIGHTS_ALL
+ , &gDummyMapping
+ , &gDummyPrivilege
+ , &dwSetLen
+ , &AccessMaskOut
+ , &bAccessStatus))
+ {
+ return CO_E_ACCESSCHECKFAILED;
+ } // if
+
+ // Convert the NT access mask back to IAccessControl access mask.
+ NTMaskToStandardMask(&AccessMaskOut, pdwRights);
+
+ return S_OK;
+
+
+} // ComputeEffectiveAccess
+
+#endif
+
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: ValidateAndTransformAccReqList
+//
+// Summary: This function validates the fields inside a list of ACCESS_REQUEST
+// structures and transform it into a list of stream ACE structures.
+// This function is
+// also responsible for estimating the total size of the STREAM_ACE
+// structures returned to the caller if they are serialized into a
+// buffer using RPC serialization service. On WIndows 95, this function
+// will set up an array of access_list_2 structures representing the
+// input access request list for the caller. On Windows NT, this function
+// will lookup the SID or the trustee name for each access request depending
+// on which one is specified by the caller.
+//
+// Args: PACCESS_REQUEST_W pAccReqList [in] - Pointer to the access request to
+// be validated and transformed.
+// ULONG ulNumOfRequestIn [in] - Number of ACCESS_REQUEST_W structures
+// STREAM_ACE **ppStreamACEs [out] - Pointer to an array of stream ACEs
+// transformed from the access request list. The array of
+// STREAM_ACE structures and the SID and trustee name inside
+// each of the STREAM_ACE structure returned are allocated by
+// this function using midl_user_allocate so the caller should
+// release the memory allocated for these structures using
+// midl_user_allocate.
+// access_list_2 **ppACEs [out] - (Chicago only)Address of a pointer to
+// an array of access_list_2 structures to be returned to the
+// caller. Notice that this function will allocate memory
+// for the array and the User/group name in each of
+// access_list_2 structure returned using LocalMemAlloc.
+// Once the caller receives this output parameter, it
+// becomes the caller's responsiblility to release the
+// memory allocated for this structure when it is no
+// longer in use.
+// ULONG *pulEstPickledSize [out] - Pointer to the estimated number of
+// bytes needed for serializing the
+// STREAM_ACE structures returned. The
+// estimated
+// number of bytes required to serialize
+// a STREAM_ACE structure into a buffer
+// using RPC serialization service is
+// computed by the folowing formula:
+// Size of the Unicode trustee string + Size of the SID + Size of the
+// STREAM_ACE structure + 48
+// The number 48 is an arbitrary large number that should account for
+// all the extra space required by RPC to align the data structure and
+// to add additional information to the header.
+//
+// Return: HRESULT - S_OK: Succeeded.
+// E_OUTOFMEMORY: The system ran out of memory for some
+// crucial operations.
+// E_INVALIDARG: The access mask in one of the
+// ACCESS_REQUEST_W structures was invalid of
+// the TRUSTEE structure provided by the user
+// was invalid.
+// CO_E_CONVERSIONFAILED: WideCharToMultiByte returned zero.
+// The caller can get extended error
+// information by calling GetLastError.
+// CO_E_INVALIDSID: At least one of the TRUSTEE_W structures
+// specified by the user contained an invalid
+// security identifier.
+// CO_E_NOMATCHINGNAMEFOUND: No matching account name
+// could be found for one of the security identifiers
+// specified by the client.
+// CO_E_LOOKUPACCSIDFAILED: The system function,
+// LookupAccountSID, failed. The client can call
+// GetLastError to obtain extended error inforamtion.
+// CO_E_NOMATCHINGSIDFOUND: No matching security identifier
+// could be found for one of the
+// trustee name specified by the
+// client.
+// CO_E_LOOKUPACCNAMEFAILED: The system function,
+// LookupAccountName, failed. The client can call
+// GetLastError to obtain extended error information.
+//
+// Called by: COAccessControl::CImpAccessControl::GrantAccessRights
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT ValidateAndTransformAccReqList
+(
+PACTRL_ACCESSW pAccessList,
+STREAM_ACE **ppStreamACEs,
+void **ppACEs,
+ULONG *pulEstPickledSize,
+ULONG *pcGrant,
+ULONG *pcDeny
+)
+{
+ HRESULT hr = S_OK;
+ STREAM_ACE *pStreamACEs; // Pointer to an array of stream ACEs
+ STREAM_ACE *pStreamACEsPtr; // Pointer for traversing the
+ // array of stream ACEs
+ PACTRL_ACCESS_ENTRYW pCurrEntry; // Pointer for traversing the
+ // access request list
+ PTRUSTEE_W pTrustee; // Pointer to the TRUSTEE structure in
+ // the access request structure
+#ifdef _CHICAGO_
+ DWORD dwLastError; // GetLastError return code holder
+ access_list_2 *pACEs; // Pointer to an array of access_list_2
+ // structures to be returned to the caller
+ access_list_2 *pACEsPtr; // Pointer for traversing the array of
+ // access_list_2 structures.
+#else
+ ULONG ulSIDLen; // Length of the SID that is currently being
+ // examined.
+#endif
+ ULONG ulStrLen; // Length of the trustee string in number
+ // of Unicode characters
+ ULONG i,j; // Loop counters
+ ULONG ulEstPickledSize = 0; // Estimated pickled size of the access
+ // requests if they all turn into stream ACEs
+ TRUSTEE_TYPE TrusteeType = TRUSTEE_IS_UNKNOWN;
+ ULONG cCount;
+
+ // Initialize ACE counts.
+ *pcGrant = 0;
+ *pcDeny = 0;
+
+ // Validate the top three levels of the structure.
+ if (pAccessList == NULL ||
+ pAccessList->cEntries != 1 ||
+ pAccessList->pPropertyAccessList == NULL ||
+ pAccessList->pPropertyAccessList->lpProperty != NULL ||
+ pAccessList->pPropertyAccessList->fListFlags != 0 ||
+ pAccessList->pPropertyAccessList->pAccessEntryList == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ cCount = pAccessList->pPropertyAccessList->pAccessEntryList->cEntries;
+ pCurrEntry = pAccessList->pPropertyAccessList->pAccessEntryList->pAccessList;
+ if (cCount != 0 && pCurrEntry == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ // Allocate an array of stream ACEs
+ pStreamACEs = (STREAM_ACE *)LocalMemAlloc( sizeof(STREAM_ACE) * cCount);
+ if (pStreamACEs == NULL)
+ {
+ return E_OUTOFMEMORY;
+ } // if
+
+#ifdef _CHICAGO_
+ pACEs = (access_list_2 *)midl_user_allocate( sizeof(access_list_2)
+ * cCount);
+
+ if (pACEs == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ }
+ pACEsPtr = pACEs;
+#endif
+
+ // Map the access requests to stream ACEs and validates the fields in
+ // of the access requests as we go along
+ pStreamACEsPtr = pStreamACEs;
+ for (i = 0; i < cCount; i++)
+ {
+ pTrustee = &(pCurrEntry->Trustee);
+ TrusteeType = pTrustee->TrusteeType;
+
+ // Validate this entry.
+ if (!IsValidAccessMask(pCurrEntry->Access))
+ {
+ hr = E_INVALIDARG;
+ goto Error;
+ } // if
+ if(FAILED(hr = ValidateTrustee(pTrustee)))
+ {
+ goto Error;
+ }
+ if (pCurrEntry->ProvSpecificAccess != 0 ||
+ pCurrEntry->Inheritance != NO_INHERITANCE ||
+ pCurrEntry->lpInheritProperty != NULL ||
+ (pCurrEntry->fAccessFlags != ACTRL_ACCESS_ALLOWED &&
+ pCurrEntry->fAccessFlags != ACTRL_ACCESS_DENIED))
+ {
+ hr = E_INVALIDARG;
+ goto Error;
+ }
+
+#ifndef _CHICAGO_
+ if (pTrustee->TrusteeForm == TRUSTEE_IS_NAME)
+ {
+#endif
+ ulStrLen = lstrlenW(pTrustee->ptstrName);
+ ulEstPickledSize += (ulStrLen + 1) * sizeof(WCHAR);
+ pStreamACEsPtr->pTrusteeName = (LPWSTR)
+ midl_user_allocate( (ulStrLen + 1) * sizeof(WCHAR));
+ if (pStreamACEsPtr->pTrusteeName == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ }
+
+ memcpy( pStreamACEsPtr->pTrusteeName
+ , pTrustee->ptstrName
+ , sizeof(WCHAR) * (ulStrLen + 1));
+ pStreamACEsPtr->pSID = NULL;
+#ifndef _CHICAGO_
+
+ if (FAILED(hr = GetSIDFromName( (void **)&(pStreamACEsPtr->pSID)
+ , pStreamACEsPtr->pTrusteeName
+ , &TrusteeType)))
+ {
+ LocalMemFree(pStreamACEsPtr->pTrusteeName);
+ goto Error;
+ } // if
+ ulEstPickledSize += GetLengthSid(pStreamACEsPtr->pSID);
+ }
+ else
+ {
+
+ // Copy the SID to the stream ACE strusture
+ ulSIDLen = GetLengthSid((PISID)(pTrustee->ptstrName));
+ ulEstPickledSize += ulSIDLen;
+ pStreamACEsPtr->pSID = (PSTREAM_SID)midl_user_allocate(ulSIDLen);
+ if (pStreamACEsPtr->pSID == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } //if
+ CopySid(ulSIDLen, (PSID)(pStreamACEsPtr->pSID),
+ (PSID)(pTrustee->ptstrName));
+
+ if(FAILED(hr = GetNameFromSID( &(pStreamACEsPtr->pTrusteeName)
+ , (PSID)(pStreamACEsPtr->pSID)
+ , &TrusteeType)))
+ {
+ LocalMemFree(pStreamACEsPtr->pSID);
+ goto Error;
+ } // if
+
+ ulEstPickledSize += lstrlenW(pStreamACEsPtr->pTrusteeName);
+ } // if
+
+#endif
+ pStreamACEsPtr->TrusteeForm = pCurrEntry->Trustee.TrusteeForm;
+ pStreamACEsPtr->grfAccessPermissions = pCurrEntry->Access;
+ pStreamACEsPtr->TrusteeType = TrusteeType;
+ pStreamACEsPtr->grfAccessMode = (ACCESS_MODE) pCurrEntry->fAccessFlags;
+ if (pCurrEntry->fAccessFlags == ACTRL_ACCESS_ALLOWED)
+ {
+ (*pcGrant)++;
+ }
+ else
+ {
+ (*pcDeny)++;
+ }
+ pStreamACEsPtr++;
+
+#ifdef _CHICAGO_
+ if (FAILED(hr = WStringToMBString(pTrustee->ptstrName, &(pACEsPtr->acl2_ugname))))
+ {
+ LocalMemFree(pStreamACEsPtr->pTrusteeName);
+ goto Error;
+ } // if
+ StandardMaskToLANManagerMask( &(pCurrEntry->Access)
+ , &(pACEsPtr->acl2_access));
+ if (pTrustee->TrusteeType == TRUSTEE_IS_GROUP)
+ {
+ pACEsPtr->acl2_access |= ACCESS_GROUP;
+ } // if
+
+ pACEsPtr++;
+#endif
+ pCurrEntry++;
+
+ } // for
+
+#ifdef _CHICAGO_
+ *ppACEs = pACEs;
+#endif
+ *ppStreamACEs = pStreamACEs;
+ *pulEstPickledSize = ulEstPickledSize
+ + cCount
+ * (sizeof(WCHAR)
+ + 48 + sizeof(STREAM_ACE));
+ return S_OK;
+
+Error:
+ pStreamACEsPtr = pStreamACEs;
+#ifdef _CHICAGO_
+ pACEsPtr = pACEs;
+#endif
+
+ // Release the memory allocated for the
+ // trustee strings and SIDs inside the
+ // each of the STREAM_ACE and access_list_2
+ // structures.
+ for ( j = 0; j < i; j++, pStreamACEsPtr++)
+ {
+ LocalMemFree(pStreamACEsPtr->pTrusteeName);
+#ifdef _CHICAGO_
+ LocalMemFree(pACEsPtr->acl2_ugname);
+ pACEsPtr++;
+#else
+ LocalMemFree(pStreamACEsPtr->pSID);
+#endif
+ } // for
+
+#ifdef _CHICAGO_
+ // Release the array of access_list_2 structures
+ if (pACEs != NULL)
+ {
+ LocalMemFree(pACEs);
+
+ } // if
+#endif
+
+ // Release the array of STREAM_ACE structures
+ if (pStreamACEs != NULL)
+ {
+ LocalMemFree(pStreamACEs);
+ }
+ *pulEstPickledSize = 0;
+ *ppStreamACEs = NULL;
+ return hr;
+
+} // ValidateAndTransformAccessRequests
+
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: ValidateAndFixStreamACL
+//
+// Summary: This function validates the fields in a STREAM_ACL structure and all
+// the STREAM_ACE structures that it contains. On Windows 95, this function
+// will make sure that the value of the TrusteeType field in
+// each of the STREAM_ACE structure is TRUSTEE_IS_NAME. On Windows NT,
+// this function will make sure that each STREAM_ACE structure contains
+// both the trustee name and the SID. Besides making sure that both the
+// trustee name and the SID are in every STREAM_ACE structure, this function
+// has to compute the total size in bytes of all the SIDs in the
+// stream ACL and the estimated "pickled" size of all the SIDs that
+// this function has found missing in the original stream ACL on
+// Windows NT.
+//
+// Args: STREAM_ACL *pStreamACL [in] - Pointer to the STREAM_ACL strucutre to be
+// validated.
+// On Windows NT:
+// ULONG *pulTotalSIDSize [out] - Address of the total size of all the SIDs
+// in the stream ACL in bytes. This number
+// is used by other parts of the module to
+// compute the expected size of the NT
+// ACL.
+// ULONG *pulEstAdditionalSIDSize [out] - Address of the estimated total
+// size of all the missing SID
+// that this function has filled-
+// in when they are serialized into
+// a buffer using the RPC serialization
+// service. This number is used
+// by the caller to estimate
+// size of the buffer required to
+// serialize the STREAM_ACL structure.
+// The estimated number of bytes
+// required for serializing each
+// additonal SID is computed by
+// the following formula:
+// Size of the SID + 32
+// Notice that it is neccessary to add extra bytes to the estimate
+// because RPC may need extra bytes for alignment and additional
+// information in the header. 32 is an arbitrary number that should
+// be big enough to accomodate the extra bytes required for alignment
+// and extra header information. Any estimate that produces a number
+// greater than or equal to the actual serialized size of an SID
+// should be considered as good asthe the one provided above.
+//
+// Return: HRESULT - S_OK: Success.
+// CO_E_EXCEEDSYSACLLIMIT: The number of ACEs in the ACL
+// provided by the user exceeded the
+// limit imposed by the system that
+// is loading the ACL. On Windows 95,
+// the system can handle 32767
+// ACTRL_ACCESS_DENIED ACEs and 32767
+// ACTRL_ACCESS_ALLOWED ACEs. On Windows NT,
+// the system can only handle 32767
+// ACTRL_ACCESS_DENIED and ACTRL_ACCESS_ALLOWED ACEs
+// combined.
+// E_INVALIDARG: This function will return E_INVALIDARG if
+// either
+// a) the ACL in the stream provided by the
+// user contains an invalid access mask, or
+// b) one of STREAM_ACE structure in the ACL
+// provided by the user contains a null
+// pTrusteeName pointer.
+// CO_E_ACESINWRONGORDER: Not all ACTRL_ACCESS_DENIED ACEs in the ACL
+// provided by the user were arranged
+// in front of the ACTRL_ACCESS_ALLOWED ACEs.
+// CO_E_WRONGTRUSTEENAMESYNTAX: The ACL provided by the user
+// contained a trustee name
+// string that didn't conform
+// to the <Domain>\<Account>
+// syntax.
+// CO_E_LOOKUPACCNAMEFAILED: (Window NT only) The system call,
+// LookupAccountName, failed. The user can
+// call GetLastError to obtain extended error
+// information.
+// E_OUTOFMEMORY: The system ran out of memory for some
+// crucial operation.
+// CO_E_NOMATCHINGSIDFOUND: (Windows NT only) At least one of the trustee
+// name in the ACL provided by the user had
+// no corresponding security identifier.
+//
+// Called by: ReadACLFromStream
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT ValidateAndFixStreamACL
+(
+#ifdef _CHICAGO_
+STREAM_ACL *pStreamACL
+#else
+STREAM_ACL *pStreamACL,
+ULONG *pulTotalSIDSize,
+ULONG *pulEstAdditionalSIDSize
+#endif
+)
+{
+ ULONG ulNumOfDenyEntries;
+ ULONG ulNumOfEntries;
+ STREAM_ACE *pStreamACEsPtr;
+ ULONG i;
+ ULONG AccessMode;
+ HRESULT hr = S_OK;
+
+#ifndef _CHICAGO_
+ *pulTotalSIDSize = 0;
+ *pulEstAdditionalSIDSize = 0;
+#endif
+
+ AccessMode = ACTRL_ACCESS_DENIED;
+ ulNumOfDenyEntries = pStreamACL->ulNumOfDenyEntries;
+ ulNumOfEntries = ulNumOfDenyEntries + pStreamACL->ulNumOfGrantEntries;
+
+// Chicago cannot handle more than 32767 entries in each list
+#ifdef _CHICAGO_
+ if(ulNumOfDenyEntries > 32767 || pStreamACL->ulNumOfGrantEntries > 32767)
+ {
+ return CO_E_EXCEEDSYSACLLIMIT;
+ } // if
+#else // NT cannot handle more than 32767 entries combined
+ if(ulNumOfEntries > 32767)
+ {
+ return CO_E_EXCEEDSYSACLLIMIT;
+ } // if
+#endif
+
+ for ( i = 0, pStreamACEsPtr = pStreamACL->pACL
+ ; i < ulNumOfEntries
+ ; i++, pStreamACEsPtr++)
+ {
+ if (i == ulNumOfDenyEntries)
+ {
+ AccessMode = ACTRL_ACCESS_ALLOWED;
+ } // if
+
+ if (!IsValidAccessMask(pStreamACEsPtr->grfAccessPermissions) ||
+ ((pStreamACEsPtr->TrusteeType != TRUSTEE_IS_USER) &&
+ (pStreamACEsPtr->TrusteeType != TRUSTEE_IS_GROUP)))
+ {
+ hr = E_INVALIDARG;
+ break;
+ } // if
+ if((ULONG) pStreamACEsPtr->grfAccessMode != AccessMode)
+ {
+ // The stream ACL is either a) not in proper order, or
+ // b) doesn't contain the number of stream ACEs
+ // stated in the header.
+ hr = CO_E_ACESINWRONGORDER;
+ break;
+ } // if
+
+ if (FAILED(hr = ValidateTrusteeString(pStreamACEsPtr->pTrusteeName) ))
+ {
+ break;
+ } // if
+
+#ifdef _CHICAGO_
+ pStreamACEsPtr->TrusteeForm = TRUSTEE_IS_NAME;
+#else
+ if(pStreamACEsPtr->pSID == NULL)
+ {
+ if(!(FAILED(hr = GetSIDFromName( (void **)&(pStreamACEsPtr->pSID)
+ , pStreamACEsPtr->pTrusteeName
+ , &pStreamACEsPtr->TrusteeType))))
+ {
+ // 32 more bytes is added to the estimated pickled size of the SID
+ // because the RPC serialization mechanism may need extra space
+ // in the header and alignment.
+ *pulEstAdditionalSIDSize += GetLengthSid(pStreamACEsPtr->pSID)
+ + 32;
+ } // if
+
+
+ } // if
+ else
+ {
+ if(!IsValidSid(pStreamACEsPtr->pSID))
+ {
+ hr = CO_E_INVALIDSID;
+ break;
+ } // if
+ } // if
+
+ if(pStreamACEsPtr->pSID != NULL)
+ {
+ *pulTotalSIDSize += GetLengthSid(pStreamACEsPtr->pSID);
+ }
+ else
+ {
+ pStreamACEsPtr->TrusteeType = TRUSTEE_IS_UNKNOWN;
+ } // if
+
+#endif
+
+ } // for
+ return hr;
+
+} // ValidateAndFixStreamACL
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: ValidateTrusteeString
+//
+// Summary: This function checks if a trustee string is not NULL.
+//
+// Args: LPWSTR pTrusteeName [in] - Pointer to the trustee name to be
+// validated.
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT ValidateTrusteeString
+(
+LPWSTR pTrusteeName
+)
+{
+ if(pTrusteeName == NULL)
+ {
+ return E_INVALIDARG;
+ } //if
+
+ // If we see the magic string that specifies everyone,
+ // we return S_OK.
+ if(pTrusteeName[0] == L'*' && pTrusteeName[1] == L'\0')
+ {
+ return S_OK;
+ } // if
+
+ // A more sophisticated check can be put in here
+ while(*pTrusteeName != L'\0')
+ {
+ if (*pTrusteeName == L'\\')
+ return S_OK;
+ pTrusteeName++;
+ }
+ return CO_E_WRONGTRUSTEENAMESYNTAX;
+} // ValidateTrusteeString
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: ValidateTrustee
+//
+// Summary: This function validates the fields in a TRUSTEE_Wstructure.
+//
+// Args: PTRUSTEE_W pTrustee [in] - Pointer to the TRUSTEE_W structure
+// to be validated.
+//
+// Return: HRESULT - S_OK: The TRUSTEE structure provided by the user was valid.
+// E_INVALIDARG: The TRUSTEE structure provided by the user
+// contained values that were not supported by
+// the COM implementation of IAccessControl.
+// CO_E_WRONGTRUSTEENAMESYNTAX: The trustee string doesn't
+// contain the '\' character.
+// Windows NT only
+// CO_E_INVALIDSID: At least one of the TRUSTEE_W structures
+// specified by the user contained an invalid
+// security identifier.
+//
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT ValidateTrustee
+(
+PTRUSTEE_W pTrustee
+)
+{
+ HRESULT hr = S_OK;
+
+ if( (pTrustee == NULL) ||
+ (pTrustee->pMultipleTrustee != NULL) ||
+ (pTrustee->MultipleTrusteeOperation != NO_MULTIPLE_TRUSTEE) ||
+#ifdef _CHICAGO_
+ (pTrustee->TrusteeForm != TRUSTEE_IS_NAME) ||
+#else
+ ((pTrustee->TrusteeForm != TRUSTEE_IS_NAME) &&
+ (pTrustee->TrusteeForm != TRUSTEE_IS_SID)) ||
+#endif
+ ((pTrustee->TrusteeType != TRUSTEE_IS_USER) &&
+ (pTrustee->TrusteeType != TRUSTEE_IS_GROUP)) ||
+ (pTrustee->ptstrName == NULL) )
+ {
+ return E_INVALIDARG;
+ }
+
+#ifdef _CHICAGO_
+ if (pTrustee->ptstrName[0] == L'*' &&
+ pTrustee->ptstrName[1] == L'\0' &&
+ pTrustee->TrusteeType != TRUSTEE_IS_GROUP)
+ {
+ return E_INVALIDARG;
+ } // if
+
+#else
+ if (pTrustee->TrusteeForm == TRUSTEE_IS_NAME)
+ {
+#endif
+ if(FAILED(hr = ValidateTrusteeString(pTrustee->ptstrName)))
+ {
+ return hr;
+ }
+#ifndef _CHICAGO_
+ }
+ else
+ {
+ if(!IsValidSid((PSID)(pTrustee->ptstrName)))
+ {
+ return CO_E_INVALIDSID;
+ }
+ } // if
+#endif
+
+ return S_OK;
+} // ValidateTrustee
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: ValidateAccessCheckClient
+//
+// Summary: This function checks to see if the current ORPC client matches
+// the trustee name provided for access checking and it also validates
+// the fields in the TRUSTEE structure.
+//
+// Args: PTRUSTEE_W pTrustee [in] - Pointer to the trustee structure
+// which contains the trustee name for
+// comparison with the name with the current
+// ORPC client.
+//
+// Return: HRESULT S_OK: The TRUSTEE structure provided by the user was valid
+// and it specfied the current ORPC client.
+// CO_E_TRUSTEEDOESNTMATCHCLIENT: The trustee specified by the
+// client was not the current
+// ORPC client.
+// CO_E_FAILEDTOQUERYCLIENTBLANKET: Unable to query for the
+// client's security blanket.
+// CO_E_WRONGTRUSTEENAMESYNTAX: The trustee name inside the
+// TRUSTEE_W structure specified
+// by the user is not of the
+// form <Domain>\<Account Name>.
+// E_INVALIDARG: The TRUSTEE structure provided by the user
+// contained values that were not supported by
+// the COM implementation of IAccessControl.
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT ValidateAccessCheckClient
+(
+PTRUSTEE_W pTrustee
+)
+{
+
+ WCHAR *pwcszClientName; // Pointer to the name of the ORPC client
+ // in multibyte format.
+ HRESULT hr;
+
+ if (FAILED(hr = ValidateTrustee(pTrustee)))
+ {
+ return hr;
+ }
+
+#ifndef _CHICAGO_
+ if (pTrustee->TrusteeForm == TRUSTEE_IS_NAME)
+#endif
+ {
+ if(FAILED(CoQueryClientBlanket( NULL
+ , NULL
+ , NULL
+ , NULL
+ , NULL
+ , (RPC_AUTHZ_HANDLE *)&pwcszClientName
+ , NULL)))
+ {
+ return CO_E_FAILEDTOQUERYCLIENTBLANKET;
+ } // if
+
+ if (lstrcmpiW(pwcszClientName, pTrustee->ptstrName) != 0)
+ {
+ return CO_E_TRUSTEEDOESNTMATCHCLIENT;
+ } // if
+ }
+ return S_OK;
+
+} // ValidateAccessCheckClient
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: LocalMemAlloc
+//
+// Summary: This fucntion makes memory allocation more efficient by using the
+// cached g_pIMalloc pointer.
+//
+// Args: ULONG cb [in] = Number of bytes to be allocated.
+//
+// Return: void * - Pointer to the a newly allocated memory block.
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+void * LocalMemAlloc(ULONG cb)
+{
+ return g_pIMalloc->Alloc(cb);
+} // LocalMemAlloc
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: LocalMemFree
+//
+// Summary: This function frees memory allocated by LocalMemAlloc.
+//
+// Args: void *pBlock - Pointer to the memory block to be freed.
+//
+// Return: void
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+void LocalMemFree(void *pBlock)
+{
+ g_pIMalloc->Free(pBlock);
+} // LocalMemFree
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: CleanUpStreamACL, Common
+//
+// Summary: This function releases all the memory allocated for the array
+// of STREAM_ACE structures inside a STREAM_ACL structure. This
+// includes all the trustee string and SID inside each of the
+// STREAM_ACE structure.
+//
+// Args: STREAM_ACL *pStreamACL [in] - Pointer to the stream ACL structure
+// to be cleaned up.
+//
+// Return: void
+//
+// Called by: COAccessControl::CImpAccessControl::Load()
+// COAccessControl::CImpAccessControl::ReplaceAllAccessRights()
+// CleanAllMemoryResources
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+void CleanUpStreamACL
+(
+STREAM_ACL *pStreamACL
+)
+{
+ ULONG ulNumOfEntries; // Total number of entries in the stream ACL
+ ULONG i; // Loop index
+ STREAM_ACE *pACE; // Pointer to elements in the stream ACL
+
+ ulNumOfEntries = pStreamACL->ulNumOfDenyEntries
+ + pStreamACL->ulNumOfGrantEntries;
+
+ pACE = pStreamACL->pACL;
+
+ for (i = 0; i < ulNumOfEntries; i++)
+ {
+ midl_user_free(pACE->pTrusteeName);
+ midl_user_free(pACE->pSID);
+ pACE++;
+ } // for
+
+ pStreamACL->ulNumOfDenyEntries = 0;
+ pStreamACL->ulNumOfGrantEntries = 0;
+
+ // free the stream ACL itself and set the pointer to NULL
+ midl_user_free(pStreamACL->pACL);
+ pStreamACL->pACL = NULL;
+
+} // CleanUpStreamACL
+
+/////////////////////////////////////////////////////////////////////////////
+// Functions that are specific to the Chicago platform
+/////////////////////////////////////////////////////////////////////////////
+#ifdef _CHICAGO_
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: AddACEToACLImage
+//
+// Summary: This function adds an ACE to an ACL image and it assumes that the
+// ACL image has enough space to hold the new entry.
+//
+// Args: access_list_2 *pNewACE [in] - The new access_list_2 structure to be
+// added to the LAN Manager ACL in the
+// ACL image.
+// ULONG AccessMode [in] - Grant or Deny
+// ACL_DESCRIPTOR ACLDesc [in,out] - Contains the grant and deny
+// Chicago ACL image structures.
+// The new access_list_2 structure is
+// added to the appropriate one.
+//
+// Return: void
+//
+// Called by: AddACEToACL
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+void AddACEToACLImage
+(
+access_list_2 *pNewACE,
+ULONG AccessMode,
+ACL_DESCRIPTOR *ACLDesc
+)
+{
+ ULONG ulStrLen;
+ access_list_2 *pACE;
+ ACL_IMAGE *pACLImage = AccessMode == ACTRL_ACCESS_ALLOWED ? &ACLDesc->GrantACL :
+ &ACLDesc->DenyACL;
+
+ pACE = (access_list_2 *)(pACLImage->pACL + 1)
+ + pACLImage->pACL->acc1_count;
+
+ memcpy(pACE, pNewACE, sizeof(access_list_2));
+ pACLImage->pACL->acc1_count++;
+
+} // AddACEToACLImage
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: CleanFileResource
+//
+// Summary: This function deletes the dummy file created for an ACL image and
+// removes the security entries associated with that file in the system
+// registry.
+// Args: ACL_IMAGE *pACLImage [in,out] - Pointer to the ACL image that contains
+// the dummy file name.
+//
+// Return: void
+//
+// Called by: COAccessControl::CImpAccessControl::~CImpAccessControl
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+void CleanFileResource
+(
+ACL_IMAGE *pACLImage
+)
+{
+ CHAR *pszFileName;
+
+ pszFileName = pACLImage->pACL->acc1_resource_name;
+ NetAccessDel(NULL, pszFileName);
+ DeleteFileA(pszFileName);
+ LocalMemFree(pszFileName);
+
+} // CleanFileResource
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: DeleteACEFromACLImage, Chicago specific
+//
+// Summary: This function removes the ACEs of a trustee from an ACL image.
+//
+// Args: LPWSTR pTrustee [in] - Pointer to the trustee to be removed from the
+// ACL image.
+// ACL_IMAGE *pACLImage [in,out] - Pointer to the ACL image to remove the
+// trustee from
+//
+// Return: void
+//
+// Called by: COAccessControl::CImpAccessControl::RevokeAccessRights
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+void DeleteACEFromACLImage
+(
+CHAR *pcszTrusteeName,
+ACL_IMAGE *pACLImage
+)
+{
+ SHORT i; // Loop counter
+ access_list_2 *pACE; // Pointer for browsing LAN Manager ACEs
+ // in the ACL image
+ SHORT sDiff; // The difference between the indices of
+ // the last entry and the the entry to
+ // be removed
+
+ pACE = (access_list_2 *)(pACLImage->pACL + 1);
+ for (i=0; i < pACLImage->pACL->acc1_count; i++, pACE++)
+ {
+ while((i < pACLImage->pACL->acc1_count) &&
+ (lstrcmpiA(pcszTrusteeName, pACE->acl2_ugname) == 0))
+ {
+ pACLImage->pACL->acc1_count--;
+ LocalMemFree(pACE->acl2_ugname);
+
+ // If the current entry is not the last entry in the ACL image
+ if (i != pACLImage->pACL->acc1_count)
+ {
+ // Compute the difference between the
+ // indices of the last entry and the current current entry
+ // Note that acc1_count has already
+ // been decremented so it should
+ // now contain the index of the last
+ // element in the ACL
+ sDiff = pACLImage->pACL->acc1_count;
+ memcpy(pACE, pACE + sDiff, sizeof(access_list_2));
+ } // if
+ break;
+ } // if
+ } // if
+
+} // DeleteACEFromACLImage
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: AllocACLImage, Chicago specific
+//
+// Summary: This function allocates memory for an ACL image large enough to hold
+// the specified number of ACEs excluding the user name inside the
+// access_list_2 structure.
+//
+// Args: ACL_IMAGE *pACLImage [in,out] - Pointer to the ACL image to allocate
+// memory for.
+// SHORT sNumOfEntries [in] - Number of ACEs to be allocated.
+//
+// Return: HRESULT - S_OK: Success.
+// E_OUTOFMEMORY: Not enough memory to allocate the LAN
+// Manager ACL.
+//
+// Called by: COAccessControl::CImpAccessControl::Load
+// EnsureACLImage
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT AllocACLImage
+(
+ACL_IMAGE *pACLImage,
+SHORT sNumOfEntries
+)
+{
+ ULONG ulACLSize;
+
+ ulACLSize = sizeof(access_info_1) + sNumOfEntries * sizeof(access_list_2);
+
+ if ((pACLImage->pACL = (access_info_1 *)LocalMemAlloc(ulACLSize)) == NULL)
+ {
+ return E_OUTOFMEMORY;
+ } // if
+
+ // It is not really necessary to set the ACL buffer to zero, but is safer
+ // to do so.
+ memset(pACLImage->pACL, 0, ulACLSize);
+ pACLImage->sMaxNumOfACEs = sNumOfEntries;
+
+ return S_OK;
+
+} // AllocACLImage
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: EnsureACLImage, Chicago specific
+//
+// Summary: This function enlarge an existing ACL image to accomodate more ACEs.
+//
+// Args: ACL_IMAGE *pACLImage [in] - Pointer to the ACL image to be enlarged.
+// SHORT sAddEntries [out] - Number of free slots to be added.
+//
+// Return: HRESULT S_OK: Success
+// E_OUTOFMEMORY: Out of memory.
+//
+// Called by: AddACEToACLImage
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT EnsureACLImage
+(
+ACL_IMAGE *pACLImage,
+ULONG lAddEntries
+)
+{
+ ACL_IMAGE LocalImage; // A local ACL_IMAGE structure for backing up the
+ // the old list
+ SHORT sNewSize; // The new size of the ACL
+ HRESULT hr = S_OK;
+
+ // If there is no ACL, just make one.
+ if (pACLImage->pACL == NULL)
+ return AllocACLImage( pACLImage, (SHORT) lAddEntries + EXTRA_ACES );
+
+ // If the ACL is large enough, return.
+ if (pACLImage->pACL->acc1_count + lAddEntries <
+ (ULONG) pACLImage->sMaxNumOfACEs)
+ return S_OK;
+ sNewSize = (SHORT) (pACLImage->pACL->acc1_count + lAddEntries + EXTRA_ACES);
+
+ // Take a snapshot of the old list
+ memcpy(&LocalImage, pACLImage, sizeof(ACL_IMAGE));
+
+ if(FAILED(hr = AllocACLImage(pACLImage, sNewSize)))
+ {
+ goto Error;
+ } // if
+
+ // Copy the content of the old list over to the new list
+ memcpy( pACLImage->pACL
+ , LocalImage.pACL
+ , sizeof(access_info_1)
+ + sizeof(access_list_2)
+ * LocalImage.pACL->acc1_count);
+
+ // free the memory used by the old list
+ LocalMemFree(LocalImage.pACL);
+ return S_OK;
+
+Error:
+ // Restore the old list
+ memcpy(pACLImage, &LocalImage, sizeof(ACL_IMAGE));
+ return hr;
+
+} // EnsureACLImage
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: CleanUpACLImage, Chicago specific
+//
+// Summary: This function releases the memory that has been allocated for
+// an ACL image except for the resource name in the ACL header.
+//
+// Args: ACL_IMAGE *pACLImage [in] - Pointer to the ACL image to be released.
+//
+// Return: void
+//
+// Called by: COAccessControl::CImpAccessControl::Load
+// COAccessControl::CImpAccessControl::ReplaceAllAccessRights
+// CleanAllMemoryResources()
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+void CleanUpACLImage
+(
+ACL_IMAGE *pACLImage
+)
+{
+ access_list_2 *pACE; // Pointer for traversing the LAN Manager ACL
+ SHORT sNumOfACEs; // Total number of LAN Manager ACEs to release
+ SHORT i; // Loop counter
+
+ pACE = (access_list_2 *)(pACLImage->pACL + 1);
+ sNumOfACEs = pACLImage->pACL->acc1_count;
+
+ // For each access_list_2 structure in the LAN Manager ACL, we have
+ // to free the user/group name string in it.
+ for (i = 0; i < sNumOfACEs; i++, pACE++)
+ {
+ LocalMemFree(pACE->acl2_ugname);
+ } // for
+
+ LocalMemFree(pACLImage->pACL);
+ pACLImage->pACL = NULL;
+} // CleanUpACLImage
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: WStringToMBString
+//
+// Summary: This function converts a Unicode string into a multibyte string
+// using the current console code page. This function will allocate
+// memory for the mulitbyte string which is returned to the caller
+// so the caller must free the string when the string is no longer
+// in use. Notice that the WC_COMPOSITECHECK and the WC_SEPCHARS
+// flags are hard-coded in the conversion but this may not be
+// the perfect setting for all languages. A more suitable approach
+// is to set up a global mask that defines the proper behaviour of
+// converting composite character when the server is started.
+//
+// Args: LPWSTR pwszString [in] - The Unicode string to be converted.
+// CHAR **pcszString [out] - Address of the pointer to the
+// converted multibyte string.
+//
+// Return: HRESULT - S_OK: Succeeded.
+// CO_E_CONVERSIONFAILED: WideCharToMultiByte returned zero.
+// The caller can get extended error
+// information by calling GetLastError.
+// E_OUTOFMEMORY: The system ran out of memory for the
+// converted string.
+//
+// Called by: ComputeEffectiveAccess
+// ValidateAndTransformAccReqList
+//
+// Remarks: This function relies on the global variable, g_uiCodePage, for
+// the conversion.
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT WStringToMBString
+(
+LPWSTR pwszString,
+CHAR **ppcszString
+)
+{
+ ULONG ulStrLen; // Lenght of the multibyte string
+
+ // The first call to WideCharToMultiByte is to figure out the length
+ // of the converted string so that enough memoy can be allocated for
+ // it.
+ ulStrLen = WideCharToMultiByte( g_uiCodePage
+ , WC_SEPCHARS | WC_COMPOSITECHECK
+ , pwszString
+ , -1
+ , NULL
+ , NULL
+ , NULL
+ , NULL );
+ if (ulStrLen == 0)
+ {
+ return CO_E_CONVERSIONFAILED;
+ } // if
+
+ *ppcszString = (CHAR *)LocalMemAlloc(ulStrLen + 1);
+ if (*ppcszString == NULL)
+ {
+ return E_OUTOFMEMORY;
+ } // if
+
+ WideCharToMultiByte( g_uiCodePage
+ , WC_SEPCHARS | WC_COMPOSITECHECK
+ , pwszString
+ , -1
+ , *ppcszString
+ , ulStrLen + 1
+ , NULL
+ , NULL );
+
+ return S_OK;
+} // WStringToMBString
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: GenerateFile, Chicago specific
+//
+// Summary: This function generates a file on the system with a (supposed)
+// unique name composed by a randomly generated uuid and the current
+// process id. Notice that this function allocates memory for the
+// gernerated filename to be returned to the caller and it also
+// creates the file with the generated filename on the file system,
+// so it is up to the caller to release these sytem resorces when
+// they are no longer in use. The syntax fo the file name generated
+// can be described by the expression:
+// <Windows directory>/<Current process ID>_<UUID>.tmp
+//
+// Args: LPTSTR *pFileName [out] - Address of the generated filename string
+// which is returned to the caller.
+//
+// Return: HRESULT - S_OK: Succeeded.
+// E_OUTOFMEMORY: The system ran out of memory for some
+// crucial operation.
+// CO_E_FAILEDTOGETWINDIR: (Windows 95 only)Unable to obtain
+// the Windows directory.
+// CO_E_PATHTOOLONG: (Windows 95 only)The path generated by
+// the GenerateFile function was longer
+// than the system's limit.
+// CO_E_FAILEDTOGENUUID: (Windows 95 only)Unable to generate
+// a uuid using the UuidCreate funciton.
+// CO_E_FAILEDTOCREATEFILE: (Windows 95 only)Unable to create
+// a dummy file.
+//
+// Called by: COAccessControl::CImpAccessControl::Load()
+//
+// Remarks: This function relies on the fact that there is global variable
+// named g_dwProcessID containing the current process ID.
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT GenerateFile
+(
+LPTSTR *pFileName
+)
+{
+ HRESULT hr = S_OK; // Function return code
+ UUID uuid; // The UUID generated by CreateUuid
+ LPTSTR pszPathName; // Pointer to the full pathname
+ LPTSTR pszFileName; // Pointer to the filename
+ SHORT sStrLen; // Temporary variable to keep track of the
+ // intermediate length of the path
+ HANDLE FileHandle; // Handle for file management.
+
+ pszPathName = NULL;
+
+ // Allocate memory for the full path of the file that is going to be
+ // generated
+ pszPathName = (LPTSTR)LocalMemAlloc(sizeof(TCHAR) * MAX_PATH);
+ if (pszPathName == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } // if
+
+
+ sStrLen = GetWindowsDirectory(pszPathName, MAX_PATH);
+ if(sStrLen == 0)
+ {
+ hr = CO_E_FAILEDTOGETWINDIR;
+ goto Error;
+ } // if
+
+ // We should worry about the case where the Windows directory is the
+ // root directory where the '\' character has already been added to
+ // the path at the end. We should add the '\' character at the
+ // end of the Windows path otherwise.
+ if(pszPathName[sStrLen - 1] != '\\')
+ {
+ pszPathName[sStrLen] = '\\';
+ sStrLen++;
+ } //if
+
+ pszFileName = pszPathName + sStrLen;
+ // Compose the filename with the process id
+ _ultoa( g_dwProcessID, pszFileName, 16 );
+ sStrLen = sStrLen + strlen(pszFileName);
+ pszFileName = pszPathName + sStrLen;
+ *(pszFileName++) = '_';
+ sStrLen += 1;
+
+ // See if the buffer can hold everything..
+ // UUID and extension etc.
+ if (sStrLen + 43 > MAX_PATH)
+ {
+ hr = CO_E_PATHTOOLONG;
+ goto Error;
+ } // if
+
+ // Compose the filename with a UUID
+ if(UuidCreate(&uuid) != RPC_S_OK)
+ {
+ hr = CO_E_FAILEDTOGENUUID;
+ goto Error;
+ } // if
+
+ // Put the uuid into the filename
+ wStringFromGUID2A( uuid, pszFileName, GUID_SIZE+1 );
+
+ // Attach a .tmp extension to the end
+ strcpy(pszFileName + GUID_SIZE, ".tmp");
+
+ // return the string to caller
+ *pFileName = pszPathName;
+
+ // Create the file
+ if ((FileHandle = CreateFileA( pszPathName
+ , GENERIC_READ | GENERIC_WRITE
+ , FILE_SHARE_READ
+ , NULL
+ , CREATE_NEW
+ , FILE_ATTRIBUTE_TEMPORARY
+ , NULL )) == INVALID_HANDLE_VALUE )
+ {
+ // There are two distinct possibilities that an error creating the file may occur:
+ // 1. The filename generated by GenerateFile has already existed in the file system.
+ // This is highly improbable because an UUID is used in the filename generation.
+ // 2. The system runs out of memory
+ hr = CO_E_FAILEDTOCREATEFILE;
+ goto Error;
+ } // if
+
+
+ // Close the file immediately since we don't really
+ // access the file
+ if (!CloseHandle(FileHandle))
+ {
+ Win4Assert( !"Unable to close file handle." );
+ } // if
+
+ return hr;
+
+ Error:
+ if (pszPathName != NULL)
+ {
+ LocalMemFree(pszPathName);
+ } // if
+ *pFileName = NULL;
+ return hr;
+
+} // GenerateFile
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: MapStreamACLToChicagoACL, Chicago specific
+//
+// Summary: This function maps a standard stream format ACL to a preallocated
+// in-Femory ACL image specifically designed to work with the
+// LAN Manager API supported on Chicago.
+//
+// Args: STREAM_ACE *pStreamACEs [in] - Pointer to an array of ACEs in
+// standard stream format.
+// ACL_IMAGE *pACLImage [in,out] - The in memory representation of an
+// ACL image.
+// SHORT sNumOfEntries [in] - The number of stream format ACEs to
+// be mapped to the in-memory ACL image.
+//
+//
+// Return: HRESULT - S_OK: Succeeded.
+// CO_E_CONVERSIONFAILED: WideCharToMultiByte returned zero.
+// The caller can get extended error
+// information by calling GetLastError.
+// E_OUTOFMEMORY: The system ran out of memory for the
+// converted string.
+//
+// Called by: COAccessControl::CImpAccessControl::Load
+// COAccessControl::CImpAccessControl::ReplaceAllAccessRights
+// ComputeEffectiveAccess
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT MapStreamACLToChicagoACL
+(
+STREAM_ACE *pStreamACEs,
+ACL_IMAGE *pACLImage,
+SHORT sNumOfEntries
+)
+{
+ USHORT i,j; // Loop counters
+ STREAM_ACE *pStreamACEsPtr; // Pointer to an array of stream format ACEs
+ access_list_2 *pACE; // Pointer to ACEs in the LAN Manager ACL
+ ULONG ulStrLen; // Length of the trustee string
+ HRESULT hr;
+
+ // Set up the ACL header
+ pACLImage->pACL->acc1_attr = 0; // Audit all by default
+ pACLImage->pACL->acc1_count = sNumOfEntries;
+
+ // Set the stream ACE pointer to point to the first stream ACE
+ pStreamACEsPtr = pStreamACEs;
+
+ pACE = (access_list_2 *)(pACLImage->pACL + 1);
+
+ for (i = 0; i < sNumOfEntries; i++)
+ {
+
+ if (FAILED(hr = WStringToMBString( pStreamACEsPtr->pTrusteeName
+ , &(pACE->acl2_ugname))))
+ {
+ goto Error;
+ } // if
+
+ // Map stream security mask to Chicago security mask
+ StandardMaskToLANManagerMask( &(pStreamACEsPtr->grfAccessPermissions)
+ , &(pACE->acl2_access));
+
+ // Set up the group bit if necessary
+ if (pStreamACEsPtr->TrusteeType == TRUSTEE_IS_GROUP)
+ {
+ pACE->acl2_access |= ACCESS_GROUP;
+ } // if
+
+ pACE++;
+
+ pStreamACEsPtr++;
+
+ } // for
+
+ return S_OK;
+
+Error:
+ pACE = (access_list_2 *)(pACLImage->pACL + 1);
+ for (j = 0; j < i; j++, pACE++)
+ {
+ LocalMemFree(pACE->acl2_ugname);
+ } // for
+ return hr;
+
+} // MapStreamToChicagoACL
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: StandardMaskToLANManagerMask, Chicago specific
+//
+// Summary: This function maps the content of a access permissions
+// supported by IAccessControl to the corresponding LAN
+// Mamager access mask.
+//
+// Args: DWORD *pStdMask [in] - The standard mask to be converted to NT
+// mask.
+// ACCESS_MASK *pNTMask [out] - Reference to the converted mask.
+//
+//
+// Return: void
+//
+// Called by:
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+SHORT StandardMaskToLANManagerMask
+(
+DWORD *pStdMask,
+USHORT *pLMMask
+)
+{
+ *pLMMask= 0;
+
+
+ if ((*pStdMask & COM_RIGHTS_EXECUTE) != 0)
+ {
+ *pLMMask |= CHICAGO_RIGHTS_EXECUTE;
+ } // if
+
+ return 0;
+
+} // StandardMaskToLANManagerMask
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: lstrcmpiW, Chicago specific
+//
+// Summary: This function is equivalent to lstrcmpiW on Windows NT.
+// Unlike the Windows NT version of lstrcmpiW, this function can
+// treats a null pointer as a null string instead of spewing out an
+// access violation error.
+//
+// Remarks: See the section on lstrcmpi inside the Win32 SDK documentation.
+// This function relies on a global variable named g_uiCodePage
+// storing the current console code page.
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+SHORT FoolstrcmpiW(LPWSTR pwsz1, LPWSTR pwsz2)
+{
+ SHORT sResult; // The result of the comparision
+ WCHAR *pwchar1 = pwsz1; // Pointer for browsing through the first string
+ // character by character.
+ WCHAR *pwchar2 = pwsz2; // Pointer for browsing through the second string
+ // character by character.
+ WCHAR wchar1;
+ WCHAR wchar2;
+
+ // The following block of code handles case where
+ // either one of the input string is a NULL pointer.
+ // By convention a string represented by a NULL pointer
+ // is an empty string.
+ if(pwchar1 == NULL)
+ {
+ if(pwchar2 == NULL)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ } // if
+ }
+ else if (pwchar2 == NULL)
+ {
+ return 1;
+ } // if
+
+ for(;;)
+ {
+ wchar1 = *pwchar1;
+ wchar2 = *pwchar2;
+
+#if 0
+ // Checking to see if the current code page is the
+ // ANSI code page may not be enough to cover all the
+ // cases where a language has the concept of upper and lower
+ // case letters.
+ if (g_uiCodePage == CP_ACP)
+ {
+#endif
+ // All lower-case characters in the both strings are
+ // converted to upper-case characters before
+ // making the comparison.
+ if ((L'a' <= *pwchar1)&& (*pwchar1 <= L'z'))
+ {
+ wchar1 = *pwchar1 - L'a' + L'A';
+ } // if
+
+ if ((L'a' <= *pwchar2) && (*pwchar2 <= L'z'))
+ {
+ wchar2 = *pwchar2 - L'a' + L'A';
+ } // if
+#if 0
+ } // if
+#endif
+ if(wchar1 == 0 && wchar2 == 0)
+ {
+ return 0;
+ }
+ else if (wchar1 > wchar2)
+ {
+ return 1;
+ }
+ else if (wchar1 < wchar2)
+ {
+ return -1;
+ } // if
+
+ // Increment the string pointers to point to the next character
+ // for comparison
+ pwchar1++;
+ pwchar2++;
+ } // if
+} // if
+
+#else
+
+/////////////////////////////////////////////////////////////////////////////
+// Functions that are specific to the Windows NT platform
+/////////////////////////////////////////////////////////////////////////////
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: InitSecDescInACLDesc, NT specific
+//
+// Summary: This function initializes the group field and the user field of the
+// security descriptor in an ACL_DESCRIPTOR structure the user SID of
+// the current process.
+//
+// Args: ACL_DESCRIPTOR pACLDesc [in,out] - Pointer to ACL descriptor containing
+// the security identifier to be
+// initialized.
+//
+// Return: HRESULT - S_OK: Succeeded.
+// CO_E_FAILEDTOOPENPROCESSTOKEN: The system call,
+// OpenProcessToken, failed.
+// The user can get extended
+// information by calling
+// GetLastError.
+// CO_E_FAILEDTOGETTOKENINFO: The system call,
+// GetTokenInformation, failed.
+// The user can call GetLastError
+// to get extended error
+// information.
+// E_OUTOFMEMORY: There was not enough memory for allocating
+// the SIDs in the security descriptor.
+//
+// Called by: COAccessControl:CImpAccessControl:Load
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT InitSecDescInACLDesc
+(
+ACL_DESCRIPTOR *pACLDesc
+)
+{
+ // Set up a security descriptor with the current process owner
+ // and primary group
+ TOKEN_USER *pTokenUser = NULL;
+ HANDLE hToken;
+ ULONG ulLen;
+ HANDLE hProcess;
+ DWORD dwLastError;
+ PSID pOwner = NULL;
+ PSID pGroup = NULL;
+ DWORD dwSIDLen;
+ HRESULT hr = S_OK;
+
+ hProcess = GetCurrentProcess();
+
+ if(!OpenProcessToken( hProcess
+ , TOKEN_QUERY
+ , &hToken ))
+ {
+ hr = CO_E_FAILEDTOOPENPROCESSTOKEN;
+ goto Error;
+ } // if
+
+ GetTokenInformation( hToken
+ , TokenUser
+ , pTokenUser
+ , 0
+ , &ulLen);
+ dwLastError = GetLastError();
+ if (dwLastError == ERROR_INSUFFICIENT_BUFFER)
+ {
+ pTokenUser = (TOKEN_USER *)LocalMemAlloc(ulLen);
+ if (pTokenUser == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } // if
+
+ if(!GetTokenInformation( hToken
+ , TokenUser
+ , pTokenUser
+ , ulLen
+ , &ulLen))
+ {
+ hr = CO_E_FAILEDTOGETTOKENINFO;
+ goto Error;
+ }
+
+ }
+ else
+ {
+ hr = CO_E_FAILEDTOGETTOKENINFO;
+ goto Error;
+ } // if
+
+ dwSIDLen = GetLengthSid(pTokenUser->User.Sid);
+
+ pOwner = (PSID)LocalMemAlloc(dwSIDLen);
+ if(pOwner == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } // if
+
+ pGroup = (PSID)LocalMemAlloc(dwSIDLen);
+ if(pGroup == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } // if
+
+ CopySid(dwSIDLen, pOwner, pTokenUser->User.Sid);
+ CopySid(dwSIDLen, pGroup, pTokenUser->User.Sid);
+
+ InitializeSecurityDescriptor( &(pACLDesc->SecDesc)
+ , SECURITY_DESCRIPTOR_REVISION);
+ pACLDesc->SecDesc.Owner = pOwner;
+ pACLDesc->SecDesc.Group = pGroup;
+
+ // Close the token handle
+ CloseHandle(hToken);
+ // Free the token user buffer
+ LocalMemFree(pTokenUser);
+
+ pACLDesc->bDirtyACL = TRUE;
+ return hr;
+
+Error:
+ if (pTokenUser != NULL)
+ {
+ LocalMemFree(pTokenUser);
+ } // if
+ if (pOwner != NULL)
+ {
+ LocalMemFree(pOwner);
+ } // if
+ if (pGroup != NULL)
+ {
+ LocalMemFree(pGroup);
+ } // if
+ return hr;
+
+} // InitSecDescInACLDesc
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: GetSIDFromName, NT specific
+//
+// Summary: This function takes an account name of the form <Domain>\<User name>
+// as an input and returns the corresponding security identifier (SID).
+// This function will automatically allocates memory for the SID
+// returned to the caller so the caller should release the SID pointer
+// using LocalMemFree as soon as the SID is no longer in use.
+//
+// Args: PSID *ppSID [out] - Address of the pointer to the returned security
+// identifier. The caller must free the memory
+// allocated for the securrity identifier using
+// LocalMemFree when the security identifier is no
+// longer in use.
+// LPWSTR pwszTrustee [in] - Pointer to the trustee name of the form
+// <Domain>\<User name>. The SID returned
+// should belong to this trustee.
+// TRUSTEE_TYPE TrusteeType [in] - Type of the trustee which is either
+// TRUSTE_IS_NAME or TRUSTEE_IS_GROUP
+//
+// Return: HRESULT - S_OK: Succeeded.
+// CO_E_NOMATCHINGSIDFOUND: No matching security identifier
+// could be found for the
+// trustee name specified by the
+// client.
+// CO_E_LOOKUPACCNAMEFAILED: The system function,
+// LookupAccountName, failed. The client can
+// call GetLastError to obtain extended error
+// information.
+// E_OUTOFMEMORY: The system ran out of memory for
+// allocating the SID to be returned
+// the caller.
+//
+//
+// Called by: ValidateAndFixStreamACL
+// ValidateAndTransformAccReqList
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT GetSIDFromName
+(
+PSID *ppSID,
+LPWSTR pwszTrustee,
+TRUSTEE_TYPE *pTrusteeType
+)
+{
+ PSID pSID; // Pointer to the SID to be retrieved
+ DWORD dwSIDSize; // Buffer size for the SID
+ LPWSTR pwszUserName; // Pointer to the user name portion of the
+ // trustee
+ DWORD dwLastError; // Error code obtained from GetLastError
+ DWORD dwDomainLength; // Length of domain name
+ LPWSTR pwszDomainName; // Pointer to the domain name returned by
+ // LookupAccountName.
+ SID_NAME_USE SIDUse; // The type of SID returned.
+ HRESULT hr;
+
+ // We trap the magic string "*' which specifies everyone
+ if (pwszTrustee[0] == L'*' && pwszTrustee[1] == L'\0')
+ {
+ if (*pTrusteeType != TRUSTEE_IS_GROUP)
+ {
+ return E_INVALIDARG;
+ } // if
+
+ if(*ppSID = (PSID)LocalMemAlloc(sizeof(gEveryone)))
+ {
+ CopySid(sizeof(gEveryone), *ppSID, &gEveryone);
+ return S_OK;
+ }
+ else
+ {
+ return E_OUTOFMEMORY;
+ } // if
+ } // if
+
+ // NT 4 does not map the domain NT Authority correctly
+ if (lstrcmpiW(pwszTrustee, L"NT Authority\\system") == 0)
+ {
+ if (*pTrusteeType != TRUSTEE_IS_USER)
+ {
+ return E_INVALIDARG;
+ } // if
+
+ if(*ppSID = (PSID)LocalMemAlloc(sizeof(gSystem)))
+ {
+ CopySid(sizeof(gSystem), *ppSID, &gSystem);
+ return S_OK;
+ }
+ else
+ {
+ return E_OUTOFMEMORY;
+ } // if
+ } // if
+
+ // Assign an arbitrarily large SID size so that the function
+ // can avoid LookupAccountName twice for most of the time.
+ pwszUserName = pwszTrustee;
+ dwDomainLength = 64;
+ dwSIDSize = 64;
+ pSID = (PSID)midl_user_allocate(dwSIDSize);
+ if (pSID == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } // if
+
+ dwDomainLength++;
+ pwszDomainName = (LPWSTR)LocalMemAlloc(sizeof(WCHAR) * dwDomainLength);
+ if (pwszDomainName == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } // if
+
+ if (!LookupAccountNameW( NULL
+ , pwszUserName
+ , pSID
+ , &dwSIDSize
+ , pwszDomainName
+ , &dwDomainLength
+ , &SIDUse))
+
+ {
+ dwLastError = GetLastError();
+
+ if (dwLastError = ERROR_INSUFFICIENT_BUFFER)
+ {
+
+ // If it is not the domain buffer that is too small, it must be
+ // the SID that is too small. In this cas, we should expand the
+ // buffer and call LookupAccountW again.
+ LocalMemFree(pSID);
+ pSID = (PSID)midl_user_allocate(dwSIDSize);
+ if (pSID== NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } // if
+
+ if(!LookupAccountNameW( NULL
+ , pwszUserName
+ , pSID
+ , &dwSIDSize
+ , pwszDomainName
+ , &dwDomainLength
+ , &SIDUse ))
+ {
+ // If LookupAccountW crashes again, we quit and return
+ // an error code.
+ hr = CO_E_LOOKUPACCNAMEFAILED;
+ goto Error;
+ } // if
+ }
+ else
+ {
+ // LookupAccountW may not be able to find the SID for the
+ // trustee or some other fatal errors occured. In any case, we
+ // return an error code and the caller can look at the details
+ // by calling GetLastError
+ hr = CO_E_LOOKUPACCNAMEFAILED;
+ goto Error;
+ } // if
+ } // if
+
+ // Check to see if the trustee type provided by the caller matches the SID
+ // type obtained from LookupAccountName. If not, we're in trouble. All
+ // well known SIDs are of type SidTypeWellKnownGroup.
+ if( !(SIDUse == SidTypeUser && *pTrusteeType == TRUSTEE_IS_USER) &&
+ !(SIDUse == SidTypeGroup && *pTrusteeType == TRUSTEE_IS_GROUP) &&
+ SIDUse != SidTypeWellKnownGroup && SIDUse != SidTypeAlias)
+ {
+ hr = CO_E_NOMATCHINGSIDFOUND;
+ goto Error;
+ } // if
+
+ LocalMemFree(pwszDomainName);
+ *ppSID = pSID;
+ return 0;
+
+Error:
+ if (pwszDomainName != NULL)
+ {
+ LocalMemFree(pwszDomainName);
+ }
+ if (pSID != NULL)
+ {
+ midl_user_free(pSID);
+ }
+ return hr;
+} // GetSIDFromName
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: GetNameFromSID, NT specific
+//
+// Summary: This function takes a security identifier (SID) as an input
+// and finds the trustee name in the form <Domain>\<User name> that
+// corresponds to the SID. This function will allocate memory for
+// the trustee name returned to the caller so the caller should
+// release the trustee name pointer using LocalMemFree whem the
+// trustee name is no longer in use.
+//
+// Args: LPWSTR *ppwszTrustee [out] - Address of the pointer to the trustee
+// name to be returned to the caller. The
+// trustee name returned is in the form
+// <Domain>\<User name>. The caller is
+// responsible for releasiung the memory
+// allocated for the trustee string once
+// it is no longer in use.
+//
+// PSID pSID [in] - Pointer to a security identifier. This function
+// will return the trustee name corresponding to
+// this security identifier through the ppwszTrustee
+// argument.
+//
+// TRUSTEE_TYPE TrusteeType [in] - The type associating with the
+// trustee name that the caller is
+// expecting.
+//
+// Return: HRESULT - S_OK: Succeeded.
+// CO_E_NOMATCHINGNAMEFOUND: No matching account name
+// could be found for one of the security identifiers
+// specified by the client.
+// CO_E_LOOKUPACCSIDFAILED: The system function,
+// LookupAccountSID, failed. The client can call
+// GetLastError to obtain extended error inforamtion.
+// E_OUTOFMEMORY: The system ran out of memory.
+//
+// Called by: ValidateAndTransformAccReqList
+//
+// Notes: On error LookupAccountSid returns strlen+1, on success it returns
+// only strlen.
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT GetNameFromSID
+(
+LPWSTR *ppwszTrustee,
+PSID pSID,
+TRUSTEE_TYPE *pTrusteeType
+)
+{
+ LPWSTR pwszDomainName; // Pointer to the domain name returned
+ // by LookupAccountSid.
+ DWORD dwDomainLength; // Length of the domain string
+ LPWSTR pwszAccountName; // Pointer to the account name returned by
+ // LookupAccountSid
+ DWORD dwAccountLength; // Length of the account string
+ LPWSTR pwszTrustee; // Pointer to the trustee string in the form
+ // <Domain>\<User name>
+ DWORD dwLastError; // Return code obtained from GetLastError
+ HRESULT hr = S_OK;
+ SID_NAME_USE SIDUse; // An enumerated variable indicating
+ // what the SID returned by LookupAccountSD.
+
+ // We trap the magic SID that specifies everyone
+ if (EqualSid(&gEveryone, pSID))
+ {
+
+ if (*pTrusteeType != TRUSTEE_IS_GROUP)
+ {
+ return E_INVALIDARG;
+ } // if
+
+ if (*ppwszTrustee = (LPWSTR)LocalMemAlloc(2*sizeof(WCHAR)))
+ {
+ (*ppwszTrustee)[0] = L'*';
+ (*ppwszTrustee)[1] = L'\0';
+ *pTrusteeType = TRUSTEE_IS_GROUP;
+ return S_OK;
+ }
+ else
+ {
+ return E_OUTOFMEMORY;
+ }
+ } // if
+
+
+ // Assign some arbitrary large number as the size of the domain name and
+ // the account name. Hopefully, these numbers are large enough so that
+ // the function can avoid calling LookupAccountSidW the second time
+ dwDomainLength = 32;
+ dwAccountLength = 64;
+
+ // Initilize the domain name pointer and the account name pointer to NULL
+ pwszDomainName = NULL;
+ pwszAccountName = NULL;
+
+ // Allocate big buffers for the domain name and the account name
+ // to minimize the chance of call LookupAccountSid twice.
+ pwszDomainName = (LPWSTR)LocalMemAlloc(dwDomainLength * sizeof(WCHAR));
+
+ if (pwszDomainName == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } // if
+
+ pwszAccountName = (LPWSTR)LocalMemAlloc(dwAccountLength * sizeof(WCHAR));
+ if (pwszAccountName == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } // if
+
+ if(!LookupAccountSidW( NULL
+ , pSID
+ , pwszAccountName
+ , &dwAccountLength
+ , pwszDomainName
+ , &dwDomainLength
+ , &SIDUse))
+ {
+ dwLastError = GetLastError();
+ if (dwLastError == ERROR_INSUFFICIENT_BUFFER)
+ {
+ if(dwDomainLength > 32)
+ {
+ LocalMemFree(pwszDomainName);
+ pwszDomainName = (LPWSTR)LocalMemAlloc(dwDomainLength *
+ sizeof(WCHAR));
+ if (pwszDomainName == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } //if
+ } // if
+
+ if(dwAccountLength > 64)
+ {
+ LocalMemFree(pwszAccountName);
+ pwszAccountName = (LPWSTR)LocalMemAlloc(dwAccountLength *
+ sizeof(WCHAR));
+ if (pwszAccountName == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } // if
+ } // if
+
+ if(!LookupAccountSidW( NULL
+ , pSID
+ , pwszAccountName
+ , &dwAccountLength
+ , pwszDomainName
+ , &dwDomainLength
+ , &SIDUse ))
+ {
+ // Either the SID doesn't belong to any account or something
+ // has gone terribly wrong. In either case, the caller should
+ // call GetLastError to get more information about the error
+ hr = CO_E_LOOKUPACCSIDFAILED;
+ goto Error;
+ } // if
+
+ } // if
+ else
+ {
+ // The caller should call GetLastError to obtain more information
+ hr = CO_E_LOOKUPACCSIDFAILED;
+ goto Error;
+ } // if
+
+ } // if
+
+ // Check to see if the SIDtype retuned by LookupAccountSidW matches the
+ // trustee type provided by the caller. If not, we're in trouble.
+ // SidTypeWellKnownGroup and SidTypeAlias can be either.
+ if( !(SIDUse == SidTypeUser && *pTrusteeType == TRUSTEE_IS_USER) &&
+ !(SIDUse == SidTypeGroup && *pTrusteeType == TRUSTEE_IS_GROUP) &&
+ SIDUse != SidTypeWellKnownGroup && SIDUse != SidTypeAlias)
+ {
+ hr = CO_E_NOMATCHINGSIDFOUND;
+ goto Error;
+ } // if
+
+ // Allocate memory for the trustee string to be returned
+ // Add 2 for null terminating the string and '\\'
+ pwszTrustee = (LPWSTR)midl_user_allocate( (lstrlenW(pwszDomainName)
+ + lstrlenW(pwszAccountName)
+ + 2) * sizeof(WCHAR)
+ );
+
+ if (pwszTrustee == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Error;
+ } // if
+
+ // Compose the trustee string
+ memcpy(pwszTrustee, pwszDomainName, dwDomainLength * sizeof(WCHAR));
+ pwszTrustee[dwDomainLength] = L'\\';
+ memcpy(&pwszTrustee[dwDomainLength+1], pwszAccountName, (dwAccountLength+1) * sizeof(WCHAR));
+
+ *ppwszTrustee = pwszTrustee;
+
+Error:
+ // Release the domain name string and the account name string
+ if (pwszAccountName != NULL)
+ {
+ LocalMemFree(pwszAccountName);
+ } // if
+ if (pwszDomainName != NULL)
+ {
+ LocalMemFree(pwszDomainName);
+ } // if
+ return hr;
+} // GetNameFromSID
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: PutStreamACLIntoSecDesc, NT specific
+//
+// Summary: This functions takes a STREAM_ACL structure and maps it to a
+// discretionary ACL in a security descriptor. The buffer for the
+// discretionary ACL and the security descriptor are packaged
+// into the NT version of ACL_DESCRICPTOR.
+//
+// Args: STREAM_ACL *pStreamACL [in] - The STREAM_ACL structure to be mapped
+// to a discretionary ACL.
+// ACL_DESCRIPTOR *pACLDesc [in,out] - The NT version of ACL_DESCRIPTOR
+// structure. This structure contains
+// a buffer for the discretionary
+// ACL, a security descriptor, size
+// information, and a control flag.
+//
+// Return: HRESULT - S_OK: Succeeded.
+// CO_E_FAILEDTOSETDACL: SetSecurityDescriptorDacl returned
+// false inside PutStreamACLIntoSecDesc.
+// The client of this method can call
+// GetLastError to get extended error
+// information.
+// E_OUTOFMEMORY: The system ran out of memory for allocating
+// the NT ACL.
+//
+// Called by: ComputeEffectiveAccess
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+HRESULT PutStreamACLIntoSecDesc
+(
+STREAM_ACL *pStreamACL,
+ACL_DESCRIPTOR *pACLDesc
+)
+{
+ ACL *pACLHeader; // Pointer to the ACL structure in the ACL
+ // buffer.
+ ULONG i; // Loop counter
+ CHAR *pBufferPtr; // Pointer for traversing the ACL buffer.
+ ULONG ulNumOfStreamACEs; // Total number of STREAM_ACE structures to map.
+ STREAM_ACE *pStreamACEsPtr; // Pointer for traversing the array of
+ // of STREAM_ACE structures to be mapped.
+ ACE_HEADER *pACEHeader; // Pointer to the header of an ACE.
+ ULONG ulACLSize;
+ WORD wSIDSize; // Size of the SID to be copied into an ACE.
+
+ // Compute the total size of the ACL buffer
+ ulACLSize = pACLDesc->ulSIDSize
+ + (pStreamACL->ulNumOfGrantEntries + pStreamACL->ulNumOfDenyEntries)
+ * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD))
+ + sizeof(ACL);
+
+ // Reallocate a new buffer for the NT ACL if the current buffer is not
+ // big enough. Note that an extra 64 bytes is padded at the end to
+ // minimize the need for reallocating the buffer if the internal ACL
+ // is changed in a minor way.
+ if (pACLDesc->ulACLBufferSize < ulACLSize)
+ {
+ LocalMemFree(pACLDesc->pACLBuffer);
+ pACLDesc->pACLBuffer = (CHAR *)LocalMemAlloc(ulACLSize + 64);
+ if (pACLDesc->pACLBuffer == NULL)
+ {
+ pACLDesc->ulACLBufferSize = 0;
+ return E_OUTOFMEMORY;
+ } // if
+ pACLDesc->ulACLBufferSize = ulACLSize + 64;
+ } // if
+
+ // Map the stream ACL to the NT ACL
+ ulNumOfStreamACEs = pStreamACL->ulNumOfDenyEntries
+ + pStreamACL->ulNumOfGrantEntries;
+
+ // Set up the ACL header first
+ pACLHeader = (ACL *)(pACLDesc->pACLBuffer);
+ pACLHeader->AclRevision = ACL_REVISION2;
+ pACLHeader->AclSize = (USHORT)ulACLSize;
+ pACLHeader->AceCount = (USHORT)ulNumOfStreamACEs;
+
+
+ pBufferPtr = (CHAR *)(pACLDesc->pACLBuffer) + sizeof(ACL);
+ pStreamACEsPtr = pStreamACL->pACL;
+
+ // The following for loop maps the STREAM_ACE structures into the
+ // ACL buffer for NT.
+ for (i = 0; i < ulNumOfStreamACEs; i++)
+ {
+ // ACCESS_ALLOWED_ACE and ACCESS_DENIED_ACE are
+ // structurally equivalent, so I may as well use one of them
+ pACEHeader = &(((ACCESS_ALLOWED_ACE *)pBufferPtr)->Header);
+
+ // Skip ACEs with NULL SID
+ if(pStreamACEsPtr->pSID == NULL)
+ {
+ continue;
+ } // if
+
+ if (pStreamACEsPtr->grfAccessMode == ACTRL_ACCESS_DENIED)
+ {
+ pACEHeader->AceType = ACCESS_DENIED_ACE_TYPE;
+ }
+ else
+ {
+ pACEHeader->AceType = ACCESS_ALLOWED_ACE_TYPE;
+ } // if
+
+ pACEHeader->AceFlags = NULL;
+ StandardMaskToNTMask( &(pStreamACEsPtr->grfAccessPermissions)
+ , &(((ACCESS_ALLOWED_ACE *)pBufferPtr)->Mask));
+ wSIDSize = (USHORT)GetLengthSid(pStreamACEsPtr->pSID);
+ CopySid( wSIDSize
+ , &(((ACCESS_ALLOWED_ACE *)pBufferPtr)->SidStart)
+ , pStreamACEsPtr->pSID);
+ pACEHeader->AceSize = sizeof(ACCESS_ALLOWED_ACE)
+ - sizeof(DWORD)
+ + wSIDSize;
+
+ // Increment the ACL buffer to the next available slot
+ // for the the next ACE
+ pBufferPtr += pACEHeader->AceSize;
+
+ // Increment the stream ACE porinter to point to the next
+ // STREAM_ACE structure to be mapped
+ pStreamACEsPtr++;
+ } // for
+
+ // Call SetSecurityDescriptorDACL to put the mapped
+ // NT ACL into the security desriptor. The security should be initialized
+ // with a group SID and a group SID by now. See the
+ // COAccessControl::CImpAccessControl:Load method for details.
+ if(!SetSecurityDescriptorDacl( &(pACLDesc->SecDesc)
+ , TRUE
+ , (ACL *)(pACLDesc->pACLBuffer)
+ , FALSE))
+ {
+ return CO_E_FAILEDTOSETDACL;
+ } // if
+
+ pACLDesc->bDirtyACL = FALSE;
+ return 0;
+
+} // PutStreamACLIntoSecurityDescriptor
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// The access mask conversion routines
+//
+// Notes: The DCOM implementation of IAccessControl only supports the
+// execute permission and so the following functions are hard-coded to
+// convert the execute permission only. However, these function can be
+// extended to support a wider range of permissions without
+// substantantial changes in the rest of the code. For an even more
+// generic architecture, a table of mask conversion can be used.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: StandardMaskToNTMask
+//
+// Summary: This function maps the content of a access permissions
+// supported by IAccessControl to the corresponding NT
+// security access mask.
+//
+// Args: DWORD *pStdMask [in] - The standard mask to be converted to NT
+// mask.
+// ACCESS_MASK *pNTMask [out] - Reference to the converted mask.
+//
+//
+// Return: void
+//
+// Called by: PutStreamACLIntoSecDesc
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+void StandardMaskToNTMask
+(
+DWORD *pStdMask,
+ACCESS_MASK *pNTMask
+)
+{
+ *pNTMask= 0;
+
+
+ if ((*pStdMask & COM_RIGHTS_EXECUTE) != 0)
+ {
+ *pNTMask |= NT_RIGHTS_EXECUTE;
+ } // if
+
+} // StandardMaskToNTMask
+
+//F+F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F+++F
+// Function: NTMaskToStandardMask, NT specific
+//
+// Summary: This function maps the content of an NT access mask to a
+// corresponding IAccessControl access mask.
+//
+// Args: ACCESS_MASK *pNTMask [in] - Address of the NT mask to be covnverted.
+// DWORD *pStdMask [in] - Address of the converted IAccessControl
+// access mask.
+//
+// Return: void
+//
+// Called by: ComputeEffectiveAccess
+//
+//F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F---F-F
+void NTMaskToStandardMask
+(
+ACCESS_MASK *pNTMask,
+DWORD *pStdMask
+)
+{
+ *pStdMask= 0;
+
+ if ((*pNTMask & NT_RIGHTS_EXECUTE) != 0)
+ {
+ *pStdMask |= COM_RIGHTS_EXECUTE;
+ } // if
+
+} // NTMaskToStandardMask
+
+#endif // #ifdef _CHICAGO_, #else
+// End of caccctrl.cxx
+
diff --git a/private/ole32/com/accctrl/caccctrl.h b/private/ole32/com/accctrl/caccctrl.h
new file mode 100644
index 000000000..f69aadf07
--- /dev/null
+++ b/private/ole32/com/accctrl/caccctrl.h
@@ -0,0 +1,407 @@
+/*---------------------------------------------------------------------------
+
+ File: CAccCntrl.h
+
+ Copyright (c) 1996-1996, Microsoft Corp. All rights reserved.
+
+ Description: This file contains the class definitions of COAccessControl,
+ CImpAccessControl, and CFAccessControl.
+ Note that the class and structure declarations contained in
+ are not meant to be used and seen directly by developers who
+ only uses the IAccessControl interface.
+
+ Classes: COAccessControl - This is the principle class that implements
+ the DCOM IAccessControl component object.
+ Except the nondelegating IUnknown interface, the
+ COAccessControl class supports the IPersist,
+ IPersistStream and IAccessControl interfaces by
+ exposing its inner CImpAccessCOntrol pointer.
+ Through this arrangement, the COAccessControl
+ class is able to support aggregation by
+ controlling the object to which the IUnknown
+ calls of the inner CImpAccess control are
+ delegated at object contruction.
+
+ CImpAccessControl - This is the class that nested inside
+ COAccessControl. CImpAccessControl
+ implements the IPersist, IPersistStream,
+ IAccessControl interfaces and the IUnknown
+ interface which always delegates the call to
+ the IUnknown methods of the controlling object.
+ When COAccessControl is not part of an
+ aggregate CImpAccessControl IUnknown calls
+ should be delegated to its outer
+ COAccessControl, otherwise the IUnknown calls
+ should be delegated to the object controlling
+ the outer COAccessControl object.
+
+ CFAccessControl - Class factory for manufacturing COAccessControl
+ objects.
+
+ Notes: The definition of IAccessControl interface can be found in
+ oleext.h in ...sdk\inc and the data types that are defined to use with
+ IAccessControl can be found in sdk\inc\accctrl.h.
+
+--------------------------------------------------------------------------*/
+
+#ifndef _CACCCNTRL_H_
+#define _CACCCNTRL_H_
+
+//////////////////////////////////////////////////////////////////////////////
+// Internal data types
+//////////////////////////////////////////////////////////////////////////////
+
+/*////////////////////////////////////////////////////////////////////////////
+ PCB- Pickle Control Block.
+ Originally intended to be a structure for maintaining the information
+ about the pickling buffer, the PCB has become something that transcends
+ its intended purposes. Besides data related to the pickling buffer, the
+ structure also contains a copy of the access control object's ACL in a
+ format that can readily be serialized into a buffer by one of the type
+ encoding function generated by the midl compiler, see acpickl.idl for
+ details. The bDirtyHandle and the bPickled fields in the PCB structure
+ are control flags which allows better coordination between different
+ methods in CImpAccessControl. The purpose of the bDirtyHandle flag is
+ to minimize the number of times the encoding handle has to be reset
+ and the purpose of the bPickled flag is to minimize the number of times
+ the ACL has to be serialized into a buffer.
+
+////////////////////////////////////////////////////////////////////////////*/
+typedef struct tagPCB
+{
+ char *pPicklingBuff; // This pointer is always aligned on the 8-byte
+ // boundary
+ char *pTruePicklingBuff; // This is the true pickling buffer pointer
+ ULONG ulPicklingBuffSize; // Size of the pickling buffer after the 8-byte alignment
+ ULONG ulBytesUsed; // This field indicates the number of bytes requires
+ // to serialize the interanl ACL
+ STREAM_ACL StreamACL; // The stream format ACL
+ handle_t PickleHandle; // Handle for encoding and decoding
+ BOOL bDirtyHandle; // This flag indicates whether the handle needs to be reset
+ BOOL bPickled; // This flag indicates whether the current stream ACL has been encoded
+ // into the pickling buffer.
+ ULONG ulMaxNumOfStreamACEs;// The maximum number of stream ACEs that the StreamACL structure has been allocated for
+ ULONG ulNumOfStreamACEs; // The number of stream ACEs that the StreamACL structure is holding
+
+} PCB;
+
+#ifdef _CHICAGO_
+
+///////////////////////////////////////////////////////////////////////////////
+// ACL_IMAGE - This structure is used on Chicago only
+// This structure can only be considered a partial representation of the
+// ACL using the native structure available on the Chicago plaform. Owing
+// to fact that the LAN Manager APIs available on the Chicago platform
+// can distinguish between GRANT_ACCESS mode ACEs and DENY_MODE ACEs, two
+// LAN Manager ACLs are used to create the illusion of having two different
+// types of ACEs can appear simultaneously in the ACL.
+///////////////////////////////////////////////////////////////////////////////
+
+typedef struct tagACL_IMAGE
+{
+ char *pACL; // Pointer to a LAN Manager ACL.
+ // Format: |access_info_1|array of access_list|
+ SHORT *psNumOfACEs; // The number of ACE
+ SHORT sMaxNumOfACEs; // The maximum number of ACEs that the
+ // structure can hold
+ BOOL bDirtyACL; // This flag indicatess whether the ACL has
+ // changed since the last time it was mapped to
+ // the system registry use the NetAccess* functions
+} ACL_IMAGE;
+
+///////////////////////////////////////////////////////////////////////////////
+// ACL_DESC - ACL Descriptor
+// The ACL descriptor is a structure that describes how access control
+// native to specific platform can be used to emulate the ACL as perceived
+// through the IAccessControl interface.
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// The following structure is the ACL descriptor on the Chicago platform.
+// This structure is divided into two symmetric portions, one portion holds
+// the DENY_ACCESS mode ACEs while the other holds GRANT_ACCESS mode ACEs.
+///////////////////////////////////////////////////////////////////////////////
+typedef struct tagACLDescriptor
+{
+ ACL_IMAGE DenyACL;
+ ACL_IMAGE GrantACL;
+} ACL_DESCRIPTOR;
+
+#else
+
+///////////////////////////////////////////////////////////////////////////////
+// The following is supposed to be the ACL descriptor on the Windows NT
+// platform. Since the Windows NT version of DCOM IAccessControl implementation
+// is still under developement, the content of the following structure may
+// change in the future.
+//////////////////////////////////////////////////////////////////////////////
+typedef struct tagACL_DESCRIPTOR
+{
+ void *pACLBuffer; // Pointer to the NT ACL buffer
+ ULONG ulACLBufferSize; // Size of the ACL buffer
+ ULONG ulSIDSize; // Exacted size of all the SIDs in the NT ACL
+ BOOL bDirtyACL; // This flag indicates whether the internal
+ // ACL has been chcanged since the last time
+ // it was mapped to an NT ACL.
+ SECURITY_DESCRIPTOR SecDesc; // We need the security descriptor to call
+ // AccessCheck
+
+} ACL_DESCRIPTOR;
+
+
+
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// CFAccessControl - COAccessControl class factory.
+//////////////////////////////////////////////////////////////////////////////
+
+class CFAccessControl : public IClassFactory
+{
+private:
+
+ // Private variables.
+ LONG m_cRefs; // Object reference count
+
+public:
+
+ // IUnknown methods
+
+ STDMETHODIMP_(HRESULT) QueryInterface
+ (
+ REFIID iid,
+ void **ppv
+ );
+
+ STDMETHODIMP_(ULONG) AddRef(void);
+
+ // If the object's reference count reaches zero, the RElease method will
+ // decrement the global object count named g_cObjects in acsrv.cxx.
+ STDMETHODIMP_(ULONG) Release(void);
+
+
+ // IClassFactory methods
+ // Upon successful creation of a new COAccessControl object,
+ // the following function will increment the global object
+ // count named g_cObjects by one.
+ STDMETHODIMP_(HRESULT) CreateInstance
+ (
+ IUnknown *pUnkOuter,
+ REFIID riid,
+ void **ppv
+ );
+
+ // The following method relies on a global lock count named g_cServer
+ // which is maintained inside acsrv.cxx.
+ STDMETHODIMP_(HRESULT) LockServer
+ (
+ BOOL fLock
+ );
+
+ // Constructor
+ CFAccessControl(void);
+
+ // Destructor
+ ~CFAccessControl(void);
+
+}; // CFAccessControl
+
+//////////////////////////////////////////////////////////////////////////////
+// COAccessControl - The DCOM IAccessControl implementation component. The
+// COAccessControl componnet is implemented as a nested
+// class to support aggregation.
+//////////////////////////////////////////////////////////////////////////////
+class COAccessControl : public IUnknown
+{
+public:
+
+ // Main object IUnknown Methods - These IUnknown methods are non-delegating
+ STDMETHODIMP_(HRESULT) QueryInterface
+ (
+ REFIID riid,
+ void **ppv
+ );
+
+ STDMETHODIMP_(ULONG) AddRef(void);
+
+ // The following method relies on a global lock count named g_cServer
+ // which is maintained inside acsrv.cxx.
+ STDMETHODIMP_(ULONG) Release(void);
+
+ // Constructor
+ COAccessControl(void);
+ STDMETHODIMP_(HRESULT) Init(IUnknown *pOuter);
+
+ // Destructor
+ ~COAccessControl(void);
+
+ //////////////////////////////////////////////////////////////////////
+ // CImpAccessControl - This class is nested inside COAccessControl.
+ // The CImpAccessControl class implements
+ // the IPersistStream interface, IPersist interface
+ // , and the IAccessControl interface
+ //////////////////////////////////////////////////////////////////////
+ class CImpAccessControl : public IPersistStream, public IAccessControl
+ {
+ public:
+
+ // IUnknown methods, all calls are delegated to the controlling object.
+ STDMETHODIMP_(HRESULT) QueryInterface
+ (
+ REFIID riid,
+ void **ppv
+ );
+
+ STDMETHODIMP_(ULONG) AddRef(void);
+
+ STDMETHODIMP_(ULONG) Release(void);
+
+ // IPersist method
+
+ STDMETHODIMP_(HRESULT) GetClassID
+ (
+ CLSID *pClassID
+ );
+
+ // IPersistStream Methods
+ STDMETHODIMP_(HRESULT) IsDirty
+ (
+ void
+ );
+
+ // Object initialization method. This method must be called
+ // before any non-IUnknown methods.
+ STDMETHODIMP_(HRESULT)Load
+ (
+ IStream *pStm
+ );
+
+ STDMETHODIMP_(HRESULT)Save
+ (
+ IStream *pStm,
+ BOOL fClearDirty
+ );
+
+ STDMETHODIMP_(HRESULT) GetSizeMax
+ (
+ ULARGE_INTEGER *pcdSize
+ );
+
+ // IAccessControl Methods
+ STDMETHODIMP_(HRESULT) GrantAccessRights
+ (
+ PACTRL_ACCESSW pAccessList
+ );
+
+ // This function is not implemented.
+ STDMETHODIMP_(HRESULT) SetAccessRights
+ (
+ PACTRL_ACCESSW pAccessList
+ );
+
+ // This function is not implemented.
+ STDMETHODIMP_(HRESULT) SetOwner
+ (
+ PTRUSTEEW pOwner,
+ PTRUSTEEW pGroup
+ );
+
+ STDMETHODIMP_(HRESULT) RevokeAccessRights
+ (
+ LPWSTR lpProperty,
+ ULONG cCount,
+ TRUSTEEW pTrustee[]
+ );
+
+ STDMETHODIMP_(HRESULT) GetAllAccessRights
+ (
+ LPWSTR lpProperty,
+ PACTRL_ACCESSW *ppAccessList,
+ PTRUSTEEW *ppOwner,
+ PTRUSTEEW *ppGroup
+ );
+
+ STDMETHODIMP_(HRESULT) IsAccessAllowed
+ (
+ PTRUSTEEW pTrustee,
+ LPWSTR lpProperty,
+ ACCESS_RIGHTS AccessRights,
+ BOOL *pfAccessAllowed
+ );
+
+ // Constructor
+ CImpAccessControl
+ (
+ IUnknown *pBackPtr,
+ IUnknown *pUnkOuter
+ );
+
+ // Destructor
+ ~CImpAccessControl(void);
+
+
+ private:
+
+ STDMETHODIMP_(void) CleanupAccessList
+ (
+ BOOL fReleaseAll,
+ STREAM_ACE *pStreamACEReqs,
+ void *pACEReqs,
+ ULONG cGrant,
+ ULONG cDeny
+ );
+
+ STDMETHODIMP_(HRESULT) AddAccessList
+ (
+ STREAM_ACE *pStreamACEReqs,
+ void *pACEReqs,
+ ULONG ulEstPickledSize,
+ ULONG cGrant,
+ ULONG cDeny
+ );
+
+#ifndef _CHICAGO_
+ STDMETHODIMP_(HRESULT) GetEffAccRightsUsingSID
+ (
+ PSID pSID,
+ DWORD *pdwRights
+ );
+
+ STDMETHODIMP_(HRESULT) GetEffAccRightsUsingName
+ (
+ LPWSTR pTrusteeName,
+ DWORD *pdwRights
+ );
+#endif
+ // Static data members
+ BOOL m_bInitialized; // Object initialization flag.
+ BOOL m_bDirty; // This flag is set to TRUE if the
+ // object has been changed since the
+ // last save.
+ IUnknown *m_pUnkOuter; // Pointer to the controlling object's
+ // IUnkown implementation.
+ CRITICAL_SECTION m_ACLLock; // Critical section object for
+ // protecting the ACL from concurrent
+ // access.
+#ifdef _CHICAGO_
+ CEffectivePermsCache m_Cache; // This cache stroes the results of
+ // previous access checking.
+#else
+ CEffPermsCacheString m_CacheString; // Access check results cache indexed by Unicode string
+ CEffPermsCacheSID m_CacheSID; // Access check results cache indexed by SID.
+#endif
+ ACL_DESCRIPTOR m_ACLDesc; // Platform dependent representation
+ // of the ACL
+ PCB m_pcb; // Pickle control block
+
+ }; // COAccessControl::CImpAccessControl
+
+ // Private variables
+
+ LONG m_cRefs; // Object's reference count
+ CImpAccessControl *m_ImpObj; // Pointer to the inner CImpAccessControl object
+
+}; // COAccessControl
+
+
+#endif // #ifndef _CACCCNTRL_H_
diff --git a/private/ole32/com/accctrl/cache.cxx b/private/ole32/com/accctrl/cache.cxx
new file mode 100644
index 000000000..43f4f3241
--- /dev/null
+++ b/private/ole32/com/accctrl/cache.cxx
@@ -0,0 +1,550 @@
+//+---------------------------------------------------------------------------
+//
+// File: cache.cxx
+//
+// Copyright (c) 1996-1996, Microsoft Corp. All rights reserved.
+//
+// Description: This file contains the implementation of the
+// CEffectivePermsCache class. The cache is implemented as a hash
+// without any fancy mechanism to handle collisions. If a
+// collision occur, the old entry is simply overwritten.
+//
+// Classes: CEffectivePermsCache
+//
+//+---------------------------------------------------------------------------
+
+#include <windows.h>
+#include <ole2.h>
+#include "Cache.h"
+#define BIG_PRIME 48271
+#define SMALL_PRIME 2683
+
+#include "acext.h"
+
+// constructor
+
+#ifdef _CHICAGO_
+CEffectivePermsCache::CEffectivePermsCache(void)
+#else
+CEffPermsCacheString::CEffPermsCacheString(void)
+#endif
+{
+ // Set the whole cache to null
+ memset(m_cache, 0 , CACHE_SIZE * sizeof(CACHE_ENTRY));
+ // Create an instance of the critical section object.
+ InitializeCriticalSection(&m_CacheLock);
+
+}
+
+// destructor
+#ifdef _CHICAGO_
+CEffectivePermsCache::~CEffectivePermsCache(void)
+#else
+CEffPermsCacheString::~CEffPermsCacheString(void)
+#endif
+{
+ // Flush the cache to free memory allocated for strings
+ FlushCache();
+ // Destroy critical section object
+ DeleteCriticalSection(&m_CacheLock);
+}
+
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CEffectivePermsCache::Hash, private
+//
+// Summary: This function returns a hash value for a Unicode string
+//
+// Args: LPWSTR pwszString [in]- Pointer to a null terminated Unicode string.
+//
+// Modifies: Nothing
+//
+// Return: DWORD - The hash value of the string.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+
+#ifdef _CHICAGO_
+DWORD CEffectivePermsCache::Hash
+#else
+DWORD CEffPermsCacheString::Hash
+#endif
+(
+LPWSTR pwszString
+)
+{
+ DWORD dwHashValue = 0;
+ LPWSTR pwszWCHAR = pwszString;
+ WCHAR wc;
+ ULONG ulStrLen = lstrlenW(pwszString);
+
+ for (USHORT i = 0; i < ulStrLen; i++, pwszWCHAR++)
+ {
+ wc = *pwszWCHAR;
+ // Make the hash function case insensitive
+ wc = toupper(wc);
+
+ dwHashValue = ((dwHashValue + wc) * SMALL_PRIME) % BIG_PRIME;
+ } // for
+
+ return (dwHashValue % CACHE_SIZE);
+
+} // Hash
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CEffectivePermsCache::LookUpEntry
+//
+// Summary: This function search for the effective permission of a trustee
+// given the trustee name in Unicode.
+//
+// Args: LPWSTR pName [in] - The name of the trustee in unicode.
+//
+// Modifies: Nothing.
+//
+// Return: TRUE - If the the trustee's effective permission is found in
+// the cache.
+// FALSE - Otherwise.
+//
+// Actions: 1) Computes the hash value of the input string, k.
+// 2) Compares the name in the kth entry of the cache with the
+// trustee's name.
+// 3) If the trustee's name matches, sets *pdwEffectivePermissions to the
+// effective permissions in the cache entry and returns TRUE.
+// 4) Returns FALSE otherwise.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+
+#ifdef _CHICAGO_
+BOOL CEffectivePermsCache::LookUpEntry
+#else
+BOOL CEffPermsCacheString::LookUpEntry
+#endif
+(
+LPWSTR pName,
+DWORD *pdwEffectivePermissions
+)
+{
+ CACHE_ENTRY *pCacheEntry = m_cache + Hash(pName);
+
+ EnterCriticalSection(&m_CacheLock);
+#ifdef _CHICAGO_
+ if (FoolstrcmpiW(pName, pCacheEntry->pName) == 0)
+#else
+ if ((pCacheEntry->pName != NULL) && (lstrcmpiW(pName, pCacheEntry->pName) == 0))
+#endif
+ {
+ *pdwEffectivePermissions = pCacheEntry->dwEffectivePermissions;
+ LeaveCriticalSection(&m_CacheLock);
+ return TRUE;
+ } // if
+ else
+ {
+ LeaveCriticalSection(&m_CacheLock);
+ return FALSE;
+
+ } // else
+} // LookUpEntry
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CEffectivePermsCache::DeleteEntry
+//
+// Summary: This function search for the effective permission of a
+//
+// Args: LPWSTR pName [in] - The name of the trustee in unicode.
+//
+// Modifies: Nothing.
+//
+// Return: TRUE - If the the trustee's effective permission is found in
+// the cache.
+// FALSE - Otherwise.
+//
+// Actions: 1) Computes the hash value of the input string, k.
+// 2) Compares the name in the kth entry of the cache with the
+// trustee's name.
+// 3) If the trustee's name matches, frees memory allocated for
+// *pCacheEntry->pName, sets *pCacheEntry->pName to
+// NULL and returns TRUE.
+// 4) Returns FALSE otherwise.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+
+#ifdef _CHICAGO_
+BOOL CEffectivePermsCache::DeleteEntry
+#else
+BOOL CEffPermsCacheString::DeleteEntry
+#endif
+(
+LPWSTR pName
+)
+{
+ CACHE_ENTRY *pCacheEntry = m_cache + Hash(pName);
+ LPWSTR pCacheName;
+
+ EnterCriticalSection(&m_CacheLock);
+ pCacheName = pCacheEntry->pName;
+#ifdef _CHICAGO_
+ if (FoolstrcmpiW(pName, pCacheName) == 0)
+#else
+ if ((pCacheName != NULL) && (lstrcmpiW(pName, pCacheName) == 0))
+#endif
+ {
+ LocalMemFree(pCacheName);
+ pCacheEntry->pName = NULL;
+ LeaveCriticalSection(&m_CacheLock);
+ return TRUE;
+ } // if
+ else
+ {
+ LeaveCriticalSection(&m_CacheLock);
+ return FALSE;
+
+ } // else
+} // DeleteEntry
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CEffectivePermsCache::WriteEntry
+//
+// Summary: This function writes a new entry to the cache. In case of a hash
+// collision the old entry is overwritten.
+//
+// Args: LPWSTR pName [in] - Name of the trustee in the form of a NULL
+// terminated unicode string.
+// DWORD dwEffectivePermissions [in] - The set of effective
+// permissions that belong to the
+// trustee.
+//
+// Modifies: m_cache - The object's private hash table.
+//
+// Return: TRUE - If the operation is successful.
+// FALSE - If there is not enough memory to allocate the new string.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+
+#ifdef _CHICAGO_
+BOOL CEffectivePermsCache::WriteEntry
+#else
+BOOL CEffPermsCacheString::WriteEntry
+#endif
+(
+LPWSTR pName,
+DWORD dwEffectivePermissions
+)
+{
+ CACHE_ENTRY *pCacheEntry = m_cache + Hash(pName);
+ ULONG ulcStringLength;
+
+ // See if the name is already in the cache
+ // and avoid reallocating a new string if possible.
+ EnterCriticalSection(&m_CacheLock);
+#ifdef _CHICAGO_
+ if (FoolstrcmpiW(pName, pCacheEntry->pName) != 0)
+#else
+ if ((pCacheEntry->pName == NULL) || (lstrcmpiW(pName, pCacheEntry->pName) != 0))
+#endif
+ {
+ if (pCacheEntry->pName != NULL)
+ {
+ // Free the old list if there was an old entry
+ // in the slot
+ LocalMemFree(pCacheEntry->pName);
+ } // if
+ ulcStringLength = lstrlenW(pName) + 1;
+ pCacheEntry->pName = (LPWSTR)LocalMemAlloc(ulcStringLength * sizeof(WCHAR));
+ if (pCacheEntry->pName == NULL)
+ {
+ // Out of memory error
+ LeaveCriticalSection(&m_CacheLock);
+ return FALSE;
+ } // if
+
+ memcpy(pCacheEntry->pName, pName, sizeof(WCHAR) * ulcStringLength);
+ } // if
+
+ pCacheEntry->dwEffectivePermissions = dwEffectivePermissions;
+ LeaveCriticalSection(&m_CacheLock);
+ return TRUE;
+} // WriteEntry
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CEffectivePermsCache::FlushCache
+//
+// Summary: This function empties the cache
+//
+// Args: void
+//
+// Modifies: m_cache - The object's private hash table
+//
+// Return: void
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+
+#ifdef _CHICAGO_
+void CEffectivePermsCache::FlushCache
+#else
+void CEffPermsCacheString::FlushCache
+#endif
+(
+void
+)
+{
+ LPWSTR pString;
+ USHORT i = 0;
+ CACHE_ENTRY *pCache;
+
+ EnterCriticalSection(&m_CacheLock);
+ for ( i = 0, pCache = m_cache
+ ; i < CACHE_SIZE
+ ; i++, pCache++)
+ {
+ if ((pString = pCache->pName) != NULL)
+ {
+ LocalMemFree(pString);
+ pCache->pName = NULL;
+ } // if
+
+ } // for
+ LeaveCriticalSection(&m_CacheLock);
+ return;
+} // FlushCache
+
+#ifndef _CHICAGO_
+CEffPermsCacheSID::CEffPermsCacheSID(void)
+{
+ // Set the whole cache to null
+ memset(m_cache, 0 , CACHE_SIZE * sizeof(CACHE_ENTRY));
+ // Create an instance of the critical section object.
+ InitializeCriticalSection(&m_CacheLock);
+
+}
+
+// destructor
+CEffPermsCacheSID::~CEffPermsCacheSID(void)
+{
+ // Flush the cache to free memory allocated for strings
+ FlushCache();
+ // Destroy critical section object
+ DeleteCriticalSection(&m_CacheLock);
+}
+
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CEffPermsCacheSID::Hash, private
+//
+// Summary: This function returns a hash value for a security identifier.
+//
+// Args: PSID pSID [in] - Pointer to a security identifier.
+//
+// Modifies: Nothing
+//
+// Return: DWORD - The hash value of the SID.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+
+DWORD CEffPermsCacheSID::Hash
+(
+PSID pSID
+)
+{
+ DWORD dwHashValue = 0;
+ CHAR *pSIDBuff = (CHAR *)pSID;
+ DWORD dwSIDLen;
+
+ dwSIDLen = GetLengthSid(pSID);
+
+ for (USHORT i = 0; i < dwSIDLen; i++, pSIDBuff++)
+ {
+ // I have the feeling that the first line works better than the second line..
+ dwHashValue = ((dwHashValue + *pSIDBuff) * SMALL_PRIME) % BIG_PRIME;
+ } // for
+
+ return (dwHashValue % CACHE_SIZE);
+
+} // Hash
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CEffPermsCacheSID::LookUpEntry
+//
+// Summary: This function search for the effective permission of a trustee
+// given the trustee's security identifier.
+//
+// Args: PSID pSID [in] - Security identifier of the trustee.
+//
+// Modifies: Nothing.
+//
+// Return: TRUE - If the the trustee's effective permission is found in
+// the cache.
+// FALSE - Otherwise.
+//
+// Actions: 1) Computes the hash value of the input SID, k.
+// 2) Compares the SID in the kth entry of the cache with the
+// trustee's SID.
+// 3) If the trustee's SID matches, sets *pdwEffectivePermissions to the
+// effective permissions in the cache entry and return TRUE.
+// 4) Returns FALSE otherwise.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+
+BOOL CEffPermsCacheSID::LookUpEntry
+(
+PSID pSID,
+DWORD *pdwEffectivePermissions
+)
+{
+ CACHE_ENTRY *pCacheEntry = m_cache + Hash(pSID);
+
+ EnterCriticalSection(&m_CacheLock);
+ if ((pCacheEntry->pSID != NULL) && (EqualSid(pSID, pCacheEntry->pSID) == TRUE))
+ {
+ *pdwEffectivePermissions = pCacheEntry->dwEffectivePermissions;
+ LeaveCriticalSection(&m_CacheLock);
+ return TRUE;
+ } // if
+ else
+ {
+ LeaveCriticalSection(&m_CacheLock);
+ return FALSE;
+
+ } // else
+} // LookUpEntry
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CEffPermsCacheSID::DeleteEntry
+//
+// Summary: This function search for the effective permission of a
+//
+// Args: PSID pSID [in] - Security identifier of the trustee.
+//
+// Modifies: Nothing.
+//
+// Return: TRUE - If the the trustee's effective permission is found in
+// the cache.
+// FALSE - Otherwise.
+//
+// Actions: 1) Computes the hash value of the input SID, k.
+// 2) Compares the SID in the kth entry of the cache with the
+// trustee's SID.
+// 3) If the trustee's SID matches, frees memory allocated for
+// *pCacheEntry->pSID, sets *pCacheEntry->pSID to
+// NULL and returns TRUE.
+// 4) Returns FALSE otherwise.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+
+BOOL CEffPermsCacheSID::DeleteEntry
+(
+PSID pSID
+)
+{
+ CACHE_ENTRY *pCacheEntry = m_cache + Hash(pSID);
+ PSID pCacheSID;
+
+ EnterCriticalSection(&m_CacheLock);
+ pCacheSID = pCacheEntry->pSID;
+ if ((pCacheSID != NULL) && (EqualSid(pSID, pCacheSID) == TRUE))
+ {
+ LocalMemFree(pCacheSID);
+ pCacheEntry->pSID = NULL;
+ LeaveCriticalSection(&m_CacheLock);
+ return TRUE;
+ } // if
+ else
+ {
+ LeaveCriticalSection(&m_CacheLock);
+ return FALSE;
+
+ } // else
+} // DeleteEntry
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CEffPermsCacheSID::WriteEntry
+//
+// Summary: This function writes a new entry to the cache. In case of a hash
+// collision the old entry is overwritten.
+//
+// Args: PSID pSID [in] - Security identifier of the trustee.
+// DWORD dwEffectivePermissions [in] - The set of effective
+// permissions that belong to the
+// trustee.
+//
+// Modifies: m_cache - The object's private hash table.
+//
+// Return: TRUE - If the operation is successful.
+// FALSE - If there is not enough memory to allocate the new string.
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+
+BOOL CEffPermsCacheSID::WriteEntry
+(
+PSID pSID,
+DWORD dwEffectivePermissions
+)
+{
+ CACHE_ENTRY *pCacheEntry = m_cache + Hash(pSID);
+ ULONG ulSIDSize;
+
+ // See if the name is already in the cache
+ // and avoid reallocating a new string if possible.
+ EnterCriticalSection(&m_CacheLock);
+ if ((pCacheEntry->pSID == NULL) || (EqualSid(pSID, pCacheEntry->pSID) == FALSE))
+ {
+ if (pCacheEntry->pSID != NULL)
+ {
+ // Free the old list if there was an old entry
+ // in the slot
+ LocalMemFree(pCacheEntry->pSID);
+ } // if
+ ulSIDSize = GetLengthSid(pSID);
+ pCacheEntry->pSID = (PSID)LocalMemAlloc(ulSIDSize);
+ if (pCacheEntry->pSID == NULL)
+ {
+ // Out of memory error
+ LeaveCriticalSection(&m_CacheLock);
+ return FALSE;
+ } // if
+
+ CopySid(ulSIDSize, pCacheEntry->pSID, pSID);
+ } // if
+
+ pCacheEntry->dwEffectivePermissions = dwEffectivePermissions;
+ LeaveCriticalSection(&m_CacheLock);
+ return TRUE;
+} // WriteEntry
+
+//M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M
+// Method: CEffPermsCacheSID::FlushCache
+//
+// Summary: This function empties the cache
+//
+// Args: void
+//
+// Modifies: m_cache - The object's private hash table
+//
+// Return: void
+//
+//M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M
+
+void CEffPermsCacheSID::FlushCache
+(
+void
+)
+{
+ PSID pSID;
+ USHORT i = 0;
+ CACHE_ENTRY *pCache;
+
+ EnterCriticalSection(&m_CacheLock);
+ for ( i = 0, pCache = m_cache
+ ; i < CACHE_SIZE
+ ; i++, pCache++)
+ {
+ if ((pSID = pCache->pSID) != NULL)
+ {
+ LocalMemFree(pSID);
+ pCache->pSID = NULL;
+ } // if
+
+ } // for
+ LeaveCriticalSection(&m_CacheLock);
+ return;
+} // FlushCache
+
+#endif
diff --git a/private/ole32/com/accctrl/cache.h b/private/ole32/com/accctrl/cache.h
new file mode 100644
index 000000000..b9d1bbe9c
--- /dev/null
+++ b/private/ole32/com/accctrl/cache.h
@@ -0,0 +1,159 @@
+//+---------------------------------------------------------------------------
+//
+// File: Cache.h
+//
+// Description: This file contains the definition of the CEffectivePermsCache
+// class which is used by the COleDs_AcccessControl class to
+// speed up the access checking process. Access to the cache is
+// made thread safe through the use of a critical section object.
+// Classes: CEffectivePermsCache
+//
+// See the Cache.cpp source file for detail description of each of the
+// methods.
+//+---------------------------------------------------------------------------
+
+#ifndef _CACHE_H_
+#define _CACHE_H_
+#define CACHE_SIZE 23
+
+
+#ifdef _CHICAGO_
+class CEffectivePermsCache
+{
+public:
+
+ BOOL LookUpEntry
+ (
+ LPWSTR pName,
+ DWORD *pdwEffectivePermissions
+ );
+
+ BOOL WriteEntry
+ (
+ LPWSTR pName,
+ DWORD dwEffectivePermissions
+ );
+
+ BOOL DeleteEntry
+ (
+ LPWSTR pName
+ );
+
+ void FlushCache(void);
+
+ void DumpCache(void);
+
+ // constructor
+ CEffectivePermsCache(void);
+
+ // destructor
+ ~CEffectivePermsCache(void);
+
+
+private:
+
+ typedef struct tagCACHE_ENTRY
+ {
+ LPWSTR pName;
+ DWORD dwEffectivePermissions;
+ } CACHE_ENTRY;
+
+ CACHE_ENTRY m_cache[CACHE_SIZE];
+ DWORD Hash(LPWSTR pStr);
+ CRITICAL_SECTION m_CacheLock;
+
+};
+#else
+class CEffPermsCacheString
+{
+public:
+
+ BOOL LookUpEntry
+ (
+ LPWSTR pName,
+ DWORD *pdwEffectivePermissions
+ );
+
+ BOOL WriteEntry
+ (
+ LPWSTR pName,
+ DWORD dwEffectivePermissions
+ );
+
+ BOOL DeleteEntry
+ (
+ LPWSTR pName
+ );
+
+ void FlushCache(void);
+
+ void DumpCache(void);
+
+ // constructor
+ CEffPermsCacheString(void);
+
+ // destructor
+ ~CEffPermsCacheString(void);
+
+
+private:
+
+ typedef struct tagCACHE_ENTRY
+ {
+ LPWSTR pName;
+ DWORD dwEffectivePermissions;
+ } CACHE_ENTRY;
+
+ CACHE_ENTRY m_cache[CACHE_SIZE];
+ DWORD Hash(LPWSTR pStr);
+ CRITICAL_SECTION m_CacheLock;
+
+};
+
+class CEffPermsCacheSID
+{
+public:
+
+ BOOL LookUpEntry
+ (
+ PSID pSID,
+ DWORD *pdwEffectivePermissions
+ );
+
+ BOOL WriteEntry
+ (
+ PSID pSID,
+ DWORD dwEffectivePermissions
+ );
+
+ BOOL DeleteEntry
+ (
+ PSID pSID
+ );
+
+ void FlushCache(void);
+
+ void DumpCache(void);
+
+ // constructor
+ CEffPermsCacheSID(void);
+
+ // destructor
+ ~CEffPermsCacheSID(void);
+
+
+private:
+
+ typedef struct tagCACHE_ENTRY
+ {
+ PSID pSID;
+ DWORD dwEffectivePermissions;
+ } CACHE_ENTRY;
+
+ CACHE_ENTRY m_cache[CACHE_SIZE];
+ DWORD Hash(PSID pSID);
+ CRITICAL_SECTION m_CacheLock;
+
+};
+#endif
+#endif // #ifndef _CACHE_H_
diff --git a/private/ole32/com/accctrl/daytona/makefile b/private/ole32/com/accctrl/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/accctrl/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/accctrl/daytona/makefile.inc b/private/ole32/com/accctrl/daytona/makefile.inc
new file mode 100644
index 000000000..4f0e5b8fa
--- /dev/null
+++ b/private/ole32/com/accctrl/daytona/makefile.inc
@@ -0,0 +1 @@
+!include ..\makeidl.inc
diff --git a/private/ole32/com/accctrl/daytona/sources b/private/ole32/com/accctrl/daytona/sources
new file mode 100644
index 000000000..aa7a9754d
--- /dev/null
+++ b/private/ole32/com/accctrl/daytona/sources
@@ -0,0 +1,72 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Raymond Mak (2nd July, 1996)
+
+!ENDIF
+
+
+MAJORCOMP = daytona
+MINORCOMP = com
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= accctrl
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES = $(BASEDIR)\public\sdk\inc;obj
+INCLUDES = $(INCLUDES);..\..\inc;..\..\..\ih
+INCLUDES= $(INCLUDES);..\..\..\..\dcomidl\obj;..\..\dcomidl\daytona
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -D_WIN32_DCOM
+
+SOURCES= \
+ acpickl_c.c \
+ ..\acsrv.cxx \
+ ..\cache.cxx \
+ ..\caccctrl.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+# Generate stubs from idl files
+NTTARGETFILE0=allidl
+
diff --git a/private/ole32/com/accctrl/dirs b/private/ole32/com/accctrl/dirs
new file mode 100644
index 000000000..3a617a726
--- /dev/null
+++ b/private/ole32/com/accctrl/dirs
@@ -0,0 +1,40 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+ Modified to build DCOM IAccessControl by
+ Raymond Mak (t-raymak) 23-Jul-1996
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ chicago \
+ daytona
+
diff --git a/private/ole32/com/accctrl/makeidl.inc b/private/ole32/com/accctrl/makeidl.inc
new file mode 100644
index 000000000..bcd1ce73d
--- /dev/null
+++ b/private/ole32/com/accctrl/makeidl.inc
@@ -0,0 +1,24 @@
+!ifndef MIDL
+MIDL = midl.exe
+!endif
+
+MIDL_FLAGS= \
+ -Zp8 \
+ -Oicf \
+ -I$(INCLUDES:;= -I) -I.. \
+ -char unsigned \
+ -error allocation \
+ -error bounds_check \
+ -error stub_data \
+ -cpp_cmd $(TARGET_CPP) \
+ -DMIDL_PASS $(C_DEFINES)
+
+obj\acpickl.h: ..\acpickl.idl ..\acpickl.acf
+ $(MIDL) $(MIDL_FLAGS) \
+ -server none -header $@ ..\acpickl.idl
+
+allidl: obj\acpickl.h
+
+clean:
+ del obj\acpickl.h >NUL 2>NUL
+
diff --git a/private/ole32/com/class/alocdbg.cxx b/private/ole32/com/class/alocdbg.cxx
new file mode 100644
index 000000000..cb765ab4a
--- /dev/null
+++ b/private/ole32/com/class/alocdbg.cxx
@@ -0,0 +1,731 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows:
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: alocdbg.cxx
+//
+// Contents: Supports symbolic stack trace dumps for leaked memory
+// allocations
+//
+// Classes: AllocArenaDump
+//
+// Functions: CoGetMalloc
+//
+// History: 04-Nov-93 AlexT Created
+// 09-Nov-95 BruceMa Added this header
+// Use imagehlp.dll rather than symhelp.dll
+//
+//--------------------------------------------------------------------------
+
+
+
+/*
+ * This file implements an arena that tracks memory allocations and frees.
+ * Isaache
+ */
+
+#if !defined(_CHICAGO_)
+extern "C" {
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <stdio.h>
+}
+#endif
+
+#include <ole2int.h>
+
+#if DBG == 1
+
+#include <imagehlp.h>
+#include <except.hxx>
+#include <alocdbg.h>
+
+#pragma optimize( "y", off )
+
+DECLARE_INFOLEVEL( heap );
+DECLARE_DEBUG( heap );
+#define heapDebugOut(x) heapInlineDebugOut x
+
+/*
+ * The maximum number of AllocArenaCreate's we expect
+ */
+static const MAXARENAS = 5;
+
+/*
+ * When printing leak dumps, the max number we will print out. Note, we keep
+ * track of all of them, we just don't want to take forever to terminate a
+ * process
+ */
+static const MAXDUMP = 50;
+
+/*
+ * The maximum size we'll let any single debug arena get
+ */
+static const ULONG ARENASIZE = 1024*1024;
+
+/*
+ * The unit of growth for the arena holding the AllocArena data.
+ * Must be a power of 2
+ */
+static const ALLOCRECINCR = 128;
+
+
+// The maximum symbol length we allow
+static const ULONG MAXNAMELENGTH = 128;
+
+
+static AllocArena *AllocArenas[ MAXARENAS + 1 ];
+
+
+// This is our interface to symhelp for address translation
+ULONG RealTranslate ( ULONG, LPSTR, ULONG );
+
+
+ULONG MissingTranslate (
+ ULONG Address,
+ LPSTR Name,
+ ULONG MaxNameLength )
+{
+ return _snprintf( Name, MaxNameLength, "0x%08x [imagehlp.dll missing]", Address );
+
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: RealTranslate
+//
+// Synopsis: Interfaces to imagehlp!SymGetSymFromAddr
+//
+// Arguments: [cFrameSkipped] -- How many stack frames to skip over and
+//
+// Returns: BOOL
+//
+// History: 09-Nov-95 BruceMa Created
+//
+//----------------------------------------------------------------------------
+ULONG RealTranslate ( ULONG address, LPSTR name, ULONG maxNameLength )
+{
+ IMAGEHLP_MODULE mod;
+ char dump[sizeof(IMAGEHLP_SYMBOL) + MAXNAMELENGTH];
+ char UnDDump[ MAXNAMELENGTH ];
+ PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL) &dump;
+ DWORD dwDisplacement;
+
+ // Fetch the module name
+ mod.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
+ if (!SymGetModuleInfo(GetCurrentProcess(), address, &mod))
+ {
+ sprintf(name, "%08lx !\0", address);
+ }
+ else
+ {
+ // Copy the address and module name
+ sprintf(name, "%08lx %s!\0", address, mod.ModuleName);
+ }
+
+
+ // Have to do this because size of sym is dynamically determined
+ pSym->SizeOfStruct = sizeof(dump);
+ pSym->MaxNameLength = MAXNAMELENGTH;
+
+ // Fetch the symbol
+ if (SymGetSymFromAddr(GetCurrentProcess(),
+ address,
+ &dwDisplacement,
+ pSym))
+ {
+ SymUnDName( pSym, UnDDump, sizeof(UnDDump ) );
+ // Copy the symbol
+ strcat(name, UnDDump );
+ }
+
+
+ // Copy the displacement
+ char szDisplacement[16];
+
+ strcat(name, "+");
+ sprintf(szDisplacement, "0x%x\0", dwDisplacement);
+ strcat(name, szDisplacement);
+
+ return TRUE;
+}
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: RecordStack functions(s) below...per processor type
+//
+// Synopsis: Record a stack backtrace into fTrace
+//
+// Arguments: [cFrameSkipped] -- How many stack frames to skip over and
+// not record
+// [fTrace] -- The recorded frames are put in here
+//
+// Returns: A checksum of the stack frames for fast initial lookups
+//
+// Notes: If we can do stack backtracing for whatever processor we're
+// compiling for, the #define CANDOSTACK
+//
+//----------------------------------------------------------------------------
+
+#if defined (_CHICAGO_)
+
+static inline DWORD
+RecordStack( int cFrameSkipped, void *fTrace[ DEPTHTRACE ] )
+{
+ return 0;
+}
+
+
+#else
+
+#define CANDOSTACK
+#define SYM_HANDLE GetCurrentProcess( )
+#if defined(_M_IX86)
+#define MACHINE_TYPE IMAGE_FILE_MACHINE_I386
+#elif defined(_M_MRX000)
+#define MACHINE_TYPE IMAGE_FILE_MACHINE_R4000
+#elif defined(_M_ALPHA)
+#define MACHINE_TYPE IMAGE_FILE_MACHINE_ALPHA
+#elif defined(_M_PPC)
+#define MACHINE_TYPE IMAGE_FILE_MACHINE_POWERPC
+#else
+#error( "unknown target machine" );
+#endif
+
+inline int
+SaveOffExceptionContext( void * fTrace[ DEPTHTRACE],
+ DWORD & sum,
+ EXCEPTION_POINTERS * pPtrs )
+{
+ CONTEXT Context;
+ STACKFRAME StackFrame;
+
+ Context = *(pPtrs->ContextRecord);
+ ZeroMemory( &StackFrame, sizeof(StackFrame) );
+
+#if defined(_M_IX86)
+ StackFrame.AddrPC.Offset = Context.Eip;
+ StackFrame.AddrPC.Mode = AddrModeFlat;
+ StackFrame.AddrFrame.Offset = Context.Ebp;
+ StackFrame.AddrFrame.Mode = AddrModeFlat;
+ StackFrame.AddrStack.Offset = Context.Esp;
+ StackFrame.AddrStack.Mode = AddrModeFlat;
+#endif
+
+ int i = 3;
+ BOOL rVal = TRUE;
+
+ // skip spurious stack frames from RaiseException and ourselves
+ while ( (i-- > 0 ) && rVal )
+ {
+ // skip our own stack frame
+ rVal = StackWalk( MACHINE_TYPE,
+ SYM_HANDLE,
+ 0,
+ &StackFrame,
+ &Context,
+ ReadProcessMemory,
+ SymFunctionTableAccess,
+ SymGetModuleBase,
+ NULL );
+ }
+
+ // now process the interesting stack frames
+ i = 0;
+ while ( (i < DEPTHTRACE) && rVal )
+ {
+
+ rVal = StackWalk( MACHINE_TYPE,
+ SYM_HANDLE,
+ 0,
+ &StackFrame,
+ &Context,
+ ReadProcessMemory,
+ SymFunctionTableAccess,
+ SymGetModuleBase,
+ NULL );
+
+ if (rVal )
+ {
+ fTrace[i++] = (void*) StackFrame.AddrPC.Offset;
+ sum += (DWORD) StackFrame.AddrPC.Offset;
+ }
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+#endif
+
+static inline DWORD
+RecordStack( int cFrameSkipped, void *fTrace[ DEPTHTRACE ] )
+{
+
+ // we need a context record, and there isn't any clean way to
+ // get our own context, so we deliberately cause an exception
+ // and catch it, then save off and look at the context record.
+
+ DWORD sum = 0;
+
+ __try
+ {
+ EXCEPTION_RECORD Except;
+ ZeroMemory( &Except, sizeof(Except) );
+
+ // we raise the exception 0!
+ RtlRaiseException( &Except );
+
+ }
+ // the exception handler puts everything in the trace block, and
+ // fills in the sum
+ __except( SaveOffExceptionContext( fTrace,
+ sum,
+ GetExceptionInformation() ) )
+ {
+ }
+
+ return sum;
+
+}
+
+//
+// This allows external monitoring of heap activity by caiheap.exe
+//
+STDAPI_( AllocArena ** )
+AllocArenaAddr( void )
+{
+ return AllocArenas;
+}
+
+//
+// Create an arena for recording allocation statistics. Return the arena
+// pointer to the caller
+//
+STDAPI_( AllocArena * )
+AllocArenaCreate( DWORD memctx, char FAR *comment )
+{
+ // the first time through, we set up the symbol handler
+ static int FirstTime = TRUE;
+ if ( FirstTime )
+ {
+ SymSetOptions( SYMOPT_DEFERRED_LOADS );
+ SymInitialize( SYM_HANDLE, NULL, TRUE );
+ FirstTime = FALSE;
+ }
+
+ struct AllocArena *paa = NULL;
+
+ if( memctx == MEMCTX_TASK ) {
+#if defined( CANDOSTACK )
+ if( heapInfoLevel & DEB_WARN ) {
+
+ paa = (struct AllocArena *)VirtualAlloc(
+ NULL, ARENASIZE, MEM_RESERVE, PAGE_NOACCESS );
+ if( paa == NULL )
+ return NULL;
+
+ paa = (AllocArena *)VirtualAlloc( paa,
+ sizeof(*paa)+(ALLOCRECINCR-1)*sizeof(HeapAllocRec),
+ MEM_COMMIT, PAGE_READWRITE );
+
+ }
+ else
+#endif
+ {
+ paa = (struct AllocArena *)LocalAlloc( LPTR, sizeof(*paa) );
+ }
+ }
+
+ if( paa == NULL )
+ return NULL;
+
+ memcpy( paa->Signature,HEAPSIG,sizeof(HEAPSIG));
+ if( comment )
+ strncpy(paa->comment, comment, sizeof(paa->comment) );
+
+ InitializeCriticalSection( &paa->csExclusive );
+
+ for( int i=0; i < MAXARENAS; i++ )
+ if( AllocArenas[i] == 0 ) {
+ AllocArenas[i] = paa;
+ break;
+ }
+
+#if defined( CANDOSTACK )
+ if(!(heapInfoLevel & DEB_ITRACE))
+#endif
+ {
+ paa->flags.KeepStackTrace = 0;
+ paa->AllocRec[0].paa = paa;
+ return paa;
+ }
+
+#if defined( CANDOSTACK )
+ paa->cRecords = ALLOCRECINCR;
+ paa->cTotalRecords = ALLOCRECINCR;
+ paa->flags.KeepStackTrace = 1;
+
+ return paa;
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: AllocArenaRecordAlloc
+//
+// Synopsis: Keep a hash table of the stack backtraces of the allocations
+// we've done.
+//
+// Arguments: [paa] -- Return value from AllocArenaCreate() above
+// [bytes] -- the number of bytes being allocated by the caller.
+// This value is recorded in the stack backtrace entry.
+//
+// Algorithm: The arena for the AllocArena is created with VirtualAlloc.
+// pAllocArena->cRecords is the index of the next
+// free record. The first ALLOCRECINCR records are heads
+// of separate lists of the records.
+//
+// Returns: A pointer to the AllocRec structure recording the entry.
+// Can return NULL if we can't record the allocation.
+//
+//----------------------------------------------------------------------------
+STDAPI_( HeapAllocRec FAR * )
+AllocArenaRecordAlloc( AllocArena *paa, size_t bytes )
+{
+ if( paa == NULL )
+ return NULL;
+
+ EnterCriticalSection( &paa->csExclusive );
+
+ if( bytes ) {
+ paa->cAllocs++;
+ paa->cBytesNow += bytes;
+ paa->cBytesTotal += bytes;
+ } else {
+ paa->czAllocs++;
+ }
+
+ //
+ // Record 'size' in the histogram of requests
+ //
+ for( int i=31; i>=0; i-- )
+ if( bytes & (1<<i) ) {
+ ++(paa->Histogram.total[i]);
+ if( paa->Histogram.simul[i] < ++(paa->Histogram.now[i]))
+ paa->Histogram.simul[i] = paa->Histogram.now[i];
+ break;
+ }
+
+ LeaveCriticalSection( &paa->csExclusive );
+
+#if defined( CANDOSTACK )
+ if( paa->flags.KeepStackTrace == 0 )
+#endif
+ return &paa->AllocRec[0];
+
+#if defined( CANDOSTACK )
+
+ DWORD sum;
+ struct HeapAllocRec *phar,*hp;
+ void *fTrace[ DEPTHTRACE ];
+
+ //
+ // See if we find an existing record of this stack backtrace
+ //
+ memset( fTrace, '\0', sizeof( fTrace ) );
+ sum = RecordStack( 1, fTrace );
+
+ hp = &paa->AllocRec[ sum & (ALLOCRECINCR-1) ];
+
+ EnterCriticalSection( &paa->csExclusive );
+
+ for( phar = hp; phar != NULL; phar = phar->u.next )
+ if( phar->sum == sum && !memcmp(phar->fTrace,fTrace,sizeof(fTrace)))
+ {
+ phar->count++;
+ phar->bytes += bytes;
+ phar->total.bytes += bytes;
+ phar->total.count++;
+ phar->paa = paa;
+ LeaveCriticalSection( &paa->csExclusive );
+ return phar;
+ }
+ //
+ // We have no record of this allocation. Make one!
+ //
+ if( hp->total.count && paa->cRecords == paa->cTotalRecords ) {
+ //
+ // The arena is currently full. Grow it by ALLOCRECINCR
+ //
+ AllocArena *npHeap;
+
+ npHeap = (AllocArena *)VirtualAlloc(
+ paa,
+ sizeof(AllocArena)+
+ ((paa->cTotalRecords + ALLOCRECINCR) *
+ sizeof(HeapAllocRec) ),
+ MEM_COMMIT, PAGE_READWRITE );
+
+ if( npHeap != paa ) {
+ paa->cMissed++;
+ LeaveCriticalSection( &paa->csExclusive );
+ return NULL;
+ }
+
+ paa->cTotalRecords += ALLOCRECINCR;
+ }
+
+ if( hp->total.count == 0 ) {
+ phar = hp;
+ } else {
+ phar = &paa->AllocRec[ paa->cRecords++ ];
+ phar->u.next = hp->u.next;
+ hp->u.next = phar;
+ }
+
+ paa->cPaths++;
+
+ memcpy( phar->fTrace, fTrace, sizeof( fTrace ) );
+ phar->count = phar->total.count = 1;
+ phar->bytes = phar->total.bytes = bytes;
+ phar->sum = sum;
+ phar->paa = paa;
+ LeaveCriticalSection( &paa->csExclusive );
+ return phar;
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: AllocArenaRecordReAlloc
+//
+// Synopsis: Update the record to reflect the fact that we've ReAlloc'd
+// the memory chunk.
+//
+// Arguments: [vp] -- Return value from AllocArenaRecordAlloc() above
+// [oldbytes] -- size of the memory before ReAllocation
+// [newbytes] -- new size of the memory
+//
+//----------------------------------------------------------------------------
+STDAPI_( void )
+AllocArenaRecordReAlloc( HeapAllocRec FAR *vp, size_t oldbytes, size_t newbytes)
+{
+ if( vp == NULL )
+ return;
+
+ struct AllocArena *paa = vp->paa;
+
+ EnterCriticalSection( &paa->csExclusive );
+
+ paa->cReAllocs++;
+ paa->cBytesNow -= oldbytes;
+ paa->cBytesNow += newbytes;
+
+ if( newbytes > oldbytes )
+ paa->cBytesTotal += newbytes - oldbytes;
+
+ //
+ // Take 'oldbytes' out of the histogram of requests
+ //
+ for( int i=31; i>=0; i-- )
+ if( oldbytes & (1<<i) ) {
+ --(paa->Histogram.now[i]);
+ break;
+ }
+
+ //
+ // Record 'newbytes' in the histogram of requests
+ //
+ for( i=31; i>=0; i-- )
+ if( newbytes & (1<<i) ) {
+ ++(paa->Histogram.total[i]);
+ if( paa->Histogram.simul[i] < ++(paa->Histogram.now[i]))
+ paa->Histogram.simul[i] = paa->Histogram.now[i];
+ break;
+ }
+
+#if defined( CANDOSTACK )
+ if( paa->flags.KeepStackTrace ) {
+ vp->bytes -= oldbytes;
+ vp->bytes += newbytes;
+ vp->total.count++;
+ if( newbytes > oldbytes )
+ vp->total.bytes += newbytes;
+ }
+#endif
+
+ LeaveCriticalSection( &paa->csExclusive );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: AllocArenaRecordFree
+//
+// Synopsis: Caller has freed memory -- keep accounting up to date
+//
+// Arguments: [vp] -- Value returned by AllocArenaRecordAlloc() above
+// [bytes] -- The number of bytes being freed
+//
+// Algorithm: AllocRec structures, once allocated, are never actually
+// freed back to the Hash memory arena. This helps us
+// understand historical use of the heap.
+//
+//----------------------------------------------------------------------------
+STDAPI_( void )
+AllocArenaRecordFree( HeapAllocRec FAR *vp, size_t bytes )
+{
+ if( vp == NULL )
+ return;
+
+ struct AllocArena *paa = vp->paa;
+
+ EnterCriticalSection( &paa->csExclusive );
+
+ //
+ // Record this free in the histogram
+ //
+ for( int i=31; i>=0; i-- )
+ if( bytes & (1<<i) ) {
+ --(paa->Histogram.now[i]);
+ break;
+ }
+
+ paa->cFrees++;
+ paa->cBytesNow -= bytes;
+
+#if defined( CANDOSTACK )
+ if( paa->flags.KeepStackTrace ) {
+ vp->count--;
+ vp->bytes -= bytes;
+ }
+#endif
+
+ LeaveCriticalSection( &paa->csExclusive );
+}
+
+STDAPI_( void )
+AllocArenaDumpRecord( HeapAllocRec FAR *bp )
+{
+
+ char achBuffer[ MAX_PATH ], *p;
+ static int FirstTime = TRUE;
+
+ // make sure we print the nice undecorated names
+ if ( FirstTime )
+ {
+ SymSetOptions( SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS );
+ FirstTime = FALSE;
+ }
+
+
+ heapDebugOut((DEB_WARN, "*** %d allocs, %u bytes:\n",
+ bp->count, bp->bytes ));
+
+ for( int j=0; j<DEPTHTRACE && bp->fTrace[j]; j++ )
+ {
+ RealTranslate((ULONG)bp->fTrace[j],
+ achBuffer,
+ sizeof(achBuffer));
+
+ if( p = strchr( achBuffer, '\n' ) )
+ *p = '\0';
+ heapDebugOut((DEB_WARN, " %s\n", achBuffer));
+ }
+
+}
+
+extern "C" ULONG DbgPrint( PCH Format, ... );
+
+STDAPI_( void )
+AllocArenaDump( AllocArena *paa )
+{
+ if( paa == NULL ) {
+ for( int i = 0; i < MAXARENAS && AllocArenas[i]; i++ )
+ AllocArenaDump( AllocArenas[i] );
+ return;
+ }
+
+ char *cmdline = GetCommandLineA();
+
+ if( cmdline == NULL )
+ cmdline = "???";
+
+ HeapAllocRec *bp = paa->AllocRec;
+ HeapAllocRec *ep = bp + paa->cRecords;
+
+ if( paa->cBytesNow )
+ heapDebugOut((DEB_WARN, "***** %u bytes leaked mem for %s in '%s'\n", paa->cBytesNow, paa->comment, cmdline ));
+
+#if defined( CANDOSTACK )
+ if( paa->cBytesNow && paa->flags.KeepStackTrace )
+ {
+ int cleaks = 0;
+
+ for( ; bp < ep; bp++) {
+ if( bp->count )
+ ++cleaks;
+ }
+
+ if( cleaks ) {
+ heapDebugOut((DEB_WARN, "***** %s %u MEM LEAKS\n",
+ paa->comment, cleaks ));
+
+ if( heapInfoLevel & DEB_TRACE ) {
+ HeapAllocRec *bp;
+ UINT maxdump = MAXDUMP;
+ for( bp = paa->AllocRec; maxdump && bp<ep; bp++)
+ if( bp->count ) {
+ heapDebugOut((DEB_TRACE, "\n"));
+ AllocArenaDumpRecord( bp );
+ maxdump--;
+ }
+ } else if( cleaks )
+ heapDebugOut((DEB_WARN, "** Set ole32!heapInfoLevel to x707 for leak backtrace\n"));
+
+ }
+ }
+#endif
+
+ if( (heapInfoLevel & DEB_TRACE) && paa->cBytesTotal )
+ {
+ heapDebugOut((DEB_TRACE,"\n"));
+ heapDebugOut((DEB_TRACE,
+ "'%s' Memory Stats: %u allocations, %u frees\n",
+ cmdline, paa->cAllocs, paa->cFrees ));
+
+ if( paa->czAllocs )
+ heapDebugOut((DEB_TRACE,
+ "\t%u zero allocs\n", paa->czAllocs ));
+
+ heapDebugOut((DEB_TRACE,
+ "\t%u bytes allocated\n", paa->cBytesTotal ));
+
+ heapDebugOut((DEB_TRACE,
+ "*** Histogram of Allocated Mem Sizes ***\n"));
+
+ heapDebugOut((DEB_TRACE, " Min Max\t Tot\t Simul\n" ));
+ for( int i=0; i < 32; i++ )
+ if( paa->Histogram.total[i] )
+ {
+ heapDebugOut((DEB_TRACE,
+ "%6u -> %6u\t%6u\t%6u\n",
+ 1<<i, (1<<(i+1))-1,
+ paa->Histogram.total[i],
+ paa->Histogram.simul[i]
+ ));
+ }
+ }
+}
+
+#endif // DBG
diff --git a/private/ole32/com/class/bestfit.hxx b/private/ole32/com/class/bestfit.hxx
new file mode 100644
index 000000000..3b1b9630a
--- /dev/null
+++ b/private/ole32/com/class/bestfit.hxx
@@ -0,0 +1,450 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: bestfit.hxx
+//
+// Contents: Class that implements best fit heap
+//
+// Classes: CBestFit
+//
+// Functions:
+//
+// History: 09-Oct-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+// Allocation signiture
+#define ALLOCATED_BLOCK ((CAvailBlock *)0xFEDEAEBE)
+
+#define SIZE_BEST_FIT_HEADER (sizeof(CAvailBlock *) + sizeof(size_t))
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CAvailBlock
+//
+// Purpose: Block in best fit free list
+//
+// Interface: Next
+// IsBigEnough
+// Allocated
+// Allocate
+// MergeWithFreeList
+// Copy
+// new
+//
+// History: 09-Oct-93 Ricksa Created
+//
+// Notes: An interesting point with respect to these objects is that
+// the destructor is never called on these things as they
+// never really go away until the heap goes away.
+//
+//--------------------------------------------------------------------------
+class CAvailBlock
+{
+public:
+ // Used to initialize the header
+ CAvailBlock(void *pvBase, size_t s);
+
+ // Used to cast block from pointer to user memory
+ // into a heap block.
+ CAvailBlock(void);
+
+ // Used to cast block when a block of memory is
+ // split.
+ CAvailBlock(CAvailBlock *pavailblkNext, size_t s);
+
+ // Get next pointer in the free list
+ CAvailBlock * Next(void);
+
+ // Does block exceed input size
+ BOOL IsBigEnough(size_t s);
+
+ // Was this block allocated by us.
+ BOOL Allocated(void);
+
+ // Allocate a block
+ void * Allocate(size_t s, CAvailBlock *pavailblkPrev);
+
+ // Put block back into the free list
+ void MergeWithFreeList(CAvailBlock *pavailblkNextInList);
+
+ // Copy data from old buffer to new
+ void Copy(void *pv);
+
+ // Allocator for turning raw memory into an avail block
+ void * operator new(size_t cSize, void *pvBase);
+
+ // Allocator used by split
+ void * operator new(size_t cSize, char *pchBase);
+
+private:
+
+ // Next block in free list
+ CAvailBlock * _pavailblkNext;
+
+ // Count of bytes in data part of the block
+ size_t _cBlock;
+
+ // Address of data area
+ char _data[1];
+};
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: operator new
+//
+// Synopsis: New for converting block from user data to heap block
+//
+// Arguments: [cSize] - size (ignored).
+// [pvBase] - pointer to start of user data block
+//
+// Returns: Pointer to where heap free block starts
+//
+// History: 09-Oct-93 Ricksa Created
+//
+// Notes: This is really used for casting user data to heap free block
+//
+//--------------------------------------------------------------------------
+inline void *CAvailBlock::operator new(size_t cSize, void *pvBase)
+{
+ return (char *) pvBase - SIZE_BEST_FIT_HEADER;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: operator new
+//
+// Synopsis: Allocator for splitting a heap block
+//
+// Arguments: [cSize] - size (ignored).
+// [pvBase] - pointer to start of user data block
+//
+// Returns: Pointer to location of new block in current block
+//
+// History: 09-Oct-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void *CAvailBlock::operator new(size_t cSize, char *pchBase)
+{
+ return pchBase;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CAvailBlock::CAvailBlock
+//
+// Synopsis: Constructor for head of free list
+//
+// Arguments: [pvBase] - pointer to base of free memory
+// [s] - of total heap
+//
+// History: 09-Oct-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CAvailBlock::CAvailBlock(void *pvBase, size_t s)
+ : _pavailblkNext(NULL), _cBlock(0)
+{
+ _pavailblkNext = new ((char *) pvBase)
+ CAvailBlock((CAvailBlock *) NULL, s - SIZE_BEST_FIT_HEADER);
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CAvailBlock::CAvailBlock
+//
+// Synopsis: Constructor converting block from user pointer to free list
+// object.
+//
+// History: 09-Oct-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CAvailBlock::CAvailBlock(void)
+{
+ // Header does all the work
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CAvailBlock::CAvailBlock
+//
+// Synopsis: Constructor for splitting a block
+//
+// Arguments: [pavailblkNext] - pointer to next block in the list
+// [s] - size of data part of the block
+//
+// History: 09-Oct-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CAvailBlock::CAvailBlock(CAvailBlock *pavailblkNext, size_t s)
+ : _pavailblkNext(pavailblkNext), _cBlock(s)
+{
+ // Header does all the work
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CAvailBlock::Next
+//
+// Synopsis: Get pointer to next itme in the list of free blocks
+//
+// History: 09-Oct-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CAvailBlock *CAvailBlock::Next(void)
+{
+ return _pavailblkNext;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CAvailBlock::Allocated
+//
+// Synopsis: Determine whether this block was allocated by this heap
+//
+// History: 09-Oct-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CAvailBlock::Allocated(void)
+{
+ return (_pavailblkNext == ALLOCATED_BLOCK);
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CAvailBlock::IsBigEnough
+//
+// Synopsis: Whether block is big enough to be used for allocation
+//
+// Arguments: [s] - size of block required
+//
+// Returns: TRUE - block is big enough
+// FALSE - block is not big enough
+//
+// History: 09-Oct-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CAvailBlock::IsBigEnough(size_t s)
+{
+ return (s <= _cBlock);
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CAvailBlock::Allocate
+//
+// Synopsis: Allocate a block of memory
+//
+// Arguments: [s] - size of block needed
+// [pavailblkPrev] - pointer to previous block in the list
+//
+// Returns: Pointer to user data
+//
+// Algorithm: If block is big enough to split, then split the block.
+// Then return a pointer to the user portion of the allocated
+// block.
+//
+// History: 09-Oct-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void *CAvailBlock::Allocate(size_t s, CAvailBlock *pavailblkPrev)
+{
+ // If the size of the remaining data in the block is big enough
+ // for a header and some data then we will split the block
+ if (_cBlock - s > SIZE_BEST_FIT_HEADER + 8)
+ {
+ pavailblkPrev->_pavailblkNext = new (_data + s)
+ CAvailBlock(_pavailblkNext, _cBlock - (s + SIZE_BEST_FIT_HEADER));
+
+ // Reset the size of the original block to the size needed for
+ // allocation.
+ _cBlock = s;
+ }
+ else
+ {
+ // No split -- We are using the whole current block so the next block
+ // should just point to the actual next block in the list
+ pavailblkPrev->_pavailblkNext = _pavailblkNext;
+ }
+
+ // Set the next pointer to something invalid. We will use this to
+ // determine if something strange has happened to the block when
+ // it is freed.
+ _pavailblkNext = ALLOCATED_BLOCK;
+
+ // Return the data portion of the block
+ return &_data;
+
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CAvailBlock::MergeWithFreeList
+//
+// Synopsis: Return a block to the free list and merge with next
+// block if possible.
+//
+// Arguments: [pavailblkNextInList] - pointer to next block in the list
+//
+// Algorithm: If the data area of this block ends at the start of
+// a new free block, then coalese the blocks otherwise
+// just update the memory pointers.
+//
+// History: 09-Oct-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CAvailBlock::MergeWithFreeList(CAvailBlock *pavailblkNextInList)
+{
+ if (((BYTE *) _data + _cBlock) == (BYTE *) pavailblkNextInList)
+ {
+ // Need to coalese these blocks together - make this block point
+ // to the next block's next
+ _pavailblkNext = pavailblkNextInList->_pavailblkNext;
+
+ // Add size of next block to size of this block
+ _cBlock += pavailblkNextInList->_cBlock + SIZE_BEST_FIT_HEADER;
+ }
+ else
+ {
+ // Just update list pointers
+ _pavailblkNext = pavailblkNextInList;
+ }
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CAvailBlock::Copy
+//
+// Synopsis: Copy user data from one heap block to a new user data area
+//
+// Arguments: [pvDest] - user area to copy the data from
+//
+// History: 09-Oct-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CAvailBlock::Copy(void *pvDest)
+{
+ CAvailBlock *pavailblkDest = new (pvDest) CAvailBlock();
+
+ int cCopy = (pavailblkDest->_cBlock > _cBlock)
+ ? _cBlock : pavailblkDest->_cBlock;
+
+ memcpy(&pavailblkDest->_data, _data, cCopy);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CBestFit
+//
+// Purpose: Implement a best fit heap
+//
+// Interface: Alloc - allocate a buffer
+// ReAlloc - reallocate a buffer
+// Free - free a buffer
+//
+// History: 09-Oct-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CBestFit
+{
+public:
+
+ CBestFit(void *pvBase, size_t s);
+
+ void * Alloc(size_t s);
+
+ void * ReAlloc(size_t s, void *pvCurrent);
+
+ void Free (void *pBlock);
+
+private:
+
+
+ CAvailBlock _availblkHead;
+
+ BYTE * _pbMax;
+
+ BYTE * _pbMin;
+};
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CBestFit::CBestFit
+//
+// Synopsis: Initialize a heap
+//
+// Arguments: [pvBase] - base of the heap
+// [size] - size of the heap
+//
+// History: 09-Oct-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CBestFit::CBestFit(void *pvBase, size_t s)
+ : _availblkHead(pvBase, s)
+{
+ // Initialize debugging constants
+ _pbMax = (BYTE *) pvBase + s;
+
+ _pbMin = (BYTE *) pvBase;
+}
+
diff --git a/private/ole32/com/class/cerror.cxx b/private/ole32/com/class/cerror.cxx
new file mode 100644
index 000000000..84f2160da
--- /dev/null
+++ b/private/ole32/com/class/cerror.cxx
@@ -0,0 +1,1236 @@
+//+-------------------------------------------------------------------
+//
+// File: cerror.cxx
+//
+// Contents: Implements COM extended error information.
+//
+// Classes: CErrorObject - Implements the COM error object.
+//
+// Functions: CoCreateErrorInfo = CreateErrorInfo
+// CoGetErrorInfo = GetErrorInfo
+// CoSetErrorInfo = SetErrorInfo
+//
+// History:
+// 20-Jun-96 MikeHill Added more OleAut32 wrappers.
+//
+//--------------------------------------------------------------------
+#include <ole2int.h>
+#include <oleauto.h>
+#include <channelb.hxx>
+#include <chock.hxx>
+#include <privoa.h> // PrivSys* routines
+
+HRESULT NdrStringRead(IStream *pStream, LPWSTR *psz);
+ULONG NdrStringSize(LPCWSTR psz);
+HRESULT NdrStringWrite(IStream *pStream, LPCWSTR psz);
+
+struct ErrorObjectData
+{
+ DWORD dwVersion;
+ DWORD dwHelpContext;
+ IID iid;
+};
+
+class CErrorObject : public IErrorInfo, public ICreateErrorInfo, public IMarshal
+{
+private:
+ long _refCount;
+ ErrorObjectData _data;
+ LPWSTR _pszSource;
+ LPWSTR _pszDescription;
+ LPWSTR _pszHelpFile;
+
+ ~CErrorObject();
+
+ public:
+ CErrorObject();
+
+ /*** IUnknown methods ***/
+ HRESULT STDMETHODCALLTYPE QueryInterface(
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppv);
+
+ ULONG STDMETHODCALLTYPE AddRef( void);
+
+ ULONG STDMETHODCALLTYPE Release( void);
+
+ /*** IMarshal methods ***/
+ HRESULT STDMETHODCALLTYPE GetUnmarshalClass(
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags,
+ /* [out] */ CLSID __RPC_FAR *pCid);
+
+ HRESULT STDMETHODCALLTYPE GetMarshalSizeMax(
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags,
+ /* [out] */ DWORD __RPC_FAR *pSize);
+
+ HRESULT STDMETHODCALLTYPE MarshalInterface(
+ /* [unique][in] */ IStream __RPC_FAR *pStm,
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags);
+
+ HRESULT STDMETHODCALLTYPE UnmarshalInterface(
+ /* [unique][in] */ IStream __RPC_FAR *pStm,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppv);
+
+ HRESULT STDMETHODCALLTYPE ReleaseMarshalData(
+ /* [unique][in] */ IStream __RPC_FAR *pStm);
+
+ HRESULT STDMETHODCALLTYPE DisconnectObject(
+ /* [in] */ DWORD dwReserved);
+
+ /*** IErrorInfo methods ***/
+ HRESULT STDMETHODCALLTYPE GetGUID(
+ /* [out] */ GUID __RPC_FAR *pGUID);
+
+ HRESULT STDMETHODCALLTYPE GetSource(
+ /* [out] */ BSTR __RPC_FAR *pBstrSource);
+
+ HRESULT STDMETHODCALLTYPE GetDescription(
+ /* [out] */ BSTR __RPC_FAR *pBstrDescription);
+
+ HRESULT STDMETHODCALLTYPE GetHelpFile(
+ /* [out] */ BSTR __RPC_FAR *pBstrHelpFile);
+
+ HRESULT STDMETHODCALLTYPE GetHelpContext(
+ /* [out] */ DWORD __RPC_FAR *pdwHelpContext);
+
+ /*** ICreateErrorInfo methods ***/
+ HRESULT STDMETHODCALLTYPE SetGUID(
+ /* [in] */ REFGUID rguid);
+
+ HRESULT STDMETHODCALLTYPE SetSource(
+ /* [in] */ LPOLESTR szSource);
+
+ HRESULT STDMETHODCALLTYPE SetDescription(
+ /* [in] */ LPOLESTR szDescription);
+
+ HRESULT STDMETHODCALLTYPE SetHelpFile(
+ /* [in] */ LPOLESTR szHelpFile);
+
+ HRESULT STDMETHODCALLTYPE SetHelpContext(
+ /* [in] */ DWORD dwHelpContext);
+
+};
+
+HINSTANCE hOleAut32 = 0;
+
+SYS_ALLOC_STRING *pfnSysAllocString = LoadSysAllocString;
+SYS_FREE_STRING *pfnSysFreeString = LoadSysFreeString;
+SYS_REALLOC_STRING_LEN *pfnSysReAllocStringLen = LoadSysReAllocStringLen;
+SYS_STRING_BYTE_LEN *pfnSysStringByteLen = LoadSysStringByteLen;
+
+//+-------------------------------------------------------------------
+//
+// Function: LoadSysAllocString
+//
+// Synopsis: Loads oleaut32.dll and calls SysAllocString.
+//
+// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
+//
+// Notes: If successful, this function will save a pointer
+// to the SysAllocString function. Subsequent calls
+// will go directly to SysAllocString.
+//
+//--------------------------------------------------------------------
+BSTR STDAPICALLTYPE
+LoadSysAllocString(OLECHAR FAR* pwsz)
+{
+ BSTR bstr = NULL;
+
+ if(!hOleAut32)
+ {
+ hOleAut32 = LoadLibraryA("oleaut32");
+ }
+
+ if(hOleAut32 != 0)
+ {
+ void *pfn = GetProcAddress(hOleAut32, "SysAllocString");
+ if(pfn != NULL)
+ {
+ pfnSysAllocString = (SYS_ALLOC_STRING *) pfn;
+ bstr = (*pfnSysAllocString)(pwsz);
+ }
+ }
+
+ return bstr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: LoadSysFreeString
+//
+// Synopsis: Loads oleaut32.dll and calls SysFreeString.
+//
+// Returns: None.
+//
+// Notes: If successful, this function will save a pointer
+// to the SysFreeString function. Subsequent calls
+// will go directly to SysFreeString.
+//
+//--------------------------------------------------------------------
+VOID STDAPICALLTYPE
+LoadSysFreeString(BSTR bstr)
+{
+ if(!hOleAut32)
+ {
+ hOleAut32 = LoadLibraryA("oleaut32");
+ }
+
+ if(hOleAut32 != 0)
+ {
+ void *pfn = GetProcAddress(hOleAut32, "SysFreeString");
+ if(pfn != NULL)
+ {
+ pfnSysFreeString = (SYS_FREE_STRING *) pfn;
+ (*pfnSysFreeString)(bstr);
+ }
+ }
+
+ return;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: LoadSysReAllocStringLen
+//
+// Synopsis: Loads oleaut32.dll and calls SysReAllocStringLen.
+//
+// Returns: TRUE if and only if successful.
+//
+// Notes: If successful, this function will save a pointer
+// to the SysReAllocString function. Subsequent calls
+// will go directly to SysReAllocStringLen.
+//
+//--------------------------------------------------------------------
+BOOL STDAPICALLTYPE
+LoadSysReAllocStringLen(BSTR FAR *pbstr, OLECHAR FAR *pwsz, UINT cch)
+{
+ BOOL fRet = FALSE;
+
+ if(!hOleAut32)
+ {
+ hOleAut32 = LoadLibraryA("oleaut32");
+ }
+
+ if(hOleAut32 != 0)
+ {
+ void *pfn = GetProcAddress(hOleAut32, "SysReAllocStringLen");
+ if(pfn != NULL)
+ {
+ pfnSysReAllocStringLen = (SYS_REALLOC_STRING_LEN *) pfn;
+ fRet = (*pfnSysReAllocStringLen)(pbstr, pwsz, cch);
+ }
+ }
+
+ return( fRet );
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: LoadSysStringByteLen
+//
+// Synopsis: Loads oleaut32.dll and calls SysFreeString.
+//
+// Returns: The byte length of the string.
+//
+// Notes: If successful, this function will save a pointer
+// to the SysStringByteLen function. Subsequent calls
+// will go directly to SysStringByteLen.
+//
+//--------------------------------------------------------------------
+UINT STDAPICALLTYPE
+LoadSysStringByteLen(BSTR bstr)
+{
+ UINT uiLen = 0;
+
+ if(!hOleAut32)
+ {
+ hOleAut32 = LoadLibraryA("oleaut32");
+ }
+
+ if(hOleAut32 != 0)
+ {
+ void *pfn = GetProcAddress(hOleAut32, "SysStringByteLen");
+ if(pfn != NULL)
+ {
+ pfnSysStringByteLen = (SYS_STRING_BYTE_LEN *) pfn;
+ uiLen = (*pfnSysStringByteLen)(bstr);
+ }
+ }
+
+ return( uiLen );
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoCreateErrorInfo
+//
+// Synopsis: Creates a COM error object.
+//
+// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
+//
+//--------------------------------------------------------------------
+WINOLEAPI
+CoCreateErrorInfo(ICreateErrorInfo **ppCreateErrorInfo)
+{
+ HRESULT hr = S_OK;
+ CErrorObject *pTemp;
+
+ __try
+ {
+ *ppCreateErrorInfo = NULL;
+
+ pTemp = new CErrorObject;
+
+ if(pTemp != NULL)
+ {
+ *ppCreateErrorInfo = (ICreateErrorInfo *) pTemp;
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CoGetErrorInfo
+//
+// Synopsis: Gets the error object for the current thread.
+//
+// Returns: S_OK, S_FALSE, E_INVALIDARG, E_NOINTERFACE.
+//
+// Notes: If sucessful, this function clears the error object
+// for the current thread.
+//
+//--------------------------------------------------------------------
+WINOLEAPI
+CoGetErrorInfo(DWORD dwReserved, IErrorInfo ** ppErrorInfo)
+{
+ HRESULT hr = S_OK;
+ COleTls tls(hr);
+
+ if(FAILED(hr))
+ {
+ //Could not access TLS.
+ return hr;
+ }
+
+ if(dwReserved != 0)
+ {
+ return E_INVALIDARG;
+ }
+
+ __try
+ {
+ *ppErrorInfo = NULL;
+
+ if(tls->punkError != NULL)
+ {
+ hr = tls->punkError->QueryInterface(IID_IErrorInfo, (void **) ppErrorInfo);
+ if(SUCCEEDED(hr))
+ {
+ //Clear the error object.
+ tls->punkError->Release();
+ tls->punkError = NULL;
+ hr = S_OK;
+ }
+ }
+ else
+ {
+ hr = S_FALSE;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoSetErrorInfo
+//
+// Synopsis: Sets the COM extended error information for the
+// current thread.
+//
+// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
+//
+//--------------------------------------------------------------------
+WINOLEAPI
+CoSetErrorInfo(unsigned long dwReserved, IErrorInfo * pErrorInfo)
+{
+ HRESULT hr = S_OK;
+ COleTls tls(hr);
+
+ if(FAILED(hr))
+ {
+ //Could not access TLS.
+ return hr;
+ }
+
+ if(dwReserved != 0)
+ {
+ return E_INVALIDARG;
+ }
+
+ __try
+ {
+ //AddRef the new error object.
+ if(pErrorInfo != NULL)
+ {
+ pErrorInfo->AddRef();
+ }
+
+ //Release the old error object.
+ if(tls->punkError != NULL)
+ {
+ tls->punkError->Release();
+ }
+
+ //Set the error object for the current thread.
+ tls->punkError = pErrorInfo;
+ hr = S_OK;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::CErrorObject
+//
+// Synopsis: Constructor for COM error object.
+//
+//----------------------------------------------------------------------------
+CErrorObject::CErrorObject()
+: _refCount(1),
+ _pszSource(NULL),
+ _pszDescription(NULL),
+ _pszHelpFile(NULL)
+{
+ _data.dwVersion = 0;
+ _data.dwHelpContext = 0;
+ _data.iid = GUID_NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::~CErrorObject
+//
+// Synopsis: Destructor for COM error object.
+//
+//----------------------------------------------------------------------------
+CErrorObject::~CErrorObject()
+{
+ if(_pszSource != NULL)
+ PrivMemFree(_pszSource);
+
+ if(_pszDescription != NULL)
+ PrivMemFree(_pszDescription);
+
+ if(_pszHelpFile != NULL)
+ PrivMemFree(_pszHelpFile);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::QueryInterface
+//
+// Synopsis: Gets a pointer to the specified interface. The error object
+// supports the IErrorInfo, ICreateErrorInfo, IMarshal, and
+// IUnknown interfaces.
+//
+// Returns: S_OK, E_NOINTERFACE, E_INVALIDARG.
+//
+// Notes: Bad parameters will raise an exception. The exception
+// handler catches exceptions and returns E_INVALIDARG.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::QueryInterface(
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppv)
+{
+ HRESULT hr = S_OK;
+
+ _try
+ {
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, IID_IMarshal))
+ {
+ AddRef();
+ *ppv = (IMarshal *) this;
+ }
+ else if (IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_ICreateErrorInfo))
+ {
+ AddRef();
+ *ppv = (ICreateErrorInfo *) this;
+ }
+ else if(IsEqualIID(riid, IID_IErrorInfo))
+ {
+ AddRef();
+ *ppv = (IErrorInfo *) this;
+ }
+ else
+ {
+ hr = E_NOINTERFACE;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::AddRef
+//
+// Synopsis: Increments the reference count.
+//
+// Returns: Reference count.
+//
+//----------------------------------------------------------------------------
+ULONG STDMETHODCALLTYPE CErrorObject::AddRef()
+{
+ Win4Assert(_refCount > 0);
+
+ InterlockedIncrement(&_refCount);
+ return _refCount;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::Release
+//
+// Synopsis: Decrements the reference count.
+//
+// Returns: Reference count.
+//
+//----------------------------------------------------------------------------
+ULONG STDMETHODCALLTYPE CErrorObject::Release()
+{
+ ULONG count = _refCount - 1;
+
+ Win4Assert(_refCount > 0);
+
+ if(0 == InterlockedDecrement(&_refCount))
+ {
+ delete this;
+ count = 0;
+ }
+ return count;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::GetUnmarshalClass
+//
+// Synopsis: Get the CLSID of the COM error object.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::GetUnmarshalClass(
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags,
+ /* [out] */ CLSID __RPC_FAR *pClassID)
+{
+ *pClassID = CLSID_ErrorObject;
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::GetMarshalSizeMax
+//
+// Synopsis: Get the size of the marshalled COM error object.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::GetMarshalSizeMax(
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags,
+ /* [out] */ DWORD __RPC_FAR *pSize)
+{
+ ULONG cb;
+
+ cb = sizeof(_data);
+ cb += NdrStringSize(_pszSource);
+ cb += NdrStringSize(_pszDescription);
+ cb += NdrStringSize(_pszHelpFile);
+
+ *pSize = cb;
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::MarshalInterface
+//
+// Synopsis: Marshal the COM error object.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::MarshalInterface(
+ /* [unique][in] */ IStream __RPC_FAR *pStream,
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags)
+{
+ HRESULT hr;
+
+ hr = pStream->Write(&_data, sizeof(_data), NULL);
+
+ if(SUCCEEDED(hr))
+ hr = NdrStringWrite(pStream, _pszSource);
+
+ if(SUCCEEDED(hr))
+ hr = NdrStringWrite(pStream, _pszDescription);
+
+ if(SUCCEEDED(hr))
+ hr = NdrStringWrite(pStream, _pszHelpFile);
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::UnmarshalInterface
+//
+// Synopsis: Unmarshal the COM error object.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::UnmarshalInterface(
+ /* [unique][in] */ IStream __RPC_FAR *pStream,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppv)
+{
+ HRESULT hr;
+
+ *ppv = NULL;
+
+ //Clear the error object.
+ if(_pszSource != NULL)
+ {
+ PrivMemFree(_pszSource);
+ _pszSource = NULL;
+ }
+
+ if(_pszDescription != NULL)
+ {
+ PrivMemFree(_pszDescription);
+ _pszDescription = NULL;
+ }
+
+ if(_pszHelpFile != NULL)
+ {
+ PrivMemFree(_pszHelpFile);
+ _pszHelpFile = NULL;
+ }
+
+ hr = pStream->Read(&_data, sizeof(_data), NULL);
+
+ if(SUCCEEDED(hr))
+ hr = NdrStringRead(pStream, &_pszSource);
+
+ if(SUCCEEDED(hr))
+ hr = NdrStringRead(pStream, &_pszDescription);
+
+ if(SUCCEEDED(hr))
+ hr = NdrStringRead(pStream, &_pszHelpFile);
+
+ //Check the version.
+ if(_data.dwVersion > 0)
+ {
+ _data.dwVersion = 0;
+ }
+
+ if(SUCCEEDED(hr))
+ {
+ hr = QueryInterface(riid, ppv);
+ }
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::ReleaseMarshalData
+//
+// Synopsis: Release a marshalled COM error object.
+//
+// Notes: Just seek to the end of the marshalled error object.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::ReleaseMarshalData(
+ /* [unique][in] */ IStream __RPC_FAR *pStm)
+{
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::DisconnectObject
+//
+// Synopsis: Disconnect the object.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::DisconnectObject(
+ /* [in] */ DWORD dwReserved)
+{
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::GetDescription
+//
+// Synopsis: Gets a textual description of the error.
+//
+// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
+//
+// Notes: Not thread-safe.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::GetDescription(
+ /* [out] */ BSTR __RPC_FAR *pBstrDescription)
+{
+ HRESULT hr = S_OK;
+ BSTR pTemp;
+
+ __try
+ {
+ *pBstrDescription = NULL;
+
+ if(_pszDescription != NULL)
+ {
+ pTemp = PrivSysAllocString(_pszDescription);
+ if(pTemp != NULL)
+ {
+ *pBstrDescription = pTemp;
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::GetGUID
+//
+// Synopsis: Gets the IID of the interface that defined the error.
+//
+// Returns: S_OK, E_INVALIDARG.
+//
+// Notes: Not thread-safe.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::GetGUID(
+ /* [out] */ GUID __RPC_FAR *pGUID)
+{
+ HRESULT hr = S_OK;
+
+ __try
+ {
+ *pGUID = _data.iid;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::GetHelpContext
+//
+// Synopsis: Gets the Help context ID for the error.
+//
+// Returns: S_OK, E_INVALIDARG.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::GetHelpContext(
+ /* [out] */ DWORD __RPC_FAR *pdwHelpContext)
+{
+ HRESULT hr = S_OK;
+
+ __try
+ {
+ *pdwHelpContext = _data.dwHelpContext;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::GetHelpFile
+//
+// Synopsis: Gets the path of the help file that describes the error.
+//
+// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
+//
+// Notes: Not thread-safe.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::GetHelpFile(
+ /* [out] */ BSTR __RPC_FAR *pBstrHelpFile)
+{
+ HRESULT hr = S_OK;
+ BSTR pTemp;
+
+ __try
+ {
+ *pBstrHelpFile = NULL;
+
+ if(_pszHelpFile != NULL)
+ {
+ pTemp = PrivSysAllocString(_pszHelpFile);
+ if(pTemp != NULL)
+ {
+ *pBstrHelpFile = pTemp;
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::GetSource
+//
+// Synopsis: Gets the ProgID of the class that is the source of the error.
+//
+// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
+//
+// Notes: Not thread-safe.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::GetSource(
+ /* [out] */ BSTR __RPC_FAR *pBstrSource)
+{
+ HRESULT hr = S_OK;
+ BSTR pTemp;
+
+ __try
+ {
+ *pBstrSource = NULL;
+
+ if(_pszSource != NULL)
+ {
+ pTemp = PrivSysAllocString(_pszSource);
+ if(pTemp != NULL)
+ {
+ *pBstrSource = pTemp;
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::SetDescription
+//
+// Synopsis: Sets the textual description of the error.
+//
+// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::SetDescription(
+ /* [in] */ LPOLESTR pszDescription)
+{
+ HRESULT hr = S_OK;
+ LPOLESTR pTemp = NULL;
+ ULONG cb;
+
+ __try
+ {
+ if(pszDescription != NULL)
+ {
+ cb = (wcslen(pszDescription) + 1) * sizeof(OLECHAR);
+ pTemp = (LPOLESTR) PrivMemAlloc(cb);
+ if(pTemp != NULL)
+ {
+ memcpy(pTemp, pszDescription, cb);
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+
+ if(SUCCEEDED(hr))
+ {
+ pTemp = (LPOLESTR) InterlockedExchange((long *)&_pszDescription,
+ (long) pTemp);
+ if(pTemp != NULL)
+ {
+ PrivMemFree(pTemp);
+ }
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::SetGUID
+//
+// Synopsis: Sets the IID of the interface that defined the error.
+//
+// Returns: S_OK, E_INVALIDARG.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::SetGUID(
+ /* [in] */ REFGUID rguid)
+{
+ HRESULT hr = S_OK;
+
+ __try
+ {
+ _data.iid = rguid;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::SetHelpContext
+//
+// Synopsis: Sets the Help context ID for the error.
+//
+// Returns: S_OK.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::SetHelpContext(
+ /* [in] */ DWORD dwHelpContext)
+{
+ _data.dwHelpContext = dwHelpContext;
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::SetHelpFile
+//
+// Synopsis: Sets the path of the Help file that describes the error.
+//
+// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::SetHelpFile(
+ /* [in] */ LPOLESTR pszHelpFile)
+{
+ HRESULT hr = S_OK;
+ LPOLESTR pTemp = NULL;
+ ULONG cb;
+
+ __try
+ {
+ if(pszHelpFile != NULL)
+ {
+ cb = (wcslen(pszHelpFile) + 1) * sizeof(OLECHAR);
+ pTemp = (LPOLESTR) PrivMemAlloc(cb);
+ if(pTemp != NULL)
+ {
+ memcpy(pTemp, pszHelpFile, cb);
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+
+ if(SUCCEEDED(hr))
+ {
+ pTemp = (LPOLESTR) InterlockedExchange((long *)&_pszHelpFile,
+ (long) pTemp);
+ if(pTemp != NULL)
+ {
+ PrivMemFree(pTemp);
+ }
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CErrorObject::SetSource
+//
+// Synopsis: Sets the source of the error.
+//
+// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
+//
+//----------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE CErrorObject::SetSource(
+ /* [in] */ LPOLESTR pszSource)
+{
+ HRESULT hr = S_OK;
+ LPOLESTR pTemp = NULL;
+ ULONG cb;
+
+ __try
+ {
+ if(pszSource != NULL)
+ {
+ cb = (wcslen(pszSource) + 1) * sizeof(OLECHAR);
+ pTemp = (LPOLESTR) PrivMemAlloc(cb);
+ if(pTemp != NULL)
+ {
+ memcpy(pTemp, pszSource, cb);
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+
+ if(SUCCEEDED(hr))
+ {
+ pTemp = (LPOLESTR) InterlockedExchange((long *)&_pszSource,
+ (long) pTemp);
+ if(pTemp != NULL)
+ {
+ PrivMemFree(pTemp);
+ }
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+
+struct NdrStringHeader
+{
+ DWORD dwMax;
+ DWORD dwOffset;
+ DWORD dwActual;
+};
+
+struct NdrStringPtrHeader
+{
+ DWORD dwUnique;
+ DWORD dwMax;
+ DWORD dwOffset;
+ DWORD dwActual;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Function: NdrStringRead
+//
+// Synopsis: Reads a string from a stream in NDR format.
+//
+// Notes: The NDR format of a string is the following.
+// DWORD - Represents the unique pointer.
+// DWORD - Maximum number of elements.
+// DWORD - offset.
+// DWORD - Actual number of elements.
+// NULL terminated UNICODE string.
+//
+//----------------------------------------------------------------------------
+HRESULT NdrStringRead(IStream *pStream, LPWSTR *ppsz)
+{
+ HRESULT hr = S_OK;
+ DWORD dwUnique = 0;
+ ULONG cbRead = 0;
+
+ *ppsz = NULL;
+
+ //Check for a NULL pointer.
+ hr = pStream->Read(&dwUnique, sizeof(dwUnique), &cbRead);
+
+ if(FAILED(hr))
+ return hr;
+
+ Win4Assert(sizeof(dwUnique) == cbRead);
+
+ if(dwUnique != 0)
+ {
+ LPWSTR pTemp = NULL;
+ NdrStringHeader hdr;
+
+ hr = pStream->Read(&hdr, sizeof(hdr), &cbRead);
+
+ if(FAILED(hr))
+ return hr;
+
+ Win4Assert(sizeof(hdr) == cbRead);
+ Win4Assert(hdr.dwMax >= hdr.dwOffset + hdr.dwActual);
+ Win4Assert(0 == hdr.dwOffset);
+
+ pTemp = (LPWSTR) PrivMemAlloc(hdr.dwMax * sizeof(WCHAR));
+
+ if(pTemp != NULL)
+ {
+ hr = pStream->Read(pTemp,
+ hdr.dwActual * sizeof(WCHAR),
+ &cbRead);
+ if(SUCCEEDED(hr))
+ {
+ Win4Assert(hdr.dwActual * sizeof(WCHAR) == cbRead);
+ *ppsz = pTemp;
+ hr = S_OK;
+ }
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: NdrStringSize
+//
+// Synopsis: Computes the size of a marshalled string.
+//
+//----------------------------------------------------------------------------
+ULONG NdrStringSize(LPCWSTR psz)
+{
+ ULONG cb;
+
+ if(psz != NULL)
+ {
+ cb = sizeof(NdrStringPtrHeader);
+ cb += (wcslen(psz) + 1) * sizeof(WCHAR);
+ }
+ else
+ {
+ cb = sizeof(DWORD);
+ }
+
+ return cb;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: NdrStringWrite
+//
+// Synopsis: Writes a string to a stream in NDR format.
+//
+// Notes: The NDR format of a string is shown below.
+// DWORD - Represents the unique pointer.
+// DWORD - Maximum number of elements.
+// DWORD - offset.
+// DWORD - Number of elements.
+// NULL terminated UNICODE string.
+//
+//----------------------------------------------------------------------------
+HRESULT NdrStringWrite(IStream *pStream, LPCWSTR psz)
+{
+ HRESULT hr = S_OK;
+ ULONG cbWritten;
+
+ //Check for a NULL pointer.
+ if(psz != NULL)
+ {
+ NdrStringPtrHeader hdr;
+
+ //Write the header.
+ hdr.dwUnique = 0xFFFFFFFF;
+ hdr.dwMax = wcslen(psz) + 1;
+ hdr.dwOffset = 0;
+ hdr.dwActual = hdr.dwMax;
+ hr = pStream->Write(&hdr, sizeof(hdr), &cbWritten);
+
+ if(SUCCEEDED(hr))
+ {
+ hr = pStream->Write(psz, hdr.dwActual * sizeof(WCHAR), &cbWritten);
+ }
+ }
+ else
+ {
+ DWORD dwUnique = 0;
+
+ //Write a NULL unique pointer.
+ hr = pStream->Write(&dwUnique, sizeof(dwUnique), &cbWritten);
+ }
+ return hr;
+}
+
+
diff --git a/private/ole32/com/class/classmap.hxx b/private/ole32/com/class/classmap.hxx
new file mode 100644
index 000000000..472a2c04e
--- /dev/null
+++ b/private/ole32/com/class/classmap.hxx
@@ -0,0 +1,253 @@
+//+---------------------------------------------------------------------------//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: classmap.hxx
+//
+// Contents: File extension to CLSID cache
+//
+// Classes: CClassExtMap
+//
+// Functions: none
+//
+// History: 20-Apr-94 Rickhi Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __CLASSMAP__
+#define __CLASSMAP__
+
+#include <sem.hxx>
+
+// function prototypes
+INTERNAL RegGetClassExt(LPCWSTR lpszExt, LPCLSID pclsid);
+
+
+// structure for one entry in the cache. the structure is variable sized
+// with the variable sized data being the filename extension at the end
+// of the structure.
+
+typedef struct SClassEntry
+{
+ CLSID Clsid; // clsid the extension maps to
+ ULONG ulEntryLen; // length of this entry
+ WCHAR wszExt[1]; // start of filename extension
+} SClassEntry;
+
+
+// amount to grow the cache by
+#define CLASSMAP_GROW_SIZE (4 * (sizeof(SClassEntry)+(4*sizeof(WCHAR))) )
+
+
+//+-------------------------------------------------------------------------
+//
+// class: CClassExtMap
+//
+// purpose: Holds a cache of file extension to clsid mappings (saves
+// two registry hits for each lookup). The cache helps reduce
+// the working set by avoiding paging in the registry.
+//
+// notes: The cache is expected to typically be small, hence the small
+// growth rate (5 entries at a time), linear search, and no
+// attempt is made at reordering the entries based on lookup
+// frequency.
+//
+// The entries are stored in a single block of memory which is
+// realloced when it needs to grow.
+//
+//--------------------------------------------------------------------------
+class CClassExtMap : public CPrivAlloc
+{
+public:
+ CClassExtMap();
+ ~CClassExtMap();
+
+ HRESULT FindClassExt(LPCWSTR pwszExt, CLSID *pClsid);
+
+private:
+
+ SClassEntry *Search(LPCWSTR pwszExt);
+ HRESULT Add(LPCWSTR pwszExt, CLSID *pClsid);
+
+ BYTE *_pStart; // ptr to first entry in the memory block
+ BYTE *_pFree; // ptr to first free byte in the memory block
+ ULONG _ulSize; // size of the memory block
+
+ CMutexSem _mxs; // mutex for single threaded access
+};
+
+
+// global class map pointer
+extern CClassExtMap *g_pClassExtMap;
+
+
+//+-------------------------------------------------------------------------
+//
+// member: CClassExtMap::CClassExtMap
+//
+// Synopsis: constructor for the cache.
+//
+//--------------------------------------------------------------------------
+inline CClassExtMap::CClassExtMap() :
+ _pStart(NULL),
+ _pFree(NULL),
+ _ulSize(0)
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CClassExtMap::~CClassExtMap
+//
+// Synopsis: destructor for the cache. Delete the entries.
+//
+//--------------------------------------------------------------------------
+inline CClassExtMap::~CClassExtMap()
+{
+ // delete the memory block
+ PrivMemFree(_pStart);
+ _pStart = NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CClassExtMap::FindClassExt
+//
+// Synopsis: Finds the clsid that maps to the given file extension
+//
+// Arguments: [pszExt] - the file extension to look up
+// [pclsid] - where to return the clsid
+//
+// Returns: S_OK if successfull
+//
+//--------------------------------------------------------------------------
+inline HRESULT CClassExtMap::FindClassExt(LPCWSTR pszExt, CLSID *pClsid)
+{
+ // single case the string now to save comparison time.
+
+ WCHAR wszExt[MAX_PATH];
+ lstrcpyW(wszExt, pszExt);
+ CharLowerW(wszExt);
+
+ // single thread access
+ CLock lck(_mxs);
+
+ // look in the existing cache first
+ SClassEntry *pEntry = Search(wszExt);
+
+ if (pEntry)
+ {
+ // already in the cache, return the classid
+ memcpy(pClsid, &pEntry->Clsid, sizeof(CLSID));
+ return S_OK;
+ }
+ else
+ {
+ // not found, try to add an entry for this file extension
+ return Add(wszExt, pClsid);
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CClassExtMap::Search
+//
+// Synopsis: looks in the cache for an entry with the given file extension
+//
+// Arguments: [pszExt] - the file extension to look up
+//
+// Returns: pEntry if found, NULL otherwise.
+//
+//--------------------------------------------------------------------------
+inline SClassEntry *CClassExtMap::Search(LPCWSTR pwszExt)
+{
+ BYTE *pEntry = _pStart;
+
+ while (pEntry < _pFree)
+ {
+ // compare the class extensions
+ if (!lstrcmpW(pwszExt, ((SClassEntry *)pEntry)->wszExt))
+ {
+ return (SClassEntry *)pEntry;
+ }
+
+ Win4Assert((((SClassEntry *)pEntry)->ulEntryLen & 0x07) == 0);
+ pEntry += ((SClassEntry *)pEntry)->ulEntryLen;
+ }
+
+ return NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CClassExtMap::Add
+//
+// Synopsis: reads the registry to get the mapping, then creates a
+// cache node and adds it to the list.
+//
+// Arguments: [pszExt] - the file extension to look up
+// [pClsid] - where to return the clsid
+//
+// Returns: S_OK if successfull,
+// REG error otherwise
+//
+//--------------------------------------------------------------------------
+inline HRESULT CClassExtMap::Add(LPCWSTR pwszExt, CLSID *pClsid)
+{
+ // read the clsid from the registry
+ HRESULT hr = RegGetClassExt(pwszExt, pClsid);
+
+ if (SUCCEEDED(hr))
+ {
+ // compute how much space we need for this entry. Note that the
+ // terminating NULL is accounted for in the sizeof(SClassEntry).
+ // we also keep the structures 8 byte aligned.
+
+ ULONG ulStrLen = lstrlenW(pwszExt) * sizeof(WCHAR);
+ ULONG ulEntryLen = (sizeof(SClassEntry) + ulStrLen + 7) & 0xfffffff8;
+
+ // see if it will fit in the currently allocated block.
+ if (_pFree + ulEntryLen > _pStart + _ulSize)
+ {
+ // this entry wont fit in the currently allocated block,
+ // so grow the block.
+
+ ULONG ulNewSize = _ulSize + ulEntryLen + CLASSMAP_GROW_SIZE;
+ BYTE *pNew = (BYTE *) PrivMemAlloc(ulNewSize);
+
+ if (pNew)
+ {
+ // update the free pointer
+ _pFree = pNew + (_pFree - _pStart);
+
+ // copy the old to the new, and free the old
+ memcpy(pNew, _pStart, _ulSize);
+ PrivMemFree(_pStart);
+
+ // update the pointers and sizes
+ _pStart = pNew;
+ _ulSize = ulNewSize;
+ }
+ else
+ {
+ // could not allocate the memory. we got the clsid above
+ // so we still return OK, we just cant cache the data.
+ return S_OK;
+ }
+ }
+
+ // copy in the guid and the extension
+ SClassEntry *pEntry = (SClassEntry *)_pFree;
+ memcpy(&pEntry->Clsid, pClsid, sizeof(CLSID));
+ memcpy(&pEntry->wszExt, pwszExt, ulStrLen + 1);
+ pEntry->ulEntryLen = ulEntryLen;
+
+ // update the free ptr
+ _pFree += ulEntryLen;
+ }
+
+ return hr;
+}
+
+#endif // __CLASSMAP__
diff --git a/private/ole32/com/class/cocrguid.cxx b/private/ole32/com/class/cocrguid.cxx
new file mode 100644
index 000000000..df118d976
--- /dev/null
+++ b/private/ole32/com/class/cocrguid.cxx
@@ -0,0 +1,89 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: CoCreateGuid.cpp
+//
+// Contents: Guid creation
+//
+// Classes:
+//
+// Functions: CoCreateGuid
+//
+// History: 12-Apr-94 BruceMa Created
+// 19-Apr-94 BruceMa Fixes chicago build
+// 20-Apr-94 BruceMa Uniqueness algorithm improved
+// 28-Apr-94 Rickhi Added UuidCreate
+// 27-Jun-94 BruceMa Use RPC system API instead of
+// original code
+// 26-Sep-94 BruceMa Fix incorect error code
+//
+//----------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <rpcdce.h>
+
+// forward reference
+INTERNAL wCoCreateGuid(GUID *pGuid);
+
+//+---------------------------------------------------------------------
+//
+// Function: CoCreateGuid
+//
+// Synopsis: Calls UuidCreate() to create a new guid.
+//
+// Arguments: [pGuid] -- Pointer to guid structure to create
+//
+// Returns: S_OK Success
+// RPC_S_xxxx Failure creating GUID
+//
+//
+//----------------------------------------------------------------------
+STDAPI CoCreateGuid(GUID *pGuid)
+{
+ OLETRACEIN((API_CoCreateGuid, PARAMFMT("pGuid= %p"), pGuid));
+
+ HRESULT hr;
+
+ if (!IsValidPtrOut(pGuid, sizeof(*pGuid)))
+ {
+ hr = E_INVALIDARG;
+ }
+ else
+ {
+ hr = wCoCreateGuid(pGuid);
+ }
+
+ OLETRACEOUT((API_CoCreateGuid, hr));
+ return hr;
+}
+
+
+
+//+---------------------------------------------------------------------
+//
+// Function: wCoCreateGuid (internal)
+//
+// Synopsis: Calls UuidCreate() to create a new guid.
+//
+// Arguments: [pGuid] -- Pointer to guid structure to create
+//
+// Returns: S_OK Success
+// RPC_S_xxxx Failure creating GUID
+//
+//
+//----------------------------------------------------------------------
+INTERNAL wCoCreateGuid(GUID *pGuid)
+{
+ int err;
+
+ // We simply use the RPC system supplied API
+ if ((err = UuidCreate(pGuid)) != RPC_S_UUID_LOCAL_ONLY)
+ {
+ return err ? HRESULT_FROM_WIN32(err) : S_OK;
+ }
+
+ return S_OK;
+}
+
diff --git a/private/ole32/com/class/compapi.cxx b/private/ole32/com/class/compapi.cxx
new file mode 100644
index 000000000..e2153cb9f
--- /dev/null
+++ b/private/ole32/com/class/compapi.cxx
@@ -0,0 +1,2542 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: compapi.cxx
+//
+// Contents: API for the compobj dll
+//
+// Classes:
+//
+// Functions:
+//
+// History: 31-Dec-93 ErikGav Chicago port
+// 28-Mar-94 BruceMa CLSID_NULL undoes TreatAs emulation
+// 20-Apr-94 Rickhi CClassExtMap, commenting, cleanup
+// 03-May-94 BruceMa Corrected IsOle1Class w/ OLE 2.01
+// 04-May-94 BruceMa Conformed CoTreatAsClass to 16-bit OLE
+// 12-Dec-94 BruceMa Support CoGetClassPattern on Chicago
+// 03-Jan-95 BruceMa Support Chicago style pattern matching
+// on NT if CoInitialize has not been
+// called
+// 28-Aug-95 MurthyS StringFromGUID2 and StringFromGUID2A
+// no longer use sprintf or wsprintf
+// 07-Sep-95 MurthyS Only do validation in API rtns with
+// work done by worker routines. Commonly
+// used (internally) worker routines moved
+// to common\ccompapi.cxx
+// 04-Feb-96 BruceMa Add per-user registry support
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include "ole1guid.h"
+#ifndef _CHICAGO_
+#include <shrtbl.hxx> // CDllShrdTbl
+#endif // !_CHICAGO_
+#include "pattbl.hxx" // CChicoPatternTable
+#include <dbgpopup.hxx>
+#include <tracelog.hxx>
+
+// forward references
+
+INTERNAL wCoMarshalHresult(IStream FAR* pstm, HRESULT hresult);
+INTERNAL wCoUnmarshalHresult(IStream FAR* pstm, HRESULT FAR * phresult);
+#ifndef _CHICAGO_
+CDllShrdTbl *GetSharedTbl(void);
+#endif
+INTERNAL wRegGetClassPattern(HANDLE hfile, CLSID *pclsid);
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoMarshalHresult (internal)
+//
+// Synopsis: writes an hresult into the stream
+//
+// Arguments: [pStm] - the stream to write into
+// [hresult] - the hresult to write
+//
+// Returns: results from the write
+//
+//--------------------------------------------------------------------------
+inline INTERNAL wCoMarshalHresult(IStream FAR* pstm, HRESULT hresult)
+{
+ return pstm->Write(&hresult,sizeof(hresult),NULL);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoUnMarshalHresult (internal)
+//
+// Synopsis: reads an hresult from the stream
+//
+// Arguments: [pStm] - the stream to write into
+// [hresult] - the hresult to write
+//
+// Returns: results from the write
+//
+//--------------------------------------------------------------------------
+inline INTERNAL wCoUnmarshalHresult(IStream FAR* pstm, HRESULT FAR * phresult)
+{
+ SCODE sc;
+
+ HRESULT hresult = pstm->Read(&sc,sizeof(sc),NULL);
+ CairoleAssert((hresult == NOERROR)
+ && "CoUnmarshalHresult: Stream read error");
+ if (hresult == NOERROR)
+ {
+ *phresult = sc;
+ }
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoGetCallerTID (internal)
+//
+// Synopsis: gets the TID of the ORPC client that called us.
+//
+// Arguments: [pTIDCaller] - where to put the result.
+//
+//--------------------------------------------------------------------------
+inline HRESULT wCoGetCallerTID(DWORD *pTIDCaller)
+{
+ HRESULT hr;
+ COleTls tls(hr);
+
+ if (SUCCEEDED(hr))
+ {
+ *pTIDCaller = tls->dwTIDCaller;
+ return (tls->dwFlags & OLETLS_LOCALTID) ? S_OK : S_FALSE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoGetCurrentLogicalThreadId (internal)
+//
+// Synopsis: Gets the current logical thread id that this physical
+// thread is operating under. The current physical thread
+// takes on the logical tid of any client application that
+// makes an Rpc call into this app. The function is exported
+// so that the tools infrastructure (conformance suite, logger,
+// etc) can use it.
+//
+// Arguments: [pguid] - where to return the logical thread id
+//
+// Returns: [S_OK] - got the logical thread id
+// [E_OUTOFMEMORY] - cant allocate resources
+//
+//--------------------------------------------------------------------------
+inline INTERNAL wCoGetCurrentLogicalThreadId(GUID *pguid)
+{
+ GUID *pguidTmp = TLSGetLogicalThread();
+ if (pguidTmp != NULL)
+ {
+ *pguid = *pguidTmp;
+ return S_OK;
+ }
+
+ return E_OUTOFMEMORY;
+}
+
+NAME_SEG(CompApi)
+ASSERTDATA
+
+
+#ifndef _CHICAGO_
+// global shared memory table object
+extern CDllShrdTbl *g_pShrdTbl;
+#else // _CHICAGO_
+
+// Chicago does not use the shared memory caches that NT does.
+// Also, NT is permitted to use the Chicago style pattern table
+// if CoInitialize has not been called
+CChicoPatternTbl *g_pPatTbl = NULL;
+
+#endif // _CHICAGO_
+
+
+// defined in com\inc\psctbl.cxx
+extern WCHAR wszProxyStubClsid[]; // L"\\ProxyStubClsid32"
+extern WCHAR wszProxyStubClsid16[]; // L"\\ProxyStubClsid"
+
+//
+// string constants used throughout this file
+//
+
+WCHAR wszCairoRoot[] = L"";
+WCHAR wszInterfaceKey[] = L"Interface\\";
+ULONG ulInterfaceKeyLen = ((sizeof(wszInterfaceKey)/sizeof(WCHAR))-1);
+
+WCHAR wszTreatAs[] = L"TreatAs";
+WCHAR wszAutoTreatAs[] = L"AutoTreatAs";
+
+WCHAR wszIID[] = L"IID";
+ULONG ulIIDKeyLen = ((sizeof(wszIID)/sizeof(WCHAR))-1);
+
+extern WCHAR wszOle1Class[]; // defined in common\ccompapi.cxx
+
+// Constant for inprocess marshaling - this s/b big enough to cover most
+// cases since reallocations just waste time.
+#define EST_INPROC_MARSHAL_SIZE 256
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoMarshalHresult (public)
+//
+// Synopsis: writes an hresult into the stream
+//
+// Arguments: [pStm] - the stream to write into
+// [hresult] - the hresult to write
+//
+// Returns: results from the write
+//
+//--------------------------------------------------------------------------
+STDAPI CoMarshalHresult(IStream FAR* pstm, HRESULT hresult)
+{
+ OLETRACEIN((API_CoMarshalHresult, PARAMFMT("pstm= %p, hresult= %x"), pstm, hresult));
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pstm);
+
+ HRESULT hr;
+
+ if (IsValidInterface(pstm))
+ {
+ hr = wCoMarshalHresult(pstm, hresult);
+
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+
+ OLETRACEOUT((API_CoMarshalHresult, hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoUnMarshalHresult (public)
+//
+// Synopsis: reads an hresult from the stream
+//
+// Arguments: [pStm] - the stream to write into
+// [hresult] - the hresult to write
+//
+// Returns: results from the write
+//
+//--------------------------------------------------------------------------
+STDAPI CoUnmarshalHresult(IStream FAR* pstm, HRESULT FAR * phresult)
+{
+ HRESULT hr;
+ OLETRACEIN((API_CoUnmarshalHresult, PARAMFMT("pstm= %p, phresult= %p"), pstm, phresult));
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pstm);
+
+ if (IsValidInterface(pstm) &&
+ IsValidPtrOut(phresult, sizeof(*phresult)))
+ {
+ hr = wCoUnmarshalHresult(pstm, phresult);
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+
+ OLETRACEOUT((API_CoUnmarshalHresult, hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoGetCallerTID (exported, but not in header files)
+//
+// Synopsis: gets the TID of the current calling application
+//
+// Arguments: [pTIDCaller] - where to return the caller TID
+//
+// Returns: [S_TRUE] - caller TID set, caller in SAME process
+// [S_FALSE] = caller TID set, caller in different process
+// [E_OUTOFMEMORY] - caller TID not set
+//
+//--------------------------------------------------------------------------
+STDAPI CoGetCallerTID(DWORD *pTIDCaller)
+{
+ OLETRACEIN((API_CoGetCallerTID, PARAMFMT("pTIDCaller= %p"), pTIDCaller));
+ HRESULT hr;
+
+ if (IsValidPtrOut(pTIDCaller, sizeof(*pTIDCaller)))
+ {
+ hr = wCoGetCallerTID(pTIDCaller);
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+
+ OLETRACEOUT((API_CoGetCallerTID, hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoGetCurrentLogicalThreadId (exported, but not in header files)
+//
+// Synopsis: Gets the current logical thread id that this physical
+// thread is operating under. The current physical thread
+// takes on the logical tid of any client application that
+// makes an Rpc call into this app. The function is exported
+// so that the tools infrastructure (conformance suite, logger,
+// etc) can use it.
+//
+// Arguments: [pguid] - where to return the logica thread id
+//
+// Returns: [S_OK] - got the logical thread id
+// [E_OUTOFMEMORY] - cant allocate resources
+//
+//--------------------------------------------------------------------------
+STDAPI CoGetCurrentLogicalThreadId(GUID *pguid)
+{
+ OLETRACEIN((API_CoGetCurrentLogicalThreadId, PARAMFMT("pguid= %p"), pguid));
+ HRESULT hr;
+
+ if (IsValidPtrOut(pguid, sizeof(*pguid)))
+ {
+ hr = wCoGetCurrentLogicalThreadId(pguid);
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+
+ OLETRACEOUT((API_CoGetCurrentLogicalThreadId, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: StringFromGUID2 (public)
+//
+// Synopsis: converts GUID into {...} form without leading identifier;
+//
+// Arguments: [rguid] - the guid to convert
+// [lpszy] - buffer to hold the results
+// [cbMax] - sizeof the buffer
+//
+// Returns: amount of data copied to lpsz if successful
+// 0 if buffer too small.
+//
+//--------------------------------------------------------------------------
+STDAPI_(int) StringFromGUID2(REFGUID rguid, LPWSTR lpsz, int cbMax)
+{
+ OLETRACECMNIN((API_StringFromGUID2, PARAMFMT("rguid= %I, lpsz= %p, cbMax= %d"),
+ &rguid, lpsz, cbMax));
+ int iRet = 0;
+ if ((&rguid != NULL) &&
+ IsValidPtrIn(&rguid, sizeof(rguid)) &&
+ IsValidPtrOut(lpsz, cbMax))
+ {
+ if (cbMax >= GUIDSTR_MAX)
+ {
+ iRet = wStringFromGUID2(rguid, lpsz, cbMax);
+ }
+ }
+
+
+ OLETRACECMNOUTEX((API_StringFromGUID2, RETURNFMT("%d"), iRet));
+ return iRet;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GUIDFromString (private)
+//
+// Synopsis: parse above format; always writes over *pguid.
+//
+// Arguments: [lpsz] - the guid string to convert
+// [pguid] - guid to return
+//
+// Returns: TRUE if successful
+//
+//--------------------------------------------------------------------------
+STDAPI_(BOOL) GUIDFromString(LPCWSTR lpsz, LPGUID pguid)
+{
+
+ if ((lpsz != NULL) &&
+ IsValidPtrIn(lpsz, GUIDSTR_MAX) &&
+ IsValidPtrOut(pguid, sizeof(*pguid)))
+ {
+ if (lstrlenW(lpsz) < (GUIDSTR_MAX - 1))
+ return(FALSE);
+
+ return(wGUIDFromString(lpsz, pguid));
+ }
+ return(FALSE);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: StringFromCLSID (public)
+//
+// Synopsis: converts GUID into {...} form.
+//
+// Arguments: [rclsid] - the guid to convert
+// [lplpsz] - ptr to buffer for results
+//
+// Returns: NOERROR
+// E_OUTOFMEMORY
+//
+//--------------------------------------------------------------------------
+STDAPI StringFromCLSID(REFCLSID rclsid, LPWSTR FAR* lplpsz)
+{
+ OLETRACEIN((API_StringFromCLSID, PARAMFMT("rclsid= %I, lplpsz= %p"), &rclsid, lplpsz));
+ HRESULT hr;
+
+ if ((&rclsid != NULL) &&
+ IsValidPtrIn(&rclsid, sizeof(rclsid)) &&
+ IsValidPtrOut(lplpsz, sizeof(*lplpsz)))
+ {
+ hr = wStringFromCLSID(rclsid, lplpsz);
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+
+ OLETRACEOUT((API_StringFromCLSID, hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CLSIDFromString (public)
+//
+// Synopsis: converts string {...} form int guid
+//
+// Arguments: [lpsz] - ptr to buffer for results
+// [lpclsid] - the guid to convert
+//
+// Returns: NOERROR
+// CO_E_CLASSSTRING
+//
+//--------------------------------------------------------------------------
+STDAPI CLSIDFromString(LPWSTR lpsz, LPCLSID lpclsid)
+{
+ HRESULT hr;
+
+ OLETRACEIN((API_CLSIDFromString, PARAMFMT("lpsz= %ws, lpclsid= %p"),
+ lpsz, lpclsid));
+
+// Note: Should be doing IsValidPtrIn(lpsz, CLSIDSTR_MAX) but can't because
+// what comes in might be a ProgId.
+
+ if (IsValidPtrIn(lpsz, 1) &&
+ IsValidPtrOut(lpclsid, sizeof(*lpclsid)))
+ {
+ hr = wCLSIDFromString(lpsz, lpclsid);
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+
+ OLETRACEOUT((API_CLSIDFromString, hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CLSIDFromOle1Class (public)
+//
+// Synopsis: translate Ole1Class into clsid
+//
+// Arguments: [lpsz] - ptr to buffer for results
+// [lpclsid] - the guid to convert
+//
+// Returns: NOERROR
+// E_INVALIDARG
+// CO_E_CLASSSTRING (not ole1 class)
+// REGDB_E_WRITEREGDB
+//
+//--------------------------------------------------------------------------
+STDAPI CLSIDFromOle1Class(LPCWSTR lpsz, LPCLSID lpclsid, BOOL fForceAssign)
+{
+ if ((lpsz != NULL) &&
+ IsValidPtrIn(lpsz,1) &&
+ IsValidPtrOut(lpclsid, sizeof(*lpclsid)))
+ {
+ if (lpsz[0] == 0)
+ {
+ // NOTE - This check wasn't in shipped versions of this
+ // code. In prior versions the empty string would be passed
+ // down into the guts of the 1.0 CLSID support and would
+ // fail there with CO_E_CLASSSTRING. That code path depended
+ // on an assert being broken to function properly. With that
+ // assert fixed, this new check is required.
+
+ *lpclsid = CLSID_NULL;
+ return CO_E_CLASSSTRING;
+ }
+
+
+ return(wCLSIDFromOle1Class(lpsz, lpclsid, fForceAssign));
+ }
+ return(E_INVALIDARG);
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Ole1ClassFromCLSID2
+//
+// Synopsis: translate CLSID into Ole1Class
+// REVIEW: might want to have CLSIDFromOle1Class instead of having
+// CLSIDFromString do the work.
+//
+// Arguments: [rclsid] --
+// [lpsz] --
+// [cbMax] --
+//
+// Returns:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(int) Ole1ClassFromCLSID2(REFCLSID rclsid, LPWSTR lpsz, int cbMax)
+{
+ if ((&rclsid != NULL) &&
+ IsValidPtrIn(&rclsid, sizeof(rclsid)) &&
+ IsValidPtrOut(lpsz, cbMax))
+ {
+ return(wOle1ClassFromCLSID2(rclsid, lpsz, cbMax));
+ }
+ return(E_INVALIDARG);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: StringFromIID (public)
+//
+// Synopsis: converts GUID into {...} form.
+//
+// Arguments: [rclsid] - the guid to convert
+// [lplpsz] - ptr to buffer for results
+//
+// Returns: NOERROR
+// E_OUTOFMEMORY
+//
+//--------------------------------------------------------------------------
+STDAPI StringFromIID(REFIID rclsid, LPWSTR FAR* lplpsz)
+{
+ OLETRACEIN((API_StringFromIID, PARAMFMT("rclsid= %I, lplpsz= %p"), &rclsid, lplpsz));
+ HRESULT hr = NOERROR;
+
+ if ((&rclsid != NULL) &&
+ IsValidPtrIn(&rclsid, sizeof(rclsid)) &&
+ IsValidPtrOut(lplpsz, sizeof(*lplpsz)))
+ {
+ hr = wStringFromIID(rclsid, lplpsz);
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+
+ }
+
+ OLETRACEOUT((API_StringFromIID, hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IIDFromString (public)
+//
+// Synopsis: converts string {...} form int guid
+//
+// Arguments: [lpsz] - ptr to buffer for results
+// [lpiid] - the guid to convert
+//
+// Returns: NOERROR
+// CO_E_CLASSSTRING
+//
+//--------------------------------------------------------------------------
+STDAPI IIDFromString(LPWSTR lpsz, LPIID lpiid)
+{
+ OLETRACEIN((API_IIDFromString, PARAMFMT("lpsz= %ws, lpiid= %p"), lpsz, lpiid));
+
+ HRESULT hr = E_INVALIDARG;
+ if (IsValidPtrIn(lpsz, IIDSTR_MAX) &&
+ IsValidPtrOut(lpiid, sizeof(*lpiid)))
+ {
+ if ((lpsz == NULL) ||
+ (lstrlenW(lpsz) == (IIDSTR_MAX - 1)))
+ {
+ hr = wIIDFromString(lpsz, lpiid);
+ }
+
+ }
+ OLETRACEOUT((API_IIDFromString, hr));
+ return hr;
+}
+
+#ifndef DCOM
+//+-------------------------------------------------------------------------
+//
+// Function: CoGetPSClsid (public)
+//
+// Synopsis: returns the proxystub clsid associated with the specified
+// interface IID.
+//
+// Arguments: [riid] - the interface iid to lookup
+// [lpclsid] - where to return the clsid
+//
+// Returns: S_OK if successfull
+// REGDB_E_IIDNOTREG if interface is not registered.
+// REGDB_E_READREGDB if any other error
+//
+// Algorithm: First it looks in the shared memory table for the specified
+// IID. If the entry is not found and the table is FULL, it
+// will look in the registry itself. I expect this latter case
+// to be very rare.
+//
+// History: 07-Apr-94 Rickhi rewrite
+//
+//--------------------------------------------------------------------------
+STDAPI CoGetPSClsid(REFIID riid, LPCLSID lpclsid)
+{
+ if ((&riid != NULL) &&
+ IsValidPtrIn(&riid, sizeof(riid)) &&
+ IsValidPtrOut(lpclsid, sizeof(*lpclsid)))
+ {
+ return(wCoGetPSClsid(riid, lpclsid));
+ }
+ return(E_INVALIDARG);
+}
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoIsOle1Class (public)
+//
+// Synopsis: reads the Ole1Class entry in the registry for the given clsid
+//
+// Arguments: [rclsid] - the classid to look up
+//
+// Returns: TRUE if Ole1Class
+// FALSE otherwise
+//
+//--------------------------------------------------------------------------
+STDAPI_(BOOL) CoIsOle1Class(REFCLSID rclsid)
+{
+ if ((&rclsid != NULL) &&
+ IsValidPtrIn(&rclsid, sizeof(rclsid)))
+ {
+ return(wCoIsOle1Class(rclsid));
+ }
+ return(FALSE);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ProgIDFromCLSID (public)
+//
+// Synopsis: convert clsid into progid
+//
+// Arguments: [rclsid] - the classid to look up
+// [pszProgID] - returned progid
+//
+// Returns: E_INVALIDARG, E_OUTOFMEMORY,
+// REGDB_CLASSNOTREG, REGDB_E_READREGDB
+//
+//--------------------------------------------------------------------------
+STDAPI ProgIDFromCLSID(REFCLSID rclsid, LPWSTR FAR* ppszProgID)
+{
+ if ((&rclsid != NULL) &&
+ IsValidPtrIn(&rclsid, sizeof(rclsid)) &&
+ IsValidPtrOut(ppszProgID, sizeof(*ppszProgID)))
+ {
+ return(wkProgIDFromCLSID(rclsid, ppszProgID));
+ }
+ return(E_INVALIDARG);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CLSIDFromProgID (public)
+//
+// Synopsis: convert progid into clsid
+//
+// Arguments: [pszProgID] - the progid to convert
+// [pclsid] - the returned classid
+//
+// Returns: E_INVALIDARG, CO_E_CLASSSTRING (not ole1 class)
+// REGDB_E_WRITEREGDB
+//
+//--------------------------------------------------------------------------
+STDAPI CLSIDFromProgID(LPCWSTR pszProgID, LPCLSID pclsid)
+{
+ return CLSIDFromOle1Class(pszProgID, pclsid);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoOpenClassKey (public)
+//
+// Synopsis: opens a registry key for specified class
+//
+// Arguments: [rclsid] - the classid to look up
+// [pszProgID] - returned progid
+//
+// Returns: REGDB_CLASSNOTREG, REGDB_E_READREGDB
+//
+//--------------------------------------------------------------------------
+STDAPI CoOpenClassKey(REFCLSID clsid, HKEY FAR* lphkeyClsid)
+{
+ if ((&clsid != NULL) &&
+ IsValidPtrIn(&clsid, sizeof(clsid)) &&
+ IsValidPtrOut(lphkeyClsid, sizeof(*lphkeyClsid)))
+ {
+ return(wCoOpenClassKey(clsid, lphkeyClsid));
+ }
+ return(E_INVALIDARG);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoGetTreatAsClass (public)
+//
+// Synopsis: get current treat as class if any
+//
+// Arguments: [clsidOld] - the classid to look up
+// [pclsidNew] - returned classid
+//
+// Returns: S_OK when there is a TreatAs entry.
+// S_FALSE when there is no TreatAs entry.
+// REGDB_E_READREGDB or same as CLSIDFromString
+//
+//--------------------------------------------------------------------------
+STDAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID lpClsidNew)
+{
+ if ((&clsidOld != NULL) &&
+ IsValidPtrIn(&clsidOld, sizeof(clsidOld)) &&
+ IsValidPtrOut(lpClsidNew, sizeof(*lpClsidNew)))
+ {
+ return(wCoGetTreatAsClass(clsidOld, lpClsidNew));
+ }
+ return(E_INVALIDARG);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoTreatAsClass (public)
+//
+// Synopsis: set current treat as class if any
+//
+// Arguments: [clsidOld] - the old classid to look up
+// [clsidNew] - the new classid
+//
+// Returns: S_OK if successful
+// REGDB_E_CLASSNOTREG, REGDB_E_READREGDB, REGDB_E_WRITEREGDB
+//
+//--------------------------------------------------------------------------
+STDAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew)
+{
+ if ((&clsidOld != NULL) &&
+ (&clsidNew != NULL) &&
+ IsValidPtrIn(&clsidOld, sizeof(clsidOld)) &&
+ IsValidPtrIn(&clsidNew, sizeof(clsidNew)))
+ {
+ return(wCoTreatAsClass(clsidOld, clsidNew));
+ }
+ return(E_INVALIDARG);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoCreateInstance (public)
+//
+// Synopsis: helper function to create instance in given context
+//
+// Arguments: [rclsid] - the class of object to create
+// [pUnkOuter] - the controlling unknown (for aggregation)
+// [dwContext] - class context
+// [riid] - interface id
+// [ppv] - pointer for returned object
+//
+// Returns: REGDB_E_CLASSNOTREG, REGDB_E_READREGDB, REGDB_E_WRITEREGDB
+//
+//--------------------------------------------------------------------------
+STDAPI CoCreateInstance(
+ REFCLSID rclsid,
+ LPUNKNOWN pUnkOuter,
+ DWORD dwContext,
+ REFIID riid,
+ LPVOID FAR* ppv)
+{
+ if ((&rclsid != NULL) &&
+ IsValidPtrIn(&rclsid, sizeof(rclsid)) &&
+ ((!pUnkOuter) || IsValidInterface(pUnkOuter)) &&
+ (&riid != NULL) &&
+ IsValidPtrIn(&riid, sizeof(riid)) &&
+ IsValidPtrOut(ppv, sizeof(*ppv)))
+ {
+ return(wCoCreateInstance(rclsid, pUnkOuter, dwContext, riid, ppv));
+ }
+ return(E_INVALIDARG);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoMarshalInterThreadInterfaceInStream, public
+//
+// Synopsis: helper function to a marshaled buffer to be passed
+// between threads.
+//
+// Arguments: [riid] - interface id
+// [pUnk] - ptr to interface we want to marshal
+// [ppStm] - stream we want to give back to caller
+//
+// Returns: NOERROR - Stream returned
+// E_INVALIDARG - Input parameters are invalid
+// E_OUTOFMEMORY - memory stream could not be created.
+//
+// Algorithm: Validate pointers. Create a stream and finally marshal
+// the input interface into the stream.
+//
+// History: 03-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CoMarshalInterThreadInterfaceInStream(
+ REFIID riid,
+ LPUNKNOWN pUnk,
+ LPSTREAM *ppStm)
+{
+ HRESULT hr = E_INVALIDARG;
+ LPSTREAM pStm = NULL;
+
+ // Validate parameters
+ if ((&riid != NULL)
+ && IsValidPtrIn(&riid, sizeof(riid))
+ && IsValidInterface(pUnk)
+ && IsValidPtrOut(ppStm, sizeof(*ppStm)))
+ {
+ return(wCoMarshalInterThreadInterfaceInStream(riid, pUnk, ppStm));
+ }
+ return(E_INVALIDARG);
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoGetInterfaceAndReleaseStream, public
+//
+// Synopsis: Helper to unmarshal object from stream for inter-thread pass
+//
+// Arguments: [riid] - interface id
+// [pStm] - stream we want to give back to caller
+// [ppv] - pointer for returned object
+//
+// Returns: NOERROR - Unmarshaled object returned
+// E_OUTOFMEMORY - out of memory
+//
+// Algorithm: Validate the input parameters. Unmarshal the stream and
+// finally release the stream pointer.
+//
+// History: 03-Nov-94 Ricksa Created
+//
+// Notes: This always releases the input stream if stream is valid.
+//
+//--------------------------------------------------------------------------
+HRESULT CoGetInterfaceAndReleaseStream(
+ LPSTREAM pstm,
+ REFIID riid,
+ LPVOID *ppv)
+{
+ // Validate parameters.
+ if (IsValidInterface(pstm) &&
+ (&riid != NULL) &&
+ IsValidPtrIn(&riid, sizeof(riid)) &&
+ IsValidPtrOut(ppv, sizeof(*ppv)))
+ {
+ return(wCoGetInterfaceAndReleaseStream(pstm, riid, ppv));
+ }
+ return(E_INVALIDARG);
+}
+
+// The real working section...worker routines. Assume parameter
+// validation has already been done and therefore can be used
+// internally by COM, STG, SCM etc
+
+WCHAR wszOle1Class[] = L"Ole1Class";
+WCHAR wszProgID[] = L"ProgID";
+WCHAR wszClassKey[] = L"CLSID\\";
+#define ulClassKeyLen ((sizeof(wszClassKey)/sizeof(WCHAR))-1)
+
+//+-------------------------------------------------------------------------
+//
+// Function: wIsInternalProxyStubIID (internal)
+//
+// Synopsis: returns the proxystub clsid associated with the specified
+// interface IID.
+//
+// Arguments: [riid] - the interface iid to lookup
+// [lpclsid] - where to return the clsid
+//
+// Returns: S_OK if successfull
+// E_OUTOFMEMORY if interface is not an internal one.
+//
+// Algorithm: See if it is one of the standard format internal IIDs.
+// If it is not one of the Automation ones, return our internal
+// proxy clsid
+//
+// History: 15-Feb-95 GregJen create
+//
+//--------------------------------------------------------------------------
+INTERNAL wIsInternalProxyStubIID(REFIID riid, LPCLSID lpclsid)
+{
+ DWORD *ptr = (DWORD *) lpclsid;
+ HRESULT hr = E_OUTOFMEMORY;
+
+ if (*(ptr+1) == 0x00000000 && // all internal iid's have these
+ *(ptr+2) == 0x000000C0 && // common values
+ *(ptr+3) == 0x46000000)
+ {
+ // make sure it is not an automation iid
+ if ( *ptr < 0x00020400 )
+ {
+ memcpy( lpclsid, &CLSID_PSOlePrx32, sizeof(CLSID));
+ hr = S_OK;
+ }
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoTreatAsClass (internal)
+//
+// Synopsis: set current treat as class if any
+//
+// Arguments: [clsidOld] - the old classid to look up
+// [clsidNew] - the new classid
+//
+// Returns: S_OK if successful
+// REGDB_E_CLASSNOTREG, REGDB_E_READREGDB, REGDB_E_WRITEREGDB
+//
+//--------------------------------------------------------------------------
+INTERNAL wCoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew)
+{
+ TRACECALL(TRACE_REGISTRY, "wCoTreatAsClass");
+
+ HRESULT hresult = S_OK;
+ HKEY hkeyClsid = NULL;
+ WCHAR szClsid[VALUE_LEN];
+ LONG cb = sizeof(szClsid);
+ CLSID clsidNewTmp;
+
+ // The class had better be registered
+ hresult = wCoOpenClassKey (clsidOld, &hkeyClsid);
+ if (hresult != S_OK)
+ {
+ return hresult;
+ }
+
+ // Save the new clsid because it's a const and we may write into it
+ clsidNewTmp = clsidNew;
+
+ // Convert the new CLSID to a string
+ Verify(StringFromCLSID2(clsidNew, szClsid, sizeof(szClsid)) != 0);
+
+ // If the new CLSID equals the old CLSID, then convert AutoTreatAs, if
+ // any, to TreatAs.
+ if (IsEqualCLSID(clsidOld, clsidNew))
+ {
+ if (RegQueryValue(hkeyClsid, wszAutoTreatAs, szClsid, &cb) ==
+ ERROR_SUCCESS)
+ {
+ if (wCLSIDFromString(szClsid, &clsidNewTmp) != S_OK)
+ {
+ return REGDB_E_INVALIDVALUE;
+ }
+ }
+
+ // If no AutoTreatAs, remove any TreatAs
+ else
+ {
+ clsidNewTmp = CLSID_NULL;
+ }
+ }
+
+ // Make sure the new CLSID is not an OLE 1 class
+ if (CoIsOle1Class(clsidNew))
+ {
+ return E_INVALIDARG;
+ }
+
+ // If the new CLSID is CLSID_NULL, then undo the emulation
+ if (IsEqualCLSID(clsidNewTmp, CLSID_NULL))
+ {
+ LONG err = RegDeleteKey(hkeyClsid, wszTreatAs);
+ if (err != ERROR_SUCCESS)
+ {
+ hresult = REGDB_E_WRITEREGDB;
+ }
+ else
+ {
+ hresult = S_OK;
+ }
+ Verify (ERROR_SUCCESS == RegCloseKey(hkeyClsid));
+ return hresult;
+ }
+
+ if (RegSetValue(hkeyClsid, wszTreatAs, REG_SZ, (LPWSTR) szClsid,
+ lstrlenW(szClsid)) != ERROR_SUCCESS)
+ {
+ hresult = REGDB_E_WRITEREGDB;
+ }
+
+ Verify (ERROR_SUCCESS == RegCloseKey(hkeyClsid));
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCLSIDFromString (internal)
+//
+// Synopsis: converts string {...} form int guid
+//
+// Arguments: [lpsz] - ptr to buffer for results
+// [lpclsid] - the guid to convert
+//
+// Returns: NOERROR
+// CO_E_CLASSSTRING
+//
+//--------------------------------------------------------------------------
+INTERNAL wCLSIDFromString(LPWSTR lpsz, LPCLSID lpclsid)
+{
+
+ if (lpsz == NULL)
+ {
+ *lpclsid = CLSID_NULL;
+ return NOERROR;
+ }
+ if (*lpsz == 0)
+ {
+ return(CO_E_CLASSSTRING);
+ }
+
+ if (lpsz[0] != '{')
+ {
+ return wCLSIDFromOle1Class(lpsz, lpclsid);
+ }
+
+ return wGUIDFromString(lpsz,lpclsid)
+ ? NOERROR : CO_E_CLASSSTRING;
+
+}
+
+// translate CLSID into Ole1Class
+// REVIEW: might want to have CLSIDFromOle1Class instead of having
+// CLSIDFromString do the work.
+INTERNAL_(int) wOle1ClassFromCLSID2(REFCLSID rclsid, LPWSTR lpsz, int cbMax)
+{
+ if (wRegQueryClassValue(rclsid, wszOle1Class, lpsz, cbMax) != ERROR_SUCCESS)
+ {
+ // Use lookup table
+ return Ole10_StringFromCLSID (rclsid, lpsz, cbMax) == NOERROR
+ ? lstrlenW (lpsz) : 0;
+ }
+ return lstrlenW(lpsz);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCLSIDFromOle1Class (internal)
+//
+// Synopsis: translate Ole1Class into clsid
+//
+// Arguments: [lpsz] - ptr to buffer for results
+// [lpclsid] - the guid to convert
+//
+// Returns: NOERROR
+// E_INVALIDARG
+// CO_E_CLASSSTRING (not ole1 class)
+// REGDB_E_WRITEREGDB
+//
+//--------------------------------------------------------------------------
+INTERNAL wCLSIDFromOle1Class(LPCWSTR lpsz, LPCLSID lpclsid, BOOL fForceAssign)
+{
+ // lookup lpsz\\clsid and call CLSIDFromString on the result;
+ // in a pathalogical case, this could infinitely recurse.
+ WCHAR sz[256];
+ LONG cbValue = sizeof(sz);
+
+ if (lpsz == NULL)
+ {
+ return(E_INVALIDARG);
+ }
+
+ if (*lpsz == 0)
+ {
+ return(CO_E_CLASSSTRING);
+ }
+ lstrcpyW(sz, lpsz);
+ lstrcatW(sz, L"\\Clsid");
+
+ if (RegQueryValue(HKEY_CLASSES_ROOT, sz, sz, &cbValue) == ERROR_SUCCESS)
+ {
+ return wCLSIDFromString(sz, lpclsid);
+ }
+
+ // Use lookup table or hash string to create CLSID
+ return Ole10_CLSIDFromString (lpsz, lpclsid, fForceAssign);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoGetTreatAsClass (internal)
+//
+// Synopsis: get current treat as class if any
+//
+// Arguments: [clsidOld] - the classid to look up
+// [pclsidNew] - returned classid
+//
+// Returns: S_OK when there is a TreatAs entry.
+// S_FALSE when there is no TreatAs entry.
+// REGDB_E_READREGDB or same as CLSIDFromString
+//
+//--------------------------------------------------------------------------
+INTERNAL wCoGetTreatAsClass(REFCLSID clsidOld, LPCLSID lpClsidNew)
+{
+ TRACECALL(TRACE_REGISTRY, "wCoGetTreatAsClass");
+
+ // lookup HKEY_CLASSES_ROOT\CLSID\{rclsid}\TreatAs
+
+ HRESULT hresult;
+ HKEY hkeyClsid = NULL;
+ WCHAR szClsid[VALUE_LEN];
+ LONG cb = sizeof(szClsid);
+
+ VDATEPTROUT (lpClsidNew, CLSID);
+
+ hresult = wCoOpenClassKey (clsidOld, &hkeyClsid);
+ if (hresult != NOERROR)
+ {
+ // same as no TreatAs case below
+ *lpClsidNew = clsidOld;
+ return S_FALSE;
+ }
+
+ CairoleDebugOut((DEB_REG, "RegQueryValue(%ws)\n", wszTreatAs));
+
+ // Fetch the TreatAs class from the registry
+ if (RegQueryValue(hkeyClsid, wszTreatAs, szClsid, &cb) == ERROR_SUCCESS)
+ {
+ hresult = wCLSIDFromString(szClsid, lpClsidNew);
+ }
+
+ // There is no TreatAs
+ else
+ {
+ *lpClsidNew = clsidOld;
+ hresult = S_FALSE;
+ }
+
+ Verify (ERROR_SUCCESS==RegCloseKey(hkeyClsid));
+ return hresult;
+}
+//+-------------------------------------------------------------------------
+//
+// Function: wRegQueryPSClsid (private)
+//
+// Synopsis: reads the proxystub clsid entry out of the registry.
+//
+// Arguments: [riid] - the interface iid to lookup
+// [lpclsid] - where to return the clsid
+//
+// Returns: S_OK if successfull
+// REGDB_E_IIDNOTREG if interface is not registered.
+// REGDB_E_READREGDB if any other error
+//
+// Notes: this is an internal function used only if the requested IID
+// entry is not in the shared memory table and the table is full.
+//
+// History: 07-Apr-94 Rickhi extracted from original source
+// 04-Feb-96 BruceMa Per-user registry support
+//
+//--------------------------------------------------------------------------
+INTERNAL wRegQueryPSClsid(REFIID riid, LPCLSID lpclsid)
+{
+ // lookup HKEY_CLASSES_ROOT\Interface\{iid}\ProxyStubClsid
+
+ WCHAR szKey[KEY_LEN];
+ WCHAR szValue[VALUE_LEN];
+ ULONG cbValue = sizeof(szValue);
+ HKEY hIf;
+ DWORD dwType;
+
+ lstrcpyW(szKey, wszInterfaceKey);
+
+ // translate riid into string
+ int cbIid = StringFromIID2(riid, &szKey[ulInterfaceKeyLen],
+ sizeof(szKey)-ulInterfaceKeyLen);
+
+ CairoleAssert((cbIid != 0) && "wRegQueryPSClsid");
+ lstrcpyW(&szKey[ulInterfaceKeyLen+cbIid-1], wszProxyStubClsid);
+
+ CairoleDebugOut((DEB_REG, "RegOpenKeyEx(%ws)\n", szKey));
+
+#ifdef DCOM
+ CDllShrdTbl *pShrdTbl = GetSharedTbl();
+ if (pShrdTbl == NULL)
+ {
+ return REGDB_E_IIDNOTREG;
+ }
+#endif
+
+ int err = RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, NULL, KEY_READ, &hIf);
+ if (err == ERROR_SUCCESS)
+ {
+ // The unnamed value is the clsid for this iid
+ RegQueryValueEx(hIf, NULL, NULL, &dwType, (BYTE *) szValue,
+ &cbValue);
+ RegCloseKey(hIf);
+ return wCLSIDFromString(szValue, lpclsid);
+ }
+ else
+ {
+ // If the key is missing, check to see if it is IDispatch
+ //
+ // There wasn't a ProxyStubClsid32 for this interface.
+ // Because many applications install with interfaces
+ // that are variations on IDispatch, we are going to check
+ // to see if there is a ProxyStubClsid. If there is, and its
+ // class is that of IDispatch, then the OLE Automation DLL is
+ // the correct one to use. In that particular case, we will
+ // pretend that ProxyStubClsid32 existed, and that it is
+ // for IDispatch.
+
+ lstrcpyW(&szKey[ulInterfaceKeyLen+cbIid-1], wszProxyStubClsid16);
+
+ if(RegQueryValue(HKEY_CLASSES_ROOT, szKey, szValue, (LONG*)&cbValue) == ERROR_SUCCESS)
+ {
+ CLSID clsid;
+ if((wCLSIDFromString(szValue,&clsid) == NOERROR) &&
+ memcmp(&CLSID_PSDispatch,&clsid,sizeof(clsid)) == 0)
+ {
+ CairoleDebugOut((DEB_WARN,
+ "Substituting IDispatch based on ProxyStubClsid\n"));
+ memcpy(lpclsid,&CLSID_PSDispatch,sizeof(CLSID));
+ return(NOERROR);
+ }
+ }
+ }
+
+ CairoleDebugOut((DEB_WARN, "Missing 'ProxyStubClsid32' registry entry for interface.\n"));
+ return REGDB_E_IIDNOTREG;
+}
+
+
+#ifndef _CHICAGO_
+//+-------------------------------------------------------------------------
+//
+// Function: GetSharedTbl (internal)
+//
+// Synopsis: returns ptr to the shared memory cache. Creates it if needed.
+//
+// History: 25-Oct-95 Rickhi Created
+//
+//+-------------------------------------------------------------------------
+CDllShrdTbl *GetSharedTbl(void)
+{
+ if (g_pShrdTbl == NULL)
+ {
+ // since two threads could call this simultaneously, we take
+ // a lock around it and check the ptr value again.
+ COleStaticLock lck(gmxsOleMisc);
+
+ if (g_pShrdTbl == NULL)
+ {
+ // intialize the shared memory tables. we allocate the
+ // CDllShrdTbl instead of using a static object because
+ // its constructor opens a mutex, and we dont want that
+ // open unless CoInitialize is called.
+
+ HRESULT hr = E_OUTOFMEMORY;
+ g_pShrdTbl = new CDllShrdTbl(hr);
+
+ if (FAILED(hr))
+ {
+ // something failed in ctor, delete the table & set ptr to NULL
+ delete g_pShrdTbl;
+ g_pShrdTbl = NULL;
+ }
+ }
+ }
+
+ return g_pShrdTbl;
+}
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoGetPSClsid (internal)
+//
+// Synopsis: returns the proxystub clsid associated with the specified
+// interface IID.
+//
+// Arguments: [riid] - the interface iid to lookup
+// [lpclsid] - where to return the clsid
+//
+// Returns: S_OK if successfull
+// REGDB_E_IIDNOTREG if interface is not registered.
+// REGDB_E_READREGDB if any other error
+//
+// Algorithm: First it looks in the shared memory table for the specified
+// IID. If the entry is not found and the table is FULL, it
+// will look in the registry itself. I expect this latter case
+// to be very rare.
+//
+// History: 07-Apr-94 Rickhi rewrite
+//
+//--------------------------------------------------------------------------
+INTERNAL wCoGetPSClsid(REFIID riid, LPCLSID lpclsid)
+{
+ TRACECALL(TRACE_REGISTRY, "wCoGetPSClsid");
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+#ifndef _CHICAGO_
+ CDllShrdTbl *pShrdTbl = GetSharedTbl();
+ if (pShrdTbl)
+ {
+ // look for the entry in the shared memory tables.
+ hr = pShrdTbl->FindPSClsid(riid, lpclsid);
+ }
+#endif
+
+ if (hr == E_OUTOFMEMORY || hr == REGDB_E_IIDNOTREG)
+ {
+ // there is no cache, look in the registry directly. this error
+ // is distinguished from the entry not existing in the cache.
+
+ hr = wRegQueryPSClsid(riid, lpclsid);
+ }
+
+#if DBG==1
+#ifndef _CHICAGO_
+ // in debug mode, verify that the cache is consistent with the
+ // registry value.
+
+ if (hr == S_OK)
+ {
+ GUID clsidReg;
+ wRegQueryPSClsid(riid, &clsidReg);
+ if (memcmp(lpclsid, &clsidReg, sizeof(GUID)) &&
+ memcmp(lpclsid,&CLSID_PSDispatch,sizeof(GUID)))
+ Win4Assert(!"Cached IID value not equal to Registry value!");
+ }
+#endif
+#endif
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoGetClassExt (internal)
+//
+// Synopsis: returns the clsid for files with the specified file extension
+//
+// Arguments: [pszExt] - the file extension to look up
+// [pclsid] - where to return the clsid
+//
+// Returns: S_OK if successfull
+// REGDB_E_CLASSNOTREG if extension is not registered.
+// REGDB_E_READREGDB if any other error
+//
+// History: 07-Apr-94 Rickhi added caching
+//
+//--------------------------------------------------------------------------
+INTERNAL wCoGetClassExt(LPCWSTR pwszExt, LPCLSID pclsid)
+{
+ TRACECALL(TRACE_REGISTRY, "wCoGetClassExt");
+
+ HRESULT hr = MK_E_INVALIDEXTENSION;
+
+#ifndef _CHICAGO_
+ //
+ // we first look in the cache.
+ //
+ if (g_cProcessInits > 0)
+ {
+ CDllShrdTbl *pShrdTbl = GetSharedTbl();
+ if (pShrdTbl)
+ {
+ hr = g_pShrdTbl->FindClassExt(pwszExt, pclsid);
+ }
+ }
+ if (hr != NOERROR)
+#endif
+ {
+ //
+ // Not in cache. Try it manually in case a registry update was
+ // missed, or in the event that it is a new OLE 1.0 registration.
+ // New OLE 1.0 registrations are handled specially in ole1guid.cxx
+ //
+ hr = wRegGetClassExt(pwszExt, pclsid);
+ }
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wRegGetClassExt (private)
+//
+// Synopsis: returns the clsid for files with the specified file extension
+//
+// Arguments: [pszExt] - the file extension to look up
+// [pclsid] - where to return the clsid
+//
+// Returns: S_OK if successfull
+// REGDB_E_CLASSNOTREG if extension is not registered.
+// REGDB_E_READREGDB if any other error
+//
+// Notes:
+//
+// History: 07-Apr-94 Rickhi added caching
+// 04-Feb-96 BruceMa Per-user registry support
+//
+//--------------------------------------------------------------------------
+INTERNAL wRegGetClassExt(LPCWSTR lpszExt, LPCLSID pclsid)
+{
+ TRACECALL(TRACE_REGISTRY, "wRegGetClassExt");
+
+ HKEY hExt;
+ int err;
+ WCHAR szKey[KEY_LEN];
+ WCHAR szValue[VALUE_LEN];
+ LONG cbValue = sizeof(szValue);
+ DWORD dwType;
+
+ // Formulate the key
+ lstrcpyW(szKey, wszCairoRoot);
+ lstrcatW(szKey, lpszExt);
+
+ CairoleDebugOut((DEB_REG, "RegOpenKeyEx(%ws)\n", szKey));
+
+ // Open the key
+ if ((err = RegOpenKeyEx(HKEY_CLASSES_ROOT, lpszExt, NULL, KEY_READ,
+ &hExt))
+ != ERROR_SUCCESS)
+ {
+ return REGDB_E_CLASSNOTREG;
+ }
+
+ // The ProgId is this key's unnamed value
+ if ((err = RegQueryValueEx(hExt, NULL, NULL, &dwType, (BYTE *) szValue,
+ (ULONG *) &cbValue))
+ != ERROR_SUCCESS)
+ {
+ RegCloseKey(hExt);
+ return REGDB_E_CLASSNOTREG;
+ }
+
+#ifdef DCOM
+ CDllShrdTbl *pShrdTbl = GetSharedTbl();
+ if (pShrdTbl == NULL)
+ {
+ RegCloseKey(hExt);
+ return REGDB_E_CLASSNOTREG;
+ }
+#endif
+
+ // Translate string into pclsid
+ RegCloseKey(hExt);
+ return wCLSIDFromProgID (szValue, pclsid); // normal case
+}
+
+
+#ifdef _CHICAGO_
+HANDLE g_hRegPatTblEvent = NULL;
+#endif
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoGetClassPattern (internal)
+//
+// Synopsis: attempts to determine the class of a file by looking
+// at byte patterns in the file.
+//
+// Arguments: [hfile] - handle of file to look at
+// [pclsid] - the class of object to create
+//
+// Returns: S_OK - a pattern match was found, pclisd contains the clsid
+// MK_E_CANTOPENFILE - cant open the file.
+// REGDB_E_CLASSNOTREG - no pattern match was made
+//
+//--------------------------------------------------------------------------
+INTERNAL wCoGetClassPattern(HANDLE hfile, CLSID *pclsid)
+{
+ TRACECALL(TRACE_REGISTRY, "wCoGetClassPattern");
+ HRESULT hr = REGDB_E_CLASSNOTREG;
+
+#ifndef _CHICAGO_
+ CDllShrdTbl *pShrdTbl = GetSharedTbl();
+ if (pShrdTbl)
+ {
+ if (SUCCEEDED(pShrdTbl->FindPattern(hfile, pclsid)))
+ {
+ return S_OK;
+ }
+
+#ifdef REVISIT_PERSONAL_CLASSES_FOR_NT50
+ // NT 5.0
+ // If PersonalClasses is turned on then search the registry
+ // if (pShrdTbl->GetPersonalClasses())
+ // return wRegGetClassPattern(hfile, pclsid);
+#endif
+ }
+
+ return hr;
+
+
+#else // !_CHICAGO_
+
+ // Check whether our pattern table has been initialized
+ if(g_pPatTbl == NULL)
+ {
+ // Create an event we'll use to signal when the registry
+ // has changed.
+ if (g_hRegPatTblEvent == NULL)
+ {
+ g_hRegPatTblEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
+ }
+
+ // Force the event so we can initialize the pattern cache
+ SetEvent(g_hRegPatTblEvent);
+ }
+
+ // If the registry has changed since we were here last then reload
+ // the pattern table
+ DWORD dwState = WaitForSingleObject(g_hRegPatTblEvent, 0);
+ if (dwState == WAIT_OBJECT_0)
+ {
+ // Remove any previous pattern cache
+ delete g_pPatTbl;
+
+ // Reload the cache
+ g_pPatTbl = new CChicoPatternTbl(hr);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+
+ // Check the file for registered patterns
+ hr = g_pPatTbl->FindPattern(hfile, pclsid);
+ return hr;
+
+#endif // _CHICAGO_
+}
+
+
+
+
+
+#ifndef _CHICAGO_
+// BUGBUG: BruceMa 05-Feb-96. The following code duplicates code in
+// com\inc\shrtbls.cxx and com\inc\pattbl.cxx. These two versions need to
+// be coalesced by making a utility class. I don't have time to do this
+// now because dcom beta is breathing down my neck!
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsValidPattern
+//
+// Synopsis: Determines if the pattern entry read from the registry is of
+// a valid format. See ParseEntry for the format.
+//
+// Arguments: [psz] - pattern buffer
+// [cb] - size of buffer read
+//
+// Returns: TRUE if pattern is valid, FALSE otherwise
+//
+//--------------------------------------------------------------------------
+BOOL IsValidPattern(LPWSTR psz, LONG cb)
+{
+ // We must find exactly 3 commas before the end of the string
+ // in order for the entry to be of a parseable format.
+
+ ULONG cCommas = 0;
+ LPWSTR pszEnd = psz + (cb / sizeof(WCHAR));
+
+ while (psz < pszEnd && *psz)
+ {
+ if (*psz == ',')
+ cCommas++;
+
+ psz++;
+ }
+
+ return (cCommas == 3) ? TRUE : FALSE;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Functon: SkipToNext
+//
+// Synopsis: Skips missing entries in the list and whitespaces
+//
+// Arguments: [sz] - ptr to string
+//
+// Returns: ptr to next entry in the list
+//
+//--------------------------------------------------------------------------
+LPWSTR SkipToNext(LPWSTR sz)
+{
+ while (*sz && *sz != ',')
+ {
+ sz++;
+ }
+
+ Assert(*sz == ',');
+ sz++;
+
+ while (*sz)
+ {
+ USHORT CharType[1];
+
+ GetStringTypeW (CT_CTYPE1, sz, 1, CharType);
+ if ((CharType[0] & C1_SPACE) == 0)
+ {
+ break;
+ }
+ sz++;
+ }
+
+ return sz;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ToHex
+//
+// Synopsis: Converts two characters to a hex byte
+//
+// Arguments: [psz] - ptr to string
+//
+// Returns: The value of the string in hex
+//
+//--------------------------------------------------------------------------
+BYTE ToHex(LPWSTR psz)
+{
+ BYTE bMask = 0xFF;
+ USHORT CharTypes[2];
+
+ GetStringTypeW (CT_CTYPE1, psz, 2, CharTypes);
+
+ if (CharTypes[0] & C1_XDIGIT)
+ {
+ bMask = CharTypes[0] & C1_DIGIT ? *psz - '0' : (BYTE)CharUpperW((LPWSTR)*psz) - 'A' + 10;
+
+ psz++;
+ if (CharTypes[1] & C1_XDIGIT)
+ {
+ bMask *= 16;
+ bMask += CharTypes[1] & C1_DIGIT ? *psz - '0' : (BYTE)CharUpperW((LPWSTR)*psz) - 'A' + 10;
+ psz++;
+ }
+ }
+
+ return bMask;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ParsePattern (internal)
+//
+// Synopsis: Parse a FileType class pattern
+//
+// Arguments: [psz] - The pattern as read from the registry
+// [cb] - Length of pattern in bytes
+// [pEntry] - Where to store the parwsed pattern
+// [rclsid] - The associated clsid
+//
+// Returns: TRUE if pattern parsed successfully
+// FALSE otherwise
+//
+// History: 05-Feb-96 BruceMa Created
+//
+//--------------------------------------------------------------------------
+BOOL ParsePattern(LPWSTR psz,
+ LONG cb,
+ SPatternEntry *pEntry,
+ REFCLSID rclsid)
+{
+ // Validate the pattern before we attempt to parse it, simplifies
+ // error handling in the rest of the routine.
+ if (!IsValidPattern(psz, cb))
+ {
+ return FALSE;
+ }
+
+ // Copy in the clsid
+ memcpy(&pEntry->clsid, &rclsid, sizeof(CLSID));
+
+ // Get the file offset
+ pEntry->lFileOffset = wcstol(psz, NULL, 0);
+ psz = SkipToNext(psz);
+
+ // Get the byte count
+ pEntry->ulCb = wcstol(psz, NULL, 0);
+ Assert(pEntry->ulCb > 0);
+
+ // Get the mask ptrs
+ LPWSTR pszMask = SkipToNext(psz);
+ BYTE *pbMask = pEntry->abData;
+
+ // Get the pattern ptrs
+ LPWSTR pszPattern = SkipToNext(pszMask);
+ BYTE *pbPattern = pbMask + pEntry->ulCb;
+
+ // Convert and copy the mask & pattern bytes into the pEntry
+ for (ULONG ulCb = pEntry->ulCb; ulCb > 0; ulCb--)
+ {
+ if (*pszMask == ',')
+ {
+ // Missing mask means use 0xff
+ *pbMask = 0xff;
+ }
+ else
+ {
+ // Convert the mask string to a byte
+ *pbMask = ToHex(pszMask);
+ pszMask += 2;
+ }
+ pbMask++;
+
+ // Convert the pattern string to a byte
+ *pbPattern = ToHex(pszPattern);
+ pbPattern++;
+ pszPattern += 2;
+ }
+
+ // Compute this entry size, rounded to 8 byte alignment.
+ // Note: the struct has 4 bytes in abData, so the sizeof
+ // returns 4 more than we need.
+ pEntry->ulEntryLen = ((sizeof(SPatternEntry) - 4 +
+ (2 * pEntry->ulCb) + 7) & 0xfff8);
+
+ return TRUE;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: Matches
+//
+// Synopsis: Checks if the bytes in the buffer match the given pattern
+//
+// Arguments: [pFileBuf] - Buffer containing the file data
+// [pPattern] - Pattern to match
+//
+// Returns: TRUE if found, FALSE otherwise.
+//
+//--------------------------------------------------------------------------
+BOOL Matches(BYTE *pFileBuf, SPatternEntry *pPattern)
+{
+ // The pattern bytes follow the mask bytes. They are the same size.
+ BYTE *pbMask = pPattern->abData;
+ BYTE *pbPattern = pbMask + pPattern->ulCb;
+
+ for (ULONG iCtr = 0; iCtr < pPattern->ulCb; iCtr++)
+ {
+ if ((BYTE)(*(pFileBuf + iCtr) & *pbMask) != *pbPattern)
+ {
+ return FALSE;
+ }
+
+ // update the mask & pattern bytes
+ pbMask++;
+ pbPattern++;
+ }
+
+ return TRUE;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: SearchForPattern
+//
+// Synopsis: Searches in the file for a given pattern
+//
+// Arguments: [hFile] - Handle to the file to look in
+// [pPattern] - The pattern to search for
+//
+// Returns: TRUE if pattern found, FALSE otherwise.
+//
+//--------------------------------------------------------------------------
+BOOL SearchForPattern(HANDLE hFile, SPatternEntry *pPattern)
+{
+ LONG lLastOffset = 0;
+ ULONG ulLastCb = 0;
+ BYTE bStackBuf[256];
+ BYTE *pBuf;
+
+ // Allocate a file read buffer
+ pBuf = (BYTE *) PrivMemAlloc(1024);
+ if (pBuf == NULL)
+ {
+ return FALSE;
+ }
+
+ // Now grovel through the file looking for a pattern match
+ BOOL fLook = TRUE;
+
+ if (pPattern->lFileOffset != lLastOffset ||
+ pPattern->ulCb > ulLastCb)
+ {
+ // Must read part of the file
+ DWORD cbRead = 0;
+ DWORD dwMethod;
+ LONG cbMove;
+
+ if (pPattern->lFileOffset < 0)
+ {
+ cbMove = -1;
+ dwMethod = FILE_END;
+ }
+ else
+ {
+ cbMove = 0;
+ dwMethod = FILE_BEGIN;
+ }
+
+ fLook = FALSE; // assume failure
+
+ if (SetFilePointer(hFile, pPattern->lFileOffset, &cbMove, dwMethod)
+ != 0xffffffff)
+ {
+ if (ReadFile(hFile, pBuf, pPattern->ulCb, &cbRead, NULL))
+ {
+ fLook = TRUE;
+ }
+ }
+ }
+
+ // Free the file read buffer
+ PrivMemFree(pBuf);
+
+ // Compare
+ return fLook && Matches(pBuf, pPattern);
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wRegGetClassPattern (internal)
+//
+// Synopsis: Attempts to determine the clsid of a file based on file
+// patterns
+//
+// Arguments: [hfile] - handle of file to look at
+// [pclsid] - where to store the determined clsid
+//
+// Returns: S_OK - a pattern match was found, pclisd contains the clsid
+// REGDB_E_CLASSNOTREG - no pattern match was made
+//
+// Notes: This is called only if the file patterns for the given clsid
+// could not be found in the shared memory pattern cache.
+//
+// History: 04-Feb-96 BruceMa Created
+//
+//--------------------------------------------------------------------------
+INTERNAL wRegGetClassPattern(HANDLE hFile, CLSID *pclsid)
+{
+ HRESULT hr = REGDB_E_CLASSNOTREG;
+ HKEY hkFileType;
+ SPatternEntry *pPattern;
+#ifdef DCOM
+ CDllShrdTbl *pShrdTbl = GetSharedTbl();
+
+ // Check that we can access the shared table
+ if (pShrdTbl == NULL)
+ {
+ return hr;
+ }
+#endif
+
+ // Allocate storage to hold a class pattern
+ pPattern = (SPatternEntry *) PrivMemAlloc(sizeof(SPatternEntry) + 128);
+ if (pPattern == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // Open the class pattern entries
+ if (RegOpenKey(HKEY_CLASSES_ROOT, L"FileType", &hkFileType)
+ == ERROR_SUCCESS)
+ {
+ // Enumerate the clsid's under this key
+ WCHAR szBuf[40];
+ DWORD iClsid = 0;
+
+ while (RegEnumKey(hkFileType, iClsid, szBuf, sizeof(szBuf))
+ == ERROR_SUCCESS)
+ {
+ // Ensure this is a valid clsid
+ WCHAR szTemp[MAX_PATH];
+ LONG cbTemp = sizeof(szTemp);
+ WCHAR szClsid[80];
+
+ lstrcpyW(szClsid, L"Clsid\\");
+ lstrcatW(szClsid, szBuf);
+
+ if (RegQueryValue(HKEY_CLASSES_ROOT, szClsid, szTemp, &cbTemp)
+ == ERROR_SUCCESS)
+ {
+ // Clsid exists, open the key and enumerate the entries.
+ HKEY hkClsid;
+ CLSID clsid;
+ BOOL fValid;
+
+ // Fetch asociated file patterns only if CLSID is valid
+ if (GUIDFromString(szBuf, &clsid) &&
+ RegOpenKey(hkFileType, szBuf, &hkClsid) == ERROR_SUCCESS)
+ {
+ // Enumerate the patterns under this clsid
+ WCHAR szNum[10];
+ DWORD iPattern = 0;
+
+ while (RegEnumKey(hkClsid, iPattern, szNum, sizeof(szNum))
+ == ERROR_SUCCESS)
+ {
+ // Read the registry value and parse the string to
+ // create a class pattern
+ WCHAR szPattern[512];
+ LONG cb = sizeof(szPattern);
+
+ if (RegQueryValue(hkClsid, szNum, szPattern, &cb) ==
+ ERROR_SUCCESS)
+ {
+ // Parse this entry
+ if (ParsePattern(szPattern, cb, pPattern, clsid))
+ {
+ // Check the file for this pattern
+ if (SearchForPattern(hFile, pPattern))
+ {
+ memcpy(pclsid, &clsid, sizeof(CLSID));
+ RegCloseKey(hkClsid);
+ RegCloseKey(hkFileType);
+ return S_OK;
+ }
+ }
+ }
+
+ ++iPattern;
+ }
+
+ RegCloseKey(hkClsid);
+ }
+ }
+
+ ++iClsid;
+ }
+
+ RegCloseKey(hkFileType);
+ }
+
+ PrivMemFree(pPattern);
+ return hr;
+}
+#endif // !_CHICAGO_
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoCreateInstance (internal)
+//
+// Synopsis: helper function to create instance in given context
+//
+// Arguments: [rclsid] - the class of object to create
+// [pUnkOuter] - the controlling unknown (for aggregation)
+// [dwContext] - class context
+// [riid] - interface id
+// [ppv] - pointer for returned object
+//
+// Returns: REGDB_E_CLASSNOTREG, REGDB_E_READREGDB, REGDB_E_WRITEREGDB
+//
+//--------------------------------------------------------------------------
+INTERNAL wCoCreateInstance(
+ REFCLSID rclsid,
+ LPUNKNOWN pUnkOuter,
+ DWORD dwContext,
+ REFIID riid,
+ LPVOID FAR* ppv)
+{
+ TRACECALL(TRACE_ACTIVATION, "wCoCreateInstance");
+
+#ifdef DCOM
+ MULTI_QI OneQI;
+ HRESULT hr;
+
+ OneQI.pItf = NULL;
+ OneQI.pIID = &riid;
+
+ hr = CoCreateInstanceEx( rclsid, pUnkOuter, dwContext, NULL, 1, &OneQI );
+
+ *ppv = OneQI.pItf;
+ return hr;
+#else
+ IClassFactory FAR* pCF = NULL;
+ *ppv = NULL;
+
+ HRESULT hr = IOldCoGetClassObject(rclsid, dwContext, NULL,
+ IID_IClassFactory, (void FAR* FAR*)&pCF);
+ if (SUCCEEDED(hr))
+ {
+ hr = pCF->CreateInstance(pUnkOuter, riid, ppv);
+ pCF->Release();
+ }
+
+ return hr;
+#endif
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoMarshalInterThreadInterfaceInStream, (internal)
+//
+// Synopsis: helper function to a marshaled buffer to be passed
+// between threads.
+//
+// Arguments: [riid] - interface id
+// [pUnk] - ptr to interface we want to marshal
+// [ppStm] - stream we want to give back to caller
+//
+// Returns: NOERROR - Stream returned
+// E_INVALIDARG - Input parameters are invalid
+// E_OUTOFMEMORY - memory stream could not be created.
+//
+// Algorithm: Create a stream and finally marshal
+// the input interface into the stream.
+//
+// History: 03-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(HRESULT) wCoMarshalInterThreadInterfaceInStream(
+ REFIID riid,
+ LPUNKNOWN pUnk,
+ LPSTREAM *ppStm)
+{
+ HRESULT hr;
+ LPSTREAM pStm = NULL;
+
+ // Assume error
+ hr = E_OUTOFMEMORY;
+
+ // Create a stream
+ pStm = CreateMemStm(EST_INPROC_MARSHAL_SIZE, NULL);
+
+ if (pStm != NULL)
+ {
+ // Marshal the interface into the stream
+ hr = CoMarshalInterface(pStm, riid, pUnk, MSHCTX_INPROC, NULL,
+ MSHLFLAGS_NORMAL);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // Reset the stream to the begining
+ LARGE_INTEGER li;
+ LISet32(li, 0);
+ pStm->Seek(li, STREAM_SEEK_SET, NULL);
+
+ // Set the return value
+ *ppStm = pStm;
+ }
+ else
+ {
+ // Cleanup if failure
+ if (pStm != NULL)
+ {
+ pStm->Release();
+ }
+
+ *ppStm = NULL;
+ }
+
+ // Assert
+
+ // Return the result
+ return hr;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoGetInterfaceAndReleaseStream, (internal)
+//
+// Synopsis: Helper to unmarshal object from stream for inter-thread pass
+//
+// Arguments: [riid] - interface id
+// [pStm] - stream we want to give back to caller
+// [ppv] - pointer for returned object
+//
+// Returns: NOERROR - Unmarshaled object returned
+// E_OUTOFMEMORY - out of memory
+//
+// Algorithm: Unmarshal the stream and
+// finally release the stream pointer.
+//
+// History: 03-Nov-94 Ricksa Created
+//
+// Notes: This always releases the input stream if stream is valid.
+//
+//--------------------------------------------------------------------------
+INTERNAL_(HRESULT) wCoGetInterfaceAndReleaseStream(
+ LPSTREAM pstm,
+ REFIID riid,
+ LPVOID *ppv)
+{
+ HRESULT hr;
+
+ // Unmarshal the interface
+ hr = CoUnmarshalInterface(pstm, riid, ppv);
+
+ // Release the stream since that is the way the function is defined.
+ pstm->Release();
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HexStringToDword (private)
+//
+// Synopsis: scan lpsz for a number of hex digits (at most 8); update lpsz
+// return value in Value; check for chDelim;
+//
+// Arguments: [lpsz] - the hex string to convert
+// [Value] - the returned value
+// [cDigits] - count of digits
+//
+// Returns: TRUE for success
+//
+//--------------------------------------------------------------------------
+static BOOL HexStringToDword(LPCWSTR FAR& lpsz, DWORD FAR& Value,
+ int cDigits, WCHAR chDelim)
+{
+ int Count;
+
+ Value = 0;
+ for (Count = 0; Count < cDigits; Count++, lpsz++)
+ {
+ if (*lpsz >= '0' && *lpsz <= '9')
+ Value = (Value << 4) + *lpsz - '0';
+ else if (*lpsz >= 'A' && *lpsz <= 'F')
+ Value = (Value << 4) + *lpsz - 'A' + 10;
+ else if (*lpsz >= 'a' && *lpsz <= 'f')
+ Value = (Value << 4) + *lpsz - 'a' + 10;
+ else
+ return(FALSE);
+ }
+
+ if (chDelim != 0)
+ return *lpsz++ == chDelim;
+ else
+ return TRUE;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wUUIDFromString (internal)
+//
+// Synopsis: Parse UUID such as 00000000-0000-0000-0000-000000000000
+//
+// Arguments: [lpsz] - Supplies the UUID string to convert
+// [pguid] - Returns the GUID.
+//
+// Returns: TRUE if successful
+//
+//--------------------------------------------------------------------------
+INTERNAL_(BOOL) wUUIDFromString(LPCWSTR lpsz, LPGUID pguid)
+{
+ DWORD dw;
+
+ if (!HexStringToDword(lpsz, pguid->Data1, sizeof(DWORD)*2, '-'))
+ return FALSE;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
+ return FALSE;
+
+ pguid->Data2 = (WORD)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
+ return FALSE;
+
+ pguid->Data3 = (WORD)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pguid->Data4[0] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '-'))
+ return FALSE;
+
+ pguid->Data4[1] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pguid->Data4[2] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pguid->Data4[3] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pguid->Data4[4] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pguid->Data4[5] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pguid->Data4[6] = (BYTE)dw;
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pguid->Data4[7] = (BYTE)dw;
+
+ return TRUE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wGUIDFromString (internal)
+//
+// Synopsis: Parse GUID such as {00000000-0000-0000-0000-000000000000}
+//
+// Arguments: [lpsz] - the guid string to convert
+// [pguid] - guid to return
+//
+// Returns: TRUE if successful
+//
+//--------------------------------------------------------------------------
+INTERNAL_(BOOL) wGUIDFromString(LPCWSTR lpsz, LPGUID pguid)
+{
+ DWORD dw;
+
+ if (*lpsz++ != '{' )
+ return FALSE;
+
+ if(wUUIDFromString(lpsz, pguid) != TRUE)
+ return FALSE;
+
+ lpsz +=36;
+
+ if (*lpsz++ != '}' )
+ return FALSE;
+
+ if (*lpsz != '\0') // check for zero terminated string - test bug #18307
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wStringFromCLSID (internal)
+//
+// Synopsis: converts GUID into {...} form.
+//
+// Arguments: [rclsid] - the guid to convert
+// [lplpsz] - ptr to buffer for results
+//
+// Returns: NOERROR
+// E_OUTOFMEMORY
+//
+//--------------------------------------------------------------------------
+INTERNAL wStringFromCLSID(REFCLSID rclsid, LPWSTR FAR* lplpsz)
+{
+ WCHAR sz[CLSIDSTR_MAX];
+
+ Verify(StringFromCLSID2(rclsid, sz, CLSIDSTR_MAX) != 0);
+
+ *lplpsz = UtDupString(sz);
+
+ return *lplpsz != NULL ? NOERROR : E_OUTOFMEMORY;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wStringFromIID (internal)
+//
+// Synopsis: converts GUID into {...} form.
+//
+// Arguments: [rclsid] - the guid to convert
+// [lplpsz] - ptr to buffer for results
+//
+// Returns: NOERROR
+// E_OUTOFMEMORY
+//
+//--------------------------------------------------------------------------
+INTERNAL wStringFromIID(REFIID rclsid, LPWSTR FAR* lplpsz)
+{
+ WCHAR sz[IIDSTR_MAX];
+ *lplpsz = NULL;
+
+ if (StringFromIID2(rclsid, sz, IIDSTR_MAX) != 0)
+ {
+ *lplpsz = UtDupString(sz);
+ }
+
+ return *lplpsz != NULL ? NOERROR : E_OUTOFMEMORY;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wIIDFromString (internal)
+//
+// Synopsis: converts string {...} form int guid
+//
+// Arguments: [lpsz] - ptr to buffer for results
+// [lpiid] - the guid to convert
+//
+// Returns: NOERROR
+// CO_E_CLASSSTRING
+//
+//--------------------------------------------------------------------------
+INTERNAL wIIDFromString(LPWSTR lpsz, LPIID lpiid)
+{
+ if (lpsz == NULL)
+ {
+ *lpiid = IID_NULL;
+ return NOERROR;
+ }
+
+ return wGUIDFromString(lpsz, lpiid)
+ ? NOERROR : CO_E_IIDSTRING;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoIsOle1Class (internal)
+//
+// Synopsis: reads the Ole1Class entry in the registry for the given clsid
+//
+// Arguments: [rclsid] - the classid to look up
+//
+// Returns: TRUE if Ole1Class
+// FALSE otherwise
+//
+//--------------------------------------------------------------------------
+INTERNAL_(BOOL) wCoIsOle1Class(REFCLSID rclsid)
+{
+ TRACECALL(TRACE_REGISTRY, "wCoIsOle1Class");
+ CairoleDebugOut((DEB_REG, "wCoIsOle1Class called.\n"));
+
+ // since we now have guid, Ole1Class = would indicate OLE 1.0 nature.
+ // lookup HKEY_CLASSES_ROOT\{rclsid}\Ole1Class
+ WCHAR szValue[VALUE_LEN];
+
+ if (wRegQueryClassValue(rclsid, wszOle1Class, szValue, sizeof(szValue)) != ERROR_SUCCESS)
+ {
+ return FALSE;
+ }
+ else
+ {
+ WORD hiWord = HIWORD(rclsid.Data1);
+
+ return hiWord == 3 || hiWord == 4;
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wkProgIDFromCLSID (internal)
+// (wProgIDFromCLSID name is already in use)
+//
+// Synopsis: convert clsid into progid
+//
+// Arguments: [rclsid] - the classid to look up
+// [pszProgID] - returned progid
+//
+// Returns: E_INVALIDARG, E_OUTOFMEMORY,
+// REGDB_CLASSNOTREG, REGDB_E_READREGDB
+//
+//--------------------------------------------------------------------------
+INTERNAL wkProgIDFromCLSID(REFCLSID rclsid, LPWSTR FAR* ppszProgID)
+{
+ TRACECALL(TRACE_REGISTRY, "wkProgIDFromCLSID");
+
+ WCHAR szProgID[KEY_LEN];
+
+ *ppszProgID = NULL;
+
+ switch (wRegQueryClassValue (rclsid, wszProgID, szProgID, sizeof(szProgID)))
+ {
+ case ERROR_SUCCESS:
+ *ppszProgID = UtDupString (szProgID);
+ return (*ppszProgID != NULL) ? NOERROR : E_OUTOFMEMORY;
+
+
+ // win32 will return file not found instead of bad key
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_BADKEY:
+ return REGDB_E_CLASSNOTREG;
+
+ default:
+ return REGDB_E_READREGDB;
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wRegQueryClassValue (Internal)
+//
+// Synopsis: reads the specified subkey of the specified clsid
+//
+// Arguments: [rclsid] - the classid to look up
+// [lpszSubKey] - subkey to read
+// [lpszValue] - buffer to hold returned value
+// [cbMax] - sizeof the buffer
+//
+// Returns: REGDB_E_CLASSNOTREG, REGDB_E_READREGDB
+//
+//--------------------------------------------------------------------------
+INTERNAL_(LONG) wRegQueryClassValue(REFCLSID rclsid, LPCWSTR lpszSubKey,
+ LPWSTR lpszValue, int cbMax)
+{
+ WCHAR szKey[KEY_LEN];
+ int cbClsid;
+ LONG cbValue = cbMax;
+
+ lstrcpyW(szKey, wszClassKey);
+
+ // translate rclsid into string
+ cbClsid = StringFromCLSID2(rclsid, &szKey[ulClassKeyLen],
+ sizeof(szKey)-ulClassKeyLen);
+
+ CairoleAssert((cbClsid != 0) && "wRegQueryClassValue");
+
+ szKey[ulClassKeyLen+cbClsid-1] = L'\\';
+ lstrcpyW(&szKey[ulClassKeyLen+cbClsid], lpszSubKey);
+
+ CairoleDebugOut((DEB_REG, "ReqQueryValue(%ws)\n", szKey));
+ return RegQueryValue(HKEY_CLASSES_ROOT, szKey, lpszValue, &cbValue);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoOpenClassKey (internal)
+//
+// Synopsis: opens a registry key for specified class
+//
+// Arguments: [rclsid] - the classid to look up
+// [pszProgID] - returned progid
+//
+// Returns: REGDB_CLASSNOTREG, REGDB_E_READREGDB
+//
+//--------------------------------------------------------------------------
+INTERNAL wCoOpenClassKey(REFCLSID clsid, HKEY FAR* lphkeyClsid)
+{
+ TRACECALL(TRACE_REGISTRY, "wCoOpenClassKey");
+
+ if (IsEqualCLSID(clsid, CLSID_NULL))
+ return REGDB_E_CLASSNOTREG;
+
+ WCHAR szKey[KEY_LEN];
+ lstrcpyW (szKey, wszClassKey);
+ Verify (StringFromCLSID2 (clsid, szKey+ulClassKeyLen,
+ sizeof(szKey)-ulClassKeyLen) != 0);
+
+ switch (RegOpenKey(HKEY_CLASSES_ROOT, szKey, lphkeyClsid))
+ {
+ case ERROR_SUCCESS:
+ return NOERROR;
+
+
+ // win32 will return file not found instead of bad key
+ case ERROR_FILE_NOT_FOUND:
+ case ERROR_BADKEY:
+ return REGDB_E_CLASSNOTREG;
+
+ default:
+ return REGDB_E_READREGDB;
+ }
+}
diff --git a/private/ole32/com/class/compobj.cxx b/private/ole32/com/class/compobj.cxx
new file mode 100644
index 000000000..942857263
--- /dev/null
+++ b/private/ole32/com/class/compobj.cxx
@@ -0,0 +1,1879 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: d:\nt\private\cairole\com\class\compobj.cxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions: GetInfoLevel
+// DllMain
+// CheckAndStartSCM
+// CoGetCurrentProcess
+// CoBuildVersion
+// SetOleThunkWowPtr
+// CoInitializeWOW
+// CoInitialize
+// CoInitializeEx
+// CoUninitialize
+//
+// History: 09-Jun-94 BruceMa Added this file header
+// 09-Jun-94 BruceMa Distinguish CoInitialize errors
+// 14-Jun-94 BruceMa Ensure single threading
+// 17-Jun-94 Bradlo Add SetState/GetState
+// 06-Jul-94 BruceMa Support for CoGetCurrentProcess
+// 28-Jul-94 BruceMa Allow CoGetCurrentProcess to do a
+// partial CoInitialize (because Publisher
+// didn't call CoInitialize (!))
+// 29-Aug-94 AndyH set the locale for the CRT
+// 29-Sep-94 AndyH remove setlocale call
+// 06-Oct-94 BruceMa Allow CoGetCurrentProcess to work even
+// if that thread didn't call CoInitialize
+// 09-Nov-94 BruceMa Initialize/Delete IMallocSpy
+// critical section
+// 12-Dec-94 BruceMa Delete Chicago pattern table at
+// CoUninitialize
+// 09-Jan-95 BruceMa Initialize/Delete ROT
+// critical section
+// 10-May-95 KentCe Defer Heap Destruction to the last
+// process detach.
+// 28-Aug-95 BruceMa Close g_hRegPatTblEvent at
+// ProcessUninitialize
+// 25-Sep-95 BruceMa Check that scm is started during
+// CoInitialize
+// 25-Oct-95 Rickhi Improve CoInit Time.
+//
+//----------------------------------------------------------------------
+// compobj.cpp - main file for the compobj dll
+
+#if !defined(_CHICAGO_)
+extern "C"
+{
+#include <nt.h> // NT_PRODUCT_TYPE
+#include <ntdef.h> // NT_PRODUCT_TYPE
+#include <ntrtl.h> // NT_PRODUCT_TYPE
+#include <nturtl.h> // NT_PRODUCT_TYPE
+#include <windef.h> // NT_PRODUCT_TYPE
+#include <winbase.h> // NT_PRODUCT_TYPE
+}
+#endif
+
+#include <ole2int.h>
+#include <verole.h> // for CoBuildVersion
+#include <thunkapi.hxx> // For interacting with the VDM
+#include <scmstart.hxx>
+#include <cevent.hxx>
+#include <olespy.hxx>
+
+#ifndef _CHICAGO_
+#include <shrtbl.hxx> // CDllShrTbl
+#endif
+
+#ifdef _CHICAGO_
+#include "pattbl.hxx"
+#include <smmutex.hxx>
+#endif // _CHICAGO_
+
+#include <olepfn.hxx>
+
+#if DBG==1
+#include <outfuncs.h>
+#endif
+
+DEFHOOKOBJECT // HOOKOLE
+
+NAME_SEG(CompObj)
+ASSERTDATA
+
+HRESULT Storage32DllGetClassObject(REFCLSID clsid, REFIID iid, void **ppv);
+HRESULT MonikerDllGetClassObject(REFCLSID clsid, REFIID iid, void **ppv);
+HRESULT Ole232DllGetClassObject(REFCLSID clsid, REFIID iid, void **ppv);
+EXTERN_C HRESULT PrxDllGetClassObject(REFCLSID clsid, REFIID iid, void **ppv);
+
+HRESULT MallocInitialize(BOOL fForceLocalAlloc);
+BOOL MallocUninitialize(void);
+
+STDAPI OleReleaseEnumVerbCache();
+extern void ClipboardProcessUninitialize();
+
+extern void CleanUpLocalServersForProcess();
+extern void CleanUpDllsForProcess();
+extern void CleanUpLocalServersForApartment();
+extern void CleanUpDllsForApartment();
+extern void CleanROTForApartment();
+
+#ifdef DCOM
+extern void DllHostProcessInitialize();
+extern void DllHostThreadUninitialize();
+extern void DllHostProcessUninitialize();
+extern ULONG gcHostProcessInits;
+#endif
+
+#if defined(_CHICAGO_)
+COleStaticMutexSem g_Rpcrt4Sem;
+#endif
+
+#ifdef _CHICAGO_
+extern HANDLE g_hRegPatTblEvent;
+extern CChicoPatternTbl *g_pPatTbl;
+STDAPI SSAPI(CoInitializeEx)(LPVOID pvReserved, ULONG flags );
+char *szHeapDestoySync = "OleHeapDestroyMutex";
+#else
+CDllShrdTbl *g_pShrdTbl = NULL;
+#endif // _CHICAGO_
+
+#ifndef _CHICAGO_
+extern void ScmGetThreadId( DWORD * pThreadID );
+#endif
+
+STDAPI CoSetState(IUnknown *punkStateNew);
+WINOLEAPI CoSetErrorInfo(DWORD dwReserved, IErrorInfo * pErrorInfo);
+
+#if defined(_CHICAGO_)
+//
+// Locate the following in a shared data segment.
+//
+#pragma data_seg(".sdata")
+
+SOleSharedTables gs_SharedTables = { 0, NULL, NULL, NULL, NULL, NULL, 0 };
+LONG gs_lNextGuidIndex = 0x1;
+
+LONG gs_ProcessAttachCount = 0; // Count of process attaches.
+
+#pragma data_seg()
+
+extern HANDLE gs_hSharedHeap; // hSharedHeap Handle for Win95.
+
+#endif // defined(_CHICAGO_)
+
+
+void ProcessUninitialize( void );
+void DoThreadSpecificCleanup();
+
+
+COleStaticMutexSem g_mxsSingleThreadOle;
+COleStaticMutexSem gmxsOleMisc;
+
+// The following pointer is used to hold an interface to the
+// WOW thunk interface.
+
+LPOLETHUNKWOW g_pOleThunkWOW = NULL;
+
+// The following is the count of per-process CoInitializes that have been done.
+DWORD g_cProcessInits = 0; // total per process inits
+DWORD g_cMTAInits = 0; // # of multi-threaded inits
+DWORD g_cSTAInits = 0; // # of apartment-threaded inits
+
+
+// Holds the process id of SCM. DCOM uses this to unmarshal an object
+// interface on the SCM. See MakeSCMProxy in dcomrem\ipidtbl.cxx.
+DWORD gdwScmProcessID = 0;
+
+//
+// On Chicago, we keep shared state
+//
+#ifdef _CHICAGO_
+
+const TCHAR * SHAREDSTATEMUTEXNAME = TEXT("OleCoSharedStateMtx");
+const WCHAR * SHAREDSTATENAME = L"OleCoSharedState";
+
+HANDLE g_hSharedState = NULL;
+HANDLE g_hSharedStateMutex = NULL;
+SOleSharedTables * g_post = NULL;
+
+#endif // _CHICAGO_
+
+// enable object hooking
+DEFENABLEHOOKOBJECT
+DEFGETHOOKINTERFACE
+
+#if DBG==1
+//---------------------------------------------------------------------------
+//
+// function: GetInfoLevel
+//
+// purpose: This routine is called when a process attaches. It extracts
+// the debug info levels values from win.ini.
+//
+//---------------------------------------------------------------------------
+
+// externals used below in calls to this function
+
+extern "C" unsigned long heapInfoLevel; // memory tracking
+//Set ole32!heapInfoLevel != 0 to use the OLE debug allocator in debug build.
+//Set ole32!heapInfoLevel & DEB_ITRACE for backtrace of memory leaks in debug build.
+
+extern "C" unsigned long olInfoLevel; // lower layer storage
+extern "C" unsigned long msfInfoLevel; // upper layer storage
+extern "C" unsigned long LEInfoLevel; // linking and embedding
+extern "C" unsigned long RefInfoLevel; // CSafeRef class
+extern "C" unsigned long DDInfoLevel; // Drag'n'drop
+extern "C" unsigned long mnkInfoLevel; // Monikers
+extern "C" unsigned long hkInfoLevel; // HOOKOLE
+
+#ifndef _CHICAGO_
+extern "C" unsigned long propInfoLevel; // properties
+#endif
+
+#ifdef SERVER_HANDLER
+extern "C" unsigned long HdlInfoLevel; // ServerHandler and ClientSiteHandler
+#endif // SERVER_HANDLER
+
+extern DWORD g_dwInfoLevel;
+
+
+DECLARE_INFOLEVEL(intr); // For 1.0/2.0 interop
+DECLARE_INFOLEVEL(UserNdr); // For Oleprxy32 and NDR
+DECLARE_INFOLEVEL(Stack); // For stack switching
+DECLARE_INFOLEVEL(hk); // hook OLE
+
+
+ULONG GetInfoLevel(CHAR *pszKey, ULONG *pulValue, CHAR *pszdefval)
+{
+ CHAR szValue[20];
+ DWORD cbValue = sizeof(szValue);
+
+ // if the default value has not been overridden in the debugger,
+ // then get it from win.ini.
+
+ if (*pulValue == (DEB_ERROR | DEB_WARN))
+ {
+ if (GetProfileStringA("CairOLE InfoLevels", // section
+ pszKey, // key
+ pszdefval, // default value
+ szValue, // return buffer
+ cbValue))
+ {
+ *pulValue = strtoul (szValue, NULL, 16);
+ }
+ }
+
+ return *pulValue;
+}
+// stack switching is by defaul on
+
+BOOL fSSOn = TRUE;
+
+#endif // DBG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllGetClassObject
+//
+// Synopsis: Dll entry point
+//
+// Arguments: [clsid] - class id for new class
+// [iid] - interface required of class
+// [ppv] - where to put new interface
+//
+// Returns: S_OK - class object created successfully created.
+//
+// History: 21-Jan-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **ppv)
+{
+ OLETRACEIN((API_DllGetClassObject, PARAMFMT("rclsid= %I,iid= %I,ppv= %p"), &clsid, &iid, ppv));
+
+ HRESULT hr = Storage32DllGetClassObject(clsid, iid, ppv);
+
+ if (FAILED(hr))
+ {
+ hr = MonikerDllGetClassObject(clsid, iid, ppv);
+ }
+
+ if (FAILED(hr))
+ {
+ hr = PrxDllGetClassObject(clsid, iid, ppv);
+ }
+
+ if (FAILED(hr))
+ {
+ hr = ComDllGetClassObject(clsid, iid, ppv);
+ }
+
+ if (FAILED(hr))
+ {
+ hr = Ole232DllGetClassObject(clsid, iid, ppv);
+ }
+
+ OLETRACEOUT((API_DllGetClassObject, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllMain
+//
+// Synopsis: Dll entry point for OLE/COM
+//
+// Arguments: [hDll] - a handle to the dll instance
+// [dwReason] - the reason LibMain was called
+// [lpvReserved] - NULL - called due to FreeLibrary
+// - non-NULL - called due to process exit
+//
+// Returns: TRUE on success, FALSE otherwise
+//
+// Notes:
+// If we are called because of FreeLibrary, then we should do as
+// much cleanup as we can. If we are called because of process
+// termination, we should not do any cleanup, as other threads in
+// this process will have already been killed, potentially while
+// holding locks around resources.
+//
+// The officially approved DLL entrypoint name is DllMain. This
+// entry point will be called by the CRT Init function.
+//
+// History: 06-Dec-93 Rickhi dont do cleanup on process exit
+// 09-Nov-94 BruceMa Initialize/Delete IMallocSpy
+// critical section
+// 16-Jan-95 KevinRo Changed to DllMain to remove a bunch
+// of unneeded code and calls
+//
+//--------------------------------------------------------------------------
+extern "C" BOOL WINAPI DllMain(
+ HANDLE hInstance,
+ DWORD dwReason,
+ LPVOID lpvReserved)
+{
+ HRESULT hr;
+
+ if (dwReason == DLL_PROCESS_DETACH)
+ {
+ CairoleDebugOut((DEB_DLL,
+ "DLL_PROCESS_DETACH: %s\n",
+ lpvReserved?"Process Exit":"Dll Unload"));
+
+ // Process is exiting so lets clean up if we have to
+
+#if defined(_CHICAGO_)
+ //
+ // BUGBUG: (KevinRo) Turns out that the Win95/Nashville loader
+ // has a bug that prevents us from correctly unloading DLL's.
+ // The problem is that they decrement their reference counts
+ // before calling DllMain()'s. When we free'd RPCRT4.DLL,
+ // the loader would in turn free MSVCRT.DLL too early, and
+ // we would die on return.
+ // The PSD group is going to fix the loader someday. Until
+ // then, we will just leave RPCRT4 loaded.
+ //
+ // FreeRPCRT4();
+ //
+
+#endif
+
+ //
+ // When there is a FreeLibrary, and we still have initialized OLE
+ // com threads, then try to get rid of all of the global process
+ // stuff we are maintaining.
+ //
+ if (g_cProcessInits != 0 && lpvReserved == NULL )
+ {
+ ProcessUninitialize();
+ UNINITHOOKOBJECT();
+ }
+
+ ThreadNotification((HINSTANCE)hInstance, dwReason, lpvReserved);
+
+ MallocUninitialize();
+
+#if defined(_CHICAGO_)
+ //
+ // Due to shared memory structures stored in our shared data segment,
+ // we must delay the destruction of the shared heap until the last
+ // process detaches from OLE32.DLL.
+ //
+
+ // We put a block here for two reasons. First to take advantage of
+ // the C++ semantics that will guarantee that the destructor for the
+ // mutex object is called by any exit path from the block. Secondly,
+ // we use it so that if code is added after this block, we won't
+ // hold the mutex any longer than we absolutely need to.
+ {
+ // Synchronize with process attaches so that we guarantee that
+ // all variables connected with the heap are valid.
+ CSmMutex smxs;
+ smxs.Init(szHeapDestoySync, TRUE);
+
+ // Are we the last process that is using the heap?
+ if (--gs_ProcessAttachCount == 0)
+ {
+ // Is there a heap?
+ if (gs_hSharedHeap != NULL)
+ {
+ HeapDestroy(gs_hSharedHeap);
+ gs_hSharedHeap = NULL;
+
+ // The following are pointers into the shared heap so
+ // they all need to be NULL'd because they are no longer
+ // valid.
+ gs_SharedTables.pscmrot = NULL;
+ gs_SharedTables.gpCHandlerList = NULL;
+ gs_SharedTables.gpCInProcList = NULL;
+ gs_SharedTables.gpCLocSrvList = NULL;
+ gs_SharedTables.gpCClassCacheList = NULL;
+ }
+ }
+ }
+#endif
+
+#if DBG==1
+ CloseDebugSinks();
+#endif
+
+ //
+ // Only bother to rundown the static mutex pool if we're being
+ // unloaded w/o exiting the process
+ //
+
+ if (lpvReserved == NULL)
+ {
+ //
+ // Destruct the static mutex pool
+ //
+
+ while (g_pInitializedStaticMutexList != NULL)
+ {
+ COleStaticMutexSem * pMutex;
+
+ pMutex = g_pInitializedStaticMutexList;
+ g_pInitializedStaticMutexList = pMutex->pNextMutex;
+ pMutex->Destroy();
+ }
+
+ DeleteCriticalSection (&g_OleMutexCreationSem);
+ }
+
+
+#if DBG==1
+
+ CairoleAssert (g_fDllState == DLL_STATE_NORMAL);
+ g_fDllState = DLL_STATE_STATIC_DESTRUCTING;
+
+#endif
+
+ return TRUE;
+ }
+
+
+ else if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ // Initialize the mutex package. Do this BEFORE doing anything
+ // else, as even a DebugOut will fault if the critical section
+ // is not initialized.
+
+ InitializeCriticalSection (&g_OleMutexCreationSem);
+
+ ComDebOut((DEB_DLL,"DLL_PROCESS_ATTACH:\n"));
+
+#if DBG==1
+
+ // Note that we've completed running the static constructors
+
+ CairoleAssert (g_fDllState == DLL_STATE_STATIC_CONSTRUCTING);
+
+ g_fDllState = DLL_STATE_NORMAL;
+
+#endif
+
+
+#if DBG==1
+ OpenDebugSinks(); // Set up for logging
+
+ // set the various info levels
+ GetInfoLevel("cairole", &CairoleInfoLevel, "0x0003");
+ GetInfoLevel("ol", &olInfoLevel, "0x0003");
+ GetInfoLevel("msf", &msfInfoLevel, "0x0003");
+ GetInfoLevel("LE", &LEInfoLevel, "0x0003");
+#ifdef SERVER_HANDLER
+ GetInfoLevel("Hdl", &HdlInfoLevel, "0x0003");
+#endif // SERVER_HANDLER
+ GetInfoLevel("Ref", &RefInfoLevel, "0x0003");
+ GetInfoLevel("DD", &DDInfoLevel, "0x0003");
+ GetInfoLevel("mnk", &mnkInfoLevel, "0x0003");
+ GetInfoLevel("intr", &intrInfoLevel, "0x0003");
+ GetInfoLevel("UserNdr", &UserNdrInfoLevel, "0x0003");
+ GetInfoLevel("Stack", &StackInfoLevel, "0x0003");
+#ifndef _CHICAGO_
+ GetInfoLevel("prop", &propInfoLevel, "0x0003");
+#endif
+
+ ULONG dummy;
+
+ // Get API trace level
+ dummy = DEB_WARN|DEB_ERROR;
+ GetInfoLevel("api", &dummy, "0x0000");
+ g_dwInfoLevel = (DWORD) dummy;
+
+ fSSOn = (BOOL)GetInfoLevel("StackOn", &dummy, "0x0003");
+ GetInfoLevel("heap", &heapInfoLevel, "0x0003");
+ if(heapInfoLevel != 0)
+ {
+ //Initialize the OLE debug memory allocator.
+ hr = MallocInitialize(FALSE);
+ }
+ else
+#endif //DBG==1
+ {
+ //Initialize the OLE retail memory allocator.
+ hr = MallocInitialize(TRUE);
+ }
+
+ if(FAILED(hr))
+ {
+ ComDebOut((DEB_ERROR, "Failed to init memory allocator hr:%x",hr));
+ return FALSE;
+ }
+ //
+ // this will be needed for the J version
+ // setlocale(LC_CTYPE, "");
+ //
+ g_hmodOLE2 = (HMODULE)hInstance;
+ g_hinst = (HINSTANCE)hInstance;
+
+#if defined(_CHICAGO_)
+ //
+ // Keep track of the number of process attaches. See detach logic
+ // for details.
+ //
+
+ {
+ // Synchronize with process detaches so that we guarantee that
+ // all variables connected with the heap are in a valid state.
+ CSmMutex smxs;
+ smxs.Init(szHeapDestoySync, TRUE);
+ gs_ProcessAttachCount++;
+ }
+#endif
+
+ InitializeOleSpy(OLESPY_TRACE);
+
+#ifdef TRACELOG
+ if (!sg_pTraceLog)
+ {
+ sg_pTraceLog = (CTraceLog *) new CTraceLog();
+ CairoleAssert(sg_pTraceLog && "Create Trace Log Failed");
+ }
+#endif // TRACELOG
+
+ // init the object hooking
+ INITHOOKOBJECT(S_OK);
+
+ }
+
+ return ThreadNotification((HINSTANCE)hInstance, dwReason, lpvReserved);
+}
+
+#ifdef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Function: CheckAndStartSCM, private
+//
+// Synopsis: Checks to see if the SCM needs to be started, and starts it
+// up if it does.
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+// History: 07-Apr-94 PhilipLa Created
+//
+// Only Chicago uses these shared state tables. At one time, NT had them also,
+// but only for the unique process ID. NT now uses a call to the SCM to get
+// the unique process ID
+//
+// On NT, the SCM is Auto-Start so we dont need to check if it is running.
+// There is a race between the shell starting and SCM starting, but the code
+// to deal with that race is in the shell and in the SCM.
+//
+//----------------------------------------------------------------------------
+HRESULT CheckAndStartSCM(void)
+{
+ CairoleDebugOut((DEB_COMPOBJ, "In CheckAndStartSCM\n"));
+
+ HRESULT hr = S_OK;
+
+ BOOL fCreated = FALSE;
+
+ SECURITY_ATTRIBUTES secattr;
+ secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ secattr.lpSecurityDescriptor = NULL;
+ secattr.bInheritHandle = FALSE;
+
+ if (g_hSharedStateMutex == NULL)
+ {
+ //First, create the Mutex for this shared block
+ if (NULL == (g_hSharedStateMutex = CreateMutex(&secattr, FALSE,
+ SHAREDSTATEMUTEXNAME)))
+ {
+ return CO_E_INIT_SCM_MUTEX_EXISTS;
+ }
+ }
+
+ //Now take the mutex. We can then party on this block as much
+ // as we want until we release the mutex.
+ WaitForSingleObject(g_hSharedStateMutex, INFINITE);
+
+ if (g_post == NULL)
+ {
+ g_post = &gs_SharedTables;
+ }
+
+ hr = StartSCM();
+
+ ReleaseMutex(g_hSharedStateMutex);
+
+ CairoleDebugOut((DEB_COMPOBJ, "Out CheckAndStartSCM\n"));
+ return hr;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: ProcessInitialize, private
+//
+// Synopsis: Performs all of the process initialization. Happens when
+// the first com thread calls CoInitialize.
+//
+// Arguments: None.
+//
+// Returns: S_OK, CO_E_INIT_RPC_CHANNEL, E_FAIL
+//
+// History: 29-Aug-95 RickHi Created
+//
+//----------------------------------------------------------------------------
+HRESULT ProcessInitialize()
+{
+ HRESULT hr = S_OK;
+
+#ifdef _CHICAGO_
+ // BUGBUG: KevinRo: Needed to add this back in to get the Nashville
+ // build going again.
+ // NASHVILLE_KEVINRO
+
+ // init remoting piece of COM
+ hr = ChannelProcessInitialize();
+
+ if (SUCCEEDED(hr))
+ {
+ // Start the SCM if necessary.
+ hr = CheckAndStartSCM();
+ }
+ else
+ {
+ hr = CO_E_INIT_RPC_CHANNEL;
+ }
+
+ if (FAILED(hr))
+ {
+ // Clean up
+ ChannelProcessUninitialize();
+ }
+#endif // _CHICAGO_
+
+ // Initialize the OleSpy
+ InitializeOleSpy(OLESPY_CLIENT);
+
+ // Initialize Access Control.
+ if (SUCCEEDED(hr))
+ hr = InitializeAccessControl();
+
+#ifdef DCOM
+ // init the dll host objects
+ DllHostProcessInitialize();
+#endif
+
+ ComDebErr(FAILED(hr), "ProcessInitialize failed\n");
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ProcessUninitialize, private
+//
+// Synopsis: Performs all of the process de-initialization. Happens when
+// the last com thread calls CoUninitialize, or when the
+// DLL_PROCESS_DETACH notification comes through.
+//
+// Arguments: None.
+//
+// Returns: Nothing.
+//
+// History: 29-Aug-94 RickHi Created
+//
+//----------------------------------------------------------------------------
+void ProcessUninitialize()
+{
+ // clean up clipboard window class registration
+ ClipboardProcessUninitialize();
+
+ // Free Enum verb cache
+ OleReleaseEnumVerbCache();
+
+ // release any proxies or marshaled server objects
+ IDTableProcessUninitialize();
+
+ // clean up the rot
+ DestroyRunningObjectTable();
+
+ // Cleanup AccessControl.
+ UninitializeAccessControl();
+
+ // Turn off RPC
+ ChannelProcessUninitialize();
+
+ // Free loaded Dlls class cache
+ CleanUpDllsForProcess();
+
+ // delete the shared mem table object
+#ifdef _CHICAGO_
+ if (g_pPatTbl != NULL)
+ {
+ delete g_pPatTbl;
+ g_pPatTbl = NULL;
+ }
+ if (g_hRegPatTblEvent)
+ {
+ CloseHandle(g_hRegPatTblEvent);
+ g_hRegPatTblEvent = NULL;
+ }
+#else
+ if (g_pShrdTbl)
+ {
+ delete g_pShrdTbl;
+ g_pShrdTbl = NULL;
+ }
+#endif // _CHICAGO_
+
+#ifdef TRACELOG
+ if (sg_pTraceLog)
+ {
+ CTraceLog *pTraceLog = sg_pTraceLog;
+ sg_pTraceLog = NULL; // prevent more entries into the log
+ delete pTraceLog; // delete the log, also dumps it.
+ }
+#endif // TRACELOG
+
+ UninitializeOleSpy(OLESPY_TRACE);
+
+ // If WOW is going down, disable it.
+ // WARNING: IsWOWThread & IsWOWProcess will no longer return valid results!!!!
+ g_pOleThunkWOW = NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: STAProcessInitialize, private
+//
+// Synopsis: Performs all of the process initialization needed when the
+// first Single-Threaded Apartment initializes.
+//
+// Returns: S_OK, E_FAIL
+//
+// History: 11-Mar-96 RickHi Created
+//
+//----------------------------------------------------------------------------
+HRESULT STAProcessInitialize()
+{
+ Win4Assert(IsSTAThread());
+
+ // we want to remember the thread so we can dispatch getting
+ // single threaded class objects to the main thread.
+ if (!InitMainThreadWnd())
+ {
+ ComDebOut((DEB_ERROR, "InitMainThreadWnd failed \n"));
+ return E_FAIL;
+ }
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: STAProcessUninitialize, private
+//
+// Synopsis: Performs all of the process uninitialization needed when the
+// first Single-Threaded Apartment uninitializes.
+//
+// History: 11-Mar-96 RickHi Created
+//
+//----------------------------------------------------------------------------
+void STAProcessUninitialize()
+{
+ Win4Assert(IsSTAThread());
+ UninitMainThreadWnd();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ApartmentUninitialzie, private
+//
+// Synopsis: Performs all of the process uninitialization needed when a
+// Single-Threaded Apartment uninitializes, and when the
+// Multi-Threaded apartment uninitializes.
+//
+// returns: TRUE - uninit complete
+// FALSE - uninit aborted
+//
+// History: 11-Mar-96 RickHi Created
+//
+//----------------------------------------------------------------------------
+BOOL ApartmentUninitialize()
+{
+ // NOTE: The following sequence of uninitializes is critical:
+ //
+ // 1) Prevent incoming calls
+ // 2) LocalServer class cache
+ // 3) object activation (objact) server object
+ // 4) Dll host server object
+ // 5) standard identity table
+ // 6) running object table
+ // 7) Prevent outgoing calls (channel)
+ // 8) Dll class cache - since chnl cleanup may touch proxies/stubs
+
+ // Prevent incoming calls.
+ ThreadStop();
+
+ // ThreadStop let pending calls complete and while doing so the apartment
+ // init count may have been incremented again. If it has, we abort the
+ // uninit before any real cleanup is done.
+
+ COleTls tls;
+ if (tls->dwFlags & OLETLS_APARTMENTTHREADED)
+ {
+ if (tls->cComInits > 1)
+ return FALSE;
+ }
+ else
+ {
+ if (g_cMTAInits > 1)
+ return FALSE;
+ }
+
+ // cleanup per apartment registered LocalServer class table
+ CleanUpLocalServersForApartment();
+
+#ifdef DCOM
+ // cleanup per apartment object activation server objects
+ ObjactThreadUninitialize();
+
+ // clean up the Dll Host Apartments
+ DllHostThreadUninitialize();
+#endif
+ // cleanup per apartment identity objects
+ IDTableThreadUninitialize();
+
+ // cleanup per apartment ROT.
+ CleanROTForApartment();
+
+ // cleanup the per apartment channel.
+ ChannelThreadUninitialize();
+
+ // cleanup per apartment Dll class table.
+ CleanUpDllsForApartment();
+
+ return TRUE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetOleThunkWowPtr
+//
+// Synopsis: Sets the value of g_pOleThunkWOW, as part of CoInitializeWow
+// and OleInitializeWow. This function is called by these
+// routines.
+//
+// Effects:
+//
+// Arguments: [pOleThunk] -- VTable pointer to OleThunkWow interface
+//
+// Returns: none
+//
+// History: 4-05-94 kevinro Created
+//----------------------------------------------------------------------------
+void SetOleThunkWowPtr(LPOLETHUNKWOW lpthk)
+{
+ //
+ // The theory here is that the lpthk parameter is the address into the
+ // olethk32.dll and once loaded will never change. Therefore it only
+ // needs to be set on the first call. After that, we can ignore the
+ // subsequent calls, since they should be passing in the same value.
+ //
+ // If g_pOleThunkWOW is set to INVALID_HANDLE_VALUE, then OLETHK32 had
+ // been previously unloaded, but is reloading
+ //
+ // I don't belive there is a multi-threaded issue here, since the pointer
+ // value will always set as the same. Therefore, if two threads set it,
+ // no problem.
+ //
+
+ if(!IsWOWThreadCallable())
+ {
+ g_pOleThunkWOW = lpthk;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoInitializeWOW, private
+//
+// Synopsis: Entry point to initialize the 16-bit WOW thunk layer.
+//
+// Effects: This routine is called when OLE32 is loaded by a VDM.
+// It serves two functions: It lets OLE know that it is
+// running in a VDM, and it passes in the address to a set
+// of functions that are called by the thunk layer. This
+// allows normal 32-bit processes to avoid loading the WOW
+// DLL since the thunk layer references it.
+//
+// Arguments: [vlpmalloc] -- 16:16 pointer to the 16 bit allocator.
+// [lpthk] -- Flat pointer to the OleThunkWOW virtual
+// interface. This is NOT an OLE/IUnknown style
+// interface.
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 3-15-94 kevinro Created
+//
+// Notes:
+//
+// Note that vlpmalloc is a 16:16 pointer, and cannot be called directly
+//----------------------------------------------------------------------------
+STDAPI CoInitializeWOW( LPMALLOC vlpmalloc, LPOLETHUNKWOW lpthk )
+{
+ //
+ // At the moment, there was no need to hang onto the 16bit vlpmalloc
+ // routine for this thread. That may change once we get to the threaded
+ // model
+ //
+
+ vlpmalloc;
+
+ HRESULT hr;
+
+ OLETRACEIN((API_CoInitializeWOW, PARAMFMT("vlpmalloc= %x, lpthk= %p"), vlpmalloc, lpthk));
+
+ // Get (or allocate) the per-thread data structure
+ COleTls Tls(hr);
+
+ if (FAILED(hr))
+ {
+ ComDebOut((DEB_ERROR, "CoInitializeWOW Tls OutOfMemory"));
+ return CO_E_INIT_TLS;
+ }
+ Tls->dwFlags |= OLETLS_WOWTHREAD;
+
+ SetOleThunkWowPtr(lpthk);
+
+ // WOW may be calling CoInitialize on multiple threads
+ hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+
+ OLETRACEOUT((API_CoInitializeWOW, hr));
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoUnloadingWow
+//
+// Synopsis: Entry point to notify OLE32 that OLETHK32 is unloading
+//
+// Effects: This routine is called by OLETHK32 when it is being unloaded.
+// The key trick is to make sure that we uninitialize the current
+// thread before OLETHK32 goes away, and set the global thunk
+// vtbl pointer to INVALID_HANDLE_VALUE before it does go away.
+//
+// Otherwise, we run a risk that OLE32 will attempt to call
+// back to OLETHK32
+//
+// Arguments: fProcessDetach - whether this is a process detach
+//
+// Requires: IsWOWProcess must be TRUE
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 3-18-95 kevinro Created
+//
+// Notes:
+//
+// This routine is only called by PROCESS_DETACH in OLETHK32.DLL.
+// Because of this, there shouldn't be any threading protection needed,
+// since the loader will protect us.
+//
+//----------------------------------------------------------------------------
+STDAPI CoUnloadingWOW(BOOL fProcessDetach)
+{
+ //
+ // First, cleanup this thread
+ //
+ DoThreadSpecificCleanup();
+
+ //
+ // Now, set the global WOW thunk pointer to an invalid value. This
+ // will prevent it from being called in the future.
+ //
+ if (fProcessDetach)
+ {
+ g_pOleThunkWOW = (OleThunkWOW *) INVALID_HANDLE_VALUE;
+ }
+
+ return(NOERROR);
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoInitialize
+//
+// Synopsis: COM Initializer
+//
+// Arguments: [pvReserved]
+//
+// Returns: HRESULT
+//
+// History: 09-Nov-94 Ricksa Added this function comment & modified
+// to get rid of single threaded init flag.
+//
+//--------------------------------------------------------------------------
+STDAPI CoInitialize(LPVOID pvReserved)
+{
+ HRESULT hr;
+
+ OLETRACEIN((API_CoInitialize, PARAMFMT("pvReserved= %p"), pvReserved));
+
+ hr = CoInitializeEx( pvReserved, COINIT_APARTMENTTHREADED);
+
+ OLETRACEOUT((API_CoInitialize, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoInitializeEx
+//
+// Synopsis: COM Initializer
+//
+// Arguments: [pMalloc]
+// [flags]
+//
+// Returns: HRESULT
+//
+// History: 06-Apr-94 AlexT Added this function comment,
+// Cleaned up pMalloc usage
+// 25-May-94 AlexT Make success return code more closely
+// match 16-bit OLE
+// 28-Aug-94 AndyH pMalloc must be NULL except for Excel
+//
+// Notes: If we're going to return successfully, we return one of the
+// following two values:
+//
+// S_OK if caller passed in a NULL pMalloc and we accepted it
+// S_OK if caller passed in NULL pMalloc and this was the first
+// successful call on this thread
+// S_FALSE if caller passed in NULL pMalloc and this was not the
+// first successful call on this thread
+//
+// This is slightly different from 16-bit OLE, because 16-bit OLE
+// didn't allow task allocations before CoInitialize was called
+// (we do), and 16-bit OLE allowed the app to change the allocator.
+//
+// For chicago: SSAPI(x) expands to SSx; the x api is in
+// stkswtch.cxx which switches to the 16 bit stack first and
+// calls then SSx.
+//
+//--------------------------------------------------------------------------
+STDAPI SSAPI(CoInitializeEx)(LPVOID pMalloc, ULONG flags)
+{
+ ComDebOut((DEB_TRACE, "CoInitializeEx pMalloc:%x flags:%x\n", pMalloc, flags));
+
+ if ((flags & (COINIT_DISABLE_OLE1DDE|COINIT_APARTMENTTHREADED|
+ COINIT_SPEED_OVER_MEMORY))
+ != flags)
+ {
+ ComDebOut((DEB_ERROR, "CoInitializeEx(%x,%x) illegal flag", pMalloc, flags));
+ return E_INVALIDARG;
+ }
+
+ if (NULL != pMalloc)
+ {
+ // Allocator NOT replaceable! When called from 16-bits, the Thunk
+ // layer always pases a NULL pMalloc.
+
+#ifndef _CHICAGO_
+ // EXCEL50 for NT supplies an allocator. We dont use it, but we
+ // dont return error either, or we would break them.
+
+ if (!IsTaskName(L"EXCEL.EXE"))
+#endif
+ {
+ ComDebOut((DEB_ERROR, "CoInitializeEx(%x,%x) illegal pMalloc", pMalloc, flags));
+ return E_INVALIDARG;
+ }
+ }
+
+
+ // Get (or allocate) the per-thread data structure
+ HRESULT hr;
+ COleTls Tls(hr);
+
+ if (FAILED(hr))
+ {
+ ComDebOut((DEB_ERROR, "CoInitializeEx Tls OutOfMemory"));
+ return CO_E_INIT_TLS;
+ }
+
+
+ if (( (flags & COINIT_APARTMENTTHREADED) && (Tls->dwFlags & OLETLS_MULTITHREADED)) ||
+ (!(flags & COINIT_APARTMENTTHREADED) && (Tls->dwFlags & OLETLS_APARTMENTTHREADED)))
+ {
+ // tried to change the threading mode.
+ ComDebOut((DEB_ERROR,"CoInitializeEx Attempt to change threadmodel\n"));
+ return RPC_E_CHANGED_MODE;
+ }
+
+#ifdef DCOM
+ // This flag can be set at any time. It cannot be disabled.
+ if (flags & COINIT_SPEED_OVER_MEMORY)
+ {
+ gSpeedOverMem = TRUE;
+ }
+#endif
+
+ // increment the per-thread init count
+ if (1 == ++(Tls->cComInits))
+ {
+ // first time for thread, might also be first time for process
+ // so go check that now.
+
+ // Single thread CoInitialize/CoUninitialize to guarantee
+ // that no race conditions occur where two threads are
+ // simultaneously initializing and uninitializing the library.
+
+ COleStaticLock lck(g_mxsSingleThreadOle);
+ hr = wCoInitializeEx(Tls, flags);
+ return hr;
+ }
+
+ // this is the 2nd or greater successful call on this thread
+ ComDebOut((DEB_TRACE, "CoInitializeEx returned S_FALSE\n"));
+ return S_FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoInitializeEx
+//
+// Synopsis: worker routine for CoInitialize, and special entry point
+// for DLLHost threads when Initializing.
+//
+// Arguments: [tls] - tls ptr for this thread
+// [flags] - initialization flags
+//
+// History: 10-Apr-96 Rickhi Created
+//
+// Notes: When called by the DLLHost threads that are initializing,
+// the g_mxsSingleThreadOle mutex is being held by the requesting
+// thread, so it is still safe to muck with global state.
+//
+//+-------------------------------------------------------------------------
+INTERNAL wCoInitializeEx(COleTls &Tls, ULONG flags)
+{
+ HRESULT hr = S_OK;
+
+ if (1 == ++g_cProcessInits)
+ {
+ // first time for process, do per-process initialization
+ hr = ProcessInitialize();
+ if (FAILED(hr))
+ {
+ // ProcessInitialize failed, we must call ProcessUninitialize
+ // to cleanup *before* we release the lock.
+ goto ErrorReturn;
+ }
+ }
+
+ if (flags & COINIT_APARTMENTTHREADED)
+ {
+ // apartment threaded, count 1 more STA init, mark the thread
+ // as being apartment threaded, and conditionally disable
+ // OLE1.
+
+ Tls->dwFlags |= OLETLS_APARTMENTTHREADED;
+ if (flags & COINIT_DISABLE_OLE1DDE)
+ {
+ Tls->dwFlags |= OLETLS_DISABLE_OLE1DDE;
+ }
+
+ if (1 == ++g_cSTAInits && gdwMainThreadId == 0)
+ {
+ // do main-thread apartment initialization. It is possible
+ // to have the first thread in here not be the main thread
+ // if the DLLHost code just spun a thread to be the main
+ // one.
+ STAProcessInitialize();
+ }
+ }
+ else
+ {
+ // multi threaded, count 1 more MTA init, mark the thread
+ // as being multi-threaded, and always disable OLE1
+
+ Tls->dwFlags |= (OLETLS_MULTITHREADED | OLETLS_DISABLE_OLE1DDE);
+ ++g_cMTAInits;
+ }
+
+#ifdef _CHICAGO_
+ hr = ChannelThreadInitialize();
+ if (FAILED(hr))
+ {
+ ChannelThreadUninitialize();
+ if (flags & COINIT_APARTMENTTHREADED)
+ {
+ if (--g_cSTAInits == 0)
+ STAProcessUninitialize();
+ }
+ else
+ {
+ --g_cMTAInits;
+ }
+
+ goto ErrorReturn;
+ }
+#endif // _CHICAGO_
+
+ // this is the first successful call on this thread. make
+ // sure to return S_OK and not some other random sucess code.
+ ComDebOut((DEB_TRACE, "CoInitializeEx returned S_OK\n"));
+ return S_OK;
+
+
+ErrorReturn:
+ // An error occurred. Fixup our tls init counter and
+ // undo the TLS state change
+
+ // cleanup our counter if the intialization failed so
+ // that other threads waiting on the lock wont assume
+ // that ProcessInitialize has been done.
+
+ if (--g_cProcessInits == 0)
+ {
+ ProcessUninitialize();
+ }
+
+ Tls->cComInits--;
+ Tls->dwFlags = OLETLS_LOCALTID; // clear all the flags
+
+ ComDebOut((DEB_ERROR,"CoInitializeEx Failed %x\n", hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: SSAPI(CoUnInitialize)
+//
+// Synopsis: COM UnInitializer, normally called from OleUninitialize
+// when the app is going away.
+//
+// Effects: Cleans up per apartment state, and if this is the last
+// apartment, cleans up global state.
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: 24-Jun-94 Rickhi Added this function comment,
+// Cleaned up pMalloc usage
+// 29-Jun-94 AlexT Rework so that we don't own the mutex
+// while we might yield.
+//
+// Notes: It is critical that we not own any mutexes when we might
+// make a call that would allow a different WOW thread to run
+// (which could otherwise lead to deadlock). Examples of such
+// calls are Object RPC, SendMessage, and Yield.
+//
+//--------------------------------------------------------------------------
+STDAPI_(void) SSAPI(CoUninitialize)(void)
+{
+ OLETRACEIN((API_CoUninitialize, NOPARAM));
+ TRACECALL(TRACE_INITIALIZE, "CoUninitialize");
+
+ // Get the thread init count.
+ COleTls Tls(TRUE);
+ if (!Tls.IsNULL() && Tls->cComInits > 0)
+ {
+ if ((1 == Tls->cComInits))
+ {
+ // last time for thread, do per-thread cleanup
+ wCoUninitialize(Tls, FALSE);
+ }
+ else
+ {
+ // Decrement thread count. This must be done after the above cleanup
+ // so that IsApartmentIntialized returns TRUE during the cleanup.
+ Tls->cComInits--;
+ }
+ }
+ else
+ {
+ ComDebOut((DEB_ERROR,
+ "(0 == thread inits) Unbalanced call to CoUninitialize\n"));
+ }
+
+ OLETRACEOUTEX((API_CoUninitialize, NORETURN));
+ return;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCoUnInitialize
+//
+// Synopsis: worker routine for CoUninitialize, and special entry point
+// for DLLHost threads when cleaning up.
+//
+// Effects: Cleans up apartment state.
+//
+// History: 10-Apr-96 Rickhi Created
+//
+// Notes: When called with fHostThread == TRUE, the g_mxsSingleThreadOle
+// critical section is already held by the main thread that is
+// uninitializing, currently waiting in DllHostProcessUninitialize
+// for the host threads to exit. The host threads use this
+// uninitializer to avoid taking the CS and deadlocking with the
+// main thread.
+//
+//--------------------------------------------------------------------------
+INTERNAL_(void) wCoUninitialize(COleTls &Tls, BOOL fHostThread)
+{
+ ComDebOut((DEB_COMPOBJ, "CoUninitialize Thread\n"));
+
+ if (Tls->dwFlags & OLETLS_THREADUNINITIALIZING)
+ {
+ // somebody called CoUninitialize while inside CoUninitialize. Since
+ // we dont subtract the thread init count until after init is done.
+ // we can end up here. Just warn the user about the problem and
+ // return without doing any more work.
+ ComDebOut((DEB_WARN, "Unbalanced Nested call to CoUninitialize\n"));
+ return;
+ }
+
+ // mark the thread as uninitializing
+ Tls->dwFlags |= OLETLS_THREADUNINITIALIZING;
+
+ if (Tls->dwFlags & OLETLS_APARTMENTTHREADED)
+ {
+ // do per-apartment cleanup
+ if (!ApartmentUninitialize())
+ {
+ // uninit was aborted while waiting for pending calls
+ // to complete.
+ Tls->dwFlags &= ~OLETLS_THREADUNINITIALIZING;
+ ComDebOut((DEB_WARN, "CoUninitialize Aborted\n"));
+ return;
+ }
+ }
+
+ if (!fHostThread)
+ {
+ // Single thread CoInitialize/CoUninitialize to guarantee
+ // that no race conditions occur where two threads are
+ // simultaneously initializing and uninitializing the library.
+ g_mxsSingleThreadOle.Request();
+
+#ifdef DCOM
+ if (g_cProcessInits-1 == gcHostProcessInits)
+ {
+ // clean up the dll host threads now, before continuing
+ DllHostProcessUninitialize();
+ }
+#endif
+ }
+
+ if (Tls->dwFlags & OLETLS_APARTMENTTHREADED)
+ {
+ // STA thread, count 1 less STA init
+ if (1 == g_cSTAInits)
+ {
+ // last STA, do last-apartment thread uninitialization
+ STAProcessUninitialize();
+ }
+ g_cSTAInits--;
+ }
+ else
+ {
+ // MTA thread, count 1 less MTA init
+ if (1 == g_cMTAInits)
+ {
+ // last thread in the MTA, uninitialize the apartment
+ // (except some low-level remoting stuff). Ignore aborts
+ // since the exit path is clean from here on (for MTA only)
+ ApartmentUninitialize();
+
+ if (g_cProcessInits-1 == gcHostProcessInits && !fHostThread)
+ {
+ // while we released the lock in ApartmentUninitialize,
+ // some other thread processing a call could have activated
+ // a host apartment, we'll go clean those up now if those
+ // are the only threads with init's left.
+ DllHostProcessUninitialize();
+ }
+ }
+ // Decrement MTA count. This must be done after the above cleanup
+ // so that IsApartmentIntialized returns TRUE during the cleanup.
+ g_cMTAInits--;
+ }
+
+ if (!fHostThread)
+ {
+ if (1 == g_cProcessInits)
+ {
+ // last time for process, do per-process cleanup
+ CairoleDebugOut((DEB_COMPOBJ, "CoUninitialize Process\n"));
+ Win4Assert(Tls->cComInits == 1);
+ ProcessUninitialize();
+ }
+ }
+
+ // Decrement process count. This must be done after the above cleanup
+ // so that IsApartmentIntialized returns TRUE during the cleanup.
+ g_cProcessInits--;
+
+ if (!fHostThread)
+ {
+ g_mxsSingleThreadOle.Release();
+ }
+
+ //Release the per-thread error object.
+ CoSetErrorInfo(0, NULL);
+
+ // Release the per-thread "state" object (regardless of whether we
+ // are Apartment or Free threaded. This must be done now since the
+ // OLE Automation Dll tries to free this in DLL detach, which may
+ // try to call back into the OLE32 dll which may already be detached!
+
+ CoSetState(NULL);
+#ifdef WX86OLE
+ // make sure wx86 state is also freed
+ if (gcwx86.SetIsWx86Calling(TRUE))
+ {
+ CoSetState(NULL);
+ }
+#endif
+
+ // mark the thread as finished uninitializing and turn off all flags
+ // and reset the count of initializations.
+ Tls->dwFlags = OLETLS_LOCALTID;
+ Tls->cComInits = 0;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsApartmentInitialized
+//
+// Synopsis: Check if the current apartment is initialized
+//
+// Returns: TRUE - apartment initialized, TLS data guaranteed to exist
+// for this thread.
+// FALSE - apartment not initialized
+//
+// History: 09-Aug-94 Rickhi commented
+//
+//--------------------------------------------------------------------------
+BOOL IsApartmentInitialized()
+{
+ HRESULT hr;
+ COleTls Tls(hr);
+
+ // initialized if any MTA apartment exists, or if the current thread has
+ // been initialized.
+
+ return (SUCCEEDED(hr) && (g_cMTAInits > 0 || Tls->cComInits != 0))
+ ? TRUE : FALSE;
+}
+//+---------------------------------------------------------------------
+//
+// Function: CoGetCurrentProcess
+//
+// Synopsis: Returns a unique value for the current thread. This routine is
+// necessary because hTask values from Windows get reused
+// periodically.
+//
+// Arguments: -
+//
+// Returns: DWORD
+//
+// History: 28-Jul-94 BruceMa Created.
+//
+// Notes:
+//
+//----------------------------------------------------------------------
+STDAPI_(DWORD) CoGetCurrentProcess(void)
+{
+ HRESULT hr;
+
+ OLETRACEIN((API_CoGetCurrentProcess, NOPARAM));
+
+#ifdef _CHICAGO_
+ // CODEWORK: The following is here because Publisher uses storage
+ // but inadvertantly (!) forgot to call CoInitialize
+ if (g_cProcessInits == 0)
+ {
+ hr = CheckAndStartSCM();
+
+ if ( FAILED(hr) )
+ {
+ CairoleDebugOut((DEB_ERROR, "Failed to start SCM, hr = %x", hr));
+ OLETRACEOUTEX((API_CoGetCurrentProcess, RETURNFMT("%ud"), 0));
+ return 0;
+ }
+ }
+#endif
+
+ COleTls Tls(hr);
+
+ if ( FAILED(hr) )
+ {
+ OLETRACEOUTEX((API_CoGetCurrentProcess, RETURNFMT("%ud"), 0));
+ return 0;
+ }
+
+ // Get our OLE-specific thread id
+ if ( Tls->dwApartmentID == 0 )
+ {
+#ifdef _CHICAGO_
+ // On Chicago, we merely increment the globally available
+ // process ID to the next value.
+ Win4Assert(g_post != NULL);
+ Win4Assert(g_hSharedStateMutex != NULL);
+
+ WaitForSingleObject(g_hSharedStateMutex, INFINITE);
+ Tls->dwApartmentID = ++g_post->dwNextProcessID;
+ ReleaseMutex(g_hSharedStateMutex);
+#else
+ // This sets our dwApartmentID.
+ ScmGetThreadId( &Tls->dwApartmentID );
+#endif
+ }
+
+ Win4Assert(Tls->dwApartmentID);
+ OLETRACEOUTEX((API_CoGetCurrentProcess, RETURNFMT("%ud"), Tls->dwApartmentID));
+
+ return Tls->dwApartmentID;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoBuildVersion
+//
+// Synopsis: Return build version DWORD
+//
+// Returns: DWORD hiword = 23
+// DWORD loword = build number
+//
+// History: 16-Feb-94 AlexT Use verole.h rmm for loword
+//
+// Notes: The high word must always be constant for a given platform.
+// For Win16 it must be exactly 23 (because that's what 16-bit
+// OLE 2.01 shipped with). We can choose a different high word
+// for other platforms. The low word must be greater than 639
+// (also because that's what 16-bit OLE 2.01 shipped with).
+//
+//--------------------------------------------------------------------------
+STDAPI_(DWORD) CoBuildVersion( VOID )
+{
+ WORD wLowWord;
+ WORD wHighWord;
+
+ OLETRACEIN((API_CoBuildVersion, NOPARAM));
+
+ wHighWord = 23;
+ wLowWord = rmm; // from ih\verole.h
+
+ Win4Assert(wHighWord == 23 && "CoBuildVersion high word magic number");
+ Win4Assert(wLowWord > 639 && "CoBuildVersion low word not large enough");
+
+ DWORD dwVersion;
+
+ dwVersion = MAKELONG(wLowWord, wHighWord);
+
+ OLETRACEOUTEX((API_CoBuildVersion, RETURNFMT("%x"), dwVersion));
+
+ return dwVersion;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoSetState
+// CoGetState
+//
+// Synopsis: These are private APIs, exported for use by the
+// OLE Automation DLLs, which allow them to get and
+// set a single per thread "state" object that is
+// released at CoUninitialize time.
+//
+// Arguments: [punk/ppunk] the object to set/get
+//
+// History: 15-Jun-94 Bradlo Created
+//
+//--------------------------------------------------------------------------
+STDAPI CoSetState(IUnknown *punkStateNew)
+{
+ OLETRACEIN((API_CoSetState, PARAMFMT("punk= %p"), punkStateNew));
+
+ HRESULT hr;
+ COleTls Tls(hr);
+#ifdef WX86OLE
+ // Make sure we get the flag on our stack before any callouts
+ BOOL fWx86Thread = gcwx86.IsWx86Calling();
+#endif
+
+ if (SUCCEEDED(hr))
+ {
+ IUnknown *punkStateOld;
+
+ // Note that either the AddRef or the Release below could (in
+ // theory) cause a reentrant call to us. By keeping
+ // punkStateOld in a stack variable, we handle this case.
+
+ if (NULL != punkStateNew)
+ {
+ // We're going to replace the existing state with punkStateNew;
+ // take a reference right away
+
+ // Note thate even if this AddRef reenters TLSSetState we're
+ // okay because we haven't touched pData->punkState yet.
+ punkStateNew->AddRef();
+ }
+
+#ifdef WX86OLE
+ // If this was called from x86 code via wx86 thunk layer then use
+ // alternate location in TLS.
+ if (fWx86Thread)
+ {
+ punkStateOld = Tls->punkStateWx86;
+ Tls->punkStateWx86 = punkStateNew;
+ } else {
+ punkStateOld = Tls->punkState;
+ Tls->punkState = punkStateNew;
+ }
+#else
+ punkStateOld = Tls->punkState;
+ Tls->punkState = punkStateNew;
+#endif
+
+ if (NULL != punkStateOld)
+ {
+ // Once again, even if this Release reenters TLSSetState we're
+ // okay because we're not going to touch pData->punkState again
+ punkStateOld->Release();
+ }
+
+ OLETRACEOUT((API_CoSetState, S_OK));
+ return S_OK;
+ }
+
+ OLETRACEOUT((API_CoSetState, S_FALSE));
+ return S_FALSE;
+}
+
+STDAPI CoGetState(IUnknown **ppunk)
+{
+ OLETRACEIN((API_CoGetState, PARAMFMT("ppunk= %p"), ppunk));
+
+ HRESULT hr;
+ COleTls Tls(hr);
+#ifdef WX86OLE
+ // Make sure we get the flag on our stack before any callouts
+ BOOL fWx86Thread = gcwx86.IsWx86Calling();
+#endif
+ IUnknown *punk;
+
+ if (SUCCEEDED(hr))
+ {
+#ifdef WX86OLE
+ // If this was called from x86 code via wx86 thunk layer then use
+ // alternate location in TLS.
+ punk = fWx86Thread ? Tls->punkStateWx86 :
+ Tls->punkState;
+#else
+ punk = Tls->punkState;
+#endif
+ if (punk)
+ {
+ punk->AddRef();
+ *ppunk = punk;
+
+ OLETRACEOUT((API_CoGetState, S_OK));
+ return S_OK;
+ }
+ }
+
+ *ppunk = NULL;
+
+ OLETRACEOUT((API_CoGetState, S_FALSE));
+ return S_FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoQueryReleaseObject, private
+//
+// Synopsis: Determine if this object is one that should be released during
+// shutdown.
+//
+// Effects: Turns out that some WOW applications don't cleanup properly.
+// Specifically, sometimes they don't release objects that they
+// really should have. Among the problems caused by this are that
+// some objects don't get properly cleaned up. Storages, for
+// example, don't get closed. This leaves the files open.
+// Monikers are being released, which eat memory.
+//
+// This function is called by the thunk manager to determine
+// if an object pointer is one that is known to be leaked, and
+// if the object should be released anyway. There are several
+// classes of object that are safe to release, and some that
+// really must be released.
+//
+// Arguments: [punk] -- Unknown pointer to check
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 8-15-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD adwQueryInterfaceTable[QI_TABLE_END] = { 0 , 0 };
+STDAPI CoQueryReleaseObject(IUnknown *punk)
+{
+ OLETRACEIN((API_CoQueryReleaseObject, PARAMFMT("punk= %p"), punk));
+ CairoleDebugOut((DEB_ITRACE,
+ "CoQueryReleaseObject(%x)\n",
+ punk));
+ //
+ // A punk is a pointer to a pointer to a vtbl. We are going to check the
+ // vtbl to see if we can release it.
+ //
+
+ DWORD pQueryInterface;
+ HRESULT hr;
+
+ if (IsBadReadPtr(punk,sizeof(DWORD)))
+ {
+ hr = S_FALSE;
+ goto ErrorReturn;
+ }
+
+ if (IsBadReadPtr(*(DWORD**)punk,sizeof(DWORD)))
+ {
+ hr = S_FALSE;
+ goto ErrorReturn;
+ }
+
+ // Pick up the QI function pointer
+ pQueryInterface = **(DWORD **)(punk);
+
+ CairoleDebugOut((DEB_ITRACE,
+ "CoQueryReleaseObject pQueryInterface = %x\n",
+ pQueryInterface));
+
+ //
+ // adwQueryInterfaceTable is an array of known QueryInterface pointers.
+ // Either the value in the table is zero, or it is the address of the
+ // classes QueryInterface method. As each object of interest is created,
+ // it will fill in its reserved entry in the array. Check olepfn.hxx for
+ // details
+ //
+
+ if( pQueryInterface != 0)
+ {
+ for (int i = 0 ; i < QI_TABLE_END ; i++)
+ {
+ if (adwQueryInterfaceTable[i] == pQueryInterface)
+ {
+ CairoleDebugOut((DEB_ITRACE,
+ "CoQueryReleaseObject punk matched %x\n",i));
+ hr = NOERROR;
+ goto ErrorReturn;
+ }
+ }
+ }
+ CairoleDebugOut((DEB_ITRACE,
+ "CoQueryReleaseObject No match on punk\n"));
+ hr = S_FALSE;
+
+ErrorReturn:
+ OLETRACEOUT((API_CoQueryReleaseObject, hr));
+
+ return hr;
+}
+
+#if defined(_CHICAGO_)
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoCreateAlmostGuid
+//
+// Synopsis: Creates a GUID for internal use that is going to be unique
+// as long as something has OLE32 loaded. We don't need a true
+// GUID for the uses of this routine, since the values are only
+// used on this local machine, and are used in data structures
+// that are not persistent.
+// Effects:
+//
+// Arguments: [pGuid] -- The output goes here.
+//
+// History: 5-08-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoCreateAlmostGuid(GUID *pGuid)
+{
+ DWORD *pGuidPtr = (DWORD *)pGuid;
+
+ //
+ // Note: As long as we increment the value, we don't
+ // care what it is. This, in combination with the PID,TID, and TickCount
+ // make this GUID unique enough for what we need. We would need to allocate
+ // 4 gig of UUID's to run the NextGuidIndex over.
+ //
+
+ InterlockedIncrement(&gs_lNextGuidIndex);
+
+ pGuidPtr[0] = gs_lNextGuidIndex;
+ pGuidPtr[1] = GetTickCount();
+ pGuidPtr[2] = GetCurrentThreadId();
+ pGuidPtr[3] = GetCurrentProcessId();
+ return(S_OK);
+}
+#endif
diff --git a/private/ole32/com/class/cspytbl.cxx b/private/ole32/com/class/cspytbl.cxx
new file mode 100644
index 000000000..bf9122303
--- /dev/null
+++ b/private/ole32/com/class/cspytbl.cxx
@@ -0,0 +1,350 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994 - 1995.
+//
+// File: cspytbl.cxx
+//
+// Contents: Used by CTaskMemory::* (memapi.cxx) to support IMallocSpy
+//
+// Synopsis: The requirements are to efficiently store, locate and remove
+// entries in a table that may have to be expanded. Therefore
+// the choice is a dynamically expandable hash table. It is
+// fast and removals do not require compaction. Expansion is
+// always to twice the current number of entries, so excessive
+// expansions will not be done.
+//
+// Classes: CSpyTable
+//
+// Functions:
+//
+// History: 27-Oct-94 BruceMa Created
+//
+//----------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include "cspytbl.hxx"
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSpyTable::CSpyTable, public
+//
+// Synopsis: Constructor
+//
+// Arguments: BOOl * - Indicates construction success
+//
+// Algorithm:
+//
+// History: 27-Oct-94 Brucema Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+CSpyTable::CSpyTable(BOOL *pfOk)
+{
+ // Allocate and initialize the hash table
+ m_cAllocations = 0;
+ m_cEntries = INITIALENTRIES;
+ m_table = (LPAENTRY) LocalAlloc(LMEM_FIXED, m_cEntries * sizeof(AENTRY));
+ if (m_table == NULL)
+ {
+ *pfOk = FALSE;
+ return;
+ }
+
+ // Initialize the table
+ // m_table[*].dwCollision = FALSE;
+ // m_table[*].allocation = NULL;
+ memset(m_table, 0, m_cEntries * sizeof(AENTRY));
+
+ // Return success
+ *pfOk = TRUE;
+
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSpyTable::~CSpyTable, public
+//
+// Synopsis: Destructor
+//
+// Arguments: -
+//
+// Algorithm:
+//
+// History: 27-Oct-94 Brucema Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+CSpyTable::~CSpyTable()
+{
+ // Delete the table
+ LocalFree(m_table);
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSpyTable::Add, public
+//
+// Synopsis: Add an entry to the hash table
+//
+// Arguments: void * - The allocation to add
+//
+// Algorithm:
+//
+// Returns: TRUE - Entry added
+// FALSE - Memory failure expanding table
+//
+// History: 27-Oct-94 Brucema Created
+//
+// Notes: (1) This can only fail on a memory allocation failure
+//
+// (2) The j == j0 test guarantees the table is full since
+// the algorithm is wrapping at a collision using a prime
+// number which is relatively prime to m_cEntries
+//
+//--------------------------------------------------------------------------
+BOOL CSpyTable::Add(void *allocation)
+{
+ ULONG j0, j;
+
+ // Don't add null entries
+ if (allocation == NULL)
+ {
+ return FALSE;
+ }
+
+ // Search for an available entry
+
+ // Do until success or the table is full
+ j = j0 = ((ULONG) allocation) % m_cEntries;
+ do
+ {
+ j = (j + PRIME) % m_cEntries;
+ if (m_table[j].pAllocation != NULL)
+ {
+ m_table[j].dwCollision = TRUE;
+ }
+ } until_(m_table[j].pAllocation == NULL || j == j0);
+
+ // Found an available entry
+ if (j != j0)
+ {
+ m_table[j].pAllocation = allocation;
+ m_cAllocations++;
+ return TRUE;
+ }
+
+ // The table is full
+ else
+ {
+ // Expand the hash table
+ if (!Expand())
+ {
+ return FALSE;
+ }
+
+ // Call ourself recusively to add
+ return Add(allocation);
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSpyTable::Remove, public
+//
+// Synopsis: Remove an entry from the table
+//
+// Arguments: void * - The allocation to remove
+//
+// Algorithm:
+//
+// Returns: TRUE - Entry removed
+// FALSE - Entry not found
+//
+// History: 27-Oct-94 Brucema Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+BOOL CSpyTable::Remove(void *allocation)
+{
+ ULONG j0, j;
+
+ // Search for the entry
+ if (Find(allocation, &j))
+ {
+ // Remove the entry
+ m_table[j].pAllocation = NULL;
+
+ // Remove collison markers from here backward until
+ // a non-empty entry (if next forward entry is not empty)
+ if (m_table[j].dwCollision)
+ {
+ j0 = (j + PRIME) % m_cEntries;
+ if (m_table[j].pAllocation == NULL && !m_table[j].dwCollision)
+ {
+ j0 = j;
+ do
+ {
+ m_table[j].dwCollision = FALSE;
+ j = (j - PRIME + m_cEntries) % m_cEntries;
+ } until_(m_table[j].pAllocation != NULL || j == j0);
+ }
+ }
+ m_cAllocations--;
+ return TRUE;
+ }
+
+ // Otherwise the entry was not found
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSpyTable::Find, public
+//
+// Synopsis: Find an entry in the table
+//
+// Arguments: void * - The allocation to find
+// ULONG * - Out parameter to store the index of
+// the found entry
+//
+// Algorithm:
+//
+// Returns: TRUE - Entry found
+// FALSE - Entry not found
+//
+// History: 27-Oct-94 Brucema Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+BOOL CSpyTable::Find(void *allocation, ULONG *pulIndex)
+{
+ ULONG j0, j;
+
+ // Don't search for null entries
+ if (allocation == NULL)
+ {
+ return FALSE;
+ }
+
+ // Search for the entry
+
+ // Do until success or end of the table is reached
+ j = j0 = ((ULONG) allocation) % m_cEntries;
+ do
+ {
+ j = (j + PRIME) % m_cEntries;
+ } until_(m_table[j].pAllocation == allocation ||
+ (m_table[j].pAllocation == NULL &&
+ m_table[j].dwCollision == FALSE) ||
+ j == j0);
+
+ // Return result
+ if (m_table[j].pAllocation == allocation)
+ {
+ *pulIndex = j;
+ return TRUE;
+ }
+
+ // Else not found
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSpyTable::Expand, private
+//
+// Synopsis: Expand the hash table
+//
+// Arguments: -
+//
+// Algorithm:
+//
+// Returns: TRUE - Expansion successful
+// FALSE - Memory allocation failure during expansion
+//
+// History: 27-Oct-94 Brucema Created
+//
+// Notes: To allow starting with a small table but not to do too many
+// expansions in a large application, we expand by twice the
+// current number of entries.
+//
+//--------------------------------------------------------------------------
+BOOL CSpyTable::Expand(void)
+{
+ LPAENTRY pOldTable;
+
+ // Save the current table
+ pOldTable = m_table;
+
+ // Allocate a new table
+ m_cEntries *= 2;
+ m_table = (LPAENTRY) LocalAlloc(LMEM_FIXED, m_cEntries * sizeof(AENTRY));
+ if (m_table == NULL)
+ {
+ m_table = pOldTable;
+ return FALSE;
+ }
+
+ // Initialize it
+ for (ULONG j = 0; j < m_cEntries; j++)
+ {
+ m_table[j].dwCollision = FALSE;
+ m_table[j].pAllocation = NULL;
+ }
+
+ // Restore the entries in the old table
+ m_cAllocations = 0;
+ for (j = 0; j < m_cEntries / 2; j++)
+ {
+ if (pOldTable[j].pAllocation != NULL)
+ {
+ Add(pOldTable[j].pAllocation);
+ }
+ }
+
+ // Clean up
+ LocalFree(pOldTable);
+
+ return TRUE;
+}
+
diff --git a/private/ole32/com/class/cspytbl.hxx b/private/ole32/com/class/cspytbl.hxx
new file mode 100644
index 000000000..e8e01da50
--- /dev/null
+++ b/private/ole32/com/class/cspytbl.hxx
@@ -0,0 +1,57 @@
+
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: cspytbl.hxx
+//
+// Contents: Definitions for cspytbl.cxx
+//
+// Classes: CSpyTable
+//
+// Functions:
+//
+// History: 27-Oct-94 BruceMa Created
+//
+//----------------------------------------------------------------------
+
+// A useful macro
+#define until_(x) while(!(x))
+
+// An entry in the hash table
+typedef struct
+{
+ ULONG dwCollision;
+ void *pAllocation;
+} AENTRY, *LPAENTRY;
+
+
+// The initial number of entries
+const ULONG INITIALENTRIES = 256;
+
+
+// The wrap constant when colliding
+const ULONG PRIME = 19; // This MUST! be relatively prime to
+ // m_cEntries
+
+
+// Managing class for the hash table
+class CSpyTable
+{
+public:
+ CSpyTable(BOOL *pfOk);
+ ~CSpyTable();
+ BOOL Add(void *allocation);
+ BOOL Remove(void *allocation);
+ BOOL Find(void *allocation, ULONG *pulIndex);
+ ULONG m_cAllocations;
+
+private:
+ BOOL Expand(void);
+ LPAENTRY m_table;
+ ULONG m_cEntries;
+};
+
+
+typedef CSpyTable *LPSPYTABLE;
diff --git a/private/ole32/com/class/daytona/compob32.src b/private/ole32/com/class/daytona/compob32.src
new file mode 100644
index 000000000..05240b341
--- /dev/null
+++ b/private/ole32/com/class/daytona/compob32.src
@@ -0,0 +1,626 @@
+#if 0
+
+ Microsoft Windows
+ Copyright (C) Microsoft Corporation, 1992 - 1992.
+ All rights reserved.
+
+ This .def file is preprocessed by the compiler to create the version for
+ the current build in the appropriate subdir. Basically, whatever you
+ would have used in your code to control what is compiled when can be
+ used in this file for the same purpose. The following defines are in
+ use at the time this file was written:
+
+ FLAT - Used to indicate a NT/DOS7 build
+ i386 - Intel i386/i486 build
+ MIPS - MIPS R3000/R4000 build
+ PPC - PowerPC build
+ ALPHA - DEC Alpha build
+ DBG - Used to control Debug/Retail. Set to 1 if Debug,
+ 0 if Retail.
+ WIN31 - Win16 build
+ __OS2__ - OS/2 build (used by CT mostly)
+
+ If none of these are used, it is assumed the entire file can be used
+ for all builds.
+
+#endif
+
+#ifdef FLAT
+
+LIBRARY compob32
+
+DESCRIPTION 'Microsoft (R) Component Object Model DLL 1.00'
+
+EXPORTS
+
+#if defined(i386)
+
+ _CoBuildVersion@0 @1
+ _CoInitialize@4 @2
+ _CoUninitialize@0 @3
+ _CoGetMalloc@8 @4
+
+ _CoMarshalInterface@24 @5
+ _CoUnmarshalInterface@12 @6
+ _CoReleaseMarshalData@4 @7
+ _CoGetStandardMarshal@24 @8
+ _CoGetMarshalSizeMax@24 @23
+ _CoMarshalHresult@8 @9
+ _CoUnmarshalHresult@8 @10
+
+ _CoRegisterClassObject@20 @11
+ _CoRevokeClassObject@4 @12
+ _CoGetClassObject@20 @13
+ _CoCreateInstance@20 @14
+
+; unused @15
+ _CoDisconnectObject@8 @16
+ _CoLockObjectExternal@12 @17
+
+ _CoLoadLibrary@8 @18
+ _CoFreeLibrary@4 @19
+ _CoFreeAllLibraries@0 @20
+ _CoFreeUnusedLibraries@0 @21
+
+ _CoRegisterMessageFilter@8 @22
+; CoBlock@0 //23 used by CoGetMarshalSizeMax
+; CoUnblock@4 @24
+ _CoFileTimeToDosDateTime@12 @25
+ _CoDosDateTimeToFileTime@12 @26
+
+ _CoInitializeCriticalSection@4 @27
+ _CoEnterCriticalSection@4 @28
+ _CoLeaveCriticalSection@4 @29
+ _CoDeleteCriticalSection@4 @30
+
+ _GetRunningObjectTable@8 @31
+
+ ; unused @32
+ _CoOpenClassKey@8 @33
+ _CoIsOle1Class@4 @34
+ _CoTreatAsClass@8 @35
+ _CoGetTreatAsClass@8 @36
+ _CoGetCurrentProcess@0 @37
+
+ _IsEqualGUID@8 @38
+ _StringFromCLSID@8 @39
+ _CLSIDFromString@8 @40
+ _ProgIDFromCLSID@8 @41
+ _CLSIDFromProgID@8 @42
+ _StringFromGUID2@12 @43
+
+ _IsValidPtrIn@8 @44
+ _IsValidPtrOut@8 @45
+ _IsValidInterface@4 @46
+ _IsValidIid@4 @47
+
+;; ResultFromScode@4 @48
+;; GetScode@4 @49
+
+
+ ;; Temporary entry points used for shared memory allocation.
+
+ _SharedMemAlloc@8 @50
+ _SharedMemReAlloc@12 @51
+ _SharedMemFree@8 @52
+ _CoMemctxOf@4 @53
+ ; Removed as this is really obsolete
+ ; CoMemAlloc@12 @54
+ ; CoMemFree@8 @55
+ _CoGetPersistentInstance@24 @56
+ _CoNewPersistentInstance@32 @57
+
+
+ ;; OLE2.01 functionality
+
+ _CoIsHandlerConnected@4 @58
+ ;;CoHasStrongExternalConnections@4 @59
+ _CoFileTimeNow@4 @60
+
+ ;; 61-69 unused, reserved for additional 2.01 stuff
+
+ ;; Moniker Functions
+
+ _BindMoniker@16 @70
+ _MkParseDisplayName@16 @71
+ _CreateBindCtx@8 @72
+ _CreateItemMoniker@12 @73
+ _CreateFileMoniker@8 @74
+ _CreateGenericComposite@12 @75
+ _CreateAntiMoniker@4 @76
+ _CreatePointerMoniker@8 @77
+ _MonikerRelativePathTo@16 @78
+#ifdef _CAIRO_
+ _CreateFileMonikerEx@12 @79
+#else
+; unused @79
+#endif
+ _GetClassFile@8 @80
+ _OleSaveToStream@8 @81
+ _OleLoadFromStream@12 @82
+ _MonikerCommonPrefixWith@12 @83
+
+ ;; internal calls below this point
+
+ ;; The following two entries are probably temporary as
+ ;; they are helpers for drag and drop
+ _AssignEndpointProperty@4
+ _UnAssignEndpointProperty@4
+ _GetInterfaceFromWindowProp@16
+
+ ;; this maybe should be removed
+ _FnAssert@16
+
+; StringFromCLSID2@12
+ _CoGetClassExt@8
+ _Ole1ClassFromCLSID2@12
+; CMemBytesUnMarshal@0
+; CMemStmUnMarshal@0
+ _GetOleMutex@0
+ _ReleaseOleMutex@0
+ _StringFromIID@8
+ _IIDFromString@8
+; _SzFixNet@20
+ _Concatenate@12
+
+ ;; are these still needed?
+ ;;
+ ;;CloneSharedMemStm@4
+ ;;CreateSharedMemStm@8
+ ;;FreeSharedMemStmHandle@4
+ ;;CreateMemLockbytes@8
+ ;;?Create@CMemBytes@@SGPAV1@PAX@Z
+
+ ;; BUGBUG: Temporary name of memory allocators till real
+ ;; memory philosophy defined.
+ ?CoMemAlloc@@YGPAXKKPAX@Z
+ ?CoMemFree@@YGXPAXK@Z
+
+ ?PubMemAlloc@@YGPAXK@Z
+ ?PubMemFree@@YGXPAX@Z
+
+#ifndef _CAIRO_
+ ??2CPrivAlloc@@SGPAXI@Z
+ ??3CPrivAlloc@@SGXPAX@Z
+
+#endif
+
+ ; Export ability to create remote handler
+ _RemCreateRemoteHandler@16
+ _CoInitializeEx@8
+ _DllDebugObjectRPCHook=_DllDebugObjectRPCHook@8
+
+#if DBG==1
+ _Dbg_FindRemoteHdlr
+#endif
+
+#ifdef LRPC
+ ;; BUGBUG: The following are old exports from 16 bit having to do
+ ;; with the LRPC part of the system. We are just keeping
+ ;; them here for reference.
+ _RemCreateRemoteHandler@40
+ _RemAllocOID@4
+ _RemFreeOID@4
+ _RemConnectToObject@8
+ _RemSetHandler@8
+ _RemClearHandler@4
+ _RemLookupHandler@8
+ _RemUninitHandlers@0
+ _RemRevokeServer@4
+ _RemLookupOrCreateServer@16
+ _RemLookupServerUnk@12
+ _RemLookupServerOID@12
+ _RemLookupSHUnk@12
+ _RemUninitServers@0
+ _RemCreateRHClassObject@24
+ _RemEnsureLocalClassObject@8
+ _RemEnsureUniqueHandler@12
+ _RemGetInfoForCid@24
+ _RemCreateStubManager@16
+
+
+ _LrpcCall@12
+ _LrpcDispatch@12
+ _LrpcRegisterMonitor@4
+ _LrpcRevokeMonitor@4
+ _LrpcGetConnClient@4
+ _LrpcGetConnObject@4
+ _LrpcGetObjServer@4
+ _LrpcGetMessage@20
+ _LrpcTimeout@4
+ _LrpcGetThreadWindow@0
+#endif // LRPC
+
+#elif defined(_MIPS_)
+
+ CoBuildVersion @1
+ CoInitialize @2
+ CoUninitialize @3
+ CoGetMalloc @4
+
+ CoMarshalInterface @5
+ CoUnmarshalInterface @6
+ CoReleaseMarshalData @7
+ CoGetStandardMarshal @8
+ CoGetMarshalSizeMax @23
+ CoMarshalHresult @9
+ CoUnmarshalHresult @10
+
+ CoRegisterClassObject @11
+ CoRevokeClassObject @12
+ CoGetClassObject @13
+ CoCreateInstance @14
+
+; unused @15
+ CoDisconnectObject @16
+ CoLockObjectExternal @17
+
+ CoLoadLibrary @18
+ CoFreeLibrary @19
+ CoFreeAllLibraries @20
+ CoFreeUnusedLibraries @21
+ CoRegisterMessageFilter @22
+; CoBlock @23
+; CoUnblock @24
+ CoFileTimeToDosDateTime @25
+ CoDosDateTimeToFileTime @26
+
+ CoInitializeCriticalSection @27
+ CoEnterCriticalSection @28
+ CoLeaveCriticalSection @29
+ CoDeleteCriticalSection @30
+
+ GetRunningObjectTable @31
+
+ ; unused @32
+ CoOpenClassKey @33
+ CoIsOle1Class @34
+ CoTreatAsClass @35
+ CoGetTreatAsClass @36
+ CoGetCurrentProcess @37
+
+ IsEqualGUID @38
+ StringFromCLSID @39
+ CLSIDFromString @40
+ ProgIDFromCLSID @41
+ CLSIDFromProgID @42
+ StringFromGUID2 @43
+
+ IsValidPtrIn @44
+ IsValidPtrOut @45
+ IsValidInterface @46
+ IsValidIid @47
+
+;; ResultFromScode @48
+;; GetScode @49
+
+
+ ;; Temporary entry points used for shared memory allocation.
+
+ SharedMemAlloc @50
+ SharedMemReAlloc @51
+ SharedMemFree @52
+ CoMemctxOf @53
+; Moved to mangled names because these are not documented
+; CoMemAlloc @54
+; CoMemFree @55
+ CoGetPersistentInstance @56
+ CoNewPersistentInstance @57
+
+ ;; OLE2.01 functionality
+
+ CoIsHandlerConnected @58
+ ;;CoHasStrongExternalConnections @59
+ CoFileTimeNow @60
+
+ ;; 61-69 reserved for additional 2.01 functionality
+
+ ;; Moniker Functions
+
+ BindMoniker @70
+ MkParseDisplayName @71
+ CreateBindCtx @72
+ CreateItemMoniker @73
+ CreateFileMoniker @74
+ CreateGenericComposite @75
+ CreateAntiMoniker @76
+ CreatePointerMoniker @77
+ MonikerRelativePathTo @78
+#ifdef _CAIRO_
+ ; CreateFileMonikerEx @79
+#else
+; unused @79
+#endif
+ GetClassFile @80
+ OleSaveToStream @81
+ OleLoadFromStream @82
+ MonikerCommonPrefixWith @83
+
+ ;; internal calls below this point
+
+ ;; The following two entries are probably temporary as
+ ;; they are helpers for drag and drop
+ AssignEndpointProperty
+ UnAssignEndpointProperty
+ GetInterfaceFromWindowProp
+
+ ;; this maybe should be removed
+ FnAssert
+
+; StringFromCLSID2
+ CoGetClassExt
+ Ole1ClassFromCLSID2
+; CMemBytesUnMarshal
+; CMemStmUnMarshal
+ GetOleMutex
+ ReleaseOleMutex
+ StringFromIID
+ IIDFromString
+; SzFixNet
+ Concatenate
+
+ ;; are these still needed?
+ ;;
+ ;;CloneSharedMemStm
+ ;;CreateSharedMemStm
+ ;;FreeSharedMemStmHandle
+ ;;CreateMemLockbytes
+ ;;?Create@CMemBytes@@SGPAV1@PAX@Z
+
+
+ ; Temparary while new CoMemAlloc defined
+ ?CoMemAlloc@@YAPAXKKPAX@Z
+ ?CoMemFree@@YAXPAXK@Z
+
+ ?PubMemAlloc@@YAPAXK@Z
+ ?PubMemFree@@YAXPAX@Z
+
+#ifndef _CAIRO_
+ ??2CPrivAlloc@@SAPAXI@Z
+ ??3CPrivAlloc@@SAXPAX@Z
+
+#endif
+
+ ; Export ability to create remote handler
+ RemCreateRemoteHandler
+
+#if DBG==1
+ Dbg_FindRemoteHdlr
+#endif
+
+ CoInitializeEx
+
+#ifdef LRPC
+ ;; BUGBUG: The following are old exports from 16 bit having to do
+ ;; with the LRPC part of the system. We are just keeping
+ ;; them here for reference.
+ RemAllocOID
+ RemFreeOID
+ RemConnectToObject
+ RemSetHandler
+ RemClearHandler
+ RemLookupHandler
+ RemUninitHandlers
+ RemRevokeServer
+ RemLookupOrCreateServer
+ RemLookupServerUnk
+ RemLookupServerOID
+ RemLookupSHUnk
+ RemUninitServers
+ RemCreateRHClassObject
+ RemEnsureLocalClassObject
+ RemEnsureUniqueHandler
+ RemGetInfoForCid
+ RemCreateStubManager
+
+ LrpcCall
+ LrpcDispatch
+ LrpcRegisterMonitor
+ LrpcRevokeMonitor
+ LrpcGetConnClient
+ LrpcGetConnObject
+ LrpcGetObjServer
+ LrpcGetMessage
+ LrpcTimeout
+ LrpcGetThreadWindow
+
+#endif // LRPC
+
+#elif defined(_PPC_)
+
+ CoBuildVersion @1
+ CoInitialize @2
+ CoUninitialize @3
+ CoGetMalloc @4
+
+ CoMarshalInterface @5
+ CoUnmarshalInterface @6
+ CoReleaseMarshalData @7
+ CoGetStandardMarshal @8
+ CoGetMarshalSizeMax @23
+ CoMarshalHresult @9
+ CoUnmarshalHresult @10
+
+ CoRegisterClassObject @11
+ CoRevokeClassObject @12
+ CoGetClassObject @13
+ CoCreateInstance @14
+
+; unused @15
+ CoDisconnectObject @16
+ CoLockObjectExternal @17
+
+ CoLoadLibrary @18
+ CoFreeLibrary @19
+ CoFreeAllLibraries @20
+ CoFreeUnusedLibraries @21
+ CoRegisterMessageFilter @22
+; CoBlock @23
+; CoUnblock @24
+ CoFileTimeToDosDateTime @25
+ CoDosDateTimeToFileTime @26
+
+ CoInitializeCriticalSection @27
+ CoEnterCriticalSection @28
+ CoLeaveCriticalSection @29
+ CoDeleteCriticalSection @30
+
+ GetRunningObjectTable @31
+
+ ; unused @32
+ CoOpenClassKey @33
+ CoIsOle1Class @34
+ CoTreatAsClass @35
+ CoGetTreatAsClass @36
+ CoGetCurrentProcess @37
+
+ IsEqualGUID @38
+ StringFromCLSID @39
+ CLSIDFromString @40
+ ProgIDFromCLSID @41
+ CLSIDFromProgID @42
+ StringFromGUID2 @43
+
+ IsValidPtrIn @44
+ IsValidPtrOut @45
+ IsValidInterface @46
+ IsValidIid @47
+
+;; ResultFromScode @48
+;; GetScode @49
+
+
+ ;; Temporary entry points used for shared memory allocation.
+
+ SharedMemAlloc @50
+ SharedMemReAlloc @51
+ SharedMemFree @52
+ CoMemctxOf @53
+; Moved to mangled names because these are not documented
+; CoMemAlloc @54
+; CoMemFree @55
+ CoGetPersistentInstance @56
+ CoNewPersistentInstance @57
+
+ ;; OLE2.01 functionality
+
+ CoIsHandlerConnected @58
+ ;;CoHasStrongExternalConnections @59
+ CoFileTimeNow @60
+
+ ;; 61-69 reserved for additional 2.01 functionality
+
+ ;; Moniker Functions
+
+ BindMoniker @70
+ MkParseDisplayName @71
+ CreateBindCtx @72
+ CreateItemMoniker @73
+ CreateFileMoniker @74
+ CreateGenericComposite @75
+ CreateAntiMoniker @76
+ CreatePointerMoniker @77
+ MonikerRelativePathTo @78
+#ifdef _CAIRO_
+ ; CreateFileMonikerEx @79
+#else
+; unused @79
+#endif
+ GetClassFile @80
+ OleSaveToStream @81
+ OleLoadFromStream @82
+ MonikerCommonPrefixWith @83
+
+ ;; internal calls below this point
+
+ ;; The following two entries are probably temporary as
+ ;; they are helpers for drag and drop
+ AssignEndpointProperty
+ UnAssignEndpointProperty
+ GetInterfaceFromWindowProp
+
+ ;; this maybe should be removed
+ FnAssert
+
+; StringFromCLSID2
+ CoGetClassExt
+ Ole1ClassFromCLSID2
+; CMemBytesUnMarshal
+; CMemStmUnMarshal
+ GetOleMutex
+ ReleaseOleMutex
+ StringFromIID
+ IIDFromString
+; SzFixNet
+ Concatenate
+
+ ;; are these still needed?
+ ;;
+ ;;CloneSharedMemStm
+ ;;CreateSharedMemStm
+ ;;FreeSharedMemStmHandle
+ ;;CreateMemLockbytes
+ ;;?Create@CMemBytes@@SGPAV1@PAX@Z
+
+
+ ; Temparary while new CoMemAlloc defined
+ ?CoMemAlloc@@YAPAXKKPAX@Z
+ ?CoMemFree@@YAXPAXK@Z
+
+ ?PubMemAlloc@@YAPAXK@Z
+ ?PubMemFree@@YAXPAX@Z
+
+#ifndef _CAIRO_
+ ??2CPrivAlloc@@SAPAXI@Z
+ ??3CPrivAlloc@@SAXPAX@Z
+
+#endif
+
+ ; Export ability to create remote handler
+ RemCreateRemoteHandler
+
+#if DBG==1
+ Dbg_FindRemoteHdlr
+#endif
+
+ CoInitializeEx
+
+#ifdef LRPC
+ ;; BUGBUG: The following are old exports from 16 bit having to do
+ ;; with the LRPC part of the system. We are just keeping
+ ;; them here for reference.
+ RemAllocOID
+ RemFreeOID
+ RemConnectToObject
+ RemSetHandler
+ RemClearHandler
+ RemLookupHandler
+ RemUninitHandlers
+ RemRevokeServer
+ RemLookupOrCreateServer
+ RemLookupServerUnk
+ RemLookupServerOID
+ RemLookupSHUnk
+ RemUninitServers
+ RemCreateRHClassObject
+ RemEnsureLocalClassObject
+ RemEnsureUniqueHandler
+ RemGetInfoForCid
+ RemCreateStubManager
+
+ LrpcCall
+ LrpcDispatch
+ LrpcRegisterMonitor
+ LrpcRevokeMonitor
+ LrpcGetConnClient
+ LrpcGetConnObject
+ LrpcGetObjServer
+ LrpcGetMessage
+ LrpcTimeout
+ LrpcGetThreadWindow
+
+#endif // LRPC
+
+#endif // i386 / _MIPS_ / _PPC_
+
+#endif // FLAT
diff --git a/private/ole32/com/class/daytona/makefile b/private/ole32/com/class/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/class/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/class/daytona/makefile.inc b/private/ole32/com/class/daytona/makefile.inc
new file mode 100644
index 000000000..e8fde76f7
--- /dev/null
+++ b/private/ole32/com/class/daytona/makefile.inc
@@ -0,0 +1 @@
+obj\$(TARGET_DIRECTORY)\compob32.def: compob32.src
diff --git a/private/ole32/com/class/daytona/sources b/private/ole32/com/class/daytona/sources
new file mode 100644
index 000000000..d5121e515
--- /dev/null
+++ b/private/ole32/com/class/daytona/sources
@@ -0,0 +1,78 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= class
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..;..\..\dcomidl\daytona;..\..\..\common;
+INCLUDES= $(INCLUDES);..\..\inc;..\..\moniker2;..\..\dcomrem;
+INCLUDES= $(INCLUDES);$(BASEDIR)\private\dcomidl\obj
+
+C_DEFINES= \
+ $(C_DEFINES)
+
+SOURCES= \
+ ..\alocdbg.cxx \
+ ..\cerror.cxx \
+ ..\cocrguid.cxx \
+ ..\compapi.cxx \
+ ..\compobj.cxx \
+ ..\cspytbl.cxx \
+ ..\longpath.cxx \
+ ..\memapi.cxx \
+ ..\ole1guid.cxx \
+ ..\tls.cxx \
+ ..\tracelog.cxx \
+ getif_i.c \
+ irot_c.c \
+ scm_c.c
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+
+#!include ..\..\precomp2.inc
diff --git a/private/ole32/com/class/dirs b/private/ole32/com/class/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/com/class/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/com/class/filelist.mk b/private/ole32/com/class/filelist.mk
new file mode 100644
index 000000000..33fb24151
--- /dev/null
+++ b/private/ole32/com/class/filelist.mk
@@ -0,0 +1,119 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = compob32.dll
+
+TARGET_DESCRIPTION = "$(PLATFORM) $(BUILDTYPE) Component Object DLL"
+
+RELEASE = 1
+
+COFFBASE = compob32
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES = .\bestfit.cxx \
+ .\compapi.cxx \
+ .\compobj.cxx \
+ .\memapi.cxx \
+ .\ole1guid.cxx \
+ .\olealloc.cxx \
+ .\smemstm.cxx \
+ .\sync.cxx \
+ .\tracelog.cxx \
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+!if "$(CAIROLE_TYPE)" == "DOWNLEVEL"
+DEFFILE = $(CAIROLE)\ilib\compob32.def
+!else
+DEFFILE = $(COMMON)\ilib\compob32.def
+!endif
+
+OBJFILES = \
+!if "$(CAIROLE_TYPE)" == "DOWNLEVEL"
+ ..\..\common\$(OBJDIR)\dllentr2.obj \
+!if "$(BUILDTYPE)" == "DEBUG"
+ ..\port\$(OBJDIR)\port.lib\
+!endif
+!endif
+ ..\coll\$(OBJDIR)\coll.lib \
+ ..\debug\$(OBJDIR)\debug.lib \
+ ..\idl\$(OBJDIR)\drot_c.obj \
+ ..\idl\$(OBJDIR)\drot_x.obj \
+ ..\idl\$(OBJDIR)\getif_s.obj \
+ ..\idl\$(OBJDIR)\getif_x.obj \
+ ..\idl\$(OBJDIR)\getif_y.obj \
+ ..\idl\$(OBJDIR)\getif_z.obj \
+ ..\idl\$(OBJDIR)\ichnl_s.obj \
+ ..\idl\$(OBJDIR)\ichnl_x.obj \
+ ..\idl\$(OBJDIR)\ichnl_y.obj \
+ ..\idl\$(OBJDIR)\ichnl_z.obj \
+ ..\idl\$(OBJDIR)\osrot_s.obj \
+ ..\idl\$(OBJDIR)\osrot_x.obj \
+ ..\idl\$(OBJDIR)\osrot_y.obj \
+ ..\idl\$(OBJDIR)\osrot_z.obj \
+ ..\idl\$(OBJDIR)\objsrv_s.obj \
+ ..\idl\$(OBJDIR)\objsrv_y.obj \
+ ..\idl\$(OBJDIR)\scm_c.obj \
+ ..\idl\$(OBJDIR)\scm_x.obj \
+ ..\remote\$(OBJDIR)\remote.lib \
+ ..\moniker2\$(OBJDIR)\moniker.lib \
+ ..\rot\$(OBJDIR)\rot.lib \
+ ..\inc\$(OBJDIR)\inc.lib \
+ ..\objact\$(OBJDIR)\objact.lib \
+ ..\util\$(OBJDIR)\util.lib
+
+LIBS = \
+!if "$(CAIROLE_TYPE)" == "DOWNLEVEL"
+ $(DOWNLVLLIB) \
+!else
+ $(CAIROLIB) \
+!endif
+ $(RPCLIBS) \
+ $(OSLIBDIR)\rpcns4.lib \
+ $(OSLIBDIR)\mpr.lib \
+ $(OSLIBDIR)\netapi32.lib \
+!if "$(OPSYS)" == "DOS" && "$(PLATFORM)" == "i386"
+ $(COMMON)\src\chicago\$(OBJDIR)\chicago.lib
+!endif
+
+#
+# Precompiled headers.
+#
+
+PXXFILE = .\headers.cxx
+PFILE =
+
+!if "$(CAIROLE_TYPE)" == "DOWNLEVEL"
+MONIKER = -I..\moniker2
+!else
+MONIKER = -I..\moniker2\cairo
+!endif
+
+CINC = $(CINC) -I..\inc $(MONIKER) -I..\remote $(CAIROLE_DOWNLEVEL) \
+ $(TRACELOG) -I..\idl
+
+MTHREAD = 1
+
+MULTIDEPEND = MERGED
diff --git a/private/ole32/com/class/fixheap.hxx b/private/ole32/com/class/fixheap.hxx
new file mode 100644
index 000000000..8f71b585d
--- /dev/null
+++ b/private/ole32/com/class/fixheap.hxx
@@ -0,0 +1,113 @@
+#if !defined __FIXHEAP_HXX__
+#define __FIXHEAP_HXX__
+
+#include <misc.hxx>
+#include <dlink.hxx>
+
+/** Memory object header definitions
+ */
+
+#define DEB_MEMORY 0x00080000
+
+#define CMAXFREELIST 29
+
+#define FREEBLOCK 0X3333
+#define BUSYBLOCK 0x6666
+
+class CFixedBlockHeader: public CDoubleLink
+{
+public:
+
+ CFixedBlockHeader* Split ( int logHalfSize )
+ {
+ return (CFixedBlockHeader*) (((BYTE*) this) + (1 << logHalfSize));
+ }
+
+ int Size () { return(1 << logSize); }
+
+ BOOL IsActive ()
+ {
+ return fFree == BUSYBLOCK;
+ }
+
+ int logSize:16; // log 2 of the block size
+ int fFree:16; // FREEBLOCK/BUSYBLOCK
+ int sizeRequest; // requested size
+};
+
+class CFixedBlockList: public CDoubleList
+{
+public:
+ void Push ( CFixedBlockHeader* pBlock );
+ CFixedBlockHeader* Pop();
+};
+
+class CFixedBlockIter: public CForwardIter
+{
+public:
+ CFixedBlockIter ( CFixedBlockList& list ): CForwardIter(list) {}
+ CFixedBlockHeader* operator->() { return (CFixedBlockHeader*)_pLinkCur; }
+ CFixedBlockHeader* GetBlock() { return (CFixedBlockHeader*) _pLinkCur; }
+};
+
+class CFixedBuddyHeap
+{
+public:
+
+ CFixedBuddyHeap(void *pvBase, ULONG size);
+
+ CFixedBlockHeader* GetBuddy(CFixedBlockHeader* pBlock);
+
+ void * Alloc(size_t s);
+
+ void * ReAlloc(size_t s, void *pvCurrent);
+
+ void Free (void *pBlock);
+
+private:
+
+ CFixedBlockHeader* FillFreeList (int i);
+
+ CFixedBlockList FreeList[CMAXFREELIST];
+
+ CFixedBlockList BusyList;
+
+ BYTE* Base;
+
+ int LogAllocSize;
+
+};
+
+inline CFixedBuddyHeap::CFixedBuddyHeap(void *pvBase, ULONG culBase)
+ : Base((BYTE *) pvBase), LogAllocSize(Log2(culBase - 1))
+{
+ //
+ // Put block on the free list. Currently this only works
+ // for power of two sizes.
+ //
+
+ CFixedBlockHeader *pfb = (CFixedBlockHeader *) pvBase;
+ pfb->logSize = LogAllocSize;
+ pfb->fFree = FREEBLOCK;
+ FreeList[LogAllocSize].Push(pfb);
+ CairoleDebugOut((DEB_MEMORY,"Base: %lx Size: %lx\n", (ULONG) pvBase,
+ culBase));
+ CairoleDebugOut((DEB_MEMORY,"LogAllocSize: %ld\n", LogAllocSize));
+ char *x = (char *) pvBase;
+ x[culBase - 1] = 0;
+}
+
+
+
+
+inline CFixedBlockHeader* CFixedBuddyHeap::GetBuddy(CFixedBlockHeader* pBlock)
+{
+ return (CFixedBlockHeader*)
+ ((((BYTE*)pBlock - Base) ^ pBlock->Size()) + Base);
+}
+
+#endif // __BUDDY_HXX__
+
+
+
+
diff --git a/private/ole32/com/class/longpath.cxx b/private/ole32/com/class/longpath.cxx
new file mode 100644
index 000000000..0498acedd
--- /dev/null
+++ b/private/ole32/com/class/longpath.cxx
@@ -0,0 +1,544 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: longpath.cxx
+//
+// Contents: GetLongPathName implementation
+//
+// History: 25-Aug-94 DrewB Created from Win32 sources for
+// GetShortPathName
+// 06-Sep-94 DrewB Rewrote using Win32 for portability
+// 11-Nov-94 BruceMa Use this version for both Chicago
+// and NT
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <widewrap.h>
+#include <longname.h>
+
+#define ARGUMENT_PRESENT2(p) ((p) != NULL)
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsLongComponent, public
+//
+// Synopsis: Determines whether the current path component is a legal
+// 8.3 name or not. If not, it is considered to be a long
+// component.
+//
+// Arguments: [pwcsPath] - Path to check
+// [ppwcsEnd] - Return for end of component pointer
+//
+// Returns: BOOL
+//
+// Modifies: [ppwcsEnd]
+//
+// History: 28-Aug-94 DrewB Created
+//
+// Notes: An empty path is considered to be long
+// The following characters are not valid in file name domain:
+// * + , : ; < = > ? [ ] |
+//
+//----------------------------------------------------------------------------
+
+BOOL IsLongComponent(LPCWSTR pwcsPath,
+ PWSTR *ppwcsEnd)
+{
+ LPWSTR pwcEnd, pwcDot;
+ BOOL fLongNameFound;
+ WCHAR wc;
+
+ pwcEnd = (LPWSTR)pwcsPath;
+ fLongNameFound = FALSE;
+ pwcDot = NULL;
+
+ while (TRUE)
+ {
+ wc = *pwcEnd;
+
+ if (wc == L'\\' || wc == 0)
+ {
+ *ppwcsEnd = pwcEnd;
+
+ // We're at a component terminator, so make the
+ // determination of whether what we've seen is a long
+ // name or short one
+
+ // If we've aready seen illegal characters or invalid
+ // structure for a short name, don't bother to check lengths
+ if (pwcEnd-pwcsPath > 0 && !fLongNameFound)
+ {
+ // If this component fits in 8.3 then it is a short name
+ if ((!pwcDot && (ULONG)(pwcEnd - pwcsPath) <= 8) ||
+ (pwcDot && ((ULONG)(pwcEnd - pwcDot) <= 3 + 1 &&
+ (ULONG)(pwcEnd - pwcsPath) <= 8 + 3 + 1)))
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ }
+
+ // Handle dots
+ if (wc == L'.')
+ {
+ // If two or more '.' or the base name is longer than
+ // 8 characters or no base name at all, it is an illegal dos
+ // file name
+ if (pwcDot != NULL ||
+ ((ULONG)(pwcEnd - pwcsPath)) > 8 ||
+ (pwcEnd == pwcsPath && *(pwcEnd + 1) != L'\\'))
+ {
+ fLongNameFound = TRUE;
+ }
+
+ pwcDot = pwcEnd;
+ }
+
+ // Check for characters which aren't valid in short names
+ else if (wc <= L' ' ||
+ wc == L'*' ||
+ wc == L'+' ||
+ wc == L',' ||
+ wc == L':' ||
+ wc == L';' ||
+ wc == L'<' ||
+ wc == L'=' ||
+ wc == L'>' ||
+ wc == L'?' ||
+ wc == L'[' ||
+ wc == L']' ||
+ wc == L'|')
+ {
+ fLongNameFound = TRUE;
+ }
+
+ pwcEnd++;
+ }
+}
+
+//
+// The following code was stolen from NT's RTL in curdir.c
+//
+
+#define IS_PATH_SEPARATOR(wch) \
+ ((wch) == L'\\' || (wch) == L'/')
+
+typedef enum
+{
+ PATH_TYPE_UNKNOWN,
+ PATH_TYPE_UNC_ABSOLUTE,
+ PATH_TYPE_LOCAL_DEVICE,
+ PATH_TYPE_ROOT_LOCAL_DEVICE,
+ PATH_TYPE_DRIVE_ABSOLUTE,
+ PATH_TYPE_DRIVE_RELATIVE,
+ PATH_TYPE_ROOTED,
+ PATH_TYPE_RELATIVE
+} PATH_TYPE;
+
+PATH_TYPE
+DetermineDosPathNameType(
+ IN PCWSTR DosFileName
+ )
+
+/*++
+
+Routine Description:
+
+ This function examines the Dos format file name and determines the
+ type of file name (i.e. UNC, DriveAbsolute, Current Directory
+ rooted, or Relative.
+
+Arguments:
+
+ DosFileName - Supplies the Dos format file name whose type is to be
+ determined.
+
+Return Value:
+
+ PATH_TYPE_UNKNOWN - The path type can not be determined
+
+ PATH_TYPE_UNC_ABSOLUTE - The path specifies a Unc absolute path
+ in the format \\server-name\sharename\rest-of-path
+
+ PATH_TYPE_LOCAL_DEVICE - The path specifies a local device in the format
+ \\.\rest-of-path this can be used for any device where the nt and
+ Win32 names are the same. For example mailslots.
+
+ PATH_TYPE_ROOT_LOCAL_DEVICE - The path specifies the root of the local
+ devices in the format \\.
+
+ PATH_TYPE_DRIVE_ABSOLUTE - The path specifies a drive letter absolute
+ path in the form drive:\rest-of-path
+
+ PATH_TYPE_DRIVE_RELATIVE - The path specifies a drive letter relative
+ path in the form drive:rest-of-path
+
+ PATH_TYPE_ROOTED - The path is rooted relative to the current disk
+ designator (either Unc disk, or drive). The form is \rest-of-path.
+
+ PATH_TYPE_RELATIVE - The path is relative (i.e. not absolute or rooted).
+
+--*/
+
+{
+ PATH_TYPE ReturnValue;
+
+ if ( IS_PATH_SEPARATOR(*DosFileName) )
+ {
+ if ( IS_PATH_SEPARATOR(*(DosFileName+1)) )
+ {
+ if ( DosFileName[2] == L'.' )
+ {
+ if ( IS_PATH_SEPARATOR(*(DosFileName+3)) )
+ {
+ ReturnValue = PATH_TYPE_LOCAL_DEVICE;
+ }
+ else if ( (*(DosFileName+3)) == 0 )
+ {
+ ReturnValue = PATH_TYPE_ROOT_LOCAL_DEVICE;
+ }
+ else
+ {
+ ReturnValue = PATH_TYPE_UNC_ABSOLUTE;
+ }
+ }
+ else
+ {
+ ReturnValue = PATH_TYPE_UNC_ABSOLUTE;
+ }
+ }
+ else
+ {
+ ReturnValue = PATH_TYPE_ROOTED;
+ }
+ }
+ else if (*(DosFileName+1) == L':')
+ {
+ if (IS_PATH_SEPARATOR(*(DosFileName+2)))
+ {
+ ReturnValue = PATH_TYPE_DRIVE_ABSOLUTE;
+ }
+ else
+ {
+ ReturnValue = PATH_TYPE_DRIVE_RELATIVE;
+ }
+ }
+ else
+ {
+ ReturnValue = PATH_TYPE_RELATIVE;
+ }
+
+ return ReturnValue;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetLongPathName, public
+//
+// Synopsis: Expand each component of the given path into its
+// long form
+//
+// Arguments: [pwcsPath] - Path
+// [pwcsLongPath] - Long path return buffer
+// [cchLongPath] - Size of return buffer in characters
+//
+// Returns: 0 for errors
+// Number of characters needed for buffer if buffer is too small
+// includes NULL terminator
+// Length of long path, doesn't include NULL terminator
+//
+// Modifies: [pwcsLongPath]
+//
+// History: 28-Aug-94 DrewB Created
+// 11-Nov-94 BruceMa Modifed to use for Chicago at
+// FindFirstFile
+//
+// Notes: The source and destination buffers can be the same memory
+// Doesn't handle paths with internal . and .., although
+// they are handled at the beginning
+//
+//----------------------------------------------------------------------------
+
+ULONG
+APIENTRY
+GetLongPathNameW(LPCWSTR pwcsPath,
+ LPWSTR pwcsLongPath,
+ ULONG cchLongPath)
+{
+ PATH_TYPE pt;
+ HANDLE h;
+ LPWSTR pwcsLocalLongPath;
+ ULONG cchReturn, cb, cch, cchOutput;
+ LPWSTR pwcStart = NULL;
+ LPWSTR pwcEnd;
+ LPWSTR pwcLong;
+ WCHAR wcSave;
+ BOOL fLong;
+ WIN32_FIND_DATA wfd;
+ cchReturn = 0;
+ pwcsLocalLongPath = NULL;
+
+
+ if (!ARGUMENT_PRESENT2(pwcsPath))
+ {
+ return 0;
+ }
+
+ __try
+ {
+ //
+ // First, run down the string checking for tilde's. Any path
+ // that has a short name section to it will have a tilde. If
+ // there are no tilde's, then we already have the long path,
+ // so we can return the string.
+ //
+ fLong = TRUE;
+ for (pwcLong = (LPWSTR)pwcsPath; *pwcLong != 0; pwcLong++)
+ {
+ if (*pwcLong == L'~')
+ {
+ fLong = FALSE;
+ }
+ }
+ //
+ // This derives the number of characters, including the NULL
+ //
+ cch = (pwcLong - pwcsPath) + 1;
+
+ //
+ // If it isn't a long path already, then we are going to have
+ // to parse it.
+ //
+ if (!fLong)
+ {
+ // Decide the path type, we want find out the position of
+ // the first character of the first name
+ pt = DetermineDosPathNameType(pwcsPath);
+ switch(pt)
+ {
+ // Form: "\\server_name\share_name\rest_of_the_path"
+ case PATH_TYPE_UNC_ABSOLUTE:
+ if ((pwcStart = wcschr(pwcsPath + 2, L'\\')) != NULL &&
+ (pwcStart = wcschr(pwcStart + 1, L'\\')) != NULL)
+ {
+ pwcStart++;
+ }
+ else
+ {
+ pwcStart = NULL;
+ }
+ break;
+
+ // Form: "\\.\rest_of_the_path"
+ case PATH_TYPE_LOCAL_DEVICE:
+ pwcStart = (LPWSTR)pwcsPath + 4;
+ break;
+
+ // Form: "\\."
+ case PATH_TYPE_ROOT_LOCAL_DEVICE:
+ pwcStart = NULL;
+ break;
+
+ // Form: "D:\rest_of_the_path"
+ case PATH_TYPE_DRIVE_ABSOLUTE:
+ pwcStart = (LPWSTR)pwcsPath + 3;
+ break;
+
+ // Form: "rest_of_the_path"
+ case PATH_TYPE_RELATIVE:
+ pwcStart = (LPWSTR) pwcsPath;
+ goto EatDots;
+
+ // Form: "D:rest_of_the_path"
+ case PATH_TYPE_DRIVE_RELATIVE:
+ pwcStart = (LPWSTR)pwcsPath+2;
+
+ EatDots:
+ // Handle .\ and ..\ cases
+ while (*pwcStart != 0 && *pwcStart == L'.')
+ {
+ if (pwcStart[1] == L'\\')
+ {
+ pwcStart += 2;
+ }
+ else if (pwcStart[1] == L'.' && pwcStart[2] == L'\\')
+ {
+ pwcStart += 3;
+ }
+ else
+ {
+ break;
+ }
+ }
+ break;
+
+ // Form: "\rest_of_the_path"
+ case PATH_TYPE_ROOTED:
+ pwcStart = (LPWSTR)pwcsPath + 1;
+ break;
+
+ default:
+ pwcStart = NULL;
+ break;
+ }
+ }
+
+ // In the special case where we have no work to do, exit quickly
+ // This saves a lot of instructions for trivial cases
+ // In one case the path as given requires no processing
+ // The middle case, we determine there were no tilde's in the path
+ // In the other, the path only has one component and it is already
+ // long
+ ///
+ if (pwcStart == NULL ||
+ (fLong == TRUE) ||
+ ((fLong = IsLongComponent(pwcStart, &pwcEnd)) &&
+ *pwcEnd == 0))
+ {
+ // Nothing to convert, copy down the source string
+ // to the buffer if necessary
+
+ if (pwcStart != NULL)
+ {
+ cch = (ULONG)(pwcEnd - pwcsPath + 1);
+ }
+
+ if (cchLongPath >= cch)
+ {
+ // If there's an output buffer which is different from
+ // the input buffer, fill it in
+ if (ARGUMENT_PRESENT2(pwcsLongPath) &&
+ pwcsLongPath != pwcsPath)
+ {
+ memcpy(pwcsLongPath, pwcsPath, cch * sizeof(WCHAR));
+ }
+
+ cchReturn = cch - 1;
+ goto gsnTryExit;
+ }
+ else
+ {
+ cchReturn = cch;
+ goto gsnTryExit;
+ }
+ }
+
+ // Make a local buffer so that we won't overlap the
+ // source pathname in case the long name is longer than the
+ // source name.
+ if (cchLongPath > 0 && ARGUMENT_PRESENT2(pwcsLongPath))
+ {
+ pwcsLocalLongPath = (PWCHAR)PrivMemAlloc(cchLongPath * sizeof(WCHAR));
+ if (pwcsLocalLongPath == NULL)
+ {
+ goto gsnTryExit;
+ }
+ }
+
+ // Set up pointer to copy output to
+ pwcLong = pwcsLocalLongPath;
+ cchOutput = 0;
+
+ // Copy the portions of the path that we skipped initially
+ cch = pwcStart-pwcsPath;
+ cchOutput += cch;
+ if (cchOutput <= cchLongPath && ARGUMENT_PRESENT2(pwcsLongPath))
+ {
+ memcpy(pwcLong, pwcsPath, cch*sizeof(WCHAR));
+ pwcLong += cch;
+ }
+
+ for (;;)
+ {
+ // Determine whether the current component is long or short
+ cch = pwcEnd-pwcStart+1;
+ cb = cch*sizeof(WCHAR);
+
+ if (fLong)
+ {
+ // If the component is already long, just copy it into
+ // the output. Copy the terminating character along with it
+ // so the output remains properly punctuated
+
+ cchOutput += cch;
+ if (cchOutput <= cchLongPath && ARGUMENT_PRESENT2(pwcsLongPath))
+ {
+ memcpy(pwcLong, pwcStart, cb);
+ pwcLong += cch;
+ }
+ }
+ else
+ {
+ WCHAR wcsTmp[MAX_PATH];
+
+ // For a short component we need to determine the
+ // long name, if there is one. The only way to
+ // do this reliably is to enumerate for the child
+
+ wcSave = *pwcEnd;
+ *pwcEnd = 0;
+
+ h = FindFirstFile(pwcsPath, &wfd);
+ *pwcEnd = wcSave;
+
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ goto gsnTryExit;
+ }
+
+ FindClose(h);
+
+ lstrcpyW(wcsTmp, wfd.cFileName);
+
+ // Copy the filename returned by the query into the output
+ // Copy the terminator from the original component into
+ // the output to maintain punctuation
+ cch = lstrlenW(wcsTmp)+1;
+ cchOutput += cch;
+ if (cchOutput <= cchLongPath && ARGUMENT_PRESENT2(pwcsLongPath))
+ {
+ memcpy(pwcLong, wcsTmp, (cch-1)*sizeof(WCHAR));
+ pwcLong += cch;
+ *(pwcLong-1) = *pwcEnd;
+ }
+ }
+
+ if (*pwcEnd == 0)
+ {
+ break;
+ }
+
+ // Update start pointer to next component
+ pwcStart = pwcEnd+1;
+ fLong = IsLongComponent(pwcStart, &pwcEnd);
+ }
+
+ // Copy local output buffer to given output buffer if necessary
+ if (cchLongPath >= cchOutput && ARGUMENT_PRESENT2(pwcsLongPath))
+ {
+ memcpy(pwcsLongPath, pwcsLocalLongPath, cchOutput * sizeof(WCHAR));
+ cchReturn = cchOutput-1;
+ }
+ else
+ {
+ cchReturn = cchOutput;
+ }
+
+gsnTryExit:;
+ }
+ __finally
+ {
+ if (pwcsLocalLongPath != NULL)
+ {
+ PrivMemFree(pwcsLocalLongPath);
+ pwcsLocalLongPath = NULL;
+ }
+ }
+
+ return cchReturn;
+}
diff --git a/private/ole32/com/class/makefile b/private/ole32/com/class/makefile
new file mode 100644
index 000000000..7f4951e2a
--- /dev/null
+++ b/private/ole32/com/class/makefile
@@ -0,0 +1,25 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+!include $(CAIROLE)\com\makefile
+
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/com/class/memapi.cxx b/private/ole32/com/class/memapi.cxx
new file mode 100644
index 000000000..8b702ced4
--- /dev/null
+++ b/private/ole32/com/class/memapi.cxx
@@ -0,0 +1,1549 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows:
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: MemAPI.CXX
+//
+// Contents: Memory allocation routines and IMallocSpy support
+//
+// Classes: CDebugMalloc
+// CRetailMalloc
+// CSpyMalloc
+//
+// Functions: CoGetMalloc
+// CoRegisterMallocSpy
+// CoRevokeMallocSpy
+// CoTaskMemAlloc
+// CoTaskMemFree
+// MIDL_user_allocate
+// MIDL_user_free
+//
+// History:
+// 04-Nov-93 AlexT Created
+// 25-Jan-94 AlexT Add CTaskMemory
+// 25-Jan-94 alexgo added PubMemRealloc
+// 08-Feb-94 AlexT Fix MIPS alignment
+// 24-Oct-94 BruceMa Add API's CoRegisterMallocSpy and
+// CoRevokeMallocSpy, and support for
+// IMallocSpy
+// 01-Nov-94 BruceMa Improve performance of retail IMalloc
+// 27-Sep-95 ShannonC Rewrote in C to improve performance.
+//
+// Notes:
+// OLE implements IMalloc using a single, static instance of CMalloc.
+// CoGetMalloc always returns the same IMalloc pointer. When necessary,
+// OLE can change the behavior of CMalloc by changing the lpVtbl.
+//
+// The CMalloc object has three interchangeable vtables. Normally,
+// the CMalloc object uses either the CRetailMallocVtbl or the
+// CDebugMallocVtbl. If an IMallocSpy is registered, OLE will switch
+// to the CSpyMallocVtbl in order to add IMallocSpy support. Note that
+// we will not change vtables when the IMallocSpy is revoked. Once OLE
+// switches to the CSpyMallocVtbl, it can never change back.
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include <memapi.hxx>
+#include "cspytbl.hxx"
+
+#if DBG==1
+#include <alocdbg.h>
+#endif // DBG==1
+
+//+-------------------------------------------------------------------------
+//
+// Class: CMalloc
+//
+// Purpose: Base class for OLE memory allocators.
+//
+// Interface: IMalloc
+//
+// See Also: CDebugMalloc, CRetailMalloc, CSpyMalloc
+//
+//--------------------------------------------------------------------------
+HRESULT __stdcall CMalloc_QueryInterface(IMalloc * pThis,
+ REFIID riid,
+ void **ppvObject);
+
+ULONG __stdcall CMalloc_AddRef(IMalloc * pThis);
+
+ULONG __stdcall CMalloc_Release(IMalloc * pThis);
+
+typedef struct IMallocVtbl
+{
+ HRESULT ( __stdcall *QueryInterface )(IMalloc * pThis,
+ REFIID riid,
+ void ** ppvObject);
+
+ ULONG ( __stdcall *AddRef )(IMalloc * pThis);
+
+ ULONG ( __stdcall *Release )(IMalloc * pThis);
+
+ void *( __stdcall *Alloc )(IMalloc * pThis, ULONG cb);
+
+ void *( __stdcall *Realloc )(IMalloc * pThis, void *pv, ULONG cb);
+
+ void ( __stdcall *Free )(IMalloc * pThis, void *pv);
+
+ ULONG ( __stdcall *GetSize )(IMalloc * pThis, void *pv);
+
+ int ( __stdcall *DidAlloc )(IMalloc * pThis, void *pv);
+
+ void ( __stdcall *HeapMinimize )(IMalloc * pThis);
+
+} IMallocVtbl;
+
+typedef struct CMalloc
+{
+ IMallocVtbl *lpVtbl;
+} CMalloc;
+
+//Global variables
+
+//g_lpVtblMalloc points to CDebugMallocVtbl or CRetailMallocVtbl.
+IMallocVtbl * g_lpVtblMalloc = 0;
+
+//WARNING: g_CMalloc.lpVtbl may change at runtime.
+//Initially, g_CMalloc.lpVtbl points to either
+//CDebugMallocVtbl or CRetailMallocVtbl. When an IMallocSpy is
+//registered, g_CMalloc.lpVtbl changes so it points to CSpyMallocVtbl.
+CMalloc g_CMalloc;
+IMalloc * g_pMalloc = (IMalloc *) &g_CMalloc;
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDebugMalloc
+//
+// Purpose: OLE debug memory allocator.
+//
+// Interface: IMalloc
+//
+//--------------------------------------------------------------------------
+#if DBG==1
+
+//function prototypes.
+void * __stdcall CDebugMalloc_Alloc(IMalloc *pThis, ULONG cb);
+
+void * __stdcall CDebugMalloc_Realloc(IMalloc *pThis, void *pv, ULONG cb);
+
+void __stdcall CDebugMalloc_Free(IMalloc *pThis, void *pv);
+
+ULONG __stdcall CDebugMalloc_GetSize(IMalloc *pThis, void *pv);
+
+int __stdcall CDebugMalloc_DidAlloc(IMalloc *pThis, void *pv);
+
+void __stdcall CDebugMalloc_HeapMinimize(IMalloc *pThis);
+
+//CDebugMalloc vtbl.
+IMallocVtbl CDebugMallocVtbl =
+{
+ CMalloc_QueryInterface,
+ CMalloc_AddRef,
+ CMalloc_Release,
+ CDebugMalloc_Alloc,
+ CDebugMalloc_Realloc,
+ CDebugMalloc_Free,
+ CDebugMalloc_GetSize,
+ CDebugMalloc_DidAlloc,
+ CDebugMalloc_HeapMinimize
+};
+
+//Global variables
+COleStaticMutexSem _mxsTaskMemory;
+ULONG g_BytesAllocated = 0;
+ULONG g_MemoryBlocksAllocated = 0;
+
+typedef struct
+{
+ DWORD dwSig; // Memory block signature
+ ULONG ulSize; // Allocated size
+ ULONG cbCommit; // Count of committed bytes
+ struct HeapAllocRec FAR *pArenaRecord; // Arena record
+} MEMINFO, *PMEMINFO;
+
+#define OLEMEM_SIG 0x5f4d454d // MEM_
+#define OLEMEM_ALLOCBYTE 0xde
+#define OLEMEM_FREEBYTE 0xed
+
+#ifdef _X86_
+# define OLEMEM_ALIGN_SIZE 4
+#else
+# define OLEMEM_ALIGN_SIZE 8
+#endif
+
+#endif //DBG==1
+//+-------------------------------------------------------------------------
+//
+// Class: CRetailMalloc
+//
+// Purpose: OLE retail memory allocator. This memory allocator uses
+// the NT heap.
+//
+// Interface: IMalloc
+//
+//--------------------------------------------------------------------------
+
+//Function prototypes.
+void * __stdcall CRetailMalloc_Alloc(IMalloc *pThis, ULONG cb);
+
+void * __stdcall CRetailMalloc_Realloc(IMalloc *pThis, void *pv, ULONG cb);
+
+void __stdcall CRetailMalloc_Free(IMalloc *pThis, void *pv);
+
+ULONG __stdcall CRetailMalloc_GetSize(IMalloc *pThis, void *pv);
+
+int __stdcall CRetailMalloc_DidAlloc(IMalloc *pThis, void *pv);
+
+void __stdcall CRetailMalloc_HeapMinimize(IMalloc *pThis);
+
+// Makes serialized heap access obvious
+const DWORD HEAP_SERIALIZE = 0;
+
+//CRetailMalloc vtbl.
+IMallocVtbl CRetailMallocVtbl =
+{
+ CMalloc_QueryInterface,
+ CMalloc_AddRef,
+ CMalloc_Release,
+ CRetailMalloc_Alloc,
+ CRetailMalloc_Realloc,
+ CRetailMalloc_Free,
+ CRetailMalloc_GetSize,
+ CRetailMalloc_DidAlloc,
+ CRetailMalloc_HeapMinimize
+};
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSpyMalloc
+//
+// Purpose: OLE spy memory allocator.
+//
+// Interface: IMalloc
+//
+//--------------------------------------------------------------------------
+
+//function prototypes.
+void * __stdcall CSpyMalloc_Alloc(IMalloc *pThis, ULONG cb);
+
+void * __stdcall CSpyMalloc_Realloc(IMalloc *pThis, void *pv, ULONG cb);
+
+void __stdcall CSpyMalloc_Free(IMalloc *pThis, void *pv);
+
+ULONG __stdcall CSpyMalloc_GetSize(IMalloc *pThis, void *pv);
+
+int __stdcall CSpyMalloc_DidAlloc(IMalloc *pThis, void *pv);
+
+void __stdcall CSpyMalloc_HeapMinimize(IMalloc *pThis);
+
+//CSpyMalloc vtbl.
+IMallocVtbl CSpyMallocVtbl =
+{
+ CMalloc_QueryInterface,
+ CMalloc_AddRef,
+ CMalloc_Release,
+ CSpyMalloc_Alloc,
+ CSpyMalloc_Realloc,
+ CSpyMalloc_Free,
+ CSpyMalloc_GetSize,
+ CSpyMalloc_DidAlloc,
+ CSpyMalloc_HeapMinimize
+};
+
+// Globals for the IMallocSpy code
+//
+// IMallocSpy instance supplied by the user
+LPMALLOCSPY g_pMallocSpy = NULL;
+
+// The thread id (via CoGetCurrentProcess) which registered the IMallocSpy
+DWORD g_dwMallocSpyRegistrationTID = 0;
+
+// Semaphore used while spying
+COleStaticMutexSem g_SpySem;
+
+// Indicates whether a revoke was attempted with allocation count > 0
+BOOL g_fRevokePending = FALSE;
+
+// Table of IMallocSpy allocations not yet freed
+LPSPYTABLE g_pAllocTbl = NULL;
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: MallocInitialize
+//
+// Synopsis: Initializes the memory allocator.
+//
+//--------------------------------------------------------------------------
+HRESULT MallocInitialize(BOOL fForceLocalAlloc)
+{
+ HRESULT hr = S_OK;
+
+ g_hHeap = GetProcessHeap();
+
+ if(0 == g_hHeap)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+#if DBG==1
+ if(fForceLocalAlloc == TRUE)
+ {
+ //Use the OLE retail memory allocator.
+ g_lpVtblMalloc = &CRetailMallocVtbl;
+ }
+ else
+ {
+ //Use the OLE debug memory allocator.
+ g_lpVtblMalloc = &CDebugMallocVtbl;
+ }
+#else
+ //Use the OLE retail memory allocator.
+ g_lpVtblMalloc = &CRetailMallocVtbl;
+#endif //DBG==1
+
+ g_CMalloc.lpVtbl = g_lpVtblMalloc;
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: MallocUninitialize
+//
+// Synopsis: Clean up and check for local memory leaks
+//
+// Effects: Prints out messages on debug terminal if there are leaks
+//
+// Returns: If no leaks, TRUE
+// Otherwise, FALSE
+//
+//--------------------------------------------------------------------------
+BOOL MallocUninitialize(void)
+{
+ BOOL bResult = TRUE;
+
+ VDATEHEAP();
+
+#if DBG==1
+ if(&CDebugMallocVtbl == g_lpVtblMalloc)
+ {
+ //Check for memory leaks from the debug heap.
+ if (g_MemoryBlocksAllocated > 0)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "Leaked %ld bytes (%ld allocations)\n",
+ g_BytesAllocated,
+ g_MemoryBlocksAllocated));
+
+ bResult = FALSE;
+ }
+ AllocArenaDump( NULL );
+ }
+#endif //DBG==1
+
+ return bResult;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoGetMalloc
+//
+// Synopsis: returns system provided IMalloc
+//
+// Arguments: [dwContext] - type of allocator to return
+// [ppMalloc] - where to return the allocator
+//
+//--------------------------------------------------------------------------
+STDAPI CoGetMalloc(DWORD dwContext, IMalloc **ppMalloc)
+{
+ HRESULT hr;
+
+ switch (dwContext)
+ {
+ case MEMCTX_TASK:
+ //We use a static IMalloc object so
+ //we don't need to AddRef it here.
+ *ppMalloc = g_pMalloc;
+ hr = S_OK;
+ break;
+
+ case MEMCTX_SHARED:
+ CairoleDebugOut((DEB_WARN, "CoGetMalloc(MEMCTX_SHARED, ...) not "
+ "supported for 32-bit OLE\n"));
+
+ // fall through to E_INVALIDARG
+ default:
+ *ppMalloc = NULL;
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------
+//
+// Function: CoRegisterMallocSpy
+//
+// Synopsis: Registers the supplied implementation instance of
+// IMallocSpy
+//
+// Arguments: [pMallocSpy]
+//
+// Returns: CO_E_OBJISREG - A spy is already registered
+// E_INVALIDARG - The QueryInterface for
+// IID_IMallocSpy failed
+// S_OK - Spy registered ok
+//
+//----------------------------------------------------------------------
+STDAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy)
+{
+ HRESULT hr = S_OK;
+
+ OLETRACEIN((API_CoRegisterMallocSpy, PARAMFMT("pMallocSpy = %p"), pMallocSpy));
+
+ if(pMallocSpy != 0)
+ {
+ LPMALLOCSPY pMSpy;
+
+ hr = pMallocSpy->QueryInterface(IID_IMallocSpy, (void **) &pMSpy);
+
+ if(SUCCEEDED(hr))
+ {
+ g_SpySem.Request();
+
+ if (0 == g_pMallocSpy)
+ {
+ BOOL fOk;
+
+ // Initialize
+ g_fRevokePending = FALSE;
+ if (g_pAllocTbl)
+ {
+ delete g_pAllocTbl;
+ }
+
+ g_pAllocTbl = new CSpyTable(&fOk);
+
+ if (fOk)
+ {
+ // Register the new one
+ CairoleDebugOut((DEB_TRACE, "IMallocSpy registered: %x\n", pMSpy));
+ g_pMallocSpy = pMSpy;
+ g_dwMallocSpyRegistrationTID = CoGetCurrentProcess();
+
+ //Switch the IMalloc lpVtbl to CSpyMallocVtbl.
+ g_CMalloc.lpVtbl = &CSpyMallocVtbl;
+
+ hr = S_OK;
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ // An IMallocSpy is already registered. Deny this registration.
+ CairoleDebugOut((DEB_ERROR, "Registering IMallocSpy %x over %x\n",
+ pMallocSpy, g_pMallocSpy));
+
+ hr = CO_E_OBJISREG;
+ }
+
+ if(FAILED(hr))
+ {
+ pMSpy->Release();
+ }
+
+ g_SpySem.Release();
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ }
+
+ OLETRACEOUT((API_CoRegisterMallocSpy, hr));
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------
+//
+// Function: CoRevokeMallocSpy
+//
+// Synopsis: Revokes any registered IMallocSpy instance
+//
+// Returns: CO_E_OBJNOTREG - No spy is currently registered
+// E_ACCESSDENIED - A spy is registered but there are
+// outstanding allocations done while
+// the spy was active which have not
+// yet been freed
+// S_OK - Spy revoked successfully
+//
+//----------------------------------------------------------------------
+STDAPI CoRevokeMallocSpy(void)
+{
+ HRESULT hr = S_OK;
+
+ OLETRACEIN((API_CoRevokeMallocSpy, NOPARAM));
+
+ // Make revoking thread safe
+ g_SpySem.Request();
+
+ // Check that an IMallocSpy instance is registered
+ if (g_pMallocSpy != 0)
+ {
+ if (0 == g_pAllocTbl->m_cAllocations)
+ {
+ // Attempt to release it
+ CairoleDebugOut((DEB_TRACE, "IMallocSpy revoked: %x\n", g_pMallocSpy));
+ g_pMallocSpy->Release();
+ g_pMallocSpy = NULL;
+ g_fRevokePending = FALSE;
+ delete g_pAllocTbl;
+ g_pAllocTbl = NULL;
+ g_dwMallocSpyRegistrationTID = 0;
+ hr = S_OK;
+ }
+ else
+ {
+ // If there are still outstanding Alloc/Realloc's which have not yet
+ // been Free'd, then deny the revoke
+ g_fRevokePending = TRUE;
+ hr = E_ACCESSDENIED;
+ }
+ }
+ else
+ {
+ CairoleDebugOut((DEB_WARN, "Attempt to revoke NULL IMallocSpy\n"));
+ hr = CO_E_OBJNOTREG;
+ }
+
+ g_SpySem.Release();
+
+ OLETRACEOUT((API_CoRevokeMallocSpy, hr));
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoTaskMemAlloc
+//
+// Synopsis: Allocate public memory (using task IMalloc)
+//
+// Arguments: [ulcb] -- memory block size
+//
+// Returns: Pointer to allocated memory or NULL
+//
+//--------------------------------------------------------------------------
+STDAPI_(LPVOID) CoTaskMemAlloc(ULONG ulcb)
+{
+ return g_pMalloc->Alloc(ulcb);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoTaskMemFree
+//
+// Synopsis: Free public memory
+//
+// Arguments: [pv] -- pointer to memory block
+//
+// Requires: pv must have been allocated with the task allocator
+//
+//--------------------------------------------------------------------------
+STDAPI_(void) CoTaskMemFree(void *pv)
+{
+ g_pMalloc->Free(pv);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoTaskMemRealloc
+//
+// Synopsis: Re-Allocate public memory (using task IMalloc)
+//
+// Arguments: [pv] -- pointer to the memory to be resized
+// [ulcb] -- memory block size
+//
+// Returns: Pointer to allocated memory or NULL
+//
+//--------------------------------------------------------------------------
+STDAPI_(LPVOID) CoTaskMemRealloc(LPVOID pv, ULONG ulcb)
+{
+ return g_pMalloc->Realloc(pv, ulcb);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: MIDL_user_allocate
+//
+// Purpose: allocates memory on behalf of midl-generated stubs
+//
+//--------------------------------------------------------------------------
+extern "C" void * __RPC_API MIDL_user_allocate(size_t cb)
+{
+ return PrivMemAlloc8(cb);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: MIDL_user_free
+//
+// Purpose: frees memory allocated by MIDL_user_allocate
+//
+//--------------------------------------------------------------------------
+extern "C" void __RPC_API MIDL_user_free(void *pv)
+{
+ PrivMemFree(pv);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CMalloc_QueryInterface
+//
+// Synopsis: QueryInterface on the memory allocator.
+//
+// Arguments: riid - Supplies the IID.
+//
+// Returns:
+//
+//--------------------------------------------------------------------------
+HRESULT __stdcall CMalloc_QueryInterface(IMalloc * pThis,
+ REFIID riid,
+ void **ppvObject)
+{
+ HRESULT hr;
+
+ if (IsEqualIID(riid,IID_IUnknown) || IsEqualIID(riid,IID_IMalloc))
+ {
+ //We use a static IMalloc object so
+ //we don't need to AddRef it here.
+ *ppvObject = pThis;
+ hr = S_OK;
+ }
+ else
+ {
+ *ppvObject = 0;
+ hr = E_NOINTERFACE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CMalloc_AddRef
+//
+// Synopsis: AddRef the memory allocator.
+//
+//--------------------------------------------------------------------------
+ULONG __stdcall CMalloc_AddRef(IMalloc * pThis)
+{
+ //We use a static IMalloc object so
+ //we don't need to AddRef it here.
+ return 1;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CMalloc_Release
+//
+// Synopsis: Release the memory allocator.
+//
+//--------------------------------------------------------------------------
+ULONG __stdcall CMalloc_Release(IMalloc * pThis)
+{
+ //We use a static IMalloc object so
+ //we don't need to Release it here.
+ return 1;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: GetMemInfo
+//
+// Synopsis: Retrieves memory info block pointer
+//
+// Arguments: [pv] - memory address
+//
+// Requires: pv != NULL
+//
+// Returns: If valid memory address, memory info block pointer
+// Otherwise, NULL
+//
+// Algorithm: The memory info block is always located before the address at
+// the beginning of the page.
+//
+//--------------------------------------------------------------------------
+#if DBG==1
+PMEMINFO GetMemInfo(void *pv)
+{
+ SYSTEM_INFO si;
+ PMEMINFO pmi;
+
+ CairoleAssert(pv != NULL && "GetMemInfo bad input");
+
+ // Retrieve page size
+#ifdef _CHICAGO_
+ si.dwPageSize = 0x1000;
+#else
+ GetSystemInfo(&si);
+#endif
+
+ pmi = (PMEMINFO) ((((ULONG) pv) - sizeof(MEMINFO)) & ~(si.dwPageSize-1));
+
+ // Make sure we can access it
+ if (IsBadReadPtr(pmi, si.dwPageSize))
+ {
+ CairoleDebugOut((DEB_WARN,
+ "GetMemInfo - no read access\n"));
+ }
+ else if (pmi->dwSig != OLEMEM_SIG)
+ {
+ CairoleDebugOut((DEB_WARN,
+ "GetMemInfo - bad mem signature\n"));
+ }
+ else
+ {
+ return(pmi);
+ }
+
+ return(NULL);
+}
+#endif //DBG==1
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDebugMalloc_Alloc
+//
+// Synopsis: Local memory allocator
+//
+// Arguments: [cb] -- memory block size
+//
+// Returns: Memory block pointer
+//
+// Modifies: Heap
+//
+// Algorithm: reserve memory including guard pages
+// commit memory
+// initialize committed memory
+// initialize control block
+// return pointer such that tail is on guard page
+//
+//--------------------------------------------------------------------------
+#if DBG==1
+void * __stdcall CDebugMalloc_Alloc(IMalloc *pThis, ULONG cb)
+{
+ SYSTEM_INFO si;
+ ULONG cbAlloc;
+ ULONG cbCommit;
+ ULONG cbReserve;
+ void *pvReserve;
+ void *pvCommit;
+ PMEMINFO pmi;
+ void *pvRet = 0;
+
+ // Parameter validation
+ if (cb > 0x7FFFFFFF)
+ return 0;
+
+ // Retrieve page size
+#ifdef _CHICAGO_
+ si.dwPageSize = 0x1000;
+#else
+ GetSystemInfo(&si);
+#endif
+
+ // For x86, align the memory on a 4 byte boundary.
+ // For non-x86 platforms, align the memory on an 8 byte boundary.
+ cbAlloc = (cb + OLEMEM_ALIGN_SIZE - 1)
+ & ~(OLEMEM_ALIGN_SIZE - 1);
+
+ // Calculate pages necessary for both requested size and our
+ // control info
+ cbCommit = (cbAlloc + sizeof(MEMINFO) + si.dwPageSize - 1)
+ & ~(si.dwPageSize - 1);
+
+ // Reserve enough for allocation and guard pages
+ cbReserve = cbCommit + si.dwPageSize;
+
+ // Reserve cbReserve pages
+ pvReserve = VirtualAlloc(
+ NULL,
+ cbReserve,
+ MEM_RESERVE,
+ PAGE_NOACCESS);
+
+ if (pvReserve != 0)
+ {
+ // Commit cbCommit pages
+ pvCommit = VirtualAlloc(pvReserve,
+ cbCommit,
+ MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE);
+
+ if (pvCommit != 0)
+ {
+ // Initialize pages
+ memset(pvCommit, OLEMEM_ALLOCBYTE, cbCommit);
+
+ // write sMemInfo data
+ pmi = (PMEMINFO) pvCommit;
+
+ pmi->dwSig = OLEMEM_SIG;
+ pmi->ulSize = cb;
+ pmi->cbCommit = cbCommit;
+
+ // Increment local count
+ {
+ COleStaticLock lck(_mxsTaskMemory);
+ static AllocArena *pAllocArena = (AllocArena *)-1;
+
+ if (pAllocArena == (AllocArena *)-1)
+ {
+ pAllocArena = AllocArenaCreate( MEMCTX_TASK, "CDebugMalloc");
+ }
+
+ pmi->pArenaRecord = AllocArenaRecordAlloc(pAllocArena, cb);
+
+ g_BytesAllocated += pmi->ulSize;
+ g_MemoryBlocksAllocated++;
+ }
+
+ // Calculate return pointer
+ pvRet = ((BYTE *) pvCommit) + cbCommit - cbAlloc;
+
+ // Public memory guaranteed to be aligned
+ CairoleAssert(((ULONG)pvRet & (OLEMEM_ALIGN_SIZE - 1)) == NULL &&
+ "public memory allocation not aligned");
+
+ }
+ else
+ {
+ CairoleDebugOut((DEB_WARN,
+ "CDebugMalloc_Alloc(%ld) couldn't commit - %lx\n",
+ cbCommit, GetLastError()));
+
+ // Release reserved pages.
+ VirtualFree(pvReserve, 0, MEM_RELEASE);
+ }
+ }
+ else
+ {
+ CairoleDebugOut((DEB_WARN,
+ "CDebugMalloc_Alloc(%ld) couldn't reserve - %lx\n",
+ cbReserve, GetLastError()));
+ }
+ return pvRet;
+}
+#endif //DBG==1
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDebugMalloc_Realloc
+//
+// Synopsis: Reallocated local memory
+//
+// Arguments: [pv] -- original memory block
+// [cb] -- new size
+//
+// Returns: new memory block
+//
+//--------------------------------------------------------------------------
+#if DBG==1
+void * __stdcall CDebugMalloc_Realloc(IMalloc * pThis, void * pv, ULONG cb)
+{
+ void *pvNew = 0;
+
+ if (pv != 0)
+ {
+ PMEMINFO pmi = GetMemInfo(pv);
+ CairoleAssert(pmi != 0 && "CDebugMalloc_Realloc - bad pointer");
+
+ if(pmi != 0)
+ {
+ if (cb != 0)
+ {
+ // Allocate a new memory block.
+ pvNew = CDebugMalloc_Alloc(pThis, cb);
+
+ if(pvNew != 0)
+ {
+ // Copy data from the old memory block.
+ memcpy(pvNew, pv, min(pmi->ulSize, cb));
+
+ // Free the old memory block.
+ CDebugMalloc_Free(pThis, pv);
+ }
+ else
+ {
+ // We could not allocate a new memory block.
+ // Leave the old memory block unchanged.
+ }
+ }
+ else
+ {
+ // Free the old memory block.
+ CDebugMalloc_Free(pThis, pv);
+ }
+ }
+ }
+ else
+ {
+ // Treat this as an Alloc
+ pvNew = CDebugMalloc_Alloc(pThis, cb);
+ }
+
+ return pvNew;
+}
+#endif //DBG==1
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDebugMalloc_Free
+//
+// Synopsis: release local memory
+//
+// Arguments: [pv] -- memory address
+//
+// Algorithm:
+// get control information
+// validate memory block
+// verify that bytes between header and pv are untouched
+// set to known bad value
+// decommit
+// unreserve
+//
+//--------------------------------------------------------------------------
+#if DBG==1
+void __stdcall CDebugMalloc_Free(IMalloc *pThis, void * pv)
+{
+ if(pv != 0)
+ {
+ PMEMINFO pmi = GetMemInfo(pv);
+ CairoleAssert(pmi != NULL && "CDebugMalloc_Free - bad pointer");
+
+ if(pmi != 0)
+ {
+ BOOL bResult;
+ MEMINFO mi = *pmi;
+ void *pvCommit = pmi;;
+ BYTE *pbCheck = ((BYTE *) pvCommit) + sizeof(MEMINFO);
+
+ // Verify that bytes between header and pvNew are untouched
+ while (pbCheck < (BYTE *) pv && *pbCheck == OLEMEM_ALLOCBYTE)
+ {
+ pbCheck++;
+ }
+
+ CairoleAssert(pbCheck == (BYTE *) pv &&
+ "CDebugMalloc_Free - header region dirty");
+
+ // Verify that bytes between allocation and end of page are untouched
+ pbCheck = ((BYTE *) pv) + mi.ulSize;
+ while (pbCheck < (BYTE *) pvCommit + mi.cbCommit &&
+ *pbCheck == OLEMEM_ALLOCBYTE)
+ {
+ pbCheck++;
+ }
+
+ CairoleAssert(pbCheck == ((BYTE *) pvCommit) + mi.cbCommit &&
+ "CDebugMalloc_Free - tail region dirty");
+
+ // Set to known bad value
+ memset(pvCommit, OLEMEM_FREEBYTE, mi.cbCommit);
+
+ // Decommit
+ bResult = VirtualFree(pvCommit, mi.cbCommit, MEM_DECOMMIT);
+ CairoleAssert(bResult && "CDebugMalloc_Free - VirtualFree(DECOMMIT) failed");
+
+ // Unreserve
+ bResult = VirtualFree(pvCommit, 0, MEM_RELEASE);
+ CairoleAssert(bResult && "CDebugMalloc_Free - VirtualFree(RELEASE) failed");
+
+ // Decrement local count
+ {
+ COleStaticLock lck(_mxsTaskMemory);
+
+ CairoleAssert(mi.ulSize <= g_BytesAllocated &&
+ "Public memory tracking broken");
+ CairoleAssert(g_MemoryBlocksAllocated > 0 &&
+ "Public memory tracking broken");
+
+ g_BytesAllocated -= mi.ulSize;
+ g_MemoryBlocksAllocated--;
+ }
+
+ AllocArenaRecordFree(mi.pArenaRecord, mi.ulSize);
+ }
+ }
+}
+#endif //DBG==1
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDebugMalloc_GetSize
+//
+// Synopsis: Return size of memory block
+//
+// Arguments: [pv] -- memory address
+//
+// Returns: If valid memory, the size of the block
+// Otherwise, 0
+//
+//--------------------------------------------------------------------------
+#if DBG==1
+ULONG __stdcall CDebugMalloc_GetSize(IMalloc *pThis, void * pv)
+{
+ ULONG ulSize = (ULONG) -1;
+
+ if (pv != 0)
+ {
+ PMEMINFO pmi = GetMemInfo(pv);
+ CairoleAssert(pmi != NULL && "CDebugMalloc_GetSize - bad pointer");
+
+ if (pmi != 0)
+ {
+ // Fetch the size of the allocation
+ ulSize = pmi->ulSize;
+ }
+ }
+ return ulSize;
+}
+#endif //DBG==1
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDebugMalloc_DidAlloc
+//
+// Synopsis: Return whether this allocator allocated the block
+//
+// Arguments: [pv] -- memory address
+//
+// Returns: If allocated by this allocator, TRUE
+// Otherwise, FALSE
+//
+//--------------------------------------------------------------------------
+#if DBG==1
+int __stdcall CDebugMalloc_DidAlloc(IMalloc *pThis, void * pv)
+{
+ int fDidAlloc = FALSE;
+
+ if (pv != 0)
+ {
+ PMEMINFO pmi = GetMemInfo(pv);
+
+ if (pmi != NULL)
+ {
+ fDidAlloc = TRUE;
+ }
+ }
+ else
+ {
+ fDidAlloc = -1;
+ }
+
+ return fDidAlloc;
+}
+#endif //DBG==1
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDebugMalloc_HeapMinimize
+//
+// Synopsis: Minimize heap
+//
+//--------------------------------------------------------------------------
+#if DBG==1
+void __stdcall CDebugMalloc_HeapMinimize(IMalloc *pThis)
+{
+ CairoleAssert(g_hHeap != 0 && "GetProcessHeap failed");
+
+ // Compact the heap
+ HeapCompact(g_hHeap, HEAP_SERIALIZE);
+}
+#endif //DBG==1
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CRetailMalloc_Alloc
+//
+// Synopsis: Allocate a block of memory.
+//
+// Arguments: [cb] -- Specifies the size of the memory block to allocate.
+//
+// Returns: Pointer to allocated memory or NULL
+//
+//--------------------------------------------------------------------------
+void * __stdcall CRetailMalloc_Alloc(IMalloc *pThis, ULONG cb)
+{
+ CairoleAssert(g_hHeap != 0 && "GetProcessHeap failed");
+
+ return (LPVOID) HeapAlloc(g_hHeap, HEAP_SERIALIZE, cb);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CRetailMalloc_DidAlloc
+//
+// Synopsis: Determine if the memory block was allocated by this
+// memory allocator.
+//
+// Arguments: [pv] -- pointer to the memory block
+//
+// Notes: The OLE spec requires that -1 be returned for
+// NULL pointers.
+//
+//--------------------------------------------------------------------------
+int __stdcall CRetailMalloc_DidAlloc(IMalloc *pThis, void * pv)
+{
+ int fDidAlloc = -1;
+
+ CairoleAssert(g_hHeap != 0 && "GetProcessHeap failed");
+
+ // Chicago does not support HeapValidate
+#ifndef _CHICAGO_
+ if (pv != 0)
+ {
+ fDidAlloc = HeapValidate(g_hHeap, HEAP_SERIALIZE, pv);
+ }
+#endif //_CHICAGO_
+
+ return fDidAlloc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CRetailMalloc_Free
+//
+// Synopsis: Free a memory block previously allocated via CRetailMalloc_Alloc.
+//
+// Arguments: [pv] -- pointer to the memory block to be freed.
+//
+//--------------------------------------------------------------------------
+void __stdcall CRetailMalloc_Free(IMalloc *pThis, void * pv)
+{
+ CairoleAssert(g_hHeap != 0 && "GetProcessHeap failed");
+
+ if (pv != 0)
+ HeapFree(g_hHeap, HEAP_SERIALIZE, pv);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CRetailMalloc_GetSize
+//
+// Synopsis: Gets the size of a memory block.
+//
+// Arguments: [pv] -- pointer to the memory block
+//
+// Notes: The OLE spec requires that -1 be returned for
+// NULL pointers.
+//
+//--------------------------------------------------------------------------
+ULONG __stdcall CRetailMalloc_GetSize(IMalloc * pThis, void * pv)
+{
+ CairoleAssert(g_hHeap != 0 && "GetProcessHeap failed");
+
+ if (0 == pv)
+ {
+ return((ULONG) -1);
+ }
+ return HeapSize(g_hHeap, HEAP_SERIALIZE, pv);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CRetailMalloc_Minimize
+//
+// Synopsis: Compact the heap.
+//
+//--------------------------------------------------------------------------
+void __stdcall CRetailMalloc_HeapMinimize(IMalloc * pThis)
+{
+ CairoleAssert(g_hHeap != 0 && "GetProcessHeap failed");
+
+ // Compact the heap
+ HeapCompact(g_hHeap, HEAP_SERIALIZE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CRetailMalloc_Realloc
+//
+// Synopsis: Changes the size of a memory block previously allocated
+// via CRetailMalloc_Alloc.
+//
+// Arguments: [pv] -- Points to the memory block to be reallocated.
+// [cb] -- Specifies the new size of the memory block.
+//
+// Returns: Pointer to allocated memory or NULL.
+//
+//--------------------------------------------------------------------------
+void * __stdcall CRetailMalloc_Realloc(IMalloc *pThis, void * pv, ULONG cb)
+{
+ LPVOID pvNew = 0;
+
+ CairoleAssert(g_hHeap != 0 && "GetProcessHeap failed");
+
+ if(pv != 0)
+ {
+ if(cb != 0)
+ {
+ pvNew = (LPVOID) HeapReAlloc(g_hHeap, HEAP_SERIALIZE, pv, cb);
+ }
+ else
+ {
+ //Treat this as a free.
+ HeapFree(g_hHeap, HEAP_SERIALIZE, pv);
+ pvNew = 0;
+ }
+ }
+ else
+ {
+ //Treat this as an alloc.
+ pvNew = (LPVOID) HeapAlloc(g_hHeap, HEAP_SERIALIZE, cb);
+ }
+
+ return pvNew;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSpyMalloc::Alloc
+//
+// Synopsis: Local memory allocator
+//
+// Arguments: [cb] -- memory block size
+//
+// Returns: Pointer to new memory block.
+//
+//--------------------------------------------------------------------------
+void * __stdcall CSpyMalloc_Alloc(IMalloc *pThis, ULONG cb)
+{
+ void *pvRet = NULL;
+
+ g_SpySem.Request();
+
+ // If an IMallocSpy is active, call the pre method
+ if (g_pMallocSpy)
+ {
+ ULONG cbAlloc = g_pMallocSpy->PreAlloc(cb);
+
+ // The pre method forces failure by returning 0
+ if ((cbAlloc != 0) || (0 == cb))
+ {
+ // Allocate the memory
+ pvRet = g_lpVtblMalloc->Alloc(pThis, cbAlloc);
+
+ // Call the post method
+ pvRet = g_pMallocSpy->PostAlloc(pvRet);
+
+ // Update the spy table.
+ if (pvRet != NULL)
+ {
+ g_pAllocTbl->Add(pvRet);
+ }
+ }
+ }
+ else
+ {
+ // Allocate the memory
+ pvRet = g_lpVtblMalloc->Alloc(pThis, cb);
+ }
+
+ g_SpySem.Release();
+
+ return pvRet;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSpyMalloc_Realloc
+//
+// Synopsis: Reallocated local memory
+//
+// Arguments: [pv] -- original memory block
+// [cb] -- new size
+//
+// Returns: Pointer to new memory block
+//
+//--------------------------------------------------------------------------
+void *CSpyMalloc_Realloc(IMalloc *pThis, void * pv, ULONG cb)
+{
+ void *pvNew = 0;
+
+ if(pv != 0)
+ {
+ if(cb != 0)
+ {
+ g_SpySem.Request();
+
+ // If an IMallocSpy is active, call the pre method
+ if (g_pMallocSpy != 0)
+ {
+ void *pvTemp = 0;
+ ULONG j = 0;
+ BOOL fSpyed = g_pAllocTbl->Find(pv, &j);
+ ULONG cbAlloc = g_pMallocSpy->PreRealloc(pv, cb, &pvTemp, fSpyed);
+
+ // The pre method forces failure by returning 0
+ if (cbAlloc != 0)
+ {
+ //Reallocate the memory
+ pvTemp = g_lpVtblMalloc->Realloc(pThis, pvTemp, cbAlloc);
+
+ // Call the post method
+ pvNew = g_pMallocSpy->PostRealloc(pvTemp, fSpyed);
+
+ // Update the spy table.
+ if (pvNew != 0)
+ {
+ if (fSpyed)
+ {
+ g_pAllocTbl->Remove(pv);
+ }
+
+ g_pAllocTbl->Add(pvNew);
+ }
+ }
+ }
+ else
+ {
+ //Reallocate the memory.
+ pvNew = g_lpVtblMalloc->Realloc(pThis, pv, cb);
+ }
+
+ g_SpySem.Release();
+ }
+ else
+ {
+ //Treat this as a Free.
+ pThis->Free(pv);
+ }
+ }
+ else
+ {
+ //Treat this as an Alloc.
+ pvNew = pThis->Alloc(cb);
+ }
+
+ return pvNew;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSpyMalloc_Free
+//
+// Synopsis: release local memory
+//
+// Arguments: [pv] -- memory address
+//
+//--------------------------------------------------------------------------
+void __stdcall CSpyMalloc_Free(IMalloc *pThis, void * pv)
+{
+ if(pv != 0)
+ {
+ g_SpySem.Request();
+
+ // If an IMallocSpy is active, call the pre method
+ if (g_pMallocSpy)
+ {
+ ULONG j;
+ BOOL fSpyed = g_pAllocTbl->Find(pv, &j);
+ void *pvNew = g_pMallocSpy->PreFree(pv, fSpyed);
+
+ // Free the buffer
+ g_lpVtblMalloc->Free(pThis, pvNew);
+
+ // If an IMallocSpy is active, call the post method
+ g_pMallocSpy->PostFree(fSpyed);
+
+ // Update the spy table.
+ if (fSpyed)
+ {
+ g_pAllocTbl->Remove(pv);
+ }
+
+ if (g_pAllocTbl->m_cAllocations == 0 && g_fRevokePending)
+ {
+ CoRevokeMallocSpy();
+ }
+ }
+ else
+ {
+ // Free the buffer
+ g_lpVtblMalloc->Free(pThis, pv);
+ }
+
+ g_SpySem.Release();
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSpyMalloc_GetSize
+//
+// Synopsis: Return size of memory block
+//
+// Arguments: [pv] -- memory address
+//
+// Returns: If valid memory, the size of the block
+// Otherwise, 0
+//
+// Notes: The OLE spec requires that -1 be returned for
+// NULL pointers.
+//
+//--------------------------------------------------------------------------
+ULONG __stdcall CSpyMalloc_GetSize(IMalloc *pThis, void * pv)
+{
+ ULONG ulSize = (ULONG) -1;
+
+ if (pv != 0)
+ {
+ g_SpySem.Request();
+
+ // If an IMallocSpy is active, call the pre method
+ if (g_pMallocSpy)
+ {
+ ULONG j;
+ BOOL fSpyed = g_pAllocTbl->Find(pv, &j);
+ void *pvNew = g_pMallocSpy->PreGetSize(pv, fSpyed);
+
+ // Fetch the size of the allocation
+ ulSize = g_lpVtblMalloc->GetSize(pThis, pvNew);
+
+ // Call the post method
+ ulSize = g_pMallocSpy->PostGetSize(ulSize, fSpyed);
+ }
+ else
+ {
+ // Fetch the size of the allocation
+ ulSize = g_lpVtblMalloc->GetSize(pThis, pv);
+ }
+
+ g_SpySem.Release();
+ }
+
+ return ulSize;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSpyMalloc_DidAlloc
+//
+// Synopsis: Return whether this allocator allocated the block
+//
+// Arguments: [pv] -- memory address
+//
+// Returns: If allocated by this allocator, TRUE
+// Otherwise, FALSE
+//
+// Notes: The OLE spec requires that -1 be returned for
+// NULL pointers.
+//
+//--------------------------------------------------------------------------
+int __stdcall CSpyMalloc_DidAlloc(IMalloc *pThis, void * pv)
+{
+ int fDidAlloc = (ULONG) -1;
+
+ if (pv != 0)
+ {
+ g_SpySem.Request();
+
+ // If an IMallocSpy is active, call the pre method
+ if (g_pMallocSpy)
+ {
+ ULONG j;
+ BOOL fSpyed = g_pAllocTbl->Find(pv, &j);
+ void *pvNew = g_pMallocSpy->PreDidAlloc(pv, fSpyed);
+
+ // Check the allocation
+ fDidAlloc = g_lpVtblMalloc->DidAlloc(pThis, pvNew);
+
+ // Call the post method
+ fDidAlloc = g_pMallocSpy->PostDidAlloc(pv, fSpyed, fDidAlloc);
+ }
+ else
+ {
+ // Check the allocation
+ fDidAlloc = g_lpVtblMalloc->DidAlloc(pThis, pv);
+ }
+
+ g_SpySem.Release();
+ }
+
+ return fDidAlloc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSpyMalloc_HeapMinimize
+//
+// Synopsis: Minimize heap
+//
+//--------------------------------------------------------------------------
+void __stdcall CSpyMalloc_HeapMinimize(IMalloc *pThis)
+{
+ g_SpySem.Request();
+
+ // If an IMallocSpy is active, call the pre method
+ if (g_pMallocSpy)
+ {
+ g_pMallocSpy->PreHeapMinimize();
+
+ // Compact the heap
+ g_lpVtblMalloc->HeapMinimize(pThis);
+
+ // Call the post method
+ g_pMallocSpy->PostHeapMinimize();
+ }
+ else
+ {
+ // Compact the heap
+ g_lpVtblMalloc->HeapMinimize(pThis);
+ }
+
+ g_SpySem.Release();
+}
+
diff --git a/private/ole32/com/class/ole1guid.cxx b/private/ole32/com/class/ole1guid.cxx
new file mode 100644
index 000000000..da23dfa46
--- /dev/null
+++ b/private/ole32/com/class/ole1guid.cxx
@@ -0,0 +1,284 @@
+/*
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Ole1Guid.cpp
+
+Abstract:
+
+ This module converts 1.0 class names to GUIDs (CLSIDs).
+ See the ole2issues database (bug 318) for a description of this
+ whole mechanism.
+
+Author:
+
+ Jason Fuller (jasonful) 19-October-1992
+*/
+
+// ErikGav 31-Dec-93 Chicago port
+
+#include <ole2int.h>
+
+// CLSID_* declarations
+#include <ole1cls.h>
+
+#define STR_MAX 80
+ASSERTDATA
+
+typedef unsigned short HASH;
+
+typedef struct ENTRY
+{
+ LPCWSTR sz; // class name
+ const CLSID FAR* pclsid; // corresponding CLSID
+} ENTRY;
+
+
+// This is the map.
+// The +6 removes "CLSID_"
+// It does unnatural things with the pre-processor, but it ensures that
+// the map and ole1cls.h will always be in sync.
+
+// REVIEW OPTIMIZATION
+// If it is a problem that the strings in this map are in the data segment,
+// we can use yet more pre-processor tricks to define a code-segment LPCSTR
+// variable for each string, then put these variables in the map.
+
+static ENTRY rgentMap[] =
+{
+ #define DEFINE_OLE1GUID(clsid,x,xx,xxx,sz) sz, &clsid, /##/
+ #include "ole1cls.h"
+ #undef DEFINE_OLE1GUID
+
+ NULL, NULL
+
+};
+
+
+
+#pragma SEG(VerifyIs10Class)
+// verify name is ole1class; errors: CO_E_CLASSSTRING
+static INTERNAL VerifyIs10Class(LPCWSTR szOle1)
+{
+ HKEY hkey = NULL;
+ HKEY hkey2 = NULL;
+ HRESULT hresult = NOERROR;
+
+ if (ERROR_SUCCESS != RegOpenKey (HKEY_CLASSES_ROOT, (LPWSTR) szOle1, &hkey) ||
+ ERROR_SUCCESS != RegOpenKey (hkey, L"protocol\\StdFileEditing", &hkey2))
+ {
+ // This string is not an OLE 1 server, so we do not know
+ // what it is.
+ hresult = ReportResult (0, CO_E_CLASSSTRING, 0, 0);
+ }
+ if (hkey)
+ RegCloseKey (hkey);
+ if (hkey2)
+ RegCloseKey (hkey2);
+ return hresult;
+}
+
+
+
+#pragma SEG(Hash)
+// hash ole1 class name; errors: none
+static INTERNAL_(HASH) Hash(LPCWSTR sz)
+{
+ HASH hash = 0;
+ Assert (sizeof (HASH) == 2); // This is vital
+
+ while (*sz)
+ hash = 257 * hash + *sz++;
+
+ return hash;
+}
+
+
+
+#define RegCall(f) \
+ if ((f) != ERROR_SUCCESS) \
+ { \
+ CairoleDebugOut((DEB_WARN, \
+ "WriteToRegDb: 2.0 registration failed\n")); \
+ if (hkey) RegCloseKey (hkey); \
+ return ResultFromScode (REGDB_E_WRITEREGDB); \
+ }
+
+#pragma SEG(WriteToRegDb)
+// errors: REGDB_E_WRITEREGDB
+static INTERNAL WriteToRegDb
+ (LPCWSTR szOle1, // OLE1 class name e.g. "ExcelWorksheet"
+ LPCWSTR szClsid) // "{...0046}"
+{
+ WCHAR szKey [256];
+ WCHAR szUserName [256];
+ LONG cbUserName = 256;
+ HKEY hkey=NULL;
+
+ Assert (szClsid[0] == '{');
+ Assert (szOle1 [0] != '{');
+
+ // szOle1 = User type Name
+ // clsid = {...0046} <- write this
+ RegCall (RegOpenKey (HKEY_CLASSES_ROOT, (LPWSTR) szOle1, &hkey))
+ RegCall (RegQueryValue (hkey, NULL, szUserName, &cbUserName))
+ RegCall (RegSetValue (hkey, L"Clsid", REG_SZ, (LPWSTR) szClsid, lstrlenW(szClsid)))
+
+ if (0==lstrcmpW(szClsid, L"{00030003-0000-0000-C000-000000000046}"))
+ {
+ // Word
+ RegSetValue (hkey, L"PackageOnFileDrop", REG_SZ, (LPWSTR)NULL, 0);
+ }
+
+ RegCall (RegCloseKey (hkey))
+ hkey=NULL;
+
+ // write this:
+ // CLSID
+ // {...00046} = User Type Name
+ // Ole1Class = szOle1
+ // ProgID = szOle1
+ wsprintf (szKey, L"CLSID\\%ws", szClsid);
+ RegCall (RegSetValue (HKEY_CLASSES_ROOT, (LPWSTR) szKey, REG_SZ, szUserName,
+ (cbUserName/sizeof(WCHAR))-1))
+ RegCall (RegOpenKey (HKEY_CLASSES_ROOT, (LPWSTR) szKey, &hkey))
+ RegCall (RegSetValue (hkey, L"Ole1Class", REG_SZ, (LPWSTR) szOle1, lstrlenW(szOle1)))
+ RegCall (RegSetValue (hkey, L"ProgID", REG_SZ, (LPWSTR) szOle1, lstrlenW(szOle1)))
+ RegCall (RegCloseKey (hkey))
+ return NOERROR;
+}
+
+#undef RegCall
+
+#pragma SEG(Ole10_CLSIDFromString)
+
+// Ole10_CLSIDFromString
+//
+// This function must only be called when the CLSID is NOT in the reg db
+// (under key "Clsid")
+//
+// errors: CO_E_CLASSSTRING (not ole1 class); REGDB_E_WRITEREGDB (errors with reg.dat)
+//
+INTERNAL Ole10_CLSIDFromString
+ (LPCWSTR szOle1,
+ CLSID FAR* pclsid,
+ BOOL fForceAssign) // always assign a CLSID, even if not in reg db
+{
+ WCHAR szClsid[STR_MAX];
+ ENTRY FAR* pent;
+
+ *pclsid = CLSID_NULL;
+
+ #ifdef _DEBUG
+ {
+ // This function should not be called if the CLSID is in the reg db
+ HKEY hkey, hkey2;
+ if (ERROR_SUCCESS==RegOpenKey (HKEY_CLASSES_ROOT, szOle1, &hkey))
+ {
+ Assert (ERROR_SUCCESS != RegOpenKey (hkey, L"Clsid", &hkey2));
+ RegCloseKey (hkey);
+ }
+ }
+ #endif
+
+ // Look for class name in Map
+ for (pent = (ENTRY FAR*) rgentMap; pent->sz != NULL; pent++)
+ {
+ // Because atoms and reg db keys are case-insensitive, OLE 1.0
+ // was case insensitive. So let's be case-insensitive also.
+ if (0==lstrcmpiW(szOle1, pent->sz))
+ {
+ *pclsid = *pent->pclsid;
+ Verify(StringFromCLSID2 (*pent->pclsid, szClsid, STR_MAX) != 0);
+ break;
+ }
+ }
+
+ if (IsEqualGUID(*pclsid, CLSID_NULL))
+ {
+ HRESULT hresult;
+
+ if (!fForceAssign &&
+ (NOERROR != (hresult = VerifyIs10Class (szOle1))))
+ {
+ // This happens when trying to get a CLSID for a packaged
+ // object, e.g., trying to get a CLSID for "txtfile"
+ // because someone called GetClassFile("foo.txt").
+ // So do not assert
+ return hresult;
+ }
+
+
+ // Class name is not in our table, so make up a GUID by hashing
+ HASH hash = Hash (szOle1);
+ wsprintf (szClsid, L"{0004%02X%02X-0000-0000-C000-000000000046}",
+ LOBYTE(hash), HIBYTE(hash));
+ Verify(CLSIDFromString (szClsid, pclsid) == NOERROR);
+ }
+
+ Assert((!IsEqualGUID(*pclsid, CLSID_NULL)) &&
+ "About to write NULL GUID into registry");
+
+ HRESULT hresult = WriteToRegDb (szOle1, szClsid);
+ // If forcing the assignment of a CLSID even if the string
+ // is not in the reg db, then WriteToRegDb is allowed to fail.
+ return fForceAssign ? NOERROR : hresult;
+}
+
+#pragma SEG(Ole10_StringFromCLSID)
+
+// Ole10_StringFromCLSID
+//
+// Only call this function if the "Ole1Class" key is NOT yet in the reg db
+//
+// errors: E_UNEXPECTED (clsid not a known ole1 class)
+//
+INTERNAL Ole10_StringFromCLSID(
+ REFCLSID clsid,
+ LPWSTR szOut,
+ int cbMax)
+{
+ ENTRY FAR* pent;
+ LPWSTR szClsid = NULL;
+
+ // Look it up in Map
+ for (pent = (ENTRY FAR*) rgentMap; pent->sz != NULL; pent++)
+ {
+ if (IsEqualGUID(clsid, *pent->pclsid))
+ {
+ if (lstrlenW (pent->sz) +1 > cbMax)
+ {
+ // unlikely
+ return E_OUTOFMEMORY;
+ }
+ lstrcpyW (szOut, pent->sz);
+
+ if (NOERROR==StringFromCLSID (clsid, &szClsid))
+ {
+ // If the info had already been in the reg db, then
+ // this function wouldn't have been called. So write
+ // the info now. This happens when we a 1.0 object (and CLSID)
+ // in a 2.0 file comes from a machine where the server is
+ // registered to one where it is not.
+ WriteToRegDb (pent->sz, szClsid);
+ PubMemFree(szClsid);
+ }
+ return NOERROR;
+ }
+ }
+
+ // We could not find the CLSID.
+ // We could iterate through the reg db and assign CLSIDs to all 1.0
+ // servers that do not yet have a CLSID, until we find one that matches.
+ // We decided it is not worth doing this because if the server
+ // was in the reg db, it probably would have been assigned a CLSID
+ // already.
+ // If not found, it is a hashed CLSID for a server that
+ // is not in our map and has not been assigned a CLSID (perhaps
+ // because it does not exist on this machine).
+ return E_UNEXPECTED;
+}
+
+
diff --git a/private/ole32/com/class/ole1guid.h b/private/ole32/com/class/ole1guid.h
new file mode 100644
index 000000000..cc179f631
--- /dev/null
+++ b/private/ole32/com/class/ole1guid.h
@@ -0,0 +1,21 @@
+/* ole1guid.h
+
+ Contains prototypes for OLE10 class string <--> CLSID conversion
+ functions in ole1guid.cpp
+
+ These functions are to be called only if the information
+ is not available in the reg db.
+
+ Copyright (c) 1992 Microsoft Corporation
+*/
+
+
+INTERNAL Ole10_StringFromCLSID
+ (REFCLSID clsid,
+ LPWSTR szOut,
+ int cbMax);
+
+INTERNAL Ole10_CLSIDFromString
+ (LPCWSTR szOle1,
+ CLSID FAR* pclsid,
+ BOOL fForceAssign);
diff --git a/private/ole32/com/class/perfmnce.cxx b/private/ole32/com/class/perfmnce.cxx
new file mode 100644
index 000000000..da20db06b
--- /dev/null
+++ b/private/ole32/com/class/perfmnce.cxx
@@ -0,0 +1,286 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: perfmnce.cxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 3-06-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <olerem.h>
+
+#include "ole1guid.h"
+#ifndef _CHICAGO_
+#include <shrtbl.hxx> // CDllShrdTbl
+#endif // !_CHICAGO_
+#include <perfmnce.hxx>
+
+#ifdef _PERF_BUILD_
+
+PerfRg perfrg =
+{
+ 32,
+ {
+ { 0x0000, "LoadLibraryOle ", 0, 0, 0, 0 },
+ { 0x1000, "OleInitialize ", 0, 0, 0, 0 },
+ { 0x1000, "CoInitialize ", 0, 0, 0, 0 },
+ { 0x2300, "ChannelProcessInit ", 0, 0, 0, 0 },
+ { 0x2400, "ChannelThreadInit ", 0, 0, 0, 0 },
+ { 0x0000, "CreateFileMap ", 0, 0, 0, 0 },
+ { 0x0000, "CreateFileMapConvert", 0, 0, 0, 0 },
+ { 0x2500, "CheckAndStartScm ", 0, 0, 0, 0 },
+ { 0x0000, "EndScm ", 0, 0, 0, 0 },
+ { 0x0000, "ISLClassCacheList ", 0, 0, 0, 0 },
+ { 0x0000, "ISLCreateAllocator ", 0, 0, 0, 0 },
+ { 0x0000, "ISLInProcList ", 0, 0, 0, 0 },
+ { 0x0000, "ISLLocSrvList ", 0, 0, 0, 0 },
+ { 0x0000, "ISLScmRot ", 0, 0, 0, 0 },
+ { 0x2100, "InitClassCache ", 0, 0, 0, 0 },
+ { 0x0000, "InitRot ", 0, 0, 0, 0 },
+ { 0x0000, "InitSharedLists ", 0, 0, 0, 0 },
+ { 0x0000, "MDFDllMain ", 0, 0, 0, 0 },
+ { 0x0000, "ServiceListen ", 0, 0, 0, 0 },
+ { 0x2200, "ShrdTbl ", 0, 0, 0, 0 },
+ { 0x2000, "StartScm ", 0, 0, 0, 0 },
+ { 0x2510, "StartScmX1 ", 0, 0, 0, 0 },
+ { 0x2520, "StartScmX2 ", 0, 0, 0, 0 },
+ { 0x2530, "StartScmX3 ", 0, 0, 0, 0 },
+ { 0x2000, "ThreadInit ", 0, 0, 0, 0 },
+ { 0x0000, "CoUnitialzie ", 0, 0, 0, 0 },
+ { 0x0000, "DllMain ", 0, 0, 0, 0 },
+ { 0x2410, "RpcService ", 0, 0, 0, 0 },
+ { 0x2420, "RpcListen ", 0, 0, 0, 0 },
+ { 0x2430, "RpcReqProtseq ", 0, 0, 0, 0 },
+ { 0x2440, "ChannelControl ", 0, 0, 0, 0 },
+ { 0x0000, "27 ", 0, 0, 0, 0 }
+ }
+};
+
+
+class CPerformance : public IPerformance
+{
+public:
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+ // *** IPerformance methods ***
+ STDMETHOD (Init) (THIS_ );
+ STDMETHOD (Print) (THIS_ DWORD PrntDest);
+ STDMETHOD (Reset) (THIS_ );
+
+ CPerformance(PPerfRg pPFRg)
+ {
+ _pPerfRg = pPFRg;
+ }
+
+private:
+ ULONG _refs;
+ PPerfRg _pPerfRg;
+
+};
+
+
+STDMETHODIMP CPerformance::QueryInterface (REFIID riid, LPVOID FAR* ppvObj)
+{
+ if (IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppvObj = (IPerformance *) this;
+ AddRef();
+ return S_OK;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPerformance::AddRef
+//
+// Synopsis: increments reference count
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CPerformance::AddRef ()
+{
+ InterlockedIncrement( (long *) &_refs );
+ return _refs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPerformance::Release
+//
+// Synopsis: decrements reference count
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CPerformance::Release ()
+{
+ if (InterlockedDecrement( (long*) &_refs ) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return _refs;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPerformance::
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns:
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CPerformance::Print (DWORD PrntDest)
+{
+ DWORD i;
+ WORD j,k,l,m;
+ char szOutStr[256];
+ char szTabStr[33];
+ WORD wPos;
+
+ LARGE_INTEGER liFrequency;
+ QueryPerformanceFrequency(&liFrequency);
+
+ for (i= 0x0000; i <= 0xf000 ; i+=0x1000)
+ {
+ for (j= 0x0000; j <= 0x0fff ; j+=0x0100)
+ {
+ for (k= 0x0000; k <= 0x00ff ; k+=0x0010)
+ {
+ for (l= 0x0000; l <= 0x000f ; l+=0x0001)
+ {
+ wPos = ((WORD)i)|j|k|l;
+
+ szTabStr[5]= '\0';
+ szTabStr[4]= '\0.';
+ szTabStr[3]= '\0';
+ szTabStr[2]= '\0';
+ szTabStr[1]= '\0';
+ szTabStr[0]= '\0';
+
+ if (l)
+ {
+ szTabStr[3]= '.';
+ szTabStr[2]= '.';
+ szTabStr[1]= '.';
+ szTabStr[0]= '.';
+ }
+ else if (k)
+ {
+ szTabStr[2]= '.';
+ szTabStr[1]= '.';
+ szTabStr[0]= '.';
+ }
+ else if (j)
+ {
+ szTabStr[1]= '.';
+ szTabStr[0]= '.';
+ }
+ else if (i)
+ szTabStr[0]= '.';
+
+ for (m=0; m < 32 ; m++)
+ {
+ if ( _pPerfRg->rgPerfData[m].wPos
+ && _pPerfRg->rgPerfData[m].wPos == wPos)
+ {
+ LARGE_INTEGER liTime;
+ LARGE_INTEGER liTemp;
+
+ liTime.QuadPart = _pPerfRg->rgPerfData[m].liEnd.QuadPart - _pPerfRg->rgPerfData[m].liStart.QuadPart;
+ liTemp.QuadPart = liTime.QuadPart * 1000000;
+ liTemp.QuadPart /= liFrequency.QuadPart;
+ //if (liTemp.LowPart)
+ {
+ switch (PrntDest)
+ {
+ case Consol:
+ printf("%s %10luus -> %s\n",szTabStr,
+ liTemp.LowPart, _pPerfRg->rgPerfData[m].szName);
+ break;
+ case DebugTerminal:
+ default:
+ wsprintfA(szOutStr,"%s %luus -> %s\n", szTabStr, liTemp.LowPart, _pPerfRg->rgPerfData[m].szName);
+ OutputDebugString(szOutStr);
+ break;
+ }
+ }
+
+ }
+ }
+
+ }
+ }
+ }
+ }
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPerformance::
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns:
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CPerformance::Init (void)
+{
+ return NOERROR;
+}
+//+-------------------------------------------------------------------------
+//
+// Method: CPerformance::
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns:
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CPerformance::Reset (void)
+{
+ return NOERROR;
+}
+
+STDAPI CoGetPerformance(PPerformance *ppPerformance)
+{
+ if (ppPerformance )
+ {
+ *ppPerformance = (PPerformance) new CPerformance((PPerfRg) &perfrg);
+ }
+ return NOERROR;
+}
+#endif // !_PERF_BUILD_
+
diff --git a/private/ole32/com/class/tls.cxx b/private/ole32/com/class/tls.cxx
new file mode 100644
index 000000000..be3c337f8
--- /dev/null
+++ b/private/ole32/com/class/tls.cxx
@@ -0,0 +1,366 @@
+//+---------------------------------------------------------------
+//
+// File: tls.cxx
+//
+// Contents: Thread Local Storage initialization and cleanup.
+//
+// History: 18-Apr-94 CraigWi Split off of channelb.cxx
+// 06-Jul-94 BruceMa Support for CoGetCurrentProcess
+// 30-Jan-95 BruceMa DLL_PROCESS_DETACH can interrupt
+// DLL_THREAD_DETACH so delete pData
+// carefully
+//
+//----------------------------------------------------------------
+#include <ole2int.h>
+#ifdef DCOM
+#include <..\dcomrem\locks.hxx>
+#endif
+
+// Thread Local Storage index.
+#ifdef _CHICAGO_
+DWORD gTlsIndex;
+#endif
+
+// Heap Handle
+extern HANDLE g_hHeap;
+#define HEAP_SERIALIZE 0
+
+#if !defined(_CHICAGO_) // multiple shared heap support for docfiles
+#define MULTIHEAP
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Function: TLSAllocData
+//
+// Synopsis: Allocates the thread local storage block
+//
+// Returns: S_OK - allocated the data
+// E_OUTOFMEMORY - could not allocate the data
+//
+// History: 09-Aug-94 Rickhi commented
+//
+//--------------------------------------------------------------------------
+HRESULT COleTls::TLSAllocData(void)
+{
+#ifdef _CHICAGO_
+ Win4Assert(TlsGetValue(gTlsIndex) == 0);
+#endif
+ Win4Assert(g_hHeap != NULL);
+
+ _pData = (SOleTlsData *) HeapAlloc(g_hHeap, HEAP_SERIALIZE,
+ sizeof(SOleTlsData));
+
+ if (_pData)
+ {
+ // This avoids having to set most fields to NULL, 0, etc and
+ // is needed cause on debug builds memory is not guaranteed to
+ // be zeroed.
+
+ memset(_pData, 0, sizeof(SOleTlsData));
+
+ // fill in the non-zero values
+
+ _pData->dwFlags = OLETLS_LOCALTID;
+
+#ifdef _CHICAGO_
+ _pData->dwEndPoint = ENDPOINT_ID_INVALID;
+
+ // store the data ptr in TLS
+ if (TlsSetValue(gTlsIndex, _pData))
+ {
+ return S_OK;
+ }
+
+ // error, cleanup and fallthru to error exit
+ HeapFree(g_hHeap, HEAP_SERIALIZE, _pData);
+ _pData = NULL;
+#else
+ NtCurrentTeb()->ReservedForOle = _pData;
+ return S_OK;
+#endif
+ }
+
+ ComDebOut((DEB_ERROR, "TLSAllocData failed.\n"));
+ return E_OUTOFMEMORY;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: TLSGetLogicalThread
+//
+// Synopsis: gets the logical threadid of the current thread,
+// allocating one if necessary
+//
+// Returns: ptr to GUID
+// NULL if error
+//
+// History: 09-Aug-94 Rickhi commented
+//
+//--------------------------------------------------------------------------
+IID *TLSGetLogicalThread()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+
+ if (SUCCEEDED(hr))
+ {
+ if (!(tls->dwFlags & OLETLS_UUIDINITIALIZED))
+ {
+#ifdef _CHICAGO_
+ CoCreateAlmostGuid(&(tls->LogicalThreadId));
+#else
+ UuidCreate(&(tls->LogicalThreadId));
+#endif
+
+
+ // BUGBUG: in the end, this might fail since it requires writing
+ // to the registry. Is there a way we can compensate for those
+ // errors to avoid duplicates and yet never fail UuidCreate?
+
+ tls->dwFlags |= OLETLS_UUIDINITIALIZED;
+ }
+
+ return &(tls->LogicalThreadId);
+ }
+
+ return NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoThreadSpecificCleanup
+//
+// Synopsis: Called to perform cleanup on all this threads data
+// structures, and to call CoUninitialize() if needed.
+//
+// Could be called by DLL_THREAD_DETACH or DLL_PROCESS_DETACH
+//
+// History: 3-18-95 kevinro Created
+//
+//----------------------------------------------------------------------------
+void DoThreadSpecificCleanup()
+{
+ CairoleDebugOut((DEB_DLL | DEB_ITRACE,"_IN DoThreadSpecificCleanup\n"));
+
+#ifdef _CHICAGO_
+ SOleTlsData *pTls = (SOleTlsData *) TlsGetValue(gTlsIndex);
+#else
+ SOleTlsData *pTls = (SOleTlsData *) (NtCurrentTeb()->ReservedForOle);
+#endif
+
+ if (pTls == NULL)
+ {
+ // there is no TLS for this thread, so there can't be anything
+ // to cleanup.
+ return;
+ }
+
+ if (IsWOWThread() && IsWOWThreadCallable() && pTls->cComInits != 0)
+ {
+ // OLETHK32 needs a chance to prepare, here is where we tell it
+ // to fail any future callbacks.
+ g_pOleThunkWOW->PrepareForCleanup();
+ }
+
+ // Because of the DLL unload rules in NT we need to be careful
+ // what we do in clean up. We notify the routines with special
+ // behavior here.
+
+ pTls->dwFlags |= OLETLS_INTHREADDETACH;
+
+
+ while (pTls->cComInits != 0)
+ {
+ // cleanup per-thread initializations;
+ ComDebOut((DEB_WARN, "Unbalanced call to CoInitialize for thread %ld\n",
+ GetCurrentThreadId()));
+
+ CoUninitialize();
+ }
+
+ // reset the index so we dont find this data again.
+#ifdef _CHICAGO_
+ TlsSetValue(gTlsIndex, NULL);
+#else
+ NtCurrentTeb()->ReservedForOle = NULL;
+#endif
+
+
+#if defined(MULTIHEAP)
+ // Release the docfile shared memory allocator
+ if (pTls->pSmAllocator != NULL)
+ {
+ ((IMalloc *) pTls->pSmAllocator)->Release();
+ pTls->pSmAllocator = NULL;
+ }
+#endif
+
+ // Release the default cursor table
+ PrivMemFree(pTls->pDragCursors);
+
+ if (pTls->hwndDdeServer != NULL)
+ {
+ SSDestroyWindow(pTls->hwndDdeServer);
+ }
+
+ if (pTls->hwndDdeClient != NULL)
+ {
+ SSDestroyWindow(pTls->hwndDdeClient);
+ }
+
+#ifdef _CHICAGO_
+ if (pTls->hwndOleRpcNotify != NULL)
+ {
+ SSDestroyWindow(pTls->hwndOleRpcNotify);
+ }
+#endif
+
+ if (pTls->hwndClip != NULL)
+ {
+ SSDestroyWindow(pTls->hwndClip);
+ }
+
+#ifdef DCOM
+ if (pTls->pPreRegOids != NULL)
+ {
+ PrivMemFree(pTls->pPreRegOids);
+ }
+#endif
+
+ HeapFree(g_hHeap, HEAP_SERIALIZE, pTls);
+
+ ComDebOut((DEB_DLL | DEB_ITRACE,"OUT DoThreadSpecificCleanup\n"));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ThreadNotification
+//
+// Synopsis: Dll entry point
+//
+// Arguments: [hDll] -- a handle to the dll instance
+// [dwReason] -- the reason LibMain was called
+// [lpvReserved] - NULL - called due to FreeLibrary
+// - non-NULL - called due to process exit
+//
+// Returns: TRUE on success, FALSE otherwise
+//
+// Notes: other one time initialization occurs in ctors for
+// global objects
+//
+// WARNING: if we are called because of FreeLibrary, then we should do as
+// much cleanup as we can. If we are called because of process
+// termination, we should not do any cleanup, as other threads in
+// this process will have already been killed, potentially while
+// holding locks around resources.
+//
+// History: 09-Aug-94 Rickhi commented
+//
+//--------------------------------------------------------------------------
+STDAPI_(BOOL) ThreadNotification(HINSTANCE hDll, DWORD dwReason, LPVOID lpvReserved )
+{
+ switch (dwReason)
+ {
+ case DLL_THREAD_ATTACH:
+
+ // new thread is starting
+ ComDebOut((DEB_DLL,"DLL_THREAD_ATTACH:\n"));
+ break;
+
+ case DLL_THREAD_DETACH:
+
+ // Thread is exiting, clean up resources associated with threads.
+ ComDebOut((DEB_DLL,"DLL_THREAD_DETACH:\n"));
+
+ DoThreadSpecificCleanup();
+
+#ifdef DCOM
+ ASSERT_LOCK_RELEASED
+#endif
+ break;
+
+ case DLL_PROCESS_ATTACH:
+
+#ifdef _CHICAGO_
+ // Initial setup. Get a thread local storage index for use by OLE
+ gTlsIndex = TlsAlloc();
+
+ if (gTlsIndex == 0xffffffff)
+ {
+ Win4Assert("Could not get TLS Index.");
+ return FALSE;
+ }
+#endif // _CHICAGO_
+
+ break;
+
+ case DLL_PROCESS_DETACH:
+
+ if (NULL == lpvReserved)
+ {
+ // exiting because of FreeLibrary, so try to cleanup
+
+ //
+ // According the to the rules, OLETHK32 should have called over to
+ // remove the global pointer (used for testing the IsWOWxxx situations)
+ // before going away. It should have done this BEFORE this
+ // DLL_PROCESS_DETACH was dispatched.
+ //
+ Win4Assert(!(IsWOWProcess() && IsWOWThreadCallable()));
+
+ //
+ // DLL_PROCESS_DETACH is called when we unload. The thread that is
+ // currently calling has not done thread specific cleanup yet.
+ //
+ DoThreadSpecificCleanup();
+
+#ifdef _CHICAGO_
+ TlsFree(gTlsIndex);
+#endif // _CHICAGO_
+ }
+
+ break;
+ }
+
+ return TRUE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: TLSIsWOWThread
+//
+// Synopsis: indicates definitively if current thread is 16-bit WOW thread
+//
+// Returns: TRUE/FALSE
+//
+// History: 15-Nov-94 MurthyS Created
+//
+//--------------------------------------------------------------------------
+BOOLEAN TLSIsWOWThread()
+{
+ COleTls tls;
+
+ return((BOOLEAN) (tls->dwFlags & OLETLS_WOWTHREAD));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: TLSIsThreadDetaching
+//
+// Synopsis: indicates if thread cleanup is in progress
+//
+// Returns: TRUE/FALSE
+//
+// History: 29-Jan-95 MurthyS Created
+//
+//--------------------------------------------------------------------------
+BOOLEAN TLSIsThreadDetaching()
+{
+ COleTls tls;
+
+ return((BOOLEAN) (tls->dwFlags & OLETLS_INTHREADDETACH));
+}
+
diff --git a/private/ole32/com/class/tracelog.cxx b/private/ole32/com/class/tracelog.cxx
new file mode 100644
index 000000000..19004e1fd
--- /dev/null
+++ b/private/ole32/com/class/tracelog.cxx
@@ -0,0 +1,490 @@
+//+-------------------------------------------------------------------
+//
+// File: tracelog.cxx
+//
+// Contents: trace log implementation
+//
+// Classes: CTraceLog - class for logging traces
+// CTraceCall - class for logging one function call
+//
+// Functions: none
+//
+// History: 23-Aug-93 Rickhi Created
+//
+// Notes: The trace log is used to record call information in a
+// process global ring buffer. The information can be used
+// to assist debugging, by allowing you to see what events
+// have taken place that lead up to some problem, and also
+// to provide profiling the CairOLE subsystem.
+//
+// CODEWORK: add call nesting depth
+// add logical thread id
+// get input parms from ini file
+//
+//--------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#ifdef TRACELOG
+
+#include <tracelog.hxx>
+#include <stdlib.h>
+
+// these prototypes must be here because the cairo headers and Nt headers
+// conflict with each other, so i cant include the latter.
+
+extern "C" {
+#define NTAPI __stdcall // winnt
+
+LONG
+NTAPI
+NtQueryPerformanceCounter (
+ LARGE_INTEGER *PerformanceCounter,
+ LARGE_INTEGER *PerformanceFrequency
+ );
+
+LARGE_INTEGER
+NTAPI
+RtlLargeIntegerSubtract (
+ LARGE_INTEGER Minuend,
+ LARGE_INTEGER Subtrahend
+ );
+
+LARGE_INTEGER
+NTAPI
+RtlLargeIntegerDivide (
+ LARGE_INTEGER Dividend,
+ LARGE_INTEGER Divisor,
+ LARGE_INTEGER *Remainder
+ );
+
+LARGE_INTEGER
+NTAPI
+RtlExtendedIntegerMultiply (
+ LARGE_INTEGER Multiplicand,
+ LONG Multiplier
+ );
+
+} // extern "C"
+
+
+
+// globals
+
+DWORD sg_dwTraceFlag = 0x0; // what to trace
+CTraceLog *sg_pTraceLog = NULL; // ptr to log
+LARGE_INTEGER sg_liFreq; // counter frequency
+
+
+//------------------------------------------------------------------------
+//
+// function: MapFlagToName
+//
+// synopsis: returns an ascii name equivalent for the trace flag value
+//
+//------------------------------------------------------------------------
+
+CHAR * MapFlagToName(DWORD dwFlag)
+{
+ if (dwFlag & TRACE_RPC)
+ return "RPC";
+ else if (dwFlag & TRACE_MARSHAL)
+ return "MSH";
+ else if (dwFlag & TRACE_ACTIVATION)
+ return "ACT";
+ else if (dwFlag & TRACE_REGISTRY)
+ return "REG";
+ else if (dwFlag & TRACE_DLL)
+ return "DLL";
+ else if (dwFlag & TRACE_INITIALIZE)
+ return "INI";
+ else if (dwFlag & TRACE_CALLCONT)
+ return "CCT";
+ else if (dwFlag & TRACE_APP)
+ return "APP";
+ else
+ return "???";
+}
+
+
+
+//------------------------------------------------------------------------
+//
+// member: CTraceCall::CTraceCall
+//
+// synopsis: constructor is called on entry to each function that we wish
+// to trace. the constructor matches the trace flag passed in
+// against the global trace mask, and if a match is made then
+// an entry is made in the trace log for this function call.
+//
+//------------------------------------------------------------------------
+
+CTraceCall::CTraceCall(DWORD dwFlags, CHAR *pszMsg) :
+ _dwFlags(dwFlags),
+ _pszMsg(pszMsg)
+{
+ // compare the flag value with the global mask to determine if this
+ // call should be traced or not.
+ if ((_dwFlags & sg_dwTraceFlag) && sg_pTraceLog)
+ {
+ // trace the call
+ _dwThreadId = GetCurrentThreadId();
+
+ LARGE_INTEGER liEndTime, liFreq;
+ liEndTime.LowPart = 0;
+ liEndTime.HighPart = 0;
+
+ NtQueryPerformanceCounter(&_liStartTime, &liFreq);
+ sg_pTraceLog->TraceEntry(_dwFlags, _pszMsg, _dwThreadId, _liStartTime, liEndTime);
+ }
+}
+
+
+//------------------------------------------------------------------------
+//
+// member: CTraceCall::~CTraceCall
+//
+// synopsis: destructor is called class placed on the stack in each function that we wish to
+// trace. the constructor matches the trace flag passed in
+// against the global trace mask, and if a match is made then
+// an entry is made in the trace log for this function call.
+//
+//------------------------------------------------------------------------
+
+CTraceCall::~CTraceCall(void)
+{
+ // if we traced the entry, then we'll trace the exit too.
+ if ((_dwFlags & sg_dwTraceFlag) && sg_pTraceLog)
+ {
+ LARGE_INTEGER liEndTime, liFreq;
+ NtQueryPerformanceCounter(&liEndTime, &liFreq);
+ sg_pTraceLog->TraceEntry(_dwFlags, _pszMsg, _dwThreadId, liEndTime, _liStartTime);
+ }
+}
+
+
+//------------------------------------------------------------------------
+//
+// member: CTraceLog
+//
+// synopsis: constructor called at process entry time.
+//
+//------------------------------------------------------------------------
+
+CTraceLog::CTraceLog(void) :
+ _dwTraceFlag(0),
+ _pLogStart(NULL),
+ _pLogCurr(NULL),
+ _pLogEnd(NULL),
+ _fDump(TRUE),
+ _ulLevel(0)
+{
+ ULONG ulLogSize = 0;
+
+ // init the mutex semaphore
+ _mxs.Init();
+
+ // read the execution parameters from win.ini, or use defaults.
+ CHAR szRead[20];
+ GetProfileStringA("CairOLE", "LogFlags", "0", szRead, sizeof(szRead));
+ sscanf(szRead, "%li", &_dwTraceFlag);
+
+ if (_dwTraceFlag != 0)
+ {
+ GetProfileStringA("CairOLE", "LogSize", "1000", szRead, sizeof(szRead));
+ sscanf(szRead, "%li", &ulLogSize);
+
+ GetProfileStringA("CairOLE", "LogDump", "Y", szRead, sizeof(szRead));
+ _fDump = (_stricmp(szRead, "Y")) ? FALSE : TRUE;
+
+ if (ulLogSize > 0)
+ {
+ // allocate the logfile and set the pointers appropriately.
+ _pLogStart = (STraceEntry *) VirtualAlloc(NULL,
+ sizeof(STraceEntry)*ulLogSize,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ Win4Assert(_pLogStart);
+
+ _pLogCurr = _pLogStart;
+ _pLogEnd = _pLogStart + ulLogSize;
+
+ // clear the trace log
+ memset((BYTE *)_pLogStart, 0, ulLogSize*sizeof(STraceEntry));
+
+ // get the startup time
+ NtQueryPerformanceCounter(&_liStartTime, &sg_liFreq);
+
+ GetProfileStringA("CairOLE", "WaitForStart", "N", szRead, sizeof(szRead));
+ if (!_stricmp(szRead, "N"))
+ {
+ // start logging right away otherwise wait for
+ // start signal.
+ StartTrace("Auto Tracing Started");
+ }
+ }
+ }
+
+ CairoleDebugOut((DEB_ITRACE, "TraceLog: LogFlags=%ld LogSize=%ld LogDump=%ld\n",
+ sg_dwTraceFlag, ulLogSize, _fDump));
+}
+
+
+//------------------------------------------------------------------------
+//
+// member: ~CTraceLog
+//
+// synopsis: destructor called at process exit time.
+//
+//------------------------------------------------------------------------
+
+CTraceLog::~CTraceLog(void)
+{
+ // if the user requested logging to a file, do it now
+ if (_pLogStart)
+ {
+ if (_fDump)
+ {
+ LogToFile();
+ }
+
+ // delete the log file
+ VirtualFree(_pLogStart,0,MEM_RELEASE);
+ }
+}
+
+
+//------------------------------------------------------------------------
+//
+// member: TraceEntry
+//
+// synopsis: adds a function call entry to the log file
+//
+//------------------------------------------------------------------------
+
+void CTraceLog::TraceEntry(DWORD dwFlags, CHAR *pszMsg, DWORD dwThreadId,
+ LARGE_INTEGER liCurrTime, LARGE_INTEGER liStartTime)
+{
+ if (!_pLogStart)
+ return;
+
+ CLock lck(_mxs); // lock the log file while we play
+
+ // record an entry in the logfile to designate function entry
+
+ _pLogCurr->dwThreadId = dwThreadId;
+ _pLogCurr->dwFlags = dwFlags;
+ _pLogCurr->pszMsg = pszMsg;
+ _pLogCurr->liCurrTime = liCurrTime;
+ _pLogCurr->liStartTime = liStartTime;
+
+ if (liStartTime.HighPart == 0 && liStartTime.LowPart == 0)
+ {
+ _pLogCurr->fExit = FALSE;
+ _pLogCurr->ulLevel = _ulLevel++;
+ }
+ else
+ {
+ _pLogCurr->fExit = TRUE;
+ _pLogCurr->ulLevel = --_ulLevel;
+ }
+
+
+ // update logfile ptr to next entry
+
+ if (++_pLogCurr == _pLogEnd)
+ _pLogCurr = _pLogStart;
+}
+
+
+//------------------------------------------------------------------------
+//
+// member: LogToFile
+//
+// synopsis: Dumps the tracelog to a file.
+//
+//------------------------------------------------------------------------
+
+void CTraceLog::LogToFile(void)
+{
+ CairoleDebugOut((DEB_ITRACE, "Dumping TraceLog to file.\n"));
+
+ CLock lck(_mxs); // lock just for safety
+
+ // extract the program name from the command line and use it
+ // to generate a file name for the log file.
+
+ CHAR szFileName[MAX_PATH];
+ CHAR *pszNameStart = GetCommandLineA();
+ CHAR *pszNameEnd = pszNameStart;
+
+ while (*pszNameEnd &&
+ *pszNameEnd != ' ' &&
+ *pszNameEnd != '\t' &&
+ *pszNameEnd != '.')
+ pszNameEnd++;
+
+ ULONG ulLen = pszNameEnd-pszNameStart;
+ strncpy(szFileName, pszNameStart, ulLen);
+ szFileName[ulLen] = '\0';
+ strcat(szFileName, ".log");
+
+
+ // open the logging file
+
+ FILE *fpLog = fopen(szFileName, "at");
+ Win4Assert(fpLog && "Can't Open TraceLog File");
+ if (!fpLog)
+ return;
+
+
+ // print the title and column header
+ fprintf(fpLog, "\t\t%s\n\n", szFileName);
+ fprintf(fpLog, "Thread Elapsed Delta Call Flg D Function\n");
+
+
+ // loop, writing the entries. we start at the current pointer (which
+ // is currently the oldest entry in the logfile) and write each one.
+ // in case we have not yet wrapped the log, we skip any blank entries.
+
+ CHAR szBlank[MAX_PATH];
+ memset(szBlank, ' ', sizeof(szBlank));
+
+ STraceEntry *pEntry = _pLogCurr;
+ BOOL fFirst = TRUE;
+ LARGE_INTEGER liPrev;
+
+ do
+ {
+ // write the entry
+ if (pEntry->pszMsg)
+ {
+ // we want the first time delta to be zero, so liPrev gets set
+ // to the value of the first entry that we write.
+ if (fFirst)
+ liPrev = pEntry->liCurrTime;
+
+ // compute the time deltas
+ LARGE_INTEGER liElapsed = PerfDelta(pEntry->liCurrTime, _liStartTime);
+ LARGE_INTEGER liDeltaPrev = PerfDelta(pEntry->liCurrTime, liPrev);
+ LARGE_INTEGER liDeltaCall;
+
+ if (pEntry->fExit)
+ {
+ liDeltaCall = PerfDelta(pEntry->liCurrTime, pEntry->liStartTime);
+ }
+ else
+ {
+ liDeltaCall.LowPart = 0;
+ liDeltaCall.HighPart = 0;
+ }
+
+ // get the ascii name for the flag
+ CHAR *pszFlagName = MapFlagToName(pEntry->dwFlags);
+
+ // null terminate the blank padding string that prefixes the
+ // pszMsg. this gives the illusion of call nesting level in
+ // the output, by shifting the output right ulLevel characters.
+ szBlank[pEntry->ulLevel] = '\0';
+
+ fprintf(fpLog, "%6ld %10lu %10lu %10lu %s %c %s%s\n",
+ pEntry->dwThreadId,
+ liElapsed.LowPart,
+ liDeltaPrev.LowPart,
+ liDeltaCall.LowPart,
+ pszFlagName,
+ (pEntry->fExit) ? '<' : '>',
+ szBlank,
+ pEntry->pszMsg);
+
+ // restore the padding string
+ szBlank[pEntry->ulLevel] = ' ';
+
+ fFirst = FALSE;
+ liPrev = pEntry->liCurrTime;
+ }
+
+ // update the current pointer
+ if (++pEntry == _pLogEnd)
+ pEntry = _pLogStart;
+
+ } while (pEntry != _pLogCurr);
+
+
+ // close the logging file
+ fclose(fpLog);
+}
+
+
+//------------------------------------------------------------------------
+//
+// member: LogToDebug
+//
+// synopsis: dumps the trace log to the debugger
+//
+//------------------------------------------------------------------------
+
+void CTraceLog::LogToDebug(void)
+{
+ CairoleDebugOut((DEB_ITRACE, "Dumping TraceLog to Debugger.\n"));
+}
+
+
+//------------------------------------------------------------------------
+//
+// function: PerfDelta
+//
+// synopsis: computes the different between two Performace Counter values
+//
+//------------------------------------------------------------------------
+
+LARGE_INTEGER CTraceLog::PerfDelta(LARGE_INTEGER liNow, LARGE_INTEGER liStart)
+{
+ LARGE_INTEGER liDelta, liRemainder;
+
+ liDelta = RtlLargeIntegerSubtract (liNow, liStart);
+ liDelta = RtlExtendedIntegerMultiply (liDelta, 1000000);
+ liDelta = RtlLargeIntegerDivide (liDelta, sg_liFreq, &liRemainder);
+
+ return liDelta;
+}
+
+
+void CTraceLog::StartTrace(LPSTR pszMsg) // start log tracing
+{
+ CHAR szMsg[260];
+ strcpy(szMsg, "\n*** Start Trace\n");
+ strcat(szMsg, pszMsg);
+
+ sg_dwTraceFlag = _dwTraceFlag;
+
+ CTraceCall trc(0xffffffff, szMsg);
+}
+
+void CTraceLog::StopTrace(LPSTR pszMsg) // stop tracing
+{
+ CHAR szMsg[260];
+ strcpy(szMsg, "\n*** Stop Trace\n");
+ strcat(szMsg, pszMsg);
+
+ CTraceCall trc(0xffffffff, szMsg);
+
+ sg_dwTraceFlag = 0;
+}
+
+
+
+STDAPI StartTrace(LPSTR pszMsg)
+{
+ sg_pTraceLog->StartTrace(pszMsg);
+ return 0;
+}
+
+STDAPI StopTrace(LPSTR pszMsg)
+{
+ sg_pTraceLog->StopTrace(pszMsg);
+ return 0;
+}
+
+
+#endif // TRACELOG
diff --git a/private/ole32/com/coll/array_fv.ctt b/private/ole32/com/coll/array_fv.ctt
new file mode 100644
index 000000000..6fe5af791
--- /dev/null
+++ b/private/ole32/com/coll/array_fv.ctt
@@ -0,0 +1,85 @@
+////////////////////////////////////////////////////////////////////////////
+// class CArray<TYPE, ARG_TYPE> - an array containing 'TYPE' elements,
+// passed in parameters as ARG_TYPE
+//
+// NOTE: ARG_TYPE must be either an lvalue or a reference type; no pointers;
+// that is, the type of &ARG_TYPE must be the same as &TYPE.
+//
+////////////////////////////////////////////////////////////////////////////
+
+//$DECLARE_TEMPLATE
+
+////////////////////////////////////////////////////////////////////////////
+
+
+template<class TYPE, class ARG_TYPE>
+class FAR CArray
+{
+public:
+
+// Construction
+ CArray(DWORD memctx = MEMCTX_SAME) : m_afv(memctx, sizeof(TYPE)) { }
+ ~CArray() { }
+
+// Attributes
+ int GetSize() const
+ { return m_afv.GetSize(); }
+ int GetUpperBound() const
+ { return m_afv.GetSize()-1; }
+ BOOL SetSize(int nNewSize, int nGrowBy = -1)
+ { return m_afv.SetSize(nNewSize, nGrowBy); }
+ int GetSizeValue() const
+ { return m_afv.GetSizeValue(); }
+
+// Operations
+ // Clean up
+ void FreeExtra()
+ { m_afv.FreeExtra(); }
+
+ void RemoveAll()
+ { m_afv.SetSize(0); }
+
+ // return pointer to element; index must be in range
+ TYPE GetAt(int nIndex) const
+ { return *(TYPE FAR*)m_afv.GetAt(nIndex); }
+ TYPE FAR& ElementAt(int nIndex)
+ { return (TYPE FAR&)*(TYPE FAR*)m_afv.GetAt(nIndex); }
+
+ // overloaded operator helpers
+ TYPE operator[](int nIndex) const
+ { return GetAt(nIndex); }
+ TYPE FAR& operator[](int nIndex)
+ { return ElementAt(nIndex); }
+
+ // set element; index must be in range
+ void SetAt(int nIndex, ARG_TYPE value)
+ { m_afv.SetAt(nIndex, (LPVOID)&value); }
+
+ // find element given part of one; offset is offset into value; returns
+ // -1 if element not found; use IndexOf(NULL, cb, offset) to find zeros;
+ // will be optimized for appropriate value size and param combinations
+ int IndexOf(LPVOID pData, UINT cbData, UINT offset)
+ { return m_afv.IndexOf(pData, cbData, offset); }
+
+ // set/add element; Potentially growing the array; return FALSE/-1 if
+ // not possible (due to OOM)
+ BOOL SetAtGrow(int nIndex, ARG_TYPE value)
+ { return m_afv.SetAtGrow(nIndex, (LPVOID)&value); }
+ int Add(ARG_TYPE value)
+ { int nIndex = GetSize();
+ return SetAtGrow(nIndex, value) ? nIndex : -1;
+ }
+
+ // Operations that move elements around
+ BOOL InsertAt(int nIndex, ARG_TYPE value, int nCount = 1)
+ { return m_afv.InsertAt(nIndex, (LPVOID)&value, nCount); }
+ void RemoveAt(int nIndex, int nCount = 1)
+ { m_afv.RemoveAt(nIndex, nCount); }
+
+ void AssertValid() const
+ { m_afv.AssertValid(); }
+
+// Implementation
+private:
+ CArrayFValue m_afv;
+};
diff --git a/private/ole32/com/coll/array_fv.cxx b/private/ole32/com/coll/array_fv.cxx
new file mode 100644
index 000000000..bd4ffda9b
--- /dev/null
+++ b/private/ole32/com/coll/array_fv.cxx
@@ -0,0 +1,342 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: d:\nt\private\cairole\com\coll\array_fv.cxx
+//
+// Contents: Implementation of Array of values
+//
+// Classes: CArrayFValue
+//
+// Functions: CArrayFValue::CArrayFValue
+// CArrayFValue::~CArrayFValue
+// CArrayFValue::SetSize
+// CArrayFValue::FreeExtra
+// CArrayFValue::_GetAt
+// CArrayFValue::SetAt
+// CArrayFValue::SetAtGrow
+// CArrayFValue::InsertAt
+// CArrayFValue::RemoveAt
+// CArrayFValue::IndexOf
+// CArrayFValue::AssertValid
+//
+// History: 26-Jul-94 BruceMa Created this file header
+// 26-Jul-94 BruceMa Memory sift fix
+//
+//----------------------------------------------------------------------
+
+/////////////////////////////////////////////////////////////////////////////
+// NOTE: we allocate an array of 'm_nMaxSize' elements, but only
+// the current size 'm_nSize' contains properly initialized elements
+
+#include <ole2int.h>
+//#include <compobj.seg>
+#pragma SEG(array_fv)
+ASSERTDATA
+
+#include "array_fv.h"
+
+#include <limits.h>
+#define SIZE_T_MAX UINT_MAX /* max size for a size_t */
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma SEG(CArrayFValue_ctor)
+CArrayFValue::CArrayFValue(UINT cbValue)
+{
+ m_pData = NULL;
+ m_cbValue = cbValue;
+ m_nSize = m_nMaxSize = m_nGrowBy = 0;
+}
+
+#pragma SEG(CArrayFValue_dtor)
+CArrayFValue::~CArrayFValue()
+{
+ ASSERT_VALID(this);
+
+ PrivMemFree(m_pData);
+}
+
+// set new size; return FALSE if OOM
+
+#pragma SEG(CArrayFValue_SetSize)
+BOOL CArrayFValue::SetSize(int nNewSize, int nGrowBy /* = -1 */)
+{
+ ASSERT_VALID(this);
+ Assert(nNewSize >= 0);
+
+ if (nGrowBy != -1)
+ m_nGrowBy = nGrowBy; // set new size
+
+ if (nNewSize == 0)
+ {
+ // shrink to nothing
+ PrivMemFree(m_pData);
+ m_pData = NULL;
+ m_nSize = m_nMaxSize = 0;
+ }
+ else if (m_pData == NULL)
+ {
+ // create one with exact size
+ Assert((long)nNewSize * m_cbValue <= SIZE_T_MAX); // no overflow
+
+ m_pData = (BYTE FAR*)PrivMemAlloc(nNewSize * m_cbValue);
+ if (m_pData == NULL)
+ {
+ m_nSize = m_nMaxSize = 0;
+ return FALSE;
+ }
+
+ memset(m_pData, 0, nNewSize * m_cbValue); // zero fill
+ m_nSize = m_nMaxSize = nNewSize;
+ }
+ else if (nNewSize <= m_nMaxSize)
+ {
+ // it fits
+ if (nNewSize > m_nSize)
+ {
+ // initialize the new elements
+ memset(&m_pData[m_nSize * m_cbValue], 0, (nNewSize-m_nSize) * m_cbValue);
+ }
+ m_nSize = nNewSize;
+ }
+ else
+ {
+ // Otherwise grow array
+ int nNewMax;
+ if (nNewSize < m_nMaxSize + m_nGrowBy)
+ nNewMax = m_nMaxSize + m_nGrowBy; // granularity
+ else
+ nNewMax = nNewSize; // no slush
+
+ Assert((long)nNewMax * m_cbValue <= SIZE_T_MAX); // no overflow
+
+ BYTE FAR* pNewData = (BYTE FAR*)PrivMemAlloc(nNewMax * m_cbValue);
+ if (pNewData == NULL)
+ return FALSE;
+
+ // copy new data from old
+ memcpy(pNewData, m_pData, m_nSize * m_cbValue);
+
+ // construct remaining elements
+ Assert(nNewSize > m_nSize);
+ memset(&pNewData[m_nSize * m_cbValue], 0, (nNewSize-m_nSize) * m_cbValue);
+
+ // get rid of old stuff (note: no destructors called)
+ PrivMemFree(m_pData);
+ m_pData = pNewData;
+ m_nSize = nNewSize;
+ m_nMaxSize = nNewMax;
+ }
+ ASSERT_VALID(this);
+
+ return TRUE;
+}
+
+#pragma SEG(CArrayFValue_FreeExtra)
+void CArrayFValue::FreeExtra()
+{
+ ASSERT_VALID(this);
+
+ if (m_nSize != m_nMaxSize)
+ {
+ // shrink to desired size
+ Assert((long)m_nSize * m_cbValue <= SIZE_T_MAX); // no overflow
+
+ BYTE FAR* pNewData = (BYTE FAR*)PrivMemAlloc(m_nSize * m_cbValue);
+ if (pNewData == NULL)
+ return; // can't shrink; don't to anything
+
+ // copy new data from old
+ memcpy(pNewData, m_pData, m_nSize * m_cbValue);
+
+ // get rid of old stuff (note: no destructors called)
+ PrivMemFree(m_pData);
+ m_pData = pNewData;
+ m_nMaxSize = m_nSize;
+ }
+ ASSERT_VALID(this);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma SEG(CArrayFValue__GetAt)
+LPVOID CArrayFValue::_GetAt(int nIndex) const
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0 && nIndex < m_nSize);
+ return &m_pData[nIndex * m_cbValue];
+}
+
+#pragma SEG(CArrayFValue_SetAt)
+void CArrayFValue::SetAt(int nIndex, LPVOID pValue)
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0 && nIndex < m_nSize);
+
+ memcpy(&m_pData[nIndex * m_cbValue], pValue, m_cbValue);
+}
+
+#pragma SEG(CArrayFValue_SetAtGrow)
+BOOL CArrayFValue::SetAtGrow(int nIndex, LPVOID pValue)
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0);
+ if (nIndex >= m_nSize && !SetSize(nIndex+1))
+ return FALSE;
+
+ SetAt(nIndex, pValue);
+
+ return TRUE;
+}
+
+#pragma SEG(CArrayFValue_InsertAt)
+BOOL CArrayFValue::InsertAt(int nIndex, LPVOID pValue, int nCount /*=1*/)
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0); // will expand to meet need
+ Assert(nCount > 0); // zero or negative size not allowed
+
+ if (nIndex >= m_nSize)
+ {
+ // adding after the end of the array
+ if (!SetSize(nIndex + nCount)) // grow so nIndex is valid
+ return FALSE;
+ }
+ else
+ {
+ // inserting in the middle of the array
+ int nOldSize = m_nSize;
+ if (!SetSize(m_nSize + nCount)) // grow it to new size
+ return FALSE;
+
+ // shift old data up to fill gap
+ memmove(&m_pData[(nIndex+nCount) * m_cbValue],
+ &m_pData[nIndex * m_cbValue],
+ (nOldSize-nIndex) * m_cbValue);
+
+ // re-init slots we copied from
+ memset(&m_pData[nIndex * m_cbValue], 0, nCount * m_cbValue);
+ }
+
+ // insert new value in the gap
+ Assert(nIndex + nCount <= m_nSize);
+ while (nCount--)
+ memcpy(&m_pData[nIndex++ * m_cbValue], pValue, m_cbValue);
+
+ ASSERT_VALID(this);
+
+ return TRUE;
+}
+
+#pragma SEG(CArrayFValue_RemoveAt)
+void CArrayFValue::RemoveAt(int nIndex, int nCount /* = 1 */)
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0);
+ Assert(nIndex < m_nSize);
+ Assert(nCount >= 0);
+ Assert(nIndex + nCount <= m_nSize);
+
+ // just remove a range
+ int nMoveCount = m_nSize - (nIndex + nCount);
+ if (nMoveCount)
+ memcpy(&m_pData[nIndex * m_cbValue],
+ &m_pData[(nIndex + nCount) * m_cbValue],
+ nMoveCount * m_cbValue);
+ m_nSize -= nCount;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+#pragma SEG(CArrayFValue_IndexOf)
+// find element given part of one; offset is offset into value; returns
+// -1 if element not found; use IndexOf(NULL, cb, offset) to find zeros;
+// will be optimized for appropriate value size and param combinations
+int CArrayFValue::IndexOf(LPVOID pData, UINT cbData, UINT offset)
+{
+ Assert(offset <= m_cbValue);
+ Assert(cbData <= m_cbValue);
+ Assert((long)offset + cbData <= m_cbValue);
+ Assert(!IsBadReadPtr(pData, cbData));
+
+#ifdef LATER
+ if (cbData == sizeof(WORD) && m_cbValue == sizeof(WORD))
+ {
+ int iwRet;
+ _asm
+ {
+ push di
+ les di,pData ;* get value
+ mov ax,es:[di] ;* from *(WORD FAR*)pData
+ les di,this
+ mov cx,[di].m_nSize ;* get size (in WORDs) of array
+ les di,[di].m_pData ;* get ptr to WORD array
+ repne scasw ;* look for *(WORD FAR*)pData
+ jeq retcx ;* brif found
+ xor cx,cx ;* return -1
+ retcx:
+ dec cx
+ mov iwRet,cx
+ pop di
+ }
+
+ return iwRet;
+ }
+#endif
+ BYTE FAR* pCompare = m_pData + offset; // points to the value to compare
+ int nIndex = 0;
+
+ if (cbData == sizeof(WORD)) {
+ for (; nIndex < m_nSize; pCompare += m_cbValue, nIndex++)
+ {
+ if (*(WORD FAR*)pCompare == *(WORD FAR*)pData)
+ return nIndex;
+ }
+ } else if (cbData == sizeof(LONG)) {
+ for (; nIndex < m_nSize; pCompare += m_cbValue, nIndex++)
+ {
+ if (*(LONG FAR*)pCompare == *(LONG FAR*)pData)
+ return nIndex;
+ }
+ } else {
+ for (; nIndex < m_nSize; pCompare += m_cbValue, nIndex++)
+ {
+ if (memcmp(pCompare, pData, cbData) == 0)
+ return nIndex;
+ }
+ }
+
+ return -1;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+#pragma SEG(CArrayFValue_AssertValid)
+void CArrayFValue::AssertValid() const
+{
+#ifdef _DEBUG
+ if (m_pData == NULL)
+ {
+ Assert(m_nSize == 0);
+ Assert(m_nMaxSize == 0);
+ }
+ else
+ {
+ Assert(m_nSize <= m_nMaxSize);
+ Assert((long)m_nMaxSize * m_cbValue <= SIZE_T_MAX); // no overflow
+ Assert(!IsBadReadPtr(m_pData, m_nMaxSize * m_cbValue));
+ }
+
+ // some collections live as global variables in the libraries, but
+ // have their existance in some context. Also, we can't check shared
+ // collections since we might be checking the etask collection
+ // which would cause an infinite recursion.
+#endif //_DEBUG
+}
diff --git a/private/ole32/com/coll/daytona/makefile b/private/ole32/com/coll/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/coll/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/coll/daytona/sources b/private/ole32/com/coll/daytona/sources
new file mode 100644
index 000000000..15487139e
--- /dev/null
+++ b/private/ole32/com/coll/daytona/sources
@@ -0,0 +1,77 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= coll
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..\..\inc
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+
+SOURCES= \
+ ..\array_fv.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
+!include ..\sources.inc
diff --git a/private/ole32/com/coll/dirs b/private/ole32/com/coll/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/com/coll/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/com/coll/filelist.mk b/private/ole32/com/coll/filelist.mk
new file mode 100644
index 000000000..d83fa7ea5
--- /dev/null
+++ b/private/ole32/com/coll/filelist.mk
@@ -0,0 +1,54 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = coll.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES = .\plex.cxx \
+ .\array_fv.cxx \
+ .\map_kv.cxx
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PXXFILE =
+PFILE =
+
+CINC = $(CINC) -I..\inc $(LRPC)
+
+MTHREAD = 1
+
+MULTIDEPEND = MERGED
diff --git a/private/ole32/com/coll/makefile b/private/ole32/com/coll/makefile
new file mode 100644
index 000000000..e09078703
--- /dev/null
+++ b/private/ole32/com/coll/makefile
@@ -0,0 +1,24 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+!include $(CAIROLE)\com\makefile
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/com/coll/map_fkv.ctt b/private/ole32/com/coll/map_fkv.ctt
new file mode 100644
index 000000000..b7eab9248
--- /dev/null
+++ b/private/ole32/com/coll/map_fkv.ctt
@@ -0,0 +1,76 @@
+/////////////////////////////////////////////////////////////////////////////
+// class CMap - a mapping from fixed length 'KEY's to fixed size 'VALUE's.
+//
+// NOTE: ARG_KEY must be either an lvalue or a reference type; no pointers;
+// that is, the type of &ARG_KEY must be the same as &KEY.
+// Same for ARG_VALUE/VALUE.
+//
+// This template class uses the MapKeyToValue implementation in compobj.dll.
+/////////////////////////////////////////////////////////////////////////////
+
+//$DECLARE_TEMPLATE
+
+////////////////////////////////////////////////////////////////////////////
+
+
+template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE>
+class FAR CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>
+{
+public:
+ // Construction
+ CMap(DWORD memctx = MEMCTX_SAME, UINT nBlockSize=10)
+ : m_mkv(memctx, sizeof(VALUE), sizeof(KEY), nBlockSize) { }
+
+ // Attributes
+ // number of elements
+ int GetCount() const
+ { return m_mkv.GetCount(); }
+ BOOL IsEmpty() const
+ { return GetCount() == 0; }
+
+ // Lookup
+ BOOL Lookup(ARG_KEY key, VALUE FAR& value) const
+ { return m_mkv.Lookup((LPVOID)&key, sizeof(KEY), (LPVOID)&value); }
+
+ BOOL LookupHKey(HMAPKEY hKey, VALUE FAR& value) const
+ { return m_mkv.LookupHKey(hKey, (LPVOID)&value); }
+
+ BOOL LookupAdd(ARG_KEY key, VALUE FAR& value) const
+ { return m_mkv.LookupAdd((LPVOID)&key, sizeof(KEY), (LPVOID)&value); }
+
+ // Add/Delete
+ // add a new (key, value) pair
+ BOOL SetAt(ARG_KEY key, ARG_VALUE value)
+ { return m_mkv.SetAt((LPVOID)&key, sizeof(KEY), (LPVOID)&value); }
+ BOOL SetAtHKey(HMAPKEY hKey, ARG_VALUE value)
+ { return m_mkv.SetAtHKey(hKey, (LPVOID)&value); }
+
+ // removing existing (key, ?) pair
+ BOOL RemoveKey(ARG_KEY key)
+ { return m_mkv.RemoveKey((LPVOID)&key, sizeof(KEY)); }
+
+ BOOL RemoveHKey(HMAPKEY hKey)
+ { return m_mkv.RemoveHKey(hKey); }
+
+ void RemoveAll()
+ { m_mkv.RemoveAll(); }
+
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return m_mkv.GetStartPosition(); }
+
+ void GetNextAssoc(POSITION FAR& rNextPosition, KEY FAR& rKey, VALUE FAR& rValue) const
+ { m_mkv.GetNextAssoc(&rNextPosition, (LPVOID)&rKey, NULL, (LPVOID)&rValue); }
+
+ HMAPKEY GetHKey(ARG_KEY key) const
+ { return m_mkv.GetHKey((LPVOID)&key, sizeof(KEY)); }
+
+#ifdef _DEBUG
+ void AssertValid() const
+ { m_mkv.AssertValid(); }
+#endif
+
+private:
+ CMapKeyToValue m_mkv;
+};
diff --git a/private/ole32/com/coll/map_kv.cxx b/private/ole32/com/coll/map_kv.cxx
new file mode 100644
index 000000000..6e141e829
--- /dev/null
+++ b/private/ole32/com/coll/map_kv.cxx
@@ -0,0 +1,565 @@
+/////////////////////////////////////////////////////////////////////////////
+// class CMapKeyToValue - a mapping from 'KEY's to 'VALUE's, passed in as
+// pv/cb pairs. The keys can be variable length, although we optmizize the
+// case when they are all the same.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include <ole2int.h>
+//#include <compobj.seg>
+#pragma SEG(map_kv)
+
+#include "map_kv.h"
+
+#include "plex.h"
+ASSERTDATA
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+#pragma SEG(CMapKeyToValue_ctor)
+CMapKeyToValue::CMapKeyToValue(DWORD memctx, UINT cbValue, UINT cbKey,
+ int nBlockSize, LPFNHASHKEY lpfnHashKey, UINT nHashSize)
+{
+ Assert(nBlockSize > 0);
+
+ m_cbValue = cbValue;
+ m_cbKey = cbKey;
+ m_cbKeyInAssoc = cbKey == 0 ? sizeof(CKeyWrap) : cbKey;
+
+ m_pHashTable = NULL;
+ m_nHashTableSize = nHashSize;
+ m_lpfnHashKey = lpfnHashKey;
+
+ m_nCount = 0;
+ m_pFreeList = NULL;
+ m_pBlocks = NULL;
+ m_nBlockSize = nBlockSize;
+ if (memctx == MEMCTX_SAME)
+ memctx = CoMemctxOf(this);
+ m_memctx = memctx;
+ Assert(m_memctx != MEMCTX_UNKNOWN);
+}
+
+#pragma SEG(CMapKeyToValue_dtor)
+CMapKeyToValue::~CMapKeyToValue()
+{
+ ASSERT_VALID(this);
+ RemoveAll();
+ Assert(m_nCount == 0);
+}
+
+
+#pragma SEG(MKVDefaultHashKey)
+// simple, default hash function
+// REVIEW: need to check the value in this for GUIDs and strings
+STDAPI_(UINT) MKVDefaultHashKey(LPVOID pKey, UINT cbKey)
+{
+ UINT hash = 0;
+ BYTE FAR* lpb = (BYTE FAR*)pKey;
+
+ while (cbKey-- != 0)
+ hash = 257 * hash + *lpb++;
+
+ return hash;
+}
+
+
+#pragma SEG(CMapKeyToValue_InitHashTable)
+BOOL CMapKeyToValue::InitHashTable()
+{
+ ASSERT_VALID(this);
+ Assert(m_nHashTableSize > 0);
+
+ if (m_pHashTable != NULL)
+ return TRUE;
+
+ Assert(m_nCount == 0);
+
+ if ((m_pHashTable = (CAssoc FAR* FAR*)CoMemAlloc(m_nHashTableSize * sizeof(CAssoc FAR*), m_memctx, NULL)) == NULL)
+ return FALSE;
+
+ memset(m_pHashTable, 0, sizeof(CAssoc FAR*) * m_nHashTableSize);
+
+ ASSERT_VALID(this);
+
+ return TRUE;
+}
+
+
+#pragma SEG(CMapKeyToValue_RemoveAll)
+void CMapKeyToValue::RemoveAll()
+{
+ ASSERT_VALID(this);
+
+ // free all key values and then hash table
+ if (m_pHashTable != NULL)
+ {
+ // destroy assocs
+ for (UINT nHash = 0; nHash < m_nHashTableSize; nHash++)
+ {
+ register CAssoc FAR* pAssoc;
+ for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL;
+ pAssoc = pAssoc->pNext)
+ // assoc itself is freed by FreeDataChain below
+ FreeAssocKey(pAssoc);
+ }
+
+ // free hash table
+ CoMemFree(m_pHashTable, m_memctx);
+ m_pHashTable = NULL;
+ }
+
+ m_nCount = 0;
+ m_pFreeList = NULL;
+ m_pBlocks->FreeDataChain(m_memctx);
+ m_pBlocks = NULL;
+
+ ASSERT_VALID(this);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Assoc helpers
+// CAssoc's are singly linked all the time
+
+#pragma SEG(CMapKeyToValue_NewAssoc)
+CMapKeyToValue::CAssoc FAR*
+ CMapKeyToValue::NewAssoc(UINT hash, LPVOID pKey, UINT cbKey, LPVOID pValue)
+{
+ if (m_pFreeList == NULL)
+ {
+ // add another block
+ CPlex FAR* newBlock = CPlex::Create(m_pBlocks, m_memctx, m_nBlockSize, SizeAssoc());
+
+ if (newBlock == NULL)
+ return NULL;
+
+ // chain them into free list
+ register BYTE FAR* pbAssoc = (BYTE FAR*) newBlock->data();
+ // free in reverse order to make it easier to debug
+ pbAssoc += (m_nBlockSize - 1) * SizeAssoc();
+ for (int i = m_nBlockSize-1; i >= 0; i--, pbAssoc -= SizeAssoc())
+ {
+ ((CAssoc FAR*)pbAssoc)->pNext = m_pFreeList;
+ m_pFreeList = (CAssoc FAR*)pbAssoc;
+ }
+ }
+ Assert(m_pFreeList != NULL); // we must have something
+
+ CMapKeyToValue::CAssoc FAR* pAssoc = m_pFreeList;
+
+ // init all fields except pNext while still on free list
+ pAssoc->nHashValue = hash;
+ if (!SetAssocKey(pAssoc, pKey, cbKey))
+ return NULL;
+
+ SetAssocValue(pAssoc, pValue);
+
+ // remove from free list after successfully initializing it (except pNext)
+ m_pFreeList = m_pFreeList->pNext;
+ m_nCount++;
+ Assert(m_nCount > 0); // make sure we don't overflow
+
+ return pAssoc;
+}
+
+
+#pragma SEG(CMapKeyToValue_FreeAssoc)
+// free individual assoc by freeing key and putting on free list
+void CMapKeyToValue::FreeAssoc(CMapKeyToValue::CAssoc FAR* pAssoc)
+{
+ pAssoc->pNext = m_pFreeList;
+ m_pFreeList = pAssoc;
+ m_nCount--;
+ Assert(m_nCount >= 0); // make sure we don't underflow
+
+ FreeAssocKey(pAssoc);
+}
+
+
+#pragma SEG(CMapKeyToValue_GetAssocAt)
+// find association (or return NULL)
+CMapKeyToValue::CAssoc FAR*
+CMapKeyToValue::GetAssocAt(LPVOID pKey, UINT cbKey, UINT FAR& nHash) const
+{
+ if (m_lpfnHashKey)
+ nHash = (*m_lpfnHashKey)(pKey, cbKey) % m_nHashTableSize;
+ else
+ nHash = MKVDefaultHashKey(pKey, cbKey) % m_nHashTableSize;
+
+ if (m_pHashTable == NULL)
+ return NULL;
+
+ // see if it exists
+ register CAssoc FAR* pAssoc;
+ for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext)
+ {
+ if (CompareAssocKey(pAssoc, pKey, cbKey))
+ return pAssoc;
+ }
+ return NULL;
+}
+
+
+#pragma SEG(CMapKeyToValue_CompareAssocKey)
+BOOL CMapKeyToValue::CompareAssocKey(CAssoc FAR* pAssoc, LPVOID pKey2, UINT cbKey2) const
+{
+ LPVOID pKey1;
+ UINT cbKey1;
+
+ GetAssocKeyPtr(pAssoc, &pKey1, &cbKey1);
+ return cbKey1 == cbKey2 && memcmp(pKey1, pKey2, cbKey1) == 0;
+}
+
+
+#pragma SEG(CMapKeyToValue_SetAssocKey)
+BOOL CMapKeyToValue::SetAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const
+{
+ Assert(cbKey == m_cbKey || m_cbKey == 0);
+
+ if (m_cbKey == 0)
+ {
+ Assert(m_cbKeyInAssoc == sizeof(CKeyWrap));
+
+ // alloc, set size and pointer
+ if ((pAssoc->key.pKey = CoMemAlloc(cbKey, m_memctx, NULL)) == NULL)
+ return FALSE;
+
+ pAssoc->key.cbKey = cbKey;
+ }
+
+ LPVOID pKeyTo;
+
+ GetAssocKeyPtr(pAssoc, &pKeyTo, &cbKey);
+
+ memcpy(pKeyTo, pKey, cbKey);
+
+ return TRUE;
+}
+
+
+#pragma SEG(CMapKeyToValue_GetAssocKeyPtr)
+// gets pointer to key and its length
+void CMapKeyToValue::GetAssocKeyPtr(CAssoc FAR* pAssoc, LPVOID FAR* ppKey,UINT FAR* pcbKey) const
+{
+ if (m_cbKey == 0)
+ {
+ // variable length key; go indirect
+ *ppKey = pAssoc->key.pKey;
+ *pcbKey = pAssoc->key.cbKey;
+ }
+ else
+ {
+ // fixed length key; key in assoc
+ *ppKey = (LPVOID)&pAssoc->key;
+ *pcbKey = m_cbKey;
+ }
+}
+
+
+#pragma SEG(CMapKeyToValue_FreeAssocKey)
+void CMapKeyToValue::FreeAssocKey(CAssoc FAR* pAssoc) const
+{
+ if (m_cbKey == 0)
+ CoMemFree(pAssoc->key.pKey, m_memctx);
+}
+
+
+#pragma SEG(CMapKeyToValue_GetAssocValuePtr)
+void CMapKeyToValue::GetAssocValuePtr(CAssoc FAR* pAssoc, LPVOID FAR* ppValue) const
+{
+ *ppValue = (char FAR*)&pAssoc->key + m_cbKeyInAssoc;
+}
+
+
+#pragma SEG(CMapKeyToValue_GetAssocValue)
+void CMapKeyToValue::GetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const
+{
+ LPVOID pValueFrom;
+ GetAssocValuePtr(pAssoc, &pValueFrom);
+ Assert(pValue != NULL);
+ memcpy(pValue, pValueFrom, m_cbValue);
+}
+
+
+#pragma SEG(CMapKeyToValue_SetAssocValue)
+void CMapKeyToValue::SetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const
+{
+ LPVOID pValueTo;
+ GetAssocValuePtr(pAssoc, &pValueTo);
+ if (pValue == NULL)
+ memset(pValueTo, 0, m_cbValue);
+ else
+ memcpy(pValueTo, pValue, m_cbValue);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma SEG(CMapKeyToValue_Lookup)
+// lookup value given key; return FALSE if key not found; in that
+// case, the value is set to all zeros
+BOOL CMapKeyToValue::Lookup(LPVOID pKey, UINT cbKey, LPVOID pValue) const
+{
+ UINT nHash;
+ return LookupHKey((HMAPKEY)GetAssocAt(pKey, cbKey, nHash), pValue);
+}
+
+
+#pragma SEG(CMapKeyToValue_LookupHKey)
+// lookup value given key; return FALSE if NULL (or bad) key; in that
+// case, the value is set to all zeros
+BOOL CMapKeyToValue::LookupHKey(HMAPKEY hKey, LPVOID pValue) const
+{
+ // REVIEW: would like some way to verify that hKey is valid
+ register CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+ if (pAssoc == NULL)
+ {
+ memset(pValue, 0, m_cbValue);
+ return FALSE; // not in map
+ }
+
+ ASSERT_VALID(this);
+
+ GetAssocValue(pAssoc, pValue);
+ return TRUE;
+}
+
+
+#pragma SEG(CMapKeyToValue_LookupAdd)
+// lookup and if not found add; returns FALSE only if OOM; if added,
+// value added and pointer passed are set to zeros.
+BOOL CMapKeyToValue::LookupAdd(LPVOID pKey, UINT cbKey, LPVOID pValue) const
+{
+ if (Lookup(pKey, cbKey, pValue))
+ return TRUE;
+
+ // value set to zeros since lookup failed
+
+ return ((CMapKeyToValue FAR*)this)->SetAt(pKey, cbKey, NULL);
+}
+
+
+#pragma SEG(CMapKeyToValue_SetAt)
+// the only place new assocs are created; return FALSE if OOM;
+// never returns FALSE if keys already exists
+BOOL CMapKeyToValue::SetAt(LPVOID pKey, UINT cbKey, LPVOID pValue)
+{
+ UINT nHash;
+ register CAssoc FAR* pAssoc;
+
+ ASSERT_VALID(this);
+
+ if ((pAssoc = GetAssocAt(pKey, cbKey, nHash)) == NULL)
+ {
+ if (!InitHashTable())
+ // out of memory
+ return FALSE;
+
+ // it doesn't exist, add a new Association
+ if ((pAssoc = NewAssoc(nHash, pKey, cbKey, pValue)) == NULL)
+ return FALSE;
+
+ // put into hash table
+ pAssoc->pNext = m_pHashTable[nHash];
+ m_pHashTable[nHash] = pAssoc;
+
+ ASSERT_VALID(this);
+ }
+ else
+ {
+ SetAssocValue(pAssoc, pValue);
+ }
+
+ return TRUE;
+}
+
+
+#pragma SEG(CMapKeyToValue_SetAtHKey)
+// set existing hkey to value; return FALSE if NULL or bad key
+BOOL CMapKeyToValue::SetAtHKey(HMAPKEY hKey, LPVOID pValue)
+{
+ // REVIEW: would like some way to verify that hKey is valid
+ register CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+ if (pAssoc == NULL)
+ return FALSE; // not in map
+
+ ASSERT_VALID(this);
+
+ SetAssocValue(pAssoc, pValue);
+ return TRUE;
+}
+
+
+#pragma SEG(CMapKeyToValue_RemoveKey)
+// remove key - return TRUE if removed
+BOOL CMapKeyToValue::RemoveKey(LPVOID pKey, UINT cbKey)
+{
+ ASSERT_VALID(this);
+
+ if (m_pHashTable == NULL)
+ return FALSE; // nothing in the table
+
+ register CAssoc FAR* FAR* ppAssocPrev;
+ UINT i;
+ if (m_lpfnHashKey)
+ i = (*m_lpfnHashKey)(pKey, cbKey) % m_nHashTableSize;
+ else
+ i = MKVDefaultHashKey(pKey, cbKey) % m_nHashTableSize;
+
+ ppAssocPrev = &m_pHashTable[i];
+
+ CAssoc FAR* pAssoc;
+ for (pAssoc = *ppAssocPrev; pAssoc != NULL; pAssoc = pAssoc->pNext)
+ {
+ if (CompareAssocKey(pAssoc, pKey, cbKey))
+ {
+ // remove it
+ *ppAssocPrev = pAssoc->pNext; // remove from list
+ FreeAssoc(pAssoc);
+ ASSERT_VALID(this);
+ return TRUE;
+ }
+ ppAssocPrev = &pAssoc->pNext;
+ }
+ return FALSE; // not found
+}
+
+
+#pragma SEG(CMapKeyToValue_RemoveHKey)
+// remove key based on pAssoc (HMAPKEY)
+BOOL CMapKeyToValue::RemoveHKey(HMAPKEY hKey)
+{
+ ASSERT_VALID(this);
+
+ if (m_pHashTable == NULL)
+ return FALSE; // nothing in the table
+
+ // REVIEW: would like some way to verify that hKey is valid
+ CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+ if (pAssoc == NULL || pAssoc->nHashValue >= m_nHashTableSize)
+ // null hkey or bad hash value
+ return FALSE;
+
+ register CAssoc FAR* FAR* ppAssocPrev;
+ ppAssocPrev = &m_pHashTable[pAssoc->nHashValue];
+
+ while (*ppAssocPrev != NULL)
+ {
+ if (*ppAssocPrev == pAssoc)
+ {
+ // remove it
+ *ppAssocPrev = pAssoc->pNext; // remove from list
+ FreeAssoc(pAssoc);
+ ASSERT_VALID(this);
+ return TRUE;
+ }
+ ppAssocPrev = &(*ppAssocPrev)->pNext;
+ }
+
+ return FALSE; // not found (must have a screwed up list or passed
+ // a key from another list)
+}
+
+
+#pragma SEG(CMapKeyToValue_GetHKey)
+HMAPKEY CMapKeyToValue::GetHKey(LPVOID pKey, UINT cbKey) const
+{
+ UINT nHash;
+
+ ASSERT_VALID(this);
+
+ return (HMAPKEY)GetAssocAt(pKey, cbKey, nHash);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Iterating
+
+// for fixed length keys, copies key to pKey; pcbKey can be NULL;
+// for variable length keys, copies pointer to key to pKey; sets pcbKey.
+
+#pragma SEG(CMapKeyToValue_GetNextAssoc)
+void CMapKeyToValue::GetNextAssoc(POSITION FAR* pNextPosition,
+ LPVOID pKey, UINT FAR* pcbKey, LPVOID pValue) const
+{
+ ASSERT_VALID(this);
+
+ Assert(m_pHashTable != NULL); // never call on empty map
+
+ register CAssoc FAR* pAssocRet = (CAssoc FAR*)*pNextPosition;
+ Assert(pAssocRet != NULL);
+
+ if (pAssocRet == (CAssoc FAR*) BEFORE_START_POSITION)
+ {
+ // find the first association
+ for (UINT nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
+ if ((pAssocRet = m_pHashTable[nBucket]) != NULL)
+ break;
+ Assert(pAssocRet != NULL); // must find something
+ }
+
+ // find next association
+ CAssoc FAR* pAssocNext;
+ if ((pAssocNext = pAssocRet->pNext) == NULL)
+ {
+ // go to next bucket
+ for (UINT nBucket = pAssocRet->nHashValue + 1;
+ nBucket < m_nHashTableSize; nBucket++)
+ if ((pAssocNext = m_pHashTable[nBucket]) != NULL)
+ break;
+ }
+
+ // fill in return data
+ *pNextPosition = (POSITION) pAssocNext;
+
+ // fill in key/pointer to key
+ LPVOID pKeyFrom;
+ UINT cbKey;
+ GetAssocKeyPtr(pAssocRet, &pKeyFrom, &cbKey);
+ if (m_cbKey == 0)
+ // variable length key; just return pointer to key itself
+ *(void FAR* FAR*)pKey = pKeyFrom;
+ else
+ memcpy(pKey, pKeyFrom, cbKey);
+
+ if (pcbKey != NULL)
+ *pcbKey = cbKey;
+
+ // get value
+ GetAssocValue(pAssocRet, pValue);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma SEG(CMapKeyToValue_AssertValid)
+void CMapKeyToValue::AssertValid() const
+{
+#ifdef _DEBUG
+ Assert(m_cbKeyInAssoc == (m_cbKey == 0 ? sizeof(CKeyWrap) : m_cbKey));
+
+ Assert(m_nHashTableSize > 0);
+ Assert(m_nCount == 0 || m_pHashTable != NULL);
+
+ if (m_pHashTable != NULL)
+ Assert(!IsBadReadPtr(m_pHashTable, m_nHashTableSize * sizeof(CAssoc FAR*)));
+
+ if (m_lpfnHashKey)
+ Assert(!IsBadCodePtr((FARPROC)m_lpfnHashKey));
+
+ if (m_pFreeList != NULL)
+ Assert(!IsBadReadPtr(m_pFreeList, SizeAssoc()));
+
+ if (m_pBlocks != NULL)
+ Assert(!IsBadReadPtr(m_pBlocks, SizeAssoc() * m_nBlockSize));
+
+ // some collections live as global variables in the libraries, but
+ // have their existance in some context. Also, we can't check shared
+ // collections since we might be checking the etask collection
+ // which would cause an infinite recursion.
+ // REVIEW: Assert(m_memctx == MEMCTX_SHARED ||
+ // CoMemctxOf(this) == MEMCTX_UNKNOWN || CoMemctxOf(this) == m_memctx);
+#endif //_DEBUG
+}
+
diff --git a/private/ole32/com/coll/map_skv.ctt b/private/ole32/com/coll/map_skv.ctt
new file mode 100644
index 000000000..cf45fc61c
--- /dev/null
+++ b/private/ole32/com/coll/map_skv.ctt
@@ -0,0 +1,76 @@
+/////////////////////////////////////////////////////////////////////////////
+// class CMapStringTo - a mapping from string 'KEY's to fixed size 'VALUE's.
+//
+// NOTE: ARG_VALUE must be either an lvalue or a reference type; no pointers;
+// that is, the type of &ARG_VALUE must be the same as &VALUE.
+//
+// This template class uses the MapKeyToValue implementation in compobj.dll.
+/////////////////////////////////////////////////////////////////////////////
+
+//$DECLARE_TEMPLATE
+
+////////////////////////////////////////////////////////////////////////////
+
+
+template<class VALUE, class ARG_VALUE>
+class FAR CMapStringTo<VALUE, ARG_VALUE>
+{
+public:
+ // Construction
+ CMapStringTo(DWORD memctx = MEMCTX_SAME, UINT nBlockSize=10)
+ : m_mkv(memctx, sizeof(VALUE), 0, nBlockSize) { }
+
+ // Attributes
+ // number of elements
+ int GetCount() const
+ { return m_mkv.GetCount(); }
+ BOOL IsEmpty() const
+ { return GetCount() == 0; }
+
+ // Lookup
+ BOOL Lookup(LPWSTR pKey, VALUE FAR& value) const
+ { return m_mkv.Lookup(pKey, lstrlenW(pKey)*sizeof(WCHAR), &value); }
+
+ BOOL LookupHKey(HMAPKEY hKey, VALUE FAR& value) const
+ { return m_mkv.LookupHKey(hKey, &value); }
+
+ BOOL LookupAdd(LPWSTR pKey, VALUE FAR& value) const
+ { return m_mkv.LookupAdd(pKey, lstrlenW(pKey)*sizeof(WCHAR), &value); }
+
+
+ // Add/Delete
+ // add a new (key, value) pair
+ BOOL SetAt(LPWSTR pKey, ARG_VALUE value)
+ { return m_mkv.SetAt(pKey, lstrlenW(pKey)*sizeof(WCHAR), (LPVOID)&value); }
+ BOOL SetAtHKey(HMAPKEY hKey, ARG_VALUE value)
+ { return m_mkv.SetAtHKey(hKey, (LPVOID)&value); }
+
+ // removing existing (key, ?) pair
+ BOOL RemoveKey(LPWSTR pKey)
+ { return m_mkv.RemoveKey(pKey, lstrlenW(pKey)*sizeof(WCHAR)); }
+
+ BOOL RemoveHKey(HMAPKEY hKey)
+ { return m_mkv.RemoveHKey(hKey); }
+
+ void RemoveAll()
+ { m_mkv.RemoveAll(); }
+
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return m_mkv.GetStartPosition(); }
+
+ void GetNextAssoc(POSITION FAR& rNextPosition, LPWSTR FAR& pKey, VALUE FAR& rValue) const
+ { m_mkv.GetNextAssoc(&rNextPosition, (LPVOID)&pKey, NULL, (LPVOID)&rValue); }
+
+ HMAPKEY GetHKey(LPWSTR pKey) const
+ { return m_mkv.GetHKey(pKey, lstrlenW(pKey)*sizeof(WCHAR)); }
+
+#ifdef _DEBUG
+ void AssertValid() const
+ { m_mkv.AssertValid(); }
+#endif
+
+private:
+ CMapKeyToValue m_mkv;
+};
diff --git a/private/ole32/com/coll/plex.cxx b/private/ole32/com/coll/plex.cxx
new file mode 100644
index 000000000..deb48c43b
--- /dev/null
+++ b/private/ole32/com/coll/plex.cxx
@@ -0,0 +1,50 @@
+// This is a part of the Microsoft Foundation Classes C++ library.
+// Copyright (C) 1992 Microsoft Corporation
+// All rights reserved.
+//
+// This source code is only intended as a supplement to the
+// Microsoft Foundation Classes Reference and Microsoft
+// QuickHelp documentation provided with the library.
+// See these sources for detailed information regarding the
+// Microsoft Foundation Classes product.
+
+#include <ole2int.h>
+//#include <compobj.seg>
+#pragma SEG(plex)
+
+#include "plex.h"
+ASSERTDATA
+
+// Collection support
+#ifdef OLE_COLL_SEG
+#pragma code_seg(OLE_COLL_SEG)
+#endif
+
+
+#pragma SEG(CPlex_Create)
+CPlex FAR* CPlex::Create(CPlex FAR* FAR& pHead, DWORD mp, UINT nMax, UINT cbElement)
+{
+ CairoleAssert(nMax > 0 && cbElement > 0);
+ CPlex FAR* p = (CPlex FAR*)CoMemAlloc(sizeof(CPlex) + nMax * cbElement, mp, NULL);
+ if (p == NULL)
+ return NULL;
+
+ p->nMax = nMax;
+ p->nCur = 0;
+ p->pNext = pHead;
+ pHead = p; // change head (adds in reverse order for simplicity)
+ return p;
+}
+
+#pragma SEG(CPlex_FreeDataChain)
+void CPlex::FreeDataChain(DWORD mp) // free this one and links
+{
+ CPlex FAR* pThis;
+ CPlex FAR* pNext;
+
+ for (pThis = this; pThis != NULL; pThis = pNext) {
+ pNext = pThis->pNext;
+ pThis->pNext = NULL; // So compiler won't do nasty optimizations
+ CoMemFree(pThis, mp);
+ }
+}
diff --git a/private/ole32/com/coll/sources.inc b/private/ole32/com/coll/sources.inc
new file mode 100644
index 000000000..8b554d1b8
--- /dev/null
+++ b/private/ole32/com/coll/sources.inc
@@ -0,0 +1,3 @@
+#
+# Additional lines for the sources files
+#
diff --git a/private/ole32/com/dcomidl/daytona/makefile b/private/ole32/com/dcomidl/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/dcomidl/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/dcomidl/daytona/makefile.inc b/private/ole32/com/dcomidl/daytona/makefile.inc
new file mode 100644
index 000000000..c41aa3fa2
--- /dev/null
+++ b/private/ole32/com/dcomidl/daytona/makefile.inc
@@ -0,0 +1,4 @@
+#just use a common makeidl.inc for all platforms
+DEST_TREE=daytona
+
+!include ..\makeidl.inc
diff --git a/private/ole32/com/dcomidl/daytona/sources b/private/ole32/com/dcomidl/daytona/sources
new file mode 100644
index 000000000..2c3cb17ed
--- /dev/null
+++ b/private/ole32/com/dcomidl/daytona/sources
@@ -0,0 +1,69 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= idl
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..;
+INCLUDES= $(INCLUDES);$(BASEDIR)\public\sdk\inc;
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -I$(BASEDIR)\private\dcomidl
+
+SOURCES= \
+ ..\empty.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+NTTARGETFILE0=allidl
+
+!include ..\sources.inc
+SYNCHRONIZE_BLOCK=1
diff --git a/private/ole32/com/dcomidl/dirs b/private/ole32/com/dcomidl/dirs
new file mode 100644
index 000000000..80cd267ad
--- /dev/null
+++ b/private/ole32/com/dcomidl/dirs
@@ -0,0 +1,37 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ daytona \
+
diff --git a/private/ole32/com/dcomidl/dscm.idl b/private/ole32/com/dcomidl/dscm.idl
new file mode 100644
index 000000000..6eb99a90f
--- /dev/null
+++ b/private/ole32/com/dcomidl/dscm.idl
@@ -0,0 +1,126 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995.
+//
+// File:
+// dscm.idl
+//
+// Contents:
+// Definition of private COM interface between ole32.dll
+// and the SCM.
+//
+// History:
+//
+//--------------------------------------------------------------------------
+[
+ uuid(00000136-0000-0000-C000-000000000046),
+ version(0.0),
+ pointer_default(unique)
+#ifndef RAW
+ ,object
+#endif
+]
+
+interface IDSCM
+#ifndef RAW
+ : IUnknown
+#endif
+{
+#ifndef DO_NO_IMPORTS
+ import "iface.idl";
+ import "wtypes.idl";
+ import "objidl.idl";
+ import "obase.idl";
+#endif
+ #include "comhndl.h"
+
+ COM_DEFINES(IDSCM)
+
+ //
+ // Clsid - CLSID to activate
+ // pServerInfo - Location/Security info specified by client
+ // pwszWinstaDesktop- Client's winsta\desktop
+ // ClsContext - Class context requested
+ // ProcessSignature - Client's process reference for rpcss
+ // bDynamicSecurity - Client's winsta\desktop and id should not be cached
+ //
+ typedef struct _ACTIVATION_INFO
+ {
+ const GUID * Clsid;
+ COSERVERINFO * pServerInfo;
+ [string] WCHAR *pwszWinstaDesktop;
+ DWORD ClsContext;
+ DWORD ProcessSignature;
+ BOOL bDynamicSecurity;
+ } ACTIVATION_INFO;
+
+ HRESULT SCMGetClassObject(
+ COM_HANDLE
+ [in] ACTIVATION_INFO * pActivationInfo,
+ [in] IID * pIID,
+
+ //
+ // OR piggyback of ClientResolveOXID.
+ //
+ [in] long Apartment,
+ [out] OXID * pOxidServer,
+ [out] DUALSTRINGARRAY ** ppServerORBindings,
+ [out] OXID_INFO * pOxidInfo,
+ [out] MID * pLocalMidOfRemote,
+
+ // ClassFactory interface data.
+ [out] MInterfacePointer ** ppIDClassFactory
+ );
+
+ HRESULT SCMCreateInstance(
+ COM_HANDLE
+ [in] ACTIVATION_INFO * pActivationInfo,
+
+ [in] DWORD Interfaces,
+ [in,size_is(Interfaces)] IID * pIIDs,
+
+ //
+ // OR piggyback of ClientResolveOXID.
+ //
+ [in] long Apartment,
+ [out] OXID * pOxidServer,
+ [out] DUALSTRINGARRAY ** ppServerORBindings,
+
+ [out] OXID_INFO * pOxidInfo,
+ [out] MID * pLocalMidOfRemote,
+
+ // Interface data and results.
+ [out,size_is(Interfaces)] MInterfacePointer ** ppInterfaceData,
+ [out,size_is(Interfaces)] HRESULT * pResults
+ );
+
+ HRESULT SCMGetPersistentInstance(
+ COM_HANDLE
+ [in] ACTIVATION_INFO * pActivationInfo,
+
+ [in, string, unique] WCHAR * pwszPath,
+ [in, unique] MInterfacePointer *pIFDStorage,
+ [in] DWORD FileMode,
+ [in] BOOL FileWasOpened,
+
+ [in] DWORD Interfaces,
+ [in,size_is(Interfaces)] IID * pIIDs,
+
+ //
+ // OR piggyback of ClientResolveOXID.
+ //
+ [in] long Apartment,
+ [out] OXID * pOxidServer,
+ [out] DUALSTRINGARRAY ** ppServerORBindings,
+
+ [out] OXID_INFO * pOxidInfo,
+ [out] MID * pLocalMidOfRemote,
+
+ // Interface data and results.
+ [out] BOOL * pFoundInROT,
+ [out,size_is(Interfaces)] MInterfacePointer ** ppInterfaceData,
+ [out,size_is(Interfaces)] HRESULT * pResults
+ );
+}
+
diff --git a/private/ole32/com/dcomidl/empty.cxx b/private/ole32/com/dcomidl/empty.cxx
new file mode 100644
index 000000000..3f2ff2d6c
--- /dev/null
+++ b/private/ole32/com/dcomidl/empty.cxx
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/private/ole32/com/dcomidl/filelist.mk b/private/ole32/com/dcomidl/filelist.mk
new file mode 100644
index 000000000..99ae875f5
--- /dev/null
+++ b/private/ole32/com/dcomidl/filelist.mk
@@ -0,0 +1,90 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES =
+
+IDLFILES = \
+ .\drot.idl \
+ .\getif.idl \
+ .\ichnl.idl \
+ .\iface.idl \
+ .\objsrv.idl \
+ .\osrot.idl \
+ .\scm.idl \
+
+IDLUSE = SSWITCH
+
+CFILES = \
+ .\drot_c.c \
+ .\drot_x.c \
+ .\drot_s.c \
+ .\drot_y.c \
+ .\drot_z.c \
+ .\getif_c.c \
+ .\getif_x.c \
+ .\getif_s.c \
+ .\getif_y.c \
+ .\getif_z.c \
+ .\ichnl_c.c \
+ .\ichnl_x.c \
+ .\ichnl_s.c \
+ .\ichnl_y.c \
+ .\ichnl_z.c \
+ .\objsrv_c.c \
+ .\objsrv_x.c \
+ .\objsrv_s.c \
+ .\objsrv_y.c \
+ .\objsrv_z.c \
+ .\osrot_c.c \
+ .\osrot_x.c \
+ .\osrot_s.c \
+ .\osrot_y.c \
+ .\osrot_z.c \
+ .\scm_c.c \
+ .\scm_x.c \
+ .\scm_s.c \
+ .\scm_y.c \
+ .\scm_z.c \
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PXXFILE =
+PFILE =
+
+
+CINC = $(CINC) -I$(CARIOLE)\h -I$(COMMON)\types
+
+MTHREAD = 1
+
+MULTIDEPEND = MERGED
diff --git a/private/ole32/com/dcomidl/getif.idl b/private/ole32/com/dcomidl/getif.idl
new file mode 100644
index 000000000..f0ee5246e
--- /dev/null
+++ b/private/ole32/com/dcomidl/getif.idl
@@ -0,0 +1,44 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: getif.idl
+//
+// Contents: Definition of private RPC interface to an Object Server
+// to get an interface attached to a window.
+//
+// History: 29-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+[ uuid(00000135-0000-0000-C000-000000000046),
+ version(0.0),
+ pointer_default(unique),
+ object
+]
+
+interface IInterfaceFromWindowProp : IUnknown
+{
+#ifndef DO_NO_IMPORTS
+ import "iface.idl";
+ import "unknwn.idl";
+ import "objidl.idl";
+#endif
+
+ HRESULT GetInterfaceFromWindowProp(
+ [in] DWORD hWnd,
+ [in] REFIID riid,
+ [out, iid_is(riid)] IUnknown **ppunk,
+ [in, string] WCHAR *pwszPropertyName );
+
+ HRESULT PrivDragDrop(
+ [in] DWORD hWnd,
+ [in, unique] InterfaceData *pIFDDataObject,
+ [in] DWORD dop,
+ [in] DWORD grfKeyState,
+ [in] POINTL pt,
+ [in, out, unique] DWORD *pdwEffect,
+ [in] DWORD dwSmId,
+ [in] IDataObject *pRealDataObject,
+ [in] DWORD hwndSource );
+}
diff --git a/private/ole32/com/dcomidl/host.idl b/private/ole32/com/dcomidl/host.idl
new file mode 100644
index 000000000..2b34d5227
--- /dev/null
+++ b/private/ole32/com/dcomidl/host.idl
@@ -0,0 +1,33 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: host.idl
+//
+// Contents: Definition of private ORPC interface between apartments.
+// Used to activate an inproc dll of one threading model from
+// an apartment of a different threading model.
+//
+// History: 04-Mar-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+[ uuid(00000141-0000-0000-C000-000000000046),
+ pointer_default(unique),
+ object
+]
+
+interface IDLLHost : IUnknown
+{
+#ifndef DO_NO_IMPORTS
+ import "iface.idl";
+ import "unknwn.idl";
+ import "objidl.idl";
+#endif
+
+ HRESULT DllGetClassObject(
+ [in] DWORD pfnGetClassObject,
+ [in] REFCLSID rclsid,
+ [in] REFIID riid,
+ [out, iid_is(riid)] IUnknown **ppunk);
+}
diff --git a/private/ole32/com/dcomidl/irot.acf b/private/ole32/com/dcomidl/irot.acf
new file mode 100644
index 000000000..a48103248
--- /dev/null
+++ b/private/ole32/com/dcomidl/irot.acf
@@ -0,0 +1,24 @@
+[ implicit_handle(handle_t any_handle) ] interface IROT
+
+{
+ IrotRegister(
+ [comm_status, fault_status] prpcstat);
+
+ IrotRevoke(
+ [comm_status, fault_status] prpcstat);
+
+ IrotIsRunning(
+ [comm_status, fault_status] prpcstat);
+
+ IrotGetObject(
+ [comm_status, fault_status] prpcstat);
+
+ IrotNoteChangeTime(
+ [comm_status, fault_status] prpcstat);
+
+ IrotGetTimeOfLastChange(
+ [comm_status, fault_status] prpcstat);
+
+ IrotEnumRunning(
+ [comm_status, fault_status] prpcstat);
+}
diff --git a/private/ole32/com/dcomidl/irot.idl b/private/ole32/com/dcomidl/irot.idl
new file mode 100644
index 000000000..3b2a0a86d
--- /dev/null
+++ b/private/ole32/com/dcomidl/irot.idl
@@ -0,0 +1,108 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: irot.idl
+//
+// Contents: Definition of private RPC interface between compobj.dll
+// and the SCM that implements the ROT.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+[ uuid(B9E79E60-3D52-11CE-AAA1-00006901293F),
+ version(0.2),
+ pointer_default(unique) ]
+
+interface IROT
+{
+ import "iface.idl";
+
+#pragma midl_echo(" ")
+#pragma midl_echo("//------------------------")
+#pragma midl_echo("// Invalid Key for SCM Reg")
+#pragma midl_echo("//------------------------")
+#pragma midl_echo("#define SCMREG_INVALID_ENTRY_LOC 0xFFFFFFFF")
+#pragma midl_echo(" ")
+
+ typedef [context_handle] void *PHPROCESS;
+
+ typedef struct _SCMREGKEY
+ {
+ DWORD dwEntryLoc;
+ DWORD dwScmId;
+ } SCMREGKEY;
+
+ typedef struct _MnkEqBuf
+ {
+ DWORD cdwSize;
+ [size_is(cdwSize)]
+ BYTE abEqData[];
+ } MNKEQBUF;
+
+ typedef struct _MkInterfaceList
+ {
+ DWORD dwSize;
+ [size_is(dwSize)]
+ InterfaceData *apIFDList[];
+ } MkInterfaceList;
+
+ HRESULT IrotRegister(
+ [in] handle_t hRpc,
+ [in] PHPROCESS phProcess,
+ [in,unique,string] WCHAR *pwszWinstaDesktop,
+ [in] MNKEQBUF *pmkeqbuf,
+ [in] InterfaceData *pifdObject,
+ [in] InterfaceData *pifdObjectName,
+ [in] FILETIME *pfiletime,
+ [in] DWORD dwProcessId,
+ [in,unique,string] WCHAR *pwszServerExe,
+ [out] SCMREGKEY *psrkRegister,
+ [out] error_status_t *prpcstat);
+
+ HRESULT IrotRevoke(
+ [in] handle_t hRpc,
+ [in] SCMREGKEY *psrkRegister,
+ [in] BOOL fServerRevoke,
+ [out] InterfaceData **pifdObject,
+ [out] InterfaceData **pifdName,
+ [out] error_status_t *prpcstat);
+
+ HRESULT IrotIsRunning(
+ [in] handle_t hRpc,
+ [in] PHPROCESS phProcess,
+ [in,unique,string] WCHAR *pwszWinstaDesktop,
+ [in] MNKEQBUF *pmkeqbuf);
+
+ HRESULT IrotGetObject(
+ [in] handle_t hRpc,
+ [in] PHPROCESS phProcess,
+ [in,unique,string] WCHAR *pwszWinstaDesktop,
+ [in] DWORD dwProcessId,
+ [in] MNKEQBUF *pmkeqbuf,
+ [out] SCMREGKEY *psrkRegister,
+ [out] InterfaceData **pifdObject,
+ [out] error_status_t *prpcstat);
+
+ HRESULT IrotNoteChangeTime(
+ [in] handle_t hRpc,
+ [in] SCMREGKEY *psrkRegister,
+ [in] FILETIME *pfiletime,
+ [out] error_status_t *prpcstat);
+
+ HRESULT IrotGetTimeOfLastChange(
+ [in] handle_t hRpc,
+ [in] PHPROCESS phProcess,
+ [in,unique,string] WCHAR *pwszWinstaDesktop,
+ [in] MNKEQBUF *pmkeqbuf,
+ [out] FILETIME *pfiletime,
+ [out] error_status_t *prpcstat);
+
+ HRESULT IrotEnumRunning(
+ [in] handle_t hRpc,
+ [in] PHPROCESS phProcess,
+ [in,unique,string] WCHAR *pwszWinstaDesktop,
+ [out] MkInterfaceList **ppMkIFList,
+ [out] error_status_t *prpcstat);
+}
diff --git a/private/ole32/com/dcomidl/makefil0 b/private/ole32/com/dcomidl/makefil0
new file mode 100644
index 000000000..825d0b6b1
--- /dev/null
+++ b/private/ole32/com/dcomidl/makefil0
@@ -0,0 +1,14 @@
+!include $(NTMAKEENV)\makefile.plt
+!include dirs
+
+DIR=$(DIRS) $(OPTIONAL_DIRS)
+
+all:
+!IF "$(BUILDMSG)" != ""
+ @ech ; $(BUILDMSG) ;
+!ENDIF
+
+clean: cleansrc all
+
+cleansrc:
+ for %%i in ($(DIR)) do cd %i & nmake -nologo BUILDMSG= clean -f makefile.inc & cd $(MAKEDIR)
diff --git a/private/ole32/com/dcomidl/makefile b/private/ole32/com/dcomidl/makefile
new file mode 100644
index 000000000..7cbed0c04
--- /dev/null
+++ b/private/ole32/com/dcomidl/makefile
@@ -0,0 +1,27 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+!include $(CAIROLE)\com\makefile
+
+all: $(OBJS)
+
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/com/dcomidl/makeidl.inc b/private/ole32/com/dcomidl/makeidl.inc
new file mode 100644
index 000000000..dd14ac67e
--- /dev/null
+++ b/private/ole32/com/dcomidl/makeidl.inc
@@ -0,0 +1,117 @@
+# DEST_TREE is set by the calling makefile
+
+CLASS_DEST=..\..\class\$(DEST_TREE)
+SCM_DEST=..\..\..\dcomss\olescm\$(DEST_TREE)
+
+
+
+
+!ifndef MIDL
+MIDL = midl.exe
+!endif
+
+MIDL_FLAGS= \
+ -Zp8 \
+ -I$(INCLUDES) \
+ -Oi2 \
+ -oldnames \
+ -char unsigned \
+ -error allocation \
+ -error stub_data \
+ -ms_ext -c_ext \
+ $(C_DEFINES) \
+ -cpp_cmd $(TARGET_CPP)
+
+CSWITCH=-prefix cstub _
+
+irot.h: ..\irot.idl ..\irot.acf
+ $(MIDL) $(MIDL_FLAGS) \
+ -cstub $(CLASS_DEST)\irot_c.c \
+ -sstub $(SCM_DEST)\irot_s.c \
+ ..\irot.idl
+
+# Only generate a header. The object proxy and stub are made with
+# mega.idl
+getif.h: ..\getif.idl
+ $(MIDL) $(MIDL_FLAGS) \
+ -client none \
+ -server none \
+ -iid $(CLASS_DEST)\getif_i.c \
+ ..\getif.idl
+
+# Only generate a header. The object proxy and stub are made with
+# mega.idl
+host.h: ..\host.idl
+ $(MIDL) $(MIDL_FLAGS) \
+ -client none \
+ -server none \
+ -iid $(CLASS_DEST)\host_i.c \
+ ..\host.idl
+
+# Only generate a header.
+multqi.h: ..\multqi.idl
+ $(MIDL) $(MIDL_FLAGS) \
+ -client none \
+ -server none \
+ ..\multqi.idl
+
+# first MIDL invocation makes the object header
+# the object proxy and stub are made with mega.idl
+# second MIDL invocation makes the server and the '_' prefixed client
+objsrv.h rwobjsrv.h: ..\objsrv.idl ..\objsrv.acf
+ $(MIDL) $(MIDL_FLAGS) \
+ -client none \
+ -server none \
+ ..\objsrv.idl
+
+ $(MIDL) $(MIDL_FLAGS) \
+ -cstub $(SCM_DEST)\objsrv_c.c \
+ -server none \
+ -header rwobjsrv.h \
+ -D RAW \
+ ..\objsrv.idl
+
+# first MIDL invocation makes proxy for ole32.dll
+# second MIDL invocation makes the server and the '_' prefixed client
+scm.h: ..\scm.idl ..\scm.acf
+ $(MIDL) $(MIDL_FLAGS) \
+ -cstub $(CLASS_DEST)\scm_c.c \
+ -server none \
+ ..\scm.idl
+
+ $(MIDL) $(MIDL_FLAGS) \
+ $(CSWITCH) \
+ -cstub $(SCM_DEST)\scm_z.c \
+ -sstub $(SCM_DEST)\scm_s.c \
+ -noheader \
+ ..\scm.idl
+
+# first MIDL invocation makes the object header
+# the object proxy and stub are made with mega.idl
+# second MIDL invocation makes the server
+dscm.h rawdscm.h: ..\dscm.idl
+ $(MIDL) $(MIDL_FLAGS) \
+ -client none \
+ -server none \
+ -iid $(CLASS_DEST)\dscm_i.c \
+ ..\dscm.idl
+
+ $(MIDL) $(MIDL_FLAGS) \
+ $(CSWITCH) \
+ -client none \
+ -sstub $(SCM_DEST)\dscm_s.c \
+ -header rawdscm.h \
+ -D RAW \
+ ..\dscm.idl
+
+allidl: irot.h getif.h host.h objsrv.h rwobjsrv.h scm.h dscm.h rawdscm.h multqi.h
+
+clean:
+ -erase multqi.h >NUL 2>NUL
+ -erase irot.h >NUL 2>NUL
+ -erase getif.h >NUL 2>NUL
+ -erase objsrv.h >NUL 2>NUL
+ -erase rwobjsrv.h >NUL 2>NUL
+ -erase scm.h >NUL 2>NUL
+ -erase rawdscm.h >NUL 2>NUL
+ -erase host.h >NUL 2>NUL
diff --git a/private/ole32/com/dcomidl/multqi.idl b/private/ole32/com/dcomidl/multqi.idl
new file mode 100644
index 000000000..f3e8cbcf3
--- /dev/null
+++ b/private/ole32/com/dcomidl/multqi.idl
@@ -0,0 +1,49 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: multiqi.idl
+//
+// Contents: Definition of types for supporting multiple QI's at a time
+//
+// History: 07-Aug-95 GregJen Created
+//
+//--------------------------------------------------------------------------
+
+[ local,
+ pointer_default(unique)
+]
+
+interface MultiQiTypes
+{
+
+#ifndef DO_NO_IMPORTS
+ import "iface.idl";
+ import "objidl.idl";
+ import "obase.idl";
+#endif
+
+typedef struct _InterfaceInfo {
+ IID * pIID;
+ HRESULT hr;
+
+// the RAW form does not do Co{Un}Marshal calls
+#ifdef RAW
+ MInterfacePointer *
+#else
+ [iid_is(pIID)] IUnknown *
+#endif
+ pIF;
+ } InterfaceInfoBlock;
+
+
+typedef struct _rawInterfaceInfo {
+ IID * pIID;
+ HRESULT hr;
+
+ MInterfacePointer * pIF;
+
+ } RawInterfaceInfoBlock;
+}
+ \ No newline at end of file
diff --git a/private/ole32/com/dcomidl/objsrv.acf b/private/ole32/com/dcomidl/objsrv.acf
new file mode 100644
index 000000000..cad32f329
--- /dev/null
+++ b/private/ole32/com/dcomidl/objsrv.acf
@@ -0,0 +1,17 @@
+[ implicit_handle(handle_t any_handle) ] interface IObjServer
+{
+#ifdef RAW
+ ObjectServerGetClassObject(
+ [comm_status, fault_status] pStatus);
+
+ ObjectServerCreateInstance(
+ [comm_status, fault_status] pStatus);
+
+ ObjectServerGetInstance(
+ [comm_status, fault_status] pStatus);
+
+ ObjectServerLoadDll(
+ [comm_status, fault_status] pStatus);
+#endif
+}
+ \ No newline at end of file
diff --git a/private/ole32/com/dcomidl/objsrv.idl b/private/ole32/com/dcomidl/objsrv.idl
new file mode 100644
index 000000000..d8f0ef86d
--- /dev/null
+++ b/private/ole32/com/dcomidl/objsrv.idl
@@ -0,0 +1,85 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: scm.idl
+//
+// Contents: Definition of private RPC interface between compobj.dll
+// and the service controller.
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+[ uuid(00000132-0000-0000-C000-000000000046),
+ version(0.0),
+ pointer_default(unique)
+#ifndef RAW
+ , object
+#endif
+]
+
+interface IObjServer
+#ifndef RAW
+ : IUnknown
+#endif
+{
+#ifndef DO_NO_IMPORTS
+ import "iface.idl";
+ import "obase.idl";
+#endif
+ #include "comhndl.h"
+
+ COM_DEFINES(IObjServer)
+
+#ifdef RAW
+ typedef error_status_t STATUSTYPE;
+#else
+ typedef DWORD STATUSTYPE;
+#endif
+
+ HRESULT ObjectServerGetClassObject(
+ COM_HANDLE
+ [in] const GUID * rclsid,
+ [in] IID * pIID,
+ [in] BOOL fSurrogate,
+ [out] MInterfacePointer ** ppIFD,
+ [out] STATUSTYPE * pStatus
+ );
+
+ HRESULT ObjectServerCreateInstance(
+ COM_HANDLE
+ [in] const GUID * rclsid,
+ [in] DWORD Interfaces,
+ [in,size_is(Interfaces)] IID * pIIDs,
+ [out,size_is(Interfaces)] MInterfacePointer **ppIFD,
+ [out,size_is(Interfaces)] HRESULT * pResults,
+ [out] STATUSTYPE * pStatus
+ );
+
+ HRESULT ObjectServerGetInstance(
+ COM_HANDLE
+ [in] const GUID * rclsid,
+ [in] DWORD Mode,
+ [in, string, unique] WCHAR * pwszPath,
+ [in, unique] MInterfacePointer * pIFDStorage,
+ [in] DWORD Interfaces,
+ [in,size_is(Interfaces)] IID * pIIDs,
+ [in, unique] MInterfacePointer * pIFDROT,
+ [out,size_is(Interfaces)] MInterfacePointer **ppIFD,
+ [out,size_is(Interfaces)] HRESULT * pResults,
+ [out] STATUSTYPE * pStatus
+ );
+
+ HRESULT ObjectServerLoadDll(
+ COM_HANDLE
+ [in] const GUID * rclsid,
+ [out] STATUSTYPE * pStatus);
+}
+
+
+
+
+
+
diff --git a/private/ole32/com/dcomidl/oleprv.h b/private/ole32/com/dcomidl/oleprv.h
new file mode 100644
index 000000000..1003b91bc
--- /dev/null
+++ b/private/ole32/com/dcomidl/oleprv.h
@@ -0,0 +1,17 @@
+
+// oleprv.h - header files matching those needed by oleprv.idl
+//
+
+// internal interfaces used by DCOM
+// this is private! (for now)
+
+// NOTE: as entries are added to oleprv.idl, corresponding entries should
+// be added here
+
+#include "remunk.h"
+#include "multqi.h"
+#include "objsrv.h"
+#include "dscm.h"
+#include "getif.h"
+#include "odeth.h"
+#include "host.h"
diff --git a/private/ole32/com/dcomidl/oleprv.idl b/private/ole32/com/dcomidl/oleprv.idl
new file mode 100644
index 000000000..ea5e0705a
--- /dev/null
+++ b/private/ole32/com/dcomidl/oleprv.idl
@@ -0,0 +1,19 @@
+// oleprv.idl
+
+// internal interfaces used by DCOM that need object-style proxies
+// this file is pulled into mega.idl in the oleprx32 subtree
+
+// NOTE: when you add an idl to here, make sure to add it to the corresponding
+// place in the file oleprv.h
+
+
+
+#include "obase.idl"
+#include "iface.idl"
+#include "multqi.idl"
+#include "remunk.idl"
+#include "objsrv.idl"
+#include "dscm.idl"
+#include "getif.idl"
+#include "odeth.idl"
+#include "host.idl"
diff --git a/private/ole32/com/dcomidl/scm.acf b/private/ole32/com/dcomidl/scm.acf
new file mode 100644
index 000000000..5c74b7afd
--- /dev/null
+++ b/private/ole32/com/dcomidl/scm.acf
@@ -0,0 +1,20 @@
+[ implicit_handle(handle_t any_handle) ] interface ISCM
+{
+ ServerRegisterClsid(
+ [comm_status, fault_status] prpcstat);
+
+ ServerRevokeClsid(
+ [comm_status, fault_status] prpcstat);
+
+ GetThreadID(
+ [comm_status, fault_status] prpcstat);
+
+ UpdateShrdTbls(
+ [comm_status, fault_status] prpcstat);
+
+ RegisterWindowPropInterface(
+ [comm_status, fault_status] prpcstat);
+
+ GetWindowPropInterface(
+ [comm_status, fault_status] prpcstat);
+}
diff --git a/private/ole32/com/dcomidl/scm.idl b/private/ole32/com/dcomidl/scm.idl
new file mode 100644
index 000000000..264a13dc3
--- /dev/null
+++ b/private/ole32/com/dcomidl/scm.idl
@@ -0,0 +1,119 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: scm.idl
+//
+// Contents: Definition of private RPC interface between compobj.dll
+// and the service controller.
+//
+// History: 21-Apr-93 Ricksa Created
+// 27-Dec-93 ErikGav TCHAR->WCHAR
+//
+//--------------------------------------------------------------------------
+[ uuid(412f241e-c12a-11ce-abff-0020af6e7a17),
+ version(0.2),
+ pointer_default(unique)
+]
+
+interface ISCM
+{
+ import "iface.idl";
+ import "obase.idl";
+
+ typedef [context_handle] void *PHPROCESS;
+
+ typedef struct _RegOutputEnt
+ {
+ DWORD dwReg;
+ DWORD dwAtStorage;
+ } RegOutputEnt;
+
+ typedef struct _RegOutput
+ {
+ DWORD dwSize;
+ [size_is(dwSize)]
+ RegOutputEnt regoutent[];
+ } RegOutput;
+
+ typedef struct _RegInputEntry
+ {
+ CLSID clsid;
+ OXID oxid;
+ IPID ipid;
+ DWORD dwFlags;
+ } RegInputEntry;
+
+ typedef struct _RegInput
+ {
+ DWORD dwSize;
+ [size_is(dwSize)]
+ RegInputEntry rginent[];
+ } RegInput;
+
+ typedef struct _RevokeEntry
+ {
+ CLSID clsid;
+ DWORD dwReg;
+ } RevokeEntry;
+
+ typedef struct _RevokeClasses
+ {
+ DWORD dwSize;
+ [size_is(dwSize)]
+ RevokeEntry revent[];
+ } RevokeClasses;
+
+ //
+ // Server to SCM methods.
+ //
+ HRESULT ServerRegisterClsid(
+ [in] handle_t hRpc,
+ [in] PHPROCESS phProcess,
+ [in, string, unique] WCHAR *pWinstaDesktop,
+ [in] RegInput * pregin,
+ [out] RegOutput ** ppregout,
+ [out] error_status_t * prpcstat);
+
+ void ServerRevokeClsid(
+ [in] handle_t hRpc,
+ [in] PHPROCESS phProcess,
+ [in] RevokeClasses * prevcls,
+ [out] error_status_t * prpcstat);
+
+ //
+ // Client/Server to SCM methods.
+ //
+
+ void GetThreadID(
+ [in] handle_t hRpc,
+ [out] DWORD * pThreadID,
+ [out] error_status_t *prpcstat);
+
+ HRESULT UpdateShrdTbls(
+ [in] handle_t hRpc,
+ [out] error_status_t *prpcstat);
+
+ void UpdateActivationSettings(
+ [in] handle_t hRpc,
+ [out] error_status_t *prpcstat);
+
+ // Register Drag/Drop
+ HRESULT RegisterWindowPropInterface(
+ [in] handle_t hRpc,
+ [in] DWORD hWnd,
+ [in] STDOBJREF *pStd,
+ [in] OXID_INFO *pOxidInfo,
+ [out] DWORD *pdwCookie,
+ [out] error_status_t *prpcstat);
+
+ HRESULT GetWindowPropInterface(
+ [in] handle_t hRpc,
+ [in] DWORD hWnd,
+ [in] DWORD dwCookie,
+ [in] BOOL fRevoke,
+ [out] STDOBJREF *pStd,
+ [out] OXID_INFO *pOxidInfo,
+ [out] error_status_t *prpcstat);
+}
diff --git a/private/ole32/com/dcomidl/sources.inc b/private/ole32/com/dcomidl/sources.inc
new file mode 100644
index 000000000..407eb4e3c
--- /dev/null
+++ b/private/ole32/com/dcomidl/sources.inc
@@ -0,0 +1,3 @@
+#
+#
+#
diff --git a/private/ole32/com/dcomrem/callctrl.cxx b/private/ole32/com/dcomrem/callctrl.cxx
new file mode 100644
index 000000000..f393fdd27
--- /dev/null
+++ b/private/ole32/com/dcomrem/callctrl.cxx
@@ -0,0 +1,1820 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: callctrl.cxx
+//
+// Contents: Contains the ORPC CallControl code
+//
+// History: 21-Dec-93 Johannp Original Version
+// 04-Nov-94 Rickhi ReWrite as layer over channel
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include <thkreg.h> // OLETHK_ defines
+#include <dde.h>
+#include <callctrl.hxx> // Class Definition
+#include <objsrv.h> // IID_IObjServer
+
+
+// private defines used only in this file
+#define WM_SYSTIMER 0x0118
+#define SYS_ALTDOWN 0x2000
+#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
+#define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
+
+
+// empty slot in window registration
+#define WD_EMPTY (HWND)-1
+
+// the following table is used to quickly determine what windows
+// message queue inputflag to specify for the various categories of
+// outgoing calls in progress. The table is indexed by CALLCATEGORY.
+
+DWORD gMsgQInputFlagTbl[4] = {
+ QS_ALLINPUT | QS_TRANSFER | QS_ALLPOSTMESSAGE, // NOCALL
+ QS_ALLINPUT | QS_TRANSFER | QS_ALLPOSTMESSAGE, // SYNCHRONOUS
+ QS_ALLINPUT | QS_TRANSFER | QS_ALLPOSTMESSAGE, // ASYNC
+ QS_SENDMESSAGE}; // INPUTSYNC
+
+
+// the following table is used to map bit flags in the Rpc Message to
+// the equivalent OLE CALLCATEGORY.
+
+DWORD gRpcFlagToCallCatMap[3] = {
+ CALLCAT_SYNCHRONOUS, // no flags set
+ CALLCAT_INPUTSYNC, // RPCFLG_INPUT_SYNCHRONOUS
+ CALLCAT_ASYNC}; // RPCFLG_ASYNCHRONOUS
+
+
+// prototype
+HRESULT CopyMsgForRetry(RPCOLEMESSAGE *pMsg,
+ IRpcChannelBuffer *pChnl,
+ HRESULT hrIn);
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoRegisterMessageFilter, public
+//
+// Synopsis: registers an applications message filter with the call control
+//
+// Arguments: [pMsgFilter] - message filter to register
+// [ppMsgFilter] - optional, where to return previous IMF
+//
+// Returns: S_OK - registered successfully
+//
+// History: 21-Dec-93 JohannP Created
+//
+//--------------------------------------------------------------------------
+STDAPI CoRegisterMessageFilter(LPMESSAGEFILTER pMsgFilter,
+ LPMESSAGEFILTER *ppMsgFilter)
+{
+ ComDebOut((DEB_MFILTER, "CoRegisterMessageFilter pMF:%x ppMFOld:%x\n",
+ pMsgFilter, ppMsgFilter));
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IMessageFilter,(IUnknown **)&pMsgFilter);
+
+ // validate the parameters. NULL acceptable for either or both parameters.
+ if (pMsgFilter != NULL && !IsValidInterface(pMsgFilter))
+ {
+ return E_INVALIDARG;
+ }
+
+ if(ppMsgFilter != NULL && !IsValidPtrOut(ppMsgFilter, sizeof(ppMsgFilter)))
+ {
+ return E_INVALIDARG;
+ }
+
+ // this operation is not allowed on MTA Threads
+ if (IsMTAThread())
+ return CO_E_NOT_SUPPORTED;
+
+ // find the callcontrol for this apartment and replace the existing
+ // message filter. if no callctrl has been created yet, just stick
+ // the pMsgFilter in tls.
+
+ COleTls tls;
+ CAptCallCtrl *pACC = tls->pCallCtrl;
+
+ IMessageFilter *pOldMF;
+
+ if (pACC)
+ {
+ pOldMF = pACC->InstallMsgFilter(pMsgFilter);
+ }
+ else
+ {
+ pOldMF = tls->pMsgFilter;
+
+ if (pMsgFilter)
+ {
+ pMsgFilter->AddRef();
+ }
+ tls->pMsgFilter = pMsgFilter;
+ }
+ if (ppMsgFilter)
+ {
+ // return old MF to the caller
+ *ppMsgFilter = pOldMF;
+ }
+ else if (pOldMF)
+ {
+ // release the old MF
+ pOldMF->Release();
+ }
+
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CAptCallCtrl::InstallMsgFilter
+//
+// Synopsis: called to install a new application provided message filter
+//
+// Arguments: [pMF] - new message filter to install (or NULL)
+//
+// Returns: previous message filter if there was one
+//
+// History: 20-Dec-93 JohannP Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(IMessageFilter *) CAptCallCtrl::InstallMsgFilter(IMessageFilter *pMF)
+{
+ IMessageFilter *pMFOld = _pMF; // save the old one to return
+
+ _pMF = pMF; // install the new one
+ if (_pMF)
+ {
+ _pMF->AddRef();
+ }
+
+ return pMFOld;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CAptCallCtrl::CAptCallCtrl
+//
+// Synopsis: constructor for per apartment call control state
+//
+// History: 11-Nov-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+CAptCallCtrl::CAptCallCtrl() :
+ _fInMsgFilter(FALSE),
+ _pTopCML(NULL)
+{
+ // The first one is reserved for ORPC. An hWnd value of WD_EMPTY
+ // means the slot is available.
+ _WD[0].hWnd = WD_EMPTY;
+
+ // The second slot has fixed values for DDE
+ _WD[1].hWnd = NULL;
+ _WD[1].wFirstMsg = WM_DDE_FIRST;
+ _WD[1].wLastMsg = WM_DDE_LAST;
+
+ // put our pointer into thread local storage, and retrieve any previously
+ // registered message filter.
+
+ COleTls tls;
+ tls->pCallCtrl = this;
+
+ _pMF = tls->pMsgFilter;
+ tls->pMsgFilter = NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CAptCallCtrl::~CAptCallCtrl
+//
+// Synopsis: destructor for per apartment call control state
+//
+// History: 11-Nov-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+CAptCallCtrl::~CAptCallCtrl()
+{
+ Win4Assert(_pTopCML == NULL); // no outgoing calls.
+
+ if (_pMF)
+ {
+ _pMF->Release();
+ }
+
+ // remove our pointer from thread local storage
+ COleTls tls;
+ tls->pCallCtrl = NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CAptCallCtrl::Register/Revoke
+//
+// Synopsis: register or revoke RPC window data
+//
+// Arguments: [hWnd] - window handle to look for calls on
+// [wFirstMsg] - msgid of first message in range to look for
+// [wLastMsg] - msgid of last message in range to look for
+//
+// Returns: nothing
+//
+// Notes: This code is only ever called by the RpcChannel and by
+// the DDE layer, and so error checking is kept to a minimum.
+//
+// History: 30-Apr-95 Rickhi Created
+//
+//--------------------------------------------------------------------------
+void CAptCallCtrl::Register(HWND hWnd, UINT wFirstMsg, UINT wLastMsg)
+{
+ Win4Assert(_WD[0].hWnd == WD_EMPTY && "Register Out of Space");
+
+ _WD[0].hWnd = hWnd;
+ _WD[0].wFirstMsg = wFirstMsg;
+ _WD[0].wLastMsg = wLastMsg;
+}
+
+void CAptCallCtrl::Revoke(HWND hWnd)
+{
+ Win4Assert(_WD[0].hWnd == hWnd && "Revoke not found");
+ _WD[0].hWnd = WD_EMPTY;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetSlowTimeFactor
+//
+// Synopsis: Get the time slowing factor for Wow apps
+//
+// Returns: The factor by which we need to slow time down.
+//
+// Algorithm: If there is a factor in the registry, we open and read the
+// registry. Otherwise we just set it to the default.
+//
+// History: 22-Jul-94 Ricksa Created
+// 09-Jun-95 Susia ANSI Chicago optimization
+//
+//--------------------------------------------------------------------------
+#ifdef _CHICAGO_
+#undef RegOpenKeyEx
+#define RegOpenKeyEx RegOpenKeyExA
+#undef RegQueryValueEx
+#define RegQueryValueEx RegQueryValueExA
+#endif
+DWORD GetSlowTimeFactor(void)
+{
+ // Default slowing time so we can just exit if there is no key which
+ // is assumed to be the common case.
+ DWORD dwSlowTimeFactor = OLETHK_DEFAULT_SLOWRPCTIME;
+
+ // Key for reading the value from the registry
+ HKEY hkeyOleThk;
+
+ // Get the Ole Thunk special value key
+ LONG lStatus = RegOpenKeyEx(HKEY_CLASSES_ROOT, OLETHK_KEY, 0, KEY_READ,
+ &hkeyOleThk);
+
+ if (lStatus == ERROR_SUCCESS)
+ {
+ DWORD dwType;
+ DWORD dwSizeData = sizeof(dwSlowTimeFactor);
+
+ lStatus = RegQueryValueEx(hkeyOleThk, OLETHK_SLOWRPCTIME_VALUE, NULL,
+ &dwType, (LPBYTE) &dwSlowTimeFactor, &dwSizeData);
+
+ if ((lStatus != ERROR_SUCCESS) || dwType != REG_DWORD)
+ {
+ // Guarantee that value is reasonable if something went wrong.
+ dwSlowTimeFactor = OLETHK_DEFAULT_SLOWRPCTIME;
+ }
+
+ // Close the key since we are done with it.
+ RegCloseKey(hkeyOleThk);
+ }
+
+ return dwSlowTimeFactor;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CanMakeOutCall
+//
+// Synopsis: called when the client app wants to make an outgoing call to
+// determine if it is OK to do it now or not. Common subroutine
+// to CAptRpcChnl::GetBuffer and RemoteReleaseRifRef.
+//
+// Arguments: [dwCallCatOut] - call category of call the app wants to make
+// [pChnl] - ptr to channel call is being made on
+// [riid] - interface call is being made on
+//
+// Returns: S_OK - ok to make the call
+// RPC_E_CANTCALLOUT_INEXTERNALCALL - inside IMessageFilter
+// RPC_E_CANTCALLOUT_INASYNCCALL - inside async call
+// RPC_E_CANTCALLOUT_ININPUTSYNCCALL - inside input sync or SendMsg
+//
+// History: 21-Dec-93 Johannp Original Version
+// 04-Nov-94 Rickhi ReWrite
+// 03-Oct-95 Rickhi Made into common subroutine
+//
+//--------------------------------------------------------------------------
+INTERNAL CanMakeOutCall(DWORD dwCallCatOut, REFIID riid)
+{
+ // get the topmost incoming call state from Tls.
+
+ HRESULT hr;
+ COleTls tls(hr);
+ if (FAILED(hr))
+ return hr;
+
+ CSrvCallState *pSCS = tls->pTopSCS;
+
+ DWORD dwCallCatIn = (pSCS) ? pSCS->GetCallCatIn() : CALLCAT_NOCALL;
+
+ // if handling an incoming ASYNC call, only allow ASYNC outgoing calls,
+ // and local calls on IRemUnknown (which locally is actually IRundown).
+
+ if (dwCallCatIn == CALLCAT_ASYNC &&
+ dwCallCatOut != CALLCAT_ASYNC &&
+ !IsEqualGUID(riid, IID_IRundown))
+ {
+ return RPC_E_CANTCALLOUT_INASYNCCALL;
+ }
+
+ // if handling an incoming INPUTSYNC call, or if we are handling a
+ // SendMessage, dont allow SYNCHRONOUS calls out or we could deadlock
+ // since SYNC uses PostMessage and INPUTSYNC uses SendMessage.
+
+ if (dwCallCatOut == CALLCAT_SYNCHRONOUS &&
+ (dwCallCatIn == CALLCAT_INPUTSYNC || InSendMessage()))
+ {
+ return RPC_E_CANTCALLOUT_ININPUTSYNCCALL;
+ }
+
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMTARpcChnl::CMTARpcChnl/~CMTARpcChnl
+//
+// Synopsis: constructor/destructor
+//
+// Parameters: [pStdId] - std identity for the object
+// [pOXIDEntry] - OXIDEntry for the object server
+// [eState] - state flags passed thru to CRpcChannelBuffer
+// (ignored by CMTARpcCnl).
+//
+// History: 11-Nov-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+CMTARpcChnl::CMTARpcChnl(CStdIdentity *pStdId,
+ OXIDEntry *pOXIDEntry,
+ DWORD eState) :
+ CRpcChannelBuffer(pStdId, pOXIDEntry, eState),
+ _dwTIDCallee(pOXIDEntry->dwTid),
+ _dwAptId(GetCurrentApartmentId())
+{
+ ComDebOut((DEB_CALLCONT,"CMTARpcChnl::CMTARpcChnl this:%x\n", this));
+}
+
+CMTARpcChnl::~CMTARpcChnl()
+{
+ ComDebOut((DEB_CALLCONT,"CMTARpcChnl::~CMTARpcChnl this:%x\n", this));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMTARpcChnl::GetBuffer
+//
+// Synopsis: Ensure it is legal to call out now, then get a buffer.
+//
+// Parameters: [pMsg] - ptr to message structure
+// [riid] - interface call is being made on
+//
+// History: 11-Nov-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CMTARpcChnl::GetBuffer(RPCOLEMESSAGE *pMsg, REFIID riid)
+{
+ HRESULT hr;
+ COleTls tls(hr); // use this form incase no calls made on this thread yet
+ if (FAILED(hr))
+ return hr;
+
+ if (!IsMTAThread())
+ {
+ ComDebOut((DEB_WARN,"CMTARpcChnl::GetBuffer - MTA proxy called on apartment thread, this: 0x%x\n",
+ this));
+ return RPC_E_WRONG_THREAD;
+ }
+
+ // Make sure we are allowed to make this outgoing call. We do that here
+ // so that we dont marshal all the parameters only to discover that we
+ // cant call out and then have to free all the marshalled parameters
+ // (especially the ones where marshalling has side effects).
+
+ if (!(_dwAptId == GetCurrentApartmentId() || CallableOnAnyApt()))
+ {
+ // we are not being called on a thread in the MTA apartment
+ return RPC_E_WRONG_THREAD;
+ }
+
+ if (pMsg->rpcFlags & RPCFLG_INPUT_SYNCHRONOUS)
+ {
+ // dont allow INPUTSYNC calls from an MTA apartment to anybody.
+ return RPC_E_CANTCALLOUT_ININPUTSYNCCALL;
+ }
+
+ // All ASYNC calls from an MTA apartment are treated as SYNCHRONOUS,
+ // so convert the call category here before proceeding.
+
+ pMsg->rpcFlags &= ~RPCFLG_ASYNCHRONOUS;
+
+ // ask the real channel for a buffer.
+ return CRpcChannelBuffer::ClientGetBuffer(pMsg, riid);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CAptRpcChnl::CAptRpcChnl/~CAptRpcChnl
+//
+// Synopsis: constructor/destructor
+//
+// Parameters: [pStdId] - std identity for the object
+// [pOXIDEntry] - OXIDEntry for the object server
+// [eState] - state flags passed thru to CRpcChannelBuffer
+// (ignored by CAptRpcCnl).
+//
+// History: 11-Nov-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+CAptRpcChnl::CAptRpcChnl(CStdIdentity *pStdId,
+ OXIDEntry *pOXIDEntry,
+ DWORD eState) :
+ CRpcChannelBuffer(pStdId, pOXIDEntry, eState),
+ _dwTIDCallee(pOXIDEntry->dwTid),
+ _dwAptId(GetCurrentApartmentId())
+{
+ ComDebOut((DEB_CALLCONT,"CAptRpcChnl::CAptRpcChnl this:%x\n", this));
+}
+
+CAptRpcChnl::~CAptRpcChnl()
+{
+ ComDebOut((DEB_CALLCONT,"CAptRpcChnl::~CAptRpcChnl this:%x\n", this));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CAptRpcChnl::GetBuffer
+//
+// Synopsis: Ensure it is legal to call out now, then get a buffer.
+//
+// Parameters: [pMsg] - ptr to message structure
+// [riid] - interface call is being made on
+//
+// History: 11-Nov-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CAptRpcChnl::GetBuffer(RPCOLEMESSAGE *pMsg, REFIID riid)
+{
+ HRESULT hr;
+ COleTls tls(hr); // use this form incase no calls made on this thread yet
+ if (FAILED(hr))
+ return hr;
+
+ // first, make sure that we are being called on the correct thread
+ // so that we are sure tls->pCallCtrl is set.
+
+ if (!IsSTAThread() || !(_dwAptId == GetCurrentApartmentId() ||
+ CallableOnAnyApt()))
+ {
+ return RPC_E_WRONG_THREAD;
+ }
+
+ // dont allow the application to call out while handling an
+ // IMessageFilter call because it screws up the call sequencing.
+
+ CAptCallCtrl *pACC = tls->pCallCtrl;
+
+ if (pACC && pACC->InMsgFilter())
+ {
+ ComDebOut((DEB_ERROR, "Illegal callout from within IMessageFilter\n"));
+ return RPC_E_CANTCALLOUT_INEXTERNALCALL;
+ }
+
+ // if the call is async and remote, or async and to an MTA apartment,
+ // then change the category to sync, since we dont support async remotely
+ // or to MTA apartments locally. This must be done before calling
+ // CanMakeOutCall in order to avoid deadlocks. If the call is input sync
+ // and remote or to an MTA apartment, dissallow the call.
+
+ if (pMsg->rpcFlags & (RPCFLG_ASYNCHRONOUS | RPCFLG_INPUT_SYNCHRONOUS))
+ {
+ DWORD dwCtx;
+ CRpcChannelBuffer::GetDestCtx(&dwCtx, NULL);
+
+ if (dwCtx == MSHCTX_DIFFERENTMACHINE ||
+ (GetOXIDEntry()->dwFlags & OXIDF_MTASERVER))
+ {
+ if (pMsg->rpcFlags & RPCFLG_INPUT_SYNCHRONOUS)
+ return RPC_E_CANTCALLOUT_ININPUTSYNCCALL;
+
+ // turn off the async flag so that the call looks (and acts)
+ // like it is synchronous.
+
+ pMsg->rpcFlags &= ~RPCFLG_ASYNCHRONOUS;
+ }
+ }
+
+ // Make sure we are allowed to make this outgoing call. We do that here
+ // so that we dont marshal all the parameters only to discover that we
+ // cant call out and then have to free all the marshalled parameters
+ // (especially the ones where marshalling has side effects).
+
+ // figure out the call category of this call by looking at bit
+ // values in the rpc message flags.
+
+ DWORD dwCallCatOut = RpcFlagToCallCat(pMsg->rpcFlags);
+
+ // check other outgoing call restrictions common to multi and single
+ // threaded apartments
+
+ hr = CanMakeOutCall(dwCallCatOut, riid);
+
+ if (hr == S_OK)
+ {
+ // ask the real channel for a buffer.
+ hr = CRpcChannelBuffer::ClientGetBuffer(pMsg, riid);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CAptRpcChnl::SendReceive
+//
+// Synopsis: instantiate a modal loop object and then transmit the call
+//
+// Parameters: [pMsg] - ptr to message structure
+// [pulStatus] - place to return a status code
+//
+// History: 11-Nov-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CAptRpcChnl::SendReceive(RPCOLEMESSAGE *pMsg, ULONG *pulStatus)
+{
+ // Figure out the call category of this call by looking at the bit
+ // values in the rpc message flags.
+
+ DWORD dwCallCatOut = RpcFlagToCallCat(pMsg->rpcFlags);
+ DWORD dwMsgQInputFlag = gMsgQInputFlagTbl[dwCallCatOut];
+
+ // Now for a spectacular hack. IRemUnknown::Release had slightly
+ // different dwMsgQInputFlag semantic in the old code base, so we
+ // check for that one case here and set the flag accordingly. Not
+ // doing this would allow SYSCOMMAND calls in during Release which
+ // we throw away, thus preventing an app from shutting down correctly.
+ // SimpSvr.exe is a good example of this.
+
+ if ((pMsg->iMethod & ~RPC_FLAGS_VALID_BIT) == 5 &&
+ (IsEqualIID(IID_IRundown, *MSG_TO_IIDPTR(pMsg)) ||
+ IsEqualIID(IID_IRemUnknown, *MSG_TO_IIDPTR(pMsg))))
+ {
+ dwMsgQInputFlag = (QS_POSTMESSAGE | QS_SENDMESSAGE | QS_TRANSFER |
+ QS_ALLPOSTMESSAGE);
+ }
+
+
+ // Now construct a modal loop object for the call that is about to
+ // be made. It maintains the call state and exits when the call has
+ // been completed, cancelled, or rejected.
+
+ HRESULT hr;
+ CCliModalLoop CML(_dwTIDCallee, dwMsgQInputFlag);
+
+ do
+ {
+ hr = CML.SendReceive(pMsg, pulStatus, this);
+
+ if (hr == RPC_E_SERVERCALL_RETRYLATER)
+ {
+ // the call was rejected by the server and the client Msg Filter
+ // decided to retry the call. We have to make a copy of the
+ // message and re-send it.
+
+ hr = CopyMsgForRetry(pMsg);
+ }
+ else if (hr == RPC_E_CALL_REJECTED)
+ {
+ // the call was rejected by the server and the client Msg Filter
+ // decided NOT to retry the call. We have to free the buffer
+ // that was returned since the proxy is not expecting it.
+
+ FreeBuffer(pMsg);
+ }
+
+ } while (hr == RPC_E_SERVERCALL_RETRYLATER);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CAptRpcChnl::CopyMsgForRetry
+//
+// Synopsis: Makes a copy of the message we sent. We have to ask Rpc
+// for another buffer and then copy the original buffer into
+// the new one so we can make another call.
+//
+// Parameters: [pMsg] - ptr to message structure to copy
+//
+// History: 11-Nov-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT CAptRpcChnl::CopyMsgForRetry(RPCOLEMESSAGE *pMsg)
+{
+ ComDebOut((DEB_CALLCONT,"CAptRpcChnl::CopyMsgForRetry pMsg:%x\n", pMsg));
+
+ // CODEWORK: this is dumb, but the channel blows chunks in FreeBuffer
+ // if i dont do this double copy.
+
+ void *pTmpBuf = PrivMemAlloc(pMsg->cbBuffer);
+ if (pTmpBuf)
+ {
+ memcpy(pTmpBuf, pMsg->Buffer, pMsg->cbBuffer);
+ }
+
+ // save copy of the contents of the old message so we can free it later
+
+ HRESULT hr = E_OUTOFMEMORY;
+ RPCOLEMESSAGE MsgToFree = *pMsg;
+ FreeBuffer(&MsgToFree);
+
+ if (pTmpBuf)
+ {
+ // allocate a new message, dont have to worry about checking the
+ // CanMakeOutCall again, so we just ask the Rpc channel directly.
+
+ hr = CRpcChannelBuffer::GetBuffer(pMsg, *MSG_TO_IIDPTR(pMsg));
+
+ if (SUCCEEDED(hr))
+ {
+ // copy the temp buffer into the new buffer
+ memcpy(pMsg->Buffer, pTmpBuf, pMsg->cbBuffer);
+ hr = RPC_E_SERVERCALL_RETRYLATER;
+ }
+
+ PrivMemFree(pTmpBuf);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliModalLoop::SendReceive
+//
+// Synopsis: called to transmit a call to the server and enter a modal
+// loop.
+//
+// Arguments: [pMsg] - message to send
+// [pulStatus] - place to return status code
+// [pChnl] - IRpcChannelBuffer pointer
+//
+// Returns: result of the call. May return RETRYLATER if the call should
+// be retransmitted.
+//
+// History: 11-Nov-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+INTERNAL CCliModalLoop::SendReceive(RPCOLEMESSAGE *pMsg, ULONG *pulStatus,
+ IRpcChannelBuffer2 *pChnl)
+{
+ // SendReceive is a blocking call. The channel will transmit the call
+ // asynchronously then call us back in BlockFn where we wait for an
+ // event such as the call completing, or a windows message arriving,
+ // or the user cancelling the call. Because of the callback, we need
+ // to set _hr before calling SR.
+
+ _hr = RPC_S_CALLPENDING;
+ _hr = pChnl->SendReceive2(pMsg, pulStatus);
+
+ // By this point the call has completed. Now check if it was rejected
+ // and if so, whether we need to retry immediately, later, or never.
+ // Handling of Rejected calls must occur here, not in the BlockFn, due
+ // to the fact that some calls and some protocols are synchronous, and
+ // other calls and protocols are asynchronous.
+
+ if (_hr == RPC_E_CALL_REJECTED || _hr == RPC_E_SERVERCALL_RETRYLATER)
+ {
+ // this function decides on 1 of 3 different courses of action
+ // 1. fail the call - sets the state to Call_Rejected
+ // 2. retry immediately - sets _hr to RETRYLATER, fall out
+ // 3. retry later - starts the timer, we block below
+
+ _hr = HandleRejectedCall(pChnl);
+
+ // if a timer was installed to retry the call later, then we have
+ // to go into modal loop until the timer expires. if the call is
+ // cancelled while in this loop, the loop will be exited.
+
+ while (!IsTimerAtZero())
+ {
+ BlockFn(NULL);
+ }
+
+ // Either it is time to retransmit the call, or the call was
+ // cancelled or rejected.
+ }
+
+ return _hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliModalLoop::HandleRejectedCall
+//
+// Synopsis: called when the response to a remote call is rejected or
+// retry later.
+//
+// Arguments: [pChnl] - channel we are calling on.
+//
+// Returns: RPC_E_CALL_REJECTED - call is rejected
+// RPC_E_SERVERCALL_RETRYLATER - the call should be retried
+// (Timer is set if retry is to be delayed)
+//
+// Algorithm: Calls the app's message filter (if there is one) to
+// determine whether the call should be failed, retried
+// immediately, or retried at some later time. If there is
+// no message filter, or the client is on a different machine,
+// then the call is always rejected.
+//
+// History: 21-Dec-93 Johannp Created
+// 30-Apr-95 Rickhi ReWrite
+//
+//--------------------------------------------------------------------------
+INTERNAL CCliModalLoop::HandleRejectedCall(IRpcChannelBuffer2 *pChnl)
+{
+ // default return value - rejected
+ DWORD dwRet = 0xffffffff;
+
+ DWORD dwDestCtx;
+ HRESULT hr = pChnl->GetDestCtx(&dwDestCtx, NULL);
+
+ if (SUCCEEDED(hr) && dwDestCtx != MSHCTX_DIFFERENTMACHINE)
+ {
+ // the call is local to this machine, ask the message filter
+ // what to do. For remote calls we never allow retry, since
+ // the parameters were not sent back to us in the packet.
+
+ IMessageFilter *pMF = _pACC->GetMsgFilter();
+ if (pMF)
+ {
+ ComDebOut((DEB_MFILTER,
+ "pMF->RetryRejectedCall(dwTIDCallee:%x ElapsedTime:%x Type:%x)\n",
+ _dwTIDCallee, GetElapsedTime(),
+ (_hr == RPC_E_CALL_REJECTED) ? SERVERCALL_REJECTED
+ : SERVERCALL_RETRYLATER));
+
+ dwRet = pMF->RetryRejectedCall((MF_HTASK)_dwTIDCallee, GetElapsedTime(),
+ (_hr == RPC_E_CALL_REJECTED) ? SERVERCALL_REJECTED
+ : SERVERCALL_RETRYLATER);
+
+ ComDebOut((DEB_MFILTER,"pMF->RetryRejected() dwRet:%x\n", dwRet));
+
+ _pACC->ReleaseMsgFilter();
+ }
+ }
+
+ if (dwRet == 0xffffffff)
+ {
+ // Really rejected. Mark it as such incase it was actually
+ // Call_RetryLater, also ensures that IsWaiting returns FALSE
+ return RPC_E_CALL_REJECTED;
+ }
+ else if (dwRet >= 100)
+ {
+ // Retry Later. Start the timer. This ensures that IsTimerAtZero
+ // returns FALSE and IsWaiting returns TRUE
+ return StartTimer(dwRet);
+ }
+ else
+ {
+ // Retry Immediately. The state is set so that IsTimerAtZero
+ // returns TRUE.
+
+ Win4Assert(IsTimerAtZero());
+ return RPC_E_SERVERCALL_RETRYLATER;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleModalLoopBlockFn
+//
+// Synopsis: Called by the RpcChannel during an outgoing call while
+// waiting for the reply message.
+//
+// Arguments: [pvWnd] - Window handle to expect the reply on
+// [pvCtx] - Call Context (the CCliModalLoop)
+// [hCallWaitEvent] - optional event to have CallControl wait on
+//
+// Returns: result of the call
+//
+// Algorithm: pvCtx is the topmost modal loop for the current apartment.
+// Just call it's block function.
+//
+// History: Dec-93 JohannP Created
+//
+//--------------------------------------------------------------------------
+RPC_STATUS OleModalLoopBlockFn(void *pvWnd, void *pvCtx, HANDLE hCallWaitEvent)
+{
+ Win4Assert( pvCtx != NULL );
+ return ((CCliModalLoop *) pvCtx)->BlockFn(hCallWaitEvent);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliModalLoop::BlockFn (private)
+//
+// Synopsis: Implements the blocking part of the modal loop. This function
+// blocks until an event of interest occurs, then it goes and
+// processes that event and returns.
+//
+// Arguments: [hCallWaitEvent] - event to wait on (optional)
+//
+// Returns: RPC_S_CALLPENDING - the call is still pending a reply
+// RPC_E_CALL_CANCELLED - the call was cancelled.
+// RPC_E_SERVERCALL_RETRYLATER - the call should be retried later
+//
+// History: Dec-93 JohannP Created
+// 30-Apr-95 Rickhi ReWrite
+//
+//--------------------------------------------------------------------------
+HRESULT CCliModalLoop::BlockFn(HANDLE hEventCallComplete)
+{
+ ComDebOut((DEB_CALLCONT,
+ "CCliModalLoop::BlockFn this:%x dwMsgQInputFlag:%x hEvent:%x\n",
+ this, _dwMsgQInputFlag, hEventCallComplete));
+
+ Win4Assert(IsWaiting() && "ModalLoop::BlockFn - not waiting on call");
+
+ // First, we wait for an event of interest to occur, either for the call
+ // to complete, or a new windows message to arrive on the queue.
+
+ DWORD dwWakeReason = WAIT_TIMEOUT;
+ HANDLE rgEvents[1] = {hEventCallComplete};
+ DWORD cEvents = 0;
+
+ if (hEventCallComplete != NULL)
+ {
+ // Check if the event is already signalled. This ensures that
+ // when we return from nested calls and the upper calls have already
+ // been acknowledged, that no windows messages can come in.
+
+ ComDebOut((DEB_CALLCONT, "WaitForSingleObject hEvent:%x\n", rgEvents[0]));
+ cEvents = 1;
+ dwWakeReason = WaitForSingleObject(rgEvents[0], 0);
+ }
+
+ if (dwWakeReason == WAIT_TIMEOUT)
+ {
+ DWORD dwWaitTime = TicksToWait();
+
+ // If we want to wake up for a posted message, we need to make
+ // sure that we haven't missed any because of the queue status
+ // being affected by prior PeekMessages. We don't worry about
+ // QS_SENDMESSAGE because if PeekMessage got called, the pending
+ // send got dispatched. Further, if we are in an input sync call,
+ // we don't want to start dispatching regular RPC calls here by
+ // accident.
+
+ if (_dwMsgQInputFlag & QS_POSTMESSAGE)
+ {
+ DWORD dwStatus = GetQueueStatus(_dwMsgQInputFlag);
+
+ // We care about any message on the queue not just new messages
+ // because PeekMessage affects the queue state. It resets the
+ // state so even if a message is not processed, the queue state
+ // represents this as an old message even though no one has
+ // ever looked at it. So even though the message queue tells us
+ // there are no new messages in the queue. A new message we are
+ // interested in could be in the queue.
+
+ WORD wNew = (WORD) dwStatus | HIWORD(dwStatus);
+
+ // Note that we look for send as well as post because our
+ // queue status could have reset the state of the send message
+ // bit and therefore, MsgWaitForMultipleObject below will not
+ // wake up to dispatch the send message.
+
+ if (wNew & (QS_POSTMESSAGE | QS_SENDMESSAGE))
+ {
+ // the acknowledge message might be already in the queue
+ if (PeekRPCAndDDEMessage())
+ {
+ // we know that *some* RPC message came in and was
+ // processed. It could have been the Reply we were waiting
+ // for OR some other incoming call. Since we cant tell
+ // which, we return to RPC land. If it was not our Reply
+ // then RPC will call our modal loop again.
+ return _hr;
+ }
+ }
+
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ WORD wOld = HIWORD(dwStatus);
+
+ if (wOld & (QS_POSTMESSAGE))
+ {
+ ComDebOut((DEB_CALLCONT, "Set timeout time to 100\n"));
+ dwWaitTime = 100;
+ }
+#endif //_CHICAGO_
+ }
+
+ ComDebOut((DEB_CALLCONT,
+ "Call MsgWaitForMultiple time:%ld, cEvents:%x hEvent:%x,\n",
+ dwWaitTime, cEvents, rgEvents[0] ));
+
+ dwWakeReason = MsgWaitForMultipleObjects(cEvents, rgEvents, FALSE,
+ dwWaitTime, _dwMsgQInputFlag);
+
+ ComDebOut((DEB_CALLCONT,
+ "MsgWaitForMultipleObjects hr:%ld\n", dwWakeReason));
+ }
+
+
+ // OK, we've done whatever blocking we were going to do and now we have
+ // been woken up, so figure out what event of interest occured to wake
+ // us up and go handle it.
+
+ if (dwWakeReason == (WAIT_OBJECT_0 + cEvents))
+ {
+ // Windows message came in - go process it
+ ComDebOut((DEB_CALLCONT, "BlockFn: Windows Message Arrived\n"));
+ HandleWakeForMsg();
+ }
+ else if (dwWakeReason == WAIT_TIMEOUT)
+ {
+ if (_hr == RPC_S_WAITONTIMER && IsTimerAtZero())
+ {
+ // The Retrytimer timed out - just exit and retransmit the call
+ ComDebOut((DEB_CALLCONT, "BlockFn: Timer at zero\n"));
+ _hr = RPC_E_SERVERCALL_RETRYLATER;
+ }
+ else
+ {
+ // we may have missed a message before we called MsgWaitForMult...
+ // so we go check now for any incoming messages.
+ ComDebOut((DEB_CALLCONT, "BlockFn: Timeout-Look for msgs\n"));
+ HandleWakeForMsg();
+ }
+ }
+ else
+ {
+ // CallComplete signalled - the call is done.
+ Win4Assert(rgEvents[dwWakeReason - WAIT_OBJECT_0] == hEventCallComplete);
+ ComDebOut((DEB_CALLCONT, "BlockFn: CallComplete Event Signaled\n"));
+ _hr = S_OK;
+ }
+
+ ComDebOut((DEB_CALLCONT, "CCliModalLoop::BlockFn this:%x returns:%x\n",
+ this, _hr));
+ return _hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliModalLoop::HandleWakeForMsg (private)
+//
+// Synopsis: Handle wake for the arrival of some kind of message
+//
+// Returns: nothing
+// fClearedQueue flag set if appropriate
+//
+// Algorithm: If this is called to wake up for a posted message, we
+// check the queue status. If the message queue status indicates
+// that there is some kind of a modal loop going on, then we
+// clear all the keyboard and mouse messages in our queue. Then
+// if we wake up for all input, we check the message queue to
+// see whether we need to notify the application that a message
+// has arrived. Then, we dispatch any messages that have to do
+// with the ORPC system. Finally we yield just in case we need
+// to dispatch a send message in the VDM. For an input sync
+// RPC, all we do is a call that will yield to get the pending
+// send message dispatched.
+//
+// History: Dec-93 JohannP Created
+// 13-Aug-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(void) CCliModalLoop::HandleWakeForMsg()
+{
+ MSG msg; // Used for various peeks.
+
+ // Is this an input sync call?
+ if (_dwMsgQInputFlag != QS_SENDMESSAGE)
+ {
+ // No, so we have to worry about the state of the message queue.
+ // We have to be careful that we aren't holding the input focus
+ // on an input synchronized queue.
+
+ // So what is the state of the queue? - note we or QS_TRANSFER because
+ // this an undocumented flag which tells us the the input focus has
+ // changed to us.
+
+ DWORD dwQueueFlags = GetQueueStatus(QS_ALLINPUT | QS_TRANSFER);
+ ComDebOut((DEB_CALLCONT, "Queue Status %lx\n", dwQueueFlags));
+
+ // Call through to the application if we are going to. We do this here
+ // so that the application gets a chance to process any
+ // messages that it wants to and also allows the call control to
+ // dispatch certain messages that it knows how to, thus making the
+ // queue more empty.
+
+ if (((_dwMsgQInputFlag & QS_ALLINPUT) == QS_ALLINPUT) &&
+ FindMessage(dwQueueFlags))
+ {
+ // pending message in the queue
+ HandlePendingMessage();
+ }
+
+ // Did the input focus change to us?
+ if ((LOWORD(dwQueueFlags) & QS_TRANSFER) || _dwFlags & CMLF_CLEAREDQUEUE)
+ {
+ ComDebOut((DEB_CALLCONT, "Message Queue is being cleared\n"));
+ _dwFlags |= CMLF_CLEAREDQUEUE;
+
+ // Try to clear the queue as best we can of any messages that
+ // might be holding off some other modal loop from executing.
+ // So we eat all mouse and key events.
+ if (HIWORD(dwQueueFlags) & QS_KEY)
+ {
+ while (MyPeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST,
+ PM_REMOVE | PM_NOYIELD))
+ {
+ ;
+ }
+ }
+
+ // Clear mouse releated messages if there are any
+ if (HIWORD(dwQueueFlags) & QS_MOUSE)
+ {
+ while (MyPeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST,
+ PM_REMOVE | PM_NOYIELD))
+ {
+ ;
+ }
+
+ while (MyPeekMessage(&msg, NULL, WM_NCMOUSEFIRST,
+ WM_NCMOUSELAST, PM_REMOVE | PM_NOYIELD))
+ {
+ ;
+ }
+
+ while (MyPeekMessage(&msg, NULL, WM_QUEUESYNC, WM_QUEUESYNC,
+ PM_REMOVE | PM_NOYIELD))
+ {
+ ;
+ }
+ }
+
+ // Get rid of paint message if we can as well -- this makes
+ // the screen look so much better.
+ if (HIWORD(dwQueueFlags) & QS_PAINT)
+ {
+ if (MyPeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE | PM_NOYIELD))
+ {
+ ComDebOut((DEB_CALLCONT, "Dispatch paint\n"));
+ DispatchMessage(&msg);
+ }
+ }
+ }
+ }
+ else if (!IsWOWThread() || !IsWOWThreadCallable())
+ {
+ // We need to give user control so that the send message
+ // can get dispatched. Thus the following is simply a no-op
+ // which gets into user to let it dispatch the message.
+ PeekMessage(&msg, 0, WM_NULL, WM_NULL, PM_NOREMOVE);
+ }
+
+ if (IsWOWThread() && IsWOWThreadCallable())
+ {
+ // In WOW, a genuine yield is the only thing to guarantee
+ // that SendMessage will get through
+ g_pOleThunkWOW->YieldTask16();
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliModalLoop::PeekRPCAndDDEMessage
+//
+// Synopsis: Called when a windows message arrives to look for incoming
+// Rpc messages which might be the reply to an outstanding call
+// or may be new incoming request messages. Also looks for
+// DDE messages.
+//
+// Returns: TRUE - found and processed an RPC message
+// FALSE - did not find an RPC message
+//
+// History: 21-Dec-93 JohannP Created
+// 30-Apr-95 Rickhi ReWrite
+//
+//--------------------------------------------------------------------------
+BOOL CCliModalLoop::PeekRPCAndDDEMessage()
+{
+ // loop over all windows looking for incoming Rpc messages. Note that
+ // it is possible for a dispatch here to cause one of the windows to
+ // be deregistered or another to be registered, so our loop has to account
+ // for that, hence the check for NULL hWnd.
+
+ BOOL fRet = FALSE;
+ MSG Msg;
+
+ for (UINT i = 0; i < 2; i++)
+ {
+ // get window info and peek on it if the hWnd is still OK
+ SWindowData *pWD = _pACC->GetWindowData(i);
+
+ if (pWD->hWnd != WD_EMPTY)
+ {
+ if (MyPeekMessage(&Msg, pWD->hWnd, pWD->wFirstMsg, pWD->wLastMsg,
+ PM_REMOVE | PM_NOYIELD))
+ {
+ Win4Assert(IsWaiting());
+ DispatchMessage(&Msg);
+
+ // exit on the first dispatched message. If the message was
+ // not the reply we were waiting for, then the channel will
+ // call us back again.
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliModalLoop::FindMessage
+//
+// Synopsis: Called by HandleWakeForMsg when a message arrives on the
+// windows msg queue. Determines if there is something of
+// interest to us, and pulls timer msgs. Dispatches RPC, DDE,
+// and RPC timer messages.
+//
+// Arguments: [dwStatus] - current Queue status (from GetQueueStatus)
+//
+// Returns: TRUE - there is a message to process
+// FALSE - no messages to process
+//
+// Algorithm: Find the next message in the queue by using the following
+// priority list:
+//
+// 1. RPC and DDE messages
+// 2. mouse and keyboard messages
+// 3. other messages
+//
+// History: 21-Dec-93 Johannp Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(BOOL) CCliModalLoop::FindMessage(DWORD dwStatus)
+{
+ WORD wOld = HIWORD(dwStatus);
+ WORD wNew = (WORD) dwStatus;
+
+ if (!wNew)
+ {
+ if (!(wOld & QS_POSTMESSAGE))
+ return FALSE; // no messages to take care of
+ else
+ wNew |= QS_POSTMESSAGE;
+ }
+
+ MSG Msg;
+
+ // Priority 1: look for RPC and DDE messages
+ if (wNew & (QS_POSTMESSAGE | QS_SENDMESSAGE | QS_TIMER))
+ {
+ if (PeekRPCAndDDEMessage())
+ {
+ // we know that *some* RPC message came in, might be our
+ // reply or may be some incoming call. In any case, return to
+ // the modal loop to guy so we can figure out if we need to
+ // keep going.
+ return FALSE;
+ }
+ }
+
+ if (wNew & QS_TIMER)
+ {
+ // throw the system timer messages away
+ while (MyPeekMessage(&Msg, 0, WM_SYSTIMER, WM_SYSTIMER, PM_REMOVE | PM_NOYIELD))
+ ;
+ }
+
+ // Priority 2: messages from the hardware queue
+ if (wNew & (QS_KEY | QS_MOUSEMOVE | QS_MOUSEBUTTON))
+ {
+ return TRUE; // these messages are always removed
+ }
+ else if (wNew & QS_TIMER)
+ {
+ if (MyPeekMessage(&Msg, 0, WM_TIMER, WM_TIMER, PM_NOREMOVE | PM_NOYIELD) )
+ return TRUE;
+ }
+ else if (wNew & QS_PAINT)
+ {
+ return TRUE; // this message might not get removed
+ }
+ else if (wNew & (QS_POSTMESSAGE | QS_SENDMESSAGE))
+ {
+ if (MyPeekMessage(&Msg, 0, 0, 0, PM_NOREMOVE))
+ return TRUE; // Priority 3: all other messages
+ }
+
+ return FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliModalLoop::HandlePendingMessage
+//
+// Synopsis: this function is called for system messages and other
+// pending messages
+//
+// Arguments: none
+//
+// Returns: nothing, _hr may be updated if call is cancelled.
+//
+// Algorithm:
+//
+// History: 21-Dec-93 Johannp Created
+// 30-Apr-95 Rickhi ReWrite
+//
+//--------------------------------------------------------------------------
+INTERNAL_(void) CCliModalLoop::HandlePendingMessage()
+{
+ // get and call the message filter if there is one
+ IMessageFilter *pMF = _pACC->GetMsgFilter();
+
+ if (pMF)
+ {
+ ComDebOut((DEB_MFILTER,
+ "pMF->MessagePending(dwTIDCallee:%x ElapsedTime:%x Type:%x)\n",
+ _dwTIDCallee, GetElapsedTime(),
+ (_pPrev) ? PENDINGTYPE_NESTED : PENDINGTYPE_TOPLEVEL));
+
+ DWORD dwRet = pMF->MessagePending((MF_HTASK)_dwTIDCallee,
+ GetElapsedTime(),
+ (_pPrev) ? PENDINGTYPE_NESTED
+ : PENDINGTYPE_TOPLEVEL);
+
+ ComDebOut((DEB_MFILTER,"pMF->MessagePending() dwRet:%x\n", dwRet));
+
+
+ _pACC->ReleaseMsgFilter();
+
+ if (dwRet == PENDINGMSG_CANCELCALL)
+ {
+ _hr = RPC_E_CALL_CANCELED;
+ return;
+ }
+
+ Win4Assert((dwRet == PENDINGMSG_WAITDEFPROCESS ||
+ dwRet == PENDINGMSG_WAITNOPROCESS) &&
+ "Invalid return value from pMF->MessagePending");
+ }
+
+ // if we get here we are going to do the default message processing.
+ // Default Processing: Continue to wait for the call return and
+ // don't dispatch the new message. Perform default processing on
+ // special system messages.
+
+ MSG msg;
+
+ // we have to take out all syscommand messages
+ if (MyPeekMessage(&msg, 0, WM_SYSCOMMAND, WM_SYSCOMMAND, PM_REMOVE | PM_NOYIELD))
+ {
+ // only dispatch some syscommands
+ if (msg.wParam == SC_HOTKEY || msg.wParam == SC_TASKLIST)
+ {
+ ComDebOut((DEB_CALLCONT,">>>> Dispatching SYSCOMMAND message: %x; wParm: %x \r\n",msg.message, msg.wParam));
+ DispatchMessage(&msg);
+ }
+ else
+ {
+ ComDebOut((DEB_CALLCONT,">>>> Received/discarded SYSCOMMAND message: %x; wParm: %x \r\n",msg.message, msg.wParam));
+ MessageBeep(0);
+ }
+ }
+ else if (MyPeekMessage(&msg, 0, WM_SYSKEYDOWN, WM_SYSKEYDOWN, PM_NOREMOVE | PM_NOYIELD))
+ {
+ if (msg.message == WM_KEYDOWN)
+ {
+ if (msg.wParam != VK_CONTROL && msg.wParam != VK_SHIFT)
+ MessageBeep(0);
+ }
+ else if (msg.message == WM_SYSKEYDOWN && msg.lParam & SYS_ALTDOWN &&
+ (msg.wParam == VK_TAB || msg.wParam == VK_ESCAPE))
+ {
+ MyPeekMessage(&msg, 0, WM_SYSKEYDOWN, WM_SYSKEYDOWN, PM_REMOVE | PM_NOYIELD);
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ else if (MyPeekMessage(&msg, 0, WM_ACTIVATE, WM_ACTIVATE, PM_REMOVE | PM_NOYIELD)
+ || MyPeekMessage(&msg, 0, WM_ACTIVATEAPP, WM_ACTIVATEAPP, PM_REMOVE | PM_NOYIELD)
+ || MyPeekMessage(&msg, 0, WM_NCACTIVATE, WM_NCACTIVATE, PM_REMOVE | PM_NOYIELD) )
+ {
+ DispatchMessage(&msg);
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliModalLoop::MyPeekMessage
+//
+// Synopsis: This function is called whenever we want to do a PeekMessage.
+// It intercepts WM_QUIT messages and remembers them so that
+// they can be reposted when the modal loop is exited.
+//
+// Arguments: [pMsg] - message structure
+// [hWnd] - window to peek on
+// [min/max] - min and max message numbers
+// [wFlag] - peek flags
+//
+// Returns: TRUE - a message is available
+// FALSE - no messages available
+//
+// History: 21-Dec-93 Johannp Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(BOOL) CCliModalLoop::MyPeekMessage(MSG *pMsg, HWND hwnd,
+ UINT min, UINT max, WORD wFlag)
+{
+ BOOL fRet = PeekMessage(pMsg, hwnd, min, max, wFlag);
+
+ while (fRet)
+ {
+ ComDebOut((DEB_CALLCONT, "MyPeekMessage: hwnd:%x msg:%d time:%ld\n",
+ pMsg->hwnd, pMsg->message, pMsg->time));
+
+ if (pMsg->message != WM_QUIT)
+ {
+ // it is not a QUIT message so exit the loop and return TRUE
+ break;
+ }
+
+ // just remember that we saw a QUIT message. we will ignore it for
+ // now and repost it after our call has completed.
+
+ ComDebOut((DEB_CALLCONT, "WM_QUIT received.\n"));
+ _wQuitCode = pMsg->wParam;
+ _dwFlags |= CMLF_QUITRECEIVED;
+
+ if (!(wFlag & PM_REMOVE)) // NOTE: dont use PM_NOREMOVE
+ {
+ // quit message is still on queue so pull it off
+ PeekMessage(pMsg, hwnd, WM_QUIT, WM_QUIT, PM_REMOVE | PM_NOYIELD);
+ }
+
+ // peek again to see if there is another message
+ fRet = PeekMessage(pMsg, hwnd, min, max, wFlag);
+ }
+
+ return fRet;
+}
+
+#if DBG==1
+//+-------------------------------------------------------------------------
+//
+// Member: CCliModalLoop::DispatchMessage
+//
+// Synopsis: This function is called whenever we want to dispatch a
+// message we have peeked. It is just a debug wrapper to provide
+// debug out statements about dispatched messages.
+//
+// Arguments: [pMsg] - message structure
+//
+//--------------------------------------------------------------------------
+INTERNAL_(void) CCliModalLoop::DispatchMessage(MSG *pMsg)
+{
+ ComDebOut((DEB_CALLCONT, "Dispatching Message hWnd:%x msg:%d wParam:%x\n",
+ pMsg->hwnd, pMsg->message, pMsg->wParam));
+
+ ::DispatchMessage(pMsg);
+}
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliModalLoop::GetElapsedTime
+//
+// Synopsis: Get the elapsed time for an RPC call
+//
+// Returns: Elapsed time of current call
+//
+// Algorithm: This checks whether we have the slow time factor. If not,
+// and we are in WOW we read it from the registry. Otherwise,
+// it is just set to one. Then we calculate the time of the
+// RPC call and divide it by the slow time factor.
+//
+// History: 22-Jul-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(DWORD) CCliModalLoop::GetElapsedTime()
+{
+ // Define slow time factor to something invalid
+ static dwSlowTimeFactor = 0;
+
+ if (dwSlowTimeFactor == 0)
+ {
+ if (IsWOWProcess())
+ {
+ // Get time factor from registry otherwise set to the default
+ dwSlowTimeFactor = GetSlowTimeFactor();
+ }
+ else
+ {
+ // Time is unmodified for 32 bit apps
+ dwSlowTimeFactor = 1;
+ }
+ }
+
+ DWORD dwTickCount = GetTickCount();
+ DWORD dwElapsedTime = dwTickCount - _dwTimeOfCall;
+ if (dwTickCount < _dwTimeOfCall)
+ {
+ // the timer wrapped
+ dwElapsedTime = 0xffffffff - _dwTimeOfCall + dwTickCount;
+ }
+
+ return (dwElapsedTime / dwSlowTimeFactor);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliModalLoop::FindPrevCallOnLID [server side]
+//
+// Synopsis: When an incoming call arrives this is used to find any
+// previous call for the same logical thread, ignoring
+// INTERNAL calls. The result is used to determine if this
+// is a nested call or not.
+//
+// Arguments: [lid] - logical threadid of incoming call
+//
+// Returns: pCML - if a previous CliModalLoop found for this lid
+// NULL - otherwise
+//
+// Algorithm: just walk backwards on the _pPrev chain
+//
+// History: 17-Dec-93 JohannP Created
+// 30-Apr-95 Rickhi ReWrite
+//
+//--------------------------------------------------------------------------
+CCliModalLoop *CCliModalLoop::FindPrevCallOnLID(REFLID lid)
+{
+ CCliModalLoop *pCML = this;
+
+ do
+ {
+ if (pCML->_lid == lid)
+ {
+ break; // found a match, return it
+ }
+
+ } while ((pCML = pCML->_pPrev) != NULL);
+
+ return pCML;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: STAInvoke
+//
+// Synopsis: Called whenever an incoming call arrives in a single-threaded
+// apartment. It asks the apps message filter (if there is one)
+// whether it wants to handle the call or not, and dispatches
+// the call if OK.
+//
+// Arguments: [pMsg] - Incoming Rpc message
+// [pStub] - stub to call if MF says it is OK
+// [pChnl] - channel ptr to give to stub
+// [pv] - real interface being called
+// [pdwFault] - where to store fault code if there is a fault
+//
+// Returns: result for MF or from call to stub
+//
+// History: 21-Dec-93 Johannp Original Version
+// 22-Jul-94 Rickhi ReWrite
+//
+//--------------------------------------------------------------------------
+INTERNAL STAInvoke(RPCOLEMESSAGE *pMsg, DWORD CallCatIn, IRpcStubBuffer *pStub,
+ IRpcChannelBuffer *pChnl, void *pv, DWORD *pdwFault)
+{
+ ComDebOut((DEB_CALLCONT,
+ "STAInvoke pMsg:%x CallCatIn:%x pStub:%x pChnl:%x\n",
+ pMsg, CallCatIn, pStub, pChnl));
+
+ HRESULT hr = HandleIncomingCall(*MSG_TO_IIDPTR(pMsg),
+ (WORD)pMsg->iMethod,
+ CallCatIn, pv);
+ if (hr == S_OK)
+ {
+ // the message filter says its OK to invoke the call.
+
+ // construct a server call state. This puts the current incoming
+ // call's CallCat in Tls so we can check it if the server tries to
+ // make an outgoing call while handling this call. See CanMakeOutCall.
+ CSrvCallState SCS(CallCatIn);
+
+ // invoke the call
+ hr = MTAInvoke(pMsg, CallCatIn, pStub, pChnl, pdwFault);
+ }
+ else if (hr == RPC_E_CALL_REJECTED || hr == RPC_E_SERVERCALL_RETRYLATER)
+ {
+ // server is rejecting the call, try to copy the incomming buffer so
+ // that the client has the option of retrying the call.
+ hr = CopyMsgForRetry(pMsg, pChnl, hr);
+ }
+
+ ComDebOut((DEB_CALLCONT,"STAInvoke returns:%x\n",hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HandleIncomingCall, internal
+//
+// Synopsis: Called whenever an incoming call arrives in a single-threaded
+// apartment. It asks the app's message filter (if there is one)
+// whether it wants to handle the call or not
+//
+// Arguments: [piid] - ptr to interface the call is being made on
+// [iMethod] - method number being called
+// [CallCatIn] - category of incoming call
+// [pv] - real interface being called
+//
+// Returns: result from MF
+//
+// History: 11-Oct-96 Rickhi Separated from STAInvoke
+//
+//--------------------------------------------------------------------------
+INTERNAL HandleIncomingCall(REFIID riid, WORD iMethod, DWORD CallCatIn, void *pv)
+{
+ ComDebOut((DEB_CALLCONT,
+ "HandleIncomingCall iid:%I iMethod:%x CallCatIn:%x pv:%x:%x\n",
+ &riid, iMethod, CallCatIn, pv));
+
+ COleTls tls;
+ if (!(tls->dwFlags & OLETLS_APARTMENTTHREADED))
+ {
+ // free-threaded apartments don't have a message filter
+ return S_OK;
+ }
+
+ HRESULT hr = S_OK;
+ CAptCallCtrl *pACC = tls->pCallCtrl;
+
+
+ // We dont call the message filter for IUnknown since older versions
+ // of OLE did not, and doing so (unfortunately) breaks compatibility.
+ // Also check for IRundown since local clients call on it instead of
+ // IRemUnknown.
+
+ IMessageFilter *pMF = (riid == IID_IRundown || riid == IID_IRemUnknown)
+ ? NULL : pACC->GetMsgFilter();
+
+ if (pMF)
+ {
+ // the app has installed a message filter, call it.
+
+ INTERFACEINFO IfInfo;
+ IfInfo.pUnk = (IUnknown *)pv;
+ IfInfo.iid = riid;
+ IfInfo.wMethod = iMethod;
+
+ ComDebOut((DEB_CALLCONT, "Calling iMethod:%x riid:%I\n",
+ IfInfo.wMethod, &IfInfo.iid));
+
+ CCliModalLoop *pCML = NULL;
+ REFLID lid = tls->LogicalThreadId;
+ DWORD TIDCaller = tls->dwTIDCaller;
+
+ DWORD dwCallType = pACC->GetCallTypeForInCall(&pCML, lid, CallCatIn);
+ DWORD dwElapsedTime = (pCML) ? pCML->GetElapsedTime() : 0;
+
+ // The DDE layer doesn't provide any interface information. This
+ // was true on the 16-bit implementation, and has also been
+ // brought forward into this implementation to insure
+ // compatibility. However, the CallCat of the IfInfo is still
+ // provided.
+ //
+ // Therefore, if pIfInfo has its pUnk member set to NULL, then
+ // we are going to send a NULL pIfInfo to the message filter.
+
+ ComDebOut((DEB_MFILTER,
+ "pMF->HandleIncomingCall(dwCallType:%x TIDCaller:%x dwElapsedTime:%x IfInfo:%x)\n",
+ dwCallType, TIDCaller, dwElapsedTime, (IfInfo.pUnk) ? &IfInfo : NULL));
+
+ DWORD dwRet = pMF->HandleInComingCall(dwCallType,
+ (MF_HTASK)TIDCaller,
+ dwElapsedTime,
+ IfInfo.pUnk ? &IfInfo : NULL);
+
+ ComDebOut((DEB_MFILTER,"pMF->HandleIncomingCall() dwRet:%x\n", dwRet));
+
+ pACC->ReleaseMsgFilter();
+
+ // strict checking of app return code for win32
+ Win4Assert(dwRet == SERVERCALL_ISHANDLED ||
+ dwRet == SERVERCALL_REJECTED ||
+ dwRet == SERVERCALL_RETRYLATER ||
+ IsWOWThread() && "Invalid Return code from App IMessageFilter");
+
+
+ if (dwRet != SERVERCALL_ISHANDLED)
+ {
+ if (CallCatIn == CALLCAT_ASYNC || CallCatIn == CALLCAT_INPUTSYNC)
+ {
+ // Note: input-sync and async calls can not be rejected
+ // Even though they can not be rejected, we still have to
+ // call the MF above to maintain 16bit compatability.
+ hr = S_OK;
+ }
+ else if (dwRet == SERVERCALL_REJECTED)
+ {
+ hr = RPC_E_CALL_REJECTED;
+ }
+ else if (dwRet == SERVERCALL_RETRYLATER)
+ {
+ hr = RPC_E_SERVERCALL_RETRYLATER;
+ }
+ else
+ {
+ // 16bit OLE let bogus return codes go through and of course
+ // apps rely on that behaviour so we let them through too, but
+ // we are more strict on 32bit.
+ hr = (IsWOWThread()) ? S_OK : RPC_E_UNEXPECTED;
+ }
+ }
+ }
+
+ ComDebOut((DEB_CALLCONT, "HandleIncomingCall hr:%x\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: MTAInvoke
+//
+// Synopsis: Multi-Threaded Apartment Invoke. Called whenever an incoming
+// call arrives in the MTA apartment (or as a subroutine to
+// STAInvoke). It just dispatches to a common sub-routine.
+//
+// Arguments: [pMsg] - Incoming Rpc message
+// [pStub] - stub to call if MF says it is OK
+// [pChnl] - channel ptr to give to stub
+// [pdwFault] - where to store fault code if there is a fault
+//
+// Returns: result from calling the stub
+//
+// History: 03-Oct-95 Rickhi Made into subroutine from STAInvoke
+//
+//--------------------------------------------------------------------------
+INTERNAL MTAInvoke(RPCOLEMESSAGE *pMsg, DWORD CallCatIn, IRpcStubBuffer *pStub,
+ IRpcChannelBuffer *pChnl, DWORD *pdwFault)
+{
+#if DBG==1
+ ComDebOut((DEB_CALLCONT,
+ "MTAInvoke pMsg:%x CallCatIn:%x pStub:%x pChnl:%x\n",
+ pMsg, CallCatIn, pStub, pChnl));
+ IID *piid = MSG_TO_IIDPTR(pMsg);
+ DebugPrintORPCCall(ORPC_INVOKE_BEGIN, *piid, pMsg->iMethod, CallCatIn);
+ RpcSpy((CALLIN_BEGIN, NULL, *piid, pMsg->iMethod, 0));
+#endif
+
+ // call a common subroutine to do the dispatch. The subroutine also
+ // catches exceptions and provides some debug help.
+
+ HRESULT hr = StubInvoke(pMsg, pStub, pChnl, pdwFault);
+
+#if DBG==1
+ RpcSpy((CALLIN_END, NULL, *piid, pMsg->iMethod, hr));
+ DebugPrintORPCCall(ORPC_INVOKE_END, *piid, pMsg->iMethod, CallCatIn);
+ ComDebOut((DEB_CALLCONT,"MTAInvoke returns:%x\n",hr));
+#endif
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CopyMsgForRetry
+//
+// Synopsis: Makes a copy of the server-side message buffer to return to
+// the client so that the client can retry the call later.
+// Returns an error if the client is on a different machine.
+//
+// Parameters: [pMsg] - ptr to message to copy
+// [pChnl] - ptr to channel call is being made on
+// [hr] - result code
+//
+// History: 30-05-95 Rickhi Created
+//
+//+-------------------------------------------------------------------------
+HRESULT CopyMsgForRetry(RPCOLEMESSAGE *pMsg, IRpcChannelBuffer *pChnl, HRESULT hrIn)
+{
+ ComDebOut((DEB_CALLCONT,"CopyMsgForRetry pMsg:%x pChnl:%x pBuffer:%x\n",
+ pMsg, pChnl, pMsg->Buffer));
+
+ DWORD dwDestCtx;
+ HRESULT hr = pChnl->GetDestCtx(&dwDestCtx, NULL);
+
+ if (SUCCEEDED(hr) && dwDestCtx != MSHCTX_DIFFERENTMACHINE &&
+ !IsEqualGUID(IID_IObjServer, *MSG_TO_IIDPTR(pMsg)))
+ {
+ // client on same machine as server.
+ void *pSavedBuffer = pMsg->Buffer;
+ hr = pChnl->GetBuffer(pMsg, *MSG_TO_IIDPTR(pMsg));
+
+ if (SUCCEEDED(hr))
+ {
+ // copy original buffer to the new buffer
+ memcpy(pMsg->Buffer, pSavedBuffer, pMsg->cbBuffer);
+ hr = hrIn;
+ }
+ }
+ else
+ {
+ // client on different machine than server, or the call was on
+ // the activation interface, fail the call and dont send back
+ // a copy of the parameter packet.
+ hr = RPC_E_CALL_REJECTED;
+ }
+
+ ComDebOut((DEB_CALLCONT,"CopyMsgForRetry pBuffer:%x hr:%x\n",
+ pMsg->Buffer, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CAptCallCtrl::GetCallTypeForInCall
+//
+// Synopsis: called when an incoming call arrives in order to determine
+// what CALLTYPE to pass to the applications message filter.
+//
+// Arguments: [ppCML] - Client Modal Loop of prev call on same lid (if any)
+// [lid] - logical thread id of this call
+// [dwCallCat] - call category of incoming call
+//
+// Returns: the CALLTYPE to give to the message filter
+//
+// History: 21-Dec-93 Johannp Created
+// 30-Apr-95 Rickhi ReWrite
+//
+// Notes:
+//
+// 1 = CALLTYPE_TOPLEVEL // sync or inputsync call - no outgoing call
+// 2 = CALLTYPE_NESTED // callback on behalf of previous outgoing call
+// 3 = CALLTYPE_ASYNC // asynchronous call - no outstanding call
+// 4 = CALLTYPE_TOPLEVEL_CALLPENDING // call with new LID - outstand call
+// 5 = CALLTYPE_ASYNC_CALLPENDING // async call - outstanding call
+//
+//--------------------------------------------------------------------------
+DWORD CAptCallCtrl::GetCallTypeForInCall(CCliModalLoop **ppCML,
+ REFLID lid, DWORD dwCallCatIn)
+{
+ DWORD CallType;
+ CCliModalLoop *pCML = GetTopCML();
+
+ if (dwCallCatIn == CALLCAT_ASYNC) // asynchronous call has arrived
+ {
+ if (pCML == NULL)
+ CallType = CALLTYPE_ASYNC; // no outstanding calls
+ else
+ CallType = CALLTYPE_ASYNC_CALLPENDING; // outstanding call
+ }
+ else // non-async call has arrived
+ {
+ if (pCML == NULL)
+ CallType = CALLTYPE_TOPLEVEL; // no outstanding call
+ else if ((*ppCML = pCML->FindPrevCallOnLID(lid)) != NULL)
+ CallType = CALLTYPE_NESTED; // outstanding call on same lid
+ else
+ CallType = CALLTYPE_TOPLEVEL_CALLPENDING; // different lid
+ }
+
+ ComDebOut((DEB_CALLCONT,"GetCallTypeForInCall return:%x\n", CallType));
+ return CallType;
+}
+
diff --git a/private/ole32/com/dcomrem/callctrl.hxx b/private/ole32/com/dcomrem/callctrl.hxx
new file mode 100644
index 000000000..44b2efcd1
--- /dev/null
+++ b/private/ole32/com/dcomrem/callctrl.hxx
@@ -0,0 +1,525 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: callctrl.hxx
+//
+// Contents: OLE Call Control
+//
+// Functions:
+//
+// History: 21-Dec-93 Johannp Original Version
+// 04-Nov-94 Rickhi ReWrite
+//
+//--------------------------------------------------------------------------
+#ifndef __CALLCTRL_HXX__
+#define __CALLCTRL_HXX__
+
+#include <channelb.hxx> // CRpcChannelBuffer
+
+#undef RPC_S_CALLPENDING
+#undef RPC_S_WAITONTIMER
+#define RPC_S_CALLPENDING 21 // BUGBUG
+#define RPC_S_WAITONTIMER 22 // BUGBUG
+
+// Max time we wait for MsgWaitForMultiple before waking up and
+// checking the queue. This is needed because the API is broken
+// (ie it does not wake up on messages posted before it is called).
+#define MAX_TICKS_TO_WAIT 1000
+
+
+// Private definition for change of input focus
+// BUGBUG: fix for CHICAGO when chicago's USER supports QS_TRANSFER
+#ifdef _CHICAGO_
+#define QS_TRANSFER 0x0000
+#else
+#define QS_TRANSFER 0x4000
+#endif
+
+
+typedef IID LID; // logical thread id
+typedef REFIID REFLID; // ref to logical thread id
+
+#define MF_HTASK struct HTASK__ *
+
+
+// the following table is used to quickly determine what windows
+// message queue inputflag to specify for the various categories of
+// outgoing calls in progress. The table is indexed by CALLCATEGORY.
+
+extern DWORD gMsgQInputFlagTbl[4]; // see callctrl.cxx
+
+// the following table is used to map bit flags in the Rpc Message to
+// the equivalent OLE CALLCATEGORY.
+
+extern DWORD gRpcFlagToCallCatMap[3]; // see callctrl.cxx
+
+// the following inline funtion is used to compute the CALLCATEGORY from
+// the RpcFlags field in the RPC message
+
+inline DWORD RpcFlagToCallCat(DWORD RpcFlags)
+{
+ return gRpcFlagToCallCatMap[(RpcFlags & 0x60000000) >> 29];
+}
+
+// convenient mapping from RPCOLEMESSAGE to IID in the message
+#define MSG_TO_IIDPTR(pMsg) \
+ &((RPC_SERVER_INTERFACE *)((RPC_MESSAGE *)pMsg)->RpcInterfaceInformation)->InterfaceId.SyntaxGUID
+
+
+// private structure used to hold the window handles and message ranges
+// to peek to see if there is more work to do when in the modal loop.
+
+typedef struct tagSWindowData
+{
+ HWND hWnd; // window handle to peek on
+ UINT wFirstMsg; // first msg in range to peek
+ UINT wLastMsg; // Last msg in range to peek
+} SWindowData;
+
+
+// function prototypes. This function is called by the channel during
+// transmission in the apartment model.
+
+RPC_STATUS OleModalLoopBlockFn(void *, void *, HANDLE hEventComplete);
+
+
+// function called by the channel during dispatch in the apartment model.
+// STAInvoke is used for single-threaded apartments, MTAInvoke is used
+// for Multi-threaded apartments.
+
+INTERNAL STAInvoke(RPCOLEMESSAGE *pMsg, DWORD dwCallCat, IRpcStubBuffer *pStub,
+ IRpcChannelBuffer *pChnl, void *pv, DWORD *pdwFault);
+
+INTERNAL MTAInvoke(RPCOLEMESSAGE *pMsg, DWORD dwCallCat, IRpcStubBuffer *pStub,
+ IRpcChannelBuffer *pChnl, DWORD *pdwFault);
+
+INTERNAL CanMakeOutCall(DWORD dwCallCatOut, REFIID riid);
+
+class CAptCallCtrl;
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetAptCallCtrl
+//
+// Synopsis: Gets the current apartment's call control ptr from TLS.
+//
+//+-------------------------------------------------------------------------
+inline CAptCallCtrl *GetAptCallCtrl(void)
+{
+ COleTls tls;
+ return tls->pCallCtrl;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CAptRpcChnl
+//
+// Synopsis: Client side Apartment model Rpc Channel.
+//
+// History: 11-Nov-94 Rickhi Created
+//
+// Notes: This object inherits the Rpc channel and adds some
+// functionality to it that is needed by the apartment model,
+// (eg deadlock prevention, call retry, nested call support).
+// For each outgoing call, it verifies the app is allowed to
+// make the call, and instantiates a modal loop for it, thereby
+// allowing callbacks and new calls to be handled by the app
+// thread.
+//
+// Important: Since no mutual exclusion primitives are used in this code,
+// the derived class CAptRpcChnl must be stateless, as some
+// proxies are freethreaded even in the apartment model, in
+// particular, IRemUnknown and the SCM activation interface. All
+// relevant state is maintained in the CCliModalLoop object which
+// is constructed on the stack on a per call basis. Note that the
+// _dwTIDCallee state is safe because it is set in the ctor and
+// never changes. The base class, CRpcChannelBuffer *is* thread
+// safe since it is used in the freethreaded model also.
+//
+//--------------------------------------------------------------------------
+class CAptRpcChnl : public CRpcChannelBuffer
+{
+public:
+ CAptRpcChnl(CStdIdentity *pStdId, OXIDEntry *pOXIDEntry, DWORD eState);
+
+ // CRpcChannelBuffer methods that we override
+ STDMETHOD (GetBuffer) (RPCOLEMESSAGE *pMsg, REFIID riid);
+ STDMETHOD (SendReceive) (RPCOLEMESSAGE *pMsg, ULONG *pulStatus);
+
+private:
+ ~CAptRpcChnl(); // can only be called from Release
+ HRESULT CopyMsgForRetry(RPCOLEMESSAGE *pMsg);
+
+ DWORD _dwTIDCallee; // TID of thread server lives on
+ DWORD _dwAptId; // Apartment ID proxy lives in.
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CMTARpcChnl
+//
+// Synopsis: Client side Multi-Threaded Apartment Rpc Channel.
+//
+// History: 11-Nov-94 Rickhi Created
+//
+// Notes: This object inherits the Rpc channel and adds some
+// functionality to it that is needed by Multi-threaded apartment.
+// For each outgoing call, it verifies the app is allowed to
+// make the call.
+//
+// Important: Since no mutual exclusion primitives are used in this code,
+// the derived class CMTARpcChnl must be stateless. Note that the
+// _dwTIDCallee state is safe because it is set in the ctor and
+// never changes. The base class, CRpcChannelBuffer *is* thread
+// safe.
+//
+//--------------------------------------------------------------------------
+class CMTARpcChnl : public CRpcChannelBuffer
+{
+public:
+ CMTARpcChnl(CStdIdentity *pStdId, OXIDEntry *pOXIDEntry, DWORD eState);
+
+ // CRpcChannelBuffer methods that we override
+ STDMETHOD (GetBuffer) (RPCOLEMESSAGE *pMsg, REFIID riid);
+
+private:
+ ~CMTARpcChnl(); // can only be called from Release
+
+ DWORD _dwTIDCallee; // TID of thread server lives on
+ DWORD _dwAptId; // Apartment ID proxy lives in.
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CCliModalLoop
+//
+// Synopsis: Each outgoing client call enters a modal loop. This object
+// maintains the state of the modal loop for one outgoing
+// call.
+//
+// History: 11-Nov-94 Rickhi Created
+//
+// Notes: This object is constructed on the stack on a per call basis
+// and needs no mutual exclusion mechanisms. A pointer to this
+// state is stored in TLS (actually in CAptCallCtrl in TLS) and
+// later referenced when OleModalLoopBlockFn is called from deep
+// within the bowls of SendReceive in the channel (or Rpc Runtime
+// if the MSWMSG transport is used).
+//
+//--------------------------------------------------------------------------
+class CCliModalLoop
+{
+public:
+ CCliModalLoop(DWORD TIDCallee, DWORD CallCatOut);
+ ~CCliModalLoop();
+
+ CCliModalLoop *FindPrevCallOnLID(REFLID lid);
+ HRESULT SendReceive(RPCOLEMESSAGE *pMsg, ULONG *pulStatus,
+ IRpcChannelBuffer2 *pChnl);
+ HRESULT BlockFn(HANDLE hEventCallComplete);
+ BOOL IsWaiting(void)
+ {
+ return (_hr == RPC_S_CALLPENDING || _hr == RPC_S_WAITONTIMER);
+ }
+
+ INTERNAL_(BOOL) MyPeekMessage(MSG *pMsg, HWND hwnd, UINT min, UINT max, WORD wFlag);
+ INTERNAL_(DWORD) GetElapsedTime();
+
+private:
+ // message processing in modal loop
+ INTERNAL_(void) HandleWakeForMsg(void);
+ INTERNAL_(BOOL) FindMessage(DWORD dwStatus);
+ INTERNAL_(void) HandlePendingMessage(void);
+ INTERNAL_(BOOL) PeekRPCAndDDEMessage(void);
+
+#if DBG==1
+ INTERNAL_(void) DispatchMessage(MSG *pMsg);
+#endif
+
+ // rejected call processing
+ INTERNAL HandleRejectedCall(IRpcChannelBuffer2 *pChnl);
+ INTERNAL StartTimer(DWORD dwMilliSecToWait);
+ INTERNAL_(BOOL) IsTimerAtZero();
+ INTERNAL_(DWORD) TicksToWait();
+
+
+ HRESULT _hr; // the return value of this call
+ CCliModalLoop *_pPrev; // Previous CCliModalLoop for this apartment
+ DWORD _dwTIDCallee; // TID of thread we are calling
+ DWORD _dwMsgQInputFlag; // message queue input flag
+ LID _lid; // logical threadid of call
+
+ DWORD _dwFlags; // internal flags (see CMLFLAGS)
+ UINT _wQuitCode; // quit code if WM_QUIT received
+
+ DWORD _dwTimeOfCall; // time when call was made
+ DWORD _dwWakeup; // absolute time to wake up
+ DWORD _dwMillSecToWait; // relative time
+
+ CAptCallCtrl *_pACC; // apartment call control object
+};
+
+// bit values for the CliModalLoop _dwFlags field
+typedef enum tagCMLFLAGS
+{
+ CMLF_QUITRECEIVED = 1, // WM_QUIT was received
+ CMLF_CLEAREDQUEUE = 2 // the msg queue has been cleared
+} CMLFLAGS;
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSrvCallState
+//
+// Synopsis: Each incoming server call generates one of these objects.
+// It maintains the state of the incoming call.
+//
+// History: 11-Nov-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+class CSrvCallState
+{
+public:
+ CSrvCallState(DWORD CallCatIn);
+ ~CSrvCallState();
+ DWORD GetCallCatIn(void) { return _dwCallCatIn; }
+
+private:
+ DWORD _dwCallCatIn; // category of this incoming call
+ CSrvCallState *_pPrev; // previous CSrvCallState on the stack
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CAptCallCtrl
+//
+// Synopsis: Represents per apartment Call Control state that is shared
+// between both the client side and server side call control
+// objects.
+//
+// History: 11-Nov-94 Rickhi Created
+//
+// Notes: Two LIFO stacks are maintained, one for client call modal
+// loops, and one for incoming server calls. The incoming
+// server calls are used in both Single-Threaded apartments
+// and multi-threaded apartments, and so are stored in TLS
+// directly, rather than chained off this object.
+//
+//--------------------------------------------------------------------------
+class CAptCallCtrl
+{
+public:
+ CAptCallCtrl();
+ ~CAptCallCtrl();
+
+ // message filter handling methods
+ IMessageFilter *InstallMsgFilter(IMessageFilter *pMF);
+ IMessageFilter *GetMsgFilter();
+ void ReleaseMsgFilter() { _fInMsgFilter = FALSE; }
+ BOOL InMsgFilter() { return _fInMsgFilter; }
+
+ // client side LIFO modal loop queue
+ void SetTopCML(CCliModalLoop *pCML) { _pTopCML = pCML; }
+ CCliModalLoop *GetTopCML(void) { return _pTopCML; }
+
+ // modal loop helper functions
+ SWindowData *GetWindowData(UINT i) { return &_WD[i]; }
+ DWORD GetCallTypeForInCall(CCliModalLoop **ppCML,
+ REFLID lid, DWORD dwCallCatIn);
+
+ // window registration/revocation methods (used by channel & dde)
+ void Register(HWND hWnd, UINT wFirstMsg, UINT wLastMsg);
+ void Revoke(HWND hWnd);
+
+private:
+ IMessageFilter *_pMF; // app supplied Msg Filter
+ BOOL _fInMsgFilter; // TRUE when calling the Apps MF
+
+ CCliModalLoop *_pTopCML; // topmost Client Modal Loop
+
+ SWindowData _WD[2]; // RPC and DDE Window Data
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CCliModalLoop::CCliModalLoop
+//
+// Synopsis: constructor for the client side modal loop
+//
+//+-------------------------------------------------------------------------
+inline CCliModalLoop::CCliModalLoop(DWORD dwTIDCallee, DWORD dwMsgQInputFlag) :
+ _dwTIDCallee(dwTIDCallee),
+ _dwMsgQInputFlag(dwMsgQInputFlag),
+ _dwFlags(0) // all flags start FALSE
+{
+ COleTls tls;
+
+ _lid = tls->LogicalThreadId;
+
+ // push self on top of the per apartment modal loop stack
+ _pACC = tls->pCallCtrl;
+ _pPrev = _pACC->GetTopCML();
+ _pACC->SetTopCML(this);
+
+ _dwTimeOfCall = GetTickCount(); // record start time of the call
+
+ // the rest of the fields are initialized when first used
+
+ ComDebOut((DEB_CALLCONT, "CCliModalLoop::CCliModalLoop at:%x\n", this));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CCliModalLoop::~CCliModalLoop
+//
+// Synopsis: destructor for the client side modal loop
+//
+//+-------------------------------------------------------------------------
+inline CCliModalLoop::~CCliModalLoop()
+{
+ // pop self off the per apartment modal loop stack by resetting the
+ // top of stack to the previous value.
+ _pACC->SetTopCML(_pPrev);
+
+ // repost any WM_QUIT message we intercepted during the call
+ if (_dwFlags & CMLF_QUITRECEIVED)
+ {
+ ComDebOut((DEB_CALLCONT, "posting WM_QUIT\n"));
+ PostQuitMessage(_wQuitCode);
+ }
+
+ ComDebOut((DEB_CALLCONT, "CCliModalLoop::~CCliModalLoop at:%x\n", this));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CCliModalLoop::StartTimer
+//
+// Synopsis: starts a timer when a call is rejected and the client
+// wants to retry it later.
+//
+//+-------------------------------------------------------------------------
+inline HRESULT CCliModalLoop::StartTimer(DWORD dwMilliSecToWait)
+{
+ // Set time when we should awake and retry the call. Note that
+ // if the GetTickCount + dwMilliSecToWait wraps the timer, then
+ // we may wakeup earlier than expected, but at least we wont
+ // deadlock.
+
+ ComDebOut((DEB_CALLCONT,
+ "Timer installed for %lu msec.\n", dwMilliSecToWait));
+
+ _dwMillSecToWait = dwMilliSecToWait;
+ _dwWakeup = GetTickCount() + dwMilliSecToWait;
+
+ // caller should place the return value in _hr
+ return RPC_S_WAITONTIMER;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CCliModalLoop::IsTimerAtZero
+//
+// Synopsis: returns TRUE if the timer is not started or the timer has
+// run down.
+//
+//+-------------------------------------------------------------------------
+inline BOOL CCliModalLoop::IsTimerAtZero()
+{
+ // if no timer installed, return TRUE
+ if (_hr != RPC_S_WAITONTIMER)
+ return TRUE;
+
+ DWORD dwTickCount = GetTickCount();
+
+ // the second test is in case GetTickCount wrapped during
+ // the call. see also the comment in StartTimer.
+
+ if (dwTickCount > _dwWakeup ||
+ dwTickCount < _dwWakeup - _dwMillSecToWait)
+ {
+ // this _hr will tell SendReceive to retransmit the call
+ _hr = RPC_E_SERVERCALL_RETRYLATER;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CCliModalLoop::TicksToWait
+//
+// Synopsis: returns the amount of time to wait for a message to arrive.
+//
+//+-------------------------------------------------------------------------
+inline DWORD CCliModalLoop::TicksToWait()
+{
+ if (_hr != RPC_S_WAITONTIMER)
+ return MAX_TICKS_TO_WAIT;
+
+ // waiting to retry a rejected call
+ DWORD dwTick = GetTickCount();
+ return (_dwWakeup < dwTick) ? 0 : _dwWakeup - dwTick;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CSrvCallState::CSrvCallState
+//
+// Synopsis: constructor for server side call state. Pushes the call
+// state on the call control stack.
+//
+//+-------------------------------------------------------------------------
+inline CSrvCallState::CSrvCallState(DWORD dwCallCatIn) :
+ _dwCallCatIn(dwCallCatIn)
+{
+ // push self on top of the per apartment server call state stack
+ COleTls tls;
+
+ _pPrev = tls->pTopSCS;
+ tls->pTopSCS = this;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CSrvCallState::~CSrvCallState
+//
+// Synopsis: destructor for server side call state. Pops the call
+// state off the call control stack.
+//
+//+-------------------------------------------------------------------------
+inline CSrvCallState::~CSrvCallState()
+{
+ // pop self on top of the per apartment server call state stack
+ COleTls tls;
+ tls->pTopSCS = _pPrev;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CAptCallCtrl::GetMsgFilter
+//
+// Synopsis: returns the IMessageFilter and set the flag indicating we
+// are currently calling the IMF, so that apps are prevented
+// from making outgoing calls while inside their IMF.
+//
+//+-------------------------------------------------------------------------
+inline IMessageFilter *CAptCallCtrl::GetMsgFilter()
+{
+ if (_pMF)
+ {
+ _fInMsgFilter = TRUE;
+ }
+ return _pMF;
+}
+
+#endif // __CALLCTRL_HXX__
diff --git a/private/ole32/com/dcomrem/chancont.cxx b/private/ole32/com/dcomrem/chancont.cxx
new file mode 100644
index 000000000..8c936f93c
--- /dev/null
+++ b/private/ole32/com/dcomrem/chancont.cxx
@@ -0,0 +1,1098 @@
+/*++
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ chancont.cxx
+
+Abstract:
+
+ This module contains thread switching code for the single threaded mode
+ and the message filter hooks
+
+Author:
+
+ Alex Mitchell
+
+Revision History:
+
+ Mar 1994 JohannP Added call category support.
+ 29 Dec 1993 Alex Mitchell Creation.
+ 19 Jul 1994 CraigWi Added support for ASYNC calls
+ 27-Jan-95 BruceMa Don't get on CChannelControl list unless
+ constructor is successsful
+
+Functions:
+
+--*/
+
+#include <ole2int.h>
+#include <userapis.h>
+
+#include <chancont.hxx>
+#include <channelb.hxx>
+#include <threads.hxx>
+#include <objerror.h>
+#include <callctrl.hxx>
+#include <service.hxx>
+#include <ipidtbl.hxx>
+
+/* Prototypes. */
+void Cancel ( CChannelCallInfo ** );
+HRESULT ModalLoop ( CChannelCallInfo *call );
+HRESULT ProtectedPostToSTA( OXIDEntry *, CChannelCallInfo *call );
+HRESULT TransmitCall( OXIDEntry *, CChannelCallInfo * );
+
+/***************************************************************************/
+/* Globals. */
+
+// Rpc worker thread cache.
+CRpcThreadCache gRpcThreadCache;
+
+// Event cache.
+CEventCache gEventCache;
+
+HANDLE CEventCache::_list[] = {0,0,0,0,0,0,0,0};
+DWORD CEventCache::_ifree = 0;
+
+
+extern LPTSTR gOleWindowClass;
+
+extern BOOL gfChannelProcessInitialized;
+
+extern BOOL gfDestroyingMainWindow;
+
+
+ /***************************************************************************/
+CChannelCallInfo::CChannelCallInfo( CALLCATEGORY callcat,
+ RPCOLEMESSAGE *message,
+ DWORD flags,
+ REFIPID ipidServer,
+ DWORD destctx,
+ CRpcChannelBuffer *channel,
+ DWORD authn_level )
+{
+ // The call info must hold a reference to the channel on the client side
+ // because the channel holds the binding handle that ThreadSendReceive
+ // uses.
+ category = callcat;
+ event = NULL;
+ iFlags = flags;
+ eState = in_progress_cs;
+ pmessage = message;
+ ipid = ipidServer;
+ iDestCtx = destctx;
+ pNext = NULL;
+ pHeader = NULL;
+ pChannel = channel;
+ lSavedAuthnLevel = 0;
+ lAuthnLevel = authn_level;
+ if (pChannel != NULL)
+ pChannel->AddRef();
+}
+
+
+ /***************************************************************************/
+CChannelCallInfo::~CChannelCallInfo()
+{
+ if (event != NULL)
+ gEventCache.Free(event);
+
+ // Release the reply buffer.
+ if (eState == canceled_cs && pmessage->Buffer != NULL)
+ DeallocateBuffer(pmessage);
+
+ // Release the channel.
+ if (pChannel != NULL)
+ pChannel->Release();
+}
+
+/***************************************************************************/
+#if DBG==1
+void DebugIsValidWindow(void *hWnd)
+{
+ // USER could be out of memory and unable to validate the handle.
+ // GetDesktopWindow only returns NULL if USER is out of memory. So
+ // we only assert if USER is not out of memory and our window handle
+ // is invalid.
+ if (GetDesktopWindow() == NULL)
+ return;
+
+ Win4Assert( IsWindow((HWND) hWnd));
+}
+#else
+inline void DebugIsValidWindow(void *hWnd) {}
+#endif
+
+/***************************************************************************/
+void Cancel( CChannelCallInfo **call )
+{
+ DWORD result;
+
+ // If the call is still in progress, change it to canceled.
+ LOCK
+ if ((*call)->eState == in_progress_cs)
+ (*call)->eState = canceled_cs;
+ UNLOCK
+
+ // If the call completed before it could be canceled, wait for it to
+ // signal the completion event and clean up.
+ if ((*call)->eState == server_done_cs || (*call)->eState == got_done_msg_cs)
+ {
+ (*call)->eState = canceled_cs;
+ if (IsWOWThread() && (*call)->Local())
+ {
+ // If the reply has arrived, the call can be deleted.
+ if ((*call)->eState == got_done_msg_cs)
+ {
+ delete *call;
+ }
+ // Otherwise
+ // the completion routine will have posted a message instead of
+ // setting an event, so we have to mark it as canceled and cleanup
+ // when the Reply msg comes in.
+ return;
+ }
+ else
+ {
+ // A call that completed in TransmitCall (ie, didn't create an event)
+ // cannot be canceled.
+
+ Win4Assert( (*call)->event != NULL );
+ result = WaitForSingleObject((*call)->event, INFINITE);
+ Win4Assert( result == WAIT_OBJECT_0 );
+
+ delete *call;
+ }
+ }
+
+ // Null the CChannelCallInfo pointer so no one tries to access it.
+ *call = NULL;
+}
+
+/***************************************************************************/
+HRESULT GetToSTA( OXIDEntry *pOxid, CChannelCallInfo *call )
+{
+ TRACECALL(TRACE_RPC, "GetToSTA");
+ ComDebOut((DEB_CHANNEL, "GetToSTA pCall:%x\n", call));
+ gOXIDTbl.ValidateOXID();
+ ASSERT_LOCK_HELD
+
+ HRESULT result;
+
+ Win4Assert(call->event == NULL);
+ Win4Assert(pOxid->dwTid != GetCurrentThreadId());
+
+
+ // Don't accept calls if this thread has been uninitialized.
+ if (pOxid->dwFlags & OXIDF_STOPPED)
+ return RPC_E_SERVER_DIED_DNE;
+
+ if (call->category == CALLCAT_INPUTSYNC)
+ {
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ // On CoUninitialize this may fail when the window is destroyed.
+ // Pass the thread id to aid debugging.
+ SetLastError( 0 );
+ SendMessage((HWND)pOxid->hServerSTA, WM_OLE_ORPC_SEND,
+ GetCurrentThreadId(), (DWORD) call);
+ if (GetLastError() == 0)
+ result = call->hResult;
+ else
+ result = RPC_E_SERVER_DIED;
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+ else if (call->category == CALLCAT_ASYNC)
+ {
+ // async call; copy message, post message and return.
+ // NOTE that in the MTA case, async was converted to SYNC by
+ // the call control.
+
+ CChannelCallInfo *copy = MakeAsyncCopy( call );
+ if (copy == NULL)
+ {
+ result = RPC_E_OUT_OF_RESOURCES;
+ }
+ else
+ {
+ // Post a message and wait for the app to get back to GetMessage.
+ result = ProtectedPostToSTA( pOxid, copy );
+
+ if (result != S_OK)
+ {
+ // error in posting; free packet and return error (result set above)
+ delete copy;
+ }
+ }
+ }
+ else
+ {
+ Win4Assert( call->category == CALLCAT_SYNCHRONOUS );
+
+ // Get completion event. May cause an event to be created.
+ result = gEventCache.Get( &call->event );
+ if (result == S_OK)
+ {
+ result = ProtectedPostToSTA( pOxid, call );
+
+ if (result == S_OK)
+ {
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ // Wait for the app to finish processing the request.
+ if (WaitForSingleObject(call->event, INFINITE) == WAIT_OBJECT_0)
+ result = call->hResult;
+ else
+ result = RPC_E_SYS_CALL_FAILED;
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+ }
+ }
+
+ ASSERT_LOCK_HELD
+ gOXIDTbl.ValidateOXID();
+ return result;
+}
+
+/***************************************************************************/
+HRESULT ModalLoop( CChannelCallInfo *pcall )
+{
+ ASSERT_LOCK_RELEASED
+ DWORD result;
+
+ // we should only enter the modal loop for synchronous calls or input
+ // synchronous calls to another process or to an MTA apartment within
+ // the current process.
+
+ Win4Assert(pcall->category == CALLCAT_SYNCHRONOUS ||
+ pcall->category == CALLCAT_INPUTSYNC);
+
+
+ // detemine if we are using an event or a postmessage for the call
+ // completion signal. We use PostMessage only for process local
+ // calls in WOW, otherwise we use events and the OleModalLoop determines
+ // if the call completed or not.
+
+ BOOL fMsg = (pcall->Local() && IsWOWThread());
+ BOOL fWait = TRUE;
+ CAptCallCtrl *pACC = GetAptCallCtrl();
+ CCliModalLoop *pCML = pACC->GetTopCML();
+
+ ComDebOut((DEB_CALLCONT,"ModalLoop: wait on %s\n",(fMsg) ? "Msg" : "Event"));
+
+ // Wait at least once so the event is returned to the cache in the
+ // unsignalled state.
+ do
+ {
+ Win4Assert(fMsg || pcall->event);
+
+ result = OleModalLoopBlockFn(NULL, pCML, pcall->event);
+
+ if (fMsg)
+ {
+ if (result == RPC_E_CALL_CANCELED)
+ {
+ fWait = FALSE;
+ }
+ else
+ {
+ // loop until the call's state indicates the arrival of the
+ // reply message.
+ fWait = (pcall->eState != got_done_msg_cs);
+ result = S_OK;
+ }
+ }
+ else
+ {
+ // loop until the OleModalLoop tells us the call is no longer
+ // pending.
+ fWait = (result == RPC_S_CALLPENDING);
+ }
+
+ } while (fWait);
+
+ ASSERT_LOCK_RELEASED
+ return result;
+}
+
+#if DBG==1
+/***************************************************************************/
+LONG ProtectedPostExceptionFilter( DWORD lCode,
+ LPEXCEPTION_POINTERS lpep )
+{
+ ComDebOut((DEB_ERROR, "Exception 0x%x in ProtectedPostToCOMThread at address 0x%x\n",
+ lCode, lpep->ExceptionRecord->ExceptionAddress));
+ DebugBreak();
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+#endif // DBG
+
+/***************************************************************************/
+// executed on client thread (in local case) and RPC thread (in remote case);
+// posts a message to the server thread, guarding against disconnected threads
+HRESULT ProtectedPostToSTA( OXIDEntry *pOxid, CChannelCallInfo *call )
+{
+ ComDebOut((DEB_CHANNEL, "ProtectedPostToSTA hWnd:%x pCall:%x\n",
+ pOxid->hServerSTA, call));
+
+ // ensure we are not posting to ourself and that the apartment is not
+ // an MTA apartment.
+ Win4Assert((pOxid->dwTid != GetCurrentThreadId()) &&
+ ((pOxid->dwFlags & OXIDF_MTASERVER) == 0));
+ ASSERT_LOCK_HELD
+
+ HRESULT result;
+
+ if (!(pOxid->dwFlags & OXIDF_STOPPED))
+ {
+#if DBG==1
+ DebugIsValidWindow(pOxid->hServerSTA);
+ _try
+ {
+#endif
+ // Pass the thread id to aid debugging.
+ if (PostMessage((HWND)pOxid->hServerSTA, WM_OLE_ORPC_POST,
+ GetCurrentThreadId(), (DWORD)call))
+ result = S_OK;
+ else
+ result = RPC_E_SYS_CALL_FAILED;
+
+#if DBG==1
+ }
+ _except( ProtectedPostExceptionFilter(GetExceptionCode(),
+ GetExceptionInformation()) )
+ {
+ }
+ Win4Assert( IsWindow((HWND) pOxid->hServerSTA) );
+#endif
+ }
+ else
+ result = RPC_E_SERVER_DIED_DNE;
+
+ return result;
+}
+
+
+/***************************************************************************/
+HRESULT SwitchSTA( OXIDEntry *pOxid, CChannelCallInfo **call )
+{
+ TRACECALL(TRACE_RPC, "SwitchSTA");
+ ComDebOut((DEB_CHANNEL, "SwitchSTA hWnd:%x pCall:%x hEvent:%x\n",
+ (*call)->hWndCaller, (*call), (*call)->event));
+ gOXIDTbl.ValidateOXID();
+ ASSERT_LOCK_RELEASED
+
+ // Transmit the call.
+ HRESULT result = TransmitCall( pOxid, *call );
+
+ // the transmit was successful and the reply isn't already here so wait.
+ if (result == RPC_S_CALLPENDING)
+ {
+ // This is a single-threaded apartment so enter the modal loop.
+ result = ModalLoop( *call );
+ }
+
+ if (result == S_OK)
+ result = (*call)->hResult;
+ else if (result == RPC_E_CALL_CANCELED)
+ Cancel( call );
+
+ ASSERT_LOCK_RELEASED
+ gOXIDTbl.ValidateOXID();
+ ComDebOut((DEB_CHANNEL, "SwitchSTA hr:%x\n", result));
+ return result;
+}
+
+/***************************************************************************/
+/*
+ This routine is called by the OLE Worker thread on the client side,
+ and by ThreadWndProc on the server side.
+
+ For the client case, it calls ThreadSendReceive which will send the
+ the data over to the server side.
+ This routine notifies the COM thread when the call is complete. If the
+ call is canceled before completion, the routine cleans up.
+*/
+void ThreadDispatch( CChannelCallInfo **ppcall)
+{
+ CChannelCallInfo *pcall = *ppcall;
+ gOXIDTbl.ValidateOXID();
+
+ // Dispatch the call.
+ if (pcall->edispatch == invoke_wd)
+ pcall->hResult = ComInvoke( pcall );
+ else
+ pcall->hResult = ThreadSendReceive( pcall );
+
+ // Change the state to done; we cheat on non-local, recipient side since
+ // there is only one thread accessing the channel control; no need to
+ // lock and no need to check for cancel since it can't happen.
+ if (pcall->edispatch == invoke_wd && !pcall->Local())
+ {
+ // non-local recipient; just set to done
+ Win4Assert(pcall->eState == in_progress_cs);
+ pcall->eState = server_done_cs;
+ }
+ else
+ {
+ // sender or local case; use lock in case other thread accesses it
+ LOCK
+ if (pcall->eState == in_progress_cs)
+ pcall->eState = server_done_cs;
+ UNLOCK
+ }
+
+ // If the call completed, wake up the waiting thread. For local calls
+ // the client thread is waiting. For remote calls the helper thread is
+ // waiting.
+ if (pcall->eState == server_done_cs)
+ {
+ // only need to wake somebody for synchronous calls
+ if (pcall->category == CALLCAT_SYNCHRONOUS ||
+ pcall->category == CALLCAT_INPUTSYNC)
+ {
+ // Don't do anything in an STA server for input synchronous
+ // calls since the other thread called here with SendMessage.
+
+ if (pcall->category == CALLCAT_SYNCHRONOUS ||
+ pcall->edispatch == sendreceive_wd ||
+ IsMTAThread())
+ {
+
+ if (!pcall->Local() || !IsWOWThread())
+ {
+ // remote calls (outside this process) always use events for
+ // notification. 32bit uses events for local calls too.
+
+ // someone waiting (e.g., not a SendMessage-type call)
+ ComDebOut((DEB_CHANNEL,"SetEvent pInfo:%x hEvent:%x\n",
+ pcall, pcall->event));
+ SetEvent( pcall->event );
+ }
+ else
+ {
+ // NOTE NOTE NOTE NOTE NOTE NOTE NOTE
+ // 16bit OLE used to do PostMessage for the Reply; we
+ // tried using SetEvent (which is faster) but this caused
+ // compatibility problems for applications which had bugs that
+ // were hidden by the 16bit OLE DLLs because messages happened
+ // to be dispatched in a particular order (see NtBug 21616 for
+ // an example). To retain the old behavior, we do a
+ // PostMessage here.
+
+ ComDebOut((DEB_CHANNEL,
+ "PostMessage Reply hWnd:%x pCall:%x hEvent:%x\n",
+ pcall->hWndCaller, pcall, pcall->event));
+
+ // Pass the thread id to aid debugging.
+ Verify(PostMessage(pcall->hWndCaller,
+ WM_OLE_ORPC_DONE,
+ GetCurrentThreadId(), (DWORD)pcall));
+ }
+
+ // pcall likely invalid here as other thread probably deleted it
+ }
+ }
+
+ // Must be asynchronous.
+ else if (pcall->edispatch == invoke_wd)
+ {
+ // async call and on recipient side, free packet (no one waiting)
+ Win4Assert( pcall->category == CALLCAT_ASYNC );
+ delete pcall;
+ *ppcall = NULL;
+ }
+ }
+
+ // If the call was canceled, clean up.
+ else
+ {
+ // can only cancel when on client side or local call
+ Win4Assert(pcall->edispatch == sendreceive_wd || pcall->Local());
+
+ delete pcall;
+ *ppcall = NULL;
+ }
+ gOXIDTbl.ValidateOXID();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: ThreadStart
+//
+// Synopsis: Apartment model only. Setup the window used for MSWMSG,
+// local thread switches and the call control.
+//
+// History: 08-02-95 Rickhi Created, from various pieces
+//
+//--------------------------------------------------------------------------
+HRESULT ThreadStart(void)
+{
+ Win4Assert(IsSTAThread());
+ HRESULT hr = S_OK;
+ RPC_STATUS sc;
+
+ LOCK // lock since GetLocalOXIDEntry expects it
+ OXIDEntry *pOxid = GetLocalOXIDEntry();
+ Win4Assert(pOxid != NULL); //already created so cant fail
+ UNLOCK
+
+
+ if (GetCurrentThreadId() == gdwMainThreadId && hwndOleMainThread != NULL)
+ {
+ // this is the main thread, we can just re-use the already
+ // existing gMainThreadWnd.
+
+ pOxid->hServerSTA = hwndOleMainThread;
+ }
+ else
+ {
+ // Create a new window for use by the current thread for the
+ // apartment model. The window is destroyed in ThreadStop.
+
+ Win4Assert(gOleWindowClass != NULL);
+ pOxid->hServerSTA = CreateWindowEx(0,
+ gOleWindowClass,
+ TEXT("OLEChannelWnd"),
+ // must use WS_POPUP so the window does not get
+ // assigned a hot key by user.
+ (WS_DISABLED | WS_POPUP),
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ NULL,
+ NULL,
+ g_hinst,
+ NULL);
+ }
+
+ if (pOxid->hServerSTA)
+ {
+ DebugIsValidWindow(pOxid->hServerSTA);
+
+ // Override the window proc function
+ SetWindowLong((HWND)pOxid->hServerSTA, GWL_WNDPROC, (LONG)ThreadWndProc);
+
+
+ // get the local call control object, and register the
+ // the window with it. Note that it MUST exist cause we
+ // created it in ChannelThreadInitialize.
+
+ CAptCallCtrl *pCallCtrl = GetAptCallCtrl();
+ pCallCtrl->Register((HWND) pOxid->hServerSTA, WM_USER, 0x7fff );
+ }
+ else
+ {
+ hr = MAKE_SCODE(SEVERITY_ERROR, FACILITY_WIN32, GetLastError());
+ }
+
+ ComDebOut((DEB_CALLCONT, "ThreadStart returns %x\n", hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: ThreadCleanup
+//
+// Synopsis: Release the window for the thread.
+//
+//--------------------------------------------------------------------------
+void ThreadCleanup()
+{
+ LOCK
+ OXIDEntry *pOxid = GetLocalOXIDEntry();
+ UNLOCK
+
+ if (pOxid != NULL)
+ {
+ Win4Assert( (pOxid->dwFlags & OXIDF_MTASERVER) == 0 );
+
+ // Destroy the window. This will unblock any pending SendMessages.
+ if (pOxid->hServerSTA == hwndOleMainThread)
+ {
+ // restore the window proceedure
+ SetWindowLong(hwndOleMainThread, GWL_WNDPROC,
+ (LONG)OleMainThreadWndProc);
+ }
+ else
+ {
+ // This may fail if threads get terminated.
+ DestroyWindow((HWND) pOxid->hServerSTA);
+ }
+
+ pOxid->hServerSTA = NULL;
+ }
+
+ ComDebOut((DEB_CALLCONT, "ThreadCleanup called.\n"));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: ThreadStop
+//
+// Synopsis: Per thread uninitialization
+//
+// History: ??-???-?? ? Created
+// 05-Jul-94 AlexT Separated thread and process uninit
+//
+// Notes: We are not holding the single thread mutex during this call
+//
+//--------------------------------------------------------------------------
+STDAPI_(void) ThreadStop(void)
+{
+ LOCK
+
+ OXIDEntry *pOxid = GetLocalOXIDEntry();
+ if (pOxid != NULL)
+ {
+ // Change state
+ pOxid->dwFlags |= OXIDF_STOPPED;
+ }
+
+ UNLOCK
+
+
+ if (pOxid != NULL)
+ {
+ // Stop MSWMSG.
+ I_RpcServerStopListening();
+
+ if (pOxid->dwFlags & OXIDF_MTASERVER)
+ {
+ if (pOxid->cCalls != 0)
+ {
+ Win4Assert( pOxid->hComplete != NULL );
+ g_mxsSingleThreadOle.Release();
+ WaitForSingleObject( pOxid->hComplete, INFINITE );
+ g_mxsSingleThreadOle.Request();
+ // a new thread may have been initialized while we released
+ // the lock, so we cant assert that the cCalls is zero.
+ }
+ }
+ else
+ {
+ // Single-threaded apartment so wait for all current calls
+ // to complete.
+
+ ASSERT_LOCK_RELEASED
+
+ MSG msg;
+ BOOL got_quit = FALSE;
+ WPARAM quit_val;
+
+ while(PeekMessage(&msg, (HWND) pOxid->hServerSTA, WM_USER,
+ 0x7fff, PM_REMOVE | PM_NOYIELD))
+ {
+ if (msg.message == WM_QUIT)
+ {
+ got_quit = TRUE;
+ quit_val = msg.wParam;
+ }
+ else
+ {
+ DispatchMessage(&msg);
+ }
+ }
+
+ if (got_quit)
+ {
+ PostQuitMessage( quit_val );
+ }
+ }
+ }
+
+ ComDebOut((DEB_CALLCONT, "ThreadStop called.\n"));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ThreadWndProc, Internal
+//
+// Synopsis: Dispatch COM windows messages. This routine is only called
+// for Single-Threaded Apartments. It dispatches calls and call
+// complete messages. If it does not recognize the message, it
+// calls MSWMSG to dispatch it.
+//
+//--------------------------------------------------------------------------
+LRESULT ThreadWndProc(HWND window, UINT message, WPARAM unused, LPARAM params)
+{
+ Win4Assert(IsSTAThread());
+
+ if (message == WM_OLE_ORPC_POST ||
+ message == WM_OLE_ORPC_SEND)
+ {
+ ASSERT_LOCK_RELEASED
+
+ CChannelCallInfo *call = (CChannelCallInfo *) params;
+ ComDebOut((DEB_CHANNEL, "ThreadWndProc: Incoming Call pCall:%x\n", call));
+
+ // Dispatch all calls through ThreadDispatch. Local calls may be
+ // canceled. Server-side, non-local calls cannot be canceled. Send
+ // message calls (event == NULL) are handled as well.
+
+ call->edispatch = invoke_wd;
+ ThreadDispatch( &call );
+
+ ASSERT_LOCK_RELEASED
+ return 0;
+ }
+ else if (message == WM_OLE_ORPC_DONE)
+ {
+ ASSERT_LOCK_RELEASED
+
+ // call completed - only happens InWow()
+ CChannelCallInfo *call = (CChannelCallInfo *) params;
+ ComDebOut((DEB_CHANNEL, "ThreadWndProc: Call Completed hWnd:%x pCall:%x\n", window, call));
+
+ if (call->eState == canceled_cs)
+ {
+ // canceled, throw it away
+ delete call;
+ }
+ else
+ {
+ // Notify the modal loop that the call is complete.
+ call->eState = got_done_msg_cs;
+ }
+
+ ASSERT_LOCK_RELEASED
+ return 0;
+ }
+ else if (message == WM_OLE_ORPC_RELRIFREF)
+ {
+ ASSERT_LOCK_RELEASED
+
+ HandlePostReleaseRifRef(params);
+
+ ASSERT_LOCK_RELEASED
+ return 0;
+ }
+ else if (message == WM_OLE_GETCLASS)
+ {
+ return OleMainThreadWndProc(window, message, unused, params);
+ }
+ else
+ {
+ // when the window is first created we are holding the lock, and the
+ // creation of the window causes some messages to be dispatched.
+ ASSERT_LOCK_DONTCARE
+
+ // check if the window is being destroyed because of UninitMainWindow
+ // or because of system shut down. Only destroy it in the former case.
+ if ((message == WM_DESTROY || message == WM_CLOSE) &&
+ window == hwndOleMainThread &&
+ gfDestroyingMainWindow == FALSE)
+ {
+ ComDebOut((DEB_WARN, "Attempted to destroy window outside of UninitMainThreadWnd"));
+ return 0;
+ }
+#ifdef _CHICAGO_
+ // Otherwise let the default window procedure have the message.
+ return DefWindowProc( window, message, unused, params );
+#else
+ return I_RpcWindowProc( window, message, unused, params );
+#endif
+ }
+}
+
+
+
+/***************************************************************************/
+/*
+ Return S_OK if the call completed successfully.
+ Return RPC_S_CALL_PENDING if the caller should block.
+ Return an error if the call failed.
+*/
+HRESULT TransmitCall( OXIDEntry *pOxid, CChannelCallInfo *call )
+{
+ ComDebOut((DEB_CHANNEL, "TransmitCall pCall:%x\n", call));
+ ASSERT_LOCK_RELEASED
+
+ BOOL fDispCall = FALSE;
+ BOOLEAN wait = FALSE;
+ HRESULT result;
+
+ // Don't touch the call hresult after the other thread starts,
+ // otherwise we might erase the results of the other thread.
+ // Since we never want signalled events returned to the cache, always
+ // wait on the event at least once. For example, the post message
+ // succeeds and the call completes immediately. Return RPC_S_CALLPENDING even
+ // though the call already has a S_OK in it.
+
+
+ if (call->Local())
+ {
+ // server is in this process.
+
+ if (!(pOxid->dwFlags & OXIDF_MTASERVER))
+ {
+ // server is in an STA apartment
+
+ if (call->category == CALLCAT_INPUTSYNC)
+ {
+ // Inputsync call. Send the message.
+ if (!(pOxid->dwFlags & OXIDF_STOPPED))
+ {
+ // On CoUninitialize this may fail when the window is destroyed.
+ // Pass the thread id to aid debugging.
+ SetLastError( 0 );
+ SendMessage((HWND)pOxid->hServerSTA, WM_OLE_ORPC_SEND,
+ GetCurrentThreadId(), (DWORD) call);
+
+ if (GetLastError() != 0)
+ {
+ call->hResult = RPC_E_SERVER_DIED;
+ }
+ }
+ else
+ {
+ call->hResult = RPC_E_SERVER_DIED_DNE;
+ }
+ }
+ else if (call->category == CALLCAT_ASYNC)
+ {
+ // Async call. Copy message, post message and return.
+
+ LOCK
+ CChannelCallInfo *copy = MakeAsyncCopy( call );
+ if (copy == NULL)
+ {
+ call->hResult = RPC_E_OUT_OF_RESOURCES;
+ }
+ else
+ {
+ call->hResult = ProtectedPostToSTA( pOxid, copy );
+
+ if (call->hResult != S_OK)
+ {
+ delete copy;
+ }
+ }
+ UNLOCK
+ }
+ else
+ {
+ // Sync call. Post the message and wait for a reply.
+
+ LOCK
+
+ Win4Assert(call->category == CALLCAT_SYNCHRONOUS);
+ call->hResult = S_OK;
+ if (!IsWOWThread())
+ {
+ // Get an event from the cache. In 32bit, replyies are done
+ // via Events, but for 16bit, repliest are done with PostMsg,
+ // so we dont need an event. Not having an event makes the
+ // callctrl modal loop a little faster.
+ call->hResult = gEventCache.Get( &call->event );
+ }
+ else
+ {
+ Win4Assert( GetLocalOXIDEntry() != NULL );
+ call->hWndCaller = (HWND) GetLocalOXIDEntry()->hServerSTA;
+ call->event = NULL;
+ }
+
+ if (call->hResult == S_OK)
+ {
+ // Post a message to server
+ call->hResult = RPC_S_CALLPENDING;
+ result = ProtectedPostToSTA( pOxid, call );
+
+ if (result != S_OK)
+ call->hResult = result;
+ else
+ wait = TRUE;
+ }
+
+ UNLOCK
+ }
+ }
+ else
+ {
+ // server is in an MTA apartment. Transmit the call by having
+ // a worker thread invoke the server directly. Async calls to
+ // a FT server are treated as SYNC calls and should have been
+ // converted by this point, so we never expect to see callcat
+ // ASYNC.
+
+ Win4Assert(call->category != CALLCAT_ASYNC);
+
+ wait = TRUE;
+ call->edispatch = invoke_wd;
+ fDispCall = TRUE;
+ }
+ }
+ else
+ {
+ // server is in a different process or on a different machine.
+
+ if (call->category == CALLCAT_ASYNC)
+ {
+ // For async calls to other local processes, just make an RPC call.
+ call->hResult = ThreadSendReceive(call);
+ }
+ else
+ {
+ // Get a worker thread to do the RPC call.
+ wait = TRUE;
+ call->edispatch = sendreceive_wd;
+ fDispCall = TRUE;
+ }
+ }
+
+ if (fDispCall)
+ {
+ // Dispatch to a worker thread to make the call
+
+ LOCK
+ call->hResult = gEventCache.Get( &call->event );
+ UNLOCK
+
+ if (call->hResult == S_OK)
+ {
+ call->hResult = RPC_S_CALLPENDING;
+
+ result = gRpcThreadCache.Dispatch( call );
+ if (result != S_OK)
+ {
+ call->hResult = result;
+ wait = FALSE;
+ }
+ }
+ }
+
+ ComDebOut((DEB_CHANNEL, "TransmitCall call->hResult:%x fWait:%x\n",
+ call->hResult, wait));
+
+ Win4Assert(wait || call->hResult != RPC_S_CALLPENDING);
+ return (wait) ? RPC_S_CALLPENDING : call->hResult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEventCache::Cleanup
+//
+// Synopsis: Empty the event cache
+//
+// Notes: This function must be thread safe because Canceled calls
+// can complete at any time.
+//
+//--------------------------------------------------------------------------
+void CEventCache::Cleanup(void)
+{
+ ASSERT_LOCK_HELD
+
+ while (_ifree > 0)
+ {
+ _ifree--; // decrement the index first!
+ Verify(CloseHandle(_list[_ifree]));
+ _list[_ifree] = NULL; // NULL slot so we dont need to re-init
+ }
+
+ // reset the index to 0 so reinitialization is not needed
+ _ifree = 0;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEventCache::Free
+//
+// Synopsis: returns an event to the cache if there are any available
+// slots, frees the event if not.
+//
+// Notes: This function must be thread safe because Canceled calls
+// can complete at any time.
+//
+//--------------------------------------------------------------------------
+void CEventCache::Free( HANDLE hEvent )
+{
+ // there better be an event
+ Win4Assert(hEvent != NULL);
+
+ LOCK
+
+ // dont return anything to the cache if the process is no longer init'd.
+ if (_ifree < CEVENTCACHE_MAX_EVENT && gfChannelProcessInitialized)
+ {
+ // there is space, save this event.
+
+#if DBG==1
+ // in debug, ensure slot is NULL
+ Win4Assert(_list[_ifree] == NULL && "Free: _list[_ifree] != NULL");
+
+ // enusre not already in the list
+ for (ULONG j=0; j<_ifree; j++)
+ {
+ Win4Assert(_list[j] != hEvent && "Free: event already in cache!");
+ }
+
+ // ensure that the event is in the non-signalled state
+ Win4Assert(WaitForSingleObject(hEvent, 0) == WAIT_TIMEOUT &&
+ "Free: Signalled event returned to cache!\n");
+#endif
+
+ _list[_ifree] = hEvent;
+ _ifree++;
+ }
+ else
+ {
+ // Otherwise really free it.
+ Verify(CloseHandle(hEvent));
+ }
+
+ UNLOCK
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEventCache::Get
+//
+// Synopsis: gets an event from the cache if there are any available,
+// allocates one if not.
+//
+// Notes: This function must be thread safe because Canceled calls
+// can complete at any time.
+//
+//--------------------------------------------------------------------------
+HRESULT CEventCache::Get( HANDLE *hEvent )
+{
+ ASSERT_LOCK_HELD
+ Win4Assert(_ifree <= CEVENTCACHE_MAX_EVENT);
+
+ if (_ifree > 0)
+ {
+ // there is an event in the cache, use it.
+ _ifree--;
+ *hEvent = _list[_ifree];
+
+#if DBG==1
+ // in debug, NULL the slot.
+ _list[_ifree] = NULL;
+#endif
+
+ return S_OK;
+ }
+
+ // no free event in the cache, allocate a new one.
+#ifdef _CHICAGO_
+ *hEvent = CreateEventA( NULL, FALSE, FALSE, NULL );
+#else //_CHICAGO_
+ *hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
+#endif //_CHICAGO_
+
+ if (*hEvent)
+ return S_OK;
+
+ Win4Assert(*hEvent != NULL && "CEventCache:GetEvent returning NULL");
+ return RPC_E_OUT_OF_RESOURCES;
+}
diff --git a/private/ole32/com/dcomrem/chancont.hxx b/private/ole32/com/dcomrem/chancont.hxx
new file mode 100644
index 000000000..3fe24bf1a
--- /dev/null
+++ b/private/ole32/com/dcomrem/chancont.hxx
@@ -0,0 +1,171 @@
+#ifndef _CHANCONT_HXX_
+#define _CHANCONT_HXX_
+
+#include <wtypes.h>
+#include <OleSpy.hxx>
+#include <ipidtbl.hxx>
+
+
+//+-------------------------------------------------------------------------
+//
+// class: CEventCache
+//
+// Synopsis: Since ORPC uses events very frequently, we keep a small
+// internal cache of them. There is only one of them, so
+// we use static initializers to reduce Init time.
+//
+// History: 25-Oct-95 Rickhi Made data static
+//
+//--------------------------------------------------------------------------
+
+// dont change this value without changing the static initializer.
+#define CEVENTCACHE_MAX_EVENT 8
+
+class CEventCache : public CPrivAlloc
+{
+public:
+ void Free( HANDLE );
+ HRESULT Get ( HANDLE * );
+
+ void Cleanup(void);
+
+private:
+
+ static HANDLE _list[CEVENTCACHE_MAX_EVENT];
+ static DWORD _ifree;
+};
+
+extern CEventCache gEventCache;
+
+
+/***************************************************************************/
+
+typedef enum
+{
+ in_progress_cs,
+ server_done_cs,
+ got_done_msg_cs,
+ canceled_cs
+} ECallState;
+
+typedef enum
+{
+ CF_LOCKED = 0x1, // Set when free buffer must call UnlockClient
+ CF_PROCESS_LOCAL = 0x2, // Set for process local calls
+ CF_WAS_IMPERSONATING = 0x4, // Client was impersonating before call started
+} ECallFlags;
+
+typedef enum
+{
+ none_wd, // dont call anything
+ invoke_wd, // call ComInvoke
+ sendreceive_wd // call ThreadSendReceive
+} EWhichDispatch;
+
+class CRpcChannelBuffer;
+
+class CChannelCallInfo
+{
+ public:
+ CChannelCallInfo();
+ CChannelCallInfo( CALLCATEGORY callcat,
+ RPCOLEMESSAGE *message,
+ DWORD iFlags,
+ REFIPID ipidServer,
+ DWORD destctx,
+ CRpcChannelBuffer *channel,
+ DWORD authn_level );
+ ~CChannelCallInfo();
+ BOOL Local () { return iFlags & CF_PROCESS_LOCAL; }
+ BOOL Locked () { return iFlags & CF_LOCKED; }
+
+ // Channel controller fields.
+ CALLCATEGORY category;
+ DWORD iFlags; // ECallFlags
+ ECallState eState;
+ SCODE hResult; // SCODE or exception code
+ HANDLE event; // caller wait event
+ HWND hWndCaller; // caller apartment hWnd (only used InWow)
+ EWhichDispatch edispatch; // which function to invoke in worker thread
+ IPID ipid;
+
+ // Channel fields.
+ RPCOLEMESSAGE *pmessage;
+ DWORD server_fault;
+ DWORD iDestCtx;
+ CChannelCallInfo *pNext;
+ void *pHeader;
+ CRpcChannelBuffer *pChannel;
+ DWORD lSavedAuthnLevel;
+ DWORD lAuthnLevel;
+};
+
+
+/***************************************************************************/
+/* Classes. */
+
+/*
+ The channel controller switches threads for the channel. It is not
+used in the free threaded mode. There are two basic scenarios: a local
+call and a remote call.
+
+ A local call looks like this.
+
+ Client Server
+ SendReceive
+ SwitchSTA
+ TransmitCall
+ PostMessage
+ ModalLoop
+ MsgWaitForMultipleObjects
+ ThreadWndProc
+ ThreadDispatch
+ ComInvoke
+ AppInvoke
+ AptInvoke
+ Stub
+ SetEvent
+
+ A remote call looks like this.
+
+ Client ClientHelper ServerHelper Server
+ SendReceive
+ SwitchSTA
+ TransmitCall
+ SetEvent
+ ModalLoop
+ MsgWaitForMultipleObjects
+ ThreadSendReceive
+ RPC
+ ThreadInvoke
+ GetToSTA
+ PostMessage
+ WaitForSingleObject
+ ThreadWndProc
+ ThreadDispatch
+ ComInvoke
+ AppInvoke
+ AptInvoke
+ Stub
+ SetEvent
+ reply
+ SetEvent
+
+ The actual thread switch mechanism (PostMessage, event) depend on
+the call category, whether or not the call is local, whether or not the
+call is in WOW, and the direction (request vs. reply).
+
+*/
+
+/***************************************************************************/
+/* Externals. */
+extern CEventCache EventCache;
+
+HRESULT GetToSTA ( OXIDEntry *, CChannelCallInfo * );
+HRESULT SwitchSTA ( OXIDEntry *, CChannelCallInfo ** );
+void ThreadCleanup ( void );
+void ThreadDispatch ( CChannelCallInfo ** );
+HRESULT ThreadStart ( void );
+LRESULT ThreadWndProc (HWND window, UINT message, WPARAM unused, LPARAM params);
+
+#endif // _CHANCONT_HXX_
diff --git a/private/ole32/com/dcomrem/channelb.cxx b/private/ole32/com/dcomrem/channelb.cxx
new file mode 100644
index 000000000..c602b2f40
--- /dev/null
+++ b/private/ole32/com/dcomrem/channelb.cxx
@@ -0,0 +1,2665 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: d:\nt\private\cairole\com\remote\channelb.cxx
+//
+// Contents: This module contains thunking classes that allow proxies
+// and stubs to use a buffer interface on top of RPC for Cairo
+//
+// Classes: CRpcChannelBuffer
+//
+// Functions:
+// ChannelThreadInitialize
+// ChannelProcessInitialize
+// ChannelRegisterProtseq
+// ChannelThreadUninitialize
+// ChannelProcessUninitialize
+// CRpcChannelBuffer::AddRef
+// CRpcChannelBuffer::AppInvoke
+// CRpcChannelBuffer::CRpcChannelBuffer
+// CRpcChannelBuffer::FreeBuffer
+// CRpcChannelBuffer::GetBuffer
+// CRpcChannelBuffer::QueryInterface
+// CRpcChannelBuffer::Release
+// CRpcChannelBuffer::SendReceive
+// DebugCoSetRpcFault
+// DllDebugObjectRPCHook
+// ThreadInvoke
+// ThreadSendReceive
+//
+// History: 22 Jun 93 AlexMi Created
+// 31 Dec 93 ErikGav Chicago port
+// 15 Mar 94 JohannP Added call category support.
+// 09 Jun 94 BruceMa Get call category from RPC message
+// 19 Jul 94 CraigWi Added support for ASYNC calls
+// 01-Aug-94 BruceMa Memory sift fix
+//
+//----------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <channelb.hxx>
+#include <hash.hxx> // CUUIDHashTable
+#include <riftbl.hxx> // gRIFTbl
+#include <callctrl.hxx> // CAptRpcChnl, AptInvoke
+#include <threads.hxx> // CRpcThreadCache
+#include <service.hxx> // StopListen
+#include <resolver.hxx> // CRpcResolver
+
+extern "C"
+{
+#include "orpc_dbg.h"
+}
+
+#include <rpcdcep.h>
+#include <rpcndr.h>
+
+#include <obase.h>
+#include <ipidtbl.hxx>
+#include <security.hxx>
+#include <chock.hxx>
+
+
+// This is needed for the debug hooks. See orpc_dbg.h
+#pragma code_seg(".orpc")
+
+/***************************************************************************/
+/* Defines. */
+
+#define MAKE_WIN32( status ) \
+ MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, (status) )
+
+// This should just return a status to runtime, but runtime does not
+// support both comm and fault status yet.
+#ifdef _CHICAGO_
+#define RETURN_COMM_STATUS( status ) return (status)
+#else
+#define RETURN_COMM_STATUS( status ) RpcRaiseException( status )
+#endif
+
+// Flags for local rpc header.
+// These are only valid on a request (in a ORPCTHIS header).
+const int ORPCF_INPUT_SYNC = ORPCF_RESERVED1;
+const int ORPCF_ASYNC = ORPCF_RESERVED2;
+
+// These are only valid on a reply (in a ORPCTHAT header).
+const int ORPCF_REJECTED = ORPCF_RESERVED1;
+const int ORPCF_RETRY_LATER = ORPCF_RESERVED2;
+
+// Default size of hash table.
+const int INITIAL_NUM_BUCKETS = 20;
+
+
+/***************************************************************************/
+/* Typedefs. */
+
+// This structure contains a copy of all the information needed to make a
+// call. It is copied so it can be canceled without stray pointer references.
+const DWORD CALLCACHE_SIZE = 8;
+struct working_call : public CChannelCallInfo
+{
+ working_call( CALLCATEGORY callcat,
+ RPCOLEMESSAGE *message,
+ DWORD flags,
+ REFIPID ipidServer,
+ DWORD destctx,
+ CRpcChannelBuffer *channel,
+ DWORD authn_level );
+ void *operator new ( size_t );
+ void operator delete( void * );
+ static void Cleanup ( void );
+ static void Initialize ( void );
+
+ RPCOLEMESSAGE message;
+
+private:
+ static void *list[CALLCACHE_SIZE];
+ static DWORD next;
+};
+
+void *working_call::list[CALLCACHE_SIZE] =
+ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
+DWORD working_call::next = 0;
+
+
+/***************************************************************************/
+/* Macros. */
+
+// Compute the size needed for the implicit this pointer including the
+// various optional headers.
+inline DWORD SIZENEEDED_ORPCTHIS( BOOL local, DWORD debug_size )
+{
+ if (debug_size == 0)
+ return sizeof(WireThisPart1) + ((local) ? sizeof(LocalThis) : 0);
+ else
+ return sizeof(WireThisPart2) + ((local) ? sizeof(LocalThis) : 0) +
+ debug_size;
+}
+
+inline DWORD SIZENEEDED_ORPCTHAT( DWORD debug_size )
+{
+ if (debug_size == 0)
+ return sizeof(WireThatPart1);
+ else
+ return sizeof(WireThatPart2) + debug_size;
+}
+
+inline CALLCATEGORY GetCallCat( void *header )
+{
+ WireThis *inb = (WireThis *) header;
+ if (inb->c.flags & ORPCF_ASYNC)
+ return CALLCAT_ASYNC;
+ else if (inb->c.flags & ORPCF_INPUT_SYNC)
+ return CALLCAT_INPUTSYNC;
+ else
+ return CALLCAT_SYNCHRONOUS;
+}
+
+
+/***************************************************************************/
+/* Globals. */
+
+// Should the debugger hooks be called?
+BOOL DoDebuggerHooks = FALSE;
+LPORPC_INIT_ARGS DebuggerArg = NULL;
+
+// The extension identifier for debug data.
+const uuid_t DEBUG_EXTENSION =
+{ 0xf1f19680, 0x4d2a, 0x11ce, {0xa6, 0x6a, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4}};
+
+#if DBG == 1
+// strings that prefix the call
+WCHAR *wszDebugORPCCallPrefixString[4] = { L"--> [BEG]", // Invoke
+ L" --> [end]",
+ L"<-- [BEG]", // SendReceive
+ L" <-- [end]" };
+
+LONG ulDebugORPCCallNestingLevel[4] = {1, -1, 1, -1};
+#endif
+
+
+SHashChain OIDBuckets[23] = { {&OIDBuckets[0], &OIDBuckets[0]},
+ {&OIDBuckets[1], &OIDBuckets[1]},
+ {&OIDBuckets[2], &OIDBuckets[2]},
+ {&OIDBuckets[3], &OIDBuckets[3]},
+ {&OIDBuckets[4], &OIDBuckets[4]},
+ {&OIDBuckets[5], &OIDBuckets[5]},
+ {&OIDBuckets[6], &OIDBuckets[6]},
+ {&OIDBuckets[7], &OIDBuckets[7]},
+ {&OIDBuckets[8], &OIDBuckets[8]},
+ {&OIDBuckets[9], &OIDBuckets[9]},
+ {&OIDBuckets[10], &OIDBuckets[10]},
+ {&OIDBuckets[11], &OIDBuckets[11]},
+ {&OIDBuckets[12], &OIDBuckets[12]},
+ {&OIDBuckets[13], &OIDBuckets[13]},
+ {&OIDBuckets[14], &OIDBuckets[14]},
+ {&OIDBuckets[15], &OIDBuckets[15]},
+ {&OIDBuckets[16], &OIDBuckets[16]},
+ {&OIDBuckets[17], &OIDBuckets[17]},
+ {&OIDBuckets[18], &OIDBuckets[18]},
+ {&OIDBuckets[19], &OIDBuckets[19]},
+ {&OIDBuckets[20], &OIDBuckets[20]},
+ {&OIDBuckets[21], &OIDBuckets[21]},
+ {&OIDBuckets[22], &OIDBuckets[22]}
+ };
+
+CUUIDHashTable gClientRegisteredOIDs;
+
+
+// flag whether or not the channel has been initialized for current process
+BOOL gfChannelProcessInitialized = 0;
+BOOL gfMTAChannelInitialized = 0;
+
+// count of multi-threaded apartment inits (see CoInitializeEx)
+extern DWORD g_cMTAInits;
+
+
+// Channel debug hook object.
+CDebugChannelHook gDebugHook;
+
+// Channel error hook object.
+CErrorChannelHook gErrorHook;
+
+#if DBG==1
+//-------------------------------------------------------------------------
+//
+// Function: GetInterfaceName
+//
+// synopsis: Gets the human readable name of an Interface given it's IID.
+//
+// History: 12-Jun-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+LONG GetInterfaceName(REFIID riid, WCHAR *pwszName)
+{
+ // convert the iid to a string
+ CDbgGuidStr dbgsIID(riid);
+
+ // Read the registry entry for the interface to get the interface name
+ LONG ulcb=256;
+ WCHAR szKey[80];
+
+ szKey[0] = L'\0';
+ lstrcatW(szKey, L"Interface\\");
+ lstrcatW(szKey, dbgsIID._wszGuid);
+
+ LONG result = RegQueryValue(
+ HKEY_CLASSES_ROOT,
+ szKey,
+ pwszName,
+ &ulcb);
+
+ Win4Assert( result == 0 );
+ return result;
+}
+
+//---------------------------------------------------------------------------
+//
+// Function: DebugPrintORPCCall
+//
+// synopsis: Prints the interface name and method number to the debugger
+// to allow simple ORPC call tracing.
+//
+// History: 12-Jun-95 Rickhi Created
+//
+//---------------------------------------------------------------------------
+void DebugPrintORPCCall(DWORD dwFlag, REFIID riid, DWORD iMethod, DWORD Callcat)
+{
+ if (CairoleInfoLevel & DEB_USER15)
+ {
+ Win4Assert (dwFlag < 4);
+
+ // adjust the nesting level for this thread.
+ COleTls tls;
+ tls->cORPCNestingLevel += ulDebugORPCCallNestingLevel[dwFlag];
+
+
+ // set the indentation string according to the nesting level
+ CHAR szNesting[100];
+ memset(szNesting, 0x20, 100);
+
+ if (tls->cORPCNestingLevel > 99) // watch for overflow
+ szNesting[99] = '\0';
+ else
+ szNesting[tls->cORPCNestingLevel] = '\0';
+
+
+ // construct the debug strings
+ WCHAR *pwszDirection = wszDebugORPCCallPrefixString[dwFlag];
+ WCHAR wszName[100];
+ GetInterfaceName(riid, wszName);
+
+ ComDebOut((DEB_USER15, "%s%ws [%x] %ws:: %x\n",
+ szNesting, pwszDirection, Callcat, wszName, iMethod));
+ }
+}
+#endif
+
+/***************************************************************************/
+void ByteSwapThis( DWORD drep, WireThis *inb )
+{
+ if ((drep & NDR_LOCAL_DATA_REPRESENTATION) != NDR_LITTLE_ENDIAN)
+ {
+ // Extensions are swapped later. If we ever use the reserved field,
+ // swap it.
+ ByteSwapShort( inb->c.version.MajorVersion );
+ ByteSwapShort( inb->c.version.MinorVersion );
+ ByteSwapLong( inb->c.flags );
+ // ByteSwapLong( inb->c.reserved1 );
+ ByteSwapLong( inb->c.cid.Data1 );
+ ByteSwapShort( inb->c.cid.Data2 );
+ ByteSwapShort( inb->c.cid.Data3 );
+ }
+}
+
+/***************************************************************************/
+void ByteSwapThat( DWORD drep, WireThat *outb )
+{
+ if ((drep & NDR_LOCAL_DATA_REPRESENTATION) != NDR_LITTLE_ENDIAN)
+ {
+ // Extensions are swapped later.
+ ByteSwapLong( outb->c.flags );
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: ChannelProcessInitialize, public
+//
+// Synopsis: Initializes the channel subsystem per process data.
+//
+// History: 23-Nov-93 AlexMit Created
+//
+//--------------------------------------------------------------------
+STDAPI ChannelProcessInitialize()
+{
+ TRACECALL(TRACE_RPC, "ChannelProcessInitialize");
+ ComDebOut((DEB_COMPOBJ, "ChannelProcessInitialize [IN]\n"));
+
+ Win4Assert( (sizeof(WireThisPart1) & 7) == 0 );
+ Win4Assert( (sizeof(WireThisPart2) & 7) == 0 );
+ Win4Assert( (sizeof(LocalThis) & 7) == 0 );
+ Win4Assert( (sizeof(WireThatPart1) & 7) == 0 );
+ Win4Assert( (sizeof(WireThatPart2) & 7) == 0 );
+
+ // we want to take the gComLock since that prevents other Rpc
+ // threads from accessing anything we are about to create, in
+ // particular, the event cache and working_call cache are accessed
+ // by Rpc worker threads of cancelled calls.
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ HRESULT hr = S_OK;
+
+ if (!gfChannelProcessInitialized)
+ {
+ // Initialize the interface hash tables, the OID hash table, and
+ // the MID hash table. We dont need to cleanup these on errors.
+
+ gMIDTbl.Initialize();
+ gOXIDTbl.Initialize();
+ gRIFTbl.Initialize();
+ gIPIDTbl.Initialize();
+ gSRFTbl.Initialize();
+ gClientRegisteredOIDs.Initialize(OIDBuckets);
+
+ // Register the debug channel hook.
+ hr = CoRegisterChannelHook( DEBUG_EXTENSION, &gDebugHook );
+
+ // Register the error channel hook.
+ if(SUCCEEDED(hr))
+ {
+ hr = CoRegisterChannelHook( ERROR_EXTENSION, &gErrorHook );
+ }
+
+ // Initialize security.
+ if (SUCCEEDED(hr))
+ {
+ hr = InitializeSecurity();
+ }
+
+ // always set to TRUE if we initialized ANYTHING, regardless of
+ // whether there were any errors. That way, ChannelProcessUninit
+ // will cleanup anything we have initialized.
+ gfChannelProcessInitialized = TRUE;
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ if (FAILED(hr))
+ {
+ // cleanup anything we have created thus far.
+ ChannelProcessUninitialize();
+ }
+
+ ComDebOut((DEB_COMPOBJ, "ChannelProcessInitialize [OUT] hr:%x\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CleanupRegOIDs, public
+//
+// Synopsis: called to delete each node of the registered OID list.
+//
+//+-------------------------------------------------------------------
+void CleanupRegOIDs(SHashChain *pNode)
+{
+ delete pNode;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: ChannelProcessUninitialize, public
+//
+// Synopsis: Uninitializes the channel subsystem global data.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Notes: This is called at process uninitialize, not thread
+// uninitialize.
+//
+//--------------------------------------------------------------------
+STDAPI_(void) ChannelProcessUninitialize(void)
+{
+ TRACECALL(TRACE_RPC, "ChannelProcessUninitialize");
+ ComDebOut((DEB_COMPOBJ, "ChannelProcessUninitialize [IN]\n"));
+
+ if (gfChannelProcessInitialized)
+ {
+ // Stop accepting calls from the object resolver and flag that service
+ // is no longer initialized. This can result in calls being
+ // dispatched. Do not hold the lock around this call.
+
+ UnregisterDcomInterfaces();
+ }
+
+ gResolver.ReleaseSCMProxy();
+
+ // we want to take the gComLock since that prevents other Rpc
+ // threads from accessing anything we are about to cleanup, in
+ // particular, the event cache and working_call are accessed by
+ // Rpc worker threaded for cancelled calls.
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ if (gfChannelProcessInitialized)
+ {
+ // Release the interface tables. This causes RPC to stop dispatching
+ // DCOM calls. This can result in calls being dispatched.
+ // UnRegisterServerInterface releases and reaquires the lock each
+ // time it is called.
+ gRIFTbl.Cleanup();
+
+ if (gpLocalMIDEntry)
+ {
+ // release the local MIDEntry
+ DecMIDRefCnt(gpLocalMIDEntry);
+ gpLocalMIDEntry = NULL;
+ }
+
+ // release the MTA apartment's OXIDEntry if there is one. Do this
+ // after the RIFTble cleanup so we are not processing any calls
+ // while it happens.
+ gOXIDTbl.ReleaseLocalMTAEntry();
+
+ if (gpsaCurrentProcess)
+ {
+ // delete the string bindings for the current process
+ PrivMemFree(gpsaCurrentProcess);
+ gpsaCurrentProcess = NULL;
+ }
+
+ // cleanup the IPID, OXID, and MID tables
+ gOXIDTbl.FreeExpiredEntries(GetTickCount()+1);
+ gIPIDTbl.Cleanup();
+ gOXIDTbl.Cleanup();
+ gMIDTbl.Cleanup();
+ gSRFTbl.Cleanup();
+
+ // Cleanup the OID registration table.
+ gClientRegisteredOIDs.Cleanup(CleanupRegOIDs);
+
+ // Cleanup the call cache.
+ working_call::Cleanup();
+
+ // Release all cached threads.
+ gRpcThreadCache.ClearFreeList();
+
+ // cleanup the event cache
+ gEventCache.Cleanup();
+
+ // Cleanup the channel hooks.
+ CleanupChannelHooks();
+ }
+
+ // Always cleanup the RPC OXID resolver since security may initialize it.
+ gResolver.Cleanup();
+
+ // Cleanup security.
+ UninitializeSecurity();
+
+ // mark the channel as no longer intialized for this process
+ gfChannelProcessInitialized = FALSE;
+ gfMTAChannelInitialized = FALSE;
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ // release the static unmarshaler
+ if (gpStdMarshal)
+ {
+ ((CStdIdentity *)gpStdMarshal)->UnlockAndRelease();
+ gpStdMarshal = NULL;
+ }
+
+ ComDebOut((DEB_COMPOBJ, "ChannelProcessUninitialize [OUT]\n"));
+ return;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: STAChannelInitialize, public
+//
+// Synopsis: Initializes the channel subsystem per thread data
+// for single-threaded apartments.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Notes: This is called at thread initialize, not process
+// initialize. Cleanup is done in ChannelThreadUninitialize.
+//
+//--------------------------------------------------------------------
+STDAPI STAChannelInitialize(void)
+{
+ ComDebOut((DEB_COMPOBJ, "STAChannelInitialize [IN]\n"));
+ Win4Assert(IsSTAThread());
+
+ HRESULT hr = S_OK;
+
+ if (!gfChannelProcessInitialized)
+ {
+ // process initialization has not been done, do that now.
+ if (FAILED(hr = ChannelProcessInitialize()))
+ return hr;
+ }
+
+ // create the callctrl before calling ThreadStart, since the latter
+ // tries to register with the call controller. We might already have
+ // a callctrl if some DDE stuff has already run.
+
+ COleTls tls;
+
+ if (tls->pCallCtrl == NULL)
+ {
+ // assume OOM and try to create callctrl. ctor sets tls.
+ hr = E_OUTOFMEMORY;
+ CAptCallCtrl *pCallCtrl = new CAptCallCtrl();
+ }
+
+ if (tls->pCallCtrl)
+ {
+ // mark the channel as initialized now to prevent re-entracy in
+ // GetLocalEntry.
+
+ tls->dwFlags |= OLETLS_CHANNELTHREADINITIALZED;
+
+ // Precreate the thread window. The window is normally only used
+ // for requests (and thus created during marshalling). But in WOW
+ // it is used for responses (and thus created during initialization).
+ // We do it for normal cases here too in order to avoid recursion
+ // when marshaling the first interface.
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ OXIDEntry *pOxid;
+ hr = gOXIDTbl.GetLocalEntry( &pOxid );
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ if (SUCCEEDED(hr))
+ {
+ hr = ThreadStart();
+ }
+
+ // Clear the channel initialized flag if initialization fails.
+ // Everything gets cleaned up in uninitialize regardless of the
+ // channel flag.
+ if (FAILED(hr))
+ tls->dwFlags &= ~OLETLS_CHANNELTHREADINITIALZED;
+ }
+
+ ComDebOut((DEB_COMPOBJ, "STAChannelInitialize [OUT] hr:%x\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: MTAChannelInitialize, public
+//
+// Synopsis: Initializes the channel subsystem per thread data
+// for multi-threaded apartments.
+//
+// History: 19-Mar-96 Rickhi Created
+//
+// Notes: This is called at thread initialize, not process
+// initialize. Cleanup is done in ChannelThreadUninitialize.
+//
+//--------------------------------------------------------------------
+STDAPI MTAChannelInitialize(void)
+{
+ ComDebOut((DEB_COMPOBJ, "MTAChannelInitialize [IN]\n"));
+ Win4Assert(IsMTAThread());
+
+ HRESULT hr = S_OK;
+
+ if (!gfChannelProcessInitialized)
+ {
+ // process initialization has not been done, do that now.
+ if (FAILED(hr = ChannelProcessInitialize()))
+ return hr;
+ }
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ if (!gfMTAChannelInitialized)
+ {
+ // Create the OXID entry for this apartment. Do it now to avoid
+ // any races with two threads creating it simultaneously.
+
+ OXIDEntry *pOxid;
+ hr = gOXIDTbl.GetLocalEntry( &pOxid );
+ if (SUCCEEDED(hr))
+ {
+ pOxid->dwFlags &= ~ OXIDF_STOPPED;
+ gfMTAChannelInitialized = TRUE;
+ }
+
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ ComDebOut((DEB_COMPOBJ, "MTAChannelInitialize [OUT] hr:%x\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: ChannelThreadUninitialize, private
+//
+// Synopsis: Uninitializes the channel subsystem per thread data.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Notes: This is called at thread uninitialize, not process
+// uninitialize.
+//
+//--------------------------------------------------------------------
+STDAPI_(void) ChannelThreadUninitialize(void)
+{
+ TRACECALL(TRACE_RPC, "ChannelThreadUninitialize");
+ ComDebOut((DEB_COMPOBJ, "ChannelThreadUninitialize [IN]\n"));
+
+ COleTls tls;
+
+ if (tls->dwFlags & OLETLS_APARTMENTTHREADED)
+ {
+ // Cleanup the window for this thread.
+ ThreadCleanup();
+
+ // Free the apartment call control.
+ delete tls->pCallCtrl;
+ tls->pCallCtrl = NULL;
+
+ // Free any registered MessageFilter that has not been picked
+ // up by the call ctrl.
+ if (tls->pMsgFilter)
+ {
+ tls->pMsgFilter->Release();
+ tls->pMsgFilter = NULL;
+ }
+
+ // release the OXIDEntry for this thread.
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ gOXIDTbl.ReleaseLocalSTAEntry();
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ // mark the thread as no longer intialized for the channel
+ tls->dwFlags &= ~OLETLS_CHANNELTHREADINITIALZED;
+ }
+ else
+ {
+ // the MTA channel is no longer initialized.
+ gfMTAChannelInitialized = FALSE;
+ }
+
+ ComDebOut((DEB_COMPOBJ, "ChannelThreadUninitialize [OUT]\n"));
+}
+
+// count of multi-threaded inits
+//+-------------------------------------------------------------------
+//
+// Function: InitChannelIfNecessary, private
+//
+// Synopsis: Checks if the ORPC channel has been initialized for
+// the current apartment and initializes if not. This is
+// required by the delayed initialization logic.
+//
+// History: 26-Oct-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+INTERNAL InitChannelIfNecessary()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!(tls->dwFlags & OLETLS_APARTMENTTHREADED))
+ {
+ if (!gfMTAChannelInitialized)
+ {
+ if (g_cMTAInits > 0)
+ {
+ // initialize the MTAChannel
+ return MTAChannelInitialize();
+ }
+
+ // CoInitializeEx(MULTITHREADED) has not been called
+ return CO_E_NOTINITIALIZED;
+ }
+ }
+ else if (!(tls->dwFlags & OLETLS_CHANNELTHREADINITIALZED))
+ {
+ if (tls->cComInits > 0 &&
+ !(tls->dwFlags & OLETLS_THREADUNINITIALIZING))
+ return STAChannelInitialize();
+
+ // CoInitializeEx(APARTMENTTHREADED) has not been called,
+ // or the thread is Uninitializing
+ return CO_E_NOTINITIALIZED;
+ }
+
+ return S_OK;
+}
+
+
+ /***************************************************************************/
+/*
+ Make a copy of a message for an asyncronous call. Also make a fake
+reply for the call.
+*/
+CChannelCallInfo *MakeAsyncCopy( CChannelCallInfo *original )
+{
+ void *pBuffer = NULL;
+ WireThat *outb;
+ BOOL success;
+
+ ASSERT_LOCK_HELD
+
+ working_call *copy = new working_call( original->category,
+ original->pmessage,
+ original->iFlags,
+ original->ipid,
+ original->iDestCtx,
+ original->pChannel,
+ original->lAuthnLevel );
+
+ if (copy != NULL)
+ {
+ original->hResult = S_OK;
+
+ if (original->pmessage->rpcFlags & RPCFLG_LOCAL_CALL)
+ {
+ // no need to duplicate the buffer, just use it as is.
+ copy->message.Buffer = original->pmessage->Buffer;
+ }
+ else
+ {
+ pBuffer = PrivMemAlloc8(original->pmessage->cbBuffer);
+ Win4Assert(((ULONG)pBuffer & 0x7) == 0 && "Buffer not aligned properly");
+
+ if (pBuffer != NULL)
+ {
+ copy->message.Buffer = pBuffer;
+ memcpy(pBuffer, original->pmessage->Buffer,
+ original->pmessage->cbBuffer);
+ }
+ else
+ {
+ original->hResult = RPC_E_OUT_OF_RESOURCES;
+ }
+ }
+
+ if (SUCCEEDED(original->hResult))
+ {
+ // pretend local so we don't touch rpc for more buffers, etc.
+ copy->message.rpcFlags |= RPCFLG_LOCAL_CALL;
+
+ // Create a fake reply containing a result even though the
+ // client will never see it.
+ original->pmessage->cbBuffer = SIZENEEDED_ORPCTHAT(0) + 4;
+
+ if (original->pmessage->rpcFlags & RPCFLG_LOCAL_CALL)
+ {
+ original->pmessage->Buffer = PrivMemAlloc8(original->pmessage->cbBuffer);
+ success = original->pmessage->Buffer != NULL;
+ }
+ else
+ {
+ success = I_RpcGetBuffer((RPC_MESSAGE *) original->pmessage) == RPC_S_OK;
+ }
+
+ // simulate success in method call
+ if (success)
+ {
+ outb = (WireThat *) original->pmessage->Buffer;
+ outb->c.flags = ORPCF_NULL;
+ outb->c.unique = 0;
+ *(SCODE *)((WireThatPart1 *)outb + 1) = S_OK;
+ return copy;
+ }
+ }
+
+ PrivMemFree(pBuffer);
+ delete copy;
+ }
+
+ return NULL;
+}
+
+
+/***************************************************************************/
+STDMETHODIMP_(ULONG) CRpcChannelBuffer::AddRef( THIS )
+{
+ // can't call AssertValid(FALSE) since it is used in asserts
+ InterlockedIncrement( (long *) &ref_count );
+ return ref_count;
+}
+
+/***************************************************************************/
+HRESULT CRpcChannelBuffer::AppInvoke( CChannelCallInfo *call,
+ IRpcStubBuffer *stub,
+ void *pv,
+ void *orig_stub_buffer,
+ LocalThis *localb )
+{
+ ASSERT_LOCK_RELEASED
+
+ RPC_MESSAGE *message = (RPC_MESSAGE *) call->pmessage;
+ void *orig_buffer = message->Buffer;
+ WireThat *outb = NULL;
+ HRESULT result;
+
+ // Save a pointer to the inbound header.
+ call->pHeader = message->Buffer;
+
+ // Adjust the buffer.
+ message->BufferLength -= (char *) orig_stub_buffer - (char *) message->Buffer;
+ message->Buffer = orig_stub_buffer;
+ message->ProcNum &= ~RPC_FLAGS_VALID_BIT;
+
+ // if the incoming call is from a non-NDR client, then set a bit in
+ // the message flags field so the stub can figure out how to dispatch
+ // the call. This allows a 32bit server to simultaneously service a
+ // 32bit client using NDR and a 16bit client using non-NDR, in particular,
+ // to support OLE Automation.
+ if (localb != NULL && localb->flags & LOCALF_NONNDR)
+ message->RpcFlags |= RPCFLG_NON_NDR;
+
+ if (IsMTAThread())
+ {
+ // do multi-threaded apartment invoke
+ result = MTAInvoke((RPCOLEMESSAGE *)message, GetCallCat( call->pHeader ),
+ stub, this, &call->server_fault);
+ }
+ else
+ {
+ // do single-threaded apartment invoke
+ result = STAInvoke((RPCOLEMESSAGE *)message, GetCallCat( call->pHeader ),
+ stub, this, pv, &call->server_fault);
+ }
+
+ // For local calls, just free the in buffer. For non-local calls,
+ // the RPC runtime does this for us.
+ if (message->RpcFlags & RPCFLG_LOCAL_CALL)
+ PrivMemFree( orig_buffer );
+
+ // If an exception occurred before a new buffer was allocated,
+ // set the Buffer field to point to the original buffer.
+ if (message->Buffer == orig_stub_buffer)
+ {
+ // The buffer pointer in the message must be correct so RPC can free it.
+ if (message->RpcFlags & RPCFLG_LOCAL_CALL)
+ message->Buffer = NULL;
+ else
+ message->Buffer = orig_buffer;
+ }
+ else if (message->Buffer != NULL)
+ {
+ // An out buffer exists, get the pointer to the channel header.
+ Win4Assert( call->pHeader != orig_buffer );
+ message->BufferLength += (char *) message->Buffer - (char *) call->pHeader;
+ message->Buffer = call->pHeader;
+ outb = (WireThat *) message->Buffer;
+ }
+
+ // If successful, adjust the buffer.
+ if (result == S_OK)
+ {
+ if (call->iDestCtx == MSHCTX_DIFFERENTMACHINE)
+ outb->c.flags = 0;
+ else
+ outb->c.flags = ORPCF_LOCAL;
+
+ // For asynchronous calls, MSWMSG will delete the out buffer. If MSWMSG
+ // is not the transport, delete it here. Non-Mswmsg async calls have
+ // been converted to local calls.
+ if (message->RpcFlags & RPCFLG_LOCAL_CALL &&
+ call->category == CALLCAT_ASYNC)
+ {
+ PrivMemFree( message->Buffer );
+ message->Buffer = NULL;
+ }
+ }
+ else if (result == RPC_E_CALL_REJECTED)
+ {
+ // Call was rejected. If the caller is on another machine, just fail the
+ // call.
+ if (call->iDestCtx != MSHCTX_DIFFERENTMACHINE && outb != NULL)
+ {
+ // Otherwise return S_OK so the buffer gets back, but set the flag
+ // to indicate it was rejected.
+ outb->c.flags = ORPCF_LOCAL | ORPCF_REJECTED;
+ result = S_OK;
+ }
+ }
+ else if (result == RPC_E_SERVERCALL_RETRYLATER)
+ {
+ // Call was rejected. If the caller is on another machine, just fail the
+ // call.
+ if (call->iDestCtx != MSHCTX_DIFFERENTMACHINE && outb != NULL)
+ {
+ // Otherwise return S_OK so the buffer gets back, but set the flag
+ // to indicate it was rejected with retry later.
+ outb->c.flags = ORPCF_LOCAL | ORPCF_RETRY_LATER;
+ result = S_OK;
+ }
+ }
+ else if (message->RpcFlags & RPCFLG_LOCAL_CALL)
+ {
+ // call failed and the call is local, free the out buffer. For
+ // non-local calls the RPC runtime does this for us.
+ PrivMemFree( message->Buffer );
+ message->Buffer = NULL;
+ }
+
+ ASSERT_LOCK_RELEASED
+ return result;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: AppInvokeExceptionFilter
+//
+// Synopsis: Determine if the application as thrown an exception we want
+// to report. If it has, then print out enough information for
+// the 'user' to debug the problem
+//
+// Arguments: [lpep] -- Exception context records
+//
+// History: 6-20-95 kevinro Created
+//
+// Notes:
+//
+// At the moment, I was unable to get this to work for Win95, so I have
+// commented out the code.
+//
+//----------------------------------------------------------------------------
+
+
+#ifdef _CHICAGO_
+
+//
+// Win95 doesn't appear to support this functionality by default.
+//
+
+inline LONG
+AppInvokeExceptionFilter(
+ LPEXCEPTION_POINTERS lpep
+ )
+{
+ return(EXCEPTION_EXECUTE_HANDLER);
+}
+
+#else
+
+#include <imagehlp.h>
+
+#define SYM_HANDLE GetCurrentProcess()
+
+#if defined(_M_IX86)
+#define MACHINE_TYPE IMAGE_FILE_MACHINE_I386
+#elif defined(_M_MRX000)
+#define MACHINE_TYPE IMAGE_FILE_MACHINE_R4000
+#elif defined(_M_ALPHA)
+#define MACHINE_TYPE IMAGE_FILE_MACHINE_ALPHA
+#elif defined(_M_PPC)
+#define MACHINE_TYPE IMAGE_FILE_MACHINE_POWERPC
+#else
+#error( "unknown target machine" );
+#endif
+
+LONG
+AppInvokeExceptionFilter(
+ LPEXCEPTION_POINTERS lpep
+ )
+{
+#if DBG == 1
+ BOOL rVal;
+ STACKFRAME StackFrame;
+ CONTEXT Context;
+
+
+ SymSetOptions( SYMOPT_UNDNAME );
+ SymInitialize( SYM_HANDLE, NULL, TRUE );
+ ZeroMemory( &StackFrame, sizeof(StackFrame) );
+ Context = *lpep->ContextRecord;
+
+#if defined(_M_IX86)
+ StackFrame.AddrPC.Offset = Context.Eip;
+ StackFrame.AddrPC.Mode = AddrModeFlat;
+ StackFrame.AddrFrame.Offset = Context.Ebp;
+ StackFrame.AddrFrame.Mode = AddrModeFlat;
+ StackFrame.AddrStack.Offset = Context.Esp;
+ StackFrame.AddrStack.Mode = AddrModeFlat;
+#endif
+
+
+ ComDebOut((DEB_FORCE,"An Exception occurred while calling into app\n"));
+ ComDebOut((DEB_FORCE,
+ "Exception address = 0x%x Exception number 0x%x\n",
+ lpep->ExceptionRecord->ExceptionAddress,
+ lpep->ExceptionRecord->ExceptionCode ));
+
+ ComDebOut((DEB_FORCE,"The following stack trace is where the exception occured\n"));
+ ComDebOut((DEB_FORCE,"Frame RetAddr mod!symbol\n"));
+ do
+ {
+ rVal = StackWalk(MACHINE_TYPE,SYM_HANDLE,0,&StackFrame,&Context,ReadProcessMemory,
+ SymFunctionTableAccess,SymGetModuleBase,NULL);
+
+ if (rVal)
+ {
+ DWORD dump[200];
+ ULONG Displacement;
+ PIMAGEHLP_SYMBOL sym = (PIMAGEHLP_SYMBOL) &dump;
+ IMAGEHLP_MODULE ModuleInfo;
+ LPSTR pModuleName = "???";
+ BOOL fSuccess;
+
+ sym->SizeOfStruct = sizeof(dump);
+
+ fSuccess = SymGetSymFromAddr(SYM_HANDLE,StackFrame.AddrPC.Offset,
+ &Displacement,sym);
+
+ //
+ // If there is module name information available, then grab it.
+ //
+ if(SymGetModuleInfo(SYM_HANDLE,StackFrame.AddrPC.Offset,&ModuleInfo))
+ {
+ pModuleName = ModuleInfo.ModuleName;
+ }
+
+ if (fSuccess)
+ {
+ ComDebOut((DEB_FORCE,
+ "%08x %08x %s!%s + %x\n",
+ StackFrame.AddrFrame.Offset,
+ StackFrame.AddrReturn.Offset,
+ pModuleName,
+ sym->Name,
+ Displacement));
+ }
+ else
+ {
+ ComDebOut((DEB_FORCE,
+ "%08x %08x %s!%08x\n",
+ StackFrame.AddrFrame.Offset,
+ StackFrame.AddrReturn.Offset,
+ pModuleName,
+ StackFrame.AddrPC.Offset));
+ }
+ }
+ } while( rVal );
+
+ SymCleanup( SYM_HANDLE );
+
+#endif
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+#endif // _CHICAGO_
+
+/***************************************************************************/
+#if DBG == 1
+DWORD AppInvoke_break = 0;
+DWORD AppInvoke_count = 0;
+#endif
+
+HRESULT StubInvoke(RPCOLEMESSAGE *pMsg, IRpcStubBuffer *pStub,
+ IRpcChannelBuffer *pChnl, DWORD *pdwFault)
+{
+ ComDebOut((DEB_CHANNEL, "StubInvoke pMsg:%x pStub:%x pChnl:%x pdwFault:%x\n",
+ pMsg, pStub, pChnl, pdwFault));
+ ASSERT_LOCK_RELEASED
+
+ HRESULT hr;
+
+#if DBG==1
+ DWORD dwMethod = pMsg->iMethod;
+ IID iidBeingCalled = ((RPC_SERVER_INTERFACE *) pMsg->reserved2[1])->InterfaceId.SyntaxGUID;
+#endif
+
+ _try
+ {
+ TRACECALL(TRACE_RPC, "StubInvoke");
+#if DBG == 1
+ //
+ // On a debug build, we are able to break on a call by serial number.
+ // This isn't really 100% thread safe, but is still extremely useful
+ // when debugging a problem.
+ //
+ DWORD dwBreakCount = ++AppInvoke_count;
+
+ ComDebOut((DEB_CHANNEL, "AppInvoke(0x%x) calling method 0x%x iid %I\n",
+ dwBreakCount,dwMethod, &iidBeingCalled));
+
+ if(AppInvoke_break == dwBreakCount)
+ {
+ DebugBreak();
+ }
+#endif
+
+#ifdef WX86OLE
+ if (! gcwx86.IsN2XProxy(pStub))
+ {
+ IUnknown *pActual;
+
+ hr = pStub->DebugServerQueryInterface((void **)&pActual);
+ if (SUCCEEDED(hr))
+ {
+ if (gcwx86.IsN2XProxy(pActual))
+ {
+ // If we are going to invoke a native stub that is
+ // connected to an object on the x86 side then
+ // set a flag in the Wx86 thread environment to
+ // let the thunk layer know that the call is a
+ // stub invoked call and allow any in or out
+ // custom interface pointers to be thunked as
+ // IUnknown rather than failing the interface thunking
+ gcwx86.SetStubInvokeFlag((BOOL)1);
+ }
+ pStub->DebugServerRelease(pActual);
+ }
+ }
+#endif
+
+ hr = pStub->Invoke(pMsg, pChnl);
+
+ }
+ _except(AppInvokeExceptionFilter( GetExceptionInformation()))
+ {
+ hr = RPC_E_SERVERFAULT;
+ *pdwFault = GetExceptionCode();
+
+#if DBG == 1
+ //
+ // OLE catches exceptions when the server generates them. This is so we can
+ // cleanup properly, and allow the client to continue.
+ //
+ if (*pdwFault == STATUS_ACCESS_VIOLATION ||
+ *pdwFault == STATUS_POSSIBLE_DEADLOCK ||
+ *pdwFault == STATUS_INSTRUCTION_MISALIGNMENT ||
+ *pdwFault == STATUS_DATATYPE_MISALIGNMENT )
+ {
+
+ WCHAR iidName[256];
+ iidName[0] = 0;
+ char achProgname[256];
+ achProgname[0] = 0;
+
+ GetModuleFileNameA(NULL,achProgname,sizeof(achProgname));
+
+ GetInterfaceName(iidBeingCalled,iidName);
+
+ ComDebOut((DEB_FORCE,
+ "OLE has caught a fault 0x%08x on behalf of the server %s\n",
+ *pdwFault,
+ achProgname));
+
+ ComDebOut((DEB_FORCE,
+ "The fault occured when OLE called the interface %I (%ws) method 0x%x\n",
+ &iidBeingCalled,iidName,dwMethod));
+
+ Win4Assert(!"The server application has faulted processing an inbound RPC request. Check the kernel debugger for useful output. OLE can continue but you probably want to stop and debug the application.");
+ }
+#endif
+ }
+
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_CHANNEL, "StubInvoke hr:%x dwFault:%x\n", hr, *pdwFault));
+ return hr;
+}
+
+/***************************************************************************/
+#if DBG==1
+LONG ComInvokeExceptionFilter( DWORD lCode,
+ LPEXCEPTION_POINTERS lpep )
+{
+ ComDebOut((DEB_ERROR, "Exception 0x%x in ComInvoke at address 0x%x\n",
+ lCode, lpep->ExceptionRecord->ExceptionAddress));
+ DebugBreak();
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+#endif
+
+/***************************************************************************/
+HRESULT ComInvoke( CChannelCallInfo *call )
+{
+ TRACECALL(TRACE_RPC, "ComInvoke");
+ ASSERT_LOCK_RELEASED
+
+ RPC_MESSAGE *message = (RPC_MESSAGE *) call->pmessage;
+ LocalThis *localb;
+ void *saved_buffer;
+ RPC_STATUS status;
+ HRESULT result;
+ IPIDEntry *ipid_entry = NULL;
+ CRpcChannelBuffer *server_channel = NULL;
+ DWORD TIDCallerSaved;
+ BOOL fLocalSaved;
+ UUID saved_threadid;
+ IUnknown *save_context;
+ DWORD saved_authn_level;
+ char *stub_data;
+ WireThis *inb = (WireThis *) message->Buffer;
+ OXIDEntry *oxid;
+ HANDLE hWakeup = NULL;
+
+ ComDebOut((DEB_CHANNEL, "ComInvoke callinfo:%x header:%x\n",
+ call, message->Buffer));
+
+ COleTls tls(result);
+ if (FAILED(result))
+ return result;
+
+ // Catch exceptions that might keep the lock.
+#if DBG == 1
+ _try
+ {
+#endif
+
+ // Find the IPID entry. Fail if the IPID or the OXID are not ready.
+ LOCK
+ ipid_entry = gIPIDTbl.LookupIPID( call->ipid );
+ Win4Assert( ipid_entry == NULL || ipid_entry->pOXIDEntry != NULL );
+ if (ipid_entry == NULL || (ipid_entry->dwFlags & IPIDF_DISCONNECTED) ||
+ (ipid_entry->pOXIDEntry->dwFlags & OXIDF_STOPPED) ||
+ ipid_entry->pChnl == NULL)
+ result = RPC_E_DISCONNECTED;
+ else if (ipid_entry->pStub == NULL)
+ result = E_NOINTERFACE;
+
+ // Keep the server object and our associated objects alive during the call.
+ if (SUCCEEDED(result))
+ {
+ oxid = ipid_entry->pOXIDEntry;
+ server_channel = ipid_entry->pChnl;
+ Win4Assert( server_channel != NULL && server_channel->pStdId != NULL );
+ server_channel->pStdId->LockServer();
+ InterlockedIncrement( &oxid->cCalls );
+ }
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ if (FAILED(result))
+ {
+ return result;
+ }
+
+ // Create a new security call context;
+ CServerSecurity security( call );
+ save_context = tls->pCallContext;
+ tls->pCallContext = &security;
+
+ // save the original threadid & copy in the new one.
+ if (!(tls->dwFlags & OLETLS_UUIDINITIALIZED))
+ {
+ UuidCreate(&tls->LogicalThreadId);
+ tls->dwFlags |= OLETLS_UUIDINITIALIZED;
+ }
+ saved_threadid = tls->LogicalThreadId;
+ tls->LogicalThreadId = inb->c.cid;
+
+ ComDebOut((DEB_CALLCONT, "ComInvoke: LogicalThreads Old:%I New:%I\n",
+ &saved_threadid, &tls->LogicalThreadId));
+
+ // Save the call info in TLS.
+ call->pNext = (CChannelCallInfo *) tls->pCallInfo;
+ tls->pCallInfo = call;
+ saved_authn_level = tls->dwAuthnLevel;
+ tls->dwAuthnLevel = call->lAuthnLevel;
+
+ // Call the channel hooks. Set up as much TLS data as possible before
+ // calling the hooks so they can access it.
+ result = ServerNotify(
+ ((RPC_SERVER_INTERFACE *) message->RpcInterfaceInformation)->InterfaceId.SyntaxGUID,
+ (WireThis *) message->Buffer,
+ message->BufferLength,
+ (void **) &stub_data,
+ message->DataRepresentation );
+
+ // Find the local header.
+ if (inb->c.flags & ORPCF_LOCAL)
+ {
+ localb = (LocalThis *) stub_data;
+ stub_data += sizeof(LocalThis);
+ }
+ else
+ localb = NULL;
+
+ // Set the caller TID. This is needed by some interop code in order
+ // to do focus management via tying queues together. We first save the
+ // current one so we can restore later to deal with nested calls
+ // correctly.
+ TIDCallerSaved = tls->dwTIDCaller;
+ fLocalSaved = tls->dwFlags & OLETLS_LOCALTID;
+ tls->dwTIDCaller = localb != NULL ? localb->client_thread : 0;
+
+ if (call->iFlags & CF_PROCESS_LOCAL)
+ tls->dwFlags |= OLETLS_LOCALTID; // turn the local bit on
+ else
+ tls->dwFlags &= ~OLETLS_LOCALTID; // turn the local bit off
+
+ // Continue dispatching the call.
+ if (result == S_OK)
+ {
+ result = server_channel->AppInvoke(
+ call,
+ (IRpcStubBuffer *) ipid_entry->pStub,
+ ipid_entry->pv,
+ stub_data,
+ localb );
+ }
+
+ // Restore the original thread id, call info, dest context and thread id.
+ tls->LogicalThreadId = saved_threadid;
+ tls->pCallInfo = call->pNext;
+ tls->dwTIDCaller = TIDCallerSaved;
+ tls->dwAuthnLevel = saved_authn_level;
+
+ if (fLocalSaved)
+ tls->dwFlags |= OLETLS_LOCALTID;
+ else
+ tls->dwFlags &= ~OLETLS_LOCALTID;
+
+ // Restore the security context;
+ tls->pCallContext = save_context;
+ security.EndCall();
+
+ // Decrement the call count. If the MTA is waiting to uninitialize
+ // and this is the last call, wake up the uninitializing thread, but
+ // do this *after* calling UnLockServer so the other thread does not
+ // blow away the server.
+ if (InterlockedDecrement( &oxid->cCalls ) == 0 &&
+ (oxid->dwFlags & (OXIDF_MTASERVER | OXIDF_STOPPED)) == (OXIDF_MTASERVER | OXIDF_STOPPED))
+ hWakeup = oxid->hComplete;
+
+ // Release our hold on the object and channel.
+ server_channel->pStdId->UnLockServer();
+
+ if (hWakeup)
+ SetEvent(hWakeup);
+
+ // Catch exceptions that might keep the lock.
+#if DBG == 1
+ }
+ _except( ComInvokeExceptionFilter(GetExceptionCode(),
+ GetExceptionInformation()) )
+ {
+ }
+#endif
+
+ ASSERT_LOCK_RELEASED
+ return result;
+}
+
+/***************************************************************************/
+CRpcChannelBuffer *CRpcChannelBuffer::Copy(OXIDEntry *pOXIDEntry,
+ REFIPID ripid, REFIID riid)
+{
+ Win4Assert( !(state & server_cs) );
+
+ CRpcChannelBuffer *chan;
+
+ if (IsMTAThread())
+ {
+ // make client side multi-threaded apartment version of channel
+ chan = new CMTARpcChnl(pStdId, pOXIDEntry, state);
+ }
+ else
+ {
+ // make client side single-threaded apartment version of channel
+ chan = new CAptRpcChnl(pStdId, pOXIDEntry, state);
+ }
+
+ if (chan != NULL)
+ {
+ chan->state = proxy_cs | (state & ~client_cs);
+ chan->lAuthnLevel = lAuthnLevel;
+ }
+
+ return chan;
+}
+
+/***************************************************************************/
+HRESULT CRpcChannelBuffer::InitClientSideHandle()
+{
+ Win4Assert((state & proxy_cs));
+ ASSERT_LOCK_HELD
+
+ if (state & initialized_cs)
+ return S_OK;
+
+ // Lookup the interface info. This cant fail.
+ pInterfaceInfo = gRIFTbl.GetClientInterfaceInfo(pIPIDEntry->iid);
+
+ RPC_STATUS status;
+#ifndef _CHICAGO_
+ if (state & process_local_cs)
+ {
+ handle = NULL;
+ status = RPC_S_OK;
+ }
+ else
+#endif
+ {
+ status = RpcBindingCopy(pOXIDEntry->hServerSTA, &handle);
+
+ if (status == RPC_S_OK)
+
+ // If this is a single threaded apartment, give LRPC the blocking
+ // hook.
+ if (state & mswmsg_cs)
+ status = I_RpcBindingSetAsync(handle, OleModalLoopBlockFn);
+
+#ifndef CHICAGO
+ // If the server is a single threaded apartment, tell LRPC to
+ // use MSWMSG to dispatch.
+ else if (pOXIDEntry->dwTid != 0)
+ status = I_RpcBindingSetAsync(handle, NULL);
+#endif
+
+ if (status == RPC_S_OK)
+ status = RpcBindingSetObject(handle, (GUID *)&pIPIDEntry->ipid);
+ }
+
+ if (status == RPC_S_OK)
+ {
+ state |= initialized_cs;
+ return S_OK;
+ }
+
+ return MAKE_WIN32(status);
+}
+
+
+/***************************************************************************/
+CRpcChannelBuffer::CRpcChannelBuffer(CStdIdentity *standard_identity,
+ OXIDEntry *pOXID,
+ DWORD eState )
+{
+ ComDebOut((DEB_MARSHAL, "CRpcChannelBuffer %s Created this:%x pOXID:%x\n",
+ (eState & client_cs) ? "CLIENT" : "SERVER", this, pOXID));
+
+ // Fill in the easy fields first.
+ ref_count = 1;
+ pStdId = standard_identity;
+ handle = NULL;
+ pOXIDEntry = pOXID;
+ pIPIDEntry = NULL;
+ pInterfaceInfo = NULL;
+ hToken = NULL;
+ lAuthnLevel = gAuthnLevel;
+ state = eState;
+ state |= pOXID->dwPid == GetCurrentProcessId() ? process_local_cs : 0;
+ SetImpLevel( gImpLevel );
+
+ if ((pOXID->dwFlags & OXIDF_MSWMSG) && IsSTAThread())
+ {
+ // use MSWMSG protocol with the blocking hook
+ state |= mswmsg_cs;
+ }
+
+ if (state & (client_cs | proxy_cs))
+ {
+ // Determine the destination context.
+ if (pOXID->dwFlags & OXIDF_MACHINE_LOCAL)
+ if (!IsWOWThread() && (state & process_local_cs))
+ iDestCtx = MSHCTX_INPROC;
+ else
+ iDestCtx = MSHCTX_LOCAL;
+ else
+ iDestCtx = MSHCTX_DIFFERENTMACHINE;
+ }
+ else
+ {
+ // On the server side, the destination context isn't known
+ // untill a call arrives.
+ iDestCtx = 0;
+ }
+}
+
+/***************************************************************************/
+CRpcChannelBuffer::~CRpcChannelBuffer()
+{
+ ComDebOut((DEB_MARSHAL, "CRpcChannelBuffer %s Deleted this:%x\n",
+ (state & server_cs) ? "SERVER" : "CLIENT", this));
+
+ if (handle != NULL)
+ RpcBindingFree( &handle );
+ if (hToken != NULL)
+ CloseHandle( hToken );
+}
+
+/***************************************************************************/
+STDMETHODIMP CRpcChannelBuffer::FreeBuffer( RPCOLEMESSAGE *pMessage )
+{
+ TRACECALL(TRACE_RPC, "CRpcChannelBuffer::FreeBuffer");
+ ASSERT_LOCK_RELEASED
+ AssertValid(FALSE, TRUE);
+
+ if (pMessage->Buffer == NULL)
+ return S_OK;
+
+ // Pop the call stack.
+ COleTls tls;
+ Win4Assert( tls->pCallInfo != NULL );
+ working_call *pCall = (working_call *) tls->pCallInfo;
+ tls->pCallInfo = pCall->pNext;
+ tls->dwAuthnLevel = pCall->lSavedAuthnLevel;
+ pMessage->Buffer = pCall->pHeader;;
+
+ DeallocateBuffer(pCall->pmessage);
+
+ // Resume any outstanding impersonation.
+ ResumeImpersonate( tls->pCallContext, pCall->iFlags & CF_WAS_IMPERSONATING );
+
+ // Release the AddRef we did earlier. Note that we cant do this until
+ // after DeallocateBuffer since it may release a binding handle that
+ // I_RpcFreeBuffer needs.
+ if (pCall->Locked())
+ pStdId->UnLockClient();
+
+ pMessage->Buffer = NULL;
+ delete pCall;
+
+ ASSERT_LOCK_RELEASED
+ return S_OK;
+}
+
+//-------------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::GetBuffer
+//
+// Synopsis: Calls ClientGetBuffer or ServerGetBuffer
+//
+//-------------------------------------------------------------------------
+STDMETHODIMP CRpcChannelBuffer::GetBuffer( RPCOLEMESSAGE *pMessage,
+ REFIID riid )
+{
+ gOXIDTbl.ValidateOXID();
+ if (state & proxy_cs)
+ return ClientGetBuffer( pMessage, riid );
+ else
+ return ServerGetBuffer( pMessage, riid );
+}
+
+//-------------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::ClientGetBuffer
+//
+// Synopsis: Gets a buffer and sets up client side stuff
+//
+//-------------------------------------------------------------------------
+HRESULT CRpcChannelBuffer::ClientGetBuffer( RPCOLEMESSAGE *pMessage,
+ REFIID riid )
+{
+ TRACECALL(TRACE_RPC, "CRpcChannelBuffer::ClientGetBuffer");
+ ASSERT_LOCK_RELEASED
+
+ RPC_STATUS status;
+ CALLCATEGORY callcat = CALLCAT_SYNCHRONOUS;
+ ULONG debug_size;
+ ULONG num_extent;
+ WireThis *inb;
+ LocalThis *localb;
+ IID *logical_thread;
+ working_call *call;
+ DWORD flags;
+ BOOL resume;
+ DWORD orig_size = pMessage->cbBuffer;
+ COleTls tls;
+
+ Win4Assert(state & proxy_cs);
+ AssertValid(FALSE, TRUE);
+
+ // Don't allow remote calls if DCOM is disabled.
+ if (gDisableDCOM && iDestCtx == MSHCTX_DIFFERENTMACHINE)
+ return RPC_E_REMOTE_DISABLED;
+
+ // Fetch the call category from the RPC message structure
+ if (pMessage->rpcFlags & RPCFLG_ASYNCHRONOUS)
+ {
+ // only allow async for these two interfaces for now
+ if (riid != IID_IAdviseSink && riid != IID_IAdviseSink2)
+ return E_UNEXPECTED;
+ callcat = CALLCAT_ASYNC;
+ }
+ else
+ {
+ logical_thread = TLSGetLogicalThread();
+ if (logical_thread == NULL)
+ {
+ return RPC_E_OUT_OF_RESOURCES;
+ }
+ if (pMessage->rpcFlags & RPCFLG_INPUT_SYNCHRONOUS)
+ {
+ callcat = CALLCAT_INPUTSYNC;
+ }
+ }
+
+ // Set the buffer complete flag for local calls.
+ pMessage->rpcFlags |= RPC_BUFFER_COMPLETE;
+
+ // Note - RPC requires that the 16th bit of the proc num be set because
+ // we use the rpcFlags field of the RPC_MESSAGE struct.
+ pMessage->iMethod |= RPC_FLAGS_VALID_BIT;
+
+ // if service object of destination is in same process, definitely local
+ // calls; async calls are also forced to be local.
+ if (state & process_local_cs)
+ {
+ pMessage->rpcFlags |= RPCFLG_LOCAL_CALL;
+ flags = CF_PROCESS_LOCAL;
+ }
+ else
+ flags = 0;
+
+ // Find out if we need hook data.
+ debug_size = ClientGetSize( riid, &num_extent );
+
+ LOCK
+
+ // Complete the channel initialization if needed.
+ status = InitClientSideHandle();
+ if (status != RPC_S_OK)
+ {
+ UNLOCK;
+ ASSERT_LOCK_RELEASED;
+ return status;
+ }
+
+ // Fill in the binding handle. Adjust the size. Clear the transfer
+ // syntax. Set the interface identifier.
+ if ((pMessage->rpcFlags & RPCFLG_LOCAL_CALL) == 0)
+ pMessage->reserved1 = handle;
+ pMessage->cbBuffer += SIZENEEDED_ORPCTHIS( pOXIDEntry->dwFlags & OXIDF_MACHINE_LOCAL,
+ debug_size );
+ pMessage->reserved2[0] = 0;
+ pMessage->reserved2[1] = pInterfaceInfo;
+ Win4Assert( pMessage->reserved2[1] != NULL );
+
+ // Allocate a call record.
+ call = new working_call( callcat, pMessage, flags, pIPIDEntry->ipid,
+ iDestCtx, this, lAuthnLevel );
+ pMessage->cbBuffer = orig_size;
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ if (call == NULL)
+ return E_OUTOFMEMORY;
+
+ // Suspend any outstanding impersonation and ignore failures.
+ SuspendImpersonate( tls->pCallContext, &resume );
+
+ // Get a buffer.
+ if (call->pmessage->rpcFlags & RPCFLG_LOCAL_CALL)
+ {
+ // NDR_DREP_ASCII | NDR_DREP_LITTLE_ENDIAN | NDR_DREP_IEEE
+ call->pmessage->dataRepresentation = 0x00 | 0x10 | 0x0000;
+ call->pmessage->Buffer = PrivMemAlloc8( call->pmessage->cbBuffer );
+ if (call->pmessage->Buffer == NULL)
+ status = RPC_S_OUT_OF_MEMORY;
+ else
+ status = RPC_S_OK;
+ }
+ else
+ {
+ TRACECALL(TRACE_RPC, "I_RpcGetBuffer");
+ status = I_RpcGetBuffer( (RPC_MESSAGE *) call->pmessage );
+ }
+
+ if (status != RPC_S_OK)
+ {
+ // Resume any outstanding impersonation.
+ ResumeImpersonate( tls->pCallContext, resume );
+
+ // Cleanup.
+ pMessage->cbBuffer = 0;
+ tls->fault = MAKE_WIN32( status );
+ delete call;
+ return MAKE_WIN32( status );
+ }
+
+ // Save the impersonation flag.
+ if (resume)
+ call->iFlags |= CF_WAS_IMPERSONATING;
+
+ // Chain the call info in TLS.
+ call->pNext = (CChannelCallInfo *)tls->pCallInfo;
+ tls->pCallInfo = call;
+ call->pHeader = call->message.Buffer;
+
+ // Adjust the authentication level in TLS.
+ call->lSavedAuthnLevel = tls->dwAuthnLevel;
+ tls->dwAuthnLevel = lAuthnLevel;
+
+ // Fill in the COM header.
+ pMessage->Buffer = call->message.Buffer;
+ inb = (WireThis *) pMessage->Buffer;
+ inb->c.version.MajorVersion = COM_MAJOR_VERSION;
+ inb->c.version.MinorVersion = COM_MINOR_VERSION;
+ inb->c.reserved1 = 0;
+
+ // Generate a new logical thread for async calls.
+ if (callcat == CALLCAT_ASYNC)
+ UuidCreate( &inb->c.cid );
+ // Find the logical thread id.
+ else
+ inb->c.cid = *logical_thread;
+
+ if (pOXIDEntry->dwFlags & OXIDF_MACHINE_LOCAL)
+ inb->c.flags = ORPCF_LOCAL;
+ else
+ inb->c.flags = ORPCF_NULL;
+
+ // Fill in any hook data and adjust the buffer pointer.
+ if (debug_size != 0)
+ {
+ pMessage->Buffer = FillBuffer( riid, &inb->d.ea, debug_size, num_extent,
+ TRUE );
+ inb->c.unique = 0x77646853; // Any non-zero value.
+ }
+ else
+ {
+ pMessage->Buffer = (void *) &inb->d.ea;
+ inb->c.unique = FALSE;
+ }
+
+ // Fill in the local header.
+ if (pOXIDEntry->dwFlags & OXIDF_MACHINE_LOCAL)
+ {
+ localb = (LocalThis *) pMessage->Buffer;
+ localb->client_thread = GetCurrentApartmentId();
+ localb->flags = 0;
+ pMessage->Buffer = localb + 1;
+ if (callcat == CALLCAT_ASYNC)
+ inb->c.flags |= ORPCF_ASYNC;
+ else if (callcat == CALLCAT_INPUTSYNC)
+ inb->c.flags |= ORPCF_INPUT_SYNC;
+
+ // if the caller is using a non-NDR proxy, set a bit in the local
+ // header flags so that server side stub knows which way to unmarshal
+ // the parameters. This lets a 32bit server simultaneously service calls
+ // from 16bit non-NDR clients and 32bit NDR clients, in particular, to
+ // support OLE Automation.
+
+ if (pIPIDEntry->dwFlags & (IPIDF_NONNDRPROXY | IPIDF_NONNDRSTUB))
+ localb->flags |= LOCALF_NONNDR;
+ }
+
+ ComDebOut((DEB_CALLCONT, "ClientGetBuffer: LogicalThreadId:%I\n",
+ &(tls->LogicalThreadId)));
+
+ ASSERT_LOCK_RELEASED
+ return S_OK;
+}
+
+//-------------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::ServerGetBuffer
+//
+// Synopsis: Gets a buffer and sets up server side stuff
+//
+//-------------------------------------------------------------------------
+HRESULT CRpcChannelBuffer::ServerGetBuffer( RPCOLEMESSAGE *pMessage,
+ REFIID riid )
+{
+ TRACECALL(TRACE_RPC, "CRpcChannelBuffer::ServerGetBuffer");
+ ASSERT_LOCK_RELEASED
+
+ RPC_STATUS status;
+ ULONG debug_size;
+ ULONG num_extent;
+ HRESULT result = S_OK;
+ WireThis *inb;
+ WireThat *outb;
+ CChannelCallInfo *call;
+ void *stub_data;
+ DWORD orig_size = pMessage->cbBuffer;
+
+ Win4Assert( state & server_cs );
+
+ AssertValid(FALSE, TRUE);
+
+ // Get the call info from TLS.
+ COleTls tls;
+ call = (CChannelCallInfo *) tls->pCallInfo;
+ Win4Assert( call != NULL );
+
+ // Find out if we need debug data.
+ pMessage->Buffer = call->pHeader;
+ debug_size = ServerGetSize( riid, &num_extent );
+
+ // Adjust the buffer size.
+ pMessage->cbBuffer += SIZENEEDED_ORPCTHAT( debug_size );
+
+ // Get a buffer.
+ if (pMessage->rpcFlags & RPCFLG_LOCAL_CALL)
+ {
+ // NDR_DREP_ASCII | NDR_DREP_LITTLE_ENDIAN | NDR_DREP_IEEE
+ pMessage->dataRepresentation = 0x00 | 0x10 | 0x0000;
+ pMessage->Buffer = PrivMemAlloc8( pMessage->cbBuffer );
+ if (pMessage->Buffer == NULL)
+ status = RPC_S_OUT_OF_MEMORY;
+ else
+ status = RPC_S_OK;
+ }
+ else
+ {
+ TRACECALL(TRACE_RPC, "I_RpcGetBuffer");
+ status = I_RpcGetBuffer( (RPC_MESSAGE *) pMessage );
+ Win4Assert( call->pHeader != pMessage->Buffer || status != RPC_S_OK );
+ }
+
+ if (status != RPC_S_OK)
+ {
+ pMessage->cbBuffer = 0;
+ pMessage->Buffer = NULL;
+ tls->fault = MAKE_WIN32( status );
+ return MAKE_WIN32( status );
+ }
+
+ // Fill in the outbound COM header.
+ call->pHeader = pMessage->Buffer;
+ outb = (WireThat *) pMessage->Buffer;
+ outb->c.flags = ORPCF_NULL;
+ pMessage->cbBuffer = orig_size;
+ if (debug_size != 0)
+ {
+ stub_data = FillBuffer( riid, &outb->d.ea, debug_size, num_extent, FALSE );
+ outb->c.unique = 0x77646853; // Any non-zero value.
+ pMessage->Buffer = stub_data;
+ }
+ else
+ {
+ outb->c.unique = 0;
+ pMessage->Buffer = &outb->d.ea;
+ }
+
+ ComDebOut((DEB_CALLCONT, "ServerGetBuffer: LogicalThreadId:%I\n",
+ &(tls->LogicalThreadId)));
+ ASSERT_LOCK_RELEASED
+ return S_OK;
+}
+
+/***************************************************************************/
+STDMETHODIMP CRpcChannelBuffer::GetDestCtx( DWORD FAR* lpdwDestCtx,
+ LPVOID FAR* lplpvDestCtx )
+{
+ TRACECALL(TRACE_RPC, "CRpcChannelBuffer::GetDestCtx");
+ AssertValid(FALSE, FALSE);
+
+ // On the client side, get the destination context from the channel.
+ if (state & (client_cs | proxy_cs))
+ {
+ *lpdwDestCtx = iDestCtx;
+ }
+
+ // On the server side, get the destination context from TLS.
+ else
+ {
+ COleTls tls;
+ Win4Assert( tls->pCallInfo != NULL );
+ *lpdwDestCtx = ((CChannelCallInfo *) tls->pCallInfo)->iDestCtx;
+ }
+
+ if (lplpvDestCtx != NULL)
+ *lplpvDestCtx = NULL;
+
+ return S_OK;
+}
+
+/***************************************************************************/
+STDMETHODIMP CRpcChannelBuffer::IsConnected( THIS )
+{
+ // must be on right thread because it is only called by proxies and stubs.
+ AssertValid(FALSE, TRUE);
+
+ // Server channels never know if they are connected. The only time the
+ // client side knows it is disconnected is after the standard identity
+ // has disconnected the proxy from the channel. In that case it doesn't
+ // matter.
+ return S_OK;
+}
+
+/***************************************************************************/
+STDMETHODIMP CRpcChannelBuffer::QueryInterface( THIS_ REFIID riid, LPVOID FAR* ppvObj)
+{
+ AssertValid(FALSE, FALSE);
+
+ // IMarshal is queried more frequently than any other interface, so
+ // check for that first.
+
+ if (IsEqualIID(riid, IID_IMarshal))
+ {
+ *ppvObj = (IMarshal *) this;
+ }
+ else if (IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IRpcChannelBuffer))
+ {
+ *ppvObj = (IRpcChannelBuffer *) this;
+ }
+ else if (IsEqualIID(riid, IID_INonNDRStub) &&
+ (state & proxy_cs) && pIPIDEntry &&
+ (pIPIDEntry->dwFlags & IPIDF_NONNDRSTUB))
+ {
+ // this interface is used to tell proxies whether the server side speaks
+ // NDR or not. Returns S_OK if NOT NDR.
+ *ppvObj = (IUnknown *) this;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+ return S_OK;
+}
+
+/***************************************************************************/
+STDMETHODIMP_(ULONG) CRpcChannelBuffer::Release( THIS )
+{
+ // can't call AssertValid(FALSE) since it is used in asserts
+ ULONG lRef = ref_count - 1;
+
+ if (InterlockedDecrement( (long*) &ref_count ) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ else
+ {
+ return lRef;
+ }
+}
+
+/***************************************************************************/
+STDMETHODIMP CRpcChannelBuffer::SendReceive( THIS_ RPCOLEMESSAGE *pMessage,
+ ULONG *status )
+{
+ return CRpcChannelBuffer::SendReceive2(pMessage, status);
+}
+
+/***************************************************************************/
+STDMETHODIMP CRpcChannelBuffer::SendReceive2( THIS_ RPCOLEMESSAGE *pMessage,
+ ULONG *status )
+{
+ TRACECALL(TRACE_RPC, "CRpcChannelBuffer::SendReceive");
+ ComDebOut((DEB_CHANNEL, "CRpcChannelBuffer::SendReceive pChnl:%x pMsg:%x\n",
+ this, pMessage));
+
+ AssertValid(FALSE, TRUE);
+ Win4Assert( state & proxy_cs );
+ gOXIDTbl.ValidateOXID();
+ ASSERT_LOCK_RELEASED
+
+ HRESULT result;
+ working_call *call;
+ working_call *next_call;
+ IID iid;
+ WireThis *inb;
+ WireThat *outb;
+ DWORD saved_authn_level;
+ BOOL resume;
+ char *stub_data;
+
+ // Get the information about the call stored in TLS
+ COleTls tls;
+ call = (working_call *) tls->pCallInfo;
+ Win4Assert( call != NULL );
+ next_call = (working_call *) call->pNext;
+ saved_authn_level = call->lSavedAuthnLevel;
+ resume = call->iFlags & CF_WAS_IMPERSONATING;
+
+ // Set up the header pointers.
+ inb = (WireThis *) call->pHeader;
+ iid =
+ ((RPC_CLIENT_INTERFACE *) ((RPC_MESSAGE *) call->pmessage)->RpcInterfaceInformation)->InterfaceId.SyntaxGUID;
+
+ // we must ensure that we dont go away during this call. we will Release
+ // ourselves in the FreeBuffer call, or in the error handling at the
+ // end of this function.
+ pStdId->LockClient();
+
+#if DBG==1
+ DWORD CallCat = GetCallCat( inb );
+ DebugPrintORPCCall(ORPC_SENDRECEIVE_BEGIN, iid, call->message.iMethod, CallCat);
+ RpcSpy((CALLOUT_BEGIN, inb, iid, call->message.iMethod, 0));
+#endif
+
+ // Send the request.
+ if ((state & mswmsg_cs) || (IsMTAThread() && !call->Local()))
+ {
+ // For MSWMSG or non-local MTA, call ThreadSendReceive directly.
+ result = ThreadSendReceive( call );
+ }
+ else
+ {
+ if (call->Local())
+ call->message.reserved2[3] = NULL;
+
+ if (IsMTAThread())
+ {
+ LOCK
+ result = GetToSTA( pOXIDEntry, call);
+ UNLOCK
+ }
+ else
+ {
+ result = SwitchSTA( pOXIDEntry, (CChannelCallInfo **) &call );
+ }
+ }
+
+#if DBG==1
+ DebugPrintORPCCall(ORPC_SENDRECEIVE_END, iid, pMessage->iMethod, CallCat);
+ RpcSpy((CALLOUT_END, inb, iid, pMessage->iMethod, result));
+#endif
+
+ // We can't look at the call structure if the call was canceled.
+ if (result != RPC_E_CALL_CANCELED)
+ {
+ // Get the reply header if there is a reply buffer.
+ if ((state & mswmsg_cs) && (pMessage->rpcFlags & RPCFLG_ASYNCHRONOUS))
+ outb = NULL;
+ else
+ outb = (WireThat *) call->message.Buffer;
+
+ // Local calls reuse pNext on the server side.
+ call->pNext = next_call;
+
+ // Save the real buffer pointer for FreeBuffer.
+ call->pHeader = call->message.Buffer;
+ }
+ else
+ outb = NULL;
+
+ // Figure out when to retry.
+ // FreeThreaded - treat retry as a failure.
+ // Apartment - return the buffer and let call control decide.
+
+ if (result == S_OK)
+ {
+ // No buffer was returned for async calls on MSWMSG.
+ if (outb == NULL)
+ *status = S_OK;
+ else if (IsMTAThread())
+ {
+ if (outb->c.flags & ORPCF_REJECTED)
+ result = RPC_E_CALL_REJECTED;
+ else if (outb->c.flags & ORPCF_RETRY_LATER)
+ result = RPC_E_SERVERCALL_RETRYLATER;
+ else
+ *status = S_OK;
+ }
+ else if (outb->c.flags & ORPCF_REJECTED)
+ *status = (ULONG) RPC_E_CALL_REJECTED;
+ else if (outb->c.flags & ORPCF_RETRY_LATER)
+ *status = (ULONG) RPC_E_SERVERCALL_RETRYLATER;
+ else
+ *status = S_OK;
+ }
+
+ // Check the packet extensions.
+ if (result != RPC_E_CALL_CANCELED)
+ {
+ stub_data = (char *) call->message.Buffer;
+ result = ClientNotify( iid, outb, call->message.cbBuffer,
+ (void **) &stub_data,
+ call->message.dataRepresentation,
+ result );
+ }
+ else
+ result = ClientNotify( iid, outb, 0, (void **) &stub_data, 0, result );
+
+ // Call succeeded.
+ if (result == S_OK && outb != NULL)
+ {
+ // The locked flag lets FreeBuffer know that it has to call
+ // RH->UnlockClient.
+ call->iFlags |= CF_LOCKED;
+ pMessage->Buffer = stub_data;
+ pMessage->cbBuffer = call->message.cbBuffer -
+ (stub_data - (char *) call->message.Buffer);
+ pMessage->dataRepresentation = call->message.dataRepresentation;
+ result = *status;
+
+ // Copy a portion of the message structure that RPC updated on SendReceive.
+ // This is needed to free the buffer. Note that we still have to free
+ // the buffer in certain failure cases (reject).
+ pMessage->reserved2[2] = call->message.reserved2[2];
+
+ }
+ else
+ {
+ // Resume any outstanding impersonation.
+ ResumeImpersonate( tls->pCallContext, resume );
+
+ // Clean up the call.
+ pStdId->UnLockClient();
+ tls->pCallInfo = next_call;
+ tls->dwAuthnLevel = saved_authn_level;
+ delete call;
+
+ // Make sure FreeBuffer doesn't try to free the in buffer.
+ pMessage->Buffer = NULL;
+
+ // If the result is server fault, get the exception code from the CChannelCallInfo.
+ if (result == RPC_E_SERVERFAULT)
+ {
+ *status = call->server_fault;
+ }
+ // Everything else is a comm fault.
+ else if (result != S_OK)
+ {
+ *status = result;
+ result = RPC_E_FAULT;
+ }
+ tls->fault = *status;
+
+ // Since result is almost always mapped to RPC_E_FAULT, display the
+ // real error here to assist debugging.
+ if (*status != S_OK)
+ ComDebOut((DEB_CHANNEL, "ORPC call failed. status = %x\n", *status));
+ }
+
+ ASSERT_LOCK_RELEASED
+ gOXIDTbl.ValidateOXID();
+ ComDebOut((DEB_CHANNEL, "CRpcChannelBuffer::SendReceive hr:%x\n", result));
+ return result;
+}
+
+/***************************************************************************/
+HANDLE CRpcChannelBuffer::SwapSecurityToken( HANDLE hNew )
+{
+ HANDLE hOld = hToken;
+ hToken = hNew;
+ return hOld;
+}
+
+#if DBG == 1
+//+-------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::AssertValid
+//
+// Synopsis: Validates that the state of the object is consistent.
+//
+// History: 25-Jan-94 CraigWi Created.
+//
+// DCOMWORK - Put in some asserts.
+//
+//--------------------------------------------------------------------
+void CRpcChannelBuffer::AssertValid(BOOL fKnownDisconnected,
+ BOOL fMustBeOnCOMThread)
+{
+ Win4Assert(state & (proxy_cs | client_cs | server_cs ));
+
+ if (state & (client_cs | proxy_cs))
+ {
+ ;
+ }
+ else if (state & server_cs)
+ {
+ Win4Assert( !(state & freethreaded_cs) );
+ if (fMustBeOnCOMThread && IsSTAThread())
+ Win4Assert(IsMTAThread() || pOXIDEntry->dwTid == GetCurrentThreadId());
+ // ref count can be 0 in various stages of connection and disconnection
+ Win4Assert(ref_count < 0x7fff && "Channel ref count unreasonably high");
+
+ // the pStdId pointer can not be NULL
+ // Win4Assert(IsValidInterface(pStdId));
+ }
+}
+#endif // DBG == 1
+
+
+/***************************************************************************/
+STDAPI_(ULONG) DebugCoGetRpcFault()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+
+ if (SUCCEEDED(hr))
+ return tls->fault;
+
+ return 0;
+}
+
+/***************************************************************************/
+STDAPI_(void) DebugCoSetRpcFault( ULONG fault )
+{
+ HRESULT hr;
+ COleTls tls(hr);
+
+ if (SUCCEEDED(hr))
+ tls->fault = fault;
+}
+
+/***************************************************************************/
+extern "C"
+BOOL _stdcall DllDebugObjectRPCHook( BOOL trace, LPORPC_INIT_ARGS pass_through )
+{
+ if (!IsWOWThread())
+ {
+ DoDebuggerHooks = trace;
+ DebuggerArg = pass_through;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/***************************************************************************/
+BOOL LocalCall()
+{
+ CChannelCallInfo *call;
+
+ // Get the call info from TLS.
+ COleTls tls;
+ call = (CChannelCallInfo *) tls->pCallInfo;
+ Win4Assert( call != NULL );
+ return call->iFlags & CF_PROCESS_LOCAL;
+}
+
+/***************************************************************************/
+LONG ThreadInvokeExceptionFilter( DWORD lCode,
+ LPEXCEPTION_POINTERS lpep )
+{
+ ComDebOut((DEB_ERROR, "Exception 0x%x in ThreadInvoke at address 0x%x\n",
+ lCode, lpep->ExceptionRecord->ExceptionAddress));
+ DebugBreak();
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+/***************************************************************************/
+/* This routine returns both comm status and server faults to the runtime
+ by raising exceptions. If FreeThreading is true, ComInvoke will throw
+ exceptions to indicate server faults. These will not be caught and will
+ propogate directly to the runtime. If FreeThreading is false, ComInvoke
+ will return the result and fault in the CChannelCallInfo record.
+
+ NOTE:
+ This function switches to the 32 bit stack under WIN95.
+ An exception has to be caught while switched to the 32 bit stack.
+ The exceptions has to be pass as a value and rethrown again on the
+ 16 bit stack (see SSInvoke in stkswtch.cxx)
+*/
+
+#ifdef _CHICAGO_
+DWORD
+#else
+void
+#endif
+SSAPI(ThreadInvoke)(RPC_MESSAGE *message )
+{
+ HRESULT result = S_OK;
+
+ TRACECALL(TRACE_RPC, "ThreadInvoke");
+ ComDebOut((DEB_CHANNEL,"ThreadInvoke pMsg:%x\n", message));
+ gOXIDTbl.ValidateOXID();
+ ASSERT_LOCK_RELEASED
+
+ BOOL success;
+ WireThis *inb = (WireThis *) message->Buffer;
+ IPID ipid;
+ RPC_STATUS status;
+ OXIDEntry *pOxid;
+ unsigned int transport_type;
+ DWORD authn_level;
+
+ // Byte swap the header.
+ ByteSwapThis( message->DataRepresentation, inb );
+
+ // Validate several things:
+ // The packet size is larger then the first header size.
+ // No extra flags are set.
+ // The procedure number is greater then 2 (not QI, AddRef, Release).
+ if (sizeof(WireThisPart1) > message->BufferLength ||
+ (inb->c.flags & ~(ORPCF_LOCAL | ORPCF_RESERVED1 |
+ ORPCF_RESERVED2 | ORPCF_RESERVED3 | ORPCF_RESERVED4)) != 0 ||
+ message->ProcNum < 3)
+ RETURN_COMM_STATUS( RPC_E_INVALID_HEADER );
+
+ // Validate the version.
+ if (inb->c.version.MajorVersion != COM_MAJOR_VERSION ||
+ inb->c.version.MinorVersion > COM_MINOR_VERSION)
+ RETURN_COMM_STATUS( RPC_E_VERSION_MISMATCH );
+
+ // Get the transport the call arrived on.
+ status = I_RpcServerInqTransportType( &transport_type );
+ if (status != RPC_S_OK)
+ RETURN_COMM_STATUS( RPC_E_SYS_CALL_FAILED );
+
+ // Don't accept the local header on remote calls.
+ if (inb->c.flags & ORPCF_LOCAL)
+ {
+ if (transport_type != TRANSPORT_TYPE_LPC &&
+ transport_type != TRANSPORT_TYPE_WMSG)
+ RETURN_COMM_STATUS( RPC_E_INVALID_HEADER );
+
+ // For local calls the authentication level will always be encrypt.
+ authn_level = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
+ }
+
+ // Don't accept remote calls if DCOM is diabled.
+ else if (gDisableDCOM &&
+ (transport_type == TRANSPORT_TYPE_CN || transport_type == TRANSPORT_TYPE_DG))
+ RETURN_COMM_STATUS( RPC_E_CALL_REJECTED );
+
+ // Lookup the authentication level.
+ else
+ {
+ result = RpcBindingInqAuthClient( message->Handle, NULL,
+ NULL, &authn_level, NULL, NULL );
+ if (result == RPC_S_BINDING_HAS_NO_AUTH)
+ authn_level = RPC_C_AUTHN_LEVEL_NONE;
+ else if (result != RPC_S_OK)
+ {
+ Win4Assert( result == RPC_S_OUT_OF_RESOURCES );
+ RETURN_COMM_STATUS( MAKE_WIN32( result ) );
+ }
+
+ // Verify the authentication level.
+ if (gAuthnLevel > RPC_C_AUTHN_LEVEL_NONE ||
+ gImpLevel > 0)
+ {
+ if (authn_level < gAuthnLevel)
+ RETURN_COMM_STATUS( RPC_E_ACCESS_DENIED );
+ }
+ }
+
+#if DBG==1
+ _try
+ {
+#endif
+
+ // Find the ipid entry from the ipid.
+ status = RpcBindingInqObject( message->Handle, &ipid );
+ if (status == RPC_S_OK)
+ {
+ // The CChannelCallInfo is created in a nested scope so that it
+ // is destroyed before the calls to throw an exception at the
+ // end of this function.
+ CChannelCallInfo call(
+ GetCallCat( inb ),
+ (RPCOLEMESSAGE *) message,
+ 0,
+ ipid,
+ (inb->c.flags & ORPCF_LOCAL) ? MSHCTX_LOCAL : MSHCTX_DIFFERENTMACHINE,
+ NULL,
+ authn_level );
+
+
+ // Find the OXIDEntry of the server apartment.
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ IPIDEntry *ipid_entry = gIPIDTbl.LookupIPID( ipid );
+
+ if (ipid_entry == NULL || (ipid_entry->dwFlags & IPIDF_DISCONNECTED)
+ || ipid_entry->pChnl == NULL )
+ {
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ result = RPC_E_DISCONNECTED;
+ }
+ else
+ {
+ pOxid = ipid_entry->pOXIDEntry;
+
+ // NCALRPC always gets the thread right (except on Chicago).
+ // For MTAs, any thread will do.
+ if (transport_type == TRANSPORT_TYPE_WMSG ||
+#ifndef _CHICAGO_
+ transport_type == TRANSPORT_TYPE_LPC ||
+#endif
+ (pOxid->dwFlags & OXIDF_MTASERVER))
+ {
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ result = ComInvoke( &call );
+ }
+ else
+ {
+ // Pass the message to the app thread.
+
+ IncOXIDRefCnt( pOxid );
+ result = GetToSTA( pOxid, &call );
+ DecOXIDRefCnt( pOxid );
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ }
+ }
+ }
+ else
+ {
+ result = MAKE_WIN32( status );
+ }
+
+#if DBG==1
+ }
+ _except( ThreadInvokeExceptionFilter(GetExceptionCode(),
+ GetExceptionInformation()) )
+ {
+ }
+#endif
+
+ // For comm and server faults, generate an exception. Otherwise the buffer
+ // is set up correctly.
+ gOXIDTbl.ValidateOXID();
+ if (result == RPC_E_SERVERFAULT)
+ {
+ ASSERT_LOCK_RELEASED
+ RETURN_COMM_STATUS( RPC_E_SERVERFAULT );
+ }
+ else if (result != S_OK)
+ {
+ ASSERT_LOCK_RELEASED
+ RETURN_COMM_STATUS( result );
+ }
+
+#ifdef _CHICAGO_
+ return 0;
+#endif //_CHICAGO_
+}
+
+
+/***************************************************************************/
+HRESULT ThreadSendReceive( CChannelCallInfo *call )
+{
+ TRACECALL(TRACE_RPC, "ThreadSendReceive");
+ ComDebOut((DEB_CHANNEL, "ThreadSendReceive pCall:%x\n", call));
+
+ ASSERT_LOCK_RELEASED
+
+ HRESULT result;
+ RPCOLEMESSAGE *message = call->pmessage;
+ WireThat *outb;
+
+ // Call the runtime. In the future, detect server faults and
+ // change the value of result to RPC_E_SERVERFAULT.
+ if (call->pChannel->state & mswmsg_cs)
+ {
+ CAptCallCtrl *pACC = GetAptCallCtrl();
+ CCliModalLoop *pCML = (pACC) ? pACC->GetTopCML() : NULL;
+ OXIDEntry *pOxidClient;
+ HWND hwnd = NULL;
+
+ if (IsWOWThread())
+ {
+ LOCK
+ result = gOXIDTbl.GetLocalEntry( &pOxidClient );
+ UNLOCK
+ Win4Assert( result == S_OK );
+ hwnd = (HWND) pOxidClient->hServerSTA;
+ }
+ TRACECALL(TRACE_RPC, "I_RpcAsyncSendReceive");
+ result = I_RpcAsyncSendReceive( (RPC_MESSAGE *) message, pCML, hwnd );
+
+ // If the call was canceled, the rest of the code path assumes that
+ // the call was deleted (by SwitchComThread). So delete it.
+ if (result == RPC_S_CALL_CANCELLED)
+ {
+ // Convert the win32 error to a hresult.
+ result = RPC_E_CALL_CANCELED;
+ delete call;
+ }
+ }
+ else
+ {
+ TRACECALL(TRACE_RPC, "I_RpcSendReceive");
+ result = I_RpcSendReceive( (RPC_MESSAGE *) message );
+ }
+
+ // If the result is small, it is probably a Win32 code.
+ if (result != 0)
+ {
+ message->Buffer = NULL;
+ if ((ULONG) result > 0xfffffff7 || (ULONG) result < 0x2000)
+ result = MAKE_WIN32( result );
+ }
+ else
+ {
+ // No buffer is returned for asynchronous calls on MSWMSG.
+ if ((call->pChannel->state & mswmsg_cs) == 0 ||
+ (message->rpcFlags & RPCFLG_ASYNCHRONOUS) == 0)
+ {
+ // Byte swap the reply header. Fail the call if the buffer is too
+ // small.
+ outb = (WireThat *) message->Buffer;
+ if (message->cbBuffer >= sizeof(WireThatPart1))
+ ByteSwapThat( message->dataRepresentation, outb);
+ else
+ result = RPC_E_INVALID_HEADER;
+ }
+ }
+
+ ComDebOut((DEB_CHANNEL, "ThreadSendReceive pCall:%x hr:%x\n", call, result));
+ return result;
+}
+
+/***************************************************************************/
+/* static */
+
+void working_call::Cleanup()
+{
+ ASSERT_LOCK_HELD
+
+ DWORD i;
+
+ // Release everything.
+ if (next <= CALLCACHE_SIZE)
+ {
+ for (i = 0; i < next; i++)
+ if (list[i] != NULL)
+ {
+ PrivMemFree( list[i] );
+ list[i] = NULL;
+ }
+
+ next = 0;
+ }
+}
+
+/***************************************************************************/
+/* static */
+
+void working_call::Initialize()
+{
+ ASSERT_LOCK_HELD
+ next = 0;
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: working_call:: operator delete
+//
+// Synopsis: Cache or actually free a working call.
+//
+// Notes: gComLock need not be held before calling this function.
+//
+//---------------------------------------------------------------------------
+void working_call::operator delete( void *call )
+{
+ // Add the structure to the list if the list is not full and
+ // if the process is still initialized (since latent threads may try
+ // to return stuff).
+
+ LOCK
+ if (next < CALLCACHE_SIZE && gfChannelProcessInitialized)
+ {
+ list[next] = call;
+ next += 1;
+ }
+
+ // Otherwise just free it.
+ else
+ {
+ PrivMemFree( call );
+ }
+ UNLOCK
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: working_call:: operator new
+//
+// Synopsis: Keep a cache of working_calls. Since the destructor is
+// virtual, the correct delete will be called if any base
+// class is deleted.
+//
+// Notes: gComLock must be held before calling this function.
+//
+//---------------------------------------------------------------------------
+void *working_call::operator new( size_t size )
+{
+ ASSERT_LOCK_HELD
+
+ void *call;
+
+ // Get the last entry from the cache.
+ Win4Assert( size == sizeof( working_call ) );
+ if (next > 0 && next < CALLCACHE_SIZE+1)
+ {
+ next -= 1;
+ call = list[next];
+ list[next] = NULL;
+ }
+
+ // If there are none, allocate a new one.
+ else
+ call = PrivMemAlloc(size);
+ return call;
+}
+
+ /**********************************************************************/
+working_call::working_call( CALLCATEGORY callcat,
+ RPCOLEMESSAGE *original_msg,
+ DWORD flags,
+ REFIPID ipidServer,
+ DWORD destctx,
+ CRpcChannelBuffer *channel,
+ DWORD authn_level ) :
+ CChannelCallInfo( callcat, &message, flags, ipidServer, destctx, channel,
+ authn_level )
+{
+ message = *original_msg;
+}
+
diff --git a/private/ole32/com/dcomrem/channelb.hxx b/private/ole32/com/dcomrem/channelb.hxx
new file mode 100644
index 000000000..75e41f23f
--- /dev/null
+++ b/private/ole32/com/dcomrem/channelb.hxx
@@ -0,0 +1,259 @@
+
+#ifndef _CHANNELB_HXX_
+#define _CHANNELB_HXX_
+
+#include <sem.hxx>
+#include <rpc.h>
+#include <rpcndr.h>
+#include <chancont.hxx>
+#include <stdid.hxx>
+
+extern "C"
+{
+#include "orpc_dbg.h"
+}
+
+/* Type definitions. */
+typedef enum EChannelState
+{
+ // The channel on the client side held by the remote handler.
+ client_cs = 0x1,
+
+ // The channels on the client side held by proxies.
+ proxy_cs = 0x2,
+
+ // The server channels held by remote handlers.
+ server_cs = 0x4,
+
+ // Flag to indicate that the channel may be used on any thread.
+ freethreaded_cs = 0x8,
+
+ // Client side only. Use mswmsg transport.
+ mswmsg_cs = 0x10,
+
+ // Client side only. handle and pInterfaceInfo initialized.
+ initialized_cs = 0x20,
+
+ // The server and client are in this process.
+ process_local_cs = 0x40,
+
+ // The proxy has been set to identify level impersonation (process local only).
+ identify_cs = 0x80
+
+} EChannelState;
+
+
+// The size of this structure must be a multiple of 8.
+typedef struct LocalThis
+{
+ DWORD flags;
+ DWORD client_thread;
+} LocalThis;
+
+// LocalThis flag indicates parameters in buffer not marshalled NDR
+const DWORD LOCALF_NONNDR = 0x800;
+
+
+/***************************************************************************/
+
+// Debug Code
+
+#define ORPC_INVOKE_BEGIN 0
+#define ORPC_INVOKE_END 1
+#define ORPC_SENDRECEIVE_BEGIN 2
+#define ORPC_SENDRECEIVE_END 3
+
+#if DBG==1
+void DebugPrintORPCCall(DWORD dwFlag, REFIID riid, DWORD iMethod, DWORD Callcat);
+#else
+inline void DebugPrintORPCCall(DWORD dwFlag, REFIID riid, DWORD iMethod, DWORD Callcat) {}
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Interface: IRpcChannelBuffer2
+//
+// Synopsis: Interface to add one more method to the IRpcChannelBuffer
+// for use by the call control.
+//
+//+-------------------------------------------------------------------------
+class IRpcChannelBuffer2 : public IRpcChannelBuffer
+{
+public:
+ STDMETHOD (QueryInterface) (REFIID riid, LPVOID FAR* ppvObj) = 0;
+ STDMETHOD_(ULONG,AddRef) (void) = 0;
+ STDMETHOD_(ULONG,Release) (void) = 0;
+
+ STDMETHOD (GetBuffer) (RPCOLEMESSAGE *pMessage, REFIID) = 0;
+ STDMETHOD (FreeBuffer) (RPCOLEMESSAGE *pMessage) = 0;
+ STDMETHOD (SendReceive) (RPCOLEMESSAGE *pMessage, ULONG *) = 0;
+ STDMETHOD (GetDestCtx) (DWORD *lpdwDestCtx, LPVOID *lplpvDestCtx) = 0;
+ STDMETHOD (IsConnected) (void) = 0;
+
+ // method on apartment channels called by CCliModalLoop
+ STDMETHOD (SendReceive2) (RPCOLEMESSAGE *pMsg, ULONG *pulStatus) = 0;
+};
+
+
+
+//+----------------------------------------------------------------
+//
+// Class: CRpcChannelBuffer
+//
+// Purpose: Three distinct uses:
+// Client side channel
+// State:
+// When not connected (after create and after disconnect):
+// ref_count 1 + 1 per addref during pending
+// calls that were in progress during
+// a disconnect.
+// pStdId back pointer to Id; not Addref'd
+// state client_cs
+//
+// When connected (after unmarshal):
+// ref_count 1 + 1 for each proxy
+// pStdId same
+// state client_cs
+//
+// Server side channel; free standing; comes and goes with each
+// connection; addref owned disconnected via last release.
+// State:
+// ref_count > 0
+// pStdId pointer to other Id; AddRef'd
+// state server_cs
+//
+// Interface: IRpcChannelBuffer
+//
+//-----------------------------------------------------------------
+
+class CRpcChannelBuffer : public IRpcChannelBuffer2,
+ public CPrivAlloc
+{
+ friend HRESULT ComInvoke ( CChannelCallInfo * );
+ friend HRESULT ThreadSendReceive ( CChannelCallInfo * );
+
+ public:
+ STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) ( void );
+ STDMETHOD_(ULONG,Release) ( void );
+ STDMETHOD ( GetBuffer ) ( RPCOLEMESSAGE *pMessage, REFIID );
+ STDMETHOD ( FreeBuffer ) ( RPCOLEMESSAGE *pMessage );
+ STDMETHOD ( SendReceive ) ( RPCOLEMESSAGE *pMessage, ULONG * );
+ STDMETHOD ( GetDestCtx ) ( DWORD FAR* lpdwDestCtx,
+ LPVOID FAR* lplpvDestCtx );
+ STDMETHOD ( IsConnected ) ( void );
+ STDMETHOD (SendReceive2) (RPCOLEMESSAGE *pMsg, ULONG *pulStatus);
+
+
+ CRpcChannelBuffer *Copy (OXIDEntry *pOXIDEntry,
+ REFIPID ripid, REFIID riid);
+ HRESULT GetHandle ( handle_t * );
+ DWORD GetImpLevel ( void );
+ REFMOXID GetMOXID ( void ) { return pOXIDEntry->moxid;}
+ OXIDEntry *GetOXIDEntry ( void ) { return pOXIDEntry; }
+ HANDLE GetSecurityToken ( void ) { return hToken; }
+ CStdIdentity *GetStdId ( void );
+ BOOL ProcessLocal ( void ) { return state & process_local_cs; }
+ void SetAuthnLevel ( DWORD level ) { lAuthnLevel = level; }
+ void SetImpLevel ( DWORD level );
+ void SetIPIDEntry(IPIDEntry *pEntry) { pIPIDEntry = pEntry; }
+ HANDLE SwapSecurityToken ( HANDLE );
+ BOOL UsingMswmsg ( void ) { return state & mswmsg_cs; }
+
+#if DBG == 1
+ void AssertValid(BOOL fKnownDisconnected, BOOL fMustBeOnCOMThread);
+#else
+ void AssertValid(BOOL fKnownDisconnected, BOOL fMustBeOnCOMThread) { }
+#endif
+
+ CRpcChannelBuffer( CStdIdentity *,
+ OXIDEntry *,
+ DWORD eState );
+ ~CRpcChannelBuffer();
+
+ protected:
+ BOOL CallableOnAnyApt( void ) { return state & freethreaded_cs; }
+ HRESULT ClientGetBuffer ( RPCOLEMESSAGE *, REFIID );
+
+ private:
+ HRESULT AppInvoke ( CChannelCallInfo *, IRpcStubBuffer *,
+ void *object, void *stub_data, LocalThis * );
+ void CheckDestCtx ( void *pDestProtseq );
+ HRESULT ServerGetBuffer( RPCOLEMESSAGE *, REFIID );
+ HRESULT InitClientSideHandle();
+
+ ULONG ref_count;
+ CStdIdentity *pStdId;
+ DWORD state; // See EChannelState
+ handle_t handle;
+ OXIDEntry *pOXIDEntry;
+ IPIDEntry *pIPIDEntry;
+ DWORD iDestCtx;
+ void *pInterfaceInfo;
+ HANDLE hToken;
+ DWORD lAuthnLevel;
+};
+
+inline void DeallocateBuffer(RPCOLEMESSAGE *message )
+{
+ if (message->rpcFlags & RPCFLG_LOCAL_CALL)
+ PrivMemFree( message->Buffer );
+ else
+ I_RpcFreeBuffer( (RPC_MESSAGE *) message );
+}
+
+// returns the std identity object; not addref'd.
+inline CStdIdentity *CRpcChannelBuffer::GetStdId()
+{
+ AssertValid(FALSE, FALSE);
+ Win4Assert( pStdId != NULL );
+ return pStdId;
+}
+
+inline DWORD CRpcChannelBuffer::GetImpLevel()
+{
+ if (state & identify_cs)
+ return RPC_C_IMP_LEVEL_IDENTIFY;
+ else
+ return RPC_C_IMP_LEVEL_IMPERSONATE;
+}
+
+inline void CRpcChannelBuffer::SetImpLevel( DWORD level )
+{
+ if (level == RPC_C_IMP_LEVEL_IDENTIFY)
+ state |= identify_cs;
+ else
+ state &= ~identify_cs;
+}
+
+inline HRESULT CRpcChannelBuffer::GetHandle( handle_t *pHandle )
+{
+ HRESULT status;
+ LOCK
+ status = InitClientSideHandle();
+ if (status == RPC_S_OK)
+ *pHandle = handle;
+ UNLOCK
+ return status;
+}
+
+/* Prototypes. */
+HRESULT ComInvoke ( CChannelCallInfo * );
+BOOL LocalCall ( void );
+CChannelCallInfo *MakeAsyncCopy ( CChannelCallInfo * );
+void ThreadInvoke ( RPC_MESSAGE *message );
+HRESULT ThreadSendReceive( CChannelCallInfo * );
+HRESULT StubInvoke(RPCOLEMESSAGE *pMsg, IRpcStubBuffer *pStub,
+ IRpcChannelBuffer *pChnl, DWORD *pdwFault);
+
+#if DBG==1
+LONG GetInterfaceName(REFIID riid, WCHAR *wszName);
+#endif
+
+// Externs
+extern BOOL DoDebuggerHooks;
+extern LPORPC_INIT_ARGS DebuggerArg;
+extern const uuid_t DEBUG_EXTENSION;
+
+#endif //_CHANNELB_HXX_
+
diff --git a/private/ole32/com/dcomrem/chock.cxx b/private/ole32/com/dcomrem/chock.cxx
new file mode 100644
index 000000000..23bd268de
--- /dev/null
+++ b/private/ole32/com/dcomrem/chock.cxx
@@ -0,0 +1,974 @@
+//+-------------------------------------------------------------------
+//
+// File: chock.cxx
+//
+// Contents: Channel hook APIs
+//
+// Classes: CDebugChannelHook
+//
+//--------------------------------------------------------------------
+#include <ole2int.h>
+extern "C"
+{
+#include "orpc_dbg.h"
+}
+#include <channelb.hxx>
+#include <ipidtbl.hxx>
+#include <chock.hxx>
+#include <stream.hxx>
+
+
+//+----------------------------------------------------------------
+// Definitions.
+
+typedef struct SHookList
+{
+ struct SHookList *pNext;
+ IChannelHook *pHook;
+ UUID uExtension;
+} SHookList;
+
+
+//+----------------------------------------------------------------
+// Global variables.
+SHookList gHookList = { &gHookList, NULL };
+ULONG gNumExtent = 0;
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CleanupChannelHooks
+//
+// Synopsis: Releases all the hooks in the list.
+//
+//--------------------------------------------------------------------
+void CleanupChannelHooks()
+{
+ SHookList *pCurr = gHookList.pNext;
+
+ // Release and free each entry.
+ while (pCurr != &gHookList)
+ {
+ pCurr->pHook->Release();
+ gHookList.pNext = pCurr->pNext;
+ PrivMemFree( pCurr );
+ pCurr = gHookList.pNext;
+ }
+ gNumExtent = 0;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoRegisterChannelHook
+//
+// Synopsis: Adds a hook object to the list of hook objects.
+//
+//--------------------------------------------------------------------
+WINOLEAPI CoRegisterChannelHook( REFGUID uExtension, IChannelHook *pCaptain )
+{
+ SHookList *pCurr;
+ HRESULT hr = S_OK;
+
+ // ChannelProcessIntialize calls while holding the lock.
+ ASSERT_LOCK_DONTCARE
+ LOCK
+
+#if DBG==1
+ // See if the extenstion is already on the list.
+ pCurr = gHookList.pNext;
+ while (pCurr != &gHookList)
+ {
+ if (pCurr->uExtension == uExtension)
+ break;
+ pCurr = pCurr->pNext;
+ }
+ Win4Assert( pCurr == &gHookList );
+ Win4Assert( pCaptain != NULL );
+#endif
+
+ // Add a node at the head.
+ pCurr = (SHookList *) PrivMemAlloc( sizeof(SHookList) );
+ if (pCurr != NULL)
+ {
+ pCaptain->AddRef();
+ pCurr->uExtension = uExtension;
+ pCurr->pHook = pCaptain;
+ pCurr->pNext = gHookList.pNext;
+ gHookList.pNext = pCurr;
+ gNumExtent += 1;
+ }
+ else
+ hr = E_OUTOFMEMORY;
+
+ UNLOCK
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: ClientGetSize
+//
+// Synopsis: Asks each hook in the list how much data it wishes to
+// place in the next request on this thread.
+//
+//--------------------------------------------------------------------
+ULONG ClientGetSize( REFIID riid, ULONG *cNumExtent )
+{
+ SHookList *pCurr = gHookList.pNext;
+ ULONG lSize = sizeof(WireExtentArray) - 8;
+ ULONG lPiece = 0;
+ *cNumExtent = 0;
+
+ // Ignore any hooks added to the head of the list.
+ ASSERT_LOCK_DONTCARE
+
+ // Ask each hook.
+ while (pCurr != &gHookList)
+ {
+ pCurr->pHook->ClientGetSize( pCurr->uExtension, riid, &lPiece );
+ if (lPiece != 0)
+ {
+ lPiece = ((lPiece + 7) & ~7) + sizeof(WireExtent);
+ lSize += lPiece;
+ *cNumExtent += 1;
+ }
+ pCurr = pCurr->pNext;
+ }
+
+ // Round up the number of extents and add size for an array of unique
+ // flags.
+ *cNumExtent = (*cNumExtent + 1) & ~1;
+ lSize += sizeof(DWORD) * *cNumExtent;
+
+ if (*cNumExtent != 0)
+ return lSize;
+ else
+ return 0;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: FillBuffer
+//
+// Synopsis: Asks each hook in the list to place data in the buffer
+// for the next request on this thread. Returns the final
+// buffer pointer.
+//
+//--------------------------------------------------------------------
+void *FillBuffer( REFIID riid, WireExtentArray *pArray, ULONG cMax,
+ ULONG cNumExtent, BOOL fClient )
+{
+ SHookList *pCurr;
+ WireExtent *pExtent;
+ ULONG lPiece;
+ ULONG cNumFill;
+ ULONG i;
+
+ // Ignore any hooks added to the head of the list.
+ ASSERT_LOCK_DONTCARE
+
+ // Figure out where the extents start.
+ pCurr = gHookList.pNext;
+ pExtent = (WireExtent *) ((void **) (pArray + 1) + cNumExtent - 2);
+ cNumFill = 0;
+ cMax -= sizeof(WireExtentArray) - 8 + sizeof(void*)*cNumExtent;
+
+ // Ask each hook.
+ while (pCurr != &gHookList && cMax > 0)
+ {
+ lPiece = cMax - sizeof(WireExtent);
+ if (fClient)
+ pCurr->pHook->ClientFillBuffer( pCurr->uExtension, riid, &lPiece,
+ pExtent+1 );
+ else
+ pCurr->pHook->ServerFillBuffer( pCurr->uExtension, riid, &lPiece,
+ pExtent+1, S_OK );
+ Win4Assert( ((lPiece+7)&~7) + sizeof(WireExtent) <= cMax );
+
+ // If the hook put in data, initialize this extent and find the next.
+ if (lPiece != 0)
+ {
+ pExtent->size = lPiece;
+ pExtent->rounded_size = (lPiece+7) & ~7;
+ pExtent->id = pCurr->uExtension;
+ cNumFill += 1;
+ cMax -= pExtent->rounded_size + sizeof(WireExtent);
+ pExtent = (WireExtent *) ((char *) (pExtent+1) +
+ pExtent->rounded_size);
+
+ Win4Assert( cNumFill <= cNumExtent );
+ }
+ pCurr = pCurr->pNext;
+ }
+
+ // If any hooks put in data, fill in the header.
+ if (cNumFill != 0)
+ {
+ pArray->size = cNumFill;
+ pArray->reserved = 0;
+ pArray->unique = 0x6d727453; // Any non-zero value.
+ pArray->rounded_size = (cNumFill+1) & ~1;
+ for (i = 0; i < cNumExtent; i++)
+ if (i < cNumFill)
+ pArray->unique_flag[i] = 0x79614b44; // Any non-zero value.
+ else
+ pArray->unique_flag[i] = 0;
+ return pExtent;
+ }
+
+ // Otherwise return the original buffer.
+ else
+ {
+ return pArray;
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: FindExtentId
+//
+// Synopsis: Search for the specified extension id in the list of
+// registered extensions. Return the index of the entry
+// if found
+//
+//--------------------------------------------------------------------
+ULONG FindExtentId( SHookList *pHead, UUID uExtension )
+{
+ ULONG i = 0;
+ while (pHead != &gHookList)
+ if (pHead->uExtension == uExtension)
+ return i;
+ else
+ {
+ i += 1;
+ pHead = pHead->pNext;
+ }
+ return 0xffffffff;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: VerifyExtent
+//
+// Synopsis: Verifies extent array and extents.
+//
+//--------------------------------------------------------------------
+void *VerifyExtent( SHookList *pHead, WireExtentArray *pArray, ULONG cMax,
+ WireExtent **aExtent, DWORD dwRep )
+{
+ WireExtent *pExtent;
+ ULONG i;
+ ULONG j;
+ ULONG cNumExtent;
+ WireExtent *pEnd;
+
+ // Fail if the buffer isn't larger then the extent array header.
+ if (cMax < sizeof(WireExtentArray) - 8)
+ return NULL;
+
+ // Byte swap the array header.
+ if ((dwRep & NDR_LOCAL_DATA_REPRESENTATION) != NDR_LITTLE_ENDIAN)
+ {
+ ByteSwapLong( pArray->size );
+ // ByteSwapLong( pArray->reserved );
+ ByteSwapLong( pArray->rounded_size );
+ }
+
+ // Validate the array header.
+ if (cMax < sizeof(WireExtentArray) - 8 +
+ sizeof(ULONG) * pArray->rounded_size ||
+ (pArray->rounded_size & 1) != 0 ||
+ pArray->size > pArray->rounded_size ||
+ pArray->reserved != 0)
+ return NULL;
+
+ // Count how many unique flags are set.
+ cNumExtent = 0;
+ for (i = 0; i < pArray->size; i++)
+ if (pArray->unique_flag[i])
+ cNumExtent += 1;
+
+ // Look up each extent from the packet in the registered list.
+ pEnd = (WireExtent *) ((char *) pArray + cMax);
+ pExtent = (WireExtent *) &pArray->unique_flag[pArray->rounded_size];
+ for (i = 0; i < cNumExtent; i++)
+ {
+ // Fail if the next extent header doesn't fit in the buffer.
+ if (pExtent + 1 > pEnd)
+ return NULL;
+
+ // Byte swap the extent header.
+ if ((dwRep & NDR_LOCAL_DATA_REPRESENTATION) != NDR_LITTLE_ENDIAN)
+ {
+ ByteSwapLong( pExtent->rounded_size );
+ ByteSwapLong( pExtent->size );
+ ByteSwapLong( pExtent->id.Data1 );
+ ByteSwapShort( pExtent->id.Data2 );
+ ByteSwapShort( pExtent->id.Data3 );
+ }
+
+ // Validate the extent.
+ if (pExtent->size > pExtent->rounded_size ||
+ (pExtent->rounded_size & 1) != 0 ||
+ ((char *) (pExtent+1)) + pExtent->rounded_size > (char *) pEnd)
+ return NULL;
+
+ // If the extension is registered, save a pointer to it.
+ j = FindExtentId( pHead, pExtent->id );
+ if (j != 0xffffffff)
+ aExtent[j] = pExtent;
+
+ // Find the next extension.
+ pExtent = (WireExtent *) ((char *) (pExtent + 1) +
+ pExtent->rounded_size);
+ }
+ return pExtent;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: ClientNotify
+//
+// Synopsis: Calls each hook and passes data to those that received
+// data in a reply.
+//
+// Notes: pOut is NULL for failed calls or async calls.
+//
+//--------------------------------------------------------------------
+HRESULT ClientNotify( REFIID riid, WireThat *pOut, ULONG cMax, void **pStubData,
+ DWORD dwRep, HRESULT hr )
+{
+ SHookList *pHead = gHookList.pNext;
+ SHookList *pCurr;
+ WireExtent **aExtent;
+ ULONG cMaxExtent = gNumExtent;
+ ULONG i;
+
+ // Return immediately if there is nothing to do.
+ *pStubData = &pOut->d.ea;
+ if (pHead == &gHookList &&
+ (pOut == NULL || pOut->c.unique == FALSE))
+ return hr;
+
+ // Initialize the array of extent pointers.
+ aExtent = (WireExtent **) _alloca( cMaxExtent * sizeof(WireExtent *) );
+ memset( aExtent, 0, cMaxExtent * sizeof( WireExtent *) );
+
+ // If there are any extents, verify them and sort them.
+ if (SUCCEEDED(hr) && pOut != NULL && pOut->c.unique)
+ {
+ *pStubData = VerifyExtent( pHead, &pOut->d.ea, cMax - sizeof(WireThatPart1),
+ aExtent, dwRep );
+ if (*pStubData == NULL)
+ return RPC_E_INVALID_EXTENSION;
+ }
+
+ // Notify all the hooks
+ for (pCurr = pHead, i = 0; pCurr != &gHookList; pCurr = pCurr->pNext, i++)
+ pCurr->pHook->ClientNotify( pCurr->uExtension, riid,
+ aExtent[i] != NULL ? aExtent[i]->size : 0,
+ aExtent[i] != NULL ? aExtent[i] + 1 : NULL,
+ dwRep, hr );
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: ServerNotify
+//
+// Synopsis: Calls each hook and passes data to those that receive
+// data in a request.
+//
+//--------------------------------------------------------------------
+HRESULT ServerNotify( REFIID riid, WireThis *pIn, ULONG cMax, void **pStubData,
+ DWORD dwRep )
+{
+ SHookList *pHead = gHookList.pNext;
+ SHookList *pCurr;
+ WireExtent **aExtent;
+ ULONG cMaxExtent = gNumExtent;
+ ULONG i;
+
+ // Return immediately if there is nothing to do.
+ *pStubData = &pIn->d.ea;
+ if (pHead == &gHookList && pIn->c.unique == FALSE)
+ return S_OK;
+
+ // Initialize the array of extent pointers.
+ aExtent = (WireExtent **) _alloca( cMaxExtent * sizeof(WireExtent *) );
+ memset( aExtent, 0, cMaxExtent * sizeof( WireExtent *) );
+
+ // If there are any extents, verify them and sort them.
+ if (pIn->c.unique)
+ {
+ *pStubData = VerifyExtent( pHead, &pIn->d.ea, cMax - sizeof(WireThisPart1),
+ aExtent, dwRep );
+ if (*pStubData == NULL)
+ return RPC_E_INVALID_EXTENSION;
+ }
+
+ // Notify all the hooks
+ for (pCurr = pHead, i = 0; pCurr != &gHookList; pCurr = pCurr->pNext, i++)
+ pCurr->pHook->ServerNotify( pCurr->uExtension, riid,
+ aExtent[i] != NULL ? aExtent[i]->size : 0,
+ aExtent[i] != NULL ? aExtent[i] + 1 : NULL,
+ dwRep );
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: ServerGetSize
+//
+// Synopsis: Asks each hook in the list how much data it wishes to
+// place in the next reply on this thread.
+//
+//--------------------------------------------------------------------
+ULONG ServerGetSize( REFIID riid, ULONG *cNumExtent )
+{
+ SHookList *pCurr = gHookList.pNext;
+ ULONG lSize = sizeof(WireExtentArray) - 8;
+ ULONG lPiece = 0;
+ *cNumExtent = 0;
+
+ // Ask each hook.
+ while (pCurr != &gHookList)
+ {
+ pCurr->pHook->ServerGetSize( pCurr->uExtension, riid, S_OK, &lPiece );
+ if (lPiece != 0)
+ {
+ lPiece = ((lPiece + 7) & ~7) + sizeof(WireExtent);
+ lSize += lPiece;
+ *cNumExtent += 1;
+ }
+ pCurr = pCurr->pNext;
+ }
+
+ // Round up the number of extents and add size for an array of unique
+ // flags.
+ *cNumExtent = (*cNumExtent + 1) & ~1;
+ lSize += sizeof(DWORD) * *cNumExtent;
+ if (*cNumExtent != 0)
+ return lSize;
+ else
+ return 0;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CDebugChannelHook::ClientGetSize
+//
+// Synopsis: Asks the VC debugger how much data to put in the next
+// request on this thread. Stores the result in TLS.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(void) CDebugChannelHook::ClientGetSize( REFGUID uExtension, REFIID riid,
+ ULONG *pSize )
+{
+ COleTls tls;
+
+ Win4Assert( DEBUG_EXTENSION == uExtension );
+
+ if (DoDebuggerHooks)
+ tls->cDebugData = DebugORPCClientGetBufferSize( NULL,
+ riid, NULL, NULL, DebuggerArg, DoDebuggerHooks );
+ else
+ tls->cDebugData = 0;
+
+ *pSize = tls->cDebugData;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CDebugChannelHook::ClientFillBuffer
+//
+// Synopsis: Asks the VC debugger to place data in the buffer for
+// the next request on this thread. Uses the size stored
+// in TLS.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(void) CDebugChannelHook::ClientFillBuffer( REFGUID uExtension,
+ REFIID riid,
+ ULONG *pSize, void *pBuffer )
+{
+ COleTls tls;
+
+ Win4Assert( DEBUG_EXTENSION == uExtension );
+ Win4Assert( tls->cDebugData <= *pSize );
+
+ if (tls->cDebugData != 0)
+ DebugORPCClientFillBuffer(
+ tls->pCallInfo->pmessage,
+ riid,
+ NULL,
+ NULL,
+ pBuffer,
+ tls->cDebugData,
+ DebuggerArg,
+ DoDebuggerHooks );
+ *pSize = tls->cDebugData;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CDebugChannelHook::ClientNotify
+//
+// Synopsis: Passes data to the VC debugger received on the last
+// reply on this thread.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(void) CDebugChannelHook::ClientNotify(
+ REFGUID uExtension, REFIID riid,
+ ULONG lSize, void *pBuffer,
+ DWORD dwRep, HRESULT hr )
+{
+ COleTls tls;
+
+ Win4Assert( DEBUG_EXTENSION == uExtension );
+
+ if (pBuffer != NULL || DoDebuggerHooks)
+ DebugORPCClientNotify(
+ tls->pCallInfo->pmessage,
+ riid,
+ NULL,
+ NULL,
+ hr,
+ pBuffer,
+ lSize,
+ DebuggerArg,
+ DoDebuggerHooks );
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CDebugChannelHook::ServerNotify
+//
+// Synopsis: Passes data to the VC debugger receive on the last
+// request on this thread.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(void) CDebugChannelHook::ServerNotify(
+ REFGUID uExtension, REFIID riid,
+ ULONG lSize, void *pBuffer,
+ DWORD dwRep )
+{
+ COleTls tls;
+ IPIDEntry *pIpid;
+ void *pv = NULL;
+
+ Win4Assert( DEBUG_EXTENSION == uExtension );
+
+ if (pBuffer != NULL || DoDebuggerHooks)
+ {
+ // Lookup the IPID entry.
+ LOCK
+ pIpid = gIPIDTbl.LookupIPID( tls->pCallInfo->ipid );
+ UNLOCK
+ Win4Assert( pIpid != NULL );
+
+ // Get the object pointer from the stub because the IPID entry
+ // might have a different pointer.
+ ((IRpcStubBuffer *) pIpid->pStub)->DebugServerQueryInterface( &pv );
+
+ // Call the debugger.
+ DebugORPCServerNotify(
+ tls->pCallInfo->pmessage,
+ riid,
+ pIpid->pChnl,
+ pv,
+ NULL,
+ pBuffer,
+ lSize,
+ DebuggerArg,
+ DoDebuggerHooks );
+
+ // Release the object pointer.
+ if (pv != NULL)
+ ((IRpcStubBuffer *) pIpid->pStub)->DebugServerRelease( pv );
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CDebugChannelHook::ServerGetSize
+//
+// Synopsis: Asks the VC debugger how much data to place in the buffer
+// for the next reply on this thread. Stores the result
+// in TLS.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(void) CDebugChannelHook::ServerGetSize( REFGUID uExtension, REFIID riid,
+ HRESULT hrFault, ULONG *pSize )
+{
+ COleTls tls;
+ IPIDEntry *pIpid;
+ void *pv = NULL;
+
+ Win4Assert( DEBUG_EXTENSION == uExtension );
+
+ if (DoDebuggerHooks)
+ {
+ // Lookup the IPID entry.
+ LOCK
+ pIpid = gIPIDTbl.LookupIPID( tls->pCallInfo->ipid );
+ UNLOCK
+ Win4Assert( pIpid != NULL );
+
+ // Get the object pointer from the stub because the IPID entry
+ // might have a different pointer.
+ ((IRpcStubBuffer *) pIpid->pStub)->DebugServerQueryInterface( &pv );
+
+ // Ask the debugger how much data it has.
+ tls->cDebugData = DebugORPCServerGetBufferSize(
+ tls->pCallInfo->pmessage,
+ riid,
+ pIpid->pChnl,
+ pv,
+ NULL,
+ DebuggerArg,
+ DoDebuggerHooks );
+
+ // Release the object pointer.
+ if (pv != NULL)
+ ((IRpcStubBuffer *) pIpid->pStub)->DebugServerRelease( pv );
+ }
+ else
+ tls->cDebugData = 0;
+
+ *pSize = tls->cDebugData;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CDebugChannelHook::ServerFillBuffer
+//
+// Synopsis: Asks the VC debugger to place data in the buffer for the
+// next reply on this thread. Uses the size from TLS.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(void) CDebugChannelHook::ServerFillBuffer( REFGUID uExtension, REFIID riid,
+ ULONG *pSize, void *pBuffer, HRESULT hrFault )
+{
+ COleTls tls;
+ IPIDEntry *pIpid;
+ void *pv = NULL;
+
+ Win4Assert( DEBUG_EXTENSION == uExtension );
+ Win4Assert( tls->cDebugData <= *pSize );
+
+ if (tls->cDebugData != 0)
+ {
+ // Lookup the IPID entry.
+ LOCK
+ pIpid = gIPIDTbl.LookupIPID( tls->pCallInfo->ipid );
+ UNLOCK
+ Win4Assert( pIpid != NULL );
+
+ // Get the object pointer from the stub because the IPID entry
+ // might have a different pointer.
+ ((IRpcStubBuffer *) pIpid->pStub)->DebugServerQueryInterface( &pv );
+
+ // Ask the debugger to write its data.
+ DebugORPCServerFillBuffer(
+ tls->pCallInfo->pmessage,
+ riid,
+ pIpid->pChnl,
+ pv,
+ NULL,
+ pBuffer,
+ tls->cDebugData,
+ DebuggerArg,
+ DoDebuggerHooks );
+
+ // Release the object pointer.
+ if (pv != NULL)
+ ((IRpcStubBuffer *) pIpid->pStub)->DebugServerRelease( pv );
+ }
+
+ *pSize = tls->cDebugData;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CDebugChannelHook::QueryInterface
+//
+// Synopsis: Queries this object for interfaces
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CDebugChannelHook::QueryInterface( REFIID riid, LPVOID FAR* ppvObj)
+{
+ if (IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IChannelHook))
+ {
+ *ppvObj = this;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+
+ // This object is not reference counted.
+ // AddRef();
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CDebugChannelHook::AddRef
+//
+// Synopsis: Increments object reference count.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CDebugChannelHook::AddRef( )
+{
+ return 1;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CDebugChannelHook::Release
+//
+// Synopsis: Decrements object reference count and deletes if zero.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CDebugChannelHook::Release( )
+{
+ return 1;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CErrorChannelHook::ClientGetSize
+//
+// Synopsis: Does nothing.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(void) CErrorChannelHook::ClientGetSize( REFGUID uExtension, REFIID riid,
+ ULONG *pSize )
+{
+ Win4Assert( ERROR_EXTENSION == uExtension );
+
+ *pSize = 0;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CErrorChannelHook::ClientFillBuffer
+//
+// Synopsis: Does nothing.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(void) CErrorChannelHook::ClientFillBuffer( REFGUID uExtension,
+ REFIID riid,
+ ULONG *pSize, void *pBuffer )
+{
+ Win4Assert( ERROR_EXTENSION == uExtension );
+
+ *pSize = 0;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CErrorChannelHook::ClientNotify
+//
+// Synopsis: Unmarshals the COM extended error information.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(void) CErrorChannelHook::ClientNotify(
+ REFGUID uExtension, REFIID riid,
+ ULONG lSize, void *pBuffer,
+ DWORD dwRep, HRESULT hr )
+{
+ COleTls tls;
+
+ Win4Assert( ERROR_EXTENSION == uExtension );
+
+
+ //Unmarshal the new error object.
+ if ((pBuffer != NULL) && (lSize > 0))
+ {
+ CNdrStream MemStream((unsigned char *)pBuffer, lSize);
+
+ //Release the old error object.
+ if(tls->punkError != NULL)
+ {
+ tls->punkError->Release();
+ tls->punkError = NULL;
+ }
+
+ CoUnmarshalInterface(&MemStream,
+ IID_IUnknown,
+ (void **) &tls->punkError);
+ }
+ else if((tls->punkError != NULL) &&
+ !IsEqualIID(riid, IID_IRundown) &&
+ !IsEqualIID(riid, IID_IRemUnknown) &&
+ !IsEqualIID(riid, IID_ISupportErrorInfo))
+ {
+ //Release the old error object.
+ tls->punkError->Release();
+ tls->punkError = NULL;
+ }
+
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CErrorChannelHook::ServerNotify
+//
+// Synopsis: Clears the COM extended error information on an
+// incoming call.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(void) CErrorChannelHook::ServerNotify(
+ REFGUID uExtension, REFIID riid,
+ ULONG lSize, void *pBuffer,
+ DWORD dwRep )
+{
+ COleTls tls;
+
+ Win4Assert( ERROR_EXTENSION == uExtension );
+
+ //Release the old error object.
+ if(tls->punkError != NULL)
+ {
+ tls->punkError->Release();
+ tls->punkError = NULL;
+ }
+
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CErrorChannelHook::ServerGetSize
+//
+// Synopsis: Calculates the size of the marshalled error object.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(void) CErrorChannelHook::ServerGetSize( REFGUID uExtension, REFIID riid,
+ HRESULT hrFault, ULONG *pSize )
+{
+ HRESULT hr;
+ COleTls tls;
+
+ Win4Assert( ERROR_EXTENSION == uExtension );
+
+ tls->cbErrorData = 0;
+
+ //Compute the size of the marshalled error object.
+ if(tls->punkError != NULL)
+ {
+ hr = CoGetMarshalSizeMax( &tls->cbErrorData,
+ IID_IUnknown,
+ tls->punkError,
+ ((CChannelCallInfo *) tls->pCallInfo)->iDestCtx,
+ NULL,
+ MSHLFLAGS_NORMAL );
+ if(FAILED(hr))
+ {
+ //Release the error object.
+ tls->punkError->Release();
+ tls->punkError = NULL;
+ tls->cbErrorData = 0;
+ }
+ }
+
+ *pSize = tls->cbErrorData;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CErrorChannelHook::ServerFillBuffer
+//
+// Synopsis: Marshals the error object.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(void) CErrorChannelHook::ServerFillBuffer( REFGUID uExtension, REFIID riid,
+ ULONG *pSize, void *pBuffer, HRESULT hrFault )
+{
+ HRESULT hr;
+ COleTls tls;
+ ULONG cbSize = 0;
+
+ Win4Assert( ERROR_EXTENSION == uExtension );
+ Win4Assert( tls->cbErrorData <= *pSize );
+
+ if(tls->punkError != NULL)
+ {
+ //Marshal the error object.
+ if(tls->cbErrorData > 0)
+ {
+ CNdrStream MemStream((unsigned char *)pBuffer, tls->cbErrorData);
+
+ hr = CoMarshalInterface(&MemStream,
+ IID_IUnknown,
+ tls->punkError,
+ ((CChannelCallInfo *) tls->pCallInfo)->iDestCtx,
+ NULL,
+ MSHLFLAGS_NORMAL);
+
+ if(FAILED(hr))
+ {
+ tls->cbErrorData = 0;
+ }
+ }
+
+ //Release the error object.
+ tls->punkError->Release();
+ tls->punkError = NULL;
+ }
+
+ *pSize = tls->cbErrorData;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CErrorChannelHook::QueryInterface
+//
+// Synopsis: Queries this object for interfaces
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CErrorChannelHook::QueryInterface( REFIID riid, LPVOID FAR* ppvObj)
+{
+ if (IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IChannelHook))
+ {
+ *ppvObj = this;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+
+ // This object is not reference counted.
+ // AddRef();
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CErrorChannelHook::AddRef
+//
+// Synopsis: Increments object reference count.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CErrorChannelHook::AddRef( )
+{
+ return 1;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CErrorChannelHook::Release
+//
+// Synopsis: Decrements object reference count and deletes if zero.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CErrorChannelHook::Release( )
+{
+ return 1;
+}
+
diff --git a/private/ole32/com/dcomrem/chock.hxx b/private/ole32/com/dcomrem/chock.hxx
new file mode 100644
index 000000000..e8c0fd5a7
--- /dev/null
+++ b/private/ole32/com/dcomrem/chock.hxx
@@ -0,0 +1,173 @@
+//+-------------------------------------------------------------------
+//
+// File: chock.hxx
+//
+// Contents: APIs for channel hooks
+//
+//--------------------------------------------------------------------
+#ifndef _CHOCK_HXX_
+#define _CHOCK_HXX_
+
+/***************************************************************************/
+const DWORD MASK_A_C_ = 0xFF00FF00;
+const DWORD MASK__B_D = 0x00FF00FF;
+const DWORD MASK_AB__ = 0xFFFF0000;
+const DWORD MASK___CD = 0x0000FFFF;
+
+inline void ByteSwapLong( DWORD &l )
+{
+ // Start with ABCD.
+ // First change it to BADC.
+ l = ((l & MASK_A_C_) >> 8) | ((l & MASK__B_D) << 8);
+
+ // Then change it to DCBA.
+ l = ((l & MASK_AB__) >> 16) | ((l & MASK___CD) << 16);
+}
+
+/***************************************************************************/
+inline void ByteSwapShort( unsigned short &s )
+{
+ s = ((s & 0x00FF) << 8) | ((s & 0xFF00) >> 8);
+}
+
+/***************************************************************************/
+typedef struct
+{
+ unsigned long rounded_size; // Actual number of extents.
+ uuid_t id; // Extension identifier.
+ unsigned long size; // Extension size.
+
+ // byte data[]; // Extension data.
+} WireExtent;
+
+
+// Array of extensions.
+typedef struct
+{
+ unsigned long size; // Number of extents.
+ unsigned long reserved; // Must be zero.
+ unsigned long unique; // Flag to indicate presence of unique_flag array.
+ unsigned long rounded_size; // Actual number of extents.
+
+ unsigned long unique_flag[2]; // Flags to indicate presense of ORPC_EXTENTs
+} WireExtentArray;
+
+// These two structures are laid out to match the NDR wire represenation
+// of the type ORPCTHIS in obase.idl.
+typedef struct
+{
+ COMVERSION version; // COM version number
+ unsigned long flags; // ORPCF flags for presence of other data
+ unsigned long reserved1; // set to zero
+ CID cid; // causality id of caller
+ unsigned long unique; // tag to indicate presence of extensions
+} WireThisPart1;
+
+typedef struct
+{
+ WireThisPart1 part1;
+
+ // Debug data.
+ WireExtentArray ea;
+ WireExtent e;
+} WireThisPart2;
+
+typedef union
+{
+ WireThisPart1 c;
+ WireThisPart2 d;
+} WireThis;
+
+// These two structures are laid out to match the NDR wire represenation
+// of the type ORPCTHAT in obase.idl.
+typedef struct
+{
+ unsigned long flags; // ORPCF flags for presence of other data
+ unsigned long unique; // tag to indicate presence of extensions
+} WireThatPart1;
+
+typedef struct
+{
+ WireThatPart1 part1;
+
+ // Debug data.
+ WireExtentArray ea;
+ WireExtent e;
+} WireThatPart2;
+
+typedef union
+{
+ WireThatPart1 c;
+ WireThatPart2 d;
+} WireThat;
+
+
+//+----------------------------------------------------------------
+//
+// Class: CDebugChannelHook, private
+//
+// Purpose: Translates channel hook calls to special calls the VC
+// debugger expects.
+//
+//-----------------------------------------------------------------
+
+class CDebugChannelHook : public IChannelHook
+{
+ public:
+ STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) ( void );
+ STDMETHOD_(ULONG,Release) ( void );
+
+ STDMETHOD_(void,ClientGetSize) ( REFGUID, REFIID, ULONG *DataSize );
+ STDMETHOD_(void,ClientFillBuffer)( REFGUID, REFIID, ULONG *DataSize, void *DataBuffer );
+ STDMETHOD_(void,ClientNotify) ( REFGUID, REFIID, ULONG DataSize, void *DataBuffer,
+ DWORD DataRep, HRESULT hrFault );
+ STDMETHOD_(void,ServerNotify) ( REFGUID, REFIID, ULONG DataSize, void *DataBuffer,
+ DWORD DataRep );
+ STDMETHOD_(void,ServerGetSize) ( REFGUID, REFIID, HRESULT hrFault,
+ ULONG *DataSize );
+ STDMETHOD_(void,ServerFillBuffer)( REFGUID, REFIID, ULONG *DataSize, void *DataBuffer,
+ HRESULT hrFault );
+};
+
+
+//+----------------------------------------------------------------
+//
+// Class: CErrorChannelHook, private
+//
+// Purpose: Channel hook for marshalling COM extended error
+// information.
+//
+//-----------------------------------------------------------------
+class CErrorChannelHook : public IChannelHook
+{
+ public:
+ STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) ( void );
+ STDMETHOD_(ULONG,Release) ( void );
+
+ STDMETHOD_(void,ClientGetSize) ( REFGUID, REFIID, ULONG *DataSize );
+ STDMETHOD_(void,ClientFillBuffer)( REFGUID, REFIID, ULONG *DataSize, void *DataBuffer );
+ STDMETHOD_(void,ClientNotify) ( REFGUID, REFIID, ULONG DataSize, void *DataBuffer,
+ DWORD DataRep, HRESULT hrFault );
+ STDMETHOD_(void,ServerNotify) ( REFGUID, REFIID, ULONG DataSize, void *DataBuffer,
+ DWORD DataRep );
+ STDMETHOD_(void,ServerGetSize) ( REFGUID, REFIID, HRESULT hrFault,
+ ULONG *DataSize );
+ STDMETHOD_(void,ServerFillBuffer)( REFGUID, REFIID, ULONG *DataSize, void *DataBuffer,
+ HRESULT hrFault );
+};
+
+/***************************************************************************/
+// Functions called by channel.
+void CleanupChannelHooks();
+ULONG ClientGetSize( REFIID riid, ULONG *cNumExtent );
+HRESULT ClientNotify ( REFIID riid, WireThat *, ULONG cMax, void **pStubData,
+ DWORD DataRep, HRESULT hr );
+void *FillBuffer ( REFIID riid, WireExtentArray *, ULONG cMaxSize,
+ ULONG cNumExtent, BOOL fClient );
+ULONG ServerGetSize( REFIID riid, ULONG *cNumExtent );
+HRESULT ServerNotify ( REFIID riid, WireThis *, ULONG cMax, void **pStubData,
+ DWORD DataRep );
+
+#endif // _CHOCK_HXX_
diff --git a/private/ole32/com/dcomrem/coapi.cxx b/private/ole32/com/dcomrem/coapi.cxx
new file mode 100644
index 000000000..681a99c12
--- /dev/null
+++ b/private/ole32/com/dcomrem/coapi.cxx
@@ -0,0 +1,773 @@
+//+-------------------------------------------------------------------
+//
+// File: coapi.cxx
+//
+// Contents: Public COM remote subsystem APIs
+//
+// Functions: CoGetStandardMarshal - returns IMarshal for given interface
+// CoGetMarshalSizeMax - returns max size buffer needed
+// CoMarshalInterface - marshals an interface
+// CoUnmarshalInterface - unmarshals an interface
+// CoReleaseMarshalData - releases data from marshaled interface
+// CoLockObjectExternal - keep object alive or releases it
+// CoDisconnectObject - kills sessions held by remote clients
+// CoIsHandlerConnected - try to determine if handler connected
+//
+// History: 23-Nov-92 Rickhi Created
+// 11-Dec-93 CraigWi Switched to identity object
+// 05-Jul-94 BruceMa Check for end of stream
+// 20-Feb-95 Rickhi Major changes for DCOM
+//
+//--------------------------------------------------------------------
+#include <ole2int.h>
+#include <olerem.h>
+#include <marshal.hxx> // CStdMarshal
+#include <stdid.hxx> // CStdIdentity, IDTable APIs
+#include <service.hxx> // SASIZE
+
+
+// static unmarshaler
+IMarshal *gpStdMarshal = NULL;
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CoGetStandardMarshal, public
+//
+// Synopsis: Returns an instance of the standard IMarshal for the
+// specifed object.
+//
+// Algorithm: lookup or create a CStdIdentity (and CStdMarshal) for
+// the object.
+//
+// History: 23-Nov-92 Rickhi Created
+// 11-Dec-93 CraigWi Switched to identity object
+// 20-Feb-95 Rickhi Switched to CStdMarshal
+//
+//--------------------------------------------------------------------
+STDAPI CoGetStandardMarshal(REFIID riid, IUnknown *pUnk, DWORD dwDestCtx,
+ void *pvDestCtx, DWORD mshlflags, IMarshal **ppMarshal)
+{
+ TRACECALL(TRACE_MARSHAL, "CoGetStandardMarshal");
+ ComDebOut((DEB_MARSHAL,
+ "CoGetStandardMarshal riid:%I pUnk:%x dwDest:%x pvDest:%x flags:%x\n",
+ &riid, pUnk, dwDestCtx, pvDestCtx, mshlflags));
+
+ // validate the input parameters
+ if (ppMarshal == NULL ||
+ dwDestCtx > MSHCTX_INPROC || pvDestCtx != NULL ||
+ (mshlflags & ~MSHLFLAGS_ALL))
+ {
+ return E_INVALIDARG;
+ }
+
+ *ppMarshal = NULL;
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (FAILED(hr))
+ return hr;
+
+ if (pUnk == NULL)
+ {
+ // this is the unmarshal side. any instance will do so we return
+ // the static one. Calling UnmarshalInterface will return the real
+ // proxy.
+
+ hr = GetStaticUnMarshaler(ppMarshal);
+ }
+ else
+ {
+ // this is the marshal side. We put a strong reference on the StdId
+ // so that the ID does not get disconnected when the last external
+ // Release occurs.
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,riid,&pUnk);
+
+ DWORD dwFlags = IDLF_CREATE | IDLF_STRONG;
+ if (mshlflags & MSHLFLAGS_NOPING)
+ {
+ // requesting NOPING, so set the IDL flags accordingly
+ dwFlags |= IDLF_NOPING;
+ }
+
+ CStdIdentity *pStdId;
+ hr = LookupIDFromUnk(pUnk, dwFlags, &pStdId);
+ *ppMarshal = (IMarshal *)pStdId;
+ }
+
+ ComDebOut((DEB_MARSHAL, "CoGetStandardMarshal: pIM:%x hr:%x\n",
+ *ppMarshal, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoGetMarshalSizeMax, public
+//
+// synopsis: returns max size needed to marshal the specified interface.
+//
+// History: 23-Nov-92 Rickhi Created
+// 11-Dec-93 CraigWi Switched to static marshaler
+// 20-Feb-95 Rickhi Return correct sizes once again.
+//
+//--------------------------------------------------------------------
+STDAPI CoGetMarshalSizeMax(ULONG *pulSize, REFIID riid, IUnknown *pUnk,
+ DWORD dwDestCtx, void *pvDestCtx, DWORD mshlflags)
+{
+ TRACECALL(TRACE_MARSHAL, "CoGetMarshalSizeMax");
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,riid,&pUnk);
+ ComDebOut((DEB_MARSHAL,
+ "CoGetMarshalSizeMax: riid:%I pUnk:%x dwDest:%x pvDest:%x flags:%x\n",
+ &riid, pUnk, dwDestCtx, pvDestCtx, mshlflags));
+
+ // validate the input parameters
+ if (pulSize == NULL || pUnk == NULL ||
+ dwDestCtx > MSHCTX_INPROC || pvDestCtx != NULL ||
+ (mshlflags & ~MSHLFLAGS_ALL))
+ {
+ return E_INVALIDARG;
+ }
+
+ *pulSize = 0;
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (FAILED(hr))
+ return hr;
+
+ IMarshal *pIM;
+ hr = pUnk->QueryInterface(IID_IMarshal, (void **)&pIM);
+
+ if (SUCCEEDED(hr))
+ {
+ // object supports custom marshalling, ask it how much space it needs
+ hr = pIM->GetMarshalSizeMax(riid, (void *)pUnk, dwDestCtx,
+ pvDestCtx, mshlflags, pulSize);
+ pIM->Release();
+
+ // add in the size of the stuff CoMarshalInterface will write
+ *pulSize += sizeof(OBJREF);
+ }
+ else
+ {
+ // uses standard marshalling, we know the max size already.
+ *pulSize = sizeof(OBJREF) + SASIZE(gpsaLocalResolver->wNumEntries);
+ hr = S_OK;
+ }
+
+ ComDebOut((DEB_MARSHAL, "CoGetMarshalSizeMax: pUnk:%x size:%x hr:%x\n",
+ pUnk, *pulSize, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoMarshalInterface, public
+//
+// Synopsis: marshals the specified interface into the given stream
+//
+// History: 23-Nov-92 Rickhi Created
+// 11-Dec-93 CraigWi Switched to identity object and
+// new marshaling format
+// 20-Feb-95 Rickhi switched to newer marshal format
+//
+//--------------------------------------------------------------------
+STDAPI CoMarshalInterface(IStream *pStm, REFIID riid, IUnknown *pUnk,
+ DWORD dwDestCtx, void *pvDestCtx, DWORD mshlflags)
+{
+ TRACECALL(TRACE_MARSHAL, "CoMarshalInterface");
+ ComDebOut((DEB_MARSHAL,
+ "CoMarshalInterface: pStm:%x riid:%I pUnk:%x dwDest:%x pvDest:%x flags:%x\n",
+ pStm, &riid, pUnk, dwDestCtx, pvDestCtx, mshlflags));
+
+ // validate the input parameters
+ if (pStm == NULL || pUnk == NULL ||
+ dwDestCtx > MSHCTX_INPROC || pvDestCtx != NULL ||
+ (mshlflags & ~MSHLFLAGS_ALL))
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (FAILED(hr))
+ return hr;
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,riid,(IUnknown **)&pUnk);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pStm);
+
+
+ // determine whether to do custom or standard marshaling
+ IMarshal *pIM;
+ hr = pUnk->QueryInterface(IID_IMarshal, (void **)&pIM);
+
+ if (SUCCEEDED(hr))
+ {
+ // object supports custom marshaling, use it. we package the
+ // custom data inside an OBJREF.
+ Win4Assert(pIM);
+
+ OBJREF objref;
+ objref.signature = OBJREF_SIGNATURE;
+ objref.flags = OBJREF_CUSTOM;
+ objref.iid = riid;
+
+ // get the clsid for unmarshaling
+ hr = pIM->GetUnmarshalClass(riid, pUnk, dwDestCtx, pvDestCtx,
+ mshlflags, &ORCST(objref).clsid);
+
+ if (SUCCEEDED(hr) &&
+ !IsEqualCLSID(CLSID_StdMarshal, ORCST(objref).clsid))
+ {
+ // get the size of data to marshal
+ hr = pIM->GetMarshalSizeMax(riid, (void *)pUnk, dwDestCtx,
+ pvDestCtx, mshlflags,
+ &ORCST(objref).size);
+
+ // currently we dont write any extensions into the custom
+ // objref. The provision is there so we can do it in the
+ // future, for example, if the unmarshaler does not have the
+ // unmarshal class code available we could to provide a callback
+ // mechanism by putting the OXID, and saResAddr in there.
+ ORCST(objref).cbExtension = 0;
+
+ // write the objref header info into the stream
+ ULONG cbToWrite = (BYTE *)(&ORCST(objref).pData) - (BYTE *)&objref;
+ hr = pStm->Write(&objref, cbToWrite, NULL);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // tell the marshaler to write the rest of the data
+ hr = pIM->MarshalInterface(pStm, riid, pUnk, dwDestCtx,
+ pvDestCtx, mshlflags);
+ }
+
+ pIM->Release();
+ }
+ else
+ {
+ // use standard marshaling - find or create a standard marshaler
+ // note this may include handler marshaling.
+
+ // HACKALERT:
+ // Figure out what flags to pass. If marshaling TABLEWEAK, don't
+ // add then remove a strong connection, since many objects have a
+ // bogus implementation of IExternalConnection that shuts down the
+ // object when the last strong count goes to zero regardless of the
+ // fLastReleaseCloses flag.
+
+ DWORD dwFlags = IDLF_CREATE;
+ if (!(mshlflags & MSHLFLAGS_TABLEWEAK))
+ {
+ dwFlags |= IDLF_STRONG;
+ }
+
+ CStdIdentity *pStdId;
+ hr = LookupIDFromUnk(pUnk, dwFlags, &pStdId);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pStdId->MarshalInterface(pStm, riid, pUnk, dwDestCtx,
+ pvDestCtx, mshlflags);
+
+ if (!(mshlflags & MSHLFLAGS_TABLEWEAK))
+ {
+ // If marshaling succeeded, removing the last strong connection
+ // should keep the object alive. If marshaling failed,
+ // removing the last strong connection should shut it down.
+
+ BOOL fKeepAlive = (SUCCEEDED(hr)) ? TRUE : FALSE;
+ pStdId->DecStrongCnt(fKeepAlive);
+ }
+ else
+ {
+ pStdId->Release();
+ }
+ }
+ }
+
+ ComDebOut((DEB_MARSHAL,"CoMarshalInterface: pUnk:%x hr:%x\n",pUnk,hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoUnmarshalInterface, public
+//
+// Synopsis: Unmarshals a marshaled interface pointer from the stream.
+//
+// Notes: when a controlling unknown is supplied, it is assumed that
+// the HANDLER for the class has done a CreateInstance and wants
+// to aggregate just the proxymanager, ie. we dont want to
+// instantiate a new class handler (the default unmarshalling
+// behaviour).
+//
+// History: 23-Nov-92 Rickhi Created
+// 11-Dec-93 CraigWi Switched to static marshaler and
+// new marshaling format
+// 20-Feb-95 Rickhi switched to newer marshal format
+//
+//--------------------------------------------------------------------
+STDAPI CoUnmarshalInterface(IStream *pStm,
+ REFIID riid,
+ void **ppv)
+{
+ TRACECALL(TRACE_MARSHAL, "CoUnmarshalInterface");
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pStm);
+ ComDebOut((DEB_MARSHAL,
+ "CoUnmarshalInterface: pStm:%x riid:%I\n", pStm, &riid));
+
+ // validate the input parameters
+ if (pStm == NULL || ppv == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ *ppv = NULL;
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (FAILED(hr))
+ return hr;
+
+ // read the objref from the stream.
+ OBJREF objref;
+ hr = ReadObjRef(pStm, objref);
+
+ if (SUCCEEDED(hr))
+ {
+ if (objref.flags & OBJREF_CUSTOM)
+ {
+ // uses custom marshaling, create an instance and ask that guy
+ // to do the unmarshaling. special case createinstance for the
+ // freethreaded marshaler.
+
+ IMarshal *pIM;
+
+ if (IsEqualCLSID(CLSID_InProcFreeMarshaler, ORCST(objref).clsid))
+ {
+ hr = GetInProcFreeMarshaler(&pIM);
+ }
+ else
+ {
+ hr = CoCreateInstance(ORCST(objref).clsid, NULL, CLSCTX_INPROC,
+ IID_IMarshal, (void **)&pIM);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pIM->UnmarshalInterface(pStm, objref.iid, ppv);
+ pIM->Release();
+ }
+ else
+ {
+ // seek past the custom marshalers data so we leave the
+ // stream at the correct position.
+
+ LARGE_INTEGER libMove;
+ libMove.LowPart = ORCST(objref).size;
+ libMove.HighPart = 0;
+ pStm->Seek(libMove, STREAM_SEEK_CUR, NULL);
+ }
+ }
+ else
+ {
+ // uses standard marshaling, call API to find or create the
+ // instance of CStdMarshal for the oid inside the objref, and
+ // ask that instance to unmarshal the interface. This covers
+ // handler unmarshaling also.
+
+ hr = UnmarshalObjRef(objref, ppv);
+ }
+
+ // free the objref we read above
+ FreeObjRef(objref);
+
+ if (!InlineIsEqualGUID(riid, GUID_NULL) &&
+ !InlineIsEqualGUID(riid, objref.iid) && SUCCEEDED(hr))
+ {
+ // the interface iid requested was different than the one that
+ // was marshaled (and was not GUID_NULL), so go get the requested
+ // one and release the marshaled one. GUID_NULL is used by the Ndr
+ // unmarshaling engine and means return whatever interface was
+ // marshaled.
+
+ IUnknown *pUnk = (IUnknown *)*ppv;
+
+#ifdef WX86OLE
+ if (gcwx86.IsN2XProxy(pUnk))
+ {
+ // Tell wx86 thunk layer to thunk as IUnknown
+ gcwx86.SetStubInvokeFlag((BOOL)1);
+ }
+#endif
+
+ hr = pUnk->QueryInterface(riid, ppv);
+ pUnk->Release();
+ }
+ }
+
+ ComDebOut((DEB_MARSHAL, "CoUnmarshalInterface: pUnk:%x hr:%x\n",
+ *ppv, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoReleaseMarshalData, public
+//
+// Synopsis: release the reference created by CoMarshalInterface
+//
+// Algorithm:
+//
+// History: 23-Nov-92 Rickhi
+// 11-Dec-93 CraigWi Switched to static marshaler and
+// new marshaling format
+// 20-Feb-95 Rickhi switched to newer marshal format
+//
+//--------------------------------------------------------------------
+STDAPI CoReleaseMarshalData(IStream *pStm)
+{
+ TRACECALL(TRACE_MARSHAL, "CoReleaseMarshalData");
+ ComDebOut((DEB_MARSHAL, "CoReleaseMarshalData pStm:%x\n", pStm));
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **) &pStm);
+
+ // validate the input parameters
+ if (pStm == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (FAILED(hr))
+ return hr;
+
+ // read the objref from the stream.
+ OBJREF objref;
+ hr = ReadObjRef(pStm, objref);
+
+ if (SUCCEEDED(hr))
+ {
+ if (objref.flags & OBJREF_CUSTOM)
+ {
+ // object uses custom marshaling. create an instance of
+ // the unmarshaling code and ask it to release the marshaled
+ // data.
+
+ IMarshal *pIM;
+
+ if (IsEqualCLSID(CLSID_InProcFreeMarshaler, ORCST(objref).clsid))
+ {
+ hr = GetInProcFreeMarshaler(&pIM);
+ }
+ else
+ {
+ hr = CoCreateInstance(ORCST(objref).clsid, NULL, CLSCTX_INPROC,
+ IID_IMarshal, (void **)&pIM);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pIM->ReleaseMarshalData(pStm);
+ pIM->Release();
+ }
+ else
+ {
+ // seek past the custom marshalers data so we leave the
+ // stream at the correct position.
+
+ LARGE_INTEGER libMove;
+ libMove.LowPart = ORCST(objref).size;
+ libMove.HighPart = 0;
+ pStm->Seek(libMove, STREAM_SEEK_CUR, NULL);
+ }
+ }
+ else
+ {
+ // uses standard marshaling, find or create the instance of
+ // CStdMarshal for the oid inside the objref, and ask that
+ // instance to unmarshal the interface.
+
+ CStdMarshal *pStdMshl;
+ hr = FindStdMarshal(objref, &pStdMshl);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pStdMshl->ReleaseMarshalObjRef(objref);
+ pStdMshl->Release();
+ }
+ else if (hr == CO_E_OBJNOTCONNECTED)
+ {
+ // it was for this process but the object is already dead
+ hr = S_OK;
+ }
+ }
+
+ // free the objref we read above
+ FreeObjRef(objref);
+ }
+
+ ComDebOut((DEB_MARSHAL, "CoReleaseMarshalData hr:%x\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoDisconnectObject, public
+//
+// synopsis: disconnects all clients of an object by marking their
+// connections as terminted abnormaly.
+//
+// History: 04-Oct-93 Rickhi Created
+// 11-Dec-93 CraigWi Switched to identity object
+//
+//--------------------------------------------------------------------
+STDAPI CoDisconnectObject(IUnknown *pUnk, DWORD dwReserved)
+{
+ TRACECALL(TRACE_MARSHAL, "CoDisconnectObject");
+ ComDebOut((DEB_MARSHAL, "CoDisconnectObject pUnk:%x dwRes:%x\n",
+ pUnk, dwReserved));
+
+ // validate the input parameters
+ if (pUnk == NULL || dwReserved != 0)
+ {
+ return E_INVALIDARG;
+ }
+
+ if (!IsValidInterface(pUnk))
+ return E_INVALIDARG;
+
+ if (!IsApartmentInitialized())
+ {
+ return CO_E_NOTINITIALIZED;
+ }
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,&pUnk);
+
+ IMarshal *pIM = NULL;
+ HRESULT hr = pUnk->QueryInterface(IID_IMarshal, (void **)&pIM);
+
+ if (FAILED(hr))
+ {
+ // object does not support IMarshal directly. Find its standard
+ // marshaler if there is one, otherwise return an error.
+
+ CStdIdentity *pStdId;
+ hr = LookupIDFromUnk(pUnk, 0, &pStdId);
+ pIM = (IMarshal *)pStdId;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pIM->DisconnectObject(dwReserved);
+ pIM->Release();
+ }
+ else
+ {
+ // could not get std marshal, must be disconnected already
+ return S_OK;
+ }
+
+ ComDebOut((DEB_MARSHAL,"CoDisconnectObject pIM:%x hr:%x\n", pIM, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoLockObjectExternal, public
+//
+// synopsis: adds/revokes a strong reference count to/from the
+// identity for the given object.
+//
+// parameters: [punkObject] - IUnknown of the object
+// [fLock] - lock/unlock the object
+// [fLastUR] - last unlock releases.
+//
+// History: 23-Nov-92 Rickhi Created
+// 11-Dec-93 CraigWi Switched to identity object
+//
+//--------------------------------------------------------------------
+STDAPI CoLockObjectExternal(IUnknown *pUnk, BOOL fLock, BOOL fLastUR)
+{
+ TRACECALL(TRACE_MARSHAL, "CoLockObjectExternal");
+ ComDebOut((DEB_MARSHAL,
+ "CoLockObjectExternal pUnk:%x fLock:%x fLastUR:%x\n", pUnk, fLock, fLastUR));
+
+ if (!IsValidInterface(pUnk))
+ return E_INVALIDARG;
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&pUnk);
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (FAILED(hr))
+ return hr;
+
+ CStdIdentity *pStdID;
+ hr = LookupIDFromUnk(pUnk, (fLock) ? IDLF_CREATE : 0, &pStdID);
+
+ switch (hr)
+ {
+ case S_OK:
+
+ // REF COUNTING: inc or dec external ref count
+ hr = pStdID->LockObjectExternal(fLock, fLastUR);
+ pStdID->Release();
+ break;
+
+ case CO_E_OBJNOTREG:
+ // unlock when not registered; 16bit code returned NOERROR;
+ // disconnected handler goes to S_OK case above.
+ hr = S_OK;
+ break;
+
+ case E_OUTOFMEMORY:
+ break;
+
+ default:
+ hr = E_UNEXPECTED;
+ break;
+ }
+
+ ComDebOut((DEB_MARSHAL,
+ "CoLockObjectExternal pStdID:%x hr:%x\n", pStdID, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoIsHandlerConnected, public
+//
+// Synopsis: Returns whether or not handler is connected to remote
+//
+// Algorithm: QueryInterface to IProxyManager. If this is supported,
+// then this is a handler. We ask the handler
+// for its opinion otherwise we simply return TRUE.
+//
+// History: 04-Oct-93 Rickhi Created
+//
+// Notes: The answer of this routine may be wrong by the time
+// the routine returns. This is correct behavior as
+// this routine is primilary to cleanup state associated
+// with connections.
+//
+//--------------------------------------------------------------------
+STDAPI_(BOOL) CoIsHandlerConnected(LPUNKNOWN pUnk)
+{
+ // validate input parameters
+ if (!IsValidInterface(pUnk))
+ return FALSE;
+
+ // Assume it is connected
+ BOOL fResult = TRUE;
+
+ // Handler should support IProxyManager
+ IProxyManager *pPM;
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&pUnk);
+ if (SUCCEEDED(pUnk->QueryInterface(IID_IProxyManager, (void **)&pPM)))
+ {
+ // We have something that thinks its is an Ole handler so we ask
+ fResult = pPM->IsConnected();
+ pPM->Release();
+ }
+
+ return fResult;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: GetStaticUnMarshaler, private
+//
+// Synopsis: Returns the static instance of the CStdMarshal.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+// Notes: The standard marshaler must be able to resolve identity, that
+// is two proxies for the same object must never be created in
+// the same apartment. Given that, it makes sense to let the
+// standard guy do the unmarshaling. Since we dont know the
+// identity of the object upfront, and any instance will do, we
+// use a static instance to handle unmarshal.
+//
+//--------------------------------------------------------------------
+INTERNAL GetStaticUnMarshaler(IMarshal **ppIM)
+{
+ HRESULT hr = S_OK;
+
+ LOCK
+ if (gpStdMarshal == NULL)
+ {
+ // the global instance has not been created yet, so go make it now.
+ hr = CreateIdentityHandler(NULL, 0, IID_IMarshal,
+ (void **)&gpStdMarshal);
+ if (SUCCEEDED(hr))
+ {
+ // dont let anybody but us delete this thing.
+ ((CStdIdentity *)gpStdMarshal)->SetLockedInMemory();
+ hr = S_OK;
+ }
+ }
+
+ *ppIM = gpStdMarshal;
+ if (gpStdMarshal)
+ {
+ gpStdMarshal->AddRef();
+ }
+ UNLOCK;
+ return hr;
+}
+
+#ifdef WX86OLE
+//+-------------------------------------------------------------------
+//
+// Function: CoGetIIDFromMarshaledInterface, public
+//
+// Synopsis: Returns the IID embedded inside a marshaled interface
+// pointer. Needed by the x86 thunking code.
+//
+// History: 16-Apr-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+STDAPI CoGetIIDFromMarshaledInterface(IStream *pStm, IID *piid)
+{
+ ULARGE_INTEGER ulSeekEnd;
+ LARGE_INTEGER lSeekStart, lSeekEnd;
+ LISet32(lSeekStart, 0);
+
+ // remember the current position
+ HRESULT hr = pStm->Seek(lSeekStart, STREAM_SEEK_CUR, &ulSeekEnd);
+
+ if (SUCCEEDED(hr))
+ {
+ // read the first part of the objref which contains the IID
+ // also check to ensure the objref is at least partially sane
+
+ OBJREF objref;
+ hr = StRead(pStm, &objref, 2*sizeof(ULONG) + sizeof(IID));
+
+ if (SUCCEEDED(hr))
+ {
+ if ((objref.signature != OBJREF_SIGNATURE) ||
+ (objref.flags & OBJREF_RSRVD_MBZ) ||
+ (objref.flags == 0))
+ {
+ // the objref signature is bad, or one of the reserved
+ // bits in the flags is set, or none of the required bits
+ // in the flags is set. the objref cant be interpreted so
+ // fail the call.
+
+ Win4Assert(!"Invalid Objref Flags");
+ return RPC_E_INVALID_OBJREF;
+ }
+
+ // extract the IID
+ *piid = objref.iid;
+ }
+
+ // put the seek pointer back to the original location
+ lSeekEnd.LowPart = ulSeekEnd.LowPart;
+ lSeekEnd.HighPart = (LONG)ulSeekEnd.HighPart;
+ hr = pStm->Seek(lSeekEnd, STREAM_SEEK_SET, NULL);
+ }
+
+ return hr;
+}
+#endif
diff --git a/private/ole32/com/dcomrem/daytona/makefile b/private/ole32/com/dcomrem/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/dcomrem/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/dcomrem/daytona/sources b/private/ole32/com/dcomrem/daytona/sources
new file mode 100644
index 000000000..4ac4f5b09
--- /dev/null
+++ b/private/ole32/com/dcomrem/daytona/sources
@@ -0,0 +1,87 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= remote
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES = ..\..\..\common\daytona;..\..\..\ih;..;..\..\inc;
+INCLUDES = $(INCLUDES);..\..\dcomidl\daytona;..\..\class;..\..\objact;
+INCLUDES = $(INCLUDES);$(BASEDIR)\private\dcomidl\obj
+
+
+C_DEFINES= \
+ $(C_DEFINES) -DMSWMSG
+
+SOURCES= \
+ ..\callctrl.cxx \
+ ..\chancont.cxx \
+ ..\channelb.cxx \
+ ..\chock.cxx \
+ ..\coapi.cxx \
+ ..\hash.cxx \
+ ..\idtable.cxx \
+ ..\ipidtbl.cxx \
+ ..\ipmrshl.cxx \
+ ..\locks.cxx \
+ ..\marshal.cxx \
+ ..\orpc_dbg.c \
+ ..\pgalloc.cxx \
+ ..\remoteu.cxx \
+ ..\resolver.cxx \
+ ..\riftbl.cxx \
+ ..\security.cxx \
+ ..\service.cxx \
+ ..\stdid.cxx \
+ ..\stream.cxx \
+ ..\threads.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
diff --git a/private/ole32/com/dcomrem/dirs b/private/ole32/com/dcomrem/dirs
new file mode 100644
index 000000000..80cd267ad
--- /dev/null
+++ b/private/ole32/com/dcomrem/dirs
@@ -0,0 +1,37 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ daytona \
+
diff --git a/private/ole32/com/dcomrem/filelist.mk b/private/ole32/com/dcomrem/filelist.mk
new file mode 100644
index 000000000..c69313e63
--- /dev/null
+++ b/private/ole32/com/dcomrem/filelist.mk
@@ -0,0 +1,58 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = remote.lib
+
+RELEASE =
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES = \
+ .\channelb.cxx \
+ .\chancont.cxx \
+ .\callcont.cxx \
+ .\callmain.cxx \
+ .\imchnl.cxx \
+ .\sichnl.cxx \
+ .\service.cxx \
+ .\endpnt.cxx \
+ .\remhdlr.cxx \
+ .\remapi.cxx \
+ .\coapi.cxx \
+ .\dd.cxx \
+ .\stdid.cxx \
+ .\idtable.cxx
+
+CFILES = .\orpc_dbg.c
+
+#
+# Libraries and other object files to link.
+#
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PXXFILE = headers.cxx
+PFILE =
+
+CINC = $(CINC) -I..\inc -I..\idl -I..\class -I..\objact $(TRACELOG)
+
+MTHREAD = 1
+
+MULTIDEPEND = MERGED
diff --git a/private/ole32/com/dcomrem/hash.cxx b/private/ole32/com/dcomrem/hash.cxx
new file mode 100644
index 000000000..ec4c519dd
--- /dev/null
+++ b/private/ole32/com/dcomrem/hash.cxx
@@ -0,0 +1,432 @@
+//+--------------------------------------------------------------------------
+//
+// File: hash.cxx
+//
+// Contents: class for maintaining a hash table.
+//
+// Classes: CUUIDHashTable
+//
+//---------------------------------------------------------------------------
+#include <ole2int.h>
+#include <hash.hxx> // CUUIDHashTable
+#include <locks.hxx> // ASSERT_LOCK_HELD
+#include <service.hxx> // SASIZE
+
+
+//+------------------------------------------------------------------------
+// Type definitions
+
+typedef struct
+{
+ const IPID *pIpid;
+ SECURITYBINDING *pName;
+} SNameKey;
+
+//+------------------------------------------------------------------------
+//
+// Secure references hash table buckets. This is defined as a global
+// so that we dont have to run any code to initialize the hash table.
+//
+//+------------------------------------------------------------------------
+SHashChain SRFBuckets[23] =
+{
+ {&SRFBuckets[0], &SRFBuckets[0]},
+ {&SRFBuckets[1], &SRFBuckets[1]},
+ {&SRFBuckets[2], &SRFBuckets[2]},
+ {&SRFBuckets[3], &SRFBuckets[3]},
+ {&SRFBuckets[4], &SRFBuckets[4]},
+ {&SRFBuckets[5], &SRFBuckets[5]},
+ {&SRFBuckets[6], &SRFBuckets[6]},
+ {&SRFBuckets[7], &SRFBuckets[7]},
+ {&SRFBuckets[8], &SRFBuckets[8]},
+ {&SRFBuckets[9], &SRFBuckets[9]},
+ {&SRFBuckets[10], &SRFBuckets[10]},
+ {&SRFBuckets[11], &SRFBuckets[11]},
+ {&SRFBuckets[12], &SRFBuckets[12]},
+ {&SRFBuckets[13], &SRFBuckets[13]},
+ {&SRFBuckets[14], &SRFBuckets[14]},
+ {&SRFBuckets[15], &SRFBuckets[15]},
+ {&SRFBuckets[16], &SRFBuckets[16]},
+ {&SRFBuckets[17], &SRFBuckets[17]},
+ {&SRFBuckets[18], &SRFBuckets[18]},
+ {&SRFBuckets[19], &SRFBuckets[19]},
+ {&SRFBuckets[20], &SRFBuckets[20]},
+ {&SRFBuckets[21], &SRFBuckets[21]},
+ {&SRFBuckets[22], &SRFBuckets[22]}
+};
+
+CNameHashTable gSRFTbl;
+
+
+//---------------------------------------------------------------------------
+//
+// Function: DummyCleanup
+//
+// Synopsis: Callback for CHashTable::Cleanup that does nothing.
+//
+//---------------------------------------------------------------------------
+void DummyCleanup( SHashChain *pIgnore )
+{
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CHashTable::Cleanup
+//
+// Synopsis: Cleans up the hash table by deleteing leftover entries.
+//
+//---------------------------------------------------------------------------
+void CHashTable::Cleanup(PFNCLEANUP *pfnCleanup)
+{
+ Win4Assert(pfnCleanup);
+ ASSERT_LOCK_HELD
+
+ for (ULONG iHash=0; iHash < NUM_HASH_BUCKETS; iHash++)
+ {
+ // the ptrs could be NULL if the hash table was never initialized.
+
+ while (_buckets[iHash].pNext != NULL &&
+ _buckets[iHash].pNext != &_buckets[iHash])
+ {
+ // remove the entry from the list and call it's cleanup function
+ SHashChain *pNode = _buckets[iHash].pNext;
+
+ Remove(pNode);
+ (pfnCleanup)(pNode);
+ }
+ }
+
+#if DBG==1
+ // Verify that the hash table is empty or uninitialized.
+ for (iHash = 0; iHash < NUM_HASH_BUCKETS; iHash++)
+ {
+ Win4Assert( _buckets[iHash].pNext == &_buckets[iHash] ||
+ _buckets[iHash].pNext == NULL);
+ Win4Assert( _buckets[iHash].pPrev == &_buckets[iHash] ||
+ _buckets[iHash].pPrev == NULL);
+ }
+#endif
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CHashTable::Lookup
+//
+// Synopsis: Searches for a given key in the hash table.
+//
+// Note: iHash is between 0 and -1, not 0 and NUM_HASH_BUCKETS
+//
+//---------------------------------------------------------------------------
+SHashChain *CHashTable::Lookup(DWORD dwHash, const void *k)
+{
+ ASSERT_LOCK_HELD
+
+ // compute the index to the hash chain (it's the hash value of the key
+ // mod the number of buckets in the hash table)
+
+ DWORD iHash = dwHash % NUM_HASH_BUCKETS;
+
+ SHashChain *pNode = _buckets[iHash].pNext;
+
+ // Search the destination bucket for the key.
+ while (pNode != &_buckets[iHash])
+ {
+ if (Compare( k, pNode, dwHash ))
+ return pNode;
+
+ pNode = pNode->pNext;
+ }
+
+ return NULL;
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CHashTable::Add
+//
+// Synopsis: Adds an element to the hash table. The Cleanup method will
+// call a Cleanup function that can be used to delete the
+// element.
+//
+// Note: iHash is between 0 and -1, not 0 and NUM_HASH_BUCKETS
+//
+//---------------------------------------------------------------------------
+void CHashTable::Add(DWORD dwHash, SHashChain *pNode)
+{
+ ASSERT_LOCK_HELD
+
+ // Add the node to the bucket chain.
+ SHashChain *pHead = &_buckets[dwHash % NUM_HASH_BUCKETS];
+ SHashChain *pNew = pNode;
+
+ pNew->pPrev = pHead;
+ pHead->pNext->pPrev = pNew;
+ pNew->pNext = pHead->pNext;
+ pHead->pNext = pNew;
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CUUIDHashTable::Remove
+//
+// Synopsis: Removes an element from the hash table.
+//
+//---------------------------------------------------------------------------
+void CHashTable::Remove(SHashChain *pNode)
+{
+ ASSERT_LOCK_HELD
+
+ pNode->pPrev->pNext = pNode->pNext;
+ pNode->pNext->pPrev = pNode->pPrev;
+}
+
+
+//---------------------------------------------------------------------------
+//
+// Method: CUUIDHashTable::HashNode
+//
+// Synopsis: Computes the hash value for a given node.
+//
+//---------------------------------------------------------------------------
+DWORD CUUIDHashTable::HashNode(SHashChain *pNode)
+{
+ return Hash( ((SUUIDHashNode *) pNode)->key );
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CUUIDHashTable::Compare
+//
+// Synopsis: Compares a node and a key.
+//
+//---------------------------------------------------------------------------
+BOOL CUUIDHashTable::Compare(const void *k, SHashChain *pNode, DWORD dwHash )
+{
+ return InlineIsEqualGUID(*(const UUID *)k,
+ ((SUUIDHashNode *)pNode)->key);
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CStringHashTable::Hash
+//
+// Synopsis: Computes the hash value for a given key.
+//
+//---------------------------------------------------------------------------
+DWORD CStringHashTable::Hash(DUALSTRINGARRAY *psaKey)
+{
+ DWORD dwHash = 0;
+ DWORD *pdw = (DWORD *) &psaKey->aStringArray[0];
+
+ for (USHORT i=0; i< (psaKey->wNumEntries/2); i++)
+ {
+ dwHash = (dwHash << 8) ^ *pdw++;
+ }
+
+ return dwHash;
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CStringHashTable::HashNode
+//
+// Synopsis: Computes the hash value for a given node.
+//
+//---------------------------------------------------------------------------
+DWORD CStringHashTable::HashNode(SHashChain *pNode)
+{
+ return Hash( ((SStringHashNode *) pNode)->psaKey );
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CStringHashTable::Compare
+//
+// Synopsis: Compares a node and a key.
+//
+//---------------------------------------------------------------------------
+BOOL CStringHashTable::Compare(const void *k, SHashChain *pNode, DWORD dwHash )
+{
+ SStringHashNode *pSNode = (SStringHashNode *) pNode;
+ const DUALSTRINGARRAY *psaKey = (const DUALSTRINGARRAY *) k;
+
+ if (dwHash == pSNode->dwHash)
+ {
+ // a quick compare of the hash values found a match, now do
+ // a full compare of the key (Note: if the sizes of the two
+ // Keys are different, we exit the memcmp on the first dword,
+ // so we dont have to worry about walking off the endo of one
+ // of the Keys during the memcmp).
+
+ return !memcmp(psaKey, pSNode->psaKey, SASIZE(psaKey->wNumEntries));
+ }
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CNameHashTable::Cleanup
+//
+// Synopsis: Call the base cleanup routine with a dummy callback function
+//
+//---------------------------------------------------------------------------
+void CNameHashTable::Cleanup()
+{
+ CHashTable::Cleanup( DummyCleanup );
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CNameHashTable::Hash
+//
+// Synopsis: Computes the hash value for a given key.
+//
+//---------------------------------------------------------------------------
+DWORD CNameHashTable::Hash( REFIPID ipid, SECURITYBINDING *pName )
+{
+ DWORD dwHash = 0;
+ DWORD *pdw = (DWORD *) &ipid;
+ DWORD dwLen = lstrlenW( (WCHAR *) pName ) >> 1;
+ ULONG i;
+
+ // First hash the IPID.
+ for (i=0; i < 4; i++)
+ {
+ dwHash = (dwHash << 8) ^ *pdw++;
+ }
+
+ // Then hash the name.
+ pdw = (DWORD *) pName;
+ for (i=0; i < dwLen; i++)
+ {
+ dwHash = (dwHash << 8) ^ *pdw++;
+ }
+
+ return dwHash;
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CNameHashTable::HashNode
+//
+// Synopsis: Computes the hash value for a given node.
+//
+//---------------------------------------------------------------------------
+DWORD CNameHashTable::HashNode(SHashChain *pNode)
+{
+ SNameHashNode *pNNode = (SNameHashNode *) pNode;
+ return Hash( pNNode->ipid, &pNNode->sName );
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CNameHashTable::Compare
+//
+// Synopsis: Compares a node and a key.
+//
+//---------------------------------------------------------------------------
+BOOL CNameHashTable::Compare(const void *k, SHashChain *pNode, DWORD dwHash )
+{
+ SNameHashNode *pNNode = (SNameHashNode *) pNode;
+ const SNameKey *pKey = (const SNameKey *) k;
+
+ if (dwHash == pNNode->dwHash)
+ {
+ // a quick compare of the hash values found a match, now do
+ // a full compare of the key
+ if (*pKey->pIpid == pNNode->ipid)
+ return !lstrcmpW( (WCHAR *) pKey->pName, (WCHAR *) &pNNode->sName );
+ else
+ return FALSE;
+ }
+
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CNameHashTable::IncRef
+//
+// Synopsis: Find or create an entry for the specified name. Increment
+// its reference count.
+//
+//---------------------------------------------------------------------------
+HRESULT CNameHashTable::IncRef( ULONG cRefs, REFIPID ipid,
+ SECURITYBINDING *pName )
+{
+ SNameHashNode *pNode;
+ DWORD dwHash = Hash( ipid, pName );
+ HRESULT hr = S_OK;
+ ULONG lLen;
+ SNameKey key;
+
+ ASSERT_LOCK_HELD
+
+ // See if there is already a node in the table.
+ key.pIpid = &ipid;
+ key.pName = pName;
+ pNode = (SNameHashNode *) Lookup( dwHash, &key );
+
+ // If not, create one.
+ if (pNode == NULL)
+ {
+ lLen = lstrlenW( (WCHAR *) pName );
+ pNode = (SNameHashNode *) PrivMemAlloc( sizeof(SNameHashNode) +
+ lLen*sizeof(WCHAR) );
+ if (pNode != NULL)
+ {
+ pNode->cRef = 0;
+ pNode->dwHash = dwHash;
+ pNode->ipid = ipid;
+ memcpy( &pNode->sName, pName, (lLen + 1) * sizeof(WCHAR) );
+ Add( dwHash, &pNode->chain );
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ }
+
+ // Increment the reference count on the node.
+ if (pNode != NULL)
+ pNode->cRef += cRefs;
+ return hr;
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CNameHashTable::DecRef
+//
+// Synopsis: Decrement references for the specified name. Do not decrement
+// more references then exist. Return the actual decrement count.
+//
+//---------------------------------------------------------------------------
+ULONG CNameHashTable::DecRef( ULONG cRefs, REFIPID ipid,
+ SECURITYBINDING *pName )
+{
+ SNameHashNode *pNode;
+ DWORD dwHash = Hash( ipid, pName );
+ SNameKey key;
+
+ ASSERT_LOCK_HELD
+
+ // Lookup the name.
+ key.pIpid = &ipid;
+ key.pName = pName;
+ pNode = (SNameHashNode *) Lookup( dwHash, &key );
+
+ if (pNode != NULL)
+ {
+ if (pNode->cRef < cRefs)
+ cRefs = pNode->cRef;
+ pNode->cRef -= cRefs;
+ if (pNode->cRef == 0)
+ {
+ Remove( &pNode->chain );
+ PrivMemFree( pNode );
+ }
+ }
+ else
+ cRefs = 0;
+
+ return cRefs;
+}
+
diff --git a/private/ole32/com/dcomrem/hash.hxx b/private/ole32/com/dcomrem/hash.hxx
new file mode 100644
index 000000000..38fc27096
--- /dev/null
+++ b/private/ole32/com/dcomrem/hash.hxx
@@ -0,0 +1,277 @@
+//+--------------------------------------------------------------------------
+//
+// File: hash.hxx
+//
+// Contents: class for maintaining a GUID-based hash table.
+//
+// Classes: CHashTable
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//---------------------------------------------------------------------------
+#ifndef _HASHTBL_HXX_
+#define _HASHTBL_HXX_
+
+#include <obase.h>
+
+//---------------------------------------------------------------------------
+//
+// Structure: SHashChain
+//
+// Synopsis: An element in the double link list. Used by S*HashNode and
+// C*HashTable.
+//
+//---------------------------------------------------------------------------
+typedef struct SHashChain
+{
+ struct SHashChain *pNext; // ptr to next node in chain
+ struct SHashChain *pPrev; // ptr to prev node in chain
+} SHashChain;
+
+//---------------------------------------------------------------------------
+//
+// Structure: SUUIDHashNode
+//
+// Synopsis: This is an element in a bucket in the UUID hash table.
+//
+//---------------------------------------------------------------------------
+typedef struct SUUIDHashNode
+{
+ SHashChain chain; // double linked list ptrs
+ UUID key; // node key (the value that is hashed)
+} SUUIDHashNode;
+
+//---------------------------------------------------------------------------
+//
+// Structure: SStringHashNode
+//
+// Synopsis: This is an element in a bucket in the string hash table.
+//
+//---------------------------------------------------------------------------
+typedef struct SStringHashNode
+{
+ SHashChain chain; // double linked list ptrs
+ DWORD dwHash; // hash value of the key
+ DUALSTRINGARRAY *psaKey; // node key (the value that is hashed)
+} SStringHashNode;
+
+//---------------------------------------------------------------------------
+//
+// Structure: SNameHashNode
+//
+// Synopsis: This is an element in a bucket in the name hash table.
+//
+//---------------------------------------------------------------------------
+typedef struct SNameHashNode
+{
+ SHashChain chain; // double linked list ptrs
+ DWORD dwHash; // hash value of the key
+ ULONG cRef; // count of references
+ IPID ipid; // ipid holding the reference
+ SECURITYBINDING sName; // user name
+} SNameHashNode;
+
+
+// ptr to cleanup function that gets called by Cleanup
+typedef void (PFNCLEANUP)(SHashChain *pNode);
+
+
+// number of buckets in the hash table array. It should be a prime
+// number > 20.
+
+#define NUM_HASH_BUCKETS 23
+
+
+//---------------------------------------------------------------------------
+// External definitions.
+
+class CNameHashTable;
+extern SHashChain SRFBuckets[23];
+extern CNameHashTable gSRFTbl;
+
+//---------------------------------------------------------------------------
+//
+// Class: CHashTable
+//
+// Synopsis: Base hash table. The table uses any key
+// and stores nodes in an array of circular double linked lists.
+// The hash value of the key is the index in the array to the
+// double linked list that the node is chained off.
+//
+// Nodes must be allocated with new. A cleanup function is
+// optionally called for each node when the table is cleaned
+// up.
+//
+// Inheritors of this class must supply the HashNode
+// and Compare functions.
+//
+// Notes: All locking must be done outside the class via LOCK/UNLOCK.
+//
+//---------------------------------------------------------------------------
+class CHashTable
+{
+public:
+ virtual void Initialize(SHashChain *pChain) { _buckets = pChain; }
+ virtual void Cleanup(PFNCLEANUP *pfn);
+ void Remove(SHashChain *pNode);
+
+ virtual BOOL Compare(const void *k, SHashChain *pNode, DWORD dwHash) = 0;
+ virtual DWORD HashNode(SHashChain *pNode) = 0;
+
+protected:
+ SHashChain *Lookup(DWORD dwHash, const void *k);
+ void Add(DWORD dwHash, SHashChain *pNode);
+
+private:
+ SHashChain *_buckets; // ptr to array of double linked lists
+};
+
+
+
+//---------------------------------------------------------------------------
+//
+// Class: CUUIDHashTable
+//
+// Synopsis: This table inherits from CHashTable. It hashs based on a UUID.
+//
+// Nodes must be allocated with new. A cleanup function is
+// optionally called for each node when the table is cleaned up.
+//
+// Notes: All locking must be done outside the class via LOCK/UNLOCK.
+//
+//---------------------------------------------------------------------------
+class CUUIDHashTable : public CHashTable
+{
+public:
+ virtual BOOL Compare(const void *k, SHashChain *pNode, DWORD dwHash);
+ virtual DWORD HashNode(SHashChain *pNode);
+
+ DWORD Hash(REFGUID k);
+ SUUIDHashNode *Lookup(DWORD dwHash, REFGUID k);
+ void Add(DWORD dwHash, REFGUID k, SUUIDHashNode *pNode);
+};
+
+
+//---------------------------------------------------------------------------
+//
+// Class: CStringHashTable
+//
+// Synopsis: String based hash table, uses a DUALSTRINGARRAY as the key,
+//
+// Nodes must be allocated with new. A cleanup function is
+// optionally called for each node when the table is cleaned up.
+//
+// Notes: All locking must be done outside the class via LOCK/UNLOCK.
+//
+//---------------------------------------------------------------------------
+class CStringHashTable : public CHashTable
+{
+public:
+ virtual BOOL Compare(const void *k, SHashChain *pNode, DWORD dwHash);
+ virtual DWORD HashNode(SHashChain *pNode);
+
+ DWORD Hash(DUALSTRINGARRAY *psaKey);
+ SStringHashNode *Lookup(DWORD dwHash, DUALSTRINGARRAY *psaKey);
+ void Add(DWORD dwHash, DUALSTRINGARRAY *psaKey, SStringHashNode *pNode);
+};
+
+
+//---------------------------------------------------------------------------
+//
+// Class: CNameHashTable
+//
+// Synopsis: Name based hash table, uses a string as the key,
+//
+// Nodes must be allocated with new. A cleanup function is
+// optionally called for each node when the table is cleaned up.
+//
+// Notes: All locking must be done outside the class via LOCK/UNLOCK.
+//
+//---------------------------------------------------------------------------
+class CNameHashTable : public CHashTable
+{
+public:
+ virtual BOOL Compare(const void *k, SHashChain *pNode, DWORD dwHash);
+ virtual DWORD HashNode(SHashChain *pNode);
+
+ void Cleanup();
+ ULONG DecRef( ULONG cRefs, REFIPID ipid, SECURITYBINDING *pName );
+ DWORD Hash ( REFIPID ipid, SECURITYBINDING *pName );
+ HRESULT IncRef( ULONG cRefs, REFIPID ipid, SECURITYBINDING *pName );
+ void Initialize() { CHashTable::Initialize( SRFBuckets ); }
+};
+
+
+//---------------------------------------------------------------------------
+//
+// Method: CUUIDHashTable::Hash
+//
+// Synopsis: Computes the hash value for a given key.
+//
+//---------------------------------------------------------------------------
+inline DWORD CUUIDHashTable::Hash(REFIID k)
+{
+ const DWORD *tmp = (DWORD *) &k;
+ DWORD sum = tmp[0] + tmp[1] + tmp[2] + tmp[3];
+ return sum % NUM_HASH_BUCKETS;
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CUUIDHashTable::Lookup
+//
+// Synopsis: Finds the node with the requested key.
+//
+//---------------------------------------------------------------------------
+inline SUUIDHashNode *CUUIDHashTable::Lookup(DWORD iHash, REFGUID k)
+{
+ return (SUUIDHashNode *) CHashTable::Lookup( iHash, (const void *) &k );
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CUUIDHashTable::Add
+//
+// Synopsis: Inserts the specified node.
+//
+//---------------------------------------------------------------------------
+inline void CUUIDHashTable::Add(DWORD iHash, REFGUID k, SUUIDHashNode *pNode)
+{
+ // set the key
+ pNode->key = k;
+
+ CHashTable::Add( iHash, (SHashChain *) pNode );
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CStringHashTable::Lookup
+//
+// Synopsis: Searches for a given key in the hash table.
+//
+//---------------------------------------------------------------------------
+inline SStringHashNode *CStringHashTable::Lookup(DWORD dwHash, DUALSTRINGARRAY *psaKey)
+{
+ return (SStringHashNode *) CHashTable::Lookup( dwHash, (const void *) psaKey);
+}
+
+//---------------------------------------------------------------------------
+//
+// Method: CStringHashTable::Add
+//
+// Synopsis: Adds an element to the hash table. The element must
+// be allocated using new. The Cleanup method will call
+// an optional Cleanup function, then will call delete on
+// the element.
+//
+//---------------------------------------------------------------------------
+inline void CStringHashTable::Add(DWORD dwHash, DUALSTRINGARRAY *psaKey, SStringHashNode *pNode)
+{
+ // set the key and hash values
+ pNode->psaKey = psaKey;
+ pNode->dwHash = dwHash;
+
+ CHashTable::Add( dwHash, (SHashChain *) pNode );
+}
+
+#endif // _HASHTBL_HXX_
diff --git a/private/ole32/com/dcomrem/idtable.cxx b/private/ole32/com/dcomrem/idtable.cxx
new file mode 100644
index 000000000..10f8c3b6c
--- /dev/null
+++ b/private/ole32/com/dcomrem/idtable.cxx
@@ -0,0 +1,625 @@
+//+-------------------------------------------------------------------
+//
+// File: idtable.cxx
+//
+// Contents: identity table
+//
+// Functions:
+//
+// History: 1-Dec-93 CraigWi Created
+// 14-Apr-95 Rickhi ReVamped
+//
+//--------------------------------------------------------------------
+#include <ole2int.h>
+#include <idtable.hxx>
+#include <locks.hxx> // LOCK/UNLOCK
+#include <resolver.hxx> // gResolver
+#include <comsrgt.hxx>
+
+CIDArray *gpOIDTable = NULL;
+
+//+-------------------------------------------------------------------
+//
+// Function: LookupIDFromUnk, private
+//
+// Synopsis: Looks up and may create the identity object for the given
+// object. If the identity object is created, it is not
+// aggregated to the given object.
+//
+// Identity lookup is based on pUnkControl.
+//
+// Arguments: [pUnk] -- the object; not necessarily the controlling unknown
+// [dwflags] -- see IDLFLAGS in idtable.hxx
+// [ppStdId] -- when S_OK is returned, this is the identity
+//
+// Returns: S_OK - identity now exists (whether created here or not)
+// CO_E_OBJNOTREG - no identity and !fCreate
+// E_OUTOFMEMORY -
+// E_UNEXPECTED - at least: no controlling unknown
+//
+//
+// Notes: If the StdId is client-side, the returned pointer will hold
+// the object alive.
+//
+// If the StdId is server-side, the returned pointer will hold
+// the object alive only if IDLF_STRONG is set, otherwise it
+// just holds the identity alive.
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL LookupIDFromUnk(IUnknown *pUnk, DWORD dwFlags, CStdIdentity **ppStdId)
+{
+ // QI for IStdID; if ok, return that
+ if (pUnk->QueryInterface(IID_IStdIdentity, (void **)ppStdId) == NOERROR)
+ return S_OK;
+
+ // QI for controlling unknown; should succeed
+ IUnknown *pUnkControl;
+ if (pUnk->QueryInterface(IID_IUnknown, (void **)&pUnkControl) != NOERROR)
+ return E_UNEXPECTED;
+
+
+ HRESULT hr = S_OK;
+ CStdIdentity *pStdId = NULL;
+ CStdIdentity *pStdIdForRelease = NULL;
+
+ // scan for value in map; may find one attached to object created by now
+ IDENTRY identry;
+ identry.m_tid = GetCurrentApartmentId();
+ identry.m_pUnkControl = pUnkControl;
+
+ // lock others out of the table while we do our stuff...
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ int iID;
+
+ if (gpOIDTable == NULL)
+ {
+ iID = -1;
+ hr = CO_E_OBJNOTREG;
+
+ if (dwFlags & IDLF_CREATE)
+ {
+ hr = E_OUTOFMEMORY;
+ gpOIDTable = new CIDArray;
+ }
+
+ if (gpOIDTable == NULL)
+ {
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ pUnkControl->Release();
+ *ppStdId = NULL;
+ return hr;
+ }
+
+ // change the GrowBy value to something better than 1
+ gpOIDTable->SetSize(0, 20);
+ }
+ else
+ {
+ iID = gpOIDTable->IndexOf((void *)&identry.m_tid,
+ sizeof(identry.m_tid) + sizeof(identry.m_pUnkControl),
+ offsetof(IDENTRY, m_tid));
+ }
+
+ Win4Assert(gpOIDTable != NULL);
+
+ if (iID == -1)
+ {
+ hr = CO_E_OBJNOTREG; // assume no creation
+
+ if (dwFlags & IDLF_CREATE)
+ {
+ // try to create one. Must release the lock to do this since
+ // we have to go ask the app a bunch of questions.
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ hr = S_OK;
+ IUnknown *pUnkID; // internal unknown of Identity, ignored on
+ // the server side.
+
+ pStdId = new CStdIdentity(STDID_SERVER, NULL,pUnkControl, &pUnkID);
+ if (pStdId == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ if (SUCCEEDED(hr))
+ {
+ MOID moid;
+ if (dwFlags & IDLF_NOPING)
+ {
+ // object wont be pinged so dont bother using a
+ // pre-registered oid, just use a reserved one. Save
+ // the pre-registered ones for pinged objects.
+ hr = gResolver.ServerGetReservedMOID(&moid);
+ }
+ else
+ {
+ // object will be pinged, so get a pre-registered OID.
+ // Do this while the lock is released incase we have
+ // to Rpc to the resolver. Note this could yield if we
+ // have to pre-register more OIDs so do this before
+ // checking the table again.
+ hr = gResolver.ServerGetPreRegMOID(&moid);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // while we released the lock, another thread could have
+ // come along and created the identity for this object,
+ // so we need to check again.
+
+ iID = gpOIDTable->IndexOf((void *)&identry.m_tid,
+ sizeof(identry.m_tid) + sizeof(identry.m_pUnkControl),
+ offsetof(IDENTRY, m_tid));
+
+ if (iID == -1)
+ {
+ // make the created StdId the identity for the object.
+ hr = pStdId->SetOID(moid);
+
+ if (SUCCEEDED(hr))
+ {
+ // need to set the marshal time of the object to
+ // ensure that it does not run down when if the lock
+ // is released before our first marshal is complete.
+ pStdId->SetMarshalTime();
+
+ if (dwFlags & IDLF_STRONG)
+ {
+ pStdId->IncStrongCnt();
+ pStdId->Release();
+ }
+
+ if (dwFlags & IDLF_NOPING)
+ {
+ pStdId->SetNoPing();
+ }
+ }
+ else
+ {
+ // OOM on SetOID, release Identity and return error
+ pStdIdForRelease = pStdId;
+ pStdId = NULL;
+ Win4Assert(iID == -1);
+ }
+ }
+ else
+ {
+ // release the one we created and use the one in the
+ // tbl. we get it below in the (iID != -1) case.
+ pStdIdForRelease = pStdId;
+ }
+ }
+ else
+ {
+ // cant allocate an OID. Release the StdId we created
+ // when we exit the lock and return an error
+
+ pStdIdForRelease = pStdId;
+ pStdId = NULL;
+ Win4Assert(iID == -1);
+ }
+ }
+ }
+ }
+
+ if (iID != -1)
+ {
+ // found, addref pStdId which holds the identity alive
+ pStdId = gpOIDTable->ElementAt(iID).m_pStdID;
+
+ if (dwFlags & IDLF_STRONG)
+ pStdId->IncStrongCnt();
+ else
+ pStdId->AddRef();
+
+ Win4Assert(hr == S_OK);
+ }
+
+
+#if DBG == 1
+ if (pStdId != NULL)
+ {
+ if (iID == -1)
+ {
+ // object was created, need to get the iID for debug
+ iID = gpOIDTable->IndexOf((void *)&identry.m_tid,
+ sizeof(identry.m_tid) + sizeof(identry.m_pUnkControl),
+ offsetof(IDENTRY, m_tid));
+ Win4Assert(iID != -1);
+ }
+
+ // verify correctness of entry
+ Win4Assert(pUnkControl == gpOIDTable->ElementAt(iID).m_pUnkControl);
+ Win4Assert(IsEqualGUID(pStdId->GetOID(), gpOIDTable->ElementAt(iID).m_moid));
+ Win4Assert(gpOIDTable->ElementAt(iID).m_tid == identry.m_tid);
+ }
+#endif
+
+ *ppStdId = pStdId;
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ // Release any of the pointers we dont need. Must unlock before
+ // doing this cause it will call app code.
+
+ if (pStdIdForRelease)
+ {
+ ASSERT_LOCK_RELEASED
+ pStdIdForRelease->Release();
+ }
+
+ pUnkControl->Release();
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: LookupIDFromID, private
+//
+// Synopsis: Lookup an identity object based on an OID; does not create.
+//
+// Arguments: [moid] -- The identity
+// [ppStdID] -- The cooresponding identity object if successful
+//
+// Returns: S_OK - have the identity object
+// CO_E_OBJNOTREG - not present (when we looked)
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL LookupIDFromID(REFMOID moid, BOOL fAddRef, CStdIdentity **ppStdID)
+{
+// ComDebOut((DEB_MARSHAL, "LookupIDFromID fAddRef:%x ppStdId:%x oid:%I\n",
+// fAddRef, ppStdID, &moid));
+ ASSERT_LOCK_HELD
+
+ *ppStdID = NULL;
+
+ if (gpOIDTable == NULL)
+ {
+ // no table, dont do lookup
+ return CO_E_OBJNOTREG;
+ }
+
+ IDENTRY identry;
+ identry.m_moid = moid;
+ identry.m_tid = GetCurrentApartmentId();
+
+ int iID = gpOIDTable->IndexOf((void *)&identry.m_moid,
+ sizeof(identry.m_moid) + sizeof(identry.m_tid),
+ offsetof(IDENTRY, m_moid));
+
+ if (iID != -1)
+ {
+ // found, addref pStdID which holds the identity alive
+ *ppStdID = gpOIDTable->ElementAt(iID).m_pStdID;
+
+ if (fAddRef)
+ {
+ // I sure hope the app doesn't try anything fancy in AddRef
+ // that would cause a deadlock here! (That is, in the aggregated
+ // case we will run app code).
+ (*ppStdID)->AddRef();
+ }
+
+#if DBG == 1
+ // verify correctness of entry
+ Win4Assert(IsEqualGUID(moid, gpOIDTable->ElementAt(iID).m_moid));
+ Win4Assert(IsEqualGUID(moid, (*ppStdID)->GetOID()));
+ Win4Assert(gpOIDTable->ElementAt(iID).m_tid == identry.m_tid);
+#endif
+ }
+
+ return (*ppStdID == NULL) ? CO_E_OBJNOTREG : NOERROR;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: SetObjectID, private
+//
+// Synopsis: Called by the object id creation and unmarshal functions
+// to establish the identity for an object (handler or server).
+// Can fail if we discover an existing identity.
+//
+// Identity lookup is based on pUnkControl.
+//
+// Arguments: [moid] -- The id for the object
+// [pUnkControl] -- The controlling uknown of the object being
+// identitified.
+// [pStdID] -- The identity object itself.
+//
+// Returns: S_OK - identity was set successfully
+// CO_E_OBJISREG - object was already registered (as determined
+// by pUnkControl); *ppStdIDExisting set (if requested).
+// E_OUTOFMEMORY -
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL SetObjectID(REFMOID moid, IUnknown *pUnkControl, CStdIdentity *pStdID)
+{
+ ComDebOut((DEB_MARSHAL, "SetObjectID pUnk:%x pStdId:%x oid:%I\n",
+ pUnkControl, pStdID, &moid));
+ Win4Assert(!IsEqualGUID(moid, GUID_NULL));
+ ASSERT_LOCK_HELD
+
+
+ HRESULT hr = S_OK;
+ if (gpOIDTable == NULL)
+ {
+ gpOIDTable = new CIDArray;
+ if (gpOIDTable == NULL)
+ return E_OUTOFMEMORY;
+
+ // change the GrowBy value to something better than 1
+ gpOIDTable->SetSize(0, 20);
+ }
+
+ IDENTRY identry;
+ identry.m_moid = moid;
+ identry.m_tid = GetCurrentApartmentId();
+ identry.m_pUnkControl = pUnkControl;
+ identry.m_pStdID = pStdID;
+
+#if DBG==1
+ // scan for value in map; better not find one
+ // CODEWORK: for freethreaded handler case we may need to allow
+ // finding a duplicate entry, and throw away the second copy.
+
+ int iID = gpOIDTable->IndexOf((void *)&identry.m_tid,
+ sizeof(identry.m_tid) + sizeof(identry.m_pUnkControl),
+ offsetof(IDENTRY, m_tid));
+
+ if (iID != -1)
+ {
+ // if found, another thread created identity for same object;
+ // this is an error.
+ Win4Assert(!"Already Registered OID");
+ }
+#endif
+
+ // add at end; no addrefs
+ if (gpOIDTable->Add(identry) == -1)
+ hr = E_OUTOFMEMORY;
+
+ ASSERT_LOCK_HELD
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: ClearObjectID, private
+//
+// Synopsis: Called during the revokation of the id only. Clears
+// the identity entry in the table.
+//
+// Identity lookup is based on oid.
+//
+// Arguments: [moid] -- The identity
+// [pUnkControl] -- The object for which the identity is being
+// revoked; used for asserts only.
+// [pStdID] -- The identity object; used for asserts only.
+//
+// Returns: S_OK - removed successfully
+// CO_E_OBJNOTREG - not present (often ignored).
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL ClearObjectID(REFMOID moid, IUnknown *pUnkControl, CStdIdentity *pStdID)
+{
+ ComDebOut((DEB_MARSHAL, "ClearObjectID pUnk:%x pStdId:%x oid:%I\n",
+ pUnkControl, pStdID, &moid));
+ ASSERT_LOCK_HELD
+
+ HRESULT hr = NOERROR;
+
+ IDENTRY identry;
+ identry.m_moid = moid;
+ identry.m_tid = GetCurrentApartmentId();
+
+ int iID = gpOIDTable->IndexOf((void *)&identry.m_moid,
+ sizeof(identry.m_moid) + sizeof(identry.m_tid),
+ offsetof(IDENTRY, m_moid));
+
+ if (iID != -1)
+ {
+ // found, remove it.
+#if DBG == 1
+ // verify correctness of entry
+ Win4Assert(pUnkControl == gpOIDTable->ElementAt(iID).m_pUnkControl);
+ Win4Assert(IsEqualGUID(pStdID->GetOID(), gpOIDTable->ElementAt(iID).m_moid));
+ Win4Assert(pStdID == gpOIDTable->ElementAt(iID).m_pStdID);
+ Win4Assert(gpOIDTable->ElementAt(iID).m_tid == identry.m_tid);
+#endif
+
+ Win4Assert(gpOIDTable->GetSize() != 0);
+ int iLast = gpOIDTable->GetSize() - 1;
+ if (iID != iLast)
+ {
+ // element removed is not last; copy last element to current
+ gpOIDTable->ElementAt(iID) = gpOIDTable->ElementAt(iLast);
+ }
+
+ // now setsize to one less to remove the now unused last element
+ gpOIDTable->SetSize(iLast);
+
+ // for surrogates, we need to detect when there are no clients
+ // using servers in the surrogate process -- we rely on the
+ // fact that the OIDTable must be empty when there are no clients
+
+ // if there are no external clients, this process should terminate
+ // if its a surrogate process
+ if(iLast == 0)
+ {
+ (void)CCOMSurrogate::FreeSurrogate();
+ }
+ }
+ else
+ {
+ Win4Assert(!"ClearObjectID not found!");
+ hr = CO_E_OBJNOTREG;
+
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: IDTableUninitializeHelper, private
+//
+// Synopsis: Clears the id table memory for the specified thread (or all
+// if party model). This involves scanning the table and for
+// entries on the current thread, calling
+// IMarshal::DisconnectObject.
+//
+// The purpose of this routine is to simulate inter-thread rundown
+// as well as clean up memory.
+//
+// History: 23-Dec-93 CraigWi Created.
+// 26-Apr-94 CraigWi Now called per-thread and disconnects
+//
+// Note: This function should only be called when the IDTable
+// really needs to be uninitialized. For the party model, this
+// means that it should only be called when the last thread
+// is exiting.
+//
+// This function must NOT assume that it is being called within
+// a critical section.
+//
+//--------------------------------------------------------------------
+INTERNAL_(void) IDTableThreadUninitializeHelper(DWORD tid)
+{
+ // The table being uninitialized is resized as items are deleted. Thus
+ // if an element in the middle is removed, the last element in the table
+ // will be copied into that slot and the table will shrink. Also, some
+ // of the calls made while cleaning up an entry will free other entries,
+ // causing further swapping.
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ int i = gpOIDTable->GetSize() - 1;
+ while (i >= 0)
+ {
+ if (gpOIDTable->ElementAt(i).m_tid == tid)
+ {
+ Win4Assert(IsValidInterface(gpOIDTable->ElementAt(i).m_pStdID));
+ CStdIdentity *pStdID = gpOIDTable->ElementAt(i).m_pStdID;
+ pStdID->AddRef();
+
+ ComDebOut((DEB_ERROR,
+ "Object [%s] at %lx still has [%x] connections\n",
+ pStdID->IsClient() ? "CLIENT" : "SERVER",
+ gpOIDTable->ElementAt(i).m_pUnkControl, pStdID->GetRC()));
+
+ pStdID->DbgDumpInterfaceList();
+
+ // release lock since the disconnect could take a long time.
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ pStdID->Disconnect();
+ pStdID->Release();
+
+ // re-request the lock since we need to guard the GetSize below
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+ i--;
+ if (i >= gpOIDTable->GetSize())
+ i = gpOIDTable->GetSize() - 1;
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: IDTableUninitialize, public
+//
+// Synopsis: Clears the id table memory for the current apartment.
+//
+// History: 13 Apr 95 AlexMit Created.
+//
+//--------------------------------------------------------------------
+INTERNAL_(void) IDTableThreadUninitialize(void)
+{
+ if (gpOIDTable)
+ {
+ IDTableThreadUninitializeHelper(GetCurrentApartmentId());
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IDTableProcessUninitialize
+//
+// Synopsis: Process specific IDTable uninitialization
+//
+// Effects: Frees up table memory
+//
+// Requires: All thread specific uninitialization already complete. This
+// function assumes that the caller is holding the
+// g_mxsSingleThreadOle mutex (so that no other thread is trying
+// to use the table while we clean it up).
+//
+// History: 29-Jun-94 AlexT Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(void) IDTableProcessUninitialize(void)
+{
+ if (gpOIDTable)
+ {
+ gpOIDTable->RemoveAll();
+ delete gpOIDTable;
+ gpOIDTable = NULL;
+ }
+}
+
+#if DBG == 1
+//+-------------------------------------------------------------------
+//
+// Function: Dbg_FindRemoteHdlr
+//
+// Synopsis: finds a remote object handler for the specified object,
+// and returns an instance of IMarshal on it. This is debug
+// code for assert that reference counts are as expected and
+// is used by tmarshal.exe.
+//
+// History: 23-Nov-93 Rickhi Created
+// 23-Dec-93 CraigWi Changed to identity object
+//
+//--------------------------------------------------------------------
+extern "C" IMarshal * _stdcall Dbg_FindRemoteHdlr(IUnknown *punkObj)
+{
+ // validate input parms
+ Win4Assert(punkObj);
+
+ IMarshal *pIM = NULL;
+ CStdIdentity *pStdID;
+ HRESULT hr = LookupIDFromUnk(punkObj, 0, &pStdID);
+ if (hr == NOERROR)
+ {
+ pIM = (IMarshal *)pStdID;
+ }
+
+ return pIM;
+}
+#endif // DBG==1
+
diff --git a/private/ole32/com/dcomrem/idtable.hxx b/private/ole32/com/dcomrem/idtable.hxx
new file mode 100644
index 000000000..41fad6f61
--- /dev/null
+++ b/private/ole32/com/dcomrem/idtable.hxx
@@ -0,0 +1,88 @@
+//+-------------------------------------------------------------------
+//
+// File: idtable.hxx
+//
+// Contents: internal identity table definitions.
+//
+// Description:
+// The table consists, logically, of two different
+// keys which map to the same value. The two
+// keys are the object identity (oid) and the
+// controlling unknown (pUnkControl). The value
+// is the pointer to the identity interface.
+//
+// Additionally, if the apartment model is in use,
+// the thread forms an additional part of both keys.
+//
+// Presently this is implemented as an array of the
+// three values and linear scans are used for lookup.
+// Neither of the pointers are addref'd (as far as the
+// table is concerned). Lookup does addref and return
+// a pointer to the identity object. The pUnkControl
+// is used solely for lookup.
+//
+// Possible changes: use two separate maps, one of
+// which is keyed by the oid and the other keyed
+// by pUnkControl. The value in the first map is
+// the hKey of value in the second map. The id object
+// would hold the hKey of the value in the first map
+// to save on space. Using two maps increases the
+// speed of lookup for large numbers of ids, but
+// increases the cost per id from 40bytes to 48bytes.
+// (40 = 2 GUIDS + 2 far pointers; 48 = 1 GUID +
+// 3 hKeys/ptrs + 16 bytes overhead for two hash
+// buckets)
+//
+// It is also possible to use one map (keyed by
+// the oid) and trim the array by the GUID. The
+// cost per id is 40bytes (1 GUID + 1 hKey + 3 ptr +
+// 8 bytes overhead for one hash bucket).
+//
+//
+// History: 1-Dec-93 CraigWi Created
+//
+//--------------------------------------------------------------------
+#ifndef __IDTABLE__
+#define __IDTABLE__
+
+#include <olerem.h>
+#include <stdid.hxx> // CStdIdentity
+#include <sem.hxx> // CMutexSem
+
+
+// flags passed in on LookupIDFromUnk.
+
+typedef enum tagIDLFLAGS
+{
+ IDLF_CREATE = 0x01, // create if not found
+ IDLF_STRONG = 0x02, // add a strong connection
+ IDLF_NOPING = 0x04 // object wont be pinged
+} IDLFLAGS;
+
+
+// entry in id array. the array is packed (no NULL holes)
+// NOTE: when looking up for the apartment model, we pair the two fields
+// m_oid/m_tid and m_tid/m_pUnkControl;
+
+struct IDENTRY
+{
+ MOID m_moid; // OID + MID
+ DWORD m_tid;
+ IUnknown *m_pUnkControl;// not addref'd directly
+ CStdIdentity *m_pStdID; // not addref'd directly
+};
+
+#include <array_id.h>
+
+
+// other functions declared in olerem.h
+INTERNAL LookupIDFromUnk(IUnknown *pUnk, DWORD dwFlags, CStdIdentity **ppStdId);
+INTERNAL LookupIDFromID(REFMOID moid, BOOL fAddRef, CStdIdentity **ppStdId);
+INTERNAL SetObjectID(REFMOID moid, IUnknown *pUnkControl, CStdIdentity *pStdID);
+INTERNAL ClearObjectID(REFMOID moid, IUnknown *pUnkControl, CStdIdentity *pStdID);
+INTERNAL_(void) IDTableThreadUninitialize(void);
+INTERNAL_(void) IDTableProcessUninitialize(void);
+
+INTERNAL GetStaticUnMarshaler(IMarshal **ppMarshal);
+
+#endif // __IDTABLE__
diff --git a/private/ole32/com/dcomrem/ipidtbl.cxx b/private/ole32/com/dcomrem/ipidtbl.cxx
new file mode 100644
index 000000000..21a7b4fac
--- /dev/null
+++ b/private/ole32/com/dcomrem/ipidtbl.cxx
@@ -0,0 +1,1502 @@
+//+-----------------------------------------------------------------------
+//
+// File: ipidtbl.cxx
+//
+// Contents: IPID (interface pointer identifier) table.
+//
+// Classes: CIPIDTable
+//
+// History: 02-Feb-95 Rickhi Created
+//
+// Notes: All synchronization is the responsibility of the caller.
+//
+//-------------------------------------------------------------------------
+#include <ole2int.h>
+#include <ipidtbl.hxx> // CIPIDTable
+#include <resolver.hxx> // CRpcResolver
+#include <service.hxx> // SASIZE
+#include <remoteu.hxx> // CRemoteUnknown
+#include <marshal.hxx> // UnmarshalObjRef
+#include <idtable.hxx> // LookupIDFromUnk
+#include <callctrl.hxx> // OleModalLoopBlockFn
+
+
+// global tables
+CMIDTable gMIDTbl; // machine ID table
+COXIDTable gOXIDTbl; // object exported ID table
+CIPIDTable gIPIDTbl; // interface pointer ID table
+
+MIDEntry *gpLocalMIDEntry = NULL; // local machine MIDEntry
+OXIDEntry *gpMTAOXIDEntry = NULL; // MTA OXIDEntry
+DUALSTRINGARRAY *gpsaLocalResolver = NULL; // local OXIDResolver address
+
+OXIDEntry COXIDTable::_InUseHead = { &_InUseHead, &_InUseHead };
+OXIDEntry COXIDTable::_CleanupHead = { &_CleanupHead, &_CleanupHead };
+OXIDEntry COXIDTable::_ExpireHead = { &_ExpireHead, &_ExpireHead };
+DWORD COXIDTable::_cExpired = 0;
+
+CStringHashTable CMIDTable::_HashTbl; // hash table for MIDEntries
+CPageAllocator CMIDTable::_palloc; // allocator for MIDEntries
+CPageAllocator COXIDTable::_palloc; // allocator for OXIDEntries
+CPageAllocator CIPIDTable::_palloc; // allocator for IPIDEntries
+
+
+//+------------------------------------------------------------------------
+//
+// Machine Identifier hash table buckets. This is defined as a global
+// so that we dont have to run any code to initialize the hash table.
+//
+//+------------------------------------------------------------------------
+SHashChain MIDBuckets[23] = {
+ {&MIDBuckets[0], &MIDBuckets[0]},
+ {&MIDBuckets[1], &MIDBuckets[1]},
+ {&MIDBuckets[2], &MIDBuckets[2]},
+ {&MIDBuckets[3], &MIDBuckets[3]},
+ {&MIDBuckets[4], &MIDBuckets[4]},
+ {&MIDBuckets[5], &MIDBuckets[5]},
+ {&MIDBuckets[6], &MIDBuckets[6]},
+ {&MIDBuckets[7], &MIDBuckets[7]},
+ {&MIDBuckets[8], &MIDBuckets[8]},
+ {&MIDBuckets[9], &MIDBuckets[9]},
+ {&MIDBuckets[10], &MIDBuckets[10]},
+ {&MIDBuckets[11], &MIDBuckets[11]},
+ {&MIDBuckets[12], &MIDBuckets[12]},
+ {&MIDBuckets[13], &MIDBuckets[13]},
+ {&MIDBuckets[14], &MIDBuckets[14]},
+ {&MIDBuckets[15], &MIDBuckets[15]},
+ {&MIDBuckets[16], &MIDBuckets[16]},
+ {&MIDBuckets[17], &MIDBuckets[17]},
+ {&MIDBuckets[18], &MIDBuckets[18]},
+ {&MIDBuckets[19], &MIDBuckets[19]},
+ {&MIDBuckets[20], &MIDBuckets[20]},
+ {&MIDBuckets[21], &MIDBuckets[21]},
+ {&MIDBuckets[22], &MIDBuckets[22]}
+};
+
+//+------------------------------------------------------------------------
+//
+// Member: CIPIDTbl::Initialize, public
+//
+// Synopsis: Initializes the IPID table.
+//
+// History: 02-Feb-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void CIPIDTable::Initialize()
+{
+ ComDebOut((DEB_OXID, "CIPIDTable::Initialize\n"));
+ _palloc.Initialize(sizeof(IPIDEntry), IPIDS_PER_PAGE);
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CIPIDTbl::Cleanup, public
+//
+// Synopsis: Cleanup the ipid table.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void CIPIDTable::Cleanup()
+{
+ ComDebOut((DEB_OXID, "CIPIDTable::Cleanup\n"));
+ _palloc.Cleanup();
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CIPIDTbl::LookupIPID, public
+//
+// Synopsis: Finds an entry in the IPID table with the given IPID.
+// This is used by the unmarshalling code, the dispatch
+// code, and CRemoteUnknown.
+//
+// Notes: This method should be called instead of GetEntryPtr
+// whenever you dont know if the IPID is valid or not (eg it
+// came in off the network), since this validates the IPID
+// index to ensure its within the table size, as well as
+// validating the rest of the IPID.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+IPIDEntry *CIPIDTable::LookupIPID(REFIPID ripid)
+{
+ ASSERT_LOCK_HELD
+
+ // Validate the IPID index that is passed in, since this came in off
+ // off the net it could be bogus and we dont want to fault on it.
+ // first dword of the ipid is the index into the ipid table.
+
+ if (_palloc.IsValidIndex(ripid.Data1))
+ {
+ IPIDEntry *pIPIDEntry = GetEntryPtr(ripid.Data1);
+
+ // entry must be server side and not vacant
+ if ((pIPIDEntry->dwFlags & (IPIDF_SERVERENTRY | IPIDF_VACANT)) ==
+ IPIDF_SERVERENTRY)
+ {
+ // validate the rest of the guid
+ if (InlineIsEqualGUID(pIPIDEntry->ipid, ripid))
+ return pIPIDEntry;
+ }
+ }
+
+ return NULL;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CIPIDTable::ReleaseEntryList
+//
+// Synopsis: return a linked list of IPIDEntry to the table's free list
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CIPIDTable::ReleaseEntryList(IPIDEntry *pFirst, IPIDEntry *pLast)
+{
+ ASSERT_LOCK_HELD
+ Win4Assert(pLast->pNextOID == NULL);
+
+#if DBG==1
+ // In debug, walk the list to ensure they are released, vacant,
+ // disconnected etc.
+ IPIDEntry *pEntry = pFirst;
+ while (pEntry != NULL)
+ {
+ Win4Assert(pEntry->pOXIDEntry == NULL); // must already be released
+ Win4Assert(pEntry->dwFlags & IPIDF_VACANT);
+ Win4Assert(pEntry->dwFlags & IPIDF_DISCONNECTED);
+
+ pEntry = pEntry->pNextOID;
+ }
+#endif
+
+ _palloc.ReleaseEntryList((PageEntry *)pFirst, (PageEntry *)pLast);
+}
+
+#if DBG==1
+//+-------------------------------------------------------------------
+//
+// Member: CIPIDTable::ValidateIPIDEntry
+//
+// Synopsis: Ensures the IPIDEntry is valid.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CIPIDTable::ValidateIPIDEntry(IPIDEntry *pEntry, BOOL fServerSide,
+ CRpcChannelBuffer *pChnl)
+{
+ // validate the IPID flags
+ Win4Assert(!(pEntry->dwFlags & IPIDF_VACANT));
+ if (fServerSide)
+ {
+ // server side must have SERVERENTRY ipids
+ Win4Assert(pEntry->dwFlags & IPIDF_SERVERENTRY);
+ }
+ else
+ {
+ // client side must not have SERVERENTRY ipids
+ Win4Assert(!(pEntry->dwFlags & IPIDF_SERVERENTRY));
+ }
+
+
+ // Validate the pStub interface
+ if (IsEqualIID(pEntry->iid, IID_IUnknown))
+ {
+ // there is no proxy or stub for IUnknown interface
+ Win4Assert(pEntry->pStub == NULL);
+ }
+ else
+ {
+ if ((pEntry->dwFlags & IPIDF_DISCONNECTED) &&
+ (pEntry->dwFlags & IPIDF_SERVERENTRY))
+ {
+ // disconnected server side has NULL pStub
+ Win4Assert(pEntry->pStub == NULL);
+ }
+ else
+ {
+ // both connected and disconnected client side has valid proxy
+ Win4Assert(pEntry->pStub != NULL);
+ Win4Assert(IsValidInterface(pEntry->pStub));
+ }
+ }
+
+
+ // Validate the interface pointer (pv)
+ if (!(pEntry->dwFlags & IPIDF_DISCONNECTED))
+ {
+ Win4Assert(pEntry->pv != NULL);
+ Win4Assert(IsValidInterface(pEntry->pv));
+ }
+
+
+ // Validate the channel ptr
+ if (fServerSide)
+ {
+ // all stubs share the same channel on the server side
+ Win4Assert(pEntry->pChnl == pChnl);
+ }
+ else
+ {
+ // all proxies have their own different channel on client side
+ Win4Assert(pEntry->pChnl != pChnl || pEntry->pChnl == NULL);
+ }
+
+ // Validate the RefCnts
+ if (!(pEntry->dwFlags & IPIDF_DISCONNECTED) && !fServerSide)
+ {
+ // if connected, must be > 0 refcnt on client side.
+ // potentially not > 0 if TABLE marshal on server side.
+ Win4Assert(pEntry->cStrongRefs + pEntry->cWeakRefs > 0);
+ }
+
+ // Validate the OXIDEntry
+ if (pEntry->pOXIDEntry)
+ {
+ OXIDEntry *pOX = pEntry->pOXIDEntry;
+ if (fServerSide)
+ {
+ // check OXID tid and pid
+ Win4Assert(pOX->dwPid == GetCurrentProcessId());
+ if ((pOX->dwFlags & OXIDF_MTASERVER))
+ Win4Assert(pOX->dwTid == 0);
+ else
+ Win4Assert(pOX->dwTid == GetCurrentThreadId());
+
+ if (pChnl != NULL)
+ {
+ // CODEWORK: ensure OXID is same as the rest of the object
+ // Win4Assert(IsEqualGUID(pOX->moxid, GetMOXID()));
+ }
+ }
+ }
+
+
+ // Validate the pNextOID
+ if (pEntry->pNextOID != NULL)
+ {
+ // ensure it is within the bounds of the table
+ Win4Assert(GetEntryIndex(pEntry) != -1);
+
+ // cant point back to self or we have a circular list
+ Win4Assert(pEntry->pNextOID != pEntry);
+ }
+}
+#endif
+
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTbl::Initialize, public
+//
+// Synopsis:
+//
+// History: 02-Feb-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void COXIDTable::Initialize()
+{
+ ComDebOut((DEB_OXID, "COXIDTable::Initialize\n"));
+ _palloc.Initialize(sizeof(OXIDEntry), OXIDS_PER_PAGE);
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTbl::Cleanup, public
+//
+// Synopsis: Cleanup the OXID table.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void COXIDTable::Cleanup()
+{
+ ComDebOut((DEB_OXID, "COXIDTable::Cleanup\n"));
+ ASSERT_LOCK_HELD
+
+ // the lists better be empty before we delete the entries
+ AssertListsEmpty();
+ _palloc.Cleanup();
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTbl::AddEntry, public
+//
+// Synopsis: Adds an entry to the OXID table. The entry is AddRef'd.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+HRESULT COXIDTable::AddEntry(REFOXID roxid, OXID_INFO *poxidInfo,
+ MIDEntry *pMIDEntry, OXIDEntry **ppEntry)
+{
+ Win4Assert(poxidInfo != NULL);
+ Win4Assert(pMIDEntry != NULL);
+ ASSERT_LOCK_HELD
+
+ // find first free entry slot, grow table if necessary
+ OXIDEntry *pEntry = (OXIDEntry *) _palloc.AllocEntry();
+ if (pEntry == NULL)
+ {
+ ComDebOut((DEB_ERROR,"Out Of Memory in COXIDTable::AddEntry\n"));
+ return E_OUTOFMEMORY;
+ }
+
+ // chain it on the list of inuse entries
+ pEntry->pPrev = &_InUseHead;
+ _InUseHead.pNext->pPrev = pEntry;
+ pEntry->pNext = _InUseHead.pNext;
+ _InUseHead.pNext = pEntry;
+
+ // Copy oxidInfo into OXIDEntry.
+
+ MOXIDFromOXIDAndMID(roxid, pMIDEntry->mid, &pEntry->moxid);
+ pEntry->cRefs = 1; // caller gets one reference
+ pEntry->cWaiters = 0;
+ pEntry->dwPid = poxidInfo->dwPid;
+ pEntry->dwTid = poxidInfo->dwTid;
+ pEntry->dwFlags = (poxidInfo->dwPid == 0) ? 0 : OXIDF_MACHINE_LOCAL;
+ pEntry->dwFlags |= (poxidInfo->dwTid != 0) ? 0 : OXIDF_MTASERVER;
+ pEntry->pRUSTA = NULL;
+ pEntry->pRUMTA = NULL;
+ pEntry->ipidRundown = poxidInfo->ipidRemUnknown;
+ pEntry->hServerSTA = NULL;
+ pEntry->hServerMTA = NULL;
+ pEntry->pMIDEntry = pMIDEntry;
+ pEntry->hComplete = NULL;
+ pEntry->cCalls = 0;
+ pEntry->cResolverRef = 0;
+ IncMIDRefCnt(pMIDEntry);
+
+
+ HRESULT hr = S_OK;
+
+ if (poxidInfo->dwPid != GetCurrentProcessId())
+ {
+ // This OXID is for an apartment outside the current process. We
+ // need to make an RPC binding handle from the supplied strings.
+
+ Win4Assert(poxidInfo->psa != NULL &&
+ poxidInfo->psa->aStringArray[0] != 0);
+
+ // Set the MSWMSG flag if the transport is MSWMSG.
+ RPC_STATUS sc = CheckClientMswmsg(poxidInfo->psa->aStringArray,
+ &pEntry->dwFlags);
+
+ // Make a binding handle from the string bindings.
+ if (sc == RPC_S_OK)
+ {
+ sc = RpcBindingFromStringBinding(poxidInfo->psa->aStringArray,
+ &pEntry->hServerSTA);
+ }
+
+ // Pass our blocking function to MSWMSG. When we make calls out,
+ // MSWMSG will call the blocking function.
+ if (sc == RPC_S_OK && (pEntry->dwFlags & OXIDF_MSWMSG))
+ {
+ sc = I_RpcBindingSetAsync(pEntry->hServerSTA, OleModalLoopBlockFn);
+ }
+
+ // Set security on the binding handle if necessary.
+ if (sc == RPC_S_OK)
+ {
+ hr = SetAuthnService( pEntry->hServerSTA, poxidInfo, pEntry );
+ }
+ else
+ {
+ hr = HRESULT_FROM_WIN32(sc);
+ }
+ }
+
+ // Get a shutdown event for server side MTAs. Don't use the event
+ // cache because the event isn't always reset.
+ else if (pEntry->dwFlags & OXIDF_MTASERVER)
+ {
+#ifdef _CHICAGO_
+ pEntry->hComplete = CreateEventA( NULL, FALSE, FALSE, NULL );
+#else //_CHICAGO_
+ pEntry->hComplete = CreateEvent( NULL, FALSE, FALSE, NULL );
+#endif //_CHICAGO_
+ if (pEntry->hComplete == NULL)
+ hr = RPC_E_OUT_OF_RESOURCES;
+ }
+
+ if (FAILED(hr))
+ {
+ // failed, release the OXIDEntry
+ DecOXIDRefCnt(pEntry);
+ pEntry = NULL;
+ }
+
+ *ppEntry = pEntry;
+ gOXIDTbl.ValidateOXID();
+ ComDebOut((DEB_OXID,"COXIDTable::AddEntry pEntry:%x moxid:%I\n",
+ pEntry, (pEntry) ? &pEntry->moxid : &GUID_NULL));
+ return hr;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTbl::LookupOXID, public
+//
+// Synopsis: finds an entry in the OXID table with the given OXID.
+// This is used by the unmarshalling code. The returned
+// entry has been AddRef'd.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+// PERFWORK: we could move the OXIDEntry to the head of the InUse list on
+// the assumption that it will be the most frequently used item
+// in the near future.
+//
+//-------------------------------------------------------------------------
+OXIDEntry *COXIDTable::LookupOXID(REFOXID roxid, REFMID rmid)
+{
+ ASSERT_LOCK_HELD
+
+ MOXID moxid;
+ MOXIDFromOXIDAndMID(roxid, rmid, &moxid);
+
+ // first, search the InUse list.
+ OXIDEntry *pEntry = SearchList(moxid, &_InUseHead);
+
+ if (pEntry == NULL)
+ {
+ // not found on InUse list, search the Expire list.
+ if ((pEntry = SearchList(moxid, &_ExpireHead)) != NULL)
+ {
+ // found it, unchain it from the list of Expire entries
+ pEntry->pPrev->pNext = pEntry->pNext;
+ pEntry->pNext->pPrev = pEntry->pPrev;
+
+ // chain it on the list of InUse entries
+ pEntry->pPrev = &_InUseHead;
+ _InUseHead.pNext->pPrev = pEntry;
+ pEntry->pNext = _InUseHead.pNext;
+ _InUseHead.pNext = pEntry;
+
+ // reset the cRefs field (which was overloaded with the
+ // expire time by ReleaseEntry), and count one less entry.
+
+ pEntry->cRefs = 1;
+ _cExpired--;
+ }
+ }
+
+ ComDebOut((DEB_OXID,"COXIDTable::LookupOXID pEntry:%x moxid:%I\n",
+ pEntry, &moxid));
+ gOXIDTbl.ValidateOXID();
+ return pEntry;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTbl::SearchList, private
+//
+// Synopsis: Searches the specified list for a matching OXID entry.
+// This is a subroutine of LookupOXID.
+//
+// History: 25-Aug-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+OXIDEntry *COXIDTable::SearchList(REFMOXID rmoxid, OXIDEntry *pStart)
+{
+ ASSERT_LOCK_HELD
+
+ OXIDEntry *pEntry = pStart->pNext;
+ while (pEntry != pStart)
+ {
+ if (InlineIsEqualGUID(rmoxid, pEntry->moxid))
+ {
+ IncOXIDRefCnt(pEntry);
+ return pEntry; // found a match, return it
+ }
+
+ pEntry = pEntry->pNext; // try next one in use
+ }
+
+ return NULL;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTbl::ReleaseEntry, public
+//
+// Synopsis: removes an entry from the OXID table InUse list and
+// places it on the Expire list. Entries on the Expire list
+// will be cleaned up by a worker thread at a later time, or
+// placed back on the InUse list by LookupOXID.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void COXIDTable::ReleaseEntry(OXIDEntry *pEntry)
+{
+ Win4Assert(pEntry);
+ Win4Assert(pEntry->cRefs == 0); // must be no users of this entry
+ gOXIDTbl.ValidateOXID();
+ ASSERT_LOCK_HELD
+
+ if (pEntry->dwFlags & OXIDF_PENDINGRELEASE)
+ {
+ return; // already being deleted, just ignore.
+ }
+
+ // unchain it from the list of InUse entries
+ pEntry->pPrev->pNext = pEntry->pNext;
+ pEntry->pNext->pPrev = pEntry->pPrev;
+
+ // chain it on the *END* of the list of Expire entries, and
+ // count one more expired entry.
+ pEntry->pPrev = _ExpireHead.pPrev;
+ pEntry->pNext = &_ExpireHead;
+ _ExpireHead.pPrev->pNext= pEntry;
+ _ExpireHead.pPrev = pEntry;
+
+ _cExpired++;
+
+ // set the time when it was placed on the Expire list. This (may be)
+ // used to determine when this entry should really expire.
+ pEntry->cRefs = GetTickCount();
+
+ // Free anything hanging around on the cleanup list. This may release
+ // the lock.
+ FreeCleanupEntries();
+
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_OXID,"COXIDTable::ReleaseEntry pEntry:%x\n", pEntry));
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTbl::FreeExpiredEntries, public
+//
+// Synopsis: Walks the Expire list and deletes the OXIDEntries that
+// were placed on the expire list before the given time.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void COXIDTable::FreeExpiredEntries(DWORD dwTime)
+{
+ ASSERT_LOCK_HELD
+
+ while (_ExpireHead.pNext != &_ExpireHead)
+ {
+#if 0
+ // CODEWORK: currently we never use the ExpireTime function,
+ // we only call this routine from ChannelProcessUninit, so ignore
+ // the expire time and release all the entries.
+
+ // there is an entry on the list. check its time stamp (which
+ // was placed in the cRefs field)
+
+ if ((DWORD)_ExpireHead.pNext->cRefs - dwTime > 0)
+ {
+ // this entry has not yet expired. All entries after this
+ // one must not have expired either, so exit early.
+ break;
+ }
+#endif
+ // unchain it from the list of Expire entries, and count one less
+ // expired entry.
+ OXIDEntry *pEntry = _ExpireHead.pNext;
+
+ pEntry->pPrev->pNext = pEntry->pNext;
+ pEntry->pNext->pPrev = pEntry->pPrev;
+
+ _cExpired--;
+
+ ExpireEntry(pEntry);
+ }
+
+ // The worker thread moves entries to the cleanup list while holding the
+ // lock. Since the expire list is now empty no more OXIDs can be added
+ // to the cleanup list. Now would be a good time to free items on the
+ // cleanup list.
+ FreeCleanupEntries();
+
+ AssertListsEmpty(); // the lists better be empty now
+ ComDebOut((DEB_OXID, "COXIDTable::FreeExpiredEntries dwTime:%x\n", dwTime));
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTbl::FreeCleanupEntries, public
+//
+// Synopsis: Deletes all OXID entries on the Cleanup list.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void COXIDTable::FreeCleanupEntries()
+{
+ ASSERT_LOCK_HELD
+
+ while (_CleanupHead.pNext != &_CleanupHead)
+ {
+ // Unchain the entries and free all resources it holds.
+ OXIDEntry *pEntry = _CleanupHead.pNext;
+ _CleanupHead.pNext = pEntry->pNext;
+ ExpireEntry(pEntry);
+ }
+
+ ComDebOut((DEB_OXID, "COXIDTable::FreeCleanupEntries\n"));
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTable::NumOxidsToRemove
+//
+// Synopsis: Returns the number of OXIDs on the expired list that can be
+// freed.
+//
+// History: 03-Jun-96 AlexMit Created
+//
+//-------------------------------------------------------------------------
+DWORD COXIDTable::NumOxidsToRemove()
+{
+ ASSERT_LOCK_HELD
+
+ // Compute how many extra OXIDs are on the expired list.
+ if (_cExpired > OXIDTBL_MAXEXPIRED)
+ return _cExpired - OXIDTBL_MAXEXPIRED;
+ else
+ return 0;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTable::GetOxidsToRemove
+//
+// Synopsis: Builds a list of OXIDs old enough to be deleted. Removes
+// them from the expired list and puts them on the cleanup list.
+// Moves machine local OXIDs directly to the cleanup list.
+//
+// History: 03-Jun-42 AlexMit Created
+//
+//-------------------------------------------------------------------------
+void COXIDTable::GetOxidsToRemove( OXID_REF *pRef, DWORD *pNum )
+{
+ OXIDEntry *pEntry;
+ ASSERT_LOCK_HELD
+
+ // Expire entries until the expired list is short enough.
+ *pNum = 0;
+ while (_cExpired > OXIDTBL_MAXEXPIRED)
+ {
+ // Only count machine remote OXIDs.
+ pEntry = _ExpireHead.pNext;
+ if ((pEntry->dwFlags & OXIDF_MACHINE_LOCAL) == 0)
+ {
+ // Add the OXID to the list to deregister.
+ MIDFromMOXID( pEntry->moxid, &pRef->mid );
+ OXIDFromMOXID( pEntry->moxid, &pRef->oxid );
+ pRef->refs = pEntry->cResolverRef;
+ pRef++;
+ *pNum += 1;
+ }
+
+ // Remove the OXID from the expired list and put it on a list
+ // of OXIDs to be released by some apartment thread.
+ _cExpired--;
+ pEntry->pPrev->pNext = pEntry->pNext;
+ pEntry->pNext->pPrev = pEntry->pPrev;
+ pEntry->pNext = _CleanupHead.pNext;
+ _CleanupHead.pNext = pEntry;
+ }
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTbl::ExpireEntry, private
+//
+// Synopsis: deletes all state associated with an OXIDEntry that has
+// been expired.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void COXIDTable::ExpireEntry(OXIDEntry *pEntry)
+{
+ ComDebOut((DEB_OXID, "COXIDTable::ExpireEntry pEntry:%x\n", pEntry));
+ Win4Assert(pEntry);
+ Win4Assert(!(pEntry->dwFlags & OXIDF_PENDINGRELEASE));
+ ASSERT_LOCK_HELD
+
+ if (pEntry->pRUSTA || pEntry->pRUMTA)
+ {
+ // release the IRemUnknown. Note that the IRemUnk is an object
+ // proxy who's IPIDEntry holds a reference back to the very
+ // OXIDEntry we are releasing. In order to prevent recursive
+ // Release's we set a simple flag here and check for it above.
+
+ pEntry->dwFlags |= OXIDF_PENDINGRELEASE;
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ if (pEntry->pRUSTA)
+ {
+ pEntry->pRUSTA->Release();
+ }
+ if (pEntry->pRUMTA)
+ {
+ pEntry->pRUMTA->Release();
+ }
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+
+ if (pEntry->hServerSTA != NULL)
+ {
+ // Note that if hServerSTA is an HWND (apartment model, same process)
+ // then it should have been cleaned up already in ThreadStop. We
+ // just assert that here.
+ Win4Assert(pEntry->dwPid != GetCurrentProcessId());
+
+ // hServerSTA is an RPC binding handle. Free it.
+ RPC_STATUS sc = RpcBindingFree(&pEntry->hServerSTA);
+ ComDebErr(sc != RPC_S_OK, "RpcBindingFree failed.\n");
+ }
+
+ if (pEntry->hServerMTA != NULL)
+ {
+ // hServerMTA is an RPC binding handle. Free it.
+ Win4Assert(pEntry->dwPid != GetCurrentProcessId());
+ RPC_STATUS sc = RpcBindingFree(&pEntry->hServerMTA);
+ ComDebErr(sc != RPC_S_OK, "RpcBindingFree failed.\n");
+ }
+
+ // dec the refcnt on the MIDEntry
+ DecMIDRefCnt(pEntry->pMIDEntry);
+
+ // Release the call shutdown event.
+ if (pEntry->hComplete != NULL)
+ CloseHandle( pEntry->hComplete );
+
+ // zero out the fields
+ memset(pEntry, 0, sizeof(OXIDEntry));
+
+ // return it to the allocator
+ _palloc.ReleaseEntry((PageEntry *)pEntry);
+
+ ComDebOut((DEB_OXID,"COXIDTable::ExpireEntry pEntry:%x\n", pEntry));
+}
+
+//+------------------------------------------------------------------------
+//
+// Function: COXIDTbl::DecOXIDRefCnt, public
+//
+// Synopsis: release one reference to the OXIDEntry and release
+// the entry if the count goes to zero.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void DecOXIDRefCnt(OXIDEntry *pEntry)
+{
+ Win4Assert(pEntry);
+ ASSERT_LOCK_HELD
+
+ ComDebOut((DEB_OXID,
+ "DecOXIDRefCnt pEntry:%x cRefs[%x]\n", pEntry, pEntry->cRefs-1));
+
+ pEntry->cRefs--;
+ if (pEntry->cRefs == 0)
+ {
+ gOXIDTbl.ReleaseEntry(pEntry);
+ }
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: COXIDTable::GetRemUnk, public
+//
+// Synopsis: Find or create the proxy for the IRemUnknown for the
+// specified OXID
+//
+// History: 27-Mar-95 AlexMit Created
+//
+//--------------------------------------------------------------------
+HRESULT COXIDTable::GetRemUnk(OXIDEntry *pOXIDEntry, IRemUnknown **ppRemUnk)
+{
+ ComDebOut((DEB_OXID, "COXIDTable::GetRemUnk pOXIDEntry:%x ppRemUnk:%x\n",
+ pOXIDEntry, ppRemUnk));
+ ASSERT_LOCK_HELD
+ HRESULT hr = S_OK;
+
+ if (IsMTAThread())
+ {
+ // return the MTA version of the IRemUnknown proxy.
+ if (pOXIDEntry->pRUMTA == NULL)
+ {
+ hr = MakeRemUnk(pOXIDEntry);
+ }
+ *ppRemUnk = pOXIDEntry->pRUMTA;
+ }
+ else
+ {
+ // return the STA version of the IRemUnknown proxy.
+ if (pOXIDEntry->pRUSTA == NULL)
+ {
+ hr = MakeRemUnk(pOXIDEntry);
+ }
+ *ppRemUnk = pOXIDEntry->pRUSTA;
+ }
+
+ ComDebOut((DEB_OXID, "COXIDTable::GetRemUnk pOXIDEntry:%x pRU:%x hr:%x\n",
+ pOXIDEntry, *ppRemUnk, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: COXIDTable::MakeRemUnk, private
+//
+// Synopsis: Create the proxy for the IRemUnknown for the
+// specified OXID and current apartments threading model.
+//
+// History: 27-Mar-95 AlexMit Created
+//
+//--------------------------------------------------------------------
+HRESULT COXIDTable::MakeRemUnk(OXIDEntry *pOXIDEntry)
+{
+ // There is no remote unknown proxy for this entry, get one.
+ // Make up an objref, then unmarshal it to create a proxy to
+ // the remunk object in the server.
+
+ // on the same machine, we ask for the IRundown interface since we may
+ // need the RemChangeRef method. IRundown inherits from IRemUnknown2
+ // and IRemUnknown.
+
+ REFIID riid = (pOXIDEntry->dwFlags & OXIDF_MACHINE_LOCAL)
+ ? IID_IRundown : IID_IRemUnknown;
+
+ OBJREF objref;
+ HRESULT hr = MakeFakeObjRef(objref, pOXIDEntry, pOXIDEntry->ipidRundown, riid);
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ IRemUnknown *pRU = NULL;
+
+ if (SUCCEEDED(hr))
+ {
+ hr = UnmarshalInternalObjRef(objref, (void **)&pRU);
+ }
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ if (SUCCEEDED(hr) && IsMTAThread() && pOXIDEntry->pRUMTA == NULL)
+ {
+ pOXIDEntry->pRUMTA = pRU;
+
+ // need to adjust the internal refcnt on the OXIDEntry, since
+ // the IRemUnknown has an IPID that holds a reference to it.
+ // Dont use DecOXIDRefCnt since that would delete if it was 0.
+
+ Win4Assert(pOXIDEntry->cRefs > 0);
+ pOXIDEntry->cRefs--;
+ }
+ else if (SUCCEEDED(hr) && IsSTAThread() && pOXIDEntry->pRUSTA == NULL)
+ {
+ pOXIDEntry->pRUSTA = pRU;
+
+ // need to adjust the internal refcnt on the OXIDEntry, since
+ // the IRemUnknown has an IPID that holds a reference to it.
+ // Dont use DecOXIDRefCnt since that would delete if it was 0.
+
+ Win4Assert(pOXIDEntry->cRefs > 0);
+ pOXIDEntry->cRefs--;
+ }
+ else if (pRU)
+ {
+ // either setting of the security failed OR, we released the
+ // lock and when we took the lock again some other thread had already
+ // created the proxy. In either case we just release the one we made.
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ pRU->Release();
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+
+ ComDebOut((DEB_OXID, "COXIDTable::GetRemUnk pOXIDEntry:%x pRU:%x hr:%x\n",
+ pOXIDEntry, pRU, hr));
+ return hr;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTbl::GetLocalEntry, public
+//
+// Synopsis: Finds an entry in the OXID table for the local apartment.
+// If no entry exists, it creates an entry, and starts RPC
+// listening if appropriate.
+//
+// History: 20-Feb-95 Rickhi Created
+//
+// Notes: Marshalling the remote unknown causes recursion back to
+// this function. The recursion is terminated because
+// GetLocalOXIDEntry is not NULL on the second call.
+//
+//-------------------------------------------------------------------------
+HRESULT COXIDTable::GetLocalEntry(OXIDEntry **ppEntry)
+{
+ ComDebOut((DEB_OXID, "COXIDTable::GetLocalEntry ppEntry:%x\n", ppEntry));
+ ASSERT_LOCK_HELD
+
+ HRESULT hr = S_OK;
+ MIDEntry *pMIDEntry;
+
+ *ppEntry = GetLocalOXIDEntry();
+
+ if (*ppEntry == NULL && SUCCEEDED(hr = GetLocalMIDEntry(&pMIDEntry)))
+ {
+ // No local OXID entry exists, make one.
+
+ // NOTE: Chicken And Egg Problem.
+ //
+ // Marshaling needs the local OXIDEntry. The local OXIDEntry needs
+ // the local OXID. To get the local OXID we have to call the resolver.
+ // To call the resolver we need the IPID for IRemUnknown. To get the
+ // IPID for IRemUnknown, we need to marshal CRemoteUnknown!
+ //
+ // To get around this problem, we create a local OXIDEntry (that has
+ // a 0 OXID and NULL ipidRemUnknown) so that marshaling can find it.
+ // Then we marshal the RemoteUnknown and extract its IPID value, stick
+ // it in the local OXIDEntry. When we call the resolver (to get some
+ // pre-registered OIDs) we get the real OXID value which we then stuff
+ // in the local OXIDEntry.
+
+ OXID_INFO oxidInfo;
+ oxidInfo.dwTid = (IsMTAThread()) ? 0 : GetCurrentThreadId();
+ oxidInfo.dwPid = GetCurrentProcessId();
+ oxidInfo.ipidRemUnknown = GUID_NULL;
+ oxidInfo.psa = NULL;
+ oxidInfo.dwAuthnHint = RPC_C_AUTHN_LEVEL_NONE;
+
+ // NOTE: temp creation of OXID. We dont know the real OXID until
+ // we call the resolver. So, we use 0 temporarily (it wont conflict
+ // with any other MOXIDs we might be searching for because we already
+ // have the real MID and our local resolver wont give out a 0 OXID).
+ // The OXID will be replaced with the real one when we register
+ // with the resolver in CRpcResolver::ServerAllocateOXIDAndOIDs.
+
+ OXID oxid;
+ memset(&oxid, 0, sizeof(oxid));
+
+ hr = AddEntry(oxid, &oxidInfo, pMIDEntry, ppEntry);
+
+ if (SUCCEEDED(hr))
+ {
+ // Set the local OXID index and marshal IRemUnknown. Note
+ // that the index must be set before we construct the
+ // CRemoteUnknown since that calls MarshalObjRef which
+ // recurses back into GetLocalEntry. Setting the LocalOXID
+ // now allows us to break the recursion.
+
+ SetLocalOXIDEntry(*ppEntry);
+
+ // Create the remote unknown for this apartment. It places
+ // itself in TLS or in the global gpMTARemoteUnknown.
+
+ hr = E_OUTOFMEMORY; // assume OOM
+ CRemoteUnknown *pRemUnk = new CRemoteUnknown(hr,
+ &(*ppEntry)->ipidRundown);
+
+ if (FAILED(hr))
+ {
+ // remove the Local OXID entry. This will also clean up
+ // pRemUnk if the allocation succeeded but ctor failed.
+
+ if (IsSTAThread())
+ {
+ ReleaseLocalSTAEntry();
+ }
+ else
+ {
+ ReleaseLocalMTAEntry();
+ }
+ }
+ }
+ }
+
+ ComDebOut((DEB_OXID, "COXIDTable::GetLocalEntry this:%x pEntry:%x\n",
+ this, *ppEntry));
+ return hr;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTbl::ReleaseLocalSTAEntry, public
+//
+// Synopsis: releases the OXIDEntry for the current STA apartment.
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//+------------------------------------------------------------------------
+void COXIDTable::ReleaseLocalSTAEntry(void)
+{
+ ComDebOut((DEB_OXID, "COXIDTable::ReleaseLocalSTAEntry\n"));
+ Win4Assert(IsSTAThread());
+ ASSERT_LOCK_HELD
+
+ COleTls tls;
+
+ OXIDEntry *pOXIDEntry = (OXIDEntry *)(tls->pOXIDEntry);
+
+ if (pOXIDEntry)
+ {
+ // get the CRemoteUnknown for this apartment.
+ CRemoteUnknown *pRemUnk = tls->pRemoteUnk;
+ tls->pRemoteUnk = NULL;
+
+ // this guy ignores refcounts so we delete him directly.
+ delete pRemUnk;
+
+ // de-register the OXID and OIDs with the resolver.
+ gResolver.ServerFreeOXID(pOXIDEntry);
+
+ // Clear the apartment OXID Entry.
+ tls->pOXIDEntry = NULL;
+
+ // now decrement its count.
+ DecOXIDRefCnt(pOXIDEntry);
+ }
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTbl::ReleaseLocalMTAEntry, public
+//
+// Synopsis: releases the OXIDEntry for the current apartment.
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//+------------------------------------------------------------------------
+void COXIDTable::ReleaseLocalMTAEntry(void)
+{
+ ComDebOut((DEB_OXID, "COXIDTable::ReleaseLocalMTAEntry\n"));
+ ASSERT_LOCK_HELD
+
+ OXIDEntry *pOXIDEntry = gpMTAOXIDEntry;
+
+ if (pOXIDEntry)
+ {
+ // get the CRemoteUnknown for this apartment.
+ CRemoteUnknown *pRemUnk = gpMTARemoteUnknown;;
+ gpMTARemoteUnknown = NULL;
+
+ // this guy ignores refcounts so we delete him directly.
+ delete pRemUnk;
+
+ // de-register the OXID and OIDs with the resolver.
+ gResolver.ServerFreeOXID(pOXIDEntry);
+
+ // Clear the MTA apartment OXID Entry.
+ gpMTAOXIDEntry = NULL;
+
+ // now decrement its count.
+ DecOXIDRefCnt(pOXIDEntry);
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: FindOrCreateOXIDEntry
+//
+// Synopsis: finds or adds an OXIDEntry for the given OXID. May
+// also create a MIDEntry if one does not yet exist.
+//
+// History: 22-Jan-96 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT FindOrCreateOXIDEntry(REFOXID roxid,
+ OXID_INFO &oxidInfo,
+ FOCOXID eResolverRef,
+ DUALSTRINGARRAY *psaResolver,
+ REFMID rmid,
+ MIDEntry *pMIDEntry,
+ OXIDEntry **ppOXIDEntry)
+{
+ ComDebOut((DEB_OXID,"FindOrCreateOXIDEntry oxid:%08x %08x oxidInfo:%x psa:%ws pMIDEntry:%x\n",
+ roxid, &oxidInfo, psaResolver, pMIDEntry));
+ gOXIDTbl.ValidateOXID();
+ ASSERT_LOCK_HELD
+
+ HRESULT hr = S_OK;
+
+ // check if the OXIDEntry was created while we were resolving it.
+ *ppOXIDEntry = gOXIDTbl.LookupOXID(roxid, rmid);
+
+ if (*ppOXIDEntry == NULL)
+ {
+ BOOL fReleaseMIDEntry = FALSE;
+
+ if (pMIDEntry == NULL)
+ {
+ // dont yet have a MIDEntry for the machine so go add it
+ hr = gMIDTbl.FindOrCreateMIDEntry(rmid, psaResolver, &pMIDEntry);
+ fReleaseMIDEntry = TRUE;
+ }
+
+ if (pMIDEntry)
+ {
+ // add a new the OXIDEntry
+ hr = gOXIDTbl.AddEntry(roxid, &oxidInfo, pMIDEntry, ppOXIDEntry);
+
+ if (fReleaseMIDEntry)
+ {
+ // undo the reference added by FindOrCreateMIDEntry
+ DecMIDRefCnt(pMIDEntry);
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr) && eResolverRef == FOCOXID_REF)
+ {
+ // Increment the count of references handed to us from the resolver.
+ (*ppOXIDEntry)->cResolverRef += 1;
+ }
+
+ gOXIDTbl.ValidateOXID();
+ ComDebOut((DEB_OXID,"FindOrCreateOXIDEntry pOXIDEntry:%x hr:%x\n",
+ *ppOXIDEntry, hr));
+ ASSERT_LOCK_HELD
+ return hr;
+}
+
+//+------------------------------------------------------------------------
+//
+// Function: GetLocalOXIDEntry
+//
+// Synopsis: Get either the global or the TLS OXIDEntry based on the
+// threading model of the current thread.
+//
+// History: 05-May-95 AlexMit Created
+//
+//-------------------------------------------------------------------------
+OXIDEntry *GetLocalOXIDEntry()
+{
+ ASSERT_LOCK_HELD
+
+ COleTls tls;
+ if (tls->dwFlags & OLETLS_APARTMENTTHREADED)
+ return (OXIDEntry *)(tls->pOXIDEntry);
+
+ return gpMTAOXIDEntry;
+}
+
+//+------------------------------------------------------------------------
+//
+// Function: SetLocalOXIDEntry
+//
+// Synopsis: Set either the global or the TLS OXIDEntry based on the
+// threading model of the current thread.
+//
+// History: 05-May-95 AlexMit Created
+//
+//-------------------------------------------------------------------------
+void SetLocalOXIDEntry(OXIDEntry *pOXIDEntry)
+{
+ ASSERT_LOCK_HELD
+
+ COleTls tls;
+ if (tls->dwFlags & OLETLS_APARTMENTTHREADED)
+ {
+ tls->pOXIDEntry = (void *)pOXIDEntry;
+ return;
+ }
+
+ gpMTAOXIDEntry = pOXIDEntry;
+}
+
+//+------------------------------------------------------------------------
+//
+// Function: CoGetTidFromIPID
+//
+// Synopsis: Take an IPID and return the thread id the object is on.
+// MSWMSG calls this function during dispatches.
+//
+//-------------------------------------------------------------------------
+STDAPI_(DWORD) CoGetTIDFromIPID( UUID *pIPID )
+{
+ DWORD iTid = 0;
+ LOCK
+
+ IPIDEntry *pEntry = gIPIDTbl.LookupIPID( *pIPID );
+ if (pEntry != NULL && pEntry->pOXIDEntry != NULL)
+ {
+ iTid = pEntry->pOXIDEntry->dwTid;
+ }
+
+ UNLOCK
+ return iTid;
+}
+
+//+------------------------------------------------------------------------
+//
+// Function: CleanupMIDEntry
+//
+// Synopsis: Called by the MID hash table when cleaning up any leftover
+// entries.
+//
+// History: 02-Feb-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void CleanupMIDEntry(SHashChain *pNode)
+{
+ gMIDTbl.ReleaseEntry((MIDEntry *)pNode);
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CMIDTbl::Initialize, public
+//
+// Synopsis: Initializes the MID table.
+//
+// History: 02-Feb-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void CMIDTable::Initialize()
+{
+ ComDebOut((DEB_OXID, "CMIDTable::Initialize\n"));
+ _HashTbl.Initialize(MIDBuckets);
+ _palloc.Initialize(sizeof(MIDEntry), MIDS_PER_PAGE);
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CMIDTbl::Cleanup, public
+//
+// Synopsis: Cleanup the MID table.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void CMIDTable::Cleanup()
+{
+ ComDebOut((DEB_OXID, "CMIDTable::Cleanup\n"));
+ _HashTbl.Cleanup(CleanupMIDEntry);
+ _palloc.Cleanup();
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CMIDTable::FindOrCreateMIDEntry, public
+//
+// Synopsis: Looks for existing copy of the string array in the MID table,
+// creates one if not found
+//
+// History: 05-Jan-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+HRESULT CMIDTable::FindOrCreateMIDEntry(REFMID rmid,
+ DUALSTRINGARRAY *psaResolver,
+ MIDEntry **ppMIDEntry)
+{
+ ComDebOut((DEB_OXID, "CMIDTable::FindOrCreateMIDEntry psa:%x\n", psaResolver));
+ Win4Assert(psaResolver != NULL);
+ ASSERT_LOCK_HELD
+
+ HRESULT hr = S_OK;
+ DWORD dwHash;
+
+ *ppMIDEntry = LookupMID(psaResolver, &dwHash);
+
+ if (*ppMIDEntry == NULL)
+ {
+ hr = AddMIDEntry(rmid, dwHash, psaResolver, ppMIDEntry);
+ }
+
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_OXID, "CMIDTable::FindOrCreateEntry pMIDEntry:%x hr:%x\n", *ppMIDEntry, hr));
+ return hr;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CMIDTable::LookupMID, public
+//
+// Synopsis: Looks for existing copy of the string array in the MID table.
+//
+// History: 05-Jan-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+MIDEntry *CMIDTable::LookupMID(DUALSTRINGARRAY *psaResolver, DWORD *pdwHash)
+{
+ ComDebOut((DEB_OXID, "CMIDTable::LookupMID psa:%x\n", psaResolver));
+ Win4Assert(psaResolver != NULL);
+ ASSERT_LOCK_HELD
+
+ *pdwHash = _HashTbl.Hash(psaResolver);
+ MIDEntry *pMIDEntry = (MIDEntry *) _HashTbl.Lookup(*pdwHash, psaResolver);
+
+ if (pMIDEntry)
+ {
+ // found the node, AddRef it and return
+ IncMIDRefCnt(pMIDEntry);
+ }
+
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_OXID, "CMIDTable::LookupMID pMIDEntry:%x\n", pMIDEntry));
+ return pMIDEntry;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CMIDTable::AddEntry, public
+//
+// Synopsis: Adds an entry to the MID table. The entry is AddRef'd.
+//
+// History: 05-Jan-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+HRESULT CMIDTable::AddMIDEntry(REFMID rmid, DWORD dwHash,
+ DUALSTRINGARRAY *psaResolver,
+ MIDEntry **ppMIDEntry)
+{
+ ComDebOut((DEB_OXID, "CMIDTable::AddMIDEntry rmid:%08x %08x dwHash:%x psa:%x\n",
+ rmid, dwHash, psaResolver));
+ Win4Assert(psaResolver != NULL);
+ ASSERT_LOCK_HELD
+
+ // We must make a copy of the psa to store in the table, since we are
+ // using the one read in from ReadObjRef (or allocated by MIDL).
+
+ DUALSTRINGARRAY *psaNew;
+ HRESULT hr = CopyStringArray(psaResolver, NULL, &psaNew);
+ if (FAILED(hr))
+ return hr;
+
+ MIDEntry *pMIDEntry = (MIDEntry *) _palloc.AllocEntry();
+
+ if (pMIDEntry)
+ {
+ pMIDEntry->cRefs = 1;
+ pMIDEntry->dwFlags = 0;
+ pMIDEntry->mid = rmid;
+
+ // add the entry to the hash table
+ _HashTbl.Add(dwHash, psaNew, &pMIDEntry->Node);
+
+ hr = S_OK;
+
+ // set the maximum size of any resolver PSA we have seen. This is used
+ // when computing the max marshal size during interface marshaling.
+
+ DWORD dwpsaSize = SASIZE(psaNew->wNumEntries);
+ if (dwpsaSize > gdwPsaMaxSize)
+ {
+ gdwPsaMaxSize = dwpsaSize;
+ }
+ }
+ else
+ {
+ // cant create a MIDEntry, free the copy of the string array.
+ PrivMemFree(psaNew);
+ hr = E_OUTOFMEMORY;
+ }
+
+ *ppMIDEntry = pMIDEntry;
+
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_OXID, "CMIDTable::AddMIDEntry pMIDEntry:%x hr:%x\n", *ppMIDEntry, hr));
+ return hr;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CMIDTable::ReleaseEntry, public
+//
+// Synopsis: remove the MIDEntry from the hash table and free the memory
+//
+// History: 05-Jan-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void CMIDTable::ReleaseEntry(MIDEntry *pMIDEntry)
+{
+ ComDebOut((DEB_OXID, "CMIDTable::ReleaseEntry pMIDEntry:%x\n", pMIDEntry));
+ Win4Assert(pMIDEntry->cRefs == 0);
+ ASSERT_LOCK_HELD
+
+ // delete the string array
+ PrivMemFree(pMIDEntry->Node.psaKey);
+
+ // remove from the hash chain and delete the node
+ _HashTbl.Remove(&pMIDEntry->Node.chain);
+
+ _palloc.ReleaseEntry((PageEntry *)pMIDEntry);
+}
+
+//+------------------------------------------------------------------------
+//
+// Function: DecMIDRefCnt, public
+//
+// Synopsis: release one reference to the MIDEntry and release
+// the entry if the count goes to zero.
+//
+// History: 05-Jan-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void DecMIDRefCnt(MIDEntry *pMIDEntry)
+{
+ Win4Assert(pMIDEntry);
+ ASSERT_LOCK_HELD
+
+ ComDebOut((DEB_OXID,
+ "DecMIDRefCnt pMIDEntry:%x cRefs[%x]\n", pMIDEntry, pMIDEntry->cRefs-1));
+
+ pMIDEntry->cRefs--;
+ if (pMIDEntry->cRefs == 0)
+ {
+ gMIDTbl.ReleaseEntry(pMIDEntry);
+ }
+}
+
+//+------------------------------------------------------------------------
+//
+// Function: GetLocalMIDEntry
+//
+// Synopsis: Get or create the MID (Machine ID) entry for the local
+// machine. gpLocalMIDEntry holds the network address for the
+// local OXID resolver.
+//
+// History: 05-Jan-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+HRESULT GetLocalMIDEntry(MIDEntry **ppMIDEntry)
+{
+ ASSERT_LOCK_HELD
+ HRESULT hr = S_OK;
+
+ if (gpLocalMIDEntry == NULL)
+ {
+ // make sure we have the local resolver string bindings
+ RPC_STATUS sc = gResolver.GetConnection();
+ if (sc == RPC_S_OK)
+ {
+ // Create a MID entry for the Local Resolver
+ hr = gMIDTbl.FindOrCreateMIDEntry(gLocalMid, gpsaLocalResolver,
+ &gpLocalMIDEntry);
+ }
+ else
+ {
+ hr = MAKE_SCODE(SEVERITY_ERROR, FACILITY_WIN32, sc);
+ }
+ }
+
+ *ppMIDEntry = gpLocalMIDEntry;
+ return hr;
+}
diff --git a/private/ole32/com/dcomrem/ipidtbl.hxx b/private/ole32/com/dcomrem/ipidtbl.hxx
new file mode 100644
index 000000000..04962ea79
--- /dev/null
+++ b/private/ole32/com/dcomrem/ipidtbl.hxx
@@ -0,0 +1,485 @@
+//+------------------------------------------------------------------------
+//
+// File: ipidtbl.hxx
+//
+// Contents: MID (machine identifier) table.
+// OXID (object exporter identifier) table.
+// IPID (interface pointer identifier) table.
+//
+// Classes: CMIDTable
+// COXIDTable
+// CIPIDTable
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+#ifndef _IPIDTBL_HXX_
+#define _IPIDTBL_HXX_
+
+#include <pgalloc.hxx> // CPageAllocator
+#include <lclor.h> // local OXID resolver interface
+#include <remoteu.hxx> // CRemoteUnknown
+#include <locks.hxx> // ASSERT_LOCK_HELD
+#include <hash.hxx> // CStringHashTable
+
+
+// forward declarations
+class CRpcChannelBuffer;
+
+
+//+------------------------------------------------------------------------
+//
+// This structure defines an Entry in the MID table. There is one MID
+// table for the entire process. There is one MIDEntry per machine that
+// the current process is talking to (including one for the local machine).
+//
+//-------------------------------------------------------------------------
+typedef struct tagMIDEntry
+{
+ SStringHashNode Node; // hash chain and key
+ MID mid; // machine identifier
+ LONG cRefs; // count of IPIDs using this OXIDEntry
+ DWORD dwFlags; // state flags
+} MIDEntry;
+
+// MID Table constants. MIDS_PER_PAGE is the number of MIDEntries
+// in one page of the page allocator.
+
+#define MIDS_PER_PAGE 5
+
+
+//+------------------------------------------------------------------------
+//
+// class: CMIDTable
+//
+// Synopsis: Table of Machine IDs (MIDs) and associated information.
+//
+// History: 05-Jan-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+class CMIDTable
+{
+public:
+ void Initialize(); // initialize table
+ void Cleanup(); // cleanup table
+
+ HRESULT FindOrCreateMIDEntry(REFMID rmid,
+ DUALSTRINGARRAY *psaResolver,
+ MIDEntry **ppMIDEntry);
+
+ MIDEntry *LookupMID(DUALSTRINGARRAY *psaResolver, DWORD *pdwHash);
+
+ void ReleaseEntry(MIDEntry *pMIDEntry);
+
+private:
+ HRESULT AddMIDEntry(REFMID rmid,
+ DWORD dwHash,
+ DUALSTRINGARRAY *psaResolver,
+ MIDEntry **ppMIDEntry);
+
+ static CStringHashTable _HashTbl; // hash table for MIDEntries
+ static CPageAllocator _palloc; // page based allocator
+};
+
+
+
+//+------------------------------------------------------------------------
+//
+// This structure defines an Entry in the OXID table. There is one OXID
+// table for the entire process. There is one OXIDEntry per apartment.
+//
+//-------------------------------------------------------------------------
+typedef struct tagOXIDEntry
+{
+ struct tagOXIDEntry *pPrev; // previous entry on inuse list
+ struct tagOXIDEntry *pNext; // next entry on free/inuse list
+ DWORD dwPid; // process id of server
+ DWORD dwTid; // thread id of server
+ MOXID moxid; // object exporter identifier + machine id
+ IPID ipidRundown;// IPID of IRundown and Remote Unknown
+ DWORD dwFlags; // state flags
+ handle_t hServerSTA; // rpc binding handle of server
+ handle_t hServerMTA; // rpc binding handle of server
+ MIDEntry *pMIDEntry; // MIDEntry for machine where server lives
+ IRemUnknown *pRUSTA; // STA model proxy for Remote Unknown
+ IRemUnknown *pRUMTA; // MTA model proxy for Remote Unknown
+ LONG cRefs; // count of IPIDs using this OXIDEntry
+ LONG cWaiters; // count of threads waiting for OIDs
+ HANDLE hComplete; // set when last outstanding call completes
+ LONG cCalls; // number of calls dispatched
+ LONG cResolverRef;//References to resolver
+ DWORD dwPad; // keep structure 16 byte aligned
+} OXIDEntry;
+
+// bit flags for dwFlags of OXIDEntry
+typedef enum tagOXIDFLAGS
+{
+ OXIDF_REGISTERED = 0x1, // oxid is registered with Resolver
+ OXIDF_MACHINE_LOCAL = 0x2, // oxid is local to this machine
+ OXIDF_STOPPED = 0x4, // thread can no longer receive calls
+ OXIDF_PENDINGRELEASE = 0x8, // oxid entry is already being released
+ OXIDF_MSWMSG = 0x10, // use mswmsg transport
+ OXIDF_REGISTERINGOIDS= 0x20, // a thread is busy registering OIDs
+ OXIDF_MTASERVER = 0x40 // the server is an MTA apartment.
+} OXIDFLAGS;
+
+// Parameter to FindOrCreateOXIDEntry
+typedef enum tagFOCOXID
+{
+ FOCOXID_REF = 1, // Got reference from resolver
+ FOCOXID_NOREF = 2 // No reference from resolver
+} FOCOXID;
+
+// OXID Table constants.
+#define OXIDS_PER_PAGE 10
+#define OXIDTBL_MAXEXPIRED 5 // max number of expired entries to keep
+
+
+//+------------------------------------------------------------------------
+//
+// class: COXIDTable
+//
+// Synopsis: Maintains a table of OXIDs and associated information
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+class COXIDTable
+{
+public:
+ HRESULT AddEntry(REFOXID roxid, OXID_INFO *poxidInfo,
+ MIDEntry *pMIDEntry, OXIDEntry **ppEntry);
+
+ void ReleaseEntry(OXIDEntry *pEntry);
+
+ HRESULT GetLocalEntry(OXIDEntry **ppEntry);
+ void ReleaseLocalSTAEntry(void);
+ void ReleaseLocalMTAEntry(void);
+ OXIDEntry *LookupOXID(REFOXID roxid, REFMID rmid);
+
+ HRESULT GetRemUnk(OXIDEntry *pOXIDEntry, IRemUnknown **ppRemUnk);
+
+ void Initialize(); // initialize table
+ void Cleanup(); // cleanup table
+ void FreeExpiredEntries(DWORD dwTime);
+ void ValidateOXID();
+ void FreeCleanupEntries();
+ DWORD NumOxidsToRemove();
+ void GetOxidsToRemove( OXID_REF *pRef, DWORD *pNum );
+
+private:
+
+ void ExpireEntry(OXIDEntry *pEntry);
+ OXIDEntry *SearchList(REFMOXID rmoxid, OXIDEntry *pStart);
+ HRESULT MakeRemUnk(OXIDEntry *pOXIDEntry);
+ void AssertListsEmpty(void);
+
+ static DWORD _cExpired; // count of expired entries
+ static OXIDEntry _InUseHead; // head of InUse list.
+ static OXIDEntry _ExpireHead; // head of Expire list.
+ static OXIDEntry _CleanupHead; // head of Cleanup list.
+
+ static CPageAllocator _palloc; // page alloctor
+
+ // PERFWORK: could save space since only the first two entries of
+ // the InUseHead and ExpireHead are used (the list ptrs) and hence
+ // dont need whole OXIDEntries here.
+};
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTbl::ValidateOXID, public
+//
+// Synopsis: Asserts that no OXIDEntries have trashed window handles.
+//
+//-------------------------------------------------------------------------
+inline void COXIDTable::ValidateOXID()
+{
+#if DBG==1
+ LOCK
+
+ // Check all entries in use.
+ OXIDEntry *pCurr = _InUseHead.pNext;
+ while (pCurr != &_InUseHead)
+ {
+ Win4Assert( pCurr->hServerSTA != (void *) 0xC000001C );
+ Win4Assert( pCurr->hServerMTA != (void *) 0xC000001C );
+ pCurr = pCurr->pNext;
+ }
+ UNLOCK
+#endif
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: COXIDTbl::AssertListsEmpty, public
+//
+// Synopsis: Asserts that no OXIDEntries are in use
+//
+// History: 19-Apr-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+inline void COXIDTable::AssertListsEmpty(void)
+{
+ // Assert that there are no entries in the InUse or Expired lists.
+ Win4Assert(_InUseHead.pNext == &_InUseHead);
+ Win4Assert(_InUseHead.pPrev == &_InUseHead);
+ Win4Assert(_ExpireHead.pNext == &_ExpireHead);
+ Win4Assert(_ExpireHead.pPrev == &_ExpireHead);
+}
+
+
+
+//+------------------------------------------------------------------------
+//
+// This structure defines an Entry in the IPID table. There is one
+// IPID table for the entire process. It holds IPIDs from local objects
+// as well as remote objects.
+//
+//-------------------------------------------------------------------------
+typedef struct tagIPIDEntry
+{
+ struct tagIPIDEntry *pNextOID; // next IPIDEntry for same object
+ DWORD dwFlags; // flags (see IPIDFLAGS)
+ ULONG cStrongRefs; // strong reference count
+ ULONG cWeakRefs; // weak reference count
+ ULONG cPrivateRefs;// private reference count
+ CRpcChannelBuffer *pChnl; // channel pointer
+ IUnknown *pStub; // proxy or stub pointer
+ OXIDEntry *pOXIDEntry; // ptr to OXIDEntry in OXID Table
+ IPID ipid; // interface pointer identifier
+ IID iid; // interface iid
+ void *pv; // real interface pointer
+ DWORD pad[3]; // round size to modulus 16
+} IPIDEntry;
+
+// bit flags for dwFlags of IPIDEntry
+typedef enum tagIPIDFLAGS
+{
+ IPIDF_CONNECTING = 0x1, // ipid is being connected
+ IPIDF_DISCONNECTED = 0x2, // ipid is disconnected
+ IPIDF_SERVERENTRY = 0x4, // SERVER IPID vs CLIENT IPID
+ IPIDF_NOPING = 0x8, // dont need to ping the server or release
+ IPIDF_COPY = 0x10, // copy for security only
+ IPIDF_VACANT = 0x80, // entry is vacant (ie available to reuse)
+ IPIDF_NONNDRSTUB = 0x100, // stub does not use NDR marshaling
+ IPIDF_NONNDRPROXY = 0x200, // proxy does not use NDR marshaling
+ IPIDF_NOTIFYACT = 0x400 // notify activation on marshal/release
+} IPIDFLAGS;
+
+
+// IPID Table constants. IPIDS_PER_PAGE is the number of IPIDEntries
+// in one page of the page allocator.
+
+#define IPIDS_PER_PAGE 50
+
+//+------------------------------------------------------------------------
+//
+// class: CIPIDTbl
+//
+// Synopsis: Maintains a table of IPIDs and associated information
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+class CIPIDTable
+{
+public:
+ IPIDEntry *LookupIPID(REFIPID ripid); // find entry in the table with
+ // the matching ipid
+
+ IPIDEntry *FirstFree(void);
+ void ReleaseEntryList(IPIDEntry *pFirst, IPIDEntry *pLast);
+ IPIDEntry *GetEntryPtr(LONG iEntry);
+ LONG GetEntryIndex(IPIDEntry *pEntry);
+
+#if DBG==1
+ void AssertValid(void) {;}
+ void ValidateIPIDEntry(IPIDEntry *pEntry, BOOL fServerSide,
+ CRpcChannelBuffer *pChnl);
+#else
+ void AssertValid(void) {;}
+ void ValidateIPIDEntry(IPIDEntry *pEntry, BOOL fServerSide,
+ CRpcChannelBuffer *pChnl) {;}
+#endif
+
+ void Initialize(); // initialize table
+ void Cleanup(); // cleanup table
+
+private:
+ static CPageAllocator _palloc; // page alloctor
+};
+
+
+//+------------------------------------------------------------------------
+//
+// Global Externals
+//
+//+------------------------------------------------------------------------
+
+extern CMIDTable gMIDTbl; // global table, defined in ipidtbl.cxx
+extern COXIDTable gOXIDTbl; // global table, defined in ipidtbl.cxx
+extern CIPIDTable gIPIDTbl; // global table, defined in ipidtbl.cxx
+extern MIDEntry *gpLocalMIDEntry; // ptr to MIDEntry for current process
+extern OXIDEntry *gpMTAOXIDEntry; // ptr to local OXIDEntry in MTA
+extern DUALSTRINGARRAY *gpsaLocalResolver; // bindings for local OXID resolver.
+
+//+------------------------------------------------------------------------
+//
+// Function Prototypes
+//
+//+------------------------------------------------------------------------
+
+HRESULT GetLocalMIDEntry(MIDEntry **ppMIDEntry);
+OXIDEntry *GetLocalOXIDEntry();
+void SetLocalOXIDEntry(OXIDEntry *pOXIDEntry);
+void DecOXIDRefCnt(OXIDEntry *pEntry);
+void DecMIDRefCnt(MIDEntry *pEntry);
+
+HRESULT FindOrCreateOXIDEntry(REFOXID roxid,
+ OXID_INFO &oxidInfo,
+ FOCOXID eReferenced,
+ DUALSTRINGARRAY *psaResolver,
+ REFMID rmid,
+ MIDEntry *pMIDEntry,
+ OXIDEntry **ppOXIDEntry);
+
+
+//+------------------------------------------------------------------------
+//
+// Member: CIPIDTbl::FirstFree, public
+//
+// Synopsis: Finds the first available entry in the table and returns
+// its index. Returns -1 if no space is available and it
+// cant grow the list.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+inline IPIDEntry *CIPIDTable::FirstFree()
+{
+ return (IPIDEntry *) _palloc.AllocEntry();
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CIPIDTbl::GetEntryIndex, public
+//
+// Synopsis: Converts an entry ptr into an entry index
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+inline LONG CIPIDTable::GetEntryIndex(IPIDEntry *pIPIDEntry)
+{
+ return _palloc.GetEntryIndex((PageEntry *)pIPIDEntry);
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CIPIDTbl::GetEntryPtr, public
+//
+// Synopsis: Converts an entry index into an entry pointer
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+inline IPIDEntry *CIPIDTable::GetEntryPtr(LONG index)
+{
+ return (IPIDEntry *) _palloc.GetEntryPtr(index);
+}
+
+
+
+//+------------------------------------------------------------------------
+//
+// Function: IncOXIDRefCnt, public
+//
+// Synopsis: increment the number of references to the OXIDEntry
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+inline void IncOXIDRefCnt(OXIDEntry *pEntry)
+{
+ Win4Assert(pEntry);
+ ASSERT_LOCK_HELD
+
+ ComDebOut((DEB_OXID,
+ "IncOXIDRefCnt pEntry:%x cRefs[%x]\n", pEntry, pEntry->cRefs+1));
+
+ pEntry->cRefs++;
+}
+
+//+------------------------------------------------------------------------
+//
+// Function: IncMIDRefCnt, public
+//
+// Synopsis: increment the number of references to the MIDEntry
+//
+// History: 05-Janb-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+inline void IncMIDRefCnt(MIDEntry *pEntry)
+{
+ Win4Assert(pEntry);
+ ASSERT_LOCK_HELD
+
+ ComDebOut((DEB_OXID,
+ "IncMIDRefCnt pEntry:%x cRefs[%x]\n", pEntry, pEntry->cRefs+1));
+
+ pEntry->cRefs++;
+}
+
+//+------------------------------------------------------------------------
+//
+// Function: MOXIDFromOXIDAndMID, public
+//
+// Synopsis: creates a MOXID (machine and object exporter ID) from
+// the individual OXID and MID components
+//
+// History: 05-Janb-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+inline void MOXIDFromOXIDAndMID(REFOXID roxid, REFMID rmid, MOXID *pmoxid)
+{
+ BYTE *pb = (BYTE *)pmoxid;
+ memcpy(pb, &roxid, sizeof(OXID));
+ memcpy(pb+8, &rmid, sizeof(MID));
+}
+
+//+------------------------------------------------------------------------
+//
+// Function: OXIDFromMOXID, public
+//
+// Synopsis: extracts the OXID from a MOXID (machine and OXID)
+//
+// History: 05-Jan-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+inline void OXIDFromMOXID(REFMOXID rmoxid, OXID *poxid)
+{
+ memcpy(poxid, (BYTE *)&rmoxid, sizeof(OXID));
+}
+
+//+------------------------------------------------------------------------
+//
+// Function: MIDFromMOXID, public
+//
+// Synopsis: extracts the MID from a MOXID (machine and OXID)
+//
+// History: 05-Jan-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+inline void MIDFromMOXID(REFMOXID rmoxid, OXID *pmid)
+{
+ memcpy(pmid, ((BYTE *)&rmoxid)+8, sizeof(MID));
+}
+
+// OID + MID versions of the above routines.
+
+#define MOIDFromOIDAndMID MOXIDFromOXIDAndMID
+#define OIDFromMOID OXIDFromMOXID
+#define MIDFromMOID MIDFromMOXID
+
+#endif // _IPIDTBL_HXX_
diff --git a/private/ole32/com/dcomrem/ipmrshl.cxx b/private/ole32/com/dcomrem/ipmrshl.cxx
new file mode 100644
index 000000000..1833d2b45
--- /dev/null
+++ b/private/ole32/com/dcomrem/ipmrshl.cxx
@@ -0,0 +1,652 @@
+//+-------------------------------------------------------------------
+//
+// File: ipmrshl.cpp
+//
+// Contents: Code the implements the standard free thread in process
+// marshaler.
+//
+// Classes: CFreeMarshaler
+// CFmCtrlUnknown
+//
+// Functions: CoCreateFreeThreadedMarshaler
+//
+// History: 03-Nov-94 Ricksa
+//
+//--------------------------------------------------------------------
+#include <ole2int.h>
+#include <stdid.hxx>
+
+//+-------------------------------------------------------------------
+//
+// Class: CFreeMarshaler
+//
+// Synopsis: Generic marshaling class
+//
+// Methods: IUnknown
+// IMarshal
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+class CFreeMarshaler : public IMarshal, public CPrivAlloc
+{
+public:
+ CFreeMarshaler(IUnknown *punk);
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, void FAR * FAR * ppv);
+ STDMETHODIMP_(ULONG) AddRef(void);
+ STDMETHODIMP_(ULONG) Release(void);
+
+ // IMarshal Interface
+ STDMETHODIMP GetUnmarshalClass(
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags,
+ CLSID *pCid);
+
+ STDMETHODIMP GetMarshalSizeMax(
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags,
+ DWORD *pSize);
+
+ STDMETHODIMP MarshalInterface(
+ IStream __RPC_FAR *pStm,
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags);
+
+ STDMETHODIMP UnmarshalInterface(
+ IStream *pStm,
+ REFIID riid,
+ void **ppv);
+
+ STDMETHODIMP ReleaseMarshalData(IStream *pStm);
+
+ STDMETHODIMP DisconnectObject(DWORD dwReserved);
+
+private:
+
+ friend class CFmCtrlUnknown;
+
+ // Pointer to the controlling unknown.
+ IUnknown * _punkCtrl;
+
+};
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Class: CFmCtrlUnknown
+//
+// Synopsis: Controlling IUnknown for generic marshaling class.
+//
+// Methods: IUnknown
+// IMarshal
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+class CFmCtrlUnknown : public IUnknown, public CPrivAlloc
+{
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, void **ppv);
+
+ STDMETHODIMP_(ULONG) AddRef(void);
+
+ STDMETHODIMP_(ULONG) Release(void);
+
+private:
+
+ friend HRESULT CoCreateFreeThreadedMarshaler(
+ IUnknown *punkCtrl,
+ IUnknown **punkMarshal);
+
+ friend HRESULT GetInProcFreeMarshaler(IMarshal **ppIM);
+
+ CFmCtrlUnknown(void);
+
+ ~CFmCtrlUnknown(void);
+
+ CFreeMarshaler * _pfm;
+
+ ULONG _cRefs;
+};
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CoCreateFreeThreadedMarshaler, public
+//
+// Synopsis: Create the controlling unknown for the marshaler
+//
+// Arguments: [punkOuter] - controlling unknown
+// [ppunkMarshal] - controlling unknown for marshaler.
+//
+// Returns: NOERROR
+// E_INVALIDARG
+// E_OUTOFMEMORY
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+HRESULT CoCreateFreeThreadedMarshaler(
+ IUnknown *punkOuter,
+ IUnknown **ppunkMarshal)
+{
+ HRESULT hr = E_INVALIDARG;
+
+ // Validate the parameters
+ if (((punkOuter == NULL) || IsValidInterface(punkOuter))
+ && IsValidPtrOut(ppunkMarshal, sizeof(IUnknown *)))
+ {
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&punkOuter);
+ // Assume failure
+ *ppunkMarshal = NULL;
+
+ hr = E_OUTOFMEMORY;
+
+ // Allocate new free marshal object
+ CFmCtrlUnknown *pfmc = new CFmCtrlUnknown();
+
+ if (pfmc != NULL)
+ {
+ if (punkOuter == NULL)
+ {
+ // Caller wants a non-aggreagated object
+ punkOuter = pfmc;
+ }
+
+ // Initialize the pointer
+ pfmc->_pfm = new CFreeMarshaler(punkOuter);
+
+ if (pfmc->_pfm != NULL)
+ {
+ *ppunkMarshal = pfmc;
+ CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_IUnknown,
+ (IUnknown **)ppunkMarshal);
+ hr = S_OK;
+ }
+ else
+ {
+ delete pfmc;
+ }
+ }
+ }
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: GetInProcFreeMarshaler, public
+//
+// Synopsis: Create the controlling unknown for the marshaler
+//
+// Arguments: [ppIM] - where to put inproc marshaler
+//
+// Returns: NOERROR
+// E_OUTOFMEMORY
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+HRESULT GetInProcFreeMarshaler(IMarshal **ppIM)
+{
+ HRESULT hr = E_OUTOFMEMORY;
+
+ // Allocate new free marshal object
+ CFmCtrlUnknown *pfmc = new CFmCtrlUnknown();
+
+ if (pfmc != NULL)
+ {
+ // Initialize the pointer
+ pfmc->_pfm = new CFreeMarshaler(pfmc);
+
+ if (pfmc->_pfm != NULL)
+ {
+ *ppIM = pfmc->_pfm;
+ hr = S_OK;
+ }
+ else
+ {
+ delete pfmc;
+ }
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFmCtrlUnknown::CFmCtrlUnknown
+//
+// Synopsis: The constructor for controling IUnknown of free marshaler
+//
+// Arguments: None
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+CFmCtrlUnknown::CFmCtrlUnknown(void) : _cRefs(1), _pfm(NULL)
+{
+ // Header does all the work.
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFmCtrlUnknown::~CFmCtrlUnknown
+//
+// Synopsis: The destructor for controling IUnknown of free marshaler
+//
+// Arguments: None
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+CFmCtrlUnknown::~CFmCtrlUnknown(void)
+{
+ delete _pfm;
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFmCtrlUnknown::QueryInterface
+//
+// Returns: S_OK
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFmCtrlUnknown::QueryInterface(REFIID iid, void **ppv)
+{
+ *ppv = NULL;
+ HRESULT hr = E_NOINTERFACE;
+
+ if (IsEqualGUID(iid, IID_IUnknown))
+ {
+ *ppv = this;
+ AddRef();
+ hr = S_OK;
+ }
+ else if (IsEqualGUID(iid, IID_IMarshal))
+ {
+ *ppv = _pfm;
+ _pfm->AddRef();
+ hr = S_OK;
+ }
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFmCtrlUnknown::AddRef
+//
+// Synopsis: Standard stuff
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CFmCtrlUnknown::AddRef(void)
+{
+ InterlockedIncrement((LONG *) &_cRefs);
+
+ return _cRefs;
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFmCtrlUnknown::Release
+//
+// Synopsis: Standard stuff
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CFmCtrlUnknown::Release(void)
+{
+ ULONG cRefs = InterlockedDecrement((LONG *) &_cRefs);
+
+ if (cRefs == 0)
+ {
+ delete this;
+ }
+
+ return cRefs;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::CFreeMarshaler()
+//
+// Synopsis: The constructor for CFreeMarshaler.
+//
+// Arguments: None
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+CFreeMarshaler::CFreeMarshaler(IUnknown *punkCtrl)
+ : _punkCtrl(punkCtrl)
+{
+ // Header does all the work.
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::QueryInterface
+//
+// Synopsis: Pass QI to our controlling IUnknown
+//
+// Returns: S_OK
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFreeMarshaler::QueryInterface(REFIID iid, void **ppv)
+{
+ return _punkCtrl->QueryInterface(iid, ppv);
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::AddRef
+//
+// Synopsis: Pass AddRef to our controlling IUnknown
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CFreeMarshaler::AddRef(void)
+{
+ return _punkCtrl->AddRef();
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::Release
+//
+// Synopsis: Pass release to our controlling IUnknown
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CFreeMarshaler::Release(void)
+{
+ return _punkCtrl->Release();
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::GetUnmarshalClass
+//
+// Synopsis: Return the unmarshaling class
+//
+// History: 08-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFreeMarshaler::GetUnmarshalClass(
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags,
+ CLSID *pCid)
+{
+ // Inprocess context?
+ if (dwDestContext == MSHCTX_INPROC)
+ {
+ // If this is an inproc marshal then we are the class
+ // that can unmarshal.
+ *pCid = CLSID_InProcFreeMarshaler;
+ return S_OK;
+ }
+
+ // we can just use the static guy here and save a lot of work.
+ IMarshal *pmrshlStd;
+ HRESULT hr = GetStaticUnMarshaler(&pmrshlStd);
+
+ if (pmrshlStd != NULL)
+ {
+ hr = pmrshlStd->GetUnmarshalClass(riid, pv, dwDestContext,
+ pvDestContext, mshlflags, pCid);
+
+ pmrshlStd->Release();
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::GetMarshalSizeMax
+//
+// Synopsis: Return maximum bytes need for marshaling
+//
+// History: 08-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFreeMarshaler::GetMarshalSizeMax(
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags,
+ DWORD *pSize)
+{
+ // Inprocess context?
+ if (dwDestContext == MSHCTX_INPROC)
+ {
+ // If this is an inproc marshal then we know the size
+ *pSize = sizeof(this);
+ return S_OK;
+ }
+
+ // we can just use the static guy here and save a lot of work.
+ IMarshal *pmrshlStd;
+ HRESULT hr = GetStaticUnMarshaler(&pmrshlStd);
+
+ if (pmrshlStd != NULL)
+ {
+ hr = pmrshlStd->GetMarshalSizeMax(riid, pv, dwDestContext,
+ pvDestContext, mshlflags, pSize);
+
+ pmrshlStd->Release();
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::MarshalInterface
+//
+// Synopsis: Marshal the interface
+//
+// History: 08-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFreeMarshaler::MarshalInterface(
+ IStream *pStm,
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags)
+{
+ HRESULT hr;
+
+ // Inprocess context?
+ if (dwDestContext == MSHCTX_INPROC)
+ {
+ // Write the marshal flags into the stream
+ hr = pStm->Write(&mshlflags, sizeof(mshlflags), NULL);
+
+ if (hr == NOERROR)
+ {
+ // Write the pointer into the stream
+ ULONG cb;
+
+ hr = pStm->Write(&pv, sizeof(pv), NULL);
+
+ // Bump reference count based on type of marshal
+ if ((hr == NOERROR) && (mshlflags != MSHLFLAGS_TABLEWEAK))
+ {
+ ((IUnknown *) pv)->AddRef();
+ }
+ }
+
+ return hr;
+ }
+
+ // find or create a stdid for this object. Make sure we get a strong
+ // reference to gaurd against a simultaneous last release by another
+ // thread.
+
+ CStdIdentity *pStdId;
+ hr = LookupIDFromUnk((IUnknown *) pv, IDLF_CREATE | IDLF_STRONG, &pStdId);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pStdId->MarshalInterface(pStm, riid, pv, dwDestContext,
+ pvDestContext, mshlflags);
+
+ pStdId->DecStrongCnt(TRUE); // fKeepAlive
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::UnmarshalInterface
+//
+// Synopsis: Unmarshal the interface
+//
+// History: 08-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFreeMarshaler::UnmarshalInterface(
+ IStream *pStm,
+ REFIID riid,
+ void **ppv)
+{
+ HRESULT hr;
+
+ // The marshal flags will tell us if we have to AddRef the object
+ DWORD mshlflags;
+
+ hr = pStm->Read(&mshlflags, sizeof(mshlflags), NULL);
+
+ if (hr == NOERROR)
+ {
+ // If Inprocess, we just read the pointer out of the stream
+ hr = pStm->Read(ppv, sizeof(*ppv), NULL);
+
+ // AddRef the pointer if marshaled for a table.
+ if ((hr == NOERROR)
+ && ((mshlflags == MSHLFLAGS_TABLEWEAK)
+ || (mshlflags == MSHLFLAGS_TABLESTRONG)))
+ {
+ ((IUnknown *) *ppv)->AddRef();
+ }
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::ReleaseMarshalData
+//
+// Synopsis: Release the marshaled data
+//
+// History: 08-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFreeMarshaler::ReleaseMarshalData(IStream *pStm)
+{
+ // Get the marshal flags
+ DWORD mshlflags;
+
+ HRESULT hr = pStm->Read(&mshlflags, sizeof(mshlflags), NULL);
+
+ if (hr == NOERROR)
+ {
+ IUnknown *punk;
+
+ // If Inprocess, we just read the pointer out of the stream
+ hr = pStm->Read(&punk, sizeof(punk), NULL);
+
+ if ((hr == NOERROR) && (mshlflags != MSHLFLAGS_TABLEWEAK))
+ {
+ // Dump the extra AddRef we put on when we put the object
+ // during marshal.
+ punk->Release();
+ }
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::DisconnectObject
+//
+// Synopsis: Disconnect the object
+//
+// History: 08-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFreeMarshaler::DisconnectObject(DWORD dwReserved)
+{
+ CStdIdentity *pStdId;
+ HRESULT hr = LookupIDFromUnk(_punkCtrl, 0, &pStdId);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pStdId->DisconnectObject(dwReserved);
+ pStdId->Release();
+ }
+ else
+ {
+ // already disconnected, report success
+ hr = S_OK;
+ }
+ return hr;
+}
diff --git a/private/ole32/com/dcomrem/locks.cxx b/private/ole32/com/dcomrem/locks.cxx
new file mode 100644
index 000000000..98244be90
--- /dev/null
+++ b/private/ole32/com/dcomrem/locks.cxx
@@ -0,0 +1,75 @@
+//+-------------------------------------------------------------------
+//
+// File: locks.cxx
+//
+// Contents: functions used in DBG builds to validate the lock state.
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+#include <ole2int.h>
+#include <locks.hxx>
+
+COleStaticMutexSem gComLock;
+
+#if DBG==1
+
+#define MyAssert Win4Assert
+// # define MyAssert(x) if (!(x)) { DebugBreak(); }
+
+struct tagGLOCK
+{
+ DWORD tid; // tid of current holder
+ LONG cLocks; // count of holds on the lock by current holder
+ DWORD line; // line # where lock taken
+ const char *file; // file name where lock taken
+} glock = {0xffffffff, 0, 0xffffffff, 0};
+
+void AssertLockHeld(void)
+{
+ MyAssert(glock.tid == GetCurrentThreadId());
+ MyAssert(glock.cLocks > 0); // && "Lock not Held"
+}
+
+void AssertLockReleased(void)
+{
+ MyAssert(glock.tid != GetCurrentThreadId() && "Lock not Released");
+}
+
+void ORPCLock(DWORD line, const char *file)
+{
+ gComLock.Request();
+
+ if (glock.cLocks > 0)
+ {
+ MyAssert(glock.tid == GetCurrentThreadId());
+ }
+ else
+ {
+ glock.line = line;
+ glock.file = file;
+ }
+
+ glock.tid = GetCurrentThreadId();
+ glock.cLocks++;
+}
+
+void ORPCUnLock(void)
+{
+ MyAssert(glock.cLocks > 0); // && "Releasing Unheld Lock"
+ MyAssert(glock.tid == GetCurrentThreadId());
+
+ glock.cLocks--;
+
+ if (glock.cLocks == 0)
+ {
+ // we no longer hold the lock, set the tid to zero
+ glock.tid = 0;
+ }
+
+ gComLock.Release();
+}
+
+#endif // DBG
+
+
diff --git a/private/ole32/com/dcomrem/locks.hxx b/private/ole32/com/dcomrem/locks.hxx
new file mode 100644
index 000000000..dfe84d437
--- /dev/null
+++ b/private/ole32/com/dcomrem/locks.hxx
@@ -0,0 +1,48 @@
+//+-------------------------------------------------------------------
+//
+// File: locks.hxx
+//
+// Contents: class and marcros for providing mutual exclusion
+//
+// Classes: CStaticSem
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+#ifndef _ORPC_LOCKS_
+#define _ORPC_LOCKS_
+
+#include "olesem.hxx"
+
+// global mutex for ORPC
+extern COleStaticMutexSem gComLock;
+
+
+//+---------------------------------------------------------------------------
+//
+// Macros for use in the code.
+//
+//----------------------------------------------------------------------------
+
+#if DBG==1
+void AssertLockHeld(void);
+void AssertLockReleased(void);
+void ORPCLock(DWORD line, const char *file);
+void ORPCUnLock(void);
+
+#define LOCK ORPCLock(__LINE__, __FILE__);
+#define UNLOCK ORPCUnLock();
+#define ASSERT_LOCK_HELD AssertLockHeld();
+#define ASSERT_LOCK_RELEASED AssertLockReleased();
+#define ASSERT_LOCK_DONTCARE // just exists to comment the code better
+
+#else
+
+#define LOCK gComLock.Request();
+#define UNLOCK gComLock.Release();
+#define ASSERT_LOCK_HELD
+#define ASSERT_LOCK_RELEASED
+#define ASSERT_LOCK_DONTCARE
+
+#endif // DBG
+#endif // _ORPC_LOCKS_
diff --git a/private/ole32/com/dcomrem/makefile b/private/ole32/com/dcomrem/makefile
new file mode 100644
index 000000000..e09078703
--- /dev/null
+++ b/private/ole32/com/dcomrem/makefile
@@ -0,0 +1,24 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+!include $(CAIROLE)\com\makefile
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/com/dcomrem/mapdwp.hxx b/private/ole32/com/dcomrem/mapdwp.hxx
new file mode 100644
index 000000000..76f904e95
--- /dev/null
+++ b/private/ole32/com/dcomrem/mapdwp.hxx
@@ -0,0 +1,108 @@
+//+-------------------------------------------------------------------
+//
+// File: mapdwp.hxx
+//
+// Contents: Class to map thread id to thread local storage ptr
+//
+// Classes: CMapDword
+//
+// Notes: This class is needed soley for debug builds and then only
+// because we dont get THREAD_DETACH notification for all
+// threads when a process exits. This allows us to clean up
+// the tls so we dont report memory leaks.
+//
+// In order to keep the implementation simple, we use a fixed
+// array of entries, meaning we (may) get memory leaks
+// reported if we ever have more than MAP_MAX_SIZE threads
+// alive at any given time.
+//
+//+-------------------------------------------------------------------
+
+#if !defined(_CAIRO_) && DBG==1
+
+#define MAP_MAX_SIZE 100
+
+class CMapDword : public CPrivAlloc
+{
+public:
+ CMapDword(void);
+ ~CMapDword(void);
+
+ void SetAt(DWORD tid, void *pData);
+ void RemoveKey(DWORD tid);
+ void RemoveAll(void);
+
+private:
+
+ DWORD _tid[MAP_MAX_SIZE];
+ void * _pData[MAP_MAX_SIZE];
+ DWORD _index;
+};
+
+
+CMapDword::CMapDword(void)
+{
+ _index = 0;
+ memset(_tid, 0, MAP_MAX_SIZE * sizeof(DWORD));
+}
+
+CMapDword::~CMapDword(void)
+{
+ RemoveAll();
+}
+
+void CMapDword::SetAt(DWORD tid, void *pData)
+{
+ for (ULONG i=_index; i<MAP_MAX_SIZE; i++)
+ {
+ if (_tid[i] == 0)
+ {
+ _tid[i] = tid;
+ _pData[i] = pData;
+ _index = i;
+ return;
+ }
+ }
+
+ for (i=0; i<_index; i++)
+ {
+ if (_tid[i] == 0)
+ {
+ _tid[i] = tid;
+ _pData[i] = pData;
+ _index = i;
+ return;
+ }
+ }
+
+ Win4Assert(!"Tls Table is FULL");
+}
+
+
+void CMapDword::RemoveKey(DWORD tid)
+{
+ for (ULONG i=0; i<MAP_MAX_SIZE; i++)
+ {
+ if (_tid[i] == tid)
+ {
+ _tid[i] = 0;
+ return;
+ }
+ }
+}
+
+
+void CMapDword::RemoveAll(void)
+{
+ for (ULONG i=0; i<MAP_MAX_SIZE; i++)
+ {
+ if (_tid[i] != 0)
+ {
+ PrivMemFree(_pData[i]);
+ _tid[i] = 0;
+ }
+ }
+}
+
+
+#endif // !defined(_CAIRO_) && DBG==1
diff --git a/private/ole32/com/dcomrem/marshal.cxx b/private/ole32/com/dcomrem/marshal.cxx
new file mode 100644
index 000000000..42380e4ca
--- /dev/null
+++ b/private/ole32/com/dcomrem/marshal.cxx
@@ -0,0 +1,4974 @@
+//+-------------------------------------------------------------------
+//
+// File: marshal.cxx
+//
+// Contents: class implementing standard COM interface marshaling
+//
+// Classes: CStdMarshal
+//
+// History: 20-Feb-95 Rickhi Created
+//
+// DCOMWORK: (maybe) implement Extended form marshal packet
+//
+// PERFWORK: during unmarshal and RMD compare the MOXID in the STDOBJREF
+// to the one for the current apartment. If equal, then i know the IPID is
+// just an index into the IPID table and i can index into it, grab the
+// channel ptr and hence the stdid ptr and do very fast unmarshal or RMD
+// with no table lookup or list walking.
+//
+//--------------------------------------------------------------------
+#include <ole2int.h>
+#include <marshal.hxx> // CStdMarshal
+#include <ipidtbl.hxx> // CIPIDTable, COXIDTable, CMIDTable
+#include <riftbl.hxx> // CRIFTable
+#include <resolver.hxx> // CRpcResolver
+#include <stdid.hxx> // CStdIdentity
+#include <channelb.hxx> // CRpcChannelBuffer
+#include <callctrl.hxx> // CAptRpcChnl, CSrvCallCtrl
+#include <scm.h> // CLSCTX_PS_DLL
+#include <service.hxx> // SASIZE
+#include <locks.hxx> // LOCK/UNLOCK etc
+#include <thunkapi.hxx> // GetAppCompatabilityFlags
+
+
+#if DBG==1
+// this flag and interface are used in debug to enable simpler testing
+// of the esoteric NonNDR stub code feature.
+
+BOOL gfFakeNonNDR = FALSE;
+const GUID IID_ICube =
+ {0x00000139,0x0001,0x0008,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
+#endif // DBG
+
+
+// BUGBUG: this is not quite reliable enough. Maybe best solution is
+// CoGetCurrentProcessId plus sequence number.
+LONG gIPIDSeqNum = 0;
+
+// mappings from MSHLFLAGS to STDOBJREF flags
+static ULONG mapMFtoSORF[] =
+{
+ SORF_NULL, // MSHLFLAGS_NORMAL
+ SORF_NULL, // MSHLFLAGS_TABLESTRONG
+ SORF_TBLWEAK // MSHLFLAGS_TABLEWEAK
+};
+
+// NULL resolver string array
+DUALSTRINGARRAY saNULL = {0,0};
+
+// number of remote AddRefs to acquire when we need more.
+#define REM_ADDREF_CNT 5
+
+// out internal psclass factory implementation
+EXTERN_C HRESULT PrxDllGetClassObject(REFCLSID clsid, REFIID iid, void **ppv);
+
+
+// structure used to post a delayed remote release call to ourself.
+typedef struct tagPOSTRELRIFREF
+{
+ OXIDEntry *pOXIDEntry; // server OXIDEntry
+ USHORT cRifRef; // count of entries in arRifRef
+ REMINTERFACEREF arRifRef; // array of REMINTERFACEREFs
+} POSTRELRIFREF;
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::CStdMarshal/Init, public
+//
+// Synopsis: constructor/initializer of a standard marshaler
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+CStdMarshal::CStdMarshal() : _dwFlags(0), _pChnl(NULL)
+{
+ // Caller must call Init before doing anything! This just makes it
+ // easier for the identity object to figure out the init parameters
+ // before initializing us.
+}
+
+void CStdMarshal::Init(IUnknown *punkObj, CStdIdentity *pStdId,
+ REFCLSID rclsidHandler, DWORD dwFlags)
+{
+ ASSERT_LOCK_DONTCARE // may be released if def handler calls CreateIdHdlr
+
+ // server side we need to do the FirstMarshal work.
+ // client side we assume disconnected until we connect the first IPIDEntry
+ // and assume NOPING until we see any interface that needs pinging
+
+ _dwFlags = dwFlags;
+ _dwFlags |= (ServerSide()) ? SMFLAGS_FIRSTMARSHAL
+ : SMFLAGS_DISCONNECTED | SMFLAGS_NOPING;
+
+ _pFirstIPID = NULL;
+ _cIPIDs = 0;
+ _pStdId = pStdId;
+ _pChnl = NULL;
+ _cNestedCalls = 0;
+ _cTableRefs = 0;
+ _dwMarshalTime = 0;
+ _clsidHandler = rclsidHandler;
+ _pSecureRemUnk = NULL;
+
+ ComDebOut((DEB_MARSHAL,"CStdMarshal %s New this:%x pStdId:%x punkObj:%x\n",
+ (ClientSide()) ? "CLIENT" : "SERVER", this, pStdId, punkObj));
+
+ AssertValid();
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::~CStdMarshal, public
+//
+// Synopsis: destructor of a standard marshaler
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+CStdMarshal::~CStdMarshal()
+{
+ ComDebOut((DEB_MARSHAL, "CStdMarshal %s Deleted this:%x\n",
+ (ClientSide()) ? "CLIENT" : "SERVER", this));
+ ASSERT_LOCK_RELEASED
+
+ if (ClientSide())
+ {
+ // Due to backward compatibility, we are not allowed to release
+ // interface proxies in Disconnect since the client might try to
+ // reconnect later and expects the same interface pointer values.
+ // Since we are going away now, we go release the proxies.
+
+ ReleaseCliIPIDs();
+ if (_pSecureRemUnk != NULL)
+ {
+ _pSecureRemUnk->Release();
+ }
+ }
+
+ if (_pChnl)
+ {
+ // release the channel
+ _pChnl->Release();
+ }
+
+ ASSERT_LOCK_RELEASED
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::GetUnmarshalClass, public
+//
+// Synopsis: returns the clsid of the standard marshaller
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CStdMarshal::GetUnmarshalClass(REFIID riid, LPVOID pv,
+ DWORD dwDestCtx, LPVOID pvDestCtx, DWORD mshlflags, LPCLSID pClsid)
+{
+ AssertValid();
+ ASSERT_LOCK_RELEASED
+
+ *pClsid = CLSID_StdMarshal;
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::GetMarshalSizeMax, public
+//
+// Synopsis: Returns an upper bound on the amount of data for
+// a standard interface marshal.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CStdMarshal::GetMarshalSizeMax(REFIID riid, LPVOID pv,
+ DWORD dwDestCtx, LPVOID pvDestCtx, DWORD mshlflags, LPDWORD pSize)
+{
+ AssertValid();
+ Win4Assert(gdwPsaMaxSize != 0);
+ ASSERT_LOCK_RELEASED
+
+ *pSize = sizeof(OBJREF) + gdwPsaMaxSize;
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: MarshalObjRef, private
+//
+// Synopsis: Marshals interface into the objref.
+//
+// Arguements: [objref] - object reference
+// [riid] - interface id to marshal
+// [pv] - interface to marshal
+// [mshlflags] - marshal flags
+//
+// Algorithm: Get the correct standard identity and ask it to do
+// all the work.
+//
+// History: 25-Mar-95 AlexMit Created
+//
+//--------------------------------------------------------------------
+INTERNAL MarshalObjRef(OBJREF &objref, REFIID riid, void *pv, DWORD mshlflags)
+{
+ TRACECALL(TRACE_MARSHAL, "MarshalObjRef");
+ ComDebOut((DEB_MARSHAL, "MarshalObjRef: riid:%I pv:%x flags:%x\n",
+ &riid, pv, mshlflags));
+ ASSERT_LOCK_RELEASED
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (SUCCEEDED(hr))
+ {
+ // Find or create the StdId for this object. We need to get a strong
+ // reference to guard against an incoming last release on another
+ // thread which would cause us to Disconnect this StdId.
+
+ DWORD dwFlags = IDLF_CREATE | IDLF_STRONG;
+ dwFlags |= (mshlflags & MSHLFLAGS_NOPING) ? IDLF_NOPING : 0;
+
+ CStdIdentity *pStdID;
+ hr = LookupIDFromUnk((IUnknown *)pv, dwFlags, &pStdID);
+
+ if (hr == NOERROR)
+ {
+ hr = pStdID->MarshalObjRef(objref, riid, pv, mshlflags);
+ pStdID->DecStrongCnt(TRUE); // fKeepAlive
+ }
+ }
+
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_MARSHAL, "MarshalObjRef: hr:%x\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: MarshalInternalObjRef, private
+//
+// Synopsis: Marshals an internal interface into the objref.
+//
+// Arguements: [objref] - object reference
+// [riid] - interface id to marshal
+// [pv] - interface to marshal
+// [mshlflags] - marshal flags
+// [ppStdId] - StdId to return (may be NULL)
+//
+// Algorithm: Create a StdIdentity and ask it to do the work.
+//
+// Notes: This differs from the normal MarshalObjRef in that it does
+// not look in the OID table for an already marshaled interface,
+// nor does it register the marshaled interface in the OID table.
+// This is used for internal interfaces such as the IObjServer
+// and IRemUnknown.
+//
+// History: 25-Oct-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+INTERNAL MarshalInternalObjRef(OBJREF &objref, REFIID riid, void *pv,
+ DWORD mshlflags, void **ppStdId)
+{
+ TRACECALL(TRACE_MARSHAL, "MarshalInternalObjRef");
+ ComDebOut((DEB_MARSHAL, "MarshalInternalObjRef: riid:%I pv:%x flags:%x\n",
+ &riid, pv, mshlflags));
+ ASSERT_LOCK_RELEASED
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (SUCCEEDED(hr))
+ {
+ if (!IsEqualGUID(riid, IID_IRundown))
+ {
+ // NOTE: make sure the local OXID is registered with the resolver.
+ // See the discussion on the Chicken and Egg problem in ipidtbl.cxx
+ // COXIDTable::GetLocalEntry for why this is necessary.
+
+ LOCK
+ MOID moid;
+ hr = gResolver.ServerGetPreRegMOID(&moid);
+ UNLOCK
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // Find or create the StdId for this object. We need to get a strong
+ // reference to guard against an incoming last release on another
+ // thread which would cause us to Disconnect this StdId.
+
+ IUnknown *pUnkId; // ignored
+ CStdIdentity *pStdId = new CStdIdentity(STDID_SERVER, NULL,
+ (IUnknown *)pv, &pUnkId);
+
+ if (pStdId != NULL)
+ {
+ hr = pStdId->MarshalObjRef(objref, riid, pv, mshlflags);
+
+ if (SUCCEEDED(hr) && ppStdId)
+ {
+ *ppStdId = (void *)pStdId;
+ }
+ else
+ {
+ pStdId->Release();
+ }
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ }
+
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_MARSHAL, "MarshalInternalObjRef: hr:%x\n", hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::MarshalInterface, public
+//
+// Synopsis: marshals the interface into the stream.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CStdMarshal::MarshalInterface(IStream *pStm, REFIID riid,
+ LPVOID pv, DWORD dwDestCtx, LPVOID pvDestCtx, DWORD mshlflags)
+{
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::MarshalInterface this:%x pStm:%x riid:%I pv:%x dwCtx:%x pvCtx:%x flags:%x\n",
+ this, pStm, &riid, pv, dwDestCtx, pvDestCtx, mshlflags));
+ AssertValid();
+ ASSERT_LOCK_RELEASED
+
+ // Marshal the interface into an objref, then write the objref
+ // into the provided stream.
+
+ OBJREF objref;
+ HRESULT hr = MarshalObjRef(objref, riid, pv, mshlflags);
+
+ if (SUCCEEDED(hr))
+ {
+ // write the objref into the stream
+ hr = WriteObjRef(pStm, objref, dwDestCtx);
+
+ if (FAILED(hr))
+ {
+ // undo whatever we just did, ignore error from here since
+ // the stream write error supercedes any error from here.
+ ReleaseMarshalObjRef(objref);
+ }
+
+ // free resources associated with the objref.
+ FreeObjRef(objref);
+ }
+
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_MARSHAL,"CStdMarshal::MarshalInterface this:%x hr:%x\n",
+ this, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::MarshalObjRef, public
+//
+// Synopsis: marshals the interface into the objref.
+//
+// History: 25-Mar-95 AlexMit Seperated from MarshalInterface
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::MarshalObjRef(OBJREF &objref, REFIID riid,
+ LPVOID pv, DWORD mshlflags)
+{
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::MarsalObjRef this:%x riid:%I pv:%x flags:%x\n",
+ this, &riid, pv, mshlflags));
+ AssertValid();
+
+ // validate the parameters. we dont allow TABLE cases if we are
+ // a client side object.
+
+ if ((mshlflags & MSHLFLAGS_TABLE) && ClientSide())
+ return E_INVALIDARG;
+
+ // count of Refs we are handing out. In the table cases we pass out
+ // zero refs because we dont know how many times it will be unmarshaled
+ // (and hence how many references to count). Zero refs will cause the
+ // client to call back and ask for more references if it does not already
+ // have any (which has the side effect of making sure the object still
+ // exists, which is required by RunningObjectTable).
+
+ ULONG cRefs = (mshlflags & MSHLFLAGS_TABLE) ? 0 :
+ (ClientSide()) ? 1 : REM_ADDREF_CNT;
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ HRESULT hr = PreventDisconnect();
+ if (SUCCEEDED(hr))
+ {
+ // The first time through we have some extra work to do so go off
+ // and do that now. Next time we can just bypass all that work.
+
+ if (_dwFlags & SMFLAGS_FIRSTMARSHAL)
+ {
+ hr = FirstMarshal((IUnknown *)pv, mshlflags);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // Create the IPID table entry. On the server side this may
+ // cause the creation of an interface stub, on the client side
+ // it may just take away one of our references or it may call
+ // the server to get more references for the interface being
+ // marshaled.
+
+ IPIDEntry *pIPIDEntry;
+ hr = MarshalIPID(riid, cRefs, mshlflags, &pIPIDEntry);
+
+ if (SUCCEEDED(hr))
+ {
+ // fill in the rest of the OBJREF
+ FillObjRef(objref, cRefs, mshlflags, pIPIDEntry);
+ }
+ }
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ // it is now OK to allow real disconnects in.
+ HRESULT hr2 = HandlePendingDisconnect(hr);
+ if (FAILED(hr2) && SUCCEEDED(hr))
+ {
+ // a disconnect came in while marshaling. The ObjRef has a
+ // reference to the OXIDEntry so go free that now.
+ FreeObjRef(objref);
+ }
+
+ ComDebOut((DEB_MARSHAL, "CStdMarshal::MarshalObjRef this:%x hr:%x\n",
+ this, hr2));
+ return hr2;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::FillObjRef, private
+//
+// Synopsis: Fill in the fields of an OBJREF
+//
+// History: 21-Sep-95 Rickhi Created
+//
+//+-------------------------------------------------------------------
+void CStdMarshal::FillObjRef(OBJREF &objref, ULONG cRefs, DWORD mshlflags,
+ IPIDEntry *pIPIDEntry)
+{
+ ComDebOut((DEB_MARSHAL, "FillObjRef pObjRef:%x\n", &objref));
+ ASSERT_LOCK_HELD
+ AssertDisconnectPrevented();
+ Win4Assert(pIPIDEntry);
+ OXIDEntry **ppOXIDEntry;
+
+ // first, fill in the STDOBJREF section
+ STDOBJREF *pStd = &ORSTD(objref).std;
+ FillSTD(pStd, cRefs, mshlflags, pIPIDEntry);
+
+ // next fill in the rest of the OBJREF
+ objref.signature = OBJREF_SIGNATURE; // 'MEOW'
+ objref.iid = pIPIDEntry->iid; // interface iid
+
+ if (_dwFlags & SMFLAGS_HANDLER)
+ {
+ // handler form, copy in the clsid
+ objref.flags = OBJREF_HANDLER;
+ ORHDL(objref).clsid = _clsidHandler;
+ ppOXIDEntry = (OXIDEntry **) &ORHDL(objref).saResAddr;
+ }
+ else
+ {
+ objref.flags = OBJREF_STANDARD;
+ ppOXIDEntry = (OXIDEntry **) &ORSTD(objref).saResAddr;
+ }
+
+ // TRICK: in order to keep the objref a fixed size internally,
+ // we use the saResAddr.size field as a ptr to the OXIDEntry. We
+ // pay attention to this in ReadObjRef, WriteObjRef, and FreeObjRef.
+
+ *ppOXIDEntry = pIPIDEntry->pOXIDEntry;
+ Win4Assert(*ppOXIDEntry != NULL);
+ IncOXIDRefCnt(*ppOXIDEntry);
+ ASSERT_LOCK_HELD
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::FillSTD, public
+//
+// Synopsis: Fill in the STDOBJREF fields of an OBJREF
+//
+// History: 21-Sep-95 Rickhi Created
+//
+//+-------------------------------------------------------------------
+void CStdMarshal::FillSTD(STDOBJREF *pStd, ULONG cRefs, DWORD mshlflags,
+ IPIDEntry *pIPIDEntry)
+{
+ // fill in the STDOBJREF to return to the caller.
+ pStd->flags = mapMFtoSORF[mshlflags & MSHLFLAGS_TABLE];
+
+ pStd->flags |= (pIPIDEntry->dwFlags & IPIDF_NOPING) ? SORF_NOPING : 0;
+ pStd->flags |= (pIPIDEntry->dwFlags & IPIDF_NONNDRSTUB) ? SORF_NONNDR : 0;
+
+ pStd->cPublicRefs = cRefs;
+
+ pStd->ipid = pIPIDEntry->ipid;
+
+ OIDFromMOID(_pStdId->GetOID(), &pStd->oid);
+ OXIDFromMOXID(pIPIDEntry->pOXIDEntry->moxid, &pStd->oxid);
+
+ ValidateSTD(pStd);
+ DbgDumpSTD(pStd);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::FirstMarshal, private
+//
+// Synopsis: Does some first-time server side marshal stuff
+//
+// Parameters: [pUnk] - interface being marshalled
+// [mshlflags] - flags for marshaling
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::FirstMarshal(IUnknown *pUnk, DWORD mshlflags)
+{
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::FirstMarshal this:%x pUnk:%x\n", this, pUnk));
+ Win4Assert(ServerSide());
+ Win4Assert(_dwFlags & SMFLAGS_FIRSTMARSHAL);
+ Win4Assert(_pChnl == NULL);
+ AssertValid();
+ AssertDisconnectPrevented();
+ ASSERT_LOCK_HELD
+
+ // have now executed this code so dont do it again.
+ _dwFlags &= ~SMFLAGS_FIRSTMARSHAL;
+
+ if (mshlflags & MSHLFLAGS_NOPING)
+ {
+ // if the first interface is marked as NOPING, then all interfaces
+ // for the object are treated as NOPING, otherwise, all interfaces
+ // are marked as PING. MakeSrvIPIDEntry will look at _dwFlags to
+ // determine whether to mark each IPIDEntry as NOPING or not.
+
+ _dwFlags |= SMFLAGS_NOPING;
+ }
+
+ // get our local OXID. This should have already been created, and
+ // so wont cause the LOCK to be released.
+
+ OXIDEntry *pOXIDEntry;
+ HRESULT hr = gOXIDTbl.GetLocalEntry(&pOXIDEntry);
+
+ if (SUCCEEDED(hr))
+ {
+ // create a channel for this object.
+ CRpcChannelBuffer *pChnl;
+ hr = CreateChannel(pOXIDEntry, 0, GUID_NULL, GUID_NULL, &pChnl);
+ }
+
+ ASSERT_LOCK_HELD
+ AssertDisconnectPrevented();
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::FirstMarshal this:%x hr:%x\n", this, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::MarshalIPID, private
+//
+// Synopsis: finds or creates an interface stub and IPID entry
+// for the given object interface.
+//
+// Arguments: [riid] - interface to look for
+// [cRefs] - count of references wanted
+// [mshlflags] - marshal flags
+// [ppEntry] - place to return IPIDEntry ptr
+//
+// Returns: S_OK if succeeded
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::MarshalIPID(REFIID riid, ULONG cRefs, DWORD mshlflags,
+ IPIDEntry **ppIPIDEntry)
+{
+ TRACECALL(TRACE_MARSHAL, "CStdMarshal::MarshalIPID");
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::MarshalIPID this:%x riid:%I cRefs:%x mshlflags:%x ppEntry:%x\n",
+ this, &riid, cRefs, mshlflags, ppIPIDEntry));
+ AssertValid();
+ AssertDisconnectPrevented();
+ ASSERT_LOCK_HELD
+
+ // validate input parms.
+ Win4Assert(!(IsEqualIID(riid, IID_NULL) || IsEqualIID(riid, IID_IMarshal)));
+
+ // look for an existing IPIDEntry for the requested interface
+ IPIDEntry *pEntry;
+ HRESULT hr = FindIPIDEntry(riid, &pEntry);
+
+ if (FAILED(hr))
+ {
+ // no entry currently exists. on the server side we try to create one.
+ // on the client side we do a remote QI for the requested interface.
+
+ if (ServerSide())
+ {
+ // this call fail if we are disconnected during a yield.
+ hr = MakeSrvIPIDEntry(riid, &pEntry);
+ }
+ else
+ {
+ hr = RemQIAndUnmarshal(1, (GUID *)&riid, NULL);
+ if (SUCCEEDED(hr))
+ {
+ hr = FindIPIDEntry(riid, &pEntry);
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // REFCOUNTING:
+ if (ServerSide())
+ {
+ // remember the latest marshal time so we can tell if the ping
+ // server has run us down too early. This can happen when an
+ // existing client dies and we remarshal the interface just
+ // moments before the pingserver tells us the first guy is gone
+ // and before the new client has had time to unmarshal and ping.
+
+ _dwMarshalTime = GetCurrentTime();
+
+ // inc the refcnt for the IPIDEntry and optionaly the stdid. Note
+ // that for TABLE marshals cRefs is 0 (that's the number that gets
+ // placed in the packet) but we do want a reference so we ask for
+ // 1 here. ReleaseMarshalData will undo the 1.
+
+ ULONG cRefs2 = (mshlflags & MSHLFLAGS_TABLE) ? 1 : cRefs;
+ IncSrvIPIDCnt(pEntry, cRefs2, 0, NULL, mshlflags);
+ }
+ else // client side,
+ {
+ // we dont support marshaling weak refs on the client side, though
+ // we do support marshaling strong from a weak client by going to
+ // the server and getting a strong reference.
+ Win4Assert(!(mshlflags & MSHLFLAGS_WEAK));
+
+ if (cRefs >= pEntry->cStrongRefs)
+ {
+ // need more references than we own, go get more from server
+ // to satisfy the marshal. Get a few extra refs for ourselves
+ // unless we are a weak client.
+
+ ULONG cExtraRefs = (_dwFlags & SMFLAGS_WEAKCLIENT)
+ ? 0 : REM_ADDREF_CNT;
+
+ hr = RemoteAddRef(pEntry, pEntry->pOXIDEntry, cRefs + cExtraRefs, 0);
+
+ if (SUCCEEDED(hr))
+ {
+ // add in the extra references we asked for (if any).
+ pEntry->cStrongRefs += cExtraRefs;
+ }
+ }
+ else
+ {
+ // we have enough references to satisfy this request (and still
+ // keep some for ourselves), just subtract from the IPIDEntry
+ pEntry->cStrongRefs -= cRefs;
+ }
+
+ // mark this object as having been client-side marshaled so
+ // that we can tell the resolver whether or not it needs to
+ // ping this object if we release it before the OID is registered.
+
+ _dwFlags |= SMFLAGS_CLIENTMARSHALED;
+ }
+
+ // do some debug stuff
+ ValidateIPIDEntry(pEntry);
+ ComDebOut((DEB_MARSHAL, "pEntry:%x cRefs:%x cStdId:%x\n", pEntry,
+ pEntry->cStrongRefs, _pStdId->GetRC()));
+ }
+
+ *ppIPIDEntry = pEntry;
+
+ ASSERT_LOCK_HELD
+ AssertDisconnectPrevented();
+ ComDebOut((DEB_MARSHAL, "CStdMarshal::MarshalIPID hr:%x pIPIDEntry\n", hr, *ppIPIDEntry));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::UnmarshalInterface, public
+//
+// Synopsis: Unmarshals an Interface from a stream.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CStdMarshal::UnmarshalInterface(LPSTREAM pStm,
+ REFIID riid, VOID **ppv)
+{
+ ComDebOut((DEB_MARSHAL, "CStdMarshal::UnmarsalInterface this:%x pStm:%x riid:%I\n",
+ this, pStm, &riid));
+ AssertValid();
+ ASSERT_LOCK_RELEASED
+
+ // read the objref from the stream and find or create an instance
+ // of CStdMarshal for its OID. Then ask that guy to do the rest of
+ // the unmarshal (create the interface proxy)
+
+ OBJREF objref;
+ HRESULT hr = ReadObjRef(pStm, objref);
+
+ if (SUCCEEDED(hr))
+ {
+ // pass objref to subroutine to unmarshal the objref
+ hr = ::UnmarshalObjRef(objref, ppv);
+
+ // release the objref we read
+ FreeObjRef(objref);
+ }
+
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_MARSHAL,
+ "UnmarsalInterface this:%x pv:%x hr:\n", this, *ppv, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: UnmarshalObjRef, private
+//
+// Synopsis: UnMarshals interface from objref.
+//
+// Arguements: [objref] - object reference
+// [ppv] - proxy
+//
+// Algorithm: Get the correct standard identity and ask it to do
+// all the work.
+//
+// History: 25-Mar-95 AlexMit Created
+//
+//--------------------------------------------------------------------
+INTERNAL UnmarshalObjRef(OBJREF &objref, void **ppv)
+{
+ ASSERT_LOCK_RELEASED
+
+ CStdMarshal *pStdMshl;
+ HRESULT hr = FindStdMarshal(objref, &pStdMshl);
+
+ if (SUCCEEDED(hr))
+ {
+ // pass objref to subroutine to unmarshal the objref
+ hr = pStdMshl->UnmarshalObjRef(objref, ppv);
+ CALLHOOKOBJECTCREATE(S_OK,ORHDL(objref).clsid,objref.iid,(IUnknown **)ppv);
+ pStdMshl->Release();
+ }
+ else
+ {
+ // we could not create the indentity or handler, release the
+ // marshaled objref.
+ ReleaseMarshalObjRef(objref);
+ }
+
+ ASSERT_LOCK_RELEASED
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: ChkIfLocalOID, private
+//
+// Synopsis: Helper function for UnmarshalInternalObjRef & FindStdMarshal
+//
+// Arguements: [objref] - object reference
+// [ppStdMshl] - CStdMarshal returned
+//
+// Algorithm: Read the objref, get the OID. If we already have an identity
+// for this OID return it AddRefd.
+//
+// History: 21-May-95 MurthyS Created.
+//
+//--------------------------------------------------------------------
+INTERNAL_(BOOL) ChkIfLocalOID(OBJREF &objref, CStdIdentity **ppStdId)
+{
+ STDOBJREF *pStd = &ORSTD(objref).std;
+ BOOL flocal = FALSE;
+
+ ComDebOut((DEB_MARSHAL, "ChkIfLocalOID (IN) poid: %x\n", &pStd->oid));
+ Win4Assert((*ppStdId == NULL) && "ChkIfLocalOID: pStdId != NULL");
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ OXIDEntry *pOXIDEntry = GetOXIDFromObjRef(objref);
+
+ if (pOXIDEntry == GetLocalOXIDEntry())
+ {
+ flocal = TRUE;
+ // OXID is for this apartment, look IPID up in the IPIDTable
+ // directly, and extract the CStdMarshal from it.
+
+ IPIDEntry *pEntry = gIPIDTbl.LookupIPID(pStd->ipid);
+ if (pEntry && pEntry->pChnl)
+ {
+ // get the Identity
+ *ppStdId = pEntry->pChnl->GetStdId();
+ (*ppStdId)->AddRef();
+ }
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ return flocal;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: UnmarshalInternalObjRef, private
+//
+// Synopsis: UnMarshals an internally-used interface from objref.
+//
+// Arguements: [objref] - object reference
+// [ppv] - proxy
+//
+// Algorithm: Create a StdId and ask it to do the work.
+//
+// Notes: This differs from UnmarshalObjRef in that it does not lookup
+// or register the OID. This saves a fair amount of work and
+// avoids initializing the OID table.
+//
+// History: 25-Oct-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+INTERNAL UnmarshalInternalObjRef(OBJREF &objref, void **ppv)
+{
+ ASSERT_LOCK_RELEASED
+
+ HRESULT hr = S_OK;
+ CStdIdentity *pStdId = NULL;
+
+ if (ChkIfLocalOID(objref, &pStdId))
+ {
+ if (pStdId)
+ {
+ // set OID in objref to match that in returned std identity
+ OIDFromMOID(pStdId->GetOID(), &ORSTD(objref).std.oid);
+ }
+ else
+ {
+ hr = CO_E_OBJNOTCONNECTED;
+ }
+ }
+ else
+ {
+ ASSERT_LOCK_RELEASED
+
+ hr = CreateIdentityHandler(NULL, ORSTD(objref).std.flags,
+ IID_IStdIdentity, (void **)&pStdId);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // pass objref to subroutine to unmarshal the objref. tell StdId not
+ // to register the OID in the OID table.
+
+ pStdId->IgnoreOID();
+ hr = pStdId->UnmarshalObjRef(objref, ppv);
+ CALLHOOKOBJECTCREATE(S_OK,ORHDL(objref).clsid,objref.iid,(IUnknown **)ppv);
+ pStdId->Release();
+ }
+
+ ASSERT_LOCK_RELEASED
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::UnmarshalObjRef, private
+//
+// Synopsis: unmarshals the objref. Called by CoUnmarshalInterface,
+// UnmarshalObjRef APIs, and UnmarshalInterface method.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::UnmarshalObjRef(OBJREF &objref, void **ppv)
+{
+ ComDebOut((DEB_MARSHAL, "CStdMarshal::UnmarsalObjRef this:%x objref:%x riid:%I\n",
+ this, &objref, &objref.iid));
+ AssertValid();
+
+ STDOBJREF *pStd = &ORSTD(objref).std;
+ OXIDEntry *pOXIDEntry = GetOXIDFromObjRef(objref);
+ DbgDumpSTD(pStd);
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // Prevent a disconnect from occuring while unmarshaling the
+ // interface since we may have to yield the ORPC lock.
+
+ HRESULT hr = PreventPendingDisconnect();
+
+ if (SUCCEEDED(hr))
+ {
+ if (objref.flags & OBJREF_HANDLER)
+ {
+ // handler form, extract the handler clsid and set our flags
+ _dwFlags |= SMFLAGS_HANDLER;
+ _clsidHandler = ORHDL(objref).clsid;
+ }
+
+ // if no OID registered yet, do that now. only possible on client side
+ // during reconnect.
+
+ MOID moid;
+ MOIDFromOIDAndMID(pStd->oid, pOXIDEntry->pMIDEntry->mid, &moid);
+ hr = _pStdId->SetOID(moid);
+
+ if (SUCCEEDED(hr))
+ {
+ // find or create the IPID entry for the interface. On the client
+ // side this may cause the creation of an interface proxy. It will
+ // also manipulate the reference counts.
+
+ hr = UnmarshalIPID(objref.iid, pStd, pOXIDEntry, ppv);
+ }
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ if (ClientSide())
+ {
+ if (SUCCEEDED(hr))
+ {
+ if (_pStdId->IsAggregated())
+ {
+ // we are currently holding a proxy pointer. If aggregated,
+ // the controlling unknown may want to override this pointer
+ // with his own version, so issue a QI to give it that chance.
+ IUnknown *pUnk = (IUnknown *)*ppv;
+
+#ifdef WX86OLE
+ if (gcwx86.IsN2XProxy(pUnk))
+ {
+ // Tell wx86 thunk layer to thunk as IUnknown
+ gcwx86.SetStubInvokeFlag((BOOL)1);
+ }
+#endif
+
+ hr = pUnk->QueryInterface(objref.iid, ppv);
+ pUnk->Release();
+ }
+ }
+ else
+ {
+ // cleanup our state on failure (only meaningful on client side,
+ // since if the unmarshal failed on the server side, the interface
+ // is already cleaned up).
+ ReleaseMarshalObjRef(objref);
+ }
+ }
+
+ // now let pending disconnect through. on server-side, ignore any
+ // error from HPD and pay attention only to the unmarshal result, since
+ // a successful unmarshal on the server side may result in a disconnect
+ // if that was the last external reference to the object.
+
+ HRESULT hr2 = HandlePendingDisconnect(hr);
+
+ if (FAILED(hr2) && ClientSide())
+ {
+ if (SUCCEEDED(hr))
+ {
+ // a disconnect came in while unmarshaling. ppv contains an
+ // AddRef'd interface pointer so go Release that now.
+ ((IUnknown *)*ppv)->Release();
+ }
+ hr = hr2;
+ }
+
+ ComDebOut((DEB_MARSHAL, "CStdMarshal::UnmarsalObjRef this:%x hr:%x\n",
+ this, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::UnmarshalIPID, private
+//
+// Synopsis: finds or creates an interface proxy for the given
+// interface. may also do a remote query interface.
+//
+// Arguements: [riid] - the interface to return
+// [std] - standard objref to unmarshal from
+// [pOXIDEntry] - ptr to OXIDEntry of the server
+// [ppv] - interface ptr of type riid returned, AddRef'd
+//
+// Returns: S_OK if succeeded
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::UnmarshalIPID(REFIID riid, STDOBJREF *pStd,
+ OXIDEntry *pOXIDEntry, void **ppv)
+{
+ TRACECALL(TRACE_MARSHAL, "CStdMarshal::UnmarshalIPID");
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::UnmarshalIPID this:%x riid:%I pStd:%x pOXIDEntry:%x\n",
+ this, &riid, pStd, pOXIDEntry));
+ DbgDumpSTD(pStd);
+ AssertValid();
+ AssertDisconnectPrevented();
+ ASSERT_LOCK_HELD
+
+ // validate input params.
+ Win4Assert(!(IsEqualIID(riid, IID_NULL) || IsEqualIID(riid, IID_IMarshal)));
+ Win4Assert(pStd != NULL);
+ ValidateSTD(pStd);
+ Win4Assert(pOXIDEntry);
+
+
+ // look for an existing IPIDEntry for the requested interface.
+ IPIDEntry *pEntry;
+ HRESULT hr = FindIPIDEntry(riid, &pEntry);
+
+#ifdef WX86OLE
+ BOOL fSameApt = SUCCEEDED(hr);
+ PVOID pvPSThunk = NULL;
+#endif
+
+
+ // REFCOUNTING:
+ if (ClientSide())
+ {
+ if (FAILED(hr))
+ {
+ // no IPID Entry exists yet for the requested interface. We do
+ // have a STDOBJREF. Create the interface proxy and IPIDEntry
+ // now, and connect it up. If successful, the proxy will be
+ // fully connected upon return, with pEntry->cStrongRefs set
+ // to pStd->cPublicRefs.
+
+ if (ppv)
+ *ppv = NULL;
+ hr = MakeCliIPIDEntry(riid, pStd, pOXIDEntry, &pEntry);
+ }
+ else if (pEntry->dwFlags & IPIDF_DISCONNECTED)
+ {
+ // reconnect the IPID entry to the server. this will set
+ // pEntry->cStrongRefs to pStd->cPublicRefs. Even though we could
+ // yield, the IPIDEntry is guarenteed connected on return
+ // (cause we are holding the lock on return).
+
+ hr = ConnectIPIDEntry(pStd, pOXIDEntry, pEntry);
+ }
+ else if ((pStd->flags & SORF_WEAKREF) &&
+ (pEntry->pOXIDEntry->dwFlags & OXIDF_MACHINE_LOCAL))
+ {
+ // add the refcnt to our weak total for this IPIDEntry
+ pEntry->cWeakRefs += pStd->cPublicRefs;
+ }
+ else
+ {
+ // add the refcnt to our strong total for this IPIDEntry
+ pEntry->cStrongRefs += pStd->cPublicRefs;
+ }
+ }
+ else if (SUCCEEDED(hr))
+ {
+ // unmarshaling in the server apartment. If the cRefs is zero,
+ // then the interface was TABLE marshalled and we dont do
+ // anything to the IPID RefCnts since the object must live until
+ // ReleaseMarshalData is called on it.
+
+#ifdef WX86OLE
+ pvPSThunk = gcwx86.UnmarshalledInSameApt(pEntry->pv, riid);
+#endif
+ if (pStd->cPublicRefs > 0)
+ {
+ // normal case, dec the ref counts from the IPID entry,
+ // OLE always passed fLastReleaseCloses = FALSE on
+ // Unmarshal and RMD so do the same here.
+
+ DWORD mshlflags = (pStd->flags & SORF_WEAKREF)
+ ? (MSHLFLAGS_WEAK | MSHLFLAGS_KEEPALIVE)
+ : (MSHLFLAGS_NORMAL | MSHLFLAGS_KEEPALIVE);
+
+ DecSrvIPIDCnt(pEntry, pStd->cPublicRefs, 0, NULL, mshlflags);
+ }
+ }
+
+ if (SUCCEEDED(hr) && ppv)
+ {
+ ValidateIPIDEntry(pEntry);
+
+ // extract and AddRef the pointer to return to the caller.
+ // Do this before releasing the lock (which we might do below
+ // on the server-side in DecSrvIPIDCnt.
+
+ // NOTE: we are calling App code while holding the lock,
+ // but there is no way to avoid this.
+
+ Win4Assert(IsValidInterface(pEntry->pv));
+ *ppv = pEntry->pv;
+ ((IUnknown *)*ppv)->AddRef();
+ AssertOutPtrIface(hr, *ppv);
+ if (_dwFlags & SMFLAGS_WEAKCLIENT && !(pStd->flags & SORF_WEAKREF))
+ {
+ // make the client interface weak, ignore errors.
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ RemoteChangeRef(0,0);
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+#ifdef WX86OLE
+ // If we unmarshalled in the same apartment as the object and Wx86
+ // recognized the interface then change the returned proxy to the
+ // proxy created for the Wx86 PSThunk.
+ if (pvPSThunk == (PVOID)-1)
+ {
+ // Wx86 recognized the interface, but could not establish a
+ // PSThunk for it. Force an error return.
+ *ppv = NULL;
+ hr = E_NOINTERFACE;
+ }
+ else if (pvPSThunk != NULL)
+ {
+ // Wx86 recognized the interface and did establish a PSThunk
+ // for it. Force a successful return with Wx86 proxy interface.
+ *ppv = pvPSThunk;
+ }
+#endif
+ }
+
+ ComDebOut((DEB_MARSHAL, "pEntry:%x cRefs:%x cStdId:%x\n", pEntry,
+ (SUCCEEDED(hr)) ? pEntry->cStrongRefs : 0, _pStdId->GetRC()));
+ ASSERT_LOCK_HELD
+ AssertDisconnectPrevented();
+ ComDebOut((DEB_MARSHAL, "CStdMarshal::UnmarshalIPID hr:%x\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::PrivateCopyProxy, internal
+//
+// Synopsis: Creates a copy of a proxy and IPID entry.
+//
+// Arguements: [pProxy] - Proxy to copy
+// [ppProxy] - return copy here.
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::PrivateCopyProxy( IUnknown *pv, IUnknown **ppv )
+{
+ TRACECALL(TRACE_MARSHAL, "CStdMarshal::PrivateCopyProxy");
+ ComDebOut((DEB_MARSHAL, "CStdMarshal::PrivateCopyProxy this:%x pv:%x\n",
+ this, pv));
+
+ // Don't copy stubs.
+ if (ServerSide())
+ return E_INVALIDARG;
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // Prevent a disconnect from occuring while unmarshaling the
+ // interface since we may have to yield the ORPC lock.
+
+ HRESULT hr = PreventPendingDisconnect();
+
+ if (SUCCEEDED(hr))
+ {
+ // Find the proxy to copy.
+ IPIDEntry *pEntry;
+ hr = FindIPIDEntryByInterface(pv, &pEntry);
+ if (SUCCEEDED(hr))
+ {
+ // Don't copy disconnected proxies.
+ if (pEntry->dwFlags & IPIDF_DISCONNECTED)
+ hr = RPC_E_DISCONNECTED;
+
+ // IUnknown can't be copied.
+ else if (IsEqualGUID( pEntry->iid, IID_IUnknown ))
+ hr = E_INVALIDARG;
+
+ else
+ {
+ BOOL fNonNDRProxy;
+ IRpcProxyBuffer *pProxy;
+ hr = CreateProxy(pEntry->iid, &pProxy, (void **)ppv,
+ &fNonNDRProxy);
+
+ if (SUCCEEDED(hr))
+ {
+ IPIDEntry *pIpidCopy;
+
+ // add a disconnected IPID entry to the table.
+ hr = AddIPIDEntry(NULL, &pEntry->ipid, pEntry->iid, NULL,
+ pProxy, *ppv, &pIpidCopy);
+
+ if (SUCCEEDED(hr))
+ {
+ // mark this IPID as a copy so we dont free it during
+ // ReleaseIPIDs.
+ pIpidCopy->dwFlags |= IPIDF_COPY;
+
+ // connect the IPIDEntry before adding it to the table so
+ // that we dont have to worry about races between Unmarshal,
+ // Disconnect, and ReconnectProxies.
+
+ // Make up an objref. Mark it as NOPING since we dont
+ // really have any references and we dont really need
+ // any because if we ever try to marshal it we will
+ // find the original IPIDEntry and use that. NOPING
+ // also lets us skip this IPID in DisconnectCliIPIDs.
+
+ STDOBJREF std;
+ OXIDFromMOXID(pEntry->pOXIDEntry->moxid, &std.oxid);
+ std.ipid = pEntry->ipid;
+ std.cPublicRefs = 1;
+ std.flags = SORF_NOPING;
+
+ hr = ConnectIPIDEntry(&std, pEntry->pOXIDEntry, pIpidCopy);
+
+ // Add this IPID entry after the original.
+ pIpidCopy->pNextOID = pEntry->pNextOID;
+ pEntry->pNextOID = pIpidCopy;
+ _cIPIDs++;
+ }
+ else
+ {
+ // could not get an IPIDEntry, release the proxy, need to
+ // release the lock to do this.
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ pProxy->Release();
+ ((IUnknown *)*ppv)->Release();
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ ValidateIPIDEntry(pEntry);
+ AssertOutPtrIface(hr, *ppv);
+ }
+ AssertDisconnectPrevented();
+ }
+ ASSERT_LOCK_HELD
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ // Now let pending disconnect through.
+ HRESULT hr2 = HandlePendingDisconnect(hr);
+ if (FAILED(hr2) && SUCCEEDED(hr))
+ {
+ // a disconnect came in while creating the proxy. ppv contains
+ // an AddRef'd interface pointer so go Release that now.
+ ((IUnknown *)*ppv)->Release();
+ }
+
+ ComDebOut((DEB_MARSHAL, "CStdMarshal::PrivateCopyProxy hr:%x\n", hr2));
+ return hr2;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: MakeSrvIPIDEntry, private
+//
+// Synopsis: creates a server side IPID table entry
+//
+// Arguements: [riid] - the interface to return
+// [ppEntry] - IPIDEntry returned
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::MakeSrvIPIDEntry(REFIID riid, IPIDEntry **ppEntry)
+{
+ Win4Assert(ServerSide());
+ AssertValid();
+ AssertDisconnectPrevented();
+ ASSERT_LOCK_HELD
+
+ BOOL fNonNDRStub;
+ void *pv;
+ IRpcStubBuffer *pStub;
+ HRESULT hr = CreateStub(riid, &pStub, &pv, &fNonNDRStub);
+
+ if (SUCCEEDED(hr))
+ {
+ OXIDEntry *pOXIDEntry = _pChnl->GetOXIDEntry();
+
+ IPID ipidDummy;
+ hr = AddIPIDEntry(pOXIDEntry, &ipidDummy, riid, _pChnl, pStub, pv,
+ ppEntry);
+
+ if (SUCCEEDED(hr))
+ {
+ if (_dwFlags & SMFLAGS_NOPING)
+ {
+ // object does no need pinging, turn on NOPING
+ (*ppEntry)->dwFlags |= IPIDF_NOPING;
+ }
+
+ if (fNonNDRStub)
+ {
+ // the stub was a custom 16bit one requested by WOW, mark the
+ // IPIDEntry as holding a non-NDR stub so we know to set the
+ // SORF_NONNDR flag in the StdObjRef when marshaling. This
+ // tells local clients whether to create a MIDL generated
+ // proxy or custom proxy. Functionality to support OLE
+ // Automation on DCOM.
+
+ (*ppEntry)->dwFlags |= IPIDF_NONNDRSTUB;
+ }
+
+ // increment the OXIDEntry ref count so that it stays
+ // around as long as the IPIDEntry points to it. It gets
+ // decremented when we disconnect the IPIDEntry.
+
+ IncOXIDRefCnt(pOXIDEntry);
+
+ // chain the IPIDEntries for this OID together
+
+ (*ppEntry)->pNextOID = _pFirstIPID;
+ _pFirstIPID = *ppEntry;
+ }
+ else
+ {
+ // release the stub. we need to release the lock to do this.
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ pStub->Release();
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+ }
+
+ ASSERT_LOCK_HELD
+ AssertDisconnectPrevented();
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: MakeCliIPIDEntry, private
+//
+// Synopsis: creates a client side IPID table entry
+//
+// Arguements: [riid] - the interface to return
+// [pStd] - standard objref
+// [pOXIDEntry] - OXIDEntry of the server
+// [ppEntry] - IPIDEntry returned
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::MakeCliIPIDEntry(REFIID riid, STDOBJREF *pStd,
+ OXIDEntry *pOXIDEntry,
+ IPIDEntry **ppEntry)
+{
+ Win4Assert(ClientSide());
+ AssertValid();
+ AssertDisconnectPrevented();
+ Win4Assert(pOXIDEntry);
+ ASSERT_LOCK_HELD
+
+ BOOL fNonNDRProxy;
+ void *pv;
+ IRpcProxyBuffer *pProxy;
+ HRESULT hr = CreateProxy(riid, &pProxy, &pv, &fNonNDRProxy);
+
+ if (SUCCEEDED(hr))
+ {
+ // add a disconnected IPID entry to the table.
+ hr = AddIPIDEntry(NULL, &pStd->ipid, riid, NULL, pProxy, pv, ppEntry);
+
+ if (pv)
+ {
+ // throw away our reference here, we will get it back later
+ // in UnmarshalIPID
+ ((IUnknown *)pv)->Release();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (fNonNDRProxy)
+ {
+ // the proxy is a custom 16bit one requested by WOW, mark the
+ // IPIDEntry as holding a non-NDR proxy so we know to set the
+ // LOCALF_NOTNDR flag in the local header when we call on it
+ // (see CRpcChannelBuffer::ClientGetBuffer). Functionality to
+ // support OLE Automation on DCOM.
+
+ (*ppEntry)->dwFlags |= IPIDF_NONNDRPROXY;
+ }
+
+ if (pStd->flags & SORF_NONNDR)
+ {
+ // need to remember this flag so we can tell other
+ // unmarshalers if we remarshal it.
+
+ (*ppEntry)->dwFlags |= IPIDF_NONNDRSTUB;
+ }
+
+ // connect the IPIDEntry before adding it to the table so
+ // that we dont have to worry about races between Unmarshal,
+ // Disconnect, and ReconnectProxies.
+
+ hr = ConnectIPIDEntry(pStd, pOXIDEntry, *ppEntry);
+
+ // chain the IPIDEntries for this OID together. On client side
+ // always add the entry to the list regardless of whether connect
+ // succeeded.
+
+ (*ppEntry)->pNextOID = _pFirstIPID;
+ _pFirstIPID = *ppEntry;
+
+ _cIPIDs++;
+ }
+ else
+ {
+ // could not get an IPIDEntry, release the proxy, need to
+ // release the lock to do this.
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ pProxy->Release();
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+ }
+
+ ASSERT_LOCK_HELD
+ AssertDisconnectPrevented();
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: ConnectIPIDEntry, private
+//
+// Synopsis: connects a client side IPID table entry to the server
+//
+// Arguments: [pStd] - standard objref
+// [pOXIDEntry] - OXIDEntry for the server
+// [pEntry] - IPIDEntry to connect, already has a proxy
+// and the IID filled in.
+//
+// Notes: This routine is re-entrant, it may be called multiple
+// times for the same IPIDEntry, with part of the work done
+// in one call and part in another. Only if the entry is
+// fully set up will it return S_OK and mark the entry as
+// connected. DisconnectCliIPIDs handles cleanup of partial
+// connections.
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::ConnectIPIDEntry(STDOBJREF *pStd,
+ OXIDEntry *pOXIDEntry,
+ IPIDEntry *pEntry)
+{
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::ConnectIPIDEntry this:%x ipid:%I pOXIDEntry:%x pIPIDEntry:%x\n",
+ this, &pStd->ipid, pOXIDEntry, pEntry));
+ Win4Assert(ClientSide());
+ AssertDisconnectPrevented();
+ AssertValid();
+ Win4Assert(pOXIDEntry);
+ ASSERT_LOCK_HELD
+ HRESULT hr = S_OK;
+
+ // mark the object as having attempted to connect an IPIDEntry so that
+ // if we fail somewhere in this routine and dont mark the whole object
+ // as connected, Disconnect will still try to clean things up.
+
+ _dwFlags |= SMFLAGS_TRIEDTOCONNECT;
+
+ if (!(pStd->flags & SORF_NOPING))
+ {
+ // this interface requires pinging, turn off NOPING for this object
+ // and this IPIDEntry.
+ _dwFlags &= ~SMFLAGS_NOPING;
+ pEntry->dwFlags &= ~IPIDF_NOPING;
+ }
+
+ if (!(_dwFlags & (SMFLAGS_REGISTEREDOID | SMFLAGS_NOPING)))
+ {
+ // register the OID with the ping server so it will get pinged
+ hr = gResolver.ClientRegisterOIDWithPingServer(pStd->oid, pOXIDEntry);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ _dwFlags |= SMFLAGS_REGISTEREDOID;
+ }
+
+ // Go get any references we need that are not already included in the
+ // STDOBJREF. These references will have been added to the counts in
+ // the IPIDEntry upon return. Any references in the STDOBJREF will be
+ // added to the IPIDEntry count only if the connect succeeds, otherwise
+ // ReleaseMarshalObjRef (which will clean up STDOBJREF references) will
+ // get called by higher level code.
+
+ hr = GetNeededRefs(pStd, pOXIDEntry, pEntry);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ if (pEntry->pChnl == NULL)
+ {
+ // create a channel for this oxid/ipid pair. On the client side we
+ // create one channel per proxy (and hence per IPID).
+
+ hr = CreateChannel(pOXIDEntry, pStd->flags, pStd->ipid,
+ pEntry->iid, &pEntry->pChnl);
+
+ if (SUCCEEDED(hr))
+ {
+ // update this IPID table entry. must update ipid too since
+ // on reconnect it differs from the old value.
+
+ IncOXIDRefCnt(pOXIDEntry);
+ pEntry->pOXIDEntry = pOXIDEntry;
+ pEntry->ipid = pStd->ipid;
+ pEntry->pChnl->SetIPIDEntry(pEntry);
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // Release the lock while we connect the proxy. We have to do
+ // this because the IDispatch proxy makes an Rpc call during
+ // Connect (Yuk!), which causes the channel to assert that the
+ // lock is released. The proxy MUST be able to handle multiple
+ // simultaneous or nested connects to the same channel ptr, since
+ // it is possible when we yield the lock for another thread to
+ // come in here and try a connect.
+
+ void *pv = NULL;
+ IRpcProxyBuffer * pProxy = (IRpcProxyBuffer *)(pEntry->pStub);
+
+ if (pProxy)
+ {
+ // HACKALERT: OleAutomation returns NULL pv in CreateProxy
+ // in cases where they dont know whether to return an NDR
+ // proxy or a custom-format proxy. So we have to go connect
+ // the proxy first then Query for the real interface once that
+ // is done.
+
+ BOOL fGetpv = (pEntry->pv) ? FALSE : TRUE;
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ hr = pProxy->Connect(pEntry->pChnl);
+ if (fGetpv && SUCCEEDED(hr))
+ {
+#ifdef WX86OLE
+ if (gcwx86.IsN2XProxy(pProxy))
+ {
+ // If we are creating a proxy for an object that is
+ // living on the x86 side then we need to set the
+ // StubInvoke flag to allow QI to thunk the
+ // custom interface QI.
+ gcwx86.SetStubInvokeFlag((BOOL)2);
+ }
+#endif
+ hr = pProxy->QueryInterface(pEntry->iid, &pv);
+ AssertOutPtrIface(hr, pv);
+
+ if(SUCCEEDED(hr))
+ {
+#ifdef WX86OLE
+ // Call whole32 thunk layer to play with the ref count
+ // and aggregate the proxy to the controlling unknown.
+ gcwx86.AggregateProxy(_pStdId->GetCtrlUnk(),
+ (IUnknown *)pv);
+#endif
+ // Release our reference here.
+ // We keep a weak reference to pv.
+ ((IUnknown *)pv)->Release();
+ }
+ }
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+
+ // Regardless of errors from Connect and QI we wont try to cleanup
+ // any of the work we have done so far in this routine. The routine
+ // is reentrant (by the same thread or by different threads) and
+ // those calls could be using some of resources we have already
+ // allocated. Instead, we rely on DisconnectCliIPIDs to cleanup
+ // the partial allocation of resources.
+
+ if (pEntry->dwFlags & IPIDF_DISCONNECTED)
+ {
+ // Mark the IPIDEntry as connected so we dont try to connect
+ // again. Also, as long as there is one IPID connected, the
+ // whole object is considered connected. This allows disconnect
+ // to find the newly connected IPID and disconnect it later.
+ // Infact, DisconnectCliIPIDs relies on there being at least
+ // one IPID with a non-NULL OXIDEntry. It is safe to set this
+ // now because Disconnects have been temporarily turned off.
+
+ if (SUCCEEDED(hr))
+ {
+ if (pv)
+ {
+ // assign the interface pointer
+ pEntry->pv = pv;
+ }
+
+ AssertDisconnectPrevented();
+ pEntry->dwFlags &= ~IPIDF_DISCONNECTED;
+ _dwFlags &= ~SMFLAGS_DISCONNECTED;
+ }
+ }
+ else
+ {
+ // while the lock was released, the IPIDEntry got connected
+ // by another thread (or by a nested call on this thread).
+ // Ignore any errors from Connect or QI since apparently
+ // things are connected now.
+
+ hr = S_OK;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // Add in any references we were given. If we were given 0 refs
+ // and the interface is noping, then pretend like we got 1 ref.
+
+ ULONG cRefs = ((pStd->cPublicRefs == 0) && (pStd->flags & SORF_NOPING))
+ ? 1 : pStd->cPublicRefs;
+
+ // figure out if we have weak or strong references. To be weak
+ // they must be local to this machine and the SORF flag set.
+ BOOL fWeak = ((pStd->flags & SORF_WEAKREF) &&
+ (pOXIDEntry->dwFlags & OXIDF_MACHINE_LOCAL));
+
+ if (fWeak)
+ pEntry->cWeakRefs += cRefs;
+ else
+ pEntry->cStrongRefs += cRefs;
+ }
+
+ // in debug build, ensure that we did not screw up
+ ValidateIPIDEntry(pEntry);
+ }
+
+ ASSERT_LOCK_HELD
+ AssertDisconnectPrevented();
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::ConnectIPIDEntry this:%x pOXIDEntry:%x pChnl:%x hr:%x\n",
+ this, pEntry->pOXIDEntry, pEntry->pChnl, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: GetNeededRefs, private
+//
+// Synopsis: Figures out if any references are needed and goes and gets
+// them from the server.
+//
+// Arguments: [pStd] - standard objref
+// [pOXIDEntry] - OXIDEntry for the server
+// [pEntry] - IPIDEntry to connect, already has a proxy
+// and the IID filled in.
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::GetNeededRefs(STDOBJREF *pStd, OXIDEntry *pOXIDEntry,
+ IPIDEntry *pEntry)
+{
+ HRESULT hr = S_OK;
+
+ if ((pStd->flags & (SORF_NOPING | SORF_WEAKREF)) == 0)
+ {
+ // if we dont have any and weren't given any strong refs, go get some.
+ ULONG cNeedStrong = ((pEntry->cStrongRefs + pStd->cPublicRefs) == 0)
+ ? REM_ADDREF_CNT : 0;
+
+ // if we are using secure refs and we dont have any, go get some.
+ ULONG cNeedSecure = ((gCapabilities & EOAC_SECURE_REFS) &&
+ (pEntry->cPrivateRefs == 0)) ? 1 : 0;
+
+ if (cNeedStrong || cNeedSecure)
+ {
+ // Need to go get some references from the remote server. Note
+ // that we will yield here but we dont have to worry about it because
+ // the IPIDEntry is still marked as disconnected.
+
+ hr = RemoteAddRef(pEntry, pOXIDEntry, cNeedStrong, cNeedSecure);
+
+ if (SUCCEEDED(hr))
+ {
+ pEntry->cStrongRefs += cNeedStrong;
+ pEntry->cPrivateRefs += cNeedSecure;
+ }
+ }
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::ReconnectProxies
+//
+// Synopsis: Reconnects the proxies to a new server (functionality
+// used by the OLE default handler).
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+// CODEWORK: CreateServer should just ask for all these interfaces
+// during the create.
+//
+// BUGBUG: fail this call if freethreaded
+//
+//--------------------------------------------------------------------
+void CStdMarshal::ReconnectProxies()
+{
+ ComDebOut((DEB_MARSHAL,"CStdMarshal::ReconnectProxies this:%x pFirst:%x\n",
+ this, _pFirstIPID));
+ AssertValid();
+ Win4Assert(ClientSide());
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // must be at least 1 proxy already connected in order to be able
+ // to reconnect the other proxies. We cant just ASSERT that's true
+ // because we were not holding the lock on entry.
+
+ HRESULT hr = PreventDisconnect();
+
+ if (SUCCEEDED(hr))
+ {
+ // allocate a stack buffer to hold the IPIDs
+ IID *pIIDsAlloc = (IID *) _alloca(_cIPIDs * sizeof(IID));
+ IID *pIIDs = pIIDsAlloc;
+ USHORT cIIDs = 0;
+
+ IPIDEntry *pNextIPID = _pFirstIPID;
+
+ while (pNextIPID)
+ {
+ // Don't allow reconnection for fancy new servers or with
+ // secure proxies.
+ if (pNextIPID->dwFlags & IPIDF_COPY)
+ {
+ hr = E_FAIL;
+ break;
+ }
+ if ((pNextIPID->dwFlags & IPIDF_DISCONNECTED))
+ {
+ // not connected, add it to the list to be connected.
+ *pIIDs = pNextIPID->iid;
+ pIIDs++;
+ cIIDs++;
+ }
+
+ pNextIPID = pNextIPID->pNextOID;
+ }
+
+ if (cIIDs != 0 && SUCCEEDED(hr))
+ {
+ // we have looped filling in the IID list, and there are
+ // entries int he list. go call QI on server now and
+ // unmarshal the results.
+
+ hr = RemQIAndUnmarshal(cIIDs, pIIDsAlloc, NULL);
+ }
+ }
+
+ DbgWalkIPIDs();
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ // this will handle any Disconnect that came in while we were busy.
+ hr = HandlePendingDisconnect(hr);
+
+ ComDebOut((DEB_MARSHAL,"CStdMarshal::ReconnectProxies [OUT] this:%x\n", this));
+ return;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::ReleaseMarshalData, public
+//
+// Synopsis: Releases the references added by MarshalInterface
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CStdMarshal::ReleaseMarshalData(LPSTREAM pStm)
+{
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::ReleaseMarshalData this:%x pStm:%x\n", this, pStm));
+ AssertValid();
+ ASSERT_LOCK_RELEASED
+
+ OBJREF objref;
+ HRESULT hr = ReadObjRef(pStm, objref);
+
+ if (SUCCEEDED(hr))
+ {
+ // call worker API to do the rest of the work
+ hr = ::ReleaseMarshalObjRef(objref);
+
+ // deallocate the objref we read
+ FreeObjRef(objref);
+ }
+
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::ReleaseMarshalData this:%x hr:%x\n", this, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: ReleaseMarshalObjRef, private
+//
+// Synopsis: Releases the references added by MarshalObjRef
+//
+// Arguements: [objref] - object reference
+//
+// Algorithm: Get the correct standard identity and ask it to do
+// a ReleaseMarshalData.
+//
+// History: 19-Jun-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+INTERNAL ReleaseMarshalObjRef(OBJREF &objref)
+{
+ ComDebOut((DEB_MARSHAL, "ReleaseMarshalObjRef objref:%x\n", &objref));
+ ASSERT_LOCK_RELEASED
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (SUCCEEDED(hr))
+ {
+ CStdMarshal *pStdMshl;
+ hr = FindStdMarshal(objref, &pStdMshl);
+
+ if (SUCCEEDED(hr))
+ {
+ // only do the RMD if on the server side.
+ if (pStdMshl->ServerSide())
+ {
+ // pass objref to subroutine to Release the marshaled data
+ hr = pStdMshl->ReleaseMarshalObjRef(objref);
+ }
+ pStdMshl->Release();
+ }
+ else
+ {
+ // we could not find or create an identity. If the server is
+ // outside this apartment, try to issue a remote release on
+ // the interface. if the OXID is local and we could not find
+ // the identity, there is nothing left to cleanup.
+
+ LOCK
+ OXIDEntry *pOXIDEntry = GetOXIDFromObjRef(objref);
+ if (pOXIDEntry != GetLocalOXIDEntry())
+ {
+ // make a remote release call
+ RemoteReleaseObjRef(objref);
+ }
+ UNLOCK
+ }
+ }
+
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_MARSHAL, "ReleaseMarshalObjRef hr:%x\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::ReleaseMarshalObjRef, public
+//
+// Synopsis: Releases the references added by MarshalObjRef
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::ReleaseMarshalObjRef(OBJREF &objref)
+{
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::ReleaseMarshalObjRef this:%x objref:%x\n", this, &objref));
+ AssertValid();
+
+ HRESULT hr = S_OK;
+ STDOBJREF *pStd = &ORSTD(objref).std;
+ ValidateSTD(pStd);
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // REFCOUNTING:
+ if (ServerSide())
+ {
+ // look for an existing IPIDEntry for the given IPID
+ IPIDEntry *pEntry;
+ hr = FindIPIDEntryByIPID(pStd->ipid, &pEntry);
+
+ if (SUCCEEDED(hr) && !(pEntry->dwFlags & IPIDF_DISCONNECTED))
+ {
+ // subtract the ref count from the IPIDEntry, may Release the
+ // StdId if this was the last reference for this IPIDEntry.
+
+ // we need to figure out how it was marshalled, strong/weak etc
+ // in order to set the flags and cRefs correctly to pass to
+ // DecSrvIPIDCnt.
+
+ if (pStd->cPublicRefs == 0)
+ {
+ // table case
+ DWORD mshlflags = (pStd->flags & SORF_TBLWEAK)
+ ? MSHLFLAGS_TABLEWEAK : MSHLFLAGS_TABLESTRONG;
+ DecSrvIPIDCnt(pEntry, 1, 0, NULL, mshlflags);
+ }
+ else
+ {
+ // normal or weak case
+ DWORD mshlflags = (pStd->flags & SORF_WEAKREF)
+ ? MSHLFLAGS_WEAK : MSHLFLAGS_NORMAL;
+ DecSrvIPIDCnt(pEntry, pStd->cPublicRefs, 0, NULL, mshlflags);
+ }
+ }
+ }
+ else // client side
+ {
+ if ((pStd->cPublicRefs == 0) || (pStd->flags & SORF_NOPING))
+ {
+ // there are no references, or this interface does not
+ // need pinging, so there is nothing to do.
+ ;
+ }
+ else
+ {
+ // look for an existing IPIDEntry for the given IPID
+ IPIDEntry *pEntry;
+ hr = FindIPIDEntryByIPID(pStd->ipid, &pEntry);
+
+ if (SUCCEEDED(hr) && !(pEntry->dwFlags & IPIDF_DISCONNECTED))
+ {
+ // add these to the cRefs of this entry, they will get freed
+ // when we do the remote release. Saves an Rpc call now.
+
+ if ((pStd->flags & SORF_WEAKREF) &&
+ (pEntry->pOXIDEntry->dwFlags & OXIDF_MACHINE_LOCAL))
+ pEntry->cWeakRefs += pStd->cPublicRefs;
+ else
+ pEntry->cStrongRefs += pStd->cPublicRefs;
+ }
+ else
+ {
+ // client side, no matching IPIDEntry so just contact the remote
+ // server to remove the reference. ignore errors since there is
+ // nothing we can do about them anyway.
+ RemoteReleaseObjRef(objref);
+ hr = S_OK;
+ }
+ }
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::ReleaseMarshalObjRef this:%x hr:%x\n", this, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::PreventDisconnect, public
+//
+// Synopsis: Prevents a Disconnect from occurring until a matching
+// HandlePendingDisconnect is called.
+//
+// History: 21-Sep-95 Rickhi Created
+//
+// The ORPC LOCK is yielded at many places in order to make calls on
+// application interfaces (server-side objects, stubs, proxies,
+// handlers, remote objects, resolver, etc). In order to keep the
+// code (reasonably?) simple, disconnects are prevented from occuring
+// while in the middle of (potentially) complex operations, and while
+// there are outstanding calls on interfaces to this object.
+//
+// To accomplish this, a counter (_cNestedCalls) is atomically incremented.
+// When _cNestedCalls != 0 and a Disconnect arrives, the object is flagged
+// as PendingDisconnect. When HandlePendingDisconnect is called, it
+// decrements the _cNestedCalls. If the _cNestedCalls == 0 and there is
+// a pending disconnect, the real Disconnect is done.
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::PreventDisconnect()
+{
+ ASSERT_LOCK_HELD
+
+ // treat this as a nested call so that if we yield, a real
+ // disconnect wont come through, instead it will be treated
+ // as pending. That allows us to avoid checking our state
+ // for Disconnected every time we yield the ORPC LOCK.
+
+ InterlockedIncrement(&_cNestedCalls);
+
+ if (_dwFlags & (SMFLAGS_DISCONNECTED | SMFLAGS_PENDINGDISCONNECT))
+ return CO_E_OBJNOTCONNECTED;
+
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::PreventPendingDisconnect, public
+//
+// Synopsis: similar to PreventDisconnect but special case for use
+// in UnmarshalObjRef (since the client side starts out
+// in the Disconnected state until the first unmarshal is done).
+//
+// History: 21-Sep-95 Rickhi Created
+//
+//+-------------------------------------------------------------------
+HRESULT CStdMarshal::PreventPendingDisconnect()
+{
+ ASSERT_LOCK_HELD
+ InterlockedIncrement(&_cNestedCalls);
+
+ if (_dwFlags &
+ (ClientSide() ? SMFLAGS_PENDINGDISCONNECT
+ : SMFLAGS_PENDINGDISCONNECT | SMFLAGS_DISCONNECTED))
+ return CO_E_OBJNOTCONNECTED;
+
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::HandlePendingDisconnect, public
+//
+// Synopsis: Reverses a call to PreventDisconnect and lets a
+// pending disconnect through.
+//
+// History: 21-Sep-95 Rickhi Created
+//
+//+-------------------------------------------------------------------
+HRESULT CStdMarshal::HandlePendingDisconnect(HRESULT hr)
+{
+ ASSERT_LOCK_RELEASED
+
+ // treat this as a nested call so that if we yield, a real
+ // disconnect wont come through, instead it will be treated
+ // as pending. That allows us to avoid checking our state
+ // for Disconnected every time we yield the ORPC LOCK.
+
+ if (InterlockedDecrement(&_cNestedCalls) == 0 &&
+ (_dwFlags & SMFLAGS_PENDINGDISCONNECT))
+ {
+ Disconnect();
+ hr = FAILED(hr) ? hr : CO_E_OBJNOTCONNECTED;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::DisconnectObject, public
+//
+// Synopsis: part of IMarshal interface, this is legal only on the
+// server side.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CStdMarshal::DisconnectObject(DWORD dwReserved)
+{
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::DisconnectObject this:%x dwRes:%x\n", this, dwReserved));
+ AssertValid();
+ ASSERT_LOCK_RELEASED
+
+ // this operation is not legal from the client side (although
+ // IProxyManager::Disconnect is), but we still have to return S_OK
+ // in either case for backward compatibility.
+
+ if (ServerSide())
+ {
+ Disconnect();
+ }
+
+ ASSERT_LOCK_RELEASED
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::Disconnect, public
+//
+// Synopsis: client side - disconnects proxies from the channel.
+// server side - disconnects stubs from the server object.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CStdMarshal::Disconnect(void)
+{
+ ComDebOut((DEB_MARSHAL, "CStdMarshal::Disconnect this:%x\n", this));
+ AssertValid();
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ if ((_dwFlags & SMFLAGS_DISCONNECTED) &&
+ !(_dwFlags & SMFLAGS_TRIEDTOCONNECT))
+ {
+ // already disconnected, no partial connects, nothing to do
+ ComDebOut((DEB_MARSHAL,"CStdMarshal::Disconnect [already done]:%x\n",this));
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ return;
+ }
+
+ // Revoke ID from the ID table if registered. This prevents other
+ // marshals/unmarshals from finding this identity that is about to
+ // be disconnected. This is the ONLY state that should change, since
+ // we dont want to screw up any work-in-progress on other threads
+ // or in calls higher up the stack.
+
+ _pStdId->RevokeOID();
+
+ if (_cNestedCalls != 0)
+ {
+ // we dont allow disconnect to occur inside a nested call since we
+ // dont want state to vanish in the middle of a call, but we do
+ // remember that we want to disconnect and will do it when the
+ // stack unwinds (or other threads complete).
+
+ _dwFlags |= SMFLAGS_PENDINGDISCONNECT;
+
+ ComDebOut((DEB_MARSHAL,"CStdMarshal::Disconnect [pending]:%x\n",this));
+ UNLOCK;
+ ASSERT_LOCK_RELEASED
+ return;
+ }
+
+
+ // No calls in progress and not already disconnected, OK to really
+ // disconnect now. First mark ourself as disconnected incase we
+ // get reentered while releasing a stub pointer.
+
+ _dwFlags |= SMFLAGS_DISCONNECTED; // turn on disconnected
+ _dwFlags &= ~(SMFLAGS_PENDINGDISCONNECT | // turn off pending disconnect
+ SMFLAGS_TRIEDTOCONNECT); // turn off tried to connect
+
+ // disconnect all our IPIDs
+ if (ServerSide())
+ DisconnectSrvIPIDs();
+ else
+ DisconnectCliIPIDs();
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ if (ServerSide())
+ {
+ // HACK - 16 and 32 bit Word 6.0 crash if you release all the objects
+ // it left lying around at CoUninitialize. Leak them.
+ COleTls tls;
+ // If we are not uninitializing, then call the release.
+ if ((tls->dwFlags & OLETLS_THREADUNINITIALIZING) == 0 ||
+
+ // If we are in WOW and the app is not word, then call the release.
+ (IsWOWThread() &&
+ (g_pOleThunkWOW->GetAppCompatibilityFlags() & OACF_NO_UNINIT_CLEANUP) == 0) ||
+
+ // If the app is not 32 bit word, then call the release.
+ !IsTaskName( L"winword.exe" ))
+ {
+ // on the server side, we have to tell the stdid to release his
+ // controlling unknown of the real object.
+ _pStdId->ReleaseCtrlUnk();
+ }
+ }
+
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_MARSHAL,"CStdMarshal::Disconnect [complete]:%x\n",this));
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::DisconnectCliIPIDs
+//
+// Synopsis: disconnects client side IPIDs for this object.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CStdMarshal::DisconnectCliIPIDs()
+{
+ ComDebOut((DEB_MARSHAL,"CStdMarshal::DisconnectCliIPIDs this:%x pFirst:%x\n",
+ this, _pFirstIPID));
+ Win4Assert(ClientSide());
+ Win4Assert(_dwFlags & SMFLAGS_DISCONNECTED);
+
+ // YIELD WARNING: Do not yield between here and the matching comment
+ // below, since we are mucking with internal state that could get
+ // messed up if a reconnect (or unmarshal) is done.
+
+ ASSERT_LOCK_HELD
+
+ // on client side, we cant actually release the proxies until the
+ // object goes away (backward compatibility), so we just release
+ // our references to the remote guy, disconnect the proxies, and
+ // delete the channels, but hold on to the IPIDEntries.
+
+ REMINTERFACEREF *pRifRefAlloc = (REMINTERFACEREF *)
+ _alloca(_cIPIDs * 2 * sizeof(REMINTERFACEREF));
+ REMINTERFACEREF *pRifRef = pRifRefAlloc;
+
+
+ OXIDEntry *pOXID = NULL;
+ USHORT cRifRef = 0;
+ IPIDEntry *pEntry = _pFirstIPID;
+
+ while (pEntry)
+ {
+ // we have to handle the case where ConnectIPIDEntry partially (but
+ // not completely) set up the IPIDEntry, hence we cant just check
+ // for the IPIDF_DISCONNECTED flag.
+
+ ValidateIPIDEntry(pEntry);
+
+ // NOTE: we are calling Proxy code here while holding the ORPC LOCK.
+ // There is no way to get around this without introducing race
+ // conditions. We cant just disconnect the channel and leave the
+ // proxy connected cause some proxies (like IDispatch) do weird shit,
+ // like keeping separate pointers to the server.
+
+ if (pEntry->pStub) // NULL for IUnknown IPID
+ {
+ ComDebOut((DEB_MARSHAL, "Disconnect pProxy:%x\n", pEntry->pStub));
+ ((IRpcProxyBuffer *)pEntry->pStub)->Disconnect();
+ pEntry->pv = NULL;
+ }
+
+ if (!(pEntry->dwFlags & IPIDF_NOPING))
+ {
+ // the object pays attention to pings (and hence refcounts)
+
+ if (pEntry->cStrongRefs > 0 || pEntry->cPrivateRefs > 0)
+ {
+ // we own some strong references on this interface, fill
+ // in an interfaceref so we release them.
+
+ pRifRef->cPublicRefs = pEntry->cStrongRefs;
+ pRifRef->cPrivateRefs = pEntry->cPrivateRefs;
+ pRifRef->ipid = pEntry->ipid;
+ pRifRef++;
+ cRifRef++;
+ }
+
+ if (pEntry->cWeakRefs > 0)
+ {
+ // we own some weak references on this interface, fill
+ // in an interfaceref so we release them.
+
+ pRifRef->cPublicRefs = pEntry->cWeakRefs;
+ pRifRef->cPrivateRefs = 0;
+ pRifRef->ipid = pEntry->ipid;
+
+ // mark the IPID as weak so that RemRelease on the server
+ // knows to release weak references instead of strong refs.
+
+ pRifRef->ipid.Data1 |= IPIDFLAG_WEAKREF;
+ pRifRef++;
+ cRifRef++;
+ }
+ }
+
+ pEntry->cStrongRefs = 0;
+ pEntry->cWeakRefs = 0;
+ pEntry->cPrivateRefs = 0;
+ pEntry->dwFlags |= IPIDF_DISCONNECTED | IPIDF_NOPING;
+
+ if (pEntry->pChnl)
+ {
+ // release the channel for this IPID
+ pEntry->pChnl->Release();
+ pEntry->pChnl = NULL;
+ }
+
+ if (pEntry->pOXIDEntry)
+ {
+ // We will be decrementing the OXID refcnt as we release IPIDEntries
+ // but we dont want the OXIDEntry to go away until after we make the
+ // RemoteRelease call below, so we hold on to it here.
+
+ if (pOXID == NULL)
+ {
+ pOXID = pEntry->pOXIDEntry;
+ IncOXIDRefCnt(pOXID);
+ }
+
+ // If we ever go to a model where different IPIDEntries on the
+ // same object can point to different OXIDEntires, then we need
+ // to re-write this code to batch the releases by OXID.
+ Win4Assert(pOXID == pEntry->pOXIDEntry);
+
+ // release the RefCnt on the OXIDEntry
+ DecOXIDRefCnt(pEntry->pOXIDEntry);
+ pEntry->pOXIDEntry = NULL;
+ }
+
+ // get next IPID in chain for this object
+ pEntry = pEntry->pNextOID;
+ }
+
+ if (_pChnl)
+ {
+ // release the last client side channel
+ _pChnl->Release();
+ _pChnl = NULL;
+ }
+
+ if (_dwFlags & SMFLAGS_REGISTEREDOID)
+ {
+ // Tell the resolver to stop pinging the OID. The OID is only
+ // registered on the client side.
+
+ Win4Assert(ClientSide());
+ gResolver.ClientDeRegisterOIDFromPingServer(_pStdId->GetOID(),
+ _dwFlags & SMFLAGS_CLIENTMARSHALED);
+
+ }
+
+ // turn these flags off so re-connect (with new OID) will behave properly.
+ _dwFlags &= ~(SMFLAGS_CLIENTMARSHALED | SMFLAGS_REGISTEREDOID |
+ SMFLAGS_NOPING);
+
+
+ // YIELD WARNING: Up this this point we have been mucking with our
+ // internal state. We cant yield before this point or a reconnect
+ // proxies could get all screwed up. It is OK to yield after this point
+ // because all internal state changes are now complete. The function
+ // to release the remote references yield.
+
+ if (cRifRef != 0)
+ {
+ // we have looped filling in the RifRef and entries exist in the
+ // array. go call the server now to release the IPIDs.
+
+ Win4Assert(pOXID); // must have been at least one
+ RemoteReleaseRifRef(pOXID, cRifRef, pRifRefAlloc);
+ }
+
+ if (pOXID)
+ {
+ // Now release the refcnt (if any) we put on the OXIDEntry above
+ // to hold it
+ DecOXIDRefCnt(pOXID);
+ }
+
+ ASSERT_LOCK_HELD
+ DbgWalkIPIDs();
+ ComDebOut((DEB_MARSHAL, "CStdMarshal::DisconnectCliIPIDs this:%x\n",this));
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::DisconnectSrvIPIDs
+//
+// Synopsis: disconnects the server side IPIDs for this object.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CStdMarshal::DisconnectSrvIPIDs()
+{
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::DisconnectSrvIPIDs this:%x pFirst:%x\n",this, _pFirstIPID));
+ Win4Assert(ServerSide());
+
+ // there should be no other threads looking at these IPIDs at this time,
+ // since Marshal, Unmarshal, and Dispatch all call PreventDisconnect,
+ // Disconnect checks the disconnected flag directly, RMD holds the
+ // lock over it's whole execution, RemAddRef and RemRelease hold the
+ // lock and check the disconnected flag of the IPIDEntry, and
+ // RemQueryInterface calls PreventDisconnect.
+
+ Win4Assert(_dwFlags & SMFLAGS_DISCONNECTED);
+ Win4Assert(_cNestedCalls == 0);
+ ASSERT_LOCK_HELD
+
+
+ // while holding the lock, flag each IPID as disconnected so that no
+ // more incoming calls are dispatched to this object. We also unchain
+ // the IPIDs to ensure that no other threads are pointing at them.
+
+ IPIDEntry *pFirstIPID = _pFirstIPID;
+ _pFirstIPID = NULL;
+
+ IPIDEntry *pEntry = pFirstIPID;
+ while (pEntry)
+ {
+ pEntry->dwFlags |= IPIDF_VACANT | IPIDF_DISCONNECTED;
+
+ // release the refcnt on the OXIDEntry and NULL it
+ DecOXIDRefCnt(pEntry->pOXIDEntry);
+ pEntry->pOXIDEntry = NULL;
+
+ pEntry = pEntry->pNextOID;
+ }
+
+
+ // now release the LOCK since we will be calling into app code to
+ // disconnect the stubs, and to release the external connection counts.
+ // There should be no other pointers to these IPIDEntries now, so it
+ // is safe to muck with their fields (except the dwFlags which is looked
+ // at by Dispatch and was already set above).
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ IPIDEntry *pLastIPID;
+ pEntry = pFirstIPID;
+
+ while (pEntry)
+ {
+ if (pEntry->dwFlags & IPIDF_NOTIFYACT)
+ {
+ // the activation code asked to be notified when the refcnt
+ // on this interface reaches zero. Turn the flag off so we
+ // don't call twice.
+ pEntry->dwFlags &= ~IPIDF_NOTIFYACT;
+ NotifyActivation(FALSE, (IUnknown *)(pEntry->pv));
+ }
+
+ if (pEntry->pStub) // pStub is NULL for IUnknown IPID
+ {
+ ComDebOut((DEB_MARSHAL, "Disconnect pStub:%x\n", pEntry->pStub));
+ ((IUnknown *)pEntry->pv)->Release();
+ ((IRpcStubBuffer *)pEntry->pStub)->Disconnect();
+ pEntry->pStub->Release();
+ pEntry->pStub = NULL;
+ pEntry->pv = NULL;
+ }
+
+ if (pEntry->cWeakRefs > 0)
+ {
+ // Release weak references on the StdId.
+ pEntry->cWeakRefs = 0;
+ _pStdId->Release();
+ }
+
+ if (pEntry->cStrongRefs > 0)
+ {
+ // Release strong references on the StdId. Note that 16bit
+ // 16bit OLE always passed fLastReleaseCloses = FALSE in
+ // DisconnectObject so we do the same here.
+
+ pEntry->cStrongRefs = 0;
+ _pStdId->DecStrongCnt(TRUE); // fKeepAlive
+ }
+
+ if (pEntry->cPrivateRefs > 0)
+ {
+ // Release private references on the StdId. Note that 16bit
+ // 16bit OLE always passed fLastReleaseCloses = FALSE in
+ // DisconnectObject so we do the same here.
+
+ pEntry->cPrivateRefs = 0;
+ _pStdId->DecStrongCnt(TRUE); // fKeepAlive
+ }
+ pLastIPID = pEntry;
+ pEntry = pEntry->pNextOID;
+ }
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ if (pFirstIPID)
+ {
+ // now we release all entries.
+ gIPIDTbl.ReleaseEntryList(pFirstIPID, pLastIPID);
+ }
+
+ ASSERT_LOCK_HELD
+ DbgWalkIPIDs();
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::DisconnectSrvIPIDs [OUT] this:%x\n",this));
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::InstantiatedProxy, public
+//
+// Synopsis: return requested interfaces to the caller if instantiated
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+BOOL CStdMarshal::InstantiatedProxy(REFIID riid, void **ppv, HRESULT *phr)
+{
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::InstantiatedProxy this:%x riid:%I ppv:%x\n",
+ this, &riid, ppv));
+ AssertValid();
+ Win4Assert(ClientSide());
+ Win4Assert(*ppv == NULL);
+ Win4Assert(*phr == S_OK);
+
+ BOOL fRet = FALSE;
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // look for an existing IPIDEntry for the requested interface
+ IPIDEntry *pEntry;
+ HRESULT hr = FindIPIDEntry(riid, &pEntry);
+
+ if (SUCCEEDED(hr) && pEntry->pv)
+ {
+ // found the ipid entry, now extract the interface
+ // pointer to return to the caller.
+
+ Win4Assert(IsValidInterface(pEntry->pv));
+ *ppv = pEntry->pv;
+ fRet = TRUE;
+ }
+ else if (_cIPIDs == 0)
+ {
+ // no IPIDEntry for the requested interface, and we have never
+ // been connected to the server. Return E_NOINTERFACE in this
+ // case. This is different from having been connected then
+ // disconnected, where we return CO_E_OBJNOTCONNECTED.
+
+ *phr = E_NOINTERFACE;
+ Win4Assert(fRet == FALSE);
+ }
+ else if (_dwFlags & SMFLAGS_PENDINGDISCONNECT)
+ {
+ // no IPIDEntry for the requested interface and disconnect is
+ // pending, so return an error.
+
+ *phr = CO_E_OBJNOTCONNECTED;
+ Win4Assert(fRet == FALSE);
+ }
+ else
+ {
+ // no IPIDEntry, we are not disconnected, and we do have other
+ // instantiated proxies. QueryMultipleInterfaces expects
+ // *phr == S_OK and FALSE returned.
+
+ Win4Assert(*phr == S_OK);
+ Win4Assert(fRet == FALSE);
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::InstantiatedProxy hr:%x pv:%x fRet:%x\n", *phr, *ppv, fRet));
+ return fRet;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::QueryRemoteInterfaces, public
+//
+// Synopsis: return requested interfaces to the caller if supported
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::QueryRemoteInterfaces(USHORT cIIDs, IID *pIIDs, SQIResult *pQIRes)
+{
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::QueryRemoteInterfaces this:%x pIIDs:%x pQIRes:%x\n",
+ this, pIIDs, pQIRes));
+ AssertValid();
+ Win4Assert(ClientSide());
+ Win4Assert(cIIDs > 0);
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ HRESULT hr = PreventDisconnect();
+
+ if (SUCCEEDED(hr))
+ {
+ // call QI on the remote guy and unmarshal the results
+ hr = RemQIAndUnmarshal(cIIDs, pIIDs, pQIRes);
+ }
+ else
+ {
+ // cant call out because we're disconnected so return error for
+ // each requested interface.
+ for (USHORT i=0; i<cIIDs; i++, pQIRes++)
+ {
+ pQIRes->hr = hr;
+ }
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ // if the object was disconnected while in the middle of the call,
+ // then we still return SUCCESS for any interfaces we acquired. The
+ // reason is that we do have the proxies, and this matches the
+ // behaviour of a QI for an instantiated proxy on a disconnected
+ // object.
+
+ hr = HandlePendingDisconnect(hr);
+
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::QueryRemoteInterfaces this:%x hr:%x\n", this, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::RemQIAndUnmarshal, private
+//
+// Synopsis: call QI on remote guy, then unmarshal the STDOBJREF
+// to create the IPID, and return the interface ptr.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+// Notes: Caller must guarantee at least one IPIDEntry is connected.
+// This function does a sparse fill of the result array.
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::RemQIAndUnmarshal(USHORT cIIDs, IID *pIIDs,
+ SQIResult *pQIRes)
+{
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::RemQIAndUnmarshal this:%x cIIDs:%x pIIDs:%x pQIRes:%x\n",
+ this, cIIDs, pIIDs, pQIRes));
+ AssertValid();
+ AssertDisconnectPrevented();
+ Win4Assert(_pFirstIPID); // must be at least 1 IPIDEntry
+ ASSERT_LOCK_HELD
+
+ // we need an IPID to call RemoteQueryInterface with, any one will
+ // do so long as it is connected (in the reconnect case there may be
+ // only one connected IPID) so we pick the first one in the chain that
+ // is connected.
+
+ IPIDEntry *pIPIDEntry = GetConnectedIPID();
+
+ // remember what type of reference to get since we yield the lock
+ // and cant rely on _dwFlags later.
+ BOOL fWeakClient = (_dwFlags & SMFLAGS_WEAKCLIENT);
+
+ // call the remote guy
+ REMQIRESULT *pRemQiRes = NULL;
+ IRemUnknown *pRemUnk;
+ HRESULT hr = GetSecureRemUnk( &pRemUnk, pIPIDEntry->pOXIDEntry );
+ if (SUCCEEDED(hr))
+ {
+ hr = RemoteQueryInterface(pRemUnk, pIPIDEntry, cIIDs, pIIDs, &pRemQiRes,
+ fWeakClient);
+ }
+
+ // need to remember the result ptr so we can free it.
+ REMQIRESULT *pRemQiResNext = pRemQiRes;
+
+ // unmarshal each STDOBJREF returned. Note that while we did the
+ // RemoteQI we could have yielded (or nested) and did another
+ // RemoteQI for the same interfaces, so we have to call UnmarshalIPID
+ // which will find any existing IPIDEntry and bump its refcnt.
+
+ HRESULT hr2;
+ HRESULT *phr = &hr2;
+ void *pv;
+ void **ppv = &pv;
+
+ for (USHORT i=0; i<cIIDs; i++)
+ {
+ if (pQIRes)
+ {
+ // caller wants the pointers returned, set ppv and phr.
+ ppv = &pQIRes->pv;
+ phr = &pQIRes->hr;
+ pQIRes++;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (SUCCEEDED(pRemQiResNext->hResult))
+ {
+ if (fWeakClient)
+ {
+ // mark the std objref with the weak reference flag so
+ // that UnmarshalIPID adds the references to the correct
+ // count.
+ pRemQiResNext->std.flags |= SORF_WEAKREF;
+ }
+
+ *phr = UnmarshalIPID(*pIIDs, &pRemQiResNext->std,
+ pIPIDEntry->pOXIDEntry,
+ (pQIRes) ? ppv : NULL);
+
+ if (FAILED(*phr))
+ {
+ // could not unmarshal, release the resources with the
+ // server.
+ RemoteReleaseStdObjRef(&pRemQiResNext->std,
+ pIPIDEntry->pOXIDEntry);
+ }
+ }
+ else if (pQIRes)
+ {
+ // the requested interface was not returned so set the
+ // return code and interface ptr.
+ *phr = pRemQiResNext->hResult;
+ *ppv = NULL;
+ }
+
+ pIIDs++;
+ pRemQiResNext++;
+ }
+ else
+ {
+ // the whole call failed so return the error for each
+ // requested interface.
+ *phr = hr;
+ *ppv = NULL;
+ }
+
+ // make sure the ptr value is NULL on failure. It may be NULL or
+ // non-NULL on success. (ReconnectProxies wants NULL).
+ Win4Assert(SUCCEEDED(*phr) || *ppv == NULL);
+ }
+
+ // free the result buffer
+ CoTaskMemFree(pRemQiRes);
+
+ ASSERT_LOCK_HELD
+ AssertDisconnectPrevented();
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::RemQIAndUnmarshal this:%x hr:%x\n", this, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::RemIsConnected, private
+//
+// Synopsis: Returns TRUE if most likely connected, FALSE if definitely
+// not connected or pending disconnect.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+BOOL CStdMarshal::RemIsConnected(void)
+{
+ AssertValid();
+ Assert(ClientSide());
+
+ // the default link depends on us returning FALSE if we are either
+ // disconnected or just pending disconnect, in order that they avoid
+ // running their cleanup code twice.
+
+ BOOL fRes = (_dwFlags & (SMFLAGS_DISCONNECTED | SMFLAGS_PENDINGDISCONNECT))
+ ? FALSE : TRUE;
+
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::RemIsConnected this:%x fResult:%x\n", this, fRes));
+ return fRes;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CreateChannel, private
+//
+// Synopsis: Creates an instance of the Rpc Channel.
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::CreateChannel(OXIDEntry *pOXIDEntry, DWORD dwFlags,
+ REFIPID ripid, REFIID riid, CRpcChannelBuffer **ppChnl)
+{
+ ASSERT_LOCK_HELD
+ HRESULT hr = S_OK;
+
+ if (_pChnl == NULL)
+ {
+ DWORD cState = ServerSide() ? server_cs : client_cs;
+ cState |= (dwFlags & SORF_FREETHREADED) ? freethreaded_cs : 0;
+
+ // make a channel. We dont need the call control stuff so just
+ // create the base class.
+
+ _pChnl = new CRpcChannelBuffer(_pStdId, pOXIDEntry, cState);
+
+ if (_pChnl == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+
+ if (SUCCEEDED(hr) && ClientSide())
+ {
+ *ppChnl = _pChnl->Copy(pOXIDEntry, ripid, riid);
+ if (*ppChnl == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ *ppChnl = _pChnl;
+ }
+
+ ASSERT_LOCK_HELD
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: GetPSFactory, private
+//
+// Synopsis: loads the proxy/stub factory for given IID
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::GetPSFactory(REFIID riid, IUnknown *pUnkWow, BOOL fServer,
+ IPSFactoryBuffer **ppIPSF, BOOL *pfNonNDR)
+{
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::GetPSFactory this:%x riid:%I pUnkWow:%x\n",
+ this, &riid, pUnkWow));
+ ASSERT_LOCK_RELEASED
+
+ // map iid to classid
+ CLSID clsid;
+ HRESULT hr = gRIFTbl.RegisterInterface(riid, fServer, &clsid);
+#ifdef WX86OLE
+ BOOL fWx86 = FALSE;
+#endif
+
+ if (SUCCEEDED(hr))
+ {
+ BOOL fWow = FALSE;
+
+ if (IsWOWThread())
+ {
+ // figure out if this is a custom interface from a 16bit
+ // app, since we have to load the 16bit proxy code if so.
+
+ IThunkManager *pThkMgr;
+ g_pOleThunkWOW->GetThunkManager(&pThkMgr);
+ Win4Assert(pThkMgr && "pUnk in WOW does not support IThunkManager.");
+
+ if (pUnkWow)
+ fWow = pThkMgr->IsCustom3216Proxy(pUnkWow, riid);
+ else
+ fWow = pThkMgr->IsIIDRequested(riid);
+
+ pThkMgr->Release();
+ }
+
+#ifdef WX86OLE
+ // If we are in a Wx86 process then we need to determine if the
+ // PSFactory needs to be an x86 or native one.
+ else if (gcwx86.IsWx86Enabled())
+ {
+ // Callout to wx86 to ask it to determine if an x86 PS factory
+ // is required. Whole32 can tell if the stub needs to be x86
+ // by determining if pUnkWow is a custom interface proxy or not.
+ // Whole32 can determine if a x86 proxy is required by checking
+ // if the riid is one for a custom interface that is expected
+ // to be returned.
+ fWx86 = gcwx86.NeedX86PSFactory(pUnkWow, riid);
+ }
+#endif
+
+ // if we are loading a 16bit custom proxy then mark it as non NDR
+ *pfNonNDR = (fWow) ? TRUE : FALSE;
+
+ if (IsEqualGUID(clsid, CLSID_PSOlePrx32))
+ {
+ // its our internal CLSID so go straight to our class factory.
+ hr = PrxDllGetClassObject(clsid, IID_IPSFactoryBuffer,
+ (void **)ppIPSF);
+ }
+ else
+ {
+#ifdef WX86OLE
+ DWORD dwContext = fWow ? CLSCTX_INPROC_SERVER16
+ : (fWx86 ? CLSCTX_INPROC_SERVERX86 :
+ CLSCTX_INPROC_SERVER)
+ | CLSCTX_PS_DLL;
+#else
+ DWORD dwContext = fWow ? CLSCTX_INPROC_SERVER16
+ : CLSCTX_INPROC_SERVER | CLSCTX_PS_DLL;
+#endif
+
+ // load the dll and get the PS class object
+ hr = ICoGetClassObject(clsid, dwContext, NULL, IID_IPSFactoryBuffer,
+ (void **)ppIPSF);
+#ifdef WX86OLE
+ if (fWx86 && FAILED(hr))
+ {
+ // if we are looking for an x86 PSFactory and we didn't find
+ // one on InprocServerX86 key then we need to check
+ // InprocServer32 key as well.
+ hr = ICoGetClassObject(clsid,
+ CLSCTX_INPROC_SERVER | CLSCTX_PS_DLL,
+ NULL, IID_IPSFactoryBuffer,
+ (void **)ppIPSF);
+
+ if (SUCCEEDED(hr) &&
+ (! gcwx86.IsN2XProxy((IUnknown *)*ppIPSF)))
+ {
+ ((IUnknown *)*ppIPSF)->Release();
+ hr = REGDB_E_CLASSNOTREG;
+ }
+ }
+#endif
+ AssertOutPtrIface(hr, *ppIPSF);
+ }
+ }
+
+#if DBG==1
+ // if the fake NonNDR flag is set and its the test interface, then
+ // trick the code into thinking this is a nonNDR proxy. This is to
+ // enable simpler testing of an esoteric feature.
+
+ if (gfFakeNonNDR && IsEqualIID(riid, IID_ICube))
+ {
+ *pfNonNDR = TRUE;
+ }
+#endif
+
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::GetPSFactory this:%x pIPSF:%x fNonNDR:%x hr:%x\n",
+ this, *ppIPSF, *pfNonNDR, hr));
+
+ ASSERT_LOCK_RELEASED
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CreateProxy, private
+//
+// Synopsis: creates an interface proxy for the given interface
+//
+// Returns: [ppv] - interface of type riid, AddRef'd
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::CreateProxy(REFIID riid, IRpcProxyBuffer **ppProxy,
+ void **ppv, BOOL *pfNonNDR)
+{
+ TRACECALL(TRACE_MARSHAL, "CreateProxy");
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::CreateProxy this:%x riid:%I\n", this, &riid));
+ AssertValid();
+ Win4Assert(ClientSide());
+ Win4Assert(ppProxy != NULL);
+ ASSERT_LOCK_HELD
+
+ // get the controlling IUnknown of this object
+ IUnknown *punkCtrl = _pStdId->GetCtrlUnk();
+ Win4Assert(punkCtrl != NULL);
+
+ if (InlineIsEqualGUID(riid, IID_IUnknown))
+ {
+ // there is no proxy for IUnknown so we handle that case here
+ punkCtrl->AddRef();
+ *ppv = (void **)punkCtrl;
+ *ppProxy = NULL;
+ *pfNonNDR = FALSE;
+ return S_OK;
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ // now construct the proxy for the interface
+ IPSFactoryBuffer *pIPSF = NULL;
+ HRESULT hr = GetPSFactory(riid, NULL, FALSE, &pIPSF, pfNonNDR);
+
+ if (SUCCEEDED(hr))
+ {
+ // got the class factory, now create an instance
+ hr = pIPSF->CreateProxy(punkCtrl, riid, ppProxy, ppv);
+ AssertOutPtrIface(hr, *ppProxy);
+ pIPSF->Release();
+ }
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::CreateProxy this:%x pProxy:%x pv:%x fNonNDR:%x hr:%x\n",
+ this, *ppProxy, *ppv, *pfNonNDR, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CreateStub, private
+//
+// Synopsis: creates an interface stub and adds it to the IPID table
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::CreateStub(REFIID riid, IRpcStubBuffer **ppStub,
+ void **ppv, BOOL *pfNonNDR)
+{
+ TRACECALL(TRACE_MARSHAL, "CreateStub");
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::CreateStub this:%x riid:%I\n", this, &riid));
+ AssertValid();
+ Win4Assert(ServerSide());
+ Win4Assert(ppStub != NULL);
+ ASSERT_LOCK_HELD
+
+ // get the IUnknown of the object
+ IUnknown *punkObj = _pStdId->GetServer();
+ Win4Assert(punkObj != NULL);
+
+ if (InlineIsEqualGUID(riid, IID_IUnknown))
+ {
+ // there is no stub for IUnknown so we handle that here
+ *ppv = (void *)punkObj;
+ *ppStub = NULL;
+ *pfNonNDR = FALSE;
+ return S_OK;
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ // make sure the object supports the given interface, so we dont
+ // waste a bunch of effort creating a stub if the interface is
+ // not supported.
+
+ IUnknown *pUnkIf = NULL;
+ HRESULT hr;
+#ifdef WX86OLE
+ if (gcwx86.IsN2XProxy(punkObj))
+ {
+ // If we are creating a stub for an object that is living on the
+ // x86 side then we need to set the StubInvoke flag to allow QI
+ // to thunk the custom interface QI.
+ gcwx86.SetStubInvokeFlag((BOOL)1);
+ }
+#endif
+ hr = punkObj->QueryInterface(riid, (void **)&pUnkIf);
+ AssertOutPtrIface(hr, pUnkIf);
+
+ if (SUCCEEDED(hr))
+ {
+ // now construct the stub for the interface
+ IPSFactoryBuffer *pIPSF = NULL;
+ hr = GetPSFactory(riid, pUnkIf, TRUE, &pIPSF, pfNonNDR);
+
+ if (SUCCEEDED(hr))
+ {
+ // got the class factory, now create an instance
+ hr = pIPSF->CreateStub(riid, punkObj, ppStub);
+ AssertOutPtrIface(hr, *ppStub);
+ pIPSF->Release();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // remember the interface pointer
+ *ppv = (void *)pUnkIf;
+ }
+ else
+ {
+ // error, release the interface and return NULL
+ pUnkIf->Release();
+ *ppv = NULL;
+ }
+ }
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ ComDebOut((DEB_MARSHAL,
+ "CStdMarshal::CreateStub this:%x pStub:%x pv:%x fNonNDR:%x hr:%x\n",
+ this, *ppStub, *ppv, *pfNonNDR, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: FindIPIDEntry, private
+//
+// Synopsis: Finds an IPIDEntry, chained off this object, with the
+// given riid.
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::FindIPIDEntry(REFIID riid, IPIDEntry **ppEntry)
+{
+ ComDebOut((DEB_OXID,"CStdMarshal::FindIPIDEntry ppEntry:%x riid:%I\n",
+ ppEntry, &riid));
+ ASSERT_LOCK_HELD
+
+ IPIDEntry *pEntry = _pFirstIPID;
+ while (pEntry)
+ {
+ if (InlineIsEqualGUID(riid, pEntry->iid))
+ {
+ *ppEntry = pEntry;
+ return S_OK;
+ }
+
+ pEntry = pEntry->pNextOID; // get next entry in object chain
+ }
+
+ ASSERT_LOCK_HELD
+ return E_NOINTERFACE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: FindIPIDEntryByIPID, private
+//
+// Synopsis: returns the IPIDEntry ptr for the given IPID
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::FindIPIDEntryByIPID(REFIPID ripid, IPIDEntry **ppEntry)
+{
+ ASSERT_LOCK_HELD
+
+ IPIDEntry *pEntry = _pFirstIPID;
+ while (pEntry)
+ {
+ if (InlineIsEqualGUID(pEntry->ipid, ripid))
+ {
+ *ppEntry = pEntry;
+ return S_OK;
+ }
+
+ pEntry = pEntry->pNextOID; // get next entry in object chain
+ }
+
+ ASSERT_LOCK_HELD
+ return E_NOINTERFACE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: FindIPIDEntryByInterface, internal
+//
+// Synopsis: returns the IPIDEntry ptr for the given proxy
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::FindIPIDEntryByInterface(void *pProxy, IPIDEntry **ppEntry)
+{
+ ASSERT_LOCK_HELD
+
+ IPIDEntry *pEntry = _pFirstIPID;
+ *ppEntry = NULL;
+ while (pEntry)
+ {
+ if (pEntry->pv == pProxy)
+ {
+ *ppEntry = pEntry;
+ break;
+ }
+
+ pEntry = pEntry->pNextOID;
+ }
+
+ if (*ppEntry != NULL)
+ return S_OK;
+ else
+ return E_NOINTERFACE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: IncSrvIPIDCnt, protected
+//
+// Synopsis: increments the refcnt on the IPID entry, and optionally
+// AddRefs the StdId.
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::IncSrvIPIDCnt(IPIDEntry *pEntry, ULONG cRefs,
+ ULONG cPrivateRefs, SECURITYBINDING *pName,
+ DWORD mshlflags)
+{
+ ComDebOut((DEB_MARSHAL, "IncSrvIPIDCnt this:%x pIPID:%x cRefs:%x cPrivateRefs:%x\n",
+ this, pEntry, cRefs, cPrivateRefs));
+ Win4Assert(ServerSide());
+ Win4Assert(pEntry);
+ Win4Assert(cRefs > 0 || cPrivateRefs > 0);
+ ASSERT_LOCK_HELD
+
+ HRESULT hr = S_OK;
+
+ if (cPrivateRefs != 0)
+ {
+ // Add a reference.
+ hr = gSRFTbl.IncRef( cPrivateRefs, pEntry->ipid, pName );
+
+ if (SUCCEEDED(hr))
+ {
+ BOOL fNotify = (pEntry->cPrivateRefs == 0) ? TRUE : FALSE;
+ pEntry->cPrivateRefs += cPrivateRefs;
+ if (fNotify)
+ {
+ // this inc causes the count to go from zero to non-zero, so we
+ // inc the strong count on the stdid to hold it alive until this
+ // IPID is released.
+ IncStrongAndNotifyAct(pEntry, mshlflags);
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (mshlflags & (MSHLFLAGS_TABLESTRONG | MSHLFLAGS_TABLEWEAK))
+ {
+ // Table Marshal Case: inc the number of table marshals.
+ IncTableCnt();
+ }
+
+ if (mshlflags & (MSHLFLAGS_WEAK | MSHLFLAGS_TABLEWEAK))
+ {
+ if (pEntry->cWeakRefs == 0)
+ {
+ // this inc causes the count to go from zero to non-zero, so we
+ // AddRef the stdid to hold it alive until this IPID is released.
+
+ _pStdId->AddRef();
+ }
+ pEntry->cWeakRefs += cRefs;
+ }
+ else
+ {
+ BOOL fNotify = (pEntry->cStrongRefs == 0) ? TRUE : FALSE;
+ pEntry->cStrongRefs += cRefs;
+ if (fNotify)
+ {
+ // this inc causes the count to go from zero to non-zero, so we
+ // inc the strong count on the stdid to hold it alive until this
+ // IPID is released.
+ IncStrongAndNotifyAct(pEntry, mshlflags);
+ }
+ }
+ }
+
+ ASSERT_LOCK_HELD
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: IncTableCnt, public
+//
+// Synopsis: increments the count of table marshals
+//
+// History: 9-Oct-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+void CStdMarshal::IncTableCnt(void)
+{
+ ASSERT_LOCK_HELD
+
+ // If something was marshaled for a table, we have to ignore
+ // rundowns until a subsequent RMD is called for it, at which
+ // time we start paying attention to rundowns again. Since there
+ // can be any number of table marshals, we have to refcnt them.
+
+ _cTableRefs++;
+ _dwFlags |= SMFLAGS_IGNORERUNDOWN;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: IncStrongAndNotifyAct, private
+//
+// Synopsis: notifies the activation code when this interface refcnt
+// goes from 0 to non-zero and the activation code asked to be
+// notified, and also increments the strong refcnt.
+//
+// History: 21-Apr-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+void CStdMarshal::IncStrongAndNotifyAct(IPIDEntry *pEntry, DWORD mshlflags)
+{
+ ASSERT_LOCK_HELD
+
+ // inc the strong count on the stdid to hold it alive until this
+ // IPIDEntry is released.
+
+ _pStdId->IncStrongCnt();
+ if (mshlflags & MSHLFLAGS_NOTIFYACTIVATION &&
+ !(pEntry->dwFlags & IPIDF_NOTIFYACT))
+ {
+ // the activation code asked to be notified when the refcnt
+ // on this interface goes positive, and when it reaches
+ // zero again. Set a flag so we remember to notify
+ // activation when the strong reference reference count
+ // goes back down to zero.
+ pEntry->dwFlags |= IPIDF_NOTIFYACT;
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ BOOL fOK = NotifyActivation(TRUE, (IUnknown *)(pEntry->pv));
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ if (!fOK)
+ {
+ // call failed, so dont bother notifying
+ pEntry->dwFlags &= ~IPIDF_NOTIFYACT;
+ }
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: DecSrvIPIDCnt, protected
+//
+// Synopsis: decrements the refcnt on the IPID entry, and optionally
+// Releases the StdId.
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+void CStdMarshal::DecSrvIPIDCnt(IPIDEntry *pEntry, ULONG cRefs,
+ ULONG cPrivateRefs, SECURITYBINDING *pName,
+ DWORD mshlflags)
+{
+ ComDebOut((DEB_MARSHAL, "DecSrvIPIDCnt this:%x pIPID:%x cRefs:%x cPrivateRefs:%x\n",
+ this, pEntry, cRefs, cPrivateRefs));
+ Win4Assert(ServerSide());
+ Win4Assert(pEntry);
+ Win4Assert(cRefs > 0 || cPrivateRefs > 0);
+ ASSERT_LOCK_HELD
+
+ // Note: we dont care about holding the LOCK over the Release call since
+ // the guy who called us is holding a ref to the StdId, so this Release
+ // wont cause us to go away.
+
+ if (mshlflags & (MSHLFLAGS_TABLESTRONG | MSHLFLAGS_TABLEWEAK))
+ {
+ // Table Marshal Case: dec the number of table marshals.
+ DecTableCnt();
+ }
+
+ if (mshlflags & (MSHLFLAGS_WEAK | MSHLFLAGS_TABLEWEAK))
+ {
+ Win4Assert(pEntry->cWeakRefs >= cRefs);
+ pEntry->cWeakRefs -= cRefs;
+
+ if (pEntry->cWeakRefs == 0)
+ {
+ // this dec caused the count to go from non-zero to zero, so we
+ // Release the stdid since this IPID is no longer holding it alive.
+ _pStdId->Release();
+ }
+ }
+ else
+ {
+ // Adjust the strong reference count. Don't let the caller release
+ // too many times.
+
+ if (pEntry->cStrongRefs < cRefs)
+ {
+ ComDebOut((DEB_WARN,"DecSrvIPIDCnt too many releases. IPID entry: 0x%x Extra releases: 0x%x",
+ pEntry, cRefs-pEntry->cStrongRefs));
+ cRefs = pEntry->cStrongRefs;
+ }
+ pEntry->cStrongRefs -= cRefs;
+
+ if (pEntry->cStrongRefs == 0 && cRefs != 0)
+ {
+ // this dec caused the count to go from non-zero to zero, so we
+ // dec the strong count on the stdid since the public references
+ // on this IPID is no longer hold it alive.
+
+ DecStrongAndNotifyAct(pEntry, mshlflags);
+ }
+
+ // Adjust the secure reference count. Don't let the caller release
+ // too many times.
+
+ if (pName != NULL)
+ {
+ cPrivateRefs = gSRFTbl.DecRef(cPrivateRefs, pEntry->ipid, pName);
+ }
+ else
+ {
+ cPrivateRefs = 0;
+ }
+
+ Win4Assert( pEntry->cPrivateRefs >= cPrivateRefs );
+ pEntry->cPrivateRefs -= cPrivateRefs;
+
+ if (pEntry->cPrivateRefs == 0 && cPrivateRefs != 0)
+ {
+ // this dec caused the count to go from non-zero to zero, so we
+ // dec the strong count on the stdid since the private references
+ // on this IPID is no longer hold it alive.
+
+ DecStrongAndNotifyAct(pEntry, mshlflags);
+ }
+ }
+
+ ASSERT_LOCK_HELD
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: DecTableCnt, public
+//
+// Synopsis: decrements the count of table marshals
+//
+// History: 9-Oct-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+void CStdMarshal::DecTableCnt(void)
+{
+ ASSERT_LOCK_HELD
+
+ // If something was marshaled for a table, we have to ignore
+ // rundowns until a subsequent RMD is called for it, at which
+ // time we start paying attention to rundowns again. Since there
+ // can be any number of table marshals, we have to refcnt them.
+ // This is also used by CoLockObjectExternal.
+
+ if (--_cTableRefs == 0)
+ {
+ // this was the last table marshal, so now we have to pay
+ // attention to rundown from normal clients, so that if all
+ // clients go away we cleanup.
+
+ _dwFlags &= ~SMFLAGS_IGNORERUNDOWN;
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: DecStrongAndNotifyAct, private
+//
+// Synopsis: notifies the activation code if this interface has
+// been released and the activation code asked to be
+// notified, and also decrements the strong refcnt.
+//
+// History: 21-Apr-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+void CStdMarshal::DecStrongAndNotifyAct(IPIDEntry *pEntry, DWORD mshlflags)
+{
+ ASSERT_LOCK_HELD
+ BOOL fNotifyAct = FALSE;
+
+ if ((pEntry->dwFlags & IPIDF_NOTIFYACT) &&
+ pEntry->cStrongRefs == 0 &&
+ pEntry->cPrivateRefs == 0)
+ {
+ // the activation code asked to be notified when the refcnt
+ // on this interface reaches zero. Turn the flag off so we
+ // don't call twice.
+ pEntry->dwFlags &= ~IPIDF_NOTIFYACT;
+ fNotifyAct = TRUE;
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ if (fNotifyAct)
+ {
+ NotifyActivation(FALSE, (IUnknown *)(pEntry->pv));
+ }
+
+ _pStdId->DecStrongCnt(mshlflags & MSHLFLAGS_KEEPALIVE);
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: AddIPIDEntry, private
+//
+// Synopsis: Allocates and fills in an entry in the IPID table.
+// The returned entry is not yet in the IPID chain.
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::AddIPIDEntry(OXIDEntry *pOXIDEntry, IPID *pipid,
+ REFIID riid, CRpcChannelBuffer *pChnl, IUnknown *pUnkStub,
+ void *pv, IPIDEntry **ppEntry)
+{
+ ComDebOut((DEB_MARSHAL,"AddIPIDEntry this:%x pOXID:%x iid:%I pStub:%x pv:%x\n",
+ this, pOXIDEntry, &riid, pUnkStub, pv));
+ ASSERT_LOCK_HELD
+
+ // CODEWORK: while we released the lock to create the proxy or stub,
+ // the same interface could have been marshaled/unmarshaled. We should
+ // go check for duplicates now. This is just an optimization, not a
+ // requirement.
+
+ // get a new entry in the IPID table.
+ IPIDEntry *pEntryNew = gIPIDTbl.FirstFree();
+
+ if (pEntryNew == NULL)
+ {
+ // no free slots and could not allocate more memory to grow
+ return E_OUTOFMEMORY;
+ }
+
+ if (ServerSide())
+ {
+ // create an IPID for this entry
+ DWORD *pdw = &pipid->Data1;
+ *pdw = gIPIDTbl.GetEntryIndex(pEntryNew); // IPID table index
+ *(pdw+1) = GetCurrentProcessId(); // current PID
+ *(pdw+2) = GetCurrentThreadId(); // current TID
+ *(pdw+3) = gIPIDSeqNum++; // process sequence #
+ }
+
+ *ppEntry = pEntryNew;
+
+ pEntryNew->ipid = *pipid;
+ pEntryNew->iid = riid;
+ pEntryNew->pChnl = pChnl;
+ pEntryNew->pStub = pUnkStub;
+ pEntryNew->pv = pv;
+ pEntryNew->dwFlags = ServerSide() ? IPIDF_SERVERENTRY :
+ IPIDF_DISCONNECTED | IPIDF_NOPING;
+ pEntryNew->cStrongRefs = 0;
+ pEntryNew->cWeakRefs = 0;
+ pEntryNew->cPrivateRefs = 0;
+ pEntryNew->pOXIDEntry = pOXIDEntry;
+
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_MARSHAL,"AddIPIDEntry this:%x pIPIDEntry:%x ipid:%I\n",
+ this, pEntryNew, &pEntryNew->ipid));
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: ReleaseCliIPIDs, private
+//
+// Synopsis: walks the IPID table releasing the proxy/stub entries
+// on the IPIDEntries associated with this Object.
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+void CStdMarshal::ReleaseCliIPIDs(void)
+{
+ Win4Assert(ClientSide());
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // first thing we do is detach the chain of IPIDs from the CStdMarshal
+ // while holding the LOCK. Then release the lock and walk the chain
+ // releasing the proxy/stub pointers. Note there should not be any other
+ // pointers to any of these IPIDs, so it is OK to muck with their state.
+
+ IPIDEntry *pFirstIPID = _pFirstIPID;
+ _pFirstIPID = NULL;
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED;
+
+ IPIDEntry *pLastIPID;
+ IPIDEntry *pEntry = pFirstIPID;
+
+ while (pEntry)
+ {
+ // mark the entry as vacant and disconnected. Note we dont put
+ // it back in the FreeList yet. We leave it chained to the other
+ // IPIDs in the list, and add the whole chain to the FreeList at
+ // the end.
+
+ pEntry->dwFlags |= IPIDF_VACANT | IPIDF_DISCONNECTED;
+
+ if (pEntry->pStub)
+ {
+ ComDebOut((DEB_MARSHAL,"ReleaseProxy pProxy:%x\n", pEntry->pStub));
+ pEntry->pStub->Release();
+ pEntry->pStub = NULL;
+ }
+
+ pLastIPID = pEntry;
+ pEntry = pEntry->pNextOID;
+ }
+
+
+ if (pFirstIPID != NULL)
+ {
+ // now take the LOCK again and release all the IPIDEntries back into
+ // the IPIDTable in one fell swoop.
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ gIPIDTbl.ReleaseEntryList(pFirstIPID, pLastIPID);
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ }
+
+ ASSERT_LOCK_RELEASED
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CStdMarshal::LockClient/UnLockClient
+//
+// Synopsis: Locks the client side object during outgoing calls in order
+// to prevent the object going away in a nested disconnect.
+//
+// Notes: UnLockClient is not safe in the freethreaded model.
+// Fortunately pending disconnect can only be set in the
+// apartment model on the client side.
+//
+// History: 12-Jun-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+ULONG CStdMarshal::LockClient(void)
+{
+ Win4Assert(ClientSide());
+ InterlockedIncrement(&_cNestedCalls);
+ return (_pStdId->GetCtrlUnk())->AddRef();
+}
+
+ULONG CStdMarshal::UnLockClient(void)
+{
+ Win4Assert(ClientSide());
+ if ((InterlockedDecrement(&_cNestedCalls) == 0) &&
+ (_dwFlags & SMFLAGS_PENDINGDISCONNECT))
+ {
+ Disconnect();
+ }
+ return (_pStdId->GetCtrlUnk())->Release();
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::GetSecureRemUnk, public
+//
+// Synopsis: If the marshaller has its own remote unknown, use it.
+// Otherwise use the OXID's remote unknown.
+//
+// History: 2-Apr-96 AlexMit Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::GetSecureRemUnk( IRemUnknown **ppSecureRemUnk,
+ OXIDEntry *pOXIDEntry )
+{
+ ComDebOut((DEB_OXID, "CStdMarshal::GetSecureRemUnk ppRemUnk:%x\n",
+ ppSecureRemUnk));
+
+ ASSERT_LOCK_DONTCARE
+
+ if (_pSecureRemUnk != NULL)
+ {
+ *ppSecureRemUnk = _pSecureRemUnk;
+ return S_OK;
+ }
+ else
+ {
+ return gOXIDTbl.GetRemUnk( pOXIDEntry, ppSecureRemUnk );
+ }
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::LookupStub, private
+//
+// Synopsis: used by the channel to acquire the stub ptr for debugging
+//
+// History: 12-Jun-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::LookupStub(REFIID riid, IRpcStubBuffer **ppStub)
+{
+ AssertValid();
+ Win4Assert(ServerSide());
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ IPIDEntry *pEntry;
+ HRESULT hr = FindIPIDEntry(riid, &pEntry);
+
+ if (SUCCEEDED(hr))
+ {
+ *ppStub = (IRpcStubBuffer *)pEntry->pStub;
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ return hr;
+}
+
+
+#if DBG==1
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::GetOXID, private, debug
+//
+// Synopsis: returns the OXID for this object
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+REFMOXID CStdMarshal::GetMOXID(void)
+{
+ ASSERT_LOCK_HELD
+
+ if (ServerSide())
+ {
+ // local to this apartment, use the local OXID
+ return GetLocalOXIDEntry()->moxid;
+ }
+ else
+ {
+ Win4Assert(_pChnl);
+ return _pChnl->GetMOXID();
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::DbgWalkIPIDs
+//
+// Synopsis: Validates that the state of all the IPIDs is consistent.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CStdMarshal::DbgWalkIPIDs(void)
+{
+ IPIDEntry *pEntry = _pFirstIPID;
+ while (pEntry)
+ {
+ ValidateIPIDEntry(pEntry);
+ pEntry = pEntry->pNextOID;
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::AssertValid
+//
+// Synopsis: Validates that the state of the object is consistent.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CStdMarshal::AssertValid()
+{
+ LOCK
+ Win4Assert((_dwFlags & ~(SMFLAGS_CLIENT_SIDE | SMFLAGS_REGISTEREDOID |
+ SMFLAGS_PENDINGDISCONNECT | SMFLAGS_DISCONNECTED |
+ SMFLAGS_FIRSTMARSHAL | SMFLAGS_HANDLER | SMFLAGS_WEAKCLIENT |
+ SMFLAGS_IGNORERUNDOWN | SMFLAGS_CLIENTMARSHALED |
+ SMFLAGS_NOPING | SMFLAGS_TRIEDTOCONNECT)) == 0);
+
+ Win4Assert(_pStdId != NULL);
+ Win4Assert(IsValidInterface(_pStdId));
+
+ if (_pChnl != NULL)
+ {
+ Win4Assert(IsValidInterface(_pChnl));
+ _pChnl->AssertValid(FALSE, FALSE);
+ }
+
+ DbgWalkIPIDs();
+ UNLOCK
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::AssertDisconnectPrevented, private
+//
+// Synopsis: Just ensures that no disconnects can/have arrived.
+//
+// History: 21-Sep-95 Rickhi Created
+//
+//+-------------------------------------------------------------------
+void CStdMarshal::AssertDisconnectPrevented()
+{
+ ASSERT_LOCK_HELD
+ if (ServerSide())
+ Win4Assert(!(_dwFlags & SMFLAGS_DISCONNECTED));
+ Win4Assert(_cNestedCalls > 0);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::ValidateSTD
+//
+// Synopsis: Ensures that the STDOBJREF is valid
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CStdMarshal::ValidateSTD(STDOBJREF *pStd)
+{
+ LOCK
+
+ // validate the flags field
+ Win4Assert((pStd->flags & SORF_RSRVD_MBZ) == 0);
+
+ // validate the OID
+ OID oid;
+ OIDFromMOID(_pStdId->GetOID(), &oid);
+ Win4Assert(pStd->oid == oid);
+
+ if (ServerSide() || _pChnl != NULL)
+ {
+ // validate the OXID
+ OXID oxid;
+ OXIDFromMOXID(GetMOXID(), &oxid);
+ Win4Assert(pStd->oxid == oxid );
+ }
+
+ UNLOCK
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: DbgDumpSTD
+//
+// Synopsis: dumps a formated STDOBJREF to the debugger
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void DbgDumpSTD(STDOBJREF *pStd)
+{
+ ULARGE_INTEGER *puintOxid = (ULARGE_INTEGER *)&pStd->oxid;
+ ULARGE_INTEGER *puintOid = (ULARGE_INTEGER *)&pStd->oid;
+
+ ComDebOut((DEB_MARSHAL,
+ "\n\tpStd:%x flags:%08x cPublicRefs:%08x\n\toxid: %08x %08x\n\t oid: %08x %08x\n\tipid:%I\n",
+ pStd, pStd->flags, pStd->cPublicRefs, puintOxid->HighPart, puintOxid->LowPart,
+ puintOid->HighPart, puintOid->LowPart, &pStd->ipid));
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::ValidateIPIDEntry
+//
+// Synopsis: Ensures that the IPIDEntry is valid
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CStdMarshal::ValidateIPIDEntry(IPIDEntry *pEntry)
+{
+ // ask the table to validate the IPID entry
+ gIPIDTbl.ValidateIPIDEntry(pEntry, ServerSide(), _pChnl);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdMarshal::DbgDumpInterfaceList
+//
+// Synopsis: Prints the list of Interfaces on the object.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CStdMarshal::DbgDumpInterfaceList(void)
+{
+ ComDebOut((DEB_ERROR, "\tInterfaces left on object are:\n"));
+ LOCK
+
+ // walk the IPID list printing the friendly name of each interface
+ IPIDEntry *pEntry = _pFirstIPID;
+ while (pEntry)
+ {
+ WCHAR wszName[MAX_PATH];
+ GetInterfaceName(pEntry->iid, wszName);
+ ComDebOut((DEB_ERROR,"\t\t %ws\t cRefs:%x\n",wszName,pEntry->cStrongRefs));
+ pEntry = pEntry->pNextOID;
+ }
+
+ UNLOCK
+}
+#endif // DBG == 1
+
+//+-------------------------------------------------------------------
+//
+// Function: RemoteQueryInterface, private
+//
+// Synopsis: call RemoteQueryInterface on remote server.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL RemoteQueryInterface(IRemUnknown *pRemUnk, IPIDEntry *pIPIDEntry,
+ USHORT cIIDs, IID *pIIDs,
+ REMQIRESULT **ppQiRes, BOOL fWeakClient)
+{
+ ComDebOut((DEB_MARSHAL,
+ "RemoteQueryInterface pIPIDEntry:%x cIIDs:%x, pIIDs:%x riid:%I\n",
+ pIPIDEntry, cIIDs, pIIDs, pIIDs));
+ Win4Assert(pIPIDEntry->pOXIDEntry); // must have a resolved oxid
+ ASSERT_LOCK_HELD
+
+ // set the IPID according to whether we want strong or weak
+ // references. It will only be weak if we are an OLE container
+ // and are talking to an embedding running on the same machine.
+
+ IPID ipid = pIPIDEntry->ipid;
+ if (fWeakClient)
+ {
+ ipid.Data1 |= IPIDFLAG_WEAKREF;
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ HRESULT hr = pRemUnk->RemQueryInterface(ipid, REM_ADDREF_CNT,
+ cIIDs, pIIDs, ppQiRes);
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_MARSHAL, "RemoteQueryInterface hr:%x pQIRes:%x\n",
+ hr, *ppQiRes));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: RemoteAddRef, private
+//
+// Synopsis: calls the remote server to AddRef one of its interfaces
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL RemoteAddRef(IPIDEntry *pIPIDEntry, OXIDEntry *pOXIDEntry,
+ ULONG cStrongRefs, ULONG cSecureRefs)
+{
+ ComDebOut((DEB_MARSHAL,
+ "RemoteAddRef cRefs:%x cSecure:%x ipid:%I\n",
+ cStrongRefs, cSecureRefs, &pIPIDEntry->ipid));
+ ASSERT_LOCK_HELD
+
+ // if the object does not require pinging, it is also ignoring
+ // reference counts, so there is no need to go get more, just
+ // pretend like we did.
+
+ if (pIPIDEntry->dwFlags & IPIDF_NOPING)
+ {
+ return S_OK;
+ }
+
+ // get the IRemUnknown for the remote server
+ IRemUnknown *pRemUnk;
+ HRESULT hr = gOXIDTbl.GetRemUnk(pOXIDEntry, &pRemUnk);
+
+ if (SUCCEEDED(hr))
+ {
+ // call RemAddRef on the interface
+ REMINTERFACEREF rifRef;
+ rifRef.ipid = pIPIDEntry->ipid;
+ rifRef.cPublicRefs = cStrongRefs;
+ rifRef.cPrivateRefs = cSecureRefs;
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ HRESULT ignore;
+ hr = pRemUnk->RemAddRef(1, &rifRef, &ignore);
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_MARSHAL, "RemoteAddRef hr:%x\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: RemoteReleaseRifRef
+//
+// Synopsis: calls the remote server to release some IPIDs
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL RemoteReleaseRifRef(OXIDEntry *pOXIDEntry,
+ USHORT cRifRef, REMINTERFACEREF *pRifRef)
+{
+ Win4Assert(pRifRef);
+ ComDebOut((DEB_MARSHAL,
+ "RemoteRelease pOXID:%x cRifRef:%x pRifRef:%x cRefs:%x ipid:%I\n",
+ pOXIDEntry, cRifRef, pRifRef, pRifRef->cPublicRefs, &pRifRef->ipid));
+ Win4Assert(pOXIDEntry);
+ ASSERT_LOCK_HELD
+
+ HRESULT hr;
+
+ if (IsSTAThread() &&
+ FAILED(CanMakeOutCall(CALLCAT_SYNCHRONOUS, IID_IRundown)))
+ {
+ // the call control will not let this apartment model thread make
+ // the outgoing release call (cause we're inside an InputSync call)
+ // so we post ourselves a message to do it later.
+
+ hr = PostReleaseRifRef(pOXIDEntry, cRifRef, pRifRef);
+ }
+ else
+ {
+ // get the IRemUnknown for the remote server
+ IRemUnknown *pRemUnk;
+ hr = gOXIDTbl.GetRemUnk(pOXIDEntry, &pRemUnk);
+
+ if (SUCCEEDED(hr))
+ {
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ hr = pRemUnk->RemRelease(cRifRef, pRifRef);
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+ }
+
+ ComDebOut((DEB_MARSHAL, "RemoteRelease hr:%x\n", hr));
+ ASSERT_LOCK_HELD
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: PostReleaseRifRef
+//
+// Synopsis: Post a message to ourself to call RemoteReleaseRifRef later.
+// This is used to make a synchronous remote Release call when
+// a Release is done inside of an InputSync call. The call is
+// delayed until we are out of the InputSync call, since the
+// call control wont allow a synch call inside an inputsync call.
+//
+// History: 05-Apr-96 Rickhi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL PostReleaseRifRef(OXIDEntry *pOXIDEntry,
+ USHORT cRifRef, REMINTERFACEREF *pRifRef)
+{
+ Win4Assert(pRifRef);
+ ComDebOut((DEB_MARSHAL,
+ "PostRelease pOXID:%x cRifRef:%x pRifRef:%x cRefs:%x ipid:%I\n",
+ pOXIDEntry, cRifRef, pRifRef, pRifRef->cPublicRefs, &pRifRef->ipid));
+ Win4Assert(pOXIDEntry);
+ ASSERT_LOCK_HELD
+
+ OXIDEntry *pLocalOXIDEntry = NULL;
+ HRESULT hr = gOXIDTbl.GetLocalEntry(&pLocalOXIDEntry);
+
+ if (SUCCEEDED(hr))
+ {
+ // allocate a structure to hold the data and copy in the RifRef
+ // list, OXIDEntry, and count of entries. Inc the OXID RefCnt to
+ // ensure it stays alive until the posted message is processed.
+
+ hr = E_OUTOFMEMORY;
+ ULONG cbRifRef = cRifRef * sizeof(REMINTERFACEREF);
+ ULONG cbAlloc = sizeof(POSTRELRIFREF) + (cbRifRef-1);
+ POSTRELRIFREF *pRelRifRef = (POSTRELRIFREF *) PrivMemAlloc(cbAlloc);
+
+ if (pRelRifRef)
+ {
+ IncOXIDRefCnt(pOXIDEntry); // keep alive
+ pRelRifRef->pOXIDEntry = pOXIDEntry;
+ pRelRifRef->cRifRef = cRifRef;
+ memcpy(&pRelRifRef->arRifRef, pRifRef, cbRifRef);
+
+ if (!PostMessage((HWND)pLocalOXIDEntry->hServerSTA,
+ WM_OLE_ORPC_RELRIFREF,
+ GetCurrentThreadId(),
+ (LPARAM)pRelRifRef))
+ {
+ // Post failed, free the structure and report an error.
+ DecOXIDRefCnt(pOXIDEntry);
+ PrivMemFree(pRelRifRef);
+ hr = RPC_E_SYS_CALL_FAILED;
+ }
+ }
+ }
+
+ ComDebOut((DEB_MARSHAL, "PostRelease hr:%x\n", hr));
+ ASSERT_LOCK_HELD
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: HandlePostReleaseRifRef
+//
+// Synopsis: Handles the ReleaseRifRef message that was posted to the
+// current thread (by the current thread) in order to do a
+// delayed remote release call. See PostReleaseRifRef above.
+//
+// History: 05-Apr-96 Rickhi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL HandlePostReleaseRifRef(LPARAM param)
+{
+ Win4Assert(param);
+ ComDebOut((DEB_MARSHAL, "HandlePostRelease pRifRef:%x\n", param));
+ POSTRELRIFREF *pRelRifRef = (POSTRELRIFREF *)param;
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // simply make the real remote release call now, then release the
+ // reference we have on the OXIDEntry, and free the message buffer.
+ // If this call fails, dont try again, otherwise we could spin busy
+ // waiting. Instead, just let Rundown clean up the server.
+
+ RemoteReleaseRifRef(pRelRifRef->pOXIDEntry,
+ pRelRifRef->cRifRef,
+ &pRelRifRef->arRifRef);
+
+ DecOXIDRefCnt(pRelRifRef->pOXIDEntry);
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ PrivMemFree(pRelRifRef);
+ ComDebOut((DEB_MARSHAL, "HandlePostRelease hr:%x\n", S_OK));
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: RemoteChangeRef
+//
+// Synopsis: calls the remote server to convert interface refereces
+// from strong to weak or vise versa. This behaviour is
+// required to support silent updates in the OLE container /
+// link / embedding scenarios.
+//
+// Notes: This functionality is not exposed in FreeThreaded apps
+// or in remote apps. The implication being that the container
+// must be on the same machine as the embedding.
+//
+// History: 20-Nov-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CStdMarshal::RemoteChangeRef(BOOL fLock, BOOL fLastUnlockReleases)
+{
+ ComDebOut((DEB_MARSHAL, "RemoteChangeRef \n"));
+ Win4Assert(ClientSide());
+ Win4Assert(IsSTAThread()); // not allowed in MTA Apartment
+ ASSERT_LOCK_RELEASED
+
+ // must be at least 1 proxy already connected in order to be able
+ // to do this. We cant just ASSERT that's true because we were not
+ // holding the lock on entry.
+
+ LOCK
+ HRESULT hr = PreventDisconnect();
+
+ // A previous version of OLE set the object to weak even it it was
+ // currently disconnected, and it remembered that it was weak and set
+ // any new interfaces that it later accquired to weak. I emulate that
+ // behaviour here.
+
+ if (fLock)
+ _dwFlags &= ~SMFLAGS_WEAKCLIENT;
+ else
+ _dwFlags |= SMFLAGS_WEAKCLIENT;
+
+
+ if (SUCCEEDED(hr))
+ {
+ REMINTERFACEREF *pRifRefAlloc = (REMINTERFACEREF *)
+ _alloca(_cIPIDs * sizeof(REMINTERFACEREF));
+ REMINTERFACEREF *pRifRef = pRifRefAlloc;
+
+ DWORD cSecure = gCapabilities & EOAC_SECURE_REFS ? 1 : 0;
+ USHORT cIIDs = 0;
+ OXIDEntry *pOXIDEntry = NULL;
+ IPIDEntry *pNextIPID = _pFirstIPID;
+
+ while (pNextIPID)
+ {
+ if (!(pNextIPID->dwFlags & IPIDF_DISCONNECTED))
+ {
+ if (pOXIDEntry == NULL)
+ {
+ // This is the first connected IPID we encountered.
+ // Get its OXID entry and make sure it is for a server
+ // process on the current machine.
+
+ if (!(pNextIPID->pOXIDEntry->dwFlags &
+ OXIDF_MACHINE_LOCAL))
+ {
+ // OXID is for a remote process. Abandon this call.
+ Win4Assert(cIIDs == 0); // skip call below
+ Win4Assert(pOXIDEntry == NULL); // dont dec below
+ Win4Assert(hr == S_OK); // report success
+ break; // exit while loop
+ }
+
+ // Remember the OXID and AddRef it to keep it alive
+ // over the duration of the call.
+
+ pOXIDEntry = pNextIPID->pOXIDEntry;
+ IncOXIDRefCnt(pOXIDEntry);
+ }
+
+ pRifRef->ipid = pNextIPID->ipid;
+
+ if (!fLock && pNextIPID->cStrongRefs > 0)
+ {
+ pRifRef->cPublicRefs = pNextIPID->cStrongRefs;
+ pRifRef->cPrivateRefs = pNextIPID->cPrivateRefs;
+ pNextIPID->cWeakRefs += pNextIPID->cStrongRefs;
+ pNextIPID->cStrongRefs = 0;
+ pNextIPID->cPrivateRefs = 0;
+
+ pRifRef++;
+ cIIDs++;
+ }
+ else if (fLock && pNextIPID->cStrongRefs == 0)
+ {
+ pRifRef->cPublicRefs = pNextIPID->cWeakRefs;
+ pRifRef->cPrivateRefs = cSecure;
+ pNextIPID->cStrongRefs += pNextIPID->cWeakRefs;
+ pNextIPID->cWeakRefs = 0;
+ pNextIPID->cPrivateRefs = cSecure;
+
+ pRifRef++;
+ cIIDs++;
+ }
+ }
+
+ // get next IPIDentry for this object
+ pNextIPID = pNextIPID->pNextOID;
+ }
+
+ if (cIIDs != 0)
+ {
+ // we have looped filling in the IPID list, and there are
+ // entries in the list. go call the server now. First, set up
+ // the flags, then reset the RifRef pointer since we trashed
+ // it while walking the list above.
+
+ DWORD dwFlags = (fLock) ? IRUF_CONVERTTOSTRONG : IRUF_CONVERTTOWEAK;
+ if (fLastUnlockReleases)
+ dwFlags |= IRUF_DISCONNECTIFLASTSTRONG;
+
+ hr = RemoteChangeRifRef(pOXIDEntry, dwFlags, cIIDs, pRifRefAlloc);
+ }
+
+ if (pOXIDEntry)
+ {
+ // release the OXIDEntry
+ DecOXIDRefCnt(pOXIDEntry);
+ }
+ }
+ else
+ {
+ // A previous implementation of OLE returned S_OK if the object was
+ // disconnected. I emulate that behaviour here.
+
+ hr = S_OK;
+ }
+
+ DbgWalkIPIDs();
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ // this will handle any Disconnect that came in while we were busy.
+ hr = HandlePendingDisconnect(hr);
+
+ ComDebOut((DEB_MARSHAL, "RemoteChangeRef hr:%x\n", hr));
+ ASSERT_LOCK_RELEASED
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: RemoteChangeRifRef
+//
+// Synopsis: calls the remote server to release some IPIDs
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL RemoteChangeRifRef(OXIDEntry *pOXIDEntry, DWORD dwFlags,
+ USHORT cRifRef, REMINTERFACEREF *pRifRef)
+{
+ Win4Assert(pRifRef);
+ ComDebOut((DEB_MARSHAL,
+ "RemoteChangeRifRef pOXID:%x cRifRef:%x pRifRef:%x cRefs:%x ipid:%I\n",
+ pOXIDEntry, cRifRef, pRifRef, pRifRef->cPublicRefs, &(pRifRef->ipid)));
+ Win4Assert(pOXIDEntry);
+ ASSERT_LOCK_HELD
+
+ // get the IRemUnknown for the remote server
+ IRemUnknown *pRemUnk;
+ HRESULT hr = gOXIDTbl.GetRemUnk(pOXIDEntry, &pRemUnk);
+
+ if (SUCCEEDED(hr))
+ {
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ hr = ((IRemUnknown2 *)pRemUnk)->RemChangeRef(dwFlags, cRifRef, pRifRef);
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+
+ ComDebOut((DEB_MARSHAL, "RemoteChangeRifRef hr:%x\n", hr));
+ ASSERT_LOCK_HELD
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: RemoteReleaseStdObjRef
+//
+// Synopsis: calls the remote server to release an ObjRef
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL RemoteReleaseStdObjRef(STDOBJREF *pStd, OXIDEntry *pOXIDEntry)
+{
+ ComDebOut((DEB_MARSHAL, "RemoteReleaseStdObjRef pStd:%x\n pOXIDEntry:%x",
+ pStd, pOXIDEntry));
+ ASSERT_LOCK_HELD
+
+ REMINTERFACEREF rifRef;
+ rifRef.ipid = pStd->ipid;
+ rifRef.cPublicRefs = pStd->cPublicRefs;
+ rifRef.cPrivateRefs = 0;
+
+ // incase we get disconnected while in the RemRelease call
+ // we need to extract the OXIDEntry and AddRef it.
+
+ IncOXIDRefCnt(pOXIDEntry);
+ RemoteReleaseRifRef(pOXIDEntry, 1, &rifRef);
+ DecOXIDRefCnt(pOXIDEntry);
+
+ ComDebOut((DEB_MARSHAL, "RemoteReleaseStdObjRef hr:%x\n", S_OK));
+ ASSERT_LOCK_HELD
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: RemoteReleaseObjRef
+//
+// Synopsis: calls the remote server to release an ObjRef
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL RemoteReleaseObjRef(OBJREF &objref)
+{
+ return RemoteReleaseStdObjRef(&ORSTD(objref).std, GetOXIDFromObjRef(objref));
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: GetOXIDFromObjRef, private
+//
+// Synopsis: extracts the OXID from the OBJREF.
+//
+// History: 09-Jan-96 Rickhi Created.
+//
+//--------------------------------------------------------------------
+OXIDEntry *GetOXIDFromObjRef(OBJREF &objref)
+{
+ // TRICK: Internally we use the saResAddr.size field as the ptr
+ // to the OXIDEntry. See ReadObjRef and FillObjRef.
+
+ OXIDEntry *pOXIDEntry = (objref.flags & OBJREF_STANDARD)
+ ? *(OXIDEntry **)&ORSTD(objref).saResAddr
+ : *(OXIDEntry **)&ORHDL(objref).saResAddr;
+
+ Win4Assert(pOXIDEntry);
+ return pOXIDEntry;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: WriteObjRef, private
+//
+// Synopsis: Writes the objref into the stream
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL WriteObjRef(IStream *pStm, OBJREF &objref, DWORD dwDestCtx)
+{
+ ASSERT_LOCK_RELEASED
+
+ ULONG cbToWrite = (objref.flags & OBJREF_STANDARD)
+ ? (2*sizeof(ULONG)) + sizeof(IID) + sizeof(STDOBJREF)
+ : (2*sizeof(ULONG)) + sizeof(IID) + sizeof(STDOBJREF) + sizeof(CLSID);
+
+ // write the fixed-sized part of the OBJREF into the stream
+ HRESULT hr = pStm->Write(&objref, cbToWrite, NULL);
+
+ if (SUCCEEDED(hr))
+ {
+ // write the resolver address into the stream.
+ // TRICK: Internally we use the saResAddr.size field as the ptr
+ // to the OXIDEntry. See ReadObjRef and FillObjRef.
+
+ DUALSTRINGARRAY *psa;
+ OXIDEntry *pOXIDEntry = GetOXIDFromObjRef(objref);
+
+ if (pOXIDEntry->pMIDEntry != gpLocalMIDEntry ||
+ dwDestCtx == MSHCTX_DIFFERENTMACHINE)
+ {
+ // the interface is for a remote server, or it is going to a
+ // remote client, therefore, marshal the resolver strings
+ psa = pOXIDEntry->pMIDEntry->Node.psaKey;
+ Win4Assert(psa->wNumEntries != 0);
+ }
+ else
+ {
+ // the interface is for an OXID local to this machine and
+ // the interface is not going to a remote client, marshal an
+ // empty string (we pay attention to this in ReadObjRef)
+ psa = &saNULL;
+ }
+
+ // These string bindings always come from the object exporter
+ // who has already padded the size to 8 bytes.
+ hr = pStm->Write(psa, SASIZE(psa->wNumEntries), NULL);
+
+ ComDebOut((DEB_MARSHAL,"WriteObjRef psa:%x\n", psa));
+ }
+
+ ASSERT_LOCK_RELEASED
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: ReadObjRef, private
+//
+// Synopsis: Reads the objref from the stream
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL ReadObjRef(IStream *pStm, OBJREF &objref)
+{
+ ASSERT_LOCK_RELEASED
+
+ // read the signature, flags, and iid fields of the objref so we know
+ // what kind of objref we are dealing with and how big it is.
+
+ HRESULT hr = StRead(pStm, &objref, 2*sizeof(ULONG) + sizeof(IID));
+
+ if (SUCCEEDED(hr))
+ {
+ if ((objref.signature != OBJREF_SIGNATURE) ||
+ (objref.flags & OBJREF_RSRVD_MBZ) ||
+ (objref.flags == 0))
+ {
+ // the objref signature is bad, or one of the reserved
+ // bits in the flags is set, or none of the required bits
+ // in the flags is set. the objref cant be interpreted so
+ // fail the call.
+
+ Win4Assert(!"Invalid Objref Flags");
+ return RPC_E_INVALID_OBJREF;
+ }
+
+ // compute the size of the remainder of the objref and
+ // include the size fields for the resolver string array
+
+ STDOBJREF *pStd = &ORSTD(objref).std;
+ DUALSTRINGARRAY *psa;
+ ULONG cbToRead;
+
+ if (objref.flags & OBJREF_STANDARD)
+ {
+ cbToRead = sizeof(STDOBJREF) + sizeof(ULONG);
+ psa = &ORSTD(objref).saResAddr;
+ }
+ else if (objref.flags & OBJREF_HANDLER)
+ {
+ cbToRead = sizeof(STDOBJREF) + sizeof(CLSID) + sizeof(ULONG);
+ psa = &ORHDL(objref).saResAddr;
+ }
+ else if (objref.flags & OBJREF_CUSTOM)
+ {
+ cbToRead = sizeof(CLSID) + 2*sizeof(DWORD); // clsid + cbExtension + size
+ psa = NULL;
+ }
+
+ // read the rest of the (fixed sized) objref from the stream
+ hr = StRead(pStm, pStd, cbToRead);
+
+ if (SUCCEEDED(hr))
+ {
+ if (psa != NULL)
+ {
+ // Non custom interface. Make sure the resolver string array
+ // has some sensible values.
+ if (psa->wNumEntries != 0 &&
+ psa->wSecurityOffset >= psa->wNumEntries)
+ {
+ hr = RPC_E_INVALID_OBJREF;
+ }
+ }
+ else
+ {
+ // custom marshaled interface
+ if (ORCST(objref).cbExtension != 0)
+ {
+ // skip past the extensions since we currently dont
+ // know about any extension types.
+ LARGE_INTEGER dlibMove;
+ dlibMove.LowPart = ORCST(objref).cbExtension;
+ dlibMove.HighPart = 0;
+ hr = pStm->Seek(dlibMove, STREAM_SEEK_CUR, NULL);
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr) && psa)
+ {
+ // Non custom interface. The data that follows is a variable
+ // sized string array. Allocate memory for it and then read it.
+
+ DbgDumpSTD(pStd);
+ DUALSTRINGARRAY *psaNew;
+
+ cbToRead = psa->wNumEntries * sizeof(WCHAR);
+ if (cbToRead == 0)
+ {
+ // server must be local to this machine, just get the local
+ // resolver strings and use them to resolve the OXID
+ psaNew = gpsaLocalResolver;
+ }
+ else
+ {
+ // allocate space to read the strings
+ psaNew = (DUALSTRINGARRAY *) _alloca(cbToRead + sizeof(ULONG));
+ if (psaNew != NULL)
+ {
+ // update the size fields and read in the rest of the data
+ psaNew->wSecurityOffset = psa->wSecurityOffset;
+ psaNew->wNumEntries = psa->wNumEntries;
+
+ hr = StRead(pStm, psaNew->aStringArray, cbToRead);
+ }
+ else
+ {
+ psa->wNumEntries = 0;
+ psa->wSecurityOffset = 0;
+ hr = E_OUTOFMEMORY;
+
+ // seek the stream past what we should have read, ignore
+ // seek errors, since the OOM takes precedence.
+
+ LARGE_INTEGER libMove;
+ libMove.LowPart = cbToRead;
+ libMove.HighPart = 0;
+ pStm->Seek(libMove, STREAM_SEEK_CUR, 0);
+ }
+ }
+
+ // TRICK: internally we want to keep the ObjRef a fixed size
+ // structure, even though we have variable sized data. To do
+ // this i use the saResAddr.size field of the ObjRef as a ptr
+ // to the OXIDEntry. We pay attention to this in FillObjRef,
+ // WriteObjRef and FreeObjRef.
+
+ if (SUCCEEDED(hr))
+ {
+ // resolve the OXID.
+ ASSERT_LOCK_RELEASED
+ LOCK
+ OXIDEntry *pOXIDEntry = NULL;
+ hr = gResolver.ClientResolveOXID(pStd->oxid,
+ psaNew, &pOXIDEntry);
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ *((void **) psa) = pOXIDEntry;
+ }
+ else
+ {
+ *((void **) psa) = NULL;
+ }
+ }
+ }
+
+ ComDebOut((DEB_MARSHAL,"ReadObjRef hr:%x objref:%x\n", hr, &objref));
+ ASSERT_LOCK_RELEASED
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: FreeObjRef, private
+//
+// Synopsis: Releases an objref that was read in from a stream via
+// ReadObjRef.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+// Notes: Anybody who calls ReadObjRef should call this guy to
+// free the objref. This decrements the refcnt on the
+// embedded pointer to the OXIDEntry.
+//
+//--------------------------------------------------------------------
+INTERNAL_(void) FreeObjRef(OBJREF &objref)
+{
+ if (objref.flags & (OBJREF_STANDARD | OBJREF_HANDLER))
+ {
+ // TRICK: Internally we use the saResAddr.size field as the ptr to
+ // the OXIDEntry. See ReadObjRef, WriteObjRef and FillObjRef.
+
+ OXIDEntry *pOXIDEntry = GetOXIDFromObjRef(objref);
+
+ LOCK
+ Win4Assert(pOXIDEntry);
+ DecOXIDRefCnt(pOXIDEntry);
+ UNLOCK
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: MakeFakeObjRef, private
+//
+// Synopsis: Invents an OBJREF that can be unmarshaled in this process.
+// The objref is partially fact (the OXIDEntry) and partially
+// fiction (the OID).
+//
+// History: 16-Jan-96 Rickhi Created.
+//
+// Notes: This is used by MakeSCMProxy and GetRemUnk. Note that
+// the pOXIDEntry is not AddRef'd here because the OBJREF
+// created is only short-lived the callers guarantee it's
+// lifetime, so FreeObjRef need not be called.
+//
+//--------------------------------------------------------------------
+INTERNAL MakeFakeObjRef(OBJREF &objref, OXIDEntry *pOXIDEntry,
+ REFIPID ripid, REFIID riid)
+{
+ // first, invent an OID since this could fail.
+
+ STDOBJREF *pStd = &ORSTD(objref).std;
+ HRESULT hr = gResolver.ServerGetReservedID(&pStd->oid);
+
+ if (SUCCEEDED(hr))
+ {
+ pStd->flags = SORF_NOPING | SORF_FREETHREADED;
+ pStd->cPublicRefs = 1;
+ pStd->ipid = ripid;
+ OXIDFromMOXID(pOXIDEntry->moxid, &pStd->oxid);
+
+ // TRICK: Internally we use the saResAddr.size field as the ptr to
+ // the OXIDEntry. See ReadObjRef, WriteObjRef and FillObjRef.
+
+ OXIDEntry **ppOXIDEntry = (OXIDEntry **) &ORSTD(objref).saResAddr;
+ *ppOXIDEntry = pOXIDEntry;
+
+ objref.signature = OBJREF_SIGNATURE;
+ objref.flags = OBJREF_STANDARD;
+ objref.iid = riid;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: MakeCallableFromAnyApt, private
+//
+// Synopsis: set SORF_FREETHREADED in OBJREF so unmarshaled proxy
+// can be called from any apartment.
+//
+// History: 16-Jan-96 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void MakeCallableFromAnyApt(OBJREF &objref)
+{
+ STDOBJREF *pStd = &ORSTD(objref).std;
+ pStd->flags |= SORF_FREETHREADED;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: FindStdMarshal, private
+//
+// Synopsis: Finds the CStdMarshal for the OID read from the stream
+//
+// Arguements: [objref] - object reference
+// [ppStdMshl] - CStdMarshal returned, AddRef'd
+//
+// Algorithm: Read the objref, get the OID. If we already have an identity
+// for this OID, use that, otherwise either create an identity
+// object, or create a handler (which in turn will create the
+// identity). The identity inherits CStdMarshal.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+INTERNAL FindStdMarshal(OBJREF &objref, CStdMarshal **ppStdMshl)
+{
+ ComDebOut((DEB_MARSHAL,
+ "FindStdMarshal objref:%x ppStdMshl:%x\n", &objref, ppStdMshl));
+
+ HRESULT hr = CO_E_OBJNOTCONNECTED;
+ CStdIdentity *pStdId = NULL;
+
+ if (ChkIfLocalOID(objref, &pStdId))
+ {
+ if (pStdId)
+ {
+ hr = S_OK;
+ }
+ else
+ {
+ hr = CO_E_OBJNOTCONNECTED;
+ }
+ }
+ else
+ {
+ STDOBJREF *pStd = &ORSTD(objref).std;
+ ComDebOut((DEB_MARSHAL, "poid: %x\n", &pStd->oid));
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ OXIDEntry *pOXIDEntry = GetOXIDFromObjRef(objref);
+
+ // OXID is for different apartment, check the identity table for
+ // an existing OID.
+
+ MOID moid;
+ MOIDFromOIDAndMID(pStd->oid, pOXIDEntry->pMIDEntry->mid, &moid);
+
+ hr = LookupIDFromID(moid, TRUE, &pStdId);
+
+ if (FAILED(hr))
+ {
+ CStdIdentity *pStdIdPrev = NULL;
+ BOOL fDuplicate = FALSE;
+
+ if (objref.flags & OBJREF_STANDARD)
+ {
+ // create an instance of the identity for this OID. We want
+ // to be holding the lock while we do this since it wont
+ // exercise any app code.
+
+ hr = CreateIdentityHandler(NULL, pStd->flags,
+ IID_IStdIdentity, (void **)&pStdId);
+ AssertOutPtrIface(hr, pStdId);
+
+ if (SUCCEEDED(hr))
+ {
+ // set the identity while holding the lock. The result is
+ // checked below and we release if this fails.
+
+ hr = pStdId->SetOID(moid);
+ Win4Assert(pStdIdPrev == NULL);
+ }
+ }
+ else
+ {
+ // create an instance of the handler. the handler will
+ // aggregate in the identity, but will pass GUID_NULL for
+ // the OID so that the identity is not set in the table yet.
+
+ Win4Assert(!(ORHDL(objref).std.flags & SORF_FREETHREADED));
+
+ // dont want to hold the lock while creating the handler
+ // since this involves running app code and calling the
+ // SCM etc.
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ hr = CoCreateInstance(ORHDL(objref).clsid, NULL,
+ CLSCTX_INPROC_HANDLER,
+ IID_IStdIdentity, (void **)&pStdId);
+
+ AssertOutPtrIface(hr, pStdId);
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // look for the OID in the table again, since it may have
+ // been added while we released the lock to create the
+ // handler.
+
+ if (SUCCEEDED(LookupIDFromID(moid, TRUE, &pStdIdPrev)))
+ {
+ // object was unmarshaled while we released the lock
+ // to create the handler, so we will use the existing one.
+ // since we are releasing app code, we need to release the
+ // lock.
+
+ fDuplicate = TRUE;
+ }
+ else if (SUCCEEDED(hr))
+ {
+ // set the OID now while we are holding the lock.
+ hr = pStdId->SetOID(moid);
+ Win4Assert(pStdIdPrev == NULL);
+ }
+ }
+
+ if (pStdId && (FAILED(hr) || fDuplicate))
+ {
+ Win4Assert( (FAILED(hr) && (pStdIdPrev == NULL)) ||
+ (fDuplicate && (pStdIdPrev != NULL)) );
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ pStdId->Release();
+ pStdId = pStdIdPrev;
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ }
+
+ *ppStdMshl = (CStdMarshal *)pStdId;
+ AssertOutPtrIface(hr, *ppStdMshl);
+
+ ComDebOut((DEB_MARSHAL,
+ "FindStdMarshal pStdMshl:%x hr:%x\n", *ppStdMshl, hr));
+ return hr;
+}
+
+//+------------------------------------------------------------------------
+//
+// Function: CompleteObjRef, public
+//
+// Synopsis: Fills in the missing fields of an OBJREF from a STDOBJREF
+// and resolves the OXID. Also sets fLocal to TRUE if the
+// object was marshaled in this apartment.
+//
+// History: 22-Jan-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+HRESULT CompleteObjRef(OBJREF &objref, OXID_INFO &oxidInfo, REFIID riid, BOOL *pfLocal)
+{
+ // tweak the objref so we can call ReleaseMarshalObjRef or UnmarshalObjRef
+ objref.signature = OBJREF_SIGNATURE;
+ objref.flags = OBJREF_STANDARD;
+ objref.iid = riid;
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (FAILED(hr))
+ return hr;
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ OXIDEntry *pOXIDEntry = NULL;
+ MIDEntry *pMIDEntry;
+ hr = GetLocalMIDEntry(&pMIDEntry);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = FindOrCreateOXIDEntry(ORSTD(objref).std.oxid,
+ oxidInfo,
+ FOCOXID_NOREF,
+ gpsaLocalResolver,
+ gLocalMid,
+ pMIDEntry,
+ &pOXIDEntry);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ OXIDEntry **ppOXIDEntry = (OXIDEntry **) &ORSTD(objref).saResAddr;
+ *ppOXIDEntry = pOXIDEntry;
+
+ *pfLocal = (pOXIDEntry == GetLocalOXIDEntry());
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ return hr;
+}
+
diff --git a/private/ole32/com/dcomrem/marshal.hxx b/private/ole32/com/dcomrem/marshal.hxx
new file mode 100644
index 000000000..54d57d202
--- /dev/null
+++ b/private/ole32/com/dcomrem/marshal.hxx
@@ -0,0 +1,388 @@
+//+-------------------------------------------------------------------
+//
+// File: marshal.hxx
+//
+// Contents: class for standard interface marshaling
+//
+// Classes: CStdMarshal
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+#ifndef _MARSHAL_HXX_
+#define _MARSHAL_HXX_
+
+#include <ipidtbl.hxx> // CIPIDTable
+#include <remunk.h> // IRemUnknown, REMINTERFACEREF
+#include <locks.hxx>
+
+// convenient mappings
+#define ORCST(objref) objref.u_objref.u_custom
+#define ORSTD(objref) objref.u_objref.u_standard
+#define ORHDL(objref) objref.u_objref.u_handler
+
+
+// bits that must be zero in the flags fields
+#define OBJREF_RSRVD_MBZ ~(OBJREF_STANDARD | OBJREF_HANDLER | OBJREF_CUSTOM)
+
+#define SORF_RSRVD_MBZ ~(SORF_NOPING | SORF_OXRES1 | SORF_OXRES2 | \
+ SORF_OXRES3 | SORF_OXRES4 | SORF_OXRES5 | \
+ SORF_OXRES6 | SORF_OXRES7 | SORF_OXRES8)
+
+
+// Internal Uses of the reserved SORF_OXRES flags.
+
+// SORF_TBLWEAK is needed so that RMD works correctly on TABLEWEAK
+// marshaling, so it is ignored by unmarshalers. Therefore, we use one of
+// the bits reserved for the object exporter that must be ignored by
+// unmarshalers.
+//
+// SORF_WEAKREF is needed for container weak references, when handling
+// an IRemUnknown::RemQueryInterface on a weak interface. This is a strictly
+// local (windows) machine protocol, so we use a reserved bit.
+//
+// SORF_NONNDR is needed for interop of 16bit custom (non-NDR) marshalers
+// with 32bit, since the 32bit guys want to use MIDL (NDR) to talk to other
+// 32bit processes and remote processes, but the custom (non-NDR) format to
+// talk to local 16bit guys. In particular, this is to support OLE Automation.
+//
+// SORF_FREETHREADED is needed when we create a proxy to the SCM interface
+// in the apartment model. All apartments can use the same proxy so we avoid
+// the test for calling on the correct thread.
+
+#define SORF_TBLWEAK SORF_OXRES1 // (table) weak reference
+#define SORF_WEAKREF SORF_OXRES2 // (normal) weak reference
+#define SORF_NONNDR SORF_OXRES3 // stub does not use NDR marshaling
+#define SORF_FREETHREADED SORF_OXRES4 // proxy may be used on any thread
+
+
+// new MARSHAL FLAG constants.
+const DWORD MSHLFLAGS_WEAK = 8;
+const DWORD MSHLFLAGS_KEEPALIVE = 32;
+
+// definitions to simplify coding
+const DWORD MSHLFLAGS_TABLE = MSHLFLAGS_TABLESTRONG | MSHLFLAGS_TABLEWEAK;
+
+const DWORD MSHLFLAGS_USER_MASK = MSHLFLAGS_NORMAL |
+ MSHLFLAGS_TABLEWEAK |
+ MSHLFLAGS_TABLESTRONG |
+ MSHLFLAGS_NOPING;
+
+const DWORD MSHLFLAGS_ALL = MSHLFLAGS_NORMAL | // 0x00
+ MSHLFLAGS_TABLEWEAK | // 0x01
+ MSHLFLAGS_TABLESTRONG | // 0x02
+ MSHLFLAGS_NOPING | // 0x04
+ MSHLFLAGS_WEAK | // 0x08
+ MSHLFLAGS_KEEPALIVE | // 0x20
+ MSHLFLAGS_NOTIFYACTIVATION; // 0x8000000
+
+// forward class declarations
+class CStdIdentity;
+class CStdMarshal;
+class CRpcChannelBuffer;
+
+extern IMarshal *gpStdMarshal;
+
+
+// internal subroutines used by CStdMarshal and CoUnmarshalInterface
+INTERNAL ReadObjRef (IStream *pStm, OBJREF &objref);
+INTERNAL WriteObjRef(IStream *pStm, OBJREF &objref, DWORD dwDestCtx);
+INTERNAL MakeFakeObjRef(OBJREF &objref, OXIDEntry *pOXIDEntry, REFIPID ipid, REFIID riid);
+INTERNAL_(void) FreeObjRef(OBJREF &objref);
+INTERNAL_(OXIDEntry *)GetOXIDFromObjRef(OBJREF &objref);
+
+INTERNAL RemoteQueryInterface(IRemUnknown *pRemUnk, IPIDEntry *pIPIDEntry,
+ USHORT cIIDs, IID *pIIDs,
+ REMQIRESULT **ppQiRes, BOOL fWeakClient);
+INTERNAL RemoteAddRef(IPIDEntry *pIPIDEntry, OXIDEntry *pOXIDEntry, ULONG cStrongRefs, ULONG cSecureRefs);
+INTERNAL RemoteReleaseObjRef(OBJREF &objref);
+INTERNAL RemoteReleaseStdObjRef(STDOBJREF *pStd, OXIDEntry *pOXIDEntry);
+INTERNAL RemoteReleaseRifRef(OXIDEntry *pOXIDEntry, USHORT cRifRef,
+ REMINTERFACEREF *pRifRef);
+INTERNAL PostReleaseRifRef(OXIDEntry *pOXIDEntry, USHORT cRifRef,
+ REMINTERFACEREF *pRifRef);
+INTERNAL HandlePostReleaseRifRef(LPARAM param);
+INTERNAL RemoteChangeRifRef(OXIDEntry *pOXIDEntry, DWORD dwFlags,
+ USHORT cRifRef, REMINTERFACEREF *pRifRef);
+INTERNAL FindStdMarshal(OBJREF &objref, CStdMarshal **ppStdMshl);
+
+#if DBG==1
+void DbgDumpSTD(STDOBJREF *pStd);
+#else
+inline void DbgDumpSTD(STDOBJREF *pStd) {};
+#endif
+
+
+// Definition of values for dwFlags field of CStdMarshal
+typedef enum tagSMFLAGS
+{
+ SMFLAGS_CLIENT_SIDE = 0x01, // object is local to this process
+ SMFLAGS_PENDINGDISCONNECT = 0x02, // disconnect is pending
+ SMFLAGS_REGISTEREDOID = 0x04, // OID is registered with resolver
+ SMFLAGS_DISCONNECTED = 0x08, // really disconnected
+ SMFLAGS_FIRSTMARSHAL = 0x10, // first time marshalled
+ SMFLAGS_HANDLER = 0x20, // object has a handler
+ SMFLAGS_WEAKCLIENT = 0x40, // client has weak ref to server
+ SMFLAGS_IGNORERUNDOWN = 0x80, // dont rundown this object
+ SMFLAGS_CLIENTMARSHALED = 0x100,// client-side has re-marshaled object
+ SMFLAGS_NOPING = 0x200,// this object is not pinged
+ SMFLAGS_TRIEDTOCONNECT = 0x400 // attempted ConnectIPIDEntry
+} SMFLAGS;
+
+
+//+----------------------------------------------------------------
+//
+// structure: SQIResult
+//
+// synopsis: structure used for QueryRemoteInterfaces
+//
+//+----------------------------------------------------------------
+typedef struct tagSQIResult
+{
+ void *pv; // interface pointer
+ HRESULT hr; // result of the QI call
+} SQIResult;
+
+
+//+----------------------------------------------------------------
+//
+// Class: CStdMarshal, private
+//
+// Purpose: Provides standard marshaling of interface pointers.
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//-----------------------------------------------------------------
+class CStdMarshal : public IMarshal
+{
+public:
+ CStdMarshal();
+ ~CStdMarshal();
+ void Init(IUnknown *pUnk, CStdIdentity *pstdID,
+ REFCLSID rclsidHandler, DWORD dwFlags);
+
+
+ // IMarshal - IUnknown taken from derived classes
+ STDMETHOD(GetUnmarshalClass)(REFIID riid, LPVOID pv, DWORD dwDestCtx,
+ LPVOID pvDestCtx, DWORD mshlflags, LPCLSID pClsid);
+ STDMETHOD(GetMarshalSizeMax)(REFIID riid, LPVOID pv, DWORD dwDestCtx,
+ LPVOID pvDestCtx, DWORD mshlflags, LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(LPSTREAM pStm, REFIID riid, LPVOID pv,
+ DWORD dwDestCtx, LPVOID pvDestCtx, DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(LPSTREAM pStm, REFIID riid, LPVOID *ppv);
+ STDMETHOD(ReleaseMarshalData)(LPSTREAM pStm);
+ STDMETHOD(DisconnectObject)(DWORD dwReserved);
+
+
+ // used by coapi's for unmarshaling/releasing
+ HRESULT MarshalObjRef(OBJREF &objref, REFIID riid, LPVOID pv, DWORD mshlflags);
+ HRESULT MarshalIPID(REFIID riid, ULONG cRefs, DWORD mshlflags, IPIDEntry **ppEntry);
+ HRESULT UnmarshalObjRef(OBJREF &objref, void **ppv);
+ HRESULT ReleaseMarshalObjRef(OBJREF &objref);
+
+
+ // used by client side StdIdentity to make calls to the remote server
+ HRESULT QueryRemoteInterfaces(USHORT cIIDs, IID *pIIDs, SQIResult *pQIRes);
+ BOOL InstantiatedProxy(REFIID riid, void **ppv, HRESULT *phr);
+ BOOL RemIsConnected(void);
+ void Disconnect(void);
+ void ReconnectProxies(void);
+ HRESULT FindIPIDEntry(REFIID riid, IPIDEntry **ppEntry);
+ void SetMarshalTime(void) { _dwMarshalTime = GetCurrentTime() ;}
+ void SetNoPing(void) { _dwFlags |= SMFLAGS_NOPING; }
+ HRESULT RemoteChangeRef(BOOL fLock, BOOL fLastUnlockReleases);
+
+ // used by CRpcChannelBuffer
+ HRESULT LookupStub(REFIID riid, IRpcStubBuffer **ppStub);
+ ULONG LockClient(void);
+ ULONG UnLockClient(void);
+ void LockServer(void);
+ void UnLockServer(void);
+
+ // used by CRemoteUnknown
+ HRESULT PreventDisconnect();
+ HRESULT PreventPendingDisconnect();
+ HRESULT HandlePendingDisconnect(HRESULT hr);
+ HRESULT IncSrvIPIDCnt(IPIDEntry *pEntry, ULONG cRefs, ULONG cPrivateRefs,
+ SECURITYBINDING *pName, DWORD mshlflags);
+ void DecSrvIPIDCnt(IPIDEntry *pEntry, ULONG cRefs, ULONG cPrivateRefs,
+ SECURITYBINDING *pName, DWORD mshlflags);
+ BOOL CanRunDown(DWORD iNow);
+ void FillSTD(STDOBJREF *pStd, ULONG cRefs, DWORD mshlflags, IPIDEntry *pEntry);
+ IPIDEntry *GetConnectedIPID();
+ HRESULT GetSecureRemUnk( IRemUnknown **, OXIDEntry * );
+ void SetSecureRemUnk( IRemUnknown *pSecure ) { _pSecureRemUnk = pSecure; }
+ BOOL CheckSecureRemUnk() { return _pSecureRemUnk != NULL; }
+
+ // used by CoLockObjectExternal
+ void IncTableCnt(void);
+ void DecTableCnt(void);
+
+ // used by CClientSecurity
+ HRESULT FindIPIDEntryByInterface( void * pProxy, IPIDEntry ** ppEntry );
+ HRESULT PrivateCopyProxy( IUnknown *pProxy, IUnknown **ppProxy );
+
+#if DBG==1
+ void DbgDumpInterfaceList(void);
+#else
+ void DbgDumpInterfaceList(void) {}
+#endif
+
+ friend INTERNAL ReleaseMarshalObjRef(OBJREF &objref);
+
+private:
+
+ HRESULT FirstMarshal(IUnknown *pUnk, DWORD mshlflags);
+ HRESULT CreateChannel(OXIDEntry *pOXIDEntry, DWORD dwFlags, REFIPID ripid,
+ REFIID riid, CRpcChannelBuffer **ppChnl);
+
+
+ // Internal methods to find or create interface proxies or stubs
+ HRESULT CreateProxy(REFIID riid, IRpcProxyBuffer **ppProxy, void **ppv, BOOL *pfNonNDR);
+ HRESULT CreateStub(REFIID riid, IRpcStubBuffer **ppStub, void **ppv, BOOL *pfNonNDR);
+ HRESULT GetPSFactory(REFIID riid, IUnknown *pUnkWow, BOOL fServer, IPSFactoryBuffer **ppIPSF, BOOL *pfNonNDR);
+
+
+ // IPID Table Manipulation subroutines
+ HRESULT UnmarshalIPID(REFIID riid, STDOBJREF *pStd, OXIDEntry *pOXIDEntry, void **ppv);
+ HRESULT FindIPIDEntryByIPID(REFIPID ripid, IPIDEntry **ppEntry);
+ HRESULT MakeSrvIPIDEntry(REFIID riid, IPIDEntry **ppEntry);
+ HRESULT MakeCliIPIDEntry(REFIID riid, STDOBJREF *pStd, OXIDEntry *pOXIDEntry, IPIDEntry **ppEntry);
+ HRESULT ConnectIPIDEntry(STDOBJREF *pStd, OXIDEntry *pOXIDEntry, IPIDEntry *pEntry);
+ HRESULT AddIPIDEntry(OXIDEntry *pOXIDEntry, IPID *pipid, REFIID riid,
+ CRpcChannelBuffer *pChnl, IUnknown *pUnkStub,
+ void *pv, IPIDEntry **ppEntry);
+ void DisconnectCliIPIDs(void);
+ void DisconnectSrvIPIDs(void);
+ void ReleaseCliIPIDs(void);
+ void IncStrongAndNotifyAct(IPIDEntry *pEntry, DWORD mshlflags);
+ void DecStrongAndNotifyAct(IPIDEntry *pEntry, DWORD mshlflags);
+
+
+
+ // reference counting routines
+ HRESULT GetNeededRefs(STDOBJREF *pStd, OXIDEntry *pOXIDEntry, IPIDEntry *pEntry);
+ HRESULT RemQIAndUnmarshal(USHORT cIIDs, IID* pIIDs, SQIResult *pQIRes);
+ void FillObjRef(OBJREF &objref, ULONG cRefs, DWORD mshlflags, IPIDEntry *pEntry);
+
+ BOOL ClientSide() { return (_dwFlags & SMFLAGS_CLIENT_SIDE); }
+ BOOL ServerSide() { return !(_dwFlags & SMFLAGS_CLIENT_SIDE); }
+
+#if DBG==1
+ void AssertValid();
+ void AssertDisconnectPrevented();
+ void ValidateSTD(STDOBJREF *pStd);
+ void ValidateIPIDEntry(IPIDEntry *pEntry);
+ void DbgWalkIPIDs();
+ REFMOXID GetMOXID(void);
+#else
+ void AssertValid() {}
+ void AssertDisconnectPrevented() {}
+ void ValidateSTD(STDOBJREF *pStd) {}
+ void ValidateIPIDEntry(IPIDEntry *pEntry) {}
+ void DbgWalkIPIDs() {}
+#endif
+
+
+ DWORD _dwFlags; // flags info (see SMFLAGS)
+ LONG _cIPIDs; // count of IPIDs in this object
+ IPIDEntry *_pFirstIPID; // first IPID of this object
+ CStdIdentity *_pStdId; // standard identity
+ CRpcChannelBuffer *_pChnl; // channel ptr
+ CLSID _clsidHandler; // clsid of handler (if needed)
+ LONG _cNestedCalls; // count of nested calls
+ LONG _cTableRefs; // count of table marshals
+ DWORD _dwMarshalTime; // tick count when last marshalled
+ IRemUnknown *_pSecureRemUnk; // remunk with app specified security
+};
+
+
+//+------------------------------------------------------------------------
+//
+// Member: CStdMarshal::CanRunDown
+//
+// Synopsis: determines if it is OK to rundown this object, based on
+// the current time and the marshaled state of the object.
+//
+// History: 24-Aug-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+
+// time period of one ping, used to determine if OK to rundown OID
+extern DWORD giPingPeriod;
+
+inline BOOL CStdMarshal::CanRunDown(DWORD iNow)
+{
+ ASSERT_LOCK_HELD
+
+ // Make sure the interface hasn't been marshalled since it
+ // was last pinged. This calculation handles the wrap case.
+
+ if (!(_dwFlags & (SMFLAGS_IGNORERUNDOWN | SMFLAGS_NOPING)) &&
+ (iNow - _dwMarshalTime >= giPingPeriod))
+ {
+ Win4Assert(_cTableRefs == 0);
+ ComDebOut((DEB_MARSHAL, "Running Down Object this:%x\n", this));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CStdMarshal::LockServer/UnLockServer
+//
+// Synopsis: Locks the server side object during incoming calls in order
+// to prevent the object going away in a nested disconnect.
+//
+// History: 12-Jun-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+inline void CStdMarshal::LockServer(void)
+{
+ Win4Assert(ServerSide());
+ ASSERT_LOCK_HELD
+
+ AddRef();
+ InterlockedIncrement(&_cNestedCalls);
+}
+
+inline void CStdMarshal::UnLockServer(void)
+{
+ Win4Assert(ServerSide());
+ ASSERT_LOCK_RELEASED
+
+ if ((InterlockedDecrement(&_cNestedCalls) == 0) &&
+ (_dwFlags & SMFLAGS_PENDINGDISCONNECT))
+ {
+ // a disconnect was pending, do that now.
+ Disconnect();
+ }
+
+ Release();
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CStdMarshal::GetConnectedIPID
+//
+// Synopsis: Finds the first connected IPID entry.
+//
+// History: 10-Apr-96 AlexMit Plagerized
+//
+//-------------------------------------------------------------------------
+inline IPIDEntry *CStdMarshal::GetConnectedIPID()
+{
+ Win4Assert( _pFirstIPID != NULL );
+ IPIDEntry *pIPIDEntry = _pFirstIPID;
+
+ // Find an IPID entry that has an OXID pointer.
+ while (pIPIDEntry->dwFlags & IPIDF_DISCONNECTED)
+ {
+ pIPIDEntry = pIPIDEntry->pNextOID;
+ }
+ Win4Assert( pIPIDEntry != NULL );
+ return pIPIDEntry;
+}
+#endif // _MARSHAL_HXX_
diff --git a/private/ole32/com/dcomrem/orpc_dbg.c b/private/ole32/com/dcomrem/orpc_dbg.c
new file mode 100644
index 000000000..ef410ce1c
--- /dev/null
+++ b/private/ole32/com/dcomrem/orpc_dbg.c
@@ -0,0 +1,643 @@
+//--------------------------------------------------------------------------
+// ORPC_DBG.C (tabs 4)
+//
+// !!!!!!!!! !!!!!!!!! NOTE NOTE NOTE NOTE !!!!!!!!! !!!!!!!!!!
+//
+// SEND MAIL TO SANJAYS IF YOU MODIFY THIS FILE!
+// WE MUST KEEP OLE AND LANGUAGES IN SYNC!
+//
+// !!!!!!!!! !!!!!!!!! NOTE NOTE NOTE NOTE !!!!!!!!! !!!!!!!!!!
+//
+// Created 08-Oct-1993 by Mike Morearty. The master copy of this file
+// is in the LANGAPI project owned by the Languages group.
+//
+// Helper functions for OLE RPC debugging.
+//--------------------------------------------------------------------------
+
+#include <windows.h>
+#ifndef _CHICAGO_
+#include <tchar.h>
+#endif
+
+#include "orpc_dbg.h"
+
+static TCHAR tszAeDebugName[] = TEXT("AeDebug");
+static TCHAR tszAutoName[] = TEXT("Auto");
+static TCHAR tszOldAutoName[] = TEXT("OldAuto");
+static TCHAR tszDebugObjectRpcEnabledName[] =
+#ifdef _CHICAGO_
+ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DebugObjectRPCEnabled";
+#else
+ TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\DebugObjectRPCEnabled");
+#endif
+
+// Emit the ORPC signature into the bytestream of the function
+#define ORPC_EMIT_SIGNATURE() 'M', 'A', 'R', 'B',
+
+// Emit a LONG into the bytestream
+#define ORPC_EMIT_LONG(l) \
+ ((l >> 0) & 0xFF), \
+ ((l >> 8) & 0xFF), \
+ ((l >> 16) & 0xFF), \
+ ((l >> 24) & 0xFF),
+
+// Emit a WORD into the bytestream
+#define ORPC_EMIT_WORD(w) \
+ ((w >> 0) & 0xFF), \
+ ((w >> 8) & 0xFF),
+
+// Emit a BYTE into the bytestream
+#define ORPC_EMIT_BYTE(b) \
+ b,
+
+// Emit a GUID into the bytestream
+#define ORPC_EMIT_GUID(l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ ORPC_EMIT_LONG(l) \
+ ORPC_EMIT_WORD(w1) ORPC_EMIT_WORD(w2) \
+ ORPC_EMIT_BYTE(b1) ORPC_EMIT_BYTE(b2) \
+ ORPC_EMIT_BYTE(b3) ORPC_EMIT_BYTE(b4) \
+ ORPC_EMIT_BYTE(b5) ORPC_EMIT_BYTE(b6) \
+ ORPC_EMIT_BYTE(b7) ORPC_EMIT_BYTE(b8)
+
+BYTE rgbClientGetBufferSizeSignature[] =
+{
+ ORPC_EMIT_SIGNATURE()
+ ORPC_EMIT_GUID(0x9ED14F80, 0x9673, 0x101A, 0xB0, 0x7B,
+ 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x11)
+ ORPC_EMIT_LONG(0)
+};
+
+BYTE rgbClientFillBufferSignature[] =
+{
+ ORPC_EMIT_SIGNATURE()
+ ORPC_EMIT_GUID(0xDA45F3E0, 0x9673, 0x101A, 0xB0, 0x7B,
+ 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x11)
+ ORPC_EMIT_LONG(0)
+};
+
+BYTE rgbClientNotifySignature[] =
+{
+ ORPC_EMIT_SIGNATURE()
+ ORPC_EMIT_GUID(0x4F60E540, 0x9674, 0x101A, 0xB0, 0x7B,
+ 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x11)
+ ORPC_EMIT_LONG(0)
+};
+
+BYTE rgbServerNotifySignature[] =
+{
+ ORPC_EMIT_SIGNATURE()
+ ORPC_EMIT_GUID(0x1084FA00, 0x9674, 0x101A, 0xB0, 0x7B,
+ 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x11)
+ ORPC_EMIT_LONG(0)
+};
+
+BYTE rgbServerGetBufferSizeSignature[] =
+{
+ ORPC_EMIT_SIGNATURE()
+ ORPC_EMIT_GUID(0x22080240, 0x9674, 0x101A, 0xB0, 0x7B,
+ 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x11)
+ ORPC_EMIT_LONG(0)
+};
+
+BYTE rgbServerFillBufferSignature[] =
+{
+ ORPC_EMIT_SIGNATURE()
+ ORPC_EMIT_GUID(0x2FC09500, 0x9674, 0x101A, 0xB0, 0x7B,
+ 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x11)
+ ORPC_EMIT_LONG(0)
+};
+
+// Macro to deal with assigning refiid for both C and C++.
+#if defined(__cplusplus)
+#define ASSIGN_REFIID(orpc_all, iid) ((orpc_all).refiid = &iid)
+#else
+#define ASSIGN_REFIID(orpc_all, iid) ((orpc_all).refiid = iid)
+#endif
+
+#pragma code_seg(".orpc")
+
+//--------------------------------------------------------------------------
+// SzSubStr()
+//
+// Find str2 in str2
+//--------------------------------------------------------------------------
+
+static LPTSTR SzSubStr(LPTSTR str1, LPTSTR str2)
+{
+ CharLower(str1);
+
+#ifdef _CHICAGO_
+ return strstr(str1, str2);
+#else
+ return _tcsstr(str1, str2);
+#endif
+}
+
+//--------------------------------------------------------------------------
+// DebugORPCSetAuto()
+//
+// Sets the "Auto" value in the "AeDebug" key to "1", and saves info
+// necessary to restore the previous value later.
+//--------------------------------------------------------------------------
+
+BOOL WINAPI DebugORPCSetAuto(VOID)
+{
+ HKEY hkey;
+ TCHAR rgtchDebugger[256]; // 256 is the length NT itself uses for this
+ TCHAR rgtchAuto[256];
+ TCHAR rgtchOldAuto[2]; // don't need to get the whole thing
+
+ // If the "DebugObjectRPCEnabled" key does not exist, then do not
+ // cause any notifications
+ if (RegOpenKey(HKEY_LOCAL_MACHINE, tszDebugObjectRpcEnabledName, &hkey))
+ return FALSE;
+ RegCloseKey(hkey);
+
+ // If the AeDebug debugger string does not exist, or if it contains
+ // "drwtsn32" anywhere in it, then don't cause any notifications,
+ // because Dr. Watson is not capable of fielding OLE notifications.
+ if (!GetProfileString(tszAeDebugName, TEXT("Debugger"), TEXT(""),
+ rgtchDebugger, sizeof(rgtchDebugger)) ||
+ SzSubStr(rgtchDebugger, TEXT("drwtsn32")) != NULL)
+ {
+ return FALSE;
+ }
+
+ // Must ensure that the "Auto" value in the AeDebug registry key
+ // is set to "1", so that the embedded INT 3 below will cause the
+ // debugger to be automatically spawned if it doesn't already
+ // exist.
+
+ // Get old "Auto" value
+ GetProfileString(tszAeDebugName, tszAutoName, TEXT(""),
+ rgtchAuto, sizeof(rgtchAuto));
+
+ // If "OldAuto" already existed, then it's probably left over from
+ // a previous invocation of the debugger, so don't overwrite it.
+ // Otherwise, copy "Auto" value to "OldAuto"
+ if (!GetProfileString(tszAeDebugName, tszOldAutoName, TEXT(""),
+ rgtchOldAuto, sizeof(rgtchOldAuto)))
+ {
+ if (!WriteProfileString(tszAeDebugName, tszOldAutoName, rgtchAuto))
+ return FALSE;
+ }
+
+ // Change "Auto" value to "1"
+ if (!WriteProfileString(tszAeDebugName, tszAutoName, TEXT("1")))
+ return FALSE;
+
+ return TRUE;
+}
+
+//--------------------------------------------------------------------------
+// DebugORPCRestoreAuto()
+//
+// Restores the previous value of the "Auto" value in the AeDebug key.
+//--------------------------------------------------------------------------
+
+VOID WINAPI DebugORPCRestoreAuto(VOID)
+{
+ TCHAR rgtchAuto[256];
+
+ // Restore old Auto value (or delete it if it didn't exist before).
+ // Very minor bug here: if "Auto" was previously "", then we will
+ // now delete it. That's not a big deal though, as an empty "Auto"
+ // and a nonexistent one have the same effect.
+ GetProfileString(tszAeDebugName, tszOldAutoName, TEXT(""),
+ rgtchAuto, sizeof(rgtchAuto));
+
+ WriteProfileString(tszAeDebugName, tszAutoName,
+ rgtchAuto[0] ? rgtchAuto : NULL);
+
+ // Delete OldAuto value
+ WriteProfileString(tszAeDebugName, tszOldAutoName, NULL);
+}
+
+ // This pragma is necessary in case the compiler chooses not to inline these
+// functions (e.g. in a debug build, when optimizations are off).
+
+#pragma code_seg(".orpc")
+
+__inline DWORD WINAPI OrpcBreakpointFilter(
+ LPEXCEPTION_POINTERS lpExcptPtr,
+ BOOL *lpAeDebugAttached ) \
+{
+ BOOL fAeDebugAttached = FALSE;
+ DWORD dwRet;
+
+ if ( lpExcptPtr->ExceptionRecord->ExceptionCode == EXCEPTION_ORPC_DEBUG )
+ {
+ if ( UnhandledExceptionFilter(lpExcptPtr) == EXCEPTION_CONTINUE_SEARCH )
+ {
+ // It is important that we don't return EXCEPTION_CONTINUE_SEARCH.
+ // This is because there might an handler up the stack which could
+ // handle this exception. Just set the flag indicating that a
+ // debugger is now attached.
+
+ fAeDebugAttached = TRUE;
+ }
+ dwRet = EXCEPTION_EXECUTE_HANDLER;
+ }
+ else
+ {
+ // Not one of our exceptions.
+ dwRet = EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ if ( lpAeDebugAttached != NULL )
+ (*lpAeDebugAttached) = fAeDebugAttached;
+
+ return dwRet;
+}
+
+ULONG WINAPI DebugORPCClientGetBufferSize(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ void * reserved,
+ IUnknown * pUnkProxyMgr,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled)
+{
+ ULONG cbBuffer = 0;
+ ORPC_DBG_ALL orpc_all = {0};
+ ORPC_DBG_ALL * lpOrpcAll = &orpc_all;
+
+ if (!fHookEnabled)
+ return 0; // We should be able to assert that this never happens.
+
+ orpc_all.pSignature = rgbClientGetBufferSizeSignature;
+ orpc_all.pMessage = pMessage;
+ orpc_all.reserved = reserved;
+ orpc_all.pUnkProxyMgr = pUnkProxyMgr;
+ orpc_all.lpcbBuffer = &cbBuffer;
+ ASSIGN_REFIID(orpc_all, iid);
+
+ if ( lpInitArgs == NULL || lpInitArgs->lpIntfOrpcDebug == NULL )
+ {
+ // Do Orpc debug notification using an exception.
+ __try
+ {
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+ __except(OrpcBreakpointFilter(GetExceptionInformation(), NULL))
+ {
+ // this just goes down to the to the return.
+ }
+ }
+ else
+ {
+ IOrpcDebugNotify __RPC_FAR *lpIntf = lpInitArgs->lpIntfOrpcDebug;
+
+ // call the appropriate method in the registered interface
+ // ( this is typically used by in-proc debuggers)
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ lpIntf->ClientGetBufferSize(lpOrpcAll);
+#else
+ lpIntf->lpVtbl->ClientGetBufferSize(lpIntf, lpOrpcAll);
+#endif
+
+ }
+
+ return cbBuffer;
+}
+
+//--------------------------------------------------------------------------
+
+void WINAPI DebugORPCClientFillBuffer(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ void * reserved,
+ IUnknown * pUnkProxyMgr,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled)
+{
+ ORPC_DBG_ALL orpc_all = {0};
+ ORPC_DBG_ALL * lpOrpcAll = &orpc_all;
+
+ if (!fHookEnabled)
+ return; // We should be able to assert that this never happens
+
+ orpc_all.pSignature = rgbClientFillBufferSignature;
+
+ orpc_all.pMessage = pMessage;
+ orpc_all.reserved = reserved;
+ orpc_all.pUnkProxyMgr = pUnkProxyMgr;
+ ASSIGN_REFIID(orpc_all, iid);
+
+ orpc_all.pvBuffer = pvBuffer;
+ orpc_all.cbBuffer = cbBuffer;
+
+
+ if ( lpInitArgs == NULL || lpInitArgs->lpIntfOrpcDebug == NULL )
+ {
+ // Do Orpc debug notification using an exception.
+ __try
+ {
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+ __except(OrpcBreakpointFilter(GetExceptionInformation(), NULL))
+ {
+ // this just returns.
+ }
+ }
+ else
+ {
+ IOrpcDebugNotify __RPC_FAR *lpIntf = lpInitArgs->lpIntfOrpcDebug;
+
+ // call the appropriate method in the registered interface
+ // ( this is typically used by in-proc debuggers)
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ lpIntf->ClientFillBuffer(lpOrpcAll);
+#else
+ lpIntf->lpVtbl->ClientFillBuffer(lpIntf, lpOrpcAll);
+#endif
+ }
+}
+
+//--------------------------------------------------------------------------
+
+// This special value is to ensure backward compatibility with VC 2.0.
+// It is not exposed in the header files. The behavior if this is the value
+// in the first four bytes of the debug packet, should be identical to
+// ORPC_DEBUG_ALWAYS.
+
+#define ORPC_COMPATIBILITY_CODE (0x4252414DL)
+
+void WINAPI DebugORPCClientNotify(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ void * reserved,
+ IUnknown * pUnkProxyMgr,
+ HRESULT hresult,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled)
+{
+ ORPC_DBG_ALL orpc_all = {0};
+ ORPC_DBG_ALL * lpOrpcAll = &orpc_all;
+ BOOL fRethrow = FALSE;
+
+ // First check to see if the debugger on the other side
+ // wants us to notify this side if the hook is not enabled.
+ if (!fHookEnabled)
+ {
+ if (cbBuffer >= 4)
+ {
+ LONG orpcCode = *(LONG *)pvBuffer;
+ if ( orpcCode == ORPC_DEBUG_IF_HOOK_ENABLED)
+ return; // No notification in this case.
+ }
+ }
+
+ orpc_all.pSignature = rgbClientNotifySignature;
+
+ orpc_all.pMessage = pMessage;
+ orpc_all.reserved = reserved;
+ orpc_all.pUnkProxyMgr = pUnkProxyMgr;
+ orpc_all.hresult = hresult;
+ ASSIGN_REFIID(orpc_all, iid);
+
+ orpc_all.pvBuffer = pvBuffer;
+ orpc_all.cbBuffer = cbBuffer;
+
+ if ( lpInitArgs == NULL || lpInitArgs->lpIntfOrpcDebug == NULL )
+ {
+ if (DebugORPCSetAuto())
+ {
+ // Do Orpc debug notification using an exception.
+ __try
+ {
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+ __except(OrpcBreakpointFilter(GetExceptionInformation(), &fRethrow))
+ {
+ // Fall through.
+ }
+
+ if (fRethrow)
+ {
+ // At this point we are sure that a debugger is attached
+ // so we raise this exception outside of a __try block.
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+
+ DebugORPCRestoreAuto();
+ }
+
+ }
+ else
+ {
+ IOrpcDebugNotify __RPC_FAR *lpIntf = lpInitArgs->lpIntfOrpcDebug;
+
+ // call the appropriate method in the registered interface
+ // ( this is typically used by in-proc debuggers)
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ lpIntf->ClientNotify(lpOrpcAll);
+#else
+ lpIntf->lpVtbl->ClientNotify(lpIntf, lpOrpcAll);
+#endif
+ }
+
+}
+
+//--------------------------------------------------------------------------
+
+void WINAPI DebugORPCServerNotify(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ IRpcChannelBuffer * pChannel,
+ void * pInterface,
+ IUnknown * pUnkObject,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled)
+
+{
+ ORPC_DBG_ALL orpc_all = {0};
+ ORPC_DBG_ALL * lpOrpcAll = &orpc_all;
+ BOOL fRethrow = FALSE;
+
+ // First check to see if the debugger on the other side
+ // wants us to notify this side if the hook is not enabled.
+ if (!fHookEnabled)
+ {
+ if (cbBuffer >= 4)
+ {
+ LONG orpcCode = *(LONG *)pvBuffer;
+ if ( orpcCode == ORPC_DEBUG_IF_HOOK_ENABLED)
+ return; // No notification in this case.
+ }
+ }
+
+ orpc_all.pSignature = rgbServerNotifySignature;
+
+ orpc_all.pMessage = pMessage;
+ orpc_all.pChannel = pChannel;
+ orpc_all.pInterface = pInterface;
+ orpc_all.pUnkObject = pUnkObject;
+ ASSIGN_REFIID(orpc_all, iid);
+
+ orpc_all.pvBuffer = pvBuffer;
+ orpc_all.cbBuffer = cbBuffer;
+
+ if ( lpInitArgs == NULL || lpInitArgs->lpIntfOrpcDebug == NULL )
+ {
+ if (DebugORPCSetAuto())
+ {
+ // Do Orpc debug notification using an exception.
+ __try
+ {
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+ __except(OrpcBreakpointFilter(GetExceptionInformation(), &fRethrow))
+ {
+ // Fall through
+ }
+
+ if (fRethrow)
+ {
+ // At this point we are sure that a debugger is attached
+ // so we raise this exception outside of a __try block.
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+
+ DebugORPCRestoreAuto();
+ }
+
+ }
+ else
+ {
+ IOrpcDebugNotify __RPC_FAR *lpIntf = lpInitArgs->lpIntfOrpcDebug;
+
+ // call the appropriate method in the registered interface
+ // ( this is typically used by in-proc debuggers)
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ lpIntf->ServerNotify(lpOrpcAll);
+#else
+ lpIntf->lpVtbl->ServerNotify(lpIntf, lpOrpcAll);
+#endif
+ }
+
+}
+
+//--------------------------------------------------------------------------
+
+ULONG WINAPI DebugORPCServerGetBufferSize(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ IRpcChannelBuffer * pChannel,
+ void * pInterface,
+ IUnknown * pUnkObject,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled)
+
+{
+ ULONG cbBuffer = 0;
+ ORPC_DBG_ALL orpc_all = {0};
+ ORPC_DBG_ALL * lpOrpcAll = &orpc_all;
+
+ if (!fHookEnabled)
+ return 0; // We should be able to assert that this never happens.
+
+ orpc_all.pSignature = rgbServerGetBufferSizeSignature;
+
+ orpc_all.pMessage = pMessage;
+ orpc_all.pChannel = pChannel;
+ orpc_all.pInterface = pInterface;
+ orpc_all.pUnkObject = pUnkObject;
+ orpc_all.lpcbBuffer = &cbBuffer;
+ ASSIGN_REFIID(orpc_all, iid);
+
+ if ( lpInitArgs == NULL || lpInitArgs->lpIntfOrpcDebug == NULL )
+ {
+ // Do Orpc debug notification using an exception.
+ __try
+ {
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+ __except(OrpcBreakpointFilter(GetExceptionInformation(), NULL))
+ {
+ // this just goes down to the return.
+ }
+ }
+ else
+ {
+ IOrpcDebugNotify __RPC_FAR *lpIntf = lpInitArgs->lpIntfOrpcDebug;
+
+ // call the appropriate method in the registered interface
+ // ( this is typically used by in-proc debuggers)
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ lpIntf->ServerGetBufferSize(lpOrpcAll);
+#else
+ lpIntf->lpVtbl->ServerGetBufferSize(lpIntf, lpOrpcAll);
+#endif
+ }
+
+ return cbBuffer;
+}
+
+//--------------------------------------------------------------------------
+
+void WINAPI DebugORPCServerFillBuffer(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ IRpcChannelBuffer * pChannel,
+ void * pInterface,
+ IUnknown * pUnkObject,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled)
+{
+ ORPC_DBG_ALL orpc_all = {0};
+ ORPC_DBG_ALL * lpOrpcAll = &orpc_all;
+
+ if (!fHookEnabled)
+ return; // We should be able to assert that this never happens.
+
+ orpc_all.pSignature = rgbServerFillBufferSignature;
+
+ orpc_all.pMessage = pMessage;
+ orpc_all.pChannel = pChannel;
+ orpc_all.pInterface = pInterface;
+ orpc_all.pUnkObject = pUnkObject;
+ ASSIGN_REFIID(orpc_all, iid);
+
+ orpc_all.pvBuffer = pvBuffer;
+ orpc_all.cbBuffer = cbBuffer;
+
+ if ( lpInitArgs == NULL || lpInitArgs->lpIntfOrpcDebug == NULL )
+ {
+ // Do Orpc debug notification using an exception.
+ __try
+ {
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+ __except(OrpcBreakpointFilter(GetExceptionInformation(), NULL))
+ {
+ // this just returns.
+ }
+ }
+ else
+ {
+ IOrpcDebugNotify __RPC_FAR *lpIntf = lpInitArgs->lpIntfOrpcDebug;
+
+ // call the appropriate method in the registered interface
+ // ( this is typically used by in-proc debuggers)
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ lpIntf->ServerFillBuffer(lpOrpcAll);
+#else
+ lpIntf->lpVtbl->ServerFillBuffer(lpIntf, lpOrpcAll);
+#endif
+ }
+}
+
+// WARNING: there is no way to "pop" to the previously active code_seg:
+// this will revert to what the code seg was when compilation began.
+#pragma code_seg()
+
+
diff --git a/private/ole32/com/dcomrem/orpc_dbg.h b/private/ole32/com/dcomrem/orpc_dbg.h
new file mode 100644
index 000000000..62b512df7
--- /dev/null
+++ b/private/ole32/com/dcomrem/orpc_dbg.h
@@ -0,0 +1,219 @@
+//--------------------------------------------------------------------------
+// ORPC_DBG.H (tabs 4)
+//
+// !!!!!!!!! !!!!!!!!! NOTE NOTE NOTE NOTE !!!!!!!!! !!!!!!!!!!
+//
+// SEND MAIL TO SANJAYS IF YOU MODIFY THIS FILE!
+// WE MUST KEEP OLE AND LANGUAGES IN SYNC!
+//
+// !!!!!!!!! !!!!!!!!! NOTE NOTE NOTE NOTE !!!!!!!!! !!!!!!!!!!
+//
+// Created 07-Oct-1993 by Mike Morearty. The master copy of this file
+// is in the LANGAPI project owned by the Languages group.
+//
+// Macros and functions for OLE RPC debugging. For a detailed explanation,
+// see OLE2DBG.DOC.
+//
+//--------------------------------------------------------------------------
+
+
+#ifndef __ORPC_DBG__
+#define __ORPC_DBG__
+
+//--------------------------------------------------------------------------
+// Public:
+//--------------------------------------------------------------------------
+
+// This structure is the information packet which OLE sends the debugger
+// when it is notifying it about an OLE debug event. The first field in this
+// structure points to the signature which identifies the type of the debug
+// notification. The consumer of the notification can then get the relevant
+// information from the struct members. Note that for each OLE debug notification
+// only a subset of the struct members are meaningful.
+
+
+typedef struct ORPC_DBG_ALL
+{
+ BYTE * pSignature;
+ RPCOLEMESSAGE * pMessage;
+ const IID * refiid;
+ IRpcChannelBuffer * pChannel;
+ IUnknown * pUnkProxyMgr;
+ void * pInterface;
+ IUnknown * pUnkObject;
+ HRESULT hresult;
+ void * pvBuffer;
+ ULONG cbBuffer;
+ ULONG * lpcbBuffer;
+ void * reserved;
+} ORPC_DBG_ALL;
+
+typedef ORPC_DBG_ALL __RPC_FAR *LPORPC_DBG_ALL;
+
+// Interface definition for IOrpcDebugNotify
+
+typedef interface IOrpcDebugNotify IOrpcDebugNotify;
+
+typedef IOrpcDebugNotify __RPC_FAR * LPORPCDEBUGNOTIFY;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOrpcDebugNotify : public IUnknown
+ {
+ public:
+ virtual VOID __stdcall ClientGetBufferSize (LPORPC_DBG_ALL) = 0;
+ virtual VOID __stdcall ClientFillBuffer (LPORPC_DBG_ALL) = 0;
+ virtual VOID __stdcall ClientNotify (LPORPC_DBG_ALL) = 0;
+ virtual VOID __stdcall ServerNotify (LPORPC_DBG_ALL) = 0;
+ virtual VOID __stdcall ServerGetBufferSize (LPORPC_DBG_ALL) = 0;
+ virtual VOID __stdcall ServerFillBuffer (LPORPC_DBG_ALL) = 0;
+ };
+
+#else /* C style interface */
+
+ typedef struct IOrpcDebugNotifyVtbl
+ {
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOrpcDebugNotify __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOrpcDebugNotify __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOrpcDebugNotify __RPC_FAR * This);
+
+ VOID ( __stdcall __RPC_FAR *ClientGetBufferSize)(
+ IOrpcDebugNotify __RPC_FAR * This,
+ LPORPC_DBG_ALL lpOrpcDebugAll);
+
+ VOID ( __stdcall __RPC_FAR *ClientFillBuffer)(
+ IOrpcDebugNotify __RPC_FAR * This,
+ LPORPC_DBG_ALL lpOrpcDebugAll);
+
+ VOID ( __stdcall __RPC_FAR *ClientNotify)(
+ IOrpcDebugNotify __RPC_FAR * This,
+ LPORPC_DBG_ALL lpOrpcDebugAll);
+
+ VOID ( __stdcall __RPC_FAR *ServerNotify)(
+ IOrpcDebugNotify __RPC_FAR * This,
+ LPORPC_DBG_ALL lpOrpcDebugAll);
+
+ VOID ( __stdcall __RPC_FAR *ServerGetBufferSize)(
+ IOrpcDebugNotify __RPC_FAR * This,
+ LPORPC_DBG_ALL lpOrpcDebugAll);
+
+ VOID ( __stdcall __RPC_FAR *ServerFillBuffer)(
+ IOrpcDebugNotify __RPC_FAR * This,
+ LPORPC_DBG_ALL lpOrpcDebugAll);
+
+ } IOrpcDebugNotifyVtbl;
+
+ interface IOrpcDebugNotify
+ {
+ CONST_VTBL struct IOrpcDebugNotifyVtbl __RPC_FAR *lpVtbl;
+ };
+
+#endif
+
+// This is the structure that is passed by the debugger to OLE when it enables ORPC
+// debugging.
+typedef struct ORPC_INIT_ARGS
+{
+ IOrpcDebugNotify __RPC_FAR * lpIntfOrpcDebug;
+ void * pvPSN; // contains ptr to Process Serial No. for Mac ORPC debugging.
+ DWORD dwReserved1; // For future use, must be 0.
+ DWORD dwReserved2;
+} ORPC_INIT_ARGS;
+
+typedef ORPC_INIT_ARGS __RPC_FAR * LPORPC_INIT_ARGS;
+
+// Function pointer prototype for the "DllDebugObjectRPCHook" function.
+typedef BOOL (WINAPI* ORPCHOOKPROC)(BOOL, LPORPC_INIT_ARGS);
+
+// The first four bytes in the debug specific packet are interpreted by the
+// ORPC debug layer. The valid values are the ones defined below.
+
+#define ORPC_DEBUG_ALWAYS (0x00000000L) // Notify always.
+#define ORPC_DEBUG_IF_HOOK_ENABLED (0x00000001L) // Notify only if hook enabled.
+
+
+// This exception code indicates that the exception is really an
+// ORPC debug notification.
+
+#define EXCEPTION_ORPC_DEBUG (0x804f4c45)
+
+
+//--------------------------------------------------------------------------------------
+// Private: Declarations below this point are related to the implementation and should
+// be removed from the distributable version of the header file.
+//--------------------------------------------------------------------------------------
+
+
+// Helper routines to set & restore the "Auto" value in the registry
+
+BOOL WINAPI DebugORPCSetAuto(VOID);
+VOID WINAPI DebugORPCRestoreAuto(VOID);
+
+ ULONG WINAPI DebugORPCClientGetBufferSize(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ void * reserved,
+ IUnknown * pUnkProxyMgr,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled);
+
+void WINAPI DebugORPCClientFillBuffer(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ void * reserved,
+ IUnknown * pUnkProxyMgr,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled);
+
+void WINAPI DebugORPCClientNotify(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ void * reserved,
+ IUnknown * pUnkProxyMgr,
+ HRESULT hresult,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled);
+
+void WINAPI DebugORPCServerNotify(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ IRpcChannelBuffer * pChannel,
+ void * pInterface,
+ IUnknown * pUnkObject,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled);
+
+ULONG WINAPI DebugORPCServerGetBufferSize(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ IRpcChannelBuffer * pChannel,
+ void * pInterface,
+ IUnknown * pUnkObject,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled);
+
+void WINAPI DebugORPCServerFillBuffer(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ IRpcChannelBuffer * pChannel,
+ void * pInterface,
+ IUnknown * pUnkObject,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled);
+
+#endif // __ORPC_DBG__
diff --git a/private/ole32/com/dcomrem/pgalloc.cxx b/private/ole32/com/dcomrem/pgalloc.cxx
new file mode 100644
index 000000000..55976b35f
--- /dev/null
+++ b/private/ole32/com/dcomrem/pgalloc.cxx
@@ -0,0 +1,317 @@
+//+-----------------------------------------------------------------------
+//
+// File: pagealloc.cxx
+//
+// Contents: Special fast allocator to allocate fixed-sized entities.
+//
+// Classes: CPageAllocator
+//
+// History: 02-Feb-96 Rickhi Created
+//
+// Notes: All synchronization is the responsibility of the caller.
+//
+// CODEWORK: faster list managment
+// free empty pages
+//
+//-------------------------------------------------------------------------
+#include <ole2int.h>
+#include <pgalloc.hxx> // class def'n
+#include <locks.hxx> // LOCK/UNLOCK
+
+
+//+------------------------------------------------------------------------
+//
+// Member: CPageAllocator::Initialize, public
+//
+// Synopsis: Initializes the page allocator.
+//
+// Notes: Instances of this class must be static since this
+// function does not init all members to 0.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void CPageAllocator::Initialize(LONG cbPerEntry, LONG cEntriesPerPage)
+{
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_PAGE,
+ "CPageAllocator::Initialize cbPerEntry:%x cEntriesPerPage:%x\n",
+ cbPerEntry, cEntriesPerPage));
+
+ Win4Assert(cbPerEntry >= sizeof(PageEntry));
+ Win4Assert(cEntriesPerPage > 0);
+
+ _cbPerEntry = cbPerEntry;
+ _cEntriesPerPage = cEntriesPerPage;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CPageAllocator::Cleanup, public
+//
+// Synopsis: Cleanup the page allocator.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void CPageAllocator::Cleanup()
+{
+ ComDebOut((DEB_PAGE, "CPageAllocator::Cleanup\n"));
+ ASSERT_LOCK_HELD
+
+ if (_pPageListStart)
+ {
+ PageEntry **pPagePtr = _pPageListStart;
+ while (pPagePtr < _pPageListEnd)
+ {
+ // release each page of the table
+ PrivMemFree(*pPagePtr);
+ pPagePtr++;
+ }
+
+ // release the page list
+ PrivMemFree(_pPageListStart);
+
+ // reset the pointers so re-initialization is not needed
+ _cPages = 0;
+ _pPageListStart = NULL;
+ _pPageListEnd = NULL;
+ _pFirstFreeEntry = NULL;
+ }
+
+ ASSERT_LOCK_HELD
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CPageAllocator::AllocEntry, public
+//
+// Synopsis: Finds the first available entry in the table and returns
+// a ptr to it. Returns NULL if no space is available and it
+// cant grow the list.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+PageEntry *CPageAllocator::AllocEntry()
+{
+ ComDebOut((DEB_PAGE, "CPageAllocator::AllocEntry\n"));
+ ASSERT_LOCK_HELD
+
+ if (_pFirstFreeEntry == NULL)
+ {
+ // no free entries, grow the list
+ Grow();
+
+ if (_pFirstFreeEntry == NULL)
+ {
+ // unable to allocate more
+ return NULL;
+ }
+ }
+
+ // get the ptr to return and update the _pFirstFree to the next
+ // available entry
+
+ PageEntry *pEntry = _pFirstFreeEntry;
+ _pFirstFreeEntry = pEntry->pNext;
+
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_PAGE, "CPageAllocator::AllocEntry pEntry:%x\n", pEntry));
+ return pEntry;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CPageAllocator::ReleaseEntry, private
+//
+// Synopsis: returns an entry on the free list.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void CPageAllocator::ReleaseEntry(PageEntry *pEntry)
+{
+ ComDebOut((DEB_PAGE, "CPageAllocator::ReleaseEntry pEntry:%x\n", pEntry));
+ Win4Assert(pEntry);
+ ASSERT_LOCK_HELD
+
+ // chain it on the free list
+ pEntry->pNext = _pFirstFreeEntry;
+ _pFirstFreeEntry = pEntry;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CPageAllocator::ReleaseEntryList, private
+//
+// Synopsis: returns a list of entries to the free list.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void CPageAllocator::ReleaseEntryList(PageEntry *pFirst, PageEntry *pLast)
+{
+ ComDebOut((DEB_PAGE,
+ "CPageAllocator::ReleaseEntryList pFirst:%x pLast:%x\n",
+ pFirst, pLast));
+ Win4Assert(pFirst);
+ Win4Assert(pLast);
+ ASSERT_LOCK_HELD
+
+ // update the free list
+ pLast->pNext = _pFirstFreeEntry;
+ _pFirstFreeEntry = pFirst;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CPageAllocator::Grow, private
+//
+// Synopsis: Grows the table to allow for more Entries.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void CPageAllocator::Grow()
+{
+ Win4Assert(_pFirstFreeEntry == NULL);
+ ASSERT_LOCK_HELD
+
+ // allocate a new page
+ LONG cbPerPage = _cbPerEntry * _cEntriesPerPage;
+ PageEntry *pNewPage = (PageEntry *) PrivMemAlloc(cbPerPage);
+
+ if (pNewPage == NULL)
+ {
+ return;
+ }
+
+#if DBG==1
+ // clear the page (only needed in debug)
+ memset(pNewPage, 0, cbPerPage);
+#endif
+
+ // compute size of current page list
+ LONG cbCurListSize = _cPages * sizeof(PageEntry *);
+
+ // allocate a new page list to hold the new page ptr.
+ PageEntry **pNewList = (PageEntry **) PrivMemAlloc(cbCurListSize +
+ sizeof(PageEntry *));
+ if (pNewList)
+ {
+ // copy old page list into the new page list
+ memcpy(pNewList, _pPageListStart, cbCurListSize);
+
+ // set the new page ptr entry
+ *(pNewList + _cPages) = pNewPage;
+ _cPages ++;
+
+ // replace old page list with the new page list
+ PrivMemFree(_pPageListStart);
+ _pPageListStart = pNewList;
+ _pPageListEnd = pNewList + _cPages;
+
+
+ // update the first free entry ptr and link all the new entries
+ // together in a linked list.
+
+ _pFirstFreeEntry = pNewPage;
+
+ PageEntry *pNextFreeEntry = pNewPage;
+ PageEntry *pLastFreeEntry = (PageEntry *)(((BYTE *)pNewPage) + cbPerPage - _cbPerEntry);
+
+ while (pNextFreeEntry < pLastFreeEntry)
+ {
+ pNextFreeEntry->pNext = (PageEntry *)((BYTE *)pNextFreeEntry + _cbPerEntry);
+ pNextFreeEntry = pNextFreeEntry->pNext;
+ }
+
+ // last entry has an pNextFree of NULL (end of list)
+ pLastFreeEntry->pNext = NULL;
+ }
+ else
+ {
+ // release the allocated page.
+ PrivMemFree(pNewPage);
+ }
+
+ ComDebOut((DEB_PAGE, "CPageAllocator::Grow _pPageListStart:%x _pPageListEnd:%x _pFirstFreeEntry:%x\n",
+ _pPageListStart, _pPageListEnd, _pFirstFreeEntry));
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CPageAllocator::GetEntryIndex, public
+//
+// Synopsis: Converts a PageEntry ptr into an index.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+LONG CPageAllocator::GetEntryIndex(PageEntry *pEntry)
+{
+ for (LONG index=0; index<_cPages; index++)
+ {
+ PageEntry *pPage = *(_pPageListStart + index); // get page ptr
+ if (pEntry >= pPage)
+ {
+ if (pEntry < (PageEntry *) ((BYTE *)pPage + (_cEntriesPerPage * _cbPerEntry)))
+ {
+ // found the page that the entry lives on, compute the index of
+ // the page and the index of the entry within the page.
+ return (index << PAGETBL_PAGESHIFT) +
+ ((BYTE *)pEntry - (BYTE *)pPage) / _cbPerEntry;
+ }
+ }
+ }
+
+ // not found
+ return -1;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CPageAllocator::IsValidIndex, private
+//
+// Synopsis: determines if the given DWORD provides a legal index
+// into the PageTable.
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+BOOL CPageAllocator::IsValidIndex(LONG index)
+{
+ // make sure the index is not negative, otherwise the shift will do
+ // sign extension. check for valid page and valid offset within page
+ if ( (index >= 0) &&
+ ((index >> PAGETBL_PAGESHIFT) < _cPages) &&
+ ((index & PAGETBL_PAGEMASK) < _cEntriesPerPage) )
+ return TRUE;
+
+ // Don't print errors during shutdown.
+ if (_cPages != 0)
+ ComDebOut((DEB_ERROR, "IsValidIndex: Invalid PageTable Index:%x\n", index));
+ return FALSE;
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CPageAllocator::GetEntryPtr, public
+//
+// Synopsis: Converts an entry index into an entry pointer
+//
+// History: 02-Feb-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+PageEntry *CPageAllocator::GetEntryPtr(LONG index)
+{
+ Win4Assert(index >= 0);
+ Win4Assert(_cPages != 0);
+ Win4Assert(IsValidIndex(index));
+
+ PageEntry *pEntry = _pPageListStart[index >> PAGETBL_PAGESHIFT];
+ pEntry = (PageEntry *) ((BYTE *)pEntry +
+ ((index & PAGETBL_PAGEMASK) * _cbPerEntry));
+ return pEntry;
+}
diff --git a/private/ole32/com/dcomrem/pgalloc.hxx b/private/ole32/com/dcomrem/pgalloc.hxx
new file mode 100644
index 000000000..1c1c709d4
--- /dev/null
+++ b/private/ole32/com/dcomrem/pgalloc.hxx
@@ -0,0 +1,96 @@
+//+-----------------------------------------------------------------------
+//
+// File: pagealloc.hxx
+//
+// Contents: Special fast allocator to allocate fixed-sized entities.
+//
+// Classes: CPageAllocator
+//
+// History: 02-Feb-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+#ifndef _PAGEALLOC_HXX_
+#define _PAGEALLOC_HXX_
+
+
+//+------------------------------------------------------------------------
+//
+// struct: PageEntry. This is one entry in the page alloctor.
+//
+//+------------------------------------------------------------------------
+typedef struct tagPageEntry
+{
+ struct tagPageEntry *pNext; // next page in list
+ struct tagPageEntry *pPrev; // prev page in list
+} PageEntry;
+
+
+// Page Table constants for Index manipulation.
+// The high 16bits of the PageEntry index provides the index to the page
+// where the PageEntry is located. The lower 16bits provides the index
+// within the page where the PageEntry is located.
+
+#define PAGETBL_PAGESHIFT 16
+#define PAGETBL_PAGEMASK 0x0000ffff
+
+
+//+------------------------------------------------------------------------
+//
+// class: CPageAllocator
+//
+// Synopsis: special fast allocator for fixed-sized entities.
+//
+// Notes: The table has two-levels. The top level is an array of ptrs
+// to "pages" of entries. Each "page" is an array of entries
+// of a given size (specified at init time). This allows us to
+// grow the table by adding a new "page" and extending the top
+// level by one more pointer, while allowing the existing entries
+// to remain at the same address throughout their life times.
+//
+// A 32bit entry index can be computed for any entry. It consists
+// if two 16bit indices, one for the page pointer index, and
+// and one for the entry index on the page. There is also a
+// function to compute the entry address from its index.
+//
+// This allocator is used for various internal DCOM tables.
+// The main points are to keep related data close together
+// to reduce working set, minimize allocation time, allow
+// verifiable handles (indexs) that can be passed outside, and
+// to make debugging easier (since all data is kept in tables
+// its easier to find in the debugger).
+//
+// Tables using instances of this allocator are:
+// CMIDTable COXIDTable CIPIDTable CRIFTable
+//
+// History: 02-Feb-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+class CPageAllocator
+{
+public:
+ PageEntry *AllocEntry(); // return ptr to first free entry
+ void ReleaseEntry(PageEntry *); // return an entry to the free list
+ void ReleaseEntryList(PageEntry *pFirst, PageEntry *pLast);
+
+ LONG GetEntryIndex(PageEntry *pEntry);
+ BOOL IsValidIndex(LONG iEntry); // TRUE if index is valid
+ PageEntry *GetEntryPtr(LONG iEntry); // return ptr based on index
+
+ // initialize the table
+ void Initialize(LONG cbPerEntry, LONG cEntryPerPage);
+ void Cleanup(); // cleanup the table
+
+private:
+
+ void Grow(); // grows the table
+
+ LONG _cPages; // count of pages in the page list
+ PageEntry **_pPageListStart; // ptr to start of page list
+ PageEntry **_pPageListEnd; // ptr to end of page list
+ PageEntry *_pFirstFreeEntry; // ptr to first free page entry
+
+ LONG _cbPerEntry; // count of bytes in a single page entry
+ LONG _cEntriesPerPage; // # of page entries in a page
+};
+
+#endif // _PAGEALLOC_HXX_
diff --git a/private/ole32/com/dcomrem/remoteu.cxx b/private/ole32/com/dcomrem/remoteu.cxx
new file mode 100644
index 000000000..3c58b8599
--- /dev/null
+++ b/private/ole32/com/dcomrem/remoteu.cxx
@@ -0,0 +1,710 @@
+//+-------------------------------------------------------------------
+//
+// File: remoteu.cxx
+//
+// Copyright (c) 1996-1996, Microsoft Corp. All rights reserved.
+//
+// Contents: Remote Unknown object implementation
+//
+// Classes: CRemoteUnknown
+//
+// History: 23-Feb-95 AlexMit Created
+//
+//--------------------------------------------------------------------
+#include <ole2int.h>
+#include <remoteu.hxx> // CRemoteUnknown
+#include <ipidtbl.hxx> // COXIDTable, CIPIDTable
+#include <stdid.hxx> // CStdIdentity
+#include <channelb.hxx> // CRpcChannelBuffer
+#include <resolver.hxx> // giPingPeriod
+#include <security.hxx> // FromLocalSystem
+
+CRemoteUnknown *gpMTARemoteUnknown = NULL;
+
+const WCHAR *gLocalName = L"\\\\\\Thread to thread";
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteUnknown::CRemoteUnknown, public
+//
+// Synopsis: ctor for the CRemoteUnknown
+//
+// History: 22-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+CRemoteUnknown::CRemoteUnknown(HRESULT &hr, IPID *pipid) :
+ _pStdId(NULL)
+{
+ ASSERT_LOCK_HELD
+
+ // Marshal the remote unknown and rundown, no pinging needed. Note
+ // that we just marshal the IRundown interfaces since it inherits
+ // from IRemUnknown. This lets us use the same IPID for both
+ // interfaces. Also, we use the Internal version of MarshalObjRef in
+ // order to prevent registering the OID in the OIDTable. This allows
+ // us to receive Release calls during IDTableThreadUninitialize since
+ // we wont get cleaned up in the middle of that function. It also allows
+ // us to lazily create the OIDTable.
+
+ UNLOCK // release the LOCK because MarshalObjRef expects it unlocked.
+
+ OBJREF objref;
+ hr = MarshalInternalObjRef(objref, IID_IRundown, this, MSHLFLAGS_NOPING,
+ (void **)&_pStdId);
+
+ LOCK
+
+ // regardless of errors, put this object in TLS or the global. If we
+ // got an error marshaling, COIXIDTable::ReleaseLocalEntry still will be
+ // able to find us to cleanup properly.
+
+ COleTls tls;
+ if (tls->dwFlags & OLETLS_APARTMENTTHREADED)
+ {
+ // Store the pRemUnk in TLS so we can clean it up on CoUninitialize.
+ tls->pRemoteUnk = this;
+ }
+ else
+ {
+ // store the pRemUnk in the global for the MTA apartment
+ gpMTARemoteUnknown = this;
+ }
+
+
+ if (SUCCEEDED(hr))
+ {
+ // return the IPID to the caller, and release any allocated resources
+ // since all we wanted was the infrastructure, not the objref itself.
+
+ *pipid = ORSTD(objref).std.ipid;
+ FreeObjRef(objref);
+ }
+
+ ComDebOut((DEB_MARSHAL,
+ "CRemoteUnk::CRemoteUnk this:%x pStdId:%x hr:%x\n", this, _pStdId, hr));
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteUnknown::~CRemoteUnknown, public
+//
+// Synopsis: dtor for the CRemoteUnknown
+//
+// History: 22-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+CRemoteUnknown::~CRemoteUnknown()
+{
+ ASSERT_LOCK_HELD
+
+ if (_pStdId)
+ {
+ UNLOCK // DisconnectObject expects lock to be released
+
+ // disconnect the standard identity and release it
+ _pStdId->DisconnectObject(0);
+ _pStdId->Release();
+
+ LOCK
+ }
+
+ ComDebOut((DEB_MARSHAL, "CRemoteUnk::~CRemoteUnk this:%x\n", this));
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteUnknown::QueryInterface, public
+//
+// Synopsis: returns supported interfaces
+//
+// History: 22-Feb-95 AlexMit Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CRemoteUnknown::QueryInterface(REFIID riid, void **ppv)
+{
+ if (IsEqualIID(riid, IID_IRundown) || // more common than IUnknown
+ IsEqualIID(riid, IID_IRemUnknown) ||
+ IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppv = (IRundown *) this;
+ // no need to AddRef since we dont refcount this object
+ return S_OK;
+ }
+
+ *ppv = NULL;
+ return E_NOINTERFACE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteUnknown::AddRef, public
+//
+// Synopsis: increment reference count
+//
+// History: 23-Feb-95 AlexMit Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CRemoteUnknown::AddRef(void)
+{
+ return 1;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteUnknown::Release, public
+//
+// Synopsis: decrement reference count
+//
+// History: 23-Feb-95 AlexMit Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CRemoteUnknown::Release(void)
+{
+ return 1;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: GetIPIDEntry, private
+//
+// Synopsis: find the IPIDEntry given an IPID
+//
+// History: 23-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+IPIDEntry *GetIPIDEntry(REFIPID ripid)
+{
+ IPIDEntry *pEntry= gIPIDTbl.LookupIPID(ripid);
+
+ if (pEntry && !(pEntry->dwFlags & IPIDF_DISCONNECTED))
+ {
+ return pEntry;
+ }
+
+ return NULL;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: GetStdIdFromIPID, private
+//
+// Synopsis: find the stdid from the ipid
+//
+// History: 23-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+CStdIdentity *GetStdIdFromIPID(REFIPID ripid)
+{
+ IPIDEntry *pEntry = GetIPIDEntry(ripid);
+
+ if (pEntry)
+ {
+ return pEntry->pChnl->GetStdId();
+ }
+
+ return NULL;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteUnknown::RemQueryInterface, public
+//
+// Synopsis: returns supported interfaces
+//
+// History: 22-Feb-95 AlexMit Created
+//
+// Notes: Remote calls to QueryInterface for this OXID arrive here.
+// This routine looks up the object and calls MarshalIPID on
+// it for each interface requested.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CRemoteUnknown::RemQueryInterface(REFIPID ripid, ULONG cRefs,
+ USHORT cIids, IID *iids, REMQIRESULT **ppQIResults)
+{
+ ComDebOut((DEB_MARSHAL,
+ "CRemUnknown::RemQueryInterface this:%x ipid:%I cRefs:%x cIids:%x iids:%x ppQIResults:%x\n",
+ this, &ripid, cRefs, cIids, iids, ppQIResults));
+
+ // init the out parameters
+ *ppQIResults = NULL;
+
+ // validate the input parameters
+ if (cIids == 0)
+ {
+ return E_INVALIDARG;
+ }
+
+ // allocate space for the return parameters
+ REMQIRESULT *pQIRes = (REMQIRESULT *)CoTaskMemAlloc(cIids *
+ sizeof(REMQIRESULT));
+
+ if (pQIRes == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // Remember whether the IPID is for a strong or a weak reference,
+ // then clear the strong/weak bit so that GetIPIDEntry will find
+ // the IPID. It is safe to mask off this bit because we are the
+ // server for this IPID and we know it's format.
+
+ DWORD mshlflags = MSHLFLAGS_NORMAL;
+ DWORD sorfflags = SORF_NULL;
+
+ if (ripid.Data1 & IPIDFLAG_WEAKREF)
+ {
+ mshlflags = MSHLFLAGS_WEAK;
+ sorfflags = SORF_WEAKREF;
+ ((IPID &)(ripid)).Data1 &= ~IPIDFLAG_WEAKREF; // overcome the const
+ }
+
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ CStdIdentity *pStdId = GetStdIdFromIPID(ripid);
+ if (pStdId == NULL)
+ {
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ CoTaskMemFree(pQIRes);
+ return RPC_E_INVALID_OBJECT;
+ }
+
+ USHORT cFails = 0;
+ HRESULT hr = pStdId->PreventDisconnect();
+
+ if (SUCCEEDED(hr))
+ {
+ *ppQIResults = pQIRes;
+
+ for (USHORT i=0; i < cIids; i++, pQIRes++)
+ {
+ // marshal each interface that was requested
+
+ IPIDEntry *pIPIDEntry;
+ pQIRes->hResult = pStdId->MarshalIPID(iids[i], cRefs, mshlflags,
+ &pIPIDEntry);
+ if (SUCCEEDED(pQIRes->hResult))
+ {
+ pStdId->FillSTD(&pQIRes->std, cRefs, mshlflags, pIPIDEntry);
+ pQIRes->std.flags |= sorfflags;
+ }
+ else
+ {
+ // on failure, the STDOBJREF must be NULL
+ memset(&pQIRes->std, 0, sizeof(pQIRes->std));
+ cFails++;
+ }
+ }
+ }
+ else
+ {
+ CoTaskMemFree(pQIRes);
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ if (cFails > 0)
+ {
+ hr = (cFails == cIids) ? E_NOINTERFACE : S_FALSE;
+ }
+
+ // handle any disconnects that came in while we were marshaling
+ // the requested interfaces.
+ hr = pStdId->HandlePendingDisconnect(hr);
+
+
+ ComDebOut((DEB_MARSHAL,
+ "CRemUnknown::RemQueryInterface this:%x pQIRes:%x hr:%x\n",
+ this, *ppQIResults, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteUnknown::GetSecBinding
+//
+// Synopsis: Get the security binding of the caller
+//
+// History: 21-Feb-96 AlexMit Created
+//
+//--------------------------------------------------------------------
+HRESULT CRemoteUnknown::GetSecBinding( SECURITYBINDING **pSecBind )
+{
+ HRESULT hr;
+ DWORD lAuthnSvc;
+ DWORD lAuthzSvc;
+ DWORD lAuthnLevel;
+ const WCHAR *pPrivs;
+ DWORD lLen;
+
+ hr = CoQueryClientBlanket( &lAuthnSvc, &lAuthzSvc, NULL,
+ &lAuthnLevel, NULL, (void **) &pPrivs, NULL );
+ if (FAILED(hr))
+ return hr;
+
+ // For thread to thread calls, make up a privilege name.
+ if (pPrivs == NULL && LocalCall())
+ pPrivs = gLocalName;
+ else if (lAuthnLevel == RPC_C_AUTHN_LEVEL_NONE ||
+ lAuthnLevel < gAuthnLevel ||
+ pPrivs == NULL ||
+ pPrivs[0] == 0)
+ return E_INVALIDARG;
+
+ lLen = lstrlenW( pPrivs ) * sizeof(WCHAR);
+ *pSecBind = (SECURITYBINDING *) PrivMemAlloc(
+ sizeof(SECURITYBINDING) + lLen );
+ if (*pSecBind != NULL)
+ {
+ // BUGBUG - Sometimes mswmsg returns authn svc 0.
+ if (lAuthnSvc == RPC_C_AUTHN_NONE)
+ lAuthnSvc = RPC_C_AUTHN_WINNT;
+
+ (*pSecBind)->wAuthnSvc = (USHORT) lAuthnSvc;
+ if (lAuthzSvc == RPC_C_AUTHZ_NONE)
+ (*pSecBind)->wAuthzSvc = COM_C_AUTHZ_NONE;
+ else
+ (*pSecBind)->wAuthzSvc = (USHORT) lAuthzSvc;
+ memcpy( &(*pSecBind)->aPrincName, pPrivs, lLen+2 );
+ return S_OK;
+ }
+ else
+ return E_OUTOFMEMORY;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteUnknown::RemAddRef, public
+//
+// Synopsis: increment reference count
+//
+// History: 22-Feb-95 AlexMit Created
+//
+// Description: Remote calls to AddRef for this OXID arrive
+// here. This routine just looks up the correct remote
+// remote handler and asks it to do the work.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CRemoteUnknown::RemAddRef(unsigned short cInterfaceRefs,
+ REMINTERFACEREF InterfaceRefs[],
+ HRESULT *pResults)
+{
+ // Adjust the reference count for each entry.
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ HRESULT hr = S_OK;
+ HRESULT hr2;
+ SECURITYBINDING *pSecBind = NULL;
+ REMINTERFACEREF *pNext = InterfaceRefs;
+
+ for (USHORT i=0; i < cInterfaceRefs; i++, pNext++)
+ {
+ // Get the IPIDEntry for the specified IPID.
+ IPIDEntry *pEntry = GetIPIDEntry(pNext->ipid);
+ if (!pEntry)
+ {
+ // Don't assert on failure. The server can disconnect and go away
+ // while clients exist.
+ pResults[i] = hr = CO_E_OBJNOTREG;
+ continue;
+ }
+
+ // get the stdmarshal identity
+ CStdIdentity *pStdId = pEntry->pChnl->GetStdId();
+
+ if (pStdId)
+ {
+ ComDebOut((DEB_MARSHAL,
+ "CRemUnknown::RemAddRef pEntry:%x cCur:%x cAdd:%x cStdId:%x ipid:%I\n", pEntry,
+ pEntry->cStrongRefs, pNext->cPublicRefs, pStdId->GetRC(), &pNext->ipid));
+
+ Win4Assert(pNext->cPublicRefs > 0 ||
+ pNext->cPrivateRefs > 0);
+
+ // Lookup security info the first time an entry asks for
+ // secure references.
+ if (pNext->cPrivateRefs != 0 && pSecBind == NULL)
+ {
+ hr2 = GetSecBinding( &pSecBind );
+ if (FAILED(hr2))
+ {
+ hr = pResults[i] = hr2;
+ continue;
+ }
+ }
+
+ hr2 = pStdId->IncSrvIPIDCnt(pEntry, pNext->cPublicRefs,
+ pNext->cPrivateRefs, pSecBind,
+ MSHLFLAGS_NORMAL);
+ if (FAILED(hr2))
+ hr = pResults[i] = hr2;
+ else
+ pResults[i] = S_OK;
+ }
+ else
+ hr = pResults[i] = CO_E_OBJNOTREG;
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ PrivMemFree( pSecBind );
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteUnknown::RemRelease, public
+//
+// Synopsis: decrement reference count
+//
+// History: 22-Feb-95 AlexMit Created
+//
+// Description: Remote calls to Release for this OXID arrive
+// here. This routine just looks up the correct remote
+// remote handler and asks it to do the work.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CRemoteUnknown::RemRelease(unsigned short cInterfaceRefs,
+ REMINTERFACEREF InterfaceRefs[])
+{
+ REMINTERFACEREF *pNext = InterfaceRefs;
+ SECURITYBINDING *pSecBind = NULL;
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // Adjust the reference count for each entry.
+ for (USHORT i=0; i < cInterfaceRefs; i++, pNext++)
+ {
+ // Get the entry for the requested IPID. Remember whether this
+ // is an IPID for a strong or a weak reference, then clear the
+ // strong/weak bit so that GetIPIDEntry will find the IPID.
+
+ DWORD mshlflags = (InterfaceRefs[i].ipid.Data1 & IPIDFLAG_WEAKREF)
+ ? MSHLFLAGS_WEAK : MSHLFLAGS_NORMAL;
+
+ InterfaceRefs[i].ipid.Data1 &= ~IPIDFLAG_WEAKREF;
+ IPIDEntry *pEntry = GetIPIDEntry(InterfaceRefs[i].ipid);
+
+ if (pEntry)
+ {
+ // Get the entry for the requested IPID.
+ CStdIdentity *pStdId = pEntry->pChnl->GetStdId();
+
+ if (pStdId)
+ {
+
+ // Get the client's security binding on the first entry
+ // that releases secure references.
+ if (pNext->cPrivateRefs > 0 && pSecBind == NULL)
+ {
+ GetSecBinding( &pSecBind );
+ if (pSecBind == NULL)
+ continue;
+ }
+ pStdId->AddRef();
+
+ ComDebOut((DEB_MARSHAL,
+ "CRemUnknown::RemRelease pEntry:%x cCur:%x cStdId:%x cRel:%x mshlflags:%x ipid:%I\n", pEntry,
+ (mshlflags == MSHLFLAGS_WEAK) ? pEntry->cWeakRefs : pEntry->cStrongRefs,
+ pStdId->GetRC(), pNext->cPublicRefs, mshlflags, &pNext->ipid));
+
+ Win4Assert(pNext->cPublicRefs > 0 || pNext->cPrivateRefs > 0);
+
+ // Prevent a disconnect from occuring while releasing the
+ // interface since we have to yield the ORPC lock.
+ HRESULT hr = pStdId->PreventDisconnect();
+
+ if (SUCCEEDED(hr))
+ {
+ pStdId->DecSrvIPIDCnt(pEntry, pNext->cPublicRefs,
+ pNext->cPrivateRefs, pSecBind,
+ mshlflags);
+ }
+
+ // do the final release of the object while not holding
+ // the lock, since it may call into the server.
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ // This will handle any Disconnect that came in while we were
+ // busy. Ignore error codes since we are releasing.
+ pStdId->HandlePendingDisconnect(hr);
+
+ pStdId->Release();
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+ }
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ PrivMemFree( pSecBind );
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRemoteUnknown::RemChangeRefs, public
+//
+// Synopsis: Change an interface reference from strong/weak or vice versa.
+//
+// History: 08-Nov-95 Rickhi Created
+//
+// Note: It is safe for this routine to ignore private refcounts
+// becuase it is only called locally hence we own the client
+// implementation and can guarantee they are zero.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRemoteUnknown::RemChangeRef(ULONG flags, USHORT cInterfaceRefs,
+ REMINTERFACEREF InterfaceRefs[])
+{
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // figure out the flags to pass to the Inc/DecSrvIPIDCnt
+ BOOL fMakeStrong = flags & IRUF_CONVERTTOSTRONG;
+ DWORD IncFlags = fMakeStrong ? MSHLFLAGS_NORMAL : MSHLFLAGS_WEAK;
+ DWORD DecFlags = fMakeStrong ? MSHLFLAGS_WEAK : MSHLFLAGS_NORMAL;
+ DecFlags |= (flags & IRUF_DISCONNECTIFLASTSTRONG) ? 0 : MSHLFLAGS_KEEPALIVE;
+
+ CStdIdentity *pStdId = NULL;
+
+ for (USHORT i=0; i < cInterfaceRefs; i++)
+ {
+ // Get the entry for the specified IPID.
+ IPIDEntry *pEntry = GetIPIDEntry(InterfaceRefs[i].ipid);
+
+ if (pEntry)
+ {
+ // find the StdId for this IPID. We assume that the client
+ // only gives us IPIDs for the same object, so first time
+ // we find a StdId we remember it and AddRef it. This is a safe
+ // assumption cause the client is local to this machine (ie
+ // we wrote the client).
+
+ CStdIdentity *pStdIdTmp = pEntry->pChnl->GetStdId();
+
+ if (pStdIdTmp != NULL)
+ {
+ if (pStdId == NULL)
+ {
+ pStdId = pStdIdTmp;
+ pStdId->AddRef();
+ }
+
+ // We assume that all IPIDs are for the same object. We
+ // just verify that here.
+
+ if (pStdId == pStdIdTmp)
+ {
+ // tweak the reference counts
+ pStdId->IncSrvIPIDCnt(
+ pEntry, InterfaceRefs[i].cPublicRefs,
+ fMakeStrong ? InterfaceRefs[i].cPrivateRefs : 0,
+ NULL, IncFlags);
+ pStdId->DecSrvIPIDCnt(
+ pEntry, InterfaceRefs[i].cPublicRefs,
+ fMakeStrong ? 0 : InterfaceRefs[i].cPrivateRefs,
+ NULL, DecFlags);
+ }
+ }
+ }
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ if (pStdId)
+ {
+ // release the AddRef (if any) we did above
+ pStdId->Release();
+ }
+
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteUnknown::RundownOid, public
+//
+// Synopsis: Tell the server that no clients are using an object
+//
+// History: 25 May 95 AlexMit Created
+//
+// Description: Lookup each OID in the IDTable. If found and not
+// recently marshaled, call DisconnectObject on it.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CRemoteUnknown::RundownOid(ULONG cOid, OID aOid[],
+ unsigned char afOkToRundown[])
+{
+ DWORD iNow = GetCurrentTime();
+
+ ASSERT_LOCK_RELEASED
+
+ if (IsCallerLocalSystem())
+ {
+ LOCK
+ for (ULONG i = 0; i < cOid; i++)
+ {
+ afOkToRundown[i] = TRUE;
+
+ MOID moid;
+ MOIDFromOIDAndMID(aOid[i], gLocalMid, &moid);
+
+ CStdIdentity *pStdId;
+ HRESULT hr = LookupIDFromID(moid, TRUE, &pStdId);
+
+ if (SUCCEEDED(hr))
+ {
+ afOkToRundown[i] = pStdId->CanRunDown(iNow);
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ if (afOkToRundown[i] == TRUE)
+ {
+ pStdId->DisconnectObject( 0 );
+ }
+ pStdId->Release();
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+ else
+ {
+ // need to look at the set of pre-registered OIDs to ensure
+ // we dont run these down before we use them.
+
+ afOkToRundown[i] = gResolver.ServerCanRundownOID(aOid[i]);
+ }
+ }
+ UNLOCK
+ }
+
+ // Rather then being rude and returning access denied, tell the caller
+ // that all the objects have been released.
+ else
+ {
+ ComDebOut((DEB_ERROR, "Invalid user called CRemoteUnknown::RundownOid" ));
+ for (ULONG i = 0; i < cOid; i++)
+ afOkToRundown[i] = TRUE;
+ }
+
+ ASSERT_LOCK_RELEASED
+ return S_OK;
+}
diff --git a/private/ole32/com/dcomrem/remoteu.hxx b/private/ole32/com/dcomrem/remoteu.hxx
new file mode 100644
index 000000000..d74984fa5
--- /dev/null
+++ b/private/ole32/com/dcomrem/remoteu.hxx
@@ -0,0 +1,93 @@
+//+-------------------------------------------------------------------
+//
+// File: remoteu.hxx
+//
+// Contents: Remote Unknown class definition
+//
+// Classes: CRemoteUnknown
+//
+// Functions:
+//
+// History: 23-Feb-95 AlexMit Created
+//
+// Notes: Each server has one remote unknown object per OXID.
+// Each client OXID has a table of proxies to OXIDs referenced
+// by the client OXID. The table includes a pointer
+// to the remote unknown for the client (if it has one).
+// Entries in the table are reference counted.
+// An OXID references a thread in the apartment model and
+// a process in the free threaded model.
+//
+//--------------------------------------------------------------------
+#ifndef __REMOTEU__
+#define __REMOTEU__
+
+#include <obase.h>
+#include <remunk.h>
+#include <odeth.h>
+
+// forward declaration
+class CStdIdentity;
+
+// we set the top bit in the first dword of an IPID to flag the IPID as
+// holding weak references, so that RemRelease and RemQueryInterface between
+// an OLE container and an embedded object works as desired. Note that this
+// this is strictly a same-machine protocol, it is not part of the published
+// DCOM protocol spec.
+
+#define IPIDFLAG_WEAKREF 0x80000000
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CRemoteUnknown
+//
+// Purpose: Pass remote IUnknown calls and rundowns to the correct
+// local standard identity.
+//
+// History: 23-Feb-95 AlexMit Created
+//
+//--------------------------------------------------------------------------
+class CRemoteUnknown : public IRundown, public CPrivAlloc
+{
+public:
+ CRemoteUnknown(HRESULT &hr, IPID *pipid);
+ ~CRemoteUnknown();
+
+ // IUnknown
+ STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) ( void );
+ STDMETHOD_(ULONG,Release) ( void );
+
+ // IRemUnknown
+ STDMETHOD(RemQueryInterface) ( REFIPID ripid,
+ ULONG cRefs,
+ unsigned short cIids,
+ IID *iids,
+ REMQIRESULT **ppQIResults);
+
+ STDMETHOD(RemAddRef) ( unsigned short cInterfaceRefs,
+ REMINTERFACEREF InterfaceRefs[],
+ HRESULT *pResults );
+ STDMETHOD(RemRelease) ( unsigned short cInterfaceRefs,
+ REMINTERFACEREF InterfaceRefs[] );
+
+ // IRemUnknown2
+ STDMETHOD(RemChangeRef) ( unsigned long flags,
+ unsigned short cInterfaceRefs,
+ REMINTERFACEREF InterfaceRefs[]);
+
+ // IRundown
+ STDMETHOD(RundownOid) ( ULONG cOid,
+ OID aOid[],
+ unsigned char afOkToRundown[] );
+private:
+ HRESULT GetSecBinding( SECURITYBINDING **pSecBind );
+
+ CStdIdentity *_pStdId; // stdid for this object
+};
+
+// remote unknown pointer for MTA Apartment.
+extern CRemoteUnknown *gpMTARemoteUnknown;
+
+#endif // __REMOTEU__
diff --git a/private/ole32/com/dcomrem/resolver.cxx b/private/ole32/com/dcomrem/resolver.cxx
new file mode 100644
index 000000000..94959df81
--- /dev/null
+++ b/private/ole32/com/dcomrem/resolver.cxx
@@ -0,0 +1,2959 @@
+//+-------------------------------------------------------------------
+//
+// File: resolver.cxx
+//
+// Contents: class implementing interface to RPC OXID/PingServer
+// resolver process. Only one instance per process.
+//
+// Classes: CRpcResolver
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+#include <ole2int.h>
+#include <resolver.hxx> // CRpcResolver
+#include <service.hxx> // GetStringBindings
+#include <locks.hxx> // LOCK/UNLOCK etc
+#include <security.hxx> // GetCallAuthnLevel
+#include <marshal.hxx> // GetOXIDFromObjRef
+#include <sobjact.hxx> // CObjServer
+
+
+// global instance of OXID resolver
+CRpcResolver gResolver;
+
+// static members of CRpcResolver
+
+handle_t CRpcResolver::_hRpc = NULL; // binding handle to resolver
+PHPROCESS CRpcResolver::_ph = NULL; // context handle to resolver
+HANDLE CRpcResolver::_hThrd = NULL; // worker thread handle
+HANDLE CRpcResolver::_hEventOXID = NULL; // event for registering threads
+DWORD CRpcResolver::_dwFlags = 0; // flags
+DWORD CRpcResolver::_dwSleepPeriod = 0; // worker thread sleep period
+ULONG CRpcResolver::_cReservedOidsAvail = 0;
+ULONGLONG CRpcResolver::_OidNextReserved = 0;
+ULONG CRpcResolver::_cOidsToAdd = 0; // # OIDs to add next call
+ULONG CRpcResolver::_cOidsToRemove = 0; // # OIDs to remove next call
+ULONG CRpcResolver::_cPreRegOidsAvail = 0; // # Pre-Regist'd OIDs available
+OID CRpcResolver::_arPreRegOids[MAX_PREREGISTERED_OIDS];
+
+IDSCM * CRpcResolver::_pSCMSTA = NULL; // single-threaded scm proxy
+IDSCM * CRpcResolver::_pSCMMTA = NULL; // multi-threaded scm proxy
+LPWSTR CRpcResolver::_pwszWinstaDesktop = NULL;
+
+DWORD CRpcResolver::_dwProcessSignature = 0;
+BOOL CRpcResolver::_bDynamicSecurity = FALSE;
+
+// List of OIDs to register/ping/revoke with the resolver used
+// for lazy/batch client-side OID processing.
+
+SOIDRegistration CRpcResolver::_ClientOIDRegList = {{{NULL, NULL},},
+ 0, 0, NULL,
+ &_ClientOIDRegList,
+ &_ClientOIDRegList};
+// MID (machine ID) of local machine
+MID gLocalMid;
+
+// Ping period in milliseconds.
+DWORD giPingPeriod;
+
+// string binding to the resolver
+const WCHAR *pwszResolverBindString = L"ncalrpc:[epmapper,Security=Impersonation Dynamic False]";
+
+// String arrays for the SCM process. These are used to tell the interface
+// marshaling code the protocol and endpoint of the SCM process.
+
+#ifdef _CHICAGO_
+typedef struct tagSCMSA
+{
+ unsigned short wNumEntries; // Number of entries in array.
+ unsigned short wSecurityOffset; // Offset of security info.
+ WCHAR awszStringArray[26];
+} SCMSA;
+
+SCMSA saSCM = {26, 25, L"mswmsg:[endpoint mapper]\0" };
+
+#else
+
+typedef struct tagSCMSA
+{
+ unsigned short wNumEntries; // Number of entries in array.
+ unsigned short wSecurityOffset; // Offset of security info.
+ WCHAR awszStringArray[60];
+} SCMSA;
+
+// The last 4 characters in the string define the security bindings.
+// \0xA is RPC_C_AUTHN_WINNT
+// \0xFFFF is COM_C_AUTHZ_NONE
+// \0 is an empty principle name
+SCMSA saSCM = {57, 56, L"ncalrpc:[epmapper,Security=Impersonation Dynamic False]\0\xA\xFFFF\0"};
+#endif
+
+DWORD GetThreadWinstaDesktop( WCHAR ** ppwszWinstaDesktop );
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::Cleanup, public
+//
+// Synopsis: cleanup the resolver state. Called by ProcessUninitialze.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CRpcResolver::Cleanup()
+{
+ ASSERT_LOCK_HELD
+
+ // release our context handle
+ if (_ph != NULL)
+ {
+ RpcSmDestroyClientContext(&_ph);
+ _ph = NULL;
+ }
+
+ // release regular handle
+ if (_hRpc)
+ {
+ RpcBindingFree(&_hRpc);
+ _hRpc = NULL;
+ }
+
+ // Release the string bindings for the local object exporter.
+ if (gpsaLocalResolver)
+ {
+ MIDL_user_free(gpsaLocalResolver);
+ gpsaLocalResolver = NULL;
+ }
+
+ // empty the OIDRegList. Any SOIDRegistration records have already
+ // been deleted by the gClientRegisteredOIDs list cleanup code.
+
+ _ClientOIDRegList.pPrevList = &_ClientOIDRegList;
+ _ClientOIDRegList.pNextList = &_ClientOIDRegList;
+ _cOidsToAdd = 0;
+ _cOidsToRemove = 0;
+
+ // zero the count of pre-registered oids since all pre-registered
+ // Oids are for our old OXID value.
+
+ _cPreRegOidsAvail = 0;
+
+ // close the event handle (if any)
+ if (_hEventOXID)
+ {
+ CloseHandle(_hEventOXID);
+ _hEventOXID = NULL;
+ }
+
+ if (_pwszWinstaDesktop != NULL)
+ {
+ PrivMemFree(_pwszWinstaDesktop);
+ _pwszWinstaDesktop = NULL;
+ }
+
+ _bDynamicSecurity = FALSE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::ReleaseSCMProxy, public
+//
+// Synopsis: cleanup the resolver state. Called by ProcessUninitialze.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CRpcResolver::ReleaseSCMProxy()
+{
+ if (_pSCMSTA != NULL)
+ {
+ _pSCMSTA->Release();
+ _pSCMSTA = NULL;
+ }
+
+ if (_pSCMMTA != NULL)
+ {
+ _pSCMMTA->Release();
+ _pSCMMTA = NULL;
+ }
+
+ if (gpMTAObjServer != NULL)
+ {
+ delete gpMTAObjServer;
+ gpMTAObjServer = NULL;
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::RetryRPC, private
+//
+// Synopsis: determine if we need to retry the RPC call due to
+// the resolver being too busy.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+BOOL CRpcResolver::RetryRPC(RPC_STATUS sc)
+{
+ if (sc != RPC_S_SERVER_TOO_BUSY)
+ return FALSE;
+
+ // give the resolver time to run, then try again.
+ Sleep(100);
+
+ // CODEWORK: this is currently an infinite loop. Should we limit it?
+ return TRUE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::CheckStatus, private
+//
+// Synopsis: Checks the status code of an Rpc call, prints a debug
+// ERROR message if failed, and maps the failed status code
+// into an HRESULT.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CRpcResolver::CheckStatus(RPC_STATUS sc)
+{
+ if (sc != RPC_S_OK)
+ {
+ ComDebOut((DEB_ERROR, "OXID Resolver Failure sc:%x\n", sc));
+ sc = HRESULT_FROM_WIN32(sc);
+ }
+
+ return sc;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::GetConnection, public
+//
+// Synopsis: connects to the resolver process
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CRpcResolver::GetConnection()
+{
+ ComDebOut((DEB_OXID,"CRpcResolver::GetConnection\n"));
+
+ HRESULT hr;
+ COleTls tls(hr);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ RPC_STATUS sc = RPC_S_OK;
+
+ LOCK
+
+ if (_ph == NULL)
+ {
+ sc = RpcBindingFromStringBinding((LPWSTR)pwszResolverBindString, &_hRpc);
+ ComDebErr(sc != RPC_S_OK, "Resolver Binding Failed.\n");
+
+ if (sc == RPC_S_OK)
+ {
+ OID oidBase;
+ DWORD fConnectFlags;
+
+ do
+ {
+ // call the resolver to get a context handle
+ sc = Connect(_hRpc,
+ &_ph,
+ &giPingPeriod,
+ &gpsaLocalResolver,
+ &gLocalMid,
+ MAX_RESERVED_OIDS,
+ &oidBase,
+ &fConnectFlags,
+ (WCHAR **) &gLegacySecurity,
+ &gAuthnLevel,
+ &gImpLevel,
+ &gServerSvcListLen,
+ &gServerSvcList,
+ &gClientSvcListLen,
+ &gClientSvcList,
+ &(tls->dwApartmentID),
+ &gdwScmProcessID,
+ &_dwProcessSignature);
+ } while (RetryRPC(sc));
+
+ if (sc == RPC_S_OK)
+ {
+ gDisableDCOM = fConnectFlags & CONNECT_DISABLEDCOM;
+ if (fConnectFlags & CONNECT_MUTUALAUTH)
+ gCapabilities = EOAC_MUTUAL_AUTH;
+ else
+ gCapabilities = EOAC_NONE;
+ if (fConnectFlags & CONNECT_SECUREREF)
+ gCapabilities |= EOAC_SECURE_REFS;
+
+ // remember the reserved OID base.
+ _OidNextReserved = oidBase;
+ _cReservedOidsAvail = MAX_RESERVED_OIDS;
+
+ // Mark the security data as initialized.
+ gGotSecurityData = TRUE;
+ if (IsWOWProcess())
+ {
+ gDisableDCOM = TRUE;
+ }
+
+ // Convert the ping period from seconds to milliseconds.
+ giPingPeriod *= 1000;
+ Win4Assert(gpsaLocalResolver->wNumEntries != 0);
+
+ // compute the sleep period for the registration worker thread
+ // (which is 1/6th the ping period). The ping period may differ
+ // on debug and retail builds.
+#if DBG==1
+ // shorter time period to enable testing
+ _dwSleepPeriod = 5000;
+#else
+ _dwSleepPeriod = giPingPeriod / 6;
+#endif
+ }
+ else
+ {
+ ComDebOut((DEB_OXID, "Resolver Connect Failed sc:%x\n", sc));
+ RpcBindingFree(&_hRpc);
+ _hRpc = NULL;
+ Win4Assert(gpsaLocalResolver == NULL);
+ Win4Assert(_ph == NULL);
+ }
+ }
+ }
+
+ if ( (sc == RPC_S_OK) && (_pwszWinstaDesktop == NULL))
+ sc = SetWinstaDesktop();
+
+ UNLOCK
+
+ hr = CheckStatus(sc);
+ ComDebErr(hr != S_OK, "GetConnection Failed.\n");
+ ComDebOut((DEB_OXID,"CRpcResolver::GetConnection hr:%x\n", hr));
+ return hr;
+}
+
+//+--------------------------------------------------------------------------
+//
+// Member: CRpcResolver::ServerGetReservedMOID, public
+//
+// Synopsis: Get an OID that does not need to be pinged.
+//
+// History: 06-Nov-95 Rickhi Created.
+//
+//----------------------------------------------------------------------------
+HRESULT CRpcResolver::ServerGetReservedMOID(MOID *pmoid)
+{
+ ComDebOut((DEB_OXID,"ServerGetReservedMOID\n"));
+
+ OID oid;
+ HRESULT hr = ServerGetReservedID(&oid);
+
+ MOIDFromOIDAndMID(oid, gLocalMid, pmoid);
+
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_OXID,"ServerGetReservedMOID hr:%x moid:%I\n", pmoid));
+ return hr;
+}
+
+//+--------------------------------------------------------------------------
+//
+// Member: CRpcResolver::ServerGetReservedID, public
+//
+// Synopsis: Get an ID that does not need to be pinged.
+//
+// History: 06-Nov-95 Rickhi Created.
+//
+//----------------------------------------------------------------------------
+HRESULT CRpcResolver::ServerGetReservedID(OID *pid)
+{
+ ComDebOut((DEB_OXID,"ServerGetReservedID\n"));
+ ASSERT_LOCK_HELD
+
+ HRESULT hr = S_OK;
+
+ if (_cReservedOidsAvail == 0)
+ {
+ // go get more reserved OIDs from the ping server
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ OID OidBase;
+
+ do
+ {
+ hr = ::AllocateReservedIds(
+ _hRpc, // Rpc binding handle
+ MAX_RESERVED_OIDS, // count of OIDs requested
+ &OidBase); // place to hold base id
+
+ } while (RetryRPC(hr));
+
+ // map Rpc status if necessary
+ hr = CheckStatus(hr);
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ if (SUCCEEDED(hr))
+ {
+ // copy into global state. Dont have to worry about two threads
+ // getting more simultaneously, since these OIDs are expendable.
+
+ _cReservedOidsAvail = MAX_RESERVED_OIDS;
+ _OidNextReserved = OidBase;
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *pid = _OidNextReserved;
+ _OidNextReserved++;
+ _cReservedOidsAvail--;
+ }
+
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_OXID,"ServerGetReservedID hr:%x id:%08x %08x\n", *pid));
+ return hr;
+}
+
+//+--------------------------------------------------------------------------
+//
+// Member: CRpcResolver::ServerGetPreRegMOID, public
+//
+// Synopsis: Get an OID that has been pre-registered with the Ping
+// Server.
+//
+// History: 06-Nov-95 Rickhi Created.
+//
+// Notes: careful. The oids are dispensed in reverse order [n]-->[0], so the
+// unused ones are from [0]-->[cPreRegOidsAvail-1]. ServerCanRundownOID
+// depends on this behavior.
+//
+//----------------------------------------------------------------------------
+HRESULT CRpcResolver::ServerGetPreRegMOID(MOID *pmoid)
+{
+ ComDebOut((DEB_OXID,"ServerGetPreRegMOID\n"));
+ ASSERT_LOCK_HELD
+
+ // Get the local OXID. This cant fail because the local
+ // entry was pre-created in ChannelThreadInitialize.
+
+ OXIDEntry *pOXIDEntry;
+ HRESULT hr = gOXIDTbl.GetLocalEntry(&pOXIDEntry);
+ Win4Assert(SUCCEEDED(hr));
+
+ COleTls tls;
+ if (!(tls->dwFlags & OLETLS_APARTMENTTHREADED))
+ {
+ // in MTA Apartment, use the global list and global count.
+
+ if (_cPreRegOidsAvail == 0)
+ {
+ hr = ServerAllocMoreOIDs(&_cPreRegOidsAvail, _arPreRegOids,
+ pOXIDEntry);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ _cPreRegOidsAvail--;
+ MOIDFromOIDAndMID(_arPreRegOids[_cPreRegOidsAvail],
+ gLocalMid, pmoid);
+ }
+ }
+ else
+ {
+ // In STA Apartment, the pre-registered OIDs are kept per apartment
+ // in a list off of tls.
+
+ if (tls->cPreRegOidsAvail == 0)
+ {
+ if (tls->pPreRegOids == NULL)
+ {
+ // first time for this thread. Allocate a list to hold
+ // the pre-registered oids.
+
+ tls->pPreRegOids = (OID *)PrivMemAlloc(MAX_PREREGISTERED_OIDS *
+ sizeof(OID));
+ if (tls->pPreRegOids == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = ServerAllocMoreOIDs(&tls->cPreRegOidsAvail,
+ tls->pPreRegOids, pOXIDEntry);
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ tls->cPreRegOidsAvail--;
+ MOIDFromOIDAndMID(tls->pPreRegOids[tls->cPreRegOidsAvail],
+ gLocalMid, pmoid);
+ }
+ }
+
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_OXID,"ServerGetPreRegMOID hr:%x moid:%I\n", hr, pmoid));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::ServerCanRundownOID, public
+//
+// Synopsis: Determine if OK to rundown the specified OID.
+//
+// History: 06-Nov-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+BOOL CRpcResolver::ServerCanRundownOID(REFOID roid)
+{
+ ComDebOut((DEB_OXID,"ServerCanRundownOID poid:%x\n", &roid));
+ ASSERT_LOCK_HELD
+
+ // look in the list of unused pre-registered OIDs to see if the
+ // OID is in there. If so, we dont want to run it down yet so
+ // return FALSE, otherwise return TRUE
+
+ BOOL fRundown = TRUE; // assume not found
+
+ ULONG cPreRegOidsAvail = _cPreRegOidsAvail;
+ OID *pPreRegOids = &_arPreRegOids[0];
+
+ COleTls tls;
+
+ if (tls->dwFlags & OLETLS_APARTMENTTHREADED)
+ {
+ cPreRegOidsAvail = tls->cPreRegOidsAvail;
+ pPreRegOids = tls->pPreRegOids;
+ }
+
+ // carefull. The oids are dispensed in reverse order (ie [n]-->[0])
+ // so when checking for unused ones check in forward order
+ // [0]-->[cPreRegOidsAvail-1]
+
+ for (ULONG i=0; i<cPreRegOidsAvail; i++, pPreRegOids++)
+ {
+ if (roid == *pPreRegOids)
+ {
+ // found the oid in the list of unused ones. Dont run it down.
+ fRundown = FALSE;
+ break;
+ }
+ }
+
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_OXID,"ServerCanRundownOID fRundown:%x\n", fRundown));
+ return fRundown;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::WaitForOXIDEntry, private
+//
+// Synopsis: waits until an OXIDEntry is not busy
+//
+// History: 06-Nov-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CRpcResolver::WaitForOXIDEntry(OXIDEntry *pOXIDEntry)
+{
+ ASSERT_LOCK_HELD
+
+ if (pOXIDEntry->dwFlags & OXIDF_REGISTERINGOIDS)
+ {
+ // some other thread is busy registering OIDs for this OXID
+ // so lets wait for it to finish. This should only happen in
+ // the MTA apartment.
+ Win4Assert(IsMTAThread());
+
+ if (_hEventOXID == NULL)
+ {
+ _hEventOXID = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (_hEventOXID == NULL)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+ }
+
+ // count one more waiter
+ pOXIDEntry->cWaiters++;
+
+ do
+ {
+ // release the lock before we block so the other thread can wake
+ // us up when it returns.
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ ComDebOut((DEB_WARN,"WaitForOXIDEntry wait on hEvent:%x\n", _hEventOXID));
+ DWORD rc = WaitForSingleObject(_hEventOXID, INFINITE);
+ Win4Assert(rc == WAIT_OBJECT_0);
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ } while (pOXIDEntry->dwFlags & OXIDF_REGISTERINGOIDS);
+
+ // one less waiter
+ pOXIDEntry->cWaiters--;
+ }
+
+ // mark the entry as busy by us
+ pOXIDEntry->dwFlags |= OXIDF_REGISTERINGOIDS;
+
+ ASSERT_LOCK_HELD
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::CheckForWaiters, private
+//
+// Synopsis: wakes up any threads waiting for this OXIDEntry
+//
+// History: 06-Nov-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CRpcResolver::CheckForWaiters(OXIDEntry *pOXIDEntry)
+{
+ ASSERT_LOCK_HELD
+
+ if (pOXIDEntry->cWaiters > 0)
+ {
+ // some other thread is busy waiting for the current thread to
+ // finish registering so signal him that we are done.
+
+ Win4Assert(_hEventOXID != NULL);
+ ComDebOut((DEB_TRACE,"CheckForWaiters signalling hEvent:%x\n", _hEventOXID));
+ SetEvent(_hEventOXID);
+ }
+
+ // mark the entry as no longer busy by us
+ pOXIDEntry->dwFlags &= ~OXIDF_REGISTERINGOIDS;
+
+ ASSERT_LOCK_HELD
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::ServerAllocMoreOIDs, private
+//
+// Synopsis: register Object ID with the local ping server
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CRpcResolver::ServerAllocMoreOIDs(ULONG *pcPreRegOidsAvail,
+ OID *parPreRegOids,
+ OXIDEntry *pOXIDEntry)
+{
+ ComDebOut((DEB_OXID,"ServerAllocMoreOIDs\n"));
+ ASSERT_LOCK_HELD
+ Win4Assert(_ph != NULL);
+
+ // wait until no other threads are calling ServerAllocOIDs
+ HRESULT hr = WaitForOXIDEntry(pOXIDEntry);
+
+ if (SUCCEEDED(hr))
+ {
+ if (*pcPreRegOidsAvail == 0)
+ {
+ // need to really go get more
+ hr = ServerAllocOIDs(pOXIDEntry,
+ pcPreRegOidsAvail,
+ parPreRegOids);
+ }
+
+ // wakeup any waiters
+ CheckForWaiters(pOXIDEntry);
+ }
+
+ ComDebOut((DEB_OXID, "ServerAllocMoreOIDs hr:%x\n", hr));
+ ComDebErr(hr != S_OK, "ServerAllocMoreOIDs Failed.\n");
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::ServerAllocOIDs, private
+//
+// Synopsis: allocate Object IDs from the local ping server
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CRpcResolver::ServerAllocOIDs(OXIDEntry *pOXIDEntry,
+ ULONG *pcPreRegOidsAvail,
+ OID *parPreRegOids)
+{
+ HRESULT hr;
+
+ // make up a list of pre-registered OIDs on our stack so multiple
+ // threads executing here simultaneously are not a problem.
+
+ ULONG cOidsToAllocate = MAX_PREREGISTERED_OIDS;
+ OID arNewOidList[MAX_PREREGISTERED_OIDS];
+
+ if (!(pOXIDEntry->dwFlags & OXIDF_REGISTERED))
+ {
+ // have not yet registered the OXID, so go do that at the same time
+ // we allocate OIDs.
+
+ hr = ServerRegisterOXID(pOXIDEntry, &cOidsToAllocate, arNewOidList);
+ }
+ else
+ {
+ // just need to allocate more OIDs.
+
+ OXID oxid;
+ OXIDFromMOXID(pOXIDEntry->moxid, &oxid);
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ do
+ {
+ hr = ::ServerAllocateOIDs(
+ _hRpc, // Rpc binding handle
+ _ph, // context handle
+ &oxid, // OXID of server
+ cOidsToAllocate, // count of OIDs requested
+ arNewOidList, // array of reserved oids
+ &cOidsToAllocate);// count actually allocated
+
+ } while (RetryRPC(hr));
+
+ // map Rpc status if necessary
+ hr = CheckStatus(hr);
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // copy the newly created OIDs into the list in whatever space
+ // is still available, since some other thread could have come
+ // along and pre-registered OIDs simultaneously (in MTA apartment
+ // only). The OIDs that are not copied will be lost and
+ // eventually the resolver will run them down. This should be
+ // relatively rare.
+
+ LONG cToCopy = min(cOidsToAllocate,
+ MAX_PREREGISTERED_OIDS - *pcPreRegOidsAvail);
+
+ memcpy(parPreRegOids + *pcPreRegOidsAvail,
+ arNewOidList,
+ sizeof(OID) * cToCopy);
+
+ *pcPreRegOidsAvail += cToCopy;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::ServerRegisterOXID, public
+//
+// Synopsis: allocate an OXID and Object IDs with the local ping server
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CRpcResolver::ServerRegisterOXID(OXIDEntry *pOXIDEntry,
+ ULONG *pcOidsToAllocate,
+ OID arNewOidList[])
+{
+ ComDebOut((DEB_OXID, "ServerRegisterOXID TID:%x\n", GetCurrentThreadId()));
+ ASSERT_LOCK_HELD
+
+ // OXID has not yet been registered with the resolver, do that
+ // now along with pre-registering a bunch of OIDs.
+
+ // make sure we have the local binding and security strings
+ HRESULT hr = StartListen();
+ ComDebErr(hr != S_OK, "StartListen Failed.\n");
+
+ if (hr == S_OK)
+ {
+ OXID_INFO oxidInfo;
+ oxidInfo.dwTid = pOXIDEntry->dwTid;
+ oxidInfo.dwPid = pOXIDEntry->dwPid;
+ oxidInfo.ipidRemUnknown = pOXIDEntry->ipidRundown;
+ oxidInfo.dwAuthnHint = gAuthnLevel;
+ oxidInfo.psa = NULL;
+
+
+ DUALSTRINGARRAY *psaSB = gpsaCurrentProcess; // string bindings
+ DUALSTRINGARRAY *psaSC = gpsaSecurity; // security bindings
+
+ if (_dwFlags & ORF_STRINGSREGISTERED)
+ {
+ // already registered these once, dont need to do it again.
+ psaSB = NULL;
+ psaSC = NULL;
+ }
+
+ OXID oxid;
+
+ ComDebOut((DEB_OXID,"ServerRegisterOXID oxidInfo:%x psaSB:%x psaSC:%x\n",
+ &oxidInfo, psaSB, psaSC));
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ do
+ {
+ hr = ::ServerAllocateOXIDAndOIDs(
+ _hRpc, // Rpc binding handle
+ _ph, // context handle
+ &oxid, // OXID of server
+ IsSTAThread(), // fApartment Threaded
+ *pcOidsToAllocate, // count of OIDs requested
+ arNewOidList, // array of reserved oids
+ pcOidsToAllocate, // count actually allocated
+ &oxidInfo, // OXID_INFO to register
+ psaSB, // string bindings for process
+ psaSC); // security bindings for process
+
+ } while (RetryRPC(hr));
+
+ // map Rpc status if necessary
+ hr = CheckStatus(hr);
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ if (hr == S_OK)
+ {
+ // mark the OXID as registered with the resolver, and replace
+ // the (temporarily zero) oxid with the real one the resolver
+ // returned to us.
+
+ pOXIDEntry->dwFlags |= OXIDF_REGISTERED;
+ MOXIDFromOXIDAndMID(oxid, gLocalMid, &pOXIDEntry->moxid);
+ }
+ }
+
+ ComDebOut((DEB_OXID, "ServerRegisterOXID hr:%x\n", hr));
+ ASSERT_LOCK_HELD
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::ServerFreeOXID, public
+//
+// Synopsis: frees an OXID and associated OIDs that were pre-registered
+// with the local ping server
+//
+// History: 20-Jan-96 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CRpcResolver::ServerFreeOXID(OXIDEntry *pOXIDEntry)
+{
+ ComDebOut((DEB_OXID, "ServerFreeOXID TID:%x\n", GetCurrentThreadId()));
+ ASSERT_LOCK_HELD
+
+ if (!(pOXIDEntry->dwFlags & OXIDF_REGISTERED))
+ {
+ // OXID was never registered, just return
+ return S_OK;
+ }
+
+ // Free any pre-registered OIDs since these are registered for the
+ // current OXID. We get a new OXID if the thread is re-initialized.
+ // Set the ptr and count of Oids to de-register.
+
+ ULONG cOids;
+ OID *pOids;
+
+ COleTls tls;
+ if (!(tls->dwFlags & OLETLS_APARTMENTTHREADED))
+ {
+ pOids = _arPreRegOids;
+ cOids = _cPreRegOidsAvail;
+ _cPreRegOidsAvail = 0;
+ }
+ else
+ {
+ cOids = tls->cPreRegOidsAvail;
+ tls->cPreRegOidsAvail = 0;
+
+ pOids = tls->pPreRegOids;
+ tls->pPreRegOids = NULL;
+ }
+
+ // extract the OXID and mark the OXIDEntry as no longer registered
+ OXID oxid;
+ OXIDFromMOXID(pOXIDEntry->moxid, &oxid);
+ pOXIDEntry->dwFlags &= ~OXIDF_REGISTERED;
+
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ // call the resolver.
+ HRESULT hr;
+
+ do
+ {
+ Win4Assert(_ph != NULL);
+
+ hr = ::ServerFreeOXIDAndOIDs(
+ _hRpc, // Rpc binding handle
+ _ph, // context handle
+ oxid, // OXID of server
+ cOids, // count of OIDs to de-register
+ pOids); // ptr to OIDs to de-register
+
+ } while (RetryRPC(hr));
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // map Rpc status if necessary
+ hr = CheckStatus(hr);
+
+ if (tls->dwFlags & OLETLS_APARTMENTTHREADED)
+ {
+ // delete the space allocated for the pre-registered OIDs
+ PrivMemFree(pOids);
+ }
+
+ ComDebOut((DEB_OXID, "ServerFreeOXID hr:%x\n", hr));
+ ASSERT_LOCK_HELD
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::ClientResolveOXID, public
+//
+// Synopsis: Resolve client-side OXID and returns the OXIDEntry, AddRef'd.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CRpcResolver::ClientResolveOXID(REFOXID roxid,
+ DUALSTRINGARRAY *psaResolver,
+ OXIDEntry **ppOXIDEntry)
+{
+ ComDebOut((DEB_OXID,"ClientResolveOXID oxid:%08x %08x psa:%x\n",
+ roxid, psaResolver));
+ ASSERT_LOCK_HELD
+ RPC_STATUS sc = RPC_S_OK;
+
+ *ppOXIDEntry = NULL;
+
+ // Look for a MID entry for the resolver. if we cant find it
+ // then we know we dont have an OXIDEntry for the oxid.
+
+ DWORD dwHash;
+ MIDEntry *pMIDEntry = gMIDTbl.LookupMID(psaResolver, &dwHash);
+ if (pMIDEntry)
+ {
+ // found the MID, now look for the OXID
+ *ppOXIDEntry = gOXIDTbl.LookupOXID(roxid, pMIDEntry->mid);
+ }
+
+ if (*ppOXIDEntry == NULL)
+ {
+ // didn't find the OXIDEntry in the table so we need to resolve it.
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ MID mid;
+ OXID_INFO oxidInfo;
+ oxidInfo.psa = NULL;
+
+ do
+ {
+ Win4Assert(_ph != NULL);
+
+ sc = ::ClientResolveOXID(
+ _hRpc, // Rpc binding handle
+ _ph, // context handle
+ (OXID *)&roxid, // OXID of server
+ psaResolver, // resolver binging strings
+ IsSTAThread(), // fApartment threaded
+ // GetCallAuthnLevel(), CODEWORK: someday
+ &oxidInfo, // resolver info returned
+ &mid); // mid for the machine
+
+ } while (RetryRPC(sc));
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // map Rpc status if necessary
+ sc = CheckStatus(sc);
+
+ if (SUCCEEDED(sc))
+ {
+ // create an OXIDEntry.
+ sc = FindOrCreateOXIDEntry(roxid, oxidInfo, FOCOXID_REF,
+ psaResolver,
+ mid, pMIDEntry, ppOXIDEntry);
+
+ // free the returned string bindings
+ MIDL_user_free(oxidInfo.psa);
+ }
+ }
+
+ if (pMIDEntry)
+ {
+ DecMIDRefCnt(pMIDEntry);
+ }
+
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_OXID,"ClientResolveOXID hr:%x pOXIDEntry:%x\n",
+ sc, *ppOXIDEntry));
+ return sc;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: FillLocalOXIDInfo
+//
+// Synopsis: Fills in a OXID_INFO structure for the current apartment.
+// Used by the Drag & Drop code to register with the resolver.
+//
+// History: 20-Feb-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT FillLocalOXIDInfo(OBJREF &objref, OXID_INFO &oxidInfo)
+{
+ // extract the OXIDEntry from the objref
+ OXIDEntry *pOXIDEntry = GetOXIDFromObjRef(objref);
+ Win4Assert(pOXIDEntry);
+
+ // fill in the fields of the OXID_INFO structure.
+ oxidInfo.dwTid = pOXIDEntry->dwTid;
+ oxidInfo.dwPid = pOXIDEntry->dwPid;
+ oxidInfo.ipidRemUnknown = pOXIDEntry->ipidRundown;
+ oxidInfo.dwAuthnHint = RPC_C_AUTHN_LEVEL_NONE;
+
+ HRESULT hr = GetStringBindings(&oxidInfo.psa);
+ ComDebErr(hr != S_OK, "GetStringBindings Failed.\n");
+ return (hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: AddToList / RemoveFromList
+//
+// Synopsis: adds or removes an SOIDRegistration entry to/from
+// a doubly linked list.
+//
+// History: 30-Oct-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void AddToList(SOIDRegistration *pOIDReg, SOIDRegistration* pOIDListHead)
+{
+ pOIDReg->pPrevList = pOIDListHead;
+ pOIDListHead->pNextList->pPrevList = pOIDReg;
+ pOIDReg->pNextList = pOIDListHead->pNextList;
+ pOIDListHead->pNextList = pOIDReg;
+}
+
+void RemoveFromList(SOIDRegistration *pOIDReg)
+{
+ pOIDReg->pPrevList->pNextList = pOIDReg->pNextList;
+ pOIDReg->pNextList->pPrevList = pOIDReg->pPrevList;
+ pOIDReg->pPrevList = pOIDReg;
+ pOIDReg->pNextList = pOIDReg;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::ClientRegisterOIDWithPingServer
+//
+// Synopsis: registers an OID with the Ping Server if it has
+// not already been registered.
+//
+// History: 30-Oct-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CRpcResolver::ClientRegisterOIDWithPingServer(REFOID roid,
+ OXIDEntry *pOXIDEntry)
+{
+ ComDebOut((DEB_OXID, "ClientRegisterOIDWithPingServer poid:%x\n", &roid));
+ ASSERT_LOCK_HELD
+ AssertValid();
+ HRESULT hr = S_OK;
+
+ // make a MOID from the OID
+ MOID moid;
+ MOIDFromOIDAndMID(roid, pOXIDEntry->pMIDEntry->mid, &moid);
+
+
+ // see if this OID already has a client-side registration
+ // record created by another apartment in this process.
+
+ DWORD iHash = gClientRegisteredOIDs.Hash(moid);
+ SOIDRegistration *pOIDReg = (SOIDRegistration *)
+ gClientRegisteredOIDs.Lookup(iHash, moid);
+
+ if (pOIDReg == NULL)
+ {
+ // not yet registered with resolver, create a new entry and
+ // add it to the hash table and to the List of items to register
+ // with the Resolver.
+
+ // make sure we have a worker thread ready to do the register
+ // at some point in the future.
+ hr = EnsureWorkerThread();
+
+ if (SUCCEEDED(hr))
+ {
+ hr = E_OUTOFMEMORY;
+ pOIDReg = new SOIDRegistration;
+
+ if (pOIDReg)
+ {
+ pOIDReg->cRefs = 1;
+ pOIDReg->pPrevList = pOIDReg;
+ pOIDReg->pNextList = pOIDReg;
+ pOIDReg->pOXIDEntry = pOXIDEntry;
+
+ gClientRegisteredOIDs.Add(iHash, moid, (SUUIDHashNode *)pOIDReg);
+
+ pOIDReg->flags = ROIDF_REGISTER;
+ AddToList(pOIDReg, &_ClientOIDRegList);
+ _cOidsToAdd++;
+
+ hr = S_OK;
+ }
+ }
+ }
+ else
+ {
+ // already have a record for this OID, inc the refcnt
+ pOIDReg->cRefs++;
+
+ if (pOIDReg->cRefs == 1)
+ {
+ // re-using an entry that had a count of zero, so it must have
+ // been going to be deregistered or pinged.
+ Win4Assert((pOIDReg->flags == ROIDF_PING) ||
+ (pOIDReg->flags == ROIDF_DEREGISTER));
+
+ _cOidsToRemove--;
+
+ if (pOIDReg->flags & ROIDF_PING)
+ {
+ // was only going to be pinged, now must be added.
+ pOIDReg->flags |= ROIDF_REGISTER;
+ }
+ else
+ {
+ // was going to be unregistered, already registered so does
+ // not need to be on the registration list anymmore
+
+ Win4Assert(pOIDReg->flags & ROIDF_DEREGISTER);
+ pOIDReg->flags = 0;
+ RemoveFromList(pOIDReg);
+ }
+ }
+ }
+
+ AssertValid();
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_OXID,"ClientRegisterOIDWithPingServer pOIDReg:%x hr:%x\n",
+ pOIDReg, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::ClientDeRegisterOIDWithPingServer
+//
+// Synopsis: de-registers an OID that has previously been registered
+// with the Ping Server
+//
+// History: 30-Oct-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CRpcResolver::ClientDeRegisterOIDFromPingServer(REFMOID rmoid,
+ BOOL fMarshaled)
+{
+ ComDebOut((DEB_OXID,"ClientDeRegisterOIDWithPingServer rmoid:%I\n", &rmoid));
+ ASSERT_LOCK_HELD
+ AssertValid();
+
+ // find the OID in the hash table. it better still be there!
+
+ DWORD iHash = gClientRegisteredOIDs.Hash(rmoid);
+ SOIDRegistration *pOIDReg = (SOIDRegistration *)
+ gClientRegisteredOIDs.Lookup(iHash, rmoid);
+ Win4Assert(pOIDReg != NULL);
+ Win4Assert((pOIDReg->flags == ROIDF_REGISTER) ||
+ (pOIDReg->flags == (ROIDF_REGISTER | ROIDF_PING)) ||
+ (pOIDReg->flags == 0));
+
+ if (-- pOIDReg->cRefs == 0)
+ {
+ // this was the last registration of the OID in this process.
+
+ if (pOIDReg->flags & ROIDF_REGISTER)
+ {
+ // still on the Register list, have not yet told the Ping Server
+ // about this OID so dont have to do anything unless it was
+ // client-side marshaled.
+
+ if (fMarshaled || pOIDReg->flags & ROIDF_PING)
+ {
+ // object was marshaled by the client. Still need to tell
+ // the Ping Server to ping the OID then forget about it.
+
+ pOIDReg->flags = ROIDF_PING;
+ _cOidsToRemove++;
+
+ // make sure we have a worker thread ready to do the deregister
+ // at some point in the future. Not much we can do about an
+ // error here. If transient, then a thread will most likely
+ // be created later.
+ EnsureWorkerThread();
+ }
+ else
+ {
+ // dont need this record any longer. remove from chain
+ // and delete the record.
+
+ RemoveFromList(pOIDReg);
+ _cOidsToAdd--;
+ gClientRegisteredOIDs.Remove((SHashChain *)pOIDReg);
+ delete pOIDReg;
+ }
+ }
+ else
+ {
+ // must already be registered with the resolver. now need to
+ // deregister it so put it on the Registration list for delete.
+
+ pOIDReg->flags = ROIDF_DEREGISTER;
+ AddToList(pOIDReg, &_ClientOIDRegList);
+ _cOidsToRemove++;
+
+ // make sure we have a worker thread ready to do the deregister
+ // at some point in the future. Not much we can do about an
+ // error here. If transient, then a thread will most likely
+ // be created later.
+ EnsureWorkerThread();
+ }
+ }
+
+ AssertValid();
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_OXID,"ClientDeRegisterOIDWithPingServer pOIDReg:%x hr:%x\n",
+ pOIDReg, S_OK));
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::ClientBulkUpdateOIDWithPingServer
+//
+// Synopsis: registers/deregisters/pings any OIDs waiting to be
+// sent to the ping server.
+//
+// History: 30-Oct-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CRpcResolver::ClientBulkUpdateOIDWithPingServer(void)
+{
+ ComDebOut((DEB_OXID, "ClientBulkUpdateOIDWithPingServer\n"));
+ ASSERT_LOCK_HELD
+ AssertValid();
+ Win4Assert(_cOidsToAdd + _cOidsToRemove != 0);
+
+ // Copy the counters so we can reset them before we make the call.
+ // Allocate space for the Add, Status, and Remove lists to send to the
+ // ping server, and remember the start address so we can free the
+ // memory later. Compute the address of the other lists within the
+ // one allocated memory block.
+
+ ULONG cOidsToAdd = _cOidsToAdd;
+ ULONG cOidsToRemove = _cOidsToRemove;
+ ULONG cOxidsToRemove = gOXIDTbl.NumOxidsToRemove();
+
+ ULONG cBytesToAlloc = (cOidsToAdd * (sizeof(OXID_OID_PAIR)+sizeof(ULONG)))
+ + (cOidsToRemove * sizeof(OID_MID_PAIR))
+ + (cOxidsToRemove * sizeof(OXID_REF));
+
+ OXID_OID_PAIR *pOidsToAdd = (OXID_OID_PAIR *)PrivMemAlloc(cBytesToAlloc);
+ if (pOidsToAdd == NULL)
+ {
+ // cant allocate memory. Leave the registration lists alone for
+ // now, this may be a transient problem and we can handle the
+ // registration later (unless of course the problem persists and
+ // our object is run down!).
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_ERROR, "ClientBulkUpdate OOM\n"));
+ return E_OUTOFMEMORY;
+ }
+
+ OXID_OID_PAIR *pOidsToAddStart = pOidsToAdd;
+ LONG *pStatusOfAdds = (LONG *) (&pOidsToAdd[cOidsToAdd]);
+ OID_MID_PAIR *pOidsToRemove = (OID_MID_PAIR *)(&pStatusOfAdds[cOidsToAdd]);
+ OXID_REF *pOxidsToRemove = (OXID_REF *) (&pOidsToRemove[cOidsToRemove]);
+
+
+ // loop through each OID registration records in the list filling in
+ // the Add and Remove lists. Pinged OIDs are placed in both lists.
+
+ while (_ClientOIDRegList.pNextList != &_ClientOIDRegList)
+ {
+ // get the entry and remove it from the registration list
+ SOIDRegistration *pOIDReg = _ClientOIDRegList.pNextList;
+ RemoveFromList(pOIDReg);
+
+ // reset the state flags before we begin
+ DWORD dwFlags = pOIDReg->flags;
+ pOIDReg->flags = 0;
+
+ if (dwFlags & (ROIDF_REGISTER | ROIDF_PING))
+ {
+ // register the OID with the ping server
+ MIDFromMOXID (pOIDReg->pOXIDEntry->moxid, &pOidsToAdd->mid);
+ OXIDFromMOXID(pOIDReg->pOXIDEntry->moxid, &pOidsToAdd->oxid);
+ OIDFromMOID (pOIDReg->Node.key, &pOidsToAdd->oid);
+
+ pOidsToAdd++;
+ _cOidsToAdd--;
+ }
+
+ if (dwFlags == ROIDF_DEREGISTER || dwFlags == ROIDF_PING)
+ {
+ // deregister the OID with the ping server
+ // Node.key is the OID+MID so extract each part
+ MIDFromMOID(pOIDReg->Node.key, &pOidsToRemove->mid);
+ OIDFromMOID(pOIDReg->Node.key, &pOidsToRemove->oid);
+
+ pOidsToRemove++;
+ _cOidsToRemove--;
+
+ // dont need the entry any more since there are no more
+ // users of it. remove from hash table and delete it.
+ gClientRegisteredOIDs.Remove((SHashChain *)pOIDReg);
+ delete pOIDReg;
+ }
+ }
+
+ // Ask the OXID table to fill in the list of OXIDs to remove.
+ gOXIDTbl.GetOxidsToRemove( pOxidsToRemove, &cOxidsToRemove );
+
+ // make sure we got all the entries and that our counters work correctly.
+ Win4Assert(_cOidsToAdd == 0);
+ Win4Assert(_cOidsToRemove == 0);
+ AssertValid();
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ // reset the OidsToRemove list pointer since we mucked with it above.
+ pOidsToRemove = (OID_MID_PAIR *) (&pStatusOfAdds[cOidsToAdd]);
+
+ RPC_STATUS sc;
+
+ do
+ {
+ // call the Resolver.
+ sc = BulkUpdateOIDs(_hRpc, // Rpc binding handle
+ _ph, // context handle
+ cOidsToAdd, // #oids to add
+ pOidsToAddStart, // ptr to oids to add
+ pStatusOfAdds, // status of adds
+ cOidsToRemove, // #oids to remove
+ pOidsToRemove, // ptr to oids to remove
+ 0, 0, // ptr to oids to free
+ cOxidsToRemove, // #oxids to remove
+ pOxidsToRemove); // ptr to oxids to remove
+
+ } while (RetryRPC(sc));
+
+ // map status if necessary
+ sc = CheckStatus(sc);
+
+ // CODEWORK: reset the status flags for any OIDs not successfully added
+ // to the resolver.
+
+ // release the memory allocated above
+ PrivMemFree(pOidsToAddStart);
+
+#if DBG==1
+ LOCK
+ AssertValid();
+ UNLOCK
+#endif
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_OXID, "ClientBulkUpdateOIDWithPingServer hr:%x\n", S_OK));
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::EnsureWorkerThread
+//
+// Synopsis: Make sure there is a worker thread. Create one if
+// necessary.
+//
+// History: 06-Nov-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+HRESULT CRpcResolver::EnsureWorkerThread(void)
+{
+ ASSERT_LOCK_HELD
+ HRESULT hr = S_OK;
+
+ if (_hThrd == NULL)
+ {
+ // no worker thread currently exists, try to create one. First, make
+ // sure that we have a connection to the resolver.
+
+ hr = GetConnection();
+
+ if (SUCCEEDED(hr))
+ {
+ DWORD dwThrdId;
+ _hThrd = CreateThread(NULL, 0,
+ WorkerThreadLoop,
+ 0, 0, &dwThrdId);
+ if (_hThrd)
+ {
+ // although the handle is closed, it is NOT nulled until
+ // the worker thread exits. That is the signal that there
+ // is no more worker thread and we may need to allocate
+ // another one.
+
+ CloseHandle(_hThrd);
+ }
+ else
+ {
+ // unable to create worker thread
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ ComDebOut((DEB_ERROR,"Create Resolver worker thread hr:%x\n",hr));
+ }
+ }
+ }
+
+ ASSERT_LOCK_HELD
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::WorkerThreadLoop
+//
+// Synopsis: Worker thread for doing lazy/bulk OID registration
+// with the ping server.
+//
+// History: 06-Nov-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+DWORD _stdcall CRpcResolver::WorkerThreadLoop(void *param)
+{
+ // First thing we need to do is LoadLibrary ourselves in order to
+ // prevent our code from going away while this worker thread exists.
+ // The library will be freed when this thread exits.
+
+ HINSTANCE hInst = LoadLibrary(L"OLE32.DLL");
+
+ while (TRUE)
+ {
+ // sleep for a while to let the OIDs batch up in the registration list
+ Sleep(_dwSleepPeriod);
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ if (_cOidsToAdd == 0 && _cOidsToRemove == 0)
+ {
+ // There is no work to do. Exit this thread. If we need to
+ // register more oids later we will spin up another thread.
+
+ _hThrd = NULL;
+ UNLOCK
+ break;
+ }
+
+ ASSERT_LOCK_HELD
+ ClientBulkUpdateOIDWithPingServer();
+ ASSERT_LOCK_RELEASED
+ }
+
+ // Simultaneously free our Dll and exit our thread. This allows us to
+ // keep our Dll around incase a remote call was is progress and the
+ // worker thread is still blocked on the call, and allows us to cleanup
+ // properly when all threads are done with the code.
+
+ ASSERT_LOCK_RELEASED
+ FreeLibraryAndExitThread(hInst, 0);
+
+ // compiler wants a return value
+ return 0;
+}
+
+#if DBG==1
+//+-------------------------------------------------------------------
+//
+// Member: CRpcResolver::AssertValid
+//
+// Synopsis: validates the state of this object
+//
+// History: 30-Oct-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CRpcResolver::AssertValid(void)
+{
+ ASSERT_LOCK_HELD
+
+ Win4Assert((_cOidsToAdd & 0xf0000000) == 0x00000000);
+ Win4Assert((_cOidsToRemove & 0xf0000000) == 0x00000000);
+
+ if (_cOidsToAdd == 0 && _cOidsToRemove == 0)
+ {
+ // make sure the Reg list is empty.
+ Win4Assert(_ClientOIDRegList.pPrevList == &_ClientOIDRegList);
+ Win4Assert(_ClientOIDRegList.pNextList == &_ClientOIDRegList);
+ }
+ else
+ {
+ // make sure we have a worker thread. we cant assert because
+ // we could be OOM trying to create the thread.
+ if (_hThrd == NULL)
+ {
+ ComDebOut((DEB_WARN, "No Resolver Worked Thread\n"));
+ }
+
+ // make sure the Reg list is consistent with the counters
+ ULONG cAdd = 0;
+ ULONG cRemove = 0;
+
+ SOIDRegistration *pOIDReg = _ClientOIDRegList.pNextList;
+ while (pOIDReg != &_ClientOIDRegList)
+ {
+ // make sure the flags are valid
+ Win4Assert(pOIDReg->flags == ROIDF_REGISTER ||
+ pOIDReg->flags == ROIDF_DEREGISTER ||
+ pOIDReg->flags == ROIDF_PING ||
+ pOIDReg->flags == (ROIDF_PING | ROIDF_REGISTER));
+
+ if (pOIDReg->flags & (ROIDF_REGISTER | ROIDF_PING))
+ {
+ // OID is to be registered
+ cAdd++;
+ }
+
+ if (pOIDReg->flags == ROIDF_DEREGISTER ||
+ pOIDReg->flags == ROIDF_PING)
+ {
+ // OID is to be deregistered
+ cRemove++;
+ }
+
+ pOIDReg = pOIDReg->pNextList;
+ }
+
+ Win4Assert(cAdd == _cOidsToAdd);
+ Win4Assert(cRemove == _cOidsToRemove);
+ }
+
+ ASSERT_LOCK_HELD
+}
+#endif
+
+//+------------------------------------------------------------------------
+//
+// Function: MakeSCMProxy, public
+//
+// Synopsis: Creates an OXIDEntry and a proxy for the SCM Activation
+// Interface.
+//
+// History: 14 Apr 95 AlexMit Created
+//
+//-------------------------------------------------------------------------
+INTERNAL MakeSCMProxy(DUALSTRINGARRAY *psaSCM, REFIID riid, void **ppSCM)
+{
+ ComDebOut((DEB_OXID, "MakeSCMProxy psaSCM:%x ppSCM:%x\n", psaSCM, ppSCM));
+ Win4Assert(gdwScmProcessID != 0);
+
+ // Init out parameter
+ *ppSCM = NULL;
+
+ // Make a fake OXIDEntry for the SCM.
+ OXID_INFO oxidInfo;
+ oxidInfo.dwTid = 0;
+ oxidInfo.dwPid = gdwScmProcessID;
+ oxidInfo.ipidRemUnknown = GUID_NULL;
+ oxidInfo.psa = psaSCM;
+ oxidInfo.dwAuthnHint = RPC_C_AUTHN_LEVEL_NONE;
+
+ LOCK
+
+ OXIDEntry *pOXIDEntry;
+ MIDEntry *pMIDEntry;
+
+ HRESULT hr = GetLocalMIDEntry(&pMIDEntry); // not AddRef'd
+
+ if (SUCCEEDED(hr))
+ {
+ // Make a fake OXID for the SCM. We can use any ID that the resolver
+ // hands out as the OXID for the SCM.
+
+ OXID oxid;
+ hr = gResolver.ServerGetReservedID(&oxid);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = gOXIDTbl.AddEntry(oxid, &oxidInfo, pMIDEntry, &pOXIDEntry);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // Make an object reference for the SCM. The oid and ipid dont
+ // matter, except the OID must be machine-unique.
+
+ IPID ipidTmp;
+ UuidCreate(&ipidTmp); // fake the IPID
+
+ OBJREF objref;
+ hr = MakeFakeObjRef(objref, pOXIDEntry, ipidTmp, riid);
+
+ if (SUCCEEDED(hr))
+ {
+ // now unmarshal the objref to create a proxy to the SCM.
+ // use the internal form to reduce initialization time.
+ UNLOCK
+ hr = UnmarshalInternalObjRef(objref, ppSCM);
+
+ if (SUCCEEDED(hr) && gImpLevel != RPC_C_IMP_LEVEL_IMPERSONATE)
+ {
+ // Make sure SCM can impersonate us.
+ hr = CoSetProxyBlanket( (IUnknown *) *ppSCM,
+ RPC_C_AUTHN_WINNT,
+ RPC_C_AUTHZ_NONE, NULL,
+ RPC_C_AUTHN_LEVEL_CONNECT,
+ RPC_C_IMP_LEVEL_IMPERSONATE,
+ NULL, EOAC_NONE );
+
+ if (FAILED(hr))
+ {
+ ((IUnknown *) (*ppSCM))->Release();
+ *ppSCM = NULL;
+ }
+ }
+
+ LOCK
+ }
+
+ // release the reference to the OXIDEntry from AddEntry, since
+ // UnmarshalInternalObjRef added another one if it was successful.
+ DecOXIDRefCnt(pOXIDEntry);
+ }
+ }
+
+ UNLOCK
+ ComDebOut((DEB_OXID, "MakeSCMProxy hr:%x *ppSCM:%x\n", hr, *ppSCM));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::BindToSCMProxy
+//
+// Synopsis: Get a proxy to the SCM Activation interface.
+//
+// History: 19-May-95 Rickhi Created
+//
+// Notes: The SCM activation interface is an ORPC interface so that
+// apartment model apps can receive callbacks and do cancels
+// while activating object servers.
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::BindToSCMProxy()
+{
+ ComDebOut((DEB_ACTIVATE, "CRpcResolver::BindToSCMProxy"));
+
+ // since we are calling out on this thread, we have to ensure that the
+ // call control is set up for this thread.
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (FAILED(hr))
+ return hr;
+
+ COleStaticLock lck(gmxsOleMisc);
+
+ if (IsSTAThread())
+ {
+ if (_pSCMSTA == NULL)
+ {
+ // Make a proxy to the SCM
+ hr = MakeSCMProxy((DUALSTRINGARRAY *)&saSCM, IID_IDSCM, (void **) &_pSCMSTA);
+ }
+ }
+ else
+ {
+ if (_pSCMMTA == NULL)
+ {
+ // Make a proxy to the SCM
+ hr = MakeSCMProxy((DUALSTRINGARRAY *)&saSCM, IID_IDSCM, (void **) &_pSCMMTA);
+ }
+ }
+
+ ComDebOut((SUCCEEDED(hr) ? DEB_SCM : DEB_ERROR,
+ "CCoScm::BindToSCMProxy for IDSCM returns %x.\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::NotifyStarted
+//
+// Synopsis: Notify the SCM that a class has been started
+//
+// Arguments: [rclsid] - class started
+// [dwFlags] - whether class is multiple use or not.
+//
+// History: 19-May-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::NotifyStarted(
+ RegInput *pRegIn,
+ RegOutput **ppRegOut)
+{
+ ComDebOut((DEB_ACTIVATE, "CRpcResolver::NotifyStarted"));
+
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = GetConnection();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat;
+ WCHAR * pwszWinstaDesktop;
+
+ hr = GetWinstaDesktop( &pwszWinstaDesktop );
+
+ if ( FAILED(hr) )
+ return hr;
+
+ do
+ {
+ hr = ServerRegisterClsid(
+ _hRpc,
+ _ph,
+ pwszWinstaDesktop,
+ pRegIn,
+ ppRegOut,
+ &rpcstat );
+
+ } while (RetryRPC(rpcstat));
+
+ if ( pwszWinstaDesktop != _pwszWinstaDesktop )
+ PrivMemFree( pwszWinstaDesktop );
+
+ ComDebOut(( (hr == S_OK) ? DEB_SCM : DEB_ERROR,
+ "Class Registration returned %x", hr));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = HRESULT_FROM_WIN32(rpcstat);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::NotifyStopped
+//
+// Synopsis: Notify the SCM that the server is stopped.
+//
+// History: 19-May-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+void CRpcResolver::NotifyStopped(
+ REFCLSID rclsid,
+ DWORD dwReg)
+{
+ ComDebOut((DEB_ACTIVATE, "CRpcResolver::NotifyStopped"));
+
+ error_status_t rpcstat;
+
+ RevokeClasses revcls;
+ revcls.dwSize = 1;
+ revcls.revent[0].clsid = rclsid;
+ revcls.revent[0].dwReg = dwReg;
+
+ do
+ {
+ ServerRevokeClsid(_hRpc, _ph, &revcls, &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::GetClassObject
+//
+// Synopsis: Send a get object request to the SCM
+//
+// Arguments: [rclsid] - class id for class object
+// [dwCtrl] - type of server required
+// [ppIFDClassObj] - marshaled buffer for class object
+// [ppwszDllToLoad] - DLL name to use for server
+//
+// Returns: S_OK
+//
+// History: 20-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::GetClassObject(
+ REFCLSID rclsid,
+ DWORD dwContext,
+ IID *pIID,
+ COSERVERINFO *pServerInfo,
+ MInterfacePointer **ppIFDClassObj,
+ DWORD *pdwDllServerType,
+ WCHAR **ppwszDllToLoad)
+{
+ ComDebOut((DEB_ACTIVATE, "CRpcResolver::GetClassObject"));
+
+ HRESULT hr;
+ ACTIVATION_INFO ActivationInfo;
+ OXID OxidServer;
+ DUALSTRINGARRAY * pssaServerObjectResolverBindings;
+ OXID_INFO OxidInfo;
+ MID LocalMidOfRemote;
+ OXIDEntry * pOxidEntry;
+ LPWSTR pwszWinstaDesktop;
+
+ hr = BindToSCMProxy();
+ if (FAILED(hr))
+ return hr;
+
+ hr = GetWinstaDesktop( &pwszWinstaDesktop );
+
+ if ( FAILED(hr) )
+ return hr;
+
+ ActivationInfo.Clsid = &rclsid;
+ ActivationInfo.pServerInfo = pServerInfo;
+ ActivationInfo.pwszWinstaDesktop = pwszWinstaDesktop;
+ ActivationInfo.ClsContext = dwContext;
+ ActivationInfo.ProcessSignature = _dwProcessSignature;
+ ActivationInfo.bDynamicSecurity = _bDynamicSecurity;
+
+ pssaServerObjectResolverBindings = 0;
+ OxidInfo.psa = 0;
+ pOxidEntry = 0;
+
+ hr = GetSCM()->SCMGetClassObject(
+ &ActivationInfo,
+ pIID,
+ IsSTAThread(),
+ &OxidServer,
+ &pssaServerObjectResolverBindings,
+ &OxidInfo,
+ &LocalMidOfRemote,
+ ppIFDClassObj );
+
+ if ( pwszWinstaDesktop != _pwszWinstaDesktop )
+ PrivMemFree( pwszWinstaDesktop );
+
+ if ( FAILED(hr) || (OxidServer == 0) )
+ {
+ ComDebOut((DEB_ACTIVATE, "CRpcResolver::GetClassObject hr:%x", hr));
+ return hr;
+ }
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ hr = FindOrCreateOXIDEntry(
+ OxidServer,
+ OxidInfo,
+ FOCOXID_REF,
+ pssaServerObjectResolverBindings,
+ LocalMidOfRemote,
+ NULL,
+ &pOxidEntry );
+
+ CoTaskMemFree(OxidInfo.psa);
+ CoTaskMemFree(pssaServerObjectResolverBindings);
+
+ //
+ // CODEWORK CODEWORK CODEWORK
+ //
+ // These comments also apply to CreateInstance and GetPersistentInstance
+ // methods.
+ //
+ // Releasing the OXID and reacquiring it makes me a little
+ // nervous. The Expired list is fairly short, so if multiple guys are doing
+ // this simultaneously, the entries could get lost. I guess this is not
+ // too bad since it should be rare and the local resolver will have it
+ // anyway, but I think there is a window where the local resolver could
+ // lose it too, forcing a complete roundtrip back to the server.
+ //
+ // A better mechanism may be to pass the iid and ppunk into this method
+ // and do the unmarshal inside it. We could improve performance by calling
+ // UnmarshalObjRef instead of putting a stream wrapper around the
+ // MInterfacePointer and then calling CoUnmarshalInterface. It would avoid
+ // looking up the OXIDEntry twice, and would avoid the race where we could
+ // lose the OXIDEntry off the expired list. It would require a small
+ // change in UnmarshalObjRef to deal with the custom marshal case.
+ //
+
+ //
+ // Decrement our ref. The interface unmarshall will do a LookupOXID
+ // which will increment the count and move the OXIDEntry back to the
+ // InUse list.
+ //
+ if ( pOxidEntry )
+ DecOXIDRefCnt(pOxidEntry);
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ ComDebOut((DEB_ACTIVATE, "CRpcResolver::GetClassObject hr:%x", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::CreateInstance
+//
+// Synopsis: Send a create instance request to the SCM
+//
+// Arguments:
+//
+// Returns: S_OK
+//
+// History: 20-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::CreateInstance(
+ COSERVERINFO *pServerInfo,
+ CLSID *pClsid,
+ DWORD dwClsCtx,
+ DWORD dwCount,
+ IID *pIIDs,
+ MInterfacePointer **pRetdItfs,
+ HRESULT *pRetdHrs,
+ DWORD *pdwDllServerType,
+ OLECHAR **ppwszDllToLoad )
+
+{
+ ComDebOut((DEB_ACTIVATE, "CRpcResolver::CreateInstance"));
+
+ HRESULT hr;
+ ACTIVATION_INFO ActivationInfo;
+ OXID OxidServer;
+ DUALSTRINGARRAY * pssaServerObjectResolverBindings;
+ OXID_INFO OxidInfo;
+ MID LocalMidOfRemote;
+ OXIDEntry * pOxidEntry;
+ LPWSTR pwszWinstaDesktop;
+
+ hr = BindToSCMProxy();
+ if (FAILED(hr))
+ return hr;
+
+ hr = GetWinstaDesktop( &pwszWinstaDesktop );
+
+ if ( FAILED(hr) )
+ return hr;
+
+ ActivationInfo.Clsid = pClsid;
+ ActivationInfo.pServerInfo = pServerInfo;
+ ActivationInfo.pwszWinstaDesktop = pwszWinstaDesktop;
+ ActivationInfo.ClsContext = dwClsCtx;
+ ActivationInfo.ProcessSignature = _dwProcessSignature;
+ ActivationInfo.bDynamicSecurity = _bDynamicSecurity;
+
+ pssaServerObjectResolverBindings = 0;
+ OxidInfo.psa = 0;
+ pOxidEntry = 0;
+
+ hr = GetSCM()->SCMCreateInstance(
+ &ActivationInfo,
+ dwCount,
+ pIIDs,
+ IsSTAThread(),
+ &OxidServer,
+ &pssaServerObjectResolverBindings,
+ &OxidInfo,
+ &LocalMidOfRemote,
+ pRetdItfs,
+ pRetdHrs );
+
+ if ( pwszWinstaDesktop != _pwszWinstaDesktop )
+ PrivMemFree( pwszWinstaDesktop );
+
+ if ( FAILED(hr) || (OxidServer == 0) )
+ {
+ ComDebOut((DEB_ACTIVATE, "CRpcResolver::CreateInstance hr:%x", hr));
+ return hr;
+ }
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ hr = FindOrCreateOXIDEntry(
+ OxidServer,
+ OxidInfo,
+ FOCOXID_REF,
+ pssaServerObjectResolverBindings,
+ LocalMidOfRemote,
+ NULL,
+ &pOxidEntry );
+
+ CoTaskMemFree(OxidInfo.psa);
+ CoTaskMemFree(pssaServerObjectResolverBindings);
+
+ //
+ // Decrement our ref. The interface unmarshall will do a LookupOXID
+ // which will increment the count and move the OXIDEntry back to the
+ // InUse list.
+ //
+ if ( pOxidEntry )
+ DecOXIDRefCnt(pOxidEntry);
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ ComDebOut((DEB_ACTIVATE, "CRpcResolver::CreateInstance hr:%x", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::GetPersistentInstance
+//
+// Synopsis: Send a get object request to the SCM
+//
+//GAJGAJ - fix this comment block
+// Arguments: [rclsid] - class id for class object
+// [dwCtrl] - type of server required
+// [ppIFDClassObj] - marshaled buffer for class object
+// [ppwszDllToLoad] - DLL name to use for server
+//
+// Returns: S_OK
+//
+// History: 20-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::GetPersistentInstance(
+ COSERVERINFO * pServerInfo,
+ CLSID *pClsid,
+ DWORD dwClsCtx,
+ DWORD grfMode,
+ BOOL bFileWasOpened,
+ OLECHAR *pwszName,
+ MInterfacePointer *pstg,
+ DWORD dwCount,
+ IID *pIIDs,
+ BOOL * FoundInROT,
+ MInterfacePointer **pRetdItfs,
+ HRESULT *pRetdHrs,
+ DWORD *pdwDllServerType,
+ OLECHAR **ppwszDllToLoad )
+{
+ ComDebOut((DEB_ACTIVATE, "CRpcResolver::GetPersistentInstance"));
+
+ HRESULT hr;
+ ACTIVATION_INFO ActivationInfo;
+ OXID OxidServer;
+ DUALSTRINGARRAY * pssaServerObjectResolverBindings;
+ OXID_INFO OxidInfo;
+ MID LocalMidOfRemote;
+ OXIDEntry * pOxidEntry;
+ LPWSTR pwszWinstaDesktop;
+
+ hr = BindToSCMProxy();
+ if (FAILED(hr))
+ return hr;
+
+ hr = GetWinstaDesktop( &pwszWinstaDesktop );
+
+ if ( FAILED(hr) )
+ return hr;
+
+ ActivationInfo.Clsid = pClsid;
+ ActivationInfo.pServerInfo = pServerInfo;
+ ActivationInfo.pwszWinstaDesktop = pwszWinstaDesktop;
+ ActivationInfo.ClsContext = dwClsCtx;
+ ActivationInfo.ProcessSignature = _dwProcessSignature;
+ ActivationInfo.bDynamicSecurity = _bDynamicSecurity;
+
+ pssaServerObjectResolverBindings = 0;
+ OxidInfo.psa = 0;
+ pOxidEntry = 0;
+
+ hr = GetSCM()->SCMGetPersistentInstance(
+ &ActivationInfo,
+ pwszName,
+ pstg,
+ grfMode,
+ bFileWasOpened,
+ dwCount,
+ pIIDs,
+ IsSTAThread(),
+ &OxidServer,
+ &pssaServerObjectResolverBindings,
+ &OxidInfo,
+ &LocalMidOfRemote,
+ FoundInROT,
+ pRetdItfs,
+ pRetdHrs );
+
+ if ( pwszWinstaDesktop != _pwszWinstaDesktop )
+ PrivMemFree( pwszWinstaDesktop );
+
+ if ( FAILED(hr) || (OxidServer == 0) )
+ {
+ ComDebOut((DEB_ACTIVATE, "CRpcResolver::GetPersistentInstance hr:%x",hr));
+ return hr;
+ }
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ hr = FindOrCreateOXIDEntry(
+ OxidServer,
+ OxidInfo,
+ FOCOXID_REF,
+ pssaServerObjectResolverBindings,
+ LocalMidOfRemote,
+ NULL,
+ &pOxidEntry );
+
+ CoTaskMemFree(OxidInfo.psa);
+ CoTaskMemFree(pssaServerObjectResolverBindings);
+
+ //
+ // Decrement our ref. The interface unmarshall will do a LookupOXID
+ // which will increment the count and move the OXIDEntry back to the
+ // InUse list.
+ //
+ if ( pOxidEntry )
+ DecOXIDRefCnt(pOxidEntry);
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ ComDebOut((DEB_ACTIVATE, "CRpcResolver::GetPersistentInstance hr:%x", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::IrotRegister
+//
+// Synopsis: Register an object in the ROT
+//
+// Arguments: [pmkeqbuf] - moniker compare buffer
+// [pifdObject] - marshaled interface for object
+// [pifdObjectName] - marshaled moniker
+// [pfiletime] - file time of last change
+// [dwProcessID] -
+// [psrkRegister] - output of registration
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::IrotRegister(
+ MNKEQBUF *pmkeqbuf,
+ InterfaceData *pifdObject,
+ InterfaceData *pifdObjectName,
+ FILETIME *pfiletime,
+ DWORD dwProcessID,
+ WCHAR *pwszServerExe,
+ SCMREGKEY *psrkRegister)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = GetConnection();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+ WCHAR * pwszWinstaDesktop;
+
+ hr = GetWinstaDesktop( &pwszWinstaDesktop );
+
+ if ( FAILED(hr) )
+ return hr;
+
+ do
+ {
+ hr = ::IrotRegister(
+ _hRpc,
+ _ph,
+ pwszWinstaDesktop,
+ pmkeqbuf,
+ pifdObject,
+ pifdObjectName,
+ pfiletime,
+ dwProcessID,
+ pwszServerExe,
+ psrkRegister,
+ &rpcstat);
+ } while (RetryRPC(rpcstat));
+
+ if ( pwszWinstaDesktop != _pwszWinstaDesktop )
+ PrivMemFree( pwszWinstaDesktop );
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::IrotRevoke
+//
+// Synopsis: Call to SCM to revoke object from the ROT
+//
+// Arguments: [psrkRegister] - moniker compare buffer
+// [fServerRevoke] - whether server for object is revoking
+// [pifdObject] - where to put marshaled object
+// [pifdName] - where to put marshaled moniker
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::IrotRevoke(
+ SCMREGKEY *psrkRegister,
+ BOOL fServerRevoke,
+ InterfaceData **ppifdObject,
+ InterfaceData **ppifdName)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = GetConnection();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+
+ do
+ {
+ hr = ::IrotRevoke(
+ _hRpc,
+ psrkRegister,
+ fServerRevoke,
+ ppifdObject,
+ ppifdName,
+ &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::IrotIsRunning
+//
+// Synopsis: Call to SCM to determine if object is in the ROT
+//
+// Arguments: [pmkeqbuf] - moniker compare buffer
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::IrotIsRunning(MNKEQBUF *pmkeqbuf)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = GetConnection();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+ WCHAR * pwszWinstaDesktop;
+
+ hr = GetWinstaDesktop( &pwszWinstaDesktop );
+
+ if ( FAILED(hr) )
+ return hr;
+
+ do
+ {
+ hr = ::IrotIsRunning(
+ _hRpc,
+ _ph,
+ pwszWinstaDesktop,
+ pmkeqbuf,
+ &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+ if ( pwszWinstaDesktop != _pwszWinstaDesktop )
+ PrivMemFree( pwszWinstaDesktop );
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::IrotGetObject
+//
+// Synopsis: Call to SCM to determine if object is in the ROT
+//
+// Arguments: [dwProcessID] - process ID for object we want
+// [pmkeqbuf] - moniker compare buffer
+// [psrkRegister] - registration ID in SCM
+// [pifdObject] - marshaled interface for the object
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::IrotGetObject(
+ DWORD dwProcessID,
+ MNKEQBUF *pmkeqbuf,
+ SCMREGKEY *psrkRegister,
+ InterfaceData **pifdObject)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = GetConnection();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+ WCHAR * pwszWinstaDesktop;
+
+ hr = GetWinstaDesktop( &pwszWinstaDesktop );
+
+ if ( FAILED(hr) )
+ return hr;
+
+ do
+ {
+ hr = ::IrotGetObject(
+ _hRpc,
+ _ph,
+ pwszWinstaDesktop,
+ dwProcessID,
+ pmkeqbuf,
+ psrkRegister,
+ pifdObject,
+ &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+ if ( pwszWinstaDesktop != _pwszWinstaDesktop )
+ PrivMemFree( pwszWinstaDesktop );
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::IrotNoteChangeTime
+//
+// Synopsis: Call to SCM to set time of change for object in the ROT
+//
+// Arguments: [psrkRegister] - SCM registration ID
+// [pfiletime] - time of change
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::IrotNoteChangeTime(
+ SCMREGKEY *psrkRegister,
+ FILETIME *pfiletime)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = GetConnection();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+
+ do
+ {
+ hr = ::IrotNoteChangeTime(
+ _hRpc,
+ psrkRegister,
+ pfiletime,
+ &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::IrotGetTimeOfLastChange
+//
+// Synopsis: Call to SCM to get time changed of object in the ROT
+//
+// Arguments: [pmkeqbuf] - moniker compare buffer
+// [pfiletime] - where to put time of last change
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::IrotGetTimeOfLastChange(
+ MNKEQBUF *pmkeqbuf,
+ FILETIME *pfiletime)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = GetConnection();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+ WCHAR * pwszWinstaDesktop;
+
+ hr = GetWinstaDesktop( &pwszWinstaDesktop );
+
+ if ( FAILED(hr) )
+ return hr;
+
+ do
+ {
+ hr = ::IrotGetTimeOfLastChange(
+ _hRpc,
+ _ph,
+ pwszWinstaDesktop,
+ pmkeqbuf,
+ pfiletime,
+ &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+ if ( pwszWinstaDesktop != _pwszWinstaDesktop )
+ PrivMemFree( pwszWinstaDesktop );
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::IrotEnumRunning
+//
+// Synopsis: Call to SCM to enumerate running objects in the ROT
+//
+// Arguments: [ppMkIFList] - output pointer to array of marshaled monikers
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::IrotEnumRunning(MkInterfaceList **ppMkIFList)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = GetConnection();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+ WCHAR * pwszWinstaDesktop;
+
+ hr = GetWinstaDesktop( &pwszWinstaDesktop );
+
+ if ( FAILED(hr) )
+ return hr;
+
+ do
+ {
+ hr = ::IrotEnumRunning(
+ _hRpc,
+ _ph,
+ pwszWinstaDesktop,
+ ppMkIFList,
+ &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+ if ( pwszWinstaDesktop != _pwszWinstaDesktop )
+ PrivMemFree( pwszWinstaDesktop );
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::UpdateShrdTbls
+//
+// Synopsis: Ask the SCM to update the shared memory tables.
+//
+// Arguments: none
+//
+// History: 11-July-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::UpdateShrdTbls(void)
+{
+ ComDebOut((DEB_ACTIVATE, "CRpcResolver::UpdateShrdTbls"));
+
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = GetConnection();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat;
+
+ do
+ {
+ hr = ::UpdateShrdTbls(_hRpc, &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+
+ ComDebOut(( (hr == S_OK) ? DEB_SCM : DEB_ERROR,
+ "UpdateShrdTbls returned %x\n", hr));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ return HRESULT_FROM_WIN32(rpcstat);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::GetThreadID
+//
+// Synopsis: Get unique thread id from SCM.
+//
+// Arguments: [pThreadID] - Pointer to returned thread ID.
+//
+// History: 22-Jan-96 Rickhi Created
+//--------------------------------------------------------------------------
+void CRpcResolver::GetThreadID( DWORD * pThreadID )
+{
+ HRESULT hr;
+
+ *pThreadID = 0;
+
+ hr = GetConnection();
+ if ( FAILED(hr) )
+ return;
+
+ //
+ // If GetConnection does the initial connect to the SCM/OR then
+ // our apartment thread id, which is aliased by pThreadID, will be set.
+ //
+ if ( *pThreadID != 0 )
+ return;
+
+ error_status_t rpcstat;
+
+ do
+ {
+ ::GetThreadID( _hRpc, pThreadID, &rpcstat );
+ } while (RetryRPC(rpcstat));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::UpdateActivationSettings
+//
+// Synopsis: Tells rpcss to re-read default activation keys/values.
+// Used by OLE test team.
+//
+// Arguments: none
+//
+//--------------------------------------------------------------------------
+void CRpcResolver::UpdateActivationSettings()
+{
+ HRESULT hr;
+
+ hr = GetConnection();
+ if ( FAILED(hr) )
+ return;
+
+ error_status_t rpcstat;
+
+ do
+ {
+ ::UpdateActivationSettings( _hRpc, &rpcstat );
+ } while (RetryRPC(rpcstat));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::RegisterWindowPropInterface
+//
+// Synopsis: Register window property interface with the SCM
+//
+// Arguments:
+//
+// History: 22-Jan-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::RegisterWindowPropInterface(HWND hWnd, STDOBJREF *pStd,
+ OXID_INFO *pOxidInfo,
+ DWORD *pdwCookie)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = GetConnection();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat;
+
+ do
+ {
+ hr = ::RegisterWindowPropInterface(_hRpc, (DWORD) hWnd,
+ pStd, pOxidInfo, pdwCookie, &rpcstat);
+ } while (RetryRPC(rpcstat));
+
+ ComDebOut(( (hr == S_OK) ? DEB_SCM : DEB_ERROR,
+ "RegisterWindowPropInterface returned %x\n", hr));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ return HRESULT_FROM_WIN32(rpcstat);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::RegisterWindowPropInterface
+//
+// Synopsis: Get (and possibly Revoke) window property interface
+// registration with the SCM.
+//
+// Arguments:
+//
+// History: 22-Jan-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::GetWindowPropInterface(HWND hWnd, DWORD dwCookie, BOOL fRevoke,
+ STDOBJREF *pStd, OXID_INFO *pOxidInfo)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = GetConnection();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat;
+
+ do
+ {
+ hr = ::GetWindowPropInterface(_hRpc, (DWORD) hWnd, dwCookie, fRevoke,
+ pStd, pOxidInfo, &rpcstat);
+ } while (RetryRPC(rpcstat));
+
+ ComDebOut(( (hr == S_OK) ? DEB_SCM : DEB_ERROR,
+ "GetWindowPropInterface returned %x\n", hr));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ return HRESULT_FROM_WIN32(rpcstat);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::SetWinstaDesktop
+//
+// Purpose: Sets the default winsta\desktop string we'll use for this
+// process.
+//
+// Returns: Success code.
+//
+// History: Nov 96 DKays Created
+//
+//--------------------------------------------------------------------------
+DWORD CRpcResolver::SetWinstaDesktop()
+{
+ return GetThreadWinstaDesktop( &_pwszWinstaDesktop );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::GetWinstaDesktop
+//
+// Purpose: Gets the winsta\desktop string to use for an activation call.
+//
+// Returns: Success code.
+//
+// History: Nov 96 DKays Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRpcResolver::GetWinstaDesktop( WCHAR ** ppwszWinstaDesktop )
+{
+ DWORD Status;
+
+ *ppwszWinstaDesktop = 0;
+
+ if ( ! _bDynamicSecurity )
+ {
+ *ppwszWinstaDesktop = _pwszWinstaDesktop;
+ return S_OK;
+ }
+
+ Status = GetThreadWinstaDesktop( ppwszWinstaDesktop );
+ return HRESULT_FROM_WIN32( Status );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::GetDynamicSecurity
+//
+// Purpose: Get the dynamic security setting for the process.
+//
+// Returns: TRUE or FALSE
+//
+// History: Nov 96 DKays Created
+//
+//--------------------------------------------------------------------------
+BOOL CRpcResolver::GetDynamicSecurity()
+{
+ return _bDynamicSecurity;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcResolver::SetDynamicSecurity
+//
+// Purpose: Set the dynamic security setting for the process to TRUE.
+//
+// Returns: None.
+//
+// History: Nov 96 DKays Created
+//
+//--------------------------------------------------------------------------
+void CRpcResolver::SetDynamicSecurity()
+{
+ _bDynamicSecurity = TRUE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: GetThreadWinstaDesktop
+//
+// Purpose: Get the winsta\desktop string for the calling thread.
+//
+// Returns: Success code.
+//
+// History: Nov-96 DKays Created
+//
+//--------------------------------------------------------------------------
+DWORD GetThreadWinstaDesktop( WCHAR ** ppwszWinstaDesktop )
+{
+ HWINSTA hWinsta;
+ HDESK hDesk;
+ WCHAR wszWinsta[32];
+ WCHAR wszDesktop[32];
+ LPWSTR pwszWinsta;
+ LPWSTR pwszDesktop;
+ DWORD WinstaSize;
+ DWORD DesktopSize;
+ DWORD Length;
+ BOOL Status;
+ DWORD Result;
+
+ *ppwszWinstaDesktop = 0;
+
+ hWinsta = GetProcessWindowStation();
+
+ if ( ! hWinsta )
+ return GetLastError();
+
+ hDesk = GetThreadDesktop(GetCurrentThreadId());
+
+ if ( ! hDesk )
+ return GetLastError();
+
+ pwszWinsta = wszWinsta;
+ pwszDesktop = wszDesktop;
+
+ Length = sizeof(wszWinsta);
+
+ Status = GetUserObjectInformation(
+ hWinsta,
+ UOI_NAME,
+ pwszWinsta,
+ Length,
+ &Length );
+
+ if ( ! Status )
+ {
+ Result = GetLastError();
+ if ( Result != ERROR_INSUFFICIENT_BUFFER )
+ goto WinstaDesktopExit;
+
+ pwszWinsta = (LPWSTR)PrivMemAlloc( Length );
+ if ( ! pwszWinsta )
+ {
+ Result = ERROR_OUTOFMEMORY;
+ goto WinstaDesktopExit;
+ }
+
+ Status = GetUserObjectInformation(
+ hWinsta,
+ UOI_NAME,
+ pwszWinsta,
+ Length,
+ &Length );
+
+ if ( ! Status )
+ {
+ Result = GetLastError();
+ goto WinstaDesktopExit;
+ }
+ }
+
+ Length = sizeof(wszDesktop);
+
+ Status = GetUserObjectInformation(
+ hDesk,
+ UOI_NAME,
+ pwszDesktop,
+ Length,
+ &Length );
+
+ if ( ! Status )
+ {
+ Result = GetLastError();
+ if ( Result != ERROR_INSUFFICIENT_BUFFER )
+ goto WinstaDesktopExit;
+
+ pwszDesktop = (LPWSTR)PrivMemAlloc( Length );
+ if ( ! pwszDesktop )
+ {
+ Result = ERROR_OUTOFMEMORY;
+ goto WinstaDesktopExit;
+ }
+
+ Status = GetUserObjectInformation(
+ hDesk,
+ UOI_NAME,
+ pwszDesktop,
+ Length,
+ &Length );
+
+ if ( ! Status )
+ {
+ Result = GetLastError();
+ goto WinstaDesktopExit;
+ }
+ }
+
+ *ppwszWinstaDesktop = (WCHAR *)
+ PrivMemAlloc( (lstrlenW(pwszWinsta) + 1 + lstrlenW(pwszDesktop) + 1) * sizeof(WCHAR) );
+
+ if ( *ppwszWinstaDesktop )
+ {
+ lstrcpyW( *ppwszWinstaDesktop, pwszWinsta );
+ lstrcatW( *ppwszWinstaDesktop, L"\\" );
+ lstrcatW( *ppwszWinstaDesktop, pwszDesktop );
+ Result = S_OK;
+ }
+ else
+ {
+ Result = ERROR_OUTOFMEMORY;
+ }
+
+WinstaDesktopExit:
+
+ if ( pwszWinsta != wszWinsta )
+ PrivMemFree( pwszWinsta );
+
+ if ( pwszDesktop != wszDesktop )
+ PrivMemFree( pwszDesktop );
+
+ return Result;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: ScmGetThreadId
+//
+// Purpose: Stupid helper method so gResolver is not used in
+// com\class subdir.
+//
+//--------------------------------------------------------------------------
+void ScmGetThreadId( DWORD * pThreadID )
+{
+ gResolver.GetThreadID( pThreadID );
+}
+
+//+---------------------------------------------------------------------
+//
+// Function: UpdateDCOMSettings
+//
+// Synopsis: Calls rpcss to re-read the default activation keys/values.
+//
+//----------------------------------------------------------------------
+STDAPI_(void) UpdateDCOMSettings(void)
+{
+ gResolver.UpdateActivationSettings();
+}
+
diff --git a/private/ole32/com/dcomrem/resolver.hxx b/private/ole32/com/dcomrem/resolver.hxx
new file mode 100644
index 000000000..3232a019e
--- /dev/null
+++ b/private/ole32/com/dcomrem/resolver.hxx
@@ -0,0 +1,269 @@
+//+-------------------------------------------------------------------
+//
+// File: resolver.hxx
+//
+// Contents: class implementing interface to RPC OXID/PingServer
+// resolver and OLE SCM process.
+//
+// Classes: CRpcResolver
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+#ifndef _RESOLVER_HXX_
+#define _RESOLVER_HXX_
+
+#include <lclor.h>
+#include <ipidtbl.hxx> // gOXIDTbl
+#include <hash.hxx> // CHashTable
+#include <iface.h>
+#include <scm.h>
+#include <irot.h>
+#include <dscm.h>
+
+// Client-Side OID registration record. Created for each client-side OID
+// that needs to be registered with the Resolver. Exists so we can lazily
+// register the OID and because the resolver expects one register/deregister
+// per process, not per apartment.
+
+typedef struct tagSOIDRegistration
+{
+ SUUIDHashNode Node; // hash node
+ USHORT cRefs; // # apartments registered this OID
+ USHORT flags; // state flags
+ OXIDEntry *pOXIDEntry;// OXID of server for this OID
+ struct tagSOIDRegistration *pPrevList; // prev ptr for list
+ struct tagSOIDRegistration *pNextList; // next ptr for list
+} SOIDRegistration;
+
+
+// bit values for SOIDRegistration flags field
+typedef enum tagROIDFLAG
+{
+ ROIDF_REGISTER = 0x01, // Register OID with Ping Server
+ ROIDF_PING = 0x02, // Ping (ie Register & DeRegister) OID
+ ROIDF_DEREGISTER = 0x04 // DeRegister OID with Ping Server
+} ROIDFLAG;
+
+// number of server-side OIDs to pre-register or reserve with the resolver
+#define MAX_PREREGISTERED_OIDS 10
+#define MAX_RESERVED_OIDS 10
+
+
+// bit values for Resolver _dwFlags field
+typedef enum tagORFLAG
+{
+ ORF_STRINGSREGISTERED = 0x01 // string bindings registerd with resolver
+} ORFLAG;
+
+//+-------------------------------------------------------------------
+//
+// Class: CRpcResolver
+//
+// Purpose: Provides an interface to OXID Resolver/PingServer process.
+// There is only one instance of this class in the process.
+//
+// History: 20-Feb-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+class CRpcResolver : public CPrivAlloc
+{
+public:
+ HRESULT ServerGetPreRegMOID(MOID *pmoid);
+ HRESULT ServerGetReservedMOID(MOID *pmoid);
+ HRESULT ServerGetReservedID(OID *pid);
+ HRESULT ServerFreeOXID(OXIDEntry *pOXIDEntry);
+
+ BOOL ServerCanRundownOID(REFOID roid);
+
+ HRESULT ClientResolveOXID(REFOXID roxid,
+ DUALSTRINGARRAY *psaResolver,
+ OXIDEntry **ppOXIDEntry);
+
+ HRESULT ClientRegisterOIDWithPingServer(REFOID roid,
+ OXIDEntry *pOXIDEntry);
+
+ HRESULT ClientDeRegisterOIDFromPingServer(REFMOID roid,
+ BOOL fMarshaled);
+
+ HRESULT NotifyStarted(
+ RegInput *pRegIn,
+ RegOutput **ppRegOut);
+
+ void NotifyStopped(
+ REFCLSID rclsid,
+ DWORD dwReg);
+
+ HRESULT GetClassObject(
+ REFCLSID rclsid,
+ DWORD dwCtrl,
+ IID *pIID,
+ COSERVERINFO *pServerInfo,
+ MInterfacePointer **ppIFDClassObj,
+ DWORD *pdwDllServerType,
+ WCHAR **ppwszDllToLoad);
+
+ HRESULT CreateInstance(
+ COSERVERINFO *pServerInfo,
+ CLSID *pClsid,
+ DWORD dwClsCtx,
+ DWORD dwCount,
+ IID *pIIDs,
+ MInterfacePointer **pRetdItfs,
+ HRESULT *pRetdHrs,
+ DWORD *pdwDllServerType,
+ OLECHAR **ppwszDllToLoad );
+
+ HRESULT GetPersistentInstance(
+ COSERVERINFO * pServerInfo,
+ CLSID *pClsid,
+ DWORD dwClsCtx,
+ DWORD grfMode,
+ BOOL bFileWasOpened,
+ OLECHAR *pwszName,
+ MInterfacePointer *pstg,
+ DWORD dwCount,
+ IID *pIIDs,
+ BOOL * FoundInROT,
+ MInterfacePointer **pRetdItfs,
+ HRESULT *pRetdHrs,
+ DWORD *pdwDllServerType,
+ OLECHAR **ppwszDllToLoad );
+
+ HRESULT IrotRegister(
+ MNKEQBUF *pmkeqbuf,
+ InterfaceData *pifdObject,
+ InterfaceData *pifdObjectName,
+ FILETIME *pfiletime,
+ DWORD dwProcessID,
+ WCHAR *pwszServerExe,
+ SCMREGKEY *pdwRegister);
+
+ HRESULT IrotRevoke(
+ SCMREGKEY *psrkRegister,
+ BOOL fServerRevoke,
+ InterfaceData **pifdObject,
+ InterfaceData **pifdName);
+
+ HRESULT IrotIsRunning(
+ MNKEQBUF *pmkeqbuf);
+
+ HRESULT IrotGetObject(
+ DWORD dwProcessID,
+ MNKEQBUF *pmkeqbuf,
+ SCMREGKEY *psrkRegister,
+ InterfaceData **pifdObject);
+
+ HRESULT IrotNoteChangeTime(
+ SCMREGKEY *psrkRegister,
+ FILETIME *pfiletime);
+
+ HRESULT IrotGetTimeOfLastChange(
+ MNKEQBUF *pmkeqbuf,
+ FILETIME *pfiletime);
+
+ HRESULT IrotEnumRunning(
+ MkInterfaceList **ppMkIFList);
+
+ HRESULT UpdateShrdTbls(void);
+
+ void GetThreadID( DWORD * pThreadID );
+
+ void UpdateActivationSettings();
+
+ HRESULT RegisterWindowPropInterface(
+ HWND hWnd,
+ STDOBJREF *pStd,
+ OXID_INFO *pOxidInfo,
+ DWORD *pdwCookie);
+
+ HRESULT GetWindowPropInterface(
+ HWND hWnd,
+ DWORD dwCookie,
+ BOOL fRevoke,
+ STDOBJREF *pStd,
+ OXID_INFO *pOxidInfo);
+
+ HRESULT GetConnection();
+ HRESULT BindToSCMProxy();
+ void ReleaseSCMProxy();
+
+ DWORD SetWinstaDesktop();
+ HRESULT GetWinstaDesktop( WCHAR ** ppwszWinstaDesktop );
+
+ BOOL GetDynamicSecurity();
+ void SetDynamicSecurity();
+
+ void Cleanup();
+
+private:
+
+#if DBG==1
+ void AssertValid(void);
+#else
+ void AssertValid(void) {};
+#endif
+
+ HRESULT EnsureWorkerThread(void);
+ DWORD _stdcall WorkerThreadLoop(void *param);
+ HRESULT ClientBulkUpdateOIDWithPingServer(void);
+
+ HRESULT WaitForOXIDEntry(OXIDEntry *pEntry);
+ void CheckForWaiters(OXIDEntry *pEntry);
+ HRESULT ServerAllocMoreOIDs(ULONG *pcPreRegOidsAvail,
+ OID *parPreRegOidsAvail,
+ OXIDEntry *pEntry);
+ HRESULT ServerAllocOIDs(OXIDEntry *pEntry,
+ ULONG *pcPreRegOidsAvail,
+ OID *parPreRegOidsAvail);
+
+ HRESULT ServerRegisterOXID(OXIDEntry *pOXIDEntry,
+ ULONG *pcOidsToAllocate,
+ OID arNewOidList[]);
+
+ HRESULT CheckStatus(RPC_STATUS sc);
+ BOOL RetryRPC(RPC_STATUS sc);
+ IDSCM *GetSCM() { return (IsSTAThread()) ? _pSCMSTA : _pSCMMTA; }
+
+ static handle_t _hRpc; // rpc binding handle to resolver
+ static PHPROCESS _ph; // context handle to resolver
+ static HANDLE _hThrd; // handle of worker thread (if any)
+ static HANDLE _hEventOXID; // event for registering threads
+ static DWORD _dwFlags; // flags
+ static DWORD _dwSleepPeriod; // worker thread sleep period
+
+ // reserved sequence of OIDs (for no-ping marshals)
+ static ULONG _cReservedOidsAvail;
+ static ULONGLONG _OidNextReserved;
+
+ // pre-registered OIDs (for objects that need to be pinged)
+ static ULONG _cPreRegOidsAvail;
+ static OID _arPreRegOids[MAX_PREREGISTERED_OIDS];
+
+ static ULONG _cOidsToAdd; // # of OIDs to register with resolver
+ static ULONG _cOidsToRemove; // # of OIDs to deregister with resolver
+
+ static SOIDRegistration _ClientOIDRegList;
+
+ static IDSCM * _pSCMSTA; // Single-threaded SCM proxy
+ static IDSCM * _pSCMMTA; // Multi-threaded SCM proxy
+ static LPWSTR _pwszWinstaDesktop;
+
+ static DWORD _dwProcessSignature;
+
+ static BOOL _bDynamicSecurity;
+};
+
+extern MID gLocalMid; // MID for current machine
+extern OXID gScmOXID; // OXID for the SCM
+
+// global ptr to the one instance of this class
+extern CRpcResolver gResolver;
+
+// Ping period in milliseconds.
+extern DWORD giPingPeriod;
+
+// table of OIDs client-registered for pinging
+extern CUUIDHashTable gClientRegisteredOIDs;
+
+#endif // _RESOLVER_HXX_
diff --git a/private/ole32/com/dcomrem/riftbl.cxx b/private/ole32/com/dcomrem/riftbl.cxx
new file mode 100644
index 000000000..0f39860ef
--- /dev/null
+++ b/private/ole32/com/dcomrem/riftbl.cxx
@@ -0,0 +1,567 @@
+//+------------------------------------------------------------------------
+//
+// File: riftbl.cxx
+//
+// Contents: RIF (Registered Interfaces) Table.
+//
+// Classes: CRIFTable
+//
+// History: 12-Feb-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+#include <ole2int.h>
+#include <riftbl.hxx> // class definition
+#include <locks.hxx> // LOCK/UNLOCK
+#include <channelb.hxx> // ThreadInvoke
+
+
+// number of Registered Interface Entries per allocator page
+#define RIFS_PER_PAGE 32
+
+// global RIF table
+CRIFTable gRIFTbl;
+
+
+//+------------------------------------------------------------------------
+//
+// Vector Table: All calls on registered interfaces are dispatched through
+// this table to ThreadInvoke, which subsequently dispatches to the
+// appropriate interface stub. All calls on COM interfaces are dispatched
+// on method #0 so the table only needs to be 1 entry long.
+//
+//+------------------------------------------------------------------------
+
+const RPC_DISPATCH_FUNCTION vector[] =
+{
+ (void (_stdcall *) (struct ::_RPC_MESSAGE *)) ThreadInvoke,
+};
+
+const RPC_DISPATCH_TABLE gDispatchTable =
+{
+ sizeof(vector)/sizeof(RPC_DISPATCH_FUNCTION),
+ (RPC_DISPATCH_FUNCTION *)&vector, 0
+};
+
+
+//+------------------------------------------------------------------------
+//
+// Interface Templates. When we register an interface with the RPC runtime,
+// we allocate an structure, copy one of these templates in (depending on
+// whether we want client side or server side) and then set the interface
+// IID to the interface being registered.
+//
+// We hand-register the RemUnknown interface because we normally marshal its
+// derived verion (IRundown), yet expect calls on IRemUnknown.
+//
+//+------------------------------------------------------------------------
+
+const RPC_SERVER_INTERFACE gServerIf =
+{
+ sizeof(RPC_SERVER_INTERFACE),
+ {0x69C09EA0, 0x4A09, 0x101B, 0xAE, 0x4B, 0x08, 0x00, 0x2B, 0x34, 0x9A, 0x02,
+ {0, 0}},
+ {0x8A885D04, 0x1CEB, 0x11C9, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60,
+ {2, 0}},
+ (RPC_DISPATCH_TABLE *)&gDispatchTable, 0, 0, 0
+};
+
+const RPC_CLIENT_INTERFACE gClientIf =
+{
+ sizeof(RPC_CLIENT_INTERFACE),
+ {0x69C09EA0, 0x4A09, 0x101B, 0xAE, 0x4B, 0x08, 0x00, 0x2B, 0x34, 0x9A, 0x02,
+ {0, 0}},
+ {0x8A885D04, 0x1CEB, 0x11C9, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60,
+ {2, 0}},
+ 0, 0, 0, 0
+};
+
+const RPC_SERVER_INTERFACE gRemUnknownIf =
+{
+ sizeof(RPC_SERVER_INTERFACE),
+ {0x00000131, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ {0, 0}},
+ {0x8A885D04, 0x1CEB, 0x11C9, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60,
+ {2, 0}},
+ (RPC_DISPATCH_TABLE *)&gDispatchTable, 0, 0, 0
+};
+
+
+//+------------------------------------------------------------------------
+//
+// Registered Interface hash table buckets. This is defined as a global
+// so that we dont have to run any code to initialize the hash table.
+//
+//+------------------------------------------------------------------------
+SHashChain RIFBuckets[23] =
+{
+ {&RIFBuckets[0], &RIFBuckets[0]},
+ {&RIFBuckets[1], &RIFBuckets[1]},
+ {&RIFBuckets[2], &RIFBuckets[2]},
+ {&RIFBuckets[3], &RIFBuckets[3]},
+ {&RIFBuckets[4], &RIFBuckets[4]},
+ {&RIFBuckets[5], &RIFBuckets[5]},
+ {&RIFBuckets[6], &RIFBuckets[6]},
+ {&RIFBuckets[7], &RIFBuckets[7]},
+ {&RIFBuckets[8], &RIFBuckets[8]},
+ {&RIFBuckets[9], &RIFBuckets[9]},
+ {&RIFBuckets[10], &RIFBuckets[10]},
+ {&RIFBuckets[11], &RIFBuckets[11]},
+ {&RIFBuckets[12], &RIFBuckets[12]},
+ {&RIFBuckets[13], &RIFBuckets[13]},
+ {&RIFBuckets[14], &RIFBuckets[14]},
+ {&RIFBuckets[15], &RIFBuckets[15]},
+ {&RIFBuckets[16], &RIFBuckets[16]},
+ {&RIFBuckets[17], &RIFBuckets[17]},
+ {&RIFBuckets[18], &RIFBuckets[18]},
+ {&RIFBuckets[19], &RIFBuckets[19]},
+ {&RIFBuckets[20], &RIFBuckets[20]},
+ {&RIFBuckets[21], &RIFBuckets[21]},
+ {&RIFBuckets[22], &RIFBuckets[22]}
+};
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CleanupRIFEntry
+//
+// Synopsis: Call the RIFTable to cleanup an entry. This is called
+// by the hash table cleanup code.
+//
+// History: 12-Feb-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+void CleanupRIFEntry(SHashChain *pNode)
+{
+ gRIFTbl.UnRegisterInterface((RIFEntry *)pNode);
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CRIFTable::Initialize, public
+//
+// Synopsis: Initialize the Registered Interface Table
+//
+// History: 12-Feb-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void CRIFTable::Initialize()
+{
+ ComDebOut((DEB_CHANNEL, "CRIFTable::Initialize\n"));
+ ASSERT_LOCK_HELD
+ _HashTbl.Initialize(RIFBuckets);
+ _palloc.Initialize(sizeof(RIFEntry), RIFS_PER_PAGE);
+}
+
+//+------------------------------------------------------------------------
+//
+// Member: CRIFTable::Cleanup, public
+//
+// Synopsis: Cleanup the Registered Interface Table.
+//
+// History: 12-Feb-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+void CRIFTable::Cleanup()
+{
+ ComDebOut((DEB_CHANNEL, "CRIFTable::Cleanup\n"));
+ ASSERT_LOCK_HELD
+ _HashTbl.Cleanup(CleanupRIFEntry);
+ _palloc.Cleanup();
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRIFTable::GetClientInterfaceInfo, public
+//
+// Synopsis: returns the interface info for a given interface
+//
+// History: 12-Feb-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+RPC_CLIENT_INTERFACE *CRIFTable::GetClientInterfaceInfo(REFIID riid)
+{
+ DWORD iHash = _HashTbl.Hash(riid);
+ RIFEntry *pRIFEntry = (RIFEntry *) _HashTbl.Lookup(iHash, riid);
+ Win4Assert(pRIFEntry); // must already be registered
+ Win4Assert(pRIFEntry->pCliInterface);
+ return pRIFEntry->pCliInterface;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRIFTable::RegisterInterface, public
+//
+// Synopsis: returns the proxy stub clsid of the specified interface,
+// and adds an entry to the registered interface hash table
+// if needed.
+//
+// History: 12-Feb-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CRIFTable::RegisterInterface(REFIID riid, BOOL fServer, CLSID *pClsid)
+{
+ ComDebOut((DEB_CHANNEL, "CRIFTable::RegisterInterface riid:%I\n", &riid));
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // look for the interface in the table.
+ RIFEntry *pRIFEntry;
+ HRESULT hr = GetPSClsid(riid, pClsid, &pRIFEntry);
+
+ if (pRIFEntry)
+ {
+ if (fServer)
+ {
+ if (pRIFEntry->pSrvInterface == NULL)
+ {
+ hr = RegisterServerInterface(pRIFEntry, riid);
+ }
+ }
+ else if (pRIFEntry->pCliInterface == NULL)
+ {
+ hr = RegisterClientInterface(pRIFEntry, riid);
+ }
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_CHANNEL,
+ "CRIFTable::RegisterInterface hr:%x clsid:%I\n", hr, pClsid));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRIFTable::RegisterClientInterface, private
+//
+// Synopsis: Register with the RPC runtime a client RPC interface
+// structure for the given IID. The IID must not already
+// be registered.
+//
+// History: 12-Feb-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CRIFTable::RegisterClientInterface(RIFEntry *pRIFEntry, REFIID riid)
+{
+ ComDebOut((DEB_CHANNEL,
+ "CRIFTable::RegisterClientInterface pRIFEntry:%x\n", pRIFEntry));
+ Win4Assert(pRIFEntry->pCliInterface == NULL);
+ ASSERT_LOCK_HELD
+
+ HRESULT hr = E_OUTOFMEMORY;
+ pRIFEntry->pCliInterface = (RPC_CLIENT_INTERFACE *)
+ PrivMemAlloc(sizeof(RPC_CLIENT_INTERFACE));
+
+ if (pRIFEntry->pCliInterface != NULL)
+ {
+ memcpy(pRIFEntry->pCliInterface, &gClientIf, sizeof(gClientIf));
+ pRIFEntry->pCliInterface->InterfaceId.SyntaxGUID = riid;
+ hr = S_OK;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRIFTable::RegisterServerInterface, private
+//
+// Synopsis: Register with the RPC runtime a server RPC interface
+// structure for the given IID. The IID must not already
+// be registered
+//
+// History: 12-Feb-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CRIFTable::RegisterServerInterface(RIFEntry *pRIFEntry, REFIID riid)
+{
+ ComDebOut((DEB_CHANNEL,
+ "CRIFTable::RegisterServerInterface pRIFEntry:%x\n", pRIFEntry));
+ Win4Assert(pRIFEntry->pSrvInterface == NULL);
+ ASSERT_LOCK_HELD
+
+ HRESULT hr = E_OUTOFMEMORY;
+ pRIFEntry->pSrvInterface = (RPC_SERVER_INTERFACE *)
+ PrivMemAlloc(sizeof(RPC_SERVER_INTERFACE));
+
+ if (pRIFEntry->pSrvInterface != NULL)
+ {
+ hr = S_OK;
+ memcpy(pRIFEntry->pSrvInterface, &gServerIf, sizeof(gServerIf));
+ pRIFEntry->pSrvInterface->InterfaceId.SyntaxGUID = riid;
+
+ RPC_STATUS sc = RpcServerRegisterIfEx(pRIFEntry->pSrvInterface, NULL,
+ NULL,
+ RPC_IF_AUTOLISTEN | RPC_IF_OLE,
+ 0xffff, GetAclFn());
+ if (sc != RPC_S_OK)
+ {
+ ComDebOut((DEB_ERROR,
+ "RegisterServerInterface %I failed:0x%x.\n", &riid, sc));
+
+ PrivMemFree(pRIFEntry->pSrvInterface);
+ pRIFEntry->pSrvInterface = NULL;
+ hr = HRESULT_FROM_WIN32(sc);
+ }
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRIFTable::UnRegisterInterface
+//
+// Synopsis: UnRegister with the RPC runtime a server RPC interface
+// structure for the given IID. This is called by
+// CUUIDHashTable::Cleanup during CoUninitialize. Also
+// delete the interface structures.
+//
+// History: 12-Feb-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+void CRIFTable::UnRegisterInterface(RIFEntry *pRIFEntry)
+{
+ if (pRIFEntry->pSrvInterface)
+ {
+ // server side entry exists, unregister the interface with RPC.
+ // Note that this can result in calls being dispatched so we
+ // have to release the lock around the call.
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ RpcServerUnregisterIf(pRIFEntry->pSrvInterface, 0, 1);
+ PrivMemFree(pRIFEntry->pSrvInterface);
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ pRIFEntry->pSrvInterface = NULL;
+ }
+
+ PrivMemFree(pRIFEntry->pCliInterface);
+
+ _palloc.ReleaseEntry((PageEntry *)pRIFEntry);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRIFTable::GetPSClsid, public
+//
+// Synopsis: Finds the RIFEntry in the table for the given riid, and
+// adds an entry if one is not found. Called by CoGetPSClsid
+// and by CRIFTable::RegisterInterface.
+//
+// History: 12-Feb-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CRIFTable::GetPSClsid(REFIID riid, CLSID *pclsid, RIFEntry **ppEntry)
+{
+ ComDebOut((DEB_CHANNEL,
+ "CRIFTable::GetPSClsid riid:%I pclsid:%x\n", &riid, pclsid));
+ ASSERT_LOCK_HELD
+ HRESULT hr = S_OK;
+
+ // look for the interface in the table.
+ DWORD iHash = _HashTbl.Hash(riid);
+ RIFEntry *pRIFEntry = (RIFEntry *) _HashTbl.Lookup(iHash, riid);
+
+ if (pRIFEntry == NULL)
+ {
+ // no entry exists for this interface, add one. Dont hold
+ // the lock over a call to the SCM.
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ hr = wCoGetPSClsid(riid, pclsid);
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // now that we are holding the lock again, do another lookup incase
+ // some other thread came it while the lock was released.
+
+ pRIFEntry = (RIFEntry *) _HashTbl.Lookup(iHash, riid);
+
+ if (pRIFEntry == NULL && SUCCEEDED(hr))
+ {
+ hr = AddEntry(*pclsid, riid, iHash, &pRIFEntry);
+ }
+ }
+ else
+ {
+ // found an entry, return the clsid
+ *pclsid = pRIFEntry->psclsid;
+ }
+
+ *ppEntry = pRIFEntry;
+
+ ASSERT_LOCK_HELD
+ ComDebOut((DEB_CHANNEL, "CRIFTable::RegisterPSClsid pRIFEntry:%x\n", pRIFEntry));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRIFTable::RegisterPSClsid, public
+//
+// Synopsis: Adds an entry to the table. Used by CoRegisterPSClsid
+// so that applications can add a temporary entry that only
+// affects the local process without having to muck with
+// the system registry.
+//
+// History: 12-Feb-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CRIFTable::RegisterPSClsid(REFIID riid, REFCLSID rclsid)
+{
+ ComDebOut((DEB_CHANNEL,
+ "CRIFTable::RegisterPSClsid rclsid:%I riid:%I\n", &rclsid, &riid));
+
+ HRESULT hr = S_OK;
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // look for the interface in the table.
+ DWORD iHash = _HashTbl.Hash(riid);
+ RIFEntry *pRIFEntry = (RIFEntry *) _HashTbl.Lookup(iHash, riid);
+
+ if (pRIFEntry == NULL)
+ {
+ // no entry exists for this interface, add one.
+ hr = AddEntry(rclsid, riid, iHash, &pRIFEntry);
+ }
+ else
+ {
+ // found an entry, update the clsid
+ pRIFEntry->psclsid = rclsid;
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_CHANNEL, "CRIFTable::RegisterPSClsid hr:%x\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRIFTable::AddEntry, private
+//
+// Synopsis: allocates and entry, fills in the values, and adds it
+// to the hash table.
+//
+// History: 12-Feb-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CRIFTable::AddEntry(REFCLSID rclsid, REFIID riid,
+ DWORD iHash, RIFEntry **ppRIFEntry)
+{
+ ASSERT_LOCK_HELD
+ RIFEntry *pRIFEntry = (RIFEntry *) _palloc.AllocEntry();
+
+ if (pRIFEntry)
+ {
+ pRIFEntry->psclsid = rclsid;
+ pRIFEntry->pSrvInterface = NULL;
+ pRIFEntry->pCliInterface = NULL;
+ *ppRIFEntry = pRIFEntry;
+
+ // add to the hash table
+ _HashTbl.Add(iHash, riid, &pRIFEntry->HashNode);
+
+ ComDebOut((DEB_CHANNEL,
+ "Added RIFEntry riid:%I pRIFEntry\n", &riid, pRIFEntry));
+ return S_OK;
+ }
+
+ ASSERT_LOCK_HELD
+ return E_OUTOFMEMORY;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoRegisterPSClsid, public
+//
+// Synopsis: registers a IID->PSCLSID mapping that applies only within
+// the current process. Can be used by code downloaded over
+// a network to do custom interface marshaling without having
+// to muck with the system registry.
+//
+// Algorithm: validate the parameters then add an entry to the RIFTable.
+//
+// History: 15-Apr-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+STDAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid)
+{
+ ComDebOut((DEB_MARSHAL,
+ "CoRegisterPSClsid riid:%I rclsid:%I\n", &riid, &rclsid));
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (FAILED(hr))
+ return hr;
+
+ hr = E_INVALIDARG;
+
+ if ((&riid != NULL) && (&rclsid != NULL) &&
+ IsValidPtrIn(&riid, sizeof(riid)) &&
+ IsValidPtrIn(&rclsid, sizeof(rclsid)))
+ {
+ ASSERT_LOCK_RELEASED
+
+ hr = gRIFTbl.RegisterPSClsid(riid, rclsid);
+
+ ASSERT_LOCK_RELEASED
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoGetPSClsid, public
+//
+// Synopsis: returns the proxystub clsid associated with the specified
+// interface IID.
+//
+// Arguments: [riid] - the interface iid to lookup
+// [lpclsid] - where to return the clsid
+//
+// Returns: S_OK if successfull
+// REGDB_E_IIDNOTREG if interface is not registered.
+// REGDB_E_READREGDB if any other error
+//
+// Algorithm: First it looks in the local RIFTable for a matching IID. If
+// no entry is found, the RIFTable looks in the shared memory
+// table (NT only), and if not found and the table is FULL, it
+// will look in the registry itself.
+//
+// History: 07-Apr-94 Rickhi rewrite
+//
+//--------------------------------------------------------------------------
+STDAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
+{
+ ComDebOut((DEB_MARSHAL, "CoGetPSClsid riid:%I pclsid:%x\n", &riid, pclsid));
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (FAILED(hr))
+ return hr;
+
+ hr = E_INVALIDARG;
+
+ if ((&riid != NULL) &&
+ IsValidPtrIn(&riid, sizeof(riid)) &&
+ IsValidPtrOut(pclsid, sizeof(*pclsid)))
+ {
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ RIFEntry *pRIFEntry;
+ hr = gRIFTbl.GetPSClsid(riid, pclsid, &pRIFEntry);
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ }
+
+ return hr;
+}
diff --git a/private/ole32/com/dcomrem/riftbl.hxx b/private/ole32/com/dcomrem/riftbl.hxx
new file mode 100644
index 000000000..a0a0b7987
--- /dev/null
+++ b/private/ole32/com/dcomrem/riftbl.hxx
@@ -0,0 +1,79 @@
+//+------------------------------------------------------------------------
+//
+// File: riftbl.hxx
+//
+// Contents: RIF (registered interface) table.
+//
+// Classes: CRIFTable
+//
+// History: 12-Feb-96 Rickhi Created
+//
+//-------------------------------------------------------------------------
+#ifndef _RIFTBL_HXX_
+#define _RIFTBL_HXX_
+
+#include <pgalloc.hxx> // CPageAllocator
+#include <hash.hxx> // CUUIDHashTable
+
+
+//+------------------------------------------------------------------------
+//
+// Struct: RIFEntry - Registered Interface Entry
+//
+// This structure defines an Entry in the RIF table. There is one RIF
+// table for the entire process. There is one RIFEntry per interface
+// the current process is using (client side or server side).
+//
+//-------------------------------------------------------------------------
+typedef struct tagRIFEntry
+{
+ SUUIDHashNode HashNode; // hash chain and key (IID)
+ CLSID psclsid; // proxy stub clsid
+ RPC_SERVER_INTERFACE *pSrvInterface; // ptr to server interface
+ RPC_CLIENT_INTERFACE *pCliInterface; // ptr tp client interface
+} RIFEntry;
+
+
+//+------------------------------------------------------------------------
+//
+// class: CRIFTable
+//
+// Synopsis: Hash table of registered interfaces.
+//
+// History: 12-Feb-96 Rickhi Created
+//
+// Notes: Entries are kept in a hash table keyed by the IID. Entries
+// are allocated via the page-based allocator. There is one
+// global instance of this table per process (gRIFTbl).
+//
+//-------------------------------------------------------------------------
+class CRIFTable
+{
+public:
+ void Initialize();
+ void Cleanup();
+
+ HRESULT RegisterInterface(REFIID riid, BOOL fServer, CLSID *pClsid);
+ RPC_CLIENT_INTERFACE *GetClientInterfaceInfo(REFIID riid);
+
+ HRESULT RegisterPSClsid(REFIID riid, REFCLSID rclsid);
+ HRESULT GetPSClsid(REFIID riid, CLSID *pclsid, RIFEntry **ppEntry);
+
+ void UnRegisterInterface(RIFEntry *pRIFEntry);
+
+private:
+
+ HRESULT RegisterClientInterface(RIFEntry *pRIFEntry, REFIID riid);
+ HRESULT RegisterServerInterface(RIFEntry *pRIFEntry, REFIID riid);
+ HRESULT AddEntry(REFCLSID rclsid, REFIID riid, DWORD iHash, RIFEntry **ppRIFEntry);
+
+ CUUIDHashTable _HashTbl; // interface lookup hash table
+ CPageAllocator _palloc; // page allocator
+};
+
+
+// global externs
+extern CRIFTable gRIFTbl;
+extern const RPC_SERVER_INTERFACE gRemUnknownIf;
+
+#endif // _RIFTBL_HXX_
diff --git a/private/ole32/com/dcomrem/rpcspy.hxx b/private/ole32/com/dcomrem/rpcspy.hxx
new file mode 100644
index 000000000..3cf829ec7
--- /dev/null
+++ b/private/ole32/com/dcomrem/rpcspy.hxx
@@ -0,0 +1,204 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: rpcspy.hxx
+//
+// Contents: A primitive rpc spy with output to debug terminal
+//
+// Classes:
+//
+// Functions:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+// Note: Can be turned on via CairOle InfoLelevel mask 0x08000000
+//
+//----------------------------------------------------------------------------
+
+#ifndef _RPCSPY_HXX_
+#define _RPCSPY_HXX_
+
+#if DBG==1
+//
+// switch on to trace rpc calls
+// by setting CairoleInfoLevel = DEB_USER1;
+//
+//
+#define NESTING_SPACES 32
+#define SPACES_PER_LEVEL 2
+static char achSpaces[NESTING_SPACES+1] = " ";
+WORD wlevel = 0;
+char tabs[128];
+
+//+---------------------------------------------------------------------------
+//
+// Method: PushLevel
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void PushLevel()
+{
+ wlevel++;
+}
+//+---------------------------------------------------------------------------
+//
+// Method: PopLevel
+//
+// Synopsis:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void PopLevel()
+{
+ if (wlevel)
+ wlevel--;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: NestingSpaces
+//
+// Synopsis:
+//
+// Arguments: [psz] --
+//
+// Returns:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void NestingSpaces(char *psz)
+{
+ int iSpaces, i;
+
+ iSpaces = wlevel * SPACES_PER_LEVEL;
+
+ while (iSpaces > 0)
+ {
+ i = min(iSpaces, NESTING_SPACES);
+ memcpy(psz, achSpaces, i);
+ psz += i;
+ *psz = 0;
+ iSpaces -= i;
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: GetTabs
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+LPSTR GetTabs()
+{
+ static char ach[256];
+ char *psz;
+
+ sprintf(ach, "%2d:", wlevel);
+ psz = ach+strlen(ach);
+
+ if (sizeof(ach)/SPACES_PER_LEVEL <= wlevel)
+ {
+ strcpy(psz, "...");
+ }
+ else
+ {
+ NestingSpaces(psz);
+ }
+ return ach;
+}
+
+
+typedef enum
+{
+ CALLIN_BEGIN =1,
+ CALLIN_TRACE,
+ CALLIN_ERROR,
+ CALLIN_END,
+ CALLOUT_BEGIN,
+ CALLOUT_TRACE,
+ CALLOUT_ERROR,
+ CALLOUT_END
+} RPCSPYMODE;
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: RpcSpyOutput
+//
+// Synopsis:
+//
+// Arguments: [mode] -- in or out call
+// [iid] -- interface id
+// [dwMethod] -- called method
+// [hres] -- hresult of finished call
+//
+// Returns:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void RpcSpyOutput(RPCSPYMODE mode , REFIID iid, DWORD dwMethod, HRESULT hres)
+{
+ switch (mode)
+ {
+ case CALLIN_BEGIN:
+ CairoleDebugOut((DEB_RPCSPY,"%s <<< %lx, %d \n",GetTabs(), iid.Data1, dwMethod));
+ PushLevel();
+ break;
+ case CALLIN_TRACE:
+ break;
+ case CALLIN_ERROR:
+ break;
+ case CALLIN_END:
+ PopLevel();
+ CairoleDebugOut((DEB_RPCSPY,"%s === %lx, %d (%lx) \n",GetTabs(), iid.Data1, dwMethod, hres));
+ break;
+ case CALLOUT_BEGIN:
+ CairoleDebugOut((DEB_RPCSPY,"%s >>> %lx, %d \n",GetTabs(), iid.Data1, dwMethod));
+ PushLevel();
+ break;
+ case CALLOUT_TRACE:
+ break;
+ case CALLOUT_ERROR:
+ CairoleDebugOut((DEB_RPCSPY,"%s !!! %lx, %d, error:%lx \n",GetTabs(), iid.Data1, dwMethod, hres));
+ break;
+ case CALLOUT_END:
+ PopLevel();
+ CairoleDebugOut((DEB_RPCSPY,"%s +++ %lx, %d (%lx) \n",GetTabs(), iid.Data1, dwMethod, hres));
+ break;
+ }
+}
+
+#define RpcSpy(x) RpcSpyOutput x
+
+#else
+
+#define RpcSpy(x)
+
+#endif // DBG==1
+
+
+#endif // _RPCSPY_HXX_
diff --git a/private/ole32/com/dcomrem/security.cxx b/private/ole32/com/dcomrem/security.cxx
new file mode 100644
index 000000000..de7f7e024
--- /dev/null
+++ b/private/ole32/com/dcomrem/security.cxx
@@ -0,0 +1,3060 @@
+//+-------------------------------------------------------------------
+//
+// File: security.cxx
+//
+// Copyright (c) 1996-1996, Microsoft Corp. All rights reserved.
+//
+// Contents: Classes for channel security
+//
+// Classes: CClientSecurity, CServerSecurity
+//
+// History: 11 Oct 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <locks.hxx>
+#include <security.hxx>
+#include <channelb.hxx>
+#include <ipidtbl.hxx>
+#include <resolver.hxx>
+#include <service.hxx>
+#include <oleext.h>
+#include <stream.hxx>
+
+#ifdef _CHICAGO_
+#include <apiutil.h>
+#include <wksta.h>
+#endif
+
+#ifdef DCOM_SECURITY
+/**********************************************************************/
+// Definitions.
+
+// Versions of the permissions in the registry.
+const WORD COM_PERMISSION_SECDESC = 1;
+const WORD COM_PERMISSION_ACCCTRL = 2;
+
+// Guess length of user name.
+const DWORD SIZEOF_NAME = 80;
+
+// This leaves space for 8 sub authorities. Currently NT only uses 6 and
+// Cairo uses 7.
+const DWORD SIZEOF_SID = 44;
+
+// This leaves space for 2 access allowed ACEs in the ACL.
+const DWORD SIZEOF_ACL = sizeof(ACL) + 2 * sizeof(ACCESS_ALLOWED_ACE) +
+ 2 * SIZEOF_SID;
+
+const DWORD SIZEOF_TOKEN_USER = sizeof(TOKEN_USER) + SIZEOF_SID;
+
+const SID LOCAL_SYSTEM_SID = {SID_REVISION, 1, {0,0,0,0,0,5},
+ SECURITY_LOCAL_SYSTEM_RID };
+
+const DWORD NUM_SEC_PKG = 8;
+
+const DWORD ACCESS_CACHE_LEN = 5;
+
+const DWORD VALID_INIT_FLAGS = EOAC_SECURE_REFS | EOAC_MUTUAL_AUTH |
+ EOAC_ACCESS_CONTROL | EOAC_APPID | EOAC_DYNAMIC;
+
+// Remove this for NT 5.0 when we link to oleext.lib
+const IID IID_IAccessControl = {0xEEDD23E0,0x8410,0x11CE,{0xA1,0xC3,0x08,0x00,0x2B,0x2B,0x8D,0x8F}};
+
+// Stores results of AccessCheck.
+typedef struct
+{
+ BOOL fAccess;
+ DWORD lHash;
+ SID sid;
+} SAccessCache;
+
+// Header in access permission key.
+typedef struct
+{
+ WORD wVersion;
+ WORD wPad;
+ GUID gClass;
+} SPermissionHeader;
+
+#ifdef _CHICAGO_
+typedef unsigned
+ (*NetWkstaGetInfoFn) ( const char FAR * pszServer,
+ short sLevel,
+ char FAR * pbBuffer,
+ unsigned short cbBuffer,
+ unsigned short FAR * pcbTotalAvail );
+#endif
+
+/**********************************************************************/
+// Externals.
+
+EXTERN_C const IID IID_IObjServer;
+
+
+/**********************************************************************/
+// Prototypes.
+void CacheAccess ( SID *pSid, BOOL fAccess );
+BOOL CacheAccessCheck ( SID *pSid, BOOL *pAccess );
+HRESULT CopySecDesc ( SECURITY_DESCRIPTOR *pOrig,
+ SECURITY_DESCRIPTOR **pCopy );
+HRESULT FixupAccessControl ( SECURITY_DESCRIPTOR **pSD, DWORD cbSD );
+HRESULT FixupSecurityDescriptor( SECURITY_DESCRIPTOR **pSD, DWORD cbSD );
+HRESULT GetLegacySecDesc ( SECURITY_DESCRIPTOR **, DWORD * );
+HRESULT GetRegistrySecDesc ( HKEY, WCHAR *pValue,
+ SECURITY_DESCRIPTOR **pSD, DWORD * );
+DWORD HashSid ( SID * );
+BOOL IsLocalAuthnService ( USHORT wAuthnService );
+HRESULT MakeSecDesc ( SECURITY_DESCRIPTOR **, DWORD * );
+HRESULT DefaultAuthnServices ( void );
+HRESULT RegisterAuthnServices ( DWORD cbSvc, SOLE_AUTHENTICATION_SERVICE * );
+
+#ifndef _CHICAGO_
+HRESULT LookupPrincName ( WCHAR ** );
+#else
+HRESULT LookupPrincName(
+ USHORT *pwAuthnServices,
+ ULONG cAuthnServices,
+ WCHAR **pPrincName
+ );
+#endif // _CHICAGO_
+
+/**********************************************************************/
+// Globals.
+
+// These variables hold the default authentication information.
+DWORD gAuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
+DWORD gImpLevel = RPC_C_IMP_LEVEL_IDENTIFY;
+DWORD gCapabilities = EOAC_NONE;
+SECURITYBINDING *gLegacySecurity = NULL;
+
+// These variables define a list of security providers OLE clients can
+// use and a list OLE servers can use.
+USHORT *gClientSvcList = NULL;
+DWORD gClientSvcListLen = 0;
+USHORT *gServerSvcList = NULL;
+DWORD gServerSvcListLen = 0;
+
+// gDisableDCOM is read from the registry by CRpcResolver::GetConnection.
+// If TRUE, all machine remote calls will be failed. It is set TRUE in WOW.
+BOOL gDisableDCOM = FALSE;
+
+// Set TRUE when CRpcResolver::GetConnection initializes the previous globals.
+BOOL gGotSecurityData = FALSE;
+
+// The security descriptor to check when new connections are established.
+// gAccessControl and gSecDesc will not both be nonNULL at the same time.
+IAccessControl *gAccessControl = NULL;
+SECURITY_DESCRIPTOR *gSecDesc = NULL;
+
+// The security string array. If gDefaultService is TRUE, compute the
+// security string array the first time a remote protocol sequence is
+// registered.
+DUALSTRINGARRAY *gpsaSecurity = NULL;
+BOOL gDefaultService = FALSE;
+
+// The security descriptor to check in RundownOID.
+SECURITY_DESCRIPTOR *gRundownSD = NULL;
+
+// Don't map any of the generic bits to COM_RIGHTS_EXECUTE or any other bit.
+GENERIC_MAPPING gMap = { 0, 0, 0, 0 };
+PRIVILEGE_SET gPriv = { 1, 0 };
+
+// Cache of results of calls to AccessCheck.
+SAccessCache *gAccessCache[ACCESS_CACHE_LEN] = {NULL, NULL, NULL, NULL, NULL};
+DWORD gMostRecentAccess = 0;
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CacheAccess
+//
+// Synopsis: Store the results of the access check in the cache.
+//
+//--------------------------------------------------------------------
+void CacheAccess( SID *pSid, BOOL fAccess )
+{
+ SAccessCache *pNew;
+ DWORD cbSid;
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // Allocate a new record.
+ cbSid = GetLengthSid( pSid );
+ pNew = (SAccessCache *) PrivMemAlloc( sizeof(SAccessCache) + cbSid -
+ sizeof(SID) );
+
+ // Initialize the record.
+ if (pNew != NULL)
+ {
+ pNew->fAccess = fAccess;
+ pNew->lHash = HashSid( pSid );
+ memcpy( &pNew->sid, pSid, cbSid );
+
+ // Free the old record and insert the new.
+ gMostRecentAccess += 1;
+ if (gMostRecentAccess >= ACCESS_CACHE_LEN)
+ gMostRecentAccess = 0;
+ PrivMemFree( gAccessCache[gMostRecentAccess] );
+ gAccessCache[gMostRecentAccess] = pNew;
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CacheAccessCheck
+//
+// Synopsis: Look for the specified SID in the cache. If found,
+// return the results of the cached access check.
+//
+//--------------------------------------------------------------------
+BOOL CacheAccessCheck( SID *pSid, BOOL *pAccess )
+{
+ DWORD i;
+ DWORD lHash = HashSid( pSid );
+ DWORD j;
+ BOOL fFound = FALSE;
+ SAccessCache *pSwap;
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // Look for the SID.
+ j = gMostRecentAccess;
+ for (i = 0; i < ACCESS_CACHE_LEN; i++)
+ {
+ if (gAccessCache[j] != NULL &&
+ gAccessCache[j]->lHash == lHash &&
+ EqualSid( pSid, &gAccessCache[j]->sid ))
+ {
+ // Move this entry to the head.
+ fFound = TRUE;
+ *pAccess = gAccessCache[j]->fAccess;
+ pSwap = gAccessCache[gMostRecentAccess];
+ gAccessCache[gMostRecentAccess] = gAccessCache[j];
+ gAccessCache[j] = pSwap;
+ break;
+ }
+ if (j == 0)
+ j = ACCESS_CACHE_LEN - 1;
+ else
+ j -= 1;
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ return fFound;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CClientSecurity::CopyProxy, public
+//
+// Synopsis: Create a new IPID entry for the specified IID.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CClientSecurity::CopyProxy( IUnknown *pProxy, IUnknown **ppCopy )
+{
+ // Make sure TLS is initialized on this thread.
+ HRESULT hr;
+ COleTls tls(hr);
+ if (FAILED(hr))
+ return hr;
+
+ // Ask the marshaller to copy the proxy.
+ return _pStdId->PrivateCopyProxy( pProxy, ppCopy );
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CClientSecurity::QueryBlanket, public
+//
+// Synopsis: Get the binding handle for a proxy. Query RPC for the
+// authentication information for that handle.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CClientSecurity::QueryBlanket(
+ IUnknown *pProxy,
+ DWORD *pAuthnSvc,
+ DWORD *pAuthzSvc,
+ OLECHAR **pServerPrincName,
+ DWORD *pAuthnLevel,
+ DWORD *pImpLevel,
+ void **pAuthInfo,
+ DWORD *pCapabilities )
+{
+ HRESULT hr;
+ IPIDEntry *pIpid;
+ RPC_STATUS sc;
+ DWORD iLen;
+ OLECHAR *pCopy;
+ handle_t hHandle;
+ IRemUnknown *pRemUnk = NULL;
+ RPC_SECURITY_QOS sQos;
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // Initialize all out parameters to default values.
+ if (pServerPrincName != NULL)
+ *pServerPrincName = NULL;
+ if (pAuthnLevel != NULL)
+ *pAuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
+ if (pImpLevel != NULL)
+ *pImpLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
+ if (pAuthnSvc != NULL)
+ *pAuthnSvc = RPC_C_AUTHN_WINNT;
+ if (pAuthInfo != NULL)
+ *pAuthInfo = NULL;
+ if (pAuthzSvc != NULL)
+ *pAuthzSvc = RPC_C_AUTHZ_NONE;
+ if (pCapabilities != NULL)
+ *pCapabilities = EOAC_NONE;
+
+ // For IUnknown just call QueryBlanket on the IRemUnknown of
+ // the IPID or the OXID.
+ if (_pStdId->GetCtrlUnk() == pProxy)
+ {
+ pIpid = _pStdId->GetConnectedIPID();
+ hr = _pStdId->GetSecureRemUnk( &pRemUnk, pIpid->pOXIDEntry );
+ if (pRemUnk != NULL)
+ {
+ UNLOCK
+ hr = CoQueryProxyBlanket( pRemUnk, pAuthnSvc, pAuthzSvc,
+ pServerPrincName, pAuthnLevel,
+ pImpLevel, pAuthInfo, pCapabilities );
+ LOCK
+ }
+ }
+
+ // Find the right IPID entry.
+ else
+ {
+ hr = _pStdId->FindIPIDEntryByInterface( pProxy, &pIpid );
+ if (SUCCEEDED(hr))
+ {
+ // Disallow server entries.
+ if (pIpid->dwFlags & IPIDF_SERVERENTRY)
+ hr = E_INVALIDARG;
+
+ // No security for disconnected proxies.
+ else if (pIpid->dwFlags & IPIDF_DISCONNECTED)
+ hr = RPC_E_DISCONNECTED;
+
+ // If it is local, use the default values for everything but the
+ // impersonation level.
+ else if (pIpid->pChnl->ProcessLocal())
+ {
+ if (pImpLevel != NULL)
+ *pImpLevel = pIpid->pChnl->GetImpLevel();
+ }
+
+ // Otherwise ask RPC.
+ else
+ {
+ hr = pIpid->pChnl->GetHandle( &hHandle );
+
+ if (SUCCEEDED(hr))
+ {
+ sc = RpcBindingInqAuthInfoExW( hHandle,
+ pServerPrincName, pAuthnLevel,
+ pAuthnSvc, pAuthInfo,
+ pAuthzSvc,
+ RPC_C_SECURITY_QOS_VERSION,
+ &sQos );
+
+ // RPC sometimes sets out parameters on error.
+ if (sc != RPC_S_OK)
+ {
+ if (pServerPrincName != NULL)
+ *pServerPrincName = NULL;
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, sc );
+ }
+ else
+ {
+ // Return the impersonation level and capabilities.
+ if (pImpLevel != NULL)
+ *pImpLevel = sQos.ImpersonationType;
+ if (pCapabilities != NULL)
+ if (sQos.Capabilities & RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH)
+ *pCapabilities = EOAC_MUTUAL_AUTH;
+ else
+ *pCapabilities = EOAC_NONE;
+
+ // Reallocate the principle name using the OLE memory allocator.
+ if (pServerPrincName != NULL && *pServerPrincName != NULL)
+ {
+ iLen = lstrlenW( *pServerPrincName ) + 1;
+ pCopy = (OLECHAR *) CoTaskMemAlloc( iLen * sizeof(OLECHAR) );
+ if (pCopy != NULL)
+ memcpy( pCopy, *pServerPrincName, iLen*sizeof(USHORT) );
+ else
+ hr = E_OUTOFMEMORY;
+ RpcStringFree( pServerPrincName );
+ *pServerPrincName = pCopy;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CClientSecurity::SetBlanket, public
+//
+// Synopsis: Get the binding handle for a proxy. Call RPC to set the
+// authentication information for that handle.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CClientSecurity::SetBlanket(
+ IUnknown *pProxy,
+ DWORD AuthnSvc,
+ DWORD AuthzSvc,
+ OLECHAR *pServerPrincName,
+ DWORD AuthnLevel,
+ DWORD ImpLevel,
+ void *pAuthInfo,
+ DWORD Capabilities )
+{
+ HRESULT hr;
+ IPIDEntry *pIpid;
+ RPC_STATUS sc;
+ BOOL fSuccess;
+ HANDLE hToken = NULL;
+ HANDLE hProcess;
+ handle_t hHandle;
+ IRemUnknown *pRemUnk;
+ IRemUnknown *pSecureRemUnk = NULL;
+ RPC_SECURITY_QOS sQos;
+ SECURITY_IMPERSONATION_LEVEL eDuplicate;
+ DWORD dwOpen;
+
+ ASSERT_LOCK_RELEASED
+
+ // IUnknown is special. Set the security on IRemUnknown instead.
+ if (_pStdId->GetCtrlUnk() == pProxy)
+ {
+ // Make sure the identity has its own copy of the OXID's
+ // IRemUnknown.
+ if (!_pStdId->CheckSecureRemUnk())
+ {
+ // This will get the remote unknown from the OXID.
+ LOCK
+ pIpid = _pStdId->GetConnectedIPID();
+ hr = _pStdId->GetSecureRemUnk( &pRemUnk, pIpid->pOXIDEntry );
+ if (SUCCEEDED(hr))
+ {
+ UNLOCK
+ hr = CoCopyProxy( pRemUnk, (IUnknown **) &pSecureRemUnk );
+ LOCK
+ if (SUCCEEDED(hr))
+ {
+ // Remote Unknown proxies are not supposed to ref count
+ // the OXID.
+ pIpid->pOXIDEntry->cRefs -= 1;
+
+ // Only keep the proxies if no one else made a copy
+ // while this thread was making a copy.
+ if (!_pStdId->CheckSecureRemUnk())
+ _pStdId->SetSecureRemUnk( pSecureRemUnk );
+ else
+ {
+ pSecureRemUnk->Release();
+ hr = _pStdId->GetSecureRemUnk( &pSecureRemUnk, NULL );
+ }
+ }
+ }
+ UNLOCK
+ }
+ else
+ hr = _pStdId->GetSecureRemUnk( &pSecureRemUnk, NULL );
+
+ // Call SetBlanket on the copy of IRemUnknown.
+ if (pSecureRemUnk != NULL)
+ hr = CoSetProxyBlanket( pSecureRemUnk, AuthnSvc, AuthzSvc,
+ pServerPrincName, AuthnLevel,
+ ImpLevel, pAuthInfo, Capabilities );
+ }
+
+ else
+ {
+ // Find the right IPID entry.
+ LOCK
+ hr = _pStdId->FindIPIDEntryByInterface( pProxy, &pIpid );
+ if (SUCCEEDED(hr))
+ {
+ // Disallow server entries.
+ if (pIpid->dwFlags & IPIDF_SERVERENTRY)
+ hr = E_INVALIDARG;
+
+ // No security for disconnected proxies.
+ else if (pIpid->dwFlags & IPIDF_DISCONNECTED)
+ hr = RPC_E_DISCONNECTED;
+
+ else if (pIpid->pChnl->ProcessLocal())
+ {
+ // Local calls can use no authn service or winnt.
+ if (AuthnSvc != RPC_C_AUTHN_NONE &&
+ AuthnSvc != RPC_C_AUTHN_WINNT)
+ hr = E_INVALIDARG;
+
+ // Make sure the authentication level is not invalid.
+ else if ((AuthnSvc == RPC_C_AUTHN_NONE &&
+ AuthnLevel != RPC_C_AUTHN_LEVEL_NONE) ||
+ (AuthnSvc == RPC_C_AUTHN_WINNT &&
+ AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY))
+ hr = E_INVALIDARG;
+
+ // No authorization services are supported locally.
+ else if (AuthzSvc != RPC_C_AUTHZ_NONE)
+ hr = E_INVALIDARG;
+
+ // You cannot supply credentials locally.
+ else if (pAuthInfo != NULL)
+ hr = E_INVALIDARG;
+
+ // Impersonation is not legal yet.
+ else if (ImpLevel != RPC_C_IMP_LEVEL_IMPERSONATE &&
+ ImpLevel != RPC_C_IMP_LEVEL_IDENTIFY)
+ hr = E_INVALIDARG;
+
+ // No capabilities are supported yet.
+ else if (Capabilities != EOAC_NONE)
+ hr = E_INVALIDARG;
+
+ // Don't do delegation for NT 4.0
+#ifndef _SOME_FUTURE_PRODUCT_
+ pIpid->pChnl->SetAuthnLevel( AuthnLevel );
+ pIpid->pChnl->SetImpLevel( ImpLevel );
+#else
+
+ // Save the user token if the app asked for security.
+ else if (AuthnLevel != RPC_C_AUTHN_LEVEL_NONE)
+ {
+ if (ImpLevel == RPC_C_IMP_LEVEL_IMPERSONATE)
+ {
+ eDuplicate = SecurityImpersonation;
+ dwOpen = TOKEN_IMPERSONATE;
+ }
+ else
+ {
+ eDuplicate = SecurityIdentification;
+ dwOpen = TOKEN_QUERY;
+ }
+ fSuccess = OpenThreadToken( GetCurrentThread(), dwOpen,
+ TRUE, &hToken );
+ hr = GetLastError();
+
+ // If the application is not impersonating, no thread token
+ // will be present. Get the process token instead.
+ if (!fSuccess && hr == ERROR_NO_TOKEN)
+ {
+ fSuccess = OpenProcessToken( GetCurrentProcess(),
+ TOKEN_DUPLICATE, &hProcess );
+ if (fSuccess)
+ {
+ fSuccess = DuplicateToken( hProcess, eDuplicate,
+ &hToken );
+ CloseHandle( hProcess );
+ }
+ }
+ if (fSuccess)
+ {
+ hToken = pIpid->pChnl->SwapSecurityToken( hToken );
+ pIpid->pChnl->SetAuthnLevel( AuthnLevel );
+ pIpid->pChnl->SetImpLevel( ImpLevel );
+ hr = S_OK;
+ }
+ else
+ {
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+ hToken = pIpid->pChnl->SwapSecurityToken( NULL );
+ }
+ CloseHandle( hToken );
+ }
+
+ // If there was an old token, toss it.
+ else if (pIpid->pChnl->GetSecurityToken() != NULL)
+ {
+ hToken = pIpid->pChnl->SwapSecurityToken( NULL );
+ CloseHandle( hToken );
+ pIpid->pChnl->SetAuthnLevel( AuthnLevel );
+ pIpid->pChnl->SetImpLevel( ImpLevel );
+ }
+#endif // !_SOME_FUTURE_PRODUCT_
+ }
+
+ // If it is remote, tell RPC.
+ else
+ {
+ // Validate the capabilities.
+ if (Capabilities & ~ EOAC_MUTUAL_AUTH)
+ hr = E_INVALIDARG;
+ else
+ hr = pIpid->pChnl->GetHandle( &hHandle );
+
+ if (SUCCEEDED(hr))
+ {
+#ifdef _CHICAGO_
+ // If the principal name is not known, the server must be
+ // NT. Replace the principal name in that case
+ // because a NULL principal name is a flag for some
+ // Chicago security hack.
+ if (pServerPrincName == NULL &&
+ AuthnSvc == RPC_C_AUTHN_WINNT &&
+ (pIpid->pOXIDEntry->dwFlags & OXIDF_MACHINE_LOCAL) == 0)
+ pServerPrincName = L"Default";
+#endif // _CHICAGO_
+
+ // Suspend any outstanding impersonation and ignore failures.
+ COleTls tls(hr);
+ BOOL resume = FALSE;
+ if (SUCCEEDED(hr))
+ SuspendImpersonate( tls->pCallContext, &resume );
+ else
+ hr = S_OK;
+
+ sQos.Version = RPC_C_SECURITY_QOS_VERSION;
+ sQos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
+ sQos.ImpersonationType = ImpLevel;
+ sQos.Capabilities = (Capabilities & EOAC_MUTUAL_AUTH) ?
+ RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH : RPC_C_QOS_CAPABILITIES_DEFAULT;
+ sc = RpcBindingSetAuthInfoExW( hHandle,
+ pServerPrincName, AuthnLevel,
+ AuthnSvc, pAuthInfo, AuthzSvc,
+ &sQos );
+
+ // Resume any outstanding impersonation.
+ ResumeImpersonate( tls->pCallContext, resume );
+
+ if (sc != RPC_S_OK)
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, sc );
+ else
+ pIpid->pChnl->SetAuthnLevel( AuthnLevel );
+ }
+ }
+ }
+
+ UNLOCK
+ }
+ ASSERT_LOCK_RELEASED
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CheckAccessControl
+//
+// Synopsis: Call the access control and ask it to check access.
+//
+//--------------------------------------------------------------------
+RPC_STATUS CheckAccessControl( RPC_IF_HANDLE pIid, void *pContext )
+{
+ HRESULT hr;
+ TRUSTEE_W sTrustee;
+ CServerSecurity sSecurity;
+ IUnknown *pSave;
+ BOOL fAccess = FALSE;
+ COleTls tls(hr);
+#if DBG == 1
+ char *pFailure = "";
+#endif
+
+ sTrustee.ptstrName = NULL;
+ if (FAILED(hr))
+ {
+#if DBG == 1
+ pFailure = "Bad TLS: 0x%x\n";
+#endif
+ }
+
+ else
+ {
+#ifdef _CHICAGO_
+ // On Chicago RpcBindingInqAuthClientW doesn't work locally. Since
+ // IObjServer is the only interface that uses security locally on
+ // Chicago, allow it if the call is local.
+ if (pIid == NULL)
+ return RPC_S_OK;
+ else if ((*(IID *) pIid) == IID_IObjServer)
+ {
+#if DBG == 1
+ pFailure = "IObjServer can't be called remotely: 0x%x\n";
+#endif
+ hr = E_ACCESSDENIED;
+ }
+#else
+ // Since IObjServer always uses dynamic impersonation, allow access here.
+ // It will be checked later in CheckObjactAccess.
+ if (pIid != NULL && *((IID *) pIid) == IID_IObjServer)
+ return RPC_S_OK;
+#endif
+
+ if (SUCCEEDED(hr))
+ {
+ // Get the trustee name.
+ hr = RpcBindingInqAuthClientW( NULL,
+ (void **) &sTrustee.ptstrName,
+ NULL, NULL, NULL, NULL );
+
+ if (hr == RPC_S_OK)
+ {
+ // Save the security context in TLS.
+ pSave = tls->pCallContext;
+ tls->pCallContext = &sSecurity;
+
+ // Check access.
+ sTrustee.pMultipleTrustee = NULL;
+ sTrustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
+ sTrustee.TrusteeForm = TRUSTEE_IS_NAME;
+ sTrustee.TrusteeType = TRUSTEE_IS_USER;
+ hr = gAccessControl->IsAccessAllowed( &sTrustee, NULL,
+ COM_RIGHTS_EXECUTE, &fAccess );
+#if DBG==1
+ if (FAILED(hr))
+ pFailure = "IsAccessAllowed failed: 0x%x\n";
+#endif
+ if (SUCCEEDED(hr) && !fAccess)
+ {
+ hr = E_ACCESSDENIED;
+#if DBG==1
+ pFailure = "IAccessControl does not allow user access.\n";
+#endif
+ }
+
+ // Restore the security context.
+ tls->pCallContext = pSave;
+ }
+#if DBG == 1
+ else
+ pFailure = "RpcBindingInqAuthClientW failed: 0x%x\n";
+#endif
+ }
+ }
+
+#if DBG==1
+ if (FAILED(hr))
+ {
+ ComDebOut(( DEB_WARN, "***** ACCESS DENIED *****\n" ));
+ ComDebOut(( DEB_WARN, pFailure, hr ));
+
+ // Print the user name.
+ if (sTrustee.ptstrName != NULL)
+ ComDebOut(( DEB_WARN, "User: %ws\n", sTrustee.ptstrName ));
+ }
+#endif
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CheckAcl
+//
+// Synopsis: Impersonate and do an AccessCheck against the global ACL.
+//
+//--------------------------------------------------------------------
+RPC_STATUS CheckAcl( RPC_IF_HANDLE pIid, void *pContext )
+{
+ RPC_STATUS sc;
+ BOOL fAccess = FALSE;
+ BOOL fSuccess;
+ DWORD lGrantedAccess;
+ DWORD lSetLen = sizeof(gPriv);
+ HANDLE hToken;
+ DWORD i;
+ DWORD lSize = SIZEOF_TOKEN_USER;
+ TOKEN_USER *pTokenInfo = (TOKEN_USER *) _alloca( lSize );
+ SID *pSid = NULL;
+#if DBG==1
+ char *pFailure = "";
+#endif
+
+ // Since IObjServer always uses dynamic impersonation, allow access here.
+ // It will be checked later in CheckObjactAccess.
+ if (pIid != NULL && *((IID *) pIid) == IID_IObjServer)
+ return RPC_S_OK;
+
+ // Impersonate.
+ sc = RpcImpersonateClient( NULL );
+
+ if (sc == RPC_S_OK)
+ {
+ // Open the thread token.
+ fSuccess = OpenThreadToken( GetCurrentThread(), TOKEN_READ,
+ TRUE, &hToken );
+
+ // Revert.
+ RpcRevertToSelf();
+
+ if (fSuccess)
+ {
+ // Get the SID and see if its cached.
+ if (GetTokenInformation( hToken, TokenUser, pTokenInfo,
+ lSize, &lSize ))
+ {
+ pSid = (SID *) pTokenInfo->User.Sid;
+ fSuccess = CacheAccessCheck( pSid, &fAccess );
+ if (fSuccess)
+ {
+ CloseHandle( hToken );
+ if (fAccess)
+ return RPC_S_OK;
+ else
+ return RPC_E_ACCESS_DENIED;
+ }
+ }
+
+ // Access check.
+ fSuccess = AccessCheck( gSecDesc, hToken, COM_RIGHTS_EXECUTE,
+ &gMap, &gPriv, &lSetLen, &lGrantedAccess,
+ &fAccess );
+ if (fSuccess)
+ CacheAccess( pSid, fAccess );
+
+ if (!fAccess)
+ {
+ sc = RPC_E_ACCESS_DENIED;
+#if DBG==1
+ pFailure = "Security descriptor does not allow user access.\n";
+#endif
+ }
+#if DBG==1
+ if (!fSuccess)
+ pFailure = "Bad security descriptor";
+#endif
+ CloseHandle( hToken );
+ }
+ else
+ {
+ sc = GetLastError();
+#if DBG==1
+ pFailure = "Could not open thread token: 0x%x\n";
+#endif
+ }
+ }
+#if DBG==1
+ else
+ pFailure = "Could not impersonate client: 0x%x\n";
+#endif
+
+#if DBG==1
+ if (sc != 0)
+ {
+ ComDebOut(( DEB_WARN, "***** ACCESS DENIED *****\n" ));
+ ComDebOut(( DEB_WARN, pFailure, sc ));
+
+ // Print the user name.
+ WCHAR *pClient;
+ if (0 == RpcBindingInqAuthClient( NULL, (void **) &pClient, NULL,
+ NULL, NULL, NULL ) &&
+ pClient != NULL)
+ ComDebOut(( DEB_WARN, "User: %ws\n", pClient ));
+
+ // Print the user sid.
+ ComDebOut(( DEB_WARN, "Security Descriptor 0x%x\n", gSecDesc ));
+ if (pSid != NULL)
+ {
+ ComDebOut(( DEB_WARN, "SID:\n" ));
+ ComDebOut(( DEB_WARN, " Revision: 0x%02x\n", pSid->Revision ));
+ ComDebOut(( DEB_WARN, " SubAuthorityCount: 0x%x\n", pSid->SubAuthorityCount ));
+ ComDebOut(( DEB_WARN, " IdentifierAuthority: 0x%02x%02x%02x%02x%02x%02x\n",
+ pSid->IdentifierAuthority.Value[0],
+ pSid->IdentifierAuthority.Value[1],
+ pSid->IdentifierAuthority.Value[2],
+ pSid->IdentifierAuthority.Value[3],
+ pSid->IdentifierAuthority.Value[4],
+ pSid->IdentifierAuthority.Value[5] ));
+ for (DWORD i = 0; i < pSid->SubAuthorityCount; i++)
+ ComDebOut(( DEB_WARN, " SubAuthority[%d]: 0x%08x\n", i,
+ pSid->SubAuthority[i] ));
+ }
+ else
+ ComDebOut(( DEB_WARN, " Unknown\n" ));
+ }
+#endif
+ return sc;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CheckObjactAccess, private
+//
+// Synopsis: Determine whether caller has permission to make call.
+//
+// Notes: Since IObjServer uses dynamic delegation, we have to allow
+// all calls to IObjServer through the normal security (which only
+// checks access on connect) and check them manually.
+//
+//--------------------------------------------------------------------
+BOOL CheckObjactAccess()
+{
+ RPC_IF_CALLBACK_FN *pAccess;
+
+ // Get the access check function.
+ pAccess = GetAclFn();
+
+ // Check access. Lie about the IID since the check access functions
+ // won't fail calls to IID_IObjServer.
+ if (pAccess != NULL)
+ return pAccess( NULL, NULL ) == S_OK;
+ else
+ return TRUE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoCopyProxy, public
+//
+// Synopsis: Copy a proxy.
+//
+//--------------------------------------------------------------------
+WINOLEAPI CoCopyProxy(
+ IUnknown *pProxy,
+ IUnknown **ppCopy )
+{
+ HRESULT hr;
+ IClientSecurity *pickle;
+ // Ask the proxy for IClientSecurity.
+ hr = ((IUnknown *) pProxy)->QueryInterface( IID_IClientSecurity,
+ (void **) &pickle );
+ if (FAILED(hr))
+ return hr;
+
+ // Ask IClientSecurity to do the copy.
+ hr = pickle->CopyProxy( pProxy, ppCopy );
+ pickle->Release();
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoGetCallContext
+//
+// Synopsis: Get an interface that supplies contextual information
+// about the call. Currently only IServerSecurity.
+//
+//--------------------------------------------------------------------
+WINOLEAPI CoGetCallContext( REFIID riid, void **ppInterface )
+{
+ HRESULT hr;
+ COleTls tls(hr);
+
+ if (SUCCEEDED(hr))
+ {
+ // Fail if there is no call context.
+ if (tls->pCallContext == NULL)
+ return RPC_E_CALL_COMPLETE;
+
+ // Look up the requested interface.
+ return tls->pCallContext->QueryInterface( riid, ppInterface );
+ }
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoImpersonateClient
+//
+// Synopsis: Get the server security for the current call and ask it
+// to do an impersonation.
+//
+//--------------------------------------------------------------------
+WINOLEAPI CoImpersonateClient()
+{
+ HRESULT hr;
+ IServerSecurity *pSS;
+
+ // Get the IServerSecurity.
+ hr = CoGetCallContext( IID_IServerSecurity, (void **) &pSS );
+ if (FAILED(hr))
+ return hr;
+
+ // Ask IServerSecurity to do the impersonate.
+ hr = pSS->ImpersonateClient();
+ pSS->Release();
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoInitializeSecurity, public
+//
+// Synopsis: Set the values to use for automatic security. This API
+// can only be called once so it does not need to be thread
+// safe.
+//
+//--------------------------------------------------------------------
+WINOLEAPI CoInitializeSecurity(
+ PSECURITY_DESCRIPTOR pVoid,
+ LONG cAuthSvc,
+ SOLE_AUTHENTICATION_SERVICE *asAuthSvc,
+ void *pReserved1,
+ DWORD dwAuthnLevel,
+ DWORD dwImpLevel,
+ void *pReserved2,
+ DWORD dwCapabilities,
+ void *pReserved3 )
+{
+ HRESULT hr = S_OK;
+ DWORD i;
+ SECURITY_DESCRIPTOR *pSecDesc = (SECURITY_DESCRIPTOR *) pVoid;
+ SECURITY_DESCRIPTOR *pCopySecDesc = NULL;
+ IAccessControl *pAccessControl = NULL;
+ BOOL fFreeSecDesc = FALSE;
+ SOLE_AUTHENTICATION_SERVICE sAuthSvc;
+
+ // Fail if OLE is not initialized or TLS cannot be allocated.
+ if (!IsApartmentInitialized())
+ return CO_E_NOTINITIALIZED;
+
+ // Make sure the security data is available.
+ if (!gGotSecurityData)
+ {
+ hr = gResolver.GetConnection();
+ if (FAILED(hr))
+ return hr;
+ Win4Assert(gGotSecurityData);
+ }
+
+ // Make sure only one of the flags defining the pVoid parameter is set.
+ if ((dwCapabilities & (EOAC_APPID | EOAC_ACCESS_CONTROL)) ==
+ (EOAC_APPID | EOAC_ACCESS_CONTROL))
+ return E_INVALIDARG;
+
+ // If the appid flag is set, read the registry security.
+ if (dwCapabilities & EOAC_APPID)
+ {
+ // Get a security descriptor from the registry.
+ if (gAuthnLevel != RPC_C_AUTHN_LEVEL_NONE)
+ {
+ hr = GetLegacySecDesc( &pSecDesc, &dwCapabilities );
+ if (FAILED(hr))
+ return hr;
+ fFreeSecDesc = TRUE;
+ }
+
+ // Fix up the security binding.
+ if (gLegacySecurity != NULL)
+ {
+ cAuthSvc = 1;
+ asAuthSvc = &sAuthSvc;
+ sAuthSvc.dwAuthnSvc = gLegacySecurity->wAuthnSvc;
+ sAuthSvc.dwAuthzSvc = gLegacySecurity->wAuthzSvc;
+ sAuthSvc.pPrincipalName = NULL;
+ if (sAuthSvc.dwAuthzSvc == COM_C_AUTHZ_NONE)
+ sAuthSvc.dwAuthzSvc = RPC_C_AUTHZ_NONE;
+ }
+ else
+ cAuthSvc = 0xFFFFFFFF;
+
+ // Initialize remaining parameters.
+ pReserved1 = NULL;
+ dwAuthnLevel = gAuthnLevel;
+ dwImpLevel = gImpLevel;
+ pReserved2 = NULL;
+ pReserved3 = NULL;
+ dwCapabilities |= gCapabilities;
+ }
+
+ // Fail if called too late, recalled, or called with bad parameters.
+ if (dwImpLevel > RPC_C_IMP_LEVEL_DELEGATE ||
+ dwAuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY ||
+ pReserved1 != NULL ||
+ pReserved2 != NULL ||
+ pReserved3 != NULL ||
+ (dwCapabilities & ~VALID_INIT_FLAGS))
+ {
+ hr = E_INVALIDARG;
+ goto Error;
+ }
+ if ((dwCapabilities & EOAC_SECURE_REFS) &&
+ dwAuthnLevel == RPC_C_AUTHN_LEVEL_NONE)
+ {
+ hr = E_INVALIDARG;
+ goto Error;
+ }
+
+ // Validate the pointers.
+ if (pSecDesc != NULL)
+ if (dwCapabilities & EOAC_ACCESS_CONTROL)
+ {
+ if (!IsValidPtrIn( pSecDesc, 4 ))
+ {
+ hr = E_INVALIDARG;
+ goto Error;
+ }
+ }
+ else if (!IsValidPtrIn( pSecDesc, sizeof(SECURITY_DESCRIPTOR) ))
+ {
+ hr = E_INVALIDARG;
+ goto Error;
+ }
+ if (cAuthSvc != 0 && cAuthSvc != -1 &&
+ !IsValidPtrOut( asAuthSvc, sizeof(SOLE_AUTHENTICATION_SERVICE) * cAuthSvc ))
+ {
+ hr = E_INVALIDARG;
+ goto Error;
+ }
+
+ LOCK
+
+ if (gpsaSecurity != NULL)
+ hr = RPC_E_TOO_LATE;
+
+ if (SUCCEEDED(hr))
+ {
+ // If the app doesn't want security, don't set up a security
+ // descriptor.
+ if (dwAuthnLevel == RPC_C_AUTHN_LEVEL_NONE)
+ {
+ // Check for some more invalid parameters.
+ if (pSecDesc != NULL)
+ hr = E_INVALIDARG;
+ }
+
+ // Check whether security is done with ACLs or IAccessControl.
+ else if (dwCapabilities & EOAC_ACCESS_CONTROL)
+ {
+ if (pSecDesc == NULL)
+ hr = E_INVALIDARG;
+ else
+ hr = ((IUnknown *) pSecDesc)->QueryInterface(
+ IID_IAccessControl, (void **) &pAccessControl );
+ }
+
+ else
+ {
+#ifdef _CHICAGO_
+ if (pSecDesc != NULL)
+ hr = E_INVALIDARG;
+#else
+ // If specified, copy the security descriptor.
+ if (pSecDesc != NULL)
+ hr = CopySecDesc( pSecDesc, &pCopySecDesc );
+#endif
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // Delay the registration of authentication services if the caller
+ // isn't picky.
+ if (cAuthSvc == -1)
+ {
+ gpsaSecurity = (DUALSTRINGARRAY *) PrivMemAlloc( SASIZE(4) );
+ if (gpsaSecurity != NULL)
+ {
+ gDefaultService = TRUE;
+ gpsaSecurity->wNumEntries = 4;
+ gpsaSecurity->wSecurityOffset = 2;
+ memset( gpsaSecurity->aStringArray, 0, 4*sizeof(WCHAR) );
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ }
+
+ // Otherwise, register the ones the caller specified.
+ else
+ hr = RegisterAuthnServices( cAuthSvc, asAuthSvc );
+ }
+
+ // If everything succeeded, change the globals.
+ if (SUCCEEDED(hr))
+ {
+ // Save the defaults.
+ gAuthnLevel = dwAuthnLevel;
+ gImpLevel = dwImpLevel;
+ gCapabilities = dwCapabilities;
+ gSecDesc = pCopySecDesc;
+ gAccessControl = pAccessControl;
+ if ( dwCapabilities & EOAC_DYNAMIC )
+ gResolver.SetDynamicSecurity();
+ }
+
+ // Otherwise free any memory allocated.
+ else
+ {
+ PrivMemFree( pCopySecDesc );
+ }
+ UNLOCK
+
+ // If anything was allocated for app id security, free it.
+Error:
+ if (fFreeSecDesc && pSecDesc != NULL)
+ if (dwCapabilities & EOAC_ACCESS_CONTROL)
+ ((IAccessControl *) pSecDesc)->Release();
+ else
+ PrivMemFree( pSecDesc );
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CopySecDesc
+//
+// Synopsis: Copy a security descriptor.
+//
+// Notes: The function does not copy the SACL because we do not do
+// auditing.
+//
+//--------------------------------------------------------------------
+HRESULT CopySecDesc( SECURITY_DESCRIPTOR *pOrig, SECURITY_DESCRIPTOR **pCopy )
+{
+ SID *pOwner;
+ SID *pGroup;
+ ACL *pDacl;
+ ULONG cSize;
+ ULONG cOwner;
+ ULONG cGroup;
+ ULONG cDacl;
+
+ // Assert if there is a new revision for the security descriptor or
+ // ACL.
+#if DBG== 1
+ if (pOrig->Revision != SECURITY_DESCRIPTOR_REVISION)
+ ComDebOut(( DEB_ERROR, "Someone made a new security descriptor revision without telling me." ));
+ if (pOrig->Dacl != NULL)
+ Win4Assert( pOrig->Dacl->AclRevision == ACL_REVISION ||
+ !"Someone made a new acl revision without telling me." );
+#endif
+
+ // Validate the security descriptor and ACL.
+ if (pOrig->Revision != SECURITY_DESCRIPTOR_REVISION ||
+ (pOrig->Control & SE_SELF_RELATIVE) != 0 ||
+ pOrig->Owner == NULL ||
+ pOrig->Group == NULL ||
+ pOrig->Sacl != NULL ||
+ (pOrig->Dacl != NULL && pOrig->Dacl->AclRevision != ACL_REVISION))
+ return E_INVALIDARG;
+
+ // Figure out how much memory to allocate for the copy and allocate it.
+ cOwner = GetLengthSid( pOrig->Owner );
+ cGroup = GetLengthSid( pOrig->Group );
+ cDacl = pOrig->Dacl == NULL ? 0 : pOrig->Dacl->AclSize;
+ cSize = sizeof(SECURITY_DESCRIPTOR) + cOwner + cGroup + cDacl;
+ *pCopy = (SECURITY_DESCRIPTOR *) PrivMemAlloc( cSize );
+ if (*pCopy == NULL)
+ return E_OUTOFMEMORY;
+
+ // Get pointers to each of the parts of the security descriptor.
+ pOwner = (SID *) (*pCopy + 1);
+ pGroup = (SID *) (((char *) pOwner) + cOwner);
+ if (pOrig->Dacl != NULL)
+ pDacl = (ACL *) (((char *) pGroup) + cGroup);
+ else
+ pDacl = NULL;
+
+ // Copy each piece.
+ **pCopy = *pOrig;
+ memcpy( pOwner, pOrig->Owner, cOwner );
+ memcpy( pGroup, pOrig->Group, cGroup );
+ if (pDacl != NULL)
+ memcpy( pDacl, pOrig->Dacl, pOrig->Dacl->AclSize );
+ (*pCopy)->Owner = pOwner;
+ (*pCopy)->Group = pGroup;
+ (*pCopy)->Dacl = pDacl;
+ (*pCopy)->Sacl = NULL;
+
+ // Check the security descriptor.
+#if DBG==1
+ if (!IsValidSecurityDescriptor( *pCopy ))
+ {
+ Win4Assert( !"COM Created invalid security descriptor." );
+ return GetLastError();
+ }
+#endif
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoQueryAuthenticationServices, public
+//
+// Synopsis: Return a list of the registered authentication services.
+//
+//--------------------------------------------------------------------
+WINOLEAPI CoQueryAuthenticationServices( DWORD *pcAuthSvc,
+ SOLE_AUTHENTICATION_SERVICE **asAuthSvc )
+{
+ DWORD i;
+ DWORD lNum = 0;
+ USHORT *pNext;
+ HRESULT hr = S_OK;
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // Count the number of services in the security string array.
+ if (gpsaSecurity != NULL)
+ {
+ pNext = &gpsaSecurity->aStringArray[gpsaSecurity->wSecurityOffset];
+ while (*pNext != 0)
+ {
+ lNum++;
+ pNext += lstrlenW(pNext)+1;
+ }
+ }
+
+ // Return nothing if there are no authentication services.
+ *pcAuthSvc = lNum;
+ if (lNum == 0)
+ {
+ *asAuthSvc = NULL;
+ goto exit;
+ }
+
+ // Allocate a list of pointers.
+ *asAuthSvc = (SOLE_AUTHENTICATION_SERVICE *)
+ CoTaskMemAlloc( lNum * sizeof(void *) );
+ if (*asAuthSvc == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto exit;
+ }
+
+ // Initialize it.
+ for (i = 0; i < lNum; i++)
+ (*asAuthSvc)[i].pPrincipalName = NULL;
+
+ // Fill in one SOLE_AUTHENTICATION_SERVICE record per service
+ pNext = &gpsaSecurity->aStringArray[gpsaSecurity->wSecurityOffset];
+ for (i = 0; i < lNum; i++)
+ {
+ (*asAuthSvc)[i].dwAuthnSvc = *(pNext++);
+ (*asAuthSvc)[i].dwAuthzSvc = *(pNext++);
+ (*asAuthSvc)[i].hr = S_OK;
+
+ // Allocate memory for the principal name string.
+ (*asAuthSvc)[i].pPrincipalName = (OLECHAR *)
+ CoTaskMemAlloc( (lstrlenW(pNext)+1)*sizeof(OLECHAR) );
+ if ((*asAuthSvc)[i].pPrincipalName == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ break;
+ }
+
+ lstrcpyW( (*asAuthSvc)[i].pPrincipalName, pNext );
+ pNext += lstrlenW(pNext) + 1;
+ }
+
+ // Clean up if there wasn't enough memory.
+ if (FAILED(hr))
+ {
+ for (i = 0; i < lNum; i++)
+ CoTaskMemFree( (*asAuthSvc)[i].pPrincipalName );
+ CoTaskMemFree( *asAuthSvc );
+ *asAuthSvc = NULL;
+ *pcAuthSvc = 0;
+ }
+
+exit:
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoQueryClientBlanket
+//
+// Synopsis: Get the authentication settings the client used to call
+// the server.
+//
+//--------------------------------------------------------------------
+WINOLEAPI CoQueryClientBlanket(
+ DWORD *pAuthnSvc,
+ DWORD *pAuthzSvc,
+ OLECHAR **pServerPrincName,
+ DWORD *pAuthnLevel,
+ DWORD *pImpLevel,
+ RPC_AUTHZ_HANDLE *pPrivs,
+ DWORD *pCapabilities )
+{
+ HRESULT hr;
+ IServerSecurity *pSS;
+
+ // Get the IServerSecurity.
+ hr = CoGetCallContext( IID_IServerSecurity, (void **) &pSS );
+ if (FAILED(hr))
+ return hr;
+
+ // Ask IServerSecurity to do the query.
+ hr = pSS->QueryBlanket( pAuthnSvc, pAuthzSvc, pServerPrincName,
+ pAuthnLevel, pImpLevel, pPrivs, pCapabilities );
+
+ pSS->Release();
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoQueryProxyBlanket, public
+//
+// Synopsis: Get the authentication settings from a proxy.
+//
+//--------------------------------------------------------------------
+WINOLEAPI CoQueryProxyBlanket(
+ IUnknown *pProxy,
+ DWORD *pAuthnSvc,
+ DWORD *pAuthzSvc,
+ OLECHAR **pServerPrincName,
+ DWORD *pAuthnLevel,
+ DWORD *pImpLevel,
+ RPC_AUTH_IDENTITY_HANDLE *pAuthInfo,
+ DWORD *pCapabilities )
+{
+ HRESULT hr;
+ IClientSecurity *pickle;
+
+ // Ask the proxy for IClientSecurity.
+ hr = ((IUnknown *) pProxy)->QueryInterface( IID_IClientSecurity,
+ (void **) &pickle );
+ if (FAILED(hr))
+ return hr;
+
+ // Ask IClientSecurity to do the query.
+ hr = pickle->QueryBlanket( pProxy, pAuthnSvc, pAuthzSvc, pServerPrincName,
+ pAuthnLevel, pImpLevel, pAuthInfo,
+ pCapabilities );
+ pickle->Release();
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoRevertToSelf
+//
+// Synopsis: Get the server security for the current call and ask it
+// to revert.
+//
+//--------------------------------------------------------------------
+WINOLEAPI CoRevertToSelf()
+{
+ HRESULT hr;
+ IServerSecurity *pSS;
+
+ // Get the IServerSecurity.
+ hr = CoGetCallContext( IID_IServerSecurity, (void **) &pSS );
+ if (FAILED(hr))
+ return hr;
+
+ // Ask IServerSecurity to do the revert.
+ hr = pSS->RevertToSelf();
+ pSS->Release();
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoSetProxyBlanket, public
+//
+// Synopsis: Set the authentication settings for a proxy.
+//
+//--------------------------------------------------------------------
+WINOLEAPI CoSetProxyBlanket(
+ IUnknown *pProxy,
+ DWORD dwAuthnSvc,
+ DWORD dwAuthzSvc,
+ OLECHAR *pServerPrincName,
+ DWORD dwAuthnLevel,
+ DWORD dwImpLevel,
+ RPC_AUTH_IDENTITY_HANDLE pAuthInfo,
+ DWORD dwCapabilities )
+{
+ HRESULT hr;
+ IClientSecurity *pickle;
+
+ // Ask the proxy for IClientSecurity.
+ hr = ((IUnknown *) pProxy)->QueryInterface( IID_IClientSecurity,
+ (void **) &pickle );
+ if (FAILED(hr))
+ return hr;
+
+ // Ask IClientSecurity to do the set.
+ hr = pickle->SetBlanket( pProxy, dwAuthnSvc, dwAuthzSvc, pServerPrincName,
+ dwAuthnLevel, dwImpLevel, pAuthInfo,
+ dwCapabilities );
+ pickle->Release();
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CoSwitchCallContext
+//
+// Synopsis: Replace the call context object in TLS. Return the old
+// context object. This API is used by custom marshallers
+// to support security.
+//
+//--------------------------------------------------------------------
+WINOLEAPI CoSwitchCallContext( IUnknown *pNewObject, IUnknown **ppOldObject )
+{
+ HRESULT hr;
+ COleTls tls(hr);
+
+ if (SUCCEEDED(hr))
+ {
+ *ppOldObject = tls->pCallContext;
+ tls->pCallContext = pNewObject;
+ }
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CServerSecurity::AddRef, public
+//
+// Synopsis: Adds a reference to an interface
+//
+// Note: This is created in the stack so its reference count is ignored.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CServerSecurity::AddRef()
+{
+ InterlockedIncrement( (long *) &_iRefCount );
+ return _iRefCount;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CServerSecurity::CServerSecurity, public
+//
+// Synopsis: Construct a server security for a remote call.
+//
+//--------------------------------------------------------------------
+CServerSecurity::CServerSecurity()
+{
+ _iRefCount = 1;
+ _pChannel = NULL;
+ _pHandle = NULL;
+ _iFlags = 0;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CServerSecurity::CServerSecurity, public
+//
+// Synopsis: Construct a server security for a call.
+//
+//--------------------------------------------------------------------
+CServerSecurity::CServerSecurity( CChannelCallInfo *call )
+{
+ _iRefCount = 1;
+ if (call->iFlags & CF_PROCESS_LOCAL)
+ {
+ _pChannel = call->pChannel;
+ _pHandle = NULL;
+ _iFlags = SS_PROCESS_LOCAL;
+ }
+ else
+ {
+ _pChannel = NULL;
+ _pHandle = (handle_t *) call->pmessage->reserved1;
+ _iFlags = 0;
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CServerSecurity::EndCall, public
+//
+// Synopsis: Clears the stored binding handle because the call
+// this object represents is over.
+//
+//--------------------------------------------------------------------
+void CServerSecurity::EndCall()
+{
+ // Revert if the app forgot to.
+ RevertToSelf();
+ _iFlags |= SS_CALL_DONE;
+ _pChannel = NULL;
+ _pHandle = NULL;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CServerSecurity::ImpersonateClient, public
+//
+// Synopsis: Calls RPC to impersonate for the stored binding handle.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CServerSecurity::ImpersonateClient()
+{
+#ifdef _CHICAGO_
+ return E_NOTIMPL;
+#else
+
+ HRESULT hr = S_OK;
+ RPC_STATUS sc;
+ BOOL fSuccess;
+ HANDLE hProcess;
+ HANDLE hToken;
+ SECURITY_IMPERSONATION_LEVEL eDuplicate;
+
+ // If the call is over, fail this request.
+ if (_iFlags & SS_CALL_DONE)
+ hr = RPC_E_CALL_COMPLETE;
+
+ // For process local calls, ask the channel to impersonate.
+ else if (_iFlags & SS_PROCESS_LOCAL)
+ {
+ if (_pChannel->GetSecurityToken() == NULL)
+ {
+ // Determine what rights to duplicate the token with.
+ if (_pChannel->GetImpLevel() == RPC_C_IMP_LEVEL_IMPERSONATE)
+ eDuplicate = SecurityImpersonation;
+ else
+ eDuplicate = SecurityIdentification;
+
+ // If the channel doesn't have a token, use the process token.
+ if (OpenProcessToken( GetCurrentProcess(),
+ TOKEN_DUPLICATE,
+ &hProcess ))
+ {
+ if (DuplicateToken( hProcess, eDuplicate, &hToken ))
+ {
+ if (!SetThreadToken( NULL, hToken ))
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+
+ // If the channel still doesn't have a token, save this one.
+ LOCK
+ if (_pChannel->GetSecurityToken() == NULL)
+ _pChannel->SwapSecurityToken( hToken );
+ else
+ CloseHandle( hToken );
+ UNLOCK
+ }
+ else
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+ CloseHandle( hProcess );
+ }
+ else
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+ }
+ else
+ {
+ fSuccess = SetThreadToken( NULL, _pChannel->GetSecurityToken() );
+ if (!fSuccess)
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+ }
+ }
+
+ // For process remote calls, ask RPC to impersonate.
+ else
+ {
+ sc = RpcImpersonateClient( _pHandle );
+ if (sc != RPC_S_OK)
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, sc );
+ }
+
+ if (SUCCEEDED(hr))
+ _iFlags |= SS_IMPERSONATING;
+ return hr;
+#endif
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CServerSecurity::IsImpersonating, public
+//
+// Synopsis: Return TRUE if ImpersonateClient has been called.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(BOOL) CServerSecurity::IsImpersonating()
+{
+#ifdef _CHICAGO_
+ return FALSE;
+#else
+ return _iFlags & SS_IMPERSONATING;
+#endif
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CServerSecurity::QueryBlanket, public
+//
+// Synopsis: Calls RPC to return the authentication information
+// for the stored binding handle.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CServerSecurity::QueryBlanket(
+ DWORD *pAuthnSvc,
+ DWORD *pAuthzSvc,
+ OLECHAR **pServerPrincName,
+ DWORD *pAuthnLevel,
+ DWORD *pImpLevel,
+ void **pPrivs,
+ DWORD *pCapabilities )
+{
+ HRESULT hr = S_OK;
+ RPC_STATUS sc;
+ DWORD iLen;
+ OLECHAR *pCopy;
+
+ // Initialize the out parameters. Currently the impersonation level
+ // and capabilities can not be determined.
+ if (pPrivs != NULL)
+ *((void **) pPrivs) = NULL;
+ if (pServerPrincName != NULL)
+ *pServerPrincName = NULL;
+ if (pAuthnSvc != NULL)
+ *pAuthnSvc = RPC_C_AUTHN_WINNT;
+ if (pAuthnLevel != NULL)
+ *pAuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
+ if (pImpLevel != NULL)
+ *pImpLevel = RPC_C_IMP_LEVEL_ANONYMOUS;
+ if (pAuthzSvc != NULL)
+ *pAuthzSvc = RPC_C_AUTHZ_NONE;
+ if (pCapabilities != NULL)
+ *pCapabilities = EOAC_NONE;
+
+ // If the call is over, fail this request.
+ if (_iFlags & SS_CALL_DONE)
+ hr = RPC_E_CALL_COMPLETE;
+
+ // For process local calls, use the defaults. Otherwise ask RPC.
+ else if ((_iFlags & SS_PROCESS_LOCAL) == 0)
+ {
+ sc = RpcBindingInqAuthClientW( _pHandle, pPrivs, pServerPrincName,
+ pAuthnLevel, pAuthnSvc, pAuthzSvc );
+
+ // Sometimes RPC sets out parameters in error cases.
+ if (sc != RPC_S_OK)
+ {
+ if (pServerPrincName != NULL)
+ *pServerPrincName = NULL;
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, sc );
+ }
+ else if (pServerPrincName != NULL && *pServerPrincName != NULL)
+ {
+ // Reallocate the principle name using the OLE memory allocator.
+ iLen = lstrlenW( *pServerPrincName );
+ pCopy = (OLECHAR *) CoTaskMemAlloc( (iLen+1) * sizeof(OLECHAR) );
+ if (pCopy != NULL)
+ lstrcpyW( pCopy, *pServerPrincName );
+ else
+ hr = E_OUTOFMEMORY;
+ RpcStringFree( pServerPrincName );
+ *pServerPrincName = pCopy;
+ }
+ }
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CServerSecurity::QueryInterface, public
+//
+// Synopsis: Returns a pointer to the requested interface.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CServerSecurity::QueryInterface( REFIID riid, LPVOID FAR* ppvObj)
+{
+ if (IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IServerSecurity))
+ {
+ *ppvObj = (IServerSecurity *) this;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CServerSecurity::Release, public
+//
+// Synopsis: Releases an interface
+//
+// Note: This is created in the stack so its reference count is ignored.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CServerSecurity::Release()
+{
+ ULONG lRef = _iRefCount - 1;
+
+ if (InterlockedDecrement( (long*) &_iRefCount ) == 0)
+ {
+ Win4Assert( !"Illegal release of IServerSecurity." );
+ delete this;
+ return 0;
+ }
+ else
+ {
+ return lRef;
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CServerSecurity::RevertToSelf, public
+//
+// Synopsis: If ImpersonateClient was called, then either ask RPC to
+// revert or NULL the thread token ourself.
+//
+//--------------------------------------------------------------------
+HRESULT CServerSecurity::RevertToSelf()
+{
+#ifdef _CHICAGO_
+ return S_OK;
+#else
+ HRESULT hr = RPC_S_OK;
+ RPC_STATUS sc;
+ BOOL fSuccess;
+
+ if (_iFlags & SS_IMPERSONATING)
+ {
+ // Ask win32 to revert for process local calls.
+ _iFlags &= ~SS_IMPERSONATING;
+ if (_iFlags & SS_PROCESS_LOCAL)
+ {
+ fSuccess = SetThreadToken( NULL, NULL );
+ if (!fSuccess)
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+ }
+
+ // Ask RPC to revert for process remote calls.
+ else
+ {
+ sc = RpcRevertToSelfEx( _pHandle );
+ if (sc != RPC_S_OK)
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, sc );
+ }
+ }
+ return hr;
+#endif
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: DefaultAuthnServices, private
+//
+// Synopsis: Register authentication services with RPC and build
+// a string array of authentication services and principal
+// names.
+//
+//--------------------------------------------------------------------
+HRESULT DefaultAuthnServices()
+{
+ HRESULT hr = S_OK;
+ DWORD i;
+ WCHAR *pPrincName = NULL;
+ DWORD lNameLen;
+ USHORT *pNextString;
+ DUALSTRINGARRAY *pOld;
+ DWORD cBinding = gServerSvcListLen ? gServerSvcListLen : 1;
+
+ ASSERT_LOCK_HELD
+
+ // Return if the security bindings are already computed.
+ if (!gDefaultService)
+ return S_OK;
+
+ // Only look up the current user name if the only security provider
+ // is not NTLMSSP since NTLMSSP doesn't do mutual auth.
+ if (gServerSvcListLen != 0 &&
+ (gServerSvcListLen != 1 || gServerSvcList[0] != RPC_C_AUTHN_WINNT))
+ {
+#ifndef _CHICAGO_
+ hr = LookupPrincName( &pPrincName );
+
+ if (SUCCEEDED(hr))
+ lNameLen = lstrlenW( pPrincName ) + 1;
+#else
+ hr = LookupPrincName( gServerSvcList, gServerSvcListLen, &pPrincName );
+ if (SUCCEEDED(hr))
+ lNameLen = lstrlenW( pPrincName ) + 1;
+ else
+ {
+ // BUGBUG: the whole PrincName mess still needs clean up
+ // especially given the state of msnsspc.dll
+ pPrincName = NULL;
+ hr = S_OK;
+ lNameLen = 1;
+ }
+#endif // _CHICAGO_
+ }
+ else
+ lNameLen = 1;
+
+ if (SUCCEEDED(hr))
+ {
+ // Allocate memory for the string array.
+ Win4Assert( gGotSecurityData );
+ pOld = gpsaSecurity;
+ gpsaSecurity = (DUALSTRINGARRAY *)
+ PrivMemAlloc( sizeof(DUALSTRINGARRAY) + 2 * sizeof(WCHAR) +
+ cBinding * (sizeof(SECURITYBINDING) +
+ lNameLen*sizeof(WCHAR)) );
+ if (gpsaSecurity != NULL)
+ {
+ // Fill in the array of security information. First two characters
+ // are NULLs to signal empty binding strings.
+ PrivMemFree( pOld );
+ gDefaultService = FALSE;
+ gpsaSecurity->wSecurityOffset = 2;
+ gpsaSecurity->aStringArray[0] = 0;
+ gpsaSecurity->aStringArray[1] = 0;
+ pNextString = &gpsaSecurity->aStringArray[2];
+
+ for (i = 0; i < gServerSvcListLen; i++)
+ {
+ // Ignore errors since applications using automatic security
+ // may not care if they can't receive secure calls.
+ hr = RpcServerRegisterAuthInfoW( pPrincName, gServerSvcList[i],
+ NULL, NULL );
+ if (hr == RPC_S_OK)
+ {
+ // Fill in authentication service, authorization service,
+ // and principal name.
+ *(pNextString++) = gServerSvcList[i];
+ *(pNextString++) = COM_C_AUTHZ_NONE;
+ if (pPrincName == NULL)
+ *pNextString = 0;
+ else
+ memcpy( pNextString, pPrincName, lNameLen*sizeof(USHORT) );
+ pNextString += lNameLen;
+ }
+ }
+
+ // Add a final NULL. Special case an empty list which requires
+ // two NULLs.
+ *(pNextString++) = 0;
+ if (gServerSvcListLen == 0)
+ *(pNextString++) = 0;
+ gpsaSecurity->wNumEntries = (USHORT)
+ (pNextString-gpsaSecurity->aStringArray);
+ hr = S_OK;
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ gpsaSecurity = pOld;
+ }
+ }
+
+ PrivMemFree( pPrincName );
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: FixupAccessControl, internal
+//
+// Synopsis: Get the access control class id. Instantiate the access
+// control class and load the data.
+//
+// Notes: The caller has already insured that the structure is
+// at least as big as a SPermissionHeader structure.
+//
+//--------------------------------------------------------------------
+HRESULT FixupAccessControl( SECURITY_DESCRIPTOR **pSD, DWORD cbSD )
+{
+ SPermissionHeader *pHeader;
+ IAccessControl *pControl = NULL;
+ IPersistStream *pPersist = NULL;
+ CNdrStream cStream( ((unsigned char *) *pSD) + sizeof(SPermissionHeader),
+ cbSD - sizeof(SPermissionHeader) );
+ HRESULT hr;
+
+ // Get the class id.
+ pHeader = (SPermissionHeader *) *pSD;
+
+ // Instantiate the class.
+ hr = CoCreateInstance( pHeader->gClass, NULL, CLSCTX_INPROC_SERVER,
+ IID_IAccessControl, (void **) &pControl );
+
+ // Get IPeristStream
+ if (SUCCEEDED(hr))
+ {
+ hr = pControl->QueryInterface( IID_IPersistStream, (void **) &pPersist );
+
+ // Load the stream.
+ if (SUCCEEDED(hr))
+ hr = pPersist->Load( &cStream );
+ }
+
+ // Release resources.
+ if (pPersist != NULL)
+ pPersist->Release();
+ if (SUCCEEDED(hr))
+ {
+ PrivMemFree( *pSD );
+ *pSD = (SECURITY_DESCRIPTOR *) pControl;
+ }
+ else if (pControl != NULL)
+ pControl->Release();
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: FixupSecurityDescriptor, internal
+//
+// Synopsis: Convert the security descriptor from self relative to
+// absolute form and check for errors.
+//
+//--------------------------------------------------------------------
+HRESULT FixupSecurityDescriptor( SECURITY_DESCRIPTOR **pSD, DWORD cbSD )
+{
+ // Fix up the security descriptor.
+ (*pSD)->Control &= ~SE_SELF_RELATIVE;
+ (*pSD)->Sacl = NULL;
+ if ((*pSD)->Dacl != NULL)
+ {
+ if (cbSD < sizeof(ACL) + sizeof(SECURITY_DESCRIPTOR) ||
+ (ULONG) (*pSD)->Dacl > cbSD - sizeof(ACL))
+ return REGDB_E_INVALIDVALUE;
+ (*pSD)->Dacl = (ACL *) (((char *) *pSD) + ((ULONG) (*pSD)->Dacl));
+ if ((*pSD)->Dacl->AclSize + sizeof(SECURITY_DESCRIPTOR) > cbSD)
+ return REGDB_E_INVALIDVALUE;
+ }
+
+ // Set up the owner and group SIDs.
+ if ((*pSD)->Group == 0 || ((ULONG) (*pSD)->Group) + sizeof(SID) > cbSD ||
+ (*pSD)->Owner == 0 || ((ULONG) (*pSD)->Owner) + sizeof(SID) > cbSD)
+ return REGDB_E_INVALIDVALUE;
+ (*pSD)->Group = (SID *) (((BYTE *) *pSD) + (ULONG) (*pSD)->Group);
+ (*pSD)->Owner = (SID *) (((BYTE *) *pSD) + (ULONG) (*pSD)->Owner);
+
+ // Check the security descriptor.
+#if DBG==1
+ if (!IsValidSecurityDescriptor( *pSD ))
+ return REGDB_E_INVALIDVALUE;
+#endif
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: GetLegacySecDesc, internal
+//
+// Synopsis: Get a security descriptor for the current app. First,
+// look under the app id for the current exe name. If that
+// fails look up the default descriptor. If that fails,
+// create one.
+//
+// Note: It is possible that the security descriptor size could change
+// during the size computation. Add code to retry.
+//
+//--------------------------------------------------------------------
+HRESULT GetLegacySecDesc( SECURITY_DESCRIPTOR **pSD, DWORD *pCapabilities )
+{
+ // Holds either Appid\{guid} or Appid\module_name.
+ WCHAR aKeyName[MAX_PATH+7];
+ HRESULT hr;
+ HKEY hKey = NULL;
+ DWORD lSize;
+ WCHAR aModule[MAX_PATH];
+ DWORD cModule;
+ DWORD i;
+ WCHAR aAppid[40]; // Hold a registry GUID.
+ DWORD lType;
+
+ // If the flag EOAC_APPID is set, the security descriptor contains the
+ // app id.
+ if ((*pCapabilities & EOAC_APPID) && *pSD != NULL)
+ {
+ if (StringFromIID2( *((GUID *) *pSD), aAppid, sizeof(aAppid) ) == 0)
+ return RPC_E_UNEXPECTED;
+ *pSD = NULL;
+
+ // Open the application id key. A GUID in the registry is stored.
+ // as a 38 character string.
+ lstrcpyW( aKeyName, L"AppID\\" );
+ memcpy( &aKeyName[6], aAppid, 39*sizeof(WCHAR) );
+ hr = RegOpenKeyEx( HKEY_CLASSES_ROOT, aKeyName,
+ NULL, KEY_READ, &hKey );
+
+ // Get the security descriptor from the registry.
+ if (hr == ERROR_SUCCESS)
+ hr = GetRegistrySecDesc( hKey, L"AccessPermission", pSD,
+ pCapabilities );
+ else
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, hr );
+
+ }
+
+ // Look up the app id from the exe name.
+ else
+ {
+ // Get the executable's name. Find the start of the file name.
+ cModule = GetModuleFileName( NULL, aModule, MAX_PATH );
+ if (cModule >= MAX_PATH)
+ {
+ Win4Assert( !"Module name too long." );
+ return RPC_E_UNEXPECTED;
+ }
+ for (i = cModule-1; i > 0; i--)
+ if (aModule[i] == '/' ||
+ aModule[i] == '\\' ||
+ aModule[i] == ':')
+ break;
+ if (i != 0)
+ i += 1;
+
+ // Open the key for the EXE's module name.
+ lstrcpyW( aKeyName, L"AppID\\" );
+ memcpy( &aKeyName[6], &aModule[i], (cModule - i + 1) * sizeof(WCHAR) );
+ hr = RegOpenKeyEx( HKEY_CLASSES_ROOT, aKeyName,
+ NULL, KEY_READ, &hKey );
+
+ // Look for an application id.
+ if (hr == ERROR_SUCCESS)
+ {
+ lSize = sizeof(aAppid);
+ hr = RegQueryValueEx( hKey, L"AppID", NULL, &lType,
+ (unsigned char *) &aAppid, &lSize );
+ RegCloseKey( hKey );
+ hKey = NULL;
+
+ // Open the application id key. A GUID in the registry is stored.
+ // as a 38 character string.
+ if (hr == ERROR_SUCCESS && lType == REG_SZ &&
+ lSize == 39*sizeof(WCHAR))
+ {
+ memcpy( &aKeyName[6], aAppid, 39*sizeof(WCHAR) );
+ hr = RegOpenKeyEx( HKEY_CLASSES_ROOT, aKeyName,
+ NULL, KEY_READ, &hKey );
+
+ // Get the security descriptor from the registry.
+ if (hr == ERROR_SUCCESS)
+ {
+ hr = GetRegistrySecDesc( hKey, L"AccessPermission", pSD,
+ pCapabilities );
+ if (SUCCEEDED(hr) || hr == REGDB_E_INVALIDVALUE)
+ goto cleanup;
+ RegCloseKey( hKey );
+ hKey = NULL;
+ }
+ }
+ }
+
+ // Open the default key.
+ hr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\OLE",
+ NULL, KEY_READ, &hKey );
+
+ // Get the security descriptor from the registry.
+ if (hr == ERROR_SUCCESS)
+ {
+ hr = GetRegistrySecDesc( hKey, L"DefaultAccessPermission", pSD,
+ pCapabilities );
+
+ // If that failed, make one.
+ if (FAILED(hr) && hr != REGDB_E_INVALIDVALUE)
+ hr = MakeSecDesc( pSD, pCapabilities );
+ }
+ else
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, hr );
+ }
+
+cleanup:
+
+ // Free the security descriptor memory if anything failed.
+ if (FAILED(hr))
+ {
+ PrivMemFree( *pSD );
+ *pSD = NULL;
+ }
+
+ // Close the registry key.
+ if (hKey != NULL)
+ RegCloseKey( hKey );
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: GetRegistrySecDesc, internal
+//
+// Synopsis: Convert a security descriptor from self relative to
+// absolute form. Stuff in an owner and a group.
+//
+// Notes:
+// REGDB_E_INVALIDVALUE is returned when there is something
+// at the specified value, but it is not a security descriptor.
+//
+// The caller must free the security descriptor in both the
+// success and failure cases.
+//
+// Codework: It would be nice to use the unicode APIs on NT.
+//
+//--------------------------------------------------------------------
+HRESULT GetRegistrySecDesc( HKEY hKey, WCHAR *pValue,
+ SECURITY_DESCRIPTOR **pSD, DWORD *pCapabilities )
+
+{
+ SID *pGroup;
+ SID *pOwner;
+ DWORD cbSD = 256;
+ DWORD lType;
+ HRESULT hr;
+ WORD wVersion;
+
+ // Guess how much memory to allocate for the security descriptor.
+ *pSD = (SECURITY_DESCRIPTOR *) PrivMemAlloc( cbSD );
+ if (*pSD == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto cleanup;
+ }
+
+ // Find put how much memory to allocate for the security
+ // descriptor.
+ hr = RegQueryValueEx( hKey, pValue, NULL, &lType,
+ (unsigned char *) *pSD, &cbSD );
+ if (hr != ERROR_SUCCESS && hr != ERROR_MORE_DATA)
+ {
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, hr );
+ goto cleanup;
+ }
+ if (lType != REG_BINARY || cbSD < sizeof(SECURITY_DESCRIPTOR))
+ {
+ hr = REGDB_E_INVALIDVALUE;
+ goto cleanup;
+ }
+
+ // If the first guess wasn't large enough, reallocate the memory.
+ if (hr == ERROR_MORE_DATA)
+ {
+ PrivMemFree( *pSD );
+ *pSD = (SECURITY_DESCRIPTOR *) PrivMemAlloc( cbSD );
+ if (*pSD == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto cleanup;
+ }
+
+ // Read the security descriptor.
+ hr = RegQueryValueEx( hKey, pValue, NULL, &lType,
+ (unsigned char *) *pSD, &cbSD );
+ if (hr != ERROR_SUCCESS)
+ {
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, hr );
+ goto cleanup;
+ }
+ if (lType != REG_BINARY || cbSD < sizeof(SECURITY_DESCRIPTOR))
+ {
+ hr = REGDB_E_INVALIDVALUE;
+ goto cleanup;
+ }
+ }
+
+ // Check the first DWORD to determine what type of data is in the
+ // registry value.
+ wVersion = *((WORD *) *pSD);
+#ifndef _CHICAGO_
+ if (wVersion == COM_PERMISSION_SECDESC)
+ hr = FixupSecurityDescriptor( pSD, cbSD );
+ else
+#endif
+ if (wVersion == COM_PERMISSION_ACCCTRL)
+ {
+ hr = FixupAccessControl( pSD, cbSD );
+ if (SUCCEEDED(hr))
+ *pCapabilities |= EOAC_ACCESS_CONTROL;
+ }
+ else
+ hr = REGDB_E_INVALIDVALUE;
+
+cleanup:
+ if (FAILED(hr))
+ {
+ PrivMemFree( *pSD );
+ *pSD = NULL;
+ }
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: HashSid
+//
+// Synopsis: Create a 32 bit hash of a SID.
+//
+//--------------------------------------------------------------------
+DWORD HashSid( SID *pSid )
+{
+ DWORD lHash = 0;
+ DWORD cbSid = GetLengthSid( pSid );
+ DWORD i;
+ unsigned char *pData = (unsigned char *) pSid;
+
+ for (i = 0; i < cbSid; i++)
+ lHash = (lHash << 1) + *pData++;
+ return lHash;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: InitializeSecurity, internal
+//
+// Synopsis: Called the first time the channel is used. If the app
+// has not initialized security yet, this function sets
+// up legacy security.
+//
+//--------------------------------------------------------------------
+HRESULT InitializeSecurity()
+{
+ HRESULT hr;
+ ASSERT_LOCK_HELD
+
+ // Return if already initialized.
+ if (gpsaSecurity != NULL)
+ return S_OK;
+
+ // Initialize. All parameters are ignored except the security descriptor
+ // since the capability is set to app id.
+ hr = CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE,
+ RPC_C_IMP_LEVEL_IDENTIFY, NULL, EOAC_APPID,
+ NULL );
+
+ // Convert confusing error codes.
+ if (hr == E_INVALIDARG)
+ hr = REGDB_E_INVALIDVALUE;
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: IsCallerLocalSystem
+//
+// Synopsis: Impersonate the caller and do an ACL check. The first
+// time this function is called, create the ACL
+//
+//--------------------------------------------------------------------
+BOOL IsCallerLocalSystem()
+{
+ HRESULT hr = S_OK;
+ DWORD granted_access;
+ BOOL access;
+ HANDLE token;
+ DWORD privilege_size = sizeof(gPriv);
+ BOOL success;
+ SECURITY_DESCRIPTOR *pSecDesc = NULL;
+ DWORD lIgnore;
+
+ ASSERT_LOCK_RELEASED
+
+ // If the security descriptor does not exist, create it.
+ if (gRundownSD == NULL)
+ {
+ // Make the security descriptor.
+ hr = MakeSecDesc( &pSecDesc, &lIgnore );
+
+ // Save the security descriptor.
+ LOCK
+ if (gRundownSD == NULL)
+ gRundownSD = pSecDesc;
+ else
+ PrivMemFree( pSecDesc );
+ UNLOCK
+ }
+
+ // Impersonate.
+ if (SUCCEEDED(hr))
+ hr = CoImpersonateClient();
+
+ // Get the thread token.
+ if (SUCCEEDED(hr))
+ {
+ success = OpenThreadToken( GetCurrentThread(), TOKEN_READ,
+ TRUE, &token );
+ if (!success)
+ hr = E_FAIL;
+ }
+
+ // Check access.
+ if (SUCCEEDED(hr))
+ {
+ success = AccessCheck( gRundownSD, token, COM_RIGHTS_EXECUTE,
+ &gMap, &gPriv, &privilege_size,
+ &granted_access, &access );
+ if (!success || !access)
+ hr = E_FAIL;
+ CloseHandle( token );
+ }
+
+ // Just call revert since it detects whether or not the impersonate
+ // succeeded.
+ CoRevertToSelf();
+
+ ASSERT_LOCK_RELEASED
+
+ return SUCCEEDED(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: IsLocalAuthnService
+//
+// Synopsis: Return TRUE is the specified authentication service is
+// on the list of services this machine supports.
+//
+// NOTE: If we ever expect the list to be more then three items
+// long, we can add code to sort it.
+//
+//--------------------------------------------------------------------
+BOOL IsLocalAuthnService( USHORT wAuthnService )
+{
+ DWORD l;
+
+ for (l = 0; l < gClientSvcListLen; l++)
+ if (gClientSvcList[l] == wAuthnService)
+ return TRUE;
+ return FALSE;
+}
+
+#ifndef _CHICAGO_
+//+-------------------------------------------------------------------
+//
+// Function: LookupPrincName, private
+//
+// Synopsis: Open the process token and find the user's name.
+//
+//--------------------------------------------------------------------
+HRESULT LookupPrincName( WCHAR **pPrincName )
+{
+ HRESULT hr = S_OK;
+ BYTE aMemory[SIZEOF_TOKEN_USER];
+ TOKEN_USER *pTokenUser = (TOKEN_USER *) &aMemory;
+ HANDLE hToken = NULL;
+ DWORD lIgnore;
+ DWORD lNameLen = 80;
+ DWORD lDomainLen = 80;
+ WCHAR *pDomainName = NULL;
+ SID_NAME_USE sIgnore;
+ BOOL fSuccess;
+
+ // Open the process's token.
+ *pPrincName = NULL;
+ if (OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ))
+ {
+
+ // Lookup SID of process token.
+ if (GetTokenInformation( hToken, TokenUser, pTokenUser, sizeof(aMemory),
+ &lIgnore ))
+ {
+ // Preallocate some memory.
+ *pPrincName = (WCHAR *) PrivMemAlloc( lNameLen*sizeof(WCHAR) );
+ pDomainName = (WCHAR *) _alloca( lDomainLen*sizeof(WCHAR) );
+ if (*pPrincName != NULL && pDomainName != NULL)
+ {
+
+ // Find the user's name.
+ fSuccess = LookupAccountSidW( NULL, pTokenUser->User.Sid,
+ *pPrincName, &lNameLen,
+ pDomainName, &lDomainLen,
+ &sIgnore );
+
+ // If the call failed, try allocating more memory.
+ if (!fSuccess)
+ {
+
+ // Allocate memory for the user's name.
+ PrivMemFree( *pPrincName );
+ *pPrincName = (WCHAR *) PrivMemAlloc( lNameLen*sizeof(WCHAR) );
+ pDomainName = (WCHAR *) _alloca( lDomainLen*sizeof(WCHAR) );
+ if (*pPrincName != NULL && pDomainName != NULL)
+ {
+
+ // Find the user's name.
+ if (!LookupAccountSidW( NULL, pTokenUser->User.Sid,
+ *pPrincName, &lNameLen, pDomainName,
+ &lDomainLen, &sIgnore ))
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+ CloseHandle( hToken );
+ }
+ else
+ {
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+#if DBG==1
+ Win4Assert( !"Why did OpenProcessToken fail?" );
+ OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken );
+#endif
+ }
+
+ if (hr != S_OK)
+ {
+ PrivMemFree( *pPrincName );
+ *pPrincName = NULL;
+ }
+ return hr;
+}
+#else // _CHICAGO_
+//+-------------------------------------------------------------------
+//
+// Function: LookupPrincName, private
+//
+// Synopsis: We have a service other than NTLMSSP.
+// Find the first (!) such and find the user's name.
+//
+// BUGBUG: This is a hack until the principal name issue is properly
+// sorted out.
+//
+//--------------------------------------------------------------------
+HRESULT LookupPrincName(
+ USHORT *pwAuthnServices,
+ ULONG cAuthnServices,
+ WCHAR **pPrincName
+ )
+{
+ // assume failure lest thou be disappointed
+ RPC_STATUS status = RPC_S_INVALID_AUTH_IDENTITY;
+
+ *pPrincName = NULL;
+
+ for (ULONG i = 0; i < cAuthnServices; i++)
+ {
+ if (pwAuthnServices[i] != RPC_C_AUTHN_WINNT)
+ {
+ status = RpcServerInqDefaultPrincNameW(
+ pwAuthnServices[i],
+ pPrincName);
+ if (status == RPC_S_OK)
+ {
+ break;
+ }
+ }
+ }
+
+ return HRESULT_FROM_WIN32(status);
+}
+
+#endif // _CHICAGO_
+
+#ifdef _CHICAGO_
+//+-------------------------------------------------------------------
+//
+// Function: MakeSecDesc, private
+//
+// Synopsis: Make an access control that allows the current user
+// access.
+//
+// NOTE: NetWkstaGetInfo does not return the size needed unless the size
+// in is zero.
+//
+//--------------------------------------------------------------------
+HRESULT MakeSecDesc( SECURITY_DESCRIPTOR **pSD, DWORD *pCapabilities )
+{
+ HRESULT hr = S_OK;
+ IAccessControl *pAccess = NULL;
+ DWORD cTrustee;
+ WCHAR *pTrusteeW;
+ char *pTrusteeA;
+ DWORD cDomain;
+ DWORD cUser;
+ char *pBuffer;
+ struct wksta_info_10 *wi10;
+ USHORT cbBuffer;
+ HINSTANCE hMsnet;
+ NetWkstaGetInfoFn fnNetWkstaGetInfo;
+ ACTRL_ACCESSW sAccessList;
+ ACTRL_PROPERTY_ENTRYW sProperty;
+ ACTRL_ACCESS_ENTRY_LISTW sEntryList;
+ ACTRL_ACCESS_ENTRYW sEntry;
+
+ // Load msnet32.dll
+ hMsnet = LoadLibraryA( "msnet32.dll" );
+ if (hMsnet == NULL)
+ return MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+
+ // Get the function NetWkstaGetInfo.
+ fnNetWkstaGetInfo = (NetWkstaGetInfoFn) GetProcAddress( hMsnet,
+ (char *) 57 );
+ if (fnNetWkstaGetInfo == NULL)
+ {
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+ goto cleanup;
+ }
+
+ // Find out how much space to allocate for the domain and user names.
+ cbBuffer = 0;
+ fnNetWkstaGetInfo( NULL, 10, NULL, 0, &cbBuffer );
+ pBuffer = (char *) _alloca( cbBuffer );
+
+ // Get the domain and user names.
+ hr = fnNetWkstaGetInfo( NULL, 10, pBuffer, cbBuffer, &cbBuffer );
+ if (hr != 0)
+ {
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, hr );
+ goto cleanup;
+ }
+
+ // Stick the user name and domain name in the same string.
+ wi10 = (struct wksta_info_10 *) pBuffer;
+ Win4Assert( wi10->wki10_logon_domain != NULL );
+ Win4Assert( wi10->wki10_username != NULL );
+ cDomain = lstrlenA( wi10->wki10_logon_domain );
+ cUser = lstrlenA( wi10->wki10_username );
+ pTrusteeA = (char *) _alloca( cDomain+cUser+2 );
+ lstrcpyA( pTrusteeA, wi10->wki10_logon_domain );
+ lstrcpyA( &pTrusteeA[cDomain+1], wi10->wki10_username );
+ pTrusteeA[cDomain] = '\\';
+
+ // Find out how long the name is in Unicode.
+ cTrustee = MultiByteToWideChar( GetConsoleCP(), 0, pTrusteeA,
+ cDomain+cUser+2, NULL, 0 );
+
+ // Convert the name to Unicode.
+ pTrusteeW = (WCHAR *) _alloca( cTrustee * sizeof(WCHAR) );
+ if (!MultiByteToWideChar( GetConsoleCP(), 0, pTrusteeA,
+ cDomain+cUser+2, pTrusteeW, cTrustee ))
+ {
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+ goto cleanup;
+ }
+
+ // Create an AccessControl.
+ *pSD = NULL;
+ hr = CoCreateInstance( CLSID_DCOMAccessControl, NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_IAccessControl, (void **) &pAccess );
+ if (FAILED(hr))
+ goto cleanup;
+
+ // Give the current user access.
+ sAccessList.cEntries = 1;
+ sAccessList.pPropertyAccessList = &sProperty;
+ sProperty.lpProperty = NULL;
+ sProperty.pAccessEntryList = &sEntryList;
+ sProperty.fListFlags = 0;
+ sEntryList.cEntries = 1;
+ sEntryList.pAccessList = &sEntry;
+ sEntry.fAccessFlags = ACTRL_ACCESS_ALLOWED;
+ sEntry.Access = COM_RIGHTS_EXECUTE;
+ sEntry.ProvSpecificAccess = 0;
+ sEntry.Inheritance = NO_INHERITANCE;
+ sEntry.lpInheritProperty = NULL;
+ sEntry.Trustee.pMultipleTrustee = NULL;
+ sEntry.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
+ sEntry.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
+ sEntry.Trustee.TrusteeType = TRUSTEE_IS_USER;
+ sEntry.Trustee.ptstrName = pTrusteeW;
+ hr = pAccess->GrantAccessRights( &sAccessList );
+
+cleanup:
+ FreeLibrary( hMsnet );
+ if (SUCCEEDED(hr))
+ {
+ *pSD = (SECURITY_DESCRIPTOR *) pAccess;
+ *pCapabilities |= EOAC_ACCESS_CONTROL;
+ }
+ else if (pAccess != NULL)
+ pAccess->Release();
+ return hr;
+}
+
+#else
+//+-------------------------------------------------------------------
+//
+// Function: MakeSecDesc, private
+//
+// Synopsis: Make a security descriptor that allows the current user
+// and local system access.
+//
+// NOTE: Compute the length of the sids used rather then using constants.
+//
+//--------------------------------------------------------------------
+HRESULT MakeSecDesc( SECURITY_DESCRIPTOR **pSD, DWORD *pCapabilities )
+{
+ HRESULT hr = S_OK;
+ ACL *pAcl;
+ DWORD lSidLen;
+ SID *pGroup;
+ SID *pOwner;
+ BYTE aMemory[SIZEOF_TOKEN_USER];
+ TOKEN_USER *pTokenUser = (TOKEN_USER *) &aMemory;
+ HANDLE hToken = NULL;
+ DWORD lIgnore;
+ HANDLE hThread;
+
+ Win4Assert( *pSD == NULL );
+
+ // Open the process's token.
+ if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ))
+ {
+ // If the thread has a token, remove it and try again.
+ if (!OpenThreadToken( GetCurrentThread(), TOKEN_IMPERSONATE, TRUE,
+ &hThread ))
+ {
+ Win4Assert( !"How can both OpenThreadToken and OpenProcessToken fail?" );
+ return MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+ }
+ if (!SetThreadToken( NULL, NULL ))
+ {
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+ CloseHandle( hThread );
+ return hr;
+ }
+ if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ))
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+ SetThreadToken( NULL, hThread );
+ CloseHandle( hThread );
+ if (FAILED(hr))
+ return hr;
+ }
+
+ // Lookup SID of process token.
+ if (!GetTokenInformation( hToken, TokenUser, pTokenUser, sizeof(aMemory),
+ &lIgnore ))
+ goto last_error;
+
+ // Compute the length of the SID.
+ lSidLen = GetLengthSid( pTokenUser->User.Sid );
+ Win4Assert( lSidLen <= SIZEOF_SID );
+
+ // Allocate the security descriptor.
+ *pSD = (SECURITY_DESCRIPTOR *) PrivMemAlloc(
+ sizeof(SECURITY_DESCRIPTOR) + 2*lSidLen + SIZEOF_ACL );
+ if (*pSD == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto cleanup;
+ }
+ pGroup = (SID *) (*pSD + 1);
+ pOwner = (SID *) (((BYTE *) pGroup) + lSidLen);
+ pAcl = (ACL *) (((BYTE *) pOwner) + lSidLen);
+
+ // Initialize a new security descriptor.
+ if (!InitializeSecurityDescriptor(*pSD, SECURITY_DESCRIPTOR_REVISION))
+ goto last_error;
+
+ // Initialize a new ACL.
+ if (!InitializeAcl(pAcl, SIZEOF_ACL, ACL_REVISION2))
+ goto last_error;
+
+ // Allow the current user access.
+ if (!AddAccessAllowedAce( pAcl, ACL_REVISION2, COM_RIGHTS_EXECUTE,
+ pTokenUser->User.Sid))
+ goto last_error;
+
+ // Allow local system access.
+ if (!AddAccessAllowedAce( pAcl, ACL_REVISION2, COM_RIGHTS_EXECUTE,
+ (void *) &LOCAL_SYSTEM_SID ))
+ goto last_error;
+
+ // Add a new ACL to the security descriptor.
+ if (!SetSecurityDescriptorDacl( *pSD, TRUE, pAcl, FALSE ))
+ goto last_error;
+
+ // Set the group.
+ memcpy( pGroup, pTokenUser->User.Sid, lSidLen );
+ if (!SetSecurityDescriptorGroup( *pSD, pGroup, FALSE ))
+ goto last_error;
+
+ // Set the owner.
+ memcpy( pOwner, pTokenUser->User.Sid, lSidLen );
+ if (!SetSecurityDescriptorOwner( *pSD, pOwner, FALSE ))
+ goto last_error;
+
+ // Check the security descriptor.
+#if DBG==1
+ if (!IsValidSecurityDescriptor( *pSD ))
+ {
+ Win4Assert( !"COM Created invalid security descriptor." );
+ goto last_error;
+ }
+#endif
+
+ goto cleanup;
+last_error:
+ hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, GetLastError() );
+
+cleanup:
+ if (hToken != NULL)
+ CloseHandle( hToken );
+ if (FAILED(hr))
+ {
+ PrivMemFree( *pSD );
+ *pSD = NULL;
+ }
+ return hr;
+}
+#endif
+
+//+-------------------------------------------------------------------
+//
+// Function: RegisterAuthnServices, public
+//
+// Synopsis: Register the specified services. Build a security
+// binding.
+//
+//--------------------------------------------------------------------
+HRESULT RegisterAuthnServices( DWORD cAuthSvc,
+ SOLE_AUTHENTICATION_SERVICE *asAuthSvc )
+{
+ DWORD i;
+ RPC_STATUS sc;
+ USHORT wNumEntries = 0;
+ USHORT *pNext;
+ HRESULT hr;
+ DWORD lNameLen;
+
+ ASSERT_LOCK_HELD
+
+ // Register all the authentication services specified.
+ for (i = 0; i < cAuthSvc; i++)
+ {
+ sc = RpcServerRegisterAuthInfoW( asAuthSvc[i].pPrincipalName,
+ asAuthSvc[i].dwAuthnSvc,
+ NULL, NULL );
+
+ // If the registration failed, store the failure code.
+ if (sc != RPC_S_OK)
+ asAuthSvc[i].hr = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, sc );
+
+ // Otherwise determine how much space to reserve for it in the string
+ // array.
+ else
+ {
+ asAuthSvc[i].hr = S_OK;
+ if (asAuthSvc[i].pPrincipalName != NULL)
+ wNumEntries += lstrlenW( asAuthSvc[i].pPrincipalName ) + 3;
+ else
+ wNumEntries += 3;
+ }
+ }
+ if (wNumEntries == 0)
+ hr = RPC_E_NO_GOOD_SECURITY_PACKAGES;
+ else
+ // make room for the two NULLs that placehold for the empty
+ // string binding and the trailing NULL.
+ wNumEntries += 3;
+
+ // If some services were registered, build a string array.
+ if (wNumEntries != 0)
+ {
+ gpsaSecurity = (DUALSTRINGARRAY *) PrivMemAlloc(
+ wNumEntries*sizeof(USHORT) + sizeof(DUALSTRINGARRAY) );
+ if (gpsaSecurity == NULL)
+ hr = E_OUTOFMEMORY;
+ else
+ {
+ gpsaSecurity->wNumEntries = wNumEntries;
+ gpsaSecurity->wSecurityOffset = 2;
+ gpsaSecurity->aStringArray[0] = 0;
+ gpsaSecurity->aStringArray[1] = 0;
+ pNext = &gpsaSecurity->aStringArray[2];
+
+ for (i = 0; i < cAuthSvc; i++)
+ {
+ if (asAuthSvc[i].hr == S_OK)
+ {
+ // Fill in authentication service, authorization service,
+ // and principal name.
+ *(pNext++) = (USHORT) asAuthSvc[i].dwAuthnSvc;
+ *(pNext++) = (USHORT) (asAuthSvc[i].dwAuthzSvc == 0 ?
+ COM_C_AUTHZ_NONE :
+ asAuthSvc[i].dwAuthzSvc);
+ if (asAuthSvc[i].pPrincipalName != NULL)
+ {
+ lNameLen = lstrlenW( asAuthSvc[i].pPrincipalName ) + 1;
+ memcpy( pNext, asAuthSvc[i].pPrincipalName,
+ lNameLen*sizeof(USHORT) );
+ pNext += lNameLen;
+ }
+ else
+ *(pNext++) = 0;
+ }
+ }
+ *pNext = 0;
+
+ hr = S_OK;
+ }
+ }
+
+ ASSERT_LOCK_HELD
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: SetAuthnService, internal
+//
+// Synopsis: Determine the authentication information to set on a
+// binding handle for a newly unmarshalled interface.
+// The authentication level is the higher of the process
+// default and the level in the interface. The
+// impersonation level is the process default. If the
+// authentication level is not zero, the function
+// scans the list of authentication services in the
+// interface looking for one this machine supports.
+//
+//--------------------------------------------------------------------
+HRESULT SetAuthnService( handle_t hHandle, OXID_INFO *pOxidInfo,
+ OXIDEntry *pOxid )
+{
+ DWORD lAuthnLevel;
+ DWORD lAuthnSvc;
+ USHORT wNext;
+ USHORT wAuthzSvc;
+ RPC_STATUS sc;
+ WCHAR *pPrincipal;
+ RPC_SECURITY_QOS sQos;
+
+ // Pick the highest authentication level between the process default
+ // and the interface hint. The constant RPC_C_AUTHN_LEVEL_DEFAULT
+ // has value zero and maps to connect.
+ if (gAuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
+ lAuthnLevel = RPC_C_AUTHN_LEVEL_CONNECT;
+ else
+ lAuthnLevel = gAuthnLevel;
+ if (pOxidInfo->dwAuthnHint == RPC_C_AUTHN_LEVEL_DEFAULT)
+ pOxidInfo->dwAuthnHint = RPC_C_AUTHN_LEVEL_CONNECT;
+ if (lAuthnLevel > pOxidInfo->dwAuthnHint)
+ lAuthnLevel = gAuthnLevel;
+ else
+ lAuthnLevel = pOxidInfo->dwAuthnHint;
+
+ // For machine local servers, only set the authentication information if
+ // the impersonation level is not the default.
+ sQos.Version = RPC_C_SECURITY_QOS_VERSION;
+ sQos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
+ sQos.ImpersonationType = gImpLevel;
+ sQos.Capabilities = (gCapabilities & EOAC_MUTUAL_AUTH) ?
+ RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH : RPC_C_QOS_CAPABILITIES_DEFAULT;
+ if (pOxid->dwFlags & OXIDF_MACHINE_LOCAL)
+ {
+ if (gImpLevel != RPC_C_IMP_LEVEL_IMPERSONATE)
+ {
+ sc = RpcBindingSetAuthInfoExW( hHandle, NULL, lAuthnLevel,
+ RPC_C_AUTHN_WINNT, NULL,
+ RPC_C_AUTHZ_NONE, &sQos );
+ if (sc != RPC_S_OK)
+ return MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, sc );
+ else
+ return S_OK;
+ }
+ }
+
+ // For machine remote servers, set the authentication information if any
+ // parameter differs from RPC's default.
+ else if (lAuthnLevel != RPC_C_AUTHN_LEVEL_NONE)
+ {
+ // Look through all the authentication services in the interface
+ // till we find one that works on this machine.
+ wNext = pOxidInfo->psa->wSecurityOffset;
+ while (wNext < pOxidInfo->psa->wNumEntries &&
+ pOxidInfo->psa->aStringArray[wNext] != 0)
+ {
+ if (IsLocalAuthnService( pOxidInfo->psa->aStringArray[wNext] ))
+ {
+ // Set the authentication info on the binding handle.
+ pPrincipal = &pOxidInfo->psa->aStringArray[wNext+2];
+ if (pPrincipal[0] == 0)
+ pPrincipal = NULL;
+
+#ifdef _CHICAGO_
+ // If the principal name is not known, the server must be
+ // NT. Replace the principal name in that case
+ // because a NULL principal name is a flag for some
+ // Chicago security hack.
+ if (pPrincipal == NULL &&
+ pOxidInfo->psa->aStringArray[wNext] == RPC_C_AUTHN_WINNT)
+ pPrincipal = L"Default";
+#endif // _CHICAGO_
+
+ wAuthzSvc = pOxidInfo->psa->aStringArray[wNext+1];
+ if (wAuthzSvc == COM_C_AUTHZ_NONE)
+ wAuthzSvc = RPC_C_AUTHZ_NONE;
+ sc = RpcBindingSetAuthInfoExW(
+ hHandle,
+ pPrincipal,
+ lAuthnLevel,
+ pOxidInfo->psa->aStringArray[wNext],
+ NULL,
+ wAuthzSvc,
+ &sQos );
+ if (sc != RPC_S_OK)
+ return MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, sc );
+ else
+ return S_OK;
+ }
+
+ // Skip to the next authentication service.
+ wNext += lstrlenW( &pOxidInfo->psa->aStringArray[wNext] ) + 1;
+ }
+
+ // No valid authentication service was found. This is an error.
+ return RPC_E_NO_GOOD_SECURITY_PACKAGES;
+ }
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: UninitializeSecurity, internal
+//
+// Synopsis: Free resources allocated while initializing security.
+//
+//--------------------------------------------------------------------
+void UninitializeSecurity()
+{
+ DWORD i;
+
+ ASSERT_LOCK_HELD
+
+ PrivMemFree(gSecDesc);
+ PrivMemFree(gpsaSecurity);
+ PrivMemFree( gRundownSD );
+#ifndef SHRMEM_OBJEX
+ MIDL_user_free( gClientSvcList );
+ MIDL_user_free( gServerSvcList );
+ MIDL_user_free( gLegacySecurity );
+#else // SHRMEM_OBJEX
+ delete [] gClientSvcList;
+ delete [] gServerSvcList;
+ delete [] gLegacySecurity;
+#endif // SHRMEM_OBJEX
+ for (i = 0; i < ACCESS_CACHE_LEN; i++)
+ {
+ PrivMemFree( gAccessCache[i] );
+ gAccessCache[i] = NULL;
+ }
+
+ if (gAccessControl != NULL)
+ gAccessControl->Release();
+
+ gAccessControl = NULL;
+ gSecDesc = NULL;
+ gAuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
+ gImpLevel = RPC_C_IMP_LEVEL_IDENTIFY;
+ gCapabilities = EOAC_NONE;
+ gLegacySecurity = NULL;
+ gpsaSecurity = NULL;
+ gClientSvcList = NULL;
+ gServerSvcList = NULL;
+ gGotSecurityData = FALSE;
+ gRundownSD = NULL;
+ gDefaultService = FALSE;
+ gMostRecentAccess = 0;
+}
+
+#endif
diff --git a/private/ole32/com/dcomrem/security.hxx b/private/ole32/com/dcomrem/security.hxx
new file mode 100644
index 000000000..96b48f760
--- /dev/null
+++ b/private/ole32/com/dcomrem/security.hxx
@@ -0,0 +1,239 @@
+//+-------------------------------------------------------------------
+//
+// File: security.hxx
+//
+// Contents: Classes for channel security
+//
+// Classes: CClientSecurity, CServerSecurity
+//
+// History: 11 Oct 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+#ifndef _SECURITY_HXX_
+#define _SECURITY_HXX_
+
+#include <chancont.hxx>
+
+//+----------------------------------------------------------------
+// Typedefs.
+typedef enum
+{
+ SS_PROCESS_LOCAL = 0x1, // Client and server are in same process
+ SS_CALL_DONE = 0x2, // Call is complete, fail new calls to impersonate
+ SS_IMPERSONATING = 0x4 // Server has called impersonate
+} EServerSecurity;
+
+//+----------------------------------------------------------------
+//
+// Class: CClientSecurity, public
+//
+// Purpose: Provides security for proxies
+//
+//-----------------------------------------------------------------
+
+class CStdIdentity;
+
+class CClientSecurity : public IClientSecurity
+{
+ public:
+ CClientSecurity( CStdIdentity *pId ) { _pStdId = pId; }
+ ~CClientSecurity() {}
+
+ STDMETHOD (QueryBlanket)
+ (
+ IUnknown *pProxy,
+ DWORD *pAuthnSvc,
+ DWORD *pAuthzSvc,
+ OLECHAR **pServerPrincName,
+ DWORD *pAuthnLevel,
+ DWORD *pImpLevel,
+ void **pAuthInfo,
+ DWORD *pCapabilities
+ );
+
+ STDMETHOD (SetBlanket)
+ (
+ IUnknown *pProxy,
+ DWORD AuthnSvc,
+ DWORD AuthzSvc,
+ OLECHAR *ServerPrincName,
+ DWORD AuthnLevel,
+ DWORD ImpLevel,
+ void *pAuthInfo,
+ DWORD Capabilities
+ );
+
+ STDMETHOD (CopyProxy)
+ (
+ IUnknown *pProxy,
+ IUnknown **ppCopy
+ );
+
+ private:
+ CStdIdentity *_pStdId;
+};
+
+//+----------------------------------------------------------------
+//
+// Class: CServerSecurity, public
+//
+// Purpose: Provides security for stubs
+//
+//-----------------------------------------------------------------
+
+class CRpcChannelBuffer;
+
+class CServerSecurity : public IServerSecurity
+{
+ public:
+ CServerSecurity( CChannelCallInfo * );
+ CServerSecurity();
+ ~CServerSecurity() {}
+
+ STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) ( void );
+ STDMETHOD_(ULONG,Release) ( void );
+ STDMETHOD (QueryBlanket)
+ (
+ DWORD *pAuthnSvc,
+ DWORD *pAuthzSvc,
+ OLECHAR **pServerPrincName,
+ DWORD *pAuthnLevel,
+ DWORD *pImpLevel,
+ void **pPrivs,
+ DWORD *pCapabilities
+ );
+ STDMETHOD (ImpersonateClient)( void );
+ STDMETHOD (RevertToSelf) ( void );
+ STDMETHOD_(BOOL,IsImpersonating) (void);
+
+ void EndCall();
+
+ private:
+ DWORD _iRefCount;
+ DWORD _iFlags; // See EServerSecurity
+ handle_t *_pHandle; // RPC server handle of call
+ CRpcChannelBuffer *_pChannel; // Channel of call
+};
+
+//+----------------------------------------------------------------
+// Prototypes.
+RPC_STATUS CheckAccessControl ( RPC_IF_HANDLE pIid, void *pContext );
+RPC_STATUS CheckAcl ( RPC_IF_HANDLE pIid, void *pContext );
+HRESULT DefaultAuthnServices();
+HRESULT InitializeSecurity ();
+BOOL IsCallerLocalSystem ();
+HRESULT SetAuthnService ( handle_t, OXID_INFO *, OXIDEntry * );
+void UninitializeSecurity();
+
+struct IAccessControl;
+
+extern IAccessControl *gAccessControl;
+extern DWORD gAuthnLevel;
+extern DWORD gCapabilities;
+extern USHORT *gClientSvcList;
+extern DWORD gClientSvcListLen;
+extern BOOL gDisableDCOM;
+extern BOOL gGotSecurityData;
+extern DWORD gImpLevel;
+extern SECURITYBINDING *gLegacySecurity;
+extern DUALSTRINGARRAY *gpsaSecurity;
+extern SECURITY_DESCRIPTOR *gSecDesc;
+extern USHORT *gServerSvcList;
+extern DWORD gServerSvcListLen;
+extern BOOL gSetAuth;
+
+
+//+-------------------------------------------------------------------
+//
+// Function: GetCallAuthnLevel, public
+//
+// Synopsis: Get the authentication level of the current call from TLS.
+// If no calls are in progress and the level has not been
+// set on this thread, use the process default instead.
+//
+//--------------------------------------------------------------------
+inline DWORD GetCallAuthnLevel()
+{
+ COleTls tls;
+ DWORD lAuthnLevel = tls->dwAuthnLevel;
+ if (lAuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
+ {
+ lAuthnLevel = tls->dwAuthnLevel = gAuthnLevel;
+ }
+ return lAuthnLevel;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: ResumeImpersonate
+//
+// Synopsis: Query the context object for IServerSecurity. If the
+// resume flag is set, call ImpersonateClient.
+//
+//--------------------------------------------------------------------
+inline void ResumeImpersonate( IUnknown *pContext, BOOL fResume )
+{
+ IServerSecurity *pServer;
+ HRESULT result;
+
+ if (pContext != NULL && fResume)
+ {
+ result = pContext->QueryInterface( IID_IServerSecurity,
+ (void **) &pServer );
+ if (SUCCEEDED(result))
+ {
+ pServer->ImpersonateClient();
+ pServer->Release();
+ }
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: SuspendImpersonate
+//
+// Synopsis: Query the context for IServerSecurity. If found,
+// check to see if the call is impersonated. If it is,
+// set pResume TRUE and call RevertToSelf.
+//
+//--------------------------------------------------------------------
+inline void SuspendImpersonate( IUnknown *pContext, BOOL *pResume )
+{
+ IServerSecurity *pServer;
+ HRESULT result;
+
+ *pResume = FALSE;
+ if (pContext != NULL)
+ {
+ result = pContext->QueryInterface( IID_IServerSecurity,
+ (void **) &pServer );
+ if (SUCCEEDED(result))
+ {
+ *pResume = pServer->IsImpersonating();
+ if (*pResume)
+ pServer->RevertToSelf();
+ pServer->Release();
+ }
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: GetAclFn()
+//
+// Synopsis: If automatic security is turned on and the level is
+// not none, return the function to do ACL checking.
+// Otherwise return NULL.
+//
+//--------------------------------------------------------------------
+inline RPC_IF_CALLBACK_FN *GetAclFn()
+{
+ if (gSecDesc != NULL)
+ return CheckAcl;
+ else if (gAccessControl != NULL)
+ return CheckAccessControl;
+ else
+ return NULL;
+}
+#endif
diff --git a/private/ole32/com/dcomrem/service.cxx b/private/ole32/com/dcomrem/service.cxx
new file mode 100644
index 000000000..6b3f2f580
--- /dev/null
+++ b/private/ole32/com/dcomrem/service.cxx
@@ -0,0 +1,818 @@
+//+-------------------------------------------------------------------
+//
+// File: service.cxx
+//
+// Contents: APIs to simplify RPC setup
+//
+// Functions:
+//
+// History: 23-Nov-92 Rickhi
+// 20-Feb-95 Rickhi Major Simplification for DCOM
+//
+//--------------------------------------------------------------------
+#include <ole2int.h>
+#include <service.hxx> // CRpcService
+#include <orcb.h> // IOrCallback
+#include <malloc.hxx> // MIDL_user_allocate
+#include <locks.hxx> // LOCK/UNLOCK etc
+#include <ipidtbl.hxx> // GetLocalEntry
+#include <security.hxx> // gpsaSecurity
+#include <channelb.hxx> // gRemUnknownIf
+
+
+BOOL gSpeedOverMem = FALSE; // Trade memory for speed.
+BOOL gfListening = FALSE; // Server is/isn't listening
+BOOL gfDefaultStrings = FALSE; // Using precomputed string bindings
+BOOL gfLrpc = FALSE; // Registered for ncalrpc
+#ifdef _CHICAGO_
+BOOL gfMswmsg = FALSE; // Registered for mswmsg
+#endif
+
+DWORD gdwEndPoint = 0;
+DWORD gdwPsaMaxSize = 0;
+DUALSTRINGARRAY *gpsaCurrentProcess = NULL;
+const DWORD MAX_LOCAL_SB = 23;
+
+#ifndef _CHICAGO_
+SECURITY_DESCRIPTOR LrpcSecurityDescriptor;
+BOOL fLrpcSDInitialized = FALSE;
+#endif
+
+// interface structure for IRemUnknown
+extern const RPC_SERVER_INTERFACE gRemUnknownIf;
+
+
+#if DBG==1
+//+-------------------------------------------------------------------
+//
+// Function: DisplayAllStringBindings, private
+//
+// Synopsis: prints the stringbindings to the debugger
+//
+// Notes: This function requires the caller to hold gComLock.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+void DisplayAllStringBindings(void)
+{
+ ASSERT_LOCK_HELD
+
+ if (gpsaCurrentProcess)
+ {
+ LPWSTR pwszNext = gpsaCurrentProcess->aStringArray;
+ LPWSTR pwszEnd = pwszNext + gpsaCurrentProcess->wSecurityOffset;
+
+ while (pwszNext < pwszEnd)
+ {
+ ComDebOut((DEB_CHANNEL, "pSEp=%x %ws\n", pwszNext, pwszNext));
+ pwszNext += lstrlenW(pwszNext) + 1;
+ }
+ }
+}
+#endif // DBG == 1
+
+
+//+-------------------------------------------------------------------
+//
+// Function: InitializeLrpcSecurity, private
+//
+// Synopsis: Create a DACL allowing all access to NCALRPC and MSWMSG
+// endpoints.
+//
+//--------------------------------------------------------------------
+void InitializeLrpcSecurity()
+{
+#ifndef _CHICAGO_
+ if (!fLrpcSDInitialized)
+ {
+ //
+ // Since this is static storage, and we always initialize it
+ // to the same values, it does not need to be MT safe.
+ //
+ InitializeSecurityDescriptor(&LrpcSecurityDescriptor,
+ SECURITY_DESCRIPTOR_REVISION);
+ SetSecurityDescriptorDacl(&LrpcSecurityDescriptor,
+ TRUE, NULL, FALSE);
+ fLrpcSDInitialized = TRUE;
+ }
+#endif
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: RegisterLrpc, private
+//
+// Synopsis: Register the ncalrpc transport.
+//
+//--------------------------------------------------------------------
+RPC_STATUS RegisterLrpc()
+{
+ RPC_STATUS sc;
+ WCHAR pwszEndPoint[12];
+
+ InitializeLrpcSecurity();
+
+ lstrcpyW( pwszEndPoint, L"OLE" );
+ _ultow( gdwEndPoint, &pwszEndPoint[3], 16 );
+
+ // The second parameter is a hint that tells lrpc whether or not it
+ // can preallocate additional resources (threads).
+ sc = RpcServerUseProtseqEp(L"ncalrpc",
+ RPC_C_PROTSEQ_MAX_REQS_DEFAULT + 1,
+ pwszEndPoint,
+#ifndef _CHICAGO_
+ &LrpcSecurityDescriptor);
+#else
+ NULL);
+#endif
+
+ // Assume that duplicate endpoint means we registered the endpoint and
+ // got unload and reloaded instead of it meaning someone else registered
+ // the endpoint.
+ if (sc == RPC_S_DUPLICATE_ENDPOINT)
+ {
+ gfLrpc = TRUE;
+ return RPC_S_OK;
+ }
+ else if (sc == RPC_S_OK)
+ {
+#ifndef _CHICAGO_
+ // Tell RPC to use this endpoint for mswmsg replies.
+ sc = I_RpcSetWMsgEndpoint( pwszEndPoint );
+ if (sc == RPC_S_OK)
+#endif
+ gfLrpc = TRUE;
+ }
+ return sc;
+}
+
+#ifdef _CHICAGO_
+//+-------------------------------------------------------------------
+//
+// Function: RegisterMswmsg, private
+//
+// Synopsis: Register the mswmsg transport.
+//
+// Notes: The caller must hold gComLock.
+//
+//--------------------------------------------------------------------
+RPC_STATUS RegisterMswmsg()
+{
+
+ RPC_STATUS sc;
+ WCHAR pwszEndPoint[12];
+
+ ASSERT_LOCK_HELD
+
+ InitializeLrpcSecurity();
+
+ lstrcpyW( pwszEndPoint, L"MSG" );
+ _ultow( gdwEndPoint, &pwszEndPoint[3], 16 );
+ sc = RpcServerUseProtseqEp(L"mswmsg",
+ RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
+ pwszEndPoint,
+ &LrpcSecurityDescriptor);
+
+ // Assume that duplicate endpoint means we registered the endpoint and
+ // got unload and reloaded instead of it meaning someone else registered
+ // the endpoint.
+ if (sc == RPC_S_OK || sc == RPC_S_DUPLICATE_ENDPOINT)
+ {
+ gfMswmsg = TRUE;
+ return RPC_S_OK;
+ }
+ else
+ return sc;
+}
+#endif
+
+//+-------------------------------------------------------------------
+//
+// Function: CheckClientMswmsg, public
+//
+// Synopsis: For the MSWMSG transport, we must call RpcServerUseProtseqEp
+// on the client side.
+//
+// Notes: The caller must hold gComLock.
+//
+// History: 27 Sept 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+RPC_STATUS CheckClientMswmsg( WCHAR *pProtseq, DWORD *pFlags )
+{
+ RPC_STATUS sc = RPC_S_OK;
+
+ ASSERT_LOCK_HELD
+
+ // Set the MSWMSG flag correctly.
+#ifdef _CHICAGO_
+ if (lstrlenW (pProtseq) >= 6 &&
+ memcmp ( L"mswmsg", pProtseq, 6 * sizeof (WCHAR)) == 0)
+#else
+ if (IsSTAThread() && (*pFlags & OXIDF_MACHINE_LOCAL))
+#endif
+ *pFlags |= OXIDF_MSWMSG;
+
+ // Find out if the transport is MSWMSG.
+ if ((*pFlags & OXIDF_MSWMSG)
+#ifdef _CHICAGO_
+ && IsSTAThread() && !gfMswmsg
+#endif
+ )
+ {
+ // Get a unique number and convert it to a string endpoint.
+ if (gdwEndPoint == 0)
+ gdwEndPoint = CoGetCurrentProcess();
+ if (gdwEndPoint == 0)
+ return E_FAIL;
+
+ // Register mswmsg.
+#ifdef _CHICAGO_
+ sc = RegisterMswmsg();
+#else
+ sc = RegisterLrpc();
+#endif
+ }
+
+ return sc;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: GetLocalEndpoint, public
+//
+// Synopsis: Get the endpoint for the local protocol sequence
+// for the local OXID.
+//
+// Notes: This function takes gComLock.
+//
+// History: 6 May 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+LPWSTR GetLocalEndpoint()
+{
+ ComDebOut((DEB_MARSHAL,"Entering GetLocalEndpoint.\n"));
+ LPWSTR pwszLocalEndpoint = NULL;
+ LOCK
+
+ StartListen();
+ if (gfListening)
+ {
+ // OLEFFFFFFFF
+ // maximum 12 character including the null, 24 bytes.
+ pwszLocalEndpoint = (LPWSTR) PrivMemAlloc( 24 );
+
+ if (pwszLocalEndpoint != NULL)
+ {
+ Win4Assert( gdwEndPoint != 0 );
+ lstrcpyW( pwszLocalEndpoint, L"OLE" );
+ _ultow( gdwEndPoint, &pwszLocalEndpoint[3], 16 );
+ }
+ }
+
+ UNLOCK
+ ComDebOut((DEB_MARSHAL,"Leaving GetLocalEndpoint Endpoint: 0x%x\n",
+ pwszLocalEndpoint));
+ return pwszLocalEndpoint;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: DefaultStringBindings, private
+//
+// Synopsis: Create a string binding with entries for just ncalrpc
+// and mswmsg
+//
+// Notes: This function requires the caller to hold gComLock.
+//
+//--------------------------------------------------------------------
+RPC_STATUS DefaultStringBindings()
+{
+ ULONG cChar;
+
+ ASSERT_LOCK_HELD
+
+ // If mswmsg has been used, reserve space for the string
+ // mswmsg:[MSGnnnnnnnn]
+#ifdef _CHICAGO_
+ if (gfMswmsg)
+ cChar = 22;
+ else
+#endif
+ cChar = 0;
+
+ // If ncalrpc has been used, reserve space for the string
+ // ncalrpc:[OLEnnnnnnnn]
+ if (gfLrpc)
+ cChar += 24;
+
+ // Allocate memory. Reserve space for an empty security binding.
+ cChar += 3;
+ gpsaCurrentProcess = (DUALSTRINGARRAY *) PrivMemAlloc( SASIZE(cChar) );
+
+ // Give up if the allocation failed.
+ if (gpsaCurrentProcess == NULL)
+ return RPC_S_OUT_OF_RESOURCES;
+
+ // If mswmsg has been used, make up a string for it.
+#ifdef _CHICAGO_
+ if (gfMswmsg)
+ {
+ lstrcpyW( gpsaCurrentProcess->aStringArray, L"mswmsg:[MSG" );
+ _ultow( gdwEndPoint, &gpsaCurrentProcess->aStringArray[11], 16 );
+ cChar = lstrlenW( gpsaCurrentProcess->aStringArray );
+ gpsaCurrentProcess->aStringArray[cChar++] = L']';
+ gpsaCurrentProcess->aStringArray[cChar++] = 0;
+ }
+ else
+#endif
+ cChar = 0;
+
+ // If ncalrpc has been used, make up a string for it.
+ if (gfLrpc)
+ {
+ lstrcpyW( &gpsaCurrentProcess->aStringArray[cChar], L"ncalrpc:[OLE" );
+ _ultow( gdwEndPoint, &gpsaCurrentProcess->aStringArray[cChar+12], 16 );
+ cChar += lstrlenW( &gpsaCurrentProcess->aStringArray[cChar] );
+ gpsaCurrentProcess->aStringArray[cChar++] = L']';
+ gpsaCurrentProcess->aStringArray[cChar++] = 0;
+ }
+
+ // Stick on an empty security binding.
+ gpsaCurrentProcess->aStringArray[cChar++] = 0;
+ gpsaCurrentProcess->wSecurityOffset = (USHORT) cChar;
+ gpsaCurrentProcess->aStringArray[cChar++] = 0;
+ gpsaCurrentProcess->aStringArray[cChar++] = 0;
+ gpsaCurrentProcess->wNumEntries = (USHORT) cChar;
+ gfDefaultStrings = TRUE;
+ return RPC_S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: InquireStringBindings, private
+//
+// Synopsis: Get and server binding handles from RPC and convert them
+// into a string array.
+//
+// Notes: This function requires the caller to hold gComLock.
+//
+// History: 23 May 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+BOOL InquireStringBindings( WCHAR *pProtseq )
+{
+ ASSERT_LOCK_HELD
+
+ BOOL fFound = FALSE;
+ DWORD cbProtseq;
+ RPC_BINDING_VECTOR *pBindVect = NULL;
+ RPC_STATUS sc = RpcServerInqBindings(&pBindVect);
+
+ if (sc == S_OK)
+ {
+ LPWSTR *apwszFullStringBinding;
+ ULONG *aulStrLen;
+ ULONG ulTotalStrLen = MAX_LOCAL_SB; // Total string lengths
+ ULONG j = 0; // BindString we're using
+
+ if (pProtseq != NULL)
+ cbProtseq = lstrlenW( pProtseq ) * sizeof(WCHAR);
+ else
+ cbProtseq = 0;
+ apwszFullStringBinding = (LPWSTR *) PrivMemAlloc( pBindVect->Count *
+ sizeof(LPWSTR) );
+ aulStrLen = (ULONG *) PrivMemAlloc( pBindVect->Count *
+ sizeof(ULONG) );
+ if (apwszFullStringBinding != NULL &&
+ aulStrLen != NULL)
+ {
+
+ // iterate over the handles to get the string bindings
+ // and dynamic endpoints for all available protocols.
+
+ for (ULONG i=0; i<pBindVect->Count; i++)
+ {
+ LPWSTR pwszStringBinding = NULL;
+ apwszFullStringBinding[j] = NULL;
+ aulStrLen[j] = 0;
+
+ sc = RpcBindingToStringBinding(pBindVect->BindingH[i],
+ &pwszStringBinding);
+ Win4Assert(sc == S_OK && "RpcBindingToStringBinding");
+
+
+ if (sc == S_OK)
+ {
+ // Determine is this is the protseq we are looking for.
+ if (memcmp( pProtseq, pwszStringBinding, cbProtseq ) == 0)
+ fFound = TRUE;
+
+ // Skip ncalrpc because rot needs to know the
+ // format of the ncalrpc endpoint.
+ if (lstrlenW (pwszStringBinding) >= 7 &&
+ memcmp ( L"ncalrpc", pwszStringBinding, 7*sizeof(WCHAR)) != 0)
+ {
+ // record the string lengths for later. include room
+ // for the NULL terminator.
+ apwszFullStringBinding[j] = pwszStringBinding;
+ aulStrLen[j] = lstrlenW(apwszFullStringBinding[j])+1;
+ ulTotalStrLen += aulStrLen[j];
+ j++;
+ }
+ else
+ {
+ RpcStringFree( &pwszStringBinding );
+ }
+ }
+ } // for
+
+
+ // now that all the string bindings and endpoints have been
+ // accquired, allocate a DUALSTRINGARRAY large enough to hold them
+ // all and copy them into the structure.
+
+ if (ulTotalStrLen > 0)
+ {
+ void *pNew = PrivMemAlloc( sizeof(DUALSTRINGARRAY) +
+ (ulTotalStrLen+1)*sizeof(WCHAR) );
+ if (pNew)
+ {
+ PrivMemFree( gpsaCurrentProcess );
+ gpsaCurrentProcess = (DUALSTRINGARRAY *) pNew;
+ LPWSTR pwszNext = gpsaCurrentProcess->aStringArray;
+
+ // Copy in ncalrpc:[OLEnnnnnnnn]
+ if (gfLrpc)
+ {
+ lstrcpyW( pwszNext, L"ncalrpc:[OLE" );
+ _ultow( gdwEndPoint, &pwszNext[12], 16 );
+ lstrcatW( pwszNext, L"]" );
+ pwszNext += lstrlenW(pwszNext) + 1;
+ }
+
+ // copy in the strings
+ for (i=0; i<j; i++)
+ {
+ lstrcpyW(pwszNext, apwszFullStringBinding[i]);
+ pwszNext += aulStrLen[i];
+ }
+
+ // Add a second null to terminate the string binding
+ // set. Add a third and fourth null to create an empty
+ // security binding set.
+
+ pwszNext[0] = 0;
+ pwszNext[1] = 0;
+ pwszNext[2] = 0;
+
+ // Fill in the size fields.
+ gpsaCurrentProcess->wSecurityOffset = pwszNext -
+ gpsaCurrentProcess->aStringArray + 1;
+ gpsaCurrentProcess->wNumEntries =
+ gpsaCurrentProcess->wSecurityOffset + 2;
+ }
+ else
+ {
+ sc = RPC_S_OUT_OF_RESOURCES;
+ }
+ }
+ else
+ {
+ // no binding strings. this is an error.
+ ComDebOut((DEB_ERROR, "No Rpc ProtSeq/EndPoints Generated\n"));
+ sc = RPC_S_NO_PROTSEQS;
+ }
+
+ // free the full string bindings we allocated above
+ for (i=0; i<j; i++)
+ {
+ // free the old strings
+ RpcStringFree(&apwszFullStringBinding[i]);
+ }
+ }
+ else
+ {
+ sc = RPC_S_OUT_OF_RESOURCES;
+ }
+
+ // free the binding vector allocated above
+ RpcBindingVectorFree(&pBindVect);
+ PrivMemFree( apwszFullStringBinding );
+ PrivMemFree( aulStrLen );
+ }
+
+#if DBG==1
+ // display our binding strings on the debugger
+ DisplayAllStringBindings();
+#endif
+
+ return fFound;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: StartListen, public
+//
+// Synopsis: this starts the Rpc service listening. this is required
+// in order to marshal interfaces. it is executed lazily,
+// that is, we dont start listening until someone tries to
+// marshal a local object interface. this is done so we dont
+// spawn a thread unnecessarily.
+//
+// Notes: This function takes gComLock.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT StartListen()
+{
+ ComDebOut((DEB_MARSHAL,"[IN] StartListen.\n"));
+ ASSERT_LOCK_HELD
+
+ RPC_STATUS sc = S_OK;
+ OXIDEntry *pOxid;
+
+ if (!gfListening)
+ {
+ // Get a unique number and convert it to a string endpoint.
+ if (gdwEndPoint == 0)
+ gdwEndPoint = CoGetCurrentProcess();
+ if (gdwEndPoint == 0)
+ return E_FAIL;
+
+ // Register ncalrpc for free threaded and mswmsg for apartment.
+#ifdef _CHICAGO_
+ if (IsMTAThread())
+ {
+#endif
+ sc = RegisterLrpc();
+#ifdef _CHICAGO_
+ }
+ else
+ {
+ sc = RegisterMswmsg();
+ // BUGBUG - Register ncalrpc until SCM can call us on mswmsg.
+ if (sc == RPC_S_OK)
+ sc = RegisterLrpc();
+ }
+#endif
+
+ if (sc == RPC_S_OK)
+ {
+
+ // Register the Object Resolver Callback interface.
+ sc = RpcServerRegisterIfEx(_IOrCallback_ServerIfHandle, NULL, NULL,
+ RPC_IF_AUTOLISTEN,
+ 0xffff, GetAclFn());
+
+ if (sc == RPC_S_OK || sc == RPC_S_TYPE_ALREADY_REGISTERED)
+ {
+ // Register the IRemUnknown interface. We need to register this
+ // manually because CRemoteUnknown marshals IRundown which inherits
+ // IRemoteUnknown. The resolver calls on IRundown and external clients
+ // call on IRemoteUnknown.
+
+ sc = RpcServerRegisterIfEx(
+ (RPC_SERVER_INTERFACE *)&gRemUnknownIf, NULL, NULL,
+ RPC_IF_AUTOLISTEN | RPC_IF_OLE,
+ 0xffff, GetAclFn() );
+
+ if (sc == RPC_S_OK || sc == RPC_S_TYPE_ALREADY_REGISTERED)
+ {
+ sc = DefaultStringBindings();
+ }
+ }
+ }
+
+ if (sc == RPC_S_OK)
+ {
+ gfListening = TRUE;
+ sc = S_OK;
+ }
+ else
+ {
+ sc = HRESULT_FROM_WIN32(sc);
+ }
+ }
+
+ if (sc == RPC_S_OK && IsSTAThread())
+ {
+ // Tell MSWMSG the window for each thread.
+ sc = gOXIDTbl.GetLocalEntry( &pOxid);
+ if (SUCCEEDED(sc))
+ {
+ sc = I_RpcServerStartListening( (HWND) pOxid->hServerSTA );
+ if (sc != RPC_S_OK)
+ sc = HRESULT_FROM_WIN32(sc);
+ }
+ }
+
+ // If something failed, make sure everything gets cleaned up.
+ if (FAILED(sc))
+ {
+ UNLOCK
+ UnregisterDcomInterfaces();
+ LOCK
+ }
+
+ ASSERT_LOCK_HELD
+ ComDebOut(((sc == S_OK) ? DEB_MARSHAL : DEB_ERROR,
+ "[OUT] StartListen hr: 0x%x\n", sc));
+ return sc;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: GetStringBindings, public
+//
+// Synopsis: Return an array of strings bindings for this process
+//
+// Notes: This function takes gComLock.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT GetStringBindings( DUALSTRINGARRAY **psaStrings )
+{
+ TRACECALL(TRACE_RPC, "GetStringBindings");
+ ComDebOut((DEB_CHANNEL, "[IN] GetStringBindings\n"));
+
+#ifdef _CHICAGO_
+ #error Register MSWMSG per thread.
+#endif
+
+ *psaStrings = NULL;
+
+ LOCK
+ HRESULT hr = StartListen();
+ if (SUCCEEDED(hr))
+ {
+ hr = CopyStringArray(gpsaCurrentProcess, gpsaSecurity, psaStrings);
+ }
+ UNLOCK
+
+ ComDebOut((DEB_CHANNEL, "[OUT] GetStringBindings hr:%x\n", hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CopyStringArray, public
+//
+// Synopsis: Combines the string bindings from the first DUALSTRINGARRAY
+// with the security bindings from the second DUALSTRINGARRAY
+// (if present) into a new DUALSTRINGARRAY.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CopyStringArray(DUALSTRINGARRAY *psaStringBinding,
+ DUALSTRINGARRAY *psaSecurity,
+ DUALSTRINGARRAY **ppsaNew)
+{
+ // compute size of string bindings
+ USHORT lSizeSB = SASIZE(psaStringBinding->wNumEntries);
+
+ // compute size of additional security strings
+ USHORT lSizeSC = (psaSecurity == NULL) ? 0 :
+ psaSecurity->wNumEntries - psaSecurity->wSecurityOffset;
+
+ *ppsaNew = (DUALSTRINGARRAY *) PrivMemAlloc( lSizeSB +
+ lSizeSC * sizeof(USHORT));
+
+ if (*ppsaNew != NULL)
+ {
+ // copy in the string bindings
+ memcpy(*ppsaNew, psaStringBinding, lSizeSB);
+
+ if (psaSecurity != NULL)
+ {
+ // copy in the security strings, and adjust the overall length.
+ memcpy(&(*ppsaNew)->aStringArray[psaStringBinding->wSecurityOffset],
+ &psaSecurity->aStringArray[psaSecurity->wSecurityOffset],
+ lSizeSC*sizeof(USHORT));
+
+ (*ppsaNew)->wNumEntries = psaStringBinding->wSecurityOffset +
+ lSizeSC;
+ }
+ return S_OK;
+ }
+
+ return E_OUTOFMEMORY;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: UnregisterDcomInterfaces
+//
+// Synopsis: Unregister the object resolver callback function and mark
+// DCOM as no longer accepting remote calls.
+//
+// Notes: This function requires that the caller guarentee
+// serialization without taking gComLock.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+SCODE UnregisterDcomInterfaces(void)
+{
+ ComDebOut((DEB_CHANNEL, "[IN] UnregisterDcomInterfaces\n"));
+ RPC_STATUS sc = RPC_S_OK;
+ ASSERT_LOCK_RELEASED
+
+ if (gfListening)
+ {
+ // Unregister IOrCallback. This can result in calls being dispatched.
+ // Do not hold the lock around this call.
+ sc = RpcServerUnregisterIf(_IOrCallback_ServerIfHandle, 0, 1 );
+
+ // Unregister IRemUnknown. This can result in calls being dispatched.
+ // Do not hold the lock around this call.
+ sc = RpcServerUnregisterIf((RPC_SERVER_INTERFACE *)&gRemUnknownIf, 0, 1);
+
+ gfListening = FALSE;
+ }
+ gSpeedOverMem = FALSE;
+
+ if (sc != RPC_S_OK)
+ sc = HRESULT_FROM_WIN32(sc);
+
+ ComDebOut((DEB_CHANNEL, "[OUT] UnregisterDcomInterfaces hr:%x\n", sc));
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: UseProtseq
+//
+// Synopsis: Use the specified protseq and return a list of all string
+// bindings.
+//
+// History: 25 May 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+error_status_t _UseProtseq( handle_t hRpc,
+ wchar_t *pwstrProtseq,
+ DUALSTRINGARRAY **ppsaNewBindings,
+ DUALSTRINGARRAY **ppsaSecurity )
+{
+ BOOL fInUse = FALSE;
+ RPC_STATUS sc = RPC_S_OK;
+
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // Make sure security is initialized.
+ sc = DefaultAuthnServices();
+
+ // If we have never inquired string bindings, inquire them before doing
+ // anything else.
+ if (sc == RPC_S_OK && gfDefaultStrings)
+ {
+ fInUse = InquireStringBindings( pwstrProtseq );
+ gfDefaultStrings = FALSE;
+ }
+
+ if (sc == RPC_S_OK && !fInUse)
+ {
+ // Special case ncalrpc.
+ if (lstrcmpW( pwstrProtseq, L"ncalrpc" ) == 0)
+ sc = RegisterLrpc();
+
+ #ifdef _CHICAGO_
+ // Special case mswmsg.
+ else if (lstrcmpW( pwstrProtseq, L"mswmsg" ) == 0)
+ {
+ if (!gfMswmsg)
+ sc = RegisterMswmsg();
+ }
+ #endif
+
+ // Register all other protocol sequences.
+ else
+ {
+ sc = RpcServerUseProtseq(pwstrProtseq,
+ RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
+ NULL);
+ }
+
+ if (sc != RPC_S_OK)
+ ComDebOut((DEB_CHANNEL, "Could not register protseq %ws: 0x%x\n",
+ pwstrProtseq, sc ));
+
+ // Return the latest string bindings. Ignore failures.
+ InquireStringBindings( NULL );
+ }
+
+ // Generate a copy to return.
+ CopyStringArray( gpsaCurrentProcess, NULL, ppsaNewBindings );
+ CopyStringArray( gpsaSecurity, NULL, ppsaSecurity );
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+ return RPC_S_OK;
+}
diff --git a/private/ole32/com/dcomrem/service.hxx b/private/ole32/com/dcomrem/service.hxx
new file mode 100644
index 000000000..8868025bc
--- /dev/null
+++ b/private/ole32/com/dcomrem/service.hxx
@@ -0,0 +1,33 @@
+//+-------------------------------------------------------------------
+//
+// File: service.hxx
+//
+// Contents: APIs to simplify RPC setup
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------
+#ifndef __SERVICE__
+#define __SERVICE__
+
+
+#define SASIZE(size) (sizeof(ULONG) + (size) * sizeof(WCHAR))
+
+// Function Prototypes.
+STDAPI StartListen(void);
+SCODE UnregisterDcomInterfaces(void);
+
+RPC_STATUS CheckClientMswmsg ( WCHAR *pProtseq, DWORD * );
+HRESULT CopyStringArray ( DUALSTRINGARRAY *psaStringBind,
+ DUALSTRINGARRAY *psaSecurity,
+ DUALSTRINGARRAY **ppsaNew );
+LPWSTR GetLocalEndpoint();
+HRESULT GetStringBindings ( DUALSTRINGARRAY **psaStrings );
+
+
+extern DWORD gdwEndPoint; // endpoint for current process
+extern DWORD gdwPsaMaxSize; // max size of any known psa
+extern DUALSTRINGARRAY *gpsaCurrentProcess; // string bindings for current process
+
+
+#endif // __SERVICE__
diff --git a/private/ole32/com/dcomrem/stdid.cxx b/private/ole32/com/dcomrem/stdid.cxx
new file mode 100644
index 000000000..2cd070026
--- /dev/null
+++ b/private/ole32/com/dcomrem/stdid.cxx
@@ -0,0 +1,1378 @@
+//+-------------------------------------------------------------------
+//
+// File: stdid.cxx
+//
+// Contents: identity object and creation function
+//
+// History: 1-Dec-93 CraigWi Created
+// 13-Sep-95 Rickhi Simplified
+//
+//--------------------------------------------------------------------
+#include <ole2int.h>
+#include <stdid.hxx> // CStdIdentity
+#include <marshal.hxx> // CStdMarshal
+#include <idtable.hxx> // Indentity Table
+
+#include "..\objact\objact.hxx" // used in IProxyManager::CreateServer
+
+
+#if DBG==1
+// head of linked list of identities for debug tracking purposes
+CStdIdentity gDbgIDHead;
+#endif // DBG
+
+
+//+----------------------------------------------------------------
+//
+// Class: CStdIdentity (stdid)
+//
+// Purpose: To be the representative of the identity of the object.
+//
+// History: 11-Dec-93 CraigWi Created.
+// 21-Apr-94 CraigWi Stubmgr addref's object; move strong cnt
+// 10-May-94 CraigWi IEC called for strong connections
+// 17-May-94 CraigWi Container weak connections
+// 31-May-94 CraigWi Tell object of weak pointers
+//
+// Details:
+//
+// The identity is determined on creation of the identity object. On the
+// server side a new OID is created, on the client side, the OID contained
+// in the OBJREF is used.
+//
+// The identity pointer is typically stored in the OIDTable, NOT AddRef'd.
+// SetOID adds the identity to the table, and can be called from ctor or
+// from Unmarshal. RevokeOID removes the identity from the table, and can
+// be called from Disconnect, or final Release.
+//
+//--------------------------------------------------------------------
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::CStdIdentity, private
+//
+// Synopsis: ctor for identity object
+//
+// Arguments: for all but the last param, see CreateIdentityHandler.
+// [ppUnkInternal] --
+// when aggregated, this the internal unknown;
+// when not aggregated, this is the controlling unknown
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+CStdIdentity::CStdIdentity(DWORD flags, IUnknown *pUnkOuter,
+ IUnknown *pUnkControl, IUnknown **ppUnkInternal) :
+ m_refs(1),
+ m_cStrongRefs(0),
+ m_flags(flags),
+ m_pIEC(NULL),
+ m_moid(GUID_NULL),
+ m_pUnkOuter((pUnkOuter) ? pUnkOuter : (IMultiQI *)&m_InternalUnk),
+ m_pUnkControl((pUnkControl) ? pUnkControl : m_pUnkOuter),
+ CClientSecurity( this )
+{
+ ComDebOut((DEB_MARSHAL, "CStdIdentity %s Created this:%x\n",
+ IsClient() ? "CLIENT" : "SERVER", this));
+ Win4Assert(!!IsClient() == (pUnkControl == NULL));
+
+#if DBG==1
+ // Chain this identity onto the global list of instantiated identities
+ // so we can track even the ones that are not placed in the ID table.
+ LOCK
+ m_pNext = gDbgIDHead.m_pNext;
+ m_pPrev = &gDbgIDHead;
+ gDbgIDHead.m_pNext = this;
+ m_pNext->m_pPrev = this;
+ UNLOCK
+#endif
+
+
+ if (pUnkOuter)
+ {
+ m_flags |= STDID_AGGREGATED;
+ }
+
+ CLSID clsidHandler;
+ DWORD dwSMFlags = SMFLAGS_CLIENT_SIDE; // assume client side
+
+ if (!IsClient())
+ {
+#if DBG == 1
+ // the caller should have a strong reference and so these tests
+ // should not disturb the object. These just check the sanity of
+ // the object we are attempting to marshal.
+
+ // addref/release pUnkControl; shouldn't go away (i.e.,
+ // should be other ref to it).
+ // Do this only if it is not Excel as it always returns which will
+ // trigger the assert on debug builds unnecessarily!
+ if (!IsTaskName(L"EXCEL.EXE"))
+ {
+ pUnkControl->AddRef();
+ Verify(pUnkControl->Release() != 0);
+
+ // verify that pUnkControl is in fact the controlling unknown
+ IUnknown *pUnkT;
+ Verify(pUnkControl->QueryInterface(IID_IUnknown,(void **)&pUnkT)==NOERROR);
+ Win4Assert(pUnkControl == pUnkT);
+ Verify(pUnkT->Release() != 0);
+ }
+#endif
+
+ dwSMFlags = 0; // server side
+ m_pUnkControl->AddRef();
+
+ // determine if we will write a standard or handler objref. we write
+ // standard unless the object implements IStdMarshalInfo and overrides
+ // the standard class. we ignore all errors from this point onward in
+ // order to maintain backward compatibility.
+
+ ASSERT_LOCK_RELEASED
+
+ IStdMarshalInfo *pSMI;
+ HRESULT hr = m_pUnkControl->QueryInterface(IID_IStdMarshalInfo,
+ (void **)&pSMI);
+ if (SUCCEEDED(hr))
+ {
+ hr = pSMI->GetClassForHandler(NULL, NULL, &clsidHandler);
+ if (SUCCEEDED(hr) && !IsEqualCLSID(clsidHandler, CLSID_NULL))
+ {
+ dwSMFlags |= SMFLAGS_HANDLER;
+ }
+ else
+ {
+ clsidHandler = GUID_NULL;
+ }
+ pSMI->Release();
+ }
+
+ // look for the IExternalConnection interface. The StdId will use
+ // this for Inc/DecStrongCnt. We do the QI here while we are not
+ // holding the LOCK.
+
+ hr = m_pUnkControl->QueryInterface(IID_IExternalConnection,
+ (void **)&m_pIEC);
+ if (FAILED(hr))
+ {
+ // make sure it is NULL
+ m_pIEC = NULL;
+ }
+
+ ASSERT_LOCK_RELEASED
+ }
+ else
+ {
+ m_cStrongRefs = 1;
+ }
+
+ // now intialize the standard marshaler
+ CStdMarshal::Init(m_pUnkControl, this, clsidHandler, dwSMFlags);
+
+ *ppUnkInternal = (IMultiQI *)&m_InternalUnk; // this is what the m_refs=1 is for
+
+ AssertValid();
+}
+
+#if DBG==1
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::CStdIdentity, public
+//
+// Synopsis: Special Identity ctor for the debug list head.
+//
+//+-------------------------------------------------------------------
+CStdIdentity::CStdIdentity() : CClientSecurity(this)
+{
+ Win4Assert(this == &gDbgIDHead);
+ m_pNext = this;
+ m_pPrev = this;
+}
+#endif // DBG
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::~CStdIdentity, private
+//
+// Synopsis: Final destruction of the identity object. ID has been
+// revoked by now (in internal ::Release). Here we disconnect
+// on server.
+//
+// History: 15-Dec-93 CraigWi Created.
+// Rickhi Simplified
+//
+//--------------------------------------------------------------------
+CStdIdentity::~CStdIdentity()
+{
+#if DBG==1
+ if (this != &gDbgIDHead)
+ {
+#endif // DBG
+
+ ComDebOut((DEB_MARSHAL, "CStdIdentity %s Deleted this:%x\n",
+ IsClient() ? "CLIENT" : "SERVER", this));
+
+ Win4Assert(m_refs == 0);
+ m_refs++; // simple guard against reentry of dtor
+ SetNowInDestructor(); // debug flag which enables asserts to detect
+
+ // make sure we have disconnected
+ Disconnect();
+
+#if DBG==1
+ // UnChain this identity from the global list of instantiated identities
+ // so we can track even the ones that are not placed in the ID table.
+ LOCK
+ m_pPrev->m_pNext = m_pNext;
+ m_pNext->m_pPrev = m_pPrev;
+ UNLOCK
+ }
+#endif // DBG
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::CInternalUnk::QueryInterface, private
+//
+// Synopsis: Queries for an interface. Just delegates to the common
+// code in QueryMultipleInterfaces.
+//
+// History: 26-Feb-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CStdIdentity::CInternalUnk::QueryInterface(REFIID riid, VOID **ppv)
+{
+ MULTI_QI mqi;
+ mqi.pIID = &riid;
+ mqi.pItf = NULL;
+
+ QueryMultipleInterfaces(1, &mqi);
+
+ *ppv = (void *)mqi.pItf;
+ return mqi.hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::CInternalUnk::QueryMultipleInterfaces, public
+//
+// Synopsis:
+//
+// History: 26-Feb-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CStdIdentity::CInternalUnk::QueryMultipleInterfaces(ULONG cMQIs,
+ MULTI_QI *pMQIs)
+{
+ // Make sure TLS is initialized.
+ HRESULT hr;
+ COleTls tls(hr);
+ if (FAILED(hr))
+ return hr;
+
+ CStdIdentity *pStdID = GETPPARENT(this, CStdIdentity, m_InternalUnk);
+ pStdID->AssertValid();
+
+ // allocate some space on the stack for the intermediate results. declare
+ // working pointers and remember the start address of the allocations.
+
+ MULTI_QI **ppMQIAlloc = (MULTI_QI **)_alloca(sizeof(MULTI_QI *) * cMQIs);
+ IID *pIIDAlloc = (IID *) _alloca(sizeof(IID) * cMQIs);
+ SQIResult *pSQIAlloc = (SQIResult *)_alloca(sizeof(SQIResult) * cMQIs);
+
+ MULTI_QI **ppMQIPending = ppMQIAlloc;
+ IID *pIIDPending = pIIDAlloc;
+ SQIResult *pSQIPending = pSQIAlloc;
+
+
+ // loop over the interfaces looking for locally supported interfaces,
+ // instantiated proxies, and unsupported interfaces. Gather up all the
+ // interfaces that dont fall into the above categories, and issue a
+ // remote query to the server.
+
+ USHORT cPending = 0;
+ ULONG cAcquired = 0;
+ MULTI_QI *pMQI = pMQIs;
+
+ for (ULONG i=0; i<cMQIs; i++, pMQI++)
+ {
+ if (pMQI->pItf != NULL)
+ {
+ // skip any entries that are not set to NULL. This allows
+ // progressive layers of handlers to optionally fill in the
+ // interfaces that they know about and pass the whole array
+ // on to the next level.
+ continue;
+ }
+
+ pMQI->hr = S_OK;
+
+ // always allow - IUnknown, IMarshal, IStdIdentity, Instantiated proxies
+ if (InlineIsEqualGUID(*(pMQI->pIID), IID_IUnknown))
+ {
+ pMQI->pItf = (IMultiQI *)this;
+ }
+ else if (InlineIsEqualGUID(*(pMQI->pIID), IID_IMarshal))
+ {
+ pMQI->pItf = (IMarshal *)pStdID;
+ }
+ else if (InlineIsEqualGUID(*(pMQI->pIID), IID_IStdIdentity))
+ {
+ pMQI->pItf = (IUnknown *)(void*)pStdID;
+ }
+ else if (InlineIsEqualGUID(*(pMQI->pIID), IID_IProxyManager))
+ {
+ // old code exposed this IID and things now depend on it.
+ pMQI->pItf = (IProxyManager *)pStdID;
+ }
+ else if (pStdID->InstantiatedProxy(*(pMQI->pIID),(void **)&pMQI->pItf,
+ &pMQI->hr))
+ {
+ // a proxy for this interface already exists
+ //
+ // NOTE: this call also set pMQI->hr = E_NOINTERFACE if the
+ // StId has never been connected, and to CO_E_OBJNOTCONNECTED if
+ // it has been connected but is not currently connected. This is
+ // required for backwards compatibility, and will cause us to skip
+ // the QueryRemoteInterface.
+ ;
+ }
+ else if (pStdID->IsAggregated())
+ {
+ // aggregate case
+ // allow - IInternalUnknown
+ // dissallow - IMultiQI, IClientSecurity, IServerSecurity
+
+ if (InlineIsEqualGUID(*(pMQI->pIID), IID_IInternalUnknown))
+ {
+ pMQI->pItf = (IInternalUnknown *)this;
+ pMQI->hr = S_OK;
+ }
+ else if (InlineIsEqualGUID(*(pMQI->pIID), IID_IMultiQI) ||
+ InlineIsEqualGUID(*(pMQI->pIID), IID_IClientSecurity) ||
+ InlineIsEqualGUID(*(pMQI->pIID), IID_IServerSecurity))
+ {
+ pMQI->hr = E_NOINTERFACE;
+ }
+ else if (pMQI->hr == S_OK)
+ {
+ // InstantiatedProxy did not return E_NOINTERFACE or
+ // CO_E_OBJNOTCONNECTED so add this interface to the
+ // list to pass to the QueryRemoteInterfaces.
+
+ pMQI->hr = RPC_S_CALLPENDING;
+ }
+ }
+ else
+ {
+ // non-aggregate case
+ // allow - IClientSecurity, IMultiQI
+ // dissallow - IInternalUnknown, IServerSecurity
+
+ if (InlineIsEqualGUID(*(pMQI->pIID), IID_IClientSecurity))
+ {
+ pMQI->pItf = (IClientSecurity *)pStdID;
+ pMQI->hr = S_OK;
+ }
+ else if (InlineIsEqualGUID(*(pMQI->pIID), IID_IMultiQI))
+ {
+ pMQI->pItf = (IMultiQI *)this;
+ pMQI->hr = S_OK;
+ }
+ else if (InlineIsEqualGUID(*(pMQI->pIID), IID_IInternalUnknown) ||
+ InlineIsEqualGUID(*(pMQI->pIID), IID_IServerSecurity))
+ {
+ pMQI->hr = E_NOINTERFACE;
+ }
+ else if (pMQI->hr == S_OK)
+ {
+ // InstantiatedProxy did not return E_NOINTERFACE or
+ // CO_E_OBJNOTCONNECTED so add this interface to the
+ // list to pass to the QueryRemoteInterfaces.
+
+ pMQI->hr = RPC_S_CALLPENDING;
+ }
+ }
+
+ if (pMQI->hr == S_OK)
+ {
+ // got an interface to return, AddRef it and count one more
+ // interface acquired.
+
+ pMQI->pItf->AddRef();
+ cAcquired++;
+ }
+ else if (pMQI->hr == RPC_S_CALLPENDING)
+ {
+ // fill in a remote QI structure and count one more
+ // pending interface
+
+ pSQIPending->pv = NULL;
+ pSQIPending->hr = S_OK;
+ *pIIDPending = *(pMQI->pIID);
+ *ppMQIPending = pMQI;
+
+ pSQIPending++;
+ pIIDPending++;
+ ppMQIPending++;
+ cPending++;
+ }
+ }
+
+ if (cPending > 0)
+ {
+ // there are some interfaces which we dont yet know about, so
+ // go ask the remoting layer to Query the server and build proxies
+ // where possible. The results are returned in the individual
+ // SQIResults, so the overall return code is ignored.
+
+ pStdID->QueryRemoteInterfaces(cPending, pIIDAlloc, pSQIAlloc);
+
+ // got some interfaces, loop over the remote QI structure filling
+ // in the rest of the MULTI_QI structure to return to the caller.
+ // the proxies are already AddRef'd.
+
+ pSQIPending = pSQIAlloc;
+ ppMQIPending = ppMQIAlloc;
+
+ for (i=0; i<cPending; i++, pSQIPending++, ppMQIPending++)
+ {
+ pMQI = *ppMQIPending;
+ pMQI->pItf = (IUnknown *)(pSQIPending->pv);
+ pMQI->hr = pSQIPending->hr;
+
+ if (SUCCEEDED(pMQI->hr))
+ {
+ // count one more acquired interface
+ cAcquired++;
+ }
+ }
+ }
+
+ // if we got all the interfaces, return S_OK. If we got none of the
+ // interfaces, return E_NOINTERFACE. If we got some, but not all, of
+ // the interfaces, return S_FALSE;
+
+ if (cAcquired == cMQIs)
+ return S_OK;
+ else if (cAcquired > 0)
+ return S_FALSE;
+ else
+ return E_NOINTERFACE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::CInternalUnk::QueryInternalInterface, public
+//
+// Synopsis: return interfaces that are internal to the aggregated
+// proxy manager.
+//
+// History: 26-Feb-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CStdIdentity::CInternalUnk::QueryInternalInterface(REFIID riid,
+ VOID **ppv)
+{
+ CStdIdentity *pStdID = GETPPARENT(this, CStdIdentity, m_InternalUnk);
+ pStdID->AssertValid();
+
+ if (!pStdID->IsAggregated())
+ {
+ // this method is only valid when we are part of a client-side
+ // aggregate.
+ return E_NOTIMPL;
+ }
+
+ if (InlineIsEqualGUID(riid, IID_IUnknown) ||
+ InlineIsEqualGUID(riid, IID_IInternalUnknown))
+ {
+ *ppv = (IInternalUnknown *)this;
+ }
+ else if (InlineIsEqualGUID(riid, IID_IMultiQI))
+ {
+ *ppv = (IMultiQI *)this;
+ }
+ else if (InlineIsEqualGUID(riid, IID_IStdIdentity))
+ {
+ *ppv = pStdID;
+ }
+ else if (InlineIsEqualGUID(riid, IID_IClientSecurity))
+ {
+ *ppv = (IClientSecurity *)pStdID;
+ }
+ else if (InlineIsEqualGUID(riid, IID_IProxyManager))
+ {
+ *ppv = (IProxyManager *)pStdID;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ ((IUnknown *)*ppv)->AddRef();
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::CInternalUnk::AddRef, public
+//
+// Synopsis: Nothing special.
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CStdIdentity::CInternalUnk::AddRef(void)
+{
+ CStdIdentity *pStdID = GETPPARENT(this, CStdIdentity, m_InternalUnk);
+ pStdID->AssertValid();
+
+ AssertSz(!pStdID->IsInDestructor(), "CStdIdentity AddRef'd during destruction");
+
+ InterlockedIncrement((long *)&pStdID->m_refs);
+ // ComDebOut((DEB_MARSHAL, "StdId:CtrlUnk::AddRef this:%x m_refs:%x\n", pStdID, pStdID->m_refs));
+ return pStdID->m_refs;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::CInternalUnk::Release, public
+//
+// Synopsis: Releases the identity object. When the ref count goes
+// to zero, revokes the id and destroys the object.
+//
+// History: 15-Dec-93 CraigWi Created.
+// 18-Apr-95 Rickhi Rewrote much faster/simpler
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CStdIdentity::CInternalUnk::Release(void)
+{
+ CStdIdentity *pStdID = GETPPARENT(this, CStdIdentity, m_InternalUnk);
+ pStdID->AssertValid();
+
+ DWORD refs = pStdID->m_refs - 1;
+ // ComDebOut((DEB_MARSHAL, "StdId:CtrlUnk::Release this:%x m_refs:%x\n", pStdID, refs));
+
+ if (InterlockedDecrement((long *)&pStdID->m_refs) == 0)
+ {
+ BOOL fDelete = FALSE;
+ ASSERT_LOCK_RELEASED
+ LOCK
+
+ // check if we are already in the dtor and skip a second destruction
+ // if so. The reason we need this is that some crusty old apps do
+ // CoMarshalInterface followed by CoLockObjectExternal(FALSE,TRUE),
+ // expecting this to accomplish a Disconnect. It subtracts from the
+ // references, but it takes away the ones that the IPIDEntry put on,
+ // without telling the IPIDEntry, so when we release the IPIDEntry,
+ // our count goes negative!!!
+
+ // the LockedInMemory flag is for the gpStdMarshal instance that we
+ // may hand out to clients, but which we never want to go away,
+ // regardless of how many times they call Release.
+
+ if (pStdID->m_refs == 0)
+ {
+ // refcnt is still zero, so the idtable did not just hand
+ // out a reference behind our back.
+
+ if (!pStdID->IsLockedOrInDestructor())
+ {
+ // remove from the OID table and delete the identity
+ // We dont delete while holding the table mutex.
+
+ pStdID->RevokeOID();
+ fDelete = TRUE;
+ }
+ else
+ {
+ // this object is locked in memory and we should never
+ // get here, but some broken test app was doing this in
+ // stress.
+
+ pStdID->m_refs = 100;
+ }
+ }
+
+ UNLOCK
+ ASSERT_LOCK_RELEASED
+
+ if (fDelete)
+ {
+ delete pStdID;
+ return 0;
+ }
+ }
+
+ return refs;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::IUnknown methods, public
+//
+// Synopsis: External IUnknown methods; delegates to m_pUnkOuter.
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CStdIdentity::QueryInterface(REFIID riid, VOID **ppvObj)
+{
+ AssertValid();
+ return m_pUnkOuter->QueryInterface(riid, ppvObj);
+}
+
+STDMETHODIMP_(ULONG) CStdIdentity::AddRef(void)
+{
+ AssertValid();
+ return m_pUnkOuter->AddRef();
+}
+
+STDMETHODIMP_(ULONG) CStdIdentity::Release(void)
+{
+ AssertValid();
+ return m_pUnkOuter->Release();
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::UnlockAndRelease, public
+//
+// Synopsis: Version of Release used for gpStdMarshal, that is
+// currently locked in memory so nobody but us can
+// release it, regardless of refcnt.
+//
+// History: 19-Apr-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+ULONG CStdIdentity::UnlockAndRelease(void)
+{
+ m_flags &= ~STDID_LOCKEDINMEM;
+ m_refs = 1;
+ return m_pUnkOuter->Release();
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::IncStrongCnt, public
+//
+// Synopsis: Increments the strong reference count on the identity.
+//
+// History: 15-Dec-93 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CStdIdentity::IncStrongCnt()
+{
+ Win4Assert(!IsClient());
+
+ // we might be holding the lock here if this is called from
+ // LookupIDFromUnk, since we have to be holding the lock while
+ // doing the lookup. We cant release it or we could go away.
+
+ ASSERT_LOCK_DONTCARE
+
+ ComDebOut((DEB_MARSHAL,
+ "CStdIdentity::IncStrongCnt this:%x cStrong:%x\n",
+ this, m_cStrongRefs+1));
+
+ AddRef();
+ InterlockedIncrement(&m_cStrongRefs);
+
+ if (m_pIEC)
+ {
+ m_pIEC->AddConnection(EXTCONN_STRONG, 0);
+ }
+
+ ASSERT_LOCK_DONTCARE
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::DecStrongCnt, public
+//
+// Synopsis: Decrements the strong reference count on the identity,
+// and releases the object if that was the last strong
+// reference.
+//
+// History: 15-Dec-93 Rickhi Created.
+//
+//--------------------------------------------------------------------
+void CStdIdentity::DecStrongCnt(BOOL fKeepAlive)
+{
+ Win4Assert(!IsClient());
+ ASSERT_LOCK_RELEASED
+
+ ComDebOut((DEB_MARSHAL,
+ "CStdIdentity::DecStrongCnt this:%x cStrong:%x fKeepAlive:%x\n",
+ this, m_cStrongRefs-1, fKeepAlive));
+
+ LONG cStrongRefs = InterlockedDecrement(&m_cStrongRefs);
+
+ if (m_pIEC)
+ {
+ m_pIEC->ReleaseConnection(EXTCONN_STRONG, 0, !fKeepAlive);
+ }
+
+ if (cStrongRefs == 0 && !fKeepAlive && (IsWOWThread() || m_pIEC == NULL))
+ {
+ // strong count has gone to zero, disconnect.
+ DisconnectObject(0);
+ }
+
+ if (cStrongRefs >= 0)
+ {
+ // some apps call CoMarshalInterface + CoLockObjectExternal(F,T)
+ // and expect the object to go away. Doing that causes Release to
+ // be called too many times (once for each IPID, once for CLOE, and
+ // once for the original Lookup).
+ Release();
+ }
+
+ ASSERT_LOCK_RELEASED
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::LockObjectExternal, public
+//
+// Synopsis: locks (or unlocks) the object so the remoting layer does
+// not (or does) go away.
+//
+// History: 09-Oct-96 Rickhi Moved from CoLockObjectExternal.
+//
+//--------------------------------------------------------------------
+HRESULT CStdIdentity::LockObjectExternal(BOOL fLock, BOOL fLastUR)
+{
+ HRESULT hr = S_OK;
+
+ if (GetServer() == NULL)
+ {
+ // attempt to lock handler, return error!
+ hr = E_UNEXPECTED;
+ }
+ else if (fLock)
+ {
+ // lock (and ignore rundowns) so it does not go away
+ IncStrongCnt();
+ LOCK;
+ IncTableCnt();
+ UNLOCK;
+ }
+ else
+ {
+ // unlock so that it can go away
+ LOCK;
+ DecTableCnt();
+ UNLOCK;
+ DecStrongCnt(!fLastUR);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::GetServer, public
+//
+// Synopsis: Returns a pUnk for the identified object; NULL on client side
+// The pointer is optionally addrefed depending upon fAddRef
+//
+// Returns: The pUnk on the object.
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+IUnknown * CStdIdentity::GetServer()
+{
+ if (IsClient() || m_pUnkControl == NULL)
+ return NULL;
+
+ // Verify validity
+ Win4Assert(IsValidInterface(m_pUnkControl));
+ return m_pUnkControl;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::ReleaseCtrlUnk, public
+//
+// Synopsis: Releases the server side controlling unknown
+// This code is safe for reentrant calls.
+//
+// History: 11-Jun-95 Rickhi Created
+//
+//--------------------------------------------------------------------
+void CStdIdentity::ReleaseCtrlUnk(void)
+{
+ AssertValid();
+ Win4Assert(!IsClient());
+
+ if (m_pUnkControl)
+ {
+ // server side: release the real object's m_pUnkControl;
+ // prevent problem on recursive disconnect
+
+ AssertSz(IsValidInterface(m_pUnkControl),
+ "Invalid IUnknown during disconnect");
+ IUnknown *pUnkControl = m_pUnkControl;
+ m_pUnkControl = NULL;
+
+ if (m_pIEC)
+ {
+ AssertSz(IsValidInterface(m_pIEC),
+ "Invalid IExternalConnection during disconnect");
+ m_pIEC->Release();
+ m_pIEC = NULL;
+ }
+
+ pUnkControl->Release();
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::SetOID, public
+//
+// Synopsis: Associates the OID and the object (handler or server).
+//
+// History: 20-Feb-95 Rickhi Simplified
+//
+//--------------------------------------------------------------------
+HRESULT CStdIdentity::SetOID(REFMOID rmoid)
+{
+ Win4Assert(rmoid != GUID_NULL);
+ ASSERT_LOCK_HELD
+
+ HRESULT hr = S_OK;
+
+ if (!(m_flags & STDID_HAVEID))
+ {
+ if (!(m_flags & STDID_IGNOREID))
+ {
+ Win4Assert(!(m_flags & STDID_FREETHREADED));
+ hr = SetObjectID(rmoid, m_pUnkControl, this);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ m_flags |= STDID_HAVEID;
+ m_moid = rmoid;
+ }
+ }
+
+ ComDebErr(hr != S_OK, "SetOID Failed. Probably OOM.\n");
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::RevokeOID, public
+//
+// Synopsis: Disassociates the OID and the object (handler or server).
+// Various other methods will fail (e.g., MarshalInterface).
+//
+// History: 15-Dec-93 CraigWi Created.
+// 20-Feb-95 Rickhi Simplified
+//
+//--------------------------------------------------------------------
+void CStdIdentity::RevokeOID(void)
+{
+ AssertValid();
+ ASSERT_LOCK_HELD
+
+ if (m_flags & STDID_HAVEID)
+ {
+ m_flags &= ~STDID_HAVEID;
+
+ if (!(m_flags & STDID_IGNOREID))
+ (void)ClearObjectID(m_moid, m_pUnkControl, this);
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::IsConnected, public
+//
+// Synopsis: Indicates if the client is connected to the server.
+// Only the negative answer is definitive because we
+// might not be able to tell if the server is connected
+// and even if we could, the answer might be wrong by
+// the time the caller acted on it.
+//
+// Returns: TRUE if the server might be connected; FALSE if
+// definitely not.
+//
+// History: 16-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(BOOL) CStdIdentity::IsConnected(void)
+{
+ Win4Assert(IsClient()); // must be client side
+ AssertValid();
+
+ return RemIsConnected();
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::Disconnect, public
+//
+// Synopsis: IProxyManager::Disconnect implementation, just forwards
+// to the standard marshaller, which may call us back to
+// revoke our OID and release our CtrlUnk.
+//
+// May also be called by the IDTable cleanup code.
+//
+// History: 11-Jun-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(void) CStdIdentity::Disconnect(void)
+{
+ AssertValid();
+ CStdMarshal::Disconnect();
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::LockConnection, public
+//
+// Synopsis: IProxyManager::LockConnection implementation. Changes
+// all interfaces to weak from strong, or strong from weak.
+//
+// History: 11-Jun-95 Rickhi Created.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CStdIdentity::LockConnection(BOOL fLock, BOOL fLastUnlockReleases)
+{
+ AssertValid();
+
+ if (!IsClient())
+ {
+ // this operation does not make sense on the server side.
+ return E_NOTIMPL;
+ }
+
+ if (IsMTAThread())
+ {
+ // this call is not allowed if we are FreeThreaded. Report
+ // success, even though we did not do anything.
+ return S_OK;
+ }
+
+
+ if (( fLock && (++m_cStrongRefs == 1)) ||
+ (!fLock && (--m_cStrongRefs == 0)))
+ {
+ // the strong count transitioned from 0 to 1 or 1 to 0, so
+ // call the server to change our references.
+
+ return RemoteChangeRef(fLock, fLastUnlockReleases);
+ }
+
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::CreateServer, public
+//
+// Synopsis: Creates the server clsid in the given context and
+// attaches it to this handler.
+//
+// History: 16-Dec-93 CraigWi Created.
+//
+// CODEWORK: this code is not thread safe in the freethreading case. We
+// need to decide if the thread safety is the responsibility
+// of the caller, or us. In the latter case, we would check
+// if we are already connected before doing UnmarshalObjRef, and
+// instead do a ::ReleaseMarshalObjRef.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CStdIdentity::CreateServer(REFCLSID rclsid, DWORD clsctx, void *pv)
+{
+ ComDebOut((DEB_ACTIVATE, "ScmCreateObjectInstance this:%x clsctx:%x pv:%x\n",
+ this, clsctx, pv));
+ AssertValid();
+ Win4Assert(IsClient()); // must be client side
+ Win4Assert(IsValidInterface(m_pUnkControl)); // must be valid
+ //Win4Assert(!IsConnected());
+ ASSERT_LOCK_RELEASED
+
+ // Loop trying to get object from the server. Because the server can be
+ // in the process of shutting down and respond with a marshaled interface,
+ // we will retry this call if unmarshaling fails assuming that the above
+ // is true.
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (FAILED(hr))
+ return hr;
+
+ const int MAX_SERVER_TRIES = 3;
+
+ for (int i = 0; i < MAX_SERVER_TRIES; i++)
+ {
+ // create object and get back marshaled interface pointer
+ InterfaceData *pIFD = NULL;
+
+ // Dll ignored here since we are just doing this to get
+ // the remote handler.
+ WCHAR *pwszDllPath = NULL;
+ DWORD dwDllType = IsSTAThread() ? APT_THREADED : FREE_THREADED;
+
+#ifdef DCOM
+ HRESULT hrinterface;
+ hr = gResolver.CreateInstance( NULL, (CLSID *)&rclsid, clsctx, 1,
+ (IID *)&IID_IUnknown, (MInterfacePointer **)&pIFD,
+ &hrinterface,&dwDllType, &pwszDllPath );
+#else
+ // The first three NULLs (pwszFrom, pstgFrom, pwszNew) trigger a
+ // simple creation.
+ hr = gResolver.CreateObject(rclsid, clsctx, 0,
+ NULL, NULL, NULL, &pIFD, &dwDllType, &pwszDllPath, NULL);
+#endif
+
+ if (pwszDllPath != NULL)
+ {
+ CoTaskMemFree(pwszDllPath);
+ }
+
+ if (FAILED(hr))
+ {
+ // If an error occurred, return that otherwise convert a wierd
+ // success into E_FAIL. The point here is to return an error that
+ // the caller can figure out what happened.
+ hr = FAILED(hr) ? hr : E_FAIL;
+ break;
+ }
+
+
+ // make a stream out of the interface data returned, then read the
+ // objref from the stream. No need to find another instance of
+ // CStdMarshal because we already know it is for us!
+
+ CXmitRpcStream Stm(pIFD);
+ OBJREF objref;
+ hr = ReadObjRef(&Stm, objref);
+
+ if (SUCCEEDED(hr))
+ {
+ // become this identity by unmarshaling the objref into this
+ // object. Note the objref must use standard marshaling.
+ Win4Assert(objref.flags & (OBJREF_HANDLER | OBJREF_STANDARD));
+ Win4Assert(IsEqualIID(objref.iid, IID_IUnknown));
+
+ IUnknown *pUnk = NULL;
+ hr = UnmarshalObjRef(objref, (void **)&pUnk);
+ if (SUCCEEDED(hr))
+ {
+ // release the AddRef done by unmarshaling
+ pUnk->Release();
+
+ // Reconnect the interface proxies
+ CStdMarshal::ReconnectProxies();
+ }
+
+ // free the objref we read above.
+ FreeObjRef(objref);
+ }
+
+ CoTaskMemFree(pIFD);
+
+
+ // If either this worked or we got a packet we couldn't unmarshal
+ // at all we give up. Otherwise, we will hope that recontacting the
+ // SCM will fix things.
+
+ if (SUCCEEDED(hr) || (hr == E_FAIL))
+ {
+ break;
+ }
+ }
+
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_ACTIVATE, "ScmCreateObjectInstance this:%x hr:%x\n",
+ this, hr));
+ return hr;
+}
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::CreateServerWithHandler, public
+//
+// Synopsis: Creates the server clsid in the given context and
+// attaches it to this handler.
+//
+// History: 10-Oct-95 JohannP Created
+//
+// CODEWORK: this code is not thread safe in the freethreading case. We
+// need to decide if the thread safety is the responsibility
+// of the caller, or us. In the latter case, we would check
+// if we are already connected before doing UnmarshalObjRef, and
+// instead do a ::ReleaseMarshalObjRef.
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CStdIdentity::CreateServerWithHandler(REFCLSID rclsid, DWORD clsctx, void *pv,
+ REFCLSID rclsidHandler, IID iidSrv, void **ppv,
+ IID iidClnt, void *pClientSiteInterface)
+{
+ ComDebOut((DEB_ACTIVATE, "ScmCreateObjectInstance this:%x clsctx:%x pv:%x\n",
+ this, clsctx, pv));
+ AssertValid();
+ Win4Assert(IsClient()); // must be client side
+ Win4Assert(IsValidInterface(m_pUnkControl)); // must be valid
+ //Win4Assert(!IsConnected());
+ Win4Assert(ppv != NULL);
+
+ ASSERT_LOCK_RELEASED
+
+ // Loop trying to get object from the server. Because the server can be
+ // in the process of shutting down and respond with a marshaled interface,
+ // we will retry this call if unmarshaling fails assuming that the above
+ // is true.
+
+ HRESULT hr = InitChannelIfNecessary();
+ if (FAILED(hr))
+ return hr;
+
+ IClientSiteHandler *pClientSiteHandler = (IClientSiteHandler *)pClientSiteInterface;
+
+ const int MAX_SERVER_TRIES = 3;
+
+ for (int i = 0; i < MAX_SERVER_TRIES; i++)
+ {
+ // create object and get back marshaled interface pointer
+ InterfaceData *pIFD = NULL;
+
+ // Dll ignored here since we are just doing this to get
+ // the remote handler.
+ WCHAR *pwszDllPath = NULL;
+ DWORD dwDllType = IsSTAThread() ? APT_THREADED : FREE_THREADED;
+
+#ifdef DCOM
+ HRESULT hrinterface;
+
+ // marshal ClientSiteHandler
+ MInterfacePointer * pIFPServerHandler = NULL;
+ MInterfacePointer * pIFPClientSiteHandler = NULL;
+
+ if (pClientSiteHandler)
+ {
+ // addref once here - MarshalHelper calls release on the object
+ pClientSiteHandler->AddRef();
+ hr = MarshalHelper(pClientSiteHandler, IID_IClientSiteHandler,
+ MSHLFLAGS_NORMAL,
+ (InterfaceData **) &pIFPClientSiteHandler);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = gResolver.CreateInstance( NULL, (CLSID *)&rclsid, clsctx, 1,
+ (IID *)&IID_IUnknown, (MInterfacePointer **)&pIFD,
+ &hrinterface, &dwDllType, &pwszDllPath );
+
+ if (pIFPServerHandler)
+ {
+ if (SUCCEEDED(hr))
+ {
+ CXmitRpcStream Stm((InterfaceData *) pIFPServerHandler);
+ hr = CoUnmarshalInterface(&Stm, IID_IServerHandler, ppv);
+ }
+ CoTaskMemFree(pIFPServerHandler);
+ }
+
+ PrivMemFree(pIFPClientSiteHandler);
+ }
+ else
+ {
+ hr = gResolver.CreateInstance( NULL, (CLSID *)&rclsid, clsctx, 1,
+ (IID *)&IID_IUnknown, (MInterfacePointer **)&pIFD,
+ &hrinterface,&dwDllType, &pwszDllPath );
+ }
+
+#else
+ // The first three NULLs (pwszFrom, pstgFrom, pwszNew) trigger a
+ // simple creation.
+ hr = gResolver.CreateObject(rclsid, clsctx, 0,
+ NULL, NULL, NULL, &pIFD, &dwDllType, &pwszDllPath, NULL);
+#endif
+
+ if (pwszDllPath != NULL)
+ {
+ CoTaskMemFree(pwszDllPath);
+ }
+
+ if (FAILED(hr))
+ {
+ // If an error occurred, return that otherwise convert a wierd
+ // success into E_FAIL. The point here is to return an error that
+ // the caller can figure out what happened.
+ hr = FAILED(hr) ? hr : E_FAIL;
+ break;
+ }
+
+
+ // make a stream out of the interface data returned, then read the
+ // objref from the stream. No need to find another instance of
+ // CStdMarshal because we already know it is for us!
+
+ CXmitRpcStream Stm(pIFD);
+ OBJREF objref;
+ hr = ReadObjRef(&Stm, objref);
+
+ if (SUCCEEDED(hr))
+ {
+ // become this identity by unmarshaling the objref into this
+ // object. Note the objref must use standard marshaling.
+ Win4Assert(objref.flags & (OBJREF_HANDLER | OBJREF_STANDARD));
+ Win4Assert(IsEqualIID(objref.iid, IID_IUnknown));
+
+ IUnknown *pUnk = NULL;
+ hr = UnmarshalObjRef(objref, (void **)&pUnk);
+ if (SUCCEEDED(hr))
+ {
+ // release the AddRef done by unmarshaling
+ pUnk->Release();
+
+ // Reconnect the interface proxies
+ CStdMarshal::ReconnectProxies();
+ }
+
+ // free the objref we read above.
+ FreeObjRef(objref);
+ }
+
+ CoTaskMemFree(pIFD);
+
+
+ // If either this worked or we got a packet we couldn't unmarshal
+ // at all we give up. Otherwise, we will hope that recontacting the
+ // SCM will fix things.
+
+ if (SUCCEEDED(hr) || (hr == E_FAIL))
+ {
+ break;
+ }
+ }
+
+ ASSERT_LOCK_RELEASED
+ ComDebOut((DEB_ACTIVATE, "ScmCreateObjectInstance this:%x hr:%x\n",
+ this, hr));
+ return hr;
+}
+
+
+
+#if DBG == 1
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::AssertValid
+//
+// Synopsis: Validates that the state of the object is consistent.
+//
+// History: 26-Jan-94 CraigWi Created.
+//
+//--------------------------------------------------------------------
+void CStdIdentity::AssertValid()
+{
+ LOCK
+ AssertSz(m_refs < 0x7fff, "Identity ref count unreasonable");
+
+ // ensure we have the controlling unknown
+ Win4Assert(IsValidInterface(m_pUnkOuter)); // must be valid
+
+ // NOTE: don't carelessly AddRef/Release because of weak references
+
+ Win4Assert((m_flags & ~(STDID_SERVER | STDID_CLIENT | STDID_HAVEID |
+ STDID_FREETHREADED | STDID_INDESTRUCTOR |
+ STDID_IGNOREID | STDID_AGGREGATED |
+ STDID_LOCKEDINMEM)) == 0);
+
+ if ((m_flags & STDID_HAVEID) &&
+ !(m_flags & (STDID_FREETHREADED | STDID_IGNOREID)))
+ {
+ CStdIdentity *pStdID;
+ Verify(LookupIDFromID(m_moid, FALSE /*fAddRef*/, &pStdID) == NOERROR);
+ Win4Assert(pStdID == this);
+ // pStdID not addref'd
+ }
+
+ if (IsClient())
+ Win4Assert(m_pUnkControl == m_pUnkOuter);
+
+ // must have RH tell identity when object goes away so we can NULL this
+ if (m_pUnkControl != NULL)
+ Win4Assert(IsValidInterface(m_pUnkControl)); // must be valid
+
+ if (m_pIEC != NULL)
+ Win4Assert(IsValidInterface(m_pIEC)); // must be valid
+
+ UNLOCK
+}
+#endif // DBG == 1
+
+//+-------------------------------------------------------------------
+//
+// Function: CreateIdentityHandler, private
+//
+// Synopsis: Creates a client side identity object (one which is
+// initialized by the first unmarshal).
+//
+// Arguments: [pUnkOuter] - controlling unknown if aggregated
+// [flags] - flags (indicates free-threaded or not)
+// [riid] - interface requested
+// [ppv] - place for pointer to that interface.
+//
+// History: 16-Dec-93 CraigWi Created.
+// 20-Feb-95 Rickhi Simplified
+//
+//--------------------------------------------------------------------
+INTERNAL CreateIdentityHandler(IUnknown *pUnkOuter, DWORD flags,
+ REFIID riid, void **ppv)
+{
+#if DBG == 1
+ Win4Assert(IsApartmentInitialized());
+
+ // if aggregating, it must ask for IUnknown.
+ Win4Assert(pUnkOuter == NULL || InlineIsEqualGUID(riid, IID_IUnknown));
+
+ if (pUnkOuter != NULL)
+ {
+ // addref/release pUnkOuter; shouldn't go away (i.e.,
+ // should be other ref to it).
+ // Except Excel which always returns 0 on Release!
+ if (!IsTaskName(L"EXCEL.EXE"))
+ {
+ pUnkOuter->AddRef();
+ Verify(pUnkOuter->Release() != 0);
+
+ // verify that pUnkOuter is in fact the controlling unknown
+ IUnknown *pUnkT;
+ Verify(pUnkOuter->QueryInterface(IID_IUnknown,(void**)&pUnkT)==NOERROR);
+ Win4Assert(pUnkOuter == pUnkT);
+ Verify(pUnkT->Release() != 0);
+ }
+ }
+#endif
+
+ *ppv = NULL;
+ IUnknown *pUnkID;
+ HRESULT hr = E_OUTOFMEMORY;
+
+ DWORD StdIdFlags = (flags & SORF_FREETHREADED) ? STDID_CLIENT | STDID_FREETHREADED :
+ STDID_CLIENT;
+
+ CStdIdentity *pStdId = new CStdIdentity(StdIdFlags, pUnkOuter,
+ NULL, &pUnkID);
+ if (pStdId)
+ {
+ // get the interface the caller asked for.
+ hr = pUnkID->QueryInterface(riid, ppv);
+ pUnkID->Release();
+ }
+
+ CALLHOOKOBJECTCREATE(hr,CLSID_NULL,riid,(IUnknown **)ppv);
+ return hr;
+}
diff --git a/private/ole32/com/dcomrem/stdid.hxx b/private/ole32/com/dcomrem/stdid.hxx
new file mode 100644
index 000000000..2e187fc65
--- /dev/null
+++ b/private/ole32/com/dcomrem/stdid.hxx
@@ -0,0 +1,143 @@
+//+-------------------------------------------------------------------
+//
+// File: stdid.hxx
+//
+// Contents: identity object and creation function
+//
+// History: 1-Dec-93 CraigWi Created
+//
+//--------------------------------------------------------------------
+#ifndef _STDID_HXX_
+#define _STDID_HXX_
+
+#include <marshal.hxx> // CStdMarshal
+#include <idtable.hxx> // IDTable APIs
+#include <srvhdl.h>
+#include <security.hxx> // CClientSecurity
+
+
+
+#define DECLARE_INTERNAL_UNK() \
+ class CInternalUnk : public IInternalUnknown, public IMultiQI \
+ { \
+ public: \
+ /* IUnknown methods */ \
+ STDMETHOD(QueryInterface)(REFIID riid, VOID **ppv); \
+ STDMETHOD_(ULONG,AddRef)(void) ; \
+ STDMETHOD_(ULONG,Release)(void); \
+ \
+ /* IInternalUnknown methods */ \
+ STDMETHOD(QueryInternalInterface)(REFIID riid, VOID **ppv); \
+ \
+ /* IMultiQI methods */ \
+ STDMETHOD(QueryMultipleInterfaces)(ULONG cMQIs, MULTI_QI *pMQIs); \
+ }; \
+ friend CInternalUnk; \
+ CInternalUnk m_InternalUnk;
+
+
+typedef enum tagSTDID_FLAGS
+{
+ STDID_SERVER = 0x0, // on server side
+ STDID_CLIENT = 0x1, // on client side (non-local in RH terms)
+ STDID_FREETHREADED = 0x2, // this object is callable on any thread
+ STDID_HAVEID = 0x4, // have an OID in the table
+ STDID_IGNOREID = 0x8, // dont put OID in the table
+ STDID_AGGREGATED = 0x10, // dont put OID in the table
+ STDID_INDESTRUCTOR = 0x100,// dtor entered; assert on AddRef and others
+ STDID_LOCKEDINMEM = 0x200,// dont delete this object regardless of refcnt
+} STDID_FLAGS;
+
+
+class CStdIdentity : public IProxyManager, public CStdMarshal,
+ public CClientSecurity
+{
+public:
+ CStdIdentity(DWORD flags, IUnknown *pUnkOuter, IUnknown *pUnkControl,
+ IUnknown **ppUnkInternal);
+ ~CStdIdentity();
+
+ // IUnknown
+ STDMETHOD(QueryInterface) (REFIID riid, LPVOID *ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ // IProxyManager (only if client side)
+ STDMETHOD(CreateServer)(REFCLSID rclsid, DWORD clsctx, void *pv);
+ STDMETHOD_(BOOL, IsConnected)(void);
+ STDMETHOD(LockConnection)(BOOL fLock, BOOL fLastUnlockReleases);
+ STDMETHOD_(void, Disconnect)();
+ STDMETHOD(CreateServerWithHandler)(REFCLSID rclsid, DWORD clsctx, void *pv,
+ REFCLSID rclsidHandler, IID iidSrv, void **ppv,
+ IID iidClnt, void *pClientSiteInterface);
+
+
+ IUnknown *GetCtrlUnk(void) { return m_pUnkControl; };
+ IUnknown *GetServer();
+ void ReleaseCtrlUnk(void);
+
+ REFMOID GetOID (void) { return m_moid; }
+ HRESULT SetOID (REFMOID rmoid);
+ void IgnoreOID (void) { m_flags |= STDID_IGNOREID; }
+ void RevokeOID (void);
+ ULONG GetRC (void) { return m_refs; }
+ BOOL IsFreeThreaded(void) { return m_flags & STDID_FREETHREADED; }
+ BOOL IsAggregated(void) { return m_flags & STDID_AGGREGATED; }
+ void SetLockedInMemory() { m_flags |= STDID_LOCKEDINMEM; }
+ ULONG UnlockAndRelease(void);
+
+ // methods to manipulate the strong reference count.
+ void IncStrongCnt();
+ void DecStrongCnt(BOOL fKeepAlive);
+
+ // method used by CoLockObjectExternal
+ HRESULT LockObjectExternal(BOOL fLock, BOOL fLastUR);
+
+ // internal unknown
+ DECLARE_INTERNAL_UNK()
+
+ friend INTERNAL CreateIdentityHandler(IUnknown *pUnkOuter,
+ DWORD flags, REFIID riid, void **ppv);
+
+ friend INTERNAL_(void) IDTableThreadUninitializeHelper(DWORD);
+
+
+#if DBG == 1
+ void AssertValid();
+ CStdIdentity(); // debug ctor for debug list head
+#else
+ void AssertValid() { }
+#endif
+
+private:
+
+ BOOL IsClient() { return m_flags & STDID_CLIENT; }
+ void SetNowInDestructor() { m_flags |= STDID_INDESTRUCTOR; }
+ BOOL IsInDestructor() { return m_flags & STDID_INDESTRUCTOR; }
+ BOOL IsLockedOrInDestructor(){ return (m_flags & (STDID_INDESTRUCTOR |
+ STDID_LOCKEDINMEM)); }
+
+ DWORD m_refs; // number of pointer refs
+ DWORD m_flags; // see STDID_* values above; set once.
+
+ IUnknown *m_pUnkOuter; // controlling unknown; set once.
+
+ IUnknown *m_pUnkControl; // the controlling unk of the object;
+ // this member has three possible values:
+ // pUnkOuter - client side; not addref'd
+ // pUnkControl - server side (which may
+ // be pUnkOuter if aggregated); addref'd
+ // NULL - server side, disconnected
+
+ MOID m_moid; // the identity (OID + MID)
+ IExternalConnection *m_pIEC;// of the server if supported
+ LONG m_cStrongRefs; // count of strong references
+
+#if DBG==1
+ CStdIdentity *m_pNext; // double chain list of instantiated
+ CStdIdentity *m_pPrev; // identity objects for debugging
+#endif // DBG
+};
+
+#endif // _STDID_HXX
+
diff --git a/private/ole32/com/dcomrem/stream.cxx b/private/ole32/com/dcomrem/stream.cxx
new file mode 100644
index 000000000..496d9bf92
--- /dev/null
+++ b/private/ole32/com/dcomrem/stream.cxx
@@ -0,0 +1,605 @@
+/*++
+
+Microsoft Windows
+Copyright (c) 1994 Microsoft Corporation. All rights reserved.
+
+Module Name:
+ stream.cxx
+
+Abstract:
+ Implements the IStream interface on a memory buffer.
+
+Author:
+ ShannonC 09-Mar-1994
+
+Environment:
+ Windows NT and Windows 95. We do not support DOS and Win16.
+
+Revision History:
+ 12-Oct-94 ShannonC Reformat for code review.
+
+--*/
+
+#include <ole2int.h>
+#include <stream.hxx>
+
+CNdrStream::CNdrStream(
+ IN unsigned char * pData,
+ IN unsigned long cbMax)
+ : pBuffer(pData), cbBufferLength(cbMax)
+/*++
+
+Routine Description:
+ This function creates a stream on the specified memory buffer.
+
+Arguments:
+ pData - Supplies pointer to memory buffer.
+ cbMax - Supplies size of memory buffer.
+
+Return Value:
+ None.
+
+--*/
+{
+ RefCount = 1;
+ position = 0;
+}
+
+
+ULONG STDMETHODCALLTYPE
+CNdrStream::AddRef()
+/*++
+
+Routine Description:
+ Increment the reference count.
+
+Arguments:
+
+Return Value:
+ Reference count.
+
+--*/
+{
+ InterlockedIncrement(&RefCount);
+ return (ULONG) RefCount;
+}
+
+HRESULT STDMETHODCALLTYPE
+CNdrStream::Clone(
+ OUT IStream **ppstm)
+/*++
+
+Routine Description:
+ Create a new IStream object. The new IStream gets an
+ independent seek pointer but it shares the underlying
+ data buffer with the original IStream object.
+
+Arguments:
+ ppstm - Pointer to the new stream.
+
+Return Value:
+ S_OK - The stream was successfully copied.
+ E_OUTOFMEMORY - The stream could not be copied due to lack of memory.
+
+--*/
+{
+ HRESULT hr;
+ CNdrStream *pStream = new CNdrStream(pBuffer, cbBufferLength);
+
+ if(pStream != 0)
+ {
+ pStream->position = position;
+ hr = S_OK;
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ *ppstm = (IStream *) pStream;
+
+ return hr;
+}
+
+HRESULT STDMETHODCALLTYPE
+CNdrStream::Commit(
+ IN DWORD grfCommitFlags)
+/*++
+
+Routine Description:
+ This stream does not support transacted mode. This function does nothing.
+
+Arguments:
+ grfCommitFlags
+
+Return Value:
+ S_OK
+
+--*/
+{
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE
+CNdrStream::CopyTo(
+ IN IStream * pstm,
+ IN ULARGE_INTEGER cb,
+ OUT ULARGE_INTEGER *pcbRead,
+ OUT ULARGE_INTEGER *pcbWritten)
+/*++
+
+Routine Description:
+ Copies data from one stream to another stream.
+
+Arguments:
+ pstm - Specifies the destination stream.
+ cb - Specifies the number of bytes to be copied to the destination stream.
+ pcbRead - Returns the number of bytes read from the source stream.
+ pcbWritten - Returns the number of bytes written to the destination stream.
+
+Return Value:
+ S_OK - The data was successfully copied.
+ Other errors from IStream::Write.
+
+--*/
+{
+ HRESULT hr;
+ unsigned char * pSource;
+ unsigned long cbRead;
+ unsigned long cbWritten;
+ unsigned long cbRemaining;
+
+ //Check if we are going off the end of the buffer.
+ if(position < cbBufferLength)
+ cbRemaining = cbBufferLength - position;
+ else
+ cbRemaining = 0;
+
+ if((cb.HighPart == 0) && (cb.LowPart <= cbRemaining))
+ cbRead = cb.LowPart;
+ else
+ cbRead = cbRemaining;
+
+ pSource = pBuffer + position;
+
+ //copy the data
+ hr = pstm->Write(pSource, cbRead, &cbWritten);
+
+ //advance the current position
+ position += cbRead;
+
+ if (pcbRead != 0)
+ {
+ pcbRead->LowPart = cbRead;
+ pcbRead->HighPart = 0;
+ }
+ if (pcbWritten != 0)
+ {
+ pcbWritten->LowPart = cbWritten;
+ pcbWritten->HighPart = 0;
+ }
+
+ return hr;
+}
+
+HRESULT STDMETHODCALLTYPE
+CNdrStream::LockRegion(
+ IN ULARGE_INTEGER libOffset,
+ IN ULARGE_INTEGER cb,
+ IN DWORD dwLockType)
+/*++
+
+Routine Description:
+ Range locking is not supported by this stream.
+
+Return Value:
+ STG_E_INVALIDFUNCTION.
+
+--*/
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+HRESULT STDMETHODCALLTYPE
+CNdrStream::QueryInterface(
+ REFIID riid,
+ void **ppvObj)
+/*++
+
+Routine Description:
+ Query for an interface on the stream. The stream supports
+ the IUnknown and IStream interfaces.
+
+Arguments:
+ riid - Supplies the IID of the interface being requested.
+ ppvObject - Returns a pointer to the requested interface.
+
+Return Value:
+ S_OK
+ E_NOINTERFACE
+
+--*/
+{
+ HRESULT hr;
+
+ if ((memcmp(&riid, &IID_IUnknown, sizeof(IID)) == 0) ||
+ (memcmp(&riid, &IID_IStream, sizeof(IID)) == 0))
+ {
+ this->AddRef();
+ *ppvObj = (IStream *) this;
+ hr = S_OK;
+ }
+ else
+ {
+ *ppvObj = 0;
+ hr = E_NOINTERFACE;
+ }
+
+ return hr;
+}
+
+HRESULT STDMETHODCALLTYPE
+CNdrStream::Read(
+ OUT void * pv,
+ IN ULONG cb,
+ OUT ULONG *pcbRead)
+/*++
+
+Routine Description:
+ Reads data from the stream starting at the current seek pointer.
+
+Arguments:
+ pv - Returns the data read from the stream.
+ cb - Supplies the number of bytes to read from the stream.
+ pcbRead - Returns the number of bytes actually read from the stream.
+
+Return Value:
+ S_OK - The data was successfully read from the stream.
+ S_FALSE - The number of bytes read was smaller than the number requested.
+
+--*/
+{
+ HRESULT hr;
+ unsigned long cbRead;
+ unsigned long cbRemaining;
+
+ //Check if we are reading past the end of the buffer.
+ if(position < cbBufferLength)
+ cbRemaining = cbBufferLength - position;
+ else
+ cbRemaining = 0;
+
+ if(cb <= cbRemaining)
+ {
+ cbRead = cb;
+ hr = S_OK;
+ }
+ else
+ {
+ cbRead = cbRemaining;
+ hr = S_FALSE;
+ }
+
+ //copy the data
+ memcpy(pv, pBuffer + position, cbRead);
+
+ //advance the current position
+ position += cbRead;
+
+ if(pcbRead != 0)
+ *pcbRead = cbRead;
+
+ return hr;
+}
+
+ULONG STDMETHODCALLTYPE
+CNdrStream::Release()
+/*++
+
+Routine Description:
+ Decrement the reference count. When the reference count
+ reaches zero, the stream is deleted.
+
+Arguments:
+
+Return Value:
+ Reference count.
+
+--*/
+{
+ unsigned long count;
+
+ count = RefCount - 1;
+ if(InterlockedDecrement(&RefCount) == 0)
+ {
+ count = 0;
+ delete this;
+ }
+
+ return count;
+}
+
+
+HRESULT STDMETHODCALLTYPE
+CNdrStream::Revert()
+/*++
+
+Routine Description:
+ This stream does not support transacted mode. This function does nothing.
+
+Arguments:
+ None.
+
+Return Value:
+ S_OK.
+
+--*/
+{
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE
+CNdrStream::Seek(
+ IN LARGE_INTEGER dlibMove,
+ IN DWORD dwOrigin,
+ OUT ULARGE_INTEGER *plibNewPosition)
+/*++
+
+Routine Description:
+ Sets the position of the seek pointer. It is an error to seek
+ before the beginning of the stream or past the end of the stream.
+
+Arguments:
+ dlibMove - Supplies the offset from the position specified in dwOrigin.
+ dwOrigin - Supplies the seek mode.
+ plibNewPosition - Returns the new position of the seek pointer.
+
+Return Value:
+ S_OK - The seek pointer was successfully adjusted.
+ STG_E_INVALIDFUNCTION - dwOrigin contains invalid value.
+ STG_E_SEEKERROR - The seek pointer cannot be positioned before the
+ beginning of the stream or past the
+ end of the stream.
+
+--*/
+{
+ HRESULT hr;
+ long high;
+ long low;
+ unsigned long offset;
+ unsigned long cbRemaining;
+
+ switch (dwOrigin)
+ {
+ case STREAM_SEEK_SET:
+ //Set the seek position relative to the beginning of the stream.
+ if((dlibMove.HighPart == 0) && (dlibMove.LowPart <= cbBufferLength))
+ {
+ position = dlibMove.LowPart;
+ hr = S_OK;
+ }
+ else
+ {
+ //It is an error to seek past the end of the stream.
+ hr = STG_E_SEEKERROR;
+ }
+ break;
+
+ case STREAM_SEEK_CUR:
+ //Set the seek position relative to the current position of the stream.
+ high = (long) dlibMove.HighPart;
+ if(high < 0)
+ {
+ //Negative offset
+ low = (long) dlibMove.LowPart;
+ offset = -low;
+
+ if((high == -1) && (offset <= position))
+ {
+ position -= offset;
+ hr = S_OK;
+ }
+ else
+ {
+ //It is an error to seek before the beginning of the stream.
+ hr = STG_E_SEEKERROR;
+ }
+ }
+ else
+ {
+ //Positive offset
+ if(position < cbBufferLength)
+ cbRemaining = cbBufferLength - position;
+ else
+ cbRemaining = 0;
+
+ if((dlibMove.HighPart == 0) && (dlibMove.LowPart <= cbRemaining))
+ {
+ position += dlibMove.LowPart;
+ hr = S_OK;
+ }
+ else
+ {
+ //It is an error to seek past the end of the stream.
+ hr = STG_E_SEEKERROR;
+ }
+ }
+ break;
+
+ case STREAM_SEEK_END:
+ //Set the seek position relative to the end of the stream.
+ high = (long) dlibMove.HighPart;
+ if(high < 0)
+ {
+ //Negative offset
+ low = (long) dlibMove.LowPart;
+ offset = -low;
+
+ if((high == -1) && (offset <= cbBufferLength))
+ {
+ position = cbBufferLength - offset;
+ hr = S_OK;
+ }
+ else
+ {
+ //It is an error to seek before the beginning of the stream.
+ hr = STG_E_SEEKERROR;
+ }
+ }
+ else if(dlibMove.QuadPart == 0)
+ {
+ position = cbBufferLength;
+ hr = S_OK;
+ }
+ else
+ {
+ //Positive offset
+ //It is an error to seek past the end of the stream.
+ hr = STG_E_SEEKERROR;
+ }
+ break;
+
+ default:
+ //dwOrigin contains an invalid value.
+ hr = STG_E_INVALIDFUNCTION;
+ }
+
+ if (plibNewPosition != 0)
+ {
+ plibNewPosition->LowPart = position;
+ plibNewPosition->HighPart = 0;
+ }
+
+ return hr;
+}
+
+HRESULT STDMETHODCALLTYPE
+CNdrStream::SetSize(
+ IN ULARGE_INTEGER libNewSize)
+/*++
+
+Routine Description:
+ Changes the size of the stream.
+
+Arguments:
+ libNewSize - Supplies the new size of the stream.
+
+Return Value:
+ S_OK - The stream size was successfully changed.
+ STG_E_MEDIUMFULL - The stream size could not be changed.
+
+--*/
+{
+ HRESULT hr;
+
+ if((libNewSize.HighPart == 0) && (libNewSize.LowPart <= cbBufferLength))
+ {
+ cbBufferLength = libNewSize.LowPart;
+ hr = S_OK;
+ }
+ else
+ {
+ hr = STG_E_MEDIUMFULL;
+ }
+
+ return hr;
+}
+
+HRESULT STDMETHODCALLTYPE
+CNdrStream::Stat(
+ OUT STATSTG * pstatstg,
+ IN DWORD grfStatFlag)
+/*++
+
+Routine Description:
+ This function gets information about this stream.
+
+Arguments:
+ pstatstg - Returns information about this stream.
+ grfStatFlg - Specifies the information to be returned in pstatstg.
+
+Return Value:
+ S_OK.
+
+--*/
+{
+ memset(pstatstg, 0, sizeof(STATSTG));
+ pstatstg->type = STGTY_STREAM;
+ pstatstg->cbSize.LowPart = cbBufferLength;
+ pstatstg->cbSize.HighPart = 0;
+
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE
+CNdrStream::UnlockRegion(
+ IN ULARGE_INTEGER libOffset,
+ IN ULARGE_INTEGER cb,
+ IN DWORD dwLockType)
+/*++
+
+Routine Description:
+ Range locking is not supported by this stream.
+
+Return Value:
+ STG_E_INVALIDFUNCTION.
+
+--*/
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+HRESULT STDMETHODCALLTYPE
+CNdrStream::Write(
+ IN void const *pv,
+ IN ULONG cb,
+ OUT ULONG * pcbWritten)
+/*++
+
+Routine Description:
+ Write data to the stream starting at the current seek pointer.
+
+Arguments:
+ pv - Supplies the data to be written to the stream.
+ cb - Specifies the number of bytes to be written to the stream.
+ pcbWritten - Returns the number of bytes actually written to the stream.
+
+Return Value:
+ S_OK - The data was successfully written to the stream.
+ STG_E_MEDIUMFULL - Data cannot be written past the end of the stream.
+
+--*/
+{
+ HRESULT hr;
+ unsigned long cbRemaining;
+ unsigned long cbWritten;
+
+ //Check if we are writing past the end of the buffer.
+ if(position < cbBufferLength)
+ cbRemaining = cbBufferLength - position;
+ else
+ cbRemaining = 0;
+
+ if(cb <= cbRemaining)
+ {
+ cbWritten = cb;
+ hr = S_OK;
+ }
+ else
+ {
+ cbWritten = cbRemaining;
+ hr = STG_E_MEDIUMFULL;
+ }
+
+ // Write the data.
+ memcpy(pBuffer + position, pv, cbWritten);
+
+ //Advance the current position
+ position += cbWritten;
+
+ //update pcbWritten
+ if (pcbWritten != 0)
+ *pcbWritten = cbWritten;
+
+ return hr;
+}
diff --git a/private/ole32/com/dcomrem/stream.hxx b/private/ole32/com/dcomrem/stream.hxx
new file mode 100644
index 000000000..af128e10b
--- /dev/null
+++ b/private/ole32/com/dcomrem/stream.hxx
@@ -0,0 +1,94 @@
+//+-------------------------------------------------------------------
+//
+// File: stream.hxx
+//
+// Contents: Implements the IStream interface on a memory buffer.
+//
+//--------------------------------------------------------------------
+#ifndef _STREAM_HXX_
+#define _STREAM_HXX_
+
+
+class CNdrStream : public IStream
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE
+ QueryInterface(
+ IN REFIID riid,
+ OUT void **ppvObj);
+
+ virtual ULONG STDMETHODCALLTYPE
+ AddRef();
+
+ virtual ULONG STDMETHODCALLTYPE
+ Release();
+
+ virtual HRESULT STDMETHODCALLTYPE
+ Read(
+ IN void * pv,
+ IN ULONG cb,
+ OUT ULONG * pcbRead);
+
+ virtual HRESULT STDMETHODCALLTYPE
+ Write(
+ IN void const *pv,
+ IN ULONG cb,
+ OUT ULONG * pcbWritten);
+
+ virtual HRESULT STDMETHODCALLTYPE
+ Seek(
+ IN LARGE_INTEGER dlibMove,
+ IN DWORD dwOrigin,
+ OUT ULARGE_INTEGER *plibNewPosition);
+
+ virtual HRESULT STDMETHODCALLTYPE
+ SetSize(
+ IN ULARGE_INTEGER libNewSize);
+
+ virtual HRESULT STDMETHODCALLTYPE
+ CopyTo(
+ IN IStream * pstm,
+ IN ULARGE_INTEGER cb,
+ OUT ULARGE_INTEGER *pcbRead,
+ OUT ULARGE_INTEGER *pcbWritten);
+
+ virtual HRESULT STDMETHODCALLTYPE
+ Commit(
+ IN DWORD grfCommitFlags);
+
+ virtual HRESULT STDMETHODCALLTYPE
+ Revert();
+
+ virtual HRESULT STDMETHODCALLTYPE
+ LockRegion(
+ IN ULARGE_INTEGER libOffset,
+ IN ULARGE_INTEGER cb,
+ IN DWORD dwLockType);
+
+ virtual HRESULT STDMETHODCALLTYPE
+ UnlockRegion(
+ IN ULARGE_INTEGER libOffset,
+ IN ULARGE_INTEGER cb,
+ IN DWORD dwLockType);
+
+ virtual HRESULT STDMETHODCALLTYPE
+ Stat(
+ OUT STATSTG * pstatstg,
+ IN DWORD grfStatFlag);
+
+ virtual HRESULT STDMETHODCALLTYPE
+ Clone(
+ OUT IStream **ppstm);
+
+ CNdrStream(
+ IN unsigned char * pData,
+ IN unsigned long cbMax);
+
+private:
+ long RefCount;
+ unsigned char * pBuffer;
+ unsigned long cbBufferLength;
+ unsigned long position;
+};
+
+#endif // _STREAM_HXX_
diff --git a/private/ole32/com/dcomrem/threads.cxx b/private/ole32/com/dcomrem/threads.cxx
new file mode 100644
index 000000000..35ca9c212
--- /dev/null
+++ b/private/ole32/com/dcomrem/threads.cxx
@@ -0,0 +1,340 @@
+//+-------------------------------------------------------------------
+//
+// File: threads.cxx
+//
+// Contents: Rpc thread cache
+//
+// Classes: CRpcThread - single thread
+// CRpcThreadCache - cache of threads
+//
+// Notes: This code represents the cache of Rpc threads used to
+// make outgoing calls in the SINGLETHREADED object Rpc
+// model.
+//
+// History: Rickhi Created
+// 07-31-95 Rickhi Fix event handle leak
+//
+//+-------------------------------------------------------------------
+#include <ole2int.h>
+#include <olerem.h>
+#include <chancont.hxx> // ThreadDispatch
+#include <threads.hxx>
+
+
+// static members of ThreadCache class
+CRpcThread * CRpcThreadCache::_pFreeList = NULL;// list of free threads
+COleStaticMutexSem CRpcThreadCache::_mxs; // for list manipulation
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThreadCache::RpcWorkerThreadEntry
+//
+// Purpose: Entry point for an Rpc worker thread.
+//
+// Returns: nothing, it never returns.
+//
+// Callers: Called ONLY by a worker thread.
+//
+//+-------------------------------------------------------------------
+DWORD _stdcall CRpcThreadCache::RpcWorkerThreadEntry(void *param)
+{
+ // First thing we need to do is LoadLibrary ourselves in order to
+ // prevent our code from going away while this worker thread exists.
+ // The library will be freed when this thread exits.
+
+ HINSTANCE hInst = LoadLibrary(L"OLE32.DLL");
+
+
+ // construct a thread object on the stack, and call the main worker
+ // loop. Do this in nested scope so the dtor is called before ExitThread.
+
+ {
+ CRpcThread Thrd(param);
+ Thrd.WorkerLoop();
+ }
+
+
+ // Simultaneously free our Dll and exit our thread. This allows us to
+ // keep our Dll around incase a remote call was cancelled and the
+ // worker thread is still blocked on the call, and allows us to cleanup
+ // properly when all threads are done with the code.
+
+ FreeLibraryAndExitThread(hInst, 0);
+
+ // compiler wants a return value
+ return 0;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThread::CRpcThread
+//
+// Purpose: Constructor for a thread object.
+//
+// Notes: Allocates a wakeup event.
+//
+// Callers: Called ONLY by a worker thread.
+//
+//+-------------------------------------------------------------------
+CRpcThread::CRpcThread(void *param) :
+ _param(param),
+ _pNext(NULL),
+ _fDone(FALSE)
+{
+ // create the Wakeup event. Do NOT use the event cache, as there are
+ // some exit paths that leave this event in the signalled state!
+
+#ifdef _CHICAGO_ // Chicago ANSI optimization
+ _hWakeup = CreateEventA(NULL, FALSE, FALSE, NULL);
+#else //_CHICAGO_
+ _hWakeup = CreateEvent(NULL, FALSE, FALSE, NULL);
+#endif //_CHICAGO_
+
+ ComDebOut((DEB_CHANNEL,
+ "CRpcThread::CRpcThread pThrd:%x _hWakeup:%x\n", this, _hWakeup));
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThread::~CRpcThread
+//
+// Purpose: Destructor for an Rpc thread object.
+//
+// Notes: When threads are exiting, they place the CRpcThread
+// object on the delete list. The main thread then later
+// pulls it from the delete list and calls this destructor.
+//
+// Callers: Called ONLY by a worker thread.
+//
+//+-------------------------------------------------------------------
+CRpcThread::~CRpcThread()
+{
+ // close the event handle. Do NOT use the event cache, since not all
+ // exit paths leave this event in the non-signalled state. Also, do
+ // not close NULL handle.
+
+ if (_hWakeup)
+ {
+ CloseHandle(_hWakeup);
+ }
+
+ ComDebOut((DEB_CHANNEL,
+ "CRpcThread::~CRpcThread pThrd:%x _hWakeup:%x\n", this, _hWakeup));
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CRpcThread::WorkerLoop
+//
+// Purpose: Entry point for a new Rpc call thread.
+//
+// Notes: This dispatches a call to the function ThreadDispatch. That
+// code signals an event that the COM thread is waiting on, then
+// returns to us. We put the thread on the free list, and wait
+// for more work to do.
+//
+// When there is no more work after some timeout period, we
+// pull it from the free list and exit.
+//
+// Callers: Called ONLY by worker thread.
+//
+//+-------------------------------------------------------------------
+void CRpcThread::WorkerLoop()
+{
+ // Main worker loop where we do some work then wait for more.
+ // When the thread has been inactive for some period of time
+ // it will exit the loop.
+
+ while (!_fDone)
+ {
+ // Dispatch the call.
+ ThreadDispatch((CChannelCallInfo **)&_param);
+
+ if (!_hWakeup)
+ {
+ // we failed to create an event in the ctor so we cant
+ // get put on the freelist to be re-awoken later with more
+ // work. Just exit.
+ break;
+ }
+
+ // put the thread object on the free list
+ gRpcThreadCache.AddToFreeList(this);
+
+ // Wait for more work or for a timeout.
+ while (WaitForSingleObjectEx(_hWakeup, THREAD_INACTIVE_TIMEOUT, 0)
+ == WAIT_TIMEOUT)
+ {
+ // try to remove ourselves from the queue of free threads.
+ // if _fDone is still FALSE, it means someone is about to
+ // give us more work to do (so go wait for that to happen).
+
+ gRpcThreadCache.RemoveFromFreeList(this);
+
+ if (_fDone)
+ {
+ // OK to exit and let this thread die.
+ break;
+ }
+ }
+ }
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThreadCache::Dispatch
+//
+// Purpose: Finds the first free thread, and dispatches the request
+// to that thread, or creates a new thread if none are
+// available.
+//
+// Returns: S_OK if dispatched OK
+// Win32 error if it cant create a thread.
+//
+// Callers: Called ONLY by the main thread.
+//
+//+-------------------------------------------------------------------
+HRESULT CRpcThreadCache::Dispatch(void *param)
+{
+ HRESULT hr = S_OK;
+
+ _mxs.Request();
+
+ // grab the first thread from the list
+ CRpcThread *pThrd = _pFreeList;
+
+ if (pThrd)
+ {
+ // update the free list pointer
+ _pFreeList = pThrd->GetNext();
+ _mxs.Release();
+
+ // dispatch the call
+ pThrd->Dispatch(param);
+ }
+ else
+ {
+ _mxs.Release();
+
+ // no free threads, spin up a new one and dispatch directly to it.
+ DWORD dwThrdId;
+ HANDLE hThrd = CreateThread(NULL, 0,
+ RpcWorkerThreadEntry,
+ param, 0,
+ &dwThrdId);
+
+ if (hThrd)
+ {
+ // close the thread handle since we dont need it for anything.
+ CloseHandle(hThrd);
+ }
+ else
+ {
+ ComDebOut((DEB_ERROR,"CreatThread failed:%x\n", GetLastError()));
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThreadCache::RemoveFromFreeList
+//
+// Purpose: Tries to pull a thread from the free list.
+//
+// Returns: pThrd->_fDone TRUE if it was successfull and thread can exit.
+// pThrd->_fDone FALSE otherwise.
+//
+// Callers: Called ONLY by a worker thread.
+//
+//+-------------------------------------------------------------------
+void CRpcThreadCache::RemoveFromFreeList(CRpcThread *pThrd)
+{
+ ComDebOut((DEB_CHANNEL,
+ "CRpcThreadCache::RemoveFromFreeList pThrd:%x\n", pThrd));
+
+ COleStaticLock lck(_mxs);
+
+ // pull pThrd from the free list. if it is not on the free list
+ // then either it has just been dispatched OR ClearFreeList has
+ // just removed it, set _fDone to TRUE, and kicked the wakeup event.
+
+ CRpcThread *pPrev = NULL;
+ CRpcThread *pCurr = _pFreeList;
+
+ while (pCurr && pCurr != pThrd)
+ {
+ pPrev = pCurr;
+ pCurr = pCurr->GetNext();
+ }
+
+ if (pCurr == pThrd)
+ {
+ // remove it from the free list.
+ if (pPrev)
+ pPrev->SetNext(pThrd->GetNext());
+ else
+ _pFreeList = pThrd->GetNext();
+
+ // tell the thread to wakeup and exit
+ pThrd->WakeAndExit();
+ }
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThreadCache::ClearFreeList
+//
+// Purpose: Cleans up all threads on the free list.
+//
+// Notes: For any threads still on the free list, it pulls them
+// off the freelist, sets their _fDone flag to TRUE, and
+// kicks their event to wake them up. When the threads
+// wakeup, they will exit.
+//
+// We do not free active threads. The only way for a thread
+// to still be active at this time is if it was making an Rpc
+// call and was cancelled by the message filter and the thread has
+// still not returned to us. We cant do much about that until
+// Rpc supports cancel for all protocols. If the thread ever
+// does return to us, it will eventually idle-out and delete
+// itself. This is safe because the threads LoadLibrary OLE32.
+//
+// Callers: Called ONLY by the last COM thread during
+// ProcessUninitialize.
+//
+//+-------------------------------------------------------------------
+void CRpcThreadCache::ClearFreeList(void)
+{
+ ComDebOut((DEB_CHANNEL, "CRpcThreadCache::ClearFreeList\n"));
+
+ {
+ COleStaticLock lck(_mxs);
+
+ CRpcThread *pThrd = _pFreeList;
+ while (pThrd)
+ {
+ // use temp variable incase thread exits before we call GetNext
+ CRpcThread *pThrdNext = pThrd->GetNext();
+ pThrd->WakeAndExit();
+ pThrd = pThrdNext;
+ }
+
+ _pFreeList = NULL;
+
+ // the lock goes out of scope at this point. we dont want to hold
+ // it while we sleep.
+ }
+
+ // yield to let the other threads run if necessary.
+ Sleep(0);
+}
diff --git a/private/ole32/com/dcomrem/threads.hxx b/private/ole32/com/dcomrem/threads.hxx
new file mode 100644
index 000000000..5c66b3941
--- /dev/null
+++ b/private/ole32/com/dcomrem/threads.hxx
@@ -0,0 +1,190 @@
+//+-------------------------------------------------------------------
+//
+// File: threads.hxx
+//
+// Contents: Rpc thread cache
+//
+// Classes: CRpcThread - single thread
+// CRpcThreadCache - cache of threads
+//
+// Notes: This code represents the cache of Rpc threads used to
+// make outgoing calls in the APARTMENT object Rpc
+// model.
+//
+// History: Rickhi Created
+// 07-31-95 Rickhi Fix event handle leak
+//
+//+-------------------------------------------------------------------
+#ifndef __THREADS_HXX__
+#define __THREADS_HXX__
+
+#include <olesem.hxx>
+
+
+// inactive thread timeout. this is how long a thread will sit idle
+// in the thread cache before deleting itself.
+
+#define THREAD_INACTIVE_TIMEOUT 30000 // in milliseconds
+
+
+//+-------------------------------------------------------------------
+//
+// Class: CRpcThread
+//
+// Purpose: Represents one thread in the cache of Rpc callout
+// threads.
+//
+// Notes: In order to make Rpc calls in the OLE Single-Threaded
+// model, we must leave the main thread and perform the
+// blocking Rpc call on a worker thread. This object
+// represents such a worker thread.
+//
+//+-------------------------------------------------------------------
+class CRpcThread
+{
+public:
+ CRpcThread(void *param);
+ ~CRpcThread();
+
+ // dispatch methods
+ void Dispatch(void *param);
+ void WorkerLoop();
+ CRpcThread * GetNext(void) { return _pNext; }
+ void SetNext(CRpcThread *pNext) { _pNext = pNext; }
+
+ // cleanup methods
+ void WakeAndExit();
+
+private:
+
+ HANDLE _hWakeup; // thread wakeup event
+ BOOL _fDone; // completion flag
+
+ void * _param; // parameter packet
+ CRpcThread * _pNext; // next thread in free list
+};
+
+
+//+-------------------------------------------------------------------
+//
+// Class: CRpcThreadCache
+//
+// Purpose: Holds a cache of Rpc threads. It finds the first
+// free CRpcThread or creates a new one and dispatches
+// the call to it.
+//
+// Notes: the free list is kept in a most recently used order
+// so that uneeded threads can time out and go away.
+//
+//+-------------------------------------------------------------------
+class CRpcThreadCache
+{
+public:
+ // no ctor, since only work is init'ing a static
+ // no dtor since nothing to do
+
+ // dispatch methods
+ HRESULT Dispatch(void *param);
+ void AddToFreeList(CRpcThread *pThrd);
+
+ // cleanup methods
+ void RemoveFromFreeList(CRpcThread *pThrd);
+ void ClearFreeList(void);
+
+private:
+
+ static DWORD _stdcall RpcWorkerThreadEntry(void *param);
+
+ static CRpcThread * _pFreeList; // list of free threads
+ static COleStaticMutexSem _mxs; // for list manipulation
+};
+
+
+// Rpc SendReceive thread pool. This must be static to handle Rpc threads
+// that block and dont return until after CoUninitialize has been called.
+
+extern CRpcThreadCache gRpcThreadCache;
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThread::Dispatch
+//
+// Purpose: wakes up a thread blocked in WorkerLoop.
+//
+// Notes: folks who want to execute code on another thread
+// call this method. It fills in the parameter packet
+// and wakes up the sleeping thread.
+//
+// Callers: Called ONLY by the COM thread.
+//
+//+-------------------------------------------------------------------
+inline void CRpcThread::Dispatch(void *param)
+{
+ CairoleDebugOut((DEB_CHANNEL,
+ "Dispatch pThrd:%x param:%x\n", this, param));
+
+ // set the call info and the completion event
+ _param = param;
+
+ // signal the Rpc thread to wakeup
+ SetEvent(_hWakeup);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThread::WakeAndExit
+//
+// Purpose: Tells the thread object to free itself
+//
+// Note: This is called by CRpcThreadCache::RemoveFromFreeList
+// when we want to free this thread, eg at ProcessUninitialize.
+//
+// Callers: Called by the COM thread OR worker thread.
+//
+//+-------------------------------------------------------------------
+inline void CRpcThread::WakeAndExit()
+{
+ // _fDone should only be set inside this function and in the
+ // constructor. _fDone must only ever transition from FALSE
+ // to TRUE and that must only happen once in the life of this
+ // object.
+
+ Win4Assert(_fDone == FALSE);
+ _fDone = TRUE;
+
+ CairoleDebugOut((DEB_CHANNEL,
+ "CRpcThreadCache:WakeAndExit pThrd:%x _hWakeup:%x\n", this, _hWakeup));
+
+ SetEvent(_hWakeup);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThreadCache::AddToFreeLlist
+//
+// Purpose: puts a thread back onto the free list after the
+// thread has completed its job.
+//
+// Callers: Called ONLY by worker thread.
+//
+//+-------------------------------------------------------------------
+inline void CRpcThreadCache::AddToFreeList(CRpcThread *pThrd)
+{
+ COleStaticLock lck(_mxs);
+
+ // place this thread on the front of the free list. it is
+ // important that we add and remove only from the front of
+ // the list so that unused threads will eventually time out
+ // and release themselves...that is, it keeps our thread pool
+ // as small as possible.
+
+ pThrd->SetNext(_pFreeList);
+ _pFreeList = pThrd;
+}
+
+
+#endif // __THREADS_HXX__
diff --git a/private/ole32/com/dde/client/cnct_tbl.cxx b/private/ole32/com/dde/client/cnct_tbl.cxx
new file mode 100644
index 000000000..bc7200223
--- /dev/null
+++ b/private/ole32/com/dde/client/cnct_tbl.cxx
@@ -0,0 +1,182 @@
+// cnct_tbl.cpp
+//
+// class CConnectionTable
+//
+// CConnectionTable maps connection numbers (as returned by ::Advise())
+// to clipformat's for DDE advise connections.
+
+#include "ddeproxy.h"
+#include "cnct_tbl.h"
+
+ASSERTDATA
+
+#define grfMemFlags (GMEM_MOVEABLE | GMEM_ZEROINIT)
+
+// number of INFO entries to grow by
+#define cinfoBlock 10
+
+typedef struct INFO
+{
+ BOOL fUsed; // is this table entry used?
+ DWORD dwConnection; // search key
+ CLIPFORMAT cf; // corresponding cf, for use in DDE_(UN)ADVISE
+ DWORD grfAdvf; // ON_CHANGE or ON_SAVE or ON_CLOSE
+} INFO, FAR* PINFO;
+
+
+
+CDdeConnectionTable::CDdeConnectionTable ()
+{
+ m_h = GlobalAlloc (grfMemFlags, cinfoBlock * sizeof(INFO));
+ Assert (m_h);
+ m_cinfo=cinfoBlock;
+}
+
+
+CDdeConnectionTable::~CDdeConnectionTable ()
+{
+ Assert(m_h);
+ m_h =GlobalFree (m_h);
+ Assert (m_h==NULL);
+ m_cinfo=0;
+}
+
+
+
+
+INTERNAL CDdeConnectionTable::Add
+ (DWORD dwConnection,
+ CLIPFORMAT cf,
+ DWORD grfAdvf)
+{
+ Start:
+ PINFO rginfo;
+
+ if (NULL==(rginfo = (PINFO) GlobalLock(m_h)))
+ {
+ Puts ("ERROR: CDdeConnectionTable::Add out of memory\n");
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ // Look for an empty table entry
+ for (DWORD i=0; i<m_cinfo; i++)
+ {
+ if (!rginfo[i].fUsed)
+ {
+ rginfo[i].fUsed = TRUE;
+ rginfo[i].dwConnection = dwConnection;
+ rginfo[i].cf = cf;
+ rginfo[i].grfAdvf = grfAdvf;
+ break;
+ }
+ else
+ {
+ Assert (rginfo[i].dwConnection != dwConnection);
+ }
+ }
+ GlobalUnlock (m_h);
+ if (i==m_cinfo) // if no empty entry found
+ {
+ Puts ("Growing the connection table\n");
+ m_h = GlobalReAlloc (m_h,(m_cinfo += cinfoBlock) * sizeof(INFO),
+ grfMemFlags);
+ if (m_h==NULL)
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ goto Start;
+ }
+ else
+ {
+ return NOERROR;
+ }
+}
+
+
+
+
+INTERNAL CDdeConnectionTable::Subtract
+ (DWORD dwConnection,
+ CLIPFORMAT FAR* pcf, // out parm
+ DWORD FAR* pgrfAdvf) // out parm
+{
+ PINFO rginfo;
+ if (dwConnection==0)
+ {
+ Puts ("CDdeConnectionTable::Subtract called with dwConnection==0\n");
+ return ReportResult(0, E_INVALIDARG, 0, 0);
+ }
+
+ if (NULL==(rginfo = (PINFO) GlobalLock(m_h)))
+ {
+ Assert (0);
+ Puts ("ERROR: CDdeConnectionTable::Subtract out of memory\n");
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ for (DWORD i=0; i<m_cinfo; i++)
+ {
+ if (rginfo[i].fUsed && rginfo[i].dwConnection == dwConnection)
+ {
+ Assert (pcf);
+ *pcf = rginfo[i].cf;
+ Assert (pgrfAdvf);
+ *pgrfAdvf = rginfo[i].grfAdvf;
+ rginfo[i].fUsed = FALSE; // remove this connection
+ GlobalUnlock (m_h);
+ return NOERROR;
+ }
+ }
+ GlobalUnlock (m_h);
+ return ReportResult(0, S_FALSE, 0, 0); // not found
+}
+
+
+
+
+INTERNAL CDdeConnectionTable::Lookup
+ (CLIPFORMAT cf, // search key
+ LPDWORD pdwConnection) // out parm. May be NULL on input
+{
+ PINFO rginfo;
+
+ if (NULL==(rginfo = (PINFO) GlobalLock(m_h)))
+ {
+ Puts ("ERROR: CDdeConnectionTable::Lookup out of memory\n");
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ for (DWORD i=0; i<m_cinfo; i++)
+ {
+ if (rginfo[i].fUsed &&
+ rginfo[i].cf == cf)
+ {
+ if (pdwConnection)
+ *pdwConnection = rginfo[i].dwConnection;
+ GlobalUnlock (m_h);
+ return NOERROR;
+ }
+ }
+ GlobalUnlock (m_h);
+ return ReportResult(0, S_FALSE, 0, 0); // not found
+}
+
+
+
+INTERNAL CDdeConnectionTable::Erase
+ (void)
+{
+ PINFO rginfo;
+ Assert (wIsValidHandle(m_h, NULL));
+ if (NULL==(rginfo = (PINFO) GlobalLock(m_h)))
+ {
+ Puts ("ERROR: CDdeConnectionTable::Lookup out of memory\n");
+ Assert (0);
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ for (DWORD i=0; i<m_cinfo; i++)
+ {
+ rginfo[i].fUsed = FALSE;
+ }
+ GlobalUnlock (m_h);
+ return NOERROR;
+}
+
diff --git a/private/ole32/com/dde/client/cnct_tbl.h b/private/ole32/com/dde/client/cnct_tbl.h
new file mode 100644
index 000000000..656b9ce89
--- /dev/null
+++ b/private/ole32/com/dde/client/cnct_tbl.h
@@ -0,0 +1,27 @@
+// cnct_tbl.h
+
+// CConnectionTable maps connection numbers (as returned by ::Advise())
+// to clipformat's for DDE advise connections.
+
+#ifndef fCnct_tbl_h
+#define fCnct_tbl_h
+
+class FAR CDdeConnectionTable : public CPrivAlloc
+{
+ public:
+ CDdeConnectionTable();
+ ~CDdeConnectionTable();
+
+ INTERNAL Add (DWORD dwConnection, CLIPFORMAT cf, DWORD grfAdvf);
+ INTERNAL Subtract (DWORD dwConnection, CLIPFORMAT FAR* pcf, DWORD FAR* pgrfAdvf);
+ INTERNAL Lookup (CLIPFORMAT cf, LPDWORD pdwConnection);
+ INTERNAL Erase (void);
+
+ private:
+ HANDLE m_h; // handle to the table
+ DWORD m_cinfo; // total number of INFO entries
+};
+
+
+#endif
+
diff --git a/private/ole32/com/dde/client/daytona/makefile b/private/ole32/com/dde/client/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/dde/client/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/dde/client/daytona/sources b/private/ole32/com/dde/client/daytona/sources
new file mode 100644
index 000000000..e264f3c35
--- /dev/null
+++ b/private/ole32/com/dde/client/daytona/sources
@@ -0,0 +1,85 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+!include ..\..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= ddecli
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES = ..\..\server;..\..\..\..\common\daytona;..\..\..\..\ih
+INCLUDES = $(INCLUDES);..\..\..\dcomrem;..\..\..\inc;..\..\..\dcomidl\daytona;
+INCLUDES = $(INCLUDES);..\..\..\class;..\..\..\objact;
+INCLUDES = $(INCLUDES);..\..\..\..\ole232\inc
+INCLUDES = $(INCLUDES);$(BASEDIR)\private\dcomidl\obj
+
+C_DEFINES= -DOLE_DDE_NO_GLOBAL_TRACKING=1\
+ $(C_DEFINES)
+
+
+SOURCES= \
+ ..\cnct_tbl.cxx \
+ ..\ddedo.cxx \
+ ..\ddeioc.cxx \
+ ..\ddemnker.cxx \
+ ..\ddeoo.cxx \
+ ..\ddeproxy.cxx \
+ ..\ddechc.cxx \
+ ..\ddestg.cxx \
+ ..\ddewnd.cxx \
+ ..\ddeworkr.cxx \
+ ..\modallp.cxx \
+ ..\packmnkr.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+# PRECOMPILED_INCLUDE= ..\headers.cxx
diff --git a/private/ole32/com/dde/client/ddechc.cxx b/private/ole32/com/dde/client/ddechc.cxx
new file mode 100644
index 000000000..e89b7af4f
--- /dev/null
+++ b/private/ole32/com/dde/client/ddechc.cxx
@@ -0,0 +1,89 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: DdeChC.cxx
+//
+// Contents: CDdeChannelControl implementation for DDE. This
+// implementation requires no instance data, therefore it is
+// intended to be static.
+//
+// Functions:
+//
+// History: 08-May-94 Johann Posch (johannp) Created
+// 10-May-94 KevinRo Made simpler
+// 29-May-94 KevinRo Added DDE Server support
+//
+//--------------------------------------------------------------------------
+#include "ddeproxy.h"
+
+//+---------------------------------------------------------------------------
+//
+// Function: DispatchCall
+//
+// Synopsis: DispatchCall is called to handle incoming calls.
+//
+// Effects: Dispatches a call to the specified in the DispatchData.
+// This function is the result of a call in OnData(), which
+// processes incoming calls from the OLE 1.0 server.
+//
+// Arguments: [pDispData] -- Points to the dispatch data structure
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-16-94 JohannP Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL DispatchCall( PDISPATCHDATA pDispData )
+{
+ intrDebugOut((DEB_ITRACE,
+ "DispatchCall(pDispData=%x)\n",
+ pDispData));
+
+ intrAssert(pDispData != NULL);
+ POLE1DISPATCHDATA pData = (POLE1DISPATCHDATA)pDispData->pData;
+ intrAssert(pData != NULL);
+
+ switch (pData->wDispFunc)
+ {
+ case DDE_DISP_SENDONDATACHANGE: // OnDataChange
+ {
+ PDDEDISPATCHDATA pDData = (PDDEDISPATCHDATA)pDispData->pData;
+ return pDData->pCDdeObject->SendOnDataChange(pDData->iArg);
+ }
+
+ case DDE_DISP_OLECALLBACK: // OleCallBack
+ {
+ PDDEDISPATCHDATA pDData = (PDDEDISPATCHDATA)pDispData->pData;
+ return pDData->pCDdeObject->OleCallBack(pDData->iArg,NULL);
+ }
+
+ //
+ // The server window has an incoming call. Look in dde\server\srvr.cxx
+ //
+ case DDE_DISP_SRVRWNDPROC:
+ return(SrvrDispatchIncomingCall((PSRVRDISPATCHDATA)pDispData->pData));
+ //
+ // This dispatches to a Document window
+ //
+ case DDE_DISP_DOCWNDPROC:
+ return(DocDispatchIncomingCall((PDOCDISPATCHDATA)pDispData->pData));
+
+ default:
+ intrAssert(!"Unknown wDispFunc");
+ }
+ return E_FAIL;
+}
diff --git a/private/ole32/com/dde/client/ddechc.hxx b/private/ole32/com/dde/client/ddechc.hxx
new file mode 100644
index 000000000..be75388ec
--- /dev/null
+++ b/private/ole32/com/dde/client/ddechc.hxx
@@ -0,0 +1,115 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: DdeChC.cxx
+//
+// Contents: CDdeChannelControl implementation for DDE. This
+// implementation requires no instance data, therefore it is
+// intended to be static.
+//
+// Functions:
+//
+// History: 08-May-94 Johann Posch (johannp) Created
+// 10-May-94 KevinRo Made simpler and commented
+//
+//--------------------------------------------------------------------------
+#ifndef __DDECHC_HXX__
+#define __DDECHC_HXX__
+
+class CDdeObject;
+//
+// The following are the possible callbacks that would be supported by
+// the CDdeObject
+//
+
+typedef enum
+{
+ DDE_DISP_SENDONDATACHANGE = 1,
+ DDE_DISP_OLECALLBACK = 2 ,
+ DDE_DISP_SRVRWNDPROC = 3 ,
+ DDE_DISP_DOCWNDPROC = 4
+} DDE_DISPATCH_FUNC;
+
+
+//
+// The following defines a base class for the OLE 1.0 support
+//
+
+typedef struct tagOLE1DISPATCHDATA
+{
+ DDE_DISPATCH_FUNC wDispFunc;
+}OLE1DISPATCHDATA, *POLE1DISPATCHDATA;
+
+//
+// The following structure is used by OLE 1.0 server support code
+//
+
+typedef struct tagDDEDISPATCHDATA : public CPrivAlloc, public OLE1DISPATCHDATA
+{
+ CDdeObject *pCDdeObject;
+ UINT iArg;
+} DDEDISPATCHDATA, *PDDEDISPATCHDATA;
+
+
+//
+// The following structure is used by the OLE 1.0 client support code
+// to dispatch incoming calls to Execute from the server window.
+//
+
+typedef struct tagSRVRDISPATCHDATA : public OLE1DISPATCHDATA,public CPrivAlloc
+{
+ HWND hwnd;
+ HANDLE hData;
+ HWND wParam;
+ LPSRVR lpsrvr;
+} SRVRDISPATCHDATA, *PSRVRDISPATCHDATA;
+
+INTERNAL SrvrDispatchIncomingCall(PSRVRDISPATCHDATA psdd);
+
+
+//
+// The following structure is used by the OLE 1.0 client support code
+// to dispatch incoming calls to a document window
+//
+
+typedef struct tagDOCDISPATCHDATA : public OLE1DISPATCHDATA,public CPrivAlloc
+{
+ HWND hwnd;
+ ULONG msg;
+ WPARAM wParam;
+ LPARAM lParam;
+ HANDLE hdata; // If already determined, these two hold
+ ATOM aItem; // valid data. All depends on the message
+ LPCLIENT lpclient;
+} DOCDISPATCHDATA, *PDOCDISPATCHDATA;
+
+INTERNAL DocDispatchIncomingCall(PDOCDISPATCHDATA psdd);
+
+
+
+//
+// DDECALLDATA is all the information needed to transmit the outbound call
+// to the server. Since this DDE channel uses PostMessage, the members
+// should look amazingly alot like the parameters to PostMessage.
+//
+// The hwndCli is used for setting callback information.
+//
+typedef struct tagDDECALLDATA : public CPrivAlloc
+{
+ HWND hwndSvr; // Server DDE window
+ WORD wMsg; // Post parameters
+ WPARAM wParam;
+ LPARAM lParam;
+
+ HWND hwndCli; // Handle to client side window
+ BOOL fFreeOnError;
+ BOOL fDone;
+ class DDE_CHANNEL * pChannel;
+} DDECALLDATA, *PDDECALLDATA;
+
+INTERNAL DispatchCall(PDISPATCHDATA);
+
+
+#endif // __DDECHC__HXX__
diff --git a/private/ole32/com/dde/client/ddecnvrt.cxx b/private/ole32/com/dde/client/ddecnvrt.cxx
new file mode 100644
index 000000000..119c67d15
--- /dev/null
+++ b/private/ole32/com/dde/client/ddecnvrt.cxx
@@ -0,0 +1,348 @@
+
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddecnvrt.cpp
+
+Abstract:
+
+ This module contains the code to read/write PBrush, MSDraw native data
+ formats. This module also contains PBrush native format <->DIbFile stream,
+ and MSDraw native format <-> placeable metafile stream conversion routines.
+
+Author:
+
+ Srini Koppolu (srinik) 06/29/1993
+
+Revision History:
+
+--*/
+
+#ifndef _MAC
+
+
+/************************ FILE FORMATS **********************************
+
+
+Normal Metafile (memory or disk based):
+
+ ------------ ---------------
+ | METAHEADER | Metafile bits |
+ ------------ ---------------
+
+Placeable Metafile:
+
+ --------------------- -----------------
+ | PLACEABLEMETAHEADER | Normal metafile |
+ --------------------- -----------------
+
+Memory Based DIB:
+
+ ------------------ --------------- ----------
+ | BITMAPINFOHEADER | RGBQUAD array | DIB bits |
+ ------------------ --------------- ----------
+
+DIB file format:
+
+ ------------------ ------------------
+ | BITMAPFILEHEADER | Memory based DIB |
+ ------------------ ------------------
+
+Ole10NativeStream Format:
+
+ -------- ----------------------
+ | dwSize | Object's Native data |
+ -------- ----------------------
+
+PBrush Native data format:
+
+ -----------------
+ | Dib File format |
+ -----------------
+
+MSDraw Native data format:
+
+ --------------------- ------------- ------------- -----------------
+ | mapping mode (WORD) | xExt (WORD) | yExt (WORD) | Normal metafile |
+ --------------------- ------------- ------------- -----------------
+
+
+*****************************************************************************/
+
+#include <ole2int.h>
+
+INTERNAL UtGetHMFPICTFromMSDrawNativeStm
+ (LPSTREAM pstm, DWORD dwSize, HANDLE FAR* lphdata)
+{
+ HRESULT error;
+ WORD mfp[3]; // mm, xExt, yExt
+ HMETAFILE hMF = NULL;
+
+ *lphdata = NULL;
+
+ if (error = pstm->Read(mfp, sizeof(mfp), NULL))
+ return error;
+
+ dwSize -= sizeof(mfp);
+
+ if (error = UtGetHMFFromMFStm(pstm, dwSize, FALSE, (void **)&hMF))
+ return error;
+
+ AssertSz(mfp[0] == MM_ANISOTROPIC, "invalid map mode in MsDraw native data");
+
+ if (*lphdata = UtGetHMFPICT(hMF, TRUE, (int) mfp[1], (int) mfp[2]))
+ return NOERROR;
+
+ return ResultFromScode(E_OUTOFMEMORY);
+}
+
+
+INTERNAL UtPlaceableMFStmToMSDrawNativeStm
+ (LPSTREAM pstmPMF, LPSTREAM pstmMSDraw)
+{
+ DWORD dwSize; // size of metafile bits excluding the placeable MF header
+ LONG xExt;
+ LONG yExt;
+ WORD wBuf[5]; // dwSize(DWORD), mm(int), xExt(int), yExt(int)
+ HRESULT error;
+
+ if (error = UtGetSizeAndExtentsFromPlaceableMFStm(pstmPMF, &dwSize,
+ &xExt, &yExt))
+ return error;
+
+ *((DWORD FAR*) wBuf) = dwSize + 3*sizeof(WORD);
+ wBuf[2] = MM_ANISOTROPIC;
+ wBuf[3] = (int) xExt;
+ wBuf[4] = (int) yExt;
+
+ if (error = pstmMSDraw->Write(wBuf, sizeof(wBuf), 0))
+ return error;
+
+ ULARGE_INTEGER ularge_int;
+ ULISet32(ularge_int, dwSize);
+ if ((error = pstmPMF->CopyTo(pstmMSDraw, ularge_int,
+ NULL, NULL)) == NOERROR)
+ StSetSize(pstmMSDraw);
+
+ return error;
+
+}
+
+
+INTERNAL UtDIBFileStmToPBrushNativeStm
+ (LPSTREAM pstmDIBFile, LPSTREAM pstmPBrush)
+{
+ BITMAPFILEHEADER bfh;
+ HRESULT error;
+
+ if (error = pstmDIBFile->Read(&bfh, sizeof(bfh), 0))
+ return error;
+
+ // seek to the begining of the stream
+ LARGE_INTEGER large_int;
+ LISet32( large_int, 0);
+ if (error = pstmDIBFile->Seek(large_int, STREAM_SEEK_SET, 0))
+ return error;
+
+ if (error = pstmPBrush->Write(&(bfh.bfSize), sizeof(DWORD), 0))
+ return error;
+
+ ULARGE_INTEGER ularge_int;
+ ULISet32(ularge_int, bfh.bfSize);
+
+ if ((error = pstmDIBFile->CopyTo(pstmPBrush, ularge_int,
+ NULL, NULL)) == NOERROR)
+ StSetSize(pstmPBrush);
+
+ return error;
+}
+
+
+
+INTERNAL UtContentsStmTo10NativeStm
+ (LPSTORAGE pstg, REFCLSID rclsid, BOOL fDeleteSrcStm, UINT FAR* puiStatus)
+{
+ CLIPFORMAT cf;
+ LPOLESTR lpszUserType = NULL;
+ HRESULT error;
+ LPSTREAM pstmSrc = NULL;
+ LPSTREAM pstmDst = NULL;
+
+ *puiStatus = NULL;
+
+ if (error = ReadFmtUserTypeStg(pstg, &cf, &lpszUserType))
+ return error;
+
+
+ if (! ((cf == CF_DIB && rclsid == CLSID_PBrush)
+ || (cf == CF_METAFILEPICT && rclsid == CLSID_MSDraw))) {
+ error = ResultFromScode(DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+
+ if (error = pstg->OpenStream(CONTENTS_STREAM, NULL,
+ (STGM_READ|STGM_SHARE_EXCLUSIVE),
+ 0, &pstmSrc)) {
+ *puiStatus |= CONVERT_NOSOURCE;
+
+ // check whether OLE10_NATIVE_STREAM exists
+ if (pstg->OpenStream(OLE10_NATIVE_STREAM, NULL,
+ (STGM_READ|STGM_SHARE_EXCLUSIVE), 0, &pstmDst))
+ *puiStatus |= CONVERT_NODESTINATION;
+ else {
+ pstmDst->Release();
+ pstmDst = NULL;
+ }
+
+ goto errRtn;
+ }
+
+ if (error = OpenOrCreateStream(pstg, OLE10_NATIVE_STREAM, &pstmDst)) {
+ *puiStatus |= CONVERT_NODESTINATION;
+ goto errRtn;
+ }
+
+ if (cf == CF_METAFILEPICT)
+ error = UtPlaceableMFStmToMSDrawNativeStm(pstmSrc, pstmDst);
+ else
+ error = UtDIBFileStmToPBrushNativeStm(pstmSrc, pstmDst);
+
+errRtn:
+ if (pstmDst)
+ pstmDst->Release();
+
+ if (pstmSrc)
+ pstmSrc->Release();
+
+ if (error == NOERROR) {
+ LPOLESTR lpszProgId = NULL;
+ ProgIDFromCLSID(rclsid, &lpszProgId);
+
+ error = WriteFmtUserTypeStg(pstg,
+ RegisterClipboardFormat(lpszProgId),
+ lpszUserType);
+
+ if (lpszProgId)
+ delete lpszProgId;
+ }
+
+ if (error == NOERROR) {
+ if (fDeleteSrcStm)
+ pstg->DestroyElement(CONTENTS_STREAM);
+ } else {
+ pstg->DestroyElement(OLE10_NATIVE_STREAM);
+ }
+
+ if (lpszUserType)
+ delete lpszUserType;
+
+ return error;
+}
+
+
+
+INTERNAL Ut10NativeStmToContentsStm
+ (LPSTORAGE pstg, REFCLSID rclsid, BOOL fDeleteSrcStm)
+{
+ extern CLIPFORMAT cfPBrush;
+ extern CLIPFORMAT cfMSDraw;
+
+ CLIPFORMAT cfOld;
+ CLIPFORMAT cfNew;
+ LPOLESTR lpszUserType = NULL;
+ HRESULT error;
+ LPSTREAM pstmSrc = NULL;
+ LPSTREAM pstmDst = NULL;
+
+
+ if (error = ReadFmtUserTypeStg(pstg, &cfOld, &lpszUserType))
+ return error;
+
+ if (rclsid == CLSID_StaticDib)
+ cfNew = CF_DIB;
+ else if (rclsid == CLSID_StaticMetafile)
+ cfNew = CF_METAFILEPICT;
+ else {
+ AssertSz(FALSE, "Internal Error: this routine shouldn't have been called for this class");
+ return ResultFromScode(E_FAIL);
+ }
+
+ if (cfOld == cfPBrush) {
+ if (cfNew != CF_DIB) {
+ error = ResultFromScode(DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+ } else if (cfOld == cfMSDraw) {
+ if (cfNew != CF_METAFILEPICT) {
+ error = ResultFromScode(DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+ } else {
+ // Converted to static object from some class other than PBrush or
+ // MSDraw. The data must be in a proper format in the CONTENTS
+ // stream.
+ return NOERROR;
+ }
+
+ if (error = pstg->OpenStream(OLE10_NATIVE_STREAM, NULL,
+ (STGM_READ|STGM_SHARE_EXCLUSIVE),
+ 0, &pstmSrc))
+ goto errRtn;
+
+ if (error = OpenOrCreateStream(pstg, CONTENTS_STREAM, &pstmDst))
+ goto errRtn;
+
+ DWORD dwSize;
+ if (error = pstmSrc->Read(&dwSize, sizeof(DWORD), NULL))
+ goto errRtn;
+
+ if (cfOld == cfMSDraw) {
+ WORD mfp[3]; // mm, xExt, yExt
+
+ if (error = pstmSrc->Read(mfp, sizeof(mfp), NULL))
+ goto errRtn;
+
+ dwSize -= sizeof(mfp);
+
+ error = UtMFStmToPlaceableMFStm(pstmSrc, dwSize,
+ (LONG) mfp[1], (LONG) mfp[2], pstmDst);
+
+ } else {
+ // The PBrush native data format is DIB File format. So all we got to
+ // do is CopyTo.
+
+ ULARGE_INTEGER ularge_int;
+ ULISet32(ularge_int, dwSize);
+ if ((error = pstmSrc->CopyTo(pstmDst, ularge_int, NULL,
+ NULL)) == NOERROR)
+ StSetSize(pstmDst);
+ }
+
+errRtn:
+ if (pstmDst)
+ pstmDst->Release();
+
+ if (pstmSrc)
+ pstmSrc->Release();
+
+ if (error == NOERROR) {
+ error = WriteFmtUserTypeStg(pstg, cfNew, lpszUserType);
+
+ if (fDeleteSrcStm)
+ pstg->DestroyElement(OLE10_NATIVE_STREAM);
+
+ } else {
+ pstg->DestroyElement(CONTENTS_STREAM);
+ }
+
+ if (lpszUserType)
+ delete lpszUserType;
+
+ return error;
+}
+
+#endif
+
diff --git a/private/ole32/com/dde/client/ddedo.cxx b/private/ole32/com/dde/client/ddedo.cxx
new file mode 100644
index 000000000..b74ba3dd3
--- /dev/null
+++ b/private/ole32/com/dde/client/ddedo.cxx
@@ -0,0 +1,951 @@
+/*
+ddedo.cpp
+DDE Data Object
+
+copyright (c) 1992 Microsoft Corporation
+
+Abstract:
+
+ This module contains the methods for DdeObject::DataObject
+
+Author:
+
+ Jason Fuller (jasonful) 24-July-1992
+
+*/
+
+#include "ddeproxy.h"
+#include <stddef.h>
+#include "trgt_dev.h"
+
+
+#define f10UserModel
+// Should we ignore a request by a 2.0 client to get advise-on-change,
+// so that the user must do an explicit File/Update or File/Close?
+// Probably yes, because:
+// 1) Advise-on-change can be expensive for apps like PaintBrush.
+// 2) It is confusing if the container asks for change updates
+// ONLY on presentation and not on native because when the user
+// closes the server and is asked "Do you want to update?" he'll say no
+// because the picture LOOKS correct even though the container does not
+// have the native data.
+// 3) Excel: if A1 is the first cell you create, changes to other cells
+// will not be sent to the client until you change A1 again.
+// If advises are only sent explicitly, then all the cells extant at that
+// time will be considered part of the object.
+
+
+ASSERTDATA
+
+
+//
+// DataObject methods
+//
+
+STDUNKIMPL_FORDERIVED(DdeObject, DataObjectImpl)
+
+
+static inline INTERNAL_(BOOL) NotEqual
+ (DVTARGETDEVICE FAR* ptd1,
+ DVTARGETDEVICE FAR* ptd2)
+{
+ if (NULL==ptd1 && NULL==ptd2)
+ return FALSE;
+ else if ((ptd1 && !ptd2)
+ || (ptd2 && !ptd1)
+ || (ptd1->tdSize != ptd2->tdSize))
+ {
+ return TRUE;
+ }
+ else
+#ifdef WIN32
+ return 0 != memcmp(ptd1, ptd2, (size_t)ptd1->tdSize);
+#else
+ return 0 != _fmemcmp(ptd1, ptd2, (size_t)ptd1->tdSize);
+#endif
+}
+
+
+
+// GetData
+//
+// The data is copied out of a private cache consisting of
+// DdeObject::m_hNative, DdeObject::m_hPict, and DdeObject::m_hExtra.
+// If the cache is empty, data is requested using WM_DDE_REQUEST.
+// The cache should only be empty before the first DDE_DATA message
+// is received.
+// See DdeObject::KeepData()
+//
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::GetData
+ (LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetData(%x,pformatetcIn=%x)\n",
+ this,pformatetcIn));
+
+lStart:
+ intrDebugOut((DEB_ITRACE,"::GetData(%x)lStart\n",this));
+
+ LPSTR lpGlobal=NULL;
+ HRESULT hres;
+ VDATEPTROUT (pmedium, STGMEDIUM);
+ pmedium->tymed = TYMED_NULL;
+ pmedium->pUnkForRelease = NULL;
+
+ if ((hres = wVerifyFormatEtc (pformatetcIn)) != NOERROR)
+ {
+ goto exitRtn;
+ }
+
+ hres = E_UNEXPECTED; // assume error unless a clipboard format is found.
+
+ if (DVASPECT_ICON & pformatetcIn->dwAspect)
+ {
+ hres = GetDefaultIcon(m_pDdeObject->m_clsid, NULL, &pmedium->hGlobal);
+ if (hres != NOERROR)
+ {
+ goto exitRtn;
+ }
+ hres = NOERROR;
+ goto lDone;
+ }
+ if (m_pDdeObject->m_fGotCloseData)
+ {
+ // If we already got DDE_DATA on close, don't try requesting more
+ // data. (MSDraw will give a bogus metafile.)
+ hres=OLE_E_NOTRUNNING;
+ goto exitRtn;
+ }
+
+ if (NotEqual (pformatetcIn->ptd, m_pDdeObject->m_ptd))
+ {
+ // If caller is asking for a different target device
+ // (We assume a different pointer points to a different target device)
+
+ if (NOERROR!=m_pDdeObject->SetTargetDevice (pformatetcIn->ptd))
+ {
+ // 1.0 server did not accept target device
+ hres=DATA_E_FORMATETC;
+ goto exitRtn;
+ }
+
+ Assert (hres!=NOERROR); // Must do RequestData with new target device
+ }
+ else
+ {
+ // Pick a member handle (H) to return, based on clipboard format CF.
+ // If caller did not pass in its own medium, we must allocate a new
+ // handle.
+
+
+ #define macro(CF,H) \
+ if (pformatetcIn->cfFormat == CF) { \
+ if (m_pDdeObject->H) { \
+ if (pmedium->tymed == TYMED_NULL) { \
+ intrDebugOut((DEB_ITRACE,"::GetData giving cf==%x hData=%x\n",CF,m_pDdeObject->H)); \
+ pmedium->hGlobal = m_pDdeObject->H; \
+ m_pDdeObject->H = NULL; \
+ } \
+ hres = NOERROR; /* found data in right format */ \
+ } \
+ }
+
+ macro (g_cfNative, m_hNative)
+ else macro (m_pDdeObject->m_cfPict, m_hPict )
+ else macro (m_pDdeObject->m_cfExtra,m_hExtra )
+
+ // If we gave away our picture, we must forget its format.
+ if (pformatetcIn->cfFormat == m_pDdeObject->m_cfPict)
+ m_pDdeObject->m_cfPict = 0;
+ #undef macro
+ }
+
+ if (hres!=NOERROR)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::GetData(%x) posting DDE_REQUEST for cf==%x\n",
+ this,
+ (ULONG)pformatetcIn->cfFormat));
+
+ // Didn't find a handle for the requested format,
+ // or handle was NULL, so request it.
+ // The sequence should be:
+ // GetData -> DDE_REQUEST -> DDE_DATA -> OnData -> return to GetData
+
+ if (hres=m_pDdeObject->RequestData (pformatetcIn->cfFormat) != NOERROR)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::GetData(%x) RequestData returns error %x\n",
+ this,hres));
+
+ hres = DV_E_CLIPFORMAT;
+ goto exitRtn;
+ }
+
+ // By now, a KeepData() should have been done with the right cf,
+ // so try again.
+ intrDebugOut((DEB_ITRACE,
+ "::GetData(%x) KeepData should have been called. Go again\n",
+ this));
+
+ Puts ("KeepData should have been called. Trying GetData again.\n");
+ goto lStart;
+ }
+ lDone:
+ Puts ("pmedium->hGlobal =="); Puth(pmedium->hGlobal); Putn();
+ pmedium->pUnkForRelease = NULL; // Let caller release medium
+ // Must set tymed _after_ the goto loop.
+ // Otherwise it'll be changed the second time around.
+
+ // tell caller what we're returning
+ pmedium->tymed = UtFormatToTymed (pformatetcIn->cfFormat);
+
+
+ intrDebugOut((DEB_ITRACE,
+ "::GetData(%x)tymed=%x cfFormat=%x hGlobal=%x\n",
+ this,
+ pmedium->tymed,
+ (USHORT)pformatetcIn->cfFormat,
+ pmedium->hGlobal));
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "::GetData(%x)hres=%x\n",
+ this,
+ hres));
+ return hres;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::GetDataHere
+ (LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetDataHere(%x,pformatetcIn=%x)\n",
+ this,
+ pformatetcIn));
+
+ HRESULT hresult = NOERROR;
+ STGMEDIUM medium;
+ if (!(pformatetcIn->tymed & TYMED_HGLOBAL))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::GetDataHere(%x)DV_E_TYMED(%x)\n",
+ this,DV_E_TYMED));
+ // Cannot GetDataHere for GDI objects
+ hresult = DV_E_TYMED;
+ goto exitRtn;
+ }
+ RetErr (GetData (pformatetcIn, &medium));
+ if (medium.tymed != TYMED_HGLOBAL)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::GetDataHere(%x)medium.tymed != TYMED_HGLOBAL\n",
+ this));
+ hresult = ResultFromScode (DV_E_TYMED);
+ goto errRtn;
+ }
+ pmedium->tymed = medium.tymed;
+ pmedium->pUnkForRelease = medium.pUnkForRelease;
+ ErrRtnH (wHandleCopy (pmedium->hGlobal, medium.hGlobal));
+
+ errRtn:
+ ReleaseStgMedium (&medium);
+
+ exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetDataHere(%x) returning %x\n",
+ this,hresult));
+ return hresult;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::QueryGetData
+ (LPFORMATETC pformatetcIn)
+{
+ HRESULT hr;
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDdeObject::QueryGetData(pformatetcIn=%x)\n",
+ this,
+ pformatetcIn));
+
+ hr = wVerifyFormatEtc (pformatetcIn);
+
+ if (hr != NOERROR)
+ {
+ goto exitRtn;
+ }
+ if (pformatetcIn->cfFormat == g_cfEmbeddedObject
+ || pformatetcIn->cfFormat == g_cfEmbedSource
+ || pformatetcIn->cfFormat == g_cfLinkSource
+ || pformatetcIn->cfFormat == g_cfFileName
+ || pformatetcIn->cfFormat == g_cfCustomLinkSource
+ || pformatetcIn->cfFormat == g_cfObjectDescriptor
+ || pformatetcIn->cfFormat == g_cfLinkSrcDescriptor)
+ {
+ hr = S_FALSE;
+ }
+
+ hr = m_pDdeObject->IsFormatAvailable (pformatetcIn);
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDdeObject::QueryGetData returning %x\n",
+ this,hr));
+ return(hr);
+
+}
+
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::SetData
+ (LPFORMATETC pformatetc,
+ STGMEDIUM FAR* pmedium,
+ BOOL fRelease)
+{
+ HANDLE hDdePoke;
+ HRESULT hresult;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDdeObject::SetData(pformatetc=%x)\n",
+ this,
+ pformatetc));
+
+ hresult = wVerifyFormatEtc (pformatetc);
+
+ if (hresult != NOERROR)
+ {
+ goto exitRtn;
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%x ::SetData(pformatetc->cfFormat=%x)\n",
+ this,
+ (ULONG)pformatetc->cfFormat));
+
+ if (pformatetc->dwAspect & DVASPECT_ICON)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%x ::SetData dwAspect & DVASPECT_ICON\n",
+ this));
+ hresult = DV_E_DVASPECT;
+ goto exitRtn;
+ }
+
+
+ if (pformatetc->ptd != m_pDdeObject->m_ptd)
+ {
+ // If caller is setting with a different target device
+ // (We assume a different pointer points to a different target device)
+
+ if (NOERROR != m_pDdeObject->SetTargetDevice (pformatetc->ptd))
+ {
+ intrDebugOut((DEB_IERROR,
+ "%x ::SetData server did not accept target device\n",
+ this));
+ hresult = DV_E_DVTARGETDEVICE;
+ goto exitRtn;
+ }
+ }
+
+ if (hDdePoke = wPreparePokeBlock (pmedium->hGlobal,
+ pformatetc->cfFormat,
+ m_pDdeObject->m_aClass,
+ m_pDdeObject->m_bOldSvr))
+ {
+ hresult = m_pDdeObject->Poke (m_pDdeObject->m_aItem, hDdePoke);
+ if (fRelease)
+ ReleaseStgMedium (pmedium);
+ goto exitRtn;
+ }
+ else
+ {
+ hresult = E_OUTOFMEMORY;
+ }
+exitRtn:
+
+ intrDebugOut((DEB_ITRACE,"%x _OUT ::SetData returns %x\n",this,hresult));
+ return(hresult);
+
+}
+
+
+
+
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::DAdvise
+ (FORMATETC FAR* pformatetc,
+ DWORD grfAdvf,
+ IAdviseSink FAR* pAdvSink,
+ DWORD FAR* pdwConnection)
+{
+ HRESULT hresult;
+ HRESULT hresLookup;
+ FORMATETC formatetc;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDdeObject::DAdvise(pformatetc=%x,grfAdvf=%x,pAdvSink=%x)\n",
+ this,
+ pformatetc,
+ grfAdvf,
+ pAdvSink));
+
+ VDATEPTROUT (pdwConnection, DWORD);
+ *pdwConnection = 0;
+
+ wNormalize (pformatetc, &formatetc);
+
+ hresult =wVerifyFormatEtc (&formatetc);
+
+ if ( hresult != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "%x ::DAdvise pformatetc->cfFormat=%x\n",
+ this,
+ pformatetc->cfFormat));
+
+ if (NotEqual (formatetc.ptd, m_pDdeObject->m_ptd))
+ {
+ if (NOERROR != m_pDdeObject->SetTargetDevice (formatetc.ptd))
+ {
+ hresult= DV_E_DVTARGETDEVICE;
+ goto errRtn;
+ }
+ }
+
+ hresLookup = m_pDdeObject->m_ConnectionTable.Lookup (formatetc.cfFormat, NULL);
+ if (hresLookup != NOERROR)
+ {
+ // We have not already done a DDE advise for this format
+
+ Puts (" m_iAdvChange = "); Puti (m_pDdeObject->m_iAdvChange); Puts("\n");
+
+ if (m_pDdeObject->m_ulObjType == OT_LINK)
+ {
+ ErrRtnH (m_pDdeObject->AdviseOn (formatetc.cfFormat, ON_CHANGE));
+ ErrRtnH (m_pDdeObject->AdviseOn (formatetc.cfFormat, ON_SAVE));
+ }
+ else
+ {
+ ErrRtnH (m_pDdeObject->AdviseOn (formatetc.cfFormat, ON_SAVE));
+ ErrRtnH (m_pDdeObject->AdviseOn (formatetc.cfFormat, ON_CLOSE));
+ }
+ }
+
+ ErrZS (m_pDdeObject->m_pDataAdvHolder, E_OUTOFMEMORY);
+ hresult = m_pDdeObject->m_pDataAdvHolder->Advise (this, pformatetc, grfAdvf,
+ pAdvSink, pdwConnection);
+
+ m_pDdeObject->m_ConnectionTable.Add (*pdwConnection, formatetc.cfFormat,
+ grfAdvf);
+
+ errRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDdeObject::DAdvise hresult=%x\n",
+ this,
+ hresult));
+ return hresult;
+}
+
+
+
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::DUnadvise
+ (DWORD dwConnection)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::DUnadvise(%x,dwConnection=%x)\n",
+ this,
+ dwConnection));
+
+ CLIPFORMAT cf;
+ HRESULT hres;
+ DWORD grfAdvf;
+
+ // Remove connection from table. Lookup the cf for this connection.
+ if (m_pDdeObject->m_ConnectionTable.Subtract (dwConnection, &cf, &grfAdvf)
+ == NOERROR)
+ {
+ // If there is not another connection that needs this format
+ if (m_pDdeObject->m_ConnectionTable.Lookup (cf, NULL) != NOERROR)
+ {
+ // We did a DDE advise for this connection, so undo it.
+ if (m_pDdeObject->m_ulObjType == OT_LINK)
+ {
+ if (NOERROR != (hres=m_pDdeObject->UnAdviseOn (cf, ON_CHANGE)))
+ {
+ intrDebugOut((DEB_IWARN,
+ "::DUnadvise(%x,dwConnection=%x) ON_CHANGE failed\n",
+ this,
+ dwConnection));
+ }
+ if (NOERROR != (hres=m_pDdeObject->UnAdviseOn (cf, ON_SAVE)))
+ {
+ intrDebugOut((DEB_IWARN,
+ "::DUnadvise(%x,dwConnection=%x) ON_SAVE failed\n",
+ this,
+ dwConnection));
+ }
+ }
+ else
+ {
+ if (NOERROR != (hres=m_pDdeObject->UnAdviseOn (cf, ON_SAVE)))
+ {
+ intrDebugOut((DEB_IWARN,
+ "::DUnadvise(%x,dwConnection=%x) ON_SAVE failed\n",
+ this,
+ dwConnection));
+ }
+ if (NOERROR != (hres=m_pDdeObject->UnAdviseOn (cf, ON_CLOSE)))
+ {
+ intrDebugOut((DEB_IWARN,
+ "::DUnadvise(%x,dwConnection=%x) ON_CLOSE failed\n",
+ this,
+ dwConnection));
+ }
+ }
+ }
+ }
+
+ // Delegate rest of the work to the DataAdviseHolder
+ RetZS (m_pDdeObject->m_pDataAdvHolder, E_OUTOFMEMORY);
+ return m_pDdeObject->m_pDataAdvHolder->Unadvise (dwConnection);
+}
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::EnumDAdvise
+ (THIS_ LPENUMSTATDATA FAR* ppenumAdvise)
+{
+ RetZS (m_pDdeObject->m_pDataAdvHolder, E_OUTOFMEMORY);
+ return m_pDdeObject->m_pDataAdvHolder->EnumAdvise(ppenumAdvise);
+}
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::EnumFormatEtc
+ (DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc)
+{
+ return OleRegEnumFormatEtc (m_pDdeObject->m_clsid, dwDirection,
+ ppenumFormatEtc);
+}
+
+
+
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::GetCanonicalFormatEtc
+(LPFORMATETC pformatetc, LPFORMATETC pformatetcOut)
+{
+ VDATEPTROUT (pformatetcOut, FORMATETC);
+ memcpy (pformatetcOut, pformatetc, sizeof (FORMATETC));
+ return ReportResult(0, DATA_S_SAMEFORMATETC, 0, 0);
+ // We must be very conservative and assume data will be different for
+ // every formatetc
+}
+
+
+
+INTERNAL CDdeObject::RequestData
+ (CLIPFORMAT cf)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::RequestData(%x,cf=%x)\n",
+ this,cf));
+
+ LPARAM lparam;
+ RetZ (m_pDocChannel);
+ intrAssert(wIsValidAtom(m_aItem));
+ ATOM aItem = wDupAtom (m_aItem);
+ intrAssert(wIsValidAtom(aItem));
+
+ lparam = MAKE_DDE_LPARAM (WM_DDE_REQUEST,cf, aItem);
+
+ HRESULT hr = SendMsgAndWaitForReply (m_pDocChannel,
+ AA_REQUEST,
+ WM_DDE_REQUEST,
+ lparam,
+ TRUE);
+ if ( aItem && FAILED(hr) )
+ {
+ GlobalDeleteAtom (aItem);
+ }
+ return hr;
+}
+
+
+// special name
+const char achSpecialName[] = "DISPLAY";
+
+//
+// Return a 1.0 target device for the screen
+//
+
+static INTERNAL DefaultTargetDevice (HANDLE FAR* ph)
+{
+ intrDebugOut((DEB_ITRACE,
+ "DefaultTargetDevice(ph=%x)\n",ph));
+
+ VDATEPTROUT ((LPVOID) ph, HANDLE);
+ LPOLETARGETDEVICE p1=NULL;
+ *ph = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, sizeof (*p1) + 10);
+ RetZS (*ph, E_OUTOFMEMORY);
+ p1 = (LPOLETARGETDEVICE) GlobalLock (*ph);
+ RetZS (p1, E_OUTOFMEMORY);
+ p1->otdDeviceNameOffset = 8;
+ p1->otdDriverNameOffset = 0; // The driver name is at otdData
+ p1->otdPortNameOffset = 9;
+ p1->otdExtDevmodeOffset = 0;
+ p1->otdExtDevmodeSize = 0;
+ p1->otdEnvironmentOffset= 0;
+ p1->otdEnvironmentSize = 0;
+
+ //
+ // Note that memcpy is moving a constant string. Therefore, sizeof()
+ // will include the NULL terminator
+ //
+ //
+ memcpy((LPSTR)p1->otdData, achSpecialName,sizeof(achSpecialName));
+ p1->otdData[8] = 0; // NULL the otdDeviceName
+ p1->otdData[9] = 0; // NULL the PortNameOffset
+ GlobalUnlock (*ph);
+ return NOERROR;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: Convert20TargetDevice
+//
+// Synopsis: Converts a 2.0 TargetDevice into a 1.0 OLETARGETDEVICE
+//
+// Effects: First converts the 2.0 UNICODE target device into ANSI,
+// then converts that into a 1.0 OLETARGETDEVICE. The astute
+// reader would say: Why not just 2.0 UNICODE to OLETARGETDEVICE?
+//
+// Two reasons: time before we ship vs time needed elsewhere.
+//
+// If you can spare some time, please change this to go
+// directly from one to the other.
+//
+// Arguments: [ptd] --
+// [phTD1] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-03-94 kevinro Created
+//
+// Notes:
+//
+// BUGBUG: the NT version of the OLE 1.0 used UINT as the size of the
+// structures members. This was baaaad, since we really need them to be
+// a fixed size. I am currently in the works of changing the NT 1.0 header
+// file to reflect what we really need it to be, which is USHORT's
+//
+//
+// We have a DVTARGETDEVICE, but we want a OLETARGETDEVICE, which looks like
+//
+// typedef struct _OLETARGETDEVICE {
+// USHORT otdDeviceNameOffset;
+// USHORT otdDriverNameOffset;
+// USHORT otdPortNameOffset;
+// USHORT otdExtDevmodeOffset;
+// USHORT otdExtDevmodeSize;
+// USHORT otdEnvironmentOffset;
+// USHORT otdEnvironmentSize;
+// BYTE otdData[1];
+// } OLETARGETDEVICE;
+//
+// A couple things to note:
+//
+// 1) The Names in the OLETARGETDEVICE need to be Ansi
+// 2) The Environment member doens't exist in the DVTARGETDEVICE, and will
+// be created in this conversion
+// 3) The ExtDevmode also needs to be ANSI
+//
+//----------------------------------------------------------------------------
+INTERNAL Convert20TargetDevice
+ (const DVTARGETDEVICE FAR* ptd, // in parm
+ HANDLE FAR* phTD1) // out parm
+{
+ const size_t cbHeader = SIZEOF_DVTARGETDEVICE_HEADER;
+ HRESULT hr;
+ LPOLETARGETDEVICE ptd1 = NULL;
+ size_t cbTD1;
+ size_t cbDevmode;
+ size_t cbOffset;
+ LPDEVMODEA pdevmode;
+
+ intrDebugOut((DEB_ITRACE,
+ "Convert20TargetDevice(ptd=%x)\n",ptd));
+
+ VDATEPTROUT ((LPVOID) phTD1, HANDLE);
+ *phTD1 = NULL;
+
+ //
+ // If no device specified, then return the default
+ //
+
+ if (NULL==ptd)
+ {
+ return DefaultTargetDevice (phTD1);
+ }
+
+ //
+ // Compute information for doing conversion using routines in utils.cpp
+ // The following structure will get the sizes
+ //
+
+ DVTDINFO dvtdInfo;
+
+ hr = UtGetDvtd32Info(ptd,&dvtdInfo);
+
+ if (hr != NOERROR)
+ {
+ return DV_E_DVTARGETDEVICE;
+ }
+
+ //
+ // The conversion routines require us to allocate memory to pass in.
+ //
+
+ DVTARGETDEVICE *pdvtdAnsi = (DVTARGETDEVICE *) PrivMemAlloc(dvtdInfo.cbConvertSize);
+
+ if (pdvtdAnsi == NULL)
+ {
+ return(E_OUTOFMEMORY);
+ }
+
+ //
+ // Convert the UNICODE target device into an ANSI target device
+ //
+
+ hr = UtConvertDvtd32toDvtd16(ptd,&dvtdInfo,pdvtdAnsi);
+
+ if (hr != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ //
+ // pdvtdAnsi now holds an ANSI version of the DVTARGETDEVICE. Turns
+ // out the structure we really want is the DVTARGETDEVICE, plus a
+ // couple of extra header bytes. Therefore, we can just do a block
+ // copy of the DVTARGETDEVICE's data, and fix up our OLETARGETDEVICE
+ // header to have the correct offsets in the data.
+ //
+ // offset of data block from beginning of 2.0 target device
+ //
+ cbOffset = offsetof (DVTARGETDEVICE, tdData);
+
+ //
+ // Calculate a pointer to the DEVMODEA
+ //
+ pdevmode = pdvtdAnsi->tdExtDevmodeOffset ?
+ (LPDEVMODEA)((LPBYTE)pdvtdAnsi + pdvtdAnsi->tdExtDevmodeOffset)
+ : NULL;
+
+ //
+ // Quick sanity check on the resulting pointer.
+ //
+ if (pdevmode && IsBadReadPtr (pdevmode, sizeof(DEVMODEA)))
+ {
+ hr = DV_E_DVTARGETDEVICE;
+ goto errRtn;
+ }
+
+ //
+ // Calculate the size of the devmode part.
+ //
+
+ cbDevmode = (pdevmode ? pdevmode->dmSize + pdevmode->dmDriverExtra:0);
+
+ //
+ // Calculate the total size needed. The DVTARGETDEVICE header has 12 bytes,
+ // and the OLETARGETDEVICE has 14 bytes. We also need to make an extra copy
+ // of the cbDevmode structure to fill in the environment. Therefore, there is
+ // an extra cbDevmode, and a sizeof(USHORT) added to the size. The size includes
+ // the size of the DVTARGETHEADER
+ //
+
+ cbTD1 = (size_t) pdvtdAnsi->tdSize +
+ cbDevmode + // For extra Environment data
+ sizeof (USHORT); // for Environment Size field
+
+ *phTD1 = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, cbTD1);
+ if (NULL== *phTD1)
+ {
+ intrAssert (!"GlobalAlloc Failed");
+ hr = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ ptd1 = (LPOLETARGETDEVICE) GlobalLock (*phTD1);
+ if (NULL== ptd1)
+ {
+ intrAssert (!"GlobalLock Failed");
+ hr = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ // Set x1 (1.0 offset) based on x2 (2.0 offset)
+ //
+ // Note that the OLETARGETDEVICE offsets are relative to the array of bytes,
+ // where the DVTARGETDEVICE is relative to the start of the structure. Thats
+ // why cbOffset is subtracted
+ //
+
+ #define ConvertOffset(x1, x2) (x1 = (x2 ? x2 - cbOffset : 0))
+
+ //
+ // Using the above macro, and assuming
+ //
+
+ ConvertOffset (ptd1->otdDeviceNameOffset, pdvtdAnsi->tdDeviceNameOffset);
+ ConvertOffset (ptd1->otdDriverNameOffset, pdvtdAnsi->tdDriverNameOffset);
+ ConvertOffset (ptd1->otdPortNameOffset , pdvtdAnsi->tdPortNameOffset );
+ ConvertOffset (ptd1->otdExtDevmodeOffset, pdvtdAnsi->tdExtDevmodeOffset);
+ ptd1->otdExtDevmodeSize = cbDevmode;
+
+ //
+ // I found this in the OLE 2 information on OLETARGETDEVICE:
+ //
+ // The otdDeviceNameOffset, otdDriverNameOffset, and otdPortNameOffset
+ // members should be null-terminated. In Windows 3.1, the ability to
+ // connect multiple printers to one port has made the environment
+ // obsolete. The environment information retrieved by the
+ // GetEnvironment function can occasionally be incorrect. To ensure that the
+ // OLETARGETDEVICE structure is initialized correctly, the application
+ // should copy information from the DEVMODEA structure retrieved by a
+ // call to the ExtDeviceMode function to the environment position of
+ // the OLETARGETDEVICE structure.
+ //
+ //
+
+ //
+ // Adjust the environment offset to the end of the converted structure, and
+ // set the size. the sizeof(USHORT) accounts for the addition of the
+ // otdEnvironmentSize field. The offsetof accounts for the fact that the
+ // OLETARGETDEVICE offsets are based from the otdData array.
+ //
+ ptd1->otdEnvironmentOffset = (USHORT) pdvtdAnsi->tdSize +
+ sizeof(USHORT) -
+ offsetof(OLETARGETDEVICE,otdData);
+
+ ptd1->otdEnvironmentSize = cbDevmode;
+
+ // Copy data block
+ if(IsBadWritePtr (ptd1->otdData, (size_t) pdvtdAnsi->tdSize - cbHeader))
+ {
+ hr = E_UNEXPECTED;
+ goto errRtn;
+ }
+ memcpy (ptd1->otdData, pdvtdAnsi->tdData, (size_t) pdvtdAnsi->tdSize - cbHeader);
+
+ if (cbDevmode != 0)
+ {
+ if(IsBadWritePtr (ptd1->otdData, sizeof (DEVMODEA)))
+ {
+ hr = E_UNEXPECTED;
+ goto errRtn;
+ }
+
+ // Copy 2.0 Devmode into 1.0 environment
+
+ memcpy (ptd1->otdData + ptd1->otdEnvironmentOffset,
+ pdvtdAnsi->tdData + pdvtdAnsi->tdExtDevmodeOffset,
+ cbDevmode);
+ }
+
+ hr = NOERROR;
+
+errRtn:
+
+ if (ptd1 != NULL)
+ {
+ GlobalUnlock(*phTD1);
+ }
+
+ if (pdvtdAnsi != NULL)
+ {
+ PrivMemFree(pdvtdAnsi);
+ }
+ intrDebugOut((DEB_ITRACE,
+ "Convert20TargetDevice(ptd=%x) returns %x\n",ptd,hr));
+ return(hr);
+}
+
+
+
+static INTERNAL CopyTargetDevice
+ (const DVTARGETDEVICE FAR* ptd,
+ DVTARGETDEVICE FAR* FAR* pptd)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CopyTargetDevice(ptd=%x)\n",ptd));
+
+ if (*pptd)
+ {
+ delete *pptd; // delete old target device
+ }
+ if (NULL==ptd)
+ {
+ *pptd = NULL;
+ }
+ else
+ {
+ *pptd = (DVTARGETDEVICE FAR*) operator new ((size_t) (ptd->tdSize));
+ if (NULL==*pptd)
+ {
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ _fmemcpy (*pptd, ptd, (size_t) ptd->tdSize);
+ }
+ return NOERROR;
+}
+
+
+
+INTERNAL CDdeObject::SetTargetDevice
+ (const DVTARGETDEVICE FAR* ptd)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::SetTargetDevice(%x,ptd=%x)\n",
+ this,
+ ptd));
+
+ HANDLE hTD1 = NULL;
+ HANDLE hDdePoke=NULL;
+
+ RetErr (Convert20TargetDevice (ptd, &hTD1));
+
+ Assert (hTD1);
+ Verify (hDdePoke = wPreparePokeBlock (hTD1, g_cfBinary, m_aClass, m_bOldSvr));
+ if (hTD1)
+ {
+ GlobalFree (hTD1);
+ }
+ // Poke new target device to 1.0 server
+ aStdTargetDevice = GlobalAddAtom (L"StdTargetDevice");
+ intrAssert(wIsValidAtom(aStdTargetDevice));
+ RetErr (Poke (aStdTargetDevice, hDdePoke));
+
+ // Remember current target device
+ RetErr (CopyTargetDevice (ptd, &m_ptd));
+ // Flush the cache because it contains a picture for the wrong
+ // target device.
+ if (m_hPict)
+ wFreeData (m_hPict, m_cfPict);
+ m_cfPict = (CLIPFORMAT)0;
+ m_hPict = NULL;
+
+ return NOERROR;
+}
diff --git a/private/ole32/com/dde/client/ddeioc.cxx b/private/ole32/com/dde/client/ddeioc.cxx
new file mode 100644
index 000000000..bca19b47d
--- /dev/null
+++ b/private/ole32/com/dde/client/ddeioc.cxx
@@ -0,0 +1,209 @@
+/*
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddeLink.cpp
+
+Abstract:
+
+ This module contains the DdeObject::OleItemContainer methods
+ and other Link-related code
+
+Author:
+
+ Jason Fuller (jasonful) 19-October-1992
+
+*/
+
+#include "ddeproxy.h"
+// #include <limits.h>
+// #include <utils.h>
+// #include <moniker.h>
+
+
+ASSERTDATA
+
+
+
+STDUNKIMPL_FORDERIVED (DdeObject, OleItemContainerImpl)
+
+
+static INTERNAL_(void) wSkipDelimiter
+ (LPOLESTR * psz)
+{
+ if (wcschr (L"!\"'*+,./:;<=>?@[\\]`|" , **psz))
+ (*psz)++;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject, COleItemContainerImpl)::ParseDisplayName
+ (LPBC pbc,
+ LPOLESTR lpszDisplayName,
+ ULONG * pchEaten,
+ LPMONIKER * ppmkOut)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::ParseDisplayName(%x,lpsz=%ws)\n",
+ this,
+ lpszDisplayName));
+
+ LPUNKNOWN pUnk = NULL;
+ VDATEPTROUT(ppmkOut,LPMONIKER);
+ *ppmkOut = NULL;
+ VDATEIFACE(pbc);
+ VDATEPTRIN(lpszDisplayName, char);
+ VDATEPTROUT(pchEaten,ULONG);
+
+ *pchEaten = lstrlen(lpszDisplayName);
+ wSkipDelimiter (&lpszDisplayName);
+ // Validate the item name
+ RetErr (GetObject (lpszDisplayName, BINDSPEED_INDEFINITE, pbc,
+ IID_IUnknown, (LPLPVOID) &pUnk));
+ if (pUnk)
+ pUnk->Release();
+ return CreateItemMoniker (L"!", lpszDisplayName, ppmkOut);
+}
+
+
+
+STDMETHODIMP NC(CDdeObject, COleItemContainerImpl)::EnumObjects
+ (DWORD grfFlags,
+ LPENUMUNKNOWN FAR* ppenumUnk)
+
+{
+ // OLE 1.0 provides no way to enumerate all the items in a document.
+ // This method is unlikely to be called since our implementation of
+ // file and item monikers does not call it.
+ Puts ("OleItemContainer::EnumObjects\r\n");
+ if (ppenumUnk)
+ {
+ *ppenumUnk = NULL;
+ return E_NOTIMPL;
+ }
+
+ return E_INVALIDARG;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject, COleItemContainerImpl)::LockContainer
+ (BOOL fLock)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::LockContainer(%x,fLock=%x)\n",
+ this,
+ fLock));
+
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject, COleItemContainerImpl)::GetObject
+ (LPOLESTR lpszItem,
+ DWORD dwSpeedNeeded,
+ LPBINDCTX pbc,
+ REFIID riid,
+ LPVOID * ppvObject)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetObject(%x,szItem=%ws)\n",
+ this,
+ lpszItem));
+
+
+ HRESULT hresult = NOERROR;
+ VDATEPTROUT (ppvObject, LPVOID);
+ *ppvObject=NULL;
+ LPUNKNOWN pUnk = NULL; // These refer to the
+ CDdeObject FAR* pdde = NULL; // same object
+
+ RetZS (pUnk =CDdeObject::Create (NULL,m_pDdeObject->m_clsid,OT_LINK,
+ m_pDdeObject->m_aTopic,lpszItem,&pdde),
+ E_OUTOFMEMORY);
+
+ // For handling invisible updates--propagate information from document
+ // to item.
+ pdde->DeclareVisibility (m_pDdeObject->m_fVisible);
+ pdde->m_fDidLaunchApp = m_pDdeObject->m_fDidLaunchApp;
+ pdde->m_fDidStdOpenDoc = m_pDdeObject->m_fDidStdOpenDoc;
+
+ intrAssert(wIsValidAtom(pdde->m_aItem));
+ ErrZ (0==lstrcmp(lpszItem, wAtomName(pdde->m_aItem)));
+
+ // OPTIMIZATION: Could use a mini Running Object Table to map lpszItem to
+ // LPUNKNOWN and avoiding the Connect() and DDE_REQUEST.
+
+ // Open a DocChannel
+ ErrRtnH (pdde->m_ProxyMgr.Connect (IID_NULL, CLSID_NULL));
+
+ // Request Native data in order to see if the item name is valid
+ Assert (pdde->m_pDocChannel);
+ LPARAM lp;
+ lp=MAKE_DDE_LPARAM (WM_DDE_REQUEST,g_cfNative, wDupAtom(pdde->m_aItem));
+ hresult = pdde->SendMsgAndWaitForReply (pdde->m_pDocChannel,
+ AA_REQUESTAVAILABLE,
+ WM_DDE_REQUEST,
+ lp,
+ TRUE);
+ if ( FAILED( hresult ) )
+ {
+ // Try metafile. Excel can't render large metafiles
+ // but it can render native.
+ lp=MAKE_DDE_LPARAM (WM_DDE_REQUEST,CF_METAFILEPICT, wDupAtom(pdde->m_aItem));
+ hresult = pdde->SendMsgAndWaitForReply (pdde->m_pDocChannel,
+ AA_REQUESTAVAILABLE,
+ WM_DDE_REQUEST,
+ lp,
+ TRUE);
+ if ( FAILED( hresult ) )
+ {
+ Assert (pdde->m_refs==1);
+ hresult = ResultFromScode (MK_E_NOOBJECT);
+ goto errRtn;
+ }
+ }
+
+ // Item name is valid
+ hresult = pdde->m_pUnkOuter->QueryInterface (riid, (LPLPVOID) ppvObject);
+ if (NOERROR==hresult)
+ {
+ m_pDdeObject->m_fDidGetObject = TRUE;
+ }
+ errRtn:
+ if (pUnk)
+ pUnk->Release();
+ return hresult;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject, COleItemContainerImpl)::GetObjectStorage
+ (LPOLESTR lpszItem,
+ LPBINDCTX ptc,
+ REFIID riid,
+ LPVOID * ppvStorage)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetObjectStorage(%x,szItem=%ws)\n",
+ this,
+ lpszItem));
+ return MK_E_NOSTORAGE;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject, COleItemContainerImpl)::IsRunning
+ (LPOLESTR szItem)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::IsRunning(%x,szItem=%ws)\n",
+ this,
+ szItem));
+
+ // By definition, all items are running
+ return NOERROR;
+}
diff --git a/private/ole32/com/dde/client/ddemnker.cxx b/private/ole32/com/dde/client/ddemnker.cxx
new file mode 100644
index 000000000..23ca2ebe5
--- /dev/null
+++ b/private/ole32/com/dde/client/ddemnker.cxx
@@ -0,0 +1,511 @@
+/*
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddeLink.cpp
+
+Abstract:
+
+ This module implements:
+ DdeBindToObject
+ DdeIsRunning
+
+Author:
+
+ Jason Fuller (jasonful) 19-October-1992
+
+*/
+#include "ddeproxy.h"
+
+
+INTERNAL DdeBindToObject
+ (LPCOLESTR szFileIn,
+ REFCLSID clsid,
+ BOOL fPackageLink,
+ REFIID iid,
+ LPLPVOID ppv)
+{
+ intrDebugOut((DEB_ITRACE,
+ "DdeBindToObject szFileIn(%ws) fPackageLink(%x)\n",
+ szFileIn,
+ fPackageLink));
+
+
+ LPUNKNOWN punk;
+ *ppv = NULL;
+ CDdeObject FAR* pdde=NULL;
+ HRESULT hresult = E_UNEXPECTED;
+ BOOL fSysConnection = FALSE;
+ WCHAR wszTmpFile [MAX_STR+5];
+
+ COleTls Tls;
+ if( Tls->dwFlags & OLETLS_DISABLE_OLE1DDE )
+ {
+ // If DDE use is disabled we shouldn't have gotten here.
+ //
+ Assert(!"Executing DdeBindToObject when DDE is disabled");
+ hresult = CO_E_OLE1DDE_DISABLED;
+ goto exitRtn;
+ }
+
+ //
+ // This protocol doesn't handle the fact that there are two names for
+ // every file. This is a bit of a problem. So, we are going to choose
+ // the short name as the one to look for. This means that DDE objects
+ // using the long filename will not work very well.
+ //
+ WCHAR szFile[MAX_PATH];
+ if ((lstrlenW(szFileIn) == 0) || (GetShortPathName(szFileIn,szFile,MAX_PATH) == 0))
+ {
+ //
+ // Unable to determine a short path for this object. Use whatever we were
+ // handed.
+ //
+ intrDebugOut((DEB_ITRACE,"No conversion for short path. Copy szFileIn\n"));
+ lstrcpyW(szFile,szFileIn);
+ }
+ intrDebugOut((DEB_ITRACE,"Short file szFile(%ws)\n",szFile));
+
+ RetZS (punk=CDdeObject::Create (NULL,clsid,OT_LINK,wGlobalAddAtom(szFile),
+ NULL,&pdde),E_OUTOFMEMORY);
+ RetZ (pdde);
+
+ // Document already running?
+
+ if (NOERROR != (hresult = pdde->DocumentLevelConnect (NULL) ))
+ {
+ if (GetScode (hresult) != S_FALSE)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "DdeBindToObject szFile(%ws) DLC returns %x \n",
+ szFile,hresult));
+ goto exitRtn;
+ }
+
+
+ // If not already running, try to make a sys level connection
+
+ if (!pdde->m_pSysChannel) {
+ if (!pdde->AllocDdeChannel (&pdde->m_pSysChannel, TRUE))
+ {
+ intrAssert( !"Out of memory");
+ hresult = E_OUTOFMEMORY;
+ goto exitRtn;
+ }
+ }
+
+ hresult = ReportResult (0, E_UNEXPECTED, 0, 0);
+
+ if (fPackageLink) {
+ lstrcpy (wszTmpFile, szFile);
+ lstrcat (wszTmpFile, L"/Link");
+ pdde->SetTopic (wGlobalAddAtom(wszTmpFile));
+ }
+
+ if (pdde->InitSysConv())
+ {
+ fSysConnection = TRUE;
+
+ // Try to make the server open the document
+ ErrRtnH (pdde->PostSysCommand (pdde->m_pSysChannel, (LPSTR)&achStdOpenDocument,FALSE));
+ pdde->m_fDidStdOpenDoc = TRUE;
+
+ }
+ else
+ {
+ // launch the server
+ if (!pdde->LaunchApp())
+ {
+ hresult = CO_E_APPNOTFOUND;
+ goto errRtn;
+ }
+ }
+
+ if (fPackageLink)
+ pdde->SetTopic (wGlobalAddAtom(szFile));
+
+ // Connect to document
+ hresult = pdde->m_ProxyMgr.Connect (IID_NULL, CLSID_NULL);
+ if (hresult != NOERROR)
+ {
+ // Excel does not register its document in time if it loads
+ // startup macros. So we force it to open the document.
+ if (pdde->InitSysConv())
+ {
+ fSysConnection = TRUE;
+ // Try to make the server open the document.
+ ErrRtnH (pdde->PostSysCommand (pdde->m_pSysChannel,
+ (LPSTR)&achStdOpenDocument,
+ FALSE));
+ pdde->m_fDidStdOpenDoc = TRUE;
+ }
+ else
+ {
+ ErrRtnH (ResultFromScode (CO_E_APPDIDNTREG));
+ }
+ // Try connecting to document again. Should succeed.
+ hresult = pdde->m_ProxyMgr.Connect (IID_NULL, CLSID_NULL);
+ }
+ }
+ else
+ {
+ // Already running, so assume visible
+ pdde->DeclareVisibility (TRUE);
+ }
+
+errRtn:
+ if (pdde->m_pSysChannel) {
+ if (fSysConnection)
+ pdde->TermConv (pdde->m_pSysChannel);
+ else
+ pdde->DeleteChannel (pdde->m_pSysChannel);
+ }
+
+ if (hresult == NOERROR) {
+ hresult = punk->QueryInterface (iid, ppv);
+ }
+ pdde->m_pUnkOuter->Release();
+ if (hresult!=NOERROR)
+ {
+ Warn ("DdeBindToObject failed");
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "DdeBindToObject szFile(%ws) returns %x \n",
+ szFile,hresult));
+
+ return hresult;
+}
+
+
+//
+// BUGBUG: This won't work in a multi-threaded world.
+//
+static LPOLESTR szOriginalUNCName;
+static WCHAR cOriginalDrive;
+
+static INTERNAL InitializeIterator
+ (LPCOLESTR wszFile)
+{
+ WCHAR wszDrive[] = L"A:\\";
+
+ if ((wszFile == NULL) || (wszFile[1] != ':'))
+ {
+ return(S_FALSE);
+ }
+
+ wszDrive[0] = (WCHAR)CharUpperW((LPWSTR)wszFile[0]);
+
+ if (GetDriveType(wszDrive) == DRIVE_REMOTE)
+ {
+
+ DWORD cb = MAX_STR;
+ wszDrive[2] = '\0';
+ if (NULL==szOriginalUNCName)
+ {
+ szOriginalUNCName = new WCHAR [MAX_STR];
+ }
+
+
+ if (WN_SUCCESS == OleWNetGetConnection (wszDrive, szOriginalUNCName, &cb))
+ {
+ cOriginalDrive = (WCHAR)CharUpperW((LPWSTR)wszFile[0]);
+ return NOERROR;
+ }
+ }
+ // szFile is not a network file
+ return ReportResult (0, S_FALSE, 0, 0);
+}
+
+
+
+// NextEquivalentNetDrive
+//
+// Change the drive letter of szFile to the next (modulo 'Z') drive letter
+// that is connected to the same net drive
+// Return S_FALSE when there are no more equivalent drives
+//
+// NOTE NOTE NOTE
+//
+// This routine is playing fast and furious with the relationship between
+// the first 128 Unicode characters and the ASCII character set.
+//
+static INTERNAL NextEquivalentNetDrive
+ (LPOLESTR szFile)
+{
+ #define incr(c) (c=='Z' ? c='A' : ++c)
+ WCHAR wszDrive[3]= L"A:";
+ Assert (szFile && szFile[1]==':');
+
+ char cDrive = (char)CharUpperA((LPSTR)szFile[0]);
+
+ while (cOriginalDrive != incr(cDrive))
+ {
+
+ DWORD cb = MAX_PATH;
+ WCHAR szUNCName [MAX_PATH];
+ wszDrive[0] = cDrive;
+
+ Assert (cDrive >= 'A' && cDrive <= 'Z');
+ Assert (szOriginalUNCName);
+
+ if (WN_SUCCESS == OleWNetGetConnection (wszDrive,szUNCName, &cb) &&
+ (0 == lstrcmpW (szUNCName, szOriginalUNCName)))
+ {
+ szFile[0] = cDrive;
+ return NOERROR;
+ }
+ }
+ // We've gone through all the drives
+ return ReportResult (0, S_FALSE, 0, 0);
+}
+
+
+
+// Dde_IsRunning
+//
+// Attempt to open a document-level conversation using the
+// filename as a topic. If the conversation is established we
+// know the file is running and terminate the conversation.
+// Otherwise it is not running.
+//
+INTERNAL DdeIsRunning
+ (CLSID clsid,
+ LPCOLESTR szFileIn,
+ LPBC pbc,
+ LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning)
+{
+ intrDebugOut((DEB_ITRACE,
+ "DdeIsRunning szFileIn(%ws)\n",szFileIn));
+
+ ATOM aTopic;
+ CDdeObject FAR* pdde=NULL;
+ HRESULT hres = ReportResult(0, S_FALSE, 0, 0);
+
+ if (NULL==szFileIn || '\0'==szFileIn[0])
+ {
+ // A NULL filename is invalid for our purposes.
+ // But if we did a DDE_INITIATE, NULL would mean "any topic",
+ // and if we were called by RunningMoniker() with CLSID_NULL,
+ // then we would be INITIATEing on "any app, any topic" and
+ // SHELL (if not others) would respond.
+ intrDebugOut((DEB_ITRACE,
+ "DdeIsRunning NULL szFileIn\n"));
+
+ hres = S_FALSE;
+ goto exitRtn;
+ }
+ //
+ // This protocol doesn't handle the fact that there are two names for
+ // every file. This is a bit of a problem. So, we are going to choose
+ // the short name as the one to look for. This means that DDE objects
+ // using the long filename will not work very well.
+ //
+ WCHAR szFile[MAX_PATH];
+ if ((lstrlenW(szFileIn) == 0) || (GetShortPathName(szFileIn,szFile,MAX_PATH) == 0))
+ {
+ //
+ // Unable to determine a short path for this object. Use whatever we were
+ // handed.
+ //
+ intrDebugOut((DEB_ITRACE,"No conversion for short path. Copy szFileIn\n"));
+ lstrcpyW(szFile,szFileIn);
+ }
+ intrDebugOut((DEB_ITRACE,"Short file szFile(%ws)\n",szFile));
+
+ aTopic = wGlobalAddAtom (szFile);
+ intrAssert(wIsValidAtom(aTopic));
+
+ ErrZ (CDdeObject::Create (NULL, clsid, OT_LINK, aTopic, NULL, &pdde));
+
+ if (NOERROR == pdde->DocumentLevelConnect (pbc))
+ {
+ // It is running!
+ // Immediately terminate conversation. We just wanted to know
+ // if it was running.
+ hres = NOERROR;
+ }
+ else
+ {
+ // Not running
+ hres = ReportResult(0, S_FALSE, 0, 0);
+ }
+
+ errRtn:
+
+ if (aTopic)
+ intrAssert(wIsValidAtom(aTopic));
+ GlobalDeleteAtom (aTopic);
+ if (pdde)
+ {
+ Assert (pdde->m_refs==1);
+ pdde->m_pUnkOuter->Release();
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "DdeIsRunning szFile(%ws) returns %x\n",szFile,hres));
+ return hres;
+}
+
+
+#if 0
+INTERNAL DdeIsRunning
+ (CLSID clsid,
+ LPCSTR cszFile,
+ LPBC pbc,
+ LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning)
+{
+ HRESULT hresult = NOERROR;
+ LPSTR szFile = NULL;
+
+ // Normal case
+ if (NOERROR == Dde_IsRunning (clsid, cszFile, pbc, pmkToLeft,
+ pmkNewlyRunning))
+ {
+ return NOERROR;
+ }
+
+ if (cszFile[0]=='\\' && cszFile[1]=='\\')
+ {
+ RetErr (SzFixNet (pbc, (LPSTR)cszFile, &szFile));
+ // Try with a drive letter instead of a UNC name
+ if (NOERROR==Dde_IsRunning (clsid, szFile, pbc, pmkToLeft,
+ pmkNewlyRunning))
+ {
+ hresult = NOERROR;
+ goto errRtn;
+ }
+ }
+ else
+ {
+ szFile = UtDupString (cszFile); // so it can be deleted
+ }
+
+ // If failure, see if the file is running under a different net
+ // drive letter that is mapped to the same drive.
+
+ if (InitializeIterator (szFile) != NOERROR)
+ {
+ // file is probably not on a network drive
+ hresult = ResultFromScode (S_FALSE);
+ goto errRtn;
+ }
+
+ while (NOERROR==NextEquivalentNetDrive (szFile))
+ {
+ if (NOERROR == Dde_IsRunning (clsid, szFile, pbc, pmkToLeft,
+ pmkNewlyRunning))
+ {
+ hresult = NOERROR;
+ goto errRtn;
+ }
+ }
+ // not running
+ hresult = ResultFromScode (S_FALSE);
+
+ errRtn:
+ delete szFile;
+ return hresult;
+}
+#endif
+
+
+
+// CDdeObject::DocumentLevelConnect
+//
+// Try to connect to document (m_aTopic) even if the document is running
+// under a different drive letter that is mapped to the same network drive.
+//
+INTERNAL CDdeObject::DocumentLevelConnect
+ (LPBINDCTX pbc)
+{
+ ATOM aOriginal;
+ ATOM aTopic;
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::DocumentLevelConnect(%x)\n",this));
+ HRESULT hresult = NOERROR;
+
+ // Normal case
+ if (NOERROR==m_ProxyMgr.Connect (IID_NULL, CLSID_NULL))
+ {
+ goto exitRtn;
+ }
+
+
+ WCHAR szFile[MAX_STR];
+ WCHAR szUNCFile[MAX_STR];
+
+ Assert (wIsValidAtom (m_aTopic));
+ if (GlobalGetAtomName (m_aTopic, szFile, MAX_STR) == 0)
+ {
+ hresult = E_UNEXPECTED;
+ goto exitRtn;
+ }
+ aOriginal = wDupAtom (m_aTopic);
+ intrAssert(wIsValidAtom(aOriginal));
+
+ intrDebugOut((DEB_ITRACE,
+ "::DocumentLevelConnect(szFile=%ws)\n",this,szFile));
+ if (NOERROR != InitializeIterator (szFile))
+ {
+ // szFile probably not a network file
+ hresult = ResultFromScode (S_FALSE);
+ goto errRtn;
+ }
+
+ while (NOERROR == NextEquivalentNetDrive (szFile))
+ {
+ SetTopic (aTopic = wGlobalAddAtom (szFile));
+ if (NOERROR==m_ProxyMgr.Connect (IID_NULL, CLSID_NULL))
+ {
+ // Inform client of new drive letter
+ ChangeTopic (wAtomNameA(aTopic));
+ hresult = NOERROR;
+ goto errRtn;
+ }
+ else
+ {
+ SetTopic ((ATOM)0);
+ }
+ }
+
+ // Try with full UNC name
+ lstrcpy (szUNCFile, szOriginalUNCName);
+ lstrcat (szUNCFile, szFile+2); // skip X:
+ SetTopic (aTopic = wGlobalAddAtom (szUNCFile));
+ if (NOERROR==m_ProxyMgr.Connect (IID_NULL, CLSID_NULL))
+ {
+ // Inform client of new name
+ ChangeTopic (wAtomNameA(aTopic));
+ hresult = NOERROR;
+ goto errRtn;
+ }
+ else
+ {
+ SetTopic ((ATOM)0);
+ }
+
+ // Not running
+ hresult = S_FALSE;
+
+errRtn:
+ if (NOERROR != hresult)
+ SetTopic (aOriginal);
+ delete szOriginalUNCName;
+ szOriginalUNCName = NULL;
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::DocumentLevelConnect(%x) returns %x\n",
+ this,hresult));
+
+ return hresult;
+}
+
diff --git a/private/ole32/com/dde/client/ddeoo.cxx b/private/ole32/com/dde/client/ddeoo.cxx
new file mode 100644
index 000000000..97c5a58fe
--- /dev/null
+++ b/private/ole32/com/dde/client/ddeoo.cxx
@@ -0,0 +1,770 @@
+/*
+ddeoo.cpp
+DDE Ole Object
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddeoo.cpp
+
+Abstract:
+
+ This module contains the methods for DdeObject::OleObject
+
+Author:
+
+ Jason Fuller (jasonful) 24-July-1992
+
+*/
+
+#include "ddeproxy.h"
+#include <limits.h>
+
+ASSERTDATA
+
+//
+// OleObject methods
+//
+
+STDUNKIMPL_FORDERIVED(DdeObject, OleObjectImpl)
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::SetClientSite
+ (IOleClientSite FAR* pClientSite)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::SetClientSite(%x,pClientSite=%x)\n",
+ this,
+ pClientSite));
+
+ ChkD (m_pDdeObject);
+
+ if (m_pDdeObject->m_pOleClientSite)
+ m_pDdeObject->m_pOleClientSite->Release();
+
+ // we've decided to keep the pointer that's been passed to us. So we
+ // must AddRef()
+ if (m_pDdeObject->m_pOleClientSite = pClientSite)
+ pClientSite->AddRef();
+
+ // this pointer need not be sent to the server, because we will always
+ // send our &m_MyDataSite as the client site
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::GetClientSite
+ (IOleClientSite FAR* FAR* ppClientSite)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetClientSite(%x)\n",
+ this));
+
+ ChkD (m_pDdeObject);
+ // we've been asked to give the pointer so we should AddRef()
+ if (*ppClientSite = m_pDdeObject->m_pOleClientSite)
+ m_pDdeObject->m_pOleClientSite->AddRef();
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::EnumVerbs
+ (IEnumOLEVERB FAR* FAR* ppenumOleVerb)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::EnumVerbs(%x)\n",
+ this));
+
+ ChkD (m_pDdeObject);
+ return ReportResult(0, OLE_S_USEREG, 0, 0);
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::Update
+( void )
+{
+ HRESULT hr;
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::Update(%x)\n",
+ this));
+
+ ChkD (m_pDdeObject);
+
+ hr = m_pDdeObject->Update(TRUE);
+ if (hr == NOERROR)
+ {
+ hr = m_pDdeObject->Save(m_pDdeObject->m_pstg);
+ }
+
+ return hr;
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::IsUpToDate
+( void )
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::IsUpToDate(%x)\n",
+ this));
+
+ ChkD (m_pDdeObject);
+ // There is no way to know if a 1.0 server has edited its embedded
+ // object, so we assume it has, to be on the safe side.
+ return ResultFromScode (m_pDdeObject->m_ulObjType==OT_EMBEDDED
+ ? S_FALSE : S_OK);
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::GetUserClassID
+ (CLSID FAR* pClsid)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetUserClassID(%x)\n",
+ this));
+
+ *pClsid = m_pDdeObject->m_clsid;
+ return NOERROR;
+}
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::GetUserType
+ (DWORD dwFormOfType,
+ LPOLESTR * pszUserType)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetUserType(%x)\n",
+ this));
+
+ return ReportResult (0, OLE_S_USEREG, 0, 0);
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::SetExtent
+( DWORD dwAspect, LPSIZEL lpsizel)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::SetExtent(%x)\n",
+ this));
+
+ HANDLE hDdePoke;
+ LPRECT16 lprc;
+
+ ChkD (m_pDdeObject);
+ Puts ("OleObject::SetExtent\n");
+ if (!(dwAspect // at least one bit
+ && !(dwAspect & (dwAspect-1)) // exactly one bit
+ && (dwAspect & DVASPECT_CONTENT))) // a bit we support
+ {
+ return ResultFromScode (DV_E_DVASPECT);
+ }
+
+#ifdef OLD
+ m_pDdeObject->m_cxContentExtent = lpsizel->cx;
+ m_pDdeObject->m_cyContentExtent = lpsizel->cy;
+#endif
+
+ if (!m_pDdeObject->m_pDocChannel)
+ {
+ return OLE_E_NOTRUNNING;
+ }
+
+ lprc = (LPRECT16) wAllocDdePokeBlock (sizeof(RECT16), g_cfBinary, &hDdePoke);
+ lprc->left = lprc->right = (SHORT) min(INT_MAX,lpsizel->cx);
+ lprc->top = lprc->bottom= (SHORT) min(INT_MAX,lpsizel->cy);
+ aStdDocDimensions = GlobalAddAtom (OLESTR("StdDocDimensions"));
+ intrAssert(wIsValidAtom(aStdDocDimensions));
+ GlobalUnlock (hDdePoke);
+ return m_pDdeObject->Poke(aStdDocDimensions, hDdePoke);
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::GetExtent
+( DWORD dwAspect, LPSIZEL lpsizel)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetExtent(%x)\n",
+ this));
+
+ ChkD (m_pDdeObject);
+
+
+#ifdef OLD
+ VDATEPTROUT (lpsizel, SIZEL);
+ if (!(dwAspect // at least one bit
+ && !(dwAspect & (dwAspect-1)) // exactly one bit
+ && !(dwAspect & (DVASPECT_CONTENT | DVASPECT_ICON)))) // a bit we support
+ {
+ return ResultFromScode (DV_E_DVASPECT);
+ }
+
+ if (dwAspect & DVASPECT_CONTENT)
+ {
+ lpsizel->cx = m_pDdeObject->m_cxContentExtent;
+ lpsizel->cy = m_pDdeObject->m_cyContentExtent;
+ }
+
+ return NOERROR;
+#endif
+ return ResultFromScode(E_NOTIMPL);
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::DoVerb
+//
+// Synopsis: Send the server a message asking it to do a verb.
+//
+// Effects: OLE1.0 servers only know how to do a couple of
+// verbs. Specifically, it will respond to PRIMARY,
+// HIDE, OPEN, and SHOW. All others return error
+//
+//
+// Arguments: [iVerb] -- Verb number
+// [lpmsg] -- Window message (ignored)
+// [pActiveSite] -- ActiveSite (ignored)
+// [lindex] -- Index (ignored)
+// [hwndParent] -- (ignored)
+// [lprcPosRect] -- (ignored)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+//
+// Notes:
+//
+// ANSI ALERT!
+//
+// The server is going to accept a command string from us. This string
+// needs to be done in ANSI, since we are going to pass it to old
+// servers. Therefore, the following code generates an ANSI string
+// The following are the supported verb strings
+//
+// [StdShowItem("aItem",FALSE)]
+// [StdDoVerbItem("aItem",verb,FALSE,FALSE)]
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::DoVerb
+ (LONG iVerb, LPMSG lpmsg, LPOLECLIENTSITE pActiveSite,
+ LONG lindex, HWND hwndParent, const RECT FAR* lprcPosRect)
+{
+ WORD len;
+ ULONG size;
+ LPSTR lpdata = NULL;
+ LPSTR lpdataStart = NULL;
+ HANDLE hdata = NULL;
+ BOOL bShow;
+ HRESULT hresult;
+
+ ChkD (m_pDdeObject);
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::DoVerb(%x,iVerb=%x,lindex=%x)\n",
+ this,iVerb,lindex));
+
+ if (iVerb < OLEIVERB_HIDE)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::DoVerb(%x)Returning invalid verb\n",
+ this));
+ return OLEOBJ_E_INVALIDVERB;
+ }
+
+
+ if (iVerb == OLEIVERB_HIDE)
+ {
+ intrDebugOut((DEB_ITRACE,"::DoVerb(%x) OLEIVERB_HIDE\n",this));
+
+ if (m_pDdeObject->m_fVisible || OT_LINK==m_pDdeObject->m_ulObjType)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::DoVerb(%x) CANNOT_DOVERB_NOW\n",this));
+ return OLEOBJ_S_CANNOT_DOVERB_NOW;
+ }
+
+ intrDebugOut((DEB_ITRACE,"::DoVerb(%x) returns NOERROR\n",this));
+ return NOERROR;
+ }
+
+ //
+ // Calculate the number of bytes needed to pass the
+ // execute command to the server.
+ //
+ if (bShow = (iVerb == OLEIVERB_SHOW
+ || iVerb == OLEIVERB_OPEN
+ || m_pDdeObject->m_bOldSvr))
+ {
+ //
+ // [StdShowItem("aItem",FALSE)]
+ //
+
+ len = 23 + wAtomLenA (m_pDdeObject->m_aItem) + 1;
+
+ }
+ else
+ {
+ // [StdDoVerbItem("aItem",verb,FALSE,FALSE)]
+ len = 32 + 10 /* for verb */ + wAtomLenA (m_pDdeObject->m_aItem) + 1;
+
+ }
+
+ if (!(hdata = GlobalAlloc (GMEM_DDESHARE, size = len)))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::DoVerb(%x) cannot alloc %x bytes\n",
+ this,size));
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+
+ if (!(lpdata = (LPSTR)GlobalLock (hdata)))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::DoVerb(%x) cannot lock\n",
+ this));
+ GlobalFree (hdata);
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ lpdataStart = lpdata;
+
+
+ strcpy (lpdata, bShow ? "[StdShowItem(\"" : "[StdDoVerbItem(\"");
+ len = strlen (lpdata);
+ lpdata += len;
+
+ // For links
+ if (m_pDdeObject->m_aItem)
+ lpdata += GlobalGetAtomNameA (m_pDdeObject->m_aItem, lpdata, size - len);
+
+ if (!bShow) {
+ wsprintfA (lpdata,"\",%lu,TRUE,FALSE)]", iVerb);
+ } else {
+ strcpy (lpdata, "\")]");
+ // apps like excel and wingraph do not support activate at item level.
+ }
+
+ intrDebugOut((DEB_ITRACE,"::DoVerb(%x)lpdata(%s)\n",this,lpdataStart));
+
+ Assert (strlen(lpdata) < size);
+
+ GlobalUnlock (hdata);
+
+ hresult = m_pDdeObject->Execute (m_pDdeObject->m_pDocChannel, hdata);
+
+ if (NOERROR==hresult)
+ {
+ // Assume doing a verb makes the server visible.
+ // This is not strictly true.
+ m_pDdeObject->DeclareVisibility (TRUE);
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::DoVerb(%x)Execute returned %x\n",
+ this,
+ hresult));
+ }
+ return hresult;
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::SetHostNames
+//
+// Synopsis: Sets the host names
+//
+// Effects:
+//
+// Arguments: [szContainerApp] -- Name of container app
+// [szContainerObj] -- Name of contained object
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+//
+// Notes:
+// ANSI ALERT!
+//
+// The server is going to accept a command string from us. This string
+// needs to be done in ANSI, since we are going to pass it to old
+// servers. Therefore, the following code generates an ANSI string
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::SetHostNames
+(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::SetHostNames(%x,App=%ws,Obj=%ws)\n",
+ this,szContainerApp,szContainerObj));
+
+ WORD cbName;
+ WORD wSize;
+ LPSTR lpBuf;
+ HANDLE hDdePoke;
+
+ ChkD (m_pDdeObject);
+
+ VDATEPTRIN (szContainerApp, char);
+
+ if (!m_pDdeObject->m_pDocChannel)
+ return NOERROR;
+ if (szContainerObj==NULL)
+ szContainerObj=OLESTR("");
+
+ if (szContainerApp[0]=='\0')
+ szContainerApp = OLESTR("Container Application");
+
+ //
+ // The OLE 1.0 server is going to want ANSI strings.
+ // convert the two that we have
+ //
+
+ char pszContainerApp[MAX_STR];
+ char pszContainerObj[MAX_STR];
+
+ if (WideCharToMultiByte(CP_ACP,
+ 0,
+ szContainerApp,
+ -1,
+ pszContainerApp,
+ MAX_STR,
+ NULL,
+ NULL) == FALSE)
+ {
+ intrDebugOut((DEB_ERROR,
+ "::SetHostNames(%x) can't convert szContainerApp(%ws) err=%x\n",
+ this,szContainerApp,GetLastError()));
+
+ //
+ // Couldn't convert string
+ //
+ return(E_UNEXPECTED);
+ }
+ if (WideCharToMultiByte(CP_ACP,
+ 0,
+ szContainerObj,
+ -1,
+ pszContainerObj,
+ MAX_STR,
+ NULL,
+ NULL) == FALSE)
+ {
+ intrDebugOut((DEB_ERROR,
+ "::SetHostNames(%x) can't convert szContainerObj(%ws) err=%x\n",
+ this,szContainerObj,GetLastError));
+
+ //
+ // Couldn't convert string
+ //
+ return(E_UNEXPECTED);
+ }
+
+
+ //
+ // We have found through experience that some OLE applications, like
+ // Clipart, use a fixed size buffer for these names. Therefore, we
+ // are going to limit the sizes of the strings, in case they are
+ // too long to send. We do this by always sticking a NULL at offset
+ // 80 in the file.
+ //
+ pszContainerApp[80]=0;
+ pszContainerObj[80]=0;
+
+ WORD cbObj;
+
+ wSize = (cbName = strlen(pszContainerApp)+1)
+ + (cbObj = strlen(pszContainerObj)+1)
+ + 2 * sizeof(WORD); // for the two offsets
+
+ lpBuf = wAllocDdePokeBlock ((DWORD)wSize, g_cfBinary, &hDdePoke);
+ ((WORD FAR*)lpBuf)[0] = 0;
+ ((WORD FAR*)lpBuf)[1] = cbName;
+ lpBuf += 2*sizeof(WORD);
+ memcpy (lpBuf,pszContainerApp,cbName);
+ memcpy (lpBuf+cbName, pszContainerObj,cbObj);
+ GlobalUnlock (hDdePoke);
+ aStdHostNames = GlobalAddAtom (OLESTR("StdHostNames"));
+ intrAssert(wIsValidAtom(aStdHostNames));
+ m_pDdeObject->Poke(aStdHostNames, hDdePoke);
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::Close
+ (DWORD dwSaveOption)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::Close(%x,dwSaveOption=%x)\n",
+ this,dwSaveOption));
+
+
+ ChkDR (m_pDdeObject);
+
+ HRESULT hresult;
+ if (m_pDdeObject->m_fDidSendOnClose)
+ return ResultFromScode (RPC_E_CANTCALLOUT_INASYNCCALL);
+
+ if (((OLECLOSE_SAVEIFDIRTY == dwSaveOption) ||
+ (OLECLOSE_PROMPTSAVE==dwSaveOption)) &&
+ (m_pDdeObject->m_clsid != CLSID_Package))
+ {
+ // Packager gives truncated native data (header info with no
+ // actual embedded file) if you DDE_REQUEST it. Bug 3103
+ Update(); // IOleObject::Update
+ m_pDdeObject->OleCallBack (ON_SAVE,NULL);
+ }
+ RetZ (m_pDdeObject->m_pDocChannel);
+ hresult=m_pDdeObject->Execute (m_pDdeObject->m_pDocChannel,
+ wNewHandle ((LPSTR)&achStdCloseDocument,sizeof(achStdCloseDocument)),
+ TRUE);
+ if (NOERROR==hresult)
+ m_pDdeObject->m_fDidStdCloseDoc = TRUE;
+
+ // Client sends StdCloseDocument. Srvr sends ACK. Srvr may or may not
+ // send Terminate. We may interpret the TERMINATE the server sends
+ // as the reply to ours even if he posted first. But since some servers
+ // post first and others wait for the client, this is what we need to do.
+
+ BOOL fVisible = m_pDdeObject->m_fWasEverVisible; // TermConv clears this flag
+ m_pDdeObject->TermConv (m_pDdeObject->m_pDocChannel);
+ if (!fVisible)
+ m_pDdeObject->MaybeUnlaunchApp();
+
+ return hresult;
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::SetMoniker
+ (DWORD dwWhichMoniker, LPMONIKER pmk)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::SetMoniker(%x,dwWhichMoniker=%x)\n",
+ this,dwWhichMoniker));
+
+ ChkD (m_pDdeObject);
+ Puts ("OleObject::SetMoniker\r\n");
+ // we ignore this always
+ return NOERROR;
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::GetMoniker
+ (DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER FAR* ppmk)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetMoniker(%x,dwWhichMoniker=%x)\n",
+ this,dwWhichMoniker));
+
+ ChkD (m_pDdeObject);
+ if (m_pDdeObject->m_pOleClientSite)
+ return m_pDdeObject->m_pOleClientSite->GetMoniker(dwAssign,
+ dwWhichMoniker, ppmk);
+ else {
+ // no client site
+ *ppmk = NULL;
+ return ReportResult(0, E_UNSPEC, 0, 0);
+ }
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::InitFromData
+ (LPDATAOBJECT pDataObject, BOOL fCreation, DWORD dwReserved)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::InitFromData(%x)\n",
+ this));
+
+ Puts ("OleObject::InitFromData\r\n");
+ return ReportResult(0, E_NOTIMPL, 0, 0);
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::GetClipboardData
+ (DWORD dwReserved, LPDATAOBJECT FAR* ppDataObject)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetClipboardData(%x)\n",
+ this));
+
+ Puts ("OleObject::GetClipboardData\r\n");
+ return ReportResult(0, E_NOTIMPL, 0, 0);
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::Advise
+ (IAdviseSink FAR* pAdvSink,
+ DWORD FAR* pdwConnection)
+{
+ HRESULT hres;
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::Advise(%x)\n",
+ this));
+
+ ChkD (m_pDdeObject);
+ Puts ("OleObject::Advise\n");
+ // Esstablish a DDE advise connection.
+ if (m_pDdeObject->m_ulObjType == OT_EMBEDDED
+ && !m_pDdeObject->m_fDidAdvNative)
+ {
+ // Embedded case.
+ // Always advise on Save and Close.
+ if (hres = m_pDdeObject->AdviseOn (g_cfNative, ON_SAVE))
+ return hres;
+ if (hres = m_pDdeObject->AdviseOn (g_cfNative, ON_CLOSE))
+ return hres;
+ if (m_pDdeObject->m_clsid == CLSID_MSDraw)
+ {
+ // MSDraw has (another) bug. If you do not do an Advise on
+ // presentation, then File.Update does not work, and you
+ // cannot close the app unless you answer "no" to the update
+ // dialog. This would happen when you "Display As Icon"
+ // because ordinarily there is no need to advise on presentation.
+ // The following "unnecessary" advise fixes this problem.
+ if (hres = m_pDdeObject->AdviseOn (CF_METAFILEPICT, ON_SAVE))
+ return hres;
+ if (hres = m_pDdeObject->AdviseOn (CF_METAFILEPICT, ON_CLOSE))
+ return hres;
+ }
+ }
+ else {
+ /* Linked case */
+ if (hres = m_pDdeObject->AdviseOn (g_cfBinary, ON_RENAME))
+ return hres;
+ }
+ RetZS (m_pDdeObject->m_pOleAdvHolder, E_OUTOFMEMORY);
+ return m_pDdeObject->m_pOleAdvHolder->Advise (pAdvSink, pdwConnection);
+}
+
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::Unadvise
+ (DWORD dwConnection)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::Unadvise(%x,dwConnection=%x)\n",
+ this,dwConnection));
+
+ HRESULT hres;
+ ChkD (m_pDdeObject);
+
+ // Terminate the DDE advise connection
+ if (m_pDdeObject->m_ulObjType == OT_EMBEDDED)
+ {
+ // Embedded case.
+ if (hres = m_pDdeObject->UnAdviseOn (g_cfNative, ON_SAVE))
+ return hres;
+ if (hres = m_pDdeObject->UnAdviseOn (g_cfNative, ON_CLOSE))
+ return hres;
+ }
+ else
+ {
+ /* Linked case */
+ if (hres = m_pDdeObject->UnAdviseOn (g_cfBinary, ON_RENAME))
+ return hres;
+ }
+ RetZS (m_pDdeObject->m_pOleAdvHolder, E_OUTOFMEMORY);
+ return m_pDdeObject->m_pOleAdvHolder->Unadvise (dwConnection);
+}
+
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::EnumAdvise
+ (THIS_ LPENUMSTATDATA FAR* ppenumAdvise)
+{
+ ChkD (m_pDdeObject);
+ RetZS (m_pDdeObject->m_pOleAdvHolder, E_OUTOFMEMORY);
+ return m_pDdeObject->m_pOleAdvHolder->EnumAdvise(ppenumAdvise);
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::GetMiscStatus
+ (DWORD dwAspect,
+ DWORD FAR* pdwStatus)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetMiscStatus(%x)\n",
+ this));
+
+ VDATEPTRIN (pdwStatus, DWORD);
+ *pdwStatus = 0L;
+ return ResultFromScode (OLE_S_USEREG);
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::SetColorScheme
+ (LPLOGPALETTE lpLogpal)
+{
+ HANDLE hDdePoke;
+ LPLOGPALETTE lptmpLogpal;
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::SetColorScheme(%x)\n",
+ this));
+
+ ChkD (m_pDdeObject);
+
+ if (!m_pDdeObject->m_pDocChannel)
+ return NOERROR;
+
+ aStdColorScheme = GlobalAddAtom (OLESTR("StdColorScheme"));
+ intrAssert(wIsValidAtom(aStdColorScheme));
+
+ DWORD dwSize = (lpLogpal->palNumEntries - 1) * sizeof(PALETTEENTRY)
+ + sizeof(LOGPALETTE);
+ lptmpLogpal = (LPLOGPALETTE) wAllocDdePokeBlock (dwSize, g_cfBinary, &hDdePoke);
+ memcpy(lptmpLogpal, lpLogpal, dwSize);
+ GlobalUnlock(hDdePoke);
+
+ return m_pDdeObject->Poke(aStdColorScheme, hDdePoke);
+}
+
+
+
+#ifdef _DEBUG
+STDMETHODIMP_(void) NC(CDdeObject,CDebug)::Dump( IDebugStream FAR * pdbstm)
+{
+}
+
+STDMETHODIMP_(BOOL) NC(CDdeObject,CDebug)::IsValid( BOOL fSuspicious )
+{
+ if( m_pDdeObject->m_refs > 0 && m_pDdeObject->m_chk == chkDdeObj )
+ return TRUE;
+ else
+ return FALSE;
+}
+#endif
diff --git a/private/ole32/com/dde/client/ddeproxy.cxx b/private/ole32/com/dde/client/ddeproxy.cxx
new file mode 100644
index 000000000..bdc87f136
--- /dev/null
+++ b/private/ole32/com/dde/client/ddeproxy.cxx
@@ -0,0 +1,2884 @@
+/*
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddeproxy.cpp
+
+Abstract:
+
+ This module contains the code for the dde proxy (wrapper)
+
+Author:
+
+ Srini Koppolu (srinik) 22-June-1992
+ Jason Fuller (jasonful) 24-July-1992
+*/
+#include "ddeproxy.h"
+#include <tls.h>
+
+
+DebugOnly (static UINT v_cDdeObjects=0;)
+/*
+ * IMPLEMENTATION of CDdeObject
+ *
+ */
+
+#ifdef OLD
+#define UpdateExtent(old,new) do { if ((long)new!=old) {old=(long)new; } } while (0)
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateDdeClientHwnd
+//
+// Synopsis: Creates a per thread ClientDde window.
+//
+// Effects: This window is created so we can keep a list of windows that
+// need to be cleaned up in the event the thread dies or OLE32 is
+// unloaded. In the case of DLL unload, we will fault if we don't
+// cleanup this window, since user will dispatch messages to
+// non-existant code. The easy way to track these windows is to
+// make them children of a common per thread window.
+//
+// This routine is called by the TLSGetDdeClient() routine to
+// create a window per thread. This window doesn't need to respond
+// to DDE Initiates.
+//
+// Arguments: [void] --
+//
+// Returns: HWND to DdeClientWindow.
+//
+// History: 12-10-94 kevinro Created
+//
+//----------------------------------------------------------------------------
+
+HWND CreateDdeClientHwnd(void)
+{
+ return SSCreateWindowExA(0,"STATIC","DdeClientHwnd",WS_DISABLED,
+ 0,0,0,0,NULL,NULL,hinstSO,NULL);
+}
+
+// CreateDdeProxy
+//
+// This corresponds to ProxyManager::Create in 2.0
+//
+
+
+INTERNAL_ (LPUNKNOWN) CreateDdeProxy
+ (IUnknown * pUnkOuter,
+ REFCLSID clsid)
+{
+ LPUNKNOWN punk;
+ intrDebugOut((DEB_ITRACE,"CreateDdeProxy(pUnkOuter=%x)\n",pUnkOuter));
+
+ COleTls Tls;
+ if (Tls->dwFlags & OLETLS_DISABLE_OLE1DDE)
+ {
+ // If DDE use is disabled we shouldn't have gotten here.
+ // This is a bad place to error because we can't return an
+ // HResult.
+ //
+ Assert(!"Executing CreateDdeProxy when DDE is disabled");
+ return NULL;
+ }
+
+ punk = CDdeObject::Create (pUnkOuter, clsid);
+ intrDebugOut((DEB_ITRACE,
+ "CreateDdeProxy(pUnkOuter=%x) returns %x\n",
+ pUnkOuter,
+ punk));
+ return punk;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::Create
+//
+// Synopsis: Creates a CDdeObject
+//
+// Effects:
+//
+// Arguments: [pUnkOuter] -- Controlling IUnknown
+// [clsid] -- OLE1 ClassID
+// [ulObjType] -- Object type. Optional: def to OT_EMBEDDED
+// [aTopic] -- Atom of link. Optional: def to NULL
+// [szItem] -- String for link object (def to NULL)
+// [ppdde] -- Output pointer to CDdeObject (def to NULL)
+// [fAllowNullClsid] -- Is NULL clsid OK? Default: false
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(LPUNKNOWN) CDdeObject::Create
+ (IUnknown * pUnkOuter,
+ REFCLSID clsid,
+ ULONG ulObjType,// optional, default OT_EMBEDDED
+ ATOM aTopic, // optional, only relevant if ulObjType==OT_LINK
+ LPOLESTR szItem, // optional, only relevant if ulObjType==OT_LINK
+ CDdeObject * * ppdde, // optional, thing created
+ BOOL fAllowNullClsid) // default FALSE
+{
+ COleTls Tls;
+ if(Tls->dwFlags & OLETLS_DISABLE_OLE1DDE)
+ {
+ //
+ // If the DDE implementation of OLE1 is disabled
+ // we shouldn't get this far. This is also a bad place
+ // to fail because we this routine is defined to not return
+ // an HResult.
+ //
+ Assert(!"Executing CDdeObject::Create but DDE is Disabled");
+ return NULL;
+ }
+ intrDebugOut((DEB_ITRACE,"CDdeObject::Create(%x,ulObjType=%x)\n",
+ pUnkOuter,
+ ulObjType));
+
+ CDdeObject * pDdeObject;
+ static int iTopic=1; // used to make topic names unique
+ WCHAR szTopic[30];
+ Assert (ulObjType==OT_LINK || ulObjType==OT_EMBEDDED);
+
+ Assert (ulObjType != OT_LINK || wIsValidAtom(aTopic));
+ if (ppdde)
+ *ppdde = NULL;
+
+ if (NULL==(pDdeObject = new CDdeObject (pUnkOuter))
+ || NULL == pDdeObject->m_pDataAdvHolder
+ || NULL == pDdeObject->m_pOleAdvHolder)
+ {
+ Assert (!"new CDdeObject failed");
+ return NULL;
+ }
+
+ pDdeObject->m_refs = 1;
+ pDdeObject->m_clsid = clsid;
+ pDdeObject->m_aClass = wAtomFromCLSID(clsid);
+
+#ifdef OLE1INTEROP
+
+ pDdeObject->m_fOle1interop = TRUE;
+
+#endif
+
+ if (ulObjType==OT_LINK)
+ {
+
+ pDdeObject->m_aTopic = wDupAtom (aTopic);
+ pDdeObject->m_aItem = wGlobalAddAtom (szItem);
+ // Never close a linked document
+ pDdeObject->m_fNoStdCloseDoc = TRUE;
+ }
+ else
+ {
+ // This string may actually be visible in the Window Title Bar for a sec.
+ InterlockedIncrement((long *)&iTopic);
+ wsprintf (szTopic,OLESTR("Embedded Object #%u"), iTopic);
+ Assert (lstrlenW(szTopic) < 30);
+ pDdeObject->m_aItem = NULL;
+ pDdeObject->m_aTopic = wGlobalAddAtom (szTopic);
+ }
+ pDdeObject->m_bOldSvr = wIsOldServer (pDdeObject->m_aClass);
+ pDdeObject->m_ulObjType = ulObjType;
+
+ // we can only run if we have a MFI
+ pDdeObject->m_aExeName = wGetExeNameAtom(clsid);
+
+ intrDebugOut((DEB_ITRACE,
+ "::Create(%x,aTopic=%x,aItem=%x,szItem=%ws,aExeName=%x)\n",
+ pDdeObject,
+ pDdeObject->m_aTopic,
+ pDdeObject->m_aItem,
+ szItem?szItem:L"<NULL>",
+ pDdeObject->m_aExeName));
+
+ if (ppdde)
+ *ppdde = pDdeObject;
+ return &pDdeObject->m_Unknown;
+}
+
+
+
+// Constructor
+CDdeObject::CDdeObject (IUnknown * pUnkOuter) :
+ m_Unknown(this),
+ CONSTRUCT_DEBUG
+ m_Data(this),
+ m_Ole(this),
+ m_PersistStg(this),
+ m_ProxyMgr(this),
+ m_OleItemContainer(this),
+ m_RpcStubBuffer(this)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::CDdeObject(%x)\n",this));
+ if (!pUnkOuter)
+ pUnkOuter = &m_Unknown;
+
+ m_pUnkOuter = pUnkOuter;
+ m_bRunning = FALSE;
+ m_pOleClientSite = NULL;
+ m_pstg = NULL;
+ m_pSysChannel = NULL;
+ m_pDocChannel = NULL;
+ m_bInitNew = NULL;
+ m_hNative = NULL;
+ m_hPict = NULL;
+ m_hExtra = NULL;
+ m_cfExtra = NULL;
+ m_cfPict = 0;
+ m_aItem = NULL;
+ m_iAdvSave = 0;
+ m_iAdvClose = 0;
+ m_iAdvChange = 0;
+ m_fDidAdvNative = FALSE;
+ m_pOleAdvHolder = NULL;
+ m_pDataAdvHolder = NULL;
+ m_fDidSendOnClose = FALSE;
+ m_fNoStdCloseDoc = FALSE;
+ m_fDidStdCloseDoc = FALSE;
+ m_fDidStdOpenDoc = FALSE;
+ m_fDidGetObject = FALSE;
+ m_fDidLaunchApp = FALSE;
+ m_fUpdateOnSave = TRUE;
+ m_fVisible = FALSE;
+ m_fWasEverVisible = FALSE;
+ m_fCalledOnShow = FALSE;
+ m_fGotCloseData = FALSE;
+ m_cLocks = 1; // connections are initially locked
+ m_chk = chkDdeObj;
+ m_ptd = NULL;
+ m_fDoingSendOnDataChange = FALSE;
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ _DelayDelete = NoDelay;
+#endif // _CHICAGO_
+
+ CreateOleAdviseHolder (&m_pOleAdvHolder);
+ Assert (m_pOleAdvHolder);
+ CreateDataAdviseHolder (&m_pDataAdvHolder);
+ Assert (m_pDataAdvHolder);
+
+#ifdef OLD
+ m_cxContentExtent = 2000; // 2 centimeters , totally random default
+ m_cyContentExtent = 2000;
+#endif
+
+ m_wTerminate = Terminate_None;
+
+ DebugOnly (v_cDdeObjects++;)
+ Putsi (v_cDdeObjects);
+}
+
+
+
+CDdeObject::~CDdeObject
+ (void)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::~CDdeObject(%x)\n",this));
+
+ if (m_pDocChannel)
+ {
+ intrDebugOut((DEB_IWARN , "Abnormal situation: Doc Channel not deleted. Server died?"));
+ delete m_pDocChannel;
+ }
+ if (m_pSysChannel)
+ {
+ Warn ("Abnormal situation: Sys Channel not deleted. Server died?");
+ delete m_pSysChannel;
+ }
+ if (m_hNative)
+ {
+ GlobalFree(m_hNative);
+ }
+
+ if (m_hPict)
+ {
+ wFreeData (m_hPict, m_cfPict, TRUE);
+ }
+
+ if (m_hExtra)
+ {
+ wFreeData (m_hExtra, m_cfExtra, TRUE);
+ }
+
+ // release all the pointers that we remember
+
+ if (m_pOleClientSite)
+ {
+ DeclareVisibility (FALSE);
+ m_pOleClientSite->Release();
+ }
+
+ if (m_pDataAdvHolder)
+ m_pDataAdvHolder->Release();
+
+ if (m_pOleAdvHolder)
+ m_pOleAdvHolder->Release();
+
+ if (m_pstg)
+ m_pstg->Release();
+
+ if (m_aExeName)
+ GlobalDeleteAtom (m_aExeName);
+
+ if (m_aClass)
+ GlobalDeleteAtom (m_aClass);
+
+ if (m_aTopic)
+ GlobalDeleteAtom (m_aTopic);
+
+ if (m_aItem)
+ GlobalDeleteAtom (m_aItem);
+
+ if (m_ptd)
+ delete m_ptd;
+
+ m_chk = 0;
+ DebugOnly (v_cDdeObjects--;)
+ Putsi (v_cDdeObjects);
+}
+
+
+
+
+// Handles WM_DDE_ACKs received while in initiate state. If this is the first
+// reply, save its window handle. If multiple replies are received, take the
+// one with the prefered instance, if there is one. Keep a count of
+// WM_DDE_TERMINATEs we send so that we don't shut the window until we get
+// all of the responses for WM_DDE_TERMINATEs.
+
+
+INTERNAL_(void) CDdeObject::OnInitAck (LPDDE_CHANNEL pChannel, HWND hwndSvr)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::OnInitAck(%x,hwndSvr=%x)\n",this,hwndSvr));
+#ifdef _MAC
+#else
+ if (!IsWindow (hwndSvr))
+ {
+ Assert (0);
+ return;
+ }
+ if (pChannel->hwndSvr) { // if we already have a handle
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::OnInitAck(%x,hwndSvr=%x) Already have hwndSvr=%x\n",
+ this,
+ hwndSvr,
+ pChannel->hwndSvr));
+ // just take the very first one. Direct post is OK
+ MPostWM_DDE_TERMINATE(hwndSvr,pChannel->hwndCli);
+ // Expect an extra WM_DDE_TERMINATE
+ ++pChannel->iExtraTerms;
+ } else {
+ // this is the server we want
+ pChannel->hwndSvr = hwndSvr;
+ pChannel->iExtraTerms = NULL;
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::OnInitAck(%x,hwndSvr=%x) Established Connection\n",
+ this,
+ hwndSvr,
+ pChannel->hwndSvr));
+ }
+#endif _MAC
+}
+
+INTERNAL_(BOOL) CDdeObject::OnAck (LPDDE_CHANNEL pChannel, LONG lParam)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::OnAck(%x,lParam=%x)\n",this,lParam));
+
+ BOOL retval = TRUE;
+ ATOM aItem;
+ WORD wStatus;
+ HANDLE hData;
+
+ if( pChannel->iAwaitAck == AA_EXECUTE)
+ {
+ wStatus = GET_WM_DDE_EXECACK_STATUS( NULL, lParam );
+ hData = GET_WM_DDE_EXECACK_HDATA( NULL, lParam );
+ }
+ else
+ {
+ wStatus = GET_WM_DDE_ACK_STATUS( NULL, lParam );
+ aItem = GET_WM_DDE_ACK_ITEM( NULL, lParam );
+ }
+
+
+ // check for busy bit
+ if (wStatus & 0x4000)
+ {
+ // we got busy from the server.
+ pChannel->fRejected = TRUE;
+ // tell the wait loop that we got a busy ack
+ //CoSetAckState(pChannel->pCI , FALSE,TRUE, SERVERCALLEX_RETRYLATER);
+ intrDebugOut((DEB_ITRACE,"::OnAck(%x) Busy SetCallState(SERVERCALLEX_RETRYLATER)\n",this));
+ pChannel->SetCallState(SERVERCALLEX_RETRYLATER);
+ return TRUE;
+ }
+
+ // just reset the flag always
+ m_wTerminate = Terminate_None;
+
+ intrDebugOut((DEB_ITRACE,
+ "::OnAck(%x)aItem=%x(%ws) wStatus=\n",
+ this,
+ aItem,
+ wAtomName(aItem),
+ wStatus));
+
+ if (pChannel->iAwaitAck == AA_EXECUTE)
+ {
+ GlobalFree (hData);
+ pChannel->hCommands = NULL;
+ }
+ else
+ {
+ if (hData)
+ GlobalDeleteAtom ((ATOM)hData);
+ }
+
+
+ // even if the client got terminate we have to go thru this path.
+
+ if (pChannel->wTimer) {
+ KillTimer (pChannel->hwndCli, 1);
+ pChannel->wTimer = 0;
+ }
+
+
+ if (pChannel->iAwaitAck == AA_POKE)
+ // We have to free the data first. OnAck can trigger
+ // another Poke (like pokehostnames)
+ wFreePokeData (pChannel, (m_bOldSvr && m_aClass==aMSDraw));
+
+
+ if (!(wStatus & POSITIVE_ACK))
+ {
+ intrDebugOut((DEB_ITRACE,"::OnAck(%x) OnAck got an ack with fAck==FALSE.\n",this));
+
+ // A negative ack is OK when doing a temporary advise from
+ // IsFormatAvailable(). Also, apps don't seem to positively
+ // ack all unadvises.
+
+ // review: johannp : this is the case were have to inform the reply rejected call
+
+ retval = FALSE;
+ // we got the ack and can leave the wait loop
+ //CoSetAckState(pChannel->pCI, FALSE);
+
+ intrDebugOut((DEB_ITRACE,
+ "::OnAck(%x) ***_ NACK _*** SetCallState(ISHANDLED,RPC_E_DDE_NACK)\n",
+ this));
+
+ pChannel->SetCallState(SERVERCALLEX_ISHANDLED, RPC_E_DDE_NACK);
+
+ // MSDraw frees hOptions even on a NACK, despite official DDE rules.
+ if (pChannel->iAwaitAck == AA_ADVISE && m_clsid != CLSID_MSDraw)
+ GlobalFree (pChannel->hopt);
+ }
+ else
+ {
+ // we got the ack and can leave the wait loop
+ // CoSetAckState(pChannel->pCI, FALSE);
+ intrDebugOut((DEB_ITRACE,
+ "::OnAck(%x) POSITIVE_ACK SetCallState(SERVERCALLEX_ISHANDLED)\n",
+ this));
+ pChannel->SetCallState(SERVERCALLEX_ISHANDLED);
+ }
+
+ pChannel->hopt = NULL;
+ pChannel->iAwaitAck = NULL;
+ return retval;
+
+}
+
+
+
+
+
+INTERNAL_(void) CDdeObject::OnTimer (LPDDE_CHANNEL pChannel)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::OnTimer(%x)\n",this));
+ // Since there is only one timer for each client, just
+ // repost the message and delete the timer.
+#ifdef _MAC
+#else
+ KillTimer (pChannel->hwndCli, 1);
+ pChannel->wTimer = 0;
+
+ if (wPostMessageToServer(pChannel, pChannel->wMsg, pChannel->lParam,FALSE))
+ return ;
+
+ // Postmessage failed. We need to getback to the main stream of
+ // commands for the object.
+ OnAck (pChannel, pChannel->lParam);
+#endif _MAC
+}
+
+
+
+// Called when we get a WM_DDE_DATA message in reponse to
+// a DDE_REQUEST we sent to check if a format is available.
+//
+INTERNAL CDdeObject::OnDataAvailable
+ (LPDDE_CHANNEL pChannel,
+ HANDLE hDdeData,
+ ATOM aItem)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::OnDataAvailable(%x)\n",this));
+ CLIPFORMAT cf;
+ Assert (AA_REQUESTAVAILABLE == pChannel->iAwaitAck);
+ intrAssert( wIsValidAtom(aItem));
+
+ DDEDATA * pDdeData = (DDEDATA *) GlobalLock (hDdeData);
+ RetZS (pDdeData, E_OUTOFMEMORY);
+ if (!pDdeData->fAckReq && aItem)
+ {
+ GlobalDeleteAtom (aItem);
+ }
+ cf = pDdeData->cfFormat;
+ GlobalUnlock (hDdeData);
+ wFreeData (wHandleFromDdeData (hDdeData), cf);
+ return NOERROR;
+}
+
+
+
+// Called for WM_DDE_DATA message. If data is from an ADVISE-ON-CLOSE and this
+// is there are no more outstanding ADVISE-ON-CLOSE requests, close the
+// document and end the conversation.
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::OnData
+//
+// Synopsis: Called when a WM_DDE_DATA message is recieved. If the data
+// is from an ADVISE_ON_CLOSE, and there are no more
+// outstanding ADVISE_ON_CLOSE request, close the document
+// and end the conversation.
+//
+// Effects: The effects of this routine are complex.
+//
+// Wow! What else can be said. This routine does alot of stuff in response
+// to an incoming WM_DDE_DATA message. There are basically two flavors of
+// response here. First is when we were expecting to get this result,
+// in which case we know what we wanted to do with the data. Second is
+// when the data just arrives, but we didn't expect it. These cases could
+// indicate that the server is shutting down.
+//
+//
+// Arguments: [pChannel] -- The DDE channel recieving the message
+// [hDdeData] -- Handle to the data
+// [aItem] -- Atom to the item
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-16-94 kevinro Restructured and commented
+//
+// Notes:
+//
+//
+// Be extra careful you change this routine.
+// This is especially neccesary if you are going to exit early. The
+// way that hDdeData is free'd or kept should be understood before
+// changing.
+//
+//
+//----------------------------------------------------------------------------
+INTERNAL CDdeObject::OnData
+ (LPDDE_CHANNEL pChannel,
+ HANDLE hDdeData,
+ ATOM aItem)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::OnData(%x,pChannel=%x,hDdeData=%x,aItem=%x(%s)iAwaitAck=%x\n",
+ this,
+ pChannel,
+ hDdeData,
+ aItem,
+ wAtomNameA(aItem),
+ pChannel->iAwaitAck));
+#ifdef _MAC
+#else
+ DDEDATA * lpDdeData = NULL;
+ BOOL fAck = TRUE;
+ int iAdvOpt;
+ BOOL fCallBack;
+ HRESULT hresult = NOERROR;
+ BOOL fRequested = FALSE;
+
+ intrAssert(wIsValidAtom(aItem));
+
+ int iAwaitAck = pChannel->iAwaitAck;
+
+ //
+ // If we were waiting for this data, then we are sitting in the
+ // modal loop. Set the call state on the call control interface
+ // to indicate that a response was recieved. Pass NOERROR to indicate
+ // that there was success. If an error is determined later, then
+ // the state will be set a second time.
+ //
+
+ if ((AA_REQUEST == iAwaitAck) || (AA_REQUESTAVAILABLE == iAwaitAck))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::OnData(%x) AA_REQUEST/AVAILABLE \n",
+ this));
+
+ //
+ // Regardless of the outcome of this call, we have recieved a
+ // response. Set the Awaiting Ack state to nothing.
+ //
+ pChannel->iAwaitAck = AA_NONE;
+
+ //
+ // Determine if this channels call data is valid
+ //
+
+ if (pChannel->pCD )
+ {
+ //CoSetAckState(pChannel->pCI, FALSE); // clear waiting flag
+ intrDebugOut((DEB_ITRACE,"::OnData(%x) SetCallState(SERVERCALLEX_ISHANDLED)\n",this));
+ pChannel->SetCallState(SERVERCALLEX_ISHANDLED);
+ }
+ }
+
+
+ //
+ // Check the string for aItem, looking for advise options. The variable
+ // iAdvOpt will be set to indicate what type of data we just got, such
+ // as ON_CHANGE, etc. If the option is invalid, then we won't know
+ // what to do with it.
+ //
+
+ if ((hresult=wScanItemOptions (aItem, (int *) &iAdvOpt)) != NOERROR)
+ {
+ intrAssert(!"Item found with unknown advise option\n");
+ LPARAM lp;
+ if(!wPostMessageToServer (pChannel,
+ WM_DDE_ACK,
+ lp = MAKE_DDE_LPARAM (WM_DDE_ACK,NEGATIVE_ACK, aItem),TRUE))
+ {
+ hresult = RPC_E_SERVER_DIED;
+
+ }
+
+ //
+ // Did we need to free hDdeData here? No, according to the DDE spec, if the
+ // receiever responds with a NACK, then the sender is responsible for
+ // freeing the data.
+ //
+ return hresult;
+ }
+
+ //
+ // If the server sent no data, there ain't much we can do about it.
+ //
+
+ if (hDdeData == NULL)
+ {
+ intrDebugOut((DEB_IERROR,
+ "::OnData(%x)hDdeData is NULL!\n",
+ this));
+
+ return(RPC_E_INVALID_PARAMETER);
+ }
+
+ //
+ // Lock the data into memory so we can use it. Be careful, the way
+ // this routine was written originally, there are places that free
+ // and realloc hDdeData. Specifically, the call to KeepData. Carefully
+ // evaluate each place where you are returning, to insure the memory
+ // isn't leaked. (if you have time, please restructure this routine
+ // so it is easier to understand.
+ //
+ if (!(lpDdeData = (DDEDATA FAR *) GlobalLock(hDdeData)))
+ {
+ intrDebugOut((DEB_IERROR,
+ "::OnData(%x)GlobalLock on lpDdeData failed\n",
+ this));
+ //
+ // BUGBUG: (KevinRo)Did we need to free hDdeData here? I think
+ // we should have if the fRelease flag was set. The old code
+ // didn't. Need to research this further (ie you figure it out!)
+ //
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+
+ intrDebugOut((INTR_DDE,
+ "::OnData(%x) lpDdeData->cfFormat=%x\n",
+ this,
+ (UINT)lpDdeData->cfFormat));
+
+ //
+ // The server will set fAckReq if it wants a response.
+ // don't call HIC for call where not acknoewledge is requested
+ //
+ fAck = lpDdeData->fAckReq;
+
+ if (pChannel->bTerminating) {
+ intrDebugOut((INTR_DDE,"::OnData(%x) Got DDE_DATA in terminate sequence\n",this));
+ //
+ // BUGBUG: this is very dangerous since the pointer on the
+ // hDocWnd does not get deleted and a further will
+ // DDE message will GPF - we need to fix this!!!
+ //
+ GlobalUnlock (hDdeData);
+ GlobalFree (hDdeData);
+ goto exitRtn;
+ }
+
+ //
+ // (KevinRo) Found this comment:
+ //
+ // important that we post the acknowledge first. Otherwise the
+ // messages are not in sync.
+ //
+ // The above comment might be intended to mean that the acknowledge needs to be
+ // send now, because we may call one of the advise functions below, which in
+ // turn may send another message to the OLE 1.0 server. Therefore, we ACK now,
+ // so the messages to the OLE 1.0 server are in the correct order.
+ //
+ if (fAck)
+ {
+ LPARAM lp;
+ if(!wPostMessageToServer (pChannel,
+ WM_DDE_ACK,
+ lp=MAKE_DDE_LPARAM(WM_DDE_ACK,POSITIVE_ACK, aItem),TRUE))
+ {
+ return(RPC_E_SERVER_DIED);
+ }
+ }
+
+ //
+ // this call is now an async call and can not be rejected be HandleIncomingMessage
+ //
+
+ if ((AA_REQUESTAVAILABLE == pChannel->iAwaitAck) && (lpDdeData->fResponse))
+ {
+ //
+ // For some reasons, OnDataAvailable will be the one to delete this data.
+ // I don't understand it, but lets roll with it. (KevinRo)
+ //
+ GlobalUnlock (hDdeData);
+ return OnDataAvailable (pChannel, hDdeData, aItem);
+ }
+
+ //
+ // If the clipboard format is binary, and the topic is aStdDocName, then this
+ // OnData is a RENAME
+ //
+ if (lpDdeData->cfFormat == (short)g_cfBinary && aItem== aStdDocName)
+ {
+ // ON_RENAME
+ //
+ // The data should be the new name, in ANSI.
+ //
+ ChangeTopic ((LPSTR)lpDdeData->Value);
+ GlobalUnlock (hDdeData);
+ GlobalFree (hDdeData);
+ return(NOERROR);
+ }
+
+ //
+ // Based on iAdvOpt, determine if we can callback. This one is a little
+ // hard to understand. I don't either. CanCallBack appears to return
+ // true if the count is 0,1, or 3, but returns FALSE if its 2 or
+ // greater than 3. There are no comments in the old code as to why
+ // this is. I am leaving it, since it must have been put there for
+ // a reason. See CanCallBack in ddeworker.cxx for futher (ie no) details
+ //
+ switch (iAdvOpt)
+ {
+ case ON_SAVE:
+ fCallBack = CanCallBack(&m_iAdvSave);
+ intrDebugOut((INTR_DDE,
+ "::OnData(%x)ON_SAVE m_iAdvSave=%x\n",
+ this,
+ m_iAdvSave));
+
+ break;
+ case ON_CLOSE:
+ fCallBack = CanCallBack(&m_iAdvClose);
+ intrDebugOut((INTR_DDE,
+ "::OnData(%x)ON_CLOSE m_iAdvClose=%x\n",
+ this,
+ m_iAdvClose));
+ break;
+ case ON_CHANGE:
+ fCallBack = TRUE;
+ intrDebugOut((INTR_DDE,
+ "::OnData(%x)ON_CHANGE m_iAdvClose=%x\n",
+ this,
+ m_iAdvClose));
+ break;
+ default:
+ intrAssert( !"Unknown iAdvOpt: Somethings really broke");
+ }
+
+ // Keep the data in a cache for a future GetData call
+ // which may be triggered a few lines later by the
+ // SendOnDataChange().
+
+ fRequested = lpDdeData->fResponse;
+
+
+ // The call to KeepData will change hDdeData and
+ // invalidate lpDdeData. Check out KeepData for details. The net
+ // result is that hDdeData is no longer valid
+
+ GlobalUnlock (hDdeData);
+ lpDdeData=NULL;
+
+ hresult = KeepData (pChannel, hDdeData);
+
+ //
+ // This is unpleasant, but if KeepData fails, we need to
+ // call SetCallState again, resetting the error code. This
+ // code is such a mess that rearranging it to do
+ // it in a rational way is going to be too much work given
+ // the amount of time I have until shipping.
+ //
+ // If you have time, please simplify this code. Thanks
+ //
+ if (hresult != NOERROR)
+ {
+ //
+ // At this point, hDdeData has been unlocked, and deleted by
+ // the KeepData routine. Therefore, the return here doesn't
+ // need to be concerned with cleaning up after hDdeData
+ //
+ intrDebugOut((DEB_ITRACE,
+ "::OnData(%x) KeepData failed %x\n",
+ this,
+ hresult));
+ //
+ // Reset the error code on the call control
+ //
+ if ((AA_REQUEST == iAwaitAck) || (AA_REQUESTAVAILABLE == iAwaitAck))
+ {
+ if (pChannel->pCD )
+ {
+ pChannel->SetCallState(SERVERCALLEX_ISHANDLED, hresult);
+ }
+ }
+ goto exitRtn;
+ }
+
+ if (fRequested)
+ {
+ // We REQUESTed the data. So, we are no longer waiting.
+ // Do NOT call SendOnDataChange because the data hasn't
+ // really changed again, we just requested it to satisfy
+ // a call to GetData, which was probably called by the
+ // real SendOnDataChange.
+ intrDebugOut((INTR_DDE,
+ "::OnData(%x) fRequested DATA\n",
+ this));
+
+ iAwaitAck = NULL;
+ hresult = NOERROR;
+ goto exitRtn;
+
+ }
+
+ //
+ // Now we have decided this is data we had not asked for. This makes
+ // it a change/close/saved notificiation.
+ //
+ intrDebugOut((INTR_DDE,"::OnData(%x) Non requested DATA\n",this));
+ pChannel->AddReference();
+ if (fCallBack && iAdvOpt != ON_CHANGE)
+ {
+ // ON_CHANGE will be handled by OleCallback, below
+
+ intrDebugOut((INTR_DDE,
+ "::OnData(%x)Dispatching SendOnDataChange\n",
+ this));
+
+
+ //
+ // There are a couple of things to note about the following. First,
+ // the iid of the call doesn't matter. Since OLE 1.0 servers don't
+ // do nested calls, the original LID (Logical ID) can be any random
+ // value. Therefore, we don't initalize it.
+ //
+ // According to JohannP, the calltype of these calls is supposed
+ // to be CALLTYPE_SYNC. I don't fully understand why they are.
+ // I am taking is decision on faith.
+ //
+ // Using the new call control interfaces, we do the following.
+ //
+
+ DDEDISPATCHDATA ddedispdata;
+ DISPATCHDATA dispatchdata;
+ DWORD dwFault;
+
+ IUnknown *pUnk = m_pDataAdvHolder;
+
+ //
+ // We are about to call method #6 in the IDataAdviseHolder interface,
+ // which is SendOnDataChange
+ //
+
+ RPCOLEMESSAGE rpcMsg;
+ RPC_SERVER_INTERFACE RpcInterfaceInfo;
+ rpcMsg.reserved2[1] = &RpcInterfaceInfo;
+
+ *MSG_TO_IIDPTR(&rpcMsg) = IID_IDataAdviseHolder;
+
+
+ rpcMsg.Buffer = &dispatchdata;
+ rpcMsg.iMethod = 6;
+
+ dispatchdata.scode = S_OK;
+ dispatchdata.pData = (LPVOID) &ddedispdata;
+
+ ddedispdata.pCDdeObject = this;
+ ddedispdata.wDispFunc = DDE_DISP_SENDONDATACHANGE;
+ ddedispdata.iArg = iAdvOpt;
+
+ // package as RPCMESSAGE and call STAInvoke
+ IRpcStubBuffer * pStub = &m_RpcStubBuffer;
+ hresult = STAInvoke(&rpcMsg, CALLCAT_SYNCHRONOUS, pStub, pChannel, NULL, &dwFault );
+ }
+ if (fCallBack )
+ {
+ // in 1.0 ON_CLOSE comes with data
+ if (iAdvOpt==ON_CLOSE)
+ {
+
+ intrDebugOut((INTR_DDE,
+ "::OnData(%x) iAdvOpt == ON_CLOSE, send ON_SAVE\n",
+ this));
+
+ m_fGotCloseData = TRUE;
+
+ hresult = OleCallBack(ON_SAVE,pChannel);
+ if (hresult != NOERROR)
+ {
+ goto errRel;
+ }
+
+ //ErrRtnH (DdeHandleIncomingCall(pChannel->hwndSvr, CALLTYPE_TOPLEVEL) );
+ //ErrRtnH (OleCallBack (ON_SAVE));
+ }
+
+ // check if app can handle this call
+ // we do not need to call HIC for SendOnClose
+
+ hresult = OleCallBack (iAdvOpt,pChannel);
+ }
+
+errRel:
+ // Don't use pChannel after this. It can get deleted. (srinik)
+ if (pChannel->ReleaseReference() == 0)
+ {
+ m_pDocChannel = NULL;
+ }
+
+exitRtn:
+ if (!fAck && aItem)
+ {
+ GlobalDeleteAtom (aItem);
+ }
+ return hresult;
+#endif _MAC
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::OleCallBack
+//
+// Synopsis: Send all the right notifications whan a Save or Close happens.
+//
+// Effects: OleCallBack is a double duty function. It is called in two
+// different cases.
+//
+// First, is to setup the callback, and call HandleIncomingCall.
+// Second is from DispatchCall() in the CDdeChannelControl.
+//
+// The reason for doing it this way is we localize the setup
+// and processing of these calls to one routine. Therefore,
+// we can go to one spot in the code to find all of the call
+// back information.
+//
+// Arguments: [iAdvOpt] -- Which Advise operation to perform
+// [pChannel] -- Which channel is being called back
+//
+// Requires: pChannel == NULL, and the AdviseHolders are called.
+// pChannel != NULL, and the call is setup, and HandleIncomingCall
+// is setup.
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-23-94 kevinro Created
+//
+// Notes:
+//
+// WARNING: This code sucks completely. One of the major problems you need
+// to know about is that the CDdeObject may go away as part of the normal
+// processing of some of the below. Be very careful about any processing
+// that might occur after an ON_CLOSE
+//
+//----------------------------------------------------------------------------
+INTERNAL CDdeObject::OleCallBack (int iAdvOpt, LPDDE_CHANNEL pChannel)
+{
+ HRESULT hresult = NOERROR;
+ DDEDISPATCHDATA ddedispdata;
+ DISPATCHDATA dispatchdata;
+ RPCOLEMESSAGE rpcMsg;
+ IUnknown *pUnk;
+
+ RPC_SERVER_INTERFACE RpcInterfaceInfo;
+ rpcMsg.reserved2[1] = &RpcInterfaceInfo;
+
+ //
+ // If the channel isn't NULL, then setup the data structures for calling
+ // off to the call control.
+ //
+ if (pChannel != NULL)
+ {
+ //
+ // Only do this work if we really have to
+ //
+
+ dispatchdata.scode = S_OK;
+ dispatchdata.pData = (LPVOID) &ddedispdata;
+
+ ddedispdata.pCDdeObject = this;
+ ddedispdata.wDispFunc = DDE_DISP_OLECALLBACK;
+ ddedispdata.iArg = iAdvOpt;
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::OleCallBack(%x,iAdvOpt=%x,pChannel=%x)\n",
+ this,
+ iAdvOpt,
+ pChannel));
+
+ //
+ // Determine what needs to be done, based on the iAdvOpt. This should be
+ // one of the handled cases below, otherwise its an error.
+ //
+ switch (iAdvOpt)
+ {
+ case ON_CLOSE:
+ if (pChannel != NULL)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::OleCallBack(%x) setup for ON_CLOSE\n",
+ this));
+
+ pUnk = m_pOleAdvHolder;
+
+ *MSG_TO_IIDPTR(&rpcMsg) = IID_IOleAdviseHolder;
+ // IOleAdviseHolder::SendOnClose is method 8
+ rpcMsg.iMethod = 8;
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE,"::OleCallBack(%x) ON_CLOSE\n",this));
+ DeclareVisibility (FALSE);
+ RetZ (!m_fDidSendOnClose); // This SendOnClose should happen 1st
+ // Don't let OnTerminate() do it too
+ hresult = SendOnClose();
+
+ //
+ // WARNING WARNING WARNING: SendOnClose() may have caused the
+ // destruction of this CDdeObject. Touch nothing on the way
+ // out. Actually, if you have time, which I currently don't,
+ // see what you can do with reference counting tricks to
+ // insure this object doesn't die during this callback.
+ // Its a tricky problem, and we are shipping in 2 weeks.
+ // (KevinRo 8/6/94)
+ //
+ }
+ break;
+
+ case ON_SAVE:
+ if (pChannel != NULL)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::OleCallBack(%x) setup for ON_SAVE\n",
+ this));
+
+ if (m_pOleClientSite == NULL)
+ {
+ pUnk = m_pOleClientSite;
+ *MSG_TO_IIDPTR(&rpcMsg) = IID_IOleClientSite;
+ // IOleClientSite::SaveObject method 7
+ rpcMsg.iMethod = 7;
+ }
+ else
+ {
+ // Going to call the IOleAdviseHolder
+
+ pUnk = m_pOleAdvHolder;
+ *MSG_TO_IIDPTR(&rpcMsg) = IID_IOleAdviseHolder;
+ // IOleAdviseHolder::SendOnSave method 7
+ // (Yes, same ordinal as above, I double checked)
+ rpcMsg.iMethod = 7;
+ }
+ }
+ else
+ {
+
+ intrDebugOut((DEB_ITRACE,"::OleCallBack(%x) ON_SAVE\n",this));
+ if (m_pOleClientSite)
+ {
+ // We just got data from the server, so we don't want to
+ // ask him for it again when the container does a save.
+ m_fUpdateOnSave = FALSE;
+
+ // Harvard Graphics Access Violates if SaveObject is called on the ClientSite from
+ // within OleCreateFromData.
+ __try
+ {
+ m_pOleClientSite->SaveObject();
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ intrDebugOut((DEB_IWARN ,"Warning: Exception in SaveObject\n"));
+ }
+
+ // SendOnSave is called in PS::SaveCompleted
+ m_fUpdateOnSave = TRUE;
+ }
+ else
+ {
+ // Link case
+ RetZS (m_pOleAdvHolder, E_OUTOFMEMORY);
+ m_pOleAdvHolder->SendOnSave();
+ }
+ }
+ break;
+
+ case ON_CHANGE:
+ if (pChannel != NULL)
+ {
+ // Going to call the IDataAdviseHolder
+
+ pUnk = m_pDataAdvHolder;
+ *MSG_TO_IIDPTR(&rpcMsg) = IID_IDataAdviseHolder;
+ // IDataAdviseHolder::SendOnDataChange method 6
+ rpcMsg.iMethod = 6;
+
+ }
+ else
+ {
+ RetZS (m_pDataAdvHolder, E_OUTOFMEMORY);
+ intrDebugOut((DEB_ITRACE,"::OleCallBack(%x) ON_CHANGE\n",this));
+ hresult = SendOnDataChange (ON_CHANGE);
+ }
+ break;
+
+ default:
+
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::OleCallBack(%x,iAdvOpt=%x) UNKNOWN iAdvOpt\n",
+ this,
+ iAdvOpt));
+ intrAssert(!"Unexpected iAdvOpt");
+ return(E_UNEXPECTED);
+ break;
+ }
+
+ //
+ // There are a couple of things to note about the following. First,
+ // the iid of the call doesn't matter. Since OLE 1.0 servers don't
+ // do nested calls, the original LID (Logical ID) can be any random
+ // value. Therefore, we don't initalize it.
+ //
+ // According to JohannP, the calltype of these calls is supposed
+ // to be CALLTYPE_SYNCHRONOUS. I don't fully understand why they are.
+ // I am taking is decision on faith.
+ //
+ //
+ // Its possible that during the handling of this call that this object
+ // will get deleted. This is a pain in the butt. This means that anything
+ // used after this call MUST be protected. lpCallCont happens to be one of
+ // these. We have been having problems with lpCallCont being released as
+ // part of the object cleanup. The call control code will access member
+ // variables on its way out of the HandleDispatch. We need to bracket
+ // the call below so this doesn't happen.
+ //
+ if (pChannel != NULL)
+ {
+ // dont have to worry about call control going away.
+ // package as RPCMESSAGE and call STAInvoke
+
+ DWORD dwFault;
+
+ rpcMsg.Buffer = &dispatchdata;
+
+ // BUGBUG: does it matter if we package up the pUnk?
+ IRpcStubBuffer * pStub = &m_RpcStubBuffer;
+ hresult = STAInvoke(&rpcMsg, CALLCAT_SYNCHRONOUS, pStub, pChannel, NULL, &dwFault);
+ }
+
+ return hresult;
+}
+
+
+INTERNAL CDdeObject::SendOnDataChange
+ (int iAdvOpt)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::SendOnDataChange(%x)\n",this));
+ HRESULT hresult;
+ RetZS (m_pDataAdvHolder, E_OUTOFMEMORY);
+ m_fDoingSendOnDataChange = TRUE;
+ hresult = m_pDataAdvHolder->SendOnDataChange (&m_Data,
+ DVASPECT_CONTENT,
+ 0);
+ if (ON_CLOSE==iAdvOpt)
+ {
+ hresult = m_pDataAdvHolder->SendOnDataChange (&m_Data,
+ DVASPECT_CONTENT,
+ ADVF_DATAONSTOP);
+ }
+ m_fDoingSendOnDataChange = FALSE;
+ return hresult;
+}
+
+
+
+
+INTERNAL CDdeObject::SendOnClose
+ (void)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::SendOnClose(%x)\n",this));
+ RetZS (m_pOleAdvHolder, E_OUTOFMEMORY);
+ m_fDidSendOnClose = TRUE;
+ RetErr (m_pOleAdvHolder->SendOnClose() );
+ return NOERROR;
+}
+
+
+
+
+INTERNAL CDdeObject::OnTerminate
+ (LPDDE_CHANNEL pChannel,
+ HWND hwndPost)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::OnTerminate(%x,pChannel=%x,hwndPost=%x)\n",
+ this,
+ pChannel,
+ hwndPost));
+
+ //
+ // If the hwndPost and hwndSvr are different, then it is one of two
+ // cases. We could have recieved more than one Acknowlege during our
+ // initiate, in which case the count iExtraTerms would have been
+ // incremented, and this terminate is accounted for iExtraTerms.
+ //
+ // The other case is that we were terminated by a window that was
+ // NOT the window we were conversing with.
+ //
+ if (pChannel->hwndSvr != hwndPost)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::OnTerminate(%x) Extra terms is 0x%x \n",
+ this,
+ pChannel->iExtraTerms));
+
+ //
+ // iExtraTerms shouldn't go below zero. If it does, something
+ // has gone wrong. We have been seeing some problems with the
+ // HWND mapping layer in the past. If the following condition
+ // ever trips, then it is possible that another mapping
+ // problem has been seen.
+ //
+#if DBG == 1
+ if((pChannel->iExtraTerms == 0 ) &&
+ (((DWORD)pChannel->hwndSvr) & (0xffff)) == ((DWORD)hwndPost & (0xffff)))
+ {
+ intrDebugOut((DEB_ERROR,
+ "*** OnTerminate expected hwnd=%x got hwnd=%x ***\n",
+ pChannel->hwndSvr,hwndPost));
+
+ intrDebugOut((DEB_ERROR,
+ "\n*** Call KevinRo or SanfordS ***\n\n",
+ pChannel->hwndSvr,hwndPost));
+
+ }
+#endif
+ --pChannel->iExtraTerms;
+
+ intrAssert((pChannel->iExtraTerms >= 0) && "Call KevinRo or SanfordS");
+ return NOERROR;
+ }
+ if (m_wTerminate == Terminate_Detect) {
+ // we should only detect the call but not execute the code
+ // set the state to Received
+ m_wTerminate = Terminate_Received;
+ pChannel->iAwaitAck = NULL;
+ // Since Excel incorrectly did not send an ACK, we need to
+ // delete the handle in the DDE message ourselves.
+ if (pChannel->hCommands)
+ {
+ GlobalFree (pChannel->hCommands);
+ pChannel->hCommands = NULL;
+ }
+ //CoSetAckState(pChannel->pCI, FALSE);
+ intrDebugOut((DEB_ITRACE,
+ "::OnTerminate(%x) Terminate_Detect SERVERCALLEX_ISHANDLED\n",
+ this));
+ pChannel->SetCallState(SERVERCALLEX_ISHANDLED, RPC_E_SERVER_DIED);
+ return NOERROR;
+ }
+
+ RetZ (pChannel);
+ ChkDR (this);
+
+ if (!pChannel->bTerminating)
+ {
+ // Got unprompted terminate
+ BOOL bBusy;
+
+ // Necessary safety bracket
+ m_pUnkOuter->AddRef();
+
+ bBusy = wClearWaitState (pChannel);
+
+ if (pChannel->iAwaitAck || bBusy)
+ {
+ pChannel->iAwaitAck = NULL;
+ //CoSetAckState(pChannel->pCI, FALSE);
+ intrDebugOut((DEB_ITRACE,"::OnTerminate(%x) !bTerminating SERVERCALLEX_ISHANDLED,RPC_E_DDE_UNEXP_MSG\n",this));
+ pChannel->SetCallState(SERVERCALLEX_ISHANDLED, RPC_E_DDE_UNEXP_MSG);
+ }
+
+ if (!m_fDidSendOnClose)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::OnTerminate(%x) SendOnClose from terminate\n",
+ this));
+
+ BOOL f= m_fNoStdCloseDoc;
+ m_fNoStdCloseDoc = TRUE;
+
+ DeclareVisibility (FALSE);
+ SendOnClose();
+
+ m_fNoStdCloseDoc = f;
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::OnTerminate(%x) Already did SendOnClose\n",
+ this));
+ Puts ("Already did SendOnClose\n");
+ }
+ intrDebugOut((DEB_ITRACE,
+ "::OnTerminate(%x) Posting DDE_TERMINATE as reply\n",
+ this));
+
+ wPostMessageToServer (pChannel, WM_DDE_TERMINATE, NULL,FALSE);
+
+ // The terminate that we are sending itself is a reply, so we don't
+ // need to do WaitForReply.
+ DeleteChannel (pChannel);
+
+ // Necessary safety bracket
+ m_pUnkOuter->Release();
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::OnTerminate(%x) Received DDE_TERMINATE in reply\n",
+ this));
+
+ // We sent the WM_DDE_TERMINATE and we got the acknowledge for it
+ pChannel->hwndSvr = NULL;
+ pChannel->iExtraTerms = NULL;
+ pChannel->iAwaitAck = NULL;
+ //CoSetAckState(pChannel->pCI, FALSE);
+ intrDebugOut((DEB_ITRACE,"::OnTerminate(%x) bTerminating SERVERCALLEX_ISHANDLED\n",this));
+ pChannel->SetCallState(SERVERCALLEX_ISHANDLED);
+ }
+ Puts ("OnTerminate() done.\n");
+ return NOERROR;
+}
+
+
+
+
+INTERNAL_(BOOL) CDdeObject::AllocDdeChannel
+ (LPDDE_CHANNEL * lplpChannel, BOOL fSysWndProc)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::AllocDdeChannel(%x,fSysWndClass=%x)\n",
+ this,
+ fSysWndProc));
+
+ //
+ // Now try to allocate a channel
+ //
+
+ if (!(*lplpChannel = (LPDDE_CHANNEL) new DDE_CHANNEL ))
+ {
+ //
+ // This failed
+ //
+ intrAssert(*lplpChannel != NULL);
+ return FALSE;
+ }
+
+ (*lplpChannel)->m_cRefs = 1;
+ (*lplpChannel)->hwndSvr = NULL;
+ (*lplpChannel)->bTerminating = FALSE;
+ (*lplpChannel)->wTimer = NULL;
+ (*lplpChannel)->hDdePoke = NULL;
+ (*lplpChannel)->hCommands = NULL;
+ (*lplpChannel)->hopt = NULL;
+ (*lplpChannel)->dwStartTickCount= 0;
+ (*lplpChannel)->msgFirst = 0;
+ (*lplpChannel)->msgLast = 0;
+ (*lplpChannel)->fRejected = FALSE;
+ (*lplpChannel)->wChannelDeleted = 0;
+ //(*lplpChannel)->pCI = NULL;
+ (*lplpChannel)->pCD = NULL;
+
+ if (!((*lplpChannel)->hwndCli = DdeCreateWindowEx(0,
+ gOleWindowClass,
+ L"DDE Channel",
+ WS_CHILD,
+ 0,0,0,0,
+ (HWND)TLSGetDdeClientWindow(),
+ NULL,
+ hinstSO,
+ NULL)))
+ {
+ intrAssert (!"Could not create AllocDdeChannel window");
+
+ //
+ // DeleteChannel will give back the CallControl
+ //
+
+ DeleteChannel(*lplpChannel);
+ *lplpChannel = NULL;
+ return FALSE;
+ }
+
+ // set the appropriate window procedure
+ if (fSysWndProc)
+ {
+ SetWindowLong ((*lplpChannel)->hwndCli, GWL_WNDPROC, (LONG)SysWndProc);
+ }
+ else
+ {
+ SetWindowLong ((*lplpChannel)->hwndCli, GWL_WNDPROC, (LONG)ClientDocWndProc);
+ }
+
+ SetWindowLong ((*lplpChannel)->hwndCli, 0, (LONG) this);
+ return TRUE;
+}
+
+
+
+INTERNAL_(BOOL) CDdeObject::InitSysConv()
+{
+ DWORD dwResult;
+ intrDebugOut((DEB_ITRACE,"CDdeObject::InitSysConv(%x)\n",this));
+
+ dwResult = wInitiate (m_pSysChannel, m_aClass, aOLE);
+ if (!dwResult)
+ {
+ intrDebugOut((DEB_ITRACE,"\t::InitSysConv(%x) Try aSysTopic\n",this));
+ dwResult = wInitiate (m_pSysChannel, m_aClass, aSysTopic);
+ }
+
+ if (!dwResult)
+ {
+ intrDebugOut((DEB_ITRACE,"\t::InitSysConv(%x) is failing\n",this));
+ }
+ return(dwResult);
+}
+
+
+
+INTERNAL_(void) CDdeObject::SetTopic(ATOM aTopic)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::SetTopic(%x)\n",this));
+ intrAssert(wIsValidAtom(aTopic));
+ if (m_aTopic)
+ GlobalDeleteAtom (m_aTopic);
+
+ m_aTopic = aTopic;
+}
+
+
+
+INTERNAL CDdeObject::TermConv
+ (LPDDE_CHANNEL pChannel,
+ BOOL fWait) // Default==TRUE. FALSE only in ProxyManager::Disconnect
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::TermConv(%x,pChannel=%x)\n",
+ this,
+ pChannel));
+
+ HRESULT hres;
+ if (!pChannel)
+ {
+ return NOERROR;
+ }
+
+ pChannel->bTerminating = TRUE;
+
+ hres = SendMsgAndWaitForReply(pChannel,
+ AA_TERMINATE,
+ WM_DDE_TERMINATE,
+ 0,
+ FALSE,
+ /*fStdCloseDoc*/FALSE,
+ /*fDetectTerminate*/ FALSE,
+ fWait);
+ if (pChannel==m_pDocChannel)
+ {
+ DeclareVisibility (FALSE);
+ if (!m_fDidSendOnClose)
+ {
+ SendOnClose();
+ }
+ }
+
+ DeleteChannel (pChannel);
+ intrDebugOut((DEB_ITRACE,"::TermConv(%x) returns %x\n",this,hres));
+ return hres;
+}
+
+
+
+
+INTERNAL_(void) CDdeObject::DeleteChannel (LPDDE_CHANNEL pChannel)
+{
+ BOOL fDocChannel = FALSE;
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::DeleteChannel(%x,pChannel=%x)\n",
+ this,
+ pChannel));
+
+ if (pChannel == NULL)
+ {
+ return;
+ }
+
+ if (pChannel == m_pDocChannel)
+ fDocChannel = TRUE;
+
+
+
+ // delete any data if we were in busy mode.
+ wClearWaitState (pChannel);
+
+ if (pChannel == m_pDocChannel)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::DeleteChannel(%x)Clean up pDocChannel\n",
+ this));
+
+ // Cleanup per-conversation information
+ m_fDidSendOnClose = FALSE;
+ m_fDidStdCloseDoc = FALSE;
+ m_ConnectionTable.Erase();
+ m_iAdvSave = 0;
+ m_iAdvClose= 0;
+ m_fWasEverVisible = FALSE;
+ m_fGotCloseData = FALSE;
+ if (m_ptd)
+ {
+ delete m_ptd;
+ m_ptd = NULL;
+ }
+ if (m_pstg)
+ {
+ m_pstg->Release();
+ m_pstg = NULL;
+ }
+ if (m_pDataAdvHolder)
+ {
+ Verify (0==m_pDataAdvHolder->Release());
+ }
+ CreateDataAdviseHolder (&m_pDataAdvHolder);
+ if (m_pOleAdvHolder)
+ {
+ m_pOleAdvHolder->Release(); // may not return 0 if we are
+ // in a SendOnClose
+ }
+ CreateOleAdviseHolder (&m_pOleAdvHolder);
+ }
+
+ if (pChannel->hwndCli)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::DeleteChannel(%x)Destroy hwndCli(%x)\n",
+ this,
+ pChannel->hwndCli));
+
+ Assert (IsWindow (pChannel->hwndCli));
+ Assert (this==(CDdeObject *)GetWindowLong (pChannel->hwndCli, 0));
+ Verify (SSDestroyWindow (pChannel->hwndCli));
+ }
+
+ if (pChannel == m_pDocChannel)
+ {
+ m_pDocChannel = NULL;
+ }
+ else
+ {
+ intrAssert(pChannel == m_pSysChannel);
+ m_pSysChannel = NULL;
+ }
+
+
+ // Channel will be deleted in the modallp.cpp
+ // if flag is on.
+
+ if (pChannel->wChannelDeleted == Channel_InModalloop)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::DeleteChannel(%x) Channel(%x) in Modal Loop\n",
+ this,pChannel));
+
+ pChannel->wChannelDeleted = Channel_DeleteNow;
+ }
+ else
+ {
+ if (pChannel->ReleaseReference() == 0)
+ pChannel = NULL;
+ }
+
+ if (fDocChannel)
+ m_pDocChannel = pChannel;
+}
+
+const WCHAR EMB_STR[]= OLESTR(" -Embedding ") ;
+
+INTERNAL_(BOOL) CDdeObject::LaunchApp (void)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::LaunchApp(%x)\n",this));
+
+ STARTUPINFO startInfo;
+ PROCESS_INFORMATION procInfo;
+ BOOL fProcStarted;
+ WCHAR cmdline[MAX_PATH + sizeof(EMB_STR)];
+ WCHAR exeName[MAX_PATH + sizeof(cmdline)];
+ //
+ // Init all fields of startInfo to zero
+ //
+ memset((void *)&startInfo,0,sizeof(startInfo));
+
+ //
+ // The normal startup is set here.
+ //
+ startInfo.wShowWindow = SW_NORMAL;
+ startInfo.dwFlags = STARTF_USESHOWWINDOW;
+
+ m_fDidLaunchApp = FALSE;
+
+
+ DWORD dw;
+
+ //
+ // Do our best to find the path
+ //
+ intrAssert(wIsValidAtom(m_aExeName));
+
+ if (m_aExeName == 0)
+ {
+ //
+ // There is no exe name to execute. Can't start it.
+ //
+ return(FALSE);
+ }
+
+ dw = SearchPath(NULL,wAtomName(m_aExeName),NULL,MAX_PATH,exeName, NULL);
+
+ if ((dw == 0) || (dw > MAX_PATH))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::LaunchApp(%x) SearchPath failed. Do Default",this));
+ //
+ // SearchPath failed. Use the default
+ //
+ GlobalGetAtomName (m_aExeName, exeName, MAX_PATH);
+ }
+
+ memcpy(cmdline, EMB_STR,sizeof(EMB_STR));
+
+ if (m_ulObjType == OT_LINK)
+ {
+ intrAssert(wIsValidAtom(m_aTopic));
+ // File name
+ Assert (wAtomName (m_aTopic));
+
+ lstrcatW (cmdline, wAtomName (m_aTopic));
+ }
+
+ if (m_clsid == CLSID_ExcelWorksheet // Stupid apps that show themselves
+ || m_clsid == CLSID_ExcelMacrosheet // when they're not supposed to
+ || m_clsid == CLSID_ExcelChart
+ || m_clsid == CLSID_PBrush)
+ {
+ startInfo.wShowWindow = SW_SHOWMINNOACTIVE;
+ }
+
+ //
+ // According to the spec, the most robust way to start the app is to
+ // only use a cmdline that consists of the exe name, followed by the
+ // command line arguments.
+ //
+
+ lstrcatW(exeName,cmdline);
+
+ Assert((lstrlenW(exeName)+1) < sizeof(exeName));
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::LaunchApp(%x) Starting '%ws' \n",
+ this,
+ exeName));
+
+ if (IsWOWThread() && IsWOWThreadCallable())
+ {
+ HRESULT hr;
+
+ hr = g_pOleThunkWOW->WinExec16(exeName, startInfo.wShowWindow);
+
+ fProcStarted = SUCCEEDED(hr);
+
+#if DBG==1
+ if (!fProcStarted)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::LaunchApp(%x) in Wow FAILED(%x) TO START %ws \n",
+ this,
+ hr,
+ exeName));
+ }
+#endif
+ }
+ else
+ {
+ fProcStarted = CreateProcess(NULL,
+ exeName,
+ NULL,
+ NULL,
+ FALSE,
+ 0,
+ NULL,
+ NULL,
+ &startInfo,
+ &procInfo);
+ if (fProcStarted)
+ {
+ //
+ // Let's give the server a chance to register itself. On NT,
+ // CreateProcess gets the other process going, but returns
+ // to let it run asynchronously. This isn't good, since we
+ // need some way of knowing when it has started, so we can
+ // send the DDE_INITIATES 'after' they create their DDE
+ // window.
+ //
+ // Maximum timeout we want here shall be set at 30 seconds.
+ // This should give enough time for even a 16bit WOW app to
+ // start. This number was picked by trial and error. Normal
+ // apps that go into an InputIdle state will return as soon
+ // as they are ready. Therefore, we normally won't wait
+ // the full duration.
+ //
+
+ ULONG ulTimeoutDuration = 30000L;
+
+ //
+ // Now modify this start time to handle classes
+ // that have known problems. This list includes:
+ //
+
+ switch(WaitForInputIdle(procInfo.hProcess, ulTimeoutDuration))
+ {
+ case 0:
+ intrDebugOut((DEB_ITRACE,
+ "::LaunchApp, %ws started\n",
+ exeName));
+ break;
+ case WAIT_TIMEOUT:
+ intrDebugOut((DEB_ITRACE,
+ "::LaunchApp, %ws wait timeout at %u (dec) ms. Go Anyway\n",
+ exeName,
+ ulTimeoutDuration));
+ break;
+ default:
+ intrDebugOut((DEB_ITRACE,
+ "::LaunchApp, %ws unknown condition (%x)\n",
+ exeName,
+ GetLastError()));
+ }
+ //
+ // We are already done with the Process and Thread handles
+ //
+ CloseHandle(procInfo.hProcess);
+ CloseHandle(procInfo.hThread);
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::LaunchApp(%x) FAILED(%x) TO START %ws \n",
+ this,
+ GetLastError(),
+ exeName));
+ }
+ }
+
+ if (fProcStarted)
+ {
+ // If we ran the server, it should not be visible yet.
+ DeclareVisibility (FALSE);
+ m_fDidLaunchApp = TRUE;
+ }
+
+ return fProcStarted;
+}
+
+
+INTERNAL CDdeObject::MaybeUnlaunchApp (void)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::MaybeUnlaunchApp(%x)\n",this));
+ if (m_fDidLaunchApp
+ && !m_fDidGetObject
+ && (m_clsid == CLSID_ExcelWorksheet
+ || m_clsid == CLSID_ExcelMacrosheet
+ || m_clsid == CLSID_ExcelChart))
+ {
+ return UnlaunchApp();
+ }
+ return NOERROR;
+}
+
+
+
+
+INTERNAL CDdeObject::UnlaunchApp (void)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::UnlaunchApp(%x)\n",this));
+ HANDLE hCommands;
+ HRESULT hresult = NOERROR;
+ RetZS (AllocDdeChannel (&m_pSysChannel, TRUE), E_OUTOFMEMORY);
+ ErrZS (InitSysConv(), E_UNEXPECTED);
+ ErrRtnH (PostSysCommand (m_pSysChannel,(LPSTR) &achStdExit, /*bStdNew*/FALSE,
+ /*fWait*/FALSE));
+ hCommands = m_pSysChannel->hCommands;
+ hresult = TermConv (m_pSysChannel);
+
+ // Since Excel incorrectly did not send an ACK, we need to
+ // delete the handle ("[StdExit]") in the DDE message ourselves.
+ if (hCommands)
+ GlobalFree (hCommands);
+
+ return hresult;
+
+ errRtn:
+ DeleteChannel (m_pSysChannel);
+ return hresult;
+}
+
+
+
+
+INTERNAL CDdeObject::Execute
+ (LPDDE_CHANNEL pChannel,
+ HANDLE hdata,
+ BOOL fStdCloseDoc,
+ BOOL fWait,
+ BOOL fDetectTerminate)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::Execute(%x,hdata=%x)\n",this,hdata));
+
+ LPARAM lp=MAKE_DDE_LPARAM(WM_DDE_EXECUTE,0, hdata);
+
+ HRESULT hr = SendMsgAndWaitForReply (pChannel,
+ AA_EXECUTE,
+ WM_DDE_EXECUTE,
+ lp,
+ TRUE,
+ fStdCloseDoc,
+ fDetectTerminate,
+ fWait);
+ if (hr == DDE_CHANNEL_DELETED)
+ {
+ // the channel was deleted already so dont access it!
+ return S_OK;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (fStdCloseDoc)
+ {
+ // Prepare to free the handle if Excel does not send an Ack
+ pChannel->hCommands = hdata;
+ }
+ return hr;
+ }
+
+ GlobalFree (hdata);
+ return ReportResult(0, RPC_E_DDE_POST, 0, 0);
+}
+
+
+
+
+INTERNAL_(HRESULT) CDdeObject::AdviseOn (CLIPFORMAT cfFormat, int iAdvOn)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::AdviseOn(%x,cfFormat=%x,iAdvOn=%x)\n",
+ this,
+ cfFormat,
+ iAdvOn));
+
+ HANDLE hopt=NULL;
+ DDEADVISE * lpopt=NULL;
+ ATOM aItem=(ATOM)0;
+ HRESULT hresult = ReportResult(0, E_UNEXPECTED, 0, 0);
+
+ RetZ (m_pDocChannel);
+
+ if (NOERROR == m_ConnectionTable.Lookup (cfFormat, NULL))
+ {
+ // We already got a call to DataObject::Advise on this format.
+ intrDebugOut((DEB_ITRACE,
+ "::AdviseOn(%x) Advise had been done on cfFormat=%x\n",
+ this,
+ cfFormat));
+ return NOERROR;
+ }
+
+ UpdateAdviseCounts (cfFormat, iAdvOn, +1);
+
+ if (m_fDidSendOnClose)
+ {
+ intrDebugOut((DEB_ITRACE,"::AdviseOn(%x)Ignoring Advise because we are closing\n",this));
+ return NOERROR;
+ }
+
+ if (!(hopt = GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT, sizeof(DDEADVISE))))
+ {
+ intrDebugOut((DEB_ITRACE,"::AdviseOn(%x)GlobalAlloc returned NULL\n",this));
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+
+ if (!(lpopt = (DDEADVISE FAR *) GlobalLock (hopt)))
+ {
+ intrDebugOut((DEB_ITRACE,"::AdviseOn(%x)GlobalLock returned NULL\n",this));
+ GlobalFree (hopt);
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ lpopt->fAckReq = TRUE;
+ lpopt->fDeferUpd = FALSE;
+ lpopt->cfFormat = cfFormat;
+ m_pDocChannel->hopt = hopt;
+
+ if (iAdvOn == ON_RENAME)
+ {
+ aItem = wDupAtom (aStdDocName);
+ intrAssert(wIsValidAtom(aItem));
+ }
+ else
+ {
+ intrAssert(wIsValidAtom(m_aItem));
+ aItem = wExtendAtom (m_aItem, iAdvOn);
+ intrAssert(wIsValidAtom(aItem));
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "::AdviseOn(%x) lpopt->cfFormat = %x, aItem=%x (%ws)\n",
+ this,
+ lpopt->cfFormat,
+ aItem,
+ wAtomName(aItem)));
+
+ GlobalUnlock (hopt);
+
+ LPARAM lp=MAKE_DDE_LPARAM(WM_DDE_ADVISE,hopt,aItem);
+ hresult =SendMsgAndWaitForReply (m_pDocChannel,
+ AA_ADVISE,
+ WM_DDE_ADVISE,
+ lp,
+ TRUE);
+ if ( FAILED(hresult) )
+ {
+ intrDebugOut((DEB_ITRACE,"::AdviseOn(%x)wPostMessageToServer failed\n",this));
+ if (aItem)
+ GlobalDeleteAtom (aItem);
+ if (hopt)
+ GlobalFree (hopt);
+ hresult = (RPC_E_DDE_NACK == hresult) ? DV_E_CLIPFORMAT : hresult;
+ intrDebugOut((DEB_ITRACE,
+ "::AdviseOn(%x) errRet, AdviseRejected, returning %x\n",
+ this,hresult));
+ }
+
+ return hresult;
+}
+
+INTERNAL CDdeObject::UpdateAdviseCounts
+ (CLIPFORMAT cf,
+ int iAdvOn,
+ signed int cDelta)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::UpdateAdviseCounts(%x)\n",this));
+ if (cf==g_cfBinary)
+ return NOERROR;
+
+ // Update m_iAdv* flags
+ #define macro(Notif, NOTIF) \
+ if (iAdvOn == ON_##NOTIF) \
+ m_iAdv##Notif += cDelta; \
+ if (m_iAdv##Notif < 0) \
+ m_iAdv##Notif = 0; \
+ else if (m_iAdv##Notif > 2) \
+ m_iAdv##Notif = 2;
+
+ macro (Close, CLOSE)
+ macro (Save, SAVE)
+ macro (Change,CHANGE)
+ #undef macro
+
+ Assert (m_iAdvClose < 3 && m_iAdvSave < 3 && m_iAdvChange < 3);
+ Assert (m_iAdvClose >= 0 && m_iAdvSave >= 0 && m_iAdvChange >= 0);
+
+ if (cf == g_cfNative)
+ {
+ if (iAdvOn != ON_CHANGE)
+ m_fDidAdvNative = (cDelta > 0);
+ else
+ intrDebugOut((DEB_ITRACE,
+ "::UpdateAdviseCounts(%x)Asked advise on cfNative\n",
+ this));
+ }
+
+ return NOERROR;
+}
+
+
+
+
+INTERNAL CDdeObject::UnAdviseOn (CLIPFORMAT cfFormat, int iAdvOn)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::UnAdviseOn(%x,cfFormat=%x,iAdvOn=%x)\n",
+ this,cfFormat,iAdvOn));
+ HRESULT hr;
+ ATOM aItem= (ATOM)0;
+
+ RetZ (m_pDocChannel);
+ UpdateAdviseCounts (cfFormat, iAdvOn, -1);
+ if (m_fDidSendOnClose)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::UnAdviseOn(%x) Ignored because closing\n",
+ this));
+ return NOERROR;
+ }
+ if (wTerminateIsComing (m_pDocChannel))
+ {
+ // We already did a StdCloseDocument, so the server is not willing
+ // to do an unadvise even though the default hanlder asked us to.
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::UnAdviseOn(%x) Terminate coming\n",
+ this));
+ return NOERROR;
+ }
+
+ if (iAdvOn == ON_RENAME)
+ {
+ aItem = wDupAtom (aStdDocName);
+ intrAssert(wIsValidAtom(aItem));
+ }
+ else
+ {
+ intrAssert(wIsValidAtom(m_aItem));
+ aItem = wExtendAtom (m_aItem, iAdvOn);
+ intrAssert(wIsValidAtom(aItem));
+ }
+
+
+ // Wait For Reply
+ hr = SendMsgAndWaitForReply (m_pDocChannel,
+ AA_UNADVISE,
+ WM_DDE_UNADVISE,
+ MAKE_DDE_LPARAM (WM_DDE_UNADVISE,cfFormat,aItem),
+ FALSE,
+ FALSE);
+ if (hr != NOERROR && hr != RPC_E_DDE_NACK)
+ {
+ if (aItem)
+ GlobalDeleteAtom (aItem);
+ intrDebugOut((DEB_ITRACE,
+ "::UnAdviseOn(%x)WaitForReply returns %x\n",
+ this));
+ return hr;
+ }
+
+
+ if (cfFormat==m_cfPict)
+ {
+ if (m_hPict)
+ {
+ // Invalidate the cache so when someone explicitly asks for
+ // the data, they will get fresh data.
+ wFreeData (m_hPict, m_cfPict, TRUE);
+ m_hPict = (HANDLE)0;
+ m_cfPict = 0;
+ }
+ }
+
+ // Due to a bug in the OLE1 libraries, unadvising on a presentation
+ // format effectively unadvises on native.
+ if (cfFormat != g_cfNative && m_fDidAdvNative)
+ {
+ if (iAdvOn == ON_SAVE)
+ {
+ // to reflect the fact that the native advise connection was lost
+ m_iAdvSave--;
+ m_fDidAdvNative = FALSE;
+ RetErr (AdviseOn (g_cfNative, ON_SAVE)); // re-establish
+ }
+ else if (iAdvOn == ON_CLOSE)
+ {
+ // to reflect the fact that the native advise connection was lost
+ m_iAdvClose--;
+ m_fDidAdvNative = FALSE;
+ RetErr (AdviseOn (g_cfNative, ON_CLOSE));
+ }
+ }
+
+ return NOERROR;
+}
+
+
+//
+// Post a message to a 1.0 server (callee) and wait for the acknowledge
+//
+
+
+INTERNAL CDdeObject::Poke
+ (ATOM aItem, HANDLE hDdePoke)
+{
+ HRESULT hr;
+
+ intrDebugOut((DEB_ITRACE,"CDdeObject::Poke(%x)\n",this));
+
+ ATOM aTmpItem;
+
+ intrAssert(wIsValidAtom(aItem));
+
+ aTmpItem = wDupAtom (aItem);
+
+ intrAssert(wIsValidAtom(aTmpItem));
+
+ m_pDocChannel->hDdePoke = hDdePoke;
+
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_POKE,hDdePoke,aTmpItem);
+ hr = SendMsgAndWaitForReply (m_pDocChannel,
+ AA_POKE,
+ WM_DDE_POKE,
+ lp,
+ TRUE);
+ if (S_OK == hr)
+ {
+ intrDebugOut((DEB_ITRACE,"::Poke(%x) returning %x\n",this,hr));
+ return hr;
+ }
+
+ intrDebugOut((DEB_ITRACE,"::Poke(%x)wPostMessage failed %x\n",this,hr));
+ // Error case
+ if (aTmpItem)
+ GlobalDeleteAtom (aTmpItem);
+ wFreePokeData (m_pDocChannel, m_bOldSvr && m_aClass==aMSDraw);
+ hr = RPC_E_DDE_POST;
+ intrDebugOut((DEB_ITRACE,"::Poke(%x)wPostMessage returns %x\n",this,hr));
+ return hr;
+
+}
+
+INTERNAL CDdeObject::PostSysCommand
+ (LPDDE_CHANNEL pChannel,
+ LPCSTR szCmd,
+ BOOL fStdNew,
+ BOOL fWait)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::PostSysCommand(%x,szCmd=%s,fStdNew=%x,fWait=%x)\n",
+ this,
+ szCmd,
+ fStdNew,
+ fWait));
+
+ ULONG size;
+ WORD len;
+ LPSTR lpdata= NULL;
+ HANDLE hdata = NULL;
+ HRESULT hresult;
+
+
+ #define LN_FUDGE 16 // [],(), 3 * 3 (2 double quotes and comma)
+
+ len = strlen (szCmd);
+
+ // for StdNewDocument command add class name
+ if (fStdNew)
+ len += wAtomLenA (m_aClass);
+
+ // Now add the document length.
+ len += wAtomLenA (m_aTopic);
+
+ // now add the fudge factor for the Quotes etc.
+ len += LN_FUDGE;
+
+ // allocate the buffer and set the command.
+ if (!(hdata = GlobalAlloc (GMEM_DDESHARE, size = len)))
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+ if (!(lpdata = (LPSTR)GlobalLock (hdata))) {
+ Assert (0);
+ GlobalFree (hdata);
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ strcpy (lpdata, (LPSTR)"["); // [
+ strcat (lpdata, szCmd); // [StdCmd
+ if (strcmp (szCmd, "StdExit"))
+ {
+ strcat (lpdata, "(\""); // [StdCmd("
+
+ if (fStdNew)
+ {
+ len = strlen (lpdata);
+ GlobalGetAtomNameA (m_aClass, (LPSTR)lpdata + len, size-len);
+ // [StdCmd("class
+ strcat (lpdata, "\",\""); // [StdCmd("class","
+ }
+
+ len = strlen (lpdata);
+ // now get the topic name.
+ GlobalGetAtomNameA (m_aTopic, lpdata + len, (WORD)size - len);
+ // [StdCmd("class","topic
+ strcat (lpdata, "\")"); // [StdCmd("class","topic")
+ }
+ strcat (lpdata, "]");
+ Assert (strlen(lpdata) < size);
+ intrDebugOut((DEB_ITRACE,"::PostSysCommand(%x) hData(%s)\n",this,lpdata));
+ GlobalUnlock (hdata);
+
+ // return Execute (m_pSysChannel, hdata, /*fStdClose*/FALSE, fWait);
+ // REVIEW: this fixed bug 1856 (johannp)
+ // JasonFul - does it break something else?
+
+ hresult = Execute (m_pSysChannel,
+ hdata,
+ /*fStdClose*/FALSE,
+ fWait,
+ /*fDetectTerminate*/ TRUE);
+
+ intrDebugOut((DEB_ITRACE,"::PostSysCommand(%x) returns:%x\n",this,hresult));
+ return hresult;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::KeepData
+//
+// Synopsis: Given the DDEDATA structure from a WM_DDE_DATA message, extract
+// the real data and keep it till GetData or Save is done.
+//
+//
+// Effects:
+//
+// Arguments: [pChannel] --
+// [hDdeData] --
+//
+// Requires:
+//
+// Returns: E_OUTOFMEMORY or E_HANDLE if failure, NOERROR if success
+//
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-14-94 kevinro Commented
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CDdeObject::KeepData
+ (LPDDE_CHANNEL pChannel, HANDLE hDdeData)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::KeepData(%x)\n",this));
+
+ DDEDATA * lpDdeData = NULL;
+ HANDLE hData;
+ CLIPFORMAT cfFormat;
+
+
+
+ if (!(lpDdeData = (DDEDATA *) (GlobalLock (hDdeData))))
+ {
+ return E_OUTOFMEMORY;;
+ }
+
+
+ cfFormat = lpDdeData->cfFormat;
+ intrDebugOut((DEB_ITRACE,
+ "::KeepData(%x) Keeping cfFormat=%x\n",
+ this,
+ cfFormat));
+
+ GlobalUnlock (hDdeData);
+
+ // Possible Side effect of wHandleFromDdeData() is the freeing of hDdeData
+ if (!(hData = wHandleFromDdeData (hDdeData))
+ || !wIsValidHandle (hData, cfFormat) )
+ {
+ Assert(0);
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ if (cfFormat == g_cfNative) {
+ if (m_hNative)
+ GlobalFree (m_hNative);
+ // Keep the native data
+ RetErr (wTransferHandle (&m_hNative, &hData, cfFormat));
+ }
+ else if (cfFormat == CF_METAFILEPICT ||
+ cfFormat == CF_BITMAP ||
+ cfFormat == CF_DIB)
+ {
+ if (m_hPict)
+ wFreeData (m_hPict, m_cfPict, TRUE);
+ m_cfPict = cfFormat;
+ // Keep the presentation data
+ RetErr (wTransferHandle (&m_hPict, &hData, cfFormat));
+
+#ifdef OLD
+ // Remember size of picture so we can return
+ // a reasonable answer for GetExtent
+ if (cfFormat == CF_METAFILEPICT)
+ {
+ LPMETAFILEPICT lpMfp = (LPMETAFILEPICT) GlobalLock (m_hPict);
+ if (NULL==lpMfp)
+ return E_HANDLE;
+ UpdateExtent (m_cxContentExtent, lpMfp->xExt);
+ UpdateExtent (m_cyContentExtent, lpMfp->yExt);
+ GlobalUnlock (m_hPict);
+ }
+ else if (cfFormat==CF_BITMAP)
+ {
+ BITMAP bm;
+ if (0==GetObject (m_hPict, sizeof(BITMAP), (LPVOID) &bm))
+ return E_HANDLE;
+ UpdateExtent (m_cxContentExtent,
+ wPixelsToHiMetric (bm.bmWidth, giPpliX));
+ UpdateExtent (m_cyContentExtent,
+ wPixelsToHiMetric (bm.bmHeight,giPpliY));
+ }
+ else if (cfFormat==CF_DIB)
+ {
+ BITMAPINFOHEADER * pbminfohdr;
+ pbminfohdr = (BITMAPINFOHEADER *) GlobalLock (m_hPict);
+ if (NULL==pbminfohdr)
+ return E_HANDLE;
+ UpdateExtent (m_cxContentExtent,
+ wPixelsToHiMetric (pbminfohdr->biWidth, giPpliX));
+ UpdateExtent (m_cyContentExtent,
+ wPixelsToHiMetric (pbminfohdr->biHeight,giPpliY));
+ GlobalUnlock (m_hPict);
+ }
+#endif
+
+ }
+ else
+ {
+ if (m_hExtra)
+ wFreeData (m_hExtra, m_cfExtra, TRUE);
+ m_cfExtra = cfFormat;
+ wTransferHandle (&m_hExtra, &hData, cfFormat);
+ }
+
+ return NOERROR;
+}
+
+
+// IsFormatAvailable
+//
+// Does a temporary DDE_REQUEST to see if server supports a format
+// Returns NOERROR if format is available.
+//
+
+
+INTERNAL CDdeObject::IsFormatAvailable
+ (LPFORMATETC pformatetc)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::IsFormatAvailable(%x)\n",this));
+ ATOM aItem=(ATOM)0;
+ HRESULT hresult;
+ LPARAM lp = 0;
+
+ Puts ("DdeObject::IsFormatAvailable\n");
+
+ if (!HasValidLINDEX(pformatetc))
+ {
+ intrDebugOut((DEB_IERROR, "\t!HasValidLINDEX(pformatetc)\n"));
+ return(DV_E_LINDEX);
+ }
+
+ if (0==pformatetc->cfFormat)
+ return ResultFromScode (E_INVALIDARG);
+
+ if (pformatetc->dwAspect & DVASPECT_ICON)
+ {
+ if (pformatetc->cfFormat==CF_METAFILEPICT)
+ {
+ // This is always available. we get it from the exe.
+ return NOERROR;
+ }
+ // an icon must be a metafile
+ return ResultFromScode (S_FALSE);
+ }
+ if (!(pformatetc->dwAspect & (DVASPECT_CONTENT | DVASPECT_DOCPRINT)))
+ {
+ // 1.0 does not support Thumb.
+ return ReportResult(0, S_FALSE, 0, 0);
+ }
+
+ if (NOERROR == (hresult=m_ConnectionTable.Lookup (pformatetc->cfFormat, NULL)))
+ {
+ // We already got a call to DataObject::Advise on this format,
+ // so it must be available.
+ Puts ("DataObject::Advise had been done on this format.\n");
+ return NOERROR;
+ }
+ else
+ {
+ // Lookup () didn't find this format.
+ ErrZ (GetScode(hresult)==S_FALSE);
+ }
+
+ intrAssert(wIsValidAtom(m_aItem));
+ aItem = wDupAtom (m_aItem);
+ intrAssert(wIsValidAtom(aItem));
+
+ lp = MAKE_DDE_LPARAM (WM_DDE_REQUEST,pformatetc->cfFormat,aItem);
+ if(NOERROR==SendMsgAndWaitForReply (m_pDocChannel,
+ AA_REQUESTAVAILABLE,
+ WM_DDE_REQUEST,
+ lp,
+ TRUE))
+ return NOERROR;
+
+ // Last ditch effort: Advise
+ if (NOERROR== AdviseOn (pformatetc->cfFormat, ON_SAVE))
+ {
+ // We cannot Unadvise because an OLE 1.0 bug
+ // terminates DDE advise connections for ALL formats.
+ //// UnAdviseOn (pformatetc->cfFormat, ON_SAVE);
+ // Instead, just remember we did this advise.
+ m_ConnectionTable.Add (0, pformatetc->cfFormat, ADVFDDE_ONSAVE);
+ return NOERROR;
+ }
+ return ResultFromScode (S_FALSE);
+
+errRtn:
+ AssertSz (0, "Error in CDdeObject::IsFormatAvailable");
+ Puth (hresult); Putn();
+ if (aItem)
+ GlobalDeleteAtom (aItem);
+
+ return hresult;
+}
+
+
+
+
+INTERNAL CDdeObject::ChangeTopic
+ (LPSTR lpszTopic)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::ChangeTopic(%x,lpszTopic=%s)\n",this,lpszTopic));
+ HRESULT hresult;
+ LPMONIKER pmkFile=NULL;
+ LPMONIKER pmkItem=NULL;
+ LPMONIKER pmkComp=NULL;
+ LPMONIKER pmkNewName=NULL;
+ ATOM aTopic = wGlobalAddAtomA (lpszTopic);
+ intrAssert(wIsValidAtom(aTopic));
+
+ // Yet-Another-Excel-Hack
+ // Excel 4.0 sends StdDocumentName every time it saves,
+ // whether or not the file name has actually changed. Bug 2957
+ if (aTopic != m_aTopic)
+ {
+ ErrRtnH (CreateOle1FileMoniker (wAtomName(aTopic), m_clsid, &pmkFile));
+ if (m_aItem)
+ {
+ intrAssert (wIsValidAtom (m_aItem));
+ ErrRtnH (CreateItemMoniker (OLESTR("!"), wAtomName (m_aItem), &pmkItem));
+ ErrRtnH (CreateGenericComposite (pmkFile, pmkItem, &pmkComp));
+ (pmkNewName = pmkComp)->AddRef();
+ }
+ else
+ {
+ (pmkNewName = pmkFile)->AddRef();
+ }
+ RetZS (m_pOleAdvHolder, E_OUTOFMEMORY);
+ RetZ (pmkNewName);
+ ErrRtnH (m_pOleAdvHolder->SendOnRename (pmkNewName));
+ }
+ SetTopic (aTopic);
+ hresult = NOERROR;
+
+ errRtn:
+ if (pmkFile)
+ pmkFile->Release();
+ if (pmkItem)
+ pmkItem->Release();
+ if (pmkComp)
+ pmkComp->Release();
+ if (pmkNewName)
+ pmkNewName->Release();
+ return hresult;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::ChangeItem
+//
+// Synopsis: Changes the m_aItem atom, using an Ansi string
+//
+// Effects:
+//
+// Arguments: [szItem] -- Ansi string for the new item
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(void) CDdeObject::ChangeItem
+ (LPSTR szItem)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::ChangeItem(%x,szItem=%s)\n",this,szItem));
+ intrAssert(wIsValidAtom(m_aItem));
+ if (m_aItem)
+ GlobalDeleteAtom (m_aItem);
+ m_aItem = wGlobalAddAtomA (szItem);
+ intrAssert(wIsValidAtom(m_aItem));
+}
+
+
+
+
+INTERNAL CDdeObject::DeclareVisibility
+ (BOOL f,
+ BOOL fCallOnShowIfNec)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::DelcareVisibility(%x)\n",this));
+ if (f)
+ m_fWasEverVisible = TRUE;
+ if ((f && (!m_fVisible || !m_fCalledOnShow)) ||
+ (!f && m_fVisible))
+ {
+ if (m_pOleClientSite && fCallOnShowIfNec && m_clsid != CLSID_Package)
+ {
+ m_pOleClientSite->OnShowWindow (f);
+ m_fCalledOnShow = f;
+ }
+ m_fVisible = f;
+ }
+ return NOERROR;
+}
+
+
+
+INTERNAL CDdeObject::Update
+ (BOOL fRequirePresentation)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::Update(%x,fRequiredPresentation=%x)\n",
+ this,
+ fRequirePresentation));
+ // Get latest data
+ // OLE 1.0 spec says servers must supply metafile format.
+ HRESULT hresult = RequestData (m_cfPict ? m_cfPict : CF_METAFILEPICT);
+ if (fRequirePresentation && hresult!=NOERROR)
+ return hresult;
+ RetErr (RequestData (g_cfNative));
+ SendOnDataChange (ON_CHANGE);
+ return NOERROR;
+}
+
+
+
+INTERNAL CDdeObject::Save
+ (LPSTORAGE pstg)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::Save(%x)\n",this));
+ VDATEIFACE (pstg);
+#ifdef OLE1INTEROP
+ RetErr (StSave10NativeData (pstg, m_hNative, m_fOle1interop));
+#else
+ RetErr (StSave10NativeData (pstg, m_hNative, FALSE));
+#endif
+ if (m_aItem)
+ {
+ intrAssert(wIsValidAtom(m_aItem));
+ RetErr (StSave10ItemName (pstg, wAtomNameA (m_aItem)));
+ }
+ RetErr (wWriteFmtUserType (pstg, m_clsid));
+ return NOERROR;
+}
+
+/*
+ * IMPLEMENTATION of CUnknownImpl
+ *
+ */
+
+
+
+STDMETHODIMP_(ULONG) NC(CDdeObject,CUnknownImpl)::AddRef()
+{
+ ChkD(m_pDdeObject);
+
+ return InterlockedAddRef(&(m_pDdeObject->m_refs));
+}
+
+
+STDMETHODIMP_(ULONG) NC(CDdeObject,CUnknownImpl)::Release()
+{
+ ChkD(m_pDdeObject);
+ Assert (m_pDdeObject->m_refs != 0);
+ ULONG ul;
+
+ if ((ul=InterlockedRelease(&(m_pDdeObject->m_refs))) == 0) {
+ m_pDdeObject->m_ProxyMgr.Disconnect();
+
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ // the object can not be delete if guarded
+ // which is the case if DelayDelete state is 'DelayIt'
+ //
+ if (m_pDdeObject->_DelayDelete == DelayIt)
+ {
+ // set the state to ReadyToDelete and
+ // the object will be deleted at the
+ // UnGuard call
+ m_pDdeObject->_DelayDelete = ReadyToDelete;
+ intrDebugOut((DEB_IWARN ,"Can not release CDdeObject\n"));
+ return 1;
+ }
+#endif //_CHICAGO_
+ delete m_pDdeObject;
+ return 0;
+ }
+ return ul;
+}
+
+
+
+
+STDMETHODIMP NC(CDdeObject,CUnknownImpl)::QueryInterface(REFIID iid, LPLPVOID ppv)
+{
+ ChkD(m_pDdeObject);
+ if (iid == IID_IUnknown) {
+ *ppv = (void FAR *)&m_pDdeObject->m_Unknown;
+ AddRef();
+ return NOERROR;
+ }
+ else if (iid == IID_IOleObject)
+ *ppv = (void FAR *) &(m_pDdeObject->m_Ole);
+ else if (iid == IID_IDataObject)
+ *ppv = (void FAR *) &(m_pDdeObject->m_Data);
+ else if (iid == IID_IPersist || iid == IID_IPersistStorage)
+ *ppv = (void FAR *) &(m_pDdeObject->m_PersistStg);
+ else if (iid == IID_IProxyManager)
+ *ppv = (void FAR *) &(m_pDdeObject->m_ProxyMgr);
+ else if (iid == IID_IOleItemContainer
+ || iid == IID_IOleContainer
+ || iid == IID_IParseDisplayName)
+ *ppv = (void FAR *) &(m_pDdeObject->m_OleItemContainer);
+ else {
+ Puts ("INTERFACE NOT FOUND \r\n");
+ *ppv = NULL;
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+
+ m_pDdeObject->m_pUnkOuter->AddRef();
+ return NOERROR;
+}
+
+
+// implementations of IRpcStubBuffer methods
+STDUNKIMPL_FORDERIVED(DdeObject, RpcStubBufferImpl)
+
+
+
+STDMETHODIMP NC(CDdeObject,CRpcStubBufferImpl)::Connect
+ (IUnknown * pUnkServer )
+{
+ // do nothing
+ return S_OK;
+}
+
+STDMETHODIMP_(void) NC(CDdeObject,CRpcStubBufferImpl)::Disconnect
+ ()
+{
+ // do nothing
+}
+
+STDMETHODIMP_(IRpcStubBuffer*) NC(CDdeObject,CRpcStubBufferImpl)::IsIIDSupported
+ (REFIID riid)
+{
+ // do nothing
+ return NULL;
+}
+
+
+STDMETHODIMP_(ULONG) NC(CDdeObject,CRpcStubBufferImpl)::CountRefs
+ ()
+{
+ // do nothing
+ return 1;
+}
+
+STDMETHODIMP NC(CDdeObject,CRpcStubBufferImpl)::DebugServerQueryInterface
+ (void ** ppv )
+{
+ // do nothing
+ *ppv = NULL;
+ return S_OK;
+}
+
+
+STDMETHODIMP_(void) NC(CDdeObject,CRpcStubBufferImpl)::DebugServerRelease
+ (void * pv)
+{
+ // do nothing
+}
+
+STDMETHODIMP NC(CDdeObject,CRpcStubBufferImpl)::Invoke
+ (RPCOLEMESSAGE *_prpcmsg, IRpcChannelBuffer *_pRpcChannelBuffer)
+{
+ PDISPATCHDATA pdispdata = (PDISPATCHDATA) _prpcmsg->Buffer;
+ return DispatchCall( pdispdata );
+}
+
+
+// implementation of IRpcChannelBuffer methods for DDE_CHANNEL
+//
+
+STDMETHODIMP DDE_CHANNEL::QueryInterface ( REFIID riid, LPVOID * ppvObj)
+{
+ *ppvObj = this;
+ return S_OK;
+}
+STDMETHODIMP_(ULONG) DDE_CHANNEL::AddRef ()
+{
+ return 1;
+}
+STDMETHODIMP_(ULONG) DDE_CHANNEL::Release ()
+{
+ return 1;
+}
+
+// Provided IRpcChannelBuffer methods (for callback methods side)
+HRESULT DDE_CHANNEL::GetBuffer(
+/* [in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+/* [in] */ REFIID riid)
+{
+ return S_OK;
+}
+
+HRESULT DDE_CHANNEL::SendReceive(
+/* [out][in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+/* [out] */ ULONG __RPC_FAR *pStatus)
+{
+ return S_OK;
+}
+
+HRESULT DDE_CHANNEL::FreeBuffer(
+/* [in] */ RPCOLEMESSAGE __RPC_FAR *pMessage)
+{
+ return S_OK;
+}
+
+HRESULT DDE_CHANNEL::GetDestCtx(
+/* [out] */ DWORD __RPC_FAR *pdwDestContext,
+/* [out] */ void __RPC_FAR *__RPC_FAR *ppvDestContext)
+{
+ *pdwDestContext = MSHCTX_LOCAL;
+ return S_OK;
+}
+
+HRESULT DDE_CHANNEL::IsConnected( void)
+{
+ return S_OK;
+}
+
+
+
+
diff --git a/private/ole32/com/dde/client/ddeproxy.h b/private/ole32/com/dde/client/ddeproxy.h
new file mode 100644
index 000000000..651f896df
--- /dev/null
+++ b/private/ole32/com/dde/client/ddeproxy.h
@@ -0,0 +1,730 @@
+// ddeproxy.h
+//
+// Used by ddeproxy.cpp ddeDO.cpp ddeOO.cpp
+//
+// Author: Jason Fuller jasonful 24-July-1992
+//
+// Modified: Brian Chapman bchapman Nov 1995
+// - Removed declarations of wAllocDdeChannel() and wGetRequestResponse()
+// because they were not used or even defined anywhere.
+// - Fixed the indention of the declarations of the "worker" routines
+// section.
+//
+//
+#ifndef fDdeProxy_h
+#define fDdeProxy_h
+
+//
+// One of the oleint.h routines redefines GlobalAlloc and friends
+// to perform some memory tracking functions.
+//
+// This doesn't work in these files, since the tracking functions
+// add tail checking, and size to the data structures. GlobalSize
+// is a common function to use to determine how much data to
+// serialize, plus it turns out that the other side of a DDE
+// connection will often be the caller to free the memory.
+//
+// Therefore, OLE_DDE_NO_GLOBAL_TRACKING is used to disable this in the
+// global header file ih\memapi.hxx. Check to insure this
+// flag is set on the compile line
+//
+#if !defined(OLE_DDE_NO_GLOBAL_TRACKING)
+error OLE_DDE_OLE_DDE_NO_GLOBAL_TRACKING must be defined to build this directory
+#endif
+
+
+#include <ole2int.h>
+#include <callctrl.hxx>
+#include <ddeint.h>
+#include <dde.h>
+#include <olerem.h>
+#include <ole1cls.h>
+#include <limits.h>
+// For fDdeCodeInOle2Dll flag
+#include <ddeatoms.h>
+#include <ddepack.h>
+#include <ddedebug.h>
+
+#ifdef OLE_DEBUG_EXT
+#include <ntsdexts.h>
+#endif OLE_DEBUG_EXT
+
+#include "ddechc.hxx"
+#define LPCALLINFO LPVOID
+#include "ddeerr.h"
+#include "cnct_tbl.h"
+
+#define MAX_STR 256
+
+// number of .01 mm per inch
+#define HIMETRIC_PER_INCH 2540
+
+//#define fDebugOutput
+
+// callback notifications
+#define ON_CHANGE 0
+#define ON_SAVE 1
+#define ON_CLOSE 2
+#define ON_RENAME 3
+
+// AwaitAck values
+#define AA_NONE 0
+#define AA_REQUEST 1
+#define AA_ADVISE 2
+#define AA_POKE 3
+#define AA_EXECUTE 4
+#define AA_UNADVISE 5
+#define AA_INITIATE 6
+#define AA_TERMINATE 7
+// A DDE_REQUEST to see if a format is available, not to keep the data.
+#define AA_REQUESTAVAILABLE 8
+
+// Bits for Positive WM_DDE_ACK
+//#define POSITIVE_ACK 0x8000
+//#define NEGATIVE_ACK 0x0000
+
+#define DDE_CHANNEL_DELETED 0xffffffff
+
+typedef DWORD CHK;
+const DWORD chkDdeObj = 0xab01; // magic cookie
+
+
+class DDE_CHANNEL : public CPrivAlloc, public IRpcChannelBuffer2 {
+
+public:
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) ( REFIID riid, LPVOID * ppvObj);
+ STDMETHOD_(ULONG,AddRef) ();
+ STDMETHOD_(ULONG,Release) ();
+
+ // Provided IRpcChannelBuffer methods (for server side)
+ virtual HRESULT __stdcall GetBuffer(
+ /* [in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+ /* [in] */ REFIID riid);
+
+ virtual HRESULT __stdcall SendReceive(
+ /* [out][in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+ /* [out] */ ULONG __RPC_FAR *pStatus);
+
+ virtual HRESULT __stdcall FreeBuffer(
+ /* [in] */ RPCOLEMESSAGE __RPC_FAR *pMessage);
+
+ virtual HRESULT __stdcall GetDestCtx(
+ /* [out] */ DWORD __RPC_FAR *pdwDestContext,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvDestContext);
+
+ virtual HRESULT __stdcall IsConnected( void);
+
+
+ // Provided IRpcChannelBuffer2 methods (for client side)
+ virtual HRESULT __stdcall SendReceive2(
+ /* [out][in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+ /* [out] */ ULONG __RPC_FAR *pStatus);
+
+ void SetCallState(SERVERCALLEX ServerCall, HRESULT hr = S_OK);
+
+ ULONG AddReference()
+ {
+ return ++m_cRefs;
+ }
+ ULONG ReleaseReference()
+ {
+ if (--m_cRefs == 0)
+ {
+ delete this;
+ return(0);
+ }
+ return(m_cRefs);
+ }
+
+ ULONG m_cRefs;
+ HWND hwndCli;
+ HWND hwndSvr;
+ BOOL bTerminating;
+ int iExtraTerms;
+ WORD wTimer;
+ DWORD dwStartTickCount;
+ WORD msgFirst;
+ WORD msgLast;
+ HWND msghwnd; //
+ BOOL fRejected; // because fBusy flag set in DDE_ACK
+ WORD wMsg;
+ LONG lParam;
+ int iAwaitAck;
+ HRESULT hres;
+ HANDLE hopt; // Memory blocks I may have to free for DDE_ADVISE
+ HANDLE hDdePoke; // for DDE_POKE
+ HANDLE hCommands; // for DDE_EXECUTE
+ WORD wChannelDeleted;
+ PDDECALLDATA pCD;
+ SERVERCALLEX CallState;
+} ;
+
+
+#define Channel_InModalloop 1
+#define Channel_DeleteNow 2
+
+
+typedef DDE_CHANNEL * LPDDE_CHANNEL;
+extern BOOL bWndClassesRegistered;
+
+#define hinstSO g_hmodOLE2
+extern HMODULE g_hmodOLE2;
+
+extern INTERNAL_(BOOL) wRegisterClasses (void);
+
+#ifndef _MAC
+extern CLIPFORMAT g_cfNative;
+extern CLIPFORMAT g_cfBinary;
+#endif
+
+#ifdef _CHICAGO_
+//Note:POSTPPC
+//
+// DelayDelete is used to delay deleting the CDdeObject
+// Guard will set it to DelayIt
+// UnGuard will reset it to NoDelay or delete the object
+// if state is ReadyToDelete
+//
+typedef enum
+{
+ NoDelay = 0, // normal state
+ DelayIt = 1, // object is protected and deleting will be delayed
+ ReadyToDelete = 2 // object was is DelayIt state and can be deleted
+} DelayDelete;
+
+#endif // _CHICAGO_
+
+/*
+ * Definition of CDdeObject
+ *
+ */
+class CMsgFilterInfo;
+class CDdeObject;
+
+class CDdeObject : public CPrivAlloc
+{
+public:
+
+ static INTERNAL_(LPUNKNOWN) Create (IUnknown * pUnkOuter,
+ REFCLSID clsidClass,
+ ULONG ulObjType = OT_EMBEDDED,
+ ATOM aTopic = NULL,
+ LPOLESTR szItem = NULL,
+ CDdeObject * * ppdde = NULL,
+ BOOL fAllowNullClsid = FALSE);
+
+ INTERNAL_(void) OnInitAck (LPDDE_CHANNEL pChannel, HWND hwndSvr);
+ INTERNAL_(BOOL) OnAck (LPDDE_CHANNEL pChannel, LONG lParam);
+ INTERNAL_(void) OnTimer (LPDDE_CHANNEL pChannel);
+ INTERNAL OnData (LPDDE_CHANNEL pChannel, HANDLE hData,ATOM aItem);
+ INTERNAL OnDataAvailable (LPDDE_CHANNEL pChannel, HANDLE hData,ATOM aItem);
+ INTERNAL OnTerminate (LPDDE_CHANNEL pChannel, HWND hwndPost);
+
+ INTERNAL_(LPDDE_CHANNEL) GetSysChannel(void)
+ { return m_pSysChannel; }
+
+ INTERNAL_(LPDDE_CHANNEL) GetDocChannel(void)
+ { return m_pDocChannel; }
+
+ INTERNAL_(BOOL) AllocDdeChannel(LPDDE_CHANNEL * lpChannel, BOOL fSysWndProc);
+ INTERNAL_(BOOL) InitSysConv (void);
+ INTERNAL_(void) SetTopic (ATOM aTopic);
+
+ INTERNAL SendOnDataChange (int iAdvOpt);
+ INTERNAL OleCallBack (int iAdvOpt,LPDDE_CHANNEL pChannel);
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ INTERNAL_(void) Guard()
+ {
+ intrDebugOut((DEB_IWARN ,"CDdeObject: %x DelayDelete is set to 'DelayIt'\n", this));
+ _DelayDelete = DelayIt;
+ }
+ INTERNAL_(BOOL) UnGuard()
+ {
+ if (_DelayDelete == ReadyToDelete)
+ {
+ intrDebugOut((DEB_IWARN ,"CDdeObject: %x DelayDelete it set 'ReadyToDelete'\n", this));
+ delete this;
+ intrDebugOut((DEB_IWARN ,"CDdeObject: %x was deleted\n", this));
+ return TRUE;
+ }
+ else
+ {
+ intrDebugOut((DEB_IWARN ,"CDdeObject: %x DelayDelete set to 'NoDelay'\n", this));
+ _DelayDelete = NoDelay;
+ }
+
+ return FALSE;
+ }
+#endif // _CHICAGO_
+
+ BOOL m_fDoingSendOnDataChange;
+ ULONG m_cRefCount;
+
+private:
+
+ CDdeObject (IUnknown * pUnkOuter);
+ ~CDdeObject (void);
+ INTERNAL TermConv (LPDDE_CHANNEL pChannel,
+ BOOL fWait=TRUE);
+ INTERNAL_(void) DeleteChannel (LPDDE_CHANNEL pChannel);
+ INTERNAL_(BOOL) LaunchApp (void);
+ INTERNAL MaybeUnlaunchApp (void);
+ INTERNAL UnlaunchApp (void);
+ INTERNAL Execute (LPDDE_CHANNEL pChannel,
+ HANDLE hdata,
+ BOOL fStdCloseDoc=FALSE,
+ BOOL fWait=TRUE,
+ BOOL fDetectTerminate = TRUE);
+ INTERNAL Advise (void);
+ INTERNAL AdviseOn (CLIPFORMAT cfFormat,
+ int iAdvOn);
+ INTERNAL UnAdviseOn (CLIPFORMAT cfFormat,
+ int iAdvOn);
+ INTERNAL Poke (ATOM aItem, HANDLE hDdePoke);
+ INTERNAL PostSysCommand (LPDDE_CHANNEL pChannel,
+ LPCSTR szCmd,
+ BOOL bStdNew=FALSE,
+ BOOL fWait=TRUE);
+
+#ifdef _CHICAGO_
+ //POSTPPC
+ INTERNAL_(BOOL) CanMakeOutCall(LPDDE_CHANNEL pChannel);
+#endif
+
+ INTERNAL SendMsgAndWaitForReply (LPDDE_CHANNEL pChannel,
+ int iAwaitAck,
+ WORD wMsg,
+ long lparam,
+ BOOL fFreeOnError,
+ BOOL fStdCloseDoc = FALSE,
+ BOOL fDetectTerminate = TRUE,
+ BOOL fWait = TRUE);
+ INTERNAL KeepData (LPDDE_CHANNEL pChannel, HANDLE hDdeData);
+ INTERNAL ChangeTopic (LPSTR lpszTopic);
+ INTERNAL_(void) ChangeItem (LPSTR lpszItem);
+ INTERNAL IsFormatAvailable (LPFORMATETC);
+ INTERNAL_(BOOL) CanCallBack(LPINT);
+ INTERNAL RequestData (CLIPFORMAT);
+ INTERNAL SetTargetDevice (const DVTARGETDEVICE *);
+ INTERNAL DocumentLevelConnect (LPBINDCTX pbc);
+ INTERNAL SendOnClose (void);
+ INTERNAL UpdateAdviseCounts (CLIPFORMAT cf,
+ int iAdvOn,
+ signed int cDelta);
+ INTERNAL DeclareVisibility (BOOL fVisible,
+ BOOL fCallOnShowIfNec=TRUE);
+ INTERNAL Save (LPSTORAGE);
+ INTERNAL Update (BOOL fRequirePresentation);
+
+implementations:
+
+ STDUNKDECL(CDdeObject,DdeObject)
+ STDDEBDECL(CDdeObject,DdeObject)
+
+
+ implement COleObjectImpl : IOleObject
+ {
+ public:
+ COleObjectImpl (CDdeObject * pDdeObject)
+ { m_pDdeObject = pDdeObject; }
+
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) ( REFIID riid, LPVOID * ppvObj);
+ STDMETHOD_(ULONG,AddRef) ();
+ STDMETHOD_(ULONG,Release) ();
+
+ // *** IOleObject methods ***
+ STDMETHOD(SetClientSite) ( LPOLECLIENTSITE pClientSite);
+ STDMETHOD(GetClientSite) ( LPOLECLIENTSITE * ppClientSite);
+ STDMETHOD(SetHostNames) ( LPCOLESTR szContainerApp, LPCOLESTR szContainerObj);
+ STDMETHOD(Close) ( DWORD reserved);
+ STDMETHOD(SetMoniker) ( DWORD dwWhichMoniker, LPMONIKER pmk);
+ STDMETHOD(GetMoniker) ( DWORD dwAssign, DWORD dwWhichMoniker,LPMONIKER * ppmk);
+ STDMETHOD(InitFromData) ( LPDATAOBJECT pDataObject,BOOL fCreation,DWORD dwReserved);
+ STDMETHOD(GetClipboardData) ( DWORD dwReserved,LPDATAOBJECT * ppDataObject);
+
+ STDMETHOD(DoVerb) ( LONG iVerb,
+ LPMSG lpmsg,
+ LPOLECLIENTSITE pActiveSite,
+ LONG lindex,
+ HWND hwndParent,
+ const RECT * lprcPosRect);
+
+ STDMETHOD(EnumVerbs) ( IEnumOLEVERB * * ppenumOleVerb);
+ STDMETHOD(Update) ();
+ STDMETHOD(IsUpToDate) ();
+ STDMETHOD(GetUserClassID) ( CLSID * pClsid);
+ STDMETHOD(GetUserType) ( DWORD dwFormOfType, LPOLESTR * pszUserType);
+ STDMETHOD(SetExtent) ( DWORD dwDrawAspect, LPSIZEL lpsizel);
+ STDMETHOD(GetExtent) ( DWORD dwDrawAspect, LPSIZEL lpsizel);
+ STDMETHOD(Advise)( IAdviseSink * pAdvSink, DWORD * pdwConnection) ;
+ STDMETHOD(Unadvise) ( DWORD dwConnection);
+ STDMETHOD(EnumAdvise) ( LPENUMSTATDATA * ppenumAdvise);
+ STDMETHOD(GetMiscStatus) ( DWORD dwAspect, DWORD * pdwStatus);
+ STDMETHOD(SetColorScheme) ( LPLOGPALETTE lpLogpal);
+
+ private:
+ CDdeObject * m_pDdeObject;
+ };
+
+
+ implement CDataObjectImpl : IDataObject
+ {
+ public:
+ CDataObjectImpl (CDdeObject * pDdeObject)
+ { m_pDdeObject = pDdeObject; }
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) ( REFIID riid, LPVOID * ppvObj);
+ STDMETHOD_(ULONG,AddRef) () ;
+ STDMETHOD_(ULONG,Release) ();
+
+ STDMETHOD(GetData) ( LPFORMATETC pformatetcIn,LPSTGMEDIUM pmedium );
+ STDMETHOD(GetDataHere) ( LPFORMATETC pformatetc,LPSTGMEDIUM pmedium );
+ STDMETHOD(QueryGetData) ( LPFORMATETC pformatetc );
+ STDMETHOD(GetCanonicalFormatEtc) ( LPFORMATETC pformatetc,LPFORMATETC pformatetcOut);
+ STDMETHOD(SetData) ( LPFORMATETC pformatetc, STGMEDIUM * pmedium, BOOL fRelease);
+ STDMETHOD(EnumFormatEtc) ( DWORD dwDirection, LPENUMFORMATETC * ppenumFormatEtc);
+ STDMETHOD(DAdvise) ( FORMATETC * pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD * pdwConnection) ;
+ STDMETHOD(DUnadvise) ( DWORD dwConnection) ;
+ STDMETHOD(EnumDAdvise) ( LPENUMSTATDATA * ppenumAdvise) ;
+
+ private:
+ CDdeObject * m_pDdeObject;
+ };
+
+
+ implement CPersistStgImpl : IPersistStorage
+ {
+ public:
+ CPersistStgImpl (CDdeObject * pDdeObject)
+ { m_pDdeObject = pDdeObject; }
+
+ STDMETHOD(QueryInterface) ( REFIID iid, LPVOID * ppvObj);
+ STDMETHOD_(ULONG,AddRef) ();
+ STDMETHOD_(ULONG,Release) ();
+ STDMETHOD(GetClassID) ( LPCLSID pClassID);
+ STDMETHOD(IsDirty) (void);
+ STDMETHOD(InitNew) ( LPSTORAGE pstg);
+ STDMETHOD(Load) ( LPSTORAGE pstg);
+ STDMETHOD(Save) ( LPSTORAGE pstgSave, BOOL fSameAsLoad);
+ STDMETHOD(SaveCompleted) ( LPSTORAGE pstgNew);
+ STDMETHOD(HandsOffStorage) (void);
+
+ private:
+ CDdeObject * m_pDdeObject;
+ };
+
+
+ implement CProxyManagerImpl : IProxyManager
+ {
+ public:
+ CProxyManagerImpl (CDdeObject * pDdeObject)
+ { m_pDdeObject = pDdeObject; }
+
+ STDMETHOD(QueryInterface) ( REFIID iid, LPVOID * ppvObj);
+ STDMETHOD_(ULONG,AddRef) ();
+ STDMETHOD_(ULONG,Release) ();
+
+ STDMETHOD(CreateServer)(REFCLSID rclsid, DWORD clsctx, void *pv);
+ STDMETHOD_(BOOL, IsConnected)(void);
+ STDMETHOD(LockConnection)(BOOL fLock, BOOL fLastUnlockReleases);
+ STDMETHOD_(void, Disconnect)();
+ STDMETHOD(CreateServerWithHandler)(REFCLSID rclsid, DWORD clsctx, void *pv,
+ REFCLSID rclsidHandler, IID iidSrv, void **ppv,
+ IID iidClnt, void *pClientSiteInterface);
+
+ STDMETHOD(Connect)(GUID oid, REFCLSID rclsid);
+ STDMETHOD(EstablishIID)(REFIID iid, LPVOID FAR* ppv);
+
+ private:
+ CDdeObject * m_pDdeObject;
+ };
+
+
+ implement COleItemContainerImpl : IOleItemContainer
+ {
+ public:
+ COleItemContainerImpl (CDdeObject * pDdeObject)
+ { m_pDdeObject = pDdeObject; }
+
+ STDMETHOD(QueryInterface) ( REFIID iid, LPVOID * ppvObj);
+ STDMETHOD_(ULONG,AddRef) ();
+ STDMETHOD_(ULONG,Release) ();
+
+ // IParseDisplayName method
+ STDMETHOD(ParseDisplayName) ( LPBC pbc,
+ LPOLESTR lpszDisplayName,
+ ULONG * pchEaten,
+ LPMONIKER * ppmkOut) ;
+
+ // IOleContainer methods
+ STDMETHOD(EnumObjects) ( DWORD grfFlags,LPENUMUNKNOWN * ppenumUnk);
+
+ STDMETHOD(LockContainer) (BOOL fLock);
+
+ // IOleItemContainer methods
+ STDMETHOD(GetObject) ( LPOLESTR lpszItem,
+ DWORD dwSpeedNeeded,
+ LPBINDCTX pbc,
+ REFIID riid,
+ LPVOID * ppvObject) ;
+ STDMETHOD(GetObjectStorage) ( LPOLESTR lpszItem,
+ LPBINDCTX pbc,
+ REFIID riid,
+ LPVOID * ppvStorage) ;
+
+ STDMETHOD(IsRunning) ( LPOLESTR lpszItem) ;
+
+ private:
+ CDdeObject * m_pDdeObject;
+ };
+
+
+ implement CRpcStubBufferImpl : public IRpcStubBuffer
+ {
+ public:
+ CRpcStubBufferImpl (CDdeObject * pDdeObject)
+ { m_pDdeObject = pDdeObject; }
+
+ STDMETHOD(QueryInterface) ( REFIID iid, LPVOID * ppvObj);
+ STDMETHOD_(ULONG,AddRef) ();
+ STDMETHOD_(ULONG,Release) ();
+ STDMETHOD(Connect)(
+ /* [in] */ IUnknown *pUnkServer);
+
+ STDMETHOD_(void,Disconnect)( void);
+
+ STDMETHOD(Invoke)(
+ /* [in] */ RPCOLEMESSAGE *_prpcmsg,
+ /* [in] */ IRpcChannelBuffer *_pRpcChannelBuffer);
+
+ STDMETHOD_(IRpcStubBuffer *,IsIIDSupported)(
+ /* [in] */ REFIID riid);
+
+ STDMETHOD_(ULONG,CountRefs)( void);
+
+ STDMETHOD(DebugServerQueryInterface)(
+ void * *ppv);
+
+ STDMETHOD_(void,DebugServerRelease)(
+ void *pv);
+
+ private:
+ CDdeObject * m_pDdeObject;
+ };
+
+ DECLARE_NC(CDdeObject, COleObjectImpl)
+ DECLARE_NC(CDdeObject, CDataObjectImpl)
+ DECLARE_NC(CDdeObject, CPersistStgImpl)
+ DECLARE_NC(CDdeObject, CProxyManagerImpl)
+ DECLARE_NC(CDdeObject, COleItemContainerImpl)
+ DECLARE_NC(CDdeObject, CRpcStubBufferImpl)
+
+ COleObjectImpl m_Ole;
+ CDataObjectImpl m_Data;
+ CPersistStgImpl m_PersistStg;
+ CProxyManagerImpl m_ProxyMgr;
+ COleItemContainerImpl m_OleItemContainer;
+ CRpcStubBufferImpl m_RpcStubBuffer;
+
+shared_state:
+ ULONG m_refs;
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ DelayDelete _DelayDelete;
+#endif // _CHICAGO_
+ ULONG m_ulObjType;
+ CLSID m_clsid;
+ ATOM m_aClass;
+ ATOM m_aExeName;
+ ATOM m_aTopic;
+ ATOM m_aItem;
+ BOOL m_bRunning;
+ IUnknown * m_pUnkOuter;
+ IOleClientSite * m_pOleClientSite;
+ LPSTORAGE m_pstg;
+ BOOL m_bInitNew;
+ BOOL m_bOldSvr;
+ HANDLE m_hNative;
+ HANDLE m_hPict;
+ HANDLE m_hExtra;
+ CLIPFORMAT m_cfPict;
+ CLIPFORMAT m_cfExtra;
+
+ BOOL m_fDidSendOnClose;
+ BOOL m_fNoStdCloseDoc;
+ BOOL m_fDidStdCloseDoc;
+ BOOL m_fDidStdOpenDoc;
+ BOOL m_fDidGetObject;
+ BOOL m_fDidLaunchApp;
+ BOOL m_fUpdateOnSave;
+ BOOL m_fGotCloseData;
+
+#ifdef OLE1INTEROP
+ BOOL m_fOle1interop;
+#endif
+
+ // Invisible update stuff
+ ULONG m_cLocks; // PM::LockConnection lock count (init 1)
+ BOOL m_fVisible; // is server visible (as best we know)?
+ BOOL m_fWasEverVisible;
+ BOOL m_fCalledOnShow; // Did we call IOleClientSite::OnShow
+
+ CHK m_chk;
+ DVTARGETDEVICE * m_ptd;
+
+ // m_iAdvClose and m_iAdvSave are counts (1 or 2) of the number of formats
+ // that have advise connections of a given type (Save or Close)
+ int m_iAdvClose;
+ int m_iAdvSave;
+ int m_iAdvChange;
+
+ BOOL m_fDidAdvNative;
+
+ // Extent info
+#ifdef OLD
+ long m_cxContentExtent;
+ long m_cyContentExtent;
+#endif
+
+ // terminate info - only used to detect a premature WM_DDE_TERMINATE
+ WORD m_wTerminate;
+
+ IDataAdviseHolder * m_pDataAdvHolder;
+ IOleAdviseHolder * m_pOleAdvHolder;
+ CDdeConnectionTable m_ConnectionTable;
+
+
+ // DDE window related stuff
+ LPDDE_CHANNEL m_pSysChannel;
+ LPDDE_CHANNEL m_pDocChannel;
+
+ friend INTERNAL DdeBindToObject
+ (LPCOLESTR szFile,
+ REFCLSID clsid,
+ BOOL fPackageLink,
+ REFIID iid,
+ LPLPVOID ppv);
+
+ friend INTERNAL DdeIsRunning
+ (CLSID clsid,
+ LPCOLESTR szFile,
+ LPBC pbc,
+ LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning);
+#ifdef OLE_DEBUG_EXT
+
+#endif OLE_DEBUG_EXT
+};
+//
+// Note: WM_DDE_TERMINATE
+// A state machine is used to delay the executing of a premature WM_DDE_TERMINTE
+// message, which is send by some apps instead of WM_DDE_ACK (or alike).
+// The code is in WaitForReply() and in OnTerminate()
+typedef enum {
+ Terminate_None = 0, // default state - terminate code is executed
+ Terminate_Detect = 1, // window proc will NOT execute terminate code
+ Terminate_Received = 2 // wait loop does not need to run, execute terminate code now
+} TERMINATE_DOCUMENT;
+
+
+
+INTERNAL_(BOOL) wPostMessageToServer(LPDDE_CHANNEL pChannel,
+ WORD wMsg,
+ LONG lParam,
+ BOOL fFreeOnError);
+
+INTERNAL_(ATOM) wAtomFromCLSID(REFCLSID rclsid);
+INTERNAL_(ATOM) wGetExeNameAtom (REFCLSID rclsid);
+INTERNAL_(BOOL) wIsWindowValid (HWND hwnd);
+INTERNAL_(void) wFreeData (HANDLE hData, CLIPFORMAT cfFormat,
+ BOOL fFreeNonGdiHandle=TRUE);
+INTERNAL_(BOOL) wInitiate (LPDDE_CHANNEL pChannel, ATOM aLow, ATOM aHigh);
+INTERNAL wScanItemOptions (ATOM aItem, int * lpoptions);
+INTERNAL_(BOOL) wClearWaitState (LPDDE_CHANNEL pChannel);
+INTERNAL_(HANDLE) wStdCloseDocumentHandle (void);
+INTERNAL_(ATOM) wExtendAtom (ATOM aIitem, int iAdvOn);
+INTERNAL_(int) wAtomLen (ATOM atom);
+INTERNAL_(int) wAtomLenA (ATOM atom);
+INTERNAL_(HANDLE) wHandleFromDdeData(HANDLE hDdeData);
+INTERNAL_(BOOL) wIsOldServer (ATOM aClass);
+INTERNAL_(LPSTR) wAllocDdePokeBlock (DWORD dwSize,
+ CLIPFORMAT cfFormat,
+ LPHANDLE phDdePoke);
+INTERNAL_(void) wFreePokeData (LPDDE_CHANNEL pChannel, BOOL fMSDrawBug);
+INTERNAL_(HANDLE) wPreparePokeBlock (HANDLE hData,
+ CLIPFORMAT cfFormat,
+ ATOM aClass,
+ BOOL bOldSvr);
+INTERNAL_(HANDLE) wNewHandle (LPSTR lpstr, DWORD cb);
+INTERNAL wDupData (LPHANDLE ph, HANDLE h, CLIPFORMAT cf);
+INTERNAL wHandleCopy (HANDLE hDst, HANDLE hSrc);
+INTERNAL wGetItemFromClipboard (ATOM * paItem);
+INTERNAL GetDefaultIcon (REFCLSID clsidIn,
+ LPCOLESTR szFile,
+ HANDLE * phmfp);
+INTERNAL_(BOOL) wTerminateIsComing (LPDDE_CHANNEL);
+INTERNAL wTimedGetMessage (LPMSG pmsg,
+ HWND hwnd,
+ WORD wFirst,
+ WORD wLast);
+
+INTERNAL_(ATOM) wGlobalAddAtom(LPCOLESTR sz);
+INTERNAL_(ATOM) wGlobalAddAtomA(LPCSTR sz);
+
+INTERNAL wVerifyFormatEtc (LPFORMATETC pformatetc);
+INTERNAL wNormalize (LPFORMATETC pfetc, LPFORMATETC pfetcOut);
+INTERNAL wTransferHandle (LPHANDLE phDst,
+ LPHANDLE phSrc,
+ CLIPFORMAT cf);
+INTERNAL wClassesMatch (REFCLSID clsidIn, LPOLESTR szFile);
+
+#if DBG == 1
+INTERNAL_(BOOL) wIsValidHandle (HANDLE h, CLIPFORMAT cf);
+INTERNAL_(BOOL) wIsValidAtom (ATOM a);
+#endif
+
+const char achStdCloseDocument[]="[StdCloseDocument]";
+const char achStdOpenDocument[]="StdOpenDocument";
+const char achStdExit[]="StdExit";
+const char achStdNewDocument[]="StdNewDocument";
+const char achStdEditDocument[]="StdEditDocument";
+
+HWND CreateDdeClientHwnd(void);
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSGetDdeClientWindow()
+//
+// Synopsis: Returns a pointer to the per thread DdeClient window. If one
+// has not been created, it will create it and return
+//
+// Returns: Pointer to the DdeClientWindow. This window is used for per
+// thread cleanup
+//
+// History: 12-12-94 kevinro Created
+//----------------------------------------------------------------------------
+inline void * TLSGetDdeClientWindow()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+
+ if (SUCCEEDED(hr))
+ {
+ if (tls->hwndDdeClient == NULL)
+ {
+ tls->hwndDdeClient = CreateDdeClientHwnd();
+ }
+ return tls->hwndDdeClient;
+ }
+
+ return NULL;
+}
+
+
+#endif // ddeproxy.h
+
+
+
diff --git a/private/ole32/com/dde/client/ddestg.cxx b/private/ole32/com/dde/client/ddestg.cxx
new file mode 100644
index 000000000..35a7e5f44
--- /dev/null
+++ b/private/ole32/com/dde/client/ddestg.cxx
@@ -0,0 +1,529 @@
+/*
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddeStg.cpp
+
+Abstract:
+
+ This module contains the DdeObject::PersistStg and
+ DdeObject::ProxyManager methods
+
+Author:
+
+ Srini Koppolu (srinik) 22-June-1992
+ Jason Fuller (jasonful) 24-July-1992
+
+*/
+
+#include "ddeproxy.h"
+ASSERTDATA
+
+
+/*
+ * IMPLEMENTATION of CPersistStgImpl methods
+ *
+ */
+
+
+STDUNKIMPL_FORDERIVED(DdeObject, PersistStgImpl)
+
+
+#pragma SEG(CDdeObject_CPersistStgImpl_GetClassID)
+STDMETHODIMP NC(CDdeObject,CPersistStgImpl)::GetClassID (CLSID FAR* pClassID)
+{
+ *pClassID = m_pDdeObject->m_clsid;
+ return NOERROR;
+}
+
+
+#pragma SEG(CDdeObject_CPersistStgImpl_IsDirty)
+STDMETHODIMP NC(CDdeObject,CPersistStgImpl)::IsDirty ()
+{
+ return NOERROR;
+}
+
+
+
+#pragma SEG(CDdeObject_CPersistStgImpl_InitNew)
+STDMETHODIMP NC(CDdeObject,CPersistStgImpl)::InitNew
+ (IStorage FAR* pstg)
+{
+ HRESULT hres;
+ intrDebugOut((DEB_ITRACE,
+ "DdeObejct::InitNew(%x,pstg=%x)\n",
+ this,
+ pstg));
+
+ if (hres = m_pDdeObject->PostSysCommand (m_pDdeObject->m_pSysChannel,
+ (LPSTR)&achStdNewDocument,
+ TRUE))
+ return hres;
+
+ if (hres = m_pDdeObject->m_ProxyMgr.Connect (IID_NULL, CLSID_NULL))
+ return hres;
+
+ RetErr (m_pDdeObject->TermConv (m_pDdeObject->m_pSysChannel));
+ if (m_pDdeObject->m_pstg)
+ {
+ m_pDdeObject->m_pstg->Release();
+ }
+ m_pDdeObject->m_pstg = pstg;
+ pstg->AddRef();
+ return hres;
+}
+
+
+
+#pragma SEG(CDdeObject_CPersistStgImpl_Load)
+STDMETHODIMP NC(CDdeObject,CPersistStgImpl)::Load (IStorage FAR* pstg)
+{
+ LPSTR lpBuf=NULL;
+ HANDLE hDdePoke = NULL;
+ DWORD dwSize;
+ CStmBufRead StmRead;
+ CStmBufRead StmReadItem;
+ HRESULT hresult;
+
+ intrDebugOut((DEB_ITRACE,"CDdeObject::Load(%x,pstg=%x)\n",this,pstg));
+
+ {
+
+ if (hresult = StmRead.OpenStream(pstg, OLE10_NATIVE_STREAM))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) OpenStream failed(%x)\n",
+ this,
+ hresult));
+ return hresult;
+ }
+
+
+ if (hresult = StmRead.Read(&dwSize, sizeof(DWORD)))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) StRead failed(%x)\n",
+ this,
+ hresult));
+
+ goto errRtn;
+ }
+
+
+ lpBuf = wAllocDdePokeBlock (dwSize, g_cfNative, &hDdePoke);
+
+ if (lpBuf == NULL)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) wAllocDdePokeBlock failed(%x)\n",
+ this,
+ hresult));
+
+ hresult = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ if (hresult = StmRead.Read(lpBuf, dwSize))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) StRead of cfNative failed(%x)\n",
+ this,
+ hresult));
+ goto errRtn;
+ }
+
+ if (m_pDdeObject->m_hNative)
+ {
+ GlobalFree (m_pDdeObject->m_hNative);
+ }
+ m_pDdeObject->m_hNative = wNewHandle (lpBuf, dwSize);
+
+ if (m_pDdeObject->m_hNative == NULL)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) m_hNative NULL\n",
+ this));
+ }
+ }
+
+ GlobalUnlock (hDdePoke); // done with lpBuf
+
+ if (hresult = m_pDdeObject->PostSysCommand (m_pDdeObject->m_pSysChannel,
+ (LPSTR)&achStdEditDocument,
+ FALSE))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) PostSysCommand %s failed (%x)\n",
+ this,
+ &achStdEditDocument,
+ hresult));
+ goto errRtn;
+ }
+
+
+ // Read Item Name, if there is one
+ if (NOERROR == StmReadItem.OpenStream(pstg, OLE10_ITEMNAME_STREAM))
+ {
+ LPSTR szItemName = NULL;
+
+ ErrRtnH (ReadStringStreamA (StmReadItem, &szItemName));
+ m_pDdeObject->ChangeItem (szItemName);
+ PubMemFree(szItemName);
+ }
+
+ if (hresult = m_pDdeObject->m_ProxyMgr.Connect (IID_NULL, CLSID_NULL))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) ProxyMgr.Connect failed(%x)\n",
+ this,
+ hresult));
+ goto errRtn;
+ }
+
+
+ if ((hresult = m_pDdeObject->Poke(m_pDdeObject->m_aItem, hDdePoke))
+ != NOERROR)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) Poke failed(%x)\n",
+ this,
+ hresult));
+
+ // the Poke calls frees the Poke data even in case of failure.
+#ifdef LATER
+
+ if (hresult = m_pDdeObject->Execute (m_pDdeObject->m_pDocChannel,
+ wNewHandle ((LPSTR)achStdCloseDocument,sizeof(achStdCloseDocument)));
+ goto errDoc;
+#elseif
+ goto errDoc;
+#endif
+ }
+
+ hresult = m_pDdeObject->TermConv (m_pDdeObject->m_pSysChannel);
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) TermConv on SysChannel failed(%x)\n",
+ this,
+ hresult));
+ goto errRtn;
+ }
+
+
+ if (m_pDdeObject->m_pstg)
+ {
+ m_pDdeObject->m_pstg->Release();
+ }
+
+ m_pDdeObject->m_pstg = pstg;
+ pstg->AddRef();
+ goto LExit;
+
+errRtn:
+ if (hDdePoke)
+ GlobalFree (hDdePoke);
+ if (m_pDdeObject->m_pDocChannel)
+ m_pDdeObject->TermConv (m_pDdeObject->m_pDocChannel);
+LExit:
+ StmReadItem.Release();
+ StmRead.Release();
+
+ intrDebugOut((DEB_ITRACE,"::Load(%x) returning (%x)\n",this,hresult));
+ return hresult;
+}
+
+
+#pragma SEG(CDdeObject_CPersistStgImpl_Save)
+STDMETHODIMP NC(CDdeObject,CPersistStgImpl)::Save
+ (IStorage FAR* pstgSave, BOOL fSameAsLoad)
+{
+ intrDebugOut((DEB_ITRACE,
+ "DdeObject::Save(%x,pstgSave=%x)\n",
+ this,
+ pstgSave));
+
+
+ HRESULT hresult=NOERROR;
+
+ if (m_pDdeObject->m_fUpdateOnSave
+ && (m_pDdeObject->m_clsid != CLSID_Package
+ || m_pDdeObject->m_hNative == NULL))
+ {
+ // Get latest data from server, if it is not shutting down
+ // or telling us to Save, in which case it just gave us data.
+ // (If it is shutting down, it probably won't respond.
+ // Draw does respond, but gives bad data.)
+ // Packager gives truncated native data (header info with no
+ // actual embedded file) if you DDE_REQUEST it. Bug 3103
+ m_pDdeObject->Update (FALSE);
+ }
+
+ if (m_pDdeObject->m_hNative == NULL)
+ {
+ // we still have nothing to save
+ return ResultFromScode (E_BLANK);
+ }
+
+ hresult = m_pDdeObject->Save (pstgSave);
+
+ Puts ("PersistStg::Save done\n");
+ return hresult;
+}
+
+
+#pragma SEG(CDdeObject_CPersistStgImpl_SaveCompleted)
+STDMETHODIMP NC(CDdeObject,CPersistStgImpl)::SaveCompleted
+ (IStorage FAR* pstgNew)
+{
+ intrDebugOut((DEB_ITRACE,
+ "DdeObejct::SaveCompleted(%x,pstgNew=%x)\n",
+ this,
+ pstgNew));
+
+ RetZ (m_pDdeObject->m_pOleAdvHolder);
+ m_pDdeObject->m_pOleAdvHolder->SendOnSave();
+ if (pstgNew)
+ {
+ if (m_pDdeObject->m_pstg)
+ m_pDdeObject->m_pstg->Release();
+ m_pDdeObject->m_pstg = pstgNew;
+ pstgNew->AddRef();
+ }
+ return NOERROR;
+}
+
+
+#pragma SEG(CDdeObject_CPersistStgImpl_HandsOffStorage)
+STDMETHODIMP NC(CDdeObject,CPersistStgImpl)::HandsOffStorage(void)
+{
+ intrDebugOut((DEB_ITRACE,"DdeObejct::HandsOffStorage(%x)\n",this));
+ if (m_pDdeObject->m_pstg)
+ {
+ m_pDdeObject->m_pstg->Release();
+ m_pDdeObject->m_pstg = NULL;
+ }
+ return NOERROR;
+}
+
+
+/*
+ * IMPLEMENTATION of CProxyManagerImpl methods
+ *
+ */
+
+
+STDUNKIMPL_FORDERIVED(DdeObject, ProxyManagerImpl)
+
+
+
+#pragma SEG(CDdeObject_CProxyManagerImpl_CreateServer)
+STDMETHODIMP NC(CDdeObject, CProxyManagerImpl)::CreateServer(REFCLSID rclsid,
+ DWORD clsctx,
+ void *pv)
+{
+ intrDebugOut((DEB_ITRACE,"DdeObejct::CreateServer(%x)\n",this));
+ HRESULT hresult = NOERROR;
+
+ if (m_pDdeObject->m_pSysChannel)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::CreateServer(%x)m_pSysChannel exists\n",
+ this));
+ return NOERROR;
+ }
+
+ if (m_pDdeObject->m_aExeName == NULL)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::CreateServer(%x) Class Not Registered\n",
+ this));
+ return(REGDB_E_CLASSNOTREG);
+ }
+
+
+ if (!m_pDdeObject->AllocDdeChannel(&m_pDdeObject->m_pSysChannel,TRUE))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::CreateServer(%x)AllocDdeChannel is failing\n",
+ this));
+ return ReportResult(0, E_OUTOFMEMORY,0,0);
+ }
+
+ if (!m_pDdeObject->InitSysConv())
+ {
+ if (!(m_pDdeObject->LaunchApp()))
+ {
+ intrDebugOut((DEB_IERROR,"::CreateServer Could not launch app\n"));
+ hresult = ResultFromScode (CO_E_APPNOTFOUND);
+ goto errRtn;
+ }
+
+ if (!m_pDdeObject->InitSysConv())
+ {
+ intrDebugOut((DEB_IERROR,"::CreateServer Second init failed\n"));
+ hresult = ResultFromScode (CO_E_APPDIDNTREG);
+ goto errRtn;
+ }
+ }
+
+ return NOERROR;
+
+errRtn:
+ intrDebugOut((DEB_ITRACE,"DdeObejct::CreateServer(%x) is failing(%x)\n",this,hresult));
+ m_pDdeObject->DeleteChannel (m_pDdeObject->m_pSysChannel);
+ Assert (hresult != NOERROR); // This is an error path
+ return hresult;
+
+}
+
+
+#pragma SEG(CDdeObject_CProxyManagerImpl_Connect)
+STDMETHODIMP NC(CDdeObject, CProxyManagerImpl)::Connect(GUID oid, REFCLSID rclsid)
+{
+ intrDebugOut((DEB_ITRACE,"DdeObject::Connect(%x)\n",this));
+
+ if (m_pDdeObject->m_pDocChannel)
+ return NOERROR;
+
+ if (!m_pDdeObject->AllocDdeChannel (&m_pDdeObject->m_pDocChannel,FALSE))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Connect(%x) AllocDdeChannel failed, return E_OUTOFMEMORY\n",
+ this));
+ return ReportResult(0, E_OUTOFMEMORY,0,0);
+ }
+
+ // Bug 3701
+ m_pDdeObject->m_fDidSendOnClose = FALSE;
+ if (wInitiate (m_pDdeObject->m_pDocChannel, m_pDdeObject->m_aClass,
+ m_pDdeObject->m_aTopic))
+ {
+ return NOERROR;
+ }
+
+ intrDebugOut((DEB_ITRACE,"::Connect(%x) wInitiate failed\n",this));
+ m_pDdeObject->DeleteChannel (m_pDdeObject->m_pDocChannel);
+ return ResultFromScode (E_FAIL);
+}
+
+
+#pragma SEG(CDdeObject_CProxyManagerImpl_LockConnection)
+STDMETHODIMP NC(CDdeObject, CProxyManagerImpl)::LockConnection(BOOL fLock, BOOL fLastUnlockReleases)
+{
+ intrDebugOut((DEB_ITRACE,
+ "DdeObject::LockConnection(%x,fLock=%x,fLastUnlockReleases=%x)\n",
+ this,
+ fLock,
+ fLastUnlockReleases));
+
+ if (fLock)
+ m_pDdeObject->m_cLocks++;
+ else
+ {
+ if (m_pDdeObject->m_cLocks!=0 && 0 == --m_pDdeObject->m_cLocks &&
+ fLastUnlockReleases && !m_pDdeObject->m_fVisible)
+ (void)m_pDdeObject->m_Ole.Close (OLECLOSE_SAVEIFDIRTY);
+ }
+ return NOERROR;
+}
+
+
+#ifdef NOTNEEDED
+#pragma SEG(CDdeObject_CProxyManagerImpl_GetClassID)
+STDMETHODIMP_(void) NC(CDdeObject, CProxyManagerImpl)::GetClassID(CLSID FAR* pClsid)
+{
+ *pClsid = m_pDdeObject->m_clsid;
+}
+
+
+#pragma SEG(CDdeObject_CProxyManagerImpl_GetOID)
+STDMETHODIMP_(OID) NC(CDdeObject, CProxyManagerImpl)::GetOID()
+{
+ if (m_pDdeObject->m_pSysChannel)
+ return (OID) m_pDdeObject->m_pSysChannel;
+
+ if (m_pDdeObject->m_pDocChannel)
+ return (OID) m_pDdeObject->m_pDocChannel;
+
+ return NULL;
+}
+#endif
+
+#pragma SEG(CDdeObject_CProxyManagerImpl_IsConnected)
+STDMETHODIMP_(BOOL) NC(CDdeObject, CProxyManagerImpl)::IsConnected(void)
+{
+ return m_pDdeObject->m_pDocChannel != NULL;
+}
+
+
+#pragma SEG(CDdeObject_CProxyManagerImpl_EstablishIID)
+STDMETHODIMP NC(CDdeObject, CProxyManagerImpl)::EstablishIID(REFIID iid, LPVOID FAR* ppv)
+{
+ // REVIEW: this is correct, but can we be smarter like in the real PM?
+ return QueryInterface(iid, ppv);
+}
+
+
+#pragma SEG(wTerminateIsComing)
+INTERNAL_(BOOL) wTerminateIsComing (LPDDE_CHANNEL pChannel)
+{
+ MSG msg;
+ return SSPeekMessage (&msg, pChannel->hwndCli, 0, 0, PM_NOREMOVE)
+ && msg.message == WM_DDE_TERMINATE
+ && (HWND)msg.wParam==pChannel->hwndSvr;
+}
+
+
+#pragma SEG(CDdeObject_CProxyManagerImpl_Disconnect)
+STDMETHODIMP_(void) NC(CDdeObject, CProxyManagerImpl)::Disconnect()
+{
+ intrDebugOut((DEB_ITRACE,"DdeObject::Disonnect(%x)\n",this));
+
+ if (m_pDdeObject->m_pDocChannel)
+ {
+ BOOL fTermComing = wTerminateIsComing (m_pDdeObject->m_pDocChannel);
+ if ((!m_pDdeObject->m_fNoStdCloseDoc
+ || (!m_pDdeObject->m_fWasEverVisible // invisible update or
+ && !m_pDdeObject->m_fDidGetObject // link from file case.
+ && m_pDdeObject->m_fDidStdOpenDoc)) // only do StdClose if did StdOpen
+ && !m_pDdeObject->m_fDidStdCloseDoc
+ && !fTermComing)
+ {
+ m_pDdeObject->Execute (m_pDdeObject->m_pDocChannel,
+ wNewHandle ((LPSTR)&achStdCloseDocument,sizeof(achStdCloseDocument)),
+ /*fStdClose*/TRUE,
+ /*fWait*/TRUE,
+ /*fDetectTerminate*/TRUE);
+
+ m_pDdeObject->m_fDidStdCloseDoc = TRUE;
+ }
+ if (!m_pDdeObject->m_fDidSendOnClose /*|| fTermComing*/)
+ {
+ // if we did not call SendOnClose() then Disconnect() was called
+ // by a Release method, not by SendOnClose().
+ // This happens when user deletes object in container.
+ BOOL fVisible = m_pDdeObject->m_fWasEverVisible; // TermConv clears this flag
+ m_pDdeObject->TermConv (m_pDdeObject->m_pDocChannel);
+ if (!fVisible)
+ m_pDdeObject->MaybeUnlaunchApp();
+ }
+ }
+
+ if (m_pDdeObject->m_pSysChannel)
+ {
+ intrDebugOut((DEB_IWARN,"Terminating system conversation in Disconnect()\n"));
+ // This should never happen, I think.
+ m_pDdeObject->TermConv (m_pDdeObject->m_pSysChannel);
+ }
+}
+STDMETHODIMP NC(CDdeObject, CProxyManagerImpl)::CreateServerWithHandler (REFCLSID rclsid, DWORD clsctx, void *pv,
+ REFCLSID rclsidHandler, IID iidSrv, void **ppv,
+ IID iidClnt, void *pClientSiteInterface)
+{
+ return E_NOTIMPL;
+}
+
+
diff --git a/private/ole32/com/dde/client/ddewnd.cxx b/private/ole32/com/dde/client/ddewnd.cxx
new file mode 100644
index 000000000..de7c8b463
--- /dev/null
+++ b/private/ole32/com/dde/client/ddewnd.cxx
@@ -0,0 +1,361 @@
+/*++
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddewnd.cpp
+
+Abstract:
+
+ This module contains the code for the dde window procs
+
+Author:
+
+ Srini Koppolu (srinik) 20-June-1992
+
+Revision History:
+
+--*/
+#include "ddeproxy.h"
+
+
+
+#define SYS_MSG 0
+#define DOC_MSG 1
+
+// SysWndProc: Window Procedure for System Topic DDE conversations
+// wndproc for system topic
+
+
+STDAPI_(LRESULT) SysWndProc (
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+)
+{
+ StackAssert(SSOnSmallStack());
+ CDdeObject FAR* pDdeObj = NULL;
+ LPDDE_CHANNEL pChannel = NULL;
+
+ if (message>=WM_DDE_FIRST && message <= WM_DDE_LAST)
+ {
+ if (pDdeObj = (CDdeObject FAR*) GetWindowLong (hwnd, 0))
+ {
+ pChannel = pDdeObj->GetSysChannel();
+ }
+
+ if (pChannel == NULL)
+ {
+ intrAssert(pChannel != NULL);
+ return SSDefWindowProc (hwnd, message, wParam, lParam);
+ }
+ }
+ if ( pChannel
+ && ( pChannel->iAwaitAck == AA_EXECUTE
+ || pChannel->iAwaitAck == AA_INITIATE) )
+ {
+ MSG msg;
+ BOOL fDisp = FALSE;
+ while (SSPeekMessage(&msg, hwnd, WM_DDE_ACK, WM_DDE_ACK, PM_REMOVE | PM_NOYIELD) )
+ {
+ intrDebugOut((DEB_WARN, "DDE SysWndProc: dispatching WM_DDE_ACK message (%x)\n",pChannel));
+ SSDispatchMessage(&msg);
+ fDisp = TRUE;
+ }
+ if (fDisp && (pDdeObj = (CDdeObject FAR*) GetWindowLong (hwnd, 0)))
+ {
+ pChannel = pDdeObj->GetSysChannel();
+ }
+
+ if (pChannel == NULL)
+ {
+ intrAssert(pChannel != NULL);
+ return SSDefWindowProc (hwnd, message, wParam, lParam);
+ }
+ }
+
+ switch (message){
+ case WM_DDE_ACK:
+ intrDebugOut((DEB_ITRACE,
+ "SWP: WM_DDE_ACK pChannel(%x)\n",pChannel));
+ if (pChannel->bTerminating)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "SWP: pChannel->bTerminating: no action\n"));
+
+ break;
+ }
+
+ switch (pChannel->iAwaitAck) {
+ case AA_INITIATE:
+ pDdeObj->OnInitAck (pChannel, (HWND)wParam);
+ if (LOWORD(lParam))
+ GlobalDeleteAtom (LOWORD(lParam));
+ if (HIWORD(lParam))
+ GlobalDeleteAtom (HIWORD(lParam));
+ break;
+
+ case AA_EXECUTE:
+ pDdeObj->OnAck (pChannel, lParam);
+ break;
+
+ default:
+ intrDebugOut((DEB_ITRACE,
+ "SWP: WM_DDE_ACK UnhandledpChannel(%x)\n",pChannel));
+ break;
+ }
+ break;
+
+ case WM_TIMER:
+ pDdeObj->OnTimer (pChannel);
+ break;
+
+ case WM_DDE_TERMINATE:
+ intrDebugOut((DEB_ITRACE,
+ "SWP: WM_DDE_TERMINATE pChannel(%x)\n",pChannel));
+ pDdeObj->OnTerminate (pChannel, (HWND)wParam);
+ break;
+
+ default:
+ return SSDefWindowProc (hwnd, message, wParam, lParam);
+ }
+
+ return 0L;
+}
+
+
+// ClientDocWndProc: Window procedure used to document DDE conversations
+STDAPI_(LRESULT) ClientDocWndProc (
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+)
+{
+ StackAssert(SSOnSmallStack());
+ CDdeObject FAR* pDdeObj = NULL;
+ LPDDE_CHANNEL pChannel = NULL;
+ HANDLE hData;
+ ATOM aItem;
+
+ if (message>=WM_DDE_FIRST && message <= WM_DDE_LAST)
+ {
+
+ if (pDdeObj = (CDdeObject FAR*) GetWindowLong (hwnd, 0))
+ pChannel = pDdeObj->GetDocChannel();
+
+ if (pChannel == NULL)
+ {
+ //
+ // pChannel == NULL. Something is very wrong! But, lets
+ // not fault on it.
+ //
+ //intrAssert(pChannel != NULL);
+ return SSDefWindowProc (hwnd, message, wParam, lParam);
+ }
+
+ }
+ if ( pChannel
+ && ( pChannel->iAwaitAck == AA_EXECUTE
+ || pChannel->iAwaitAck == AA_INITIATE
+ || pChannel->iAwaitAck == AA_REQUESTAVAILABLE
+ || pChannel->iAwaitAck == AA_REQUEST
+ || pChannel->iAwaitAck == AA_UNADVISE
+ || pChannel->iAwaitAck == AA_EXECUTE
+ || pChannel->iAwaitAck == AA_ADVISE
+ || pChannel->iAwaitAck == AA_POKE) )
+ {
+ MSG msg;
+ BOOL fDisp = FALSE;
+ while (SSPeekMessage(&msg, hwnd, WM_DDE_ACK, WM_DDE_ACK, PM_REMOVE | PM_NOYIELD) )
+ {
+ intrDebugOut((DEB_WARN, "DDE DocWndProc: dispatching WM_DDE_ACK message (%x)\n",pChannel));
+ SSDispatchMessage(&msg);
+ fDisp = TRUE;
+ }
+
+ if (fDisp && (pDdeObj = (CDdeObject FAR*) GetWindowLong (hwnd, 0)))
+ {
+ pChannel = pDdeObj->GetDocChannel();
+ }
+
+ if (pChannel == NULL)
+ {
+ intrAssert(pChannel != NULL);
+ return SSDefWindowProc (hwnd, message, wParam, lParam);
+ }
+ }
+
+ switch (message)
+ {
+ case WM_DDE_ACK:
+
+ intrDebugOut((DEB_ITRACE,
+ "ClientWndProc: WM_DDE_ACK pChannel(%x)\n",
+ pChannel));
+ if (pChannel->bTerminating){
+ // ### this error recovery may not be correct.
+ DEBUG_OUT ("No action due to termination process",0)
+ break;
+ }
+
+ switch(pChannel->iAwaitAck){
+ case AA_INITIATE:
+ pDdeObj->OnInitAck (pChannel, (HWND)wParam);
+ if (LOWORD(lParam))
+ GlobalDeleteAtom (LOWORD(lParam));
+ if (HIWORD(lParam))
+ GlobalDeleteAtom (HIWORD(lParam));
+ break;
+
+ case AA_REQUESTAVAILABLE:
+ case AA_REQUEST:
+ case AA_UNADVISE:
+ case AA_EXECUTE:
+ case AA_ADVISE:
+ pDdeObj->OnAck (pChannel, lParam);
+ break;
+
+ case AA_POKE:
+ // freeing pokedata is done in handleack
+ pDdeObj->OnAck (pChannel, lParam);
+ break;
+
+ default:
+ intrDebugOut((DEB_IERROR,
+ "ClientWndProc: WM_DDE_ACK unhandled\n"));
+ break;
+
+ } // end of switch
+ break;
+
+ case WM_DDE_DATA:
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ pDdeObj->Guard();
+#endif // _CHICAGO_
+ hData = GET_WM_DDE_DATA_HDATA(wParam,lParam);
+ aItem = GET_WM_DDE_DATA_ITEM(wParam,lParam);
+ intrDebugOut((DEB_ITRACE,
+ "CWP: WM_DDE_DATA pChannel(%x) hData(%x) aItem(%x)\n",
+ pChannel,hData,aItem));
+ pDdeObj->OnData (pChannel, hData, aItem);
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ if (pDdeObj->UnGuard())
+ {
+ SetWindowLong(hwnd, 0, (LONG)0);
+ intrDebugOut((DEB_IWARN, "DDE ClientDocWndProc Release on pUnkOuter == 0 (this:%x, hwnd:%x\n",pDdeObj, hwnd ));
+ }
+#endif // _CHICAGO_
+
+ break;
+
+ case WM_DDE_TERMINATE:
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ pDdeObj->Guard();
+#endif // _CHICAGO_
+ intrDebugOut((DEB_ITRACE,
+ "CWP: WM_DDE_TERMINATE pChannel(%x)\n",pChannel));
+
+
+ if (pDdeObj->m_fDoingSendOnDataChange)
+ {
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ BOOL fPostMsg = TRUE;
+#endif
+ //
+ // Cheese alert! This protocol is very bad. The original
+ // 16 bit code something even more worse, so we are stuck
+ // to do something roughly compatible.
+ //
+ // If fDoingSendOnDataChange, the client may be asking for
+ // additional information from the server. The way the code
+ // is structured, it doesn't handle OnTerminate gracefully
+ // in this case.
+ //
+ // To fix this, we first tell the call control that
+ // the server has died. Then we repost the terminate
+ // message so we can handle it later.
+ //
+ // The old code did a
+ // pDdeObj->QueueMsg (hwnd, message, wParam, lParam);
+ //
+ // and the old SendOnDataChange removed the message.
+ // This probably didn't work either, but was never
+ // actually encountered.
+ //
+
+ intrDebugOut((DEB_ITRACE,
+ "CWP: term doing SendOnDataChange \n"));
+ //
+ // If we got here, there should be a CallData assigned
+ // to the channel.
+ //
+ if (pChannel->pCD)
+ {
+ intrDebugOut((DEB_ITRACE,"CWP: Setting call state\n"));
+
+ pChannel->SetCallState(SERVERCALLEX_ISHANDLED, RPC_E_SERVER_DIED);
+
+ }
+ else
+ {
+ //
+ // If there is no call data, then we aren't waiting in
+ // the channel. Terminate the conversation.
+ //
+
+ intrDebugOut((DEB_ERROR,"CWP: No call state exists\n"));
+ pDdeObj->OnTerminate (pChannel, (HWND)wParam);
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ fPostMsg = FALSE;
+#else
+ break;
+#endif //
+ }
+
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ if (fPostMsg)
+ {
+#endif
+ //
+ // Repost the message and try again.
+ //
+ intrDebugOut((DEB_ITRACE,"CWP: Reposting WM_DDE_TERMINATE\n"));
+ PostMessage(hwnd,message,wParam,lParam);
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ }
+#else
+ break;
+#endif
+
+ }
+ else
+ {
+ pDdeObj->OnTerminate (pChannel, (HWND)wParam);
+ }
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ if (pDdeObj->UnGuard())
+ {
+ SetWindowLong(hwnd, 0, (LONG)0);
+ intrDebugOut((DEB_IWARN, "DDE ClientDocWndProc Release on pUnkOuter == 0 (this:%x, hwnd:%x\n",pDdeObj, hwnd ));
+ }
+#endif // _CHICAGO_
+ break;
+
+ default:
+ return SSDefWindowProc (hwnd, message, wParam, lParam);
+
+ }
+
+ return 0L;
+}
diff --git a/private/ole32/com/dde/client/ddeworkr.cxx b/private/ole32/com/dde/client/ddeworkr.cxx
new file mode 100644
index 000000000..9d117db18
--- /dev/null
+++ b/private/ole32/com/dde/client/ddeworkr.cxx
@@ -0,0 +1,1331 @@
+/*++
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddeworkr.cpp
+
+Abstract:
+
+ This module contains the code for the worker routines
+
+Author:
+
+ Srini Koppolu (srinik) 22-June-1992
+ Jason Fuller (jasonful) 24-July-1992
+
+Revision History:
+ Kevin Ross (KevinRo) 10-May-1994
+ Mostly added comments, and attempted to clean
+ it up.
+
+--*/
+#include "ddeproxy.h"
+
+ASSERTDATA
+
+/*
+ * WORKER ROUTINES
+ *
+ */
+
+
+INTERNAL_(BOOL) wPostMessageToServer(LPDDE_CHANNEL pChannel,
+ WORD wMsg,
+ LONG lParam,
+ BOOL fFreeOnError)
+{
+ int c=0;
+ intrDebugOut((DEB_ITRACE,
+ "wPostMessageToServer(pChannel=%x,wMsg=%x,lParam=%x,fFreeOnError=%x\n",
+ pChannel,
+ wMsg,
+ lParam,
+ fFreeOnError));
+ if (NULL==pChannel)
+ {
+ AssertSz (0, "Channel missing");
+ return FALSE;
+ }
+ pChannel->wMsg = wMsg;
+ pChannel->lParam = lParam;
+ pChannel->hres = NOERROR;
+
+ while (TRUE && c<10 )
+ {
+ if (!IsWindow (pChannel->hwndSvr))
+ {
+ intrDebugOut((DEB_IWARN,
+ "wPostMessageToServer: invalid window %x\n",
+ pChannel->hwndSvr));
+ goto errRet;
+ }
+ if (wTerminateIsComing (pChannel)
+ && wMsg != WM_DDE_ACK
+ && wMsg != WM_DDE_TERMINATE)
+ {
+ intrDebugOut((DEB_IWARN,"Server sent terminate, cannot post\n"));
+ goto errRet;
+ }
+ if (!PostMessage (pChannel->hwndSvr, wMsg, (WPARAM) pChannel->hwndCli, lParam))
+ {
+ intrDebugOut((DEB_IWARN,
+ "wPostMessageToServer: PostMessageFailed, yielding\n"));
+ Yield ();
+ c++;
+ }
+ else
+ return TRUE;
+ }
+ AssertSz (0, "PostMessage failed");
+
+errRet:
+ intrDebugOut((DEB_IWARN,"wPostMessageToServer returns FALSE\n"));
+ if (fFreeOnError)
+ {
+ DDEFREE(wMsg,lParam);
+ }
+
+ return FALSE;
+}
+
+
+// call Ole1ClassFromCLSID then global add atom; returns NULL if error.
+INTERNAL_(ATOM) wAtomFromCLSID(REFCLSID rclsid)
+{
+ WCHAR szClass[MAX_STR];
+ ATOM aCls;
+
+ if (Ole1ClassFromCLSID2(rclsid, szClass, sizeof(szClass)) == 0)
+ return NULL;
+ aCls = wGlobalAddAtom(szClass);
+ intrAssert(wIsValidAtom(aCls));
+ return aCls;
+}
+
+INTERNAL_(ATOM) wGlobalAddAtom(LPCOLESTR sz)
+{
+ if (sz==NULL || sz[0] == '\0')
+ {
+ return NULL;
+ }
+
+ ATOM a = GlobalAddAtom(sz);
+ intrAssert(wIsValidAtom(a));
+ return a;
+}
+
+INTERNAL_(ATOM) wGlobalAddAtomA(LPCSTR sz)
+{
+ if (sz==NULL || sz[0] == '\0')
+ return NULL;
+ ATOM a = GlobalAddAtomA(sz);
+ intrAssert(wIsValidAtom(a));
+ return a;
+}
+
+
+INTERNAL_(ATOM) wGetExeNameAtom (REFCLSID rclsid)
+{
+ LONG cb = MAX_STR;
+ WCHAR key[MAX_STR];
+ ATOM a;
+
+ if (Ole1ClassFromCLSID2(rclsid, key, sizeof(key)) == 0)
+ return NULL;
+
+ lstrcatW (key, OLESTR("\\protocol\\StdFileEditing\\server"));
+
+ if (RegQueryValue (HKEY_CLASSES_ROOT, key, key, &cb))
+ {
+ Puts ("ERROR: wGetExeNameAtom failed\n");
+ return NULL;
+ }
+ a = wGlobalAddAtom (key);
+ intrAssert(wIsValidAtom(a));
+ return a;
+}
+
+INTERNAL_(void) wFreeData (HANDLE hData, CLIPFORMAT cfFormat,
+ BOOL fFreeNonGdiHandle)
+{
+ intrDebugOut((DEB_ITRACE,
+ "wFreeData(hData=%x,cfFormat=%x,FreeNonGDIHandle=%x\n",
+ hData,
+ (USHORT)cfFormat,
+ fFreeNonGdiHandle));
+
+ AssertSz (hData != NULL, "Trying to free NULL handle");
+ AssertSz (hData != (HANDLE) 0xcccccccc, "Trying to free handle from a deleted object");
+
+ switch (cfFormat) {
+ case CF_METAFILEPICT:
+ LPMETAFILEPICT lpMfp;
+
+ if (lpMfp = (LPMETAFILEPICT) GlobalLock (hData))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "wFreeData freeing metafile %x\n",
+ lpMfp->hMF));
+
+ OleDdeDeleteMetaFile(lpMfp->hMF);
+ GlobalUnlock (hData);
+ }
+ GlobalFree (hData);
+ break;
+
+ case CF_BITMAP:
+ case CF_PALETTE:
+ Verify(DeleteObject (hData));
+ break;
+
+ case CF_DIB:
+ GlobalFree (hData);
+ break;
+
+ default:
+ if (fFreeNonGdiHandle)
+ GlobalFree (hData);
+ break;
+ }
+}
+
+
+
+INTERNAL_(BOOL) wInitiate (LPDDE_CHANNEL pChannel, ATOM aLow, ATOM aHigh)
+{
+ intrDebugOut((DEB_ITRACE,"wInitiate(pChannel=%x,aLow=%x,aHigh=%x)\n",
+ pChannel, aLow, aHigh));
+
+ intrAssert(wIsValidAtom(aLow));
+ if (aLow == (ATOM)0)
+ {
+ intrDebugOut((DEB_IERROR,"wInitiate Failed, aLow == 0\n"));
+ return FALSE;
+ }
+
+ pChannel->iAwaitAck = AA_INITIATE;
+
+ SSSendMessage ((HWND)-1, WM_DDE_INITIATE, (WPARAM) pChannel->hwndCli,
+ MAKE_DDE_LPARAM (WM_DDE_INITIATE, aLow, aHigh));
+
+ pChannel->iAwaitAck = NULL;
+
+ intrDebugOut((DEB_ITRACE,
+ "wInitiate pChannel->hwndSrvr = %x\n",
+ pChannel->hwndSvr));
+
+ return (pChannel->hwndSvr != NULL);
+}
+
+
+
+INTERNAL_(HRESULT) wScanItemOptions (ATOM aItem, int FAR* lpoptions)
+{
+ ATOM aModifier;
+ LPOLESTR lpbuf;
+ WCHAR buf[MAX_STR];
+
+ *lpoptions = ON_CHANGE; // default
+
+ if (!aItem) {
+ // NULL item with no modifier means ON_CHANGE for NULL item
+ return NOERROR;
+ }
+
+ intrAssert(wIsValidAtom(aItem));
+ GlobalGetAtomName (aItem, buf, MAX_STR);
+ lpbuf = buf;
+
+ while ( *lpbuf && *lpbuf != '/')
+ IncLpch (lpbuf);
+
+ // no modifier same as /change
+
+ if (*lpbuf == NULL)
+ return NOERROR;
+
+ *lpbuf++ = NULL; // seperate out the item string
+ // We are using this in the caller.
+
+ if (!(aModifier = GlobalFindAtom (lpbuf)))
+ {
+ Puts ("ERROR: wScanItemOptions found non-atom modifier\n");
+ return ReportResult(0, RPC_E_DDE_SYNTAX_ITEM, 0, 0);
+ }
+
+ intrAssert(wIsValidAtom(aModifier));
+
+ if (aModifier == aChange)
+ return NOERROR;
+
+ // Is it a save?
+ if (aModifier == aSave){
+ *lpoptions = ON_SAVE;
+ return NOERROR;
+ }
+ // Is it a Close?
+ if (aModifier == aClose){
+ *lpoptions = ON_CLOSE;
+ return NOERROR;
+ }
+
+ // unknown modifier
+ Puts ("ERROR: wScanItemOptions found bad modifier\n");
+ return ReportResult(0, RPC_E_DDE_SYNTAX_ITEM, 0, 0);
+}
+
+
+INTERNAL_(BOOL) wClearWaitState (LPDDE_CHANNEL pChannel)
+{
+ Assert (pChannel);
+ // kill if any timer active.
+ if (pChannel->wTimer) {
+ KillTimer (pChannel->hwndCli, 1);
+ pChannel->wTimer = 0;
+
+ if (pChannel->hDdePoke) {
+ GlobalFree (pChannel->hDdePoke);
+ pChannel->hDdePoke = NULL;
+ }
+
+ if (pChannel->hopt) {
+ GlobalFree (pChannel->hopt);
+ pChannel->hopt = NULL;
+ }
+
+ //
+ // If the channel is waiting on an Ack, and there is an
+ // lParam, then we may need to cleanup the data.
+
+ if (pChannel->iAwaitAck && (pChannel->lParam)) {
+ if (pChannel->iAwaitAck == AA_EXECUTE)
+ {
+ //
+ // KevinRo: Found the following comment in the code.
+ // ; // BUGBUG32 - get hData from GET_WM_DDE_EXECUTE_HADATA ??
+ // It appears, by looking at what the 16-bit code does,
+ // that the goal is to free the handle that was passed as
+ // part of the EXECUTE message. Judging by what the 16-bit
+ // code did, I have determined that this is correct.
+ //
+ // The macro used below wanted two parameters. The first was
+ // the WPARAM, the second the LPARAM. We don't have the WPARAM.
+ // However, it isn't actually used by the macro, so I have
+ // cheated and provided 0 as a default
+ //
+ GlobalFree(GET_WM_DDE_EXECUTE_HDATA(0,pChannel->lParam));
+
+#ifdef KEVINRO_HERE_IS_THE_16_BIT_CODE
+ GlobalFree (HIWORD (pChannel->lParam));
+#endif
+ }
+ else
+ {
+ //
+ // All of the other DDE messages pass an Atom in the high word.
+ // Therefore, we should delete the atom.
+ //
+ //
+ ATOM aTmp;
+
+ aTmp = MGetDDElParamHi(pChannel->wMsg,pChannel->lParam);
+
+ intrAssert(wIsValidAtom(aTmp));
+ if (aTmp)
+ {
+ GlobalDeleteAtom (aTmp);
+ }
+ }
+ DDEFREE(pChannel->wMsg,pChannel->lParam);
+
+ // we want to wipe out the lParam
+ pChannel->lParam = 0x0;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+// wNewHandle (LPSTR, DWORD)
+//
+// Copy cb bytes from lpstr into a new memory block and return a handle to it.
+// If lpstr is an ASCIIZ string, cb must include 1 for the null terminator.
+//
+
+INTERNAL_(HANDLE) wNewHandle (LPSTR lpstr, DWORD cb)
+{
+
+ HANDLE hdata = NULL;
+ LPSTR lpdata = NULL;
+
+ hdata = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, cb);
+ if (hdata == NULL || (lpdata = (LPSTR) GlobalLock (hdata)) == NULL)
+ goto errRtn;
+
+ memcpy (lpdata, lpstr, cb);
+ GlobalUnlock (hdata);
+ return hdata;
+
+errRtn:
+ Puts ("ERROR: wNewHandle\n");
+ Assert (0);
+ if (lpdata)
+ GlobalUnlock (hdata);
+
+ if (hdata)
+ GlobalFree (hdata);
+ return NULL;
+}
+
+
+
+// wDupData
+//
+// Copy data from handle h into a new handle which is returned as *ph.
+//
+
+INTERNAL wDupData (LPHANDLE ph, HANDLE h, CLIPFORMAT cf)
+{
+ Assert (ph);
+ RetZ (wIsValidHandle(h, cf));
+ *ph = OleDuplicateData (h, cf, GMEM_DDESHARE | GMEM_MOVEABLE);
+ RetZ (wIsValidHandle (*ph, cf));
+ return NOERROR;
+}
+
+
+// wTransferHandle
+//
+//
+INTERNAL wTransferHandle
+ (LPHANDLE phDst,
+ LPHANDLE phSrc,
+ CLIPFORMAT cf)
+{
+ RetErr (wDupData (phDst, *phSrc, cf));
+ wFreeData (*phSrc, cf, TRUE);
+ *phSrc = (HANDLE)0;
+ return NOERROR;
+}
+
+
+// wHandleCopy
+//
+// copy data from hSrc to hDst.
+// Both handles must already have memory allocated to them.
+//
+
+INTERNAL wHandleCopy (HANDLE hDst, HANDLE hSrc)
+{
+ LPSTR lpDst, lpSrc;
+ DWORD dwSrc;
+
+ if (NULL==hDst || NULL==hSrc)
+ return ResultFromScode (E_INVALIDARG);
+ if (GlobalSize(hDst) < (dwSrc=GlobalSize(hSrc)))
+ {
+ HANDLE hDstNew = GlobalReAlloc (hDst, dwSrc, GMEM_DDESHARE | GMEM_MOVEABLE);
+ if (hDstNew != hDst)
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+ if (!(lpDst = (LPSTR) GlobalLock(hDst)))
+ {
+ intrAssert(!"ERROR: wHandleCopy hDst");
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ if (!(lpSrc = (LPSTR) GlobalLock(hSrc)))
+ {
+ GlobalUnlock(hDst);
+ intrAssert (!"ERROR: wHandleCopy hSrc");
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ memcpy (lpDst, lpSrc, dwSrc);
+ GlobalUnlock(hDst);
+ GlobalUnlock(hSrc);
+ return NOERROR;
+}
+
+
+// ExtendAtom: Create a new atom, which is the old one plus extension
+
+INTERNAL_(ATOM) wExtendAtom (ATOM aItem, int iAdvOn)
+{
+ WCHAR buffer[MAX_STR+1];
+ LPOLESTR lpext;
+
+ buffer[0] = 0;
+ // aItem==NULL for embedded objects.
+ // If so, there is no item name before the slash.
+ if (aItem)
+ GlobalGetAtomName (aItem, buffer, MAX_STR);
+
+ switch (iAdvOn) {
+ case ON_CHANGE:
+ lpext = OLESTR("");
+ break;
+
+ case ON_SAVE:
+ lpext = OLESTR("/Save");
+ break;
+
+ case ON_CLOSE:
+ lpext = OLESTR("/Close");
+ break;
+
+ default:
+ AssertSz (FALSE, "Unknown Advise option");
+ break;
+
+ }
+
+ lstrcatW (buffer, lpext);
+ if (buffer[0])
+ return wGlobalAddAtom (buffer);
+ else
+ return NULL;
+ // not an error. For embedded object on-change, aItem==NULL
+}
+
+
+
+
+INTERNAL_(ATOM) wDupAtom (ATOM a)
+{
+ WCHAR sz[MAX_STR];
+
+ if (!a)
+ return NULL;
+
+ Assert (wIsValidAtom (a));
+ GlobalGetAtomName (a, sz, MAX_STR);
+ return wGlobalAddAtom (sz);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: wAtomLen
+//
+// Synopsis: Return the length, in characters, of the atom name.
+// The length includes the NULL. This function returns the
+// length of the UNICODE version of the atom.
+//
+// Effects:
+//
+// Arguments: [atom] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(int) wAtomLen (ATOM atom)
+{
+ WCHAR buf[MAX_STR];
+
+ if (!atom)
+ return NULL;
+
+ return (GlobalGetAtomName (atom, buf, MAX_STR));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: wAtomLenA
+//
+// Synopsis: Return the length, in characters, of the atom name.
+// The length includes the NULL This function returns the
+// length of the ANSI version of the atom,
+//
+// Effects:
+//
+// Arguments: [atom] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(int) wAtomLenA (ATOM atom)
+{
+ char buf[MAX_STR];
+
+ if (!atom)
+ return NULL;
+
+ return (GlobalGetAtomNameA (atom, (LPSTR)buf, MAX_STR));
+}
+
+
+
+// NOTE: returns address of static buffer. Use return value immediately.
+//
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: wAtomName
+//
+// Synopsis: Returns a STATIC BUFFER that holds the string name of the
+// atom.
+//
+// Effects:
+//
+// Arguments: [atom] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Commented
+//
+// Notes:
+//
+// WARNING: This uses a static buffer, so don't depend on the pointer for
+// very long.
+//
+//----------------------------------------------------------------------------
+INTERNAL_(LPOLESTR) wAtomName (ATOM atom)
+{
+ static WCHAR buf[MAX_STR];
+
+ if (!atom)
+ return NULL;
+
+ if (0==GlobalGetAtomName (atom, buf, MAX_STR))
+ return NULL;
+
+ return buf;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: wAtomName
+//
+// Synopsis: Returns a STATIC BUFFER that holds the string name of the
+// atom.
+//
+// Effects:
+//
+// Arguments: [atom] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Commented
+//
+// Notes:
+//
+// WARNING: This uses a static buffer, so don't depend on the pointer for
+// very long.
+//
+//----------------------------------------------------------------------------
+INTERNAL_(LPSTR) wAtomNameA (ATOM atom)
+{
+ static char buf[MAX_STR];
+
+ if (!atom)
+ return NULL;
+
+ if (0==GlobalGetAtomNameA (atom, (LPSTR)buf, MAX_STR))
+ return NULL;
+
+ return buf;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: wHandleFromDdeData
+//
+// Synopsis: Return a handle from the DDEDATA passed in.
+//
+// Effects: This function will return the correct data from the
+// DDEDATA that is referenced by the handle passed in.
+//
+// DDEDATA is a small structure that is used in DDE to
+// specify the data type of the buffer, its release
+// semantics, and the actual data.
+//
+// In the case of a known format, the handle to the
+// data is extracted from the DDEDATA structure, and
+// the hDdeData is released.
+//
+// If its a Native format, the data is either moved
+// within the memory block allocated, or is copied to
+// another block, depending on the fRelease flag in
+// the hDdeData.
+//
+// Arguments: [hDdeData] -- Handle to DDEDATA
+//
+// Requires:
+//
+// Returns: A handle to the data. hDdeData will be invalidated
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-13-94 kevinro Commented
+//
+// Notes:
+//
+// hDdeData is invalid after calling this function
+//
+//----------------------------------------------------------------------------
+
+
+INTERNAL_(HANDLE) wHandleFromDdeData
+ (HANDLE hDdeData)
+{
+ intrDebugOut((DEB_ITRACE,"wHandleFromDdeData(%x)\n",hDdeData));
+ BOOL fRelease;
+ HGLOBAL h = NULL; // return value
+
+ DDEDATA FAR* lpDdeData = (DDEDATA FAR *) GlobalLock (hDdeData);
+
+ //
+ // If the handle is invalid, then the lpDdeData will be NULL
+ //
+ if (!lpDdeData)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "\twHandleFromDdeData(%x) invalid handle\n",
+ hDdeData));
+ return NULL;
+ }
+
+
+ //
+ // The header section of a DDEDATA consists of 2 shorts.
+ // That makes it 4 bytes. Due to the new packing values,
+ // it turns out that doing a sizeof(DDEDATA) won't work,
+ // because the size gets rounded up to a multple of 2
+ //
+ // We will just hard code the 4 here, since it cannot change
+ // for all time anyway.
+ //
+ #define cbHeader 4
+ Assert (cbHeader==4);
+
+ //
+ // If the cfFormat is BITMAP or METAFILEPICT, then the
+ // handle will be retrieved from the first DWORD of the
+ // buffer
+ //
+ if (lpDdeData->cfFormat == CF_BITMAP ||
+ lpDdeData->cfFormat == CF_METAFILEPICT)
+ {
+ //
+ // The alignment here should be fine, since the Value
+ // field is DWORD aligned. So, we trust this cast
+ //
+ h = *(LPHANDLE)lpDdeData->Value;
+ Assert (GlobalFlags(h) != GMEM_INVALID_HANDLE);
+ fRelease = lpDdeData->fRelease;
+ GlobalUnlock (hDdeData);
+ if (fRelease)
+ {
+ GlobalFree (hDdeData);
+ }
+
+ return h;
+ }
+ else if (lpDdeData->cfFormat == CF_DIB)
+ {
+ //
+ // The alignment here should be fine, since the Value
+ // field is DWORD aligned.
+ //
+ // This changes the memory from fixed to moveable.
+ //
+ h = GlobalReAlloc (*(LPHANDLE)lpDdeData->Value, 0L,
+ GMEM_MODIFY|GMEM_MOVEABLE);
+ Assert (GlobalFlags(h) != GMEM_INVALID_HANDLE);
+ fRelease = lpDdeData->fRelease;
+ GlobalUnlock (hDdeData);
+ if (fRelease)
+ GlobalFree (hDdeData);
+ return h;
+ }
+
+
+ // Native and other data case
+ // dwSize = size of Value array, ie, size of the data itself
+ const DWORD dwSize = GlobalSize (hDdeData) - cbHeader;
+
+ if (lpDdeData->fRelease)
+ {
+ // Move the Value data up over the DDE_DATA header flags.
+ memcpy ((LPSTR)lpDdeData, ((LPSTR)lpDdeData)+cbHeader, dwSize);
+ GlobalUnlock (hDdeData);
+ h = GlobalReAlloc (hDdeData, dwSize, GMEM_MOVEABLE);
+ Assert (GlobalFlags(h) != GMEM_INVALID_HANDLE);
+ return h;
+ }
+ else
+ {
+ // Duplicate the data because the server will free the original.
+ h = wNewHandle (((LPSTR)lpDdeData)+cbHeader, dwSize);
+ Assert (GlobalFlags(h) != GMEM_INVALID_HANDLE);
+ GlobalUnlock (hDdeData);
+ return h;
+ }
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::CanCallBack
+//
+// Synopsis: This routine apparently was supposed to determine if a
+// call back could be made. However, the PeekMessage stuff
+// was commented out.
+//
+// So, it returns TRUE if 0 or 1, FALSE but increments lpCount
+// if 2, returns true but decrements lpCount if > 3. Why?
+// Dunno. Need to ask JasonFul
+//
+// Effects:
+//
+// Arguments: [lpCount] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-16-94 kevinro Commented, confused, and disgusted
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(BOOL) CDdeObject::CanCallBack (LPINT lpCount)
+{
+ switch (*lpCount) {
+ case 0:
+ case 1:
+ return TRUE;
+
+ case 2:
+ {
+// MSG msg;
+ if (0)
+ //!PeekMessage (&msg, m_pDocChannel->hwndCli,0,0, PM_NOREMOVE) ||
+ // msg.message != WM_DDE_DATA)
+ {
+ Puts ("Server only sent one format (hopefully presentation)\n");
+ return TRUE;
+ }
+ else
+ {
+ ++(*lpCount);
+ return FALSE;
+ }
+ }
+
+ case 3:
+ --(*lpCount);
+ return TRUE;
+
+ default:
+ AssertSz (FALSE, "012345" + *lpCount);
+ return FALSE;
+ }
+}
+
+
+INTERNAL_(BOOL) wIsOldServer (ATOM aClass)
+{
+ LONG cb = MAX_STR;
+ WCHAR key[MAX_STR];
+ int len;
+
+ if (aClass==(ATOM)0)
+ return FALSE;
+
+ if (!GlobalGetAtomName (aClass, key, sizeof(key)))
+ return TRUE;
+
+ lstrcatW (key, OLESTR("\\protocol\\StdFileEditing\\verb\\"));
+ len = lstrlenW (key);
+ key [len++] = (char) ('0');
+ key [len++] = 0;
+
+ if (RegQueryValue (HKEY_CLASSES_ROOT, key, key, &cb))
+ return TRUE; // no verbs registered
+
+ return FALSE;
+}
+
+
+
+
+INTERNAL_(void) wFreePokeData
+ (LPDDE_CHANNEL pChannel,
+ BOOL fMSDrawBug)
+{
+ DDEPOKE FAR * lpdde;
+
+ if (!pChannel )
+ return;
+
+ if (!pChannel->hDdePoke)
+ return;
+
+ if (lpdde = (DDEPOKE FAR *) GlobalLock (pChannel->hDdePoke)) {
+
+ // The old version of MSDraw expects the _contents_ of METAFILEPICT
+ // structure, rather than the handle to it, to be part of DDEPOKE.
+
+ if (fMSDrawBug && lpdde->cfFormat==CF_METAFILEPICT) {
+ intrDebugOut((DEB_ITRACE,
+ "wFreePokeData is accomodating MSDraw bug\n"));
+ //
+ // This meta file was created in 32-bits, and was not passed
+ // into us by DDE. Therefore, this metafile should not need to
+ // call WOW to be free'd.
+ //
+ DeleteMetaFile (((LPMETAFILEPICT) ((LPVOID) &lpdde->Value))->hMF);
+ }
+ // If there is a normal metafile handle in the Value field,
+ // it will be freed (if necessary) by the ReleaseStgMedium()
+ // in DO::SetData
+ GlobalUnlock (pChannel->hDdePoke);
+ }
+ GlobalFree (pChannel->hDdePoke);
+ pChannel->hDdePoke = NULL;
+}
+
+
+
+
+INTERNAL_(HANDLE) wPreparePokeBlock
+ (HANDLE hData, CLIPFORMAT cfFormat, ATOM aClass, BOOL bOldSvr)
+{
+ HANDLE hDdePoke;
+ LPSTR lpBuf;
+
+ if (!hData)
+ return NULL;
+
+ // The old version of MSDraw expects the contents of METAFILEPICT
+ // structure to be part of DDEPOKE, rather than the handle to it.
+ if ((cfFormat==CF_METAFILEPICT && !(aClass==aMSDraw && bOldSvr))
+ || (cfFormat == CF_DIB)
+ || (cfFormat == CF_BITMAP)) {
+
+ Verify (lpBuf = wAllocDdePokeBlock (4, cfFormat, &hDdePoke));
+ *((HANDLE FAR*)lpBuf) = hData;
+
+ }
+ else {
+ // Handle the non-metafile case and the MS-Draw bug
+ DWORD dwSize = GlobalSize (hData);
+
+ if ((aClass == aMSDraw) && bOldSvr)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "wPreparePokeBlock is accomodating MSDraw bug\n"));
+ }
+
+ if (lpBuf = wAllocDdePokeBlock (dwSize, cfFormat, &hDdePoke)) {
+ memcpy (lpBuf, GlobalLock(hData), dwSize);
+ GlobalUnlock (hData);
+ }
+ }
+ GlobalUnlock (hDdePoke);
+ return hDdePoke;
+}
+
+
+// wAllocDdePokeBlock
+// The caller must unlock *phDdePoke when it is done using the return value
+// of this function but before a DDe message is sent using *phDdePoke.
+//
+
+INTERNAL_(LPSTR) wAllocDdePokeBlock
+ (DWORD dwSize, CLIPFORMAT cfFormat, LPHANDLE phDdePoke)
+{
+ HANDLE hdde = NULL;
+ DDEPOKE FAR * lpdde = NULL;
+
+ if (!(hdde = GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT,
+ (dwSize + sizeof(DDEPOKE) - sizeof(BYTE) ))))
+ return NULL;
+
+ if (!(lpdde = (DDEPOKE FAR*)GlobalLock (hdde))) {
+ GlobalFree (hdde);
+ return NULL;
+ }
+ // hdde will be UnLock'ed in wPreparePokeBlock and Free'd in wFreePokeData
+ lpdde->fRelease = FALSE;
+ lpdde->cfFormat = cfFormat;
+ *phDdePoke = hdde;
+ return (LPSTR) &(lpdde->Value);
+}
+
+
+#ifdef OLD
+INTERNAL_(ULONG) wPixelsToHiMetric
+ (ULONG cPixels,
+ ULONG cPixelsPerInch)
+{
+ return cPixels * HIMETRIC_PER_INCH / cPixelsPerInch;
+}
+#endif
+
+// Can ask for icon based on either CLSID or filename
+//
+
+INTERNAL GetDefaultIcon (REFCLSID clsidIn, LPCOLESTR szFile, HANDLE FAR* phmfp)
+{
+ if (!(*phmfp = OleGetIconOfClass(clsidIn, NULL, TRUE)))
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ return NOERROR;
+}
+
+#ifdef OLD
+ VDATEPTROUT (phmfp, HICON);
+ VDATEPTRIN (szFile, char);
+ WCHAR szExe[MAX_STR];
+ HICON hicon;
+ HDC hdc;
+ METAFILEPICT FAR* pmfp=NULL;
+ HRESULT hresult;
+ static int cxIcon = 0;
+ static int cyIcon = 0;
+ static int cxIconHiMetric = 0;
+ static int cyIconHiMetric = 0;
+
+ *phmfp = NULL;
+ CLSID clsid;
+ if (clsidIn != CLSID_NULL)
+ {
+ clsid = clsidIn;
+ }
+ else
+ {
+ RetErr (GetClassFile (szFile, &clsid));
+ }
+ ATOM aExe = wGetExeNameAtom (clsid);
+ if (0==GlobalGetAtomName (aExe, szExe, MAX_STR))
+ {
+ Assert (0);
+ return ReportResult(0, E_UNEXPECTED, 0, 0);
+ }
+ hicon = ExtractIcon (hmodOLE2, szExe, 0/*first icon*/);
+ if (((HICON) 1)==hicon || NULL==hicon)
+ {
+ // ExtractIcon failed, so we can't support DVASPECT_ICON
+ return ResultFromScode (DV_E_DVASPECT);
+ }
+ *phmfp = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(METAFILEPICT));
+ ErrZS (*phmfp, E_OUTOFMEMORY);
+ pmfp = (METAFILEPICT FAR*) GlobalLock (*phmfp);
+ ErrZS (pmfp, E_OUTOFMEMORY);
+ if (0==cxIcon)
+ {
+ // In units of pixels
+ Verify (cxIcon = GetSystemMetrics (SM_CXICON));
+ Verify (cyIcon = GetSystemMetrics (SM_CYICON));
+ // In units of .01 millimeter
+ cxIconHiMetric = (int)(long)wPixelsToHiMetric (cxIcon, giPpliX) ;
+ cyIconHiMetric = (int)(long)wPixelsToHiMetric (cyIcon, giPpliY) ;
+ }
+ pmfp->mm = MM_ANISOTROPIC;
+ pmfp->xExt = cxIconHiMetric;
+ pmfp->yExt = cyIconHiMetric;
+ hdc = CreateMetaFile (NULL);
+ SetWindowOrg (hdc, 0, 0);
+ SetWindowExt (hdc, cxIcon, cyIcon);
+ DrawIcon (hdc, 0, 0, hicon);
+ pmfp->hMF = CloseMetaFile (hdc);
+ ErrZ (pmfp->hMF);
+ Assert (wIsValidHandle (pmfp->hMF, NULL));
+ GlobalUnlock (*phmfp);
+ Assert (wIsValidHandle (*phmfp, CF_METAFILEPICT));
+ return NOERROR;
+
+ errRtn:
+ if (pmfp)
+ GlobalUnlock (*phmfp);
+ if (*phmfp)
+ GlobalFree (*phmfp);
+ return hresult;
+}
+#endif
+
+#define DWTIMEOUT 1000L
+
+INTERNAL wTimedGetMessage
+ (LPMSG pmsg,
+ HWND hwnd,
+ WORD wFirst,
+ WORD wLast)
+{
+ DWORD dwStartTickCount = GetTickCount();
+ while (!SSPeekMessage (pmsg, hwnd, wFirst, wLast, PM_REMOVE))
+ {
+ if (GetTickCount() - dwStartTickCount > DWTIMEOUT)
+ {
+ if (!IsWindow (hwnd))
+ return ResultFromScode (RPC_E_CONNECTION_LOST);
+ else
+ return ResultFromScode (RPC_E_SERVER_DIED);
+ }
+ }
+ return NOERROR;
+}
+
+
+INTERNAL wNormalize
+ (LPFORMATETC pformatetcIn,
+ LPFORMATETC pformatetcOut)
+{
+ if (pformatetcIn->cfFormat == 0
+ && pformatetcIn->ptd == NULL // Is WildCard
+ && pformatetcIn->dwAspect == -1L
+ && pformatetcIn->lindex == -1L
+ && pformatetcIn->tymed == -1L)
+ {
+ pformatetcOut->cfFormat = CF_METAFILEPICT;
+ pformatetcOut->ptd = NULL;
+ pformatetcOut->dwAspect = DVASPECT_CONTENT;
+ pformatetcOut->lindex = DEF_LINDEX;
+ pformatetcOut->tymed = TYMED_MFPICT;
+ }
+ else
+ {
+ memcpy (pformatetcOut, pformatetcIn, sizeof(FORMATETC));
+ }
+ return NOERROR;
+}
+
+
+
+INTERNAL wVerifyFormatEtc
+ (LPFORMATETC pformatetc)
+{
+ intrDebugOut((DEB_ITRACE,
+ "wVerifyFormatEtc(pformatetc=%x)\n",
+ pformatetc));
+
+ VDATEPTRIN (pformatetc, FORMATETC);
+ if (!HasValidLINDEX(pformatetc))
+ {
+ intrDebugOut((DEB_IERROR, "\t!HasValidLINDEX(pformatetc)\n"));
+ return(DV_E_LINDEX);
+ }
+
+ if (0==(pformatetc->tymed & (TYMED_HGLOBAL | TYMED_MFPICT | TYMED_GDI)))
+ {
+ intrDebugOut((DEB_IERROR,
+ "\t0==(pformatetc->tymed & (TYMED_HGLOBAL | TYMED_MFPICT | TYMED_GDI))\n"));
+ return ResultFromScode (DV_E_TYMED);
+ }
+ if (0==(UtFormatToTymed (pformatetc->cfFormat) & pformatetc->tymed))
+ {
+ intrDebugOut((DEB_IERROR,
+ "\t0==(UtFormatToTymed (pformatetc->cfFormat) & pformatetc->tymed)\n"));
+ return ResultFromScode (DV_E_TYMED);
+ }
+ if (0==(pformatetc->dwAspect & (DVASPECT_CONTENT | DVASPECT_ICON)))
+ {
+ intrDebugOut((DEB_IERROR,
+ "\t0==(pformatetc->dwAspect & (DVASPECT_CONTENT | DVASPECT_ICON))\n"));
+
+ return ResultFromScode (DV_E_DVASPECT);
+ }
+ if (pformatetc->dwAspect & DVASPECT_ICON)
+ {
+ if (CF_METAFILEPICT != pformatetc->cfFormat)
+ {
+ intrDebugOut((DEB_IERROR,
+ "\tCF_METAFILEPICT != pformatetc->cfFormat\n"));
+ return ResultFromScode (DV_E_CLIPFORMAT);
+ }
+
+ if (0==(pformatetc->tymed & TYMED_MFPICT))
+ {
+ intrDebugOut((DEB_IERROR,
+ "\t0==(pformatetc->tymed & TYMED_MFPICT)\n"));
+ return ResultFromScode (DV_E_TYMED);
+ }
+ }
+ if (pformatetc->ptd)
+ {
+ if (IsBadReadPtr (pformatetc->ptd, sizeof (DWORD))
+ || IsBadReadPtr (pformatetc->ptd, (size_t)pformatetc->ptd->tdSize))
+ {
+ intrDebugOut((DEB_IERROR,"\tDV_E_DVTARGETDEVICE\n"));
+
+ return ResultFromScode (DV_E_DVTARGETDEVICE);
+ }
+ }
+ return NOERROR;
+}
+
+
+
+INTERNAL wClassesMatch
+ (REFCLSID clsidIn,
+ LPOLESTR szFile)
+{
+ CLSID clsid;
+ if (NOERROR==GetClassFile (szFile, &clsid))
+ {
+ return clsid==clsidIn ? NOERROR : ResultFromScode (S_FALSE);
+ }
+ else
+ {
+ // If we can't determine the class of the file (because it's
+ // not a real file) then OK. Bug 3937.
+ return NOERROR;
+ }
+}
+
+
+
+#ifdef KEVINRO_DUPLICATECODE
+
+This routine also appears in ole1.lib in the OLE232\OLE1 directory
+
+INTERNAL wWriteFmtUserType
+ (LPSTORAGE pstg,
+ REFCLSID clsid)
+{
+ HRESULT hresult = NOERROR;
+ LPOLESTR szProgID = NULL;
+ LPOLESTR szUserType = NULL;
+
+ ErrRtnH (ProgIDFromCLSID (clsid, &szProgID));
+ ErrRtnH (OleRegGetUserType (clsid, USERCLASSTYPE_FULL, &szUserType));
+ ErrRtnH (WriteFmtUserTypeStg (pstg, RegisterClipboardFormat (szProgID),
+ szUserType));
+ errRtn:
+ delete szProgID;
+ delete szUserType;
+ return hresult;
+}
+#endif
+
+#if DBG == 1
+
+INTERNAL_(BOOL) wIsValidHandle
+ (HANDLE h,
+ CLIPFORMAT cf) // cf==NULL means normal memory
+{
+ LPVOID p;
+ if (CF_BITMAP == cf)
+ {
+ BITMAP bm;
+ return (0 != GetObject (h, sizeof(BITMAP), (LPVOID) &bm));
+ }
+ if (CF_PALETTE == cf)
+ {
+ WORD w;
+ return (0 != GetObject (h, sizeof(w), (LPVOID) &w));
+ }
+ if (!(p=GlobalLock(h)))
+ {
+ Puts ("Invalid handle");
+ Puth (h);
+ Putn();
+ return FALSE;
+ }
+ if (IsBadReadPtr (p, (WPARAM) min (UINT_MAX, GlobalSize(h))))
+ {
+ GlobalUnlock (h);
+ return FALSE;
+ }
+ GlobalUnlock (h);
+ return TRUE;
+}
+INTERNAL_(BOOL) wIsValidAtom (ATOM a)
+{
+ WCHAR sz[MAX_STR];
+ if (a==0)
+ return TRUE;
+ if (a < 0xC000)
+ return FALSE;
+ if (0==GlobalGetAtomName (a, sz, MAX_STR))
+ return FALSE;
+ if ('\0'==sz[0])
+ return FALSE;
+ return TRUE;
+}
+
+
+// A "gentle" assert used in reterr.h
+//
+
+
+INTERNAL_(void) wWarn
+ (LPSTR sz,
+ LPSTR szFile,
+ int iLine)
+{
+ intrDebugOut((DEB_WARN,
+ "Warning: %s:%u %s\n",
+ szFile,iLine,sz));
+}
+
+#endif // DBG
+
+
diff --git a/private/ole32/com/dde/client/dirs b/private/ole32/com/dde/client/dirs
new file mode 100644
index 000000000..820fa2392
--- /dev/null
+++ b/private/ole32/com/dde/client/dirs
@@ -0,0 +1,37 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ daytona
diff --git a/private/ole32/com/dde/client/modallp.cxx b/private/ole32/com/dde/client/modallp.cxx
new file mode 100644
index 000000000..a9faa18c1
--- /dev/null
+++ b/private/ole32/com/dde/client/modallp.cxx
@@ -0,0 +1,315 @@
+/*
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ modallp.cpp
+
+Abstract:
+
+ This module contains the code to wait for reply on a remote call.
+
+Author:
+ Johann Posch (johannp) 01-March-1993 modified to use CoRunModalLoop
+
+*/
+
+#include "ddeproxy.h"
+
+
+#define DebWarn(x)
+#define DebError(x)
+#define DebAction(x)
+#if DBG==1
+static unsigned iCounter=0;
+#endif
+//
+// Called after posting a message (call) to a server
+//
+#pragma SEG(CDdeObject_WaitForReply)
+
+
+
+INTERNAL CDdeObject::SendMsgAndWaitForReply
+ (LPDDE_CHANNEL pChannel,
+ int iAwaitAck,
+ WORD wMsg,
+ long lparam,
+ BOOL fFreeOnError,
+ BOOL fStdCloseDoc,
+ BOOL fDetectTerminate,
+ BOOL fWait )
+{
+#ifdef _MAC
+#else
+ DDECALLDATA DdeCD;
+ BOOL fPending;
+ HRESULT hres;
+ ULONG status = 0;
+
+
+
+#if DBG == 1
+ unsigned iAutoCounter;
+ intrDebugOut((INTR_DDE,
+ "DdeObject::WaitForReply(%x) Call#(%x) awaiting %x\n",
+ this,
+ iAutoCounter=++iCounter,
+ iAwaitAck));
+#endif
+
+ // make sure we have a call control. if OLE2 stuff has never been run,
+ // then we might not yet have a call control (since
+ // ChannelThreadInitialize may not have been be called).
+
+ COleTls tls;
+ CAptCallCtrl *pCallCtrl = tls->pCallCtrl;
+
+ if (pCallCtrl == NULL)
+ {
+ // OLE2 stuff has never been run and we dont yet have a CallCtrl
+ // for this thread. Go create one now. ctor adds it to the tls.
+
+ pCallCtrl = new CAptCallCtrl;
+ if (pCallCtrl == NULL)
+ {
+ intrDebugOut((DEB_ERROR,"SendRecieve2 couldn't alloc CallCtrl\n"));
+ return RPC_E_OUT_OF_RESOURCES;
+ }
+ }
+
+ // see if we can send the message, and then send it...
+
+ CALLCATEGORY CallCat = fWait ? CALLCAT_SYNCHRONOUS : CALLCAT_ASYNC;
+
+ if (pChannel->pCD != NULL)
+ {
+ // a DDE call is already in progress, dont let another DDE call out.
+ hres = E_UNEXPECTED;
+ }
+ else
+ {
+ // we dont know what interface is being called on, but we do
+ // know it is NOT IRemUnknown (IRundown) so it does not matter
+ // what we pass here as long as it is not IRemUnknown (IRundown).
+ hres = CanMakeOutCall(CallCat, IID_IUnknown);
+ }
+
+ if ( FAILED(hres) )
+ {
+ intrDebugOut((INTR_DDE, "CanMakeOutCall failed:%x\n", hres));
+ return hres;
+ }
+
+ // Note: this is to detect a premature DDE_TERMINATE
+ // here we care about if we receive a WM_DDE_TERMINATE instead ACK
+ // the next call to WaitForReply will detect this state and return
+ // since the terminate was send prematurly (Excel is one of this sucker)
+ //
+ if ( fDetectTerminate ) {
+ Assert(m_wTerminate == Terminate_None);
+ // if this flag is on terminate should not execute the default code
+ // in the window procedure
+ m_wTerminate = Terminate_Detect;
+ }
+
+
+ pChannel->iAwaitAck = iAwaitAck;
+ pChannel->dwStartTickCount = GetTickCount();
+
+ // start looking only for dde messages first
+ pChannel->msgFirst = WM_DDE_FIRST;
+ pChannel->msgLast = WM_DDE_LAST;
+ pChannel->msghwnd = pChannel->hwndCli;
+
+ pChannel->fRejected = FALSE;
+ // see if there is a thread window for lrpc communication
+ // if so we have to dispatch this messages as well
+ fPending = FALSE;
+
+ intrDebugOut((DEB_ITRACE,
+ "+++ Waiting for reply: server: %x, client %x Call#(%x) +++\n",
+ pChannel->hwndSvr,
+ pChannel->hwndCli,
+ iAutoCounter));
+
+ // prepare and enter the modal loop
+ DdeCD.hwndSvr = pChannel->hwndSvr;
+ DdeCD.hwndCli = pChannel->hwndCli;
+ DdeCD.wMsg = wMsg;
+ DdeCD.wParam = (WPARAM) pChannel->hwndCli,
+ DdeCD.lParam = lparam;
+ DdeCD.fDone = FALSE;
+ DdeCD.fFreeOnError = fFreeOnError;
+ DdeCD.pChannel = pChannel;
+
+ pChannel->pCD = &DdeCD;
+
+ //
+ // Setting this value tells DeleteChannel NOT to delete itself.
+ // If the value changes to Channel_DeleteNow while we are in
+ // the modal loop, this routine will delete the channel
+ //
+ pChannel->wChannelDeleted = Channel_InModalloop;
+
+ //
+ // hres will be the return code from the message
+ // handlers, or from the channel itself. The return
+ // code comes from calls to SetCallState. Most of the
+ // time, it will be things like RPC_E_DDE_NACK. However,
+ // it may also return OUTOFMEMORY, or other ModalLoop
+ // problems.
+ //
+
+ RPCOLEMESSAGE RpcOleMsg;
+ RpcOleMsg.Buffer = &DdeCD;
+
+ // Figure out the call category of this call by looking at the bit
+ // values in the rpc message flags.
+
+ DWORD dwMsgQInputFlag = gMsgQInputFlagTbl[CallCat];
+
+ // Now construct a modal loop object for the call that is about to
+ // be made. It maintains the call state and exits when the call has
+ // been completed, cancelled, or rejected.
+
+ CCliModalLoop CML(0, dwMsgQInputFlag);
+
+ do
+ {
+ hres = CML.SendReceive(&RpcOleMsg, &status, pChannel);
+
+ } while (hres == RPC_E_SERVERCALL_RETRYLATER);
+
+
+ if (hres != NOERROR)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "**************** CallRunModalLoop returns %x ***\n",
+ hres));
+ }
+
+ if (m_wTerminate == Terminate_Received) {
+ intrAssert(fDetectTerminate);
+ //
+ // There really wasn't an error, its just that the server decided
+ // to terminate. If we return an error here, the app may decide
+ // that things have gone awry. Excel, for example, will decide
+ // that the object could not be activated, even though it has
+ // already updated its cache information.
+ //
+ hres = NOERROR;
+ intrDebugOut((DEB_ITRACE,
+ "::WaitForReply setting hres=%x\n",
+ hres));
+ intrDebugOut((DEB_ITRACE,
+ "::WaitForReply posting TERMINATE to self hwnd=%x\n",
+ DdeCD.hwndCli));
+ // set state to normal and repost message
+ Verify (PostMessage (DdeCD.hwndCli, WM_DDE_TERMINATE,
+ (WPARAM)DdeCD.hwndSvr, (LPARAM)0));
+ }
+ m_wTerminate = Terminate_None;
+
+ //
+ // If the channel is to be deleted, then do it now. This flag would
+ // have been set in the DeleteChannel routine.
+ //
+ if (pChannel->wChannelDeleted == Channel_DeleteNow)
+ {
+ intrDebugOut((INTR_DDE,
+ "::WaitForReply(%x) Channel_DeleteNow pChannel(%x)\n",
+ pChannel));
+
+ // If the channel is closed then its pointer in the DdeChannel must
+ // be NULL. This assumes that the passed in "pChannel" is always
+ // equal to either the "Doc" or "Sys" member channels.
+ // This code fragment is patterned after a code fragment
+ // found in CDdechannel::DeleteChannel().
+
+ if(0 == pChannel->ReleaseReference())
+ {
+ if(pChannel == m_pDocChannel)
+ {
+ m_pDocChannel = NULL;
+ }
+ else
+ {
+ Assert(pChannel == m_pSysChannel);
+ m_pSysChannel = NULL;
+ }
+ }
+
+ // Excel will send TERMINATE before sending an ACK to StdCloseDoc
+ return ResultFromScode (fStdCloseDoc ? DDE_CHANNEL_DELETED : RPC_E_DDE_POST);
+ }
+ pChannel->wChannelDeleted = 0;
+
+ pChannel->iAwaitAck = 0;
+ pChannel->pCD = NULL;
+
+ intrDebugOut((DEB_ITRACE,
+ "### Waiting for reply done: server: %x, client %x hres(%x)###\n",
+ pChannel->hwndSvr,
+ pChannel->hwndCli,
+ hres));
+
+ return hres;
+#endif _MAC
+}
+
+// Provided IRpcChannelBuffer2 methods
+HRESULT DDE_CHANNEL::SendReceive2(
+ /* [out][in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+ /* [out] */ ULONG __RPC_FAR *pStatus)
+{
+ pCD = (DDECALLDATA *) pMessage->Buffer;
+
+ if(!wPostMessageToServer(pCD->pChannel,
+ pCD->wMsg,
+ pCD->lParam,
+ pCD->fFreeOnError))
+ {
+ intrDebugOut((DEB_ITRACE, "SendRecieve2(%x)wPostMessageToServer failed", this));
+ return RPC_E_SERVER_DIED;
+ }
+
+
+ CAptCallCtrl *pCallCtrl = GetAptCallCtrl();
+
+ CCliModalLoop *pCML = pCallCtrl->GetTopCML();
+
+ hres = S_OK;
+ BOOL fWait = !pCD->fDone;
+
+ while (fWait)
+ {
+ HRESULT hr = OleModalLoopBlockFn(NULL, pCML, NULL);
+
+ if (pCD->fDone)
+ {
+ fWait = FALSE;
+ }
+ else if (hr != RPC_S_CALLPENDING)
+ {
+ fWait = FALSE;
+ hres = hr; // return result from OleModalLoopBlockFn()
+ }
+ }
+
+ if (FAILED(hres))
+ {
+ intrDebugOut((DEB_ITRACE, "**** CallRunModalLoop returns %x ***\n", hres));
+ }
+ return hres;
+}
+
+
+void DDE_CHANNEL::SetCallState(SERVERCALLEX ServerCall, HRESULT hr)
+{
+ CallState = ServerCall;
+ hres = hr;
+ Win4Assert(pCD);
+ pCD->fDone = TRUE;
+}
diff --git a/private/ole32/com/dde/client/packmnkr.cxx b/private/ole32/com/dde/client/packmnkr.cxx
new file mode 100644
index 000000000..eddc1adde
--- /dev/null
+++ b/private/ole32/com/dde/client/packmnkr.cxx
@@ -0,0 +1,333 @@
+/*
+ PackMnkr.cpp
+ PackageMoniker
+
+ This module implements the CPackagerMoniker class and
+ CreatePackagerMoniker()
+
+ Author:
+ Jason Fuller jasonful Nov-2-1992
+
+ Copyright (c) 1992 Microsoft Corporation
+*/
+
+#include <ole2int.h>
+#include "packmnkr.h"
+#include "..\server\ddedebug.h"
+#include <ole1cls.h>
+#include <winerror.h>
+
+ASSERTDATA
+
+
+STDMETHODIMP CPackagerMoniker::QueryInterface
+ (REFIID riid, LPVOID * ppvObj)
+{
+ M_PROLOG(this);
+ VDATEIID (riid);
+ VDATEPTROUT (ppvObj, LPVOID);
+
+ if ((riid == IID_IMoniker) || (riid == IID_IUnknown) ||
+ (riid == IID_IPersistStream) || (riid == IID_IInternalMoniker))
+ {
+ *ppvObj = this;
+ ++m_refs;
+ return NOERROR;
+ }
+ AssertSz (0, "Could not find interface\r\n");
+ *ppvObj = NULL;
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+}
+
+
+
+STDMETHODIMP_(ULONG) CPackagerMoniker::AddRef()
+{
+ M_PROLOG(this);
+ return ++m_refs;
+}
+
+
+
+STDMETHODIMP_(ULONG) CPackagerMoniker::Release()
+{
+ M_PROLOG(this);
+ Assert (m_refs > 0);
+ if (0 == --m_refs)
+ {
+ if (m_pmk)
+ {
+ m_pmk->Release();
+ }
+
+ if (m_szFile)
+ {
+ delete m_szFile;
+ }
+
+ delete this;
+ return 0;
+ }
+ return m_refs;
+}
+
+
+
+STDMETHODIMP CPackagerMoniker::GetClassID (THIS_ LPCLSID lpClassID)
+{
+ M_PROLOG(this);
+ *lpClassID = CLSID_PackagerMoniker;
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP CPackagerMoniker::BindToObject (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID * ppvResult)
+{
+ M_PROLOG(this);
+ WIN32_FIND_DATA fd;
+ HRESULT hr;
+
+ COleTls Tls;
+ if( Tls->dwFlags & OLETLS_DISABLE_OLE1DDE )
+ {
+ // If this app doesn't want or can tolerate having a DDE
+ // window then currently it can't use OLE1 classes because
+ // they are implemented using DDE windows.
+ //
+ return CO_E_OLE1DDE_DISABLED;
+ }
+
+ // The following code ensures that the file exists before we try to bind it.
+ HANDLE hFind = FindFirstFile(m_szFile, &fd);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ hr = DdeBindToObject (m_szFile, CLSID_Package, m_fLink, riidResult, ppvResult);
+ FindClose(hFind);
+ }
+ else
+ hr = MK_E_CANTOPENFILE;
+ return hr;
+}
+
+STDMETHODIMP CPackagerMoniker::IsRunning (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning)
+{
+ M_PROLOG(this);
+ VDATEIFACE (pbc);
+
+ if (pmkToLeft)
+ VDATEIFACE (pmkToLeft);
+ if (pmkNewlyRunning)
+ VDATEIFACE (pmkNewlyRunning);
+
+ // There is no way to tell if a packaged object is running
+ return ReportResult (0, S_FALSE, 0, 0);
+}
+
+
+STDAPI CreatePackagerMoniker(LPOLESTR szFile,LPMONIKER *ppmk,BOOL fLink)
+{
+ return CPackagerMoniker::Create (szFile,NULL,fLink,ppmk);
+}
+
+STDAPI CreatePackagerMonikerEx(LPOLESTR szFile,LPMONIKER lpFileMoniker,BOOL fLink,LPMONIKER * ppmk)
+{
+ return CPackagerMoniker::Create (szFile,lpFileMoniker,fLink,ppmk);
+}
+
+
+HRESULT CPackagerMoniker::Create(LPOLESTR szFile,LPMONIKER lpFileMoniker, BOOL fLink, LPMONIKER * ppmk)
+{
+HRESULT hresult = E_OUTOFMEMORY;
+CPackagerMoniker *pmkPack = NULL;
+
+ VDATEPTROUT (ppmk, LPMONIKER);
+ *ppmk = NULL;
+
+ if (NULL == szFile)
+ {
+ return MK_E_SYNTAX;
+ }
+
+ pmkPack = new CPackagerMoniker;
+ if (NULL != pmkPack)
+ {
+ pmkPack->m_fLink = fLink;
+ pmkPack->m_refs = 1;
+
+ // an exception could be caused by szFile being bogus
+ __try
+ {
+ pmkPack->m_szFile = new WCHAR [lstrlenW(szFile)+1];
+ if (NULL != pmkPack->m_szFile)
+ {
+ lstrcpyW (pmkPack->m_szFile, szFile);
+
+ // If we weren't given a FileMoniker try to create one now, else just hold on to the one given.
+ if (NULL == lpFileMoniker)
+ {
+ if (NOERROR == (hresult = CreateFileMoniker (szFile, &(pmkPack->m_pmk))))
+ {
+ *ppmk = pmkPack;
+ }
+ }
+ else
+ {
+ pmkPack->m_pmk = lpFileMoniker;
+ pmkPack->m_pmk->AddRef();
+ *ppmk = pmkPack;
+ hresult = NOERROR;
+ }
+ }
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ hresult = MK_E_SYNTAX;
+ }
+
+ }
+
+ if ((NOERROR != hresult) && pmkPack)
+ {
+ Assert(0);
+ pmkPack->Release();
+ }
+
+ return hresult;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////
+// The rest of these methods just delegate to m_pmk
+// or return some error code.
+
+
+STDMETHODIMP CPackagerMoniker::IsDirty (THIS)
+{
+ M_PROLOG(this);
+ return ReportResult(0, S_FALSE, 0, 0);
+ // monikers are immutable so they are either always dirty or never dirty.
+ //
+}
+
+STDMETHODIMP CPackagerMoniker::Load (THIS_ LPSTREAM pStm)
+{
+ M_PROLOG(this);
+ return m_pmk->Load(pStm);
+}
+
+
+STDMETHODIMP CPackagerMoniker::Save (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty)
+{
+ M_PROLOG(this);
+ return m_pmk->Save(pStm, fClearDirty);
+}
+
+
+STDMETHODIMP CPackagerMoniker::GetSizeMax (THIS_ ULARGE_INTEGER * pcbSize)
+{
+ M_PROLOG(this);
+ return m_pmk->GetSizeMax (pcbSize);
+}
+
+ // *** IMoniker methods ***
+STDMETHODIMP CPackagerMoniker::BindToStorage (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID * ppvObj)
+{
+ M_PROLOG(this);
+ *ppvObj = NULL;
+ return ReportResult(0, E_NOTIMPL, 0, 0);
+}
+
+STDMETHODIMP CPackagerMoniker::Reduce (THIS_ LPBC pbc, DWORD dwReduceHowFar, LPMONIKER *
+ ppmkToLeft, LPMONIKER * ppmkReduced)
+{
+ M_PROLOG(this);
+ return m_pmk->Reduce (pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced);
+}
+
+STDMETHODIMP CPackagerMoniker::ComposeWith (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNotGeneric,
+ LPMONIKER * ppmkComposite)
+{
+ M_PROLOG(this);
+ return m_pmk->ComposeWith (pmkRight, fOnlyIfNotGeneric, ppmkComposite);
+}
+
+STDMETHODIMP CPackagerMoniker::Enum (THIS_ BOOL fForward, LPENUMMONIKER * ppenumMoniker)
+{
+ M_PROLOG(this);
+ return m_pmk->Enum (fForward, ppenumMoniker);
+}
+
+STDMETHODIMP CPackagerMoniker::IsEqual (THIS_ LPMONIKER pmkOtherMoniker)
+{
+ M_PROLOG(this);
+ return m_pmk->IsEqual (pmkOtherMoniker);
+}
+
+STDMETHODIMP CPackagerMoniker::Hash (THIS_ LPDWORD pdwHash)
+{
+ M_PROLOG(this);
+ return m_pmk->Hash (pdwHash);
+}
+
+STDMETHODIMP CPackagerMoniker::GetTimeOfLastChange (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME * pfiletime)
+{
+ M_PROLOG(this);
+ return m_pmk->GetTimeOfLastChange (pbc, pmkToLeft, pfiletime);
+}
+
+STDMETHODIMP CPackagerMoniker::Inverse (THIS_ LPMONIKER * ppmk)
+{
+ M_PROLOG(this);
+ return m_pmk->Inverse (ppmk);
+}
+
+STDMETHODIMP CPackagerMoniker::CommonPrefixWith (LPMONIKER pmkOther, LPMONIKER *
+ ppmkPrefix)
+{
+ M_PROLOG(this);
+ return m_pmk->CommonPrefixWith (pmkOther, ppmkPrefix);
+}
+
+STDMETHODIMP CPackagerMoniker::RelativePathTo (THIS_ LPMONIKER pmkOther, LPMONIKER *
+ ppmkRelPath)
+{
+ M_PROLOG(this);
+ return m_pmk->RelativePathTo (pmkOther, ppmkRelPath);
+}
+
+STDMETHODIMP CPackagerMoniker::GetDisplayName (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPOLESTR * lplpszDisplayName)
+{
+ M_PROLOG(this);
+ return m_pmk->GetDisplayName (pbc, pmkToLeft, lplpszDisplayName);
+}
+
+STDMETHODIMP CPackagerMoniker::ParseDisplayName (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPOLESTR lpszDisplayName, ULONG * pchEaten,
+ LPMONIKER * ppmkOut)
+{
+ M_PROLOG(this);
+ return m_pmk->ParseDisplayName (pbc, pmkToLeft, lpszDisplayName, pchEaten,
+ ppmkOut);
+}
+
+
+STDMETHODIMP CPackagerMoniker::IsSystemMoniker (THIS_ LPDWORD pdwMksys)
+{
+ M_PROLOG(this);
+ VDATEPTROUT (pdwMksys, DWORD);
+
+ *pdwMksys = MKSYS_NONE;
+ return NOERROR;
+}
+
+
+
+
diff --git a/private/ole32/com/dde/client/packmnkr.h b/private/ole32/com/dde/client/packmnkr.h
new file mode 100644
index 000000000..cf91ef62d
--- /dev/null
+++ b/private/ole32/com/dde/client/packmnkr.h
@@ -0,0 +1,63 @@
+/*
+ packmnkr.h
+*/
+
+class CPackagerMoniker : public IMoniker
+{
+ public:
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) ( REFIID riid, LPVOID * ppvObj) ;
+ STDMETHOD_(ULONG,AddRef) () ;
+ STDMETHOD_(ULONG,Release) () ;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) ( LPCLSID lpClassID) ;
+
+ // *** IPersistStream methods ***
+ STDMETHOD(IsDirty) () ;
+ STDMETHOD(Load) ( LPSTREAM pStm) ;
+ STDMETHOD(Save) ( LPSTREAM pStm,
+ BOOL fClearDirty) ;
+ STDMETHOD(GetSizeMax) ( ULARGE_INTEGER * pcbSize) ;
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) ( LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID * ppvResult) ;
+ STDMETHOD(BindToStorage) ( LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID * ppvObj) ;
+ STDMETHOD(Reduce) ( LPBC pbc, DWORD dwReduceHowFar, LPMONIKER *
+ ppmkToLeft, LPMONIKER * ppmkReduced) ;
+ STDMETHOD(ComposeWith) ( LPMONIKER pmkRight, BOOL fOnlyIfNotGeneric,
+ LPMONIKER * ppmkComposite) ;
+ STDMETHOD(Enum) ( BOOL fForward, LPENUMMONIKER * ppenumMoniker)
+ ;
+ STDMETHOD(IsEqual) ( LPMONIKER pmkOtherMoniker) ;
+ STDMETHOD(Hash) ( LPDWORD pdwHash) ;
+ STDMETHOD(IsRunning) ( LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+ pmkNewlyRunning) ;
+ STDMETHOD(GetTimeOfLastChange) ( LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME * pfiletime) ;
+ STDMETHOD(Inverse) ( LPMONIKER * ppmk) ;
+ STDMETHOD(CommonPrefixWith) ( LPMONIKER pmkOther, LPMONIKER *
+ ppmkPrefix) ;
+ STDMETHOD(RelativePathTo) ( LPMONIKER pmkOther, LPMONIKER *
+ ppmkRelPath) ;
+ STDMETHOD(GetDisplayName) ( LPBC pbc, LPMONIKER pmkToLeft,
+ LPOLESTR * lplpszDisplayName) ;
+ STDMETHOD(ParseDisplayName) ( LPBC pbc, LPMONIKER pmkToLeft,
+ LPOLESTR lpszDisplayName, ULONG * pchEaten,
+ LPMONIKER * ppmkOut) ;
+ STDMETHOD(IsSystemMoniker) ( LPDWORD pdwMksys) ;
+
+ static HRESULT Create ( LPOLESTR szFile,LPMONIKER lpFileMoniker,BOOL fLink,LPMONIKER * ppmk) ;
+
+ private:
+
+ ULONG m_refs;
+ LPOLESTR m_szFile;
+ LPMONIKER m_pmk;
+ BOOL m_fLink;
+
+
+};
+
diff --git a/private/ole32/com/dde/client/trgt_dev.h b/private/ole32/com/dde/client/trgt_dev.h
new file mode 100644
index 000000000..a2de2d4b3
--- /dev/null
+++ b/private/ole32/com/dde/client/trgt_dev.h
@@ -0,0 +1,19 @@
+// trgt_dev.h
+
+// OLE 1.0 Target Device
+
+typedef struct _OLETARGETDEVICE
+{
+ USHORT otdDeviceNameOffset;
+ USHORT otdDriverNameOffset;
+ USHORT otdPortNameOffset;
+ USHORT otdExtDevmodeOffset;
+ USHORT otdExtDevmodeSize;
+ USHORT otdEnvironmentOffset;
+ USHORT otdEnvironmentSize;
+ BYTE otdData[1];
+} OLETARGETDEVICE;
+
+typedef OLETARGETDEVICE const FAR* LPCOLETARGETDEVICE;
+typedef OLETARGETDEVICE FAR* LPOLETARGETDEVICE;
+
diff --git a/private/ole32/com/dde/dirs b/private/ole32/com/dde/dirs
new file mode 100644
index 000000000..8d723ece9
--- /dev/null
+++ b/private/ole32/com/dde/dirs
@@ -0,0 +1,36 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS= client server
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS=
+
diff --git a/private/ole32/com/dde/server/daytona/makefile b/private/ole32/com/dde/server/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/dde/server/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/dde/server/daytona/sources b/private/ole32/com/dde/server/daytona/sources
new file mode 100644
index 000000000..6b5d83a57
--- /dev/null
+++ b/private/ole32/com/dde/server/daytona/sources
@@ -0,0 +1,86 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+!include ..\..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= ddesvr
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES = ..\.;..\..\client;..\..\..\..\common\daytona;..\..\..\..\ih
+INCLUDES = $(INCLUDES);..\..\..\dcomrem;..\..\..\inc;..\..\..\dcomidl\daytona;
+INCLUDES = $(INCLUDES);..\..\..\class;..\..\..\objact;
+INCLUDES = $(INCLUDES);..\..\..\..\ole232\inc
+INCLUDES = $(INCLUDES);$(BASEDIR)\private\dcomidl\obj
+
+
+C_DEFINES= -DOLE_DDE_NO_GLOBAL_TRACKING=1\
+ $(C_DEFINES)
+
+
+SOURCES= \
+ ..\ddeadv.cxx \
+ ..\ddesink.cxx \
+ ..\ddesite.cxx \
+ ..\ddesrvr.cxx \
+ ..\ddeutils.cxx \
+ ..\doc.cxx \
+ ..\item.cxx \
+ ..\item2.cxx \
+ ..\itemutil.cxx \
+ ..\srvr.cxx \
+ ..\srvrmain.cxx
+
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+# PRECOMPILED_INCLUDE= ..\headers.cxx
diff --git a/private/ole32/com/dde/server/ddeadv.cxx b/private/ole32/com/dde/server/ddeadv.cxx
new file mode 100644
index 000000000..0d03789ed
--- /dev/null
+++ b/private/ole32/com/dde/server/ddeadv.cxx
@@ -0,0 +1,132 @@
+// ddeadv.cpp
+//
+// Mapping from DDE advise to/from OLE 2.0 advises
+//
+// Author:
+// Jason Fuller jasonful 8-16-92
+//
+// Copyright (c) 1992 Microsoft Corporation
+
+#include "ole2int.h"
+#include "srvr.h"
+#include "ddedebug.h"
+ASSERTDATA
+
+
+INTERNAL CDefClient::DoOle20Advise
+ (OLE_NOTIFICATION options,
+ CLIPFORMAT cf)
+{
+ HRESULT hresult = NOERROR;
+ FORMATETC formatetc;
+ formatetc.cfFormat = cf;
+ formatetc.ptd = m_ptd;
+ formatetc.lindex = DEF_LINDEX;
+ formatetc.dwAspect = DVASPECT_CONTENT;
+ // only types 1.0 client wants
+ formatetc.tymed = TYMED_HGLOBAL | TYMED_MFPICT | TYMED_GDI;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::DoOle20Advise(options=%x,cf=%x)\n",
+ this,
+ options,
+ (ULONG)cf));
+ ChkC(this);
+ switch (options)
+ {
+ case OLE_CHANGED:
+#ifdef UPDATE
+ case OLE_SAVED:
+#endif
+ if (0 == m_dwConnectionDataObj)
+ {
+ Assert (m_lpdataObj);
+ RetErr (m_lpdataObj->DAdvise (&formatetc,0/* ADVF_PRIMEFIRST*/,
+ &m_AdviseSink,
+ &m_dwConnectionDataObj));
+ Assert (m_dwConnectionDataObj != 0);
+ }
+ // Fall through:
+ // Even for OLE_CHANGED do an Ole Advise so we get OnClose
+ // notifications for linked objects.
+
+#ifndef UPDATE
+ case OLE_SAVED:
+#endif
+ case OLE_RENAMED: // Link case
+ case OLE_CLOSED:
+ Assert (m_lpoleObj);
+ // Only do one OleObject::Advise even if 1.0 client asks
+ // for two advises for two different formats and two events,
+ // i.e., native and metafile, save and close.
+ if (m_lpoleObj && 0==m_dwConnectionOleObj)
+ {
+ Puts ("Calling OleObject::Advise\r\n");
+ Assert (m_dwConnectionOleObj == 0L);
+ hresult = m_lpoleObj->Advise (&m_AdviseSink, &m_dwConnectionOleObj);
+ if (hresult != NOERROR)
+ {
+ goto errRtn;
+ }
+ }
+ Assert (m_dwConnectionOleObj != 0);
+ break;
+
+ default:
+ Assert(0);
+ break;
+ }
+
+errRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::DoOle20Advise hresult=%x\n",
+ this,hresult));
+
+
+ return NOERROR;
+}
+
+
+
+
+INTERNAL CDefClient::DoOle20UnAdviseAll
+ (void)
+{
+ HRESULT hr;
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::DoOle20UnAdviseAll\n",
+ this));
+
+ ChkC(this);
+ if (m_dwConnectionOleObj != 0L)
+ {
+ if (m_lpoleObj)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%x ::DoOle20UnAdviseAll unadvise OLE obj\n",
+ this));
+ Puts ("Unadvising ole obj\r\n");
+ hr = m_lpoleObj->Unadvise (m_dwConnectionOleObj);
+ intrAssert(hr == NOERROR);
+ m_dwConnectionOleObj = 0L;
+ }
+ }
+ if (m_dwConnectionDataObj != 0L)
+ {
+ if (m_lpdataObj)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%x ::DoOle20UnAdviseAll unadvise DATA obj\n",
+ this));
+ Puts ("Unadvising data obj\r\n");
+ hr = m_lpdataObj->DUnadvise (m_dwConnectionDataObj);
+ intrAssert(hr == NOERROR);
+ m_dwConnectionDataObj = 0L;
+ }
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::DoOle20UnAdviseAll\n",
+ this));
+
+ return NOERROR;
+}
diff --git a/private/ole32/com/dde/server/ddeatoms.h b/private/ole32/com/dde/server/ddeatoms.h
new file mode 100644
index 000000000..ba105ba17
--- /dev/null
+++ b/private/ole32/com/dde/server/ddeatoms.h
@@ -0,0 +1,42 @@
+/* ddeatoms.h */
+
+//This is here because the file is #included by both client and server files
+#define fDdeCodeInOle2Dll 1
+
+// These atoms are defined in srvrmain.cpp
+extern ATOM aEditItems;
+extern ATOM aFormats;
+extern ATOM aOLE;
+extern ATOM aProtocols;
+extern ATOM aStatus;
+extern ATOM aStdClose;
+extern ATOM aStdCreate;
+extern ATOM aStdCreateFromTemplate;
+extern ATOM aStdEdit;
+extern ATOM aStdExit;
+extern ATOM aStdOpen;
+extern ATOM aStdShowItem;
+extern ATOM aSysTopic;
+extern ATOM aTopics;
+
+// defined in ddewnd.cpp
+extern ATOM aChange;
+extern ATOM aClose;
+extern ATOM aMSDraw;
+extern ATOM aNullArg;
+extern ATOM aOle;
+extern ATOM aSave;
+extern ATOM aStdColorScheme;
+extern ATOM aStdDocDimensions;
+extern ATOM aStdDocName;
+extern ATOM aStdHostNames;
+extern ATOM aStdTargetDevice ;
+extern ATOM aSystem;
+
+// defined in ddewnd.cpp
+extern CLIPFORMAT cfBinary; // "Binary format"
+extern CLIPFORMAT cfNative; // "NativeFormat"
+
+// defined in srvrmain.cpp
+extern CLIPFORMAT cfLink; // "ObjectLink"
+extern CLIPFORMAT cfOwnerLink; // "Ownerlink"
diff --git a/private/ole32/com/dde/server/ddedebug.h b/private/ole32/com/dde/server/ddedebug.h
new file mode 100644
index 000000000..dfb7401e6
--- /dev/null
+++ b/private/ole32/com/dde/server/ddedebug.h
@@ -0,0 +1,99 @@
+// ddeDebug.h
+//
+// Generic debug routines
+//
+// Author:
+// Jason Fuller jasonful 8-16-92
+//
+
+#ifndef fDdedebug_h
+#define fDdedebug_h
+
+#define INTR_DDE 0x00010000
+#define INTR_CHNL 0x00020000
+#define INTR_PARAM 0x00040000
+
+//#define fDebugOutput
+#define WIDECHECK(x) (x?x:L"<NULL>")
+#define ANSICHECK(x) (x?x:"<NULL>")
+
+#if DBG == 1
+#define DEBUG_GUIDSTR(name,guid) WCHAR name [48]; StringFromGUID2( *guid , name , sizeof( name ));
+#else
+#define DEBUG_GUIDSTR(name,guid)
+#endif
+#ifdef _DEBUG
+
+ // defined in clientddeworkr.cpp
+ BOOL wIsValidHandle (HANDLE, CLIPFORMAT);
+ BOOL wIsValidAtom (ATOM);
+
+ #define DebugOnly(x) x
+ #define ChkC(p) Assert (p && p->m_chk==chkDefClient)
+ #define ChkS(p) Assert (p && p->m_chk==chkDdeSrvr)
+ #define ChkD(p) Assert ((p) && (p)->m_chk==chkDdeObj)
+ #define AssertIsDoc(p) Assert ((p) && (p)->m_pdoc==(p) && (p)->m_bContainer)
+
+ #define ChkCR(p) RetZ (p && p->m_chk==chkDefClient)
+ #define ChkSR(p) RetZ (p && p->m_chk==chkDdeSrvr)
+ #define ChkDR(p) RetZ ((p) && (p)->m_chk==chkDdeObj)
+ #define AssertIsDocR(p) RetZ ((p) && (p)->m_pdoc==(p) && (p)->m_bContainer)
+
+ #ifdef fDebugOutput
+
+ #define Puti(i) do {char sz[50]; wsprintf(sz, " %lu ", (unsigned long) (i)); Puts(sz);} while(0)
+ #define Puth(i) do {char sz[50]; wsprintf(sz, " 0x%lx ", (unsigned long) (i)); Puts(sz);} while(0)
+ #define Puta(a) do {char sz[50]="NULL"; if (a) GlobalGetAtomName(a,sz,50); \
+ Puth(a); Puts("\""); Puts(sz); Puts("\" "); } while(0)
+ #define Putsi(i) do { Puts(#i " = "); Puti(i); Puts("\n");} while (0)
+ #define Putn() Puts("\r\n")
+
+ #else
+
+ #undef Puts
+ #define Puts(i) ((void)0)
+ #define Puti(i) ((void)0)
+ #define Puth(i) ((void)0)
+ #define Puta(a) ((void)0)
+ #define Putsi(i) ((void)0)
+ #define Putn() ((void)0)
+
+ #endif // fDebugOutput
+ #define DEBUG_OUT(a,b) OutputDebugStringA(a);
+#else
+ #define DEBUG_OUT(a,b)
+ #define Puti(i) ((void)0)
+ #define Puth(i) ((void)0)
+ #define Puta(a) ((void)0)
+ #define Putsi(i) ((void)0)
+ #define Putn() ((void)0)
+ #define wIsValidHandle(h,cf) (TRUE)
+ #define wIsValidAtom(a) (TRUE)
+ #define DebugOnly(x)
+ #define ChkC(p)
+ #define ChkS(p)
+ #define ChkD(p)
+ #define AssertIsDoc(p)
+ #define ChkCR(p)
+ #define ChkSR(p)
+ #define ChkDR(p)
+ #define AssertIsDocR(p)
+
+#endif // _DEBUG
+
+
+// Stuff common to both client and server directories
+
+#define POSITIVE_ACK (0x8000)
+#define NEGATIVE_ACK (0x0000)
+
+#include <reterr.h>
+
+INTERNAL_(LPOLESTR) wAtomName (ATOM atom);
+INTERNAL_(LPSTR) wAtomNameA (ATOM atom);
+INTERNAL_(ATOM) wDupAtom (ATOM aSrc);
+
+INTERNAL wClassesMatch (REFCLSID clsid, LPOLESTR szFile);
+INTERNAL wWriteFmtUserType (LPSTORAGE, REFCLSID);
+
+#endif // fDdedebug_h
diff --git a/private/ole32/com/dde/server/ddeerr.h b/private/ole32/com/dde/server/ddeerr.h
new file mode 100644
index 000000000..f35a88b63
--- /dev/null
+++ b/private/ole32/com/dde/server/ddeerr.h
@@ -0,0 +1,78 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ddeerr.h
+//
+// Contents: Error codes from the previous release
+//
+// Classes:
+//
+// Functions:
+//
+// History: 4-26-94 kevinro Commented/cleaned
+//
+// This is actually the contents from ole2anac.h, with some parts removed.
+// Specifically, including ole2anac.h renamed DAdvise and friends, which
+// is bad.
+//----------------------------------------------------------------------------
+#if !defined( _OLE2ANAC_H_ )
+#define _OLE2ANAC_H_
+
+typedef enum tagSTGSTATE
+{
+ STGSTATE_DOC = 1,
+ STGSTATE_CONVERT = 2,
+ STGSTATE_FILESTGSAME = 4
+} STGSTATE;
+
+
+#define MK_E_EXCEEDED_DEADLINE MK_E_EXCEEDEDDEADLINE
+#define MK_E_NEED_GENERIC MK_E_NEEDGENERIC
+#define MK_E_INVALID_EXTENSION MK_E_INVALIDEXTENSION
+#define MK_E_INTERMEDIATE_INTERFACE_NOT_SUPPORTED \
+ MK_E_INTERMEDIATEINTERFACENONOT_SUPPORTED
+#define MK_E_NOT_BINDABLE MK_E_NOTBINDABLE
+#define S_TRUE S_OK
+
+#define E_BLANK OLE_E_BLANK
+#define E_STATIC OLE_E_STATIC
+#define E_NOTRUNNING OLE_E_NOTRUNNING
+#define E_FORMAT DV_E_CLIPFORMAT
+#define OLE_E_CLSID REGDB_E_CLASSNOTREG
+#define OLE_E_NOTSUPPORTED E_NOTIMPL
+#define OLE_E_REGDB_KEY REGDB_E_KEYMISSING
+#define OLE_E_REGDB_FMT REGDB_E_INVALIDVALUE
+
+
+#define OLEVERB_PRIMARY OLEIVERB_PRIMARY
+#define OLEVERB_SHOW OLEIVERB_SHOW
+
+// these DDE error codes are not returned anymore; these definitions are
+// here just to make existing code compile without changes.
+#define RPC_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_RPC, 0x000)
+#define RPC_E_DDE_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_RPC, 0x100)
+
+#define RPC_E_DDE_BUSY (RPC_E_DDE_FIRST + 0x0)
+#define RPC_E_DDE_CANT_UPDATE (RPC_E_DDE_FIRST + 0x1)
+#define RPC_E_DDE_INIT (RPC_E_DDE_FIRST + 0x2)
+#define RPC_E_DDE_NACK E_FAIL
+#define RPC_E_DDE_LAUNCH CO_E_APPNOTFOUND
+#define RPC_E_DDE_POST RPC_E_SERVER_DIED
+#define RPC_E_DDE_PROTOCOL (RPC_E_DDE_FIRST + 0x6)
+#define RPC_E_DDE_REVOKE (RPC_E_DDE_FIRST + 0x7)
+#define RPC_E_DDE_SYNTAX_EXECUTE RPC_E_INVALID_PARAMETER
+#define RPC_E_DDE_SYNTAX_ITEM RPC_E_INVALID_PARAMETER
+#define RPC_E_DDE_UNEXP_MSG (RPC_E_DDE_FIRST + 0xa)
+#define RPC_E_DDE_DATA RPC_E_INVALID_PARAMETER
+
+
+#define RPC_E_CONNECTION_LOST (RPC_E_FIRST + 0x6)
+#define RPC_E_BUSY (RPC_E_FIRST + 0x0)
+#define RPC_E_MSG_REJECTED (RPC_E_FIRST + 0x1)
+#define RPC_E_CANCELLED (RPC_E_FIRST + 0x2)
+#define RPC_E_DISPATCH_ASYNCCALL (RPC_E_FIRST + 0x4)
+
+
+#endif // _OLE2ANAC_H_
diff --git a/private/ole32/com/dde/server/ddeint.h b/private/ole32/com/dde/server/ddeint.h
new file mode 100644
index 000000000..c59274f9e
--- /dev/null
+++ b/private/ole32/com/dde/server/ddeint.h
@@ -0,0 +1,181 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ddeint.h
+//
+// Contents: This file contains shared macros/state between the server
+// and client directories
+// Classes:
+//
+// Functions:
+//
+// History: 5-04-94 kevinro Commented/cleaned
+//
+//----------------------------------------------------------------------------
+
+//
+// BUGBUG: (KevinRo) The new definition of DVTARGETDEVICE uses an unsized array
+// of bytes at the end. Therefore, the sizeof operator no longer works. So, I
+// have calculated the size of the cbHeader by accounting for each member of
+// the structure independently. I am not too proud of this at the moment,
+// but need to move on.
+//
+
+#define DEB_DDE_INIT (DEB_ITRACE|DEB_USER1)
+
+// global OLE class used to create windows in OLE.
+extern LPTSTR gOleWindowClass;
+extern HINSTANCE g_hinst;
+
+// names of the DDE window classes
+#ifdef _CHICAGO_
+// Note: we have to create a unique string so that we
+// register a unique class for each 16 bit app.
+// The class space is global on chicago.
+//
+
+extern LPSTR szOLE_CLASSA;
+extern LPSTR szSYS_CLASSA;
+
+#define OLE_CLASSA szOLE_CLASSA
+#define SRVR_CLASSA szSRVR_CLASSA
+
+#define DDEWNDCLASS WNDCLASSA
+#define DdeRegisterClass RegisterClassA
+#define DdeUnregisterClass UnregisterClassA
+#define DdeCreateWindowEx SSCreateWindowExA
+
+#else
+
+#define OLE_CLASS L"Ole2WndClass"
+#define OLE_CLASSA "Ole2WndClass"
+
+#define SRVR_CLASS (OLESTR("SrvrWndClass"))
+#define SRVR_CLASSA ("SrvrWndClass")
+
+#define DDEWNDCLASS WNDCLASS
+#define DdeRegisterClass RegisterClass
+#define DdeUnregisterClass UnregisterClass
+#define DdeCreateWindowEx CreateWindowEx
+
+#endif // !_CHICAGO_
+
+STDAPI_(LRESULT) DocWndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+STDAPI_(LRESULT) SrvrWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+STDAPI_(LRESULT) SysWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+STDAPI_(LRESULT) ClientDocWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+BOOL SendMsgToChildren (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+#define SIZEOF_DVTARGETDEVICE_HEADER (sizeof(DWORD) + (sizeof(WORD) * 4))
+
+// forward declarations
+class CDefClient;
+typedef CDefClient FAR *LPCLIENT;
+
+class CDDEServer;
+typedef CDDEServer FAR *LPSRVR;
+typedef CDDEServer FAR *HDDE; // used by ClassFactory table
+
+
+typedef struct tagDISPATCHDATA
+{
+ SCODE scode; // might be no necessary
+ LPVOID pData; // pointer to channel data
+} DISPATCHDATA, *PDISPATCHDATA;
+
+
+// SERVERCALLEX is an extension of SERVERCALL and represents the set of
+// valid responses from IMessageFilter::HandleIncoming Call.
+
+typedef enum tagSERVERCALLEX
+{
+ SERVERCALLEX_ISHANDLED = 0, // server can handle the call now
+ SERVERCALLEX_REJECTED = 1, // server can not handle the call
+ SERVERCALLEX_RETRYLATER = 2, // server suggests trying again later
+ SERVERCALLEX_ERROR = 3, // error?
+ SERVERCALLEX_CANCELED = 5 // client suggests canceling
+} SERVERCALLEX;
+
+
+
+
+//
+// The wire representation of STDDOCDIMENSIONS is a 16-bit
+// format. This means instead of 4 longs, there are
+// 4 shorts. This structure is used below to pick the data
+// from the wire representation. Amazingly stupid, but
+// backward compatible is the name of the game.
+//
+typedef struct tagRECT16
+{
+ SHORT left;
+ SHORT top;
+ SHORT right;
+ SHORT bottom;
+
+} RECT16, *LPRECT16;
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertToFullHWND
+//
+// Synopsis: This function is used to convert a 16-bit HWND into a 32-bit
+// hwnd
+//
+// Effects: When running in a VDM, depending on who dispatches the message
+// we can end up with either a 16 or 32 bit window message. This
+// routine is used to make sure we always deal with a 32bit
+// HWND. Otherwise, some of our comparisions are incorrect.
+//
+// Arguments: [hwnd] -- HWND to convert. 16 or 32 bit is fine
+//
+// Returns: Always returns a 32 bit HWND
+//
+// History: 8-03-94 kevinro Created
+//
+// Notes:
+// This routine calls a private function given to use by OLETHK32
+//
+//----------------------------------------------------------------------------
+inline
+HWND ConvertToFullHWND(HWND hwnd)
+{
+ if (IsWOWThreadCallable() &&
+ ((((ULONG)hwnd & 0xFFFF0000) == 0) ||
+ (((ULONG)hwnd & 0xFFFF0000) == 0xFFFF0000)))
+ {
+ return(g_pOleThunkWOW->ConvertHwndToFullHwnd(hwnd));
+ }
+ return(hwnd);
+}
+
+inline
+void OleDdeDeleteMetaFile(HANDLE hmf)
+{
+ intrDebugOut((DEB_ITRACE,
+ "OleDdeDeleteMetaFile(%x)\n",
+ hmf));
+ if (IsWOWThreadCallable())
+ {
+ intrDebugOut((DEB_ITRACE,
+ "InWow: calling WOWFreeMetafile(%x)\n",
+ hmf));
+
+ if (!g_pOleThunkWOW->FreeMetaFile(hmf))
+ {
+ return;
+ }
+ intrDebugOut((DEB_ITRACE,
+ "WOWFreeMetafile(%x) FAILED\n",
+ hmf));
+ }
+ intrDebugOut((DEB_ITRACE,
+ "Calling DeleteMetaFile(%x)\n",
+ hmf));
+
+ DeleteMetaFile((HMETAFILE)hmf);
+}
diff --git a/private/ole32/com/dde/server/ddepack.h b/private/ole32/com/dde/server/ddepack.h
new file mode 100644
index 000000000..ef250cafb
--- /dev/null
+++ b/private/ole32/com/dde/server/ddepack.h
@@ -0,0 +1,20 @@
+
+#ifdef WIN32
+extern "C"
+{
+#include <port1632.h>
+}
+
+#define MAKE_DDE_LPARAM(msg,lo,hi) PackDDElParam(msg,(UINT)lo,(UINT)hi)
+
+#else
+
+#define GET_WM_DDE_EXECUTE_HDATA(wParam,lParam) ((HANDLE) HIWORD(lParam))
+#define GET_WM_DDE_DATA_HDATA(wParam,lParam) ((HANDLE) LOWORD(lParam))
+#define GET_WM_DDE_REQUEST_ITEM(wParam,lParam) ((ATOM) HIWORD(lParam))
+#define GET_WM_DDE_DATA_ITEM(wParam,lParam) ((ATOM) HIWORD(lParam))
+#define MAKE_DDE_LPARAM(msg,lo,hi) MAKELONG(lo,hi)
+#define DDEFREE(msg,lParam)
+
+#endif
+
diff --git a/private/ole32/com/dde/server/ddesink.cxx b/private/ole32/com/dde/server/ddesink.cxx
new file mode 100644
index 000000000..302db683e
--- /dev/null
+++ b/private/ole32/com/dde/server/ddesink.cxx
@@ -0,0 +1,251 @@
+// ddesink.cpp
+//
+// Methods for CDefClient::CAdviseSinkImpl
+//
+// Author:
+// Jason Fuller jasonful 8-16-92
+//
+// Copyright (c) 1990, 1991 Microsoft Corporation
+
+
+#include <ole2int.h>
+#include "srvr.h"
+#include "ddedebug.h"
+
+
+ASSERTDATA
+
+STDUNKIMPL_FORDERIVED (DefClient, AdviseSinkImpl)
+
+ BOOL PeekOneMessage
+ (MSG FAR* pmsg,
+ HWND hwnd,
+ UINT message)
+{
+ // We have to verify pmsg->message because PeekMessage will return
+ // WM_QUIT even if you didn't ask for it.
+
+ if (SSPeekMessage (pmsg, hwnd, message, message, PM_REMOVE))
+ {
+ if (pmsg->message==message)
+ return TRUE;
+ else
+ {
+ AssertSz (pmsg->message == WM_QUIT, "Unexpected message");
+ if (WM_QUIT==pmsg->message)
+ {
+ // Put message back
+ PostQuitMessage (pmsg->wParam);
+ }
+ return FALSE;
+ }
+ }
+ else
+ return FALSE;
+}
+
+
+
+
+
+
+STDMETHODIMP_(void) NC(CDefClient,CAdviseSinkImpl)::OnClose
+ (void)
+{
+ MSG msg;
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::OnClose\n",
+ this));
+
+ ChkC(m_pDefClient);
+
+ m_pDefClient->m_fInOnClose = TRUE;
+ // AddRef/Release safety bracket. Do not remove.
+ m_pDefClient->m_pUnkOuter->AddRef();
+
+ #ifdef _DEBUG
+ if (m_pDefClient->m_bContainer)
+ {
+ if (NOERROR != m_pDefClient->NoItemConnections())
+ Warn ("OnClose called on document before item");
+ }
+ #endif
+
+ if (m_pDefClient->m_ExecuteAck.f)
+ {
+ // in case the server closes in the middle of a DoVerb, send the ACK
+ // for the EXECUTE now to keep the messages in order.
+ m_pDefClient->SendExecuteAck (NOERROR);
+ }
+
+ if (!m_pDefClient->m_fGotStdCloseDoc)
+ {
+ // if client sent us StdCloseDocument, then he certainly
+ // is not in a state to receive callbacks
+ m_pDefClient->ItemCallBack (OLE_CLOSED);
+ }
+
+ // We have to check the message field because PeekMessage will return
+ // WM_QUIT even if you didn't ask for it.
+ if (PeekOneMessage (&msg, m_pDefClient->m_hwnd, WM_DDE_EXECUTE))
+ {
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_ACK,POSITIVE_ACK,
+ GET_WM_DDE_EXECUTE_HDATA(msg.wParam,msg.lParam));
+
+ intrDebugOut((DEB_ITRACE,
+ "%x ::OnClose found StdCloseDocument in queue\n",
+ this));
+
+ if(!PostMessageToClient ((HWND)msg.wParam,
+ WM_DDE_ACK,
+ (UINT) m_pDefClient->m_hwnd,
+ lp))
+ {
+ DDEFREE(WM_DDE_ACK,lp);
+ }
+
+ }
+
+
+ ChkC (m_pDefClient);
+
+ if (m_pDefClient->m_bContainer)
+ {
+ // If the document (container) is closing, then we
+ // should send a TERMINATE to the client windows.
+ // We don't do this for items because a client window
+ // may still be connected to another item.
+ // Items within one document share one window.
+
+ m_pDefClient->SendTerminateMsg ();
+ ChkC (m_pDefClient);
+ AssertIsDoc (m_pDefClient);
+ m_pDefClient->ReleaseAllItems();
+ }
+ else
+ {
+ m_pDefClient->RemoveItemFromItemList ();
+ }
+
+ // If item was deleted in client app, m_lpoleObj could be NULL
+ m_pDefClient->ReleaseObjPtrs ();
+
+ // If "this" is an item, get the doc that contains this item
+ LPCLIENT pdoc = m_pDefClient->m_pdoc;
+ Assert (pdoc);
+
+ Assert (pdoc->m_chk==chkDefClient);
+ if (pdoc->m_chk==chkDefClient && pdoc->m_fRunningInSDI)
+ if (pdoc->m_fRunningInSDI)
+ {
+ Puts ("Running in SDI\r\n");
+ // The server app never registered a class factory, so no
+ // RevokeClassFactory will trigger the destruction of the
+ // CDdeServer, so we do it here if there are no other clients
+ // connected to that CDdeServer
+ if (pdoc->m_psrvrParent->QueryRevokeClassFactory())
+ {
+ // Assert (No sibling documents)
+ Verify (NOERROR==pdoc->m_psrvrParent->Revoke());
+ pdoc->m_psrvrParent = NULL;
+ }
+ }
+ m_pDefClient->m_fInOnClose = FALSE;
+
+ // AddRef/Release safety bracket. Do not remove.
+ // Do not use m_pDefClient after this Release.
+ m_pDefClient->m_pUnkOuter->Release();
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::OnClose\n",
+ this));
+}
+
+
+
+
+STDMETHODIMP_(void) NC(CDefClient,CAdviseSinkImpl)::OnSave
+ (THIS)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::OnSave\n",
+ this));
+
+ ChkC(m_pDefClient);
+ if (!m_pDefClient->m_fInOleSave)
+ {
+ // If we called OleSave to get the native data, then of course
+ // we will get an OnSave notification.
+ m_pDefClient->ItemCallBack (OLE_SAVED);
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::OnSave\n",
+ this));
+}
+
+
+
+STDMETHODIMP_(void) NC(CDefClient,CAdviseSinkImpl)::OnDataChange
+ (THIS_ FORMATETC FAR* pFormatetc,
+ STGMEDIUM FAR* pStgmed)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::OnDataChange pFormatetc=%x\n",
+ this,
+ pFormatetc));
+ // note we are ignoring both the pformatetc and the pStgMed.
+ // ItemCallBack will ask (using GetData) for the data the client wants.
+ // We are treating a call to this function as a simple Ping.
+
+ ChkC(m_pDefClient);
+ m_pDefClient->ItemCallBack (OLE_CHANGED);
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::OnDataChange\n",
+ this));
+}
+
+
+
+STDMETHODIMP_(void) NC(CDefClient,CAdviseSinkImpl)::OnRename
+ (THIS_ LPMONIKER pmk)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::OnRename pmk=%x\n",
+ this,pmk));
+
+ LPOLESTR szFile=NULL;
+
+ ChkC(m_pDefClient);
+ if (Ole10_ParseMoniker (pmk, &szFile, NULL) != NOERROR)
+ {
+ // Wrong type of moniker
+ intrDebugOut((DEB_IERROR,
+ "%x ::OnRename pmk=%x wrong moniker\n",
+ this,pmk));
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%x ::OnRename pmk=%x pmk.Name=(%ws)\n",
+ this,
+ pmk,
+ WIDECHECK(szFile)));
+ // Notify client
+ m_pDefClient->ItemCallBack (OLE_RENAMED, szFile);
+ CoTaskMemFree(szFile);
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::OnRename\n",
+ this));
+}
+
+
+
+STDMETHODIMP_(void) NC(CDefClient,CAdviseSinkImpl)::OnViewChange
+ (THIS_ DWORD aspects, LONG lindex)
+{
+ // Response to IViewObjectAdvise::Advise, which we do not do
+}
+
+
diff --git a/private/ole32/com/dde/server/ddesite.cxx b/private/ole32/com/dde/server/ddesite.cxx
new file mode 100644
index 000000000..6f1a4e503
--- /dev/null
+++ b/private/ole32/com/dde/server/ddesite.cxx
@@ -0,0 +1,89 @@
+// ddesite.cpp
+//
+// Methods for CDefClient::COleClientSiteImpl
+//
+// Author:
+// Jason Fuller jasonful 8-16-92
+//
+// Copyright (c) 1990, 1991 Microsoft Corporation
+
+
+#include <ole2int.h>
+#include "srvr.h"
+#include "ddedebug.h"
+
+ASSERTDATA
+
+STDUNKIMPL_FORDERIVED (DefClient, OleClientSiteImpl)
+
+
+STDMETHODIMP NC(CDefClient,COleClientSiteImpl)::SaveObject
+ (void)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::SaveObject\n",
+ this));
+
+ ChkC(m_pDefClient);
+
+ if (!m_pDefClient->m_fGotStdCloseDoc)
+ m_pDefClient->ItemCallBack (OLE_SAVED);
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::SaveObject\n",
+ this));
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP NC(CDefClient,COleClientSiteImpl)::GetContainer
+ (LPOLECONTAINER FAR * lplpContainer)
+{
+ VDATEPTROUT( lplpContainer, LPOLECONTAINER);
+ *lplpContainer = NULL;
+
+ ChkC(m_pDefClient);
+ return ResultFromScode (E_NOTIMPL);
+}
+
+
+
+STDMETHODIMP NC(CDefClient,COleClientSiteImpl)::GetMoniker
+ (DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER FAR* ppmk)
+{
+ VDATEPTROUT( ppmk, LPMONIKER);
+ *ppmk = NULL;
+
+ ChkC(m_pDefClient);
+ // OLE 1.0 does not support linking to embeddings
+ return ReportResult(0, E_NOTIMPL, 0, 0);
+}
+
+STDMETHODIMP NC(CDefClient,COleClientSiteImpl)::ShowObject
+ (void)
+{
+ ChkC(m_pDefClient);
+ Puts ("OleClientSite::ShowObject\r\n");
+ // REVIEW: what are we supposed do?
+ return ResultFromScode (E_NOTIMPL);
+}
+
+STDMETHODIMP NC(CDefClient,COleClientSiteImpl)::OnShowWindow
+ (BOOL fShow)
+{
+ ChkC(m_pDefClient);
+ Puts ("OleClientSite::OnShowWindow\r\n");
+ // REVIEW: what are we supposed do?
+ return NOERROR;
+}
+
+STDMETHODIMP NC(CDefClient,COleClientSiteImpl)::RequestNewObjectLayout(void)
+{
+ ChkC(m_pDefClient);
+ Puts ("OleClientSite::RequestNewObjectLayout\r\n");
+ return ReportResult(0, S_FALSE, 0, 0);
+}
+
+
+
diff --git a/private/ole32/com/dde/server/ddesrvr.cxx b/private/ole32/com/dde/server/ddesrvr.cxx
new file mode 100644
index 000000000..b571c2f3a
--- /dev/null
+++ b/private/ole32/com/dde/server/ddesrvr.cxx
@@ -0,0 +1,757 @@
+/*
+ ddesrvr.cpp
+
+ Author:
+ Jason Fuller jasonful 8-11-92
+*/
+
+#include <ole2int.h>
+#include <dde.h>
+#include <olerem.h>
+#include "srvr.h"
+#include "ddeatoms.h"
+#include "ddesrvr.h"
+#include "ddedebug.h"
+#include "map_up.h"
+
+#include "map_dwp.h"
+
+ASSERTDATA
+
+// Dde Common Window stuff
+
+UINT cCommonWindows = 0;
+
+#ifdef _CHICAGO_
+// Note: we have to create a unique string so that get
+// register a unique class for each 16 bit app.
+// The class space is global on chicago.
+//
+LPSTR szOLE_CLASSA = "Ole2WndClass 0x######## ";
+LPSTR szSRVR_CLASSA = "SrvrWndClass 0x######## ";
+
+LPSTR szDdeServerWindow = "DDE Server Window";
+#define szDdeCommonWindowClass szCOMMONCLASSA
+#else
+const LPOLESTR szDdeServerWindow = OLESTR("DDE Server Window");
+const LPOLESTR szDdeCommonWindowClass = OLESTR("DdeCommonWindowClass");
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateDdeSrvrWindow
+//
+// Synopsis: When CoRegisterClassObject is called, this function
+// is called to create a DDE window to listen for DDE messages
+// from a 1.0 client.
+//
+// Effects:
+//
+// Arguments: [clsid] --
+// [aClass] --
+// [phwnd] --
+// [fIsRunning] --
+// [aOriginalClass] --
+// [cnvtyp] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-27-94 kevinro Commented/cleaned
+// 13-Jul-94 BruceMa Make register/unregister dde window class
+// thread safe
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CreateDdeSrvrWindow
+ (REFCLSID clsid,
+ ATOM aClass,
+ HWND FAR* phwnd, // optional out parm: created window
+ BOOL fIsRunning, // Is the item atom a file in the ROT?
+ ATOM aOriginalClass, // for TreatAs/ConvertTo case
+ CNVTYP cnvtyp)
+{
+ intrDebugOut((DEB_DDE_INIT,"0 _IN CreateDdeSrvrWindow\n"));
+
+ VDATEHEAP();
+ HWND hwnd = NULL;
+
+ HRESULT hresult = NOERROR;
+
+ DdeClassInfo ddeClassInfo;
+
+ ddeClassInfo.dwContextMask = CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER;
+ ddeClassInfo.fClaimFactory = FALSE;
+
+ // Null out parameter in case of error
+ if (phwnd)
+ {
+ *phwnd = NULL;
+ }
+
+ intrAssert (wIsValidAtom (aClass));
+
+ //
+ // See if this process is registered as a class server for
+ // the requested class. If it isn't, then check for a running
+ // object.
+ //
+ if (GetClassInformationForDde(clsid,&ddeClassInfo) == FALSE)
+ {
+ intrDebugOut((DEB_DDE_INIT,
+ "CreateDdeSrvrWindow No class information available\n"));
+
+ //
+ // The ClassObject was not found in the table.
+ //
+
+ if (fIsRunning)
+ {
+ // Link case.
+ // An SDI app was launched by the user (without "-Embedding").
+ // It did not register its class factory. (It never does.)
+ // Meanwhile, a DDE_INIT with a filename as an item atom was
+ // broadcasted.
+ // We are in the task of the SDI app that loaded that filename,
+ // so this function was called.
+ // So we need to create the window even though no class factory
+ // was registered.
+ // Call CDDEServer::Create with a lot of NULLs.
+ // Once the DDE_INIT is passed along to the server window, it
+ // should immediately cause a doc window to be created.
+ // Must be SDI or we wouldn't have this problem.
+ //
+ // This works because we are going to attempt to 'bind' to the
+ // object which is the subject of the link. If the link object
+ // was registered as running, we will find it. Otherwise, the
+ // attempt to create via the class factory will fail, since the
+ // class factory doesn't exist.
+ //
+
+ intrDebugOut((DEB_DDE_INIT,
+ "::CreateDdeServerWindow fIsRunning - override dwFlags\n"));
+
+ //
+ // NULL out the entire structure, then set only the flags
+ //
+ memset(&ddeClassInfo,0,sizeof(ddeClassInfo));
+ ddeClassInfo.dwFlags = REGCLS_SINGLEUSE;
+
+
+ }
+ else
+ {
+ intrDebugOut((DEB_DDE_INIT,
+ "CreateDdeServerWindow Returning FALSE\n"));
+
+ hresult = S_FALSE;
+ goto errRtn;
+ }
+ }
+ intrDebugOut((DEB_DDE_INIT,
+ "::CreateDdeServerWindow found class\n"));
+ // Create() does the real work: creates a CDDEServer and the window.
+ WCHAR szClass[MAX_STR];
+ lstrcpyW (szClass, wAtomName (aClass));
+ Assert (szClass[0]);
+
+ hresult = CDDEServer::Create(szClass,
+ clsid,
+ &ddeClassInfo,
+ &hwnd,
+ aOriginalClass,
+ cnvtyp);
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "CreateDdeServerWindow CDDEServer::Create returns %x\n",
+ hresult));
+ goto errRtn;
+ }
+
+ Assert (IsWindowValid(hwnd));
+
+ // Fill in out parameter
+ if (phwnd)
+ {
+ *phwnd = hwnd;
+ }
+
+
+errRtn:
+ VDATEHEAP();
+ intrDebugOut((DEB_DDE_INIT,
+ "0 _OUT CreateDdeSrvrWindow %x\n",
+ hresult));
+ return hresult;
+
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DestroyDdeSrvrWindow
+//
+// Synopsis: Destroy a DDE server window
+//
+// Effects:
+//
+// Arguments: [hwnd] -- Window to destroy
+// [aClass] -- Class for server
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-24-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL DestroyDdeSrvrWindow
+ (HWND hwnd,
+ ATOM aClass)
+{
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN DestroyDdeSrvrWindow\n"));
+ VDATEHEAP();
+ Assert (IsAtom (aClass));
+
+ // Make sure it is a server window
+ RetZ (IsWindowValid (hwnd));
+ RetZ (GetWindowWord (hwnd, WW_LE) == WC_LE);
+
+
+ // Get the Common window for this task.
+
+ HWND hwndCommonServer = (HWND)TLSGetDdeServer();
+
+ if (hwndCommonServer == NULL)
+ {
+ intrDebugOut((DEB_IERROR,"hwndCommonServer != NULL\n"));
+ return(E_UNEXPECTED);
+ }
+ if (!IsWindow(hwndCommonServer))
+ {
+ intrAssert(IsWindow(hwndCommonServer));
+ return(E_UNEXPECTED);
+ }
+
+ // Get the map from the common window
+ CMapUintPtr FAR *pmapClassToHwnd;
+ Assert (sizeof (CMapUintPtr FAR *)==sizeof(LONG));
+ pmapClassToHwnd = (CMapUintPtr FAR *) GetWindowLong (hwndCommonServer, 0);
+ Assert (pmapClassToHwnd);
+
+ // Make sure the window we're deleting is the server window for this class
+ void *hwndSrvr;
+ RetZ (pmapClassToHwnd->Lookup (aClass,hwndSrvr) && hwndSrvr == hwnd);
+
+ RetZ (SSDestroyWindow (hwnd));
+
+ // Remove this window from the map
+ pmapClassToHwnd->RemoveKey (aClass);
+
+ VDATEHEAP();
+ intrDebugOut((DEB_ITRACE,
+ "0 _OUT DestroyDdeSrvrWindow\n"));
+
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DdeCommonWndProc
+//
+// Synopsis: Window proc for the common dde server window that
+// listens for all WM_DDE_INITIATEs
+//
+// Effects: When a DDE_INITIATE comes in, this routine will determine
+// the class of the object being requested. If the class is
+// served by this thread, then it will create a window to
+// converse with the server.
+//
+// Arguments: [hWnd] -- hWnd of Common DDE
+// [wMsg] -- msg
+// [wParam] -- Return Window to converse with
+// [lParam] -- HIWORD(aItem) LOWORD(aClass)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-27-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+// When running in a VDM, it is possible that this window was dispatched
+// without having a full window handle. This happens when the getmessage
+// was dispatched from 16-bit. Therefore, we need to convert the hwnd to
+// a full hwnd before doing any comparision functions.
+//
+//----------------------------------------------------------------------------
+STDAPI_(LRESULT)
+DdeCommonWndProc(HWND hwndIn, UINT wMsg, WPARAM wParam, LPARAM lParam)
+{
+
+ switch (wMsg)
+ {
+ case WM_DDE_INITIATE:
+ {
+ VDATEHEAP();
+ ATOM aClass = LOWORD(lParam);
+ ATOM aItem = HIWORD(lParam);
+ HWND hwnd;
+
+ CNVTYP cnvtyp = cnvtypNone;
+
+ BOOL fIsFile= FALSE; // Must initialize
+ BOOL fIsRunning= FALSE; // Must initialize
+ BOOL fUnsavedDoc = FALSE; // Is the "file" really an unsaved doc
+ HWND hwndServer;
+ HRESULT hresult;
+
+
+ //
+ // From this point forward, we need to insure we are using a
+ // FULL hwnd.
+ //
+ hwnd = ConvertToFullHWND(hwndIn);
+
+ //
+ // The following should already be initialized
+ //
+ intrAssert (aOLE != NULL);
+ intrAssert (aSysTopic != NULL);
+
+ if (aItem==aOLE || aItem==aSysTopic
+ || (fIsFile=IsFile (aItem, &fUnsavedDoc)))
+ {
+
+
+ intrDebugOut((DEB_DDE_INIT,
+ "DdeCommonWndProc:hWnd(%x) DDE_INITIATE cls(%ws)\n",
+ hwnd,
+ wAtomName(aClass)));
+
+ //
+ // Get the ClassToHwnd map for this thread
+ //
+ CMapUintPtr FAR *pmapClassToHwnd;
+ Assert (sizeof (CMapUintPtr FAR *)==sizeof(LONG));
+ pmapClassToHwnd = (CMapUintPtr FAR *) GetWindowLong (hwnd, 0);
+ Assert (pmapClassToHwnd);
+
+
+ // Convert atom to CLSID, taking into account
+ // TreatAs and AutoConvert.
+ CLSID clsid;
+ ATOM aOriginalClass = aClass;
+
+ if (CLSIDFromAtomWithTreatAs (&aClass, &clsid, &cnvtyp) != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,"Could not get clsid for this class\n"));
+ return 0L;
+ }
+
+ void *pServerTmp;
+ if (TRUE == pmapClassToHwnd->Lookup (aClass, pServerTmp))
+ {
+ //
+ // Since a server window for this class already exists, but is a child window
+ // of ours, we will send it this message directly.
+ //
+
+ intrDebugOut((DEB_DDE_INIT,
+ "DdeCommonWndProc Server cls exists. Forwarding to %x\n",
+ pServerTmp));
+
+ return SSSendMessage ((HWND)pServerTmp, WM_DDE_INITIATE, wParam,lParam);
+
+ }
+
+ if (CoIsOle1Class (clsid))
+ {
+ // We have no business intercepting Initiates sent
+ // to 1.0 servers
+ intrDebugOut((DEB_DDE_INIT,
+ "DdeCommonWndProc: Its a OLE 1.0 class\n"));
+ return 0L;
+ }
+
+ if (fIsFile)
+ {
+ // Link case
+ WCHAR szFile[MAX_STR];
+
+ WORD cb=GlobalGetAtomName (aItem, szFile, MAX_STR);
+ Assert (cb>0 && cb < MAX_STR-1);
+ intrDebugOut((DEB_DDE_INIT,
+ "Looking for file %ws\n",szFile));
+
+ IsRunningInThisTask (szFile, &fIsRunning);
+ }
+
+ // If it's not a file, it can't be running, obviously.
+ intrAssert (fIsFile || !fIsRunning);
+
+ if (NOERROR == (hresult=(CreateDdeSrvrWindow (clsid,
+ aClass,
+ &hwndServer,
+ fIsRunning,
+ aOriginalClass,
+ cnvtyp))))
+ {
+
+ // Indicate that we have created a server window
+ // for this class. We could have used any value in
+ // place of hwndServer_. It's just a flag.
+ // REVIEW jasonful: how to handle OOM?
+
+ pmapClassToHwnd->SetAt (wDupAtom(aClass), hwndServer);
+
+#if DBG == 1
+ // Verify the SetAt we just did.
+ void FAR* pv;
+ Verify (pmapClassToHwnd->Lookup(aClass, pv));
+ Assert (pv == hwndServer);
+#endif
+ // Pass the INITIATE along to the real,
+ // newly-created server window and forge
+ // the sender's hwnd to be whoever called
+ // the common server window.
+ // SendMessage should return 1L is doc is running,
+ // indicating an ACK was sent.
+ Assert (IsWindowValid (hwndServer));
+ SSSendMessage (hwndServer, WM_DDE_INITIATE, wParam,lParam);
+ intrDebugOut((DEB_DDE_INIT,
+ "DdeCommonWndProc:hWnd(%x) DDE_INITIATE complete(%ws)\n",
+ hwnd,
+ wAtomName(aClass)));
+ VDATEHEAP();
+ }
+ else
+ {
+ if (S_FALSE!=GetScode(hresult))
+ {
+ intrDebugOut((DEB_IERROR,
+ "DCWP: CreateDdeSrvrWindow failed %x\n",
+ hresult));
+ }
+ }
+ }
+ else
+ {
+ //
+ // We have a DDE_INITIATE message that needs to be forwarded to our
+ // child window.
+ //
+ return SendMsgToChildren(hwnd,wMsg,wParam,lParam);
+ }
+ return 0L;
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ //
+ // When this window is destroyed, we cleanup the
+ // windows attached data.
+ //
+
+ CMapUintPtr FAR *pmapClassToHwnd;
+ pmapClassToHwnd = (CMapUintPtr FAR *) GetWindowLong (hwndIn, 0);
+
+ //
+ // Make sure there are no server windows
+ // created by this common window still extant. If there are, print out
+ // a message on a debug build. Otherwise, there really isn't much we
+ // can do about it. We are already closing down. The DDE emulation layer
+ // will send appropriate terminate messages.
+ //
+
+ #if DBG == 1
+ if (pmapClassToHwnd && !pmapClassToHwnd->IsEmpty())
+ {
+ intrDebugOut((DEB_ERROR,
+ "DCDW Leaking active OLE 1.0 clients\n"));
+ intrDebugOut((DEB_ERROR,
+ "There were active OLE 1.0 connections at shutdown\n"));
+ }
+ #endif
+ delete pmapClassToHwnd;
+ return(0);
+ }
+
+
+
+ default:
+ return SSDefWindowProc (hwndIn, wMsg, wParam, lParam);
+ }
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateCommonDdeWindow
+//
+// Synopsis: Creates a DDE window for initiating conversations with this
+// threads objects.
+//
+// Effects: Creates a window that responds to DDE_INITIATE messages, and
+// determines if it needs to respond to the INITIATE. This
+// routine is called by OleInitializeEx()
+//
+// The handle to the created window is placed in the TLS
+// structure.
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-27-94 kevinro Converted to OLE32
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CreateCommonDdeWindow
+ (void)
+{
+ intrDebugOut((DEB_ITRACE,"%p _IN CreateCommonDdeWindow\n",0));
+
+ HRESULT hr = NOERROR;
+ HWND hwndDdeServer;
+
+
+ COleTls tls;
+ if (tls->dwFlags & OLETLS_DISABLE_OLE1DDE)
+ {
+ // If DDE use is disabled we shouldn't have gotten here.
+ //
+ Assert(!"Executing CreateCommonDdeWindow when DDE is disabled");
+ hr = CO_E_OLE1DDE_DISABLED;
+ goto exitRtn;
+ }
+
+ //
+ // If a DdeServer window already exists, then return NOERROR.
+ // If Com has been initialized but Ole has not, then we dont
+ // create a window, we just return NOERROR. This way, COM-only
+ // servers dont start serving OLE1 clients.
+ //
+
+ if (tls->hwndDdeServer != NULL || tls->cOleInits == 0)
+ {
+ goto exitRtn;
+ }
+
+ if (!(hwndDdeServer = DdeCreateWindowEx(0, gOleWindowClass,
+ szDdeServerWindow,
+ WS_POPUP,0,0,0,0,
+ NULL,NULL,
+ g_hmodOLE2, NULL)))
+ {
+ intrDebugOut((DEB_IERROR,
+ "CreateCommonDocWindow() has failed %x\n",
+ GetLastError()));
+
+ hr = E_OUTOFMEMORY;
+ goto exitRtn;
+ }
+
+ // fix up the WindowProc entry point.
+ SetWindowLong(hwndDdeServer, GWL_WNDPROC, (LONG)DdeCommonWndProc);
+
+ intrDebugOut((DEB_ITRACE,
+ "CreateCommonDocWindow() hwndDdeServer=%x\n",
+ hwndDdeServer));
+
+ // Give the common window a map from classes to server windows
+
+ CMapUintPtr FAR *pmapClassToHwnd;
+
+ Assert (sizeof(LONG)==sizeof (CMapUintPtr FAR*));
+
+ if ((pmapClassToHwnd = new CMapUintPtr) == NULL)
+ {
+ intrDebugOut((DEB_ERROR,"pmapClassToHwnd != NULL\n"));
+ hr = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ SetWindowLong (hwndDdeServer, 0, (LONG)pmapClassToHwnd);
+ //
+ // Set the pointer to the server in the TLS data
+ //
+
+ tls->hwndDdeServer = hwndDdeServer;
+
+exitRtn:
+
+ intrDebugOut((DEB_ITRACE,"%p _OUT CreateCommonDocWindow (%x)\n",0,hr));
+
+ return(hr);
+
+ //
+ // In the error case, if the hwnDdeServer != NULL, then destroy it
+ //
+errRtn:
+ if (hwndDdeServer != NULL)
+ {
+ SSDestroyWindow(hwndDdeServer);
+ }
+
+ goto exitRtn;
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DestroyCommonDdeWindow
+//
+// Synopsis: Destroys the common DDE Server window
+//
+// Effects:
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-27-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL DestroyCommonDdeWindow
+ (void)
+{
+ intrDebugOut((DEB_ITRACE,"%p _IN DestroyCommonDdeWindow\n",0));
+
+ HRESULT hr = S_OK;
+ COleTls tls;
+
+ HWND hwndDdeServer = tls->hwndDdeServer;
+
+ if (hwndDdeServer == NULL)
+ {
+ goto errRtn;
+ }
+
+
+ //
+ // The map from the common window got deleted in DdeCommonWndProc
+ //
+
+ //
+ // If destroying this window fails, there isn't much we can
+ // do about it.
+ //
+ if(!SSDestroyWindow (hwndDdeServer))
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ // NULL out the TLS
+ tls->hwndDdeServer = NULL;
+
+errRtn:
+ intrDebugOut((DEB_ITRACE,"%p _OUT DestroyCommonDdeWindow %x\n",0,hr));
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsRunningInThisTask
+//
+// Synopsis: Determine if the given file is running in the current task
+//
+// Effects: Calls a special function in the ROT to determine if the
+// file szFile is loaded as a moniker in the current task
+//
+// Arguments: [szFile] -- Filename
+// [pf] -- Points to a BOOL. Returned TRUE if running
+//
+// History: 6-29-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL IsRunningInThisTask(LPOLESTR szFileIn,BOOL FAR* pf) // out parm
+{
+ HRESULT hresult;
+
+ intrDebugOut((DEB_DDE_INIT,
+ "IsRunninginThisTask szFileIn=%ws\n",
+ WIDECHECK(szFileIn)));
+
+ //
+ // The RunningObjectTable always stores LONG filenames, therefore we
+ // need to convert this name to the long name for the lookup.
+ //
+
+ WCHAR szFile[MAX_PATH];
+ if ((lstrlenW(szFileIn) == 0) || (GetLongPathNameW(szFileIn,szFile,MAX_PATH) == 0))
+ {
+ //
+ // Unable to determine a long path for this object. Use whatever we were
+ // handed.
+ //
+ intrDebugOut((DEB_DDE_INIT,"No conversion to long path. Copy szFileIn\n"));
+ lstrcpyW(szFile,szFileIn);
+ }
+
+ intrDebugOut((DEB_DDE_INIT,"Long file szFile(%ws)\n",szFile));
+
+ hresult = GetLocalRunningObjectForDde(szFile,NULL);
+
+ *pf = (hresult == S_OK);
+
+ intrDebugOut((DEB_DDE_INIT,
+ "IsRunninginThisTask szFile=%ws returns %s\n",
+ WIDECHECK(szFile),
+ *pf?"TRUE":"FALSE"));
+ return NOERROR;
+}
+
diff --git a/private/ole32/com/dde/server/ddesrvr.h b/private/ole32/com/dde/server/ddesrvr.h
new file mode 100644
index 000000000..291b2c389
--- /dev/null
+++ b/private/ole32/com/dde/server/ddesrvr.h
@@ -0,0 +1,26 @@
+/*
+ ddesrvr.h
+ Header file for ddesrvr.cpp
+
+ Author:
+ Jason Fuller jasonful 8-11-92
+*/
+
+#ifndef fDdesrvr_h
+#define fDdesrvr_h
+
+// Defined in cftable.cpp
+STDAPI RemGetInfoForCid
+ (REFCLSID clsid,
+ LPDWORD pgrf,
+ LPCLASSFACTORY FAR* ppCF,
+ LPHANDLE FAR* pphwndDde,
+ BOOL FAR* FAR* ppfAvail,
+ BOOL fEvenIfHidden=FALSE);
+
+INTERNAL DestroyDdeSrvrWindow (HWND hwnd, ATOM aClass);
+INTERNAL CreateCommonDdeWindow (void);
+INTERNAL DestroyCommonDdeWindow (void);
+
+INTERNAL IsRunningInThisTask (LPOLESTR szFile, BOOL FAR* pf);
+#endif
diff --git a/private/ole32/com/dde/server/ddeutils.cxx b/private/ole32/com/dde/server/ddeutils.cxx
new file mode 100644
index 000000000..e40436759
--- /dev/null
+++ b/private/ole32/com/dde/server/ddeutils.cxx
@@ -0,0 +1,1013 @@
+/****************************** Module Header ******************************\
+* Module Name: ddeutils.c
+*
+* Purpose: Conatains all the utility routines
+*
+* Created: 1990
+*
+* Copyright (c) 1990, 1991 Microsoft Corporation
+*
+* History:
+* Raor, Srinik (../../1990) Designed and coded
+*
+\***************************************************************************/
+#include "ole2int.h"
+#include <dde.h>
+#include "srvr.h"
+#include "ddesrvr.h"
+#include "ddedebug.h"
+ASSERTDATA
+
+
+#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
+#define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
+
+
+
+#define KB_64 65536
+
+extern ATOM aTrue;
+extern ATOM aFalse;
+
+extern ATOM aStdCreateFromTemplate;
+extern ATOM aStdCreate;
+extern ATOM aStdOpen;
+extern ATOM aStdEdit;
+extern ATOM aStdShowItem;
+extern ATOM aStdClose;
+extern ATOM aStdExit;
+extern ATOM aStdDoVerbItem;
+
+
+//ScanBoolArg: scans the argument which is not included in
+//the quotes. These args could be only TRUE or FALSE for
+//the time being. !!!The scanning routines should be
+//merged and it should be generalized.
+
+INTERNAL_(LPSTR) ScanBoolArg
+(
+LPSTR lpstr,
+BOOL FAR *lpflag
+)
+{
+
+
+ LPSTR lpbool;
+ ATOM aShow;
+ char ch;
+
+ lpbool = lpstr;
+
+ // !!! These routines does not take care of quoted quotes.
+
+ while((ch = *lpstr) && (!(ch == ')' || ch == ',')))
+ lpstr++;
+
+ if(ch == NULL)
+ return NULL;
+
+ *lpstr++ = NULL; // terminate the arg by null
+
+ // if terminated by paren, then check for end of command
+ // syntax.
+
+ // Check for the end of the command string.
+ if (ch == ')') {
+ if (*lpstr++ != ']')
+ return NULL;
+
+ if(*lpstr != NULL)
+ return NULL; //finally should be terminated by null.
+
+ }
+
+ aShow = GlobalFindAtomA (lpbool);
+ if (aShow == aTrue)
+ *lpflag = TRUE;
+
+ else {
+ if (aShow ==aFalse)
+ *lpflag = FALSE;
+ else
+ return NULL;;
+ }
+ return lpstr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateUnicodeFromAnsi
+//
+// Synopsis: Creates a UNICODE string from an ANSI string
+//
+// Effects: Makes a new UNICODE string from the given ANSI string.
+// The new UNICODE string is returned. Memory is allocated
+// using PrivMemAlloc
+//
+// Arguments: [lpAnsi] -- Ansi version of string
+//
+// Requires:
+//
+// Returns: NULL if cannot create new string.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-07-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+LPOLESTR CreateUnicodeFromAnsi( LPCSTR lpAnsi)
+{
+ WCHAR buf[MAX_PATH];
+ ULONG ccbuf;
+ LPOLESTR lpWideStr;
+
+ if ((ccbuf=MultiByteToWideChar(CP_ACP,0,lpAnsi,-1,buf,MAX_PATH))
+ == FALSE)
+ {
+ intrAssert(!"Unable to convert characters");
+ return NULL;
+ }
+
+ lpWideStr = (LPOLESTR) PrivMemAlloc(ccbuf * sizeof(WCHAR));
+
+ if (lpWideStr != NULL)
+ {
+ memcpy(lpWideStr,buf,ccbuf*sizeof(WCHAR));
+ }
+ return(lpWideStr);
+}
+//+---------------------------------------------------------------------------
+//
+// Function: CreateAnsiFromUnicode
+//
+// Synopsis: Creates an Ansi string from a UNICODE string
+//
+// Effects: Makes a new ANSI string from the given UNICODE string.
+// The new string is returned. Memory is allocated
+// using PrivMemAlloc
+//
+// Arguments: [lpUnicode] -- Unicode version of string
+//
+// Requires:
+//
+// Returns: NULL if cannot create new string.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-07-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+LPSTR CreateAnsiFromUnicode( LPCOLESTR lpUnicode)
+{
+ char buf[MAX_PATH];
+ ULONG ccbuf;
+ LPSTR lpAnsiStr;
+
+ ccbuf = WideCharToMultiByte(CP_ACP,
+ 0,
+ lpUnicode,
+ -1,
+ buf,
+ MAX_PATH,
+ NULL,
+ NULL);
+
+
+ if (ccbuf == FALSE)
+ {
+ intrAssert(!"Unable to convert characters");
+ return NULL;
+ }
+
+ lpAnsiStr = (LPSTR) PrivMemAlloc(ccbuf * sizeof(char));
+
+ if (lpAnsiStr != NULL)
+ {
+ memcpy(lpAnsiStr,buf,ccbuf);
+ }
+ return(lpAnsiStr);
+}
+
+//ScannumArg: Checks for the syntax of num arg in Execute and if
+//the arg is syntactically correct, returns the ptr to the
+//beginning of the next arg and also, returns the number
+//Does not take care of the last num arg in the list.
+
+INTERNAL_(LPSTR) ScanNumArg
+(
+LPSTR lpstr,
+LPINT lpnum
+)
+{
+
+ WORD val = 0;
+ char ch;
+
+ while((ch = *lpstr++) && (ch != ',')) {
+ if (ch < '0' || ch >'9')
+ return NULL;
+ val += val * 10 + (ch - '0');
+
+ }
+
+ if(!ch)
+ return NULL;
+
+ *lpnum = val;
+ return lpstr;
+}
+
+
+
+
+//ScanArg: Checks for the syntax of arg in Execute and if
+//the arg is syntactically correct, returns the ptr to the
+//beginning of the next arg or to the end of the excute string.
+
+INTERNAL_(LPSTR) ScanArg
+(
+LPSTR lpstr
+)
+{
+
+
+ // !!! These routines does not take care of quoted quotes.
+
+ // first char should be quote.
+
+ if (*(lpstr-1) != '\"')
+ return NULL;
+
+ while(*lpstr && *lpstr != '\"')
+ lpstr++;
+
+ if(*lpstr == NULL)
+ return NULL;
+
+ *lpstr++ = NULL; // terminate the arg by null
+
+ if(!(*lpstr == ',' || *lpstr == ')'))
+ return NULL;
+
+
+ if(*lpstr++ == ','){
+
+ if(*lpstr == '\"')
+ return ++lpstr;
+ // If it is not quote, leave the ptr on the first char
+ return lpstr;
+ }
+
+ // terminated by paren
+ // already skiped right paren
+
+ // Check for the end of the command string.
+ if (*lpstr++ != ']')
+ return NULL;
+
+ if(*lpstr != NULL)
+ return NULL; //finally should be terminated by null.
+
+ return lpstr;
+}
+
+// ScanCommand: scanns the command string for the syntax
+// correctness. If syntactically correct, returns the ptr
+// to the first arg or to the end of the string.
+
+INTERNAL_(WORD) ScanCommand
+(
+LPSTR lpstr,
+WORD wType,
+LPSTR FAR * lplpnextcmd,
+ATOM FAR * lpAtom
+)
+{
+ // !!! These routines does not take care of quoted quotes.
+ // and not taking care of blanks arround the operators
+
+ // !!! We are not allowing blanks after operators.
+ // Should be allright! since this is arestricted syntax.
+
+ char ch;
+ LPSTR lptemp = lpstr;
+
+
+ while(*lpstr && (!(*lpstr == '(' || *lpstr == ']')))
+ lpstr++;
+
+ if(*lpstr == NULL)
+ return NULL;
+
+ ch = *lpstr;
+ *lpstr++ = NULL; // set the end of command
+
+ *lpAtom = GlobalFindAtomA (lptemp);
+
+ if (!IsOleCommand (*lpAtom, wType))
+ return NON_OLE_COMMAND;
+
+ if (ch == '(') {
+ ch = *lpstr++;
+
+ if (ch == ')') {
+ if (*lpstr++ != ']')
+ return NULL;
+ }
+ else {
+ if (ch != '\"')
+ return NULL;
+ }
+
+ *lplpnextcmd = lpstr;
+ return OLE_COMMAND;
+ }
+
+ // terminated by ']'
+
+ if (*(*lplpnextcmd = lpstr)) // if no nul termination, then it is error.
+ return NULL;
+
+ return OLE_COMMAND;
+}
+
+
+//MakeDataAtom: Creates a data atom from the item string
+//and the item data otions.
+
+INTERNAL_(ATOM) MakeDataAtom
+(
+ATOM aItem,
+int options
+)
+{
+ WCHAR buf[MAX_STR];
+
+ if (options == OLE_CHANGED)
+ return DuplicateAtom (aItem);
+
+ if (!aItem)
+ buf[0] = NULL;
+ else
+ GlobalGetAtomName (aItem, buf, MAX_STR);
+
+ if (options == OLE_CLOSED)
+ lstrcatW (buf, OLESTR("/Close"));
+ else {
+ if (options == OLE_SAVED)
+ lstrcatW (buf, OLESTR("/Save"));
+ else
+ AssertSz (0, "Bad option\n");
+ }
+
+ Puts ("MakeDataAtom "); Puts(buf); Putn();
+ if (buf[0])
+ return wGlobalAddAtom (buf);
+ else
+ return NULL;
+}
+
+//DuplicateAtom: Duplicates an atom
+INTERNAL_(ATOM) DuplicateAtom
+(
+ATOM atom
+)
+{
+ WCHAR buf[MAX_STR];
+
+ if (!atom)
+ return NULL;
+
+ GlobalGetAtomName (atom, buf, MAX_STR);
+ return wGlobalAddAtom (buf);
+}
+
+// MakeGlobal: makes global out of strings.
+// works only for << 64k
+
+INTERNAL_(HANDLE) MakeGlobal
+(
+LPSTR lpstr
+)
+{
+
+ int len = 0;
+ HANDLE hdata = NULL;
+ LPSTR lpdata = NULL;
+
+ len = strlen (lpstr) + 1;
+
+ hdata = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, len);
+
+ if (hdata == NULL || (lpdata = (LPSTR) GlobalLock (hdata)) == NULL)
+ goto errRtn;
+
+
+ memcpy(lpdata, lpstr, (DWORD)len);
+ GlobalUnlock (hdata);
+ return hdata;
+
+errRtn:
+ Assert (0);
+ if (lpdata)
+ GlobalUnlock (hdata);
+
+
+ if (hdata)
+ GlobalFree (hdata);
+
+ return NULL;
+
+}
+
+
+INTERNAL_(BOOL) CLSIDFromAtom(ATOM aClass, LPCLSID lpclsid)
+{
+ WCHAR szProgID[MAX_STR];
+ if (!ISATOM (aClass))
+ return FALSE;
+ WORD cb=GlobalGetAtomName (aClass, szProgID, MAX_STR);
+ Assert (cb>0 && cb < (MAX_STR - 1));
+
+ return CLSIDFromProgID(szProgID, lpclsid) == S_OK;
+}
+
+// CLSIDFromAtomWithTreatAs
+//
+// Input: *paClass
+// Output: *pclsid == corresponding CLSID, taking into account TreatAs and
+// AutoConvert
+// *paClass == atom correpsonding to *pclsid
+//
+#pragma SEG(CLSIDFromAtomWithTreatAs)
+INTERNAL CLSIDFromAtomWithTreatAs
+ (ATOM FAR* paClass,
+ LPCLSID pclsid,
+ CNVTYP FAR* pcnvtyp)
+{
+ HRESULT hr;
+
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CLSIDFromAtomWithTreatAs(paClass=%x,"
+ "pclsid=%x,pcnvtyp=%x)\n",0,
+ paClass,pclsid,pcnvtyp));
+
+ LPOLESTR szProgID = NULL;
+ CLSID clsidNew;
+
+ if (!CLSIDFromAtom (*paClass, pclsid))
+ {
+ hr = S_FALSE;
+ goto exitRtn;
+ }
+
+ DEBUG_GUIDSTR(clsidStr,pclsid);
+
+ intrDebugOut((DEB_ITRACE,"Guid %ws",clsidStr));
+ if (CoGetTreatAsClass (*pclsid, &clsidNew) == NOERROR)
+ {
+ DEBUG_GUIDSTR(newStr,pclsid);
+
+ intrDebugOut((DEB_ITRACE," cnvtypTreatAs %ws\n",newStr));
+ if (pcnvtyp)
+ *pcnvtyp = cnvtypTreatAs;
+ }
+ else if (OleGetAutoConvert (*pclsid, &clsidNew) == NOERROR)
+ {
+ DEBUG_GUIDSTR(newStr,pclsid);
+ intrDebugOut((DEB_ITRACE," cnvtypConvertTo %ws\n",newStr));
+ if (pcnvtyp)
+ *pcnvtyp = cnvtypConvertTo;
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE," no conversion\n"));
+ if (pcnvtyp)
+ *pcnvtyp = cnvtypNone;
+ clsidNew = *pclsid; // no translation
+ }
+
+ hr = ProgIDFromCLSID(clsidNew, &szProgID);
+ if (FAILED(hr))
+ {
+ intrDebugOut((DEB_ITRACE," ProgIDFromCLSID failed\n"));
+ goto exitRtn;
+ }
+
+ intrDebugOut((DEB_ITRACE,"ProgIDFromCLSID returns %ws\n",szProgID));
+ *paClass = GlobalAddAtom (szProgID);
+ *pclsid = clsidNew;
+ CoTaskMemFree(szProgID);
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%p OUT CLSIDFromAtomWithTreatAs returns %x\n",
+ 0,hr));
+
+ return hr;
+}
+
+
+INTERNAL_(BOOL) PostMessageToClientWithReply
+(
+HWND hWnd,
+UINT wMsg,
+WPARAM wParam, // posting window
+LPARAM lParam,
+UINT wReplyMsg
+)
+{
+ MSG msg;
+
+ if (!IsWindowValid (hWnd))
+ {
+ AssertSz(FALSE, "Client's window is missing");
+ return FALSE;
+ }
+
+ if (!IsWindowValid ((HWND)wParam))
+ {
+ AssertSz (0, "Posting window is invalid");
+ return FALSE;
+ }
+
+ // Post message to client failed. Treat it as if we got the reply.
+ if (!PostMessageToClient (hWnd, wMsg, wParam, lParam))
+ return FALSE;
+
+ return NOERROR == wTimedGetMessage (&msg, (HWND)wParam, WM_DDE_TERMINATE,
+ WM_DDE_TERMINATE);
+}
+
+
+
+INTERNAL_(BOOL) PostMessageToClient
+(
+ HWND hWnd,
+ UINT wMsg,
+ WPARAM wParam,
+ LPARAM lParam
+)
+{
+ UINT c=0;
+
+ while (c < 10)
+ {
+ if (!IsWindowValid (hWnd)) {
+ Warn ("Client's window is missing");
+ return FALSE;
+ }
+ Puts ("Posting"); Puth(wMsg); Puts("to"); Puth(hWnd); Putn();
+ if (PostMessage (hWnd, wMsg, wParam, lParam))
+ return TRUE; // success
+ else
+ {
+ Yield();
+ c++; // try again
+ }
+ }
+ return FALSE;
+}
+
+
+INTERNAL_(BOOL) IsWindowValid
+ (HWND hwnd)
+{
+ HTASK htask;
+
+ if (!IsWindow (hwnd))
+ return FALSE;
+
+ htask = GetWindowThreadProcessId(hwnd, NULL);
+
+#ifndef WIN32
+ if (IsTask(htask))
+#endif
+ return TRUE;
+
+ return FALSE;
+}
+
+
+
+INTERNAL_(BOOL) UtilQueryProtocol
+(
+ATOM aClass,
+LPOLESTR lpprotocol
+)
+{
+ HKEY hKey;
+ WCHAR key[MAX_STR];
+ WCHAR cclass[MAX_STR];
+
+ if (!aClass)
+ return FALSE;
+
+ if (!GlobalGetAtomName (aClass, cclass, MAX_STR))
+ return FALSE;
+
+ lstrcpyW (key, cclass);
+ lstrcatW (key, OLESTR("\\protocol\\"));
+ lstrcatW (key, lpprotocol);
+ lstrcatW (key, OLESTR("\\server"));
+ if (RegOpenKey (HKEY_CLASSES_ROOT, key, &hKey) != ERROR_SUCCESS)
+ return FALSE;
+ RegCloseKey (hKey);
+ return TRUE;
+}
+
+
+
+INTERNAL_(BOOL) IsOleCommand
+(
+ATOM aCmd,
+WORD wType
+)
+{
+ if (wType == WT_SRVR) {
+ if ((aCmd == aStdCreateFromTemplate)
+ || (aCmd == aStdCreate)
+ || (aCmd == aStdOpen)
+ || (aCmd == aStdEdit)
+ || (aCmd == aStdShowItem)
+ || (aCmd == aStdClose)
+ || (aCmd == aStdExit))
+ return TRUE;
+ }
+ else {
+ if ((aCmd == aStdClose)
+ || (aCmd == aStdDoVerbItem)
+ || (aCmd == aStdShowItem))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+INTERNAL wFileBind
+ (LPOLESTR szFile,
+ LPUNKNOWN FAR* ppUnk)
+{
+ HRESULT hresult = NOERROR;
+ LPBC pbc = NULL;
+ LPMONIKER pmk = NULL;
+ *ppUnk = NULL;
+ ErrRtnH (CreateBindCtx (0, &pbc));
+ ErrRtnH (CreateFileMoniker (szFile, &pmk));
+ ErrRtnH (pmk->BindToObject (pbc, NULL, IID_IUnknown, (LPLPVOID) ppUnk));
+ errRtn:
+// AssertOutPtrIface(hresult, *ppUnk);
+ if (pbc)
+ pbc->Release();
+ if (pmk)
+ pmk->Release();
+ return hresult;
+}
+
+// SynchronousPostMessage
+//
+// Post a message and wait for the ack.
+// (jasonful)
+//
+INTERNAL SynchronousPostMessage
+ (HWND hWndTo, // also who you expect the reply from
+ UINT wMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+#ifdef _MAC
+#else
+
+ HRESULT hresult = NOERROR;
+
+ static unsigned iCounter;
+
+
+ HWND hWndFrom = (HWND) wParam;
+
+
+
+ RetZ (IsWindowValid(hWndFrom));
+ RetZ (IsWindowValid(hWndTo));
+
+ Assert (wMsg != WM_DDE_INITIATE); // can't check for positive ack.
+
+ RetZS (PostMessage (hWndTo, wMsg, wParam, lParam), RPC_E_SERVER_DIED);
+
+ MSG msg;
+ RetErr (wTimedGetMessage (&msg, hWndFrom, WM_DDE_ACK, WM_DDE_ACK));
+ Assert (msg.message == WM_DDE_ACK);
+ if (!( GET_WM_DDE_ACK_STATUS(msg.wParam,msg.lParam) & POSITIVE_ACK))
+ hresult = ResultFromScode (RPC_E_DDE_NACK);
+ if (msg.hwnd != hWndFrom)
+ hresult = ResultFromScode (RPC_E_DDE_UNEXP_MSG);
+
+
+
+ return hresult;
+#endif _MAC
+}
+
+
+INTERNAL wFileIsRunning
+ (LPOLESTR szFile)
+{
+ LPMONIKER pmk = NULL;
+ LPBINDCTX pbc=NULL;
+ HRESULT hresult;
+
+ RetErr (CreateBindCtx (0, &pbc));
+ ErrRtnH (CreateFileMoniker (szFile, &pmk));
+ hresult = pmk->IsRunning (pbc, NULL, NULL);
+ errRtn:
+ if (pbc)
+ pbc->Release();
+ if (pmk)
+ pmk->Release();
+ return hresult;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsFile
+//
+// Synopsis: Given a handle to an atom, determine if it is a file
+//
+// Effects: Attempts to get the files attributes. If there are no
+// attributes, then the file doesn't exist.
+//
+// Arguments: [a] -- Atom for filename
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-03-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_ (BOOL) IsFile
+ (ATOM a, BOOL FAR* pfUnsavedDoc)
+{
+ LPMONIKER pmk = NULL;
+ LPBC pbc = NULL;
+ LPRUNNINGOBJECTTABLE pROT=NULL;
+
+ WCHAR szFile [MAX_STR];
+ if (0==GlobalGetAtomName (a, szFile, MAX_STR))
+ return FALSE;
+
+ DWORD dwAttribs = GetFileAttributes(szFile);
+
+ /* flags prevent sharing violation*/
+ if (dwAttribs != 0xFFFFFFFF)
+ {
+ if (pfUnsavedDoc)
+ *pfUnsavedDoc = FALSE;
+ return TRUE;
+ }
+ // This will deal with unsaved documents in the ROT.
+ // We do NOT want to call pmk->IsRunning because if a 2.0 client called
+ // DdeIsRunning, we do not want call it here, because then we get stuck
+ // in an infinite loop. We only care about true 2.0 running objects.
+
+
+ //
+ // BUGBUG: KevinRo There is a function (GetPathFromRot) that could replace
+ // the following code sequence.
+ //
+
+ BOOL f= NOERROR==CreateBindCtx (0, &pbc) &&
+ NOERROR==CreateFileMoniker (szFile, &pmk) &&
+ NOERROR==pbc->GetRunningObjectTable (&pROT) &&
+ NOERROR==pROT->IsRunning (pmk) ;
+ if (pROT)
+ pROT->Release();
+ if (pmk)
+ pmk->Release();
+ if (pbc)
+ pbc->Release();
+ if (pfUnsavedDoc)
+ *pfUnsavedDoc = TRUE;
+ return f;
+
+
+}
+
+// wCompatibleClasses
+//
+// Determine if class "aClient" is Auto-Converted to class "aSrvr" or
+// Treated-As class "aSrvr".
+// (Does not check if aClient==aSrvr)
+//
+#pragma SEG(wCompatibleClasses)
+INTERNAL wCompatibleClasses
+ (ATOM aClient,
+ ATOM aSrvr)
+{
+ CLSID clsidClient, clsidSrvr, clsidTo;
+ HRESULT hresult;
+ RetZS (CLSIDFromAtom (aClient, &clsidClient), S_FALSE);
+ RetZS (CLSIDFromAtom (aSrvr, &clsidSrvr ), S_FALSE);
+ if (NOERROR==OleGetAutoConvert (clsidClient, &clsidTo)
+ && clsidTo == clsidSrvr)
+ {
+ // aClient is Auto-Converted to aSrvr
+ return NOERROR;
+ }
+ hresult = CoGetTreatAsClass(clsidClient, &clsidTo);
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "wCompatibleClasses CoGetTreatAs returns %x\n",
+ hresult));
+ return(hresult);
+ }
+
+ if (clsidTo == clsidSrvr)
+ {
+ // aClient is Treated-As aSrvr
+ return NOERROR;
+ }
+ return ResultFromScode (S_FALSE); // not compatible
+}
+
+
+
+// wCreateStgAroundNative
+//
+// Build an OLE2 storage around 1.0 native data by putting it in
+// stream "\1Ole10Native" and creating valid CompObj and OLE streams.
+// Return the IStorage and the ILockBytes it is built on.
+//
+INTERNAL wCreateStgAroundNative
+ (HANDLE hNative,
+ ATOM aClassOld,
+ ATOM aClassNew,
+ CNVTYP cnvtyp,
+ ATOM aItem,
+ LPSTORAGE FAR* ppstg,
+ LPLOCKBYTES FAR* pplkbyt)
+{
+ HRESULT hresult;
+ LPSTORAGE pstg = NULL;
+ LPLOCKBYTES plkbyt = NULL;
+ LPOLESTR szUserType = NULL;
+ WCHAR szClassOld [256];
+ CLSID clsid;
+ ATOM aClass;
+ *ppstg = NULL;
+
+ intrDebugOut((DEB_ITRACE,
+ "%p wCreateStgAroundNative(hNative=%x,aClassOld=%x"
+ ",aClassNew=%x cnvtyp=%x,aItem=%x)\n",
+ 0,hNative,aClassOld,aClassNew,cnvtyp,aItem));
+
+ // Create temporary docfile on our ILockBytes
+ ErrRtnH (CreateILockBytesOnHGlobal (NULL,/*fDeleteOnRelease*/TRUE,&plkbyt));
+
+ Assert (plkbyt);
+
+ ErrRtnH (StgCreateDocfileOnILockBytes (plkbyt, grfCreateStg, 0, &pstg));
+
+ RetZ (pstg);
+ Assert (NOERROR==StgIsStorageILockBytes(plkbyt));
+
+ aClass = (cnvtyp == cnvtypConvertTo)?aClassNew:aClassOld;
+
+ if (CLSIDFromAtom (aClass,(LPCLSID)&clsid) == FALSE)
+ {
+ hresult = REGDB_E_CLASSNOTREG;
+ goto errRtn;
+ }
+
+ ErrRtnH (WriteClassStg (pstg, clsid));
+
+ // The UserType always corresponds to the clsid.
+ ErrRtnH (OleRegGetUserType (clsid, USERCLASSTYPE_FULL, &szUserType));
+
+ // The format is always the 1.0 format (classname/progid)
+ ErrZS (GlobalGetAtomName (aClassOld, szClassOld, 256), E_UNEXPECTED);
+
+ ErrRtnH (WriteFmtUserTypeStg (pstg, RegisterClipboardFormat(szClassOld),
+ szUserType));
+
+
+ if (cnvtyp == cnvtypConvertTo)
+ {
+ // SetConvertStg also writes a complete default Ole Stream
+ ErrRtnH (SetConvertStg (pstg, TRUE));
+ }
+ else
+ {
+ ErrRtnH (WriteOleStg (pstg, NULL, (CLIPFORMAT)0, NULL));
+ }
+ ErrRtnH (StSave10NativeData (pstg, hNative, FALSE));
+ if (aItem)
+ {
+ ErrRtnH (StSave10ItemName (pstg, wAtomNameA (aItem)));
+ }
+ *ppstg = pstg;
+ *pplkbyt = plkbyt;
+ return NOERROR;
+
+ errRtn:
+ if (pstg)
+ pstg->Release();
+ if (plkbyt)
+ plkbyt->Release();
+ CoTaskMemFree(szUserType);
+ return hresult;
+}
+
+
+#ifdef _DEBUG
+
+
+INTERNAL_ (BOOL) IsAtom (ATOM a)
+{
+ WCHAR sz[256]= {0};
+ if (a < 0xc000)
+ return FALSE;
+ WORD cb=GlobalGetAtomName (a, sz, 256);
+ Assert (lstrlenW(sz) == (int) cb);
+ return cb>0 && cb < MAX_STR;
+}
+
+
+#include <limits.h>
+#undef GlobalFree
+
+
+
+
+INTERNAL_(HANDLE) wGlobalFree (HANDLE h)
+{
+ LPVOID p;
+ Assert ((GlobalFlags(h) & GMEM_LOCKCOUNT)==0);
+ if (!(p=GlobalLock(h)))
+ {
+ Puts ("Cannot free handle");
+ Puth (h);
+ Putn();
+ AssertSz(0, "Invalid Handle\r\n");
+ }
+ Assert (!IsBadReadPtr (p, (UINT) min (UINT_MAX, GlobalSize(h))));
+ Assert (GlobalUnlock(h)==0);
+ Verify (!GlobalFree (h));
+ Puts ("FREEING ");
+ Puth (h);
+ Putn ();
+ return NULL; // success
+}
+
+
+
+#undef GlobalDeleteAtom
+
+INTERNAL_(ATOM) wGlobalDeleteAtom (ATOM a)
+{
+ WCHAR sz[256];
+ Assert (0 != GlobalGetAtomName (a, sz, 256));
+ Assert (0==GlobalDeleteAtom (a));
+ return (ATOM)0;
+}
+
+INTERNAL_(int) wCountChildren
+ (HWND h)
+{
+ int c = 0;
+ HWND hwndChild = GetWindow (h, GW_CHILD);
+ while (hwndChild)
+ {
+ c++;
+ hwndChild = GetWindow (hwndChild, GW_HWNDNEXT);
+ }
+ return c;
+}
+
+
+#endif // _DEBUG
diff --git a/private/ole32/com/dde/server/dirs b/private/ole32/com/dde/server/dirs
new file mode 100644
index 000000000..820fa2392
--- /dev/null
+++ b/private/ole32/com/dde/server/dirs
@@ -0,0 +1,37 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ daytona
diff --git a/private/ole32/com/dde/server/doc.cxx b/private/ole32/com/dde/server/doc.cxx
new file mode 100644
index 000000000..fe1b6165c
--- /dev/null
+++ b/private/ole32/com/dde/server/doc.cxx
@@ -0,0 +1,1653 @@
+/***************************************************************************\
+* Module Name: Doc.c Document Main module
+*
+* Purpose: Includes All the document level object communication related.
+*
+* Created: Oct 1990.
+*
+* Copyright (c) 1990, 1991 Microsoft Corporation
+*
+* History:
+* Raor (../10/1990) Designed, coded (modified for 2.0)
+*
+\***************************************************************************/
+
+#include "ole2int.h"
+//#include "cmacs.h"
+#include <dde.h>
+
+#include "srvr.h"
+#include "ddedebug.h"
+#include "valid.h"
+ASSERTDATA
+
+extern ATOM aStdClose;
+extern ATOM aStdShowItem;
+extern ATOM aStdDoVerbItem;
+extern ATOM aStdDocName;
+extern ATOM aTrue;
+extern ATOM aFalse;
+
+extern HANDLE hddeRename;
+extern HWND hwndRename;
+
+#ifdef _CHICAGO_
+#define szDDEViewObj "DDE ViewObj"
+#else
+#define szDDEViewObj L"DDE ViewObj"
+#endif
+
+
+// HRESULT DdeHandleIncomingCall(HWND hwndCli, WORD wCallType);
+
+//
+// Call CoHandleIncomingCall which will call the message filter
+// Note: only call this functions with:
+// - CALLTYPE_TOPLEVEL ... for synchranous calls
+// - CALLTYPE_ASYNC ... for async calls
+//
+HRESULT DdeHandleIncomingCall(HWND hwndCli, WORD wCallType)
+{
+
+ Assert(!"DdeHandleIncomingCall not implemented");
+
+ return(RPC_E_CALL_REJECTED);
+
+ // Review: bug: get the correcr hwnd
+ switch ( /* CoHandleIncomingCall(hwndCli, wCallType, NULL) */ wCallType) {
+ default:
+ case SERVERCALL_ISHANDLED: // call can be proccesed
+ return NOERROR;
+
+ case SERVERCALL_REJECTED: // call rejected
+ return ResultFromScode(RPC_E_CALL_REJECTED);
+
+ case SERVERCALL_RETRYLATER: // call should be retried later
+ return ResultFromScode(RPC_E_DDE_BUSY);
+ }
+}
+
+
+INTERNAL CDefClient::Create
+(
+ LPSRVR lhOLESERVER,
+ LPUNKNOWN lpunkObj,
+ LPOLESTR lpdocName,
+ const BOOL fSetClientSite,
+ const BOOL fDoAdvise,
+ const BOOL fRunningInSDI, // optional
+ HWND FAR* phwnd // optional
+)
+{
+ LPSRVR lpsrvr = NULL;
+ LPCLIENT lpclient = NULL;
+ HANDLE hclient = NULL;
+ HRESULT hresult = NOERROR;
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN CDefClient::Create(lpsrvr=%x,lpdocName=%ws)\n",
+ lhOLESERVER,WIDECHECK(lpdocName)));
+
+ // REVIEW: server's termination has already started. Are
+ // we going to see this condition in the synchronous mode.
+ lpsrvr = (LPSRVR)lhOLESERVER;
+ if (lpsrvr && lpsrvr->m_bTerminate)
+ {
+ Assert(0);
+ return ReportResult(0, RPC_E_DDE_REVOKE, 0, 0);
+ }
+
+#ifdef FIREWALLS
+ PROBE_READ(lpunkObj);
+ PROBE_READ(lpmkObj);
+ PROBE_WRITE(lplhobj);
+#endif
+
+ lpclient = new CDefClient (/*pUnkOuter==*/NULL);;
+
+ Assert(lpclient->m_pUnkOuter);
+
+ lpclient->m_aItem = wGlobalAddAtom (/*lpszObjName*/lpdocName);
+ lpclient->m_fRunningInSDI = fRunningInSDI;
+ lpclient->m_psrvrParent = lpsrvr;
+ // A doc has itself as its containing document
+ lpclient->m_pdoc = lpclient;
+
+ ErrRtnH (lpunkObj->QueryInterface (IID_IOleObject,
+ (LPLPVOID) &lpclient->m_lpoleObj));
+
+ ErrRtnH (lpunkObj->QueryInterface (IID_IDataObject,
+ (LPLPVOID) &lpclient->m_lpdataObj));
+
+ // Lock object; do after the QI so that ReleaseObjPtrs will unlock correctly
+ lpclient->m_fLocked =
+ (NOERROR==CoLockObjectExternal (lpunkObj, TRUE, /*dont care*/ FALSE));
+
+ if (!(lpclient->m_hwnd = DdeCreateWindowEx(0, gOleWindowClass,szDDEViewObj,
+ WS_CHILD,0,0,0,0,lpsrvr->m_hwnd,NULL, g_hinst, NULL)))
+ {
+ intrDebugOut((DEB_ITRACE,"CDefClient::Create() couldn't create window\n"));
+ goto errRtn;
+ }
+
+ // fix up the WindowProc entry point.
+ SetWindowLong(lpclient->m_hwnd, GWL_WNDPROC, (LONG)DocWndProc);
+
+ if (fDoAdvise)
+ {
+ // This is for Packager, in particular, and manual links.
+ // If client does not advise on any data, we still need
+ // to do an OLE advise so we can get OnClose notifications.
+ ErrRtnH (lpclient->DoOle20Advise (OLE_CLOSED, (CLIPFORMAT)0));
+ }
+
+ intrDebugOut((DEB_ITRACE," Doc window %x created\n",lpclient->m_hwnd));
+
+ // Set out parm (window)
+ if (phwnd != NULL)
+ {
+ *phwnd = lpclient->m_hwnd;
+ }
+
+ if (fSetClientSite)
+ {
+ // Should not set the client site if the object has not been
+ // initialized yet, by BindMoniker (i.e. PersistFile::Load)
+ // or PersistStorage::Load
+ if (lpclient->SetClientSite() != NOERROR)
+ {
+ goto errRtn;
+ }
+ }
+
+ Putsi(lpclient->m_cRef);
+
+ SetWindowLong (lpclient->m_hwnd, 0, (LONG)lpclient);
+ SetWindowWord (lpclient->m_hwnd, WW_LE, WC_LE);
+ SetWindowLong (lpclient->m_hwnd,WW_HANDLE,
+ (GetWindowLong (lpsrvr->m_hwnd, WW_HANDLE)));
+
+ hresult = NOERROR;
+
+exitRtn:
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _OUT CDefClient::Create(lpsrvr=%x,lpdocName=%ws) hr=%x\n",
+ lhOLESERVER,
+ WIDECHECK(lpdocName),
+ hresult));
+
+
+ return(hresult);
+errRtn:
+ intrDebugOut((DEB_ITRACE,"CDefClient::Create() in error handling routine\n"));
+ if (lpclient)
+ {
+ if (lpclient->m_hwnd)
+ SSDestroyWindow (lpclient->m_hwnd);
+
+ if (lpclient->m_aItem)
+ GlobalDeleteAtom (lpclient->m_aItem);
+ delete lpclient;
+ }
+ hresult = E_OUTOFMEMORY;
+ goto exitRtn;
+}
+
+
+
+INTERNAL CDefClient::Revoke (BOOL fRelease)
+{
+ Puts ("DefClient::Revoke "); Puth(this); Puta(m_aItem); Putn();
+
+ ChkC(this);
+
+
+ ReleaseObjPtrs();
+
+ // We are done with this CDefClient but someone may still have a reference
+ // to an instance of one of our nested classes. In particular, an advise
+ // holder may be holding on to our sink, or an item may have a pointer
+ // to us if we are its parent document. So we cannot actually do a
+ // "delete this".
+ // The corresponding AddRef is in CDefClient::Create
+ // or CDefClient::RegisterItem
+
+ m_pUnkOuter->Release();
+
+ Puts ("DefClient::Revoke done\r\n");
+ return NOERROR;
+}
+
+
+
+INTERNAL CDefClient::ReleaseObjPtrs
+ (void)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CDefClient::ReleaseObjPtrs\n",
+ this));
+
+ ULONG ulResult;
+
+ if (m_lpoleObj && m_fLocked)
+ {
+ // Unlock object. Set m_fLocked to FALSE first to prevent reentrant
+ // problems (unlock causes close which causes this routine to be called)
+
+ m_fLocked = FALSE;
+ CoLockObjectExternal(m_lpoleObj, FALSE, TRUE);
+ }
+ if (m_lpoleObj)
+ {
+ if (m_fDidSetClientSite)
+ m_lpoleObj->SetClientSite(NULL);
+ DoOle20UnAdviseAll();
+ Assert (m_lpoleObj);
+ if (m_lpoleObj)
+ {
+ ulResult = m_lpoleObj->Release();
+ m_lpoleObj = NULL;
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT ::ReleaseObjPtrs lpoleObj ulResult=%x\n",
+ this,ulResult));
+ }
+ if (m_lpdataObj)
+ {
+ // Must do it this way because the Release can cause recursion
+ LPDATAOBJECT pdata = m_lpdataObj;
+ m_lpdataObj = NULL;
+ ulResult = pdata->Release();
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT ::ReleaseObjPtrs pdata ulResult=%x\n",
+ this,ulResult));
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT CDefClient::ReleaseObjPtrs\n",
+ this));
+ return NOERROR;
+}
+#if 000
+//RevokeAllDocs : revokes all the doc objects attached to a given
+//server.
+
+INTERNAL_(HRESULT) CDDEServer::RevokeAllDocObjs ()
+{
+
+ HWND hwnd;
+ HWND hwndnext;
+ LPCLIENT lpclient;
+ Puts ("RevokeAllDocObjs\r\n");
+ ChkS(this);
+
+ hwnd = GetWindow (m_hwnd, GW_CHILD);
+
+ // Go thru each of the child windows and revoke the corresponding
+ // document. Doc windows are child windows for the server window.
+
+ while (hwnd){
+ // sequence is important
+ hwndnext = GetWindow (hwnd, GW_HWNDNEXT);
+ lpclient = ((LPCLIENT)GetWindowLong (hwnd, 0));
+ lpclient->Revoke();
+ hwnd = hwndnext;
+ }
+ return NOERROR;
+}
+#endif
+
+// FindDoc: Given a doc obj, searches for the doc obj
+// in the given class factory tree. returns true if the
+// doc obj is available.
+
+
+INTERNAL_(LPCLIENT) CDDEServer::FindDocObj
+(
+LPSTR lpdocname
+)
+{
+ ATOM aItem;
+ HWND hwnd;
+ LPCLIENT lpclient;
+
+ ChkS(this);
+ aItem = (ATOM)GlobalFindAtomA (lpdocname);
+ Assert (IsWindowValid (m_hwnd));
+ hwnd = GetWindow (m_hwnd, GW_CHILD);
+ Assert (NULL==hwnd || IsWindowValid (hwnd));
+
+ while (hwnd)
+ {
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+ if (lpclient->m_aItem == aItem)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "FindDocObj found %s lpclient=%x\n",
+ lpdocname,
+ lpclient));
+ return lpclient;
+ }
+ hwnd = GetWindow (hwnd, GW_HWNDNEXT);
+ }
+ return NULL;
+}
+
+BOOL PostAckToClient(HWND hwndClient,HWND hwndServer,ATOM aItem,DWORD retval)
+{
+ HRESULT hr = TRUE;
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN PostAckToClient(hwndClient=%x,hwndServer=%x,aItem=%x(%ws)\n",
+ hwndClient,
+ hwndServer,
+ aItem,
+ wAtomName(aItem)));
+
+ DWORD status = 0;
+ SET_MSG_STATUS (retval, status);
+
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
+
+ if (!PostMessageToClient (hwndClient,
+ WM_DDE_ACK,
+ (UINT)hwndServer,
+ lp))
+ {
+ DDEFREE(WM_DDE_ACK,lp);
+ hr = FALSE;
+ }
+ intrDebugOut((DEB_ITRACE,
+ "0 _OUT PostAckToClient returns %x\n",
+ hr));
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DocHandleIncomingCall
+//
+// Synopsis: Setup and call the CallControl to dispatch a call to the doc
+//
+// Effects: A call has been made from the client that requires us to call
+// into our server. This must be routed through the call control.
+// This routine sets up the appropriate data structures, and
+// calls into the CallControl. The CallControl will in turn
+// call DocDispatchIncomingCall to actually process the call.
+//
+// This routine should only be called by the DocWndProc
+//
+//
+// Arguments: [pDocData] -- Points to DOCDISPATCHDATA for this call
+// This contains all required information for
+// handling the message.
+//
+// Requires:
+//
+// Returns: If an error is returned, it is assumed that the Dispatch
+// routine was not reached. DocDispatchIncomingCall() should
+// not be returning an error.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-05-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+// This is a co-routine with DocDispatchIncomingCall. See that routine
+// for more details
+//
+//----------------------------------------------------------------------------
+INTERNAL DocHandleIncomingCall(PDOCDISPATCHDATA pDocData)
+{
+ HRESULT hresult = NOERROR;
+ DISPATCHDATA dispatchdata;
+ DWORD callcat;
+
+ intrAssert(pDocData != NULL);
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN DocHandleIncomingCall lpclient=%x pDocData=%x\n",
+ pDocData->lpclient,
+ pDocData));
+
+ //
+ // TERMINATE messages must always be handled ASYNC, and cannot
+ // be rejected.
+ //
+ if (pDocData->msg == WM_DDE_TERMINATE)
+ {
+ callcat = CALLCAT_ASYNC;
+ }
+ else
+ {
+ callcat = CALLCAT_SYNCHRONOUS;
+ }
+
+ dispatchdata.pData = (LPVOID) pDocData;
+ pDocData->wDispFunc = DDE_DISP_DOCWNDPROC;
+
+ RPCOLEMESSAGE rpcMsg;
+ RPC_SERVER_INTERFACE RpcInterfaceInfo;
+ DWORD dwFault;
+
+ rpcMsg.iMethod = 0;
+ rpcMsg.Buffer = &dispatchdata;
+ rpcMsg.cbBuffer = sizeof(dispatchdata);
+ rpcMsg.reserved2[1] = &RpcInterfaceInfo;
+ *MSG_TO_IIDPTR(&rpcMsg) = GUID_NULL;
+
+
+ IRpcStubBuffer * pStub = &(pDocData->lpclient->m_pCallMgr);
+ IRpcChannelBuffer * pChannel = &(pDocData->lpclient->m_pCallMgr);
+ hresult = STAInvoke(&rpcMsg, callcat, pStub, pChannel, NULL, &dwFault);
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _OUT DocHandleIncomingCall hresult=%x\n",
+ hresult));
+
+ return(hresult);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DocDispatchIncomingCall
+//
+// Synopsis: Dispatch a call into the client.
+//
+// Effects: This is a co-routine to DocHandleIncomingCall. This routine
+// is called to implement functions that call into the CDefClient
+// object. It is dispatched by the call control stuff, and helps
+// to insure the server is ready to accept these calls.
+//
+// This routine is coded as a continuation of the DocWndProc.
+// There is a switch on the message. Each message does slightly
+// different things. The code to handle each message was snatched
+// from the original DocWndProc, before it was converted to the
+// new call control mechanism.
+//
+//
+// Arguments: [pDocData] -- Points to Doc Dispatch Data, which are the
+// parameters to DocWndProc which need processing
+//
+// Requires:
+// pDocData cannot be NULL
+//
+// Returns:
+// This routine will always return NOERROR. There are no useful
+// error returns to be made from here. If you decide to return
+// an error, check the DocHandleIncomingCall and DocWndProc to be
+// sure the error paths are correctly handled. Some of the
+// cases do additional error processing in the DocWndProc on
+// error.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-05-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL DocDispatchIncomingCall(PDOCDISPATCHDATA pDocData)
+{
+ LPCLIENT lpclient = pDocData->lpclient;
+ BOOL fack;
+ HANDLE hdata = pDocData->hdata;
+ ATOM aItem = pDocData->aItem;
+ WPARAM wParam = pDocData->wParam;
+ HWND hwnd = pDocData->hwnd;
+ HRESULT retval;
+
+
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN DocDispatchIncomingCall pDocData(%x)\n",
+ pDocData));
+
+ intrAssert(pDocData);
+
+ //
+ // This switch statement is intended to continue the functionality found
+ // in the DocWndProc. These routines are directly interrelated to the
+ // same cases in DocWndProc, and need special care before changing.
+ //
+ switch (pDocData->msg)
+ {
+ case WM_DDE_TERMINATE:
+ {
+ intrDebugOut((DEB_ITRACE,
+ "DDIC: WM_DDE_TERMINATE hwnd=%x \n",
+ pDocData->hwnd));
+
+ //
+ // Here is a fine hack for you. 32-bit applications appear to shut
+ // down slightly differently than 16-bit applications. There is a
+ // problem with Lotus Notes interacting with 32-bit OFFICE apps.
+ // When notes has done an OleCreateFromFile, it starts the
+ // 32-bit hidden, and does a normal DDE conversation. However,
+ // on termination, the 32-bit Doc Window was going away during
+ // this routine. Since the world is now multi-tasking, Lotus
+ // Notes was seeing its server window die because we get
+ // pre-empted during DeleteItemsFromList giving the 16-bit app a
+ // chance to run. Since Lotus is in the
+ // standard OleQueryReleaseStatus() loop, it will detect that the
+ // server has shutdown BEFORE it gets the terminate message.
+ // Go figure. So, insure that we post the reply DDE_TERMINATE
+ // before destroying our window, or the 16-bit applications
+ // won't like us.
+ //
+ PostMessageToClient ((HWND)wParam, WM_DDE_TERMINATE,
+ (UINT) hwnd, NULL);
+
+ // Client initiated the termination. So, we should remove
+ // his window from any of our doc or items' lists.
+ lpclient->DeleteFromItemsList ((HWND)wParam
+ /*, lpclient->m_fEmbed*/);
+
+ ChkC (lpclient);
+
+
+ // REVIEW: If the termination is sent from the client side,
+ // lpoleObj will not be NULL.
+ if (lpclient->m_cClients == 0 && lpclient->m_fEmbed)
+ {
+ Assert (lpclient->m_chk==chkDefClient);
+ lpclient->ReleaseAllItems ();
+ Assert (lpclient->m_chk==chkDefClient);
+ Assert (NULL==lpclient->m_lpoleObj &&
+ NULL==lpclient->m_lpdataObj) ;
+
+ }
+ break;
+ }
+
+ case WM_DDE_EXECUTE:
+ {
+
+ intrDebugOut((DEB_ITRACE,
+ "DDIC: WM_DDE_EXECUTE hwnd=%x hdata=%x\n",
+ pDocData->hwnd,
+ pDocData->hdata));
+
+ //
+ // The following state variables appear to be used by
+ // the execute code.
+ //
+ lpclient->m_ExecuteAck.f = TRUE; // assume we will need to
+ lpclient->m_ExecuteAck.hdata = hdata;
+ lpclient->m_ExecuteAck.hwndFrom = (HWND)wParam;
+ lpclient->m_ExecuteAck.hwndTo = hwnd;
+
+ //
+ // In the event that the command is a StdClose, we need
+ // to force the client to stay around for the duration of
+ // the call.
+ //
+ lpclient->m_pUnkOuter->AddRef();
+
+ retval = lpclient->DocExecute (hdata);
+
+ if (lpclient->m_ExecuteAck.f)
+ {
+ lpclient->SendExecuteAck (retval);
+ }
+
+ lpclient->m_pUnkOuter->Release();
+ break;
+
+ }
+ case WM_DDE_POKE:
+ {
+ int iStdItem;
+ intrDebugOut((DEB_ITRACE,
+ "DDIC: WM_DDE_POKE hwnd=%x aItem=%x(%ws) hdata=%x\n",
+ hwnd,
+ aItem,
+ wAtomName(aItem),
+ hdata));
+
+ if (iStdItem = GetStdItemIndex (aItem))
+ {
+ retval = lpclient->PokeStdItems ((HWND)wParam,
+ aItem,
+ hdata,
+ iStdItem);
+ }
+ else
+ {
+ retval = lpclient->PokeData ((HWND)wParam,
+ aItem,
+ hdata);
+ // This is allowed to fail. PowerPoint tries to poke
+ // data with cfFormat=="StdSave" and "StdFont"
+ }
+
+ if (!PostAckToClient((HWND)wParam,hwnd,aItem,retval))
+ {
+ goto errRtn;
+ }
+ break;
+ }
+ case WM_DDE_ADVISE:
+ {
+ intrDebugOut((DEB_ITRACE,
+ "DDIC: WM_DDE_ADVISE hwnd=%x aItem=%x(%ws) hdata=%x\n",
+ hwnd,
+ aItem,
+ wAtomName(aItem),
+ hdata));
+
+ if (IsAdviseStdItems (aItem))
+ {
+ retval = lpclient->AdviseStdItems ((HWND)wParam,
+ aItem,
+ hdata,
+ (BOOL FAR *)&fack);
+ }
+ else
+ {
+ retval = lpclient->AdviseData ((HWND)wParam,
+ aItem,
+ hdata,
+ (BOOL FAR *)&fack);
+ }
+
+ if (fack)
+ {
+ if (!PostAckToClient((HWND)wParam,hwnd,aItem,retval))
+ {
+ GlobalFree(hdata);
+ }
+ }
+ else if (aItem != NULL)
+ {
+ GlobalDeleteAtom (aItem);
+ }
+ break;
+ }
+ case WM_DDE_UNADVISE:
+ {
+ intrDebugOut((DEB_ITRACE,
+ "DDIC: WM_DDE_UNADVISE hwnd=%x aItem=%x(%ws)\n",
+ hwnd,
+ aItem,
+ wAtomName(aItem)));
+
+ retval = lpclient->UnAdviseData ((HWND)wParam, aItem);
+
+ if (!PostAckToClient((HWND)wParam,hwnd,aItem,retval))
+ {
+ goto errRtn;
+ }
+ break;
+ }
+ case WM_DDE_REQUEST:
+ {
+ intrDebugOut((DEB_ITRACE,
+ "DDIC: WM_DDE_REQUEST hwnd=%x aItem=%x(%ws) cfFormat=%x\n",
+ hwnd,
+ aItem,
+ wAtomName(aItem),
+ (USHORT)LOWORD(pDocData->lParam)));
+
+ retval = lpclient->RequestData ((HWND)wParam,
+ aItem,
+ LOWORD(pDocData->lParam),
+ (HANDLE FAR *)&hdata);
+
+ if (retval == NOERROR)
+ {
+ // post the data message and we are not asking for any
+ // acknowledge.
+
+ intrDebugOut((DEB_ITRACE,
+ "DDIC: posting WM_DDE_DATA\n"));
+
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_DATA,hdata,aItem);
+ if (!PostMessageToClient ((HWND)wParam, WM_DDE_DATA, (UINT) hwnd,lp))
+ {
+ // hdata will be freed by the client because fRelease
+ // was set to true by MakeDdeData (called by RequestData)
+
+ DDEFREE(WM_DDE_DATA,lp);
+ goto errRtn;
+ }
+ }
+ else
+ {
+ if (!PostAckToClient((HWND)wParam,hwnd,aItem,retval))
+ {
+ goto errRtn;
+ }
+ }
+ break;
+ }
+ default:
+ //
+ // Whoops, this is very bad. We should never get here.
+ //
+ intrAssert(!"Unknown MSG in DocWndProc: Very Bad indeed");
+
+
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "0 _OUT DocDispatchIncomingCall pDocData(%x) hr = 0\n",
+ pDocData));
+
+ return(NOERROR);
+errRtn:
+ intrDebugOut((DEB_IERROR,
+ "***** ERROR DDIC pDocData(%x) Post ACK failed. \n",
+ pDocData));
+
+ if (aItem != NULL)
+ {
+ GlobalDeleteAtom (aItem);
+ }
+ goto exitRtn;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DocWndProc
+//
+// Synopsis: Document Window Procedure
+//
+// Effects: Processes DDE messages for a document window.
+//
+// Arguments: [hwnd] --
+// [msg] --
+// [wParam] --
+// [lParam] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-05-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+// When running in a VDM, it is possible that this window was dispatched
+// without having a full window handle. This happens when the getmessage
+// was dispatched from 16-bit. Therefore, we need to convert the hwnd to
+// a full hwnd before doing any comparision functions.
+//
+//----------------------------------------------------------------------------
+STDAPI_(LRESULT) DocWndProc (
+HWND hwndIn,
+UINT msg,
+WPARAM wParam,
+LPARAM lParam
+)
+{
+
+ //
+ // Since this is the DocWndProc, we aren't going to initialize
+ // any of the local variables. This function is called as a WNDPROC,
+ // which is pretty often.
+ //
+
+ DOCDISPATCHDATA docData;
+ LPCLIENT lpclient;
+ WORD status=0;
+ HANDLE hdata;
+ ATOM aItem;
+ HRESULT retval;
+ LPOLEOBJECT lpoleObj;
+ HWND hwnd;
+ DebugOnly (HWND hwndClient;)
+
+ // REVIEW: We need to take care of the bug, related to
+ // Excel. Excel does the sys level connection and sends
+ // terminates immediately before making the connection
+ // to the doc level. If we send release to classfactory
+ // app may revoke the classfactory.
+
+
+ // REVIEW: It may not be necessary to do the blocking.
+ // ReVIEW: For fixing the ref count right way for
+ // CreateInstance Vs. WM_DDE_INIT
+
+#ifdef LATER
+ if (AddMessage (hwnd, msg, wParam, lParam, WT_DOC))
+ return 0L;
+#endif
+
+ switch (msg){
+
+ case WM_CREATE:
+ intrDebugOut((DEB_ITRACE,
+ "DocWndProc: CreateWindow hwndIn=%x\n",
+ hwndIn));
+ break;
+
+
+ case WM_DDE_INITIATE:
+ hwnd = ConvertToFullHWND(hwndIn);
+ intrAssert(IsWindowValid(hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+
+ intrDebugOut((DEB_ITRACE,
+ "DocWndProc: WM_DDE_INITIATE hwnd=%x\n",
+ hwnd));
+
+ ChkC(lpclient);
+
+
+ // REVIEW: We may not allow initiates to get thru
+ // while we are waiting for terminates. So, this case
+ // may not arise
+
+ // Need to verify that m_pCI is not NULL during incoming
+ // calls from the client.
+ //
+ if (lpclient->m_fCallData)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "DocWndProc: No initiates while waiting on terminate\n"));
+
+ break;
+ }
+ // if we are the document then respond.
+
+ if (! (lpclient->m_aItem == (ATOM)(HIWORD(lParam))))
+ {
+ break;
+ }
+
+ // We can enterain this client. Put this window in the client list
+ // and acknowledge the initiate.
+
+ if (!AddClient ((LPHANDLE)&lpclient->m_hcli, (HWND)wParam, (HWND)wParam))
+ {
+ break;
+ }
+
+
+ // post the acknowledge
+ DuplicateAtom (LOWORD(lParam));
+ DuplicateAtom (HIWORD(lParam));
+ SSSendMessage ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lParam);
+
+ lpclient->m_cClients++;
+ lpclient->m_fCreatedNotConnected = FALSE;
+ lpoleObj = lpclient->m_lpoleObj;
+
+ // we have added an addref because of createinstance.
+
+ if (lpclient->m_bCreateInst)
+ {
+ lpclient->m_bCreateInst = FALSE;
+ }
+
+ return 1L; // fAckSent
+ break;
+
+
+ case WM_DDE_EXECUTE:
+ {
+ hwnd = ConvertToFullHWND(hwndIn);
+ intrAssert(IsWindowValid(hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+
+ hdata = GET_WM_DDE_EXECUTE_HDATA(wParam,lParam);
+ intrDebugOut((DEB_ITRACE,
+ "DocWndProc: WM_DDE_EXECUTE hwnd=%x hdata=%x\n",
+ hwnd,
+ hdata));
+
+ ChkC(lpclient);
+
+#ifdef FIREWALLS
+ // find the client in the client list.
+ hwndClient = FindClient (lpclient->m_hcli, (HWND)wParam, FALSE);
+ AssertSz (hwndClient, "Client is missing from the server");
+#endif
+ if (!IsWindowValid ((HWND)wParam) || lpclient->m_fCallData)
+ {
+ if (lpclient->m_fCallData)
+ {
+ // This means the terminate has already been sent
+ // to this window (from AdviseSink::OnClose) so
+ // we can ignore the StdCloseDocument.
+ }
+ else
+ {
+ intrAssert(!"Execute received from dead sending window");
+ }
+ // Since we are not sending an ACK, the sender will not
+ // have the chance to free the hCommands handle.
+ DDEFREE(WM_DDE_ACK,lParam);
+ // GlobalFree (hdata);
+ break;
+ }
+
+ //
+ // Fill in the used items in DocData
+ //
+ docData.hwnd = hwnd;
+ docData.msg = msg;
+ docData.wParam = wParam;
+ docData.hdata = hdata;
+ docData.lpclient = lpclient;
+
+ retval = DocHandleIncomingCall(&docData);
+
+ //
+ // If error return, then we didn't call DocDispatchIncomingCall
+ // and therefore need to send a NACK
+ //
+ if (retval != NOERROR)
+ {
+ lpclient->SendExecuteAck (retval);
+ }
+ break;
+ }
+ case WM_DDE_TERMINATE:
+ hwnd = ConvertToFullHWND(hwndIn);
+ intrAssert(IsWindowValid(hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+
+ intrDebugOut((DEB_ITRACE,
+ "DocWndProc: WM_DDE_TERMINATE hwnd=%x\n",
+ hwnd));
+
+ ChkC(lpclient);
+
+ //
+ // If m_fCallData, then we are are waiting for a terminate, which
+ // means we generated the original terminate message. If
+ // this is so, then we are waiting for a reply to the
+ // terminate. Set the AckState and break;
+ //
+ if (lpclient->m_fCallData)
+ {
+ lpclient->SetCallState(SERVERCALLEX_ISHANDLED);
+ break;
+ }
+
+
+#ifdef _DEBUG
+ // find the client in the client list.
+ hwndClient = (HWND)FindClient (lpclient->m_hcli,(HWND)wParam, FALSE);
+ AssertSz(hwndClient, "Client is missing from the server");
+#endif
+ AssertIsDoc (lpclient);
+ Assert (lpclient->m_cClients > 0);
+ lpclient->m_cClients--;
+
+ // Necessary safety bracket
+ lpclient->m_pUnkOuter->AddRef();
+
+ // terminate has to be handled always
+ // The DocHandleIncomingCall() routine will set the
+ // calltype to be CALLTYPE_ASYNC
+ // async calls are never rejected
+
+ docData.hwnd = hwnd;
+ docData.msg = msg;
+ docData.wParam = wParam;
+ docData.lpclient = lpclient;
+
+ retval = DocHandleIncomingCall(&docData);
+
+ intrAssert(retval == NOERROR);
+
+ // Necessary safety bracket
+ lpclient->m_pUnkOuter->Release();
+ break;
+
+ case WM_DESTROY:
+
+ intrDebugOut((DEB_ITRACE,
+ "DocWndProc: WM_DESTROY\n"));
+ break;
+
+ case WM_DDE_POKE:
+ {
+ hwnd = ConvertToFullHWND(hwndIn);
+ intrAssert(IsWindowValid(hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+ hdata = GET_WM_DDE_POKE_HDATA(wParam,lParam);
+ aItem = GET_WM_DDE_POKE_ITEM(wParam,lParam);
+ ChkC(lpclient);
+
+ if (!IsWindowValid ((HWND) wParam) || lpclient->m_fCallData)
+ {
+ // The sending window is invalid or we have already sent a
+ // TERMINATE to it (as indicated by m_pCI != NULL).
+ // We cannot ACK the message, so we must free any
+ // handles or atoms.
+ Warn ("Ignoring message");
+
+ FreePokeData (hdata);
+LDeleteAtom:
+
+ if (aItem != NULL)
+ {
+ GlobalDeleteAtom (aItem);
+ }
+ break;
+ }
+
+ docData.hwnd = hwnd;
+ docData.msg = msg;
+ docData.wParam = wParam;
+ docData.hdata = hdata;
+ docData.aItem = aItem;
+ docData.lpclient = lpclient;
+
+ retval = DocHandleIncomingCall(&docData);
+ if (retval != NOERROR)
+ {
+ SET_MSG_STATUS (retval, status);
+
+ // !!! If the fRelease is false and the post fails
+ // then we are not freeing the hdata. Are we supposed to
+
+ // REVIEW: The assumption is
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
+ if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (UINT) hwnd,lp))
+ {
+ DDEFREE(WM_DDE_ACK,lp);
+ goto LDeleteAtom;
+ }
+ }
+ // johannp: set the busy bit here in the status word
+ break;
+ }
+
+
+ case WM_DDE_ADVISE:
+ {
+ hwnd = ConvertToFullHWND(hwndIn);
+ intrAssert(IsWindowValid(hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+ HANDLE hOptions = GET_WM_DDE_ADVISE_HOPTIONS(wParam,lParam);
+ aItem = GET_WM_DDE_ADVISE_ITEM(wParam,lParam);
+
+ ChkC(lpclient);
+ if (!IsWindowValid ((HWND)wParam) || lpclient->m_fCallData)
+ {
+AdviseErr:
+ Warn ("Ignoring advise message");
+ //
+ // GlobalFree wants a handle, we are giving it a DWORD.
+ //
+ GlobalFree (hOptions);
+ break;
+ }
+ docData.hwnd = hwnd;
+ docData.msg = msg;
+ docData.wParam = wParam;
+ docData.hdata = hOptions;
+ docData.aItem = aItem;
+ docData.lpclient = lpclient;
+
+ retval = DocHandleIncomingCall(&docData);
+
+ if (retval != NOERROR)
+ {
+ SET_MSG_STATUS (retval, status);
+
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
+
+ if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (UINT) hwnd,lp))
+ {
+ DDEFREE(WM_DDE_ACK,lp);
+ goto AdviseErr;
+ }
+ }
+ break;
+ }
+ case WM_DDE_UNADVISE:
+ {
+ hwnd = ConvertToFullHWND(hwndIn);
+ intrAssert(IsWindowValid(hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+
+ aItem = HIWORD(lParam);
+ ChkC(lpclient);
+ if (!IsWindowValid ((HWND)wParam) || lpclient->m_fCallData)
+ {
+ goto LDeleteAtom;
+ }
+ docData.hwnd = hwnd;
+ docData.msg = msg;
+ docData.wParam = wParam;
+ docData.aItem = aItem;
+ docData.lpclient = lpclient;
+
+ retval = DocHandleIncomingCall(&docData);
+
+ if (retval != NOERROR)
+ {
+ SET_MSG_STATUS (retval, status);
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
+
+ if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (UINT) hwnd,lp))
+ {
+ DDEFREE(WM_DDE_ACK,lp);
+ goto LDeleteAtom;
+ }
+ }
+
+ break;
+ }
+ case WM_DDE_REQUEST:
+ {
+ hwnd = ConvertToFullHWND(hwndIn);
+ intrAssert(IsWindowValid(hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+
+ aItem = HIWORD(lParam);
+
+ ChkC(lpclient);
+ if (!IsWindowValid ((HWND) wParam) || lpclient->m_fCallData)
+ {
+ goto LDeleteAtom;
+ }
+ docData.hwnd = hwnd;
+ docData.msg = msg;
+ docData.wParam = wParam;
+ docData.lParam = lParam;
+ docData.aItem = aItem;
+ docData.lpclient = lpclient;
+
+ retval = DocHandleIncomingCall(&docData);
+ if (retval != NOERROR)
+ {
+ if (retval == RPC_E_DDE_BUSY)
+ {
+ status = 0x4000;
+ }
+ else
+ {
+ status = 0; // negative acknowledge
+ }
+
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
+ // if request failed, then acknowledge with error.
+ if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (UINT) hwnd,lp))
+ {
+ DDEFREE(WM_DDE_ACK,lp);
+ goto LDeleteAtom;
+ }
+ }
+ break;
+ }
+ default:
+ return SSDefWindowProc (hwndIn, msg, wParam, lParam);
+
+ }
+
+ return 0L;
+
+}
+
+
+
+
+INTERNAL_(void) CDefClient::SendExecuteAck
+ (HRESULT hresult)
+{
+ AssertIsDoc (this);
+ WORD status = NULL;
+ SET_MSG_STATUS (hresult, status);
+
+ m_ExecuteAck.f = FALSE;
+
+ LPARAM lParam = MAKE_DDE_LPARAM (WM_DDE_ACK,status,
+ (UINT) m_ExecuteAck.hdata);
+ // Post the acknowledge to the client
+ if (!PostMessageToClient (m_ExecuteAck.hwndFrom, WM_DDE_ACK,
+ (UINT) m_ExecuteAck.hwndTo, lParam))
+ {
+ Assert (0);
+ // the window either died or post failed, delete the data
+ DDEFREE (WM_DDE_ACK,lParam);
+ GlobalFree (m_ExecuteAck.hdata);
+ }
+}
+
+
+
+//DocExecute: Interprets the execute command for the
+//document conversation.
+
+
+INTERNAL CDefClient::DocExecute
+ (HANDLE hdata)
+{
+
+ ATOM acmd;
+ BOOL fShow;
+ BOOL fActivate;
+
+ HANDLE hdup = NULL;
+ HRESULT retval = ReportResult(0, S_OOM, 0, 0);
+
+ LPSTR lpitemname;
+ LPSTR lpopt;
+ LPSTR lpnextarg;
+ LPSTR lpdata = NULL;
+ LPSTR lpverb = NULL;
+ INT verb;
+ WORD wCmdType;
+
+ ChkC(this);
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CDefClient::DocExecute(hdata=%x)\n",
+ this,
+ hdata));
+
+ // !!!Can we modify the string which has been passed to us
+ // rather than duplicating the data. This will get some speed
+ // and save some space.
+
+ if(!(hdup = UtDupGlobal(hdata,GMEM_MOVEABLE)))
+ goto errRtn;
+
+ if (!(lpdata = (LPSTR)GlobalLock (hdup)))
+ goto errRtn;
+
+ retval = ReportResult(0, RPC_E_DDE_SYNTAX_EXECUTE, 0, 0);
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CDefClient::DocExecute command=(%s)\n",
+ this,
+ lpdata));
+
+ if(*lpdata++ != '[') // commands start with the left sqaure bracket
+ goto errRtn;
+
+ // scan the command and scan upto the first arg.
+ if (!(wCmdType = ScanCommand(lpdata, WT_DOC, &lpnextarg, &acmd)))
+ goto errRtn;
+
+ if (wCmdType == NON_OLE_COMMAND) {
+
+#ifdef LATER
+ if (lpsrvr = (LPSRVR) GetWindowLong (GetParent (hwnd), 0)) {
+ if (!UtilQueryProtocol (lpsrvr->aClass, PROTOCOL_EXECUTE))
+ retval = OLE_ERROR_PROTOCOL;
+ else {
+#ifdef FIREWALLS
+ if (!CheckPointer (lpoledoc, WRITE_ACCESS))
+ AssertSz (0, "Invalid LPOLESERVERDOC");
+ else if (!CheckPointer (lpoledoc->lpvtbl, WRITE_ACCESS))
+ AssertSz (0, "Invalid LPOLESERVERDOCVTBL");
+ else
+ AssertSz (lpoledoc->lpvtbl->Execute,
+ "Invalid pointer to Execute method");
+#endif
+
+ retval = (*lpoledoc->lpvtbl->Execute) (lpoledoc, hdata);
+ }
+
+ }
+#endif
+ AssertSz(0, "Doc level execute is being called");
+
+ goto errRtn;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdCloseDocument]
+ //
+ //////////////////////////////////////////////////////////////////////////
+ if (acmd == aStdClose){
+
+ LPCLIENT lpclient=NULL;
+ // if not terminated by NULL error
+ if (*lpnextarg)
+ goto errRtn;
+
+ if ((retval = FindItem (NULL, (LPCLIENT FAR *)&lpclient)) != NOERROR)
+ return retval;
+
+
+ lpclient->m_fGotStdCloseDoc = TRUE;
+ retval = lpclient->m_lpoleObj->Close (OLECLOSE_SAVEIFDIRTY);
+ goto end;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdDoVerbItem("itemname", verb, BOOL, BOOL]
+ //
+ //////////////////////////////////////////////////////////////////////////
+ if (acmd == aStdDoVerbItem){
+ lpitemname = lpnextarg;
+
+ if(!(lpverb = ScanArg(lpnextarg)))
+ goto errRtn;
+
+
+ if(!(lpnextarg = ScanNumArg(lpverb, &verb)))
+ goto errRtn;
+
+#ifdef FIREWALLS
+ AssertSz (verb < 9 , "Unexpected verb number");
+#endif
+
+ // now scan the show BOOL
+
+ if (!(lpnextarg = ScanBoolArg (lpnextarg, (BOOL FAR *)&fShow)))
+ goto errRtn;
+
+ fActivate = FALSE;
+
+ // if activate BOOL is present, scan it.
+
+ if (*lpnextarg) {
+ if (!(lpnextarg = ScanBoolArg (lpnextarg, (BOOL FAR *)&fActivate)))
+ goto errRtn;
+ }
+
+ if (*lpnextarg)
+ goto errRtn;
+
+ if (m_fEmbed)
+ {
+ // This is a totally bogus call to SetHostNames whose only
+ // purpose is to notify the server that this is an embedded
+ // (not linked) object.
+ if (!m_fDidRealSetHostNames)
+ {
+ Puts ("Bogus call to SetHostNames before DoVerb\r\n");
+ m_lpoleObj->SetHostNames (OLESTR("Container"), OLESTR("Object"));
+ }
+ }
+ // REVIEW: We are assuming that calling the Docdoverb method
+ // will not post any more DDE messahes.
+
+ retval = DocDoVerbItem (lpitemname, verb, fShow, !fActivate);
+ goto end;
+ }
+
+
+
+
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdShowItem("itemname"[, "true"])]
+ //
+ //////////////////////////////////////////////////////////////////////////
+ if (acmd != aStdShowItem)
+ goto errRtn;
+
+ lpitemname = lpnextarg;
+
+ if(!(lpopt = ScanArg(lpitemname)))
+ goto errRtn;
+
+ // Now scan for optional parameter.
+
+ fActivate = FALSE;
+
+ if (*lpopt) {
+
+ if(!(lpnextarg = ScanBoolArg (lpopt, (BOOL FAR *)&fActivate)))
+ goto errRtn;
+
+ if (*lpnextarg)
+ goto errRtn;
+
+
+ }
+
+ if (m_fEmbed)
+ {
+ // This is a totally bogus call to SetHostNames whose only
+ // purpose is to notify the server that this is an embedded
+ // (not linked) object.
+ // REVIEW LINK
+ if (!m_fDidRealSetHostNames)
+ {
+ Puts ("Bogus call to SetHostNames before ShowItem\r\n");
+ m_lpoleObj->SetHostNames (OLESTR("Container"), OLESTR("Object"));
+ }
+ }
+
+ retval = DocShowItem (lpitemname, !fActivate);
+
+end:
+errRtn:
+ if (lpdata)
+ GlobalUnlock (hdup);
+
+ if (hdup)
+ GlobalFree (hdup);
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT CDefClient::DocExecute(hdata=%x) hresult=%x\n",
+ this,
+ hdata,
+ retval));
+
+ return (HRESULT)retval;
+}
+
+
+
+INTERNAL_(HRESULT) CDefClient::DocShowItem
+(
+LPSTR lpAnsiitemname,
+BOOL fAct
+)
+{
+ LPCLIENT lpclient;
+ HRESULT retval;
+ LPOLEOBJECT lpoleObj;
+
+ ChkC(this);
+ WCHAR lpitemname[MAX_STR];
+
+ if (MultiByteToWideChar(CP_ACP,0,lpAnsiitemname,-1,lpitemname,MAX_STR) == FALSE)
+ {
+ Assert(!"Unable to convert characters");
+ return(E_UNEXPECTED);
+ }
+
+ if ((retval = FindItem (lpitemname, (LPCLIENT FAR *)&lpclient))
+ != NOERROR)
+ return retval;
+
+ ChkC(lpclient);
+
+ lpoleObj = lpclient->m_lpoleObj;
+
+
+#ifdef FIREWALLS1
+ if (!CheckPointer (lpoleObj->lpvtbl, WRITE_ACCESS))
+ AssertSz (0, "Invalid LPOLEOBJECTVTBL");
+ else
+ AssertSz (lpoleObj->lpvtbl->DoVerb,
+ "Invalid pointer to DoVerb method");
+#endif
+
+ // protocol sends false for activating and TRUE for not activating.
+ // for api send TRUE for avtivating and FALSE for not activating.
+ return lpclient->m_lpoleObj->DoVerb(OLEVERB_SHOW, NULL, NULL, NULL, NULL, NULL);
+}
+
+
+
+INTERNAL_(HRESULT) CDefClient::DocDoVerbItem
+(
+LPSTR lpAnsiitemname,
+WORD verb,
+BOOL fShow,
+BOOL fAct
+)
+{
+ LPCLIENT lpclient;
+ HRESULT retval;
+
+ WCHAR lpitemname[MAX_STR];
+
+ if (MultiByteToWideChar(CP_ACP,0,lpAnsiitemname,-1,lpitemname,MAX_STR) == FALSE)
+ {
+ Assert(!"Unable to convert characters");
+ return(E_UNEXPECTED);
+ }
+
+ ChkC(this);
+ Puts ("DefClient::DocDoVerbItem\r\n");
+ if ((retval = FindItem (lpitemname, (LPCLIENT FAR *)&lpclient))
+ != NOERROR)
+ return retval;
+ ChkC(lpclient);
+
+#ifdef FIREWALLS1
+ if (!CheckPointer (lpclient->lpoleObj->lpvtbl, WRITE_ACCESS))
+ AssertSz (0, "Invalid LPOLEOBJECTVTBL");
+ else
+ AssertSz (lpclient->lpoleObj->lpvtbl->DoVerb,
+ "Invalid pointer to DoVerb method");
+#endif
+
+ // pass TRUE to activate and False not to activate. Differnt from
+ // protocol.
+
+ retval = lpclient->m_lpoleObj->DoVerb(verb, NULL, &m_OleClientSite, NULL, NULL, NULL);
+ // Apparently an obsolete version of Lotus Notes is the only
+ // container (other than Cltest) that sets fShow=FALSE
+ if (!fShow && lpclient->m_lpoleObj && lpclient->m_fEmbed)
+ lpclient->m_lpoleObj->DoVerb(OLEIVERB_HIDE, NULL, &m_OleClientSite, NULL, NULL, NULL);
+ return retval;
+}
+
+INTERNAL CDefClient::DoInitNew()
+{
+ HRESULT hresult;
+ ATOM aClass;
+ LPPERSISTSTORAGE pPersistStg=NULL;
+
+ hresult = m_lpoleObj->QueryInterface(IID_IPersistStorage,
+ (LPLPVOID)&pPersistStg);
+ if (hresult == NOERROR)
+ {
+ CLSID clsid;
+ RetZ (pPersistStg);
+ ErrRtnH (CreateILockBytesOnHGlobal ((HGLOBAL)NULL,
+ /*fDeleteOnRelease*/ TRUE,
+ &m_plkbytNative));
+ ErrZS (m_plkbytNative, E_OUTOFMEMORY);
+
+ ErrRtnH (StgCreateDocfileOnILockBytes
+ (m_plkbytNative,
+ grfCreateStg, 0,
+ &m_pstgNative));
+
+ ErrZS (m_pstgNative, E_OUTOFMEMORY);
+
+ aClass = m_psrvrParent->m_cnvtyp == cnvtypTreatAs ? m_psrvrParent->m_aOriginalClass
+ : m_psrvrParent->m_aClass;
+ // Write appropriate class tag
+ ErrZS (CLSIDFromAtom (aClass,(LPCLSID)&clsid),
+ REGDB_E_CLASSNOTREG);
+ ErrRtnH (WriteClassStg (m_pstgNative, clsid));
+
+ // Provide server with a storage to use for its persistent
+ // storage, i.e., native data. We remember this IStorage and the
+ // ILockBytes it is built on.
+ ErrRtnH (pPersistStg->InitNew(m_pstgNative));
+ m_fGotEditNoPokeNativeYet = FALSE;
+
+ // Now that we have initialized the object, we are allowed to
+ // set the client site, and advise.
+ ErrRtnH (SetClientSite());
+
+ // This is for Packager, in particular. If client does not advise
+ // on any data, we still need to do an OLE advise so we can get
+ // OnClose notifications.
+ DoOle20Advise (OLE_CLOSED, (CLIPFORMAT)0);
+ }
+ else
+ {
+ AssertSz (0, "Can't get IPersistStorage from OleObj\r\n");
+ }
+
+ m_fEmbed = TRUE;
+
+errRtn:
+ if (pPersistStg)
+ pPersistStg->Release();
+ return hresult;
+}
+
+
+// FreePokeData: Frees the poked dats.
+INTERNAL_(void) FreePokeData
+(
+HANDLE hdde
+)
+{
+ DDEPOKE FAR * lpdde;
+ Puts ("FreePokeData\r\n");
+
+ if (hdde) {
+ if (lpdde = (DDEPOKE FAR *) GlobalLock (hdde)) {
+ GlobalUnlock (hdde);
+ FreeGDIdata (*(LPHANDLE)lpdde->Value, lpdde->cfFormat);
+ }
+
+ GlobalFree (hdde);
+ }
+}
+
+
+
+// Returns TRUE if GDI format else returns FALSE
+
+INTERNAL_(BOOL) FreeGDIdata
+(
+HANDLE hData,
+CLIPFORMAT cfFormat
+)
+{
+ Puts ("FreeGDIData\r\n");
+ if (cfFormat == CF_METAFILEPICT) {
+ LPMETAFILEPICT lpMfp;
+
+ if (lpMfp = (LPMETAFILEPICT) GlobalLock (hData)) {
+ GlobalUnlock (hData);
+ DeleteMetaFile (lpMfp->hMF);
+ }
+
+ GlobalFree (hData);
+ }
+ else if (cfFormat == CF_BITMAP)
+ DeleteObject (hData);
+ else if (cfFormat == CF_DIB)
+ GlobalFree (hData);
+ else
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/private/ole32/com/dde/server/item.cxx b/private/ole32/com/dde/server/item.cxx
new file mode 100644
index 000000000..f268cdbcc
--- /dev/null
+++ b/private/ole32/com/dde/server/item.cxx
@@ -0,0 +1,1210 @@
+/****************************** Module Header ******************************\
+* Module Name: Item.c Object(item) main module
+*
+* Purpose: Includes All the object releated routiens.
+*
+* Created: Oct 1990.
+*
+* Copyright (c) 1990, 1991 Microsoft Corporation
+*
+* History:
+* Raor (../10/1990) Designed, coded
+*
+*
+\***************************************************************************/
+
+
+#include "ole2int.h"
+//#include "cmacs.h"
+#include <dde.h>
+#include "ddeatoms.h"
+#include "ddedebug.h"
+#include "srvr.h"
+#include "itemutil.h"
+
+ASSERTDATA
+
+
+// !!!change child enumeration.
+// !!!No consistency in errors (Sometimes Bools and sometimes HRESULT).
+
+
+//SearchItem: Searches for a given item in a document tree.
+//If found, returns the corresponding client ptr.
+
+INTERNAL_(LPCLIENT) CDefClient::SearchItem
+(
+LPOLESTR lpitemname
+)
+
+{
+ ATOM aItem;
+ LPCLIENT lpclient;
+
+ ChkC(this);
+ Assert (m_pdoc==this);
+ Assert (m_bContainer);
+
+ Puts ("DefClient::SearchItem\r\n");
+ // If the item passed is an atom, get its name.
+ if (!HIWORD(lpitemname))
+ aItem = (ATOM) (LOWORD((DWORD)lpitemname));
+ else if (!lpitemname[0])
+ aItem = NULL;
+ else
+ aItem = GlobalFindAtom (lpitemname);
+
+ // walk thru the items list and mtach for the itemname.
+ lpclient = this;
+
+ while (lpclient) {
+ ChkC(lpclient);
+ if (lpclient->m_aItem == aItem)
+ return lpclient;
+ // The NULL item is the client that is a container (the whole doc).
+ // REVIEW: jasonful
+ if (lpclient->m_bContainer && aItem==NULL)
+ return lpclient;
+ lpclient = lpclient->m_lpNextItem;
+ }
+
+ Puts ("SearchItem failed\r\n");
+ return NULL;
+
+}
+
+
+
+// FindItem: Given the itemname and the doc obj ptr,
+// searches for the the item (object) in the document tree.
+// Items are lonked to the doc obj.
+
+INTERNAL_(HRESULT) CDefClient::FindItem
+(
+LPOLESTR lpitemname,
+LPCLIENT FAR * lplpclient
+)
+{
+ LPCLIENT lpclient;
+ WCHAR buf[MAX_STR];
+
+ Puts ("DefClient::FindItem "); Puts (lpitemname); Putn();
+ ChkC(this);
+
+ if (lpclient = SearchItem (lpitemname)) {
+ // we found the item window
+
+ ChkC(lpclient);
+ *lplpclient = lpclient;
+ return NOERROR;
+
+ }
+
+ if (!HIWORD(lpitemname)){
+ if (LOWORD(lpitemname))
+ GlobalGetAtomName ((ATOM)LOWORD((DWORD)lpitemname),
+ buf, MAX_STR);
+ else
+ buf[0] = NULL;
+
+ lpitemname = buf;
+ }
+
+ // Item (object)window is not created yet. Let us create one.
+ return RegisterItem (lpitemname, lplpclient, TRUE);
+}
+
+
+
+//RegisterItem: Given the document handle and the item string
+//creates item with the given name in the doc obj list..
+
+INTERNAL CDefClient::RegisterItem
+ (LPOLESTR lpitemname,
+ LPCLIENT FAR * lplpclient,
+ BOOL bSrvr)
+{
+ LPCLIENT pitemNew = NULL;
+ HRESULT hresult = ReportResult(0, E_UNEXPECTED, 0, 0);
+ LPOLEOBJECT lpoleObj = NULL;
+ LPOLEITEMCONTAINER lpcontainer;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::RegisterItem(%ws)\n",
+ this,WIDECHECK(lpitemname)));
+ ChkC(this);
+ AssertIsDoc(this);
+ *lplpclient = NULL;
+
+ ErrZS (pitemNew = new CDefClient(NULL), E_OUTOFMEMORY);
+
+ pitemNew->m_bTerminate = FALSE;
+ pitemNew->m_bContainer = FALSE; // not a container, i.e.,document
+
+
+ // Set containing document
+ pitemNew->m_pdoc = this;
+ m_pUnkOuter->AddRef(); // item keeps its document alive
+ // Corresponding Release is in CDefClient::~CDefClient
+
+ if (!HIWORD(lpitemname)) {
+ AssertSz (!bSrvr, "invalid lpitemname in RegisterItem\r\n");
+ pitemNew->m_aItem = LOWORD((DWORD)lpitemname);
+ }
+ else if (!lpitemname[0])
+ pitemNew->m_aItem = NULL;
+ else
+ pitemNew->m_aItem = wGlobalAddAtom (lpitemname);
+
+ lpoleObj = m_lpoleObj;
+
+ // Call the server if the item is not one of the standard items.
+ if (bSrvr) {
+
+ // Call the server app for container interface
+ hresult = lpoleObj->QueryInterface (IID_IOleItemContainer, (LPVOID FAR *)&lpcontainer);
+
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "%x ::RegisterItem(%ws) No IOleContainer intr\n",
+ this,WIDECHECK(lpitemname)));
+ goto errRtn;
+ }
+
+ hresult = lpcontainer->GetObject(lpitemname, BINDSPEED_INDEFINITE, 0,
+ IID_IOleObject, (LPLPVOID)&pitemNew->m_lpoleObj);
+
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_ERROR,
+ "IOleItemContainer::GetObject(%ws,...) failed (hr=%x)\n",
+ lpitemname,
+ hresult));
+ }
+
+ lpcontainer->Release ();
+ if (hresult != NOERROR)
+ goto errRtn;
+
+ hresult = pitemNew->m_lpoleObj->QueryInterface (IID_IDataObject, (LPLPVOID)
+ &pitemNew->m_lpdataObj);
+
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_ERROR,
+ "::QueryInterface(IID_IDataObject) failed (hr=%x)\n",
+ hresult));
+ pitemNew->m_lpoleObj->Release();
+ goto errRtn;
+ }
+
+
+ // This is for Packager, in particular. If client does not advise
+ // on any data, we still need to do an OLE advise so we can get
+ // OnClose notifications.
+ pitemNew->DoOle20Advise (OLE_CLOSED, (CLIPFORMAT)0);
+ }
+
+
+
+ // This keeps the CDefClient alive until _we_ are done with it
+ // The corresponding Release is in CDefClient::Revoke
+ pitemNew->m_pUnkOuter->AddRef();
+
+ pitemNew->m_lpNextItem = m_lpNextItem;
+ pitemNew->m_hwnd = m_hwnd; // set the window handle to
+ // same as the doc level window
+
+ m_lpNextItem = pitemNew;
+ *lplpclient = pitemNew;
+
+ hresult = NOERROR;
+ goto exitRtn;
+
+errRtn:
+ if (pitemNew) {
+ delete pitemNew;
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x CDefClient::RegisterItem(%ws) hresult=%x\n",
+ this,WIDECHECK(lpitemname),hresult));
+
+
+ return(hresult);
+}
+
+
+
+// Return NOERROR if "this" document has no items which have connections
+// (client windows).
+//
+INTERNAL CDefClient::NoItemConnections (void)
+{
+ PCLINFO pclinfo = NULL;
+ HANDLE hcliPrev = NULL;
+ HANDLE hcli;
+ PCLILIST pcli;
+ HANDLE *phandle;
+
+ ChkCR (this);
+ AssertIsDoc (this);
+ LPCLIENT pitem;
+ for (pitem = m_lpNextItem;
+ pitem;
+ pitem = pitem->m_lpNextItem)
+ {
+ ChkCR (pitem);
+ if (pitem->m_aItem == aStdDocName)
+ continue;
+ hcli = pitem->m_hcliInfo;
+ while (hcli)
+ {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ return ResultFromScode (S_FALSE);
+
+ phandle = (HANDLE *) (pcli->info);
+ while (phandle < (HANDLE *)(pcli + 1))
+ {
+ if (*phandle)
+ {
+ LocalUnlock (hcli);
+ return ResultFromScode (S_FALSE);
+ }
+ else
+ {
+ phandle++;
+ phandle++;
+ }
+ }
+
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ }
+ }
+ return NOERROR;
+}
+
+
+
+INTERNAL_(void) CDefClient::DeleteAdviseInfo (void)
+{
+
+
+ PCLINFO pclinfo = NULL;
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+ HANDLE hcli;
+ HANDLE hcliInfo;
+
+ Puts ("DefClient::DeleteAdviseInfo\r\n");
+ ChkC(this);
+ hcli = m_hcliInfo;
+ while (hcli) {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ return;
+
+ phandle = (HANDLE *) (pcli->info);
+ while (phandle < (HANDLE *)(pcli + 1)) {
+ if (*phandle) {
+ *phandle++ = 0;
+
+ // delete the printer dev info block
+ if(pclinfo = (PCLINFO)LocalLock ((hcliInfo = *phandle++))){
+ if(pclinfo->hdevInfo)
+ GlobalFree (pclinfo->hdevInfo);
+
+ LocalUnlock (hcliInfo);
+ // no free if lock failed
+ LocalFree (hcliInfo);
+ }
+ } else {
+ phandle++;
+ phandle++;
+
+ }
+ }
+
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ LocalFree (hcliPrev); // free the block;
+ }
+ m_hcliInfo = NULL;
+}
+
+
+
+//DeleteFromItemsList: Deletes a client from the object lists of
+//all the objects of a given document. Thie client possibly
+//is terminating the conversation with our doc window.
+//
+INTERNAL_(void) CDefClient::DeleteFromItemsList
+ (HWND hwndClient)
+{
+ HANDLE hclinfo;
+ PCLINFO pclinfo;
+ LPCLIENT lpclient;
+ LPCLIENT FAR* ppitemLast = NULL;
+ BOOL fRevokedDoc = FALSE;
+ static int staticcounter;
+ int counter = ++staticcounter;
+
+ Puts ("DefClient::DeleteFromItemsList "); Puti(counter); Putn();
+ AssertIsDoc(this);
+ lpclient = this;
+ ppitemLast = &m_lpNextItem;
+ while (lpclient)
+ {
+ ChkC(lpclient);
+ BOOL fDoc = (lpclient==this);
+ if (fDoc)
+ {
+ AssertIsDoc (lpclient);
+ // Remove window from doc's master list
+ HWND hwnd = (HWND) FindClient (lpclient->m_hcli, hwndClient, /*fDelete*/TRUE);
+ Assert (hwnd==hwndClient);
+ }
+
+ hclinfo = FindClient (lpclient->m_hcliInfo, hwndClient, /*fDelete*/TRUE);
+ LPCLIENT pitemNext = lpclient->m_lpNextItem;
+
+ // We must make sure no other client is connected (linked)
+ // to this item before deleting.
+ if (!fDoc && AreNoClients (lpclient->m_hcliInfo))
+ {
+ Assert (ppitemLast);
+ if (ppitemLast && !fDoc)
+ {
+ // Remove from linked list
+ *ppitemLast = lpclient->m_lpNextItem;
+ }
+ fRevokedDoc |= fDoc;
+ lpclient->Revoke ();
+ }
+ else
+ {
+ ppitemLast = &(lpclient->m_lpNextItem);
+ }
+ if (hclinfo)
+ {
+ if(pclinfo = (PCLINFO)LocalLock (hclinfo))
+ {
+ if(pclinfo->hdevInfo)
+ GlobalFree (pclinfo->hdevInfo);
+ LocalUnlock (hclinfo);
+ }
+ LocalFree (hclinfo);
+ }
+ lpclient = pitemNext;
+ }
+
+ // Handle invisible update
+ if (!fRevokedDoc && !m_fEmbed //&& !m_fGotDdeAdvise
+ && NOERROR ==NoItemConnections()
+ && AreNoClients (m_hcliInfo)
+ && AreNoClients (m_hcli) )
+ {
+ ChkC (this);
+ Assert (m_lpoleObj);
+ Assert (m_lpdataObj);
+ ReleaseObjPtrs();
+ }
+
+ Puts ("DefClient::DeleteFromItemsList Done "); Puti(counter); Putn();
+}
+
+
+INTERNAL_(void) CDefClient::RemoveItemFromItemList
+ (void)
+{
+ // Make sure it's an item
+ Assert (m_pdoc != this && !m_bContainer);
+
+ LPCLIENT lpclient = m_pdoc;
+ ChkC (lpclient);
+ LPCLIENT FAR* ppitemLast = &(m_pdoc->m_lpNextItem);
+
+ while (lpclient)
+ {
+ ChkC(lpclient);
+ if (lpclient==this)
+ {
+ // Remove from linked list
+ *ppitemLast = lpclient->m_lpNextItem;
+ break;
+ }
+ ppitemLast = &(lpclient->m_lpNextItem);
+ lpclient = lpclient->m_lpNextItem;
+ }
+ Revoke();
+}
+
+
+
+
+INTERNAL_(void) CDefClient::ReleaseAllItems ()
+{
+ LPCLIENT lpclient;
+
+ Puts ("DefClient::ReleaseAllItems\r\n");
+ AssertIsDoc(this);
+
+ // leave the doc level object.
+ lpclient = m_lpNextItem;
+
+ while (lpclient)
+ {
+ ChkC(this);
+ LPCLIENT pitemNext = lpclient->m_lpNextItem;
+ lpclient->Revoke();
+ lpclient = pitemNext;
+ }
+ // After revoking all the items, we can't keep any refernces to them.
+ m_lpNextItem = NULL;
+}
+
+
+
+INTERNAL_(void) CDefClient::DeleteAllItems ()
+{
+ LPCLIENT lpclient;
+
+ Puts ("DefClient::DeleteAllItems\r\n");
+ AssertIsDoc(this);
+
+ // leave the doc level object.
+ lpclient = m_lpNextItem;
+
+ while (lpclient)
+ {
+ ChkC(lpclient);
+ if (ISATOM(lpclient->m_aItem))
+ GlobalDeleteAtom (lpclient->m_aItem);
+ // Delete client advise info
+ lpclient->DeleteAdviseInfo ();
+
+ lpclient = lpclient->m_lpNextItem;
+ }
+}
+
+
+
+
+// PokeData: Prepares and gives the data to the server app thru
+// the SetData object method.
+
+INTERNAL CDefClient::PokeData(HWND hwndClient,ATOM aItem,HANDLE hPoke)
+{
+ HRESULT hresult = ReportResult(0, E_UNEXPECTED, 0, 0);
+ DDEPOKE FAR * lpPoke = NULL;
+ int format;
+ BOOL fRelease = FALSE;
+ LPPERSISTSTORAGE pPersistStg=NULL;
+ FORMATETC formatetc;
+ STGMEDIUM medium;
+
+ // Due to a C7 bug, do not use a structure initialization for STGMEDIUM
+ medium.tymed = TYMED_HGLOBAL;
+ medium.hGlobal = NULL; // invalid
+ medium.pUnkForRelease= NULL;
+
+ intrDebugOut((DEB_ITRACE,
+ "%p CDefClient::PokeData(hwndClient=%x,aItem=%x,hPoke=%x)\n",
+ this,hwndClient,aItem,hPoke));
+
+ ChkC(this);
+ AssertIsDoc (this);
+
+
+ // Until now, m_aItem had been the client-generated (ugly) document name.
+ // Now it becomes the actual item name, which will almost always be NULL.
+ // Only in the TreatAs/ConvertTo case will it be non-NULL.
+ m_aItem = aItem;
+
+ formatetc.cfFormat = 0; /* invalid */
+ formatetc.ptd = m_ptd;
+ formatetc.lindex = DEF_LINDEX;
+ formatetc.dwAspect = DVASPECT_CONTENT;
+ formatetc.tymed = TYMED_HGLOBAL;
+
+ ErrZS (hPoke && (lpPoke = (DDEPOKE FAR *) GlobalLock (hPoke)),
+ E_OUTOFMEMORY);
+
+ format = formatetc.cfFormat = (UINT)(unsigned short)lpPoke->cfFormat;
+ Assert (format);
+ fRelease = lpPoke->fRelease;
+
+ // We found the item. Now prepare the data to be given to the object
+ // MakeItemData returns a newly allocated handle.
+ if (!(medium.hGlobal = MakeItemData (lpPoke, hPoke, format)))
+ goto errRtn;
+
+ // Change type acording to format (not that default has been set above)
+ if (format == CF_METAFILEPICT)
+ formatetc.tymed = medium.tymed = TYMED_MFPICT;
+ else
+ if (format == CF_BITMAP)
+ formatetc.tymed = medium.tymed = TYMED_GDI;
+
+ // Now send the data to the object
+
+
+ if (formatetc.cfFormat==g_cfNative)
+ {
+ m_fGotEditNoPokeNativeYet = FALSE;
+
+ // Cannot do SetData. Must do PersisStg::Load on an IStorage
+ // made from the native data, i.e., medium.hGlobal.
+
+ Assert (m_plkbytNative==NULL);
+ ErrRtnH (CreateILockBytesOnHGlobal (medium.hGlobal,
+ /*fDeleteOnRelease*/TRUE,
+ &m_plkbytNative));
+
+ Assert (m_pstgNative==NULL);
+
+ if (NOERROR==StgIsStorageILockBytes(m_plkbytNative))
+ {
+ // This is a flattened 2.0 storage
+ ErrRtnH (StgOpenStorageOnILockBytes (m_plkbytNative,
+ (LPSTORAGE)NULL,
+ STGM_READWRITE| STGM_SHARE_EXCLUSIVE| STGM_DIRECT,
+ (SNB)NULL,
+ 0,
+ &m_pstgNative));
+ }
+ else
+ {
+ // It is a raw 1.0 Native handle.
+ // This is the TreatAs/ ConvertTo case.
+ LPLOCKBYTES plkbyt = NULL;
+ Assert (m_psrvrParent->m_aOriginalClass);
+
+ ErrRtnH (wCreateStgAroundNative (medium.hGlobal,
+ m_psrvrParent->m_aOriginalClass,
+ m_psrvrParent->m_aClass,
+ m_psrvrParent->m_cnvtyp,
+ m_aItem,
+ &m_pstgNative,
+ &plkbyt));
+
+
+ Assert (m_plkbytNative);
+ if (m_plkbytNative)
+ {
+ // This should free the original native hGlobal also.
+ m_plkbytNative->Release();
+ medium.hGlobal = NULL;
+ }
+ m_plkbytNative = plkbyt;
+
+ }
+
+ RetZ (m_pstgNative);
+ Assert (m_lpoleObj);
+ ErrRtnH (m_lpoleObj->QueryInterface (IID_IPersistStorage,
+ (LPLPVOID) &pPersistStg));
+ hresult = pPersistStg->Load (m_pstgNative);
+ pPersistStg->Release();
+ pPersistStg=NULL;
+ ErrRtnH (hresult);
+
+ // Now that we have initialized the object, we can call SetClientSite
+ ErrRtnH (SetClientSite() );
+
+ // This is for Packager, in particular. If client does not advise
+ // on any data, we still need to do an OLE advise so we can get
+ // OnClose notifications.
+ ErrRtnH (DoOle20Advise (OLE_CLOSED, (CLIPFORMAT)0));
+ }
+ else
+ {
+ if (m_fGotEditNoPokeNativeYet)
+ {
+ // We got StdEdit, but instead of getting Poke for native data,
+ // we got poke for someother format. So we want to generate
+ // InitNew() call for the object.
+
+ ErrRtnH (DoInitNew()); // the function clears the flag
+ }
+
+ // Not native format, do SetData
+ // Callee frees medium, i.e., the hglobal returned by MakeItemData
+ Assert (m_lpdataObj);
+ hresult = m_lpdataObj->SetData (&formatetc, &medium, TRUE);
+#ifdef _DEBUG
+ if (hresult != NOERROR)
+ {
+ Puts ("****WARNING: SetData failed. cfFormat==");
+ WCHAR sz[100];
+ GetClipboardFormatName (formatetc.cfFormat, sz, 100);
+ Puts (sz);
+ Putn();
+ }
+#endif
+ // We free the data if server deos not return NOERROR.
+ // Otherwise server must've deleted it.
+ if (hresult == NOERROR)
+ medium.hGlobal = NULL;
+ }
+
+
+errRtn:
+ GlobalUnlock (hPoke);
+
+ if (fRelease && hPoke)
+ GlobalFree (hPoke);
+
+// Do NOT free medium.hGlobal, because it becomes the hGlobal on which
+// m_plkbytNative (and therefore m_pstgNative) is based.
+// It will be freed when m_plkbytNative is Release().
+// if (medium.hGlobal)
+// ReleaseStgMedium(&medium);
+
+ if (pPersistStg)
+ pPersistStg->Release();
+
+ return hresult;
+}
+
+
+
+INTERNAL_(HRESULT) CDefClient::UnAdviseData
+ (HWND hwndClient,
+ ATOM aItem)
+{
+ WCHAR buf[MAX_STR];
+ int options;
+ LPCLIENT lpclient;
+ HRESULT hresult = ReportResult(0, E_UNEXPECTED, 0, 0);
+ HANDLE hclinfo = NULL;
+ PCLINFO pclinfo = NULL;
+
+ Puts ("DefClient::UnadviseData\r\n");
+ ChkC(this);
+
+ if (aItem == NULL)
+ {
+ buf[0] = NULL;
+ }
+ else
+ {
+ GlobalGetAtomName (aItem, buf, MAX_STR);
+ }
+
+ // Scan for the advise options like "Close", "Save" etc
+ // at the end of the item.
+
+ ErrRtnH (ScanItemOptions (buf, (int far *)&options));
+
+ // Now get the corresponding object.
+ ErrRtnH (FindItem (buf, (LPCLIENT FAR *)&lpclient));
+
+ // Find the client structure to be attached to the object.
+ if ((hclinfo = FindClient (lpclient->m_hcliInfo, hwndClient, FALSE)) == NULL ||
+ (pclinfo = (PCLINFO) LocalLock (hclinfo)) == NULL )
+ {
+ hresult = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ goto errRtn;
+ }
+
+ pclinfo->options &= (~(0x0001 << options));
+
+errRtn:
+ if (pclinfo)
+ LocalUnlock (hclinfo);
+ return hresult;
+
+}
+
+
+
+// AdviseStdItems: This routine takes care of the DDEADVISE for a
+//particular object in given document. Creates a client strutcure
+//and attaches to the property list of the object window.
+
+INTERNAL_(HRESULT) CDefClient::AdviseStdItems
+(
+
+HWND hwndClient,
+ATOM aItem,
+HANDLE hopt,
+BOOL FAR * lpfack
+)
+{
+
+ DDEADVISE FAR *lpopt;
+ HRESULT hresult = ReportResult(0, E_UNEXPECTED, 0, 0);
+
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::AdviseStdItems(hwndClient=%x,aItem=%x(%ws),hopt=%x)\n",
+ this,
+ hwndClient,
+ aItem,
+ wAtomName(aItem),
+ hopt));
+
+ ChkC(this);
+ ErrZS (lpopt = (DDEADVISE FAR *) GlobalLock (hopt), E_OUTOFMEMORY);
+
+ AssertSz (aItem == aStdDocName, "AdviseStdItem is not Documentname");
+
+ *lpfack = lpopt->fAckReq;
+ hresult = (HRESULT)SetStdInfo (hwndClient, OLESTR("StdDocumentName"), NULL);
+
+
+ if (lpopt)
+ GlobalUnlock (hopt);
+
+errRtn:
+
+ if (hresult == NOERROR)
+ {
+ // Rules say to free handle if ACK will be positive
+ GlobalFree (hopt);
+ }
+ Assert (hresult==NOERROR);
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::AdviseStdItems hresult=%x\n",
+ this,
+ hresult));
+
+ return hresult;
+}
+
+
+
+//AdviseData: This routine takes care of the DDE_ADVISE for a
+//particular object in given document. Creates a client strutcure
+//and attaches to the property list of the object window.
+
+INTERNAL CDefClient::AdviseData
+(
+HWND hwndClient,
+ATOM aItem,
+HANDLE hopt,
+BOOL FAR * lpfack
+)
+{
+ DDEADVISE FAR *lpopt = NULL;
+ int format = NULL;
+ WCHAR buf[MAX_STR];
+ OLE_NOTIFICATION options;
+ LPCLIENT lpclient;
+ HRESULT hresult = ReportResult(0, E_UNEXPECTED, 0, 0);
+ HANDLE hclinfo = NULL;
+ PCLINFO pclinfo = NULL;
+ BOOL fAllocatedClInfo = FALSE;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::AdviseData(hwndClient=%x,aItem=%x(%ws),hopt=%x)\n",
+ this,
+ hwndClient,
+ aItem,
+ wAtomName(aItem),
+ hopt));
+ ChkC(this);
+ if (m_fGotEditNoPokeNativeYet) {
+ // We got StdEdit, but instead of getting Poke for native data,
+ // we got advise. So we want to generate InitNew() call for
+ // the object.
+
+ DoInitNew(); // the function clears the flag
+ }
+
+ m_fGotDdeAdvise = TRUE;
+
+ ErrZS (lpopt = (DDEADVISE FAR *) GlobalLock (hopt), E_OUTOFMEMORY);
+
+ if (!aItem)
+ buf[0] = NULL;
+ else
+ GlobalGetAtomName (aItem, buf, MAX_STR);
+
+ // Scan for the advise options like "Close", "Save" etc
+ // at the end of the item.
+
+ // ack flag should be set before the error return. Otherwise the
+ // the atom is getting deleted.
+
+ *lpfack = lpopt->fAckReq;
+ ErrRtnH (ScanItemOptions (buf, (int far *)&options));
+
+ // Now get the corresponding item.
+ ErrRtnH (FindItem (buf, (LPCLIENT FAR *)&lpclient));
+
+ if (!IsFormatAvailable ((CLIPFORMAT)(unsigned short)lpopt->cfFormat)){
+ hresult = ReportResult(0, DV_E_CLIPFORMAT, 0, 0); // this format is not supported;
+ goto errRtn;
+ }
+
+ lpclient->DoOle20Advise (options, (CLIPFORMAT)(unsigned short)lpopt->cfFormat);
+
+
+ // Create the client structure to be attcahed to the object.
+ if (!(hclinfo = FindClient (lpclient->m_hcliInfo, hwndClient, FALSE)))
+ {
+ hclinfo = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof (CLINFO));
+ fAllocatedClInfo = TRUE;
+ }
+
+
+ if (hclinfo == NULL || (pclinfo = (PCLINFO) LocalLock (hclinfo)) == NULL){
+ hresult = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ goto errRtn;
+ }
+
+ // Remember the client window (Needed for sending DATA later on
+ // when the data change message comes from the server)
+
+ pclinfo->hwnd = hwndClient;
+ if ((CLIPFORMAT)(unsigned short)lpopt->cfFormat == g_cfNative)
+ pclinfo->bnative = TRUE;
+ else
+ pclinfo->format = (CLIPFORMAT)(unsigned short)lpopt->cfFormat;
+
+ // Remeber the data transfer options
+ pclinfo->options |= (1 << options) ;
+
+ pclinfo->bdata = !lpopt->fDeferUpd;
+ LocalUnlock (hclinfo);
+ pclinfo = NULL;
+
+ // if the entry exists already, delete it.
+ FindClient (lpclient->m_hcliInfo, hwndClient, /*fDelete*/TRUE);
+
+ // Now add this client to item client list
+ // !!! This error recovery is not correct.
+ if(!AddClient ((LPHANDLE)&lpclient->m_hcliInfo, hwndClient, hclinfo))
+ goto errRtn;
+
+
+errRtn:
+ if (lpopt)
+ GlobalUnlock (hopt);
+
+ if (pclinfo)
+ LocalUnlock (hclinfo);
+
+ if (hresult==NOERROR)
+ {
+ // hresult==NOERROR iff we will send a postive ACK, so we must
+ // free the hOptions handle.
+ GlobalFree (hopt);
+ }
+ else
+ {
+ intrDebugOut((DEB_IERROR,
+ "%x ::AdviseData() failing.\n",this));
+ // We free hclinfo because it was not stored in the item's
+ // client list via the AddClient just before the errRtn label.
+ if (hclinfo && fAllocatedClInfo)
+ LocalFree (hclinfo);
+
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::AdviseData() returns hresult = %x\n",
+ this, hresult));
+
+ return hresult;
+
+}
+
+
+
+
+
+INTERNAL_(BOOL) CDefClient::IsFormatAvailable
+ (CLIPFORMAT cfFormat)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::IsFormatAvailable(cfFormat=%x)\n",
+ this, cfFormat));
+
+ ChkC(this);
+
+ BOOL f = ((cfFormat==g_cfNative) || UtIsFormatSupported (m_lpdataObj, DATADIR_GET, cfFormat));
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::IsFormatAvailable(cfFormat=%x) returning %x\n",
+ this, cfFormat,f));
+
+ return f;
+}
+
+
+//RequestData: Sends data in response to a DDE Request message.
+// for agiven doc and an object.
+
+INTERNAL_(HRESULT) CDefClient::RequestData
+(
+HWND hwndClient,
+ATOM aItem,
+USHORT cfFormat,
+LPHANDLE lphdde
+)
+{
+
+ HRESULT hresult = NOERROR;
+ LPCLIENT lpclient;
+ FORMATETC formatetc;
+ STGMEDIUM medium;
+ // Due to a C7 bug, do not use a structure initialization for STGMEDIUM
+ medium.tymed = TYMED_NULL;
+ medium.hGlobal = 0;
+ medium.pUnkForRelease= NULL;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::RequestData(hwndClient=%x,aItem=%x(%ws),cfFormat=%x,lphdde=%x)\n",
+ this,
+ hwndClient,
+ aItem,
+ wAtomName(aItem),
+ cfFormat,
+ lphdde));
+ ChkC(this);
+
+ // If edit environment Send data if we can
+ if (aItem == aEditItems)
+ {
+ hresult = RequestDataStd (aItem, lphdde);
+ goto exitRtn;
+ }
+
+ hresult = FindItem ((LPOLESTR) MAKEINTATOM(aItem),(LPCLIENT FAR *)&lpclient);
+ if (hresult != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ ChkC (lpclient);
+
+ formatetc.cfFormat = cfFormat;
+ formatetc.ptd = lpclient->m_ptd;
+ formatetc.lindex = DEF_LINDEX;
+ formatetc.dwAspect = DVASPECT_CONTENT;
+ formatetc.tymed = TYMED_HGLOBAL;
+
+
+ hresult = ReportResult(0, DV_E_FORMATETC, 0, 0);
+ if (!lpclient->IsFormatAvailable (formatetc.cfFormat))
+ {
+ goto errRtn;
+ }
+
+
+ // Now ask the item for the given format data
+
+ SendDevInfo (hwndClient);
+
+ wSetTymed (&formatetc);
+ hresult = lpclient->GetData (&formatetc, &medium);
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "GetData returns hresult=%x\n",
+ hresult));
+ goto errRtn;
+ }
+ if (medium.tymed & ~(TYMED_HGLOBAL | TYMED_MFPICT | TYMED_GDI))
+ {
+ AssertSz (0, "Got a storage medium of type other than hGlobal");
+ goto errRtn;
+ }
+ if (cfFormat == CF_METAFILEPICT)
+ {
+ ChangeOwner (medium.hGlobal);
+ }
+
+
+ // Duplicate the DDE data
+ // medium.hGlobal is freed by MakeDdeData or by the client once the
+ // DDE_DATA is posted with *lphdde.
+ if (MakeDDEData (medium.hGlobal, cfFormat, lphdde, TRUE)){
+ // !!! Why do we have to duplicate the atom
+ DuplicateAtom (aItem);
+ hresult = NOERROR;
+ }
+ else
+ hresult = E_OUTOFMEMORY;
+
+errRtn:
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::RequestData() returning %x\n",
+ this, hresult));
+
+ return hresult;
+}
+
+
+
+// REVIEW: needs review. Item callvback has to be split
+
+// ItemCallback: Calback routine for the server to inform the
+// data changes. When the change message is received, DDE data
+// message is sent to each of the clients depending on the
+// options.
+
+INTERNAL_(HRESULT) CDefClient::ItemCallBack
+(
+ int msg, // notification message
+ LPOLESTR szNewName // for OLE_RENAMED notification
+)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::ItemCallBack(msg=%x,szNewName=%x)\n",
+ this,
+ szNewName));
+
+ HRESULT hresult = NOERROR;
+ BOOL bSaved;
+ LPCLIENT lpclientRename;
+ LPCLIENT lpclient;
+
+ ChkC(this);
+
+ if (msg == OLE_RENAMED) {
+
+ Assert (szNewName);
+ intrDebugOut((DEB_ITRACE,
+ "%x ::ItemCallBack(szNewName=(%ws))\n",
+ WIDECHECK(szNewName)));
+
+
+ if (!m_bContainer)
+ {
+ lpclient = (LPCLIENT)GetWindowLong (m_hwnd, 0);
+ Assert (lpclient==m_pdoc);
+ }
+ else
+ lpclient = this;
+
+ Assert (lpclient->m_chk==chkDefClient);
+
+ // Replace the internally-stored name
+ if (lpclient->m_aItem)
+ {
+ GlobalDeleteAtom (lpclient->m_aItem);
+ lpclient->m_aItem = wGlobalAddAtom (szNewName);
+ }
+
+
+ // find if any StdDocName item is present at all
+ if (lpclientRename =
+ lpclient->SearchItem ((LPOLESTR) MAKEINTATOM(aStdDocName)))
+ {
+ HANDLE hDdeData=NULL;
+
+ //
+ // We have a new name in UNICODE. Need to create a new
+ // name in ANSI.
+ //
+ LPSTR lpName = CreateAnsiFromUnicode(szNewName);
+
+ HANDLE hNewName = wNewHandle (lpName, strlen(lpName) + 1);
+
+ PrivMemFree(lpName);
+
+ // hNewName is freed by MakeDDEData
+
+ if (!MakeDDEData (hNewName, (int)g_cfBinary, &hDdeData, FALSE))
+ {
+ hresult = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ goto errrtn;
+ }
+
+ Assert (hDdeData);
+ lpclientRename->SendRenameMsgs (hDdeData);
+ GlobalFree (hDdeData);
+
+ // Post termination for each of the doc clients that did not
+ // advise on rename
+ lpclient->TerminateNonRenameClients (lpclientRename);
+ }
+
+
+ Assert (FALSE == lpclient->m_fEmbed);
+
+ // REVIEW: what is this?
+ //lpclient->m_fEmbed = FALSE;
+
+ hresult = NOERROR;
+
+ errrtn:
+ Assert (hresult == NOERROR);
+ goto exitRtn;
+
+ } else {
+
+ // Enumerate all the clients and send DDE_DATA if necessary.
+ bSaved = SendDataMsg (msg);
+
+ // REVIEW: Hack from 1.0 for old pre-OLE-library apps
+ if ((msg == OLE_SAVED) && m_fEmbed && !bSaved)
+ return ReportResult(0, RPC_E_DDE_CANT_UPDATE, 0, 0);
+
+ hresult = NOERROR;
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::ItemCallBack() returning hresult=%x\n",
+ this,hresult));
+
+ return(hresult);
+}
+
+
+// This func should definitely be replaced by use of MFC map. (IsEmpty)
+INTERNAL_(BOOL) AreNoClients (HANDLE hcli)
+{
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+
+ while (hcli) {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ {
+ Puth (hcli);
+ Putn();
+ Assert(0);
+ return TRUE;
+ }
+
+ phandle = (HANDLE *) pcli->info;
+ while (phandle < (HANDLE *)(pcli + 1))
+ {
+ if (*phandle)
+ {
+ LocalUnlock (hcli);
+ return FALSE;
+ }
+ phandle++;
+ phandle++;
+ }
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ }
+ return TRUE;
+}
+
+
+#ifdef _DEBUG
+// For use in CodeView
+// NOTE: Returns a static string
+INTERNAL_(LPOLESTR) a2s (ATOM a)
+{
+ static WCHAR sz[256];
+ GlobalGetAtomName (a, sz, 256);
+ return sz;
+}
+#endif
diff --git a/private/ole32/com/dde/server/item2.cxx b/private/ole32/com/dde/server/item2.cxx
new file mode 100644
index 000000000..05a1f9c0c
--- /dev/null
+++ b/private/ole32/com/dde/server/item2.cxx
@@ -0,0 +1,1405 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: item2.cxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 6-07-94 kevinro Converted to NT and commented
+//
+//----------------------------------------------------------------------------
+
+#include "ole2int.h"
+#include <dde.h>
+#include "ddeatoms.h"
+#include "ddedebug.h"
+#include "srvr.h"
+#include "itemutil.h"
+#include "trgt_dev.h"
+#include <stddef.h>
+#include <limits.h>
+#ifndef WIN32
+// #include <print.h>
+#endif
+
+ASSERTDATA
+
+
+INTERNAL_(void) CDefClient::TerminateNonRenameClients
+(
+LPCLIENT lprenameClient
+)
+{
+
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+ HANDLE hcli;
+ HWND hwndClient;
+ LPCLIENT lpdocClient;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::TerminateNonRenameClients(lprenClient=%x)\n",
+ this,
+ lprenameClient));
+
+ // items also keep the parents window handle.
+ hwndClient = m_hwnd;
+ lpdocClient = (LPCLIENT)GetWindowLong (m_hwnd, 0);
+
+
+ hcli = m_hcliInfo;
+ while (hcli)
+ {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ {
+ break;
+ }
+
+ phandle = (HANDLE *) (pcli->info);
+ while (phandle < (HANDLE *)(pcli + 1))
+ {
+ if (*phandle)
+ {
+ // This client is in the rename list. So, no termination
+ if(!FindClient (lprenameClient->m_hcliInfo, *phandle, FALSE))
+ {
+
+#ifdef KEVINRO_I_CHANGED_THIS
+//
+// BUGBUG: (KevinRo) I don't understand why this didn't just call Terminate() instead.
+// There may be the potential for problems on this PostMessageToClient, since it doesn't
+// do the ModalLoop stuff. It is going to busy wait by doing Peeks
+//
+// I have changed this to call Terminate
+//
+ PostMessageToClientWithReply ((HWND)*phandle,
+ WM_DDE_TERMINATE,
+ (UINT) hwndClient, NULL,
+ WM_DDE_TERMINATE);
+#endif
+ //
+ // Terminate will send a WM_DDE_TERMINATE at the client
+ //
+ Terminate((HWND)*phandle,hwndClient);
+
+ // delete this client from all the items lists.
+ lpdocClient->DeleteFromItemsList ((HWND)*phandle);
+ }
+ }
+ phandle++;
+ phandle++;
+ }
+
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::TerminateNonRenameClients\n",
+ this));
+
+}
+
+
+
+INTERNAL CDefClient::Terminate
+ (HWND hwndTo,
+ HWND hwndFrom)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::Terminate hwndTo=%x hwndFrom=%x\n",
+ this,
+ hwndTo,
+ hwndFrom));
+
+ DDECALLDATA DdeCD;
+ HRESULT hresult;
+
+ DdeCD.hwndSvr = hwndTo;
+ DdeCD.hwndCli = hwndFrom;
+ DdeCD.wMsg = WM_DDE_TERMINATE;
+ DdeCD.wParam = (WPARAM)hwndFrom,
+ DdeCD.lParam = 0;
+
+ //
+ // Setting the fCallData variable effects the way that the
+ // DocWndProc handles WM_DDE_TERMINATE. If it is set, then this
+ // object initiated the terminate, and will not reply to the
+ // TERMINATE. It will allow us to leave the CallRunModalLoop
+ //
+ m_fCallData = TRUE;
+
+ RPCOLEMESSAGE RpcOleMsg;
+ RpcOleMsg.Buffer = &DdeCD;
+
+ // Figure out the MsgQ input flags based on the callcat of the call.
+ DWORD dwMsgQInputFlag = gMsgQInputFlagTbl[CALLCAT_SYNCHRONOUS];
+
+ // Now construct a modal loop object for the call that is about to
+ // be made. It maintains the call state and exits when the call has
+ // been completed, cancelled, or rejected.
+
+ CCliModalLoop CML(0, dwMsgQInputFlag);
+
+ do
+ {
+ DWORD status = 0;
+ hresult = CML.SendReceive(&RpcOleMsg, &status, &m_pCallMgr);
+
+ } while (hresult == RPC_E_SERVERCALL_RETRYLATER);
+
+
+ m_fCallData = FALSE;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::Terminate hresult = %x\n",
+ this,hresult));
+
+ return(hresult);
+}
+
+
+INTERNAL_(void) CDefClient::SendTerminateMsg ()
+{
+
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+ HANDLE hcli;
+ HWND hwnd;
+ LPCLIENT lpdocClient;
+ static int staticcounter;
+ int counter = ++staticcounter;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::SendTerminateMsg\n",
+ this));
+
+ // items also keep the document's window handle
+
+ Assert (IsWindow (m_hwnd));
+
+ if (!IsWindow (m_hwnd))
+ {
+ goto exitRtn;
+ }
+
+ hwnd = m_hwnd;
+
+ lpdocClient = (LPCLIENT)GetWindowLong (m_hwnd, 0);
+
+ Assert (lpdocClient);
+
+ if (NULL==lpdocClient)
+ {
+ goto exitRtn;
+ }
+
+ Assert (lpdocClient==m_pdoc);
+ AssertIsDoc (lpdocClient);
+ // If "this" is a document (container) then iterate through
+ // and terminate all its client windows. If "this" is an item
+ // just terminate that item's client windows.
+ hcli = m_bContainer ? lpdocClient->m_hcli : m_hcliInfo;
+ while (hcli)
+ {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ {
+ goto exitRtn;
+ }
+ phandle = (HANDLE *) (pcli->info);
+ while (phandle < (HANDLE *)(pcli + 1))
+ {
+ if ((HWND)*phandle)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%x ::SendTerminateMsg on hwnd=%x\n",
+ this,
+ (HWND)*phandle));
+
+ Terminate ((HWND)*phandle, hwnd);
+
+ Assert (lpdocClient->m_cClients > 0);
+
+ lpdocClient->m_cClients--;
+
+ HWND hwndClient = *(HWND *)phandle;
+ // This window is no longer a client.
+
+ // Remove window from document's master list
+ // and its item's list.
+ lpdocClient->DeleteFromItemsList (hwndClient);
+ }
+ //
+ // (KevinRo): Don't understand why the phandle is
+ // incremented twice. This is the same as the original
+ // code. Leaving it for now, since I don't have enough
+ // information.
+ //
+ phandle++;
+ phandle++;
+ }
+
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::SendTerminateMsg\n",
+ this));
+
+}
+
+
+
+// SendRenameMsg: enumerates the clients for the rename item
+// and sends rename message for all the clients.
+
+INTERNAL_(void) CDefClient::SendRenameMsgs
+(
+HANDLE hddeRename
+)
+{
+ ATOM aData = NULL;
+ HANDLE hdde = NULL;
+ PCLINFO pclinfo = NULL;
+ HWND hwndClient;
+
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+ HANDLE hcli;
+ HANDLE hcliInfo;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::SendRenameMsgs(hddeRename=%x)\n",
+ this,
+ hddeRename));
+
+ hcli = m_hcliInfo;
+ LPARAM lp;
+ while (hcli)
+ {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ {
+ goto exitRtn;
+ }
+
+
+ phandle = (HANDLE *) (pcli->info);
+ while (phandle < (HANDLE *)(pcli + 1))
+ {
+ if (*phandle++)
+ {
+ hdde = NULL;
+ aData = NULL;
+
+ if (!(pclinfo = (PCLINFO) LocalLock (hcliInfo = *phandle++)))
+ {
+ goto exitRtn;
+ }
+
+
+ // Make the item atom with the options.
+ aData = DuplicateAtom (aStdDocName);
+ hdde = UtDupGlobal (hddeRename,GMEM_MOVEABLE);
+
+ hwndClient = pclinfo->hwnd;
+ LocalUnlock (hcliInfo);
+
+ // Post the message
+
+ lp = MAKE_DDE_LPARAM(WM_DDE_DATA,hdde,aData);
+
+ if (!PostMessageToClient (hwndClient,
+ WM_DDE_DATA,
+ (UINT) m_hwnd,
+ lp))
+ {
+ DDEFREE(WM_DDE_DATA,lp);
+ if (hdde)
+ GlobalFree (hdde);
+ if (aData)
+ GlobalDeleteAtom (aData);
+ }
+ }
+ else
+ {
+ phandle++;
+ }
+
+ }
+
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::SendRenameMsgs void return\n",
+ this));
+
+}
+
+
+
+INTERNAL_(BOOL) CDefClient::SendDataMsg
+(
+WORD msg // notification message
+)
+{
+
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+ HANDLE hcli;
+ BOOL bSaved = FALSE;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::SendDataMsg(msg=%x)\n",
+ this,
+ msg));
+
+ hcli = m_hcliInfo;
+ while (hcli)
+ {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ {
+ break;
+ }
+ phandle = (HANDLE *) (pcli->info);
+ while (phandle < (HANDLE *)(pcli + 1)) {
+ if (*phandle++)
+ bSaved = SendDataMsg1 (*phandle++, msg);
+ else
+ phandle++;
+ }
+
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::SendDataMsg() returns %x)\n",
+ this,bSaved));
+
+ return bSaved;
+}
+
+
+
+//SendDataMsg: Send data to the clients, if the data change options
+//match the data advise options.
+
+INTERNAL_(BOOL) CDefClient::SendDataMsg1
+(
+HANDLE hclinfo, // handle of the client info
+WORD msg // notification message
+)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::SendDataMsg1(hclinfo=%x,msg=%x)\n",
+ this,
+ hclinfo,
+ msg));
+
+ PCLINFO pclinfo = NULL;
+ HANDLE hdde = NULL;
+ ATOM aData = NULL;
+ HRESULT retval;
+ BOOL bSaved = FALSE;
+
+
+ ChkC (this);
+ if (m_lpdataObj == NULL) goto errRtn;
+
+ // LATER: Allow server to give us other tymed's beside HGLOBAL and do
+ // the conversion ourselves, e.g., IStorageToHGlobal()
+
+ FORMATETC formatetc;// = {0, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
+ STGMEDIUM medium;// = {TYMED_NULL, NULL, NULL};
+ formatetc.ptd = m_ptd;
+ formatetc.dwAspect = DVASPECT_CONTENT;
+ formatetc.lindex = DEF_LINDEX;
+ formatetc.tymed = TYMED_HGLOBAL;
+ medium.tymed = TYMED_NULL;
+ medium.hGlobal=0; // not really necessary
+ medium.pUnkForRelease = NULL;
+
+ if (!(pclinfo = (PCLINFO) LocalLock (hclinfo)))
+ {
+ goto errRtn;
+ }
+
+ // if the client dead, then no message
+ if (!IsWindowValid(pclinfo->hwnd))
+ {
+ goto errRtn;
+ }
+
+
+ //
+ // (KevinRo) UPDATE was not defined in the OLE 2.01 code base
+ //
+#ifdef UPDATE
+ // OLE_SAVED is what 1.0 clients expect to get for embedded objects.
+ if (msg==OLE_CHANGED && m_fEmbed)
+ msg=OLE_SAVED;
+#endif
+
+ if (pclinfo->options & (0x0001 << msg))
+ {
+ bSaved = TRUE;
+ SendDevInfo (pclinfo->hwnd);
+
+ // send message if the client needs data for every change or
+ // only for the selective ones he wants.
+
+ // now look for the data option.
+ if (pclinfo->bnative){
+ // prepare native data
+ if (pclinfo->bdata){
+
+ // Wants the data with DDE_DATA message
+ // Get native data from the server.
+
+ // GetData
+ formatetc.cfFormat = g_cfNative;
+ wSetTymed (&formatetc);
+ retval = GetData (&formatetc, &medium);
+
+ if (retval != NOERROR)
+ {
+ Assert(0);
+ goto errRtn;
+ }
+ Assert (medium.tymed==TYMED_HGLOBAL);
+ Assert (medium.hGlobal);
+
+ // Prepare the DDE data block.
+ // REVIEW: MakeDDEData frees medium.hGlobal manually, but should
+ // really call ReleaseStgMedium.
+ if(!MakeDDEData (medium.hGlobal, (int)g_cfNative, (LPHANDLE)&hdde, FALSE))
+ {
+ goto errRtn;
+ }
+ }
+
+
+ // Make the item atom with the options.
+ aData = MakeDataAtom (m_aItem, msg);
+
+ intrDebugOut((DEB_ITRACE,
+ "%x ::SendDataMsg1 send NativeData to hwnd=%x"
+ "format %x\n",
+ this,
+ pclinfo->hwnd,
+ pclinfo->format));
+
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_DATA,hdde,aData);
+ if (!PostMessageToClient(pclinfo->hwnd,
+ WM_DDE_DATA,
+ (UINT) m_hwnd,
+ lp))
+
+
+ {
+ DDEFREE(WM_DDE_DATA,lp);
+ //
+ // The two data items will be free'd on exit
+ //
+ goto errRtn;
+ }
+ hdde = NULL;
+ aData = NULL;
+ }
+
+
+ // Now post the data for the display format
+
+ if (pclinfo->format)
+ {
+ if (pclinfo->bdata)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%x ::SendDataMsg1 GetData on cf = %x\n",
+ pclinfo->format));
+ // Must reset because previous call to GetData set it.
+ medium.tymed = TYMED_NULL;
+
+ // GetData
+ formatetc.cfFormat = pclinfo->format;
+ wSetTymed (&formatetc);
+ Assert (IsValidInterface (m_lpdataObj));
+ retval = m_lpdataObj->GetData (&formatetc, &medium);
+
+ if (retval != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "m_lpdataObj->GetData returns %x\n",
+ retval));
+ goto errRtn;
+ }
+
+
+ if (pclinfo->format == CF_METAFILEPICT)
+ ChangeOwner (medium.hGlobal);
+
+ if(!MakeDDEData (medium.hGlobal, pclinfo->format, (LPHANDLE)&hdde, FALSE))
+ goto errRtn;
+
+ }
+
+ // atom is deleted. So, we need to duplicate for every post
+ aData = MakeDataAtom (m_aItem, msg);
+ // now post the message to the client;
+ intrDebugOut((DEB_ITRACE,
+ "%x ::SendDataMsg1 send PresentationData to hwnd=%x"
+ " cf=%x\n",
+ this,
+ pclinfo->hwnd,
+ pclinfo->format));
+
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_DATA,hdde,aData);
+
+ if (!PostMessageToClient(pclinfo->hwnd,
+ WM_DDE_DATA,
+ (UINT) m_hwnd,
+ lp))
+ {
+ DDEFREE(WM_DDE_DATA,lp);
+ goto errRtn;
+ }
+
+ hdde = NULL;
+ aData = NULL;
+ }
+
+ }
+
+
+errRtn:
+ if (pclinfo)
+ LocalUnlock (hclinfo);
+
+ if (hdde)
+ GlobalFree (hdde);
+
+ if (aData)
+ GlobalDeleteAtom (aData);
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::SendDataMsg1() returns %x\n",
+ this,bSaved));
+
+
+ return bSaved;
+
+}
+
+
+
+// FixWriteBug
+//
+// `Write' gives a target device that is missing a NULL between
+// the device name and the driver name. This function creates
+// a fixed 1.0 target device.
+//
+// REVIEW: There is another Write bug we should work around.
+// Write does not send the "extra bytes" that are supposed to follow
+// the DEVMODE. It puts the Environment immediately after the DEVMODE.
+// So the driver will read the Environment thinking it is the extra bytes.
+// To fix this, FixWriteBug() should zero out the Environment bytes; the
+// 2.0 target device does not use them anyway.
+//
+ INTERNAL FixWriteBug
+ (HANDLE hTD,
+ LPHANDLE ph)
+{
+ HRESULT hresult;
+ LPBYTE pChunk2;
+ LPBYTE pNewChunk2;
+ const LPCOLETARGETDEVICE ptd1 = (LPCOLETARGETDEVICE) GlobalLock (hTD);
+ RetZS (ptd1, E_OUTOFMEMORY);
+
+ HANDLE hNew = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE,
+ GlobalSize (hTD) + 1);
+ RetZS (hNew, E_OUTOFMEMORY);
+ const LPBYTE pNew = (LPBYTE) GlobalLock (hNew);
+ RetZS (pNew, E_OUTOFMEMORY);
+ ULONG cbChunk1 = 7 * sizeof(UINT) + ptd1->otdDriverNameOffset;
+ ULONG cbChunk2 = GlobalSize (hTD) - cbChunk1;
+ ErrZS (!IsBadWritePtr (pNew, (UINT)cbChunk1), E_OUTOFMEMORY);
+ memcpy (pNew, ptd1, cbChunk1);
+ pNew[cbChunk1] = '\0'; // insert the missing NULL
+
+ pNewChunk2 = pNew + cbChunk1 + 1;
+ pChunk2 = (LPBYTE)ptd1 + cbChunk1;
+ ErrZS (!IsBadWritePtr (pNewChunk2, (UINT)cbChunk2), E_OUTOFMEMORY);
+ Assert (!IsBadReadPtr (pChunk2, (UINT)cbChunk2));
+ memcpy (pNewChunk2, pChunk2, cbChunk2);
+
+ // Fix up the offsets to accomodate the added NULL
+ #define macro(x) if (ptd1->otd##x##Offset > ptd1->otdDeviceNameOffset)\
+ ((LPOLETARGETDEVICE)pNew)->otd##x##Offset++;
+ macro (DriverName)
+ macro (PortName)
+ macro (ExtDevmode)
+ macro (Environment)
+ #undef macro
+
+ GlobalUnlock (hNew);
+ GlobalUnlock (hTD);
+ *ph = hNew;
+ return NOERROR;
+
+ errRtn:
+ if (pNew)
+ GlobalUnlock (hNew);
+ if (ptd1)
+ GlobalUnlock (hTD);
+ return hresult;
+}
+
+
+
+
+
+
+// Convert10TargetDevice
+//
+INTERNAL Convert10TargetDevice
+ (HANDLE hTD, // 1.0 Target Device
+ DVTARGETDEVICE FAR* FAR* pptd2) // Out parm, corresponding 2.0 TD
+{
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN Convert10TargetDevice hTD=%x\n",hTD));
+
+ ULONG cbData1, cbData2;
+
+ if (NULL==hTD)
+ {
+ Assert(0);
+ return ReportResult(0, E_INVALIDARG, 0, 0);
+ }
+
+ if (*pptd2)
+ {
+ // delete old target device
+ PrivMemFree(*pptd2);
+ *pptd2 = NULL;
+ }
+
+ LPOLETARGETDEVICE ptd1 = (LPOLETARGETDEVICE) GlobalLock (hTD);
+
+ RetZS (ptd1, E_OUTOFMEMORY);
+
+ if ((ptd1->otdDeviceNameOffset < ptd1->otdDriverNameOffset)
+ && (ptd1->otdDeviceNameOffset
+ + strlen (LPSTR(((BYTE *)ptd1->otdData) +
+ ptd1->otdDeviceNameOffset)) + 1 > ptd1->otdDriverNameOffset))
+ {
+ // No NULL between device and driver name
+ HANDLE hNew;
+ GlobalUnlock (hTD);
+ RetErr (FixWriteBug (hTD, &hNew));
+ HRESULT hresult = Convert10TargetDevice (hNew, pptd2);
+ Verify (0==GlobalFree (hNew));
+ return hresult;
+ }
+ // Word Bug
+ DEVMODEA UNALIGNED *pdevmode = (DEVMODEA UNALIGNED *)
+ (((BYTE *)ptd1->otdData)+ ptd1->otdExtDevmodeOffset);
+
+ if ( HIBYTE(pdevmode->dmSpecVersion) < 3
+ || HIBYTE(pdevmode->dmSpecVersion) > 6
+ || pdevmode->dmDriverExtra > 0x1000)
+ {
+ if (0==ptd1->otdEnvironmentSize)
+ {
+ // Sometimes Word does not give an environment.
+ ptd1->otdExtDevmodeOffset = 0;
+ ptd1->otdExtDevmodeSize = 0;
+ }
+ else
+ {
+ // DevMode is garbage, use environment instead.
+ ptd1->otdExtDevmodeOffset = ptd1->otdEnvironmentOffset;
+ ptd1->otdExtDevmodeSize = ptd1->otdEnvironmentSize;
+ }
+ }
+
+ // These next assert does not HAVE to be true,
+ // but it's a sanity check.
+ Assert (ptd1->otdDeviceNameOffset
+ + strlen (LPSTR(((BYTE *)ptd1->otdData) +
+ ptd1->otdDeviceNameOffset)) + 1
+ == ptd1->otdDriverNameOffset);
+
+
+ // Excel has zeroes for DevMode and Environment offsets and sizes
+
+ // Calculate size of Data block. Many 1.0 clients don't make their
+ // target device data block big enough for the DEVMODE.dmDriverExtra
+ // bytes (and they don't copy those bytes either). We can't reconstruct
+ // the bytes out of thin air, but we can at least make sure there's not
+ // a GP fault when the printer driver tries to access those bytes in
+ // a call to CreateDC. Any extra bytes are zeroed.
+ cbData2 = ptd1->otdExtDevmodeOffset + ptd1->otdExtDevmodeSize;
+
+ if (ptd1->otdExtDevmodeOffset != 0)
+ {
+ cbData2 += ((DEVMODEA UNALIGNED *)((LPBYTE)ptd1->otdData +
+ ptd1->otdExtDevmodeOffset))->dmDriverExtra;
+ }
+
+ cbData2 = max (cbData2,
+ ptd1->otdPortNameOffset + strlen (LPCSTR(
+ ((BYTE *)ptd1->otdData) + ptd1->otdPortNameOffset)) + 1);
+
+ // Calculate size of OLE2 Target Device
+ //
+ // Its the size of the DVTARGETDEVICE header, plus the cbData2
+ // The definition of DVTARGETDEVICE currently uses an unsized array
+ // of bytes at the end, therefore we can not just do a sizeof().
+ //
+
+ ULONG cbTD2 = SIZEOF_DVTARGETDEVICE_HEADER + cbData2;
+
+ // Allocate OLE2 Target Device
+ *pptd2 = (DVTARGETDEVICE FAR*) PrivMemAlloc(cbTD2);
+ if (IsBadWritePtr (*pptd2, cbTD2)
+ || IsBadWritePtr ((*pptd2)->tdData, cbData2))
+ {
+ AssertSz (0, "out of memory");
+ GlobalUnlock (hTD);
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+ _fmemset (*pptd2, '\0', cbTD2);
+
+ // OLE2 offsets are from the beginning of the DVTARGETDEVICE
+ const ULONG cbOffset = offsetof (DVTARGETDEVICE, tdData);
+
+ // Fill in new Target Device
+
+ (*pptd2)->tdSize = cbTD2;
+
+ #define Convert(a) \
+ ((*pptd2)->td##a##Offset = (USHORT)(ptd1->otd##a##Offset + cbOffset))
+
+ Convert (DeviceName);
+ Convert (DriverName);
+ Convert (PortName);
+ if (ptd1->otdExtDevmodeOffset != 0)
+ Convert (ExtDevmode);
+ else // Excel uses 0
+ (*pptd2)->tdExtDevmodeOffset = 0;
+
+ // Calculate size of 1.0 data block in case the 1.0 target
+ // device is incorrectly not big enough.
+ cbData1 = (size_t) GlobalSize(hTD) - offsetof (OLETARGETDEVICE, otdData);
+
+ #undef Convert
+ _fmemcpy ((*pptd2)->tdData, ptd1->otdData, min(cbData1, cbData2));
+
+ GlobalUnlock (hTD);
+
+ //
+ // At this point, pptd2 holds an ANSI version of a DVTARGET device
+ //
+ // Now, we need to convert it to a UNICODE version. There are routines
+ // for doing this in the UTILS.H file.
+ //
+
+ DVTDINFO dvtdInfo;
+ DVTARGETDEVICE * pdvtd32 = NULL;
+ HRESULT hr;
+
+ hr = UtGetDvtd16Info(*pptd2, &dvtdInfo);
+ if (hr != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ pdvtd32 = (DVTARGETDEVICE *) PrivMemAlloc(dvtdInfo.cbConvertSize);
+
+ if (pdvtd32 == NULL)
+ {
+ goto errRtn;
+ }
+
+ hr = UtConvertDvtd16toDvtd32(*pptd2, &dvtdInfo, pdvtd32);
+
+ if (hr != NOERROR)
+ {
+ PrivMemFree(pdvtd32);
+ pdvtd32=NULL;
+ }
+
+errRtn:
+
+ PrivMemFree(*pptd2);
+ *pptd2 = pdvtd32;
+
+ return hr;
+}
+//+---------------------------------------------------------------------------
+//
+// Method: CDefClient::PokeStdItems
+//
+// Synopsis: Pokes the data for the standard items.
+//
+// Effects:
+//
+// For StdHostnames, StdDocDimensions and SetColorScheme the data is
+// sent immediately and for the the StdTargetDeviceinfo the
+// data is set in each client block and the data is sent just
+// before the GetData call for rendering the right data.
+//
+// Arguments: [hwndClient] --
+// [aItem] --
+// [hdata] --
+// [index] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 6-07-94 kevinro Commented
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CDefClient::PokeStdItems(HWND hwndClient,
+ ATOM aItem,
+ HANDLE hdata,
+ int index)
+{
+ DDEDATA FAR * lpdata = NULL;
+ HANDLE hnew = NULL;
+ LPHOSTNAMES lphostnames;
+ HRESULT retval = E_OUTOFMEMORY;
+ WORD format;
+ BOOL fRelease;
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CDefClient::PokeStdItems(hwndClient=%x,aItem=%x(%ws)hdata=%x,index=%x)\n",
+ this,
+ hwndClient,
+ aItem,
+ wAtomName(aItem),
+ hdata,
+ index));
+
+ if (m_fGotEditNoPokeNativeYet)
+ {
+ // We got StdEdit, but instead of getting Poke for native data,
+ // we got poke for some std items. So we want to generate InitNew()
+ // call for the object.
+
+ DoInitNew(); // the function clears the flag
+ }
+
+ if(!(hdata && (lpdata = (DDEDATA FAR *)GlobalLock (hdata))))
+ {
+ goto errRtn;
+ }
+
+ format = lpdata->cfFormat;
+ fRelease = lpdata->fRelease;
+
+ AssertSz (format == (int)g_cfBinary, "Format is not binary");
+
+ // we have extracted the data successfully.
+ m_lpoleObj = m_lpoleObj;
+
+ if (index == STDHOSTNAMES)
+ {
+ lphostnames = (LPHOSTNAMES)lpdata->Value;
+ //
+ // The client should have sent the HOSTNAMES in ANSI. This
+ // means we need to convert them to UNICODE before we can
+ // use them.
+ //
+ LPOLESTR lpstrClient = CreateUnicodeFromAnsi((LPSTR)(lphostnames->data) + lphostnames->clientNameOffset);
+ LPOLESTR lpstrDoc = CreateUnicodeFromAnsi((LPSTR)(lphostnames->data) + lphostnames->documentNameOffset);
+
+ intrDebugOut((DEB_ITRACE,
+ "%p ::PokeStdItems setting hostnames Client(%ws) Doc(%ws) \n",
+ this,
+ lpstrClient,
+ lpstrDoc));
+
+ retval = (HRESULT)m_lpoleObj->SetHostNames(lpstrClient,lpstrDoc);
+
+ if (retval==NOERROR)
+ {
+ m_fDidRealSetHostNames = TRUE;
+ }
+
+ PrivMemFree(lpstrClient);
+ PrivMemFree(lpstrDoc);
+
+ goto end;
+ }
+
+
+ if (index == STDDOCDIMENSIONS)
+ {
+
+ SIZEL size;
+ size.cy = ((LPRECT16)(lpdata->Value))->top;
+ size.cx = ((LPRECT16)(lpdata->Value))->left;
+ intrDebugOut((DEB_ITRACE,
+ "%p ::PokeStdItems STDDOCDIMENSIONS cy=%x cx=%x\n",
+ this,
+ size.cy,
+ size.cx));
+ retval = m_lpoleObj->SetExtent (DVASPECT_CONTENT, &size);
+
+ goto end;
+
+ }
+
+
+ if (index == STDCOLORSCHEME) {
+ intrDebugOut((DEB_ITRACE,
+ "%p ::PokeStdItems setting STDCOLORSCHEME\n",this));
+
+ retval = m_lpoleObj->SetColorScheme((LPLOGPALETTE)(lpdata->Value));
+
+ goto end;
+ }
+
+ // Target Device
+ if (index == STDTARGETDEVICE)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%p ::PokeStdItems setting STDTARGETDEVICE\n",this));
+
+ if (!(hnew = MakeItemData ((DDEPOKE FAR *)lpdata, hdata, format)))
+ goto errRtn;
+
+ retval = Convert10TargetDevice (hnew, &m_ptd);
+ goto end;
+
+ }
+ retval = E_UNEXPECTED;
+
+ intrAssert(!"::PokeStdItems - Unknown index\n");
+
+ //
+ // (KevinRo) Found the following line already commented out.
+ //
+ //(HRESULT)SetStdInfo (hwndClient, (LPOLESTR) (MAKELONG(STDTARGETDEVICE,0)),hnew);
+
+end:
+errRtn:
+ if (hnew)
+ // can only be global memory block
+ GlobalFree (hnew);
+
+ if (lpdata) {
+ GlobalUnlock (hdata);
+ if (retval == NOERROR && fRelease)
+ GlobalFree (hdata);
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT CDefClient::PokeStdItems() hresult = %x\n",
+ this,
+ retval));
+
+ return retval;
+}
+
+
+
+
+
+
+// SetStdInfo: Sets the targetdevice info. Creates a client
+// for "StdTargetDevice". This item is created only within the
+// lib and it is never visible in server app. When the change
+// message comes from the server app, before we ask for
+// the data, we send the targetdevice info if there is
+// info for the client whom we are trying to send the data
+// on advise.
+
+
+INTERNAL_(HRESULT) CDefClient::SetStdInfo
+(
+HWND hwndClient,
+LPOLESTR lpitemname,
+HANDLE hdata
+)
+{
+ HANDLE hclinfo = NULL;
+ PCLINFO pclinfo = NULL;
+ LPCLIENT lpclient;
+ HRESULT retval = NOERROR;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::SetStdInfo(hwndClient=%x,ItemName=(%ws),hdata=%x)\n",
+ this,
+ hwndClient,
+ lpitemname,
+ hdata));
+ //
+ // first create/find the StdTargetDeviceItem.
+ //
+
+ if ((lpclient = SearchItem (lpitemname)) == NULL)
+ {
+ retval = (HRESULT)RegisterItem (lpitemname,(LPCLIENT FAR *)&lpclient, FALSE);
+ if (retval != NOERROR)
+ {
+ goto errRtn;
+ }
+ }
+
+ if(hclinfo = FindClient (lpclient->m_hcliInfo, hwndClient, FALSE))
+ {
+ if (pclinfo = (PCLINFO) LocalLock (hclinfo))
+ {
+ if (pclinfo->hdevInfo)
+ GlobalFree (pclinfo->hdevInfo);
+ pclinfo->bnewDevInfo = TRUE;
+ if (hdata)
+ pclinfo->hdevInfo = UtDupGlobal (hdata,GMEM_MOVEABLE);
+ else
+ pclinfo->hdevInfo = NULL;
+ pclinfo->hwnd = hwndClient;
+ LocalUnlock (hclinfo);
+
+ // We do not have to reset the client because we did not
+ // change the handle it self.
+ }
+ }
+ else
+ {
+ // Create the client structure to be attcahed to the object.
+ hclinfo = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof (CLINFO));
+ if (hclinfo == NULL || (pclinfo = (PCLINFO) LocalLock (hclinfo)) == NULL)
+ goto errRtn;
+
+ pclinfo->bnewDevInfo = TRUE;
+ if (hdata)
+ pclinfo->hdevInfo = UtDupGlobal (hdata,GMEM_MOVEABLE);
+ else
+ pclinfo->hdevInfo = NULL;
+
+ pclinfo->hwnd = hwndClient;
+ LocalUnlock (hclinfo);
+
+
+ // Now add this client to item client list
+ // !!! This error recovery is not correct.
+ if (!AddClient ((LPHANDLE)&lpclient->m_hcliInfo, hwndClient, hclinfo))
+ goto errRtn;
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::SetStdInfo() hresult=%x\n",
+ this,retval));
+
+ return retval;
+errRtn:
+ Assert(0);
+ if (pclinfo)
+ LocalUnlock (hclinfo);
+
+ if (hclinfo)
+ LocalFree (hclinfo);
+
+ retval = E_OUTOFMEMORY;
+ goto exitRtn;
+}
+
+
+// SendDevInfo: Sends targetdevice info to the the object.
+// Caches the last targetdevice info sent to the object.
+// If the targetdevice block is same as the one in the
+// cache, then no targetdevice info is sent.
+// (!!! There might be some problem here getting back
+// the same global handle).
+
+INTERNAL_(void) CDefClient::SendDevInfo
+(
+HWND hWndCli
+)
+{
+
+ HANDLE hclinfo = NULL;
+ PCLINFO pclinfo = NULL;
+ HANDLE hdata;
+ LPCLIENT lpdocClient;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::SendDevInfo(hwndCli=%x)\n",
+ this,
+ hWndCli));
+#if 0
+ if (!m_bContainer)
+ lpdocClient = (LPCLIENT)GetWindowLong (m_hwnd, 0);
+ else
+ lpdocClient = this;
+#endif
+
+ // find if any StdTargetDeviceInfo item is present at all
+ AssertIsDoc(m_pdoc);
+ lpdocClient = m_pdoc->SearchItem ((LPOLESTR) (MAKELONG(STDTARGETDEVICE, 0)));
+ if (lpdocClient == NULL)
+ {
+ goto exitRtn;
+ }
+
+ hclinfo = FindClient (lpdocClient->m_hcliInfo, hWndCli, FALSE);
+
+ // This client has not set any target device info. no need to send
+ // any stdtargetdevice info
+ if (hclinfo != NULL) {
+ if (!(pclinfo = (PCLINFO)LocalLock (hclinfo)))
+ goto end;
+
+ // if we cached it, do not send it again.
+ if ((!pclinfo->bnewDevInfo) && pclinfo->hdevInfo == m_hdevInfo)
+ goto end;
+
+ pclinfo->bnewDevInfo = FALSE;
+ if(!(hdata = UtDupGlobal (pclinfo->hdevInfo,GMEM_MOVEABLE)))
+ goto end;
+ } else {
+
+ // already screen
+ if (!m_hdevInfo)
+ goto end;
+
+ //for screen send NULL.
+ hdata = NULL;
+ }
+
+
+
+ if (pclinfo)
+ {
+ m_hdevInfo = pclinfo->hdevInfo;
+ }
+ else
+ {
+ m_hdevInfo = NULL;
+ }
+
+
+
+ // !!! error case who frees the data?'
+
+end:
+ if (pclinfo)
+ LocalUnlock (hclinfo);
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::SendDevInfo(hwndCli=%x)\n",
+ this,
+ hWndCli));
+ return;
+}
+
+
+
+
+// Constructor
+CDefClient::CDefClient (LPUNKNOWN pUnkOuter): m_Unknown (this),
+ m_OleClientSite (this),
+ m_AdviseSink (this),
+ m_pCallMgr (this)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::CDefClient(pUnkOuter=%x)\n",
+ this,
+ pUnkOuter));
+
+ m_pUnkOuter = pUnkOuter ? pUnkOuter : &m_Unknown;
+ m_bContainer = TRUE;
+ m_lpoleObj = NULL;
+ m_lpdataObj = NULL;
+ m_bCreateInst = FALSE;
+ m_bTerminate = FALSE;
+ m_termNo = 0;
+ m_hcli = NULL;
+ m_lpNextItem = NULL;
+ m_cRef = 0;
+ m_hwnd = (HWND)0;
+ m_hdevInfo = NULL;
+ m_hcliInfo = NULL;
+ m_fDidRealSetHostNames= FALSE;
+ m_fDidSetClientSite = FALSE;
+ m_fGotDdeAdvise = FALSE;
+ m_fCreatedNotConnected = FALSE;
+ m_fInOnClose = FALSE;
+ m_fInOleSave = FALSE;
+ m_dwConnectionOleObj = 0L;
+ m_dwConnectionDataObj = 0L;
+ m_fGotStdCloseDoc = FALSE;
+ m_fEmbed = FALSE;
+ m_cClients = 0;
+ m_plkbytNative = NULL;
+ m_pstgNative = NULL;
+ m_fRunningInSDI = FALSE;
+ m_psrvrParent = NULL;
+ m_ptd = NULL;
+ m_pdoc = NULL;
+ m_chk = chkDefClient;
+ m_ExecuteAck.f = FALSE;
+ m_fGotEditNoPokeNativeYet = FALSE;
+ m_fLocked = FALSE;
+ m_fCallData = FALSE;
+ // CDefClient::Create does all the real work.
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::CDefClient(pUnkOuter=%x)\n",
+ this,
+ pUnkOuter));
+
+}
+
+
+CDefClient::~CDefClient (void)
+{
+ // This should be more object-oriented.
+ // But right now, this BOOL tells us what kind of obj
+ // (doc or item) "this" is
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::~CDefClient\n",
+ this));
+
+ Puts ("~CDefClient "); Puta(m_aItem); Putn();
+ BOOL fDoc = (m_pdoc==this);
+
+ Assert (m_chk==chkDefClient);
+
+ ReleaseObjPtrs ();
+
+ if (m_pdoc && !fDoc)
+ {
+ Assert (m_pdoc->m_chk==chkDefClient);
+ m_pdoc->m_pUnkOuter->Release();
+ }
+ if (fDoc)
+ {
+ // delete all the items(objects) for this doc
+ DeleteAllItems ();
+ if (m_fRunningInSDI && m_psrvrParent
+ && m_psrvrParent->QueryRevokeClassFactory())
+ {
+ m_psrvrParent->Revoke();
+ }
+
+ }
+
+ if (ISATOM(m_aItem))
+ GlobalDeleteAtom (m_aItem);
+ if (m_plkbytNative)
+ {
+ m_plkbytNative->Release();
+ Assert (m_pstgNative);
+ // They always go together
+ }
+ if (m_pstgNative)
+ m_pstgNative->Release();
+ if (m_ptd)
+ PrivMemFree(m_ptd);
+
+ // Delete client advise info
+ DeleteAdviseInfo ();
+ if (fDoc && IsWindow(m_hwnd))
+ {
+ SSDestroyWindow (m_hwnd);
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::~CDefClient\n",
+ this));
+
+}
+
+
+//
+// Unknown Implementation
+//
+
+STDMETHODIMP NC(CDefClient,CUnknownImpl)::QueryInterface
+ (REFIID iid,
+ LPVOID FAR* ppv)
+{
+ intrDebugOut((DEB_ITRACE,"%p CDefClient::QueryInterface()\n",this));
+
+ if (iid == IID_IUnknown)
+ {
+ *ppv = (LPVOID) &m_pDefClient->m_Unknown;
+ AddRef();
+ return NOERROR;
+ }
+ else if (iid==IID_IAdviseSink)
+ *ppv = (LPVOID) &m_pDefClient->m_AdviseSink;
+ else if (iid==IID_IOleClientSite)
+ *ppv = (LPVOID) &m_pDefClient->m_OleClientSite;
+ else
+ {
+ *ppv = NULL;
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+ m_pDefClient->m_pUnkOuter->AddRef();
+
+ return NOERROR;
+}
+
+
+STDMETHODIMP_(ULONG) NC(CDefClient,CUnknownImpl)::AddRef()
+{
+ intrDebugOut((DEB_ITRACE,
+ "%p CDefClient::AddRef() returns %x\n",
+ this,
+ m_pDefClient->m_cRef+1));
+
+ return ++m_pDefClient->m_cRef;
+}
+
+
+STDMETHODIMP_(ULONG) NC(CDefClient,CUnknownImpl)::Release()
+{
+ AssertSz (m_pDefClient->m_cRef, "Release is being called on ref count of zero");
+ if (--m_pDefClient->m_cRef == 0)
+ {
+ delete m_pDefClient;
+ intrDebugOut((DEB_ITRACE,
+ "%p CDefClient::Release() returns 0\n",
+ this));
+ return 0;
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%p CDefClient::Release() returns %x\n",
+ this,
+ m_pDefClient->m_cRef));
+
+ return m_pDefClient->m_cRef;
+}
diff --git a/private/ole32/com/dde/server/itemutil.cxx b/private/ole32/com/dde/server/itemutil.cxx
new file mode 100644
index 000000000..c0ba1b0f0
--- /dev/null
+++ b/private/ole32/com/dde/server/itemutil.cxx
@@ -0,0 +1,516 @@
+// itemutil.h//
+// routines used by item.cpp
+// They used to be in item.cpp but it got too big.
+
+
+#include "ole2int.h"
+#include "srvr.h"
+#include "itemutil.h"
+#include "ddedebug.h"
+
+ASSERTDATA
+
+
+//ScanItemOptions: Scan for the item options like Close/Save etc.
+
+INTERNAL_(HRESULT) ScanItemOptions
+(
+LPOLESTR lpbuf,
+int far *lpoptions
+)
+{
+
+ ATOM aModifier;
+
+ *lpoptions = OLE_CHANGED;
+ while ( *lpbuf && *lpbuf != '/') lpbuf++;
+
+ // no modifier same as /change
+
+ if (*lpbuf == NULL)
+ return NOERROR;
+
+ *lpbuf++ = NULL; // seperate out the item string
+ // We are using this in the caller.
+
+ if (!(aModifier = GlobalFindAtom (lpbuf)))
+ return ReportResult(0, RPC_E_DDE_SYNTAX_ITEM, 0, 0);
+
+ if (aModifier == aChange)
+ return NOERROR;
+
+ // Is it a save?
+ if (aModifier == aSave){
+ *lpoptions = OLE_SAVED;
+ return NOERROR;
+ }
+ // Is it a Close?
+ if (aModifier == aClose){
+ *lpoptions = OLE_CLOSED;
+ return NOERROR;
+ }
+
+ // unknow modifier
+ return ReportResult(0, RPC_E_DDE_SYNTAX_ITEM, 0, 0);
+
+}
+
+
+
+
+//MakeDDEData: Create a Global DDE data handle from the server
+// app data handle.
+
+INTERNAL_(BOOL) MakeDDEData
+(
+HANDLE hdata,
+int format,
+LPHANDLE lph,
+BOOL fResponse
+)
+{
+ DWORD size;
+ HANDLE hdde = NULL;
+ DDEDATA FAR *lpdata= NULL;
+ BOOL bnative;
+ LPSTR lpdst;
+ LPSTR lpsrc;
+
+ Puts ("MakeDDEData\r\n");
+
+ if (!hdata) {
+ *lph = NULL;
+ return TRUE;
+ }
+
+
+ if (bnative = !(format == CF_METAFILEPICT
+ || format == CF_DIB
+ || format == CF_BITMAP))
+ {
+ // g_cfNative, CF_TEXT, g_cfBinary
+ size = GlobalSize (hdata) + sizeof (DDEDATA);
+ }
+ else
+ size = sizeof (LONG) + sizeof (DDEDATA);
+
+
+ hdde = (HANDLE) GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT, size);
+ if (hdde == NULL || (lpdata = (DDEDATA FAR *) GlobalLock (hdde)) == NULL)
+ goto errRtn;
+
+ // set the data otions. Ask the client to delete
+ // it always.
+
+ lpdata->fAckReq = FALSE;
+ lpdata->fRelease = TRUE; // release the data
+ lpdata->cfFormat = format;
+ lpdata->fResponse = fResponse;
+
+ if (!bnative)
+ // If not native, stick in the handle what the server gave us.
+ *(LPHANDLE)lpdata->Value = hdata;
+
+ else {
+ // copy the native data junk here.
+ lpdst = (LPSTR)lpdata->Value;
+ if(!(lpsrc = (LPSTR)GlobalLock (hdata)))
+ goto errRtn;
+
+ size -= sizeof (DDEDATA);
+ memcpy (lpdst, lpsrc, size);
+ GlobalUnlock (hdata);
+ GlobalFree (hdata);
+
+ }
+
+ GlobalUnlock (hdde);
+ *lph = hdde;
+ return TRUE;
+
+errRtn:
+ if (lpdata)
+ GlobalUnlock (hdde);
+
+ if (hdde)
+ GlobalFree (hdde);
+
+ if (bnative)
+ GlobalFree (hdata);
+
+ return FALSE;
+}
+
+
+
+// IsAdviseStdItems: returns true if the item is one of the standard items
+// StdDocName;
+INTERNAL_(BOOL) IsAdviseStdItems (
+ATOM aItem
+)
+{
+
+ if ( aItem == aStdDocName)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+
+// GetStdItemIndex: returns index to Stditems in the "stdStrTable" if the item
+// is one of the standard items StdHostNames, StdTargetDevice,
+// StdDocDimensions, StdColorScheme
+WCHAR * stdStrTable[STDHOSTNAMES+1] = {NULL,
+ OLESTR("StdTargetDevice"),
+ OLESTR("StdDocDimensions"),
+ OLESTR("StdColorScheme"),
+ OLESTR("StdHostNames")};
+
+INTERNAL_(int) GetStdItemIndex (
+ATOM aItem
+)
+{
+
+ WCHAR str[MAX_STR];
+
+ if (!aItem)
+ return NULL;
+
+ if (!GlobalGetAtomName (aItem, str, MAX_STR))
+ return NULL;
+
+ if (!lstrcmpiW (str, stdStrTable[STDTARGETDEVICE]))
+ return STDTARGETDEVICE;
+ else if (!lstrcmpiW (str, stdStrTable[STDHOSTNAMES]))
+ return STDHOSTNAMES;
+ else if (!lstrcmpiW (str, stdStrTable[STDDOCDIMENSIONS]))
+ return STDDOCDIMENSIONS;
+ else if (!lstrcmpiW (str, stdStrTable[STDCOLORSCHEME]))
+ return STDCOLORSCHEME;
+
+ return NULL;
+}
+
+
+
+
+void ChangeOwner
+ (HANDLE hmfp)
+{
+
+#ifndef WIN32
+ LPMETAFILEPICT lpmfp;
+ if (lpmfp = (LPMETAFILEPICT) GlobalLock (hmfp))
+ {
+ SetMetaFileBitsBetter (lpmfp->hMF);
+ GlobalUnlock (hmfp);
+ }
+#endif
+}
+
+
+INTERNAL_(HANDLE) MakeItemData
+(
+DDEPOKE FAR * lpPoke,
+HANDLE hPoke,
+CLIPFORMAT cfFormat
+)
+{
+ HANDLE hnew;
+ LPBYTE lpnew;
+ DWORD dwSize;
+
+ Puts ("MakeItemData\r\n");
+
+ if (cfFormat == CF_METAFILEPICT)
+ return DuplicateMetaFile (*(LPHANDLE)lpPoke->Value);
+
+ if (cfFormat == CF_BITMAP)
+ return (HANDLE)DuplicateBitmap (*(HBITMAP *)lpPoke->Value);
+
+ if (cfFormat == CF_DIB)
+ return UtDupGlobal (*(LPHANDLE)lpPoke->Value,GMEM_MOVEABLE);
+
+ // Now we are dealing with normal case
+ if (!(dwSize = GlobalSize (hPoke)))
+ return NULL;
+
+ dwSize -= sizeof (DDEPOKE) - sizeof(BYTE);
+
+ // Use GMEM_ZEROINIT so there is no garbage after the data in field Value.
+ // This may be important when making an IStorage from native data,
+ // but I'm not sure.
+ // Note that the Value field itself could have garbage
+ // at the end if the hData of the DDE_POKE message is bigger than
+ // necessary, i.e.,
+ // GlobalSize(hData) > sizeof(DDEPOKE) - sizeof(Value) + realsize(Value)
+
+ // A DocFile is of size 512n
+ DebugOnly (
+ if (cfFormat==g_cfNative && dwSize%512 != 0)
+ {
+ Putsi(dwSize);
+ Puts ("DDE_POKE.Value not of size 512n\r\n");
+ }
+ )
+
+ if (hnew = GlobalAlloc (GMEM_MOVEABLE|GMEM_ZEROINIT, dwSize)) {
+ if (lpnew = (LPBYTE) GlobalLock (hnew)) {
+ memcpy (lpnew, lpPoke->Value, dwSize);
+ GlobalUnlock (hnew);
+ }
+ else {
+ GlobalFree (hnew);
+ hnew = NULL;
+ }
+ }
+
+ return hnew;
+}
+
+
+
+INTERNAL_(HANDLE) DuplicateMetaFile
+(
+HANDLE hSrcData
+)
+{
+ LPMETAFILEPICT lpSrcMfp;
+ LPMETAFILEPICT lpDstMfp = NULL;
+ HANDLE hMF = NULL;
+ HANDLE hDstMfp = NULL;
+
+ Puts ("DuplicateMetaFile\r\n");
+
+ if (!(lpSrcMfp = (LPMETAFILEPICT) GlobalLock(hSrcData)))
+ return NULL;
+
+ GlobalUnlock (hSrcData);
+
+ if (!(hMF = CopyMetaFile (lpSrcMfp->hMF, NULL)))
+ return NULL;
+
+ if (!(hDstMfp = GlobalAlloc (GMEM_MOVEABLE, sizeof(METAFILEPICT))))
+ goto errMfp;
+
+ if (!(lpDstMfp = (LPMETAFILEPICT) GlobalLock (hDstMfp)))
+ goto errMfp;
+
+ GlobalUnlock (hDstMfp);
+
+ *lpDstMfp = *lpSrcMfp;
+ lpDstMfp->hMF = (HMETAFILE)hMF;
+ return hDstMfp;
+errMfp:
+ //
+ // The following Metafile was created in this
+ // process. Therefore, the delete shouldn't need to
+ // call the DDE functions for deleting the DDE pair
+ //
+ if (hMF)
+ DeleteMetaFile ((HMETAFILE)hMF);
+
+ if (hDstMfp)
+ GlobalFree (hDstMfp);
+
+ return NULL;
+}
+
+
+
+INTERNAL_(HBITMAP) DuplicateBitmap
+(
+HBITMAP hold
+)
+{
+ HBITMAP hnew;
+ HANDLE hMem;
+ LPBYTE lpMem;
+ LONG retVal = TRUE;
+ DWORD dwSize;
+ BITMAP bm;
+
+ // !!! another way to duplicate the bitmap
+
+ Puts ("DuplicateBitmap\r\n");
+
+ GetObject (hold, sizeof(BITMAP), (LPSTR) &bm);
+ dwSize = ((DWORD) bm.bmHeight) * ((DWORD) bm.bmWidthBytes) *
+ ((DWORD) bm.bmPlanes) * ((DWORD) bm.bmBitsPixel);
+
+ if (!(hMem = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize)))
+ return NULL;
+
+ if (!(lpMem = (LPBYTE) GlobalLock (hMem))){
+ GlobalFree (hMem);
+ return NULL;
+ }
+
+ GetBitmapBits (hold, dwSize, lpMem);
+ if (hnew = CreateBitmap (bm.bmWidth, bm.bmHeight,
+ bm.bmPlanes, bm.bmBitsPixel, NULL))
+ retVal = SetBitmapBits (hnew, dwSize, lpMem);
+
+ GlobalUnlock (hMem);
+ GlobalFree (hMem);
+
+ if (hnew && (!retVal)) {
+ DeleteObject (hnew);
+ hnew = NULL;
+ }
+
+ return hnew;
+}
+
+
+
+
+// CDefClient::GetData
+//
+// Perform a normal GetData on m_lpdataObj, but if g_cfNative is requested,
+// do an OleSave onto our IStorage implemented
+// on top of an ILockBytes, then convert the ILockBytes to an hGlobal.
+// This flattened IStorage will be used as the native data.
+//
+INTERNAL CDefClient::GetData
+ (LPFORMATETC pformatetc,
+ LPSTGMEDIUM pmedium)
+{
+ LPPERSISTSTORAGE pPersistStg=NULL;
+ HANDLE hNative =NULL;
+ HANDLE hNativeDup =NULL;
+ HRESULT hresult =NOERROR;
+ BOOL fFreeHNative = FALSE;
+ CLSID clsid;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::GetData(%x,%x)\n",
+ this,
+ pformatetc,
+ pmedium));
+
+ intrDebugOut((DEB_ITRACE,
+ " ::GetData format=%x\n",
+ pformatetc->cfFormat));
+
+ if (pformatetc->cfFormat==g_cfNative)
+ {
+ ErrRtnH (m_lpdataObj->QueryInterface (IID_IPersistStorage,
+ (LPLPVOID) &pPersistStg));
+ ErrZ (pPersistStg);
+ if (NULL==m_pstgNative)
+ {
+ // Embed from file case
+ Assert (NULL==m_plkbytNative);
+ ErrRtnH (CreateILockBytesOnHGlobal (NULL,
+ /*fDeleteOnRelease*/TRUE,
+ &m_plkbytNative));
+
+ Assert (m_plkbytNative);
+
+ ErrRtnH (StgCreateDocfileOnILockBytes (m_plkbytNative,
+ grfCreateStg, 0, &m_pstgNative));
+
+ ErrZ (m_pstgNative);
+ Assert (NOERROR==StgIsStorageILockBytes(m_plkbytNative));
+
+ m_fInOleSave = TRUE;
+ hresult = OleSave (pPersistStg, m_pstgNative, FALSE);
+ pPersistStg->SaveCompleted(NULL);
+ m_fInOleSave = FALSE;
+ ErrRtnH (hresult);
+ }
+ else
+ {
+ // Get the native data by calling OleSave
+ m_fInOleSave = TRUE;
+ hresult = OleSave (pPersistStg, m_pstgNative, TRUE);
+ pPersistStg->SaveCompleted(NULL);
+ m_fInOleSave = FALSE;
+ ErrRtnH (hresult);
+ }
+ ErrRtnH (ReadClassStg (m_pstgNative, &clsid));
+ if (CoIsOle1Class (clsid))
+ {
+ // TreatAs case:
+ // Get Native data from "\1Ole10Native" stream
+ fFreeHNative = TRUE;
+ ErrRtnH (StRead10NativeData (m_pstgNative, &hNative));
+ }
+ else
+ {
+
+ Assert (NOERROR==StgIsStorageILockBytes (m_plkbytNative));
+
+ ErrRtnH (GetHGlobalFromILockBytes (m_plkbytNative, &hNative));
+ }
+
+ ErrZ (wIsValidHandle (hNative, g_cfNative));
+
+ // Must duplicate because we let the client free the handle,
+ // so it can't be the one our ILockBytes depends on.
+ hNativeDup = UtDupGlobal (hNative, GMEM_DDESHARE | GMEM_MOVEABLE);
+ ErrZ (wIsValidHandle (hNativeDup, g_cfNative));
+
+ if (GlobalSize(hNativeDup) % 512 != 0)
+ {
+ Puts ("WARNING:\r\n\t");
+ Putsi (GlobalSize(hNativeDup));
+ }
+
+ pmedium->tymed = TYMED_HGLOBAL;
+ pmedium->hGlobal = hNativeDup;
+ pmedium->pUnkForRelease = NULL;
+
+ pPersistStg->Release();
+ hresult = NOERROR;
+ goto exitRtn;
+ }
+ else
+ {
+ // Anything but native
+ hresult = m_lpdataObj->GetData (pformatetc, pmedium);
+// AssertOutStgmedium(hresult, pmedium);
+ goto exitRtn;
+ }
+
+
+errRtn:
+ if (hNative && fFreeHNative)
+ GlobalFree (hNative);
+ if (pPersistStg)
+ pPersistStg->Release();
+
+ pmedium->tymed = TYMED_NULL;
+ pmedium->pUnkForRelease = NULL;
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x OUT CDefClient::GetData() return %x\n",
+ this,
+ hresult));
+ return hresult;
+}
+
+
+// Set pformatetc->tymed based on pformatetc->cfFormat
+//
+INTERNAL wSetTymed
+ (LPFORMATETC pformatetc)
+{
+ if (pformatetc->cfFormat == CF_METAFILEPICT)
+ {
+ pformatetc->tymed = TYMED_MFPICT;
+ }
+ else if (pformatetc->cfFormat == CF_PALETTE ||
+ pformatetc->cfFormat == CF_BITMAP)
+ {
+ pformatetc->tymed = TYMED_GDI;
+ }
+ else
+ {
+ pformatetc->tymed = TYMED_HGLOBAL;
+ }
+ return NOERROR;
+}
diff --git a/private/ole32/com/dde/server/itemutil.h b/private/ole32/com/dde/server/itemutil.h
new file mode 100644
index 000000000..e9af61df2
--- /dev/null
+++ b/private/ole32/com/dde/server/itemutil.h
@@ -0,0 +1,14 @@
+// itemutil.h
+//
+// Corresponds to itemutil.cpp
+
+void ChangeOwner (HANDLE hmfp);
+INTERNAL ScanItemOptions (LPSTR lpbuf, int far *lpoptions);
+INTERNAL_(BOOL) MakeDDEData (HANDLE hdata, int format, LPHANDLE lph, BOOL fResponse);
+INTERNAL_(BOOL) IsAdviseStdItems (ATOM aItem);
+INTERNAL_(int) GetStdItemIndex (ATOM aItem);
+void ChangeOwner (HANDLE hmfp);
+INTERNAL_(HANDLE) MakeItemData (DDEPOKE FAR *lpPoke, HANDLE hPoke, CLIPFORMAT cfFormat);
+INTERNAL_(HANDLE) DuplicateMetaFile (HANDLE hSrcData);
+INTERNAL_(HBITMAP) DuplicateBitmap (HBITMAP hold);
+INTERNAL wSetTymed (LPFORMATETC pformatetc);
diff --git a/private/ole32/com/dde/server/srvr.cxx b/private/ole32/com/dde/server/srvr.cxx
new file mode 100644
index 000000000..2f2d8eb40
--- /dev/null
+++ b/private/ole32/com/dde/server/srvr.cxx
@@ -0,0 +1,2497 @@
+
+/****************************** Module Header ******************************\
+* Module Name: Srvr.c Server Main module
+*
+* Purpose: Includes All the server communication related routines.
+*
+* Created: Oct 1990.
+*
+* Copyright (c) 1985, 1986, 1987, 1988, 1989 Microsoft Corporation
+*
+* History:
+* Raor: Wrote the original version.
+*
+*
+\***************************************************************************/
+
+#include "ole2int.h"
+//#include <shellapi.h>
+// #include "cmacs.h"
+#include <dde.h>
+
+// for RemDdeRevokeClassFactory and HDDESRVR
+#include <olerem.h>
+
+#include "srvr.h"
+#include "ddedebug.h"
+#include "ddesrvr.h"
+ASSERTDATA
+
+#define WM_DONOTDESTROY WM_USER+1
+
+#ifdef FIREWALLS
+BOOL bShowed = FALSE;
+void ShowVersion (void);
+#endif
+
+#ifdef _CHICAGO_
+#define DdeCHAR CHAR
+#define Ddelstrcmp lstrcmpA
+#define DdeGetClassName GetClassNameA
+#define szCDDEServer "CDDEServer"
+#else
+#define DdeCHAR WCHAR
+#define Ddelstrcmp lstrcmpW
+#define DdeGetClassName GetClassName
+#define szCDDEServer OLESTR("CDDEServer")
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDDEServer::Create
+//
+// Synopsis: Create a server window to service a particular class
+//
+// Effects: Using lpclass, and the information in lpDdeInfo, create
+// a server window that is ready to respond to initiate
+// messages from this class.
+//
+// Arguments: [lpclass] -- Class name
+// [rclsid] -- Class ID
+// [lpDdeInfo] -- Class Object information
+// [phwnd] -- Out pointer for new window
+// [aOriginalClass] -- For TreatAs/Convert to case
+// [cnvtyp] -- Conversion type
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-28-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CDDEServer::Create
+ (LPOLESTR lpclass,
+ REFCLSID rclsid,
+ LPDDECLASSINFO lpDdeInfo,
+ HWND FAR * phwnd,
+ ATOM aOriginalClass,
+ CNVTYP cnvtyp)
+{
+ // REVIEW what happens if we have two MDI servers register the
+ // same class factory?.
+
+ LPSRVR lpDDEsrvr = NULL;
+ ATOM aExe = NULL;
+
+ intrDebugOut((DEB_DDE_INIT,
+ "0 _IN CDDEServer::Create(lpclass=%ws)\n",
+ lpclass));
+
+ // add the app atom to global list
+ if (!ValidateSrvrClass (lpclass, &aExe))
+ {
+ intrDebugOut((DEB_IWARN,
+ "CDDEServer::Create(%ws) Invalid Class\n",
+ lpclass));
+
+ return OLE_E_CLSID;
+ }
+
+ lpDDEsrvr = new CDDEServer;
+ RetZS (lpDDEsrvr, E_OUTOFMEMORY);
+
+ // set the signature handle and the app atom.
+ lpDDEsrvr->m_chk = chkDdeSrvr;
+ lpDDEsrvr->m_aClass = wGlobalAddAtom (lpclass);
+ lpDDEsrvr->m_clsid = rclsid; // Class ID (already TreatAs'd)
+ lpDDEsrvr->m_aOriginalClass = wDupAtom (aOriginalClass);
+ lpDDEsrvr->m_pClassFactory = NULL;
+ lpDDEsrvr->m_dwClassFactoryKey = lpDdeInfo->dwRegistrationKey;
+ lpDDEsrvr->m_aExe = aExe;
+ lpDDEsrvr->m_cnvtyp = cnvtyp;
+ lpDDEsrvr->m_fcfFlags = lpDdeInfo->dwFlags;
+
+ lpDDEsrvr->m_bTerminate = FALSE; // Set if we are terminating.
+ lpDDEsrvr->m_hcli = NULL; // handle to the first block of clients list
+ lpDDEsrvr->m_termNo = 0; // termination count
+ lpDDEsrvr->m_cSrvrClients= 0; // no of clients;
+ lpDDEsrvr->m_fDoNotDestroyWindow= 0;
+
+
+
+
+
+#ifdef FIREWALLS
+ AssertSz(lpDdeInfo.dwFlags <= REGCLS_MULTI_SEPARATE, "invalid server options");
+#endif
+
+ // Create the server window and do not show it.
+ //
+ // We are explicitly calling CreateWindowA here.
+ // The DDE tracking layer will attempt to convert hCommands to UNICODE
+ // if the two windows in the conversation are both UNICODE.
+ // This window is created as a child of the common server window for this
+ // thread. When this thread dies, the common server window is destroyed if
+ // it exists, which will cause all of the child windows to be destroyed also.
+ //
+ //
+ if (!(lpDDEsrvr->m_hwnd = DdeCreateWindowEx (0, gOleWindowClass,
+ szCDDEServer,
+ WS_OVERLAPPED | WS_CHILD,
+ 0,0,0,0,
+ (HWND)TLSGetDdeServer(),
+ NULL,
+ g_hinst, NULL)))
+ {
+ goto errReturn;
+ }
+
+ // fix up the WindowProc entry point.
+ SetWindowLong(lpDDEsrvr->m_hwnd, GWL_WNDPROC, (LONG)SrvrWndProc);
+
+ //
+ // The following will inform the class object in the class registration table
+ // that this window should be notified when the class object is revoked. This
+ // enables the window to shutdown properly.
+ //
+ // If there isn't a class factory, which happens for single instance servers
+ // which were launched with a filename, then m_dwClassFactory will be 0,
+ // in which case we don't make the set call.
+ //
+ if(lpDDEsrvr->m_dwClassFactoryKey != 0)
+ {
+ if(!SetDdeServerWindow(lpDDEsrvr->m_dwClassFactoryKey,lpDDEsrvr->m_hwnd))
+ {
+ intrDebugOut((DEB_IERROR,
+ "0 CDDEServer::Create unable to SetDdeServerWindow\n"));
+ goto errReturn;
+ }
+ }
+
+ intrDebugOut((DEB_DDE_INIT,
+ "DDE Server window for %ws created in task %x\n",
+ lpclass,GetCurrentThreadId()));
+
+ // save the ptr to the server struct in the window.
+ SetWindowLong (lpDDEsrvr->m_hwnd, 0, (LONG)lpDDEsrvr);
+
+ // Set the signature.
+ SetWindowWord (lpDDEsrvr->m_hwnd, WW_LE, WC_LE);
+
+ *phwnd = lpDDEsrvr->m_hwnd;
+
+
+ intrDebugOut((DEB_DDE_INIT,
+ "0 _OUT CDDEServer::Create returns %x\n",
+ NOERROR));
+ return NOERROR;
+
+errReturn:
+ AssertSz (0, "CDDEServer::Create errReturn");
+ if (lpDDEsrvr)
+ {
+ if (lpDDEsrvr->m_hwnd)
+ SSDestroyWindow (lpDDEsrvr->m_hwnd);
+
+ if (lpDDEsrvr->m_aClass)
+ GlobalDeleteAtom (lpDDEsrvr->m_aClass);
+
+ if (lpDDEsrvr->m_aExe)
+ GlobalDeleteAtom (lpDDEsrvr->m_aExe);
+ delete lpDDEsrvr;
+ }
+
+ intrDebugOut((DEB_IERROR,
+ "0 _OUT CDDEServer::Create returns %x\n",
+ E_OUTOFMEMORY));
+
+ return E_OUTOFMEMORY;
+}
+
+
+
+// ValidateSrvrClass checks whether the given server class is valid by
+// looking in the registration database.
+
+INTERNAL_(BOOL) ValidateSrvrClass (
+LPOLESTR lpclass,
+ATOM FAR * lpAtom
+)
+{
+ WCHAR buf[MAX_STR];
+ LONG cb = MAX_STR;
+ WCHAR key[MAX_STR];
+ LPOLESTR lptmp;
+ LPOLESTR lpbuf;
+ WCHAR ch;
+ CLSID clsid;
+
+ if (CLSIDFromProgID (lpclass, &clsid) != NOERROR)
+ {
+ // ProgId is not correctly registered in reg db
+ return FALSE;
+ }
+
+ lstrcpyW (key, lpclass);
+ lstrcatW (key, OLESTR("\\protocol\\StdFileEditing\\server"));
+
+ if (RegQueryValue (HKEY_CLASSES_ROOT, key, buf, &cb))
+ return TRUE;
+
+ if (!buf[0])
+ {
+ AssertSz (0, "ValidateSrvrClass failed.");
+ return FALSE;
+ }
+
+ // Get exe name without path and then get an atom for that
+ lptmp = lpbuf = buf;
+ while (ch = *lptmp)
+ {
+ lptmp++;
+ if (ch == '\\' || ch == ':')
+ lpbuf = lptmp;
+ }
+ *lpAtom = wGlobalAddAtom (lpbuf);
+
+ return TRUE;
+}
+
+
+
+INTERNAL RemDdeRevokeClassFactory
+ (LPSRVR lpsrvr)
+{
+ HRESULT hr;
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN RemDdeRevokeClassFactory(%x)\n",
+ lpsrvr));
+
+ ChkS(lpsrvr);
+ hr = lpsrvr->Revoke();
+ intrDebugOut((DEB_ITRACE,
+ "0 OUT RemDdeRevokeClassFactory(%x) %x\n",
+ lpsrvr,hr));
+ return(hr);
+}
+
+
+
+INTERNAL CDDEServer::Revoke ()
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDDEServer::Revoke() m_cSrvrClients=%x\n",
+ this,
+ m_cSrvrClients));
+ HRESULT hr;
+
+ ChkS(this);
+
+ //
+ // Can't revoke if there are still clients. QueryRevokeCLassFactory
+ // determines if there are still clients attached.
+ //
+ if (!QueryRevokeClassFactory ())
+ {
+ intrDebugOut((DEB_IERROR,
+ "QueryRevokeClassFactory failed!"));
+ hr = RPC_E_DDE_REVOKE;
+ goto exitRtn;
+ }
+
+ if (m_cSrvrClients)
+ {
+ m_bTerminate = TRUE;
+ // if there are any clients connected to this classfactory,
+ // send terminates.
+ SendServerTerminateMsg ();
+ m_bTerminate = FALSE;
+ }
+
+ hr = FreeSrvrMem ();
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x OUT CDDEServer::Revoke(%x) hr = %x\n",
+ this, hr));
+ return hr;
+}
+
+INTERNAL_(void) CDDEServer::SendServerTerminateMsg ()
+{
+
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+ HANDLE hcli;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDDEServer::SendServerTerminateMsg\n",
+ this));
+
+ hcli = m_hcli;
+ while (hcli) {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ {
+ Assert(0);
+ goto exitRtn;
+ }
+
+ phandle = (HANDLE *) (pcli->info);
+ while (phandle < (HANDLE *)(pcli + 1)) {
+ if (*phandle)
+ {
+ PostMessageToClientWithReply ((HWND)(*phandle), WM_DDE_TERMINATE,
+ (WPARAM) m_hwnd, NULL, WM_DDE_TERMINATE);
+ Assert (m_cSrvrClients);
+ m_cSrvrClients--;
+ }
+ phandle++;
+ phandle++;
+ }
+
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x OUT CDDEServer::SendServerTerminateMsg\n",
+ this));
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDDEServer::FreeSrvrMem
+//
+// Synopsis: Free's up a CDDEServer.
+//
+// Effects:
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 6-26-94 kevinro Commented
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CDDEServer::FreeSrvrMem
+ (void)
+{
+ HRESULT hr;
+ // REVIEW: Not clear how this works in the synchronous mode
+ // Release for class factory is called only when everything is
+ // cleaned and srvr app can post WM_QUIT at this stage
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDDEServer::FreeSrvrMem\n",
+ this));
+
+ PCLILIST pcliPrev;
+ HANDLE hcli, hcliPrev;
+
+ if (m_bTerminate)
+ {
+ AssertSz (0, "terminate flag is not FALSE");
+ }
+
+
+ if (m_aExe)
+ {
+ GlobalDeleteAtom (m_aExe);
+ }
+
+
+ // We deliberately do not call this->Lock (FALSE)
+ // If the server has revoked his class object without
+ // waiting for his Lock count to go to zero, then
+ // presumably he doesn't need us to unlock him. In fact,
+ // doing such an unlock might confuse a server who then
+ // tries to call CoRevokeClassObject recursively.
+ if (m_pClassFactory)
+ {
+ m_pClassFactory->Release();
+ m_pClassFactory = NULL;
+ }
+
+ hcli = m_hcli;
+ while (hcli)
+ {
+ hcliPrev = hcli;
+ if (pcliPrev = (PCLILIST) LocalLock (hcliPrev))
+ {
+ hcli = pcliPrev->hcliNext;
+ }
+ else
+ {
+ AssertSz (0, "Corrupt internal data structure or out-of-memory");
+ hcli = NULL;
+ }
+ Verify (0==LocalUnlock (hcliPrev));
+ Verify (NULL==LocalFree (hcliPrev));
+ }
+
+ hr = DestroyDdeSrvrWindow(m_hwnd,m_aClass);
+ if (hr != NOERROR)
+ {
+ //
+ // Well now, if DestroyWindow fails, there isn't a whole heck of
+ // alot we can do about it. It could mean that the window was
+ // destroyed previously, or the parent window was destroyed during
+ // thread shutdown. We should still continue to cleanup
+ //
+ intrDebugOut((DEB_IERROR,
+ "%x CDDEServer::FreeSrvrMem DestroyDdeSrvrWindow failed %x\n",
+ this,
+ hr));
+ }
+
+ if (m_aClass)
+ {
+ GlobalDeleteAtom (m_aClass);
+ }
+
+ delete this;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDDEServer::FreeSrvrMem\n",
+ this));
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SrvrHandleIncomingCall
+//
+// Synopsis: Setup and call the CallControl to dispatch a call to the server
+//
+// Effects: A call has been made from the client that requires us to call
+// into our server. This must be routed through the call control.
+// This routine sets up the appropriate data structures, and
+// calls into the CallControl. The CallControl will in turn
+// call SrvrDispatchIncomingCall to actuall process the call.
+//
+// This routine should only be called by the SrvrWndProc
+//
+//
+// Arguments: [lpsrvr] -- Points to the server
+// [hwnd] -- hwnd of server
+// [hdata] -- Handle to data
+// [wParam] -- hwnd of client
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-05-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL SrvrHandleIncomingCall(LPSRVR lpsrvr,
+ HWND hwnd,
+ HANDLE hdata,
+ HWND wParam)
+{
+ VDATEHEAP();
+ HRESULT hresult = NOERROR;
+ SRVRDISPATCHDATA srvrdispdata;
+ DISPATCHDATA dispatchdata;
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN SrvrHandleIncomingCall lpsrvr=%x hwnd=%x hdata=%x wParam=%x\n",
+ lpsrvr,
+ hwnd,
+ hdata,
+ wParam));
+
+ srvrdispdata.wDispFunc = DDE_DISP_SRVRWNDPROC;
+ srvrdispdata.hwnd = hwnd;
+ srvrdispdata.hData = hdata;
+ srvrdispdata.wParam = wParam;
+ srvrdispdata.lpsrvr = lpsrvr;
+
+ dispatchdata.pData = &srvrdispdata;
+
+ RPCOLEMESSAGE rpcMsg;
+ RPC_SERVER_INTERFACE RpcInterfaceInfo;
+ DWORD dwFault;
+
+ rpcMsg.iMethod = 0;
+ rpcMsg.Buffer = &dispatchdata;
+ rpcMsg.cbBuffer = sizeof(dispatchdata);
+ rpcMsg.reserved2[1] = &RpcInterfaceInfo;
+ *MSG_TO_IIDPTR(&rpcMsg) = GUID_NULL;
+
+
+ IRpcStubBuffer * pStub = &(lpsrvr->m_pCallMgr);
+ IRpcChannelBuffer * pChannel = &(lpsrvr->m_pCallMgr);
+ hresult = STAInvoke(&rpcMsg, CALLCAT_SYNCHRONOUS, pStub, pChannel, NULL, &dwFault);
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _OUT SrvrHandleIncomingCall hresult=%x\n",
+ hresult));
+
+ return(hresult);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SrvrDispatchIncomingCall
+//
+// Synopsis: Dispatch a call into the server.
+//
+// Effects: At the moment, the only incoming call that requires handling
+// by the server window is Execute. This routine dispatchs to it,
+// and returns.
+//
+// Arguments: [psdd] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-05-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL SrvrDispatchIncomingCall(PSRVRDISPATCHDATA psdd)
+{
+ VDATEHEAP();
+ HRESULT hr;
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN SrvrDispatchIncomingCall psdd(%x)\n",psdd));
+
+ hr = psdd->lpsrvr->SrvrExecute (psdd->hwnd,
+ psdd->hData,
+ (HWND)(psdd->wParam));
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _OUT SrvrDispatchIncomingCall psdd(%x) hr =%x\n",
+ psdd,
+ hr));
+
+ return(hr);
+}
+
+
+// REVIEW: Revoking Class Factory will not be successful if
+// any clients are either connected to the classfactory
+// or to the object instances.
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SrvrWndProc
+//
+// Synopsis: This is the server window procedure.
+//
+// Effects:
+//
+// Arguments: [hwndIn] -- Window handle (may not be full. See note)
+// [msg] --
+// [wParam] --
+// [lParam] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 8-03-94 kevinro Created
+//
+// Notes:
+//
+// When running in a VDM, it is possible that this window was dispatched
+// without having a full window handle. This happens when the getmessage
+// was dispatched from 16-bit. Therefore, we need to convert the hwnd to
+// a full hwnd before doing any comparision functions.
+//
+//----------------------------------------------------------------------------
+STDAPI_(LRESULT) SrvrWndProc (
+HWND hwndIn,
+UINT msg,
+WPARAM wParam,
+LPARAM lParam
+)
+{
+ BOOL fRevoke=FALSE;
+ LPSRVR lpsrvr;
+ WORD status = NULL;
+ HANDLE hdata;
+ ATOM aItem;
+ HRESULT retval;
+
+ //
+ // The following hwnd variable is used to determine the full HWND, in the
+ // event we were dispatched in a 16 bit process.
+ //
+ HWND hwnd;
+
+#ifdef FIREWALLS
+ HWND hwndClient;
+#endif
+
+
+ switch (msg){
+
+ case WM_DDE_INITIATE:
+ VDATEHEAP();
+#ifdef FIREWALLS
+ AssertSz (lpsrvr, "No server window handle in server window");
+#endif
+ hwnd = ConvertToFullHWND(hwndIn);
+
+ lpsrvr = (LPSRVR)GetWindowLong (hwnd, 0);
+ if (lpsrvr->m_bTerminate){
+ // we are terminating, no more connections
+ break;
+ }
+
+ // class is not matching, so it is not definitely for us.
+ // for apps sending the EXE for initiate, do not allow if the app
+ // is mutiple instance (Bug fix for winworks).
+
+ if (!(lpsrvr->m_aClass == (ATOM)(LOWORD(lParam)) ||
+ (NOERROR==wCompatibleClasses (LOWORD(lParam), lpsrvr->m_aClass)) ||
+ (lpsrvr->m_aExe == (ATOM)(LOWORD(lParam)) && IsSingleServerInstance() )))
+ {
+ break;
+ }
+
+ intrDebugOut((DEB_DDE_INIT,"::SrvrWndProc INITIATE\n"));
+
+
+ if (!lpsrvr->HandleInitMsg (lParam))
+ {
+ if (!(aSysTopic == (ATOM)(HIWORD(lParam))))
+ {
+ //
+ // If this isn't a sys topic, then it must be a request for
+ // a specific document. Send a message to the
+ // children windows, asking for the document. If one of them
+ // may send an ACK to the client.
+ //
+
+ // if the server window is not the right window for
+ // DDE conversation, then try with the doc windows.
+ BOOL fAckSent = SendInitMsgToChildren (hwnd, msg, wParam, lParam);
+
+#ifdef KEVINRO_OLDCODE
+ The following code was removed, because I don't belive it is required
+ any longer. I am not 100% sure yet, so I have left it in. If you find it,
+ you can probably remove it.
+ It appears to be trying to claim the SINGLE_USE class factory from the class
+ factory table. It does this when a child document window sends an ACK to the
+ client, claiming to support the document being asked for. It really doesn't
+ make too much sense here, since a single use server would have already removed
+ its class factory if there was an open document.
+
+ Anyway, the 16-bit version had a direct hack into the class factory table. We
+ don't have that anymore, so this code wouldn't work anyway.
+
+ if (lpsrvr->m_fcfFlags==REGCLS_SINGLEUSE)
+ {
+ if (lpsrvr->m_pfAvail)
+ {
+ // Hide the entry in the class factory table so that no 2.0
+ // client can connect to the same server.
+ Assert (!IsBadWritePtr (lpsrvr->m_pfAvail, sizeof(BOOL)));
+ *(lpsrvr->m_pfAvail) = FALSE;
+ }
+ }
+#endif // KEVINRO_OLDCODE
+ intrDebugOut((DEB_DDE_INIT,"SrvrWndProc Child Init\n"));
+ return fAckSent;
+ }
+ break;
+ }
+
+ // We can enterain this client. Put him in our client list
+ // and acknowledge the initiate.
+
+ if (!AddClient ((LPHANDLE)&lpsrvr->m_hcli, (HWND)wParam,(HWND)/*fLocked*/FALSE))
+ {
+ break;
+ }
+
+ //
+ // Now its time to grab up the class factory from the class
+ // factory table. When this window was created, the class factory
+ // was available. However, it is possible that it has already
+ // been claimed by someone else. So, we try grabbing it (which
+ // normally should succeed). If it fails, then delete the client
+ // and don't acknowledge.
+ //
+
+ if (lpsrvr->m_pClassFactory == NULL)
+ {
+ DdeClassInfo ddeInfo;
+ ddeInfo.dwContextMask = CLSCTX_LOCAL_SERVER |
+ CLSCTX_INPROC_SERVER;
+ intrDebugOut((DEB_DDE_INIT,"SrvrWndProc getting class factory\n"));
+ //
+ // The following asks for control of the class
+ // factory in the case of a single use class
+ //
+ ddeInfo.fClaimFactory = TRUE;
+ ddeInfo.dwRegistrationKey = lpsrvr->m_dwClassFactoryKey;
+
+ if (GetClassInformationFromKey(&ddeInfo) == FALSE)
+ {
+ intrDebugOut((DEB_IERROR,"SrvrWndProc failed to get class factory\n"));
+ //
+ // Whoops, we were not able to grab the class factory
+ // Cleanup and hop out
+ if (!FindClient ((LPHANDLE)lpsrvr->m_hcli,(HWND)wParam, TRUE))
+ {
+ intrAssert(!"FindClient failed\n");
+ }
+ return(0);
+ }
+ lpsrvr->m_pClassFactory = (IClassFactory *)ddeInfo.punk;
+ lpsrvr->m_fcfFlags = ddeInfo.dwFlags;
+ }
+
+ intrAssert(lpsrvr->m_pClassFactory != NULL);
+
+ lpsrvr->m_cSrvrClients++;
+
+ lpsrvr->Lock (TRUE, (HWND)wParam);
+
+ // Post acknowledge
+ DuplicateAtom (LOWORD(lParam));
+ DuplicateAtom (HIWORD(lParam));
+ SSSendMessage ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lParam);
+
+
+ return 1L; // fAckSent==TRUE
+ VDATEHEAP();
+ break;
+
+
+ case WM_DDE_EXECUTE:
+ VDATEHEAP();
+ hwnd = ConvertToFullHWND(hwndIn);
+
+ lpsrvr = (LPSRVR)GetWindowLong (hwnd, 0);
+
+ hdata = GET_WM_DDE_EXECUTE_HDATA(wParam,lParam);
+
+#ifdef FIREWALLS
+ AssertSz (lpsrvr, "No server handle in server window");
+#endif
+
+ intrDebugOut((DEB_ITRACE,"SrvrWndProc WM_DDE_EXECUTE\n"));
+
+#ifdef FIREWALLS
+ // find the client in the client list.
+ hwndClient = FindClient (lpsrvr->m_hcli, (HWND)wParam, FALSE);
+ AssertSz (hwndClient, "Client is missing from the server")
+#endif
+ // Are we terminating
+ if (lpsrvr->m_bTerminate) {
+ intrDebugOut((DEB_ITRACE,
+ "SrvrWndProc WM_DDE_EXECUTE ignored for TERMINATE\n"));
+ // !!! are we supposed to free the data
+ GlobalFree (hdata);
+ break;
+ }
+
+ retval = SrvrHandleIncomingCall(lpsrvr,hwnd,hdata,(HWND)wParam);
+
+ if (NOERROR!=retval)
+ {
+ intrDebugOut((DEB_IERROR,
+ "SrvrWndProc SrvrHandleIncomingCall fail %x\n",
+ retval));
+ }
+ SET_MSG_STATUS (retval, status)
+
+ if (!lpsrvr->m_bTerminate)
+ {
+ // REVIEW: We are making an assumption that, we will not be posting
+ // any DDE messages because of calling the SrvrExecute.
+ // If we post any messages, before we post the acknowledge
+ // we will be in trouble.
+
+ lParam = MAKE_DDE_LPARAM(WM_DDE_ACK,status,(UINT) hdata);
+
+ intrDebugOut((DEB_ITRACE,
+ "SrvrWndProc WM_DDE_EXECUTE sending %x for ack\n",status));
+
+ // Post the acknowledge to the client
+ if (!PostMessageToClient ((HWND) wParam,
+ WM_DDE_ACK, (UINT) hwnd, lParam)) {
+ // if the window died or post failed, delete the atom.
+ GlobalFree (hdata);
+ DDEFREE(WM_DDE_ACK,lParam);
+ }
+ }
+ VDATEHEAP();
+ break;
+
+
+
+ case WM_DDE_TERMINATE:
+ intrDebugOut((DEB_ITRACE,
+ "SrvrWndProc WM_DDE_TERMINATE\n"));
+
+ hwnd = ConvertToFullHWND(hwndIn);
+
+ lpsrvr = (LPSRVR)GetWindowLong (hwnd, 0);
+
+#ifdef FIREWALLS
+ // find the client in the client list.
+ hwndClient = FindClient (lpsrvr->m_hcli, (HWND)wParam, FALSE);
+ AssertSz (hwndClient, "Client is missing from the server")
+#endif
+ Putsi (lpsrvr->m_bTerminate);
+ if (lpsrvr->m_bTerminate)
+ {
+ AssertSz (0, "Unexpected code path");
+ }
+ else
+ {
+ // If client initiated the terminate. post matching terminate
+ PostMessageToClient ((HWND)wParam,
+ WM_DDE_TERMINATE,
+ (UINT) hwnd,
+ NULL);
+ --lpsrvr->m_cSrvrClients;
+ if (0==lpsrvr->m_cSrvrClients
+ && lpsrvr->QueryRevokeClassFactory())
+ {
+#ifdef KEVINRO_OLD_CODE
+ if (lpsrvr->m_phwndDde)
+ {
+ // Remove from class factory table
+ *(lpsrvr->m_phwndDde) = (HWND)0;
+ }
+#endif // KEVINRO_OLD_CODE
+ fRevoke = TRUE;
+ }
+
+ lpsrvr->Lock (FALSE, (HWND)wParam); // Unlock server
+ FindClient (lpsrvr->m_hcli, (HWND)wParam, /*fDelete*/TRUE);
+
+ if (fRevoke)
+ {
+ lpsrvr->Revoke();
+ }
+ }
+ break;
+
+
+ case WM_DDE_REQUEST:
+ aItem = GET_WM_DDE_REQUEST_ITEM(wParam,lParam);
+
+ hwnd = ConvertToFullHWND(hwndIn);
+
+ lpsrvr = (LPSRVR)GetWindowLong (hwnd, 0);
+
+ intrDebugOut((DEB_ITRACE,
+ "SrvrWndProc WM_DDE_REQUEST(aItem=%x)\n",aItem));
+
+ if (lpsrvr->m_bTerminate || !IsWindowValid ((HWND) wParam))
+ {
+ goto RequestErr;
+ }
+
+ if(RequestDataStd (aItem, (HANDLE FAR *)&hdata) != NOERROR)
+ {
+
+ lParam = MAKE_DDE_LPARAM(WM_DDE_ACK,0x8000,aItem);
+
+ // if request failed, then acknowledge with error.
+ if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK,
+ (UINT) hwnd, lParam))
+ {
+ DDEFREE(WM_DDE_ACK,lParam);
+RequestErr:
+ if (aItem)
+ {
+ GlobalDeleteAtom (aItem);
+ }
+
+ }
+ }
+ else
+ {
+ lParam = MAKE_DDE_LPARAM(WM_DDE_REQUEST,
+ (UINT) hdata,(UINT) aItem);
+
+ // post the data message and we are not asking for any
+ // acknowledge.
+
+ if (!PostMessageToClient ((HWND)wParam, WM_DDE_DATA,
+ (UINT) hwnd, lParam))
+ {
+ GlobalFree (hdata);
+ DDEFREE(WM_DDE_REQUEST,lParam);
+ goto RequestErr;
+ }
+ }
+ break;
+
+ case WM_DONOTDESTROY:
+ intrDebugOut((DEB_ITRACE,
+ "SrvrWndProc WM_DONOTDESTROY %x\n",
+ wParam));
+
+ //
+ // This message is only sent by 32-bit code that has been
+ // given our full handle
+ //
+
+ lpsrvr = (LPSRVR)GetWindowLong (hwndIn, 0);
+
+ //
+ // The WM_DONOTDESTROY message tells the server how to
+ // handle the following WM_USER message. If wParam is set,
+ // then the m_fDoNotDestroyWindow flag will be set, which
+ // keeps us from destroying the server window. If cleared,
+ // it will enable the destruction. This message is sent
+ // from the MaybeCreateDocWindow routine
+ //
+
+ lpsrvr->m_fDoNotDestroyWindow = wParam;
+ return 0;
+ break;
+
+ case WM_USER:
+ intrDebugOut((DEB_ITRACE,
+ "SrvrWndProc WM_USER\n"));
+ //
+ // This message is only sent by 32-bit code that has been
+ // given our full handle
+ //
+
+ lpsrvr = (LPSRVR)GetWindowLong (hwndIn, 0);
+
+ // cftable.cpp sends a WM_USER message to destory the DDE
+ // server window when a 2.0 client has connected to a
+ // SDI 2.0 server (and no 1.0 client should be allowed to also
+ // connect.
+ // cftable.cpp cannot call RemDdeRevokeClassFactory directly
+ // becuase they may be in different processes.
+ //
+ // The m_fDoNotDestroyWindow flag is used by
+ // MaybeCreateDocWindow in the case that the server is a
+ // single use server, and revokes its class factory when
+ // an object is created. MaybeCreateDocWindow will set this
+ // flag, telling us to ignore the message.
+ //
+ // returning 0 means we did destroy, 1 means we did not.
+
+ if (!lpsrvr->m_fDoNotDestroyWindow)
+ {
+ RemDdeRevokeClassFactory(lpsrvr);
+ return(0);
+ }
+ return 1;
+ break;
+
+ default:
+ return SSDefWindowProc (hwndIn, msg, wParam, lParam);
+ }
+
+ return 0L;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDDEServer::HandleInitMsg
+//
+// Synopsis: Determine if we are going to handle the INITIATE message.
+//
+// Effects:
+//
+// Arguments: [lParam] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-28-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(BOOL) CDDEServer::HandleInitMsg(LPARAM lParam)
+{
+
+ // If it is not system or Ole, this is not the server.
+ if (!((aSysTopic == (ATOM)(HIWORD(lParam))) || (aOLE == (ATOM)(HIWORD(lParam)))))
+ {
+ return FALSE;
+ }
+ Assert (m_fcfFlags<=REGCLS_MULTI_SEPARATE);
+
+ // single instance MDI accept
+ if (m_fcfFlags != REGCLS_SINGLEUSE)
+ {
+ return TRUE;
+ }
+
+ // this server is multiple instance. So, check for any clients or docs.
+ if (!GetWindow (m_hwnd, GW_CHILD) && 0==m_cSrvrClients)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+
+// AddClient: Adds a client entry to the list.
+// Each client entry is a pair of handles; key handle
+// and data handle. Ecah list entry contains space for
+// MAX_LIST of pairs of handles.
+
+INTERNAL_(BOOL) AddClient
+(
+LPHANDLE lphead, // ptr to loc which contains the head handle
+HANDLE hkey, // key
+HANDLE hdata // hdata
+)
+{
+
+ HANDLE hcli = NULL;
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+
+
+ hcli = *lphead;
+
+ // if the entry is already present, return error.
+ if (hcli && FindClient (hcli, hkey, FALSE))
+ return FALSE;
+
+ while (hcli) {
+ if (hcliPrev)
+ LocalUnlock (hcliPrev);
+
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ return FALSE;
+
+ phandle = (HANDLE *) pcli->info;
+ while (phandle < (HANDLE *)(pcli + 1)) {
+ if (*phandle == NULL) {
+ *phandle++ = hkey;
+ *phandle++ = hdata;
+ LocalUnlock (hcli);
+ return TRUE;
+ }
+ phandle++;
+ phandle++;
+ }
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ lphead = (LPHANDLE)&pcli->hcliNext;
+ }
+
+ // not in the list.
+ hcli = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof (CLILIST));
+ if (hcli == NULL)
+ goto errRtn;
+
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ goto errRtn;
+
+ // set the link to this handle in the previous entry
+ *lphead = hcli;
+ if (hcliPrev)
+ LocalUnlock (hcliPrev);
+
+ phandle = (HANDLE *) pcli->info;
+ *phandle++ = hkey;
+ *phandle++ = hdata;
+ LocalUnlock (hcli);
+ return TRUE;
+
+errRtn:
+
+ if (hcliPrev)
+ LocalUnlock (hcliPrev);
+
+ if (hcli)
+ LocalFree (hcli);
+
+ return FALSE;
+
+}
+
+
+// FindClient: finds a client and deletes the client if necessary.
+INTERNAL_(HANDLE) FindClient
+(
+HANDLE hcli,
+HANDLE hkey,
+BOOL bDelete
+)
+{
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+ HANDLE hdata;
+
+ while (hcli) {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ return FALSE;
+
+ phandle = (HANDLE *) pcli->info;
+ while (phandle < (HANDLE *)(pcli + 1)) {
+ if (*phandle == hkey) {
+ if (bDelete)
+ *phandle = NULL;
+
+ hdata = *++phandle;
+ LocalUnlock (hcli);
+ return hdata;
+ }
+ phandle++;
+ phandle++;
+ }
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+
+ }
+ return NULL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDDEServer::SrvrExecute
+//
+// Synopsis: takes care of the WM_DDE_EXECUTE for the server.
+//
+// Effects: Parses the EXECUTE string, and determines what it should be
+// done.
+//
+// Arguments: [hwnd] -- Server window
+// [hdata] -- Handle to EXECUTE string
+// [hwndClient] -- Client window
+//
+// Requires:
+// hdata is an ANSI string. It was passed to us by a DDE client.
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 6-05-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CDDEServer::SrvrExecute
+(
+HWND hwnd,
+HANDLE hdata,
+HWND hwndClient
+)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDDESrvr::SrvrExecute(hwnd=%x,hdata=%x,hwndClient=%x)\n",
+ this,
+ hwnd,
+ hdata,
+ hwndClient));
+
+ ATOM aCmd;
+ BOOL fActivate;
+
+ LPSTR lpdata = NULL;
+ HANDLE hdup = NULL;
+ HRESULT hresult = E_UNEXPECTED;
+
+ LPSTR lpdocname;
+ LPSTR lptemplate;
+ LPCLIENT lpdocClient = NULL;
+ LPSTR lpnextarg;
+ LPSTR lpclassname;
+ LPSTR lpitemname;
+ LPSTR lpopt;
+ CLSID clsid;
+ WORD wCmdType;
+ BOOL bCreateInst = FALSE;
+ LPUNKNOWN pUnk = NULL;
+
+ LPPERSISTSTORAGE pPersistStg=NULL;
+
+ // REVIEW: if any methods called on the objects genarate DDE messages
+ // before we return from Execute, we will be in trouble.
+
+
+ // REVIEW: this code can be lot simplified if we do the argument scanning
+ // seperately and return the ptrs to the args. Rewrite later on.
+
+ ErrZS (hdup = UtDupGlobal (hdata,GMEM_MOVEABLE), E_OUTOFMEMORY);
+
+ ErrZS (lpdata = (LPSTR)GlobalLock (hdup), E_OUTOFMEMORY);
+
+ intrDebugOut((DEB_ITRACE,
+ "CDDESrvr::SrvrExecute(lpdata = %s)\n",lpdata));
+
+ if (*lpdata++ != '[') // commands start with the left sqaure bracket
+ {
+ hresult = ResultFromScode (RPC_E_DDE_SYNTAX_EXECUTE);
+ goto errRtn;
+ }
+
+ hresult = ReportResult(0, RPC_E_DDE_SYNTAX_EXECUTE, 0, 0);
+ // scan upto the first arg
+ if (!(wCmdType = ScanCommand (lpdata, WT_SRVR, &lpdocname, &aCmd)))
+ goto errRtn;
+
+ if (wCmdType == NON_OLE_COMMAND)
+ {
+ if (!UtilQueryProtocol (m_aClass, PROTOCOL_EXECUTE))
+ hresult = ReportResult(0, RPC_E_DDE_PROTOCOL, 0, 0);
+ else {
+ // REVIEW: StdExecute has to be mapped on to the StdCommandProtocol
+ // What command do we map on to?
+
+ AssertSz (0, "StdExecute is being called for server");
+ }
+
+ goto errRtn1;
+ }
+
+ if (aCmd == aStdExit)
+ {
+ if (*lpdocname)
+ goto errRtn1;
+
+ hresult = NOERROR;
+ // REVIEW: Do we have to initiate any terminations from the
+ // the servr side? Check how this works with excel.
+ goto end2;
+ }
+
+ // scan the next argument.
+ if (!(lpnextarg = ScanArg(lpdocname)))
+ goto errRtn;
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdShowItem("docname", "itemname"[, "true"])]
+ //
+ //////////////////////////////////////////////////////////////////////////
+
+ if (aCmd == aStdShowItem) {
+
+ // first find the documnet. If the doc does not exist, then
+ // blow it off.
+
+ if (!(lpdocClient = FindDocObj (lpdocname)))
+ goto errRtn1;
+
+ lpitemname = lpnextarg;
+
+ if( !(lpopt = ScanArg(lpitemname)))
+ goto errRtn1;
+
+ // scan for the optional parameter
+ // Optional can be only TRUE or FALSE.
+
+ fActivate = FALSE;
+ if (*lpopt) {
+
+ if( !(lpnextarg = ScanBoolArg (lpopt, (BOOL FAR *)&fActivate)))
+ goto errRtn1;
+
+ if (*lpnextarg)
+ goto errRtn1;
+
+ }
+
+
+ // scan it. But, igonre the arg.
+ hresult = lpdocClient->DocShowItem (lpitemname, !fActivate);
+ goto end2;
+
+
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdCloseDocument ("docname")]
+ //
+ //////////////////////////////////////////////////////////////////////////
+
+ if (aCmd == aStdClose) {
+ if (!(lpdocClient = FindDocObj (lpdocname)))
+ goto errRtn1;
+
+ if (*lpnextarg)
+ goto errRtn1;
+
+ // REVIEW: Do we have to do anything for shutting down the
+ // the app? Is the client going to initiate the terminate?.
+ // if we need to initiate the terminates, make sure we post
+ // the ACK first.
+
+ lpdocClient->Revoke();
+ goto end2;
+ }
+
+
+ if (aCmd == aStdOpen)
+ {
+ // find if any doc level object is already registerd.
+ // if the object is registerd, then no need to call srvr app.
+ if (FindDocObj (lpdocname))
+ {
+ // A client has already opened the document or user opened the
+ // doc. We should do an addref to the docobj
+
+#ifdef TRY
+ if (m_cSrvrClients == 0)
+ // Why are we doing this?
+ hresult = lpdocClient->m_lpoleObj->AddRef();
+ else
+#endif
+ hresult = NOERROR;
+ goto end1;
+ }
+ }
+
+ if (aCmd == aStdCreate || aCmd == aStdCreateFromTemplate) {
+ lpclassname = lpdocname;
+ lpdocname = lpnextarg;
+ if( !(lpnextarg = ScanArg(lpdocname)))
+ goto errRtn1;
+
+ }
+
+ // check whether we can create/open more than one doc.
+
+ if ((m_fcfFlags == REGCLS_SINGLEUSE) &&
+ GetWindow (m_hwnd, GW_CHILD))
+ goto errRtn;
+
+
+ ErrZ (CLSIDFromAtom(m_aClass, &clsid));
+
+
+ //
+ // Generate a wide version of the name
+ //
+
+ WCHAR awcWideDocName[MAX_STR];
+
+ if (MultiByteToWideChar(CP_ACP,0,lpdocname,-1,awcWideDocName,MAX_STR) == FALSE)
+ {
+ Assert(!"Unable to convert characters");
+ hresult = E_UNEXPECTED;
+ goto errRtn;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdOpenDocument ("docname")]
+ //
+ //////////////////////////////////////////////////////////////////////////
+
+ // Document does not exist.
+ if (aCmd == aStdOpen)
+ {
+ ErrRtnH (wClassesMatch (clsid, awcWideDocName));
+ ErrRtnH (wFileBind (awcWideDocName, &pUnk));
+ }
+
+
+ ErrRtnH (CreateInstance (clsid, awcWideDocName, lpdocname, pUnk, &lpdocClient, hwndClient));
+ bCreateInst = TRUE;
+
+ if (aCmd == aStdOpen)
+ {
+ // Temporary flag to indicate someone will INITIATE on this doc.
+ // The flag is reset after the INITITATE.
+ // This is Yet-Another-Excel-Hack. See ::QueryRevokeClassFactory
+ lpdocClient->m_fCreatedNotConnected = TRUE;
+ }
+ else
+ {
+ lpdocClient->m_fEmbed = TRUE;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdNewDocument ("classname", "docname")]
+ //
+ //////////////////////////////////////////////////////////////////////////
+
+ if (aCmd == aStdCreate)
+ {
+ hresult = lpdocClient->DoInitNew();
+ lpdocClient->m_fCreatedNotConnected = TRUE;
+ goto end;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdNewFormTemplate ("classname", "docname". "templatename)]
+ //
+ //////////////////////////////////////////////////////////////////////////
+ if (aCmd == aStdCreateFromTemplate)
+ {
+ ErrRtnH (lpdocClient->DoInitNew());
+ lpdocClient->m_fCreatedNotConnected = TRUE;
+ IPersistFile FAR * lpPF;
+ lptemplate = lpnextarg;
+
+ if(!(lpnextarg = ScanArg(lpnextarg)))
+ {
+ goto errRtn;
+ }
+
+
+ hresult = lpdocClient->m_lpoleObj->QueryInterface(IID_IPersistFile,(LPLPVOID)&lpPF);
+ if (hresult == NOERROR)
+ {
+ WCHAR awcWideTemplate[MAX_STR];
+
+ if (MultiByteToWideChar(CP_ACP,0,lpdocname,-1,awcWideTemplate,MAX_STR) != FALSE)
+ {
+ hresult = lpPF->Load(awcWideTemplate, 0);
+ }
+ else
+ {
+ Assert(!"Unable to convert characters");
+ lpPF->Release();
+ hresult = E_UNEXPECTED;
+ goto end;
+ }
+
+ lpPF->Release();
+ lpdocClient->m_fEmbed = TRUE;
+ }
+ else
+ {
+ goto end;
+ }
+ }
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdEditDocument ("docname")]
+ //
+ //////////////////////////////////////////////////////////////////////////
+ // REVIEW: Do we have to call InitNew for editing an embedded object
+
+ if (aCmd == aStdEdit)
+ {
+ lpdocClient->m_fEmbed = TRUE;
+ lpdocClient->m_fGotEditNoPokeNativeYet = TRUE;
+ lpdocClient->m_fCreatedNotConnected = TRUE;
+ goto end;
+ }
+
+ intrDebugOut((DEB_IERROR,
+ "%x CDDESrvr::SrvrExecute Unknown command\n",
+ this));
+
+end:
+
+ if (hresult != NOERROR)
+ goto errRtn;
+end1:
+ // make sure that the srg string is indeed terminated by
+ // NULL.
+ if (*lpnextarg)
+ {
+ hresult = RPC_E_DDE_SYNTAX_EXECUTE;
+ }
+errRtn:
+
+ if ( hresult != NOERROR)
+ {
+ if (bCreateInst && lpdocClient)
+ {
+ lpdocClient->DestroyInstance ();
+ lpdocClient = NULL; //DestroyInstance invalidates the pointer
+ }
+ }
+
+end2:
+errRtn1:
+
+ if (lpdata)
+ GlobalUnlock (hdup);
+
+ if (hdup)
+ GlobalFree (hdup);
+ if (pUnk)
+ pUnk->Release();
+
+ if (pPersistStg)
+ pPersistStg->Release();
+
+ Assert (GetScode(hresult) != E_UNEXPECTED);
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDDESrvr::SrvrExecute hresult=%x\n",
+ this,
+ hresult));
+
+ return hresult;
+}
+
+
+
+
+// Maybe CreateDocWindow
+//
+// Return NOERROR only if a doc window was created and it sent an ACK.
+//
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: MaybeCreateDocWindow
+//
+// Synopsis: Determine if a DocWindow should be created
+//
+// Effects: Given a class, and a filename atom, determine if this thread
+// should be the server for this request.
+//
+// Arguments: [aClass] -- Class of object (PROGID)
+// [aFile] -- Filename (ATOM)
+// [hwndDdeServer] -- HWND of CDDEServer
+// [hwndSender] -- HWND of new requesting client
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-29-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+ INTERNAL MaybeCreateDocWindow
+ (ATOM aClass,
+ ATOM aFile,
+ HWND hwndDdeServer,
+ HWND hwndSender)
+{
+ CLSID clsid = CLSID_NULL;
+ LPUNKNOWN pUnk = NULL;
+ HWND hwndClient = NULL;
+ ULONG fAckSent = FALSE;
+ LPSRVR pDdeSrvr = NULL;
+ WCHAR szFile [MAX_STR];
+ BOOL fTrue = TRUE;
+ BOOL fRunningInSDI = FALSE;
+ HRESULT hresult = NOERROR;
+ IClassFactory *pcf = NULL;
+ IPersistFile *ppf = NULL;
+ DdeClassInfo ddeClassInfo;
+
+ intrDebugOut((DEB_DDE_INIT,
+ "MaybeCreateDocWindow(aClass=%x(%ws),aFile=%x,"
+ "hwndDdeServer=%x,hwndSender=%x\n",
+ aClass,wAtomName(aClass),aFile,hwndDdeServer,hwndSender));
+
+ //
+ // If the window isn't valid, it would be very bad.
+ //
+ if (!IsWindowValid(hwndDdeServer))
+ {
+ intrDebugOut((DEB_DDE_INIT,
+ "MaybeCreateDocWindow: hwndDdeServer is invalid\n"));
+ hresult = E_UNEXPECTED;
+ goto exitRtn;
+ }
+
+ //
+ // We need the filename, which is passed in an Atom
+ //
+ Assert (IsFile (aFile));
+ if (GlobalGetAtomName(aFile,szFile,MAX_STR) == 0)
+ {
+ //
+ // The filename was not valid
+ //
+ hresult = S_FALSE;
+ intrDebugOut((DEB_IERROR,
+ "MaybeCreateDocWindow Invalid file atom\n"));
+ goto exitRtn;
+ }
+
+ intrDebugOut((DEB_DDE_INIT,
+ "MaybeCreateDocWindow File=(%ws)\n",
+ WIDECHECK(szFile)));
+
+ //
+ // Get the class of the object. The class was passed as an atom
+ // in the INITIATE message.
+ //
+ if (CLSIDFromAtomWithTreatAs (&aClass, &clsid, NULL))
+ {
+ intrDebugOut((DEB_IERROR,
+ "MaybeCreateDocWindow CLSIDFromAtom failed\n"));
+
+ hresult = S_FALSE;
+ goto exitRtn;
+ }
+
+ if (CoIsOle1Class(clsid))
+ {
+ // we shouldn't even be looking at this INIT message
+ hresult = S_FALSE;
+ intrDebugOut((DEB_DDE_INIT,
+ "MaybeCreateDocWindow Its an OLE 1.0 class\n"));
+ goto exitRtn;
+ }
+
+ //
+ // First of three cases is to see if the object is running in our
+ // local apartment. If it is, then this is the object we need to create
+ // a DDEServer for.
+ //
+ // Otherwise, We are going to try and load this file.
+ // Therefore, we need the class factory from the CFT.
+ //
+ // GetClassInformationForDde won't find a match if the class factory was
+ // single use, and is now hidden or invalid.
+ //
+ // If there was no class information available, then we are going to
+ // check to see if the object is in the local ROT. If it is in the
+ // local ROT, then we will use it, since it is registered and
+ // available for use by others
+ //
+
+ ddeClassInfo.dwContextMask = CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER;
+ ddeClassInfo.fClaimFactory = TRUE;
+
+ if ( GetLocalRunningObjectForDde(szFile, &pUnk) == NOERROR)
+ {
+ intrDebugOut((DEB_DDE_INIT,
+ "Found %ws in ROT\n",WIDECHECK(szFile)));
+ //
+ // Elsewhere in the code, we need to know if this is an SDI server.
+ // The old code determined this by detecting that there is a running
+ // object, and there was no class factory registered.
+ // This is sick, and obscene. Compatibilities says we need to get the
+ // class info anyway. However, we don't want to claim it.
+ //
+
+ ddeClassInfo.fClaimFactory = FALSE;
+ fRunningInSDI = !GetClassInformationForDde(clsid,&ddeClassInfo);
+ }
+ else if (!GetClassInformationForDde(clsid,&ddeClassInfo))
+ {
+ intrDebugOut((DEB_IERROR,
+ "No class registered for %ws\n",WIDECHECK(szFile)));
+
+ hresult = S_FALSE;
+ goto exitRtn;
+ }
+ else
+ {
+ //
+ // Otherwise, we are registered as the server for this class. This
+ // means we can create this object.
+ //
+ // A 1.0 client will have launched the server with a command line
+ // like server.exe -Embedding filename The server ignored the filename
+ // so now we must make it load the file by binding the moniker.
+ //
+ // KevinRo: The old code did a bind moniker here, on the filename,
+ // which went through the ROT, didn't find the object, so went for
+ // a server. This isn't terribly safe, since we could end up binding
+ // out of process when we really didn't mean to. So, I have made this
+ // routine just use the ClassFactory we retrieve from the
+ // local class factory table.
+ //
+
+ intrDebugOut((DEB_DDE_INIT,
+ "Found classinfo: Loading %ws\n",WIDECHECK(szFile)));
+
+
+ //
+ // Need to insure that the server doesn't go away on us. The following
+ // tells the server not to destroy itself.
+ //
+ SSSendMessage(hwndDdeServer,WM_DONOTDESTROY,TRUE,0);
+
+ intrAssert(ddeClassInfo.punk != NULL);
+ pcf = (IClassFactory *) ddeClassInfo.punk;
+
+ hresult = pcf->CreateInstance(NULL,IID_IUnknown,(void **)&pUnk);
+
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "MaybeCreateDocWindow CreateInstancefailed File=(%ws)\n",
+ WIDECHECK(szFile)));
+ goto sndMsg;
+ }
+
+ //
+ // Get the IPersistFile interface, and ask the object to load
+ // itself.
+ //
+ hresult = pUnk->QueryInterface(IID_IPersistFile,(void **)&ppf);
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "MaybeCreateDocWindow QI IPF failed File=(%ws)\n",
+ WIDECHECK(szFile)));
+ goto sndMsg;
+ }
+ //
+ // Attempt to load the object. The flags STGM_READWRITE are the
+ // same default values used by a standard bind context.
+ //
+ hresult = ppf->Load(szFile,STGM_READWRITE);
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "MaybeCreateDocWindow ppf->Load(%ws) failed %x\n",
+ WIDECHECK(szFile),
+ hresult));
+ goto sndMsg;
+ }
+sndMsg:
+ SSSendMessage(hwndDdeServer,WM_DONOTDESTROY,FALSE,0);
+ if (hresult != NOERROR)
+ {
+ goto exitRtn;
+
+ }
+ intrDebugOut((DEB_DDE_INIT,
+ "Loading %ws complete\n",WIDECHECK(szFile)));
+
+ }
+
+
+ intrAssert(IsWindowValid(hwndDdeServer));
+ intrAssert (pUnk);
+
+ pDdeSrvr = (LPSRVR) GetWindowLong (hwndDdeServer, 0);
+ if (pDdeSrvr == NULL)
+ {
+ intrAssert(pDdeSrvr != NULL);
+ hresult = E_UNEXPECTED;
+ goto exitRtn;
+ }
+
+ // This actually creates the doc window as a child of the server window
+ // Do not set the client site becuase this is a link.
+ hresult = CDefClient::Create (pDdeSrvr,
+ pUnk,
+ szFile,
+ /*fSetClientSite*/FALSE,
+ /*fDoAdvise*/TRUE,
+ fRunningInSDI,
+ &hwndClient);
+
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "MaybeCreateDocWindow CDefClient::Create failed %x\n",
+ hresult));
+ goto exitRtn;
+ }
+
+ Assert (IsWindowValid (hwndClient));
+
+ //
+ // Pass along the original DDE_INIT to the newly created window.
+ // That window should respond by sending an ACK to the 1.0 client.
+ //
+ fAckSent = SSSendMessage (hwndClient,
+ WM_DDE_INITIATE,
+ (UINT) hwndSender,
+ MAKELONG(aClass, aFile));
+ if (!fAckSent)
+ {
+ intrDebugOut((DEB_IERROR,
+ "MaybeCreateDocWindow !fAckSent\n"));
+ hresult = CO_E_APPDIDNTREG;
+ }
+
+exitRtn:
+
+ if (ppf)
+ {
+ ppf->Release();
+ }
+ if (pUnk)
+ {
+ pUnk->Release();
+ }
+ if (pcf)
+ {
+ pcf->Release();
+ }
+
+ intrDebugOut((DEB_DDE_INIT,
+ "MaybeCreateDocWindow returns %x\n",
+ hresult));
+ return hresult;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SendMsgToChildren
+//
+// Synopsis: This routine sends the msg to all child windows.
+//
+// Arguments: [hwnd] -- Hwnd of parent window
+// [msg] -- Message and parameters to send
+// [wParam] --
+// [lParam] --
+//
+// Notes: This routine will stop on the first non-zero return code.
+//
+//----------------------------------------------------------------------------
+BOOL SendMsgToChildren (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN SendMsgToChildren(hwnd=%x,msg=%x,wParam=%x,lParam=%x)\n",
+ hwnd,msg,wParam,lParam));
+
+ BOOL fAckSent = FALSE;
+
+ hwnd = GetWindow(hwnd, GW_CHILD);
+
+ //
+ // This routine is to be called only from one place, which is
+ // in the handling of WM_DDE_INITIATE. Because of that, we will terminate
+ // the loop on the first non-zero return code.
+ //
+ Assert (msg == WM_DDE_INITIATE);
+
+ while (hwnd)
+ {
+ intrDebugOut((DEB_ITRACE," SendMsgToChildren send to hwnd=%x\n",hwnd));
+
+ if (fAckSent = (1L==SSSendMessage (hwnd, msg, wParam, lParam)))
+ {
+ break;
+ }
+
+ hwnd = GetWindow (hwnd, GW_HWNDNEXT);
+ }
+
+ intrDebugOut((DEB_ITRACE,"0 OUT SendMsgToChildren returns %x\n",fAckSent));
+ return(fAckSent);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SendInitMsgToChildren
+//
+// Synopsis: Sends an init message to all child windows of the hwnd
+//
+// Effects: This routine will send an init message to all children
+// of the given window. It is assuming that the lParam is
+// the atom that contains the topic (ie filename) of the
+// object being looked for.
+//
+// Arguments: [hwnd] -- hwnd of server window
+// [msg] -- MSG to send
+// [wParam] -- hwnd of client window
+// [lParam] -- HIWORD(lParam) is atom of filename
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-28-94 kevinro Commented
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL SendInitMsgToChildren (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ intrDebugOut((DEB_DDE_INIT,
+ "0 _IN SendInitMsgToChildren(hwnd=%x,msg=%x,wParam=%x,lParam=%x)\n",
+ hwnd,msg,wParam,lParam));
+
+ BOOL fAckSent = FALSE;
+
+ fAckSent = SendMsgToChildren(hwnd,msg,wParam,lParam);
+
+ //
+ // If no windows acknowledged, then we might need to create a doc window
+ //
+ if (!fAckSent)
+ {
+ ATOM aTopic = HIWORD(lParam);
+ Assert (IsAtom(aTopic));
+
+ // if someone's trying to initiate on a filename, i.e., for a link
+ // then create the doc window on demand because 2.0 servers do not
+ // register doc windows. They don't even accept "-Embedding filename"
+ // on the command line
+ if (aTopic != aOLE && aTopic != aSysTopic && IsFile (aTopic))
+ {
+ intrDebugOut((DEB_DDE_INIT," Initiate for link %ws\n",wAtomName(aTopic)));
+ HRESULT hresult = MaybeCreateDocWindow (LOWORD(lParam), aTopic,
+ hwnd, (HWND)wParam);
+
+ fAckSent = (NOERROR==hresult);
+ }
+ }
+ intrDebugOut((DEB_DDE_INIT,
+ "0 _OUT SendInitMsgToChildren fAckSent=%x\n",fAckSent));
+ return fAckSent;
+}
+
+
+
+INTERNAL_(HRESULT) RequestDataStd
+(
+ATOM aItem,
+LPHANDLE lphdde
+)
+{
+
+
+ HANDLE hnew = NULL;
+
+ if (!aItem)
+ goto errRtn;
+
+ if (aItem == aEditItems){
+ hnew = MakeGlobal ("StdHostNames\tStdDocDimensions\tStdTargetDevice");
+ goto PostData;
+
+ }
+
+ if (aItem == aProtocols) {
+ hnew = MakeGlobal ("Embedding\tStdFileEditing");
+ goto PostData;
+ }
+
+ if (aItem == aTopics) {
+ hnew = MakeGlobal ("Doc");
+ goto PostData;
+ }
+
+ if (aItem == aFormats) {
+ hnew = MakeGlobal ("Picture\tBitmap");
+ goto PostData;
+ }
+
+ if (aItem == aStatus) {
+ hnew = MakeGlobal ("Ready");
+ goto PostData;
+ }
+
+ // format we do not understand.
+ goto errRtn;
+
+PostData:
+
+ // Duplicate the DDE data
+ if (MakeDDEData (hnew, CF_TEXT, lphdde, TRUE)){
+ // !!! why are we duplicating the atom.
+ DuplicateAtom (aItem);
+ return NOERROR;
+ }
+errRtn:
+ return ReportResult(0, S_FALSE, 0, 0);
+}
+
+
+//IsSingleServerInstance: returns true if the app is single server app else
+//false.
+
+INTERNAL_(BOOL) IsSingleServerInstance ()
+{
+ HWND hwnd;
+ WORD cnt = 0;
+ HTASK hTask;
+ DdeCHAR buf[MAX_STR];
+
+ hwnd = GetWindow (GetDesktopWindow(), GW_CHILD);
+ hTask = GetCurrentThreadId();
+
+ while (hwnd) {
+ if (hTask == ((HTASK) GetWindowThreadProcessId (hwnd,NULL))) {
+ DdeGetClassName (hwnd, buf, MAX_STR);
+ if (Ddelstrcmp (buf, SRVR_CLASS) == 0)
+ cnt++;
+ }
+ hwnd = GetWindow (hwnd, GW_HWNDNEXT);
+ }
+#ifdef FIREWALLS
+ AssertSz (cnt > 0, "srvr window instance count is zero");
+#endif
+ if (cnt == 1)
+ return TRUE;
+ else
+ return FALSE;
+
+}
+
+
+// QueryRevokeClassFactory: returns FALSE if there are clients
+// connected tothis class factory;
+INTERNAL_(BOOL) CDDEServer::QueryRevokeClassFactory ()
+{
+
+ HWND hwnd;
+ LPCLIENT lpclient;
+
+ Assert (IsWindow (m_hwnd));
+ hwnd = GetWindow (m_hwnd, GW_CHILD);
+ while (hwnd)
+ {
+ Assert (IsWindow (hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+ if (lpclient->m_cClients != 0 || lpclient->m_fCreatedNotConnected)
+ return FALSE;
+ hwnd = GetWindow (hwnd, GW_HWNDNEXT);
+ }
+ return TRUE;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDDEServer::CreateInstance
+//
+// Synopsis: Create an instance of a document
+//
+// Effects:
+//
+// Arguments: [lpclassName] --
+// [lpWidedocName] --
+// [lpdocName] --
+// [pUnk] --
+// [lplpdocClient] --
+// [hwndClient] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-30-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CDDEServer::CreateInstance
+(
+REFCLSID lpclassName,
+LPOLESTR lpWidedocName,
+LPSTR lpdocName,
+LPUNKNOWN pUnk,
+LPCLIENT FAR* lplpdocClient,
+HWND hwndClient)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CDDEServer::CreateInstance(lpWidedocName=%ws,hwndClient=%x)\n",
+ this,
+ WIDECHECK(lpWidedocName),
+ hwndClient));
+
+
+ LPUNKNOWN pUnk2=NULL;
+ LPOLEOBJECT lpoleObj= NULL; // unknown object
+ HRESULT hresult;
+
+ ChkS(this);
+
+ if (NULL==pUnk)
+ {
+ Assert (m_pClassFactory);
+ hresult = m_pClassFactory->CreateInstance (NULL, IID_IUnknown, (LPLPVOID)&pUnk2);
+
+ if (hresult != NOERROR)
+ {
+ return hresult;
+ }
+
+ // Now that we have *used* the DDE server window, we can unlock
+ // the server.
+ // The OLE1 OleLockServer API opens a dummy DDE system channel
+ // and just leaves it open until OleunlockServer is called.
+ // Since we have now used this channel, we know it was not created
+ // for the purpose of locking the server.
+ this->Lock (FALSE, hwndClient);
+
+ // if it is an SDI app, we must revoke the ClassFactory after using it
+ // it is only good for "one-shot" createinstance call.
+ if (m_fcfFlags == REGCLS_SINGLEUSE)
+ {
+ m_pClassFactory->Release(); // done with the ClassFactory
+ Puts ("NULLing m_pCF\r\n");
+ m_pClassFactory = NULL;
+ }
+ }
+ else
+ {
+ pUnk2 = pUnk;
+ pUnk->AddRef();
+ }
+
+ hresult = CDefClient::Create ((LPSRVR)this,
+ pUnk2,
+ lpWidedocName,
+ /*fSetClientSite*/FALSE,
+ /*fDoAdvise*/pUnk!=NULL);
+
+ intrAssert (pUnk2 != NULL);
+ if (pUnk2 != NULL)
+ {
+ pUnk2->Release();
+ }
+
+ pUnk2 = NULL;
+
+ // REVIEW: error recovery
+ if (!(*lplpdocClient = FindDocObj (lpdocName)))
+ {
+ intrAssert(!"Document created but not found");
+ }
+ else
+ {
+ // set the server instance flag so that WM_DDE_INITIATE will not icrement
+ // the ref count. (EXCEL BUG)
+ (*lplpdocClient)->m_bCreateInst = TRUE;
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT CDDEServer::CreateInstance hresult=%x\n",
+ this,hresult));
+ return hresult;
+}
+
+
+INTERNAL_(void) CDDEServer::Lock
+ (BOOL fLock, // lock or unlock?
+ HWND hwndClient) // on behalf of which window?
+{
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CDDEServer::Lock(fLock=%x,hwndCient=%x)\n",
+ this,
+ fLock,
+ hwndClient));
+
+ VDATEHEAP();
+ BOOL fIsLocked = (BOOL) FindClient (m_hcli, hwndClient, /*fDelete*/FALSE);
+
+ if (fLock && !fIsLocked)
+ {
+ if (m_pClassFactory)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%p ::Locking %x\n",
+ this,
+ m_pClassFactory));
+
+ m_pClassFactory->LockServer (TRUE);
+ // Only way to change the data associated with a client window
+ // is to delete it and re-add it with the new data.
+ FindClient (m_hcli, hwndClient, /*fDelete*/ TRUE);
+ AddClient (&m_hcli, hwndClient, (HANDLE) TRUE); // mark as locked
+ }
+ }
+ else if (!fLock && fIsLocked)
+ {
+ if (m_pClassFactory)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%p ::UnLocking %x\n",
+ this,
+ m_pClassFactory));
+ m_pClassFactory->LockServer (FALSE);
+ FindClient (m_hcli, hwndClient, /*fDelete*/ TRUE);
+ AddClient (&m_hcli, hwndClient, (HANDLE) FALSE); //mark as unlocked
+ }
+ }
+ VDATEHEAP();
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT CDDEServer::Lock(fLock=%x,hwndCient=%x)\n",
+ this,
+ fLock,
+ hwndClient));
+}
+
+
+
+
+
+INTERNAL CDefClient::DestroyInstance
+ (void)
+{
+ Puts ("DestroyInstance\r\n");
+ // We just created the instance. we ran into error.
+ // just call Release.
+ m_pUnkOuter->AddRef();
+ ReleaseObjPtrs();
+ Verify (0==m_pUnkOuter->Release());
+ // "this" should be deleted now
+ return NOERROR;
+}
+
+
+
+INTERNAL CDefClient::SetClientSite
+ (void)
+{
+ HRESULT hresult = m_lpoleObj->SetClientSite (&m_OleClientSite);
+ if (hresult==NOERROR)
+ {
+ m_fDidSetClientSite = TRUE;
+ }
+ else
+ {
+ Warn ("SetClientSite failed");
+ }
+ return hresult;
+}
+
+
+// implementations of IRpcStubBuffer methods
+STDMETHODIMP CDdeServerCallMgr::QueryInterface
+ ( REFIID iid, LPVOID * ppvObj )
+{
+ return S_OK;
+}
+
+STDMETHODIMP_(ULONG)CDdeServerCallMgr::AddRef ()
+{
+ return 1;
+}
+
+STDMETHODIMP_(ULONG)CDdeServerCallMgr::Release ()
+{
+ return 1;
+}
+
+
+STDMETHODIMP CDdeServerCallMgr::Connect
+ (IUnknown * pUnkServer )
+{
+ // do nothing
+ return S_OK;
+}
+
+STDMETHODIMP_(void) CDdeServerCallMgr::Disconnect
+ ()
+{
+ // do nothing
+}
+
+STDMETHODIMP_(IRpcStubBuffer*) CDdeServerCallMgr::IsIIDSupported
+ (REFIID riid)
+{
+ // do nothing
+ return NULL;
+}
+
+
+STDMETHODIMP_(ULONG) CDdeServerCallMgr::CountRefs
+ ()
+{
+ // do nothing
+ return 1;
+}
+
+STDMETHODIMP CDdeServerCallMgr::DebugServerQueryInterface
+ (void ** ppv )
+{
+ // do nothing
+ *ppv = NULL;
+ return S_OK;
+}
+
+
+STDMETHODIMP_(void) CDdeServerCallMgr::DebugServerRelease
+ (void * pv)
+{
+ // do nothing
+}
+
+STDMETHODIMP CDdeServerCallMgr::Invoke
+ (RPCOLEMESSAGE *_prpcmsg, IRpcChannelBuffer *_pRpcChannelBuffer)
+{
+ DISPATCHDATA *pdispdata = (PDISPATCHDATA) _prpcmsg->Buffer;
+ return DispatchCall( pdispdata );
+}
+
+
+// Provided IRpcChannelBuffer methods (for callback methods side)
+STDMETHODIMP CDdeServerCallMgr::GetBuffer(
+/* [in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+/* [in] */ REFIID riid)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CDdeServerCallMgr::SendReceive(
+/* [out][in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+/* [out] */ ULONG __RPC_FAR *pStatus)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CDdeServerCallMgr::FreeBuffer(
+/* [in] */ RPCOLEMESSAGE __RPC_FAR *pMessage)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CDdeServerCallMgr::GetDestCtx(
+/* [out] */ DWORD __RPC_FAR *pdwDestContext,
+/* [out] */ void __RPC_FAR *__RPC_FAR *ppvDestContext)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CDdeServerCallMgr::IsConnected( void)
+{
+ return S_OK;
+}
+
+STDMETHODIMP CDdeServerCallMgr::SendReceive2(
+/* [out][in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+/* [out] */ ULONG __RPC_FAR *pStatus)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CDdeServerCallMgr::SendReceive2(pMessage=%x,pStatus=%x)\n",
+ this,
+ pMessage,
+ pStatus));
+
+ DDECALLDATA *pCD = ((DDECALLDATA *) pMessage->Buffer);
+
+ if(!PostMessageToClient(pCD->hwndSvr,
+ pCD->wMsg,
+ pCD->wParam,
+ pCD->lParam))
+ {
+ intrDebugOut((DEB_ITRACE, "SendRecieve2(%x)PostMessageToClient failed", this));
+ return RPC_E_SERVER_DIED;
+ }
+
+
+ CAptCallCtrl *pCallCtrl = GetAptCallCtrl();
+
+ CCliModalLoop *pCML = pCallCtrl->GetTopCML();
+
+ HRESULT hres = S_OK;
+ BOOL fWait = !(m_pDefClient->m_CallState == SERVERCALLEX_ISHANDLED);
+
+ while (fWait)
+ {
+ HRESULT hr = OleModalLoopBlockFn(NULL, pCML, NULL);
+
+ if (m_pDefClient->m_CallState == SERVERCALLEX_ISHANDLED)
+ {
+ fWait = FALSE;
+ }
+ else if (hr != RPC_S_CALLPENDING)
+ {
+ fWait = FALSE;
+ hres = hr; // return result from OleModalLoopBlockFn()
+ }
+ }
+
+ if (FAILED(hres))
+ {
+ intrDebugOut((DEB_ITRACE, "**** CDdeServerCallMgr::SendReceive2 OleModalLoopBlockFn returned %x ***\n", hres));
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT CDdeServerCallMgr::SendReceive2(pMessage=%x,pStatus=%x)\n",
+ this,
+ pMessage,
+ pStatus));
+
+ return hres;
+}
diff --git a/private/ole32/com/dde/server/srvr.h b/private/ole32/com/dde/server/srvr.h
new file mode 100644
index 000000000..f2e410f33
--- /dev/null
+++ b/private/ole32/com/dde/server/srvr.h
@@ -0,0 +1,656 @@
+/****************************** Module Header ******************************\
+* Module Name: srvr.h
+*
+* PURPOSE: Private definitions file for server code
+*
+* Created: 1990
+*
+* Copyright (c) 1990, 1991 Microsoft Corporation
+*
+* History:
+* Raor (../../90,91) Original
+*
+\***************************************************************************/
+//
+// One of the oleint.h routines redefines GlobalAlloc and friends
+// to perform some memory tracking functions.
+//
+// This doesn't work in these files, since the tracking functions
+// add tail checking, and size to the data structures. GlobalSize
+// is a common function to use to determine how much data to
+// serialize, plus it turns out that the other side of a DDE
+// connection will often be the caller to free the memory.
+//
+// Therefore, OLE_DDE_NO_GLOBAL_TRACKING is used to disable this in the
+// global header file ih\memapi.hxx. Check to insure this
+// flag is set on the compile line
+//
+#if !defined(OLE_DDE_NO_GLOBAL_TRACKING)
+error OLE_DDE_OLE_DDE_NO_GLOBAL_TRACKING must be defined to build this directory
+#endif
+
+#include <dde.h>
+#include <ddeerr.h>
+#include "ddeatoms.h"
+#include "ddepack.h"
+#include <callctrl.hxx>
+#include <ddeint.h>
+#include <ddechc.hxx>
+#include <longname.h>
+
+//#define UPDATE
+/*
+ if UPDATE is defined it means:
+ If a 1.0 client advises on save, also do a data advise.
+ This way the client will always
+ have an up-to-date picture (and native data) with respect to a
+ 2.0 server, like 2.0 clients do.
+ If a 1.0 client is prepared to accept data at save time
+ it should be able to handle data on each change: it is exactly
+ as if the user chose File.Update after each change.
+ In fact the item atom is appended with /Save, (see SendDataMsg1)
+ which is sort of a lie, but is what a 1.0 client expects for an
+ embedded object.
+ This is a UI issue.
+*/
+
+#define DEFSTD_ITEM_INDEX 0
+#define STDTARGETDEVICE 1
+#define STDDOCDIMENSIONS 2
+#define STDCOLORSCHEME 3
+#define STDHOSTNAMES 4
+
+
+#define PROTOCOL_EDIT (OLESTR("StdFileEditing"))
+#define PROTOCOL_EXECUTE (OLESTR("StdExecute"))
+
+#define ISATOM(a) ((a >= 0xC000) && (a <= 0xFFFF))
+
+// same limit as in OLE 1.0
+#define MAX_STR 124
+
+#define WW_LPTR 0 // ptr tosrvr/doc/item
+#define WW_HANDLE 4 // instance handle
+#define WW_LE 8 // signature
+
+
+#define WC_LE 0x4c45 // LE chars
+
+
+// Signatures for validity checking
+typedef enum
+{
+ chkDdeSrvr = 0x1234,
+ chkDefClient = 0x5678
+} CHK;
+
+
+const DWORD grfCreateStg = STGM_READWRITE | STGM_SHARE_EXCLUSIVE
+ | STGM_DIRECT | STGM_CREATE ;
+
+
+// If we running under WLO, the HIGHWORD of version number will be >= 0x0A00
+#define VER_WLO 0x0A00
+
+extern "C" WORD CheckPointer (LPVOID, int);
+
+#define READ_ACCESS 0
+#define WRITE_ACCESS 1
+
+#define PROBE_READ(lp){\
+ if (!CheckPointer(lp, READ_ACCESS))\
+ return ReportResult(0, E_INVALIDARG, 0, 0); \
+}
+
+#define PROBE_WRITE(lp){\
+ if (!CheckPointer(lp, WRITE_ACCESS))\
+ return ReportResult(0, E_INVALIDARG, 0, 0); \
+}
+
+#define OLE_COMMAND 1
+#define NON_OLE_COMMAND 2
+
+
+#define WT_SRVR 0 // server window
+#define WT_DOC 1 // document window
+
+#define PROBE_BLOCK(lpsrvr) { \
+ if (lpsrvr->bBlock) \
+ return ReportResult(0, S_SERVER_BLOCKED, 0, 0); \
+}
+
+
+#define SET_MSG_STATUS(retval, status) { \
+ if (!FAILED (GetScode (retval))) \
+ status |= 0x8000; \
+ if (GetScode(retval) == RPC_E_SERVERCALL_RETRYLATER)\
+ status |= 0x4000; \
+}
+
+
+/* Codes for CallBack events */
+typedef enum {
+ OLE_CHANGED, /* 0 */
+ OLE_SAVED, /* 1 */
+ OLE_CLOSED, /* 2 */
+ OLE_RENAMED, /* 3 */
+} OLE_NOTIFICATION;
+
+typedef enum { cnvtypNone, cnvtypConvertTo, cnvtypTreatAs } CNVTYP;
+
+typedef struct _QUE : public CPrivAlloc { // nodes in Block/Unblock queue
+ HWND hwnd; //***
+ UINT msg; // window
+ WPARAM wParam; // procedure parameters
+ LPARAM lParam; //***
+ HANDLE hqNext; // handle to next node
+} QUE;
+
+typedef QUE NEAR * PQUE;
+typedef QUE FAR * LPQUE;
+
+// structure for maintaining the client info.
+#define LIST_SIZE 10
+typedef struct _CLILIST : public CPrivAlloc {
+ HANDLE hcliNext;
+ HANDLE info[LIST_SIZE * 2];
+}CLILIST;
+
+typedef CLILIST FAR *LPCLILIST;
+typedef CLILIST *PCLILIST;
+
+
+// this is an object to be embedded in both CDefClient and CDDEServer to glue
+// to the new(est) call control interface
+class CDdeServerCallMgr : public IRpcStubBuffer, public IRpcChannelBuffer2 {
+
+ private:
+ CDefClient * m_pDefClient; // our embeddor (either a CDefClient or a CDDEServer)
+ CDDEServer * m_pDDEServer; // one of these is NULL;
+
+ public:
+ CDdeServerCallMgr (CDefClient * pDefClient)
+ { m_pDefClient = pDefClient;
+ m_pDDEServer = NULL;}
+
+ CDdeServerCallMgr (CDDEServer * pDefClient)
+ { m_pDefClient = NULL;
+ m_pDDEServer = pDefClient;}
+
+ STDMETHOD(QueryInterface) ( REFIID iid, LPVOID * ppvObj);
+ STDMETHOD_(ULONG,AddRef) ();
+ STDMETHOD_(ULONG,Release) ();
+
+ // IRpcStubBuffer methods
+ STDMETHOD(Connect)(
+ /* [in] */ IUnknown *pUnkServer);
+
+ STDMETHOD_(void,Disconnect)( void);
+
+ STDMETHOD(Invoke)(
+ /* [in] */ RPCOLEMESSAGE *_prpcmsg,
+ /* [in] */ IRpcChannelBuffer *_pRpcChannelBuffer);
+
+ STDMETHOD_(IRpcStubBuffer *,IsIIDSupported)(
+ /* [in] */ REFIID riid);
+
+ STDMETHOD_(ULONG,CountRefs)( void);
+
+ STDMETHOD(DebugServerQueryInterface)(
+ void * *ppv);
+
+ STDMETHOD_(void,DebugServerRelease)(
+ void *pv);
+
+
+
+ // IRpcChannelBuffer methods
+ STDMETHOD(GetBuffer) (
+ /* [in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+ /* [in] */ REFIID riid);
+
+ STDMETHOD(SendReceive) (
+ /* [out][in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+ /* [out] */ ULONG __RPC_FAR *pStatus);
+
+ STDMETHOD(FreeBuffer) (
+ /* [in] */ RPCOLEMESSAGE __RPC_FAR *pMessage);
+
+ STDMETHOD(GetDestCtx) (
+ /* [out] */ DWORD __RPC_FAR *pdwDestContext,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvDestContext);
+
+ STDMETHOD(IsConnected) ( void);
+
+ STDMETHOD(SendReceive2) (
+ /* [out][in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+ /* [out] */ ULONG __RPC_FAR *pStatus);
+};
+
+
+class FAR CDDEServer
+{
+ public:
+ static HRESULT Create (LPOLESTR lpclass,
+ REFCLSID rclsid,
+ LPDDECLASSINFO lpDdeInfo,
+ HWND FAR * phwnd,
+ ATOM aOriginalClass,
+ CNVTYP cnvtyp);
+
+ INTERNAL_(BOOL) HandleInitMsg (LPARAM);
+ INTERNAL SrvrExecute (HWND, HANDLE, HWND);
+ INTERNAL Revoke (void);
+ INTERNAL_(BOOL) QueryRevokeClassFactory (void);
+ INTERNAL_(LPCLIENT) FindDocObj (LPSTR lpDoc);
+ INTERNAL_(void) Lock (BOOL fLock, HWND hwndClient);
+
+
+ CLSID m_clsid; // Class ID
+ DWORD m_dwClassFactoryKey; // Class factory reg key
+ LPCLASSFACTORY m_pClassFactory; // class factory
+ CDdeServerCallMgr m_pCallMgr; // call management interfaces
+ BOOL m_bTerminate; // Set if we are terminating.
+ HWND m_hwnd; // corresponding window
+ HANDLE m_hcli; // handle to the first block of clients list
+ int m_termNo; // termination count
+ int m_cSrvrClients; // no of clients;
+ DWORD m_fcfFlags; // Class factory instance usage flags
+ CNVTYP m_cnvtyp;
+ CHK m_chk;
+
+ ATOM m_aClass; // class atom
+ ATOM m_aOriginalClass; // for TreatAs/ConvertTo case
+ ATOM m_aExe;
+
+ BOOL m_fDoNotDestroyWindow; // When set, server wnd ingores WM_USER
+
+ private:
+ INTERNAL_(void) SendServerTerminateMsg (void);
+ INTERNAL RevokeAllDocObjs (void);
+ INTERNAL FreeSrvrMem (void);
+ INTERNAL CreateInstance (REFCLSID clsid, LPOLESTR lpWidedocName, LPSTR lpdocName,
+ LPUNKNOWN pUnk, LPCLIENT FAR* lplpdocClient,
+ HWND hwndClient);
+
+public:
+ //ctor
+ CDDEServer()
+ : m_pCallMgr( this )
+ {
+ }
+
+
+};
+
+
+
+
+BOOL SendInitMsgToChildren (HWND, UINT msg, WPARAM wParam, LPARAM lParam);
+
+INTERNAL RequestDataStd (ATOM, HANDLE FAR *);
+INTERNAL_(BOOL) ValidateSrvrClass (LPOLESTR, ATOM FAR *);
+INTERNAL_(ATOM) GetExeAtom (LPOLESTR);
+INTERNAL_(BOOL) AddClient (LPHANDLE, HANDLE, HANDLE);
+INTERNAL_(HANDLE) FindClient (HANDLE hCli, HANDLE hkey, BOOL fDelete);
+
+INTERNAL_(BOOL) IsSingleServerInstance (void);
+
+INTERNAL_(void) UtilMemCpy (LPSTR, LPSTR, DWORD);
+INTERNAL_(HANDLE) DuplicateData (HANDLE);
+INTERNAL_(LPSTR) ScanBoolArg (LPSTR, BOOL FAR *);
+INTERNAL_(LPSTR) ScanNumArg (LPSTR, LPINT);
+INTERNAL_(LPSTR) ScanArg(LPSTR);
+INTERNAL_(ATOM) MakeDataAtom (ATOM, int);
+INTERNAL_(ATOM) DuplicateAtom (ATOM);
+INTERNAL_(BOOL) CLSIDFromAtom(ATOM aClass, LPCLSID lpclsid);
+INTERNAL CLSIDFromAtomWithTreatAs (ATOM FAR* paClass, LPCLSID lpclsid,
+ CNVTYP FAR* pcnvtyp);
+INTERNAL wFileIsRunning (LPOLESTR szFile);
+INTERNAL wFileBind (LPOLESTR szFile, LPUNKNOWN FAR* ppUnk);
+INTERNAL wCreateStgAroundNative (HANDLE hNative,
+ ATOM aClassOld,
+ ATOM aClassNew,
+ CNVTYP cnvtyp,
+ ATOM aItem,
+ LPSTORAGE FAR* ppstg,
+ LPLOCKBYTES FAR* pplkbyt);
+INTERNAL wCompatibleClasses (ATOM aClient, ATOM aSrvr);
+
+
+
+
+typedef struct FARSTRUCT : public CPrivAlloc {
+ BOOL f; // do we need to send an ack?
+ // If this is FALSE, other fields don't matter
+ HGLOBAL hdata;
+ HWND hwndFrom; // who sent the execute?
+ HWND hwndTo;
+} EXECUTEACK;
+
+
+// client struct definitions.
+
+
+
+class FAR CDefClient : public CPrivAlloc
+{
+ public:
+ static INTERNAL Create
+ (LPSRVR pDdeSrvr,
+ LPUNKNOWN lpunkObj,
+ LPOLESTR lpdocName,
+ const BOOL fSetClientSite,
+ const BOOL fDoAdvise,
+ const BOOL fRunningInSDI = FALSE,
+ HWND FAR* phwnd = NULL);
+
+ INTERNAL DocExecute (HANDLE);
+ INTERNAL DocDoVerbItem (LPSTR, WORD, BOOL, BOOL);
+ INTERNAL DocShowItem (LPSTR, BOOL);
+ INTERNAL DestroyInstance ();
+ INTERNAL_(void) DeleteFromItemsList (HWND h);
+ INTERNAL_(void) RemoveItemFromItemList (void);
+ INTERNAL_(void) ReleasePseudoItems (void);
+ INTERNAL_(void) ReleaseAllItems ();
+ INTERNAL PokeStdItems (HWND, ATOM, HANDLE,int);
+ INTERNAL PokeData (HWND, ATOM, HANDLE);
+ INTERNAL AdviseData (HWND, ATOM, HANDLE, BOOL FAR *);
+ INTERNAL AdviseStdItems (HWND, ATOM, HANDLE, BOOL FAR *);
+ INTERNAL UnAdviseData (HWND, ATOM);
+ INTERNAL RequestData (HWND, ATOM, USHORT, HANDLE FAR *);
+ INTERNAL Revoke (BOOL fRelease=TRUE);
+ INTERNAL ReleaseObjPtrs (void);
+ INTERNAL_(void) DeleteAdviseInfo ();
+ INTERNAL DoOle20Advise (OLE_NOTIFICATION, CLIPFORMAT);
+ INTERNAL DoOle20UnAdviseAll (void);
+ INTERNAL SetClientSite (void);
+ INTERNAL NoItemConnections (void);
+ INTERNAL_(void) SendExecuteAck (HRESULT hresult);
+ INTERNAL DoInitNew(void);
+ INTERNAL Terminate(HWND, HWND);
+ INTERNAL_(void) SetCallState (SERVERCALLEX State)
+ {
+ m_CallState = State;
+ }
+
+ CHK m_chk; // signature
+ CDdeServerCallMgr m_pCallMgr; // call management interfaces
+ SERVERCALLEX m_CallState;
+
+ IUnknown FAR* m_pUnkOuter;
+ LPOLEOBJECT m_lpoleObj; // corresponding oleobj
+ LPDATAOBJECT m_lpdataObj; // corresponding dataobj
+ BOOL m_bCreateInst; // instance is just created.
+ BOOL m_bTerminate; // REVIEW: The next two fields may not be necessary.
+ int m_termNo;
+ ATOM m_aItem; // item atom or index for some std items
+ HANDLE m_hcli; // handle to the first block of clients list (Document only)
+ CDefClient FAR *m_lpNextItem; // ptr to the next item.
+ BOOL m_bContainer; // Is document?
+ BOOL m_cRef;
+ HWND m_hwnd; // doc window (only needed in document)
+ HANDLE m_hdevInfo; // latest printer dev info sent
+ HANDLE m_hcliInfo; // advise info for each of the clients
+ BOOL m_fDidRealSetHostNames;
+ BOOL m_fDidSetClientSite;
+ BOOL m_fGotDdeAdvise;
+ BOOL m_fCreatedNotConnected;
+ BOOL m_fInOnClose;
+ BOOL m_fInOleSave;
+ EXECUTEACK m_ExecuteAck;
+ DWORD m_dwConnectionOleObj;
+ DWORD m_dwConnectionDataObj;
+ LPLOCKBYTES m_plkbytNative; // These two fields always refer to
+ LPSTORAGE m_pstgNative; // to the same bits:
+ // The server's persistent storage is
+ // used as its native data.
+ BOOL m_fRunningInSDI;// Link case: file was already open in
+ // an SDI app which does not register a
+ // class factory.
+ LPSRVR m_psrvrParent; // (Document only)
+ DVTARGETDEVICE FAR* m_ptd;
+ BOOL m_fGotStdCloseDoc;
+ BOOL m_fGotEditNoPokeNativeYet;
+ BOOL m_fLocked; // locked by CoLockObjectExternal ?
+
+ // If not FALSE, then we are waiting for a matching TERMINATE
+
+ BOOL m_fCallData;
+
+
+
+
+
+ // REVIEW: These fields might be necssary for doc (old) level object
+ BOOL m_fEmbed; // embedded object (Document only)
+ int m_cClients; // (Document only)
+ LPCLIENT m_pdoc; // containing document (for items) or self (for docs)
+
+
+implementations:
+
+ STDUNKDECL (CDefClient,DefClient);
+
+ /*** IOleClientSite ***/
+ implement COleClientSiteImpl : IOleClientSite
+ {
+ public:
+ // Constructor
+ COleClientSiteImpl (CDefClient FAR* pDefClient)
+ { m_pDefClient = pDefClient;
+ }
+ STDMETHOD(QueryInterface) (REFIID, LPVOID FAR *);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ /*** IOleClientSite methods ***/
+ STDMETHOD(SaveObject) (THIS);
+ STDMETHOD(GetMoniker) (THIS_ DWORD dwAssign, DWORD dwWhichMoniker,
+ LPMONIKER FAR* ppmk);
+ STDMETHOD(GetContainer) (THIS_ LPOLECONTAINER FAR* ppContainer);
+ STDMETHOD(ShowObject) (THIS);
+ STDMETHOD(OnShowWindow) (THIS_ BOOL fShow);
+ STDMETHOD(RequestNewObjectLayout) (THIS);
+
+ private:
+ CDefClient FAR* m_pDefClient;
+ };
+
+ DECLARE_NC (CDefClient, COleClientSiteImpl)
+ COleClientSiteImpl m_OleClientSite;
+
+
+
+ /*** IAdviseSink ***/
+ implement CAdviseSinkImpl : IAdviseSink
+ {
+ public:
+ // Constructor
+ CAdviseSinkImpl (CDefClient FAR* pDefClient)
+ { m_pDefClient = pDefClient;
+ }
+
+ STDMETHOD(QueryInterface) (REFIID, LPVOID FAR *);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ /**** IAdviseSink methods ****/
+ STDMETHOD_(void,OnDataChange)(THIS_ FORMATETC FAR* pFormatetc,
+ STGMEDIUM FAR* pStgmed) ;
+ STDMETHOD_(void,OnViewChange)(THIS_ DWORD aspects, LONG lindex) ;
+ STDMETHOD_(void,OnExtentChange)(DWORD dwAspect, LPSIZEL lpsizel) {}
+ STDMETHOD_(void,OnRename)(THIS_ LPMONIKER pmk) ;
+ STDMETHOD_(void,OnSave)(THIS) ;
+ STDMETHOD_(void,OnClose)(THIS) ;
+
+ private:
+ CDefClient FAR* m_pDefClient;
+ };
+
+
+ DECLARE_NC (CDefClient, CAdviseSinkImpl)
+
+ CAdviseSinkImpl m_AdviseSink;
+ctor_dtor:
+ CDefClient (LPUNKNOWN pUnkOuter);
+ ~CDefClient (void);
+
+private:
+ INTERNAL ItemCallBack (int msg, LPOLESTR szNewName = NULL);
+ INTERNAL_(void) SendTerminateMsg ();
+ INTERNAL_(BOOL) SendDataMsg1 (HANDLE, WORD);
+ INTERNAL_(BOOL) SendDataMsg (WORD);
+ INTERNAL_(void) TerminateNonRenameClients (LPCLIENT);
+ INTERNAL_(void) SendRenameMsgs (HANDLE);
+ INTERNAL RegisterItem (LPOLESTR, LPCLIENT FAR *, BOOL);
+ INTERNAL FindItem (LPOLESTR, LPCLIENT FAR *);
+ INTERNAL_(LPCLIENT) SearchItem (LPOLESTR);
+ INTERNAL_(void) DeleteAllItems ();
+ INTERNAL SetStdInfo (HWND, LPOLESTR, HANDLE);
+ INTERNAL_(void) SendDevInfo (HWND);
+ INTERNAL_(BOOL) IsFormatAvailable (CLIPFORMAT);
+ INTERNAL GetData (LPFORMATETC, LPSTGMEDIUM);
+};
+
+
+
+
+typedef struct _CLINFO : public CPrivAlloc { /*clInfo*/ // client transaction info
+ HWND hwnd; // client window handle
+ BOOL bnative; // doe sthis client require native
+ int format; // dusplay format
+ int options; // transaction advise time otipns
+ BOOL bdata; // need wdat with advise?
+ HANDLE hdevInfo; // device info handle
+ BOOL bnewDevInfo; // new device info
+} CLINFO;
+
+typedef CLINFO *PCLINFO;
+
+
+
+INTERNAL_(BOOL) MakeDDEData (HANDLE, int, LPHANDLE, BOOL);
+INTERNAL_(HANDLE) MakeGlobal (LPSTR);
+INTERNAL ScanItemOptions (LPOLESTR, int far *);
+INTERNAL_(int) GetStdItemIndex (ATOM);
+INTERNAL_(BOOL) IsAdviseStdItems (ATOM);
+INTERNAL_(HANDLE) MakeItemData (DDEPOKE FAR *, HANDLE, CLIPFORMAT);
+INTERNAL_(BOOL) AddMessage (HWND, unsigned, WORD, LONG, int);
+
+
+
+#define ITEM_FIND 1 // find the item
+#define ITEM_DELETECLIENT 2 // delete the client from item clients
+#define ITEM_DELETE 3 // delete th item window itself
+#define ITEM_SAVED 4 // item saved
+
+// host names data structcure
+typedef struct _HOSTNAMES : public CPrivAlloc {
+ WORD clientNameOffset;
+ WORD documentNameOffset;
+ BYTE data[1];
+} HOSTNAMES;
+
+typedef HOSTNAMES FAR * LPHOSTNAMES;
+
+
+// routines in UTILS.C
+LPOLESTR CreateUnicodeFromAnsi( LPCSTR lpAnsi);
+LPSTR CreateAnsiFromUnicode( LPCOLESTR lpAnsi);
+INTERNAL_(HANDLE) DuplicateData (HANDLE);
+INTERNAL_(LPSTR) ScanLastBoolArg (LPSTR);
+INTERNAL_(LPSTR) ScanArg(LPSTR);
+INTERNAL_(WORD) ScanCommand(LPSTR, WORD, LPSTR FAR *, ATOM FAR *);
+INTERNAL_(ATOM) MakeDataAtom (ATOM, int);
+INTERNAL_(ATOM) DuplicateAtom (ATOM);
+INTERNAL_(WORD) StrToInt (LPOLESTR);
+INTERNAL_(BOOL) PostMessageToClientWithReply (HWND, UINT, WPARAM, LPARAM, UINT);
+INTERNAL_(BOOL) PostMessageToClient (HWND, UINT, WPARAM, LPARAM);
+INTERNAL_(BOOL) IsWindowValid (HWND);
+INTERNAL_(BOOL) IsOleCommand (ATOM, WORD);
+INTERNAL_(BOOL) UtilQueryProtocol (ATOM, LPOLESTR);
+INTERNAL SynchronousPostMessage (HWND, UINT, WPARAM, LPARAM);
+INTERNAL_(BOOL) IsAtom (ATOM);
+INTERNAL_(BOOL) IsFile (ATOM a, BOOL FAR* pfUnsavedDoc = NULL);
+
+
+// routines for queueing messages and posting them
+INTERNAL_(BOOL) UnblockPostMsgs(HWND, BOOL);
+INTERNAL_(BOOL) BlockPostMsg (HWND, WORD, WORD, LONG);
+INTERNAL_(BOOL) IsBlockQueueEmpty (HWND);
+
+// routine in GIVE2GDI.ASM
+extern "C" HANDLE FAR PASCAL GiveToGDI (HANDLE);
+
+
+// routine in item.c
+INTERNAL_(HBITMAP) DuplicateBitmap (HBITMAP);
+INTERNAL_(HANDLE) DuplicateMetaFile (HANDLE);
+INTERNAL_(BOOL) AreNoClients (HANDLE hcli);
+#ifdef _DEBUG
+INTERNAL_(LPOLESTR) a2s (ATOM);
+#endif
+
+// routines in doc.c
+INTERNAL_(void) FreePokeData (HANDLE);
+INTERNAL_(BOOL) FreeGDIdata (HANDLE, CLIPFORMAT);
+INTERNAL DdeHandleIncomingCall(HWND hwndCli, WORD wCallType);
+
+
+// in ddeworkr.cpp
+INTERNAL_(HANDLE) wNewHandle (LPSTR lpstr, DWORD cb);
+INTERNAL wTimedGetMessage (LPMSG pmsg, HWND hwnd, WORD wFirst, WORD wLast);
+INTERNAL_(ATOM) wGlobalAddAtom (LPCOLESTR sz);
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSSetDdeServer
+//
+// Synopsis: Sets hwnd to CommonDdeServer window
+//
+// Arguments: [hwndDdeServer] --
+//
+// History: 5-13-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+inline BOOL TLSSetDdeServer(HWND hwndDdeServer)
+{
+ HRESULT hr;
+ COleTls tls(hr);
+
+ if (SUCCEEDED(hr))
+ {
+ tls->hwndDdeServer = hwndDdeServer;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSGetDdeServer
+//
+// Synopsis: Returns a handle to the per thread DdeServer window
+//
+// Returns: hwndDdeServer for thread
+//
+// History: 5-13-94 kevinro Created
+//
+// Notes:
+//----------------------------------------------------------------------------
+inline HWND TLSGetDdeServer()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+
+ if (SUCCEEDED(hr))
+ {
+ return tls->hwndDdeServer;
+ }
+
+ return NULL;
+}
diff --git a/private/ole32/com/dde/server/srvrmain.cxx b/private/ole32/com/dde/server/srvrmain.cxx
new file mode 100644
index 000000000..67a13dcc7
--- /dev/null
+++ b/private/ole32/com/dde/server/srvrmain.cxx
@@ -0,0 +1,253 @@
+/****************************** Module Header ******************************\
+* Module Name: Srvrmain.c Server Main module
+*
+* Purpose: Includes server intialization and termination code.
+*
+* Created: Oct 1990.
+*
+* Copyright (c) 1990, 1991 Microsoft Corporation
+*
+* History:
+* Raor (../10/1990) Designed, coded
+* Raor (03/../1992) Modified for OLE 2.0
+*
+\***************************************************************************/
+
+#include "ole2int.h"
+#include <dde.h>
+// #include "cmacs.h"
+#include "srvr.h"
+#include "ddeatoms.h"
+#include "ddedebug.h"
+ASSERTDATA
+
+ATOM aStdExit = NULL; // "StdExit"
+ATOM aStdCreate = NULL; // "StdNewDicument"
+ATOM aStdOpen = NULL; // "StdOpenDocument"
+ATOM aStdEdit = NULL; // "StdOpenDocument"
+ATOM aStdCreateFromTemplate = NULL;// "StdNewFromTemplate"
+ATOM aStdClose = NULL; // "StdCloseDocument"
+ATOM aStdShowItem = NULL; // "StdShowItem"
+ATOM aStdDoVerbItem = NULL; // "StddoVerbItem"
+ATOM aSysTopic = NULL; // "System"
+ATOM aOLE = NULL; // "OLE"
+ATOM aProtocols = NULL; // "Protocols"
+ATOM aTopics = NULL; // "Topics"
+ATOM aFormats = NULL; // "Formats"
+ATOM aStatus = NULL; // "Status"
+ATOM aEditItems = NULL; // "Edit items
+ATOM aTrue = NULL; // "True"
+ATOM aFalse = NULL; // "False"
+
+
+ATOM aStdHostNames;
+ATOM aStdTargetDevice ;
+ATOM aStdDocDimensions;
+ATOM aStdColorScheme;
+ATOM aChange;
+ATOM aSave;
+ATOM aClose;
+ATOM aStdDocName;
+ATOM aMSDraw;
+
+
+INTERNAL_(BOOL) DDELibMain (
+ HANDLE hInst,
+ WORD wDataSeg,
+ WORD cbHeapSize,
+ LPOLESTR lpszCmdLine
+)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN DDELibMain hInst=%x\n",
+ 0,
+ hInst));
+
+ if( !aStdExit )
+ {
+#ifndef _CHICAGO_
+ // On NT3.51, user preregisters all of these formats for us,
+ // thus giving us a big speed improvement during startup (because
+ // these atoms never change).
+ // Chicago and Cairo do not yet have this functionality.
+
+ aStdExit = GlobalFindAtom(OLESTR("StdExit"));
+
+ aStdCreate = aStdExit + 1;
+ Assert(aStdCreate == GlobalFindAtom (OLESTR("StdNewDocument")));
+
+ aStdOpen = aStdExit + 2;
+ Assert(aStdOpen == GlobalFindAtom (OLESTR("StdOpenDocument")));
+
+ aStdEdit = aStdExit + 3;
+ Assert(aStdEdit == GlobalFindAtom (OLESTR("StdEditDocument")));
+
+ aStdCreateFromTemplate = aStdExit + 4;
+ Assert(aStdCreateFromTemplate ==
+ GlobalFindAtom(OLESTR("StdNewfromTemplate")));
+
+ aStdClose = aStdExit + 5;
+ Assert(aStdClose == GlobalFindAtom (OLESTR("StdCloseDocument")));
+
+ aStdShowItem = aStdExit + 6;
+ Assert(aStdShowItem == GlobalFindAtom (OLESTR("StdShowItem")));
+
+ aStdDoVerbItem = aStdExit + 7;
+ Assert(aStdDoVerbItem == GlobalFindAtom (OLESTR("StdDoVerbItem")));
+
+ aSysTopic = aStdExit + 8;
+ Assert(aSysTopic == GlobalFindAtom (OLESTR("System")));
+
+ aOLE = aStdExit + 9;
+ Assert(aOLE == GlobalFindAtom (OLESTR("OLEsystem")));
+
+ aStdDocName = aStdExit + 10;
+ Assert(aStdDocName == GlobalFindAtom (OLESTR("StdDocumentName")));
+
+ aProtocols = aStdExit + 11;
+ Assert(aProtocols == GlobalFindAtom (OLESTR("Protocols")));
+
+ aTopics = aStdExit + 12;
+ Assert(aTopics == GlobalFindAtom (OLESTR("Topics")));
+
+ aFormats = aStdExit + 13;
+ Assert(aFormats == GlobalFindAtom (OLESTR("Formats")));
+
+ aStatus = aStdExit + 14;
+ Assert(aStatus == GlobalFindAtom (OLESTR("Status")));
+
+ aEditItems = aStdExit + 15;
+ Assert(aEditItems == GlobalFindAtom (OLESTR("EditEnvItems")));
+
+ aTrue = aStdExit + 16;
+ Assert(aTrue == GlobalFindAtom (OLESTR("True")));
+
+ aFalse = aStdExit + 17;
+ Assert(aFalse == GlobalFindAtom (OLESTR("False")));
+
+ aChange = aStdExit + 18;
+ Assert(aChange == GlobalFindAtom (OLESTR("Change")));
+
+ aSave = aStdExit + 19;
+ Assert(aSave == GlobalFindAtom (OLESTR("Save")));
+
+ aClose = aStdExit + 20;
+ Assert(aClose == GlobalFindAtom (OLESTR("Close")));
+
+ aMSDraw = aStdExit + 21;
+ Assert(aMSDraw == GlobalFindAtom (OLESTR("MSDraw")));
+
+ }
+#else // _CHICAGO_
+
+ aStdExit = GlobalAddAtomA("StdExit");
+
+ aStdCreate = GlobalAddAtomA("StdNewDocument");
+ aStdOpen = GlobalAddAtomA("StdOpenDocument");
+ aStdEdit = GlobalAddAtomA("StdEditDocument");
+ aStdCreateFromTemplate = GlobalAddAtomA("StdNewfromTemplate");
+
+ aStdClose = GlobalAddAtomA("StdCloseDocument");
+ aStdShowItem = GlobalAddAtomA("StdShowItem");
+ aStdDoVerbItem = GlobalAddAtomA("StdDoVerbItem");
+ aSysTopic = GlobalAddAtomA("System");
+ aOLE = GlobalAddAtomA("OLEsystem");
+ aStdDocName = GlobalAddAtomA("StdDocumentName");
+
+ aProtocols = GlobalAddAtomA("Protocols");
+ aTopics = GlobalAddAtomA("Topics");
+ aFormats = GlobalAddAtomA("Formats");
+ aStatus = GlobalAddAtomA("Status");
+ aEditItems = GlobalAddAtomA("EditEnvItems");
+
+ aTrue = GlobalAddAtomA("True");
+ aFalse = GlobalAddAtomA("False");
+
+ aChange = GlobalAddAtomA("Change");
+ aSave = GlobalAddAtomA("Save");
+ aClose = GlobalAddAtomA("Close");
+ aMSDraw = GlobalAddAtomA("MSDraw");
+
+ }
+
+ if (IsWowThread())
+ {
+ wsprintfA(szOLE_CLASSA, "Ole2WndClass %08X", CoGetCurrentProcess());
+ }
+#endif // _CHICAGO_
+
+ return TRUE;
+}
+
+
+INTERNAL_(void) DDEWEP (
+ BOOL fSystemExit
+)
+{
+#if DBG==1
+ Puts("DdeWep\r\n");
+
+ if (fSystemExit != WEP_FREE_DLL)
+ {
+ AssertSz (0, "Bad parm to Wep");
+ return;
+ }
+#endif // DBG==1
+
+ // free the global atoms.
+
+ // on NT3.51, these atoms were pre-allocated for us by user, we do
+ // not need to free them.
+#ifdef _CHICAGO_
+
+ if (aStdExit)
+ GlobalDeleteAtom (aStdExit);
+ if (aStdCreate)
+ GlobalDeleteAtom (aStdCreate);
+ if (aStdOpen)
+ GlobalDeleteAtom (aStdOpen);
+ if (aStdEdit)
+ GlobalDeleteAtom (aStdEdit);
+ if (aStdCreateFromTemplate)
+ GlobalDeleteAtom (aStdCreateFromTemplate);
+ if (aStdClose)
+ GlobalDeleteAtom (aStdClose);
+ if (aStdShowItem)
+ GlobalDeleteAtom (aStdShowItem);
+ if (aStdDoVerbItem)
+ GlobalDeleteAtom (aStdDoVerbItem);
+ if (aSysTopic)
+ GlobalDeleteAtom (aSysTopic);
+ if (aOLE)
+ GlobalDeleteAtom (aOLE);
+ if (aStdDocName)
+ GlobalDeleteAtom (aStdDocName);
+
+ if (aProtocols)
+ GlobalDeleteAtom (aProtocols);
+ if (aTopics)
+ GlobalDeleteAtom (aTopics);
+ if (aFormats)
+ GlobalDeleteAtom (aFormats);
+ if (aStatus)
+ GlobalDeleteAtom (aStatus);
+ if (aEditItems)
+ GlobalDeleteAtom (aEditItems);
+
+ if (aTrue)
+ GlobalDeleteAtom (aTrue);
+ if (aFalse)
+ GlobalDeleteAtom (aFalse);
+
+ if (aChange)
+ GlobalDeleteAtom (aChange);
+ if (aSave)
+ GlobalDeleteAtom (aSave);
+ if (aClose)
+ GlobalDeleteAtom (aClose);
+
+ if (aMSDraw)
+ GlobalDeleteAtom (aMSDraw);
+
+#endif // _CHICAGO_
+}
diff --git a/private/ole32/com/debug/assert.cxx b/private/ole32/com/debug/assert.cxx
new file mode 100644
index 000000000..7105fdf79
--- /dev/null
+++ b/private/ole32/com/debug/assert.cxx
@@ -0,0 +1,97 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: assert.cxx
+//
+// Functions: FnAssert
+// DbgDllSetSiftObject
+//
+// History: 4-Jan-94 CraigWi Created
+// 16-Jun-94 t-ChriPi Added DbgDllSetSiftObject
+//
+//----------------------------------------------------------------------------
+
+
+
+#include <ole2int.h>
+
+//+-------------------------------------------------------------------
+//
+// Function: FnAssert, public
+//
+// Synopsis: Prints a message and optionally stops the program
+//
+// Effects: Simply maps to Win4AssertEx for now.
+//
+// History: 4-Jan-94 CraigWi Created for Win32 OLE2.
+//
+//--------------------------------------------------------------------
+
+STDAPI FnAssert( LPSTR lpstrExpr, LPSTR lpstrMsg, LPSTR lpstrFileName, UINT iLine )
+{
+#if DBG == 1
+ char szMessage[1024];
+
+ if (lpstrMsg == NULL)
+ lstrcpyA(szMessage, lpstrExpr);
+ else
+ wsprintfA(szMessage, "%s; %s", lpstrExpr, lpstrMsg);
+
+ Win4AssertEx(lpstrFileName, iLine, szMessage);
+#endif
+ return NOERROR;
+}
+
+#if DBG==1
+
+#include <osift.hxx>
+
+ISift *g_psftSiftObject = NULL;
+
+//+---------------------------------------------------------------------------
+//
+// Function: DbgDllSetSiftObject
+//
+// Arguments: [psftSiftImpl] -- pointer to a new sift implementation
+//
+// Synopsis: Sets global sift object pointer to a new implementation
+//
+// Returns: S_OK if successful
+//
+// History: 6-14-94 t-chripi Created
+//
+// Notes: Passing NULL to this function will release the global
+// pointer's reference and then set it to NULL.
+//
+//----------------------------------------------------------------------------
+
+STDAPI DbgDllSetSiftObject(ISift *psftSiftImpl)
+{
+ // Passing a non-NULL invalid pointer will cause an error
+ if ((NULL != psftSiftImpl) &&
+ (IsBadReadPtr(psftSiftImpl, sizeof(ISift*))))
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "DbgDllSetSiftObject was passed an invalid ptr.\n"));
+ return(E_FAIL);
+ }
+ else
+ {
+ if (NULL != g_psftSiftObject)
+ {
+ g_psftSiftObject->Release();
+ }
+ g_psftSiftObject = psftSiftImpl;
+
+ if (NULL != g_psftSiftObject)
+ {
+ g_psftSiftObject->AddRef();
+ }
+ }
+ return(S_OK);
+}
+
+#endif // DBG==1
+
diff --git a/private/ole32/com/debug/daytona/makefile b/private/ole32/com/debug/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/debug/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/debug/daytona/sources b/private/ole32/com/debug/daytona/sources
new file mode 100644
index 000000000..5ae687d39
--- /dev/null
+++ b/private/ole32/com/debug/daytona/sources
@@ -0,0 +1,65 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= debug
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..;..\..\..\common\daytona;..\..\..\ih;..\..\inc
+
+C_DEFINES= \
+ $(C_DEFINES)
+
+SOURCES= \
+ ..\assert.cxx \
+ ..\valid.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
diff --git a/private/ole32/com/debug/dirs b/private/ole32/com/debug/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/com/debug/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/com/debug/filelist.mk b/private/ole32/com/debug/filelist.mk
new file mode 100644
index 000000000..2fa6c1943
--- /dev/null
+++ b/private/ole32/com/debug/filelist.mk
@@ -0,0 +1,55 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = debug.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES = .\assert.cxx \
+ .\valid.cxx
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PXXFILE = .\headers.cxx
+PFILE =
+
+
+CINC = $(CINC) -I..\inc $(LRPC)
+
+
+MTHREAD = 1
+
+MULTIDEPEND = MERGED
diff --git a/private/ole32/com/debug/makefile b/private/ole32/com/debug/makefile
new file mode 100644
index 000000000..e09078703
--- /dev/null
+++ b/private/ole32/com/debug/makefile
@@ -0,0 +1,24 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+!include $(CAIROLE)\com\makefile
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/com/debug/valid.cxx b/private/ole32/com/debug/valid.cxx
new file mode 100644
index 000000000..0a3d137fd
--- /dev/null
+++ b/private/ole32/com/debug/valid.cxx
@@ -0,0 +1,102 @@
+#include <ole2int.h>
+
+#include "valid.h"
+
+#if 1
+// we cannot turn this off until we remove from the export list!
+#undef IsValidPtrIn
+#undef IsValidPtrOut
+
+// BUGBUG: The following two functions are MACRO's in 2.01 code
+// but we need them for now because we only run with a storage
+// that uses ole232.dll. When we get rid of this these may die.
+
+#pragma SEG(IsValidPtrIn)
+STDAPI_(BOOL) IsValidPtrIn( const void FAR* pv, UINT cb )
+{ // NULL is acceptable
+ if (pv && IsBadReadPtr(pv,cb))
+ {
+// AssertSz(FALSE, "Invalid in pointer");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+
+#pragma SEG(IsValidPtrOut)
+STDAPI_(BOOL) IsValidPtrOut( void FAR* pv, UINT cb )
+ // NULL is not acceptable
+{
+ if (IsBadWritePtr(pv,cb))
+ {
+// AssertSz(FALSE, "Invalid out pointer");
+ return FALSE;
+ }
+ return TRUE;
+}
+#endif
+
+
+#pragma SEG(IsValidInterface)
+STDAPI_(BOOL) IsValidInterface( void FAR* pv )
+{
+ DWORD FAR* pVtbl;
+ BYTE FAR* pFcn;
+ volatile BYTE bInstr;
+ int i;
+
+ __try {
+ pVtbl = *(DWORD FAR* FAR*)pv; // pVtbl now points to beginning of vtable
+
+#if DBG==1
+ for (i=0;i<3;++i) // loop through qi,addref,rel
+#else
+ i=1; // in retail, just do AddRef
+#endif
+ {
+ pFcn = *(BYTE FAR* FAR*) &pVtbl[i]; // pFcn now points to beginning of QI,Addref, or Release
+#if DBG==1
+ if (IsBadCodePtr((FARPROC FAR)pFcn)) {
+ return FALSE;
+ }
+#endif
+ bInstr = *(BYTE FAR*) pFcn; // get 1st byte of 1st instruction
+ }
+
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+// #if DBG==1
+// we cannot remove IsValidIID fcn until we remove from export list!
+
+// This function is NOT called in retail builds.
+// Its former implementation always returned TRUE thus doing NO validation.
+// It now validates in debug build and is not called in retail build
+
+#if DBG==0
+#ifdef IsValidIid
+#undef IsValidIid
+STDAPI_(BOOL) IsValidIid( REFIID iid );
+#endif
+#endif
+
+STDAPI_(BOOL) IsValidIid( REFIID iid )
+{
+#if DBG==1
+ if (IsBadReadPtr((void*) &iid, 16)) {
+ AssertSz(FALSE, "Invalid iid");
+ return FALSE;
+ }
+#endif
+ return TRUE;
+}
+// #endif // DBG==1
+
diff --git a/private/ole32/com/dirs b/private/ole32/com/dirs
new file mode 100644
index 000000000..3791c22c0
--- /dev/null
+++ b/private/ole32/com/dirs
@@ -0,0 +1,50 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS= \
+ idl \
+ dcomidl \
+ inc \
+ coll \
+ debug \
+ moniker2 \
+ util \
+ remote \
+ dcomrem \
+ dde \
+ objact \
+ rot \
+ class \
+ accctrl \
+ wx86grpa
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS=
diff --git a/private/ole32/com/idl/classf_c.sav b/private/ole32/com/idl/classf_c.sav
new file mode 100644
index 000000000..46d1e1a5b
--- /dev/null
+++ b/private/ole32/com/idl/classf_c.sav
@@ -0,0 +1,295 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: classf_c.cxx
+//
+// Contents: Interface proxy for IClassFactory
+//
+// Classes: CProxyIClassFactory
+//
+// History: Created by Microsoft (R) MIDL Compiler Version 1.10.82
+//
+//--------------------------------------------------------------------------
+#include "stdrpc.hxx"
+#pragma hdrstop
+#include "classf_x.h"
+
+
+#include "iface.h"
+extern "C" const GUID CLSID_RemoteHdlr;
+STDAPI CoCreateRemoteHandler(IUnknown *pUnkOuter, void **pUnk);
+
+
+HRESULT STDMETHODCALLTYPE CProxyIClassFactory::CreateInstance
+(
+
+ IUnknown *pUnkOuter,
+
+ REFIID riid,
+
+ void **ppvObject
+)
+{
+ RPCOLE_INTERFACE _RpcInterfaceInformation;
+ RPCOLE_MESSAGE _message;
+ RPCOLE_MESSAGE * _prpcmsg = &_message;
+ HRESULT _ret_value;
+
+ unsigned char *_tempbuf;
+ unsigned char *_savebuf;
+
+
+ memset((void *) &_message, 0, sizeof(_message));
+ //Initialize [out] parameters
+ memset((void *) ppvObject, 0, (sizeof(void *)));
+
+ //Calculate size of message buffer
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = S_OK;
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = _pRpcChannel->GetDestCtx(&_prpcmsg->_dwDestContext, &_prpcmsg->_pvDestContext);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ {
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+ _prpcmsg->BufferLength = 24;
+ _prpcmsg->BufferLength += 3;
+ _prpcmsg->BufferLength &= (unsigned int)0xfffffffc;
+ _prpcmsg->BufferLength += 4;
+
+ //Get RPC message
+ memset(&_RpcInterfaceInformation, 0, sizeof(_RpcInterfaceInformation));
+ _RpcInterfaceInformation.InterfaceId.Syntax = _iid;
+ _RpcInterfaceInformation.TransferSyntax = NdrTransferSyntax;
+ _prpcmsg->Interface = &_RpcInterfaceInformation;
+ _prpcmsg->ProcNum = IClassFactory_CreateInstance_OPNUM;
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = _pRpcChannel->GetBuffer(_prpcmsg);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ {
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+
+
+ //Marshal [in] and [in,out] parameters
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = _pRpcChannel->GetStream(_prpcmsg, _prpcmsg->_cbStream, &_prpcmsg->_pStream);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult == S_OK)
+ {
+
+
+ _try
+ {
+ /* send data from pUnkOuter */
+ *(unsigned long FAR *)&_prpcmsg->Buffer += 3;
+ *(unsigned long FAR *)&_prpcmsg->Buffer &= 0xfffffffc;
+ *(*(long FAR *FAR *)&_prpcmsg->Buffer)++ = (long)pUnkOuter;
+
+ /* send data from &riid */
+ *(unsigned long FAR *)&_prpcmsg->Buffer += 3;
+ *(unsigned long FAR *)&_prpcmsg->Buffer &= 0xfffffffc;
+ NDRcopy (_prpcmsg->Buffer, (void __RPC_FAR *) (&riid), (unsigned int)(16));
+ *(unsigned long FAR *)&_prpcmsg->Buffer += 16;
+
+ }
+ _except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Catch exceptions and map them into HRESULT error codes
+ HRESULT_from_exception(GetExceptionCode(), &((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+ //Release the stream
+ _prpcmsg->_pStream->Release();
+ _prpcmsg->_pStream = 0;
+ }
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ {
+ //Free the RPC message buffer
+ _pRpcChannel->FreeBuffer(_prpcmsg);
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+
+
+
+ //Send the request message, then receive the result message.
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = _pRpcChannel->SendReceive(_prpcmsg);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ {
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+
+
+ //Unmarshal parameters and return value
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = _pRpcChannel->GetStream(_prpcmsg, _prpcmsg->_cbStream, &_prpcmsg->_pStream);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult == S_OK)
+ {
+ _try
+ {
+
+ _tempbuf = (unsigned char FAR *)_prpcmsg->Buffer;
+ if (ppvObject ==0)
+ RpcRaiseException(RPC_X_NULL_REF_POINTER);
+ *(unsigned long FAR *)&_prpcmsg->Buffer += 3;
+ *(unsigned long FAR *)&_prpcmsg->Buffer &= 0xfffffffc;
+ if (*(*(unsigned long FAR *FAR *)&_prpcmsg->Buffer)++)
+ {
+ // BUGBUG: this is where to do custom unmarshalling work.
+ // ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = CoUnmarshalInterface(((PRPCOLE_MESSAGE)_prpcmsg)->_pStream , riid, (void **) &(*ppvObject));
+
+ HRESULT sc;
+ SApiDataHdr ApiHdr;
+ IUnknown *pUnk = NULL;
+ IMarshal *pIM = NULL;
+ IStream *pStm = ((PRPCOLE_MESSAGE)_prpcmsg)->_pStream;
+
+ sc = pStm->Read(&ApiHdr, sizeof(SApiDataHdr), NULL);
+ if (SUCCEEDED(sc))
+ {
+ if (IsEqualCLSID(CLSID_RemoteHdlr, ApiHdr.classid))
+ {
+ sc = CoCreateRemoteHandler(pUnkOuter, (void **)&pUnk);
+ }
+ else
+ {
+ sc = CoCreateInstance(ApiHdr.classid, pUnkOuter, CLSCTX_INPROC,
+ IID_IUnknown, (void **)&pUnk);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ sc = pUnk->QueryInterface(IID_IMarshal, (void **)&pIM);
+ if (SUCCEEDED(sc))
+ {
+ sc = pIM->UnmarshalInterface(pStm, riid, (void **) &(*ppvObject));
+ pIM->Release();
+ }
+ pUnk->Release();
+ }
+ }
+
+ if(sc != S_OK)
+ RpcRaiseException(sc);
+ }
+
+ /* receive data into &_ret_value */
+ long_from_ndr((PRPC_MESSAGE)_prpcmsg, (unsigned long FAR *)&_ret_value);
+
+ }_except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Catch exceptions and map them into HRESULT error codes
+ HRESULT_from_exception(GetExceptionCode(), &((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ //Free the [out] parameters
+ }
+ //Release the stream
+ _prpcmsg->_pStream->Release();
+ _prpcmsg->_pStream = 0;
+ }
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = _pRpcChannel->FreeBuffer(_prpcmsg);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ else
+ return (_ret_value);
+}
+
+HRESULT STDMETHODCALLTYPE CProxyIClassFactory::LockServer
+(
+
+ BOOL fLock
+)
+{
+ RPCOLE_INTERFACE _RpcInterfaceInformation;
+ RPCOLE_MESSAGE _message;
+ RPCOLE_MESSAGE * _prpcmsg = &_message;
+ HRESULT _ret_value;
+ unsigned long _alloc_total;
+
+ void *_xmit_type;
+ unsigned char *_packet;
+
+
+ memset((void *) &_message, 0, sizeof(_message));
+ //Initialize [out] parameters
+
+ //Calculate size of message buffer
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = S_OK;
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = _pRpcChannel->GetDestCtx(&_prpcmsg->_dwDestContext, &_prpcmsg->_pvDestContext);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ {
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+ _prpcmsg->BufferLength = 0;
+ INT_to_xmit (&fLock, (long FAR *FAR *)&_xmit_type);
+ _prpcmsg->BufferLength += 3;
+ _prpcmsg->BufferLength &= (unsigned int)0xfffffffc;
+ _prpcmsg->BufferLength += 4;
+ INT_free_xmit ((long FAR *)_xmit_type);
+
+
+ //Get RPC message
+ memset(&_RpcInterfaceInformation, 0, sizeof(_RpcInterfaceInformation));
+ _RpcInterfaceInformation.InterfaceId.Syntax = _iid;
+ _RpcInterfaceInformation.TransferSyntax = NdrTransferSyntax;
+ _prpcmsg->Interface = &_RpcInterfaceInformation;
+ _prpcmsg->ProcNum = IClassFactory_LockServer_OPNUM;
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = _pRpcChannel->GetBuffer(_prpcmsg);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ {
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+
+
+ //Marshal [in] and [in,out] parameters
+ _packet = _prpcmsg->Buffer;
+ _try
+ {
+ INT_to_xmit (&fLock, (long FAR *FAR *)&_xmit_type);
+ /* send data from *((long FAR *)_xmit_type) */
+ *(unsigned long FAR *)&_prpcmsg->Buffer += 3;
+ *(unsigned long FAR *)&_prpcmsg->Buffer &= 0xfffffffc;
+ *(*(long FAR *FAR *)&_prpcmsg->Buffer)++ = (long)*((long FAR *)_xmit_type);
+ INT_free_xmit ((long FAR *)_xmit_type);
+
+ }
+ _except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Catch exceptions and map them into HRESULT error codes
+ HRESULT_from_exception(GetExceptionCode(), &((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+ _prpcmsg->BufferLength = _prpcmsg->Buffer - _packet;
+ _prpcmsg->Buffer = _packet;
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ {
+ //Free the RPC message buffer
+ _pRpcChannel->FreeBuffer(_prpcmsg);
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+
+
+
+ //Send the request message, then receive the result message.
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = _pRpcChannel->SendReceive(_prpcmsg);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ {
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+
+
+ //Unmarshal parameters and return value
+ _packet = _prpcmsg->Buffer;
+ _try
+ {
+
+ /* receive data into &_ret_value */
+ long_from_ndr((PRPC_MESSAGE)_prpcmsg, (unsigned long FAR *)&_ret_value);
+
+ }_except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Catch exceptions and map them into HRESULT error codes
+ HRESULT_from_exception(GetExceptionCode(), &((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ //Free the [out] parameters
+ }
+ _prpcmsg->Buffer = _packet;
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = _pRpcChannel->FreeBuffer(_prpcmsg);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ else
+ return (_ret_value);
+}
diff --git a/private/ole32/com/idl/classf_s.sav b/private/ole32/com/idl/classf_s.sav
new file mode 100644
index 000000000..e8a74d364
--- /dev/null
+++ b/private/ole32/com/idl/classf_s.sav
@@ -0,0 +1,255 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: classf_s.cxx
+//
+// Contents: Interface stub for IClassFactory
+//
+// Classes: CStubIClassFactory
+//
+// History: Created by Microsoft (R) MIDL Compiler Version 1.10.82
+//
+//--------------------------------------------------------------------------
+#include "stdrpc.hxx"
+#pragma hdrstop
+#include "classf_x.h"
+
+HRESULT STDMETHODCALLTYPE CStubIClassFactory::Invoke(RPCOLE_MESSAGE *_prpcmsg, IRpcChannelBuffer *_pRpcChannel)
+{
+ HRESULT _hResult = S_OK;
+ switch(_prpcmsg->ProcNum)
+ {
+ case IClassFactory_CreateInstance_OPNUM:
+ _hResult = CStubCreateInstance(_prpcmsg, _pRpcChannel);
+ break;
+ case IClassFactory_LockServer_OPNUM:
+ _hResult = CStubLockServer(_prpcmsg, _pRpcChannel);
+ break;
+ default:
+ _hResult = E_FAIL;
+ break;
+ }
+ return _hResult;
+}
+
+HRESULT CStubIClassFactory::CStubCreateInstance(RPCOLE_MESSAGE * _prpcmsg, IRpcChannelBuffer *_pRpcChannel)
+{
+ IUnknown *pUnkOuter = 0;
+
+ IID riid;
+ void *ppvObject = 0;
+
+ HRESULT _ret_value;
+ unsigned long _alloc_bound;
+ unsigned long _alloc_total;
+ unsigned char *_savebuf;
+ unsigned char *_tempbuf;
+ RPC_STATUS _status;
+ //Initialize [in] and [in, out] parameters
+
+ //Unmarshal [in] and [in,out] parameters
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = S_OK;
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = _pRpcChannel->GetStream(_prpcmsg, _prpcmsg->_cbStream, &_prpcmsg->_pStream);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult == S_OK)
+ {
+ _try
+ {
+ _tempbuf = (unsigned char FAR *)_prpcmsg->Buffer;
+ *(unsigned long FAR *)&_prpcmsg->Buffer += 3;
+ *(unsigned long FAR *)&_prpcmsg->Buffer &= 0xfffffffc;
+ if (*(*(unsigned long FAR *FAR *)&_prpcmsg->Buffer)++)
+ {
+ }
+ _gns__GUID ((GUID FAR *)&riid, (PRPC_MESSAGE)_prpcmsg);
+
+
+ }
+ _except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Catch exceptions and map them into HRESULT error codes
+ HRESULT_from_exception(GetExceptionCode(), &((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+ //Release the stream
+ _prpcmsg->_pStream->Release();
+ _prpcmsg->_pStream = 0;
+ }
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ {
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+
+ //Initialize [out] parameters
+
+ _try
+ {
+ _ret_value = ((IClassFactory *)_pInterface)->CreateInstance((IUnknown *)pUnkOuter, (REFIID )riid, (void **)&ppvObject);
+ }
+ _except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Catch exceptions and map them into HRESULT error codes
+ HRESULT_from_exception(GetExceptionCode(), &((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ {
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+
+
+ //Calculate size of message buffer
+
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = _pRpcChannel->GetDestCtx(&_prpcmsg->_dwDestContext, &_prpcmsg->_pvDestContext);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ {
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+ _prpcmsg->BufferLength = 16;
+ _prpcmsg->BufferLength += 3;
+ _prpcmsg->BufferLength &= (unsigned int)0xfffffffc;
+ _prpcmsg->BufferLength += 4;
+ if (ppvObject !=0)
+ {
+((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = CoGetMarshalSizeMax(&((PRPCOLE_MESSAGE)_prpcmsg)->_size, riid, (IUnknown *)ppvObject, ((PRPCOLE_MESSAGE)_prpcmsg)->_dwDestContext, ((PRPCOLE_MESSAGE)_prpcmsg)->_pvDestContext, 0);
+ _prpcmsg->BufferLength += ((PRPCOLE_MESSAGE)_prpcmsg)->_size;
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_cbStream += ((PRPCOLE_MESSAGE)_prpcmsg)->_size;
+ }
+
+
+ //Get RPC message buffer
+ _status = _pRpcChannel->GetBuffer(_prpcmsg);
+
+ //Marshal [out] and [in,out] parameters
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = _pRpcChannel->GetStream(_prpcmsg, _prpcmsg->_cbStream, &_prpcmsg->_pStream);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult == S_OK)
+ {
+ _try
+ {
+ /* send data from ppvObject */
+ *(unsigned long FAR *)&_prpcmsg->Buffer += 3;
+ *(unsigned long FAR *)&_prpcmsg->Buffer &= 0xfffffffc;
+ *(*(long FAR *FAR *)&_prpcmsg->Buffer)++ = (long)ppvObject;
+ if (ppvObject !=0)
+ {
+((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = CoMarshalInterface(((PRPCOLE_MESSAGE)_prpcmsg)->_pStream, riid, (IUnknown *)ppvObject, ((PRPCOLE_MESSAGE)_prpcmsg)->_dwDestContext, ((PRPCOLE_MESSAGE)_prpcmsg)->_pvDestContext, 0);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ RpcRaiseException(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+ /* send data from _ret_value */
+ *(unsigned long FAR *)&_prpcmsg->Buffer += 3;
+ *(unsigned long FAR *)&_prpcmsg->Buffer &= 0xfffffffc;
+ *(*(long FAR *FAR *)&_prpcmsg->Buffer)++ = (long)_ret_value;
+
+
+ }
+ _except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Catch exceptions and map them into HRESULT error codes
+ HRESULT_from_exception(GetExceptionCode(), &((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+ //Release the stream
+ _prpcmsg->_pStream->Release();
+ _prpcmsg->_pStream = 0;
+ }
+ //Clean up local variables
+ if (pUnkOuter !=0)
+ {
+((IUnknown *)pUnkOuter)->Release();
+pUnkOuter = 0; }
+ if (ppvObject !=0)
+ {
+((IUnknown *)ppvObject)->Release();
+ppvObject = 0; }
+return ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult;
+}
+
+HRESULT CStubIClassFactory::CStubLockServer(RPCOLE_MESSAGE * _prpcmsg, IRpcChannelBuffer *_pRpcChannel)
+{
+ BOOL fLock;
+
+ HRESULT _ret_value;
+ unsigned char *_savebuf;
+ unsigned char *_tempbuf;
+ void *_xmit_type;
+ RPC_STATUS _status;
+ unsigned char *_packet;
+ //Initialize [in] and [in, out] parameters
+
+ //Unmarshal [in] and [in,out] parameters
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = S_OK;
+ _packet = _prpcmsg->Buffer;
+ _try
+ {
+ (*(long FAR *FAR *)&_xmit_type) = (long *)MIDL_user_allocate ((size_t)(sizeof(long)));
+ /* receive data into (long FAR *)_xmit_type */
+ long_from_ndr((PRPC_MESSAGE)_prpcmsg, (unsigned long FAR *)(long FAR *)_xmit_type);
+ INT_from_xmit ((long FAR *)_xmit_type, &fLock);
+ INT_free_xmit ((long FAR *)_xmit_type);
+
+
+ }
+ _except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Catch exceptions and map them into HRESULT error codes
+ HRESULT_from_exception(GetExceptionCode(), &((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+ _prpcmsg->Buffer = _packet;
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ {
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+
+ //Initialize [out] parameters
+
+ _try
+ {
+ _ret_value = ((IClassFactory *)_pInterface)->LockServer((BOOL )fLock);
+ }
+ _except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Catch exceptions and map them into HRESULT error codes
+ HRESULT_from_exception(GetExceptionCode(), &((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ {
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+
+
+ //Calculate size of message buffer
+
+ ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult = _pRpcChannel->GetDestCtx(&_prpcmsg->_dwDestContext, &_prpcmsg->_pvDestContext);
+ if(((PRPCOLE_MESSAGE)_prpcmsg)->_hResult != S_OK)
+ {
+ return (((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+ _prpcmsg->BufferLength = 4;
+
+
+ //Get RPC message buffer
+ _status = _pRpcChannel->GetBuffer(_prpcmsg);
+
+ //Marshal [out] and [in,out] parameters
+ _packet = _prpcmsg->Buffer;
+ _try
+ {
+ /* send data from _ret_value */
+ *(unsigned long FAR *)&_prpcmsg->Buffer += 3;
+ *(unsigned long FAR *)&_prpcmsg->Buffer &= 0xfffffffc;
+ *(*(long FAR *FAR *)&_prpcmsg->Buffer)++ = (long)_ret_value;
+
+
+ }
+ _except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Catch exceptions and map them into HRESULT error codes
+ HRESULT_from_exception(GetExceptionCode(), &((PRPCOLE_MESSAGE)_prpcmsg)->_hResult);
+ }
+ _prpcmsg->BufferLength = _prpcmsg->Buffer - _packet;
+ _prpcmsg->Buffer = _packet;
+ //Clean up local variables
+ return ((PRPCOLE_MESSAGE)_prpcmsg)->_hResult;
+}
diff --git a/private/ole32/com/idl/daytona/makefile b/private/ole32/com/idl/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/idl/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/idl/daytona/makefile.inc b/private/ole32/com/idl/daytona/makefile.inc
new file mode 100644
index 000000000..dc61bade5
--- /dev/null
+++ b/private/ole32/com/idl/daytona/makefile.inc
@@ -0,0 +1,5 @@
+#just use a common makeidl.inc for all platforms
+
+DEST_TREE=daytona
+
+!include ..\makeidl.inc
diff --git a/private/ole32/com/idl/daytona/sources b/private/ole32/com/idl/daytona/sources
new file mode 100644
index 000000000..a3da76af0
--- /dev/null
+++ b/private/ole32/com/idl/daytona/sources
@@ -0,0 +1,66 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= idl
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..;
+
+C_DEFINES= \
+ $(C_DEFINES)
+
+SOURCES= \
+ ..\empty.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+NTTARGETFILE0=allidl
+
+!include ..\sources.inc
diff --git a/private/ole32/com/idl/dirs b/private/ole32/com/idl/dirs
new file mode 100644
index 000000000..334deea03
--- /dev/null
+++ b/private/ole32/com/idl/dirs
@@ -0,0 +1,36 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+
diff --git a/private/ole32/com/idl/drot.acf b/private/ole32/com/idl/drot.acf
new file mode 100644
index 000000000..4564d6c66
--- /dev/null
+++ b/private/ole32/com/idl/drot.acf
@@ -0,0 +1,10 @@
+[ implicit_handle(handle_t any_handle) ] interface IRotDir
+
+{
+ RotDirRegister(
+ [comm_status, fault_status] prpcstat);
+
+ RotDirRevoke(
+ [comm_status, fault_status] prpcstat);
+
+}
diff --git a/private/ole32/com/idl/drot.idl b/private/ole32/com/idl/drot.idl
new file mode 100644
index 000000000..e51cfdff5
--- /dev/null
+++ b/private/ole32/com/idl/drot.idl
@@ -0,0 +1,46 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: lsrot.idl
+//
+// Contents: Definition of private RPC interface to local system
+// ROT from an object server.
+//
+// History: 30-Sep-93 Ricksa Created
+//
+// Notes: We use InterfaceData structures here because this is
+// a regular RPC interface rather than an Object interface.
+//
+// An important point to remember with respect to this
+// interface is that the table is in shared R/O so there
+// are no read operations in this interface.
+//
+//--------------------------------------------------------------------------
+[ uuid(AC923BE8-DAD9-101A-87FC-02608C4D1A7F),
+ version(0.1),
+ pointer_default(unique) ]
+
+interface IRotDir
+{
+ import "iface.idl";
+
+ HRESULT RotDirRegister(
+ [in] handle_t hRpc,
+ [in] const GUID * guidThreadId,
+ [in] InterfaceData * pIFDMoniker,
+ [in] DWORD dwHash,
+ [in] DWORD dwEndPointID,
+ [in] HAPT hApt,
+ [out] DWORD *pdwRegistration,
+ [out] error_status_t *prpcstat);
+
+ HRESULT RotDirRevoke(
+ [in] handle_t hRpc,
+ [in] DWORD dwHash,
+ [in] DWORD dwEndPointID,
+ [in] HAPT hApt,
+ [in] DWORD dwRegistration,
+ [out] error_status_t *prpcstat);
+}
diff --git a/private/ole32/com/idl/empty.cxx b/private/ole32/com/idl/empty.cxx
new file mode 100644
index 000000000..3f2ff2d6c
--- /dev/null
+++ b/private/ole32/com/idl/empty.cxx
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/private/ole32/com/idl/filelist.mk b/private/ole32/com/idl/filelist.mk
new file mode 100644
index 000000000..99ae875f5
--- /dev/null
+++ b/private/ole32/com/idl/filelist.mk
@@ -0,0 +1,90 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES =
+
+IDLFILES = \
+ .\drot.idl \
+ .\getif.idl \
+ .\ichnl.idl \
+ .\iface.idl \
+ .\objsrv.idl \
+ .\osrot.idl \
+ .\scm.idl \
+
+IDLUSE = SSWITCH
+
+CFILES = \
+ .\drot_c.c \
+ .\drot_x.c \
+ .\drot_s.c \
+ .\drot_y.c \
+ .\drot_z.c \
+ .\getif_c.c \
+ .\getif_x.c \
+ .\getif_s.c \
+ .\getif_y.c \
+ .\getif_z.c \
+ .\ichnl_c.c \
+ .\ichnl_x.c \
+ .\ichnl_s.c \
+ .\ichnl_y.c \
+ .\ichnl_z.c \
+ .\objsrv_c.c \
+ .\objsrv_x.c \
+ .\objsrv_s.c \
+ .\objsrv_y.c \
+ .\objsrv_z.c \
+ .\osrot_c.c \
+ .\osrot_x.c \
+ .\osrot_s.c \
+ .\osrot_y.c \
+ .\osrot_z.c \
+ .\scm_c.c \
+ .\scm_x.c \
+ .\scm_s.c \
+ .\scm_y.c \
+ .\scm_z.c \
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PXXFILE =
+PFILE =
+
+
+CINC = $(CINC) -I$(CARIOLE)\h -I$(COMMON)\types
+
+MTHREAD = 1
+
+MULTIDEPEND = MERGED
diff --git a/private/ole32/com/idl/getif.acf b/private/ole32/com/idl/getif.acf
new file mode 100644
index 000000000..696a08511
--- /dev/null
+++ b/private/ole32/com/idl/getif.acf
@@ -0,0 +1,10 @@
+[ implicit_handle(handle_t any_handle) ] interface IInterfaceFromWindowProp
+
+{
+ RemGetInterfaceFromWindowProp(
+ [comm_status,fault_status] prpcstat);
+
+ RemPrivDragDrop(
+ [comm_status,fault_status] prpcstat);
+}
+ \ No newline at end of file
diff --git a/private/ole32/com/idl/getif.idl b/private/ole32/com/idl/getif.idl
new file mode 100644
index 000000000..8e1eeb0ef
--- /dev/null
+++ b/private/ole32/com/idl/getif.idl
@@ -0,0 +1,50 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: getif.idl
+//
+// Contents: Definition of private RPC interface to an Object Server
+// to get an interface attached to a window.
+//
+// History: 29-Dec-93 Ricksa Created
+//
+// Notes: We use InterfaceData structures here because this is
+// a regular RPC interface rather than an Object interface.
+//
+//--------------------------------------------------------------------------
+[ uuid(D0B6FA10-E69E-101A-88A5-02608C4D1A7F),
+ version(0.1),
+ pointer_default(unique) ]
+
+interface IInterfaceFromWindowProp
+{
+ import "iface.idl";
+
+ HRESULT RemGetInterfaceFromWindowProp(
+ [in] handle_t hRpc,
+ [in] const GUID *pguidThreadId,
+ [in] DWORD hWnd,
+ [in] HAPT hApt,
+ [in] const GUID *riid,
+ [out] InterfaceData **ppIFDunk,
+ [in, string] WCHAR *pwszPropertyName,
+ [out] error_status_t *prpcstat);
+
+ HRESULT RemPrivDragDrop(
+ [in] handle_t hRpc,
+ [in] const GUID *guidThreadId,
+ [in] DWORD hWnd,
+ [in] HAPT hApt,
+ [in, unique] InterfaceData *pIFDDataObject,
+ [in] DWORD dop,
+ [in] DWORD grfKeyState,
+ [in] POINTL pt,
+ [in, out] DWORD *pdwEffect,
+ [out] HRESULT *phrDragOp,
+ [in] DWORD dwSmId,
+ [in] DWORD hwndSource,
+ [out] error_status_t *prpcstat);
+}
+ \ No newline at end of file
diff --git a/private/ole32/com/idl/ichnl.acf b/private/ole32/com/idl/ichnl.acf
new file mode 100644
index 000000000..3777fc61d
--- /dev/null
+++ b/private/ole32/com/idl/ichnl.acf
@@ -0,0 +1,37 @@
+[ implicit_handle(handle_t any_handle) ] interface IChannelService
+
+{
+
+ ICS_GetContextHdl(
+ [comm_status, fault_status] prpcstat);
+
+
+ ICS_ReleaseContextHdl(
+ [comm_status, fault_status] prpcstat);
+
+
+ ICS_GetChannelId(
+ [comm_status, fault_status] prpcstat);
+
+
+ ICS_ReleaseChannel(
+ [comm_status, fault_status] prpcstat);
+
+#ifdef _CHICAGO_
+ ICS_AsyncReleaseChannel();
+#endif // _CHICAGO_
+
+
+ ICS_SyncChannelOp(
+ [comm_status, fault_status] prpcstat);
+
+
+ ICS_InputSyncChannelOp(
+ [comm_status, fault_status] prpcstat);
+
+
+ ICS_RegisterProtseq(
+ [comm_status, fault_status] prpcstat);
+
+
+}
diff --git a/private/ole32/com/idl/ichnl.idl b/private/ole32/com/idl/ichnl.idl
new file mode 100644
index 000000000..9ce8512f0
--- /dev/null
+++ b/private/ole32/com/idl/ichnl.idl
@@ -0,0 +1,116 @@
+//[ IChannelService_itf
+//+---------------------------------------------------------------------------
+//
+// Copyright (C) 1992, Microsoft Corporation.
+//
+// File: ichnl.idl
+//
+// Contents: interface between the client and server side channels
+//
+// History: 28-Jan-93 Rickhi Created.
+//
+//----------------------------------------------------------------------------
+
+[ uuid(00000006-0000-0000-C000-000000000046),
+ version(0.1),
+ pointer_default(unique) ]
+
+
+interface IChannelService
+{
+ import "iface.idl";
+
+ // CHannel OPeration : collesces simple and common operations on the
+ // channel together; saves midl proxy/stub space.
+ typedef enum tagCHOP
+ {
+ CHOP_ADD_MARSHALCONNECTION = 1, // simulate normal marshal
+ CHOP_REMOVE_MARSHALCONNECTION = 2, // remove normal marshal conn
+ CHOP_TRANSFER_MARSHALCONNECTION = 3, // transfers ownership of
+ // connection to channel
+ // by incrementing marshal cnt
+ CHOP_LOCK_CONNECTION = 4, // lock connection
+ // for container
+ CHOP_UNLOCK_CONNECTION = 5, // unlock connection
+ // for container
+ CHOP_DOESSUPPORTIID = 6, // old IQI_QueryInterface;
+ // returns S_OK or error.
+
+ CHOP_OPERATION = 0x00ff,
+
+ CHOPFLAG_CHECK_OID_ENDPOINT_APT = 0x0100,// any op: check end point/apt
+ CHOPFLAG_LASTUNLOCKCLOSES = 0x0200, // for remove/unlock connection
+ } CHOP;
+
+ [input_sync]
+ HRESULT ICS_GetContextHdl(
+ [in] handle_t hRpcBind, // rpc handle
+ [in] SEndPoint*caller_bindings, // string bindings of caller
+ [out] PPOBJCTX ppObjCtx, // object context handle
+ [out] error_status_t *prpcstat); // RPC error status
+
+ [input_sync]
+ HRESULT ICS_ReleaseContextHdl(
+ [in,out] PPOBJCTX ppObjCtx, // object context handle
+ [out] error_status_t *prpcstat); // RPC error status
+
+ [input_sync]
+ HRESULT ICS_GetChannelId(
+ [in,out] PPOBJCTX context, // context handle
+ [in] SEndPoint*caller_bindings, // string bindings of caller
+ [in] OID ObjectId, // object id
+ [in] DWORD dwFlags, // marshal flags
+ [in] HAPT server, // server apartment
+ [in] GUID logical_thread, // logical thread of caller
+ [in] DWORD dwClientTID, // client ThreadId
+ [out] DWORD *dwChannelId, // channel id
+ [out] error_status_t *prpcstat); // RPC error status
+
+ HRESULT ICS_ReleaseChannel(
+ [in] handle_t hRpcBind, // rpc handle
+ [in] DWORD ChannelID, // channel id
+ [in] ULONG ulMarshalCnt, // release count
+ [in] BOOL fAsync, // TRUE -> returns immed.
+ [in] GUID logical_thread, // logical thread of caller
+ [out] error_status_t *prpcstat); // RPC error status
+
+#ifdef _CHICAGO_
+ [async]
+ void ICS_AsyncReleaseChannel(
+ [in] handle_t hRpcBind, // rpc handle
+ [in] DWORD ChannelID, // channel id
+ [in] ULONG ulMarshalCnt, // release count
+ [in] BOOL fAsync, // TRUE -> returns immed.
+ [in] GUID logical_thread); // logical thread of caller
+#endif // _CHICAGO_
+
+ HRESULT ICS_SyncChannelOp(
+ [in] handle_t hRpcBind, // rpc handle
+ [in] DWORD ChannelID, // channel id
+ [in] GUID logical_thread, // logical thread of caller
+ [in] DWORD chop, // CHOP_* : what to do
+ [in] HAPT hapt, // server apartment to chk
+ [in,unique] const GUID *pguid, // for CHOP_DOESSUPPORTIID
+ // and others.
+ [out] error_status_t *prpcstat); // RPC error status
+
+ [input_sync]
+ HRESULT ICS_InputSyncChannelOp(
+ [in] handle_t hRpcBind, // rpc handle
+ [in] DWORD ChannelID, // channel id
+ [in] GUID logical_thread, // logical thread of caller
+ [in] DWORD chop, // CHOP_* : what to do
+ [in] HAPT hapt, // server apartment to chk
+ [in,unique] const GUID *pguid, // for CHOP_DOESSUPPORTIID
+ // and others.
+ [out] error_status_t *prpcstat); // RPC error status
+
+ HRESULT ICS_RegisterProtseq(
+ [in] handle_t hRpcBind, // rpc handle
+ [in,string] WCHAR *pwszProtseq, // protocol sequence
+ [out] SEndPoint **ppSEndPoint,// endpoint array
+ [out] error_status_t *prpcstat); // RPC error status
+
+}
+
+
diff --git a/private/ole32/com/idl/iface.idl b/private/ole32/com/idl/iface.idl
new file mode 100644
index 000000000..d88d9e134
--- /dev/null
+++ b/private/ole32/com/idl/iface.idl
@@ -0,0 +1,176 @@
+//+---------------------------------------------------------------------------
+//
+// Copyright (C) 1992, Microsoft Corporation.
+//
+// File: iface.idl
+//
+// Contents: Public definitions used for xmiting interfaces via RPC
+//
+// History: 28-Jan-93 Ricksa Created.
+// 02-Oct-93 Rickhi new marshalling
+// 11-Dec-93 CraigWi optimized and added identity object
+//
+// Notes: These definitions are used for transmitting interfaces
+// via RPC.
+//
+//----------------------------------------------------------------------------
+
+[ uuid(5C0EB534-BF9F-101A-8818-02608C4D2359),
+ version(0.1),
+ pointer_default(unique) ]
+
+
+interface XmitDefs
+{
+ import "wtypes.idl";
+#pragma midl_echo("#ifndef OID_DEFINED")
+#pragma midl_echo("#define OID_DEFINED")
+typedef GUID OID;
+#pragma midl_echo("#endif // OID_DEFINED")
+
+typedef DWORD HAPT;
+
+// context handle for OLE objects.
+
+typedef [context_handle] void * POBJCTX;
+typedef POBJCTX * PPOBJCTX;
+
+
+// Rpc context handle wire representation. We dont transmit as a context
+// handle since we want to control when and how it gets unmarshalled.
+
+typedef struct tagNDRCONTEXT
+{
+ long type; // context handle type
+ char guid[16]; // context handle guid
+} NDRCONTEXT;
+
+
+
+// data written and read by standard Rpc channel, and not used by anything
+// else. identifies the the channel, the endpoint or context handle, and
+// the marshal flags.
+
+typedef struct tagSChannelDataHdr
+{
+ ULONG ulDataSize; // sizeof data written in the stream
+ DWORD dwFlags; // CHNLFLAGS
+ HAPT aptServer; // server apartment
+} SChannelDataHdr;
+
+// channel data flags. note: the first few bits are reserved to
+// equal the MSHLFLAGS values.
+
+typedef enum tagCHNLFLAGS
+{
+ CHNLFLAGS_TABLE = 0x00FF, // TABLESTRONG | TABLEWEAK | reserved
+ CHNLFLAGS_NONE = 0x0100, // no data follows
+ CHNLFLAGS_ENDPNT = 0x0200, // data is an Rpc string binding
+ CHNLFLAGS_CTXHDL = 0x0400, // data is a marshalled context handle
+ CHNLFLAGS_MSHLTRANSFERED = 0x0800,// marshal connection transfer successful
+} CHNLFLAGS;
+
+
+// data written and read by standard remote handler, and not used by anything
+// else. identifies the interface, the class of the channel,
+// and the marshal flags.
+
+typedef struct tagSHandlerDataHdr
+{
+ DWORD dwflags; // marshal flags || HDLRFLAGS
+ GUID iid; // interface identifier
+ // GUID clsidChnl present if !HDLRFLAGS_STDRPCCHNL
+ // DWORD cb; rgb[cb] extension present if HDLRFLAGS_EXTENSION
+} SHandlerDataHdr;
+
+// handler data flags. note: the first few bits are reserved to
+// equal the MSHLFLAGS values.
+
+typedef enum tagHDLRFLAGS
+{
+ HDLRFLAGS_TABLE = 0x00FF, // TABLESTRONG | TABLEWEAK | reserved
+ HDLRFLAGS_STDRPCCHNL= 0x0100,// standard channel clsid (no clsid present)
+ HDLRFLAGS_EXTENSION= 0x0200, // byte counted extension present
+} HDLRFLAGS;
+
+
+
+// data written and read by standard identity object, and not used by anything
+// else. identifies the object, the class of the handler,
+// and the marshal flags.
+
+typedef struct tagSIdentityDataHdr
+{
+ DWORD dwflags; // marshal flags || HDLRFLAGS
+ GUID ObjectID; // Object id of object
+ // GUID clsidHdlr present if !IDENFLAGS_STDMARSHAL
+ // DWORD cb; rgb[cb] extension present if HDLRFLAGS_EXTENSION
+} SIdentityDataHdr;
+
+// identity data flags. note: the first few bits are reserved to
+// equal the MSHLFLAGS values.
+
+typedef enum tagIDENFLAGS
+{
+ IDENFLAGS_TABLE = 0x00FF, // TABLESTRONG | TABLEWEAK | reserved
+ IDENFLAGS_STDMARSHAL= 0x0100,// standard remoting handler (CLSID_StdMarshal)
+ IDENFLAGS_EXTENSION= 0x0200,// byte counted extension present
+} IDENFLAGS;
+
+
+
+// data written and read by CoMarshal APIs, and not used by anything
+// else. identifies the class of the unmarshaller and the marshal flags
+
+typedef struct tagSMiApiDataHdr
+{
+ DWORD dwflags; // marshal flags | MIAPIFLAGS
+ // GUID clsidUnmarshal present if !MIAPIFLAGS_STDIDENTITY
+ // DWORD cb; rgb[cb] extension present if MIAPIFLAGS_EXTENSION
+} SMiApiDataHdr;
+
+
+// api flags. note the first few bits are reserved to
+// equal the MSHLFLAGS values.
+
+typedef enum tagMIAPIFLAGS
+{
+ MIAPIFLAGS_TABLE = 0x00FF, // TABLESTRONG | TABLEWEAK | reserved
+ MIAPIFLAGS_RELEASED = 0x0100,// data stream has been released
+ MIAPIFLAGS_STDIDENTITY = 0x0200,// standard identity unmarshal
+ MIAPIFLAGS_EXTENSION = 0x0400,// byte counted extension present
+ MIAPIFLAGS_IPFM = 0x0800, // marshaler is in process free marshaler.
+} MIAPIFLAGS;
+
+
+// data exchanged by the channel when registering new protocols
+
+typedef struct tagSEndPoint
+{
+#ifdef _CHICAGO_
+ ULONG ulhwnd; // hwnd for notification
+#endif
+ ULONG ulStrLen; // string lengths in Characters
+ [size_is(ulStrLen)] WCHAR awszEndPoint[]; // array of Rpc string bindings
+} SEndPoint;
+
+
+
+
+// wire representation of an entire interface. used for wrapping a
+// marshalled interface in a stream representation CXmitRpcStream.
+
+typedef struct tagInterfaceData
+{
+ ULONG ulCntData; // size of data
+ [length_is(ulCntData)] BYTE abData[1024]; // data BUGBUG: sizeis()
+} InterfaceData;
+
+typedef [unique] InterfaceData * PInterfaceData;
+
+#pragma midl_echo("// BUGBUG: until the length_is midl option is fixed, we have a")
+#pragma midl_echo("// different computation for the size of the IFD.")
+#pragma midl_echo("#define IFD_SIZE(pIFD) (sizeof(InterfaceData) + pIFD->ulCntData - 1024)")
+
+
+}
diff --git a/private/ole32/com/idl/irot.acf b/private/ole32/com/idl/irot.acf
new file mode 100644
index 000000000..14c174f6e
--- /dev/null
+++ b/private/ole32/com/idl/irot.acf
@@ -0,0 +1,30 @@
+[ implicit_handle(handle_t any_handle) ] interface IROT
+
+{
+ IrotRegister(
+ [comm_status, fault_status] prpcstat);
+
+ IrotRevoke(
+ [comm_status, fault_status] prpcstat);
+
+ IrotIsRunning(
+ [comm_status, fault_status] prpcstat);
+
+ IrotGetObject(
+ [comm_status, fault_status] prpcstat);
+
+ IrotNoteChangeTime(
+ [comm_status, fault_status] prpcstat);
+
+ IrotGetTimeOfLastChange(
+ [comm_status, fault_status] prpcstat);
+
+ IrotEnumRunning(
+ [comm_status, fault_status] prpcstat);
+
+#ifndef _CHICAGO_
+ IrotGetUniqueProcessID(
+ [comm_status, fault_status] prpcstat);
+#endif
+
+}
diff --git a/private/ole32/com/idl/irot.idl b/private/ole32/com/idl/irot.idl
new file mode 100644
index 000000000..beb997a86
--- /dev/null
+++ b/private/ole32/com/idl/irot.idl
@@ -0,0 +1,105 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: irot.idl
+//
+// Contents: Definition of private RPC interface between compobj.dll
+// and the SCM that implements the ROT.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+[ uuid(B9E79E60-3D52-11CE-AAA1-00006901293F),
+ version(0.2),
+ pointer_default(unique) ]
+
+interface IROT
+{
+ import "iface.idl";
+
+#pragma midl_echo(" ")
+#pragma midl_echo("//------------------------")
+#pragma midl_echo("// Invalid Key for SCM Reg")
+#pragma midl_echo("//------------------------")
+#pragma midl_echo("#define SCMREG_INVALID_ENTRY_LOC 0xFFFFFFFF")
+#pragma midl_echo(" ")
+
+
+ typedef struct _SCMREGKEY
+ {
+ DWORD dwEntryLoc;
+ DWORD dwScmId;
+ } SCMREGKEY;
+
+ typedef struct _MnkEqBuf
+ {
+ DWORD cdwSize;
+ [size_is(cdwSize)]
+ BYTE abEqData[];
+ } MNKEQBUF;
+
+ typedef struct _MkInterfaceList
+ {
+ DWORD dwSize;
+ [size_is(dwSize)]
+ InterfaceData *apIFDList[];
+ } MkInterfaceList;
+
+ HRESULT IrotRegister(
+ [in] handle_t hRpc,
+ [in] MNKEQBUF *pmkeqbuf,
+ [in] InterfaceData *pifdObject,
+ [in] InterfaceData *pifdObjectName,
+ [in] FILETIME *pfiletime,
+ [in] DWORD dwProcessId,
+ [out] SCMREGKEY *psrkRegister,
+ [out] error_status_t *prpcstat);
+
+ HRESULT IrotRevoke(
+ [in] handle_t hRpc,
+ [in] SCMREGKEY *psrkRegister,
+ [in] BOOL fServerRevoke,
+ [out] InterfaceData **pifdObject,
+ [out] InterfaceData **pifdName,
+ [out] error_status_t *prpcstat);
+
+ HRESULT IrotIsRunning(
+ [in] handle_t hRpc,
+ [in] MNKEQBUF *pmkeqbuf);
+
+ HRESULT IrotGetObject(
+ [in] handle_t hRpc,
+ [in] DWORD dwProcessId,
+ [in] MNKEQBUF *pmkeqbuf,
+ [out] SCMREGKEY *psrkRegister,
+ [out] InterfaceData **pifdObject,
+ [out] error_status_t *prpcstat);
+
+ HRESULT IrotNoteChangeTime(
+ [in] handle_t hRpc,
+ [in] SCMREGKEY *psrkRegister,
+ [in] FILETIME *pfiletime,
+ [out] error_status_t *prpcstat);
+
+ HRESULT IrotGetTimeOfLastChange(
+ [in] handle_t hRpc,
+ [in] MNKEQBUF *pmkeqbuf,
+ [out] FILETIME *pfiletime,
+ [out] error_status_t *prpcstat);
+
+ HRESULT IrotEnumRunning(
+ [in] handle_t hRpc,
+ [out] MkInterfaceList **ppMkIFList,
+ [out] error_status_t *prpcstat);
+
+#ifndef _CHICAGO_
+ HRESULT IrotGetUniqueProcessID(
+ [in] handle_t hRpc,
+ [out] DWORD * pdwProcessID,
+ [out] DWORD * pdwScmProcessID,
+ [out] error_status_t *prpcstat);
+#endif
+
+}
diff --git a/private/ole32/com/idl/makefil0 b/private/ole32/com/idl/makefil0
new file mode 100644
index 000000000..825d0b6b1
--- /dev/null
+++ b/private/ole32/com/idl/makefil0
@@ -0,0 +1,14 @@
+!include $(NTMAKEENV)\makefile.plt
+!include dirs
+
+DIR=$(DIRS) $(OPTIONAL_DIRS)
+
+all:
+!IF "$(BUILDMSG)" != ""
+ @ech ; $(BUILDMSG) ;
+!ENDIF
+
+clean: cleansrc all
+
+cleansrc:
+ for %%i in ($(DIR)) do cd %i & nmake -nologo BUILDMSG= clean -f makefile.inc & cd $(MAKEDIR)
diff --git a/private/ole32/com/idl/makefile b/private/ole32/com/idl/makefile
new file mode 100644
index 000000000..7cbed0c04
--- /dev/null
+++ b/private/ole32/com/idl/makefile
@@ -0,0 +1,27 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+!include $(CAIROLE)\com\makefile
+
+all: $(OBJS)
+
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/com/idl/makeidl.inc b/private/ole32/com/idl/makeidl.inc
new file mode 100644
index 000000000..48d15f213
--- /dev/null
+++ b/private/ole32/com/idl/makeidl.inc
@@ -0,0 +1,91 @@
+# DEST_TREE is set by the calling makefile
+
+CLASS_DEST=..\..\class\$(DEST_TREE)
+SCM_DEST=..\..\..\dcomss\olescm\$(DEST_TREE)
+
+
+
+
+!ifndef MIDL
+MIDL = midl.exe
+!endif
+
+#
+# BUGBUG - We want to compile these IDL files /Oi but the interpretor
+# cannot handle error_status_t parameters. When it can, change /Os to /Oi
+#
+MIDL_FLAGS= \
+ -Zp8 \
+ -I$(INCLUDES) \
+ -Os \
+ -oldnames \
+ -char unsigned \
+ -error allocation \
+ -ms_ext -c_ext \
+ $(C_DEFINES) \
+ -cpp_cmd $(TARGET_CPP)
+
+CSWITCH=-prefix cstub _
+
+irot.h: ..\irot.idl
+ $(MIDL) $(MIDL_FLAGS) \
+ -cstub $(CLASS_DEST)\irot_c.c \
+ -sstub $(SCM_DEST)\irot_s.c \
+ ..\irot.idl
+
+# the client gets '_' prefixed routine names
+getif.h: ..\getif.idl
+ $(MIDL) $(MIDL_FLAGS) \
+ $(CSWITCH) \
+ -cstub $(CLASS_DEST)\getif_z.c \
+ -sstub $(CLASS_DEST)\getif_s.c \
+ ..\getif.idl
+
+# the client gets '_' prefixed routine names
+ichnl.h: ..\ichnl.idl
+ $(MIDL) $(MIDL_FLAGS) \
+ $(CSWITCH) \
+ -cstub $(CLASS_DEST)\ichnl_z.c \
+ -sstub $(CLASS_DEST)\ichnl_s.c \
+ ..\ichnl.idl
+
+# only a header file generated
+iface.h: ..\iface.idl
+ $(MIDL) $(MIDL_FLAGS) \
+ ..\iface.idl
+
+# first MIDL invocation makes the plain client
+# second MIDL invocation makes the server and the '_' prefixed client
+objsrv.h: ..\objsrv.idl
+ $(MIDL) $(MIDL_FLAGS) \
+ -cstub $(SCM_DEST)\objsrv_c.c \
+ ..\objsrv.idl
+
+ $(MIDL) $(MIDL_FLAGS) \
+ $(CSWITCH) \
+ -cstub $(SCM_DEST)\objsrv_z.c \
+ -sstub $(CLASS_DEST)\objsrv_s.c \
+ ..\objsrv.idl
+
+# first MIDL invocation makes the plain client
+# second MIDL invocation makes the server and the '_' prefixed client
+scm.h: ..\scm.idl
+ $(MIDL) $(MIDL_FLAGS) \
+ -cstub $(CLASS_DEST)\scm_c.c \
+ ..\scm.idl
+
+ $(MIDL) $(MIDL_FLAGS) \
+ $(CSWITCH) \
+ -cstub $(SCM_DEST)\scm_z.c \
+ -sstub $(SCM_DEST)\scm_s.c \
+ ..\scm.idl
+
+allidl: irot.h getif.h ichnl.h iface.h objsrv.h scm.h
+
+clean:
+ -erase irot.h >NUL 2>NUL
+ -erase getif.h >NUL 2>NUL
+ -erase ichnl.h >NUL 2>NUL
+ -erase iface.h >NUL 2>NUL
+ -erase objsrv.h >NUL 2>NUL
+ -erase scm.h >NUL 2>NUL
diff --git a/private/ole32/com/idl/objsrv.acf b/private/ole32/com/idl/objsrv.acf
new file mode 100644
index 000000000..f1d616128
--- /dev/null
+++ b/private/ole32/com/idl/objsrv.acf
@@ -0,0 +1,13 @@
+[ implicit_handle(handle_t any_handle) ] interface IObjServer
+
+{
+ RemCoGetActiveClassObject(
+ [comm_status, fault_status] prpcstat);
+
+ RemCoActivateObject(
+ [comm_status, fault_status] prpcstat);
+
+ RemCoCreateObject(
+ [comm_status, fault_status] prpcstat);
+
+}
diff --git a/private/ole32/com/idl/objsrv.idl b/private/ole32/com/idl/objsrv.idl
new file mode 100644
index 000000000..9529925a5
--- /dev/null
+++ b/private/ole32/com/idl/objsrv.idl
@@ -0,0 +1,57 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: scm.idl
+//
+// Contents: Definition of private RPC interface between compobj.dll
+// and the service controller.
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+[ uuid(5C0EB536-BF9F-101A-8818-02608C4D2359),
+ version(0.1),
+ pointer_default(unique) ]
+
+interface IObjServer
+{
+ import "iface.idl";
+
+ HRESULT RemCoGetActiveClassObject(
+ [in] handle_t hRpc,
+ [in] const GUID *guidThreadId,
+ [in] const GUID *rclsid,
+ [out] InterfaceData **ppIFD,
+ [out] error_status_t *prpcstat);
+
+ HRESULT RemCoActivateObject(
+ [in] handle_t hRpc,
+ [in, string, unique] WCHAR *pwszProtseq,
+ [in] const GUID *guidThreadId,
+ [in] const GUID *rclsid,
+ [in] DWORD grfMode,
+ [in, string, unique] WCHAR *pwszPath,
+ [in, unique] InterfaceData *pIFDstg,
+ [in] DWORD dwTIDCaller,
+ [in, out] DWORD *pdwTIDCallee,
+ [out] InterfaceData **ppIFD,
+ [in, unique] InterfaceData *pIFDFromROT,
+ [out] error_status_t *prpcstat);
+
+ HRESULT RemCoCreateObject(
+ [in] handle_t hRpc,
+ [in, string, unique] WCHAR *pwszProtseq,
+ [in] const GUID *guidThreadId,
+ [in] const GUID *rclsid,
+ [in] DWORD grfMode,
+ [in, string, unique] WCHAR *pwszPathFrom,
+ [in, unique] InterfaceData *pIFDstgFrom,
+ [in, string, unique] WCHAR *pwszPath,
+ [in] DWORD dwTIDCaller,
+ [in, out] DWORD *pdwTIDCallee,
+ [out] InterfaceData **ppIFD,
+ [out] error_status_t *prpcstat);
+}
diff --git a/private/ole32/com/idl/osrot.acf b/private/ole32/com/idl/osrot.acf
new file mode 100644
index 000000000..0ace06860
--- /dev/null
+++ b/private/ole32/com/idl/osrot.acf
@@ -0,0 +1,10 @@
+[ implicit_handle(handle_t any_handle) ] interface IOsRot
+
+{
+ OsGetObjectInfo(
+ [comm_status, fault_status] prpcstat);
+
+ OsEnumRunning(
+ [comm_status, fault_status] prpcstat);
+
+}
diff --git a/private/ole32/com/idl/osrot.idl b/private/ole32/com/idl/osrot.idl
new file mode 100644
index 000000000..70255663d
--- /dev/null
+++ b/private/ole32/com/idl/osrot.idl
@@ -0,0 +1,74 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: osrot.idl
+//
+// Contents: Definition of private RPC interface to per Object Server
+// ROT.
+//
+// History: 30-Sep-93 Ricksa Created
+//
+// Notes: We use InterfaceData structures here because this is
+// a regular RPC interface rather than an Object interface.
+//
+//--------------------------------------------------------------------------
+[ uuid(AC923B84-DAD9-101A-87FC-02608C4D1A7F),
+ version(0.1),
+ pointer_default(unique) ]
+
+interface IOsRot
+{
+ import "iface.idl";
+
+ typedef struct _MkInterfaceList
+ {
+ DWORD dwSize;
+ [size_is(dwSize)]
+ InterfaceData *apIFDList[];
+ } MkInterfaceList;
+
+ HRESULT OsGetObjectInfo(
+ [in] handle_t hRpc,
+ [in] const GUID *guidThreadId,
+ [in] HAPT hApt,
+ [in, unique] InterfaceData *pIFDmk,
+ [in, string, unique] WCHAR *pwszPath,
+ [in, out, unique] InterfaceData **ppIFDobj,
+ [in, out, unique] FILETIME *pFileTime,
+ [in, string, unique] WCHAR *pwszProtseq,
+ [in] DWORD dwCallCat,
+ [out] error_status_t *prpcstat);
+
+ //************************************************************
+ //
+ // This method exists for use with the mswmsg transport on Chicago.
+ // The simplest way to call OsGetObjectInfo synchronously and input
+ // input synchronously is to have two methods. The only other ways
+ // are to get a MIDL extension or hand code the proxies.
+ //
+ //************************************************************
+#ifdef _CHICAGO_
+ [input_sync]
+ HRESULT OsGetObjectInfoInputSync(
+ [in] handle_t hRpc,
+ [in] const GUID *guidThreadId,
+ [in] HAPT hApt,
+ [in, unique] InterfaceData *pIFDmk,
+ [in, string, unique] WCHAR *pwszPath,
+ [in, out, unique] InterfaceData **ppIFDobj,
+ [in, out, unique] FILETIME *pFileTime,
+ [in, string, unique] WCHAR *pwszProtseq,
+ [in] DWORD dwCallCat,
+ [out] error_status_t *prpcstat);
+#endif
+
+ HRESULT OsEnumRunning(
+ [in] handle_t hRpc,
+ [in] const GUID *guidThreadId,
+ [in] HAPT hApt,
+ [in] DWORD dwCallCat,
+ [out] MkInterfaceList **ppMkIFList,
+ [out] error_status_t *prpcstat);
+}
diff --git a/private/ole32/com/idl/scm.acf b/private/ole32/com/idl/scm.acf
new file mode 100644
index 000000000..e792dad2b
--- /dev/null
+++ b/private/ole32/com/idl/scm.acf
@@ -0,0 +1,32 @@
+[ implicit_handle(handle_t any_handle) ] interface ISCM
+
+{
+#ifdef CAIROLE_DISTRIBUTED
+ PingSCM(
+ [comm_status, fault_status] prpcstat);
+#endif
+
+ StartObjectService(
+ [comm_status, fault_status] prpcstat);
+
+
+ SvcActivateObject(
+ [comm_status, fault_status] prpcstat);
+
+
+ SvcCreateActivateObject(
+ [comm_status, fault_status] prpcstat);
+
+
+ ObjectServerStarted(
+ [comm_status, fault_status] prpcstat);
+
+ StopServer(
+ [comm_status, fault_status] prpcstat);
+
+ ScmSetInfoLevel(
+ [comm_status, fault_status] prpcstat);
+
+ UpdateShrdTbls(
+ [comm_status, fault_status] prpcstat);
+}
diff --git a/private/ole32/com/idl/scm.idl b/private/ole32/com/idl/scm.idl
new file mode 100644
index 000000000..0d55ca0ac
--- /dev/null
+++ b/private/ole32/com/idl/scm.idl
@@ -0,0 +1,171 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: scm.idl
+//
+// Contents: Definition of private RPC interface between compobj.dll
+// and the service controller.
+//
+// History: 21-Apr-93 Ricksa Created
+// 27-Dec-93 ErikGav TCHAR->WCHAR
+//
+//--------------------------------------------------------------------------
+[ uuid(5C0EB535-BF9F-101A-8818-02608C4D2359),
+ version(0.2),
+ pointer_default(unique) ]
+
+interface ISCM
+{
+ import "iface.idl";
+
+#pragma midl_echo(" ")
+#pragma midl_echo("//-----------------")
+#pragma midl_echo("// SUCCESS HRESULTS")
+#pragma midl_echo("//-----------------")
+#pragma midl_echo("#define SCM_S_SUCCESS 0")
+#pragma midl_echo("#define SCM_S_HANDLER 1")
+#pragma midl_echo("#define SCM_S_INPROCSERVER 2")
+#pragma midl_echo("#define SCM_S_HANDLER16 3")
+#pragma midl_echo("#define SCM_S_INPROCSERVER16 4")
+#pragma midl_echo(" ")
+
+#pragma midl_echo(" ")
+#pragma midl_echo("//---------------------------------")
+#pragma midl_echo("// Internal DLL Thread Model Values")
+#pragma midl_echo("//---------------------------------")
+#pragma midl_echo("#define APT_THREADED 0")
+#pragma midl_echo("#define FREE_THREADED 1")
+#pragma midl_echo("#define SINGLE_THREADED 2")
+#pragma midl_echo("#define BOTH_THREADED 3")
+#pragma midl_echo("#define GOT_FROM_ROT 0x80000000")
+#pragma midl_echo(" ")
+
+#pragma midl_echo(" ")
+#pragma midl_echo("//-------------------------------------------------")
+#pragma midl_echo("// Internal CLSCTX used for loading Proxy/Stub DLLs")
+#pragma midl_echo("//-------------------------------------------------")
+#pragma midl_echo("#define CLSCTX_PS_DLL 0x80000000")
+#pragma midl_echo(" ")
+
+ typedef struct _RegOutputEnt
+ {
+ DWORD dwReg;
+ DWORD dwAtStorage;
+ } RegOutputEnt;
+
+ typedef struct _RegOutput
+ {
+ DWORD dwSize;
+ [size_is(dwSize)]
+ RegOutputEnt regoutent[];
+ } RegOutput;
+
+ typedef struct _RegInputEntry
+ {
+ CLSID clsid;
+ [ref,string] WCHAR* pwszEndPoint;
+ DWORD dwFlags;
+ } RegInputEntry;
+
+ typedef struct _RegInput
+ {
+ DWORD dwSize;
+ [size_is(dwSize)]
+ RegInputEntry rginent[];
+ } RegInput;
+
+ typedef struct _RevokeEntry
+ {
+ CLSID clsid;
+ DWORD dwReg;
+ } RevokeEntry;
+
+ typedef struct _RevokeClasses
+ {
+ DWORD dwSize;
+ [size_is(dwSize)]
+ RevokeEntry revent[];
+ } RevokeClasses;
+
+#ifdef CAIROLE_DISTRIBUTED
+ HRESULT PingSCM(
+ [in] handle_t hRpc,
+ [out] error_status_t *prpcstat);
+#endif
+
+ HRESULT StartObjectService(
+ [in] handle_t hRpc,
+ [in, string, unique] WCHAR * lpDesktop,
+ [in] const GUID *guidThreadId,
+ [in] const GUID *rclsid,
+ [in] DWORD dwCtrl,
+ [in, string, unique] WCHAR *pwszServer,
+ [out] InterfaceData **ppIFDClassObj,
+ [in, out] DWORD *pdwDllServerType,
+ [out, string] WCHAR **ppwszDllToLoad,
+ [out] error_status_t *prpcstat);
+
+ HRESULT SvcActivateObject(
+ [in] handle_t hRpc,
+ [in, string, unique] WCHAR * lpDesktop,
+ [in, string, unique] WCHAR *pwszProtseq,
+ [in] const GUID *guidThreadId,
+ [in] const GUID *rclsid,
+ [in] DWORD dwOptions,
+ [in] DWORD grfMode,
+ [in] DWORD dwHash,
+ [in, string, unique] WCHAR *pwszPath,
+ [in, unique] InterfaceData *pIFDstg,
+ [out] InterfaceData **ppIFDunk,
+ [in, out] DWORD *pdwDllServerType,
+ [out, string] WCHAR **pwszDllPath,
+ [in, string, unique] WCHAR *pwszServerAddress,
+ [in] DWORD dwTIDCaller,
+ [in, out] DWORD *pdwTIDCallee,
+ [out] error_status_t *prpcstat);
+
+
+ HRESULT SvcCreateActivateObject(
+ [in] handle_t hRpc,
+ [in, string, unique] WCHAR * lpDesktop,
+ [in, string, unique] WCHAR *pwszProtseq,
+ [in] const GUID *guidThreadId,
+ [in] const GUID *rclsid,
+ [in] DWORD dwOptions,
+ [in] DWORD dwMode,
+ [in, string, unique] WCHAR *pwszPath,
+ [in, unique] InterfaceData *pIFDstg,
+ [in, string, unique] WCHAR *pwszNewName,
+ [out] InterfaceData **ppIFDunk,
+ [in, out] DWORD *pdwDllServerType,
+ [out, string] WCHAR **pwszDllPath,
+ [in, string, unique] WCHAR *pwszServerAddress,
+ [in] DWORD dwTIDCaller,
+ [in, out] DWORD *pdwTIDCallee,
+ [out] error_status_t *prpcstat);
+
+ HRESULT ObjectServerStarted(
+ [in] handle_t hRpc,
+ [in, string, unique] WCHAR * lpDesktop,
+ [in] RegInput *pregin,
+ [out] RegOutput **ppregout,
+ [out] error_status_t *prpcstat);
+
+ void StopServer(
+ [in] handle_t hRpc,
+ [in] RevokeClasses *prevcls,
+ [out] error_status_t *prpcstat);
+
+ // This allows debug information to be printed out
+ DWORD ScmSetInfoLevel(
+ [in] handle_t hRpc,
+ [in] DWORD dwNewFlags,
+ [out] error_status_t *prpcstat);
+
+ HRESULT UpdateShrdTbls(
+ [in] handle_t hRpc,
+ [out] error_status_t *prpcstat);
+}
+ \ No newline at end of file
diff --git a/private/ole32/com/idl/sources.inc b/private/ole32/com/idl/sources.inc
new file mode 100644
index 000000000..407eb4e3c
--- /dev/null
+++ b/private/ole32/com/idl/sources.inc
@@ -0,0 +1,3 @@
+#
+#
+#
diff --git a/private/ole32/com/inc/allguid.cxx b/private/ole32/com/inc/allguid.cxx
new file mode 100644
index 000000000..6dbdb6703
--- /dev/null
+++ b/private/ole32/com/inc/allguid.cxx
@@ -0,0 +1,170 @@
+#define INITGUID
+#define INITGUID
+#include "windows.h"
+
+// Handle port problems easily
+
+// PORT: HTASK no longer seems to be defined in Win32
+#define HTASK DWORD
+#define HINSTANCE_ERROR 32
+#define __loadds
+#define __segname
+#define BASED_CODE
+#define HUGE
+#define __based(x)
+
+#include "ole2.h"
+
+// #include "privguid.h"
+
+#ifndef CAIROLE_DOWNLEVEL
+DEFINE_OLEGUID(CLSID_StdOleLink, 0x00000300, 0, 0);
+DEFINE_OLEGUID(CLSID_StdMemStm, 0x00000301, 0, 0);
+DEFINE_OLEGUID(CLSID_StdMemBytes, 0x00000302, 0, 0);
+DEFINE_OLEGUID(CLSID_FileMoniker, 0x00000303, 0, 0);
+DEFINE_OLEGUID(CLSID_ItemMoniker, 0x00000304, 0, 0);
+DEFINE_OLEGUID(CLSID_AntiMoniker, 0x00000305, 0, 0);
+DEFINE_OLEGUID(CLSID_PointerMoniker, 0x00000306, 0, 0);
+// NOT TO BE USED 0x00000307, 0, 0);
+DEFINE_OLEGUID(CLSID_PackagerMoniker, 0x00000308, 0, 0);
+DEFINE_OLEGUID(CLSID_CompositeMoniker, 0x00000309, 0, 0);
+#endif // !CAIROLE_DOWNLEVEL
+
+DEFINE_OLEGUID(CLSID_RemoteHdlr, 0x00000200, 0, 8);
+DEFINE_OLEGUID(CLSID_RpcChannelBuffer, 0x00000199, 0, 8);
+
+// clsids for proxy/stub objects
+// these are defined in \common\h\win40\cguid.h
+//DEFINE_OLEGUID(CLSID_PSGenObject, 0x0000030c, 0, 0);
+//DEFINE_OLEGUID(CLSID_PSClientSite, 0x0000030d, 0, 0);
+//DEFINE_OLEGUID(CLSID_PSClassObject, 0x0000030e, 0, 0);
+//DEFINE_OLEGUID(CLSID_PSInPlaceActive, 0x0000030f, 0, 0);
+//DEFINE_OLEGUID(CLSID_PSInPlaceFrame, 0x00000310, 0, 0);
+//DEFINE_OLEGUID(CLSID_PSDragDrop, 0x00000311, 0, 0);
+//DEFINE_OLEGUID(CLSID_PSBindCtx, 0x00000312, 0, 0);
+//DEFINE_OLEGUID(CLSID_PSEnumerators, 0x00000313, 0, 0);
+//DEFINE_OLEGUID(CLSID_PSStore, 0x00000314, 0, 0);
+
+// #include "ole1cls.h"
+
+#ifndef DEFINE_OLE1GUID
+#define DEFINE_OLE1GUID(a,b,c,d,e) DEFINE_OLEGUID (a,b,c,d)
+#endif
+
+#ifndef CAIROLE_DOWNLEVEL
+DEFINE_OLE1GUID(CLSID_ExcelWorksheet, 0x00030000, 0, 0, "ExcelWorksheet");
+DEFINE_OLE1GUID(CLSID_ExcelChart, 0x00030001, 0, 0, "ExcelChart");
+DEFINE_OLE1GUID(CLSID_ExcelMacrosheet, 0x00030002, 0, 0, "ExcelMacrosheet");
+DEFINE_OLE1GUID(CLSID_WordDocument, 0x00030003, 0, 0, "WordDocument");
+#endif // !CAIROLE_DOWNLEVEL
+DEFINE_OLE1GUID(CLSID_MSPowerPoint, 0x00030004, 0, 0, "MSPowerPoint");
+DEFINE_OLE1GUID(CLSID_MSPowerPointSho, 0x00030005, 0, 0, "MSPowerPointSho");
+DEFINE_OLE1GUID(CLSID_MSGraph, 0x00030006, 0, 0, "MSGraph");
+#ifndef CAIROLE_DOWNLEVEL
+DEFINE_OLE1GUID(CLSID_MSDraw, 0x00030007, 0, 0, "MSDraw");
+#endif // !CAIROLE_DOWNLEVEL
+DEFINE_OLE1GUID(CLSID_Note_It, 0x00030008, 0, 0, "Note-It");
+DEFINE_OLE1GUID(CLSID_WordArt, 0x00030009, 0, 0, "WordArt");
+#ifndef CAIROLE_DOWNLEVEL
+DEFINE_OLE1GUID(CLSID_PBrush, 0x0003000a, 0, 0, "PBrush");
+#endif // !CAIROLE_DOWNLEVEL
+DEFINE_OLE1GUID(CLSID_Equation, 0x0003000b, 0, 0, "Equation");
+#ifndef CAIROLE_DOWNLEVEL
+DEFINE_OLE1GUID(CLSID_Package, 0x0003000c, 0, 0, "Package");
+#endif // !CAIROLE_DOWNLEVEL
+DEFINE_OLE1GUID(CLSID_SoundRec, 0x0003000d, 0, 0, "SoundRec");
+DEFINE_OLE1GUID(CLSID_MPlayer, 0x0003000e, 0, 0, "MPlayer");
+
+/* test apps */
+DEFINE_OLE1GUID(CLSID_ServerDemo, 0x0003000f, 0, 0, "ServerDemo");
+DEFINE_OLE1GUID(CLSID_Srtest, 0x00030010, 0, 0, "Srtest");
+DEFINE_OLE1GUID(CLSID_SrtInv, 0x00030011, 0, 0, "SrtInv");
+DEFINE_OLE1GUID(CLSID_OleDemo, 0x00030012, 0, 0, "OleDemo");
+
+/* External ISVs */
+// Coromandel / Dorai Swamy / 718-793-7963
+DEFINE_OLE1GUID(CLSID_CoromandelIntegra, 0x00030013, 0, 0, "CoromandelIntegra");
+DEFINE_OLE1GUID(CLSID_CoromandelObjServer,0x00030014, 0, 0, "CoromandelObjServer");
+
+// 3-d Visions Corp / Peter Hirsch / 310-325-1339
+DEFINE_OLE1GUID(CLSID_StanfordGraphics, 0x00030015, 0, 0, "StanfordGraphics");
+
+// Deltapoint / Nigel Hearne / 408-648-4000
+DEFINE_OLE1GUID(CLSID_DGraphCHART, 0x00030016, 0, 0, "DGraphCHART");
+DEFINE_OLE1GUID(CLSID_DGraphDATA, 0x00030017, 0, 0, "DGraphDATA");
+
+// Corel / Richard V. Woodend / 613-728-8200 x1153
+DEFINE_OLE1GUID(CLSID_PhotoPaint, 0x00030018, 0, 0, "PhotoPaint");
+DEFINE_OLE1GUID(CLSID_CShow, 0x00030019, 0, 0, "CShow");
+DEFINE_OLE1GUID(CLSID_CorelChart, 0x0003001a, 0, 0, "CorelChart");
+DEFINE_OLE1GUID(CLSID_CDraw, 0x0003001b, 0, 0, "CDraw");
+
+// Inset Systems / Mark Skiba / 203-740-2400
+DEFINE_OLE1GUID(CLSID_HJWIN1_0, 0x0003001c, 0, 0, "HJWIN1.0");
+
+// Mark V Systems / Mark McGraw / 818-995-7671
+DEFINE_OLE1GUID(CLSID_ObjMakerOLE, 0x0003001d, 0, 0, "ObjMakerOLE");
+
+// IdentiTech / Mike Gilger / 407-951-9503
+DEFINE_OLE1GUID(CLSID_FYI, 0x0003001e, 0, 0, "FYI");
+DEFINE_OLE1GUID(CLSID_FYIView, 0x0003001f, 0, 0, "FYIView");
+
+// Inventa Corporation / Balaji Varadarajan / 408-987-0220
+DEFINE_OLE1GUID(CLSID_Stickynote, 0x00030020, 0, 0, "Stickynote");
+
+// ShapeWare Corp. / Lori Pearce / 206-467-6723
+DEFINE_OLE1GUID(CLSID_ShapewareVISIO10, 0x00030021, 0, 0, "ShapewareVISIO10");
+DEFINE_OLE1GUID(CLSID_ImportServer, 0x00030022, 0, 0, "ImportServer");
+
+
+// test app SrTest
+DEFINE_OLE1GUID(CLSID_SrvrTest, 0x00030023, 0, 0, "SrvrTest");
+
+// Special clsid for when a 1.0 client pastes an embedded object
+// that is a link.
+// **This CLSID is obsolete. Do not reuse number.
+//DEFINE_OLE1GUID(CLSID_10EmbedObj, 0x00030024, 0, 0, "OLE2_Embedded_Link");
+
+// test app ClTest. Doesn't really work as a server but is in reg db
+DEFINE_OLE1GUID(CLSID_ClTest, 0x00030025, 0, 0, "Cltest");
+
+// Microsoft ClipArt Gallery Sherry Larsen-Holmes
+DEFINE_OLE1GUID(CLSID_MS_ClipArt_Gallery,0x00030026, 0, 0, "MS_ClipArt_Gallery");
+
+// Microsoft Project Cory Reina
+DEFINE_OLE1GUID(CLSID_MSProject, 0x00030027, 0, 0, "MSProject");
+
+// Microsoft Works Chart
+DEFINE_OLE1GUID(CLSID_MSWorksChart, 0x00030028, 0, 0, "MSWorksChart");
+
+// Microsoft Works Spreadsheet
+DEFINE_OLE1GUID(CLSID_MSWorksSpreadsheet,0x00030029, 0, 0, "MSWorksSpreadsheet");
+
+// AFX apps - Dean McCrory
+DEFINE_OLE1GUID(CLSID_MinSvr, 0x0003002A, 0, 0, "MinSvr");
+DEFINE_OLE1GUID(CLSID_HierarchyList, 0x0003002B, 0, 0, "HierarchyList");
+DEFINE_OLE1GUID(CLSID_BibRef, 0x0003002C, 0, 0, "BibRef");
+DEFINE_OLE1GUID(CLSID_MinSvrMI, 0x0003002D, 0, 0, "MinSvrMI");
+DEFINE_OLE1GUID(CLSID_TestServ, 0x0003002E, 0, 0, "TestServ");
+
+// Ami Pro
+DEFINE_OLE1GUID(CLSID_AmiProDocument, 0x0003002F, 0, 0, "AmiProDocument");
+
+// WordPerfect Presentations For Windows
+DEFINE_OLE1GUID(CLSID_WPGraphics, 0x00030030, 0, 0, "WPGraphics");
+DEFINE_OLE1GUID(CLSID_WPCharts, 0x00030031, 0, 0, "WPCharts");
+
+
+// MicroGrafx Charisma
+DEFINE_OLE1GUID(CLSID_Charisma, 0x00030032, 0, 0, "Charisma");
+DEFINE_OLE1GUID(CLSID_Charisma_30, 0x00030033, 0, 0, "Charisma_30");
+DEFINE_OLE1GUID(CLSID_CharPres_30, 0x00030034, 0, 0, "CharPres_30");
+
+// MicroGrafx Draw
+DEFINE_OLE1GUID(CLSID_Draw, 0x00030035, 0, 0, "Draw");
+
+// MicroGrafx Designer
+DEFINE_OLE1GUID(CLSID_Designer_40, 0x00030036, 0, 0, "Designer_40");
+
+
+#undef DEFINE_OLE1GUID
diff --git a/private/ole32/com/inc/array_fv.h b/private/ole32/com/inc/array_fv.h
new file mode 100644
index 000000000..04684f203
--- /dev/null
+++ b/private/ole32/com/inc/array_fv.h
@@ -0,0 +1,73 @@
+#ifndef __ARRAY_FV_H__
+#define __ARRAY_FV_H__
+
+////////////////////////////////////////////////////////////////////////////
+// class CArrayFValue - an array containing fixed size elements,
+//
+////////////////////////////////////////////////////////////////////////////
+
+
+class FAR CArrayFValue
+{
+public:
+
+// Construction
+ CArrayFValue(UINT cbValue);
+ ~CArrayFValue();
+
+// Attributes
+ int GetSize() const
+ { return m_nSize; }
+ int GetUpperBound() const
+ { return m_nSize-1; }
+ BOOL SetSize(int nNewSize, int nGrowBy = -1);
+ int GetSizeValue() const
+ { return m_cbValue; }
+
+// Operations
+ // Clean up
+ void FreeExtra();
+ void RemoveAll()
+ { SetSize(0); }
+
+ // return pointer to element; index must be in range
+#ifdef _DEBUG
+ // with debug checks
+ LPVOID GetAt(int nIndex) const
+ { return _GetAt(nIndex); }
+#else
+ // no debug checks
+ LPVOID GetAt(int nIndex) const
+ { return &m_pData[nIndex * m_cbValue]; }
+#endif
+ LPVOID _GetAt(int nIndex) const;
+
+ // set element; index must be in range
+ void SetAt(int nIndex, LPVOID pValue);
+
+ // find element given part of one; offset is offset into value; returns
+ // -1 if element not found; use IndexOf(NULL, cb, offset) to find zeros;
+ // will be optimized for appropriate value size and param combinations
+ int IndexOf(LPVOID pData, UINT cbData, UINT offset);
+
+ // set/add element; Potentially growing the array; return FALSE/-1 if
+ // not possible (due to OOM)
+ BOOL SetAtGrow(int nIndex, LPVOID pValue);
+
+ // Operations that move elements around
+ BOOL InsertAt(int nIndex, LPVOID pValue, int nCount = 1);
+ void RemoveAt(int nIndex, int nCount = 1);
+
+ void AssertValid() const;
+
+// Implementation
+private:
+ BYTE FAR* m_pData; // the actual array of data
+ UINT m_cbValue; // size of each value (in bytes)
+ int m_nSize; // current # of elements (m_cbValue bytes in length)
+ int m_nMaxSize; // max # of elements (m_cbValue bytes in length)
+ int m_nGrowBy; // grow amount (in # elements)
+};
+
+
+#endif // !__ARRAY_FV_H__
diff --git a/private/ole32/com/inc/array_id.h b/private/ole32/com/inc/array_id.h
new file mode 100644
index 000000000..955a37a16
--- /dev/null
+++ b/private/ole32/com/inc/array_id.h
@@ -0,0 +1,79 @@
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+
+class FAR CIDArray
+{
+public:
+
+// Construction
+ CIDArray() : m_afv(sizeof(IDENTRY)) { }
+ ~CIDArray() { }
+
+// Attributes
+ int GetSize() const
+ { return m_afv.GetSize(); }
+ int GetUpperBound() const
+ { return m_afv.GetSize()-1; }
+ BOOL SetSize(int nNewSize, int nGrowBy = -1)
+ { return m_afv.SetSize(nNewSize, nGrowBy); }
+ int GetSizeValue() const
+ { return m_afv.GetSizeValue(); }
+
+// Operations
+ // Clean up
+ void FreeExtra()
+ { m_afv.FreeExtra(); }
+
+ void RemoveAll()
+ { m_afv.SetSize(0); }
+
+ // return pointer to element; index must be in range
+ IDENTRY GetAt(int nIndex) const
+ { return *(IDENTRY FAR*)m_afv.GetAt(nIndex); }
+ IDENTRY FAR& ElementAt(int nIndex)
+ { return (IDENTRY FAR&)*(IDENTRY FAR*)m_afv.GetAt(nIndex); }
+
+ // overloaded operator helpers
+ IDENTRY operator[](int nIndex) const
+ { return GetAt(nIndex); }
+ IDENTRY FAR& operator[](int nIndex)
+ { return ElementAt(nIndex); }
+
+ // get address of first element efficiently
+ operator IDENTRY *() { return (IDENTRY FAR*)m_afv.GetAt(0); }
+
+ // set element; index must be in range
+ void SetAt(int nIndex, IDENTRY& value)
+ { m_afv.SetAt(nIndex, (LPVOID)&value); }
+
+ // find element given part of one; offset is offset into value; returns
+ // -1 if element not found; use IndexOf(NULL, cb, offset) to find zeros;
+ // will be optimized for appropriate value size and param combinations
+ int IndexOf(LPVOID pData, UINT cbData, UINT offset)
+ { return m_afv.IndexOf(pData, cbData, offset); }
+
+ // set/add element; Potentially growing the array; return FALSE/-1 if
+ // not possible (due to OOM)
+ BOOL SetAtGrow(int nIndex, IDENTRY& value)
+ { return m_afv.SetAtGrow(nIndex, (LPVOID)&value); }
+ int Add(IDENTRY& value)
+ { int nIndex = GetSize();
+ return SetAtGrow(nIndex, value) ? nIndex : -1;
+ }
+
+ // Operations that move elements around
+ BOOL InsertAt(int nIndex, IDENTRY& value, int nCount = 1)
+ { return m_afv.InsertAt(nIndex, (LPVOID)&value, nCount); }
+ void RemoveAt(int nIndex, int nCount = 1)
+ { m_afv.RemoveAt(nIndex, nCount); }
+
+ void AssertValid() const
+ { m_afv.AssertValid(); }
+
+// Implementation
+private:
+ CArrayFValue m_afv;
+};
diff --git a/private/ole32/com/inc/assrtdlg.h b/private/ole32/com/inc/assrtdlg.h
new file mode 100644
index 000000000..f61ae784c
--- /dev/null
+++ b/private/ole32/com/inc/assrtdlg.h
@@ -0,0 +1,9 @@
+#define AssertFail 5100
+#define Expr 5101
+#define Location 5102
+#define ASSRT_ID_BREAK 5103
+#define ASSRT_ID_EXIT 5104
+#define ASSRT_ID_IGNORE 5105
+#define ASSRT_ID_LOC 5106
+#define ASSRT_ID_EXPR 5107
+#define ASSRT_ID_MSG 5108
diff --git a/private/ole32/com/inc/callinfo.h b/private/ole32/com/inc/callinfo.h
new file mode 100644
index 000000000..a5f895977
--- /dev/null
+++ b/private/ole32/com/inc/callinfo.h
@@ -0,0 +1,61 @@
+#ifndef _CALLINFO_H
+#define _CALLINFO_H
+
+//
+// Shared information between DDE and LRPC
+//
+typedef ULONG TIMERID;
+typedef ULONG CALLID, FAR * LPCALLID;
+//
+// the call info holds all information for one particular outgoing call
+//
+typedef struct tagCallInfo CallInfo, CALLINFO, FAR* LPCALLINFO;
+
+struct tagCallInfo {
+ UINT m_id; // this is the callinfo id for the table lookup
+ HWND m_hwndSvr; // window of callee
+ HWND m_hwndCli; // window of caller
+ BOOL m_fWait; // wait for acknowledge
+ BOOL m_fRejected; // call was rejected
+ DWORD m_dwServerCall; // set by HIC, passed to RetryRejectedCall (ack/busyack/nak/error)
+ HRESULT m_hresult; // the return value of this loop
+
+ // info to retry the call
+ WORD m_wMsg;
+ WPARAM m_wParam;
+ LPARAM m_lParam;
+
+ // timer status for this callinfo
+ WORD m_wTimer;
+
+ // Note: Call State
+ // here we remember the current call state we are in
+ // if the call was at the 'root' level the call state is 0
+ // REVIEW: this is not ready yet and used to detect if we call
+ // out on an external call.
+ DWORD m_dwCallState;
+
+ //
+ // internaly used to manage multiple
+ LONG m_lid;
+ LPVOID m_pData;
+ LPCALLINFO m_pCINext;
+};
+
+//
+// The origin of RunModalLoop is needed for the priority of message.
+// If call by LRPC, lrpc messages are peeked first.
+//
+typedef enum tagCALLORIGIN {
+ CALLORIGIN_LRPC = 1,
+ CALLORIGIN_DDE = 2,
+} CALLORIGIN;
+
+// function used by DDE and LRPC
+STDAPI CoRunModalLoop (LPCALLINFO pCI, WORD wOrigin);
+STDAPI_(DWORD) CoHandleIncomingCall( HWND hwndCaller, WORD wCallType, LPINTERFACEINFO lpIfInfo = NULL);
+STDAPI_(DWORD) CoSetAckState(LPCALLINFO pCI, BOOL fWait, BOOL fRejected = FALSE, DWORD dwServerCall = 0);
+
+#endif // _CALLINFO_H
+
+
diff --git a/private/ole32/com/inc/cevent.cxx b/private/ole32/com/inc/cevent.cxx
new file mode 100644
index 000000000..56ac54219
--- /dev/null
+++ b/private/ole32/com/inc/cevent.cxx
@@ -0,0 +1,129 @@
+//+-------------------------------------------------------------------
+//
+// File: cevent.cxx
+//
+// Contents: Implementation of classes handling win32 events
+//
+// Functions: CEvent::CEvent -- constructor for event object
+// CEvent::~CEvent -- destructor for event object
+// CEvent::Signal -- signals the event
+// CEvent::Wait -- waits for the event to be signaled
+// CEvent::GetName -- returns the name of the event
+//
+// History: 27-Jul-92 Rickhi Created
+// 31-Dec-93 ErikGav Chicago port
+//
+//--------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <secdes.hxx>
+#include <cevent.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEvent::CEvent
+//
+// Synopsis: Constructor for event object. This version of the ctor
+// creates an event of the given name. The event will be
+// in the non-signaled state, ready to be blocked on via the
+// Wait() method.
+//
+// Arguments: [pwszService] -- name of executable to run
+// [cSerial] -- serial number for this event
+//
+// Signals: CException if the event creation failed
+//
+// Returns: nothing
+//
+// History: 27-Jul-92 Rickhi Created
+// 07-Jan-94 AlexT No security for Chicago
+// 13-Jun-95 SusiA ANSI optimization for Chicago
+//
+//--------------------------------------------------------------------------
+
+#ifdef _CHICAGO_
+#undef CreateEvent
+#define CreateEvent CreateEventA
+#undef OpenEvent
+#define OpenEvent OpenEventA
+#endif //_CHICAGO_
+
+CEvent::CEvent(LPTSTR ptszEventName,
+ HRESULT& hr,
+ BOOL fManualReset) : _hdl(NULL)
+
+{
+ // Assume this works
+ hr = S_OK;
+
+ // Just try to create the event - if it already exists the create
+ // function still succeeds
+
+#ifndef _CHICAGO_
+ CWorldSecurityDescriptor secd;
+#endif
+
+ // Security attributes needed by CreateEvent
+ SECURITY_ATTRIBUTES secattr;
+
+ secattr.nLength = sizeof(secattr);
+#ifdef _CHICAGO_
+ secattr.lpSecurityDescriptor = NULL;
+#else
+ secattr.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) secd;
+#endif
+ secattr.bInheritHandle = FALSE;
+
+ _hdl = CreateEvent(&secattr, // all/anyone access
+ fManualReset, // manual reset
+ FALSE, // initially not signaled
+ ptszEventName); // name of the event
+
+ if (_hdl == NULL)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEvent::Wait
+//
+// Synopsis: Waits for the event to be signalled.
+//
+// Arguments: [ulTimeOut] -- max time to wait for the event to be signaled
+// A value of -1 means wait for ever.
+//
+// Returns: 0 -- event was signalled
+// WAIT_TIMEOUT -- timed out waiting for the event
+// WAIT_INVALID_HANDLE -- the handle is invalid - should not
+// be possible!
+//
+// History: 27-Jul-92 Rickhi Created
+//
+//--------------------------------------------------------------------------
+
+int CEvent::Wait(ULONG ulTimeOut)
+{
+ int rc = WaitForSingleObject(_hdl, ulTimeOut);
+
+ // Note. The signal will be auto reset or not depending on the constructor
+ // parameter fManualReset which is defaulted to auto reset
+
+ switch (rc)
+ {
+ case 0:
+ case WAIT_TIMEOUT:
+ break;
+
+ default:
+ // if the rc is not zero or WAIT_TIMEOUT, you have to call
+ // GetLastError to figure out what it really is.
+ rc = GetLastError();
+ }
+
+ return rc;
+}
diff --git a/private/ole32/com/inc/cevent.hxx b/private/ole32/com/inc/cevent.hxx
new file mode 100644
index 000000000..bb39d86fd
--- /dev/null
+++ b/private/ole32/com/inc/cevent.hxx
@@ -0,0 +1,119 @@
+//+-------------------------------------------------------------------
+//
+// File: cevent.hxx
+//
+// Contents: Definition of classes handling win32 events
+//
+// Classes: CEvent
+//
+// Functions: none
+//
+// History: 27-Jul-92 Rickhi Created
+// 31-Dec-93 ErikGav Chicago port
+//
+//--------------------------------------------------------------------
+
+#ifndef __CEVENT_HXX__
+#define __CEVENT_HXX__
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CEvent (ev)
+//
+// Purpose: C++ wrapper for win32 events
+//
+// Interface: CEvent -- creates/opens the event
+// ~CEvent -- closes the event handle
+// Wait -- waits for event object to be signaled
+// Signal -- signals the event object
+// Reset -- resets the event object
+// GetName -- returns ptr to the event name
+//
+// History: 27-Jul-92 Rickhi Created
+//
+//--------------------------------------------------------------------------
+
+class CEvent
+{
+public:
+
+ CEvent(LPTSTR ptszEventName,
+ HRESULT& hr,
+ BOOL fManualReset = FALSE);
+ ~CEvent(void);
+
+ INT Wait(ULONG ulTimeOut);
+ void Signal(void);
+ void Reset(void);
+
+private:
+
+ HANDLE _hdl; // event object handle
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEvent::~CEvent
+//
+// Synopsis: Destructor for event object. Closes the event handle.
+//
+// Arguments: none
+//
+// History: 27-Jul-92 Rickhi Created
+//
+//--------------------------------------------------------------------------
+
+inline CEvent::~CEvent(void)
+{
+ if (_hdl != NULL)
+ {
+ CloseHandle(_hdl);
+ }
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEvent::Signal
+//
+// Synopsis: Signals the event object.
+//
+// Arguments: none
+//
+// History: 27-Jul-92 Rickhi Created
+//
+//--------------------------------------------------------------------------
+
+inline void CEvent::Signal(void)
+{
+ int rc = SetEvent(_hdl);
+ Win4Assert(rc);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEvent::Reset
+//
+// Synopsis: Resets the event object.
+//
+// Arguments: none
+//
+// History: 26-Sep -95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+
+inline void CEvent::Reset(void)
+{
+ int rc = ResetEvent(_hdl);
+ Win4Assert(rc);
+}
+
+
+
+#endif // __CEVENT_HXX__
diff --git a/private/ole32/com/inc/clskey.hxx b/private/ole32/com/inc/clskey.hxx
new file mode 100644
index 000000000..b33d1b6c8
--- /dev/null
+++ b/private/ole32/com/inc/clskey.hxx
@@ -0,0 +1,167 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: clskey.hxx
+//
+// Contents: Class used for searching by class ID
+//
+// Classes: CClassID
+//
+// Functions: CClassID::CClassID
+// CClassID::~CClassID
+// CClassID::Compare
+//
+// History: 21-Apr-93 Ricksa Created
+// 20-Oct-94 BillMo Removed sklist macro stuff
+//
+//--------------------------------------------------------------------------
+#ifndef __CLSKEY_HXX__
+#define __CLSKEY_HXX__
+
+#include <memapi.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Class: CClassID (clsid)
+//
+// Purpose: Key for searching cache of class information
+//
+// Interface: Compare
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+class CClassID
+{
+public:
+ CClassID(const GUID& guid);
+
+ CClassID(const CClassID& clsid);
+
+ CClassID(BYTE bFill);
+
+ virtual ~CClassID(void);
+
+ int Compare(const CClassID& ccid) const;
+
+ GUID& GetGuid(void);
+
+protected:
+
+ GUID _guid;
+};
+
+inline CClassID::CClassID(BYTE bFill)
+{
+ memset(&_guid, bFill, sizeof(_guid));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassID::CClassID
+//
+// Synopsis: Creat class id key from GUID
+//
+// Arguments: [guid] - guid for key
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CClassID::CClassID(const GUID& guid)
+{
+ memcpy(&_guid, &guid, sizeof(GUID));
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassID::CClassID
+//
+// Synopsis: Copy constructor
+//
+// Arguments: [clsid] - class key to construct from
+//
+// History: 21-Apr-93 Ricksa Created
+//
+// Notes: Copy constructor is explicit because we need to
+// put in an END_CONSTRUCTION macro for exception handling.
+//
+//--------------------------------------------------------------------------
+inline CClassID::CClassID(const CClassID& clsid)
+{
+ memcpy(&_guid, &clsid._guid, sizeof(GUID));
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassID::~CClassID
+//
+// Synopsis: Free key
+//
+// History: 21-Apr-93 Ricksa Created
+//
+// Notes: This definition is needed because destructor is virtual
+//
+//--------------------------------------------------------------------------
+inline CClassID::~CClassID(void)
+{
+ // Automatic actions are enough
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassID::Compare
+//
+// Synopsis: Compare two keys
+//
+// Arguments: [clsid] - key to compare with
+//
+// Returns: = 0 keys are equal
+// < 0 object key is less
+// > 0 object key is greater.
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline int CClassID::Compare(const CClassID& clsid) const
+{
+ return memcmp(&_guid, &clsid._guid, sizeof(GUID));
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassID::GetGuid
+//
+// Synopsis: Return the guid
+//
+// Arguments: -
+//
+// Returns: GUID&
+//
+// History: 29-Jan-96 BruceMa Created
+//
+//--------------------------------------------------------------------------
+inline GUID& CClassID::GetGuid(void)
+{
+ return _guid;
+}
+
+
+extern GUID guidCidMax;
+
+
+#endif // __CLSKEY_HXX__
diff --git a/private/ole32/com/inc/compname.cxx b/private/ole32/com/inc/compname.cxx
new file mode 100644
index 000000000..a5d0a9675
--- /dev/null
+++ b/private/ole32/com/inc/compname.cxx
@@ -0,0 +1,94 @@
+//+-------------------------------------------------------------------
+//
+// File: compname.cxx
+//
+// Contents: implementation of class to retrieve the local machine name
+//
+// Classes: CComputerName - class to get the machine name
+//
+// Functions: CComputerName::Init - initializes the computername object
+//
+// History: 09-Oct-92 Rickhi Created
+// 31-Dec-93 ErikGav Chicago port
+//
+//--------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <compname.hxx>
+
+
+// Define the registry path to the computer name
+#define REG_COMPUTERNAME_KEY L"system\\currentcontrolset\\control\\computername\\computername"
+#define REG_COMPUTERNAME_VALUE L"computername"
+
+// Define and Initialize the static data members.
+BOOL CComputerName::_fInit = FALSE;
+WCHAR CComputerName::_wszComputerName[COMPNAME_SIZE];
+
+//+-------------------------------------------------------------------
+//
+// Member: CComputerName::Init
+//
+// Synopsis: looks in the registry to get the local computer name and
+// stores this away. Subsequent constructors need not
+// do anything, since the name is cached.
+//
+// Returns: nothing
+//
+// History: 09-Oct-92 Rickhi Created
+// 26-Jun-93 Rickhi Use registry instead of Net API
+// 7-Jan-93 ErikGav Use GetComputerName API instead of registry
+// (for Chicago only, at present)
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+void CComputerName::Init(void)
+{
+#ifdef _CHICAGO_
+ DWORD dwBufSize = MAX_COMPUTERNAME_LENGTH + 1;
+ BOOL bRet;
+
+ _wszComputerName[2] = L'\0';
+ bRet = ::GetComputerName(&_wszComputerName[2], &dwBufSize);
+ if (!bRet)
+ {
+ CairoleDebugOut((DEB_WARN, "GetComputerName failed\n"));
+ }
+
+ // stick the backslashes in to form the UNC name
+ _wszComputerName[0] = L'\\';
+ _wszComputerName[1] = L'\\';
+
+ _fInit = TRUE;
+
+#else
+ HKEY hkReg;
+ SCODE sc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ REG_COMPUTERNAME_KEY,
+ REG_OPTION_NON_VOLATILE,
+ KEY_QUERY_VALUE,
+ &hkReg);
+
+ if (sc == S_OK)
+ {
+ DWORD dwTypeCode;
+ ULONG ulBufSize = sizeof(_wszComputerName) * sizeof(WCHAR);
+ sc = RegQueryValueEx(hkReg,
+ REG_COMPUTERNAME_VALUE,
+ NULL, // title index
+ &dwTypeCode, // type of data returned
+ (BYTE *)(&_wszComputerName[2]),
+ &ulBufSize); // size of returned data
+
+ RegCloseKey(hkReg);
+
+ // stick the backslashes in to form the UNC name
+ _wszComputerName[0] = L'\\';
+ _wszComputerName[1] = L'\\';
+
+ _fInit = TRUE;
+ }
+#endif
+}
diff --git a/private/ole32/com/inc/compname.hxx b/private/ole32/com/inc/compname.hxx
new file mode 100644
index 000000000..befe256c8
--- /dev/null
+++ b/private/ole32/com/inc/compname.hxx
@@ -0,0 +1,112 @@
+//+-------------------------------------------------------------------
+//
+// File: compname.hxx
+//
+// Contents: Classes to retrieve the local computer name
+//
+// Classes: CComputerName - class to get the computer name
+//
+// Functions: CComputerName::GetComputerName - returns computername
+// CComputerName::GetUNCName - retuns \\computername
+//
+// History: 09-Oct-92 Rickhi Created
+// 31-Dec-93 ErikGav Chicago port
+//
+// Notes: This class retrieves and stores the computer name locally
+// so that subsequent calls to the constructor just use
+// the cached name instead of making more Net API calls.
+//
+// Since the members of this class are allocated statically,
+// they are initialized outside this class definition, and
+// no constructor or destructor is required.
+//
+//--------------------------------------------------------------------
+#ifndef __COMPNAME_HXX__
+#define __COMPNAME_HXX__
+
+#define COMPNAME_SIZE MAX_COMPUTERNAME_LENGTH + 3
+
+
+//+-------------------------------------------------------------------
+//
+// Class: CComputerName (cn)
+//
+// Purpose: Retrieve and store the local computer name
+//
+// Interface:
+//
+// History: 09-Oct-92 Rickhi Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+class CComputerName
+{
+public:
+
+ LPWSTR GetUNCComputerName(void);
+ LPWSTR GetComputerName(void);
+
+private:
+
+ void Init(void);
+
+ static BOOL _fInit;
+
+ // large enough to hold computer name + NULL terminator + \\ UNC prefix
+ static WCHAR _wszComputerName[COMPNAME_SIZE];
+};
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CComputerName::GetComputerName
+//
+// Synopsis: returns a pointer to the computer name.
+//
+// Returns: Pointer to ComputerName, excluding the preceeding
+// backslashes
+//
+// History: 09-Oct-92 Rickhi Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+inline LPWSTR CComputerName::GetComputerName(void)
+{
+ if (!_fInit)
+ {
+ Init();
+ }
+ return &_wszComputerName[2];
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CComputerName::GetUNCComputerName
+//
+// Synopsis: returns a pointer to the computer name.
+//
+// Returns: Pointer to ComputerName, including the preceeding
+// backslashes. This is for convenience when creating
+// UNC style names.
+//
+// History: 09-Oct-92 Rickhi Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+inline LPWSTR CComputerName::GetUNCComputerName(void)
+{
+ if (!_fInit)
+ {
+ Init();
+ }
+ return &_wszComputerName[0];
+}
+
+#endif // __COMPNAME_HXX__
diff --git a/private/ole32/com/inc/comsrgt.hxx b/private/ole32/com/inc/comsrgt.hxx
new file mode 100644
index 000000000..6b712587f
--- /dev/null
+++ b/private/ole32/com/inc/comsrgt.hxx
@@ -0,0 +1,163 @@
+//+-------------------------------------------------------------------
+//
+// File: comsrgt.hxx
+//
+// Contents: declarations for accessing an instance of ISurrogate
+//
+// Functions:
+//
+// History: 21-Oct-96 t-adame Created
+//
+//--------------------------------------------------------------------
+
+#ifndef __COMSRGT_HXX__
+#define __COMSRGT_HXX__
+
+#include <ole2int.h>
+#include <..\com\dcomrem\locks.hxx>
+
+extern COleStaticMutexSem gComLock;
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CCOMSurrogate
+//
+// Purpose: This class provides threadsafe access to an ISurrogate pointer
+//
+// Interface: LoadDllServer - Loads the dll for the specified clsid
+//
+// FreeSurrogate - Tells the surrogate process to terminate
+// and prevents subsequent calls to LoadDll
+//
+// SetISurrogate - Set the value of the ISurrogate pointer
+//
+// History: 21-Oct-96 t-adame Created
+//
+// Notes: This class should only be declared in debug at file scope
+//
+//
+//----------------------------------------------------------------------------
+class CCOMSurrogate
+{
+public:
+
+ static HRESULT LoadDllServer(REFCLSID clsid);
+ static HRESULT FreeSurrogate();
+ static HRESULT InitializeISurrogate(LPSURROGATE pSurrogate);
+
+private:
+
+ static LPSURROGATE _pSurrogate;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CCOMSurrogate::FreeSurrogate()
+//
+// Synopsis: Calls ISurrogate::FreeSurrogate, so the process will
+// terminate, and sets our _pSurrogate to NULL and releases
+// it so that it can't be used to load further dll servers
+//
+// Returns: S_OK if it tells the surrogate process to terminate,
+// S_FALSE if it doesn'tx
+//
+// History: 21-Oct-96
+//
+//----------------------------------------------------------------------------
+inline HRESULT CCOMSurrogate::FreeSurrogate()
+{
+ LOCK(gComLock);
+ LPSURROGATE pSurrogate = _pSurrogate;
+
+ if(pSurrogate)
+ {
+ _pSurrogate = NULL;
+
+ CoSuspendClassObjects();
+
+ UNLOCK(gComLock);
+ (void)pSurrogate->FreeSurrogate();
+
+ pSurrogate->Release(); // we no longer need it
+
+ return S_OK;
+ }
+ UNLOCK(gComLock);
+ return S_FALSE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CCOMSurrogate::SetISurrogate()
+//
+// Synopsis: sets ISurrogate pointer according to the pSurrogate
+// parameter of this function.
+//
+// Notes: calls to this function are NOT serialized
+//
+// History: 21-Oct-96
+//
+//----------------------------------------------------------------------------
+inline HRESULT CCOMSurrogate::InitializeISurrogate(LPSURROGATE pSurrogate)
+{
+ ASSERT_LOCK_DONTCARE(gComLock);
+
+ // should only be used to set an uninitialized (NULL) and
+ // should not be initialized to NULL
+
+ if(_pSurrogate)
+ {
+ return MAKE_SCODE(SEVERITY_ERROR, FACILITY_WIN32, ERROR_ALREADY_INITIALIZED);
+ }
+
+ if(pSurrogate)
+ {
+ pSurrogate->AddRef();
+ _pSurrogate = pSurrogate;
+ return S_OK;
+ }
+
+ return E_INVALIDARG;
+}
+
+
+//+---------------------------------------------------------------------------
+ //
+// Member: CCOMSurrogate::LoadDllServer
+//
+// Synopsis: Loads the server for the specified clsid
+//
+// History: 21-Oct-96
+//
+//----------------------------------------------------------------------------
+inline HRESULT CCOMSurrogate::LoadDllServer(REFCLSID clsid)
+{
+
+ HRESULT hr = CO_E_SERVER_STOPPING;
+
+ ASSERT_LOCK_DONTCARE(gComLock);
+
+ LOCK(gComLock);
+ LPSURROGATE pSurrogate = _pSurrogate;
+ UNLOCK(gComLock);
+
+ // if _pSurrogate is NULL, then the surrogate process either
+ // failed to register its ISurrogate with CoRegisterSurrogate,
+ // a requirement for surrogate processes, or (more likely),
+ // the surrogate is shutting down -- in either case, we
+ // return CO_E_SERVER_STOPPING so that activation will
+ // try to start up another surrogate
+ if (pSurrogate)
+ {
+ hr = pSurrogate->LoadDllServer(clsid);
+ }
+
+
+
+ return hr;
+}
+#endif // !__COMSRGT_HXX__
+
+
diff --git a/private/ole32/com/inc/daytona/makefile b/private/ole32/com/inc/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/inc/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/inc/daytona/sources b/private/ole32/com/inc/daytona/sources
new file mode 100644
index 000000000..94264fef8
--- /dev/null
+++ b/private/ole32/com/inc/daytona/sources
@@ -0,0 +1,83 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= inc
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..\..\inc;..\..\dcomidl\daytona;
+INCLUDES= $(INCLUDES);..\..\objact;..\..\dcomrem;..\..\..\dcomss\olescm
+INCLUDES= $(INCLUDES);$(BASEDIR)\private\dcomidl\obj
+
+C_DEFINES= \
+ $(C_DEFINES)
+
+SOURCES= \
+ ..\cevent.cxx \
+ ..\compname.cxx \
+ ..\dbgpopup.cxx \
+ ..\exttbl.cxx \
+ ..\pathkey.cxx \
+ ..\pattbl.cxx \
+ ..\psctbl.cxx \
+ ..\rotdata.cxx \
+ ..\rothelp.cxx \
+ ..\shrtblc.cxx \
+ ..\shrtbls.cxx \
+ ..\skiplist.cxx \
+ ..\smblock.cxx \
+ ..\smcreate.cxx \
+ ..\smmutex.cxx \
+ ..\smstack.cxx \
+ ..\xmit.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
+!include ..\sources.inc
diff --git a/private/ole32/com/inc/dbgpopup.cxx b/private/ole32/com/inc/dbgpopup.cxx
new file mode 100644
index 000000000..db5c62478
--- /dev/null
+++ b/private/ole32/com/inc/dbgpopup.cxx
@@ -0,0 +1,105 @@
+//+-------------------------------------------------------------------
+//
+// File: dbgpopup.cxx
+//
+// Contents: Component Object Model debug APIs that popup error msgs
+// on the screen.
+//
+// Classes: None
+//
+// Functions: PopupStringMsg
+// PopupDWORDMsg
+// PopupGUIDMsg
+//
+// History: 23-Nov-92 Rickhi Created
+// 31-Dec-93 ErikGav Chicago port
+//
+//--------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <dbgpopup.hxx>
+
+#if DBG == 1
+
+//--------------------------------------------------------------------
+//
+// Function: PopupStringMsg
+//
+// synopsis: formats and displays a popup error message. this is
+// used in non-retail builds to display error messages
+// on the screen, in the format of a popup.
+//
+// Algorithm:
+//
+// History: 23-Nov-92 Rickhi Created
+//
+// Notes: this API takes a format string and a LPWSTR as parameters.
+//
+//--------------------------------------------------------------------
+
+extern "C" void PopupStringMsg (char *pfmt, LPWSTR pwszParm)
+{
+ char szParm[MAX_PATH];
+ char outmsg[MAX_PATH];
+
+ // convert incomming string to ascii
+ WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, pwszParm, -1, szParm, MAX_PATH, NULL, NULL);
+ wsprintfA (outmsg, pfmt, szParm);
+ _Win4Assert( __FILE__, __LINE__, outmsg);
+}
+
+//--------------------------------------------------------------------
+//
+// Function: PopupDWORDMsg
+//
+// synopsis: formats and displays a popup error message. this is
+// used in non-retail builds to display error messages
+// on the screen, in the format of a popup.
+//
+// Algorithm:
+//
+// History: 23-Nov-92 Rickhi Created
+//
+// Notes: this API takes a format string and a DWORD as parameters.
+//
+//--------------------------------------------------------------------
+
+extern "C" void PopupDWORDMsg (char *pfmt, DWORD dwParm)
+{
+ char outmsg[256];
+
+ wsprintfA (outmsg, pfmt, dwParm);
+ _Win4Assert( __FILE__, __LINE__, outmsg);
+}
+
+
+//--------------------------------------------------------------------
+//
+// Function: PopupGUIDMsg
+//
+// synopsis: formats and displays a popup error message. this is
+// used in non-retail builds to display error messages
+// on the screen, in the format of a popup.
+//
+// Algorithm:
+//
+// History: 23-Nov-92 Rickhi Created
+//
+// Notes: this API takes a mag and a GUID as parameters.
+//
+//--------------------------------------------------------------------
+
+extern "C" void PopupGUIDMsg (char *msg, GUID guid)
+{
+ char outmsg[256];
+
+ wsprintfA (outmsg, "%s %08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ msg, guid.Data1, guid.Data2, guid.Data3, (int) guid.Data4[0],
+ (int) guid.Data4[1], (int) guid.Data4[2], (int) guid.Data4[3],
+ (int) guid.Data4[4], (int) guid.Data4[5],
+ (int) guid.Data4[6], (int) guid.Data4[7]);
+
+ _Win4Assert( __FILE__, __LINE__, outmsg);
+}
+
+#endif
diff --git a/private/ole32/com/inc/dbgpopup.hxx b/private/ole32/com/inc/dbgpopup.hxx
new file mode 100644
index 000000000..ce72eae38
--- /dev/null
+++ b/private/ole32/com/inc/dbgpopup.hxx
@@ -0,0 +1,65 @@
+//+-------------------------------------------------------------------
+//
+// File: dbgpopup.hxx
+//
+// Contents: Component Object Model debug APIs prototypes and MACRO
+// definitions.
+//
+// Classes: None
+//
+// Functions: None
+//
+// Macros: DbgStringPopup
+// DbgDWORDPopup
+// DbgGUIDPopup
+//
+// History: 23-Nov-92 Rickhi Created
+// 31-Dec-93 ErikGav Chicago port
+//
+//--------------------------------------------------------------------
+
+#ifndef _DBGPOPUP_
+#define _DBGPOPUP_
+
+
+#if DBG == 1
+
+// Note: these are defined extern "C" so that CairOLE, which overrides
+// the definition of GUID can also use them without getting
+// a different decorated name.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void PopupStringMsg (char *pfmt, LPWSTR pwszParm);
+void PopupDWORDMsg (char *pfmt, DWORD dwParm);
+void PopupGUIDMsg (char *msg, GUID guid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define DbgStringPopup(fmt, parm) \
+ PopupStringMsg ( fmt, parm);
+
+#define DbgDWORDPopup(fmt, parm) \
+ PopupDWORDMsg ( fmt, parm);
+
+#define DbgGUIDPopup(msg, guid) \
+ PopupGUIDMsg ( msg, guid);
+
+
+#else
+
+
+#define DbgStringPopup(fmt, parm)
+#define DbgDWORDPopup(fmt, parm)
+#define DbgGUIDPopup(msg, guid)
+
+
+#endif // DBG == 1
+
+
+
+#endif // _DBGPOPUP_
diff --git a/private/ole32/com/inc/dirs b/private/ole32/com/inc/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/com/inc/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/com/inc/exttbl.cxx b/private/ole32/com/inc/exttbl.cxx
new file mode 100644
index 000000000..867329a7d
--- /dev/null
+++ b/private/ole32/com/inc/exttbl.cxx
@@ -0,0 +1,245 @@
+//+---------------------------------------------------------------------------//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: exttbl.cxx
+//
+// Contents: File extension to CLSID cache
+//
+// Classes: CFileExtTbl
+// CScmFileExtTbl
+//
+// Functions: none
+//
+// History: 20-May-94 Rickhi Created
+// 20-Feb-95 BruceMa Don't include file extension unless
+// CLSID is valid
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <exttbl.hxx>
+
+
+//+-------------------------------------------------------------------------
+//
+// member: CFileExtTbl::FindClassExt
+//
+// Synopsis: Finds the clsid that maps to the given file extension
+//
+// Arguments: [pszExt] - the file extension to look up
+// [pclsid] - where to return the clsid
+//
+// Returns: S_OK if found
+// REGDB_E_CLASSNOTREG if not found
+//
+//--------------------------------------------------------------------------
+HRESULT CFileExtTbl::FindClassExt(LPCWSTR pszExt, CLSID *pClsid)
+{
+ // lower case the entry so that searches can be case sensitive
+ // (faster than case insensitive searches).
+
+ WCHAR wszExt[MAX_PATH];
+ lstrcpyW(wszExt, pszExt);
+ CharLowerW(wszExt);
+
+
+ Win4Assert(_pStart && "CFileExtTbl not initialized");
+ BYTE *pEntry = _pStart;
+ BYTE *pEnd = _pStart + (_pTblHdr->OffsEnd - _pTblHdr->OffsStart);
+
+ while (pEntry < pEnd)
+ {
+ // compare the class extensions
+ if (!lstrcmpW(wszExt, ((SExtEntry *)pEntry)->wszExt))
+ {
+ // found a match, we're done
+ memcpy(pClsid, &((SExtEntry *)pEntry)->Clsid, sizeof(CLSID));
+ return S_OK;
+ }
+
+ Win4Assert((((SExtEntry *)pEntry)->ulEntryLen & 0x07) == 0);
+ pEntry += ((SExtEntry *)pEntry)->ulEntryLen;
+ }
+
+ return REGDB_E_CLASSNOTREG;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmFileExtTbl::InitTbl
+//
+// Synopsis: creates a local memory copy of the file extension to CLSID
+// mapping table.
+//
+// Arguments: [pulSize] - where to return the size of the generated table
+//
+// Returns: S_OK if successful
+// E_OUTOFMEMORY if no memory
+//
+//--------------------------------------------------------------------------
+HRESULT CScmFileExtTbl::InitTbl(ULONG *pulSize)
+{
+ // init size to zero
+ *pulSize = 0;
+
+ // allocate local memory in which to build the table
+ _pLocTbl = (SExtTblHdr *) PrivMemAlloc(EXTTBL_MAX_SIZE);
+ if (!_pLocTbl)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // initialize the table header
+ _pLocTbl->ulSize = EXTTBL_MAX_SIZE;
+ _pLocTbl->cEntries = 0;
+ _pLocTbl->OffsStart = sizeof(SExtTblHdr);
+ _pLocTbl->OffsEnd = sizeof(SExtTblHdr);
+
+
+ // build the table from the data in the registry
+ // enumerate the entries under the key
+
+ HKEY hkRoot = HKEY_CLASSES_ROOT;
+ DWORD iFileExt = 0;
+ FILETIME ftLastWrite;
+ WCHAR szFileExt[MAX_PATH];
+ DWORD cbFileExt = sizeof(szFileExt);
+
+ while (RegEnumKeyEx(hkRoot, iFileExt, szFileExt, &cbFileExt,
+ NULL, NULL, NULL, &ftLastWrite)== ERROR_SUCCESS)
+ {
+ if (szFileExt[0] == L'.')
+ {
+ // the entry begins with '.' so it may be a file extension
+ // query the value (which is the ProgID)
+
+ WCHAR szProgID[MAX_PATH];
+ LONG cbProgID = sizeof(szProgID);
+
+ if (RegQueryValue(hkRoot, szFileExt, szProgID, &cbProgID)
+ == ERROR_SUCCESS)
+ {
+ // we got the value (ProgID), now query for the CLSID
+ // string and convert it to a CLSID
+
+ WCHAR szClsid[40];
+ LONG cbClsid = sizeof(szClsid);
+ lstrcatW(szProgID, L"\\Clsid");
+
+ if (RegQueryValue(HKEY_CLASSES_ROOT, szProgID, szClsid,
+ &cbClsid) == ERROR_SUCCESS)
+ {
+ // make sure the clsid is valid
+ cbProgID = sizeof(szProgID);
+ WCHAR szClsidEntry[80];
+ lstrcpyW(szClsidEntry, L"Clsid\\");
+ lstrcatW(szClsidEntry, szClsid);
+
+ if (RegQueryValue(HKEY_CLASSES_ROOT, szClsidEntry,
+ szProgID, &cbProgID) == ERROR_SUCCESS)
+ {
+ CLSID clsid;
+
+ // Don't add file extension unless CLSID is valid
+ if (GUIDFromString(szClsid, &clsid))
+ {
+ Add(szFileExt, &clsid);
+ }
+ }
+ }
+ }
+ }
+
+ ++iFileExt;
+ cbFileExt = sizeof(szFileExt);
+ }
+
+ // update the table size to the combined size of all the entries
+ // we generated above, and return this size to the caller.
+
+ _pLocTbl->ulSize = _pLocTbl->OffsEnd;
+ *pulSize = _pLocTbl->ulSize;
+
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmFileExtTbl::Add
+//
+// Synopsis: creates a cache node and adds it to the table.
+//
+// Arguments: [pszExt] - the file extension to look up
+// [pClsid] - where to return the clsid
+//
+// Returns: S_OK if successfull,
+// REG error otherwise
+//
+//--------------------------------------------------------------------------
+HRESULT CScmFileExtTbl::Add(LPCWSTR pwszExt, CLSID *pClsid)
+{
+ // lower case the entry so that searches can be case sensitive
+ // (faster than case insensitive searches).
+
+ WCHAR wszExt[MAX_PATH];
+ lstrcpyW(wszExt, pwszExt);
+ CharLowerW(wszExt);
+
+ // compute how much space we need for this entry. Note that the
+ // terminating NULL is accounted for in the sizeof(SExtEntry).
+ // we also keep the structures 8 byte aligned.
+
+ ULONG ulStrLen = lstrlenW(wszExt) * sizeof(WCHAR);
+ ULONG ulEntryLen = (sizeof(SExtEntry) + ulStrLen + 7) & 0xfffffff8;
+
+ // make sure this entry will fit in the currently allocated block.
+ if (_pLocTbl->OffsEnd + ulEntryLen <= _pLocTbl->ulSize)
+ {
+ // copy in the guid and the extension
+ SExtEntry *pEntry = (SExtEntry *)((BYTE *)_pLocTbl + _pLocTbl->OffsEnd);
+
+ memcpy(&pEntry->Clsid, pClsid, sizeof(CLSID));
+ memcpy(&pEntry->wszExt, wszExt, ulStrLen + sizeof(WCHAR));
+ pEntry->ulEntryLen = ulEntryLen;
+
+ // update the ending offset
+ _pLocTbl->OffsEnd += ulEntryLen;
+
+ return S_OK;
+ }
+
+ // could not fit this entry in the table
+ return E_OUTOFMEMORY;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmExtTbl::CopyTbl
+//
+// Synopsis: copies the locally-built table to shared memory
+//
+// Arguments: [pShrTbl] - ptr to shared memory table
+//
+// Returns: nothing
+//
+//--------------------------------------------------------------------------
+BYTE *CScmFileExtTbl::CopyTbl(BYTE *pShrTbl)
+{
+ BYTE *pEnd = pShrTbl;
+
+ if (_pLocTbl != NULL)
+ {
+ // now that we have built a local memory copy of the table, copy
+ // the table into shared memory.
+
+ memcpy(pShrTbl, (BYTE *)_pLocTbl, _pLocTbl->ulSize);
+ pEnd += _pLocTbl->ulSize;
+ }
+
+ return pEnd;
+}
diff --git a/private/ole32/com/inc/exttbl.hxx b/private/ole32/com/inc/exttbl.hxx
new file mode 100644
index 000000000..d8b5b7b46
--- /dev/null
+++ b/private/ole32/com/inc/exttbl.hxx
@@ -0,0 +1,199 @@
+//+---------------------------------------------------------------------------//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: exttbl.hxx
+//
+// Contents: File extension to CLSID cache
+//
+// Classes: CFileExtTbl
+//
+// Functions: none
+//
+// History: 20-Apr-94 Rickhi Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __EXTTBL__
+#define __EXTTBL__
+
+#include <olesem.hxx>
+
+// structure for global table info. This appears at the start of
+// the table and is used by all readers.
+
+typedef struct tagSExtTblHdr
+{
+ ULONG ulSize; // table size
+ ULONG cEntries; // count of entries in table
+ ULONG OffsStart; // offset to start of entries
+ ULONG OffsEnd; // offset to end of entries
+} SExtTblHdr;
+
+
+// structure for one entry in the cache. the structure is variable sized
+// with the variable sized data being the filename extension at the end
+// of the structure.
+
+typedef struct tagSExtEntry
+{
+ CLSID Clsid; // clsid the extension maps to
+ ULONG ulEntryLen; // length of this entry
+ WCHAR wszExt[1]; // start of filename extension
+} SExtEntry;
+
+
+// amount to grow the cache by
+#define EXTTBL_MAX_SIZE 16300
+
+
+//+-------------------------------------------------------------------------
+//
+// class: CFileExtTbl
+//
+// purpose: Holds a cache of file extension to clsid mappings (saves
+// two registry hits for each lookup). The cache helps reduce
+// the working set by avoiding paging in the registry.
+//
+// notes: The cache is expected to typically be small, hence the small
+// growth rate (5 entries at a time), linear search, and no
+// attempt is made at reordering the entries based on lookup
+// frequency.
+//
+// The entries are stored in a single block of memory which is
+// realloced when it needs to grow.
+//
+//--------------------------------------------------------------------------
+class CFileExtTbl : public CPrivAlloc
+{
+public:
+ CFileExtTbl();
+ ~CFileExtTbl();
+
+ void Initialize(BYTE *pTblHdr);
+ HRESULT FindClassExt(LPCWSTR pwszExt, CLSID *pClsid);
+
+private:
+
+ SExtTblHdr *_pTblHdr; // ptr to table header structure
+ BYTE *_pStart; // ptr to first entry in the memory block
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// member: CFileExtTbl::CFileExtTbl
+//
+// Synopsis: constructor for the cache.
+//
+//--------------------------------------------------------------------------
+inline CFileExtTbl::CFileExtTbl() :
+ _pTblHdr(NULL),
+ _pStart(NULL)
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CFileExtTbl::~CFileExtTbl
+//
+// Synopsis: destructor for the cache. Delete the entries.
+//
+//--------------------------------------------------------------------------
+inline CFileExtTbl::~CFileExtTbl()
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CFileExtTbl::Initialize
+//
+// Synopsis: initializes the client side object
+//
+//--------------------------------------------------------------------------
+inline void CFileExtTbl::Initialize(BYTE *pTblHdr)
+{
+ Win4Assert(pTblHdr && "CFileExtTbl invalid TblHdr pointer");
+
+ _pTblHdr = (SExtTblHdr *)pTblHdr;
+ _pStart = (BYTE *)_pTblHdr + _pTblHdr->OffsStart;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// class: CScmFileExtTbl
+//
+// purpose: Holds a cache of file extension to clsid mappings (saves
+// two registry hits for each lookup). The cache helps reduce
+// the working set by avoiding paging in the registry.
+//
+// notes: The cache is expected to typically be small, hence the small
+// growth rate (5 entries at a time), linear search, and no
+// attempt is made at reordering the entries based on lookup
+// frequency.
+//
+// The entries are stored in a single block of memory which is
+// realloced when it needs to grow.
+//
+//--------------------------------------------------------------------------
+class CScmFileExtTbl : public CPrivAlloc
+{
+public:
+ CScmFileExtTbl();
+ ~CScmFileExtTbl();
+
+ HRESULT InitTbl(ULONG *pulSize);
+ BYTE *CopyTbl(BYTE *pShrTbl);
+ void FreeTbl(void);
+
+private:
+
+ HRESULT Add(LPCWSTR pwszExt, CLSID *pClsid);
+
+ SExtTblHdr *_pLocTbl; // ptr to local memory table
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmFileExtTbl::CScmFileExtTbl
+//
+// Synopsis: constructor for the class
+//
+// Arguments: none
+//
+//--------------------------------------------------------------------------
+inline CScmFileExtTbl::CScmFileExtTbl() :
+ _pLocTbl(NULL)
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmFileExtTbl::~CScmFileExtTbl
+//
+// Synopsis: destructor for the class
+//
+//--------------------------------------------------------------------------
+inline CScmFileExtTbl::~CScmFileExtTbl()
+{
+ PrivMemFree((BYTE *)_pLocTbl);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmFileExtTbl::~CScmFileExtTbl
+//
+// Synopsis: destructor for the class
+//
+//--------------------------------------------------------------------------
+inline void CScmFileExtTbl::FreeTbl(void)
+{
+ PrivMemFree((BYTE *)_pLocTbl);
+ _pLocTbl = NULL;
+}
+
+#endif // __EXTTBL__
diff --git a/private/ole32/com/inc/filelist.mk b/private/ole32/com/inc/filelist.mk
new file mode 100644
index 000000000..1a5dc78e5
--- /dev/null
+++ b/private/ole32/com/inc/filelist.mk
@@ -0,0 +1,68 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = inc.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+
+CXXFILES = \
+!if "$(OPSYS)" == "NT"
+ .\allguid.cxx \
+!endif
+ .\cevent.cxx \
+ .\clskey.cxx \
+ .\compname.cxx \
+ .\dbgpopup.cxx \
+ .\malloc.cxx \
+ .\pathkey.cxx \
+ .\smmutex.cxx \
+ .\sklist.cxx \
+ .\xmit.cxx \
+
+
+CFILES =
+
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PXXFILE =
+PFILE =
+
+
+CINC = $(CINC) -I..\inc -I..\idl -DWIN32 $(LRPC) $(TRACELOG)
+
+MTHREAD = 1
+
+MULTIDEPEND = MERGED
diff --git a/private/ole32/com/inc/guidmap.cxx b/private/ole32/com/inc/guidmap.cxx
new file mode 100644
index 000000000..e513f4616
--- /dev/null
+++ b/private/ole32/com/inc/guidmap.cxx
@@ -0,0 +1,225 @@
+//+---------------------------------------------------------------------------//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: guidmap.cxx
+//
+// Contents: IID to proxy/stub CLSID mapping cache
+//
+// Classes: CScmGuidMap - shared memory guid map
+//
+// Functions:
+//
+// History: 07-Apr-94 Rickhi Created
+//
+// Notes: this class maintains an IID to CLSID mapping table
+// in shared memory.
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <guidmap.hxx>
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmGuidMap::FreeSpace
+//
+// Synopsis: returns the amount of free space left in the table
+//
+// Returns: see Synopsis.
+//
+// Algorithm: computes the freespace by multiplying the number of each type
+// of entry with the size of that type of entry, summing them,
+// and subtracting the total from the map size.
+//
+//--------------------------------------------------------------------------
+ULONG CScmGuidMap::FreeSpace()
+{
+ ULONG ulUsed =
+ (_pGuidMap->ulCntShort + _pGuidMap->ulCntShortOverFlow) *sizeof(DWORDPAIR)+
+ (_pGuidMap->ulCntLong + _pGuidMap->ulCntLongOverFlow) *sizeof(GUIDPAIR);
+
+ return (IIDMAP_SIZE - sizeof(GUIDMAP) - ulUsed);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmGuidMap::SearchShortList
+//
+// Synopsis: searches the short list for a matching entry and returns
+// a pointer to the found element, or NULL.
+//
+// Arguments: [dwFind] - the first dword of the GUID we want to find
+//
+// Returns: ptr to matching entry if found, NULL otherwise.
+//
+// Algorithm: does a binary search on the part of the short list that
+// is sorted. If still not found, it does a linear search
+// on the unsorted part of the short list.
+//
+//--------------------------------------------------------------------------
+DWORDPAIR *CScmGuidMap::SearchShortList(DWORD dwFind)
+{
+ // we do a binary search in the short list because we know
+ // they are in numerical order.
+
+ LONG lLow = 0;
+ LONG lHigh = _pGuidMap->ulCntShort;
+
+ while (lLow <= lHigh)
+ {
+ LONG lGuess = (lLow + lHigh) / 2;
+ DWORDPAIR *pCurr = _pShortList + lGuess;
+
+ if (pCurr->dw1 == dwFind)
+ {
+ return pCurr;
+ }
+ else if (pCurr->dw1 < dwFind)
+ {
+ lLow = lGuess + 1;
+ }
+ else
+ {
+ lHigh = lGuess - 1;
+ }
+ }
+
+ // not found, look in the overflow area. This is where new guids
+ // are added when the registry is updated while the SCM is running
+
+ DWORDPAIR *pCurr = _pShortList + _pGuidMap->ulCntShort;
+ DWORDPAIR *pEnd = pCurr + _pGuidMap->ulCntShortOverFlow;
+
+ while (pCurr < pEnd)
+ {
+ if (pCurr->dw1 == dwFind)
+ {
+ return pCurr;
+ }
+ pCurr++;
+ }
+
+ return NULL;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmGuidMap::SearchLongList
+//
+// Synopsis: searches the long list for a matching entry and returns
+// a pointer to the found element, or NULL.
+//
+// Arguments: [rguid] - the GUID we want to find
+//
+// Returns: ptr to matching entry if found, NULL otherwise.
+//
+// Algorithm: does a binary search on the part of the long list that
+// is sorted. If still not found, it does a linear search
+// on the unsorted part of the long list.
+//
+//--------------------------------------------------------------------------
+GUIDPAIR *CScmGuidMap::SearchLongList(REFGUID rguid)
+{
+ // we do a binary search in the long list because we know
+ // they are in reversed numerical order.
+
+ LONG lLow = 0;
+ LONG lHigh = _pGuidMap->ulCntLong;
+
+ while (lLow <= lHigh)
+ {
+ LONG lGuess = (lLow + lHigh) / 2;
+ GUIDPAIR *pCurr = _pLongList - lGuess;
+
+ int iRes = memcmp(&pCurr->guid1, &rguid, sizeof(GUID));
+ if (iRes == 0)
+ {
+ return pCurr;
+ }
+ else if (iRes < 0)
+ {
+ lLow = lGuess + 1;
+ }
+ else
+ {
+ lHigh = lGuess - 1;
+ }
+ }
+
+ // not found, look in the overflow area. This is where new guids
+ // are added when the registry is updated while the SCM is running
+
+ GUIDPAIR *pCurr = _pLongList - _pGuidMap->ulCntLong;
+ GUIDPAIR *pEnd = pCurr - _pGuidMap->ulCntLongOverFlow;
+
+ while (pCurr > pEnd)
+ {
+ if (memcmp(&pCurr->guid1, &rguid, sizeof(GUID)))
+ {
+ return pCurr;
+ }
+ pCurr--;
+ }
+
+ return NULL;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmGuidMap::Find
+//
+// Synopsis: Searches the map for a matching guid and copies the
+// mapped to value into pGuidOut.
+//
+// Arguments: [rguid] - the guid to find.
+// [pGuidOut] - place to store the resulting guid
+//
+// Returns: ptr to guid if found, NULL otherwise.
+//
+// Algorithm: If the guid is an OLE201 style guid, we scan the short
+// table first, otherwise we skip to the long table. If it
+// is not found in the short table, we scan the long table
+// anyway, since the second guid may not be Ole2 style.
+//
+//--------------------------------------------------------------------------
+GUID *CScmGuidMap::Find(REFGUID rguid, GUID *pGuidOut)
+{
+ if (_pGuidMap)
+ {
+ if (IsOleStyleGuid(rguid))
+ {
+ // look in the short list. here we store just the first DWORD
+ // because we know what the other 3 dwords look like.
+
+ DWORDPAIR *pEntry = SearchShortList(rguid.Data1);
+ if (pEntry)
+ {
+ // found it, fill the guid to return
+ memcpy(pGuidOut, &guidOleTemplate, sizeof(GUID));
+ pGuidOut->Data1 = pEntry->dw2;
+ return pGuidOut;
+ }
+ }
+
+ // either the first guid is not OLE201 style, or we did not
+ // find a match in the short table. Scan the long table.
+
+ // have to look in the long list. here we store the entire
+ // guids because they dont look like Ole Style guids.
+
+ GUIDPAIR *pEntry = SearchLongList(rguid);
+ if (pEntry)
+ {
+ memcpy(pGuidOut, &pEntry->guid2, sizeof(GUID));
+ return pGuidOut;
+ }
+ }
+
+ return NULL;
+}
diff --git a/private/ole32/com/inc/guidmap.hxx b/private/ole32/com/inc/guidmap.hxx
new file mode 100644
index 000000000..7ebf806ae
--- /dev/null
+++ b/private/ole32/com/inc/guidmap.hxx
@@ -0,0 +1,373 @@
+//+---------------------------------------------------------------------------//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: guidmap.hxx
+//
+// Contents: IID to proxy/stub CLSID mapping cache
+//
+// Classes: CScmGuidMap - shared memory guid map
+//
+// Functions: none
+//
+// History: 07-Apr-94 Rickhi Created
+//
+// Notes: this class maintains an IID to CLSID mapping table
+// in shared memory.
+//
+//----------------------------------------------------------------------------
+
+// function prototypes
+extern HANDLE CreateSharedFileMapping(TCHAR *pszName, ULONG ulSize, void *pvBase,
+ PSECURITY_DESCRIPTOR lpSecDes, void **ppv, BOOL *pfCreated);
+
+extern HANDLE OpenSharedFileMapping(TCHAR *pszName, ULONG ulSize, void **ppv);
+
+void CloseSharedFileMapping(HANDLE hMem, void *pv);
+
+
+// name and size of shared memory region
+#define IIDMAP_NAME L"PSClsidMapName"
+#define IIDMAP_SIZE 4096
+
+
+typedef struct tagDWORDPAIR
+{
+ DWORD dw1; // IID
+ DWORD dw2; // CLSID
+} DWORDPAIR;
+
+typedef struct tagGUIDPAIR
+{
+ GUID guid1; // IID
+ GUID guid2; // CLSID
+} GUIDPAIR;
+
+
+typedef struct tagGUIDMAP
+{
+ ULONG ulCntShort; // number of entries in the short list
+ ULONG ulCntLong; // number of entries in the long list
+ ULONG ulCntShortOverFlow; // number of entries in short overflow
+ ULONG ulCntLongOverFlow; // number of entries in long overflow
+ DWORDPAIR DwordStart; // first entry in the list
+} GUIDMAP;
+
+
+// template for OLE201 style guids
+const GUID guidOleTemplate =
+ {0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
+
+
+
+//+---------------------------------------------------------------------------
+//
+// class: CScmGuidMap
+//
+// synopsis: shared memory cache of IID to PSCLSID mappings
+//
+// Classes: CScmGuidMap
+//
+// History: 06-Apr-94 Rickhi Created
+//
+// Notes: this maintains a list of IID to CLSID mappings in shared mem.
+// this list is used by ole32.dll when loading interface proxies
+// and stubs, and we want to avoid random registry hits.
+//
+// the SCM creates the list and is the only one who can modify
+// the shared memory. the clients are simply read only. the
+// SCM updates it when the registry changes.
+//
+// for OLE20 style guids that change only in the first DWORD,
+// we store only the first DWORD instead of the whole GUID,
+// giving us 4-1 compression for the (currently) common case.
+//
+// the DWORD cache starts at the beginning of the shared mem
+// and grows up, the GUID cache starts at the end of the shared
+// mem and grows down, giving us the maximum capacity.
+//
+//----------------------------------------------------------------------------
+
+class CScmGuidMap
+{
+public:
+ CScmGuidMap(BOOL fCreate);
+ ~CScmGuidMap();
+
+ void Add(REFGUID rguid1, REFGUID rguid2, BOOL fReload);
+ GUID * Find(REFGUID rguid, GUID *pGuidOut);
+ BOOL IsFull();
+
+private:
+
+ BOOL IsOleStyleGuid(REFGUID rguid1);
+ ULONG FreeSpace();
+ DWORDPAIR * SearchShortList(DWORD dwFind);
+ GUIDPAIR * SearchLongList(REFGUID rguid);
+
+
+ HANDLE _hMem;
+ GUIDMAP * _pGuidMap;
+
+ DWORDPAIR * _pShortList; // list of OLE style guids
+ GUIDPAIR * _pLongList; // list of non OLE style guids
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmGuidMap::CScmGuidMap
+//
+// Synopsis: Creates or gets access to memory mapped file.
+//
+// Arguments: [fCreate] - TRUE = create file mapping, FALSE = open
+//
+// Algorithm: if fCreate it creates and intializes the shared file mapping,
+// otherwise it opens it.
+//
+//--------------------------------------------------------------------------
+inline CScmGuidMap::CScmGuidMap(BOOL fCreate) :
+ _pGuidMap(NULL),
+ _hMem(NULL)
+{
+ if (!fCreate)
+ {
+ // ole32 client. just open the shared memory
+ _hMem = OpenSharedFileMapping(IIDMAP_NAME, IIDMAP_SIZE, (void **)&_pGuidMap);
+ }
+ else
+ {
+ // scm. create the file mapping
+ _hMem = CreateSharedFileMapping(IIDMAP_NAME, IIDMAP_SIZE, NULL, NULL,
+ (void **)&_pGuidMap, NULL);
+ if (_pGuidMap)
+ {
+ _pGuidMap->ulCntShort = 0;
+ _pGuidMap->ulCntLong = 0;
+ _pGuidMap->ulCntShortOverFlow = 0;
+ _pGuidMap->ulCntLongOverFlow = 0;
+ }
+ }
+
+ if (_pGuidMap)
+ {
+ _pShortList = &_pGuidMap->DwordStart;
+ _pLongList = (GUIDPAIR *) (((BYTE *)_pGuidMap) +
+ IIDMAP_SIZE - sizeof(GUIDPAIR));
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmGuidMap::~CScmGuidMap
+//
+// Synopsis: unmaps file mapping and closes the handle
+//
+// Algorithm: calls CloseSharedFileMapping to unmap the view and close the
+// file handle.
+//
+//--------------------------------------------------------------------------
+inline CScmGuidMap::~CScmGuidMap()
+{
+ CloseSharedFileMapping(_hMem, _pGuidMap);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmGuidMap::IsOleStyleGuid
+//
+// Synopsis: determines if the GUID is one of the OLE201 style guids
+//
+// Arguments: [rguid] - guid to check
+//
+// Returns: TRUE if OLE20 style guid, FALSE otherwise.
+//
+// Algorithm: If the last 3 dwords of the GUID match the ones uses by all
+// OLE20 guids, then this returns TRUE, otherwise FALSE
+//
+//--------------------------------------------------------------------------
+inline BOOL CScmGuidMap::IsOleStyleGuid(REFGUID rguid)
+{
+ const DWORD *ptr = &rguid.Data1;
+
+ return (*(ptr+1) == 0x00000000 && // all ole sytle guids's have
+ *(ptr+2) == 0x000000C0 && // these common values
+ *(ptr+3) == 0x46000000);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmGuidMap::IsFull
+//
+// Synopsis: returns TRUE if there is no room in the table
+//
+// Algorithm: compares FreeSpace with the size of the largest entry we
+// might need to make.
+//
+//--------------------------------------------------------------------------
+inline BOOL CScmGuidMap::IsFull()
+{
+ return ((FreeSpace() - sizeof(GUIDPAIR)) < 0);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmGuidMap::Add
+//
+// Synopsis: Adds a new entry to the table.
+//
+// Arguments: [rguid1] - the IID to add
+// [rguid2] - the CLSID to map the IID to
+// [fReload] - TRUE if reloading the cache due to registry
+// changes.
+//
+// Algorithm: This is called only be the SCM, no one else has write access
+// to the memory.
+//
+// If fReload is set, we scan the list to ensure there are no
+// duplicates before adding the new one. Note that we NEVER
+// REPLACE any existing guid, as doing so while the system is
+// running will have unpredicatable results.
+//
+// If boths guids are OLE201 style guids, we only store the
+// first DWORD of each guid in the short table.
+//
+// If either one is not an OLE201 style guid, we store the
+// whole guids in the long table.
+//
+// Note: This function is inline because it is used in only one place
+// (in SCM.EXE LoadIIDMap).
+//
+//--------------------------------------------------------------------------
+inline void CScmGuidMap::Add(REFGUID rguid1, REFGUID rguid2, BOOL fReload)
+{
+ Win4Assert(_pGuidMap &&
+ "CScmGuidMap should have already created shared memory!");
+
+ if (_pGuidMap)
+ {
+ if (fReload)
+ {
+ // if reloading, we must check for duplicates before
+ // placing this entry in the tables.
+ GUID guidDummy;
+ if (Find(rguid1, &guidDummy))
+ return;
+ }
+
+
+ if (IsOleStyleGuid(rguid1) && IsOleStyleGuid(rguid2))
+ {
+ // start by placing it at the end of the short table
+
+ if (FreeSpace() < sizeof(DWORDPAIR))
+ {
+ CairoleDebugOut((DEB_WARN,
+ "CScmGuidMap table is FULL. For efficiency, table size should be increased.\n"));
+ return;
+ }
+
+ DWORDPAIR *pInsertSlot = _pShortList + _pGuidMap->ulCntShort +
+ _pGuidMap->ulCntShortOverFlow;
+#if DBG==1
+ WCHAR wszBuf[80];
+ StringFromIID2(rguid1, wszBuf, sizeof(wszBuf));
+ CairoleDebugOut((DEB_USER2, "PSClsidMap adding key: %ws\n", wszBuf));
+#endif
+
+ if (!fReload)
+ {
+ // must ensure the initial list remains sorted, so go find
+ // the insertion slot.
+
+ DWORDPAIR *pPrev = pInsertSlot - 1;
+
+ while (pPrev >= _pShortList && pPrev->dw1 > rguid1.Data1)
+ {
+ // move the data from the previous slot to the current
+ // insert slot, and make the previous slot the current
+ // insert slot.
+
+ pInsertSlot->dw1 = pPrev->dw1;
+ pInsertSlot->dw2 = pPrev->dw2;
+ pInsertSlot--;
+ pPrev--;
+ }
+ }
+
+ // found the insertion slot, copy in the data
+ pInsertSlot->dw1 = rguid1.Data1;
+ pInsertSlot->dw2 = rguid2.Data1;
+
+ // only after we've copied the data do we inc the count.
+ // this is important to avoid races in the Reload case.
+
+ if (fReload)
+ _pGuidMap->ulCntShortOverFlow++;
+ else
+ _pGuidMap->ulCntShort++;
+
+ }
+ else
+ {
+ // put it in the long table
+
+ if (FreeSpace() < sizeof(GUIDPAIR))
+ {
+ CairoleDebugOut((DEB_WARN,
+ "CScmGuidMap table is FULL. For efficiency, table size should be increased.\n"));
+ return;
+ }
+
+#if DBG==1
+ WCHAR wszBuf[80];
+ StringFromIID2(rguid1, wszBuf, sizeof(wszBuf));
+ CairoleDebugOut((DEB_USER2, "PSClsidMap adding key: %ws\n", wszBuf));
+#endif
+
+ GUIDPAIR *pInsertSlot = _pLongList - _pGuidMap->ulCntLong;
+
+ if (!fReload)
+ {
+ // must ensure initial list remains sorted, so go find the
+ // insertion spot.
+
+ GUIDPAIR *pPrev = pInsertSlot + 1;
+
+ while (pPrev <= _pLongList &&
+ (memcmp(&pPrev->guid1, &rguid1, sizeof(GUID)) > 0))
+ {
+ // move both guids up in the table, and make the previous
+ // slot the current insert slot.
+
+ memcpy(&pInsertSlot->guid1, &pPrev->guid1, 2*sizeof(GUID));
+ pInsertSlot++;
+ pPrev++;
+ }
+
+ }
+
+ // found the insertion slot, so copy in the data
+ memcpy(&pInsertSlot->guid1, &rguid1, sizeof(GUID));
+ memcpy(&pInsertSlot->guid2, &rguid2, sizeof(GUID));
+
+ // only after we've copied the data do we inc the count.
+ // this is important to avoid races in the Reload case.
+
+ if (fReload)
+ _pGuidMap->ulCntLongOverFlow++;
+ else
+ _pGuidMap->ulCntLong++;
+ }
+ }
+}
+
+
+// global pointer to this map
+extern CScmGuidMap *g_pPSClsidMap;
diff --git a/private/ole32/com/inc/longname.h b/private/ole32/com/inc/longname.h
new file mode 100644
index 000000000..74f4b245b
--- /dev/null
+++ b/private/ole32/com/inc/longname.h
@@ -0,0 +1,33 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: longname.h
+//
+// Contents: GetLongPathName
+//
+// History: 25-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __LONGNAME_H__
+#define __LONGNAME_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DWORD
+APIENTRY
+GetLongPathNameW(
+ IN LPCWSTR lpszPath,
+ IN LPWSTR lpszLongPath,
+ IN DWORD cchBuffer
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef __LONGNAME_H__
diff --git a/private/ole32/com/inc/makefile b/private/ole32/com/inc/makefile
new file mode 100644
index 000000000..e09078703
--- /dev/null
+++ b/private/ole32/com/inc/makefile
@@ -0,0 +1,24 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+!include $(CAIROLE)\com\makefile
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/com/inc/malloc.hxx b/private/ole32/com/inc/malloc.hxx
new file mode 100644
index 000000000..197e29293
--- /dev/null
+++ b/private/ole32/com/inc/malloc.hxx
@@ -0,0 +1,21 @@
+//+-------------------------------------------------------------------------
+//
+// Copyright (C) 1992, Microsoft Corporation.
+//
+// File: alloc.hxx
+//
+// Contents: memory allocation functions for RPC transmission
+//
+// Functions: MIDL_user_allocate
+// MIDL_user_free
+//
+// History: 02-Sep-92 Rickhi Created
+//
+//--------------------------------------------------------------------------
+#ifndef __MIDL_ALLOC_HXX
+#define __MIDL_ALLOC_HXX
+
+extern "C" void * MIDL_user_allocate(size_t len);
+extern "C" void MIDL_user_free(void * pvMemory);
+
+#endif // __MIDL_ALLOC_HXX
diff --git a/private/ole32/com/inc/map_dwp.h b/private/ole32/com/inc/map_dwp.h
new file mode 100644
index 000000000..1a1ea8d2d
--- /dev/null
+++ b/private/ole32/com/inc/map_dwp.h
@@ -0,0 +1,66 @@
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+
+class FAR CMapDwordPtr : public CPrivAlloc
+{
+public:
+ // Construction
+ CMapDwordPtr(UINT nBlockSize=10)
+ : m_mkv(sizeof(void FAR*), sizeof(DWORD), nBlockSize) { }
+
+ // Attributes
+ // number of elements
+ int GetCount() const
+ { return m_mkv.GetCount(); }
+ BOOL IsEmpty() const
+ { return GetCount() == 0; }
+
+ // Lookup
+ BOOL Lookup(DWORD key, void FAR* FAR& value) const
+ { return m_mkv.Lookup((LPVOID)&key, sizeof(DWORD), (LPVOID)&value); }
+
+ BOOL LookupHKey(HMAPKEY hKey, void FAR* FAR& value) const
+ { return m_mkv.LookupHKey(hKey, (LPVOID)&value); }
+
+ BOOL LookupAdd(DWORD key, void FAR* FAR& value) const
+ { return m_mkv.LookupAdd((LPVOID)&key, sizeof(DWORD), (LPVOID)&value); }
+
+ // Add/Delete
+ // add a new (key, value) pair
+ BOOL SetAt(DWORD key, void FAR* value)
+ { return m_mkv.SetAt((LPVOID)&key, sizeof(DWORD), (LPVOID)&value); }
+ BOOL SetAtHKey(HMAPKEY hKey, void FAR* value)
+ { return m_mkv.SetAtHKey(hKey, (LPVOID)&value); }
+
+ // removing existing (key, ?) pair
+ BOOL RemoveKey(DWORD key)
+ { return m_mkv.RemoveKey((LPVOID)&key, sizeof(DWORD)); }
+
+ BOOL RemoveHKey(HMAPKEY hKey)
+ { return m_mkv.RemoveHKey(hKey); }
+
+ void RemoveAll()
+ { m_mkv.RemoveAll(); }
+
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return m_mkv.GetStartPosition(); }
+
+ void GetNextAssoc(POSITION FAR& rNextPosition, DWORD FAR& rKey, void FAR* FAR& rValue) const
+ { m_mkv.GetNextAssoc(&rNextPosition, (LPVOID)&rKey, NULL, (LPVOID)&rValue); }
+
+ HMAPKEY GetHKey(DWORD key) const
+ { return m_mkv.GetHKey((LPVOID)&key, sizeof(DWORD)); }
+
+#ifdef _DEBUG
+ void AssertValid() const
+ { m_mkv.AssertValid(); }
+#endif
+
+private:
+ CMapKeyToValue m_mkv;
+};
diff --git a/private/ole32/com/inc/map_gp.h b/private/ole32/com/inc/map_gp.h
new file mode 100644
index 000000000..ed4feed4a
--- /dev/null
+++ b/private/ole32/com/inc/map_gp.h
@@ -0,0 +1,66 @@
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+
+class FAR CMapGUIDToPtr
+{
+public:
+ // Construction
+ CMapGUIDToPtr(DWORD memctx = MEMCTX_SAME, UINT nBlockSize=10)
+ : m_mkv(memctx, sizeof(void FAR*), sizeof(GUID), nBlockSize) { }
+
+ // Attributes
+ // number of elements
+ int GetCount() const
+ { return m_mkv.GetCount(); }
+ BOOL IsEmpty() const
+ { return GetCount() == 0; }
+
+ // Lookup
+ BOOL Lookup(REFGUID key, void FAR* FAR& value) const
+ { return m_mkv.Lookup((LPVOID)&key, sizeof(GUID), (LPVOID)&value); }
+
+ BOOL LookupHKey(HMAPKEY hKey, void FAR* FAR& value) const
+ { return m_mkv.LookupHKey(hKey, (LPVOID)&value); }
+
+ BOOL LookupAdd(REFGUID key, void FAR* FAR& value) const
+ { return m_mkv.LookupAdd((LPVOID)&key, sizeof(GUID), (LPVOID)&value); }
+
+ // Add/Delete
+ // add a new (key, value) pair
+ BOOL SetAt(REFGUID key, void FAR* value)
+ { return m_mkv.SetAt((LPVOID)&key, sizeof(GUID), (LPVOID)&value); }
+ BOOL SetAtHKey(HMAPKEY hKey, void FAR* value)
+ { return m_mkv.SetAtHKey(hKey, (LPVOID)&value); }
+
+ // removing existing (key, ?) pair
+ BOOL RemoveKey(REFGUID key)
+ { return m_mkv.RemoveKey((LPVOID)&key, sizeof(GUID)); }
+
+ BOOL RemoveHKey(HMAPKEY hKey)
+ { return m_mkv.RemoveHKey(hKey); }
+
+ void RemoveAll()
+ { m_mkv.RemoveAll(); }
+
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return m_mkv.GetStartPosition(); }
+
+ void GetNextAssoc(POSITION FAR& rNextPosition, GUID FAR& rKey, void FAR* FAR& rValue) const
+ { m_mkv.GetNextAssoc(&rNextPosition, (LPVOID)&rKey, NULL, (LPVOID)&rValue); }
+
+ HMAPKEY GetHKey(REFGUID key) const
+ { return m_mkv.GetHKey((LPVOID)&key, sizeof(GUID)); }
+
+#ifdef _DEBUG
+ void AssertValid() const
+ { m_mkv.AssertValid(); }
+#endif
+
+private:
+ CMapKeyToValue m_mkv;
+};
diff --git a/private/ole32/com/inc/map_sp.h b/private/ole32/com/inc/map_sp.h
new file mode 100644
index 000000000..0dd2d5a2b
--- /dev/null
+++ b/private/ole32/com/inc/map_sp.h
@@ -0,0 +1,67 @@
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+
+class FAR CMapStringToPtr : public CPrivAlloc
+{
+public:
+ // Construction
+ CMapStringToPtr(UINT nBlockSize=10)
+ : m_mkv(sizeof(void FAR*), 0, nBlockSize) { }
+
+ // Attributes
+ // number of elements
+ int GetCount() const
+ { return m_mkv.GetCount(); }
+ BOOL IsEmpty() const
+ { return GetCount() == 0; }
+
+ // Lookup
+ BOOL Lookup(LPWSTR pKey, void FAR* FAR& value) const
+ { return m_mkv.Lookup(pKey, lstrlenW(pKey)*sizeof(WCHAR), &value); }
+
+ BOOL LookupHKey(HMAPKEY hKey, void FAR* FAR& value) const
+ { return m_mkv.LookupHKey(hKey, &value); }
+
+ BOOL LookupAdd(LPWSTR pKey, void FAR* FAR& value) const
+ { return m_mkv.LookupAdd(pKey, lstrlenW(pKey)*sizeof(WCHAR), &value); }
+
+
+ // Add/Delete
+ // add a new (key, value) pair
+ BOOL SetAt(LPWSTR pKey, void FAR* value)
+ { return m_mkv.SetAt(pKey, lstrlenW(pKey)*sizeof(WCHAR), (LPVOID)&value); }
+ BOOL SetAtHKey(HMAPKEY hKey, void FAR* value)
+ { return m_mkv.SetAtHKey(hKey, (LPVOID)&value); }
+
+ // removing existing (key, ?) pair
+ BOOL RemoveKey(LPWSTR pKey)
+ { return m_mkv.RemoveKey(pKey, lstrlenW(pKey)*sizeof(WCHAR)); }
+
+ BOOL RemoveHKey(HMAPKEY hKey)
+ { return m_mkv.RemoveHKey(hKey); }
+
+ void RemoveAll()
+ { m_mkv.RemoveAll(); }
+
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return m_mkv.GetStartPosition(); }
+
+ void GetNextAssoc(POSITION FAR& rNextPosition, LPWSTR FAR& pKey, void FAR* FAR& rValue) const
+ { m_mkv.GetNextAssoc(&rNextPosition, (LPVOID)&pKey, NULL, (LPVOID)&rValue); }
+
+ HMAPKEY GetHKey(LPWSTR pKey) const
+ { return m_mkv.GetHKey(pKey, lstrlenW(pKey)*sizeof(WCHAR)); }
+
+#ifdef _DEBUG
+ void AssertValid() const
+ { m_mkv.AssertValid(); }
+#endif
+
+private:
+ CMapKeyToValue m_mkv;
+};
diff --git a/private/ole32/com/inc/memdebug.hxx b/private/ole32/com/inc/memdebug.hxx
new file mode 100644
index 000000000..dff7a2afe
--- /dev/null
+++ b/private/ole32/com/inc/memdebug.hxx
@@ -0,0 +1,55 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992
+//
+// File: memdebug.hxx
+//
+// Contents: Error code handler routines
+//
+// History: 19-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __MEMDEBUG_HXX__
+#define __MEMDEBUG_HXX__
+
+#if DBG == 1
+#define ErrJmp(comp, label, errval, var) \
+{\
+ var = errval;\
+ comp##DebugOut((DEB_IERROR, "Error %lX at %s:%d\n",\
+ (unsigned long)var, __FILE__, __LINE__));\
+ goto label;\
+}
+#else
+#define ErrJmp(comp, label, errval, var) \
+{\
+ var = errval;\
+ goto label;\
+}
+#endif
+
+#define memErr(l, e) ErrJmp(mem, l, e, sc)
+#define memChkTo(l, e) if (FAILED(sc = (e))) memErr(l, sc) else 1
+#define memHChkTo(l, e) if (FAILED(sc = GetScode(e))) memErr(l, sc) else 1
+#define memChk(e) memChkTo(EH_Err, e)
+#define memHChk(e) memHChkTo(EH_Err, e)
+#define memMemTo(l, e) \
+ if ((e) == NULL) memErr(l, E_OUTOFMEMORY) else 1
+#define memMem(e) memMemTo(EH_Err, e)
+
+
+#if DBG == 1
+DECLARE_DEBUG(mem)
+
+#define memDebugOut(x) memInlineDebugOut x
+#define memAssert(x) Win4Assert(x)
+#define memVerify(x) Win4Assert(x)
+#else
+#define memDebugOut(x)
+#define memAssert(x)
+#define memVerify(x) (x)
+#endif
+
+#endif // #ifndef __MEMDEBUG_HXX__
diff --git a/private/ole32/com/inc/ole2int.h b/private/ole32/com/inc/ole2int.h
new file mode 100644
index 000000000..7087e50eb
--- /dev/null
+++ b/private/ole32/com/inc/ole2int.h
@@ -0,0 +1,383 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: ole2int.h
+//
+// Contents: internal ole2 header
+//
+// Notes: This is the internal ole2 header, which means it contains those
+// interfaces which might eventually be exposed to the outside
+// and which will be exposed to our implementations. We don't want
+// to expose these now, so I have put them in a separate file.
+//
+// History: 12-27-93 ErikGav Include uniwrap.h for Chicago builds
+//
+//----------------------------------------------------------------------------
+
+#if !defined( _OLE2INT_H_ )
+#define _OLE2INT_H_
+
+// -----------------------------------------------------------------------
+// System Includes
+// -----------------------------------------------------------------------
+//
+// Prevent lego errors under Chicago.
+//
+#if defined(_CHICAGO_)
+#define _CTYPE_DISABLE_MACROS
+#endif
+
+#ifndef _CHICAGO_
+// For TLS on Nt we use a reserved DWORD in the TEB directly. We need these
+// include files to get the macro NtCurrentTeb(). They must be included
+// before windows.h
+extern "C"
+{
+#include <nt.h> // NT_PRODUCT_TYPE
+#include <ntdef.h> // NT_PRODUCT_TYPE
+#include <ntrtl.h> // NT_PRODUCT_TYPE
+#include <nturtl.h> // NT_PRODUCT_TYPE
+#include <windef.h> // NT_PRODUCT_TYPE
+#include <winbase.h> // NT_PRODUCT_TYPE
+}
+#endif // _CHICAGO_
+
+#include <wchar.h>
+#include <StdLib.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+// Cairo builds use DBG==1; old OLE2 code used _DEBUG
+#if DBG == 1
+#define _DEBUG
+#endif
+
+
+// Guarantee that WIN32 is defined.
+#ifndef WIN32
+#define WIN32 100
+#endif
+
+
+#ifdef WIN32
+#include <pcrt32.h>
+#endif // WIN32
+
+
+// BUGBUG: Where should this really go?
+#define BEGIN_BLOCK do {
+#define EXIT_BLOCK break
+#define END_BLOCK }while(FALSE);
+
+
+#include <windows.h>
+#include <olecom.h>
+#include <malloc.h>
+#include <shellapi.h>
+
+
+// -----------------------------------------------------------------------
+// Debug Aids
+// -----------------------------------------------------------------------
+
+#define ComDebOut CairoleDebugOut
+
+#if DBG==1
+
+#include <debnot.h>
+
+// recast the user mode debug flags to meaningfull names. These are
+// used in xDebugOut calls.
+#define DEB_DLL 0x0008 // DLL Load/Unload
+#define DEB_CHANNEL DEB_USER1 // rpc channel
+#define DEB_DDE DEB_USER2 // dde
+#define DEB_CALLCONT DEB_USER3 // call control & msg filter
+#define DEB_MARSHAL DEB_USER4 // interface marshalling
+#define DEB_SCM DEB_USER5 // rpc calls to the SCM
+#define DEB_ROT DEB_USER6 // running object table
+#define DEB_ACTIVATE DEB_USER7 // object activation
+#define DEB_OXID DEB_USER8 // OXID stuff
+#define DEB_REG DEB_USER9 // registry calls
+#define DEB_COMPOBJ DEB_USER10 // misc compobj
+#define DEB_MEMORY DEB_USER11 // memory allocations
+#define DEB_RPCSPY DEB_USER12 // rpc spy to debug output
+#define DEB_MFILTER DEB_USER13 // message filter
+#define DEB_ENDPNT DEB_USER13 // endpoint stuff
+#define DEB_PAGE DEB_USER14 // page allocator
+
+#define ComDebErr(failed, msg) if (failed) { ComDebOut((DEB_ERROR, msg)); }
+
+#else // DBG
+
+#define ComDebErr(failed, msg)
+
+#endif // DBG
+
+
+#ifdef DCOM
+//-------------------------------------------------------------------
+//
+// class: CDbgGuidStr
+//
+// Synopsis: Class to convert guids to strings in debug builds for
+// debug outs
+//
+//--------------------------------------------------------------------
+class CDbgGuidStr
+{
+public:
+ ~CDbgGuidStr() {}
+#if DBG==1
+ CDbgGuidStr(REFGUID rguid) { StringFromGUID2(rguid, _wszGuid, 40); }
+ WCHAR _wszGuid[40];
+#else
+ CDbgGuidStr(REFGUID rguid) {}
+#endif
+};
+#endif
+
+
+// -----------------------------------------------------------------------
+// Public Includes
+// -----------------------------------------------------------------------
+#include <ole2.h>
+
+// BUGBUG: prevent scode.h from being included. remove at some point since
+// scode.h must go away.
+#define __SCODE_H__
+
+#include <ole2sp.h>
+#include <ole2com.h>
+
+
+// -----------------------------------------------------------------------
+// Internal Includes
+// -----------------------------------------------------------------------
+#include <utils.h>
+#include <olecoll.h>
+#include <valid.h>
+#include <array_fv.h>
+#include <map_kv.h>
+#include <privguid.h>
+#include <tls.h>
+#include <tracelog.hxx>
+#include <memapi.hxx>
+
+// We are Unicode enabled
+// #define _DBCS
+
+// Macros for Double-Byte Character Support (DBCS)
+#ifdef _DBCS
+ #ifdef _MAC
+ #define IncLpch IncLpch
+ #define DecLpch DecLpch
+ #else
+ // Beware of double evaluation
+ #define IncLpch(sz) ((sz)=AnsiNext((sz)))
+ #define DecLpch(szStart, sz) ((sz)=AnsiPrev ((szStart),(sz)))
+ #endif
+#else
+ #define IncLpch(sz) (++(sz))
+ #define DecLpch(szStart,sz) (--(sz))
+#endif
+
+// -----------------------------------------------------------------------
+// DDE Externs
+//
+// The following routines support the DDE server window. They are
+// implemented in objact
+//
+// The following structure is passed to the class factory table
+// to retrieve information about a registered class factory.
+//
+// The routine that finally fills in this structure is in
+// CClsRegistration::GetClassObjForDde.
+//
+// -----------------------------------------------------------------------
+
+typedef struct _tagDdeClassInfo
+{
+ // Filled in by the caller
+ DWORD dwContextMask; // Class context to search for
+ BOOL fClaimFactory; // True if class factory to be
+ // returned in punk
+
+ // Filled in by callee
+ DWORD dwContext; // Context registered
+ DWORD dwFlags; // Use flags registered
+ DWORD dwThreadId; // ThreadID registered
+ DWORD dwRegistrationKey; // Key for registration.
+ // Used later for calling SetDdeServerWindow
+
+ IUnknown * punk; // Pointer to class factory
+
+} DdeClassInfo;
+
+typedef DdeClassInfo * LPDDECLASSINFO;
+
+BOOL GetClassInformationForDde( REFCLSID clsid,
+ LPDDECLASSINFO lpDdeInfo);
+
+BOOL SetDdeServerWindow( DWORD dwKey,
+ HWND hwndDdeServer);
+
+BOOL GetClassInformationFromKey(LPDDECLASSINFO lpDdeInfo);
+
+//
+// This function is shared between the DDE layer and the ROT
+//
+
+HRESULT GetLocalRunningObjectForDde(LPOLESTR lpstrPath,
+ LPUNKNOWN * ppunkObject);
+
+
+
+// -----------------------------------------------------------------------
+// Activation Externs
+// -----------------------------------------------------------------------
+
+#include <olerem.h>
+#include <iface.h>
+
+// Internal version of CoGetClassObject without parameter validation.
+STDAPI IOldCoGetClassObject(
+ REFCLSID rclsid,
+ DWORD dwContext,
+ LPVOID pvReserved,
+ REFIID riid,
+ void FAR* FAR* ppvClassObj);
+
+#ifdef DCOM
+// Internal version of CoGetClassObject without parameter validation.
+STDAPI ICoGetClassObject(
+ REFCLSID rclsid,
+ DWORD dwContext,
+ COSERVERINFO * pvReserved,
+ REFIID riid,
+ void FAR* FAR* ppvClassObj);
+#else
+#define ICoGetClassObject(a,b,c,d,e) IOldCoGetClassObject((a),(b),(c),(d),(e))
+#endif // DCOM
+
+// Internal COM Init/Uninit routines
+INTERNAL wCoInitializeEx(COleTls &Tls, DWORD flags);
+INTERNAL_(void) wCoUninitialize(COleTls &Tls, BOOL fHostThread);
+
+// Main thread Init/Uninit routines
+BOOL InitMainThreadWnd(void);
+void UninitMainThreadWnd(void);
+
+// Main thread window handle and TID
+extern HWND hwndOleMainThread;
+extern DWORD gdwMainThreadId;
+
+// called by marshaling code on first marshal/last release of ICF interface
+INTERNAL_(BOOL) NotifyActivation(BOOL fLock, IUnknown *pUnk);
+
+// flag value used by the Activation ObjServer in ServerGetClassObject
+const DWORD MSHLFLAGS_NOTIFYACTIVATION = 0x80000000;
+
+
+// global count of per-process COM initializations
+extern DWORD g_cProcessInits;
+
+
+// Messages on OLE windows. RPC MSWMSG uses other values too.
+// Messages Sent/Posted by OLE should have the magic value in WPARAM as this
+// is used by USER32 to enable/diable SetForegroundWindow. The magic value is
+// also in ntuser\kernel\userk.h.
+const DWORD WMSG_MAGIC_VALUE = 0x0000babe;
+
+const UINT WM_OLE_ORPC_POST = (WM_USER + 0);
+const UINT WM_OLE_ORPC_SEND = (WM_USER + 1);
+const UINT WM_OLE_ORPC_DONE = (WM_USER + 2);
+const UINT WM_OLE_ORPC_RELRIFREF = (WM_USER + 3);
+const UINT WM_OLE_ORPC_NOTIFY = (WM_USER + 4);
+const UINT WM_OLE_GETCLASS = (WM_USER + 5);
+
+
+LRESULT OleMainThreadWndProc(HWND hWnd, UINT message,
+ WPARAM wParam, LPARAM lParam);
+
+extern DWORD gdwScmProcessID;
+
+#ifdef _CHICAGO_
+// Chicago presents this new interface for internal use
+STDAPI CoCreateAlmostGuid(GUID *pGuid);
+#endif
+
+
+// -----------------------------------------------------------------------
+// ORPC Externs
+// -----------------------------------------------------------------------
+
+#include <sem.hxx>
+#include <olesem.hxx>
+extern COleStaticMutexSem g_mxsSingleThreadOle;
+extern COleStaticMutexSem gmxsOleMisc;
+
+STDAPI_(BOOL) ThreadNotification(HINSTANCE, DWORD, LPVOID);
+STDAPI ChannelRegisterProtseq(WCHAR *pwszProtseq);
+
+STDAPI ChannelProcessInitialize ();
+STDAPI ChannelThreadInitialize ();
+STDAPI_(void) ChannelProcessUninitialize( void );
+STDAPI_(void) ChannelThreadUninitialize ( void );
+STDAPI_(void) ThreadStop ( void );
+
+STDAPI_(void) ObjactThreadUninitialize(void);
+
+INTERNAL_(void) IDTableThreadUninitialize(void);
+INTERNAL_(void) IDTableProcessUninitialize(void);
+
+#ifdef DCOM
+extern BOOL gSpeedOverMem;
+#else
+STDAPI_(void) ChannelStopListening(void);
+STDAPI ChannelControlProcessInitialize(void);
+STDAPI_(void) ChannelControlThreadUninitialize(void);
+STDAPI_(void) ChannelControlProcessUninitialize(void);
+#endif
+
+
+#ifdef DCOM
+// -----------------------------------------------------------------------
+// Marshalling Externs
+// -----------------------------------------------------------------------
+
+// internal subroutines used by COXIDTable ResolveOXID and GetLocalEntry.
+INTERNAL MarshalInternalObjRef (OBJREF &objref, REFIID riid, void *pv,
+ DWORD mshlflags, void **ppStdId);
+INTERNAL MarshalObjRef (OBJREF &objref, REFIID riid, LPVOID pv,
+ DWORD mshlflags);
+INTERNAL UnmarshalInternalObjRef(OBJREF &objref, void **ppv);
+INTERNAL UnmarshalObjRef (OBJREF &objref, void **ppv);
+INTERNAL ReleaseMarshalObjRef (OBJREF &objref);
+
+// internal routines used by Drag & Drop
+INTERNAL_(void) FreeObjRef (OBJREF &objref);
+INTERNAL CompleteObjRef (OBJREF &objref, OXID_INFO &oxidInfo, REFIID riid, BOOL *pfLocal);
+INTERNAL FillLocalOXIDInfo(OBJREF &objref, OXID_INFO &oxidInfo);
+
+// internal subroutine used by CRpcResolver
+INTERNAL InitChannelIfNecessary();
+
+// Internal routines used by objact
+BOOL CheckObjactAccess();
+INTERNAL HandleIncomingCall(REFIID riid, WORD iMethod, DWORD CallCatIn, void *pv);
+
+
+#endif // DCOM
+
+// -----------------------------------------------------------------------
+// Access Control Externs
+// -----------------------------------------------------------------------
+
+HRESULT ComDllGetClassObject ( REFCLSID clsid, REFIID riid, void **ppv );
+HRESULT InitializeAccessControl ();
+void UninitializeAccessControl();
+
+#endif // _OLE2INT_H_
diff --git a/private/ole32/com/inc/olecom.h b/private/ole32/com/inc/olecom.h
new file mode 100644
index 000000000..37ce5d2e6
--- /dev/null
+++ b/private/ole32/com/inc/olecom.h
@@ -0,0 +1,56 @@
+//+-------------------------------------------------------------------
+//
+// File: olecom.hxx
+//
+// Contents: General includes for common library in ole\src project
+//
+// Classes: None
+//
+// Functions: None.
+//
+// History: 06-Jan-92 Rickhi Created
+//
+//--------------------------------------------------------------------
+#ifndef __OLECOM_H__
+#define __OLECOM_H__
+
+// Need for debugging headers
+#include <except.hxx>
+
+#if DBG==1
+DECLARE_DEBUG(Cairole)
+
+#define CairoleDebugOut(x) CairoleInlineDebugOut x
+#define CairoleAssert(x) Win4Assert(x)
+#define CairoleVerify(x) Win4Assert(x)
+
+extern "C" void brkpt(void);
+
+#else
+
+#define CairoleDebugOut(x)
+#define CairoleAssert(x)
+#define CairoleVerify(x) (x)
+
+#endif // DBG
+
+#if DBG==1
+DECLARE_DEBUG(intr)
+
+#define intrDebugOut(x) intrInlineDebugOut x
+#define intrAssert(x) Win4Assert(x)
+#define intrVerify(x) Win4Assert(x)
+
+extern "C" void brkpt(void);
+
+#else
+
+#define intrDebugOut(x)
+#define intrAssert(x)
+#define intrVerify(x) (x)
+
+#endif // DBG
+
+
+
+#endif // __OLECOM_H__
diff --git a/private/ole32/com/inc/olereg.h b/private/ole32/com/inc/olereg.h
new file mode 100644
index 000000000..2305cb0cd
--- /dev/null
+++ b/private/ole32/com/inc/olereg.h
@@ -0,0 +1,32 @@
+/* olereg.h
+
+ Registration database helper functions
+ Jason Fuller (jasonful) 16-November-1992
+
+ These functions are candidates for export
+
+*/
+
+FARINTERNAL OleRegGetUserType
+ (REFCLSID clsid,
+ DWORD dwFormOfType,
+ LPWSTR FAR* pszUserType)
+;
+
+
+FARINTERNAL OleRegGetMiscStatus
+ (REFCLSID clsid,
+ DWORD dwAspect,
+ DWORD FAR* pdwStatus)
+;
+
+FARINTERNAL OleRegEnumFormatEtc
+ (REFCLSID clsid,
+ DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenum)
+;
+
+FARINTERNAL OleRegEnumVerbs
+ (REFCLSID clsid,
+ LPENUMOLEVERB FAR* ppenum)
+;
diff --git a/private/ole32/com/inc/olespy.hxx b/private/ole32/com/inc/olespy.hxx
new file mode 100644
index 000000000..9e06b5b9e
--- /dev/null
+++ b/private/ole32/com/inc/olespy.hxx
@@ -0,0 +1,66 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: OleSpy.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+// Note: Can be turned on via CairOle InfoLelevel mask 0x08000000
+//
+//----------------------------------------------------------------------------
+
+#ifndef _OLESPY_HXX_
+#define _OLESPY_HXX_
+
+typedef struct _INTERFACENAMES
+{
+ char *pszInterface;
+ char **ppszMethodNames;
+} INTERFACENAMES;
+
+extern INTERFACENAMES inInterfaceNames[];
+extern char *apszApiNames[];
+
+typedef enum
+{
+ CALLIN_BEGIN =1,
+ CALLIN_TRACE,
+ CALLIN_ERROR,
+ CALLIN_QI,
+ CALLIN_END,
+ CALLOUT_BEGIN,
+ CALLOUT_TRACE,
+ CALLOUT_ERROR,
+ CALLOUT_END
+} RPCSPYMODE;
+
+
+#define OLESPY_TRACE 1
+#define OLESPY_CLIENT 2
+
+#if DBG==1
+
+HRESULT InitializeOleSpy(DWORD dwLevel);
+HRESULT UninitializeOleSpy(DWORD dwLevel);
+
+void RpcSpyOutput(RPCSPYMODE mode, LPVOID pv, REFIID iid, DWORD dwMethod, HRESULT hres);
+#define RpcSpy(x) RpcSpyOutput x
+
+#else
+
+#define RpcSpy(x)
+#define InitializeOleSpy(x)
+#define UninitializeOleSpy(x)
+
+#endif // DBG==1
+
+
+#endif // _OLESPY_HXX_
diff --git a/private/ole32/com/inc/pathkey.cxx b/private/ole32/com/inc/pathkey.cxx
new file mode 100644
index 000000000..fd19755ec
--- /dev/null
+++ b/private/ole32/com/inc/pathkey.cxx
@@ -0,0 +1,89 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: pathkey.cxx
+//
+// Contents: static definitions used by string key class
+//
+// History: 09-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include "pathkey.hxx"
+
+// BUGBUG: Is this key "max" enough?
+WCHAR wszMaxPath[] = {0xFFFF, 0xFFFF, 0};
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPathBaseKey::CPathBaseKey
+//
+// Synopsis: Construct key from path
+//
+// Arguments: [pwszPath] - path to use for the key
+//
+// History: 09-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+CPathBaseKey::CPathBaseKey(const WCHAR *pwszPath)
+{
+ _cPath = (lstrlenW(pwszPath) + 1) * sizeof(WCHAR);
+ _pwszPath = (WCHAR *) PrivMemAlloc(_cPath);
+
+ // Check for out of memory
+ if (_pwszPath != NULL)
+ {
+ // Copy in path
+ memcpy(_pwszPath, pwszPath, _cPath);
+ }
+ else
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CPathBaseKey::CPathBaseKey Alloc of path failed\n"));
+ _cPath = 0;
+ }
+#if DBG==1
+ _ulSig = PATHBASEKEYSIG;
+#endif
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPathBaseKey::CPathBaseKey
+//
+// Synopsis: Construct key from another key
+//
+// Arguments: [pwszPath] - path to use for the key
+//
+// History: 09-May-93 Ricksa Created
+//
+// Notes: We must explicitly define the copy constructor
+// because of the current implementation of exception
+// handling.
+//
+//--------------------------------------------------------------------------
+
+CPathBaseKey::CPathBaseKey(const CPathBaseKey& cpthbky)
+{
+ _cPath = cpthbky._cPath;
+ _pwszPath = (WCHAR *) PrivMemAlloc(_cPath);
+
+ // Check for out of memory
+ if (_pwszPath != NULL)
+ {
+ memcpy(_pwszPath, cpthbky._pwszPath, cpthbky._cPath);
+ }
+ else
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CPathBaseKey::CPathBaseKey Alloc of path failed\n"));
+ _cPath = 0;
+ }
+#if DBG==1
+ _ulSig = PATHBASEKEYSIG;
+#endif
+}
+
diff --git a/private/ole32/com/inc/pathkey.hxx b/private/ole32/com/inc/pathkey.hxx
new file mode 100644
index 000000000..0d7bfd9e7
--- /dev/null
+++ b/private/ole32/com/inc/pathkey.hxx
@@ -0,0 +1,143 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: pathkey.hxx
+//
+// Contents: classes which implement a string key entry for a skip list
+//
+// Classes: CPathBaseKey
+//
+// Functions: CPathBaseKey::CPathBaseKey
+// CPathBaseKey::~CPathBaseKey
+// CPathBaseKey::Compare
+// CPathBaseKey::GetPath
+//
+// History: 09-May-93 Ricksa Created
+// 21-Jum-94 BruceMa Check allocated memory pointers
+// 26-Jun-94 BruceMa Memory sift fixes
+// 03-Nov-94 BillMo Signatures to catch skiplist void*
+//
+//--------------------------------------------------------------------------
+
+#ifndef __PATHKEY_HXX__
+#define __PATHKEY_HXX__
+
+#include <skiplist.hxx>
+
+#define PATHBASEKEYSIG 0x504B4944
+
+//+-------------------------------------------------------------------------
+//
+// Class: CPathBaseKey (cpthbky)
+//
+// Purpose: String key class for a base of a skip list
+//
+// Interface: Compare - comparison operator on paths
+// GetPath - return path to server
+// AddRef - add a reference to this object
+//
+// History: 09-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+class CPathBaseKey : public CPrivAlloc
+{
+public:
+ CPathBaseKey(const CPathBaseKey& cpthbky);
+
+ CPathBaseKey(const WCHAR *pwszPath);
+
+ virtual ~CPathBaseKey(void);
+
+ int Compare(const CPathBaseKey& cstrid) const;
+
+ const WCHAR * GetPath(void) const;
+
+private:
+
+ // Length of path in bytes stored in the object
+ int _cPath;
+
+#if DBG==1
+ ULONG _ulSig;
+#endif
+
+protected:
+
+ // Buffer big enough to store the path
+ WCHAR * _pwszPath;
+};
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPathBaseKey::~CPathBaseKey
+//
+// Synopsis: Free object
+//
+// History: 09-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CPathBaseKey::~CPathBaseKey(void)
+{
+ delete _pwszPath;
+#if DBG==1
+ Win4Assert(_ulSig == PATHBASEKEYSIG);
+ _ulSig = 0xd1d2d3d4;
+#endif
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPathBaseKey::Compare
+//
+// Synopsis: Compare two keys
+//
+// Arguments: [pwszPath] - path to use for the key
+//
+// Returns: 0 = Two keys are equal
+// < 0 implies object key is less
+// > 0 implies object key is greater
+//
+// History: 09-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline int CPathBaseKey::Compare(const CPathBaseKey& cpthbky) const
+{
+ int cCmp = (_cPath < cpthbky._cPath) ? _cPath : cpthbky._cPath;
+
+ Win4Assert(_ulSig == PATHBASEKEYSIG);
+
+ // Note that the _cPath includes the trailing NULL so if the
+ // memcmp returns 0 the strings are equal.
+ return memcmp(_pwszPath, cpthbky._pwszPath, cCmp);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPathBaseKey::CPathBaseKey
+//
+// Synopsis: Construct key from path
+//
+// Returns: Pointer to path in key
+//
+// History: 09-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline const WCHAR *CPathBaseKey::GetPath(void) const
+{
+ Win4Assert(_ulSig == PATHBASEKEYSIG);
+ return _pwszPath == NULL ? NULL : _pwszPath;
+}
+
+
+// Maxium key for string ids
+extern WCHAR wszMaxPath[];
+
+
+#endif // __PATHKEY_HXX__
diff --git a/private/ole32/com/inc/pattbl.cxx b/private/ole32/com/inc/pattbl.cxx
new file mode 100644
index 000000000..e6c0be8ee
--- /dev/null
+++ b/private/ole32/com/inc/pattbl.cxx
@@ -0,0 +1,599 @@
+//+---------------------------------------------------------------------------//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: pattbl.cxx
+//
+// Contents: File pattern to clsid table.
+//
+// Classes: CPatternTbl
+// CScmPatternTbl
+// CChicoPatternTbl
+//
+// Functions: none
+//
+// History: 20-May-94 Rickhi Created
+// 12-Dec-94 BruceMa Support pattern table on Chicago
+// 20-Feb-95 BruceMa Don't pick up file patterns for
+// invalid CLSID's
+//
+// CODEWORK: Should add Docfile pattern in here and create a private
+// storage API that accepts a file handle and returns the
+// clsid so we minimize the Opens in all cases.
+//
+//----------------------------------------------------------------------------
+#include <ole2int.h>
+#include <pattbl.hxx>
+
+
+//+-------------------------------------------------------------------------
+//
+// member: CPatternTbl::FindPattern
+//
+// Synopsis: Finds a pattern in a file.
+//
+// Arguments: [hFile] - handle to the file to look in
+// [pclsid] - where to return the clsid
+//
+// Returns: S_OK if successfull
+//
+//--------------------------------------------------------------------------
+HRESULT CPatternTbl::FindPattern(HANDLE hFile, CLSID *pClsid)
+{
+ if (!IsEmpty())
+ {
+ return SearchForPattern(hFile, pClsid);
+ }
+ else
+ {
+ // no entry found, and the cache is not full, so return an error.
+ return REGDB_E_CLASSNOTREG;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CPatternTbl::SearchForPattern
+//
+// Synopsis: searches in the file for a know pattern, and returns the
+// CLSID index if found.
+//
+// Arguments: [hFile] - handle to the file to look in
+// [pclsid] - where to return the clsid
+//
+// Returns: pEntry if found, NULL otherwise.
+//
+//--------------------------------------------------------------------------
+HRESULT CPatternTbl::SearchForPattern(HANDLE hFile, CLSID *pClsid)
+{
+ HRESULT hr = REGDB_E_CLASSNOTREG;
+ LONG lLastOffset = 0;
+ ULONG ulLastCb = 0;
+ BYTE bStackBuf[256];
+ BYTE *pBuf = bStackBuf;
+
+ if (_pTblHdr->cbLargest > sizeof(bStackBuf))
+ {
+ // allocate a buffer big enough for largest pattern
+ pBuf = (BYTE *) PrivMemAlloc(_pTblHdr->cbLargest);
+ }
+
+ // now grovel through the file looking for a pattern match
+
+ BYTE *pCurr = _pStart;
+ BYTE *pEnd = _pStart + (_pTblHdr->OffsEnd - _pTblHdr->OffsStart);
+
+ while (pCurr < pEnd)
+ {
+ SPatternEntry *pEntry = (SPatternEntry *)pCurr;
+ BOOL fLook = TRUE;
+
+ if (pEntry->lFileOffset != lLastOffset ||
+ pEntry->ulCb > ulLastCb)
+ {
+ // must read part of the file
+
+ DWORD cbRead = 0;
+ DWORD dwMethod;
+ LONG cbMove;
+
+ if (pEntry->lFileOffset < 0)
+ {
+ cbMove = -1;
+ dwMethod = FILE_END;
+ }
+ else
+ {
+ cbMove = 0;
+ dwMethod = FILE_BEGIN;
+ }
+
+ fLook = FALSE; // assume failure
+
+ if (SetFilePointer(hFile, pEntry->lFileOffset, &cbMove, dwMethod)
+ != 0xffffffff)
+ {
+ if (ReadFile(hFile, pBuf, pEntry->ulCb, &cbRead, NULL))
+ {
+ // remember the last read positions
+ lLastOffset = pEntry->lFileOffset;
+ ulLastCb = pEntry->ulCb;
+ fLook = TRUE;
+ }
+ }
+ }
+
+ // compare the patterns
+ if (fLook && Matches(pBuf, pEntry))
+ {
+ // found a match, return the index of the CLSID
+ memcpy(pClsid, &pEntry->clsid, sizeof(CLSID));
+ return S_OK;
+ }
+
+ // get the next entry
+ pCurr = pCurr + pEntry->ulEntryLen;
+ }
+
+ // free the buffer if we need to
+ if (pBuf != bStackBuf)
+ {
+ PrivMemFree(pBuf);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CPatternTbl::Matches
+//
+// Synopsis: checks if the bytes in the buffer match the given pattern
+//
+// Arguments: [pFileBuf] - buffer containing the file data
+// [pEntry] -
+//
+// Returns: pEntry if found, NULL otherwise.
+//
+//--------------------------------------------------------------------------
+BOOL CPatternTbl::Matches(BYTE *pFileBuf, SPatternEntry *pEntry)
+{
+ // the pattern bytes follow the mask bytes. they are the same size.
+ BYTE *pbMask = pEntry->abData;
+ BYTE *pbPattern = pbMask + pEntry->ulCb;
+
+ for (ULONG iCtr = 0; iCtr < pEntry->ulCb; iCtr++)
+ {
+ if ((BYTE)(*(pFileBuf + iCtr) & *pbMask) != *pbPattern)
+ {
+ return FALSE;
+ }
+
+ // update the mask & pattern bytes
+ pbMask++;
+ pbPattern++;
+ }
+
+ return TRUE;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmPatternTbl::InitTbl
+//
+// Synopsis: reads the registry entries and converts them to a shared
+// memory table format
+//
+// Arguments: [pulSize] - where to return the table size
+//
+// Returns: S_OK if successfull.
+// E_OUTOFMEMORY
+//
+//--------------------------------------------------------------------------
+HRESULT CScmPatternTbl::InitTbl(ULONG *pulSize)
+{
+ // init size to zero
+ *pulSize = 0;
+
+ // allocate local memory in which to build the table
+ _pLocTbl = (BYTE *) PrivMemAlloc(PATTBL_GROW_SIZE);
+ if (!_pLocTbl)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // cast for simplicity
+ STblHdr *pLocTbl = (STblHdr *) _pLocTbl;
+
+ // initialize the table header
+ pLocTbl->ulSize = PATTBL_GROW_SIZE;
+ pLocTbl->OffsStart = sizeof(STblHdr);
+ pLocTbl->OffsEnd = sizeof(STblHdr);
+ pLocTbl->cbLargest = 0;
+
+
+ // build the table from the data in the registry
+ HKEY hkFileType;
+
+ if (RegOpenKey(HKEY_CLASSES_ROOT, L"FileType",&hkFileType)== ERROR_SUCCESS)
+ {
+ // enumerate the clsid's under this key
+ WCHAR szBuf[40];
+ DWORD iClsid = 0;
+
+ while (RegEnumKey(hkFileType, iClsid, szBuf, sizeof(szBuf)) == ERROR_SUCCESS)
+ {
+ // ensure this is a valid clsid
+ WCHAR szTemp[MAX_PATH];
+ LONG cbTemp = sizeof(szTemp);
+
+ WCHAR szClsid[80];
+ lstrcpyW(szClsid, L"Clsid\\");
+ lstrcatW(szClsid, szBuf);
+
+ if (RegQueryValue(HKEY_CLASSES_ROOT, szClsid, szTemp, &cbTemp)
+ == ERROR_SUCCESS)
+ {
+ // clsid exist, open the key and enumerate the entries.
+ HKEY hkClsid;
+ CLSID clsid;
+ BOOL fValid;
+
+ // Fetch asociated file patterns only if CLSID is valid
+ if (GUIDFromString(szBuf, &clsid) &&
+ RegOpenKey(hkFileType, szBuf, &hkClsid) == ERROR_SUCCESS)
+ {
+
+ // enumerate the patterns under this clsid
+ WCHAR szNum[10];
+ DWORD iPattern = 0;
+
+ while (RegEnumKey(hkClsid, iPattern, szNum, sizeof(szNum))
+ == ERROR_SUCCESS)
+ {
+ // read the registry value and parse the string to
+ // create a table entry
+
+ WCHAR szPattern[512];
+ LONG cb = sizeof(szPattern);
+
+ if (RegQueryValue(hkClsid, szNum, szPattern, &cb) ==
+ ERROR_SUCCESS)
+ {
+ SPatternEntry *pEntry = (SPatternEntry *)
+ ((BYTE *)_pLocTbl + pLocTbl->OffsEnd);
+
+ if (ParseEntry(szPattern, cb, pEntry, clsid) ==
+ ERROR_SUCCESS)
+ {
+ // update the table header
+ pLocTbl->cbLargest = MAX(pLocTbl->cbLargest,
+ pEntry->ulCb);
+
+ pLocTbl->OffsEnd += pEntry->ulEntryLen;
+ }
+ }
+
+ ++iPattern;
+ }
+
+ RegCloseKey(hkClsid);
+ }
+ }
+
+ ++iClsid;
+ }
+
+ RegCloseKey(hkFileType);
+ }
+
+ // update the table size to something reasonable. Use the combined size
+ // of all the entries we generated above, plus some padding for
+ // expansion. We return this size to the caller.
+
+ pLocTbl->ulSize = sizeof(STblHdr) + pLocTbl->OffsEnd;
+ *pulSize = pLocTbl->ulSize;
+
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmPatternTbl::IsValidPattern
+//
+// Synopsis: determines if the pattern entry read from the registry is of
+// a valid format. See ParseEntry for the format.
+//
+// Arguments: [psz] - pattern buffer
+// [cb] - size of buffer read
+//
+// Returns: TRUE if pattern is valid, FALSE otherwise
+//
+//--------------------------------------------------------------------------
+BOOL CScmPatternTbl::IsValidPattern(LPWSTR psz, LONG cb)
+{
+ // we must find exactly 3 commas before the end of the string
+ // in order for the entry to be of a parseable format.
+
+ ULONG cCommas = 0;
+ LPWSTR pszEnd = psz + (cb / sizeof(WCHAR));
+
+ while (psz < pszEnd && *psz)
+ {
+ if (*psz == ',')
+ cCommas++;
+
+ psz++;
+ }
+
+ return (cCommas == 3) ? TRUE : FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmPatternTbl::ParseEntry
+//
+// Synopsis: takes the registry string and parses it into a table entry.
+//
+// Arguments: [psz] - ptr to string from registry
+// [cb] - size of psz
+// [pEntry] - ptr to pattern table entry
+// [rclsid] - clsid the pattern maps to
+//
+// Returns: S_OK - pEntry updated
+//
+// Notes: the format of the registry string is...
+// <offset>,<cb>,<mask>,<pattern>
+// where...
+// <offset> and <cb> are decimal unless preceeded by 0x
+// <mask> is optional (not there means use all 1's
+//
+//--------------------------------------------------------------------------
+HRESULT CScmPatternTbl::ParseEntry(LPWSTR psz, LONG cb,
+ SPatternEntry *pEntry, REFCLSID rclsid)
+{
+ // validate the pattern before we attempt to parse it, simplifies
+ // error handling in the rest of the routine.
+ if (!IsValidPattern(psz, cb))
+ return E_INVALIDARG;
+
+ // copy in the clsid
+ memcpy(&pEntry->clsid, &rclsid, sizeof(CLSID));
+
+ // get the file offset
+ pEntry->lFileOffset = wcstol(psz, NULL, 0);
+ psz = SkipToNext(psz);
+
+ // get the byte count
+ pEntry->ulCb = wcstol(psz, NULL, 0);
+ Assert(pEntry->ulCb > 0);
+
+ // get the mask ptrs
+ LPWSTR pszMask = SkipToNext(psz);
+ BYTE *pbMask = pEntry->abData;
+
+ // get the pattern ptrs
+ LPWSTR pszPattern = SkipToNext(pszMask);
+ BYTE *pbPattern = pbMask + pEntry->ulCb;
+
+ // convert and copy the mask & pattern bytes into the pEntry
+ for (ULONG ulCb = pEntry->ulCb; ulCb > 0; ulCb--)
+ {
+ if (*pszMask == ',')
+ {
+ // missing mask means use 0xff
+ *pbMask = 0xff;
+ }
+ else
+ {
+ // convert the mask string to a byte
+ *pbMask = ToHex(pszMask);
+ pszMask += 2;
+ }
+ pbMask++;
+
+ // convert the pattern string to a byte
+ *pbPattern = ToHex(pszPattern);
+ pbPattern++;
+ pszPattern += 2;
+ }
+
+ // compute this entry size, rounded to 8 byte alignment.
+ // Note: the struct has 4 bytes in abData, so the sizeof
+ // returns 4 more than we need.
+ pEntry->ulEntryLen = ((sizeof(SPatternEntry) - 4 +
+ (2 * pEntry->ulCb) + 7) & 0xfff8);
+
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmPatternTbl::SkipToNext
+//
+// Synopsis: skips missing entries in the list and whitespaces
+//
+// Arguments: [sz] - ptr to string
+//
+// Returns: ptr to next entry in the list
+//
+//--------------------------------------------------------------------------
+LPWSTR CScmPatternTbl::SkipToNext(LPWSTR sz)
+{
+ while (*sz && *sz != ',')
+ {
+ sz++;
+ }
+
+ Assert(*sz == ',');
+ sz++;
+
+ while (*sz)
+ {
+ USHORT CharType[1];
+
+ GetStringTypeW (CT_CTYPE1, sz, 1, CharType);
+ if ((CharType[0] & C1_SPACE) == 0)
+ {
+ break;
+ }
+ sz++;
+ }
+
+ return sz;
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmPatternTbl::ToHex
+//
+// Synopsis: converts two characters to a hex byte
+//
+// Arguments: [psz] - ptr to string
+//
+// Returns: the value of the string in hex
+//
+//--------------------------------------------------------------------------
+BYTE CScmPatternTbl::ToHex(LPWSTR psz)
+{
+ BYTE bMask = 0xFF;
+ USHORT CharTypes[2];
+
+ GetStringTypeW (CT_CTYPE1, psz, 2, CharTypes);
+
+ if (CharTypes[0] & C1_XDIGIT)
+ {
+ bMask = CharTypes[0] & C1_DIGIT ? *psz - '0' : (BYTE)CharUpperW((LPWSTR)*psz) - 'A' + 10;
+
+ psz++;
+ if (CharTypes[1] & C1_XDIGIT)
+ {
+ bMask *= 16;
+ bMask += CharTypes[1] & C1_DIGIT ? *psz - '0' : (BYTE)CharUpperW((LPWSTR)*psz) - 'A' + 10;
+ psz++;
+ }
+ }
+
+ return bMask;
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmPatternTbl::CopyTbl
+//
+// Synopsis: copies the locally-built table to shared memory
+//
+// Arguments: [pShrTbl] - ptr to shared memory table
+//
+// Returns: pointer to end of table
+//
+//--------------------------------------------------------------------------
+BYTE *CScmPatternTbl::CopyTbl(BYTE *pShrTbl)
+{
+ BYTE *pEnd = pShrTbl;
+
+ if (_pLocTbl != NULL)
+ {
+ // now that we have built a local memory copy of the table, copy
+ // the table into shared memory.
+
+ ULONG ulNeed = ((STblHdr *)_pLocTbl)->ulSize;
+ memcpy(pShrTbl, _pLocTbl, ulNeed);
+ pEnd += ulNeed;
+ }
+
+ return pEnd;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CChicoPatternTbl::CChicoPatternTbl
+//
+// Synopsis: Constructor
+//
+// Arguments: fOk - FALSE is initialization failed
+//
+// Returns: -
+//
+//--------------------------------------------------------------------------
+CChicoPatternTbl::CChicoPatternTbl(HRESULT &hr)
+{
+ // Allocate internal structures
+ m_pPatTbl = new CPatternTbl();
+ m_pScmPatTbl = new CScmPatternTbl();
+ if (m_pPatTbl == NULL || m_pScmPatTbl == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ return;
+ }
+
+ // Read the patterns from the registry
+ if (FAILED(hr = m_pScmPatTbl->InitTbl(&m_ulSize)))
+ {
+ return;
+ }
+
+ // So CPatternTbl can use them
+ m_pPatTbl->Initialize(m_pScmPatTbl->GetTbl());
+
+ //Good return
+ hr = S_OK;
+ return;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CChicoPatternTbl::~CChicoPatternTbl
+//
+// Synopsis: Destructor
+//
+// Arguments: -
+//
+// Returns: -
+//
+//--------------------------------------------------------------------------
+CChicoPatternTbl::~CChicoPatternTbl(void)
+{
+ delete m_pPatTbl;
+ delete m_pScmPatTbl;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CChicoPatternTbl::IsEmpty
+//
+// Synopsis: Determines if the pattern table is empty
+//
+// Arguments: -
+//
+// Returns: TRUE if table is empty; FALSE otherwise
+//
+//--------------------------------------------------------------------------
+BOOL CChicoPatternTbl::IsEmpty(void)
+{
+ return m_pPatTbl->IsEmpty();;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CChicoPatternTbl::FindPattern
+//
+// Synopsis: Search for byte patterns in the specified file
+//
+// Arguments: hFile - Handle of file to search
+// pClsid - Where to store the returned CLSID
+//
+// Returns: HRESULT
+//
+//--------------------------------------------------------------------------
+HRESULT CChicoPatternTbl::FindPattern(HANDLE hFile, CLSID *pClsid)
+{
+ return m_pPatTbl->FindPattern(hFile, pClsid);
+}
+
diff --git a/private/ole32/com/inc/pattbl.hxx b/private/ole32/com/inc/pattbl.hxx
new file mode 100644
index 000000000..c979406b1
--- /dev/null
+++ b/private/ole32/com/inc/pattbl.hxx
@@ -0,0 +1,265 @@
+//+---------------------------------------------------------------------------//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: pattbl.hxx
+//
+// Contents: File pattern to clsid table.
+//
+// Classes: CPatternTbl
+// CScmPatternTbl
+// CChicoPatternTbl
+//
+// Functions: none
+//
+// History: 20-May-94 Rickhi Created
+// 12-Dec-94 BruceMa Support pattern table on Chicago
+//
+// CODEWORK: Should add Docfile pattern in here and create a private
+// storage API that accepts a file handle, so we minimize
+// the Opens in all cases.
+//
+//----------------------------------------------------------------------------
+#ifndef __PATTERNTBL__
+#define __PATTERNTBL__
+
+#include <olesem.hxx>
+
+// structure for global table info. This appears at the start of the table
+// and is used by all readers.
+
+typedef struct STblHdr
+{
+ ULONG ulSize; // size of pattern table
+ ULONG cbLargest; // largest pattern size
+ ULONG OffsStart; // offset to start of entries
+ ULONG OffsEnd; // offset to end of entries
+} STblHdr;
+
+
+// structure for one entry in the cache. the structure is variable sized
+// with the variable sized data being the string at the end of the struct.
+
+typedef struct SPatternEntry
+{
+ CLSID clsid; // index of clsid the pattern maps to
+ ULONG ulEntryLen; // length of this entry
+ LONG lFileOffset; // offset in file where pattern begins
+ ULONG ulCb; // count bytes in pattern
+ BYTE abData[4]; // start of mask & pattern strings
+} SPatternEntry;
+
+
+#define PATTBL_GROW_SIZE 2048
+
+
+// returns the max value of two
+#define MAX(a,b) ((a > b) ? a : b)
+
+
+//+-------------------------------------------------------------------------
+//
+// class: CPatternTbl
+//
+// purpose: Holds a cache of file patterns to clsid mappings (saves
+// many registry hits for each lookup). The cache helps reduce
+// the working set by avoiding paging in the registry.
+//
+// notes: The cache is expected to typically be small. The entries are
+// ordered in ascending offset and decending pattern size so we
+// can take advantage of read ahead and reduce the number of
+// reads.
+//
+// History: 20-May-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+class CPatternTbl : public CPrivAlloc
+{
+public:
+ CPatternTbl();
+ ~CPatternTbl();
+
+ void Initialize(BYTE *pTblHdr);
+ HRESULT FindPattern(HANDLE hFile, CLSID *pClsid);
+ BOOL IsEmpty();
+
+private:
+
+ HRESULT SearchForPattern(HANDLE hFile, CLSID *pClsid);
+ BOOL Matches(BYTE *pFileBuf, SPatternEntry *pEntry);
+
+ STblHdr *_pTblHdr; // ptr to table header struct
+ BYTE *_pStart; // ptr to first entry in the memory block
+};
+
+//+-------------------------------------------------------------------------
+//
+// member: CPatternTbl::CPatternTbl
+//
+// Synopsis: constructor for the cache.
+//
+//--------------------------------------------------------------------------
+inline CPatternTbl::CPatternTbl() :
+ _pTblHdr(NULL),
+ _pStart(NULL)
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CPatternTbl::~CPatternTbl
+//
+// Synopsis: destructor for the cache. Do nothing.
+//
+//--------------------------------------------------------------------------
+inline CPatternTbl::~CPatternTbl()
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CPatternTbl::Initialize
+//
+// Synopsis: inits the table
+//
+//--------------------------------------------------------------------------
+inline void CPatternTbl::Initialize(BYTE *pTblHdr)
+{
+ Win4Assert(pTblHdr && "CPatternTbl invalid TblHdr pointer");
+
+ _pTblHdr = (STblHdr *)pTblHdr;
+ _pStart = (BYTE *)_pTblHdr + _pTblHdr->OffsStart;
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CPatternTbl::IsEmpty
+//
+// Synopsis: determines if the table is empty of not
+//
+// Arguments: none
+//
+// Returns: TRUE if empty, FALSE otherwise
+//
+//--------------------------------------------------------------------------
+inline BOOL CPatternTbl::IsEmpty()
+{
+ return (_pTblHdr && _pTblHdr->OffsEnd != _pTblHdr->OffsStart) ? FALSE
+ : TRUE;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// class: CScmPatternTbl
+//
+// purpose: Creates the cache of file patterns to clsid mappings used
+// by the clients. See CPatternTbl above.
+//
+// notes: This is implemented in the SCM. The client side is
+// implemented in ole32.dll. This class creates the cache.
+//
+// History: 20-May-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+class CScmPatternTbl : public CPrivAlloc
+{
+public:
+ CScmPatternTbl();
+ ~CScmPatternTbl();
+
+ HRESULT InitTbl(ULONG *pulSize);
+ BYTE *CopyTbl(BYTE *pShrTbl);
+ void FreeTbl(void);
+ BYTE *GetTbl(void);
+
+private:
+
+ HRESULT ParseEntry(LPWSTR psz, LONG cb, SPatternEntry *pEntry, REFCLSID rclsid);
+ BOOL IsValidPattern(LPWSTR psz, LONG cb);
+ LPWSTR SkipToNext(LPWSTR sz);
+ BYTE ToHex(LPWSTR psz);
+
+ BYTE *_pLocTbl; // ptr to local memory table header struct
+};
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmPatternTbl::CScmPatternTbl
+//
+// Synopsis: constructor for the pattern table.
+//
+//--------------------------------------------------------------------------
+inline CScmPatternTbl::CScmPatternTbl() :
+ _pLocTbl(NULL)
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmPatternTbl::~CScmPatternTbl
+//
+// Synopsis: destructor for the cache.
+//
+//--------------------------------------------------------------------------
+inline CScmPatternTbl::~CScmPatternTbl()
+{
+ PrivMemFree(_pLocTbl);
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmPatternTbl::FreeTbl
+//
+// Synopsis: free local copy of table
+//
+//--------------------------------------------------------------------------
+inline void CScmPatternTbl::FreeTbl(void)
+{
+ PrivMemFree(_pLocTbl);
+ _pLocTbl = NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// member: CScmPatternTbl::GetTbl
+//
+// Synopsis: Return the internal local address of the pattern table
+//
+//--------------------------------------------------------------------------
+inline BYTE *CScmPatternTbl::GetTbl(void)
+{
+ return _pLocTbl;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// class: CChicoPatternTbl
+//
+// purpose: Wraps CPatternTbl and CScmPatternTbl in order to support
+// caching of registry file patterns on Chicago
+// Note - This is also used on NT when CoInitialize has not
+// been called.
+//
+// History: 12-Dec-94 BruceMa Created
+//
+//--------------------------------------------------------------------------
+class CChicoPatternTbl
+{
+public:
+ CChicoPatternTbl(HRESULT &hr);
+ ~CChicoPatternTbl(void);
+ HRESULT FindPattern(HANDLE hFile, CLSID *pClsid);
+ BOOL IsEmpty();
+
+private:
+ ULONG m_ulSize;
+ CPatternTbl *m_pPatTbl;
+ CScmPatternTbl *m_pScmPatTbl;
+};
+
+#endif // __PATTERNTBL__
diff --git a/private/ole32/com/inc/psctbl.cxx b/private/ole32/com/inc/psctbl.cxx
new file mode 100644
index 000000000..78b8abd2c
--- /dev/null
+++ b/private/ole32/com/inc/psctbl.cxx
@@ -0,0 +1,349 @@
+//+---------------------------------------------------------------------------//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: psctbl.cxx
+//
+// Contents: IID to proxy/stub CLSID mapping cache
+//
+// Classes: CPSClsidTbl - shared memory guid map
+//
+// History: 07-Apr-94 Rickhi Created
+// 28-Jun-95 BruceMa Return correct HRESULT from
+// CPSClsidTbl::Find
+//
+// Notes: this class maintains an IID to CLSID mapping table
+// in shared memory.
+//
+//----------------------------------------------------------------------------
+#include <ole2int.h>
+#include <psctbl.hxx>
+
+
+TCHAR tszInterface[] = TEXT("Interface");
+
+// the following string is used in compapi.cxx
+WCHAR wszProxyStubClsid[] = L"\\ProxyStubClsid32";
+WCHAR wszProxyStubClsid16[] = L"\\ProxyStubClsid";
+
+#if !defined(_CHICAGO_)
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPSClsidTbl::SearchShortList
+//
+// Synopsis: searches the short list for a matching entry and returns
+// a pointer to the found element, or NULL.
+//
+// Arguments: [dwFind] - the first dword of the GUID we want to find
+//
+// Returns: ptr to matching entry if found, NULL otherwise.
+//
+// Algorithm: does a binary search on the short list.
+//
+//--------------------------------------------------------------------------
+DWORDPAIR *CPSClsidTbl::SearchShortList(DWORD dwFind)
+{
+ // we do a binary search in the short list because we know
+ // they are in numerical order.
+
+ LONG lLow = 0;
+ LONG lHigh = _pGuidMap->ulCntShort-1;
+
+ while (lLow <= lHigh)
+ {
+ LONG lGuess = (lLow + lHigh) / 2;
+ DWORDPAIR *pCurr = _pShortList + lGuess;
+
+ if (pCurr->dw1 == dwFind)
+ {
+ return pCurr;
+ }
+ else if (pCurr->dw1 < dwFind)
+ {
+ lLow = lGuess + 1;
+ }
+ else
+ {
+ lHigh = lGuess - 1;
+ }
+ }
+
+ // not found
+ return NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPSClsidTbl::SearchLongList
+//
+// Synopsis: searches the long list for a matching entry and returns
+// a pointer to the found element, or NULL.
+//
+// Arguments: [rguid] - the GUID we want to find
+//
+// Returns: ptr to matching entry if found, NULL otherwise.
+//
+// Algorithm: does a binary search on the long list.
+//
+//--------------------------------------------------------------------------
+GUIDPAIR *CPSClsidTbl::SearchLongList(REFGUID rguid)
+{
+ // we do a binary search in the long list because we know
+ // they are in reversed numerical order.
+
+ LONG lLow = 0;
+ LONG lHigh = _pGuidMap->ulCntLong-1;
+
+ while (lLow <= lHigh)
+ {
+ LONG lGuess = (lLow + lHigh) / 2;
+ GUIDPAIR *pCurr = _pLongList - lGuess;
+
+ int iRes = memcmp(&pCurr->guid1, &rguid, sizeof(GUID));
+ if (iRes == 0)
+ {
+ return pCurr;
+ }
+ else if (iRes < 0)
+ {
+ lLow = lGuess + 1;
+ }
+ else
+ {
+ lHigh = lGuess - 1;
+ }
+ }
+
+ // not found
+ return NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPSClsidTbl::Find
+//
+// Synopsis: Searches the map for a matching guid and copies the
+// mapped to value into pGuidOut.
+//
+// Arguments: [rguid] - the guid to find.
+// [pGuidOut] - place to store the resulting guid
+//
+// Returns: ptr to guid if found, NULL otherwise.
+//
+// Algorithm: If the guid is an OLE201 style guid, we scan the short
+// table first, otherwise we skip to the long table. If it
+// is not found in the short table, we scan the long table
+// anyway, since the second guid may not be Ole2 style.
+//
+//--------------------------------------------------------------------------
+HRESULT CPSClsidTbl::Find(REFGUID rguid, GUID *pGuidOut)
+{
+ if (!_pGuidMap)
+ return E_OUTOFMEMORY;
+
+ if (IsOleStyleGuid(rguid))
+ {
+ // look in the short list. here we store just the first DWORD
+ // because we know what the other 3 dwords look like.
+
+ DWORDPAIR *pEntry = SearchShortList(rguid.Data1);
+ if (pEntry)
+ {
+ // found it, fill the guid to return
+ memcpy(pGuidOut, &guidOleTemplate, sizeof(GUID));
+ pGuidOut->Data1 = pEntry->dw2;
+ return S_OK;
+ }
+ }
+
+ // either the first guid is not OLE201 style, or we did not
+ // find a match in the short table. Scan the long table.
+
+ // have to look in the long list. here we store the entire
+ // guids because they dont look like Ole Style guids.
+
+ GUIDPAIR *pEntry = SearchLongList(rguid);
+ if (pEntry)
+ {
+ memcpy(pGuidOut, &pEntry->guid2, sizeof(GUID));
+ return S_OK;
+ }
+
+ // If couldn't find it and table is full, force the registry to be
+ // searched for it. Otherwise it's a real error.
+ return IsFull() ? E_OUTOFMEMORY : REGDB_E_IIDNOTREG;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmPSClsidTbl::Add
+//
+// Synopsis: Adds a new entry to the table.
+//
+// Arguments: [rguid1] - the IID to add
+// [rguid2] - the CLSID to map the IID to
+//
+// Returns: [TRUE] - entry added
+// [FALSE] - out of memory
+//
+// Algorithm: This is called only by the SCM, no one else has write access
+// to the memory.
+//
+// If boths guids are OLE201 style guids, we only store the
+// first DWORD of each guid in the short table.
+//
+// If either one is not an OLE201 style guid, we store the
+// whole guids in the long table.
+//
+//--------------------------------------------------------------------------
+BOOL CScmPSClsidTbl::Add(REFGUID rguid1, REFGUID rguid2)
+{
+ Win4Assert(_pGuidMap &&
+ "CScmPSClsidTbl should have already created shared memory!");
+
+ if (!_pGuidMap)
+ return FALSE;
+
+ if (IsOleStyleGuid(rguid1) && IsOleStyleGuid(rguid2))
+ {
+ // put it in the short table
+
+ if (_pGuidMap->ulFreeSpace < sizeof(DWORDPAIR))
+ {
+ CairoleDebugOut((DEB_WARN,
+ "CScmPSClsidTbl table is FULL. For efficiency, table size should be increased.\n"));
+ return FALSE;
+ }
+
+#if DBG==1
+ WCHAR wszBuf[80];
+ StringFromIID2(rguid1, wszBuf, sizeof(wszBuf));
+ CairoleDebugOut((DEB_USER2, "PSClsidMap adding key: %ws\n", wszBuf));
+#endif
+
+ // must ensure the initial list remains sorted, so go find
+ // the insertion slot.
+
+ DWORDPAIR *pInsertSlot = _pShortList + _pGuidMap->ulCntShort;
+ DWORDPAIR *pPrev = pInsertSlot - 1;
+
+ while (pPrev >= _pShortList && pPrev->dw1 > rguid1.Data1)
+ {
+ // move the data from the previous slot to the current
+ // insert slot, and make the previous slot the current
+ // insert slot.
+
+ pInsertSlot->dw1 = pPrev->dw1;
+ pInsertSlot->dw2 = pPrev->dw2;
+ pInsertSlot--;
+ pPrev--;
+ }
+
+ // found the insertion slot, copy in the data
+ pInsertSlot->dw1 = rguid1.Data1;
+ pInsertSlot->dw2 = rguid2.Data1;
+
+ _pGuidMap->ulFreeSpace -= sizeof(DWORDPAIR);
+ _pGuidMap->ulCntShort++;
+ }
+ else
+ {
+ // put it in the long table
+
+ if (_pGuidMap->ulFreeSpace < sizeof(GUIDPAIR))
+ {
+ CairoleDebugOut((DEB_WARN,
+ "CScmPSClsidTbl table is FULL. For efficiency, table size should be increased.\n"));
+ return FALSE;
+ }
+
+#if DBG==1
+ WCHAR wszBuf[80];
+ StringFromIID2(rguid1, wszBuf, sizeof(wszBuf));
+ CairoleDebugOut((DEB_USER2, "PSClsidMap adding key: %ws\n", wszBuf));
+#endif
+
+ // must ensure initial list remains sorted, so go find the
+ // insertion spot.
+
+ GUIDPAIR *pInsertSlot = _pLongList - _pGuidMap->ulCntLong;
+ GUIDPAIR *pPrev = pInsertSlot + 1;
+
+ while (pPrev <= _pLongList &&
+ (memcmp(&pPrev->guid1, &rguid1, sizeof(GUID)) > 0))
+ {
+ // move both guids up in the table, and make the previous
+ // slot the current insert slot.
+
+ memcpy(&pInsertSlot->guid1, pPrev, sizeof(GUIDPAIR));
+ pInsertSlot++;
+ pPrev++;
+ }
+
+ // found the insertion slot, so copy in the data
+ memcpy(&pInsertSlot->guid1, &rguid1, sizeof(GUID));
+ memcpy(&pInsertSlot->guid2, &rguid2, sizeof(GUID));
+
+ _pGuidMap->ulFreeSpace -= sizeof(GUIDPAIR);
+ _pGuidMap->ulCntLong++;
+ }
+
+ return TRUE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmPSClsidTbl::CopyTbl
+//
+// Synopsis: compresses & copies the built up table to the shared mem
+// passed in.
+//
+// Arguments: [pShrTbl] - ptr to shared memory to copy the table into
+//
+// Algorithm: This is called only by the SCM, no one else has write access
+// to the shared memory.
+//
+//--------------------------------------------------------------------------
+BYTE *CScmPSClsidTbl::CopyTbl(BYTE *pShrTbl)
+{
+ if (_pGuidMap != NULL)
+ {
+ // copy the header
+
+ BYTE *pStart = (BYTE *)_pGuidMap;
+ BYTE *pEnd = pStart + sizeof(GUIDMAP);
+ ULONG ulLen = pEnd - pStart;
+
+ memcpy(pShrTbl, pStart, ulLen);
+ pShrTbl += ulLen;
+
+
+ // copy the short list
+
+ DWORDPAIR *pEndShort = _pShortList + _pGuidMap->ulCntShort;
+ pStart = (BYTE *)_pShortList;
+ pEnd = (BYTE *)pEndShort;
+ ulLen = pEnd - pStart;
+
+ memcpy(pShrTbl, pStart, ulLen);
+ pShrTbl += ulLen;
+
+
+ // copy the long list immediately after the short list
+
+ GUIDPAIR *pStartLong = _pLongList - _pGuidMap->ulCntLong + 1;
+ pStart = (BYTE *)pStartLong;
+ pEnd = (BYTE *)(_pLongList + 1);
+ ulLen = pEnd - pStart;
+
+ memcpy(pShrTbl, pStart, ulLen);
+ pShrTbl += ulLen;
+ }
+
+ return pShrTbl;
+}
+
+#endif //if !defined(_CHICAGO_)
diff --git a/private/ole32/com/inc/psctbl.hxx b/private/ole32/com/inc/psctbl.hxx
new file mode 100644
index 000000000..7ba798104
--- /dev/null
+++ b/private/ole32/com/inc/psctbl.hxx
@@ -0,0 +1,438 @@
+//+---------------------------------------------------------------------------//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: psctbl.hxx
+//
+// Contents: IID to proxy/stub CLSID mapping cache
+//
+// Classes: CPSClsidTbl - shared memory guid map
+//
+// Functions: none
+//
+// History: 07-Apr-94 Rickhi Created
+//
+// Notes: this class maintains an IID to CLSID mapping table
+// in shared memory.
+//
+//----------------------------------------------------------------------------
+
+#ifndef __PSCTBL__
+#define __PSCTBL__
+
+#define IIDTBL_MAX_SIZE 12288
+
+// structures for one entry in the cache. the first is for entries of
+// ole2 style guids, the second for other guids.
+
+typedef struct tagDWORDPAIR
+{
+ DWORD dw1; // IID
+ DWORD dw2; // CLSID
+} DWORDPAIR;
+
+typedef struct tagGUIDPAIR
+{
+ GUID guid1; // IID
+ GUID guid2; // CLSID
+} GUIDPAIR;
+
+
+// structure for global table info. This appears at the start of the table
+// and is used by all readers.
+
+typedef struct tagGUIDMAP
+{
+ ULONG ulSize; // size of table
+ ULONG ulFreeSpace; // Free space in table
+ ULONG ulCntShort; // number of entries in the short list
+ ULONG ulCntLong; // number of entries in the long list
+} GUIDMAP;
+
+
+// template for OLE201 style guids
+const GUID guidOleTemplate =
+ {0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
+
+
+extern TCHAR tszInterface[];
+
+// the following string is used in compapi.cxx
+extern WCHAR wszProxyStubClsid[];
+extern WCHAR wszProxyStubClsid16[];
+
+
+//+---------------------------------------------------------------------------
+//
+// class: CPSClsidTbl
+//
+// synopsis: OLE32 version of shared memory cache for
+// IID to PSCLSID mappings
+//
+// Classes: CPSClsidTbl
+//
+// History: 06-Apr-94 Rickhi Created
+//
+// Notes: this is the OLE32.DLL version of the class. It reads the
+// the entries from the shared memory table, but never updates
+// them.
+//
+// the table is a list of IID to CLSID mappings in shared mem.
+// this list is used by ole32.dll when loading interface proxies
+// and stubs, and we want to avoid random registry hits.
+//
+// the SCM creates the list and is the only one who can modify
+// the shared memory. the clients are simply read only. the
+// SCM updates it when the registry changes.
+//
+// for OLE20 style guids that change only in the first DWORD,
+// we store only the first DWORD instead of the whole GUID,
+// giving us 4-1 compression for the (currently) common case.
+//
+// the DWORD cache starts at the beginning of the shared mem
+// and grows up, the GUID cache starts at the end of the shared
+// mem and grows down, giving us the maximum capacity.
+//
+//----------------------------------------------------------------------------
+class CPSClsidTbl
+{
+public:
+ CPSClsidTbl();
+
+ void Initialize(BYTE *pTbl);
+ HRESULT Find(REFGUID rguid, GUID *pGuidOut);
+ BOOL IsFull();
+
+private:
+
+ DWORDPAIR * SearchShortList(DWORD dwFind);
+ GUIDPAIR * SearchLongList(REFGUID rguid);
+
+
+ GUIDMAP * _pGuidMap; // ptr to table header
+ DWORDPAIR * _pShortList; // list of OLE style guids
+ GUIDPAIR * _pLongList; // list of non OLE style guids
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPSClsidTbl::CPSClsidTbl
+//
+// Synopsis: ctor for the client side table
+//
+//--------------------------------------------------------------------------
+inline CPSClsidTbl::CPSClsidTbl() :
+ _pGuidMap(NULL),
+ _pShortList(NULL),
+ _pLongList(NULL)
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPSClsidTbl::Initialize
+//
+// Synopsis: intializes the client side of the table
+//
+// Arguments: [pTblHdr] - ptr to where the table header should start
+//
+//--------------------------------------------------------------------------
+inline void CPSClsidTbl::Initialize(BYTE *pTblHdr)
+{
+ Win4Assert(pTblHdr && "CPSClsidTbl invalid TblHdr pointer");
+
+ _pGuidMap = (GUIDMAP *)pTblHdr;
+
+ _pShortList = (DWORDPAIR *)(((BYTE *)_pGuidMap) + sizeof(GUIDMAP));
+ _pLongList = (GUIDPAIR *) (((BYTE *)_pGuidMap) + _pGuidMap->ulSize -
+ sizeof(GUIDPAIR));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPSClsidTbl::IsFull
+//
+// Synopsis: returns TRUE if there is no room in the table
+//
+// Algorithm: ulFreeSpace is zero if there is no room in the table,
+// otherwise it is set to 1.
+//
+//--------------------------------------------------------------------------
+inline BOOL CPSClsidTbl::IsFull()
+{
+ return (_pGuidMap->ulFreeSpace == 0);
+}
+
+//+---------------------------------------------------------------------------
+//
+// class: CScmPSClsidTbl
+//
+// synopsis: shared memory cache of IID to PSCLSID mappings
+//
+// History: 06-Apr-94 Rickhi Created
+//
+// Notes: this is the SCM.EXE version of the class. It constructs
+// the table in shared memory.
+//
+// it maintains a list of IID to CLSID mappings in shared mem.
+// this list is used by ole32.dll when loading interface proxies
+// and stubs, and we want to avoid random registry hits.
+//
+// the SCM creates the list and is the only one who can modify
+// the shared memory. the clients are simply read only. the
+// SCM updates it when the registry changes.
+//
+// for OLE20 style guids that change only in the first DWORD,
+// we store only the first DWORD instead of the whole GUID,
+// giving us 4-1 compression for the (currently) common case.
+//
+// the DWORD cache starts at the beginning of the shared mem
+// and grows up, the GUID cache starts at the end of the shared
+// mem and grows down, giving us the maximum capacity.
+//
+//----------------------------------------------------------------------------
+class CScmPSClsidTbl
+{
+public:
+ CScmPSClsidTbl();
+ ~CScmPSClsidTbl();
+
+ HRESULT InitTbl(ULONG *pulSize);
+ BYTE *CopyTbl(BYTE *pShrTbl);
+ void FreeTbl(void);
+
+private:
+
+ BOOL Add(REFGUID rguid1, REFGUID rguid2);
+
+ GUIDMAP * _pGuidMap; // ptr to table header
+ DWORDPAIR * _pShortList; // list of OLE style guids
+ GUIDPAIR * _pLongList; // list of non OLE style guids
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmPSClsidTbl::CScmPSClsidTbl
+//
+// Synopsis: constructor for the SCM side of the table
+//
+//--------------------------------------------------------------------------
+inline CScmPSClsidTbl::CScmPSClsidTbl() :
+ _pGuidMap(NULL),
+ _pShortList(NULL),
+ _pLongList(NULL)
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmPSClsidTbl::~CScmPSClsidTbl
+//
+// Synopsis: destructor for the SCM side of the table
+//
+//--------------------------------------------------------------------------
+inline CScmPSClsidTbl::~CScmPSClsidTbl()
+{
+ PrivMemFree(_pGuidMap);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmPSClsidTbl::FreeTbl
+//
+// Synopsis: deletes the local copy of the table
+//
+//--------------------------------------------------------------------------
+inline void CScmPSClsidTbl::FreeTbl(void)
+{
+ PrivMemFree(_pGuidMap);
+ _pGuidMap = NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsOleStyleGuid
+//
+// Synopsis: determines if the GUID is one of the OLE201 style guids
+//
+// Arguments: [rguid] - guid to check
+//
+// Returns: TRUE if OLE20 style guid, FALSE otherwise.
+//
+// Algorithm: If the last 3 dwords of the GUID match the ones uses by all
+// OLE20 guids, then this returns TRUE, otherwise FALSE
+//
+//--------------------------------------------------------------------------
+inline BOOL IsOleStyleGuid(REFGUID rguid)
+{
+ const DWORD *ptr = &rguid.Data1;
+
+ return (*(ptr+1) == 0x00000000 && // all ole sytle guids's have
+ *(ptr+2) == 0x000000C0 && // these common values
+ *(ptr+3) == 0x46000000);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmPSClsidTbl::InitTbl
+//
+// Synopsis: intializes the local copy of the table
+//
+// Arguments: [pulSize] - where to return the table size
+//
+// Algorithm: This starts by building the table in local memory. When
+// the table is complete, a call to Copy will copy the local
+// table into shared memory.
+//
+//--------------------------------------------------------------------------
+inline HRESULT CScmPSClsidTbl::InitTbl(ULONG *pulSize)
+{
+ HKEY hKey;
+ FILETIME ftLastWrite;
+ WCHAR awName[MAX_PATH];
+ DWORD cName = sizeof(awName);
+ DWORD iSubKey = 0;
+ BOOL fTableFull = FALSE;
+
+
+ // allocate some local memory in which to build the mapping
+ _pGuidMap = (GUIDMAP *) PrivMemAlloc(IIDTBL_MAX_SIZE);
+ if (_pGuidMap == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // initialize the map header
+ _pGuidMap->ulSize = IIDTBL_MAX_SIZE;
+ _pGuidMap->ulFreeSpace = IIDTBL_MAX_SIZE - sizeof(GUIDMAP);
+ _pGuidMap->ulCntShort = 0;
+ _pGuidMap->ulCntLong = 0;
+
+
+ // initialize this objects pointers
+ _pShortList = (DWORDPAIR *)(((BYTE *)_pGuidMap) + sizeof(GUIDMAP));
+ _pLongList = (GUIDPAIR *) (((BYTE *)_pGuidMap) + _pGuidMap->ulSize -
+ sizeof(GUIDPAIR));
+
+
+ // enumerate the interface keys in the registry and create a table
+ // entry for each interface that has a ProxyStubClsid32 entry.
+
+ #ifdef _CHICAGO_
+ if (RegOpenKeyExA(HKEY_CLASSES_ROOT, tszInterface, NULL, KEY_READ, &hKey)
+ == ERROR_SUCCESS)
+ #else //_CHICAGO_
+ if (RegOpenKeyEx(HKEY_CLASSES_ROOT, tszInterface, NULL, KEY_READ, &hKey)
+ == ERROR_SUCCESS)
+ #endif //_CHICAGO_
+
+ {
+ while (RegEnumKeyEx(hKey, iSubKey, awName, &cName,
+ NULL, NULL, NULL, &ftLastWrite) == ERROR_SUCCESS)
+ {
+ // Get data from registry for this interface
+
+ WCHAR awcsPSClsid[80];
+ LONG cbPSClsid = sizeof(awcsPSClsid);
+
+ // This variable is used below to overwrite the ProxyStubClsid32
+ WCHAR *pwcEndOfName = awName + lstrlenW(awName);
+
+ lstrcatW(awName, wszProxyStubClsid);
+
+ if (RegQueryValue(hKey, awName, awcsPSClsid, &cbPSClsid)
+ == ERROR_SUCCESS)
+ {
+ // Convert registry string formats to GUID formats
+ GUID guidIID;
+ GUID guidCLSID;
+
+ *pwcEndOfName = 0;
+
+ if (GUIDFromString(awName, &guidIID))
+ {
+ if (GUIDFromString(awcsPSClsid, &guidCLSID))
+ {
+ if (!Add(guidIID, guidCLSID))
+ {
+ // we ran out of space in the cache table, exit
+ // now to avoid doing anymore work
+ fTableFull = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ // There wasn't a ProxyStubClsid32 for this interface.
+ // Because many applications install with interfaces
+ // that are variations on IDispatch, we are going to check
+ // to see if there is a ProxyStubClsid. If there is, and its
+ // class is that of IDispatch, then the OLE Automation DLL is
+ // the correct one to use. In that particular case, we will
+ // pretend that ProxyStubClsid32 existed, and that it is
+ // for IDispatch.
+
+ // Copy over ProxyStubClsid
+
+ cbPSClsid = sizeof(awcsPSClsid);
+ lstrcpyW(pwcEndOfName, wszProxyStubClsid16);
+
+ if (RegQueryValue(hKey, awName, awcsPSClsid, &cbPSClsid)
+ == ERROR_SUCCESS)
+ {
+ // Convert registry string formats to GUID formats
+ GUID guidIID;
+ GUID guidCLSID;
+
+ if (GUIDFromString(awcsPSClsid, &guidCLSID))
+ {
+ // If the clsid for the proxy stub is that of
+ // IDispatch, then register it.
+
+ *pwcEndOfName = 0;
+ if (!memcmp(&guidCLSID,&CLSID_PSDispatch, sizeof(GUID)) &&
+ GUIDFromString(awName, &guidIID))
+ {
+ if (!Add(guidIID, guidCLSID))
+ {
+ // we ran out of space in the cache table, exit
+ // now to avoid doing anymore work
+ fTableFull = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ iSubKey++;
+ cName = sizeof(awName);
+ }
+
+ RegCloseKey(hKey);
+ }
+
+
+ // update the size and freespace. Note: because CopyTbl compacts the table,
+ // it is important to subtract the correct amount of freespace left in the
+ // table in order for the client-side computation of _pLongList to work
+ // out correctly.
+
+ _pGuidMap->ulSize = _pGuidMap->ulSize - _pGuidMap->ulFreeSpace;
+ _pGuidMap->ulFreeSpace = (fTableFull) ? 0 : 1;
+
+ // set the return values
+ *pulSize = _pGuidMap->ulSize;
+ return S_OK;
+}
+
+
+
+
+#endif __PSCTBL__
diff --git a/private/ole32/com/inc/psctbl2.cxx b/private/ole32/com/inc/psctbl2.cxx
new file mode 100644
index 000000000..77a64eedb
--- /dev/null
+++ b/private/ole32/com/inc/psctbl2.cxx
@@ -0,0 +1,1797 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995.
+//
+// File: psctbl2.cxx
+//
+// Contents: Trie-based IID to CLSID map
+//
+// Classes: CMapGuidToGuidBase
+// CPSClsidTbl (DLL)
+// CScmPSClsidTbl (SCM/EXE)
+//
+// Functions: bmemcmp
+// bmemcpy
+// CMapGuidToGuidBase::Initialize
+// CMapGuidToGuidBase::CGUIDBlock -> internal functions
+// CMapGuidToGuidBase::TrieNode -> internal functions
+// CPSClsidTbl::Initialize
+// CPSClsidTbl::Find
+// CScmPSClsidTbl::Initialize
+// CScmPSClsidTbl::InitTbl
+// CScmPSClsidTbl::AddLocal
+// CScmPSClsidTbl::CopyToSharedMem
+//
+// History: 06-Jun-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#pragma hdrstop
+#include <psctbl2.hxx>
+
+
+// *** Defines and Constants ***
+// The number of bits used to store the number of key bytes in a TrieNode
+const int KEYBYTE_BITS = 5;
+
+// # of bits used to store # of links
+const int LINKS_BITS = 9;
+
+// The mask for number of key bytes stored in a TrieNode
+const WORD KEYBYTE_MASK = 0x1f;
+
+// The mask for the number of links stored in a TrieNode
+const WORD LINKS_MASK = (0x1ff<<KEYBYTE_BITS);
+
+// Mask for leaf bit in TrieNode
+const WORD ISLEAF_MASK = 0x4000;
+
+// Mask for deleted flag bit in TrieNode
+const WORD DELETED_MASK = 0x8000;
+
+// *** These definitions control the amount of memory that the cache uses/can use ***
+// The default number of links per TrieNode
+const int NODE_LINKS = 4;
+
+// The initial amount to grow by
+const int NODE_INIT_GROWBY =4;
+
+// The amount to growby afterwards
+// Note: must be a factor of 256, so therefore must be power of 2
+// also, NODE_LINKS+NODE_INIT_GROWBY = multiple of NODE_GROWBY
+const int NODE_GROWBY = 8;
+
+// Mod mask for NODE_GROWBY so we can just and it instead of using %
+const int NODE_GROWBY_MOD_MASK = NODE_GROWBY-1;
+
+// Constants for our initial/maximum map size
+const ULONG MAP_INITIAL_SIZE = 4096; // initial size of map = 4K
+const ULONG MAP_MAX_SIZE = 65536; // maximum size of map = 64K
+
+// Key text of registry
+TCHAR tszInterface[] = TEXT("Interface");
+
+// the following string is used in compapi.cxx
+WCHAR wszProxyStubClsid[] = L"\\ProxyStubClsid32";
+WCHAR wszProxyStubClsid16[] = L"\\ProxyStubClsid";
+
+// macros for setting up a pointer to base off of in member funcs
+#ifdef SETUP_BASE_POINTER
+#undef SETUP_BASE_POINTER
+#endif
+
+#define SETUP_BASE_POINTER() void *pBase = m_pMemBase
+
+#ifdef SYNC_BASE_POINTER
+#undef SYNC_BASE_POINTER
+#endif
+
+#define SYNC_BASE_POINTER() pBase = m_pMemBase
+
+// a based pointer for TrieNode, using passed bases
+#define PASSBASED __based(pBase)
+#define OLDBASED __based(pOldBase)
+#define NEWBASED __based(pNewBase)
+
+//+-------------------------------------------------------------------------
+//
+// Function: bmemcmp
+//
+// Synopsis: compares two memory strings, the first of which runs forward in memory
+// the second of which runs backwards in memory
+//
+// Arguments: [pFBuf] - the forward-running string in memory
+// [pBBuf] - the backward-running string in memory
+// [count] - the number of bytes to compare
+//
+// Returns: 0 if the two memory strings are equal. Example: pFBuf = "abcd", pBBuf-3 = "dcba" would be equal
+// else it returns the number of bytes left to compare.
+//
+//--------------------------------------------------------------------------
+inline int bmemcmp(const BYTE *pFBuf, const BYTE *pBBuf, size_t count)
+{
+ // pFBuf goes forward, pBBuf goes backward
+ while((count > 0) && (*pFBuf++ == *pBBuf--))
+ {
+ count--;
+ }
+
+ return count;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: bmemcpy
+//
+// Synopsis: copies a backward-running memory string into a forward running one,
+//
+// Arguments: [pFDest] - the forward-running destination
+// [pBSrc] - the backward-running string in memory
+// [count] - the number of bytes to copy
+//
+// Returns: nothing
+//
+//--------------------------------------------------------------------------
+inline void bmemcpy(BYTE *pFDest, const BYTE *pBSrc, size_t count)
+{
+ while(count-- > 0)
+ {
+ *pFDest++ = *pBSrc--;
+ }
+}
+
+// *** CMapGuidToGuidBase ***
+//+-------------------------------------------------------------------------
+//
+// Function: CMapGuidToGuidBase::Initialize
+//
+// Synopsis: Initializes base (client or server) guid -> guid map
+//
+// Arguments: [pBase] - the base address of our shared memory region
+//
+// Returns: appropriate status code
+//
+//--------------------------------------------------------------------------
+HRESULT CMapGuidToGuidBase::Initialize(void *pBase)
+{
+ CairoleDebugOut((DEB_ITRACE, "CMapGuidToGuidBase::Initialize(pBase = %p)\n", pBase));
+
+ m_pMemBase = pBase;
+
+ return S_OK;
+}
+
+// *** CMapGuidToGuidBase::CGUIDBlock ***
+//+-------------------------------------------------------------------------
+//
+// Function: CMapGuidToGuidBase::CGUIDBlock::Initialize, public
+//
+// Synopsis: Initializes the GUID list, we store the mapped-to GUIDs in this
+// list because there aren't that many different ones, so storing one per
+// leaf would be wasteful
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+//--------------------------------------------------------------------------
+inline void CMapGuidToGuidBase::CGUIDBlock::Initialize()
+{
+ m_nGuids = 0;
+ m_bpNext = NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CMapGuidToGuidBase::CGUIDBlock::GetGuid, public
+//
+// Synopsis: Returns a GUID associated with a given GUIDIndex
+//
+// Arguments: [pBase] - the base address of the memory region
+// [guidIndex] - the index of the GUID to retreive
+// [guidOut] - a reference to a GUID to store the retreive guid in
+//
+// Returns: TRUE if found, FALSE if didn't
+//
+//--------------------------------------------------------------------------
+inline BOOL CMapGuidToGuidBase::CGUIDBlock::GetGuid(void *pBase, GUIDIndex guidIndex, GUID &guidOut) const
+{
+ const CGUIDBlock * pBlock = this;
+
+ if(guidIndex == INVALID_GUID_INDEX)
+ {
+ return FALSE;
+ }
+
+ while(guidIndex > cGuids)
+ {
+ guidIndex -= cGuids;
+ pBlock = BP_TO_P(CGUIDBlock *, (CGUIDBlock PASSBASED *) pBlock->m_bpNext);
+ if(pBlock == NULL)
+ {
+ return FALSE;
+ }
+ }
+
+ guidOut = pBlock->m_guidArray[guidIndex];
+
+ return TRUE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CMapGuidToGuidBase::CGUIDBlock::AddGuid, public
+//
+// Synopsis: Adds a GUID to the list, or if the GUID is already there, just returns the proper
+// reference to it.
+//
+// Arguments: [pBase] - base address of memory region (NULL if using local memory)
+// [guid] - the guid to insert into the list
+// [alloc] - the functor to use to allocate memory
+//
+// Returns: a based pointer to the GUID in the table
+//
+//--------------------------------------------------------------------------
+GUIDIndex CMapGuidToGuidBase::CGUIDBlock::AddGuid(void *pBase, REFGUID guid, CAllocFunctor &alloc)
+{
+ CGUIDBlock *pBlock;
+ int iRetVal; // use an int so we can detect if our table of GUIDs is full
+
+ // First check to see if this GUID is already in the table
+ iRetVal = GuidInTable(pBase, this, guid);
+
+ if(iRetVal == INVALID_GUID_INDEX)
+ {
+ // Nope, add it
+ // avoid recursion
+ pBlock = this;
+ iRetVal = 0;
+
+ while(pBlock != NULL && (iRetVal < INVALID_GUID_INDEX))
+ {
+ Win4Assert(pBlock->m_nGuids <= cGuids && "More than cGuids in CGUIDBlock");
+
+ if(pBlock->m_nGuids == cGuids)
+ {
+ // we've outgrown this table, add a new block to the end
+ if(BP_TO_P(CGUIDBlock *, (CGUIDBlock PASSBASED *) pBlock->m_bpNext) == NULL)
+ {
+ CGUIDBlock *pNewBlock;
+
+ // allocate a new one
+ pNewBlock = (CGUIDBlock *) alloc.Alloc(sizeof(CGUIDBlock));
+
+ if(pNewBlock == NULL)
+ {
+ // we're out of memory
+ return INVALID_GUID_INDEX;
+ }
+
+ // initialize it
+ pNewBlock->Initialize();
+
+ // add the guid to it
+ pNewBlock->m_guidArray[0] = guid;
+ pNewBlock->m_nGuids++;
+
+ // chain it on the list
+ pBlock->m_bpNext = (CGUIDBlockBasedPtr) P_TO_BP(CGUIDBlock PASSBASED *, pNewBlock);
+
+ // set the return value
+ iRetVal += cGuids; // we're the first guid on this link in the chain
+ break;
+ }
+ else
+ {
+ // keep on looking for empty space
+ pBlock = BP_TO_P(CGUIDBlock *, (CGUIDBlock PASSBASED *) pBlock->m_bpNext);
+ iRetVal += cGuids;
+ }
+ }
+ else
+ {
+ // insert this GUID (in no particular order) into the block's array
+ pBlock->m_guidArray[pBlock->m_nGuids] = guid;
+ iRetVal += pBlock->m_nGuids;
+ pBlock->m_nGuids++;
+ break;
+ }
+ }
+ }
+
+ if(iRetVal >= INVALID_GUID_INDEX)
+ {
+ iRetVal = INVALID_GUID_INDEX;
+ }
+
+ return (GUIDIndex) iRetVal;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CMapGuidToGuidBase::CGUIDBlock::GuidInTable, private (implementation)
+//
+// Synopsis: Looks down the chained block list for a particular GUID, if it finds it return a
+// reference to it.
+//
+// Arguments: [pBase] - pointer to the base of the shared memory region
+// [pBlock] - the block to start at
+// [guid] - the guid to find
+//
+// Returns: a based pointer to the GUID in the table, NULL if it was not found
+//
+//--------------------------------------------------------------------------
+GUIDIndex CMapGuidToGuidBase::CGUIDBlock::GuidInTable(void *pBase, CGUIDBlock *pBlock, REFGUID guid)
+{
+ GUIDIndex iRet = 0;
+ GUID *pIndex;
+ BOOL fFound = FALSE;
+ int i;
+
+ // avoid recursion!
+ while(pBlock != NULL)
+ {
+ // Check this block
+ for(i =0, pIndex = &(pBlock->m_guidArray[0]); i < pBlock->m_nGuids; i++, pIndex++)
+ {
+ if(*pIndex == guid)
+ {
+ // found it, break outta here
+ iRet += i;
+ fFound = TRUE;
+ break;
+ }
+ }
+
+ if(!fFound)
+ {
+ // not in this block ,try next one
+ pBlock = BP_TO_P(CGUIDBlock *, (CGUIDBlock PASSBASED *) pBlock->m_bpNext);
+ iRet += cGuids;
+ }
+ else
+ {
+ // we found it, break outta here
+ break;
+ }
+ }
+
+ if(!fFound)
+ {
+ return INVALID_GUID_INDEX;
+ }
+
+ return iRet;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CMapGuidToGuidBase::CGUIDBlock::CopyToSharedMem
+//
+// Synopsis: Copies an entire list of CGUIDBlocks allocated in local memory
+// to shared memory, making sure the original blocks now have
+// based pointers to where the new (copied) data lies
+//
+// Arguments: [pNewBase] - the base pointer of the destination shared memory block
+// [pOldBase] - the base pointer of the source memory block (usually NULL)
+// [pCopyBlock] - the block to copy the first CGUIDBlock to
+// [alloc] - the allocator to use to allocate shared memory
+//
+// Returns: appropriate status code
+//
+//--------------------------------------------------------------------------
+HRESULT CMapGuidToGuidBase::CGUIDBlock::CopyToSharedMem(void *pNewBase, void *pOldBase, CGUIDBlock *pCopyBlock, CAllocFunctor &alloc)
+{
+ CGUIDBlock *pBlock = this;
+ int i;
+
+ while(pBlock != NULL)
+ {
+ pCopyBlock->m_nGuids = pBlock->m_nGuids;
+
+ for(i = 0; i < m_nGuids; i++)
+ {
+ pCopyBlock->m_guidArray[i] = pBlock->m_guidArray[i];
+ }
+
+ pBlock = BP_TO_P(CGUIDBlock *, (CGUIDBlock OLDBASED *) pBlock->m_bpNext);
+
+ if(pBlock != NULL)
+ {
+ CGUIDBlock *pNewBlock;
+
+ pNewBlock = (CGUIDBlock *) alloc.Alloc(sizeof(CGUIDBlock));
+
+ if(pNewBlock == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ pCopyBlock->m_bpNext = (CGUIDBlockBasedPtr) P_TO_BP(CGUIDBlock NEWBASED *, pNewBlock);
+ pCopyBlock = pNewBlock;
+ }
+ else
+ {
+ pCopyBlock->m_bpNext = (CGUIDBlockBasedPtr) P_TO_BP(CGUIDBlock NEWBASED *, NULL);
+ }
+ }
+
+ return S_OK;
+}
+
+// *** CMapGuidToGuidBase::TrieNode ***
+//+-------------------------------------------------------------------------
+//
+// Member: CMapGuidToGuidBase::TrieNode::NumLinks
+//
+// Synopsis: Return the number of links used in a node
+//
+// Arguments: (none)
+//
+// Returns: see synopsis
+//
+//--------------------------------------------------------------------------
+inline int CMapGuidToGuidBase::TrieNode::NumLinks() const
+{
+ return (m_wInfo & LINKS_MASK)>>KEYBYTE_BITS;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapGuidToGuidBase::TrieNode::NumKeyBytes
+//
+// Synopsis: Return the number of bytes of the key stored in this node
+//
+// Arguments: (none)
+//
+// Returns: see synopsis
+//
+//--------------------------------------------------------------------------
+inline int CMapGuidToGuidBase::TrieNode::NumKeyBytes() const
+{
+ return (m_wInfo & KEYBYTE_MASK);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPSClsidTbl::TrieNode::IsLeaf
+//
+// Synopsis: Return whether a node is a Node or a Leaf
+//
+// Arguments: (none)
+//
+// Returns: TRUE if the node is a Leaf (is has no links)
+// FALSE if it is a Node (it has links)
+//--------------------------------------------------------------------------
+inline BOOL CMapGuidToGuidBase::TrieNode::IsLeaf() const
+{
+ if(m_wInfo & ISLEAF_MASK)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPSClsidTbl::TrieNode::IsDeleted
+//
+// Synopsis: Return whether a given node is deleted
+//
+// Arguments: (none)
+//
+// Returns: TRUE if the node is marked as deleted
+// FALSE otherwise
+//
+//--------------------------------------------------------------------------
+inline BOOL CMapGuidToGuidBase::TrieNode::IsDeleted() const
+{
+ if(m_wInfo & DELETED_MASK)
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapGuidToGuidBase::TrieNode::SetLeaf
+//
+// Synopsis: sets the leaf bit of a node
+//
+// Arguments: [fLeaf] - should be TRUE to set this node to a Leaf
+// FALSE if this node should be a Node
+// Returns: nothing
+//
+//--------------------------------------------------------------------------
+inline void CMapGuidToGuidBase::TrieNode::SetLeaf(BOOL fLeaf)
+{
+ if(fLeaf)
+ {
+ m_wInfo = m_wInfo | ISLEAF_MASK;
+ }
+ else
+ {
+ m_wInfo = m_wInfo & (~ISLEAF_MASK);
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapGuidToGuidBase::TrieNode::SetDeleted
+//
+// Synopsis: sets the deleted bit of a node
+//
+// Arguments: [fDeleted] - should be TRUE to mark this node as deleted
+// FALSE to not mark it (equivalent to un-marking it)
+//
+// Returns: nothing
+//
+//--------------------------------------------------------------------------
+inline void CMapGuidToGuidBase::TrieNode::SetDeleted(BOOL fDeleted)
+{
+ Win4Assert(IsLeaf() && "Tried to delete a non-Leaf TrieNode!");
+
+ if (fDeleted)
+ {
+ m_wInfo = m_wInfo | DELETED_MASK;
+ }
+ else
+ {
+ m_wInfo = m_wInfo & (~DELETED_MASK);
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapGuidToGuidBase::TrieNode::SetKeyBytes
+//
+// Synopsis: Sets the number of bytes of a key stored in this node
+//
+// Arguments: [nKeyBytes] - the number of bytes
+//
+// Returns: nothing
+//
+//--------------------------------------------------------------------------
+inline void CMapGuidToGuidBase::TrieNode::SetKeyBytes(int nKeyBytes)
+{
+ Win4Assert(nKeyBytes <= GUID_BYTES && "Tried to add more than GUID_BYTES to a TrieNode!");
+
+ m_wInfo = (m_wInfo & (~KEYBYTE_MASK)) |
+ (nKeyBytes&KEYBYTE_MASK);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapGuidToGuidBase::TrieNode::SetLinks
+//
+// Synopsis: Sets the number of links used in a node
+//
+// Arguments: [nLinks] - the number of links used
+//
+// Returns: nothing
+//
+//--------------------------------------------------------------------------
+inline void CMapGuidToGuidBase::TrieNode::SetLinks(int nLinks)
+{
+ Win4Assert(nLinks <= 256 && "Tried to have more than 256 links in a node");
+
+ m_wInfo = (m_wInfo & (~LINKS_MASK)) |
+ ((nLinks<<KEYBYTE_BITS)&LINKS_MASK);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPSClsidTbl::TrieNode::IncrementLinks
+//
+// Synopsis: Increments the number of links used in a node by 1
+//
+// Arguments: (none)
+//
+// Returns: (nothing)
+//
+//--------------------------------------------------------------------------
+inline void CMapGuidToGuidBase::TrieNode::IncrementLinks()
+{
+ Win4Assert(((m_wInfo & LINKS_MASK)>>KEYBYTE_BITS) <= 255
+ && "Tried to insert past 256 links in a node");
+
+ m_wInfo += (1<<KEYBYTE_BITS);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapGuidToGuidBase::TrieNode::GetKey
+//
+// Synopsis: Return a pointer to a node's key data
+//
+// Arguments: (none)
+//
+// Returns: see synopsis
+//
+//--------------------------------------------------------------------------
+inline BYTE *CMapGuidToGuidBase::TrieNode::GetKey()
+{
+#if !defined(_M_IX86)
+ // we need to worry about alignment
+ // so we put the 2-byte GUIDIndex before the n-byte key
+ if(IsLeaf())
+ {
+ return m_bData + sizeof(GUIDIndex);
+ }
+ else
+ {
+ return m_bData;
+ }
+#else
+ // On the x86, we don't need to worry about alignment
+ return m_bData; // remember, this pointer not based!!
+#endif // !defined(_M_IX86)
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapGuidToGuidBase::TrieNode::GetData
+//
+// Synopsis: Return a pointer to a Leaf's data (the data mapped to the key)
+//
+// Arguments: (none)
+//
+// Returns: pointer to a Leaf's data
+//
+//--------------------------------------------------------------------------
+inline GUIDIndex *CMapGuidToGuidBase::TrieNode::GetData()
+{
+ Win4Assert(IsLeaf() && "Tried to get data from a non-Leaf node!");
+
+#if !defined(_M_IX86)
+ // we need to worry about alignment
+ // so we put the 2-byte GUIDIndex before the n-byte key
+ return (GUIDIndex *) m_bData;
+#else
+ // On the x86, we don't need to worry about alignment
+ return (GUIDIndex *) &m_bData[NumKeyBytes()];
+#endif // !defined(_M_IX86)
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapGuidToGuidBase::TrieNode::GetNodeSize
+//
+// Synopsis: Calculates the amount of bytes a node will take with the given parameters
+//
+// Arguments: [bKeyBytes] - the number of bytes of the key stored in this node
+// [fLeaf] - TRUE = Leaf node, FALSE = Node node
+// [bLinks] - the number of links to *allocate* (not the number of links used!!!!!)
+//
+// Returns: the computed size of the node
+//
+//--------------------------------------------------------------------------
+inline DWORD CMapGuidToGuidBase::TrieNode::GetNodeSize(BYTE bKeyBytes, BOOL fLeaf, int bLinks)
+{
+ return sizeof(WORD)+bKeyBytes+sizeof(GUIDIndex)*(fLeaf?1:0)+bLinks*sizeof(TrieNodeBasedPtr);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapGuidToGuidBase::TrieNode::GetLinkStart
+//
+// Synopsis: Return the beginning of the link array of a node
+//
+// Arguments: (none)
+//
+// Returns: a pointer to the beginning of the link array
+//
+//--------------------------------------------------------------------------
+inline TrieNodeBasedPtr UNALIGNED *CMapGuidToGuidBase::TrieNode::GetLinkStart() const
+{
+ return (TrieNodeBasedPtr UNALIGNED *) &m_bData[NumKeyBytes()];
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: TrieNode::InsertIntoLinkArray (static)
+//
+// Synopsis: insert a based pointer into the array of links to other nodes
+//
+// Arguments: [pArray] - pointer to the place in the array we wish to insert
+// [pInsert] - based pointer to insert
+// [nAfter] - number of nodes we need to "tumble" down the rest of the array
+//
+// Returns: void
+//
+//--------------------------------------------------------------------------
+inline void CMapGuidToGuidBase::TrieNode::InsertIntoLinkArray(TrieNodeBasedPtr UNALIGNED *pbpArray, TrieNodeBasedPtr bpInsert,int nAfter)
+{
+ Win4Assert(pbpArray != NULL && "Tried to insert into a NULL link array");
+ Win4Assert(bpInsert != 0 && "Tried to insert a NULL based pointer into link array");
+
+ // must use memmove, because memory regions overlap
+ memmove((pbpArray+1), pbpArray, nAfter*sizeof(TrieNodeBasedPtr));
+ *pbpArray = bpInsert;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CMapGuidToGuidBase::TrieNode::FindLinkSize, static
+//
+// Synopsis: Finds the number of allocated links to hold a given number of used links
+//
+// Arguments: [num] number of used links
+//
+// Returns: number of allocated links
+//
+//--------------------------------------------------------------------------
+inline int CMapGuidToGuidBase::TrieNode::FindLinkSize(int nLinks)
+{
+ if(nLinks <= NODE_LINKS)
+ {
+ return NODE_LINKS;
+ }
+
+ if(nLinks <= (NODE_LINKS+NODE_INIT_GROWBY))
+ {
+ return NODE_LINKS+NODE_INIT_GROWBY;
+ }
+
+ return NODE_GROWBY*((nLinks+(NODE_GROWBY-1))/NODE_GROWBY);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: TrieNode::GetLink
+//
+// Synopsis: Given the next byte of a key, return the link to the next node in the trie
+//
+// Arguments: [pBase] - pointer to base of shared memory
+// [bComp] - the next byte of the key to look for a link on
+// [pbpLink]- a reference to a TrieNodeBasedPtr *, which on exit will hold
+// the address of the link pointer so it can be changed
+// in the future.
+// Returns: the pointer to the node correspoding to bComp, or NULL if no such
+// node exists
+//
+//--------------------------------------------------------------------------
+CMapGuidToGuidBase::TrieNode *CMapGuidToGuidBase::TrieNode::GetLink(void *pBase, BYTE bComp, TrieNodeBasedPtr UNALIGNED *&pbpLink)
+{
+ TrieNodeBasedPtr UNALIGNED *pbpLower;
+ TrieNodeBasedPtr UNALIGNED *pbpUpper;
+ TrieNodeBasedPtr UNALIGNED *pbpIndex;
+ BYTE bIndex;
+
+ Win4Assert(!IsLeaf() && "Tried to get a link from a leaf!\n");
+
+ pbpLower = GetLinkStart();
+ pbpUpper = pbpLower+(NumLinks() - 1);
+
+ // Use binary search
+ while(pbpLower < pbpUpper)
+ {
+ pbpIndex = pbpLower + ((pbpUpper - pbpLower)>>1);
+ bIndex = *(((TrieNode PASSBASED *) (*pbpIndex))->GetKey());
+ if(bComp < bIndex)
+ {
+ pbpUpper = pbpIndex - 1;
+ }
+ else
+ if(bComp > bIndex)
+ {
+ pbpLower = pbpIndex + 1;
+ }
+ else
+ {
+ // found it
+ pbpLink = pbpIndex;
+ return BP_TO_P(TrieNode *, (TrieNode PASSBASED *)(*pbpIndex));
+ }
+ }
+
+ if((pbpLower != pbpUpper) ||
+ (bComp != *(((TrieNode PASSBASED *) (*pbpLower))->GetKey())))
+ {
+ return NULL; // didn't find anything
+ }
+
+ pbpLink = pbpLower;
+ return BP_TO_P(TrieNode *, (TrieNode PASSBASED *) (*pbpLower));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: TrieNode::AddLink (static)
+//
+// Synopsis: Adds a link to a node to the link array
+//
+// Arguments: [pBase] - pointer to the base of the block of memory the trie is in
+// [pRoot] - pointer of node to add to
+// pretty much an explicit "this" pointer so we can
+// avoid a recursive step if we need to allocated more
+// links (and therefore a new node)
+// [pNode] - pointer of node to add
+// [pbpNewNode]- handle to stick a new node in if we need to increase
+// the number of links allocated to this node. If this is
+// done, the original node will be deleted, so we need to
+// change references to it.
+// [alloc] - The allocator to use to allocate new memory
+//
+// Returns: S_OK if link was added without allocating more links,
+// S_FALSE if more links were allocated, and there for *pbpNewNode is the
+// pointer of the node that should be used to replace this one.
+// Otherwise appropriate status code
+//
+//--------------------------------------------------------------------------
+HRESULT CMapGuidToGuidBase::TrieNode::AddLink(void *pBase, TrieNode *pRoot, TrieNode *pNode,
+ TrieNodeBasedPtr UNALIGNED*pbpNewNode, CAllocFunctor &alloc)
+{
+ Win4Assert(pNode != NULL && "Tried to add link to NULL TrieNode");
+ Win4Assert(!pRoot->IsLeaf() && "Tried to add link to leaf TrieNode"); // can't add links to leafs!
+ HRESULT retVal = S_OK;
+ int newLinks = NODE_LINKS;
+
+ if(pRoot->NumLinks() == NODE_LINKS) // Check to see if we need more links
+ {
+ newLinks += NODE_INIT_GROWBY; // we need to grow by NODE_INIT_GROWBY
+ }
+ else if (((pRoot->NumLinks()&NODE_GROWBY_MOD_MASK) == 0) && (pRoot->NumLinks() != 0))
+ {
+ // we need to grow by NODE_GROWBY
+ // this computes the size of the node
+ newLinks = pRoot->NumLinks()+NODE_GROWBY;
+ }
+ else
+ {
+ newLinks = 0; // we don't need to grow
+ }
+
+ if((newLinks != 0) && (newLinks <= 256)) // we don't grow over 256
+ {
+ TrieNode *pTemp;
+
+ // we have to allocate another TrieNode, we've used all our links
+ Win4Assert(pRoot->NumLinks() <= 255);
+
+ // Create new trienode with more links
+ pTemp = (TrieNode *) alloc.Alloc(GetNodeSize(pRoot->NumKeyBytes(), FALSE, newLinks));
+
+ if(pTemp == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ *pbpNewNode = (TrieNodeBasedPtr) P_TO_BP(TrieNode PASSBASED *, pTemp);
+
+ // Copy over current data
+ memcpy(pTemp, pRoot, GetNodeSize(pRoot->NumKeyBytes(), FALSE, pRoot->NumLinks()));
+
+ // we don't delete the current node
+ alloc.Free(pRoot, GetNodeSize(pRoot->NumKeyBytes(), FALSE, pRoot->NumLinks()));
+
+ pRoot = pTemp;
+
+ retVal = S_FALSE;
+ }
+
+ if(pRoot->NumLinks() == 0) // Now that that's taken care of, let's add the link
+ {
+ // just pluck it right in the beginning
+ *(pRoot->GetLinkStart()) = (TrieNodeBasedPtr) P_TO_BP(TrieNode PASSBASED *, pNode);
+ }
+ else
+ {
+ // Insert using binary insertion
+ // This gives us an array in sorted order
+ TrieNodeBasedPtr UNALIGNED *pbpLower;
+ TrieNodeBasedPtr UNALIGNED *pbpUpper;
+ TrieNodeBasedPtr UNALIGNED *pbpIndex;
+ BYTE bIndex;
+
+ pbpLower = pRoot->GetLinkStart();
+ pbpUpper = pbpLower + (pRoot->NumLinks() - 1);
+
+ while(pbpLower < pbpUpper)
+ {
+ pbpIndex = pbpLower + (pbpUpper - pbpLower)/2;
+ bIndex = *(((TrieNode PASSBASED *) (*pbpIndex))->GetKey());
+ if(*(pNode->GetKey()) < bIndex)
+ {
+ pbpUpper = pbpIndex - 1;
+ }
+ else
+ if(*(pNode->GetKey()) > bIndex)
+ {
+ pbpLower = pbpIndex + 1;
+ }
+ else
+ {
+ // we shouldn't have duplicates in the table
+ Win4Assert(0 && "Duplicate Entries in IID->CLSID table!\n");
+ }
+ }
+ TrieNodeBasedPtr UNALIGNED *pStart = pRoot->GetLinkStart();
+ int iNumLinks = pRoot->NumLinks();
+
+ if(*(((TrieNode PASSBASED *) (*pbpLower))->GetKey()) > *(pNode->GetKey()))
+ {
+ // insert before
+ InsertIntoLinkArray(pbpLower,
+ (TrieNodeBasedPtr) P_TO_BP(TrieNode PASSBASED *, pNode),
+ iNumLinks - (pbpLower - pStart));
+ }
+ else
+ {
+ // insert after
+ InsertIntoLinkArray(pbpLower+1,
+ (TrieNodeBasedPtr) P_TO_BP(TrieNode PASSBASED *, pNode),
+ iNumLinks - (pbpLower+ 1 - pStart));
+ }
+
+ }
+
+
+ // Keep track of how many links
+ pRoot->IncrementLinks();
+
+ return retVal;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: TrieNode::CreateSuffixNode
+//
+// Synopsis: Creates a suffix node from the current node. A suffix node is
+// the same node except with the bytes that are the same chopped off the beginning
+// of the key
+//
+// Arguments: [bBytesDifferent] - the number of bytes which make up the suffix
+// [alloc] - a memory allocator to use
+//
+// Returns: pointer to a TrieNode, which is the suffix node
+//
+//--------------------------------------------------------------------------
+CMapGuidToGuidBase::TrieNode *CMapGuidToGuidBase::TrieNode::CreateSuffixNode(BYTE bBytesDifferent,
+ CAllocFunctor &alloc)
+{
+ TrieNode *pNewNode;
+
+ if(IsLeaf())
+ {
+ // Create a Suffix leaf
+ pNewNode = (TrieNode *) alloc.Alloc(GetNodeSize(bBytesDifferent, TRUE, 0));
+
+ if(pNewNode == NULL)
+ {
+ return NULL;
+ }
+
+ pNewNode->SetLeaf(TRUE);
+ pNewNode->SetKeyBytes(bBytesDifferent);
+ pNewNode->SetLinks(0);
+ memcpy(pNewNode->GetKey(), GetKey()+(NumKeyBytes() - bBytesDifferent), bBytesDifferent);
+ *(pNewNode->GetData()) = *(GetData());
+ }
+ else
+ {
+ // Create a Suffix Node
+ pNewNode = (TrieNode *) alloc.Alloc(GetNodeSize(bBytesDifferent, FALSE, FindLinkSize(NumLinks())));
+
+ if(pNewNode == NULL)
+ {
+ return NULL;
+ }
+
+ pNewNode->SetKeyBytes(bBytesDifferent);
+ pNewNode->SetLeaf(FALSE);
+ pNewNode->SetLinks(NumLinks());
+ memcpy(pNewNode->GetKey(), GetKey()+(NumKeyBytes() - bBytesDifferent), bBytesDifferent);
+ memcpy(pNewNode->GetLinkStart(), GetLinkStart(), NumLinks()*sizeof(TrieNodeBasedPtr));
+
+ }
+
+ return pNewNode;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: TrieNode::CreateTrieNode (static)
+//
+// Synopsis: creates a trie Node with the passed data
+//
+// Arguments: [pbKey] - a pointer to key data (goes forward)
+// [bKeyBytes] - how many bytes are in the key
+// [bLinks] - how many links to allocated (must be power of 2)
+// [alloc] - a memory allocator to use
+//
+// Returns: a pointer to a TrieNode filled with the above data
+//
+//--------------------------------------------------------------------------
+CMapGuidToGuidBase::TrieNode *CMapGuidToGuidBase::TrieNode::CreateTrieNode(const BYTE *pbKey,
+ BYTE bKeyBytes,
+ BYTE bLinks,
+ CAllocFunctor &alloc)
+{
+ TrieNode *pNode;
+
+ // if pbKey == NULL, bKeyBytes must = 0
+ Win4Assert(pbKey != NULL || (bKeyBytes == 0));
+ Win4Assert(bKeyBytes >= 0);
+
+ pNode = (TrieNode *) alloc.Alloc(GetNodeSize(bKeyBytes, FALSE, bLinks));
+
+ if(pNode == NULL)
+ {
+ return NULL;
+ }
+
+ pNode->SetLeaf(FALSE);
+ pNode->SetKeyBytes(bKeyBytes);
+ pNode->SetLinks(0);
+ memcpy(pNode->GetKey(), pbKey, bKeyBytes);
+
+ return pNode;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: TrieNode::CreateTrieLeaf (static)
+//
+// Synopsis: creates a Leaf node with the passed data
+//
+// Arguments: [pbKey] - a pointer to the key data (goes backwards)
+// [bKeyBytes] - how many bytes are in the key
+// [data] - a GUIDIndex this key maps to.
+// [alloc] - a memory allocator to use
+//
+// Returns: a pointer to a TrieNode structure filled with above data
+//
+//--------------------------------------------------------------------------
+CMapGuidToGuidBase::TrieNode *CMapGuidToGuidBase::TrieNode::CreateTrieLeaf(const BYTE *pbKey,
+ BYTE bKeyBytes,
+ GUIDIndex data,
+ CAllocFunctor &alloc)
+{
+ Win4Assert(pbKey != NULL);
+ Win4Assert(bKeyBytes > 0);
+
+ TrieNode *pNode;
+
+ pNode = (TrieNode *) alloc.Alloc(GetNodeSize(bKeyBytes, TRUE, 0));
+
+ if(pNode == NULL)
+ {
+ return NULL;
+ }
+
+ pNode->SetLeaf(TRUE);
+ pNode->SetKeyBytes(bKeyBytes);
+ pNode->SetLinks(0);
+ bmemcpy(pNode->GetKey(), pbKey, bKeyBytes);
+ *(pNode->GetData()) = data;
+
+ return pNode;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: TrieNode::AddKey (static)
+//
+// Synopsis: This function adds a key/GUIDBasedPtr pair to the passed trie.
+//
+// Arguments: [pBase] - the base of our shared memory block
+// [pRoot] - the root node of the trie (explicit "this" pointer)
+// [pbpPrev] - a handle to the previous reference to the root node,
+// so that if AddLink requires us to update it, we can.
+// [pbKey] - a pointer to the END of the key data, we add the key reversed!!!
+// [data] - the GUIDIndex to map this key to
+// [fReplace] - whether or not we should replace an existing entry
+// [alloc] - a memory allocator to use
+//
+// Returns: S_OK if successful, S_FALSE if the key was already in the trie and fReplace == FALSE,
+// appropriate error code otherwise
+//
+//--------------------------------------------------------------------------
+HRESULT CMapGuidToGuidBase::TrieNode::AddKey(void *pBase, TrieNode *pRoot, TrieNodeBasedPtr UNALIGNED *pbpPrev,
+ const BYTE *pbKey, GUIDIndex data, BOOL fReplace,
+ CAllocFunctor &alloc)
+{
+ Win4Assert(pRoot != NULL && "Tried to add key to NULL trie");
+ Win4Assert(pbpPrev != NULL && "Backlink to Trie NULL");
+ Win4Assert(pbKey != NULL && "Pointer to key data NULL");
+
+ int numDifferent, nNodeKeyBytes, nKeyBytes;
+ BYTE *pbNodeKey;
+ TrieNode *pNextLevel, *pNewNode, *pPrefixNode, *pSuffixNode;
+ TrieNodeBasedPtr UNALIGNED *pbpLinkPointer;
+ TrieNodeBasedPtr bpDummy;
+
+ nKeyBytes = GUID_BYTES; // Every Key is a full GUID
+ pbNodeKey = pRoot->GetKey();
+ nNodeKeyBytes = pRoot->NumKeyBytes();
+
+ // while both keys are the same, traverse the trie
+ while((numDifferent = bmemcmp(pbNodeKey, pbKey, nNodeKeyBytes)) == 0)
+ {
+ Win4Assert(nKeyBytes >= nNodeKeyBytes);
+
+ // Key prefix is the same
+ if(nKeyBytes == nNodeKeyBytes) // that means these keys are *exactly* the same!!!
+ { // so we might have to replace the key/data mapping
+ if(pRoot->IsDeleted() || fReplace)
+ {
+ Win4Assert(pRoot->IsLeaf());
+ // the leaf node is deleted, or the replace flag is set, we can write over the data map
+ *(pRoot->GetData()) = data;
+ pRoot->SetDeleted(FALSE); // this doesn't hurt if the node wasn't deleted in the first place
+
+ return S_OK;
+ }
+
+ return S_FALSE; // else we don't do anything
+ }
+
+ pbKey-= nNodeKeyBytes; // Chop off this part of the key, continue down the trie
+ nKeyBytes -= nNodeKeyBytes;
+ pNextLevel = BP_TO_P(TrieNode *, (TrieNode PASSBASED *) pRoot->GetLink(pBase, *pbKey, pbpLinkPointer));
+
+ if(pNextLevel == NULL) // no next level, create new leaf here
+ {
+ HRESULT hr;
+
+ pNewNode = CreateTrieLeaf(pbKey, nKeyBytes, data, alloc);
+
+ if(pNewNode == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ hr = AddLink(pBase, pRoot, pNewNode, &bpDummy, alloc);
+
+ if(FAILED(hr))
+ {
+ return hr;
+ }
+
+ if(hr == S_FALSE)
+ {
+ // had to allocate a new node (ran out of links), reattatch to previous link
+ *pbpPrev = bpDummy;
+ }
+
+ return S_OK;
+ }
+
+ pRoot = pNextLevel;
+ pbpPrev = pbpLinkPointer;
+ pbNodeKey = pRoot->GetKey();
+ nNodeKeyBytes = pRoot->NumKeyBytes();
+ }
+
+ // we have to split the tree up
+ Win4Assert(*pbNodeKey == *pbKey && "Took wrong path in Trie"); // if this isn't true, something's really screwed up
+
+ // We create three nodes : a prefix node, containing the part of the key similar both to the existing
+ // GUIDs in the trie and the new GUID we are adding
+ // a new node, containing the part of the new GUID that's DIFFERENT from the rest
+ // a suffix node, containg the part of the old GUID subtrie that's different from the new GUID
+ pSuffixNode = pRoot->CreateSuffixNode(numDifferent, alloc);
+
+ if(pSuffixNode == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ pNewNode = CreateTrieLeaf(pbKey-(nNodeKeyBytes - numDifferent), nKeyBytes - (nNodeKeyBytes - numDifferent),
+ data, alloc);
+
+ if(pNewNode == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ pPrefixNode = CreateTrieNode(pbNodeKey, (nNodeKeyBytes - numDifferent), NODE_LINKS, alloc);
+
+ if(pPrefixNode == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // Delete original node
+ alloc.Free(pRoot, GetNodeSize(pRoot->NumKeyBytes(), pRoot->IsLeaf(), FindLinkSize(pRoot->NumLinks())));
+
+ *pbpPrev = (TrieNodeBasedPtr) P_TO_BP(TrieNode PASSBASED *, pPrefixNode);
+
+ // This is the assumption we make, that each new node has at least 2 links pre-allocated
+ Win4Assert(NODE_LINKS >= 2);
+
+ // We add the link here without calling AddLink because we know that our newly created node
+ // has no existing links, and we can just stick the two in order
+ if(*(pSuffixNode->GetKey()) < *(pNewNode->GetKey()))
+ {
+ // suffix node goes before new node
+ *(pPrefixNode->GetLinkStart()) = (TrieNodeBasedPtr) P_TO_BP(TrieNode PASSBASED *, pSuffixNode);
+ pPrefixNode->IncrementLinks();
+
+ *(pPrefixNode->GetLinkStart()+1) = (TrieNodeBasedPtr) P_TO_BP(TrieNode PASSBASED *, pNewNode);
+ pPrefixNode->IncrementLinks();
+ }
+ else
+ {
+ // new node goes before suffix node
+ *(pPrefixNode->GetLinkStart()+1) = (TrieNodeBasedPtr) P_TO_BP(TrieNode PASSBASED *, pNewNode);
+ pPrefixNode->IncrementLinks();
+
+ *(pPrefixNode->GetLinkStart()) = (TrieNodeBasedPtr) P_TO_BP(TrieNode PASSBASED *, pSuffixNode);
+ pPrefixNode->IncrementLinks();
+ }
+
+ return TRUE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: TrieNode::RemoveKey (static)
+//
+// Synopsis: Given a key and a trie, removes the key from the trie
+//
+//
+// Arguments: [pRoot] - the trie (explicit "this" pointer)
+// [ppPrev] - a handle to the previous reference to the root node,
+// so that if we need to update it, we can.
+// [pbKey] - the key
+//
+// Returns: TRUE if we succeeded
+// FALSE if we failed to find the key
+//--------------------------------------------------------------------------
+/*BOOL CMapGuidToGuidBase::TrieNode::RemoveKey(void *pBase, TrieNode *pRoot, const BYTE *pbKey)
+{
+ int nKeyBytes = GUID_BYTES;
+ TrieNodeBasedPtr *ppDummy;
+ Win4Assert(pRoot != NULL);
+ Win4Assert(pbKey != NULL);
+
+ while(pRoot != NULL)
+ {
+ if(bmemcmp(pRoot->GetKey(), pbKey, pRoot->NumKeyBytes()))
+ {
+ return FALSE; // if the prefix of this node ain't the same as the prefix of the key
+ // then the key is not in the table
+ }
+
+ pbKey -= pRoot->NumKeyBytes();
+ nKeyBytes -= pRoot->NumKeyBytes();
+
+ Win4Assert(nKeyBytes >= 0);
+
+ if(nKeyBytes == 0) // then this should be a leaf node
+ {
+ Win4Assert(pRoot->IsLeaf());
+
+ if(!pRoot->IsDeleted())
+ {
+ pRoot->SetDeleted(TRUE); // set the flag on the node to deleted
+
+ return TRUE;
+ }
+
+ return FALSE; // node is already deleted
+ }
+
+ pRoot = pRoot->GetLink(pBase, *pbKey, ppDummy);
+ }
+
+ return FALSE;
+}
+*/
+
+//+-------------------------------------------------------------------------
+//
+// Function: TrieNode::TraverseKey (static)
+//
+// Synopsis: Given a key, a trie, and a place to store data, find the data mapped to the key
+//
+// Arguments: [pBase] - the base pointer of our memory block
+// [pRoot] - the trie to traverse (explicit "this" pointer)
+// [pbKey] - a pointer to the key data
+// [data] - a GUIDIndex ref to stick the data in if we succeed
+//
+// Returns: TRUE if we succeeded, then dwData has the GUIDIndex mapped to the passed key
+// FALSE if we failed to find the key
+//--------------------------------------------------------------------------
+BOOL CMapGuidToGuidBase::TrieNode::TraverseKey(void *pBase, TrieNode *pRoot, const BYTE *pbKey,
+ GUIDIndex &data)
+{
+ Win4Assert(pRoot != NULL && "Tried to traverse a NULL Trie");
+ Win4Assert(pbKey != NULL && "Pointer to key data is NULL");
+ int bKeyBytes = GUID_BYTES;
+ TrieNodeBasedPtr UNALIGNED *pbpDummy;
+
+ while(pRoot != NULL)
+ {
+ if(bmemcmp(pRoot->GetKey(), pbKey, pRoot->NumKeyBytes()))
+ {
+ return FALSE; // if the prefix of this node ain't the same as the prefix of the key
+ // then the key is not in the table
+ }
+
+ pbKey -= pRoot->NumKeyBytes();
+ bKeyBytes -= pRoot->NumKeyBytes();
+
+ Win4Assert(bKeyBytes >= 0 && "Too many key bytes in this Trie path");
+
+ if(bKeyBytes == 0) // then this should be a leaf node
+ {
+ Win4Assert(pRoot->IsLeaf() && "Ran out of key bytes before got to leaf");
+
+ if(pRoot->IsDeleted()) // is this node deleted
+ {
+ return FALSE; // if so, this map is not valid
+ }
+
+ data = *(pRoot->GetData());
+
+ return TRUE;
+ }
+
+ pRoot = pRoot->GetLink(pBase, *pbKey, pbpDummy);
+ }
+
+ return FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: TrieNode::CopyToSharedMem
+//
+// Synopsis: Copy a given trie from one memory block to another
+//
+// Arguments: [pNewBase] - the base of the destination memory block
+// [pOldBase] - the base of the source memory block
+// [pRoot] - the trie to copy
+// [alloc] - the allocation functor to use to allocate memory
+//
+// Returns: a based pointer (off of pNewBase) to the newly copied trie
+// NULL if we failed to copy the trie
+//--------------------------------------------------------------------------
+
+TrieNodeBasedPtr CMapGuidToGuidBase::TrieNode::CopyToSharedMem(void *pNewBase, void *pOldBase, TrieNode *pRoot,
+ CAllocFunctor &alloc)
+{
+ // we use recursion here because it is more complex than simple tail recursion
+ // and a non-recursive implementation would be very confusing
+ // considering that there is a recursive depth of at most 16, this means this function
+ // could take a maximum of 7*4*16=448 bytes on the stack
+ TrieNode *pCopy;
+
+ Win4Assert(pRoot != NULL && "Tried to copy a NULL Trie to shared memory");
+
+ if(pRoot->IsLeaf())
+ {
+ // allocate shared memory
+ pCopy = (TrieNode *) alloc.Alloc(GetNodeSize(pRoot->NumKeyBytes(), TRUE, 0));
+
+ if(pCopy == NULL)
+ {
+ return (TrieNodeBasedPtr) BP_TO_P(TrieNode NEWBASED *, NULL);
+ }
+
+ // copy over data
+ memcpy(pCopy, pRoot, GetNodeSize(pRoot->NumKeyBytes(), TRUE, 0));
+
+ return (TrieNodeBasedPtr) P_TO_BP(TrieNode NEWBASED *, pCopy);
+ }
+ else
+ {
+ // allocate shared memory
+ pCopy = (TrieNode *) alloc.Alloc(GetNodeSize(pRoot->NumKeyBytes(), FALSE,
+ FindLinkSize(pRoot->NumLinks())));
+
+ if(pCopy == NULL)
+ {
+ return (TrieNodeBasedPtr) BP_TO_P(TrieNode NEWBASED *, NULL);
+ }
+
+ // copy over data
+ memcpy(pCopy, pRoot, sizeof(WORD)+pRoot->NumKeyBytes());
+
+ // recursively set links
+ for(int i = 0; i < pRoot->NumLinks(); i++)
+ {
+ (pCopy->GetLinkStart())[i] = CopyToSharedMem(pNewBase, pOldBase, BP_TO_P(TrieNode *,
+ (TrieNode OLDBASED *)(pRoot->GetLinkStart()[i])),
+ alloc);
+ if(BP_TO_P(TrieNode *, (TrieNode NEWBASED *) (pCopy->GetLinkStart())[i]) == NULL)
+ {
+ return (TrieNodeBasedPtr) BP_TO_P(TrieNode NEWBASED *, NULL);
+ }
+ }
+
+ return (TrieNodeBasedPtr) P_TO_BP(TrieNode NEWBASED *, pCopy);
+ }
+}
+
+
+// *** CPSClsidTbl *** (DLL)
+//+-------------------------------------------------------------------------
+//
+// Function: CPSClsidTbl::Initialize
+//
+// Synopsis: Initializes the client side of the guid->guid map
+//
+// Arguments: [pscMapName] - name of this stack, used to create a shared stack
+//
+// Returns: appropriate status code
+//
+//--------------------------------------------------------------------------
+HRESULT CPSClsidTbl::Initialize(void *pBase)
+{
+ HRESULT hr;
+
+ CairoleDebugOut((DEB_ITRACE, "CPSClsidTbl::Initialize(pBase = %p)\n", pBase));
+
+ hr = CMapGuidToGuidBase::Initialize(pBase);
+
+ if(SUCCEEDED(hr))
+ {
+ // Get a pointer to our shared memory header
+ m_pHeader = (SharedMemHeader *) m_pMemBase;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CPSClsidTbl::Find
+//
+// Synopsis: Given a GUID key, looks for the data mapped to it
+//
+// Arguments: [refguid] - a C++ reference to a GUID structure
+// [pGuidOut] - a GUID * to store the data in
+//
+// Returns: a pointer to the data (really pGuidOut)
+// NULL if guid was not found
+//
+//--------------------------------------------------------------------------
+HRESULT CPSClsidTbl::Find(REFGUID srcguid, GUID *pGuidOut) const
+{
+ GUIDIndex iGuid;
+ HRESULT hr;
+
+ SETUP_BASE_POINTER();
+
+ if(IsFull()) // initialize hr to error value
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ {
+ hr = REGDB_E_IIDNOTREG;
+ }
+
+ if(TrieNode::TraverseKey(m_pMemBase, BP_TO_P(TrieNode *, (TrieNode PASSBASED *)m_pHeader->m_bpTrie),
+ ((const BYTE *)&srcguid)+GUID_BYTES-1, iGuid))
+ {
+ if(m_pHeader->m_GUIDs.GetGuid(m_pMemBase, iGuid, *pGuidOut))
+ {
+ hr = S_OK; // set hr to OK
+ }
+ else
+ {
+ CairoleDebugOut((DEB_IWARN, "CPSClsidTbl: Found GUID %I in table, but couldn't find CLSID at %d\n",
+ srcguid, iGuid));
+ }
+ }
+ else
+ {
+ CairoleDebugOut((DEB_IWARN, "CPSClsidTbl: Couldn't find GUID - %I\n", &srcguid));
+ }
+
+ return hr;
+}
+
+
+// *** CScmPSClsidTbl *** (SCM)
+//+-------------------------------------------------------------------------
+//
+// Function: CScmPSClsidTbl::Initialize
+//
+// Synopsis: Initializes the server side of the guid->guid map
+//
+// Arguments: [pscMapName] - name of this stack, used to create a shared stack
+//
+// Returns: appropriate status code
+//
+//--------------------------------------------------------------------------
+HRESULT CScmPSClsidTbl::Initialize()
+{
+ HRESULT hr;
+
+ CairoleDebugOut((DEB_ITRACE, "CScmPSClsidTbl::Initialize()\n"));
+
+ hr = CMapGuidToGuidBase::Initialize(NULL);
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CScmPSClsidTbl::AddLocal
+//
+// Synopsis: Adds a key/data (GUID/GUIDBasedPtr) pair to internal dictionary
+//
+// Arguments: [guid] - a C++ reference to a GUID structure
+// [dataGuid] - a GUID to map the GUID to
+// [fReplace] - if TRUE, if the guid is already a key
+// replace what it is mapped to with dataGuid
+//
+// Returns: TRUE if key/data pair was added to the dictionary
+// FALSE if key was already in dictionary
+//
+//--------------------------------------------------------------------------
+HRESULT CScmPSClsidTbl::AddLocal(REFGUID keyGuid, REFGUID dataGuid, BOOL fReplace)
+{
+ GUIDIndex iGuid;
+ CHeapAlloc heap(m_hHeap); // create allocation functor
+ void *pBase = NULL; // the base of our locally-created table
+ // we use this so we can support adding GUIDs to the table later, when it is in shared memory
+
+ CairoleDebugOut((DEB_ITRACE, "CScmPSClsidTbl::AddLocal called with keyGuid = %I, dataGuid = %I, fReplace =%d.\n"
+ , &keyGuid, &dataGuid, (DWORD) fReplace));
+
+ // Add guid to array of GUIDs
+ iGuid = m_pLocalHeader->m_GUIDs.AddGuid(pBase, dataGuid, heap);
+
+ if(iGuid == INVALID_GUID_INDEX)
+ {
+ m_pLocalHeader->m_fFull = TRUE; // we are out of memory
+
+ return E_OUTOFMEMORY;
+ }
+
+ return TrieNode::AddKey(pBase, BP_TO_P(TrieNode *, (TrieNode PASSBASED *) m_pLocalHeader->m_bpTrie),
+ &m_pLocalHeader->m_bpTrie, ((const BYTE *)&keyGuid)+GUID_BYTES - 1,
+ iGuid, fReplace, heap);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CScmPSClsidTbl::Delete
+//
+// Synopsis: Given a GUID key, removes it from the trie
+//
+// Arguments: [guid] - a C++ reference to a GUID structure
+//
+// Returns: TRUE if key/data pair was found and deleted
+// FALSE if key was not found
+//
+//--------------------------------------------------------------------------
+/*BOOL CScmPSClsidTbl::Delete(REFGUID srcguid)
+{
+ TrieNode *pRoot;
+ BYTE index;
+
+ SETUP_BASE_POINTER();
+
+ index = *(((const BYTE *)&srcguid)+GUID_BYTES - 1);
+
+ pRoot = BP_TO_P(TrieNode *, (TrieNode PASSBASED *) m_pHeader->m_pTries[index]);
+
+ if(pRoot == NULL)
+ {
+ return FALSE;
+ }
+
+ return TrieNode::RemoveKey(m_pMemBase, pRoot, ((const BYTE *)&srcguid)+GUID_BYTES-1);
+}
+*/
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmPSClsidTbl::CopytoSharedMem
+//
+// Synopsis: Copies a locally created GUID->GUID map into shared memory
+//
+// Arguments: [pBase] - base pointer of shared memory
+// [alloc] - stack-based allocator of shared memory
+//
+// Returns: appropriate status code
+//
+//--------------------------------------------------------------------------
+HRESULT CScmPSClsidTbl::CopyToSharedMem(void *pBase, CSmStackAllocator &alloc)
+{
+ HRESULT hr = S_OK;
+ Win4Assert(m_hHeap != NULL);
+ CStackAlloc stack(alloc);
+ void *pOldBase = NULL;
+
+ // Allocate our shared memory header
+ m_pHeader = (SharedMemHeader *) alloc.Alloc(sizeof(SharedMemHeader));
+
+ if(m_pHeader == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ m_pMemBase = pBase;
+ m_pHeader->m_fFull = m_pLocalHeader->m_fFull;
+
+ // first copy over guids
+ hr = m_pLocalHeader->m_GUIDs.CopyToSharedMem(m_pMemBase, pOldBase, &(m_pHeader->m_GUIDs), stack);
+
+ if(SUCCEEDED(hr))
+ {
+ // now copy over our trie
+ if( BP_TO_P(TrieNode *, (TrieNode OLDBASED *) m_pLocalHeader->m_bpTrie) != NULL)
+ {
+ m_pHeader->m_bpTrie = TrieNode::CopyToSharedMem(m_pMemBase, pOldBase,
+ BP_TO_P(TrieNode *, (TrieNode OLDBASED *) m_pLocalHeader->m_bpTrie), stack);
+
+ if(BP_TO_P(TrieNode *, (TrieNode PASSBASED *) m_pHeader->m_bpTrie) == NULL)
+ {
+ m_pHeader->m_fFull = TRUE;
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ m_pHeader->m_fFull = TRUE;
+ hr = E_OUTOFMEMORY;
+ }
+ }
+
+ // we are done
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmPSClsidTbl::InitTbl
+//
+// Synopsis: intializes the table
+//
+// Arguments: none
+//
+// Returns : appropriate status code
+//
+//--------------------------------------------------------------------------
+HRESULT CScmPSClsidTbl::InitTbl()
+{
+ HKEY hKey;
+ FILETIME ftLastWrite;
+ WCHAR awName[MAX_PATH], awcsPSClsid[80];
+ WCHAR *pwcEndOfName;
+ GUID guidIID, guidCLSID;
+ DWORD cName = sizeof(awName);
+ DWORD iSubKey = 0;
+ LONG cbPSClsid = sizeof(awcsPSClsid);
+ void *pOldBase = NULL;
+
+ // Create a local heap to build the trie in
+ m_hHeap = HeapCreate(0, MAP_INITIAL_SIZE, MAP_MAX_SIZE);
+
+ if(m_hHeap == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // allocate our local header
+ m_pLocalHeader = (LocalMemHeader *) HeapAlloc(m_hHeap, 0, sizeof(LocalMemHeader));
+
+ if(m_pLocalHeader == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ m_pLocalHeader->m_fFull = FALSE;
+
+ m_pLocalHeader->m_GUIDs.Initialize();
+ TrieNode *pNode = TrieNode::CreateTrieNode(NULL, 0, NODE_LINKS, CHeapAlloc(m_hHeap));
+ m_pLocalHeader->m_bpTrie = (TrieNodeBasedPtr) P_TO_BP(TrieNode OLDBASED *, pNode);
+
+ if(BP_TO_P(TrieNode *, (TrieNode OLDBASED *) m_pLocalHeader->m_bpTrie) == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // enumerate the interface keys in the registry and create a table
+ // entry for each interface that has a ProxyStubClsid32 entry.
+
+ #ifdef _CHICAGO_
+ if (RegOpenKeyExA(HKEY_CLASSES_ROOT, tszInterface, NULL, KEY_READ, &hKey)
+ == ERROR_SUCCESS)
+ #else //_CHICAGO_
+ if (RegOpenKeyEx(HKEY_CLASSES_ROOT, tszInterface, NULL, KEY_READ, &hKey)
+ == ERROR_SUCCESS)
+ #endif //_CHICAGO_
+
+ {
+ while (RegEnumKeyEx(hKey, iSubKey, awName, &cName,
+ NULL, NULL, NULL, &ftLastWrite) == ERROR_SUCCESS)
+ {
+ // Get data from registry for this interface
+
+ // This variable is used below to overwrite the ProxyStubClsid32
+ pwcEndOfName = awName + lstrlenW(awName);
+
+ lstrcatW(awName, wszProxyStubClsid);
+
+ if (RegQueryValue(hKey, awName, awcsPSClsid, &cbPSClsid)
+ == ERROR_SUCCESS)
+ {
+ // Convert registry string formats to GUID formats
+ *pwcEndOfName = 0;
+
+ if (GUIDFromString(awName, &guidIID))
+ {
+ if (GUIDFromString(awcsPSClsid, &guidCLSID))
+ {
+
+ if (FAILED(AddLocal(guidIID, guidCLSID, TRUE)))
+ {
+ // we ran out of space in the cache table, exit
+ // now to avoid doing anymore work
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ //
+ // There wasn't a ProxyStubClsid32 for this interface.
+ // Because many applications install with interfaces
+ // that are variations on IDispatch, we are going to check
+ // to see if there is a ProxyStubClsid. If there is, and its
+ // class is that of IDispatch, then the OLE Automation DLL is
+ // the correct one to use. In that particular case, we will
+ // pretend that ProxyStubClsid32 existed, and that it is
+ // for IDispatch.
+ //
+
+ // Copy over ProxyStubClsid
+
+ lstrcpyW(pwcEndOfName,wszProxyStubClsid16);
+
+ if (RegQueryValue(hKey, awName, awcsPSClsid, &cbPSClsid)
+ == ERROR_SUCCESS)
+ {
+ // Convert registry string formats to GUID formats
+ if (GUIDFromString(awcsPSClsid, &guidCLSID))
+ {
+ //
+ // If the clsid for the proxy stub is that of
+ // IDispatch, then register it.
+ //
+ *pwcEndOfName = 0;
+ if (!memcmp(&guidCLSID,&CLSID_PSDispatch, sizeof(GUID)) &&
+ GUIDFromString(awName, &guidIID))
+ {
+
+ if (FAILED(AddLocal(guidIID, guidCLSID, TRUE)))
+ {
+ // we ran out of space in the cache table, exit
+ // now to avoid doing anymore work
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ iSubKey++;
+ cName = sizeof(awName);
+ }
+
+ RegCloseKey(hKey);
+ }
+
+ return S_OK;
+}
+
+
diff --git a/private/ole32/com/inc/psctbl2.hxx b/private/ole32/com/inc/psctbl2.hxx
new file mode 100644
index 000000000..98cf5057e
--- /dev/null
+++ b/private/ole32/com/inc/psctbl2.hxx
@@ -0,0 +1,476 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995.
+//
+// File: psctbl2.hxx
+//
+// Contents: Trie-based IID to CLSID map
+//
+// Classes: CMapGuidToGuidBase
+// CPSClsidTbl
+// CScmPSClsidTbl
+//
+// History: 06-Jun-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+#ifndef __GUIDMAP2_HXX__
+#define __GUIDMAP2_HXX__
+
+#include <smstack.hxx>
+
+// *** Defines ***
+// Size of GUID in bytes
+const int GUID_BYTES =16;
+
+// Number of GUIDs per GUIDBlock
+const int cGuids = 16;
+
+// *** Types ***
+// handy types to pass around based pointers in, so that we don't have to
+// use __based all the time, since the usage of __based is severely limited
+typedef SmBasedPtr TrieNodeBasedPtr;
+typedef SmBasedPtr CGUIDBlockBasedPtr;
+typedef SmBasedPtr GUIDBasedPtr;
+
+// We reference each CLSID by a 16 bit index, so therefore we have a maximum
+// of 65,535 classids in the cache
+typedef WORD GUIDIndex;
+
+// an invalid GUIDIndex = 65535
+const GUIDIndex INVALID_GUID_INDEX = 0xffff;
+
+// Functors for allocationg memory
+//+-------------------------------------------------------------------------
+//
+// Class: CAllocFunctor, CStackAlloc, CHeapAlloc
+//
+// Purpose: Used to isolate the exact memory allocator being used so that adding GUIDs to the map
+// works both when the map is in shared memory and in local memory
+//
+// Interface: appropriate constructors
+// Alloc
+// Free
+//
+// History: 05-Jul-95 t-stevan Created
+//
+// Note: These classes only represent an interface to a given allocator, they are not the allocators
+// themselves, so no resources are freed when these classes are destructed expect the room
+// used to hold the references to the other allocators
+//
+//--------------------------------------------------------------------------
+class CAllocFunctor
+{
+ public:
+ virtual void *Alloc(ULONG cbSize)=0;
+ virtual void Free(void *pvMem, ULONG cbSize)=0;
+};
+
+// CStackAlloc - functor for CSmStackAllocator
+class CStackAlloc : public CAllocFunctor
+{
+ public:
+ CStackAlloc(CSmStackAllocator &stack) : m_stack(stack)
+ {}
+
+ void *Alloc(ULONG cbSize)
+ { return m_stack.Alloc(cbSize); }
+
+ void Free(void *pvMem, ULONG cbSize)
+ { m_stack.Free(pvMem, cbSize); }
+
+ private:
+ CSmStackAllocator &m_stack; // use a reference
+};
+
+// CHeapAlloc - functor for Heap* API calls
+class CHeapAlloc : public CAllocFunctor
+{
+ public:
+ CHeapAlloc(HANDLE hHeap)
+ { m_hHeap = hHeap; }
+
+ void *Alloc(ULONG cbSize)
+ { return HeapAlloc(m_hHeap, 0, cbSize); }
+
+ void Free(void *pvMem, ULONG)
+ { HeapFree(m_hHeap, 0, pvMem); }
+
+ private:
+ HANDLE m_hHeap;
+};
+
+// *** Externs ***
+// This string is used to hold the key name for IIDs in the registry
+extern TCHAR tszInterface[];
+
+// the following string is used in compapi.cxx
+extern WCHAR wszProxyStubClsid[];
+extern WCHAR wszProxyStubClsid16[];
+//+-------------------------------------------------------------------------
+//
+// Class: CMapGuidToGuidBase
+//
+// Purpose: Trie-based GUID to GUID map, this is the base implementation
+// class for the two versions of the class - the DLL (client) version
+// and the EXE (server) version
+//
+// Interface: CGuidToGuidMapBase
+// ~CGuidToGuidMapBase
+// Initialize
+//
+// History: 06-Jun-95 t-stevan Created
+//
+// Note: This class is optimized for a IID->CLSID mapping, where there are many
+// IIDs and relatively few CLSIDs. So it represents a (usually) many-to-one mapping
+// Some efficiency would be lost in a one-to-one mapping.
+//--------------------------------------------------------------------------
+class CMapGuidToGuidBase
+{
+ public:
+ inline CMapGuidToGuidBase();
+
+ // Our initialization funciton.
+ HRESULT Initialize(void *pBase);
+
+ protected:
+ // *** Implementation ***
+ // CGUIDBlock is a block of 16 GUIDs which hold the GUIDs which our key GUIDs are mapped TO
+ // this is because there are a LOT of repeitions in a typical IID/CLSID mapping, so it's more
+ // space economical to save a 2-byte index to one copy of a 16-byte GUID in each leaf, instead
+ // of storing a 16 byte GUID.
+ // Insertion into this chained list of blocks in linear time. Retrieval is O(1) (a pointer dereference).
+ class CGUIDBlock
+ {
+ public:
+ // space is allocated for us, so we don't use a constructor
+ inline void Initialize();
+
+ GUIDIndex AddGuid(void *pBase, REFGUID guid, CAllocFunctor &alloc);
+
+ HRESULT CopyToSharedMem(void *pNewBase, void *pOldBase, CGUIDBlock *pFirstBlock, CAllocFunctor &alloc);
+
+ // returns the GUID a GUIDIndex maps to
+ inline BOOL GetGuid(void *pBase, GUIDIndex guidIndex, GUID &guidOut) const;
+
+ private:
+ static GUIDIndex GuidInTable(void *pBase, CGUIDBlock *pBlock, REFGUID guid);
+
+ int m_nGuids; // number of guids in this block
+ CGUIDBlockBasedPtr m_bpNext; // pointer to next block in chained list
+ GUID m_guidArray[cGuids]; // array of guids
+
+ };
+
+ // Information that we keep in shared memory
+ struct SharedMemHeader
+ {
+ CGUIDBlock m_GUIDs;
+ TrieNodeBasedPtr m_bpTrie; // our dummy start node
+ BOOL m_fFull;
+ };
+
+ // Internal node structure
+ // Variable length structure
+ // Properties of Trie:
+ //
+ // (1) Each node in a trie is either an internal node (designated Node),
+ // or a leaf node (designated Leaf). IsLeaf() returns this status
+ // (2) Each Node has NumLinks() many links to other nodes
+ // (3) Each Node has x amount of links allocated, such that
+ // x = multiple of NODE_GROWBY greater than NumLinks()
+ // unless # of links < NODE_LINKS, in this case x = NODE_LINKS
+ // (4) The total size in bytes of a Node is sizeof(WORD)+NumKeyBytes()+sizeof(TrieNodeBasedPtr)*x,
+ // where x is from (3) above
+ // (5) Each Leaf has 0 links allocated, and sizeo(GUIDIndex) bytes for a GUID index,
+ // which holds what the IID maps to.
+ // (6) The total size in bytes of a Leaf is sizeof(WORD)+NumKeyBytes()+sizeof(GUIDIndex)
+ // (7) Each Node and Leaf has NumKeyBytes() bytes allocated for storing parts of a key
+ // NumKeyBytes() can be zero.
+ // (8) Starting at the root of a trie, continuing down any path of links, will create a GUID
+ // by taking the KeyBytes stored in each Node and the final Leaf in order. This is
+ // the principle that Find is based on.
+ // (9) Insertion involves going down the trie until a difference between the key being inserted,
+ // and the existing key paths are found. When this happens, the Node or Leaf where the
+ // difference occurred is split into three nodes : a prefix Node, holding the part of the
+ // keys that were the same (garaunteed to be at least 1), a suffix Node or Leaf, holding the part
+ // of the original key in the trie, and a new Leaf, holding the rest of the inserted key.
+ // (10) Only leaves can be deleted, and thus have the Deleted flag set to 1
+ struct TrieNode
+ {
+ // Node info word allocated as follows:
+ //
+ // 15 14 13-5 4-0
+ // | D | F | L L L L L L L L L | K K K K K | m_wInfo
+ // | | | ^---------- # of bytes of key stored at node (5 bits)
+ // | | ^--------------------------- # of links to other nodes (9 bits)
+ // | ^---------------------------------------- 1 = Data stored at node (leaf) (1 bit leaf flag)
+ // | 0 = No data stored at node (non-leaf)
+ // ^------------------------------------------- 1 = Node deleted (1 bit deleted flag)
+ // 0 = Node not deleted
+ // Note that the number of allocated links is
+ // NODE_LINKS if NumLinks() < NODE_LINKS, or the closest multiple of NODE_GROWBY to NodeLinks()
+ // these constants are defined in psctbl2.cxx
+ WORD m_wInfo;
+
+ BYTE m_bData[2]; // Placeholder for data
+
+ // We use static functions and explicit "this" pointers (pRoot)
+ // so that we can remove recursion easily by changing pRoot on the fly
+
+ // Adds a key to a Trie starting at pRoot
+ static HRESULT AddKey(void *pBase, TrieNode *pRoot, TrieNodeBasedPtr UNALIGNED *ppPrev, const BYTE *pbKey,
+ GUIDIndex data, BOOL fReplace, CAllocFunctor &alloc);
+
+ // copies a trie to shared memory and returns a based pointer to it
+ static TrieNodeBasedPtr CopyToSharedMem(void *pNewBase, void *pOldBase, TrieNode *pRoot, CAllocFunctor &alloc);
+
+ // skeleton code as to how to go about key removal is included, but
+ // commented out.
+ //static BOOL RemoveKey(TrieNode *pRoot, const BYTE *pbKey);
+
+ // finds the data mapped to a key
+ static BOOL TraverseKey(void *pBase, TrieNode *pRoot, const BYTE *pbKey, GUIDIndex &data);
+
+ // public because members of CMapGuidToGuidBase and derived classes need to create leaves and nodes
+ static TrieNode *CreateTrieLeaf(const BYTE *pbKey, BYTE bKeyBytes, GUIDIndex data, CAllocFunctor &alloc);
+ static TrieNode *CreateTrieNode(const BYTE *pbKey, BYTE bKeyBytes, BYTE bLinks,
+ CAllocFunctor &alloc);
+
+ private:
+ // *** Internal Functions ***
+ // NOTE: All private inline TrieNode functions are implemented in psctbl2.cxx
+ // and therefore only accessable from there
+ inline int NumLinks() const;
+ inline int NumKeyBytes() const;
+ inline BOOL IsLeaf() const;
+ inline BOOL IsDeleted() const;
+ inline void SetLeaf(BOOL fLeaf);
+ inline void SetDeleted(BOOL fDeleted);
+ inline void SetKeyBytes(int nKeyBytes);
+ inline void SetLinks(int nLinks);
+ inline void IncrementLinks();
+ inline BYTE *GetKey();
+ inline GUIDIndex *GetData();
+ inline static int FindLinkSize(int nLinks);
+
+ // Returns the computed size of a node given the information about the node
+ inline static DWORD GetNodeSize(BYTE bKeyBytes, BOOL fLeaf, int bLinks);
+
+ // return the start of the link array
+ inline TrieNodeBasedPtr UNALIGNED *GetLinkStart() const;
+
+ // Function which inserts a pointer into the link array
+ // shifts nAfter nodes back one spot to make room
+ inline static void InsertIntoLinkArray(TrieNodeBasedPtr UNALIGNED *pArray, TrieNodeBasedPtr pNode, int nAfter);
+
+ // Returns S_OK if the node was added successfully
+ // returns S_FALSE if the a new block of links had to be allocated
+ // if this happens, a new TrieNode structure will be passed
+ // in ppNewNode, and the old TrieNode structure will be invalid
+ // This means any links to pRoot must be updated!!!!
+ static HRESULT AddLink(void *pBase, TrieNode *pRoot, TrieNode *pNode,
+ TrieNodeBasedPtr UNALIGNED *ppNewNode, CAllocFunctor &alloc);
+
+ // Returns the TrieNode associated with the next byte in the key (bKey),
+ // and also returns a pointer to where this link is stored.
+ // This pointer (ppLink) is necessary so that if AddLink requires us to update
+ // links to this retrieved node, we can do that.
+ TrieNode *GetLink(void *pBase, BYTE bKey, TrieNodeBasedPtr UNALIGNED*&ppLink);
+
+
+ // Creates a suffix node from an existing node, used for splitting tries up
+ TrieNode *CreateSuffixNode(BYTE bBytesDifferent, CAllocFunctor &alloc);
+
+ };
+
+ // *** Actual data for class ***
+ void *m_pMemBase; // the base address for all our memory needs
+ SharedMemHeader *m_pHeader; // our shared memory header
+};
+
+//+-------------------------------------------------------------------------
+//
+// Class: CPSClsidTbl
+//
+// Purpose: Trie-based GUID to GUID map, this is the DLL (client) side
+// implementation, which only allows read-only operations
+//
+// Interface: Initialize
+// Find
+//
+// History: 22-Jun-95 t-stevan Created
+//
+// Note: Again, optimized for IID->CLSID maps
+//--------------------------------------------------------------------------
+class CPSClsidTbl : public CMapGuidToGuidBase
+{
+ public:
+ HRESULT Initialize(void *pBase);
+
+ HRESULT Find(REFGUID keyGuid, GUID *pGuidOut) const;
+
+ inline BOOL IsFull() const;
+};
+
+//+-------------------------------------------------------------------------
+//
+// Class: CScmPSClsidTbl
+//
+// Purpose: Trie-based GUID to GUID map, this is the EXE (server) side
+// implementation, which only allows write ops
+//
+// Interface: CScmPSClsidTbl
+// Initialize
+// InitTbl
+// FreeTbl
+// CopyToSharedMem
+// Add
+// IsFull
+//
+// History: 22-Jun-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+class CScmPSClsidTbl : public CMapGuidToGuidBase
+{
+ public:
+ inline CScmPSClsidTbl();
+
+ // This initializes the object itself
+ HRESULT Initialize();
+
+ // This loads in the entries to the table from the registry
+ HRESULT InitTbl();
+
+ inline void FreeTbl();
+
+ // copies the locally built map to shared memory
+ HRESULT CopyToSharedMem(void *pBase, CSmStackAllocator &alloc);
+
+ // adds a key to the locally build map
+ HRESULT AddLocal(REFGUID keyGuid, REFGUID dataGuid, BOOL fReplace=FALSE);
+
+ //BOOL Delete(REFGUID keyGuid);
+
+ inline BOOL IsFull() const;
+
+ private:
+ // Information we use to create the trie
+ struct LocalMemHeader
+ {
+ CGUIDBlock m_GUIDs;
+ TrieNodeBasedPtr m_bpTrie;
+ BOOL m_fFull;
+ };
+
+ LocalMemHeader *m_pLocalHeader; // local tree information
+ HANDLE m_hHeap; // local heap used to construct the table
+
+};
+
+// *** Inline Functions ***
+//+-------------------------------------------------------------------------
+//
+// Function: CMapGuidToGuidBase::CMapGuidToGuidBase
+//
+// Synopsis: Constructor of GUID->GUID map
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+//--------------------------------------------------------------------------
+CMapGuidToGuidBase::CMapGuidToGuidBase() : m_pMemBase(NULL), m_pHeader(NULL)
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPSClsidTbl::IsFull
+//
+// Synopsis: Returns if the map is full
+//
+// Arguments: (none)
+//
+// Returns: TRUE if the map is full, FALSE is not
+//
+//--------------------------------------------------------------------------
+inline BOOL CPSClsidTbl::IsFull() const
+{
+ if(m_pHeader != NULL)
+ {
+ return m_pHeader->m_fFull;
+ }
+ else
+ {
+ Win4Assert(0 && "CPSClsidTbl::IsFull() called with no valid header!");
+
+ return TRUE;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CScmPSClsidTbl::CScmPSClsidTbl
+//
+// Synopsis: Constructor of GUID->GUID map, server side
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+//--------------------------------------------------------------------------
+CScmPSClsidTbl::CScmPSClsidTbl() : m_pLocalHeader(NULL), m_hHeap(NULL)
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmPSClsidTbl::IsFull
+//
+// Synopsis: Returns if the map is full
+//
+// Arguments: (none)
+//
+// Returns: TRUE if the map is full, FALSE is not
+//
+//--------------------------------------------------------------------------
+inline BOOL CScmPSClsidTbl::IsFull() const
+{
+ if(m_pLocalHeader != NULL)
+ {
+ return m_pLocalHeader->m_fFull;
+ }
+ else if(m_pHeader != NULL)
+ {
+ return m_pHeader->m_fFull;
+ }
+ else
+ {
+ Win4Assert(0 && "CScmPSClsidTbl::IsFull() called with no valid header!");
+
+ return TRUE;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CScmPSClsidTbl::FreeTbl
+//
+// Synopsis: Frees up the locally allocated table
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+//--------------------------------------------------------------------------
+void CScmPSClsidTbl::FreeTbl()
+{
+ Win4Assert(m_hHeap != NULL);
+
+ HeapDestroy(m_hHeap);
+
+ m_hHeap = NULL;
+}
+
+#endif // __GUIDMAP2_HXX__
diff --git a/private/ole32/com/inc/rotdata.cxx b/private/ole32/com/inc/rotdata.cxx
new file mode 100644
index 000000000..fe3d3ab84
--- /dev/null
+++ b/private/ole32/com/inc/rotdata.cxx
@@ -0,0 +1,242 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: rotdata.cxx
+//
+// Contents: Functions supporting building ROT data comparison buffers
+//
+// Functions:
+//
+// History: 03-Feb-95 Ricksa Created
+//
+//----------------------------------------------------------------------------
+#include <ole2int.h>
+#include <rotdata.hxx>
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: BuildRotDataFromDisplayName
+//
+// Synopsis: Build ROT comparison data from display name
+//
+// Arguments: [pbc] - bind context (optional)
+// [pmk] - moniker to use for display name
+// [pbData] - buffer to put the data in.
+// [cbMax] - size of the buffer
+// [pcbData] - count of bytes used in the buffer
+//
+// Returns: NOERROR
+// E_OUTOFMEMORY
+//
+// Algorithm: Build the bind context if necessary. Get the display name.
+// See if there is enough room in the buffer for the display
+// name and the clsid. If there is copy it in.
+//
+// History: 03-Feb-95 ricksa Created
+//
+// Note:
+//
+//----------------------------------------------------------------------------
+HRESULT BuildRotDataFromDisplayName(
+ LPBC pbc,
+ IMoniker *pmk,
+ BYTE *pbData,
+ DWORD cbData,
+ DWORD *pcbUsed)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN BuildRotDataFromDisplayName"
+ "( %p , %p , %p , %lx , %p )\n", NULL, pbc, pmk, pbData, cbData,
+ pcbUsed));
+
+ HRESULT hr;
+ BOOL fCreatedBindCtx = FALSE;
+ WCHAR *pwszDisplayName = NULL;
+
+ BEGIN_BLOCK
+
+ // Do we have a bind context to work with?
+ if (pbc == NULL)
+ {
+ // Get the display name
+ if ((hr = CreateBindCtx(0, &pbc)) != NOERROR)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "BuildRotDataFromDisplayName CreateBindCtx Failed %lx\n",
+ hr));
+
+ EXIT_BLOCK;
+ }
+
+ fCreatedBindCtx = TRUE;
+ }
+
+ if ((hr = pmk->GetDisplayName(pbc, NULL, &pwszDisplayName)) != NOERROR)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "BuildRotDataFromDisplayName IMoniker::GetDisplayName "
+ "failed %lx\n", hr));
+ EXIT_BLOCK;
+ }
+
+ DWORD dwLen = (lstrlenW(pwszDisplayName) + 1) * sizeof(WCHAR)
+ + sizeof(CLSID);
+
+ CLSID clsid;
+
+ // Get the class id if we can
+ if ((hr = pmk->GetClassID(&clsid)) == NOERROR)
+ {
+ // Assume that it is too big
+ hr = E_OUTOFMEMORY;
+
+ // Can the buffer hold all the data?
+ if (dwLen <= cbData)
+ {
+ // Yes, so copy it in
+
+ // First the CLSID
+ memcpy(pbData, &clsid, sizeof(CLSID));
+
+ // Uppercase the display name
+ CharUpperW(pwszDisplayName);
+
+ // Then the string for the display name
+ lstrcpyW((WCHAR *) (pbData + sizeof(CLSID)), pwszDisplayName);
+
+ *pcbUsed = dwLen;
+
+ hr = S_OK;
+ }
+#if DBG == 1
+ else
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "BuildRotDataFromDisplayName Comparison buffer too bing\n"));
+ }
+#endif // DBG == 1
+ }
+#if DBG == 1
+ else
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "BuildRotDataFromDisplayName IMoniker::GetClassID failed %lX\n",
+ hr));
+ }
+#endif // DBG == 1
+
+
+ END_BLOCK;
+
+ if (pwszDisplayName != NULL)
+ {
+ CoTaskMemFree(pwszDisplayName);
+ }
+
+ if (fCreatedBindCtx)
+ {
+ pbc->Release();
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT BuildRotDataFromDisplayName"
+ "( %lx ) [ %lx ]\n", NULL, hr, *pcbUsed));
+
+ return hr;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: BuildRotData
+//
+// Synopsis: Build ROT comparison data from a moniker
+//
+// Arguments: [pmk] - moniker to use for display name
+// [pbData] - buffer to put the data in.
+// [cbMax] - size of the buffer
+// [pcbData] - count of bytes used in the buffer
+//
+// Returns: NOERROR
+// E_OUTOFMEMORY
+//
+// Algorithm: See if the moniker supports IROT data. If it does, then
+// use the result from that otherwise call through to
+// BuildRotDataFromDisplayName to build the data from the
+// display name if possible.
+//
+// History: 03-Feb-95 ricksa Created
+//
+// Note:
+//
+//----------------------------------------------------------------------------
+HRESULT BuildRotData(
+ LPBC pbc,
+ IMoniker *pmk,
+ BYTE *pbData,
+ DWORD cbData,
+ DWORD *pcbUsed)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN BuildRotData"
+ "( %p , %p , %p , %lx , %p )\n", NULL, pbc, pmk, pbData, cbData,
+ pcbUsed));
+
+ HRESULT hr;
+ IROTData *protdata = NULL;
+
+ BEGIN_BLOCK
+
+ // Does the moniker support the new interface for registering
+ // in the ROT?
+ if (pmk->QueryInterface(IID_IROTData, (void **) &protdata)
+ == NOERROR)
+ {
+ hr = protdata->GetComparisonData(
+ pbData,
+ cbData,
+ pcbUsed);
+
+#if DBG == 1
+ if (FAILED(hr))
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "BuildRotData IROTData::GetComparisonData failed %lX\n",
+ hr));
+ }
+#endif // DBG == 1
+
+ if (SUCCEEDED(hr) && (hr != NOERROR))
+ {
+ // We got a success code that was not NOERROR. This makes
+ // no sense since the only thing that can happen is the
+ // buffer is filled with data. Therefore, we remap this to
+ // an error.
+ CairoleDebugOut((DEB_ERROR,
+ "BuildRotData IROTData::GetComparisonData return bad"
+ " success %lX\n", hr));
+
+ hr = E_UNEXPECTED;
+ }
+
+ EXIT_BLOCK;
+ }
+
+ hr = BuildRotDataFromDisplayName(NULL, pmk, pbData, cbData, pcbUsed);
+
+ END_BLOCK;
+
+ if (protdata != NULL)
+ {
+ protdata->Release();
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT BuildRotData"
+ "( %lx ) [ %lx ]\n", NULL, hr, *pcbUsed));
+
+ return hr;
+}
diff --git a/private/ole32/com/inc/rotdata.hxx b/private/ole32/com/inc/rotdata.hxx
new file mode 100644
index 000000000..19591664e
--- /dev/null
+++ b/private/ole32/com/inc/rotdata.hxx
@@ -0,0 +1,80 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: rotdata.hxx
+//
+// Contents: Functions supporting building ROT data comparison buffers
+//
+// Functions: BuildRotDataFromDisplayName
+// BuildRotData
+//
+// History: 03-Feb-95 Ricksa Created
+//
+//----------------------------------------------------------------------------
+#ifndef __ROTDATA_HXX__
+#define __ROTDATA_HXX__
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: BuildRotDataFromDisplayName
+//
+// Synopsis: Build ROT comparison data from display name
+//
+// Arguments: [pbc] - bind context (optional)
+// [pmk] - moniker to use for display name
+// [pbData] - buffer to put the data in.
+// [cbMax] - size of the buffer
+// [pcbData] - count of bytes used in the buffer
+//
+// Returns: NOERROR
+// E_OUTOFMEMORY
+//
+// Algorithm: See rotdata.cxx
+//
+// History: 03-Feb-95 ricksa Created
+//
+// Note:
+//
+//----------------------------------------------------------------------------
+HRESULT BuildRotDataFromDisplayName(
+ LPBC pbc,
+ IMoniker *pmk,
+ BYTE *pbData,
+ DWORD cbData,
+ DWORD *pcbUsed);
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: BuildRotData
+//
+// Synopsis: Build ROT comparison data from a moniker
+//
+// Arguments: [pmk] - moniker to use for display name
+// [pbData] - buffer to put the data in.
+// [cbMax] - size of the buffer
+// [pcbData] - count of bytes used in the buffer
+//
+// Returns: NOERROR
+// E_OUTOFMEMORY
+//
+// Algorithm: See rotdata.cxx
+//
+// History: 03-Feb-95 ricksa Created
+//
+// Note:
+//
+//----------------------------------------------------------------------------
+HRESULT BuildRotData(
+ LPBC pbc,
+ IMoniker *pmk,
+ BYTE *pbData,
+ DWORD cbData,
+ DWORD *pcbUsed);
+
+
+#endif // __ROTDATA_HXX__
diff --git a/private/ole32/com/inc/rothelp.cxx b/private/ole32/com/inc/rothelp.cxx
new file mode 100644
index 000000000..154d27895
--- /dev/null
+++ b/private/ole32/com/inc/rothelp.cxx
@@ -0,0 +1,125 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: rothelp.cxx
+//
+// Contents: Implementation of helpers used by SCM and OLE32
+//
+// Functions: CreateFileMonikerComparisonBuffer
+//
+// History: 30-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include <rothint.hxx>
+#include <rothelp.hxx>
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ScmRotHash
+//
+// Synopsis: Calculate hash value of comparison buffer in the SCM.
+//
+// Arguments: [pbKey] - pointer to buffer
+// [cdwKey] - size of buffer
+// [dwInitHash] - Initial hash value
+//
+// Returns: Hash value for SCM ROT entry.
+//
+// History: 30-Jan-95 Ricksa Created
+// 30-Nov-95 BruceMa Don't let the hash value overflow
+//
+// Note: The 3rd parameter is used only by RunningMoniker which
+// needs to compute partial hashes by path components
+//
+//--------------------------------------------------------------------------
+DWORD ScmRotHash(BYTE *pbKey, DWORD cdwKey, DWORD dwInitHash)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN ScmRotHash"
+ "( %p , %lx )\n", NULL, pbKey, cdwKey));
+
+ DWORD dwResult = dwInitHash;
+
+ for (DWORD i = 0; i < cdwKey; i++)
+ {
+ dwResult *= 3;
+ dwResult ^= *pbKey;
+ dwResult %= SCM_HASH_SIZE;
+ pbKey++;
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT ScmRotHash"
+ "( %lx )\n", NULL, dwResult % SCM_HASH_SIZE));
+
+ return dwResult;
+}
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateFileMonikerComparisonBuffer
+//
+// Synopsis: Convert a file path to a moniker comparison buffer
+//
+// Arguments: [pwszPath] - path
+// [pbBuffer] - comparison buffer
+// [cdwMaxSize] - maximum size of the comparison buffer
+// [cdwUsed] - number of bytes used in the comparison buffer
+//
+// Returns: NOERROR - comparison buffer successfully created
+// E_OUTOFMEMORY - The buffer was not big enough to hold the data.
+//
+// History: 30-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CreateFileMonikerComparisonBuffer(
+ WCHAR *pwszPath,
+ BYTE *pbBuffer,
+ DWORD cdwMaxSize,
+ DWORD *pcdwUsed)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CreateFileMonikerComparisonBuffer"
+ "( %p , %p , %lx , %p )\n", NULL, pwszPath, pbBuffer, cdwMaxSize,
+ pcdwUsed));
+
+ // Assume there will be an error
+ HRESULT hr = E_OUTOFMEMORY;
+ *pcdwUsed = 0;
+
+ // Cache size needed for path locally. Of course, the "+1" is required
+ // for the terminating NUL in the string.
+ DWORD cdwPath = (lstrlenW(pwszPath) + 1) * sizeof(WCHAR);
+
+ // Figure out if the buffer is being enough to hold the data.
+ DWORD cdwSizeNeeded = sizeof(CLSID) + cdwPath;
+
+ if (cdwSizeNeeded <= cdwMaxSize)
+ {
+ // Copy in the CLSID for a file moniker
+ memcpy(pbBuffer, &CLSID_FileMoniker, sizeof(CLSID_FileMoniker));
+
+ // Copy in the path
+ memcpy(pbBuffer + sizeof(CLSID_FileMoniker), pwszPath, cdwPath);
+
+ // Uppercase the path in the comparison buffer
+ CharUpperW((WCHAR *) (pbBuffer + sizeof(CLSID_FileMoniker)));
+
+ *pcdwUsed = cdwSizeNeeded;
+
+ hr = NOERROR;
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CreateFileMonikerComparisonBuffer"
+ "( %lx ) [ %lx ]\n", NULL, hr, *pcdwUsed));
+
+ return hr;
+}
diff --git a/private/ole32/com/inc/rothelp.hxx b/private/ole32/com/inc/rothelp.hxx
new file mode 100644
index 000000000..a82d4f29e
--- /dev/null
+++ b/private/ole32/com/inc/rothelp.hxx
@@ -0,0 +1,168 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: rothelp.hxx
+//
+// Contents: Definition of helpers that are shared between SCM and OLE32
+//
+// Classes: CTmpMkEqBuf
+//
+// History: 30-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __ROTHELP_HXX__
+#define __ROTHELP_HXX__
+
+#include <irot.h>
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTmpMkEqBuf
+//
+// Purpose: Encapsulate the difference in RPC format to the SCM
+// and the format passed to IROTData interface.
+//
+// Interface: GetMkEqBuf - get the pointer the buffer approproiate for SCM
+//
+// History: 26-Jan-95 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+class CTmpMkEqBuf
+{
+public:
+
+ MNKEQBUF * GetMkEqBuf(void);
+
+ BYTE * GetBuf(void);
+
+ DWORD GetSize(void);
+
+ DWORD * GetSizeAddr(void);
+
+private:
+
+ MNKEQBUF _mkeqbuf;
+
+ // Subtract 1 from max size because MNKEQBUF has
+ // a buffer defined of one byte.
+ BYTE _abData[ROT_COMPARE_MAX - 1];
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTmpMkEqBuf::GetMkEqBuf
+//
+// Synopsis: Get a pointer to the MNKEQBUF
+//
+// History: 26-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline MNKEQBUF *CTmpMkEqBuf::GetMkEqBuf(void)
+{
+ return &_mkeqbuf;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTmpMkEqBuf::GetBuf
+//
+// Synopsis: Get pointer to buffer to stick comparison data
+//
+// History: 26-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BYTE *CTmpMkEqBuf::GetBuf(void)
+{
+ return &_mkeqbuf.abEqData[0];
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTmpMkEqBuf::GetSize
+//
+// Synopsis: Get size of data buffer
+//
+// History: 26-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline DWORD CTmpMkEqBuf::GetSize(void)
+{
+ return ROT_COMPARE_MAX;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTmpMkEqBuf::GetSizeAddr
+//
+// Synopsis: Get pointer to the size of the buffer
+//
+// History: 26-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline DWORD *CTmpMkEqBuf::GetSizeAddr(void)
+{
+ return &_mkeqbuf.cdwSize;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateFileMonikerComparisonBuffer
+//
+// Synopsis: Convert a file path to a moniker comparison buffer
+//
+// Arguments: [pwszPath] - path
+// [pbBuffer] - comparison buffer
+// [cdwMaxSize] - maximum size of the comparison buffer
+// [cdwUsed] - number of bytes used in the comparison buffer
+//
+// History: 30-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CreateFileMonikerComparisonBuffer(
+ WCHAR *pwszPath,
+ BYTE *pbBuffer,
+ DWORD cdwMaxSize,
+ DWORD *cUsed);
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ScmRotHash
+//
+// Synopsis: Calculate hash value of comparison buffer in the SCM.
+//
+// Arguments: [pbKey] - pointer to buffer
+// [cdwKey] - size of buffer
+//
+// Returns: Hash value for SCM ROT entry.
+//
+// History: 30-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+DWORD ScmRotHash(BYTE *pbKey, DWORD cdwKey, DWORD dwInitHash);
+
+
+
+
+
+#endif // __ROTHELP_HXX__
diff --git a/private/ole32/com/inc/rpcbind.hxx b/private/ole32/com/inc/rpcbind.hxx
new file mode 100644
index 000000000..676d6678d
--- /dev/null
+++ b/private/ole32/com/inc/rpcbind.hxx
@@ -0,0 +1,291 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: rpcbind.hxx
+//
+// Contents: Class to encapsulate various bindings to Rpc servers
+//
+// Classes: CRpcBindHandle
+// CRpcOwnedBindString
+//
+// Functions: CRpcBindHandle::CRpcBindHandle
+// CRpcBindHandle::~CRpcBindHandle
+// CRpcBindHandle::BindByString
+// CRpcBindHandle::Handle
+// CRpcBindString::CRpcBindString
+// CRpcBindString::~CRpcBindString
+// CRpcBindString::BindToServer
+//
+// History: 17-Jul-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __RPCBIND__
+#define __RPCBIND__
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CRpcBindHandle
+//
+// Purpose: Encapsulate a basic RPC binding handle
+//
+// Interface: BindByString - binds to server by string address
+// Handle - return handle to bound server
+//
+// History: 17-Jul-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CRpcBindHandle
+{
+public:
+
+ CRpcBindHandle(void);
+
+ ~CRpcBindHandle(void);
+
+ HRESULT BindByString(LPWSTR pwszBindingString);
+
+ void UnBind(void);
+
+ handle_t Handle(void);
+
+private:
+
+ handle_t _hServer;
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcBindHandle::CRpcBindHandle, public
+//
+// Synopsis: Create object with invalid handle
+//
+// History: 17-Jul-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CRpcBindHandle::CRpcBindHandle(void)
+ : _hServer(0)
+{
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcBindHandle::~CRpcBindHandle, public
+//
+// Synopsis: Unbinds from handle and frees the object
+//
+// History: 17-Jul-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CRpcBindHandle::~CRpcBindHandle(void)
+{
+ UnBind();
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcBindHandle::BindByString, public
+//
+// Synopsis: Bind to a server based on the RPC address string
+//
+// Arguments: [pszBindingString] - RPC address string
+//
+// History: 17-Jul-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CRpcBindHandle::BindByString(LPWSTR pwszBindingString)
+{
+ // Do the bind
+ CairoleDebugOut((DEB_ITRACE, "Binding To: %ws\n", pwszBindingString));
+
+ RPC_STATUS status =
+ RpcBindingFromStringBinding(pwszBindingString, &_hServer);
+
+ Win4Assert((status == NO_ERROR)
+ && "CRpcBindHandle - RpcBindingFromStringBinding failed");
+
+ return (status == NO_ERROR) ? S_OK : HRESULT_FROM_WIN32(status);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcBindHandle::UnBind, public
+//
+// Synopsis: Release our binding handle to a given server
+//
+// History: 17-Jul-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CRpcBindHandle::UnBind(void)
+{
+ // Do the bind
+ if (_hServer != NULL)
+ {
+ RPC_STATUS status = RpcBindingFree(&_hServer);
+
+ Win4Assert((status == NO_ERROR)
+ && "CRpcBindHandle - UnBind failed");
+
+ _hServer = NULL;
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcBindHandle::Handle, public
+//
+// Synopsis: Returns the binding handle for use by APIs
+//
+// History: 17-Jul-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline handle_t CRpcBindHandle::Handle(void)
+{
+ return _hServer;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CRpcBindString
+//
+// Purpose: Encasulate an address string for RPC.
+//
+// Interface: BindToServer - Binds to an RPC server based on the string
+// DoBind - Bind based on the string
+//
+// History: 17-Jul-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CRpcBindString
+{
+public:
+
+ CRpcBindString(void);
+
+ ~CRpcBindString(void);
+
+ HRESULT CreateBindString(
+ LPWSTR pszProtocolSequence,
+ LPWSTR pszNetworkAddress,
+ LPWSTR pszEndPoint);
+
+ LPWSTR GetStringPtr(void);
+
+private:
+
+ LPWSTR _pwszBindString;
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcBindString::CRpcBindString, public
+//
+// Synopsis: Allocates an empty object
+//
+// History: 17-Jul-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CRpcBindString::CRpcBindString(void) : _pwszBindString(NULL)
+{
+ // Header does the work
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcBindString::~CRpcBindString, public
+//
+// Synopsis: Free address string if there is one
+//
+// History:17-Jul-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CRpcBindString::~CRpcBindString(void)
+{
+ if (_pwszBindString)
+ {
+ RpcStringFree(&_pwszBindString);
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcBindString::CreateBindString, public
+//
+// Synopsis: Create a binding string
+//
+// Arguments: [pszBindString] - RPC address string
+//
+// History: 17-Jul-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CRpcBindString::CreateBindString(
+ LPWSTR pwszProtocolSequence,
+ LPWSTR pwszNetworkAddress,
+ LPWSTR pwszEndPoint)
+{
+ // Bind to object server
+ RPC_STATUS status = RpcStringBindingCompose(
+ NULL,
+ pwszProtocolSequence,
+ pwszNetworkAddress,
+ pwszEndPoint,
+ NULL,
+ &_pwszBindString);
+
+ // Convert status to an hresult and pass it back
+ return (status == ERROR_SUCCESS) ? S_OK : HRESULT_FROM_WIN32(status);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRpcBindString::GetStringPtr, public
+//
+// Synopsis: Get pointer to binding string
+//
+// Arguments: [pszBindString] - RPC address string
+//
+// History: 26-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline LPWSTR CRpcBindString::GetStringPtr(void)
+{
+ return _pwszBindString;
+}
+
+
+
+
+#endif // __RPCBIND__
diff --git a/private/ole32/com/inc/scmmem.hxx b/private/ole32/com/inc/scmmem.hxx
new file mode 100644
index 000000000..ca73ed9b2
--- /dev/null
+++ b/private/ole32/com/inc/scmmem.hxx
@@ -0,0 +1,53 @@
+//+-------------------------------------------------------------------
+//
+// File: scmmem.hxx
+//
+// Contents: Shared allocator or not depending on SCM-less or not
+//
+// History: 20-Sep-94 BillMo Created
+//
+//---------------------------------------------------------------------
+
+#ifndef _SCMMEM_HXX_
+#define _SCMMEM_HXX_
+
+#define SCMBASED
+
+#if !defined(_CHICAGO_)
+
+//---------------------------------------------------------------------
+// OLE with SCM -- memory allocation
+//---------------------------------------------------------------------
+
+#define ScmMemAlloc PrivMemAlloc
+#define ScmMemFree PrivMemFree
+#define CScmAlloc CPrivAlloc
+
+#else
+
+//---------------------------------------------------------------------
+// OLE without SCM -- shared memory allocation
+//---------------------------------------------------------------------
+
+extern void *ScmMemAlloc(size_t size);
+extern void ScmMemFree(void * pv);
+
+class CScmAlloc
+{
+public:
+ void *operator new(size_t size);
+ void operator delete(void *pv);
+};
+
+inline void *CScmAlloc::operator new(size_t size)
+{
+ return ScmMemAlloc(size);
+}
+
+inline void CScmAlloc::operator delete(void *pv)
+{
+ ScmMemFree(pv);
+}
+
+#endif
+#endif
diff --git a/private/ole32/com/inc/scmstart.hxx b/private/ole32/com/inc/scmstart.hxx
new file mode 100644
index 000000000..71e12f4d8
--- /dev/null
+++ b/private/ole32/com/inc/scmstart.hxx
@@ -0,0 +1,69 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: scmstart.hxx
+//
+// Contents: Win9x only definitions.
+//
+// Classes: SOleSharedTables
+//
+// History: 05-Oct-93 Ricksa Created
+// 25-Jan-95 Ricksa New ROT implementation
+//
+//--------------------------------------------------------------------------
+
+//
+// The SOleSharedTables and friends are only used on Win95
+//
+
+#ifdef _CHICAGO_
+
+// Forward declarations
+class CScmRot;
+class CHandlerList;
+class CInProcList;
+class CLocSrvList;
+class CRemSrvList;
+class CClassCacheList;
+class CStringID;
+
+//+-------------------------------------------------------------------------
+//
+// Struct: SOleSharedTables
+//
+// Purpose: Hold pointer to tables common to all OLE processes
+//
+// History: 17-Nov-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+struct SOleSharedTables
+{
+ DWORD dwNextProcessID;
+
+ CScmRot * pscmrot;
+
+ CHandlerList * gpCHandlerList;
+
+ CInProcList * gpCInProcList;
+
+ CLocSrvList * gpCLocSrvList;
+
+ CRemSrvList * gpCRemSrvList;
+
+ CClassCacheList * gpCClassCacheList;
+
+ LONG lSharedObjId;
+
+
+};
+
+// Global per process pointer to the above shared memory.
+extern SOleSharedTables *g_post;
+
+HRESULT StartSCM(void);
+
+#endif // _CHICAGO_
+
diff --git a/private/ole32/com/inc/secdes.hxx b/private/ole32/com/inc/secdes.hxx
new file mode 100644
index 000000000..2b39cbdb3
--- /dev/null
+++ b/private/ole32/com/inc/secdes.hxx
@@ -0,0 +1,62 @@
+//+-------------------------------------------------------------------
+//
+// File: secdes.hxx
+//
+// Contents: Encapsulates all access allowed Win32 security descriptor.
+//
+// Classes: CWorldSecurityDescriptor
+//
+// Functions: none
+//
+// History: 07-Aug-92 randyd Created.
+//
+//--------------------------------------------------------------------
+
+#ifndef __SECDES_HXX__
+#define __SECDES_HXX__
+
+
+#include <debnot.h>
+
+
+class CWorldSecurityDescriptor
+{
+public:
+ // Default constructor creates a descriptor that allows all access.
+ CWorldSecurityDescriptor();
+
+ // Return a PSECURITY_DESCRIPTOR
+ operator PSECURITY_DESCRIPTOR() const {return((PSECURITY_DESCRIPTOR) &_sd); };
+
+private:
+
+ // The security descriptor.
+ SECURITY_DESCRIPTOR _sd;
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CWorldSecurityDescriptor
+//
+// Synopsis: Create an all acccess allowed security descriptor.
+//
+// History: 07-Aug-92 randyd Created.
+//
+//--------------------------------------------------------------------------
+
+inline CWorldSecurityDescriptor::CWorldSecurityDescriptor()
+{
+ BOOL fSucceeded = InitializeSecurityDescriptor(&_sd, 1);
+ Win4Assert(fSucceeded && "InitializeSecurityDescriptor Failed!");
+
+ // According to richardw, this sets up a sd with "all" access.
+ fSucceeded = SetSecurityDescriptorDacl(&_sd, TRUE, NULL, FALSE);
+ Win4Assert(fSucceeded && "SetSecurityDescriptorDacl Failed!");
+}
+
+
+#endif // __SECDES_HXX__
+
diff --git a/private/ole32/com/inc/shrtbl.hxx b/private/ole32/com/inc/shrtbl.hxx
new file mode 100644
index 000000000..0a8534c5c
--- /dev/null
+++ b/private/ole32/com/inc/shrtbl.hxx
@@ -0,0 +1,310 @@
+//+---------------------------------------------------------------------------//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: shrtbl.hxx
+//
+// Contents: shared memory tables
+//
+// Classes: CScmShrdTbl - SCM version of the class
+// CDllShrdTbl - DLL version of the class
+//
+// History: 12-May-94 Rickhi Created
+// 04-Feb-96 BruceMa Add per-user registry support
+//
+// Notes: This class caches various tables in shared memory. The
+// tables are typically small, used by all OLE processes,
+// rarely change, and are expensive to lookup manually in
+// the registry, hence they are cached in shared memory.
+//
+//----------------------------------------------------------------------------
+
+#ifndef __SHRDTBL__
+#define __SHRDTBL__
+
+#include <smmutex.hxx> // CSmMutex
+#include <smblock.hxx> // CSharedMemoryBlock
+#include <pattbl.hxx> // CPatternTbl
+#include <psctbl.hxx> // CPSClsidTbl
+#include <exttbl.hxx> // CFileExtTbl
+
+
+// name and sizes of the shared memory region
+
+#define SHRDTBL_NAME TEXT("OLESharedTables")
+#define SHRDTBL_MUTEX_NAME TEXT("OLESharedTablesMutex")
+#define SHRDTBL_EVENT_NAME TEXT("OLESharedTablesEvent")
+
+#define SHRDTBL_MAX_SIZE 16384
+#define SHRDTBL_MIN_SIZE 4096
+
+#ifdef _CHICAGO_ // for Chicago ANSI optimization
+#undef CreateEvent
+#define CreateEvent CreateEventA
+#undef OpenEvent
+#define OpenEvent OpenEventA
+#endif
+// structure for global table info. This appears at the start of the table
+// and is used by all readers.
+
+typedef struct SShrdTblHdr
+{
+ DWORD dwSeqNum; // update sequence number
+ ULONG OffsIIDTbl; // offset of the start of IID table
+ ULONG OffsPatTbl; // offset to start of file pattern table
+ ULONG OffsExtTbl; // offset to file extension table
+ ULONG OffsClsTbl; // offset to start of CLSID table
+// Make sure this header is 8-byte bounded
+} SShrdTblHdr;
+
+
+
+//+---------------------------------------------------------------------------
+//
+// class: CScmShrdTbl
+//
+// synopsis: This holds the SCM version of the table classes, which are
+// responsible for building the tables, and updating them when
+// the registy data changes.
+//
+// History: 12-May-94 Rickhi Created
+//
+//----------------------------------------------------------------------------
+class CScmShrdTbl
+{
+public:
+ CScmShrdTbl(HRESULT& hr);
+ ~CScmShrdTbl();
+
+ HRESULT UpdateNoLock(); // update table, dont take lock
+ HRESULT UpdateWithLock(); // update table, take the lock
+
+private:
+
+ HRESULT GetSharedMem(ULONG ulTblSize);
+
+ CSharedMemoryBlock _smb; // shared memory class
+ CSmMutex _mxs; // shared mutex for use by clients
+ CMutexSem _mxsLocal; // local lock to prevent multiple
+ // updates.
+ HANDLE _hRegEvent; // shared event handle
+
+ CScmPSClsidTbl _PSClsidTbl; // proxy stub clsid table
+ CScmPatternTbl _PatternTbl; // file pattern table
+ CScmFileExtTbl _FileExtTbl; // file extension table
+
+ SShrdTblHdr *_pShrdTblHdr; // ptr to table header
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmShrdTbl::~CScmShrdTbl
+//
+// Synopsis: destructor for the SCM shared memory table
+//
+//--------------------------------------------------------------------------
+inline CScmShrdTbl::~CScmShrdTbl()
+{
+ // other destructors do the rest of the work
+
+ if (_hRegEvent != NULL)
+ {
+ CloseHandle(_hRegEvent);
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// class: CDllShrdTbl
+//
+// synopsis: This holds the DLL version of the classes, which only
+// need to read the tables, not write to them.
+//
+// History: 20-May-94 Rickhi Created
+//
+//----------------------------------------------------------------------------
+class CDllShrdTbl
+{
+public:
+ CDllShrdTbl(HRESULT &hr);
+ ~CDllShrdTbl();
+
+ HRESULT FindPSClsid(REFIID riid, CLSID *pclsid);
+ HRESULT FindPattern(HANDLE hfile, CLSID *pclsid);
+ HRESULT FindClassExt(LPCWSTR pwszExt, CLSID *pclsid);
+ BOOL IsPatternTblEmpty(void);
+
+private:
+
+ SShrdTblHdr * GetSharedMem(void); // return ptr to shared mem
+ void Update(void); // update the table headers
+
+ CSharedMemoryBlock _smb; // shared memory block
+ CSmMutex _mxs; // shared mutex
+ HANDLE _hRegEvent; // shared event handle
+
+ CPSClsidTbl _PSClsidTbl; // proxy stub clsid table
+ CPatternTbl _PatternTbl; // file pattern table
+ CFileExtTbl _FileExtTbl; // file extension table
+
+ SShrdTblHdr *_pShrdTblHdr; // shared mem copy of table
+ DWORD _dwSeqNum; // sequence number
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllShrdTbl::~CDllShrdTbl
+//
+// Synopsis: destructor for the client side shared memory table
+//
+//--------------------------------------------------------------------------
+inline CDllShrdTbl::~CDllShrdTbl()
+{
+ // close the event handle
+ CloseHandle(_hRegEvent);
+
+ // other destructors do the rest of the work
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllShrdTbl::FindPSClsid
+//
+// Synopsis: finds the clsid for an iid by looking in the shared mem
+// cache.
+//
+// Arguments: [riid] - the interface to map
+// [pclsid] - where to return the clsid
+//
+// Returns: S_OK if found
+// E_OUTOFMEMORY if cache does not exist
+//
+//--------------------------------------------------------------------------
+inline HRESULT CDllShrdTbl::FindPSClsid(REFIID riid, CLSID *pclsid)
+{
+ CLockSmMutex lck(_mxs);
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ if ((GetSharedMem() != NULL) && (_pShrdTblHdr->OffsIIDTbl != 0))
+ {
+ hr = _PSClsidTbl.Find(riid, pclsid);
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllShrdTbl::FindPattern
+//
+// Synopsis: finds the clsid for a file via pattern matching
+//
+// Arguments: [hfile] - handle to the open file
+// [pclisd] - where to return the clsid
+//
+// Returns: S_OK if found,
+// E_OUTOFMEMORY if cache does not exist
+//
+//--------------------------------------------------------------------------
+inline HRESULT CDllShrdTbl::FindPattern(HANDLE hfile, CLSID *pclsid)
+{
+ CLockSmMutex lck(_mxs);
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ if ((GetSharedMem() != NULL) && (_pShrdTblHdr->OffsPatTbl != 0))
+ {
+ hr = _PatternTbl.FindPattern(hfile, pclsid);
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllShrdTbl::IsPatternTblEmpty
+//
+// Synopsis: determines if the pattern table is empty, so that we can
+// bypass opening the file if there are no patterns to match.
+//
+// Arguments: none
+//
+// Returns: TRUE if the table is empty,
+// FALSE if not, or the cache does not exist
+//
+//--------------------------------------------------------------------------
+inline BOOL CDllShrdTbl::IsPatternTblEmpty()
+{
+ CLockSmMutex lck(_mxs);
+
+ BOOL fEmpty = FALSE;
+
+ if ((GetSharedMem() != NULL) && (_pShrdTblHdr->OffsPatTbl != 0))
+ {
+ fEmpty = _PatternTbl.IsEmpty();
+ }
+
+ return fEmpty;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllShrdTbl::FindClassExt
+//
+// Synopsis: finds the clsid for a file by looking at the filename
+// extension.
+//
+// Arguments: [pszExt] - file name extension
+// [pclsid] - where to return the clsid
+//
+// Returns: S_OK if found
+// REG_DB_CLASSNOTREG if no entry in the cache
+// E_OUTOFMEMORY if cache does not exist
+//
+//--------------------------------------------------------------------------
+inline HRESULT CDllShrdTbl::FindClassExt(LPCWSTR pszExt, CLSID *pclsid)
+{
+ CLockSmMutex lck(_mxs);
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ if ((GetSharedMem() != NULL) && (_pShrdTblHdr->OffsExtTbl != 0))
+ {
+ hr = _FileExtTbl.FindClassExt(pszExt, pclsid);
+ }
+
+ return hr;
+}
+
+#ifdef REVISIT_PERSONAL_CLASSES_FOR_NT50
+// NT 5.0
+/***
+//+-------------------------------------------------------------------------
+//
+// Member: CDllShrdTbl::GetPersonalClasses
+//
+// Synopsis: Returns whether PersonalClasses is turned on
+//
+// Arguments: -
+//
+// Returns: TRUE is PersonalClasses is turned on
+// FALSE otherwise
+//
+//--------------------------------------------------------------------------
+inline BOOL CDllShrdTbl::GetPersonalClasses(void)
+{
+ return _pShrdTblHdr->fPersonalClasses;
+}
+***/
+#endif
+
+#endif // __SHRDTBL__
diff --git a/private/ole32/com/inc/shrtblc.cxx b/private/ole32/com/inc/shrtblc.cxx
new file mode 100644
index 000000000..68ecceab6
--- /dev/null
+++ b/private/ole32/com/inc/shrtblc.cxx
@@ -0,0 +1,172 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: shrtbl.cxx
+//
+// Contents: shared memory tables - client side
+//
+// Classes: CDllShrdTbl - DLL version of the class
+//
+// History: 12-May-94 Rickhi Created
+//
+// Notes: This class caches various tables in shared memory. The
+// tables are typically small, used by all OLE processes,
+// rarely change, and are expensive to lookup manually in
+// the registry, hence they are cached in shared memory.
+//
+// The caches are created by the SCM (which has write access),
+// and read by OLE32.DLL (which has read access). Cache
+// coherency is maintained via RegistryNotifications and an
+// Rpc call to the SCM.
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <shrtbl.hxx>
+#include <resolver.hxx>
+#include <objact.hxx>
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllShrdTbl::CDllShrdTbl
+//
+// Synopsis: constructor for the client side shared memory table
+//
+// Arguments: [hr] - return code from the creation
+//
+//--------------------------------------------------------------------------
+CDllShrdTbl::CDllShrdTbl(HRESULT &hr) :
+ _pShrdTblHdr(NULL),
+ _dwSeqNum(0)
+{
+ _mxs.Init(SHRDTBL_MUTEX_NAME, FALSE);
+ // create/open the event for registry change notifications
+
+ hr = S_OK;
+ _hRegEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, SHRDTBL_EVENT_NAME);
+
+ if (_hRegEvent == NULL)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+
+ CairoleDebugOut((DEB_ERROR,
+ "CDllShrdTbl::CDllShrdTbl OpenEvent Failed hr = %lx\n", hr));
+ }
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllShrdTbl::GetSharedMem
+//
+// Synopsis: returns the ptr to the shared memory table, initializing
+// or re-syncing it if necessary, and calling the SCM if the
+// registry information has changed.
+//
+// Arguments: none
+//
+// Effects: _pShrdTblHdr may be changed, table headers may be updated.
+//
+// Notes: thread safety is the responsibility of the caller.
+//
+//--------------------------------------------------------------------------
+SShrdTblHdr * CDllShrdTbl::GetSharedMem(void)
+{
+ if (_pShrdTblHdr == NULL)
+ {
+ // must init the shared mem block. We subtract off the
+ // hdr size so we dont cause us to go over a page boundary
+ // for just 8 bytes of header!
+
+ HRESULT hr = _smb.Init(SHRDTBL_NAME,
+ SHRDTBL_MAX_SIZE - _smb.GetHdrSize(), // reserve size
+ SHRDTBL_MIN_SIZE - _smb.GetHdrSize(), // commit size
+ NULL, // shared mem base
+ NULL, // security descriptor
+ FALSE); // Dont create if doesnt exist
+
+ if (hr == S_OK)
+ {
+ _pShrdTblHdr = (SShrdTblHdr *) _smb.GetBase();
+ }
+ }
+
+ if (_pShrdTblHdr)
+ {
+ // test the RegNotify event to see if has been signalled
+
+ if (WaitForSingleObject(_hRegEvent, 0) == WAIT_OBJECT_0)
+ {
+ // the change event has been signalled indicating the registry
+ // has changed. Update() resets the Notify in the SCM, since
+ // the Notify must be done in the SCM due to the way RegNCKV
+ // works.
+
+
+ gResolver.UpdateShrdTbls();
+ }
+
+ if (_dwSeqNum != _pShrdTblHdr->dwSeqNum)
+ {
+ // the sequence numbers dont match, grow my view of the
+ // block if necessary
+ _smb.Sync();
+
+ _pShrdTblHdr = (SShrdTblHdr *) _smb.GetBase();
+
+ // update the tables
+ Update();
+ }
+ }
+
+ return _pShrdTblHdr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllShrdTbl::Update
+//
+// Synopsis: intializes the client side of the shared mem table
+//
+// Arguments: none
+//
+// Effects: updates the shared table headers, and the sequence #
+//
+// Notes: thread safety is the responsibility of the caller.
+//
+//--------------------------------------------------------------------------
+void CDllShrdTbl::Update(void)
+{
+
+ if (_pShrdTblHdr != NULL)
+ {
+ // remember the sequence number
+ _dwSeqNum = _pShrdTblHdr->dwSeqNum;
+
+ // intialize the client side tables
+ BYTE *pTbl;
+
+ if (_pShrdTblHdr->OffsIIDTbl != 0)
+ {
+ pTbl = (BYTE *)_pShrdTblHdr + _pShrdTblHdr->OffsIIDTbl;
+ _PSClsidTbl.Initialize(pTbl);
+ }
+
+ if (_pShrdTblHdr->OffsPatTbl != 0)
+ {
+ pTbl = (BYTE *)_pShrdTblHdr + _pShrdTblHdr->OffsPatTbl;
+ _PatternTbl.Initialize(pTbl);
+ }
+
+ if (_pShrdTblHdr->OffsExtTbl != 0)
+ {
+ pTbl = (BYTE *)_pShrdTblHdr + _pShrdTblHdr->OffsExtTbl;
+ _FileExtTbl.Initialize(pTbl);
+ }
+ }
+}
diff --git a/private/ole32/com/inc/shrtbls.cxx b/private/ole32/com/inc/shrtbls.cxx
new file mode 100644
index 000000000..b8a265442
--- /dev/null
+++ b/private/ole32/com/inc/shrtbls.cxx
@@ -0,0 +1,275 @@
+//+---------------------------------------------------------------------------//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: shrtbl2.cxx
+//
+// Contents: shared memory tables - SCM side
+//
+// Classes: CScmShrdTbl - SCM version of the class
+//
+// History: 12-May-94 Rickhi Created
+//
+//
+// Notes: This class caches various tables in shared memory. The
+// tables are typically small, used by all OLE processes,
+// rarely change, and are expensive to lookup manually in
+// the registry, hence they are cached in shared memory.
+//
+// The caches are created by the SCM (which has write access),
+// and read by OLE32.DLL (which has read access). Cache
+// coherency is maintained via RegistryNotifications and an
+// Rpc call to the SCM.
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <shrtbl.hxx>
+
+extern "C"
+{
+#include <lm.h>
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmShrdTbl::CScmShrdTbl
+//
+// Synopsis: constructor for the SCM shared memory table
+//
+// Arguments: [hr] - result of creation of object.
+//
+//--------------------------------------------------------------------------
+CScmShrdTbl::CScmShrdTbl(HRESULT& hr) :
+ _pShrdTblHdr(NULL), _hRegEvent(NULL)
+{
+ _mxs.Init(SHRDTBL_MUTEX_NAME, FALSE);
+
+ // Create the event so clients will notice the change
+ SECURITY_ATTRIBUTES secattr;
+ secattr.nLength = sizeof(secattr);
+ secattr.bInheritHandle = FALSE;
+ CWorldSecurityDescriptor secd;
+ secattr.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) secd;
+
+ hr = S_OK;
+ _hRegEvent = CreateEvent(&secattr, FALSE, FALSE, SHRDTBL_EVENT_NAME);
+
+ if (!_hRegEvent)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ CairoleDebugOut((DEB_ERROR,
+ "CScmShrdTbl::CScmShrdTbl CreateEvent Failed hr = %lx\n", hr));
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmShrdTbl::UpdateWithLock
+//
+// Synopsis: updates (or initializes) the shared mem table, takes the
+// lock while doing so.
+//
+// Arguments: none
+//
+// Algorithm: take the lock.
+// build local copies of the tables.
+// allocate or grow the memory mapped file if needed
+// copy in the new data
+// free the local copies of the tables
+//
+//--------------------------------------------------------------------------
+HRESULT CScmShrdTbl::UpdateWithLock()
+{
+ HRESULT hr;
+ // Prevent concurrent updates.
+ CLock lck(_mxsLocal);
+
+ // Register a change notify here in the SCM. It won't work
+ // in the client. If the registration fails there is not much we can
+ // do to recover at this point, so just print out an error message
+ // and continue.
+
+ LONG sc = RegNotifyChangeKeyValue(HKEY_CLASSES_ROOT,
+ TRUE,
+ REG_NOTIFY_CHANGE_ATTRIBUTES |
+ REG_NOTIFY_CHANGE_LAST_SET |
+ REG_NOTIFY_CHANGE_NAME,
+ _hRegEvent,
+ TRUE);
+
+ if (sc != ERROR_SUCCESS)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CScmShrdTbl::UpdateWithLock RegNotify failed %x\n", sc));
+ }
+
+ __try
+ {
+ // first, we construct local copies of the tables so we can find out
+ // how big they need to be.
+
+ // construct the Local CLSID Table
+ ULONG ulClsidTblSize = 0;
+
+ // construct the Local Pattern Table.
+ ULONG ulPatternTblSize = 0;
+ _PatternTbl.InitTbl(&ulPatternTblSize);
+
+ // construct the Local IID Table
+ ULONG ulPSClsidTblSize = 0;
+ _PSClsidTbl.InitTbl(&ulPSClsidTblSize);
+
+ // construct the Local File Extension table
+ ULONG ulExtTblSize = 0;
+ _FileExtTbl.InitTbl(&ulExtTblSize);
+
+
+ // figure out how much memory we need, and allocate (or grow) that much
+ // shared memory. Note we add in the shared memory header block size,
+ // round up to a page boundary, then subtract out the header block size.
+ // this ensures that our rounding doesnt force us over a page by just
+ // because of the header size.
+
+ ULONG ulShrdMemSize = sizeof(SShrdTblHdr) +
+ ulPatternTblSize +
+ ulPSClsidTblSize +
+ ulExtTblSize +
+ ulClsidTblSize +
+ _smb.GetHdrSize();
+
+ // round out to a 4K boundary, and subtract our the smb header size.
+ ulShrdMemSize += 0xfff;
+ ulShrdMemSize &= 0xfffff000;
+ ulShrdMemSize -= _smb.GetHdrSize();
+
+ hr = GetSharedMem(ulShrdMemSize);
+
+
+ if (SUCCEEDED(hr))
+ {
+ // Pick up the "PersonalClasses" flag
+ // _pShrdTblHdr->fPersonalClasses = g_pcllClassCache->GetPersonalClasses();
+
+ // bump the sequence number so that clients know when the info
+ // has changed and they need to resync.
+
+ _pShrdTblHdr->dwSeqNum++;
+
+ // copy the data from the locally constructed tables into the
+ // shared memory. If there is no room for a particular table,
+ // it is skipped, and the Offset to it is set to zero. This
+ // should be extremly rare, and the tables are just optimizations
+ // anyway. On seeing a zero offset, clients will just go read the
+ // data out of the registry directly.
+
+ BYTE *pTbl = (BYTE *)_pShrdTblHdr + sizeof(SShrdTblHdr);
+ BYTE *pTblEnd = (BYTE *)_pShrdTblHdr + _smb.GetSize();
+ ULONG ulSpaceLeft = pTblEnd - pTbl;
+
+ // copy the pattern table
+ _pShrdTblHdr->OffsPatTbl = 0;
+ if (ulSpaceLeft >= ulPatternTblSize)
+ {
+ _pShrdTblHdr->OffsPatTbl = pTbl - (BYTE *)_pShrdTblHdr;
+ pTbl = _PatternTbl.CopyTbl(pTbl);
+ ulSpaceLeft = pTblEnd - pTbl;
+ }
+
+ // copy the IID table
+ _pShrdTblHdr->OffsIIDTbl = 0;
+ if (ulSpaceLeft >= ulPSClsidTblSize)
+ {
+ _pShrdTblHdr->OffsIIDTbl = pTbl - (BYTE *)_pShrdTblHdr;
+ pTbl = _PSClsidTbl.CopyTbl(pTbl);
+ ulSpaceLeft = pTblEnd - pTbl;
+ }
+
+ // copy the file extension table
+ _pShrdTblHdr->OffsExtTbl = 0;
+ if (ulSpaceLeft >= ulExtTblSize)
+ {
+ _pShrdTblHdr->OffsExtTbl = pTbl - (BYTE *)_pShrdTblHdr;
+ pTbl = _FileExtTbl.CopyTbl(pTbl);
+ ulSpaceLeft = pTblEnd - pTbl;
+ }
+
+ // copy the CLSID table
+ _pShrdTblHdr->OffsClsTbl = 0;
+
+ hr = S_OK;
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+
+ // free the locally allocated copies of the tables
+
+ _PatternTbl.FreeTbl();
+ _PSClsidTbl.FreeTbl();
+ _FileExtTbl.FreeTbl();
+ }
+ __except( 1 )
+ {
+ Win4Assert( !"exception thrown during shared table update" );
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmShrdTbl::GetSharedMem
+//
+// Synopsis: Creates or gets access to memory mapped file.
+//
+// Arguments: [ulTblSize] - the size of memory we need
+//
+//--------------------------------------------------------------------------
+HRESULT CScmShrdTbl::GetSharedMem(ULONG ulTblSize)
+{
+ HRESULT hr = S_OK;
+ Win4Assert(ulTblSize < SHRDTBL_MAX_SIZE);
+
+ if (_pShrdTblHdr == NULL)
+ {
+ // must init the shared memory block. We subtract off the
+ // hdr size so we dont cause us to go over a page boundary
+ // for just 8 bytes of header!
+
+ hr = _smb.Init(SHRDTBL_NAME,
+ SHRDTBL_MAX_SIZE - _smb.GetHdrSize(), // reserve size
+ ulTblSize, // commit size
+ NULL, // shared mem base
+ NULL, // security descriptor
+ TRUE); // Create if doesn't exist
+
+ if (hr == S_OK && _smb.Created())
+ {
+ // if we created the shared memory, initialize the header.
+ memset(_smb.GetBase(), 0, sizeof(SShrdTblHdr));
+ }
+ }
+ else if (ulTblSize > _smb.GetSize())
+ {
+ // have to grow the shared mem block. This could fail, its
+ // extremly unlikely, but possible.
+
+ hr = _smb.Commit(ulTblSize);
+ }
+
+ if (hr == S_OK)
+ {
+ _pShrdTblHdr = (SShrdTblHdr *) _smb.GetBase();
+ }
+ else
+ {
+ _pShrdTblHdr = NULL;
+ }
+
+ return hr;
+}
diff --git a/private/ole32/com/inc/skiplist.cxx b/private/ole32/com/inc/skiplist.cxx
new file mode 100644
index 000000000..f2da36f90
--- /dev/null
+++ b/private/ole32/com/inc/skiplist.cxx
@@ -0,0 +1,600 @@
+//+-------------------------------------------------------------------------
+//
+// Copyright (C) 1992, Microsoft Corporation.
+//
+// File: sklist.cxx
+//
+// Contents: Level generator functions required by skip lists
+//
+// Functions: RandomBit - generate a random on or off bit
+// InitSkLevelGenerator - initialize random bit seed
+// GetSkLevel - return a skip list forward pointer array size
+//
+// History: 30-Apr-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include <time.h>
+#include "skiplist.hxx"
+
+static ULONG ulLSFR;
+
+//+-------------------------------------------------------------------------
+//
+// Function: RandomBit
+//
+// Synopsis: Uses various shifts to generate random bit
+//
+// Returns: 0 or 1
+//
+// History: 30-Apr-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+static inline ULONG RandomBit(void)
+{
+ ulLSFR = (((ulLSFR >> 31)
+ ^ (ulLSFR >> 6)
+ ^ (ulLSFR >> 4)
+ ^ (ulLSFR >> 2)
+ ^ (ulLSFR >> 1)
+ ^ ulLSFR
+ & 0x00000001)
+ << 31)
+ | (ulLSFR >> 1);
+
+ return ulLSFR & 0x00000001;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: InitSkLevelGenerator
+//
+// Synopsis: Seed the random bit generator with the time
+//
+// History: 30-Apr-92 Ricksa Created
+//
+// Notes: Set up the generator for skip list levels
+//
+//--------------------------------------------------------------------------
+
+void InitSkLevelGenerator(void)
+{
+ // BUGBUG: Need to revisit whether this is a random enough
+ // value to use for the seed
+ time_t timeCurrent;
+ time(&timeCurrent);
+ ulLSFR = timeCurrent;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetSkLevel
+//
+// Synopsis: Set the level for an entry in a skip list
+//
+// Arguments: [cMax] - maximum level to return
+//
+// Returns: a number between 1 and cMax
+//
+// History: 30-Apr-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+int GetSkLevel(int cMax)
+{
+ // There should always be at least one entry returned
+ int cRetLevel = 1;
+
+ // Loop while the level is less than the maximum level
+ // to return and a 1 is returned from RandomBit. Note
+ // that this is equivalent to p = 1/2. If you don't
+ // know what p = 1/2 means see Communications of the ACM
+ // June 1990 on Skip Lists.
+ while (cRetLevel < cMax && RandomBit())
+ {
+ cRetLevel++;
+ }
+
+ return cRetLevel;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipList::CSkipList
+//
+// Synopsis: Skip list constructor.
+//
+// Arguments: [lpfnCompare] -- Pointer to client-supplied comparison
+// function. Client supplied routine should cast
+// the pointer parameters to the class that is the
+// key and then perform the comparison. The [pvMaxKey]
+// parameter may at times be passed unchanged to the
+// comparison function in the second parameter.
+// The first parameter of the comparison function will
+// receive a pointer to the key part (base part) of
+// the entries inserted using CSkipList::Insert ; the
+// pointer to the key part is calculated by adding
+// [EntryToKeyOffset] to the address of the entry passed
+// to CSkipList::Insert.
+//
+// [lpfnDelete] -- Pointer to client-supplied routine that
+// takes a single pointer parameter and is only ever
+// called by CSkipList::~CSkipList to perform any
+// necessary deallocation of entries within
+// the skip list.
+//
+// [EntryToKeyOffset] -- Added to entry pointers to
+// convert an "entry*" to "key*". See description
+// of [lpfnCompare] and header in skiplist.hxx.
+// Units are sizeof(char)
+//
+// [fSharedAlloc] -- If TRUE, the skip list allocates its
+// internal objects in shared memory, otherwise the
+// skip list uses private memory. (Of course, the
+// CSkipList object itself is allocated by the client
+// which must ensure that this flag and where the
+// CSkipList is allocated are consistent.)
+//
+// [pvMaxKey] -- Parameter which is passed unchanged to
+// the user-supplied comparison routine specified by
+// [lpfnCompare] during insertions/deletions/searches.
+//
+// [cMaxLevel] -- The max level the skip list should use.
+//
+// [hr] -- Reference to an HRESULT which is only set in
+// the error cases. This will be set to E_OUTOFMEMORY
+// if the construction failed because of low memory.
+//
+//--------------------------------------------------------------------
+
+CSkipList::CSkipList(
+ LPFNCOMPARE lpfnCompare,
+ LPFNDELETE lpfnDelete,
+ const int EntryToKeyOffset,
+ BOOL fSharedAlloc,
+ Base * pvMaxKey,
+ const int cMaxLevel,
+ HRESULT & hr)
+ :
+ _cCurrentMaxLevel(0),
+ _lpfnCompare(lpfnCompare),
+ _lpfnDelete(lpfnDelete),
+ _EntryToKeyOffset(EntryToKeyOffset),
+ _fSharedAlloc(fSharedAlloc),
+ _cMaxLevel(cMaxLevel)
+{
+
+ //
+ // NOTE! 2nd param of CSkipListEntry is usually an entry, but for head is key.
+ //
+
+ _pEntryHead = (CSkipListEntry*)Allocate(CSkipListEntry::GetSize(_cMaxLevel));
+
+ if (_pEntryHead)
+ {
+ _pEntryHead->Initialize(pvMaxKey, _cMaxLevel, TRUE /* fHead */ );
+
+ for (int i = 0; i < _cMaxLevel; i++)
+ {
+ _pEntryHead->SetForward(i, _pEntryHead);
+ }
+ }
+ else
+ hr = E_OUTOFMEMORY;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipList::~CSkipList
+//
+// Synopsis: Skip list destructor.
+//
+// Effects: For every entry that has been inserted into the skip
+// list (using CSkipList::Insert), but not removed
+// (using CSkipList::Remove), the destructor calls
+// the user-supplied routine (lpfnDelete parameter of
+// CSkipList constructor) with a pointer to each entry.
+//
+// The user-supplied routine should cast the passed
+// pointer parameter to the class of the entry and
+// deallocate it (only if the skip list "owns" the
+// object of course.)
+//
+//--------------------------------------------------------------------
+
+CSkipList::~CSkipList()
+{
+ if (_pEntryHead)
+ {
+ if (_pEntryHead->GetBase())
+ {
+ while (_pEntryHead->GetForward(0) != _pEntryHead)
+ {
+ Base * pvKey = _pEntryHead->GetForward(0)->GetKey(_EntryToKeyOffset);
+ Entry * pvEntry = Remove(pvKey);
+ _lpfnDelete(pvEntry);
+ }
+ }
+ Deallocate(_pEntryHead);
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipList::_Search, private
+//
+// Synopsis: Search the skip list for an entry matching the supplied
+// key.
+//
+// Effects: Search calls the user-supplied comparison function
+// with two pointers. The first is the address of the key
+// part of entries in the skip list that were inserted
+// by CSkipList::Insert (see description of constructor
+// for how the key address is found.)
+// The second parameter of the user-supplied function
+// is the [BaseKey] parameter of this function.
+//
+// Arguments: [BaseKey] -- passed to user-supplied comparison function.
+// Pointer to key that should match the key part
+// of an entry that was inserted into the skip
+// list using CSkipList::Insert.
+// [ppPrivEntry -- returns pointer to CSkipListEntry that
+// contains user entry pointer.
+// Will contain null if not found.
+//
+// Returns: Pointer to the entry part (not key part) of the found
+// object. This will be the same as the respective parameter
+// to Insert.
+// NULL if not found.
+//
+//--------------------------------------------------------------------
+
+Entry *CSkipList::_Search(const Base * BaseKey, CSkipListEntry **ppPrivEntry)
+{
+ CSkipListEntry *pEntrySearch = _pEntryHead;
+
+ register int CmpResult = -1;
+ *ppPrivEntry = NULL;
+
+ for (int i = _cCurrentMaxLevel - 1; i >= 0; i--)
+ {
+ while ((CmpResult =
+ _lpfnCompare(pEntrySearch->GetForward(i)->GetKey(_EntryToKeyOffset), (Base*)BaseKey)) < 0)
+ {
+ pEntrySearch = pEntrySearch->GetForward(i);
+ }
+
+ if (CmpResult == 0)
+ {
+ *ppPrivEntry = pEntrySearch->GetForward(i);
+ break;
+ }
+ }
+
+ return (CmpResult == 0) ? (*ppPrivEntry)->GetEntry() : NULL;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipList::Search
+//
+// Synopsis: Search the skip list for an entry matching the supplied
+// key.
+//
+// Effects: Search calls the user-supplied comparison function
+// with two pointers. The first is the address of the key
+// part of entries in the skip list that were inserted
+// by CSkipList::Insert (see description of constructor
+// for how the key address is found.)
+// The second parameter of the user-supplied function
+// is the [BaseKey] parameter of this function.
+//
+// Arguments: [BaseKey] -- passed to user-supplied comparison function.
+// Pointer to key that should match the key part
+// of an entry that was inserted into the skip
+// list using CSkipList::Insert.
+//
+// Returns: Pointer to the entry part (not key part) of the found
+// object. This will be the same as the respective parameter
+// to Insert.
+// NULL if not found.
+//
+//--------------------------------------------------------------------
+
+Entry *CSkipList::Search(const Base * BaseKey)
+{
+ CSkipListEntry *pPrivEntry;
+ return _Search(BaseKey, &pPrivEntry);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipList::FillUpdateArray
+//
+// Synopsis: Private member which fills the array with pointers
+// to entries that only compare >=
+//
+// Arguments: [BaseKey] -- Pointer to key part of an entry.
+// [ppEntryUpdate] -- The array to fill.
+//
+// Returns: Pointer to most closely matching entry or NULL if head not
+// allocated (shouldn't happen)
+//
+//--------------------------------------------------------------------
+
+CSkipListEntry *CSkipList::FillUpdateArray(
+ const Base *BaseKey,
+ CSkipListEntry **ppEntryUpdate)
+{
+ CSkipListEntry *pEntrySearch = _pEntryHead;
+ if (pEntrySearch)
+ {
+ for (int i = _cCurrentMaxLevel - 1; i >= 0; i--)
+ {
+ while (_lpfnCompare(
+ pEntrySearch->GetForward(i)->GetKey(_EntryToKeyOffset),
+ (Base*)BaseKey) < 0)
+ {
+ pEntrySearch = pEntrySearch->GetForward(i);
+ }
+
+ ppEntryUpdate[i] = pEntrySearch;
+ }
+ return pEntrySearch->GetForward(0);
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipList::Insert
+//
+// Synopsis: Inserts the supplied entry into the skip list.
+//
+// Arguments: [pEntry] -- The pointer to the entry to insert.
+// When searching, this pointer will
+// have the "EntryToKeyOffset" parameter
+// to CSkipList constructor added before
+// being passed to the user-supplied
+// comparison function. The offset is
+// in sizeof(char) units.
+//
+// Upon destruction of the skip list,
+// ~CSkipList will call the user-supplied
+// deletion routine with the stored [pEntry]
+// unless it is removed using CSkipList::Remove
+// prior to the destruction of CSkipList.
+//
+// Should never be NULL.
+//
+// Returns: If successful, returns the input parameter, otherwise
+// returns NULL which is indicative of E_OUTOFMEMORY.
+//
+//--------------------------------------------------------------------
+
+Entry * CSkipList::Insert(Entry *pEntry)
+{
+ CSkipListEntry *apEntryUpdate[SKIP_LIST_MAX];
+
+ if (pEntry == NULL)
+ return(NULL);
+
+ Win4Assert(_pEntryHead != NULL);
+
+ int level = GetSkLevel((_cCurrentMaxLevel != _cMaxLevel) ?
+ _cCurrentMaxLevel + 1 : _cMaxLevel);
+
+ CSkipListEntry *pEntryNew = (CSkipListEntry*)Allocate(CSkipListEntry::GetSize(level));
+
+ if (pEntryNew != NULL)
+ {
+ pEntryNew->Initialize(pEntry, level, FALSE /* fHead */ );
+
+ FillUpdateArray( (((char*)pEntry)+_EntryToKeyOffset), apEntryUpdate);
+
+ int iNewLevel = pEntryNew->cLevel();
+
+ if (iNewLevel > _cCurrentMaxLevel)
+ {
+ for (int i = _cCurrentMaxLevel; i < iNewLevel; i++)
+ {
+ apEntryUpdate[i] = _pEntryHead;
+ }
+
+ _cCurrentMaxLevel = iNewLevel;
+ }
+
+ for (int i = 0; i < iNewLevel ; i++)
+ {
+ pEntryNew->SetForward(i, apEntryUpdate[i]->GetForward(i));
+ apEntryUpdate[i]->SetForward(i, pEntryNew);
+ }
+ return(pEntry);
+ }
+ return(NULL);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipList::Remove
+//
+// Synopsis: Searches the skip list for an entry that matches
+// [BaseKey] and removes the pointer to it from the skip
+// list (if found.)
+//
+// Effects: Calls the user-supplied comparison routine as part of
+// the search (see documentation of CSkipList::CSkipList,
+// CSkipList::Insert, and skiplist.hxx header for more
+// information about how the search occurs.)
+//
+// Arguments: [BaseKey] -- pointer to key that should match a key of
+// an entry in the list.
+//
+// Returns: NULL if not found, otherwise a pointer to the entry
+// part of the entry that was matched.
+//
+//--------------------------------------------------------------------
+
+Entry * CSkipList::Remove(Base * BaseKey)
+{
+ CSkipListEntry *apEntryUpdate[SKIP_LIST_MAX];
+ Entry * pEntry;
+ CSkipListEntry *pEntryDelete = FillUpdateArray(BaseKey, apEntryUpdate);
+
+ for (int i = 0; i < _cCurrentMaxLevel; i++)
+ {
+ if (apEntryUpdate[i]->GetForward(i) != pEntryDelete)
+ {
+ break;
+ }
+
+ apEntryUpdate[i]->SetForward(i, pEntryDelete->GetForward(i));
+ }
+
+ if (pEntryDelete)
+ pEntry = pEntryDelete->GetEntry();
+ else
+ pEntry = NULL;
+
+ Deallocate(pEntryDelete);
+
+ while (_cCurrentMaxLevel > 1 &&
+ _pEntryHead->GetForward(_cCurrentMaxLevel - 1) == _pEntryHead)
+ {
+ _cCurrentMaxLevel--;
+ }
+ return pEntry;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipList::Replace
+//
+// Synopsis: Searches the skip list for an entry that matches
+// [BaseKey] and returns the pointer to the entry.
+// The entry pointer is replaced by [pEntryNew]
+//
+// Effects: Calls the user-supplied comparison routine as part of
+// the search (see documentation of CSkipList::CSkipList,
+// CSkipList::Insert, and skiplist.hxx header for more
+// information about how the search occurs.)
+//
+// Arguments: [BaseKey] -- pointer to key that should match a key of
+// an entry in the list.
+// [pEntryNew] -- pointer to entry that has same key value
+// as [BaseKey] that is to replace the pointer
+// currently associated with the that key value.
+//
+// Returns: The old pointer. If this is used to own the data, then
+// it must be deleted.
+//
+//--------------------------------------------------------------------
+
+Entry * CSkipList::Replace(Base * BaseKey, Entry * pEntryNew)
+{
+ Win4Assert(_lpfnCompare(BaseKey, ((char*)pEntryNew)+_EntryToKeyOffset)==0);
+
+ CSkipListEntry *pPrivEntry;
+ Entry * pOldEntry = _Search(BaseKey, &pPrivEntry);
+ if (pPrivEntry != NULL)
+ {
+ Win4Assert(pOldEntry);
+ pPrivEntry->_pvEntry = pEntryNew;
+ }
+ else
+ {
+ Win4Assert(pOldEntry == NULL);
+ }
+ return pOldEntry;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipList::First
+//
+// Synopsis: Initializes the "skip list enumerator" to point
+// to the first CSkipListEntry in the skip list and return a
+// pointer to the user-supplied entry.
+//
+// Arguments: [psle] -- Pointer to a CSkipListEnum which is initialized.
+//
+// Returns: A pointer previously passed into CSkipList::Insert.
+// The first entry in this skip list.
+//
+//--------------------------------------------------------------------
+
+Entry *CSkipList::First(CSkipListEnum *psle)
+{
+ *psle = _pEntryHead;
+ return Next(psle);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipList::Next
+//
+// Synopsis: Using the state of the passed enumerator, return the
+// next entry and update the enumerator for the next
+// call to Next.
+//
+// Arguments: [psle] -- Pointer to CSkipListEnum previously
+// initialized by CSkipList::First or
+// updated by CSkipList::Next.
+//
+// Returns: NULL if no more to enumerate, otherwise a pointer to
+// the user-supplied entry (i.e. the returned pointer
+// was previously passed to CSkipList::Insert (but not
+// then removed.)
+//
+//--------------------------------------------------------------------
+
+Entry *CSkipList::Next(CSkipListEnum *psle)
+{
+ if (*psle == NULL)
+ {
+ return(NULL);
+ }
+
+ CSkipListEntry *pEntryTo = (*psle)->GetForward(0);
+ Entry * pvRet;
+
+ if (pEntryTo != _pEntryHead)
+ {
+ pvRet = pEntryTo->GetEntry();
+ *psle = pEntryTo;
+ }
+ else
+ {
+ *psle = NULL;
+ pvRet = NULL;
+ }
+ return pvRet;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipList::GetList
+//
+// Synopsis: BUGBUG: BillMo. Old code hangover. This function is
+// used to test the success of allocation of
+// _pEntryHead in the constructor because of the
+// removal of exception code.
+// All uses of this should now be redundant and should
+// be removed since the constructor now returns an error
+// code should a failure occur.
+//
+//--------------------------------------------------------------------
+
+CSkipListEntry *CSkipList::GetList(void)
+{
+ Win4Assert(_pEntryHead != NULL);
+ return _pEntryHead;
+}
+
diff --git a/private/ole32/com/inc/skiplist.hxx b/private/ole32/com/inc/skiplist.hxx
new file mode 100644
index 000000000..4e09e820c
--- /dev/null
+++ b/private/ole32/com/inc/skiplist.hxx
@@ -0,0 +1,670 @@
+//--------------------------------------------------------------------------
+//
+// Copyright (C) 1992, Microsoft Corporation.
+//
+// File: skiplist.hxx
+//
+// Contents: Skip list classes.
+//
+// CSkipList -- A class that implements skip lists.
+// The skip list manages the efficient lookup
+// of "Entry"s which are inserted into the skip list
+// by the client. "Entry"s are represented by
+// a pointer passed into the CSkipList::Insert()
+// method by the client.
+// These pointers can be retrieved by the Search()
+// method which takes a pointer to a "Base", (which
+// acts as a key.)
+//
+// "Entry"s are always derived from "Base"s. That is,
+// the CSkipList::Search() method assumes that a
+// simple pointer manipulation can turn a pointer to
+// an "Entry" that it has in the list into a pointer
+// to "Base" that it needs for comparison purposes.
+// Once the pointer is converted, the user-supplied
+// comparison function is called to facilitate the
+// search.
+//
+// An example
+// ----------
+//
+// We have a "Base" class which is a key. Pointers
+// to CKeys will be passed to CSkipList::Search()
+// and to the constructor of CSkipList (the max key)
+//
+// class CKey
+// {
+// int keyvalue; // a simple integer key
+// public:
+// static int Compare(void *pkey1, void *pkey2)
+// {
+// return ((CKey*)pkey1)->keyvalue <
+// ((CKey*)pkey2)->keyvalue;
+// }
+//
+// static int Delete(const *pentry)
+// {
+// delete pentry;
+// }
+// };
+//
+// We have an "Entry" class which is-a key and also
+// is-a CExtra (whatever the client needs/wants.)
+// Pointers to CDataEntrys are passed to
+// CSkipList::Insert. Also, pointers to CDataEntrys
+// are converted to pointers to CKeys by the addition
+// of an offset which is set once for all skip list
+// entries when passed to CSkipList constructor.
+//
+// class CDataEntry : public CExtra, private CKey
+// {
+// char *pszData;
+// };
+//
+// we can easily make a skip list out of the
+// CDataEntries as follows:
+//
+// static int maxkey=32677;
+//
+// CSkipList mysl((LPFNCOMPARE)(CKey::Compare),
+// (LPFNDELETE)(CKey::Delete),
+// OFFSETBETWEEN(CDataEntry, CKey),
+// SKIPLIST_PRIVATE,
+// &maxkey,
+// 10,
+// hr);
+//
+// Notes on parameters:
+// 1. Pass in the address of the comparison function.
+// This comparison function is called by
+// CSkipList::Search(). The first paramter to
+// the compare function is a pointer to the "Base"
+// part of an "Entry" in the skip list (computed by
+// adding offset computed by OFFSETBETWEEN macro).
+// Search() routine makes the determination as to which
+// "Entry"s to compare based on internal details of
+// the skip list mechanism.
+// The second parameter to the Compare function is the
+// "Base" pointer parameter passed to Search.
+//
+// 2. Pass in the address of the deletion function.
+// This function is called only as part of the
+// destructor of CSkipList and allows the deletion
+// of any entries left in the skip list. If
+// the skip list is used in such a way as to not
+// "own" the pointers within, then this function
+// will simple return after doing nothing.
+// If the skip list is used in such a way as to
+// actually "own" the objects inserted, then
+// the user-supplied delete function should be used
+// to cleanup correctly.
+//
+// 3. Since all entries in the list must be used as both
+// "key" and "data", the EntryToKeyOffset gives
+// the offset in bytes between the "Entry" part and
+// the "Base" part. In the example, the offset would
+// be the size of CExtra.
+//
+// See method description for details on other parameters.
+//
+// Insert an entry:
+// ----------------
+// mysl.Insert(new CDataEntry);
+//
+// Lookup an entry:
+// ----------------
+// CKey key(some param to ctr);
+// mysl.Search(&key); // returns a pointer to respective
+// // CDataEntry *
+//
+// CSkipListEntry -- class used privately by CSkipList.
+//
+// History: 06-May-92 Ricksa Created
+// 18-May-94 BruceMa Fixed scm memory leak in SKIP_LIST_ENTRY
+// 28-Jun-94 BruceMa Memory sift fixes
+// 04-Oct-94 BillMo Changed from macro to class implementation.
+// Added comments above and to skip list methods
+// after demacroization.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __SKIPLIST_HXX__
+#define __SKIPLIST_HXX__
+
+#include <scmmem.hxx>
+
+// Used by insert/delete algorithms to preallocate array on stack.
+// This is valid for skip lists with <= 64K elements.
+#define SKIP_LIST_MAX 16
+
+// Set up the generator for skip list levels
+void InitSkLevelGenerator(void);
+
+// Get a level from the generator
+int GetSkLevel(int cMax);
+
+//+-------------------------------------------------------------------------
+//
+// Macro: OFFSETBETWEEN
+//
+// Parameters: [Entry] -- class name of the class which forms entries
+// in the skip list. see example below.
+// MUST BE DERIVED from class named in parameter
+// 'Base'
+//
+// [Base] -- class name of the class which is the 'key'
+// for the skip list entries
+//
+// Purpose: Encapsulate calculation of offset that the skip list uses
+// to convert pointers to "Entrys" to pointers to "Bases"
+//
+// History: 04-Nov-94 Ricksa Created
+//
+// Notes: VERY IMPORTANT NOTE: "Entry" must be derived from "Base"
+//
+//--------------------------------------------------------------------------
+
+#define OFFSETBETWEEN(Entry, Base) \
+ ((char*)( (const Base*)((const Entry*)0x1000 ))) - \
+ ((char*)( (const Base*)0x1000))
+
+//+-------------------------------------------------------------------------
+//
+// The following defines control how allocation is done by the skip list.
+// The fSharedAlloc parameter of CSkipList::CSkipList can either be:
+//
+// SKIPLIST_SHARED -- in x86 Windows builds will cause the shared allocator
+// to be used for CSkipListEntrys.
+// (In NT builds will currently be privately allocated.)
+//
+// SKIPLIST_PRIVATE -- in all build environments use PrivMemAlloc.
+//
+//--------------------------------------------------------------------------
+
+#define SKIPLIST_SHARED TRUE
+#define SKIPLIST_PRIVATE FALSE
+
+
+//+-------------------------------------------------------------------------
+//
+// Documentation aid:
+//
+// Since CSkipLists do not know the actual classes to be inserted/deleted
+// there will always be a cast involved in using the comparison function.
+// For this reason the typedefs below act as a documentation aid and
+// reminder that the pointers are expected to point to particular
+// meta-types of objects.
+//
+// "Base" is used where a pointer to the "key" is expected. (e.g. the
+// Search method.)
+//
+// "Entry" is used where a pointer to the derived class (data+key) is
+// expected (e.g. the Insert method.)
+//
+//--------------------------------------------------------------------------
+
+typedef void Base;
+typedef void Entry;
+
+//+-------------------------------------------------------------------------
+//
+// Some type definitions.
+//
+//--------------------------------------------------------------------------
+
+class CSkipListEntry;
+
+// note: the name CSkipListEnum is used so that the details of the
+// enumerator are hidden and can be expanded in the future without
+// have to modify the source of clients.
+
+typedef CSkipListEntry * CSkipListEnum;
+
+//+-------------------------------------------------------------------------
+//
+// Function type: LPFNCOMPARE
+//
+// Purpose: Provide parameter signature for comparison function used
+// by skip lists. The user implementation should
+// compare the two keys and return <0, >0 or ==0.
+//
+// Arguments: [pkey1] -- pointer to the "Base" part of an "Entry" in
+// the skip list as calculated by adding the
+// "EntryToKeyOffset" value (passed to CSkipList
+// constructor) to the address of an "Entry" in the
+// list.
+// [pkey2] -- the address passed to CSkipList::Search which is
+// the address of a "Base" key being used to locate
+// the respective entry in skip list.
+//
+// History: 04-Nov-94 BillMo Created
+//
+//--------------------------------------------------------------------------
+
+typedef int (*LPFNCOMPARE)(Base *pkey1, Base *pkey2);
+
+//+-------------------------------------------------------------------------
+//
+// Function type: LPFNDELETE
+//
+// Purpose: Provide parameter signature for deletion function used
+// by skip list's destructor. The user implementation should
+// delete the entry as appropriate (i.e. should delete it
+// if the destruction of the skip list without deleting
+// would cause leaks.)
+//
+// i.e. if the skip list owns the pointers, delete them in this
+// function, otherwise don't.
+//
+// Arguments: [pentry] -- pointer to an "Entry" part of an "Entry"
+// originally passed to CSkipList::Insert.
+//
+// History: 04-Nov-94 BillMo Created
+//
+//--------------------------------------------------------------------------
+
+typedef void (*LPFNDELETE)(Entry *);
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSkipList
+//
+// Purpose: Implements head of a skip list.
+//
+// Interface: CSkipList -- constructor
+// ~CSkipList -- destructor (calls user-supplied deletion
+// routine)
+// Search -- find item in list
+// Insert -- add new item to the list (insert the pointer)
+// Remove -- remove item from the list (return the pointer)
+// (this doesn't delete the pointer or call
+// lpfnDelete.)
+// Replace -- replace the entry (MUST be same key value.)
+// First -- get first entry in skip list.
+// Next -- get next entry given by CSkipListEnum param.
+// GetList -- get the list
+//
+// History: 06-May-92 Ricksa Created
+// 04-Nov-94 BillMo Update comments.
+//
+// Notes: CSkipList has a nested class: CSkipListEntry
+//
+//--------------------------------------------------------------------------
+
+class CSkipList
+{
+public:
+
+ CSkipList(
+ LPFNCOMPARE lpfnCompare,
+ LPFNDELETE lpfnDelete,
+ const int EntryToKeyOffset,
+ BOOL fSharedAlloc,
+ Base * pvMaxKey,
+ const int cMaxLevel,
+ HRESULT & hr);
+
+ ~CSkipList(void);
+
+ Entry * Search(const Base * skey);
+
+ Entry * Insert(Entry *pEntryNew);
+
+ Entry * Remove(Base * BaseKey);
+
+ Entry * Replace(Base * BaseKey, Entry * pEntryNew);
+
+ Entry * First(CSkipListEnum *psle);
+
+ Entry * Next(CSkipListEnum *psle);
+
+ CSkipListEntry * GetList(void);
+
+private:
+
+ void * Allocate(ULONG cb);
+
+ void Deallocate(void *pv);
+
+ CSkipListEntry * FillUpdateArray(const Base *BaseKey,
+ CSkipListEntry **ppEntryUpdate);
+
+ Entry * _Search(const Base * BaseKey,
+ CSkipListEntry **ppPrivEntry);
+
+ int _cCurrentMaxLevel;
+
+ int _cMaxLevel;
+
+ CSkipListEntry * _pEntryHead;
+
+ BOOL _fSharedAlloc;
+
+ const int _EntryToKeyOffset;
+
+ LPFNCOMPARE _lpfnCompare;
+
+ LPFNDELETE _lpfnDelete;
+
+
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipList::Allocate
+//
+// Synopsis: Allocate the requested number of bytes from the
+// shared heap, or private heap, depending on the
+// state of CSkipList::_fSharedAlloc
+// If _fSharedAlloc is TRUE, then ScmMemAlloc is called,
+// otherwise PrivMemAlloc is used.
+//
+// Arguments: [cb] -- Number of bytes requsted.
+//
+// Returns: Pointer to allocated memory, or NULL on failure.
+//
+//--------------------------------------------------------------------
+
+inline void *
+CSkipList::Allocate(ULONG cb)
+{
+ if (_fSharedAlloc)
+ return ScmMemAlloc(cb);
+ else
+ return PrivMemAlloc(cb);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipList::Deallocate
+//
+// Synopsis: Dellocate the requested block from the
+// shared heap, or private heap, depending on the
+// state of CSkipList::_fSharedAlloc
+// If _fSharedAlloc is TRUE, then ScmMemFree is called,
+// otherwise PrivMemFree is used.
+//
+// Arguments: [pv] -- Pointer to block to free.
+//
+//--------------------------------------------------------------------
+
+inline void
+CSkipList::Deallocate(void *pv)
+{
+ if (_fSharedAlloc)
+ ScmMemFree(pv);
+ else
+ PrivMemFree(pv);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSkipListEntry
+//
+// Purpose: Implements an entry in a skip list.
+//
+// Interface: Initialize -- initialize object
+// GetSize -- calculate size to allocate for object
+// cLevel -- returns number of forward pointers
+// GetForward -- returns the ith forward pointer
+// SetForward -- sets ith forward pointer
+// GetBase -- return base address of array
+// GetEntry -- get user-supplied object pointer
+// GetKey -- get key of user-supplied object
+//
+// History: 06-May-92 Ricksa Created
+// 04-Nov-94 BillMo Demacroize and update comments.
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+class CSkipListEntry
+{
+private:
+ friend class CSkipList;
+
+ CSkipListEntry(); // declared but not defined
+
+ void Initialize(Entry * pvEntry,
+ const int cEntries,
+ BOOL fHead);
+
+ static int GetSize(const int cEntries);
+
+ int cLevel(void);
+
+ CSkipListEntry* GetForward(int iCur);
+
+ void SetForward(int iCur, CSkipListEntry* pnew);
+
+ CSkipListEntry ** GetBase(void);
+
+ Entry * GetEntry(void);
+
+ Base * GetKey(const int EntryToKeyOffset);
+
+
+ int _cEntries:24;
+ int _fHead:8;
+ Entry * _pvEntry;
+ CSkipListEntry * _apBaseForward[1];
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipListEntry::Initialize
+//
+// Synopsis: Set up member variables of skip list entry
+//
+// Arguments: [pvEntry] -- client-supplied "entry"/"base" pointer
+// [cEntries] -- count of entries requested.
+// [fHead] -- TRUE if head of skip list
+//
+// Returns: size in bytes required for an object to contain requested
+// number of entries.
+//
+//--------------------------------------------------------------------
+
+inline void
+CSkipListEntry::Initialize(Entry * pvEntry,
+ const int cEntries,
+ BOOL fHead)
+{
+ _pvEntry = pvEntry;
+ _cEntries = cEntries;
+ _fHead = fHead;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipListEntry::GetSize
+//
+// Synopsis: Calculate the size in bytes required for a CSkipListEntry
+// to contain [cEntries] elements.
+//
+// Arguments: [cEntries] -- count of entries requested.
+//
+// Returns: size in bytes required for an object to contain requested
+// number of entries.
+//
+//--------------------------------------------------------------------
+
+inline int
+CSkipListEntry::GetSize(const int cEntries)
+{
+ return sizeof(CSkipListEntry) +
+ (cEntries-1)*sizeof(CSkipListEntry *);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipListEntry::cLevel
+//
+// Synopsis: Returns the level (entry count) of skip list entry.
+//
+//--------------------------------------------------------------------
+
+inline int CSkipListEntry::cLevel(void)
+{
+ return _cEntries;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipListEntry::GetForward
+//
+// Synopsis: Return the [iCur]'th forward pointer.
+//
+//--------------------------------------------------------------------
+
+inline CSkipListEntry* CSkipListEntry::GetForward(int iCur)
+{
+ return _apBaseForward[iCur];
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipListEntry::SetForward
+//
+// Synopsis: Set the [iCur]'th forward pointer to [pnew]
+//
+//--------------------------------------------------------------------
+
+inline void CSkipListEntry::SetForward(int iCur, CSkipListEntry* pnew)
+{
+ _apBaseForward[iCur] = pnew;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipListEntry::GetBase
+//
+// Synopsis: Get the base address of the forward pointer array.
+//
+//--------------------------------------------------------------------
+
+inline CSkipListEntry **CSkipListEntry::GetBase(void)
+{
+ return _apBaseForward;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipListEntry::GetEntry
+//
+// Synopsis: Get pointer to the client-supplied object that was
+// inserted into the skiplist using CSkipList::Insert.
+//
+//--------------------------------------------------------------------
+
+inline Entry * CSkipListEntry::GetEntry(void)
+{
+ Win4Assert(!_fHead);
+ return(_pvEntry);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CSkipListEntry::GetKey
+//
+// Synopsis: Return a pointer to the key of the object passed into
+// CSkipList::Insert or CSkipList::CSkipList.
+//
+// Arguments: [EntryToKeyOffset] -- amount to add to the address of
+// the client-supplied entry in
+// order to get the address of the
+// key.
+//
+//
+// Returns: Pointer to "Base", otherwise known as key, of client
+// inserted object (or max key)
+//
+// Notes: If _fHead is TRUE, this indicates that the skip list
+// entry is the one allocated by CSkipList::CSkipList.
+// In this case, the pointer to the user-supplied entry
+// is actually a pointer to the key (since we don't need
+// a full entry object for use as a maximum key value.)
+// If _fHead is FALSE, then the object was allocated by
+// CSkipList::Insert and thus the entry pointer needs
+// to be adjusted in order to get the address of the key.
+//
+//--------------------------------------------------------------------
+
+inline Base * CSkipListEntry::GetKey(const int EntryToKeyOffset)
+{
+ if (_fHead)
+ return (Base*)_pvEntry;
+ else
+ return (Base*) (((char*)_pvEntry)+EntryToKeyOffset);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Macro: DEFINE_TYPE_SAFE_SKIPLIST
+//
+// Purpose: Generates a wrapper class to provide type safe skip lists.
+//
+// Arguments: [NewType] -- The name of the new class (derives privately
+// from CSkipList.
+// [EntryType] -- type of entry (must be derived from BaseType.
+// [BaseType] -- type of key
+//
+// History: 04-Nov-94 BillMo Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#define DEFINE_TYPE_SAFE_SKIPLIST(NewType,EntryType,BaseType)\
+class NewType : private CSkipList\
+{\
+public:\
+ inline NewType(\
+ LPFNCOMPARE lpfnCompare,\
+ LPFNDELETE lpfnDelete,\
+ const int EntryToKeyOffset,\
+ BOOL fSharedAlloc,\
+ Base * pvMaxKey,\
+ const int cMaxLevel,\
+ HRESULT & hr) :\
+ CSkipList(lpfnCompare,\
+ lpfnDelete,\
+ EntryToKeyOffset,\
+ fSharedAlloc,\
+ pvMaxKey,\
+ cMaxLevel,\
+ hr) {}\
+ inline EntryType * Search(const BaseType * skey)\
+ {\
+ return (EntryType*) CSkipList::Search(skey);\
+ }\
+ inline EntryType * Insert(EntryType *pEntryNew)\
+ {\
+ return (EntryType*) CSkipList::Insert(pEntryNew);\
+ }\
+ inline EntryType * Remove(BaseType * BaseKey)\
+ {\
+ return (EntryType*) CSkipList::Remove(BaseKey);\
+ }\
+ inline EntryType * Replace(BaseType * BaseKey, EntryType * pEntryNew)\
+ {\
+ return (EntryType*) CSkipList::Replace(BaseKey, pEntryNew);\
+ }\
+ inline EntryType * First(CSkipListEnum *psle)\
+ {\
+ return (EntryType*) CSkipList::First(psle);\
+ }\
+ inline EntryType * Next(CSkipListEnum *psle)\
+ {\
+ return (EntryType*) CSkipList::Next(psle);\
+ }\
+ inline CSkipListEntry * GetList(void)\
+ {\
+ return CSkipList::GetList();\
+ }\
+};
+
+#endif // __SKIPLIST_HXX__
+
diff --git a/private/ole32/com/inc/sklist.cxx b/private/ole32/com/inc/sklist.cxx
new file mode 100644
index 000000000..b5bfc2edd
--- /dev/null
+++ b/private/ole32/com/inc/sklist.cxx
@@ -0,0 +1,103 @@
+//+-------------------------------------------------------------------------
+//
+// Copyright (C) 1992, Microsoft Corporation.
+//
+// File: sklist.cxx
+//
+// Contents: Level generator functions required by skip lists
+//
+// Functions: RandomBit - generate a random on or off bit
+// InitSkLevelGenerator - initialize random bit seed
+// GetSkLevel - return a skip list forward pointer array size
+//
+// History: 30-Apr-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include <time.h>
+#include <sklist.hxx>
+
+static ULONG ulLSFR;
+
+//+-------------------------------------------------------------------------
+//
+// Function: RandomBit
+//
+// Synopsis: Uses various shifts to generate random bit
+//
+// Returns: 0 or 1
+//
+// History: 30-Apr-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+static inline ULONG RandomBit(void)
+{
+ ulLSFR = (((ulLSFR >> 31)
+ ^ (ulLSFR >> 6)
+ ^ (ulLSFR >> 4)
+ ^ (ulLSFR >> 2)
+ ^ (ulLSFR >> 1)
+ ^ ulLSFR
+ & 0x00000001)
+ << 31)
+ | (ulLSFR >> 1);
+
+ return ulLSFR & 0x00000001;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: InitSkLevelGenerator
+//
+// Synopsis: Seed the random bit generator with the time
+//
+// History: 30-Apr-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+// Set up the generator for skip list levels
+void InitSkLevelGenerator(void)
+{
+ // BUGBUG: Need to revisit whether this is a random enough
+ // value to use for the seed
+ time_t timeCurrent;
+ time(&timeCurrent);
+ ulLSFR = timeCurrent;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetSkLevel
+//
+// Synopsis: Set the level for an entry in a skip list
+//
+// Arguments: [cMax] - maximum level to return
+//
+// Returns: a number between 1 and cMax
+//
+// History: 30-Apr-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+// Get a level from the generator
+int GetSkLevel(int cMax)
+{
+ // There should always be at least one entry returned
+ int cRetLevel = 1;
+
+ // Loop while the level is less than the maximum level
+ // to return and a 1 is returned from RandomBit. Note
+ // that this is equivalent to p = 1/2. If you don't
+ // know what p = 1/2 means see Communications of the ACM
+ // June 1990 on Skip Lists.
+ while (cRetLevel < cMax && RandomBit())
+ {
+ cRetLevel++;
+ }
+
+ return cRetLevel;
+}
diff --git a/private/ole32/com/inc/sklist.hxx b/private/ole32/com/inc/sklist.hxx
new file mode 100644
index 000000000..55637ae20
--- /dev/null
+++ b/private/ole32/com/inc/sklist.hxx
@@ -0,0 +1,334 @@
+//+-------------------------------------------------------------------------
+//
+// Copyright (C) 1992, Microsoft Corporation.
+//
+// File: sklist.hxx
+//
+// Contents: Macros that are used as templates for skip list
+// implementation.
+//
+// History: 06-May-92 Ricksa Created
+// 18-May-94 BruceMa Fixed scm memory leak in SKIP_LIST_ENTRY
+// 28-Jun-94 BruceMa Memory sift fixes
+//
+//--------------------------------------------------------------------------
+#ifndef __SKLIST_HXX__
+#define __SKLIST_HXX__
+
+//
+// BUGBUG: this unnessarily forces all skip lists in shared memory
+//
+#include <scmmem.hxx>
+
+// Used by insert/delete algorithms to preallocate array on stack.
+// This is valid for skip lists with <= 64K elements.
+#define SKIP_LIST_MAX 16
+
+// Set up the generator for skip list levels
+void InitSkLevelGenerator(void);
+
+// Get a level from the generator
+int GetSkLevel(int cMax);
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Macro: SKIP_LIST_ENTRY
+//
+// Purpose: Implements an entry in a skip list.
+//
+// Interface: cLevel - returns number of forward pointers
+// GetForward - returns the ith forward pointer
+// SetForward - sets the ith forward pointer
+//
+// History: 06-May-92 Ricksa Created
+//
+// Notes: Base class is assumed to be defined with
+// INHERIT_VIRTUAL_UNWIND
+//
+//--------------------------------------------------------------------------
+#define SKIP_LIST_ENTRY(Entry, Base) \
+ \
+class Entry : public Base \
+{ \
+public: \
+ Entry( \
+ const Base& Base##Value, \
+ const int cEntries); \
+ \
+ virtual ~Entry##(void); \
+ \
+ int cLevel(void); \
+ \
+ Entry* GetForward(int iCur); \
+ \
+ void SetForward(int iCur, Entry* pnew); \
+ Entry **GetBase(void); \
+ \
+private: \
+ \
+ int _cEntries; \
+ \
+ Entry SCMBASED * SCMBASED * _ap##Base##Forward; \
+}; \
+ \
+inline Entry::Entry( \
+ const Base& Base##Value, \
+ const int cEntries) : \
+ Base(Base##Value), \
+ _cEntries(cEntries), \
+ _ap##Base##Forward(NULL) \
+{ \
+ if (cEntries != 0) \
+ { \
+ _ap##Base##Forward = (Entry **) \
+ ScmMemAlloc(sizeof(Entry*) * _cEntries); \
+ } \
+} \
+ \
+ \
+inline Entry##::~Entry##(void) \
+{ \
+\
+ ScmMemFree(_ap##Base##Forward); \
+} \
+ \
+inline int Entry##::cLevel(void) \
+{ \
+ return _cEntries; \
+} \
+ \
+inline Entry* Entry::GetForward(int iCur) \
+{ \
+ return _ap##Base##Forward[iCur]; \
+} \
+ \
+inline void Entry::SetForward(int iCur, Entry* pnew) \
+{ \
+ _ap##Base##Forward[iCur] = pnew; \
+} \
+ \
+inline Entry **Entry::GetBase(void) \
+{ \
+ return _ap##Base##Forward; \
+} \
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Macro: SKIP_LIST_HEAD
+//
+// Purpose: Implements head of a skip list.
+//
+// Interface: Search - find item in list
+// Insert - add new item to the list
+// Delete - remove item from the list
+// GetSkLevel - generate forward pointer for item in the list
+//
+// History: 06-May-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#define SKIP_LIST_HEAD(Head, Entry, Base) \
+class Head : public CScmAlloc \
+{ \
+public: \
+ \
+ Head##( \
+ const int cMaxLevel, \
+ Base##& p##Base##MaxKey); \
+ \
+ ~Head##(void); \
+ \
+ Entry * Search(const Base##& skey); \
+ \
+ void Insert(Entry *p##Entry##New); \
+ \
+ void Delete(Base##& Base##Key); \
+ \
+ int GetSkLevel(void); \
+ \
+ Entry * First(void); \
+ \
+ Entry * Next(Entry *); \
+ Entry * GetList(void); \
+ \
+private: \
+ \
+ Entry * FillUpdateArray( \
+ const Base *Base##Key, \
+ Entry **pp##Entry##Update); \
+ \
+ int _cCurrentMaxLevel; \
+ \
+ int _cMaxLevel; \
+ \
+ Entry SCMBASED * _p##Entry##Head; \
+}; \
+ \
+inline Head##::##Head##( \
+ const int cMaxLevel, \
+ Base& Base##MaxKey) : _cCurrentMaxLevel(0), _cMaxLevel(cMaxLevel) \
+{ \
+ _p##Entry##Head = new Entry(Base##MaxKey, cMaxLevel); \
+ \
+ if (_p##Entry##Head && _p##Entry##Head->GetBase()) \
+ { \
+ for (int i = 0; i < cMaxLevel; i++) \
+ { \
+ _p##Entry##Head->SetForward(i, _p##Entry##Head); \
+ } \
+ } \
+} \
+ \
+inline Head##::~##Head##(void) \
+{ \
+ if (_p##Entry##Head) \
+ { \
+ if (_p##Entry##Head->GetBase()) \
+ { \
+ while (_p##Entry##Head->GetForward(0) != _p##Entry##Head) \
+ { \
+ Delete(*_p##Entry##Head->GetForward(0)); \
+ } \
+ } \
+ \
+ delete (Entry *) _p##Entry##Head; \
+ } \
+} \
+ \
+inline Entry *##Head##::Search(const Base##& Base##Key) \
+{ \
+ Entry *p##Entry##Search = _p##Entry##Head; \
+ \
+ register int CmpResult = -1; \
+ \
+ for (int i = _cCurrentMaxLevel - 1; i >= 0; i--) \
+ { \
+ while ((CmpResult = \
+ p##Entry##Search->GetForward(i)->Compare(Base##Key)) < 0) \
+ { \
+ p##Entry##Search = p##Entry##Search->GetForward(i); \
+ } \
+ \
+ if (CmpResult == 0) \
+ { \
+ break; \
+ } \
+ } \
+ \
+ return (CmpResult == 0) \
+ ? (Entry *) p##Entry##Search->GetForward(i) : NULL; \
+} \
+ \
+inline Entry *##Head##::FillUpdateArray( \
+ const Base *Base##Key, \
+ Entry **pp##Entry##Update) \
+{ \
+ Entry *p##Entry##Search = _p##Entry##Head; \
+ if (p##Entry##Search) \
+ { \
+ \
+ for (int i = _cCurrentMaxLevel - 1; i >= 0; i--) \
+ { \
+ while (p##Entry##Search->GetForward(i)->Compare(*##Base##Key) < 0) \
+ { \
+ p##Entry##Search = p##Entry##Search->GetForward(i); \
+ } \
+ \
+ pp##Entry##Update[i] = p##Entry##Search; \
+ } \
+ \
+ return p##Entry##Search->GetForward(0); \
+ } \
+ else \
+ { \
+ return NULL; \
+ } \
+} \
+ \
+inline void Head##::Insert(Entry *p##Entry##New) \
+{ \
+ Entry *ap##Entry##Update[SKIP_LIST_MAX]; \
+ \
+ if (p##Entry##New && _p##Entry##Head) \
+ { \
+ FillUpdateArray(p##Entry##New, ap##Entry##Update); \
+ \
+ int iNewLevel = p##Entry##New->cLevel(); \
+ \
+ if (iNewLevel > _cCurrentMaxLevel) \
+ { \
+ for (int i = _cCurrentMaxLevel; i < iNewLevel; i++) \
+ { \
+ ap##Entry##Update[i] = _p##Entry##Head; \
+ } \
+ \
+ _cCurrentMaxLevel = iNewLevel; \
+ } \
+ \
+ for (int i = 0; i < iNewLevel ; i++) \
+ { \
+ p##Entry##New->SetForward(i, ap##Entry##Update[i]->GetForward(i)); \
+ ap##Entry##Update[i]->SetForward(i, p##Entry##New); \
+ } \
+ } \
+} \
+ \
+inline void Head##::Delete(Base##& Base##Key) \
+{ \
+ Entry *ap##Entry##Update[SKIP_LIST_MAX]; \
+ \
+ Entry *p##Entry##Delete = \
+ FillUpdateArray(&##Base##Key, ap##Entry##Update); \
+ \
+ for (int i = 0; i < _cCurrentMaxLevel; i++) \
+ { \
+ if (ap##Entry##Update[i]->GetForward(i) != p##Entry##Delete) \
+ { \
+ break; \
+ } \
+ \
+ ap##Entry##Update[i]->SetForward(i, p##Entry##Delete->GetForward(i)); \
+ } \
+ delete p##Entry##Delete; \
+ \
+ while (_cCurrentMaxLevel > 1 && \
+ _p##Entry##Head->GetForward(_cCurrentMaxLevel - 1) == \
+ _p##Entry##Head) \
+ { \
+ _cCurrentMaxLevel--; \
+ } \
+} \
+ \
+inline int Head::GetSkLevel(void) \
+{ \
+ return ::GetSkLevel( \
+ (_cCurrentMaxLevel != _cMaxLevel) ? _cCurrentMaxLevel + 1 : _cMaxLevel); \
+} \
+ \
+inline Entry *Head::First(void) \
+{ \
+ Entry *p##Entry##First = _p##Entry##Head->GetForward(0); \
+ \
+ return (p##Entry##First != _p##Entry##Head) ? p##Entry##First : NULL; \
+} \
+ \
+inline Entry *Head::Next(Entry *p##Entry##From) \
+{ \
+ Entry *p##Entry##To = p##Entry##From->GetForward(0); \
+ \
+ return (p##Entry##To != _p##Entry##Head) ? p##Entry##To : NULL; \
+} \
+ \
+inline Entry *Head::GetList(void) \
+{ \
+ \
+ return _p##Entry##Head; \
+} \
+
+#endif // __SKLIST_HXX__
diff --git a/private/ole32/com/inc/smbasep.hxx b/private/ole32/com/inc/smbasep.hxx
new file mode 100644
index 000000000..a692eaa75
--- /dev/null
+++ b/private/ole32/com/inc/smbasep.hxx
@@ -0,0 +1,30 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: smbasep.hxx
+//
+// Contents: Macros and types for using based pointers
+//
+// History: 19-Jun-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+#ifndef __SMBASEP_HXX__
+#define __SMBASEP_HXX__
+
+// Make these warnings errors, they deal with based pointers
+#pragma warning(error: 4795 4796)
+
+// Macro for converting a pointer to a based pointer
+// example: P_TO_BP(MyPointer __based(mybase) *, pMyPointer)
+#define P_TO_BP(t, p) ((t)((p) ? (int)(t)(char *)(p) : 0))
+
+// Macro for converting a based pointer to a pointer
+// example : BP_TO_P(MyPointer *, bpMyPointer)
+#define BP_TO_P(t, bp) (t)((bp) != 0 ? (bp) : 0)
+
+// a type to hold a based pointer
+typedef DWORD SmBasedPtr;
+
+#endif // __SMBASEP_HXX__
diff --git a/private/ole32/com/inc/smblock.cxx b/private/ole32/com/inc/smblock.cxx
new file mode 100644
index 000000000..e3dbd22a6
--- /dev/null
+++ b/private/ole32/com/inc/smblock.cxx
@@ -0,0 +1,321 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: smblock.cxx
+//
+// Contents: Shared memory block code
+//
+// Classes:
+//
+// Functions:
+//
+// History: 24-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <smblock.hxx>
+#include <smcreate.hxx>
+
+#if DBG == 1
+DECLARE_INFOLEVEL(mem);
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSharedMemoryBlock::~CSharedMemoryBlock, public
+//
+// Synopsis: Destructor
+//
+// Returns: Appropriate status code
+//
+// History: 25-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CSharedMemoryBlock::~CSharedMemoryBlock()
+{
+ CloseSharedFileMapping(_hMem, _pbBase);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSharedMemoryBlock::Init
+//
+// Synopsis: Create/get address of shared memory block.
+//
+// Arguments: [pszName] - name of block to allocate
+// [culSize] - size of block to allocate
+//
+// Algorithm: Attempts to open the block first. If this fails then
+// this creates the block of memory. It then puts the
+// address of the block as the first bytes of the block.
+// If the block already exists, the memory is mapped
+// and then the address is read. The memory is then mapped
+// to the address.
+//
+// History: 03-Nov-93 Ricksa Created
+// 07-Jan-94 AlexT No security for CHICAGO
+//
+// Notes: Counts on some outside synchronization to prevent
+// a race in the creation of the memory.
+//
+//--------------------------------------------------------------------------
+SCODE CSharedMemoryBlock::Init(
+ LPWSTR pszName,
+ ULONG culSize,
+ ULONG culCommitSize,
+ void *pvBase,
+ PSECURITY_DESCRIPTOR lpSecDes,
+ BOOL fOKToCreate)
+{
+ SCODE sc = S_OK;
+
+ memAssert((_hMem == NULL) &&
+ "Attempt to Init CSharedMemoryBlock twice.");
+
+ //We store a header on the shared memory - this should be
+ // transparent to clients.
+ culSize = culSize + sizeof(CSharedMemHeader);
+
+
+ if (fOKToCreate)
+ {
+ // try to create the shared file mapping
+ // creates or opens it for Read/Write access.
+
+ _fReadWrite = TRUE;
+
+ _hMem = CreateSharedFileMapping(pszName,
+ culSize, // size of shared mem
+ 0, // map size
+ pvBase, // base addr
+ lpSecDes, // security desc
+ PAGE_READWRITE | SEC_RESERVE,
+ (void **)&_pbBase, // returned base ptr
+ &_fCreated); // created or not
+ }
+ else
+ {
+ // try to open the shared file mapping.
+ // opens it for read only access, base address unspecified.
+
+ _fReadWrite = FALSE;
+ _fCreated = FALSE;
+
+ _hMem = OpenSharedFileMapping(pszName,
+ 0, // map size
+ (void **)&_pbBase); // returned base ptr
+ }
+
+ if (_hMem == NULL)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+
+#if DBG == 1
+ MEMORY_BASIC_INFORMATION meminf;
+ ULONG cbReal;
+
+ cbReal = VirtualQuery(_pbBase, &meminf, sizeof(MEMORY_BASIC_INFORMATION));
+
+ memDebugOut((DEB_ITRACE, "cbReal == %lu, Mem Info: Base Address %p, Allocation Base %p, AllocationProtect %lx, Region Size %lu, State %lx, Protect %lx, Type %lx\n",
+ cbReal, meminf.BaseAddress, meminf.AllocationBase, meminf.AllocationProtect,
+ meminf.RegionSize, meminf.State, meminf.Protect, meminf.Type));
+#endif
+
+ // Commit the first page
+ void *pvResult;
+ pvResult = VirtualAlloc(_pbBase, culCommitSize, MEM_COMMIT,
+ (_fReadWrite) ? PAGE_READWRITE : PAGE_READONLY);
+ if (pvResult == NULL)
+ {
+ sc = GetScode(HRESULT_FROM_WIN32(GetLastError()));
+ memDebugOut((DEB_ERROR, "CSharedMemoryBlock::Commit of %lu bytes"
+ " failed with %lx\n", culCommitSize, sc));
+ return sc;
+ }
+
+#if DBG == 1
+ cbReal = VirtualQuery(_pbBase, &meminf, sizeof(MEMORY_BASIC_INFORMATION));
+
+ memDebugOut((DEB_ITRACE, "cbReal == %lu, Mem Info: Base Address %p, Allocation Base %p, AllocationProtect %lx, Region Size %lu, State %lx, Protect %lx, Type %lx\n",
+ cbReal, meminf.BaseAddress, meminf.AllocationBase, meminf.AllocationProtect,
+ meminf.RegionSize, meminf.State, meminf.Protect, meminf.Type));
+#endif
+
+ _culCommitSize = culCommitSize;
+ _culInitCommitSize = culCommitSize;
+
+ //If we created the block, mark the size in the header.
+ if (_fCreated)
+ {
+ ((CSharedMemHeader *)_pbBase)->SetSize(_culCommitSize);
+ }
+ else
+ {
+ sc = Sync();
+ }
+
+ return sc;
+}
+
+#ifdef RESETOK
+//+---------------------------------------------------------------------------
+//
+// Member: CSharedMemoryBlock::Reset, public
+//
+// Synopsis: Reset the shared memory block to its original empty state
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+// History: 04-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CSharedMemoryBlock::Reset(void)
+{
+#if DBG == 1
+ BOOL b;
+#endif
+ void *pv;
+
+ memDebugOut((DEB_ITRACE, "In CSharedMemoryBlock::Reset:%p()\n", this));
+
+#if DBG == 1
+ b =
+#endif
+ VirtualFree(_pbBase, _culCommitSize, MEM_DECOMMIT);
+ memAssert(b && "VirtualFree failed.");
+
+#if DBG == 1
+ if (b == NULL)
+ {
+ memDebugOut((DEB_ERROR, "VirtualFree failed with %lx\n", GetLastError()));
+ }
+#endif
+
+ pv = VirtualAlloc(_pbBase, , _culInitCommitSize, MEM_COMMIT,
+ (_fReadWrite) ? PAGE_READWRITE : PAGE_READONLY);
+ if (pv == NULL)
+ {
+ SCODE sc = GetScode(HRESULT_FROM_WIN32(GetLastError()));
+ memDebugOut((DEB_ERROR, "CSharedMemoryBlock::Commit of %lu bytes"
+ " failed with %lx\n", _culInitCommitSize, sc));
+ return sc;
+ }
+
+ _culCommitSize = _culInitCommitSize;
+ ((CSharedMemHeader *)_pbBase)->SetSize(_culCommitSize);
+
+ memDebugOut((DEB_ITRACE, "Out CSharedMemoryBlock::Reset\n"));
+ return S_OK;
+}
+#endif //RESETOK
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSharedMemoryBlock::Commit, public
+//
+// Synopsis: Commit the given number of bytes within the block
+//
+// Arguments: [culNewSize] -- Number of bytes to commit
+//
+// Returns: Appropriate status code
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CSharedMemoryBlock::Commit(ULONG culNewSize)
+{
+ SCODE sc = S_OK;
+ culNewSize = culNewSize + sizeof(CSharedMemHeader);
+
+ memAssert((culNewSize >= _culCommitSize) &&
+ "Attempted to shrink shared memory heap.");
+
+ if (culNewSize == _culCommitSize)
+ {
+ return sc;
+ }
+
+ void *pb;
+
+ pb = VirtualAlloc(_pbBase,
+ culNewSize,
+ MEM_COMMIT,
+ (_fReadWrite) ? PAGE_READWRITE : PAGE_READONLY);
+
+ if (pb == NULL)
+ {
+ sc = GetScode(HRESULT_FROM_WIN32(GetLastError()));
+ memDebugOut((DEB_ERROR,
+ "CSharedMemoryBlock::Commit of %lu bytes failed with %lx\n", culNewSize, sc));
+ }
+ else
+ {
+ _culCommitSize = culNewSize;
+
+ //If the new size is greater than the maximum committed size,
+ // update the maximum committed size.
+ CSharedMemHeader *psmh = (CSharedMemHeader *)_pbBase;
+ if (_culCommitSize > psmh->GetSize())
+ {
+ psmh->SetSize(_culCommitSize);
+ }
+ }
+
+#if DBG == 1
+ MEMORY_BASIC_INFORMATION meminf;
+ ULONG cbReal;
+
+ cbReal = VirtualQuery(_pbBase, &meminf, sizeof(MEMORY_BASIC_INFORMATION));
+
+ memDebugOut((DEB_ITRACE, "Commit size == %lu, cbReal == %lu, Mem Info: Base Address %p, Allocation Base %p, AllocationProtect %lx, Region Size %lu, State %lx, Protect %lx, Type %lx\n",
+ _culCommitSize, cbReal, meminf.BaseAddress, meminf.AllocationBase, meminf.AllocationProtect,
+ meminf.RegionSize, meminf.State, meminf.Protect, meminf.Type));
+
+ if (cbReal != sizeof(MEMORY_BASIC_INFORMATION))
+ {
+ memDebugOut((DEB_ERROR, "Virtual Query error: %lx\n", GetLastError()));
+ }
+
+#endif
+
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSharedMemoryBlock::Sync, public
+//
+// Synopsis: Match committed view to largest committed view
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CSharedMemoryBlock::Sync(void)
+{
+ CSharedMemHeader *psmh = (CSharedMemHeader *)_pbBase;
+
+ ULONG culSize = psmh->GetSize();
+
+ if (culSize != _culCommitSize)
+ {
+ return Commit(culSize - sizeof(CSharedMemHeader));
+ }
+ return S_OK;
+}
diff --git a/private/ole32/com/inc/smblock.hxx b/private/ole32/com/inc/smblock.hxx
new file mode 100644
index 000000000..918591b59
--- /dev/null
+++ b/private/ole32/com/inc/smblock.hxx
@@ -0,0 +1,262 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: smblock.hxx
+//
+// Contents: Class & Functions for allocting & using a block of shared
+// memory.
+//
+// Classes: CSharedMemoryBlock
+//
+// Functions:
+//
+// History: 03-Nov-92 Ricksa Created
+// 24-Mar-94 PhilipLa Modified for growable memory block
+//
+//--------------------------------------------------------------------------
+#ifndef __SMBLOCK_HXX__
+#define __SMBLOCK_HXX__
+
+#include <debnot.h>
+#include <secdes.hxx>
+#include <memdebug.hxx>
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSharedMemHeader
+//
+// Purpose: Header information for shared mem block
+//
+// Interface:
+//
+// History: 22-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+class CSharedMemHeader
+{
+public:
+ inline ULONG GetSize(void);
+ inline void SetSize(ULONG ulSize);
+
+private:
+ ULONG _ulSize;
+ ULONG ulPad;
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSharedMemHeader::GetSize, public
+//
+// Synopsis: Returns the maximum committed size of the block
+//
+// History: 22-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CSharedMemHeader::GetSize(void)
+{
+ return _ulSize;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSharedMemHeader::SetSize, public
+//
+// Synopsis: Sets the maximum committed size of the block
+//
+// History: 22-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CSharedMemHeader::SetSize(ULONG ulSize)
+{
+ _ulSize = ulSize;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSharedMemoryBlock
+//
+// Purpose: Class to handle allocation/connection with a shared
+// memory block.
+//
+// Interface: Base - get base of shared memory block.
+// InRange - whether pointer falls in range of the block.
+// CreatedSharedMemory - whether this process created the block
+//
+// History: 03-Nov-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CSharedMemoryBlock
+{
+public:
+ inline CSharedMemoryBlock();
+
+ ~CSharedMemoryBlock();
+
+ SCODE Init(LPWSTR pszName,
+ ULONG culSize,
+ ULONG culCommitSize,
+ void *pvBase,
+ PSECURITY_DESCRIPTOR lpSecDes,
+ BOOL fOKToCreate);
+
+#ifdef RESETOK
+ SCODE Reset(void);
+#endif
+
+ SCODE Commit(ULONG culNewSize);
+
+ SCODE Sync(void);
+
+ inline ULONG GetSize(void);
+
+ inline void * GetBase(void);
+
+ inline BOOL InRange(void const *pv);
+
+ inline BOOL Created(void);
+
+ inline ULONG GetHdrSize(void);
+
+ inline BOOL IsSynced(void);
+
+private:
+
+ HANDLE _hMem;
+
+ BYTE *_pbBase;
+
+ ULONG _culCommitSize; // current commit size
+
+ ULONG _culInitCommitSize; // initial commit size
+
+ BOOL _fCreated; // mem created vs already existed
+
+ BOOL _fReadWrite; // want read/write access
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSharedMemoryBlock::CSharedMemoryBlock, public
+//
+// Synopsis: Default constructor
+//
+// History: 22-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CSharedMemoryBlock::CSharedMemoryBlock()
+{
+ _hMem = NULL;
+ _pbBase = NULL;
+ _culCommitSize = 0;
+ _culInitCommitSize = 0;
+ _fCreated = TRUE;
+ _fReadWrite = FALSE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSharedMemoryBlock::GetSize, public
+//
+// Synopsis: Return the committed size for this block
+//
+// History: 22-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CSharedMemoryBlock::GetSize(void)
+{
+ return _culCommitSize - sizeof(CSharedMemHeader);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSharedMemoryBlock::GetBase, public
+//
+// Synopsis: Return the base pointer for this memory block
+//
+// History: 22-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void * CSharedMemoryBlock::GetBase(void)
+{
+ return _pbBase + sizeof(CSharedMemHeader);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSharedMemoryBlock::InRange
+//
+// Synopsis: Return whether pointer falls within the block
+//
+// Arguments: [pv] - pointer to check
+//
+// Returns: FALSE - no within block
+// TRUE - within block
+//
+// History: 03-Nov-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CSharedMemoryBlock::InRange(void const *pv)
+{
+ return (ULONG) ((BYTE *) pv - _pbBase) < _culCommitSize;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSharedMemoryBlock::Created, public
+//
+// Synopsis: Return TRUE if we created the shared mem block or
+// FALSE if it already existed
+//
+// History: 22-Apr-94 Rickhi Created
+//
+//----------------------------------------------------------------------------
+inline BOOL CSharedMemoryBlock::Created(void)
+{
+ return _fCreated;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSharedMemoryBlock::GetHdrSize, public
+//
+// Synopsis: Return the size of the shared mem hdr structure
+//
+// History: 22-Apr-94 Rickhi Created
+//
+//----------------------------------------------------------------------------
+inline ULONG CSharedMemoryBlock::GetHdrSize(void)
+{
+ return sizeof(CSharedMemHeader);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSharedMemoryBlock::IsSynced, public
+//
+// Synopsis: Return true if the block is in sync
+//
+// History: 12-Aug-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+inline BOOL CSharedMemoryBlock::IsSynced(void)
+{
+ return ((CSharedMemHeader *)_pbBase)->GetSize() == _culCommitSize;
+}
+
+
+#endif // __SMBLOCK_HXX__
diff --git a/private/ole32/com/inc/smcreate.cxx b/private/ole32/com/inc/smcreate.cxx
new file mode 100644
index 000000000..f64128f15
--- /dev/null
+++ b/private/ole32/com/inc/smcreate.cxx
@@ -0,0 +1,235 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: smcreate.cxx
+//
+// Contents: Routines for Creating or Opening memory mapped files.
+//
+// Functions: CreateSharedFileMapping
+// OpenSharedFileMapping
+// CloseSharedFileMapping
+//
+// History: 03-Nov-93 Ricksa Created
+// 07-Apr-94 Rickhi Seperated into APIs
+//
+// Notes: These APIs are used by dirrot.cxx, dirrot2.cxx, smblock.cxx,
+// (both ole32.dll and scm.exe), that is why they are in the
+// the directory.
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include <secdes.hxx>
+#include <smcreate.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateSharedFileMapping
+//
+// Synopsis: Creates or gets access to memory mapped file.
+//
+// Arguments: [pszName] - name of file
+// [ulSize] - size of shared memory
+// [ulMapSize] - size of shared memory to map right now
+// [pvBase] - base address to request
+// [lpSecDes] - security descriptor
+// [dwAccess] - access wanted
+// [ppv] - return address for memory ptr
+// [pfCreated] - returns TRUE if memory was created
+//
+// Algorithm: Creates a file mapping of the requested name and size
+// and maps it into memory with READ and WRITE access.
+//
+// Returns: HANDLE of file or NULL if failed.
+// [ppv] - base address of shared memory
+// [fCreated] - TRUE if the file was created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HANDLE CreateSharedFileMapping(WCHAR *pszName,
+ ULONG ulSize,
+ ULONG ulMapSize,
+ void *pvBase,
+ PSECURITY_DESCRIPTOR lpSecDes,
+ DWORD dwAccess,
+ void **ppv,
+ BOOL *pfCreated)
+{
+ CairoleDebugOut((DEB_MEMORY,
+ "CreateSharedFileMapping name:%ws size:%x base:%x\n",
+ pszName, ulSize, pvBase));
+
+ BOOL fCreated = TRUE;
+
+#if defined(_CHICAGO_)
+ // no security on Chicago
+ lpSecDes = NULL;
+#else
+ // BUGBUG: Need to make this memory read only for all users
+ CWorldSecurityDescriptor wsd;
+ if (lpSecDes == NULL)
+ {
+ lpSecDes = &wsd;
+ }
+#endif
+
+ // Holder for attributes to pass in on create.
+ SECURITY_ATTRIBUTES secattr;
+
+ secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ secattr.lpSecurityDescriptor = lpSecDes;
+ secattr.bInheritHandle = FALSE;
+
+ // Create the shared memory object
+ HANDLE hMem = CreateFileMapping((HANDLE) 0xFFFFFFFF, &secattr,
+ dwAccess, 0, ulSize, pszName);
+
+#if DBG==1
+ if (hMem == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CreateSharedFileMapping create of memory failed %d\n",
+ GetLastError()));
+ }
+
+#endif
+
+ void *pvAddr = NULL;
+
+ if (hMem != NULL)
+ {
+ if (GetLastError() != ERROR_SUCCESS)
+ {
+ // If memory existed before our call then GetLastError returns
+ // ERROR_ALREADY_EXISTS, so we can tell whether we were the first
+ // one in or not.
+
+#if DBG==1
+ if (GetLastError() != ERROR_ALREADY_EXISTS)
+ {
+ CairoleDebugOut((DEB_WARN,
+ "CreateFileMapping - expected ERROR_ALREADY_EXISTS, got %lx\n",
+ GetLastError()));
+ }
+#endif // DBG==1
+
+ CairoleDebugOut((DEB_MEMORY ,"SharedMem File Existed\n"));
+ fCreated = FALSE;
+ }
+
+ // Map the shared memory we have created into our process space
+ pvAddr = MapViewOfFileEx(hMem, FILE_MAP_WRITE,
+ 0, 0, ulMapSize, pvBase);
+
+#if DBG==1
+ if (pvAddr == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR, "MapViewOfFile failed!! with %d\n",
+ GetLastError()));
+ }
+#endif // DBG==1
+
+ if (pvAddr == NULL)
+ {
+ CloseHandle(hMem);
+ hMem = NULL;
+ }
+ }
+
+ if (pfCreated)
+ {
+ *pfCreated = fCreated;
+ }
+
+ *ppv = pvAddr;
+ return hMem;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OpenSharedFileMapping
+//
+// Synopsis: opens a memory mapped file.
+//
+// Arguments: [pszName] - name of file
+// [ulMapSize] - size of shared memory to map right now
+// [ppv] - return address for memory ptr
+//
+// Algorithm: Does an OpenFileMapping on the requested filename,
+// then a MapViewOfFile. ReadOnly access is granted.
+//
+// Returns: HANDLE of the file or NULL if failed.
+// [ppv] - base address of the shared memory.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HANDLE OpenSharedFileMapping(WCHAR *pszName,
+ ULONG ulMapSize,
+ void **ppv)
+{
+ CairoleDebugOut((DEB_MEMORY, "OpenSharedFileMapping name:%ws size:%x\n",
+ pszName, ulMapSize));
+
+ // Create the shared memory object
+ HANDLE hMem = OpenFileMapping(FILE_MAP_READ, FALSE, pszName);
+
+ void *pvAddr = NULL;
+
+ if (hMem != NULL)
+ {
+ // Map the shared memory we have created into our process space
+ pvAddr = MapViewOfFile(hMem, FILE_MAP_READ, 0, 0, ulMapSize);
+
+ Win4Assert(pvAddr && "MapViewOfFile failed!!");
+
+ if (pvAddr == NULL)
+ {
+ CloseHandle(hMem);
+ hMem = NULL;
+ }
+ }
+ else
+ {
+ CairoleDebugOut((DEB_MEMORY, "OpenFileMapping failed.\n"));
+ }
+
+ *ppv = pvAddr;
+ return hMem;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CloseSharedFileMapping
+//
+// Synopsis: closes a memory mapped file.
+//
+// Arguments: [hMem] - shared memory handle
+// [pv] - base address of shared memory pointer
+//
+// Algorithm: Unmaps the view of the file and closes the file handle.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+void CloseSharedFileMapping(HANDLE hMem, void *pv)
+{
+ if (pv != NULL)
+ {
+ // release the shared memory. carefull not to release NULL.
+ UnmapViewOfFile(pv);
+ }
+ if (hMem != NULL)
+ {
+ CloseHandle(hMem);
+ }
+}
diff --git a/private/ole32/com/inc/smcreate.hxx b/private/ole32/com/inc/smcreate.hxx
new file mode 100644
index 000000000..2be2ae7b1
--- /dev/null
+++ b/private/ole32/com/inc/smcreate.hxx
@@ -0,0 +1,44 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: smcreate.hxx
+//
+// Contents: Prototypes for routines for Creating or Opening
+// memory mapped files.
+//
+// Functions: CreateSharedFileMapping
+// OpenSharedFileMapping
+// CloseSharedFileMapping
+//
+// History: 03-Nov-93 Ricksa Created
+// 07-Apr-94 Rickhi Seperated into APIs
+//
+// Notes: These APIs are used by dirrot.cxx, dirrot2.cxx, smblock.cxx,
+// (both ole32.dll and scm.exe), that is why they are in the
+// the directory.
+//
+//--------------------------------------------------------------------------
+#ifndef __SMCREATE_HXX__
+#define __SMCREATE_HXX__
+
+
+HANDLE CreateSharedFileMapping(WCHAR *pszName,
+ ULONG ulSize,
+ ULONG ulMapSize,
+ void *pvBase,
+ PSECURITY_DESCRIPTOR lpSecDes,
+ DWORD dwAccess,
+ void **ppv,
+ BOOL *pfCreated);
+
+
+HANDLE OpenSharedFileMapping(WCHAR *pszName,
+ ULONG ulMapSize,
+ void **ppv);
+
+void CloseSharedFileMapping(HANDLE hMem, void *pv);
+
+
+#endif // __SMCREATE_HXX__
diff --git a/private/ole32/com/inc/smmutex.cxx b/private/ole32/com/inc/smmutex.cxx
new file mode 100644
index 000000000..5cf3eda71
--- /dev/null
+++ b/private/ole32/com/inc/smmutex.cxx
@@ -0,0 +1,103 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: smmutex.cxx
+//
+// Contents: Cleanup routine for exception handler
+//
+// Functions: CSmMutex::CSmMutex
+//
+// History: 03-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include "secdes.hxx"
+#include "smmutex.hxx"
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSmMutex::Init
+//
+// Synopsis: Creates/or gets access to inter-process mutex
+//
+// Arguments: [pszName] - name of mutex
+// [fGet] - whether to return with mutex owned.
+//
+// Algorithm:
+//
+// History: 03-Nov-93 Author Comment
+// 07-Jan-94 AlexT No security for Chicago
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+SCODE CSmMutex::Init(LPTSTR pszName, BOOL fGet)
+{
+ SCODE sc = S_OK;
+
+ //If _hMutex is not NULL, we've already been initalized - make
+ // this a no-op.
+ if (_hMutex == NULL)
+ {
+#ifndef _CHICAGO_
+ // build all allowed security descriptor
+ CWorldSecurityDescriptor wsd;
+#endif
+
+ // Holder for attributes to pass in on create.
+ SECURITY_ATTRIBUTES secattr;
+
+ secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
+#ifdef _CHICAGO_
+ secattr.lpSecurityDescriptor = NULL;
+#else
+ secattr.lpSecurityDescriptor = &wsd;
+#endif
+ secattr.bInheritHandle = FALSE;
+
+ // This class is designed based on the idea that any process
+ // can be the creator of the mutex and therefore when
+ // no processes are using the mutex it disappears.
+
+ // The Win32 SDK Help recommends passing FALSE in fInitialOwner
+ // when creating a named mutex. This eliminates the ambiguity
+ // when this thread does not create, but rather opens the mutex.
+
+ _hMutex = CreateMutex(&secattr, FALSE, pszName);
+
+ if (_hMutex != NULL)
+ {
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ // We know that after a handle is returned that if GetLastError
+ // returns non-zero (actually ERROR_ALREADY_EXISTS), the current
+ // process is not the one to create this object. So we set our
+ // creation flag accordingly. The owner parameter is ignored by
+ // CreateMutex if this isn't the first creator, so we want to
+ // get the mutex as well so we can be sure that whoever created
+ // it is done with it for the moment.
+
+ _fCreated = FALSE;
+ }
+ }
+ else
+ {
+ sc = HRESULT_FROM_WIN32(GetLastError());
+ }
+ }
+
+ if (SUCCEEDED(sc) && (fGet))
+ {
+ Get();
+ }
+
+ // Note: we leave here with the mutex owned by this process iff the
+ // caller specified TRUE on the fGet parameter.
+ return sc;
+}
diff --git a/private/ole32/com/inc/smmutex.hxx b/private/ole32/com/inc/smmutex.hxx
new file mode 100644
index 000000000..22f0f3567
--- /dev/null
+++ b/private/ole32/com/inc/smmutex.hxx
@@ -0,0 +1,205 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: smmutex.hxx
+//
+// Contents: Class definition for shared memory mutex.
+//
+// Classes: CSmMutex
+//
+// Functions:
+//
+// History: 03-Nov-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __SMMUTEX_HXX__
+#define __SMMUTEX_HXX__
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSmMutex
+//
+// Purpose: Mutex shared among processes
+//
+// Interface: Get - get the mutex
+// Release - release the mutex for other processes
+// Created - tell whether this process created the mutex
+//
+// History: 21-Feb-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CSmMutex
+{
+public:
+
+ inline CSmMutex();
+
+ inline ~CSmMutex(void);
+
+ SCODE Init(LPTSTR pszName, BOOL fGet = TRUE);
+
+ inline void Get(void);
+
+ inline void Release(void);
+
+ inline BOOL Created(void);
+
+private:
+
+ BOOL _fCreated;
+
+ HANDLE _hMutex;
+
+};
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmMutex::CSmMutex, public
+//
+// Synopsis: Constructor
+//
+// History: 07-Jul-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CSmMutex::CSmMutex()
+{
+ _fCreated = FALSE;
+ _hMutex = NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSmMutex::~CSmMutex
+//
+// Synopsis: Clean up mutex when we are done with it.
+//
+// History: 21-Feb-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CSmMutex::~CSmMutex(void)
+{
+ // Release the Mutex -- this allows destructors of objects
+ // to get the mutex and leave it set until the mutex is released
+ // by the destructor.
+ Release();
+
+ // Release our handle.
+ CloseHandle(_hMutex);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSmMutex::Get
+//
+// Synopsis: Get control of mutex
+//
+// History: 21-Feb-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CSmMutex::Get(void)
+{
+ WaitForSingleObject(_hMutex, INFINITE);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSmMutex::Release
+//
+// Synopsis: Release mutex after a get
+//
+// History: 21-Feb-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CSmMutex::Release(void)
+{
+ ReleaseMutex(_hMutex);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSmMutex::Created
+//
+// Synopsis: Tell whether this process created the mutex
+//
+// Returns: TRUE if this process created the mutex
+//
+// History: 21-Feb-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CSmMutex::Created(void)
+{
+ return _fCreated;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CLockSmMutex
+//
+// Purpose: Simple class to guarantee about Mutex is unlocked
+//
+// History: 21-Feb-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CLockSmMutex
+{
+public:
+
+ CLockSmMutex(CSmMutex& smm);
+
+ ~CLockSmMutex(void);
+
+private:
+
+ CSmMutex& _smm;
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLockSmMutex::CLockSmMutex
+//
+// Synopsis: Get mutex
+//
+// Arguments: [smm] -- mutex to get
+//
+// History: 21-Feb-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CLockSmMutex::CLockSmMutex(CSmMutex& smm) : _smm(smm)
+{
+ _smm.Get();
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLockSmMutex::~CLockSmMutex
+//
+// Synopsis: Release the mutex
+//
+// History: 21-Feb-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CLockSmMutex::~CLockSmMutex(void)
+{
+ _smm.Release();
+}
+
+
+#endif // __SMMUTEX_HXX__
diff --git a/private/ole32/com/inc/smstack.cxx b/private/ole32/com/inc/smstack.cxx
new file mode 100644
index 000000000..00495750f
--- /dev/null
+++ b/private/ole32/com/inc/smstack.cxx
@@ -0,0 +1,175 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: smstack.cxx
+//
+// Contents: Shared mem stack-based allocator implementation
+//
+// Classes: CSmStackAllocator
+//
+// History: 19-Jun-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+#include <ole2int.h>
+#include <secdes.hxx>
+#pragma hdrstop
+#include <smstack.hxx>
+
+// *** Macros ***
+// quick macro to set up a pointer to base off of
+#define SETUP_BASE_POINTER() void *pbBase = m_pbBase
+
+// quick macro to make sure our base pointer is in sync
+#define SYNC_BASE_POINTER() pbBase = m_pbBase
+
+// quick macro to tell that a pointer is based off of the shared stack
+#define STACKBASED __based(pbBase)
+
+#define SHAREDMEMBASE NULL
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmStackAllocator::Init, public
+//
+// Synopsis: Initialize stack for use
+//
+// Arguments: [pszName] -- Name of shared memory block to use
+//
+// Returns: Appropriate hresult
+//
+// History: 19-Jun-95 t-stevan Created
+//
+// Remarks: Review the class destructor if you change this code.
+//
+//----------------------------------------------------------------------------
+HRESULT CSmStackAllocator::Init(LPWSTR pszName, ULONG cbMaxSize, ULONG cbInitSize)
+{
+ HRESULT hresult = S_OK;
+
+ SETUP_BASE_POINTER();
+
+ CairoleDebugOut((DEB_ITRACE, "CSmStackAllocator::Init(pszName = %ws,cbMaxSize = %d, cbInitSize = %d)\n",
+ pszName, cbMaxSize, cbInitSize));
+
+ // the SMB needs a few bytes for its own header. If we request
+ // a page sized allocation, those few header bytes will cause an
+ // extra page to be allocated, so to prevent that we subtract off
+ // the header space from our requests.
+ hresult = m_smb.Init(pszName, cbMaxSize - m_smb.GetHdrSize(), // reserve size
+ cbInitSize - m_smb.GetHdrSize(), // commit size
+ SHAREDMEMBASE, // base address
+ NULL, // security descriptor
+ TRUE); // create if doesn't exist
+
+ if(SUCCEEDED(hresult))
+ {
+ m_cbSize = m_smb.GetSize();
+ m_pbBase = (BYTE *) m_smb.GetBase();
+
+ if(m_smb.Created())
+ {
+ // we're the first stack, initialize shared memory
+ m_pHeader = (CSmStackHeader *) m_pbBase;
+ m_pbBase += sizeof(CSmStackHeader);
+
+ SYNC_BASE_POINTER();
+
+ m_pHeader->m_ulStack = 4; // start at 4 so that we still can have NULL pointers
+
+#if DBG == 1
+ m_pHeader->m_cbLostBytes = 0;
+#endif
+ }
+ else
+ {
+ // just sync up with the global stack
+ m_pHeader = (CSmStackHeader *) m_pbBase;
+ m_pbBase += sizeof(CSmStackHeader);
+
+ SYNC_BASE_POINTER();
+ }
+
+ }
+
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmStackAllocator::Alloc, public
+//
+// Synopsis: Allocate a block of memory from the stack
+//
+// Arguments: [cbSize] - the size of the block to allocate
+//
+// Returns: a pointer to the block allocated
+// NULL if failed to allocate
+//
+// History: 19-Jun-95 t-stevan Created
+//
+// Remarks: The pointer returned is not a based pointer, it is absolute.
+// Use the macro P_TO_BP() to convert if you want a based pointer
+//
+//----------------------------------------------------------------------------
+void *CSmStackAllocator::Alloc(ULONG cbSize)
+{
+ void *pResult = NULL;
+
+ SETUP_BASE_POINTER();
+
+ Win4Assert((m_pHeader != NULL) && (m_pbBase != NULL)
+ && "Stack memory block not initialized.");
+
+ if(cbSize > 0) // cbSize <= 0 means noop
+ {
+ if(!m_smb.IsSynced()) // First make sure we are synced up
+ {
+ m_smb.Sync();
+ }
+
+#if !defined(_M_IX86)
+ // we worry about alignment on non-x86 machines
+ // we align allocations on DWORD boundaries
+ // round to nearest multiple of 4
+ cbSize += 3;
+ cbSize &= 0xfffffffc;
+#endif
+
+ if(m_cbSize <= (m_pHeader->m_ulStack+sizeof(CSmStackHeader)+cbSize))
+ {
+ ULONG ulCommit; // We need to commit more memory
+ SYSTEM_INFO sysInfo;
+
+ GetSystemInfo(&sysInfo);
+
+ // Compute the total committed amount
+ ulCommit = m_cbSize+m_smb.GetHdrSize()+cbSize+sysInfo.dwPageSize-1;
+
+ // Round to the page size
+ ulCommit -= ulCommit%sysInfo.dwPageSize;
+
+ // account for smb header
+ ulCommit -= m_smb.GetHdrSize();
+
+ if(FAILED(m_smb.Commit(ulCommit))) // commit memory
+ {
+ return NULL;
+ }
+
+ if(FAILED(Sync())) // sync up again
+ {
+ return NULL;
+ }
+ }
+
+ // Get return address
+ pResult = BP_TO_P(BYTE *, (BYTE STACKBASED *)(m_pHeader->m_ulStack));
+
+ m_pHeader->m_ulStack += cbSize; // increment stack pointer
+ }
+
+ return pResult;
+}
+
diff --git a/private/ole32/com/inc/smstack.hxx b/private/ole32/com/inc/smstack.hxx
new file mode 100644
index 000000000..b02df4c91
--- /dev/null
+++ b/private/ole32/com/inc/smstack.hxx
@@ -0,0 +1,290 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: smstack.hxx
+//
+// Contents: Shared mem stack-based allocator header
+//
+// Classes: CSmStackAllocator
+//
+// Remarks: Shared memory stack is NOT thread-synchronized -> callers responsibility!
+//
+// History: 19-Jun-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __SMSTACK_HXX__
+#define __SMSTACK_HXX__
+
+#include <smblock.hxx>
+#include <memdebug.hxx>
+#include <smbasep.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSmStackHeader
+//
+// Purpose: Stack header at beginning of shared block
+//
+// History: 19-Jun-95 t-stevan Created
+//
+// Remarks: Note that all pointers in the header are based
+//
+//----------------------------------------------------------------------------
+class CSmStackHeader
+{
+ public:
+ ULONG m_ulStack; // offset of stack pointer into stack
+#if DBG == 1
+ ULONG m_cbLostBytes; // the number of bytes lost because an allocation create a fragment to small
+ // to keep (i.e. not enough space to hold a CSmStackBlockHeader)
+#endif
+};
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSmStackAllocator
+//
+// Purpose: Shared stack-based allocator implementation
+// NOTE: stack grows up
+//
+// History: 19-Jun-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+class CSmStackAllocator
+{
+ public:
+ inline CSmStackAllocator();
+ inline ~CSmStackAllocator();
+
+ HRESULT Init(LPWSTR pszName, ULONG cbMaxSize, ULONG cbInitSize);
+
+ void *Alloc(ULONG cb);
+
+ void Free(void *, ULONG) {}; // free is a no-op
+
+ inline void Reset(); // reset the stack
+
+ inline int DidAlloc(void *pvMem) const;
+
+ inline HRESULT Sync();
+
+ inline void *GetBase() const;
+
+ inline ULONG GetSize() const;
+
+ inline BOOL Created();
+
+ inline ULONG GetHeaderSize() const
+ { return sizeof(CSmStackHeader); }
+
+#if DBG == 1
+ inline ULONG GetCommitted() const;
+
+ ULONG GetLostBytes() const
+ { return m_pHeader->m_cbLostBytes; }
+
+#endif
+
+ private:
+ CSharedMemoryBlock m_smb;
+ CSmStackHeader *m_pHeader;
+ BYTE *m_pbBase;
+ ULONG m_cbSize;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmStackAllocator::CSmStackAllocator, public
+//
+// Synopsis: Constructor
+//
+// History: 19-Jun-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+inline CSmStackAllocator::CSmStackAllocator()
+ : m_pbBase(NULL), m_pHeader(NULL), m_cbSize(0)
+{
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmStackAllocator::~CSmStackAllocator, public
+//
+// Synopsis: Destructor
+//
+// History: 19-Jun-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+inline CSmStackAllocator::~CSmStackAllocator()
+{
+ // other destructors take care of everything
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmStackAllocator::DidAlloc, public
+//
+// Synopsis: Determine if a pointer is within the stack
+// Note: this doesn't necessarily mean that pointer
+// points to the start of an allocation
+//
+// Arguments: [pvMem] - a pointer to the memory to determine
+//
+// Returns: 1 if we the pointer falls within the stack
+// 0 if it is outside the stack
+//
+// History: 19-Jun-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+inline int CSmStackAllocator::DidAlloc(void *pvMem) const
+{
+ if((pvMem < m_pbBase)
+ || (pvMem >= (void *) (((BYTE *)m_pbBase)+m_pHeader->m_ulStack+sizeof(CSmStackHeader))))
+ {
+ return 0;
+ }
+
+ return 1;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmStackAllocator::Sync, public
+//
+// Synopsis: Sync memory to global state
+//
+// Returns: Appropriate HRESULT.
+//
+// History: 19-Jun-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+inline HRESULT CSmStackAllocator::Sync()
+{
+ if(!m_smb.IsSynced())
+ {
+ m_smb.Sync();
+ }
+
+ m_cbSize = m_smb.GetSize();
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmStackAllocator::GetBase, public
+//
+// Synopsis: Get base pointer of memory block
+//
+// Returns: Pointer to the base of the memory block the stack is allocated
+// from
+//
+// Note: Note that the first allocated element is always 4 bytes after this
+// so that we still have NULL
+//
+// History: 19-Jun-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+inline void *CSmStackAllocator::GetBase() const
+{
+ return m_pbBase;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmStackAllocator::Created, public
+//
+// Synopsis: Determine if we created the stack
+//
+// Returns: TRUE if we did
+// FALSE otherwise
+//
+// History: 19-Jun-95 t-stevan Created
+//
+//---------------------------------------------------------------------------
+inline BOOL CSmStackAllocator::Created()
+{
+ return m_smb.Created();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmStackAllocator::GetSize, public
+//
+// Synopsis: Get the number of bytes used in table
+//
+// Arguments: none
+//
+// Returns: the number of bytes allocated
+//
+// History: 27-Jun-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+ULONG CSmStackAllocator::GetSize() const
+{
+ return m_pHeader->m_ulStack-4;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmStackAllocator::Reset, public
+//
+// Synopsis: Reset the stack to its initial state
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: 03-Jul-95 t-stevan Created
+//
+// Note: Reset() does not uncommit already committed pages
+//
+//----------------------------------------------------------------------------
+void CSmStackAllocator::Reset()
+{
+ Win4Assert(m_pHeader != NULL);
+
+ m_pHeader->m_ulStack = 4;
+
+#if DBG == 1
+ m_pHeader->m_cbLostBytes = 0;
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmStackAllocator::GetNumPages, public, debug only
+//
+// Synopsis: Returns the number of pages allocated to the stack
+//
+// Returns: the number of pages allocated
+//
+// History: 27-Jun-95 t-stevan Created
+//
+//---------------------------------------------------------------------------
+#if DBG == 1
+inline ULONG CSmStackAllocator::GetCommitted() const
+{
+ MEMORY_BASIC_INFORMATION memInfo;
+
+ if(VirtualQuery(m_pbBase, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) != sizeof(MEMORY_BASIC_INFORMATION))
+ {
+ SYSTEM_INFO sysInfo;
+
+ GetSystemInfo(&sysInfo);
+ CairoleDebugOut((DEB_IWARN, "CSmStackAllocator: Couldn't get debug information on stack memory\n"));
+ // we can make a stab at it
+ return ((m_cbSize+(sysInfo.dwPageSize-1))/sysInfo.dwPageSize)*sysInfo.dwPageSize;
+ }
+
+ return memInfo.RegionSize;
+
+}
+#endif
+
+#endif // __SMSTACK_HXX__
+
diff --git a/private/ole32/com/inc/sources.inc b/private/ole32/com/inc/sources.inc
new file mode 100644
index 000000000..ef716da8c
--- /dev/null
+++ b/private/ole32/com/inc/sources.inc
@@ -0,0 +1,2 @@
+SYNCHRONIZE_BLOCK=1
+SYNCHRONIZE_DRAIN=1
diff --git a/private/ole32/com/inc/thread.hxx b/private/ole32/com/inc/thread.hxx
new file mode 100644
index 000000000..c160b2cff
--- /dev/null
+++ b/private/ole32/com/inc/thread.hxx
@@ -0,0 +1,175 @@
+//+---------------------------------------------------------------------------
+//
+// File: THREAD.HXX
+//
+// Contents: Windows Thread
+//
+// Classes: CThread
+//
+// History: 27-Feb-92 BartoszM Created
+//
+// Notes: Thread object
+//----------------------------------------------------------------------------
+
+#ifndef __THREAD_HXX__
+#define __THREAD_HXX__
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CThread
+//
+// Purpose: Encapsulation of thread
+//
+// History: 27-Feb-92 BartoszM Created
+//
+//----------------------------------------------------------------------------
+
+class CThread
+{
+public:
+ CThread(
+ DWORD (WINAPI *pFun)(void*),
+ void* obj,
+ HRESULT& hr,
+ BOOL fSuspend=FALSE);
+
+ ~CThread(void);
+
+ HRESULT SetPriority(int nPriority);
+
+ DWORD Suspend(HRESULT& hr);
+
+ DWORD Resume(HRESULT& hr);
+
+ HRESULT WaitForDeath(DWORD dwMilliseconds = 0xFFFFFFFF);
+
+private:
+
+ HANDLE _handle;
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThread::CThread
+//
+// Synopsis: Creates a new thread
+//
+// Arguments: [pFun] -- entry point
+// [obj] -- pointer passed to thread
+// [fSuspend] -- start suspended
+//
+// History: 27-Feb-92 BartoszM Created
+//
+//----------------------------------------------------------------------------
+
+inline CThread::CThread(
+ DWORD (WINAPI *pFun)(void*),
+ void* obj,
+ HRESULT& hr,
+ BOOL fSuspend)
+{
+ ULONG tid;
+
+ _handle = CreateThread(
+ 0, 0, pFun, obj, fSuspend? CREATE_SUSPENDED: 0, &tid);
+
+ hr = (_handle != NULL) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThread::~CThread
+//
+// Synopsis: Closes the handle
+//
+// History: 10-Nov-92 BartoszM Created
+//
+//----------------------------------------------------------------------------
+
+inline CThread::~CThread ()
+{
+ TerminateThread( _handle, 0 );
+ WaitForDeath();
+ CloseHandle ( _handle );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThread::SetPriority
+//
+// Arguments: [nPriority] -- desired priority
+//
+// History: 27-Feb-92 BartoszM Created
+//
+//----------------------------------------------------------------------------
+
+inline HRESULT CThread::SetPriority ( int nPriority )
+{
+ return SetThreadPriority (_handle, nPriority)
+ ? S_OK : HRESULT_FROM_WIN32(GetLastError());
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThread::Suspend
+//
+// Synopsis: Increments suspension count. Suspends the thread.
+//
+// Returns: suspended count
+//
+// History: 27-Feb-92 BartoszM Created
+//
+//----------------------------------------------------------------------------
+
+inline DWORD CThread::Suspend(HRESULT& hr)
+{
+ DWORD susCount = SuspendThread(_handle);
+
+ hr = (susCount != -1) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
+
+ return(susCount);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThread::Resume
+//
+// Synopsis: Decrements suspension count. Restarts if zero
+//
+// Returns: suspended count
+//
+// History: 27-Feb-92 BartoszM Created
+//
+//----------------------------------------------------------------------------
+
+inline DWORD CThread::Resume(HRESULT& hr)
+{
+ DWORD susCount = ResumeThread ( _handle );
+
+ hr = (susCount != -1) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
+
+ return(susCount);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThread::WaitForDeath
+//
+// Synopsis: Block until thread dies.
+//
+// History: 24-Apr-92 Kyleap Created
+//
+//----------------------------------------------------------------------------
+
+inline HRESULT CThread::WaitForDeath( DWORD msec )
+{
+ DWORD res = WaitForSingleObject ( _handle, msec );
+
+ return (res >= 0) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
+}
+
+
+#endif
diff --git a/private/ole32/com/inc/tracelog.hxx b/private/ole32/com/inc/tracelog.hxx
new file mode 100644
index 000000000..dc69a0804
--- /dev/null
+++ b/private/ole32/com/inc/tracelog.hxx
@@ -0,0 +1,181 @@
+//+-------------------------------------------------------------------
+//
+// File: tracelog.hxx
+//
+// Contents: trace log definitions
+//
+// Classes: CTraceLog - class for logging traces
+// CTraceCall - class for logging one function call
+//
+// Functions: none
+//
+// History: 23-Aug-93 Rickhi Created
+//
+// Notes: The trace log is used to record call information in a
+// process global ring buffer. The information can be used
+// to assist debugging, by allowing you to see what events
+// have taken place that lead up to some problem, and also
+// to provide profiling the CairOLE subsystem.
+//
+//--------------------------------------------------------------------
+
+#ifndef __TRACELOG_HXX__
+#define __TRACELOG_HXX__
+
+#ifdef TRACELOG
+
+#include <memapi.hxx>
+#include <sem.hxx>
+#include <except.hxx>
+
+
+// structure to define an entry in the trace log. note that it stores
+// only a ptr to the message, not the whole message. the message is
+// allocated as a static character string via the tracing macros below.
+
+typedef struct tagSTraceEntry
+{
+ LARGE_INTEGER liCurrTime; // current time
+ LARGE_INTEGER liStartTime; // time entry was started
+ DWORD dwThreadId; // low = thread id
+ DWORD dwFlags; // trace flag
+ ULONG ulLevel; // call level
+ CHAR *pszMsg; // ptr to message
+ BOOL fExit; // call entry/exit direction
+} STraceEntry;
+
+
+
+//------------------------------------------------------------------------
+//
+// class: CTraceLog
+//
+// synopsis: class to define the trace log.
+//
+//------------------------------------------------------------------------
+
+class CTraceLog : public CPrivAlloc
+{
+public:
+ CTraceLog(void); // constructor
+ ~CTraceLog(void); // destructor
+
+ void TraceEntry(DWORD dwFlags, // record entry in the log
+ CHAR *pszMsg,
+ DWORD dwThreadId,
+ LARGE_INTEGER liCurrTime,
+ LARGE_INTEGER liStartTime);
+
+ void LogToFile(void); // copy log to a file
+ void LogToDebug(void); // copy log to debug screen
+ void StartTrace(LPSTR pszMsg); // start log tracing
+ void StopTrace(LPSTR pszMsg); // stop tracing.
+
+private:
+ LARGE_INTEGER PerfDelta(LARGE_INTEGER liNow, LARGE_INTEGER liStart);
+
+ LARGE_INTEGER _liStartTime; // time that logging was started.
+ ULONG _ulLevel; // current call trace level
+ DWORD _dwTraceFlag; // trace flags
+
+ STraceEntry *_pLogStart; // ptr to first entry in trace log
+ STraceEntry *_pLogCurr; // ptr to current entry in trace log
+ STraceEntry *_pLogEnd; // ptr to last entry in trace log
+
+ CMutexSem _mxs; // mutex to single thread log access
+ BOOL _fDump; // dump to file or not
+};
+
+
+//------------------------------------------------------------------------
+//
+// class: CTraceCall
+//
+// synopsis: class to trace one function call.
+//
+// notes: an instance of this class is placed on the stack at entry
+// to each function we want to trace or profile. the constructor
+// records the time the function was called, and the destructor
+// records the time the function was exited. both of these
+// generate an entry in the trace log.
+//
+// the dwFlag is ANDed with the sg_dwTraceFlags to determine if
+// we are interrested in tracing this call or not.
+//
+//------------------------------------------------------------------------
+
+class CTraceCall
+{
+public:
+ CTraceCall(DWORD dwFlag, CHAR *pszMsg); // constructor
+ ~CTraceCall(void); // destructor
+private:
+
+ LARGE_INTEGER _liStartTime; // time the call trace was started
+ CHAR *_pszMsg; // message
+ DWORD _dwThreadId; // thread id of running thread
+ DWORD _dwFlags; // trace flags
+ BOOL _fTrace; // TRUE = trace, FALSE = no trace
+};
+
+
+
+//------------------------------------------------------------------------
+//
+// macros: TRACECALL
+//
+// synopsis: macro used in procedure entry to initiate tracing the
+// function call. place a TRACECALL macro at the start of
+// each function you want to trace or profile.
+//
+//------------------------------------------------------------------------
+
+// flags used to select what events to trace and what events to ignore.
+// each flag selects one group of related activities. since the flag is
+// a dword, there is room to define up to 32 groups. note that if you add
+// a flag here, you should add the name of the flag to the MapFlagToName
+// function in tracelog.cxx also.
+
+typedef enum tagTRACEFLAGS
+{
+ TRACE_RPC = 1, // trace Rpc calls
+ TRACE_MARSHAL = 2, // trace interface marshalling
+ TRACE_ACTIVATION = 4, // trace object activation
+ TRACE_DLL = 8, // trace dll load/free
+ TRACE_REGISTRY = 16, // trace registry actions
+ TRACE_INITIALIZE = 32, // trace initialization
+ TRACE_CALLCONT = 64, // trace call control interface
+ TRACE_APP = 128 // trace application code
+} TRACEFLAGS;
+
+
+// APIs to start/stop trace logging
+
+STDAPI StartTrace(LPSTR pszMsg);
+STDAPI StopTrace(LPSTR pszMsg);
+
+
+// macro to construct a CTraceCall on the stack at procedure entry
+
+#define TRACECALL(dwFlag, pszMsg) CTraceCall trc(dwFlag, pszMsg);
+#define STARTTRACE(pszMsg) StartTrace(pszMsg);
+#define STOPTRACE(pszMsg) StopTrace(pszMsg);
+
+// global values that holds the user selected trace value. this can be
+// set either in the debugger, or through win.ini
+
+
+extern DWORD sg_dwTraceFlag;
+extern CTraceLog *sg_pTraceLog;
+
+
+#else // not TRACECALL
+
+#define TRACECALL(dwFlag, pszMsg)
+#define STARTTRACE(pszMsg)
+#define STOPTRACE(pszMsg)
+
+#endif // TRACECALL
+
+
+#endif // __TRACELOG_HXX__
diff --git a/private/ole32/com/inc/xmit.cxx b/private/ole32/com/inc/xmit.cxx
new file mode 100644
index 000000000..eee7174d7
--- /dev/null
+++ b/private/ole32/com/inc/xmit.cxx
@@ -0,0 +1,302 @@
+//+-------------------------------------------------------------------
+//
+// File: xmit.cxx
+//
+// Contents: code for converting interfaces to Rpc'able constructs.
+//
+// Classes: CXmitRpcStream
+//
+// Functions: None.
+//
+// Macros: DEFINE_INTERFACE_XMIT_ROUTINES
+//
+// History: 30-Jan-93 Ricksa Created
+//
+// Notes: Since cairo interfaces cant be Rpc'd, they get converted
+// into an InterfaceReferenceData structure via the Rpc
+// [transmit_as] attribute. The <IFace>_to_xmit function
+// and <IFace>_from_xmit function call CoMarshalInterface
+// and CoUnmarshalInterface respectively. These APIs expect
+// a stream interface as input. The CXmitRpcStream is a
+// stream wrapper for the InterfaceReferenceData structure.
+//
+// CODEWORK: since this is used only internally, we want it to be
+// screaming fast. check parameters only in DBG builds.
+// and ignore thread safety on AddRef/Release.
+//
+//--------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <xmit.hxx>
+
+
+
+
+STDMETHODIMP CXmitRpcStream::QueryInterface(
+ REFIID iidInterface,
+ void FAR* FAR* ppvObj)
+{
+ HRESULT hresult = S_OK;
+
+ // We only support IUnknown and IStream
+ if (IsEqualIID(iidInterface, IID_IUnknown) ||
+ IsEqualIID(iidInterface, IID_IStream))
+ {
+ *ppvObj = this;
+ AddRef();
+ }
+ else
+ {
+ *ppvObj = NULL;
+ hresult = E_NOINTERFACE;
+ }
+
+ return hresult;
+}
+
+STDMETHODIMP_(ULONG) CXmitRpcStream::AddRef(void)
+{
+ Win4Assert((_clRefs != 0) && "CXmitRpcStream::AddRef");
+ InterlockedIncrement(&_clRefs);
+ return _clRefs;
+}
+
+STDMETHODIMP_(ULONG) CXmitRpcStream::Release(void)
+{
+ Win4Assert((_clRefs != 0) && "CXmitRpcStream::Release");
+
+ if (InterlockedDecrement(&_clRefs) == 0)
+ {
+ delete this;
+ return 0;
+ }
+
+ return _clRefs;
+}
+
+STDMETHODIMP CXmitRpcStream::Read(
+ VOID HUGEP* pv,
+ ULONG cb,
+ ULONG FAR* pcbRead)
+{
+ HRESULT hresult = S_OK;
+
+ if (pcbRead)
+ {
+ *pcbRead = 0L;
+ }
+
+ if (cb + _lOffset > _cbData)
+ {
+ cb = _cbData - _lOffset;
+ CairoleDebugOut((DEB_ERROR, "CXmitRpcStream read past end of stream %x\n", cb+_lOffset));
+ hresult = STG_E_READFAULT;
+ }
+
+ memcpy(pv,_pifData->abData + _lOffset, (size_t) cb);
+ _lOffset += cb;
+
+ if (pcbRead != NULL)
+ {
+ *pcbRead = cb;
+ }
+
+ return hresult;
+}
+
+STDMETHODIMP CXmitRpcStream::Write(
+ VOID const HUGEP* pv,
+ ULONG cbToWrite,
+ ULONG FAR* pcbWritten)
+{
+ HRESULT hresult = S_OK;
+
+ if (pcbWritten)
+ {
+ *pcbWritten = 0L;
+ }
+
+ if (cbToWrite + _lOffset > _cbData)
+ {
+ // the current stream is too small, try to grow it.
+
+ if (!_fFree)
+ {
+ // The stream doesn't own the buffer so it can't reallocate it
+ CairoleDebugOut((DEB_ERROR, "CXmitRpcStream write past end of stream %x\n",
+ cbToWrite + _lOffset));
+ return STG_E_WRITEFAULT;
+ }
+
+ // Reallocate the size of the buffer
+ // BUGBUG: The constant added to the size allocated is a number
+ // designed simply to try and decrease the number of follow on
+ // allocations. In other words it needs to be tuned (or dropped!).
+
+ BYTE *pbNewBuf = (BYTE *) MyMemAlloc(sizeof(DWORD) +
+ cbToWrite +
+ _lOffset + 64);
+
+ if (pbNewBuf == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR, "CXmitRpcStream cant grow stream\n"));
+ return E_OUTOFMEMORY;
+ }
+
+ if (_pifData)
+ {
+ // we had a buffer from before, copy that in, and free the old one.
+ memcpy(pbNewBuf, _pifData, sizeof(DWORD) + _cbData);
+ MyMemFree(_pifData);
+ }
+
+ _cbData = cbToWrite + _lOffset + 64;
+ _pifData = (InterfaceData *)pbNewBuf;
+ }
+
+
+ // copy in the new data
+ memcpy(_pifData->abData + _lOffset, pv, (size_t) cbToWrite);
+ _lOffset += cbToWrite;
+
+ if (pcbWritten != NULL)
+ {
+ *pcbWritten = cbToWrite;
+ }
+
+ // We assume maxium size of buffer is the size to send on the network.
+ if (_cSize < _lOffset)
+ {
+ _cSize = _lOffset;
+ }
+
+ return hresult;
+}
+
+STDMETHODIMP CXmitRpcStream::Seek(
+ LARGE_INTEGER dlibMoveIN,
+ DWORD dwOrigin,
+ ULARGE_INTEGER FAR* plibNewPosition)
+{
+ HRESULT hresult = S_OK;
+
+#ifdef BUGBUG
+can't use this code until the stuff in ole2pr32.dll is fixed.
+
+ // check against -2^31-1 <= x <= 2^31-1
+ if (dlibMoveIN.HighPart == 0 && dlibMoveIN.LowPart < 0x80000000)
+ // positive 31 bit value
+ ;
+ else if (dlibMoveIN.HighPart == -1L && dlibMoveIN.LowPart >= 0x80000000)
+ // negative 31 bit value
+ ;
+ else
+ return STG_E_SEEKERROR;
+#endif
+
+ LONG dlibMove = dlibMoveIN.LowPart;
+ ULONG cbNewPos = dlibMove;
+
+ switch(dwOrigin)
+ {
+ case STREAM_SEEK_SET:
+
+ if (dlibMove >= 0)
+ {
+ _lOffset = dlibMove;
+ }
+ else
+ {
+ hresult = STG_E_SEEKERROR;
+ }
+ break;
+
+ case STREAM_SEEK_CUR:
+
+ if (!(dlibMove < 0 && (-dlibMove > _lOffset)))
+ {
+ _lOffset += (ULONG) dlibMove;
+ }
+ else
+ {
+ hresult = STG_E_SEEKERROR;
+ }
+ break;
+
+ case STREAM_SEEK_END:
+
+ if (!(dlibMove < 0 && ((ULONG) -dlibMove) > _cbData))
+ {
+ _lOffset = _cbData + dlibMove;
+ }
+ else
+ {
+ hresult = STG_E_SEEKERROR;
+ }
+ break;
+
+ default:
+
+ hresult = STG_E_SEEKERROR;
+ }
+
+ if (plibNewPosition != NULL)
+ {
+ ULISet32(*plibNewPosition, _lOffset);
+ }
+
+ return hresult;
+}
+
+STDMETHODIMP CXmitRpcStream::SetSize(ULARGE_INTEGER cb)
+{
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CXmitRpcStream::CopyTo(
+ IStream FAR* pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER FAR* pcbRead,
+ ULARGE_INTEGER FAR* pcbWritten)
+{
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CXmitRpcStream::Commit(DWORD grfCommitFlags)
+{
+ return NOERROR;
+}
+
+STDMETHODIMP CXmitRpcStream::Revert(void)
+{
+ return NOERROR;
+}
+
+STDMETHODIMP CXmitRpcStream::LockRegion(
+ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+STDMETHODIMP CXmitRpcStream::UnlockRegion(
+ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+STDMETHODIMP CXmitRpcStream::Stat(
+ STATSTG FAR* pstatstg,
+ DWORD statflag)
+{
+ memset(pstatstg, 0, sizeof(STATSTG));
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CXmitRpcStream::Clone(IStream FAR * FAR *ppstm)
+{
+ return E_NOTIMPL;
+}
diff --git a/private/ole32/com/inc/xmit.hxx b/private/ole32/com/inc/xmit.hxx
new file mode 100644
index 000000000..6901af491
--- /dev/null
+++ b/private/ole32/com/inc/xmit.hxx
@@ -0,0 +1,180 @@
+//+-------------------------------------------------------------------
+//
+// File: xmit.hxx
+//
+// Contents: definition of class for converting interfaces to Rpc'able
+// constructs.
+//
+// Classes: CXmitRpcStream
+//
+// Functions: None.
+//
+// History: 30-Jan-93 Ricksa Created
+//
+// Notes: Since cairo interfaces cant be Rpc'd, they get converted
+// into an InterfaceReferenceData structure via the Rpc
+// [transmit_as] attribute. The <IFace>_to_xmit function
+// and <IFace>_from_xmit function call CoMarshalInterface
+// and CoUnmarshalInterface respectively. These APIs expect
+// a stream interface as input. The CXmitRpcStream is a
+// stream wrapper for the InterfaceReferenceData structure.
+//
+//--------------------------------------------------------------------
+
+#ifndef __XMITRPC_HXX__
+#define __XMITRPC_HXX__
+
+
+// BUGBUG: for some unknown reason PrivMemAlloc on Cairo is different than
+// other platforms. When we fix that, these defines can go away and we can
+// just use MIDL_user_alloc.
+
+#ifdef DCOM
+#define MyMemAlloc(cb) CoTaskMemAlloc(cb)
+#define MyMemFree(pv) CoTaskMemFree(pv)
+#else
+#define MyMemAlloc(cb) MIDL_user_allocate(cb)
+#define MyMemFree(pv) MIDL_user_free(pv)
+#endif
+
+
+
+#include <iface.h> // InterfaceData
+
+//+-------------------------------------------------------------------
+//
+// Class: CXmitRpcStream
+//
+// Purpose: Stream wrapper for an InterfaceData structure,
+// the construct that is transmitted by Rpc in place of an
+// interface pointer.
+//
+// History: 30-Jan-93 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+class CXmitRpcStream : public IStream
+{
+public:
+ CXmitRpcStream(void);
+
+ CXmitRpcStream(ULONG ulMaxSize);
+
+ CXmitRpcStream(InterfaceData *pOIR);
+
+ ~CXmitRpcStream(void);
+
+ STDMETHOD(QueryInterface)(
+ REFIID iidInterface,
+ void FAR* FAR* ppvObj);
+
+ STDMETHOD_(ULONG,AddRef)(void);
+
+ STDMETHOD_(ULONG,Release)(void);
+
+ STDMETHOD(Read)(
+ VOID HUGEP* pv,
+ ULONG cb,
+ ULONG FAR* pcbRead);
+
+ STDMETHOD(Write)(
+ VOID const HUGEP* pv,
+ ULONG cb,
+ ULONG FAR* pcbWritten);
+
+ STDMETHOD(Seek)(
+ LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER FAR* plibNewPosition);
+
+ STDMETHOD(SetSize) (ULARGE_INTEGER cb);
+
+ STDMETHOD(CopyTo)(
+ IStream FAR* pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER FAR* pcbRead,
+ ULARGE_INTEGER FAR* pcbWritten);
+
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+
+ STDMETHOD(Revert)(void);
+
+ STDMETHOD(LockRegion)(
+ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+
+ STDMETHOD(UnlockRegion)(
+ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+
+ STDMETHOD(Stat)(
+ STATSTG FAR* pstatstg,
+ DWORD statflag);
+
+ STDMETHOD(Clone)(IStream FAR * FAR *ppstm);
+
+ void AssignSerializedInterface(InterfaceData **ppIFD);
+
+
+private:
+
+ LONG _clRefs; // reference count
+ LONG _lOffset; // current ptr
+ LONG _cSize; // number of bytes written
+ ULONG _cbData; // size of data
+ InterfaceData *_pifData; // ptr to data
+ BOOL _fFree; // TRUE - destructor frees data
+};
+
+
+inline CXmitRpcStream::CXmitRpcStream(void)
+ : _clRefs(1), _lOffset(0), _cSize(0), _pifData(NULL), _cbData(0),
+ _fFree(TRUE)
+{
+ _pifData = (InterfaceData *) MyMemAlloc(sizeof(DWORD) + 512);
+ _cbData = _pifData == NULL ? 0 : 512;
+}
+
+inline CXmitRpcStream::CXmitRpcStream(ULONG ulMaxSize)
+ : _clRefs(1), _lOffset(0), _cSize(0), _pifData(NULL), _cbData(0),
+ _fFree(TRUE)
+{
+ _pifData = (InterfaceData *) MyMemAlloc(sizeof(DWORD) + ulMaxSize);
+ _cbData = _pifData == NULL ? 0 : ulMaxSize;
+}
+
+inline CXmitRpcStream::CXmitRpcStream(InterfaceData *pIFD)
+ : _clRefs(1), _lOffset(0), _cSize(0), _pifData(pIFD),
+ _fFree(FALSE)
+{
+ _cbData = _pifData == NULL ? 0 : pIFD->ulCntData;
+}
+
+inline CXmitRpcStream::~CXmitRpcStream(void)
+{
+ if (_fFree)
+ {
+ MyMemFree(_pifData);
+ }
+}
+
+inline void CXmitRpcStream::AssignSerializedInterface(InterfaceData **ppIFD)
+{
+ // Offset of next byte to be written is assumed
+ // to be size of the buffer since all writing s/b
+ // sequential.
+
+ *ppIFD = _pifData;
+ (*ppIFD)->ulCntData = _cSize;
+
+ // Tell destructor not to free this buffer as some one
+ // else owns the destruction now.
+ _fFree = FALSE;
+}
+
+
+#endif // __XMITRPC_HXX__
diff --git a/private/ole32/com/inc/xstring.cxx b/private/ole32/com/inc/xstring.cxx
new file mode 100644
index 000000000..9e2e3a198
--- /dev/null
+++ b/private/ole32/com/inc/xstring.cxx
@@ -0,0 +1,184 @@
+//+-------------------------------------------------------------------------
+//
+// Copyright (C) 1992, Microsoft Corporation.
+//
+// File: xstring.cxx
+//
+// Contents: Member functions for XString class
+//
+// Classes: XString
+//
+// History: 01-Dec-92 MikeSe Created
+// 13-Oct-92 Ricksa Ported to cairole & deleted exceptions
+//
+//--------------------------------------------------------------------------
+
+#include <xstring.hxx>
+
+static WCHAR awszEmpty[] = L"";
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: XString::XString, public
+//
+// Synopsis: Constructor, no arguments
+//
+// History: 1-Dec-92 MikeSe Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+EXPORTIMP
+XString::XString ( ) :_pwsz(NULL)
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: XString::XString, public
+//
+// Synopsis: Constructor, taking a length argument
+//
+// Arguments: [cNewStr] -- size to allocate
+//
+// Signals: Exception from heap allocation failure
+//
+// History: 1-Dec-92 MikeSe Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+EXPORTIMP
+XString::XString ( ULONG cNewStr ) :_pwsz(NULL)
+{
+ _pwsz = new WCHAR [cNewStr];
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: XString::XString, public
+//
+// Synopsis: Constructor, taking a single string argument
+//
+// Arguments: [pwsz] -- string to store
+//
+// Signals: Exception from heap allocation failure
+//
+// History: 1-Dec-92 MikeSe Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+EXPORTIMP
+XString::XString ( WCHAR const * pwsz ) :_pwsz(NULL)
+{
+ if ( pwsz != NULL )
+ {
+ _pwsz = new WCHAR [lstrlenW(pwsz) + 1];
+ lstrcpyW ( _pwsz, pwsz );
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: XString::XString, public
+//
+// Synopsis: Constructor, taking two string arguments
+//
+// Arguments: [pwsz1] -- first string to store
+// [pwsz2] -- second string, to be concatenated with first
+//
+// Signals: Exception from heap allocation failure
+//
+// History: 1-Dec-92 MikeSe Created
+//
+// Notes: This function converts NULL pointers to a null string.
+// This saves having to check for NULL elsewhere.
+//
+//--------------------------------------------------------------------------
+
+EXPORTIMP
+XString::XString ( WCHAR const * pwsz1, WCHAR const * pwsz2 )
+{
+ if ( pwsz1 == NULL )
+ pwsz1 = awszEmpty;
+
+ if ( pwsz2 == NULL )
+ pwsz2 = awszEmpty;
+
+ ULONG len = lstrlenW ( pwsz1 ) + lstrlenW ( pwsz2 ) + 1;
+ _pwsz = new WCHAR [len];
+ lstrcpyW ( _pwsz, pwsz1 );
+ lstrcatW ( _pwsz, pwsz2 );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: XString::XString, public
+//
+// Synopsis: Constructor, taking a single DBCS string argument,
+// incorporating conversion to wide char using current locale.
+//
+// Arguments: [psz] -- string to store
+//
+// Signals: Exception from heap allocation failure
+//
+// History: 1-Dec-92 MikeSe Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+EXPORTIMP
+XString::XString ( CHAR const * psz ) :_pwsz(NULL)
+{
+ if ( psz != NULL )
+ {
+ ULONG len = strlen ( psz ) + 1;
+ _pwsz = new WCHAR [len];
+ MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, psz, -1, _pwsz, len);
+ }
+}
+
+EXPORTIMP XString&
+XString::operator= ( WCHAR const *pwsz )
+{
+ delete _pwsz;
+
+ if ( pwsz == NULL )
+ {
+ _pwsz = NULL;
+ }
+ else
+ {
+ _pwsz = new WCHAR [lstrlenW(pwsz)+1];
+ lstrcpyW ( _pwsz, pwsz );
+ }
+
+ return *this;
+}
+
+//-----------------------------------------------------------------------------
+//
+// Member: XString::operator&
+//
+// Synopsis: Returns the address of the _pwsz member so that a WCHAR * can be
+// transferred to the XString
+//
+// History: 31-Mar-1993 KirtD Created
+//
+// Notes: PLEASE USE WITH CARE, see declaration in xstring.hxx
+//
+//-----------------------------------------------------------------------------
+EXPORTIMP WCHAR **
+XString::operator& ()
+{
+ delete _pwsz;
+ _pwsz = NULL;
+
+ return(&_pwsz);
+}
diff --git a/private/ole32/com/moniker/cmonimp.h b/private/ole32/com/moniker/cmonimp.h
new file mode 100644
index 000000000..b6d76fffe
--- /dev/null
+++ b/private/ole32/com/moniker/cmonimp.h
@@ -0,0 +1,730 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: cmonimp.h
+//
+// Contents: Defines of classes used in the implementation of monikers.
+//
+// Classes:
+// CBaseMoniker base moniker implementation. Other derive from base.
+// CFileMoniker file moniker implementation.
+// CItemMoniker item moniker
+// CCompositeMoniker generic composite moniker
+// CAntiMoniker
+//
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 22-Mar-93 Randyd Modified for Cairole
+//
+//--------------------------------------------------------------------------
+
+
+#if !defined( _CMONIMP_H_ )
+#define _CMONIMP_H_
+
+// Define NEW_ENUMERATOR to get enumerations that don't include delimiters.
+// (e.g. c:\d1\d2\f1.ext => c: \ d1 d2 f1.ext)
+// Old enumerations include delimiters.
+// (e.g. c:\d1\d2\f1.ext => c: \ d1\ d2\ f1.ext)
+#define NEW_ENUMERATOR
+
+
+#include "map_sp.h"
+#include <dfsapi.h>
+#include <filemon.hxx>
+#include <dfspath.hxx>
+
+
+#ifdef _DEBUG
+#define CONSTR_DEBUG : m_Debug(this)
+#else
+#define CONSTR_DEBUG
+#endif
+
+
+#define PATH_DELIMITER L"\\"
+#define WCHAR_BACKSLASH L'\\'
+#define WCHAR_FWDSLASH L'/'
+#define IS_PATH_SEPARATOR_OLE(ch) ((ch == WCHAR_BACKSLASH) || (ch == WCHAR_FWDSLASH) || (ch == UNICODE_NULL))
+#define IS_PATH_SEPARATOR_STRICT(ch) ((ch == WCHAR_BACKSLASH) || (ch == WCHAR_FWDSLASH))
+
+
+
+
+STDAPI CreateOle1FileMoniker( LPTSTR, REFCLSID, LPMONIKER FAR*);
+
+
+/*
+ * An implementation of the IMarshal interface that uses the
+ * IPersistStream interface to copy the object. Any object that
+ * supports IPersistStream may use this to implement marshalling
+ * by copying, rather than by reference.
+ */
+
+class FAR CMarshalImplPStream : public IMarshal
+{
+ LPPERSISTSTREAM m_pPS;
+ SET_A5;
+public:
+ CMarshalImplPStream( LPPERSISTSTREAM pPS );
+
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ // *** IMarshal methods ***
+ STDMETHOD(GetUnmarshalClass)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(THIS_ IStream FAR* pStm, REFIID riid,
+ LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(THIS_ IStream FAR* pStm, REFIID riid,
+ LPVOID FAR* ppv);
+ STDMETHOD(ReleaseMarshalData)(THIS_ IStream FAR* pStm);
+ STDMETHOD(DisconnectObject)(THIS_ DWORD dwReserved);
+};
+
+
+
+class FAR CBaseMoniker : public IMoniker
+/*
+ * CBaseMoniker is a base implementation class that does the
+ * following:
+ *
+ * 1. It implements QueryInterface, AddRef, and Release, and IsDirty,
+ * since these all have the same implementation for all the moniker
+ * classes defined here.
+ *
+ * 2. It returns error messages for other methods. Normally
+ * these will be replaced by real implementations in the
+ * derived classes, but in some cases, AntiMonikers, for
+ * instance, it allows us to declare and write only those
+ * methods with meaningful implementations. Methods such as
+ * BindToObject for antimonikers will inherit the error code
+ * form the base implementation.
+ */
+
+{
+protected:
+ CBaseMoniker(void) : m_marshal(this)
+ { //SETPVTBL(CBaseMoniker);
+ GET_A5();
+ m_refs = 0;
+ }
+
+public:
+
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID);
+
+ // *** IPersistStream methods ***
+ STDMETHOD(IsDirty) (THIS);
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm);
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty);
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR * pcbSize);
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID FAR* ppvResult);
+ STDMETHOD(BindToStorage) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD(Reduce) (THIS_ LPBC pbc, DWORD dwReduceHowFar, LPMONIKER FAR*
+ ppmkToLeft, LPMONIKER FAR * ppmkReduced);
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNotGeneric,
+ LPMONIKER FAR* ppmkComposite);
+ STDMETHOD(Enum) (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker);
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker);
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash);
+ STDMETHOD(IsRunning) (THIS_ LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+ pmkNewlyRunning);
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime);
+ STDMETHOD(Inverse) (THIS_ LPMONIKER FAR* ppmk);
+ STDMETHOD(CommonPrefixWith) (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix);
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath);
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPTSTR FAR* lplpszDisplayName);
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPTSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut);
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys);
+ // REVIEW: we need the following method on monikers but it is not in
+ // the spec.
+ STDMETHOD(Clone) (THIS_ LPMONIKER FAR* ppmkDest, MemoryPlacement memPlace);
+ // "IInternalMoniker method"
+
+#if DBG == 1
+ // Debugging methods.
+ // Dump dumps the state of the moniker.
+ STDMETHOD_(void, Dump) (THIS_);
+#endif // DBG == 1
+
+ ULONG m_refs;
+
+ CMarshalImplPStream m_marshal;
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CFileMoniker
+//
+// Purpose: The standard Cairole implementation of a file moniker.
+//
+// Interface:
+//
+// History: dd-mmm-yy Author Comment
+// 26-Mar-93 randyd Converted to use DFS normalized paths
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class FAR CFileMoniker : public CBaseMoniker
+{
+public:
+ static CFileMoniker FAR* Create(
+ LPTSTR szPathName,
+ MemoryPlacement memLoc = TASK,
+ FILEMONIKERTYPE fmtType = defaultType,
+ DFS_ROOT dfsRoot = DFS_ROOT_ORG,
+ UINT cAnti = 0 );
+
+ private:
+
+ CFileMoniker( void );
+ ~CFileMoniker( void );
+ INTERNAL_(BOOL) Initialize(
+ UINT cAnti,
+ LPTSTR szPathName,
+ FILEMONIKERTYPE fmtType = defaultType,
+ DFS_ROOT dfsRoot = DFS_ROOT_ORG);
+
+ // Return the "total size" of this moniker, if serialized.
+ // BUGBUG: Need serialized form. INTERNAL_(ULONG) TotalSize();
+ INTERNAL_(BOOL) IsOle1Class( LPCLSID pclsid );
+
+ STDDEBDECL(CFileMoniker, FileMoniker)
+ implementations:
+
+ // *** IUnknown methods inherited from CBaseMoniker***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,Release) (THIS);
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID);
+ // *** IPersistStream methods ***
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm);
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty);
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR * pcbSize);
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID FAR* ppvResult);
+ STDMETHOD(BindToStorage) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNotGeneric,
+ LPMONIKER FAR* ppmkComposite);
+ STDMETHOD(Enum) (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker);
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker);
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash);
+ STDMETHOD(IsRunning) (THIS_ LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+ pmkNewlyRunning);
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime);
+ STDMETHOD(Inverse) (THIS_ LPMONIKER FAR* ppmk);
+ STDMETHOD(CommonPrefixWith) (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix);
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath);
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPTSTR FAR* lplpszDisplayName);
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPTSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut);
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys);
+ // REVIEW: we need the following method on monikers but it is not in
+ // the spec.
+ /*
+ * Since IMoniker::Clone is not in the spec, this is the
+ * documentation for it. It clones a moniker; it is needed since
+ * the tables (RunningObjectTable, e.g.) need a pointer to moniker
+ * that is valid in shared memory, which means monikers must be
+ * copied to shared memory.
+ *
+ * If *ppmkDest == NULL, an allocation is made using memLoc = TASK to
+ * decide whether it is allocated in shared memory or task memory.
+ * If *ppmkDest is not NULL, the moniker is copied into the same
+ * type of space as *ppmkDest. The pointer to the moniker is
+ * returned in *ppmkDest, and we guarantee that *ppmkDest does not
+ * change unless it started out as NULL.
+ */
+ STDMETHOD(Clone) (THIS_ LPMONIKER FAR* ppmkDest, MemoryPlacement memPlace);
+ // "IInternalMoniker method"
+
+#if DBG == 1
+ // Debugging methods.
+ STDMETHOD_(void, Dump) ();
+#endif // DBG == 1
+
+
+private:
+
+ // Comare m_cAnti counts of two monikers: return prefix.
+ HRESULT CompareAntiCount(CFileMoniker* pcfmOther,
+ IMoniker** ppmkPrefix);
+
+
+ shared_state:
+ // From cfilemon.cxx:
+ /*
+ * Storage of paths in file monikers:
+ *
+ * A separate unsigned integer holds the count of .. at the
+ * beginning of the path, so the canononical form of a file
+ * moniker contains this count and the "path" described above,
+ * which will not contain "..\" or ".\".
+ *
+ * It is considered an error for a path to contain ..\ anywhere
+ * but at the beginning. I assume that these will be taken out by
+ * ParseUserName.
+ */
+
+ // m_dfsPath is a DFS normalized path. It is the core of the
+ // activated state of a file moniker.
+ CDfsPath* m_CDfsPath;
+
+ // m_cAnti is a count: the number of leading ".."'s at the beginning
+ // of supplied path.
+ UINT m_cAnti;
+ CLSID m_clsid; // used only if OLE 1.0
+ enum olever { undetermined, ole1, ole2 };
+ olever m_ole1;
+ DWORD m_cbMacAlias;
+ TCHAR FAR * m_pchMacAlias;
+ BOOL m_fClassVerified;
+
+ friend class CFileMonikerEnum;
+ friend class CDfsMoniker;
+ friend class CDfsMonikerEnum;
+ friend class CCompositeMoniker;
+ friend BOOL RunningMoniker(LPBINDCTX,LPTSTR,ULONG FAR&,LPMONIKER FAR*);
+ friend
+ HRESULT STDAPICALLTYPE CreateOle1FileMoniker(LPTSTR, REFCLSID, LPMONIKER FAR*);
+};
+
+
+
+class FAR CItemMoniker : public CBaseMoniker
+{
+
+public:
+ static CItemMoniker FAR* Create( LPTSTR szDelim, LPTSTR szItemName,
+ MemoryPlacement memLoc = TASK );
+
+private:
+
+ CItemMoniker( void ) CONSTR_DEBUG
+ { //SETPVTBL(CItemMoniker); GET_A5();
+ m_lpszItem = NULL; m_lpszDelimiter = NULL; };
+ ~CItemMoniker( void );
+ INTERNAL_(BOOL) Initialize( LPTSTR szDelim, LPTSTR szItemName );
+ STDDEBDECL(CItemMoniker, ItemMoniker)
+
+public:
+ // *** IUnknown methods inherited from CBaseMoniker ***
+
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,Release) (THIS);
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID);
+
+ // *** IPersistStream methods ***
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm);
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty);
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR * pcbSize);
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID FAR* ppvResult);
+ STDMETHOD(BindToStorage) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNOtGeneric,
+ LPMONIKER FAR* ppmkComposite);
+ STDMETHOD(Enum) (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker);
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker);
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash);
+ STDMETHOD(IsRunning) (THIS_ LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+ pmkNewlyRunning);
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime);
+ STDMETHOD(Inverse) (THIS_ LPMONIKER FAR* ppmk);
+ STDMETHOD(CommonPrefixWith) (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix);
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath);
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPTSTR FAR* lplpszDisplayName);
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPTSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut);
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys);
+ // REVIEW: we need the following method on monikers but it is not in
+ // the spec.
+ STDMETHOD(Clone) (THIS_ LPMONIKER FAR* ppmkDest, MemoryPlacement memPlace);
+ // "IInternalMoniker method"
+
+ TCHAR FAR* m_lpszItem;
+shared_state:
+ TCHAR FAR* m_lpszDelimiter;
+ SET_A5;
+};
+
+
+
+class FAR CCompositeMoniker : public CBaseMoniker
+{
+
+public:
+ static CCompositeMoniker FAR* Create( LPMONIKER pmkFirst, LPMONIKER pmkRest,
+ MemoryPlacement memLoc = TASK );
+
+
+ CCompositeMoniker( void ) CONSTR_DEBUG
+ { // SETPVTBL(CCompositeMoniker); GET_A5();
+ m_pmkLeft = NULL; m_pmkRight = NULL; m_fReduced = FALSE;}
+ ~CCompositeMoniker( void );
+ INTERNAL_(BOOL) Initialize( LPMONIKER pmkFirst, LPMONIKER pmkRest );
+ INTERNAL_(LPMONIKER) AllButLast( void );
+ INTERNAL_(LPMONIKER) AllButFirst( void );
+ INTERNAL_(LPMONIKER) Last( void );
+ INTERNAL_(LPMONIKER) First( void );
+ INTERNAL_(ULONG) Count( void );
+ HRESULT CloneHelper(
+ IMoniker *pmk,
+ IMoniker **pmkCloned,
+ MemoryPlacement memPlace);
+
+ STDDEBDECL(CCompositeMoniker, CompositeMoniker)
+
+implementations:
+
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,Release) (THIS);
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID);
+
+ // *** IPersistStream methods ***
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm);
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty);
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR * pcbSize);
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID FAR* ppvResult);
+ STDMETHOD(BindToStorage) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD(Reduce) (THIS_ LPBC pbc, DWORD dwReduceHowFar, LPMONIKER FAR*
+ ppmkToLeft, LPMONIKER FAR * ppmkReduced);
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNOtGeneric,
+ LPMONIKER FAR* ppmkComposite);
+ STDMETHOD(Enum) (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker);
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker);
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash);
+ STDMETHOD(IsRunning) (THIS_ LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+ pmkNewlyRunning);
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime);
+ STDMETHOD(Inverse) (THIS_ LPMONIKER FAR* ppmk);
+ STDMETHOD(CommonPrefixWith) (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix);
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath);
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPTSTR FAR* lplpszDisplayName);
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPTSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut);
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys);
+ // REVIEW: we need the following method on monikers but it is not in
+ // the spec.
+ STDMETHOD(Clone) (THIS_ LPMONIKER FAR* ppmkDest, MemoryPlacement memPlace);
+ // "IInternalMoniker method"
+
+ friend
+ HRESULT STDAPICALLTYPE CreateGenericComposite( LPMONIKER, LPMONIKER,
+ LPMONIKER FAR*);
+
+ friend class CCompositeMonikerEnum;
+ friend BOOL IsReduced( LPMONIKER pmk );
+shared_state:
+
+ LPMONIKER m_pmkLeft;
+ LPMONIKER m_pmkRight;
+ BOOL m_fReduced;
+ SET_A5;
+};
+
+
+class FAR CCompositeMonikerEnum : IEnumMoniker
+{
+ CCompositeMonikerEnum( BOOL fForward, CCompositeMoniker FAR*);
+ ~CCompositeMonikerEnum( void );
+
+public:
+ static LPENUMMONIKER Create( BOOL fForward, CCompositeMoniker FAR*);
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ // *** IEnumMoniker methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, LPMONIKER FAR* reelt, ULONG FAR* pceltFetched);
+ STDMETHOD(Skip) (THIS_ ULONG celt);
+ STDMETHOD(Reset) (THIS);
+ STDMETHOD(Clone) (THIS_ LPENUMMONIKER FAR* ppenm);
+private:
+ struct FAR se // stackelement
+ {
+ CCompositeMoniker FAR* m_pCM;
+ se FAR* m_pseNext;
+ se FAR* m_psePrev;
+
+ se( CCompositeMoniker FAR* pCM ) { m_pCM = pCM; m_pseNext = NULL;
+ m_psePrev = NULL; }
+ };
+
+ void Push( CCompositeMoniker FAR* pCM );
+ LPMONIKER GetNext( LPMONIKER pmk );
+ LPMONIKER Pop( void );
+
+
+ ULONG m_refs;
+ CCompositeMoniker FAR* m_pCM; // the moniker being enumerated
+ BOOL m_fForward;
+ se FAR* m_pBase;
+ se FAR* m_pTop;
+ LPMONIKER m_pNext;
+ SET_A5;
+};
+
+
+class FAR CBindCtx
+{
+
+public:
+ static IUnknown FAR* Create( IUnknown FAR * pUnkOuter, DWORD reserved, MemoryPlacement memLoc = TASK );
+
+private:
+
+ CBindCtx( IUnknown FAR * pUnkOuter );
+ ~CBindCtx( void );
+
+ class FAR CObjList
+ {
+ public:
+
+ LPUNKNOWN m_punk;
+ CObjList FAR* m_pNext;
+
+ CObjList( IUnknown FAR * punk )
+ { m_punk = punk; m_pNext = NULL; }
+
+ ~CObjList( void );
+ };
+ DECLARE_NC(CBindCtx, CObjList)
+
+ INTERNAL_(void) AddToList( CObjList FAR* pCObjList )
+ { M_PROLOG(this); pCObjList->m_pNext = m_pFirstObj; m_pFirstObj = pCObjList; }
+
+
+
+implementations:
+
+ STDUNKDECL(CBindCtx,BindCtx)
+ STDDEBDECL(CBindCtx,BindCtx)
+
+ implement CBindCtxImpl : IBindCtx
+ {
+ public:
+ CBindCtxImpl( CBindCtx FAR * pBindCtx )
+ { m_pBindCtx = pBindCtx; }
+ STDMETHOD(QueryInterface) (THIS_ REFIID iid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ STDMETHOD(RegisterObjectBound) (THIS_ LPUNKNOWN punk);
+ STDMETHOD(RevokeObjectBound) (THIS_ LPUNKNOWN punk);
+ STDMETHOD(ReleaseBoundObjects) (THIS);
+
+ STDMETHOD(SetBindOptions) (THIS_ LPBIND_OPTS pbindopts);
+ STDMETHOD(GetBindOptions) (THIS_ LPBIND_OPTS pbindopts);
+ STDMETHOD(GetRunningObjectTable) (THIS_ LPRUNNINGOBJECTTABLE FAR*
+ pprot);
+ STDMETHOD(RegisterObjectParam) (THIS_ LPTSTR lpszKey, LPUNKNOWN punk);
+ STDMETHOD(GetObjectParam) (THIS_ LPTSTR lpszKey, LPUNKNOWN FAR* ppunk);
+ STDMETHOD(EnumObjectParam) (THIS_ LPENUMSTRING FAR* ppenum);
+ STDMETHOD(RevokeObjectParam) (THIS_ LPTSTR lpszKey);
+
+ CBindCtx FAR * m_pBindCtx;
+ };
+ DECLARE_NC(CBindCtx, CBindCtxImpl)
+
+ CBindCtxImpl m_BindCtx;
+
+
+shared_state:
+ SET_A5;
+ IUnknown FAR* m_pUnkOuter;
+ ULONG m_refs;
+
+ LPBIND_OPTS m_pBindOpts;
+ CObjList FAR* m_pFirstObj;
+ CMapStringToPtr FAR* m_pMap;
+ DWORD m_reserved;
+};
+
+
+
+
+class FAR CAntiMoniker : public CBaseMoniker
+{
+
+public:
+ static CAntiMoniker FAR* Create( ULONG count,
+ MemoryPlacement memLoc = TASK );
+
+private:
+
+ CAntiMoniker( ULONG count ) CONSTR_DEBUG
+ { //SETPVTBL(CAntiMoniker); GET_A5();
+ m_count = count; }
+
+implementations:
+
+ STDDEBDECL(CAntiMoniker, AntiMoniker)
+
+ // *** IUnknown methods inherited from CBaseMoniker***
+ STDMETHOD(QueryInterface) (THIS_ REFIID iid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,Release) (THIS);
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID);
+ // *** IPersistStream methods ***
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm);
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty);
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR * pcbSize);
+
+ // *** IMoniker methods which get reimplemented ***
+
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNotGeneric,
+ LPMONIKER FAR* ppmkComposite);
+ STDMETHOD(Enum) (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker);
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker);
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash);
+ STDMETHOD(CommonPrefixWith) (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix);
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath);
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPTSTR FAR* lplpszDisplayName);
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPTSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut);
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys);
+ // REVIEW: we need the following method on monikers but it is not in
+ // the spec.
+ STDMETHOD(Clone) (THIS_ LPMONIKER FAR* ppmkDest, MemoryPlacement memPlace);
+ // "IInternalMoniker method"
+
+public:
+ void EatOne( LPMONIKER FAR* ppmk );
+
+shared_state:
+ ULONG m_count;
+ SET_A5;
+};
+
+
+
+class FAR CPointerMoniker : public CBaseMoniker
+{
+
+public:
+ static CPointerMoniker FAR* Create( LPUNKNOWN pUnk, MemoryPlacement memLoc );
+
+private:
+
+ CPointerMoniker( LPUNKNOWN pUnk );
+ ~CPointerMoniker( void );
+
+ STDDEBDECL(CPointerMoniker, PointerMoniker)
+
+ STDMETHOD(QueryInterface) (THIS_ REFIID iid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,Release) (THIS);
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassId);
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID FAR* ppvResult);
+ STDMETHOD(BindToStorage) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNOtGeneric,
+ LPMONIKER FAR* ppmkPointer);
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker);
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash);
+// STDMETHOD(IsRunning) (THIS_ LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+// pmkNewlyRunning);
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime);
+ STDMETHOD(Inverse) (THIS_ LPMONIKER FAR* ppmk);
+ STDMETHOD(CommonPrefixWith) (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix);
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath);
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPTSTR FAR* lplpszDisplayName);
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPTSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut);
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys);
+ STDMETHOD(Clone) (THIS_ LPMONIKER FAR* ppmkDest, MemoryPlacement memPlace);
+shared_state:
+
+ LPUNKNOWN m_pUnk;
+ SET_A5;
+};
+
+INTERNAL_(DWORD) GetMonikerType( LPMONIKER pmk );
+INTERNAL_(BOOL) IsCompositeMoniker( LPMONIKER pmk );
+INTERNAL_(BOOL) IsAntiMoniker( LPMONIKER pmk );
+INTERNAL_(BOOL) IsFileMoniker( LPMONIKER pmk );
+INTERNAL_(BOOL) IsItemMoniker( LPMONIKER pmk );
+STDAPI Concatenate( LPMONIKER pmkFirst, LPMONIKER pmkRest,
+ LPMONIKER FAR* ppmkComposite );
+
+
+BOOL FAR PASCAL FIsCDROMDrive(WORD wDrive);
+INTERNAL SzFixNet( LPBINDCTX pbc, LPTSTR szUNCName, LPTSTR FAR * lplpszReturn );
+
+#endif // _CMONIMP_H_
diff --git a/private/ole32/com/moniker/dfspath.hxx b/private/ole32/com/moniker/dfspath.hxx
new file mode 100644
index 000000000..623ea35ef
--- /dev/null
+++ b/private/ole32/com/moniker/dfspath.hxx
@@ -0,0 +1,148 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dfspath.hxx
+//
+// Contents: Helper classes for IFileMoniker
+//
+// Classes:
+// CDfsPath Encapsulates a DFS path.
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+//
+//--------------------------------------------------------------------------
+
+#ifndef _DFSPATH_HXX_
+#define _DFSPATH_HXX_
+
+#include <memalloc.h>
+#include <dfsapi.h>
+
+
+
+// FILEMONIKERTYPE
+// A enumeration that specifies how a file moniker should be constructed.
+// default = default construction: try to normalize the provided path.
+// notNormalized = a non-normalized path is provided, don't attempt to
+// to normalize it: use as is.
+// normalizedProvided = a normalized path is provided. It's already
+// normalized: use as is.
+
+typedef enum _fileMonikerType
+{
+ defaultType,
+ notNormalized,
+ normalizedProvided
+} FILEMONIKERTYPE;
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDfsPath
+//
+// Purpose:
+//
+// Interface:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class
+CDfsPath
+{
+public:
+ ~CDfsPath() { delete _dfsPath; };
+ CDfsPath();
+
+ // Construct a path object.
+ // pvMemPlace: place object in shared memory or in task memory.
+ // pDrivePath: specifies the path to use in constructing the object.
+ // fmtType: determines if a DFS path or a non-DFS path is used.
+ // dfsRoot: specifies the root to use if a DFS path is created.
+ CDfsPath(
+ void* pvMemPlacement,
+ LPTSTR pDrivePath,
+ FILEMONIKERTYPE fmtType = defaultType,
+ DFS_ROOT dfsRoot = DFS_ROOT_ORG);
+
+ // Return the path backing this object.
+ // GetNormalPath() is something of a misnomer, since the returned
+ // string may be either a DFS normalized path or a regular path,
+ // depending on what is backing this object.
+ // Note: Returns just a pointer: there is no resource transfer.
+ // Copy the data if required.
+ DFS_PATH GetNormalPath() { return(_dfsPath); };
+
+ // Return the UNC path that corresponds to this normalized path.
+ // If no UNC path corresponds, returns a simple path.
+ // Path is stored in MemAlloc'ed memory.
+ TCHAR* GetUncPath(TCHAR** ppwszUncPath);
+
+ // Return the drive-path equivalent for the DfsPath.
+ // Path is stored in MemAlloc'ed memory.
+ TCHAR* GetDrivePath(TCHAR** ppwszDrivePath);
+
+ // Return the equivalent DFS path with the highest possible root
+ // Path is stored in MemAlloc'ed memory.
+ HRESULT GetHighestPath(TCHAR** ppwszHighestPath);
+
+ // Return true if the object is back by a normalized path.
+ BOOL Normalized() { return _bNormalized; };
+
+#if DBG == 1
+ // Dump the path as a string.
+ void Dump();
+#endif // DBG == 1
+
+private:
+ DFS_PATH _dfsPath;
+ BOOL _bNormalized;
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDfsPath::CDfsPath()
+//
+// Synopsis: Default constructor.
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline
+CDfsPath::CDfsPath()
+ : _dfsPath(NULL),
+ _bNormalized(TRUE)
+{
+};
+
+
+#endif // _DFSPATH_HXX_
diff --git a/private/ole32/com/moniker/filemon.hxx b/private/ole32/com/moniker/filemon.hxx
new file mode 100644
index 000000000..672b6df7d
--- /dev/null
+++ b/private/ole32/com/moniker/filemon.hxx
@@ -0,0 +1,399 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: filemon.hxx
+//
+// Contents: Helper classes and functions for IFileMoniker
+//
+// Classes:
+//
+// Functions:
+// AppendComponent append a component to a path.
+//
+// History: dd-mmm-yy Author Comment
+//
+//--------------------------------------------------------------------------
+
+#ifndef _FILEMON_HXX_
+#define _FILEMON_HXX_
+
+#include <dfsapi.h>
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ByteLength
+//
+// Synopsis: Returns the length, in bytes, of the supplied string.
+// Includes the terminating null byte(s).
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+// Returns 0 if the supplied pointer is NULL
+// An empty string (no characters) will return 1 * (character size),
+// which is the NULL termination.
+//
+//--------------------------------------------------------------------------
+
+ULONG
+ByteLength(TCHAR const* pwszString);
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: AppendComponent
+//
+// Synopsis: Appends the supplied component to the supplied path.
+//
+// Effects:
+//
+// Arguments:
+// pszStartOfBuffer: the path buffer to append the new component to.
+// ulBufferSize: the buffer size, in characters.
+// pszOldEnd: the current end of path (pointer to terminating NULL).
+// ppszNewEnd: the end (terminating NULL) after the component is added.
+// pszComponent: the component to append: is copied.
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+void
+AppendComponent(
+ TCHAR* pszStartOfBuffer,
+ ULONG ulBufferSize,
+ TCHAR* pszOldEnd,
+ TCHAR** ppszNewEnd,
+ TCHAR* pszComponent);
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: AllocAndCopy
+//
+// Synopsis: Copy a string, allocating space for the copy.
+//
+// Effects:
+//
+// Arguments:
+// pwszSource: the source string to copy
+//
+// Requires:
+//
+// Returns:
+// The allocated string.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+// The space for the copy is MemAlloc'ed.
+// Throws an exception in the case of errors.
+//
+//--------------------------------------------------------------------------
+
+TCHAR*
+AllocAndCopy(
+TCHAR* pwszSource);
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: AllocAndCopy
+//
+// Synopsis: Copy a string, allocating space for the copy.
+//
+// Effects:
+//
+// Arguments:
+// pwszSource: the source string to copy
+// ppwszDest: on return, *ppwszDest points to the copy
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+// The space for the copy is MemAlloc'ed.
+// Throws an exception in the case of errors.
+//
+//--------------------------------------------------------------------------
+
+void
+AllocAndCopy(
+TCHAR* pwszSource,
+TCHAR** ppwszDest);
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: AllocAndCopy
+//
+// Synopsis: Copy a string, allocating space for the copy.
+//
+// Effects:
+//
+// Arguments:
+// pwsSourceStart: the start of the source string to copy
+// pwsSourceEnd: the end of the source string to copy
+// ppwszDest: on return, *ppwszDest points to the copy
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+// The space for the copy is MemAlloc'ed.
+// Throws an exception in the case of errors.
+//
+// pwsSourceStart and pwsSourceEnd should point into the same
+// string, with pwsSourceStart <= pwsSourceEnd.
+// The substring from start to end, inclusive, is copied.
+//
+//--------------------------------------------------------------------------
+
+void
+AllocAndCopy(
+TCHAR* pwsSourceStart,
+TCHAR* pwsSourceEnd,
+TCHAR** ppwszDest);
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: AllocAndCopy
+//
+// Synopsis: Copy a string, allocating space for the copy.
+//
+// Effects:
+//
+// Arguments:
+// pwszSource: the source string to copy
+// ppwszDest: on return, *ppwszDest points to the copy
+// pvMemPlacement: a memory placement indicator.
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+// The space for the copy is new'd.
+// Throws an exception in the case of errors.
+//
+//--------------------------------------------------------------------------
+
+void
+AllocAndCopy(
+TCHAR* pwszSource,
+TCHAR** ppwszDest,
+void* pvMemPlacement);
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ExpandUNCName
+//
+// Synopsis: Convert a drive-based name to a UNC name if the drive is
+// connected to somewhere. Otherwise, just copy the drive-based name.
+//
+// Effects:
+//
+// Arguments:
+// lpszIn the path to convert to UNC if possible
+// *lplpszOut points to the UNC name, or a copy of the input.
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+// BUGBUG: Defined in cmonimp.cxx right now.
+// Return buffer is allocated by new
+//
+//--------------------------------------------------------------------------
+
+HRESULT
+ExpandUNCName( LPTSTR lpszIn, LPTSTR FAR * lplpszOut );
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ByteLength
+//
+// Synopsis: Returns the length, in bytes, of the supplied string.
+// Includes the terminating null byte(s).
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+// Returns 0 if the supplied pointer is NULL
+// An empty string (no characters) will return 1 * (character size),
+// which is the NULL termination.
+//
+//--------------------------------------------------------------------------
+
+ULONG
+ByteLength(TCHAR const* pwszString);
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReadStringStream2
+//
+// Synopsis: Read bytes from a stream. First item in stream should be count
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns: Returns the number of bytes read (the count field).
+// Throws an exception on errors.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+// Allocates memory for the returned array of bytes, using new.
+// The byte array returned is not guaranteed to be a zero-terminated
+// string.
+//
+//--------------------------------------------------------------------------
+
+ULONG
+ReadStringStream2( LPSTREAM pStm, BYTE** ppBytes );
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CStream
+//
+// Purpose: Encapsulates a LPSTREAM
+//
+// Interface:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+// Provided to handle errors by throwing exceptions.
+//
+//--------------------------------------------------------------------------
+
+class CStream
+{
+public:
+
+ ~CStream() { m_pStm->Release(); };
+
+ CStream(LPSTREAM pStm) { pStm->AddRef(); m_pStm = pStm;};
+
+ // IStream::Write(), except throws exceptions on error
+ void Write(VOID const* pv, ULONG cb, ULONG* pcbWritten);
+
+ // User-defined conversion: Return the LPSTREAM
+ operator LPSTREAM() { return(m_pStm); };
+
+private:
+ LPSTREAM m_pStm;
+
+};
+
+
+#endif // _FILEMON_HXX_
+
+
diff --git a/private/ole32/com/moniker2/cantimon.cxx b/private/ole32/com/moniker2/cantimon.cxx
new file mode 100644
index 000000000..d838ef394
--- /dev/null
+++ b/private/ole32/com/moniker2/cantimon.cxx
@@ -0,0 +1,788 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: cantimon.cxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Did not write this code
+// 02-04-94 KevinRo Gag'd on it, then rewrote it
+// 06-14-94 Rickhi Fix type casting
+//
+// An Anti moniker is intended to be the inverse of any moniker, such as
+// an Item Moniker. When another moniker composes itself with an Anti moniker
+// on the right, it is supposed to remove itself from the result.
+//
+// The original implementation of Anti monikers attempted to be optimal by
+// collapsing itself when composed with another Anti moniker. This was an
+// unfortunate decision, since other monikers decide to eliminate themselves
+// (and the Anti moniker) based on whether the moniker type to the right is
+// an Anti moniker.
+//
+// For example, File moniker (F) composed with an Anti moniker (A) should
+// result in nothing. F o A == (). The previous implementation was in error
+// because a composite of two anti-monikers was treated as a single anti
+// moniker with a count of two, denoted A(2).
+// Therefore, when the file moniker looked at the anti moniker using the
+// interface, it saw only one Anti moniker, instead of a composite.
+// ( F o A(2)) == (). It should have been ( F o (A o A) ) == ( A )
+//
+// To fix this, when we compose Anti monikers, we will always use a
+// composite. We need to be careful when loading old serialized Anti
+// monikers, and convert them as we see them.
+//
+// This actually makes this a sucky problem, since old monikers have a
+// funny behaviour if loaded from stream. The way the Load() interface
+// works, the client has a pointer to the Anti moniker before it is loaded.
+// Therefore, we can't just magically make this work.
+//
+// However, we can fix this up as soon as we can during the first Reduce or
+// Compose with that is called. You will find this code in the Compose
+// with methods, plus in the Create(count) methods.
+//
+// Save() is also a problem, since the caller has already written out our
+// class ID. Therefore, we can't just sneak in a composite, since it will
+// break the old fellows.
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include "cbasemon.hxx"
+#include "cantimon.hxx"
+#include "mnk.h"
+
+
+
+INTERNAL_(CAntiMoniker *) IsAntiMoniker( LPMONIKER pmk )
+{
+ CAntiMoniker *pCAM;
+
+ if ((pmk->QueryInterface(CLSID_AntiMoniker, (void **)&pCAM)) == S_OK)
+ {
+ // we release the AddRef from QI but stll return the pointer.
+ pCAM->Release();
+ return pCAM;
+ }
+
+ // dont rely on user implementations to return NULL on failed QI
+ return NULL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CAntiMoniker::Create
+//
+// Synopsis: Create a single AntiMoniker
+//
+// Effects:
+//
+// Arguments: (none)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-04-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CAntiMoniker FAR *CAntiMoniker::Create()
+{
+ CAntiMoniker FAR * pCAM = new CAntiMoniker();
+ if (pCAM)
+ {
+ pCAM->AddRef();
+ }
+ return pCAM;
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CAntiMoniker::Create
+//
+// Synopsis: Create a composite anti moniker.
+//
+// Effects: This function supports the 'old' way of creating Anti
+// monikers, by creating [count] Anti monikers, and composing
+// them together.
+//
+// Arguments: [count] -- Number of Anti monikers
+//
+// Requires:
+//
+// Returns:
+// if count == 1, this routine will return an CAntiMoniker.
+// if count > 1, this routine will create a composite moniker made up
+// of Anti monikers.
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-04-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+IMoniker * CAntiMoniker::Create(ULONG count)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CAntiMoniker::Create(0x%x))\n",
+ count));
+
+
+ HRESULT hr;
+ IMoniker *pmkComposite = NULL;
+
+ while(count--)
+ {
+ IMoniker *pmkNew;
+
+ CAntiMoniker FAR * pCAM = new CAntiMoniker();
+
+ //
+ // If there was failure, then releasing the old composite is
+ // required.
+ //
+
+ if (pCAM == NULL)
+ {
+ if (pmkComposite != NULL)
+ {
+ pmkComposite->Release();
+ }
+ return(NULL);
+ }
+ else
+ {
+ //
+ // The ref counting mechanism originally choosen makes it the
+ // responsibility of the Create() routine to do the AddRef on
+ // the newly created moniker.
+ //
+
+ pCAM->AddRef();
+ }
+
+ //
+ // Create a generic composite using the existing and new
+ // monikers. If this succeededs, then pmkNew will increment
+ // both reference counts.
+ //
+ //
+ // If there was a failure, then calling Release() on the new and
+ // old sections of the composite will cause both of them to be
+ // released, thus releasing the entire tree of monikers.
+ //
+ // If it succeeds, pmkNew will hold references to both of the
+ // old monikers, and life will be good.
+ //
+ // Note: First time around, pmkComposite == NULL, and
+ // CreateGenericComposite() will just return pCAM. It works.
+ //
+
+ hr = CreateGenericComposite(pmkComposite,pCAM,&pmkNew);
+
+ pCAM->Release();
+
+ //
+ // Watch out for the first time around the loop. This will
+ // cause pmkComposite to be NULL
+ //
+ if (pmkComposite != NULL)
+ {
+ pmkComposite->Release();
+ }
+
+ //
+ // If failed, then the last two releases cleaned up for us.
+ //
+ if (FAILED(hr))
+ {
+ return(NULL);
+ }
+
+ pmkComposite = pmkNew;
+ }
+
+ return pmkComposite;
+}
+
+
+STDMETHODIMP CAntiMoniker::QueryInterface(THIS_ REFIID riid,
+ LPVOID FAR* ppvObj)
+{
+ M_PROLOG(this);
+ VDATEIID (riid);
+ VDATEPTROUT(ppvObj, LPVOID);
+
+#ifdef _DEBUG
+ if (riid == IID_IDebug)
+ {
+ *ppvObj = &(m_Debug);
+ return NOERROR;
+ }
+#endif
+
+ if (IsEqualIID(riid, CLSID_AntiMoniker))
+ {
+ // called by IsAntiMoniker.
+ AddRef();
+ *ppvObj = this;
+ return S_OK;
+ }
+ else if (IsEqualIID(riid, IID_IROTData))
+ {
+ // called by ROT
+ AddRef();
+ *ppvObj = (IROTData *)this;
+ return S_OK;
+ }
+
+ return CBaseMoniker::QueryInterface(riid, ppvObj);
+}
+
+
+STDMETHODIMP_(ULONG) CAntiMoniker::Release(void)
+{
+ M_PROLOG(this);
+ Assert(m_refs != 0);
+
+ ULONG ul = m_refs;
+
+ if (InterlockedDecrement((long *)&m_refs) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return ul - 1;
+}
+
+
+
+STDMETHODIMP CAntiMoniker::GetClassID(LPCLSID lpClassId)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(lpClassId, CLSID);
+
+ *lpClassId = CLSID_AntiMoniker;
+ return NOERROR;
+}
+
+
+STDMETHODIMP CAntiMoniker::Load(LPSTREAM pStm)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CAntiMoniker::Load(%x)\n",
+ this));
+
+ M_PROLOG(this);
+ VDATEIFACE(pStm);
+
+ HRESULT hresult;
+ ULONG count;
+
+ hresult = StRead(pStm, &count, sizeof(ULONG));
+
+ if (SUCCEEDED(hresult))
+ {
+ m_count = count;
+ }
+ return hresult;
+}
+
+
+STDMETHODIMP CAntiMoniker::Save(LPSTREAM pStm, BOOL fClearDirty)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CAntiMoniker::Save(%x)\n",
+ this));
+
+ M_PROLOG(this);
+ VDATEIFACE(pStm);
+
+ UNREFERENCED(fClearDirty);
+ ULONG cbWritten;
+
+ return pStm->Write(&m_count, sizeof(ULONG), &cbWritten);
+ // REVIEW: what is proper error handling? Should we restore the seek
+ // pointer?
+}
+
+
+STDMETHODIMP CAntiMoniker::GetSizeMax(ULARGE_INTEGER FAR* pcbSize)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CAntiMoniker::GetSizeMax(%x)\n",
+ this));
+
+ M_PROLOG(this);
+ VDATEPTROUT(pcbSize, ULONG);
+
+ ULISet32(*pcbSize, sizeof(CLSID) + sizeof(ULONG));
+ noError;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CAntiMoniker::ComposeWith
+//
+// Synopsis: Compose this moniker with another moniker.
+//
+// Effects:
+//
+// Arguments: [pmkRight] --
+// [fOnlyIfNotGeneric] --
+// [ppmkComposite] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-04-94 kevinro Created
+//
+// Notes:
+//
+// In the event that m_count > 1, we can use this opportunity to fixup the
+// anti moniker into a composite of single anti monikers. This will help make
+// the monikers work correctly.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CAntiMoniker::ComposeWith( LPMONIKER pmkRight,
+ BOOL fOnlyIfNotGeneric, LPMONIKER FAR* ppmkComposite)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CAntiMoniker::ComposeWith(%x,pmkRight(%x))\n",
+ this,
+ pmkRight));
+
+ VDATEPTROUT(ppmkComposite,LPMONIKER);
+ *ppmkComposite = NULL;
+ VDATEIFACE(pmkRight);
+
+ HRESULT hresult = NOERROR;
+ IMoniker *pmkThis = NULL;
+ IMoniker *pmkRightComposite = NULL;
+
+
+ //
+ // The only way CAntiMonikers can compose is generically
+ //
+ if (fOnlyIfNotGeneric)
+ {
+ hresult = MK_E_NEEDGENERIC;
+ *ppmkComposite = NULL;
+ return hresult;
+ }
+
+ //
+ // Now, we are going to make a generic composite. This is a
+ // good time to determine if we need to convert this
+ // anti moniker into a composite
+ //
+ // If m_count > 1, create an equivalent composite moniker
+ //
+
+ if (m_count > 1)
+ {
+ pmkThis = Create(m_count);
+ }
+
+ //
+ // Regardless of the outcome, be sure pmkThis == a moniker to
+ // compose with.
+ //
+
+ if (pmkThis == NULL)
+ {
+ pmkThis = this;
+ }
+
+ //
+ // If the right side is an anti moniker also, then we need to
+ // concatenate the two Anti monikers into a composite.
+ //
+
+ CAntiMoniker *pmkRightAnti = IsAntiMoniker(pmkRight);
+ if (pmkRightAnti)
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "::ComposeWith(%x) CAntiMoniker(%x)\n",
+ this,
+ pmkRight));
+
+ //
+ // The right side is also an Anti moniker. Does it need fixing
+ // as well? If so, then fix it up, and assign it to pmkRight
+ //
+
+ if (pmkRightAnti->m_count > 1 )
+ {
+ pmkRightComposite = CAntiMoniker::Create(m_count);
+
+ if (pmkRightComposite != NULL)
+ {
+ pmkRight = pmkRightComposite;
+ }
+ }
+
+ hresult = Concatenate(pmkThis,pmkRight,ppmkComposite);
+ }
+ else
+ {
+ //
+ // Anti monikers can only be composed using generic composites
+ // when they are on the left.
+ //
+
+ hresult = CreateGenericComposite( pmkThis,
+ pmkRight,
+ ppmkComposite );
+ }
+
+ //
+ // Clean up after possible conversions
+ //
+
+ if (pmkThis != this)
+ {
+ pmkThis->Release();
+ }
+
+ if (pmkRightComposite != NULL)
+ {
+ pmkRightComposite->Release();
+ }
+
+ return hresult;
+}
+
+STDMETHODIMP CAntiMoniker::Enum (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker)
+{
+ VDATEPTROUT(ppenumMoniker,LPENUMMONIKER);
+ *ppenumMoniker = NULL;
+ noError;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CAntiMoniker::GetComparisonData
+//
+// Synopsis: Get comparison data for registration in the ROT
+//
+// Arguments: [pbData] - buffer to put the data in.
+// [cbMax] - size of the buffer
+// [pcbData] - count of bytes used in the buffer
+//
+// Returns: NOERROR
+// E_OUTOFMEMORY
+//
+// Algorithm: Build ROT data for anti moniker.
+//
+// History: 03-Feb-95 kevinro Created
+//
+// Note: Validating the arguments is skipped intentionally because this
+// will typically be called internally by OLE with valid buffers.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CAntiMoniker::GetComparisonData(
+ byte *pbData,
+ ULONG cbMax,
+ DWORD *pcbData)
+{
+ ULONG ulLength = sizeof(CLSID_AntiMoniker) + sizeof(m_count);
+
+ Assert(pcbData != NULL);
+ Assert(pbData != NULL);
+
+ if (cbMax < ulLength)
+ {
+ return(E_OUTOFMEMORY);
+ }
+
+ memcpy(pbData,&CLSID_AntiMoniker,sizeof(CLSID_AntiMoniker));
+ memcpy(pbData+sizeof(CLSID_AntiMoniker),&m_count,sizeof(m_count));
+
+ *pcbData = ulLength;
+
+ return NOERROR;
+}
+
+STDMETHODIMP CAntiMoniker::IsEqual (THIS_ LPMONIKER pmkOtherMoniker)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CAntiMoniker::IsEqual(%x,pmkOther(%x))\n",
+ this,
+ pmkOtherMoniker));
+
+ VDATEIFACE(pmkOtherMoniker);
+
+ CAntiMoniker *pCAM = IsAntiMoniker(pmkOtherMoniker);
+
+ if (pCAM)
+ {
+ // the other moniker is an anti moniker.
+ if (m_count == pCAM->m_count)
+ {
+ return NOERROR;
+ }
+ }
+
+ return ResultFromScode(S_FALSE);
+}
+
+
+
+STDMETHODIMP CAntiMoniker::Hash (THIS_ LPDWORD pdwHash)
+{
+ VDATEPTROUT(pdwHash, DWORD);
+ *pdwHash = 0x80000000 + m_count;
+ noError;
+}
+
+
+
+STDMETHODIMP CAntiMoniker::CommonPrefixWith (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CAntiMoniker::CommonPrefixWith(%x,pmkOther(%x))\n",
+ this,
+ pmkOther));
+
+ M_PROLOG(this);
+ VDATEPTROUT(ppmkPrefix,LPMONIKER);
+ *ppmkPrefix = NULL;
+ VDATEIFACE(pmkOther);
+
+ CAntiMoniker *pAntiMoniker = IsAntiMoniker(pmkOther);
+ if (pAntiMoniker)
+ {
+ if (m_count <= pAntiMoniker->m_count)
+ {
+ *ppmkPrefix = this;
+ AddRef();
+ if (m_count == pAntiMoniker->m_count)
+ return ResultFromScode(MK_S_US);
+ return ResultFromScode(MK_S_ME);
+ }
+ *ppmkPrefix = pmkOther;
+ pmkOther->AddRef();
+ return ResultFromScode(MK_S_HIM);
+ }
+ return MonikerCommonPrefixWith(this, pmkOther, ppmkPrefix);
+ // this handles the case where pmkOther is composite, as well as
+ // all other cases.
+}
+
+
+
+STDMETHODIMP CAntiMoniker::RelativePathTo (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CAntiMoniker::RelativePathTo(%x,pmkOther(%x))\n",
+ this,
+ pmkOther));
+
+ VDATEPTROUT(ppmkRelPath,LPMONIKER);
+ VDATEIFACE(pmkOther);
+
+ *ppmkRelPath = NULL;
+
+ *ppmkRelPath = pmkOther;
+ pmkOther->AddRef();
+
+ return MK_S_HIM;
+}
+
+
+
+STDMETHODIMP CAntiMoniker::GetDisplayName( LPBC pbc, LPMONIKER
+ pmkToLeft, LPWSTR FAR * lplpszDisplayName )
+ // return "\..\..\.. "
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CAntiMoniker::GetDisplayName(%x,pmkLeft(%x))\n",
+ this,
+ pmkToLeft));
+
+ M_PROLOG(this);
+
+ VDATEPTROUT(lplpszDisplayName, LPWSTR);
+
+ *lplpszDisplayName = NULL;
+
+ VDATEIFACE(pbc);
+
+ if (pmkToLeft) VDATEIFACE(pmkToLeft);
+
+ WCHAR FAR * lpch;
+ ULONG i;
+ ULONG ccDisplayName;
+
+ //
+ // ccDisplayName is the number of characters to allocate
+ //
+ // For each anti moniker, return one instance of '\..', which
+ // is 3 characters long. Also, add 1 for the terminating NULL
+ //
+
+ ccDisplayName = 1 + ( 3 * m_count );
+
+ *lplpszDisplayName = (WCHAR *)
+ CoTaskMemAlloc(sizeof(WCHAR) * ccDisplayName);
+
+ lpch = *lplpszDisplayName;
+
+ if (lpch == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ //
+ // Concat a whole bunch of strings forming the display name for
+ // the anti moniker
+ //
+ for (i = m_count; i > 0; i-- , lpch += 3)
+ {
+ memcpy(lpch, L"\\..", 3 * sizeof(WCHAR));
+ }
+
+ *lpch = '\0';
+
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP CAntiMoniker::ParseDisplayName( LPBC pbc,
+ LPMONIKER pmkToLeft, LPWSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CAntiMoniker::ParseDisplayName(%x,pmkLeft(%x)lpszName(%ws))\n",
+ this,
+ pmkToLeft,
+ WIDECHECK(lpszDisplayName)));
+
+ M_PROLOG(this);
+ VDATEPTROUT(ppmkOut,LPMONIKER);
+ *ppmkOut = NULL;
+ VDATEIFACE(pbc);
+ if (pmkToLeft) VDATEIFACE(pmkToLeft);
+ VDATEPTRIN(lpszDisplayName, WCHAR);
+ VDATEPTROUT(pchEaten,ULONG);
+
+ return ResultFromScode(E_NOTIMPL); // ParseDisplayName not implemented for AntiMonikers
+}
+
+
+
+STDMETHODIMP CAntiMoniker::IsSystemMoniker (THIS_ LPDWORD pdwType)
+{
+ M_PROLOG(this);
+ *pdwType = MKSYS_ANTIMONIKER;
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CAntiMoniker::EatOne
+//
+// Synopsis: This function creates an appropriate Anti moniker
+//
+// Effects:
+//
+// Arguments: [ppmk] --
+//
+// Requires:
+//
+// Returns:
+// if m_count == 1, returns NULL
+// if m_count == 2, returns a CAntiMoniker
+// if m_count > 2, returns a composite made up of anti monikers.
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-04-94 kevinro Created
+//
+// Notes:
+//
+// Back in the days when monikers collapsed themselves, this routine was
+// called in order to eat one of the counts. Now, it is used as a good place
+// to throw in a conversion for composite anti-monikers.
+//
+//----------------------------------------------------------------------------
+void CAntiMoniker::EatOne(LPMONIKER *ppmk)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CAntiMoniker::EatOne(%x)\n",
+ this));
+
+ *ppmk = CAntiMoniker::Create(m_count - 1);
+}
+
+
+#ifdef _DEBUG
+
+STDMETHODIMP_(void) NC(CAntiMoniker,CDebug)::Dump( IDebugStream FAR * pdbstm)
+{
+ VOID_VDATEIFACE(pdbstm);
+
+ *pdbstm << "CAntiMoniker @" << (VOID FAR *)m_pAntiMoniker;
+ *pdbstm << '\n';
+ pdbstm->Indent();
+ *pdbstm << "Refcount is " << (int)(m_pAntiMoniker->m_refs) << '\n';
+ *pdbstm << "Anti count is " << (int)(m_pAntiMoniker->m_count) << '\n';
+ pdbstm->UnIndent();
+}
+
+STDMETHODIMP_(BOOL) NC(CAntiMoniker,CDebug)::IsValid( BOOL fSuspicious )
+{
+ return ((LONG)(m_pAntiMoniker->m_refs) > 0);
+ // add more later, maybe
+}
+
+#endif
diff --git a/private/ole32/com/moniker2/cantimon.hxx b/private/ole32/com/moniker2/cantimon.hxx
new file mode 100644
index 000000000..d0b696793
--- /dev/null
+++ b/private/ole32/com/moniker2/cantimon.hxx
@@ -0,0 +1,79 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: cantimon.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Created
+//
+//----------------------------------------------------------------------------
+
+class FAR CAntiMoniker : public CBaseMoniker
+{
+
+public:
+ static IMoniker * Create( ULONG count);
+
+ static CAntiMoniker FAR* Create();
+
+ // *** IROTData Methods ***
+ STDMETHOD(GetComparisonData)(
+ byte *pbData,
+ ULONG cbMax,
+ ULONG *pcbData);
+
+
+ friend CAntiMoniker * IsAntiMoniker(LPMONIKER pmk);
+
+private:
+
+ CAntiMoniker( ULONG count = 1 ) CONSTR_DEBUG
+ { m_count = count; }
+
+implementations:
+
+ STDDEBDECL(CAntiMoniker, AntiMoniker)
+
+ // *** IUnknown methods inherited from CBaseMoniker***
+ STDMETHOD(QueryInterface) (THIS_ REFIID iid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,Release) (THIS);
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID);
+ // *** IPersistStream methods ***
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm);
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty);
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR * pcbSize);
+
+ // *** IMoniker methods which get reimplemented ***
+
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNotGeneric,
+ LPMONIKER FAR* ppmkComposite);
+ STDMETHOD(Enum) (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker);
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker);
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash);
+ STDMETHOD(CommonPrefixWith) (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix);
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath);
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR FAR* lplpszDisplayName);
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut);
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys);
+
+public:
+ void EatOne( LPMONIKER * ppmk );
+
+shared_state:
+ ULONG m_count;
+ SET_A5;
+};
diff --git a/private/ole32/com/moniker2/cbasemon.cxx b/private/ole32/com/moniker2/cbasemon.cxx
new file mode 100644
index 000000000..1a2383b4e
--- /dev/null
+++ b/private/ole32/com/moniker2/cbasemon.cxx
@@ -0,0 +1,251 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: cbasemon.cxx
+//
+// Contents: Implementation of CBaseMoniker
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Commented
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include "cbasemon.hxx"
+#include "mnk.h"
+
+inline
+HRESULT DerivedMustImplement( void )
+{
+ return ResultFromScode(E_NOTIMPL); // The derived class must implement this method
+}
+inline
+HRESULT InappropriateMemberFunction( void )
+{
+ return ResultFromScode(E_NOTIMPL); // Member function inappropriate for moniker class
+}
+
+
+STDMETHODIMP CBaseMoniker::QueryInterface
+ (REFIID riid, LPVOID FAR* ppvObj)
+{
+ M_PROLOG(this);
+
+ // Do not validate input as it has already been validated
+ // by derived classes.
+
+ if (IsEqualIID(riid, IID_IMoniker)
+ || IsEqualIID(riid, IID_IUnknown)
+ || IsEqualIID(riid, IID_IPersistStream)
+ || IsEqualIID(riid, IID_IInternalMoniker))
+ {
+ *ppvObj = this;
+ }
+ else if (IsEqualIID(riid, IID_IMarshal))
+ {
+ *ppvObj = &m_marshal;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+
+ InterlockedIncrement((long *)&m_refs);
+ return NOERROR;
+}
+
+
+STDMETHODIMP_(ULONG) CBaseMoniker::AddRef ()
+{
+ mnkDebugOut((DEB_TRACE, "%p CBaseMoniker::AddRef(%ld)\n",
+ this, m_refs + 1));
+
+ return InterlockedIncrement((long *)&m_refs);
+}
+
+
+STDMETHODIMP CBaseMoniker::IsDirty (THIS)
+{
+ M_PROLOG(this);
+ return ResultFromScode(S_FALSE);
+ // monikers are immutable so they are either always dirty or never dirty.
+ //
+}
+
+STDMETHODIMP CBaseMoniker::Load (THIS_ LPSTREAM pStm)
+{
+ M_PROLOG(this);
+ return InappropriateMemberFunction();
+}
+
+
+STDMETHODIMP CBaseMoniker::Save (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty)
+{
+ M_PROLOG(this);
+ return InappropriateMemberFunction();
+}
+
+
+STDMETHODIMP CBaseMoniker::GetSizeMax (THIS_ ULARGE_INTEGER FAR * pcbSize)
+{
+ M_PROLOG(this);
+ return InappropriateMemberFunction();
+}
+
+ // *** IMoniker methods ***
+STDMETHODIMP CBaseMoniker::BindToObject (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID FAR* ppvResult)
+{
+ M_PROLOG(this);
+ return InappropriateMemberFunction();
+}
+
+STDMETHODIMP CBaseMoniker::BindToStorage (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj)
+{
+ M_PROLOG(this);
+ return InappropriateMemberFunction();
+}
+
+STDMETHODIMP CBaseMoniker::Reduce (THIS_ LPBC pbc, DWORD dwReduceHowFar, LPMONIKER FAR*
+ ppmkToLeft, LPMONIKER FAR * ppmkReduced)
+{
+ M_PROLOG(this);
+ *ppmkReduced = this;
+ AddRef();
+ return ResultFromScode(MK_S_REDUCED_TO_SELF);
+}
+
+STDMETHODIMP CBaseMoniker::ComposeWith (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNotGeneric,
+ LPMONIKER FAR* ppmkComposite)
+{
+ M_PROLOG(this);
+ return InappropriateMemberFunction();
+}
+
+STDMETHODIMP CBaseMoniker::Enum (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker)
+{
+ M_PROLOG(this);
+ return InappropriateMemberFunction();
+}
+
+STDMETHODIMP CBaseMoniker::IsEqual (THIS_ LPMONIKER pmkOtherMoniker)
+{
+ M_PROLOG(this);
+ return InappropriateMemberFunction();
+}
+
+STDMETHODIMP CBaseMoniker::Hash (THIS_ LPDWORD pdwHash)
+{
+ M_PROLOG(this);
+ return InappropriateMemberFunction();
+}
+
+STDMETHODIMP CBaseMoniker::GetTimeOfLastChange (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime)
+{
+ M_PROLOG(this);
+ return InappropriateMemberFunction();
+}
+
+STDMETHODIMP CBaseMoniker::Inverse (THIS_ LPMONIKER FAR* ppmk)
+{
+ M_PROLOG(this);
+ *ppmk = NULL;
+ return ResultFromScode(MK_E_NOINVERSE);
+}
+
+STDMETHODIMP CBaseMoniker::CommonPrefixWith (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix)
+{
+ M_PROLOG(this);
+ return InappropriateMemberFunction();
+}
+
+STDMETHODIMP CBaseMoniker::RelativePathTo (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath)
+{
+ M_PROLOG(this);
+ return InappropriateMemberFunction();
+}
+
+STDMETHODIMP CBaseMoniker::GetDisplayName (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR FAR* lplpszDisplayName)
+{
+ M_PROLOG(this);
+ return InappropriateMemberFunction();
+}
+
+STDMETHODIMP CBaseMoniker::ParseDisplayName (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut)
+{
+ M_PROLOG(this);
+ return InappropriateMemberFunction();
+}
+
+
+STDMETHODIMP CBaseMoniker::IsSystemMoniker (THIS_ LPDWORD pdwMksys)
+{
+ M_PROLOG(this);
+ VDATEPTROUT (pdwMksys, DWORD);
+
+ *pdwMksys = 0;
+ return NOERROR;
+}
+
+
+STDMETHODIMP CBaseMoniker::IsRunning (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning)
+{
+ M_PROLOG(this);
+ VDATEIFACE (pbc);
+ LPRUNNINGOBJECTTABLE pROT;
+ HRESULT hresult;
+
+
+ if (pmkToLeft)
+ VDATEIFACE (pmkToLeft);
+ if (pmkNewlyRunning)
+ VDATEIFACE (pmkNewlyRunning);
+
+ if (pmkToLeft == NULL)
+ {
+ if (pmkNewlyRunning != NULL)
+ {
+ return pmkNewlyRunning->IsEqual (this);
+ }
+ else
+ {
+ hresult = pbc->GetRunningObjectTable (&pROT);
+ if (hresult == NOERROR)
+ {
+ hresult = pROT->IsRunning (this);
+ pROT->Release ();
+ }
+ return hresult;
+ }
+ }
+ else
+ {
+ return ResultFromScode(S_FALSE);
+ }
+
+}
+
+
+STDMETHODIMP CBaseMoniker::GetComparisonData(
+ byte *pbData,
+ ULONG cbMax,
+ ULONG *pcbData)
+{
+ return InappropriateMemberFunction();
+}
diff --git a/private/ole32/com/moniker2/cbasemon.hxx b/private/ole32/com/moniker2/cbasemon.hxx
new file mode 100644
index 000000000..87c86deed
--- /dev/null
+++ b/private/ole32/com/moniker2/cbasemon.hxx
@@ -0,0 +1,107 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: cbasemon.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Created
+// 05-18-94 AlexT Remove Release and GetClassId, which
+// must be implemented by the derived class
+//
+//----------------------------------------------------------------------------
+
+#ifdef _DEBUG
+#define CONSTR_DEBUG : m_Debug(this)
+#else
+#define CONSTR_DEBUG
+#endif
+
+#include "cmarshal.hxx"
+
+class FAR CBaseMoniker : public CPrivAlloc, public IMoniker, public IROTData
+/*
+ * CBaseMoniker is a base implementation class that does the
+ * following:
+ *
+ * 1. It implements QueryInterface, AddRef, and IsDirty,
+ * since these all have the same implementation for all the moniker
+ * classes defined here.
+ *
+ * 2. It returns error messages for other methods. Normally
+ * these will be replaced by real implementations in the
+ * derived classes, but in some cases, AntiMonikers, for
+ * instance, it allows us to declare and write only those
+ * methods with meaningful implementations. Methods such as
+ * BindToObject for antimonikers will inherit the error code
+ * form the base implementation.
+ */
+
+{
+protected:
+
+ //
+ // BUGBUG: We really should set m_refs == 1 and remove the AddRefs()
+ // from other places in the code.
+ //
+
+ CBaseMoniker(void) : m_marshal(this)
+ { m_refs = 0; }
+
+public:
+
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+
+ // *** IPersistStream methods ***
+ STDMETHOD(IsDirty) (THIS);
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm);
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty);
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR * pcbSize);
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID FAR* ppvResult);
+ STDMETHOD(BindToStorage) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD(Reduce) (THIS_ LPBC pbc, DWORD dwReduceHowFar, LPMONIKER FAR*
+ ppmkToLeft, LPMONIKER FAR * ppmkReduced);
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNotGeneric,
+ LPMONIKER FAR* ppmkComposite);
+ STDMETHOD(Enum) (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker);
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker);
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash);
+ STDMETHOD(IsRunning) (THIS_ LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+ pmkNewlyRunning);
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime);
+ STDMETHOD(Inverse) (THIS_ LPMONIKER FAR* ppmk);
+ STDMETHOD(CommonPrefixWith) (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix);
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath);
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR FAR* lplpszDisplayName);
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut);
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys);
+
+ // *** IROTData Methods ***
+ STDMETHOD(GetComparisonData)(
+ byte *pbData,
+ ULONG cbMax,
+ ULONG *pcbData);
+
+ ULONG m_refs;
+ CMarshalImplPStream m_marshal;
+ SET_A5;
+};
diff --git a/private/ole32/com/moniker2/cbindctx.cxx b/private/ole32/com/moniker2/cbindctx.cxx
new file mode 100644
index 000000000..01aaca2bd
--- /dev/null
+++ b/private/ole32/com/moniker2/cbindctx.cxx
@@ -0,0 +1,610 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: cbindctx.cxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 12-27-93 ErikGav Created
+// 10-05-95 MikeHill Added 'dwRestricted' field to BIND_OPTS.
+// 11-14-95 MikeHill Removed previous change (to BIND_OPTS).
+// 12-06-95 MikeHill Fixed Get/SetBindOptions so they don't corrupt
+// the cbStruct field.
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include "cbindctx.hxx"
+#include "mnk.h"
+
+
+/*
+ * Implementation of CBindCtx
+ *
+ *
+ *
+ *
+ */
+
+
+NAME_SEG(CBindCtx)
+
+#ifdef NOTYET
+// IEnumString implementation for EnumObjectParam call
+
+class CEnumStringImpl : public IEnumString
+{
+public:
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj)
+ {
+ if (riid == IID_IEnumString || riid == IID_IUnknown)
+ {
+ *ppvObj = this;
+ AddRef();
+ return NOERROR;
+ }
+ return ResultFromScode(E_NOINTERFACE);
+ }
+
+ STDMETHOD_(ULONG,AddRef) (THIS)
+ {
+ return ++m_refs;
+ }
+
+ STDMETHOD_(ULONG,Release) (THIS)
+ {
+ if (--m_refs == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return m_refs;
+ }
+
+ // *** IEnumString methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt,
+ LPWSTR FAR* reelt,
+ ULONG FAR* pceltFetched);
+ STDMETHOD(Skip) (THIS_ ULONG celt);
+ STDMETHOD(Reset) (THIS);
+ STDMETHOD(Clone) (THIS_ LPENUMSTRING FAR* ppenm);
+
+ //constructor/destructor
+ CEnumStringImpl( CMapStringToPtr FAR * pMap );
+ ~CEnumStringImpl( void );
+
+private:
+ class LI
+ {
+ public:
+ LI FAR * pliNext;
+ LPWSTR lpszKey;
+
+ LI( LPWSTR lpsz ) {
+ lpszKey = lpsz;
+ }
+ };
+ friend class LI;
+
+ LI FAR * pliHead;
+ LI FAR * pliCurrent;
+ ULONG m_refs;
+};
+#endif // NOTYET
+
+
+
+CBindCtx::CBindCtx()
+#ifdef _DEBUG
+ : m_Debug(this)
+#endif
+{
+ GET_A5();
+ m_refs = 1;
+ m_pFirstObj = NULL;
+
+ m_bindopts.cbStruct = sizeof(m_bindopts);
+ m_bindopts.grfFlags = 0;
+ m_bindopts.grfMode = STGM_READWRITE;
+ m_bindopts.dwTickCountDeadline = 0;
+ m_bindopts.dwTrackFlags = 0;
+
+#ifdef WX86OLE
+ m_bindopts.dwClassContext = gcwx86.IsWx86Enabled() ?
+ CLSCTX_SERVER | CLSCTX_INPROC_SERVERX86 :
+ CLSCTX_SERVER;
+#else
+ m_bindopts.dwClassContext = CLSCTX_SERVER;
+#endif
+
+ m_bindopts.locale = GetThreadLocale();
+ m_bindopts.pServerInfo = 0;
+
+ m_pMap = NULL;
+}
+
+
+CBindCtx::~CBindCtx( void )
+{
+ LPWSTR lpszKey;
+ LPVOID lpvoid;
+ M_PROLOG(this);
+
+ ReleaseBoundObjects();
+
+ if (m_pMap)
+ {
+ POSITION pos = m_pMap->GetStartPosition();
+ while (pos != NULL)
+ {
+ m_pMap->GetNextAssoc(pos, lpszKey, lpvoid);
+ if (lpvoid) ((LPUNKNOWN)lpvoid)->Release();
+ }
+ delete m_pMap;
+ }
+}
+
+
+
+NC(CBindCtx,CObjList)::~CObjList(void)
+{
+ if (m_punk) m_punk->Release();
+}
+
+
+IBindCtx FAR *CBindCtx::Create()
+{
+ return new FAR CBindCtx();
+}
+
+
+STDMETHODIMP CBindCtx::QueryInterface(REFIID iidInterface, void FAR* FAR* ppv)
+{
+ HRESULT hr;
+
+ __try
+ {
+ //Parameter validation.
+ //An invalid parameter will throw an exception.
+ *ppv = 0;
+
+ if (IsEqualIID(iidInterface, IID_IUnknown)
+ || IsEqualIID(iidInterface, IID_IBindCtx))
+ {
+ AddRef();
+ *ppv = this;
+ hr = S_OK;
+ }
+#ifdef _DEBUG
+ else if(IsEqualIID(iidInterface,IID_IDebug))
+ {
+ *ppv = (void FAR *)&m_Debug;
+ hr = S_OK;
+ }
+#endif
+ else
+ {
+ hr = E_NOINTERFACE;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //An exception occurred, probably because of a bad parameter.
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+
+
+STDMETHODIMP_(ULONG) CBindCtx::AddRef( void )
+{
+ InterlockedIncrement((long *)&m_refs);
+ return m_refs;
+}
+
+
+STDMETHODIMP_(ULONG) CBindCtx::Release( void )
+{
+ ULONG count = m_refs - 1;
+
+ if(InterlockedDecrement((long *)&m_refs) == 0)
+ {
+ delete this;
+ count = 0;
+ }
+
+ return count;
+}
+
+
+STDMETHODIMP CBindCtx::RegisterObjectBound( LPUNKNOWN punk )
+{
+ M_PROLOG(this);
+ if (punk == NULL) noError;
+ VDATEIFACE(punk);
+ CObjList FAR* pCOL = new CObjList( punk );
+ if (pCOL)
+ {
+ punk->AddRef();
+ AddToList(pCOL);
+ noError;
+ }
+ return ResultFromScode(S_OOM);
+}
+
+
+
+STDMETHODIMP CBindCtx::RevokeObjectBound
+ ( LPUNKNOWN punk )
+{
+ M_PROLOG(this);
+ VDATEIFACE(punk);
+ CObjList FAR * pCOL = m_pFirstObj;
+ CObjList FAR * pCOLPrev = NULL;
+
+ // look for entry which matches punk given
+ for (; pCOL && (pCOL->m_punk != punk);
+ pCOLPrev = pCOL, pCOL = pCOL->m_pNext)
+ {
+ // empty
+ }
+
+ // pCOL is null or pCOL->m_punk = punk
+ if (pCOL != NULL)
+ {
+ if (pCOLPrev == NULL) m_pFirstObj = pCOL->m_pNext;
+ else pCOLPrev->m_pNext = pCOL->m_pNext;
+ delete pCOL;
+ noError;
+ }
+ return ResultFromScode(MK_E_NOTBOUND);
+}
+
+
+
+
+STDMETHODIMP CBindCtx::ReleaseBoundObjects(THIS)
+{
+ M_PROLOG(this);
+ CObjList FAR * pCOL = m_pFirstObj;
+ CObjList FAR * pCOLNext = NULL;
+ m_pFirstObj = NULL;
+ while (pCOL != NULL)
+ {
+ pCOLNext = pCOL->m_pNext;
+ delete pCOL; // calls Release on the object
+ pCOL = pCOLNext;
+ }
+ noError;
+}
+
+STDMETHODIMP CBindCtx::SetBindOptions (LPBIND_OPTS pbindopts)
+{
+ HRESULT hr;
+
+ __try
+ {
+ if (pbindopts->cbStruct <= sizeof(m_bindopts))
+ {
+ //Set the bind options.
+ memcpy(&m_bindopts, pbindopts, (size_t)(pbindopts->cbStruct));
+ hr = S_OK;
+ }
+ else
+ {
+ //pbindopts is too large.
+ hr = E_INVALIDARG;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //An exception occurred, probably because of a bad parameter.
+ hr = E_INVALIDARG;
+ }
+
+ Assert(m_bindopts.cbStruct <= sizeof(m_bindopts));
+ return hr;
+}
+
+
+STDMETHODIMP CBindCtx::GetBindOptions (LPBIND_OPTS pbindopts)
+{
+ HRESULT hr;
+ ULONG cbDest;
+
+ Assert(m_bindopts.cbStruct <= sizeof(m_bindopts));
+
+ __try
+ {
+ cbDest = pbindopts->cbStruct;
+ if(m_bindopts.cbStruct <= cbDest)
+ {
+ memcpy(pbindopts, &m_bindopts, m_bindopts.cbStruct);
+ }
+ else
+ {
+ BIND_OPTS2 bindopts = m_bindopts;
+ bindopts.cbStruct = cbDest;
+ memcpy(pbindopts, &bindopts, cbDest);
+ }
+ hr = S_OK;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //An exception occurred, probably because of a bad parameter.
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+
+STDMETHODIMP CBindCtx::GetRunningObjectTable (THIS_ LPRUNNINGOBJECTTABLE FAR*
+ pprot)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(pprot, LPRUNNINGOBJECTTABLE);
+ return ::GetRunningObjectTable(0, pprot);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CBindCtx::RegisterObjectParam
+//
+// Synopsis: Registers object with key
+//
+// Effects: Adds object to bind context
+//
+// Arguments: [lpszKey] -- registration key
+// [punk] -- object
+//
+// Returns: HRESULT
+//
+// Modifies:
+//
+// Derivation: IBindContext
+//
+// Algorithm:
+//
+// History: 03-Jun-94 AlexT Added header block; release previous
+// object (if it exists)
+//
+// Notes: This function is not multithread safe!
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CBindCtx::RegisterObjectParam (THIS_ LPWSTR lpszKey, LPUNKNOWN punk)
+{
+ M_PROLOG(this);
+ VDATEPTRIN(lpszKey, WCHAR);
+ VDATEIFACE(punk);
+
+ if (m_pMap == NULL)
+ {
+ // We don't have a map yet; allocate one
+ m_pMap = new CMapStringToPtr();
+ if (NULL == m_pMap)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+ }
+ else
+ {
+ LPVOID pv;
+
+ // We already have a map; if we have an existing entry for this
+ // key we release it here (we don't remove the key because we're
+ // about to assign a new value with the same key below
+
+ if (m_pMap->Lookup(lpszKey, pv))
+ {
+ ((LPUNKNOWN)pv)->Release();
+ }
+ }
+
+ // SetAt is guaranteed not to fail if lpszKey is already in the map
+
+ if (m_pMap->SetAt(lpszKey, (LPVOID&)punk))
+ {
+ punk->AddRef();
+ return NOERROR;
+ }
+
+ return ResultFromScode(E_OUTOFMEMORY);
+}
+
+
+STDMETHODIMP CBindCtx::GetObjectParam (THIS_ LPWSTR lpszKey, LPUNKNOWN FAR* ppunk)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(ppunk, LPUNKNOWN);
+ *ppunk = NULL;
+ VDATEPTRIN(lpszKey, WCHAR);
+
+ LPVOID pNewValue = (LPVOID)(*ppunk);
+
+ if (m_pMap != NULL && m_pMap->Lookup(lpszKey, pNewValue))
+ {
+ *ppunk = (LPUNKNOWN)pNewValue;
+ (*ppunk)->AddRef();
+ return NOERROR;
+ }
+
+ return ResultFromScode(E_FAIL);
+}
+
+//BUGBUG: We should implement IBindCtx::EnumObjectParam.
+STDMETHODIMP CBindCtx::EnumObjectParam
+(THIS_ LPENUMSTRING FAR* ppenum)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(ppenum, LPENUMSTRING);
+
+#ifdef NOTYET
+ *ppenum = new CEnumStringImpl( m_pMap );
+ if (*ppenum == NULL) return ResultFromScode(E_OUTOFMEMORY);
+ return NOERROR;
+#else
+ *ppenum = NULL;
+ return ResultFromScode(E_NOTIMPL);
+#endif
+}
+
+
+STDMETHODIMP CBindCtx::RevokeObjectParam
+(THIS_ LPWSTR lpszKey)
+{
+ M_PROLOG(this);
+ VDATEPTRIN(lpszKey, WCHAR);
+ LPVOID lpvoid;
+
+ if (m_pMap != NULL
+ && (m_pMap->Lookup(lpszKey, lpvoid))
+ && m_pMap->RemoveKey(lpszKey))
+ {
+ ((LPUNKNOWN)lpvoid)->Release();
+ return NOERROR;
+ }
+
+ return ResultFromScode(E_FAIL);
+}
+
+
+
+
+
+#ifdef _DEBUG
+STDMETHODIMP_(void) NC(CBindCtx,CDebug)::Dump( IDebugStream FAR * pdbstm)
+{
+ VOID_VDATEIFACE(pdbstm);
+
+ NC(CBindCtx,CObjList) FAR * pCOL;
+
+ *pdbstm << "CBindCtx @" << (VOID FAR *)m_pBindCtx <<'\n';
+ pdbstm->Indent();
+ *pdbstm << "m_BindCtx is " << (VOID FAR *)&(m_pBindCtx)<<'\n';
+ *pdbstm << "Refcount is " << (int)(m_pBindCtx->m_refs) << '\n';
+ *pdbstm << "Registered objects: \n";
+ pdbstm->Indent();
+ for (pCOL = m_pBindCtx->m_pFirstObj; pCOL; pCOL = pCOL->m_pNext )
+ *pdbstm << (pCOL->m_punk);
+
+ pdbstm->UnIndent();
+ *pdbstm<<"End of registered objects \n";
+ pdbstm->UnIndent();
+}
+
+
+STDMETHODIMP_(BOOL) NC(CBindCtx,CDebug)::IsValid( BOOL fSuspicious )
+{
+ return ((LONG)(m_pBindCtx->m_refs) > 0);
+ // add more later, maybe
+}
+#endif // _DEBUG
+
+
+#ifdef NOTYET
+
+NOTE: this code has to be fixed before used again: the ctor should
+really fail if not enough memory is available and the next function
+should copy the strings. An alternative implementation might be wise.
+
+#pragma SEG(CEnumStringImpl_ctor)
+CEnumStringImpl::CEnumStringImpl( CMapStringToPtr FAR * pMap )
+{
+ LPWSTR lpsz;
+ LPWSTR lpszKey;
+ LPVOID lpvoid;
+ size_t n;
+ LI FAR * pli;
+
+ POSITION pos = pMap->GetStartPosition();
+ pliHead = NULL;
+ while (pos != NULL)
+ {
+ pMap->GetNextAssoc(pos, lpszKey, lpvoid );
+ lpsz = new FAR WCHAR[n = (1+_fstrlen(lpszKey))];
+ if (lpsz == NULL)
+ continue;
+
+ memcpy(lpsz, lpszKey, n * sizeof(WCHAR));
+ pli = new LI( lpsz );
+ if (pli)
+ {
+ pli->pliNext = pliHead;
+ pliHead = pli;
+ }
+ }
+ pliCurrent = pliHead;
+ m_refs = 1;
+}
+
+
+
+#pragma SEG(CEnumStringImpl_dtor)
+CEnumStringImpl::~CEnumStringImpl( void )
+{
+ LI FAR * pli = pliHead;
+ while (pli)
+ {
+ pliHead = pli->pliNext;
+ delete pli->lpszKey;
+ delete pli;
+ pli = pliHead;
+ }
+}
+
+#pragma SEG(CEnumStringImpl_Next)
+STDMETHODIMP CEnumStringImpl::Next (ULONG celt,
+ LPWSTR FAR* reelt,
+ ULONG FAR* pceltFetched)
+{
+ ULONG celtTemp = 0;
+ while (celtTemp < celt && pliCurrent)
+ {
+ reelt[celtTemp++] = pliCurrent->lpszKey;
+ pliCurrent = pliCurrent->pliNext;
+ }
+ if (pceltFetched) *pceltFetched = celtTemp;
+ return celtTemp == celt ? NOERROR : ResultFromScode(S_FALSE);
+}
+
+
+#pragma SEG(CEnumStringImpl_Skip)
+STDMETHODIMP CEnumStringImpl::Skip (ULONG celt)
+{
+ ULONG celtTemp = 0;
+ while (celtTemp < celt && pliCurrent)
+ pliCurrent = pliCurrent->pliNext;
+ return celtTemp == celt ? NOERROR : ResultFromScode(S_FALSE);
+}
+
+
+#pragma SEG(CEnumStringImpl_Reset)
+STDMETHODIMP CEnumStringImpl::Reset (void)
+{
+ pliCurrent = pliHead;
+ return NOERROR;
+}
+
+
+#pragma SEG(CEnumStringImpl_Clone)
+STDMETHODIMP CEnumStringImpl::Clone (LPENUMSTRING FAR* ppenm)
+{
+ // REVIEW : to be implemented
+ VDATEPTROUT(ppenm, LPENUMSTRING);
+ *ppenm = NULL;
+ return ResultFromScode(E_NOTIMPL);
+}
+#endif // NOTYET
diff --git a/private/ole32/com/moniker2/cbindctx.hxx b/private/ole32/com/moniker2/cbindctx.hxx
new file mode 100644
index 000000000..6b15d805d
--- /dev/null
+++ b/private/ole32/com/moniker2/cbindctx.hxx
@@ -0,0 +1,75 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: cbindctx.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Commented
+//
+//----------------------------------------------------------------------------
+
+
+#include <map_sp.h>
+
+
+class FAR CBindCtx : public CPrivAlloc, public IBindCtx
+{
+public:
+ static IBindCtx FAR*Create();
+
+ STDMETHOD(QueryInterface) (THIS_ REFIID iid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ STDMETHOD(RegisterObjectBound) (THIS_ LPUNKNOWN punk);
+ STDMETHOD(RevokeObjectBound) (THIS_ LPUNKNOWN punk);
+ STDMETHOD(ReleaseBoundObjects) (THIS);
+
+ STDMETHOD(SetBindOptions) (THIS_ LPBIND_OPTS pbindopts);
+ STDMETHOD(GetBindOptions) (THIS_ LPBIND_OPTS pbindopts);
+ STDMETHOD(GetRunningObjectTable) (THIS_ LPRUNNINGOBJECTTABLE FAR* pprot);
+ STDMETHOD(RegisterObjectParam) (THIS_ LPWSTR lpszKey, LPUNKNOWN punk);
+ STDMETHOD(GetObjectParam) (THIS_ LPWSTR lpszKey, LPUNKNOWN FAR* ppunk);
+ STDMETHOD(EnumObjectParam) (THIS_ LPENUMSTRING FAR* ppenum);
+ STDMETHOD(RevokeObjectParam) (THIS_ LPWSTR lpszKey);
+
+private:
+
+ CBindCtx();
+ ~CBindCtx( void );
+
+ class FAR CObjList : public CPrivAlloc
+ {
+ public:
+
+ LPUNKNOWN m_punk;
+ CObjList FAR* m_pNext;
+
+ CObjList( IUnknown FAR * punk )
+ { m_punk = punk; m_pNext = NULL; }
+
+ ~CObjList( void );
+ };
+ DECLARE_NC(CBindCtx, CObjList)
+
+ INTERNAL_(void) AddToList( CObjList FAR* pCObjList )
+ { M_PROLOG(this); pCObjList->m_pNext = m_pFirstObj; m_pFirstObj = pCObjList; }
+
+
+ STDDEBDECL(CBindCtx,BindCtx)
+
+shared_state:
+ SET_A5;
+ ULONG m_refs;
+ BIND_OPTS2 m_bindopts;
+
+ CObjList FAR* m_pFirstObj;
+ CMapStringToPtr FAR* m_pMap;
+};
diff --git a/private/ole32/com/moniker2/ccompmon.cxx b/private/ole32/com/moniker2/ccompmon.cxx
new file mode 100644
index 000000000..230821a69
--- /dev/null
+++ b/private/ole32/com/moniker2/ccompmon.cxx
@@ -0,0 +1,3428 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: ccompmon.cxx
+//
+// Contents: Generic Composite Monikers
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Commented
+// 02-01-94 KevinRo Gagged on it, then tried to explain
+// 06-14-94 Rickhi Fix type casting
+// 08-08-94 BruceMa Memory sift fix
+// 10-Jan-95 BruceMa Conform MonikerRelativePathTo to spec
+// 03-Apr-96 BruceMa Fix ::IsEqual
+// 22-May-96 BruceMa Re fix ::IsEqual
+//
+//
+// Composite monikers are implemented here. A composite moniker is created
+// as a binary tree of monikers, with the leaf nodes of the tree being
+// non-composite monikers.
+//
+// Every composite moniker has a left and a right part (otherwise it
+// wouldn't be a composite moniker). The composition of two monikers
+// involves creating a new composite, and pointing left and right at
+// the two parts of the composite. This is how the binary tree is
+// built.
+//
+// (Note: This may not be the most efficient way of implementing this,
+// but it is legacy code we are going to adopt. Sorry!)
+//
+// The ordering in the tree is left most. Therefore, there are many
+// possible tree configurations, as long as the leaf nodes evaluate
+// to the same order when done left to right. This is an important point
+// to keep in mind when you are looking at some of the functions, such
+// as AllButFirst, which creates a new composite tree. At first, it doesn't
+// appear to do the correct thing, until you draw it out on paper, and
+// realize that the nodes are still visited in the same order.
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include "cbasemon.hxx"
+#include "ccompmon.hxx"
+#include "cfilemon.hxx"
+#include "mnk.h"
+#include <rotdata.hxx>
+
+#include <olepfn.hxx>
+
+INTERNAL_(CCompositeMoniker *) IsCompositeMoniker ( LPMONIKER pmk )
+{
+ CCompositeMoniker *pCMk;
+
+ if ((pmk->QueryInterface(CLSID_CompositeMoniker, (void **)&pCMk)) == S_OK)
+ {
+ // the Release the AddRef done by QI, but still return the ptr
+ pCMk->Release();
+ return pCMk;
+ }
+
+ // dont rely on user implementations to set pCMk to NULL on failed QI
+ return NULL;
+}
+
+CCompositeMoniker::CCompositeMoniker( void ) CONSTR_DEBUG
+{
+ m_pmkLeft = NULL;
+ m_pmkRight = NULL;
+ m_fReduced = FALSE;
+
+#ifdef _TRACKLINK_
+ _tcm.SetParent(this);
+ m_fReduceForced = FALSE;
+#endif
+
+ //
+ // CoQueryReleaseObject needs to have the address of the this objects
+ // query interface routine.
+ //
+ if (adwQueryInterfaceTable[QI_TABLE_CCompositeMoniker] == 0)
+ {
+ adwQueryInterfaceTable[QI_TABLE_CCompositeMoniker] =
+ **(DWORD **)((IMoniker *)this);
+ }
+
+}
+
+/*
+ * Implementation of CCompositeMoniker
+ */
+
+CCompositeMoniker::~CCompositeMoniker( void )
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::~CCompositeMoniker(%x)\n",
+ this));
+
+ // REVIEW: this is recursive deletion of what is essentially a linked
+ // list. A rewrite could save stack space.
+ if (m_pmkLeft)
+ {
+ m_pmkLeft->Release();
+ }
+
+ if (m_pmkRight)
+ {
+ m_pmkRight->Release();
+ }
+}
+
+//
+// BUGBUG: (KevinRo) Other parts of the code depend on composite monikers ALWAYS
+// having at two parts. This code allows zero or one part. Why?
+//
+// Turns out that the classfactory for this moniker will create an empty
+// instance by called ::Create(NULL,NULL). The create function has been
+// changed to special case this condition, and NOT call initialize.
+//
+
+INTERNAL_(BOOL) CCompositeMoniker::Initialize( LPMONIKER pmkFirst,
+ LPMONIKER pmkRest)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::Initialize(%x)\n",
+ this));
+ //
+ // Neither moniker can be NULL
+ //
+ if ((pmkFirst == NULL) || (pmkRest == NULL))
+ {
+ return(FALSE);
+ }
+
+ GEN_VDATEIFACE(pmkFirst, FALSE);
+ GEN_VDATEIFACE(pmkRest, FALSE);
+
+ m_pmkLeft = pmkFirst;
+
+ pmkFirst->AddRef();
+
+ m_pmkRight = pmkRest;
+
+ pmkRest->AddRef();
+
+ m_fReduced = IsReduced(pmkFirst) && IsReduced(pmkRest);
+
+ return TRUE;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCompositeMoniker::Create
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pmkFirst] --
+// [pmkRest] --
+// [memLoc] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-03-94 kevinro Commented
+//
+// Notes:
+//
+// We assume that *pmkFirst is not capable of collapsing with *pmkRest;
+// otherwise, this would not have been called.
+//
+//----------------------------------------------------------------------------
+CCompositeMoniker FAR *
+CCompositeMoniker::Create( LPMONIKER pmkFirst, LPMONIKER pmkRest)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::Create()\n"));
+
+ //
+ // Create can be called with both pointers being NULL, in which
+ // case the Initialize function need not be called. This is the
+ // case when a CompositeMoniker is being loaded from stream.
+ //
+ // Either both are NULL, or neither is NULL
+ //
+
+ if ((pmkFirst == NULL) || (pmkRest == NULL))
+ {
+ //
+ // One of them is NULL. If the other isn't NULL, return an error
+ //
+
+ if (pmkFirst != pmkRest)
+ {
+ return NULL;
+ }
+ }
+
+ //
+ // Both pointers are not NULL, initialize the moniker
+ //
+
+ CCompositeMoniker FAR * pCM = new CCompositeMoniker();
+
+ if (pCM != NULL)
+ {
+ pCM->AddRef();
+
+ if (pmkFirst != NULL || pmkRest != NULL)
+ {
+ if (!pCM->Initialize( pmkFirst, pmkRest ))
+ {
+ delete pCM;
+ return NULL;
+ }
+ }
+ }
+
+ CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_IMoniker,(IUnknown **)&pCM);
+ return pCM;
+}
+
+
+STDMETHODIMP CCompositeMoniker::QueryInterface(THIS_ REFIID riid,
+ LPVOID FAR* ppvObj)
+{
+ VDATEIID (riid);
+ VDATEPTROUT(ppvObj, LPVOID);
+
+#ifdef _DEBUG
+ if (riid == IID_IDebug)
+ {
+ *ppvObj = &(m_Debug);
+ return NOERROR;
+ }
+#endif
+#ifdef _TRACKLINK_
+ if (IsEqualIID(riid, IID_ITrackingMoniker))
+ {
+ AddRef();
+ *ppvObj = (ITrackingMoniker *) & _tcm;
+ return(S_OK);
+ }
+#endif
+ if (IsEqualIID(riid, CLSID_CompositeMoniker))
+ {
+ // called by IsCompositeMoniker.
+ AddRef();
+ *ppvObj = this;
+ return S_OK;
+ }
+ else if (IsEqualIID(riid, IID_IROTData))
+ {
+ AddRef();
+ *ppvObj = (IROTData *) this;
+ return S_OK;
+ }
+
+ return CBaseMoniker::QueryInterface(riid, ppvObj);
+}
+
+
+STDMETHODIMP_(ULONG) CCompositeMoniker::Release(void)
+{
+ M_PROLOG(this);
+ ULONG ul = m_refs;
+
+ if (InterlockedDecrement((long *)&m_refs) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return ul - 1;
+}
+
+
+STDMETHODIMP CCompositeMoniker::GetClassID (THIS_ LPCLSID lpClassID)
+{
+ VDATEPTROUT(lpClassID, CLSID);
+ *lpClassID = CLSID_CompositeMoniker;
+ return NOERROR;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCompositeMoniker::Load
+//
+// Synopsis: Loads a composite moniker from stream
+//
+// Effects:
+//
+// Arguments: [pStm] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-03-94 kevinro Commented
+//
+// Notes:
+// The serialized form of a composite moniker is a ULONG count of
+// monikers, followed by each non-composite moniker written
+// left to right.
+//
+// WARNING: Be very careful with the refernce counting in this routine.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CCompositeMoniker::Load (THIS_ LPSTREAM pStm)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::Load(%x)\n",this));
+
+ VDATEIFACE(pStm);
+
+ ULONG cMonikers = 0;
+ ULONG n;
+ LPMONIKER pmk;
+ LPMONIKER pmkPrev = NULL;
+ HRESULT hresult;
+
+ //
+ // Monikers are immutable, so this is called only when creating a
+ // moniker, and so we assert if this moniker is not newly created.
+ //
+
+ Assert(m_pmkLeft == NULL && m_pmkRight == NULL);
+
+ if ((m_pmkLeft != NULL) || (m_pmkRight != NULL ))
+ {
+ return(E_UNEXPECTED);
+ }
+
+
+ // There is no collapsing of successive pieces of the moniker, since
+ // this was once written to disk, and the collapsing would have happened
+ // before that.
+
+ hresult = StRead(pStm, (LPVOID)&cMonikers, sizeof(ULONG));
+
+ if (FAILED(hresult))
+ {
+ goto errRet;
+ }
+
+ // some plausibility checking on cMonikers might be appropriate
+ // if there is only one, we shouldn't have had a composite moniker
+
+ Assert( cMonikers >= 2 );
+
+
+ if (cMonikers < 2)
+ {
+ hresult = E_UNEXPECTED;
+ goto errRet;
+ }
+
+ //
+ // Note: n is used 1 based, since this loop does something special on the
+ // last moniker.
+ //
+
+ for (n = 1; n <= cMonikers; n++ )
+ {
+
+ //
+ // After loading the reference count for the new moniker will == 1
+ //
+ hresult = OleLoadFromStream(pStm, IID_IMoniker, (LPVOID FAR*)&pmk);
+
+ if (FAILED(hresult))
+ {
+ goto errRet;
+ }
+
+ //
+ // If this is the last moniker, then it will be the right moniker
+ // to 'this' composite moniker.
+ //
+ if (n == cMonikers) // this is the last moniker read
+ {
+ //
+ // Save away the pointer into the right moniker for this instance
+ // of the composite.
+ // The reference count is OK, since it was set to 1 on creation,
+ // and we are saving it
+ //
+ m_pmkRight = pmk;
+
+ //
+ // AddRef not needed, its already 1, and we are supposed to
+ // exit the loop
+ //
+
+ m_pmkLeft = pmkPrev;
+
+ Assert( pmkPrev != NULL );
+
+ }
+ else if (pmkPrev == NULL)
+ {
+ pmkPrev = pmk;
+ }
+ else
+ {
+ LPMONIKER pmkTemp;
+
+ //
+ // Warning: Here is some tricky stuff. pmkPrev has a reference
+ // of 1 at the moment, because thats how we created it.
+ //
+ // pmk also has a refcount == 1
+ //
+ // We are going to create another composite, of which they will
+ // become members. The Create function is going to increment
+ // both (making them 2).
+ //
+
+ pmkTemp = CCompositeMoniker::Create(pmkPrev,
+ pmk);
+
+ if (pmkTemp == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ goto errRet;
+ }
+
+ //
+ // The new moniker is holding refcounts to both monikers that
+ // are not needed. Releasing these two sets the refcounts
+ // back to 1 like they should be.
+ //
+
+ pmkPrev->Release();
+ pmk->Release();
+
+ //
+ // Now, pmkPrev gets the new composite.
+ //
+
+ pmkPrev = pmkTemp;
+ }
+
+ //
+ // pmk has been given to another pointer. NULL it out in case
+ // there is an error later, so we don't try to release it too
+ // many times.
+ //
+
+ pmk = NULL;
+ }
+
+ //
+ // Exiting at this point leaves the moniker pointed to by pmkPrev
+ //
+
+ return(NOERROR);
+
+errRet:
+ if (pmkPrev != NULL)
+ {
+ pmkPrev->Release();
+ }
+ if (pmk != NULL)
+ {
+ pmk->Release();
+ }
+
+ return hresult;
+}
+
+INTERNAL_(ULONG) CCompositeMoniker::Count(void)
+{
+ M_PROLOG(this);
+
+ CCompositeMoniker *pCMk = IsCompositeMoniker(m_pmkLeft);
+ ULONG cMk = (pCMk) ? pCMk->Count() : 1;
+
+ Assert(m_pmkLeft != NULL);
+
+ pCMk = IsCompositeMoniker(m_pmkRight);
+ cMk += (pCMk) ? pCMk->Count() : 1;
+
+ Assert(cMk >= 2);
+ return cMk;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCompositeMoniker::Save
+//
+// Synopsis: Save the composite to a stream
+//
+// Effects:
+//
+// Arguments: [pStm] --
+// [fClearDirty] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-03-94 kevinro Commented
+//
+// Notes:
+//
+// The serialized form of a composite moniker is a ULONG count of
+// monikers, followed by each non-composite moniker written
+// left to right.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CCompositeMoniker::Save (THIS_ LPSTREAM pStm, BOOL fClearDirty)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::Save(%x)\n",this));
+
+ VDATEIFACE(pStm);
+ ULONG cMonikers; // count of monikers in this composite.
+ HRESULT hresult;
+ LPENUMMONIKER pEnum;
+ LPMONIKER pmk;
+ ULONG i;
+
+ cMonikers = Count();
+
+ hresult = pStm->Write(&cMonikers, sizeof(ULONG), NULL);
+
+ if (FAILED(hresult))
+ {
+ goto errRet;
+ }
+
+ //
+ // Write out left to right using enumerator.
+ //
+
+ hresult = Enum(TRUE, &pEnum);
+
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+
+ if (pEnum != NULL)
+ {
+ for( i = 0; i < cMonikers; i++)
+ {
+ hresult = pEnum->Next(1, &pmk, NULL);
+
+ if (hresult != NOERROR)
+ {
+ if (S_FALSE == hresult)
+ {
+ //
+ // If the enumerator returns S_FALSE, then it has no more
+ // monikers to hand out. This is bad, since we haven't
+ // written out the number of monikers we were supposed to.
+ // Therefore, it is an E_UNEXPECTED error
+ //
+ hresult = E_UNEXPECTED;
+
+ }
+ goto errRet;
+ }
+
+ //
+ // If pmk is NULL, something seriously wrong happened.
+ //
+
+ if (pmk == NULL)
+ {
+ hresult = E_UNEXPECTED;
+ goto errRet;
+ }
+
+ hresult = OleSaveToStream( pmk, pStm );
+
+ pmk->Release();
+
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+ }
+
+ pEnum->Release();
+ }
+ else
+ {
+ //
+ // If we get here, and cMonikers isn't 0, something else happened
+ //
+ if (cMonikers != 0)
+ {
+ hresult = E_UNEXPECTED;
+ }
+ }
+
+errRet:
+ return hresult;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCompositeMoniker::GetSizeMax
+//
+// Synopsis: Return the maximum size required to marshal this composite
+//
+// Effects:
+//
+// Arguments: [pcbSize] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-03-94 kevinro Commented
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CCompositeMoniker::GetSizeMax (ULARGE_INTEGER FAR * pcbSize)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::GetSizeMax(%x)\n",this));
+
+ VDATEPTROUT(pcbSize, ULARGE_INTEGER);
+
+ LPENUMMONIKER pEnum = NULL;
+ LPMONIKER pmk = NULL;
+ HRESULT hresult;
+ ULARGE_INTEGER cbSize2;
+
+
+ //
+ // The composite itself writes out a CLSID and a count of monikers
+ //
+ ULONG cbSize = sizeof(CLSID) + sizeof(ULONG);
+
+ //
+ // Use an enumerator to walk the list of monikers
+ //
+ hresult = Enum(TRUE, &pEnum);
+
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+
+ Assert(pEnum != NULL);
+
+ while (TRUE)
+ {
+ hresult = pEnum->Next(1, &pmk, NULL);
+ if (hresult != NOERROR)
+ {
+ if (hresult == S_FALSE)
+ {
+ //
+ // S_FALSE is the 'done' code
+ //
+
+ hresult = NOERROR;
+ }
+
+ goto errRet;
+ }
+ Assert(pmk != NULL);
+
+ cbSize2.LowPart = cbSize2.HighPart = 0;
+
+ hresult = pmk->GetSizeMax(&cbSize2);
+
+ pmk->Release();
+
+ if (hresult)
+ {
+ goto errRet;
+ }
+
+ //
+ // The sub-GetSizeMax's don't account for the GUID
+ // that OleSaveToStream writes on the monikers behalf.
+ // Therefore, we will add it in on our own.
+ //
+
+ cbSize += cbSize2.LowPart + sizeof(GUID);
+ }
+errRet:
+ if (pEnum)
+ {
+ pEnum->Release();
+ }
+
+ ULISet32(*pcbSize,cbSize);
+ RESTORE_A5();
+ return hresult;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCompositeMoniker::AllButLast
+//
+// Synopsis:
+//
+// returns a moniker that consists of all but the last moniker of this
+// composite. Since a composite must have at least two pieces, this will
+// never be zero, but it may not be a composite.
+//
+// Effects:
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-03-94 kevinro Commented
+// 17-May-94 AlexT Plug memory leak, check for error
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(LPMONIKER)
+CCompositeMoniker::AllButLast(void)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::AllButLast(%x)\n",this));
+
+ LPMONIKER pmk;
+
+ Assert(m_pmkRight != NULL );
+
+ //
+ // Recurse down the right branch of the tree until a non composite moniker
+ // is found. When a non-composite right most moniker is found, return the
+ // left part of the tree. As the recurse unwinds, a new composite is
+ // formed from each intermediate node.
+ //
+ // Yeah, I know, its seems expensive. However, composite monikers are
+ // fairly cheap to allocate (no strings or stuff). The average
+ // composite moniker only has one or two nodes, so this isn't as bad
+ // as you might think. In theory, there are only LOG2(n) nodes created,
+ // where n == number of parts in the composite.
+ //
+
+ CCompositeMoniker *pCMk = IsCompositeMoniker(m_pmkRight);
+ if (pCMk)
+ {
+ LPMONIKER pmkRight;
+
+ pmkRight = pCMk->AllButLast();
+ if (NULL == pmkRight)
+ {
+ // We didn't get back a moniker from AllButLast, even though
+ // pmkRight is a composite moniker. Probably out of memory...
+ mnkDebugOut((DEB_WARN,
+ "CCompositeMoniker::AllButLast recursive call "
+ "returned NULL\n"));
+
+ pmk = NULL;
+ }
+ else
+ {
+ pmk = CCompositeMoniker::Create(m_pmkLeft, pmkRight);
+ pmkRight->Release();
+ }
+ }
+ else
+ {
+ Assert(m_pmkLeft != NULL && "Bad composite moniker");
+ pmk = m_pmkLeft;
+ pmk->AddRef();
+ }
+ return pmk;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCompositeMoniker::Last
+//
+// Synopsis:
+// return the last moniker in the composite list. It is guaranteed to be
+// non-null and non-composite
+//
+// Effects:
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-03-94 kevinro Commented
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(LPMONIKER)
+CCompositeMoniker::Last(void)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::Last(%x)\n",this));
+
+ CCompositeMoniker FAR * pCM = this;
+ CCompositeMoniker FAR * pCMNext;
+
+ //
+ // Run down the right side of the tree, looking for a non-composite
+ // right moniker (the leaf node).
+ //
+
+ while ((pCMNext = IsCompositeMoniker(pCM->m_pmkRight)) != NULL)
+ {
+ pCM = pCMNext;
+ }
+
+ IMoniker *pmk = pCM->m_pmkRight;
+
+ Assert(pmk != NULL && (!IsCompositeMoniker(pmk)));
+
+ pmk->AddRef();
+
+ return pmk;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCompositeMoniker::AllButFirst
+//
+// Synopsis:
+// returns a moniker that consists of all but the first moniker of this
+// composite. Since a composite must have at least two pieces, this will
+// never be zero, but it may not be a composite.
+//
+// Effects:
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-03-94 kevinro Commented
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(LPMONIKER)
+CCompositeMoniker::AllButFirst(void)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::AllButFirst(%x)\n",this));
+
+ LPMONIKER pmk;
+
+ //
+ // Run down the left side of the tree, creating a composite moniker with
+ // everything but the first moniker. See AllButLast for a pithy quote
+ // about the efficiency
+ //
+
+ CCompositeMoniker *pCM = IsCompositeMoniker(m_pmkLeft);
+ if (pCM)
+ {
+ LPMONIKER pmkABF = pCM->AllButFirst();
+
+ pmk = CCompositeMoniker::Create(pmkABF, m_pmkRight);
+
+ pmkABF->Release();
+ }
+ else
+ {
+ pmk = m_pmkRight;
+ pmk->AddRef();
+ }
+ return pmk;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCompositeMoniker::First
+//
+// Synopsis:
+// return the first moniker in the composite list. It is guaranteed to be
+// non-null and non-composite
+//
+// Effects:
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-03-94 kevinro Commented
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(LPMONIKER)
+CCompositeMoniker::First(void)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::First(%x)\n",this));
+
+ CCompositeMoniker *pCM = this;
+ CCompositeMoniker *pCMNext;
+
+ while ((pCMNext = IsCompositeMoniker(pCM->m_pmkLeft)) != NULL)
+ {
+ pCM = pCMNext;
+ }
+
+ IMoniker *pmk = pCM->m_pmkLeft;
+
+ Assert(pmk != NULL && (!IsCompositeMoniker(pmk)));
+
+ pmk->AddRef();
+
+ return pmk;
+}
+
+
+STDMETHODIMP CCompositeMoniker::BindToObject (LPBC pbc,
+ LPMONIKER pmkToLeft, REFIID riidResult, LPVOID FAR* ppvResult)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::BindToObject(%x)\n",this));
+
+ VDATEPTROUT(ppvResult, LPVOID);
+ VDATEIFACE(pbc);
+ VDATEIID(riidResult);
+
+ *ppvResult = NULL;
+
+ if (pmkToLeft)
+ {
+ VDATEIFACE(pmkToLeft);
+ }
+
+ HRESULT hresult = NOERROR;
+ LPRUNNINGOBJECTTABLE prot;
+ *ppvResult = NULL;
+
+ LPMONIKER pmkAllButLast = NULL;
+ LPMONIKER pmkLast = NULL;
+ LPMONIKER pmkNewLeft = NULL;
+
+ // Look for moniker in running objects table if there is nothing to the
+ // left
+
+ if (pmkToLeft == NULL)
+ {
+ hresult = pbc->GetRunningObjectTable( &prot );
+ if (hresult == NOERROR)
+ {
+ LPUNKNOWN pUnk;
+ hresult = prot->GetObject(this, &pUnk);
+ prot->Release();
+ if ((hresult == NOERROR) && (pUnk != NULL))
+ {
+ hresult = pUnk->QueryInterface(riidResult, ppvResult);
+ pUnk->Release();
+ goto errRet;
+ }
+ }
+ else
+ {
+ goto errRet;
+ }
+ }
+
+
+ pmkAllButLast = AllButLast();
+
+ if (pmkAllButLast == NULL)
+ {
+ // The creation must have failed. The only reason we could think of was
+ // out of memory.
+ hresult = E_OUTOFMEMORY;
+ goto errRet;
+ }
+
+ pmkLast = Last();
+ if (pmkLast == NULL)
+ {
+ // The creation must have failed. The only reason we could think of was
+ // out of memory.
+ hresult = E_OUTOFMEMORY;
+ goto errRet1;
+ }
+
+ Assert((pmkLast != NULL) && (pmkAllButLast != NULL));
+
+ if (pmkToLeft != NULL)
+ {
+ // REVIEW: check for error from ComposeWith
+ hresult = pmkToLeft->ComposeWith(pmkAllButLast, FALSE, &pmkNewLeft);
+ if (FAILED(hresult))
+ {
+ goto errRet2;
+ }
+ }
+ else
+ {
+ pmkNewLeft = pmkAllButLast;
+ pmkNewLeft->AddRef();
+ }
+
+ hresult = pmkLast->BindToObject(pbc, pmkNewLeft, riidResult, ppvResult);
+
+errRet2:
+ pmkLast->Release();
+errRet1:
+ pmkAllButLast->Release();
+
+ if (pmkNewLeft != NULL)
+ {
+ pmkNewLeft->Release();
+ }
+
+errRet:
+
+ return hresult;
+}
+
+
+STDMETHODIMP CCompositeMoniker::BindToStorage (LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::BindToStorage(%x)\n",this));
+
+ M_PROLOG(this);
+ VDATEPTROUT(ppvObj,LPVOID);
+ *ppvObj = NULL;
+ VDATEIFACE(pbc);
+ if (pmkToLeft) VDATEIFACE(pmkToLeft);
+ VDATEIID(riid);
+
+ HRESULT hresult = NOERROR;
+
+ LPMONIKER pmkAllButLast = AllButLast();
+ LPMONIKER pmkLast = Last();
+ LPMONIKER pmkNewLeft = NULL ;
+
+ if (pmkToLeft)
+ {
+ hresult = pmkToLeft->ComposeWith(pmkAllButLast, FALSE, &pmkNewLeft);
+ if (hresult) goto errRet;
+ }
+ else
+ {
+ pmkNewLeft = pmkAllButLast;
+ pmkNewLeft->AddRef();
+ }
+
+ hresult = pmkLast->BindToStorage(pbc, pmkNewLeft, riid, ppvObj);
+
+errRet:
+ if (pmkAllButLast) pmkAllButLast->Release();
+ if (pmkLast) pmkLast->Release();
+ if (pmkNewLeft) pmkNewLeft->Release();
+
+ return hresult;
+}
+
+
+
+
+STDMETHODIMP CCompositeMoniker::Reduce (LPBC pbc,
+ DWORD dwReduceHowFar,
+ LPMONIKER FAR* ppmkToLeft,
+ LPMONIKER FAR * ppmkReduced)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::Reduce(%x)\n",this));
+
+ M_PROLOG(this);
+ VDATEPTROUT(ppmkReduced,LPMONIKER);
+ *ppmkReduced = NULL;
+ VDATEIFACE(pbc);
+ if (ppmkToLeft)
+ {
+ VDATEPTROUT(ppmkToLeft,LPMONIKER);
+ if (*ppmkToLeft) VDATEIFACE(*ppmkToLeft);
+ }
+
+ LPMONIKER pmkLeftReduced = NULL;
+ LPMONIKER pmkRightReduced = NULL;
+ CCompositeMoniker FAR * pmkCompositeReduced;
+ SCODE scode1;
+ SCODE scode2;
+
+#ifdef _TRACKLINK_
+ if (!m_fReduceForced && m_fReduced) // already reduced maximally
+#else
+ if (m_fReduced) // already reduced maximally
+#endif
+ {
+ AddRef();
+ *ppmkReduced = this;
+ return ResultFromScode(MK_S_REDUCED_TO_SELF);
+ }
+
+ if (m_pmkLeft)
+ {
+ scode1 = GetScode( m_pmkLeft->Reduce(pbc,
+ dwReduceHowFar,
+ NULL,
+ &pmkLeftReduced));
+ // AssertOutPtrIface(scode1, pmkLeftReduced);
+ if (scode1 != S_OK && scode1 != MK_S_REDUCED_TO_SELF)
+ return ResultFromScode(scode1);
+ }
+
+ if (m_pmkRight)
+ {
+ // SPEC:
+
+ /*
+
+ ppmkToLeft
+
+ [out] On entry, ppmkToLeft points to the moniker that
+ prefixes this one within the composite, that is, the
+ moniker to the left of the current moniker. On exit, the
+ pointer will be NULL or non-NULL. Non-NULL indicates that
+ the previous prefix should be disregarded and the moniker
+ returned through ppmkToLeft should be used as the prefix
+ in its place (this is not usual). NULL indicates that the
+ prefix should not be replaced. Most monikers will NULL
+ out this parameter before returning. The ppmkToLeft
+ parameter is an [in,out] parameter and it must be released
+ before NULLing out. If an error is returned, this
+ parameter must be set to NULL. For more information on
+ [in,out] parameters, see the discussion of parameter types
+ in the section on Memory Management.
+
+ */
+
+ IMoniker *pmkLeftReducedTmp = pmkLeftReduced;
+ pmkLeftReducedTmp->AddRef();
+
+ scode2 = GetScode( m_pmkRight->Reduce(pbc,
+ dwReduceHowFar,
+ &pmkLeftReducedTmp,
+ &pmkRightReduced));
+ // AssertOutPtrIface(scode2, pmkRightReduced);
+
+ if (pmkLeftReducedTmp == NULL)
+ {
+ // prefix should not be replaced
+ // we still have original ref
+ }
+ else
+ {
+ // use pmkLeftReducedTmp as the new left piece
+ pmkLeftReduced->Release(); // the original ref
+ pmkLeftReduced = pmkLeftReducedTmp;
+ }
+
+ if (scode2 != S_OK && scode2 != MK_S_REDUCED_TO_SELF)
+ {
+ if (pmkLeftReduced)
+ pmkLeftReduced->Release();
+ return ResultFromScode(scode2);
+ }
+ }
+ if (scode1 == MK_S_REDUCED_TO_SELF && scode2 == MK_S_REDUCED_TO_SELF)
+ {
+ pmkLeftReduced->Release();
+ pmkRightReduced->Release();
+ AddRef();
+ m_fReduced = TRUE;
+ *ppmkReduced = this;
+ return ResultFromScode(MK_S_REDUCED_TO_SELF);
+ }
+ // No error, and one of the two pieces actually reduced.
+ pmkCompositeReduced = CCompositeMoniker::Create(pmkLeftReduced,
+ pmkRightReduced );
+ pmkLeftReduced->Release();
+ pmkRightReduced->Release();
+ if (pmkCompositeReduced != NULL)
+ pmkCompositeReduced->m_fReduced = TRUE;
+ *ppmkReduced = pmkCompositeReduced;
+ return pmkCompositeReduced == NULL ? E_OUTOFMEMORY : NOERROR;
+}
+
+
+
+
+STDMETHODIMP CCompositeMoniker::ComposeWith (LPMONIKER pmkRight,
+ BOOL fOnlyIfNotGeneric, LPMONIKER FAR* ppmkComposite)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::ComposeWith(%x)\n",this));
+
+ M_PROLOG(this);
+
+ if (fOnlyIfNotGeneric)
+ {
+ return(MK_E_NEEDGENERIC);
+ }
+
+ return CreateGenericComposite( this, pmkRight, ppmkComposite );
+}
+
+
+STDMETHODIMP CCompositeMoniker::Enum (BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::Enum(%x)\n",this));
+
+ M_PROLOG(this);
+ VDATEPTROUT(ppenumMoniker,LPENUMMONIKER);
+ *ppenumMoniker = NULL;
+ *ppenumMoniker = CCompositeMonikerEnum::Create(fForward, this);
+ if (*ppenumMoniker) return NOERROR;
+ return ResultFromScode(E_OUTOFMEMORY);
+}
+
+
+STDMETHODIMP CCompositeMoniker::IsEqual (LPMONIKER pmkOtherMoniker)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::IsEqual(%x)\n",this));
+
+ M_PROLOG(this);
+ VDATEIFACE(pmkOtherMoniker);
+
+ HRESULT hr = S_FALSE;
+ HRESULT hr2;
+ LPENUMMONIKER pEnumMe;
+ LPENUMMONIKER pEnumOther;
+ LPMONIKER pMkMe;
+ LPMONIKER pMkOther;
+
+ // REVIEW: do we call Reduce first? No: spec isssue 330
+
+ CCompositeMoniker *pCMk = IsCompositeMoniker(pmkOtherMoniker);
+ if (pCMk)
+ {
+ hr = Enum(TRUE, &pEnumMe);
+ if (SUCCEEDED(hr))
+ {
+ hr = pmkOtherMoniker->Enum(TRUE, &pEnumOther);
+ if (SUCCEEDED(hr))
+ {
+ // Initialize
+ pEnumMe->Reset();
+ pEnumOther->Reset();
+
+ // Compare successive elements
+ for (;;)
+ {
+ // Fetch the next two elements
+ hr = pEnumMe->Next(1, &pMkMe, NULL);
+ hr2 = pEnumOther->Next(1, &pMkOther, NULL);
+
+ // Compare them
+ if (hr == S_OK && hr2 == S_OK)
+ {
+ if (pMkMe->IsEqual(pMkOther) == S_FALSE)
+ {
+ pMkMe->Release();
+ pMkOther->Release();
+ hr = S_FALSE;
+ break;
+ }
+ }
+
+ // Release the individual monikers
+ if (hr == S_OK)
+ {
+ pMkMe->Release();
+ }
+ if (hr2 == S_OK)
+ {
+ pMkOther->Release();
+ }
+
+ // All elements exhausted
+ if (hr == S_FALSE && hr2 == S_FALSE)
+ {
+ hr = S_OK;
+ break;
+ }
+
+ // One contained fewer elements than the other
+ else if (hr == S_FALSE || hr2 == S_FALSE)
+ {
+ hr = S_FALSE;
+ break;
+ }
+ }
+ pEnumOther->Release();
+ }
+ pEnumMe->Release();
+ }
+ }
+
+ return hr;
+}
+
+// the following is non-recursive version using enumerators.
+#ifdef NONRECURSIVE_ISEQUAL
+ LPENUMMONIKER penumOther = NULL;
+ LPENUMMONIKER penumThis = NULL;
+ LPMONIKER pmkThis = NULL;
+ LPMONIKER pmkOther = NULL;
+
+ HRESULT hresult;
+ SCODE scode1;
+ SCODE scode2;
+
+ if (!IsCompositeMoniker(pmkOtherMoniker))
+ return ResultFromScode(S_FALSE);
+ hresult = Enum(TRUE, &penumThis);
+ if (hresult != NOERROR) goto errRet;
+ hresult = pmkOtherMoniker->Enum(TRUE, &penumOther);
+ if (hresult != NOERROR) goto errRet;
+ // now go through the enumeration, checking IsEqual on the individual
+ // pieces.
+
+ while (TRUE)
+ {
+ hresult = penumThis->Next( 1, &pmkThis, NULL );
+ scode1 = GetScode(hresult);
+ if ((hresult != NOERROR) && (S_FALSE != scode1))
+ {
+ goto errRet;
+ }
+ hresult = penumOther->Next( 1, &pmkOther, NULL );
+ scode2 = GetScode(hresult);
+ if ((hresult != NOERROR) && (S_FALSE != scode2))
+ {
+ goto errRet;
+ }
+ if (scode1 != scode2)
+ {
+ hresult = ResultFromScode(S_FALSE);
+ goto errRet;
+ }
+ if (S_FALSE == scode1)
+ {
+ hresult = NOERROR;
+ goto errRet;
+ }
+ hresult = pmkThis->IsEqual(pmkOther);
+ pmkThis->Release();
+ pmkOther->Release();
+ pmkThis = NULL;
+ pmkOther = NULL;
+ if (hresult != NOERROR) goto errRet;
+ }
+errRet:
+ if (pmkThis) pmkThis->Release();
+ if (pmkOther) pmkOther->Release();
+ if (penumOther) penunOther->Release();
+ if (penumThis) penumThis->Release();
+ return hresult;
+}
+#endif // NONRECURSIVE_ISEQUAL
+
+
+STDMETHODIMP CCompositeMoniker::Hash (LPDWORD pdwHash)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::Hash(%x)\n",this));
+
+ M_PROLOG(this);
+ VDATEPTROUT(pdwHash, DWORD);
+
+ DWORD dwHashLeft;
+ DWORD dwHashRight;
+ m_pmkLeft->Hash(&dwHashLeft);
+ // check for errors
+ m_pmkRight->Hash(&dwHashRight);
+ *pdwHash = dwHashLeft^dwHashRight;
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP CCompositeMoniker::IsRunning
+ (LPBC pbc,
+ LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::IsRunning(%x)\n",this));
+
+ VDATEIFACE(pbc);
+ if (pmkToLeft) VDATEIFACE(pmkToLeft);
+ if (pmkNewlyRunning) VDATEIFACE(pmkNewlyRunning);
+
+ LPMONIKER pmkFirst = First();
+ HRESULT hresult;
+ LPMONIKER pmk = NULL;
+ LPMONIKER pmkLast = NULL;
+ LPRUNNINGOBJECTTABLE prot = NULL;
+
+
+ CFileMoniker FAR * pCFM = IsFileMoniker(pmkFirst);
+ if (pCFM)
+ {
+ CLSID clsid;
+ if (pCFM->IsOle1Class(&clsid))
+ {
+
+ hresult = DdeIsRunning(clsid, pCFM->m_szPath, pbc,
+ pmkToLeft, pmkNewlyRunning);
+ goto errRet;
+ }
+ }
+
+ if (pmkToLeft != NULL)
+ {
+ hresult = pmkToLeft->ComposeWith(this, FALSE, &pmk);
+ if (hresult)
+ goto errRet;
+ hresult = pmk->IsRunning(pbc, NULL, pmkNewlyRunning);
+ }
+ else if (pmkNewlyRunning != NULL)
+ {
+ hresult = pmkNewlyRunning->IsEqual(this);
+ }
+ else
+ {
+ hresult = pbc->GetRunningObjectTable(&prot);
+ if (hresult != NOERROR)
+ goto errRet;
+ hresult = prot->IsRunning(this);
+ if (hresult == NOERROR)
+ goto errRet;
+ pmk = AllButLast();
+ pmkLast = Last();
+ hresult = pmkLast->IsRunning(pbc, pmk, pmkNewlyRunning);
+ }
+errRet:
+ if (pmk) pmk->Release();
+ if (pmkLast) pmkLast->Release();
+ if (prot) prot->Release();
+ if (pmkFirst) pmkFirst->Release();
+
+ return hresult;
+}
+
+
+STDMETHODIMP CCompositeMoniker::GetTimeOfLastChange (LPBC pbc, LPMONIKER pmkToLeft, FILETIME FAR* pfiletime)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::GetTimeOfLastChange(%x)\n",this));
+
+ M_PROLOG(this);
+ VDATEIFACE(pbc);
+ if (pmkToLeft) VDATEIFACE(pmkToLeft);
+ VDATEPTROUT(pfiletime, FILETIME);
+
+ HRESULT hresult;
+ LPMONIKER pmkTemp = NULL;
+ LPMONIKER pmkABL = NULL;
+ LPMONIKER pmkL = NULL;
+ LPRUNNINGOBJECTTABLE prot = NULL;
+
+ if (pmkToLeft == NULL)
+ {
+ pmkTemp = this;
+ AddRef();
+ }
+ else
+ {
+ hresult = CreateGenericComposite( pmkToLeft, this, &pmkTemp );
+ if (hresult != NOERROR) goto errRet;
+ }
+ hresult = pbc->GetRunningObjectTable(& prot);
+ if (hresult != NOERROR) goto errRet;
+ hresult = prot->GetTimeOfLastChange( pmkTemp, pfiletime);
+ if (hresult != MK_E_UNAVAILABLE) goto errRet;
+
+ pmkTemp->Release(); pmkTemp = NULL;
+
+ pmkABL = AllButLast();
+ pmkL = Last();
+ Assert(pmkABL != NULL);
+ if (pmkToLeft == NULL)
+ {
+ pmkTemp = pmkABL;
+ pmkABL->AddRef();
+ }
+ else
+ {
+ hresult = CreateGenericComposite(pmkToLeft, pmkABL, &pmkTemp);
+ if (hresult != NOERROR) goto errRet;
+ }
+ hresult = pmkL->GetTimeOfLastChange(pbc, pmkTemp, pfiletime);
+errRet:
+ if (pmkTemp) pmkTemp->Release();
+ if (pmkABL) pmkABL->Release();
+ if (pmkL) pmkL->Release();
+ if (prot) prot->Release();
+ return hresult;
+}
+
+
+STDMETHODIMP CCompositeMoniker::Inverse (LPMONIKER FAR* ppmk)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::Inverse(%x)\n",this));
+
+ M_PROLOG(this);
+ VDATEPTROUT(ppmk, LPMONIKER);
+ *ppmk = NULL;
+
+ HRESULT hresult;
+ LPMONIKER pmkLeftInverse;
+ LPMONIKER pmkRightInverse;
+
+ hresult = m_pmkLeft->Inverse(&pmkLeftInverse);
+ // AssertOutPtrIface(hresult, pmkLeftInverse);
+ if (hresult != NOERROR) return hresult;
+ hresult = m_pmkRight->Inverse(&pmkRightInverse);
+ // AssertOutPtrIface(hresult, pmkRightInverse);
+ if (hresult != NOERROR)
+ {
+ pmkLeftInverse->Release();
+ return hresult;
+ }
+ hresult = CreateGenericComposite( pmkRightInverse, pmkLeftInverse, ppmk);
+ pmkRightInverse->Release();
+ pmkLeftInverse->Release();
+ return hresult;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCompositeMoniker::CommonPrefixWith
+//
+// Synopsis: This method determines the common prefix between this moniker
+// and the provided moniker
+//
+// Effects:
+//
+// Arguments: [pmkOther] -- Moniker to determine common prefix with
+// [ppmkPrefix] -- Outputs moniker with common prefix
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-03-94 kevinro Commented
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CCompositeMoniker::CommonPrefixWith (LPMONIKER pmkOther,
+ LPMONIKER FAR* ppmkPrefix)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::CommonPrefixWith(%x)\n",this));
+
+ VDATEPTROUT(ppmkPrefix,LPMONIKER);
+ VDATEIFACE(pmkOther);
+
+ CCompositeMoniker FAR * pCCMOther;
+ LPMONIKER pmkFirst = NULL;
+ LPMONIKER pmkRest = NULL;
+ LPMONIKER pmkOtherFirst = NULL;
+ LPMONIKER pmkOtherRest = NULL;
+ LPMONIKER pmkResult = NULL;
+ LPMONIKER pmkResult2 = NULL;
+ HRESULT hresult = E_UNEXPECTED;
+ HRESULT hresult2;
+
+ *ppmkPrefix = NULL;
+
+ pmkFirst = First();
+
+ if (pmkFirst == NULL)
+ {
+ goto errRet;
+ }
+
+ //
+ // If the other moniker is also a composite, then we need to recurse
+ // down both lists to find the common prefix
+ //
+
+ pCCMOther = IsCompositeMoniker(pmkOther);
+
+ if (pCCMOther)
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "::CommonPrefixWith C(%x) and C(%x)\n",
+ this,
+ pmkOther));
+
+ //
+ // For each element of the composite, get the common prefix
+ //
+
+ pmkOtherFirst = pCCMOther->First();
+
+ if(pmkOtherFirst == NULL)
+ {
+ goto errRet;
+ }
+
+ //
+ // We have both 'first' monikers from the composite.
+ //
+ hresult = pmkFirst->CommonPrefixWith(pmkOtherFirst, &pmkResult);
+
+ if (FAILED(hresult))
+ {
+ goto errRet;
+ }
+
+ //
+ // If the monikers are the same, then recurse to get the common
+ // prefix of the rest.
+ // It is possible that the rest won't be common, in which case we need
+ // to return just pmkResult.
+ //
+
+ if (MK_S_US == hresult)
+ {
+ pmkOtherRest = pCCMOther->AllButFirst();
+
+ if (pmkOtherRest == NULL)
+ {
+ goto errRet;
+ }
+
+ pmkRest = AllButFirst();
+
+ if (pmkRest == NULL)
+ {
+ goto errRet;
+ }
+
+ hresult = pmkRest->CommonPrefixWith(pmkOtherRest, &pmkResult2);
+
+ //
+ // If hresult == MK_E_NOPREFIX, then pmkResult holds the entire
+ // prefix. In this case, we need to convert the hresult into
+ // another error code.
+ //
+ // If hresult == MK_S_US, MK_S_HIM, or MK_S_ME, then composing
+ // to the end of pmkResult and returning hresult will do the
+ // correct thing.
+ //
+
+ if (hresult == MK_E_NOPREFIX)
+ {
+ //
+ // There was no additional prefix match, return the
+ // current result
+ //
+
+ *ppmkPrefix = pmkResult;
+ pmkResult->AddRef();
+
+ hresult = NOERROR;
+
+ goto errRet;
+
+ } else if (FAILED(hresult))
+ {
+ goto errRet;
+ }
+
+
+ //
+ // Since MK_E_NOPREFIX was not the return error, and
+ // the call didn't fail, then the other moniker must have returned
+ // a prefix. Compose it with the existing result
+ //
+ // If the compose succeeds, then return the existing hresult.
+ // We are either going to return MK_S_HIM, MK_S_US, MK_S_ME, or
+ // NOERROR (or some other error we don't know.
+ //
+
+ hresult2 = pmkResult->ComposeWith(pmkResult2, FALSE, ppmkPrefix);
+
+ if (FAILED(hresult2))
+ {
+ //
+ // Compose with failed. Convert hresult, which is the return
+ // value, into hresult2
+ //
+
+ hresult = hresult2;
+ }
+
+ goto errRet;
+ }
+ else if ((hresult == MK_S_HIM) || (hresult == MK_S_ME))
+ {
+ //
+ // The common prefix was either him or me, therefore the
+ // proper thing to do is to return the result. However, we
+ // need to change the hresult, since the result is a prefix
+ // of one of the composites. (Try that 3 times fast)
+ //
+ *ppmkPrefix = pmkResult;
+
+ pmkResult->AddRef();
+
+ hresult = NOERROR;
+ }
+ goto errRet;
+ }
+ else
+ {
+ hresult = pmkFirst->CommonPrefixWith(pmkOther, ppmkPrefix);
+
+ // if the first part of me is the common prefix, then the prefix
+ // is a subpart of me since I am composite. The actual prefix is
+ // NOT me, since only the first moniker was prefix
+
+ if (MK_S_ME == hresult)
+ {
+ hresult = NOERROR;
+ }
+ else if (hresult == MK_S_US)
+ {
+ //
+ // If the First moniker returned MK_S_US, then the actual
+ // return should be MK_S_HIM, since this composite has additional
+ // parts that weren't considered by the call.
+ //
+ hresult = MK_S_HIM;
+ }
+ }
+errRet:
+ if (pmkFirst) pmkFirst->Release();
+ if (pmkRest) pmkRest->Release();
+ if (pmkOtherFirst) pmkOtherFirst->Release();
+ if (pmkOtherRest) pmkOtherRest->Release();
+ if (pmkResult) pmkResult->Release();
+ if (pmkResult2) pmkResult2->Release();
+ return hresult;
+}
+
+
+
+HRESULT ComposeWithEnum( LPMONIKER pmkLeft, LPENUMMONIKER penum,
+ LPMONIKER FAR * ppmkComposite )
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::ComposeWithEnum(pmkLeft=%x,penum=%x)\n",
+ pmkLeft,
+ penum));
+
+ LPMONIKER pmk = NULL;
+ LPMONIKER pmkTempLeft = pmkLeft;
+ LPMONIKER pmkTempComp = NULL;
+ HRESULT hresult;
+
+ *ppmkComposite = NULL;
+ pmkTempLeft->AddRef();
+ while ((hresult = penum->Next(1, &pmk, NULL)) == NOERROR)
+ {
+ hresult = pmkTempLeft->ComposeWith(pmk, FALSE, &pmkTempComp);
+ pmk->Release();
+ pmkTempLeft->Release();
+ pmkTempLeft=pmkTempComp; // no need to release pmkTempComp
+ if (hresult != NOERROR) goto errRet;
+ }
+errRet:
+ if (GetScode(hresult) == S_FALSE) hresult = NOERROR;
+ if (hresult == NOERROR) *ppmkComposite = pmkTempLeft;
+ else pmkTempLeft->Release();
+ return hresult;
+}
+
+
+
+HRESULT InverseFromEnum( LPENUMMONIKER penum, LPMONIKER FAR * ppmkInverse)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::InverseFromEnum(%x)\n",penum));
+
+ LPMONIKER pmk = NULL;
+ LPMONIKER pmkInverse = NULL;
+ LPMONIKER pmkTailInverse = NULL;
+ HRESULT hresult;
+
+ *ppmkInverse = NULL;
+
+ hresult = penum->Next(1, &pmk, NULL );
+ if (hresult == NOERROR)
+ {
+ hresult = InverseFromEnum( penum, &pmkTailInverse);
+ if (hresult != NOERROR)
+ goto errRet;
+ hresult = pmk->Inverse(&pmkInverse);
+ // AssertOutPtrIface(hresult, pmkInverse);
+ if (hresult != NOERROR) goto errRet;
+ if (pmkTailInverse)
+ hresult = pmkTailInverse->ComposeWith( pmkInverse, FALSE, ppmkInverse );
+ else
+ *ppmkInverse = pmkInverse;
+ }
+errRet:
+ if (GetScode(hresult) == S_FALSE) hresult = NOERROR;
+ if (pmk) pmk->Release();
+ if (pmkTailInverse) pmkTailInverse->Release();
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCompositeMoniker::RelativePathTo
+//
+// Synopsis: Determines the relative path to pmkOther
+//
+// Effects:
+//
+// Arguments: [pmkOther] -- moniker to which to find relative path
+// [ppmkRelPath] -- placeholder for returned moniker
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Derivation: IMoniker
+//
+// Algorithm: There are two major cases - B is or is not a composite moniker.
+//
+// * * *
+//
+// If both monikers are composite monikers, we compare their
+// component monikers. Using the following notation for the
+// monikers A and B:
+//
+// (a[0], a[1], a[2], ... a[m]) and (b[0], b[1], b[2], ... b[n])
+//
+// We find the first pair (a[i], b[i]) such that a[i] != b[i].
+//
+// Case 1:
+// If i == 0, then no component monikers match.
+// Case 1A:
+// If we can form a relative path between a[0] and b[0], we
+// can construct a correct relative path between A and B by
+// combining (in order):
+//
+// !(a[1], ... a[m]) - inverse of the remaining elements of A
+// (can be NULL)
+// (!a[0], b[0]) - relative path between a[0] and b[0]
+// (b[1], ... b[n]) - remaining elements of B
+//
+// Case 1B:
+// Else there is no relative path and we just return B as the
+// relative path and MK_S_HIM as the HRESULT
+//
+// Case 2:
+// Else if (a[i] != NULL) && (b[i] != NULL) then both monikers
+// have leftover pieces. We can construct a correct relative
+// path by combining (in order):
+//
+// !(a[i+1], ... a[m]) - inverse of remaining elements of A
+// !a[i]
+// b[i]
+// (b[i+1], ... b[n]) - remaining elements of B
+//
+// Case 3:
+// Else if (a[i] != NULL) && (b[i] == NULL) then B is a prefix
+// of A. We can construct a correct relative path by combining:
+//
+// !(a[i+1], ... a[m]) - inverse of remaining elements of A
+// !a[i]
+//
+// Note that this is just the first two steps of the previous
+// case.
+//
+// Case 4:
+// Else if (a[i] == NULL) && (b[i] != NULL) then A is a prefix
+// of B. We can construct a correct relative path by combining:
+//
+// b[i]
+// (b[i+1], ... b[n]) - remaining elements of B
+//
+// Case 5:
+// Else if (a[i] == NULL) && (b[i] == NULL) then A == B. We
+// return B as the relative moniker and MK_S_HIM as the HRESULT.
+//
+// * * *
+//
+// If B is not a composite moniker, we compare the first
+// component of A to B. Using the following notation:
+//
+// (a[0], a[1], a[2], ... a[m]) and B (not a composite)
+//
+// Case 6:
+// If a[0] == B, then B is a prefix of A. We can construct the
+// correct relative path as:
+//
+// !(a[1], ... a[m]) - inverse of remaining elements of A
+//
+// Case 7:
+// Else if we can form a relative path between a[0] and B, we
+// can construct a relative path between A and B by combining
+// (in order):
+//
+// !(a[1], ... a[m]) - inverse of remaining elements of A
+// (!a[0], B) - relative path between a[0] and B
+//
+// Case 8:
+// Else there is no relative path between a[0] and B so we just
+// return B as the relative moniker and MK_S_HIM as the HRESULT
+//
+// History: 2-03-94 kevinro Commented
+// 07/10/94 AlexT Handle pmkOther == this case
+// 10/21/94 AlexT Rewrite, plug leaks, add Algorithm
+//
+// Notes: InverseFromEnum can return S_OK with an out moniker of NULL
+// (if there are no more elements to enumerate)
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CCompositeMoniker::RelativePathTo (LPMONIKER pmkOther,
+ LPMONIKER FAR* ppmkRelPath)
+{
+ mnkDebugOut((DEB_TRACE,
+ "%p _IN CCompositeMoniker::RelativePathTo (%p, %p)\n",
+ this, pmkOther, ppmkRelPath));
+ VDATEPTROUT(ppmkRelPath,LPMONIKER);
+ VDATEIFACE(pmkOther);
+
+ *ppmkRelPath = NULL;
+
+ LPENUMMONIKER pEnumThis; // Enumerator for this moniker's components
+ HRESULT hr;
+ hr = Enum(TRUE, &pEnumThis);
+
+ if (NOERROR == hr)
+ {
+ LPMONIKER pmkThisElement; // Next element of this moniker
+
+ hr = pEnumThis->Next(1, &pmkThisElement, NULL);
+ Assert(NOERROR == hr && "Moniker enumeration failure");
+
+ if (IsCompositeMoniker(pmkOther))
+ {
+ LPENUMMONIKER pEnumOther; // Enumerator for other moniker's
+ // components
+ hr = pmkOther->Enum(TRUE, &pEnumOther);
+ if (NOERROR == hr)
+ {
+ LPMONIKER pmkOtherElement; // Next element of other moniker
+ BOOL fMatch = FALSE; // Did any components match?
+
+ // we now have enumerators for both this and pmkOther
+ Assert(pEnumThis && pEnumOther && "Bad return values");
+
+ hr = pEnumOther->Next(1, &pmkOtherElement, NULL);
+ Assert(NOERROR == hr && "Moniker enumeration failure");
+
+ // find the first element pair that aren't equal
+ do
+ {
+ if (pmkThisElement->IsEqual(pmkOtherElement) != NOERROR)
+ {
+ // moniker elements aren't equal
+ break;
+ }
+
+ fMatch = TRUE; // at least one element pair matched
+ pmkThisElement->Release();
+ pmkOtherElement->Release();
+
+ pEnumThis->Next(1, &pmkThisElement, NULL);
+ pEnumOther->Next(1, &pmkOtherElement, NULL);
+ } while (pmkThisElement != NULL && pmkOtherElement != NULL);
+
+ if (!fMatch)
+ {
+ // Case 1: No component monikers matched
+ LPMONIKER pmkBetween; // Relative path between this
+ // element and other element
+
+ hr = pmkThisElement->RelativePathTo(pmkOtherElement,
+ &pmkBetween);
+ if (NOERROR == hr)
+ {
+ // Case 1A: There is a relative path from first
+ // element of this to first element of pmkOther
+ LPMONIKER pmkInverse; // Inverse of remaining elements
+ // of this moniker
+ hr = InverseFromEnum(pEnumThis, &pmkInverse);
+
+ if (SUCCEEDED(hr))
+ {
+ if (NULL == pmkInverse)
+ {
+ // There were no remaining elements
+ hr = ComposeWithEnum(pmkBetween, pEnumOther,
+ ppmkRelPath);
+ }
+ else
+ {
+ LPMONIKER pmkTemp; // Inverse + Between
+
+ // + relative path from this element to
+ // Other element
+ hr = pmkInverse->ComposeWith(pmkBetween,
+ FALSE,
+ &pmkTemp);
+ if (SUCCEEDED(hr))
+ {
+ // + remaining elements of Other
+ hr = ComposeWithEnum(pmkTemp,
+ pEnumOther,
+ ppmkRelPath);
+ pmkTemp->Release();
+ }
+ pmkInverse->Release();
+ }
+ }
+ pmkBetween->Release();
+ }
+ else if (MK_S_HIM == hr)
+ {
+ // Case 1B: There is no relative path between the
+ // elements - return pmkOther and MK_S_HIM
+ pmkBetween->Release();
+
+ pmkOther->AddRef();
+ *ppmkRelPath = pmkOther;
+ Assert(MK_S_HIM == hr && "Bad logic");
+ }
+ else
+ {
+ // error case; nothing to do
+ Assert(FAILED(hr) && "Unexpected success!");
+ }
+ }
+ else if (pmkThisElement != NULL)
+ {
+ // Case 2 and 3: Both monikers have remaining pieces or
+ // pmkOther is a prefix of this
+ LPMONIKER pmkInverse; // Inverse of remaining elements
+ // of this moniker
+ hr = InverseFromEnum(pEnumThis, &pmkInverse);
+
+ if (SUCCEEDED(hr))
+ {
+ LPMONIKER pmkElementInverse; // Inverse of current
+ // element of this
+ hr = pmkThisElement->Inverse(&pmkElementInverse);
+ if (SUCCEEDED(hr))
+ {
+ LPMONIKER pmkTemp; // partial result
+
+ if (NULL == pmkInverse)
+ {
+ // There were no remaining elements of this
+ // moniker - we begin with the element inverse
+ pmkTemp = pmkElementInverse;
+ }
+ else
+ {
+ hr = pmkInverse->ComposeWith(
+ pmkElementInverse,
+ FALSE, &pmkTemp);
+ pmkElementInverse->Release();
+ }
+
+ if (NULL == pmkOtherElement)
+ {
+ // Case 3: pmkOther is a prefix of this
+ *ppmkRelPath = pmkTemp;
+ }
+ else if (SUCCEEDED(hr))
+ {
+ // Case 2: both monikers had remaining pieces
+ LPMONIKER pmkTemp2; // partial result
+
+ // + other element
+ hr = pmkTemp->ComposeWith(pmkOtherElement,
+ FALSE,
+ &pmkTemp2);
+ if (SUCCEEDED(hr))
+ {
+ // + remaining other elements
+ hr = ComposeWithEnum(pmkTemp2, pEnumOther,
+ ppmkRelPath);
+
+ pmkTemp2->Release();
+ }
+ pmkTemp->Release();
+ }
+ }
+
+ if (NULL != pmkInverse)
+ {
+ pmkInverse->Release();
+ }
+ }
+ }
+ else if (pmkOtherElement != NULL)
+ {
+ // Case 4: this is a prefix of pmkOther
+ hr = ComposeWithEnum(pmkOtherElement, pEnumOther,
+ ppmkRelPath);
+ }
+ else
+ {
+ // Case 5: this and pmkOther are equal
+ pmkOther->AddRef();
+ *ppmkRelPath = pmkOther;
+ hr = MK_S_HIM;
+ }
+
+ if (NULL != pmkOtherElement)
+ {
+ pmkOtherElement->Release();
+ }
+ pEnumOther->Release();
+ }
+ }
+ else
+ {
+ // pmkrOther is not a composite moniker
+ hr = pmkThisElement->IsEqual(pmkOther);
+ if (NOERROR == hr)
+ {
+ // Case 6: first element of this equals pmkOther; pmkOther
+ // is a prefix of this
+
+ hr = InverseFromEnum(pEnumThis, ppmkRelPath);
+ if (SUCCEEDED(hr) && (NULL == *ppmkRelPath))
+ {
+ // There were no more elements to enumerate; return
+ // pmkOther as the relative path
+ pmkOther->AddRef();
+ *ppmkRelPath = pmkOther;
+ hr = MK_S_HIM;
+ }
+ }
+ else
+ {
+ LPMONIKER pmkBetween;
+ hr = pmkThisElement->RelativePathTo(pmkOther, &pmkBetween);
+ if (NOERROR == hr)
+ {
+ // Case 7: There is a relative path between first element
+ // of this and pmkOther
+ LPMONIKER pmkInverse; // Inverse of remaining elements
+ // of this moniker
+ hr = InverseFromEnum(pEnumThis, &pmkInverse);
+ if (SUCCEEDED(hr))
+ {
+ if (NULL == pmkInverse)
+ {
+ *ppmkRelPath = pmkBetween;
+ pmkBetween = NULL;
+ }
+ else
+ {
+ hr = pmkInverse->ComposeWith(pmkBetween, FALSE,
+ ppmkRelPath);
+ pmkInverse->Release();
+ }
+ }
+ }
+ else if (MK_S_HIM == hr)
+ {
+ // Case 8: There is no relative path between first
+ // element of this and pmkOther (which is pmkBetween),
+ // return pmkOther and MK_S_HIM
+ *ppmkRelPath = pmkBetween;
+ pmkBetween = NULL;
+ Assert(NOERROR == pmkOther->IsEqual(*ppmkRelPath) &&
+ "Bad logic");
+ Assert(MK_S_HIM == hr && "Bad logic");
+ }
+ else
+ {
+ // error case; nothing to do
+ Assert(FAILED(hr) && "Unexpected success!");
+ }
+
+ if (NULL != pmkBetween)
+ {
+ pmkBetween->Release();
+ }
+ }
+ }
+
+ if (NULL != pmkThisElement)
+ {
+ pmkThisElement->Release();
+ }
+
+ pEnumThis->Release();
+ }
+
+ mnkDebugOut((DEB_TRACE,
+ "%p OUT CCompositeMoniker::RelativePathTo(%lx) [%p]\n",
+ this, hr, *ppmkRelPath));
+ return(hr);
+}
+
+STDMETHODIMP CCompositeMoniker::GetDisplayName (LPBC pbc,
+ LPMONIKER pmkToLeft, LPWSTR FAR* lplpszDisplayName)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::GetDisplayName(%x)\n",this));
+
+ M_PROLOG(this);
+ VDATEPTROUT(lplpszDisplayName, LPWSTR);
+ *lplpszDisplayName = NULL;
+ //REVIEW MM3 Find out who is calling this with pbc == NULL and get them
+ // to stop it.
+ VDATEIFACE(pbc);
+ if (pmkToLeft) VDATEIFACE(pmkToLeft);
+
+ LPWSTR lpszToLeft = NULL;
+ LPWSTR lpszLeft = NULL;
+ LPWSTR lpszRight = NULL;
+ LPWSTR lpsz;
+ HRESULT hresult;
+
+ int n1, n2, n3;
+
+ // No error checking yet
+
+ if (pmkToLeft)
+ {
+ hresult = pmkToLeft->GetDisplayName( pbc, NULL, &lpszToLeft );
+ // AssertOutPtrParam(hresult, lpszToLeft);
+ if (hresult != NOERROR)
+ goto errRtn;
+ }
+ hresult = m_pmkLeft->GetDisplayName(pbc, NULL, &lpszLeft);
+ // AssertOutPtrParam(hresult, lpszLeft);
+ if (hresult != NOERROR)
+ goto errRtn;
+ hresult = m_pmkRight->GetDisplayName(pbc, NULL, &lpszRight);
+ // AssertOutPtrParam(hresult, lpszRight);
+ if (hresult != NOERROR)
+ goto errRtn;
+
+ if (lpszToLeft) n1 = lstrlenW(lpszToLeft);
+ else n1 = 0;
+ n2 = lstrlenW(lpszLeft);
+ n3 = lstrlenW(lpszRight);
+
+ lpsz = (WCHAR *)
+ CoTaskMemAlloc(sizeof(WCHAR) * (n1 + n2 + n3 + 1));
+
+ if (lpsz == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+ *lplpszDisplayName = lpsz;
+
+ if (n1) _fmemmove( lpsz, lpszToLeft, n1 * sizeof(WCHAR));
+
+ lpsz += n1;
+
+ _fmemmove( lpsz, lpszLeft, n2 * sizeof(WCHAR));
+
+ lpsz += n2;
+
+ _fmemmove( lpsz, lpszRight, (n3 + 1) * sizeof(WCHAR));
+
+errRtn:
+
+ CoTaskMemFree(lpszToLeft);
+ CoTaskMemFree(lpszLeft);
+ CoTaskMemFree(lpszRight);
+ return hresult;
+}
+
+
+STDMETHODIMP CCompositeMoniker::ParseDisplayName (LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR lpszDisplayName, ULONG FAR* pchEaten, LPMONIKER FAR* ppmkOut)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::ParseDisplayName(%x)\n",this));
+
+ M_PROLOG(this);
+ VDATEPTROUT(ppmkOut,LPMONIKER);
+ *ppmkOut = NULL;
+ VDATEIFACE(pbc);
+ if (pmkToLeft) VDATEIFACE(pmkToLeft);
+ VDATEPTRIN(lpszDisplayName, WCHAR);
+ VDATEPTROUT(pchEaten,ULONG);
+
+ HRESULT hresult = NOERROR;
+
+ LPMONIKER pmkAllButLast = AllButLast();
+ LPMONIKER pmkLast = Last();
+ LPMONIKER pmkNewLeft = NULL ;
+
+ Assert((pmkLast != NULL) && (pmkAllButLast != NULL));
+ if (pmkToLeft) pmkToLeft->ComposeWith(pmkAllButLast, FALSE, &pmkNewLeft);
+ // REVIEW: check for error from ComposeWith
+ else
+ {
+ pmkNewLeft = pmkAllButLast;
+ pmkNewLeft->AddRef();
+ }
+
+ hresult = pmkLast->ParseDisplayName(pbc, pmkNewLeft, lpszDisplayName,
+ pchEaten, ppmkOut);
+ // AssertOutPtrIface(hresult, *ppmkOut);
+
+ pmkAllButLast->Release();
+ pmkLast->Release();
+ if (pmkNewLeft) pmkNewLeft->Release();
+
+ return hresult;
+}
+
+
+STDMETHODIMP CCompositeMoniker::IsSystemMoniker (THIS_ LPDWORD pdwType)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::IsSystemMoniker(%x)\n",this));
+
+ M_PROLOG(this);
+ VDATEPTROUT(pdwType,DWORD);
+
+ *pdwType = MKSYS_GENERICCOMPOSITE;
+ return NOERROR;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCompositeMoniker::GetComparisonData
+//
+// Synopsis: Get comparison data for registration in the ROT
+//
+// Arguments: [pbData] - buffer to put the data in.
+// [cbMax] - size of the buffer
+// [pcbData] - count of bytes used in the buffer
+//
+// Returns: NOERROR
+// E_OUTOFMEMORY
+//
+// Algorithm: First verify buffer is big enough for the composite moniker
+// class id. Put that into the buffer. Then put the left part
+// into the buffer. Finally put the right part into the buffer.
+//
+// History: 03-Feb-95 ricksa Created
+//
+// Note: Validating the arguments is skipped intentionally because this
+// will typically be called internally by OLE with valid buffers.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CCompositeMoniker::GetComparisonData(
+ byte *pbData,
+ ULONG cbMax,
+ ULONG *pcbData)
+{
+ HRESULT hr = E_OUTOFMEMORY;
+ ULONG cOrigMax = cbMax;
+ ULONG cSizeHolder;
+
+ BEGIN_BLOCK
+
+ // Can buffer hold the clsid?
+ if (cbMax < sizeof(CLSID))
+ {
+ // No - so we are out of here;
+ mnkDebugOut((DEB_ERROR,
+ "CCompositeMoniker::GetComparisonData buffer not big enough"
+ " for CLSID\n"));
+ EXIT_BLOCK;
+ }
+
+ cbMax -= sizeof(CLSID);
+
+ memcpy(pbData, &CLSID_CompositeMoniker, sizeof(CLSID));
+
+ pbData += sizeof(CLSID);
+
+ hr = BuildRotData(NULL, m_pmkLeft, pbData, cbMax, &cSizeHolder);
+
+ if (FAILED(hr))
+ {
+ // No - so we are out of here;
+ mnkDebugOut((DEB_ERROR,
+ "CCompositeMoniker::GetComparisonData BuildRotData of left"
+ " failed %lx\n", hr));
+ EXIT_BLOCK;
+ }
+
+ cbMax -= cSizeHolder;
+ pbData += cSizeHolder;
+
+ hr = BuildRotData(NULL, m_pmkRight, pbData, cbMax, &cSizeHolder);
+
+#if DBG == 1
+ if (FAILED(hr))
+ {
+ mnkDebugOut((DEB_ERROR,
+ "CCompositeMoniker::GetComparisonData BuildRotData of right"
+ " failed %lx\n", hr));
+ }
+#endif // DBG == 1
+
+ cbMax -= cSizeHolder;
+
+ END_BLOCK;
+
+ *pcbData = (SUCCEEDED(hr)) ? cOrigMax - cbMax : 0;
+
+ return hr;
+}
+
+
+
+
+/*
+ * Concatenate makes a composite moniker without ever calling
+ * ComposeWith on the individual pieces.
+ */
+
+STDAPI Concatenate( LPMONIKER pmkFirst, LPMONIKER pmkRest,
+ LPMONIKER FAR* ppmkComposite )
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::Concatentate(pmkFirst=%x,pmkRest%x)\n",
+ pmkFirst,
+ pmkRest));
+
+ LPMONIKER pmkConcat = CCompositeMoniker::Create( pmkFirst, pmkRest);
+ *ppmkComposite = pmkConcat;
+
+ if (pmkConcat == NULL)
+ {
+ return ResultFromScode(S_OOM);
+ }
+ // Create did the AddRef
+
+ return NOERROR;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateGenericComposite
+//
+// Synopsis: Creates a generic composite from two other monikers
+//
+// Effects:
+//
+// Arguments: [pmkFirst] --
+// [pmkRest] --
+// [ppmkComposite] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-03-94 kevinro Commented
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CreateGenericComposite( LPMONIKER pmkFirst, LPMONIKER pmkRest,
+ LPMONIKER FAR * ppmkComposite )
+{
+ OLETRACEIN((API_CreateGenericComposite, PARAMFMT("pmkFirst = %p, pmkRest= %p, ppmkComposite= %p"),
+ pmkFirst, pmkRest, ppmkComposite));
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::CreateGenericComposite(First=%x,Rest=%x)\n",
+ pmkFirst,
+ pmkRest));
+
+ LPMONIKER pmkAllButFirstOfRest = NULL;
+ LPMONIKER pmkFirstOfRest = NULL;
+ LPMONIKER pmkAllButLastOfFirst = NULL;
+ LPMONIKER pmkLastOfFirst = NULL;
+ LPMONIKER pmk = NULL;
+ LPMONIKER pmk2 = NULL;
+
+ CCompositeMoniker *pCMk = NULL;
+ CCompositeMoniker *pCMkRest = NULL;
+
+ HRESULT hresult;
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IMoniker,(IUnknown **)&pmkFirst);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IMoniker,(IUnknown **)&pmkRest);
+
+ //
+ // Initialize ppmkComposite. Might return in the middle of this
+ // routine, so be sure its NULL in the error case
+ //
+
+ *ppmkComposite = NULL;
+
+
+ //
+ // If both pointers are NULL, return a NULL composite
+ //
+ if ((pmkFirst == NULL) && (pmkRest == NULL))
+ {
+ hresult = NOERROR;
+ goto errRtn;
+ }
+
+ //
+ // Otherwise, if one pointer is NULL, return the other as the
+ // composite.
+ //
+ if (pmkFirst == NULL)
+ {
+ *ppmkComposite = pmkRest;
+ pmkRest->AddRef();
+ hresult = NOERROR;
+ goto errRtn;
+ }
+
+ if (pmkRest == NULL)
+ {
+ *ppmkComposite = pmkFirst;
+ pmkFirst->AddRef();
+ hresult = NOERROR;
+ goto errRtn;
+ }
+
+
+ //
+ // Handle the two cases where pmkFirst is NOT a composite
+ //
+
+ pCMk = IsCompositeMoniker( pmkFirst );
+ if (!pCMk)
+ {
+ //
+ // If pmkRest is not a composite, then we have two
+ // monikers that are considered 'simple' monikers.
+ //
+
+ pCMk = IsCompositeMoniker( pmkRest );
+ if (!pCMk)
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "::CreateGenericComposite( S(%x) o S(%x) )\n",
+ pmkFirst,
+ pmkRest));
+
+ // Case 1: two simple monikers
+
+ hresult = pmkFirst->ComposeWith(pmkRest, TRUE, ppmkComposite);
+
+ if (hresult == MK_E_NEEDGENERIC)
+ {
+ Assert(*ppmkComposite == NULL);
+ hresult = Concatenate(pmkFirst, pmkRest, ppmkComposite);
+ goto errRtn;
+ }
+ }
+ else
+ {
+
+ //
+ // Case 2: S o C(b1, b2, b3).
+ //
+ // Compose S with b1,
+ // then
+ // Compose ( S o b1 ) with C( b2, b3, ...)
+ //
+ //
+
+
+ mnkDebugOut((DEB_ITRACE,
+ "::CreateGenericComposite( S(%x) o C(%x) )\n",
+ pmkFirst,
+ pmkRest));
+
+ //
+ // Since the right side is a composite, the following should
+ // always exist. It would be a severe suprise if it didn't.
+ //
+
+ pmkFirstOfRest = pCMk->First();
+
+ //
+ // However, the AllButFirst function needs to allocate memory,
+ // which might fail.
+ //
+
+ pmkAllButFirstOfRest = pCMk->AllButFirst();
+
+ if (pmkAllButFirstOfRest == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ goto exitRet;
+ }
+
+ hresult = pmkFirst->ComposeWith(pmkFirstOfRest, TRUE, &pmk);
+
+ if ( hresult == MK_E_NEEDGENERIC)
+ {
+ Assert(pmk == NULL);
+ hresult = Concatenate(pmkFirst, pmkRest, ppmkComposite);
+ }
+ else if (SUCCEEDED(hresult))
+ {
+ //
+ // pmkFirst->ComposeWith can succeed, but return NULL.
+ // If it doesn't return NULL, then ( a o b1 ) is a
+ // moniker of some ilk. Create a generic composite with
+ // this result, and the rest of the moniker
+ //
+ if (pmk != NULL)
+ {
+ hresult = CreateGenericComposite(pmk,
+ pmkAllButFirstOfRest,
+ ppmkComposite);
+ }
+ else
+ {
+ //
+ // pmkFirst and pmkFirstOfRest annihilated each other.
+ // This is indicated by a success code, and a pmk == NULL,
+ // which is how we got here.
+ //
+
+ *ppmkComposite = pmkAllButFirstOfRest;
+
+ //
+ // pmkAllButFirstOfRest is the moniker we want to
+ // return.
+ //
+
+ pmkAllButFirstOfRest->AddRef();
+
+ hresult = NOERROR;
+ }
+ }
+ }
+
+ //
+ // We are done, goto exit routine
+ //
+ goto exitRet;
+
+ }
+
+ //
+ // We have determined that pmkFirst is a Composite Moniker
+ //
+
+ pmkAllButLastOfFirst = pCMk->AllButLast();
+
+ if (pmkAllButLastOfFirst == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ goto exitRet;
+ }
+
+ pmkLastOfFirst = pCMk->Last();
+
+ if (pmkLastOfFirst == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ goto exitRet;
+ }
+
+ //
+ // Determine if pmkRest is a composite. If not, then just
+ // compose the last of pmkFirst with pmkRest
+ //
+
+ pCMkRest = IsCompositeMoniker(pmkRest);
+ if (!pCMkRest)
+ {
+ // case 3: (a1 a2 a3...) o b
+
+ mnkDebugOut((DEB_ITRACE,
+ "::CreateGenericComposite( C(%x) o S(%x) )\n",
+ pmkFirst,
+ pmkRest));
+
+ hresult = pmkLastOfFirst->ComposeWith(pmkRest, TRUE, &pmk);
+
+ if (MK_E_NEEDGENERIC == GetScode(hresult))
+ {
+ Assert(pmk==NULL);
+ hresult = Concatenate(pmkFirst, pmkRest, ppmkComposite);
+ }
+ else if (SUCCEEDED(hresult))
+ {
+ //
+ // If pmk != NULL, create a generic composite out of
+ // of the results
+ if (pmk != NULL)
+ {
+ hresult = CreateGenericComposite(pmkAllButLastOfFirst,
+ pmk,
+ ppmkComposite);
+ }
+ else
+ {
+ //
+ // a3 o b resulted in NULL. Therefore, the result
+ // of the composition is pmkAllButLastOfFirst
+ //
+ *ppmkComposite = pmkAllButLastOfFirst;
+ pmkAllButLastOfFirst->AddRef();
+ hresult = NOERROR;
+ }
+ }
+
+ goto exitRet;
+ }
+
+ //
+ // case 4: (a1 a2 ... aN) o (b1 b2 .. bN )
+ //
+ // Compose two composite monikers. In order to compose them, we need
+ // to compose ( A ) with b1, then recurse to do ( A b1 ) with b2, etc
+ //
+ //
+ mnkDebugOut((DEB_ITRACE,
+ "::CreateGenericComposite( C(%x) o C(%x) )\n",
+ pmkFirst,
+ pmkRest));
+
+ pmkFirstOfRest = pCMkRest->First();
+
+ if (pmkFirstOfRest == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ goto exitRet;
+
+ }
+
+ pmkAllButFirstOfRest = pCMkRest->AllButFirst();
+
+ if (pmkAllButFirstOfRest == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ goto exitRet;
+ }
+
+ hresult = pmkLastOfFirst->ComposeWith(pmkFirstOfRest, TRUE, &pmk);
+
+ if (hresult == MK_E_NEEDGENERIC)
+ {
+ //
+ // In this case, aN didn't know how to compose with b1, other than
+ // to do it generically. The best we can do is to generically
+ // compose the two halves.
+ //
+
+ Assert(pmk == NULL);
+
+ hresult = Concatenate(pmkFirst, pmkRest, ppmkComposite);
+ }
+ else if (SUCCEEDED(hresult))
+ {
+ //
+ // If pmk is not NULL, then there was a result of the composition.
+ // Create a new composite with the first part, then compose it with
+ // whats left of the second part.
+ //
+ if (pmk != NULL)
+ {
+ hresult = CreateGenericComposite(pmkAllButLastOfFirst, pmk, &pmk2);
+
+ if (FAILED(hresult))
+ {
+ goto exitRet;
+ }
+
+ hresult = CreateGenericComposite(pmk2, pmkAllButFirstOfRest, ppmkComposite);
+ }
+ else
+ {
+ //
+ // pmkLastOfFirst annihilated pmkFirstOfRest
+ //
+ // Thats OK. Compose the remaining parts.
+ //
+ hresult = CreateGenericComposite(pmkAllButLastOfFirst,
+ pmkAllButFirstOfRest,
+ ppmkComposite);
+ }
+ }
+
+exitRet:
+
+ if (pmkFirstOfRest) pmkFirstOfRest->Release();
+ if (pmkAllButFirstOfRest) pmkAllButFirstOfRest->Release();
+ if (pmkAllButLastOfFirst) pmkAllButLastOfFirst->Release();
+ if (pmkLastOfFirst) pmkLastOfFirst->Release();
+ if (pmk) pmk->Release();
+ if (pmk2) pmk2->Release();
+
+ CALLHOOKOBJECTCREATE(hresult, CLSID_CompositeMoniker, IID_IMoniker, (IUnknown **)ppmkComposite);
+
+errRtn:
+ OLETRACEOUT((API_CreateGenericComposite, hresult));
+
+ return hresult;
+}
+
+
+
+//------------------------------------------------
+
+
+// Implementation of CCompositeMonikerEnum
+
+CCompositeMonikerEnum::CCompositeMonikerEnum( BOOL fForward,
+ CCompositeMoniker FAR* pCM)
+{
+ GET_A5();
+ Assert(pCM != NULL);
+ m_refs = 0;
+ m_pCM = pCM;
+ pCM -> AddRef();
+ m_fForward = fForward;
+ m_pBase = NULL;
+ m_pTop = NULL;
+ m_pNext = GetNext(pCM); // m_pNext points to the next moniker to return
+}
+
+
+
+CCompositeMonikerEnum::~CCompositeMonikerEnum(void)
+{
+ M_PROLOG(this);
+ se FAR* pse;
+ se FAR* pse2;
+ if (m_pCM)
+ m_pCM->Release();
+ for (pse = m_pBase; pse != NULL; pse = pse2)
+ {
+ pse2 = pse->m_pseNext;
+ pse->m_pseNext = NULL; // workaround for compiler optimization bug
+ delete pse;
+ }
+}
+
+
+BOOL CCompositeMonikerEnum::Push( CCompositeMoniker FAR* pCM)
+// push the composite moniker onto our stack
+{
+ M_PROLOG(this);
+ se FAR * pse;
+
+ pse = new se(pCM);
+ if (pse == NULL)
+ {
+ return FALSE;
+ }
+ pse->m_psePrev = m_pTop;
+ if (m_pTop) m_pTop->m_pseNext = pse;
+ m_pTop = pse;
+ if (m_pBase == NULL) m_pBase = pse;
+ return TRUE;
+}
+
+
+LPMONIKER CCompositeMonikerEnum::GetNext( LPMONIKER pmk )
+{
+ M_PROLOG(this);
+ LPMONIKER pmkRover = pmk;
+ Assert(pmk != NULL);
+ if (pmk == NULL) return NULL;
+
+ CCompositeMoniker *pCMk; ;
+ while ((pCMk = IsCompositeMoniker(pmkRover)) != NULL)
+ {
+ if (!Push(pCMk))
+ {
+ return NULL;
+ }
+ pmkRover = (m_fForward ? pCMk->m_pmkLeft : pCMk->m_pmkRight);
+ }
+ return pmkRover;
+}
+
+
+LPMONIKER CCompositeMonikerEnum::Pop( void )
+{
+ M_PROLOG(this);
+ CCompositeMoniker FAR* pCM;
+ se FAR * pse;
+
+ if (m_pTop == NULL) return NULL;
+ pCM = m_pTop->m_pCM;
+ if ((pse = m_pTop->m_psePrev) != NULL)
+ {
+ pse->m_pseNext = NULL;
+ }
+ else m_pBase = NULL;
+ delete m_pTop;
+ m_pTop = pse;
+ Assert(pCM->m_pmkRight != NULL);
+ Assert(pCM->m_pmkLeft != NULL);
+ return GetNext(m_fForward ? pCM->m_pmkRight : pCM->m_pmkLeft);
+}
+
+
+STDMETHODIMP CCompositeMonikerEnum::QueryInterface (THIS_ REFIID riid, LPVOID FAR* ppvObj)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(ppvObj, LPVOID);
+ *ppvObj = NULL;
+ VDATEIID(riid);
+
+ if (IsEqualIID(riid, IID_IEnumMoniker)
+ || IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppvObj = this;
+ AddRef();
+ return NOERROR;
+ }
+ *ppvObj = NULL;
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+
+
+
+STDMETHODIMP_(ULONG) CCompositeMonikerEnum::AddRef (THIS)
+{
+ M_PROLOG(this);
+ InterlockedIncrement((long *)&m_refs);
+ return m_refs;
+}
+
+
+
+STDMETHODIMP_(ULONG) CCompositeMonikerEnum::Release (THIS)
+{
+ M_PROLOG(this);
+ Assert(m_refs != 0);
+
+ ULONG ul = m_refs;
+
+ if (InterlockedDecrement((long *)&m_refs) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return ul - 1;
+}
+
+
+
+STDMETHODIMP CCompositeMonikerEnum::Next (THIS_ ULONG celt, LPMONIKER FAR* reelt, ULONG FAR* pceltFetched)
+{
+ A5_PROLOG(this);
+ VDATEPTROUT(reelt, LPMONIKER);
+ *reelt = NULL;
+ if (pceltFetched) VDATEPTROUT(pceltFetched, ULONG);
+
+ ULONG count = 0;
+ while (count < celt)
+ {
+ if (m_pNext)
+ {
+ *reelt = m_pNext;
+ m_pNext->AddRef();
+ count++;
+ reelt++;
+ m_pNext = Pop();
+ }
+ else goto ret;
+ }
+ret:
+ if (pceltFetched) *pceltFetched = count;
+ if (count == celt){
+ RESTORE_A5();
+ return NOERROR;
+ }
+ RESTORE_A5();
+ return ResultFromScode(S_FALSE);
+}
+
+
+
+STDMETHODIMP CCompositeMonikerEnum::Skip (THIS_ ULONG celt)
+{
+ M_PROLOG(this);
+ ULONG count = 0;
+ while (count < celt)
+ {
+ if (m_pNext)
+ {
+ count++;
+ m_pNext = Pop();
+ }
+ else return ResultFromScode(S_FALSE);
+ }
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP CCompositeMonikerEnum::Reset (THIS)
+{
+ M_PROLOG(this);
+ se FAR* pse;
+ se FAR* pse2;
+ for (pse=m_pBase; pse != NULL; pse = pse2)
+ {
+ pse2 = pse->m_pseNext;
+ pse->m_pseNext = NULL; // workaround for compiler optimization bug
+ delete pse;
+ }
+ m_pBase = NULL;
+ m_pTop = NULL;
+ m_pNext = GetNext(m_pCM);
+ if (m_pNext) return NOERROR;
+ return ResultFromScode(S_FALSE);
+}
+
+
+
+STDMETHODIMP CCompositeMonikerEnum::Clone (THIS_ LPENUMMONIKER FAR* ppenm)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(ppenm, LPENUMMONIKER);
+ *ppenm = NULL;
+
+ CairoleAssert(FALSE && "Clone not implemented for composite moniker enums");
+ return ResultFromScode(E_NOTIMPL); // Clone not implemented for composite moniker enums
+}
+
+
+LPENUMMONIKER CCompositeMonikerEnum::Create
+ (BOOL fForward, CCompositeMoniker FAR* pCM)
+{
+ CCompositeMonikerEnum FAR* pCME =
+ new CCompositeMonikerEnum(fForward, pCM);
+ if (pCME && pCME->m_pNext)
+ {
+ pCME->AddRef();
+ return pCME;
+ }
+ else
+ {
+ delete pCME;
+ return NULL;
+ }
+}
+
+
+
+STDAPI MonikerCommonPrefixWith( LPMONIKER pmkThis, LPMONIKER pmkOther,
+ LPMONIKER FAR * ppmkPrefix)
+{
+ OLETRACEIN((API_MonikerCommonPrefixWith, PARAMFMT("pmkThis= %p, pmkOther= %p, ppmkPrefix= %p"),
+ pmkThis, pmkOther, ppmkPrefix));
+
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::CommonPrefixWith(pmkThis=%x,pmkOther=%x)\n",
+ pmkThis,
+ pmkOther));
+
+ HRESULT hresult;
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IMoniker,(IUnknown **)&pmkThis);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IMoniker,(IUnknown **)&pmkOther);
+
+ if (IsCompositeMoniker(pmkThis))
+ {
+ hresult = pmkThis->CommonPrefixWith(pmkOther, ppmkPrefix);
+ // AssertOutPtrIface(hresult, *ppmkPrefix);
+ goto errRtn;
+ }
+
+ if (IsCompositeMoniker(pmkOther))
+ {
+ hresult = pmkOther->CommonPrefixWith(pmkThis, ppmkPrefix);
+ // AssertOutPtrIface(hresult, *ppmkPrefix);
+ if (MK_S_HIM == GetScode(hresult))
+ hresult = ResultFromScode(MK_S_ME);
+ else if (MK_S_ME == GetScode(hresult))
+ hresult = ResultFromScode(MK_S_HIM);
+ goto errRtn;
+ }
+ // This doesn't get called unless the monikers are atomic and unrelated
+ *ppmkPrefix = NULL;
+
+ hresult = ResultFromScode(MK_E_NOPREFIX);
+
+errRtn:
+ OLETRACEOUT((API_MonikerCommonPrefixWith, hresult));
+
+ return hresult;
+}
+
+
+
+STDAPI MonikerRelativePathTo(LPMONIKER pmkSrc, LPMONIKER pmkDest, LPMONIKER
+ FAR* ppmkRelPath, BOOL dwReserved)
+{
+ // An implementation of RelativePathTo should check to see if the
+ // other moniker is a type that it recognizes and handles specially.
+ // If not, it should call MonikerRelativePathTo, which will handle
+ // the generic composite cases correctly. Note that this cannot be
+ // done entirely in the CCompositeMoniker implementation because if the
+ // first moniker is not a generic composite and the second is, then
+ // this code is required.
+
+ // CODEWORK: This comment is obsolete. fCalledFromMethod has changed
+ // to dwReserved wich must always be TRUE
+ //
+ // If fCalledFromMethod is false, and if neither moniker is a generic
+ // composite, then this function will call pmkSrc->RelativePathTo. If
+ // fCalledFromMethod is true, it will not call pmkSrc->RelativePathTo,
+ // since the assumption is that pmkSrc->RelativePathTo has called
+ // MonikerRelativePathTo after determining that pmkDest is not of a type
+ // that it recognizes.
+
+ OLETRACEIN((API_MonikerRelativePathTo,
+ PARAMFMT("pmkSrc= %p, pmkDest= %p, ppmkRelPath= %p, dwReserved= %B"),
+ pmkSrc, pmkDest, ppmkRelPath, dwReserved));
+
+ mnkDebugOut((DEB_ITRACE,
+ "CCompositeMoniker::MonikerRelativePathTo(pmkSrc=%x,pmkDest=%x)\n",
+ pmkSrc,
+ pmkDest));
+
+ HRESULT hresult;
+ int caseId = 0;
+ LPMONIKER pmkFirst = NULL;
+ LPMONIKER pmkRest = NULL;
+ LPMONIKER pmkPartialRelPath = NULL;
+ CCompositeMoniker FAR* pccmDest;
+
+ // Check the reserved parameter, which must be TRUE
+ if (dwReserved != TRUE)
+ {
+ *ppmkRelPath = NULL;
+ hresult = E_INVALIDARG;
+ goto errRtn;
+ }
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IMoniker,(IUnknown **)&pmkSrc);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IMoniker,(IUnknown **)&pmkDest);
+
+ VDATEPTROUT_LABEL(ppmkRelPath,LPMONIKER, errRtn, hresult);
+ *ppmkRelPath = NULL;
+ VDATEIFACE_LABEL(pmkSrc, errRtn, hresult);
+ VDATEIFACE_LABEL(pmkDest, errRtn, hresult);
+
+
+
+ pccmDest = IsCompositeMoniker(pmkDest);
+
+ if (IsCompositeMoniker(pmkSrc)) caseId++;
+ if (pccmDest) caseId += 2;
+
+ switch (caseId)
+ {
+ case 0: // neither moniker is composite
+ if (dwReserved)
+ {
+ *ppmkRelPath = pmkDest;
+ pmkDest->AddRef();
+ hresult = ResultFromScode(MK_S_HIM);
+ goto errRtn;
+ }
+ // fall-through to the next case if !dwReserved is
+ // deliberate
+ case 3:
+ case 1: // Src is composite, other might be. Let CCompositeMoniker
+ // implementation handle it.
+ hresult = pmkSrc->RelativePathTo(pmkDest, ppmkRelPath);
+ // AssertOutPtrIface(hresult, *ppmkRelPath);
+ goto errRtn;
+
+ case 2: // Src is not composite, Dest is.
+ pmkFirst = pccmDest->First();
+ pmkRest = pccmDest->AllButFirst();
+ if (NOERROR == pmkSrc->IsEqual(pmkFirst))
+ {
+ *ppmkRelPath = pmkRest;
+ pmkRest->AddRef();
+ hresult = NOERROR;
+ }
+ else
+ {
+ hresult = pmkSrc->RelativePathTo(pmkFirst, &pmkPartialRelPath);
+ // AssertOutPtrIface(hresult, pmkPartialRelPath);
+ if (NOERROR == hresult)
+ {
+ hresult = CreateGenericComposite(pmkPartialRelPath, pmkRest,
+ ppmkRelPath);
+ }
+ else
+ {
+ *ppmkRelPath = pmkDest;
+ pmkDest->AddRef();
+ hresult = ResultFromScode(MK_S_HIM);
+ }
+ }
+
+ if (pmkFirst) pmkFirst->Release();
+ if (pmkRest) pmkRest->Release();
+ if (pmkPartialRelPath) pmkPartialRelPath->Release();
+ }
+
+errRtn:
+ OLETRACEOUT((API_MonikerRelativePathTo, hresult));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTrackingCompositeMoniker
+//
+// Purpose: Provide implementation of ITrackingMoniker for composite
+// monikers.
+//
+// Notes: This object responds to ITrackingMoniker and forwards other
+// QI's to the composite moniker.
+//
+// EnableTracking currently only enables tracking on the moniker to
+// left. When we expose this functionality, we will need to
+// try QI to ITrackingMoniker on the right moniker and pass the
+// moniker to left (as all other moniker fns do.)
+//
+//--------------------------------------------------------------------------
+
+
+#ifdef _TRACKLINK_
+VOID
+CTrackingCompositeMoniker::SetParent(CCompositeMoniker *pCCM)
+{
+ _pCCM = pCCM;
+}
+
+STDMETHODIMP CTrackingCompositeMoniker::QueryInterface(REFIID riid, void **ppv)
+{
+ if (IsEqualIID(IID_ITrackingMoniker, riid))
+ {
+ *ppv = (ITrackingMoniker*) this;
+ _pCCM->AddRef();
+ return(S_OK);
+ }
+ else
+ return(_pCCM->QueryInterface(riid, ppv));
+}
+
+STDMETHODIMP_(ULONG) CTrackingCompositeMoniker::AddRef()
+{
+ return(_pCCM->AddRef());
+}
+
+STDMETHODIMP_(ULONG) CTrackingCompositeMoniker::Release()
+{
+ return(_pCCM->Release());
+}
+
+STDMETHODIMP CTrackingCompositeMoniker::EnableTracking( IMoniker *pmkToLeft, ULONG ulFlags )
+{
+ ITrackingMoniker *ptm=NULL;
+ HRESULT hr;
+
+ hr = _pCCM->m_pmkLeft->QueryInterface(IID_ITrackingMoniker, (void**) &ptm);
+ if (hr == S_OK)
+ {
+ hr = ptm->EnableTracking(NULL, ulFlags);
+
+ if (hr == S_OK)
+ {
+ if (ulFlags & OT_ENABLEREDUCE)
+ {
+ _pCCM->m_fReduceForced = TRUE;
+ }
+
+ if (ulFlags & OT_DISABLEREDUCE)
+ {
+ _pCCM->m_fReduceForced = FALSE;
+ }
+ }
+
+ ptm->Release();
+ }
+ return(hr);
+}
+#endif
+
+
+
+
+
+#ifdef _DEBUG
+
+STDMETHODIMP_(void) NC(CCompositeMoniker,CDebug)::Dump( IDebugStream FAR * pdbstm)
+{
+ VOID_VDATEIFACE(pdbstm);
+
+ *pdbstm << "CCompositeMoniker @" << (VOID FAR *)m_pCompositeMoniker;
+ *pdbstm << '\n';
+ pdbstm->Indent();
+ *pdbstm << "Refcount is " << (int)(m_pCompositeMoniker->m_refs) << '\n';
+ pdbstm->Indent();
+
+ *pdbstm << m_pCompositeMoniker->m_pmkLeft;
+ *pdbstm << m_pCompositeMoniker->m_pmkRight;
+
+ pdbstm->UnIndent();
+ pdbstm->UnIndent();
+}
+
+STDMETHODIMP_(BOOL) NC(CCompositeMoniker,CDebug)::IsValid( BOOL fSuspicious )
+{
+ return ((LONG)(m_pCompositeMoniker->m_refs) > 0);
+ // add more later, maybe
+}
+#endif
diff --git a/private/ole32/com/moniker2/ccompmon.hxx b/private/ole32/com/moniker2/ccompmon.hxx
new file mode 100644
index 000000000..b12c1ec5d
--- /dev/null
+++ b/private/ole32/com/moniker2/ccompmon.hxx
@@ -0,0 +1,178 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: ccompmon.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Commented
+//
+//----------------------------------------------------------------------------
+
+#ifdef _TRACKLINK_
+#include <itrkmnk.hxx>
+class CCompositeMoniker;
+
+class CTrackingCompositeMoniker : public ITrackingMoniker
+{
+public:
+ VOID SetParent(CCompositeMoniker *pCCM);
+
+ virtual HRESULT __stdcall QueryInterface(
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ virtual ULONG __stdcall AddRef( void);
+
+ virtual ULONG __stdcall Release( void);
+
+ virtual HRESULT __stdcall EnableTracking ( IMoniker *pmkToLeft, ULONG ulFlags );
+
+private:
+ CCompositeMoniker * _pCCM;
+};
+
+#endif
+
+class FAR CCompositeMoniker : public CBaseMoniker
+{
+
+public:
+ static CCompositeMoniker FAR*Create( LPMONIKER pmkFirst, LPMONIKER pmkRest);
+
+
+ CCompositeMoniker( void );
+ ~CCompositeMoniker( void );
+ INTERNAL_(BOOL) Initialize( LPMONIKER pmkFirst, LPMONIKER pmkRest );
+ INTERNAL_(LPMONIKER) AllButLast( void );
+ INTERNAL_(LPMONIKER) AllButFirst( void );
+ INTERNAL_(LPMONIKER) Last( void );
+ INTERNAL_(LPMONIKER) First( void );
+ INTERNAL_(ULONG) Count( void );
+
+ STDDEBDECL(CCompositeMoniker, CompositeMoniker)
+
+#ifdef _TRACKLINK_
+ CTrackingCompositeMoniker _tcm;
+#endif
+
+implementations:
+
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,Release) (THIS);
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID);
+
+ // *** IPersistStream methods ***
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm);
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty);
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR * pcbSize);
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID FAR* ppvResult);
+ STDMETHOD(BindToStorage) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD(Reduce) (THIS_ LPBC pbc, DWORD dwReduceHowFar, LPMONIKER FAR*
+ ppmkToLeft, LPMONIKER FAR * ppmkReduced);
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNOtGeneric,
+ LPMONIKER FAR* ppmkComposite);
+ STDMETHOD(Enum) (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker);
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker);
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash);
+ STDMETHOD(IsRunning) (THIS_ LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+ pmkNewlyRunning);
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime);
+ STDMETHOD(Inverse) (THIS_ LPMONIKER FAR* ppmk);
+ STDMETHOD(CommonPrefixWith) (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix);
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath);
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR FAR* lplpszDisplayName);
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut);
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys);
+
+ // *** IROTData Methods ***
+ STDMETHOD(GetComparisonData)(
+ byte *pbData,
+ ULONG cbMax,
+ ULONG *pcbData);
+
+
+ friend
+ HRESULT STDAPICALLTYPE CreateGenericComposite( LPMONIKER, LPMONIKER,
+ LPMONIKER FAR*);
+
+ friend class CCompositeMonikerEnum;
+ friend class CMarshalImplPStream;
+#ifdef _TRACKLINK_
+ friend class CTrackingCompositeMoniker;
+#endif
+ friend BOOL IsReduced( LPMONIKER pmk );
+ friend CCompositeMoniker * IsCompositeMoniker(LPMONIKER pmk);
+
+shared_state:
+
+ LPMONIKER m_pmkLeft;
+ LPMONIKER m_pmkRight;
+ BOOL m_fReduced;
+
+#ifdef _TRACKLINK_
+ BOOL m_fReduceForced;
+#endif
+ SET_A5;
+};
+
+
+class FAR CCompositeMonikerEnum : public CPrivAlloc, public IEnumMoniker
+{
+ CCompositeMonikerEnum( BOOL fForward, CCompositeMoniker FAR*);
+ ~CCompositeMonikerEnum( void );
+
+public:
+ static LPENUMMONIKER Create( BOOL fForward, CCompositeMoniker FAR*);
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ // *** IEnumMoniker methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, LPMONIKER FAR* reelt, ULONG FAR* pceltFetched);
+ STDMETHOD(Skip) (THIS_ ULONG celt);
+ STDMETHOD(Reset) (THIS);
+ STDMETHOD(Clone) (THIS_ LPENUMMONIKER FAR* ppenm);
+private:
+ struct FAR se : public CPrivAlloc // stack element
+ {
+ CCompositeMoniker FAR* m_pCM;
+ se FAR* m_pseNext;
+ se FAR* m_psePrev;
+
+ se( CCompositeMoniker FAR* pCM ) { m_pCM = pCM; m_pseNext = NULL;
+ m_psePrev = NULL; }
+ };
+
+ BOOL Push( CCompositeMoniker FAR* pCM );
+ LPMONIKER GetNext( LPMONIKER pmk );
+ LPMONIKER Pop( void );
+
+
+ ULONG m_refs;
+ CCompositeMoniker FAR* m_pCM; // the moniker being enumerated
+ BOOL m_fForward;
+ se FAR* m_pBase;
+ se FAR* m_pTop;
+ LPMONIKER m_pNext;
+ SET_A5;
+};
diff --git a/private/ole32/com/moniker2/cfactory.cxx b/private/ole32/com/moniker2/cfactory.cxx
new file mode 100644
index 000000000..706da8442
--- /dev/null
+++ b/private/ole32/com/moniker2/cfactory.cxx
@@ -0,0 +1,589 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1996.
+//
+// File: cfactory.cxx
+//
+// Contents: The class factory implementations for the monikers.
+//
+// Classes: CMonikerFactory
+// CClassMonikerFactory
+// CFileMonikerFactory
+//
+// Functions: MonikerDllGetClassObject
+//
+// History: 22-Feb-96 ShannonC Created
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include "cfactory.hxx"
+#include "cbasemon.hxx"
+#include "cfilemon.hxx"
+#include "classmon.hxx"
+#include "mnk.h"
+
+//Static class factory objects.
+static CClassMonikerFactory g_ClassMonikerFactory;
+static CFileMonikerFactory g_FileMonikerFactory;
+
+//+-------------------------------------------------------------------------
+//
+// Function: MonikerDllGetClassObject
+//
+// Synopsis: Returns a pointer to the moniker class factory.
+// This function provides access to the class factories for
+// the file moniker and the class moniker.
+//
+// Arguments: [clsid] -- the class id desired
+// [iid] -- the requested interface
+// [ppv] -- where to put the pointer to the new object
+//
+// Returns: S_OK
+// CLASS_E_CLASSNOTAVAILABLE
+// E_INVALIDARG
+// E_NOINTERFACE
+// E_OUTOFMEMORY
+//
+// Notes: This is an internal function called by DllGetClassObject.
+//
+//--------------------------------------------------------------------------
+#pragma SEG(DllGetClassObject)
+HRESULT MonikerDllGetClassObject(REFCLSID clsid, REFIID iid, void **ppv)
+{
+ HRESULT hr;
+
+ mnkDebugOut((DEB_ITRACE,
+ "MonikerDllGetClassObject(%I,%I,%x)\n",
+ &clsid, &iid, ppv));
+
+ if(IsEqualCLSID(clsid, CLSID_FileMoniker))
+ {
+ hr = g_FileMonikerFactory.QueryInterface(iid, ppv);
+ }
+ else if(IsEqualCLSID(clsid, CLSID_ClassMoniker))
+ {
+ hr = g_ClassMonikerFactory.QueryInterface(iid, ppv);
+ }
+ else
+ {
+ hr = CLASS_E_CLASSNOTAVAILABLE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMonikerFactory::QueryInterface
+//
+// Synopsis: The moniker factory support IUnknown, IClassFactory,
+// and IParseDisplayName
+//
+// Arguments: [iid] -- the requested interface
+// [ppvObj] -- where to put the interface pointer
+//
+// Returns: S_OK
+// E_INVALIDARG
+// E_NOINTERFACE
+//
+// Notes: Bad parameters will raise an exception. The exception
+// handler catches exceptions and returns E_INVALIDARG.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CMonikerFactory::QueryInterface (REFIID iid, void ** ppvObj)
+{
+ HRESULT hr;
+
+ __try
+ {
+ mnkDebugOut((DEB_TRACE,
+ "CMonikerFactory::QueryInterface(%x,%I,%x)\n",
+ this, &iid, ppvObj));
+
+ *ppvObj = NULL;
+
+ if(IsEqualIID(iid,IID_IClassFactory) ||
+ IsEqualIID(iid,IID_IUnknown))
+ {
+ AddRef();
+ *ppvObj = (IClassFactory *) this;
+ hr = S_OK;
+ }
+ else if(IsEqualIID(iid,IID_IParseDisplayName))
+ {
+ AddRef();
+ *ppvObj = (IParseDisplayName *) this;
+ hr = S_OK;
+ }
+ else
+ {
+ hr = E_NOINTERFACE;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMonikerFactory::AddRef
+//
+// Synopsis: Increment the reference count.
+//
+// Arguments: void
+//
+// Returns: ULONG -- the new reference count
+//
+// Notes: This is a static object. The reference count is always 1.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CMonikerFactory::AddRef(void)
+{
+ mnkDebugOut((DEB_TRACE,
+ "CMonikerFactory::AddRef(%x)\n",
+ this));
+
+ return 1;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMonikerFactory::Release
+//
+// Synopsis: Decrements the reference count.
+//
+// Arguments: void
+//
+// Returns: ULONG -- the remaining reference count
+//
+// Notes: This is a static object. The reference count is always 1.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CMonikerFactory::Release(void)
+{
+ mnkDebugOut((DEB_TRACE,
+ "CMonikerFactory::Release(%x)\n",
+ this));
+ return 1;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMonikerFactory::LockServer
+//
+// Synopsis: Lock the server. Does nothing.
+//
+// Arguments: fLock
+//
+// Returns: S_OK
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CMonikerFactory::LockServer(BOOL fLock)
+{
+ mnkDebugOut((DEB_TRACE,
+ "CMonikerFactory::LockServer(%x,%x)\n",
+ this, fLock));
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassMonikerFactory::CreateInstance
+//
+// Synopsis: Creates a class moniker.
+//
+// Arguments: [pUnkOuter] - The controlling unknown (for aggregation)
+// [iid] - The requested interface ID.
+// [ppv] - Returns the pointer to the new object
+//
+// Returns: S_OK
+// CLASS_E_NOAGGREGATION
+// E_NOINTERFACE
+// E_OUTOFMEMORY
+// E_INVALIDARG
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CClassMonikerFactory::CreateInstance(
+ IUnknown * pUnkOuter,
+ REFIID riid,
+ void ** ppv)
+{
+ HRESULT hr;
+ IID iid;
+
+ __try
+ {
+ mnkDebugOut((DEB_TRACE,
+ "CClassMonikerFactory::CreateInstance(%x,%x,%I,%x)\n",
+ this, pUnkOuter, &iid, ppv));
+
+ //Parameter validation.
+ *ppv = NULL;
+ iid = riid;
+
+ if(NULL == pUnkOuter)
+ {
+ CClassMoniker *pmk = new CClassMoniker(CLSID_NULL);
+ if(pmk != NULL)
+ {
+ hr = pmk->QueryInterface(iid, ppv);
+ pmk->Release();
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ //Class moniker does not support aggregation.
+ hr = CLASS_E_NOAGGREGATION;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ParseClassID
+//
+// Synopsis: Parses a display name containing a class ID.
+//
+// Arguments: pszDisplayName - Supplies display name to be parsed.
+// pchEaten - Returns the number of characters parsed.
+// pClassID - Returns the class ID.
+//
+// Returns: S_OK
+// MK_E_SYNTAX
+//
+// Notes: The class ID can have one of the following formats:
+// 00000000-0000-0000-0000-000000000000
+// {00000000-0000-0000-0000-000000000000}
+//
+//--------------------------------------------------------------------------
+HRESULT ParseClassID(
+ LPCWSTR pszDisplayName,
+ ULONG * pchEaten,
+ CLSID * pClassID)
+{
+ HRESULT hr = MK_E_SYNTAX;
+
+ *pchEaten = 0;
+
+ //Parse xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ if(wUUIDFromString(pszDisplayName, pClassID) == TRUE)
+ {
+ //There are 36 characters in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ *pchEaten = 36;
+ hr = S_OK;
+ }
+ //Parse {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
+ else if((L'{' == pszDisplayName[0]) &&
+ (wUUIDFromString(&pszDisplayName[1], pClassID) == TRUE) &&
+ (L'}' == pszDisplayName[37]))
+ {
+ //There are 38 characters in {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
+ *pchEaten = 38;
+ hr = S_OK;
+
+ }
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassMonikerFactory::ParseDisplayName
+//
+// Synopsis: Parse a class moniker display name.
+//
+// Arguments: pbc - Supplies bind context.
+// pszDisplayName - Supplies display name to be parsed.
+// pchEaten - Returns the number of characters parsed.
+// ppmkOut - Returns the pointer to the resulting moniker.
+//
+// Returns: S_OK
+// E_INVALIDARG
+// E_OUTOFMEMORY
+// MK_E_SYNTAX
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CClassMonikerFactory::ParseDisplayName(
+ IBindCtx * pbc,
+ LPOLESTR pszDisplayName,
+ ULONG * pchEaten,
+ IMoniker ** ppmkOut)
+{
+ HRESULT hr;
+ BIND_OPTS bindopts;
+ ULONG chName;
+ ULONG cbName;
+ LPWSTR pName;
+ CClassMoniker *pmkClass = NULL;
+ ULONG cEaten = 0;
+ CLSID classID;
+ LPCWSTR pszParameters = NULL;
+ LPOLESTR pch = pszDisplayName;
+
+ __try
+ {
+
+ mnkDebugOut((DEB_TRACE,
+ "CClassMonikerFactory::ParseDisplayName(%x,%x,%ws,%x,%x)\n",
+ this, pbc, pszDisplayName, pchEaten, ppmkOut));
+
+ //Validate parameters.
+ *pchEaten = 0;
+ *ppmkOut = NULL;
+ bindopts.cbStruct = sizeof(BIND_OPTS);
+ pbc->GetBindOptions(&bindopts);
+
+ // Eat the prefix.
+ while (*pch != '\0' && *pch != ':')
+ {
+ pch++;
+ }
+
+ if(':' == *pch)
+ {
+ pch++;
+ }
+ else
+ {
+ return MK_E_SYNTAX;
+ }
+
+ //Copy the display name.
+ //Note that we allocate memory from the stack so we don't have to free it.
+ chName = lstrlenW(pch);
+ cbName = chName * sizeof(WCHAR) + sizeof(WCHAR);
+ pName = (LPWSTR) alloca(cbName);
+
+ if(pName != NULL)
+ {
+ memcpy(pName, pch, cbName);
+ hr = ParseClassID(pName, &cEaten, &classID);
+
+ if(SUCCEEDED(hr))
+ {
+ //Parse the parameters.
+ if(L';' == pName[cEaten])
+ {
+ pszParameters = &pName[cEaten];
+ cEaten++;
+ }
+
+ //Parse the name up to the :.
+ while(cEaten < chName &&
+ pName[cEaten] != L':')
+ {
+ cEaten++;
+ }
+
+ if(L':' == pName[cEaten])
+ {
+ pName[cEaten] = L'\0';
+
+ //Eat the :
+ cEaten++;
+ }
+
+ //Create the class moniker.
+ pmkClass = new CClassMoniker(classID);
+
+ if(pmkClass != NULL)
+ {
+ //Set the parameters.
+ if(pszParameters != NULL)
+ {
+ hr = pmkClass->SetParameters(pszParameters);
+ if(FAILED(hr))
+ {
+ pmkClass->Release();
+ pmkClass = NULL;
+ }
+ }
+ else
+ {
+ hr = S_OK;
+ }
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ if(SUCCEEDED(hr))
+ {
+ cEaten += pch - pszDisplayName;
+ *pchEaten = cEaten;
+ *ppmkOut = pmkClass;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFileMonikerFactory::CreateInstance
+//
+// Synopsis: Creates a file moniker.
+//
+// Arguments: [pUnkOuter] -- the controlling unknown (for aggregation)
+// [iid] -- the requested interface ID
+// [ppv] -- where to put the pointer to the new object
+//
+// Returns: S_OK
+// CLASS_E_NOAGGREGATION
+// E_NOINTERFACE
+// E_OUTOFMEMORY
+// E_INVALIDARG
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CFileMonikerFactory::CreateInstance(
+ IUnknown * pUnkOuter,
+ REFIID riid,
+ void ** ppv)
+{
+ HRESULT hr;
+ IID iid;
+
+ __try
+ {
+ mnkDebugOut((DEB_TRACE,
+ "CFileMonikerFactory::CreateInstance(%x,%x,%I,%x)\n",
+ this, pUnkOuter, &iid, ppv));
+
+ //Parameter validation.
+ *ppv = NULL;
+ iid = riid;
+
+ if(NULL == pUnkOuter)
+ {
+ IMoniker *pmk;
+
+ pmk = CFileMoniker::Create(OLESTR(""), 0, DEF_ENDSERVER);
+
+ if(pmk != NULL)
+ {
+ hr = pmk->QueryInterface(iid, ppv);
+ pmk->Release();
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ //File moniker does not support aggregation.
+ hr = CLASS_E_NOAGGREGATION;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFileMonikerFactory::ParseDisplayName
+//
+// Synopsis: Parse a file moniker display name.
+//
+// Arguments: pbc - Supplies bind context.
+// pszDisplayName - Supplies display name to be parsed.
+// pchEaten - Returns the number of characters parsed.
+// ppmkOut - Returns the pointer to the resulting moniker.
+//
+// Returns: S_OK
+// E_INVALIDARG
+// E_OUTOFMEMORY
+// MK_E_SYNTAX
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CFileMonikerFactory::ParseDisplayName(
+ IBindCtx * pbc,
+ LPOLESTR pszDisplayName,
+ ULONG * pchEaten,
+ IMoniker ** ppmkOut)
+{
+ HRESULT hr;
+ BIND_OPTS bindopts;
+ IMoniker *pmkFile;
+ ULONG cEaten;
+
+ __try
+ {
+ LPOLESTR pch = pszDisplayName;
+
+ mnkDebugOut((DEB_TRACE,
+ "CFileMonikerFactory::ParseDisplayName(%x,%x,%ws,%x,%x)\n",
+ this, pbc, pszDisplayName, pchEaten, ppmkOut));
+
+ //Validate parameters.
+ *ppmkOut = NULL;
+ *pchEaten = 0;
+ bindopts.cbStruct = sizeof(BIND_OPTS);
+ pbc->GetBindOptions(&bindopts);
+
+ // Eat the prefix.
+ while (*pch != '\0' && *pch != ':')
+ {
+ pch++;
+ }
+
+ if(':' == *pch)
+ {
+ pch++;
+ }
+ else
+ {
+ return MK_E_SYNTAX;
+ }
+
+ hr = FindFileMoniker(pbc, pch, &cEaten, &pmkFile);
+ if(SUCCEEDED(hr))
+ {
+ cEaten += pch - pszDisplayName;
+ *pchEaten = cEaten;
+ *ppmkOut = pmkFile;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
diff --git a/private/ole32/com/moniker2/cfactory.hxx b/private/ole32/com/moniker2/cfactory.hxx
new file mode 100644
index 000000000..463ecaa65
--- /dev/null
+++ b/private/ole32/com/moniker2/cfactory.hxx
@@ -0,0 +1,89 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1996.
+//
+// File: CFactory.hxx
+//
+// Contents: Class factories for file moniker and class moniker
+//
+// Classes: CClassMonikerFactory - Class factory for class moniker.
+// CFileMonikerFactory - Class factory for file moniker.
+// CMonikerFactory - Base class for class factories.
+//
+// Functions: FindFileMoniker - Parses display name as file name.
+//
+// History: 22-Feb-96 ShannonC Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef _CFACTORY_HXX_
+#define _CFACTORY_HXX_
+
+//+-------------------------------------------------------------------------
+//
+// Class: CMonikerFactory
+//
+// Purpose: The base class for CClassMonikerFactory
+// and CFileMonikerFactory.
+//
+// Notes: CMonikerFactory supports the IClassFactory and
+// IParseDisplayName interfaces.
+//
+//--------------------------------------------------------------------------
+class CMonikerFactory : public IClassFactory , public IParseDisplayName
+{
+public:
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void ** ppvObj);
+ ULONG STDMETHODCALLTYPE AddRef(void);
+ ULONG STDMETHODCALLTYPE Release(void);
+ HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock);
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CClassMonikerFactory
+//
+// Purpose: The class factory for the class moniker.
+//
+//--------------------------------------------------------------------------
+class CClassMonikerFactory : public CMonikerFactory
+{
+public:
+ HRESULT STDMETHODCALLTYPE CreateInstance(
+ LPUNKNOWN pUnkOuter,
+ REFIID iid,
+ LPVOID * ppv);
+
+ HRESULT STDMETHODCALLTYPE ParseDisplayName(
+ IBindCtx * pbc,
+ LPOLESTR pszDisplayName,
+ ULONG * pchEaten,
+ IMoniker **ppmkOut);
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CFileMonikerFactory
+//
+// Purpose: The class factory for the file moniker.
+//
+//--------------------------------------------------------------------------
+class CFileMonikerFactory : public CMonikerFactory
+{
+public:
+ HRESULT STDMETHODCALLTYPE CreateInstance(
+ LPUNKNOWN pUnkOuter,
+ REFIID iid,
+ LPVOID * ppv);
+
+ HRESULT STDMETHODCALLTYPE ParseDisplayName(
+ IBindCtx * pbc,
+ LPOLESTR pszDisplayName,
+ ULONG * pchEaten,
+ IMoniker **ppmkOut);
+};
+
+#endif // _CFACTORY_HXX_
diff --git a/private/ole32/com/moniker2/cfilemon.cxx b/private/ole32/com/moniker2/cfilemon.cxx
new file mode 100644
index 000000000..84cf19620
--- /dev/null
+++ b/private/ole32/com/moniker2/cfilemon.cxx
@@ -0,0 +1,6709 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: cfilemon.cxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Commented
+// 01-04-94 KevinRo Serious modifications
+// UNC paths are used directly
+// Added UNICODE extents
+// 03-18-94 BruceMa #5345 Fixed Matches to parse
+// offset correctly
+// 03-18-94 BruceMa #5346 Fixed error return on invalid CLSID
+// string
+// 05-10-94 KevinRo Added Long Filename/8.3 support so
+// downlevel guys can see new files
+// 06-14-94 Rickhi Fix type casting
+// 22-Feb-95 BruceMa Account for OEM vs. ANSI code pages
+// 01-15-95 BillMo Add tracking on x86 Windows.
+// 19-Sep-95 BruceMa Change ::ParseDisplayName to try the
+// object first and then the class
+// 10-13-95 stevebl threadsafety
+// 10-20-95 MikeHill Updated to support new CreateFileMonikerEx API.
+// 11-15-95 MikeHill Use BIND_OPTS2 when Resolving a ShellLink object.
+// 11-22-95 MikeHill - In ResolveShellLink, always check for a null path
+// returned from IShellLink::Resolve.
+// - Also changed m_fPathSetInShellLink to
+// m_fShellLinkInitialized.
+// - In RestoreShellLink & SetPathShellLink,
+// only early-exit if m_fShellLinkInitialized.
+// 12-01-95 MikeHill - Validate bind_opts2.dwTrackFlags before using it.
+// - For Cairo, do an unconditional ResolveShellLink
+// for BindToObject/Storage
+// - Don't do a Resolve in GetTimeOfLastChange.
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include "cbasemon.hxx"
+#include "extents.hxx"
+#include "cfilemon.hxx"
+#include "ccompmon.hxx"
+#include "cantimon.hxx"
+#include "mnk.h"
+#include <olepfn.hxx>
+#include <rotdata.hxx>
+
+#ifdef _TRACKLINK_
+#include <itrkmnk.hxx>
+#endif
+
+#define LPSTGSECURITY LPSECURITY_ATTRIBUTES
+#include "..\..\..\stg\h\dfentry.hxx"
+
+
+DECLARE_INFOLEVEL(mnk)
+
+//
+// The following value is used to determine the average string size for use
+// in optimizations, such as copying strings to the stack.
+//
+
+#define AVERAGE_STR_SIZE (MAX_PATH)
+
+//
+// Determine an upper limit on the length of a path. This is a sanity check
+// so that we don't end up reading in megabyte long paths. The 16 bit code
+// used to use INT_MAX, which is 32767. That is reasonable, plus old code
+// will still work.
+//
+
+#define MAX_MBS_PATH (32767)
+
+// function prototype
+
+// Special function from ROT
+HRESULT GetObjectFromLocalRot(
+ IMoniker *pmk,
+ IUnknown **ppvUnk);
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReadAnsiStringStream
+//
+// Synopsis: Reads a counted ANSI string from the stream.
+//
+// Effects: Old monikers store paths in ANSI characters. This routine
+// reads ANSI strings.
+//
+//
+// Arguments: [pStm] -- Stream to read from
+// [pszAnsiPath] -- Reference to the path variable.
+// [cbAnsiPath] -- Reference to number of bytes read
+//
+// Requires:
+//
+// Returns:
+// pszAnsiPath was allocated using PrivMemAlloc. May return NULL
+// if there were zero bytes written.
+//
+// cbAnsiPath is the total size of the buffer allocated
+//
+// This routine treats the string as a blob. There may be more
+// than one NULL character (ItemMonikers, for example, append
+// UNICODE strings to the end of existing strings.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-08-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT ReadAnsiStringStream( IStream *pStm,
+ LPSTR & pszAnsiPath,
+ USHORT &cbAnsiPath)
+{
+ HRESULT hresult;
+
+ pszAnsiPath = NULL;
+ ULONG cbAnsiPathTmp;
+
+ cbAnsiPath = 0;
+
+ hresult = StRead(pStm, &cbAnsiPathTmp, sizeof(ULONG));
+
+ if (FAILED(hresult))
+ {
+ return hresult;
+ }
+
+ //
+ // If no bytes exist in the stream, thats OK.
+ //
+ if (cbAnsiPathTmp == 0)
+ {
+ return NOERROR;
+ }
+
+ //
+ // Quick sanity check against the size of the string
+ //
+ if (cbAnsiPathTmp > MAX_MBS_PATH)
+ {
+ //
+ // String length didn't make sense.
+ //
+ return E_UNSPEC;
+ }
+
+ cbAnsiPath = (USHORT) cbAnsiPathTmp;
+
+ //
+ // This string is read in as char's.
+ //
+ // NOTE: cb includes the null terminator. Therefore, we don't add
+ // extra room. Also, the read in string is complete. No additional
+ // work needed.
+ //
+
+ pszAnsiPath = (char *)PrivMemAlloc(cbAnsiPath);
+
+ if (pszAnsiPath == NULL)
+ {
+ return(E_OUTOFMEMORY);
+ }
+
+ hresult = StRead(pStm, pszAnsiPath, cbAnsiPath);
+
+ if (FAILED(hresult))
+ {
+ goto errRtn;
+ }
+
+ return NOERROR;
+
+errRtn:
+ if (pszAnsiPath != NULL)
+ {
+ PrivMemFree( pszAnsiPath);
+ pszAnsiPath = NULL;
+ }
+ cbAnsiPath = 0;
+
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteAnsiStringStream
+//
+// Synopsis: Writes a counted ANSI string to the stream.
+//
+// Effects: Old monikers store paths in ANSI characters. This routine
+// writes ANSI strings.
+//
+// Arguments: [pStm] -- Stream to serialize to
+// [pszAnsiPath] -- AnsiPath to serialize
+// [cbAnsiPath] -- Count of bytes in ANSI path
+//
+// Requires:
+//
+// cbAnsiPath is the length of the cbAnsiPath buffer, INCLUDING the
+// terminating NULL.
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-08-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT WriteAnsiStringStream( IStream *pStm, LPSTR pszAnsiPath ,ULONG cbAnsiPath)
+{
+ HRESULT hr;
+ ULONG cb = 0;
+
+ // The >= is because there may be an appended unicode string
+ Assert( (pszAnsiPath == NULL) || (cbAnsiPath >= strlen(pszAnsiPath)+1) );
+
+ if (pszAnsiPath != NULL)
+ {
+ cb = cbAnsiPath;
+
+ //
+ // We don't allow the write of arbitrary length strings, since
+ // we won't be able to read them back in.
+ //
+
+ if (cb > MAX_MBS_PATH)
+ {
+ Assert(!"Attempt to write cbAnsiPath > MAX_MBS_PATH" );
+ return(E_UNSPEC);
+ }
+
+ //
+ // Optimization for the write
+ // if possible, do a single write instead of two by using a temp
+ // buffer.
+
+ if (cb <= AVERAGE_STR_SIZE-4)
+ {
+ char szBuf[AVERAGE_STR_SIZE];
+
+ *((ULONG FAR*) szBuf) = cb;
+
+ //
+ // cb is the string length including the NULL. A memcpy is
+ // used instead of a strcpy
+ //
+
+ memcpy(szBuf+sizeof(ULONG), pszAnsiPath, cb);
+
+ hr = pStm->Write((VOID FAR *)szBuf, cb+sizeof(ULONG), NULL);
+
+ return hr;
+ }
+ }
+
+ if (hr = pStm->Write((VOID FAR *)&cb, sizeof(ULONG), NULL))
+ {
+ return hr;
+ }
+
+ if (pszAnsiPath == NULL)
+ {
+ hr = NOERROR;
+ }
+ else
+ {
+ hr = pStm->Write((VOID FAR *)pszAnsiPath, cb, NULL);
+ }
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CopyPathFromUnicodeExtent
+//
+// Synopsis: Given a path to a UNICODE moniker extent, return the path and
+// its length.
+//
+// Effects:
+//
+// Arguments: [pExtent] --
+// [ppPath] --
+// [cbPath] --
+//
+// Requires:
+//
+// Returns: ppPath is a copy of the string (NULL terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-08-94 kevinro Created
+//
+// Notes:
+//
+// m_szPath should be freed using PrivMemFree();
+//
+//----------------------------------------------------------------------------
+HRESULT
+CopyPathFromUnicodeExtent(MONIKEREXTENT UNALIGNED *pExtent,
+ LPWSTR & pwcsPath,
+ USHORT & ccPath)
+{
+
+ //
+ // The path isn't NULL terminated in the serialized format. Add enough
+ // to have NULL termination.
+ //
+
+ pwcsPath =(WCHAR *)PrivMemAlloc(pExtent->cbExtentBytes + sizeof(WCHAR));
+
+ if (pwcsPath == NULL)
+ {
+ return(E_OUTOFMEMORY);
+ }
+
+ memcpy(pwcsPath,pExtent->achExtentBytes,pExtent->cbExtentBytes);
+
+ //
+ // The length divided by the size of the character yields the count
+ // of characters.
+ //
+
+ ccPath = ((USHORT)(pExtent->cbExtentBytes)) / sizeof(WCHAR);
+
+ //
+ // NULL terminate the string.
+ //
+
+ pwcsPath[ccPath] = 0;
+
+ return(NOERROR);
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CopyPathToUnicodeExtent
+//
+// Synopsis: Given a UNICODE path and a length, return a MONIKEREXTENT
+//
+// Effects:
+//
+// Arguments: [pwcsPath] -- UNICODE string to put in extent
+// [ccPath] -- Count of unicode characters
+// [pExtent] -- Pointer reference to recieve buffer
+//
+// Requires:
+//
+// Returns:
+// pExtent allocated using PrivMemAlloc
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-09-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CopyPathToUnicodeExtent(LPWSTR pwcsPath,ULONG ccPath,LPMONIKEREXTENT &pExtent)
+{
+ pExtent = (LPMONIKEREXTENT)PrivMemAlloc(MONIKEREXTENT_HEADERSIZE +
+ (ccPath * sizeof(WCHAR)));
+
+ if (pExtent == NULL)
+ {
+ return(E_OUTOFMEMORY);
+ }
+
+ pExtent->cbExtentBytes = ccPath * sizeof(WCHAR);
+ pExtent->usKeyValue = mnk_UNICODE;
+ memcpy(pExtent->achExtentBytes,pwcsPath,ccPath*sizeof(WCHAR));
+
+ return(NOERROR);
+}
+
+
+INTERNAL_(DWORD) GetMonikerType ( LPMONIKER pmk )
+{
+ GEN_VDATEIFACE (pmk, 0);
+
+ DWORD dw;
+
+ CBaseMoniker FAR* pbasemk;
+
+ if (NOERROR == pmk->QueryInterface(IID_IInternalMoniker,(LPVOID FAR*)&pbasemk))
+ {
+ pbasemk->IsSystemMoniker(&dw);
+ ((IMoniker *) pbasemk)->Release();
+ return dw;
+ }
+
+ return 0;
+}
+
+
+INTERNAL_(BOOL) IsReduced ( LPMONIKER pmk )
+{
+ DWORD dw = GetMonikerType(pmk);
+ if (dw != 0)
+ {
+ CCompositeMoniker *pCMk;
+ if ((pCMk = IsCompositeMoniker(pmk)) != NULL)
+ {
+ return pCMk->m_fReduced;
+ }
+ else
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+INTERNAL_(CFileMoniker *) IsFileMoniker ( LPMONIKER pmk )
+{
+ CFileMoniker *pCFM;
+
+ if ((pmk->QueryInterface(CLSID_FileMoniker, (void **)&pCFM)) == S_OK)
+ {
+ // we release the AddRef done by QI, but still return the ptr.
+ pCFM->Release();
+ return pCFM;
+ }
+
+ // dont rely on user implementations to set pCFM NULL on failed QI
+ return NULL;
+}
+
+/*
+ * Implementation of CFileMoniker
+ *
+ *
+ *
+ *
+ */
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::CFileMoniker
+//
+// Synopsis: Constructor for CFileMoniker
+//
+// Effects:
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-09-94 kevinro Modified
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CFileMoniker::CFileMoniker( void ) CONSTR_DEBUG
+{
+#ifdef _TRACKLINK_
+ _tfm.SetParent(this);
+#endif
+
+ mnkDebugOut((DEB_ITRACE,
+ "CFileMoniker::CFileMoniker(%x)\n",this));
+
+ m_szPath = NULL;
+ m_ccPath = 0;
+ m_pszAnsiPath = NULL;
+ m_cbAnsiPath = 0;
+ m_cAnti = 0;
+
+ m_ole1 = undetermined;
+ m_clsid = CLSID_NULL;
+
+ m_fClassVerified = FALSE;
+ m_fUnicodeExtent = FALSE;
+ m_fHashValueValid = FALSE;
+ m_dwHashValue = 0x12345678;
+
+ m_endServer = DEF_ENDSERVER;
+
+#ifdef _TRACKLINK_
+ m_pShellLink = NULL;
+ m_fTrackingEnabled = FALSE;
+ m_fSaveShellLink = FALSE;
+ m_fReduceEnabled = FALSE;
+ m_fDirty = FALSE;
+ m_fIsTracking = FALSE; // Is this a tracking moniker?
+ m_fShellLinkInitialized = FALSE; // Has IShellLink->SetPath been called?
+#ifdef _CAIRO_
+ m_pShellLinkTracker = NULL;
+#endif // _CAIRO_
+#endif // _TRACKLINK_
+
+ //
+ // CoQueryReleaseObject needs to have the address of the this objects
+ // query interface routine.
+ //
+ if (adwQueryInterfaceTable[QI_TABLE_CFileMoniker] == 0)
+ {
+ adwQueryInterfaceTable[QI_TABLE_CFileMoniker] =
+ **(DWORD **)((IMoniker *)this);
+ }
+
+ wValidateMoniker();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::ValidateMoniker
+//
+// Synopsis: As a debugging routine, this will validate the contents
+// as VALID
+//
+// Effects:
+//
+// Arguments: (none)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-12-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+#if DBG == 1
+
+void
+CFileMoniker::ValidateMoniker()
+{
+ CLock lck(m_mxs); // protect all internal state
+ wValidateMoniker();
+}
+
+void
+CFileMoniker::wValidateMoniker()
+{
+ //
+ // A valid moniker should have character counts set correctly
+ // m_ccPath holds the number of characters in m_szPath
+ //
+ if (m_szPath != NULL)
+ {
+ Assert(m_ccPath == lstrlenW(m_szPath));
+
+ Assert((m_endServer == DEF_ENDSERVER) || (m_endServer <= m_ccPath));
+ }
+ else
+ {
+ Assert(m_ccPath == 0);
+ Assert(m_endServer == DEF_ENDSERVER);
+ }
+
+ //
+ // If the ANSI version of the path already exists, then validate that
+ // its buffer length is the same as its strlen
+ //
+ if (m_pszAnsiPath != NULL)
+ {
+ Assert(m_cbAnsiPath == strlen(m_pszAnsiPath) + 1);
+ }
+ else
+ {
+ Assert(m_cbAnsiPath == 0);
+ }
+
+ //
+ // There is a very very remote chance that this might fail when it
+ // shouldn't. If it happens, congratulations, you win!
+ //
+ if (!m_fHashValueValid)
+ {
+ Assert(m_dwHashValue == 0x12345678);
+ }
+
+ //
+ // If there is an extent, then we would be very surprised to see it
+ // have a zero size.
+ //
+ if (m_fUnicodeExtent)
+ {
+ Assert(m_ExtentList.GetSize() >= sizeof(ULONG));
+ }
+
+}
+
+#endif
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::~CFileMoniker
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-09-94 kevinro Modified
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CFileMoniker::~CFileMoniker( void )
+{
+ // no locking needed here, since we are going away, and nobody should
+ // have any references to us.
+ wValidateMoniker();
+
+ mnkDebugOut((DEB_ITRACE,
+ "CFileMoniker::~CFileMoniker(%x) m_szPath(%ws)\n",
+ this,
+ m_szPath?m_szPath:L"<No Path>"));
+
+ if( m_szPath != NULL)
+ {
+ PrivMemFree(m_szPath);
+ }
+ if (m_pszAnsiPath != NULL)
+ {
+ PrivMemFree(m_pszAnsiPath);
+ }
+#ifdef _TRACKLINK_
+ if (m_pShellLink != NULL)
+ {
+ m_pShellLink->Release();
+ }
+#ifdef _CAIRO_
+ if (m_pShellLinkTracker != NULL)
+ {
+ m_pShellLinkTracker->Release();
+ }
+#endif // _CAIRO_
+#endif // _TRACKLINK_
+}
+
+
+void UpdateClsid (LPCLSID pclsid)
+{
+
+ CLSID clsidNew = CLSID_NULL;
+
+ // If a class has been upgraded, we want to use
+ // the new class as the server for the link.
+ // The old class's server may no longer exist on
+ // the machine. See Bug 4147.
+
+ if (NOERROR == OleGetAutoConvert (*pclsid, &clsidNew))
+ {
+ *pclsid = clsidNew;
+ }
+ else if (NOERROR == CoGetTreatAsClass (*pclsid, &clsidNew))
+ {
+ *pclsid = clsidNew;
+ }
+}
+
+/*
+When IsOle1Class determines that the moniker should now be an OLE2 moniker
+and sets m_ole1 = ole2, it does NOT set m_clsid to CLSID_NULL.
+This is intentional. This ensures that when GetClassFileEx is called, it
+will be called with this CLSID. This allows BindToObject, after calling
+GetClassFileEx, to map the 1.0 CLSID, via UpdateClsid(), to the correct
+2.0 CLSID. If m_clsid was NULLed, GetClassFileEx would have no
+way to determine the 1.0 CLSID (unless pattern matching worked).
+
+Note that this means that the moniker may have m_ole1==ole2 and
+m_clsid!=CLSID_NULL. This may seem a little strange but is intentional.
+The moniker is persistently saved this way, which is also intentional.
+*/
+
+
+INTERNAL_(BOOL) CFileMoniker::IsOle1Class ( LPCLSID pclsid )
+{
+ wValidateMoniker();
+ {
+ if (m_fClassVerified)
+ {
+ if (m_ole1 == ole1)
+ {
+ *pclsid = m_clsid;
+ return TRUE;
+ }
+ if (m_ole1 == ole2)
+ {
+ return FALSE;
+ }
+ }
+ //
+ // BUGBUG: (KevinRo)If GetClassFileEx fails, then we have not really
+ // verified the class. Is this a problem?
+ //
+
+ m_fClassVerified = TRUE;
+
+ HRESULT hr = GetClassFileEx (m_szPath, pclsid, m_clsid);
+
+ if (NOERROR== hr)
+ {
+ UpdateClsid (pclsid);
+ if (CoIsOle1Class(*pclsid))
+ {
+ m_clsid = *pclsid;
+ m_ole1 = ole1;
+ return TRUE;
+ }
+ else
+ {
+ m_ole1 = ole2;
+ // Do not set m_clsid to CLSID_NULL. See note above.
+ }
+ }
+ return m_ole1==ole1;
+ }
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::GetShellLink, private
+//
+// Synopsis: Ensure that m_pShellLink is valid, or return error.
+//
+// Arguments: [void]
+//
+// Algorithm: if m_pShellLink is already valid return S_OK, else
+// sort of CoCreateInstance a shell link using the routine
+// OleGetShellLink in com\util\dynload.cxx.
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef _TRACKLINK_
+extern VOID * OleGetShellLink();
+
+INTERNAL CFileMoniker::GetShellLink()
+{
+ if (m_pShellLink == NULL)
+ m_pShellLink = (IShellLink*) OleGetShellLink();
+
+ return(m_pShellLink != NULL ? S_OK : E_FAIL);
+}
+#endif
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFileMoniker::EnableTracking
+//
+// Synopsis: Creates/destroys the information neccessary to
+// track objects on BindToObject calls.
+//
+// Arguments: [pmkToLeft] -- moniker to left.
+//
+// [ulFlags] -- flags to control behaviour of tracking
+// extensions.
+//
+// Combination of:
+// OT_READTRACKINGINFO -- get id from source
+// OT_ENABLESAVE -- enable tracker to be saved in
+// extents.
+// OT_DISABLESAVE -- disable tracker to be saved.
+// OT_DISABLETRACKING -- destroy any tracking info
+// and prevent tracking and save of
+// tracking info.
+//
+// OT_DISABLESAVE takes priority of OT_ENABLESAVE
+// OT_READTRACKINGINFO takes priority over
+// OT_DISABLETRACKING
+//
+// OT_ENABLEREDUCE -- enable new reduce functionality
+// OT_DISABLEREDUCE -- disable new reduce functionality
+//
+// OT_MAKETRACKING -- make the moniker inherently tracking;
+// then tracking need not be enabled, and cannot be disabled.
+//
+// Returns: HResult
+// Success is SUCCEEDED(hr)
+//
+// Modifies:
+//
+//--------------------------------------------------------------------
+
+#ifdef _TRACKLINK_
+STDMETHODIMP CFileMoniker::EnableTracking(IMoniker *pmkToLeft, ULONG ulFlags)
+{
+
+ //
+ // - if the shellink does not exist, and shellink creation has not
+ // been disabled by the OLELINK (using private i/f ITrackingMoniker)
+ // then create one and save in extent list. (The EnabledTracking(FALSE)
+ // call prevents the file moniker from creating the shellink on save.)
+ // - if the shellink exists, update the ShellLink in the extent list
+ //
+ //
+ // BUGBUG: BillMo, Optimization. If the path is not extant (e.g. "New1")
+ // then we shouldn't even bother to create the link.
+ //
+
+ CLock lck(m_mxs); // protect all internal state
+
+ //
+ // create an in memory shell link object if needed.
+ //
+
+ HRESULT hr = S_OK;
+
+
+ if (ulFlags & OT_ENABLESAVE)
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::EnableTracking() -- enable save\n",
+ this));
+
+ m_fSaveShellLink = TRUE;
+ }
+
+ if (ulFlags & OT_DISABLESAVE)
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::EnableTracking() -- disable save\n",
+ this));
+
+ m_fSaveShellLink = FALSE;
+ }
+
+ if (ulFlags & OT_ENABLEREDUCE)
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::EnableTracking() -- enable reduce\n",
+ this));
+
+ m_fReduceEnabled = TRUE;
+ }
+
+ if (ulFlags & OT_DISABLEREDUCE)
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::EnableTracking() -- disable reduce\n",
+ this));
+
+ m_fReduceEnabled = FALSE;
+ }
+
+
+ if (ulFlags & OT_READTRACKINGINFO)
+ {
+
+ // Trigger the ShellLink object to get file attributes.
+
+ hr = SetPathShellLink();
+ if( FAILED( hr ))
+ {
+ if( m_pShellLink )
+ {
+ m_pShellLink->Release();
+ m_pShellLink = NULL;
+ }
+
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::EnableTracking(%ls) -- m_pShellLink->SetPath failed %08X.\n",
+ this,
+ m_szPath,
+ hr));
+
+ } // ShellLink->SetPath ... if (FAILED(hr))
+ else
+ {
+ m_fTrackingEnabled = TRUE;
+ hr = S_OK;
+ }
+ } // if (ulFlags & OT_READTRACKINGINFO)
+
+ else
+ if (ulFlags & OT_DISABLETRACKING)
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::EnableTracking() -- disabletracking\n",
+ this));
+
+ // If this is a tracking moniker, the Shell Link cannot
+ // be deleted.
+
+ if( !m_fIsTracking )
+ {
+ if (m_pShellLink != NULL)
+ m_pShellLink->Release();
+ m_pShellLink = NULL;
+ m_ExtentList.DeleteExtent(mnk_ShellLink);
+ }
+
+ m_fSaveShellLink = FALSE;
+ m_fTrackingEnabled = FALSE;
+ } // else if (ulFlags & OT_DISABLETRACKING)
+
+
+#ifdef _CAIRO_
+
+ if( ulFlags & OT_MAKETRACKING )
+ {
+
+ // Initialize the shell link for tracking. As such, it will
+ // always perform enhanced tracking, regardless of the
+ // m_fTrackingEnabled or m_fReduceEnabled flags.
+
+ // Get the ShellLinkTracker interface.
+ hr = GetShellLinkTracker();
+ if( FAILED(hr) )
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::EnableTracking(%ls) -- Could not get ShellLinkTracker (%08X).\n",
+ this,
+ m_szPath,
+ hr));
+ }
+ else
+ {
+ Assert( m_pShellLink != NULL );
+ Assert( m_pShellLinkTracker != NULL );
+
+ // Initialize the Shell Link object with respect to Tracking.
+ // Note that the Track Flags (necessary for this initialization)
+ // are embedded in the ulFlags from our caller.
+
+ hr = m_pShellLinkTracker->Initialize( OT_2_TRACK_FLAGS(ulFlags) );
+ if( FAILED(hr) )
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::EnableTracking(%ls) -- Could not initialize ShellLinkTracker %08X.\n",
+ this,
+ m_szPath,
+ hr));
+ }
+ else
+ {
+ // We've successfully made this a tracking moniker.
+
+ m_fIsTracking = TRUE;
+
+ // Set the path in the ShellLink object.
+
+ hr = SetPathShellLink();
+ if( FAILED( hr ))
+ {
+ // Even though we couldn't set the path, this is
+ // still a Tracking moniker. We might be able to
+ // find and set the path later.
+
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::EnableTracking(%ls) -- SetPath in ShellLink %08X.\n",
+ this,
+ m_szPath,
+ hr));
+ }
+ } // hr = m_pShellLinkTracker->Initialize ... if( FAILED(hr) )
+ } // hr = GetShellLinkTracker() ... if( FAILED(hr) )
+ } // if( ulFlags & OT_MAKETRACKING )
+
+#endif // _CAIRO_
+
+ return(hr);
+}
+
+#endif
+
+/*
+ * Storage of paths in file monikers:
+ *
+ * A separate unsigned integer holds the count of .. at the
+ * beginning of the path, so the canononical form of a file
+ * moniker contains this count and the "path" described above,
+ * which will not contain "..\" or ".\".
+ *
+ * It is considered an error for a path to contain ..\ anywhere
+ * but at the beginning. I assume that these will be taken out by
+ * ParseUserName.
+ */
+
+
+
+inline BOOL IsSeparator( WCHAR ch )
+{
+ return (ch == L'\\' || ch == L'/' || ch == L':');
+}
+
+#ifdef MAC_REVIEW
+Needs to be mac'ifyed
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: EatDotDDots
+//
+// Synopsis: Remove directory prefixes
+//
+// Effects:
+// Removes and counts the number of 'dot dots' on a path. It also
+// removes the case where the leading characters are '.\', which
+// is the 'current' directory.
+//
+// Arguments: [pch] --
+// [cDoubleDots] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 3-02-94 kevinro Commented
+// 3-21-95 kevinro Fixed case where path is ..foo
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL EatDotDots ( LPCWSTR *ppch, USHORT FAR *pcDoubleDots )
+{
+ // passes over ..'s (or ..\'s at the beginning of paths, and returns
+ // an integer counting the ..
+
+ LPWSTR pch = (LPWSTR) *ppch;
+
+ if (pch == NULL)
+ {
+ //
+ // NULL paths are alright
+ //
+ return(TRUE);
+ }
+
+ while (pch[0] == L'.')
+ {
+ //
+ // If the next character is a dot, the consume both, plus any
+ // seperator
+ //
+
+ if (pch[1] == L'.')
+ {
+
+ //
+ // If the next character is a seperator, then remove it also
+ // This handles the '..\' case.
+ //
+
+ if (IsSeparator(pch[2]))
+ {
+ pch += 3;
+ (*pcDoubleDots)++;
+ }
+ //
+ // If the next char is a NULL, then eat it and count a dotdot.
+ // This handles the '..' case where we want the parent directory
+ //
+ else if(pch[2] == 0)
+ {
+ pch += 2;
+ (*pcDoubleDots)++;
+ }
+ //
+ // Otherwise, we just found a '..foobar', which is a valid name.
+ // We can stop processing the string all together and be done.
+ //
+ else
+ {
+ break;
+ }
+
+ }
+ else if (IsSeparator(pch[1]))
+ {
+ //
+ // Found a .\ construct, eat the dot and the seperator
+ //
+ pch += 2;
+ }
+ else
+ {
+ //
+ // There is a dot at the start of the name. This is valid,
+ // since many file systems allow names to start with dots
+ //
+ break;
+ }
+ }
+
+ *ppch = pch;
+ return TRUE;
+}
+
+
+
+int CountSegments ( LPWSTR pch )
+{
+ // counts the number of pieces in a path, after the first colon, if
+ // there is one
+
+ int n = 0;
+ LPWSTR pch1;
+ pch1 = pch;
+ while (*pch1 != L'\0' && *pch1 != L':') IncLpch(pch1);
+ if (*pch1 == ':') pch = ++pch1;
+ while (*pch != '\0')
+ {
+ while (*pch && IsSeparator(*pch)) pch++;
+ if (*pch) n++;
+ while (*pch && (!IsSeparator(*pch))) IncLpch(pch);
+ }
+ return n;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::Initialize
+//
+// Synopsis: Initializes data members.
+//
+// Effects: This one stores the path, its length, and the AntiMoniker
+// count.
+//
+// Arguments: [cAnti] --
+// [pszAnsiPath] -- Ansi version of path. May be NULL
+// [cbAnsiPath] -- Number of bytes in pszAnsiPath buffer
+// [szPathName] -- Path. Takes control of memory
+// [ccPathName] -- Number of characters in Wide Path
+// [usEndServer] -- Offset to end of server section
+//
+// Requires:
+// szPathName must be allocated by PrivMemAlloc();
+// This routine doesn't call EatDotDots. Therefore, the path should
+// not include any leading DotDots.
+//
+// Returns:
+// TRUE success
+// FALSE failure
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-08-94 kevinro Modified
+//
+// Notes:
+//
+// There is at least one case where Initialize is called with a pre
+// allocated string. This routine is called rather than the other.
+// Removes an extra memory allocation, and the extra string scan
+//
+//----------------------------------------------------------------------------
+INTERNAL_(BOOL)
+CFileMoniker::Initialize ( USHORT cAnti,
+ LPSTR pszAnsiPath,
+ USHORT cbAnsiPath,
+ LPWSTR szPathName,
+ USHORT ccPathName,
+ USHORT usEndServer )
+
+
+{
+ wValidateMoniker(); // Be sure we started with something
+ // we expected
+
+ mnkDebugOut((DEB_ITRACE,
+ "CFileMoniker::Initialize(%x) szPathName(%ws)cAnti(%u) ccPathName(0x%x)\n",
+ this,
+ szPathName?szPathName:L"<NULL>",
+ cAnti,
+ ccPathName));
+
+ mnkDebugOut((DEB_ITRACE,
+ "\tpszAnsiPath(%s) cbAnsiPath(0x%x) usEndServer(0x%x)\n",
+ pszAnsiPath?pszAnsiPath:"<NULL>",
+ cbAnsiPath,
+ usEndServer));
+
+ Assert( (szPathName == NULL) || ccPathName == lstrlenW(szPathName) );
+ Assert( (pszAnsiPath == NULL) || cbAnsiPath == strlen(pszAnsiPath) + 1);
+
+ Assert( (usEndServer <= ccPathName) || (usEndServer == DEF_ENDSERVER) );
+
+ //
+ // It is possible to get Initialized twice.
+ // Be careful not to leak
+ //
+
+ if (m_szPath != NULL)
+ {
+ PrivMemFree(m_szPath); // OleLoadFromStream causes two inits
+ }
+
+ if (m_pszAnsiPath != NULL)
+ {
+ PrivMemFree(m_pszAnsiPath);
+ }
+
+ m_cAnti = cAnti;
+ m_pszAnsiPath = pszAnsiPath;
+ m_cbAnsiPath = cbAnsiPath;
+
+ m_szPath = szPathName;
+ m_ccPath = (USHORT)ccPathName;
+ m_endServer = usEndServer;
+
+ //
+ // m_ole1 and m_clsid where loaded in 'Load'. Really should get moved
+ // into here.
+ //
+
+ m_fClassVerified = FALSE;
+
+ // m_fUnicodeExtent gets set in DetermineUnicodePath() routine, so
+ // leave it alone here.
+
+ //
+ // We just loaded new strings. Hash value is no longer valid.
+ //
+
+ m_fHashValueValid = FALSE;
+ m_dwHashValue = 0x12345678;
+
+ //
+ // Notice that the extents are not initialized.
+ //
+ // The two cases are:
+ // 1) This is called as result of CreateFileMoniker, in which case
+ // no extents are created. The default constructor suffices.
+ //
+ // 2) This is called as result of ::Load(), in which case the extents
+ // have already been loaded.
+ //
+
+ wValidateMoniker();
+
+ return(TRUE);
+
+}
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::Initialize
+//
+// Synopsis: This version of Initialize is called by CreateFileMoniker
+//
+// Effects:
+//
+// Arguments: [cAnti] -- Anti moniker count
+// [szPathName] -- Unicode path name
+// [usEndServer] -- End of server section of UNC path
+//
+// Requires:
+//
+// Returns:
+// TRUE success
+// FALSE failure
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-08-94 kevinro Modified
+//
+// Notes:
+//
+// Preprocesses the path, makes a copy of it, then calls the other
+// version of Initialize.
+//
+//----------------------------------------------------------------------------
+INTERNAL_(BOOL)
+CFileMoniker::Initialize ( USHORT cAnti,
+ LPCWSTR szPathName,
+ USHORT usEndServer )
+{
+
+ WCHAR const *pchSrc = szPathName;
+ WCHAR *pwcsPath = NULL;
+ USHORT ccPath;
+
+ //
+ // Adjust for leading '..'s
+ //
+ if (EatDotDots(&pchSrc, &cAnti) == FALSE)
+ {
+ return FALSE;
+ }
+
+ if (FAILED(DupWCHARString(pchSrc,pwcsPath,ccPath)))
+ {
+ return(FALSE);
+ }
+
+ //
+ // Be sure we are creating a valid Win32 path. ccPath is the count of
+ // characters. It needs to fit into a MAX_PATH buffer
+ //
+
+ if (ccPath >= MAX_PATH)
+ {
+ goto errRet;
+ }
+
+ if (Initialize(cAnti, NULL, 0, pwcsPath, ccPath, usEndServer) == FALSE)
+ {
+ goto errRet;
+ }
+
+ return(TRUE);
+
+errRet:
+ if (pwcsPath != NULL)
+ {
+ PrivMemFree(pwcsPath);
+ }
+ return(FALSE);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::Create
+//
+// Synopsis: Create function for file moniker
+//
+// Effects:
+//
+// Arguments: [szPathName] -- Path to create with
+// [cbPathName] -- Count of characters in path
+// [memLoc] -- Memory context
+// [usEndServer] -- Offset to end of server name in path
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-11-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CFileMoniker FAR *
+CFileMoniker::Create ( LPCWSTR szPathName,
+ USHORT cAnti ,
+ USHORT usEndServer)
+
+{
+
+ mnkDebugOut((DEB_ITRACE,
+ "CFileMoniker::Create szPath(%ws)\n",
+ szPathName?szPathName:L"<NULL PATH>"));
+
+ CFileMoniker FAR * pCFM = new CFileMoniker();
+
+ if (pCFM != NULL)
+ {
+ pCFM->AddRef();
+ pCFM->m_mxs.Request(); // protect all internal state
+
+ if (pCFM->Initialize( cAnti,
+ szPathName,
+ usEndServer))
+ {
+ pCFM->m_mxs.Release();
+ return pCFM;
+ }
+
+ pCFM->m_mxs.Release(); // we have to do this before we blow it away...
+ delete pCFM;
+ }
+ return NULL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: FindExt
+//
+// Synopsis:
+//
+// Effects:
+// returns a pointer into szPath which points to the period (.) of the
+// extension; returns NULL if no such point exists.
+//
+// Arguments: [szPath] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-16-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+LPCWSTR FindExt ( LPCWSTR szPath )
+{
+ LPCWSTR sz = szPath;
+
+ if (!sz)
+ {
+ return NULL;
+ }
+
+ sz += lstrlenW(szPath); // sz now points to the null at the end
+
+ Assert(*sz == '\0');
+
+ DecLpch(szPath, sz);
+
+ while (*sz != '.' && *sz != '\\' && *sz != '/' && sz > szPath )
+ {
+ DecLpch(szPath, sz);
+ }
+ if (*sz != '.') return NULL;
+
+ return sz;
+}
+
+
+
+
+
+STDMETHODIMP CFileMoniker::QueryInterface (THIS_ REFIID riid,
+ LPVOID FAR* ppvObj)
+{
+ wValidateMoniker();
+
+ VDATEIID (riid);
+ VDATEPTROUT(ppvObj, LPVOID);
+
+#ifdef _DEBUG
+ if (riid == IID_IDebug)
+ {
+ *ppvObj = &(m_Debug);
+ return NOERROR;
+ }
+#endif
+
+#ifdef _TRACKLINK_
+ if (IsEqualIID(riid, IID_ITrackingMoniker))
+ {
+ AddRef();
+ *ppvObj = (ITrackingMoniker *) &_tfm;
+ return(S_OK);
+ }
+#endif
+ if (IsEqualIID(riid, CLSID_FileMoniker))
+ {
+ // called by IsFileMoniker.
+ AddRef();
+ *ppvObj = this;
+ return S_OK;
+ }
+ else if (IsEqualIID(riid, IID_IROTData))
+ {
+ AddRef();
+ *ppvObj = (IROTData *) this;
+ return S_OK;
+ }
+
+ return CBaseMoniker::QueryInterface(riid, ppvObj);
+}
+
+
+STDMETHODIMP_(ULONG) CFileMoniker::Release (void)
+{
+ wValidateMoniker();
+
+ Assert(m_refs != 0);
+
+ ULONG ul = m_refs;
+
+ if (InterlockedDecrement((long *)&m_refs) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return ul - 1;
+}
+
+
+STDMETHODIMP CFileMoniker::GetClassID (LPCLSID lpClassId)
+{
+ VDATEPTROUT (lpClassId, CLSID);
+
+ CLock lck(m_mxs); // protect all internal state during operation
+
+ *lpClassId = CLSID_FileMoniker;
+
+ return NOERROR;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::Load
+//
+// Synopsis: Loads a moniker from a stream
+//
+// Effects:
+//
+// Arguments: [pStm] -- Stream to load from
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-07-94 kevinro Modified
+//
+// Notes:
+//
+// We have some unfortunate legacy code to deal with here. Previous monikers
+// saved their paths in ANSI instead of UNICODE. This was a very unfortunate
+// decision, since we now are forced to pull some tricks to support UNICODE
+// paths.
+//
+// Specifically, there isn't always a translation between UNICODE and ANSI
+// characters. This means we may need to save a seperate copy of the UNCODE
+// string, if the mapping to ASCII fails.
+//
+// The basic idea is the following:
+//
+// The in memory representation is always UNICODE. The serialized form
+// will always attempt to be ANSI. If, while seralizing, the UNICODE path
+// to ANSI path conversion fails, then we will create an extent to save the
+// UNICODE version of the path. We will use whatever the ANSI path conversion
+// ended up with to store in the ANSI part of the stream, though it will not
+// be a good value. We will replace the non-converted characters with the
+// systems 'default' mapping character, as defined by WideCharToMultiByte()
+//
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CFileMoniker::Load (LPSTREAM pStm)
+{
+ CLock lck(m_mxs); // protect all internal state during load operation
+
+ wValidateMoniker();
+
+ mnkDebugOut((DEB_ITRACE,
+ "CFileMoniker::Load(%x)\n",
+ this));
+
+ VDATEIFACE (pStm);
+
+ HRESULT hresult;
+ LPSTR szAnsiPath = NULL;
+ USHORT cAnti;
+ USHORT usEndServer;
+
+ WCHAR *pwcsWidePath = NULL;
+ USHORT ccWidePath = 0; // Number of characters in UNICODE path
+
+ ULONG cbExtents = 0;
+ USHORT cbAnsiPath = 0; // Number of bytes in path including NULL
+
+#ifdef _CAIRO_
+
+ //
+ // If we're about to load from a stream, then our existing
+ // state is now invalid. There's no need to explicitely
+ // re-initialize our persistent state, except for the
+ // Shell Link object. An existing ShellLink should be
+ // deleted.
+ //
+
+ if( m_pShellLink )
+ m_pShellLink->Release();
+ m_pShellLink = NULL;
+
+#endif // _CAIRO_
+
+
+ //
+ // The cAnti field was written out as a UINT in the original 16-bit code.
+ // This has been changed to a USHORT, to preserve its 16 bit size.
+ //
+
+ hresult = StRead(pStm, &cAnti, sizeof(USHORT));
+
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+
+ //
+ // The path string is stored in ANSI format.
+ //
+
+ hresult = ReadAnsiStringStream( pStm, szAnsiPath , cbAnsiPath );
+
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+
+ //
+ // The first version of the moniker code only had a MAC alias field.
+ // The second version used a cookie in m_cbMacAlias field to determine
+ // if the moniker is a newer version.
+ //
+
+ hresult = StRead(pStm, &cbExtents, sizeof(DWORD));
+
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+
+ usEndServer = LOWORD(cbExtents);
+
+ if (usEndServer== 0xBEEF) usEndServer = DEF_ENDSERVER;
+
+ if (HIWORD(cbExtents) == 0xDEAD)
+ {
+ MonikerReadStruct ioStruct;
+
+ hresult = StRead(pStm, &ioStruct, sizeof(ioStruct));
+
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+
+ m_clsid = ioStruct.m_clsid;
+ m_ole1 = (enum CFileMoniker::olever) ioStruct.m_ole1;
+ cbExtents = ioStruct.m_cbExtents;
+ }
+ //
+ // If cbExtents is != 0, then there are extents to be read. Call
+ // the member function of CExtentList to load them from stream.
+ //
+ // Having to pass cbExtents from this routine is ugly. But, we have
+ // to since it is read in as part of the cookie check above.
+ //
+ if (cbExtents != 0)
+ {
+ hresult = m_ExtentList.Load(pStm,cbExtents);
+
+#ifdef _TRACKLINK_
+
+ if (hresult == S_OK)
+ {
+#ifdef _CAIRO_
+
+ MONIKEREXTENT *pmeTracking;
+
+ // Is this a tracking moniker?
+
+ if( pmeTracking = m_ExtentList.FindExtent( mnk_TrackingInformation ))
+ {
+ m_fIsTracking = TRUE;
+
+ // Initialize the shell link object (in m_pShellLink)
+ // by creating it, and restoring its
+ // persistent data.
+
+ if( FAILED( hresult = RestoreShellLink() ))
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::Load could not restore shell link (%08x).\n",
+ this,
+ hresult));
+ }
+ else
+ {
+ // Have we ever successfully IShellLink->SetPath()?
+
+ m_fShellLinkInitialized = pmeTracking->achExtentBytes[0];
+ }
+
+ } // if( pmeTracking = m_ExtentList.FindExtent( mnk_TrackingInformation ))
+ else
+
+ {
+ // This is not a Tracking Moniker, but it may still have
+ // tracking enabled.
+
+#endif // _CAIRO_
+
+ m_fTrackingEnabled =
+ NULL != m_ExtentList.FindExtent(mnk_ShellLink);
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::Load did%s find mnk_ShellLink extent, m_fTrackingEnabled=%d.\n",
+ this,
+ m_fTrackingEnabled ? "" : " not",
+ m_fTrackingEnabled));
+
+#ifdef _CAIRO_
+ } // if( ... FindExtent( mnk_TrackingInformation )) ... else
+#endif
+ } // hresult = m_ExtentList.Load(pStm,cbExtents) ... if (hresult == S_OK)
+
+#endif // _TRACKLINK_
+ } // if (cbExtents != 0)
+
+ //
+ // DetermineUnicodePath will handle the mbs to UNICODE conversions, and
+ // will also check the Extents to determine if there is a
+ // stored UNICODE path.
+ //
+
+ hresult = DetermineUnicodePath(szAnsiPath,pwcsWidePath,ccWidePath);
+
+ if (FAILED(hresult))
+ {
+ goto errRet;
+ }
+
+ //
+ // Initialize will take control of all path memory
+ //
+
+ if (Initialize( cAnti,
+ szAnsiPath,
+ cbAnsiPath,
+ pwcsWidePath,
+ ccWidePath,
+ usEndServer) == FALSE)
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRet;
+ }
+
+errRet:
+
+ if (FAILED(hresult))
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "::Load(%x) failed hr(%x)\n",
+ this,
+ hresult));
+
+ }
+ else
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "::Load(%x) cAnti(%x) m_szPath(%ws) m_pszAnsiPath(%s)\n",
+ this,
+ cAnti,
+ m_szPath,
+ m_pszAnsiPath));
+ }
+
+ wValidateMoniker();
+
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::Save
+//
+// Synopsis: Save this moniker to stream.
+//
+// Effects:
+//
+// Arguments: [pStm] -- Stream to save to
+// [fClearDirty] -- Dirty flag
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-07-94 kevinro Modified
+//
+// Notes:
+//
+// It is unfortunate, but we may need to save two sets of paths in the
+// moniker. The shipped version of monikers saved paths as ASCII strings.
+//
+// See the notes found in ::Load for more details
+//
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CFileMoniker::Save (LPSTREAM pStm, BOOL fClearDirty)
+{
+ CLock lck(m_mxs); // protect all internal state during save operation
+
+ wValidateMoniker();
+ mnkDebugOut((DEB_ITRACE,
+ "CFileMoniker::Save(%x)m_szPath(%ws)\n",
+ this,
+ m_szPath?m_szPath:L"<Null Path>"));
+
+ M_PROLOG(this);
+
+ VDATEIFACE (pStm);
+
+ HRESULT hresult;
+ UNREFERENCED(fClearDirty);
+ ULONG cbWritten;
+
+ //
+ // We currently have a UNICODE string. Need to write out an
+ // Ansi version.
+ //
+
+ hresult = ValidateAnsiPath();
+
+ if (hresult != NOERROR) goto errRet;
+
+ hresult = pStm->Write(&m_cAnti, sizeof(USHORT), &cbWritten);
+ if (hresult != NOERROR) goto errRet;
+
+ //
+ // Write the ANSI version of the path.
+ //
+
+ hresult = WriteAnsiStringStream( pStm, m_pszAnsiPath, m_cbAnsiPath );
+ if (hresult != NOERROR) goto errRet;
+
+ //
+ // Here we write out everything in a single blob
+ //
+
+ MonikerWriteStruct ioStruct;
+
+ ioStruct.m_endServer = m_endServer;
+ ioStruct.m_w = 0xDEAD;
+ ioStruct.m_clsid = m_clsid;
+ ioStruct.m_ole1 = m_ole1;
+
+
+ hresult = pStm->Write(&ioStruct, sizeof(ioStruct), &cbWritten);
+
+ if (hresult != NOERROR) goto errRet;
+
+ Assert(cbWritten == sizeof(ioStruct));
+
+
+#ifdef _TRACKLINK_
+
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::Save m_fSaveShellLink = %s, m_pShellLink=%08X.\n",
+ this,
+ m_fSaveShellLink ? "TRUE" : "FALSE",
+ m_pShellLink));
+
+
+ // If we have a ShellLink object, and either this is a tracking moniker
+ // or we've been asked to save the ShellLink, then save it in a
+ // Moniker Extent.
+
+ if ( ( m_fSaveShellLink
+ ||
+ m_fIsTracking
+ )
+ &&
+ m_pShellLink != NULL
+ )
+ {
+ //
+ // Here we are saving the shell link to a MONIKEREXTENT.
+ // The basic idea here is to save the shell link to an in memory
+ // stream (using CreateStreamOnHGlobal). The format of the stream
+ // is the same as a MONIKEREXTENT (i.e. has a MONIKEREXTENT at the
+ // front of the stream.)
+ //
+
+ IPersistStream *pps = NULL;
+ IStream * pstm = NULL;
+ BOOL fOk;
+ HRESULT hr;
+
+ Verify(S_OK == m_pShellLink->QueryInterface(IID_IPersistStream, (void **) & pps));
+
+ hr = CreateStreamOnHGlobal(NULL, // auto alloc
+ TRUE, // delete on release
+ &pstm);
+
+ if (hr != S_OK)
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::Save CreateStreamOnHGlobal failed %08X",
+ this,
+ hr));
+ goto ExitShellLink;
+ }
+
+ //
+ // We write out the MONIKEREXTENT header to the stream ...
+ //
+
+ MONIKEREXTENT me;
+ MONIKEREXTENT *pExtent;
+
+ me.cbExtentBytes = 0;
+ me.usKeyValue = mnk_ShellLink;
+
+ hr = pstm->Write(&me, MONIKEREXTENT_HEADERSIZE, NULL);
+ if (hr != S_OK)
+ goto ExitShellLink;
+
+ // ... and then save the shell link
+ hr = pps->Save(pstm, FALSE);
+
+ if (hr != S_OK)
+ goto ExitShellLink;
+
+ // We then seek back and write the cbExtentList value.
+ LARGE_INTEGER li0;
+ ULARGE_INTEGER uli;
+
+ memset(&li0, 0, sizeof(li0));
+
+ Verify(S_OK == pstm->Seek(li0, STREAM_SEEK_END, &uli));
+
+ me.cbExtentBytes = uli.LowPart - MONIKEREXTENT_HEADERSIZE;
+ Verify(S_OK == pstm->Seek(li0, STREAM_SEEK_SET, &uli));
+ Assert(uli.LowPart == 0 && uli.HighPart == 0);
+
+ Verify(S_OK == pstm->Write(&me.cbExtentBytes, sizeof(me.cbExtentBytes), NULL));
+
+
+ // Finally, we get access to the memory of the stream and
+ // cast it to a MONIKEREXTENT to pass to PutExtent.
+
+ HGLOBAL hGlobal;
+
+ Verify(S_OK == GetHGlobalFromStream(pstm, &hGlobal));
+
+ pExtent = (MONIKEREXTENT *) GlobalLock(hGlobal);
+ Assert(pExtent != NULL);
+
+ // this overwrites the existing mnk_ShellLink extent if any.
+ hr = m_ExtentList.PutExtent(pExtent);
+
+ fOk = GlobalUnlock(hGlobal);
+
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::Save serialized shell link to extent=%08X\n",
+ this,
+ hr));
+
+ // If this is a Tracking Moniker, then we additionally write
+ // out the fShellLinkInitialized flag. Not only does this make the
+ // flag persistent, but the existence of this Extent indicates
+ // that this is a Tracking Moniker (put another way, it makes the
+ // fIsTracking member persistent).
+
+#ifdef _CAIRO_
+
+ if( m_fIsTracking )
+ {
+ // We needn't allocate any memory for the flag; it
+ // fits into the default MONIKEREXTENT (since it is
+ // a BYTE).
+
+ Assert( sizeof(m_fShellLinkInitialized) == sizeof(BYTE) );
+
+ MONIKEREXTENT meTracking;
+
+ meTracking.usKeyValue = mnk_TrackingInformation;
+ meTracking.cbExtentBytes = sizeof( meTracking )
+ - MONIKEREXTENT_HEADERSIZE;
+ meTracking.achExtentBytes[0] = m_fShellLinkInitialized;
+
+ // Put this extent.
+
+ hr = m_ExtentList.PutExtent( &meTracking );
+
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::Save serialized tracking info to extent=%08X\n",
+ this,
+ hr));
+
+ } // if( m_fIsTracking )
+
+#endif // _CAIRO_
+
+
+ExitShellLink:
+
+ if (pstm != NULL)
+ pstm->Release(); // releases the hGlobal.
+
+ if (pps != NULL)
+ pps->Release();
+
+ } // if ( ( m_fSaveShellLink ...
+#endif // _TRACKLINK_
+
+ //
+ // A UNICODE version may exist in the ExtentList. Write that out.
+ //
+
+ hresult = m_ExtentList.Save(pStm);
+
+errRet:
+
+#ifdef _TRACKLINK_
+ if (SUCCEEDED(hresult) && fClearDirty)
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::Save clearing dirty flag\n",
+ this));
+ m_fDirty = FALSE;
+ }
+#endif
+
+ wValidateMoniker();
+
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::IsDirty
+//
+// Synopsis: Return the dirty flag
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+#ifdef _TRACKLINK_
+STDMETHODIMP CFileMoniker::IsDirty (VOID)
+{
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::IsDirty returning%s dirty\n",
+ this,
+ m_fDirty ? "" : " not"));
+ return(m_fDirty ? S_OK : S_FALSE);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::GetSizeMax
+//
+// Synopsis: Return the current max size for a serialized moniker
+//
+// Effects:
+//
+// Arguments: [pcbSize] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-09-94 kevinro Modified
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CFileMoniker::GetSizeMax (ULARGE_INTEGER FAR* pcbSize)
+{
+ CLock lck(m_mxs); // protect all internal state during this call
+ wValidateMoniker();
+
+ M_PROLOG(this);
+ VDATEPTROUT (pcbSize, ULONG);
+
+ wValidateMoniker();
+
+ //
+ // Total the string lengths. If the Ansi string doesn't exist yet, then
+ // assume the maximum length will be 2 bytes times the number of
+ // characters. 2 bytes is the maximum length of a DBCS character.
+ //
+
+
+ ULONG ulStringLengths = (m_cbAnsiPath?m_cbAnsiPath:m_ccPath*2);
+
+
+ //
+ // Now add in the size of the UNICODE string, if we haven't seen
+ // a UNICODE extent yet.
+ //
+
+ if (!m_fUnicodeExtent )
+ {
+ ulStringLengths += (m_ccPath * sizeof(WCHAR));
+ }
+
+ //
+ // The original code had added 10 bytes to the size, apparently just
+ // for kicks. I have left it here, since it doesn't actually hurt
+ //
+
+ ULONG cbSize;
+
+ cbSize = ulStringLengths +
+ sizeof(CLSID) + // The monikers class ID
+ sizeof(CLSID) + // OLE 1 classID
+ sizeof(ULONG) +
+ sizeof(USHORT) +
+ sizeof(DWORD) +
+ m_ExtentList.GetSize()
+ + 10;
+
+ ULISet32(*pcbSize,cbSize);
+
+ mnkDebugOut((DEB_ITRACE,
+ "CFileMoniker::GetSizeMax(%x)m_szPath(%ws) Size(0x%x)\n",
+ this,
+ m_szPath?m_szPath:L"<Null Path>",
+ cbSize));
+
+ return NOERROR;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetClassFileEx
+//
+// Synopsis: returns the classid associated with a file
+//
+// Arguments: [lpszFileName] -- name of the file
+// [pcid] -- where to return the clsid
+// [clsidOle1] -- ole1 clsid to use (or CLSID_NULL)
+//
+// Returns: S_OK if clisd determined
+//
+// Algorithm:
+//
+// History: 1-16-94 kevinro Created
+//
+// Notes: On Cairo, STGFMT_FILE will try to read the clsid from a file,
+// then do pattern matching, and then do extension matching.
+// For all other storage formats, pattern matching is skipped.
+// If at any point along the way we find a clsid, exit
+//
+//----------------------------------------------------------------------------
+STDAPI GetClassFileEx( LPCWSTR lpszFileName, CLSID FAR *pcid,
+ REFCLSID clsidOle1)
+{
+ VDATEPTRIN (lpszFileName, WCHAR);
+ VDATEPTROUT (pcid, CLSID);
+
+
+ LPCWSTR szExt = NULL;
+ HRESULT hresult;
+ HANDLE hFile = INVALID_HANDLE_VALUE;
+
+
+ //
+ // Don't crash when provided a bogus file path.
+ //
+ if (lpszFileName == NULL)
+ {
+ hresult = MK_E_CANTOPENFILE;
+ goto errRet;
+ }
+
+#ifdef _CAIRO_
+
+ hresult = StgGetClassFile (NULL, lpszFileName, pcid, &hFile);
+
+ if (hresult == NOERROR && !IsEqualIID(*pcid, CLSID_NULL))
+ {
+ // we have a class id from the file
+ goto errRet;
+ }
+
+ // In certain cases, StgGetClassFile (NtCreateFile) will fail
+ // but CreateFile will successfully open a docfile or OFS storage.
+ // In the docfile case, DfGetClass returns lock violation
+ // but Daytona ignores it, and checks the pattern & extensions
+ // In the OFS case, GetNtHandle returns share violation
+ // but CreateFile will work, skip the pattern & check extensions
+ // This is intended to emulate this odd behavior
+
+ if (hresult != STG_E_LOCKVIOLATION &&
+ hresult != STG_E_SHAREVIOLATION &&
+ !SUCCEEDED(hresult)) // emulate CreateFile error
+ {
+ hresult = MK_E_CANTOPENFILE;
+ goto errRet;
+ }
+#endif // _CAIRO_
+
+#ifndef _CAIRO_
+
+ // open the file once, then pass the file handle to the various
+ // subsystems (storage, pattern matching) to do the work.
+
+ hFile = CreateFile(lpszFileName, // file name
+ GENERIC_READ, // read only access
+ FILE_SHARE_READ | FILE_SHARE_WRITE, // allow any other access
+ NULL, // no sec descriptor
+ OPEN_EXISTING, // file if file doesn't exist
+ NULL, // no flags or attributes
+ NULL); // no template
+
+ if (INVALID_HANDLE_VALUE == hFile)
+ {
+ hresult = MK_E_CANTOPENFILE;
+ goto errRet;
+ }
+
+ // First, check with storage to see if this a docfile. if it is,
+ // storage will return us the clsid.
+
+ hresult = DfGetClass(hFile, pcid);
+
+ if (hresult == NOERROR && !IsEqualIID(*pcid, CLSID_NULL))
+ {
+ goto errRet;
+ }
+
+#endif // _CAIRO_
+
+ // If this is an OLE1 file moniker, then use the CLSID given
+ // to the moniker at creation time instead of using the
+ // file extension. Bug 3948.
+
+ if (!IsEqualCLSID(clsidOle1,CLSID_NULL))
+ {
+ *pcid = clsidOle1;
+
+ hresult = NOERROR;
+ goto errRet;
+ }
+
+#ifdef _CAIRO_
+ if (hFile != INVALID_HANDLE_VALUE)
+ {
+#endif
+
+ // Attempt to find the class by matching byte patterns in
+ // the file with patterns stored in the registry.
+
+ hresult = wCoGetClassPattern(hFile, pcid);
+
+ if (hresult != REGDB_E_CLASSNOTREG)
+ {
+ // either a match was found, or the file does not exist.
+ goto errRet;
+ }
+#ifdef _CAIRO_
+ } // end if (hFile != INVALID_HANDLE_VALUE)
+#endif
+
+
+ // The file is not a storage, there was no pattern matching, and
+ // the file exists. Look up the class for this extension.
+ // Find the extension by scanning backward from the end for ".\/!"
+ // There is an extension only if we find "."
+
+ hresult = NOERROR;
+ szExt = FindExt(lpszFileName);
+
+ if (!szExt)
+ {
+ // no file extension
+ hresult = ResultFromScode(MK_E_INVALIDEXTENSION);
+ goto errRet;
+ }
+
+ if (wCoGetClassExt(szExt, pcid) != 0)
+ {
+ hresult = ResultFromScode(MK_E_INVALIDEXTENSION);
+ }
+
+
+errRet:
+
+ if (INVALID_HANDLE_VALUE != hFile)
+ {
+ CloseHandle(hFile);
+ }
+
+ if (hresult != NOERROR)
+ {
+ *pcid = CLSID_NULL;
+ }
+
+ return hresult;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetClassFile
+//
+// Synopsis: returns the classid associated with a file
+//
+// Arguments: [lpszFileName] -- name of the file
+// [pcid] -- where to return the clsid
+//
+// Returns: S_OK if clisd determined
+//
+// Algorithm: just calls GetClassFileEx
+//
+// History: 1-16-94 kevinro Created
+//
+//----------------------------------------------------------------------------
+STDAPI GetClassFile( LPCWSTR lpszFileName, CLSID FAR *pcid )
+{
+ OLETRACEIN((API_GetClassFile, PARAMFMT("lpszFileName= %ws, pcid= %p"),
+ lpszFileName, pcid));
+
+ HRESULT hr;
+
+ hr = GetClassFileEx (lpszFileName, pcid, CLSID_NULL);
+
+ OLETRACEOUT((API_GetClassFile, hr));
+
+ return hr;
+}
+
+
+#ifdef _TRACKLINK_
+STDMETHODIMP CFileMoniker::Reduce (LPBC pbc,
+ DWORD dwReduceHowFar,
+ LPMONIKER FAR* ppmkToLeft,
+ LPMONIKER FAR * ppmkReduced)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CFileMoniker::Reduce(%x)\n",this));
+
+ M_PROLOG(this);
+
+ CLock lck(m_mxs); // protect all internal state
+
+ VDATEPTROUT(ppmkReduced,LPMONIKER);
+ VDATEIFACE(pbc);
+ if (ppmkToLeft)
+ {
+ VDATEPTROUT(ppmkToLeft,LPMONIKER);
+ if (*ppmkToLeft) VDATEIFACE(*ppmkToLeft);
+ }
+
+ HRESULT hr=E_FAIL;
+ IMoniker *pmkNew=NULL;
+ BOOL fReduceToSelf = TRUE;
+
+ *ppmkReduced = NULL;
+
+ //
+ // search for the file
+ //
+
+ if ( m_fIsTracking
+ ||
+ ( m_fTrackingEnabled && m_fReduceEnabled )
+ )
+ {
+ // Resolve the ShellLink object.
+
+ if( SUCCEEDED( ResolveShellLink( pbc )))
+ {
+
+ Assert(m_szPath != NULL);
+
+ // Use the path that we now know is up-to-date, to create
+ // a default (i.e., non-tracking) File Moniker.
+
+ hr = CreateFileMoniker(m_szPath, ppmkReduced); // expensive
+
+ if (hr == S_OK)
+ fReduceToSelf = FALSE;
+
+ } // if( SUCCEEDED( ResolveShellLink( pbc )))
+ } // if ( m_fIsTracking || ...
+
+
+ if (fReduceToSelf)
+ {
+ *ppmkReduced = this;
+ AddRef();
+ hr = MK_S_REDUCED_TO_SELF;
+ }
+
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::Reduce exit with hr=%08X.\n",
+ this,
+ hr));
+ return(hr);
+}
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: FileBindToObject
+//
+// Synopsis: Given a filename, and some other information, bind to the
+// file and load it.
+//
+// Effects: This routine is used to load an object when the caller to
+// CFileMoniker::BindToObject had provided its own bind context.
+
+ //If pmkToLeft != 0, then we have a moniker on the left of the
+ //file moniker. The file moniker will use pmkToLeft to bind to
+ //either the IClassFactory or the IClassActivator interface.
+ //
+ //If protSystem != prot, then the bind context has supplied a
+ //non-standard ROT. CoGetInstanceFromFile and CoGetPersistentInstance
+ //only search the standard ROT. Therefore we cannot call
+ //CoGetInstanceFromFile or CoGetPersistentInstance in this case.
+
+//
+// Arguments: [pmkThis] -- Moniker being bound
+// [pwzPath] -- Path to bind
+// [clsid] -- CLSID for path
+// [pbc] -- The bind context - Not ours! Make no assumptions
+// [pmkToLeft] -- Moniker to left
+// [riidResult] -- IID being requested
+// [ppvResult] -- punk for result
+//
+//----------------------------------------------------------------------------
+INTERNAL FileBindToObject
+ (LPMONIKER pmkThis,
+ LPWSTR pwzPath,
+ REFCLSID clsid,
+ LPBC pbc,
+ BIND_OPTS2 *pBindOptions,
+ LPMONIKER pmkToLeft,
+ REFIID riidResult,
+ LPVOID FAR* ppvResult)
+{
+ HRESULT hr;
+ LPPERSISTFILE pPF = NULL;
+
+ *ppvResult = NULL;
+
+ //Get an IPersistFile interface pointer.
+ if(0 == pmkToLeft)
+ {
+ if ( pBindOptions->pServerInfo )
+ {
+ MULTI_QI MultiQi;
+
+ MultiQi.pIID = &IID_IPersistFile;
+ MultiQi.pItf = 0;
+
+ hr = CoCreateInstanceEx(clsid, NULL,
+ pBindOptions->dwClassContext,
+ pBindOptions->pServerInfo,
+ 1, &MultiQi );
+
+ pPF = (IPersistFile *) MultiQi.pItf;
+ }
+ else
+ {
+ hr = CoCreateInstance(clsid, NULL,
+ pBindOptions->dwClassContext,
+ IID_IPersistFile,
+ (void **) &pPF);
+ }
+ }
+ else
+ {
+ IClassActivator *pActivator;
+ IClassFactory *pFactory = 0;
+
+ //Bind to IClassActivator interface.
+ hr = pmkToLeft->BindToObject(pbc,
+ 0,
+ IID_IClassActivator,
+ (void **) &pActivator);
+
+ if(SUCCEEDED(hr))
+ {
+ hr = pActivator->GetClassObject(clsid,
+ pBindOptions->dwClassContext,
+ pBindOptions->locale,
+ IID_IClassFactory,
+ (void **) &pFactory);
+ pActivator->Release();
+ }
+ else
+ {
+ //Bind to the IClassFactory interface.
+ hr = pmkToLeft->BindToObject(pbc,
+ 0,
+ IID_IClassFactory,
+ (void **) &pFactory);
+ }
+
+ if(SUCCEEDED(hr) && pFactory != 0)
+ {
+ //Create an instance and get the IPersistFile interface.
+ hr = pFactory->CreateInstance(0,
+ IID_IPersistFile,
+ (void **) &pPF);
+ pFactory->Release();
+ }
+ }
+
+ //Load the instance from the file.
+ if(SUCCEEDED(hr))
+ {
+ hr = pPF->Load(pwzPath, pBindOptions->grfMode);
+ if (SUCCEEDED(hr))
+ {
+ hr = pPF->QueryInterface(riidResult, ppvResult);
+ }
+ pPF->Release();
+ }
+ else if(E_NOINTERFACE == hr)
+ {
+ hr = MK_E_INTERMEDIATEINTERFACENOTSUPPORTED;
+ }
+
+ return hr;
+}
+
+
+/*
+BindToObject takes into account AutoConvert and TreatAs keys when
+determining which class to use to bind. It does not blindly use the
+CLSID returned by GetClassFileEx. This is to allow a new OLE2
+server to service links (files) created with its previous OLE1 or OLE2
+version.
+
+This can produce some strange behavior in the follwoing (rare) case.
+Suppose you have both an OLE1 version (App1) and an OLE2 version
+(App2) of a server app on your machine, and the AutoConvert key is
+present. Paste link from App1 to an OLE2 container. The link will
+not be connected because BindToObject will try to bind
+using 2.0 behavior (because the class has been upgraded) rather than 1.0
+behavior (DDE). Ideally, we would call DdeIsRunning before doing 2.0
+binding. If you shut down App1, then you will be able to bind to
+App2 correctly.
+*/
+
+STDMETHODIMP CFileMoniker::BindToObject ( LPBC pbc,
+ LPMONIKER pmkToLeft, REFIID riidResult, LPVOID FAR* ppvResult)
+{
+ mnkDebugOut((DEB_ITRACE,"CFileMoniker(%x)::BindToObject\n",this));
+
+ m_mxs.Request();
+ BOOL bGotLock = TRUE;
+
+ wValidateMoniker();
+
+
+ A5_PROLOG(this);
+ VDATEPTROUT (ppvResult, LPVOID);
+ *ppvResult = NULL;
+ VDATEIFACE (pbc);
+ if (pmkToLeft)
+ {
+ VDATEIFACE (pmkToLeft);
+ }
+ VDATEIID (riidResult);
+ HRESULT hr;
+ CLSID clsid;
+ LPRUNNINGOBJECTTABLE prot = NULL;
+ LPRUNNINGOBJECTTABLE protSystem = NULL;
+ LPUNKNOWN pUnk = NULL;
+ BIND_OPTS2 bindopts;
+ BOOL fOle1Loaded;
+
+#ifdef _CAIRO_
+ // Resolve the link source for tracking monikers. This will cause its
+ // file attributes to be updated, including its name & location if the
+ // file has been moved.
+ if( m_fIsTracking )
+ {
+ hr = ResolveShellLink(pbc))
+ if(FAILED(hr))
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::BindToObject Resolve failed %08X.\n",
+ this,
+ hr));
+ goto exitRtn;
+ }
+ }
+#endif // _CAIRO_
+
+ //Get the bind options from the bind context.
+ bindopts.cbStruct = sizeof(bindopts);
+ hr = pbc->GetBindOptions(&bindopts);
+
+ if(FAILED(hr))
+ {
+ //Try the smaller BIND_OPTS size.
+ bindopts.cbStruct = sizeof(BIND_OPTS);
+ hr = pbc->GetBindOptions(&bindopts);
+ if(FAILED(hr))
+ {
+ goto exitRtn;
+ }
+ }
+
+ if(bindopts.cbStruct < sizeof(BIND_OPTS2))
+ {
+ //Initialize the new BIND_OPTS2 fields
+ bindopts.dwTrackFlags = 0;
+ bindopts.locale = GetThreadLocale();
+ bindopts.pServerInfo = 0;
+
+#ifdef WX86OLE
+ bindopts.dwClassContext = gcwx86.IsWx86Enabled() ?
+ CLSCTX_SERVER | CLSCTX_INPROC_SERVERX86 :
+ CLSCTX_SERVER;
+#else
+ bindopts.dwClassContext = CLSCTX_SERVER;
+#endif //WX86OLE
+ }
+
+
+ hr = GetRunningObjectTable(0,&protSystem);
+ if(SUCCEEDED(hr))
+ {
+ // Get the Bind Contexts version of the ROT
+ hr = pbc->GetRunningObjectTable( &prot );
+ if(SUCCEEDED(hr))
+ {
+ // first snapshot some member data and unlock
+ CLSID TempClsid = m_clsid;
+ TCHAR TempPath[MAX_PATH+1];
+ olever NewOleVer = m_ole1;
+ BOOL fUpdated = FALSE;
+
+ lstrcpyW( TempPath, m_szPath );
+
+ bGotLock = FALSE;
+ m_mxs.Release();
+
+ if((prot == protSystem) && (0 == pmkToLeft))
+ {
+ //This is the normal case.
+ //Bind to the object.
+#ifdef DCOM
+ MULTI_QI QI_Block;
+ QI_Block.pItf = NULL;
+ QI_Block.pIID = &riidResult;
+ CLSID * pClsid = &TempClsid;
+
+ if ( IsEqualGUID( GUID_NULL, m_clsid ) )
+ pClsid = NULL;
+
+ hr = CoGetInstanceFromFile(bindopts.pServerInfo,
+ pClsid,
+ NULL,
+ bindopts.dwClassContext,
+ bindopts.grfMode,
+ TempPath,
+ 1,
+ &QI_Block);
+ *ppvResult = (LPVOID) QI_Block.pItf;
+#else // !DCOM
+ hr = CoGetPersistentInstance(riidResult,
+ bindopts.dwClassContext,
+ bindopts.grfMode,
+ TempPath,
+ NULL,
+ TempClsid,
+ &fOle1Loaded,
+ ppvResult);
+#endif // !DCOM
+ }
+ else // prot != protSystem or pmkToLeft exists
+ {
+
+ mnkDebugOut((DEB_ITRACE,"::BindToObject using non-standard ROT\n"));
+
+ //Search the ROT for the object.
+ hr = prot->GetObject(this, &pUnk);
+ if (SUCCEEDED(hr))
+ {
+ // Found in the ROT. Try and get the interface and return
+ mnkDebugOut((DEB_ITRACE,"::BindToObject Found object in ROT\n"));
+ hr = pUnk->QueryInterface(riidResult, ppvResult);
+ pUnk->Release();
+ }
+ else
+ {
+ //Object was not found in the ROT. Get the class ID,
+ //then load the object from the file.
+ mnkDebugOut((DEB_ITRACE,"::BindToObject doing old style bind\n"));
+
+ hr = GetClassFileEx (TempPath, &clsid,TempClsid);
+
+ if (hr == NOERROR)
+ {
+ UpdateClsid (&clsid); // See note above
+ if (CoIsOle1Class (clsid))
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "::BindToObject found OLE1.0 class\n"));
+ COleTls Tls;
+ if( Tls->dwFlags & OLETLS_DISABLE_OLE1DDE )
+ {
+ // If this app doesn't want or can tolerate having a DDE
+ // window then currently it can't use OLE1 classes because
+ // they are implemented using DDE windows.
+ //
+ hr = CO_E_OLE1DDE_DISABLED;
+ }
+ else // DDE not disabled
+ {
+ hr = DdeBindToObject (TempPath,
+ clsid,
+ FALSE,
+ riidResult,
+ ppvResult);
+ {
+ NewOleVer = ole1;
+ TempClsid = clsid;
+ m_fClassVerified = TRUE;
+ fUpdated = TRUE;
+ }
+ }
+ }
+ else // Not OLE 1 class
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "::BindToObject found OLE2.0 class\n"));
+ hr = FileBindToObject (this,
+ TempPath,
+ clsid,
+ pbc,
+ &bindopts,
+ pmkToLeft,
+ riidResult,
+ ppvResult);
+ {
+ NewOleVer = ole2;
+ TempClsid = clsid;
+ m_fClassVerified = TRUE;
+ fUpdated = TRUE;
+ }
+ }
+ }
+ else
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "::BindToObject failed GetClassFileEx %x\n",
+ hr));
+ }
+ }
+ }
+ prot->Release();
+ if (fUpdated)
+ {
+ // note that the lock is never held at this point...
+ CLock lck(m_mxs);
+ m_ole1 = NewOleVer;
+ m_clsid = TempClsid;
+ }
+ }
+ else
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "::BindToObject failed pbc->GetRunningObjectTable() %x\n",
+ hr));
+ }
+ protSystem->Release();
+ }
+ else
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "::BindToObject failed GetRunningObjectTable() %x\n",
+ hr));
+ }
+
+
+exitRtn:
+ mnkDebugOut((DEB_ITRACE,
+ "CFileMoniker(%x)::BindToObject returns %x\n",
+ this,
+ hr));
+
+ // make sure we exit with the lock clear in case of errors.
+ if ( bGotLock )
+ m_mxs.Release();
+
+ return hr;
+}
+
+
+BOOL Peel( LPWSTR lpszPath, USHORT endServer, LPWSTR FAR * lplpszNewPath, ULONG n )
+// peels off the last n components of the path, leaving a delimiter at the
+// end. Returns the address of the new path via *lplpszNewPath. Returns
+// false if an error occurred -- e.g., n too large, trying to peel off a
+// volume name, etc.
+{
+WCHAR FAR* lpch;
+ULONG i = 0;
+ULONG j;
+WCHAR FAR* lpszRemainingPath; // ptr to beginning of path name minus the share name
+
+ if (*lpszPath == '\0') return FALSE;
+
+ //
+ // Find the end of the string and determine the string length.
+ //
+
+ for (lpch=lpszPath; *lpch; lpch++);
+
+ DecLpch (lpszPath, lpch); // lpch now points to the last real character
+
+// if n == 0, we dup the string, possibly adding a delimiter at the end.
+
+ if (n == 0)
+ {
+ i = lstrlenW(lpszPath);
+
+ if (!IsSeparator(*lpch))
+ {
+ j = 1;
+ }
+ else
+ {
+ j = 0;
+ }
+
+ *lplpszNewPath = (WCHAR *) PrivMemAlloc((i + j + 1) * sizeof(WCHAR));
+
+ if (*lplpszNewPath == NULL)
+ {
+ return FALSE;
+ }
+
+ memcpy(*lplpszNewPath, lpszPath, i * sizeof(WCHAR));
+
+ if (j == 1)
+ {
+ *(*lplpszNewPath + i) = '\\';
+ }
+
+ *(*lplpszNewPath + i + j) = '\0';
+
+ return TRUE;
+ }
+
+
+ if (DEF_ENDSERVER == endServer)
+ endServer = 0;
+
+ lpszRemainingPath = lpszPath + endServer; // if endServer > 0 the remaining path will be in the form of \dir\file
+
+
+#ifdef _DEBUG
+ if (endServer)
+ {
+ Assert(lpszRemainingPath[0] == '\\');
+ }
+#endif // _DEBUG
+
+ if (lpch < lpszRemainingPath)
+ {
+ AssertSz(0,"endServer Value is larger than Path");
+ return FALSE;
+ }
+
+ for (i = 0; i < n; i++)
+ {
+ if (IsSeparator(*lpch))
+ {
+ DecLpch(lpszPath, lpch);
+ }
+ if ((lpch < lpszRemainingPath) || (*lpch == ':') || (IsSeparator(*lpch)))
+ {
+ return FALSE;
+ }
+
+ // n is too large, or we hit two delimiters in a row, or a volume name.
+
+ while( !IsSeparator(*lpch) && (lpch > lpszRemainingPath) )
+ {
+ DecLpch(lpszPath, lpch);
+ }
+ }
+
+ // lpch points to the last delimiter we will leave or lpch == lpszPath
+ // REVIEW: make sure we haven't eaten into the volume name
+
+ if (lpch == lpszPath)
+ {
+ *lplpszNewPath = (WCHAR *) PrivMemAlloc(1 * sizeof(WCHAR));
+
+ if (*lplpszNewPath == NULL)
+ {
+ return FALSE;
+ }
+
+ **lplpszNewPath = '\0';
+ }
+ else
+ {
+ *lplpszNewPath = (WCHAR *) PrivMemAlloc(
+ (lpch - lpszPath + 2) * sizeof(WCHAR));
+
+ if (*lplpszNewPath == NULL) return FALSE;
+
+ memcpy(*lplpszNewPath,lpszPath,(lpch - lpszPath + 1) * sizeof(WCHAR));
+ *(*lplpszNewPath + (lpch - lpszPath) + 1) = '\0';
+ }
+
+
+ return TRUE;
+}
+
+
+
+STDMETHODIMP CFileMoniker::BindToStorage (LPBC pbc, LPMONIKER
+ pmkToLeft, REFIID riid, LPVOID FAR* ppvObj)
+{
+ wValidateMoniker();
+ M_PROLOG(this);
+
+ CLock lck(m_mxs); // protect all internal state
+
+ VDATEPTROUT (ppvObj, LPVOID);
+ *ppvObj = NULL;
+ VDATEIFACE (pbc);
+
+ if (pmkToLeft)
+ {
+ VDATEIFACE (pmkToLeft);
+ }
+ VDATEIID (riid);
+
+ *ppvObj = NULL;
+ HRESULT hresult = NOERROR;
+
+ BIND_OPTS bindopts;
+ bindopts.cbStruct = sizeof(BIND_OPTS);
+
+
+ hresult = pbc->GetBindOptions(&bindopts);
+ if FAILED(hresult)
+ goto errRet;
+
+ // Resolve the link source for tracking monikers. This will cause
+ // its file attributes to be updated, including its name & location
+ // if the file has been moved.
+
+#ifdef _CAIRO_
+ if( m_fIsTracking )
+ {
+ hresult = ResolveShellLink( pbc );
+ if( FAILED(hresult))
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::BindToStorage Resolve failed %08X.\n",
+ this,
+ hresult));
+ goto errRet;
+ }
+ }
+#endif // _CAIRO_
+
+
+ // Bind to the storage.
+
+ if (IsEqualIID(riid, IID_IStorage))
+ {
+ hresult = StgOpenStorage( m_szPath, NULL, bindopts.grfMode, NULL, 0, (LPSTORAGE FAR*)ppvObj );
+ }
+ else if (IsEqualIID(riid, IID_IStream))
+ {
+ hresult = ResultFromScode(E_UNSPEC); // unimplemented until CreateStreamOnFile is implemented
+
+ }
+ else if (IsEqualIID(riid, IID_ILockBytes))
+ {
+ hresult = ResultFromScode(E_UNSPEC); // unimplemented until CreateILockBytesOnFile is implemented
+ }
+ else
+ {
+ // CFileMoniker:BindToStorage called for unsupported interface
+ hresult = ResultFromScode(E_NOINTERFACE);
+ }
+
+
+ // REVIEW: CFileMoniker:BindToStorage being called for unsupported interface
+
+errRet:
+ return hresult;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::ComposeWith
+//
+// Synopsis: Compose another moniker to the end of this
+//
+// Effects: Given another moniker, create a composite between this
+// moniker and the other. If the other is also a CFileMoniker,
+// then collapse the two monikers into a single one by doing a
+// concatenate on the two paths.
+//
+// Arguments: [pmkRight] --
+// [fOnlyIfNotGeneric] --
+// [ppmkComposite] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 3-03-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CFileMoniker::ComposeWith ( LPMONIKER pmkRight,
+ BOOL fOnlyIfNotGeneric, LPMONIKER FAR* ppmkComposite)
+{
+ CLock lck(m_mxs); // protect all internal state
+
+ wValidateMoniker();
+ M_PROLOG(this);
+ VDATEPTROUT (ppmkComposite, LPMONIKER);
+ *ppmkComposite = NULL;
+ VDATEIFACE (pmkRight);
+
+ HRESULT hresult = NOERROR;
+ CFileMoniker FAR* pcfmRight;
+ LPWSTR lpszLeft = NULL;
+ LPWSTR lpszRight;
+ LPWSTR lpszComposite;
+ CFileMoniker FAR* pcfmComposite;
+ int n1;
+ int n2;
+
+ *ppmkComposite = NULL;
+
+ //
+ // If we are being composed with an Anti-Moniker, then return
+ // the resulting composition. The EatOne routine will take care
+ // of returning the correct composite of Anti monikers (or NULL)
+ //
+
+ CAntiMoniker *pCAM = IsAntiMoniker(pmkRight);
+ if(pCAM)
+ {
+ pCAM->EatOne(ppmkComposite);
+ return(NOERROR);
+ }
+
+ //
+ // If the moniker is a CFileMoniker, then collapse the two monikers
+ // into one by doing a concate of the two strings.
+ //
+
+ if ((pcfmRight = IsFileMoniker(pmkRight)) != NULL)
+ {
+ lpszRight = pcfmRight->m_szPath;
+
+ // lpszRight may be NULL
+
+ if (NULL == lpszRight)
+ lpszRight = L"";
+
+ if (( *lpszRight == 0) &&
+ pcfmRight->m_cAnti == 0)
+ {
+ // Second moniker is "". Simply return the first.
+ *ppmkComposite = this;
+ AddRef();
+ return NOERROR;
+ }
+
+ //
+ // If the path on the right is absolute, then there is a
+ // syntax error. The path is invalid, since you can't
+ // concat d:\foo and d:\bar to get d:\foo\d:\bar and
+ // expect it to work.
+ //
+ if (IsAbsolutePath(lpszRight))
+ {
+ return(MK_E_SYNTAX);
+ }
+
+ //
+ // If the right moniker has m_cAnti != 0, then peel back
+ // the path
+ //
+
+ if (Peel(m_szPath,m_endServer, &lpszLeft, pcfmRight->m_cAnti))
+ {
+ // REVIEW: check that there is no volume name at the start
+ // skip over separator
+
+ while (IsSeparator(*lpszRight)) lpszRight++;
+
+ n1 = lstrlenW(lpszLeft);
+
+ n2 = lstrlenW(lpszRight);
+
+ lpszComposite = (WCHAR *) PrivMemAlloc((n1 + n2 + 1)*sizeof(WCHAR));
+
+ if (!lpszComposite)
+ {
+ hresult = E_OUTOFMEMORY;
+ }
+ else
+ {
+ memcpy(lpszComposite, lpszLeft, n1 * sizeof(WCHAR));
+ memcpy(lpszComposite + n1, lpszRight, n2 * sizeof(WCHAR));
+
+ lpszComposite[n1 + n2] = '\0';
+
+ pcfmComposite = CFileMoniker::Create(lpszComposite,
+ m_cAnti,m_endServer);
+
+ if (pcfmComposite == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ }
+
+ else
+ {
+ // Is tracking moniker?
+
+#ifdef _CAIRO_
+ if( m_fIsTracking )
+ {
+ // Since this is a tracking moniker, we should get our TrackFlags
+ // and use them to make the composite a tracking moniker.
+
+ DWORD dwTrackFlags;
+
+ hresult = GetTrackFlags( &dwTrackFlags );
+
+ if( SUCCEEDED( hresult ))
+ {
+ // Make the composite a tracking moniker. Note that the
+ // Track Flags get piggy-backed onto the
+ // EnableTracking routine's OT flags.
+
+ hresult = pcfmComposite->EnableTracking(
+ NULL,
+ ( TRACK_2_OT_FLAGS( dwTrackFlags )
+ |
+ OT_MAKETRACKING
+ )
+ );
+
+ if( SUCCEEDED( hresult ))
+ {
+ *ppmkComposite = pcfmComposite;
+ pcfmComposite = NULL;
+ }
+ else
+ {
+ pcfmComposite->Release();
+ pcfmComposite = NULL;
+ }
+ }
+
+ } // if( m_fIsTracking )
+ else
+#endif // _CAIRO_
+ {
+ *ppmkComposite = pcfmComposite;
+ pcfmComposite = NULL;
+ }
+
+ } // if (pcfmComposite == NULL) ... else
+
+
+ PrivMemFree(lpszComposite);
+ } // if (!lpszComposite) ... else
+
+ if ( lpszLeft != NULL)
+ {
+ PrivMemFree(lpszLeft);
+ }
+ } // if (Peel(m_szPath, &lpszLeft, pcfmRight->m_cAnti))
+ else
+ {
+ // Peel failed, which means the caller attempted an
+ // invalid composition of file paths. There is apparently
+ // a syntax error in the names.
+ //
+ hresult = MK_E_SYNTAX;
+ } // if (Peel(m_szPath, &lpszLeft, pcfmRight->m_cAnti)) ... else
+ } // if ((pcfmRight = IsFileMoniker(pmkRight)) != NULL)
+ else
+ {
+ if (!fOnlyIfNotGeneric)
+ {
+ hresult = CreateGenericComposite( this, pmkRight, ppmkComposite );
+ }
+ else
+ {
+ hresult = MK_E_NEEDGENERIC;
+ *ppmkComposite = NULL;
+ }
+ } // if ((pcfmRight = IsFileMoniker(pmkRight)) != NULL) ... else
+
+ return hresult;
+}
+
+
+STDMETHODIMP CFileMoniker::Enum (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker)
+{
+ wValidateMoniker();
+ M_PROLOG(this);
+ VDATEPTROUT (ppenumMoniker, LPENUMMONIKER);
+ *ppenumMoniker = NULL;
+ // REVIEW: this says files monikers are not enumerable.
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP CFileMoniker::IsEqual (THIS_ LPMONIKER pmkOtherMoniker)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CFileMoniker::IsEqual(%x) m_szPath(%ws)\n",
+ this,
+ WIDECHECK(m_szPath)));
+
+ CLock lck(m_mxs); // protect all internal state
+
+ wValidateMoniker();
+ M_PROLOG(this);
+ VDATEIFACE (pmkOtherMoniker);
+
+ CFileMoniker FAR* pCFM = IsFileMoniker(pmkOtherMoniker);
+ if (!pCFM)
+ {
+ return ResultFromScode(S_FALSE);
+ }
+
+ if (pCFM->m_cAnti != m_cAnti)
+ {
+ return ResultFromScode(S_FALSE);
+ }
+
+ mnkDebugOut((DEB_ITRACE,
+ "::IsEqual(%x) m_szPath(%ws) pOther(%ws)\n",
+ this,
+ WIDECHECK(m_szPath),
+ WIDECHECK(pCFM->m_szPath)));
+
+ // for the paths, we just do a case-insensitive compare.
+ if (lstrcmpiW(pCFM->m_szPath, m_szPath) == 0)
+ {
+ return NOERROR;
+ }
+
+ return ResultFromScode(S_FALSE);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CalcFileMonikerHash
+//
+// Synopsis: Given a LPWSTR, calculate the hash value for the string.
+//
+// Effects:
+//
+// Arguments: [lp] -- String to compute has value for
+//
+// Requires:
+// Uses a MAX_PATH+1 sized buffer. Never pass a longer string,
+// or we will crash violently. The +1 accounts for the NULL
+// Returns:
+// DWORD hash value for string.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-15-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD CalcFileMonikerHash(LPWSTR lp)
+{
+ DWORD dwTemp = 0;
+ WCHAR ch;
+
+ //
+ // toupper turns out to be expensive, since it takes a
+ // critical section each and every time. It turns out to be
+ // much cheaper to make a local copy of the string, then upper the
+ // whole thing.
+ //
+
+ WCHAR pszTempPath[MAX_PATH+1];
+
+ if (lp == NULL)
+ {
+ return(0);
+ }
+ lstrcpyW(pszTempPath,lp);
+
+ CharUpperW(pszTempPath);
+
+ lp = pszTempPath;
+
+ while (*lp)
+ {
+ dwTemp *= 3;
+ ch = *lp;
+ dwTemp ^= ch;
+ lp++;
+ }
+
+ return dwTemp;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::Hash
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pdwHash] -- Output pointer for hash value
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-09-94 kevinro Modified
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CFileMoniker::Hash (THIS_ LPDWORD pdwHash)
+{
+ CLock lck(m_mxs); // protect m_fHashValueValid and m_dwHashValue
+ wValidateMoniker();
+
+ M_PROLOG(this);
+ VDATEPTROUT (pdwHash, DWORD);
+
+ //
+ // Calculating the hash value is expensive. Cache it.
+ //
+ if (!m_fHashValueValid)
+ {
+ m_dwHashValue = m_cAnti + CalcFileMonikerHash(m_szPath);
+
+ m_fHashValueValid = TRUE;
+ }
+
+ *pdwHash = m_dwHashValue;
+
+ wValidateMoniker();
+
+ return(NOERROR);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::IsRunning
+//
+// Synopsis: Determine if the object pointed to by the moniker is listed
+// as currently running.
+//
+// Effects:
+//
+// Arguments: [pbc] --
+// [pmkToLeft] --
+// [pmkNewlyRunning] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 3-03-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CFileMoniker::IsRunning (THIS_ LPBC pbc,
+ LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning)
+{
+ M_PROLOG(this);
+
+ CLock lck(m_mxs); // protect all internal state
+
+ VDATEIFACE (pbc);
+ LPRUNNINGOBJECTTABLE pROT;
+ HRESULT hresult;
+
+ //
+ // According to the spec, CFileMoniker ignores the
+ // moniker to the left.
+ //
+ if (pmkToLeft)
+ {
+ VDATEIFACE (pmkToLeft);
+ }
+
+ if (pmkNewlyRunning)
+ {
+ VDATEIFACE (pmkNewlyRunning);
+ }
+
+
+ CLSID clsid;
+
+ if (IsOle1Class(&clsid))
+ {
+ return DdeIsRunning (clsid, m_szPath, pbc, pmkToLeft, pmkNewlyRunning);
+ }
+
+
+
+ if (pmkNewlyRunning != NULL)
+ {
+ return pmkNewlyRunning->IsEqual (this);
+ }
+ hresult = pbc->GetRunningObjectTable (&pROT);
+ if (hresult == NOERROR)
+ {
+ hresult = pROT->IsRunning (this);
+ pROT->Release ();
+ }
+ return hresult;
+}
+
+
+
+STDMETHODIMP CFileMoniker::GetTimeOfLastChange (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime)
+{
+ M_PROLOG(this);
+
+ CLock lck(m_mxs); // protect all internal state
+
+ VDATEIFACE (pbc);
+ if (pmkToLeft) VDATEIFACE (pmkToLeft);
+ VDATEPTROUT (pfiletime, FILETIME);
+
+ HRESULT hresult;
+
+ LPMONIKER pmkTemp = NULL;
+ LPRUNNINGOBJECTTABLE prot = NULL;
+ LPWSTR lpszName = NULL;
+
+ WCHAR localBuffer[MAX_PATH+1];
+
+
+ if (pmkToLeft == NULL)
+ {
+ pmkTemp = this;
+ AddRef();
+ }
+ else
+ {
+ hresult = CreateGenericComposite(pmkToLeft, this, &pmkTemp );
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+ }
+
+ hresult = pbc->GetRunningObjectTable(&prot);
+
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+
+ // Attempt to get the time-of-last-change from the ROT. Note that
+ // if there is a File Moniker in 'pmkTemp', the ROT will Reduce it.
+ // Thus, if it is a *Tracking* File Moniker, it will be updated to reflect
+ // any changes to the file (such as location, timestamp, etc.)
+
+ hresult = prot->GetTimeOfLastChange(pmkTemp, pfiletime);
+
+ if (hresult != MK_E_UNAVAILABLE)
+ {
+ goto errRet;
+ }
+
+ //
+ // BUGBUG: Why aren't we just
+ // looking in the file moniker to the left. Is it possible to have
+ // another MKSYS_FILEMONIKER implementation?
+ //
+
+
+ if (IsFileMoniker(pmkTemp))
+ {
+ hresult = pmkTemp->GetDisplayName(pbc, NULL, &lpszName);
+
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+
+ if (lstrlenW(lpszName) < _MAX_PATH)
+ {
+ lstrcpyW(localBuffer, lpszName );
+ }
+ else
+ {
+ hresult = E_UNSPEC;
+ goto errRet;
+ }
+
+ // Attempt to get the file's attributes. If the file exists,
+ // give the modify time to the caller.
+
+#ifdef _CHICAGO_
+
+ HANDLE hdl;
+
+ WIN32_FIND_DATA fid;
+
+ if ((hdl = FindFirstFile(lpszName, &fid)) != INVALID_HANDLE_VALUE)
+ {
+ memcpy(pfiletime, &fid.ftLastWriteTime, sizeof(FILETIME));
+ FindClose(hdl);
+ hresult = S_OK;
+ }
+
+#else // _CHICAGO_
+
+ WIN32_FILE_ATTRIBUTE_DATA fad;
+
+ if( GetFileAttributesEx( lpszName, GetFileExInfoStandard, &fad ))
+ {
+ memcpy(pfiletime, &fad.ftLastWriteTime, sizeof(FILETIME));
+ hresult = S_OK;
+ }
+
+#endif // _CHICAGO_
+
+ else
+ {
+ hresult = ResultFromScode(MK_E_NOOBJECT);
+ }
+ }
+ else
+ {
+ hresult = ResultFromScode(E_UNSPEC);
+ }
+
+
+errRet:
+
+ if (prot != NULL)
+ {
+ prot->Release();
+ }
+
+ if (pmkTemp != NULL)
+ {
+ pmkTemp->Release();
+ }
+
+ if (lpszName != NULL)
+ {
+ CoTaskMemFree(lpszName);
+ }
+
+ return hresult;
+}
+
+
+
+STDMETHODIMP CFileMoniker::Inverse (THIS_ LPMONIKER FAR* ppmk)
+{
+ CLock lck(m_mxs); // protect all internal state
+
+ wValidateMoniker();
+
+ M_PROLOG(this);
+ VDATEPTROUT (ppmk, LPMONIKER);
+ return CreateAntiMoniker(ppmk);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CompareNCharacters
+//
+// Synopsis: Compare N characters, ignoring case and sort order
+//
+// Effects: We are interested only in whether the strings are the same.
+// Unlike wcscmp, which determines the sort order of the strings.
+// This routine should save us some cycles
+//
+// Arguments: [pwcThis] --
+// [pwcOther] --
+// [n] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-14-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL CompareNCharacters( LPWSTR pwcThis, LPWSTR pwcOther, ULONG n)
+{
+ while(n--)
+ {
+ if (CharUpperW((LPWSTR)*pwcThis) != CharUpperW((LPWSTR)*pwcOther))
+ {
+ return(FALSE);
+ }
+ pwcThis++;
+ pwcOther++;
+ }
+ return(TRUE);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CopyNCharacters
+//
+// Synopsis: Copy N characters from lpSrc to lpDest
+//
+// Effects:
+//
+// Arguments: [lpDest] -- Reference to lpDest
+// [lpSrc] -- Pointer to source characters
+// [n] --
+//
+// Requires:
+//
+// Returns:
+//
+// Returns with lpDest pointing to the end of the string. The string will
+// be NULL terminated
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-14-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+inline
+void CopyNCharacters( LPWSTR &lpDest, LPWSTR lpSrc, ULONG n)
+{
+ memcpy(lpDest,lpSrc,sizeof(WCHAR)*n);
+ lpDest += n;
+ *lpDest = 0;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DetermineLongestString
+//
+// Synopsis: Used by CommonPrefixWith to handle case where one string may
+// be longer than the other.
+// Effects:
+//
+// Arguments: [pwcBase] --
+// [pwcPrefix] --
+// [pwcLonger] --
+//
+// Requires:
+//
+// Returns: TRUE if all of pwcBase is a prefix of what pwcLonger is the
+// end of, or if tail of pwcBase is a separator.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-14-94 kevinro Created
+// 03-27-94 darryla Added special case where pwcPrefix is
+// pointing at terminator and previous char
+// is a separator.
+//
+// Notes:
+//
+// See CommonPrefixWith. This code isn't a general purpose routine, and is
+// fairly intimate with CommonPrefixWith.
+//
+//
+//----------------------------------------------------------------------------
+BOOL DetermineLongestString( LPWSTR pwcBase,
+ LPWSTR &pwcPrefix,
+ LPWSTR pwcLonger)
+
+{
+ //
+ // pwcPrefix is the end of the string that so far matches pwcLonger
+ // as a prefix.
+ //
+ // If the next character in pwcLonger is a seperator, then pwcPrefix
+ // is a complete prefix. Otherwise, we need to back pwcPrefix to the
+ // next prevous seperator character
+ //
+ if (IsSeparator(*pwcLonger))
+ {
+ //
+ // pwcPrefix is a true prefix
+ //
+ return TRUE;
+ }
+
+ // One more special case. If pwcPrefix is pointing at a terminator and
+ // the previous char is a separator, then this, too, is a valid prefix.
+ // It is easier to catch this here than to try to walk back to the
+ // separator and then determine if it was at the end.
+ if (*pwcPrefix == '\0' && IsSeparator(*(pwcPrefix - 1)))
+ {
+ //
+ // pwcPrefix is a true prefix ending with a separator
+ //
+ return TRUE;
+ }
+
+ //
+ // We now have a situtation where pwcPrefix holds a string that is
+ // might not be a prefix of pwcLonger. We need to start backing up
+ // until we find a seperator character.
+ //
+
+ LPWSTR pStart = pwcPrefix;
+
+ while (pwcPrefix > pwcBase)
+ {
+ if (IsSeparator(*pwcPrefix))
+ {
+ break;
+ }
+ pwcPrefix--;
+ }
+
+ //
+ // NULL terminate the output string.
+ //
+
+ *pwcPrefix = 0;
+
+ //
+ // If pStart == pwcPrefix, then we didn't actually back up anything, or
+ // we just removed a trailing backslash. If so, return TRUE, since the
+ // pwcPrefix is a prefix of pwcLonger
+ //
+ if (pStart == pwcPrefix)
+ {
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsEmptyString
+//
+// Synopsis: Determine if a string is 'Empty', which means either NULL
+// or zero length
+//
+// Effects:
+//
+// Arguments: [lpStr] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-25-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+inline
+BOOL IsEmptyString(LPWSTR lpStr)
+{
+ if ((lpStr == NULL) || (*lpStr == 0))
+ {
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::CommonPrefixWith
+//
+// Synopsis: Given two file monikers, determine the common prefix for
+// the two monikers.
+//
+// Effects: Computes a path that is the common prefix between the two
+// paths. It does this by string comparision, taking into
+// account the m_cAnti member, which counts the number of
+// preceeding dot dots constructs for each moniker.
+//
+// Arguments: [pmkOther] --
+// [ppmkPrefix] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-10-94 kevinro Created
+//
+// Notes:
+//
+// Welcome to some rather hairy code. Actually, it isn't all that bad,
+// there are just quite a few boundary cases that you will have to
+// contend with. I am sure if I thought about it long enough, there is
+// a better way to implement this routine. However, it really isn't
+// worth the effort, given the frequency at which this API is called.
+//
+// I have approached this in a very straightforward way. There is
+// room for optimization, but it currently isn't high enough on
+// the priority list.
+//
+// File monikers need to treat the end server with care. We actually
+// consider the \\server\share as a single component. Therefore, if
+// the two monikers are \\savik\win40\foo and \\savik\cairo\foo,
+// then \\savik is NOT a common prefix.
+//
+// Same holds true with the <drive>: case, where we need to treat
+// the drive as a unit
+//
+// To determine if two monikers have a common prefix, we look
+// down both paths watching for the first non-matching
+// character. When we find it, we need determine the correct
+// action to take.
+//
+// \\foo\bar and foo\bar shouldn't match
+// c:\foo\bar and c:\foo should return c:\foo
+// c:\foo\bar and c:\foobar should return c:\ .
+//
+// Be careful to handle the server case.
+//
+// \\savik\win40 and
+// \\savik\win40\src\foo\bar should return \\savik\win40
+// while \\savik\cairo should return MK_E_NOPREFIX
+//
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CFileMoniker::CommonPrefixWith (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix)
+{
+ CLock lck(m_mxs); // protect all internal state
+ return wCommonPrefixWith( pmkOther, ppmkPrefix );
+}
+
+STDMETHODIMP CFileMoniker::wCommonPrefixWith (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix)
+{
+ wValidateMoniker();
+
+ VDATEPTROUT (ppmkPrefix, LPMONIKER);
+ *ppmkPrefix = NULL;
+ VDATEIFACE (pmkOther);
+
+ CFileMoniker FAR* pcfmOther = NULL;
+ CFileMoniker FAR* pcfmPrefix = NULL;
+
+ HRESULT hresult = NOERROR;
+ USHORT cAnti;
+
+ //
+ // The following buffer will contain the matching prefix. We should
+ // be safe in MAX_PATH, since neither path can be longer than that.
+ // This was verified when the moniker was created, so no explicit
+ // checking is done in this routine
+ //
+
+ WCHAR awcMatchingPrefix[MAX_PATH + 1];
+ WCHAR *pwcPrefix = awcMatchingPrefix;
+
+ //
+ // Each subsection of the path will be parsed into the following
+ // buffer. This allows us to match each section of the path
+ // independently
+ //
+
+ WCHAR awcComponent[MAX_PATH + 1];
+ WCHAR *pwcComponent = awcComponent;
+
+
+ *pwcPrefix = 0; // Null terminate the empty string
+ *pwcComponent = 0; // Null terminate the empty string
+
+ //
+ // A couple temporaries to walk the paths.
+ //
+
+ LPWSTR pwcThis = NULL;
+ LPWSTR pwcOther = NULL;
+
+ HRESULT hrPrefixType = S_OK;
+
+ //
+ // If the other moniker isn't 'one of us', then get the generic system
+ // provided routine to handle the rest of this call.
+ //
+
+ if ((pcfmOther = IsFileMoniker(pmkOther)) == NULL)
+ {
+ return MonikerCommonPrefixWith(this, pmkOther, ppmkPrefix);
+ }
+
+ //
+ // If the m_cAnti fields are different, then match the minimum number of
+ // dotdots.
+ //
+ //
+ if (pcfmOther->m_cAnti != m_cAnti)
+ {
+ // differing numbers of ..\ at the beginning
+ cAnti = (m_cAnti > pcfmOther->m_cAnti ? pcfmOther->m_cAnti :m_cAnti );
+
+ if (cAnti == 0)
+ {
+ hresult = ResultFromScode(MK_E_NOPREFIX);
+ }
+ // pcfmPrefix is NULL
+ else
+ {
+ pcfmPrefix = CFileMoniker::Create(L"",
+ cAnti);
+ if (pcfmPrefix == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ goto exitRoutine;
+
+ }
+
+ // we must check to see if the final result is that same as
+ // this or pmkOther
+
+ hresult = NOERROR;
+
+ if (cAnti == m_cAnti)
+ {
+ if ((m_szPath==NULL)||(*m_szPath == '\0'))
+ {
+ hresult = MK_S_ME;
+ }
+ }
+ else
+ {
+ if ((pcfmOther->m_szPath == NULL ) ||
+ (*(pcfmOther->m_szPath) == '\0') )
+ {
+ hresult = MK_S_HIM;
+ }
+ }
+ }
+
+ goto exitRoutine;
+ }
+
+ //
+ // The number of leading dot-dots match. Therefore, we need to
+ // compare the paths also. If no path exists, then the common prefix
+ // is going to be the 'dot-dots'
+ //
+ cAnti = m_cAnti;
+
+ pwcThis = m_szPath;
+ pwcOther = pcfmOther->m_szPath;
+
+
+ //
+ // If either pointer is empty, then only the dotdots make for a prefix
+ //
+ if (IsEmptyString(pwcThis) || IsEmptyString(pwcOther))
+ {
+ //
+ // At least one of the strings was empty, therefore the common
+ // prefix is only the dotdots. Determine if its US, ME, or HIM
+ //
+
+ if (IsEmptyString(pwcThis) && IsEmptyString(pwcOther))
+ {
+ hrPrefixType = MK_S_US;
+ }
+ else if (IsEmptyString(pwcThis))
+ {
+ hrPrefixType = MK_S_ME;
+ }
+ else
+ {
+ hrPrefixType = MK_S_HIM;
+ }
+ goto onlyDotDots;
+ }
+
+ //
+ // The strings may be prefaced by either a UNC name, or a 'drive:'
+ // We treat both of these as a unit, and will only match prefixes
+ // on paths that match UNC servers, or match drives.
+ //
+ // If it is a UNC name, then m_endServer will be set to point at
+ // the end of the UNC name.
+ //
+ // First part of the match is to determine if the end servers are even
+ // close. If the offsets are different, the answer is no.
+ //
+
+ //
+ // The assertion at this point is that neither string is 'empty'
+ //
+ Assert( !IsEmptyString(pwcThis));
+ Assert( !IsEmptyString(pwcOther));
+
+ if (m_endServer != pcfmOther->m_endServer)
+ {
+ //
+ // End servers are different, match only the dotdots. Neither
+ // string is a complete
+ //
+
+ hrPrefixType = S_OK;
+
+ goto onlyDotDots;
+ }
+
+ //
+ // If the end servers are the default value, then look to see if
+ // this is an absolute path. Otherwise, copy over the server section
+ //
+
+ if (m_endServer == DEF_ENDSERVER)
+ {
+ BOOL fThisAbsolute = IsAbsoluteNonUNCPath(pwcThis);
+ BOOL fOtherAbsolute = IsAbsoluteNonUNCPath(pwcOther);
+ //
+ // If both paths are absolute, check for matching characters.
+ // If only one is absolute, then match the dot dots.
+ //
+ if (fThisAbsolute && fOtherAbsolute)
+ {
+ //
+ // Both absolute paths (ie 'c:' at the front)
+ // If not the same, only dotdots
+ //
+ if (CharUpperW((LPWSTR)*pwcThis) != CharUpperW((LPWSTR)*pwcOther))
+ {
+ //
+ // The paths don't match
+ //
+ hrPrefixType = S_OK;
+ goto onlyDotDots;
+ }
+
+ //
+ // The <drive>: matched. Copy it over
+ //
+ CopyNCharacters(pwcPrefix,pwcThis,2);
+ pwcThis += 2;
+ pwcOther += 2;
+ }
+ else if (fThisAbsolute || fOtherAbsolute)
+ {
+ //
+ // One path is absolute, the other isn't.
+ // Match only the dots
+ //
+ hrPrefixType = S_OK;
+ goto onlyDotDots;
+ }
+
+ //
+ // The fall through case does more path processing
+ //
+ }
+ else
+ {
+ //
+ // m_endServer is a non default value. Check to see if the
+ // first N characters match. If they don't, then only match
+ // the dotdots. If they do, copy them to the prefix buffer
+ //
+
+ if (!CompareNCharacters(pwcThis,pwcOther,m_endServer))
+ {
+ //
+ // The servers didn't match.
+ //
+ hrPrefixType = S_OK;
+ goto onlyDotDots;
+ }
+
+ //
+ // The UNC paths matched, copy them over
+ //
+
+ CopyNCharacters(pwcPrefix,pwcThis,m_endServer);
+
+ pwcThis += m_endServer;
+ pwcOther += m_endServer;
+ }
+
+ //
+ // Handle the root directory case. If BOTH monikers start
+ // with a backslash, then copy this to the prefix section.
+ // This allows for having '\foo' and '\bar' have the common
+ // prefix of '\'. The code below this section will remove
+ // any trailing backslashes.
+ //
+ // This also takes care of the case where you have a
+ // drive: or \\server\share, followed by a root dir.
+ // In either of these cases, we should return
+ // drive:\ or \\server\share\ respectively
+ //
+
+ if ((*pwcThis == '\\') && (*pwcOther == '\\'))
+ {
+ *pwcPrefix = '\\';
+ pwcThis++;
+ pwcOther++;
+ pwcPrefix++;
+ *pwcPrefix = 0;
+ }
+
+
+
+ //
+ // At this point, we have either matched the drive/server section,
+ // or have an empty string. Time to start copying over the rest
+ // of the data.
+ //
+
+ //
+ // Walk down the strings, looking for the first non-matching
+ // character
+ //
+
+ while (1)
+ {
+ if ((*pwcThis == 0) || (*pwcOther == 0))
+ {
+ //
+ // We have hit the end of one or both strings.
+ // awcComponent holds all of the matching
+ // characters so far. Break out of the loop
+ //
+ break;
+ }
+ if (CharUpperW((LPWSTR)*pwcThis) != CharUpperW((LPWSTR)*pwcOther))
+ {
+ //
+ // This is the first non-matching character.
+ // We should break out here.
+ //
+ break;
+ }
+
+ //
+ // At this point, the characters match, and are part
+ // of the common prefix. Copy it to the string, and move on
+ //
+
+ *pwcComponent = *pwcThis;
+ pwcThis++;
+ pwcOther++;
+ pwcComponent++;
+
+ //
+ // NULL terminate the current version of the component string
+ //
+ *pwcComponent = '\0';
+ }
+
+ //
+ // If both strings are at the end, then we have a
+ // complete match.
+ //
+
+ if ((*pwcThis == 0) && (*pwcOther == 0))
+ {
+ //
+ // Ah, this feels good. The strings ended up being
+ // the same length, with all matching characters.
+ //
+ // Therefore, we can just return one of us as the
+ // result.
+ //
+ pcfmPrefix = this;
+ AddRef();
+ hresult = MK_S_US;
+ goto exitRoutine;
+ }
+
+ //
+ // If one of the strings is longer than the other...
+ //
+ if ((*pwcThis == 0) || (*pwcOther == 0))
+ {
+ //
+ // Test to see if the next character in the longer string is a
+ // seperator character. If it isn't, then back up the string to
+ // the character before the previous seperator character.
+ //
+ // If TRUE then the shorter of the strings ends up being the
+ // entire prefix.
+ //
+ //
+ if( DetermineLongestString( awcComponent,
+ pwcComponent,
+ (*pwcThis == 0)?pwcOther:pwcThis) == TRUE)
+ {
+ if (*pwcThis == 0)
+ {
+ //
+ // This is the entire prefix
+ //
+ pcfmPrefix = this;
+ hresult = MK_S_ME;
+ }
+ else
+ {
+ //
+ // The other guy is the entire prefix
+ //
+ pcfmPrefix = pcfmOther;
+ hresult = MK_S_HIM;
+ }
+ pcfmPrefix->AddRef();
+ goto exitRoutine;
+ }
+ }
+ else
+ {
+ //
+ // Right now, pwcThis and pwcOther point at non-matching characters.
+ // Given the above tests, we know that neither character is
+ // == 0.
+ //
+ // Backup the string to the previous seperator. To do this, we
+ // will use DetermineLongestString, and pass it the string that
+ // doesn't have a seperator
+ //
+
+ DetermineLongestString( awcComponent,
+ pwcComponent,
+ IsSeparator(*pwcThis)?pwcOther:pwcThis);
+ }
+
+
+ //
+ // At this point, awcsComponent holds the second part of the string,
+ // while awcsPrefix holds the server or UNC prefix. Either of these
+ // may be NULL. Append awcComponent to the end of awcPrefix.
+ //
+
+ CopyNCharacters( pwcPrefix, awcComponent, pwcComponent - awcComponent);
+
+
+ //
+ // Check to see if anything matched.
+ //
+
+ if (pwcPrefix == awcMatchingPrefix)
+ {
+ //
+ // The only matching part is the dotdot count.
+ // This is easy, since we can just create a new
+ // moniker consisting only of dotdots.
+ //
+ // However, if there are no preceeding dotdots,
+ // then there was absolutely no prefix, which means
+ // we return MK_E_NOPREFIX
+ //
+ if (cAnti == 0)
+ {
+ hresult = MK_E_NOPREFIX;
+ goto exitRoutine;
+
+ }
+
+ //
+ // Nothing special about the moniker, so just return S_OK
+ //
+
+ hrPrefixType = S_OK;
+ goto onlyDotDots;
+
+ }
+
+ //
+ // Create a new file moniker using the awcMatchingPrefix
+ //
+
+ pcfmPrefix = CFileMoniker::Create(awcMatchingPrefix,0,cAnti);
+
+ if (pcfmPrefix == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ goto exitRoutine;
+ }
+ hresult = S_OK;
+
+exitRoutine:
+ *ppmkPrefix = pcfmPrefix; // null, or a file moniker
+ return hresult;
+
+
+onlyDotDots:
+ //
+ // We have determined that only the dotdot's match, so create a
+ // new moniker with the appropriate number of them.
+ //
+ // If there are no dotdots, then return NULL
+ //
+
+ if (cAnti == 0)
+ {
+ hresult = MK_E_NOPREFIX;
+ goto exitRoutine;
+ }
+
+ pcfmPrefix = CFileMoniker::Create(L"",0,cAnti);
+
+ if (pcfmPrefix == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ }
+ else
+ {
+ hresult = hrPrefixType;
+ }
+
+ goto exitRoutine;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::RelativePathTo
+//
+// Synopsis: Compute a relative path to the other moniker
+//
+// Effects:
+//
+// Arguments: [pmkOther] --
+// [ppmkRelPath] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-24-94 kevinro Created
+//
+// Notes:
+//
+// BUGBUG: (KevinRo)
+// This routine was really bad, and didn't generate correct results (aside
+// from the fact that it faulted). I replaced it with a slightly less
+// effiecient, but correct implementation.
+//
+// This can be improved on, but I currently have time restraints, so I am
+// not spending the needed amount of time. What really needs to happen is
+// the code that determines the common path prefix string from
+// CommonPrefixWith() should be broken out so this routine can share it.
+//
+// Thats more work that I can do right now, so we will just call CPW,
+// and use its result to compute the relative path. This results in an
+// extra moniker creation (allocate and construct only), but will work
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CFileMoniker::RelativePathTo (THIS_ LPMONIKER pmkOther,
+ LPMONIKER FAR*
+ ppmkRelPath)
+{
+ CLock lck(m_mxs); // protect all internal state
+
+ wValidateMoniker();
+
+ M_PROLOG(this);
+ VDATEPTROUT (ppmkRelPath, LPMONIKER);
+ *ppmkRelPath = NULL;
+ VDATEIFACE (pmkOther);
+
+ HRESULT hr;
+ CFileMoniker FAR* pcfmPrefix;
+ LPWSTR lpszSuffix;
+ LPWSTR lpszOther;
+
+ CFileMoniker FAR* pcfmRelPath = NULL;
+ CFileMoniker FAR* pcfmOther = IsFileMoniker(pmkOther);
+
+ if (!pcfmOther)
+ {
+ return MonikerRelativePathTo(this, pmkOther, ppmkRelPath, TRUE);
+ }
+
+ //
+ // Determine the common prefix between the two monikers. This generates
+ // a moniker which has a path that is the prefix between the two
+ // monikers
+ //
+
+ hr = CommonPrefixWith(pmkOther,(IMoniker **)&pcfmPrefix);
+
+ //
+ // If there was no common prefix, then the relative path is 'him'
+ //
+ if (hr == MK_E_NOPREFIX)
+ {
+ *ppmkRelPath = pmkOther;
+ pmkOther->AddRef();
+
+ return MK_S_HIM;
+ }
+
+ if (FAILED(hr))
+ {
+ *ppmkRelPath = NULL;
+ return(hr);
+ }
+
+ //
+ // At this point, the common prefix to the two monikers is in pcfmPrefix
+ // Since pcfmPrefix is a file moniker, we know that m_ccPath is the
+ // number of characters that matched in both moniker paths. To
+ // compute the relative part, we use the path from pmkOther, minus the
+ // first pcfmPrefix->m_ccPath characters.
+ //
+ // We don't want to start with a seperator. Therefore, skip over the
+ // first set of seperator characters. (Most likely, there aren't any).
+ //
+
+ lpszOther = pcfmOther->m_szPath + pcfmPrefix->m_ccPath;
+ lpszSuffix = m_szPath + pcfmPrefix->m_ccPath;
+
+ while ((*lpszSuffix != 0) && IsSeparator(*lpszSuffix))
+ {
+ lpszSuffix++;
+ }
+
+ //
+ // Create new file moniker that holds the prefix.
+ //
+
+ pcfmRelPath = CFileMoniker::Create(lpszOther,
+ CountSegments(lpszSuffix));
+
+ //
+ // At this point, we are all done with the prefix
+ //
+
+ pcfmPrefix->Release();
+
+ if (pcfmRelPath == NULL)
+ {
+ *ppmkRelPath = NULL;
+ return ResultFromScode(S_OOM);
+ }
+
+ *ppmkRelPath = pcfmRelPath;
+ return NOERROR;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::GetDisplayNameLength
+//
+// Synopsis: Returns the length of the display name if GenerateDisplayName
+// was called
+//
+// Effects:
+//
+// Returns: Length of display name in bytes
+//
+// Algorithm:
+//
+// History: 3-16-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+ULONG
+CFileMoniker::GetDisplayNameLength()
+{
+ CLock lck(m_mxs); // protect all internal state
+
+ // Number of characters in path plus number of anti components plus NULL
+ // All times the size of WCHAR
+ //
+ // Anti components look like '..\' in the string. 3 characters
+ ULONG ulLength = (m_ccPath + (3 * m_cAnti) + 1) * sizeof(WCHAR);
+
+ return(ulLength);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::GenerateDisplayName, private
+//
+// Synopsis: Generates a display name for this moniker.
+//
+// Effects:
+//
+// Arguments: [pwcDisplayName] -- A buffer that is at least as long as
+// GetDisplayNameLength
+//
+// Returns: void
+//
+// Algorithm:
+//
+// History: 3-16-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void
+CFileMoniker::GenerateDisplayName(LPWSTR pwcDisplayName)
+{
+ Assert(pwcDisplayName != NULL);
+
+ //
+ // The display name may need 'dotdots' at the front
+ //
+ for (USHORT i = 0; i < m_cAnti; i++)
+ {
+ memcpy(pwcDisplayName, L"..\\", 3 * sizeof(WCHAR));
+ pwcDisplayName += 3;
+ }
+
+ //
+ // don't duplicate '\' since the anti monikers may
+ // have already appended one. Copy rest of string
+ // over, including the NULL
+ //
+
+ if (m_cAnti > 0 && *m_szPath == '\\')
+ {
+ memcpy(pwcDisplayName, m_szPath + 1, m_ccPath * sizeof(WCHAR));
+ }
+ else
+ {
+ memcpy(pwcDisplayName, m_szPath, (m_ccPath + 1) * sizeof(WCHAR));
+ }
+}
+
+STDMETHODIMP CFileMoniker::GetDisplayName ( LPBC pbc, LPMONIKER
+ pmkToLeft, LPWSTR FAR * lplpszDisplayName )
+{
+
+ HRESULT hr = E_FAIL;
+
+ CLock lck(m_mxs); // protect all internal state
+
+ wValidateMoniker();
+ M_PROLOG(this);
+ VDATEPTROUT (lplpszDisplayName, LPWSTR);
+ *lplpszDisplayName = NULL;
+ VDATEIFACE (pbc);
+ if (pmkToLeft)
+ {
+ VDATEIFACE (pmkToLeft);
+ }
+
+ int n;
+ LPWSTR pch;
+ LPWSTR pchSrc;
+ DWORD cchSrc;
+ DWORD ulLen;
+
+#ifdef _CAIRO_
+ // First, if this is a tracking moniker, resolve it.
+
+ if( m_fIsTracking )
+ {
+ //
+ // Attempt to Resolve the moniker very quickly. That is, if it has
+ // moved within the local set of indexed (e.g. OFS) volumes, we will update the
+ // moniker and be able to give the correct display name to the user.
+ // If any stage of this process fails, the error is ignored,
+ // and we return the currently known display name to the caller.
+ //
+
+ QuickShellLinkResolve( pbc );
+
+ } // if( m_fIsTracking )
+
+#endif // _CAIRO_
+
+ ulLen = GetDisplayNameLength();
+
+ //
+ // cchSrc is the number of characters including the NULL. This will
+ // always be half the number of bytes.
+ //
+
+ cchSrc = ulLen >> 1;
+
+ (*lplpszDisplayName) = (WCHAR *) CoTaskMemAlloc(ulLen);
+
+ pch = *lplpszDisplayName;
+
+ if (!pch)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ //
+ // Call a common routine to generate the initial display name
+ //
+ GenerateDisplayName(pch);
+
+ // If we're in WOW, return short path names so that 16-bit apps
+ // don't see names they're not equipped to handle. This also
+ // affects 32-bit inproc DLLs in WOW; they'll need to be written
+ // to handle it
+ if (IsWOWProcess())
+ {
+ DWORD cchShort, cchDone;
+ LPOLESTR posCur;
+
+ posCur = *lplpszDisplayName;
+
+ // GetShortPathName only works on files that exist. Monikers
+ // don't have to refer to files that exist, so if GetShortPathName
+ // fails we just return whatever the moniker has as a path
+
+ // Special case zero-length paths since the length returns from
+ // GetShortPathName become ambiguous when zero characters are processed
+ cchShort = lstrlenW(posCur);
+ if (cchShort > 0)
+ {
+ cchShort = GetShortPathName(posCur, NULL, 0);
+ }
+
+ if (cchShort != 0)
+ {
+ LPOLESTR posShort;
+
+ // GetShortPathName can convert in place so if our source
+ // string is long enough, don't allocate a new string
+ if (cchShort <= cchSrc)
+ {
+ posShort = posCur;
+ cchShort = cchSrc;
+ }
+ else
+ {
+ posShort = (LPOLESTR)CoTaskMemAlloc(cchShort*sizeof(WCHAR));
+ if (posShort == NULL)
+ {
+ CoTaskMemFree(posCur);
+ *lplpszDisplayName = NULL;
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+ }
+ cchDone = GetShortPathName(posCur, posShort, cchShort);
+
+ // For both success and failure cases we're done with posCur,
+ // so get rid of it (unless we've reused it for the short name)
+ if (posShort != posCur)
+ {
+ CoTaskMemFree(posCur);
+ }
+
+ if (cchDone == 0 || cchDone > cchShort)
+ {
+ CoTaskMemFree(posShort);
+ *lplpszDisplayName = NULL;
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ *lplpszDisplayName = posShort;
+ }
+ }
+
+ hr = NOERROR;
+
+Exit:
+
+ return( hr );
+
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::ParseDisplayName
+//
+// Synopsis: Bind to object, and ask it to parse the display name given.
+//
+// Effects:
+//
+// Arguments: [pbc] -- Bind context
+// [pmkToLeft] -- Moniker to the left
+// [lpszDisplayName] -- Display name to be parsed
+// [pchEaten] -- Outputs the number of characters parsed
+// [ppmkOut] -- Output moniker
+//
+// Requires:
+// File-monikers never have monikers to their left
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-02-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CFileMoniker::ParseDisplayName ( LPBC pbc,
+ LPMONIKER pmkToLeft,
+ LPWSTR lpszDisplayName,
+ ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut)
+{
+
+ HRESULT hresult;
+ IParseDisplayName * pPDN = NULL;
+ CLSID cid;
+
+ VDATEPTROUT (ppmkOut, LPMONIKER);
+
+ *ppmkOut = NULL;
+
+ VDATEIFACE (pbc);
+
+ if (pmkToLeft)
+ {
+ VDATEIFACE (pmkToLeft);
+ }
+
+ VDATEPTRIN (lpszDisplayName, WCHAR);
+ VDATEPTROUT (pchEaten, ULONG);
+
+ //
+ // Since this is the most frequent case, try binding to the object
+ // itself first
+ //
+
+ hresult = BindToObject( pbc,
+ pmkToLeft,
+ IID_IParseDisplayName,
+ (VOID FAR * FAR *)&pPDN );
+
+ // we deferred doing this lock until after the BindToObject, in case the
+ // BindToObject is very slow. It manages locking internally to itself.
+ CLock lck(m_mxs); // protect all internal state
+
+
+ // If binding to the object failed, then try binding to the class object
+ // asking for the IParseDisplayName interface
+ if (FAILED(hresult))
+ {
+ hresult = GetClassFile(m_szPath, &cid);
+
+ if (SUCCEEDED(hresult))
+ {
+ hresult = CoGetClassObject(cid,
+#ifdef WX86OLE
+ gcwx86.IsWx86Enabled() ?
+ CLSCTX_INPROC |
+ CLSCTX_INPROC_SERVERX86 |
+ CLSCTX_INPROC_HANDLERX86 :
+ CLSCTX_INPROC,
+#else
+ CLSCTX_INPROC,
+#endif
+ NULL,
+ IID_IParseDisplayName,
+ (LPVOID FAR*)&pPDN);
+ }
+ if (FAILED(hresult))
+ {
+ goto errRet;
+ }
+ }
+
+ //
+ // Now that we have bound this object, we register it with the bind
+ // context. It will be released with the bind context release.
+ //
+
+ hresult = pbc->RegisterObjectBound(pPDN);
+
+ if (FAILED(hresult))
+ {
+ goto errRet;
+ }
+
+ //
+ // As the class code to parse the rest of the display name for us.
+ //
+
+ hresult = pPDN->ParseDisplayName(pbc,
+ lpszDisplayName,
+ pchEaten,
+ ppmkOut);
+errRet:
+ if (pPDN) pPDN->Release();
+ return hresult;
+}
+
+
+STDMETHODIMP CFileMoniker::IsSystemMoniker (THIS_ LPDWORD pdwType)
+{
+ M_PROLOG(this);
+ VDATEPTROUT (pdwType, DWORD);
+ *pdwType = MKSYS_FILEMONIKER;
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::ValidateAnsiPath
+//
+// Synopsis: This function validates the ANSI version of the path. Intended
+// to be used to get the serialized Ansi version of the path.
+//
+// This function also detects when a Long File Name exists, and
+// must be dealt with.
+//
+// Effects:
+//
+// This routine will set the Ansi path suitable for serializing
+// into the stream. This path may just use the stored ANSI path,
+// or may be a path that was created from the UNICODE version.
+//
+// If the ANSI version of the path doesn't exist, then the UNICODE
+// version of the path is converted to ANSI. There are several possible
+// conversions.
+//
+// First, if the path uses a format that is > 8.3, then the path to
+// be serialized needs to be the alternate name. This allows the
+// downlevel systems to access the file using the short name. This step
+//
+// If the UNICODE path is all ANSI characters already (no DBCSLeadBytes),
+// then the path is converted by doing a simple truncation algorithm.
+//
+// If the UNICODE path contains large characters, or DBCSLeadBytes,
+// then the routine will create a UNICODE extent, then try to convert
+// the UNICODE string into a ANSI path. If some of the characters
+// won't convert, then those characters are represented by an ANSI
+// character constant defined in the registry.
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+// m_pszAnsiPath
+// m_cbAnsiPath
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-09-94 kevinro Created
+// 05-24-94 AlexT Use GetShortPathNameW
+//
+// Notes:
+//
+// The path created may not actually be useful. It is quite possible
+// for there to be a path that will not convert correctly from UNICODE
+// to Ansi. In these cases, this routine will create a UNICODE extent.
+//
+//----------------------------------------------------------------------------
+
+HRESULT CFileMoniker::ValidateAnsiPath(void)
+{
+ wValidateMoniker();
+ HRESULT hr = NOERROR;
+
+ {
+ CLock lck(m_mxs); // protect m_pszAnsiPath, and m_cbAnsiPath
+ // also AddExtent (needed since mutext was removed from CExtentList).
+
+ mnkDebugOut((DEB_ITRACE,
+ "GetAnsiPath(%x) m_szPath(%ws)\n",
+ this,
+ m_szPath?m_szPath:L"<NULL>"));
+
+
+
+ BOOL fFastConvert = FALSE;
+
+ //
+ // If there is no path, return NULL
+ //
+ if (m_szPath == NULL)
+ {
+ goto NoError;
+ }
+
+ //
+ // If there is already an ANSI path, return, we are OK.
+ //
+
+ if (m_pszAnsiPath != NULL)
+ {
+ goto NoError;
+ }
+
+ // We can't call GetShortPathNameW with a NULL string. m_szPath can
+ // be "" as the result of CoCreateInstance of a file moniker or as
+ // the result of RelativePathTo being called on an identical file moniker
+ if ('\0' != *m_szPath)
+ {
+ OLECHAR szShortPath[MAX_PATH];
+ DWORD dwBytesCopied;
+
+ dwBytesCopied = GetShortPathName(m_szPath, szShortPath, MAX_PATH);
+
+ if (dwBytesCopied > 0 && dwBytesCopied <= MAX_PATH)
+ {
+ hr = MnkUnicodeToMulti(szShortPath,
+ lstrlenW(szShortPath),
+ m_pszAnsiPath,
+ m_cbAnsiPath,
+ fFastConvert);
+ if (FAILED(hr))
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "MnkUnicodeToMulti failed (%x) on %ws\n",
+ WIDECHECK(szShortPath)));
+ goto ErrRet;
+ }
+ }
+
+#if DBG==1
+ if (0 == dwBytesCopied)
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "GetShortPathName failed (%x) on %ws\n",
+ GetLastError(),
+ WIDECHECK(szShortPath)));
+
+ // let code below handle the path
+ }
+ else if (dwBytesCopied > MAX_PATH)
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "GetShortPathName buffer not large enough (%ld, %ld)\n",
+ MAX_PATH, dwBytesCopied,
+ WIDECHECK(szShortPath)));
+
+ // let code below handle the path
+ }
+#endif // DBG==1
+ }
+
+ //
+ // If there is no m_pszAnsiPath yet, then just convert
+ // the UNICODE path to the ANSI path
+ //
+ if (m_pszAnsiPath == NULL)
+ {
+ //
+ // There was no alternate file name
+ //
+ hr = MnkUnicodeToMulti( m_szPath,
+ m_ccPath,
+ m_pszAnsiPath,
+ m_cbAnsiPath,
+ fFastConvert);
+ if (FAILED(hr))
+ {
+ goto ErrRet;
+ }
+ }
+ else
+ {
+ //
+ // We have an alternate name. By setting
+ // fFastConvert to be FALSE, we force the
+ // following code to add a UNICODE extent
+ // if one doesn't exist.
+ //
+ fFastConvert = FALSE;
+ }
+
+ //
+ // If an extent doesn't already exist, and it wasn't a fast
+ // conversion, create a UNICODE extent.
+ //
+ if ( !m_fUnicodeExtent && !fFastConvert)
+ {
+ LPMONIKEREXTENT pExtent = NULL;
+
+ hr = CopyPathToUnicodeExtent(m_szPath,m_ccPath,pExtent);
+
+ if (FAILED(hr))
+ {
+ goto ErrRet;
+ }
+
+ hr = m_ExtentList.AddExtent(pExtent);
+
+ PrivMemFree(pExtent);
+
+ if (FAILED(hr))
+ {
+ goto ErrRet;
+ }
+ }
+
+NoError:
+
+ mnkDebugOut((DEB_ITRACE,
+ "GetAnsiPath(%x) m_pszAnsiPath(%s) m_cbAnsiPath(0x%x)\n",
+ this,
+ m_pszAnsiPath?m_pszAnsiPath:"<NULL>",
+ m_cbAnsiPath));
+ return(NOERROR);
+
+ErrRet:
+ mnkDebugOut((DEB_IERROR,
+ "GetAnsiPath(%x) Returning error hr(%x)\n",
+ this,
+ hr));
+
+ if (m_pszAnsiPath != NULL)
+ {
+ PrivMemFree(m_pszAnsiPath);
+
+ m_pszAnsiPath = NULL;
+ m_cbAnsiPath = 0;
+
+ }
+ }
+ wValidateMoniker();
+
+ return(hr);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: MnkUnicodeToMulti
+//
+// Synopsis: Convert a Unicode path to an Ansi path.
+//
+// Effects:
+//
+// Arguments: [pwcsWidePath] -- Unicode path
+// [ccWidePath] -- Wide character count
+// [pszAnsiPath] -- Reference
+// [cbAnsiPath] -- ref number of bytes in ANSI path incl NULL
+// [fFastConvert] -- Returns TRUE if fast conversion
+//
+// Requires:
+//
+// Returns:
+//
+// pszAnsiPath was allocated using PrivMemAlloc
+//
+// fFastConvert means that the ANSI and UNICODE paths were converted
+// by WCHAR->CHAR truncation.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-16-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT
+MnkUnicodeToMulti(LPWSTR pwcsWidePath,
+ USHORT ccWidePath,
+ LPSTR & pszAnsiPath,
+ USHORT & cbAnsiPath,
+ BOOL & fFastConvert)
+{
+
+ HRESULT hr = NOERROR;
+ ULONG cb;
+ BOOL fUsedDefaultChar = FALSE;
+
+ WCHAR *lp = pwcsWidePath;
+
+ fFastConvert = TRUE;
+
+ if (pwcsWidePath == NULL)
+ {
+ cbAnsiPath = 0;
+ pszAnsiPath = 0;
+ return(NOERROR);
+ }
+
+ //
+ // Lets hope for the best. If we can run the length of the
+ // unicode string, and all the characters are 1 byte long, and
+ // there are no conflicts with DBCSLeadBytes, then we
+ // can cheat and just do a truncation copy
+ //
+
+
+ while ( (*lp != 0) && (*lp == (*lp & 0xff)) && !IsDBCSLeadByte(*lp & 0xff))
+ {
+ lp++;
+ }
+ if (*lp == 0)
+ {
+ //
+ // We are at the end of the string, and we are safe to do our
+ // simple copy. We will assume the ANSI version of the path is
+ // going to have the same number of characters as the wide path
+ //
+ pszAnsiPath = (char *)PrivMemAlloc(ccWidePath + 1);
+
+ if (pszAnsiPath == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto ErrRet;
+ }
+
+ USHORT i;
+
+ //
+ // By doing i <= m_ccPath, we pick up the NULL
+ //
+
+ for (i = 0 ; i <= ccWidePath ; i++ )
+ {
+ pszAnsiPath[i] = pwcsWidePath[i] & 0xff;
+ }
+
+ //
+ // We just converted to a single byte path. The cb is the
+ // count of WideChar + 1 for the NULL
+ //
+ cbAnsiPath = ccWidePath + 1;
+
+ goto NoError;
+ }
+
+ //
+ // At this point, all of the easy out options have expired. We
+ // must convert the path the hard way.
+ //
+
+ fFastConvert = FALSE;
+
+ mnkDebugOut((DEB_ITRACE,
+ "MnkUnicodeToMulti(%ws) doing path conversions\n",
+ pwcsWidePath?pwcsWidePath:L"<NULL>"));
+
+ //
+ // We haven't a clue how large this path may be in bytes, other
+ // than some really large number. So, we need to call and find
+ // out the correct size to allocate for the path.
+ //
+ cb = WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ WC_COMPOSITECHECK | WC_DEFAULTCHAR,
+ pwcsWidePath,
+ ccWidePath + 1, // Convert the NULL
+ NULL,
+ 0,
+ NULL,
+ &fUsedDefaultChar);
+
+ if (cb == 0)
+ {
+ //
+ // Hmmm... Can't convert anything. Sounds like the downlevel
+ // guys are flat out of luck. This really isn't a hard error, its
+ // just an unfortunate fact of life. This is going to be a very
+ // rare situation, but one we need to handle gracefully
+ //
+
+ pszAnsiPath = NULL;
+ cbAnsiPath = 0;
+ }
+ else
+ {
+ //
+ // cb holds the number of bytes required for the output path
+ //
+ pszAnsiPath = (char *)PrivMemAlloc(cb + 1);
+
+ if (pszAnsiPath == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto ErrRet;
+ }
+ cbAnsiPath = (USHORT)cb;
+
+ cb = WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ WC_COMPOSITECHECK | WC_DEFAULTCHAR,
+ pwcsWidePath,
+ ccWidePath + 1, // Convert the NULL
+ pszAnsiPath,
+ cbAnsiPath,
+ NULL,
+ &fUsedDefaultChar);
+ //
+ // Again, if there was an error, its just unfortunate
+ //
+ if (cb == 0)
+ {
+ PrivMemFree(pszAnsiPath);
+ pszAnsiPath = NULL;
+ cbAnsiPath = 0;
+ }
+ }
+
+NoError:
+
+ return(NOERROR);
+
+ErrRet:
+
+ if (pszAnsiPath != NULL)
+ {
+ PrivMemFree(pszAnsiPath);
+
+ pszAnsiPath = NULL;
+
+ cbAnsiPath = 0;
+ }
+
+ return(hr);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: MnkMultiToUnicode
+//
+// Synopsis: Converts a MultiByte string to a Unicode string
+//
+// Effects:
+//
+// Arguments: [pszAnsiPath] -- Path to convert
+// [pWidePath] -- Output path
+// [ccWidePath] -- Size of output path
+// [ccNewString] -- Reference characters in new path
+// including the NULL
+// [nCodePage] -- Must be CP_ACP || CP_OEMCP. This is
+// the first code page to be used in
+// the attempted conversion. If the
+// conversion fails, the other CP is
+// tried.
+//
+// Requires:
+//
+// if pWidePath != NULL, then this routine uses pWidePath as the return
+// buffer, which should be ccWidePath in length.
+//
+// Otherwise, it will allocate a buffer on your behalf.
+//
+// Returns:
+//
+// pWidePath != NULL
+// ccNewString == number of characters in new path include NULL
+//
+// pWidePath == NULL (NULL string)
+//
+// if ccNewString returns 0, then pWidePath may not be valid. In this
+// case, there are no valid characters in pWidePath.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-16-94 kevinro Created
+// 2-3-95 scottsk Added nCodePage param
+//
+// Notes:
+//
+// Why so complex you ask? In the file moniker case, we want know that the
+// buffer can be MAX_PATH in length, so we pass a stack buffer in to handle
+// it. In the CItemMoniker case, the limit jumps to 32767 bytes, which is
+// too big to declare on the stack. I wanted to use the same routine for
+// both, since we may end up changing this later.
+//
+// Passing in your own buffer is best for this routine.
+//
+//----------------------------------------------------------------------------
+HRESULT MnkMultiToUnicode(LPSTR pszAnsiPath,
+ LPWSTR & pWidePath,
+ ULONG ccWidePath,
+ USHORT & ccNewString,
+ UINT nCodePage)
+{
+ LPWSTR pwcsTempPath = NULL;
+ HRESULT hr;
+
+ Assert(nCodePage == CP_ACP || nCodePage == CP_OEMCP);
+
+ //
+ // If the pszAnsiPath is NULL, then so should be the UNICODE one
+ //
+ if (pszAnsiPath == NULL)
+ {
+ ccNewString = 0;
+ return(NOERROR);
+ }
+
+ Assert( (pWidePath == NULL) || (ccWidePath > 0));
+
+ //
+ // If the buffer is NULL, be sure that ccWide is zero
+ //
+ if (pWidePath == NULL)
+ {
+ ccWidePath = 0;
+ }
+
+
+ConvertAfterAllocate:
+ ccNewString = MultiByteToWideChar(nCodePage,
+ MB_PRECOMPOSED,
+ pszAnsiPath,
+ -1,
+ pWidePath,
+ ccWidePath);
+ if (ccNewString == FALSE)
+ {
+ mnkDebugOut((DEB_IERROR,
+ "::MnkMultiToUnicode failed on (%s) err (%x)\n",
+ pszAnsiPath,
+ GetLastError()));
+ //
+ // We were not able to convert to UNICODE.
+ //
+ hr = E_UNEXPECTED;
+ goto errRet;
+ }
+
+
+ //
+ // ccNewString holds the total string length, including the terminating
+ // NULL.
+ //
+
+ if (pWidePath == NULL)
+ {
+ //
+ // The first time through did no allocations. Allocate the
+ // correct buffer, and actually do the conversion
+ //
+
+ pWidePath = (WCHAR *)PrivMemAlloc(sizeof(WCHAR)*ccNewString);
+
+ if (pWidePath == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto errRet;
+ }
+
+ pwcsTempPath = pWidePath;
+ ccWidePath = ccNewString;
+ goto ConvertAfterAllocate;
+ }
+
+ //
+ // ccNewString holds the total number of characters converted,
+ // including the NULL. We really want it to have the count of
+ // characeters
+ //
+
+ Assert (ccNewString != 0);
+
+ ccNewString--;
+
+ hr = NOERROR;
+ return(hr);
+
+errRet:
+ mnkDebugOut((DEB_IERROR,
+ "::MnkMultiToUnicode failed on (%s) err (%x)\n",
+ pszAnsiPath,
+ GetLastError()));
+
+ PrivMemFree(pwcsTempPath);
+ return(hr);
+
+}
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::DetermineUnicodePath
+//
+// Synopsis: Given the input path, determine the path to store and use
+// as the initialized path.
+//
+// Effects:
+//
+// When loading or creating a CFileMoniker, its possible that the 'path'
+// that was serialized is not valid. This occurs when the original
+// UNICODE path could not be translated into ANSI. In this case, there
+// will be a MONIKEREXTENT that holds the original UNICODE based path.
+//
+// If a UNICODE extent exists, then the path will be ignored, and the
+// path in the extent will be used.
+//
+// If a UNICODE extent doesn't exist, then the path will be translated
+// into UNICODE. In theory, this will not fail, since there is supposed
+// to always be a mapping from ANSI to UNICODE (but not the inverse).
+// However, it is possible that the conversion will fail because the
+// codepage needed to translate the ANSI path to UNICODE may not be
+// loaded.
+//
+// In either case, the CFileMoniker::m_szPath should return set
+// with some UNICODE path set. If not, then an error is returned
+//
+// Arguments: [pszPath] -- The ANSI version of the path.
+// [pWidePath] -- Reference to pointer recieving new path
+// [cbWidePath]-- Length of new path
+//
+// Requires:
+//
+// Returns:
+// pWidePath is returned, as allocated from PrivMemAlloc
+// cbWidePath holds length of new path
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-08-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT
+CFileMoniker::DetermineUnicodePath(LPSTR pszAnsiPath,
+ LPWSTR & pWidePath,
+ USHORT &ccWidePath)
+{
+
+ wValidateMoniker();
+
+ mnkDebugOut((DEB_ITRACE,
+ "DetermineUnicodePath(%x) pszAnsiPath(%s)\n",
+ this,
+ pszAnsiPath));
+
+ HRESULT hr = NOERROR;
+
+ //
+ // Check to see if a MONIKEREXTENT exists with mnk_UNICODE
+ //
+
+ MONIKEREXTENT UNALIGNED *pExtent = m_ExtentList.FindExtent(mnk_UNICODE);
+
+ //
+ // Normal fall through case is no UNICODE path, which means that there
+ // was a conversion between mbs and unicode in the original save.
+ //
+ if (pExtent == NULL)
+ {
+ m_fUnicodeExtent = FALSE;
+
+ //
+ // If the pszAnsiPath is NULL, then so should be the UNICODE one
+ //
+ if (pszAnsiPath == NULL)
+ {
+ pWidePath = NULL;
+ ccWidePath = 0;
+ return(NOERROR);
+ }
+
+ //
+ // It turns out to be cheaper to just assume a MAX_PATH size
+ // buffer, and to copy the resulting string. We use MAX_PATH + 1
+ // so we always have room for the terminating NULL
+ //
+
+ WCHAR awcTempPath[MAX_PATH+1];
+ WCHAR *pwcsTempPath = awcTempPath;
+
+ hr = MnkMultiToUnicode( pszAnsiPath,
+ pwcsTempPath,
+ MAX_PATH+1,
+ ccWidePath,
+ AreFileApisANSI() ? CP_ACP : CP_OEMCP);
+
+
+ if (FAILED(hr) || ccWidePath == 0)
+ {
+ goto errRet;
+ }
+
+ pWidePath = (WCHAR *)PrivMemAlloc(sizeof(WCHAR)*(ccWidePath+1));
+
+ if (pWidePath == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto errRet;
+ }
+
+ memcpy(pWidePath,pwcsTempPath,(ccWidePath+1)*sizeof(WCHAR));
+
+ hr = NOERROR;
+
+ }
+ else
+ {
+ //
+ // Get the UNICODE path from the extent.
+ //
+
+ mnkDebugOut((DEB_ITRACE,
+ "DeterminePath(%x) Found UNICODE extent\n",
+ this));
+
+ m_fUnicodeExtent = TRUE;
+
+ hr = CopyPathFromUnicodeExtent(pExtent,pWidePath,ccWidePath);
+ }
+
+
+errRet:
+
+
+ if (FAILED(hr))
+ {
+ if (pWidePath != NULL)
+ {
+ PrivMemFree(pWidePath);
+ }
+
+ mnkDebugOut((DEB_IERROR,
+ "DeterminePath(%x) ERROR: Returning %x\n",
+ this,
+ hr));
+ }
+ else
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "DeterminePath(%x) pWidePath(%ws) ccWidePath(0x%x)\n",
+ this,
+ pWidePath?pWidePath:L"<NULL PATH>",
+ ccWidePath));
+
+ }
+
+ return(hr);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::GetComparisonData
+//
+// Synopsis: Get comparison data for registration in the ROT
+//
+// Arguments: [pbData] - buffer to put the data in.
+// [cbMax] - size of the buffer
+// [pcbData] - count of bytes used in the buffer
+//
+// Returns: NOERROR
+// E_OUTOFMEMORY
+//
+// Algorithm: Build ROT data for file moniker. This puts the classid
+// followed by the display name.
+//
+// History: 03-Feb-95 ricksa Created
+//
+// Note: Validating the arguments is skipped intentionally because this
+// will typically be called internally by OLE with valid buffers.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CFileMoniker::GetComparisonData(
+ byte *pbData,
+ ULONG cbMax,
+ DWORD *pcbData)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "_IN GetComparisionData(%x,%x,%x) for CFileMoniker(%ws)\n",
+ pbData,
+ cbMax,
+ *pcbData,
+ m_szPath));
+
+ CLock lck(m_mxs); // protect all internal state
+
+ ULONG ulLength = sizeof(CLSID_FileMoniker) + GetDisplayNameLength();
+
+ Assert(pcbData != NULL);
+ Assert(pbData != NULL);
+
+ if (cbMax < ulLength)
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "OUT GetComparisionData() Buffer Too Small!\n"));
+
+ return(E_OUTOFMEMORY);
+ }
+
+ memcpy(pbData,&CLSID_FileMoniker,sizeof(CLSID_FileMoniker));
+
+ GenerateDisplayName((WCHAR *)(pbData+sizeof(CLSID_FileMoniker)));
+
+ //
+ // Insure this is an upper case string.
+ //
+ CharUpperW((WCHAR *)(pbData+sizeof(CLSID_FileMoniker)));
+
+ *pcbData = ulLength;
+
+ mnkDebugOut((DEB_ITRACE,
+ "OUT GetComparisionData() *pcbData == 0x%x\n",
+ *pcbData));
+
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CTrackingFileMoniker::*
+//
+// Synopsis: These members implement ITrackingMoniker on behalf of
+// the file moniker.
+//
+// Algorithm: The CTrackingFileMoniker object has a pointer to
+// the CFileMoniker object and forwards any QI's (other than
+// ITrackingMoniker) and AddRefs/Releases to the CFileMoniker.
+//
+//----------------------------------------------------------------------------
+
+#ifdef _TRACKLINK_
+VOID
+CTrackingFileMoniker::SetParent(CFileMoniker *pCFM)
+{
+ _pCFM = pCFM;
+}
+
+STDMETHODIMP CTrackingFileMoniker::QueryInterface(REFIID riid, void **ppv)
+{
+ if (IsEqualIID(IID_ITrackingMoniker, riid))
+ {
+ *ppv = (ITrackingMoniker*) this;
+ _pCFM->AddRef();
+ return(S_OK);
+ }
+ else
+ return(_pCFM->QueryInterface(riid, ppv));
+}
+
+STDMETHODIMP_(ULONG) CTrackingFileMoniker::AddRef()
+{
+ return(_pCFM->AddRef());
+}
+
+STDMETHODIMP_(ULONG) CTrackingFileMoniker::Release()
+{
+ return(_pCFM->Release());
+}
+
+STDMETHODIMP CTrackingFileMoniker::EnableTracking( IMoniker *pmkToLeft, ULONG ulFlags )
+{
+ return(_pCFM->EnableTracking(pmkToLeft, ulFlags));
+}
+#endif
+
+#ifdef _DEBUG
+STDMETHODIMP_(void) NC(CFileMoniker,CDebug)::Dump ( IDebugStream FAR * pdbstm)
+{
+ VOID_VDATEIFACE(pdbstm);
+
+ *pdbstm << "CFileMoniker @" << (VOID FAR *)m_pFileMoniker;
+ *pdbstm << '\n';
+ pdbstm->Indent();
+ *pdbstm << "Refcount is " << (int)(m_pFileMoniker->m_refs) << '\n';
+ *pdbstm << "Path is " << m_pFileMoniker->m_szPath << '\n';
+ *pdbstm << "Anti count is " << (int)(m_pFileMoniker->m_cAnti) << '\n';
+ pdbstm->UnIndent();
+}
+
+
+
+STDMETHODIMP_(BOOL) NC(CFileMoniker,CDebug)::IsValid ( BOOL fSuspicious )
+{
+ return ((LONG)(m_pFileMoniker->m_refs) > 0);
+ // add more later, maybe
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::RestoreShellLink, private
+//
+// Synopsis: Restore a ShellLink object by creating it, and
+// loading the object's persistent state from the Extent
+// of this Moniker (where the state was saved by an earlier
+// instantiation).
+//
+// Arguments: [void]
+//
+// Returns: [HRESULT]
+// - S_FALSE: the shell link had already been restored.
+//
+// Algorithm: If ShellLink object doesn't already exist
+// GetShellLink()
+// Load ShellLink object from moniker Extent.
+// On Error,
+// Release ShellLink
+//
+// Notes: - This routine does not restore the information
+// in mnk_TrackingInformation. This is restored
+// in Load().
+//
+//----------------------------------------------------------------------------
+
+INTERNAL CFileMoniker::RestoreShellLink()
+{
+
+ MONIKEREXTENT UNALIGNED * pExtent;
+ LARGE_INTEGER li0;
+ ULARGE_INTEGER uli;
+ HRESULT hr = E_FAIL;
+ IStream * pstm = NULL;
+ IPersistStream * pps = NULL;
+
+
+ // If we've already, successfully, initialized the shell link object,
+ // then we're done.
+
+ if( m_fShellLinkInitialized )
+ {
+ hr = S_FALSE;
+ goto Exit;
+ }
+
+ // Create the ShellLink object.
+
+ if( FAILED( hr = GetShellLink() ))
+ goto Exit;
+ Assert( m_pShellLink != NULL );
+
+ //
+ // Load ShellLink from Extent list by
+ // writing the MONIKEREXTENT to an in memory stream and then doing
+ // IPersistStream::Load.
+ //
+
+ pExtent = m_ExtentList.FindExtent(mnk_ShellLink);
+ if (pExtent == NULL) // no extent, exit.
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::RestoreShellLink no shell link in extent.\n",
+ this));
+ hr = E_FAIL;
+ goto Exit;
+ }
+
+ if (S_OK != (hr=CreateStreamOnHGlobal(NULL, TRUE, &pstm)))
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::RestoreShellLink CreateStreamOnHGlobal failed %08X.\n",
+ this,
+ hr));
+ goto Exit;
+ }
+
+ if (S_OK != (hr=pstm->Write(((char*)pExtent)+MONIKEREXTENT_HEADERSIZE,
+ pExtent->cbExtentBytes,
+ NULL)))
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::RestoreShellLink pstm->Write failed %08X.\n",
+ this,
+ hr));
+ goto Exit;
+ }
+
+ // Get the Shell Link's IPersistStream interface, and
+ // load it with the data from the Extent.
+
+ Verify(S_OK == m_pShellLink->QueryInterface(IID_IPersistStream,
+ (void**)&pps));
+
+ memset(&li0, 0, sizeof(li0));
+ Verify(S_OK == pstm->Seek(li0, STREAM_SEEK_SET, &uli));
+ Assert(uli.LowPart == 0 && uli.HighPart == 0);
+
+ if (S_OK != (hr=pps->Load(pstm)))
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::RestoreShellLink pps->Load failed %08X.\n",
+ this,
+ hr));
+ goto Exit;
+ }
+
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::RestoreShellLink successfully loaded shell link (%08X) from extent.\n",
+ this,
+ m_pShellLink));
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( FAILED( hr ))
+ {
+ if( m_pShellLink )
+ {
+ m_pShellLink->Release();
+ m_pShellLink = NULL;
+ }
+ }
+
+ return( hr );
+
+} // RestoreShellLink()
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::SetPathShellLink, private
+//
+// Synopsis: Set the path in the ShellLink object.
+//
+// Arguments: [void]
+//
+// Returns: [HRESULT]
+// - S_OK: The path is set successfully.
+// - S_FALSE: The path was not set.
+//
+// Algorithm: If a SetPath isn't necessary/valid, exit (S_OK).
+// Get the ShellLink object (create if necessary)
+// Perform IShellLink->SetPath()
+// If this succeeds, set the m_fShellLinkInitialized
+//
+// Notes: Setting the path in the ShellLink object causes it to
+// read data (attributes) from the file. This data makes that
+// file trackable later on if the file is moved. This routine
+// can be called any number of times, since it exits early if
+// it has executed sucessfully before. Success is indicated by
+// the m_fShellLinkInitialized flag.
+//
+//----------------------------------------------------------------------------
+
+
+INTERNAL CFileMoniker::SetPathShellLink()
+{
+
+ HRESULT hr = S_FALSE;
+ IPersistStream* pps = NULL;
+ LPCTSTR ptszPath = NULL;
+
+ WIN32_FILE_ATTRIBUTE_DATA fadLinkSource;
+
+ // ----------
+ // Initialize
+ // ----------
+
+ // If the path has already been set, or this moniker is not
+ // performing any tracking, then we needn't do anything.
+
+ if( m_fShellLinkInitialized )
+ {
+ hr = S_OK;
+ goto Exit;
+ }
+
+
+ // If necessary, create the ShellLink object.
+
+ if( FAILED( hr = GetShellLink() ))
+ goto Exit;
+ Assert( m_pShellLink != NULL );
+
+ // ----------------------------------
+ // Get the correct path into ptszPath
+ // ----------------------------------
+
+#ifdef _CHICAGO_
+
+ char *pszAnsiPath;
+ USHORT cbAnsiPath;
+ BOOL fFastConvert;
+
+ hr = MnkUnicodeToMulti(m_szPath,
+ lstrlenW(m_szPath),
+ pszAnsiPath,
+ cbAnsiPath,
+ fFastConvert);
+
+ if( FAILED( hr ))
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::SetPathShellLink(%ls) -- Could not convert Unicode to Ansi\n",
+ this,
+ m_szPath));
+ goto Exit;
+ }
+ ptszPath = pszAnsiPath;
+
+#else // !_CHICAGO_
+
+ ptszPath = m_szPath;
+
+#endif // !_CHICAGO_
+
+ // ------------------------------
+ // Set the path of the shell link
+ // ------------------------------
+
+ hr = m_pShellLink->SetPath( (char *) ptszPath );
+
+#ifdef _CHICAGO_
+ PrivMemFree( (void *) ptszPath);
+#endif
+
+ // Was the link source missing?
+
+ if (S_FALSE == hr)
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::SetPathShellLink(%ls) -- readtrackinginfo -- NOT FOUND\n",
+ this,
+ m_szPath));
+ }
+
+ else if (SUCCEEDED(hr))
+ {
+
+ // Remember that we've done this so we won't have to again.
+
+ m_fShellLinkInitialized = TRUE;
+
+ // Set the moniker's dirty bit according to the ShellLink's
+ // dirty bit. (It should be dirty.)
+
+ Verify (S_OK == m_pShellLink->
+ QueryInterface(IID_IPersistStream, (void**)&pps));
+ if (pps->IsDirty() == S_OK)
+ {
+ m_fDirty = TRUE;
+ }
+ else
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::SetPathShellLink(%ls) -- IsDirty not dirty\n",
+ this,
+ m_szPath));
+
+ }
+
+ } // ShellLink->SetPath ... if (SUCCEEDED(hr))
+ else
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::SetPathShellLink(%ls) -- m_pShellLink->SetPath failed %08X.\n",
+ this,
+ m_szPath,
+ hr));
+
+ } // ShellLink->SetPath ... if (SUCCEEDED(hr)) ... else
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( pps )
+ pps->Release();
+
+ return( hr );
+
+} // CFileMoniker::SetPathShellLink()
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::ResolveShellLink, private
+//
+// Synopsis: Perform an IShellLink->Resolve, and updates the data
+// in this moniker accordingly.
+//
+// Arguments: [IBindCtx*] pbc
+// - The caller's bind context.
+//
+// Outputs: [HRESULT]
+// S_OK if the link is successfully resolved.
+// S_FALSE if the link is not resolved, but there were no errors.
+//
+// Algorithm: Get the caller's Bind_Opts
+// Get IShellLinkTracker from the ShellLink object.
+// Perform IShellLinkTracker->Resolve
+// Set the dirty flag if necessary.
+// If we found a new path
+// ReInitialize this moniker with the new path.
+//
+// Notes: This routine does not restore the information in
+// mnk_TrackingInformation. The information is restored
+// Load().
+//
+//----------------------------------------------------------------------------
+
+INTERNAL CFileMoniker::ResolveShellLink( IBindCtx* pbc )
+{
+
+ HRESULT hr = E_FAIL;
+ IPersistStream* pps = NULL;
+
+ WCHAR * pwszWidePath = NULL; // Path in Unicode format
+ char * ptszPath = NULL; // Path in either ANSI or Unicode
+
+ USHORT ccNewString = 0;
+ DWORD dwTrackFlags = 0L;
+ DWORD dwTickCountDeadline = 0L;
+ USHORT ccPathBufferSize = 0;
+
+
+ // Validate the inputs
+
+ Assert( pbc != NULL );
+ Assert( m_fIsTracking || m_fTrackingEnabled );
+
+
+ if( !m_fIsTracking )
+ {
+ // This is not a tracking moniker, which means that
+ // we may not yet have a ShellLink object. If so,
+ // then create one and restore its persistent state
+ // (which is stored in this Moniker's CExtent).
+
+ if( FAILED( hr = RestoreShellLink() ))
+ goto Exit;
+ }
+ Assert( m_pShellLink != NULL );
+
+#ifdef _CAIRO_
+
+ //
+ // Now, we've got a shell link. Let's get its Tracker
+ // interface.
+ //
+
+ if( FAILED( hr = GetShellLinkTracker() ))
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::ResolveShellLink GetShellLinkTracker failed %08X.\n",
+ this,
+ hr));
+ goto Exit;
+ }
+ Assert( m_pShellLinkTracker != NULL );
+
+ // Since the Resolve may require tracking, we need to
+ // determine the tracking restrictions and deadline. These were
+ // defaulted above, but can be overridden by the caller
+ // (with values from the bind opts) for tracking monikers.
+
+ if( m_fIsTracking )
+ {
+ // Check the bind opts for restrictions and the deadline.
+
+ BIND_OPTS2 bind_opts;
+
+ bind_opts.cbStruct = sizeof( bind_opts );
+ if( SUCCEEDED( hr = pbc->GetBindOptions( (LPBIND_OPTS) &bind_opts )))
+ {
+ if( !ValidateBindOpts( (LPBIND_OPTS) &bind_opts ))
+ {
+ hr = E_INVALIDARG;
+ goto Exit;
+ }
+
+ dwTrackFlags = bind_opts.dwTrackFlags;
+ dwTickCountDeadline = bind_opts.dwTickCountDeadline;
+
+ }
+ else
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::ResolveShellLink pbc->GetBindOptions failed %08X.\n",
+ this,
+ hr));
+ goto Exit;
+
+ } // if( SUCCEEDED( hr = pbc->GetBindOptions( &bind_opts ))) ... else
+ } // if( m_fIsTracking )
+
+#endif // _CAIRO_
+
+ // Finally, resolve the link.
+
+#ifdef _CAIRO_
+
+ if (S_OK != (hr = m_pShellLinkTracker->Resolve(
+ GetDesktopWindow(),
+ SLR_ANY_MATCH | SLR_NO_UI,
+ dwTrackFlags,
+ dwTickCountDeadline,
+ 0L // Reserved
+ )
+ )
+ )
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::ResolveShellLink IShellLinkTracker->Resolve failed %08X.\n",
+ this,
+ hr));
+ goto Exit;
+ }
+
+#else
+
+ if (S_OK != (hr = m_pShellLink->Resolve(
+ GetDesktopWindow(),
+ 0xFFFF0000 | SLR_ANY_MATCH | SLR_NO_UI
+ )
+ )
+ )
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::ResolveShellLink IShellLink->Resolve failed %08X.\n",
+ this,
+ hr));
+ goto Exit;
+ }
+
+#endif // _CAIRO_
+
+
+ //
+ // The above Resolve may have made the Shell Link object dirty,
+ // in which case this FileMoniker should be dirty as well.
+ //
+
+ Verify(S_OK == m_pShellLink->QueryInterface(IID_IPersistStream,
+ (void**)&pps));
+
+ if (pps->IsDirty() == S_OK)
+ {
+ m_fDirty = TRUE;
+ }
+
+
+ //
+ // We appear to have found a matching file. We will
+ // check that we can activate it properly before updating
+ // the file moniker's internal path.
+ // Before we can attempt activation we might have to get the
+ // path into unicode.
+ //
+
+#ifdef _CHICAGO_
+ ccPathBufferSize = MAX_PATH + sizeof( '\0' );
+#else
+ ccPathBufferSize = sizeof( WCHAR ) * MAX_PATH + sizeof( L'\0' );
+#endif
+
+ ptszPath = (char*)PrivMemAlloc( ccPathBufferSize );
+ if (ptszPath == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::ResolveShellLink PrivMemAlloc failed.\n",
+ this));
+ goto Exit;
+ }
+
+ WIN32_FIND_DATA fd;
+ if (S_OK != (hr=m_pShellLink->GetPath(ptszPath,
+ MAX_PATH, &fd, IsWOWProcess() ? SLGP_SHORTPATH : 0)))
+
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::ResolveShellLink m_pShellLink->GetPath failed %08X.\n",
+ this,
+ hr));
+ goto Exit;
+ }
+
+#ifdef _CHICAGO_
+
+ // Convert the path to Unicode.
+
+ hr = MnkMultiToUnicode(ptszPath,
+ pwszWidePath /*OUT*/,
+ 0,
+ ccNewString, /*OUT*/
+ CP_OEMCP );
+ if (hr != S_OK)
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::ResolveShellLink MnkUnicodeToMulti failed %08X.\n",
+ this,
+ hr));
+ goto Exit;
+ }
+
+
+#else // !_CHICAGO_
+
+ // The path is already in Unicode. Transfer responsibility
+ // from 'ptszPath' to 'pwszWidePath'.
+
+ pwszWidePath = (WCHAR *) ptszPath;
+ ptszPath = NULL;
+ ccNewString = (USHORT) -1;
+
+#endif // !_CHICAGO_
+
+
+ // Verify that we received an actual path from IShellLink::GetPath.
+
+ if (*pwszWidePath == L'\0' || ccNewString == 0)
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::ResolveShellLink MnkUnicodeToMulti failed 2 %08X.\n",
+ this,
+ hr));
+ hr = E_FAIL;
+ goto Exit;
+ }
+
+ //
+ // If the path to the linked file has changed, update the internal
+ // state of this File Moniker.
+ //
+
+ if( lstrcmpW( pwszWidePath, m_szPath )) // Cmp wide path; Ansi may not exist.
+ {
+
+ // Re-initialize this moniker with the new
+ // path. We will save and restore the fClassVerified, because
+ // if it is set we might avoid a redundant verification.
+
+ BOOL fClassVerified = m_fClassVerified;
+
+ if( !Initialize(m_cAnti,
+ ptszPath, // Either the ANSI path or NULL
+ ptszPath ? strlen( ptszPath ) + 1 : 0,
+ pwszWidePath,
+ lstrlenW( pwszWidePath ),
+ m_endServer )
+ )
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::ResolveShellLink Initialize (with new path) failed.\n",
+ this));
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // Restore the previous fClassVerified.
+
+ if( !m_fClassVerified )
+ m_fClassVerified = fClassVerified;
+
+ // The paths are now the responsibility of the CFileMoniker.
+
+ ptszPath = NULL;
+ pwszWidePath = NULL;
+
+ } // if( !strcmp( pszAnsiPath, m_szPath )
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( pps )
+ pps->Release();
+
+ if (ptszPath)
+ PrivMemFree(ptszPath);
+
+ if (pwszWidePath)
+ PrivMemFree(pwszWidePath);
+
+ return( hr );
+
+} // CFileMoniker::ResolveShellLink()
+
+
+
+#ifdef _CAIRO_
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::GetTrackFlags, private
+//
+// Synopsis: Get the TrackFlags from the Shell Link object.
+//
+// Arguments: [DWORD *] pdwTrackFlags
+// - On return holds the Track Flags.
+//
+// Returns: [HRESULT]
+// - E_FAIL is returned if there is no Shell Link object.
+//
+// Algorithm: Use the Tracker interface to get the Track Flags
+//
+//----------------------------------------------------------------------------
+
+INTERNAL CFileMoniker::GetTrackFlags( DWORD * pdwTrackFlags )
+{
+ HRESULT hr = E_FAIL;
+
+ *pdwTrackFlags = 0L;
+
+ if (m_pShellLink)
+ {
+ // Get the Shell Link's Tracker interface.
+
+ hr = GetShellLinkTracker();
+ if( FAILED(hr) )
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::GetTrackFlags(%ls) -- Could not get ShellLinkTracker (%08X).\n",
+ this,
+ m_szPath,
+ hr));
+ }
+ else
+ {
+ Assert( m_pShellLinkTracker != NULL );
+
+ // Ask the SLTracker for the Track Flags.
+
+ hr = m_pShellLinkTracker->GetTrackFlags( pdwTrackFlags );
+ if( FAILED(hr) )
+ {
+ *pdwTrackFlags = 0L;
+
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::GetTrackFlags(%ls) -- Could not get TrackFlags %08X.\n",
+ this,
+ m_szPath,
+ hr));
+ }
+
+
+ } // if( FAILED(hr) )
+ } // if (m_pShellLink)
+
+
+ // ----
+ // Exit
+ // ----
+
+ return( hr );
+
+} // CFileMoniker::GetTrackFlags
+
+#endif // _CAIRO_
+
+#ifdef _CAIRO_
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::GetShellLinkTracker, private
+//
+// Synopsis: Ensure that m_pShellLinkTracker is valid, or return error.
+//
+// Arguments: [void]
+//
+// Returns: [HRESULT]
+//
+// Algorithm: if m_pShellLinkTracker is already valid return S_OK, else
+// query the ShellLink object for one.
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+
+INTERNAL CFileMoniker::GetShellLinkTracker()
+{
+ HRESULT hr;
+
+ if (m_pShellLinkTracker == NULL)
+ {
+ if( FAILED( hr = GetShellLink()))
+ goto Exit;
+ Assert( m_pShellLink != NULL );
+
+ hr = m_pShellLink->QueryInterface(IID_IShellLinkTracker,
+ (void**) &m_pShellLinkTracker );
+ if( FAILED(hr) )
+ {
+ mnkDebugOut((DEB_TRACK,
+ "CFileMoniker(%x)::GetShellLinkTracker -- Could not QI(IShellLinkTracker) %08X.\n",
+ this,
+ hr));
+ }
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return( hr );
+
+} // CFileMoniker::GetShellLinkTracker()
+
+#endif // _CAIRO_
+
+#ifdef _CAIRO_
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFileMoniker::QuickShellLinkResolve, private
+//
+// Synopsis: Attempt to quickly resolve the ShellLink object.
+// This routine never fails.
+//
+// Arguments: [pbc] A Bind Context.
+//
+// Returns: [HRESULT]
+// S_OK -- The link was resolved.
+// S_FALSE -- The link was not resolved.
+//
+// Algorithm: If this is a tracking moniker, then further restrict the
+// bind_opts to track only local/indexed volumes, and then
+// attempt a resolve.
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+
+INTERNAL CFileMoniker::QuickShellLinkResolve( IBindCtx* pbc )
+{
+
+ HRESULT hr = S_FALSE;
+ BIND_OPTS2 bind_opts;
+ BOOL bBindOptsModified = FALSE;
+ DWORD dwOriginalTrackFlags = 0L;
+
+ Assert( pbc != NULL );
+
+ // We only attempt the Resolve on tracking monikers.
+ if( !m_fIsTracking )
+ {
+ goto Exit;
+ }
+
+ // Get the caller's bind_opts.
+
+ bind_opts.cbStruct = sizeof( bind_opts );
+ if( FAILED( hr = pbc->GetBindOptions( (LPBIND_OPTS) &bind_opts )))
+ {
+ mnkDebugOut(( DEB_ITRACE,
+ "CFileMoniker::QuickShellLinkResolve(%x) -- could not get caller's bind_opts (%x)\n",
+ this,
+ hr ));
+ goto Exit;
+ }
+
+ // No need to validate this bind_opts since we're not using it yet.
+ // Further restrict the caller's bind_opts to only track local indexed
+ // drives.
+
+ dwOriginalTrackFlags = bind_opts.dwTrackFlags;
+ bind_opts.dwTrackFlags |= TRACK_LOCALONLY | TRACK_INDEXEDONLY;
+
+ // Set this modified bind_opts back into the caller's bind context, and attempt
+ // a resolve.
+
+ if( FAILED( hr = pbc->SetBindOptions( (LPBIND_OPTS) &bind_opts )))
+ {
+ mnkDebugOut(( DEB_ITRACE,
+ "CFileMoniker::QuickShellLinkResolve(%x) -- could not set bind options (%x)\n",
+ this,
+ hr ));
+ goto Exit;
+ }
+ bBindOptsModified = TRUE;
+
+ if( FAILED( hr = ResolveShellLink( pbc )))
+ {
+ mnkDebugOut(( DEB_ITRACE,
+ "CFileMoniker::QuickShellLinkResolve(%x) -- could not resolve shell link (%x)\n",
+ this,
+ hr ));
+ goto Exit;
+ }
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // Restore the caller's bind_opts
+
+ if( bBindOptsModified )
+ {
+ bind_opts.dwTrackFlags = dwOriginalTrackFlags;
+
+ if( FAILED( hr = pbc->SetBindOptions( (LPBIND_OPTS) &bind_opts )))
+ {
+ mnkDebugOut(( DEB_ITRACE,
+ "CFileMoniker::QuickShellLinkResolve(%x) -- could not restore caller's bind options (%x)\n",
+ this,
+ hr ));
+ }
+ }
+
+ // Standardize hresult to either S_OK or S_FALSE.
+
+ if( hr != S_OK )
+ {
+ hr = S_FALSE;
+ }
+
+ return( hr );
+
+} // CFileMoniker::QuickShellLinkResolve()
+
+#endif // _CAIRO_
diff --git a/private/ole32/com/moniker2/cfilemon.hxx b/private/ole32/com/moniker2/cfilemon.hxx
new file mode 100644
index 000000000..93e61e8be
--- /dev/null
+++ b/private/ole32/com/moniker2/cfilemon.hxx
@@ -0,0 +1,296 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: cfilemon.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Commented
+// 10-13-95 stevebl threadsafety
+// 10-20-95 MikeHill Updated to support new CreateFileMonikerEx API.
+// 11-22-95 MikeHIll Change m_fPathSetInShellLink to
+// m_fShellLinkInitialized.
+// 12-01-95 MikeHill Added QuickShellLinkResolve() member.
+//
+//----------------------------------------------------------------------------
+
+#include <sem.hxx>
+#include "extents.hxx"
+#ifdef _TRACKLINK_
+#include "shellink.hxx" // BUGBUG BillMo: need a better way of getting this interface.
+#include <itrkmnk.hxx>
+#ifdef _CAIRO_
+#include <ISLTrack.h>
+#endif // _CAIRO_
+#endif // _TRACKLINK_
+
+STDAPI FindFileMoniker(LPBC pbc,
+ LPCWSTR pwszDisplayName,
+ ULONG *pchEaten,
+ LPMONIKER *ppmk);
+
+
+#ifdef _TRACKLINK_
+class CFileMoniker;
+
+class CTrackingFileMoniker : public ITrackingMoniker
+{
+public:
+ VOID SetParent(CFileMoniker *pCFM);
+
+ virtual HRESULT __stdcall QueryInterface(
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ virtual ULONG __stdcall AddRef( void);
+
+ virtual ULONG __stdcall Release( void);
+
+ virtual HRESULT __stdcall EnableTracking ( IMoniker *pmkToLeft, ULONG ulFlags );
+
+private:
+ CFileMoniker * _pCFM;
+};
+
+#endif
+
+
+class FAR CFileMoniker : public CBaseMoniker
+{
+
+public:
+ static CFileMoniker * Create(LPCWSTR szPathName,
+ USHORT cAnti = 0,
+ USHORT usEndServer = 0xFFFF);
+
+
+private:
+
+ CFileMoniker( void );
+ ~CFileMoniker( void );
+ INTERNAL_(BOOL) Initialize( USHORT cAnti,
+ LPSTR pszAnsiPath,
+ USHORT cbAnsiPath,
+ LPWSTR szPathName,
+ USHORT ccPathName,
+ USHORT usEndServer);
+
+ INTERNAL_(BOOL) Initialize( USHORT cAnti,
+ LPCWSTR szPathName,
+ USHORT usEndServer);
+
+
+ INTERNAL_(BOOL) IsOle1Class( LPCLSID pclsid );
+
+#ifdef _TRACKLINK_
+ INTERNAL GetShellLink(VOID);
+ INTERNAL GetShellLinkTracker( VOID );
+ INTERNAL RestoreShellLink( VOID );
+ INTERNAL SetPathShellLink( VOID );
+ INTERNAL ResolveShellLink( IBindCtx* pbc );
+ INTERNAL GetTrackFlags( DWORD * pdwTrackFlags );
+#endif // _TRACKLINK_
+
+#ifdef _CAIRO_
+ INTERNAL QuickShellLinkResolve( IBindCtx* pbc );
+#endif // _CAIRO_
+
+ STDDEBDECL(CFileMoniker, FileMoniker)
+public:
+
+ // *** IUnknown methods inherited from CBaseMoniker***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,Release) (THIS);
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID);
+ // *** IPersistStream methods ***
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm);
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty);
+#ifdef _TRACKLINK_
+ STDMETHOD(IsDirty) (THIS_ VOID);
+#endif
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR * pcbSize);
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID FAR* ppvResult);
+ STDMETHOD(BindToStorage) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNotGeneric,
+ LPMONIKER FAR* ppmkComposite);
+ STDMETHOD(Enum) (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker);
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker);
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash);
+ STDMETHOD(IsRunning) (THIS_ LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+ pmkNewlyRunning);
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime);
+ STDMETHOD(Inverse) (THIS_ LPMONIKER FAR* ppmk);
+ STDMETHOD(CommonPrefixWith) (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix);
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath);
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR FAR* lplpszDisplayName);
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut);
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys);
+
+#ifdef _TRACKLINK_
+ STDMETHOD(Reduce) (THIS_ LPBC pbc,
+ DWORD dwReduceHowFar,
+ LPMONIKER FAR* ppmkToLeft,
+ LPMONIKER FAR * ppmkReduced);
+#endif
+
+ // *** ITrackingMoniker methods ***
+#ifdef _TRACKLINK_
+ virtual HRESULT __stdcall EnableTracking(THIS_ IMoniker *pmkToLeft, ULONG ulFlags);
+#endif
+
+ // *** IROTData Methods ***
+ STDMETHOD(GetComparisonData)(
+ byte *pbData,
+ ULONG cbMax,
+ ULONG *pcbData);
+
+//
+// Private routines
+//
+
+ HRESULT DetermineUnicodePath(LPSTR pszAnsiPath,
+ LPWSTR &pWidePath,
+ USHORT &cbWidePath);
+
+ HRESULT ValidateAnsiPath(void);
+
+ ULONG GetDisplayNameLength();
+ void GenerateDisplayName(LPWSTR pwcDisplayName);
+
+#if DBG == 1
+ void ValidateMoniker(void);
+#else
+ inline void ValidateMoniker(void) {;}
+#endif
+
+
+shared_state:
+private:
+
+ CLSID m_clsid; // used only if OLE 1.0
+ CExtentList m_ExtentList;
+
+ //
+ // For ease of debugging, the path sizes are kept right after
+ // the string pointers. Notice that 2 USHORTS == 1 ULONG, so the
+ // alignment is correct
+ //
+
+ WCHAR * m_szPath; // Unicode path
+ char * m_pszAnsiPath; // Original ANSI path
+
+ USHORT m_ccPath; // Count of characters in path
+ USHORT m_cbAnsiPath; // Count of bytes in Ansi verision of path
+
+
+
+ DWORD m_dwHashValue; // Cached hash value
+
+ //
+ // The following flags keep track of important things, like whether
+ // we have loaded from a UNICODE extent.
+ //
+
+ ULONG m_fUnicodeExtent:1; // Is there a UNICODE extent?
+ ULONG m_fClassVerified:1; // Has the class be verified
+ ULONG m_fHashValueValid:1; // Is the cached hash value correct?
+
+ //
+ // The fIsTracking flag indicates that this moniker
+ // was created to be a tracking file moniker, regardless of how
+ // the TrackingEnabled flag is set. If a moniker
+ // is not a tracking file moniker, but the TrackingEnabled
+ // flag is set, then the moniker will still perform tracking as
+ // if it were created as a tracking moniker.
+ // The fShellLinkInitialized flag is a BYTE, rather than a BOOL,
+ // so that it can be loaded more efficiently in a Moniker
+ // Extent (see CFileMoniker::Save/Load).
+ //
+
+#ifdef _TRACKLINK_
+ BOOL m_fIsTracking; // Created as tracking moniker?
+ BYTE m_fShellLinkInitialized;// Has IShellLink->SetPath() succeeded?
+ ULONG m_fTrackingEnabled:1; // Is creation of shell link enabled
+ // on save ?
+ ULONG m_fSaveShellLink:1; // Is saving of shell link enabled ?
+ ULONG m_fDirty:1; // Have we changed since save ?
+ ULONG m_fReduceEnabled:1; // Should reduce track ?
+#endif // _TRACKLINK_
+
+ USHORT m_cAnti;
+ USHORT m_endServer; // m_szPath to m_szPath + m_endServer
+ // is the server part of the path
+ enum olever { undetermined, ole1, ole2 };
+ olever m_ole1;
+
+#ifdef _TRACKLINK_
+ IShellLink *m_pShellLink; // if nz implies tracking enabled.
+ CTrackingFileMoniker _tfm;
+#ifdef _CAIRO_
+ IShellLinkTracker *m_pShellLinkTracker;
+#endif // _CAIRO_
+#endif // _TRACKLINK_
+
+ CMutexSem m_mxs;
+
+ friend class CCompositeMoniker;
+ friend BOOL RunningMoniker(LPBINDCTX,LPWSTR,ULONG FAR&,LPMONIKER FAR*);
+ friend HRESULT STDAPICALLTYPE
+ CreateOle1FileMoniker(LPWSTR, REFCLSID, LPMONIKER FAR*);
+
+ // these functions are REALLY private
+private:
+
+#if DBG == 1
+ void wValidateMoniker(void);
+#else
+ void wValidateMoniker(void) { }
+#endif
+ STDMETHOD (wCommonPrefixWith) (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix);
+
+};
+
+
+//
+// The following structures are used to make IO to a stream faster.
+// Note: The packing has been changed to 1 for these structures. This is
+// done because we need to have the same alignment as one would find
+// in the stream.
+//
+
+#pragma pack(1)
+typedef struct _MonikerWriteStruct
+{
+ USHORT m_endServer;
+ USHORT m_w; // Flag used as version number
+ CLSID m_clsid;
+ ULONG m_ole1;
+} MonikerWriteStruct;
+
+typedef struct _MonikerReadStruct
+{
+ CLSID m_clsid;
+ ULONG m_ole1;
+ ULONG m_cbExtents;
+} MonikerReadStruct;
+
+#pragma pack()
diff --git a/private/ole32/com/moniker2/citemmon.cxx b/private/ole32/com/moniker2/citemmon.cxx
new file mode 100644
index 000000000..c535c1f70
--- /dev/null
+++ b/private/ole32/com/moniker2/citemmon.cxx
@@ -0,0 +1,2055 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: citemmon.cxx
+//
+// Contents: Implementation of CItemMoniker
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Created
+// 01-14-94 KevinRo Updated so it actually works
+// 06-14-94 Rickhi Fix type casting
+// 10-13-95 stevebl threadsafty
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include "cbasemon.hxx"
+#include "citemmon.hxx"
+#include "cantimon.hxx"
+#include "mnk.h"
+
+#include <olepfn.hxx>
+#include <rotdata.hxx>
+
+
+INTERNAL RegisterContainerBound(LPBC pbc, LPOLEITEMCONTAINER pOleCont);
+
+
+INTERNAL_(CItemMoniker *) IsItemMoniker( LPMONIKER pmk )
+{
+ CItemMoniker *pIMk;
+
+ if ((pmk->QueryInterface(CLSID_ItemMoniker, (void **)&pIMk)) == S_OK)
+ {
+ // we release the AddRef done by QI, but still return the pointer
+ pIMk->Release();
+ return pIMk;
+ }
+
+ // dont rely on user implementations to set pIMk to NULL on failed QI.
+ return pIMk;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CItemMoniker::CItemMoniker
+//
+// Synopsis: Constructor
+//
+// Effects:
+//
+// Arguments: (none)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-17-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CItemMoniker::CItemMoniker() CONSTR_DEBUG
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CItemMoniker::CItemMoniker(%x)\n",
+ this));
+
+ m_lpszItem = NULL;
+ m_lpszDelimiter = NULL;
+ m_pszAnsiItem = NULL;
+ m_pszAnsiDelimiter = NULL;
+ m_fHashValueValid = FALSE;
+ m_ccItem = 0;
+ m_cbAnsiItem = 0;
+ m_cbAnsiDelimiter = 0;
+ m_ccDelimiter = 0;
+
+ m_dwHashValue = 0x12345678;
+ //
+ // CoQueryReleaseObject needs to have the address of the this objects
+ // query interface routine.
+ //
+ if (adwQueryInterfaceTable[QI_TABLE_CItemMoniker] == 0)
+ {
+ adwQueryInterfaceTable[QI_TABLE_CItemMoniker] =
+ **(DWORD **)((IMoniker *)this);
+ }
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CItemMoniker::ValidateMoniker
+//
+// Synopsis: Check the consistency of this moniker
+//
+// Effects: In a DBG build, check to see if the member variables are
+// sane values.
+//
+// Arguments: (none)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-17-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+#if DBG == 1
+void CItemMoniker::ValidateMoniker()
+{
+ Assert( (m_lpszItem == NULL && m_ccItem == 0) ||
+ (m_ccItem == lstrlenW(m_lpszItem)));
+
+
+ Assert( (m_lpszDelimiter == NULL && m_ccDelimiter == 0) ||
+ (m_ccDelimiter == lstrlenW(m_lpszDelimiter)));
+
+ //
+ // cbAnsi* fields are NOT string lengths. However, the size of the
+ // buffer should be at least equal or bigger to the length of the
+ // Ansi part.
+ //
+
+ Assert( (m_pszAnsiItem == NULL && m_cbAnsiItem == 0) ||
+ (m_cbAnsiItem >= strlen(m_pszAnsiItem)+1));
+
+
+ Assert( (m_pszAnsiDelimiter == NULL && m_cbAnsiDelimiter == 0) ||
+ (m_cbAnsiDelimiter >= strlen(m_pszAnsiDelimiter)+1));
+
+ Assert( !m_fHashValueValid || (m_dwHashValue != 0x12345678) );
+}
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CItemMoniker::~CItemMoniker
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-17-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CItemMoniker::~CItemMoniker( void )
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CItemMoniker::~CItemMoniker(%x)\n",
+ this));
+ UnInit();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CItemMoniker::UnInit
+//
+// Synopsis: Uninitialize the Item moniker
+//
+// Effects: Free's path memory stored in Item Moniker.
+//
+// Arguments: (none)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-16-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void
+CItemMoniker::UnInit()
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CItemMoniker::UnInit(%x)\n",
+ this));
+
+ ValidateMoniker();
+
+ if (m_lpszDelimiter != NULL)
+ {
+ PrivMemFree(m_lpszDelimiter);
+ m_lpszDelimiter = NULL;
+ m_ccDelimiter = 0;
+ }
+
+ if (m_pszAnsiDelimiter != NULL)
+ {
+ PrivMemFree(m_pszAnsiDelimiter);
+ m_pszAnsiDelimiter = NULL;
+ m_cbAnsiDelimiter = 0;
+ }
+
+ if (m_lpszItem != NULL)
+ {
+ PrivMemFree(m_lpszItem);
+ m_lpszItem = NULL;
+ m_ccItem = 0;
+ }
+
+ if (m_pszAnsiItem != NULL)
+ {
+ PrivMemFree(m_pszAnsiItem);
+ m_pszAnsiItem = NULL;
+ m_cbAnsiItem = 0;
+ }
+
+ m_fHashValueValid = FALSE;
+ m_dwHashValue = 0x12345678;
+
+ ValidateMoniker();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CItemMoniker::Initialize
+//
+// Synopsis: Initilaize an Item Moniker
+//
+// Effects: Clears the current state, then sets new state
+//
+// Arguments: [lpwcsDelimiter] -- Delimiter string
+// [ccDelimiter] -- char count of delimiter
+// [lpszAnsiDelimiter] -- Ansi version of delimiter
+// [cbAnsiDelimiter] -- Count of bytes in AnsiDelimiter
+// [lpwcsItem] -- Item string
+// [ccItem] -- Count of characters in item string
+// [lpszAnsiItem] -- Ansi version of item string
+// [cbAnsiItem] -- Count of bytes in Ansi version
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-16-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void
+CItemMoniker::Initialize ( LPWSTR lpwcsDelimiter,
+ USHORT ccDelimiter,
+ LPSTR lpszAnsiDelimiter,
+ USHORT cbAnsiDelimiter,
+ LPWSTR lpwcsItem,
+ USHORT ccItem,
+ LPSTR lpszAnsiItem,
+ USHORT cbAnsiItem )
+{
+ //
+ // OleLoadFromStream causes two inits; the member vars may already be set
+ // UnInit() will free existing resources
+ //
+
+ UnInit();
+
+ ValidateMoniker();
+
+ m_lpszItem = lpwcsItem;
+ m_ccItem = ccItem;
+
+ m_pszAnsiItem = lpszAnsiItem;
+ m_cbAnsiItem = cbAnsiItem;
+
+ m_lpszDelimiter = lpwcsDelimiter;
+ m_ccDelimiter = ccDelimiter;
+
+ m_pszAnsiDelimiter = lpszAnsiDelimiter;
+ m_cbAnsiDelimiter = cbAnsiDelimiter;
+
+ ValidateMoniker();
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CItemMoniker::Initialize
+//
+// Synopsis: Initialize the contents of this moniker
+//
+// Effects:
+// Copies the input parameters using PrivMemAlloc(), then passes them
+// to the other version of Initialize, which takes control of the
+// pointers.
+//
+// Arguments: [lpszDelimiter] --
+// [lpszItemName] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-17-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(BOOL)
+CItemMoniker::Initialize ( LPCWSTR lpszDelimiter,
+ LPCWSTR lpszItemName )
+{
+ ValidateMoniker();
+
+ USHORT ccItem;
+ USHORT ccDelimiter;
+
+ LPWSTR pwcsDelimiter = NULL;
+ LPWSTR pwcsItem = NULL;
+
+ //VDATEPTRIN rejects NULL
+ if( lpszDelimiter )
+ {
+ GEN_VDATEPTRIN(lpszDelimiter,WCHAR, FALSE);
+ }
+
+ if( lpszItemName )
+ {
+ GEN_VDATEPTRIN(lpszItemName,WCHAR, FALSE);
+ }
+
+ if (FAILED(DupWCHARString(lpszDelimiter,
+ pwcsDelimiter,
+ ccDelimiter)))
+ {
+ goto errRet;
+ }
+
+ if (FAILED(DupWCHARString(lpszItemName,pwcsItem,ccItem)))
+ {
+ goto errRet;
+ }
+ Initialize(pwcsDelimiter,
+ ccDelimiter,
+ NULL,
+ 0,
+ pwcsItem,
+ ccItem,
+ NULL,
+ 0);
+
+ return TRUE;
+
+errRet:
+
+ if (pwcsDelimiter != NULL)
+ {
+ PrivMemFree(pwcsDelimiter);
+ }
+ return(FALSE);
+}
+
+
+CItemMoniker FAR *CItemMoniker::Create (
+ LPCWSTR lpszDelimiter, LPCWSTR lpszItemName)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CItemMoniker::Create() item(%ws) delim(%ws)\n",
+ lpszItemName,
+ lpszDelimiter));
+ //
+ // Parameter validation is handled in Initialize
+ //
+ CItemMoniker FAR * pCIM = new CItemMoniker();
+
+ if (pCIM)
+ {
+ pCIM->AddRef();
+
+ if (pCIM->Initialize( lpszDelimiter, lpszItemName ))
+ return pCIM;
+
+ delete pCIM;
+ }
+ return NULL;
+}
+
+
+
+STDMETHODIMP CItemMoniker::QueryInterface (THIS_ REFIID riid,
+ LPVOID FAR* ppvObj)
+{
+ VDATEIID (riid);
+ VDATEPTROUT(ppvObj, LPVOID);
+
+#ifdef _DEBUG
+ if (riid == IID_IDebug)
+ {
+ *ppvObj = &(m_Debug);
+ return NOERROR;
+ }
+#endif
+
+ if (IsEqualIID(riid, CLSID_ItemMoniker))
+ {
+ // called by IsItemMoniker.
+ AddRef();
+ *ppvObj = this;
+ return S_OK;
+ }
+ else if (IsEqualIID(riid, IID_IROTData))
+ {
+ AddRef();
+ *ppvObj = (IROTData *) this;
+ return S_OK;
+ }
+
+ return CBaseMoniker::QueryInterface(riid, ppvObj);
+}
+
+
+
+STDMETHODIMP_(ULONG) CItemMoniker::Release (void)
+{
+ mnkDebugOut((DEB_TRACE, "%p CItemMoniker::Release(%ld)\n",
+ this, m_refs - 1));
+
+ Assert(m_refs != 0);
+
+ if (InterlockedDecrement((long *)&m_refs) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return m_refs;
+}
+
+
+
+STDMETHODIMP CItemMoniker::GetClassID (LPCLSID lpClassId)
+{
+
+ VDATEPTROUT(lpClassId, CLSID);
+
+ *lpClassId = CLSID_ItemMoniker;
+ return NOERROR;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteDoubleString
+//
+// Synopsis: Writes a double string to stream. See ExtractUnicodeString
+//
+// Effects:
+//
+// Arguments: [pStm] --
+// [pwcsWide] --
+// [ccWide] --
+// [pszAnsi] --
+// [cbAnsi] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-16-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT
+WriteDoubleString( LPSTREAM pStm,
+ LPWSTR pwcsWide,
+ USHORT ccWide,
+ LPSTR pszAnsi,
+ USHORT cbAnsi)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "WriteDoubleString pwcsWide(%ws) cbWide(0x%x) psz(%s) cb(0x%x)\n",
+ pwcsWide?pwcsWide:L"<NULL>",
+ ccWide,
+ pszAnsi?pszAnsi:"<NULL>",
+ cbAnsi));
+ HRESULT hr;
+
+ //
+ // The string size is always written, but not including the size of the
+ // preceding DWORD so we conform to the way WriteAnsiString does it
+ //
+
+ ULONG ulTotalSize = 0;
+
+ //
+ // The entire reason we are supposed to be in this routine is that the
+ // pwcsWide could not be converted to ANSI. Therefore, it had better
+ // be valid.
+ //
+
+ Assert( (pwcsWide != NULL) && (ccWide == lstrlenW(pwcsWide)));
+ Assert( (pszAnsi == NULL) || (cbAnsi == (strlen(pszAnsi) + 1)));
+
+ ulTotalSize += ccWide * sizeof(WCHAR);
+
+ // Lets assume most ItemStrings will fit in this buffer
+
+ BYTE achQuickBuffer[256];
+ BYTE *pcbQuickBuffer = achQuickBuffer;
+
+ //
+ // Since we are going to cheat, and write something to the back of the
+ // ANSI string, the ANSI string must contain at least a NULL character.
+ // If it doesn't, we are going to cheat one in.
+ //
+ if (pszAnsi == NULL)
+ {
+ ulTotalSize += sizeof(char);
+ }
+ else
+ {
+ ulTotalSize += cbAnsi;
+ }
+
+ //
+ // If we don't fit in the QuickBuffer, allocate some memory
+ //
+ if (ulTotalSize > sizeof(achQuickBuffer))
+ {
+ pcbQuickBuffer = (BYTE *)PrivMemAlloc(ulTotalSize);
+
+ if (pcbQuickBuffer == NULL)
+ {
+ return(E_OUTOFMEMORY);
+ }
+ }
+
+ //
+ // First DWORD in the buffer is the total size of the string. This
+ // value includes strlen's of both strings, plus the size of the NULL
+ // on the Ansi string.
+ //
+ // Intrinsics will make this into a move of the correct alignment.
+ // Casting pcbQuickBuffer to a ULONG pointer is dangerous, since
+ // the alignment may be incorrect. Let the compiler figure out the
+ // correct thing to do.
+ //
+
+ memcpy(pcbQuickBuffer,&ulTotalSize,sizeof(ulTotalSize));
+
+ //
+ // Here, we make sure that pszAnsi ends up writing at least the NULL
+ // character
+ //
+
+ ULONG ulAnsiWritten;
+
+ memcpy(pcbQuickBuffer + sizeof(ulTotalSize),
+ pszAnsi?pszAnsi:"",
+ ulAnsiWritten = pszAnsi?cbAnsi:1);
+
+ //
+ // At this point, there should be a ULONG followed by at least 1
+ // character. The pointer arithmetic below puts us just past the
+ // null terminator of the Ansi string
+ //
+
+ memcpy(pcbQuickBuffer + sizeof(ulTotalSize) + ulAnsiWritten,
+ pwcsWide,
+ ccWide * sizeof(WCHAR));
+
+ mnkDebugOut((DEB_ITRACE,
+ "WriteDoubleString ulTotalSize(0x%x)\n",
+ ulTotalSize));
+
+ hr = pStm->Write(pcbQuickBuffer, ulTotalSize + sizeof(ULONG) ,NULL);
+
+ if (pcbQuickBuffer != achQuickBuffer)
+ {
+ PrivMemFree(pcbQuickBuffer);
+ }
+
+ return(hr);
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ExtractUnicodeString
+//
+// Synopsis: Given an ANSI string buffer, return a UNICODE path
+//
+// Effects:
+// If it exists, this routine will extract the UNICODE section
+// of a string written out in the following format:
+//
+// <ANSI string><0><UNICODESTRING>
+// ^ cbAnsiString ^
+//
+//
+// If the UNICODE string doesn't exist, then the Ansi string is converted
+// to UNICODE and returned
+//
+// Arguments: [pszAnsiString] -- Ansi string with potential UNICODE end
+// [cbAnsiString] -- Total number of bytes in pszAnsiString
+// [pwcsWideString] -- Reference to output string pointer
+// [ccWideString] -- Reference to output cound of characters
+//
+// Requires:
+//
+// Returns:
+// pwcsWideString will be a PrivMemAlloc()'d UNICODE string
+// ccWideString will be the character count (excluding the NULL)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-16-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT ExtractUnicodeString(LPSTR pszAnsiString,
+ USHORT cbAnsiString,
+ LPWSTR & pwcsString,
+ USHORT & ccString)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "ExtractUnicodeString pszAnsi(%s) cbAnsi(0x%x)\n",
+ ANSICHECK(pszAnsiString),
+ cbAnsiString));
+
+
+ USHORT cbAnsiStrLen;
+ HRESULT hr;
+
+
+ //
+ // If the Ansi string is NULL, then the Wide char will be also
+ //
+
+ if (pszAnsiString == NULL)
+ {
+ pwcsString = NULL;
+ ccString = 0;
+
+ return(NOERROR);
+ }
+
+ Assert( pwcsString == NULL);
+
+ //
+ // If strlen(pszAnsiString)+1 == cbAnsiString, then there is no
+ // UNICODE extent.
+ //
+
+ cbAnsiStrLen = strlen(pszAnsiString);
+
+ if ((cbAnsiStrLen + 1) == cbAnsiString)
+ {
+ //
+ // There is not a UNICODE extent. Convert from Ansi to UNICODE
+ //
+ pwcsString = NULL;
+
+ hr= MnkMultiToUnicode(pszAnsiString,
+ pwcsString,
+ 0,
+ ccString,
+ CP_ACP);
+
+ mnkDebugOut((DEB_ITRACE,
+ "ExtractUnicodeString converted (%s) to (%ws) ccString(0x%x)\n",
+ ANSICHECK(pszAnsiString),
+ WIDECHECK(pwcsString),
+ ccString));
+ }
+ else
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "ExtractUnicodeString found UNICODE extent\n"));
+
+ //
+ // There are extra characters following the AnsiString. Make a
+ // new buffer to copy them. Don't forget to add an extra WCHAR for
+ // the NULL termination
+ //
+ // AnsiStrLen + AnsiNull char
+ USHORT cbWideString = cbAnsiString - (cbAnsiStrLen + 1);
+
+ Assert(cbWideString != 0);
+
+ //
+ // There had best be an even number of bytes, or else something
+ // has gone wrong.
+ //
+
+ Assert( ! (cbWideString & 1));
+ // Strlen + sizeof(1 NULL char)
+ pwcsString = (WCHAR *) PrivMemAlloc(cbWideString + sizeof(WCHAR));
+ if (pwcsString == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto errRet;
+ }
+
+ memcpy(pwcsString,pszAnsiString + cbAnsiStrLen + 1, cbWideString);
+
+ ccString = cbWideString / sizeof(WCHAR);
+
+ pwcsString[ccString] = 0;
+
+ hr = NOERROR;
+ }
+
+errRet:
+ mnkDebugOut((DEB_ITRACE,
+ "ExtractUnicodeString result hr(%x) pwcsString(%ws) ccString(0x%x)\n",
+ hr,
+ WIDECHECK(pwcsString),
+ ccString));
+ return(hr);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CItemMoniker::Load
+//
+// Synopsis: Loads an Item moniker from a stream
+//
+// Effects: The first version of CItemMoniker stored two counted strings
+// in the stream. Both were stored in ANSI.
+//
+// This version saves a UNICODE string on the end of the ANSI
+// string. Therefore, when it is read back in, the count of
+// bytes read as the ANSI string may include a UNICODE string.
+//
+// See ::Save() for more details.
+//
+//
+// Arguments: [pStm] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-16-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CItemMoniker::Load (LPSTREAM pStm)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CItemMoniker::Load(%x)\n",
+ this));
+
+ VDATEIFACE(pStm);
+
+ ValidateMoniker();
+
+ HRESULT hresult;
+ LPSTR pszAnsiItem = NULL;
+ LPSTR pszAnsiDelim = NULL;
+
+ LPWSTR pwcsItem = NULL;
+ LPWSTR pwcsDelim = NULL;
+
+ USHORT cbAnsiDelim;
+ USHORT cbAnsiItem;
+
+ USHORT ccDelim;
+ USHORT ccItem;
+
+ //
+ // First, read in the two strings into the Ansi versions
+ //
+
+ hresult = ReadAnsiStringStream( pStm, pszAnsiDelim,cbAnsiDelim );
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+
+ mnkDebugOut((DEB_ITRACE,
+ "::Load(%x) pszAnsiDelim(%s) cbAnsiDelim(0x%x)\n",
+ this,
+ pszAnsiDelim,
+ cbAnsiDelim));
+
+ hresult = ReadAnsiStringStream( pStm, pszAnsiItem, cbAnsiItem );
+
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+
+ mnkDebugOut((DEB_ITRACE,
+ "::Load(%x) pszAnsiItem(%s) cbAnsiItem(0x%x)\n",
+ this,
+ pszAnsiItem,
+ cbAnsiItem));
+ //
+ // Now, determine the UNICODE strings. They may be stashed at the
+ // end of the Ansi strings.
+ //
+
+ hresult = ExtractUnicodeString(pszAnsiDelim,
+ cbAnsiDelim,
+ pwcsDelim,
+ ccDelim);
+
+ if (FAILED(hresult))
+ {
+ goto errRet;
+ }
+
+ hresult = ExtractUnicodeString(pszAnsiItem,
+ cbAnsiItem,
+ pwcsItem,
+ ccItem);
+ if (FAILED(hresult))
+ {
+ goto errRet;
+ }
+
+ Initialize ( pwcsDelim,
+ ccDelim,
+ pszAnsiDelim,
+ cbAnsiDelim,
+ pwcsItem,
+ ccItem,
+ pszAnsiItem,
+ cbAnsiItem );
+
+ ValidateMoniker();
+ return(NOERROR);
+
+errRet:
+ PrivMemFree(pszAnsiItem);
+ PrivMemFree(pszAnsiDelim);
+ PrivMemFree(pwcsItem);
+ PrivMemFree(pwcsDelim);
+ return hresult;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SaveUnicodeAsAnsi
+//
+// Synopsis: This function will save a string to the stream
+//
+// Effects:
+// This routine always attempts to save the string in Ansi. If it isn't
+// possible to save an Ansi version of the string, it will save an
+// Ansi version (which may be NULL), and a UNICODE version.
+//
+// Arguments: [pStm] -- Stream to write to
+// [pwcsWide] -- Unicode string
+// [ccWide] -- Count of UNICODE characters (EXCL NULL)
+// [pszAnsi] -- Ansi string
+// [cbAnsi] -- Count of bytes (INCL NULL)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-17-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT SaveUnicodeAsAnsi( LPSTREAM pStm,
+ LPWSTR pwcsWide,
+ USHORT ccWide,
+ LPSTR pszAnsi,
+ USHORT cbAnsi)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "::SaveUnicodeAsAnsi pwcsWide(%ws) ccWide(0x%x) pwsAnsi(%s) cbAnsi(0x%x)\n",
+ WIDECHECK(pwcsWide),
+ ccWide,
+ ANSICHECK(pszAnsi),
+ cbAnsi));
+ HRESULT hr;
+ BOOL fFastConvert;
+
+ //
+ // If the Ansi version exists, or the Unicode string is NULL,
+ // write out the Ansi version
+ //
+
+ if ((pszAnsi != NULL) || (pwcsWide == NULL))
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "::SaveUnicodeAsAnsi Ansi Only (%s)\n",
+ ANSICHECK(pszAnsi)));
+
+ hr = WriteAnsiStringStream( pStm,
+ pszAnsi,
+ cbAnsi);
+ }
+ else
+ {
+ //
+ // There isn't an AnsiVersion, and the UNICODE version isn't NULL
+ // Try to convert the UNICODE to Ansi
+ //
+
+ Assert( (pwcsWide != NULL) &&
+ (ccWide == lstrlenW(pwcsWide)));
+
+ mnkDebugOut((DEB_ITRACE,
+ "::SaveUnicodeAsAnsi Unicode string exists(%ws)\n",
+ WIDECHECK(pwcsWide)));
+
+ //
+ // We can use the pszAnsi pointer since it is NULL
+ //
+
+ Assert( pszAnsi == NULL);
+
+ hr = MnkUnicodeToMulti( pwcsWide,
+ ccWide,
+ pszAnsi,
+ cbAnsi,
+ fFastConvert);
+
+ Assert( (pszAnsi == NULL) || (cbAnsi == strlen(pszAnsi)+1) );
+
+ //
+ // A failure would mean out of memory, or some other terrible thing
+ // happened.
+ //
+
+ if (FAILED(hr))
+ {
+ goto errRet;
+ }
+
+ //
+ // If fFastConvert, then the UnicodeString was converted using a
+ // truncation algorithm, and the resulting Ansi string can be saved
+ // without the Unicode section appended
+ //
+
+ if (fFastConvert)
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "::SaveUnicodeAsAnsi Fast converted wide(%ws) to (%s) cbAnsi(0x%x)\n",
+ WIDECHECK(pwcsWide),
+ ANSICHECK(pszAnsi),
+ cbAnsi));
+
+ hr = WriteAnsiStringStream( pStm,
+ pszAnsi,
+ cbAnsi);
+ }
+ else
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "::SaveUnicodeAsAnsi Full conversion wide(%ws) to (%s) cbAnsi(0x%x)\n",
+ WIDECHECK(pwcsWide),
+ ANSICHECK(pszAnsi),
+ cbAnsi));
+
+ hr = WriteDoubleString( pStm,
+ pwcsWide,
+ ccWide,
+ pszAnsi,
+ cbAnsi);
+ }
+
+ //
+ // We are done with the Ansi string.
+ //
+ // BUGBUG: (KevinRo) It would be nice if we could get the double
+ // string back from WriteDoubleString and cache it. Perhaps later
+ // this can be done.
+ //
+
+ PrivMemFree(pszAnsi);
+ }
+
+errRet:
+ return(hr);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CItemMoniker::Save
+//
+// Synopsis: Save the moniker to a stream
+//
+// Effects: The first version of CItemMoniker stored two counted strings
+// in the stream. Both were stored in ANSI.
+//
+// This version saves a UNICODE string on the end of the ANSI
+// string. Therefore, when it is read back in, the count of
+// bytes read as the ANSI string may include a UNICODE string.
+//
+// We don't actually write the UNICODE string unless we have
+// to.
+//
+// Arguments: [pStm] --
+// [fClearDirty] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-16-94 kevinro Created
+//
+// Notes:
+//
+// There are two ways to create a CItemMoniker. Using CreateItemMoniker(),
+// and Load().
+//
+// If we were Load()'d, then it will be the case that we already have an
+// Ansi version of both strings. In this case, we will just save those
+// Ansi strings back out. If they already contain the UNICODE sections,
+// then they are saved as part of the package. Hopefully, this will be
+// the common case.
+//
+// Another possibility is the moniker was created using CreateItemMoniker.
+// If this is the case, then there are no Ansi versions of the strings.
+// We need to create Ansi strings, if possible. If we can't convert the
+// string to Ansi cleanly, then we need to save away a UNICODE section
+// of the string.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CItemMoniker::Save (LPSTREAM pStm, BOOL fClearDirty)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CItemMoniker::Save(%x)\n",
+ this));
+
+ ValidateMoniker();
+
+ VDATEIFACE(pStm);
+ UNREFERENCED(fClearDirty);
+ HRESULT hr;
+
+ //
+ // If a AnsiDelimiter exists, OR the UNICODE version is NULL, then
+ // write out the Ansi version
+ //
+
+ hr = SaveUnicodeAsAnsi( pStm,
+ m_lpszDelimiter,
+ m_ccDelimiter,
+ m_pszAnsiDelimiter,
+ m_cbAnsiDelimiter);
+ if (FAILED(hr))
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "CItemMoniker::Save(%x) SaveUnicodeAsAnsi Delim failed (%x)\n",
+ this,
+ hr));
+ goto errRet;
+ }
+
+ hr = SaveUnicodeAsAnsi( pStm,
+ m_lpszItem,
+ m_ccItem,
+ m_pszAnsiItem,
+ m_cbAnsiItem);
+ if (FAILED(hr))
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "CItemMoniker::Save(%x) SaveUnicodeAsAnsi Item failed (%x)\n",
+ this,
+ hr));
+ goto errRet;
+ }
+
+errRet:
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CItemMoniker::GetSizeMax
+//
+// Synopsis: Get the maximum size required to serialize this moniker
+//
+// Effects:
+//
+// Arguments: [pcbSize] -- Place to return value
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-17-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CItemMoniker::GetSizeMax (ULARGE_INTEGER FAR* pcbSize)
+{
+ ValidateMoniker();
+ VDATEPTROUT(pcbSize, ULARGE_INTEGER);
+ UINT cb;
+
+ //
+ // BUGBUG: (KevinRo) Revisit this calculation. Is there a better
+ // way of determining the size?
+ //
+ // The largest a UNICODE to MBSTRING should end up being is
+ // 2 * character count.
+ //
+ if (m_lpszItem)
+ {
+ cb = (m_ccItem + 1) * 2 * sizeof(WCHAR);
+ }
+ if (m_lpszDelimiter)
+ {
+ cb += (m_ccDelimiter + 1) * 2 * sizeof(WCHAR);
+ }
+
+ //
+ // sizeof(CLSID) accounts for the GUID that OleSaveToStream might
+ // write on our behalf. The two ULONGs are the string lengths,
+ // and cb is the max string sizes.
+ //
+
+ ULISet32(*pcbSize, sizeof(CLSID) + 2*(1 + sizeof(ULONG)) + cb);
+
+ return(NOERROR);
+}
+
+
+#define dwModerateTime 2500
+// 2.5 seconds divides immediate from moderate.
+
+DWORD BindSpeedFromBindCtx( LPBC pbc )
+{
+ BIND_OPTS bindopts;
+ HRESULT hresult;
+ DWORD dwBindSpeed = BINDSPEED_INDEFINITE;
+
+ bindopts.cbStruct = sizeof(bindopts);
+ hresult = pbc->GetBindOptions( &bindopts );
+ if (hresult != NOERROR) return dwBindSpeed;
+ Assert( bindopts.cbStruct >= 16);
+ if (bindopts.dwTickCountDeadline != 0)
+ {
+ if (bindopts.dwTickCountDeadline < dwModerateTime)
+ dwBindSpeed = BINDSPEED_IMMEDIATE;
+ else dwBindSpeed = BINDSPEED_MODERATE;
+ }
+ // else speed = default, BINDSPEED_INDEFINITE
+ return dwBindSpeed;
+}
+
+STDMETHODIMP CItemMoniker::BindToObject ( LPBC pbc,
+ LPMONIKER pmkToLeft, REFIID iidResult,
+ VOID FAR * FAR * ppvResult)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(ppvResult, LPVOID);
+ *ppvResult = NULL;
+ VDATEIFACE(pbc);
+ if (pmkToLeft) VDATEIFACE(pmkToLeft);
+ VDATEIID(iidResult);
+
+ ValidateMoniker();
+ HRESULT hresult;
+ LPOLEITEMCONTAINER pOleCont;
+
+ if (pmkToLeft)
+ {
+ hresult = pmkToLeft->BindToObject( pbc, NULL, IID_IOleItemContainer,
+ (LPVOID FAR*)&pOleCont);
+ // AssertOutPtrIface(hresult, pOleCont);
+ if (hresult != NOERROR) return hresult;
+
+ hresult = RegisterContainerBound(pbc, pOleCont);
+ hresult = pOleCont->GetObject(m_lpszItem, BindSpeedFromBindCtx(pbc),
+ pbc, iidResult, ppvResult);
+ // AssertOutPtrIface(hresult, *ppvResult);
+ pOleCont->Release();
+ return hresult;
+ }
+ return ResultFromScode(E_INVALIDARG); // needs non-null moniker to left.
+}
+
+
+STDMETHODIMP CItemMoniker::BindToStorage (LPBC pbc, LPMONIKER
+ pmkToLeft, REFIID riid, LPVOID FAR* ppvObj)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(ppvObj,LPVOID);
+ *ppvObj = NULL;
+ VDATEIFACE(pbc);
+ if (pmkToLeft) VDATEIFACE(pmkToLeft);
+ VDATEIID(riid);
+
+ HRESULT hresult;
+ LPOLEITEMCONTAINER pOleCont;
+
+ ValidateMoniker();
+
+ if (pmkToLeft)
+ {
+ hresult = pmkToLeft->BindToObject( pbc, NULL, IID_IOleItemContainer,
+ (LPVOID FAR*)&pOleCont);
+ // AssertOutPtrIface(hresult, pOleCont);
+ if (hresult != NOERROR) return hresult;
+ hresult = RegisterContainerBound(pbc, pOleCont);
+ hresult = pOleCont->GetObjectStorage(m_lpszItem, pbc,
+ riid, ppvObj);
+ // AssertOutPtrIface(hresult, *ppvObj);
+ pOleCont->Release();
+ return hresult;
+ }
+ return ResultFromScode(E_INVALIDARG); // needs non-null moniker to left.
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CItemMoniker::ComposeWith
+//
+// Synopsis: Compose this moniker with another moniker
+//
+// Effects:
+//
+// Arguments: [pmkRight] --
+// [fOnlyIfNotGeneric] --
+// [ppmkComposite] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-04-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CItemMoniker::ComposeWith ( LPMONIKER pmkRight,
+ BOOL fOnlyIfNotGeneric, LPMONIKER FAR* ppmkComposite)
+{
+
+ VDATEPTROUT(ppmkComposite,LPMONIKER);
+ *ppmkComposite = NULL;
+ VDATEIFACE(pmkRight);
+
+ HRESULT hresult = NOERROR;
+
+ ValidateMoniker();
+
+ //
+ // If this is an AntiMoniker, then we are going to ask the AntiMoniker
+ // for the composite. This is a backward compatibility problem. Check
+ // out the CAntiMoniker::EatOne() routine for details.
+ //
+
+ CAntiMoniker *pCAM = IsAntiMoniker(pmkRight);
+ if (pCAM)
+ {
+ pCAM->EatOne(ppmkComposite);
+ }
+ else
+ {
+ if (!fOnlyIfNotGeneric)
+ {
+ hresult = CreateGenericComposite( this, pmkRight, ppmkComposite );
+ }
+ else
+ {
+ hresult = ResultFromScode(MK_E_NEEDGENERIC);
+ *ppmkComposite = NULL;
+ }
+ }
+ return hresult;
+}
+
+
+
+STDMETHODIMP CItemMoniker::Enum (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(ppenumMoniker,LPENUMMONIKER);
+ *ppenumMoniker = NULL;
+ noError;
+}
+
+
+
+STDMETHODIMP CItemMoniker::IsEqual (THIS_ LPMONIKER pmkOtherMoniker)
+{
+ M_PROLOG(this);
+ VDATEIFACE(pmkOtherMoniker);
+
+ ValidateMoniker();
+
+ CItemMoniker FAR* pCIM = IsItemMoniker(pmkOtherMoniker);
+ if (!pCIM)
+ return ResultFromScode(S_FALSE);
+
+ // the other moniker is a item moniker.
+ // for the names, we do a case-insensitive compare.
+ if (m_lpszItem && pCIM->m_lpszItem)
+ {
+ if (0 == lstrcmpiW(pCIM->m_lpszItem, m_lpszItem))
+ return NOERROR; // S_TRUE;
+ }
+ else
+ return (m_lpszItem || pCIM->m_lpszItem ? ResultFromScode(S_FALSE ) : NOERROR /*S_TRUE*/);
+
+ return ResultFromScode(S_FALSE);
+
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CItemMoniker::Hash
+//
+// Synopsis: Compute a hash value
+//
+// Effects: Computes a hash using the same basic algorithm as the
+// file moniker. If possible, use the same routine as the
+// file monikers. However, if the string is longer than
+// MAX_PATH, calc it on our own.
+//
+// Arguments: [pdwHash] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-17-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CItemMoniker::Hash (THIS_ LPDWORD pdwHash)
+{
+ CLock lck(m_mxs); // protect m_fHashValueValid and m_dwHashValue
+
+ VDATEPTROUT(pdwHash, DWORD);
+ DWORD dwTemp = 0;
+ LPWSTR lp;
+ WCHAR ch;
+
+ ValidateMoniker();
+ if (m_fHashValueValid == FALSE)
+ {
+ //
+ // The CalcFileMonikerHash function does a STRUPR before running
+ // the length of the string. In UNICODE, that is faster.
+ // It uses a MAX_PATH buffer to do this. If the length is
+ // greater than MAX_PATH, then calculate it the old fashioned way.
+ //
+ if (m_ccItem < MAX_PATH)
+ {
+ m_dwHashValue = CalcFileMonikerHash(m_lpszItem);
+ }
+ else
+ {
+ lp = m_lpszItem;
+
+ if (lp != NULL)
+ {
+ while (*lp != 0)
+ {
+ dwTemp *= 3;
+ ch = (WCHAR)CharUpperW((LPWSTR)*lp);
+ dwTemp ^= ch;
+ lp++;
+ }
+ }
+ m_dwHashValue = dwTemp;
+ }
+ m_fHashValueValid = TRUE;
+ }
+ *pdwHash = m_dwHashValue;
+
+ return(NOERROR);
+}
+
+
+STDMETHODIMP CItemMoniker::IsRunning (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning)
+{
+ VDATEIFACE (pbc);
+ HRESULT hresult;
+
+
+ if (pmkToLeft)
+ VDATEIFACE (pmkToLeft);
+ if (pmkNewlyRunning)
+ VDATEIFACE (pmkNewlyRunning);
+
+ LPMONIKER pmkWild = NULL;
+ LPMONIKER pmk = NULL;
+ LPOLEITEMCONTAINER pCont = NULL;
+ LPRUNNINGOBJECTTABLE prot = NULL;
+
+ hresult = CreateItemMoniker(L"\\", NULL, &pmkWild);
+ if (hresult != NOERROR) goto errRet;
+
+ if (pmkToLeft == NULL)
+ {
+ if (pmkNewlyRunning != NULL)
+ {
+ hresult = IsEqual(pmkNewlyRunning);
+ if (hresult == NOERROR) goto errRet;
+ hresult = IsEqual(pmkNewlyRunning);
+ if (hresult != NOERROR)
+ {
+ hresult = ResultFromScode(S_FALSE);
+ goto errRet;
+ }
+ }
+ pbc->GetRunningObjectTable( &prot );
+ // check to see if "this" is in ROT
+ hresult = prot->IsRunning(this);
+ goto errRet;
+ }
+
+ hresult = pmkToLeft->IsRunning(pbc, NULL, NULL);
+ if (hresult == NOERROR)
+ {
+ hresult = pmkToLeft->BindToObject(pbc, NULL, IID_IOleItemContainer,
+ (LPVOID FAR *)&pCont );
+ // AssertOutPtrIface(hresult, pCont);
+ if (hresult == NOERROR)
+ {
+ // don't use RegisterContainerBound(pbc, pCont) here since we
+ // will lock/unlock the container unecessarily and possibly
+ // shut it down.
+ hresult = pbc->RegisterObjectBound(pCont);
+ if (hresult != NOERROR) goto errRet;
+ hresult = pCont->IsRunning(m_lpszItem);
+ }
+ }
+errRet:
+ if (pmkWild) pmkWild->Release();
+ if (pCont) pCont->Release();
+ if (prot) prot->Release();
+ return hresult;
+}
+
+
+
+STDMETHODIMP CItemMoniker::GetTimeOfLastChange (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime)
+{
+ M_PROLOG(this);
+ VDATEIFACE(pbc);
+ if (pmkToLeft) VDATEIFACE(pmkToLeft);
+ VDATEPTROUT(pfiletime, FILETIME);
+
+ ValidateMoniker();
+
+ HRESULT hresult;
+ LPMONIKER pmkTemp = NULL;
+ LPRUNNINGOBJECTTABLE prot = NULL;
+
+ if (pmkToLeft == NULL)
+ return ResultFromScode(MK_E_NOTBINDABLE);
+ // Getting time of last change
+ // for an orphan item moniker.
+
+ // Check to see if the composite is in the running object table
+ hresult = CreateGenericComposite( pmkToLeft, this, &pmkTemp );
+ if (hresult != NOERROR) goto errRet;
+ hresult = pbc->GetRunningObjectTable(& prot);
+ if (hresult != NOERROR) goto errRet;
+ hresult = prot->GetTimeOfLastChange( pmkTemp, pfiletime);
+ if (hresult != MK_E_UNAVAILABLE) goto errRet;
+
+ // if not, pass on to the left.
+ hresult = pmkToLeft->GetTimeOfLastChange(pbc, NULL, pfiletime);
+errRet:
+ if (pmkTemp) pmkTemp->Release();
+ if (prot) prot->Release();
+ return hresult;
+}
+
+
+
+STDMETHODIMP CItemMoniker::Inverse (THIS_ LPMONIKER FAR* ppmk)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(ppmk, LPMONIKER);
+ return CreateAntiMoniker(ppmk);
+}
+
+
+
+STDMETHODIMP CItemMoniker::CommonPrefixWith (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix)
+{
+ ValidateMoniker();
+ VDATEPTROUT(ppmkPrefix,LPMONIKER);
+ *ppmkPrefix = NULL;
+ VDATEIFACE(pmkOther);
+
+ if (!IsItemMoniker(pmkOther))
+ {
+ return(MonikerCommonPrefixWith(this,pmkOther,ppmkPrefix));
+ }
+
+ if (NOERROR == IsEqual(pmkOther))
+ {
+ *ppmkPrefix = this;
+ AddRef();
+ return ResultFromScode(MK_S_US);
+ }
+ return ResultFromScode(MK_E_NOPREFIX);
+}
+
+
+
+STDMETHODIMP CItemMoniker::RelativePathTo (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath)
+{
+ ValidateMoniker();
+ VDATEPTROUT(ppmkRelPath,LPMONIKER);
+
+ *ppmkRelPath = NULL;
+
+ VDATEIFACE(pmkOther);
+
+ return ResultFromScode(MK_E_NOTBINDABLE);
+}
+
+
+
+STDMETHODIMP CItemMoniker::GetDisplayName ( LPBC pbc, LPMONIKER
+ pmkToLeft, LPWSTR FAR * lplpszDisplayName )
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CItemMoniker::GetDisplayName(%x)\n",
+ this));
+
+ ValidateMoniker();
+
+ VDATEPTROUT(lplpszDisplayName, LPWSTR);
+ *lplpszDisplayName = NULL;
+
+ VDATEIFACE(pbc);
+
+ if (pmkToLeft)
+ {
+ VDATEIFACE(pmkToLeft);
+ }
+
+ ULONG cc = m_ccItem + m_ccDelimiter;
+
+ //
+ // cc holds the count of characters. Make extra room for the NULL
+ //
+
+ *lplpszDisplayName = (LPWSTR) CoTaskMemAlloc(sizeof(WCHAR)*(1 + cc));
+
+ if (*lplpszDisplayName == NULL)
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "::GetDisplayName(%x) returning out of memory\n",
+ this));
+
+ return E_OUTOFMEMORY;
+
+ }
+
+ //
+ // To handle the case where both strings are NULL, we set the first
+ // (and perhaps only) character to 0
+ //
+
+ *lplpszDisplayName[0] = 0;
+
+ //
+ // Concat the two strings. Don't forget the NULL! Thats what the
+ // extra character is for.
+ //
+
+ if (m_lpszDelimiter != NULL)
+ {
+ memcpy( *lplpszDisplayName,
+ m_lpszDelimiter,
+ (m_ccDelimiter + 1) * sizeof(WCHAR));
+ }
+
+ //
+ // The existing string was NULL terminated to just in case the
+ // Item string is NULL.
+ //
+ // Concat the Item string on the end of the Delimiter Again, don't
+ // forget the NULL.
+ //
+
+ if (m_lpszItem != NULL)
+ {
+ memcpy( *lplpszDisplayName + m_ccDelimiter,
+ m_lpszItem,
+ (m_ccItem + 1) * sizeof(WCHAR));
+ }
+
+ mnkDebugOut((DEB_ITRACE,
+ "::GetDisplayName(%x) returning %ws\n",
+ this,
+ *lplpszDisplayName));
+
+ return(NOERROR);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CItemMoniker::ParseDisplayName
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pbc] -- Bind Context
+// [pmkToLeft] -- Left moniker
+// [lpszDisplayName] -- String to parse
+// [pchEaten] -- Output number of characters eaten
+// [ppmkOut] -- Output moniker
+//
+// Requires:
+// pmkToLeft MUST be valid. NULL is inappropriate
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 2-03-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CItemMoniker::ParseDisplayName ( LPBC pbc,
+ LPMONIKER pmkToLeft,
+ LPWSTR lpszDisplayName,
+ ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut)
+{
+ HRESULT hresult;
+ VDATEPTRIN(lpszDisplayName, WCHAR);
+ VDATEPTROUT(pchEaten,ULONG);
+ VDATEPTROUT(ppmkOut,LPMONIKER);
+
+ IParseDisplayName FAR * pPDN = NULL;
+ IOleItemContainer FAR * pOIC = NULL;
+
+ ValidateMoniker();
+
+ *pchEaten = 0;
+ *ppmkOut = NULL;
+
+ VDATEIFACE(pbc);
+
+ //
+ // Item monikers require the moniker on the left to be non-null, so
+ // they can get the container to parse the display name
+ //
+
+ if (pmkToLeft != NULL)
+ {
+ VDATEIFACE(pmkToLeft);
+ }
+ else
+ {
+ hresult = MK_E_SYNTAX;
+ goto errRet;
+ }
+
+
+ hresult = pmkToLeft->BindToObject( pbc,
+ NULL,
+ IID_IOleItemContainer,
+ (VOID FAR * FAR *)&pOIC );
+ if (FAILED(hresult))
+ {
+ goto errRet;
+ }
+
+ hresult = RegisterContainerBound(pbc, pOIC);
+
+ if (FAILED(hresult))
+ {
+ goto errRet;
+ }
+
+ hresult = pOIC->GetObject( m_lpszItem,
+ BindSpeedFromBindCtx(pbc),
+ pbc,
+ IID_IParseDisplayName,
+ (LPVOID FAR*)&pPDN);
+ if (FAILED(hresult))
+ {
+ goto errRet;
+ }
+
+ hresult = pPDN->ParseDisplayName(pbc,
+ lpszDisplayName,
+ pchEaten,
+ ppmkOut );
+ if (FAILED(hresult))
+ {
+ goto errRet;
+ }
+
+ hresult = pbc->RegisterObjectBound( pPDN );
+
+errRet:
+ if (pPDN)
+ {
+ pPDN->Release();
+ }
+
+ if (pOIC)
+ {
+ pOIC->Release();
+ }
+
+ return hresult;
+}
+
+
+STDMETHODIMP CItemMoniker::IsSystemMoniker (THIS_ LPDWORD pdwType)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(pdwType,DWORD);
+
+ *pdwType = MKSYS_ITEMMONIKER;
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CItemMoniker::GetComparisonData
+//
+// Synopsis: Get comparison data for registration in the ROT
+//
+// Arguments: [pbData] - buffer to put the data in.
+// [cbMax] - size of the buffer
+// [pcbData] - count of bytes used in the buffer
+//
+// Returns: NOERROR
+// E_OUTOFMEMORY
+//
+// Algorithm: Build the ROT data from internal data of the item moniker.
+//
+// History: 03-Feb-95 ricksa Created
+//
+// Note: Validating the arguments is skipped intentionally because this
+// will typically be called internally by OLE with valid buffers.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CItemMoniker::GetComparisonData(
+ byte *pbData,
+ ULONG cbMax,
+ DWORD *pcbData)
+{
+ //
+ // CLSID plus delimiter plus item plus one NULL
+ //
+ ULONG ulLength = sizeof(CLSID_ItemMoniker) +
+ (m_ccItem + m_ccDelimiter + 1) * sizeof(WCHAR);
+
+ Assert(pcbData != NULL);
+ Assert(pbData != NULL);
+
+ if (cbMax < ulLength)
+ {
+ return(E_OUTOFMEMORY);
+ }
+
+ //
+ // Copy the classID
+ //
+ memcpy(pbData,&CLSID_ItemMoniker,sizeof(CLSID_FileMoniker));
+
+ //
+ // Copy the delimiter WITHOUT the NULL. This saves a little space,
+ // and allows us to uppercase them both as a single string
+ //
+ memcpy(pbData+sizeof(CLSID_FileMoniker),
+ m_lpszDelimiter,
+ m_ccDelimiter * sizeof(WCHAR));
+
+ //
+ // Copy the item plus the NULL
+ //
+ memcpy(pbData+sizeof(CLSID_FileMoniker)+(m_ccDelimiter * sizeof(WCHAR)),
+ m_lpszItem,
+ (m_ccItem + 1)*sizeof(WCHAR));
+
+ //
+ // Insure entire string is upper case, since the item monikers are spec'd
+ // (and already do) case insensitive comparisions
+ //
+ CharUpperW((WCHAR *)(pbData+sizeof(CLSID_FileMoniker)));
+
+ *pcbData = ulLength;
+
+ return NOERROR;
+}
+
+#ifdef _DEBUG
+
+STDMETHODIMP_(void) NC(CItemMoniker,CDebug)::Dump ( IDebugStream FAR * pdbstm)
+{
+ VOID_VDATEIFACE(pdbstm);
+
+ *pdbstm << "CItemMoniker @" << (VOID FAR *)m_pItemMoniker;
+ *pdbstm << '\n';
+ pdbstm->Indent();
+ *pdbstm << "Refcount is " << (int)(m_pItemMoniker->m_refs) << '\n';
+ *pdbstm << "Item string is " << m_pItemMoniker->m_lpszItem << '\n';
+ *pdbstm << "Delimiter is " << m_pItemMoniker->m_lpszDelimiter << '\n';
+ pdbstm->UnIndent();
+}
+
+STDMETHODIMP_(BOOL) NC(CItemMoniker,CDebug)::IsValid ( BOOL fSuspicious )
+{
+ return ((LONG)(m_pItemMoniker->m_refs) > 0);
+ // add more later, maybe
+}
+
+#endif
+
+
+//
+// Unlock Delay object
+//
+class FAR CDelayUnlockContainer : public CPrivAlloc, public IUnknown
+{
+public:
+ STDMETHOD(QueryInterface) ( REFIID iid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ CDelayUnlockContainer();
+
+private:
+ ULONG m_refs;
+ IOleItemContainer FAR * m_pOleCont;
+
+ friend INTERNAL RegisterContainerBound(LPBC pbc, LPOLEITEMCONTAINER pOleCont);
+};
+
+
+CDelayUnlockContainer::CDelayUnlockContainer()
+{
+ m_pOleCont = NULL;
+ m_refs = 1;
+}
+
+
+STDMETHODIMP CDelayUnlockContainer::QueryInterface (REFIID iid, LPLPVOID ppv)
+{
+ M_PROLOG(this);
+ if (IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppv = this;
+ AddRef();
+ return NOERROR;
+ }
+ else {
+ *ppv = NULL;
+ return ResultFromScode(E_NOINTERFACE);
+ }
+}
+
+
+STDMETHODIMP_(ULONG) CDelayUnlockContainer::AddRef ()
+{
+ return(InterlockedIncrement((long *)&m_refs));
+
+}
+
+
+STDMETHODIMP_(ULONG) CDelayUnlockContainer::Release ()
+{
+ if (InterlockedDecrement((long *)&m_refs) == 0)
+ {
+ if (m_pOleCont != NULL)
+ {
+ m_pOleCont->LockContainer(FALSE);
+ m_pOleCont->Release();
+ }
+ delete this;
+ return 0;
+ }
+
+ return 1;
+}
+
+
+INTERNAL RegisterContainerBound (LPBC pbc, LPOLEITEMCONTAINER pOleCont)
+{
+ // don't give the delay object the pOleCont before we lock it; do in
+ // this order so error checking is correct and we don't lock/unlock
+ // inappropriately.
+
+ CDelayUnlockContainer FAR* pCDelay = new CDelayUnlockContainer();
+ if (pCDelay == NULL)
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ HRESULT hresult;
+ if ((hresult = pbc->RegisterObjectBound(pCDelay)) != NOERROR)
+ goto errRet;
+
+ if ((hresult = pOleCont->LockContainer(TRUE)) != NOERROR) {
+ // the delay object is still in the bindctx; no harm
+ hresult = E_FAIL;
+ goto errRet;
+ }
+
+
+ pCDelay->m_pOleCont = pOleCont;
+ pOleCont->AddRef();
+
+errRet:
+ pCDelay->Release();
+ return hresult;
+}
diff --git a/private/ole32/com/moniker2/citemmon.hxx b/private/ole32/com/moniker2/citemmon.hxx
new file mode 100644
index 000000000..242fa1851
--- /dev/null
+++ b/private/ole32/com/moniker2/citemmon.hxx
@@ -0,0 +1,125 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: citemmon.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Commented
+// 10-13-95 stevebl threadsafety
+//
+//----------------------------------------------------------------------------
+
+#include <sem.hxx>
+
+class FAR CItemMoniker : public CBaseMoniker
+{
+
+public:
+ static CItemMoniker *Create( LPCWSTR szDelim, LPCWSTR szItemName);
+
+private:
+
+ CItemMoniker( void );
+ ~CItemMoniker( void );
+ INTERNAL_(BOOL) Initialize( LPCWSTR szDelim, LPCWSTR szItemName );
+ void CItemMoniker::Initialize ( LPWSTR lpwcsDelimiter,
+ USHORT ccDelimiter,
+ LPSTR lpszAnsiDelimiter,
+ USHORT cbAnsiDelimiter,
+ LPWSTR lpwcsItemName,
+ USHORT ccItemName,
+ LPSTR lpszAnsiItem,
+ USHORT cbAnsiItem );
+
+ STDDEBDECL(CItemMoniker, ItemMoniker)
+
+ void UnInit(void);
+public:
+ // *** IUnknown methods inherited from CBaseMoniker ***
+
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,Release) (THIS);
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID);
+
+ // *** IPersistStream methods ***
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm);
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty);
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR * pcbSize);
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID FAR* ppvResult);
+ STDMETHOD(BindToStorage) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNOtGeneric,
+ LPMONIKER FAR* ppmkComposite);
+ STDMETHOD(Enum) (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker);
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker);
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash);
+ STDMETHOD(IsRunning) (THIS_ LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+ pmkNewlyRunning);
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime);
+ STDMETHOD(Inverse) (THIS_ LPMONIKER FAR* ppmk);
+ STDMETHOD(CommonPrefixWith) (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix);
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath);
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR FAR* lplpszDisplayName);
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut);
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys);
+
+ // *** IROTData Methods ***
+ STDMETHOD(GetComparisonData)(
+ byte *pbData,
+ ULONG cbMax,
+ ULONG *pcbData);
+
+#if DBG == 1
+ void ValidateMoniker();
+#else
+ inline void ValidateMoniker() {;}
+#endif
+
+ //
+ // Note: We keep the sizes of the strings in two formats.
+ // For wide characters, we know the count.
+ //
+ // For Ansi strings, we know the number of bytes. The number of
+ // bytes includes the terminating NULL, where the ccPath doesn't.
+ //
+ // The reason for this is we write out the Ansi strings as blobs
+ //
+ //
+ // WARNING: m_cbAnsi* fields are NOT string lengths!
+ //
+
+ WCHAR FAR* m_lpszItem;
+ char * m_pszAnsiItem;
+
+ USHORT m_ccItem; // Only valid if m_lpszItem != NULL
+ USHORT m_cbAnsiItem; // Only valid if m_lpszAnsiItem != NULL
+
+shared_state:
+ WCHAR FAR* m_lpszDelimiter;
+ char * m_pszAnsiDelimiter;
+
+ USHORT m_ccDelimiter; // Only valid if m_lpszDelimiter!= NULL
+ USHORT m_cbAnsiDelimiter; // Only valid if m_lpszAnsiDelimiter!= NULL
+
+ ULONG m_fHashValueValid:1;
+ DWORD m_dwHashValue;
+ CMutexSem m_mxs;
+};
diff --git a/private/ole32/com/moniker2/classmon.cxx b/private/ole32/com/moniker2/classmon.cxx
new file mode 100644
index 000000000..ccaebf32e
--- /dev/null
+++ b/private/ole32/com/moniker2/classmon.cxx
@@ -0,0 +1,1336 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1996.
+//
+// File: classmon.cxx
+//
+// Contents: Implementation of CClassMoniker
+//
+// Classes: CClassMoniker
+//
+// Functions: CreateClassMoniker
+//
+// History: 22-Feb-96 ShannonC Created
+//
+//----------------------------------------------------------------------------
+#include <ole2int.h>
+#include "classmon.hxx"
+#include "mnk.h"
+
+#ifndef OLETRACEIN
+#define OLETRACEIN(x)
+#endif
+
+#ifndef OLETRACEOUT
+#define OLETRACEOUT(x)
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateClassMoniker
+//
+// Synopsis: Creates a class moniker for the specified CLSID.
+//
+// Arguments: [rclsid] - Supplies the CLSID of the class.
+// [ppmk] - Returns interface pointer of the new moniker.
+//
+// Returns: S_OK
+// E_INVALIDARG
+// E_OUTOFMEMORY
+//
+//----------------------------------------------------------------------------
+STDAPI CreateClassMoniker(
+ REFCLSID rclsid,
+ IMoniker **ppmk)
+{
+ HRESULT hr;
+ CLSID clsid;
+ IMoniker *pmk;
+
+ __try
+ {
+ OLETRACEIN((API_CreateClassMoniker,
+ PARAMFMT("rclsid= %I, ppmk= %p"),
+ &rclsid, ppmk));
+
+ //Validate parameters.
+ *ppmk = NULL;
+ clsid = rclsid;
+
+ pmk = new CClassMoniker(clsid);
+
+ if (pmk != NULL)
+ {
+ *ppmk = pmk;
+ hr = S_OK;
+ CALLHOOKOBJECTCREATE(hr,
+ CLSID_ClassMoniker,
+ IID_IMoniker,
+ (IUnknown **)ppmk);
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+
+ }
+
+ OLETRACEOUT((API_CreateFileMoniker, hr));
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::CClassMoniker
+//
+// Synopsis: Constructor for class moniker.
+//
+// Arguments: rclsid - Supplies the CLSID of the class.
+//
+//----------------------------------------------------------------------------
+CClassMoniker::CClassMoniker(REFCLSID rclsid)
+: _cRefs(1), _pExtra(NULL)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::CClassMoniker(%x,%I)\n",
+ this, &rclsid));
+
+ _data.clsid = rclsid;
+ _data.cbExtra = 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::~CClassMoniker
+//
+// Synopsis: Constructor for class moniker.
+//
+// Arguments: rclsid - Supplies the CLSID of the class.
+//
+//----------------------------------------------------------------------------
+CClassMoniker::~CClassMoniker()
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::~CClassMoniker(%x)\n",
+ this));
+
+ if(_pExtra != NULL)
+ {
+ PrivMemFree(_pExtra);
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::SetParameters
+//
+// Synopsis: Set the parameters on the class moniker
+//
+// Arguments: pszName - Name of the parameter.
+// pszValue - Value of the parameter.
+//
+//----------------------------------------------------------------------------
+HRESULT CClassMoniker::SetParameters(
+ LPCWSTR pszParameters)
+{
+ HRESULT hr = S_OK;
+
+ //Free the old data.
+ if(_pExtra != NULL)
+ {
+ PrivMemFree(_pExtra);
+ _pExtra = NULL;
+ }
+
+ if(pszParameters != NULL)
+ {
+ _data.cbExtra = lstrlenW(pszParameters) * sizeof(WCHAR) + sizeof(WCHAR);
+
+ //Allocate memory for the extra bytes.
+ _pExtra = PrivMemAlloc(_data.cbExtra);
+
+ if(_pExtra != 0)
+ {
+ memcpy(_pExtra, pszParameters, _data.cbExtra);
+ hr = S_OK;
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::QueryInterface
+//
+// Synopsis: Gets a pointer to the specified interface. The class
+// moniker supports the IMarshal, IMoniker, IPersistStream,
+// IPersist, IROTData, and IUnknown interfaces. The class
+// moniker also supports CLSID_ClassMoniker so that the
+// IsEqual method can directly access the data members.
+//
+// Arguments: [iid] -- the requested interface
+// [ppv] -- where to put the interface pointer
+//
+// Returns: S_OK
+// E_INVALIDARG
+// E_NOINTERFACE
+//
+// Notes: Bad parameters will raise an exception. The exception
+// handler catches exceptions and returns E_INVALIDARG.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::QueryInterface(
+ REFIID riid,
+ void **ppv)
+{
+ HRESULT hr;
+
+ __try
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::QueryInterface(%x,%I,%x)\n",
+ this, &riid, ppv));
+
+ //Parameter validation.
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, IID_IMarshal))
+ {
+ AddRef();
+ *ppv = (IMarshal *) this;
+ hr = S_OK;
+ }
+ else if (IsEqualIID(riid, IID_IUnknown)
+ || IsEqualIID(riid, IID_IMoniker)
+ || IsEqualIID(riid, IID_IPersistStream)
+ || IsEqualIID(riid, IID_IPersist))
+ {
+ AddRef();
+ *ppv = (IMoniker *) this;
+ hr = S_OK;
+ }
+ else if (IsEqualIID(riid, IID_IROTData))
+ {
+ AddRef();
+ *ppv = (IROTData *) this;
+ hr = S_OK;
+ }
+ else if (IsEqualIID(riid, CLSID_ClassMoniker))
+ {
+ AddRef();
+ *ppv = (CClassMoniker *) this;
+ hr = S_OK;
+ }
+ else
+ {
+ hr = E_NOINTERFACE;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::AddRef
+//
+// Synopsis: Increment the reference count.
+//
+// Arguments: void
+//
+// Returns: ULONG -- the new reference count
+//
+// Notes: Use InterlockedIncrement to make it multi-thread safe.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CClassMoniker::AddRef(void)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::AddRef(%x)\n",
+ this));
+
+ InterlockedIncrement(&_cRefs);
+ return _cRefs;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::Release
+//
+// Synopsis: Decrement the reference count.
+//
+// Arguments: void
+//
+// Returns: ULONG -- the remaining reference count
+//
+// Notes: Use InterlockedDecrement to make it multi-thread safe.
+// We use a local variable so that we don't access
+// a data member after decrementing the reference count.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CClassMoniker::Release(void)
+{
+ ULONG count = _cRefs - 1;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::Release(%x)\n",
+ this));
+
+ if(0 == InterlockedDecrement(&_cRefs))
+ {
+ delete this;
+ count = 0;
+ }
+
+ return count;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::GetClassID
+//
+// Synopsis: Gets the class ID of the object.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::GetClassID(
+ CLSID *pClassID)
+{
+ HRESULT hr;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::GetClassID(%x,%x)\n",
+ this, pClassID));
+
+ __try
+ {
+
+ *pClassID = CLSID_ClassMoniker;
+ hr = S_OK;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::IsDirty
+//
+// Synopsis: Checks the object for changes since it was last saved.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::IsDirty()
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::IsDirty(%x)\n",
+ this));
+
+ return S_FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::Load
+//
+// Synopsis: Loads a class moniker from a stream
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::Load(
+ IStream *pStream)
+{
+ HRESULT hr;
+ ULONG cbRead;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::Load(%x,%x)\n",
+ this, pStream));
+
+ __try
+ {
+ hr = pStream->Read(&_data, sizeof(_data), &cbRead);
+
+ if(SUCCEEDED(hr))
+ {
+ if(sizeof(_data) == cbRead)
+ {
+ if(_data.cbExtra != 0)
+ {
+ //Free the old buffer if necessary.
+ if(_pExtra != NULL)
+ {
+ PrivMemFree(_pExtra);
+ }
+
+ //Allocate buffer and read the extra bytes.
+ _pExtra = PrivMemAlloc(_data.cbExtra);
+ if(_pExtra != NULL)
+ {
+ hr = pStream->Read(_pExtra,
+ _data.cbExtra,
+ &cbRead);
+ if(SUCCEEDED(hr))
+ {
+ if(cbRead == _data.cbExtra)
+ hr = S_OK;
+ else
+ hr = STG_E_READFAULT;
+ }
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ hr = S_OK;
+ }
+ }
+ else
+ {
+ hr = STG_E_READFAULT;
+ }
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::Save
+//
+// Synopsis: Save the class moniker to a stream
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::Save(
+ IStream *pStream,
+ BOOL fClearDirty)
+{
+ HRESULT hr;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::Save(%x,%x,%x)\n",
+ this, pStream, fClearDirty));
+
+ __try
+ {
+ hr = pStream->Write(&_data, sizeof(_data), NULL);
+ if(SUCCEEDED(hr) && _pExtra != NULL && _data.cbExtra > 0)
+ {
+ //Write the extra bytes.
+ hr = pStream->Write(_pExtra, _data.cbExtra, NULL);
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::GetSizeMax
+//
+// Synopsis: Get the maximum size required to serialize this moniker
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::GetSizeMax(
+ ULARGE_INTEGER * pcbSize)
+{
+ HRESULT hr;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::GetSizeMax(%x,%x)\n",
+ this, pcbSize));
+
+ __try
+ {
+ ULISet32(*pcbSize, sizeof(_data) + _data.cbExtra);
+ hr = S_OK;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::BindToObject
+//
+// Synopsis: Bind to the object named by this moniker.
+//
+// Notes: If pmkToLeft is zero, then the class moniker calls
+// CoGetClassObject to get an interface pointer to the class object.
+//
+// If pmkToLeft is non-zero, then the class moniker binds to the
+// IClassActivator interface and then calls
+// IClassActivator::GetClassObject.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::BindToObject (
+ IBindCtx *pbc,
+ IMoniker *pmkToLeft,
+ REFIID iidResult,
+ void ** ppvResult)
+{
+ HRESULT hr;
+ IID iid;
+ BIND_OPTS2 bindOpts;
+
+ __try
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::BindToObject(%x,%x,%x,%I,%x)\n",
+ this, pbc, pmkToLeft, &iidResult, ppvResult));
+
+ //Validate parameters
+ *ppvResult = NULL;
+ iid = iidResult;
+
+ bindOpts.cbStruct = sizeof(bindOpts);
+ hr = pbc->GetBindOptions(&bindOpts);
+
+ if(SUCCEEDED(hr))
+ {
+ //Get the class object.
+ if(NULL == pmkToLeft)
+ {
+ //Call the internal CoGetClassObject.
+ hr = ICoGetClassObject(_data.clsid,
+ bindOpts.dwClassContext,
+ NULL,
+ iid,
+ ppvResult);
+ }
+ else
+ {
+ IClassActivator *pActivate;
+
+ hr = pmkToLeft->BindToObject(pbc,
+ NULL,
+ IID_IClassActivator,
+ (void **) &pActivate);
+
+ if(SUCCEEDED(hr))
+ {
+ hr = pActivate->GetClassObject(_data.clsid,
+ bindOpts.dwClassContext,
+ bindOpts.locale,
+ iid,
+ ppvResult);
+
+ pActivate->Release();
+ }
+
+ }
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::BindToStorage
+//
+// Synopsis: Bind to the storage for the object named by the moniker.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::BindToStorage(
+ IBindCtx *pbc,
+ IMoniker *pmkToLeft,
+ REFIID riid,
+ void ** ppv)
+{
+ HRESULT hr;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::BindToStorage(%x,%x,%x,%I,%x)\n",
+ this, pbc, pmkToLeft, &riid, ppv));
+
+ hr = BindToObject(pbc, pmkToLeft, riid, ppv);
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::Reduce
+//
+// Synopsis: Reduce the moniker.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::Reduce(
+ IBindCtx * pbc,
+ DWORD dwReduceHowFar,
+ IMoniker ** ppmkToLeft,
+ IMoniker ** ppmkReduced)
+{
+ HRESULT hr;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::Reduce(%x,%x,%x,%x,%x)\n",
+ this, pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced));
+
+ __try
+ {
+ //Validate parameters.
+ *ppmkReduced = NULL;
+
+ AddRef();
+ *ppmkReduced = (IMoniker *) this;
+ hr = MK_S_REDUCED_TO_SELF;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::ComposeWith
+//
+// Synopsis: Compose another moniker onto the end of this moniker.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::ComposeWith(
+ IMoniker * pmkRight,
+ BOOL fOnlyIfNotGeneric,
+ IMoniker **ppmkComposite)
+{
+ HRESULT hr;
+ IMoniker *pmk;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::ComposeWith(%x,%x,%x,%x)\n",
+ this, pmkRight, fOnlyIfNotGeneric, ppmkComposite));
+
+ __try
+ {
+ //Validate parameters.
+ *ppmkComposite = NULL;
+
+ //Check for an anti-moniker
+ hr = pmkRight->QueryInterface(CLSID_AntiMoniker, (void **)&pmk);
+
+ if(FAILED(hr))
+ {
+ //pmkRight is not an anti-moniker.
+ if (!fOnlyIfNotGeneric)
+ {
+ hr = CreateGenericComposite(this, pmkRight, ppmkComposite);
+ }
+ else
+ {
+ hr = MK_E_NEEDGENERIC;
+ }
+ }
+ else
+ {
+ //pmkRight is an anti-moniker.
+ pmk->Release();
+ hr = S_OK;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::Enum
+//
+// Synopsis: Enumerate the components of this moniker.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::Enum(
+ BOOL fForward,
+ IEnumMoniker ** ppenumMoniker)
+{
+ HRESULT hr;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::Enum(%x,%x,%x)\n",
+ this, fForward, ppenumMoniker));
+
+ __try
+ {
+ *ppenumMoniker = NULL;
+ hr = S_OK;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::IsEqual
+//
+// Synopsis: Compares with another moniker.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::IsEqual(
+ IMoniker *pmkOther)
+{
+ HRESULT hr;
+ CClassMoniker *pClassMoniker;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::IsEqual(%x,%x)\n",
+ this, pmkOther));
+
+ __try
+ {
+ hr = pmkOther->QueryInterface(CLSID_ClassMoniker,
+ (void **) &pClassMoniker);
+
+ if(SUCCEEDED(hr))
+ {
+ if(IsEqualCLSID(_data.clsid,
+ pClassMoniker->_data.clsid))
+ {
+ hr = S_OK;
+ }
+ else
+ {
+ hr = S_FALSE;
+ }
+
+ pClassMoniker->Release();
+ }
+ else
+ {
+ hr = S_FALSE;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::Hash
+//
+// Synopsis: Compute a hash value
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::Hash(
+ DWORD * pdwHash)
+{
+ HRESULT hr;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::Hash(%x,%x)\n",
+ this, pdwHash));
+
+ __try
+ {
+ *pdwHash = _data.clsid.Data1;
+ hr = S_OK;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::IsRunning
+//
+// Synopsis: Determines if the object identified by this moniker is
+// running. Since we can't search the class table to determine
+// if the object is running, we just return E_NOTIMPL.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::IsRunning(
+ IBindCtx * pbc,
+ IMoniker * pmkToLeft,
+ IMoniker * pmkNewlyRunning)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::IsRunning(%x,%x,%x,%x)\n",
+ this, pbc, pmkToLeft, pmkNewlyRunning));
+
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::GetTimeOfLastChange
+//
+// Synopsis: Returns the time when the object identified by this moniker
+// was changed.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::GetTimeOfLastChange (
+ IBindCtx * pbc,
+ IMoniker * pmkToLeft,
+ FILETIME * pFileTime)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::GetTimeOfLastChange(%x,%x,%x,%x)\n",
+ this, pbc, pmkToLeft, pFileTime));
+
+ return MK_E_UNAVAILABLE;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::Inverse
+//
+// Synopsis: Returns the inverse of this moniker.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::Inverse(
+ IMoniker ** ppmk)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::Inverse(%x,%x)\n",
+ this, ppmk));
+
+ return CreateAntiMoniker(ppmk);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::CommonPrefixWith
+//
+// Synopsis: Returns the common prefix shared by this moniker and the
+// other moniker.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::CommonPrefixWith(
+ IMoniker * pmkOther,
+ IMoniker ** ppmkPrefix)
+{
+ HRESULT hr;
+ CClassMoniker *pClassMoniker;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::CommonPrefixWith(%x,%x,%x)\n",
+ this, pmkOther, ppmkPrefix));
+
+ __try
+ {
+ //Validate parameters.
+ *ppmkPrefix = NULL;
+
+ hr = pmkOther->QueryInterface(CLSID_ClassMoniker,
+ (void **) &pClassMoniker);
+
+ if(SUCCEEDED(hr))
+ {
+ if(IsEqualCLSID(_data.clsid,
+ pClassMoniker->_data.clsid))
+ {
+ AddRef();
+ *ppmkPrefix = (IMoniker *) this;
+ hr = MK_S_US;
+ }
+ else
+ {
+ hr = MK_E_NOPREFIX;
+ }
+
+ pClassMoniker->Release();
+ }
+ else
+ {
+ hr = MonikerCommonPrefixWith(this, pmkOther, ppmkPrefix);
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::RelativePathTo
+//
+// Synopsis: Returns the relative path between this moniker and the
+// other moniker.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::RelativePathTo(
+ IMoniker * pmkOther,
+ IMoniker ** ppmkRelPath)
+{
+ HRESULT hr;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::RelativePathTo(%x,%x,%x)\n",
+ this, pmkOther, ppmkRelPath));
+
+ __try
+ {
+ *ppmkRelPath = NULL;
+ hr = MonikerRelativePathTo(this, pmkOther, ppmkRelPath, TRUE);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::GetDisplayName
+//
+// Synopsis: Get the display name of this moniker.
+//
+// Notes: Call ProgIDFromClassID to get the ProgID
+// Append a ':' to the end of the string.
+// If no ProgID is available, then use
+// clsid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx;parameters:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::GetDisplayName(
+ IBindCtx * pbc,
+ IMoniker * pmkToLeft,
+ LPWSTR * lplpszDisplayName)
+{
+ HRESULT hr = E_FAIL;
+ LPWSTR pszDisplayName;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::GetDisplayName(%x,%x,%x,%x)\n",
+ this, pbc, pmkToLeft, lplpszDisplayName));
+
+ __try
+ {
+ LPWSTR pszPrefix;
+ WCHAR szClassID[37];
+ LPWSTR pszParameters = (LPWSTR) _pExtra;
+
+ //Validate parameters.
+ *lplpszDisplayName = NULL;
+
+
+ //Create a display name from the class ID.
+ //Get the class ID string.
+ wStringFromUUID(_data.clsid, szClassID);
+
+ //Get the prefix
+ hr = ProgIDFromCLSID(CLSID_ClassMoniker,
+ &pszPrefix);
+
+ if(SUCCEEDED(hr))
+ {
+ ULONG cName;
+ cName = lstrlenW(pszPrefix) + 1 + lstrlenW(szClassID);
+ if(pszParameters != NULL)
+ {
+ cName += lstrlenW(pszParameters);
+ }
+ cName += 2;
+
+ pszDisplayName = (LPWSTR) CoTaskMemAlloc(cName * sizeof(wchar_t));
+ if(pszDisplayName != NULL)
+ {
+ lstrcpyW(pszDisplayName, pszPrefix);
+ lstrcatW(pszDisplayName, L":");
+ lstrcatW(pszDisplayName, szClassID);
+ if(pszParameters != NULL)
+ {
+ lstrcatW(pszDisplayName, pszParameters);
+ }
+
+ lstrcatW(pszDisplayName, L":");
+ *lplpszDisplayName = pszDisplayName;
+ hr = S_OK;
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ CoTaskMemFree(pszPrefix);
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::ParseDisplayName
+//
+// Synopsis: Parse the display name.
+//
+// Algorithm: Call BindToObject to get an IParseDisplayName on the class
+// object. Call IParseDisplayName::ParseDisplayName on the
+// class object.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::ParseDisplayName (
+ IBindCtx * pbc,
+ IMoniker * pmkToLeft,
+ LPWSTR lpszDisplayName,
+ ULONG * pchEaten,
+ IMoniker ** ppmkOut)
+{
+ HRESULT hr;
+ IParseDisplayName *pPDN;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::ParseDisplayName(%x,%x,%x,%ws,%x,%x)\n",
+ this, pbc, pmkToLeft, lpszDisplayName, pchEaten, ppmkOut));
+
+ __try
+ {
+ //Validate parameters
+ *ppmkOut = NULL;
+ *pchEaten = 0;
+
+ hr = BindToObject(pbc,
+ pmkToLeft,
+ IID_IParseDisplayName,
+ (void **) &pPDN);
+
+ if(SUCCEEDED(hr))
+ {
+ //Register the object with the bind context.
+ hr = pbc->RegisterObjectBound(pPDN);
+ if(SUCCEEDED(hr))
+ {
+ //Parse the display name.
+ hr = pPDN->ParseDisplayName(pbc,
+ lpszDisplayName,
+ pchEaten,
+ ppmkOut);
+ }
+ pPDN->Release();
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::IsSystemMoniker
+//
+// Synopsis: Determines if this is one of the system supplied monikers.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::IsSystemMoniker(
+ DWORD * pdwType)
+{
+ HRESULT hr;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::IsSystemMoniker(%x,%x)\n",
+ this, pdwType));
+
+ __try
+ {
+ *pdwType = MKSYS_CLASSMONIKER;
+ hr = S_OK;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::GetComparisonData
+//
+// Synopsis: Get comparison data for registration in the ROT
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::GetComparisonData(
+ byte * pbData,
+ ULONG cbMax,
+ DWORD *pcbData)
+{
+ HRESULT hr;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::GetComparisonData(%x,%x,%x,%x)\n",
+ this, pbData, cbMax, pcbData));
+
+ __try
+ {
+ *pcbData = 0;
+ if(cbMax >= sizeof(CLSID_ClassMoniker) + sizeof(_data.clsid))
+ {
+ memcpy(pbData, &CLSID_ClassMoniker, sizeof(CLSID_ClassMoniker));
+ pbData += sizeof(CLSID);
+ memcpy(pbData, &_data.clsid, sizeof(_data.clsid));
+ *pcbData = sizeof(CLSID_ClassMoniker) + sizeof(_data.clsid);
+ hr = S_OK;
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::GetUnmarshalClass
+//
+// Synopsis: Get the class ID.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::GetUnmarshalClass(
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ CLSID * pClassID)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::GetUnmarshalClass(%x,%I,%x,%x,%x,%x,%x)\n",
+ this, &riid, pv, dwDestContext, pvDestContext, mshlflags,
+ pClassID));
+
+ return GetClassID(pClassID);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::GetMarshalSizeMax
+//
+// Synopsis: Get maximum size of marshalled moniker.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::GetMarshalSizeMax(
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ DWORD *pSize)
+{
+ HRESULT hr;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::GetMarshalSizeMax(%x,%I,%x,%x,%x,%x,%x)\n",
+ this, &riid, pv, dwDestContext, pvDestContext, mshlflags,
+ pSize));
+
+ __try
+ {
+ *pSize = sizeof(_data) + _data.cbExtra;
+ hr = S_OK;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::MarshalInterface
+//
+// Synopsis: Marshal moniker into a stream.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::MarshalInterface(
+ IStream * pStream,
+ REFIID riid,
+ void * pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::MarshalInterface(%x,%x,%I,%x,%x,%x,%x)\n",
+ this, pStream, &riid, pv, dwDestContext, pvDestContext,
+ mshlflags));
+
+ return Save(pStream, FALSE);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::UnmarshalInterface
+//
+// Synopsis: Unmarshal moniker from a stream.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::UnmarshalInterface(
+ IStream * pStream,
+ REFIID riid,
+ void ** ppv)
+{
+ HRESULT hr;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::UnmarshalInterface(%x,%x,%I,%x)\n",
+ this, pStream, &riid, ppv));
+
+ __try
+ {
+ //Validate parameters.
+ *ppv = NULL;
+
+ hr = Load(pStream);
+
+ if(SUCCEEDED(hr))
+ {
+ hr = QueryInterface(riid, ppv);
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::ReleaseMarshalData
+//
+// Synopsis: Release a marshalled class moniker.
+// Just seek to the end of the marshalled class moniker.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::ReleaseMarshalData(
+ IStream * pStream)
+{
+ HRESULT hr;
+ LARGE_INTEGER liSize;
+
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::ReleaseMarshalData(%x,%x)\n",
+ this, pStream));
+
+ hr = GetSizeMax((ULARGE_INTEGER *) &liSize);
+ if(SUCCEEDED(hr))
+ {
+ hr = pStream->Seek(liSize, STREAM_SEEK_CUR, NULL);
+ }
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassMoniker::DisconnectObject
+//
+// Synopsis: Disconnect the object.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClassMoniker::DisconnectObject(
+ DWORD dwReserved)
+{
+ mnkDebugOut((DEB_ITRACE,
+ "CClassMoniker::DisconnectObject(%x,%x)\n",
+ this, dwReserved));
+
+ return S_OK;
+}
+
diff --git a/private/ole32/com/moniker2/classmon.hxx b/private/ole32/com/moniker2/classmon.hxx
new file mode 100644
index 000000000..ff4b45e9b
--- /dev/null
+++ b/private/ole32/com/moniker2/classmon.hxx
@@ -0,0 +1,182 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1996.
+//
+// File: classmon.hxx
+//
+// Contents: Class moniker implementation.
+//
+// Classes: CClassMoniker
+//
+// Functions: FindClassMoniker - Parses a class moniker display name.
+//
+// History: 22-Feb-96 ShannonC Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI FindClassMoniker(LPBC pbc,
+ LPCWSTR pszDisplayName,
+ ULONG *pcchEaten,
+ LPMONIKER *ppmk);
+
+
+struct ClassMonikerData {
+ CLSID clsid;
+ ULONG cbExtra;
+};
+
+class CClassMoniker : public IMoniker, public IROTData, public IMarshal
+{
+private:
+ LONG _cRefs;
+ ClassMonikerData _data;
+ void * _pExtra;
+
+public:
+ CClassMoniker(REFCLSID rclsid);
+
+ HRESULT SetParameters(
+ LPCWSTR pszParameters);
+
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface)(
+ REFIID riid,
+ void ** ppv);
+
+ STDMETHOD_(ULONG,AddRef) ();
+
+ STDMETHOD_(ULONG,Release) ();
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID)(
+ CLSID * pClassID);
+
+ // *** IPersistStream methods ***
+ STDMETHOD(IsDirty) ();
+
+ STDMETHOD(Load)(
+ IStream * pStream);
+
+ STDMETHOD(Save) (
+ IStream * pStream,
+ BOOL fClearDirty);
+
+ STDMETHOD(GetSizeMax)(
+ ULARGE_INTEGER * pcbSize);
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) (
+ IBindCtx *pbc,
+ IMoniker *pmkToLeft,
+ REFIID iidResult,
+ void ** ppvResult);
+
+ STDMETHOD(BindToStorage) (
+ IBindCtx *pbc,
+ IMoniker *pmkToLeft,
+ REFIID riid,
+ void ** ppv);
+
+ STDMETHOD(Reduce) (
+ IBindCtx * pbc,
+ DWORD dwReduceHowFar,
+ IMoniker ** ppmkToLeft,
+ IMoniker ** ppmkReduced);
+
+ STDMETHOD(ComposeWith) (
+ IMoniker * pmkRight,
+ BOOL fOnlyIfNotGeneric,
+ IMoniker **ppmkComposite);
+
+ STDMETHOD(Enum)(
+ BOOL fForward,
+ IEnumMoniker ** ppenumMoniker);
+
+ STDMETHOD(IsEqual)(
+ IMoniker *pmkOther);
+
+ STDMETHOD(Hash)(
+ DWORD * pdwHash);
+
+ STDMETHOD(IsRunning) (
+ IBindCtx * pbc,
+ IMoniker * pmkToLeft,
+ IMoniker * pmkNewlyRunning);
+
+ STDMETHOD(GetTimeOfLastChange) (
+ IBindCtx * pbc,
+ IMoniker * pmkToLeft,
+ FILETIME * pFileTime);
+
+ STDMETHOD(Inverse)(
+ IMoniker ** ppmk);
+
+ STDMETHOD(CommonPrefixWith) (
+ IMoniker * pmkOther,
+ IMoniker ** ppmkPrefix);
+
+ STDMETHOD(RelativePathTo) (
+ IMoniker * pmkOther,
+ IMoniker ** ppmkRelPath);
+
+ STDMETHOD(GetDisplayName) (
+ IBindCtx * pbc,
+ IMoniker * pmkToLeft,
+ LPWSTR * lplpszDisplayName);
+
+ STDMETHOD(ParseDisplayName) (
+ IBindCtx * pbc,
+ IMoniker * pmkToLeft,
+ LPWSTR lpszDisplayName,
+ ULONG * pchEaten,
+ IMoniker ** ppmkOut);
+
+ STDMETHOD(IsSystemMoniker)(
+ DWORD * pdwType);
+
+ // *** IROTData Methods ***
+ STDMETHOD(GetComparisonData)(
+ byte * pbData,
+ ULONG cbMax,
+ ULONG *pcbData);
+
+ // *** IMarshal methods ***
+ STDMETHOD(GetUnmarshalClass)(
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ CLSID * pClassID);
+
+ STDMETHOD(GetMarshalSizeMax)(
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ DWORD *pSize);
+
+ STDMETHOD(MarshalInterface)(
+ IStream * pStream,
+ REFIID riid,
+ void * pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags);
+
+ STDMETHOD(UnmarshalInterface)(
+ IStream * pStream,
+ REFIID riid,
+ void ** ppv);
+
+ STDMETHOD(ReleaseMarshalData)(
+ IStream * pStream);
+
+ STDMETHOD(DisconnectObject)(
+ DWORD dwReserved);
+
+private:
+ ~CClassMoniker();
+};
diff --git a/private/ole32/com/moniker2/cmarshal.cxx b/private/ole32/com/moniker2/cmarshal.cxx
new file mode 100644
index 000000000..3c7a92be9
--- /dev/null
+++ b/private/ole32/com/moniker2/cmarshal.cxx
@@ -0,0 +1,225 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: cmarshal.cxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Commented
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include "cbasemon.hxx"
+#include "ccompmon.hxx"
+#include "mnk.h"
+
+CMarshalImplPStream::CMarshalImplPStream( LPPERSISTSTREAM pPS )
+{
+ GET_A5();
+ m_pPS = pPS;
+}
+
+
+
+STDMETHODIMP CMarshalImplPStream::QueryInterface (THIS_
+ REFIID riid, LPVOID FAR* ppvObj)
+{
+ M_PROLOG(this);
+ *ppvObj = NULL;
+ VDATEIID (riid);
+ VDATEPTROUT (ppvObj, LPVOID);
+
+ return m_pPS->QueryInterface(riid, ppvObj);
+}
+
+
+
+STDMETHODIMP_(ULONG) CMarshalImplPStream::AddRef (THIS)
+{
+ M_PROLOG(this);
+ return m_pPS->AddRef();
+}
+
+
+
+STDMETHODIMP_(ULONG) CMarshalImplPStream::Release (THIS)
+{
+ M_PROLOG(this);
+ return m_pPS->Release();
+}
+
+
+ // *** IMarshal methods ***
+STDMETHODIMP CMarshalImplPStream::GetUnmarshalClass(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, CLSID FAR* pCid)
+{
+ M_PROLOG(this);
+ VDATEIID (riid);
+ VDATEPTROUT (pCid, CLSID);
+
+ return m_pPS->GetClassID(pCid);
+}
+
+
+
+STDMETHODIMP CMarshalImplPStream::GetMarshalSizeMax (REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, DWORD FAR* pSize)
+{
+ ULARGE_INTEGER ularge_integer;
+
+ M_PROLOG(this);
+ VDATEIID (riid);
+ VDATEPTROUT (pSize, DWORD);
+
+ LPMONIKER pmk;
+
+ HRESULT hres;
+
+ hres = m_pPS->QueryInterface(IID_IMoniker, (LPVOID FAR*)&pmk);
+ if (hres == NOERROR)
+ {
+ CCompositeMoniker *pmkComp = IsCompositeMoniker(pmk);
+ if (pmkComp)
+ {
+ DWORD size ;
+
+ hres = CoGetMarshalSizeMax(pSize, riid, pmkComp->m_pmkLeft,
+ dwDestContext, pvDestContext, mshlflags) ;
+
+ if (hres != NOERROR)
+ {
+ goto errRet ;
+ }
+
+ hres = CoGetMarshalSizeMax(&size, riid, pmkComp->m_pmkRight,
+ dwDestContext, pvDestContext, mshlflags) ;
+
+ if (hres != NOERROR)
+ {
+ goto errRet ;
+ }
+
+ *pSize += size + sizeof(CLSID);
+ goto errRet;
+ }
+ else
+ {
+ hres = m_pPS->GetSizeMax( &ularge_integer );
+ if (hres == NOERROR)
+ *pSize = ularge_integer.LowPart;
+ }
+ }
+ else
+ hres = ResultFromScode(E_FAIL);
+errRet:
+ if (pmk) pmk->Release();
+ return hres;
+}
+
+
+
+STDMETHODIMP CMarshalImplPStream::MarshalInterface (IStream FAR* pStm, REFIID riid,
+ void FAR* pv, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags)
+{
+ M_PROLOG(this);
+ VDATEIFACE (pStm);
+ VDATEIID (riid);
+
+
+ LPMONIKER pmk;
+ CCompositeMoniker FAR* pmkComp;
+ HRESULT hres;
+
+ hres = m_pPS->QueryInterface(IID_IMoniker, (LPVOID FAR*)&pmk);
+ if (hres == NOERROR)
+ {
+ if ((pmkComp = IsCompositeMoniker(pmk)) != NULL)
+ {
+ // special code for the composite moniker case
+ hres = CoMarshalInterface(pStm, riid, pmkComp->m_pmkLeft, dwDestContext,
+ pvDestContext, mshlflags);
+
+ if (hres != NOERROR) goto errRet;
+
+ hres = CoMarshalInterface(pStm, riid, pmkComp->m_pmkRight, dwDestContext,
+ pvDestContext, mshlflags);
+
+ if (hres != NOERROR) goto errRet;
+ }
+ else
+ hres = m_pPS->Save(pStm, FALSE);
+ }
+ else
+ hres = ResultFromScode(E_FAIL);
+errRet:
+ if (pmk) pmk->Release();
+ return hres;
+}
+
+
+
+STDMETHODIMP CMarshalImplPStream::UnmarshalInterface (IStream FAR* pStm,
+ REFIID riid, void FAR* FAR* ppv)
+{
+ M_PROLOG(this);
+ VDATEPTROUT (ppv, LPVOID);
+ *ppv = NULL;
+ VDATEIFACE (pStm);
+ VDATEIID (riid);
+
+ HRESULT hresult;
+ LPMONIKER pmk = NULL;
+ CCompositeMoniker FAR* pmkComp;
+
+ hresult = m_pPS->QueryInterface(IID_IMoniker, (LPVOID FAR*)&pmk);
+ if (hresult == NOERROR)
+ {
+ if ((pmkComp = IsCompositeMoniker(pmk)) != NULL)
+ {
+ // special code for the composite moniker case
+ hresult = CoUnmarshalInterface(pStm, IID_IMoniker,
+ (LPVOID FAR*)&(pmkComp->m_pmkLeft));
+ if (hresult != NOERROR) goto errRet;
+
+ hresult = CoUnmarshalInterface(pStm, IID_IMoniker,
+ (LPVOID FAR*)&(pmkComp->m_pmkRight));
+ if (hresult != NOERROR) goto errRet;
+ }
+ else
+ {
+ hresult = m_pPS->Load(pStm);
+ }
+ }
+ else
+ hresult = ResultFromScode(E_FAIL);
+ if (hresult == NOERROR)
+ {
+ hresult = m_pPS->QueryInterface(riid, ppv);
+ }
+errRet:
+ if (pmk)
+ pmk->Release();
+ return hresult;
+}
+
+
+STDMETHODIMP CMarshalImplPStream::ReleaseMarshalData (IStream FAR* pStm)
+{
+ M_PROLOG(this);
+ return NOERROR;
+}
+
+
+STDMETHODIMP CMarshalImplPStream::DisconnectObject (DWORD dwReserved)
+{
+ M_PROLOG(this);
+ return NOERROR;
+}
diff --git a/private/ole32/com/moniker2/cmarshal.hxx b/private/ole32/com/moniker2/cmarshal.hxx
new file mode 100644
index 000000000..c12937211
--- /dev/null
+++ b/private/ole32/com/moniker2/cmarshal.hxx
@@ -0,0 +1,51 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: cmarshal.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Created
+//
+//----------------------------------------------------------------------------
+
+
+/*
+ * An implementation of the IMarshal interface that uses the
+ * IPersistStream interface to copy the object. Any object that
+ * supports IPersistStream may use this to implement marshalling
+ * by copying, rather than by reference.
+ */
+
+class FAR CMarshalImplPStream : public CPrivAlloc, public IMarshal
+{
+ LPPERSISTSTREAM m_pPS;
+ SET_A5;
+public:
+ CMarshalImplPStream( LPPERSISTSTREAM pPS );
+
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ // *** IMarshal methods ***
+ STDMETHOD(GetUnmarshalClass)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(THIS_ IStream FAR* pStm, REFIID riid,
+ LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(THIS_ IStream FAR* pStm, REFIID riid,
+ LPVOID FAR* ppv);
+ STDMETHOD(ReleaseMarshalData)(THIS_ IStream FAR* pStm);
+ STDMETHOD(DisconnectObject)(THIS_ DWORD dwReserved);
+};
diff --git a/private/ole32/com/moniker2/cmonimp.cxx b/private/ole32/com/moniker2/cmonimp.cxx
new file mode 100644
index 000000000..a5438652a
--- /dev/null
+++ b/private/ole32/com/moniker2/cmonimp.cxx
@@ -0,0 +1,2255 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: cmonimp.cxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Created
+// 16-May-94 AlexT Removed reference variables
+// Added support for '!' in paths
+// 21-Jun-94 KentCe Corrected string dup routine.
+// 11-Nov-94 BruceMa Make use of GetLongPathName more efficient
+// and enable its use for Chicago
+// 20-Jul-95 BruceMa Rewrote MkParseDisplayName
+// Rewrote FindMaximalFileName
+// General cleanup
+// 22-Sep-95 MikeHill Added CreateFileMonikerEx
+// 29-Nov-95 MikeHill Added ValidateBindOpts().
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include <io.h>
+
+#include "cbasemon.hxx"
+#include "citemmon.hxx"
+#include "cfilemon.hxx"
+#include "cantimon.hxx"
+#include "cbindctx.hxx"
+#include "cptrmon.hxx"
+#include "mnk.h"
+#include "rothint.hxx"
+#include "crot.hxx"
+#include "classmon.hxx"
+
+#include <longname.h>
+
+#define IsFileSystemSeparator(ch) ('\\' == (ch) || ':' == (ch))
+#define IsItemMonikerSeparator(ch) ('!' == (ch) || '/' == (ch) || '[' == (ch) || '#' == (ch))
+#define IsDriveLetter(ch) ( ( (ch) >= L'A' && (ch) <= L'Z') || ( (ch) >= L'a' && (ch) <= L'z'))
+
+
+#ifdef _CAIRO_
+
+//+---------------------------------------------------------------------------
+//
+// Function: ValidateBindOpts
+//
+// Synopsis: Validates the fields of a BIND_OPTS (or BIND_OPTS2) structure with
+// respect to file monikers.
+//
+// Effects: Outputs a debugger message if an invalid condition is found.
+//
+// Arguments: [pbind_opts] -- Pointer to a BIND_OPTS or BIND_OPTS2 structure.
+//
+// Requires: None.
+//
+// Returns: TRUE if valid. FALSE otherwise.
+//
+// Signals: None.
+//
+// Modifies: None.
+//
+// Algorithm: Verify that bits set in dwTrackFlags are defined.
+//
+// History: 11-29-95 MikeHill Created.
+//
+// Notes: This routine can process either BIND_OPTS or BIND_OPTS2 structures,
+// but the latter must be cast as an LPBIND_OPTS.
+//
+//----------------------------------------------------------------------------
+
+BOOL ValidateBindOpts( const LPBIND_OPTS pbind_opts )
+{
+ Assert( pbind_opts != NULL );
+
+ // Validate fields that only exist in BIND_OPTS2.
+
+ if( pbind_opts->cbStruct >= sizeof( BIND_OPTS2 ))
+ {
+ const LPBIND_OPTS2 &pbind_opts2 = (const LPBIND_OPTS2) pbind_opts;
+
+ // Verify the TRACK_FLAGS.
+
+ if( pbind_opts2->dwTrackFlags & ~TRACK_FLAGS_MASK )
+ {
+ mnkDebugOut(( DEB_ITRACE,
+ "ValidateBindOpts: Invalid TRACK_FLAGS (%x)\n",
+ pbind_opts2->dwTrackFlags ));
+ return( FALSE );
+ }
+ }
+
+ // No error conditions were found, so we'll declare this a valid Bind Opts.
+
+ return( TRUE );
+
+} // ValidateBindOpts
+
+#endif // _CAIRO_
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DupWCHARString
+//
+// Synopsis: Duplicate a WCHAR string
+//
+// Effects:
+// lpwcsOutput is allocated via PrivMemAlloc(), and lpwcsString
+// is copied into it.
+//
+// Arguments: [lpwcsString] -- String to dup
+// [lpwcsOutput] -- Reference to new string pointer
+// [ccOutput] -- Reference to character count in string
+//
+// Requires:
+//
+// Returns:
+// If lpwcsString == NULL, then lpwcsOutput == NULL, and
+// ccOutput == 0.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-16-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT DupWCHARString(LPCWSTR lpwcsString,
+ LPWSTR & lpwcsOutput,
+ USHORT & ccOutput)
+{
+ if (lpwcsString != NULL)
+ {
+ ccOutput = lstrlenW(lpwcsString);
+
+ lpwcsOutput = (WCHAR *)PrivMemAlloc(sizeof(WCHAR)*(1+ccOutput));
+
+ if (lpwcsOutput != NULL)
+ {
+ memcpy(lpwcsOutput, lpwcsString, (ccOutput + 1) * sizeof(WCHAR));
+
+ return(NOERROR);
+ }
+ else
+ {
+ return(E_OUTOFMEMORY);
+ }
+
+ }
+ lpwcsOutput = NULL;
+ ccOutput = 0;
+ return(NOERROR);
+}
+
+
+STDAPI CreateItemMoniker ( LPCWSTR lpszDelim, LPCWSTR lpszItem,
+ LPMONIKER FAR * ppmk )
+{
+ OLETRACEIN((API_CreateItemMoniker, PARAMFMT("lpszDelim= %ws, lpszItem= %ws, ppmk= %p"),
+ lpszDelim, lpszItem, ppmk));
+
+ mnkDebugOut((DEB_ITRACE,
+ "CreateItemMoniker lpszDelim(%ws) lpszItem(%ws)\n",
+ lpszDelim?lpszDelim:L"<NULL>",
+ lpszItem?lpszItem:L"<NULL>"));
+
+ CItemMoniker FAR * pCIM;
+ HRESULT hresult;
+
+ VDATEPTROUT_LABEL(ppmk,LPMONIKER, errRtn, hresult);
+ VDATEPTRIN_LABEL(lpszDelim,WCHAR, errRtn, hresult);
+
+ *ppmk = NULL;
+
+ //VDATEPTRIN rejects NULL
+ if( lpszItem )
+ VDATEPTRIN_LABEL(lpszItem,WCHAR, errRtn, hresult);
+
+ pCIM = CItemMoniker::Create(lpszDelim, lpszItem);
+
+ if (pCIM)
+ {
+ *ppmk = (LPMONIKER)pCIM;
+ CALLHOOKOBJECTCREATE(S_OK,CLSID_ItemMoniker,IID_IMoniker,(IUnknown **)ppmk);
+ hresult = NOERROR;
+ }
+ else
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ }
+
+errRtn:
+ OLETRACEOUT((API_CreateItemMoniker, hresult));
+
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsAbsolutePath
+//
+// Synopsis: Returns true if the path starts with a drive letter, or
+// with a UNC delimiter ('\\')
+//
+// Effects:
+//
+// Arguments: [szPath] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 3-03-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL IsAbsolutePath (LPCWSTR szPath)
+{
+ if (NULL==szPath || *szPath == '\0')
+ {
+ return FALSE;
+ }
+
+ if (*szPath == '\\')
+ {
+ // return TRUE if UNC path
+ return (szPath[1] == '\\');
+ }
+
+ //
+ // If the second character is a ':', then
+ // it could very well be a drive letter and a ':'
+ //
+ // We could test for valid drive letters, but we don't have a really
+ // compelling reason to do so. It will either work or fail later
+ //
+ return (szPath[1] == ':');
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsAbsoluteNonUNCPath
+//
+// Synopsis: Returns true if the path is an absolute, non UNC path
+//
+// Effects:
+//
+// Arguments: [szPath] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 3-03-94 kevinro Created
+// 04-27-94 darryla changed to return FALSE if first char
+// a \ since either relative or UNC
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL IsAbsoluteNonUNCPath (LPCWSTR szPath)
+{
+ if (NULL==szPath || *szPath == '\0')
+ {
+ return FALSE;
+ }
+
+ if (*szPath == '\\')
+ {
+ // return FALSE since it is either a UNC path or a relative
+ // path like \foo
+ return FALSE;
+ }
+
+ //
+ // If the second character is a ':', then
+ // it could very well be a drive letter and a ':'
+ //
+ // We could test for valid drive letters, but we don't have a really
+ // compelling reason to do so. It will either work or fail later
+ //
+
+ return (szPath[1] == ':');
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: FindUNCEndServer
+//
+// Synopsis: Finds the end of the server section of a UNC path
+//
+// Effects:
+//
+// Arguments: [lpszPathName] -- Path to search for UNC prefix
+// [endServer] -- Returned offset to end of UNC name
+//
+// Requires:
+//
+// Returns:
+// If the path is a UNC name, then endServer will point to the first
+// character of the 'path' section.
+//
+// For example, \\server\share\path would return with endServer = 14
+// or \\server\share would also return with endServer = 14.
+//
+// If the path isn't of this form, endServer == DEF_ENDSERVER on return.
+// Also, we need to make sure that if the form is ill-formed, we
+// mislead later steps into thinking this is a real UNC name. For
+// example, \\server\ is ill-formed and would later be treated as a
+// real UNC name.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-11-94 kevinro Created
+// 03-27-94 darryla Changed to catch \\server\share legal
+// form and illegal \\server\.
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void FindUNCEndServer(LPCWSTR lpszPathName, USHORT *pendServer)
+{
+ if (lpszPathName[0] == '\\' && lpszPathName[1] == '\\')
+ {
+ //
+ // Need to find the second slash following the UNC delimiter
+ //
+ ULONG ulCountDown = 2;
+
+ //
+ // Found UNC prefix. Now find the second backslash
+ //
+ for(*pendServer = 2 ; lpszPathName[*pendServer] != 0 ; (*pendServer)++)
+ {
+ if (lpszPathName[*pendServer] == '\\')
+ {
+ if( --ulCountDown == 0)
+ {
+ return;
+ }
+ }
+ }
+
+ // If we reached the end of the string and found one \, then we
+ // have the form \\server\share and the *pendServer is the terminator
+ // as long as we aren't looking at \\server\.
+ if(lpszPathName[*pendServer] == '\0' &&
+ ulCountDown == 1 &&
+ lpszPathName[*pendServer - 1] != '\\')
+ {
+ return;
+ }
+ }
+
+ *pendServer = DEF_ENDSERVER;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ExpandUNCName
+//
+// Synopsis: Given a path, determine a UNC share to it
+//
+// Effects:
+//
+// Arguments: [lpszIn] -- Path to determine UNC name of
+// [lplpszOut] -- Output UNC name, allocated using new
+// [pEndServer] -- Output USHORT offset to start of actual path
+//
+// Requires:
+// lpszIn should be of the form 'A:\<path>'
+//
+// Returns:
+//
+// lplpszOut can return as NULL if there was no UNC path available. In
+// this case, the caller should just use the normal string
+//
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-11-94 kevinro Created
+// 05-25-94 AlexT Use WNetGetUniversalName for non-Chicago
+// 06-15-94 AlexT Only call WNetGetUniversalName for remote
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+#ifdef _CAIRO_
+
+// We need to pass a buffer to WNetGetUniversalName which will get filled in
+// with a UNIVERSAL_NAME_INFOW structure plus a universal path which
+// can be up to MAX_PATH long.
+
+#define UNIVERSAL_NAME_BUFFER_SIZE (sizeof(UNIVERSAL_NAME_INFOW) + \
+ MAX_PATH * sizeof(WCHAR) )
+
+#else
+
+// We need to pass a buffer to WNetGetUniversalName which will get filled in
+// with a REMOTE_NAME_INFO structure add three strings - a universal path
+// (can be up to MAX_PATH long) and a remote connection and remaing path
+// (these last two will be at most MAX_PATH + 1 characters).
+
+
+#define REMOTE_NAME_BUFFER_SIZE (sizeof(REMOTE_NAME_INFO) + \
+ MAX_PATH * sizeof(WCHAR) + \
+ (MAX_PATH + 1) * sizeof(WCHAR))
+#endif
+
+INTERNAL ExpandUNCName ( LPWSTR lpszIn, LPWSTR FAR * lplpszOut, USHORT FAR* pEndServer )
+{
+ mnkDebugOut((DEB_ITRACE,
+ "%p _IN ExpandUNCName (%ws, %p, %p)\n",
+ NULL, lpszIn, lplpszOut, pEndServer));
+
+ WCHAR szDevice[] = L"A:\\";
+ ULONG ulDriveType;
+
+ *pEndServer = DEF_ENDSERVER;
+
+ *szDevice = *lpszIn;
+ Assert(lpszIn[1] == ':');
+ ulDriveType = GetDriveType(szDevice);
+
+ mnkDebugOut((DEB_ITRACE,
+ "ExpandUNCName: GetDriveType(%ws) says %s (%x)\n",
+ szDevice,
+ ulDriveType==DRIVE_REMOTE?"DRIVE_REMOTE":"not remote",
+ ulDriveType));
+
+#ifdef _CHICAGO_
+ //
+ // Note: szRemoteName doesn't really need to be this big. Need to
+ // findout what the largest \\server\share combination is allowed, and
+ // use that as the size.
+ //
+
+ WCHAR szRemoteName[MAX_PATH];
+ DWORD cbRemoteName = MAX_PATH;
+ HRESULT hr = NOERROR;
+
+ int lenRemoteName;
+ int lenIn;
+
+ //
+ // If this is a remote drive, attempt to get the UNC path that maps
+ // to it.
+ //
+
+ //
+ // The device name needs to be A:, not a root like the other API wanted.
+ //
+ szDevice[2] = 0;
+
+ if (ulDriveType == DRIVE_REMOTE &&
+ (WN_SUCCESS == (hr = OleWNetGetConnection(szDevice, szRemoteName,&cbRemoteName))))
+ {
+ //
+ // Allocate a buffer large enough to hold the UNC server and share,
+ // plus the size of the path
+ //
+ //
+
+ lenRemoteName = lstrlenW(szRemoteName);
+ lenIn = lstrlenW(lpszIn);
+
+ //
+ // Make sure we aren't about to create a path that is too large.
+ //
+
+ //
+ // (lenIn - 2) removes the space required by the drive and the
+ // colon, which are not going to be copied
+ //
+ if ((lenRemoteName + lenIn - 2) > MAX_PATH)
+ {
+ hr = MK_E_SYNTAX;
+ goto errRet;
+ }
+
+ //
+ // Allocate room for the concatenated string. The length of the
+ // buffer is the length of the remote name, plus the length of the
+ // input string. Subtract from that the drive + colon (2 WCHARS),
+ // then add back room for a terminating NULL. This is where
+ // (lenIn - 1) is derived
+ //
+ *lplpszOut = (WCHAR *)
+ PrivMemAlloc(sizeof(WCHAR) * (lenRemoteName + (lenIn - 1)));
+
+ if( !*lplpszOut )
+ {
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ goto errRet;
+ }
+
+ memcpy( *lplpszOut, szRemoteName, lenRemoteName * sizeof(WCHAR));
+
+ //
+ // We know that the lpszIn is of the form A:\path and we want to end
+ // up with \\server\share\path. Skipping the first two characters of
+ // lpszIn should suffice. Copying (lenIn - 1) characters makes us
+ // copy over the NULL character from lpszIn
+ //
+ memcpy( *lplpszOut + lenRemoteName, lpszIn + 2, (lenIn - 1) * sizeof(WCHAR));
+
+ //
+ // EndServer is the offset to the start of the 'path'. It should point at the
+ // first backslash
+ //
+
+ *pEndServer = lenRemoteName;
+ }
+ else
+ {
+ //
+ // Its possible that WNetGetConnection failed. In this case, we
+ // can only use the path that we were given.
+ //
+
+ if (ulDriveType == DRIVE_REMOTE)
+ {
+ mnkDebugOut((DEB_IERROR,
+ "ExpandUNCName: WNetGetConnection(%ws) failed (%x)\n",
+ szDevice,
+ hr));
+ }
+
+ //
+ // There was no UNC form of this path. Set the output pointer to be
+ // NULL
+ //
+
+ // NOTE:
+ //
+ // This would be a very good place to determine if the given path
+ // has a UNC equivalent, even if it is a local drive.
+ //
+
+ *lplpszOut = NULL;
+ *pEndServer = DEF_ENDSERVER;
+ }
+errRet:
+
+#else
+
+ //
+ // If this is a remote drive, attempt to get the UNC path that maps
+ // to it.
+ //
+
+
+ HRESULT hr = NOERROR;
+
+# ifdef _CAIRO_
+ // BUGBUG: [mikese] This is the correct thing to do -- use the universal path the
+ // provider gives back to us. The Daytona code is broken.
+
+ BYTE abInfoBuffer[UNIVERSAL_NAME_BUFFER_SIZE];
+ DWORD dwBufferSize = UNIVERSAL_NAME_BUFFER_SIZE;
+
+ if ((DRIVE_REMOTE == ulDriveType) &&
+ (WN_SUCCESS == OleWNetGetUniversalName(lpszIn, UNIVERSAL_NAME_INFO_LEVEL,
+ abInfoBuffer, &dwBufferSize)))
+ {
+ UNIVERSAL_NAME_INFOW * pUniversalInfo = (UNIVERSAL_NAME_INFOW*)abInfoBuffer;
+
+ int cchPath = lstrlenW ( pUniversalInfo->lpUniversalName );
+
+ // Allocate space to copy the path, including the terminating null
+ *lplpszOut = (WCHAR *) PrivMemAlloc(sizeof(WCHAR) * (cchPath + 1));
+
+ if( *lplpszOut == NULL )
+ {
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ goto errRet;
+ }
+
+ memcpy(*lplpszOut, pUniversalInfo->lpUniversalName,
+ (cchPath + 1) * sizeof(WCHAR));
+
+ FindUNCEndServer ( *lplpszOut, pEndServer );
+ }
+
+# else
+
+ // Daytona. This isn't really correct.
+
+ BYTE abInfoBuffer[REMOTE_NAME_BUFFER_SIZE];
+ LPREMOTE_NAME_INFO pRemoteNameInfo;
+ DWORD dwBufferSize;
+ int cchConnectionName;
+ int cchRemainingPath;
+
+ //
+ // If this is a remote drive, attempt to get the UNC path that maps
+ // to it.
+ //
+
+ pRemoteNameInfo = (LPREMOTE_NAME_INFO) abInfoBuffer;
+ dwBufferSize = REMOTE_NAME_BUFFER_SIZE;
+
+ if ((DRIVE_REMOTE == ulDriveType) &&
+ (WN_SUCCESS == OleWNetGetUniversalName(lpszIn, REMOTE_NAME_INFO_LEVEL,
+ pRemoteNameInfo, &dwBufferSize)))
+ {
+ // Got it
+ cchConnectionName = lstrlenW(pRemoteNameInfo->lpConnectionName);
+ cchRemainingPath = lstrlenW(pRemoteNameInfo->lpRemainingPath);
+
+ //
+ // Make sure we aren't about to create a path that is too large.
+ //
+
+ if ((cchConnectionName + cchRemainingPath + 1) > MAX_PATH)
+ {
+ hr = MK_E_SYNTAX;
+ goto errRet;
+ }
+
+ // Allocate room for the concatenated string. The length of the
+ // buffer is the length of the remote name, plus the length of the
+ // remaining path, plus room for a terminating NULL.
+
+ *lplpszOut = (WCHAR *)
+ PrivMemAlloc(sizeof(WCHAR) * (cchConnectionName + cchRemainingPath + 1));
+
+ if( !*lplpszOut )
+ {
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ goto errRet;
+ }
+
+ memcpy(*lplpszOut, pRemoteNameInfo->lpConnectionName,
+ cchConnectionName * sizeof(WCHAR));
+ memcpy(*lplpszOut + cchConnectionName, pRemoteNameInfo->lpRemainingPath,
+ (cchRemainingPath + 1) * sizeof(WCHAR));
+
+ //
+ // EndServer is the offset to the start of the 'path'. It should point at the
+ // first backslash
+ //
+
+ *pEndServer = cchConnectionName;
+ }
+#endif
+ else
+ {
+#if DBG==1
+ if (DRIVE_REMOTE == ulDriveType)
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "Local drive or WNetGetUniversalName failed - %ld\n",
+ GetLastError()));
+ }
+#endif
+
+ //
+ // There was no UNC form of this path. Set the output pointer to be
+ // NULL
+ //
+
+ // NOTE:
+ //
+ // This would be a very good place to determine if the given path
+ // has a UNC equivalent, even if it is a local drive.
+ //
+
+ *lplpszOut = NULL;
+ *pEndServer = DEF_ENDSERVER;
+ }
+errRet:
+
+#endif // !_CHICAGO_
+ mnkDebugOut((DEB_ITRACE,
+ "%p OUT ExpandUNCName (%lx) [%ws, %d]\n",
+ NULL, hr, *lplpszOut ? *lplpszOut : L"<NULL>",
+ *pEndServer));
+ return hr;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateFileMoniker
+//
+// Synopsis: Creates a FileMoniker
+//
+// Effects:
+//
+// Arguments: [lpszPathName] -- Path to create moniker to
+// [ppmk] -- Output moniker interface pointer
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-11-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CreateFileMoniker ( LPCWSTR lpszPathName, LPMONIKER FAR * ppmk )
+{
+ OLETRACEIN((API_CreateFileMoniker, PARAMFMT("lpszPathName= %ws, ppmk= %p"),
+ lpszPathName, ppmk));
+
+ mnkDebugOut((DEB_TRACE,
+ "CreateFileMoniker(%ws)\n",
+ lpszPathName?lpszPathName:L"<NULL PATH>"));
+
+ HRESULT hresult = NOERROR;
+ CFileMoniker FAR * pCFM = NULL;
+
+ USHORT endServer = DEF_ENDSERVER;
+ *ppmk = NULL;
+ LPWSTR lpsz = NULL;
+ WCHAR szBuffer[MAX_PATH+1];
+ LPOLESTR posPath;
+
+ if (NULL == lpszPathName)
+ {
+ return MK_E_SYNTAX;
+ }
+
+ VDATEPTROUT_LABEL(ppmk,LPMONIKER, errNoHookRet, hresult);
+ VDATEPTRIN_LABEL(lpszPathName,WCHAR, errNoHookRet, hresult);
+
+
+ //
+ // If this is an absolute path, then create as strong of a link to it
+ // that we can. If not, then its relative, just use the name.
+ //
+
+ // BUGBUG - IsAbsoluteNonUNCPath will return TRUE for relative
+ // paths like a:foo. Is this a bug or is the function poorly named?
+
+ if ( IsAbsoluteNonUNCPath(lpszPathName))
+ {
+ mnkDebugOut((DEB_ITRACE,
+ "CreateFileMoniker(%ws) Is absolute path\n",
+ lpszPathName?lpszPathName:L"<NULL PATH>"));
+
+ szBuffer[MAX_PATH] = 0;
+
+ //
+ // GetFullPathName resolves, using the current directory and drive,
+ // the path into as much of a normal form as possible
+ //
+
+ LPWSTR pszFilePart;
+ if (!GetFullPathName(lpszPathName, MAX_PATH, szBuffer, &pszFilePart))
+ {
+ hresult = ResultFromScode(MK_E_SYNTAX);
+ goto errRet;
+ }
+
+ //
+ // We now demand to have a drive based path.
+ //
+
+ if (*(szBuffer + 1) != ':')
+ {
+ hresult = ResultFromScode(MK_E_SYNTAX);
+ goto errRet;
+ }
+
+ Assert(*(szBuffer + 1) == ':');
+
+ hresult = ExpandUNCName( szBuffer, &lpsz, &endServer);
+
+
+ mnkDebugOut((DEB_ITRACE,
+ "CreateFileMoniker(%ws) Expanded name (%ws)\n",
+ lpszPathName?lpszPathName:L"<NULL PATH>",
+ lpsz?lpsz:szBuffer));
+
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+
+ posPath = lpsz ? lpsz : szBuffer;
+ }
+ else
+ {
+ //
+ // If this is a UNC path, then we need to set the
+ // m_endServer variable. Otherwise, it defaults to DEF_ENDSERVER
+ //
+ mnkDebugOut((DEB_ITRACE,
+ "CreateFileMoniker(%ws) Is relative path\n",
+ lpszPathName?lpszPathName:L"<NULL PATH>"));
+
+
+ FindUNCEndServer(lpszPathName, &endServer);
+ posPath = (LPOLESTR)lpszPathName;
+ }
+
+
+ // Now that we have a path, expand each component into its long
+ // form so that monikers create with short names equal their
+ // long name equivalents
+ // This only works for files that exist, so if it fails
+ // simply use the given path
+
+ DWORD cchLong, cchDone;
+ LPOLESTR posLong;
+ WCHAR wcsTmp[MAX_PATH];
+
+ posLong = NULL;
+
+ // Special case zero-length paths since the length returns from
+ // GetLongPathName become ambiguous when zero characters are processed
+ if (posPath[0])
+ {
+ // Attempt to build the long path on the stack
+ cchLong = GetLongPathNameW(posPath, wcsTmp, MAX_PATH);
+
+ // Check for failure
+ if (cchLong > 0)
+ {
+ // Check if stack array was large enough
+ if (cchLong < MAX_PATH)
+ {
+ posPath = wcsTmp;
+ mnkDebugOut((DEB_ITRACE, "CreateFileMoniker: "
+ "Lengthened '%ws' to '%ws'\n",
+ posPath, wcsTmp));
+ }
+
+ // Need to use a larger buffer
+ else
+ {
+ posLong = (LPOLESTR)PrivMemAlloc(cchLong*sizeof(WCHAR));
+ if (posLong == NULL)
+ {
+ goto ErrNoLongMem;
+ }
+ cchDone = GetLongPathNameW(posPath, posLong, cchLong);
+ Win4Assert(cchDone != 0 &&
+ "GetLongPathNameW shouldn't fail");
+ mnkDebugOut((DEB_ITRACE, "CreateFileMoniker: "
+ "Lengthened '%ws' to '%ws'\n",
+ posPath, posLong));
+ posPath = posLong;
+ }
+ }
+ }
+ else
+ {
+ mnkDebugOut((DEB_ITRACE, "CreateFileMoniker: No long path for '%ws'\n",
+ posPath));
+ }
+
+ pCFM = CFileMoniker::Create(posPath,
+ 0,
+ endServer);
+
+ if (posLong != NULL)
+ {
+ PrivMemFree(posLong);
+ }
+
+ ErrNoLongMem:
+
+ if (lpsz != NULL)
+ {
+ PrivMemFree(lpsz);
+ }
+
+ if (!pCFM)
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRet;
+ }
+
+ *ppmk = (LPMONIKER)pCFM;
+
+errRet:
+
+ CALLHOOKOBJECTCREATE(hresult, CLSID_FileMoniker, IID_IMoniker, (IUnknown **)ppmk); // HOOKOLE
+
+errNoHookRet:
+ OLETRACEOUT((API_CreateFileMoniker, hresult));
+
+ return hresult;
+}
+
+
+
+
+
+#ifdef _CAIRO_
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateFileMonikerEx
+//
+// Synopsis: Creates a tracking FileMoniker.
+//
+// Effects:
+//
+// Arguments: [DWORD] dwTrackFlags
+// -- Tracking flags ("TRACK_*").
+// [LPCWSTR] lpszPathName
+// -- Path to which to create the moniker.
+// [LPMONIKER FAR *] pmk
+// -- Output moniker interface pointer.
+//
+// Requires:
+//
+// Returns: [HRESULT]
+//
+// Signals: None.
+//
+// Modifies: None.
+//
+// Algorithm: Create a FileMoniker, and initializes the tracking
+// state.
+//
+// History: 9-20-95 MikeHill Created
+//
+// Notes: This function was added to extend the CreateFileMoniker
+// API for the newer tracking file monikers. This allows
+// the caller to configure the tracking algorithm (with the
+// dwTrackFlags) at creation time.
+//
+//----------------------------------------------------------------------------
+
+STDAPI CreateFileMonikerEx (DWORD dwTrackFlags,
+ LPCWSTR lpszPathName,
+ LPMONIKER FAR * ppmk )
+{
+
+ OLETRACEIN((API_CreateFileMoniker, PARAMFMT("lpszPathName= %ws, ppmk= %p"),
+ lpszPathName, ppmk));
+
+
+ mnkDebugOut( (DEB_TRACE,
+ "CreateFileMonikerEx(%ws)\n",
+ lpszPathName?lpszPathName:L"<NULL PATH>"));
+
+
+ HRESULT hresult = E_FAIL;
+
+ VDATEPTROUT_LABEL(ppmk,LPMONIKER, errNoHookRet, hresult);
+ VDATEPTRIN_LABEL(lpszPathName,WCHAR, errNoHookRet, hresult);
+
+ *ppmk = NULL;
+
+
+ // Create a default (i.e. non-tracking) File Moniker.
+
+ if( FAILED( hresult = CreateFileMoniker( lpszPathName,
+ ppmk ))
+ )
+ {
+ goto errRet;
+ }
+ Assert( *ppmk != NULL );
+
+ // Perform the tracking-related initialization of this moniker.
+ // Note that the Track Flags are piggy-backed onto the
+ // EnableTracking routine's OT flags.
+
+ hresult = ( (CFileMoniker *) *ppmk)->EnableTracking( NULL,
+ TRACK_2_OT_FLAGS( dwTrackFlags )
+ |
+ OT_MAKETRACKING
+ );
+
+ if( FAILED( hresult ))
+ {
+ goto errRet;
+ }
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ // Return S_OK unless there was an error. (Word considers everything
+ // except S_OK to be fatal).
+
+ hresult = SUCCEEDED( hresult ) ? S_OK : hresult;
+
+ CALLHOOKOBJECTCREATE(hresult, CLSID_FileMoniker, IID_IMoniker, (IUnknown **)ppmk); // HOOKOLE
+
+errNoHookRet:
+ OLETRACEOUT((API_CreateFileMoniker, hresult));
+
+ return hresult;
+
+} // CreateFileMonikerEx
+
+#endif // _CAIRO_
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateOle1FileMoniker
+//
+// Synopsis: Creates a FileMoniker
+//
+// Effects:
+//
+// Arguments: [lpszPathName] - Path to create moniker to
+// [rclsidOle1] - Ole1 clsid
+// [ppmk] - Output moniker interface pointer
+//
+// Returns: HRESULT
+//
+//
+// Algorithm:
+//
+// History: 01-Aug-95 BruceMa Added this header
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT
+STDAPICALLTYPE
+CreateOle1FileMoniker ( LPWSTR lpszPathName,
+ REFCLSID rclsidOle1,
+ LPMONIKER FAR * ppmk)
+{
+ CFileMoniker FAR * pCFM;
+ HRESULT hr;
+
+ hr = CreateFileMoniker( lpszPathName, (LPMONIKER FAR *)&pCFM);
+
+ *ppmk = pCFM; // this nulls *ppmk in case of error
+
+ if (hr == NOERROR)
+ {
+ pCFM->m_ole1 = CFileMoniker::ole1;
+ pCFM->m_clsid = rclsidOle1;
+ pCFM->m_fClassVerified = TRUE;
+
+ }
+
+ return hr;
+}
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateAntiMoniker
+//
+// Synopsis: Creates a anti moniker
+//
+// Effects:
+//
+// Arguments: [ppmk] - Path to create moniker to
+//
+// Returns: HRESULT
+//
+//
+// Algorithm:
+//
+// History: 01-Aug-95 BruceMa Added this header
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CreateAntiMoniker (LPMONIKER FAR* ppmk)
+{
+ CAntiMoniker FAR* pCAM;
+ HRESULT hr;
+
+ OLETRACEIN((API_CreateAntiMoniker, PARAMFMT("ppmk= %p"), ppmk));
+
+ VDATEPTROUT_LABEL(ppmk, LPMONIKER, errRtn, hr);
+
+ *ppmk = NULL;
+ pCAM = CAntiMoniker::Create();
+
+ if (pCAM != NULL)
+ {
+ *ppmk = pCAM;
+ CALLHOOKOBJECTCREATE(S_OK,CLSID_AntiMoniker,IID_IMoniker,(IUnknown **)ppmk);
+ hr = NOERROR;
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+errRtn:
+ OLETRACEOUT((API_CreateAntiMoniker, hr));
+
+ return hr;
+}
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateBindCtx
+//
+// Synopsis: Creates a bind context
+//
+// Effects:
+//
+// Arguments: [reserved] - Reserved for future expansion
+// [ppbc] - Where to place the created bnind context
+//
+// Returns: HRESULT
+//
+//
+// Algorithm:
+//
+// History: 01-Aug-95 BruceMa Added this header
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CreateBindCtx ( DWORD reserved, LPBC FAR * ppbc )
+{
+ HRESULT hr;
+
+ OLETRACEIN((API_CreateBindCtx, PARAMFMT("reserved= %x, ppbc= %p"), reserved, ppbc));
+
+ VDATEPTROUT_LABEL(ppbc, LPBC, errRtn, hr);
+
+ if(reserved != 0)
+ {
+ return E_INVALIDARG;
+ }
+
+ *ppbc = CBindCtx::Create();
+
+ if (*ppbc == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ CALLHOOKOBJECTCREATE(S_OK,CLSID_PSBindCtx,IID_IBindCtx,(IUnknown **)ppbc);
+ hr = NOERROR;
+
+errRtn:
+ OLETRACEOUT((API_CreateBindCtx, hr));
+
+ return hr;
+}
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreatePointerMoniker
+//
+// Synopsis: Creates a pointer moniker
+//
+// Effects:
+//
+// Arguments: [punk] - Pointer being wrappaed
+// [ppmk] - Output moniker interface pointer
+//
+// Returns: HRESULT
+//
+//
+// Algorithm:
+//
+// History: 01-Aug-95 BruceMa Added this header
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CreatePointerMoniker (LPUNKNOWN punk, LPMONIKER FAR* ppmk)
+{
+ OLETRACEIN((API_CreatePointerMoniker, PARAMFMT("punk= %p, ppmk= %p"),
+ punk, ppmk));
+
+ HRESULT hresult;
+ CPointerMoniker FAR* pCPM;
+
+ VDATEPTROUT_LABEL(ppmk, LPMONIKER, errRtn, hresult);
+ *ppmk = NULL;
+
+ // When unmarshaling a remoted pointer moniker punk is initially NULL
+ if (punk)
+ {
+ VDATEIFACE_LABEL(punk, errRtn, hresult);
+ }
+
+ pCPM = CPointerMoniker::Create(punk);
+ if (pCPM)
+ {
+ *ppmk = pCPM;
+ CALLHOOKOBJECTCREATE(S_OK,CLSID_PointerMoniker,IID_IMoniker,(IUnknown **)ppmk);
+ hresult = NOERROR;
+ }
+ else
+ {
+ hresult = E_OUTOFMEMORY;
+ }
+
+errRtn:
+ OLETRACEOUT((API_CreatePointerMoniker, hresult));
+
+ return hresult;
+}
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleLoadFromStream
+//
+// Synopsis: Load a moniker from a stream and QI for the
+// requested interface
+//
+// Effects:
+//
+// Arguments: [pStm] - The stream to load from
+// [iidInterface] - The requested interface
+// [ppvObj] - Output moniker interface pointer
+//
+// Returns: HRESULT
+//
+//
+// Algorithm:
+//
+// History: 01-Aug-95 BruceMa Added this header
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleLoadFromStream ( LPSTREAM pStm, REFIID iidInterface,
+ LPVOID FAR* ppvObj)
+{
+ OLETRACEIN((API_OleLoadFromStream, PARAMFMT("pStm= %p, iidInterface= %I"),
+ pStm, &iidInterface));
+
+ // Assumptions: The name of the object class is in the stream,
+ // as a length-prefixed string.
+ HRESULT hresult = NOERROR;
+ CLSID cid;
+ LPPERSISTSTREAM pPS;
+ LPUNKNOWN pUnk;
+
+ VDATEPTROUT_LABEL(ppvObj,LPVOID, errRtn, hresult);
+ *ppvObj = NULL;
+ VDATEIID_LABEL(iidInterface, errRtn, hresult);
+ VDATEIFACE_LABEL(pStm, errRtn, hresult);
+
+
+ if ((hresult = ReadClassStm(pStm, &cid)) != NOERROR)
+ goto errRtn;
+
+ hresult = CoCreateInstance(cid, NULL,
+#ifdef WX86OLE
+ gcwx86.IsWx86Enabled() ? CLSCTX_SERVER | CLSCTX_INPROC_SERVERX86 :
+ CLSCTX_SERVER,
+#else
+ CLSCTX_SERVER,
+#endif
+ iidInterface,
+ (LPVOID FAR *) &pUnk);
+ if (hresult)
+ goto errRtn;
+ hresult = pUnk->QueryInterface(IID_IPersistStream,
+ (LPVOID FAR*) &pPS);
+ if (!hresult)
+ {
+ hresult = pPS->Load( pStm );
+ pPS->Release();
+ }
+ if (!hresult)
+ hresult = pUnk->QueryInterface(iidInterface, ppvObj );
+ pUnk->Release();
+
+errRtn:
+ OLETRACEOUT((API_OleLoadFromStream, hresult));
+
+ return hresult;
+}
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleSaveToStream
+//
+// Synopsis: Given an IPersistStream on a moniker, save that moniker
+// to a stream
+//
+// Effects:
+//
+// Arguments: [pPStm] - IPersistStream pointer
+// [pStm] - Stream to save the moniker to
+//
+// Returns: HRESULT
+//
+//
+// Algorithm:
+//
+// History: 01-Aug-95 BruceMa Added this header
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleSaveToStream ( LPPERSISTSTREAM pPStm, LPSTREAM pStm)
+{
+ OLETRACEIN((API_OleSaveToStream, PARAMFMT("pPStm= %p, pStm= %p"),
+ pPStm, pStm));
+
+ HRESULT hresult = 0;
+ CLSID clsid;
+
+ VDATEIFACE_LABEL(pPStm, errRtn, hresult);
+ VDATEIFACE_LABEL(pStm, errRtn, hresult);
+
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IPersistStream,(IUnknown **)&pPStm);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pStm);
+
+
+ if (!pPStm)
+ {
+ hresult = ResultFromScode(OLE_E_BLANK);
+ goto errRtn;
+ }
+
+ if (hresult = pPStm->GetClassID(&clsid))
+ goto errRtn;
+
+ if ((hresult = WriteClassStm(pStm, clsid)) != NOERROR)
+ goto errRtn;
+
+ hresult = pPStm->Save(pStm, TRUE);
+
+errRtn:
+ OLETRACEOUT((API_OleSaveToStream, hresult));
+
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Parse10DisplayName private
+//
+// Synopsis: Parse a ProgId string as an ole 1.0 file moniker
+//
+// Arguments: [pbc] - Bind context
+// [pszDisplayName] - Display name
+// [pcchEaten] - Number of characters eaten
+// [ppmk] - Moniker of running object
+// if successful, otherwise NULL
+//
+// Returns:
+//
+// Algorithm: This routine is being rewritten for performance, hence the
+//
+// History: 20-Jul-95 BruceMa Added this header and cleaned up
+//
+//----------------------------------------------------------------------------
+STDAPI Parse10DisplayName(REFCLSID clsid,
+ LPCWSTR szDisplayName,
+ ULONG *pcchEaten,
+ ULONG cchEatenSoFar,
+ LPMONIKER *ppmk)
+{
+ LPCWSTR pch = szDisplayName;
+ LPMONIKER pmkFile = NULL;
+ LPMONIKER pmkItem = NULL;
+ HRESULT hres = NOERROR;
+ size_t cbFile;
+
+ // Skip past the "file" name, looking for first delimiter character
+ // Note: strtok is not DBCS-friendly.
+ while (*pch && !wcschr (L"!\"'*+,/;<=>?@[]`|" , *pch))
+ {
+ IncLpch(pch);
+ }
+
+ if (*pch)
+ {
+ // We hit a delimiter, so there is an item moniker.
+ CreateItemMoniker (L"!", (LPWSTR)pch+1, &pmkItem);
+
+ // Copy the "file" part
+ LPWSTR szFile = (WCHAR *)
+ PrivMemAlloc(sizeof(WCHAR) * (cbFile = pch - szDisplayName + 1));
+ if (NULL==szFile)
+ {
+ hres = ResultFromScode (E_OUTOFMEMORY);
+ goto errRtn;
+ }
+ _fmemcpy (szFile, szDisplayName, (cbFile - 1) * sizeof(WCHAR));
+ szFile [cbFile - 1] = '\0';
+
+ hres = CreateOle1FileMoniker (szFile, clsid, &pmkFile);
+ PrivMemFree(szFile);
+ if (hres != NOERROR)
+ {
+ goto errRtn;
+ }
+ hres = CreateGenericComposite (pmkFile, pmkItem, ppmk);
+ }
+ else
+ {
+ // no Item moniker, just a file
+ hres = CreateOle1FileMoniker ((LPWSTR)szDisplayName, clsid, ppmk);
+ }
+
+ errRtn:
+ if (pmkFile)
+ {
+ pmkFile->Release();
+ }
+ if (pmkItem)
+ {
+ pmkItem->Release();
+ }
+ *pcchEaten = ((hres==NOERROR) ? lstrlenW (szDisplayName) + cchEatenSoFar : 0);
+ return hres;
+
+}
+//+---------------------------------------------------------------------------
+//
+// Function: FindProgIdMoniker private
+//
+// Synopsis: Interpreting a display name as a ProgID, derive a
+// moniker from it
+//
+// Arguments: [pbc] - Bind context
+// [pszDisplayName] - Display name to parse
+// [pcchEaten] - Number of characters eaten
+// [ppmk] - Moniker of running object
+//
+// Returns: S_OK if successful
+// Another HRESULT otherwise
+//
+// Algorithm: Find largest left-bounded name that corresponds to a
+// valid initial moniker, either of an object currently running
+// and registered in the ROT or of an extant file. Call
+// IParseDisplayName::ParseDisplayName on the right-part of the
+// display name not yet consumed.
+//
+// History: 20-Jul-95 BruceMa Added this header and cleaned up
+//
+//----------------------------------------------------------------------------
+STDAPI FindProgIdMoniker(LPBC pbc,
+ LPCWSTR pszDisplayName,
+ ULONG *pcchEaten,
+ LPMONIKER *ppmk)
+{
+ int cbProgId;
+ LPWSTR sz = NULL;
+ WCHAR const *pch;
+ HRESULT hres;
+ CLSID cid;
+ IParseDisplayName *pPDN;
+
+
+ // Initialize
+ *pcchEaten = 0;
+ *ppmk = NULL;
+
+ // find the prog id
+ pch = pszDisplayName;
+ Assert(*pch == '@');
+ pch++;
+ if (*pch >= '0' && *pch <= '9')
+ {
+ return ResultFromScode(MK_E_SYNTAX);
+ }
+ while ((*pch >= '0' && *pch <= '9') || (*pch >= 'a' && *pch <= 'z') ||
+ (*pch >= 'A' && *pch <= 'Z') || (*pch == '.'))
+ {
+ pch++;
+ }
+ cbProgId = pch - pszDisplayName;
+
+ sz = (WCHAR *) PrivMemAlloc(sizeof(WCHAR) * cbProgId);
+ _fmemcpy(sz, pszDisplayName + 1, (cbProgId - 1) * sizeof(WCHAR));
+ sz[cbProgId - 1] = '\0';
+
+ // prog id string is now in sz
+ hres = CLSIDFromProgID(sz, &cid);
+ if (hres == NOERROR)
+ {
+ if (CoIsOle1Class (cid))
+ {
+ hres = Parse10DisplayName (cid, pch + 1, pcchEaten, cbProgId + 1,
+ ppmk);
+ CairoleAssert(hres!=NOERROR ||
+ *pcchEaten == (ULONG)lstrlenW(pszDisplayName));
+ goto errRet;
+ }
+
+ hres = CoGetClassObject(cid,
+#ifdef WX86OLE
+ gcwx86.IsWx86Enabled() ? CLSCTX_ALL |
+ CLSCTX_INPROC_HANDLERX86 |
+ CLSCTX_INPROC_SERVERX86 :
+ CLSCTX_ALL,
+#else
+ CLSCTX_ALL,
+#endif
+ NULL, IID_IParseDisplayName,
+ (LPVOID *) &pPDN);
+ if (hres != NOERROR)
+ {
+ hres = CoCreateInstance(cid, NULL,
+#ifdef WX86OLE
+ gcwx86.IsWx86Enabled() ?
+ CLSCTX_INPROC_SERVERX86 |
+ CLSCTX_INPROC_HANDLERX86 :
+ CLSCTX_INPROC,
+#else
+ CLSCTX_INPROC,
+#endif
+ IID_IParseDisplayName,
+ (LPVOID *) &pPDN);
+ }
+ }
+
+ if (hres == NOERROR)
+ {
+ // Unfortunately, IParseDisplayName's 2nd parameter is
+ // LPOLESTR instead of LPCOLESTR
+ hres = pPDN->ParseDisplayName(pbc,
+ (LPOLESTR) pszDisplayName,
+ pcchEaten,
+ ppmk);
+ // AssertOutPtrIface(hres, *ppmk);
+
+ pPDN->Release();
+ }
+
+
+errRet:
+
+ if (sz)
+ {
+
+ PrivMemFree(sz);
+ }
+
+ return hres;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: MkParseDisplayName public
+//
+// Synopsis: Attempts to parse the given file moniker "display name" and
+// return the corresponding moniker
+//
+// Arguments: [pbc] - Bind context
+// [pszDisplayName] - Display name to parse
+// [pcchEaten] - Number of characters eaten
+// [ppmk] - Moniker of running object
+//
+// Returns: S_OK if successful
+// Another HRESULT otherwise
+//
+// Algorithm: Find the largest left-bounded name that corresponds to a
+// valid initial moniker, either of an object currently running
+// and registered in the ROT or of an extant file. Then call
+// IParseDisplayName::ParseDisplayName on this moniker
+// inductively with the right-part of the display name not
+// yet consumed, composing the current moniker with the result to
+// form the next moniker in the induction
+//
+// History: 20-Jul-95 BruceMa Rewrote
+// 22-Feb-96 ShannonC Added class moniker support.
+//
+//----------------------------------------------------------------------------
+STDAPI MkParseDisplayName(LPBC pbc,
+ LPCWSTR pwszDisplayName,
+ ULONG *pchEaten,
+ LPMONIKER *ppmk)
+{
+ HRESULT hr = MK_E_SYNTAX;
+ LPCWSTR pszRemainder = pwszDisplayName;
+ ULONG cchEaten = 0;
+ LONG cbUneaten;
+ LPMONIKER pmk;
+ LPMONIKER pmkNext;
+ LPMONIKER pmkTemp;
+
+ // Some simple checks
+ if (pwszDisplayName == NULL || pwszDisplayName[0] == L'\0')
+ {
+ return E_INVALIDARG;
+ }
+
+ OLETRACEIN((API_MkParseDisplayName,
+ PARAMFMT("pbc= %p, pszDisplayName= %ws, pchEaten= %p, ppmk= %p"),
+ pbc, pwszDisplayName, pchEaten, ppmk));
+
+ // Trace
+ mnkDebugOut((DEB_ITRACE, "In MkParseDisplayName \"%ws\"\n",
+ pwszDisplayName));
+
+ // Validate parameters
+ VDATEPTRIN_LABEL(pwszDisplayName, WCHAR, errRet, hr);
+ VDATEIFACE_LABEL(pbc, errRet, hr);
+ VDATEPTROUT_LABEL(pchEaten, ULONG, errRet, hr);
+ VDATEPTROUT_LABEL(ppmk, LPMONIKER, errRet, hr);
+
+ // Call hook ole
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IBindCtx,(IUnknown **)&pbc);
+
+ // Initialize
+ *ppmk = NULL;
+ *pchEaten = 0;
+
+
+ //Find the initial moniker.
+
+ //Parse a class moniker display name.
+ hr = FindClassMoniker(pbc, pwszDisplayName, &cchEaten, &pmk);
+
+ if(FAILED(hr))
+ {
+ //Parse a file moniker display name.
+ hr = FindFileMoniker(pbc, pwszDisplayName, &cchEaten, &pmk);
+ }
+
+ if(FAILED(hr) && (L'@' == pwszDisplayName[0]))
+ {
+ //Parse the leftmost part of the display name as a ProgID.
+ hr = FindProgIdMoniker(pbc, pwszDisplayName, &cchEaten, &pmk);
+ }
+
+
+
+ // Inductively consume the remainder of the display name.
+
+ // Initialize to loop
+ if(SUCCEEDED(hr))
+ {
+ pszRemainder += cchEaten;
+ cbUneaten = lstrlenW(pszRemainder);
+ }
+
+ // While more display name remains, successively pass the remainder to the
+ // current moniker for it to parse
+ while (SUCCEEDED(hr) && cbUneaten > 0)
+ {
+ cchEaten = 0;
+ hr = pmk->ParseDisplayName(pbc,
+ NULL,
+ (LPOLESTR) pszRemainder,
+ &cchEaten,
+ &pmkNext);
+
+ if (SUCCEEDED(hr) && pmkNext != 0)
+ {
+ hr = pmk->ComposeWith(pmkNext, FALSE, &pmkTemp);
+ if(SUCCEEDED(hr))
+ {
+ pmk->Release();
+ pmk = pmkTemp;
+
+ // Update the amount consumed so far
+ pszRemainder += cchEaten;
+ cbUneaten -= cchEaten;
+ }
+ pmkNext->Release();
+ }
+ }
+
+ *ppmk = pmk;
+ *pchEaten = pszRemainder - pwszDisplayName;
+
+errRet:
+ // Trace
+ mnkDebugOut((DEB_ITRACE, "Out MkParseDisplayName: %ws",
+ pwszDisplayName));
+ OLETRACEOUT((API_MkParseDisplayName, hr));
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: BindMoniker public
+//
+// Synopsis: Given a moniker, bind to the object it names and
+// QI for the requested interface.
+//
+// Arguments: [pmk] - The moniker
+// [grfOpt] - RESERVED (0l)
+// [iidResult] - Interface requested
+// [ppvResult] - Where to store interface
+//
+// Returns: S_OK if successful
+// Another HRESULT otherwise
+//
+// Algorithm: Create a bind context and call BindToObject on the moniker
+// within that bind context
+//
+// History: 20-Jul-95 BruceMa Rewrote
+//
+// Note: This is simply a convenience function
+//
+//----------------------------------------------------------------------------
+STDAPI BindMoniker (LPMONIKER pmk,
+ DWORD grfOpt,
+ REFIID iidResult,
+ LPVOID *ppvResult)
+{
+ LPBC pbc = NULL;
+ HRESULT hr;
+
+ OLETRACEIN((API_BindMoniker, PARAMFMT("pmk= %p, grfOpt= %x, iidResult= %I, ppvResult= %p"),
+ pmk, grfOpt, &iidResult, ppvResult));
+
+ // Validate parameters
+ VDATEPTROUT_LABEL(ppvResult,LPVOID, errSafeRtn, hr);
+ *ppvResult = NULL;
+ VDATEIFACE_LABEL(pmk, errSafeRtn, hr);
+ VDATEIID_LABEL(iidResult, errSafeRtn, hr);
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IMoniker,(IUnknown **)&pmk);
+
+ if (grfOpt != 0)
+ {
+ hr = E_INVALIDARG;
+ goto errSafeRtn;
+ }
+
+ // Initialize
+ *ppvResult = NULL;
+
+ // Create a bind context
+ if (FAILED(hr = CreateBindCtx( 0, &pbc)))
+ {
+ goto errRtn;
+ }
+
+ // Bind to the object
+ hr = pmk->BindToObject(pbc, NULL, iidResult, ppvResult);
+
+errRtn:
+ if (pbc)
+ {
+ pbc->Release();
+ }
+
+ // An ole spy hook
+ CALLHOOKOBJECT(hr,CLSID_NULL,iidResult,(IUnknown **)ppvResult);
+
+errSafeRtn:
+ OLETRACEOUT((API_BindMoniker, hr));
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoGetObject public
+//
+// Synopsis: Get the object identified by the display name.
+//
+// Arguments: [pszName] - Supplies the display name of the object.
+// [pBindOptions] - Supplies the bind options. May be NULL.
+// [riid] - Supplies the IID of the requested interface.
+// [ppv] - Returns interface pointer to the object.
+//
+// Returns: S_OK if successful
+// Another HRESULT otherwise
+//
+// Algorithm: Create a bind context, parse the display name, then bind to
+// the object.
+//
+// Note: This is simply a convenience function.
+//
+// History: 22-Feb-96 ShannonC Created
+//
+//----------------------------------------------------------------------------
+STDAPI CoGetObject(
+ LPCWSTR pszName,
+ BIND_OPTS * pBindOptions,
+ REFIID riid,
+ void ** ppv)
+{
+ HRESULT hr;
+ IBindCtx * pbc;
+ IID iid;
+
+ OLETRACEIN((API_CoGetObject,
+ PARAMFMT("%ws, %p, %I, %p"),
+ pszName, pBindOptions, &riid, ppv));
+
+ __try
+ {
+ //Validate parameters.
+ *ppv = 0;
+ iid = riid;
+
+ //Create a bind context.
+ hr = CreateBindCtx(0, &pbc);
+
+ if(SUCCEEDED(hr))
+ {
+ //Set the bind options.
+ if(pBindOptions != 0)
+ {
+ hr = pbc->SetBindOptions(pBindOptions);
+ }
+
+ if(SUCCEEDED(hr))
+ {
+ IMoniker * pmk = 0;
+ ULONG chEaten = 0;
+
+ //Parse the display name.
+ hr = MkParseDisplayName(pbc, pszName, &chEaten, &pmk);
+ if(SUCCEEDED(hr))
+ {
+ //Bind to the object.
+ hr = pmk->BindToObject(pbc, 0, iid, ppv);
+ pmk->Release();
+ }
+ }
+ pbc->Release();
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ CALLHOOKOBJECT(hr, CLSID_NULL, iid, (IUnknown **)ppv);
+ OLETRACEOUT((API_CoGetObject, hr));
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: FindClassID private
+//
+// Synopsis: Parse a display name to get a CLSID.
+//
+// Arguments: [pszDisplayName] - Display name to parse
+// [pcchEaten] - Number of characters eaten
+// [pClassID] - returns the CLSID
+//
+// Returns: S_OK if successful
+// MK_E_SYNTAX
+// E_OUTOFMEMORY
+//
+// History: 22-Feb-96 ShannonC Created
+//
+//----------------------------------------------------------------------------
+STDAPI FindClassID(
+ LPCWSTR pszDisplayName,
+ ULONG * pcchEaten,
+ CLSID * pClassID)
+{
+ HRESULT hr = MK_E_SYNTAX;
+ WCHAR const *pch = pszDisplayName;
+ ULONG cchProgID = 0;
+
+ mnkDebugOut((DEB_ITRACE,
+ "FindClassID(%ws,%x,%x)\n",
+ pszDisplayName, pcchEaten, pClassID));
+
+ *pcchEaten = 0;
+
+ //Check if display name contains ProgID:
+ //or {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}:
+ while (*pch != '\0' && *pch != ':')
+ {
+ pch++;
+ }
+
+ if(':' == *pch)
+ {
+ cchProgID = pch - pszDisplayName;
+ pch++;
+ }
+
+ //cchProgID has the number of characters in the ProgID or CLSID.
+ //pch points to the next character to be parsed.
+ if(cchProgID > 1)
+ {
+ LPWSTR psz;
+
+ //Allocate memory from the stack.
+ //This memory is freed automatically on function return.
+ psz = (WCHAR *) alloca(sizeof(WCHAR) * cchProgID + sizeof(WCHAR));
+
+ if (psz != 0)
+ {
+ //Copy the ProgID string.
+ memcpy(psz, pszDisplayName, cchProgID * sizeof(WCHAR));
+
+ //Add a zero terminator.
+ psz[cchProgID] = '\0';
+
+ //Convert the string to a CLSID. Note that CLSIDFromString will
+ //parse both ProgID strings and {CLSID} strings.
+ hr = CLSIDFromString(psz, pClassID);
+
+ if(SUCCEEDED(hr))
+ {
+ //Calculate the number of characters parsed.
+ *pcchEaten = pch - pszDisplayName;
+ }
+
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: FindClassMoniker private
+//
+// Synopsis: Interpreting a display name as a ProgID, derive a
+// moniker from it.
+//
+// Arguments: [pbc] - Bind context
+// [pszDisplayName] - Display name to parse
+// [pcchEaten] - Number of characters eaten
+// [ppmk] - Moniker of running object
+//
+// Returns: S_OK if successful
+// CLASS_E_CLASSNOTAVAILABLE
+// E_OUTOFMEMORY
+// E_NOINTERFACE
+// MK_E_SYNTAX
+//
+// Algorithm: Parse the first part of the display name to get a CLSID.
+// Use the CLSID to create a class moniker.
+//
+// History: 22-Feb-96 ShannonC Created
+//
+//----------------------------------------------------------------------------
+STDAPI FindClassMoniker(
+ IBindCtx * pbc,
+ LPCWSTR pszDisplayName,
+ ULONG * pcchEaten,
+ IMoniker **ppmk)
+{
+ HRESULT hr;
+ CLSID classID;
+ ULONG cEaten = 0;
+
+ *ppmk = 0;
+ *pcchEaten = 0;
+
+ mnkDebugOut((DEB_ITRACE,
+ "FindClassMoniker(%x,%ws,%x,%x)\n",
+ pbc, pszDisplayName, pcchEaten, ppmk));
+
+ hr = FindClassID(pszDisplayName, &cEaten, &classID);
+
+ if(SUCCEEDED(hr))
+ {
+ IParseDisplayName *pPDN = NULL;
+ DWORD dwClassContext;
+
+#ifdef WX86OLE
+ dwClassContext = gcwx86.IsWx86Enabled() ?
+ CLSCTX_ALL | CLSCTX_INPROC_HANDLERX86 |CLSCTX_INPROC_SERVERX86 :
+ CLSCTX_ALL;
+#else
+ dwClassContext = CLSCTX_ALL;
+#endif
+
+ hr = CoGetClassObject(classID,
+ dwClassContext,
+ NULL,
+ IID_IParseDisplayName,
+ (LPVOID *) &pPDN);
+ if (FAILED(hr))
+ {
+ hr = CoCreateInstance(classID,
+ NULL,
+ dwClassContext,
+ IID_IParseDisplayName,
+ (LPVOID *) &pPDN);
+ }
+
+ if(SUCCEEDED(hr))
+ {
+ hr = pPDN->ParseDisplayName(pbc,
+ (LPOLESTR) pszDisplayName,
+ pcchEaten,
+ ppmk);
+ pPDN->Release();
+ }
+ }
+
+ return hr;
+}
+
+INTERNAL_(BOOL) RunningMoniker ( LPBINDCTX pbc,
+ LPWSTR pszFullPath,
+ USHORT ccFullPath,
+ ULONG FAR *pcchEaten,
+ LPMONIKER FAR * ppmk)
+{
+
+ mnkDebugOut((DEB_ITRACE,
+ "RunningMoniker szDisplayName(%ws)",
+ WIDECHECK(pszFullPath)));
+
+ WCHAR ch;
+ LPWSTR pch;
+ HRESULT hresult;
+ CFileMoniker FAR * pCFM = NULL;
+ LPRUNNINGOBJECTTABLE pRot = NULL;
+ BOOL retVal = FALSE;
+ *pcchEaten = 0;
+
+ pch = pszFullPath + ccFullPath;
+
+ hresult = pbc->GetRunningObjectTable(&pRot);
+
+ if (hresult != NOERROR) goto errRet;
+
+ while (pch > pszFullPath)
+ {
+ if (IsFileSystemSeparator(*pch) ||
+ IsItemMonikerSeparator(*pch) ||
+ ('\0' == *pch))
+ {
+ ch = *pch;
+ *pch = '\0';
+ hresult = CreateFileMoniker( pszFullPath, (LPMONIKER FAR *)&pCFM );
+ *pch = ch;
+
+ if(SUCCEEDED(hresult))
+ {
+ hresult = pRot->IsRunning(pCFM);
+
+ //
+ // If found, then pCFM is our return moniker
+ //
+ if (hresult == S_OK)
+ {
+ *ppmk = pCFM;
+ *pcchEaten = (ULONG) (pch - pszFullPath);
+ retVal = TRUE;
+ break;
+ }
+ else
+ {
+ //
+ // This one isn't a match. Release it and try the next smaller
+ // path
+ //
+
+ pCFM->Release();
+ pCFM = NULL;
+ }
+ }
+ }
+ pch--;
+ }
+
+
+errRet:
+ if (pRot) pRot->Release();
+
+ return retVal;
+}
+
+INTERNAL FindMaximalFileMoniker(LPWSTR pszFullPath,
+ USHORT ccFullPath,
+ ULONG FAR *pcchEaten,
+ LPMONIKER FAR * ppmk)
+{
+ HRESULT hr = MK_E_SYNTAX;
+ WCHAR ch;
+ LPWSTR pch;
+ DWORD dwAttr;
+
+ *pcchEaten = 0;
+ *ppmk = 0;
+
+ pch = pszFullPath + ccFullPath;
+
+ while((pch > pszFullPath) &&
+ (MK_E_SYNTAX == hr))
+ {
+ if (IsFileSystemSeparator(*pch) ||
+ IsItemMonikerSeparator(*pch) ||
+ ('\0' == *pch))
+ {
+ ch = *pch;
+ *pch = '\0';
+
+ // Check if this path exists
+ dwAttr = GetFileAttributes(pszFullPath);
+
+ // The file exists
+ if (dwAttr != 0xffffffff)
+ {
+ // We fail if we found a directory
+ // but not a file.
+ if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ hr = MK_E_CANTOPENFILE;
+ }
+ else
+ {
+ hr = CreateFileMoniker(pszFullPath, ppmk);
+ if(SUCCEEDED(hr))
+ {
+ *pcchEaten = (ULONG) (pch - pszFullPath);
+ }
+ }
+ }
+
+ *pch = ch;
+ }
+ pch--;
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: FindFileMoniker
+//
+// Synopsis: Parse a file moniker display name.
+//
+// Arguments: [pbc] - Bind context
+// [pszDisplayName] - Display name to parse
+// [pcchEaten] - Number of characters eaten
+// [ppmk] - Moniker of running object
+//
+// Returns: S_OK if successful
+// Another HRESULT otherwise
+//
+// Algorithm: Find the largest left-bounded name that corresponds to a
+// valid initial moniker, either of an object currently running
+// and registered in the ROT or of an extant file.
+//
+// History: 22-Feb-96 ShannonC Moved code from MkParseDisplayName.
+//
+//----------------------------------------------------------------------------
+STDAPI FindFileMoniker(
+ LPBC pbc,
+ LPCWSTR pszDisplayName,
+ ULONG *pcchEaten,
+ LPMONIKER *ppmk)
+{
+ HRESULT hr = E_OUTOFMEMORY;
+ USHORT ccPath;
+ LPWSTR pszPath;
+
+ ccPath = lstrlenW(pszDisplayName);
+
+ pszPath = (WCHAR *) alloca((ccPath + 1) * sizeof(WCHAR));
+ if(pszPath != NULL)
+ {
+ memcpy(pszPath, pszDisplayName, (ccPath + 1) * sizeof(WCHAR));
+
+ if (RunningMoniker(pbc, pszPath, ccPath, pcchEaten, ppmk))
+ {
+ hr = S_OK;
+ }
+ else
+ {
+ hr = FindMaximalFileMoniker(pszPath, ccPath, pcchEaten, ppmk);
+ }
+ }
+
+ return hr;
+}
diff --git a/private/ole32/com/moniker2/cptrmon.cxx b/private/ole32/com/moniker2/cptrmon.cxx
new file mode 100644
index 000000000..49d9f36a3
--- /dev/null
+++ b/private/ole32/com/moniker2/cptrmon.cxx
@@ -0,0 +1,1188 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: cptrmon.cxx
+//
+// Contents: Implementation of CPointerMoniker
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Created
+// 06-14-94 Rickhi Fix type casting
+// 07-06-95 BruceMa Make remotable
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include "cbasemon.hxx"
+#include "cptrmon.hxx"
+#include "cantimon.hxx"
+#include "mnk.h"
+
+NAME_SEG(CPtrMon)
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::CPointerMoniker
+//
+// Synopsis: Constructor
+//
+// Arguments: [pUnk] --
+//
+// Returns: -
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+CPointerMoniker::CPointerMoniker( LPUNKNOWN pUnk ) CONSTR_DEBUG
+{
+ // We allow pUnk == NULL initially when remoting a pointer moniker
+ if (pUnk)
+ {
+ pUnk->AddRef();
+ }
+ m_pUnk = pUnk;
+}
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::~CPointerMoniker
+//
+// Synopsis: Destructor
+//
+// Arguments: -
+//
+// Returns: -
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+CPointerMoniker::~CPointerMoniker( void )
+{
+ M_PROLOG(this);
+
+ if (m_pUnk)
+ {
+ m_pUnk->Release();
+ }
+}
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsPointerMoniker : Private
+//
+// Synopsis: Constructor
+//
+// Arguments: [pmk] --
+//
+// Returns: pmk if it supprts CLSID_PointerMoniker
+// NULL otherwise
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+INTERNAL_(CPointerMoniker *) IsPointerMoniker ( LPMONIKER pmk )
+{
+ CPointerMoniker *pCPM;
+
+ if ((pmk->QueryInterface(CLSID_PointerMoniker, (void **)&pCPM)) == S_OK)
+ {
+ // we release the AddRef done by QI but return the pointer
+ pCPM->Release();
+ return pCPM;
+ }
+
+ // dont rely on user implementations to set pCPM to NULL on failed QI
+ return NULL;
+}
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::Create
+//
+// Synopsis: Create a new pointer moniker
+//
+// Arguments: [pmk] --
+//
+// Returns: pmk if it supprts CLSID_PointerMoniker
+// NULL otherwise
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+CPointerMoniker *CPointerMoniker::Create(
+ LPUNKNOWN pUnk )
+{
+ CPointerMoniker *pCIM = new CPointerMoniker(pUnk);
+
+ if (pCIM)
+ {
+ ((CBaseMoniker *) pCIM)->AddRef();
+ return pCIM;
+ }
+ return NULL;
+}
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::QueryInterface
+//
+// Synopsis:
+//
+// Arguments: [riid]
+// [ppvObj]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::QueryInterface (THIS_ REFIID riid,
+ LPVOID *ppvObj)
+{
+ M_PROLOG(this);
+ VDATEIID (riid);
+ VDATEPTROUT(ppvObj, LPVOID);
+
+#ifdef _DEBUG
+ if (riid == IID_IDebug)
+ {
+ *ppvObj = &(m_Debug);
+ return NOERROR;
+ }
+#endif
+
+ if (IsEqualIID(riid, CLSID_PointerMoniker))
+ {
+ // called by IsPointerMoniker.
+ AddRef();
+ *ppvObj = this;
+ return S_OK;
+ }
+
+ if (IsEqualIID(riid, IID_IMarshal))
+ {
+ AddRef();
+ *ppvObj = (IMarshal *) this;
+ return S_OK;
+ }
+
+ return CBaseMoniker::QueryInterface(riid, ppvObj);
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::AddRef
+//
+// Synopsis:
+//
+// Arguments: -
+//
+// Returns: New reference count
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CPointerMoniker::AddRef (void)
+{
+ M_PROLOG(this);
+
+ CBaseMoniker::AddRef();
+ return m_refs;
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::Release
+//
+// Synopsis:
+//
+// Arguments: -
+//
+// Returns: Current reference count
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CPointerMoniker::Release (void)
+{
+ M_PROLOG(this);
+ Assert(m_refs != 0);
+
+ ULONG ul = m_refs;
+
+ if (InterlockedDecrement((long *)&m_refs) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return ul - 1;
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::GetClassId
+//
+// Synopsis:
+//
+// Arguments: [riid]
+// [ppvObj]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::GetClassID (LPCLSID lpClassId)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(lpClassId, CLSID);
+
+ *lpClassId = CLSID_PointerMoniker;
+ return S_OK;
+}
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::GetUnmarshalClass
+//
+// Synopsis: Return the unmarshaling class
+//
+// Arguments: [riid]
+// [pv]
+// [dwMemctx]
+// [pvMemctx]
+// [mshlflags]
+// [pClsid]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::GetUnmarshalClass(THIS_ REFIID riid,
+ LPVOID pv,
+ DWORD dwMemctx,
+ LPVOID pvMemctx,
+ DWORD mshlflags,
+ LPCLSID pClsid)
+{
+ M_PROLOG(this);
+
+ *pClsid = CLSID_PointerMoniker;
+ return S_OK;
+}
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::GetMarshalSizeMax
+//
+// Synopsis: Return the maximum stream size needed
+//
+// Arguments: [riid]
+// [pv]
+// [dwMemctx]
+// [pvMemctx]
+// [mshlflags]
+// [lpdwSize]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::GetMarshalSizeMax(THIS_ REFIID riid,
+ LPVOID pv,
+ DWORD dwMemctx,
+ LPVOID pvMemctx,
+ DWORD mshlflags,
+ LPDWORD lpdwSize)
+{
+ M_PROLOG(this);
+
+
+ return CoGetMarshalSizeMax(lpdwSize, riid, m_pUnk, dwMemctx,
+ pvMemctx, mshlflags);
+}
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::MarshalInterface
+//
+// Synopsis: Marshal the object we're wrapping
+//
+// Arguments: [pStm]
+// [riid]
+// [pv]
+// [dwMemctx]
+// [pvMemctx]
+// [mshlflags]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::MarshalInterface(THIS_ LPSTREAM pStm,
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwMemctx,
+ LPVOID pvMemctx,
+ DWORD mshlflags)
+{
+ HRESULT hr;
+ LPVOID pUnk;
+
+ M_PROLOG(this);
+
+ // Make sure we support the requested interface
+ if (FAILED(hr = QueryInterface(riid, &pUnk)))
+ {
+ return hr;
+ }
+ Release();
+
+ // Marshal the wrapped object
+ hr = CoMarshalInterface(pStm,
+ IID_IUnknown,
+ m_pUnk,
+ dwMemctx,
+ pvMemctx,
+ mshlflags);
+ return hr;
+}
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::UnmarshalInterface
+//
+// Synopsis: Unmarshal the object we're wrapping
+//
+// Arguments: [pStm]
+// [riid]
+// [ppv]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::UnmarshalInterface(THIS_ LPSTREAM pStm,
+ REFIID riid, LPVOID *ppv)
+{
+ HRESULT hr;
+ LPVOID pUnk;
+
+ M_PROLOG(this);
+
+ // Unmarshal the object we're wrapping
+ if (FAILED(hr = CoUnmarshalInterface(pStm, IID_IUnknown,
+ (LPVOID *) &m_pUnk)))
+ {
+ return hr;
+ }
+
+ // Make sure we support the requested interface - this also takes
+ // the reference we need
+ if (FAILED(hr = QueryInterface(riid, &pUnk)))
+ {
+ return hr;
+ }
+
+ // Return ourselves as the unmarshaled object
+ *ppv = this;
+
+ return S_OK;
+}
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::ReleaseMarshalData
+//
+// Synopsis: Don't do anything
+//
+// Arguments: [pStm]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::ReleaseMarshalData(THIS_ LPSTREAM pStm)
+{
+ M_PROLOG(this);
+
+ return CoReleaseMarshalData(pStm);;
+}
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::DisconnectObject
+//
+// Synopsis: Don't do anything
+//
+// Arguments: [pStm]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::DisconnectObject(THIS_ DWORD dwReserved)
+{
+ M_PROLOG(this);
+
+ return CoDisconnectObject(m_pUnk, NULL);
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::BindToObject
+//
+// Synopsis:
+//
+// Arguments: [pbc]
+// [pmkToLeft]
+// [iidResult]
+// [ppvResult]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::BindToObject ( LPBC pbc,
+ LPMONIKER pmkToLeft, REFIID iidResult,
+ VOID **ppvResult)
+{
+ HRESULT hr;
+ LARGE_INTEGER cMove = {0, 0};
+
+ M_PROLOG(this);
+ VDATEPTROUT(ppvResult, LPVOID);
+ *ppvResult = NULL;
+ VDATEIFACE(pbc);
+ if (pmkToLeft)
+ {
+ VDATEIFACE(pmkToLeft);
+ }
+ VDATEIID(iidResult);
+
+ // Attempt to return the requested interface
+ if (m_pUnk)
+ {
+ return m_pUnk->QueryInterface(iidResult, ppvResult);
+ }
+
+ // No object
+ return E_UNEXPECTED;
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::BindToStorage
+//
+// Synopsis:
+//
+// Arguments: [lpbc]
+// [pmkToLeft]
+// [riid]
+// [ppvResult]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::BindToStorage (LPBC pbc, LPMONIKER
+ pmkToLeft, REFIID riid, LPVOID *ppvObj)
+{
+ M_PROLOG(this);
+
+ // Same logic as for BindToStorage
+ return BindToObject(pbc, pmkToLeft, riid, ppvObj);
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::ComposeWith
+//
+// Synopsis:
+//
+// Arguments: [pmkRight]
+// [fOnlyIfNotGeneric]
+// [ppmkComposite]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::ComposeWith (LPMONIKER pmkRight,
+ BOOL fOnlyIfNotGeneric, LPMONIKER *ppmkComposite)
+{
+
+ VDATEPTROUT(ppmkComposite,LPMONIKER);
+ *ppmkComposite = NULL;
+ VDATEIFACE(pmkRight);
+
+ HRESULT hresult = NOERROR;
+
+ //
+ // If this is an AntiMoniker, then we are going to ask the AntiMoniker
+ // for the composite. This is a backward compatibility problem. Check
+ // out the CAntiMoniker::EatOne() routine for details.
+ //
+
+ CAntiMoniker *pCAM = IsAntiMoniker(pmkRight);
+ if (pCAM)
+ {
+ pCAM->EatOne(ppmkComposite);
+ }
+ else
+ {
+ if (!fOnlyIfNotGeneric)
+ {
+ hresult = CreateGenericComposite( this, pmkRight, ppmkComposite );
+ }
+ else
+ {
+ hresult = ResultFromScode(MK_E_NEEDGENERIC);
+ *ppmkComposite = NULL;
+ }
+ }
+ return hresult;
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::IsEqual
+//
+// Synopsis:
+//
+// Arguments: [pmkOtherMoniker]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::IsEqual (THIS_ LPMONIKER pmkOtherMoniker)
+{
+ M_PROLOG(this);
+ VDATEIFACE(pmkOtherMoniker);
+
+ CPointerMoniker FAR* pCIM = IsPointerMoniker(pmkOtherMoniker);
+ if (pCIM)
+ {
+ // the other moniker is a ptr moniker.
+ //for the names, we do a case-insensitive compare.
+ if (m_pUnk == pCIM->m_pUnk)
+ {
+ return S_OK;
+ }
+ }
+
+ return S_FALSE;
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::Hash
+//
+// Synopsis:
+//
+// Arguments: [pdwHash]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::Hash (THIS_ LPDWORD pdwHash)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(pdwHash, DWORD);
+
+ *pdwHash = (DWORD)m_pUnk; // REVIEW: safe for portability???
+ noError;
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::GetTimeOfLastChange
+//
+// Synopsis:
+//
+// Arguments: [pbc]
+// [pmkToLeft]
+// [pFileTime]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::GetTimeOfLastChange(THIS_ LPBC pbc,
+ LPMONIKER pmkToLeft,
+ FILETIME *pfiletime)
+{
+ M_PROLOG(this);
+ VDATEIFACE(pbc);
+ if (pmkToLeft)
+ {
+ VDATEIFACE(pmkToLeft);
+ }
+ VDATEPTROUT(pfiletime, FILETIME);
+
+ return E_NOTIMPL; // GetTimeOfLastChange not implemented
+ // for pointer monikers
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::Inverse
+//
+// Synopsis:
+//
+// Arguments: [ppmk]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::Inverse (THIS_ LPMONIKER *ppmk)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(ppmk, LPMONIKER);
+ return CreateAntiMoniker(ppmk);
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::CommonPrefixWith
+//
+// Synopsis:
+//
+// Arguments: [pmkOther]
+// [ppmkPrefix]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::CommonPrefixWith (LPMONIKER pmkOther,
+ LPMONIKER *ppmkPrefix)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(ppmkPrefix,LPMONIKER);
+ *ppmkPrefix = NULL;
+ VDATEIFACE(pmkOther);
+
+ if (S_OK == IsEqual(pmkOther))
+ {
+ *ppmkPrefix = this;
+ AddRef();
+ return MK_S_US;
+ }
+ return MK_E_NOPREFIX;
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::RelativePathTo
+//
+// Synopsis:
+//
+// Arguments: [pmkOther]
+// [ppmkRelPath]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::RelativePathTo (THIS_ LPMONIKER pmkOther,
+ LPMONIKER *ppmkRelPath)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(ppmkRelPath,LPMONIKER);
+ *ppmkRelPath = NULL;
+ VDATEIFACE(pmkOther);
+
+ return E_NOTIMPL;
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::GetDisplayName
+//
+// Synopsis:
+//
+// Arguments: [pbc]
+// [pmkToLeft]
+// [lplpszisplayName]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::GetDisplayName (LPBC pbc,
+ LPMONIKER pmkToLeft,
+ LPWSTR *lplpszDisplayName )
+{
+ M_PROLOG(this);
+ VDATEPTROUT(lplpszDisplayName, LPWSTR);
+ *lplpszDisplayName = NULL;
+ VDATEIFACE(pbc);
+ if (pmkToLeft)
+ {
+ VDATEIFACE(pmkToLeft);
+ }
+
+ return E_NOTIMPL;
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::ParseDisplayName
+//
+// Synopsis:
+//
+// Arguments: [pbc]
+// [pmkToLeft]
+// [lpszDisplayName]
+// [pchEaten]
+// [ppmkOut]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::ParseDisplayName (LPBC pbc,
+ LPMONIKER pmkToLeft,
+ LPWSTR lpszDisplayName,
+ ULONG *pchEaten,
+ LPMONIKER *ppmkOut)
+{
+ M_PROLOG(this);
+ VDATEPTROUT(ppmkOut,LPMONIKER);
+ *ppmkOut = NULL;
+ VDATEIFACE(pbc);
+ if (pmkToLeft)
+ {
+ VDATEIFACE(pmkToLeft);
+ }
+ VDATEPTRIN(lpszDisplayName, WCHAR);
+ VDATEPTROUT(pchEaten,ULONG);
+
+ IParseDisplayName FAR * lpPDN;
+ HRESULT hresult;
+
+ hresult = m_pUnk->QueryInterface(IID_IParseDisplayName, (LPLPVOID)&lpPDN);
+ if (hresult == S_OK)
+ {
+ hresult = lpPDN->ParseDisplayName(pbc, lpszDisplayName,
+ pchEaten, ppmkOut);
+ lpPDN->Release();
+ }
+
+ return hresult;
+}
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::IsRunning
+//
+// Synopsis: Objects that pointer monikers point to must be running, since
+// the pointer moniker holds an active reference to it.
+// Therefore, this routine will validate the parameters, then
+// always return S_OK.
+//
+// Effects:
+//
+// Arguments: [pbc] --
+// [pmkToLeft] --
+// [pmkNewlyRunning] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 3-03-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::IsRunning (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning)
+{
+ M_PROLOG(this);
+ VDATEIFACE (pbc);
+ if (pmkToLeft)
+ {
+ VDATEIFACE (pmkToLeft);
+ }
+
+ if (pmkNewlyRunning)
+ {
+ VDATEIFACE (pmkNewlyRunning);
+ }
+
+ //
+ // Always running.
+ //
+ return(S_OK);
+}
+
+
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::IsSystemMoniker
+//
+// Synopsis:
+//
+// Arguments: [pdwType]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPointerMoniker::IsSystemMoniker (THIS_ LPDWORD pdwType)
+{
+ M_PROLOG(this);
+ *pdwType = MKSYS_POINTERMONIKER;
+ return S_OK;
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::CDebug::Dump
+//
+// Synopsis:
+//
+// Arguments: [riid]
+// [ppvObj]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+#ifdef _DEBUG
+STDMETHODIMP_(void) NC(CPointerMoniker,CDebug)::Dump ( IDebugStream *pdbstm)
+{
+ VOID_VDATEIFACE( pdbstm );
+
+ *pdbstm << "CPointerMoniker @" << (VOID FAR *)m_pPointerMoniker;
+ *pdbstm << '\n';
+ pdbstm->Indent();
+ *pdbstm << "Refcount is " << (int)(m_pPointerMoniker->m_refs) << '\n';
+ *pdbstm << "Pointer is " << (LPVOID)m_pPointerMoniker->m_pUnk << '\n';
+ pdbstm->UnIndent();
+}
+
+
+
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CPointerMoniker::CDebug::IsValid
+//
+// Synopsis:
+//
+// Arguments: [fSuspicious]
+//
+// Returns:
+//
+// Algorithm:
+//
+// History: 06-Jul-95 BruceMa Added this header
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(BOOL) NC(CPointerMoniker,CDebug)::IsValid ( BOOL fSuspicious )
+{
+ return ((LONG)(m_pPointerMoniker->m_refs) > 0);
+ // add more later, maybe
+}
+
+#endif
diff --git a/private/ole32/com/moniker2/cptrmon.hxx b/private/ole32/com/moniker2/cptrmon.hxx
new file mode 100644
index 000000000..7053cf42a
--- /dev/null
+++ b/private/ole32/com/moniker2/cptrmon.hxx
@@ -0,0 +1,88 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: cptrmon.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Commented
+// 07-06-95 BruceMa Make remotable
+//
+//----------------------------------------------------------------------------
+
+
+class FAR CPointerMoniker : public CBaseMoniker, public IMarshal
+{
+
+public:
+ static CPointerMoniker *Create(LPUNKNOWN pUnk);
+
+ friend CPointerMoniker *IsPointerMoniker(LPMONIKER pmk);
+
+private:
+
+ CPointerMoniker( LPUNKNOWN pUnk );
+ ~CPointerMoniker( void );
+
+ STDDEBDECL(CPointerMoniker, PointerMoniker)
+
+ // IUnknown methods
+ STDMETHOD(QueryInterface) (THIS_ REFIID iid, LPVOID *ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID);
+
+ // *** IMarshal Methods
+ STDMETHOD(GetUnmarshalClass)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwMemctx, LPVOID pvMemctx,
+ DWORD mshlflags, LPCLSID pClsid);
+ STDMETHOD(GetMarshalSizeMax)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwMemctx, LPVOID pvMemctx,
+ DWORD mshlflags, LPDWORD lpdwSize);
+ STDMETHOD(MarshalInterface)(THIS_ LPSTREAM pStm, REFIID riid,
+ LPVOID pv, DWORD dwMemctx, LPVOID pvMemctx,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(THIS_ LPSTREAM pStm, REFIID riid,
+ LPVOID *ppv);
+ STDMETHOD(ReleaseMarshalData)(THIS_ LPSTREAM pStm);
+ STDMETHOD(DisconnectObject)(THIS_ DWORD dwReserved);
+
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID FAR* ppvResult);
+ STDMETHOD(BindToStorage) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNOtGeneric,
+ LPMONIKER FAR* ppmkPointer);
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker);
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash);
+ STDMETHOD(IsRunning) (THIS_ LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+ pmkNewlyRunning);
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime);
+ STDMETHOD(Inverse) (THIS_ LPMONIKER FAR* ppmk);
+ STDMETHOD(CommonPrefixWith) (LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix);
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath);
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR FAR* lplpszDisplayName);
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPWSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut);
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys);
+
+shared_state:
+
+ LPUNKNOWN m_pUnk; // The punk of the wrapped object
+ SET_A5;
+};
diff --git a/private/ole32/com/moniker2/daytona/makefile b/private/ole32/com/moniker2/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/moniker2/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/moniker2/daytona/sources b/private/ole32/com/moniker2/daytona/sources
new file mode 100644
index 000000000..2c5704df5
--- /dev/null
+++ b/private/ole32/com/moniker2/daytona/sources
@@ -0,0 +1,79 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= moniker
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..;..\..\inc;..\..\rot;..\..\objact
+INCLUDES= $(INCLUDES);..\..\dcomrem;..\..\dcomidl\daytona
+INCLUDES= $(INCLUDES);$(BASEDIR)\private\dcomidl\obj
+
+
+C_DEFINES= \
+ $(C_DEFINES)
+
+SOURCES= \
+ ..\cantimon.cxx \
+ ..\cbindctx.cxx \
+ ..\ccompmon.cxx \
+ ..\cfactory.cxx \
+ ..\cfilemon.cxx \
+ ..\classmon.cxx \
+ ..\extents.cxx \
+ ..\citemmon.cxx \
+ ..\cmonimp.cxx \
+ ..\cptrmon.cxx \
+ ..\mkparse.cxx \
+ ..\cbasemon.cxx \
+ ..\cmarshal.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
diff --git a/private/ole32/com/moniker2/dirs b/private/ole32/com/moniker2/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/com/moniker2/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/com/moniker2/extents.cxx b/private/ole32/com/moniker2/extents.cxx
new file mode 100644
index 000000000..abe7e8f9d
--- /dev/null
+++ b/private/ole32/com/moniker2/extents.cxx
@@ -0,0 +1,475 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: extents.cxx
+//
+// Contents: Implmentation for CExtentList
+//
+// Classes: CExtentList
+//
+// Functions:
+//
+// History: 1-08-94 kevinro Created
+// 31-Jan-95 BruceMa Set size to 0 if E_OUTOFMEMORY
+// 17-Jul-95 BruceMa Add mutex to protect AddExtent (Cairo only)
+// 10-13-95 stevebl moved mutex to CFileMoniker as part of
+// adding general threadsafety to monikers
+//
+//----------------------------------------------------------------------------
+#include <ole2int.h>
+
+#include "extents.hxx"
+#include "mnk.h"
+
+
+CExtentList::CExtentList():
+ m_pchMonikerExtents(NULL),
+ m_cbMonikerExtents(0)
+{
+ ;
+}
+CExtentList::~CExtentList()
+{
+ if (m_pchMonikerExtents != NULL)
+ {
+ CoTaskMemFree(m_pchMonikerExtents);
+ }
+
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CExtentList::Copy
+//
+// Synopsis: Make a copy of a CExtentList
+//
+// Effects:
+//
+// Arguments: [newExtent] -- Recieving list
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-08-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CExtentList::Copy(CExtentList & newExtent)
+{
+ newExtent.m_cbMonikerExtents = m_cbMonikerExtents;
+ newExtent.m_pchMonikerExtents = (BYTE *) CoTaskMemAlloc(m_cbMonikerExtents);
+
+ if ( newExtent.m_pchMonikerExtents == NULL )
+ {
+ newExtent.m_cbMonikerExtents = 0;
+ return(E_OUTOFMEMORY);
+ }
+
+ memcpy(newExtent.m_pchMonikerExtents,
+ m_pchMonikerExtents,
+ m_cbMonikerExtents);
+
+ return(NOERROR);
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CExtentList::FindExtent
+//
+// Synopsis: Searches the extent list, looking for a matching extent.
+//
+// Effects:
+//
+// Arguments: [usKeyValue] --
+//
+// Requires:
+//
+// Returns: NULL not found
+// UNALIGNED POINTER to extent.
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-08-94 kevinro Created
+//
+// Notes:
+//
+// WARNINGS:
+//
+// The pointer returned is not aligned.
+//
+// The pointer will become invalide if an extent is added to the block.
+// This falls under the not multi-thread safe category. This is done for
+// efficiency reasons, since we don't ever expect to both add and lookup
+// at the same time.
+//
+//----------------------------------------------------------------------------
+MONIKEREXTENT UNALIGNED *
+CExtentList::FindExtent(USHORT usKeyValue)
+{
+ ULONG ulOffset = 0;
+
+ while(ulOffset < m_cbMonikerExtents)
+ {
+
+ MONIKEREXTENT UNALIGNED *pExtent = (MONIKEREXTENT UNALIGNED *)
+ &m_pchMonikerExtents[ulOffset];
+
+ //
+ // There had better be enough bytes left to look at! If not, there
+ // is some corruption in the extent block. Not much we can do about
+ // it, other than return NULL
+ // If the end minus the pointer is less than sizeof MONIKEREXTENT
+ // we have a problem.
+
+ if( (m_pchMonikerExtents + m_cbMonikerExtents) - ((BYTE*)pExtent ) <
+ sizeof(MONIKEREXTENT) )
+ {
+ return(NULL);
+ }
+
+ //
+ // Get the key value from the buffer and compare against what we want.
+ // Be careful about alignment here.
+ //
+
+
+ if (pExtent->usKeyValue == usKeyValue )
+ {
+ return(pExtent);
+ }
+
+ ulOffset += MonikerExtentSize(pExtent);
+ }
+ return(NULL);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CExtentList::DeleteExtent
+//
+// Synopsis: Deletes the given extent if it exists.
+//
+// Effects:
+//
+// Arguments: [usKeyValue] --
+//
+// Requires:
+//
+// Returns: S_OK -- found and deleted.
+// S_FALSE -- not found.
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-08-95 BillMo Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef _TRACKLINK_
+HRESULT
+CExtentList::DeleteExtent(USHORT usKeyValue)
+{
+ MONIKEREXTENT UNALIGNED *pExtent = FindExtent(usKeyValue);
+ BYTE *pbExtent = (BYTE *)pExtent;
+
+ if (pExtent != NULL)
+ {
+ ULONG cbRemove = MonikerExtentSize(pExtent);
+ BYTE * pbFrom = pbExtent + cbRemove;
+
+ MoveMemory(pbExtent,
+ pbFrom,
+ m_cbMonikerExtents - (pbFrom - m_pchMonikerExtents));
+
+ m_cbMonikerExtents -= cbRemove;
+ return(S_OK);
+ }
+ return(S_FALSE);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Method: CExtentList::AddExtent
+//
+// Synopsis: Adds an extent to the list. This function adds a copy
+// of the data.
+// Effects:
+//
+// Arguments: [pExtent] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-08-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT
+CExtentList::AddExtent(MONIKEREXTENT const * pExtent)
+{
+ //
+ // Reallocate the current buffer to make room for the new extent
+ // The new extent is appended to the end of the current list.
+ //
+
+ ULONG ulNewSize = m_cbMonikerExtents + MonikerExtentSize(pExtent);
+ BYTE * pchNewBuffer;
+
+ pchNewBuffer = (BYTE *)CoTaskMemRealloc(m_pchMonikerExtents,ulNewSize);
+
+ if (pchNewBuffer == NULL)
+ {
+ return(E_OUTOFMEMORY);
+ }
+
+ m_pchMonikerExtents = pchNewBuffer;
+
+ //
+ // Append new extent
+ //
+
+ memcpy(m_pchMonikerExtents + m_cbMonikerExtents,
+ pExtent,
+ MonikerExtentSize(pExtent));
+
+ m_cbMonikerExtents = ulNewSize;
+
+ return(NOERROR);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CExtentList::PutExtent
+//
+// Synopsis: Deletes the extent (if it exists) and then adds it back.
+//
+// Effects:
+//
+// Arguments: [pExtent] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-15-95 BillMo Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef _TRACKLINK_
+HRESULT
+CExtentList::PutExtent(MONIKEREXTENT const * pExtent)
+{
+ DeleteExtent(pExtent->usKeyValue);
+ return(AddExtent(pExtent));
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: Save
+//
+// Synopsis: Save the extent to a stream
+//
+// Effects: Nice straightforward write of the entire blob to a stream
+//
+// Arguments: [pStm] -- Stream to write to
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 1-08-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT
+CExtentList::Save(IStream * pStm)
+{
+ HRESULT hr;
+
+ //
+ // It must be true that both are zero, or neither is zero
+ //
+
+ Assert( ((m_cbMonikerExtents == 0) && (m_pchMonikerExtents == NULL)) ||
+ ((m_pchMonikerExtents != NULL) && (m_cbMonikerExtents != 0)));
+
+ //
+ // First, write the length, then write the blob
+ //
+ hr = pStm->Write((void *)&m_cbMonikerExtents,
+ sizeof(m_cbMonikerExtents),
+ NULL);
+
+ if (FAILED(hr))
+ {
+ return(hr);
+ }
+
+ //
+ // Only write moniker extents if some exist
+ //
+
+ if (m_cbMonikerExtents != 0)
+ {
+ hr = pStm->Write((void *)m_pchMonikerExtents,
+ m_cbMonikerExtents,
+ NULL);
+ }
+
+ return(hr);
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CExtentList::Load
+//
+// Synopsis: Load the moniker extents from stream
+//
+// Effects:
+//
+// Arguments: [pStm] -- Stream to load from
+// [ulSize] -- Size of extents, in bytes
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-08-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT
+CExtentList::Load(IStream * pStm, ULONG ulSize)
+{
+ HRESULT hr;
+
+ //
+ // In the debugging verision, we should never have an extent larger
+ // than say about 2k. This should catch any errors
+ //
+
+ Assert( ulSize < (2 * 1024));
+
+ //
+ // Be sure not to drop any memory. This normally should never happen.
+ //
+
+ if (m_pchMonikerExtents != NULL)
+ {
+ CoTaskMemFree(m_pchMonikerExtents);
+ }
+
+ m_cbMonikerExtents = ulSize;
+
+ m_pchMonikerExtents = (BYTE *)CoTaskMemAlloc(m_cbMonikerExtents);
+
+ if (m_pchMonikerExtents == NULL)
+ {
+ m_cbMonikerExtents = 0;
+ return(E_OUTOFMEMORY);
+ }
+
+ hr = StRead(pStm, m_pchMonikerExtents, m_cbMonikerExtents);
+
+ return(hr);
+
+}
+//+---------------------------------------------------------------------------
+//
+// Method: CExtentList::GetSize
+//
+// Synopsis: Returns the size needed to serialize this object
+//
+// Effects:
+//
+// Arguments: [pcbSize] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 1-08-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+ULONG
+CExtentList::GetSize()
+{
+ return sizeof(m_cbMonikerExtents)+m_cbMonikerExtents;
+
+}
diff --git a/private/ole32/com/moniker2/extents.hxx b/private/ole32/com/moniker2/extents.hxx
new file mode 100644
index 000000000..c2b1c5ac5
--- /dev/null
+++ b/private/ole32/com/moniker2/extents.hxx
@@ -0,0 +1,175 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: extents.hxx
+//
+// Contents: Moniker extent definitions
+//
+// Classes: CExtentList
+//
+// Functions:
+//
+// History: 1-08-94 kevinro Created
+// 17-Jul-95 BruceMa Add mutex to protect AddExtent (Cairo only)
+// 10-10-95 stevebl moved mutex to CFileMoniker as part of
+// adding general threadsafety to monikers
+//
+//----------------------------------------------------------------------------
+//
+// Monikers need to be extendable. The on disk representation of a moniker
+// has a reserved field that is treated as a bag of bits. This field,
+// called achMonikerExtents (formerly read into m_pchMacAlias) contains
+// a list of MONIKEREXTENT structures. The length of the achMonikerExtents
+// cbMonikerExents.
+//
+// (Historical note: This bag of bits was once reserved for storing a
+// Macintosh alias. The MAC and Win32 versions of the moniker code have
+// agreed to share this field. There are several extents already in the
+// works, such as the UNICODE extent, and the DFS extent. KevinRo 1/94)
+//
+// The format for the serialized data types is x86 (little endian).
+//
+// As seralized in the stream, the MONIKEREXENT looks like:
+// -------------------------------------------------------------------------
+// | | | < achMonikerExtents> |
+// | <other data> | cbMonikerExtents | [MONIKEREXENT] [MONIKEREXENT]|
+// -------------------------------------------------------------------------
+// ^ ^
+// -- cbMonikerExtent bytes --
+//
+// Each MONIKEREXENT has an internal structure that is represented below.
+// Each has a size, and a key value, followed by a series of bytes.
+//
+// -------------------------------------------------------------------------
+// | cbExtentBytes | usKeyValue | achExtentBytes[m_cbExentBytes] |
+// -------------------------------------------------------------------------
+//
+// Therefore, the total length of an extent equals
+// sizeof(cbExtentBytes) + sizeof(usKeyValue) + cbExtentBytes
+//
+// To read in the list, the following algorithm could be used
+//
+// Read cbMonikerExtents
+//
+// while( cbMonikerExtents != 0)
+// {
+// Read cbExtentBytes and usKeyValue to determine size of buffer
+// Alloc sizeof(MONIKEREXENT) + cbExtentBytes - 1;
+// Read achExtentBytes[cbExtentBytes]
+//
+// cbMonikerExtents -= sizeof(cbExtentBytes) +
+// sizeof(usKeyValue) +
+// cbExtentBytes
+// }
+//
+// The alternative is to read the entire block at once, and parse through
+// it. See CExentList for details.
+//
+// The philosophy here is to keep the moniker serialized format up and down
+// level compatible by storing new information in extents. Not all extents
+// will exist at all times, therefore we have a dynamic list of possible
+// extents. If a particular implemenation doesn't understand an extent, it
+// has the repsonsiblity of storing the extent as a bag of bits.
+//
+// For example, the MacAlias extent is only used when the Mac has seralized
+// a moniker. The UNICODE extent is only used when the UNICODE path used to
+// create the moniker could not be converted into an ANSI string without
+// data loss.
+//
+
+#ifndef _EXTENTS_HXX_
+#define _EXTENTS_HXX_
+
+typedef struct _MONIKEREXTENT
+{
+ ULONG cbExtentBytes; // Number of data bytes in extent
+ USHORT usKeyValue; // Key value for this extent
+ BYTE achExtentBytes[1]; // Data bytes for extent
+
+} MONIKEREXTENT;
+typedef MONIKEREXTENT * LPMONIKEREXTENT;
+
+#define MONIKEREXTENT_HEADERSIZE (sizeof(ULONG) + sizeof(USHORT))
+#define MonikerExtentSize(pExtent) (pExtent->cbExtentBytes + MONIKEREXTENT_HEADERSIZE)
+
+
+//
+// The following are the currently known values of extent keys.
+//
+// NEVER EVER CHANGE THE ORDER OR VALUES.
+//
+// You may add one to the end. Never allow them to conflict.
+//
+
+enum ExtentKeys
+{
+ mnk_MAC = 1,
+ mnk_DFS = 2,
+ mnk_UNICODE = 3,
+ mnk_MacPathName = 4,
+ mnk_ShellLink = 5,
+ mnk_TrackingInformation = 6
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CExtentList (private)
+//
+// Purpose:
+//
+// If we get a set of MONIKEREXTENTS, it would be much friendlier throughout
+// the code to abstract the MONIKEREXENTS into a list, rather than having
+// to munge our way through the buffer each time.
+//
+// CExentList acts as that abstraction. It has the advantages of reading
+// and writing the extents as a single large blob.
+//
+//
+// Interface: m_pchMonikerExtents --
+// CoMemFree --
+// FindExtent --
+// AddExetent --
+// PutExtent -- creates or overwrites extent.
+// m_cbMonikerExents --
+//
+// History: 1-08-94 kevinro Created
+//
+// Notes:
+//
+// To day, I haven't found a need for a remove function for this list
+//
+// WARNINGS:
+//
+// An extent is not aligned when returned from the Find routine. The pointer
+// returned must be UNALIGNED, or we will fault on RISC machines. Take
+// appropriate precautions. Items returned from find are pointers into the
+// list. Be carefule about modificiations.
+//
+// This list is not multi-thread safe. Be sure to serialize access to it.
+//
+//----------------------------------------------------------------------------
+class CExtentList : public CPrivAlloc
+{
+public:
+ CExtentList();
+ ~CExtentList();
+
+ MONIKEREXTENT UNALIGNED * FindExtent(USHORT usKeyValue);
+ HRESULT AddExtent(MONIKEREXTENT const * pExtent);
+#ifdef _TRACKLINK_
+ HRESULT PutExtent(MONIKEREXTENT const * pExtent);
+ HRESULT DeleteExtent(USHORT usKeyValue);
+#endif
+ HRESULT Save(IStream * pStm);
+ HRESULT Load(IStream * pStm,ULONG ulSize);
+ ULONG GetSize();
+ HRESULT Copy(CExtentList & newExtent);
+
+private:
+ ULONG m_cbMonikerExtents;
+ BYTE * m_pchMonikerExtents;
+};
+#endif //_EXTENTS_HXX_
diff --git a/private/ole32/com/moniker2/filelist.mk b/private/ole32/com/moniker2/filelist.mk
new file mode 100644
index 000000000..45f4570bd
--- /dev/null
+++ b/private/ole32/com/moniker2/filelist.mk
@@ -0,0 +1,48 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = moniker.lib
+
+!if "$(CAIROLE_TYPE)" == "DOWNLEVEL"
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES = \
+ .\cantimon.cxx \
+ .\cfilemon.cxx \
+ .\cbasemon.cxx \
+ .\cmarshal.cxx \
+ .\cbindctx.cxx \
+ .\ccompmon.cxx \
+ .\citemmon.cxx \
+ .\cmonimp.cxx \
+ .\cptrmon.cxx \
+ .\extents.cxx \
+ .\mkparse.cxx
+
+PXXFILE = .\headers.cxx
+
+CINC = $(CINC) -I..\inc $(LRPC)
+
+!else
+
+SUBDIRS = cairo
+LIBS = .\cairo\$(OBJDIR)\cairomnk.lib
+
+!endif
+
+
+MTHREAD = 1
+
diff --git a/private/ole32/com/moniker2/makefile b/private/ole32/com/moniker2/makefile
new file mode 100644
index 000000000..b891625bc
--- /dev/null
+++ b/private/ole32/com/moniker2/makefile
@@ -0,0 +1,24 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+!include $(CAIROLE)\com\makefile
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/com/moniker2/mkparse.cxx b/private/ole32/com/moniker2/mkparse.cxx
new file mode 100644
index 000000000..c585a713a
--- /dev/null
+++ b/private/ole32/com/moniker2/mkparse.cxx
@@ -0,0 +1,161 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: mkparse.cxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 06-Nov-92 jasonful Created
+// 12-27-93 ErikGav Commented
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include "cbasemon.hxx"
+#include "ccompmon.hxx"
+#include "citemmon.hxx"
+#include "mnk.h"
+
+// Moved here as a temporary measure since this macro is not used in 32 bit
+#define RetErr(x) {HRESULT hresult; if (NOERROR != (hresult=(x))) {return hresult;}}
+
+// INTERNAL Ole10_ParseMoniker
+//
+// If pmk is a file moniker or a file::item composite, then return
+// the obvious strings in *pszFile and *pszItem.
+// NOTE: these strings must be deleted.
+// Return error if moniker is of some other type.
+//
+// Can pass NULL, meaning you don't care about the strings
+//
+INTERNAL Ole10_ParseMoniker
+ (LPMONIKER pmk,
+ LPWSTR FAR* pszFile,
+ LPWSTR FAR* pszItem)
+{
+ LPWSTR szFile = NULL;
+ LPWSTR szItem = NULL;
+ LPMONIKER pmkFile= NULL;
+ LPMONIKER pmkItem= NULL;
+ HRESULT hr = ResultFromScode (E_UNSPEC);
+ LPBC pbc = NULL;
+
+ CCompositeMoniker *pCMk = NULL;
+ CItemMoniker *pIMk = NULL;
+
+ if (IsFileMoniker(pmk))
+ {
+ RetErr (CreateBindCtx(0, &pbc));
+ Assert(pbc != NULL);
+ if (NOERROR != pmk->GetDisplayName (pbc, NULL, &szFile))
+ {
+ Assert(szFile == NULL);
+ CairoleAssert(0 && "Could not get Display name for file piece");
+ goto errRtn;
+ }
+ // AssertOutPtrParam(NOERROR, szFile);
+ }
+ else if ((pCMk = IsCompositeMoniker(pmk)) != NULL)
+ {
+ pmkFile = pCMk->First();
+ if (NULL==pmkFile)
+ {
+ CairoleAssert(0 && "Composite moniker does not have car");
+ hr = ResultFromScode(E_UNSPEC);
+ goto errRtn;
+ }
+ // Is first piece a file moniker?
+ if (IsFileMoniker (pmkFile))
+ {
+ RetErr (CreateBindCtx(0, &pbc));
+ Assert(pbc != NULL);
+ if (NOERROR != pmkFile->GetDisplayName (pbc, NULL, &szFile))
+ {
+ Assert(szFile == NULL);
+ CairoleAssert(0 && "Could not get Display name for file piece");
+ goto errRtn;
+ }
+ // AssertOutPtrParam(NOERROR, szFile);
+ }
+ else
+ {
+ CairoleAssert(0 && "First piece is not a file moniker");
+ hr = NOERROR;
+ goto errRtn;
+ }
+
+ // Get Item Moniker
+
+ pmkItem = pCMk->AllButFirst();
+ if (NULL==pmkItem)
+ {
+ CairoleAssert(0 && "Composite moniker does not have cdr");
+ hr = ResultFromScode(E_UNSPEC);
+ goto errRtn;
+ }
+ if ((pIMk = IsItemMoniker (pmkItem)) != NULL)
+ {
+ // This is the case we want: FileMoniker :: ItemMoniker
+
+ if (NULL==(szItem = pIMk->m_lpszItem))
+ {
+ CairoleAssert(0 && "Could not get string for item moniker");
+ goto errRtn;
+ }
+ szItem = UtDupString (szItem); // so it'll be allocated like
+ // an out parm from GetDisplayName
+ }
+ else
+ {
+ // This is the FileMoniker - ItemMoniker - ItemMoniker... case
+ // We cannot convert this to 1.0
+ hr = ResultFromScode(S_FALSE);
+ goto errRtn;
+ }
+ }
+ else
+ {
+ CairoleAssert(0 && "Cannot identify moniker type");
+ hr = ResultFromScode (E_UNSPEC);
+ goto errRtn;
+ }
+
+ if (pszFile)
+ *pszFile = szFile;
+ else
+ CoTaskMemFree(szFile);
+
+ if (pszItem)
+ *pszItem = szItem;
+ else
+ CoTaskMemFree(szItem);
+
+ if (pmkFile)
+ pmkFile->Release();
+ if (pmkItem)
+ pmkItem->Release();
+
+ if (pbc)
+ pbc->Release();
+
+ return NOERROR;
+
+ errRtn:
+ CoTaskMemFree(szFile);
+ CoTaskMemFree(szItem);
+ if (pmkFile)
+ pmkFile->Release();
+ if (pmkItem)
+ pmkItem->Release();
+ if (pbc)
+ pbc->Release();
+
+ return hr;
+}
diff --git a/private/ole32/com/moniker2/mnk.h b/private/ole32/com/moniker2/mnk.h
new file mode 100644
index 000000000..f3784359d
--- /dev/null
+++ b/private/ole32/com/moniker2/mnk.h
@@ -0,0 +1,106 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: mnk.h
+//
+// Contents: Internal moniker functions
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-27-93 ErikGav Created
+// 06-14-94 Rickhi Fix type casting
+// 12-01-95 MikeHill Added prototype for ValidateBindOpts().
+//
+//----------------------------------------------------------------------------
+
+INTERNAL_(DWORD) GetMonikerType( LPMONIKER pmk );
+
+// The following APIs determine if the given moniker is of the specified
+// class and if so, return a pointer to the C++ class IN A TYPE SAFE WAY!
+//
+// NEVER do the casting directly, always use these APIs to do it for you!
+
+class CCompositeMoniker;
+class CPointerMoniker;
+class CAntiMoniker;
+class CFileMoniker;
+class CItemMoniker;
+
+INTERNAL_(CCompositeMoniker *) IsCompositeMoniker( LPMONIKER pmk );
+INTERNAL_(CPointerMoniker *) IsPointerMoniker( LPMONIKER pmk );
+INTERNAL_(CAntiMoniker *) IsAntiMoniker( LPMONIKER pmk );
+INTERNAL_(CFileMoniker *) IsFileMoniker( LPMONIKER pmk );
+INTERNAL_(CItemMoniker *) IsItemMoniker( LPMONIKER pmk );
+
+STDAPI Concatenate( LPMONIKER pmkFirst, LPMONIKER pmkRest,
+ LPMONIKER FAR* ppmkComposite );
+
+#define BINDRES_INROTREG 1
+
+#define DEF_ENDSERVER 0xFFFF
+
+// STDAPI CreateOle1FileMoniker(LPWSTR, REFCLSID, LPMONIKER FAR*);
+
+#ifdef _CAIRO_
+extern
+BOOL ValidateBindOpts( const LPBIND_OPTS pbind_opts );
+#endif
+
+extern
+HRESULT DupWCHARString( LPCWSTR lpwcsString,
+ LPWSTR & lpwcsOutput,
+ USHORT & ccOutput);
+extern
+HRESULT ReadAnsiStringStream( IStream *pStm,
+ LPSTR & pszAnsiPath ,
+ USHORT &cbAnsiPath);
+extern
+HRESULT WriteAnsiStringStream( IStream *pStm,
+ LPSTR pszAnsiPath ,
+ ULONG cbAnsiPath);
+extern
+HRESULT MnkMultiToUnicode(LPSTR pszAnsiPath,
+ LPWSTR &pWidePath,
+ ULONG ccWidePath,
+ USHORT &ccNewString,
+ UINT nCodePage);
+extern
+HRESULT
+MnkUnicodeToMulti(LPWSTR pwcsWidePath,
+ USHORT ccWidePath,
+ LPSTR & pszAnsiPath,
+ USHORT & cbAnsiPath,
+ BOOL & fFastConvert);
+
+extern
+DWORD CalcFileMonikerHash(LPWSTR lp);
+
+extern
+BOOL IsAbsoluteNonUNCPath (LPCWSTR szPath);
+
+extern
+BOOL IsAbsolutePath (LPCWSTR szPath);
+
+
+#define WIDECHECK(x) (x?x:L"<NULL>")
+#define ANSICHECK(x) (x?x:"<NULL>")
+
+
+#if DBG == 1
+ DECLARE_DEBUG(mnk)
+# define mnkDebugOut(x) mnkInlineDebugOut x
+# define mnkAssert(x) Win4Assert(x)
+# define mnkVerify(x) mnkAssert(x)
+#else
+# define mnkDebugOut(x)
+# define mnkAssert(x)
+# define mnkVerify(x) x
+
+#endif
+
+#define MNK_P_STREAMOP 0x01000000
+#define MNK_P_RESOURCE 0x02000000
diff --git a/private/ole32/com/moniker2/shellink.hxx b/private/ole32/com/moniker2/shellink.hxx
new file mode 100644
index 000000000..a22736e2b
--- /dev/null
+++ b/private/ole32/com/moniker2/shellink.hxx
@@ -0,0 +1,65 @@
+//===========================================================================
+//
+// IShellLink Interface
+//
+// History: /* ;Internal */
+// --/--/94 ChrisG Created /* ;Internal */
+// /* ;Internal */
+//===========================================================================
+
+// IShellLink::Resolve fFlags
+typedef enum {
+ SLR_NO_UI = 0x0001,
+ SLR_ANY_MATCH = 0x0002,
+ SLR_UPDATE = 0x0004,
+} SLR_FLAGS;
+
+// IShellLink::GetPath fFlags
+typedef enum {
+ SLGP_SHORTPATH = 0x0001,
+ SLGP_UNCPRIORITY = 0x0002,
+} SLGP_FLAGS;
+
+typedef void * LPITEMIDLIST;
+typedef void * LPCITEMIDLIST;
+
+#undef INTERFACE
+#define INTERFACE IShellLink
+
+DECLARE_INTERFACE_(IShellLink, IUnknown) // sl
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ STDMETHOD(GetPath)(THIS_ LPSTR pszFile, int cchMaxPath, WIN32_FIND_DATA *pfd, DWORD fFlags) PURE;
+
+ STDMETHOD(GetIDList)(THIS_ LPITEMIDLIST * ppidl) PURE;
+ STDMETHOD(SetIDList)(THIS_ LPCITEMIDLIST pidl) PURE;
+
+ STDMETHOD(GetDescription)(THIS_ LPSTR pszName, int cchMaxName) PURE;
+ STDMETHOD(SetDescription)(THIS_ LPCSTR pszName) PURE;
+
+ STDMETHOD(GetWorkingDirectory)(THIS_ LPSTR pszDir, int cchMaxPath) PURE;
+ STDMETHOD(SetWorkingDirectory)(THIS_ LPCSTR pszDir) PURE;
+
+ STDMETHOD(GetArguments)(THIS_ LPSTR pszArgs, int cchMaxPath) PURE;
+ STDMETHOD(SetArguments)(THIS_ LPCSTR pszArgs) PURE;
+
+ STDMETHOD(GetHotkey)(THIS_ WORD *pwHotkey) PURE;
+ STDMETHOD(SetHotkey)(THIS_ WORD wHotkey) PURE;
+
+ STDMETHOD(GetShowCmd)(THIS_ int *piShowCmd) PURE;
+ STDMETHOD(SetShowCmd)(THIS_ int iShowCmd) PURE;
+
+ STDMETHOD(GetIconLocation)(THIS_ LPSTR pszIconPath, int cchIconPath, int *piIcon) PURE;
+ STDMETHOD(SetIconLocation)(THIS_ LPCSTR pszIconPath, int iIcon) PURE;
+
+ STDMETHOD(SetRelativePath)(THIS_ LPCSTR pszPathRel, DWORD dwReserved) PURE;
+
+ STDMETHOD(Resolve)(THIS_ HWND hwnd, DWORD fFlags) PURE;
+
+ STDMETHOD(SetPath)(THIS_ LPCSTR pszFile) PURE;
+};
+
diff --git a/private/ole32/com/objact/actapi.cxx b/private/ole32/com/objact/actapi.cxx
new file mode 100644
index 000000000..7c8bf2452
--- /dev/null
+++ b/private/ole32/com/objact/actapi.cxx
@@ -0,0 +1,1373 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: actapi.cxx
+//
+// Contents: Functions that activate objects residing in persistent storage.
+//
+// Functions: CoGetPersistentInstanceEx
+//
+// History: 20-Sep-95 GregJen Created
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+
+#include <iface.h>
+#include <objsrv.h>
+#include <compname.hxx>
+#include "resolver.hxx"
+#include "smstg.hxx"
+#include "objact.hxx"
+#include "clsctx.hxx"
+#include "treat.hxx"
+
+// We use this to calculate the hash value for the path
+extern DWORD CalcFileMonikerHash(LPWSTR pwszPath);
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSplit_QI
+//
+// Synopsis: Helper for splitting a multi_QI block into separate arrays
+//
+// Arguments: [pMqi] - pointer to multi_QI array
+//
+// History: 14-Nov-95 GregJen Created
+//
+// notes: the RPC calls to the SCM take a bunch of arrays, some [in], and
+// some [out]. We get called with an array of structs. This class
+// splits everything out of the array of MULTI_QI structs, and
+// makes arrays for the RPC call parameters.
+//--------------------------------------------------------------------------
+
+class CSplit_QI
+{
+private:
+ PMInterfacePointer SomePMItfPtrs[2];
+ HRESULT SomeHRs[2];
+ IID SomeIIDs[2];
+
+ DWORD _dwCount;
+
+ char * _pAllocBlock;
+
+public:
+ PMInterfacePointer * _pItfArray;
+ HRESULT * _pHrArray;
+ IID * _pIIDArray;
+
+ // we just have a constructor and a destructor
+ CSplit_QI( HRESULT & hr, DWORD count, MULTI_QI * pInputArray );
+
+ ~CSplit_QI();
+
+};
+
+//+-------------------------------------------------------------------------
+//
+// Function: CSplit_QI constructor
+//
+// Synopsis: Helper for allocating the arrays for a multi-qi call
+//
+// Arguments: [hr] - hr to return by reference
+// [count] - number of IIDs requested
+// [pInputArray] - the MULTI_QI structure passed in to us
+//
+// Returns: S_OK - everything set up OK
+//
+// History: 01-Dec-95 GregJen Created
+////
+//--------------------------------------------------------------------------
+CSplit_QI::CSplit_QI( HRESULT & hr, DWORD count, MULTI_QI * pInputArray )
+{
+ _pAllocBlock = NULL;
+ _pItfArray = NULL;
+ _dwCount = count;
+
+ // if they only asked for 1 or 2, save time by just using
+ // our memory on the stack
+ if ( count <= 2 )
+ {
+ _pItfArray = SomePMItfPtrs;
+ _pHrArray = SomeHRs;
+ _pIIDArray = SomeIIDs;
+ for ( DWORD i = 0; i < count; i++ )
+ {
+ _pIIDArray[i] = *(pInputArray[i].pIID);
+ }
+ memset( _pItfArray, 0, sizeof(SomePMItfPtrs) );
+
+ hr = S_OK;
+ return;
+ }
+
+ ULONG ulItfArrSz = count * sizeof( PMInterfacePointer );
+ ULONG ulHRArrSz = count * sizeof( HRESULT );
+ ULONG ulIIDArrSz = count * sizeof( IID );
+
+ _pAllocBlock = (char * )PrivMemAlloc( ulItfArrSz +
+ ulHRArrSz +
+ ulIIDArrSz );
+ if ( _pAllocBlock )
+ {
+ hr = S_OK;
+
+ // carve up the allocated block
+ _pItfArray = (PMInterfacePointer *) _pAllocBlock;
+ _pHrArray = (HRESULT *) (_pAllocBlock +
+ ulItfArrSz );
+ _pIIDArray = (IID * ) ( _pAllocBlock +
+ ulItfArrSz +
+ ulHRArrSz );
+
+ // copy the IIDs and zero the MInterfacePointers
+ for ( DWORD i = 0; i < count; i++ )
+ {
+ _pIIDArray[i] = *(pInputArray[i].pIID);
+ }
+ memset( _pItfArray, 0, ulItfArrSz );
+
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+}
+//+-------------------------------------------------------------------------
+//
+// Function: CSplit_QI destructor
+//
+// Synopsis: Helper for freeing the arrays for a multi-qi call
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: 01-Dec-95 GregJen Created
+//
+//--------------------------------------------------------------------------
+CSplit_QI::~CSplit_QI()
+{
+
+ // make sure to clean up any dangling interface pointers
+ if ( _pItfArray )
+ {
+ for ( DWORD i = 0; i < _dwCount; i++ )
+ {
+ if ( _pItfArray[i] )
+ {
+ CXmitRpcStream xrpc( (InterfaceData*)_pItfArray[i] );
+
+ CoReleaseMarshalData(&xrpc);
+
+ MyMemFree(_pItfArray[i]);
+ _pItfArray[i] = NULL;
+ }
+ }
+ }
+
+ // only do the free if we allocated something
+ if ( _pAllocBlock )
+ {
+ PrivMemFree( _pAllocBlock );
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UpdateResultsArray
+//
+// Synopsis: Helper for returning the correct hr from a multi-qi call
+//
+// Arguments: [hrIn] - hr from the calling function
+// [dwCount] - number of IIDs requested
+// [pResults] - where to put pointer to returned interface
+//
+// Returns: S_OK - All Interface are OK
+//
+// History: 30-Aug-95 GregJen Created
+////
+//--------------------------------------------------------------------------
+inline
+HRESULT
+UpdateResultsArray( HRESULT hrIn, DWORD dwCount, MULTI_QI * pResults )
+{
+ HRESULT hr = hrIn;
+ DWORD i;
+
+ // make sure the HR is set correctly
+ if ( SUCCEEDED( hrIn ) )
+ {
+ // assume no interfaces were found
+ DWORD dwFound = 0;
+ for ( i=0; i<dwCount; i++ )
+ {
+ if ( FAILED( pResults[i].hr ) )
+ pResults[i].pItf = NULL;
+ else
+ {
+ dwFound++;
+ Win4Assert(pResults[i].pItf != NULL );
+ }
+ }
+
+ if ( dwFound == 0 )
+ {
+ // if there was only 1 interface, return its hr.
+ if ( dwCount == 1 )
+ hr = pResults[0].hr;
+ else
+ hr = E_NOINTERFACE;
+ }
+ else if ( dwFound < dwCount )
+ hr = CO_S_NOTALLINTERFACES;
+
+ }
+ else
+ {
+ // failed - set all the hr's to the overall failure code,
+ // and clean up any interface pointers we got
+ for ( i=0; i<dwCount; i++ )
+ {
+ if ( pResults[i].pItf )
+ pResults[i].pItf->Release();
+ pResults[i].pItf = NULL;
+ pResults[i].hr = hr;
+ }
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DoBetterUnmarshal
+//
+// Synopsis: Helper for unmarshaling an interface from remote
+//
+// Arguments: [pIFD] - serialized interface reference returned by SCM
+// [riid] - interface ID requested by application
+// [ppvUnk] - where to put pointer to returned interface
+//
+// Returns: S_OK - Interface unmarshaled
+//
+// Algorithm: Convert marshaled data to a stream and then unmarshal
+// to the right interface
+//
+//
+// History: 11-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline
+HRESULT DoBetterUnmarshal(MInterfacePointer *&pIFD, REFIID riid, IUnknown **ppvUnk)
+{
+ // Convert returned interface to a stream
+ CXmitRpcStream xrpc( (InterfaceData*)pIFD );
+
+ HRESULT hr = CoUnmarshalInterface(&xrpc, riid, (void **) ppvUnk);
+
+ //CODEWORK: Stress revealed CoGetClassObject returning a null class factory
+ // and S_OK
+ Win4Assert(((hr == S_OK && *ppvUnk != NULL) ||
+ (hr != S_OK && *ppvUnk == NULL))
+ && "DoBetterUnmarshal QueryInterface failure");
+
+ MyMemFree(pIFD);
+ pIFD = NULL;
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UnmarshalMultipleSCMResults
+//
+// Synopsis: Common routine for dealing with results from SCM
+//
+// Arguments: [sc] - SCODE returned by SCM
+// [pIFD] - serialized interface reference returned by SCM
+// [riid] - interface ID requested by application
+// [ppunk] - where to put pointer to returned interface
+// [pwszDllPath] - path to DLL if there is one.
+// [ppunk] - pointer to returned interface.
+// [usMethodOrdinal] - method for error reporting
+//
+// Returns: TRUE - processing is complete for the call
+// FALSE - this is a DLL and client needs to instantiate.
+//
+// Algorithm: If the SCODE indicates a failure, then this sets an
+// SCODE indicating that the service controller returned
+// an error and propagates the result from the SCM. Otherwise,
+// if the SCM has returned a result indicating that a
+// handler has been returned, the handler DLL is cached.
+// If a marshaled interface has been returned, then that is
+// unmarshaled. If an inprocess server has been returned,
+// the DLL is cached and the class object is created.
+//
+// History: 11-May-93 Ricksa Created
+//
+// Notes: This routine is simply a helper for CoGetPersistentInstance.
+//
+//--------------------------------------------------------------------------
+BOOL UnmarshalMultipleSCMResults(
+ HRESULT& hr,
+ PMInterfacePointer *pItfArray,
+ DWORD dwContext,
+ REFCLSID rclsid,
+ IUnknown * punkOuter,
+ DWORD dwCount,
+ IID * pIIDs,
+ HRESULT * pHrArray,
+ MULTI_QI * pResults,
+ DWORD dwDllThreadModel,
+ WCHAR *pwszDllPath,
+ IClassFactory **ppvCf)
+{
+ BOOL fResult = TRUE;
+ DWORD i;
+ HRESULT hr2;
+ IUnknown * pUnk;
+
+ if (SUCCEEDED(hr))
+ {
+ // Flag for fall through from a 16 bit case
+ BOOL f16BitFallThru = FALSE;
+ // Flag for fall through from got-handler
+ BOOL fGetClassObject = FALSE;
+ BOOL fHandlerAndServer = FALSE;
+
+ switch (hr)
+ {
+#ifdef GET_INPROC_FROM_SCM
+ case SCM_S_HANDLER16:
+ CairoleDebugOut((DEB_ACTIVATE,
+ "16-bit InprocHandler\n"));
+
+ // Note: if the process is a 32 bit process and the
+ // DLL is a 16 bit DLL, the load will fail. Since
+ // we assume that this is a fairly rare case, we
+ // let the lower level code discover this.
+
+ f16BitFallThru = TRUE;
+
+#ifdef WX86OLE
+ case SCM_S_HANDLERX86:
+#endif
+ case SCM_S_HANDLER:
+ CairoleDebugOut((DEB_ACTIVATE,
+ "InprocHandler(%ws)\n",pwszDllPath));
+
+ // Just in case we chicken out and back out our changes
+ if (!f16BitFallThru)
+ {
+ // Validate that 32 bit handler DLL is being loaded
+ // in the correct process.
+ hr = CheckScmHandlerResult(pwszDllPath);
+
+ if (hr != NOERROR)
+ {
+ break;
+ }
+ }
+
+ // Figure out if we really need the class object for the
+ // handler. Otherwise we will just put it in the cache
+ // and unmarshal the class object.
+ fGetClassObject =
+ (dwContext & CLSCTX_INPROC_HANDLER) ? TRUE : FALSE;
+
+/***
+#else // GET_INPROC_FROM_SCM
+ // Only time we should be in this path is when we called the
+ // SCM for non-INPROC and get advised that a handler exists
+ fGetClassObject = FALSE;
+ ***/
+
+ // Store the handler returned
+ pUnk = gdllcacheHandler.Add(rclsid, IID_IClassFactory,
+ dwDllThreadModel, pwszDllPath, fGetClassObject,
+ (hr == SCM_S_HANDLER16),
+#ifdef WX86OLE
+ (hr == SCM_S_HANDLERX86),
+#endif
+ hr);
+
+ if (FAILED(hr))
+ {
+ return TRUE;
+ }
+
+ if (fGetClassObject)
+ {
+ // Request was really for a handler so we are done.
+ *ppvCf = (IClassFactory*) pUnk;
+ fResult = FALSE;
+ break;
+ }
+
+ // We got a handler back but we have just cached it to make
+ // processing faster when we create a real instance of an
+ // object. So we unmarshal the real object.
+ fHandlerAndServer = TRUE;
+#endif // GET_INPROC_FROM_SCM
+
+ case S_OK :
+ if ( punkOuter && !fHandlerAndServer )
+ return CLASS_E_NOAGGREGATION;
+
+ for ( i=0; i<dwCount; i++, pResults++ )
+ {
+
+ pResults->hr = pHrArray[i];
+
+ if ( SUCCEEDED( pHrArray[i] ) )
+ {
+ hr2 = DoBetterUnmarshal( pItfArray[i],
+ *(pResults->pIID),
+ &pResults->pItf);
+
+
+
+ // ... and try to set the overall HR correctly
+ pResults->hr = hr2;
+ if ( FAILED( hr2 ) )
+ hr = CO_S_NOTALLINTERFACES;
+ }
+ else
+ hr = CO_S_NOTALLINTERFACES;
+
+ }
+ break;
+
+#ifdef GET_INPROC_FROM_SCM
+ case SCM_S_INPROCSERVER16:
+ CairoleDebugOut((DEB_ACTIVATE, "16-bit InprocServer\n"));
+
+#ifdef WX86OLE
+ case SCM_S_INPROCSERVERX86:
+#endif
+ case SCM_S_INPROCSERVER:
+ CairoleDebugOut((DEB_ACTIVATE, "InprocServer(%ws)\n",pwszDllPath));
+
+ // Just in case we chicken out and back out our changes
+ // This is an inprocesses server -- we want cache that information
+ // and do the work of instantiating an object.
+ *ppvCf = (IClassFactory*) gdllcacheInprocSrv.Add(rclsid, IID_IClassFactory,
+ dwDllThreadModel, pwszDllPath, TRUE,
+ (hr == SCM_S_INPROCSERVER16),
+#ifdef WX86OLE
+ (hr == SCM_S_INPROCSERVERX86),
+#endif
+ hr);
+
+ // If we actually got an inproc server object successfully
+ // then we want to continue processing otherwise we can
+ // just return the error that occurred.
+ if (SUCCEEDED(hr))
+ {
+ fResult = FALSE;
+ }
+#else // GET_INPROC_FROM_SCM
+ // Error: Should never come here as we handled INPROC_SERVERS
+ // before calling SCM
+ Win4Assert((FALSE) && "UnmarshalMultipleSCMResults: SCM_S_INPROC return from SCM");
+#endif // GET_INPROC_FROM_SCM
+ }
+ }
+
+ return fResult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoGetInstanceFromFile
+//
+// Synopsis: Returns an instantiated interface to an object whose
+// stored state resides on disk.
+//
+// Arguments: [pServerInfo] - server information block
+// [dwCtrl] - kind of server required
+// [grfMode] - how to open the storage if it is a file.
+// [pwszName] - name of storage if it is a file.
+// [pstg] - IStorage to use for object
+// [pclsidOverride]
+// [ppvUnk] - where to put bound interface pointer
+//
+// Returns: S_OK - object bound successfully
+// MISSING
+//--------------------------------------------------------------------------
+
+STDAPI CoGetInstanceFromFile(
+ COSERVERINFO * pServerInfo,
+ CLSID * pclsidOverride,
+ IUnknown * punkOuter, // only relevant locally
+ DWORD dwClsCtx,
+ DWORD grfMode,
+ OLECHAR * pwszName,
+ DWORD dwCount,
+ MULTI_QI * pResults )
+{
+ TRACECALL(TRACE_ACTIVATION, "CoGetInstanceFromFile");
+
+#ifdef DCOM
+ if ( pServerInfo &&
+ ( ! IsValidPtrIn( pServerInfo, sizeof(COSERVERINFO) ) ||
+ pServerInfo->dwReserved1 ||
+ pServerInfo->dwReserved2 ) )
+#else
+ if ( pServerInfo )
+#endif
+ return E_INVALIDARG;
+
+ return GetInstanceHelper( pServerInfo,
+ pclsidOverride,
+ punkOuter,
+ dwClsCtx,
+ grfMode,
+ pwszName,
+ NULL,
+ dwCount,
+ pResults );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoGetInstanceFromIStorage
+//
+// Synopsis: Returns an instantiated interface to an object whose
+// stored state resides on disk.
+//
+// Arguments: [pServerInfo] - server information block
+// [dwCtrl] - kind of server required
+// [grfMode] - how to open the storage if it is a file.
+// [pwszName] - name of storage if it is a file.
+// [pstg] - IStorage to use for object
+// [pclsidOverride]
+// [ppvUnk] - where to put bound interface pointer
+//
+// Returns: S_OK - object bound successfully
+// MISSING
+//
+//--------------------------------------------------------------------------
+
+STDAPI CoGetInstanceFromIStorage(
+ COSERVERINFO * pServerInfo,
+ CLSID * pclsidOverride,
+ IUnknown * punkOuter, // only relevant locally
+ DWORD dwClsCtx,
+ struct IStorage * pstg,
+ DWORD dwCount,
+ MULTI_QI * pResults )
+{
+
+ STATSTG statstg;
+ CLSID clsid;
+ HRESULT hr;
+
+ TRACECALL(TRACE_ACTIVATION, "CoGetInstanceFromIStorage");
+
+#ifdef DCOM
+ if ( pServerInfo &&
+ ( ! IsValidPtrIn( pServerInfo, sizeof(COSERVERINFO) ) ||
+ pServerInfo->dwReserved1 ||
+ pServerInfo->dwReserved2 ) )
+#else
+ if ( pServerInfo )
+#endif
+ return E_INVALIDARG;
+
+ statstg.pwcsName = 0;
+
+ hr = pstg->Stat(&statstg, STATFLAG_DEFAULT);
+
+ if ( FAILED(hr) )
+ return hr;
+
+ if ( pclsidOverride == NULL )
+ clsid = statstg.clsid;
+ else
+ clsid = *pclsidOverride;
+
+ hr = GetInstanceHelper( pServerInfo,
+ pclsidOverride,
+ punkOuter,
+ dwClsCtx,
+ statstg.grfMode,
+ statstg.pwcsName,
+ pstg,
+ dwCount,
+ pResults );
+
+ PrivMemFree( statstg.pwcsName );
+
+ return hr;
+}
+
+HRESULT GetInstanceHelper(
+ COSERVERINFO * pServerInfo,
+ CLSID * pclsidOverride,
+ IUnknown * punkOuter, // only relevant locally
+ DWORD dwClsCtx,
+ DWORD grfMode,
+ OLECHAR * pwszName,
+ struct IStorage * pstg,
+ DWORD dwCount,
+ MULTI_QI * pResults )
+{
+ if (!IsApartmentInitialized())
+ return CO_E_NOTINITIALIZED;
+
+ IUnknown *punk;
+
+ WCHAR awcNameBuf[MAX_PATH];
+ WCHAR * pwszNameUNC = awcNameBuf;
+ WCHAR awcServer[MAX_PATH];
+ WCHAR * pwszServer = awcServer;
+
+ DWORD dwDllServerType = IsSTAThread() ? APT_THREADED : FREE_THREADED;
+ IClassFactory * pcf;
+ HRESULT hr = E_FAIL;
+ BOOL fExitBlock;
+ BOOL bFileWasOpened;
+ DWORD i; // handy iterator
+
+ // Make sure input request is at least slightly logical
+ if ( ((pwszName == NULL) && (pstg == NULL))
+ || ((dwClsCtx & ~CLSCTX_VALID_MASK) != 0)
+ || ( dwCount < 1 )
+ || ( pResults == NULL ) )
+ {
+ return E_INVALIDARG;
+ }
+
+ // check the MULTI_QI for validity (and clear out the hresults)
+ for ( i=0; i<dwCount; i++ )
+ {
+ if ( pResults[i].pItf || !pResults[i].pIID )
+ {
+ hr = E_INVALIDARG;
+ goto final_exit;
+ }
+ pResults[i].hr = E_NOINTERFACE;
+ }
+
+ bFileWasOpened = FALSE;
+
+ CLSID clsid;
+ if (pwszName)
+ {
+ // If there is a path supplied convert it to a normalized form
+ // so it can be used by any process in the net.
+ hr = ProcessPath(pwszName, &pwszNameUNC, &pwszServer);
+
+ if (FAILED(hr))
+ {
+ goto exit_point;
+ }
+
+ // Limit on loops for retrying to get class of object
+ DWORD cGetClassRetries = 0;
+
+ // We loop here looking for either the running object or
+ // for the class of the file. We do this because there
+ // are race conditions where the can be starting or stopping
+ // and the class of the object might not be available because
+ // of the opening mode of the object's server.
+ do
+ {
+ // Look in the ROT first to see if we need to bother
+ // looking up the class of the file.
+
+ if (GetObjectFromRotByPath(pwszName,
+ (IUnknown **) &punk) == S_OK)
+ {
+ // Got object from ROT so we are done.
+ goto qiexit_point;
+ }
+
+ // Try to get the class of the file
+ if ( pclsidOverride != NULL )
+ {
+ clsid = *pclsidOverride;
+ hr = S_OK;
+ }
+ else
+ {
+ hr = GetClassFile(pwszName, &clsid);
+ bFileWasOpened = TRUE;
+ }
+
+
+ if (hr == STG_E_ACCESSDENIED)
+ {
+ // The point here of the sleep is to try to let the
+ // operation that is holding the class id unavailable
+ // complete.
+ Sleep(GET_CLASS_RETRY_SLEEP_MS);
+ continue;
+ }
+
+ // Either we succeeded or something other than error
+ // access denied occurred here. For all these cases
+ // we break the loop.
+ break;
+
+ } while (cGetClassRetries++ < GET_CLASS_RETRY_MAX);
+
+ if (FAILED(hr))
+ {
+ // If we were unable to determine the classid, and the
+ // caller provided one as a Ole1 clsid, try loading it
+ // If it succeeds, then return
+
+ if (pclsidOverride != NULL)
+ {
+ goto dde_exit;
+ }
+
+ goto final_exit;
+ }
+ }
+
+ CLSID tmpClsid;
+
+ hr = OleGetAutoConvert(clsid, &tmpClsid);
+ if ( ( hr == REGDB_E_KEYMISSING ) || ( hr == REGDB_E_CLASSNOTREG ) )
+ {
+ // do nothing
+ }
+ else if ( FAILED(hr) )
+ {
+ goto exit_point;
+ }
+ else
+ {
+ clsid = tmpClsid;
+ }
+
+ hr = GetTreatAs(clsid, clsid);
+ if ( FAILED(hr) )
+ {
+ goto exit_point;
+ }
+
+ // Make sure we are asking for the correct inproc server
+ dwClsCtx = RemapClassCtxForInProcServer(dwClsCtx);
+
+ //
+ // If this is a OLE 1.0 class, then do a DdeBindToObject on it,
+ // and return.
+ //
+ if (CoIsOle1Class(clsid))
+ {
+ if (pwszName != NULL)
+ {
+ goto dde_exit;
+ }
+ else
+ {
+ //
+ // Something is fishy here. We don't have a pwszName,
+ // yet CoIsOle1Class returned the class as an ole1 class.
+ // To get to this point without a pwszName, there must have
+ // been a pstg passed into the API.
+ //
+ // This isn't supposed to happen. To recover, just fall
+ // through and load the class as an OLE 2.0 class
+ //
+ CairoleDebugOut((DEB_ERROR,
+ "CoIsOle1Class is TRUE on a storage!\n"));
+ }
+ }
+
+
+ // At this point, we know the clsid we want to activate
+ pcf = (IClassFactory *)
+ SearchCacheOrLoadInProc(clsid,
+ IID_IClassFactory,
+ (pwszServer != NULL),
+ FALSE,
+ dwClsCtx,
+ dwDllServerType,
+ hr);
+
+ if ( pcf ==NULL )
+ {
+ // Marshal pstg since SCM can't deal with unmarshaled objects
+ CSafeStgMarshaled MarshalledStg(pstg, MSHCTX_DIFFERENTMACHINE, hr);
+ MInterfacePointer * pMrshlStg;
+
+ if ( pstg == 0 )
+ pMrshlStg = 0;
+ else
+ pMrshlStg = MarshalledStg;
+
+ if (FAILED(hr))
+ goto exit_point;
+
+ // split the array of structs into individual arrays
+ CSplit_QI SplitQI( hr, dwCount, pResults );
+
+ DWORD cLoops = 0;
+ BOOL FoundInROT;
+
+#ifndef GET_INPROC_FROM_SCM
+ // Just in case we chicken out and back out our changes
+ dwClsCtx &= ~(CLSCTX_INPROC_SERVERS | CLSCTX_INPROC_HANDLERS); // make sure we don't ask for inproc stuff
+#endif // GET_INPROC_FROM_SCM
+
+ do
+ {
+ hr = gResolver.GetPersistentInstance( pServerInfo,
+ &clsid,
+ dwClsCtx,
+ grfMode,
+ bFileWasOpened,
+ pwszName,
+ pMrshlStg,
+ dwCount,
+ SplitQI._pIIDArray,
+ &FoundInROT,
+ SplitQI._pItfArray,
+ SplitQI._pHrArray,
+ &dwDllServerType,
+ &pwszServer );
+
+ fExitBlock = UnmarshalMultipleSCMResults(hr,
+ SplitQI._pItfArray,
+ dwClsCtx,
+ clsid,
+ punkOuter,
+ dwCount,
+ SplitQI._pIIDArray,
+ SplitQI._pHrArray,
+ pResults,
+ dwDllServerType,
+ pwszServer,
+ &pcf);
+
+ // If we get something from the ROT, we need to retry until
+ // we get an object. Because objects can disappear from the
+ // ROT async to us, we need to retry a few times. But since
+ // this theoretically could happen forever, we place an arbitrary
+ // limit on the number of retries to the ROT.
+ } while( (hr != NOERROR)
+ && (FoundInROT)
+ && (++cLoops < 5));
+
+ }
+
+ if ( pcf )
+ {
+ // Create the instance and do the qi's
+ hr = GetObjectHelperMulti( pcf,
+ grfMode,
+ punkOuter,
+ pwszName,
+ pstg,
+ dwCount,
+ NULL,
+ NULL,
+ NULL,
+ pResults );
+
+ pcf->Release();
+ }
+
+exit_point:
+
+ hr = UpdateResultsArray( hr, dwCount, pResults );
+
+final_exit:
+ if ( pwszServer != awcServer )
+ PrivMemFree( pwszServer );
+
+ return hr;
+
+dde_exit:
+ if (hr != MK_E_CANTOPENFILE)
+ {
+ COleTls Tls;
+ if( Tls->dwFlags & OLETLS_DISABLE_OLE1DDE )
+ {
+ // If this app doesn't want or can tolerate having a DDE
+ // window then currently it can't use OLE1 classes because
+ // they are implemented using DDE windows.
+ //
+ hr = CO_E_OLE1DDE_DISABLED;
+ goto final_exit;
+ }
+
+ hr = DdeBindToObject(pwszName,
+ clsid,
+ FALSE,
+ IID_IUnknown,
+ (void **)&punk);
+
+ if (FAILED(hr))
+ goto final_exit;
+ }
+ // FALLTHRU to qi exit point
+
+qiexit_point:
+ // Get the requested interfaces
+ for ( i = 0; i<dwCount; i++ )
+ {
+ pResults[i].hr = punk->QueryInterface(*(pResults[i].pIID),
+ (void**)&pResults[i].pItf );
+ }
+ punk->Release();
+
+ // Got object from ROT so we are done.
+ goto exit_point;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ICoGetClassObject
+//
+// Synopsis: Internal entry point that returns an instantiated class object
+//
+// Arguments: [rclsid] - class id for class object
+// [dwContext] - kind of server we wish
+// [pvReserved] - Reserved
+// [riid] - interface to bind class object
+// [ppvClassObj] - where to put interface pointer
+//
+// Returns: S_OK - successfully bound class object
+//
+// Algorithm: First, the context is validated. Then we try to use
+// any cached information by looking up either cached in
+// process servers or handlers based on the context.
+// If no cached information suffices, we call the SCM
+// to find out what to use. If the SCM returns a handler
+// or an inprocess server, we cache that information.
+// If the class is implemented by a local server, then
+// the class object is unmarshaled. Otherwise, the object
+// is instantiated locally using the returned DLL.
+//
+//
+// History: 15-Nov-94 Ricksa Split into external and internal calls
+//
+//
+//--------------------------------------------------------------------------
+STDAPI ICoGetClassObject(
+ REFCLSID rclsid,
+ DWORD dwContext,
+ COSERVERINFO * pServerInfo,
+ REFIID riid,
+ void FAR* FAR* ppvClassObj)
+{
+ TRACECALL(TRACE_ACTIVATION, "CoGetClassObject");
+
+ IUnknown *punk = NULL;
+ HRESULT hr = S_OK;
+ WCHAR *pwszDllToLoad = NULL;
+ MInterfacePointer *pIFD = NULL;
+ CLSID clsid;
+ DWORD dwDllServerType = IsSTAThread() ? APT_THREADED : FREE_THREADED;
+
+#ifdef DCOM
+ if ( pServerInfo &&
+ ( ! IsValidPtrIn( pServerInfo, sizeof(COSERVERINFO) ) ||
+ pServerInfo->dwReserved1 ||
+ pServerInfo->dwReserved2 ) )
+#else
+ if ( pServerInfo )
+#endif
+ return E_INVALIDARG;
+
+ BEGIN_BLOCK
+
+ // IsInternalCLSID will also check to determine if the CLSID is
+ // an OLE 1.0 CLSID, in which case we get back our internal
+ // class factory.
+
+ if (IsInternalCLSID(rclsid, riid, hr, ppvClassObj))
+ {
+ // this is an internally implemented clsid, or an OLE 1.0 class
+ // so we already got the class factory (if available) and set
+ // the return code appropriately.
+ EXIT_BLOCK;
+ }
+
+ if (FAILED(hr = GetTreatAs(rclsid, clsid)))
+ {
+ EXIT_BLOCK;
+ }
+
+ punk = SearchCacheOrLoadInProc(clsid,
+ riid,
+ FALSE,
+ FALSE,
+ dwContext,
+ dwDllServerType,
+ hr);
+
+ // If still don't have a punk, go to the scm
+ if (!punk)
+ {
+ // Ask the service controller for the class object
+#ifndef GET_INPROC_FROM_SCM
+ // Just in case we chicken out and back out our changes
+ dwContext &= ~(CLSCTX_INPROC_SERVERS | CLSCTX_INPROC_HANDLERS); //
+#endif // GET_INPROC_FROM_SCM
+ hr = gResolver.GetClassObject(clsid, dwContext, (IID *)&riid,
+ pServerInfo, &pIFD, &dwDllServerType, &pwszDllToLoad);
+
+ // A proxy/stub DLL needs to be loaded as both no matter what
+ if (dwContext & CLSCTX_PS_DLL)
+ {
+ dwDllServerType = BOTH_THREADED;
+ }
+
+ if (FAILED(hr))
+ {
+ EXIT_BLOCK;
+ }
+
+ // Flag for special handler behavior
+ BOOL fGetClassObject;
+
+ // Flag for fall through from a 16 bit case
+ BOOL f16BitFallThru = FALSE;
+
+ switch (hr)
+ {
+#ifdef GET_INPROC_FROM_SCM
+ case SCM_S_HANDLER16:
+ CairoleDebugOut((DEB_ACTIVATE,
+ "16-bit InprocHandler\n"));
+
+ // Note: if the process is a 32 bit process and the
+ // DLL is a 16 bit DLL, the load will fail. Since
+ // we assume that this is a fairly rare case, we
+ // let the lower level code discover this.
+
+ f16BitFallThru = TRUE;
+
+#ifdef WX86OLE
+ case SCM_S_HANDLERX86:
+#endif
+ case SCM_S_HANDLER:
+ CairoleDebugOut((DEB_ACTIVATE,
+ "InprocHandler(%ws)\n",pwszDllToLoad));
+
+ // Just in case we chicken out and back out our changes
+ if (!f16BitFallThru)
+ {
+ // Validate that 32 bit handler DLL is being loaded
+ // in the correct process.
+ hr = CheckScmHandlerResult(pwszDllToLoad);
+
+ if (hr != NOERROR)
+ {
+ break;
+ }
+ }
+
+ // Figure out if we really need the class object for the
+ // handler. Otherwise we will just put it in the cache
+ // and unmarshal the class object.
+ fGetClassObject =
+ (dwContext & CLSCTX_INPROC_HANDLER) ? TRUE : FALSE;
+
+/***
+#else // GET_INPROC_FROM_SCM
+ // Only time we should be in this path is when we called the
+ // SCM for non-INPROC and get advised that a handler exists
+ fGetClassObject = FALSE;
+ ***/
+
+ // Store the handler returned
+ punk = gdllcacheHandler.Add(clsid, riid, dwDllServerType,
+ pwszDllToLoad, fGetClassObject,
+ (hr == SCM_S_HANDLER16),
+#ifdef WX86OLE
+ (hr == SCM_S_HANDLERX86),
+#endif
+ hr);
+
+ if (fGetClassObject)
+ {
+ // Request was really for a handler so we are done.
+ break;
+ }
+
+ // We got a handler back but we have just cached it to make
+ // processing faster when we create a real instance of an
+ // object. So we unmarshal the real object.
+
+#endif // GET_INPROC_FROM_SCM
+ case S_OK :
+
+ //hr = DoUnmarshal((InterfaceData*)pIFD, riid,(void**) &punk);
+ hr = DoBetterUnmarshal(pIFD, riid, &punk);
+ break;
+
+
+#ifdef GET_INPROC_FROM_SCM
+ case SCM_S_INPROCSERVER16:
+ CairoleDebugOut((DEB_ACTIVATE,
+ "16-bit InprocServer\n"));
+
+#ifdef WX86OLE
+ case SCM_S_INPROCSERVERX86:
+#endif
+ case SCM_S_INPROCSERVER:
+ CairoleDebugOut((DEB_ACTIVATE,
+ "InprocServer(%ws)\n",pwszDllToLoad));
+
+ // Just in case we chicken out and back out our changes
+ // In process server for class object
+ punk = gdllcacheInprocSrv.Add(clsid, riid, dwDllServerType,
+ pwszDllToLoad, TRUE,(hr == SCM_S_INPROCSERVER16),
+#ifdef WX86OLE
+ (hr == SCM_S_INPROCSERVERX86),
+#endif
+ hr);
+#else // GET_INPROC_FROM_SCM
+ // Error: Should never come here as we handled INPROC_SERVERS
+ // before calling SCM
+ Win4Assert((FALSE) && "IOldCoGetClassObject: SCM_S_INPROC return from SCM");
+#endif // GET_INPROC_FROM_SCM
+ }
+ }
+
+ *ppvClassObj = punk;
+ if ((punk == NULL) && SUCCEEDED(hr))
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ END_BLOCK;
+
+ if (pwszDllToLoad != NULL)
+ {
+ MyMemFree(pwszDllToLoad);
+ }
+
+ CALLHOOKOBJECTCREATE(hr,clsid,riid,(IUnknown **)ppvClassObj);
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoCreateInstanceEx
+//
+// Synopsis: Returns an instantiated interface to an object
+//
+//
+// Arguments: [Clsid] - requested CLSID
+// [pServerInfo] - server information block
+// [punkOuter] - controlling unknown for aggregating
+// [dwCtrl] - kind of server required
+// [dwCount] - count of interfaces
+// [pResults] - MULTI_QI struct of interfaces
+//
+// Returns: S_OK - object bound successfully
+// MISSING
+//
+//
+//--------------------------------------------------------------------------
+
+STDAPI CoCreateInstanceEx(
+ REFCLSID Clsid,
+ IUnknown * punkOuter, // only relevant locally
+ DWORD dwClsCtx,
+ COSERVERINFO * pServerInfo,
+ DWORD dwCount,
+ MULTI_QI * pResults )
+{
+ TRACECALL(TRACE_ACTIVATION, "CoCreateInstanceEx");
+
+ if (!IsApartmentInitialized())
+ return CO_E_NOTINITIALIZED;
+
+ WCHAR awcNameBuf[MAX_PATH];
+ WCHAR * pwszNameUNC = awcNameBuf;
+ WCHAR awcServer[MAX_PATH];
+ WCHAR * pwszServer = awcServer;
+
+ DWORD dwDllServerType = IsSTAThread() ? APT_THREADED : FREE_THREADED;
+ IClassFactory * pcf = NULL;
+ HRESULT hr;
+ BOOL fExitBlock;
+ DWORD i;
+#ifdef WX86OLE
+ BOOL fPunkIsProxy;
+#endif
+
+#ifdef DCOM
+ if ( pServerInfo &&
+ ( ! IsValidPtrIn( pServerInfo, sizeof(COSERVERINFO) ) ||
+ pServerInfo->dwReserved1 ||
+ pServerInfo->dwReserved2 ) )
+#else
+ if ( pServerInfo )
+#endif
+ return E_INVALIDARG;
+
+ // Make sure input request is at least slightly logical
+ if ( ((dwClsCtx & ~CLSCTX_VALID_MASK) != 0)
+ || ( dwCount < 1 )
+ || ( pResults == NULL ) )
+ {
+ hr = E_INVALIDARG;
+ goto final_exit;
+ }
+
+ // check the MULTI_QI for validity (and clear out the hresults)
+ for ( i=0; i<dwCount; i++ )
+ {
+ if ( pResults[i].pItf || !pResults[i].pIID )
+ {
+ hr = E_INVALIDARG;
+ goto final_exit;
+ }
+ pResults[i].hr = E_NOINTERFACE;
+ }
+
+ CLSID realclsid;
+
+ hr = GetTreatAs(Clsid, realclsid);
+ if ( FAILED(hr) )
+ {
+ goto exit_point;
+ }
+
+ // Make sure we are asking for the correct inproc server
+ dwClsCtx = RemapClassCtxForInProcServer(dwClsCtx);
+
+ // IsInternalCLSID will also check to determine if the CLSID is
+ // an OLE 1.0 CLSID, in which case we get back our internal
+ // class factory.
+
+ if (IsInternalCLSID(Clsid, IID_IClassFactory, hr, (void **)&pcf))
+ {
+ // this is an internally implemented clsid, or an OLE 1.0 class
+ // so we already got the class factory (if available) and set
+ // the return code appropriately.
+ ;
+ }
+ else
+ {
+ // At this point, we know the clsid we want to activate
+ pcf = (IClassFactory *)
+ SearchCacheOrLoadInProc(realclsid,
+ IID_IClassFactory,
+ (pwszServer != NULL),
+ FALSE,
+ dwClsCtx,
+ dwDllServerType,
+ hr);
+ }
+
+ if ( pcf == NULL )
+ {
+ // split the array of structs into individual arrays
+ CSplit_QI SplitQI( hr, dwCount, pResults );
+
+ if ( FAILED(hr) )
+ goto exit_point;
+
+#ifndef GET_INPROC_FROM_SCM
+ // Just in case we chicken out and back out our changes
+ dwClsCtx &= ~(CLSCTX_INPROC_SERVERS | CLSCTX_INPROC_HANDLERS); // make sure we don't ask for inproc stuff
+#endif // GET_INPROC_FROM_SCM
+
+ hr = gResolver.CreateInstance(pServerInfo,
+ &realclsid,
+ dwClsCtx,
+ dwCount,
+ SplitQI._pIIDArray,
+ SplitQI._pItfArray,
+ SplitQI._pHrArray,
+ &dwDllServerType,
+ &pwszServer);
+
+
+ fExitBlock = UnmarshalMultipleSCMResults(hr,
+ SplitQI._pItfArray,
+ dwClsCtx,
+ realclsid,
+ punkOuter,
+ dwCount,
+ SplitQI._pIIDArray,
+ SplitQI._pHrArray,
+ pResults,
+ dwDllServerType,
+ pwszServer,
+ &pcf);
+
+ if (fExitBlock)
+ goto exit_point;
+ }
+
+ // if we loaded it inproc, get the interfaces
+ if ( pcf )
+ {
+ IUnknown * pUnk;
+ HRESULT hr2;
+
+#ifdef WX86OLE
+ // If we are calling through the wx86 thunk layer then set a
+ // flag that to let it know that ole32 is calling and let any
+ // custom interface that was specified for an out parameter to
+ // x86 code via an api be thunked as IUnknown since we know it
+ // will just be returned back to x86 code.
+ fPunkIsProxy = gcwx86.IsN2XProxy(pcf);
+ if (fPunkIsProxy)
+ {
+ gcwx86.SetStubInvokeFlag((UCHAR)-1);
+ }
+#endif
+ // ask for the first interface (we'll use it as our IUnknown)
+ hr = pcf->CreateInstance(punkOuter,*(pResults[0].pIID), (void**) &pUnk );
+
+ // note that we don't need the pcf anymore, whether there is an
+ // error or not.
+ pcf->Release();
+
+ if ( FAILED(hr) )
+ goto exit_point;
+
+ for ( i=0; i<dwCount; i++ )
+ {
+#ifdef WX86OLE
+ // If we are calling through the wx86 thunk layer then set a
+ // flag that to let it know that ole32 is calling and let any
+ // custom interface that was specified for an out parameter to
+ // x86 code via an api be thunked as IUnknown since we know it
+ // will just be returned back to x86 code.
+ if (fPunkIsProxy)
+ {
+ gcwx86.SetStubInvokeFlag((UCHAR)-1);
+ }
+#endif
+ hr2 = pUnk->QueryInterface( *(pResults[i].pIID),
+ (void**)&pResults[i].pItf );
+ pResults[i].hr = hr2;
+
+ }
+ pUnk->Release();
+ // rely on the UpdateResultsArray to count up failed QI's
+ }
+
+
+exit_point:
+ hr = UpdateResultsArray( hr, dwCount, pResults );
+
+final_exit:
+ if ( pwszServer != awcServer )
+ PrivMemFree( pwszServer );
+
+ return hr;
+
+}
diff --git a/private/ole32/com/objact/cobjact.cxx b/private/ole32/com/objact/cobjact.cxx
new file mode 100644
index 000000000..1b5f19e1f
--- /dev/null
+++ b/private/ole32/com/objact/cobjact.cxx
@@ -0,0 +1,1452 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: cobjact.cxx
+//
+// Contents: Functions that activate objects residing in persistent storage.
+//
+// Functions: UnmarshalSCMResult
+// CoGetPersistentInstance
+// CoGetClassObject
+//
+// History: 11-May-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+// 07-Apr-94 BruceMa Fixed parameter (#5573)
+// 02-May-94 BruceMa CoGetPersistentInstance could return
+// wrong interface
+// 24-Jun-94 BruceMa Memory allocation check
+// 07-Jul-94 BruceMa UnmarshalSCMResult mem alloc check
+// 28-Jul-94 BruceMa Memory sift fix
+// 30-Jan-95 Ricksa New ROT
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+
+#include <clsctx.hxx>
+#include <iface.h>
+#include <objsrv.h>
+#include <compname.hxx>
+#include "resolver.hxx"
+#include "smstg.hxx"
+#include "objact.hxx"
+#include "treat.hxx"
+
+// We use this to calculate the hash value for the path
+DWORD CalcFileMonikerHash(LPWSTR pwszPath);
+
+// computer name. Note that the static constructor does nothing. When the
+// object first gets used, the computer name is extracted from the registry.
+// we cant do it in the constructor because some things that are loaded
+// early in the boot process (before registry Apis are ready) statically
+// link to this Dll.
+
+CComputerName g_CompName;
+
+// Number of classes that we will try to use the old binding logic on
+const MAX_MULTI_STEP_CLASSES = 2;
+
+// Table of classes. Right now this is only WordPerfect.
+// BUGBUG: We should put this information in the registry and then other
+// badly written 16 bit apps can work as well.
+// BUGBUG: We should reinvestigate whether the WP delayed class registration
+// logic is necessary in the thunk layer.
+const CLSID clsidMultiStep[MAX_MULTI_STEP_CLASSES] =
+ {{ 0x89FE3FE3, 0x9FF6, 0x101B, {0xB6, 0x78, 0x04, 0x02, 0x1C, 0x00, 0x70, 0x02}},
+ { 0x1395F281, 0x4326, 0x101b, {0x8B, 0x9A, 0xCE, 0x29, 0x3E, 0xF3, 0x84, 0x49}}};
+
+#ifdef _CHICAGO_
+CRpcResolver gResolver;
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetMultiStepClassFactory
+//
+// Synopsis: Get a class object for a class that can't stand the new
+// optimized binding logic.
+//
+// Arguments: [rclsid] - class for code we wish to get
+// [dwClsctx] - class context required.
+// [ppcf] - where to put the class factory.
+//
+// Returns: S_OK - we are returning a class factor
+// S_FALSE - this is not an old style object
+// Other - some failure occurred.
+//
+// History: 05-11-95 Ricksa Created
+//
+//+-------------------------------------------------------------------------
+HRESULT GetMultiStepClassFactory(
+ REFCLSID rclsid,
+ DWORD dwClsctx,
+ IClassFactory **ppcf)
+{
+ HRESULT hr = S_FALSE;
+
+ // We only care if this is a request for a local server because in the
+ // in proc case there is no time lag between calls.
+ if (dwClsctx & CLSCTX_LOCAL_SERVER)
+ {
+ // Is this a class that we know about that should be a slow bind?
+ for (int i = 0; i < MAX_MULTI_STEP_CLASSES; i++)
+ {
+ if (IsEqualCLSID(clsidMultiStep[i], rclsid))
+ {
+ // Get the class object & return it.
+ hr = ICoGetClassObject(rclsid, CLSCTX_LOCAL_SERVER, NULL,
+ IID_IClassFactory, (void **) ppcf);
+
+ break;
+ }
+ }
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetObjectByPath
+//
+// Synopsis: Get object from the ROT by its path
+//
+// Arguments: [pwszName] - name of object to get from the ROT
+// [ppvUnk] - unk to return to caller
+// [riid] - interface to get.
+//
+// Returns: S_OK - got object from the ROT
+// S_FALSE - object was not in the ROT
+// Other - QueryInterface for IID failed.
+//
+// Notes: Ask ROT if path is in the ROT. If it is QI for the requested
+// interface.
+//
+// History: 03-15-95 Ricksa Created
+//
+// Notes: This routine counts on the fact that S_FALSE is not a valid
+// response IUnknown::QueryInterface.
+//
+//+-------------------------------------------------------------------------
+HRESULT GetObjectByPath(WCHAR *pwszName, void **ppvUnk, REFIID riid)
+{
+ HRESULT hr = S_FALSE;
+
+ IUnknown *punk;
+
+ if (GetObjectFromRotByPath(pwszName, &punk) == S_OK)
+ {
+ // Get the requested interface
+ hr = punk->QueryInterface(riid, ppvUnk);
+
+ Win4Assert((hr != S_FALSE) && "GetObjectByPath QI ret S_FALSE");
+ punk->Release();
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: RemapClassCtxForInProcServer
+//
+// Synopsis: Remap CLSCTX so that the correct type of inproc server will
+// be requested.
+//
+// Arguments: [dwCtrl] - requested server context
+//
+// Returns: Updated dwCtrl appropriate for the process' context
+//
+// Notes: If an inproc server is requested make sure it is the right
+// type for the process. In other words, we only load 16 bit
+// inproc servers into 16 bit processes and 32 bit servers
+// into 32 bit processes. The special logic here is only for
+// 16 bit servers since the attempt to load a 16-bit DLL into
+// a 32 bit process will fail anyway.
+//
+// History: 01-11-95 Ricksa Created
+//
+//+-------------------------------------------------------------------------
+DWORD RemapClassCtxForInProcServer(DWORD dwCtrl)
+{
+ if (IsWOWThread())
+ {
+ // 16 bit process - remap CLSCTX_INPROC_SERVER if necessary
+ if ((dwCtrl & CLSCTX_INPROC_SERVER) != 0)
+ {
+ // Turn on the 16 bit inproc server request and turn off the
+ // 32 bit server request flag.
+ dwCtrl = (dwCtrl & ~CLSCTX_INPROC_SERVER) | CLSCTX_INPROC_SERVER16;
+ }
+ // if handlers are requested make sure 16-bit is looked for first
+ // We mask out 32bit handler flag for Wow threads because we will
+ // always look for a 32 bit handler if we don't find a 16 bit one
+ if ((dwCtrl & CLSCTX_INPROC_HANDLER) != 0)
+ {
+ // Turn on the 16 bit inproc handler request and turn off the
+ // 32 bit handler request flag.
+ dwCtrl = (dwCtrl & ~CLSCTX_INPROC_HANDLER) | CLSCTX_INPROC_HANDLER16;
+ }
+ }
+#ifdef WX86OLE
+ //
+ // if we are allowed to remap the clsctx flags and we are running in a
+ // wx86 process then remap the flags to prefer an x86 inproc
+ else if (((dwCtrl & CLSCTX_NO_REMAP) == 0) && (gcwx86.IsWx86Enabled()))
+ {
+ if (dwCtrl & CLSCTX_INPROC_SERVER)
+ {
+ dwCtrl |= CLSCTX_INPROC_SERVERX86;
+ }
+
+ if (dwCtrl & CLSCTX_INPROC_HANDLER)
+ {
+ dwCtrl |= CLSCTX_INPROC_HANDLERX86;
+ }
+ }
+#endif
+ else
+ {
+ if ((dwCtrl & CLSCTX_INPROC_SERVER) != 0)
+ {
+ // Turn off the 16 bit inproc server request
+ dwCtrl &= ~CLSCTX_INPROC_SERVER16;
+ }
+ }
+#ifdef WX86OLE
+ if (dwCtrl & CLSCTX_NO_REMAP)
+ {
+ dwCtrl &= ~CLSCTX_NO_REMAP;
+ }
+#endif
+
+ return dwCtrl;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CheckScmHandlerResult
+//
+// Synopsis: Verify that a 32 bit Handler DLL is being returned to the
+// right context.
+//
+// Arguments: [pwszDllToLoad] - DLL to load
+//
+// Returns: S_OK - Everything is OK
+// CO_E_ERRORINDLL - Trying to load bad DLL for process type.
+//
+// Notes: This is only important for 16 bit processes to prevent them
+// from loading 32 handler code. We only allow the loading of
+// OLE32.DLL as a handler in a 16 bit process because it is
+// already loaded anyway.
+//
+// History: 01-11-95 Ricksa Created
+//
+//+-------------------------------------------------------------------------
+HRESULT CheckScmHandlerResult(WCHAR *pwszDllToLoad)
+{
+ HRESULT hr = S_OK;
+
+ if (IsWOWThread())
+ {
+ // We are a 16 bit process. Unless this is OLE32.DLL, we will fail
+ // the load of the handler.
+
+ // Scan string for last "\" if any.
+ WCHAR *pwszScan = pwszDllToLoad;
+ WCHAR *pwszLastComponent = pwszDllToLoad;
+
+ while(*pwszScan != 0)
+ {
+ if ((*pwszScan == '\\') || (*pwszScan == '/'))
+ {
+ pwszLastComponent = pwszScan + 1;
+ }
+
+ pwszScan++;
+ }
+
+ // Compare last path component to see if it ole32.dll
+ if (lstrcmpiW(pwszLastComponent, L"OLE32.DLL") != 0)
+ {
+ hr = CO_E_ERRORINDLL;
+ }
+ }
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsInternalCLSID
+//
+// Synopsis: checks if the given clsid is an internal class, and
+// bypasses the TreatAs and SCM lookup if so. Also checks for
+// OLE 1.0 classes, which are actually considered to be
+// internal, since their OLE 2.0 implementation wrapper is
+// ours.
+//
+// Arguments: [rclsid] - clsid to look for
+// [riid] - the iid requested
+// [hr] - returns the hresult from DllGetClassObject
+// [ppvClassObj] - where to return the class factory
+//
+// Returns: TRUE - its an internal class, hr is the return code from
+// DllGetClassObject and if hr==S_OK ppvClassObj
+// is the class factory.
+// FALSE - not an internal class
+//
+// Notes: internal classes can not be overridden because there are
+// other mechanisms for creating them eg CreateFileMoniker that
+// bypass implementation lookup.
+//
+// History: 5-04-94 Rickhi Created
+// 5-04-94 KevinRo Added OLE 1.0 support
+//
+//+-------------------------------------------------------------------------
+
+BOOL IsInternalCLSID(REFCLSID rclsid,
+ REFIID riid,
+ HRESULT &hr,
+ void ** ppvClassObj)
+{
+ DWORD *ptr = (DWORD *) &rclsid;
+ CLSID clsid = rclsid;
+
+ if (*(ptr+1) == 0x00000000 && // all internal clsid's have these
+ *(ptr+2) == 0x000000C0 && // common values
+ *(ptr+3) == 0x46000000)
+ {
+ // internal class (eg file moniker). just ask our selves
+ // for the class factory.
+ //
+ //
+ // Its possible that an OLE 1.0 class has been marked
+ // as TREATAS as part of an upgrade. Here we are going
+ // to handle the loading of OLE 1.0 servers. We
+ // need to do the GetTreatAs trick first. Rather than
+ // invalidate this perfectly good caching routine, the
+ // GetTreatAs will only be done if the clsid is in the
+ // range of the OLE 1.0 UUID's. Note that the GetTreatAs
+ // done here will add the class to the cache, so if the
+ // resulting class is outside of the internal range, the
+ // lookup done later will be nice and fast.
+ //
+
+ WORD hiWord = HIWORD(clsid.Data1);
+
+ if (hiWord == 3 || hiWord == 4)
+ {
+ //
+ // Its in the OLE 1.0 class range. See if it has
+ // been marked as 'treatas'
+ //
+ GetTreatAs(rclsid, clsid);
+ ptr = (DWORD *) &clsid;
+ hiWord = HIWORD(clsid.Data1);
+ }
+
+ if ((*ptr > 0x000002ff && *ptr < 0x00000321) ||
+ (hiWord == 3 || hiWord == 4))
+ {
+ // internal class (eg file moniker) or an OLE 1.0 class.
+ // just ask our selves for the class factory.
+
+ hr = DllGetClassObject(clsid, riid, ppvClassObj);
+ return TRUE;
+ }
+ }
+ // not an internal class.
+ return FALSE;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DoUnmarshal
+//
+// Synopsis: Helper for unmarshaling an interface from remote
+//
+// Arguments: [pIFD] - serialized interface reference returned by SCM
+// [riid] - interface ID requested by application
+// [ppvUnk] - where to put pointer to returned interface
+//
+// Returns: S_OK - Interface unmarshaled
+//
+// Algorithm: Convert marshaled data to a stream and then unmarshal
+// to IUnknown. Next, use unknown to query interface to
+//
+//
+// History: 11-May-93 Ricksa Created
+//
+// Notes: This helper should go away when the server marshals
+// to the interface that it actually wants to return.
+//
+//--------------------------------------------------------------------------
+HRESULT DoUnmarshal(InterfaceData *pIFD, REFIID riid, void **ppvUnk)
+{
+ // Convert returned interface to a stream
+ CXmitRpcStream xrpc(pIFD);
+
+ // Unmarshal interface
+ XIUnknown xunk;
+
+ HRESULT hr = CoUnmarshalInterface(&xrpc, IID_IUnknown, (void **) &xunk);
+
+ //CODEWORK: Stress revealed CoGetClassObject returning a null class factory
+ // and S_OK
+ Win4Assert(((hr == S_OK && xunk != NULL) ||
+ (hr != S_OK && xunk == NULL)) &&
+ "DoUnamrshal CoUnmarshalInterface failure");
+
+ if (SUCCEEDED(hr))
+ {
+ hr = xunk->QueryInterface(riid, ppvUnk);
+ }
+
+ //CODEWORK: Stress revealed CoGetClassObject returning a null class factory
+ // and S_OK
+ Win4Assert(((hr == S_OK && *ppvUnk != NULL) ||
+ (hr != S_OK && *ppvUnk == NULL))
+ && "DoUnamrshal QueryInterface failure");
+
+ MyMemFree(pIFD);
+
+ return hr;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UnmarshalSCMResult
+//
+// Synopsis: Common routine for dealing with results from SCM
+//
+// Arguments: [sc] - SCODE returned by SCM
+// [pIFD] - serialized interface reference returned by SCM
+// [riid] - interface ID requested by application
+// [ppunk] - where to put pointer to returned interface
+// [pwszDllPath] - path to DLL if there is one.
+// [ppunk] - pointer to returned interface.
+// [usMethodOrdinal] - method for error reporting
+//
+// Returns: TRUE - processing is complete for the call
+// FALSE - this is a DLL and client needs to instantiate.
+//
+// Algorithm: If the SCODE indicates a failure, then this sets an
+// SCODE indicating that the service controller returned
+// an error and propagates the result from the SCM. Otherwise,
+// if the SCM has returned a result indicating that a
+// handler has been returned, the handler DLL is cached.
+// If a marshaled interface has been returned, then that is
+// unmarshaled. If an inprocess server has been returned,
+// the DLL is cached and the class object is created.
+//
+// History: 11-May-93 Ricksa Created
+//
+// Notes: This routine is simply a helper for CoGetPersistentInstance.
+//
+//--------------------------------------------------------------------------
+BOOL UnmarshalSCMResult(
+ HRESULT& hr,
+ InterfaceData *pIFD,
+ REFCLSID rclsid,
+ REFIID riid,
+ void **ppvUnk,
+ DWORD dwDllThreadModel,
+ WCHAR *pwszDllPath,
+ void **ppvCf)
+{
+ BOOL fResult = TRUE;
+#ifndef _UNICODE
+ TCHAR *ptszDllPath;
+ UINT cb;
+ int ret;
+#else // !_UNICODE
+ const TCHAR *ptszDllPath;
+#endif // _UNICODE
+
+ if (SUCCEEDED(hr))
+ {
+ // Flag for fall through from a 16 bit case
+ BOOL f16BitFallThru = FALSE;
+
+ switch (hr)
+ {
+#ifdef GET_INPROC_FROM_SCM
+ case SCM_S_HANDLER16:
+ CairoleDebugOut((DEB_ACTIVATE,
+ "16-bit InprocHandler\n"));
+
+ // Note: if the process is a 32 bit process and the
+ // DLL is a 16 bit DLL, the load will fail. Since
+ // we assume that this is a fairly rare case, we
+ // let the lower level code discover this.
+
+ f16BitFallThru = TRUE;
+
+#ifdef WX86OLE
+ case SCM_S_HANDLERX86:
+#endif
+ case SCM_S_HANDLER:
+ CairoleDebugOut((DEB_ACTIVATE,
+ "InprocHandler(%ws)\n",pwszDllPath));
+
+ // Just in case we chicken out and back out our changes
+ if (!f16BitFallThru)
+ {
+ // Validate that 32 bit handler DLL is being loaded
+ // in the correct process.
+ hr = CheckScmHandlerResult(pwszDllPath);
+
+ if (hr != NOERROR)
+ {
+ break;
+ }
+ }
+
+
+ // Store handler class object -- when the request to unmarshal the
+ // object call CoGetClassObject, the call will automatically find
+ // this handler in the cache.
+
+#ifndef _UNICODE
+ // Now that SCM doesn't return inproc results we should never exercise
+ // this code path. It is here for completeness.
+ ptszDllPath = NULL;
+ Win4Assert((pwszDllPath) && "UnmarshalSCMResult: (pwszDllPath == NULL)");
+ cb = (lstrlenW(pwszDllPath) + 1) * sizeof(WCHAR);
+ ptszDllPath = (LPTSTR) PrivMemAlloc(cb);
+ if (ptszDllPath == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ return(TRUE);
+ }
+
+ ret = WideCharToMultiByte( (AreFileApisANSI())?CP_ACP:CP_OEMCP,WC_COMPOSITECHECK,
+ pwszDllPath, -1, ptszDllPath, cb, NULL, NULL);
+
+#if DBG==1
+ CairoleAssert(ret != 0 && "Lost characters in Unicode->Ansi conversion");
+#endif
+#else // !_UNICODE
+ ptszDllPath = pwszDllPath;
+#endif // _UNICODE
+
+ gdllcacheHandler.Add(rclsid, IID_IClassFactory, dwDllThreadModel,
+ ptszDllPath, FALSE,(hr == SCM_S_HANDLER16),
+#ifdef WX86OLE
+ (hr == SCM_S_HANDLERX86),
+#endif
+ hr);
+
+#ifndef _UNICODE
+ PrivMemFree(ptszDllPath);
+#endif
+ ptszDllPath = NULL;
+
+ if (FAILED(hr))
+ {
+ return TRUE;
+ }
+
+ // Fall into unmarshal code if we also have an interface pointer
+ if ( pIFD == NULL )
+ {
+ break;
+ }
+#endif // GET_INPROC_FROM_SCM
+
+ case S_OK :
+
+ hr = DoUnmarshal(pIFD, riid, ppvUnk);
+ break;
+
+#ifdef GET_INPROC_FROM_SCM
+ case SCM_S_INPROCSERVER16:
+ CairoleDebugOut((DEB_ACTIVATE, "16-bit InprocServer\n"));
+
+#ifdef WX86OLE
+ case SCM_S_INPROCSERVERX86:
+#endif
+ case SCM_S_INPROCSERVER:
+ CairoleDebugOut((DEB_ACTIVATE, "InprocServer(%ws)\n",pwszDllPath));
+
+ // Just in case we chicken out and back out our changes
+ // This is an inprocesses server -- we want cache that information
+ // and do the work of instantiating an object.
+#ifndef _UNICODE
+ ptszDllPath = NULL;
+ Win4Assert((pwszDllPath) && "UnmarshalSCMResult: (pwszDllPath == NULL)");
+ cb = (lstrlenW(pwszDllPath) + 1) * sizeof(WCHAR);
+ ptszDllPath = (LPTSTR) PrivMemAlloc(cb);
+ if (ptszDllPath == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ return(TRUE);
+ }
+
+ ret = WideCharToMultiByte( (AreFileApisANSI())?CP_ACP:CP_OEMCP,WC_COMPOSITECHECK,
+ pwszDllPath, -1, ptszDllPath, cb, NULL, NULL);
+
+#if DBG==1
+ CairoleAssert(ret != 0 && "Lost characters in Unicode->Ansi conversion");
+#endif
+#else // !_UNICODE
+ ptszDllPath = pwszDllPath;
+#endif // _UNICODE
+ *ppvCf = gdllcacheInprocSrv.Add(rclsid, IID_IClassFactory,
+ dwDllThreadModel, ptszDllPath, TRUE,
+ (hr == SCM_S_INPROCSERVER16),
+#ifdef WX86OLE
+ (hr == SCM_S_INPROCSERVERX86),
+#endif
+ hr);
+
+#ifndef _UNICODE
+ PrivMemFree(ptszDllPath);
+#endif
+ ptszDllPath = NULL;
+
+ // If we actually got an inproc server object successfully
+ // then we want to continue processing otherwise we can
+ // just return the error that occurred.
+ if (SUCCEEDED(hr))
+ {
+ fResult = FALSE;
+ }
+#else // GET_INPROC_FROM_SCM
+ // Error: Should never come here as we handled INPROC_SERVERS
+ // before calling SCM
+ Win4Assert((FALSE) && "UnmarshalSCMResult: SCM_S_INPROC return from SCM");
+#endif // GET_INPROC_FROM_SCM
+ }
+ }
+
+ return fResult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoGetPersistentInstance
+//
+// Synopsis: Returns an instantiated interface to an object whose
+// stored state resides on disk.
+//
+// Arguments: [riid] - interface to bind object to
+// [dwCtrl] - kind of server required
+// [grfMode] - how to open the storage if it is a file.
+// [pwszName] - name of storage if it is a file.
+// [pstg] - IStorage to use for object
+// [rclsidOle1] -- ClassID if OLE 1.0 (CLSID_NULL otherwise)
+// [pfOle1Loaded] -- Returns TRUE if loaded as OLE 1.0
+// [ppvUnk] - where to put bound interface pointer
+//
+// Returns: S_OK - object bound successfully
+// MISSING
+//
+// Algorithm: Parameters are validated first. Then the class ID is retrieved
+// from the storage. We check whether we can use a cached
+// in process server. If we can't we call through to the
+// SCM to get the information. We call UnmarshalSCMResult
+// to process the return from the SCM. If the result is
+// completely processed, we return that result to the caller.
+// Otherwise, if the server is inprocess, we go through the
+// steps to create and bind the interface by calling
+// GetObjectHelper. Finally, we QI to the requested interface.
+//
+// History: 11-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifdef _CHICAGO_
+STDAPI CoGetPersistentInstance(
+ REFIID riid,
+ DWORD dwCtrl,
+ DWORD grfMode,
+ WCHAR *pwszName,
+ struct IStorage *pstg,
+ REFCLSID rclsidOle1,
+ BOOL * pfOle1Loaded,
+ void **ppvUnk)
+{
+ TRACECALL(TRACE_ACTIVATION, "CoGetPersistentInstance");
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pstg);
+
+ if (!IsApartmentInitialized())
+ return CO_E_NOTINITIALIZED;
+
+ IClassFactory *pcf = NULL;
+ WCHAR *pwszDllPath = NULL;
+ InterfaceData *pIFD = NULL;
+ IUnknown *punk = NULL;
+ WCHAR awcNameBuf[MAX_PATH];
+ WCHAR *pwszNameUNC = awcNameBuf;
+ WCHAR awcServer[MAX_PATH];
+ WCHAR *pwszServer = awcServer;
+ DWORD dwDllTypeToGet = IsSTAThread() ? APT_THREADED : FREE_THREADED;
+ DWORD dwDllServerType;
+ DWORD dwHash = 0;
+ COleTls Tls;
+
+ HRESULT hr;
+
+ BEGIN_BLOCK
+
+ // Set output parameter in case of error.
+ *ppvUnk = NULL;
+
+ // Make sure input request is at least slightly logical
+ if (((pstg != NULL) && (pwszName != NULL))
+ || ((pstg == NULL) && (pwszName == NULL))
+ || ((dwCtrl & ~CLSCTX_SERVER) != 0))
+ {
+ hr = E_INVALIDARG;
+ EXIT_BLOCK;
+ }
+
+ // Make sure we are asking for the correct inproc server
+ dwCtrl = RemapClassCtxForInProcServer(dwCtrl);
+
+ CLSID clsid;
+ if(pfOle1Loaded != NULL)
+ {
+ *pfOle1Loaded = FALSE;
+ }
+
+ if (pwszName)
+ {
+ // If there is a path supplied convert it to a normalized form
+ // so it can be used by any process in the net.
+ hr = ProcessPath(pwszName, &pwszNameUNC, &pwszServer);
+
+ if (FAILED(hr))
+ {
+ EXIT_BLOCK;
+ }
+
+ // Limit on loops for retrying to get class of object
+ DWORD cGetClassRetries = 0;
+
+ // We loop here looking for either the running object or
+ // for the class of the file. We do this because there
+ // are race conditions where the can be starting or stopping
+ // and the class of the object might not be available because
+ // of the opening mode of the object's server.
+ do
+ {
+ // Look in the ROT first to see if we need to bother
+ // looking up the class of the file.
+ if ((hr = GetObjectByPath(pwszName, ppvUnk, riid)) != S_FALSE)
+ {
+ // Got object from ROT so we are done.
+ return hr;
+ }
+
+ // Try to get the class of the file
+ hr = GetClassFileEx(pwszName, &clsid, rclsidOle1);
+
+
+ if (hr == STG_E_ACCESSDENIED)
+ {
+ // The point here of the sleep is to try to let the
+ // operation that is holding the class id unavailable
+ // complete.
+ Sleep(GET_CLASS_RETRY_SLEEP_MS);
+ continue;
+ }
+
+ // Either we succeeded or something other than error
+ // access denied occurred here. For all these cases
+ // we break the loop.
+ break;
+
+ } while (cGetClassRetries++ < GET_CLASS_RETRY_MAX);
+
+ if (FAILED(hr))
+ {
+ // If we were unable to determine the classid, and the
+ // caller provided one as a Ole1 clsid, try loading it
+ // If it succeeds, then return
+
+ if (rclsidOle1 != CLSID_NULL)
+ {
+ if( Tls->dwFlags & OLETLS_DISABLE_OLE1DDE )
+ {
+ // If this app doesn't want or can tolerate having a DDE
+ // window then currently it can't use OLE1 classes because
+ // they are implemented using DDE windows.
+ //
+ hr = CO_E_OLE1DDE_DISABLED;
+ EXIT_BLOCK;
+ }
+
+ if (hr != MK_E_CANTOPENFILE)
+ hr = DdeBindToObject(pwszName,
+ rclsidOle1,
+ FALSE,
+ riid,
+ ppvUnk);
+
+ if(pfOle1Loaded != NULL)
+ {
+ *pfOle1Loaded = TRUE;
+ }
+ }
+
+ EXIT_BLOCK;
+ }
+ }
+ else
+ {
+ pwszNameUNC = NULL;
+ pwszServer = NULL;
+
+ STATSTG statstg;
+
+ if (FAILED(hr = pstg->Stat(&statstg, STATFLAG_NONAME)))
+ {
+ EXIT_BLOCK;
+ }
+
+ clsid = statstg.clsid;
+ }
+
+ GetTreatAs(clsid, clsid);
+ //
+ // If this is a OLE 1.0 class, then do a DdeBindToObject on it,
+ // and return.
+ //
+ if (CoIsOle1Class(clsid))
+ {
+ if( Tls->dwFlags & OLETLS_DISABLE_OLE1DDE )
+ {
+ // If this app doesn't want or can tolerate having a DDE
+ // window then currently it can't use OLE1 classes because
+ // they are implemented using DDE windows.
+ //
+ hr = CO_E_OLE1DDE_DISABLED;
+ EXIT_BLOCK;
+ }
+
+ if (pwszName != NULL)
+ {
+ if (hr != MK_E_CANTOPENFILE)
+ hr = DdeBindToObject(pwszName,clsid,FALSE,riid,ppvUnk);
+
+ if(pfOle1Loaded != NULL)
+ {
+ *pfOle1Loaded = TRUE;
+ }
+ EXIT_BLOCK;
+ }
+ else
+ {
+ //
+ // Something is fishy here. We don't have a pwszName,
+ // yet CoIsOle1Class returned the class as an ole1 class.
+ // To get to this point without a pwszName, there must have
+ // been a pstg passed into the API.
+ //
+ // This isn't supposed to happen. To recover, just fall
+ // through and load the class as an OLE 2.0 class
+ //
+ CairoleDebugOut((DEB_ERROR,
+ "CoIsOle1Class is TRUE on a storage!\n"));
+ }
+ }
+
+ // Default to success at this point
+ hr = S_OK;
+
+ // We cache information about in process servers so we look in the
+ // cache first in hopes of saving some time.
+ pcf = (IClassFactory *)
+ SearchCacheOrLoadInProc(clsid,
+ IID_IClassFactory,
+ (pwszServer != NULL),
+ FALSE,
+ dwCtrl,
+ dwDllTypeToGet,
+ hr);
+
+ if ((pcf == NULL)
+ && ((hr = GetMultiStepClassFactory(clsid, dwCtrl, &pcf))
+ == S_FALSE))
+ {
+ // Marshal pstg since SCM can't deal with unmarshaled objects
+ fsCSafeStgMarshaled sms(pstg, MSHCTX_DIFFERENTMACHINE, hr);
+
+ if (FAILED(hr))
+ {
+ EXIT_BLOCK;
+ }
+
+ BOOL fExitBlock;
+ DWORD cLoops = 0;
+
+ do
+ {
+ dwDllServerType = dwDllTypeToGet;
+
+#ifndef GET_INPROC_FROM_SCM
+ // Just in case we chicken out and back out our changes
+ dwCtrl &= ~(CLSCTX_INPROC_SERVERS | CLSCTX_INPROC_HANDLERS); // make sure we don't ask for inproc stuff
+#endif // GET_INPROC_FROM_SCM
+
+ // Forward call to service controller
+ hr = gResolver.ActivateObject(clsid, dwCtrl, grfMode,
+ pwszNameUNC, sms, &pIFD, &dwDllServerType,
+ &pwszDllPath, pwszServer);
+
+ fExitBlock = UnmarshalSCMResult(hr, pIFD, clsid, riid, ppvUnk,
+ dwDllServerType, pwszDllPath, (void **) &pcf);
+
+ if ((hr != NOERROR) && (dwDllServerType == GOT_FROM_ROT))
+ {
+ // Got something from the ROT. We need to make sure the
+ // ROT is clean, so we try accessing the ROT again by
+ // name which will go through the logic that cleans the
+ // table of bogus entries. Note that we can actually find
+ // a valid item while we are doing this clean up.
+ if ((hr = GetObjectByPath(pwszName, ppvUnk, riid))
+ != S_FALSE)
+ {
+ // Got object from ROT so we are done.
+ return hr;
+ }
+
+ // This might be our last loop so make sure that this
+ // will return an error. Since this is a highly unexpected
+ // error case, we return that.
+ hr = E_UNEXPECTED;
+ }
+
+ // If we get something from the ROT, we need to retry until
+ // we get an object. Because objects can disappear from the
+ // ROT async to us, we need to retry a few times. But since
+ // this theoretically could happen forever, we place an arbitrary
+ // limit on the number of retries to the ROT.
+ } while((hr != NOERROR) && (dwDllServerType == GOT_FROM_ROT)
+ && (++cLoops < 5));
+
+ if (fExitBlock)
+ {
+ EXIT_BLOCK;
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = GetObjectHelper(pcf, grfMode, pwszName, pstg, NULL, &punk);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = punk->QueryInterface(riid, ppvUnk);
+ }
+ }
+
+ END_BLOCK;
+
+ if (pcf != NULL)
+ {
+ pcf->Release();
+ }
+
+ if (punk != NULL)
+ {
+ punk->Release();
+ }
+
+ // RPC stubs allocated path so we trust that it is null or valid.
+ if (pwszDllPath != NULL)
+ {
+ MyMemFree(pwszDllPath);
+ }
+
+ CALLHOOKOBJECT(hr,rclsidOle1,riid,(IUnknown **)ppvUnk);
+ return hr;
+}
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoGetClassObject
+//
+// Synopsis: External entry point that returns an instantiated class object
+//
+// Arguments: [rclsid] - class id for class object
+// [dwContext] - kind of server we wish
+// [pvReserved] - Reserved for future use
+// [riid] - interface to bind class object
+// [ppvClassObj] - where to put interface pointer
+//
+// Returns: S_OK - successfully bound class object
+//
+// Algorithm: Validate all then parameters and then pass this to the
+// internal version of the call.
+//
+// History: 11-May-93 Ricksa Created
+// 11-May-94 KevinRo Added OLE 1.0 support
+// 23-May-94 AlexT Make sure we're initialized!
+// 15-Nov-94 Ricksa Split into external and internal calls
+//
+//
+//--------------------------------------------------------------------------
+STDAPI CoGetClassObject(
+ REFCLSID rclsid,
+ DWORD dwContext,
+ LPVOID pvReserved,
+ REFIID riid,
+ void FAR* FAR* ppvClassObj)
+{
+ OLETRACEIN((API_CoGetClassObject, PARAMFMT("rclsid= %I, dwContext= %x, pvReserved= %p, riid= %I, ppvClassObj= %p"),
+ &rclsid, dwContext, pvReserved, &riid, ppvClassObj));
+
+ TRACECALL(TRACE_ACTIVATION, "CoGetClassObject");
+
+ HRESULT hr = E_INVALIDARG;
+
+ if (ppvClassObj)
+ {
+ *ppvClassObj = NULL;
+ }
+
+ if (!IsApartmentInitialized())
+ {
+ CairoleDebugOut((DEB_ERROR, "CoGetClassObject failed - Appartment not initialized\n"));
+ hr = CO_E_NOTINITIALIZED;
+ goto errRtn;
+ }
+
+ // Validate parameters
+ if (IsValidPtrIn(&rclsid, sizeof(CLSID))
+ && IsValidPtrIn(&riid, sizeof(IID))
+ && IsValidPtrOut(ppvClassObj, sizeof(void *))
+#ifdef WX86OLE
+ && ((dwContext & ~(CLSCTX_ALL | CLSCTX_INPROC_SERVER16 |
+ CLSCTX_INPROC_SERVERX86 |
+ CLSCTX_NO_REMAP |
+ CLSCTX_PS_DLL |
+ CLSCTX_INPROC_HANDLERX86)) == 0))
+#else
+ && ((dwContext & ~(CLSCTX_ALL | CLSCTX_INPROC_SERVER16 |
+ CLSCTX_PS_DLL)) == 0))
+#endif
+ {
+ *ppvClassObj = NULL;
+
+ // Make sure we are asking for the correct inproc server
+ dwContext = RemapClassCtxForInProcServer(dwContext);
+#ifdef DCOM
+ hr = ICoGetClassObject(rclsid,
+ dwContext,
+ (COSERVERINFO *) pvReserved,
+ riid,
+ ppvClassObj);
+#else
+ hr = IOldCoGetClassObject(rclsid, dwContext, pvReserved, riid,
+ ppvClassObj);
+#endif
+ }
+
+errRtn:
+ OLETRACEOUT((API_CoGetClassObject, hr));
+
+ return hr;
+}
+
+
+
+
+#ifndef DCOM
+//+-------------------------------------------------------------------------
+//
+// Function: IOldCoGetClassObject
+//
+// Synopsis: Internal entry point that returns an instantiated class object
+//
+// Arguments: [rclsid] - class id for class object
+// [dwContext] - kind of server we wish
+// [pvReserved] - Reserved
+// [riid] - interface to bind class object
+// [ppvClassObj] - where to put interface pointer
+//
+// Returns: S_OK - successfully bound class object
+//
+// Algorithm: First, the context is validated. Then we try to use
+// any cached information by looking up either cached in
+// process servers or handlers based on the context.
+// If no cached information suffices, we call the SCM
+// to find out what to use. If the SCM returns a handler
+// or an inprocess server, we cache that information.
+// If the class is implemented by a local server, then
+// the class object is unmarshaled. Otherwise, the object
+// is instantiated locally using the returned DLL.
+//
+//
+// History: 15-Nov-94 Ricksa Split into external and internal calls
+//
+//
+//--------------------------------------------------------------------------
+STDAPI IOldCoGetClassObject(
+ REFCLSID rclsid,
+ DWORD dwContext,
+ LPVOID pvReserved,
+ REFIID riid,
+ void FAR* FAR* ppvClassObj)
+{
+ TRACECALL(TRACE_ACTIVATION, "CoGetClassObject");
+
+ IUnknown *punk = NULL;
+ HRESULT hr = S_OK;
+ WCHAR *pwszDllToLoad = NULL;
+ InterfaceData *pIFD = NULL;
+ CLSID clsid;
+ DWORD dwDllServerType = IsSTAThread() ? APT_THREADED : FREE_THREADED;
+#ifndef _UNICODE
+ TCHAR *ptszDllToLoad;
+ UINT cb;
+ int ret;
+#else // !_UNICODE
+ const TCHAR *ptszDllToLoad;
+#endif // _UNICODE
+
+
+ BEGIN_BLOCK
+
+ // IsInternalCLSID will also check to determine if the CLSID is
+ // an OLE 1.0 CLSID, in which case we get back our internal
+ // class factory.
+
+ if (IsInternalCLSID(rclsid, riid, hr, ppvClassObj))
+ {
+ // this is an internally implemented clsid, or an OLE 1.0 class
+ // so we already got the class factory (if available) and set
+ // the return code appropriately.
+ EXIT_BLOCK;
+ }
+
+ if (FAILED(hr = GetTreatAs(rclsid, clsid)))
+ {
+ EXIT_BLOCK;
+ }
+
+ // Make sure we are asking for the correct inproc server
+ // We do this here even though it might already be done in CoGetClassObject
+ // as we could get here directly from CoCreateInstance.
+ dwContext = RemapClassCtxForInProcServer(dwContext);
+
+ punk = SearchCacheOrLoadInProc(clsid,
+ riid,
+ FALSE,
+ FALSE,
+ dwContext,
+ dwDllServerType,
+ hr);
+
+ // If still don't have a punk, go to the scm
+ if (!punk)
+ {
+ // Ask the service controller for the class object
+#ifndef GET_INPROC_FROM_SCM
+ // Just in case we chicken out and back out our changes
+ dwContext &= ~(CLSCTX_INPROC_SERVERS | CLSCTX_INPROC_HANDLERS); // make sure we don't ask for inproc stuff
+#endif // GET_INPROC_FROM_SCM
+ hr = gResolver.OldGetClassObject(clsid, dwContext, NULL, &pIFD,
+ &dwDllServerType, &pwszDllToLoad);
+
+ // A proxy/stub DLL needs to be loaded as both no matter what
+ if (dwContext & CLSCTX_PS_DLL)
+ {
+ dwDllServerType = BOTH_THREADED;
+ }
+
+ if (FAILED(hr))
+ {
+ EXIT_BLOCK;
+ }
+
+ // Flag for special handler behavior
+ BOOL fGetClassObject;
+
+ // Flag for fall through from a 16 bit case
+ BOOL f16BitFallThru = FALSE;
+
+ switch (hr)
+ {
+ case SCM_S_HANDLER16:
+ CairoleDebugOut((DEB_ACTIVATE,
+ "16-bit InprocHandler\n"));
+
+ // Note: if the process is a 32 bit process and the
+ // DLL is a 16 bit DLL, the load will fail. Since
+ // we assume that this is a fairly rare case, we
+ // let the lower level code discover this.
+
+ f16BitFallThru = TRUE;
+
+#ifdef WX86OLE
+ case SCM_S_HANDLERX86:
+#endif
+ case SCM_S_HANDLER:
+ CairoleDebugOut((DEB_ACTIVATE,
+ "InprocHandler(%ws)\n",pwszDllToLoad));
+
+#ifdef GET_INPROC_FROM_SCM
+ // Just in case we chicken out and back out our changes
+ if (!f16BitFallThru)
+ {
+ // Validate that 32 bit handler DLL is being loaded
+ // in the correct process.
+ hr = CheckScmHandlerResult(pwszDllToLoad);
+
+ if (hr != NOERROR)
+ {
+ break;
+ }
+ }
+
+ // Figure out if we really need the class object for the
+ // handler. Otherwise we will just put it in the cache
+ // and unmarshal the class object.
+ fGetClassObject =
+ (dwContext & CLSCTX_INPROC_HANDLER) ? TRUE : FALSE;
+#else // GET_INPROC_FROM_SCM
+ // Only time we should be in this path is when we called the
+ // SCM for non-INPROC and get advised that a handler exists
+ fGetClassObject = FALSE;
+#endif // GET_INPROC_FROM_SCM
+
+#ifndef _UNICODE
+ // Now that SCM doesn't return inproc results we should never exercise
+ // this code path. It is here for completeness.
+ ptszDllToLoad = NULL;
+ Win4Assert((pwszDllToLoad) && "IOldCoGetClassObject: (pwszDllToLoad == NULL)");
+ cb = (lstrlenW(pwszDllToLoad) + 1) * sizeof(WCHAR);
+ ptszDllToLoad = (LPTSTR) PrivMemAlloc(cb);
+ if (ptszDllToLoad == NULL)
+ {
+ return(E_OUTOFMEMORY);
+ }
+
+ ret = WideCharToMultiByte( (AreFileApisANSI())?CP_ACP:CP_OEMCP,WC_COMPOSITECHECK,
+ pwszDllToLoad, -1, ptszDllToLoad, cb, NULL, NULL);
+
+#if DBG==1
+ CairoleAssert(ret != 0 && "Lost characters in Unicode->Ansi conversion");
+#endif
+
+#else // !_UNICODE
+ ptszDllPath = pwszDllToLoad;
+#endif // _UNICODE
+
+ // Store the handler returned
+ punk = gdllcacheHandler.Add(clsid, riid, dwDllServerType,
+ ptszDllToLoad, fGetClassObject,
+ (hr == SCM_S_HANDLER16),
+#ifdef WX86OLE
+ (hr == SCM_S_HANDLERX86),
+#endif
+ hr);
+
+#ifndef _UNICODE
+ PrivMemFree(ptszDllToLoad);
+#endif
+ ptszDllToLoad = NULL;
+
+ if (fGetClassObject)
+ {
+ // Request was really for a handler so we are done.
+ break;
+ }
+
+ // We got a handler back but we have just cached it to make
+ // processing faster when we create a real instance of an
+ // object. So we unmarshal the real object.
+
+ case S_OK :
+
+ hr = DoUnmarshal(pIFD, riid, (void **) &punk);
+ break;
+
+
+ case SCM_S_INPROCSERVER16:
+ CairoleDebugOut((DEB_ACTIVATE,
+ "16-bit InprocServer\n"));
+
+#ifdef WX86OLE
+ case SCM_S_INPROCSERVERX86:
+#endif
+ case SCM_S_INPROCSERVER:
+ CairoleDebugOut((DEB_ACTIVATE,
+ "InprocServer(%ws)\n",pwszDllToLoad));
+
+#ifdef GET_INPROC_FROM_SCM
+ // Just in case we chicken out and back out our changes
+ // In process server for class object
+#ifndef _UNICODE
+ ptszDllToLoad = NULL;
+ Win4Assert((pwszDllToLoad) && "IOldCoGetClassObject: (pwszDllToLoad == NULL)");
+ cb = (lstrlenW(pwszDllToLoad) + 1) * sizeof(WCHAR);
+ ptszDllToLoad = (LPTSTR) PrivMemAlloc(cb);
+ if (ptszDllToLoad == NULL)
+ {
+ return(E_OUTOFMEMORY);
+ }
+
+ ret = WideCharToMultiByte( (AreFileApisANSI())?CP_ACP:CP_OEMCP,WC_COMPOSITECHECK,
+ pwszDllToLoad, -1, ptszDllToLoad, cb, NULL, NULL);
+
+#if DBG==1
+ CairoleAssert(ret != 0 && "Lost characters in Unicode->Ansi conversion");
+#endif
+
+#else // !_UNICODE
+ ptszDllPath = pwszDllToLoad;
+#endif // _UNICODE
+
+ punk = gdllcacheInprocSrv.Add(clsid, riid, dwDllServerType,
+ ptszDllToLoad, TRUE,(hr == SCM_S_INPROCSERVER16),
+#ifdef WX86OLE
+ (hr == SCM_S_INPROCSERVERX86),
+#endif
+ hr);
+#ifndef _UNICODE
+ PrivMemFree(ptszDllToLoad);
+#endif
+ ptszDllToLoad = NULL;
+
+#else // GET_INPROC_FROM_SCM
+ // Error: Should never come here as we handled INPROC_SERVERS
+ // before calling SCM
+ Win4Assert((FALSE) && "IOldCoGetClassObject: SCM_S_INPROC return from SCM");
+#endif // GET_INPROC_FROM_SCM
+ }
+ }
+
+ *ppvClassObj = punk;
+ if ((punk == NULL) && SUCCEEDED(hr))
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ END_BLOCK;
+
+ if (pwszDllToLoad != NULL)
+ {
+ MyMemFree(pwszDllToLoad);
+ }
+
+ CALLHOOKOBJECTCREATE(hr,clsid,riid,(IUnknown **)ppvClassObj);
+ return hr;
+}
+#endif // !DCOM
+
+#ifndef GET_INPROC_FROM_SCM
+// Just in case we chicken out and back out our changes
+//+---------------------------------------------------------------------------
+//
+// Function: SearchCacheOrLoadInProc
+//
+// Synopsis: Searches the cache for requested classid.
+// If not found looks to see if an inproc server or handler
+// can be loaded (if requested).
+//
+// Arguments: [rclsid] Class ID
+// [riid] Interface required of class object
+// [fRemote] Whether path is remote
+// [fForScm] Whether it's the scm requesting
+// [dwContext] Which context to load
+// [dwCallerThreadModel] Which threading model to load
+// [hr] Reference to HRESULT for error returns
+//
+// Returns: ~NULL - Class factory for object
+// NULL - Class factory could not be found or
+// constructed.
+//
+// History: 2-5-96 murthys Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+IUnknown *SearchCacheOrLoadInProc(REFCLSID rclsid,
+ REFIID riid,
+ BOOL fRemote,
+ BOOL fForSCM,
+ DWORD dwContext,
+ DWORD dwDllServerType,
+ HRESULT &hr)
+{
+ IUnknown *punk = NULL;
+
+#ifdef WX86OLE
+ if (gcwx86.IsWx86Enabled())
+ {
+ if (dwContext & CLSCTX_INPROC_SERVERX86)
+ {
+ // Search cache for in process
+ punk = gdllcacheInprocSrv.GetOrLoadClass(rclsid,
+ riid,
+ FALSE,
+ FALSE,
+ TRUE,
+ dwContext & CLSCTX_INPROC_SERVERS,
+ dwDllServerType,
+ hr);
+ }
+
+ if ((punk == NULL) && (dwContext & CLSCTX_INPROC_HANDLERX86))
+ {
+ // Search cache for a cached handler DLL
+ punk = gdllcacheHandler.GetOrLoadClass(rclsid,
+ riid,
+ FALSE,
+ FALSE,
+ TRUE,
+ dwContext & CLSCTX_INPROC_HANDLERS,
+ dwDllServerType,
+ hr);
+ }
+ }
+#endif
+ if ((punk == NULL) &&
+ (dwContext & (CLSCTX_INPROC_SERVERS) ))
+ {
+ punk = gdllcacheInprocSrv.GetOrLoadClass(rclsid,
+ riid,
+ FALSE,
+ FALSE,
+#ifdef WX86OLE
+ FALSE,
+#endif
+ dwContext & CLSCTX_INPROC_SERVERS,
+ dwDllServerType,
+ hr);
+ }
+ if (punk == NULL && dwContext & CLSCTX_INPROC_HANDLERS)
+ {
+ punk = gdllcacheHandler.GetOrLoadClass(rclsid,
+ riid,
+ FALSE,
+ FALSE,
+#ifdef WX86OLE
+ FALSE,
+#endif
+ dwContext & CLSCTX_INPROC_HANDLERS,
+ dwDllServerType,
+ hr);
+ }
+
+ return(punk);
+}
+#endif // GET_INPROC_FROM_SCM
diff --git a/private/ole32/com/objact/coscm.cxx b/private/ole32/com/objact/coscm.cxx
new file mode 100644
index 000000000..833b37ec1
--- /dev/null
+++ b/private/ole32/com/objact/coscm.cxx
@@ -0,0 +1,1535 @@
+
+*********************************************************************
+THIS FILE IS NO LONGER PART OF THE BUILD.
+IT IS BEING LEFT IN THE SLM ENLISTMENT FOR catsrc USAGE.
+SEE resolver.cxx in dcomrem or remote\chicago\resolver.hxx.
+*********************************************************************
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dcoscm.cxx
+//
+// Contents: Files relating to compobj communication with the SCM
+// for the DCOM version of OLE remoting.
+//
+// Functions: CCoScm::CCoScm
+// CCoScm::~CCoScm
+// CCoScm::BindToSCM
+// CCoScm::NotifyStarted
+// CCoScm::NotifyStopped
+//
+// History: 19-May-92 Ricksa Created
+// 20-May-95 AlexMit Use object interfaces
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include <coscm.hxx>
+#include <service.hxx> // GetLocalStringBinding
+#include <objerror.h>
+#include <sobjact.hxx>
+
+
+// mutex to guard binding to the SCM.
+extern COleStaticMutexSem g_mxsSingleThreadOle;
+
+
+// String arrays for the SCM process. These are used to tell the interface
+// marshaling code the protocol and endpoint of the SCM process.
+
+#ifdef _CHICAGO_
+typedef struct tagSCMSA
+{
+ unsigned short wNumEntries; // Number of entries in array.
+ unsigned short wSecurityOffset; // Offset of security info.
+ WCHAR awszStringArray[26];
+} SCMSA;
+
+SCMSA saSCM = {26, 25, L"mswmsg:[endpoint mapper]\0" };
+
+#else
+
+typedef struct tagSCMSA
+{
+ unsigned short wNumEntries; // Number of entries in array.
+ unsigned short wSecurityOffset; // Offset of security info.
+ WCHAR awszStringArray[60];
+} SCMSA;
+
+// The last 4 characters in the string define the security bindings.
+// \0xA is RPC_C_AUTHN_WINNT
+// \0xFFFF is COM_C_AUTHZ_NONE
+// \0 is an empty principle name
+SCMSA saSCM = {57, 56, L"ncalrpc:[epmapper,Security=Impersonation Dynamic False]\0\xA\xFFFF\0"};
+#endif
+
+// Static data members of CCoScm
+#ifndef _CHICAGO_
+#define INVALID_VALUE -1
+
+handle_t CCoScm::_hRPC = NULL;
+IOSCM * CCoScm::_pSCMSTA = NULL;
+IOSCM * CCoScm::_pSCMMTA = NULL;
+IDSCM * CCoScm::_pNewSCMSTA = NULL;
+IDSCM * CCoScm::_pNewSCMMTA = NULL;
+LONG CCoScm::_fInteractiveUser = INVALID_VALUE;
+LPWSTR CCoScm::_lpDesktop = NULL;
+enum CCoScm::_HandleState CCoScm::_HandleState = SCM_HSTATE_NOT_YET_RUNNING;
+COleStaticMutexSem CCoScm::_mHRpcLock;
+#endif
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: GetObjectClientDesktop
+//
+// Purpose: Get the string representing the desktop which the object
+// client runs on.
+//
+// Returns: A string representing the desktop or NULL.
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifdef _CHICAGO_
+inline LPWSTR GetObjectClientDesktop (void)
+{
+ return NULL;
+}
+#else // not _CHICAGO_
+LPWSTR GetObjectClientDesktop (void)
+{
+ LPWSTR lpDesktop = NULL;
+
+ HDESK hDesk = GetThreadDesktop (GetCurrentThreadId());
+ if (hDesk)
+ {
+ DWORD cbDesktop;
+
+ if (!GetUserObjectInformation (hDesk, UOI_NAME, NULL, 0, &cbDesktop)
+ && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ lpDesktop = (WCHAR *) PrivMemAlloc (cbDesktop);
+ if (lpDesktop != NULL)
+ {
+ GetUserObjectInformation(hDesk, UOI_NAME,
+ lpDesktop, cbDesktop, &cbDesktop);
+ }
+ }
+ }
+
+ return lpDesktop;
+}
+#endif // _CHICAGO_
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::CleanUp
+//
+// Synopsis: Release the RPC connection with the SCM
+//
+// History: 24-Jun-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+void CCoScm::CleanUp(void)
+{
+ // Just close the RPC handle if it has been set
+ if (_hRPC != NULL)
+ {
+ // make sure we don't try to reconnect
+ _HandleState = SCM_HSTATE_TERMINATING;
+
+ RpcBindingFree(&_hRPC);
+ _hRPC = NULL;
+ }
+
+ if (_pSCMSTA != NULL)
+ {
+ _pSCMSTA->Release();
+ _pSCMSTA = NULL;
+ }
+
+ if (_pSCMMTA != NULL)
+ {
+ _pSCMMTA->Release();
+ _pSCMMTA = NULL;
+ }
+
+ if (_pNewSCMSTA != NULL)
+ {
+ _pNewSCMSTA->Release();
+ _pNewSCMSTA = NULL;
+ }
+
+ if (_pNewSCMMTA != NULL)
+ {
+ _pNewSCMMTA->Release();
+ _pNewSCMMTA = NULL;
+ }
+
+ if (_lpDesktop != NULL)
+ {
+ PrivMemFree(_lpDesktop);
+ _lpDesktop = NULL;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::CleanUp
+//
+// Synopsis: Release the RPC connection with the SCM
+//
+// History: 24-Jun-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+void CCoScm::ShutDown(void)
+{
+ // Just close the RPC handle if it has been set
+ if (_HandleState != SCM_HSTATE_TERMINATING)
+ {
+ // Don't do the shutdown unless we have done the cleanup
+ CleanUp;
+
+ }
+
+ _HandleState = SCM_HSTATE_NOT_YET_RUNNING;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::BindToSCMBody
+//
+// Synopsis: Get a connection to the SCM
+//
+// Algorithm: The well known address is built for the SCM. Then we bind
+// to the address and release the string that we created.
+//
+// History: 19-May-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::BindToSCMBody(void)
+{
+ TRACECALL(TRACE_ACTIVATION, "CCoScm::BindToSCM");
+ ComDebOut((DEB_SCM, "CCoScm::BindToSCM\n"));
+
+ HRESULT hr = S_OK;
+
+ if ( _HandleState == SCM_HSTATE_RUNNING )
+ return hr;
+
+ // if the connection to the SCM is anything other than uninitialized,
+ // we are cleaning up, and we aren't going to ever give it out again.
+ // BUGBUG: find the right return code here...
+ if ( _HandleState != SCM_HSTATE_NOT_YET_RUNNING )
+ return E_FAIL;
+
+ // must single thread access to this code.
+ // WARNING: we cant use the SingleThreadOle lock since we could
+ // be called by the ORPC code in BindToSCMProxy below on another thread.
+ COleStaticLock lck(_mHRpcLock);
+
+ // Don't do anything if we already have a binding handle.
+ if (_hRPC == NULL)
+ {
+ RPC_STATUS sc = RpcBindingFromStringBinding(saSCM.awszStringArray,
+ &_hRPC);
+
+ if (sc != RPC_S_OK)
+ {
+ hr = HRESULT_FROM_WIN32(sc);
+ }
+
+#ifdef DCOM
+ // Determine if we're the interactive user
+ if (_fInteractiveUser == INVALID_VALUE)
+ {
+ HWINSTA hWinSta = OpenWindowStation(L"winsta0",
+ FALSE,
+ MAXIMUM_ALLOWED);
+ if (hWinSta == NULL)
+ {
+ _fInteractiveUser = FALSE;
+ }
+ else
+ {
+ _fInteractiveUser = TRUE;
+ CloseWindowStation(hWinSta);
+ }
+ }
+#endif // DCOM
+
+ if (_lpDesktop == NULL)
+ {
+ _lpDesktop = GetObjectClientDesktop();
+ }
+
+ _HandleState == SCM_HSTATE_RUNNING;
+ }
+
+ ComDebOut((SUCCEEDED(hr) ? DEB_SCM : DEB_ERROR,
+ "CCoScm::BindToSCM returns:%x _hRPC:%x\n", hr, _hRPC));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::BindToSCMProxy
+//
+// Synopsis: Get a proxy to the SCM Activation interface.
+//
+// History: 19-May-95 Rickhi Created
+//
+// Notes: The SCM activation interface is an ORPC interface so that
+// apartment model apps can receive callbacks and do cancels
+// while activating object servers.
+//
+// The reason we have 2 differnt BindToSCM routines is that
+// IrotGetUniqueProcessID is called during CoInitializeEx, before
+// we are initialized enough to be able to build a proxy, so for
+// all the routines that are RAW RPC and only require an Rpc
+// handle, we call BindToSCM, while the activation routines which
+// require a proxy, must call BindToSCMProxy.
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::BindToSCMProxy(void)
+{
+ TRACECALL(TRACE_ACTIVATION, "CCoScm::BindToSCMProxy");
+ ComDebOut((DEB_SCM, "CCoScm::BindToSCMProxy\n"));
+
+ // since we are calling out on this thread, we have to ensure that the
+ // call control is set up for this thread.
+ HRESULT hr = InitChannelIfNecessary();
+
+ // must single thread access to this code since we are creating just
+ // one proxy to the SCM usable by all threads, and multiple threads
+ // can try to simultaneously use it.
+
+ COleStaticLock lck(g_mxsSingleThreadOle);
+
+ if (IsSTAThread())
+ {
+ if (_pSCMSTA == NULL)
+ {
+ // Make a proxy to the SCM
+ hr = MakeSCMProxy((DUALSTRINGARRAY *)&saSCM, IID_IOSCM, (void **) &_pSCMSTA);
+ }
+
+ ComDebOut((SUCCEEDED(hr) ? DEB_SCM : DEB_ERROR,
+ "CCoScm::BindToSCMProxy returns:%x _pSCMSTA:%x\n", hr, _pSCMSTA));
+
+ if (_pNewSCMSTA == NULL)
+ {
+ HRESULT hr2;
+
+ // Make a proxy to the SCM
+ hr2 = MakeSCMProxy((DUALSTRINGARRAY *)&saSCM, IID_IDSCM, (void **) &_pNewSCMSTA);
+
+ ComDebOut((SUCCEEDED(hr2) ? DEB_SCM : DEB_ERROR,
+ "CCoScm::BindToSCMProxy for IDSCM returns %x.\n", hr2));
+
+ // make sure we set hr to the first failure here...
+ if (SUCCEEDED(hr) && FAILED(hr2))
+ hr = hr2;
+ }
+ }
+ else
+ {
+ if (_pSCMMTA == NULL)
+ {
+ // Make a proxy to the SCM
+ hr = MakeSCMProxy((DUALSTRINGARRAY *)&saSCM, IID_IOSCM, (void **) &_pSCMMTA);
+ }
+
+ ComDebOut((SUCCEEDED(hr) ? DEB_SCM : DEB_ERROR,
+ "CCoScm::BindToSCMProxy returns:%x _pSCMSTA:%x\n", hr, _pSCMMTA));
+
+ if (_pNewSCMMTA == NULL)
+ {
+ HRESULT hr2;
+
+ // Make a proxy to the SCM
+ hr2 = MakeSCMProxy((DUALSTRINGARRAY *)&saSCM, IID_IDSCM, (void **) &_pNewSCMMTA);
+
+ ComDebOut((SUCCEEDED(hr2) ? DEB_SCM : DEB_ERROR,
+ "CCoScm::BindToSCMProxy for IDSCM returns %x.\n", hr2));
+
+ // make sure we set hr to the first failure here...
+ if (SUCCEEDED(hr) && FAILED(hr2))
+ hr = hr2;
+ }
+ }
+
+ // Determine if we're the interactive user
+ if (_fInteractiveUser == INVALID_VALUE)
+ {
+ HWINSTA hWinSta = OpenWindowStation(L"winsta0",
+ FALSE,
+ MAXIMUM_ALLOWED);
+ if (hWinSta == NULL)
+ {
+ _fInteractiveUser = FALSE;
+ }
+ else
+ {
+ _fInteractiveUser = TRUE;
+ CloseWindowStation(hWinSta);
+ }
+ }
+
+ if (_lpDesktop == NULL)
+ {
+ _lpDesktop = GetObjectClientDesktop();
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::NotifyStarted
+//
+// Synopsis: Notify the SCM that a class has been started
+//
+// Arguments: [rclsid] - class started
+// [dwFlags] - whether class is multiple use or not.
+//
+// Algorithm: MISSING pending move to new marshal model.
+//
+// History: 19-May-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::NotifyStarted(
+ REFCLSID rclsid,
+ DWORD dwFlags,
+ DWORD& dwAtStorage,
+ DWORD& dwReg)
+{
+ TRACECALL(TRACE_ACTIVATION, "CCoScm::NotifyStarted");
+
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCM();
+ if (FAILED(hr))
+ return hr;
+
+ // Dig our local binding string out of the list of endpoints.
+ // Remember we are always local to our SCM so we don't have to
+ // send the entire set of endpoints. Just the one they need
+ // to call us.
+
+ LPWSTR pwszBindString = GetLocalStringBinding();
+ if (pwszBindString == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // Tell SCM that we are started
+ error_status_t rpcstat;
+
+ // for now, we only register one class at a time...
+ const DWORD OLE_CLASS_COUNT = 1;
+
+ RegOutput *pregout = NULL;
+ CObjServer *pobjserver = GetObjServer();
+
+ RegInput *pRegin = (RegInput*) new char[ sizeof(RegInput) + (OLE_CLASS_COUNT-1)*sizeof(RegInputEntry)];
+ pRegin->dwSize = OLE_CLASS_COUNT;
+ pRegin->rginent[0].clsid = rclsid;
+ pRegin->rginent[0].pwszEndPoint = pwszBindString;
+ pRegin->rginent[0].dwFlags = dwFlags;
+ pRegin->rginent[0].ipid = pobjserver->GetIPID();
+
+ do
+ {
+ hr = ObjectServerStarted(
+ _hRPC,
+ _lpDesktop,
+ pRegin,
+ &pregout,
+ &rpcstat
+ );
+
+ } while (RetryRPC(rpcstat));
+
+ PrivMemFree( pwszBindString );
+
+ ComDebOut(( (hr == S_OK) ? DEB_SCM : DEB_ERROR,
+ "Class Registration returned %x", hr));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ return HRESULT_FROM_WIN32(rpcstat);
+ }
+ else if (SUCCEEDED(hr))
+ {
+ Win4Assert((pregout->dwSize <= 2) &&
+ "CCoScm::NotifyStarted Invalid regout");
+ dwAtStorage = pregout->regoutent[0].dwAtStorage;
+ dwReg = pregout->regoutent[0].dwReg;
+
+ // Free memory from RPC
+ MIDL_user_free(pregout);
+ }
+
+ delete[] pRegin;
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::NotifyStopped
+//
+// Synopsis: Notify the SCM that the server is stopped.
+//
+// History: 19-May-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+void CCoScm::NotifyStopped(REFCLSID rclsid, DWORD dwReg)
+{
+ TRACECALL(TRACE_ACTIVATION, "CCoScm::NotifyStopped");
+
+ error_status_t rpcstat;
+
+ RevokeClasses revcls;
+ revcls.dwSize = 1;
+ revcls.revent[0].clsid = rclsid;
+ revcls.revent[0].dwReg = dwReg;
+
+ do
+ {
+ StopServer(_hRPC, &revcls, &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::GetClassObject
+//
+// Synopsis: Send a get object request to the SCM
+//
+// Arguments: [rclsid] - class id for class object
+// [dwCtrl] - type of server required
+// [ppIFDClassObj] - marshaled buffer for class object
+// [ppwszDllToLoad] - DLL name to use for server
+//
+// Returns: S_OK
+//
+// History: 20-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::OldGetClassObject(
+ REFCLSID rclsid,
+ DWORD dwContext,
+ WCHAR *pwszServer,
+ InterfaceData **ppIFDClassObj,
+ DWORD *pdwDllServerType,
+ WCHAR **ppwszDllToLoad)
+{
+ TRACECALL(TRACE_ACTIVATION, "CCoScm::GetClassObject");
+
+ Win4Assert(((*pdwDllServerType == APT_THREADED)
+ || (*pdwDllServerType == FREE_THREADED))
+ && "CCoScm::GetClassObject Invalid Requested Thread Model");
+
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCMProxy();
+ if (FAILED(hr))
+ return hr;
+
+ // determine the class context to use for this call. We should
+ // not allow a CoGetClassObject of a local server inside of an
+ // input sync call, but we have to allow inproc server because
+ // we may be unmarshalling an interface and need the proxy dll.
+
+ if (dwContext & CLSCTX_PS_DLL)
+ {
+ hr = GetSCM()->InputSyncStartObjectService(_lpDesktop,
+ &rclsid,
+ dwContext,
+ pwszServer,
+ ppIFDClassObj,
+ pdwDllServerType,
+ ppwszDllToLoad );
+ }
+ else
+ {
+ hr = GetSCM()->SyncStartObjectService( _lpDesktop,
+ &rclsid,
+ dwContext,
+ pwszServer,
+ ppIFDClassObj,
+ pdwDllServerType,
+ ppwszDllToLoad );
+ }
+
+ return hr;
+}
+
+#ifdef DCOM
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::GetClassObject
+//
+// Synopsis: Send a get object request to the SCM
+//
+// Arguments: [rclsid] - class id for class object
+// [dwCtrl] - type of server required
+// [ppIFDClassObj] - marshaled buffer for class object
+// [ppwszDllToLoad] - DLL name to use for server
+//
+// Returns: S_OK
+//
+// History: 20-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::GetClassObject(
+ REFCLSID rclsid,
+ DWORD dwContext,
+ COSERVERINFO *pServerInfo,
+ MInterfacePointer **ppIFDClassObj,
+ DWORD *pdwDllServerType,
+ WCHAR **ppwszDllToLoad)
+{
+ TRACECALL(TRACE_ACTIVATION, "CCoScm::GetClassObject");
+
+ Win4Assert(((*pdwDllServerType == APT_THREADED)
+ || (*pdwDllServerType == FREE_THREADED))
+ && "CCoScm::GetClassObject Invalid Requested Thread Model");
+
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCMProxy();
+ if (FAILED(hr))
+ return hr;
+
+ WCHAR * pServerName = NULL;
+
+ // extract the server information
+ if ( pServerInfo )
+ {
+ pServerName = pServerInfo->pszName;
+ }
+
+ // determine the class context to use for this call. We should
+ // not allow a CoGetClassObject of a local server inside of an
+ // input sync call, but we have to allow inproc server because
+ // we may be unmarshalling an interface and need the proxy dll.
+
+/*
+ HRESULT SCMGetClassObject(
+ COM_HANDLE
+ [in] const GUID * Clsid,
+ [in, string, unique] WCHAR * pwszServer,
+ [in, string, unique] WCHAR * pwszDesktop,
+ [in] DWORD ClsContext,
+ [in, out] DWORD * pDllServerType,
+ [out, string] WCHAR ** ppwszDllToLoad,
+ [out] InterfaceData ** ppIDClassFactory
+ );
+*/
+
+ if (dwContext & CLSCTX_PS_DLL)
+ {
+ hr = GetNewSCM()->InputSyncSCMGetClassObject(&rclsid,
+ pServerName,
+ _lpDesktop,
+ _fInteractiveUser,
+ dwContext,
+ pdwDllServerType,
+ ppwszDllToLoad,
+ ppIFDClassObj );
+ }
+ else
+ {
+ hr = GetNewSCM()->SCMGetClassObject( &rclsid,
+ pServerName,
+ _lpDesktop,
+ _fInteractiveUser,
+ dwContext,
+ pdwDllServerType,
+ ppwszDllToLoad,
+ ppIFDClassObj );
+ }
+
+ return hr;
+}
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::CreateObject
+//
+// Synopsis: Ask SCM to tell a server to create and activate an object
+//
+// Arguments: [rclsid] - class id for object to create
+// [dwOptions] - type of server required
+// [dwMode] - mode to open file if file name supplied
+// [pwszPath] - path to use for creating the file
+// [ppIFDstg] - istorage to use as a template for the file
+// [pwszNewName] - name of object to create.
+// [ppIFDunk] - marshaled interface to newly created object
+// [ppwszDllPath] - path to DLL for server or handler
+//
+// Returns: S_OK
+//
+// History: 20-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::CreateObject(
+ REFCLSID rclsid,
+ DWORD dwOptions,
+ DWORD dwMode,
+ WCHAR *pwszPath,
+ InterfaceData *pIFDstg,
+ WCHAR *pwszNewName,
+ InterfaceData **ppIFDunk,
+ DWORD *pdwDllServerType,
+ WCHAR **ppwszDllPath,
+ WCHAR *pwszServer)
+{
+ TRACECALL(TRACE_ACTIVATION, "CCoScm::CreateObject");
+
+ Win4Assert(((*pdwDllServerType == APT_THREADED)
+ || (*pdwDllServerType == FREE_THREADED))
+ && "CCoScm::CreateObject Invalid Requested Thread Model");
+
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCMProxy();
+ if (FAILED(hr))
+ return hr;
+
+ hr = GetSCM()->SvcCreateActivateObject(
+ _lpDesktop,
+ NULL,
+ &rclsid,
+ dwOptions,
+ dwMode,
+ pwszPath,
+ pIFDstg,
+ pwszNewName,
+ ppIFDunk,
+ pdwDllServerType,
+ ppwszDllPath,
+ pwszServer );
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::ActivateObject
+//
+// Synopsis: Activate an already existing object
+//
+// Arguments: [rclsid] - class id for object to create
+// [dwOptions] - type of server required
+// [grfMode] - mode to open file if file name supplied
+// [pwszPath] - path to use for the file
+// [ppIFDstg] - istorage to use for the file
+// [ppIFDunk] - marshaled interface to newly created object
+// [pdwDllServerType] -
+// [ppwszDllPath] - path to DLL for server or handler
+// [pwszServer] -
+//
+// Returns: S_OK
+//
+// History: 20-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::ActivateObject(
+ REFCLSID rclsid,
+ DWORD dwOptions,
+ DWORD grfMode,
+ WCHAR *pwszPath,
+ InterfaceData *pIFDstg,
+ InterfaceData **ppIFDunk,
+ DWORD *pdwDllServerType,
+ WCHAR **ppwszDllPath,
+ WCHAR *pwszServer)
+{
+ TRACECALL(TRACE_ACTIVATION, "CCoScm::ActivateObject");
+
+ Win4Assert(((*pdwDllServerType == APT_THREADED)
+ || (*pdwDllServerType == FREE_THREADED))
+ && "CCoScm::ActivateObject Invalid Requested Thread Model");
+
+ HRESULT hr = BindToSCMProxy();
+ if (FAILED(hr))
+ return hr;
+
+ hr = GetSCM()->SvcActivateObject(
+ _lpDesktop,
+ NULL,
+ &rclsid,
+ dwOptions,
+ grfMode,
+ 0,
+ pwszPath,
+ pIFDstg,
+ ppIFDunk,
+ pdwDllServerType,
+ ppwszDllPath,
+ pwszServer );
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::GetPersistentInstance
+//
+// Synopsis: Send a get object request to the SCM
+//
+//GAJGAJ - fix this comment block
+// Arguments: [rclsid] - class id for class object
+// [dwCtrl] - type of server required
+// [ppIFDClassObj] - marshaled buffer for class object
+// [ppwszDllToLoad] - DLL name to use for server
+//
+// Returns: S_OK
+//
+// History: 20-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::GetPersistentInstance(
+ COSERVERINFO * pServerInfo,
+ CLSID * pClsid,
+ DWORD dwClsCtx,
+ DWORD grfMode,
+ OLECHAR * pwszName,
+ MInterfacePointer * pstg,
+ DWORD dwCount,
+ IID * pIIDs,
+ MInterfacePointer ** pRetdItfs,
+ HRESULT * pRetdHrs,
+ DWORD * pdwDllServerType,
+ OLECHAR ** ppwszDllToLoad )
+{
+ TRACECALL(TRACE_ACTIVATION, "CCoScm::GetPersistentInstance");
+
+ Win4Assert(((*pdwDllServerType == APT_THREADED)
+ || (*pdwDllServerType == FREE_THREADED))
+ && "CCoScm::GetPersistentInstance Invalid Requested Thread Model");
+
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCMProxy();
+ if (FAILED(hr))
+ return hr;
+
+/*
+ [in] const GUID * Clsid,
+ [in, string, unique] WCHAR * pwszServer,
+ [in, string, unique] WCHAR * pwszDesktop,
+ [in, string, unique] WCHAR * pwszObjectName,
+ [in, unique] InterfaceData * pObjectStorage,
+ [in] DWORD ClsContext,
+ [in] DWORD FileMode,
+ [in] DWORD Interfaces,
+ [in,size_is(Interfaces)] IID * pIIDs,
+ [in, out] DWORD * pdwDllServerType,
+ [out, string] WCHAR ** ppwszDllToLoad,
+ [out,size_is(Interfaces)] PInterfaceData * ppInterfaceData,
+ [out,size_is(Interfaces)] HRESULT * pResults
+*/
+ hr = GetNewSCM()->SCMGetPersistentInstance(
+ pClsid,
+ pServerInfo ? pServerInfo->pszName : 0,
+ _lpDesktop,
+ _fInteractiveUser,
+ pwszName,
+ pstg,
+ dwClsCtx,
+ grfMode,
+ dwCount,
+ pIIDs,
+ pdwDllServerType,
+ ppwszDllToLoad,
+ pRetdItfs,
+ pRetdHrs);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::CreateInstance
+//
+// Synopsis: Send a get object request to the SCM
+//
+//GAJGAJ - fix this comment block
+// Arguments: [rclsid] - class id for class object
+// [dwCtrl] - type of server required
+// [ppIFDClassObj] - marshaled buffer for class object
+// [ppwszDllToLoad] - DLL name to use for server
+//
+// Returns: S_OK
+//
+// History: 20-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::CreateInstance(
+ COSERVERINFO * pServerInfo,
+ CLSID * pClsid,
+ DWORD dwClsCtx,
+ DWORD dwCount,
+ IID * pIIDs,
+ MInterfacePointer ** pRetdItfs,
+ HRESULT * pRetdHrs,
+ DWORD * pdwDllServerType,
+ OLECHAR ** ppwszDllToLoad )
+{
+ TRACECALL(TRACE_ACTIVATION, "CCoScm::CreateInstance");
+
+ Win4Assert(((*pdwDllServerType == APT_THREADED)
+ || (*pdwDllServerType == FREE_THREADED))
+ && "CCoScm::GetPersistentInstance Invalid Requested Thread Model");
+
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCMProxy();
+ if (FAILED(hr))
+ return hr;
+
+/*
+ [in] const GUID * Clsid,
+ [in, string, unique] WCHAR * pwszServer,
+ [in, string, unique] WCHAR * pwszDesktop,
+ [in] DWORD ClsContext,
+ [in] DWORD Interfaces,
+ [in,size_is(Interfaces)] IID * pIIDs,
+ [in, out] DWORD * pDllServerType,
+ [out, string] WCHAR ** ppwszDllToLoad,
+ [out,size_is(Interfaces)] PInterfaceData * ppInterfaceData,
+ [out,size_is(Interfaces)] HRESULT * pResults
+*/
+ hr = GetNewSCM()->SCMCreateInstance(
+ pClsid,
+ pServerInfo ? pServerInfo->pszName : 0,
+ _lpDesktop,
+ _fInteractiveUser,
+ dwClsCtx,
+ dwCount,
+ pIIDs,
+ pdwDllServerType,
+ ppwszDllToLoad,
+ pRetdItfs,
+ pRetdHrs);
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCoScm::CreateInstanceWithHandler
+//
+// Synopsis: Calls scm which will launch the application for given class id
+// and instanciate a class object with a severhandler object.
+//
+// Arguments: [pServerInfo] --
+// [pClsid] --
+// [dwClsCtx] --
+// [dwCount] --
+// [pIIDs] --
+// [pRetdItfs] --
+// [pRetdHrs] --
+// [pdwDllServerType] --
+// [ppwszDllToLoad] --
+// [pClsidHandler] --
+// [ppIFPServerHandler] --
+// [pIFPClientSiteHandler] --
+//
+// Returns:
+//
+// History: 11-11-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CCoScm::CreateInstanceWithHandler(
+ COSERVERINFO * pServerInfo,
+ CLSID * pClsid,
+ DWORD dwClsCtx,
+ DWORD dwCount,
+ IID * pIIDs,
+ MInterfacePointer ** pRetdItfs,
+ HRESULT * pRetdHrs,
+ DWORD * pdwDllServerType,
+ OLECHAR ** ppwszDllToLoad,
+ CLSID * pClsidHandler,
+ MInterfacePointer ** ppIFPServerHandler,
+ MInterfacePointer * pIFPClientSiteHandler
+ )
+{
+TRACECALL(TRACE_ACTIVATION, "CCoScm::CreateInstanceWithHandler");
+
+ Win4Assert(((*pdwDllServerType == APT_THREADED)
+ || (*pdwDllServerType == FREE_THREADED))
+ && "CCoScm::GetPersistentInstance Invalid Requested Thread Model");
+
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCMProxy();
+ if (FAILED(hr))
+ return hr;
+
+/*
+ [in] const GUID * Clsid,
+ [in, string, unique] WCHAR * pwszServer,
+ [in, string, unique] WCHAR * pwszDesktop,
+ [in] DWORD ClsContext,
+ [in] DWORD Interfaces,
+ [in,size_is(Interfaces)] IID * pIIDs,
+ [in, out] DWORD * pDllServerType,
+ [out, string] WCHAR ** ppwszDllToLoad,
+ [out,size_is(Interfaces)] PInterfaceData * ppInterfaceData,
+ [out,size_is(Interfaces)] HRESULT * pResults
+ [in] CLSID * pClsidHandler,
+ [out] MInterfacePointer ** ppIFPServerHandler,
+ [in] MInterfacePointer * pIFPClientSiteHandler
+
+*/
+ hr = GetNewSCM()->SCMCreateInstanceWithHandler(
+ pClsid,
+ pServerInfo ? pServerInfo->pszName : 0,
+ _lpDesktop,
+ _fInteractiveUser,
+ dwClsCtx,
+ dwCount,
+ pIIDs,
+ pdwDllServerType,
+ ppwszDllToLoad,
+ pRetdItfs,
+ pRetdHrs,
+ pClsidHandler,
+ ppIFPServerHandler,
+ pIFPClientSiteHandler);
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotRegister
+//
+// Synopsis: Register an object in the ROT
+//
+// Arguments: [pmkeqbuf] - moniker compare buffer
+// [pifdObject] - marshaled interface for object
+// [pifdObjectName] - marshaled moniker
+// [pfiletime] - file time of last change
+// [dwProcessID] -
+// [psrkRegister] - output of registration
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::IrotRegister(
+ MNKEQBUF *pmkeqbuf,
+ InterfaceData *pifdObject,
+ InterfaceData *pifdObjectName,
+ FILETIME *pfiletime,
+ DWORD dwProcessID,
+ SCMREGKEY *psrkRegister)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCM();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+
+ do
+ {
+ hr = ::IrotRegister(
+ _hRPC,
+ pmkeqbuf,
+ pifdObject,
+ pifdObjectName,
+ pfiletime,
+ dwProcessID,
+ psrkRegister,
+ &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotRevoke
+//
+// Synopsis: Call to SCM to revoke object from the ROT
+//
+// Arguments: [psrkRegister] - moniker compare buffer
+// [fServerRevoke] - whether server for object is revoking
+// [pifdObject] - where to put marshaled object
+// [pifdName] - where to put marshaled moniker
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::IrotRevoke(
+ SCMREGKEY *psrkRegister,
+ BOOL fServerRevoke,
+ InterfaceData **ppifdObject,
+ InterfaceData **ppifdName)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCM();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+
+ do
+ {
+ hr = ::IrotRevoke(
+ _hRPC,
+ psrkRegister,
+ fServerRevoke,
+ ppifdObject,
+ ppifdName,
+ &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotIsRunning
+//
+// Synopsis: Call to SCM to determine if object is in the ROT
+//
+// Arguments: [pmkeqbuf] - moniker compare buffer
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::IrotIsRunning(MNKEQBUF *pmkeqbuf)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCM();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+
+ do
+ {
+ hr = ::IrotIsRunning(
+ _hRPC,
+ pmkeqbuf,
+ &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotGetObject
+//
+// Synopsis: Call to SCM to determine if object is in the ROT
+//
+// Arguments: [dwProcessID] - process ID for object we want
+// [pmkeqbuf] - moniker compare buffer
+// [psrkRegister] - registration ID in SCM
+// [pifdObject] - marshaled interface for the object
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::IrotGetObject(
+ DWORD dwProcessID,
+ MNKEQBUF *pmkeqbuf,
+ SCMREGKEY *psrkRegister,
+ InterfaceData **pifdObject)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCM();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+
+ do
+ {
+ hr = ::IrotGetObject(
+ _hRPC,
+ dwProcessID,
+ pmkeqbuf,
+ psrkRegister,
+ pifdObject,
+ &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotNoteChangeTime
+//
+// Synopsis: Call to SCM to set time of change for object in the ROT
+//
+// Arguments: [psrkRegister] - SCM registration ID
+// [pfiletime] - time of change
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::IrotNoteChangeTime(
+ SCMREGKEY *psrkRegister,
+ FILETIME *pfiletime)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCM();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+
+ do
+ {
+ hr = ::IrotNoteChangeTime(
+ _hRPC,
+ psrkRegister,
+ pfiletime,
+ &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotGetTimeOfLastChange
+//
+// Synopsis: Call to SCM to get time changed of object in the ROT
+//
+// Arguments: [pmkeqbuf] - moniker compare buffer
+// [pfiletime] - where to put time of last change
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::IrotGetTimeOfLastChange(
+ MNKEQBUF *pmkeqbuf,
+ FILETIME *pfiletime)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCM();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+
+ do
+ {
+ hr = ::IrotGetTimeOfLastChange(
+ _hRPC,
+ pmkeqbuf,
+ pfiletime,
+ &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotEnumRunning
+//
+// Synopsis: Call to SCM to enumerate running objects in the ROT
+//
+// Arguments: [ppMkIFList] - output pointer to array of marshaled monikers
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::IrotEnumRunning(MkInterfaceList **ppMkIFList)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCM();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+
+ do
+ {
+ hr = ::IrotEnumRunning(
+ _hRPC,
+ ppMkIFList,
+ &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+ return hr;
+}
+
+#ifndef _CHICAGO_
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotGetUniqueProcessID
+//
+// Synopsis: Call to SCM to generate a unique process ID
+//
+// Arguments: [pdwProcessID] - Returns a process ID
+//
+// Returns: S_OK - dwProcessID is valid
+// other - dwProcessID is undefined
+//
+// History: 28-Mar-95 KevinRo Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::IrotGetUniqueProcessID(DWORD *pdwProcessID,
+ DWORD *pdwScmProcessID)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCM();
+ if (FAILED(hr ))
+ return hr;
+
+ error_status_t rpcstat = RPC_S_OK;
+
+ do
+ {
+ hr = ::IrotGetUniqueProcessID(
+ _hRPC,
+ pdwProcessID,
+ pdwScmProcessID,
+ &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ hr = CO_E_SCM_RPC_FAILURE;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::UpdateShrdTbls
+//
+// Synopsis: Ask the SCM to update the shared memory tables.
+//
+// Arguments: none
+//
+// History: 11-July-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::UpdateShrdTbls(void)
+{
+ TRACECALL(TRACE_ACTIVATION, "CCoScm::UpdateShrdTbls");
+
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCM();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat;
+
+ do
+ {
+ hr = ::UpdateShrdTbls(_hRPC, &rpcstat);
+
+ } while (RetryRPC(rpcstat));
+
+
+ ComDebOut(( (hr == S_OK) ? DEB_SCM : DEB_ERROR,
+ "UpdateShrdTbls returned %x\n", hr));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ return HRESULT_FROM_WIN32(rpcstat);
+ }
+
+ return hr;
+}
+#endif // _CHICAGO_
+
+
+#ifdef DCOM
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::RegisterWindowPropInterface
+//
+// Synopsis: Register window property interface with the SCM
+//
+// Arguments:
+//
+// History: 22-Jan-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::RegisterWindowPropInterface(HWND hWnd, STDOBJREF *pStd,
+ OXID_INFO *pOxidInfo,
+ DWORD *pdwCookie)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCM();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat;
+
+ do
+ {
+ hr = ::RegisterWindowPropInterface(_hRPC, (DWORD) hWnd,
+ pStd, pOxidInfo, pdwCookie, &rpcstat);
+ } while (RetryRPC(rpcstat));
+
+ ComDebOut(( (hr == S_OK) ? DEB_SCM : DEB_ERROR,
+ "RegisterWindowPropInterface returned %x\n", hr));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ return HRESULT_FROM_WIN32(rpcstat);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::RegisterWindowPropInterface
+//
+// Synopsis: Get (and possibly Revoke) window property interface
+// registration with the SCM.
+//
+// Arguments:
+//
+// History: 22-Jan-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT CCoScm::GetWindowPropInterface(HWND hWnd, DWORD dwCookie, BOOL fRevoke,
+ STDOBJREF *pStd, OXID_INFO *pOxidInfo)
+{
+ // Bind to the SCM if that hasn't already happened
+ HRESULT hr = BindToSCM();
+ if (FAILED(hr))
+ return hr;
+
+ error_status_t rpcstat;
+
+ do
+ {
+ hr = ::GetWindowPropInterface(_hRPC, (DWORD) hWnd, dwCookie, fRevoke,
+ pStd, pOxidInfo, &rpcstat);
+ } while (RetryRPC(rpcstat));
+
+ ComDebOut(( (hr == S_OK) ? DEB_SCM : DEB_ERROR,
+ "GetWindowPropInterface returned %x\n", hr));
+
+ if (rpcstat != RPC_S_OK)
+ {
+ return HRESULT_FROM_WIN32(rpcstat);
+ }
+
+ return hr;
+}
+
+#endif // DCOM
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::RetryRPC
+//
+// Synopsis: Determines whether RPC to SCM should be retried.
+//
+// Arguments: [rpcstat] - status of the operation
+//
+// Returns: TRUE - retry the operation
+// FALSE - do not retry the operation
+//
+// History: 06-Jun-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CCoScm::RetryRPC(error_status_t rpcstat)
+{
+ if (rpcstat == S_OK)
+ {
+ return FALSE;
+ }
+
+ TRACECALL(TRACE_ACTIVATION, "CCoScm::RetryRpc");
+
+ // Special server error that means the server will probably
+ // recover.
+ if (rpcstat == RPC_S_SERVER_TOO_BUSY)
+ {
+ CairoleDebugOut(( DEB_ITRACE|DEB_SCM,
+ "CCoScm::RetryRPC is sleeping\n"));
+ // If the SCM is too busy to talk with us, take a break
+ Sleep(3000);
+
+ // We will try again
+ // BUGBUG: this is currently an infinite loop. Should
+ // there be a retry limit?
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/private/ole32/com/objact/coscm.hxx b/private/ole32/com/objact/coscm.hxx
new file mode 100644
index 000000000..a0ebde3cc
--- /dev/null
+++ b/private/ole32/com/objact/coscm.hxx
@@ -0,0 +1,928 @@
+
+*********************************************************************
+THIS FILE IS NO LONGER PART OF THE BUILD.
+IT IS BEING LEFT IN THE SLM ENLISTMENT FOR catsrc USAGE.
+SEE resolver.hxx in dcomrem or remote\chicago.
+*********************************************************************
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: coscm.hxx
+//
+// Contents: class declaration for SCM object
+//
+// Classes: CLogicalThread
+// CCoScm
+//
+// Functions: CLogicalThread::CLogicalThread
+//
+// History: 20-May-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+//
+//--------------------------------------------------------------------------
+#ifndef __COSCM_HXX__
+#define __COSCM_HXX__
+
+#include <iface.h>
+#include <scm.h>
+#include <irot.h>
+#include <olesem.hxx>
+
+#ifdef DCOM
+#include <oscm.h>
+#include <dscm.h>
+#else
+#include <channelb.hxx>
+#include <endpnt.hxx>
+#define STRING_BINDING_OPTIONS L"Security=Impersonation Dynamic False"
+#endif // DCOM
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CCoScm
+//
+// Purpose: Provide abstraction for communication with the SCM
+//
+// Interface: BindToSCM - Bind to the SCM
+// BindToSCMProxy- build proxy to SCM for Activation (DCOM only)
+// CleanUp - release Rpc connection with SCM
+// NotifyStarted - Notify SCM that a class has started
+// NotifyStopped - Notify SCM that a class has stopped
+// GetClassObject- Ask SCM to get us a class object
+// CreateObject - Ask SCM to create an object
+// ActivateObject- Ask SCM to activate an object
+// IrotRegister - register object with ROT
+// IrotRevoke - unregister object with ROT
+// IrotIsRunning - check if object is registered in the ROT
+// IrotGetObject - get object from ROT
+// IrotNoteChangeTime - register time of last change
+// IrotGetTimeOfLastChange - get time of last change
+// IrotEnumRunning - enumerate objects registered in ROT
+// IrotGetUniqueProcessID - get unique process id
+// UpdateShrdTbls- update shared tables
+//
+// History: 20-May-93 Ricksa Created
+// 09-Jan-96 BruceMa Add interactive user boolean
+//
+//--------------------------------------------------------------------------
+class CCoScm
+{
+public:
+ void CleanUp(void);
+
+ void ShutDown(void);
+
+ // Notify the dirty SCM that a class has started
+ HRESULT NotifyStarted(
+ REFCLSID rclsid,
+ DWORD dwFlags,
+ DWORD& dwAtStorage,
+ DWORD& dwReg);
+
+ // Notify the dirty SCM that the class has stopped
+ void NotifyStopped(REFCLSID rclsid, DWORD dwReg);
+
+#ifdef DCOM
+ // Get class object information from SCM
+ HRESULT GetClassObject(
+ REFCLSID rclsid,
+ DWORD dwCtrl,
+ COSERVERINFO *pServerInfo,
+ MInterfacePointer **ppIFDClassObj,
+ DWORD *pdwDllServerType,
+ WCHAR **ppwszDllToLoad);
+#endif
+
+ // Get class object information from SCM
+ HRESULT OldGetClassObject(
+ REFCLSID rclsid,
+ DWORD dwCtrl,
+ WCHAR *pwszServer,
+ InterfaceData **ppIFDClassObj,
+ DWORD *pdwDllServerType,
+ WCHAR **ppwszDllToLoad);
+
+ // Create and activate object
+ HRESULT CreateObject(
+ REFCLSID rclsid,
+ DWORD dwOptions,
+ DWORD dwMode,
+ WCHAR *pwszPath,
+ InterfaceData *pIFDstg,
+ WCHAR *pwszNewName,
+ InterfaceData **ppIFDunk,
+ DWORD *pdwDllServerType,
+ WCHAR **pwszDllPath,
+ WCHAR *pwszServer);
+
+ // Activate object
+ HRESULT ActivateObject(
+ REFCLSID rclsid,
+ DWORD dwOptions,
+ DWORD grfMode,
+ WCHAR *pwszPath,
+ InterfaceData *pIFDstg,
+ InterfaceData **ppIFDunk,
+ DWORD *pdwDllServerType,
+ WCHAR **pwszDllPath,
+ WCHAR *pwszServer);
+
+ // Register object in the SCM ROT
+ HRESULT IrotRegister(
+ MNKEQBUF *pmkeqbuf,
+ InterfaceData *pifdObject,
+ InterfaceData *pifdObjectName,
+ FILETIME *pfiletime,
+ DWORD dwProcessID,
+ SCMREGKEY *pdwRegister);
+
+ // Revoke the object from the SCM ROT
+ HRESULT IrotRevoke(
+ SCMREGKEY *psrkRegister,
+ BOOL fServerRevoke,
+ InterfaceData **pifdObject,
+ InterfaceData **pifdName);
+
+ // Determine if object is running in the SCM ROT
+ HRESULT IrotIsRunning(
+ MNKEQBUF *pmkeqbuf);
+
+ // Get object from the SCM ROT
+ HRESULT IrotGetObject(
+ DWORD dwProcessID,
+ MNKEQBUF *pmkeqbuf,
+ SCMREGKEY *psrkRegister,
+ InterfaceData **pifdObject);
+
+ // Update time of last change in SCM ROT
+ HRESULT IrotNoteChangeTime(
+ SCMREGKEY *psrkRegister,
+ FILETIME *pfiletime);
+
+ // Get time of last change from SCM ROT
+ HRESULT IrotGetTimeOfLastChange(
+ MNKEQBUF *pmkeqbuf,
+ FILETIME *pfiletime);
+
+ // Enumerate all running objects in SCM ROT
+ HRESULT IrotEnumRunning(
+ MkInterfaceList **ppMkIFList);
+
+#ifndef _CHICAGO_
+ // Generate a unique process ID
+ HRESULT IrotGetUniqueProcessID(
+ DWORD *pdwProcessID,
+ DWORD *pdwScmProcessID
+ );
+
+ HRESULT UpdateShrdTbls(void);
+#endif // _CHICAGO_
+
+#ifdef DCOM
+ HRESULT RegisterWindowPropInterface(
+ HWND hWnd,
+ STDOBJREF *pStd,
+ OXID_INFO *pOxidInfo,
+ DWORD *pdwCookie);
+
+ HRESULT GetWindowPropInterface(
+ HWND hWnd,
+ DWORD dwCookie,
+ BOOL fRevoke,
+ STDOBJREF *pStd,
+ OXID_INFO *pOxidInfo);
+#endif // DCOM
+
+private:
+
+ // Get a connection to the SCM
+ HRESULT BindToSCM(void);
+ IOSCM * GetSCM(void);
+ IDSCM * GetNewSCM(void);
+
+ // For Chicago there is no communication with the SCM since the SCM
+ // is in shared memory. Therefore, for Chicago, all calls become direct
+ // calls to the appropriate routine and there is no need for data
+ // internal to this class.
+
+#ifdef DCOM
+public:
+ HRESULT GetPersistentInstance(
+ COSERVERINFO * pServerInfo,
+ CLSID * pClsid,
+ DWORD dwClsCtx,
+ DWORD grfMode,
+ OLECHAR * pwszName,
+ MInterfacePointer * pstg,
+ DWORD dwCount,
+ IID * pIIDs,
+ MInterfacePointer ** pRetdItfs,
+ HRESULT * pRetdHrs,
+ DWORD * pdwDllServerType,
+ OLECHAR ** ppwszDllToLoad );
+
+ HRESULT CreateInstance(
+ COSERVERINFO * pServerInfo,
+ CLSID * pClsid,
+ DWORD dwClsCtx,
+ DWORD dwCount,
+ IID * pIIDs,
+ MInterfacePointer ** pRetdItfs,
+ HRESULT * pRetdHrs,
+ DWORD * pdwDllServerType,
+ OLECHAR ** ppwszDllToLoad );
+
+ HRESULT CreateInstanceWithHandler(
+ COSERVERINFO * pServerInfo,
+ CLSID * pClsid,
+ DWORD dwClsCtx,
+ DWORD dwCount,
+ IID * pIIDs,
+ MInterfacePointer ** pRetdItfs,
+ HRESULT * pRetdHrs,
+ DWORD * pdwDllServerType,
+ OLECHAR ** ppwszDllToLoad,
+ CLSID * pClsidHandler,
+ MInterfacePointer ** ppIFPServerHandler,
+ MInterfacePointer * pIFPClientSiteHandler
+ );
+
+
+
+private:
+
+ // Get a proxy to the SCM Activation Interface
+ HRESULT BindToSCMProxy(void);
+
+ // the body of the BindToSCM call
+ HRESULT BindToSCMBody(void);
+
+ // restore our state to uninitialized
+ HRESULT Shutdown(void);
+
+ // Whether we should retry RPC call
+ BOOL RetryRPC(error_status_t rpcstat);
+
+ // Handle to the SCM and its lock.
+ static handle_t _hRPC;
+ static COleStaticMutexSem _mHRpcLock;
+
+ // state flag to make sure we never try to reconstruct the
+ // RPC handle to the SCM. This also allows a quick inline
+ // version (below) of BindToSCM.
+ static enum _HandleState {
+ SCM_HSTATE_NOT_YET_RUNNING,
+ SCM_HSTATE_RUNNING,
+ SCM_HSTATE_TERMINATING } _HandleState;
+
+ // Proxy to the SCM's object interface
+ static IOSCM * _pSCMSTA;
+ static IOSCM * _pSCMMTA;
+
+ static IDSCM * _pNewSCMSTA;
+ static IDSCM * _pNewSCMMTA;
+
+ static LONG _fInteractiveUser;
+
+#endif // DCOM
+ // desktop string
+ static LPWSTR _lpDesktop;;
+
+};
+
+
+#ifdef DCOM
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::BindToSCM
+//
+// Synopsis: DCOM inline BindToSCM piece. If already bound, just return S_OK.
+//
+// History: 19-May-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CCoScm::BindToSCM(void)
+{
+ if ( _HandleState == SCM_HSTATE_RUNNING )
+ return S_OK;
+
+ // if the connection to the SCM is anything other than uninitialized,
+ // we are cleaning up, and we aren't going to ever give it out again.
+ // BUGBUG: find the right return code here...
+ if ( _HandleState != SCM_HSTATE_NOT_YET_RUNNING )
+ return E_FAIL;
+
+ return BindToSCMBody();
+}
+
+inline IOSCM * CCoScm::GetSCM(void)
+{
+ return (IsSTAThread()) ? _pSCMSTA : _pSCMMTA;
+}
+
+inline IDSCM * CCoScm::GetNewSCM(void)
+{
+ return (IsSTAThread()) ? _pNewSCMSTA : _pNewSCMMTA;
+}
+#endif // DCOM
+
+
+#ifndef DCOM
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::Cleanup
+//
+// Synopsis: Non-DCOM version of cleanup.
+//
+// History: 19-May-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CCoScm::CleanUp(void)
+{
+ // this is a noop on non DCOM platforms.
+}
+
+#endif // DCOM
+
+
+//
+// For Chicago, we make all the calls inline since the SCM is in the
+// same process as the caller.
+//
+#ifdef _CHICAGO_
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::NotifyStarted
+//
+// Synopsis: Notify the SCM that a class has been started
+//
+// Arguments: [rclsid] - class started
+// [dwFlags] - whether class is multiple use or not.
+//
+// Algorithm: MISSING pending move to new marshal model.
+//
+// History: 19-May-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CCoScm::NotifyStarted(
+ REFCLSID rclsid,
+ DWORD dwFlags,
+ DWORD& dwAtStorage,
+ DWORD& dwReg)
+{
+ // Result from call
+ HRESULT hr;
+
+ // Dig our local binding string out of the list of endpoints.
+ // Remember we are always local to our SCM so we don't have to
+ // send the entire set of endpoints. Just the one they need
+ // to call us.
+
+ CairoleAssert(LocalService() && "RPC Server not defined");
+ LPWSTR pwszBindString = LocalService()->GetStringBinding();
+ CairoleAssert(pwszBindString && "No local endpoint");
+
+ // Tell SCM that we are started
+ error_status_t rpcstat;
+
+ RegInput regin;
+ RegOutput *pregout = NULL;
+ regin.dwSize = 1;
+ regin.rginent[0].clsid = rclsid;
+ regin.rginent[0].pwszEndPoint = pwszBindString;
+ regin.rginent[0].dwFlags = dwFlags;
+
+ hr = ObjectServerStarted(
+ NULL,
+ NULL,
+ &regin,
+ &pregout,
+ &rpcstat);
+
+ if (rpcstat != RPC_S_OK)
+ {
+ return HRESULT_FROM_WIN32(rpcstat);
+ }
+
+ CairoleDebugOut(( (hr == S_OK) ? DEB_SCM : DEB_ERROR,
+ "CCoScm::NotifyStarted returned %x", hr));
+
+ if (SUCCEEDED(hr))
+ {
+ Win4Assert((pregout->dwSize == 1) &&
+ "CCoScm::NotifyStarted Invalid regout");
+
+ dwAtStorage = pregout->regoutent[0].dwAtStorage;
+ dwReg = pregout->regoutent[0].dwReg;
+
+ // Free memory from RPC
+ MIDL_user_free(pregout);
+ }
+
+ return hr;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::NotifyStopped
+//
+// Synopsis: Notify the SCM that the server is stopped.
+//
+// History: 19-May-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CCoScm::NotifyStopped(REFCLSID rclsid, DWORD dwReg)
+{
+ error_status_t rpcstat;
+
+ RevokeClasses revcls;
+ revcls.dwSize = 1;
+ revcls.revent[0].clsid = rclsid;
+ revcls.revent[0].dwReg = dwReg;
+
+ StopServer(NULL, &revcls, &rpcstat);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::GetClassObject
+//
+// Synopsis: Send a get object request to the SCM
+//
+// Arguments: [rclsid] - class id for class object
+// [dwCtrl] - type of server required
+// [ppIFDClassObj] - marshaled buffer for class object
+// [ppwszDllToLoad] - DLL name to use for server
+//
+// Returns: S_OK
+//
+// History: 20-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CCoScm::OldGetClassObject(
+ REFCLSID rclsid,
+ DWORD dwContext,
+ WCHAR *pwszServer,
+ InterfaceData **ppIFDClassObj,
+ DWORD *pdwDllServerType,
+ WCHAR **ppwszDllToLoad)
+{
+ CairoleAssert(((*pdwDllServerType == APT_THREADED)
+ || (*pdwDllServerType == FREE_THREADED))
+ && "CCoScm::GetClassObject Invalid Requested Thread Model");
+
+ error_status_t rpcstat;
+
+ return StartObjectService(
+ NULL,
+ NULL,
+ TLSGetLogicalThread(),
+ &rclsid,
+ dwContext,
+ pwszServer,
+ ppIFDClassObj,
+ pdwDllServerType,
+ ppwszDllToLoad,
+ &rpcstat);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::CreateObject
+//
+// Synopsis: Ask SCM to tell a server to create and activate an object
+//
+// Arguments: [rclsid] - class id for object to create
+// [dwOptions] - type of server required
+// [dwMode] - mode to open file if file name supplied
+// [pwszPath] - path to use for creating the file
+// [ppIFDstg] - istorage to use as a template for the file
+// [pwszNewName] - name of object to create.
+// [ppIFDunk] - marshaled interface to newly created object
+// [ppwszDllPath] - path to DLL for server or handler
+//
+// Returns: S_OK
+//
+// History: 20-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CCoScm::CreateObject(
+ REFCLSID rclsid,
+ DWORD dwOptions,
+ DWORD dwMode,
+ WCHAR *pwszPath,
+ InterfaceData *pIFDstg,
+ WCHAR *pwszNewName,
+ InterfaceData **ppIFDunk,
+ DWORD *pdwDllServerType,
+ WCHAR **ppwszDllPath,
+ WCHAR *pwszServer)
+{
+ CairoleAssert(((*pdwDllServerType == APT_THREADED)
+ || (*pdwDllServerType == FREE_THREADED))
+ && "CCoScm::CreateObject Invalid Requested Thread Model");
+
+ error_status_t rpcstat = RPC_S_OK;
+ DWORD dwTIDCallee = 0;
+
+ return SvcCreateActivateObject(
+ NULL,
+ NULL,
+ NULL,
+ TLSGetLogicalThread(),
+ &rclsid,
+ dwOptions,
+ dwMode,
+ pwszPath,
+ pIFDstg,
+ pwszNewName,
+ ppIFDunk,
+ pdwDllServerType,
+ ppwszDllPath,
+ pwszServer,
+ GetCurrentThreadId(),
+ &dwTIDCallee,
+ &rpcstat);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::ActivateObject
+//
+// Synopsis: Activate an already existing object
+//
+// Arguments: [rclsid] - class id for object to create
+// [dwOptions] - type of server required
+// [grfMode] - mode to open file if file name supplied
+// [pwszPath] - path to use for the file
+// [ppIFDstg] - istorage to use for the file
+// [ppIFDunk] - marshaled interface to newly created object
+// [ppwszDllPath] - path to DLL for server or handler
+//
+// Returns: S_OK
+//
+// History: 20-May-93 Ricksa Created
+// 18-Aug-94 AlexT Add caller thread id
+//
+//--------------------------------------------------------------------------
+inline HRESULT CCoScm::ActivateObject(
+ REFCLSID rclsid,
+ DWORD dwOptions,
+ DWORD grfMode,
+ WCHAR *pwszPath,
+ InterfaceData *pIFDstg,
+ InterfaceData **ppIFDunk,
+ DWORD *pdwDllServerType,
+ WCHAR **ppwszDllPath,
+ WCHAR *pwszServer)
+{
+ CairoleAssert(((*pdwDllServerType == APT_THREADED)
+ || (*pdwDllServerType == FREE_THREADED))
+ && "CCoScm::ActivateObject Invalid Requested Thread Model");
+
+ error_status_t rpcstat;
+ DWORD dwTIDCallee = 0;
+
+ return SvcActivateObject(
+ NULL,
+ NULL,
+ NULL,
+ TLSGetLogicalThread(),
+ &rclsid,
+ dwOptions,
+ grfMode,
+ 0,
+ pwszPath,
+ pIFDstg,
+ ppIFDunk,
+ pdwDllServerType,
+ ppwszDllPath,
+ pwszServer,
+ GetCurrentThreadId(),
+ &dwTIDCallee,
+ &rpcstat);
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotRegister
+//
+// Synopsis: Register an object in the ROT
+//
+// Arguments: [pmkeqbuf] - moniker compare buffer
+// [pifdObject] - marshaled interface for object
+// [pifdObjectName] - marshaled moniker
+// [pfiletime] - file time of last change
+// [psrkRegister] - output of registration
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CCoScm::IrotRegister(
+ MNKEQBUF *pmkeqbuf,
+ InterfaceData *pifdObject,
+ InterfaceData *pifdObjectName,
+ FILETIME *pfiletime,
+ DWORD dwProcessID,
+ SCMREGKEY *psrkRegister)
+{
+ error_status_t rpcstat;
+
+ return ::IrotRegister(
+ NULL,
+ pmkeqbuf,
+ pifdObject,
+ pifdObjectName,
+ pfiletime,
+ dwProcessID,
+ psrkRegister,
+ &rpcstat);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotRevoke
+//
+// Synopsis: Call to SCM to revoke object from the ROT
+//
+// Arguments: [psrkRegister] - moniker compare buffer
+// [fServerRevoke] - whether server for object is revoking
+// [pifdObject] - where to put marshaled object
+// [pifdName] - where to put marshaled moniker
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CCoScm::IrotRevoke(
+ SCMREGKEY *psrkRegister,
+ BOOL fServerRevoke,
+ InterfaceData **ppifdObject,
+ InterfaceData **ppifdName)
+{
+ error_status_t rpcstat;
+
+ return ::IrotRevoke(
+ NULL,
+ psrkRegister,
+ fServerRevoke,
+ ppifdObject,
+ ppifdName,
+ &rpcstat);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotIsRunning
+//
+// Synopsis: Call to SCM to determine if object is in the ROT
+//
+// Arguments: [pmkeqbuf] - moniker compare buffer
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CCoScm::IrotIsRunning(MNKEQBUF *pmkeqbuf)
+{
+ error_status_t rpcstat;
+
+ return ::IrotIsRunning(
+ NULL,
+ pmkeqbuf,
+ &rpcstat);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotGetObject
+//
+// Synopsis: Call to SCM to determine if object is in the ROT
+//
+// Arguments: [dwProcessID] - process ID for object we want
+// [pmkeqbuf] - moniker compare buffer
+// [psrkRegister] - registration ID in SCM
+// [pifdObject] - marshaled interface for the object
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CCoScm::IrotGetObject(
+ DWORD dwProcessID,
+ MNKEQBUF *pmkeqbuf,
+ SCMREGKEY *psrkRegister,
+ InterfaceData **pifdObject)
+{
+ error_status_t rpcstat;
+
+ return ::IrotGetObject(
+ NULL,
+ dwProcessID,
+ pmkeqbuf,
+ psrkRegister,
+ pifdObject,
+ &rpcstat);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotNoteChangeTime
+//
+// Synopsis: Call to SCM to set time of change for object in the ROT
+//
+// Arguments: [psrkRegister] - SCM registration ID
+// [pfiletime] - time of change
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CCoScm::IrotNoteChangeTime(
+ SCMREGKEY *psrkRegister,
+ FILETIME *pfiletime)
+{
+ error_status_t rpcstat;
+
+ return ::IrotNoteChangeTime(
+ NULL,
+ psrkRegister,
+ pfiletime,
+ &rpcstat);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotGetTimeOfLastChange
+//
+// Synopsis: Call to SCM to get time changed of object in the ROT
+//
+// Arguments: [pmkeqbuf] - moniker compare buffer
+// [pfiletime] - where to put time of last change
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CCoScm::IrotGetTimeOfLastChange(
+ MNKEQBUF *pmkeqbuf,
+ FILETIME *pfiletime)
+{
+ error_status_t rpcstat;
+
+ return ::IrotGetTimeOfLastChange(
+ NULL,
+ pmkeqbuf,
+ pfiletime,
+ &rpcstat);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCoScm::IrotEnumRunning
+//
+// Synopsis: Call to SCM to enumerate running objects in the ROT
+//
+// Arguments: [ppMkIFList] - output pointer to array of marshaled monikers
+//
+// Returns: S_OK
+//
+// History: 28-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CCoScm::IrotEnumRunning(MkInterfaceList **ppMkIFList)
+{
+ error_status_t rpcstat;
+
+ return ::IrotEnumRunning(
+ NULL,
+ ppMkIFList,
+ &rpcstat);
+}
+
+
+#endif // _CHICAGO_
+
+
+
+
+
+#ifndef DCOM
+
+// CODEWORK: these probably belong some place else
+
+// return size in bytes of unicode string, including null; will always be even;
+// string may be NULL in which case 0 is returned.
+inline DWORD CbFromWideString(WCHAR *pwsz)
+{
+ if (pwsz == NULL)
+ return 0;
+ else
+ {
+ return (lstrlenW(pwsz) + 1) * sizeof(WCHAR);
+ }
+}
+
+
+// return size in bytes of interfance data; will always be even;
+// pointer may be NULL in which case 0 is returned.
+inline DWORD CbFromInterfaceData(InterfaceData *pIFD)
+{
+ if (pIFD == NULL)
+ return 0;
+ else
+ {
+ // round up to an even number of bytes; this is the simplest
+ // way to keep the other entries word aligned.
+ return (IFD_SIZE(pIFD) + 1) & ~1;
+ }
+}
+
+// copy string and return dest; returns NULL for NULL string
+inline WCHAR * CopyWideString(void *pvTo, WCHAR *pwsz, DWORD cb)
+{
+ if (pwsz == NULL)
+ return NULL;
+
+ // ensure 2 byte aligned
+ Win4Assert((((DWORD)pvTo) & 0x1) == 0);
+
+#ifndef MEMCPYHACK
+ // WARNING: memcpy on the MIPS doesn't return pvTo as it should
+ memcpy(pvTo, pwsz, cb);
+ return (WCHAR *)pvTo;
+#else
+ return (WCHAR *)memcpy(pvTo, pwsz, cb);
+#endif
+}
+
+
+// copy interface data and return dest; returns NULL for NULL interface data
+inline InterfaceData * CopyInterfaceData(void *pvTo, InterfaceData *pIFD, DWORD cb)
+{
+ if (pIFD == NULL)
+ return NULL;
+
+#ifdef _X86_
+ // x86; ensure 2 byte aligned
+ Win4Assert((((DWORD)pvTo) & 0x1) == 0);
+#else
+ // non-x86; ensure 4 byte aligned
+ Win4Assert((((DWORD)pvTo) & 0x3) == 0);
+#endif
+
+#ifndef MEMCPYHACK
+ // WARNING: memcpy on the MIPS doesn't return pvTo as it should
+ memcpy(pvTo, pIFD, cb);
+ return (InterfaceData *)pvTo;
+#else
+ return (InterfaceData *)memcpy(pvTo, pIFD, cb);
+#endif
+}
+#endif // DCOM
+
+#endif // __COSCM_HXX__
diff --git a/private/ole32/com/objact/daytona/makefile b/private/ole32/com/objact/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/objact/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/objact/daytona/sources b/private/ole32/com/objact/daytona/sources
new file mode 100644
index 000000000..edb76dd87
--- /dev/null
+++ b/private/ole32/com/objact/daytona/sources
@@ -0,0 +1,76 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= objact
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..;..\..\inc;
+INCLUDES= $(INCLUDES);..\..\dcomidl\daytona;..\..\dcomrem;
+INCLUDES= $(INCLUDES);$(BASEDIR)\private\dcomidl\obj
+
+C_DEFINES= \
+ $(C_DEFINES)
+
+
+SOURCES= \
+ ..\actapi.cxx \
+ ..\cobjact.cxx \
+ ..\distname.cxx \
+ ..\dllapi.cxx \
+ ..\dllcache.cxx \
+ ..\dllhost.cxx \
+ ..\hobjact.cxx \
+ ..\smstg.cxx \
+ ..\sobjact.cxx \
+ ..\treat.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
diff --git a/private/ole32/com/objact/dirs b/private/ole32/com/objact/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/com/objact/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/com/objact/distname.cxx b/private/ole32/com/objact/distname.cxx
new file mode 100644
index 000000000..d144f0c07
--- /dev/null
+++ b/private/ole32/com/objact/distname.cxx
@@ -0,0 +1,422 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: cobjact.cxx
+//
+// Contents: Functions that activate objects residing in persistent storage.
+//
+// Functions: ConvertToOrgBasedDfsPath
+// ProcessPath
+// PathFromNormal
+//
+// History: 05-Oct-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+
+#ifdef _CAIRO_
+
+#include <compname.hxx>
+#include "objact.hxx"
+
+// Name of current computer
+CComputerName cnMachine;
+
+#ifdef CAIROLE_DECDEMO
+
+//+-------------------------------------------------------------------------
+//
+// Function: ProcessDCEPath
+//
+// Synopsis: Processes the path of a DCE filename
+//
+// Arguments: [pwszPathIn] - Input path
+// [ppwszPathOut] - Output UNC path
+//
+// Returns: S_OK - Path processed correctly
+//
+// Algorithm:
+//
+// History:
+//
+// Notes: There is a trick in this routine. The output buffer
+// is expected to be pointing to a MAX_PATH sized buffer.
+// But if we don't need to build the path we just assign
+// the old path to it. In other words, the out path
+// should be allocated on the stack so it is automatically
+// freed.
+//
+//--------------------------------------------------------------------------
+HRESULT ProcessDCEPath(
+ WCHAR *pwszPathIn,
+ WCHAR **ppwszPathOut,
+ WCHAR **ppwszServer)
+{
+ HRESULT hr = CO_E_BAD_PATH;
+ WCHAR * pch;
+ WCHAR chHld;
+ RPC_NS_HANDLE hRpc;
+ RPC_STATUS rpcStatus;
+ WCHAR * pwszBinding;
+
+ RPC_BINDING_VECTOR * pBindVec;
+ RPC_BINDING_HANDLE hBindIpTcp = NULL;
+ RPC_BINDING_HANDLE hBindNp = NULL;
+ RPC_BINDING_HANDLE hBind = NULL;
+
+ WCHAR * pProtSeq;
+ WCHAR * pNetworkAddr;
+
+ BOOL fContinue;
+
+ // split off the DCE Name
+ pch = pwszPathIn;
+ while(*pch != '!' && *pch != '\0')
+ pch++;
+
+ // The remain part should point to the path of the file
+ if(*pch == '!')
+ *ppwszPathOut = pch+1;
+
+ // if no server to find, we are done
+ if(ppwszServer == NULL)
+ return(hr);
+
+ // otherwise find the server name
+ chHld = *pch;
+ *pch = '\0';
+
+ rpcStatus = RpcNsBindingLookupBegin(RPC_C_NS_SYNTAX_DCE,
+ pwszPathIn,
+ NULL,
+ NULL,
+ 0,
+ &hRpc);
+
+ *pch = chHld;
+ if(rpcStatus)
+ return(hr);
+
+ fContinue = TRUE;
+ while( fContinue && !RpcNsBindingLookupNext(hRpc, &pBindVec) ) {
+
+ while( fContinue && !RpcNsBindingSelect(pBindVec, &hBind) ) {
+
+ if( !RpcBindingToStringBinding(hBind, &pwszBinding) ) {
+
+ RpcStringBindingParse(pwszBinding,
+ NULL,
+ &pProtSeq,
+ NULL,
+ NULL,
+ NULL);
+
+ // tcp or lpc protocall
+ if(!hBindIpTcp && (
+ !lstrcmpW(pProtSeq, LOCAL_PROTSEQ) ||
+ !lstrcmpW(pProtSeq, L"ncacn_ip_tcp") ||
+ !lstrcmpW(pProtSeq, L"ncacn_nb_tcp") )
+ ) {
+ hBindIpTcp = hBind;
+ fContinue = FALSE;
+ }
+
+ // named pipes
+ else if(!hBindNp && !lstrcmpW(pProtSeq, L"ncacn_np"))
+ hBindNp = hBind;
+ else
+ RpcBindingFree(&hBind);
+
+ RpcStringFree(&pwszBinding);
+ RpcStringFree(&pProtSeq);
+ }
+ }
+
+ RpcBindingVectorFree(&pBindVec);
+ }
+
+ RpcNsBindingLookupDone(&hRpc);
+
+ // select the binding of choice
+ if(hBindIpTcp)
+ hBind = hBindIpTcp;
+ else
+ hBind = hBindNp;
+
+ // get the network address
+ if( hBind && !RpcBindingToStringBinding(hBind, &pwszBinding) ) {
+
+ RpcStringBindingParse(pwszBinding,
+ NULL,
+ NULL,
+ &pNetworkAddr,
+ NULL,
+ NULL);
+
+ **ppwszServer = '\0';
+ if(pNetworkAddr[0] != '\\' || pNetworkAddr[1] != '\\')
+ lstrcpyW(*ppwszServer, L"\\\\");
+ lstrcatW(*ppwszServer, pNetworkAddr);
+
+ RpcStringFree(&pwszBinding);
+ RpcStringFree(&pNetworkAddr);
+
+ hr = S_OK;
+ }
+
+
+ // free up the binding handle
+ if(hBindIpTcp)
+ RpcBindingFree(&hBindIpTcp);
+ if(hBindNp)
+ RpcBindingFree(&hBindNp);
+
+ return(hr);
+}
+#endif
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ProcessPath
+//
+// Synopsis: Converts an old style redirection to UNC path
+//
+// Arguments: [pwszPathIn] - Input path
+// [ppwszPathOut] - Output UNC path
+//
+// Returns: S_OK - Path processed correctly
+//
+// Algorithm: Determine if drive is remote. If drive is remote
+// try to get the connection which should fail for
+// a DFS drive. If drive is an old style remote drive
+// then build a UNC path to the object. For DFS paths
+// and local paths just return the paths that were input.
+// For paths whose root is invalid return and invalid
+// path invalid path indication.
+//
+// History: 25-Jun-93 Ricksa Created
+//
+// Notes: There is a trick in this routine. The output buffer
+// is expected to be pointing to a MAX_PATH sized buffer.
+// But if we don't need to build the path we just assign
+// the old path to it. In other words, the out path
+// should be allocated on the stack so it is automatically
+// freed.
+//
+// BUGBUG [mikese] The ppwszServer parameter is redundant
+// since the server address is now computed inside SCM.
+//
+//--------------------------------------------------------------------------
+HRESULT ProcessPath(
+ WCHAR *pwszPathIn,
+ WCHAR **ppwszPathOut,
+ WCHAR **ppwszServer)
+{
+ // build a root directory for the API
+ WCHAR awcRootDir[3] = L"A:";
+ awcRootDir[0] = *pwszPathIn;
+ HRESULT hr = S_OK;
+
+#ifdef CAIROLE_DECDEMO
+ if( (lstrlenW(pwszPathIn) >= 3 && memcmp(pwszPathIn, L"/.:", 3*sizeof(WCHAR))) ||
+ (lstrlenW(pwszPathIn) >= 4 && memcmp(pwszPathIn, L"/...", 4*sizeof(WCHAR))) ) {
+ {
+ hr = ProcessDCEPath(pwszPathIn, ppwszPathOut, ppwszServer);
+ return(hr);
+ }
+
+#endif
+
+ // The server address is now computed inside SCM.
+ **ppwszServer = NULL;
+
+ // For UNC paths we don't need to do anything much
+ if ((pwszPathIn[0] == '\\') && (pwszPathIn[1] == '\\'))
+ {
+ // UNC path
+ *ppwszPathOut = pwszPathIn;
+ }
+ else
+ {
+ // Conventional drive based path. Attempt to resolve to universal form
+
+ CHAR achInfoBuffer[sizeof(UNIVERSAL_NAME_INFOW)
+ + MAX_PATH * sizeof(WCHAR)];
+ DWORD dwInfoSize = sizeof(achInfoBuffer);
+
+ DWORD dwStatus = OleWNetGetUniversalName ( pwszPathIn,
+ UNIVERSAL_NAME_INFO_LEVEL,
+ achInfoBuffer, &dwInfoSize );
+ if ( dwStatus == ERROR_SUCCESS )
+ {
+ // We successfully resolved to a UNC name
+
+ lstrcpyW ( *ppwszPathOut,
+ ((UNIVERSAL_NAME_INFOW*)achInfoBuffer)->lpUniversalName );
+ }
+ else
+ {
+ // Could not resolve to universal form, so probably local
+ *ppwszPathOut = pwszPathIn;
+ }
+ }
+
+ return hr;
+}
+
+
+#else // !_CAIRO_
+
+
+#ifdef CAIROLE_NT1X_DIST
+
+#include <compname.hxx>
+
+// Name of current computer
+CComputerName cnMachine;
+
+//+-------------------------------------------------------------------------
+//
+// Function: ProcessPath
+//
+// Synopsis: Converts an old style redirection to UNC path
+//
+// Arguments: [pwszPathIn] - Input path
+// [ppwszPathOut] - Output UNC path
+//
+// Returns: S_OK - Path processed correctly
+//
+// Algorithm: Determine if drive is remote. If drive is remote
+// try to get the connection which should fail for
+// a DFS drive. If drive is an old style remote drive
+// then build a UNC path to the object. For DFS paths
+// and local paths just return the paths that were input.
+// For paths whose root is invalid return and invalid
+// path invalid path indication.
+//
+// History: 25-Jun-93 Ricksa Created
+//
+// Notes: There is a trick in this routine. The output buffer
+// is expected to be pointing to a MAX_PATH sized buffer.
+// But if we don't need to build the path we just assign
+// the old path to it. In other words, the out path
+// should be allocated on the stack so it is automatically
+// freed.
+//
+//--------------------------------------------------------------------------
+HRESULT ProcessPath(
+ WCHAR *pwszPathIn,
+ WCHAR **ppwszPathOut,
+ WCHAR **ppwszServer)
+{
+ // build a root directory for the API
+ WCHAR awcRootDir[4] = L"A:\\";
+ awcRootDir[0] = *pwszPathIn;
+ HRESULT hr = S_OK;
+
+ if ((pwszPathIn[0] == '\\') && (pwszPathIn[1] == '\\'))
+ {
+ // UNC path
+ *ppwszPathOut = pwszPathIn;
+
+ // Do we need to find what server to contact?
+ if (ppwszServer != NULL)
+ {
+ // Find the end of the server name
+ WCHAR *pwszSlash = wcschr(pwszPathIn + 2, '\\');
+
+ // Store the length
+ int cServer = pwszSlash - pwszPathIn;
+
+ if (cServer >= MAX_PATH)
+ {
+ // This path is invalid
+ return CO_E_BAD_PATH;
+ }
+
+ // Is the endpoint us?
+ if ((lstrlenW(pwszPathIn) == cServer) &&
+ (lstrlenW((cnMachine.GetUNCCompuerName()) == cServer) &&
+ (memcmp(pwszPathIn, cnMachine.GetUNCComputerName(), cServer) == 0)))
+ {
+ // This path is local
+ *ppwszServer = NULL;
+ }
+ else
+ {
+ // Non local path -- Copy in server address & nul terminate.
+ memcpy(*ppwszServer, pwszPathIn, cServer * sizeof(WCHAR));
+ (*ppwszServer)[cServer] = 0;
+ }
+ }
+ }
+ else if (pwszPathIn[1] == ':')
+ {
+ if (GetDriveType(awcRootDir) == DRIVE_REMOTE)
+ {
+ // Conventional drive based path
+ DWORD cUNCPath = MAX_PATH;
+
+ awcRootDir[2] = 0;
+
+ DWORD dwErr;
+
+ // Connection based path
+ if ((dwErr
+ = OleWNetGetConnection(awcRootDir, *ppwszPathOut, &cUNCPath))
+ == NO_ERROR)
+ {
+ // Find the end of the server name
+ WCHAR *pwszSlash = wcschr(*ppwszPathOut + 2, '\\');
+ WCHAR wcSave = *pwszSlash;
+ *pwszSlash = 0;
+
+ // Is this a local path?
+ if (ppwszServer
+ && (lstrcmpiW(*ppwszPathOut, cnMachine.GetUNCComputerName())
+ != 0))
+ {
+ lstrcpyW(*ppwszServer, *ppwszPathOut);
+ }
+ else if (ppwszServer)
+ {
+ *ppwszServer = NULL;
+ }
+
+ *pwszSlash = wcSave;
+
+ // Concatenate path relative to the root to the
+ // connection name
+ lstrcat(*ppwszPathOut, pwszPathIn + 2);
+ }
+ else
+ {
+ // Convert error to HRESULT
+ hr = HRESULT_FROM_WIN32(dwErr);
+ }
+ }
+ else
+ {
+ *ppwszPathOut = pwszPathIn;
+
+ if (ppwszServer)
+ {
+ *ppwszServer = NULL;
+ }
+ }
+ }
+ else
+ {
+ hr = CO_E_BAD_PATH;
+ }
+
+ return hr;
+}
+#endif // CAIROLE_NT1X_DIST
+
+#endif // _CAIRO_
diff --git a/private/ole32/com/objact/dllapi.cxx b/private/ole32/com/objact/dllapi.cxx
new file mode 100644
index 000000000..0400bda16
--- /dev/null
+++ b/private/ole32/com/objact/dllapi.cxx
@@ -0,0 +1,161 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dllapi.cxx
+//
+// Contents: API entry points for DLL manipulation
+//
+// Functions: CoLoadLibrary
+// CoFreeLibrary
+// CoFreeAllLibraries
+// CoFreeUnusedLibraries
+//
+// History: 12-May-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+//
+//--------------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <objact.hxx>
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoLoadLibrary
+//
+// Synopsis: Loads a DLL
+//
+// Arguments: [pLibName] - name of DLL to load
+// [fAutoLoad] - whether DLL s/b unloaded automatically.
+//
+// Returns: HINSTANCE
+//
+// Algorithm: Just calls through to the Windows.
+//
+// History: 12-May-93 Ricksa Created
+//
+// Notes: This API is provided for Cross Platform portability.
+//
+//--------------------------------------------------------------------------
+STDAPI_(HINSTANCE) CoLoadLibrary(LPWSTR pLibName, BOOL fAutoLoad)
+{
+ OLETRACEIN((API_CoLoadLibrary, PARAMFMT("pLibName= %ws, fAutoLoad= %B"), pLibName, fAutoLoad));
+ TRACECALL(TRACE_DLL, "CoLoadLibrary");
+
+ HINSTANCE hInst = NULL;
+
+#if DBG
+ if (lstrlenW(&pLibName[1]) >= 2 && memcmp(&pLibName[1], L":\\", 2*sizeof(WCHAR)))
+ {
+ if ((lstrcmpiW(pLibName, L"OLEPRX32.DLL")) &&
+ (lstrcmpiW(pLibName, L"OLE32.DLL")))
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "\nDLL doesn't have fully qualified path in registry\n%ws\n\n",
+ pLibName));
+ }
+ }
+#endif
+
+ hInst = LoadLibraryEx(pLibName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+
+ OLETRACEOUTEX((API_CoLoadLibrary, RETURNFMT("%x"), hInst));
+
+ return hInst;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoFreeLibrary
+//
+// Synopsis: Used to free a DLL loaded by CoLoadLibrary.
+//
+// Arguments: [hInst] - handle to DLL
+//
+// Algorithm: Just passes through call to the OS
+//
+// History: 12-May-93 Ricksa Created
+//
+// Notes: This API is provided for Cross Platform portability.
+//
+//--------------------------------------------------------------------------
+STDAPI_(void) CoFreeLibrary(HINSTANCE hInst)
+{
+ OLETRACEIN((API_CoFreeLibrary, PARAMFMT("hInst= %x"), hInst));
+ TRACECALL(TRACE_DLL, "CoFreeLibrary");
+
+ FreeLibrary(hInst);
+
+ OLETRACEOUTEX((API_CoFreeLibrary, NORETURN));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoFreeAllLibraries
+//
+// Synopsis: Free all libraries
+//
+// History: 12-May-93 Ricksa Created
+//
+// Notes: All libraries are freed at process exit in Win32 anyway
+// so we just notify any unused libraries that they can
+// go way in the DEV build so memory can be totally cleaned
+// up to facilitate the discovery of memory leaks.
+//
+//--------------------------------------------------------------------------
+STDAPI_(void) CoFreeAllLibraries(void)
+{
+ OLETRACEIN((API_CoFreeAllLibraries, NOPARAM));
+
+#if DBG == 1
+ CoFreeUnusedLibraries();
+#endif // DBG
+
+ OLETRACEOUTEX((API_CoFreeAllLibraries, NORETURN));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoFreeUnusedLibraries
+//
+// Synopsis: Free any unused single-threaded DLLS.
+//
+// Algorithm: Ask DLL cache objects to free any DLLs that respond
+// to DllCanUnloadNow with TRUE.
+//
+// History: 12-May-93 Ricksa Created
+//
+// Notes: The DllCanUnloadNow protocol is as follows:
+//
+// Apartment Model DLLs: CoFreeUnusedLibraries must be called on
+// each thread that has loaded an object from the DLL, before the
+// DLL will realy be unloaded.
+//
+// FreeThreaded DLLs: OLE will wait 10 minutes from the last
+// use of the DLL before unloading it.
+//
+//--------------------------------------------------------------------------
+STDAPI_(void) CoFreeUnusedLibraries(void)
+{
+ OLETRACEIN((API_CoFreeUnusedLibraries, NOPARAM));
+ TRACECALL(TRACE_DLL, "CoFreeUnusedLibraries");
+
+ HRESULT hr;
+ COleTls tls(hr); // ensure TLS exists
+
+ if (SUCCEEDED(hr))
+ {
+ if (!IsWOWProcess())
+ {
+ CallFreeUnused();
+ }
+ }
+
+ OLETRACEOUTEX((API_CoFreeUnusedLibraries, NORETURN));
+}
diff --git a/private/ole32/com/objact/dllcache.cxx b/private/ole32/com/objact/dllcache.cxx
new file mode 100644
index 000000000..1c963abbf
--- /dev/null
+++ b/private/ole32/com/objact/dllcache.cxx
@@ -0,0 +1,4060 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dllcache.cxx
+//
+// Contents: Implementations of classes declared in dllcache.hxx
+//
+// Functions:
+// CDllAptEntry::Init
+// CDllAptEntry::Create
+// CDllAptEntry::
+//
+// CDllCache::CDllCache
+// CDllCache::~CDllCache
+// CDllCache::InitClsent
+// CDllCache::CreateClsent
+// CDllCache::GetClassObjForDdeByClsent
+// CDllCache::CleanUpLocalServersForApartment
+// CDllCache::CleanUpDllsForApartment
+// CDllCache::CleanUpDllsForProcess
+// CDllCache::CleanUpForApartmentByDllent
+// CDllCache::AtStorageRef
+// CDllCache::Release
+// CDllCache::InitDllent
+// CDllCache::CreateDllent
+// CDllCache::NewAptEntries
+// CDllCache::AllocAptEntry
+// CDllCache::FreeAptEntry
+// CDllCache::IsValidInApartment
+// CDllCache::MakeValidInApartment
+// CDllCache::GetClassInterface
+// CDllCache::CanUnloadNow
+// CDllCache::Remove
+// CDllCache::Init
+// CDllCache::GetClass
+// CDllCache::GetOrLoadClass
+// CDllCache::GetClassObjForDde
+// CDllCache::GetClassInformationFromKey
+// CDllCache::GetApartmentForCLSID
+// CDllCache::Add
+// CDllCache::FreeUnused
+// CDllCache::RegisterServer
+// CDllCache::Revoke
+// CDllCache::SetDdeServerWindow
+// CDllCache::Search (x4)
+// CDllCache::AllocClassEntry
+// CDllCache::AllocDllPathEntry
+// CDllCache::FreeClassEntry
+// CDllCache::FreeDllPathEntry
+//
+// CleanUpDllsForProcess
+// CleanUpLocalServersForApartment
+// CleanUpDllsForApartment
+// GetAptForCLSID
+// GetClassInformationForDde
+// GetClassInformationFromKey
+// OleMainThreadWndProc
+// InitMainThreadWnd
+// UninitMainThreadWnd
+//
+//
+// History: 09-May-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+// 09-Jun-94 BruceMa Check new pointers
+// 21-Jun-94 BruceMa Check new pointers
+// 24-Jun-94 Rickhi Add Apartment Crap
+// 24-Jun-94 BruceMa Check new pointers
+// 28-Jun-94 BruceMa Memory sift fixes
+// 07-Jul-94 BruceMa Memory sift fixes
+// 08-Nov-94 Ricksa Final threading changes
+// 07-Mar-95 BruceMa Rewrote
+// 06-Oct-95 BruceMa Various fixes - mostly race conditions
+// 19-Apr-96 Rickhi Add Suspend/Resume/AddRef/Release
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include <channelb.hxx>
+#include <tracelog.hxx>
+#include <scmmem.hxx>
+
+#include "objact.hxx"
+#include <dllhost.hxx>
+#include <sobjact.hxx>
+#include <treat.hxx>
+
+LPCTSTR ptszOle32DllName = TEXT("OLE32.DLL");
+
+// Name of window class and message class for dispatching messages.
+//const TCHAR OLE_WINDOW_CLASS = TEXT("OleObjectRpcWindow");
+LPTSTR gOleWindowClass = NULL; // class used to create windows
+
+// Various things used for special single threaded DLL processing
+DWORD gdwMainThreadId = 0;
+HWND hwndOleMainThread = NULL;
+
+// this flag is to indicate whether it is UninitMainThread that is
+// destroying the window, or system shut down destroying the window.
+BOOL gfDestroyingMainWindow = FALSE;
+
+const TCHAR *ptszOleMainThreadWndName = TEXT("OleMainThreadWndName");
+#define DllRegisterClass RegisterClassT
+#define DllUnregisterClass UnregisterClassT
+
+
+#ifdef _CHICAGO_
+// Note: we have to create a unique string so that get
+// register a unique class for each 16 bit app.
+// The class space is global on chicago.
+//
+LPSTR ptszOleMainThreadWndClass = "OleMainThreadWndClass 0x######## ";
+#define DllCreateWindowEx SSCreateWindowExA
+
+STDAPI_(LRESULT) OleNotificationProc(UINT wMsg, WPARAM wParam, LPARAM lParam);
+
+#else // !_CHICAGO_
+
+const WCHAR *ptszOleMainThreadWndClass = L"OleMainThreadWndClass";
+#define DllCreateWindowEx CreateWindowEx
+
+#endif // _CHICAGO_
+
+
+#ifdef _UNICODE
+#define TSZFMT "%ws"
+#else
+#define TSZFMT "%s"
+#endif
+
+static const TCHAR tszOle32Dll[] = TEXT("OLE32.DLL");
+
+#define OLE32_DLL tszOle32Dll
+#define OLE32_BYTE_LEN sizeof(OLE32_DLL)
+#define OLE32_CHAR_LEN (sizeof(OLE32_DLL) / sizeof(TCHAR) - 1)
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CallFreeUnused
+//
+// Synopsis: Free unused from main thread
+//
+// Arguments: [pData] - pointer to single thread parameter packet (unused)
+//
+// Returns: S_OK - call succeeded
+//
+// Algorithm: Call free unused for both inproc servers and in proc handlers.
+//
+// History: 10-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CallFreeUnused(void)
+{
+ TRACECALL(TRACE_DLL, "CallFreeUnused");
+
+ gdllcacheInprocSrv.FreeUnused();
+ gdllcacheHandler.FreeUnused();
+
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllAptEntry::Init
+//
+// Synopsis: Initialize the entry to empty
+//
+// Arguments: dwNext - The next apartment entry in the free list
+//
+// Returns:
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void CDllAptEntry::Init(DWORD dwNext)
+{
+ _dwNext = dwNext;
+ _dwSig = 0;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllAptEntry::Create
+//
+// Synopsis: Create an apartment entry
+//
+// Arguments: hApt - The creating apartment
+//
+// Returns:
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void CDllAptEntry::Create(HAPT hApt)
+{
+ _dwSig = DLL_APT_CACHE_SIG;
+ _hApt = hApt;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::CDllCache
+//
+// Synopsis: Create a DLL cache object
+//
+// Algorithm: Let sub-objects do all the work.
+//
+// History: 09-May-93 Ricksa Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+CDllCache::CDllCache(void) :
+ _pClassEntries(NULL), _pDllPathEntries(NULL),
+ _nClassEntryAvail(NONE), _nDllPathEntryAvail(NONE),
+ _nClassEntryInUse(NONE), _nDllPathEntryInUse(NONE),
+ _cClassEntries(0), _cDllPathEntries(0),
+ _cRefsServerProcess(0)
+{
+ Win4Assert (g_fDllState == DLL_STATE_STATIC_CONSTRUCTING);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::Load
+//
+// Synopsis: Load the module into the current apartment & retrieve
+// the entry points
+//
+// Arguments: [ptszPath] - Dll path
+// [ppfnGetClassObject] - where to return DllGetClassObejct EP
+// [ppfnDllCanUnloadNow] - where to return DllCanUnloadNow EP
+// fSixteenBit - Whether this is a 16-bit dll
+// phDll - Address to store the loaded HMODULE
+// pIsX86Dll returns TRUE if dll is an X86 dll
+// fLoadAsX86 is TRUE if Dll was found on InprocServerX86 key
+//
+// Returns: S_OK - if successfull
+//
+// History: 24-Jun-94 Rickhi Created
+// 07-Mar-95 BruceMa Rewrote
+// 30-Sep-95 AlanWar Added support for WX86
+//
+//
+//--------------------------------------------------------------------------
+HRESULT CDllCache::Load(LPCTSTR ptszPath,
+ LPFNGETCLASSOBJECT *ppfnGetClassObject,
+ DLLUNLOADFNP *ppfnDllCanUnload,
+ BOOL fSixteenBit,
+ HMODULE *phDll
+#ifdef WX86OLE
+ ,BOOL *pfIsX86Dll,
+ BOOL fLoadAsX86
+#endif
+ )
+{
+ HRESULT hr = S_OK;
+#ifdef WX86OLE
+ BOOL fIsX86Dll;
+#endif
+
+ if (fSixteenBit)
+ {
+ CairoleDebugOut((DEB_TRACE,
+ "Attempting to load 16 bit DLL " TSZFMT "\n", ptszPath));
+
+ // In this section, we need to call 16-bit DllGetClassObject. The
+ // g_OleThunkWow pointer is the VTABLE to use for getting back to
+ // the 16-bit implementation.
+ LPFNGETCLASSOBJECT pfnGetClassObject;
+ DLLUNLOADFNP pfnDllCanUnload;
+
+ hr = g_pOleThunkWOW->LoadProcDll(ptszPath,
+ (DWORD *)&pfnGetClassObject,
+ (DWORD *)&pfnDllCanUnload,
+ (DWORD *)phDll);
+
+ // A failure condition would mean that the DLL could not be found,
+ // or otherwise could not be loaded
+ if (FAILED(hr))
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "Load 16 bit DLL " TSZFMT " failed(%x)\n",ptszPath,hr));
+ return CO_E_DLLNOTFOUND;
+ }
+
+ // The other possible error is the DLL didn't have the required
+ // interface
+ if (ppfnGetClassObject)
+ {
+ if (pfnGetClassObject == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "Get pfnGetClassObject %ws failed\n",
+ ptszPath));
+
+ return(CO_E_ERRORINDLL);
+ }
+ *ppfnGetClassObject = pfnGetClassObject;
+ }
+
+ if (ppfnDllCanUnload)
+ {
+ *ppfnDllCanUnload = pfnDllCanUnload;
+ }
+ }
+ else
+ {
+ CairoleDebugOut((DEB_TRACE,
+ "Attempting to load 32 bit DLL " TSZFMT "\n", ptszPath));
+
+#ifdef WX86OLE
+ fLoadAsX86 = gcwx86.SetLoadAsX86(fLoadAsX86);
+#endif
+ // Load the 32-bit DLL
+ *phDll = LoadLibraryExT(ptszPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+#ifdef WX86OLE
+ gcwx86.SetLoadAsX86(fLoadAsX86);
+#endif
+
+ if (*phDll == NULL)
+ {
+ // Dll could not be loaded
+ CairoleDebugOut((DEB_ERROR,
+ "Load of " TSZFMT " failed\n",
+ ptszPath));
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+#ifdef WX86OLE
+ fIsX86Dll = gcwx86.IsModuleX86(*phDll);
+ if (pfIsX86Dll)
+ {
+ *pfIsX86Dll = fIsX86Dll;
+ }
+#endif
+
+ // Get the entry points if desired
+ if (ppfnGetClassObject)
+ {
+#ifdef WX86OLE
+ *ppfnGetClassObject = (LPFNGETCLASSOBJECT)
+ GetProcAddress(*phDll, DLL_GET_CLASS_OBJECT_EP);
+ if ((*ppfnGetClassObject == NULL) ||
+ (fIsX86Dll && ( (*ppfnGetClassObject =
+ gcwx86.TranslateDllGetClassObject(
+ *ppfnGetClassObject)) == NULL)))
+#else
+ if ((*ppfnGetClassObject = (LPFNGETCLASSOBJECT)
+ GetProcAddress(*phDll, DLL_GET_CLASS_OBJECT_EP)) == NULL)
+#endif
+ {
+ // Doesn't have a valid entry point for creation of class objects
+ return CO_E_ERRORINDLL;
+ }
+ }
+
+ if (ppfnDllCanUnload)
+ {
+ // Not having a unload entry point is valid behavior
+ *ppfnDllCanUnload = (DLLUNLOADFNP) GetProcAddress(*phDll,
+ DLL_CAN_UNLOAD_EP);
+#ifdef WX86OLE
+ if (fIsX86Dll)
+ {
+ // Translating a NULL address will do nothing but return a
+ // NULL address
+ *ppfnDllCanUnload =
+ gcwx86.TranslateDllCanUnloadNow(
+ *ppfnDllCanUnload);
+ }
+#endif
+ }
+ }
+
+ return hr;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::InitClsent
+//
+// Synopsis: Initialize a class entry structure
+//
+// Algorithm: dwCls - The index of this class entry
+// k - The next class entry index in the free list
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void CDllCache::InitClsent(DWORD dwCls, DWORD k)
+{
+ _pClassEntries[dwCls]._dwNext = k;
+ _pClassEntries[dwCls]._dwSig = 0;
+ _pClassEntries[dwCls]._dwNextDllCls = NONE;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::CreateClsentLSvr
+//
+// Synopsis: Create a class entry for a local server
+//
+// Algorithm: dwCls - The index of this class entry
+// rclsid - The class ID for this server
+// punk - IUnknown for the server
+// dwFlags - Either REGCLS_SINGLEUSE or REGCLS_MULTIPLEUSE
+// dwContext - CLSCTX_INPROC_SERVER | CLSREG_LOCAL_SERVER
+// dwReg - The registration key returned to the user
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CDllCache::CreateClsentLSvr(DWORD dwCls,
+ REFCLSID rclsid,
+ IUnknown *punk,
+ DWORD dwFlags,
+ DWORD dwContext,
+ DWORD dwReg)
+{
+ HRESULT hr = S_OK;
+
+ // Initialize the class entry
+ _pClassEntries[dwCls]._dwSig = CLASS_CACHE_SIG;
+ _pClassEntries[dwCls]._fAtStorage = FALSE;
+ _pClassEntries[dwCls]._clsid = rclsid;
+ _pClassEntries[dwCls]._pUnk = punk;
+ _pClassEntries[dwCls]._dwContext = dwContext;
+ _pClassEntries[dwCls]._dwFlags = dwFlags;
+ _pClassEntries[dwCls]._hApt = GetCurrentApartmentId();
+ _pClassEntries[dwCls]._dwReg = dwReg;
+ _pClassEntries[dwCls]._cCallOut = 0;
+ _pClassEntries[dwCls]._fRevoking = FALSE;
+ _pClassEntries[dwCls]._fRevokePending = FALSE;
+ _pClassEntries[dwCls]._fReleasing = FALSE;
+ _pClassEntries[dwCls]._dwDllEnt = NONE;
+ _pClassEntries[dwCls]._dwNextDllCls = NONE;
+ _pClassEntries[dwCls]._hWndDdeServer = NULL;
+ _pClassEntries[dwCls]._dwScmReg = NONE;
+ _pClassEntries[dwCls]._pObjServer = NULL;
+
+
+ if (dwContext & CLSCTX_LOCAL_SERVER)
+ {
+ // store off a pointer to the activation server object.
+ _pClassEntries[dwCls]._pObjServer = GetObjServer();
+
+ if (!(dwFlags & REGCLS_SUSPENDED))
+ {
+ // Notify SCM that the class is started.
+ RegOutput *pRegOut = NULL;
+
+ RegInput RegIn;
+ RegIn.dwSize = 1;
+ RegIn.rginent[0].clsid = rclsid;
+ RegIn.rginent[0].dwFlags = dwFlags;
+ RegIn.rginent[0].ipid = _pClassEntries[dwCls]._pObjServer->GetIPID();
+ RegIn.rginent[0].oxid = _pClassEntries[dwCls]._pObjServer->GetOXID();
+
+ // Release the lock across outgoing calls to the SCM.
+ _mxs.Release();
+ hr = gResolver.NotifyStarted(&RegIn, &pRegOut);
+ _mxs.Request();
+
+ if (SUCCEEDED(hr))
+ {
+ _pClassEntries[dwCls]._fAtStorage = pRegOut->regoutent[0].dwAtStorage;
+ _pClassEntries[dwCls]._dwScmReg = pRegOut->regoutent[0].dwReg;
+ MIDL_user_free(pRegOut);
+ }
+ }
+ }
+
+ return hr;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::CreateClsentInProc
+//
+// Synopsis: Create a class entry for an inproc server
+//
+// Algorithm: dwCls - The index of this class entry
+// dwDll - The index of the parent dll path entry
+// rclsid - The class ID for this server
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CDllCache::CreateClsentInProc(DWORD dwCls,
+ DWORD dwDll,
+ DWORD dwDllThreadModel,
+ DWORD dwNextDllCls,
+ REFCLSID rclsid
+#ifdef WX86OLE
+ ,BOOL fWx86
+#endif
+)
+{
+ ComDebOut((DEB_TRACE,
+ "CDllCache::CreateClsentInproc clsid:%I dwCls:%x dwDll:%x\n",
+ &rclsid, dwCls, dwDll));
+
+ // Initialize the class entry
+ _pClassEntries[dwCls]._dwSig = CLASS_CACHE_SIG;
+ _pClassEntries[dwCls]._fAtStorage = FALSE;
+ _pClassEntries[dwCls]._clsid = rclsid;
+ _pClassEntries[dwCls]._pUnk = NULL;
+ _pClassEntries[dwCls]._dwContext =
+#ifdef WX86OLE
+ fWx86 ? CLSCTX_INPROC_SERVERX86 :
+#endif
+ CLSCTX_INPROC_SERVER;
+ _pClassEntries[dwCls]._dwFlags = REGCLS_MULTIPLEUSE;
+ _pClassEntries[dwCls]._hApt = GetCurrentApartmentId();
+ _pClassEntries[dwCls]._dwReg = 0;
+ _pClassEntries[dwCls]._cCallOut = 0;
+ _pClassEntries[dwCls]._fRevokePending = FALSE;
+ _pClassEntries[dwCls]._fRevoking = FALSE;
+ _pClassEntries[dwCls]._fReleasing = FALSE;
+ _pClassEntries[dwCls]._dwDllEnt = dwDll;
+ _pClassEntries[dwCls]._dwDllThreadModel= dwDllThreadModel;
+ _pClassEntries[dwCls]._dwNextDllCls = dwNextDllCls;
+ _pClassEntries[dwCls]._hWndDdeServer = NULL;
+ _pClassEntries[dwCls]._dwScmReg = NONE;
+
+ if (dwDllThreadModel == FREE_THREADED ||
+ dwDllThreadModel == BOTH_THREADED)
+ {
+ // for any FT and BOTH threaded classes, delay unloading the DLL
+ _pDllPathEntries[dwDll]._dwFlags |= DELAYED_UNLOAD;
+ }
+ return S_OK;
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDllCache::GetClassObjForDdeByClsent
+//
+// Synopsis: Get a class entry from the table for Dde, returning
+// extra information, including the flags.
+//
+// Effects: The DdeServer needs the ability to query the class factory
+// table to search for classes it needs to provide OLE 1.0
+// support for. This routine will allow it to access the
+// required information.
+//
+// Arguments: dwCls - The index of this class entry
+// lpDdeClassInfo - The DDE structure to fill in
+//
+// Returns: TRUE if the entry matched, FALSE if it did not.
+//
+// History: 5-28-94 kevinro Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//----------------------------------------------------------------------------
+BOOL CDllCache::GetClassObjForDdeByClsent(DWORD dwCls,
+ LPDDECLASSINFO lpDdeClassInfo)
+{
+ Win4Assert(IsValidPtrOut(lpDdeClassInfo, sizeof(DWORD)) &&
+ "CDllCache::GetClassObjForDde invalid out parameter");
+
+ if (lpDdeClassInfo->dwContextMask & _pClassEntries[dwCls]._dwContext)
+ {
+ HAPT hApt = GetCurrentApartmentId();
+
+ if (hApt == _pClassEntries[dwCls]._hApt)
+ {
+ // Found a matching record, set its info
+ lpDdeClassInfo->dwContext = _pClassEntries[dwCls]._dwContext;
+ lpDdeClassInfo->dwFlags = _pClassEntries[dwCls]._dwFlags;
+ lpDdeClassInfo->dwThreadId = _pClassEntries[dwCls]._hApt;
+ lpDdeClassInfo->dwRegistrationKey = _pClassEntries[dwCls]._dwReg;
+
+ if (lpDdeClassInfo->fClaimFactory == TRUE)
+ {
+ // Release the lock across the outgoing call
+ IUnknown *pUnkTmp = _pClassEntries[dwCls]._pUnk;
+
+ _mxs.Release();
+ HRESULT hr = pUnkTmp->QueryInterface(
+ IID_IClassFactory,
+ (void **)&(lpDdeClassInfo->punk));
+ _mxs.Request();
+
+ if (hr != S_OK)
+ {
+ return FALSE;
+ }
+
+ // We do this only after the QueryInterface has succeeded
+ if (_pClassEntries[dwCls]._dwFlags == REGCLS_SINGLEUSE)
+ {
+ // For a single use class we can only pass it out once. To
+ // guarantee it, we set the context to zero so that the
+ // above test will not pass again.
+ _pClassEntries[dwCls]._dwContext = 0;
+ }
+ }
+ else
+ {
+ lpDdeClassInfo->punk = NULL;
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::Release
+//
+// Synopsis: Disconnect and release the associated server
+//
+// Arguments: dwCls - The index of this class entry
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CDllCache::Release(DWORD dwCls)
+{
+ HRESULT hr = S_OK;
+
+ CairoleDebugOut((DEB_TRACE, "CDllCache::Release Releasing class %d\n",
+ dwCls));
+
+ // Disallow recursive releases (like Lotus Notes 4.0)
+ if (_pClassEntries[dwCls]._fReleasing)
+ {
+ return S_OK;
+ }
+
+ // Invalidate this class entry
+ _pClassEntries[dwCls]._dwContext = 0;
+ _pClassEntries[dwCls]._fReleasing = TRUE;
+
+ // Release the lock across outgoing calls and SendMessage (We can do this
+ // without setting up local variables since the class entry can't be
+ // reused until we do FreeClassEntry)
+ if (_pClassEntries[dwCls]._pUnk != NULL)
+ {
+ _mxs.Release();
+
+ // Tell SCM about multiple use classes stopping.
+ if (_pClassEntries[dwCls]._dwScmReg != NONE)
+ {
+ gResolver.NotifyStopped(_pClassEntries[dwCls]._clsid,
+ _pClassEntries[dwCls]._dwScmReg);
+ _pClassEntries[dwCls]._dwScmReg = NONE;
+ }
+
+ // If a DDE Server window exists for this class, then we need to
+ // release it now.
+ if (_pClassEntries[dwCls]._hWndDdeServer != NULL)
+ {
+ // It's possible that SendMessage could fail. However, there
+ // really isn't anything we can do about it. So, the error
+ // code is not checked.
+ SSSendMessage(_pClassEntries[dwCls]._hWndDdeServer, WM_USER, 0, 0);
+ _pClassEntries[dwCls]._hWndDdeServer == NULL;
+ }
+
+ // Now really release it
+ if (_pClassEntries[dwCls]._pUnk != NULL)
+ {
+ if (IsValidInterface(_pClassEntries[dwCls]._pUnk))
+ {
+ CoDisconnectObject(_pClassEntries[dwCls]._pUnk, NULL);
+ _pClassEntries[dwCls]._pUnk->Release();
+
+ hr = S_OK;
+ }
+ else
+ {
+ hr = CO_E_RELEASED;
+ }
+ }
+
+ // Retake the lock
+ _mxs.Request();
+ }
+
+ return hr;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::InitDllent
+//
+// Synopsis: Initialize a dll path entry structure
+//
+// Arguments: dwDll - The index of this dll path entry
+// k - The next dll path entry in the free list
+//
+// Algorithm:
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void CDllCache::InitDllent(DWORD dwDll, DWORD k)
+{
+ _pDllPathEntries[dwDll]._dwNext = k;
+ _pDllPathEntries[dwDll]._dwSig = 0;
+ _pDllPathEntries[dwDll]._dwFlags = 0;
+ _pDllPathEntries[dwDll]._dw1stClass = NONE;
+ _pDllPathEntries[dwDll]._cAptEntries = NOMINAL_NUMBER_THREADS;
+ _pDllPathEntries[dwDll]._nAptAvail = 0;
+ _pDllPathEntries[dwDll]._nAptInUse = NONE;
+ _pDllPathEntries[dwDll]._dwExpireTime = 0;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::CreateDllent
+//
+// Synopsis: Fully initialize a DLL object
+//
+// Arguments: dwDll - The index of this dll path entry
+// ptszDllPath - The load path for the dll
+// fSixteenBit - Whether this is a 16-bit dll
+//
+// Algorithm: Creates the first CDllAptEntry which loads the
+// DLL specified by the path, gets the DllGetClassObject
+// entry point and the DllCanUnloadNow entry point.
+// At this point object construction is complete.
+//
+// History: 09-May-93 Ricksa Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+HRESULT CDllCache::CreateDllent(DWORD dwDll,
+ LPCTSTR ptszDllPath,
+ BOOL fSixteenBit,
+ LPFNGETCLASSOBJECT pfnGetClassObject,
+ DLLUNLOADFNP pfnDllCanUnload,
+ HMODULE hDll
+#ifdef WX86OLE
+ ,BOOL fIsX86Dll,
+ BOOL fLoadAsX86
+#endif
+ )
+{
+ TRACECALL(TRACE_DLL, "CDllCache::CreateDllent");
+ CairoleDebugOut((DEB_TRACE, "Initializing dll " TSZFMT "\n", ptszDllPath));
+
+ // Get the path length and allocate for it
+ UINT ccH = lstrlen(ptszDllPath) + 1;
+ _pDllPathEntries[dwDll]._ptszPath = (TCHAR *) PrivMemAlloc(ccH * sizeof(TCHAR));
+ if (_pDllPathEntries[dwDll]._ptszPath == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // Initialize the dll path entry
+ memcpy(_pDllPathEntries[dwDll]._ptszPath, ptszDllPath, ccH * sizeof(TCHAR));
+ CharUpper(_pDllPathEntries[dwDll]._ptszPath);
+ _pDllPathEntries[dwDll]._dwFlags |= fSixteenBit ? SIXTEEN_BIT : 0;
+ _pDllPathEntries[dwDll]._cUsing = 0;
+
+ // Compute a hash value for more optimal searchs
+ _pDllPathEntries[dwDll]._dwHash = Hash(_pDllPathEntries[dwDll]._ptszPath);
+
+
+ // 32 bit libraries have process wide handles, so
+ // we'll store them in the DllPathEntry
+ if (fSixteenBit)
+ {
+ _pDllPathEntries[dwDll]._hDll32 = 0;
+ }
+ else
+ {
+ _pDllPathEntries[dwDll]._hDll32 = hDll;
+ }
+
+ // Construct the initial per apartment entry
+ DWORD dwAptent = AllocAptEntry(dwDll);
+ if (dwAptent == NONE)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // Initialize it
+ _pDllPathEntries[dwDll]._pAptEntries[dwAptent].Create(GetCurrentApartmentId());
+
+ // Check if this is "OLE32.DLL"
+ if (lstrcmp(_pDllPathEntries[dwDll]._ptszPath, ptszOle32DllName)
+ == 0)
+ {
+ _pDllPathEntries[dwDll]._pfnGetClassObject = DllGetClassObject;
+ _pDllPathEntries[dwDll]._pfnDllCanUnload = NULL;
+ _pDllPathEntries[dwDll]._dwFlags |= IS_OLE32;
+ }
+ else
+ {
+ _pDllPathEntries[dwDll]._pfnGetClassObject = pfnGetClassObject;
+ _pDllPathEntries[dwDll]._pfnDllCanUnload = pfnDllCanUnload;
+ _pDllPathEntries[dwDll]._pAptEntries[dwAptent]._hDll = (fSixteenBit ? hDll : 0);
+#ifdef WX86OLE
+ if (fIsX86Dll)
+ {
+ _pDllPathEntries[dwDll]._dwFlags |= WX86_THUNK;
+ }
+ if (fLoadAsX86)
+ {
+ _pDllPathEntries[dwDll]._dwFlags |= WX86_LOADASX86;
+ }
+#endif
+ }
+
+ return S_OK;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::NewAptEntries
+//
+// Synopsis: Allocate and initialize the apartment entries for
+// a dll path entry
+//
+// Arguments: dwDll - The index of this dll path entry
+//
+// Algorithm:
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+BOOL CDllCache::NewAptEntries(DWORD dwDll)
+{
+
+ _pDllPathEntries[dwDll]._pAptEntries = new CDllAptEntry[NOMINAL_NUMBER_THREADS];
+ if (_pDllPathEntries[dwDll]._pAptEntries == NULL)
+ {
+ return FALSE;
+ }
+ for (int dwApt = 0; dwApt < NOMINAL_NUMBER_THREADS; dwApt++)
+ {
+ _pDllPathEntries[dwDll]._pAptEntries[dwApt].Init(
+ dwApt == NOMINAL_NUMBER_THREADS - 1 ? NONE : dwApt + 1);
+ }
+
+ return TRUE;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::AllocAptEntry
+//
+// Synopsis: Allocate a new apartment entry for a dll path entry
+//
+// Arguments: dwDll - The index of this dll path entry
+//
+// Algorithm:
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DWORD CDllCache::AllocAptEntry(DWORD dwDll)
+{
+ // If we don't have any available entries, then expand the array
+ if (_pDllPathEntries[dwDll]._nAptAvail == NONE)
+ {
+ // Allocate a new array
+ DWORD cEnt = _pDllPathEntries[dwDll]._cAptEntries;
+ CDllAptEntry *p = new CDllAptEntry[cEnt + NOMINAL_NUMBER_THREADS];
+ if (p == NULL)
+ {
+ return NONE;
+ }
+
+ // Initialize it
+ memcpy(p,
+ _pDllPathEntries[dwDll]._pAptEntries,
+ _pDllPathEntries[dwDll]._cAptEntries * sizeof(CDllAptEntry));
+
+ // Free old array
+ delete _pDllPathEntries[dwDll]._pAptEntries;
+ _pDllPathEntries[dwDll]._pAptEntries = p;
+
+ for (DWORD k = _pDllPathEntries[dwDll]._cAptEntries;
+ k < _pDllPathEntries[dwDll]._cAptEntries + NOMINAL_NUMBER_THREADS;
+ k++)
+ {
+ _pDllPathEntries[dwDll]._pAptEntries[k].Init(
+ k == _pDllPathEntries[dwDll]._cAptEntries + NOMINAL_NUMBER_THREADS - 1 ? NONE : k + 1 );
+ }
+ _pDllPathEntries[dwDll]._nAptAvail = _pDllPathEntries[dwDll]._cAptEntries;
+ _pDllPathEntries[dwDll]._cAptEntries += NOMINAL_NUMBER_THREADS;
+ }
+
+ // Return the next available entry
+ DWORD dwAptent = _pDllPathEntries[dwDll]._nAptAvail;
+ _pDllPathEntries[dwDll]._pAptEntries[dwAptent]._dwSig = DLL_APT_CACHE_SIG;
+
+ _pDllPathEntries[dwDll]._nAptAvail =
+ _pDllPathEntries[dwDll]._pAptEntries[dwAptent]._dwNext;
+ _pDllPathEntries[dwDll]._pAptEntries[dwAptent]._dwNext =
+ _pDllPathEntries[dwDll]._nAptInUse;
+ _pDllPathEntries[dwDll]._nAptInUse = dwAptent;
+ return dwAptent;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::FreeAptEntry
+//
+// Synopsis: Free an apt entry in a dll path entry - i.e., make it available
+//
+// Arguments: dwDll - The index of this dll path entry
+// dwAptent - The index of the apartment entry to free
+//
+// Algorithm:
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void CDllCache::FreeAptEntry(DWORD dwDll, DWORD dwAptent)
+{
+ // It's at the head of the list
+ if (_pDllPathEntries[dwDll]._nAptInUse == dwAptent)
+ {
+ _pDllPathEntries[dwDll]._nAptInUse =
+ _pDllPathEntries[dwDll]._pAptEntries[dwAptent]._dwNext;
+ }
+
+ // Otherwise search for the entry that points to the one we're freeing
+ else
+ {
+ for (DWORD dwPrev = _pDllPathEntries[dwDll]._nAptInUse;
+ _pDllPathEntries[dwDll]._pAptEntries[dwPrev]._dwNext != dwAptent;
+ dwPrev = _pDllPathEntries[dwDll]._pAptEntries[dwPrev]._dwNext)
+ {
+ }
+ _pDllPathEntries[dwDll]._pAptEntries[dwPrev]._dwNext =
+ _pDllPathEntries[dwDll]._pAptEntries[dwAptent]._dwNext;
+ }
+
+ // Relink into the list of available entries
+ _pDllPathEntries[dwDll]._pAptEntries[dwAptent]._dwNext =
+ _pDllPathEntries[dwDll]._nAptAvail;
+ _pDllPathEntries[dwDll]._nAptAvail = dwAptent;
+ _pDllPathEntries[dwDll]._pAptEntries[dwAptent].Init(
+ _pDllPathEntries[dwDll]._pAptEntries[dwAptent]._dwNext);
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::IsValidInApartment
+//
+// Synopsis: Determine whether Dll object is valid in the current apartment
+//
+// Arguments: dwDll - The index of this dll path entry
+// hApt - apartment to check
+//
+// Returns: TRUE - it is valid
+// FALSE - it isn't valid
+//
+// History: 10-Nov-94 Ricksa Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+BOOL CDllCache::IsValidInApartment(DWORD dwDll, HAPT hApt)
+{
+ for (DWORD dwAptent = _pDllPathEntries[dwDll]._nAptInUse;
+ dwAptent != NONE;
+ dwAptent = _pDllPathEntries[dwDll]._pAptEntries[dwAptent]._dwNext)
+ {
+ if (_pDllPathEntries[dwDll]._pAptEntries[dwAptent]._hApt == hApt)
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::MakeValidInApartment
+//
+// Synopsis: Ensure the Dll object is valid in the current apartment
+//
+// Arguments: dwDll - The index of this dll path entry
+//
+// Returns: S_OK - Dll is valid in this apartment
+// E_OUTOFMEMORY - Could not allocate memory
+//
+// History: 24-Jun-94 Rickhi Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+HRESULT CDllCache::MakeValidInApartment(DWORD dwDll)
+{
+ HRESULT hr;
+#ifdef WX86OLE
+ BOOL fIsX86Dll;
+#endif
+
+
+
+ // Walk the list of apartment entries looking for a match
+ // with the current apartment id. If one exists, we are valid,
+ // Otherwise, we will try to create an entry for the current
+ // apartment.
+ HAPT hApt = GetCurrentApartmentId();
+ if (IsValidInApartment(dwDll, hApt))
+ {
+ CairoleDebugOut((DEB_TRACE, "Making dll " TSZFMT " valid in apt %d\n",
+ _pDllPathEntries[dwDll]._ptszPath, hApt));
+ return S_OK;
+ }
+
+ // No match found, create a new entry
+ DWORD dwAptent = AllocAptEntry(dwDll);
+ if (dwAptent == NONE)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // Initialize the new apartment entry
+ _pDllPathEntries[dwDll]._pAptEntries[dwAptent].Create(hApt);
+
+
+ // Dll is always valid if Ole32 and for non-WOW case
+ if ((_pDllPathEntries[dwDll]._dwFlags & IS_OLE32) || !IsWOWProcess())
+ {
+ _pDllPathEntries[dwDll]._pAptEntries[dwAptent]._hDll = 0;
+ return S_OK;
+ }
+
+ // We need to release the lock across the LoadLibrary since there is
+ // a chance that an exiting thread waits on our mutext to
+ // CleanUpFoApartment while we wait on the kernel mutex which the
+ // exiting thread owns
+ TCHAR *ptszPath;
+ LPFNGETCLASSOBJECT pfnGetClassObject;
+ DLLUNLOADFNP pfnDllCanUnload;
+ DWORD dwSixteenBit;
+ HMODULE hDll;
+
+ ptszPath = _pDllPathEntries[dwDll]._ptszPath;
+ dwSixteenBit = _pDllPathEntries[dwDll]._dwFlags & SIXTEEN_BIT;
+
+ // Reset the entry point values on every apartment initialization
+ // to handle DLLs being unloaded and then reloaded at a different
+ // address.
+ _mxs.Release();
+ hr = Load(ptszPath,
+ &pfnGetClassObject,
+ &pfnDllCanUnload,
+ dwSixteenBit,
+ &hDll
+#ifdef WX86OLE
+ , &fIsX86Dll,
+ _pDllPathEntries[dwDll]._dwFlags & WX86_LOADASX86
+#endif
+ );
+ _mxs.Request();
+
+#ifdef WX86OLE
+ if (fIsX86Dll)
+ {
+ _pDllPathEntries[dwDll]._dwFlags |= WX86_THUNK;
+ }
+#endif
+
+ _pDllPathEntries[dwDll]._pfnGetClassObject = pfnGetClassObject;
+ _pDllPathEntries[dwDll]._pfnDllCanUnload = pfnDllCanUnload;
+ _pDllPathEntries[dwDll]._pAptEntries[dwAptent]._hDll = hDll;
+
+ if (FAILED(hr))
+ {
+ FreeAptEntry(dwDll, dwAptent);
+ }
+ else
+ {
+ CairoleDebugOut((DEB_TRACE, "Making dll %ws valid in apt %d\n",
+ _pDllPathEntries[dwDll]._ptszPath, hApt));
+ }
+
+ return hr;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::GetClassInterface
+//
+// Synopsis: Create the class factory from the DLL
+//
+// Arguments: [dwDll] - The index of this dll path entry
+// [rclsid] - class ID
+// [riid] - interface req'd of class object
+// [hr] - HRESULT to return
+//
+// Returns: NULL - class factory could not be created
+// ~NULL - newly created class factory
+//
+// History: 09-May-93 Ricksa Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+IUnknown *CDllCache::GetClassInterface(DWORD dwDll,
+ DWORD dwDllThreadModel,
+ REFCLSID rclsid,
+ REFIID riid,
+ HRESULT& hr)
+{
+ TRACECALL(TRACE_DLL, "CDllCache::GetClassInterface");
+ CairoleDebugOut((DEB_TRACE, "Getting class interface\n"));
+
+ IUnknown *punk = NULL;
+
+ // Make sure this Dll is valid in the current apartment.
+ if(FAILED(MakeValidInApartment(dwDll)))
+ {
+ return NULL;
+ }
+
+ // Need to check to see if the class is 16-bit or not.
+ // If it is 16-bit, then this call needs to be routed through
+ // a thunk
+ if (!(_pDllPathEntries[dwDll]._dwFlags & SIXTEEN_BIT))
+ {
+ // Find 32 bit interface
+ //
+ // We load single threaded DLLs specially if we are not in WOW.
+ // The reason for this is that the initial release of Daytona
+ // did not know about multiple threads and therefore, we want
+ // to make sure that they don't get inadvertently multithreaded.
+ // The reason we don't have to do this if we are in WOW is that
+ // only one thread is allowed to execute at a time even though
+ // there are multiple physical threads and therefore the DLL
+ // will never be executed in a multithreaded manner.
+
+ // Release the lock across outgoing calls
+ LPFNGETCLASSOBJECT pfnGetClassObject =
+ _pDllPathEntries[dwDll]._pfnGetClassObject;
+
+ // This prevents DllCanUnloadNow being called during this call out
+ _pDllPathEntries[dwDll]._cUsing++;
+
+ // this resets the delay time for delayed unload DLLs
+ _pDllPathEntries[dwDll]._dwExpireTime = 0;
+
+ _mxs.Release();
+
+ BOOL fThisThread = TRUE;
+ switch (dwDllThreadModel)
+ {
+ case SINGLE_THREADED:
+ if ((!IsWOWProcess() || !IsWOWThread() || !IsWOWThreadCallable())
+ && !OnMainThread())
+ {
+ // Pass the call to the main thread
+ fThisThread = FALSE;
+ if (IsMTAThread())
+ {
+ hr = DoSTMTClassCreate(pfnGetClassObject, rclsid, riid, &punk);
+ }
+ else
+ {
+ hr = DoSTClassCreate(pfnGetClassObject, rclsid, riid, &punk);
+ }
+ }
+ break;
+
+ case APT_THREADED:
+ if (IsMTAThread())
+ {
+ // pass call to apartment thread worker
+ fThisThread = FALSE;
+ hr = DoATClassCreate(pfnGetClassObject, rclsid, riid, &punk);
+ }
+ break;
+
+ case FREE_THREADED:
+ if (IsSTAThread())
+ {
+ // pass call to apartment thread worker
+ fThisThread = FALSE;
+ hr = DoMTClassCreate(pfnGetClassObject, rclsid, riid, &punk);
+ }
+ break;
+
+ case BOTH_THREADED:
+ break;
+ }
+
+ if (fThisThread)
+ {
+ hr = (*pfnGetClassObject)(rclsid, riid, (void **) &punk);
+ }
+
+ if (FAILED(hr))
+ {
+ CairoleDebugOut((DEB_ERROR,"GetClassInterface failed (0x%x)\n",hr));
+ }
+
+ _mxs.Request();
+ _pDllPathEntries[dwDll]._cUsing--;
+ }
+ else
+ {
+ // Find 16-bit interface
+ if (!IsWOWProcess())
+ {
+ CairoleDebugOut((DEB_TRACE,
+ "GetClassInterface on 16bit while not in VDM\n"));
+ return NULL;
+ }
+
+ if (!IsWOWThread())
+ {
+ CairoleDebugOut((DEB_TRACE,
+ "GetClassInterface on 16bit while not in 16-bit thread\n"));
+ return NULL;
+ }
+
+ // Release the lock across outgoing calls
+ LPFNGETCLASSOBJECT pfnGetClassObject =
+ _pDllPathEntries[dwDll]._pfnGetClassObject;
+
+ // This prevents DllCanUnloadNow being called during this call out
+ _pDllPathEntries[dwDll]._cUsing++;
+
+ _mxs.Release();
+ hr = g_pOleThunkWOW->CallGetClassObject((DWORD)pfnGetClassObject,
+ rclsid,
+ riid,
+ (void **)&punk);
+ _mxs.Request();
+ _pDllPathEntries[dwDll]._cUsing--;
+
+ if (FAILED(hr))
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "GetClassInterface 16-bit failed (0x%x)\n",hr));
+ }
+ }
+
+ return punk;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::CanUnloadNow
+//
+// Synopsis: Find out whether DLL can be unloaded.
+//
+// Algorithm: If the DLL supports unloading, ask it if it can be
+// unloaded and return the result to the caller.
+//
+// Arguments: dwDll - The index of this dll path entry
+//
+// History: 09-May-93 Ricksa Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+HRESULT CDllCache::CanUnloadNow(DWORD dwDll)
+{
+ CairoleDebugOut((DEB_TRACE, "Calling CanUnloadNow on " TSZFMT "\n",
+ _pDllPathEntries[dwDll]._ptszPath));
+
+ // Single thread access to the table
+ COleStaticLock lck(_mxs);
+
+ // Unless the code is changed, we should not be here in the Wow case
+ CairoleAssert(!IsWOWProcess() && "Freeing unused libraries in WOW");
+
+
+ if (_pDllPathEntries[dwDll]._cUsing != 0)
+ {
+ // At least one thread is using the object unlocked so we better
+ // not release the DLL object.
+ return S_FALSE;
+ }
+
+ // Does DLL support unloading itself?
+ if (_pDllPathEntries[dwDll]._pfnDllCanUnload)
+ {
+ // Release the lock across outgoing call
+ BOOL fSixteenBit = _pDllPathEntries[dwDll]._dwFlags & SIXTEEN_BIT;
+ DLLUNLOADFNP pfnDllCanUnload = _pDllPathEntries[dwDll]._pfnDllCanUnload;
+ HRESULT hr;
+
+ _mxs.Release();
+
+ // Need to check to see if the class is 16-bit.
+ // If it is 16-bit, then this call needs to be routed through a thunk
+ if (!fSixteenBit)
+ {
+ // Call through to the DLL -- does it think it can unload?
+ hr = (*pfnDllCanUnload)();
+ if (hr == S_OK &&
+ _pDllPathEntries[dwDll]._dwFlags & DELAYED_UNLOAD)
+ {
+ // the DLL thinks it's OK to unload, but we are employing
+ // delayed unloading, so go check if we've reached the
+ // expire time yet.
+ DWORD dwCurrentTime = GetTickCount();
+ if (_pDllPathEntries[dwDll]._dwExpireTime == 0)
+ {
+ // first time we've reached this state, record the
+ // expire timer. When current time exceeds this time
+ // we can unload.
+ _pDllPathEntries[dwDll]._dwExpireTime = dwCurrentTime + DLL_DELAY_UNLOAD_TIME;
+ if (_pDllPathEntries[dwDll]._dwExpireTime < DLL_DELAY_UNLOAD_TIME)
+ {
+ // handle counter wrapping, we'll just wait a little
+ // longer once every 49.7 days.
+ _pDllPathEntries[dwDll]._dwExpireTime = DLL_DELAY_UNLOAD_TIME;
+ }
+ hr = S_FALSE;
+ }
+ else
+ {
+ if ((_pDllPathEntries[dwDll]._dwExpireTime > dwCurrentTime) ||
+ (dwCurrentTime + DLL_DELAY_UNLOAD_TIME < _pDllPathEntries[dwDll]._dwExpireTime))
+ {
+ hr = S_FALSE;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (!IsWOWThread() || !IsWOWThreadCallable())
+ {
+ _mxs.Request();
+ return S_FALSE;
+ }
+
+ hr = g_pOleThunkWOW->CallCanUnloadNow((DWORD) pfnDllCanUnload);
+ }
+
+ _mxs.Request();
+ return hr;
+
+ }
+
+ return S_FALSE;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::CleanUpForApartmentByDllent
+//
+// Synopsis: Find and delete the apartment entry for the given apt
+//
+// Arguments: [dwDll] - the index of this dll path entry
+// [hApt] - apartment to clean up
+//
+// Returns: TRUE - There are no apartments using this object
+// FALSE - There are still apartments using this object
+//
+// Algorithm: Search the list for a matching apartment entry, unlink
+// it from the chain, and delete it.
+//
+// History: 24-Jun-94 Rickhi Created
+// 10-Nov-94 Ricksa Modified for DllCanUnloadNow
+// 07-Mar-95 BruceMa Rewrote
+// 29-May-96 BruceMa Also release class entries for the
+// specified apartment for this dll
+//
+//--------------------------------------------------------------------------
+BOOL CDllCache::CleanUpForApartmentByDllent(DWORD dwDll, HAPT hApt)
+{
+ DWORD dwNext;
+ // Remove all class entries associated with this apartment
+ DWORD dwClsent, dwNextCls;
+
+
+ // Loop through the active apartments for this dll
+ for (DWORD dwAptent = _pDllPathEntries[dwDll]._nAptInUse;
+ dwAptent != NONE;
+ dwAptent = dwNext)
+ {
+
+ // BUGBUG: The following for loop is inside the outer for loop to
+ // decrease the likelihood of a race condition in which another thread in
+ // the multithreaded apartement creates a class entry while the Release
+ // routine is being called only to have the corresponding apartment entry deleted
+ // and even worse, the DLL unloaded out from under it.
+
+ for (dwClsent = _pDllPathEntries[dwDll]._dw1stClass;
+ dwClsent != NONE;
+ dwClsent = dwNextCls)
+ {
+ // Pickup the next class entry now in case we delete
+ // this class entry
+ dwNextCls = _pClassEntries[dwClsent]._dwNextDllCls;
+
+ // Remove this class entry if it's for this apartment
+ if (_pClassEntries[dwClsent]._hApt == hApt)
+ {
+ // Release the server
+ Release(dwClsent);
+
+ // In case another thread came in and invalidated dwNextCls
+ dwNextCls = _pClassEntries[dwClsent]._dwNextDllCls;
+
+ // Release the class entry
+ FreeClassEntry(dwClsent);
+ }
+ }
+
+ // Save the next apartment entry in case we delete this one
+ dwNext = _pDllPathEntries[dwDll]._pAptEntries[dwAptent]._dwNext;
+
+ // Only for the specified apartment
+ if (_pDllPathEntries[dwDll]._pAptEntries[dwAptent]._hApt == hApt)
+ {
+ HMODULE hDll =
+ _pDllPathEntries[dwDll]._pAptEntries[dwAptent]._hDll;
+ BOOL fSixteenBit = _pDllPathEntries[dwDll]._dwFlags & SIXTEEN_BIT;
+
+ // Free the library
+ if (fSixteenBit && IsWOWThread() && IsWOWThreadCallable() &&
+ !(_pDllPathEntries[dwDll]._dwFlags & IS_OLE32))
+ {
+
+ // Release the lock across the free library
+ // No need to worry about another thread coming in and attaching while
+ // the lock is released because that would only happen in the free threaded
+ // apartment, which cannot host 16-bit DLLs.
+ _mxs.Release();
+ g_pOleThunkWOW->UnloadProcDll((DWORD) hDll);
+ // Retake the lock
+ _mxs.Request();
+
+ // In case dwNext got invalidated
+ dwNext = _pDllPathEntries[dwDll]._pAptEntries[dwAptent]._dwNext;
+ }
+
+ // Remove the apartment entry
+ FreeAptEntry(dwDll, dwAptent);
+ }
+
+
+ }
+
+ return _pDllPathEntries[dwDll]._nAptInUse != NONE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::RemoveAndUnload
+//
+// Synopsis: Unload a dll
+//
+// Arguments: dwDll - This index of this dll path entry
+//
+// History: 07-Mar-95 BruceMa Created
+//
+// Notes: The dll has already said it can unload
+//
+//--------------------------------------------------------------------------
+void CDllCache::RemoveAndUnload(DWORD dwDll)
+{
+ CairoleDebugOut((DEB_TRACE, "RemoveAndUnload " TSZFMT " dwDll:%x\n",
+ _pDllPathEntries[dwDll]._ptszPath, dwDll));
+ Win4Assert(_pDllPathEntries[dwDll]._nAptInUse == NONE && "Cannot unload dll with apartments attached.");
+ Win4Assert(_pDllPathEntries[dwDll]._dw1stClass == NONE && "Cannot unload dll with classes attached.");
+
+ // Invalidate this entry while holding the lock because we're going to
+ // unload the dll
+ _pDllPathEntries[dwDll]._dwSig = NULL;
+
+ // 32 bit libraries haven't been freed yet
+ if (!(_pDllPathEntries[dwDll]._dwFlags & SIXTEEN_BIT) &&
+ !IsWOWThread() &&
+ !(_pDllPathEntries[dwDll]._dwFlags & IS_OLE32) &&
+ _pDllPathEntries[dwDll]._hDll32)
+ {
+ _mxs.Release();
+ FreeLibrary(_pDllPathEntries[dwDll]._hDll32);
+ _mxs.Request();
+ }
+
+ // Delete the path
+ PrivMemFree(_pDllPathEntries[dwDll]._ptszPath);
+ _pDllPathEntries[dwDll]. _ptszPath = NULL;
+
+
+ delete _pDllPathEntries[dwDll]._pAptEntries;
+ _pDllPathEntries[dwDll]._pAptEntries = NULL;
+
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::GetClass
+//
+// Synopsis: Get a class factory object for a class
+//
+// Arguments: [rclsid] Class ID
+// [riid] Interface required of class object
+// [fRemote] Whether path is remote
+// [fForScm] Whether it's the scm requesting
+//
+// Returns: ~NULL - Class factory for object
+// NULL - Class factory could not be found or
+// constructed.
+//
+// History: 09-May-93 Ricksa Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+HRESULT CDllCache::GetClass(REFCLSID rclsid,
+ REFIID riid,
+ BOOL fRemote,
+ BOOL fForSCM,
+ BOOL fSurrogate,
+#ifdef WX86OLE
+ BOOL fWx86,
+#endif
+ IUnknown **ppunk
+)
+{
+ TRACECALL(TRACE_DLL, "CDllCache::GetClass");
+ CairoleDebugOut((DEB_TRACE, "Get class\n"));
+
+ HRESULT hr = S_OK;
+
+ *ppunk = NULL;
+
+ // Single thread access to the table
+ COleStaticLock lck(_mxs);
+
+ // It's on behalf of the scm
+ if (fForSCM)
+ {
+ DWORD dwClsent;
+
+ // Note: On Chicago we are already on the thread that registered
+ // the class; RPC sees to this. On NT we are on the thread that
+ // registered the class because GetAptForCLSID() followed by
+ // GetToComThread() guarantees this.
+ //
+ // Search for the entry for this CLSID
+ dwClsent = Search(rclsid, CLSCTX_LOCAL_SERVER, GetCurrentApartmentId());
+
+ // Check if we have a registered class
+ if (dwClsent != NONE &&
+ !(_pClassEntries[dwClsent]._dwFlags & REGCLS_SUSPENDED))
+ {
+ if (_pClassEntries[dwClsent]._dwFlags == REGCLS_SINGLEUSE)
+ {
+ _pClassEntries[dwClsent]._dwContext = 0;
+ }
+
+ // Release the lock across outgoing call
+ IUnknown *pUnkTmp = _pClassEntries[dwClsent]._pUnk;
+
+ // Indicate we're in an outgoing call
+ _pClassEntries[dwClsent]._cCallOut++;
+
+ _mxs.Release();
+ // Since we are being called on behalf of SCM we know that
+ // we are being invoked remotely. Set the Wx86 stub invoked flag
+ // if we are calling into x86 code so that any custom interfaces
+ // can be thunked back and not rejected.
+#ifdef WX86OLE
+ if (gcwx86.IsN2XProxy(pUnkTmp))
+ {
+ gcwx86.SetStubInvokeFlag(1);
+ }
+#endif
+ hr = pUnkTmp->QueryInterface(fSurrogate ? IID_IClassFactory : riid,
+ (void **)ppunk);
+
+ _mxs.Request();
+
+ // We're no longer in an outgoing call
+ _pClassEntries[dwClsent]._cCallOut--;
+
+ // If a revoke came in while we were calling out then do the
+ // revoke now
+ if (_pClassEntries[dwClsent]._fRevokePending &&
+ _pClassEntries[dwClsent]._cCallOut == 0)
+ {
+ // Release our reference on the server
+ Release(dwClsent);
+
+ // Free the class entry
+ FreeClassEntry(dwClsent);
+
+ // Since the object has been released return failure
+ hr = CO_E_OBJNOTCONNECTED;
+ }
+
+ return hr;
+ }
+ }
+ else
+ {
+ // Else it's a local request
+ DWORD dwClsent;
+
+ // Search for the class
+ dwClsent = Search(rclsid,
+#ifdef WX86OLE
+ fWx86 ? CLSCTX_INPROC_SERVERX86 | CLSCTX_INPROC_HANDLERX86 :
+ CLSCTX_INPROC,
+#else
+ CLSCTX_INPROC,
+#endif
+ GetCurrentApartmentId());
+
+ // Check if we found it
+ if (dwClsent != NONE)
+ {
+ // If the path is remote and we were launched AtStorage, then
+ // we need to be launched AtStorage again at the remote site, so
+ // fail locally
+ if (fRemote && _pClassEntries[dwClsent]._fAtStorage)
+ {
+ return NULL;
+ }
+
+ // Check if it's a locally registered local server
+ if (_pClassEntries[dwClsent]._dwDllEnt == NONE)
+ {
+ if (_pClassEntries[dwClsent]._dwFlags == REGCLS_SINGLEUSE)
+ {
+ _pClassEntries[dwClsent]._dwContext = 0;
+ }
+
+ // Release the lock across outgoing call
+ IUnknown *pUnkTmp = _pClassEntries[dwClsent]._pUnk;
+
+ // Indicate we're in an outgoing call
+ _pClassEntries[dwClsent]._cCallOut++;
+
+ _mxs.Release();
+
+ hr = pUnkTmp->QueryInterface(fSurrogate ? IID_IClassFactory : riid,
+ (void **)ppunk);
+ _mxs.Request();
+
+ // We're no longer in an outgoing call
+ _pClassEntries[dwClsent]._cCallOut--;
+
+ // If a revoke came in while we were calling out then do the
+ // revoke now
+ if (_pClassEntries[dwClsent]._fRevokePending &&
+ _pClassEntries[dwClsent]._cCallOut == 0)
+ {
+ // Release our reference on the server
+ Release(dwClsent);
+
+ // Free the class entry
+ FreeClassEntry(dwClsent);
+ }
+ }
+
+ // Else it's a dll. Note - we could have AddRef'd the
+ // interface the first time we got it, when we created this
+ // class entry, but then there would be no way to know when
+ // to release it and therefore the dll could never unload. So
+ // instead we do the same as if we had just loaded the dll.
+ else
+ {
+ *ppunk = GetClassInterface(_pClassEntries[dwClsent]._dwDllEnt,
+ _pClassEntries[dwClsent]._dwDllThreadModel,
+ rclsid,
+ riid,
+ hr);
+ }
+
+ return hr;
+ }
+
+ }
+
+ //
+ // It's ok to have no class factory in the cache, so return a success
+ // error code here.
+ //
+ Win4Assert( *ppunk == 0 );
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::GetOrLoadClass
+//
+// Synopsis: Get a class factory object for a class, loading an INPROC
+// DLL if needed
+//
+// Arguments: [rclsid] Class ID
+// [riid] Interface required of class object
+// [fRemote] Whether path is remote
+// [fForScm] Whether it's the scm requesting
+// [dwContext] Which context to load
+// [dwCallerThreadModel] Which threading model to load
+// [hr] Reference to HRESULT for error returns
+//
+// Returns: ~NULL - Class factory for object
+// NULL - Class factory could not be found or
+// constructed.
+//
+// History: 09-May-93 KevinRo
+//
+// Note:
+//
+//--------------------------------------------------------------------------
+IUnknown *CDllCache::GetOrLoadClass(REFCLSID rclsid,
+ REFIID riid,
+ BOOL fRemote,
+ BOOL fForSCM,
+#ifdef WX86OLE
+ BOOL fWx86,
+#endif
+ DWORD dwContext,
+ DWORD dwCallerThreadModel,
+ HRESULT &hr)
+{
+ CairoleDebugOut((DEB_ITRACE,
+ "CDllCache::GetOrLoadClass(clsid(%I),riid(%I),fRemote(%x),fForSCM(%x)"
+ ",dwContext(%x),dwCallerThreadModel(%x))\n",
+ &rclsid,
+ &riid,
+ fRemote,
+ fForSCM,
+ dwContext,
+ dwCallerThreadModel));
+
+ IUnknown *punk = NULL;
+
+ hr = S_OK;
+
+#ifndef GET_INPROC_FROM_SCM
+ // Just in case we chicken out and back out our changes
+ //
+ // The context should either be INPROC_HANDLER or INPROC_SERVER, but
+ // never both.
+ //
+ Win4Assert((dwContext & CLSCTX_INPROC_HANDLERS) || (dwContext & CLSCTX_INPROC_SERVERS));
+ Win4Assert(!!(dwContext & CLSCTX_INPROC_SERVERS) != !!(dwContext & CLSCTX_INPROC_HANDLERS));
+#endif // GET_INPROC_FROM_SCM
+
+ //
+ // First, check to see if the class is available in the cache
+ // already. If it is, grab it and get out.
+ //
+#ifdef WX86OLE
+ hr = GetClass(rclsid,riid,fRemote,fForSCM,FALSE,fWx86,&punk);
+#else
+ hr = GetClass(rclsid,riid,fRemote,fForSCM,FALSE,&punk);
+#endif
+
+ //
+ // If it is, then just return it
+ //
+ if (punk != NULL)
+ {
+ CairoleDebugOut((DEB_ITRACE,
+ "::GetOrLoadClass(clsid(%I)...) found class in cache",&rclsid));
+ return(punk);
+ }
+
+#ifndef GET_INPROC_FROM_SCM
+ // Just in case we chicken out and back out our changes
+ //
+ // The CLSID wasn't found. Look it up
+ // in the registry and see if it exists. We follow a priority order
+ //
+
+ CairoleDebugOut((DEB_ITRACE,"::GetClass clsid(%I) not found. Try loading\n",&rclsid));
+
+ TCHAR achBuffer[80]; // Holds the string CLSID\{guid}\InprocServer|handler etc
+
+ memcpy(achBuffer,CLSIDBACK,CLSIDBACK_BYTE_LEN);
+
+ wStringFromGUID2T(rclsid,&achBuffer[CLSIDBACK_CHAR_LEN],GUIDSTR_MAX);
+
+ //
+ // achBuffer now has the string 'CLSID\{strofguid}'. This is the prefix string we
+ // need for doing the following code. Each bit of code below will stomp its own.
+ //
+ // Note that GUIDSTR_MAX is the number of characters including the NULL of the
+ // length of a GUID. We are going to manually append an additional slash to
+ // the string, which 'eats' the NULL character.
+ //
+#define PREFIX_STRING_OFFSET (CLSIDBACK_CHAR_LEN + GUIDSTR_MAX )
+
+ achBuffer[PREFIX_STRING_OFFSET - 1] = '\\';
+
+ TCHAR achDllPath[MAX_PATH];
+ LONG clDllPath;
+ ULONG ulDllType;
+ LONG lErr;
+
+ //
+ // Assume it won't be found
+ //
+ hr = REGDB_E_CLASSNOTREG;
+
+ // If 16-bit has been requested and we find it, we'll return that
+ if (dwContext & CLSCTX_INPROC_SERVER16)
+ {
+ clDllPath = MAX_PATH;
+ memcpy(&achBuffer[PREFIX_STRING_OFFSET],tszInprocServer16,sizeof(tszInprocServer16));
+
+ CairoleAssert(punk == NULL);
+ hr = REGDB_E_CLASSNOTREG;
+
+ // Read 16 bit DLL information
+ if (wQueryStripRegValue(HKEY_CLASSES_ROOT,achBuffer,achDllPath,&clDllPath) == ERROR_SUCCESS)
+ {
+ //
+ // Found a 16-bit INPROC server. Add it to the cache.
+ //
+#ifdef WX86OLE
+ punk = Add(rclsid,riid,APT_THREADED,achDllPath,TRUE,TRUE,FALSE,hr);
+#else
+ punk = Add(rclsid,riid,APT_THREADED,achDllPath,TRUE,TRUE,hr);
+#endif
+ }
+ }
+
+#ifdef WX86OLE
+ if ((punk == NULL) && (fWx86) && (dwContext & CLSCTX_INPROC_SERVERX86))
+ {
+ clDllPath = MAX_PATH;
+ memcpy(&achBuffer[PREFIX_STRING_OFFSET],tszInprocServerX86,sizeof(tszInprocServerX86));
+
+ hr = REGDB_E_CLASSNOTREG;
+
+ // Read 32 bit DLL information
+ if (wGetDllInfo(HKEY_CLASSES_ROOT,achBuffer,achDllPath,&clDllPath,&ulDllType) == ERROR_SUCCESS)
+ {
+ //
+ // If we are after a proxy/stub dll, then load it as both
+ // no matter what the DLL says.
+ //
+ if (dwContext & CLSCTX_PS_DLL)
+ {
+ ulDllType = BOTH_THREADED;
+ }
+
+ //
+ // If it turns out this path is for OLE32.DLL, then add the DLL without the
+ // path.
+ //
+ LPCTSTR pDllName = wCompareDllName(achDllPath,OLE32_DLL,OLE32_CHAR_LEN)?
+ OLE32_DLL:achDllPath;
+
+ //
+ // load it.
+ //
+ punk = Add(rclsid,riid,ulDllType,achDllPath,TRUE,FALSE,
+ !(pDllName == OLE32_DLL),hr);
+ }
+ }
+#endif
+
+ //
+ // Could be that we are trying to load an INPROC_SERVER
+ //
+ if ( (punk == NULL) && (dwContext & CLSCTX_INPROC_SERVER))
+ {
+ clDllPath = MAX_PATH;
+
+ //
+ // Need to reassign since it could have changed above
+ //
+ hr = REGDB_E_CLASSNOTREG;
+
+ memcpy(&achBuffer[PREFIX_STRING_OFFSET],tszInprocServer,sizeof(tszInprocServer));
+
+ // Read 32-bit DLL information
+ if (wGetDllInfo(HKEY_CLASSES_ROOT,achBuffer,achDllPath,&clDllPath,&ulDllType) == ERROR_SUCCESS)
+ {
+ //
+ // If we are after a proxy/stub dll, then load it as both
+ // no matter what the DLL says.
+ //
+ if (dwContext & CLSCTX_PS_DLL)
+ {
+ ulDllType = BOTH_THREADED;
+ }
+ //
+ // load it.
+ //
+#ifdef WX86OLE
+ punk = Add(rclsid,riid,ulDllType,achDllPath,TRUE,FALSE,FALSE,hr);
+#else
+ punk = Add(rclsid,riid,ulDllType,achDllPath,TRUE,FALSE,hr);
+#endif
+ }
+ }
+
+ //
+ // If INPROC_HANDLER16 set, then we look to load a 16-bit handler.
+ // If the handler is ole2.dll, then we will load ole32 instead.
+ // Otherwise we load the found 16bit dll but only if in a WOW thread.
+ //
+ if ((punk == NULL) && (dwContext & CLSCTX_INPROC_HANDLER16 ))
+ {
+ clDllPath = MAX_PATH;
+
+ memcpy(&achBuffer[PREFIX_STRING_OFFSET],tszInprocHandler16,sizeof(tszInprocHandler16));
+
+ lErr = wGetDllInfo(HKEY_CLASSES_ROOT,achBuffer,achDllPath,&clDllPath,&ulDllType);
+
+ //
+ // Need to reassign since it could have changed above
+ //
+ hr = REGDB_E_CLASSNOTREG;
+
+ if (lErr == ERROR_SUCCESS)
+ {
+ //
+ // If the inproc handler is ole2.dll, then subst
+ // ole32.dll instead
+ //
+ if (wCompareDllName(achDllPath,OLE2_DLL,OLE2_CHAR_LEN))
+ {
+ // Add and load OLE32.DLL
+#ifdef WX86OLE
+ punk = Add(rclsid,riid,BOTH_THREADED,OLE32_DLL,TRUE,FALSE,FALSE,hr);
+#else
+ punk = Add(rclsid,riid,BOTH_THREADED,OLE32_DLL,TRUE,FALSE,hr);
+#endif
+ }
+ else
+ {
+ // Otherwise, load the 16-bit fellow but only if in WOW thread
+ if (IsWOWThread())
+ {
+#ifdef WX86OLE
+ punk = Add(rclsid,riid,ulDllType,achDllPath,TRUE,TRUE,FALSE,hr);
+#else
+ punk = Add(rclsid,riid,ulDllType,achDllPath,TRUE,TRUE,hr);
+#endif
+ }
+ }
+ }
+ }
+
+ //
+ // See about 32-bit handlers. A was a change made after the
+ // Win95 (August release) and Windows/NT 3.51 release. Previously
+ // the code would give preference to loading 32-bit handlers. This
+ // means that even if an ISV provided both 16 and 32-bit handlers,
+ // the code would only attempt to provide the 32-bit handler. This
+ // was bad because servers with handlers could not be inserted into
+ // containers in the wrong model. We have fixed it here.
+ //
+ // Another thing to watch out for are applications that use our
+ // default handler. 16-bit applications can and should be able to
+ // use OLE32 has a handler. This will happen if the server app is
+ // actually a 32-bit.
+ //
+ //
+#ifdef WX86OLE
+ if((punk == NULL) && (fWx86) && (dwContext & CLSCTX_INPROC_HANDLERX86))
+ {
+ clDllPath = MAX_PATH;
+
+ memcpy(&achBuffer[PREFIX_STRING_OFFSET],tszInprocHandlerX86,sizeof(tszInprocHandlerX86));
+
+ lErr = wGetDllInfo(HKEY_CLASSES_ROOT,achBuffer,achDllPath,&clDllPath,&ulDllType);
+
+ //
+ // Need to reassign since it could have changed above
+ //
+ hr = REGDB_E_CLASSNOTREG;
+
+ if (lErr == ERROR_SUCCESS)
+ {
+ //
+ // If it turns out this path is for OLE32.DLL, then add the DLL without the
+ // path.
+ //
+ LPCTSTR pDllName = wCompareDllName(achDllPath,OLE32_DLL,OLE32_CHAR_LEN)?
+ OLE32_DLL:achDllPath;
+
+ // Add a 32-bit handler to the pile.
+ punk = Add(rclsid,riid,ulDllType,pDllName,TRUE,FALSE,!(pDllName == ptszOle32DllName),hr);
+ }
+ }
+#endif
+
+ if((punk == NULL) && (dwContext & CLSCTX_INPROC_HANDLERS))
+ {
+ clDllPath = MAX_PATH;
+
+ memcpy(&achBuffer[PREFIX_STRING_OFFSET],tszInprocHandler,sizeof(tszInprocHandler));
+
+ lErr = wGetDllInfo(HKEY_CLASSES_ROOT,achBuffer,achDllPath,&clDllPath,&ulDllType);
+
+ //
+ // Need to reassign since it could have changed above
+ //
+ hr = REGDB_E_CLASSNOTREG;
+
+ if (lErr == ERROR_SUCCESS)
+ {
+ //
+ // If it turns out this path is for OLE32.DLL, then add the DLL without the
+ // path.
+ //
+ LPCTSTR pDllName = wCompareDllName(achDllPath,OLE32_DLL,OLE32_CHAR_LEN)?
+ OLE32_DLL:achDllPath;
+
+ //
+ // If we are looking for a INPROC_HANDER16 and this is OLE32.DLL, or if we
+ // are looking for an INPROC_HANDLER, then load this path. Note that pDllName
+ // was set above.
+ //
+ // If we're in a Wow thread the only 32 bit DLL we're allowed to load is
+ // OLE32.DLL
+ if ((IsWOWThread() && (pDllName == OLE32_DLL)) ||
+ (!IsWOWThread() ))
+ {
+ // Add a 32-bit handler to the pile.
+#ifdef WX86OLE
+ punk = Add(rclsid,riid,ulDllType,pDllName,TRUE,FALSE,FALSE,hr);
+#else
+ punk = Add(rclsid,riid,ulDllType,pDllName,TRUE,FALSE,hr);
+#endif
+ }
+ }
+#ifdef WX86OLE
+ else if (gcwx86.IsWx86Installed() && (! gcwx86.IsWx86Enabled()))
+ {
+ // If Wx86 is installed on this system, but this is not a Wx86
+ // process and we could not find an InprocHandler32 we want to
+ // look for a InprocHandlerX86 in case an x86 local server is
+ // avaialable. If we find an InprocHandlerX86 and it is Ole32.dll
+ // then we will use it otherwise we can't since we assume it is
+ // an x86 dll.
+ clDllPath = MAX_PATH;
+
+ memcpy(&achBuffer[PREFIX_STRING_OFFSET],tszInprocHandlerX86,sizeof(tszInprocHandlerX86));
+
+ lErr = wGetDllInfo(HKEY_CLASSES_ROOT,achBuffer,achDllPath,&clDllPath,&ulDllType);
+
+ if (lErr == ERROR_SUCCESS)
+ {
+ //
+ // If it turns out this path is for OLE32.DLL, then add the DLL without the
+ // path.
+ //
+ BOOLEAN fIsOle32 = wCompareDllName(achDllPath,OLE32_DLL,OLE32_CHAR_LEN);
+ if (fIsOle32)
+ {
+ // Only if it is Ole32.Dll Add a 32-bit handler to native pile.
+ LPCTSTR pDllName = OLE32_DLL;
+ punk = Add(rclsid,riid,ulDllType,pDllName,TRUE,FALSE,FALSE,hr);
+ }
+ }
+ }
+ if (lErr != ERROR_SUCCESS)
+#else
+ else
+#endif
+ {
+ // We're here if we couldn't find a 32-bit handler. If non-Wow caller didn't
+ // explicitly request 16-bit handler we'll look for one here. But the only one
+ // allowed is OLE2.DLL => OLE32.DLL
+ if (!IsWOWThread() && !(dwContext & CLSCTX_INPROC_HANDLER16))
+ {
+ clDllPath = MAX_PATH;
+
+ memcpy(&achBuffer[PREFIX_STRING_OFFSET],tszInprocHandler16,sizeof(tszInprocHandler16));
+
+ lErr = wGetDllInfo(HKEY_CLASSES_ROOT,achBuffer,achDllPath,&clDllPath,&ulDllType);
+
+ //
+ // Need to reassign since it could have changed above
+ //
+ hr = REGDB_E_CLASSNOTREG;
+
+ if (lErr == ERROR_SUCCESS)
+ {
+ //
+ // If the inproc handler is ole2.dll, then subst
+ // ole32.dll instead
+ //
+ if (wCompareDllName(achDllPath,OLE2_DLL,OLE2_CHAR_LEN))
+ {
+ // Add and load OLE32.DLL
+#ifdef WX86OLE
+ punk = Add(rclsid,riid,BOTH_THREADED,OLE32_DLL,TRUE,FALSE,FALSE,hr);
+#else
+ punk = Add(rclsid,riid,BOTH_THREADED,OLE32_DLL,TRUE,FALSE,hr);
+#endif
+ }
+ }
+ }
+ }
+ }
+
+ return(punk);
+#else // GET_INPROC_FROM_SCM
+ return NULL; // don't have it cached
+#endif // GET_INPROC_FROM_SCM
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDllCache::GetClassObjForDde
+//
+// Synopsis: Get a class entry from the table for Dde, returning
+// extra information, including the flags.
+//
+// Effects: The DdeServer needs the ability to query the class factory
+// table to search for classes it needs to provide OLE 1.0
+// support for. This routine will allow it to access the
+// required information.
+//
+// Arguments: [clsid] Class to lookup ClassObject for
+// [lpDdeInfo] Structure to fill in
+//
+// Returns: TRUE if the entry matched, FALSE if it did not.
+//
+// History: 5-28-94 kevinro Created
+// 07-Mar-95 BruceMa Rewrote
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL CDllCache::GetClassObjForDde(REFCLSID clsid,
+ LPDDECLASSINFO lpDdeInfo)
+{
+ TRACECALL(TRACE_DLL, "CDllCache::GetClassObjForDde");
+
+ CairoleDebugOut((DEB_TRACE, "Get class object for DDE\n"));
+
+ // Single thread access to the table
+ COleStaticLock lck(_mxs);
+
+ Win4Assert(IsValidPtrOut(lpDdeInfo, sizeof(DWORD)) &&
+ "CDllCache::GetClassObjForDde invalid out parameter");
+
+ DWORD dwClsent = Search(clsid, CLSCTX_LOCAL_SERVER, GetCurrentApartmentId());
+
+ if (dwClsent != NONE)
+ {
+ return GetClassObjForDdeByClsent(dwClsent, lpDdeInfo);
+ }
+
+ return FALSE;
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDllCache::GetClassInformationFromKey
+//
+// Synopsis: Get class object information for the Dde server using a key
+//
+// Effects: This routine is called by the DDE server code to retrieve the
+// class information for a specific class registration. The
+// theory is that the DDE server window has already called
+// GetClassInformationForDde. Some time X has passed, and the
+// server has a request for the specific class registration.
+//
+// This routine allows the DDE server to request current
+// class information by specific registration key.
+//
+// Arguments: [lpDdeInfo] Structure to fill in with information
+//
+// Requires: lpDdeInfo->dwRegistrationKey is the key to the specific
+// class being asked for.
+//
+// Returns: TRUE Structure filled in with appropriate information
+// FALSE The registration is no longer valid.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-28-94 kevinro Created
+// 07-Mar-95 BruceMa Rewrote
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL CDllCache::GetClassInformationFromKey(LPDDECLASSINFO lpDdeInfo)
+{
+ TRACECALL(TRACE_DLL, "CDllCache::GetClassInformationFromKey");
+
+ CairoleDebugOut((DEB_TRACE, "Get class inbfo from key for DDE\n"));
+
+ // Single thread access to the table
+ COleStaticLock lck(_mxs);
+
+ DWORD dwClsent = Search(lpDdeInfo->dwRegistrationKey, GetCurrentApartmentId());
+
+ if (dwClsent != NONE)
+ {
+ return GetClassObjForDdeByClsent(dwClsent, lpDdeInfo);
+ }
+
+ return FALSE;
+}
+
+
+
+
+#ifdef _CHICAGO_
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::GetApartmentForCLSID
+//
+// Synopsis: Get the apartment id for this clsid
+//
+// Arguments: [rclsid] class ID
+// [hApt] Where to return the apartment id
+//
+// Returns: TRUE Got the apartment id for an available class object
+// FALSE No available class object for given class
+//
+// History: 30-Apr-93 JohannP Created
+// 07-Mar-95 BruceMa Rewrote
+// 06-Oct-95 BruceMa Make for Chicago only
+//
+//--------------------------------------------------------------------------
+inline BOOL CDllCache::GetApartmentForCLSID(REFCLSID rclsid, HAPT &hApt)
+{
+
+ CairoleDebugOut((DEB_TRACE, "Get apartment for CLSID\n"));
+
+ // On Chicago we are already on the correct thread
+ hApt = GetCurrentApartmentId();
+ return TRUE;
+}
+#endif // _CHICAGO_
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::Add
+//
+// Synopsis: Add a DLL entry to the cache
+//
+// Arguments: [rclsid] - class id
+// [riid] - interface required of the class object
+// [ptszDllPath] - path to DLL
+// [fGetClassObject] - whether class factory object is needed.
+// [fSixteenBit] - TRUE if we want the 16bit dll
+// [fWx86] - TRUE if x86 dll in Wx86 process
+// [hr] - hresult returned
+//
+// Returns: Pointer to class factory if requested.
+//
+// Algorithm: Create a path key. If such a DLL is already cached, use
+// that otherwise create a new DLL path entry. Then add
+// a new class object.
+//
+// History: 09-May-93 Ricksa Created
+// 28-Jun-94 BruceMa Memory SIFT fixes
+// 07-Jul-94 BruceMa Memory SIFT fixes
+// 21-Nov-94 BruceMa Don't return E_OUTOFMEMORY if can't find
+// dll
+// 07-Mar-95 BruceMa Rewrote
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+IUnknown *CDllCache::Add(REFCLSID rclsid,
+ REFIID riid,
+ DWORD dwDllThreadModel,
+ const TCHAR *ptszDllPath,
+ BOOL fGetClassObject,
+ BOOL fSixteenBit,
+#ifdef WX86OLE
+ BOOL fWx86,
+#endif
+ HRESULT& hr)
+{
+ TRACECALL(TRACE_DLL, "CDllCache::Add");
+ CairoleDebugOut((DEB_TRACE, "Add dll %ts to cache\n", ptszDllPath));
+
+ hr = E_FAIL;
+
+ IUnknown *punk = NULL;
+
+ // Single thread access to the table
+ COleStaticLock lck(_mxs);
+
+ // This better be a valid dll path
+ if (ptszDllPath != NULL)
+ {
+ LPFNGETCLASSOBJECT pfnGetClassObject;
+ DLLUNLOADFNP pfnDllCanUnload;
+ HMODULE hDll;
+
+#ifdef WX86OLE
+ BOOL fIsX86Dll = FALSE;
+#endif
+
+ // Check if we already have an entry for this dll
+ DWORD dwDllent = SearchForDll(ptszDllPath
+#ifdef WX86OLE
+ , fWx86
+#endif
+);
+ // If not, create a new dll path entry
+ if (dwDllent == NONE)
+ {
+ // Check if this is "OLE32.DLL" - we don't need to load
+ // ourselves; we're already running
+ if (lstrcmp(ptszDllPath, ptszOle32DllName)
+ != 0)
+ {
+ // We need to release the lock across the LoadLibrary since
+ // there is a chance that an exiting thread waits on our
+ // mutext to CleanUpForApartment while we wait on the kernel
+ // mutex which the exiting thread owns, causing a deadlock.
+ _mxs.Release();
+
+ // Load the library
+ hr = Load(ptszDllPath,
+ &pfnGetClassObject,
+ &pfnDllCanUnload,
+ fSixteenBit,
+ &hDll
+#ifdef WX86OLE
+ ,&fIsX86Dll,
+ fWx86
+#endif
+);
+
+ // Retake the lock while intializng the dll entry
+ _mxs.Request();
+
+ // Check for success
+ if (FAILED(hr))
+ {
+ return NULL;
+ }
+ }
+
+ // Check whether another thread got in and loaded the dll
+ dwDllent = SearchForDll(ptszDllPath
+#ifdef WX86OLE
+ , fWx86
+#endif
+);
+
+ // If so, then use that
+ if (dwDllent != NONE)
+ {
+ // Make it valid for this apartment
+ if (FAILED(MakeValidInApartment(dwDllent)))
+ {
+ return NULL;
+ }
+ _mxs.Release();
+ FreeLibrary(hDll);
+ _mxs.Request();
+ }
+
+ // Else create a new dll entry
+ else
+ {
+ // Allocate a dll path entry
+ dwDllent = AllocDllPathEntry();
+ if (dwDllent == NONE)
+ {
+ hr = E_OUTOFMEMORY;
+ return NULL;
+ }
+
+ // Initialize the dll path entry (this will load the dll)
+ hr = CreateDllent(dwDllent,
+ ptszDllPath,
+ fSixteenBit,
+ pfnGetClassObject,
+ pfnDllCanUnload,
+ hDll
+#ifdef WX86OLE
+ ,fIsX86Dll,
+ fWx86
+#endif
+);
+ if (FAILED(hr))
+ {
+ FreeDllPathEntry(dwDllent);
+ return NULL;
+ }
+
+ _pDllPathEntries[dwDllent]._dw1stClass = NONE;
+
+ // Make it valid for this apartment
+ if (FAILED(MakeValidInApartment(dwDllent)))
+ {
+ return NULL;
+ }
+ }
+ }
+
+ CairoleAssert(dwDllent != NONE);
+
+
+ // Get requested interface
+ punk = GetClassInterface(dwDllent,
+ dwDllThreadModel,
+ rclsid,
+ riid,
+ hr);
+
+ if (SUCCEEDED(hr))
+ {
+ // Add a class entry for this interface if we don't already
+ // have one
+
+ // search according to type of dll as passed into thus func
+ if (Search(rclsid,
+#ifdef WX86OLE
+ fWx86 ? CLSCTX_INPROC_SERVERX86 :
+#endif
+ CLSCTX_INPROC_SERVER,
+ GetCurrentApartmentId()) == NONE)
+ {
+ DWORD dwClsent = AllocClassEntry();
+ if (dwClsent == NONE)
+ {
+ return NULL;
+ }
+ CreateClsentInProc(dwClsent,
+ dwDllent,
+ dwDllThreadModel,
+ _pDllPathEntries[dwDllent]._dw1stClass,
+ rclsid
+#ifdef WX86OLE
+ ,fWx86
+#endif
+);
+ _pDllPathEntries[dwDllent]._dw1stClass = dwClsent;
+ }
+
+ return punk;
+ }
+ }
+
+ return NULL;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::FreeUnused
+//
+// Synopsis: Free any unused DLLs
+//
+// Algorithm: For each DLL in the list of DLLs call its Dll can unload
+// now entry point.
+//
+// History: 09-May-93 Ricksa Created
+// 04-May-94 AlexT Only free DLL if it returns S_OK!
+// 07-Mar-95 BruceMa Rewrote
+//
+//
+//
+//--------------------------------------------------------------------------
+void CDllCache::FreeUnused(void)
+{
+ TRACECALL(TRACE_DLL, "CDllCache::FreeUnused");
+
+ CairoleDebugOut((DEB_TRACE, "Free unused dll's\n"));
+
+ // Single thread access to the table
+ COleStaticLock lck(_mxs);
+
+ // Unless the code is changed, we should not be here in the Wow case
+ CairoleAssert(!IsWOWProcess() && "Freeing unused libraries in WOW");
+
+ // Free any loaded dll's (only if we still have a cache)
+ if (_pDllPathEntries)
+ {
+ // Sequentially scan the list of loaded dll's, unloading where we can
+ DWORD dwNext;
+
+ for (DWORD dwDllent = _nDllPathEntryInUse;
+ dwDllent != NONE;
+ dwDllent = dwNext)
+ {
+ // Save the next entry in case we free this one
+ dwNext = _pDllPathEntries[dwDllent]._dwNext;
+
+ // Check if we can unload this dll
+ if (CanUnloadNow(dwDllent) == S_OK)
+ {
+ // remove our apartment from the dll
+ BOOL fRemove = !CleanUpForApartmentByDllent(dwDllent, GetCurrentApartmentId());
+
+ // get the next entry again in case we Released the lock
+ // in the above routine
+ dwNext = _pDllPathEntries[dwDllent]._dwNext;
+
+ if (fRemove)
+ {
+ RemoveAndUnload(dwDllent);
+ FreeDllPathEntry(dwDllent);
+ }
+ }
+ }
+ }
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::RegisterServer
+//
+// Synopsis: Register a class factory
+//
+// Arguments: [rclsid] - class ID
+// [punk] - class factory instance ptr
+// [flags] - type of factory instance
+//
+// Returns: Registration key
+//
+// Algorithm: Create a class entry and then add server to list of
+// registered servers.
+//
+// History: 09-May-93 Ricksa Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+HRESULT CDllCache::RegisterServer(REFCLSID rclsid,
+ IUnknown *punk,
+ DWORD dwFlags,
+ DWORD dwContext,
+ LPDWORD lpdwRegister)
+{
+ CairoleDebugOut((DEB_TRACE, "Register server\n"));
+ TRACECALL(TRACE_DLL, "CDllCache::RegisterServer");
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ // Take a reference immediately (if we fail for any reason we
+ // Release it below)
+ punk->AddRef();
+
+ {
+ // scoped single thread access to the table
+ COleStaticLock lck(_mxs);
+
+ // Allocate a new class entry
+ DWORD dwClsent = AllocClassEntry();
+ if (dwClsent != NONE)
+ {
+ // Formulate a unique registration key for this class entry
+ DWORD dwReg = (GetCurrentApartmentId()) << 16 | dwClsent;
+
+ // Initialize it
+ hr = CreateClsentLSvr(dwClsent,
+ rclsid,
+ punk,
+ dwFlags,
+ dwContext,
+ dwReg);
+
+ if (SUCCEEDED(hr))
+ {
+ *lpdwRegister = dwReg;
+ }
+ else
+ {
+ FreeClassEntry(dwClsent);
+ }
+ }
+ }
+
+ // If we failed we release our reference. This is done outside the
+ // scope of the lock.
+ if (FAILED(hr))
+ {
+ punk->Release();
+ }
+
+ return(hr);
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::Revoke
+//
+// Synopsis: Revoke the registration of a previously registered
+// class object.
+//
+// Arguments: [dwRegister] - registration key
+//
+// Returns: TRUE - remote objects have been deregistered.
+// FALSE - remote objects were not deregistered.
+//
+// Algorithm: First validate the registration key. If objects have
+// been revoked already we will always say TRUE. Then if
+// the object is remote, revoke this list of remote objects.
+// For local objects we just revoke the single entry.
+//
+// Note: dwRegistry has the form aptId << 16 + CClassEntry index
+//
+// History: 09-May-93 Ricksa Created
+// 01-Jul-94 AlexT Don't call out while holding mutex
+// 13-Feb-95 BruceMa Change registration/revocation logic
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+HRESULT CDllCache::Revoke(DWORD dwRegister)
+{
+ IUnknown *pUnk;
+
+ TRACECALL(TRACE_DLL, "CDllCache::Revoke");
+
+ CairoleDebugOut((DEB_TRACE, "Revokeclass object %x\n", dwRegister));
+
+ // Single thread access to the table
+ COleStaticLock lck(_mxs);
+
+ DWORD dwClsent = dwRegister & 0xffff;
+
+
+ // There is case where an app calls CoRevoke from CoDisconnectObject which
+ // we call from Release - so guard against this recursive behavior
+ if (_pClassEntries[dwClsent]._fRevoking)
+ {
+ return S_OK;
+ }
+
+ // Make sure the registration key contains an index to a valid
+ // in use class entry and that the class entry is still valid
+ if (!(0 <= dwClsent &&
+ dwClsent < _cClassEntries &&
+ _pClassEntries[dwClsent]._dwSig == CLASS_CACHE_SIG))
+ {
+ CairoleAssert("CDllCache::Revoke Invalid registration key");
+ return CO_E_OBJNOTREG;
+ }
+
+ // Make sure apartment id's match if we're not free threaded
+ DWORD dwRegAptId = (dwRegister >> 16) & 0xffff; // Chicago has
+ // negative tid's
+ HAPT hCurrApt = GetCurrentApartmentId();
+
+ if (!(dwRegAptId == (hCurrApt & 0xffff) &&
+ hCurrApt == _pClassEntries[dwClsent]._hApt))
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CDllCache::Revoke %x: Wrong thread attempting to revoke\n", dwRegister));
+ return RPC_E_WRONG_THREAD;
+ }
+
+ // If there is an active outgoing call on another thread, then let
+ // that thread do the revoke
+ if (_pClassEntries[dwClsent]._cCallOut > 0)
+ {
+ _pClassEntries[dwClsent]._fRevokePending = TRUE;
+ return S_OK;
+ }
+
+ // Release our reference on the server
+ _pClassEntries[dwClsent]._fRevoking = TRUE;
+ Release(dwClsent);
+
+ // Free the class entry
+ FreeClassEntry(dwClsent);
+
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::AddRefServerProcess
+//
+// Synopsis: increments the reference count on the server process
+//
+// Notes: CoAddRefServerProcess and CoReleaseServerProcess are used
+// by the applications object instances and LockServer
+// implementation in order to control the lifetime of the server
+// process.
+//
+// When a new object instance is created, and when class object's
+// LockServer(TRUE) method is called, applications should call
+// CoAddRefServerProcess. When an object instance's reference
+// count reaches zero, and when the class object's
+// LockServer(FALSE) method is called, applications should call
+// CoReleaseServerProcess.
+//
+// When the server's global reference count reaches zero, all
+// externaly registered class objects are automatically
+// suspended, allowing the server to shutdown in a thread-safe
+// manner.
+//
+// History: 17-Apr-96 Rickhi Created
+//
+//+-------------------------------------------------------------------------
+ULONG CDllCache::AddRefServerProcess(void)
+{
+ COleStaticLock lck(_mxs);
+ return ++_cRefsServerProcess;
+}
+
+ULONG CDllCache::ReleaseServerProcess(void)
+{
+ COleStaticLock lck(_mxs);
+
+ ULONG cRefs = --_cRefsServerProcess;
+ if (cRefs == 0)
+ {
+ HRESULT hr = SuspendProcessClassObjects();
+ Win4Assert(hr == S_OK);
+ }
+ return cRefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::SuspendProcessClassObjects
+//
+// Synopsis: Marks all the externally registered class objects in this
+// process as suspended, so that no new activation requests
+// from the SCM will be honoured.
+//
+// Notes: See AddRefServerProcess and ReleaseServerProcess above.
+//
+// History: 17-Apr-96 Rickhi Created
+//
+//+-------------------------------------------------------------------------
+HRESULT CDllCache::SuspendProcessClassObjects(void)
+{
+ CairoleDebugOut((DEB_ACTIVATE, "SuspendProcessClassObjects\n"));
+ COleStaticLock lck(_mxs);
+
+ // walk the list of class entries, and for any that are registered as
+ // local servers, mark them as suspended.
+
+ for (int k = _nClassEntryInUse; k != NONE; k = _pClassEntries[k]._dwNext)
+ {
+ if (_pClassEntries[k]._dwContext & CLSCTX_LOCAL_SERVER)
+ {
+ _pClassEntries[k]._dwFlags |= REGCLS_SUSPENDED;
+ }
+ }
+
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::ResumeProcessClassObjects
+//
+// Synopsis: Marks all the externally registered class objects in this
+// process as available, so that new activation requests from
+// the SCM will be honoured. This also notifies the SCM about
+// any class objects that have been registered suspended.
+//
+// Notes: See SuspendProcessClassObjects above.
+//
+// History: 17-Apr-96 Rickhi Created
+//
+//+-------------------------------------------------------------------------
+HRESULT CDllCache::ResumeProcessClassObjects(void)
+{
+ CairoleDebugOut((DEB_ACTIVATE, "ResumeProcessClassObjects\n"));
+
+ HRESULT hr = S_OK;
+ COleStaticLock lck(_mxs);
+
+ // if none in use, exit early, otherwise _nClassEntryInUse == -1 and
+ // we try to allocate a huge amount of stack space.
+
+ if (_nClassEntryInUse == NONE)
+ return hr;
+
+ // allocate a block of memory on the stack, large enough to hold the
+ // maximum number of entries we may have to register with the SCM.
+
+ ULONG cbAlloc = sizeof(RegInput) +
+ ((sizeof(RegInputEntry) + sizeof(DWORD))*
+ _nClassEntryInUse);
+
+ RegInput *pRegIn = (RegInput*) _alloca(cbAlloc);
+ RegInputEntry *pRegEnt = &pRegIn->rginent[0];
+ DWORD *pRegIndex = (DWORD *)(&pRegIn->rginent[_nClassEntryInUse+1]);
+ ULONG cToReg = 0;
+
+
+ // walk the list of class entries, and for any that are registered as
+ // local servers and marked suspended, mark them as available and
+ // notify the SCM about them.
+
+ for (int k = _nClassEntryInUse; k != NONE; k = _pClassEntries[k]._dwNext)
+ {
+ if ((_pClassEntries[k]._dwFlags & REGCLS_SUSPENDED) &&
+ (_pClassEntries[k]._dwScmReg == NONE))
+ {
+ // must be for a local server
+ Win4Assert(_pClassEntries[k]._dwContext & CLSCTX_LOCAL_SERVER);
+ Win4Assert(_pClassEntries[k]._pObjServer != NULL);
+
+ // turn off the suspended flag for this clsid.
+ _pClassEntries[k]._dwFlags &= ~REGCLS_SUSPENDED;
+
+ // add to the list to tell the SCM about
+ pRegEnt->clsid = _pClassEntries[k]._clsid;
+ pRegEnt->dwFlags = _pClassEntries[k]._dwFlags;
+ pRegEnt->oxid = _pClassEntries[k]._pObjServer->GetOXID();
+ pRegEnt->ipid = _pClassEntries[k]._pObjServer->GetIPID();
+ pRegEnt++;
+
+ *pRegIndex = k; // remember the index of this entry
+ pRegIndex++; // so we can update it below.
+
+ cToReg++;
+ }
+ }
+
+ // reset the pointers we mucked with in the loop above, and set the
+ // total number of entries we are passing to the SCM.
+
+ pRegIn->dwSize = cToReg;
+ pRegEnt = &pRegIn->rginent[0];
+ pRegIndex = (DWORD *)(&pRegIn->rginent[_nClassEntryInUse+1]);
+
+
+ // call the SCM to register all the classes and get back all the
+ // registration keys.
+
+ RegOutput *pRegOut = NULL;
+ _mxs.Release();
+ hr = gResolver.NotifyStarted(pRegIn, &pRegOut);
+ _mxs.Request();
+
+
+ if (SUCCEEDED(hr))
+ {
+ Win4Assert((pRegOut->dwSize == pRegIn->dwSize) &&
+ "CRpcResolver::NotifyStarted Invalid regout");
+
+ // update the entries with the registration keys from the SCM.
+ for (ULONG i = 0; i < cToReg; i++)
+ {
+ k = *pRegIndex;
+ pRegIndex++;
+
+ _pClassEntries[k]._fAtStorage = pRegOut->regoutent[0].dwAtStorage;
+ _pClassEntries[k]._dwScmReg = pRegOut->regoutent[0].dwReg;
+ }
+
+ // Free memory from RPC
+ MIDL_user_free(pRegOut);
+ }
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDllCache::SetDdeServerWindow
+//
+// Synopsis: Finds the registration associated with dwKey, and sets the
+// HWND for the DDE server.
+//
+// Effects: Part of the shutdown of a class object involves telling the
+// DDE server to stop servicing requests for the class. The
+// communication mechanism used between the DDE server and
+// the Class Registration Table is a window handle.
+//
+// During the initial creation of the DDE server window, we
+// don't know what the window handle is going to be. This
+// routine allows us to set the window handle into the table,
+// so we can be called back.
+//
+// It is also possible that the Server Window may go away
+// before the class object is revoked. This routine is also
+// called in that case to set the hwnd to NULL.
+//
+// Arguments: [dwKey] -- Key for the registration
+// [hwndDdeServer] -- Window handle to Dde Server
+//
+// Returns: TRUE if call was successful.
+// FALSE if the dwKey was not valid.
+//
+// History: 7-05-94 kevinro Created
+// 07-Mar-95 BruceMa Rewrote
+//
+// Notes:
+//
+// This is part of the DDE server support. The code that calls it is
+// in com\remote\dde\server
+//
+//----------------------------------------------------------------------------
+BOOL CDllCache::SetDdeServerWindow(DWORD dwKey, HWND hwndDdeServer)
+{
+ TRACECALL(TRACE_DLL, "CDllCache::SetDdeServer");
+
+ CairoleDebugOut((DEB_TRACE, "Set DDE server window\n"));
+
+ // Single thread access to the table
+ COleStaticLock lck(_mxs);
+
+ Win4Assert(dwKey != 0);
+ Win4Assert((hwndDdeServer == NULL) || IsWindow(hwndDdeServer));
+
+ // Search for the class entry
+ DWORD dwClsent = Search(dwKey, GetCurrentApartmentId());
+
+ // Found it
+ if (dwClsent != NONE)
+ {
+ _pClassEntries[dwClsent]._hWndDdeServer = hwndDdeServer;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::CleanUpLocalServersForApartment
+//
+// Synopsis: Clean up any registered local servers for the current apartment
+//
+// Algorithm: Delete internal objects
+//
+// History: 02-Feb-94 Ricksa Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+void CDllCache::CleanUpLocalServersForApartment(void)
+{
+ // Single thread access to the tables
+ COleStaticLock lck(_mxs);
+
+ // It is possible for the entries to be NULL if CoInitializeEx fails.
+ if (_pClassEntries)
+ {
+ HAPT hApt = GetCurrentApartmentId();
+ DWORD dwNext;
+
+ for (DWORD dwClsent = _nClassEntryInUse; dwClsent != NONE;
+ dwClsent = dwNext)
+ {
+ // Get the next entry in case we release this one
+ dwNext = _pClassEntries[dwClsent]._dwNext;
+
+ // Check whether it's valid and for this apartment
+ // Only release if it was for a local server. If it is for
+ // a Dll it will get released later, either when the Dll
+ // is unloaded or at CoUninitialize
+
+ if (_pClassEntries[dwClsent]._dwSig == CLASS_CACHE_SIG &&
+ _pClassEntries[dwClsent]._hApt == hApt &&
+ _pClassEntries[dwClsent]._dwDllEnt == NONE)
+ {
+ // Let the developer know that they're missing a Revoke
+ CairoleDebugOut((DEB_ERROR,
+ "Missing revoke on pClassFactory=%lx (%I)\n",
+ _pClassEntries[dwClsent]._pUnk,
+ &(_pClassEntries[dwClsent]._clsid)));
+
+ // Release the server
+ Release(dwClsent);
+
+ // In case dwNext got invalidated
+ dwNext = _pClassEntries[dwClsent]._dwNext;
+
+ // Release the class entry
+ FreeClassEntry(dwClsent);
+ }
+ }
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::CleanUpDllsForApartment
+//
+// Synopsis: Clean up any class information for the current apartment
+//
+// Algorithm: Delete internal objects
+//
+// History: 02-Feb-94 Ricksa Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+void CDllCache::CleanUpDllsForApartment(void)
+{
+ // Release all the DLL objects associated with
+ // this apartment
+
+ HAPT hApt = GetCurrentApartmentId();
+
+ // Single thread access to the tables
+ COleStaticLock lck(_mxs);
+
+ if (_pDllPathEntries)
+ {
+ DWORD dwNext;
+ BOOL fMore;
+
+ for (DWORD dwDllent = _nDllPathEntryInUse; dwDllent != NONE;
+ dwDllent = dwNext)
+ {
+ // Save the next entry in case we delete this one
+ dwNext = _pDllPathEntries[dwDllent]._dwNext;
+
+ if (IsValidInApartment(dwDllent, hApt))
+ {
+ // Clean up this entry for this apartment
+ BOOL fRemove = !CleanUpForApartmentByDllent(dwDllent, hApt);
+
+ // In case dwNext got invalidated
+ dwNext = _pDllPathEntries[dwDllent]._dwNext;
+
+ if (fRemove)
+ {
+ HRESULT hr = S_OK;
+ if (!IsWOWProcess())
+ {
+ _mxs.Release();
+ hr = CanUnloadNow(dwDllent);
+ _mxs.Request();
+ }
+
+ if ((hr == S_OK) && (_pDllPathEntries[dwDllent]._nAptInUse == NONE))
+ {
+ // Delete the dll entry if no more apartments are using it
+ // *and* the Dll says it's OK.
+ RemoveAndUnload(dwDllent);
+ FreeDllPathEntry(dwDllent);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::CleanUpDllsForProcess
+//
+// Synopsis: Clean up any remaining cache allocations
+//
+// Algorithm: Delete internal objects
+//
+// History: 02-Feb-94 Ricksa Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+void CDllCache::CleanUpDllsForProcess(void)
+{
+ CairoleDebugOut((DEB_TRACE, "Clean up Dll class cache for process\n"));
+
+ // Single thread
+ COleStaticLock lck(_mxs);
+
+ // In case CoInitialize failed
+ if (_pDllPathEntries)
+ {
+ // Delete the dll path entries. This is explicit because there
+ // are apartment entries to clean up. (Note - this must be done
+ // first because there are class entries associated with a dll.)
+ while (_nDllPathEntryInUse != NONE)
+ {
+ DWORD dwApt;
+
+ for(dwApt = _pDllPathEntries[_nDllPathEntryInUse]._nAptInUse;
+ dwApt != NONE;
+ dwApt = _pDllPathEntries[_nDllPathEntryInUse]._nAptInUse)
+ {
+ CleanUpForApartmentByDllent(_nDllPathEntryInUse,
+ _pDllPathEntries[_nDllPathEntryInUse]._pAptEntries[dwApt]._hApt );
+ }
+ RemoveAndUnload(_nDllPathEntryInUse);
+ FreeDllPathEntry(_nDllPathEntryInUse);
+ }
+ PrivMemFree(_pDllPathEntries);
+ _pDllPathEntries = NULL;
+ }
+
+ _cDllPathEntries = 0;
+ _nDllPathEntryInUse = NONE;
+ _nDllPathEntryAvail = NONE;
+
+
+ // Now free the class entries.
+ if (_pClassEntries)
+ {
+ // Delete the class entries
+ PrivMemFree(_pClassEntries);
+ _pClassEntries = NULL;
+ }
+
+ _cClassEntries = 0;
+ _nClassEntryInUse = NONE;
+ _nClassEntryAvail = NONE;
+
+ CleanupTreatAs();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::Search
+//
+// Synopsis: Search for a class entry by clsid and specific context
+// and specific apartment
+//
+// Algorithm:
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DWORD CDllCache::Search(REFCLSID clsid, DWORD dwContext, HAPT hApt)
+{
+ // Search
+ for (int k = _nClassEntryInUse; k != NONE; k = _pClassEntries[k]._dwNext)
+ {
+ if (IsEqualCLSID(clsid, _pClassEntries[k]._clsid) &&
+ (_pClassEntries[k]._dwContext & dwContext) &&
+ !((dwContext & CLSCTX_INPROC_SERVER) &&
+ (_pClassEntries[k]._dwFlags & REGCLS_SURROGATE)) &&
+ (_pClassEntries[k]._hApt == hApt))
+ {
+ return k;
+ }
+ }
+
+ return NONE;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::Search
+//
+// Synopsis: Search for a class entry by registration key
+//
+// Algorithm:
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DWORD CDllCache::Search(DWORD dwRegKey, HAPT hApt)
+{
+ // Search
+ for (int k = _nClassEntryInUse; k != NONE; k = _pClassEntries[k]._dwNext)
+ {
+ if (dwRegKey == _pClassEntries[k]._dwReg &&
+ hApt == _pClassEntries[k]._hApt)
+ {
+ return k;
+ }
+ }
+
+ return NONE;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::SearchForDll
+//
+// Synopsis: Search for a dll path entry
+//
+// Algorithm: Upper case and compute a hash. Then search by the hash
+// value and by the pathname only if the hash matches.
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DWORD CDllCache::SearchForDll(const TCHAR *ptszDllPath
+#ifdef WX86OLE
+ , BOOL fWx86
+#endif
+)
+{
+ TCHAR tszPath[MAX_PATH];
+ LPTSTR ptszPath = tszPath;
+ DWORD cCh = lstrlen(ptszDllPath);
+ DWORD dwHash;
+ BOOL fFreePath = FALSE;
+#ifdef WX86OLE
+ BOOL fWx86Dll;
+#endif
+
+ // Compute a hash value for the search path
+ if (cCh > MAX_PATH - 1)
+ {
+ ptszPath = (LPTSTR) PrivMemAlloc((cCh + 1) * sizeof(TCHAR));
+ if (ptszPath == NULL)
+ {
+ return NONE;
+ }
+ fFreePath = TRUE;
+ }
+ lstrcpy(ptszPath, ptszDllPath);
+ CharUpper(ptszPath);
+ dwHash = Hash(ptszPath);
+
+ // Search
+ for (int k = _nDllPathEntryInUse; k != NONE;
+ k = _pDllPathEntries[k]._dwNext)
+ {
+#ifdef WX86OLE
+ fWx86Dll = _pDllPathEntries[k]._dwFlags & WX86_LOADASX86;
+#endif
+ if (_pDllPathEntries[k]._dwHash == dwHash &&
+ _pDllPathEntries[k]._dwSig == DLL_PATH_CACHE_SIG
+#ifdef WX86OLE
+ // We also must match the dll type (x86 or risc)
+ && ((fWx86 && fWx86Dll) || (! fWx86 && ! fWx86Dll))
+#endif
+ )
+ {
+ if (lstrcmp(_pDllPathEntries[k]._ptszPath, ptszPath) == 0)
+ {
+ if (fFreePath)
+ {
+ PrivMemFree(ptszPath);
+ }
+ return k;
+ }
+ }
+ }
+
+ if (fFreePath)
+ {
+ PrivMemFree(ptszPath);
+ }
+
+ return NONE;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::AllocClassEntry
+//
+// Synopsis: Allocate a new class entry
+//
+// Algorithm:
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DWORD CDllCache::AllocClassEntry(void)
+{
+ // If we don't have any available entries, then expand the array
+ if (_nClassEntryAvail == NONE)
+ {
+ // Allocate a new array
+ SClassEntry *p = (SClassEntry *) PrivMemAlloc(sizeof(SClassEntry) *
+ (_cClassEntries + NOMINAL_CACHE_SIZE));
+ if (p == NULL)
+ {
+ return NONE;
+ }
+
+ // Initialize it and free the old one.
+ memcpy(p, _pClassEntries, _cClassEntries * sizeof(SClassEntry));
+
+ PrivMemFree(_pClassEntries);
+ _pClassEntries = p;
+
+ for (DWORD k = _cClassEntries;
+ k < _cClassEntries + NOMINAL_CACHE_SIZE;
+ k++)
+ {
+ InitClsent(k, k == _cClassEntries + NOMINAL_CACHE_SIZE - 1 ? NONE
+ : k + 1 );
+ }
+ _nClassEntryAvail = _cClassEntries;
+ _cClassEntries += NOMINAL_CACHE_SIZE;
+ }
+
+ // Init and return the next available entry
+ DWORD dwClsent = _nClassEntryAvail;
+ _pClassEntries[dwClsent]._dwSig = CLASS_CACHE_SIG;
+
+ _nClassEntryAvail = _pClassEntries[dwClsent]._dwNext;
+ _pClassEntries[dwClsent]._dwNext = _nClassEntryInUse;
+ Win4Assert((_pClassEntries[dwClsent]._dwNext == NONE ||
+ _pClassEntries[dwClsent]._dwNext < _cClassEntries)
+ && "Bad class entry index");
+ _nClassEntryInUse = dwClsent;
+ return dwClsent;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::AllocDllPathEntry
+//
+// Synopsis: Allocate a new dll path entry
+//
+// Algorithm:
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DWORD CDllCache::AllocDllPathEntry(void)
+{
+ // If we don't have any available entries, then expand the array
+ if (_nDllPathEntryAvail == NONE)
+ {
+ // Allocate a new array
+ SDllPathEntry *p = (SDllPathEntry *) PrivMemAlloc(
+ sizeof(SDllPathEntry) * (_cDllPathEntries + NOMINAL_CACHE_SIZE));
+ if (p == NULL)
+ {
+ return NONE;
+ }
+
+ // Initialize it and free the old one.
+ memcpy(p, _pDllPathEntries, _cDllPathEntries * sizeof(SDllPathEntry));
+
+ PrivMemFree(_pDllPathEntries);
+ _pDllPathEntries = p;
+
+ for (DWORD k = _cDllPathEntries;
+ k < _cDllPathEntries + NOMINAL_CACHE_SIZE;
+ k++)
+ {
+ InitDllent(k, k == _cDllPathEntries + NOMINAL_CACHE_SIZE - 1 ? NONE
+ : k + 1 );
+ }
+ _nDllPathEntryAvail = _cDllPathEntries;
+ _cDllPathEntries += NOMINAL_CACHE_SIZE;
+ }
+
+ // Init and return the next available entry
+ DWORD dwDllent = _nDllPathEntryAvail;
+ _pDllPathEntries[dwDllent]._dwSig = DLL_PATH_CACHE_SIG;
+
+ // Allocate and initialize apartment entries
+ if (!NewAptEntries(dwDllent))
+ {
+ return NONE;
+ }
+
+ _nDllPathEntryAvail = _pDllPathEntries[dwDllent]._dwNext;
+ _pDllPathEntries[dwDllent]._dwNext = _nDllPathEntryInUse;
+ _nDllPathEntryInUse =dwDllent;
+ return dwDllent;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::FreeClassEntry
+//
+// Synopsis: Free a class entry - i.e., make it available
+//
+// Algorithm:
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void CDllCache::FreeClassEntry(DWORD dwClsent)
+{
+ DWORD dwPrevCls;
+ BOOL fBreak = FALSE;
+
+ // Saftey check
+ if (_pClassEntries[dwClsent]._dwSig != CLASS_CACHE_SIG)
+ {
+ return;
+ }
+
+ // First check whether it is on a list of class entries for a given dll
+ // - if so, unthread it
+ for (DWORD dwDllent = _nDllPathEntryInUse;
+ dwDllent != NONE;
+ dwDllent = _pDllPathEntries[dwDllent]._dwNext)
+ {
+ for (DWORD dwNextCls = _pDllPathEntries[dwDllent]._dw1stClass;
+ dwNextCls != NONE;
+ dwPrevCls = dwNextCls,
+ dwNextCls = _pClassEntries[dwNextCls]._dwNextDllCls)
+ {
+ if (dwNextCls == dwClsent)
+ {
+ // It's at the head of the list
+ if (dwNextCls == _pDllPathEntries[dwDllent]._dw1stClass)
+ {
+ _pDllPathEntries[dwDllent]._dw1stClass =
+ _pClassEntries[dwNextCls]._dwNextDllCls;
+ }
+
+ // Else it's in the list
+ else
+ {
+ _pClassEntries[dwPrevCls]._dwNextDllCls =
+ _pClassEntries[dwNextCls]._dwNextDllCls;
+ }
+ fBreak = TRUE;
+ break;
+ }
+ }
+ if (fBreak)
+ {
+ break;
+ }
+ }
+
+
+ // Then remove it from the list of in-use entries
+ // It's at the head of the list
+ if (_nClassEntryInUse == dwClsent)
+ {
+ _nClassEntryInUse = _pClassEntries[dwClsent]._dwNext;
+ Win4Assert((_nClassEntryInUse == NONE ||
+ _nClassEntryInUse < _cClassEntries) && "Bad class entry index");
+ }
+
+ // Otherwise search for the entry that points to the one we're releasing
+ else
+ {
+ for (DWORD dwPrev = _nClassEntryInUse;
+ _pClassEntries[dwPrev]._dwNext != dwClsent;
+ dwPrev = _pClassEntries[dwPrev]._dwNext)
+ {
+ }
+ _pClassEntries[dwPrev]._dwNext = _pClassEntries[dwClsent]._dwNext;
+ }
+
+ // Relink into the list of available entries
+ _pClassEntries[dwClsent]._dwNext = _nClassEntryAvail;
+ _nClassEntryAvail = dwClsent;
+ InitClsent(dwClsent, _pClassEntries[dwClsent]._dwNext);
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::FreeDllPathEntry
+//
+// Synopsis: Free a dll path entry - i.e., make it available
+//
+// Algorithm:
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void CDllCache::FreeDllPathEntry(DWORD dwDllent)
+{
+ ComDebOut((DEB_TRACE, "FreeDllPathEntry dwDll:%x\n", dwDllent));
+
+ // It's at the head of the list
+ if (_nDllPathEntryInUse == dwDllent)
+ {
+ _nDllPathEntryInUse = _pDllPathEntries[dwDllent]._dwNext;
+ }
+
+ // Otherwise search for the entry that points to the one we're releasing
+ else
+ {
+ for (DWORD dwPrev = _nDllPathEntryInUse;
+ _pDllPathEntries[dwPrev]._dwNext != dwDllent;
+ dwPrev = _pDllPathEntries[dwPrev]._dwNext)
+ {
+ }
+ _pDllPathEntries[dwPrev]._dwNext = _pDllPathEntries[dwDllent]._dwNext;
+ }
+
+ // Relink into the list of available entries
+ _pDllPathEntries[dwDllent]._dwNext = _nDllPathEntryAvail;
+ _nDllPathEntryAvail = dwDllent;
+
+ // Delete the array of apartment entries
+ if (_pDllPathEntries[dwDllent]._pAptEntries)
+ {
+ delete _pDllPathEntries[dwDllent]._pAptEntries;
+ }
+
+ // Now reinitialize this dll path entry
+ InitDllent(dwDllent, _pDllPathEntries[dwDllent]._dwNext);
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllCache::Hash
+//
+// Synopsis: Compute a hash value for a pathname
+//
+// Algorithm:
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DWORD CDllCache::Hash(LPTSTR ptszPath)
+{
+ DWORD dwHash = 0;
+
+ for (DWORD k = 0; ptszPath[k]; k++)
+ {
+ dwHash *= 3;
+ dwHash ^= ptszPath[k];
+ }
+ return dwHash;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CleanUpDllsForProcess
+//
+// Synopsis: Free all cached Dll class object information for this process
+//
+// Algorithm: Tell class caches to free themselves
+//
+// History: 02-Feb-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+void CleanUpDllsForProcess(void)
+{
+ // Clean up server cache
+ gdllcacheInprocSrv.CleanUpDllsForProcess();
+
+ // Clean up handler cache
+ gdllcacheHandler.CleanUpDllsForProcess();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CleanUpDllsForApartment
+//
+// Synopsis: Free all cached class object information for this Apartment.
+//
+// Algorithm: Tell class caches to cleanup the current apartment
+//
+// History: 26-Jun-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+void CleanUpDllsForApartment(void)
+{
+ // Clean up server cache
+ gdllcacheInprocSrv.CleanUpDllsForApartment();
+
+ // Clean up handler cache
+ gdllcacheHandler.CleanUpDllsForApartment();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CleanUpLocalServersForApartment
+//
+// Synopsis: Free all cached LocalServer class objects for this Apartment.
+//
+// Algorithm: Tell class caches to cleanup the current apartment
+//
+// History: 18-Dec-95 Rickhi Created
+//
+//--------------------------------------------------------------------------
+void CleanUpLocalServersForApartment(void)
+{
+ // Clean up server cache
+ gdllcacheInprocSrv.CleanUpLocalServersForApartment();
+
+ // dont need to call on gdllcacheHandler since local servers are never
+ // stored in that cache.
+}
+
+
+
+#ifdef _CHICAGO_
+//+-------------------------------------------------------------------------
+//
+// Function: GetAptForCLSID
+//
+// Synopsis: Get the ApartmentId for a given class
+//
+// Algorithm: search the cache of registrations for an available class
+// object of the given class, and return its apartment id.
+//
+// Returns: HAPT - if found (thread id is member)
+// haptNULL - if not
+//
+// History: 30-Apr-94 JohannP Created
+// 06-Oct-95 BruceMa Make for Chicago only
+//
+//--------------------------------------------------------------------------
+HAPT GetAptForCLSID(const GUID *pclsid)
+{
+ HAPT hApt;
+ if (gdllcacheInprocSrv.GetApartmentForCLSID(*pclsid, hApt))
+ {
+ return hApt;
+ }
+ else
+ {
+ return haptNULL;
+ }
+}
+#endif // _CHICAGO_
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetClassInformationForDde
+//
+// Synopsis: Get class object information for the Dde server
+//
+// Effects:
+//
+// Arguments: [clsid] -- ClassID to search for
+// [lpDdeInfo] -- Structure to fill in with information
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL GetClassInformationForDde( REFCLSID clsid,
+ LPDDECLASSINFO lpDdeInfo)
+{
+ return gdllcacheInprocSrv.GetClassObjForDde(clsid,lpDdeInfo);
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetClassInformationFromKey
+//
+// Synopsis: Get class object information for the Dde server using a key
+//
+// Arguments: [lpDdeInfo] -- Structure to fill in with information
+//
+// Requires: lpDdeInfo->dwRegistrationKey is the key to the specific
+// class being asked for.
+//
+// Returns: TRUE - Structure filled in with appropriate information
+// FALSE - The registration is no longer valid.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-28-94 kevinro Created
+//
+// Notes:
+//
+// See CDllCache::GetClassInformationFromKey
+//
+//----------------------------------------------------------------------------
+BOOL GetClassInformationFromKey(LPDDECLASSINFO lpDdeInfo)
+{
+ return gdllcacheInprocSrv.GetClassInformationFromKey(lpDdeInfo);
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetDdeServerWindow
+//
+// Synopsis: Finds the registration associated with dwKey, and sets the
+// HWND for the DDE server.
+//
+// Effects: See CDllCache::SetDdeServerWindow for details
+//
+// Arguments: [dwKey] -- Key for the registration
+// [hwndDdeServer] -- Window handle to Dde Server
+//
+// Returns: TRUE if call was successful.
+// FALSE if the dwKey was not valid.
+//
+// History: 7-05-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL SetDdeServerWindow( DWORD dwKey, HWND hwndDdeServer)
+{
+
+ TRACECALL(TRACE_DLL, "SetDdeServerWindow");
+ return gdllcacheInprocSrv.SetDdeServerWindow(dwKey, hwndDdeServer);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleMainThreadWndProc
+//
+// Synopsis: Window proc for handling messages to the main thread
+//
+// Arguments: [hWnd] - window the message is on
+// [message] - message the window receives
+// [wParam] - first message parameter
+// [lParam] - second message parameter.
+//
+// Returns: Depends on the message
+//
+// Algorithm: If the message is one a user message that we have defined,
+// dispatch it. Otherwise, send any other message to the
+// default window proc.
+//
+// History: 22-Nov-94 Ricksa Created
+//
+//----------------------------------------------------------------------------
+LRESULT OleMainThreadWndProc(
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch(message)
+ {
+ case WM_OLE_GETCLASS:
+ // get the host interface for single-threaded dlls
+ return GetSingleThreadedHost(lParam);
+
+#ifdef _CHICAGO_
+ case WM_OLE_ORPC_NOTIFY:
+ // got the initialization message
+ OleNotificationProc(message, wParam, lParam);
+ return 0;
+
+#endif // _CHICAGO_
+
+#ifndef _CHICAGO_
+ // Check whether it is UninitMainThreadWnd or system shutdown that
+ // is destroying the window. Only actually do the destroy if it is us.
+ //
+ // BUGBUG: Chicago hit this but the debugger was unable to tell
+ // us who we were called by....so for now i just removed it.
+ case WM_DESTROY:
+ case WM_CLOSE:
+ if (gfDestroyingMainWindow == FALSE)
+ {
+ // Not in UninitMainThreadWnd so just ignore this message. Do not
+ // dispatch it.
+ ComDebOut((DEB_WARN, "Attempted to destroy Window outside of UninitMainThreadWnd"));
+ return 0;
+ }
+ // else fallthru
+#endif // _CHICAGO_
+ }
+
+ // We don't process the message so pass it on to the default
+ // window proc.
+ return SSDefWindowProc(hWnd, message, wParam, lParam);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: InitMainThreadWnd
+//
+// Synopsis: Do initialization necessary for main window processing.
+//
+// Returns: TRUE - we got initialized
+// FALSE - initialization failed.
+//
+// Algorithm: First register out window class. Then create our main thread
+// window. Finally, save the id of the main thread.
+//
+// History: 22-Nov-94 Ricksa Created
+// 24-Mar-95 JohannP Added notify mechanismen
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL InitMainThreadWnd(void)
+{
+ ComDebOut((DEB_ENDPNT, "InitMainThreadWnd on %x\n", GetCurrentThreadId()));
+ Win4Assert(IsSTAThread());
+
+#ifdef _CHICAGO_
+ if (IsWOWProcess())
+ {
+ // Chicago WOW requires a different class per thread.
+ wsprintfA(ptszOleMainThreadWndClass,"OleMainThreadWndClass %08X",
+ CoGetCurrentProcess());
+ }
+#endif // _CHICAGO_
+
+ BOOL fRetVal = TRUE;
+
+ // Register windows class.
+ WNDCLASST xClass;
+ xClass.style = 0;
+ xClass.lpfnWndProc = OleMainThreadWndProc;
+ xClass.cbClsExtra = 0;
+
+ // DDE needs some extra space in the window
+ xClass.cbWndExtra = sizeof(LPVOID) + sizeof(ULONG) + sizeof(HANDLE);
+ xClass.hInstance = g_hinst;
+ xClass.hIcon = NULL;
+ xClass.hCursor = NULL;
+ xClass.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
+ xClass.lpszMenuName = NULL;
+ xClass.lpszClassName = ptszOleMainThreadWndClass;
+
+ gOleWindowClass = (LPTSTR) RegisterClassT( &xClass );
+ if (gOleWindowClass == 0)
+ {
+ // it is possible the dll got unloaded without us having called
+ // unregister so we call it here and try again.
+
+ UnregisterClassT(ptszOleMainThreadWndClass, g_hinst);
+ gOleWindowClass = (LPTSTR) RegisterClassT(&xClass);
+
+ if (gOleWindowClass == 0)
+ {
+ ComDebOut((DEB_ERROR, "RegisterClass failed in InitMainThreadWnd\n"));
+ fRetVal = FALSE;
+ }
+ }
+
+ // Remember the main thread
+ gdwMainThreadId = GetCurrentThreadId();
+
+ if (!IsWOWProcess() && fRetVal)
+ {
+ // this window is only needed for the non WOW case since
+ // WOW is not a real apartment case
+ // Create a main window for this application instance.
+
+ hwndOleMainThread = DllCreateWindowEx(
+ 0,
+ gOleWindowClass,
+ ptszOleMainThreadWndName,
+ // must use WS_POPUP so the window does not get assigned
+ // a hot key by user.
+ (WS_DISABLED | WS_POPUP),
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ NULL,
+ NULL,
+ g_hinst,
+ NULL);
+
+ Win4Assert(hwndOleMainThread && "Register Window on OleWindowClass failed \n");
+ if (!hwndOleMainThread)
+ {
+ // We did not get a window so we can not report success.
+ // Cleanup the registered window class and gdwMainThreadId.
+ UninitMainThreadWnd();
+ fRetVal = FALSE;
+ }
+ }
+
+ ComDebOut((DEB_ENDPNT, "InitMainThreadWnd done on %x\n", gdwMainThreadId));
+ return fRetVal;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: UninitMainThreadWnd
+//
+// Synopsis: Free resources used by main window processing.
+//
+// Algorithm: Destroy the window and then unregister the window class.
+//
+// History: 22-Nov-94 Ricksa Created
+// 24-Mar-95 JohannP Added notify mechanismen
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void UninitMainThreadWnd(void)
+{
+ ComDebOut((DEB_ENDPNT, "UninitMainThreadWnd on %x\n", gdwMainThreadId));
+ Win4Assert(IsSTAThread());
+
+ if (gdwMainThreadId)
+ {
+ BOOL fRet = FALSE;
+
+#ifdef _CHICAGO_
+ // destroy the notification window if it still exist
+ COleTls tls;
+ if (tls->hwndOleRpcNotify != NULL)
+ {
+ ComDebOut((DEB_ENDPNT,"Destroying NotifyThreadWnd %x\n", tls->hwndOleRpcNotify));
+ fRet = SSDestroyWindow(tls->hwndOleRpcNotify);
+ Win4Assert(fRet && "Destroy Window failed on NotifyThreadWnd\n");
+ tls->hwndOleRpcNotify = NULL;
+ }
+#endif // _CHICAGO_
+
+ // Destroy the window
+ if (!IsWOWProcess() && IsWindow(hwndOleMainThread))
+ {
+ // flag here is to indicate that we are destroying the window.
+ // as opposed to the system shutdown closing the window. the
+ // flag is looked at in dcomrem\chancont\ThreadWndProc.
+ gfDestroyingMainWindow = TRUE;
+ SSDestroyWindow(hwndOleMainThread);
+ gfDestroyingMainWindow = FALSE;
+ hwndOleMainThread = NULL;
+ }
+
+ // Unregister the window class
+ if (UnregisterClassT(ptszOleMainThreadWndClass, g_hinst) == FALSE)
+ {
+ ComDebOut((DEB_ERROR,"Unregister Class failed on OleMainThreadWndClass %ws because %d\n", ptszOleMainThreadWndClass, GetLastError()));
+ }
+
+ gdwMainThreadId = 0;
+ }
+
+ ComDebOut((DEB_ENDPNT,"UninitMainThreadWnd done on %x\n", gdwMainThreadId));
+ return;
+}
diff --git a/private/ole32/com/objact/dllcache.hxx b/private/ole32/com/objact/dllcache.hxx
new file mode 100644
index 000000000..003afde10
--- /dev/null
+++ b/private/ole32/com/objact/dllcache.hxx
@@ -0,0 +1,418 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: dllcache.hxx
+//
+// Contents: Classes which implement cache of class Dlls previously
+// located and local server class registrations.
+//
+// Classes: CDllCache
+// CDllAptEntry
+//
+// Structures: SClassntry
+// SDllPathEntry
+//
+// Functions:
+//
+// History: 09-May-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+// 24-Jun-94 Rickhi Add Apartment Crap
+// 13-Feb-95 BruceMa Change class object registration so
+// volatile addresses are not used
+// 07-Mar-95 BruceMa Rewrote
+//
+// Notes: The dll/class cache was rewritten to simplify and to improve
+// performance. Since only a few entries (max ~16) are expected,
+// linear search is deemed sufficient. The inclinaton then is to
+// store entries on a linked list. However, since the cache is
+// visited infrequently there is a good chance that it will have
+// been paged out. So, instead of a linked list of different
+// allocations which may touch many pages, the entries are
+// stored in an array occupying a single area of memory. There
+// are two arrays, one storing dll paths, etc. and one for
+// class registrations. These arrays are initialized small and
+// dynamically expanded as needed. Also, the CDllAptEntry
+// was eliminated for the same reason. Instead, threadId's
+// associated with a dll are stored in the CDllPathEntry to
+// nominally 16, and thereafter it is dynamically expanded.
+//
+// SDllPathEntry and SClassEntry were originally implemented as
+// classes but were made structures and their management was
+// moved to the CDllCache level, since during an outgoing call
+// it is possible that another thread may come in causing the
+// cache to get reallocated and moved. This would invalidate
+// any internal 'this' pointers. Because of the WOW we can't
+// hold a mutex across outgoing calls. Therefore class entries
+// and dll path entries are managed from the top level via
+// indices.
+//
+//--------------------------------------------------------------------------
+#ifndef __DLLCACHE_HXX__
+#define __DLLCACHE_HXX__
+
+#include <olesem.hxx>
+
+const UINT NOMINAL_CACHE_SIZE = 8;
+const UINT NOMINAL_NUMBER_THREADS = 16;
+
+const DWORD CLASS_CACHE_SIG = 0x53534c43;
+const DWORD DLL_PATH_CACHE_SIG = 0x534c4c44;
+const DWORD DLL_APT_CACHE_SIG = 0x53545041;
+
+#define DLL_GET_CLASS_OBJECT_EP "DllGetClassObject"
+#define DLL_CAN_UNLOAD_EP "DllCanUnloadNow"
+
+const DWORD NONE = ~0UL;
+
+// Flags
+#define SIXTEEN_BIT 0x00000001
+#define IS_OLE32 0x00000002
+#ifdef WX86OLE
+#define WX86_THUNK 0x00000004
+#define WX86_LOADASX86 0x00000008
+#endif
+#define DELAYED_UNLOAD 0x00000010 // delay unloading this DLL
+
+#define DLL_DELAY_UNLOAD_TIME 600000 // 600,000 ticks == 10 minutes
+
+
+// Typedef for pointer to DllCanUnloadNow function
+typedef HRESULT (*DLLUNLOADFNP)(void);
+
+
+class CDllCache;
+class CObjServer;
+
+
+//+-------------------------------------------------------------------------
+//
+// Structure: SClassEntry
+//
+// Purpose: Provides cached information for a class object
+//
+// History: 09-May-93 Ricksa Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+struct SClassEntry
+{
+ DWORD _dwNext; // Next entry in in-use or avail list
+ DWORD _dwSig; // Marks entry as in use
+ CLSID _clsid; // Class of this server
+ IUnknown *_pUnk; // Class factory IUnknown
+ DWORD _dwContext; // Class context
+ DWORD _dwFlags; // Single vs. multiple use
+ DWORD _dwReg; // Registration key for caaller
+ DWORD _dwScmReg; // Registration ID at the SCM
+ HAPT _hApt; // Thread Id
+ DWORD _cCallOut; // Count of active call outs
+ ULONG _fRevokePending:1; // Whether revoked while calling out
+ ULONG _fRevoking:1; // Prevents recursive revoking
+ ULONG _fReleasing:1; // Prevents recursive releasing
+ DWORD _dwDllThreadModel; // Threading model for the DLL
+ DWORD _fAtStorage; // Whether server is an at bits server
+ DWORD _dwDllEnt; // Associated dll path entry
+ DWORD _dwNextDllCls; // Next class entrry for this dll
+ HWND _hWndDdeServer; // Handle of associated DDE window
+ CObjServer *_pObjServer; // object server interface
+};
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDllAptEntry
+//
+// Purpose: Abstracts per apartment info for a Dll.
+//
+// Interface: Init - loads the Dll and retrieves the entry points
+// IsValidInApartment - TRUE if data valid for given apartment
+//
+// History: 27-Jun-94 Rickhi Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+class CDllAptEntry
+{
+public:
+
+ void Init(DWORD j);
+
+ void Create(HAPT hApt);
+
+private:
+
+ DWORD _dwNext; // Next entry in avail or in use list
+ DWORD _dwSig; // Unique signature for apt entries
+ HAPT _hApt; // apartment id
+ HMODULE _hDll; // module handle
+
+ friend class CDllCache;
+};
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Structure: SDllPathEntry
+//
+// Purpose: Represents a DLL.
+//
+// Interface: Init - Complete initialization
+// MakeValidInApartment - make Dll valid for current apartment
+// GetClassInterface - Gets DLL to return the class factory
+// CanUnloadNow - Asks DLL if it can unload
+// AddClass - Adds class object to list of classes
+// served by DLL
+// CleanUpForApartment - cleanup per apartment entries
+//
+// History: 09-May-93 Ricksa Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+struct SDllPathEntry
+{
+ DWORD _dwNext; // Next in-use/avail entry
+ DWORD _dwSig; // Unique signature for safty
+ LPTSTR _ptszPath; // The dll pathname
+ DWORD _dwHash; // Hash value for searching
+ LPFNGETCLASSOBJECT _pfnGetClassObject; // Create object entry point
+ DLLUNLOADFNP _pfnDllCanUnload; // DllCanUnloadNow entry point
+ DWORD _dwFlags; // Internal flags
+ DWORD _dw1stClass; // First class entry for dll
+ DWORD _cUsing; // Count of using threads
+ DWORD _cAptEntries; // Total apt entries
+ DWORD _nAptAvail; // List of available apt entries
+ DWORD _nAptInUse; // List of in use apt entries
+ CDllAptEntry *_pAptEntries; // Per thread info
+ HMODULE _hDll32; // Module handle if this is a 32 bit dll
+ DWORD _dwExpireTime; // Time until safe to unload dll
+};
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDllCache
+//
+// Purpose: Provide unified access to the cached class/dll information
+//
+// Interface: GetClass - Get a class factory for a class
+// Add - Add a DLL and class
+// FreeUnused - Free DLLs which are not being used
+// RegisterServer - Add a server object to the registration
+// Revoke - Revoke a server object
+//
+// Notes: This class *must* be allocated statically, since it includes
+// a COleStaticMutexSem.
+//
+// History: 09-May-93 Ricksa Created
+// 07-Mar-95 BruceMa Rewrote
+//
+//--------------------------------------------------------------------------
+class CDllCache
+{
+public:
+
+ // Top level methods
+
+ CDllCache(void);
+
+ IUnknown *GetClassInterface(DWORD dwDll,
+ DWORD dwDllThreadModel,
+ REFCLSID rclsid,
+ REFIID riid,
+ HRESULT& hr);
+
+ HRESULT CanUnloadNow(DWORD dwDll);
+
+ void RemoveAndUnload(DWORD dwDll);
+
+ BOOL Init(void);
+
+ // Get a class factory interface for a class
+ HRESULT GetClass(REFCLSID rclsid,
+ REFIID riid,
+ BOOL fRemote,
+ BOOL fForSCM,
+ BOOL fForSurrogate,
+#ifdef WX86OLE
+ BOOL fWx86,
+#endif
+ IUnknown **ppunk
+);
+
+ IUnknown *GetOrLoadClass(REFCLSID rclsid,
+ REFIID riid,
+ BOOL fRemote,
+ BOOL fForSCM,
+#ifdef WX86OLE
+ BOOL fWx86,
+#endif
+ DWORD dwContext,
+ DWORD dwThreadingType,
+ HRESULT &hr);
+
+ BOOL GetClassObjForDde(REFCLSID clsid,
+ LPDDECLASSINFO lpDdeInfo);
+
+ BOOL GetClassInformationFromKey(LPDDECLASSINFO lpDdeInfo);
+
+
+#ifdef _CHICAGO_
+ BOOL GetApartmentForCLSID(REFCLSID rclsid, HAPT &hApt);
+#endif
+
+ // Add a new entry to the class/dll cache and
+ // get a class factory if requested.
+ IUnknown * Add(REFCLSID rclsid,
+ REFIID riid,
+ DWORD dwDllThreadModel,
+ const TCHAR *ptszDllPath,
+ BOOL fGetClassObject,
+ BOOL fSixteenBit,
+#ifdef WX86OLE
+ BOOL fWx86,
+#endif
+ HRESULT& hr);
+
+ void FreeUnused(void);
+
+ HRESULT RegisterServer(REFCLSID rclsid,
+ IUnknown *punk,
+ DWORD flags,
+ DWORD dwTypeToRegister,
+ LPDWORD lpdwRegister);
+
+ HRESULT Revoke(DWORD pdwRegister);
+
+ BOOL SetDdeServerWindow(DWORD dwKey,
+ HWND hwndDdeServer);
+
+ void CleanUpDllsForApartment(void);
+ void CleanUpLocalServersForApartment(void);
+ void CleanUpDllsForProcess(void);
+
+ ULONG AddRefServerProcess(void);
+ ULONG ReleaseServerProcess(void);
+ HRESULT SuspendProcessClassObjects(void);
+ HRESULT ResumeProcessClassObjects(void);
+
+private:
+
+#ifdef WX86OLE
+ HRESULT Load(LPCTSTR pwszPath,
+ LPFNGETCLASSOBJECT *ppfnGetClassObject,
+ DLLUNLOADFNP *ppfnDllCanUnload,
+ BOOL fSixteenBit,
+ HMODULE *hDll,
+ BOOL *pIsX86Dll,
+ BOOL fLoadAsX86);
+#else
+ HRESULT Load(LPCTSTR pwszPath,
+ LPFNGETCLASSOBJECT *ppfnGetClassObject,
+ DLLUNLOADFNP *ppfnDllCanUnload,
+ BOOL fSixteenBit,
+ HMODULE *hDll);
+#endif
+
+ void InitClsent(DWORD dwCls, DWORD k);
+
+ HRESULT CreateClsentLSvr(DWORD dwCls,
+ REFCLSID rclsid,
+ IUnknown *punk,
+ DWORD dwFlags,
+ DWORD dwContext,
+ DWORD dwReg);
+
+ HRESULT CreateClsentInProc(DWORD dwCls,
+ DWORD dwDll,
+ DWORD dwDllThreadModel,
+ DWORD dwNextDllCls,
+ REFCLSID rclsid
+#ifdef WX86OLE
+ ,BOOL fWx86
+#endif
+);
+
+ BOOL GetClassObjForDdeByClsent(DWORD dwCls,
+ LPDDECLASSINFO lpDdeClassInfo);
+
+ HRESULT Release(DWORD dwCls);
+
+ void InitDllent(DWORD dwDll, DWORD k);
+
+ HRESULT CreateDllent(DWORD dwDll,
+ LPCTSTR ptszDllPath,
+ BOOL fSixteenBit,
+ LPFNGETCLASSOBJECT pfnGetClassObject,
+ DLLUNLOADFNP pfnDllCanUnload,
+ HMODULE hDll
+#ifdef WX86OLE
+ ,BOOL fIsX86Dll,
+ BOOL fLoadAsX86
+#endif
+);
+
+ BOOL NewAptEntries(DWORD dwDll);
+
+ DWORD AllocAptEntry(DWORD dwDll);
+
+ void FreeAptEntry(DWORD dwDll, DWORD dwAptent);
+
+ HRESULT MakeValidInApartment(DWORD dwDll);
+
+ BOOL CleanUpForApartmentByDllent(DWORD dwDll, HAPT hApt);
+
+ // Search for a class entry by registration key
+ DWORD Search(DWORD dwRegkey, HAPT hApt);
+
+ // Search for a class entry for specific apartment
+ DWORD Search(REFCLSID clsid, DWORD dwContext, HAPT hApt);
+
+ // Search for a dll path entry
+ DWORD SearchForDll(const _TCHAR *ptszDllPath
+#ifdef WX86OLE
+ , BOOL fWx86
+#endif
+);
+
+ // Allocate/free class and dll entries
+ DWORD AllocClassEntry(void);
+ DWORD AllocDllPathEntry(void);
+ void FreeClassEntry(DWORD dwClsent);
+ void FreeDllPathEntry(DWORD dwDllent);
+
+ // For dll path entries
+ BOOL IsValidInApartment(DWORD dwDllent, HAPT hApt);
+
+ // Compute a hash on the pathname
+ DWORD Hash(LPTSTR ptszPath);
+
+ COleStaticMutexSem _mxs; // Protects from multiple threads
+ DWORD _cClassEntries; // Count of class entries
+ DWORD _nClassEntryInUse; // First in-use class entry
+ DWORD _nClassEntryAvail; // First available class entry
+ SClassEntry *_pClassEntries; // Array of class entries
+ DWORD _cDllPathEntries; // Count of dll path entries
+ DWORD _nDllPathEntryInUse; // First in-use dll path entry
+ DWORD _nDllPathEntryAvail; // First available dll path entry
+ SDllPathEntry *_pDllPathEntries; // Array of DLL path entries
+ ULONG _cRefsServerProcess; // global refcnt for this process
+};
+
+
+
+#endif // __DLLCACHE_HXX__
diff --git a/private/ole32/com/objact/dllhost.cxx b/private/ole32/com/objact/dllhost.cxx
new file mode 100644
index 000000000..2a5a2b743
--- /dev/null
+++ b/private/ole32/com/objact/dllhost.cxx
@@ -0,0 +1,676 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dllhost.cxx
+//
+// Contents: code for activating inproc dlls of one threading model
+// from apartments of a different threading model.
+//
+// History: 04-Mar-96 Rickhi Created
+//
+// Notes: the basic idea is to call over to an apartment of the
+// appropriate type, get it to do the object creation, then
+// marshal the object back to the calling apartment.
+//
+//+-------------------------------------------------------------------------
+#include <ole2int.h>
+#include <dllhost.hxx>
+
+
+// globals for the various thread-model hosts
+CDllHost gSTHost; // single-threaded host object for STA clients
+CDllHost gSTMTHost; // single-threaded host object for MTA clients
+CDllHost gATHost; // apartment-threaded host object fo MTA clients
+CDllHost gMTHost; // mutli-threaded host object for STA client
+
+ULONG gcHostProcessInits = 0; // count of DLL host threads.
+
+extern void MakeCallableFromAnyApt(OBJREF &objref);
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CDllHost::QueryInterface, public
+//
+// Synopsis: returns supported interfaces
+//
+// History: 04-Mar-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CDllHost::QueryInterface(REFIID riid, void **ppv)
+{
+ // only valid to call this from within the host apartment
+ Win4Assert(_dwHostAptId == GetCurrentApartmentId());
+
+ if (IsEqualIID(riid, IID_IDLLHost) ||
+ IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppv = (IDLLHost *) this;
+ AddRef();
+ return S_OK;
+ }
+
+ *ppv = NULL;
+ return E_NOINTERFACE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CDllHost::AddRef, public
+//
+// Synopsis: we dont refcnt this object so this is a noop
+//
+// History: 04-Mar-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+ULONG CDllHost::AddRef(void)
+{
+ // only valid to call this from within the host apartment
+ Win4Assert(_dwHostAptId == GetCurrentApartmentId());
+ return 1;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CDllHost::Release, public
+//
+// Synopsis: we dont refcnt this object so this is a noop
+//
+// History: 04-Mar-96 Rickhi Created
+//
+//--------------------------------------------------------------------
+ULONG CDllHost::Release(void)
+{
+ // only valid to call this from within the host apartment
+ Win4Assert(_dwHostAptId == GetCurrentApartmentId());
+ return 1;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DoSTClassCreate / DoATClassCreate / DoMTClassCreate
+//
+// Synopsis: Package up get class object so that happens on the proper
+// thread
+//
+// Arguments: [fnGetClassObject] - DllGetClassObject entry point
+// [rclsid] - class id of class object
+// [riid] - interface requested
+// [ppunk] - where to put output interface.
+//
+// Returns: NOERROR - Successfully returned interface
+// E_OUTOFMEMORY - could not allocate memory buffer.
+//
+// Algorithm: pass on to the CDllHost object for the correct apartment.
+//
+// History: 06-Nov-94 Ricksa Created
+// 22-Feb-96 KevinRo Changed implementation drastically
+// 06-Mar-96 Rickhi Use CDllHost
+//
+//--------------------------------------------------------------------------
+HRESULT DoSTClassCreate(LPFNGETCLASSOBJECT pfnGetClassObject,
+ REFCLSID rclsid, REFIID riid, IUnknown **ppunk)
+{
+ ComDebOut((DEB_DLL, "DoSTClassCreate rclsid:%I\n", &rclsid));
+ return gSTHost.GetClassObject(pfnGetClassObject, rclsid, riid, ppunk);
+}
+
+HRESULT DoSTMTClassCreate(LPFNGETCLASSOBJECT pfnGetClassObject,
+ REFCLSID rclsid, REFIID riid, IUnknown **ppunk)
+{
+ ComDebOut((DEB_DLL, "DoSTClassCreate rclsid:%I\n", &rclsid));
+ return gSTMTHost.GetClassObject(pfnGetClassObject, rclsid, riid, ppunk);
+}
+
+HRESULT DoATClassCreate(LPFNGETCLASSOBJECT pfnGetClassObject,
+ REFCLSID rclsid, REFIID riid, IUnknown **ppunk)
+{
+ ComDebOut((DEB_DLL, "DoATClassCreate rclsid:%I\n", &rclsid));
+ return gATHost.GetClassObject(pfnGetClassObject, rclsid, riid, ppunk);
+}
+
+HRESULT DoMTClassCreate(LPFNGETCLASSOBJECT pfnGetClassObject,
+ REFCLSID rclsid, REFIID riid, IUnknown **ppunk)
+{
+ ComDebOut((DEB_DLL, "DoMTClassCreate rclsid:%I\n", &rclsid));
+ return gMTHost.GetClassObject(pfnGetClassObject, rclsid, riid, ppunk);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllHost::GetClassObject
+//
+// Synopsis: called by an apartment to get a class object from
+// a host apartment.
+//
+// History: 04-Mar-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT CDllHost::GetClassObject(LPFNGETCLASSOBJECT pfnGetClassObject,
+ REFCLSID rclsid, REFIID riid, IUnknown **ppUnk)
+{
+ ComDebOut((DEB_DLL,
+ "CDllHost::GetClassObject this:%x tid:%x pfn:%x rclsid:%I riid:%I ppUnk:%x\n",
+ this, GetCurrentThreadId(), pfnGetClassObject, &rclsid, &riid, ppUnk));
+
+ HRESULT hr = CO_E_DLLNOTFOUND;
+ IDLLHost *pIDLLHost = GetHostProxy();
+
+ if (pIDLLHost)
+ {
+ // call the proxy to get to the correct apartment.
+ hr = pIDLLHost->DllGetClassObject((DWORD)pfnGetClassObject,
+ rclsid, riid, ppUnk);
+ pIDLLHost->Release();
+ }
+
+ ComDebOut((DEB_DLL,
+ "CDllHost::GetClassObject this:%x hr:%x\n", this, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllHost::DllGetClassObject
+//
+// Synopsis: Calls the passed in DllGetClassObject on the current thread.
+// Used by an apartment of one threading model to load a DLL
+// of another threading model.
+//
+// History: 04-Mar-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDllHost::DllGetClassObject(DWORD pfnGetClassObject,
+ REFCLSID rclsid, REFIID riid, IUnknown **ppUnk)
+{
+ ComDebOut((DEB_DLL,
+ "CDllHost::DllGetClassObject this:%x tid:%x pfn:%x rclsid:%I riid:%I ppUnk:%x\n",
+ this, GetCurrentThreadId(), pfnGetClassObject, &rclsid, &riid, ppUnk));
+ // only valid to call this from within the host apartment
+ Win4Assert(_dwHostAptId == GetCurrentApartmentId());
+
+ HRESULT hr = ((LPFNGETCLASSOBJECT)pfnGetClassObject)
+ (rclsid, riid, (void **) ppUnk);
+
+ ComDebOut((DEB_DLL,"CDllHost::DllGetClassObject this:%x hr:%x\n", this, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllHost::GetHostProxy
+//
+// Synopsis: returns the host proxy, AddRef'd. Creates it (and
+// potentially the host apartment) if it does not yet exist.
+//
+// History: 04-Mar-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+IDLLHost *CDllHost::GetHostProxy()
+{
+ // we could be called from any thread, esp one that has not done any
+ // marshaling/unmarshaling yet, so we need to initialized the channel
+ // if not already done.
+
+ if (FAILED(InitChannelIfNecessary()))
+ {
+ return NULL;
+ }
+
+ // prevent two threads from creating the proxy simultaneously.
+ _mxs.Request();
+
+ IDLLHost *pIDH = _pIDllProxy;
+ if (pIDH == NULL)
+ {
+ // proxy does not yet exist, create it (and create the host apartment
+ // for apartment-threaded and multi-threaded.
+
+ DWORD dwType = _dwType;
+ if (dwType == HDLLF_SINGLETHREADED && gdwMainThreadId == 0)
+ {
+ // single threaded DLL and there is no main thread yet, so we
+ // create an apartment thread that will also act as the main
+ // thread.
+ dwType = HDLLF_APARTMENTTHREADED;
+ }
+
+ switch (dwType)
+ {
+ case HDLLF_SINGLETHREADED:
+ // send a message to the single-threaded host apartment (the
+ // OleMainThread) to marshal the host interface.
+
+ SSSendMessage(hwndOleMainThread, WM_OLE_GETCLASS,
+ WMSG_MAGIC_VALUE, (LPARAM) this);
+ break;
+
+ case HDLLF_MULTITHREADED:
+ // it is possible that we're comming through here twice if
+ // the first time through we got an error in the marshal or
+ // unmarshal, so dont create the event twice.
+ if (_hEventWakeUp == NULL)
+ {
+ _hEventWakeUp = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (_hEventWakeUp == NULL)
+ {
+ break;
+ }
+ }
+ // fallthru to common code for these two cases.
+
+ case HDLLF_APARTMENTTHREADED:
+ // create a thread to act as the apartment for the dll host. It
+ // will marshal the host interface and set an event when done.
+
+ // it is possible that we're comming through here twice if
+ // the first time through we got an error in the marshal or
+ // unmarshal, so dont create the event twice.
+ if (_hEvent == NULL)
+ {
+ _hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ }
+ if (_hEvent)
+ {
+ DWORD tid;
+ HANDLE hThrd = CreateThread(NULL, 0, DLLHostThreadEntry,
+ (void *)this, 0, &tid);
+ if (hThrd)
+ {
+ WaitForSingleObject(_hEvent, 0xffffffff);
+ CloseHandle(hThrd);
+ }
+ }
+
+ // dont try to cleanup if there are errors from the other
+ // thread, we'll just try again later.
+ break;
+ }
+
+ // the other thread marshaled the interface pointer into _objref and
+ // placed the hresult into _hrMarshal. Check it and unmarshal to
+ // get the host interface proxy.
+
+ if (SUCCEEDED(_hrMarshal))
+ {
+ Win4Assert(_pIDllProxy == NULL);
+ Unmarshal();
+ pIDH = _pIDllProxy;
+ }
+ }
+
+ if (pIDH)
+ {
+ // AddRef the proxy before releasing the lock
+ pIDH->AddRef();
+ }
+
+ _mxs.Release();
+ return pIDH;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetSingleThreadedHost
+//
+// Synopsis: Get the host interface for single threaded inproc class
+// object creation.
+//
+// Arguments: [param] - pointer to the CDllHost for the single-threaded
+// host apartment.
+//
+// History: 06-Mar-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT GetSingleThreadedHost(LPARAM param)
+{
+ ComDebOut((DEB_DLL,
+ "GetSingleThreadedHost pDllHost:%x tid:%x\n", param, GetCurrentThreadId()));
+
+ // param is the ptr to the CDllHost object. Just tell it to marshal
+ // it's IDLLHost interface into it's _objref. The _objref will be
+ // unmarshaled by the calling apartment and the proxy placed in
+ // _pIDllProxy. Dont need to call Lock because we are already
+ // guarenteed to be the only thread accessing the state at this time.
+
+ CDllHost *pDllHost = (CDllHost *)param;
+ return pDllHost->GetSingleThreadHost();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllHost::GetSingleThreadedHost
+//
+// Synopsis: Get the host interface for single threaded inproc class
+// object creation.
+//
+// History: 06-Apr-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT CDllHost::GetSingleThreadHost()
+{
+ // set up the TID and apartment id, then marshal the interface
+ _dwHostAptId = GetCurrentApartmentId();
+ _dwTid = GetCurrentThreadId();
+ return Marshal();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DLLHostThreadEntry
+//
+// Synopsis: Worker thread entry point for AT & MT DLL loading
+//
+// History 06-Apr-96 Rickhi Created
+//
+//+-------------------------------------------------------------------------
+DWORD _stdcall DLLHostThreadEntry(void *param)
+{
+ ComDebOut((DEB_DLL, "DLLHostThreadEntry Tid:%x\n", GetCurrentThreadId()));
+
+ CDllHost *pDllHost = (CDllHost *)param;
+ HRESULT hr = pDllHost->WorkerThread();
+
+ ComDebOut((DEB_DLL, "DLLHostThreadEntry hr:%x\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: WorkerThread
+//
+// Synopsis: Worker thread for STA and MTA DLL loading. Single threaded
+// Dlls are loaded on the main thread (gdwOleMainThread).
+//
+// History 06-Apr-96 Rickhi Created
+//
+//+-------------------------------------------------------------------------
+HRESULT CDllHost::WorkerThread()
+{
+ ComDebOut((DEB_DLL, "WorkerThread pDllHost:%x\n", this));
+ Win4Assert(_hEvent);
+
+ HRESULT hr = CoInitializeEx(NULL, (_dwType == HDLLF_MULTITHREADED)
+ ? COINIT_MULTITHREADED
+ : COINIT_APARTMENTTHREADED);
+ if (SUCCEEDED(hr))
+ {
+ // count 1 more host process
+ InterlockedIncrement((LONG *)&gcHostProcessInits);
+
+ // marshal the DllHost interface to pass back to the caller
+ _dwHostAptId = GetCurrentApartmentId();
+ _dwTid = GetCurrentThreadId();
+
+ hr = Marshal();
+
+ if (SUCCEEDED(hr))
+ {
+ // wake up the thread that started us
+ SetEvent(_hEvent);
+
+ if (_hEventWakeUp)
+ {
+ WaitForSingleObject(_hEventWakeUp, 0xffffffff);
+ }
+ else
+ {
+ // enter a message loop to process requests.
+ MSG msg;
+ while (SSGetMessage(&msg, NULL, 0, 0))
+ {
+ SSDispatchMessage(&msg);
+ }
+ }
+ }
+
+ // special uninitialize for the host threads that does not take
+ // the single thread mutex and does not check for process uninits.
+ COleTls tls;
+ wCoUninitialize(tls, TRUE);
+
+ // count 1 less host process *after* doing the Uninit.
+ InterlockedDecrement((LONG *)&gcHostProcessInits);
+ }
+
+ // Either CoInit/Marshal failed or we are exiting due to the last
+ // CoUninitialize by some other thread. Wake up the calling thread.
+ SetEvent(_hEvent);
+
+ ComDebOut((DEB_DLL, "WorkerThread pDllHost:%x hr:%x\n", this, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllHost::Marshal
+//
+// Synopsis: marshals IDLLHost interface on this object
+//
+// History: 04-Mar-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT CDllHost::Marshal()
+{
+ ComDebOut((DEB_DLL,
+ "CDllHost::Marshal this:%x tid:%x\n", this, GetCurrentThreadId()));
+ // only valid to call this from inside the host apartment
+ Win4Assert(_dwHostAptId == GetCurrentApartmentId());
+
+ // marshal this objref so another apartment can unmarshal it.
+ _hrMarshal = MarshalInternalObjRef(_objref, IID_IDLLHost,
+ (IDLLHost*) this, MSHLFLAGS_NOPING, NULL);
+
+ // make the unmarshaled proxy callable from any apartment.
+ MakeCallableFromAnyApt(_objref);
+
+ ComDebOut((DEB_DLL, "CDllHost::Marshal this:%x hr:%x\n", this, _hrMarshal));
+ return _hrMarshal;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllHost::UnMarshal
+//
+// Synopsis: unmarshals the IDLLHost interface to create a proxy
+//
+// History: 04-Mar-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT CDllHost::Unmarshal()
+{
+ ComDebOut((DEB_DLL,
+ "CDllHost::Unmarshal this:%x tid:%x\n", this, GetCurrentThreadId()));
+ // only valid to call this from outside the host apartment
+ Win4Assert(_dwHostAptId != GetCurrentApartmentId());
+
+ HRESULT hr = _hrMarshal;
+
+ if (SUCCEEDED(hr))
+ {
+ // unmarshal this objref so it can be used in this apartment
+ hr = UnmarshalInternalObjRef(_objref, (void **)&_pIDllProxy);
+ }
+
+ ComDebOut((DEB_DLL, "CDllHost::Unmarshal this:%x hr:%x\n", this, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllHost::Initialize
+//
+// Synopsis: initializer for Dll host object.
+//
+// History: 04-Mar-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+void CDllHost::Initialize(DWORD dwType)
+{
+ ComDebOut((DEB_DLL,"CDllHost::Initialize this:%x type:%x\n", this,dwType));
+
+ _dwType = dwType;
+ _dwHostAptId = 0;
+ _dwTid = 0;
+ _hrMarshal = E_UNSPEC; // never been marshaled yet, dont cleanup
+ _pIDllProxy = NULL;
+ _hEvent = NULL;
+ _hEventWakeUp = NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllHost::ClientCleanup
+//
+// Synopsis: client-side cleanup for Dll host object.
+//
+// History: 04-Apr-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+void CDllHost::ClientCleanup()
+{
+ ComDebOut((DEB_DLL, "CDllHost::ClientCleanup this:%x AptId:%x\n",
+ this, GetCurrentApartmentId()));
+
+ _mxs.Request();
+ // the g_mxsSingleThreadOle mutex is already held in order to
+ // prevent simultaneous use/creation of the proxy while this thread
+ // is doing the cleanup. Since we own all the code that will run during
+ // cleanup, we know it is safe to hold the lock for the duration.
+
+ if (_pIDllProxy)
+ {
+ // proxy exists, release it.
+ _pIDllProxy->Release();
+ _pIDllProxy = NULL;
+ }
+
+ if (SUCCEEDED(_hrMarshal) && (_dwTid != GetCurrentThreadId()))
+ {
+ // wakeup host thread to tell it to exit, then wait for it
+ // to complete it's Uninitialization before continuing.
+
+ if (_dwType == HDLLF_MULTITHREADED)
+ {
+ SetEvent(_hEventWakeUp);
+ }
+ else
+ {
+ PostThreadMessage(_dwTid, WM_QUIT, 0, 0);
+ }
+
+ // wait for the server threads to uninitialize before continuing.
+ WaitForSingleObject(_hEvent, 0xffffffff);
+ }
+
+ // Close the event handles.
+ if (_hEvent)
+ {
+ CloseHandle(_hEvent);
+ _hEvent = NULL;
+ }
+
+ if (_hEventWakeUp)
+ {
+ CloseHandle(_hEventWakeUp);
+ _hEventWakeUp = NULL;
+ }
+
+ _mxs.Release();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllHost::ServerCleanup
+//
+// Synopsis: server-side cleanup for Dll host object.
+//
+// History: 04-Apr-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+void CDllHost::ServerCleanup(DWORD dwAptId)
+{
+ // only do cleanup if the apartment id's match
+ if (_dwHostAptId != dwAptId)
+ return;
+
+ ComDebOut((DEB_DLL, "CDllHost::ServerCleanup this:%x AptId:%x Type:%x\n",
+ this, GetCurrentApartmentId(), _dwType));
+
+ // the _mxs mutex is already held in order to
+ // prevent simultaneous use/creation of the proxy while this thread
+ // is doing the cleanup. Since we own all the code that will run during
+ // cleanup, we know it is safe to hold the lock for the duration.
+
+ if (SUCCEEDED(_hrMarshal))
+ {
+ // server side, marshal was successful so release via RMD
+ ReleaseMarshalObjRef(_objref);
+ FreeObjRef(_objref);
+ _hrMarshal = E_UNSPEC;
+ }
+
+ ComDebOut((DEB_DLL,
+ "CDllHost::Cleanup this:%x tid:%x\n", this, GetCurrentThreadId()));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllHostProcessInitialize
+//
+// Synopsis: initializes the state for DllHost objects.
+//
+// History 06-Mar-96 Rickhi Created
+//
+//+-------------------------------------------------------------------------
+void DllHostProcessInitialize()
+{
+ gSTHost.Initialize(HDLLF_SINGLETHREADED);
+ gSTMTHost.Initialize(HDLLF_SINGLETHREADED);
+ gATHost.Initialize(HDLLF_APARTMENTTHREADED);
+ gMTHost.Initialize(HDLLF_MULTITHREADED);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllHostProcessUninitialize
+//
+// Synopsis: Cleans up the state for DllHost objects. This is called when
+// the process is going to uninitialize. It cleans up the
+// client half of the objects, and wakes the worker threads to
+// cleanup the server half of the objects.
+//
+// History 06-Mar-96 Rickhi Created
+//
+//+-------------------------------------------------------------------------
+void DllHostProcessUninitialize()
+{
+ // initiate the cleanup of the STA and MTA host objects
+ gSTHost.ClientCleanup();
+ gSTMTHost.ClientCleanup();
+ gATHost.ClientCleanup();
+ gMTHost.ClientCleanup();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllHostThreadUninitialize
+//
+// Synopsis: Cleans up the server-side state for any DllHost objects
+// that happen to live on this thread.
+//
+// History 06-Mar-96 Rickhi Created
+//
+//+-------------------------------------------------------------------------
+void DllHostThreadUninitialize()
+{
+ // call each DLL host to see if we need to do any per-thread cleanup.
+ DWORD dwAptId = GetCurrentApartmentId();
+
+ gSTHost.ServerCleanup(dwAptId);
+ gSTMTHost.ServerCleanup(dwAptId);
+ gATHost.ServerCleanup(dwAptId);
+ gMTHost.ServerCleanup(dwAptId);
+}
diff --git a/private/ole32/com/objact/dllhost.hxx b/private/ole32/com/objact/dllhost.hxx
new file mode 100644
index 000000000..55fbead03
--- /dev/null
+++ b/private/ole32/com/objact/dllhost.hxx
@@ -0,0 +1,114 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dllhost.hxx
+//
+// Contents: class for activating inproc dlls of one threading model
+// from apartments of a different threading model.
+//
+// History: 04-Mar-96 Rickhi Created
+//
+//+-------------------------------------------------------------------------
+#include <host.h>
+#include <olesem.hxx>
+
+
+//+-------------------------------------------------------------------------
+//
+// APIs for DLL Hosts
+//
+//+-------------------------------------------------------------------------
+HRESULT GetSingleThreadedHost(LPARAM param);
+
+HRESULT DoSTClassCreate(LPFNGETCLASSOBJECT pfnGetClassObject,
+ REFCLSID rclsid, REFIID riid, IUnknown **ppunk);
+
+HRESULT DoSTMTClassCreate(LPFNGETCLASSOBJECT pfnGetClassObject,
+ REFCLSID rclsid, REFIID riid, IUnknown **ppunk);
+
+HRESULT DoATClassCreate(LPFNGETCLASSOBJECT pfnGetClassObject,
+ REFCLSID rclsid, REFIID riid, IUnknown **ppunk);
+
+HRESULT DoMTClassCreate(LPFNGETCLASSOBJECT pfnGetClassObject,
+ REFCLSID rclsid, REFIID riid, IUnknown **ppunk);
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDllHost
+//
+// Purpose: Accept calls from other apartments within this process to
+// activate inproc objects inside this apartment.
+//
+// History: 04-Mar-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+class CDllHost : public IDLLHost, public CPrivAlloc
+{
+public:
+ friend HRESULT GetSingleThreadedHost(LPARAM param);
+ friend DWORD _stdcall DLLHostThreadEntry(void *param);
+
+ friend void DllHostProcessInitialize();
+ friend void DllHostProcessUninitialize();
+ friend void DllHostThreadUninitialize();
+
+
+ // IDLLHost methods
+ STDMETHOD(QueryInterface)(REFIID riid, VOID **ppv);
+ STDMETHOD_(ULONG,AddRef)(void) ;
+ STDMETHOD_(ULONG,Release)(void);
+
+ STDMETHOD(DllGetClassObject)(
+ DWORD pfnGetClassObject,
+ REFCLSID rclsid,
+ REFIID riid,
+ IUnknown **ppUnk);
+
+ // methods called by different threads
+ HRESULT GetClassObject(
+ LPFNGETCLASSOBJECT pfnGetClassObject,
+ REFCLSID rclsid,
+ REFIID riid,
+ IUnknown **ppUnk);
+
+private:
+ void Initialize(DWORD dwType);
+ void ServerCleanup(DWORD dwTid);
+ void ClientCleanup();
+
+ HRESULT GetSingleThreadHost(void);
+ HRESULT WorkerThread(void);
+ HRESULT Marshal(void);
+ HRESULT Unmarshal(void);
+ IDLLHost *GetHostProxy(void);
+
+ IDLLHost *_pIDllProxy; // ptr to the proxy to the host
+ DWORD _dwType; // flags (see HOSTDLLFLAGS)
+ DWORD _dwHostAptId; // host apartment ID
+ DWORD _dwTid; // ThreadId of server
+ HRESULT _hrMarshal; // result of the marshal
+ HANDLE _hEvent; // event to synchronize thread creation
+ HANDLE _hEventWakeUp; // event to synchronize thread deletion
+ OBJREF _objref; // marshaled object reference
+ COleStaticMutexSem _mxs; // single thread access to some state
+};
+
+
+//
+// Flag values for the _dwType field of the CDllHost object.
+//
+typedef enum tagHOSTDLLFLAGS
+{
+ HDLLF_SINGLETHREADED = 0x1, // host is single threaded
+ HDLLF_APARTMENTTHREADED = 0x2, // host is apartment threaded
+ HDLLF_MULTITHREADED = 0x4, // host is multi threaded
+} HOSTDLLFLAGS;
+
+
+// external defines for the various thread-model hosts
+extern CDllHost gSTHost; // single-threaded host object for STA client
+extern CDllHost gSTMTHost; // single-threaded host object for MTA clients
+extern CDllHost gATHost; // apartment-threaded host object for MTA clients
+extern CDllHost gMTHost; // mutli-threaded host object for STA host clients
diff --git a/private/ole32/com/objact/filelist.mk b/private/ole32/com/objact/filelist.mk
new file mode 100644
index 000000000..dea0e3055
--- /dev/null
+++ b/private/ole32/com/objact/filelist.mk
@@ -0,0 +1,60 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = objact.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES = .\cobjact.cxx \
+ .\coscm.cxx \
+ .\distname.cxx \
+ .\dllapi.cxx \
+ .\dllcache.cxx \
+ .\hobjact.cxx \
+ .\smstg.cxx \
+ .\sobjact.cxx \
+ .\treat.cxx
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES = ..\idl\$(OBJDIR)\scm_s.obj
+
+#
+# Precompiled headers.
+#
+
+PXXFILE = .\headers.cxx
+PFILE =
+
+CINC = $(CINC) -I..\inc -I..\idl -I..\remote $(TRACELOG)
+
+MTHREAD = 1
+
+MULTIDEPEND = MERGED
diff --git a/private/ole32/com/objact/hobjact.cxx b/private/ole32/com/objact/hobjact.cxx
new file mode 100644
index 000000000..4562b9bdd
--- /dev/null
+++ b/private/ole32/com/objact/hobjact.cxx
@@ -0,0 +1,652 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: hobjact.cxx
+//
+// Contents: Helper Functions for object activation
+//
+// Functions: CreateObjectHelper
+// GetObjectHelper
+// MarshalHelper
+//
+// History: 12-May-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+
+#include <iface.h>
+#include <objsrv.h>
+#include <objact.hxx>
+
+// Global cache of Inprocess server DLLs
+CDllCache gdllcacheInprocSrv;
+
+// Global cache of handler DLLs
+CDllCache gdllcacheHandler;
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateObjectHelper
+//
+// Synopsis: Creates an object in a persistent state
+//
+// Arguments: [pcf] - class factory
+// [grfMode] - mode to use when loading file
+// [pwszCreateFrom] - file path to create from
+// [pstgCreateFrom] - storage to create from
+// [pwszNewName] - name of new object on persistent storage
+// [ppvUnk] - pointer to IUnknown
+//
+// Returns: S_OK - object successfully created
+// MISSING
+//
+// Algorithm: This creates an instance of the object. Then if
+// if an IStorage is provided, it uses that to create
+// a persistent instance; a copy of the loaded object is
+// saved to pwszNewName. If a file name is provided,
+// that is used; again a copy is saved to pwszNewName.
+// If pwszNewName is non-NULL (in addition to the other
+// values being NULL), a new storage is created with that
+// name and the object is told to initialize itself on
+// that storage. Otherwise (all three values are NULL),
+// the object is not initialized at all.
+//
+// History: 12-May-93 Ricksa Created
+//
+// Notes: This helper is called by by servers and clients
+//
+//--------------------------------------------------------------------------
+HRESULT CreateObjectHelper(
+ IClassFactory *pcf,
+ DWORD grfMode,
+ WCHAR *pwszCreateFrom,
+ IStorage *pstgCreateFrom,
+ WCHAR *pwszNewName,
+ IUnknown **ppunk)
+{
+ TRACECALL(TRACE_ACTIVATION, "CreateObjectHelper");
+
+ HRESULT hr;
+
+ XIUnknown xunk;
+
+ XIPersistFile xipfile;
+
+ // Get the controlling unknown for the instance.
+ hr = pcf->CreateInstance(NULL, IID_IUnknown, (void **) &xunk);
+
+ // This shouldn't fail but it is untrusted code ...
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ if (pstgCreateFrom)
+ {
+ XIPersistStorage xipstg;
+
+ // Load the storage requested as an template
+ hr = xunk->QueryInterface(IID_IPersistStorage, (void **) &xipstg);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = xipstg->Load(pstgCreateFrom);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // Save the storage to a file.
+ hr = xunk->QueryInterface(IID_IPersistFile, (void **) &xipfile);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = xipfile->Save(pwszNewName, TRUE);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = xipfile->SaveCompleted(pwszNewName);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+ else if (pwszCreateFrom)
+ {
+ // Load from a file
+ hr = xunk->QueryInterface(IID_IPersistFile, (void **) &xipfile);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = xipfile->Load(pwszCreateFrom, grfMode);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // Save to new objact
+ hr = xipfile->Save(pwszNewName, TRUE);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = xipfile->SaveCompleted(pwszNewName);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+ else if (pwszNewName != NULL)
+ {
+ // Safe place to put the IStorage we want to create
+ XIStorage xistg;
+
+ hr = StgCreateDocfile(pwszNewName,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL,
+ &xistg);
+
+ // BUGBUG: Fix the error here!
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // Create a new empty object
+ XIPersistStorage xipstg;
+
+ // Load the storage requested as an template
+ hr = xunk->QueryInterface(IID_IPersistStorage, (void **) &xipstg);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // BUGBUG: How does a new empty object get created?
+ // For now we assume this kind of load will do
+ // the trick.
+ hr = xipstg->InitNew(xistg);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+
+
+ // We only get here if no error occurred
+ xunk.Transfer(ppunk);
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetObjectHelper
+//
+// Synopsis: Creates an object in a persistent state
+//
+// Arguments: [pcf] - class factory
+// [grfMode] - mode to use when loading file
+// [pwszName] - file path to persistent storage
+// [pstg] - storage for persistent storage
+// [ppvUnk] - pointer to IUnknown
+//
+// Returns: S_OK - object successfully instantiated
+//
+// Algorithm: Create an empty instance of the object and then use
+// either the provided storage or file to load the object.
+//
+// History: 12-May-93 Ricksa Created
+//
+// Notes: This helper is called by by servers and clients
+//
+//--------------------------------------------------------------------------
+HRESULT GetObjectHelper(
+ IClassFactory *pcf,
+ DWORD grfMode,
+ WCHAR *pwszName,
+ IStorage *pstg,
+ InterfaceData **ppIFD,
+ IUnknown **ppunk)
+{
+ TRACECALL(TRACE_ACTIVATION, "GetObjectHelper");
+
+ XIUnknown xunk;
+
+ // Get the controlling unknown for the instance.
+ HRESULT hr = pcf->CreateInstance(NULL, IID_IUnknown, (void **) &xunk);
+
+ // This shouldn't fail but it is untrusted code ...
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // We put all these safe interface classes in the outer block because
+ // we might be in the VDM where some idiotic classes will release
+ // themselves at ref counts greater than one. Therefore, we avoid
+ // releases at all costs.
+ XIPersistStorage xipstg;
+ XIPersistFile xipfile;
+
+ // This is the case that the class requested is a DLL
+ if (pstg)
+ {
+ // Load the storage requested as an template
+ hr = xunk->QueryInterface(IID_IPersistStorage, (void **) &xipstg);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = xipstg->Load(pstg);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+ else
+ {
+ hr = xunk->QueryInterface(IID_IPersistFile, (void **) &xipfile);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = xipfile->Load(pwszName, grfMode);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+
+ // If an interface buffer was passed in, then this is a remote call
+ // and we need to marshal the interface.
+ if (ppIFD)
+ {
+ // AddRef the pointer because MarshalHelper expects to release
+ // pointer. Because MarshalHelper is called from two other places,
+ // we do an AddRef here instead of moving the AddRef out of
+ // MarshalHelper.
+ xunk->AddRef();
+ hr = MarshalHelper(xunk, IID_IUnknown, MSHLFLAGS_NORMAL, ppIFD);
+ }
+ else
+ {
+ // This is an inprocess server so we need to return the output
+ // punk
+ xunk.Transfer(ppunk);
+ }
+
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: MarshalHelper
+//
+// Synopsis: Marshals an Interface
+//
+// Arguments: [punk] - interface to marshal
+// [riid] - iid to marshal
+// [ppIRD] - where to put pointer to marshaled data
+//
+// Returns: S_OK - object successfully marshaled.
+//
+// Algorithm: Marshal the object and then get the pointer to
+// the marshaled data so we can give it to RPC
+//
+// History: 12-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT MarshalHelper(
+ IUnknown *punk,
+ REFIID riid,
+ DWORD mshlflags,
+ InterfaceData **ppIRD)
+{
+ TRACECALL(TRACE_ACTIVATION, "MarshalHelper");
+
+ // Stream to put marshaled interface in
+ CXmitRpcStream xrpc;
+
+ // use MSHCTX_DIFFERENTMACHINE so we get the long form OBJREF
+ HRESULT hr = CoMarshalInterface(&xrpc, riid, punk,
+ MSHCTX_DIFFERENTMACHINE,
+ NULL, mshlflags);
+
+ if (SUCCEEDED(hr))
+ {
+ xrpc.AssignSerializedInterface(ppIRD);
+ }
+
+ // We release our reference to this object here. Either we
+ // are going to hand it out to the client, in which case, we
+ // want to release it when the client is done or the marshal
+ // failed in which case we want it to go away since we can't
+ // pass it back to the client.
+ punk->Release();
+
+ return hr;
+}
+#ifdef DCOM
+//+---------------------------------------------------------------------------
+//
+// Function: UnMarshalHelper
+//
+// Synopsis:
+//
+// Arguments: [pIFP] --
+// [riid] --
+// [ppv] --
+//
+// Returns:
+//
+// History: 10-10-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT UnMarshalHelper(MInterfacePointer *pIFP, REFIID riid, void **ppv)
+{
+ HRESULT hr = E_INVALIDARG;
+
+ if (pIFP && ppv)
+ {
+ CXmitRpcStream Stm((InterfaceData *) pIFP);
+
+ *ppv = NULL;
+
+ hr = CoUnmarshalInterface(&Stm, riid, ppv);
+ }
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetObjectHelperMulti
+//
+// Synopsis: Creates an object in a persistent state
+//
+// Arguments: [pcf] - class factory
+// [grfMode] - mode to use when loading file
+// [pwszName] - file path to persistent storage
+// [pstg] - storage for persistent storage
+// [ppvUnk] - pointer to IUnknown
+//
+// Returns: S_OK - object successfully instantiated
+//
+// Algorithm: Create an empty instance of the object and then use
+// either the provided storage or file to load the object.
+//
+// History: 12-May-93 Ricksa Created
+//
+// Notes: This helper is called by by servers and clients
+//
+//--------------------------------------------------------------------------
+HRESULT GetObjectHelperMulti(
+ IClassFactory *pcf,
+ DWORD grfMode,
+ IUnknown * punkOuter,
+ WCHAR *pwszName,
+ IStorage *pstg,
+ DWORD dwInterfaces,
+ IID * pIIDs,
+ MInterfacePointer **ppIFDArray,
+ HRESULT * pResultsArray,
+ MULTI_QI *pResults )
+{
+ TRACECALL(TRACE_ACTIVATION, "GetObjectHelperMulti");
+
+ XIUnknown xunk;
+
+ // Get the controlling unknown for the instance.
+ HRESULT hr = pcf->CreateInstance(punkOuter, IID_IUnknown, (void **) &xunk);
+
+ // This shouldn't fail but it is untrusted code ...
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // We put all these safe interface classes in the outer block because
+ // we might be in the VDM where some idiotic classes will release
+ // themselves at ref counts greater than one. Therefore, we avoid
+ // releases at all costs.
+ XIPersistStorage xipstg;
+ XIPersistFile xipfile;
+
+ // This is the case that the class requested is a DLL
+ if (pstg)
+ {
+ // Load the storage requested as an template
+ hr = xunk->QueryInterface(IID_IPersistStorage, (void **) &xipstg);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = xipstg->Load(pstg);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+ else
+ {
+ hr = xunk->QueryInterface(IID_IPersistFile, (void **) &xipfile);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = xipfile->Load(pwszName, grfMode);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+
+ // If an interface buffer was passed in, then this is a remote call
+ // and we need to marshal the interface.
+ if (ppIFDArray)
+ {
+ // AddRef the pointer because MarshalHelper expects to release
+ // pointer. Because MarshalHelper is called from two other places,
+ // we do an AddRef here instead of moving the AddRef out of
+ // MarshalHelper.
+ xunk->AddRef();
+ hr = MarshalHelperMulti(xunk, dwInterfaces, pIIDs, ppIFDArray, pResultsArray);
+ }
+ else
+ {
+ // This is an inprocess server so we need to return the output
+ // punk
+ HRESULT hr2;
+
+ for ( DWORD i=0; i<dwInterfaces; i++ )
+ {
+ hr2 = xunk->QueryInterface( *(pResults[i].pIID),
+ (void**)&pResults[i].pItf );
+
+ pResults[i].hr = hr2;
+
+ }
+ // rely on the caller to count up the failed QI's
+ return S_OK;
+
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetInstanceHelperMulti
+//
+// Synopsis: Creates an instance
+//
+// Arguments: [pcf] - class factory
+// [grfMode] - mode to use when loading file
+// [pwszName] - file path to persistent storage
+// [pstg] - storage for persistent storage
+// [ppvUnk] - pointer to IUnknown
+//
+// Returns: S_OK - object successfully instantiated
+//
+// Algorithm: Create an empty instance of the object and then use
+// either the provided storage or file to load the object.
+//
+// History: 12-May-93 Ricksa Created
+//
+// Notes: This helper is called by by servers and clients
+//
+//--------------------------------------------------------------------------
+HRESULT GetInstanceHelperMulti(
+ IClassFactory *pcf,
+ DWORD dwInterfaces,
+ IID * pIIDs,
+ MInterfacePointer **ppIFDArray,
+ HRESULT * pResultsArray,
+ IUnknown **ppunk)
+{
+ TRACECALL(TRACE_ACTIVATION, "GetInstanceHelperMulti");
+
+ XIUnknown xunk;
+
+ // Get the controlling unknown for the instance.
+ HRESULT hr = pcf->CreateInstance(NULL, IID_IUnknown, (void **) &xunk);
+
+ // This shouldn't fail but it is untrusted code ...
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // If an interface buffer was passed in, then this is a remote call
+ // and we need to marshal the interface.
+ if (ppIFDArray)
+ {
+ // AddRef the pointer because MarshalHelper expects to release
+ // pointer. Because MarshalHelper is called from two other places,
+ // we do an AddRef here instead of moving the AddRef out of
+ // MarshalHelper.
+ xunk->AddRef();
+ hr = MarshalHelperMulti(xunk, dwInterfaces, pIIDs, ppIFDArray, pResultsArray);
+
+ if (ppunk)
+ {
+ xunk.Transfer(ppunk);
+ }
+
+ return hr;
+ }
+ else
+ {
+ // This is an inprocess server so we need to return the output
+ // punk
+ xunk.Transfer(ppunk);
+ }
+
+ return S_OK;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: MarshalHelperMulti
+//
+// Synopsis: Marshals a bunch of Interfaces
+//
+// Arguments: [punk] - interface to marshal
+// [riid] - iid to marshal
+// [ppIRD] - where to put pointer to marshaled data
+//
+// Returns: S_OK - object successfully marshaled.
+//
+// Algorithm: Marshal the object and then get the pointer to
+// the marshaled data so we can give it to RPC
+//
+// History: 12-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT MarshalHelperMulti(
+ IUnknown *punk,
+ DWORD dwInterfaces,
+ IID * pIIDs,
+ MInterfacePointer **ppIFDArray,
+ HRESULT * pResultsArray)
+{
+ TRACECALL(TRACE_ACTIVATION, "MarshalHelperMulti");
+
+ HRESULT hr = E_NOINTERFACE;
+
+ for ( DWORD i = 0; i<dwInterfaces; i++ )
+ {
+ // Stream to put marshaled interface in
+ CXmitRpcStream xrpc;
+
+ // use DIFFERENTMACHINE so we get the long form OBJREF
+ HRESULT hr2 = CoMarshalInterface(&xrpc, pIIDs[i], punk,
+ MSHCTX_DIFFERENTMACHINE,
+ NULL, MSHLFLAGS_NORMAL);
+
+ pResultsArray[i] = hr2;
+ if (SUCCEEDED(hr2))
+ {
+ xrpc.AssignSerializedInterface((InterfaceData**)&ppIFDArray[i]);
+ hr = hr2; // report OK if ANY interface was found
+ }
+
+ }
+
+ // We release our reference to this object here. Either we
+ // are going to hand it out to the client, in which case, we
+ // want to release it when the client is done or the marshal
+ // failed in which case we want it to go away since we can't
+ // pass it back to the client.
+ punk->Release();
+
+ return hr;
+}
+
+#endif // DCOM
+
+
diff --git a/private/ole32/com/objact/makefile b/private/ole32/com/objact/makefile
new file mode 100644
index 000000000..e09078703
--- /dev/null
+++ b/private/ole32/com/objact/makefile
@@ -0,0 +1,24 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+!include $(CAIROLE)\com\makefile
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/com/objact/objact.hxx b/private/ole32/com/objact/objact.hxx
new file mode 100644
index 000000000..450e7a895
--- /dev/null
+++ b/private/ole32/com/objact/objact.hxx
@@ -0,0 +1,274 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: objact.hxx
+//
+// Contents: Common definitions for object activation.
+//
+// Classes: XIUnknown
+// XIPersistStorage
+// XIPersistFile
+// XIStorage
+//
+// History: 12-May-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+//
+//--------------------------------------------------------------------------
+#ifndef __OBJACT_HXX__
+#define __OBJACT_HXX__
+
+#include <safepnt.hxx>
+#include <xmit.hxx>
+#include <tracelog.hxx>
+#include "dllcache.hxx"
+#include "resolver.hxx"
+
+// Constants used during attempt to get the class of an object
+#define GET_CLASS_RETRY_SLEEP_MS 250
+#define GET_CLASS_RETRY_MAX 3
+
+// Global cache of Inprocess server DLLs
+extern CDllCache gdllcacheInprocSrv;
+
+// Global cache of handler DLLs
+extern CDllCache gdllcacheHandler;
+
+// Global object for talking to SCM
+extern CRpcResolver gResolver;
+
+// Helper function that creates an object
+HRESULT CreateObjectHelper(
+ IClassFactory *pcf,
+ DWORD grfMode,
+ WCHAR *pwszCreateFrom,
+ IStorage *pstgCreateFrom,
+ WCHAR *pwszNewName,
+ IUnknown **ppunk);
+
+// Helper function that activates an object
+HRESULT GetObjectHelper(
+ IClassFactory *pcf,
+ DWORD grfMode,
+ WCHAR *pwszName,
+ IStorage *pstg,
+ InterfaceData **pIFD,
+ IUnknown **ppunk);
+
+// Helper function for marshaling an object
+HRESULT MarshalHelper(
+ IUnknown *punk,
+ REFIID riid,
+ DWORD mshlflags,
+ InterfaceData **pIFD);
+
+#ifdef DCOM
+HRESULT UnMarshalHelper(
+ MInterfacePointer *pIFP,
+ REFIID riid,
+ void **ppv);
+
+
+
+// Helper function that activates an object
+HRESULT GetObjectHelperMulti(
+ IClassFactory *pcf,
+ DWORD grfMode,
+ IUnknown * punkOuter,
+ WCHAR *pwszName,
+ IStorage *pstg,
+ DWORD dwInterfaces,
+ IID * pIIDs,
+ MInterfacePointer **pIFDArray,
+ HRESULT * pResultsArray,
+ MULTI_QI *pResults);
+
+HRESULT GetInstanceHelperMulti(
+ IClassFactory *pcf,
+ DWORD dwInterfaces,
+ IID * pIIDs,
+ MInterfacePointer **ppIFDArray,
+ HRESULT * pResultsArray,
+ IUnknown **ppunk);
+
+// Helper function for marshaling an object
+HRESULT MarshalHelperMulti(
+ IUnknown *punk,
+ DWORD dwInterfaces,
+ IID * pIIDs,
+ MInterfacePointer **pIFDArray,
+ HRESULT * pResultsArray);
+
+HRESULT GetInstanceHelper(
+ COSERVERINFO * pServerInfo,
+ CLSID * pclsidOverride,
+ IUnknown * punkOuter, // only relevant locally
+ DWORD dwClsCtx,
+ DWORD grfMode,
+ OLECHAR * pwszName,
+ struct IStorage * pstg,
+ DWORD dwCount,
+ MULTI_QI * pResults );
+
+#endif // DCOM
+
+// Get object from the ROT by its path
+HRESULT GetObjectByPath(WCHAR *pwszName, void **ppvUnk, REFIID riid);
+
+// Remap CLSCTX so that the correct type of inproc server will be requested.
+DWORD RemapClassCtxForInProcServer(DWORD dwCtrl);
+
+// Verify that a 32 bit Handler DLL is being returned to the right context
+HRESULT CheckScmHandlerResult(WCHAR *pwszDllToLoad);
+
+// Checks if the given clsid is an internal class, and
+// bypasses the TreatAs and SCM lookup if so. Also checks for
+// OLE 1.0 classes, which are actually considered to be
+// internal, since their OLE 2.0 implementation wrapper is
+// ours.
+BOOL IsInternalCLSID(REFCLSID rclsid,
+ REFIID riid,
+ HRESULT &hr,
+ void ** ppvClassObj);
+
+// Helper for unmarshaling an interface from remote
+HRESULT DoUnmarshal(InterfaceData *pIFD, REFIID riid, void **ppvUnk);
+
+// Routine for cleaning out unused DLLs
+HRESULT CallFreeUnused(void);
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OnMainThread
+//
+// Synopsis: Determine whether we are on the main thread or not
+//
+// History: 10-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL OnMainThread(void)
+{
+ return (GetCurrentThreadId() == gdwMainThreadId);
+}
+
+// Helper routine to find clsid in cache or load inproc if requested and
+// found
+IUnknown *SearchCacheOrLoadInProc(REFCLSID rclsid,
+ REFIID riid,
+ BOOL fRemote,
+ BOOL fForSCM,
+ DWORD dwContext,
+ DWORD dwDllServerType,
+ HRESULT &hr);
+
+#ifndef _CAIRO_
+
+# ifdef CAIROLE_NT1X_DIST
+
+HRESULT ProcessPath(
+ WCHAR *pwszPathIn,
+ WCHAR **ppwszPathOut,
+ WCHAR **ppwszServer);
+
+# else
+
+// BUGBUG: This inline routine exists to make the code less messy and is
+// a very fast way to replace the Cairo code processing. We may want to
+// fix the code some better way in the long run.
+inline HRESULT ProcessPath(
+ WCHAR *pwszPathIn,
+ WCHAR **ppwszPathOut,
+ WCHAR **ppwszServer)
+{
+ *ppwszPathOut = pwszPathIn;
+
+ if (ppwszServer)
+ {
+# ifdef _CHICAGO_
+ // BUGBUG - We & RPC need to agree on the right local name - take it
+ // from the registry?
+ *ppwszServer = L"local";
+# else
+ *ppwszServer = NULL;
+# endif
+ }
+
+ return S_OK;
+}
+
+# endif // CAIROLE_NT1X_DIST
+
+#else
+
+HRESULT ProcessPath(
+ WCHAR *pwszPathIn,
+ WCHAR **ppwszPathOut,
+ WCHAR **ppwszServer);
+
+#endif // _CAIRO_
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: XIUnknown
+//
+// Purpose: Smart pointer for IUnknown interface
+//
+// Interface: see common\ih\safepnt.hxx
+//
+// History: 12-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+SAFE_INTERFACE_PTR(XIUnknown, IUnknown)
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: XIPersistStorage
+//
+// Purpose: Smart pointer for IPersistStorage interface
+//
+// Interface: see common\ih\safepnt.hxx
+//
+// History: 12-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+SAFE_INTERFACE_PTR(XIPersistStorage, IPersistStorage)
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: XIPersistFile
+//
+// Purpose: Smart pointer for IPersistFile interface
+//
+// Interface: see common\ih\safepnt.hxx
+//
+// History: 12-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+SAFE_INTERFACE_PTR(XIPersistFile, IPersistFile)
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: XIStorage
+//
+// Purpose: Smart pointer for IStorage interface
+//
+// Interface: see common\ih\safepnt.hxx
+//
+// History: 12-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+SAFE_INTERFACE_PTR(XIStorage, IStorage)
+
+#endif // __OBJACT_HXX__
diff --git a/private/ole32/com/objact/remapi.cxx b/private/ole32/com/objact/remapi.cxx
new file mode 100644
index 000000000..e9cd7aa64
--- /dev/null
+++ b/private/ole32/com/objact/remapi.cxx
@@ -0,0 +1,524 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: remapi.cxx
+//
+// Contents: Rem calls to object servers for Win95
+//
+// Classes: SScmGetClassObj
+// SScmCreateObj
+// SScmActivateObj
+//
+// Functions: CallObjSrvGetClassObject
+// CallObjSrvCreateObject
+// CallObjSrvActivateObject
+// GetToRemCoGetActiveClassObject
+// GetToRemCoActivateObject
+// GetToRemCoCreateObject
+//
+// History: 06-Jun-95 Ricksa Created.
+//
+// Notes: This file is Chicago ONLY!
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+
+#include <iface.h>
+#include <objsrv.h>
+#include <endpnt.hxx>
+#include <service.hxx>
+#include <resolver.hxx>
+#include <objerror.h>
+#include <channelb.hxx>
+
+
+#ifdef _CHICAGO_
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: SOSGetClassObj
+//
+// Purpose: Pass GetClassObject parameters through channel threading
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+struct SOSGetClassObj : STHREADCALLINFO
+{
+ // init base class and copy string in place
+ SOSGetClassObj (TRANSMIT_FN fn,CALLCATEGORY callcat)
+ : STHREADCALLINFO(fn, callcat, 0)
+ {
+ // Header does the work
+ }
+
+ handle_t hRpc; // Rpc handle
+ CLSID clsid;
+
+ // out params; can't point directly to caller's data because of cancel
+ InterfaceData * pIFDClassObj;
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: SOSCreateObj
+//
+// Purpose: Pass CreatePersistentInstance parameters through channel
+// threading.
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+struct SOSCreateObj : STHREADCALLINFO
+{
+ // alloc enough for class, strings and iface data together
+ void *operator new(size_t size, DWORD cbPath, DWORD cbIFD,
+ DWORD cbNewName)
+ { return PrivMemAlloc(size + cbPath + cbIFD + cbNewName); }
+
+ SOSCreateObj (TRANSMIT_FN fn,CALLCATEGORY callcat,
+ WCHAR *pwszP, DWORD cbPath,
+ InterfaceData *pIFD, DWORD cbIFD,
+ WCHAR *pwszN, DWORD cbNewName)
+ : STHREADCALLINFO(fn, callcat, 0)
+ {
+ // interface data is first to easily get 4byte alignment
+ pIFDstg = CopyInterfaceData(this+1, pIFD, cbIFD);
+ pwszPath = CopyWideString((char *)(this+1) + cbIFD, pwszP, cbPath);
+ pwszNewName = CopyWideString((char *)(this+1) + cbIFD + cbPath,
+ pwszN, cbNewName);
+ }
+
+ handle_t hRpc; // Rpc handle
+ CLSID clsid;
+ DWORD dwMode;
+ WCHAR *pwszPath;
+ DWORD dwTIDCaller; // will be passed to callee's
+ // message filter
+ InterfaceData * pIFDstg; // points after this struct
+ WCHAR * pwszNewName; // points after this struct
+
+ // out params; can't point directly to caller's data because of cancel
+ InterfaceData * pIFDunk;
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: SOSActivateObj
+//
+// Purpose: Pass GetPersistenInstance request parameters through threading
+// mechanism.
+//
+// History: 11-Nov-93 Ricksa Created
+// 18-Aug-94 AlexT Add dwTIDCaller
+//
+//--------------------------------------------------------------------------
+struct SOSActivateObj : STHREADCALLINFO
+{
+ // alloc enough for class, strings and iface data together
+ void *operator new(size_t size, DWORD cbPath, DWORD cbIFD)
+ { return PrivMemAlloc(size + cbPath + cbIFD); }
+
+ SOSActivateObj(TRANSMIT_FN fn,CALLCATEGORY callcat,
+ WCHAR *pwszP, DWORD cbPath,
+ InterfaceData *pIFD, DWORD cbIFD)
+ : STHREADCALLINFO(fn, callcat, 0)
+ {
+ // interface data is first to easily get 4byte alignment
+ pIFDstg = CopyInterfaceData(this+1, pIFD, cbIFD);
+ pwszPath = CopyWideString((char *)(this+1) + cbIFD, pwszP, cbPath);
+ }
+
+
+ handle_t hRpc; // Rpc handle
+ CLSID clsid;
+ DWORD grfMode;
+ DWORD dwTIDCaller; // will be passed to callee's
+ // message filter
+ WCHAR * pwszPath; // points after this struct
+ InterfaceData * pIFDstg; // points after this struct
+ InterfaceData * pIFDFromROT;
+
+ // out params; can't point directly to caller's data because of cancel
+ InterfaceData * pIFDunk;
+
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CallObjSrvGetClassObject
+//
+// Synopsis: Call through to the SCM to get a class object
+//
+// Arguments: [pData] - parmeters
+//
+// Returns: S_OK
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT __stdcall CallObjSrvGetClassObject( STHREADCALLINFO *pData )
+{
+ SOSGetClassObj *posclsobj = (SOSGetClassObj *) pData;
+
+ error_status_t rpcstat = RPC_S_OK;
+
+ HRESULT result = _RemCoGetActiveClassObject(posclsobj->hRpc, &pData->lid(),
+ &posclsobj->clsid, &posclsobj->pIFDClassObj, &rpcstat);
+
+ if (rpcstat != RPC_S_OK)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CallObjSrvGetClassObject error rpcstat = %lx\n", rpcstat));
+ result = CO_E_SCM_RPC_FAILURE;
+ }
+
+ return result;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CallObjSrvCreateObject
+//
+// Synopsis: Call through to the SCM to create an object
+//
+// Arguments: [pData] - parmeters
+//
+// Returns: S_OK
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT __stdcall CallObjSrvCreateObject( STHREADCALLINFO *pData )
+{
+ SOSCreateObj *poscrtobj = (SOSCreateObj *) pData;
+ HRESULT result;
+ DWORD dwTIDCallee = 0;
+
+ error_status_t rpcstat = RPC_S_OK;
+
+ result = _RemCoCreateObject(poscrtobj->hRpc, NULL, &pData->lid(),
+ &poscrtobj->clsid, poscrtobj->dwMode, poscrtobj->pwszPath,
+ poscrtobj->pIFDstg, poscrtobj->pwszNewName, poscrtobj->dwTIDCaller,
+ &dwTIDCallee, &poscrtobj->pIFDunk, &rpcstat);
+
+ if (rpcstat != RPC_S_OK)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CallObjSrvCreateObject error rpcstat = %lx\n", rpcstat));
+ result = CO_E_SCM_RPC_FAILURE;
+ }
+
+ // _RemCoCreateObject returns the thread id of the callee - we record it
+ // in the STHREADCALLINFO so that we can pass it to this app's message
+ // filter as needed
+
+ pData->SetTIDCallee(dwTIDCallee);
+
+ return result;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CallObjSrvActivateObject
+//
+// Synopsis: Call through to the SCM to activate an object
+//
+// Arguments: [pData] - parmeters
+//
+// Returns: S_OK
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT __stdcall CallObjSrvActivateObject( STHREADCALLINFO *pData )
+{
+ SOSActivateObj *posactobj = (SOSActivateObj *) pData;
+ HRESULT result;
+ DWORD dwTIDCallee = 0;
+
+ error_status_t rpcstat = RPC_S_OK;
+
+ result = _RemCoActivateObject(posactobj->hRpc, NULL,
+ &pData->lid(), &posactobj->clsid, posactobj->grfMode,
+ posactobj->pwszPath, posactobj->pIFDstg, posactobj->dwTIDCaller,
+ &dwTIDCallee, &posactobj->pIFDunk, posactobj->pIFDFromROT,
+ &rpcstat);
+
+ if (rpcstat != RPC_S_OK)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CallObjSrvActivateObject error rpcstat = %lx\n", rpcstat));
+ result = CO_E_SCM_RPC_FAILURE;
+ }
+
+ // _RemCoActivateObject returns the thread id of the callee - we record it
+ // in the STHREADCALLINFO so that we can pass it to this app's message
+ // filter as needed
+
+ pData->SetTIDCallee(dwTIDCallee);
+
+ return result;
+}
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetToRemCoGetActiveClassObject
+//
+// Synopsis: Dispatch RemCoGetActiveClassObject via call control
+//
+// Arguments: [hRpc] - handle to RPC connection
+// [guidThreadId] - logical thread id
+// [pclsid] - class ID.
+// [ppIFD] - where to return marshaled interface
+// [prpcstat] - communication error status
+//
+// Returns: S_OK - class object successful found & returned
+// Other - call failed.
+//
+// Algorithm: Build packet for dispatching call and then call RPC
+// to get the call dispatched.
+//
+// History: 06-Jun-95 Ricksa Created.
+//
+// Notes: This is only used in Chicago. Its purpose is to create
+// make the call to the object server non-raw so we get
+// the benefit of the call control.
+//
+//--------------------------------------------------------------------------
+HRESULT GetToRemCoGetActiveClassObject(
+ handle_t hRpc,
+ const GUID *guidThreadId,
+ const GUID *pclsid,
+ InterfaceData **ppIFD,
+ error_status_t *prpcstat)
+{
+ // Result from call
+ HRESULT hr;
+
+ // Make a parameter packet suitable for passing to the channel
+ SOSGetClassObj *posclsobj =
+ new SOSGetClassObj(CallObjSrvGetClassObject, CALLCAT_SYNCHRONOUS);
+
+ if (posclsobj == NULL)
+ return E_OUTOFMEMORY;
+
+ posclsobj->hRpc = hRpc;
+ posclsobj->clsid = *pclsid;
+ posclsobj->pIFDClassObj = NULL;
+
+ // Let the channel handle the work of getting this on the right thread
+ hr = CChannelControl::GetOffCOMThread((STHREADCALLINFO **)&posclsobj);
+
+ if (SUCCEEDED(hr))
+ {
+ *ppIFD = posclsobj->pIFDClassObj;
+ }
+
+ if (hr != RPC_E_CALL_CANCELED)
+ {
+ delete posclsobj;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetToRemCoActivateObject
+//
+// Synopsis: Dispatch RemCoActivateObject to object server
+//
+// Arguments: [hRpc] - rpc handle
+// [pwszProtseq] - protocol seq (not used in Chicago)
+// [guidThreadId] - logical thread id.
+// [pclsid] - class ID for the object
+// [grfMode] - mode to open file if file supplied.
+// [pwsPath] - path to object if supplied.
+// [pIFDstg] - marshaled storage if supplied.
+// [dwTIDCaller] - caller's thread id
+// [pdwTIDCallee] - place holder for callee's thread id
+// [ppIFD] - where to return marshaled object.
+// [prpcstat] - communication status
+//
+// Returns: S_OK - Object instantiated and marshaled.
+// Other - call failed.
+//
+// Algorithm: Build packet for dispatching call and then call RPC
+// to get the call dispatched.
+//
+// History: 06-Jun-95 Ricksa Created.
+//
+// Notes: This exists to get the call control in the loop between
+// the client and server since this call in Chicago is actually
+// between the client and the server.
+//
+//--------------------------------------------------------------------------
+HRESULT GetToRemCoActivateObject(
+ handle_t hRpc,
+ WCHAR *pwszProtseq,
+ const GUID *guidThreadId,
+ const GUID *pclsid,
+ DWORD grfMode,
+ WCHAR *pwszPath,
+ InterfaceData *pIFDstg,
+ DWORD dwTIDCaller,
+ DWORD *pdwTIDCallee,
+ InterfaceData **ppIFD,
+ InterfaceData *pIFDFromROT,
+ error_status_t *prpcstat)
+{
+ // Result from call
+ HRESULT hr;
+
+ // Make a parameter packet suitable for passing to the channel
+ DWORD cbPath = CbFromWideString(pwszPath);
+ DWORD cbIFD = CbFromInterfaceData(pIFDstg);
+
+ SOSActivateObj *posactobj = new(cbPath, cbIFD)
+ SOSActivateObj(CallObjSrvActivateObject, CALLCAT_SYNCHRONOUS,
+ pwszPath, cbPath, pIFDstg, cbIFD);
+
+ if (posactobj == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // This call is actually a combination of a number of calls and so
+ // gets the category of the weakest.
+
+ posactobj->hRpc = hRpc;
+ posactobj->clsid = *pclsid;
+ posactobj->grfMode = grfMode;
+ // posactobj->pwszPath set above
+ // posactobj->pIFDstg set above
+ posactobj->pIFDunk = NULL;
+ posactobj->pIFDFromROT = pIFDFromROT;
+ posactobj->dwTIDCaller = GetCurrentThreadId();
+
+ // Let the channel handle the work of getting this on the right thread
+ hr = CChannelControl::GetOffCOMThread((STHREADCALLINFO **) &posactobj);
+
+ if (SUCCEEDED(hr))
+ {
+ *ppIFD = posactobj->pIFDunk;
+ }
+
+ if (hr != RPC_E_CALL_CANCELED)
+ delete posactobj;
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetToRemCoCreateObject
+//
+// Synopsis: Dispatch RemCoCreateObject to object server via call control
+//
+// Arguments: [hRpc] - RPC handle
+// [pclsid] - class id
+// [grfMode] - mode for loading if file name supplied
+// [pwszPathFrom] - path to file to use for create
+// [pIFDstgFrom] - IStorage to use for new object
+// [pwszPath] - new path to the object
+// [dwTIDCaller] - caller's thread id
+// [pdwTIDCallee] - place holder for callee's thread id
+// [ppIFD] - where to put marshaled interface to the object
+//
+// Returns: S_OK - object successfully instantiated
+// Other - call failed.
+//
+// Algorithm: Build packet for dispatching call and then call RPC
+// to get the call dispatched.
+//
+// History: 06-Jun-95 Ricksa Created.
+//
+// Notes: This exists to get the call control in the loop between
+// the client and server since this call in Chicago is actually
+// between the client and the server.
+//
+//--------------------------------------------------------------------------
+HRESULT GetToRemCoCreateObject(
+ handle_t hRpc,
+ WCHAR *pwszProtseq,
+ const GUID *guidThreadId,
+ const GUID *pclsid,
+ DWORD grfMode,
+ WCHAR *pwszPathFrom,
+ InterfaceData *pIFDstgFrom,
+ WCHAR *pwszPath,
+ DWORD dwTIDCaller,
+ DWORD *pdwTIDCallee,
+ InterfaceData **ppIFD,
+ error_status_t *prpcstat)
+{
+ // Result from call
+ HRESULT hr;
+
+ // Make a parameter packet suitable for passing to the channel
+ DWORD cbPath = CbFromWideString(pwszPathFrom);
+ DWORD cbIFD = CbFromInterfaceData(pIFDstgFrom);
+ DWORD cbNewName = CbFromWideString(pwszPath);
+
+ SOSCreateObj *poscrtobj = new(cbPath, cbIFD, cbNewName)
+ SOSCreateObj(CallObjSrvCreateObject, CALLCAT_SYNCHRONOUS,
+ pwszPathFrom, cbPath, pIFDstgFrom, cbIFD, pwszPath, cbNewName);
+
+ if (poscrtobj == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // This call is actually a combination of a number of calls and so
+ // gets the category of the weakest.
+
+ poscrtobj->hRpc = hRpc;
+ poscrtobj->clsid = *pclsid;
+ poscrtobj->dwMode = grfMode;
+ // poscrtobj->pwszPath set above
+ // poscrtobj->pIFDstg set above
+ // poscrtobj->pwszNewName set above
+ poscrtobj->pIFDunk = NULL;
+
+ poscrtobj->dwTIDCaller = GetCurrentThreadId();
+
+ // Let the channel handle the work of getting this on the right thread
+ hr = CChannelControl::GetOffCOMThread((STHREADCALLINFO **)&poscrtobj);
+
+ if (SUCCEEDED(hr))
+ {
+ *ppIFD = poscrtobj->pIFDunk;
+ }
+
+ if (hr != RPC_E_CALL_CANCELED)
+ {
+ delete poscrtobj;
+ }
+
+ return hr;
+}
+
+
+
+#endif // _CHICAGO_
diff --git a/private/ole32/com/objact/rrace.hxx b/private/ole32/com/objact/rrace.hxx
new file mode 100644
index 000000000..f60e2a25e
--- /dev/null
+++ b/private/ole32/com/objact/rrace.hxx
@@ -0,0 +1,23 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: rrace.hxx
+//
+// Contents: Temporary classes/methods for getting rid of ROT/object
+// instantiation race.
+//
+// Classes: CRotRaceEntry
+// CRotRaceList
+//
+// Functions: CRotRaceEntry::CRotRaceAs
+//
+// History: 25-Aug-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+// 21-Jun-94 BruceMa Check allocated memory pointer
+// 20-Oct-94 BillMo Not used - this can be deleted
+//
+//--------------------------------------------------------------------------
+
+
diff --git a/private/ole32/com/objact/smstg.cxx b/private/ole32/com/objact/smstg.cxx
new file mode 100644
index 000000000..78c2ca7c8
--- /dev/null
+++ b/private/ole32/com/objact/smstg.cxx
@@ -0,0 +1,129 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: smstg.cxx
+//
+// Contents: Implementation for class to handle marshaled data as stg.
+//
+// Functions: CSafeMarshaledStg::CSafeMarshaledStg
+// CSafeMarshaledStg::~CSafeMarshaledStg
+// CSafeStgMarshaled::CSafeStgMarshaled
+// CSafeStgMarshaled::~CSafeStgMarshaled
+//
+// History: 14-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+
+#include <xmit.hxx>
+#include <smstg.hxx>
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeMarshaledStg::CSafeMarshaledStg
+//
+// Synopsis: Create an IStorage from a marshaled buffer
+//
+// Arguments: [pIFD] - marshaled interface pointer
+//
+// Algorithm: If pointer is not NULL, then unmarshal the interface.
+// If the interface cannot be unmarshaled throw an error.
+//
+// History: 14-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CSafeMarshaledStg::CSafeMarshaledStg(InterfaceData *pIFD, HRESULT&hr)
+ : _pstg(NULL)
+{
+ if (pIFD != NULL)
+ {
+ // Turn raw marshaled data into a stream
+ CXmitRpcStream xrpc(pIFD);
+
+
+ // Unmarshal data into an interface
+ hr = CoUnmarshalInterface(&xrpc, IID_IStorage, (void **) &_pstg);
+ }
+ else
+ {
+ hr = S_OK;
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeMarshaledStg::~CSafeMarshaledStg
+//
+// Synopsis: Release an IStorage that this class created
+//
+// History: 14-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CSafeMarshaledStg::~CSafeMarshaledStg(void)
+{
+ if (_pstg)
+ {
+ _pstg->Release();
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeStgMarshaled::CSafeStgMarshaled
+//
+// Synopsis: Create a marshaled interface from an IStorage
+//
+// Arguments: [pstg] - IStorage to marshal
+//
+// History: 14-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CSafeStgMarshaled::CSafeStgMarshaled(IStorage *pstg, DWORD dwDestCtx, HRESULT& hr)
+ : _pIFD(NULL)
+{
+ if (pstg != NULL)
+ {
+ // Turn raw interface into marshaled data
+ CXmitRpcStream xrpc;
+
+ if (SUCCEEDED(hr = CoMarshalInterface(&xrpc, IID_IStorage, pstg,
+ dwDestCtx, NULL, MSHLFLAGS_NORMAL)))
+ {
+ // Hand of the serialized interface so we can use it
+ xrpc.AssignSerializedInterface(&_pIFD);
+ }
+ }
+ else
+ {
+ hr = S_OK;
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeStgMarshaled::~CSafeStgMarshaled
+//
+// Synopsis: Release marshaled data
+//
+// History: 14-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CSafeStgMarshaled::~CSafeStgMarshaled(void)
+{
+ if (_pIFD)
+ {
+ delete _pIFD;
+ }
+}
diff --git a/private/ole32/com/objact/smstg.hxx b/private/ole32/com/objact/smstg.hxx
new file mode 100644
index 000000000..7a7769480
--- /dev/null
+++ b/private/ole32/com/objact/smstg.hxx
@@ -0,0 +1,179 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: smstg.hxx
+//
+// Contents: Declaration for class to handle marshaled data as stg.
+//
+// Classes: CSafeMarshaledStg
+// CSafeStgMarshaled
+//
+// Functions: CSafeMarshaledStg::operator->
+// CSafeMarshaledStg::IStorage*
+// CSafeStgMarshaled::operator->
+// CSafeStgMarshaled::IStorage*
+//
+// History: 14-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __SMSTG_HXX__
+#define __SMSTG_HXX__
+
+#include <iface.h>
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSafeMarshaledStg (smstg)
+//
+// Purpose: Handle bookkeeping of translating a marshaled buffer into
+// and IStorage
+//
+// Interface: operator-> - make class act like a pointer to an IStorage
+// operator IStorage* - convert object into ptr to IStorage
+//
+// History: 14-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CSafeMarshaledStg
+{
+public:
+ CSafeMarshaledStg(InterfaceData *pIFD, HRESULT& hr);
+
+ ~CSafeMarshaledStg(void);
+
+ IStorage * operator->(void);
+
+ operator IStorage*(void);
+
+private:
+
+ IStorage * _pstg;
+
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeMarshaledStg::operator->
+//
+// Synopsis: Make object act like a pointer to an IStorage
+//
+// History: 14-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline IStorage *CSafeMarshaledStg::operator->(void)
+{
+ return _pstg;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeMarshaledStg::operator IStorage*
+//
+// Synopsis: Convert object to pointer to IStorage
+//
+// History: 14-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CSafeMarshaledStg::operator IStorage*(void)
+{
+ return _pstg;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSafeStgMarshaled
+//
+// Purpose: Handle bookkeeping of creating a marshaled buffer from
+// and IStorage
+//
+// Interface: operator-> - make class act like a pointer to marshaled data
+// operator IStorage* - convert object into ptr to marshaled data
+//
+// History: 14-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CSafeStgMarshaled
+{
+public:
+ CSafeStgMarshaled(IStorage *pstg, DWORD dwDestCtx, HRESULT& hr);
+
+ ~CSafeStgMarshaled(void);
+
+ InterfaceData *operator->(void);
+
+ operator InterfaceData*(void);
+
+#ifdef DCOM
+ operator MInterfacePointer *(void);
+#endif
+
+private:
+
+ InterfaceData *_pIFD;
+
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeStgMarshaled::operator->
+//
+// Synopsis: Make object into pointer to the marshal buffer
+//
+// History: 14-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline InterfaceData *CSafeStgMarshaled::operator->(void)
+{
+ return _pIFD;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeStgMarshaled::operator InterfaceData*
+//
+// Synopsis: Convert object to pointer to marshal buffer
+//
+// History: 14-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CSafeStgMarshaled::operator InterfaceData*(void)
+{
+ return _pIFD;
+}
+
+
+
+#ifdef DCOM
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeStgMarshaled::operator MInterfacePointer*
+//
+// Synopsis: Convert object to pointer to marshal buffer
+//
+// History: 14-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CSafeStgMarshaled::operator MInterfacePointer*(void)
+{
+ return (MInterfacePointer *) _pIFD;
+}
+#endif // DCOM
+
+#endif // __SMSTG_HXX__
diff --git a/private/ole32/com/objact/sobjact.cxx b/private/ole32/com/objact/sobjact.cxx
new file mode 100644
index 000000000..1302623e5
--- /dev/null
+++ b/private/ole32/com/objact/sobjact.cxx
@@ -0,0 +1,780 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: sobjact.cxx
+//
+// Contents: Activation Functions used by object servers.
+//
+// Functions: CoRegisterClassObject
+// CoRevokeClassObject
+// CoAddRefServerProcess
+// CoReleaseServerProcess
+// CoSuspendClassObjects
+//
+// Classes: CObjServer
+//
+// History: 12-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include <iface.h>
+#include <olerem.h>
+
+#include "..\..\ole232\stdimpl\handler.hxx"
+
+#include "resolver.hxx"
+#include "smstg.hxx"
+#include "objact.hxx"
+#include "service.hxx"
+#include <sobjact.hxx>
+#include <comsrgt.hxx>
+
+CObjServer *gpMTAObjServer = NULL;
+
+extern INTERNAL CreateCommonDdeWindow(void);
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoRegisterClassObject, public
+//
+// Synopsis: Register a class object in the requested context
+//
+// Arguments: [rclsid] - class ID
+// [pUnk] - class object
+// [dwContext] - context to register it in
+// [flags] - single/multiple use.
+// [lpdwRegister] - registration cookie
+//
+// Returns: S_OK - object is successfully registered
+//
+// Algorithm: Validate the parmeters. The get the class factory interface.
+// Then add the class object to the list and finally notify
+// the SCM that the service is started.
+//
+// History: 12-May-93 Ricksa Created
+// 26-Jul-94 AndyH #20843 - restarting OLE in the shared WOW
+//
+//--------------------------------------------------------------------------
+STDAPI CoRegisterClassObject(
+ REFCLSID rclsid,
+ IUnknown FAR* pUnk,
+ DWORD dwContext,
+ DWORD flags,
+ LPDWORD lpdwRegister)
+{
+ HRESULT hr;
+#ifdef WX86OLE
+ BOOL fContextArgBad;
+#endif
+
+ OLETRACEIN((API_CoRegisterClassObject,
+ PARAMFMT("rclsid= %I, pUnk= %p, dwContext= %x, flags= %x, lpdwRegister= %p"),
+ &rclsid, pUnk, dwContext, flags, lpdwRegister));
+
+ TRACECALL(TRACE_ACTIVATION, "CoRegisterClassObject");
+
+ if (!IsApartmentInitialized())
+ {
+ hr = CO_E_NOTINITIALIZED;
+ goto errRtn;
+ }
+
+ // Validate the out parameter
+ if (!IsValidPtrOut(lpdwRegister, sizeof(DWORD)))
+ {
+ CairoleAssert(IsValidPtrOut(lpdwRegister, sizeof(DWORD)) &&
+ "CoRegisterClassObject invalid registration ptr");
+ hr = E_INVALIDARG;
+ goto errRtn;
+ }
+ *lpdwRegister = 0;
+
+ // Validate the pUnk
+ if (!IsValidInterface(pUnk))
+ {
+ CairoleAssert(IsValidInterface(pUnk) &&
+ "CoRegisterClassObject invalid pUnk");
+ hr = E_INVALIDARG;
+ goto errRtn;
+ }
+
+ // Hook the pUnk
+ CALLHOOKOBJECT(S_OK,rclsid,IID_IClassFactory,&pUnk);
+
+ // Validate context flags
+#ifdef WX86OLE
+ if (gcwx86.IsWx86Enabled())
+ {
+ fContextArgBad = (dwContext & (~(CLSCTX_ALL | CLSCTX_INPROC_SERVER16 |
+ CLSCTX_INPROC_SERVERX86) |
+ CLSCTX_INPROC_HANDLER |
+ CLSCTX_INPROC_HANDLERX86));
+ } else {
+ fContextArgBad = (dwContext & (~(CLSCTX_ALL | CLSCTX_INPROC_SERVER16)
+ | CLSCTX_INPROC_HANDLER));
+ }
+ if (fContextArgBad)
+#else
+ if ((dwContext & (~(CLSCTX_ALL | CLSCTX_INPROC_SERVER16) |
+ CLSCTX_INPROC_HANDLER)) != 0)
+#endif
+ {
+ hr = E_INVALIDARG;
+ goto errRtn;
+ }
+
+ // Validate flag flags
+ if (flags > (REGCLS_SUSPENDED | REGCLS_MULTI_SEPARATE | REGCLS_SURROGATE))
+ {
+ hr = E_INVALIDARG;
+ goto errRtn;
+ }
+
+ if ((flags & REGCLS_SURROGATE) && !(dwContext & CLSCTX_LOCAL_SERVER))
+ {
+ hr = E_INVALIDARG;
+ goto errRtn;
+ }
+
+#ifdef WX86OLE
+ if (flags & REGCLS_MULTIPLEUSE)
+ {
+ if (gcwx86.IsWx86Enabled())
+ {
+ if (dwContext & CLSCTX_INPROC_SERVERX86)
+ {
+ dwContext |= CLSCTX_INPROC_HANDLERX86 |
+ CLSCTX_INPROC_HANDLER;
+ } else {
+ dwContext |= CLSCTX_INPROC;
+ }
+ } else {
+ dwContext |= CLSCTX_INPROC;
+ }
+ }
+#else
+ if (flags & REGCLS_MULTIPLEUSE)
+ {
+ dwContext |= CLSCTX_INPROC;
+ }
+#endif
+
+ if (dwContext & CLSCTX_LOCAL_SERVER)
+ {
+ // thread safe incase we are in MultiThreaded model.
+ COleStaticLock lck(gmxsOleMisc);
+
+ // Make sure an instance of CObjServer exists for this thread.
+ // The SCM will call back on it to activate objects.
+
+ CObjServer *pObjServer = GetObjServer();
+
+ if (pObjServer == NULL)
+ {
+ COleTls Tls;
+
+ // no activation server for this apartment yet, go make one now.
+
+ HRESULT hr = E_OUTOFMEMORY;
+ pObjServer = new CObjServer(hr);
+
+ if (FAILED(hr))
+ {
+ delete pObjServer;
+ return hr;
+ }
+
+ // If we want to service OLE1 clients, we need to create the
+ // common Dde window now if it has not already been done.
+ if( !(Tls->dwFlags & OLETLS_DISABLE_OLE1DDE) )
+ {
+ CreateCommonDdeWindow();
+ }
+ }
+ }
+
+ // Put our object in the server table
+ hr = gdllcacheInprocSrv.RegisterServer(rclsid, pUnk,
+ flags, dwContext, lpdwRegister);
+
+errRtn:
+ OLETRACEOUT((API_CoRegisterClassObject, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoRevokeClassObject, public
+//
+// Synopsis: Revoke a previously registered class object
+//
+// Arguments: [dwRegister] - registration key returned from CoRegister...
+//
+// Returns: S_OK - class successfully deregistered.
+//
+// Algorithm: Ask cache to deregister the class object.
+//
+// History: 12-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDAPI CoRevokeClassObject(DWORD dwRegister)
+{
+ OLETRACEIN((API_CoRevokeClassObject, PARAMFMT("dwRegister= %x"), dwRegister));
+
+ TRACECALL(TRACE_ACTIVATION, "CoRevokeClassObject");
+
+ HRESULT hr = CO_E_NOTINITIALIZED;
+
+ if (IsApartmentInitialized())
+ {
+ // Try to revoke the object
+ hr = gdllcacheInprocSrv.Revoke(dwRegister);
+ }
+
+ OLETRACEOUT((API_CoRevokeClassObject, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoAddRefServerProcess, public
+//
+// Synopsis: Increments the global per-process server reference count.
+// See CDllCache::AddRefServerProcess for more detail.
+//
+// History: 17-Apr-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+STDAPI_(ULONG) CoAddRefServerProcess(void)
+{
+ return gdllcacheInprocSrv.AddRefServerProcess();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoReleaseServerProcess, public
+//
+// Synopsis: Decrements the global per-process server reference count.
+// See CDllCache::ReleaseServerProcess for more detail.
+//
+// History: 17-Apr-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+STDAPI_(ULONG) CoReleaseServerProcess(void)
+{
+ return gdllcacheInprocSrv.ReleaseServerProcess();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoSuspendClassObjects, public
+//
+// Synopsis: suspends all registered LOCAL_SERVER class objects for this
+// process so that no new activation calls from the SCM will
+// be accepted.
+//
+// History: 17-Apr-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+STDAPI CoSuspendClassObjects(void)
+{
+ return gdllcacheInprocSrv.SuspendProcessClassObjects();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoResumeClassObjects, public
+//
+// Synopsis: resumes all registered LOCAL_SERVER class objects for this
+// process that are currently marked as SUSPENDED, so that new
+// activation calls from the SCM will now be accepted.
+//
+// History: 17-Apr-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+STDAPI CoResumeClassObjects(void)
+{
+ return gdllcacheInprocSrv.ResumeProcessClassObjects();
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CObjServer::CObjServer, public
+//
+// Synopsis: construction
+//
+// History: 10 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+CObjServer::CObjServer(HRESULT &hr)
+{
+ _hr = MarshalInternalObjRef(_objref, IID_IObjServer,
+ (IObjServer*) this, MSHLFLAGS_NOPING, NULL);
+ if (SUCCEEDED(_hr))
+ {
+ SetObjServer(this);
+ }
+
+ hr = _hr;
+
+ ComDebOut((DEB_ACTIVATE, "CObjServer::CObjServer _hr:%x\n", _hr));
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CObjServer::~CObjServer, public
+//
+// Synopsis: dtor for activation object
+//
+// History: 19 Jun 95 Rickhi Created
+//
+//--------------------------------------------------------------------
+CObjServer::~CObjServer()
+{
+ if (SUCCEEDED(_hr))
+ {
+ // only do RMD if the marshall was sucessfull
+ SetObjServer(NULL);
+ _hr = ReleaseMarshalObjRef(_objref);
+ Win4Assert(SUCCEEDED(_hr));
+ FreeObjRef(_objref);
+ }
+
+ ComDebOut((DEB_ACTIVATE, "CObjServer::~CObjServer _hr:%x\n", _hr));
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CObjServer::AddRef, public
+//
+// Synopsis: we dont refcnt this object so this is a noop
+//
+// History: 10 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+ULONG CObjServer::AddRef(void)
+{
+ return 1;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CObjServer::Release, public
+//
+// Synopsis: we dont refcnt this object so this is a noop
+//
+// History: 10 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+ULONG CObjServer::Release(void)
+{
+ return 1;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CObjServer::QueryInterface, public
+//
+// Synopsis: returns supported interfaces
+//
+// History: 10 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CObjServer::QueryInterface(REFIID riid, void **ppv)
+{
+ if (IsEqualIID(riid, IID_IObjServer) || // more common than IUnknown
+ IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppv = (IObjServer *) this;
+ AddRef();
+ return S_OK;
+ }
+
+ *ppv = NULL;
+ return E_NOINTERFACE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: ObjactThreadUninitialize
+//
+// Synopsis: Cleans up the CObjServer object
+//
+// History: 10 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+STDAPI_(void) ObjactThreadUninitialize(void)
+{
+ CObjServer *pObjServer = GetObjServer();
+ if (pObjServer != NULL)
+ {
+ delete pObjServer;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CObjServer::ObjectServerGetClassObject
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CObjServer::ObjectServerGetClassObject(
+ const GUID *guidCLSID,
+ IID *pIID,
+ BOOL fSurrogate,
+ MInterfacePointer **ppIFD,
+ DWORD * pStatus )
+{
+ ComDebOut((DEB_ACTIVATE,
+ "CObjServer::ObjectServerGetClassObject clsid:%I\n", &guidCLSID));
+
+ *pStatus = RPC_S_OK;
+
+ // Check access.
+ if (!CheckObjactAccess())
+ {
+ return HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
+ }
+
+ HRESULT hr;
+ IUnknown *pcf;
+
+ // Get the class object
+#ifdef WX86OLE
+ hr = gdllcacheInprocSrv.GetClass(*guidCLSID, *pIID, FALSE, TRUE, fSurrogate, FALSE, &pcf);
+#else
+ hr = gdllcacheInprocSrv.GetClass(*guidCLSID, *pIID, FALSE, TRUE, fSurrogate, &pcf);
+#endif
+
+ if (pcf)
+ {
+ // We got the class object, create a buffer and marshal it for return.
+ // Marshal it NORMAL and turn on the NotifyActivation flag so we can
+ // add an implicit LockServer during marshaling to plug inherent races
+ // in the IClassFactory protocol.
+
+ hr = MarshalHelper(pcf, *pIID,
+ MSHLFLAGS_NORMAL | MSHLFLAGS_NOTIFYACTIVATION,
+ (InterfaceData**) ppIFD);
+ }
+ else
+ {
+ // If we get a NULL, this means that we have
+ // recieved the request after we have decided
+ // to stop, so we tell the caller we are stopping
+ // so they can start a new copy of the server.
+ if ( hr == S_OK )
+ hr = CO_E_SERVER_STOPPING;
+ }
+
+ ComDebOut((DEB_ACTIVATE,
+ "CObjServer::ObjectServerGetClassObject hr:%x\n", hr));
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CObjServer::ObjectServerCreateInstance
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CObjServer::ObjectServerCreateInstance(
+ /* [in] */ const GUID *rclsid,
+ /* [in] */ DWORD dwInterfaces,
+ /* [size_is][in] */ IID *pIIDs,
+ /* [size_is][out] */ MInterfacePointer **ppIFDs,
+ /* [size_is][out] */ HRESULT *pResults,
+ /* [out] */ DWORD * pStatus )
+{
+ ComDebOut((DEB_ACTIVATE,
+ "CObjServer::ObjectServerCreateInstance clsid:%I\n", rclsid));
+
+ *pStatus = RPC_S_OK;
+
+ // Check access.
+ if (!CheckObjactAccess())
+ {
+ return HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
+ }
+
+ HRESULT hr;
+ IUnknown *pcf;
+
+ // Get the class object
+#ifdef WX86OLE
+ hr = gdllcacheInprocSrv.GetClass(*rclsid, IID_IClassFactory, FALSE, TRUE, FALSE, FALSE, &pcf);
+#else
+ hr = gdllcacheInprocSrv.GetClass(*rclsid, IID_IClassFactory, FALSE, TRUE, FALSE, &pcf);
+#endif
+
+ if (pcf)
+ {
+ // first, check if the server is willing to accept the incoming call
+ // on IClassFactory. The reason we need this is that EXCEL's message
+ // filter rejects calls on IID_IClassFactory if it is busy. They dont
+ // know about IID_IObjServer.
+ hr = HandleIncomingCall(IID_IClassFactory, 3,
+ CALLCAT_SYNCHRONOUS,
+ (void *)pcf);
+
+ if (SUCCEEDED(hr))
+ {
+ // Load the object
+ hr = GetInstanceHelperMulti((IClassFactory *)pcf, dwInterfaces, pIIDs,
+ ppIFDs, pResults, NULL);
+ }
+ pcf->Release();
+ }
+ else
+ {
+ // If we get a NULL, this means that we have
+ // recieved the request after we have decided
+ // to stop, so we tell the caller we are stopping
+ // so they can start a new copy of the server.
+ if ( hr == S_OK )
+ hr = CO_E_SERVER_STOPPING;
+ }
+
+ ComDebOut((DEB_ACTIVATE,
+ "CObjServer::ObjectServerCreateInstance hr:%x\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CObjServer::ObjectServerGetInstance
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CObjServer::ObjectServerGetInstance(
+ /* [in] */ const GUID *rclsid,
+ /* [in] */ DWORD grfMode,
+ /* [unique][string][in] */ WCHAR *pwszPath,
+ /* [unique][in] */ MInterfacePointer *pIFDstg,
+ /* [in] */ DWORD Interfaces,
+ /* [size_is][in] */ IID *pIIDs,
+ /* [unique][in] */ MInterfacePointer *pIFDFromROT,
+ /* [size_is][out] */ MInterfacePointer **ppIFDs,
+ /* [size_is][out] */ HRESULT *pResults,
+ /* [out] */ DWORD * pStatus )
+{
+ HRESULT hr = S_OK;
+
+ *pStatus = RPC_S_OK;
+
+ // Check access.
+ if (!CheckObjactAccess())
+ {
+ return HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
+ }
+
+ if (pIFDFromROT != NULL)
+ {
+ // If the SCM has passed us an object from the ROT, we
+ // try to use that first by unmarshalling it and then
+ // marshaling it normal.
+ CXmitRpcStream xrpcForUnmarshal((InterfaceData*)pIFDFromROT);
+ IUnknown *punk;
+
+ hr = CoUnmarshalInterface(&xrpcForUnmarshal, IID_IUnknown,
+ (void **) &punk);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = E_NOINTERFACE;
+
+ for ( DWORD i = 0; i < Interfaces; i++ )
+ {
+ // Stream to put marshaled interface in
+ CXmitRpcStream xrpc;
+ HRESULT hr2;
+
+ // use DIFFERENTMACHINE so we get the long form OBJREF
+ hr2 = CoMarshalInterface(&xrpc, pIIDs[i], punk,
+ MSHCTX_DIFFERENTMACHINE, NULL, MSHLFLAGS_NORMAL);
+
+ if (SUCCEEDED(hr2))
+ {
+ // Report OK if any interface is found.
+ hr = hr2;
+ xrpc.AssignSerializedInterface((InterfaceData **) &ppIFDs[i]);
+ }
+ pResults[i] = hr2;
+ }
+ // Don't need the unknown ptr any more
+ punk->Release();
+
+ return hr;
+ }
+
+ // Assume any errors are the result of a stale entry in the ROT
+ // so we just fall into the regular code path from here.
+ hr = S_OK;
+ }
+
+ CSafeMarshaledStg smstg( (InterfaceData*) pIFDstg, hr);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // Get the class object
+ IUnknown *pcf = NULL;
+#ifdef WX86OLE
+ hr = gdllcacheInprocSrv.GetClass(*rclsid, IID_IClassFactory, FALSE, TRUE, FALSE, FALSE, &pcf);
+#else
+ hr = gdllcacheInprocSrv.GetClass(*rclsid, IID_IClassFactory, FALSE, TRUE, FALSE, &pcf);
+#endif
+
+ if (pcf)
+ {
+ // first, check if the server is willing to accept the incoming call
+ // on IClassFactory. The reason we need this is that EXCEL's message
+ // filter rejects calls on IID_IClassFactory if it is busy. They dont
+ // know about IID_IObjServer.
+ hr = HandleIncomingCall(IID_IClassFactory, 3,
+ CALLCAT_SYNCHRONOUS,
+ (void *)pcf);
+
+ if (SUCCEEDED(hr))
+ {
+ // Load the object
+ hr = GetObjectHelperMulti((IClassFactory *)pcf, grfMode, NULL,
+ pwszPath, smstg, Interfaces, pIIDs, ppIFDs, pResults, NULL);
+ }
+ pcf->Release();
+ }
+ else
+ {
+ // If we get a NULL, this means that we have
+ // recieved the request after we have decided
+ // to stop, so we tell the caller we are stopping
+ // so they can start a new copy of the server.
+ if ( hr == S_OK )
+ hr = CO_E_SERVER_STOPPING;
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CObjServer::ObjectServerLoadDll
+//
+// Synopsis: Loads the requested dll into a surrogate process which
+// implements the ISurrogate interface
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CObjServer::ObjectServerLoadDll(
+ /* [in] */ const GUID *rclsid,
+ /* [out] */ DWORD* pStatus)
+{
+ ComDebOut((DEB_ACTIVATE, "ObjectServerLoadDll clsid:%I\n", rclsid));
+
+ *pStatus = RPC_S_OK;
+
+ HRESULT hr = CCOMSurrogate::LoadDllServer(*rclsid);
+
+ ComDebOut((DEB_ACTIVATE, "ObjectServerLoadDll hr:%x\n", hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: NotifyActivation
+//
+// Synopsis: Add/Remove implicit IClassFactory::LockServer during marshal
+// and last external release of an interface pointer.
+//
+// Arguments: [fLock] - whether to Lock or Unlock
+// [pUnk] - ptr to object interface
+//
+// Returns: TRUE - call again during last release
+// FALSE - dont call again during last release
+//
+// History: 12-May-96 RickHi Created
+//
+// Notes: there is an inherent race condition in the IClassFactory (and
+// derived interfaces) in that between the time a client gets the
+// ICF pointer and the time they call LockServer(TRUE), a server could
+// shut down. In order to plug this hole, COM's activation code will
+// attempt to do an implicit LockServer(TRUE) on the server side of
+// CoGetClassObject during the marshaling of the class object
+// interface. Since we dont know for sure that it is IClassFactory
+// being marshaled, we QI for it here.
+//
+//--------------------------------------------------------------------------
+INTERNAL_(BOOL) NotifyActivation(BOOL fLock, IUnknown *pUnk)
+{
+ ComDebOut((DEB_ACTIVATE, "NotifyActivation fLock:%x pUnk:%x\n", fLock, pUnk));
+
+ // If the object supports IClassFactory, do an implicit LockServer(TRUE)
+ // on behalf of the client when the interface is first marshaled by
+ // CoGetClassObject. When the last external reference to the interface is
+ // release, do an implicit LockServer(FALSE).
+
+ IClassFactory *pICF = NULL;
+ if (SUCCEEDED(pUnk->QueryInterface(IID_IClassFactory, (void **)&pICF)))
+ {
+ pICF->LockServer(fLock);
+ pICF->Release();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoRegisterSurrogate, public
+//
+// Synopsis: Register an ISurrogate interface for a surrogate process
+//
+// Arguments: [pSurrogate] - existing ISurrogate interface ponter
+//
+// Returns: S_OK - object is successfully registered
+//
+// Algorithm: Validate the parameter. Then set a global pointer to the
+// value of the pSurrogate parameter
+//
+// History: 2-Jun-96 t-AdamE Created
+//
+//--------------------------------------------------------------------------
+STDAPI CoRegisterSurrogate(ISurrogate* pSurrogate)
+{
+ HRESULT hr;
+
+ OLETRACEIN((API_CoRegisterSurrogate,
+ PARAMFMT("pSurrogate= %p"),
+ pSurrogate));
+
+ TRACECALL(TRACE_ACTIVATION, "CoRegisterSurrogate");
+
+ if (!IsApartmentInitialized())
+ {
+ hr = CO_E_NOTINITIALIZED;
+ goto errRtn;
+ }
+
+ // Validate the pSurrogate
+ if (!IsValidInterface(pSurrogate))
+ {
+ CairoleAssert(IsValidInterface(pSurrogate) &&
+ "CoRegisterSurrogate invalid pSurrogate");
+ hr = E_INVALIDARG;
+ goto errRtn;
+ }
+
+ hr = CCOMSurrogate::InitializeISurrogate(pSurrogate);
+
+errRtn:
+ OLETRACEOUT((API_CoRegisterSurrogate, hr));
+
+ return hr;
+}
+
diff --git a/private/ole32/com/objact/sobjact.hxx b/private/ole32/com/objact/sobjact.hxx
new file mode 100644
index 000000000..4e90a879a
--- /dev/null
+++ b/private/ole32/com/objact/sobjact.hxx
@@ -0,0 +1,133 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: sobjact.hxx
+//
+// Contents: class declaration for Object Server object
+//
+// Classes: CObjServer
+//
+// History: 12 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------------
+#ifndef _SOBJACT_HXX_
+#define _SOBJACT_HXX_
+
+#include <ole2int.h>
+#include <objsrv.h>
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CObjServer
+//
+// Purpose: Accept calls from the SCM on the IObjServer interface
+// to activate objects inside this apartment.
+//
+// History: 10 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------------
+class CObjServer : public IObjServer,
+ public CPrivAlloc
+{
+public:
+ CObjServer(HRESULT &hr);
+ ~CObjServer();
+
+ STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) ( void );
+ STDMETHOD_(ULONG,Release) ( void );
+
+ STDMETHOD (ObjectServerGetClassObject)(
+ /* [in] */ const GUID *rclsid,
+ /* [in] */ IID *pIID,
+ /* [in] */ BOOL fSurrogate,
+ /* [out] */ MInterfacePointer **ppIFD,
+ /* [out] */ DWORD *pStatus );
+
+ STDMETHOD (ObjectServerCreateInstance)(
+ /* [in] */ const GUID *rclsid,
+ /* [in] */ DWORD Interfaces,
+ /* [size_is][in] */ IID *pIIDs,
+ /* [size_is][out] */ MInterfacePointer **ppIFDs,
+ /* [size_is][out] */ HRESULT *pResults,
+ /* [out] */ DWORD *pStatus );
+
+ STDMETHOD (ObjectServerGetInstance)(
+ /* [in] */ const GUID *rclsid,
+ /* [in] */ DWORD grfMode,
+ /* [unique][string][in] */ WCHAR *pwszPath,
+ /* [unique][in] */ MInterfacePointer *pIFDstg,
+ /* [in] */ DWORD Interfaces,
+ /* [size_is][in] */ IID *pIIDs,
+ /* [unique][in] */ MInterfacePointer *pIFDFromROT,
+ /* [size_is][out] */ MInterfacePointer **ppIFD,
+ /* [size_is][out] */ HRESULT *pResults,
+ /* [out] */ DWORD *pStatus );
+
+ STDMETHOD (ObjectServerLoadDll)(
+ /* [in] */ const GUID *rclsid,
+ /* [out] */ DWORD *pStatus);
+
+ IPID GetIPID() { return _objref.u_objref.u_standard.std.ipid; }
+ OXID GetOXID() { return _objref.u_objref.u_standard.std.oxid; }
+
+private:
+
+ OBJREF _objref; // objref for this object
+ HRESULT _hr; // result of the marshal
+};
+
+extern ISurrogate* g_pSurrogate;
+
+// holder for CObjServer for the MultiThreaded apartment. For single-threaded
+// apartments we store it in TLS.
+
+extern CObjServer *gpMTAObjServer;
+
+//+-------------------------------------------------------------------
+//
+// Function: GetObjServer
+//
+// Synopsis: Get the TLS or global object server based on the
+// threading model in use on this thread.
+//
+// History: 24 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+inline CObjServer *GetObjServer()
+{
+ COleTls tls;
+
+ if (tls->dwFlags & OLETLS_APARTMENTTHREADED)
+ return tls->pObjServer;
+
+ return gpMTAObjServer;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: SetObjServer
+//
+// Synopsis: Set the TLS or global object server based on the
+// threading model in use on this thread.
+//
+// History: 24 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+inline void SetObjServer( CObjServer *pObjServer )
+{
+ COleTls tls;
+
+ if (tls->dwFlags & OLETLS_APARTMENTTHREADED)
+ {
+ tls->pObjServer = pObjServer;
+ return;
+ }
+
+ gpMTAObjServer = pObjServer;
+}
+
+#endif // _SOBJACT_HXX_
diff --git a/private/ole32/com/objact/treat.cxx b/private/ole32/com/objact/treat.cxx
new file mode 100644
index 000000000..079335591
--- /dev/null
+++ b/private/ole32/com/objact/treat.cxx
@@ -0,0 +1,152 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: treat.cxx
+//
+// Contents: Methods for classes implementing Treat as cach
+//
+// Functions:
+// CTreatList::CTreatList
+// CTreatList::~CTreatList
+// CTreatList::GetTreatAs
+//
+// History: 08-Jun-93 Ricksa Created
+// 09-Jun-94 BruceMa Check new pointers
+// 20-Oct-94 BillMo Fixed init bugs for new skip lists
+// 05-Jan-95 BillMo Removed notification stuff for Chicago
+// 12-Oct-95 MurthyS Use array instead of skip list
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include "objact.hxx"
+#include <scmmem.hxx>
+#include "treat.hxx"
+
+#define DWINITIALTREATLISTSIZE 16 // start with 16 and grow 16 at a time
+
+CTreatList *gptrtlstTreatClasses = NULL;
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTreatList::GetTreatAs
+//
+// Synopsis: Get the treat as class for a class
+//
+// Arguments: [rclsid] - class id to use as the key
+// [clsidout] - class id to use for implementation
+//
+// Returns: S_OK - class found
+//
+// Algorithm: Check the cache first. If we have found this
+// key before then use it. Otherwise, check the
+// registry for the key and cache it for future
+// requests.
+//
+// History: 08-Jun-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CTreatList::GetTreatAs(REFCLSID rclsid, CLSID& clsidOut)
+{
+ CairoleDebugOut((DEB_TRACE, "GetTreatAs: called for %I\n has %x entries", &rclsid, m_dwcentries));
+
+ // Search the cache to see if we have the object already
+ for (DWORD i = 0; i < m_dwcentries; i++)
+ {
+ STreatEntry *ptreat = (STreatEntry *) _GetAt(i);
+ if (InlineIsEqualGUID(ptreat->oclsid, rclsid))
+ {
+ clsidOut = ptreat->tclsid;
+ CairoleDebugOut((DEB_TRACE, "GetTreatAs: returned %I for %I (from cache)\n", &clsidOut, &rclsid));
+ return(S_OK);
+ }
+ }
+
+ // Look up data in the registry
+ HRESULT hr = CoGetTreatAsClass(rclsid, &clsidOut);
+
+ if (SUCCEEDED(hr))
+ {
+ // Create a new entry
+ CairoleDebugOut((DEB_TRACE, "GetTreatAs: adding treatas entry %I for %I\n", &clsidOut, &rclsid));
+ hr = S_OK;
+
+ STreatEntry treat;
+ treat.oclsid = rclsid;
+ treat.tclsid = clsidOut;
+
+ if (SetAtGrow(m_dwcentries, &treat))
+ {
+ m_dwcentries++;
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: GetTreatAs
+//
+// Synopsis: Look in the cache to get the treat as class for a class
+//
+// Arguments: [rclsid] - class id to use as the key
+// [clsidout] - class id to use for implementation
+//
+// Returns: S_OK - class found
+//
+// Algorithm: Check the cache first. If we have found this
+// key before then use it. Otherwise, check the
+// registry for the key and cache it for future
+// requests.
+//
+// History: 29-Oct-95 RickHi Delay creation of treat list.
+//
+//--------------------------------------------------------------------------
+INTERNAL GetTreatAs(REFCLSID rclsid, CLSID& clsidOut)
+{
+ COleStaticLock lck(gmxsOleMisc);
+
+ if (gptrtlstTreatClasses == NULL)
+ {
+ gptrtlstTreatClasses = new CTreatList(DWINITIALTREATLISTSIZE); // to start with
+
+ if (gptrtlstTreatClasses == NULL || !gptrtlstTreatClasses->CreatedOK())
+ {
+ delete gptrtlstTreatClasses;
+ gptrtlstTreatClasses = NULL;
+
+ CairoleDebugOut((DEB_ERROR, "GetTreatAs new TreatAs failed\n"));
+ return E_OUTOFMEMORY;
+ }
+ }
+
+ return gptrtlstTreatClasses->GetTreatAs(rclsid, clsidOut);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CleanupTreatAs
+//
+// Synopsis: Cleans up the TreatAs list.
+//
+// Arguments: none
+//
+// History: 29-Oct-95 RickHi Delay creation of treat list.
+//
+//--------------------------------------------------------------------------
+void CleanupTreatAs()
+{
+ COleStaticLock lck(gmxsOleMisc);
+
+ if (gptrtlstTreatClasses != NULL)
+ {
+ delete gptrtlstTreatClasses;
+ gptrtlstTreatClasses = NULL;
+ }
+}
diff --git a/private/ole32/com/objact/treat.hxx b/private/ole32/com/objact/treat.hxx
new file mode 100644
index 000000000..64a3da2ea
--- /dev/null
+++ b/private/ole32/com/objact/treat.hxx
@@ -0,0 +1,129 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: treat.hxx
+//
+// Contents: Class for caching treat as results to decrease
+// registery queries.
+//
+// Classes: STreatEntry
+// CTreatList
+//
+// Functions: CTreatEntry::CTreatAs
+// GetTreatAs
+//
+// History: 08-Jun-93 Ricksa Created
+// 05-Jan-95 BillMo Removed notification stuff for Chicago
+// 12-Oct-95 MurthyS Changed TreatAs cache to not use SkipList
+//
+//--------------------------------------------------------------------------
+#ifndef __TREAT_HXX__
+#define __TREAT_HXX__
+
+#include <olesem.hxx>
+#include <clskey.hxx>
+
+
+// function called by activation code to do the lookup.
+extern INTERNAL GetTreatAs(REFCLSID rclsid, CLSID& clsidOut);
+extern void CleanupTreatAs();
+
+//+-------------------------------------------------------------------------
+//
+// Structure: STreatEntry
+//
+// Purpose: Maintain XRef between treated class and class we use
+//
+// History: 12-Oct-95 MurthyS Rewrote TreatAs cache w/o skip lists
+//
+//--------------------------------------------------------------------------
+struct STreatEntry
+{
+ CLSID oclsid; // original CLSID
+ CLSID tclsid; // treat as CLSID
+};
+
+typedef struct STreatEntry * LPSTreatEntry;
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTreatList
+//
+// Purpose: Maintain list of cached XRefs between treated classes
+//
+// Interface: GetTreatAs - get treat as class
+//
+// History: 08-Jun-93 Ricksa Created
+// 12-Oct-95 MurthyS Now an array instead of skip list
+//
+// Notes: BUGBUG: We don't update this cache in the face of changes
+//
+//--------------------------------------------------------------------------
+class CTreatList : public CArrayFValue
+{
+public:
+ CTreatList(DWORD dwSize);
+ ~CTreatList();
+
+ HRESULT GetTreatAs(REFCLSID rclsid, CLSID& clsidOut);
+ BOOL CreatedOK(void);
+
+private:
+
+ // count of entries
+ DWORD m_dwcentries;
+};
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTreatList::CTreatList
+//
+// Synopsis: constructor for the class
+//
+// Arguments: [dwSize] - initial size of the list
+//
+// History: 12-Oct-95 MurthyS re-wrote
+//
+//--------------------------------------------------------------------------
+inline CTreatList::CTreatList(DWORD dwSize)
+ : CArrayFValue(sizeof(struct STreatEntry)), m_dwcentries(0)
+{
+ SetSize(dwSize, dwSize);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTreatList::~CTreatList
+//
+// Synopsis: destructor for the class
+//
+// Arguments: none
+//
+//--------------------------------------------------------------------------
+inline CTreatList::~CTreatList()
+{
+ // dtor of inherited class automatically frees the data
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTreatList::CreatedOk
+//
+// Synopsis: Indicate whether the initial construction worked.
+//
+// Returns: [TRUE] - initial construction worked
+// [FALSE] - initial construction failed
+//
+// History: 12-Oct-1995 MurthyS Created
+//
+// Notes: This should be called immediatedly after the construction
+// to see whether the constuctor really worked.
+//
+//--------------------------------------------------------------------------
+inline BOOL CTreatList::CreatedOK(void)
+{
+ return GetSize() != 0;
+}
+#endif // __TREAT_HXX__
diff --git a/private/ole32/com/precomp2.inc b/private/ole32/com/precomp2.inc
new file mode 100644
index 000000000..d13443649
--- /dev/null
+++ b/private/ole32/com/precomp2.inc
@@ -0,0 +1,20 @@
+#//+---------------------------------------------------------------
+#//
+#// File: precom2.inc
+#//
+#// Contents: directives for global precompiled include file when the
+#// sources file is two directories below com (or wherever
+#// this file is located). We could easily have precomp3 and
+#// precomp4 for other areas. The ole2int.* files should not
+#// otherwise be mentioned in the sources files.
+#//
+#// History: 18-May-94 CraigWi Created
+#//
+#//----------------------------------------------------------------
+
+PRECOMPILED_CXX=1
+PRECOMPILED_INCLUDE=..\..\inc\ole2int.h
+PRECOMPILED_TARGET=..\..\inc\$(GPCH_BUILD)\obj\*\com2int.pch
+PRECOMPILED_OPTION=/Yuole2int.h /Fp..\..\inc\$(GPCH_BUILD)\obj\*\com2int.pch
+PRECOMPILED_OBJ=..\..\inc\$(GPCH_BUILD)\obj\*\com2int.obj
+
diff --git a/private/ole32/com/remote/callcont.cxx b/private/ole32/com/remote/callcont.cxx
new file mode 100644
index 000000000..71def9dfb
--- /dev/null
+++ b/private/ole32/com/remote/callcont.cxx
@@ -0,0 +1,506 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: CallCont.cxx (32 bit target)
+//
+// Contents: Contains the CallControl interface
+//
+// Functions:
+//
+// History: 23-Dec-93 Johann Posch (johannp) Created
+//
+// CODEWORK: probably does not need to be an OLE-style interface
+//
+//--------------------------------------------------------------------------
+
+#include <ole2int.h>
+#include "callcont.hxx"
+#include "callmain.hxx"
+#include <olespy.hxx>
+
+
+COleStaticMutexSem sgmxs; // protects CoRegisterMessageFilter & CoGetCallControll
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CCallControl
+//
+// Synopsis: interface between channels and call main control
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+class CCallControl : public ICallControl
+{
+public:
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) ;
+ STDMETHOD_(ULONG,AddRef) (THIS) ;
+ STDMETHOD_(ULONG,Release) (THIS) ;
+
+ // *** ICallControl methods ***
+ STDMETHOD (CallRunModalLoop) (THIS_ PCALLDATA pCalldata) ;
+ STDMETHOD (SetCallState) (THIS_ PCALLDATA pCalldata,
+ SERVERCALLEX ServerCall,
+ SCODE scode);
+ STDMETHOD (HandleDispatchCall) (THIS_ DWORD TIDCaller, REFLID lid,
+ PINTERFACEINFO32 pIfInfo,
+ PDISPATCHDATA pDispatchData) ;
+ STDMETHOD (ModalLoopBlockFunction) (THIS_ );
+
+ CCallControl(PORIGINDATA pOrigindata, CCallMainControl &rCMC, HRESULT *phr);
+ ~CCallControl();
+
+private:
+ ULONG _refs; // reference count
+ BOOL _fReg; // TRUE if we registered OD with CMC.
+
+ CCallMainControl &_CMC; // pointer to call main controller
+ ORIGINDATA _OD; // origin data
+};
+
+#ifdef _CHICAGO_
+HRESULT StackSwitch (CCallMainControl *pCMC, CCallInfo *pCallInfo);
+
+HRESULT StackSwitch(CCallMainControl *pCMC, CCallInfo *pCallInfo)
+{
+ HRESULT hres;
+ StackDebugOut((DEB_STCKSWTCH, "SSCallRunModalLoop 32->16 : CMC(%x), pCallInfo(%x)\n", pCMC,pCallInfo));
+ hres = pCMC->TransmitAndRunModalLoop(pCallInfo);
+ StackDebugOut((DEB_STCKSWTCH, "SSCallRunModalLoop 32<-16 back; hres:%ld\n", hres));
+ return hres;
+}
+#endif // _CHICAGO_
+
+//+-------------------------------------------------------------------------
+//
+// Method: CCallControl::QueryInterface
+//
+// Synopsis: query for a new interface
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CCallControl::QueryInterface (REFIID riid, LPVOID FAR* ppvObj)
+{
+ if (IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppvObj = (ICallControl *) this;
+ AddRef();
+ return S_OK;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CCallControl::AddRef
+//
+// Synopsis: increments reference count
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CCallControl::AddRef ()
+{
+ InterlockedIncrement( (long *) &_refs );
+ return _refs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CCallControl::Release
+//
+// Synopsis: decrements reference count
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CCallControl::Release ()
+{
+ ULONG refs = _refs - 1;
+
+ if (InterlockedDecrement( (long*) &_refs ) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return refs;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CCallControl::CallRunModalLoop
+//
+// Synopsis: dispatch an outgoing call and enter the modal loop
+//
+// Arguments: [pCalldata] - call info
+//
+// Returns:
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CCallControl::CallRunModalLoop (PCALLDATA pCalldata)
+{
+ TRACECALL(TRACE_CALLCONT, "CCallControl::CallRunModalLoop");
+ CairoleDebugOut((DEB_CALLCONT, "CCallControl::CallRunModalLoop"));
+ Win4Assert(pCalldata && pCalldata->id == CALLDATAID_UNUSED &&
+ "CallRunModalLoop - Invalid pCalldata.");
+ RpcSpy((CALLOUT_BEGIN, NULL, pCalldata->iid, pCalldata->iMethod, 0));
+
+ // check if we can call out
+ HRESULT hres = _CMC.CanMakeOutCall(pCalldata->CallCat, pCalldata->iid);
+
+ // CODEWORK: below, we transform CALLCAT_INTERNALSYNC calls into
+ // CALLCAT_INTERNALINPUTSYNC calls when processing an CALLCAT_INPUTSYNC
+ // call. The above routine takes that transformation into account. We
+ // should address the BUGBUG below and then if we keep the transformation,
+ // move it above the call to CanMakeOutCall and change CanMakeOutCall
+ // to not compensate for the transformation.
+
+ if (hres == S_OK)
+ {
+ // create callinfo
+ CCallInfo CallInfo(pCalldata, &_OD);
+ CALLTYPE ctSaved = _CMC.GetCallType();
+
+ // BUGBUG: RICKHI: do we really want to do this?
+ if ((_CMC.GetCallCatOfInCall() == CALLCAT_INPUTSYNC
+ || InSendMessage())
+ && pCalldata->CallCat == CALLCAT_INTERNALSYNC)
+ {
+ pCalldata->CallCat = CALLCAT_INTERNALINPUTSYNC;
+ }
+
+#ifdef _CHICAGO_
+ // Note: Switch to the 16 bit stack under WIN95.
+ if (SSONBIGSTACK())
+ {
+ CairoleDebugOut((DEB_CALLCONT, "In CallRunModalLoop: CMC(%x), pCallInfo(%x)\n", &_CMC,&CallInfo));
+ hres = SSCall(8, SSF_SmallStack, (LPVOID)StackSwitch, (DWORD)&_CMC, (DWORD) &CallInfo);
+ }
+ else
+ hres = _CMC.TransmitAndRunModalLoop(&CallInfo);
+#else
+ // call the modal loop
+ hres = _CMC.TransmitAndRunModalLoop(&CallInfo);
+#endif // _CHICAGO_
+
+ // reset the main call type
+ _CMC.SetCallType(ctSaved);
+ }
+
+ RpcSpy((CALLOUT_END, NULL, pCalldata->iid, pCalldata->iMethod, 0));
+ CairoleDebugOut((DEB_CALLCONT, "CallRunModalLoop returned: %ld\n", hres));
+ return hres;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CCallControl::SetCallState
+//
+// Synopsis: sets the state of the given call
+//
+// Arguments: [pCalldata] - call info
+// [ServerCall] - call state
+// [scode] - return code
+//
+// Returns: S_OK
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CCallControl::SetCallState (PCALLDATA pCalldata,
+ SERVERCALLEX ServerCall,
+ SCODE scode)
+{
+ TRACECALL(TRACE_CALLCONT, "CCallControl::SetCallState\n");
+ Win4Assert(pCalldata && "SetCallState - Invalid calldata.");
+ Win4Assert(ServerCall <= SERVERCALLEX_CANCELED && "SetCallState - Invalid SERVERCALLEX.");
+
+ PCALLINFO pCallInfo = _CMC.GetCIfromCallID(pCalldata->id);
+ Win4Assert(pCallInfo && "SetCallState - Invalid pCalldata->id");
+
+ pCallInfo->SetCallState((CallState) ServerCall, scode);
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CCallControl::HandleDispatchCall
+//
+// Synopsis: determine if the app can handle an incoming call, and if
+// so, dispatch the call
+//
+// Arguments: [TIDCaller] - threadid of the calling app
+// [lid] - logical threadid the call was made on
+// [pIfInfo] - call interface info
+// [pChannelData] - channel specific data
+//
+// Returns: RPC_E_SERVERCALL_REJECTED - call was rejected
+// RPC_E_SERVERCALL_RETRYLATER - call was rejected, retry later
+// S_OK - call succeeded
+// other - error from app
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CCallControl::HandleDispatchCall (DWORD TIDCaller,
+ REFLID lid,
+ PINTERFACEINFO32 pIfInfo,
+ PDISPATCHDATA pChannelData)
+{
+ TRACECALL(TRACE_CALLCONT, "CCallControl::HandleDispatchCall");
+ Win4Assert(pIfInfo && "HandleDispatchCall - Invalid pIfInfo.");
+ CairoleDebugOut((DEB_CALLCONT, "CCallControl::HandleDispatchCall TIDCaller:%x CallCat:%x\n",
+ TIDCaller, pIfInfo->callcat));
+ RpcSpy((CALLIN_BEGIN, NULL, pIfInfo->iid, pIfInfo->wMethod, 0));
+
+ // HandleDispatchCall is only called from ComInvoke. Internal calls are
+ // dispatched directly to their worker functions.
+ Win4Assert(!(pIfInfo->callcat == CALLCAT_INTERNALSYNC ||
+ pIfInfo->callcat == CALLCAT_INTERNALINPUTSYNC) &&
+ "HandleDispatchCall called on Internal Call");
+
+ Win4Assert(TIDCaller);
+
+ //
+ // BUGBUG #27041 <RickHi>
+ //
+ // Stabilize this object to correct a problem of exiting Word 2.0c while
+ // a Media Player object is open. The below ->DispatchCall() would
+ // cause this object to be deleted, thus a crash in the following
+ // statement.
+ //
+ {
+ AddRef();
+ }
+
+ // ask the App's message filter (if there is one) what to do
+ CALLTYPE ctSaved = _CMC.GetCallType();
+ HRESULT hres = _CMC.CanHandleIncomingCall(TIDCaller, lid, pIfInfo);
+
+ if (hres == S_OK)
+ {
+ // app will allow the call, dispatch it
+ CALLCATEGORY CallCat = _CMC.SetCallCatOfInCall(pIfInfo->callcat);
+ hres = _OD.pChCont->DispatchCall(pChannelData);
+ _CMC.SetCallCatOfInCall(CallCat);
+ }
+
+ // reset the main call state
+ _CMC.SetCallType(ctSaved);
+
+ //
+ // End of stabilization section.
+ //
+ {
+ Release();
+ }
+
+ RpcSpy((CALLIN_END, NULL, pIfInfo->iid, pIfInfo->wMethod, hres));
+ CairoleDebugOut((DEB_CALLCONT, "CCallControl::HandleDispatchCall hres = %ld \n", hres));
+ return hres;
+}
+
+STDMETHODIMP CCallControl::ModalLoopBlockFunction()
+{
+ return _CMC.BlockFn();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CCallControl::CCallControl
+//
+// Synopsis: constructs a new call control
+//
+// Arguments: [pOrigindata] - call origin info
+// [rCMC] - callmain control
+// [phr] - where to return the result code
+//
+// Returns: S_OK - created OK
+// RPC_E_UNEXPECTED - duplicate origin data
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+CCallControl::CCallControl(PORIGINDATA pOrigindata, CCallMainControl &rCMC, HRESULT *phr) :
+ _CMC(rCMC),
+ _refs(1)
+{
+ Win4Assert(pOrigindata && "Invalid parameter to constructor");
+
+ _OD = *pOrigindata;
+
+ // addref the channelcontrol interface
+ _OD.pChCont->AddRef();
+
+ // try to register this origin data with the Main Call Control. We
+ // cant do this earlier due to threading issues.
+
+ _fReg = _CMC.Register(&_OD);
+
+ *phr = (_fReg) ? S_OK : RPC_E_UNEXPECTED;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CCallControl::~CCallControl
+//
+// Synopsis: destructor for call control
+//
+// Arguments: none
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+CCallControl::~CCallControl()
+{
+ if (_fReg)
+ {
+ // only if we successfully registered do we unregister. this
+ // avoids deregistering a valid OD if registration failed due
+ // to duplicates.
+
+ _CMC.Unregister(&_OD);
+ }
+
+ _OD.pChCont->Release();
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoGetCallControl, private
+//
+// Synopsis: Returns a pointer to CCallControl
+//
+// Arguments: Pointer to OriginData
+//
+// Returns: CCallControl
+//
+// Algorithm:
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+STDAPI CoGetCallControl(PORIGINDATA pOrigindata, PCALLCONTROL FAR* ppCallControl)
+{
+ TRACECALL(TRACE_CALLCONT, "CCallControl::CoGetCallControl");
+
+ Win4Assert((pOrigindata && pOrigindata->CallOrigin < CALLORIGIN_LAST)
+ && L"CoGetCallControl: Invalid CallOrigin specified" );
+
+
+ HRESULT hr = RPC_E_UNEXPECTED;
+
+ // only one thread should enter here
+ COleStaticLock lck(sgmxs);
+
+ CCallMainControl *pcmc = GetCallMainControlForThread();
+
+ if (pcmc)
+ {
+ // create a new callcontrol with the same callmaincontrol
+
+ *ppCallControl = new CCallControl(pOrigindata, *pcmc, &hr);
+
+ if (FAILED(hr))
+ {
+ // registration failed.
+ delete *ppCallControl;
+ *ppCallControl = NULL;
+ }
+ }
+ else
+ {
+ CairoleDebugOut((DEB_ERROR, "CoGetCallControl: GetCallMainControl Failed\n"));
+ *ppCallControl = NULL;
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoRegisterMessageFilter, public
+//
+// Synopsis: registers an applications message filter with the call control
+//
+// Arguments: [pMsgFilter] - message filter to register
+// [ppMsgFilter] - optional, where to return previous IMF
+//
+// Returns: S_OK - registered successfully
+//
+// History: 27-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+STDAPI CoRegisterMessageFilter(LPMESSAGEFILTER pMsgFilter,
+ LPMESSAGEFILTER *ppMsgFilter)
+{
+ OLETRACEIN((API_CoRegisterMessageFilter, PARAMFMT("pMsgFilter= %p, ppMsgFilter= %p"), pMsgFilter, ppMsgFilter));
+
+ HRESULT hr;
+
+ hr = CoRegisterMessageFilterEx(
+ (LPMESSAGEFILTER32) ((void *)pMsgFilter),
+ (LPMESSAGEFILTER32 *) ((void **)ppMsgFilter)
+ );
+
+ OLETRACEOUT((API_CoRegisterMessageFilter, hr));
+
+ return hr;
+}
+
+
+STDAPI CoRegisterMessageFilterEx(LPMESSAGEFILTER32 pMsgFilter,
+ LPMESSAGEFILTER32 * ppMsgFilter)
+{
+ TRACECALL(TRACE_CALLCONT, "CoRegisterMessageFilter");
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IMessageFilter,
+ (IUnknown **)&pMsgFilter);
+
+ HRESULT hr = S_OK;
+ CCallMainControl *pcmc = NULL;
+
+ {
+ // only one thread should enter here
+ COleStaticLock lck(sgmxs);
+
+ if ((pcmc = GetCallMainControlForThread()))
+ {
+ LPMESSAGEFILTER32 pMF = pcmc->SetMessageFilter(pMsgFilter);
+
+ if (ppMsgFilter)
+ {
+ // return the old one.
+ *ppMsgFilter = pMF;
+ }
+ else if (pMF)
+ {
+ // release the old one.
+ pMF->Release();
+ }
+ }
+ else
+ {
+ // error here
+ Win4Assert(FALSE && "CoRegisterMessageFilter invalid call.");
+ hr = E_FAIL;
+ }
+ }
+
+ return hr;
+}
diff --git a/private/ole32/com/remote/callcont.hxx b/private/ole32/com/remote/callcont.hxx
new file mode 100644
index 000000000..58579fc15
--- /dev/null
+++ b/private/ole32/com/remote/callcont.hxx
@@ -0,0 +1,231 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: CallCont.hxx (32 bit target)
+//
+// Contents: Contains the CallControl interface for OLE 2.0 32 bit.
+//
+// Functions: The CallControl interface is used by a channel to make
+// outgoing calls and receive call. It interacts with the
+// application provided MessageFilter interface.
+// It essentially contains the functionality what makes the
+// "OLE 2.0 Logicial Thread Model".
+// For more information see the aOLTM.doc
+//
+// History: 21-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+#ifndef __CALLCONT_H__
+#define __CALLCONT_H__
+
+#include <limits.h>
+
+typedef LPVOID PRPCMSG;
+typedef HANDLE EVENT;
+typedef IID LID; // logical thread id
+typedef REFIID REFLID; // ref to logical thread id
+
+
+typedef struct tagDISPATCHDATA
+{
+ SCODE scode; // might be no necessary
+ LPVOID pData; // pointer to channel data
+} DISPATCHDATA, *PDISPATCHDATA;
+
+
+// SERVERCALLEX is an extension of SERVERCALL and represents the set of
+// valid responses from IMessageFilter::HandleIncoming Call.
+
+typedef enum tagSERVERCALLEX
+{
+ SERVERCALLEX_ISHANDLED = 0, // server can handle the call now
+ SERVERCALLEX_REJECTED = 1, // server can not handle the call
+ SERVERCALLEX_RETRYLATER = 2, // server suggests trying again later
+ SERVERCALLEX_ERROR = 3, // error?
+ SERVERCALLEX_CANCELED = 5 // client suggests canceling
+} SERVERCALLEX;
+
+
+// CALLCATEGORY is used internally and represents the categories of calls
+// that can be made.
+
+typedef enum tagCALLCATEGORY
+{
+ CALLCAT_NOCALL = 0, // no call in progress
+ CALLCAT_SYNCHRONOUS = 1, // normal sychornous call
+ CALLCAT_ASYNC = 2, // asynchronous call
+ CALLCAT_INPUTSYNC = 3, // input-synchronous call
+ CALLCAT_INTERNALSYNC = 4, // internal ssync call
+ CALLCAT_INTERNALINPUTSYNC = 5, // internal inputssync call
+} CALLCATEGORY;
+
+
+// the INTERFACEINFO structure contains information that is passed to the
+// applications message filter via HandleIncomingCall when an incomming
+// ORPC call arrives. INTERFACEINFO32 contains an extra parameter on the
+// end (the callcat).
+
+typedef struct tagINTERFACEINFO32
+{
+ IUnknown FAR *pUnk; // the pointer to the object
+ IID iid; // interface id
+ WORD wMethod; // interface method
+ CALLCATEGORY callcat; // the category of call
+} INTERFACEINFO32, *PINTERFACEINFO32;
+
+
+// callcontrol data representing one call
+typedef struct tagCALLDATA
+{
+ IID iid; // iid on which call is made; only
+ // used to check for certain iids
+ // when processing ASYNC calls.
+ LID lid; // logical threadid this call was made on
+ UINT id; // callinfo id for the table lookup
+ DWORD TIDCallee; // threadid of callee
+ BOOL fDirectedYield;// TRUE if callcontrol should do yield
+ CALLCATEGORY CallCat; // category of call
+ EVENT Event; // the event we wait on
+ PRPCMSG pRpcMsg; // rpc msg (used by dde)
+#if DBG == 1
+ ULONG iMethod; // method index for rpx spy
+#endif
+
+} CALLDATA, * PCALLDATA;
+
+
+//
+// predefined calldata ids
+//
+#define CALLDATAID_INVALID UINT_MAX
+#define CALLDATAID_UNUSED UINT_MAX
+#define METHOD_INTERNAL (WORD) UINT_MAX
+
+
+// CALLORIGIN is an enumeration of the valid sources of an Rpc call.
+// The origin of CallRunModalLoop is needed for the priority of message.
+// If called by RPC, rpc messages are peeked first.
+
+typedef enum tagCALLORIGIN
+{
+ CALLORIGIN_LRPC = 1, // lrpc - windows based rpc (16bit)
+ CALLORIGIN_DDE = 2, // dde
+ CALLORIGIN_RPC16 = 3, // rpc - NT 16 bit app
+ CALLORIGIN_RPC32_APARTMENT = 4, // rpc - NT 32 bit appartment model
+ CALLORIGIN_RPC32_MULTITHREAD = 5, // rpc - NT 32 bit multi threaded
+ CALLORIGIN_LAST = 6 // first unused
+} CALLORIGIN;
+
+
+
+
+#undef INTERFACE
+#define INTERFACE IMessageFilter32
+
+// MessageFilter interface provided by the app
+
+DECLARE_INTERFACE_(IMessageFilter32, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IMessageFilter methods ***
+ STDMETHOD_(DWORD, HandleInComingCall) (THIS_ DWORD dwCallType,
+ DWORD TIDCaller, DWORD dwTickCount,
+ PINTERFACEINFO32 pIfInfo ) PURE;
+ STDMETHOD_(DWORD, RetryRejectedCall) (THIS_
+ DWORD TIDCallee, DWORD dwTickCount,
+ DWORD dwRejectType ) PURE;
+ STDMETHOD_(DWORD, MessagePending) (THIS_
+ DWORD TIDCallee, DWORD dwTickCount,
+ DWORD dwPendingType ) PURE;
+};
+typedef IMessageFilter32 FAR* LPMESSAGEFILTER32, *PMESSAGEFILTER32;
+
+
+
+#undef INTERFACE
+#define INTERFACE IChannelControl
+
+// each app using the CallControl interface has to provide the
+// a ChannelControl interface
+
+DECLARE_INTERFACE_(IChannelControl, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IChannelCall methods ***
+ // DispatchCall is called in case the client wants to retry the call
+ STDMETHOD (DispatchCall) (THIS_ PDISPATCHDATA pDispatchData) PURE;
+ // TransmitCall is called in case the client wants to retry the call
+ STDMETHOD (TransmitCall) (THIS_ PCALLDATA pCallData) PURE;
+ // OnEvent is called if the event is signaled we wait on
+ STDMETHOD (OnEvent) (THIS_ PCALLDATA pCallData) PURE;
+};
+typedef IChannelControl FAR* LPCHANNELCONTROL, *PCHANNELCONTROL;
+#undef INTERFACE
+
+
+
+// structure to hold channel specific information, such as the
+// range of messages the channel is interested in, channel controller,
+// etc.
+
+typedef struct tagOriginData
+{
+ PCHANNELCONTROL pChCont; // channel controller
+ CALLORIGIN CallOrigin; // call origin type
+ HWND hwnd; // window handle
+ UINT wFirstMsg; // first MSG # in contiguous range
+ UINT wLastMsg; // last MSG # in contiguous range
+} ORIGINDATA, * PORIGINDATA;
+
+
+
+#define INTERFACE ICallControl
+DECLARE_INTERFACE_(ICallControl, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** ICallControl methods ***
+
+ STDMETHOD (CallRunModalLoop) (THIS_ PCALLDATA pCalldata) PURE;
+ STDMETHOD (SetCallState) (THIS_ PCALLDATA pCalldata,
+ SERVERCALLEX ServerCall,
+ SCODE scode) PURE;
+ STDMETHOD (HandleDispatchCall) (THIS_ DWORD TIDCaller, REFLID lid,
+ PINTERFACEINFO32 pIfInfo,
+ PDISPATCHDATA pDispatchData) PURE;
+ STDMETHOD (ModalLoopBlockFunction) (THIS_ ) PURE;
+
+};
+typedef ICallControl FAR* LPCALLCONTROL, *PCALLCONTROL;
+
+
+STDAPI CoGetCallControl(PORIGINDATA pOrigindata, PCALLCONTROL FAR* ppCallControl);
+
+// app can register a MessageFilter interface
+STDAPI CoRegisterMessageFilterEx(PMESSAGEFILTER32 pMsgFilter, PMESSAGEFILTER32 *ppMsgFilter);
+
+#if DBG == 1
+#define METHOD_SYSROT_CALLGETOSINFO MAXDWORD-1
+#define METHOD_SYSROT_ENUMRUNNING MAXDWORD-2
+#define METHOD_ROT_GETIFFROMPROP MAXDWORD-3
+#define METHOD_CHANNEL_GETCHANNELID MAXDWORD-4
+#define METHOD_CHANNEL_RELEASECHANNEL MAXDWORD-5
+#define METHOD_CHANNEL_DOCHANNELOPERATION MAXDWORD-6
+#endif
+
+#endif // __CALLCONT__HXX__
+
+
diff --git a/private/ole32/com/remote/callmain.cxx b/private/ole32/com/remote/callmain.cxx
new file mode 100644
index 000000000..056e3f799
--- /dev/null
+++ b/private/ole32/com/remote/callmain.cxx
@@ -0,0 +1,1858 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: CallMain.cxx (32 bit target)
+//
+// Contents: Contains the CallMainControl interface
+//
+// Functions:
+//
+// History: 23-Dec-93 Johann Posch (johannp) Created
+//
+// CODEWORK: nuke many pCI parameters and use _pCICur instead to reduce
+// code and stack usage
+//
+//--------------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <userapis.h>
+#include <tls.h>
+#include <thkreg.h>
+#include "callcont.hxx"
+#include "callmain.hxx"
+#include "chancont.hxx"
+
+#define WM_SYSTIMER 0x0118
+#define SYS_ALTDOWN 0x2000
+#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
+#define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
+#define DebWarn(x)
+
+
+// the callmaincontrol pointer for multithreaded case
+CCallMainControl *sgpCMCMultiThread = NULL;
+extern COleStaticMutexSem sgmxs;
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetSlowTimeFactor
+//
+// Synopsis: Get the time slowing factor for Wow apps
+//
+// Returns: The factor by which we need to slow time down.
+//
+// Algorithm: If there is a factor in the registry, we open and read the
+// registry. Otherwise we just set it to the default.
+//
+// History: 22-Jul-94 Ricksa Created
+// 09-Jun-95 Susia ANSI Chicago optimization
+//
+//--------------------------------------------------------------------------
+#ifdef _CHICAGO_
+#undef RegOpenKeyEx
+#define RegOpenKeyEx RegOpenKeyExA
+#undef RegQueryValueEx
+#define RegQueryValueEx RegQueryValueExA
+#endif
+
+DWORD GetSlowTimeFactor(void)
+{
+ // Default slowing time so we can just exit if there is no key which
+ // is assumed to be the common case.
+ DWORD dwSlowTimeFactor = OLETHK_DEFAULT_SLOWRPCTIME;
+
+ // Key for reading the value from the registry
+ HKEY hkeyOleThk;
+
+ // Get the Ole Thunk special value key
+
+ LONG lStatus = RegOpenKeyEx(HKEY_CLASSES_ROOT, OLETHK_KEY, 0, KEY_READ, &hkeyOleThk);
+
+
+ if (lStatus == ERROR_SUCCESS)
+ {
+ DWORD dwType;
+ DWORD dwSizeData = sizeof(dwSlowTimeFactor);
+
+ lStatus = RegQueryValueEx (hkeyOleThk, OLETHK_SLOWRPCTIME_VALUE, NULL,
+ &dwType, (LPBYTE) &dwSlowTimeFactor, &dwSizeData);
+
+ if ((lStatus != ERROR_SUCCESS) || dwType != REG_DWORD)
+ {
+ // Guarantee that value is reasonable if something went wrong.
+ dwSlowTimeFactor = OLETHK_DEFAULT_SLOWRPCTIME;
+ }
+
+ // Close the key since we are done with it.
+ RegCloseKey(hkeyOleThk);
+ }
+
+ return dwSlowTimeFactor;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallInfo::GetElapsedTime
+//
+// Synopsis: Get the elapsed time for an RPC call
+//
+// Returns: Elapsed time of current call
+//
+// Algorithm: This checks whether we have the slow time factor. If not,
+// and we are in WOW we read this from the registry. Otherwise,
+// this is just set to one. Then we calculate the time of the
+// RPC and divide it by the slow time factor.
+//
+// History: 22-Jul-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(DWORD) CCallInfo::GetElapsedTime()
+{
+ // Define slow time factor to something invalid
+ static dwSlowTimeFactor = 0;
+
+ if (dwSlowTimeFactor == 0)
+ {
+ if (IsWOWProcess())
+ {
+ // Get time factor from registry otherwise set to the default
+ dwSlowTimeFactor = GetSlowTimeFactor();
+ }
+ else
+ {
+ // Time is unmodified for 32 bit apps
+ dwSlowTimeFactor = 1;
+ }
+ }
+
+ DWORD dwTickCount = GetTickCount();
+ DWORD dwElapsedTime = dwTickCount - _dwTimeOfCall;
+ if (dwTickCount < _dwTimeOfCall)
+ {
+ // the timer wrapped
+ dwElapsedTime = 0xffffffff - _dwTimeOfCall + dwTickCount;
+ }
+
+ return (dwElapsedTime / dwSlowTimeFactor);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetCallMainControlForThread
+//
+// Synopsis: retrieves the callmaincontrol for the current thread
+//
+// Arguments: none
+//
+// Returns: CallMainControl
+//
+// History: Jan-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CCallMainControl *GetCallMainControlForThread()
+{
+ if (FreeThreading)
+ {
+ // there is only one CMC per process for a FreeThreading app.
+ if (!sgpCMCMultiThread)
+ {
+ sgpCMCMultiThread = new CCallMainControl();
+ }
+
+ return sgpCMCMultiThread;
+ }
+
+ // there is a CMC per thread for non freethreading apps
+ CCallMainControl *pcmc = (CCallMainControl *)TLSGetCallControl();
+
+ if (pcmc == NULL)
+ {
+ pcmc = new CCallMainControl();
+ TLSSetCallControl(pcmc);
+ }
+
+ return pcmc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetCallMainControlForThread
+//
+// Synopsis: installs a new callmaincontrol
+//
+// Arguments: [pcmc] -- callmaincontrol to install
+//
+// Returns: TRUE on success
+//
+// History: Jan-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL SetCallMainControlForThread(CCallMainControl *pcmc)
+{
+ if (FreeThreading)
+ {
+ // only need one CMC for this whole process
+ sgpCMCMultiThread = pcmc;
+ return TRUE;
+ }
+
+ // need one CMC per apartment
+ return TLSSetCallControl(pcmc);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// CallMainControl implementation
+//
+/////////////////////////////////////////////////////////////////////////////
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCallMainControl::CCallMainControl
+//
+// Synopsis: Constructor
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CCallMainControl::CCallMainControl()
+{
+ _cRef = 0;
+ _pMF = NULL;
+
+ // initialize the call info table
+ _pCICur = NULL;
+
+ _cCur = CALLDATAID_INVALID;
+ // CODEWORK: nuke this & use single linked list
+ _cCallInfoMac = CALLINFOMAX;
+ memset(_CallInfoTable, 0, sizeof(_CallInfoTable));
+
+ _cODs = 0;
+ _CallType = CALLTYPE_NOCALL; // 0 is no call at all
+ _CallCat = CALLCAT_NOCALL;
+ _fInMessageFilter = FALSE;
+
+ _fMultiThreaded = FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCallMainControl::~CCallMainControl
+//
+// Synopsis: Destructor
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CCallMainControl::~CCallMainControl()
+{
+ if (_pMF)
+ {
+ _pMF->Release();
+ }
+
+ SetCallMainControlForThread(NULL);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCallMainControl::Register
+//
+// Synopsis: registers a new callcontrol on the current callmaincontrol
+//
+// Arguments: [pOrigindata] -- origindata of callcontrol
+//
+// Returns:
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(BOOL) CCallMainControl::Register (PORIGINDATA pOrigindata)
+{
+ BOOL fRet = TRUE;
+
+ // single thread access
+ CLock lck(_mxs);
+
+ if ( (pOrigindata && pOrigindata->CallOrigin > 0 && pOrigindata->CallOrigin < CALLORIGIN_LAST)
+ && _cODs < ODMAX)
+ {
+ for (UINT i = 0; i < _cODs; i++)
+ {
+ // check if all call origins are valid
+ Win4Assert(_rgpOrigindata[i] && "CallMainControl: invalid origin state");
+
+ if (_rgpOrigindata[i]->CallOrigin == pOrigindata->CallOrigin)
+ {
+ // already registered
+ CairoleDebugOut((DEB_ERROR, "CallMainControl: Callorigin already registered"));
+ fRet = FALSE;
+ break;
+ }
+ }
+
+ if (fRet)
+ {
+ // determine if this is multithreaded
+ _fMultiThreaded = FreeThreading;
+
+ // add origin to the next empty spot
+ _rgpOrigindata[_cODs] = pOrigindata;
+ _cODs++;
+ _cRef++;
+ }
+ }
+ else
+ {
+ fRet = FALSE;
+ }
+
+ return fRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CCallMainControl::Unregister
+//
+// Synopsis: unregister a callcontrol on the callmaincontrol
+//
+// Arguments: [pOrigindata] -- origindata of callcontrol
+//
+// Returns:
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(BOOL) CCallMainControl::Unregister (PORIGINDATA pOrigindata)
+{
+ BOOL fRet = FALSE;
+
+ // always single thread access
+ {
+ CLock lck(_mxs);
+
+ if ( (pOrigindata && pOrigindata->CallOrigin > 0 && pOrigindata->CallOrigin < CALLORIGIN_LAST)
+ && (_cODs < ODMAX) )
+ {
+ for (UINT i = 0; i < _cODs; i++)
+ {
+ if (_rgpOrigindata[i] == pOrigindata)
+ {
+ // copy the last one in the freed spot
+ _cODs--;
+ _rgpOrigindata[i] = _rgpOrigindata[_cODs];
+
+ // PeekOriginAndDDE needs this to be NULL
+ _rgpOrigindata[_cODs] = NULL;
+ _cRef--;
+
+ if (pOrigindata->CallOrigin == CALLORIGIN_RPC32_MULTITHREAD)
+ {
+ _fMultiThreaded = FALSE;
+ }
+
+ fRet = TRUE;
+ break; // break out of the loop
+ }
+ }
+
+ // fRet should be TRUE by now - otherwise callorigin was not found
+ Win4Assert(fRet && "CallMainControl::Unregister Callorigin not found in list.");
+ }
+
+ // CLock leaves scope here
+ }
+
+ if (FreeThreading)
+ {
+ // take the global lock that protects sgpCMCMultiThread
+ COleStaticLock lck(sgmxs);
+
+ if (_cRef == 0)
+ {
+ // we are about to delete ourselves so NULL the global
+ // pointer to this thing.
+ sgpCMCMultiThread = NULL;
+ }
+ }
+
+ if (_cRef == 0)
+ {
+ delete this;
+ }
+
+ return fRet;
+}
+
+//
+// Hook up the msgFilter info with a new new message filter
+//
+INTERNAL_(PMESSAGEFILTER32) CCallMainControl::SetMessageFilter(PMESSAGEFILTER32 pMF)
+{
+ BeginCriticalSection();
+
+ // save the old one to return
+ PMESSAGEFILTER32 pMFOld = _pMF;
+
+ // hook up the new one
+ _pMF = pMF;
+ if (_pMF)
+ {
+ _pMF->AddRef();
+ }
+
+ EndCriticalSection();
+
+ return pMFOld;
+}
+
+
+INTERNAL_(ULONG) CCallMainControl::AddRef()
+{
+ InterlockedIncrement((long *)&_cRef);
+ return _cRef;
+}
+
+INTERNAL_(ULONG) CCallMainControl::Release()
+{
+ ULONG cRef = _cRef - 1;
+
+ if (InterlockedDecrement((long *)&_cRef) == 0)
+ {
+ delete this;
+ return 0;
+ }
+
+ return cRef;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallMainControl::CanHandleIncomingCall
+//
+// Synopsis: called whenever an incoming call arrives to ask the apps
+// message filter (if there is one) whether it wants to handle
+// the call or not.
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+//--------------------------------------------------------------------------
+INTERNAL CCallMainControl::CanHandleIncomingCall(DWORD TIDCaller,
+ REFLID lid,
+ PINTERFACEINFO32 pIfInfo)
+{
+ // default: all calls are accepted
+ HRESULT hr = S_OK;
+
+ // single thread retrieval of the previous call info and
+ // the message filter, since other threads can change them.
+
+ BeginCriticalSection();
+
+ PCALLINFO pCI = GetPrevCallInfo(lid);
+
+#if DBG==1
+ LID lidPrev;
+ if (pCI)
+ lidPrev = pCI->GetLID();
+ else
+ lidPrev = GUID_NULL;
+
+ CairoleDebugOut((DEB_CALLCONT,
+ "CanHandleIncomingCall: TIDCaller:%x CallType:%x lid:%x pCI:%x prevLid:%x\n",
+ TIDCaller, _CallType, lid.Data1, pCI, lidPrev.Data1));
+#endif
+
+ CALLTYPE CallType = SetCallTypeOfCall(pCI, pIfInfo->callcat);
+ PMESSAGEFILTER32 pMF = GetMessageFilter();
+
+ EndCriticalSection();
+
+
+ if (pMF)
+ {
+ // the app has installed a message filter. call it.
+
+ DWORD dwElapsedTime = (pCI) ? pCI->GetElapsedTime() : 0;
+
+ // ensure that we dont allow the App to make an outgoing call
+ // from within the message filter code.
+ _fInMessageFilter = TRUE;
+
+ // The DDE layer doesn't provide any interface information. This
+ // was true on the 16-bit implementation, and has also been
+ // brought forward into this implementation to insure
+ // compatibility. However, the callcat of the pIfInfo is still
+ // provided.
+ //
+ // Therefore, if pIfInfo has its pUnk member set to NULL, then
+ // we are going to send a NULL pIfInfo to the message filter.
+
+ DWORD dwRet = pMF->HandleInComingCall((DWORD) CallType,
+ TIDCaller,
+ dwElapsedTime,
+ pIfInfo->pUnk?pIfInfo:NULL);
+ _fInMessageFilter = FALSE;
+
+ ReleaseMessageFilter(pMF);
+
+ // strict checking of app return code for win32
+ Win4Assert(dwRet == SERVERCALLEX_ISHANDLED ||
+ dwRet == SERVERCALLEX_REJECTED ||
+ dwRet == SERVERCALLEX_RETRYLATER ||
+ IsWOWThread() && "Invalid Return code from App IMessageFilter");
+
+
+ if (dwRet != SERVERCALLEX_ISHANDLED)
+ {
+ if (pIfInfo->callcat == CALLCAT_ASYNC ||
+ pIfInfo->callcat == CALLCAT_INPUTSYNC)
+ {
+ // Note: input-sync and async calls can not be rejected
+ // Even though they can not be rejected, we still have to
+ // call the MF above to maintain 16bit compatability.
+
+ hr = S_OK;
+ }
+ else if (dwRet == SERVERCALLEX_REJECTED)
+ {
+ hr = RPC_E_SERVERCALL_REJECTED;
+ }
+ else if (dwRet == SERVERCALLEX_RETRYLATER)
+ {
+ hr = RPC_E_SERVERCALL_RETRYLATER;
+ }
+ else
+ {
+ // 16bit OLE let bogus return codes go through and of course
+ // apps rely on that behaviour so we let them through too, but
+ // we are more strict on 32bit.
+ hr = (IsWOWThread()) ? S_OK : RPC_E_UNEXPECTED;
+ }
+ }
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallMainControl::SetCallTypeOfCall
+//
+// Synopsis: called when an incoming call arrives to maintain the state
+// of the thread.
+//
+// Arguments: [pCI] - callinfo
+// [callcat] - call category of incoming call
+//
+// Returns: the new calltype
+//
+// Algorithm: complicated state machine
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+// CALLTYPE_TOPLEVEL = 1, // toplevel call - no outgoing call
+// CALLTYPE_NESTED = 2, // callback on behalf of previous outgoing call
+// CALLTYPE_ASYNC = 3, // aysnchronous call - can NOT be rejected
+// CALLTYPE_TOPLEVEL_CALLPENDING = 4, // new toplevel call with new ***LID
+// CALLTYPE_ASYNC_CALLPENDING = 5 // async call - can NOT be rejected
+//
+//--------------------------------------------------------------------------
+INTERNAL_(CALLTYPE) CCallMainControl::SetCallTypeOfCall (PCALLINFO pCI, CALLCATEGORY CallCat)
+{
+ CALLTYPE ctNow = (CallCat == CALLCAT_ASYNC)
+ ? CALLTYPE_ASYNC : CALLTYPE_TOPLEVEL;
+
+ switch (_CallType)
+ {
+ case CALLTYPE_NOCALL: // no incomming call - no call to dispatch
+ if (_cCur == CALLDATAID_INVALID)
+ {
+ _CallType = ctNow;
+ break;
+ }
+
+ // otherwise fallthru the toplevel case
+
+ case CALLTYPE_TOPLEVEL: // dispatching or making a toplevel call
+ case CALLTYPE_NESTED: // nested call
+ if (pCI)
+ {
+ // same locigal thread
+ _CallType = (ctNow == CALLTYPE_TOPLEVEL)
+ ? CALLTYPE_NESTED : CALLTYPE_ASYNC;
+ }
+ else
+ {
+ // Note: the new incoming call has a different LID!
+ _CallType = (ctNow == CALLTYPE_TOPLEVEL)
+ ? CALLTYPE_TOPLEVEL_CALLPENDING : CALLTYPE_ASYNC_CALLPENDING;
+ }
+ break;
+
+ case CALLTYPE_ASYNC: // dispatching or making an async call
+ // Note: we do not allow to call out on async calls
+ // -> all new incoming calls have to be on a new LID
+ if (pCI)
+ {
+ _CallType = (ctNow == CALLTYPE_TOPLEVEL)
+ ? CALLTYPE_TOPLEVEL_CALLPENDING : CALLTYPE_ASYNC_CALLPENDING;
+ }
+ break;
+
+ case CALLTYPE_TOPLEVEL_CALLPENDING:
+ _CallType = CALLTYPE_NESTED;
+ break;
+
+ case CALLTYPE_ASYNC_CALLPENDING:
+ default:
+ // no state change
+ break;
+ }
+
+ CairoleDebugOut((DEB_CALLCONT,"SetCallTypeOfCall return:%x\n", _CallType));
+ return _CallType;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallMainControl::CanMakeOutCall
+//
+// Synopsis: called when the app wants to make an outgoing call to
+// determine if it is OK to do it now or not.
+//
+// Arguments: [callcat] - call category of call the app wants to make
+// [iid] - interface the call is being made on
+//
+// Returns: S_OK - ok to make the call
+// RPC_E_CANTCALLOUT_INEXTERNALCALL - inside IMessageFilter
+// RPC_E_CANTCALLOUT_INASYNCCALL - inside async call
+// RPC_E_CANTCALLOUT_ININPUTSYNCCALL - inside input sync or SendMsg
+//
+// Algorithm: * NO outgoing call while dispatching an async call
+// * Only input sync calls can be made while
+// dispatching an input-sync call
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+// Notes: CODEWORK: this can be heavily optimized.
+// Might be better to call this from GetBuffer instead of
+// after all the parameters have been marshalled.
+//
+//--------------------------------------------------------------------------
+INTERNAL CCallMainControl::CanMakeOutCall (CALLCATEGORY callcat, REFIID iid)
+{
+ HRESULT hr = NOERROR;
+
+ Win4Assert(callcat >= CALLCAT_SYNCHRONOUS
+ && callcat <= CALLCAT_INTERNALINPUTSYNC
+ && "CallMainControl::CanMakeOutCall invalid call category.");
+
+ if (!_fMultiThreaded)
+ {
+ // this lets RotRegister go through
+ if (_fInMessageFilter && callcat != CALLCAT_INTERNALINPUTSYNC)
+ {
+ CairoleDebugOut((DEB_ERROR, "App trying to call out from within IMessageFilter\n"));
+ hr = RPC_E_CANTCALLOUT_INEXTERNALCALL;
+ }
+ // let pass async and internal calls if dispatching an async call
+ else if ((_CallType == CALLTYPE_ASYNC
+ || _CallType == CALLTYPE_ASYNC_CALLPENDING)
+ && callcat != CALLCAT_ASYNC
+ && callcat != CALLCAT_INTERNALSYNC
+ && callcat != CALLCAT_INTERNALINPUTSYNC)
+ {
+ hr = RPC_E_CANTCALLOUT_INASYNCCALL;
+ }
+ // * do not allow a non-async and non-inputsync outgoing calls
+ // if dispatching an inputsync call, an internal input sync call
+ // or if we are in the process of handling a send message.
+ //
+ // If we are in WOW, then we are going to allow outgoing calls
+ // while InSendMessage(). They used to be allowed, and there
+ // are cases such as Publishers Cue Cards that do this
+ //
+ else if (((_CallCat == CALLCAT_INPUTSYNC)
+ || (_CallCat == CALLCAT_INTERNALINPUTSYNC)
+ || InSendMessage())
+ && (callcat != CALLCAT_ASYNC)
+ && (callcat != CALLCAT_INPUTSYNC)
+ && (callcat != CALLCAT_INTERNALSYNC)
+ && (callcat != CALLCAT_INTERNALINPUTSYNC))
+ {
+#if DBG == 1
+ if ((_CallCat != CALLCAT_INPUTSYNC)
+ && (_CallCat != CALLCAT_INTERNALINPUTSYNC))
+ {
+ CairoleDebugOut((DEB_WARN,
+ "CCallMainControl::CanMakeOutCall Failing Call because InSendMessage\n"));
+ }
+#endif // DBG == 1
+ hr = RPC_E_CANTCALLOUT_ININPUTSYNCCALL;
+ }
+ }
+
+ CairoleDebugOut(((hr == S_OK) ? DEB_CALLCONT : DEB_ERROR,
+ "CanMakeOutCall: _CallType:%x _CallCat:%x callcat:%x Return:%x\n",
+ _CallType, _CallCat, callcat, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallMainControl::GetPrevCallInfo
+//
+// Synopsis: When an incoming call arrives this is used to find any
+// previous call for the same logical thread, ignoring
+// INTERNAL calls.
+//
+// Arguments: [lid] - logical threadid of incoming call
+//
+// Returns: pCI - if previous callinfo found for this lid
+// NULL - if not
+//
+// Algorithm: see synopsis
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(PCALLINFO) CCallMainControl::GetPrevCallInfo(REFLID lid)
+{
+ for (UINT i = _cCur; i != CALLDATAID_INVALID; i--)
+ {
+ PCALLINFO pCI = GetCIfromCallID(i);
+ if ( pCI
+ && pCI->GetLID() == lid
+ && pCI->GetCallCat() < CALLCAT_INTERNALSYNC
+ && pCI->GetCallCat() > CALLCAT_NOCALL)
+ {
+ return pCI;
+ }
+ }
+
+ return NULL;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallMainControl::HandleRejectedCall
+//
+// Synopsis: called when the response to a remote call is rejected or
+// retry later.
+//
+// Arguments: [pCI] - call info
+//
+// Returns: nothing - CallState of pCI modified appropriately
+//
+// Algorithm: Calls the app's message filter (if there is one) to
+// determine whether the call should be failed, retried
+// immediately, or retried at some later time. If there is
+// no message filter then the call is rejected.
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(void) CCallMainControl::HandleRejectedCall (PCALLINFO pCI)
+{
+ // we should not end up here if there is no outstanding call
+ Win4Assert(_cCur != CALLDATAID_UNUSED && "HandleRejectedCall:: not call waiting.");
+ CairoleDebugOut((DEB_CALLCONT,
+ "RetryRejectedCall pCI:%x TaskId:%x ElapsedTime:%x CallState:%x\n",
+ pCI, pCI->GetTaskIdServer(), pCI->GetElapsedTime(), pCI->GetCallState()));
+
+ // default return value - rejected
+ DWORD dwRet = 0xffffffff;
+
+ // single thread access to getting the message filter
+ BeginCriticalSection();
+ PMESSAGEFILTER32 pMF = GetMessageFilter();
+ EndCriticalSection();
+
+ // in case caller has no MessageFilter - return MSG_REJECTED
+ if (pMF)
+ {
+ // ensure that we dont allow the App to make an outgoing call
+ // from within the message filter code.
+ _fInMessageFilter = TRUE;
+
+ dwRet = pMF->RetryRejectedCall(pCI->GetTaskIdServer(),
+ pCI->GetElapsedTime(),
+ pCI->GetCallState());
+ _fInMessageFilter = FALSE;
+ ReleaseMessageFilter(pMF);
+ }
+
+ if (dwRet == 0xffffffff)
+ {
+ // Really rejected. Mark is as such incase it was actually
+ // Call_RetryLater, also ensures that IsWaiting returns FALSE
+ pCI->SetCallState(Call_Rejected, RPC_E_SERVERCALL_REJECTED);
+ }
+ else if (dwRet >= 100)
+ {
+ // Retrt Later. Start the timer. This ensures that IsTimerAtZero
+ // returns FALSE and IsWaiting returns TRUE
+ pCI->StartTimer(dwRet);
+ }
+ else
+ {
+ // Retry Immediately. Set the state so that IsTimerAtZero
+ // returns TRUE and IsWaiting returns TRUE
+ pCI->SetCallState(Call_WaitOnCall, S_OK);
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallMainControl::HandlePendingMessage
+//
+// Synopsis: this function is called for system messages and other
+// pending messages
+//
+// Arguments: [pCI] - call info
+//
+// Returns: result of the call
+//
+// Algorithm:
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(DWORD) CCallMainControl::HandlePendingMessage(PCALLINFO pCI)
+{
+ TRACECALL(TRACE_CALLCONT, "CallMainControl::HandlePendingMessage called");
+ CairoleDebugOut((DEB_CALLCONT,
+ "MessagePending pCI:%x TaskId:%x ElapsedTime:%x CallState:%x\n",
+ pCI, pCI->GetTaskIdServer(), pCI->GetElapsedTime(),
+ (_cCur >= 1) ? PENDINGTYPE_NESTED : PENDINGTYPE_TOPLEVEL));
+
+ DWORD dwRet = PENDINGMSG_WAITDEFPROCESS;
+
+ // single thread access to getting the message filter
+ BeginCriticalSection();
+ PMESSAGEFILTER32 pMF = GetMessageFilter();
+ EndCriticalSection();
+
+ if (pMF)
+ {
+ // call the message filter
+ DWORD dwPendingType = (_cCur == 0) ? PENDINGTYPE_TOPLEVEL
+ : PENDINGTYPE_NESTED;
+
+ // ensure that we dont allow the App to make an outgoing call
+ // from within the message filter code.
+ _fInMessageFilter = TRUE;
+
+ dwRet = pMF->MessagePending(pCI->GetTaskIdServer(),
+ pCI->GetElapsedTime(),
+ dwPendingType);
+ _fInMessageFilter = FALSE;
+ ReleaseMessageFilter(pMF);
+ }
+
+ switch (dwRet)
+ {
+ case PENDINGMSG_CANCELCALL :
+
+ pCI->SetCallState(Call_Canceled, RPC_E_CALL_CANCELED);
+ break;
+
+ default :
+ Win4Assert(FALSE && "Invalid return value from HandleIncomingCall" );
+ // do default processing
+
+ case PENDINGMSG_WAITDEFPROCESS:
+ // For Win32, default and wait no process are the same.
+
+ case PENDINGMSG_WAITNOPROCESS :
+ {
+ // wait for the return and don't dispatch the message
+ // handle only the important system stuff
+ MSG msg;
+
+ // perform default action on system message
+ // only dispatch special system messages
+ BOOL fSys = FALSE;
+ if ((fSys = MyPeekMessage(pCI, &msg, 0, WM_SYSCOMMAND, WM_SYSCOMMAND, PM_REMOVE | PM_NOYIELD) )
+ || (MyPeekMessage(pCI, &msg, 0, WM_SYSKEYDOWN, WM_SYSKEYDOWN, PM_NOREMOVE | PM_NOYIELD) )
+ )
+ {
+ // Note: message: SYSOCMMAND SC_TASKLIST is generated by system and posted to the active window;
+ // we let this message by default thru
+ if (fSys)
+ {
+ // only dispatch some syscommands
+ switch (msg.wParam)
+ {
+ case SC_HOTKEY:
+ case SC_TASKLIST:
+ CairoleDebugOut((DEB_CALLCONT,">>>> Dispatching SYSCOMMAND message: %x; wParm: %x \r\n",msg.message, msg.wParam));
+ DispatchMessage(&msg);
+ default:
+ // we have to take out all syscommand messages
+ CairoleDebugOut((DEB_CALLCONT,">>>> Received/discarded SYSCOMMAND message: %x; wParm: %x \r\n",msg.message, msg.wParam));
+ MessageBeep(0);
+ break;
+ }
+ }
+ else if (DispatchSystemMessage(msg, FALSE))
+ {
+ // take care of the sys key messages
+ // dispatch the message
+ CairoleDebugOut((DEB_CALLCONT, "==> Dispatched system message: %x \r\n",msg.message));
+ MyPeekMessage(pCI, &msg, 0, WM_SYSKEYDOWN, WM_SYSKEYDOWN, PM_REMOVE | PM_NOYIELD);
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ else if ( MyPeekMessage(pCI, &msg, 0, WM_ACTIVATE, WM_ACTIVATE, PM_REMOVE | PM_NOYIELD)
+ || MyPeekMessage(pCI, &msg, 0, WM_ACTIVATEAPP, WM_ACTIVATEAPP, PM_REMOVE | PM_NOYIELD)
+ || MyPeekMessage(pCI, &msg, 0, WM_NCACTIVATE, WM_NCACTIVATE, PM_REMOVE | PM_NOYIELD) )
+ {
+ CairoleDebugOut((DEB_CALLCONT, ">>> Dispatched ACTIVATE message: Hwnd: >%x< message: %x \r\n",msg.hwnd, msg.message));
+ DispatchMessage(&msg);
+ }
+ else
+ {
+ // no message peeked
+ //CairoleDebugOut((DEB_CALLCONT, "==> No system message peeked: %x \r\n",msg.message));
+ }
+ }
+ break;
+
+ } // end switch
+
+ return dwRet;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallMainControl::DispatchSystemMessages
+//
+// Synopsis: called when....
+//
+// Arguments: [msg] -
+// [fBeep] - TRUE means beep - CODEWORK: nobody sets to TRUE
+//
+// Returns: result of the call
+//
+// Algorithm: Dispatach mouse and keyboard message.
+// The folling keysstroke should get handled:
+//
+// alt-escape - enunerate tasks by window
+// alt-tab - enumerate tasks by icons
+// alt-shift-escape - enunerate tasks by window
+// alt-shift-tab - enumerate tasks by icons
+// ctrl-escape - switch to task list
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(BOOL) CCallMainControl::DispatchSystemMessage(MSG msg, BOOL fBeep)
+{
+ BOOL fDispatch = FALSE;
+
+ WORD wMsg = msg.message;
+ WORD wKeyCode = msg.wParam;
+ DWORD dwKeyData = msg.lParam;
+
+ CairoleDebugOut((DEB_CALLCONT, "Command: %x; KeyCode %x, KeyData %08x \r\n",wMsg, wKeyCode, dwKeyData));
+
+ switch (wMsg)
+ {
+ case WM_SYSKEYDOWN:
+ // user hold ALT key was pressed another key
+ // no window has the focus and we are the window which is active
+ if ( dwKeyData & SYS_ALTDOWN)
+ {
+ // alt key is pressed
+ switch (wKeyCode)
+ {
+ case VK_MENU: // ALT KEY
+ case VK_SHIFT:
+ // don't beep
+ break;
+ case VK_TAB:
+ case VK_ESCAPE:
+ // Alt-Esc, Alt-Tab - let it thru to the DefWinProc
+ fDispatch = TRUE;
+ break;
+ default:
+ // beep on all other keystrokes
+ if (fBeep)
+ MessageBeep(0);
+ break;
+
+ }
+ }
+ break;
+
+ case WM_KEYDOWN:
+ if ( wKeyCode != VK_CONTROL
+ && wKeyCode != VK_SHIFT)
+ MessageBeep(0);
+ break;
+
+ default:
+ break;
+ }
+
+ return fDispatch;
+}
+
+//
+// insert the callinfo in a free spot
+//
+INTERNAL_(UINT) CCallMainControl::InsertCI (PCALLINFO pCI)
+{
+ // CODEWORK: Assert that we are inside critical section in MT case
+ // CODEWORK: Use a linked list for the callinfos, then InsertCI,
+ // SetupModalLoop and ResetModalLoop can mostly vanish,
+ // we save 800 bytes of data per apartment, and we loose
+ // the limitation of _cCallInfoMac concurrent calls.
+
+ // find empty spot
+ for (UINT i = 0; i < _cCallInfoMac && _CallInfoTable[i]; i++)
+ ;
+
+ if (i < _cCallInfoMac)
+ {
+ _CallInfoTable[i] = pCI;
+ pCI->SetId(i);
+ return i;
+ }
+
+ // table is full
+ return CALLDATAID_INVALID;
+}
+
+//
+// Set up the a new call info - prepare the modal loop for a new outgoing call
+// Note: Must be called before calling RunModalLoop
+INTERNAL_(UINT) CCallMainControl::SetupModalLoop (PCALLINFO pCI)
+{
+ // insert the new callinfo in the table
+ // single thread access to _cCur and the CallInfo table
+ CLock lck(_mxs);
+
+ UINT cNew = InsertCI(pCI);
+
+ if (cNew != CALLDATAID_INVALID)
+ {
+ // set the topmost pointer
+ if ( _cCur == CALLDATAID_UNUSED
+ || _cCur < cNew)
+ _cCur = cNew;
+ }
+ else
+ {
+ Win4Assert(!"CallInfo table is full");
+ CairoleDebugOut((DEB_ERROR,"CallInfo table is full\n\r"));
+ }
+
+ return cNew;
+}
+//
+// Restore the call info - with the previous call info - previous call on the stack
+// Note: Must be called after RunModalLoop
+//
+INTERNAL_(VOID) CCallMainControl::ResetModalLoop (UINT id)
+{
+ Win4Assert(id < _cCallInfoMac && "ResetModalLoop: restoring wrong callinfo.");
+
+ // reset the old call state
+ // remove the call info from the table
+ {
+ CLock lck(_mxs);
+
+ FreeCallID(id);
+ // reset the current values
+ if (id == _cCur)
+ {
+ // reset it back to the first one in use
+ while( --_cCur != CALLDATAID_INVALID && !GetCIfromCallID(_cCur) )
+ ;
+ }
+ // lock leaves scope
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallMainControl::CallOnEvent
+//
+// Synopsis: this function is called when an event occurs signalling
+// the completion of the call
+//
+// Arguments: [pCI] - call info
+//
+// Returns: result of the call
+//
+// Algorithm:
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(void) CCallMainControl::CallOnEvent(PCALLINFO pCI)
+{
+ CairoleDebugOut((DEB_CALLCONT, "CallMainControl::OnEvent called pCI:%x hEvent:%x\n",
+ pCI, pCI->GetEvent()));
+
+#if DBG==1
+ if (!_fMultiThreaded)
+ {
+ // if we are not MT, then the pCI MUST be for the current thread
+ Win4Assert(pCI->GetTID() == GetCurrentThreadId() &&
+ "OnEvent: thread id wrong.");
+ }
+#endif
+
+ // in MT case only one thread should call OnEvent
+ if (!_fMultiThreaded || (pCI->GetTID() == GetCurrentThreadId()))
+ {
+ pCI->OnEvent();
+ }
+
+ CairoleDebugOut((DEB_CALLCONT, "CallMainControl::OnEvent returned\n"));
+ return;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallMainControl::PeekOriginAndDDEMessage
+//
+// Synopsis: Called when a windows message arrives to look for incoming
+// Rpc messages which might be the reply to an outstanding call
+// or may be new incoming messages requests.
+//
+// Arguments: [pCI] - call info
+// [pMsg] - ptr to message
+// [fDDEMsg] - TRUE -> search also for DDE messages
+//
+// Returns: nothing
+//
+// Algorithm:
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(void) CCallMainControl::PeekOriginAndDDEMessage(PCALLINFO pCI,
+ BOOL fDDEMsg)
+{
+ // loop over all call origins looking for incoming Rpc messages. Note that
+ // it is possible for a dispatch here to cause one of the call origins to
+ // be deregistered or another to be registered, so our loop has to account
+ // for that. The outer loop is OK because it always references the current
+ // count of ODs (_cODs). The while loop is OK because it always ensures
+ // _rgpOrigindata is non NULL.
+
+
+ CairoleDebugOut((DEB_CALLCONT, "PeekOriginAndDDEMessage: fDDEMsg:%d\n", fDDEMsg));
+
+ MSG Msg;
+
+ for (UINT i = 0; i < _cODs; i++)
+ {
+ ORIGINDATA *pOD;
+
+ while ( pCI->IsWaiting() // waiting for current call to complete
+ && ((pOD = _rgpOrigindata[i]) != NULL) // origin data is valid
+ && (MyPeekMessage(pCI, &Msg, pOD->hwnd,
+ pOD->wFirstMsg, pOD->wLastMsg,PM_REMOVE | PM_NOYIELD)))
+ {
+ // dispatch all messages
+ CairoleDebugOut((DEB_CALLCONT,
+ "Origin Msg to dispatch: hwnd:%d, msg:%d time:%ld\n",
+ Msg.hwnd, Msg.message, Msg.time));
+ DispatchMessage(&Msg);
+ }
+ }
+
+ if (fDDEMsg)
+ {
+ while ( pCI->IsWaiting()
+ && MyPeekMessage(pCI, &Msg, 0,WM_DDE_FIRST, WM_DDE_LAST,
+ PM_REMOVE | PM_NOYIELD))
+ {
+ CairoleDebugOut((DEB_CALLCONT,
+ "DDE message to dispatch: hwnd: %x, message %x time: %ld\n",
+ Msg.hwnd,Msg.message, Msg.time));
+ DispatchMessage(&Msg);
+ }
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallMainControl::MyPeekMessage
+//
+// Synopsis: This function is called whenever we want to do a PeekMessage.
+// It has special handling for WM_QUIT messages.
+//
+// Arguments: [pCI] - call info
+// [pMsg] - message structure
+// [hWnd] - window to peek on
+// [min/max] - min and max message numbers
+// [wFlag] - peek flags
+//
+// Returns: TRUE - a message is available
+// FALSE - no messages available
+//
+// Algorithm:
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(BOOL) CCallMainControl::MyPeekMessage(PCALLINFO pCI,
+ MSG *pMsg, HWND hwnd, UINT min, UINT max, WORD wFlag)
+{
+ BOOL fRet = PeekMessage(pMsg, hwnd, min, max, wFlag);
+ if (fRet)
+ {
+ CairoleDebugOut((DEB_CALLCONT, "MyPeekMessage: hwnd:%x, msg:%x time:%x\n", pMsg->hwnd, pMsg->message, pMsg->time));
+ if (pMsg->message == WM_QUIT)
+ {
+ // just remember that we saw a QUIT message. we will ignore it for
+ // now and repost it after our call has completed.
+
+ CairoleDebugOut((DEB_CALLCONT, "WM_QUIT received while waiting on remote call\n"));
+ pCI->SetQuitCode(pMsg->wParam);
+
+ if (wFlag & PM_NOREMOVE)
+ {
+ // quit message is still on queue so pull it off
+ PeekMessage(pMsg, hwnd, WM_QUIT, WM_QUIT, PM_REMOVE | PM_NOYIELD);
+ }
+
+ // peek again to see if there is another message
+ fRet = PeekMessage(pMsg, hwnd, min, max, wFlag);
+ }
+ }
+
+ return fRet;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallMainControl::FindMessage
+//
+// Synopsis: Called by HandleWakeForMsg when a message arrives on the
+// windows msg queue. Determines if there is something of
+// interest to us, and pulls timer msgs. Dispatches RPC, DDE,
+// and RPC timer messages.
+//
+// Arguments: [pCI] - call info
+// [dwStatus] - current Queue status (from GetQueueStatus)
+//
+// Returns: TRUE - there is a message to process
+// FALSE - no messages to process
+//
+// Algorithm: Find the next message in the queue by using the following
+// priority list:
+//
+// 1. RPC and DDE messages
+// 2. mouse and keyboard messages
+// 3. other messages
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(BOOL) CCallMainControl::FindMessage(PCALLINFO pCI, DWORD dwStatus)
+{
+ WORD wOld = HIWORD(dwStatus);
+ WORD wNew = (WORD) dwStatus;
+
+ if (!wNew)
+ {
+ if (!(wOld & QS_POSTMESSAGE))
+ {
+ // there are no message to take care of
+ return FALSE;
+ }
+ else
+ {
+ wNew |= QS_POSTMESSAGE;
+ }
+ }
+
+ MSG Msg;
+
+ // Priority 1: look for CALLORIGIN and DDE messages
+ if (wNew & (QS_POSTMESSAGE | QS_SENDMESSAGE | QS_TIMER))
+ {
+ PeekOriginAndDDEMessage(pCI, TRUE);
+
+ // check if we got the acknowledge
+ if (!pCI->IsWaiting())
+ return FALSE;
+ }
+
+ if (wNew & QS_TIMER)
+ {
+ // throw the system timer messages away
+ while (MyPeekMessage(pCI, &Msg, 0, WM_SYSTIMER, WM_SYSTIMER, PM_REMOVE | PM_NOYIELD))
+ ;
+ }
+
+ // Priority 2: messages from the hardware queue
+ if (wNew & (QS_KEY | QS_MOUSEMOVE | QS_MOUSEBUTTON))
+ {
+ // this messages are always removed
+ return TRUE;
+ }
+ else if (wNew & QS_TIMER)
+ {
+ if (MyPeekMessage(pCI, &Msg, 0, WM_TIMER, WM_TIMER, PM_NOREMOVE | PM_NOYIELD) )
+ return TRUE;
+ }
+ else if (wNew & QS_PAINT)
+ {
+ // this message might not get removed
+ return TRUE;
+ }
+ else if (wNew & (QS_POSTMESSAGE | QS_SENDMESSAGE))
+ {
+ if (MyPeekMessage(pCI, &Msg, 0, 0, 0, PM_NOREMOVE))
+ {
+ // Priority 3: all other messages
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallMainControl::HandleWakeForMsg (private)
+//
+// Synopsis: Handle wake for the arrival of some kind of message
+//
+// Arguments: [dwInput] - input type for call to wake up on
+// [pCI] - call information structure
+// [fClearedQueueInPast] - whether we ever decided to clear queue
+//
+// Returns: nothing
+// pCI->fClearedQueue set if appropriate
+//
+// Algorithm: If this is called to wake up for a posted message, we
+// check the queue status. If the message queue status indicates
+// that there is some kind of a modal loop going on, then we
+// clear all the keyboard and mouse messages in our queue. Then
+// if we wake up for all input, we check the message queue to
+// see whether we need to notify the application that a message
+// has arrived. Then, we dispatch any messages that have to do
+// with the ORPC system. Finally we yield just in case we need
+// to dispatch a send message in the VDM. For an input sync
+// RPC, all we do is a call that will yield to get the pending
+// send message dispatched.
+//
+// History: 13-Aug-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+INTERNAL_(void) CCallMainControl::HandleWakeForMsg(DWORD dwInput,
+ PCALLINFO pCI)
+{
+ // Use for various peeks.
+ MSG msg;
+
+ // Is this an input sync call?
+ if (dwInput != QS_SENDMESSAGE)
+ {
+ // No, so we have to worry about the state of the message queue.
+ // We have to be careful that we aren't holding the input focus
+ // on an input synchronized queue.
+
+ // So what is the state of the queue? - note we or QS_TRANSFER because
+ // this an undocumented flag which tells us the the input focus has
+ // changed to us.
+ DWORD dwQueueFlags =
+ GetQueueStatus(QS_TRANSFER | QS_ALLINPUT);
+
+ CairoleDebugOut((DEB_CALLCONT, "Queue Status %lx\n", dwQueueFlags));
+
+ // Call through to the application if we are going to. We do this here
+ // so that the application gets a chance to process any
+ // messages that it wants to and also allows the call control to
+ // dispatch certain messages that it knows how to, thus making the
+ // queue more empty.
+ if (((dwInput & QS_ALLINPUT) == QS_ALLINPUT)
+ && FindMessage(pCI, dwQueueFlags))
+ {
+ CairoleDebugOut((DEB_CALLCONT, "HandlePendingMessage calling\n"));
+ // pending message in the queue
+ HandlePendingMessage(pCI);
+ }
+
+ // Did the input focus change to us?
+ if (((LOWORD(dwQueueFlags) & QS_TRANSFER)) || pCI->GetClearedQueue())
+ {
+ CairoleDebugOut((DEB_CALLCONT, "Message Queue is being cleared\n"));
+ pCI->SetClearedQueue();
+
+ // Try to clear the queue as best we can of any messages that
+ // might be holding off some other modal loop from executing.
+ // So we eat all mouse and key events.
+ if (HIWORD(dwQueueFlags) & QS_KEY)
+ {
+ while (MyPeekMessage(pCI, &msg, NULL, WM_KEYFIRST, WM_KEYLAST,
+ PM_REMOVE | PM_NOYIELD))
+ {
+ ;
+ }
+ }
+
+ // Clear mouse releated messages if there are any
+ if (HIWORD(dwQueueFlags) & QS_MOUSE)
+ {
+ while (MyPeekMessage(pCI, &msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST,
+ PM_REMOVE | PM_NOYIELD))
+ {
+ ;
+ }
+
+ while (MyPeekMessage(pCI, &msg, NULL, WM_NCMOUSEFIRST,
+ WM_NCMOUSELAST, PM_REMOVE | PM_NOYIELD))
+ {
+ ;
+ }
+
+ while (MyPeekMessage(pCI, &msg, NULL, WM_QUEUESYNC, WM_QUEUESYNC,
+ PM_REMOVE | PM_NOYIELD))
+ {
+ ;
+ }
+ }
+
+ // Get rid of paint message if we can as well -- this makes
+ // the screen look so much better.
+ if (HIWORD(dwQueueFlags) & QS_PAINT)
+ {
+ if (MyPeekMessage(pCI, &msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE | PM_NOYIELD))
+ {
+ CairoleDebugOut((DEB_CALLCONT, "Dispatch paint\n"));
+ DispatchMessage(&msg);
+ }
+ }
+ }
+
+ // We process posted messages so make sure DDE and
+ // RPC have all their messages handled.
+ PeekOriginAndDDEMessage(pCI, TRUE);
+
+ if (IsWOWThreadCallable())
+ {
+ // In WOW, a genuine yield is the only thing to guarantee
+ // that SendMessage will get through
+ g_pOleThunkWOW->YieldTask16();
+ }
+
+ }
+ else
+ {
+ // We need to give user control so that the send message
+ // can get dispatched. Thus the following is simply a no-op
+ // which gets into user to let it dispatch the message.
+ if (!IsWOWThreadCallable())
+ {
+ PeekMessage(&msg, 0, WM_NULL, WM_NULL, PM_NOREMOVE);
+ }
+ else
+ {
+ // In WOW, a genuine yield is the only thing to guarantee
+ // that SendMessage will get through
+ g_pOleThunkWOW->YieldTask16();
+ }
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallMainControl::BlockFn (private)
+//
+// Synopsis: implements the modal loop part of a call. This block function
+// is called either by the transmit code above, or by the Rpc
+// runtime during a call.
+//
+// Arguments: none
+//
+// Returns: result of the call
+//
+// Algorithm:
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+//--------------------------------------------------------------------------
+INTERNAL CCallMainControl::BlockFn(void)
+{
+ COleTls tls;
+ PCALLINFO pCICur = (PCALLINFO) tls->pCALLINFO;
+ Win4Assert(pCICur && "Blocked but no call in progress!");
+
+ DWORD dwStatus = 0;
+ CALLCATEGORY CallCatOut = pCICur->GetCallCat();
+ DWORD dwInput = pCICur->GetMsgQInputFlag();
+
+ CairoleDebugOut((DEB_CALLCONT,
+ "CallMainControl::BlockFn CallCat:%x, dwInput:%x\n",
+ CallCatOut, dwInput));
+
+
+ // wait for an incomming message or for the call to complete.
+ DWORD dwWakeReason = WAIT_TIMEOUT;
+ EVENT rgEvents[1];
+ DWORD cEvents = 0;
+
+ rgEvents[0] = pCICur->GetEvent();
+ if (rgEvents[0] != NULL)
+ {
+ // first check if the event is already signalled. This ensures
+ // that when we return from nested calls and the upper calls
+ // have already been acknowledged, that no windows messages
+ // can come in.
+
+ cEvents = 1;
+ CairoleDebugOut((DEB_CALLCONT, "WaitForSingleObject hEvent:%x\n", rgEvents[1]));
+ dwWakeReason = WaitForSingleObject(rgEvents[0], 0);
+ }
+
+ if (dwWakeReason == WAIT_TIMEOUT)
+ {
+ // event (if any) is not signalled yet, wait for more work, either
+ // the call to complete, a SCM call to come in that MUST get through,
+ // or a message arrives (except if we are making an outgoing SCM call)
+
+ // in Wow, do a directed yield because MsgWaitForMultiple does
+ // not yield. If the call is handled during that time, a msg
+ // should have been posted and MsgWait will wake up immediately.
+
+ DWORD WaitTime;
+
+ pCICur->DoDirectedYieldIfNeeded();
+
+ // Even if we do a directed yield, there is no particular reason
+ // not to wait the maximum amount of time since we have to wait
+ // some time if we want to be sure to get a QS_TRANSFER indication.
+ WaitTime = pCICur->TicksToWait();
+
+ // If we want to wake up for a posted message, we need to make
+ // sure that we haven't missed any because of the queue status
+ // being affected by prior PeekMessages. We don't worry about
+ // QS_SENDMESSAGE because if PeekMessage got called, the pending
+ // send got dispatched. Further, if we are in an input sync call,
+ // we don't want to start dispatching regular RPC calls here by
+ // accident.
+ if (dwInput & QS_POSTMESSAGE)
+ {
+ dwStatus = GetQueueStatus(dwInput);
+
+ // We care about any message on the queue not just new messages
+ // because PeekMessage affects the queue state. It resets the
+ // state so even if a message is not processed, the queue state
+ // represents this as an old message even though no one has
+ // ever looked at it. So even though the message queue tells us
+ // there are no new messages in the queue. A new message we are
+ // interested in could be in the queue.
+ WORD wNew = (WORD) dwStatus | HIWORD(dwStatus);
+
+ // Note that we look for send as well as post because our
+ // queue status could have reset the state of the send message
+ // bit and therefore, MsgWaitForMultipleObject below will not
+ // wake up to dispatch the send message.
+ if (wNew & (QS_POSTMESSAGE | QS_SENDMESSAGE))
+ {
+ // the acknowledge message might be already in the queue
+ PeekOriginAndDDEMessage(pCICur, TRUE);
+
+ // check if we got the acknowledge
+ if (!pCICur->IsWaiting())
+ {
+ return RPC_S_OK;
+ }
+ }
+
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ WORD wOld = HIWORD(dwStatus);
+
+ if (wOld & (QS_POSTMESSAGE))
+ {
+ CairoleDebugOut((DEB_CALLCONT | DEB_IWARN, "Set timeout time to 100\n"));
+ WaitTime = 100;
+ }
+#endif //_CHICAGO_
+ }
+
+ CairoleDebugOut((DEB_CALLCONT,
+ "MsgWaitForMultiple cEvents:%x hEvent[0]:%x WaitTime:%x dwInput:%x\n",
+ cEvents, rgEvents[0], WaitTime, dwInput));
+
+ dwWakeReason = MsgWaitForMultipleObjects(cEvents, rgEvents, FALSE,
+ WaitTime, dwInput);
+
+ CairoleDebugOut((DEB_CALLCONT,"MsgWaitForMultipleObject returned:%ld\n",
+ dwWakeReason));
+ }
+
+ // OK, we've done whatever blocking we were going to do and now we have
+ // been woken up, so figure out why we woke up and handle it.
+
+ if (dwWakeReason == (WAIT_OBJECT_0 + cEvents))
+ {
+ HandleWakeForMsg(dwInput, pCICur);
+ }
+ else if (dwWakeReason == WAIT_TIMEOUT)
+ {
+ // retrytimer is at zero - exit and retransmit the call
+ CairoleDebugOut((DEB_CALLCONT, "Timer at zero!\n"));
+
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ WORD wOld = HIWORD(dwStatus);
+ //
+ // we need to call message pending here since there might be a message the app has not seen yet
+ //
+ if (wOld & (QS_POSTMESSAGE))
+ {
+ CairoleDebugOut((DEB_CALLCONT | DEB_IWARN, "Timer at zero - Calling HandleWakeForMsg\n"));
+ HandleWakeForMsg(dwInput, pCICur);
+ CairoleDebugOut((DEB_CALLCONT | DEB_IWARN, "Timer at zero - Calling HandleWakeForMsg done\n"));
+ }
+#endif // _CHICAGO_
+ }
+ else
+ {
+ // an event was signaled
+ Win4Assert(dwWakeReason >= WAIT_OBJECT_0 && dwWakeReason < WAIT_OBJECT_0 + cEvents
+ && "Bad return from (Msg)WaitFor(Single/Multiple)Objects");
+
+ // call completion event was signalled
+ CairoleDebugOut((DEB_CALLCONT, "CallComplete Event signaled\n"));
+ CallOnEvent(pCICur);
+ }
+
+
+ if (pCICur->GetCallState() == Call_Canceled)
+ return RPC_S_CALL_CANCELLED;
+ else
+ {
+ // return call fail in case of timout
+ return (dwWakeReason == WAIT_TIMEOUT) ? RPC_S_CALL_IN_PROGRESS : RPC_S_OK;
+
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallMainControl::TransmitAndRunModalLoop (private)
+//
+// Synopsis: transmits an outgoing call, then enters a modal loop until
+// the reply comes in.
+//
+// Arguments: [pCI] - call information structure
+//
+// Returns: result of the call
+//
+// Algorithm:
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+//--------------------------------------------------------------------------
+INTERNAL CCallMainControl::TransmitAndRunModalLoop (PCALLINFO pCICur)
+{
+ TRACECALL(TRACE_CALLCONT, "CCallMainControl::TrasmitAndRunModalLoop");
+
+ // set up the call info
+ // CODEWORK: nuke this and use a linked list on the stack
+
+ UINT id = SetupModalLoop(pCICur);
+ if (id == CALLDATAID_INVALID)
+ {
+ Win4Assert(id && "RunModalLoop: could not set up callinfo.\n");
+ return RPC_E_INVALID_CALLDATA;
+ }
+
+ COleTls tls;
+ PCALLINFO pCIPrev = (PCALLINFO) tls->pCALLINFO;
+ tls->pCALLINFO = (void *)pCICur;
+
+ do
+ {
+ // Transmit the call.
+ CairoleDebugOut((DEB_CALLCONT, "TransmitCall pCI:%x pCIPrev:%x\n", pCICur, pCIPrev));
+ TransmitCall(pCICur);
+
+ // In the MSWMSG protocol, TransmitCall is a blocking call. The Rpc
+ // transport will transmit the call asynchronously then call us back
+ // in BlockFn which is our real modal loop. When this call returns,
+ // IsWaiting will be FALSE.
+ //
+ // For all other protocols, including DDE, TransmitCall is non
+ // blocking so we have to call the BlockFn ourselves. In these cases,
+ // IsWaiting will be TRUE until the call completes.
+ //
+ // For all protocols, input synchronous calls and failed calls will
+ // return with IsWaiting FALSE.
+
+ while (pCICur->IsWaiting())
+ {
+ BlockFn();
+ }
+
+ // By this point the call has completed. Now check if it was rejected
+ // and if so, whether we need to retry immediately, later, or never.
+ // Handling of Rejected calls must occur here, not in the BlockFn, due
+ // to the fact that some calls and some protocols are synchronous, and
+ // other calls and protocols are asynchronous.
+
+ if (pCICur->IsRejected())
+ {
+ // this function decides on 1 of 3 different courses of action
+ // 1. fail the call - sets the state to Call_Rejected
+ // 2. retry immediately - starts timer but set to zero time
+ // 3. retry later - starts the timer, set to > 100
+
+ HandleRejectedCall(pCICur);
+
+ // have to go into modal loop if there is a timer installed to
+ // retry the call later. if the call is cancelled while in this
+ // loop, the loop will be exited.
+
+ while (!pCICur->IsTimerAtZero())
+ {
+ BlockFn();
+ }
+
+ // Either it is time to retransmit the call, or the call was
+ // cancelled or rejected. Clear the timer just in case.
+
+ pCICur->ClearTimer();
+ }
+
+ // the only way we could be waiting now is if the call is about to
+ // be retried after being rejected.
+
+ } while (pCICur->IsWaiting());
+
+ Win4Assert(pCICur->GetCallState() == Call_Ok ||
+ pCICur->GetCallState() == Call_Error ||
+ pCICur->GetCallState() == Call_Canceled ||
+ pCICur->GetCallState() == Call_Rejected);
+
+ HRESULT hr = pCICur->GetHresultOfCall();
+
+ // CODEWORK: do this in the dtor
+ // restore the current callinfo
+ tls->pCALLINFO = (void *)pCIPrev;
+
+
+ // reset the call info - we are done with this call
+ // CODEWORK: nuke this
+ ResetModalLoop(id);
+
+ // only the lowest modal loop should repost the Quit message
+ // CODEWORK: move this into dtor of pCI
+ pCICur->HandleQuitCode();
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CCallMainControl::TransmitCall
+//
+// Synopsis: sets our call state and transmits the call to the server.
+//
+// Arguments: [pCI] - call info
+//
+// Returns: result of the call
+//
+// Algorithm:
+//
+// History: Dec-93 JohannP (Johann Posch) Created
+//
+//--------------------------------------------------------------------------
+INTERNAL CCallMainControl::TransmitCall(PCALLINFO pCI)
+{
+ TRACECALL(TRACE_CALLCONT, "CCallMainControl::TransmitCall called");
+ Win4Assert(pCI && "CCallMainControl::TransmitCall Invalid CallInfo");
+
+
+ HRESULT hr;
+ // set our internal state to indicate we are making a call
+ pCI->SetCallState(Call_WaitOnCall, S_OK);
+
+ // Transmit may issue a callback to BlockFn.
+ hr = pCI->Transmit();
+
+ if (FAILED(hr))
+ {
+ if (hr == RPC_E_SERVERCALL_RETRYLATER)
+ {
+ pCI->SetCallState(Call_RetryLater, RPC_E_SERVERCALL_RETRYLATER);
+ }
+ else if (hr == RPC_E_SERVERCALL_REJECTED)
+ {
+ pCI->SetCallState(Call_Rejected, RPC_E_SERVERCALL_REJECTED);
+ }
+ else if (hr == RPC_E_CALL_CANCELED)
+ {
+ pCI->SetCallState(Call_Canceled, hr);
+ }
+ else
+ {
+ // the call failed, set the state to error. This also ensures
+ // IsWaiting returns FALSE.
+ pCI->SetCallState(Call_Error, hr);
+ }
+ }
+
+ return hr;
+}
diff --git a/private/ole32/com/remote/callmain.hxx b/private/ole32/com/remote/callmain.hxx
new file mode 100644
index 000000000..13fb94a1b
--- /dev/null
+++ b/private/ole32/com/remote/callmain.hxx
@@ -0,0 +1,505 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: CallCont.hxx (32 bit target)
+//
+// Contents: Contains the CallControl interface
+//
+// Functions:
+//
+// History: 23-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+#ifndef _CALLMAIN_HXX_
+#define _CALLMAIN_HXX_
+
+#include <dde.h>
+#include <scode.h>
+#include <objerror.h>
+#include <sem.hxx>
+#include <chancont.hxx>
+
+
+// Private definition for change of input focus
+#define QS_TRANSFER 0x4000
+
+// Maximum time we will wait for a response on message wait for multiple.
+// Note: this must be less than infinite because MsgWaitForMultipleObjects
+// will not wake up on messages posted before it is called.
+#define MAX_TICKS_TO_WAIT 1000
+
+
+typedef enum tagCallState
+{
+ // BUGBUG: rickhi: make these bitmasks and we can do computations faster.
+ // the following codes map with SERVERCALL
+ Call_Ok = 0, // call was successful
+ Call_Rejected = 1, // call was rejected by callee
+ Call_RetryLater = 2, // call was busy ack by callee
+ Call_Error = 3, // call was ack with errror
+ // internal call state codes
+ Call_WaitOnCall = 4, // call was transmited, wait for return
+ Call_Canceled = 5, // call was cancelled by caller
+ Call_WaitOnTimer = 6, // call is waiting on running timer
+
+} CallState;
+
+
+//
+// to pass back an error from the callee
+//
+#define SERVERCALL_FIRST SERVERCALL_RETRYLATER
+#define SERVERCALL_ERROR SERVERCALL_FIRST+1
+#define SERVERCALL_REPOSTED SERVERCALL_FIRST+2
+
+
+#define CALLTYPE_NOCALL (CALLTYPE)0
+
+// bit values for call info flags
+typedef enum tagCALLFLAGS
+{
+ CIF_QUITRECEIVED = 1, // WM_QUIT was received
+ CIF_CLEAREDQUEUE = 2 // Cleared the Msg queue in the past
+} CALLFLAGS;
+
+class CCallInfo{
+public:
+
+ CCallInfo(PCALLDATA pCalldata, PORIGINDATA pOrigindata)
+ {
+ Win4Assert(pCalldata && pOrigindata);
+
+ _pCalldata = pCalldata;
+ _pOrigindata = pOrigindata;
+ _dwFlags = 0; // all flags start FALSE
+ _tid = GetCurrentThreadId(); // used in MT case
+ _dwTimeOfCall = GetTickCount();
+
+#if 0 // the following fields are initialized when the
+ // call is first xmited
+ _id = 0; // set by SetupModalLoop
+ _CallState = Call_WaitOnCall; // set by SetState
+ _hresult = S_OK;
+
+ // the following fields are initialized only if we go into
+ // a wait state
+ _dwWakeup = 0; // set by StartTimer
+ _dwMillSecToWait = 0;
+
+ // the following field is initialized only if we receive a quit msg
+ _wQuitCode = 0;
+#endif
+
+ }
+
+ INTERNAL_(VOID) SetCallState (CallState callstate, SCODE scode)
+ {
+ _hresult = scode;
+ _CallState = callstate;
+ }
+ INTERNAL_(DWORD) GetCallState()
+ {
+ return _CallState;
+ }
+
+ // CODEWORK: ensure all callers of SetState do the right thing and this
+ // function can be a noop.
+ INTERNAL GetHresultOfCall()
+ {
+ switch (_CallState)
+ {
+ case Call_Ok:
+ case Call_Error:
+ break;
+
+ case Call_Canceled:
+ _hresult = RPC_E_CALL_CANCELED;
+ break;
+
+ case Call_Rejected:
+ case Call_RetryLater:
+ _hresult = RPC_E_CALL_REJECTED;
+ break;
+
+ default:
+ Win4Assert(!"CallInfo: invalid state at return");
+ break;
+ }
+ return _hresult;
+ }
+
+ INTERNAL_(BOOL) IsWaiting()
+ {
+ return (_CallState == Call_WaitOnCall || _CallState == Call_WaitOnTimer);
+ }
+ INTERNAL_(BOOL) IsRejected()
+ {
+ return (_CallState == Call_Rejected || _CallState == Call_RetryLater);
+ }
+
+ INTERNAL_(void) SetClearedQueue(void)
+ {
+ _dwFlags |= CIF_CLEAREDQUEUE;
+ }
+ INTERNAL_(BOOL) GetClearedQueue(void)
+ {
+ return _dwFlags & CIF_CLEAREDQUEUE;
+ }
+
+ INTERNAL_(void) SetQuitCode(UINT wParam)
+ {
+ _wQuitCode = wParam;
+ _dwFlags |= CIF_QUITRECEIVED;
+ }
+ INTERNAL_(void) HandleQuitCode()
+ {
+ if (_dwFlags & CIF_QUITRECEIVED)
+ {
+ CairoleDebugOut((DEB_CALLCONT, "posting WM_QUIT\n"));
+ PostQuitMessage(_wQuitCode);
+ }
+ }
+
+ INTERNAL_(BOOL) LookForAllMsg()
+ {
+ return _pCalldata->CallCat != CALLCAT_INPUTSYNC;
+ }
+ INTERNAL_(DWORD) GetTaskIdServer()
+ {
+ return _pCalldata->TIDCallee;
+ }
+ INTERNAL_(REFLID) GetLID()
+ {
+ return _pCalldata->lid;
+ }
+ INTERNAL_(DWORD) GetTID()
+ {
+ return _tid;
+ }
+ INTERNAL_(CALLCATEGORY) GetCallCat()
+ {
+ return _pCalldata->CallCat;
+ }
+
+ INTERNAL_(void) StartTimer(DWORD dwMilliSecToWait)
+ {
+ // set time when we should awake and retry the call. note that
+ // if the GetTickCount + dwMilliSecToWait wraps the timer, then
+ // we may wakeup earlier than expected, but at least we wont
+ // deadlock.
+
+ CairoleDebugOut((DEB_ERROR,
+ "Timer insstalled for %lu msec.\r\n", dwMilliSecToWait));
+
+ _dwMillSecToWait = dwMilliSecToWait;
+ _dwWakeup = GetTickCount() + dwMilliSecToWait;
+
+ SetCallState(Call_WaitOnTimer, S_OK);
+ }
+ INTERNAL_(void) ClearTimer()
+ {
+ _dwMillSecToWait = _dwWakeup = 0;
+ }
+ INTERNAL_(BOOL) IsTimerAtZero()
+ {
+ // if no timer installed, return TRUE
+ if (_CallState != Call_WaitOnTimer)
+ return TRUE;
+
+ DWORD dwTickCount = GetTickCount();
+
+ // the second test is in case GetTickCount wrapped during
+ // the call. see also the comment in StartTimer.
+
+ return (dwTickCount > _dwWakeup ||
+ dwTickCount < _dwWakeup - _dwMillSecToWait);
+ }
+ INTERNAL_(DWORD) TicksToWait()
+ {
+ if (_CallState != Call_WaitOnTimer)
+ return MAX_TICKS_TO_WAIT;
+
+ // waiting to retry a rejected call
+ DWORD dwTick = GetTickCount();
+ return (_dwWakeup < dwTick) ? 0 : _dwWakeup - dwTick;
+ }
+ INTERNAL_(DWORD) GetElapsedTime();
+
+
+ INTERNAL_(EVENT) GetEvent()
+ {
+ return _pCalldata->Event;
+ }
+ INTERNAL_(void) SetEvent(EVENT Event)
+ {
+ _pCalldata->Event = Event;
+ }
+ INTERNAL_(UINT) GetId()
+ {
+ return _id;
+ }
+ INTERNAL_(void) SetId(UINT id)
+ {
+ _pCalldata->id = _id = id;
+ }
+ INTERNAL Transmit()
+ {
+ CairoleDebugOut((DEB_CALLCONT, "CCallInfo::TransmitCall TIDCallee:%x called\n",
+ _pCalldata->TIDCallee));
+
+ _pCalldata->Event = NULL;
+
+ HRESULT hres = _pOrigindata->pChCont->TransmitCall(_pCalldata);
+
+ CairoleDebugOut((DEB_CALLCONT, "CCallInfo::TransmitCall TIDCallee:%x returned :%x\n",
+ _pCalldata->TIDCallee, hres));
+ return hres;
+ }
+
+ INTERNAL OnEvent()
+ {
+ CairoleDebugOut((DEB_CALLCONT, "CCallInfo::OnEvent returned\n"));
+ return _pOrigindata->pChCont->OnEvent(_pCalldata);
+ }
+
+ INTERNAL_(DWORD) GetMsgQInputFlag()
+ {
+ DWORD dwInput;
+
+ // CODEWORK: optimize this using a table lookup instead of
+ // a switch statement
+
+ switch (_pCalldata->CallCat)
+ {
+ case CALLCAT_INTERNALSYNC:
+#ifdef _CHICAGO_
+ // BUGBUG: Chicago needs user update for QS_TRANSFER
+ dwInput = QS_POSTMESSAGE | QS_SENDMESSAGE;
+#else
+ dwInput = QS_POSTMESSAGE | QS_SENDMESSAGE | QS_TRANSFER;
+#endif // _CHICAGO_
+ break;
+
+ case CALLCAT_INTERNALINPUTSYNC:
+ case CALLCAT_INPUTSYNC:
+ dwInput = QS_SENDMESSAGE;
+ break;
+
+ default:
+#ifdef _CHICAGO_
+ // BUGBUG: Chicago needs user update for QS_TRANSFER
+ dwInput = QS_ALLINPUT;
+#else
+ dwInput = QS_ALLINPUT | QS_TRANSFER;
+#endif // _CHICAGO_
+ break;
+ }
+
+ return dwInput;
+ }
+
+ INTERNAL_(BOOL) DoDirectedYieldIfNeeded()
+ {
+ if (_pCalldata->fDirectedYield)
+ {
+ CairoleDebugOut((DEB_CALLCONT, "DoDirectedYield\n"));
+ Win4Assert(IsWOWThread());
+ g_pOleThunkWOW->DirectedYield(_pCalldata->TIDCallee);
+ return TRUE;
+ }
+ else
+ {
+ CairoleDebugOut((DEB_CALLCONT, "Skip DoDirectedYield\n"));
+ return FALSE;
+ }
+ }
+
+private:
+ UINT _id; // callinfo id for the table lookup
+ DWORD _tid; // threadid where call is made on
+
+ // call state
+ CallState _CallState; // our current call state
+ DWORD _dwFlags; // internal flags
+ UINT _wQuitCode; // quit code if WM_QUIT received
+ HRESULT _hresult; // the return value of this call
+
+ // timer status for this callinfo
+ DWORD _dwTimeOfCall; // time when call was made
+ DWORD _dwWakeup; // absolute time to wake up
+ DWORD _dwMillSecToWait; // relative time
+
+ // caller specific information
+ PCALLDATA _pCalldata;
+ PORIGINDATA _pOrigindata;
+};
+typedef CCallInfo *PCALLINFO;
+
+
+class FAR CCallMainControl
+{
+public:
+ INTERNAL_(ULONG) AddRef();
+ INTERNAL_(ULONG) Release();
+
+ // wrapper of messagfilter methods
+ INTERNAL CanHandleIncomingCall( DWORD TIDCaller, REFLID lid,
+ PINTERFACEINFO32 pIfInfo);
+ INTERNAL_(DWORD) GetElapsedTimeOfLastOutCall();
+
+ INTERNAL CanMakeOutCall (CALLCATEGORY callcat, REFIID iid);
+ INTERNAL_(void) HandleRejectedCall (PCALLINFO pCI);
+ INTERNAL_(DWORD) HandlePendingMessage (PCALLINFO pCI);
+ INTERNAL_(BOOL) DispatchSystemMessage (MSG msg, BOOL fBeep = TRUE);
+
+ // modal loop functions - Origin is who called the loop
+ INTERNAL TransmitAndRunModalLoop (PCALLINFO pCI);
+ INTERNAL_(BOOL) FindMessage (PCALLINFO pCI, DWORD dwStatus);
+ INTERNAL_(void) PeekOriginAndDDEMessage(PCALLINFO pCI, BOOL fDDEMsg);
+
+ INTERNAL TransmitCall(PCALLINFO pCI);
+ INTERNAL_(void) CallOnEvent(PCALLINFO pCI);
+ INTERNAL_(BOOL) MyPeekMessage(PCALLINFO pCI ,MSG *pMsg, HWND hwnd, UINT min, UINT max, WORD wFlag);
+
+ //
+ // the main call type stat
+ //
+ INTERNAL_(CALLTYPE) GetCallType () { return _CallType; }
+ INTERNAL_(void) SetCallType (CALLTYPE calltype)
+ {
+ CairoleDebugOut((DEB_CALLCONT, "Changing _CallType from:%x to:%x\n", _CallType, calltype));
+ _CallType = calltype;
+ }
+ INTERNAL_(CALLTYPE) SetCallTypeOfCall (PCALLINFO pCI, CALLCATEGORY callcat);
+
+ INTERNAL_(CALLCATEGORY) SetCallCatOfInCall (CALLCATEGORY callcat)
+ {
+ CALLCATEGORY ccold = _CallCat;
+ _CallCat = callcat;
+ return ccold;
+ }
+ INTERNAL_(CALLCATEGORY) GetCallCatOfInCall ()
+ {
+ return _CallCat;
+ }
+
+ // install/ remove the message filter - by app
+ INTERNAL_(PMESSAGEFILTER32) GetMessageFilter()
+ {
+#ifdef _CAIRO_
+ // cairo allows multithreading, so one thread could change the MF
+ // while another thread is using it. To prevent that we AddRef the
+ // MF then Release it when done. It is the callers responsibility
+ // to take the mutex when calling this function.
+ if (_pMF)
+ {
+ _pMF->AddRef();
+ }
+#endif
+ return _pMF;
+ };
+
+ INTERNAL_(void) ReleaseMessageFilter(PMESSAGEFILTER32 pMF)
+ {
+#ifdef _CAIRO_
+ // cairo allows multithreading, so one thread could release while
+ // another is using the MF. To prevent that we AddRef and Release
+ // the pMF when using it
+ pMF->Release();
+#endif
+ };
+
+
+ INTERNAL_(PMESSAGEFILTER32) SetMessageFilter (PMESSAGEFILTER32 pMF);
+
+ INTERNAL_(BOOL)Register (PORIGINDATA pOrigindata);
+ INTERNAL_(BOOL)Unregister (PORIGINDATA pOrigindata);
+
+ // Aysnc Rpc Block callback function
+ INTERNAL BlockFn(void);
+
+ // bookkeeping for running callinfos on the stack - used for timer stuff
+ INTERNAL_(PCALLINFO) GetPrevCallInfo (REFLID lid);
+
+ // CODEWORK: nuke the following 5 functions & use a linked list
+ INTERNAL_(UINT) SetupModalLoop (PCALLINFO pCI);
+ INTERNAL_(void) ResetModalLoop (UINT id);
+ INTERNAL_(UINT) InsertCI (PCALLINFO pCI);
+ INTERNAL_(PCALLINFO) GetCIfromCallID (UINT callid)
+ {
+ // Get the callinfo associated with the call id
+ Win4Assert(callid < _cCallInfoMac
+ && L"CCallMainControl::FreeCallID invalid call id.");
+
+ return _CallInfoTable[callid];
+ }
+ INTERNAL_(void) CCallMainControl::FreeCallID (UINT callid)
+ {
+ // frees the entrie in the table - only called by ResetModalLoop
+ Win4Assert(callid < _cCallInfoMac
+ && L"CCallMainControl::FreeCallID invalid call id.");
+
+ _CallInfoTable[callid] = 0;
+ }
+
+
+ INTERNAL_(void) BeginCriticalSection()
+ {
+ if (_fMultiThreaded)
+ _mxs.Request();
+ }
+ INTERNAL_(void) EndCriticalSection()
+ {
+ if (_fMultiThreaded)
+ _mxs.Release();
+ }
+
+ CCallMainControl();
+ ~CCallMainControl();
+
+private:
+
+ INTERNAL_(void) HandleWakeForMsg(DWORD dwInput, PCALLINFO pCI);
+
+ long _cRef; // reference count
+
+ // Note: Main Call State
+ // here we remember the current state the app is
+ // if the call was at the 'root' level the call state is 0
+ CALLTYPE _CallType; // call state of server
+ CALLCATEGORY _CallCat; // call category of Incoming Call,
+ // NOT outgoing call.
+
+ // pointer to the Apps messagefilter
+ PMESSAGEFILTER32 _pMF; // the current installed message filter
+ BOOL _fInMessageFilter; // TRUE when calling the Apps MF
+
+ // call origin data
+ #define ODMAX 5
+ UINT _cODs;
+ PORIGINDATA _rgpOrigindata[ODMAX];
+
+ // BUBUG:
+ // Note: Table of CallInfos
+ // * the table holds pointers to the call info in use
+ // entry 1 is the first outgoing call (wait loop)
+ // entry 2 is the second one etc.
+ // * return value 0 means error for functions dealing with call infos
+ #define CALLINFOMAX 200
+ UINT _cCur; // this is the number of callinfos in the table
+ UINT _cCallInfoMac;
+ PCALLINFO _CallInfoTable[CALLINFOMAX];
+ PCALLINFO _pCICur; // current outgoing call
+
+ // thread safety
+ BOOL _fMultiThreaded;
+ CMutexSem _mxs;
+};
+
+CCallMainControl *GetCallMainControlForThread();
+BOOL SetCallMainControlForThread(CCallMainControl *pcmc);
+
+
+#endif // _CALLMAIN_HXX_
diff --git a/private/ole32/com/remote/chancont.cxx b/private/ole32/com/remote/chancont.cxx
new file mode 100644
index 000000000..961240f2c
--- /dev/null
+++ b/private/ole32/com/remote/chancont.cxx
@@ -0,0 +1,1363 @@
+/*++
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ chancont.cxx
+
+Abstract:
+
+ This module contains thread switching code for the single threaded mode
+ and the message filter hooks
+
+Author:
+
+ Alex Mitchell
+
+Revision History:
+
+ Mar 1994 JohannP Added call category support.
+ 29 Dec 1993 Alex Mitchell Creation.
+ 19 Jul 1994 CraigWi Added support for ASYNC calls
+ 27-Jan-95 BruceMa Don't get on CChannelControl list unless
+ constructor is successsful
+
+Functions:
+
+--*/
+
+#include <ole2int.h>
+
+#include <chancont.hxx>
+#include <channelb.hxx>
+#include <threads.hxx>
+#include <objerror.h>
+#include <callmain.hxx>
+
+// Name of window class and message class for dispatching messages.
+#define CHANNEL_WINDOW_CLASS L"OleObjectRpcWindow"
+
+
+/***************************************************************************/
+/* Globals. */
+
+// Windows identifiers needed to post to the messsage queue.
+ATOM ChannelClass = 0;
+
+// Window message id used by channel in the channel window class.
+UINT channel_message = WM_USER;
+UINT channel_message_send = WM_USER+1;
+UINT channel_message_done = WM_USER+2;
+
+// Rpc worker thread cache.
+CRpcThreadCache RpcThreadCache;
+
+// Event cache.
+CEventCache EventCache;
+
+// List of channel controllers.
+CChannelControl *CChannelControl::_pChanContRoot = NULL;
+COleStaticMutexSem CChannelControl::lock;
+CChannelControl *ProcessChannelControl = NULL;
+
+// caller-side ctor for packet;can be used for GetOffCOMThread or SwithCOMThread
+STHREADCALLINFO::STHREADCALLINFO(TRANSMIT_FN fnTrans,
+ CALLCATEGORY callcat, DWORD tid)
+{
+ // filter.lid set by GetOffCOMThread and SwitchCOMThread.
+ filter.id = CALLDATAID_UNUSED;
+ filter.TIDCallee= tid;
+ filter.CallCat = callcat;
+ filter.Event = NULL;
+ filter.fDirectedYield = FALSE;
+ // filter.pRpcMsg set by caller if needed via ???
+ fnDispatch = fnTrans;
+ pServer = NULL;
+ fLocal = FALSE;
+ eState = in_progress_cs;
+ // hResult set later
+}
+
+
+// server-side ctor (a.k.a. recipient side); used for GetToCOMThread.
+STHREADCALLINFO::STHREADCALLINFO(DISPATCH_FN fnDisp,
+ CALLCATEGORY callcat, REFLID lid)
+{
+ filter.lid = lid;
+ // filter.id not set; only used on the transmit side (by the call control)
+ // filter.TIDCallee not set; only used on the transmit side
+ // (for RetryRejectedCall)
+ filter.CallCat = callcat;
+ filter.Event = NULL;
+ filter.fDirectedYield = FALSE;
+ // filter.pRpcMsg set by caller if needed via ???
+ fnDispatch = fnDisp;
+ pServer = NULL;
+ fLocal = FALSE;
+ eState = in_progress_cs;
+ // hResult set later
+}
+
+
+// virtual destructor
+STHREADCALLINFO::~STHREADCALLINFO()
+{
+ if (filter.Event != NULL)
+ EventCache.Free(filter.Event);
+ if (pServer != NULL)
+ pServer->Release();
+}
+
+
+// called to make a copy of the packet in the newly allocated memory; ptciNew
+// has only been allocated, not initialized; this avoids redundant code.
+// the original packet is not modified. This can only be called on the
+// receiving side of the call (pServer != NULL).
+STHREADCALLINFO *STHREADCALLINFO::MakeAsyncCopy(STHREADCALLINFO *ptciNew)
+{
+ Win4Assert(ptciNew != NULL); // must have new one to fill in
+ Win4Assert(IsValidInterface(pServer)); // must be on receiving side
+
+ // the following is like a ctor on the receving (dispatch) side,
+ // but more efficient in the copy case
+ ptciNew->filter.lid = filter.lid;
+ // filter.id set by call control
+ // filter.TIDCallee not set ???
+ ptciNew->filter.CallCat = filter.CallCat;
+ ptciNew->filter.Event = NULL;
+ ptciNew->filter.fDirectedYield = FALSE;
+ ptciNew->filter.pRpcMsg = filter.pRpcMsg;
+ ptciNew->fnDispatch = fnDispatch;
+ ptciNew->pServer = pServer;
+ pServer->AddRef();
+ ptciNew->fLocal = fLocal;
+ ptciNew->eState = eState;
+ // hResult set later
+
+ return this;
+}
+
+
+// convert this packet into a reply packet that indicates success;
+// returns FALSE if OOM. Most of the work done by the derived classes.
+BOOL STHREADCALLINFO::FormulateAsyncReply()
+{
+ hResult = S_OK;
+ return TRUE;
+}
+
+
+/***************************************************************************/
+STDMETHODIMP CChannelControl::QueryInterface( THIS_ REFIID riid, LPVOID FAR* ppvObj)
+{
+ if (IsEqualIID(riid, IID_IUnknown)
+// || IsEqualIID(riid, IID_IChannelControl)
+ )
+ {
+ *ppvObj = (IChannelControl *) this;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+ return S_OK;
+}
+
+/***************************************************************************/
+STDMETHODIMP_(ULONG) CChannelControl::Release( THIS )
+{
+ ULONG retval = ref_count - 1;
+
+ if (InterlockedDecrement( (long*) &ref_count ) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ else
+ return retval;
+}
+
+/***************************************************************************/
+STDMETHODIMP_(ULONG) CChannelControl::AddRef( THIS )
+{
+ InterlockedIncrement( (long *) &ref_count );
+ return ref_count;
+}
+
+
+/***************************************************************************/
+// executed on client thread (in local case) and RPC thread (in remote case);
+// posts a message to the server thread, guarding against disconnected channels
+HRESULT CChannelControl::ProtectedPostToCOMThread(STHREADCALLINFO *call)
+{
+ CairoleDebugOut((DEB_CHANNEL, "ProtectedPostToCOMThread hWnd:%x pCall:%x\n",
+ ChannelWindow, call));
+
+ HRESULT result;
+
+ // NOTE: this lock is on the server's channel control, not the client's;
+ // in the apartment model this makes a difference because the state we
+ // are checking is in the server channel control.
+
+ lock.Request();
+ if (state == cool_ccs)
+ {
+ if (PostMessage(ChannelWindow, channel_message, 0, (DWORD)call))
+ result = S_OK;
+ else
+ result = RPC_E_SYS_CALL_FAILED;
+ }
+ else
+ result = RPC_E_SERVER_DIED_DNE;
+ lock.Release();
+
+ return result;
+}
+
+
+/***************************************************************************/
+STDMETHODIMP_(void) CChannelControl::Cancel( STHREADCALLINFO **call )
+{
+ DWORD result;
+
+ // If the call is still in progress, change it to canceled.
+ lock.Request();
+ if ((*call)->eState == in_progress_cs)
+ (*call)->eState = canceled_cs;
+ lock.Release();
+
+ // If the call completed before it could be canceled, wait for it to
+ // signal the completion event and clean up.
+ if ((*call)->eState == done_cs)
+ {
+ if (IsWOWThread() && ((*call)->fLocal))
+ // cant cancel inputsync calls
+ {
+ // the completion routine will have posted a message instead of
+ // setting an event, so we have to mark it as canceled and cleanup
+ // when the Reply msg comes in.
+ (*call)->eState = canceled_cs;
+ return;
+ }
+ else
+ {
+ // A call that completed in TransmitCall (ie, didn't create an event)
+ // cannot be canceled.
+
+ Win4Assert( (*call)->filter.Event != NULL );
+ result = WaitForSingleObject((*call)->filter.Event, INFINITE);
+ Win4Assert( result == WAIT_OBJECT_0 );
+
+ delete *call;
+ }
+ }
+
+ // Null the STHREADCALLINFO pointer so no one tries to access it.
+ *call = NULL;
+}
+
+/***************************************************************************/
+/*
+ This routine is called by the OLE Worker thread on the client side,
+ by the RPC worker thread on the server side for remote calls, and
+ by ThreadWndProc for local calls on the server side.
+
+ For the client case, it calls the dispatch routine which will send the
+ the data over to the server side.
+ This routine notifies the COM thread when the call is complete. If the
+ call is canceled before completion, the routine cleans up.
+
+ CODEWORK: the ThreadDispatch call could be reimplented to be faster
+ since there are various constraints on its operation (as
+ asserted in threads.cxx).
+*/
+/* static */
+void CChannelControl::ThreadDispatch( STHREADCALLINFO **ppcall,
+ BOOL dispatch )
+{
+ STHREADCALLINFO *pcall = *ppcall;
+
+ // Dispatch the call.
+ if (dispatch)
+ pcall->hResult = pcall->fnDispatch( pcall );
+
+ // Change the state to done; we cheat on non-local, recipient side since
+ // there is only one thread accessing the channel control; no need to
+ // lock and no need to check for cancel since it can't happen.
+ if (pcall->pServer == NULL || pcall->fLocal)
+ {
+ // sender or local case; use lock in case other thread accesses it
+ lock.Request();
+ if (pcall->eState == in_progress_cs)
+ pcall->eState = done_cs;
+ lock.Release();
+ }
+ else
+ {
+ // non-local recipient; just set to done and skip the next test
+ Win4Assert(pcall->eState == in_progress_cs);
+ pcall->eState = done_cs;
+ goto Done;
+ }
+
+ // If the call completed, wake up the client COM thread.
+ if (pcall->eState == done_cs)
+ {
+Done:
+ if (pcall->filter.Event != NULL)
+ {
+ if (!IsWOWThread() || (!pcall->fLocal && pcall->pServer) ||
+ pcall->filter.CallCat == CALLCAT_INPUTSYNC ||
+ pcall->filter.CallCat == CALLCAT_INTERNALINPUTSYNC)
+ {
+ // 32bit always uses events for notification
+ // remote server side calls always use events
+ // client side INPUTSYNC always uses events
+
+ // someone waiting (e.g., not a SendMessage-type call)
+ CairoleDebugOut((DEB_CHANNEL,"SetEvent pInfo:%x hEvent:%x\n",
+ pcall, pcall->filter.Event));
+ SetEvent( pcall->filter.Event );
+ //
+ // We know that the other thread is waiting to run at this
+ // point. If we yield here, then the other thread will be
+ // able to return to our client. This sleep of zero will give up
+ // the rest of our timeslice, and allow the other thread
+ // to run.
+ //
+ Sleep(0);
+
+ }
+ else
+ {
+ // NOTE NOTE NOTE NOTE NOTE NOTE NOTE
+ // 16bit OLE used to do PostMessage for the Reply; we
+ // tried using SetEvent (which is faster) but this caused
+ // compatibility problems for applications which had bugs that
+ // were hidden by the 16bit OLE DLLs because messages happened
+ // to be dispatched in a particular order (see NtBug 21616 for
+ // an example). To retain the old behavior, we do a
+ // PostMessage here.
+
+ CairoleDebugOut((DEB_CHANNEL,
+ "PostMessage Reply hWnd:%x pCall:%x hEvent:%x\n",
+ pcall->hWndCaller, pcall, pcall->filter.Event));
+
+ Verify(PostMessage(pcall->hWndCaller,
+ channel_message_done, 0, (DWORD)pcall));
+ }
+
+ // pcall likely invalid here as other thread probably deleted it
+ }
+ else if (pcall->pServer != NULL && pcall->filter.CallCat == CALLCAT_ASYNC)
+ {
+ // async call and on recipient side, free packet (no one waiting)
+ delete pcall;
+ *ppcall = NULL;
+ }
+ }
+
+ // If the call was canceled, clean up.
+ else
+ {
+ // can only cancel when on client side or local call
+ Win4Assert(pcall->pServer == NULL || pcall->fLocal);
+
+ delete pcall;
+ *ppcall = NULL;
+ }
+}
+
+/***************************************************************************/
+STDMETHODIMP CChannelControl::DispatchCall( PDISPATCHDATA data )
+{
+ STHREADCALLINFO *call = (STHREADCALLINFO *) data->pData;
+ return call->fnDispatch( call );
+}
+
+/***************************************************************************/
+STDMETHODIMP CChannelControl::OnEvent( PCALLDATA data )
+{
+ STHREADCALLINFO *call = STHREADCALLINFO::MapCDToTCI(data);
+ SERVERCALLEX type;
+
+ // NOTE: the event used to be freed here; it is now freed in the dtor
+ // of STHREADCALLINFO.
+
+ HRESULT hr = call->hResult;
+
+ // CODEWORK: just return the error and let the callcontrol set its
+ // own state...eliminates a callback
+
+ if (hr == RPC_E_SERVERCALL_RETRYLATER)
+ type = SERVERCALLEX_RETRYLATER;
+ else if (hr == RPC_E_SERVERCALL_REJECTED)
+ type = SERVERCALLEX_REJECTED;
+ else
+ {
+ type = SERVERCALLEX_ISHANDLED;
+ hr = S_OK;
+ }
+
+ return _pCallControl->SetCallState(data, type, hr);
+}
+
+/***************************************************************************/
+/* This function is static. */
+CChannelControl *CChannelControl::Lookup( HAPT apt )
+{
+ CChannelControl *pChannelControl;
+
+ lock.Request();
+ pChannelControl = _pChanContRoot;
+ if (pChannelControl != NULL && !FreeThreading)
+ {
+ do
+ {
+ if (pChannelControl->_dwMyThreadId == apt.dwThreadId)
+ break;
+ pChannelControl = pChannelControl->_pChanContNext;
+ }
+ while (pChannelControl != _pChanContRoot);
+ if (pChannelControl->_dwMyThreadId != apt.dwThreadId &&
+ apt.dwThreadId != ANY_APT.dwThreadId)
+ pChannelControl = NULL;
+ }
+
+ if (pChannelControl != NULL)
+ pChannelControl->AddRef();
+ lock.Release();
+
+ return pChannelControl;
+}
+
+
+/***************************************************************************/
+/*
+ Return a failure code to indicate that no event will ever be set.
+ Then the message filter will pass the result back to the channel controller
+ who will set up the STHREADCALLINFO. Return S_OK if the event will be
+ signalled some time. In that case you must set the error fields of
+ STHREADCALLINFO before returning.
+
+ Note that the CallControl knows about the input_sync case. In that
+ case we call SendMessage which blocks. There is never an event in the
+ input_sync case.
+*/
+STDMETHODIMP CChannelControl::TransmitCall( PCALLDATA pdata )
+{
+ STHREADCALLINFO *call = STHREADCALLINFO::MapCDToTCI(pdata);
+ HRESULT result = S_OK;
+ BOOL set_call_state = TRUE;
+ SERVERCALLEX type = SERVERCALLEX_ERROR;
+
+ if (FreeThreading)
+ {
+ call->hResult = call->fnDispatch( call );
+ type = SERVERCALLEX_ISHANDLED;
+ }
+
+ // Dispatch directly to the server thread.
+ else if (call->fLocal)
+ {
+ if (call->filter.CallCat == CALLCAT_INPUTSYNC ||
+ call->filter.CallCat == CALLCAT_INTERNALINPUTSYNC)
+ {
+ // Send the message.
+ if (state == cool_ccs)
+ {
+ // On CoUninitialize this may fail when the window is destroyed.
+ if (SendMessage(call->pServer->ChannelWindow,
+ channel_message_send, 0, (DWORD) call))
+ {
+ if (call->hResult == RPC_E_SERVERCALL_RETRYLATER)
+ type = SERVERCALLEX_RETRYLATER;
+ else if (call->hResult == RPC_E_SERVERCALL_REJECTED)
+ type = SERVERCALLEX_REJECTED;
+ else
+ type = SERVERCALLEX_ISHANDLED;
+ }
+ else
+ {
+ result = RPC_E_SERVER_DIED;
+ }
+ }
+ else
+ result = RPC_E_SERVER_DIED_DNE;
+ }
+ else if (call->filter.CallCat == CALLCAT_ASYNC)
+ {
+ // async call; copy message, post message and return.
+ // NOTE that the FreeThreading case is caught above. Async
+ // support is only for single-threaded apps.
+
+ STHREADCALLINFO *callT;
+ if ((callT = call->MakeAsyncCopy(NULL)) == NULL)
+ {
+ result = RPC_E_OUT_OF_RESOURCES;
+ }
+ else if (!call->FormulateAsyncReply())
+ {
+ delete callT;
+ result = RPC_E_OUT_OF_RESOURCES;
+ }
+ else
+ {
+ result = callT->pServer->ProtectedPostToCOMThread(callT);
+
+ if (result == S_OK)
+ {
+ // post succeeded; will be dispatched and freed;
+ // set call state to indicate a successful call;
+ // simulate overall success (normally set by ThreadDispatch);
+ // FormulateAsyncReply setup the buffer for successful return
+ // including setting hResult to S_OK.
+ type = SERVERCALLEX_ISHANDLED;
+ }
+ else
+ {
+ // result and type already set; delete copy of message
+ delete callT;
+ }
+ }
+ }
+ else
+ {
+ // Get an event from the cache.
+ result = call->AllocEvent();
+ if (result == S_OK)
+ {
+ // Post a message to server
+ result = call->pServer->ProtectedPostToCOMThread(call);
+
+ if (result == S_OK)
+ {
+ // post successful, but call not complete; don't set call state;
+ // call->hResult not set also
+ set_call_state = FALSE;
+ if (IsWOWThread())
+ {
+ if (call->filter.TIDCallee == 0)
+ {
+ // This happens when there is a call made by internal
+ // RPC. We therefore get the thread id from the
+ // window that we just posted the message so we can
+ //yield to the correct thread.
+ call->filter.TIDCallee = GetWindowThreadProcessId(
+ call->pServer->ChannelWindow, NULL);
+ }
+
+ call->filter.fDirectedYield = TRUE;
+ }
+ }
+ }
+ }
+ }
+ else if (call->filter.CallCat == CALLCAT_ASYNC)
+ {
+ // inter-proceess async call; make rpc call to other process (which will
+ // post a message) directly on this thread. This is done to avoid any
+ // processing of incoming calls. This call has no event to signal and
+ // can not be canceled (this might change in the network case).
+ // Much like the free threading case above.
+ call->hResult = call->fnDispatch( call );
+ type = SERVERCALLEX_ISHANDLED;
+ }
+
+ // Get a RPC thread to do the work.
+ else
+ {
+ // dispatch to a worker thread to make the call
+ result = call->AllocEvent();
+ if (result == S_OK)
+ {
+ result = RpcThreadCache.Dispatch( call );
+ set_call_state = FALSE;
+ }
+ }
+
+ if (set_call_state)
+ _pCallControl->SetCallState( &call->filter, type, result );
+ return result;
+}
+
+/***************************************************************************/
+/* The result of this routine indicates comm status. This routine throws
+ exceptions to indicate fault status. If FreeThreading is false, a
+ thread_switch_data record is used to communicate with the thread doing the
+ work. That thread will return both kinds of results in the record.
+ If a request comes in, this routine will call AppInvoke which will catch
+ all exceptions and return both types as its result. If FreeThreading is
+ TRUE, this routine just calls I_RpcSendReceive. For now, the result of
+ I_RpcSendReceive will always be treated as a comm status (and thus just
+ returned). Someday, I_RpcSendReceive will indicate server faults which
+ this routine can throw.
+*/
+HRESULT CChannelControl::GetOffCOMThread( STHREADCALLINFO **call )
+{
+ TRACECALL(TRACE_RPC, "CChannelControl::GetOffCOMThread");
+
+ HRESULT result;
+ IID *logical_thread;
+ CChannelControl *pChannelControl;
+ RPC_STATUS status;
+
+ // assert initialized correctly.
+ Win4Assert((*call)->pServer == NULL && !(*call)->fLocal);
+ Win4Assert((*call)->filter.Event == NULL);
+
+ // Find the channel controller for this thread.
+ GetLocalChannelControl( pChannelControl );
+ if (pChannelControl)
+ {
+ (*call)->hWndCaller = pChannelControl->ChannelWindow;
+
+ // Generate a new logical thread for async calls.
+ if ((*call)->GetCallCat() == CALLCAT_ASYNC)
+ {
+ status = UuidCreate(&(*call)->filter.lid);
+ if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY)
+ return HRESULT_FROM_WIN32( status );
+ }
+
+ // Find the logical thread id.
+ else
+ {
+ logical_thread = TLSGetLogicalThread();
+ if (logical_thread)
+ (*call)->filter.lid = *logical_thread;
+ else
+ return RPC_E_OUT_OF_RESOURCES;
+ }
+
+ CairoleDebugOut((DEB_CHANNEL,
+ "GetOffCOMThread hWnd:%x pCall:%x hEvent:%x\n",
+ (*call)->hWndCaller, (*call), (*call)->filter.Event));
+
+ // Let the modal loop transmit the call and wait for the reply.
+ result = pChannelControl->_pCallControl->CallRunModalLoop( &(*call)->filter );
+ if (result == S_OK)
+ result = (*call)->hResult;
+ else if (result == RPC_E_CALL_CANCELED)
+ Cancel( call );
+ }
+
+ // Can't get channel controller.
+ else
+ {
+ result = RPC_E_THREAD_NOT_INIT;
+ }
+ return result;
+}
+
+/***************************************************************************/
+/* Really, I'm static. No, really. */
+HRESULT CChannelControl::GetToCOMThread( HAPT apt, STHREADCALLINFO *call )
+{
+ CChannelControl *pChannelControl;
+ HRESULT result;
+
+ pChannelControl = Lookup( apt );
+ if (pChannelControl != NULL)
+ {
+ result = pChannelControl->GetToCOMThread( call );
+ pChannelControl->Release();
+ }
+ else
+ {
+ result = RPC_E_SERVER_DIED_DNE;
+ }
+ return result;
+}
+
+/***************************************************************************/
+HRESULT CChannelControl::GetToCOMThread( STHREADCALLINFO *call )
+{
+ TRACECALL(TRACE_RPC, "CChannelControl::GetToCOMThread");
+
+ CairoleDebugOut((DEB_CHANNEL, "GetToCOMThread pCall:%x\n", call));
+
+ HRESULT result;
+
+ Win4Assert(call->pServer == NULL && !call->fLocal);
+ Win4Assert(call->filter.Event == NULL);
+
+ // ctor sets pServer to NULL; we need one; will be released in dtor
+ call->pServer = this;
+ AddRef();
+
+ if (FreeThreading)
+ {
+ // In the multithreaded case, just call the dispatch function
+ // directly from this thread.
+ if (TLSSetLogicalThread(call->filter.lid))
+ result = call->fnDispatch( call );
+ else
+ result = RPC_E_SYS_CALL_FAILED;
+ }
+ else if ( call->filter.CallCat == CALLCAT_INPUTSYNC
+ || call->filter.CallCat == CALLCAT_INTERNALINPUTSYNC)
+ {
+ // input synchronous call, send a message
+ if (state == cool_ccs)
+ {
+ // On CoUninitialize this may fail when the window is destroyed.
+ if (SendMessage(ChannelWindow, channel_message_send, 0, (DWORD) call))
+ result = call->hResult;
+ else
+ result = RPC_E_SERVER_DIED;
+ }
+ else
+ {
+ result = RPC_E_SERVER_DIED_DNE;
+ }
+ }
+ else if ( call->filter.CallCat == CALLCAT_ASYNC)
+ {
+ // async call; copy message, post message and return.
+ // NOTE that the FreeThreading case is caught above. Async
+ // support is only for single-threaded apps.
+
+ STHREADCALLINFO *callT;
+ if ((callT = call->MakeAsyncCopy(NULL)) == NULL)
+ {
+ result = RPC_E_OUT_OF_RESOURCES;
+ }
+ else if (!call->FormulateAsyncReply())
+ {
+ delete callT;
+ result = RPC_E_OUT_OF_RESOURCES;
+ }
+ else
+ {
+ // Post a message and wait for the app to get back to GetMessage.
+ result = ProtectedPostToCOMThread(callT);
+
+ if (result == S_OK)
+ {
+ // post succeeded; will be dispatched and freed
+ // fnAsyncCopy setup the buffer for successful return
+ }
+ else
+ {
+ // error in posting; free packet and return error (result set above)
+ delete callT;
+ }
+ }
+ }
+ else
+ {
+ // Get this thread's event. May cause an event to be created.
+ result = call->AllocEvent();
+ if (result == S_OK)
+ {
+ result = ProtectedPostToCOMThread(call);
+
+ if (result == S_OK)
+ {
+ // Wait for the app to finish processing the request.
+ if (WaitForSingleObject(call->filter.Event, INFINITE) == WAIT_OBJECT_0)
+ result = call->hResult;
+ else
+ result = RPC_E_SYS_CALL_FAILED;
+ }
+ }
+ }
+ return result;
+}
+
+/***************************************************************************/
+/* Really, I'm static. No, really. */
+HRESULT CChannelControl::SwitchCOMThread( HAPT apt, STHREADCALLINFO **call )
+{
+ CChannelControl *pChannelControl;
+ HRESULT result;
+
+ pChannelControl = Lookup( apt );
+ if (pChannelControl != NULL)
+ {
+ result = pChannelControl->SwitchCOMThread( call );
+ pChannelControl->Release();
+ }
+ else
+ {
+ result = RPC_E_SERVER_DIED_DNE;
+ }
+ return result;
+}
+
+/***************************************************************************/
+HRESULT CChannelControl::SwitchCOMThread( STHREADCALLINFO **call )
+{
+ TRACECALL(TRACE_RPC, "CChannelControl::SwitchCOMThread");
+
+ HRESULT result;
+ IID *logical_thread;
+ CChannelControl *pChannelControl;
+
+ Win4Assert((*call)->pServer == NULL && !(*call)->fLocal);
+ Win4Assert((*call)->filter.Event == NULL);
+
+ Win4Assert( !FreeThreading );
+
+ // Generate a new logical thread for async calls.
+ if ((*call)->GetCallCat() == CALLCAT_ASYNC)
+ {
+ RPC_STATUS status = UuidCreate(&(*call)->filter.lid);
+ if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY)
+ return HRESULT_FROM_WIN32( status );
+ }
+
+ // Find the logical thread id.
+ else
+ {
+ logical_thread = TLSGetLogicalThread();
+ if (logical_thread)
+ (*call)->filter.lid = *logical_thread;
+ else
+ return RPC_E_OUT_OF_RESOURCES;
+ }
+
+ // set fields we need different than ctor
+ (*call)->fLocal = TRUE;
+ (*call)->pServer = this;
+ AddRef(); // will be released in dtor
+
+ // Call the message filter for this thread, not the server's thread.
+ pChannelControl = (CChannelControl *) TLSGetChannelControl();
+ if (pChannelControl != NULL)
+ {
+ (*call)->hWndCaller = pChannelControl->ChannelWindow;
+
+ CairoleDebugOut((DEB_CHANNEL,
+ "SwitchCOMThread hWnd:%x pCall:%x hEvent:%x\n",
+ (*call)->hWndCaller, (*call), (*call)->filter.Event));
+
+ result = pChannelControl->_pCallControl->CallRunModalLoop( &(*call)->filter );
+ if (result == S_OK)
+ result = (*call)->hResult;
+ else if (result == RPC_E_CALL_CANCELED)
+ Cancel( call );
+ }
+ else
+ result = RPC_E_THREAD_NOT_INIT;
+
+ // NOTE: Event and pServer are cleaned up by dtor of STHREADCALLINFO.
+ return result;
+}
+
+/***************************************************************************/
+/* This routine is only called if FreeThreading is false. AppInvoke will
+ catch all exceptions and return both comm status and server faults in
+ its result. This routine stuffs the result of comm status into a
+ thread_switch_data record that is passed back to ThreadInvoke on another
+ thread. */
+
+LRESULT ThreadWndProc(HWND window, UINT message, WPARAM unused, LPARAM params)
+{
+ if (message == channel_message ||
+ message == channel_message_send)
+ {
+ STHREADCALLINFO *call = (STHREADCALLINFO *) params;
+ CairoleDebugOut((DEB_CHANNEL, "ThreadWndProc: Incoming Call pCall:%x\n", call));
+
+ // If the server isn't taking calls, just fail this one.
+ if (call->pServer->state != cool_ccs)
+ {
+ call->hResult = RPC_E_SERVER_DIED_DNE;
+
+ // Wake up the caller; ThreadDispatch takes care of the two main
+ // cases: local (pServer != NULL and fLocal == TRUE) and server
+ // side non-local (pServer != NULL and fLocal == FALSE). It also
+ // handles the orthoginal cases of send message (filter.Event == NULL)
+ // and async (CallCat == CALLCAT_ASYNC and pServer != NULL).
+
+ // In the server-side non-local case, we assert that the call is not
+ // canceled. Canceling is handled only on the client side or local cases.
+
+ CChannelControl::ThreadDispatch( &call, FALSE );
+ }
+
+ // This server is running, dispatch the call.
+ else
+ {
+ // Set the logical thread id. Note this cant fail because we
+ // are on the app main thread and we pre-allocated the TLS
+ // in CoInitialize and the uuid allocation can't fail.
+ IID *threadid_ptr = TLSGetLogicalThread();
+ Win4Assert(threadid_ptr && "TLSGetLogicalThread failed.");
+ Win4Assert( !FreeThreading );
+
+ // save the original threadid & copy in the new one.
+ UUID saved_threadid = *threadid_ptr;
+ *threadid_ptr = call->filter.lid;
+
+ // Dispatch all calls through ThreadDispatch. Local calls may be
+ // canceled. Server-side, non-local calls cannot be canceled. Send
+ // message calls (filter.Event == NULL) are handled as well.
+ CChannelControl::ThreadDispatch( &call, TRUE );
+
+ // restore the original thread id.
+ *threadid_ptr = saved_threadid;
+ }
+
+ return 1;
+ }
+ else if (message == channel_message_done)
+ {
+ // call completed - only happens InWow()
+ STHREADCALLINFO *call = (STHREADCALLINFO *) params;
+ CairoleDebugOut((DEB_CHANNEL, "ThreadWndProc: Call Completed hWnd:%x pCall:%x\n", window, call));
+
+ if (call->eState == canceled_cs)
+ {
+ // canceled, throw it away
+ delete call;
+ }
+ else if (call->filter.Event)
+ {
+ // mark the call as done
+ ((CChannelControl *) TLSGetChannelControl())->OnEvent( &call->filter );
+ }
+
+ return 1;
+ }
+ else
+ {
+ // Otherwise let the default window procedure have the message.
+ return DefWindowProc( window, message, unused, params );
+ }
+}
+
+
+
+/***************************************************************************/
+CChannelControl::CChannelControl( HRESULT *result )
+{
+ ORIGINDATA OriginDataQ;
+
+ state = bummin_ccs;
+ ref_count = 1;
+ *result = RPC_E_OUT_OF_RESOURCES;
+ _dwMyThreadId = GetCurrentThreadId();
+
+
+ if (!FreeThreading)
+ {
+
+ // Create hidden channel window.
+ ChannelWindow = CreateWindowEx(0,
+ (LPCWSTR) ChannelClass,
+ L"OLEChannelWnd",
+ // must use WS_POPUP so the window does not get
+ // assigned a hot key by user.
+ (WS_DISABLED | WS_POPUP),
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ NULL,
+ NULL,
+ g_hinst,
+ NULL );
+ if (!ChannelWindow)
+ {
+ CairoleDebugOut((DEB_ERROR,"CreateWindowEx failed in CChannelControl constructor\n"));
+ return;
+ }
+ }
+ else
+ {
+ ChannelWindow = NULL;
+ }
+
+ // Get a message filter.
+ if (FreeThreading)
+ OriginDataQ.CallOrigin = CALLORIGIN_RPC32_MULTITHREAD;
+ else
+ OriginDataQ.CallOrigin = CALLORIGIN_RPC32_APARTMENT;
+
+ OriginDataQ.pChCont = this;
+ OriginDataQ.hwnd = ChannelWindow;
+ OriginDataQ.wFirstMsg = channel_message;
+ OriginDataQ.wLastMsg = channel_message_done;
+
+ *result = CoGetCallControl( &OriginDataQ, &_pCallControl );
+
+ _pCMC = GetCallMainControlForThread();
+
+ if (SUCCEEDED(*result) && _pCMC)
+ {
+ // pre-allocate thread local storage so we dont have to test this on
+ // every dispatch later on. Don't preallocate the logical
+ // thread id itself since that casuses some a hang on Cairo startup;
+ // the allocation of the logical thread id (UuidCreate) can't fail.
+
+ COleTls tls(*result);
+ if (SUCCEEDED(*result))
+ {
+ // Everything was successful so get on the ChannelController list
+ lock.Request();
+ if (_pChanContRoot == NULL)
+ _pChanContRoot = _pChanContPrev = _pChanContNext = this;
+ else
+ {
+ _pChanContNext = _pChanContRoot->_pChanContNext;
+ _pChanContPrev = _pChanContRoot;
+ _pChanContRoot->_pChanContNext->_pChanContPrev = this;
+ _pChanContRoot->_pChanContNext = this;
+ }
+ lock.Release();
+
+ // Report success
+ *result = S_OK;
+ state = cool_ccs;
+ }
+ }
+}
+
+/***************************************************************************/
+CChannelControl::~CChannelControl()
+{
+ // We should have changed state and been removed from the channel controller
+ // list in ThreadUnintialize.
+ Assert( state == bummin_ccs );
+}
+
+/***************************************************************************/
+
+//+-------------------------------------------------------------------------
+//
+// Member: CChannelControl::ThreadStop
+//
+// Synopsis: Per thread uninitialization
+//
+// Effects:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: ??-???-?? ? Created
+// 05-Jul-94 AlexT Separated thread and process uninit
+//
+// Notes: We are not holding the single thread mutex during this call
+//
+//--------------------------------------------------------------------------
+
+void CChannelControl::ThreadStop(void)
+{
+ MSG msg;
+ BOOL got_quit = FALSE;
+ WPARAM quit_val;
+
+ // Change state and get off pChannelControl list.
+ lock.Request();
+ state = bummin_ccs;
+ if (_pChanContNext == this)
+ _pChanContNext = _pChanContPrev = _pChanContRoot = NULL;
+ else
+ {
+ _pChanContNext->_pChanContPrev = _pChanContPrev;
+ _pChanContPrev->_pChanContNext = _pChanContNext;
+ if (_pChanContRoot == this)
+ _pChanContRoot = _pChanContNext;
+ }
+ lock.Release();
+
+ // Wait for all current calls to complete.
+ if (!FreeThreading)
+ {
+ while( PeekMessage( &msg, ChannelWindow, channel_message,
+ channel_message_send, PM_REMOVE | PM_NOYIELD) )
+ {
+ if (msg.message == WM_QUIT)
+ {
+ got_quit = TRUE;
+ quit_val = msg.wParam;
+ }
+ else
+ DispatchMessage( &msg );
+ }
+ }
+
+ // Destroy the window. This will unblock any pending send messages.
+ if (ChannelWindow != NULL)
+ {
+ // This may fail if threads get terminated.
+ DestroyWindow( ChannelWindow );
+ ChannelWindow = 0;
+ }
+
+ // Release the call controller.
+ if (_pCallControl != NULL)
+ {
+ _pCallControl->Release();
+ _pCallControl = NULL;
+ }
+
+ if (got_quit)
+ PostQuitMessage( quit_val );
+}
+
+/***************************************************************************/
+HRESULT ChannelThreadInitialize()
+{
+ WNDCLASS stuff;
+ HRESULT result = S_OK;
+ CChannelControl *ChannelControl;
+
+ // Only get window stuff for the single threaded mode.
+ Win4Assert(!FreeThreading);
+
+ // Register windows class.
+ if (ChannelClass == 0)
+ {
+ stuff.style = 0;
+ stuff.lpfnWndProc = ThreadWndProc;
+ stuff.cbClsExtra = 0;
+ stuff.cbWndExtra = 0;
+ stuff.hInstance = g_hinst;
+ stuff.hIcon = NULL;
+ stuff.hCursor = NULL;
+ stuff.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
+ stuff.lpszMenuName = NULL;
+ stuff.lpszClassName = CHANNEL_WINDOW_CLASS;
+
+ ChannelClass = RegisterClass( &stuff );
+ if (ChannelClass == 0)
+ {
+ // it is possible the dll got unloaded without us having called
+ // unregister so we call it here and try again.
+ UnregisterClass( CHANNEL_WINDOW_CLASS, g_hinst );
+ ChannelClass = RegisterClass( &stuff );
+ if ( ChannelClass == 0 )
+ {
+ CairoleDebugOut((DEB_ERROR,"RegisterClass failed in ChannelThreadInitialize\n"));
+ }
+ }
+ }
+
+ if (ChannelClass != 0)
+ {
+ // Create a class for message filter hooks.
+ // This is released in ThreadUninitialize.
+ ChannelControl = new CChannelControl( &result );
+
+ //
+ // BUGBUG - We leak memory in a strange case. If OLE32 is FreeLibrary'd
+ // then the ThreadUninitialize function is never called. This will cause
+ // us to leak a CChannelControl for every apartment.
+ //
+ if (ChannelControl)
+ {
+ if (SUCCEEDED(result))
+ {
+ if (TLSSetChannelControl( ChannelControl ))
+ return S_OK;
+ }
+ delete ChannelControl;
+ }
+ }
+
+ // If we get here, something failed. Our caller (CoInitializeEx) will
+ // call the necessary uninitialization routines on our behalf.
+
+ return CO_E_INIT_TLS_CHANNEL_CONTROL;
+}
+
+/***************************************************************************/
+void ChannelControlThreadUninitialize()
+{
+ CChannelControl *pChannelControl;
+
+ if (!FreeThreading)
+ {
+ // Find the channel controller for this thread. Stop it and release it.
+ pChannelControl = (CChannelControl *) TLSGetChannelControl();
+ if (pChannelControl != NULL)
+ {
+ TLSSetChannelControl( NULL );
+ pChannelControl->ThreadStop();
+
+ // This release matches the create in ChannelThreadInitialize.
+ pChannelControl->Release();
+ }
+ }
+}
+
+/***************************************************************************/
+HRESULT ChannelControlProcessInitialize(void)
+{
+ // initialize the event cache
+ EventCache.Initialize();
+
+ HRESULT result = S_OK;
+
+ // Get a channel controller the first time we are initialized in
+ // the multithreaded mode.
+ if (FreeThreading)
+ {
+ // Create a class for message filter hooks.
+ result = E_OUTOFMEMORY;
+ ProcessChannelControl = new CChannelControl( &result );
+ Win4Assert(ProcessChannelControl && "Could not allocate ChannelControl");
+ }
+
+ return result;
+}
+
+/***************************************************************************/
+void ChannelControlProcessUninitialize(void)
+{
+ BOOL success;
+
+ if (!FreeThreading)
+ {
+ // When the process is stopping, tell RPC to stop listening.
+ StopListen();
+
+ // Free up the resources needed for single threading.
+ // Deregister the window class.
+ if (ChannelClass != 0)
+ {
+ success = UnregisterClass( CHANNEL_WINDOW_CLASS, g_hinst );
+#if DBG == 1
+ if (!success)
+ CairoleDebugOut((DEB_ERROR, "Could not UnregisterClass 0x%x\n",
+ GetLastError()));
+#endif
+ ChannelClass = 0;
+ }
+ }
+ else
+ {
+ Assert(FreeThreading && "Bad threading logic");
+
+ if (ProcessChannelControl != NULL)
+ {
+ ProcessChannelControl->ThreadStop();
+ StopListen();
+
+ ProcessChannelControl->Release();
+ ProcessChannelControl = NULL;
+ }
+ }
+
+ // release all cached threads
+ RpcThreadCache.ClearFreeList();
+
+ // release cached events
+ EventCache.Cleanup();
+}
+
+/***************************************************************************/
+void CEventCache::Initialize()
+{
+ CLock lck(_EventLock);
+
+ memset(_list, 0, sizeof(_list));
+ _ifree = 0;
+}
+
+
+/***************************************************************************/
+void CEventCache::Cleanup(void)
+{
+ CLock lck(_EventLock);
+
+ if (_ifree < CEVENTCACHE_MAX_EVENT + 1)
+ {
+ while (_ifree > 0)
+ {
+ _ifree--; // decrement the index first!
+ Verify(CloseHandle(_list[_ifree]));
+ _list[_ifree] = NULL;
+ }
+ }
+
+ // set the index high so that if an event is returned to the cache
+ // after Cleanup, it gets Closed instead of lost in the list.
+ _ifree = CEVENTCACHE_MAX_EVENT + 1;
+}
+
+
+/***************************************************************************/
+void CEventCache::Free( HANDLE event )
+{
+ // Do nothing if there is no event.
+ if (event == NULL)
+ return;
+
+ CLock lck(_EventLock);
+
+ if (_ifree < CEVENTCACHE_MAX_EVENT)
+ {
+ // there is space, save this event.
+
+#if DBG==1
+ // in debug, ensure slot is NULL
+ Win4Assert(_list[_ifree] == NULL && "Free: _list[_ifree] != NULL");
+
+ // enusre not already in the list
+ for (ULONG j=0; j<_ifree; j++)
+ {
+ Win4Assert(_list[j] != event && "Free: event already in cache!");
+ }
+
+ // ensure that the event is in the non-signalled state
+ Win4Assert(WaitForSingleObject(event, 0) == WAIT_TIMEOUT &&
+ "Free: Signalled event returned to cache!\n");
+
+#endif
+
+ _list[_ifree] = event;
+ _ifree++;
+ }
+ else
+ {
+ // Otherwise really free it.
+ Verify(CloseHandle(event));
+ }
+}
+
+/***************************************************************************/
+HANDLE CEventCache::Get()
+{
+ HANDLE event = NULL;
+
+ Win4Assert(_ifree <= CEVENTCACHE_MAX_EVENT);
+
+ {
+ CLock lck(_EventLock);
+
+ // If there is an event in the cache, use it.
+ if (_ifree > 0)
+ {
+ _ifree--;
+ event = _list[_ifree];
+#if DBG==1
+ // in debug, NULL the slot.
+ _list[_ifree] = NULL;
+#endif
+ }
+
+ // lock goes out of scope at this point.
+ }
+
+ // Otherwise allocate a new one.
+ if (event == NULL)
+#ifdef _CHICAGO_
+ event = CreateEventA( NULL, FALSE, FALSE, NULL );
+#else //_CHICAGO_
+ event = CreateEvent( NULL, FALSE, FALSE, NULL );
+#endif //_CHICAGO_
+
+ Win4Assert(event != NULL && "CEventCache:GetEvent returning NULL");
+
+ return event;
+}
diff --git a/private/ole32/com/remote/chancont.hxx b/private/ole32/com/remote/chancont.hxx
new file mode 100644
index 000000000..82b886d28
--- /dev/null
+++ b/private/ole32/com/remote/chancont.hxx
@@ -0,0 +1,299 @@
+#ifndef _CHANCONT_HXX_
+#define _CHANCONT_HXX_
+
+#include <wtypes.h>
+#include <olesem.hxx>
+#include <olerem.h>
+#include <callcont.hxx>
+#include <tls.h>
+#include <iface.h>
+
+// forward declaration
+class CCallMainControl;
+
+
+/***************************************************************************/
+#define CEVENTCACHE_MAX_EVENT 8
+
+class CEventCache : public CPrivAlloc
+{
+ public:
+
+ CEventCache() { Initialize(); }
+
+ void Free( HANDLE );
+ HANDLE Get ( void );
+
+ void Initialize(void);
+ void Cleanup(void);
+
+ private:
+
+ HANDLE _list[CEVENTCACHE_MAX_EVENT];
+ DWORD _ifree;
+
+ COleStaticMutexSem _EventLock;
+};
+
+extern CEventCache EventCache;
+
+
+/***************************************************************************/
+/* Macros. */
+
+#define GetLocalChannelControl( pChannelControl ) \
+{ \
+ if (FreeThreading) \
+ (pChannelControl) = ProcessChannelControl; \
+ else \
+ (pChannelControl) = (CChannelControl *) TLSGetChannelControl(); \
+}
+
+
+/***************************************************************************/
+typedef enum
+{
+ cool_ccs,
+ bummin_ccs
+} EChannelControlState;
+
+typedef enum
+{
+ in_progress_cs,
+ done_cs,
+ canceled_cs
+} ECallState;
+
+enum INIT_VTABLE
+{
+ init_vtable = 0x12345678
+};
+
+typedef HRESULT (*TRANSMIT_FN)( struct STHREADCALLINFO * );
+typedef HRESULT (*DISPATCH_FN)( struct STHREADCALLINFO * );
+
+class CChannelControl;
+
+typedef struct STHREADCALLINFO : CPrivAlloc
+{
+public:
+ STHREADCALLINFO(TRANSMIT_FN fn, CALLCATEGORY callcat, DWORD tid = 0);
+ STHREADCALLINFO(DISPATCH_FN fn, CALLCATEGORY callcat, REFLID lid);
+ virtual ~STHREADCALLINFO();
+ DISPATCH_FN ResetDispatchFn(DISPATCH_FN fnDispNew)
+ {
+ DISPATCH_FN fnOld = fnDispatch;
+ fnDispatch = fnDispNew;
+ return fnOld;
+ }
+ REFLID lid() { return filter.lid; }
+ EVENT Event() { return filter.Event; }
+ CALLCATEGORY GetCallCat() { return filter.CallCat; }
+
+ HRESULT AllocEvent(void)
+ {
+ Win4Assert(filter.Event == NULL && "Event not initialized correctly");
+ return ((filter.Event = EventCache.Get()) != NULL) ? S_OK
+ : RPC_E_OUT_OF_RESOURCES;
+ }
+
+ void SetCalledIID(REFIID riid) { filter.iid = riid; }
+ void SetTIDCallee(DWORD dwTIDCallee) {filter.TIDCallee = dwTIDCallee;}
+
+ virtual STHREADCALLINFO *MakeAsyncCopy(STHREADCALLINFO *); // like copy ctor
+ virtual BOOL FormulateAsyncReply(); // formulate reply to async call
+#if DBG == 1
+ // assert calling process for non-local case
+ void AssertCallingProcess() { Win4Assert(pServer == NULL && !fLocal); }
+#else
+ void AssertCallingProcess() { }
+#endif
+
+protected:
+ // this ctor is used in conjunction with MakeAsyncCopy and sets up the vtable
+ // pointer; MakeAsyncCopy actually initializes the instance. A normal copy
+ // constructor isn't used because they aren't virtual.
+ STHREADCALLINFO(INIT_VTABLE) { }
+
+
+private:
+ CALLDATA filter;
+ TRANSMIT_FN fnDispatch; // derived transmit/dispatch;
+
+ // The following fields are all private. Do not touch them.
+ CChannelControl *pServer;
+ BOOL fLocal;
+ ECallState eState;
+ SCODE hResult; // SCODE or exception code
+ HWND hWndCaller; // caller apartment hWnd (only used InWow)
+
+ friend class CChannelControl;
+ friend LRESULT ThreadWndProc(HWND, UINT, WPARAM, LPARAM);
+
+ // we pass &filter to the call control; this maps back to a STHREADCALLINFO
+ // and is necessary because of the virtual function table pointer.
+ static STHREADCALLINFO *MapCDToTCI(PCALLDATA pcd)
+ {
+ return (STHREADCALLINFO *)((char *)pcd - offsetof(STHREADCALLINFO,filter));
+ }
+
+} STHREADCALLINFO;
+
+
+// Temporaty hack that for GetTo and Switch that will go to any apartment.
+const HAPT ANY_APT = { 0xffffffff };
+
+
+/***************************************************************************/
+/* Classes. */
+
+/*
+
+ You have entered the channel controller zone (insert spooky
+ music here).
+
+ GetOffCOMThread
+
+ This function provides the client half of the COM message filter
+ scheme. In the multithread mode, it just calls the dispatch
+ function. In the single thread mode, it calls the dispatch function
+ on another thread and waits for other incoming calls. In either
+ case, if the call is rejected and the client wants to retry, the
+ dispatch function is recalled.
+
+ If HandleDispatchCall on the server side fails and returns
+ RPC_E_SERVERCALL_RETRYLATER or RPC_E_SERVERCALL_REJECTED, that value should
+ be returned by the dispatch function. It signals the call controller to
+ ask the application to retry a call. This routine does not throw
+ exceptions and the dispatch routine is not allowed to throw them. The
+ dispatch function should get the caller's logical thread is by looking at
+ the call.lid field.
+
+ The caller must derive its own data structure from STHREADCALLINFO and
+ provide the appropriate constructors. If the call is canceled
+ GetOffCOMThread will return RPC_E_CALL_CANCELED and null the
+ STHREADCALLINFO pointer. The virtual destructor will be called to
+ cause the block of memory to be uninitialized and freed.
+ The destructor may be called on either the RPC or the COM thread. Only
+ reference counted pointers can be passed through GetOffCOMThread to avoid
+ stale accesses if a call is canceled.
+
+
+ GetToCOMThread
+
+ This function provides the server half of the COM message filter
+ scheme. In the multithreaded mode, it just calls the dispatch
+ function. In the single threaded mode, it calls the dispatch
+ function on the thread indicated by the this pointer. The dispatch
+ function must call HandleDispatchCall before making any calls to the
+ server object except to the IUknown interface. HandleDispatchCall
+ may not be called in the multithreaded case.
+
+ HandleDispatchCall will call the channel controller. You must
+ set the pData field in the pDispatchData parameter to point to a
+ STHREADCALLINFO structure with the fnDispatch field set to your
+ second dispatch routine (via ResetDispatchFn).
+
+ In the multithreaded mode, the dispatch routine may throw server
+ exceptions. Otherwise the dispatch routine may not throw exceptions.
+ This routine will not throw exceptions.
+
+ The caller must derive its own data structure from STHREADCALLINFO and
+ provide the appropriate constructors. See GetOffCOMThread above.
+
+ If the call is an async call (CALLCAT_ASYNC), the caller must
+ implement the MakeAsyncCopy and FormulateAsyncReply methods. Those
+ functions are used to copy/detatch the data just before posting the
+ message. The regular destructor is used to delete the copy of the data
+ after processing it in the wnd proc.
+
+ Note that every async call will have a new logical thread id.
+
+
+ SwitchCOMThread
+
+ This function provides thread switching for in process apartment
+ model calls. It may not be called in the multithreaded mode. The
+ this pointer indicates which thread to switch to. It calls the
+ dispatch function on the server's apartment thread. The dispatch
+ function must call HandleDispatchCall before making any calls to the
+ server object except to the IUnknown and IMalloc interfaces.
+
+ HandleDispatchCall will call the channel controller. You must
+ set the pData field in the pDispatchData parameter to point to a
+ STHREADCALLINFO structure with the fnDispatch field set to your
+ second dispatch routine (via ResetDispatchFn).
+
+ The caller must derive its own data structure from STHREADCALLINFO and
+ provide the appropriate constructors. See GetOffCOMThread above.
+
+ If the call is an async call (CALLCAT_ASYNC), the caller must
+ implement the MakeAsyncCopy and FormulateAsyncReply methods as for
+ GetToCOMThread.
+
+*/
+
+class CChannelControl : public IChannelControl, public CPrivAlloc
+{
+ friend
+ LRESULT ThreadWndProc( HWND, UINT, WPARAM, LPARAM );
+
+ public:
+ // Struction methods
+ CChannelControl( HRESULT * );
+ ~CChannelControl();
+
+ // IUnknown methods
+ STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) ( void );
+ STDMETHOD_(ULONG,Release) ( void );
+
+ // IChannelControl
+ STDMETHOD (DispatchCall)( PDISPATCHDATA );
+ STDMETHOD (OnEvent) ( PCALLDATA );
+ STDMETHOD (TransmitCall)( PCALLDATA );
+
+ // Thread switching methods
+ static HRESULT GetOffCOMThread( STHREADCALLINFO ** );
+ static HRESULT GetToCOMThread ( HAPT, STHREADCALLINFO * );
+ static HRESULT SwitchCOMThread( HAPT, STHREADCALLINFO ** );
+ HRESULT GetToCOMThread ( STHREADCALLINFO * );
+ HRESULT SwitchCOMThread ( STHREADCALLINFO ** );
+
+ void ThreadStop ( void );
+
+ // Lookup the channel controller for a particular thread.
+ // Reference counted.
+ static CChannelControl *Lookup ( HAPT );
+ ICallControl *GetCallControl() { return _pCallControl; };
+ static void ThreadDispatch( STHREADCALLINFO **, BOOL dispatch );
+
+ private:
+ static void Cancel( STHREADCALLINFO ** );
+ HRESULT ProtectedPostToCOMThread(STHREADCALLINFO *call);
+
+ ULONG ref_count;
+ HWND ChannelWindow;
+ ICallControl *_pCallControl;
+ CCallMainControl *_pCMC;
+ EChannelControlState state;
+ DWORD _dwMyThreadId;
+ CChannelControl *_pChanContNext;
+ CChannelControl *_pChanContPrev;
+ static CChannelControl *_pChanContRoot;
+ static COleStaticMutexSem lock;
+};
+
+
+
+/***************************************************************************/
+/* Externals. */
+extern CEventCache EventCache;
+extern CChannelControl *ProcessChannelControl;
+
+#ifdef _CHICAGO_
+RPC_STATUS OleModalLoopBlockFn( void *, void *);
+HRESULT InitChannelControl();
+#endif
+
+#endif // _CHANCONT_HXX_
diff --git a/private/ole32/com/remote/channelb.cxx b/private/ole32/com/remote/channelb.cxx
new file mode 100644
index 000000000..3abc0b027
--- /dev/null
+++ b/private/ole32/com/remote/channelb.cxx
@@ -0,0 +1,2708 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: d:\nt\private\cairole\com\remote\channelb.cxx
+//
+// Contents: This module contains thunking classes that allow proxies
+// and stubs to use a buffer interface on top of RPC for Cairo
+//
+// Classes: CHeaderBrain
+// CChannelList
+// CRpcChannelBuffer
+//
+// Functions: CHeaderBrain::GetInboundData
+// CHeaderBrain::GetOutboundData
+// CHeaderBrain::SetOutboundBase
+// CHeaderBrain::SetInboundData
+// CHeaderBrain::SetOutboundData
+// CChannelList::Add
+// CChannelList::Grow
+// CChannelList::Cleanup
+// CChannelList::DisconnectHdlr
+// CChannelList::Lookup
+// CChannelList::LookupControl
+// CChannelList::DisconnectServiceHere
+// CChannelList::DisconnectService
+// ChannelInitialize
+// ChannelRegisterProtseq
+// ChannelUninitialize
+// CRpcChannelBuffer::AddRef
+// CRpcChannelBuffer::AppInvoke
+// CRpcChannelBuffer::ComInvoke
+// CRpcChannelBuffer::CRpcChannelBuffer
+// CRpcChannelBuffer::FreeBuffer
+// CRpcChannelBuffer::GetBuffer
+// CRpcChannelBuffer::QueryInterface
+// CRpcChannelBuffer::Release
+// CRpcChannelBuffer::GetCallCategory
+// CRpcChannelBuffer::SendReceive
+// DebugCoSetRpcFault
+// DllDebugObjectRPCHook
+// ThreadInvoke
+// ThreadSendReceive
+//
+// History: 22 Jun 93 AlexMi Created
+// 31 Dec 93 ErikGav Chicago port
+// 15 Mar 94 JohannP Added call category support.
+// 09 Jun 94 BruceMa Get call category from RPC message
+// 19 Jul 94 CraigWi Added support for ASYNC calls
+// 01-Aug-94 BruceMa Memory sift fix
+//
+//----------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include <channelb.hxx>
+
+#ifdef _CHICAGO_
+#include <islocalp.hxx>
+#endif // _CHICAGO_
+
+extern "C"
+{
+#include "orpc_dbg.h"
+}
+
+#include "rpcdcep.h"
+
+//+---------------------------------------------------------------------------
+//
+// Function: AppInvokeExceptionFilter
+//
+// Synopsis: Determine if the application as thrown an exception we want
+// to report. If it has, then print out enough information for
+// the 'user' to debug the problem
+//
+// Arguments: [lpep] -- Exception context records
+//
+// History: 6-20-95 kevinro Created
+//
+// Notes:
+//
+// At the moment, I was unable to get this to work for Win95, so I have
+// commented out the code.
+//
+//----------------------------------------------------------------------------
+
+
+#ifdef _CHICAGO_
+
+//
+// Win95 doesn't appear to support this functionality by default.
+//
+
+inline LONG
+AppInvokeExceptionFilter(
+ LPEXCEPTION_POINTERS lpep
+ )
+{
+ return(EXCEPTION_EXECUTE_HANDLER);
+}
+
+#else
+
+#include <imagehlp.h>
+
+#define SYM_HANDLE GetCurrentProcess()
+
+#if defined(_M_IX86)
+#define MACHINE_TYPE IMAGE_FILE_MACHINE_I386
+#elif defined(_M_MRX000)
+#define MACHINE_TYPE IMAGE_FILE_MACHINE_R4000
+#elif defined(_M_ALPHA)
+#define MACHINE_TYPE IMAGE_FILE_MACHINE_ALPHA
+#elif defined(_M_PPC)
+#define MACHINE_TYPE IMAGE_FILE_MACHINE_POWERPC
+#else
+#error( "unknown target machine" );
+#endif
+
+LONG
+AppInvokeExceptionFilter(
+ LPEXCEPTION_POINTERS lpep
+ )
+{
+#if DBG == 1
+ BOOL rVal;
+ STACKFRAME StackFrame;
+ CONTEXT Context;
+
+ SymSetOptions( SYMOPT_UNDNAME );
+ SymInitialize( SYM_HANDLE, NULL, TRUE );
+ ZeroMemory( &StackFrame, sizeof(StackFrame) );
+ Context = *lpep->ContextRecord;
+
+#if defined(_M_IX86)
+ StackFrame.AddrPC.Offset = Context.Eip;
+ StackFrame.AddrPC.Mode = AddrModeFlat;
+ StackFrame.AddrFrame.Offset = Context.Ebp;
+ StackFrame.AddrFrame.Mode = AddrModeFlat;
+ StackFrame.AddrStack.Offset = Context.Esp;
+ StackFrame.AddrStack.Mode = AddrModeFlat;
+#endif
+
+
+ CairoleDebugOut((DEB_FORCE,"An Exception occurred while calling into app\n"));
+ CairoleDebugOut((DEB_FORCE,
+ "Exception address = 0x%x Exception number 0x%x\n",
+ lpep->ExceptionRecord->ExceptionAddress,
+ lpep->ExceptionRecord->ExceptionCode ));
+
+ CairoleDebugOut((DEB_FORCE,"The following stack trace is where the exception occured\n"));
+ CairoleDebugOut((DEB_FORCE,"Frame RetAddr mod!symbol\n"));
+ do
+ {
+ rVal = StackWalk(MACHINE_TYPE,SYM_HANDLE,0,&StackFrame,&Context,ReadProcessMemory,
+ SymFunctionTableAccess,SymGetModuleBase,NULL);
+
+ if (rVal)
+ {
+ ULONG Displacement;
+ PIMAGEHLP_SYMBOL sym;
+ IMAGEHLP_MODULE ModuleInfo;
+ LPSTR pModuleName = "???";
+
+ sym = SymGetSymFromAddr(SYM_HANDLE,StackFrame.AddrPC.Offset,&Displacement);
+
+ //
+ // If there is module name information available, then grab it.
+ //
+ if(SymGetModuleInfo(SYM_HANDLE,StackFrame.AddrPC.Offset,&ModuleInfo))
+ {
+ pModuleName = ModuleInfo.ModuleName;
+ }
+
+ if (sym != NULL)
+ {
+ CairoleDebugOut((DEB_FORCE,
+ "%08x %08x %s!%s + %x\n",
+ StackFrame.AddrFrame.Offset,
+ StackFrame.AddrReturn.Offset,
+ pModuleName,
+ sym->Name,
+ Displacement));
+ }
+ else
+ {
+ CairoleDebugOut((DEB_FORCE,
+ "%08x %08x %s!%08x\n",
+ StackFrame.AddrFrame.Offset,
+ StackFrame.AddrReturn.Offset,
+ pModuleName,
+ StackFrame.AddrPC.Offset));
+ }
+ }
+ } while( rVal );
+
+ SymCleanup( SYM_HANDLE );
+
+#endif
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+#endif // _CHICAGO_
+
+#pragma code_seg(".orpc")
+
+/***************************************************************************/
+/* Defines. */
+
+#define MAKE_WIN32( status ) \
+ MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, (status) )
+
+// This should just return a status to runtime, but runtime does not
+// support both comm and fault status yet.
+#ifdef _CHICAGO_
+#define RETURN_COMM_STATUS( status ) return (status)
+#else
+#define RETURN_COMM_STATUS( status ) RpcRaiseException( status )
+#endif
+
+/***************************************************************************/
+/* Typedefs. */
+// The size of this structure must be a multiple of 8.
+typedef struct Inbound_Header
+{
+ DWORD channel_id;
+ UUID logical_thread;
+ IID iid;
+ unsigned int proc_num;
+ DWORD callcat;
+
+ // Warning - This field must be last, see CHeaderBrain.
+ unsigned long debug_data_size;
+} Inbound_Header;
+
+
+
+// The size of this structure must be a multiple of 8.
+typedef struct Outbound_Header
+{
+ // This field has one of the following values: RPC_E_SERVERCALL_REJECTED,
+ // RPC_E_SERVERCALL_RETRYLATER, or S_OK.
+ HRESULT rejected;
+
+ // Warning - This field must be last, see CHeaderBrain.
+ unsigned long debug_data_size;
+} Outbound_Header;
+
+struct com_call : STHREADCALLINFO
+{
+ com_call(TRANSMIT_FN fn,CALLCATEGORY callcat,DWORD tid=0)
+ : STHREADCALLINFO(fn, callcat, tid) { }
+ com_call(DISPATCH_FN fn,CALLCATEGORY callcat,REFLID lid)
+ : STHREADCALLINFO(fn, callcat, lid) { }
+ virtual ~com_call();
+ virtual STHREADCALLINFO *MakeAsyncCopy(STHREADCALLINFO *);
+ virtual BOOL FormulateAsyncReply();
+
+ // this ctor is used in conjunction with MakeAsyncCopy and sets up the vtable
+ // pointer; MakeAsyncCopy actually initializes the instance. A normal copy
+ // constructor isn't used because they aren't virtual.
+ com_call(INIT_VTABLE i) : STHREADCALLINFO(i) { }
+
+ RPCOLEMESSAGE *pmessage;
+ DWORD server_fault;
+
+ // The client and server specific parts cannot be a union because they
+ // both exists in the local case.
+ // Client side only.
+ BOOL first_try;
+ DWORD channel_id;
+ CRpcService *service; // (NULL on server side)
+
+ // Server side only (only used within CRpcChannelBuffer::ComInvoke/AppInvoke)
+ IRpcStubBuffer *stub;
+ CRpcChannelBuffer *channel;
+};
+
+struct disconnect_service_data : STHREADCALLINFO
+{
+ disconnect_service_data (DISPATCH_FN fn,CALLCATEGORY callcat,REFLID lid)
+ : STHREADCALLINFO(fn, callcat, lid) { }
+ virtual ~disconnect_service_data()
+ { if (service != NULL) service->Release(); }
+
+ CRpcService *service; // NULL or valid
+};
+
+// This structure contains a copy of all the information needed to make a
+// call. It is copied so it can be canceled without stray pointer references.
+struct working_call : com_call
+{
+ // we only construct this on the transmitting side.
+ working_call(TRANSMIT_FN fn,CALLCATEGORY callcat,DWORD tid=0)
+ : com_call(fn, callcat, tid) { }
+
+ // this ctor is used in conjunction with MakeAsyncCopy and sets up the vtable
+ // pointer; MakeAsyncCopy actually initializes the instance. A normal copy
+ // constructor isn't used because they aren't virtual.
+ working_call(INIT_VTABLE i) : com_call(i) { }
+
+ RPCOLEMESSAGE message;
+};
+
+//-------------------------------------------------------------------------
+//
+// Function: GetInterfaceName
+//
+// synopsis: Gets the human readable name of an Interface given it's IID.
+//
+// History: 12-Jun-95 Rickhi Created
+//
+//-------------------------------------------------------------------------
+LONG GetInterfaceName(REFIID riid, WCHAR *pwszName)
+{
+ // Read the registry entry for the interface to get the interface name
+ LONG ulcb=256;
+ WCHAR szKey[80];
+
+ lstrcpyW(szKey, L"Interface\\");
+ StringFromGUID2(riid,&szKey[10],80);
+
+ LONG result = RegQueryValue(
+ HKEY_CLASSES_ROOT,
+ szKey,
+ pwszName,
+ &ulcb);
+
+ return result;
+}
+
+/***************************************************************************/
+/* Classes. */
+
+/* This class manages the various headers in a COM packet. For inbound packets
+ the Inbound_Header is followed by the optional debug data which is followed
+ by the users data. For outbound packets, the Outbound_Header is followed by
+ the optional debug data which is followed by the users data.
+
+ The space for the debug data is reserved in the following cases:
+ client get buf to send receive
+ server ThreadInvoke to stub invoke
+ server get buffer to the return of ThreadInvoke
+ client send receive to client free buffer
+
+ The debug data is only valid, however, from the SendReceive in the client
+ to the beginning of AppInvoke in the server and from the end of AppInvoke
+ on the server back to SendReceive on the client. All cases that write
+ a debug size on to the tail end of the debug information (and thus corrupt
+ it) are outside these times of validity.
+
+ The following terms are used to create the function names:
+ Get Get some data about the headers.
+ Set Set some data about the headers.
+ Inbound A packet going from client to server (request).
+ Outbound A packet going from server to client (reply).
+ Base Pointer to the Channel header (Inbound_Header or Outbound_Header).
+ Debug Pointer to the debug data.
+ Data Pointer to the user data.
+
+ Warning: the methods of this class are full of side effects (data destroying
+ side effects). The methods must be called in a particular order.
+
+ Client:
+ GetBuffer
+ SetDebugSize
+ SetBase
+ GetInboundData
+ SendReceive
+ SetInboundData
+ GetBase or GetDebugSize
+ GetInboundDebug
+ I_RpcSendReceive
+ SetOutboundBase
+ GetDebugSize
+ GetOutboundDebug
+ GetOutboundData
+ FreeBuffer
+ SetOutboundData
+ GetBase or GetDebugSize
+
+ Server:
+ AppInvoke:
+ SetBase
+ SetDebugSize
+ GetDebugSize
+ GetInboundDebug
+ GetInboundData
+ stub
+ SetOutboundData
+ GetBase
+ GetDebugSize
+ GetOutboundDebug
+ GetBuffer
+ SetInboundBase
+ GetBase
+ SetDebugSize
+ GetDebugSize
+ I_RpcGetBuffer
+ SetBase
+ GetOutboundData
+ GetDebugSize
+ GetBase or GetDebugSize
+
+*/
+
+class CHeaderBrain
+{
+ public:
+ CHeaderBrain() { debug_size = 0; };
+ RPCOLEMESSAGE *GetBase() { return (RPCOLEMESSAGE *) base; };
+ inline void *GetInboundData();
+ inline void *GetOutboundData();
+ void *GetInboundDebug() { return base+sizeof(Inbound_Header); };
+ void *GetOutboundDebug() { return base+sizeof(Outbound_Header); };
+ ULONG GetDebugSize() { return debug_size; };
+ inline void SetBase( void *param ) { base = (char *) param; };
+ inline void SetInboundData( void * );
+ inline void SetOutboundBase( void *param );
+ inline void SetOutboundData( void * );
+ inline void SetDebugSize( ULONG param ) { debug_size = param; };
+
+ private:
+ char *base;
+ ULONG debug_size;
+};
+
+/*
+ Get the Inbound user data pointer. At this time the debug header size is
+ stashed away just before the user data. Saving the debug size corrupts the
+ debug data if present. If not present, it ends up being written back to
+ the debug size field in the Inbound_Header.
+*/
+inline void *CHeaderBrain::GetInboundData()
+{
+ ULONG *tmp = (ULONG *) (base + sizeof(Inbound_Header) + debug_size - sizeof(ULONG));
+ *tmp = debug_size;
+ return tmp+1;
+}
+
+/*
+ Get the Outbound user data pointer. At this time the debug header size is
+ stashed away just before the user data. Saving the debug size corrupts the
+ debug data if present. If not present, it ends up being written back to
+ the debug size field in the Outbound_Header.
+*/
+inline void *CHeaderBrain::GetOutboundData()
+{
+ ULONG *tmp = (ULONG *) (base + sizeof(Outbound_Header) + debug_size - sizeof(ULONG));
+ *tmp = debug_size;
+ return tmp+1;
+}
+
+/*
+ Initialize a CHeaderBrain given a pointer to the Outbound_Header.
+*/
+inline void CHeaderBrain::SetOutboundBase( void *param )
+{
+ base = (char *) param;
+ debug_size = ((Outbound_Header *) base)->debug_data_size;
+};
+
+/*
+ Initialize a CHeaderBrain given a pointer to the user data in an
+ inbound packet. Note that this is only called after GetInboundData
+ so the debug data size is stashed just before the user data.
+ Read the debug size and compute the real base.
+*/
+inline void CHeaderBrain::SetInboundData( void *param )
+{
+ ULONG *tmp = ((ULONG *) param) - 1;
+ debug_size = *tmp;
+ base = ((char *) (tmp+1)) - debug_size - sizeof(Inbound_Header);
+ ((Inbound_Header *) base)->debug_data_size = debug_size;
+}
+
+/*
+ Initialize a CHeaderBrain given a pointer to the user data in an
+ outbound packet. Note that this is only called after GetOutboundData
+ so the debug data size is stashed just before the user data.
+ Read the debug size and compute the real base.
+*/
+inline void CHeaderBrain::SetOutboundData( void *param )
+{
+ ULONG *tmp = ((ULONG *) param) - 1;
+ debug_size = *tmp;
+ base = ((char *) (tmp+1)) - debug_size - sizeof(Outbound_Header);
+ ((Outbound_Header *) base)->debug_data_size = debug_size;
+}
+
+/***************************************************************************/
+//+-------------------------------------------------------------------
+//
+// Class: CCallCache
+//
+// Purpose: This class caches allocations on the working_call structure.
+// The class keeps an array of up to CALLCACHE_SIZE elements.
+// If there is an element in the array on Get, it is returned.
+// Otherwise on if allocated. If there is space in the array
+// on Free, the block is cached. Otherwise it is freed.
+//
+// Note that this class must use PrivMemAlloc because the
+// caller is allowed to free them using PrivMemFree rather
+// then calling Free. The channel controller frees the
+// structures when calls are canceled.
+//
+// NOTE: this class is identical to the event cache except that the
+// resource allocation and free is different. This suggests makeing this
+// a virtual base class with virtual methods that do that allocation
+// and free, and virtual methods that just do casting to the correct type
+// for get and free.
+//
+// NOTE: this class *must* be allocated statically, as it holds a
+// COleStaticMutexSem. We take advantage of the platform initializing static
+// memory to 0, and so don't use a constructor for this class. If the
+// Initialize member is modified to set something to other than 0, then this
+// needs to be reworked.
+//
+// Interface:
+//
+// History: 28 June 94 AlexMit Created
+//
+//--------------------------------------------------------------------
+const DWORD CALLCACHE_SIZE = 8;
+
+class CCallCache
+{
+ public:
+ void Cleanup();
+ void Free( working_call * );
+ working_call *Get();
+ void Initialize();
+
+ private:
+ working_call *list[CALLCACHE_SIZE];
+ DWORD next;
+ COleStaticMutexSem lock;
+};
+
+/***************************************************************************/
+/* Prototypes. */
+void ThreadInvoke ( RPC_MESSAGE *message );
+HRESULT ThreadSendReceive ( STHREADCALLINFO * );
+
+
+/***************************************************************************/
+/* Globals. */
+
+COleStaticMutexSem ChannelLock;
+
+RPC_DISPATCH_FUNCTION vector =
+ (void (__stdcall *) (struct ::_RPC_MESSAGE *)) ThreadInvoke;
+
+RPC_DISPATCH_TABLE the_dispatch_table =
+{ 1, &vector, 0 };
+
+RPC_SERVER_INTERFACE the_server_if =
+{
+ sizeof(RPC_SERVER_INTERFACE),
+ {0x69C09EA0, 0x4A09, 0x101B, 0xAE, 0x4B, 0x08, 0x00, 0x2B, 0x34, 0x9A, 0x02,
+ {0, 0}},
+ {0x8A885D04, 0x1CEB, 0x11C9, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60,
+ {2, 0}},
+ &the_dispatch_table, 0, 0, 0
+};
+
+
+RPC_CLIENT_INTERFACE the_client_if =
+{
+ sizeof(RPC_CLIENT_INTERFACE),
+ {0x69C09EA0, 0x4A09, 0x101B, 0xAE, 0x4B, 0x08, 0x00, 0x2B, 0x34, 0x9A, 0x02,
+ {0, 0}},
+ {0x8A885D04, 0x1CEB, 0x11C9, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60,
+ {2, 0}},
+ 0, 0, 0, 0
+};
+
+
+// Has the app made remote calls?
+BOOL MadeCalls = FALSE;
+
+
+// Should the debugger hooks be called?
+BOOL DoDebuggerHooks = FALSE;
+LPORPC_INIT_ARGS DebuggerArg = NULL;
+
+// List of channels.
+CChannelList ChannelList;
+CRpcChannelBuffer **CChannelList::_pList = NULL;
+DWORD CChannelList::_ulLength = 0;
+DWORD CChannelList::_dwSequence;
+DWORD CChannelList::_dwFree = BAD_CHANNEL_ID;
+COleStaticMutexSem CChannelList::_lock;
+
+// Cache of working_call structures.
+CCallCache CallCache;
+
+
+/***************************************************************************/
+/*
+ Insert a channel into the list of channels. The list is used to look up
+ server side channels during dispatch. The channel stays in the list until
+ it is disconnected, runs down, or is released (when the channel is released
+ the lookup function is called with the remove parameter true). In the
+ normal case, the client side channel holds the server side channel till
+ ReleaseChannel is called.
+
+ The channel list holds an addref for each pointer in the list. Thus,
+ the removal of an entry also releases it.
+*/
+
+DWORD CChannelList::Add(CRpcChannelBuffer *pChannel)
+{
+ // single thread access
+ COleStaticLock lck(_lock);
+
+ // grab first entry on the free list
+ DWORD id = _dwFree;
+
+ if (id == BAD_CHANNEL_ID)
+ {
+ // there is no free space in the list, grow the list.
+
+ Win4Assert(((_ulLength + CLIST_EXPAND_SIZE) & CLIST_SEQUENCE_MASK) == 0);
+ id = Grow(_ulLength + CLIST_EXPAND_SIZE);
+
+ if (id == BAD_CHANNEL_ID)
+ {
+ // couldn't grow the list
+ return id;
+ }
+ }
+
+ // adjust the free list to next entry
+ _dwFree = (DWORD) _pList[id];
+
+ _pList[id] = pChannel;
+ id |= _dwSequence;
+ _dwSequence += CLIST_SEQUENCE_INC;
+
+ pChannel->AddRef();
+ pChannel->SetID( id );
+
+ return id;
+}
+
+
+/***************************************************************************/
+DWORD CChannelList::Grow(ULONG ulNewSize)
+{
+ CRpcChannelBuffer **pNewList = (CRpcChannelBuffer **)
+ PrivMemAlloc (ulNewSize * sizeof(CRpcChannelBuffer **));
+
+ if (pNewList)
+ {
+ if (_pList)
+ {
+ // there was an existing list, copy it over to the new list
+ // and free the old one.
+
+ memcpy(pNewList, _pList, _ulLength * sizeof(CRpcChannelBuffer **));
+ PrivMemFree(_pList);
+ }
+
+ // build the new free list
+ ULONG i;
+ for (i = _ulLength; i < ulNewSize-1; i++)
+ {
+ pNewList[i] = (CRpcChannelBuffer *) (i+1);
+ }
+
+ // set the last one to BAD so we know when to grow again.
+ pNewList[i] = (CRpcChannelBuffer *) BAD_CHANNEL_ID;
+
+ _dwFree = _ulLength;
+ _ulLength = ulNewSize;
+ _pList = pNewList;
+ }
+
+ // if the allocation failed, free_list is still BAD, if it succeeded,
+ // then free_list is the first free spot in the list.
+
+ return _dwFree;
+}
+
+
+/***************************************************************************/
+void CChannelList::Cleanup()
+{
+ _lock.Request();
+#if DBG==1
+ // Make sure there are no channels left in the list.
+ ULONG i;
+ for (i = 0; i < _ulLength; i++)
+ if ((ULONG) _pList[i] > _ulLength &&
+ (ULONG) _pList[i] != BAD_CHANNEL_ID)
+ CairoleDebugOut((DEB_ERROR, "ChannelList is not empty on cleanup, channel = %x\n",
+ _pList[i]));
+#endif
+
+ PrivMemFree( _pList );
+ _pList = NULL;
+ _ulLength = 0;
+ _dwFree = BAD_CHANNEL_ID;
+ _lock.Release();
+}
+
+/***************************************************************************/
+/*
+ Note that this must be called on the thread the object lives on.
+*/
+void CChannelList::DisconnectHdlr( IRemoteHdlr *remote_handler )
+{
+ CairoleDebugOut((DEB_CHANNEL, "DisconnectHdlr pRH:%x\n", remote_handler));
+
+ CRpcChannelBuffer *pChannel = NULL;
+
+ _lock.Request();
+
+ for (ULONG i = 0; i < _ulLength; i++)
+ {
+ if ((ULONG) _pList[i] > _ulLength &&
+ (ULONG) _pList[i] != BAD_CHANNEL_ID &&
+ (pChannel = _pList[i])->GetRH() == remote_handler)
+ {
+ // Remove the channel from the list and release it.
+ _pList[i] = (CRpcChannelBuffer *) _dwFree;
+ _dwFree = i;
+ pChannel->SetID(BAD_CHANNEL_ID);
+ _lock.Release();
+ pChannel->DisconnectObject(0);
+ pChannel->Release();
+ _lock.Request();
+ }
+ }
+
+ _lock.Release();
+}
+
+
+/***************************************************************************/
+CRpcChannelBuffer *CChannelList::Lookup(DWORD id, BOOL fRemove, BOOL fAddref)
+{
+ // don't allow removing and not addrefing at the same time
+ // (since the channel pointer returned would likely be of no use).
+ Win4Assert(!fRemove || fAddref);
+
+ COleStaticLock lck(_lock);
+
+ if ((id & CLIST_ID_MASK) >= _ulLength )
+ return NULL;
+
+ CRpcChannelBuffer *pChannel = _pList[id & CLIST_ID_MASK];
+
+ if ((DWORD) pChannel < _ulLength ||
+ (DWORD) pChannel == BAD_CHANNEL_ID ||
+ pChannel->GetID() != id)
+ {
+ pChannel = NULL;
+ }
+ else
+ {
+ if (fAddref)
+ {
+ pChannel->AddRef();
+ pChannel->AssertValid(FALSE, FALSE); // not in assert, can do assert
+ }
+
+ if (fRemove)
+ {
+ _pList[id & CLIST_ID_MASK] = (CRpcChannelBuffer *) _dwFree;
+ _dwFree = id & CLIST_ID_MASK;
+ pChannel->SetID(BAD_CHANNEL_ID);
+ pChannel->Release();
+ }
+ }
+
+ return pChannel;
+}
+
+
+/***************************************************************************/
+CChannelControl *CChannelList::LookupControl( DWORD id )
+{
+ CChannelControl *controller = NULL;
+
+ Win4Assert( (id & CLIST_ID_MASK) < _ulLength );
+ COleStaticLock lck(_lock);
+
+ if ((id & CLIST_ID_MASK) >= _ulLength )
+ return NULL;
+
+ CRpcChannelBuffer *pChannel = _pList[id & CLIST_ID_MASK];
+
+ if ((DWORD) pChannel > _ulLength &&
+ (DWORD) pChannel != BAD_CHANNEL_ID &&
+ pChannel->GetID() == id)
+ {
+ controller = pChannel->GetControl();
+ controller->AddRef();
+ }
+
+ return controller;
+}
+
+
+/***************************************************************************/
+DWORD CChannelList::LookupIdByOid( OID object, CRpcService *service, DWORD tid )
+{
+ CRpcChannelBuffer *channel = NULL;
+ DWORD thread = GetCurrentThreadId();
+ DWORD id = BAD_CHANNEL_ID;
+ OID channel_oid;
+
+ _lock.Request();
+
+ for (ULONG i = 0; i < _ulLength; i++)
+ {
+ channel = _pList[i];
+ if ((ULONG) channel > _ulLength &&
+ (ULONG) channel != BAD_CHANNEL_ID &&
+ channel->my_thread == thread &&
+ channel->_dwClientTID == tid &&
+ channel->_pService == service)
+ {
+ channel->_pRH->GetObjectID( &channel_oid );
+ if (channel_oid == object)
+ {
+ id = channel->_ChannelID;
+ break;
+ }
+ }
+ }
+
+ _lock.Release();
+
+ return id;
+}
+
+
+/***************************************************************************/
+/* static */
+/*
+ This function disconnects all the channels on the current thread that
+ use the specified service object. Since this is private, it is obviously
+ only used by this class. I'll give you one guess which function calls
+ this one. If you can't figure it out, you should retire.
+*/
+/* static */
+HRESULT CChannelList::DisconnectServiceHere( STHREADCALLINFO *callinfo )
+{
+ CairoleDebugOut((DEB_CHANNEL, "DisconnectServiceHere\n"));
+
+ CRpcChannelBuffer *pChannel;
+ disconnect_service_data *msg = (disconnect_service_data *) callinfo;
+ DWORD thread = GetCurrentThreadId();
+
+ _lock.Request();
+
+ for (ULONG i = 0; i < _ulLength; i++)
+ {
+ if ((ULONG) _pList[i] > _ulLength &&
+ (ULONG) _pList[i] != BAD_CHANNEL_ID)
+ {
+ pChannel = _pList[i];
+ if (pChannel->GetServerApt() == thread)
+ if (msg->service == NULL ||
+ pChannel->GetService() == msg->service)
+ {
+ // Remove the channel from the list and release it.
+ _pList[i] = (CRpcChannelBuffer *) _dwFree;
+ _dwFree = i;
+ pChannel->SetID(BAD_CHANNEL_ID);
+ _lock.Release();
+
+ pChannel->DisconnectObject(0);
+ pChannel->Release();
+ _lock.Request();
+ }
+ }
+ }
+
+ _lock.Release();
+ if (msg->service != NULL)
+ {
+ msg->service->Release();
+ msg->service = NULL; // NULL out so dtor doesn't release again
+ }
+
+ return S_OK;
+}
+
+/***************************************************************************/
+/*
+ This function disconnects all server channels that use a service object.
+ The function may be called on any thread and causes DisconnectObject
+ to be called on each relevent channel on the correct thread.
+
+ This function is called in two cases: rundown and process uninitialization.
+ On rundown, we want to notify all threads that use the
+ service object. On process uninitialize there are no other threads so
+ we can call DisconnectServiceHere for this thread.
+
+ NOTE: There is a special requirement that process uninitialize be
+ synchronous.
+
+ NOTE: This routine should be optimized to only post one message per
+ thread.
+
+ service == NULL means to disconnect all channel objects.
+*/
+void CChannelList::DisconnectService( CRpcService *pService )
+{
+ CRpcChannelBuffer *pChannel;
+ CChannelControl *controller;
+
+ HRESULT result;
+
+ // If process uninitialize, just clean up this thread, it is the only
+ // one left.
+ if (pService == NULL)
+ {
+ disconnect_service_data msg(DisconnectServiceHere,
+ CALLCAT_INTERNALSYNC, GUID_NULL);
+ msg.service = pService;
+ DisconnectServiceHere( &msg );
+ }
+
+ // Clean up all threads.
+ else
+ {
+ // we don't care if this fails (which is unlikely, anyway) because
+ // we would rather cleanup on a bogus lid than not clean up.
+ LID lid;
+ (void)CoCreateAlmostGuid(&lid);
+
+ _lock.Request();
+
+ for (ULONG i = 0; i < _ulLength; i++)
+ {
+ if ((ULONG) _pList[i] > _ulLength &&
+ (ULONG) _pList[i] != BAD_CHANNEL_ID)
+ {
+ pChannel = _pList[i];
+ if (pChannel->GetService() == pService)
+ {
+ controller = pChannel->GetControl();
+ controller->AddRef();
+ _lock.Release();
+
+ // must construct a new msg for each call.
+ disconnect_service_data msg(DisconnectServiceHere,
+ CALLCAT_INTERNALSYNC, lid);
+
+ // NOTE - This can be optimized to avoid sending multiple
+ // requests to the same channel.
+ msg.service = pService;
+ pService->AddRef(); // released by DisconnectServiceHere or dtor
+
+ result = controller->GetToCOMThread( &msg );
+
+ controller->Release();
+ _lock.Request();
+ }
+ }
+ }
+
+ _lock.Release();
+ }
+}
+
+
+/***************************************************************************/
+STDAPI ChannelProcessInitialize()
+{
+ TRACECALL(TRACE_RPC, "ChannelInitialize");
+ Win4Assert( (sizeof(Inbound_Header) & 7) == 0 );
+ Win4Assert( (sizeof(Outbound_Header) & 7) == 0 );
+
+ // Initialize the channel list
+ ChannelList.AdjustSequence( GetCurrentProcessId() );
+ CallCache.Initialize();
+
+#ifdef _CHICAGO_
+ // For chicago set up the global list of local services
+ lslLocalServices.Init();
+#endif // _CHICAGO_
+
+#ifndef _CHICAGO_
+ // create the service object for the LOCAL process and store
+ // it in the global service list.
+ SetLocalService( FindSRVFromEP(NULL, TRUE) );
+ if (LocalService())
+ {
+ LocalService()->AssertValid();
+ }
+ else
+ {
+ return E_OUTOFMEMORY;
+ }
+#endif
+
+ return ChannelControlProcessInitialize();
+}
+
+//--------------------------------------------------------------------
+//
+// Function: ChannelRegisterProtseq
+//
+// synopsis:
+//
+//
+// Algorithm:
+//
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+STDAPI ChannelRegisterProtseq(WCHAR *pwszProtseq)
+{
+ return LocalService()->RegisterProtseq(pwszProtseq);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: ChannelThreadUninitialize, public
+//
+// Synopsis: Uninitializes the channel subsystem per thread data.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Notes: This is called at thread uninitialize, not process
+// uninitialize.
+//
+//--------------------------------------------------------------------
+STDAPI_(void) ChannelThreadUninitialize(void)
+{
+ TRACECALL(TRACE_RPC, "ChannelThreadUninitialize");
+
+ // On Chicago, the local service object and service list are kept
+ // per apartment, whereas on Daytona they are per process. We clean
+ // up the per apartment stuff here and the per process stuff in
+ // ChannelProcessUninitialize.
+
+ Win4Assert(!FreeThreading
+ && "ChannelThreadUninitialize called and Free Threading");
+
+#ifdef _CHICAGO_
+ CRpcService *pSrv = LocalService();
+ if (pSrv)
+ {
+ // disconnect all client channels from the local service object
+ ChannelList.DisconnectService(pSrv);
+ }
+#endif
+
+ // cleanup the channel controller, disallowing any more incoming
+ // calls to this apartment.
+ ChannelControlThreadUninitialize();
+
+#ifdef _CHICAGO_
+ // release the local service object
+ if (pSrv != NULL)
+ {
+ pSrv->Release();
+ SetLocalService(NULL);
+ }
+
+ // cleanup the list of service objects
+ CSrvList *list = (CSrvList *) TLSGetServiceList();
+ if (list != NULL)
+ {
+ list->Cleanup();
+ TLSSetServiceList(NULL);
+ delete list;
+ }
+#endif
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: ChannelProcessUninitialize, public
+//
+// Synopsis: Uninitializes the channel subsystem global data.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Notes: This is called at process uninitialize, not thread
+// uninitialize.
+//
+//--------------------------------------------------------------------
+STDAPI_(void) ChannelProcessUninitialize(void)
+{
+ TRACECALL(TRACE_RPC, "ChannelProcessUninitialize");
+
+ // cleanup the channel controller process wide state
+ ChannelControlProcessUninitialize();
+
+ ChannelList.Cleanup();
+
+#ifdef _CHICAGO_
+ // For chicago clean up the global list of local services
+ lslLocalServices.Uninit();
+#else
+ // On Chicago, the local service object and service list are kept
+ // per apartment, wheras on Daytona they are per process. We clean
+ // up the per process stuff here and the per apartment stuff in
+ // ChannelThreadUninitialize.
+
+ // release the global local service object
+ CRpcService *pSrv = LocalService();
+ if (pSrv != NULL)
+ {
+ // BUGBUG: must release the local service before doing SetLocalService
+ // to NULL because CRpcService::AssertValid makes use of LocalService
+ // to determine if this is a client service object or the local service
+ // object. This info should be intrinsic to the object itself.
+ pSrv->Release();
+ SetLocalService(NULL);
+ }
+
+ // cleanup the list of service objects
+ sg_SrvList.Cleanup();
+
+#endif // _CHICAGO_
+
+ CallCache.Cleanup();
+ return;
+}
+
+
+/***************************************************************************/
+/* This is the destructor for a com_call.
+*/
+com_call::~com_call()
+{
+ // Release the reply buffer.
+ if (pmessage != NULL)
+ DeallocateBuffer(pmessage);
+
+ // the message pointer is either NULL or points immediately after us
+ // and thus there is no need to free it separately.
+ Win4Assert(pmessage == NULL || (RPCOLEMESSAGE *)(this + 1) == pmessage);
+
+ // Release the service object.
+ if (service != NULL)
+ service->Release();
+
+ // NOTE: the stub and channel members are set and reset synchronously
+ // within ComInvoke and thus need no attention here.
+}
+
+
+/***************************************************************************/
+/* Makes an copy of the message (which is returned); the original is untouched.
+ The copy has a new lid, separate event, addref'd pointers, etc.
+*/
+STHREADCALLINFO *com_call::MakeAsyncCopy(STHREADCALLINFO *thread)
+{
+ Win4Assert(thread == NULL && "should be top-level async copy");
+
+ working_call *pwcall = CallCache.Get();
+
+ if (pwcall == NULL)
+ return NULL;
+
+ // we don't want to call a regular constructor here because that would
+ // do the initialization twice, but we do want to call some ctor to
+ // initialize the vtable pointers.
+ pwcall->working_call::working_call(init_vtable);
+
+ void *pBuffer = PrivMemAlloc8(pmessage->cbBuffer);
+
+ Win4Assert(((ULONG)pBuffer & 0x7) == 0 && "Buffer not aligned properly");
+
+ if (pBuffer != NULL && STHREADCALLINFO::MakeAsyncCopy(pwcall) != NULL)
+ {
+ // finish constructing the instance of working_call
+
+ // NULL this out so the dtor can tell that this is the server
+ // side and this value need not be released.
+ pwcall->service = NULL;
+
+ pwcall->pmessage = &pwcall->message;
+ memcpy(&pwcall->message, pmessage, sizeof(RPCOLEMESSAGE));
+
+ pwcall->message.Buffer = pBuffer;
+ memcpy(pBuffer, pmessage->Buffer, pmessage->cbBuffer);
+
+ // pretend local so we don't touch rpc for more buffers, etc.
+ pwcall->message.rpcFlags |= RPCFLG_LOCAL_CALL;
+
+ }
+ else
+ {
+ // could not allocate all pieces; nothing constructed so just free
+ PrivMemFree(pBuffer);
+ CallCache.Free(pwcall);
+ pwcall = NULL;
+ }
+
+ // Free the input buffer for local calls.
+ if (pmessage->rpcFlags & RPCFLG_LOCAL_CALL)
+ DeallocateBuffer( pmessage );
+ return pwcall;
+}
+
+
+// called to convert an incoming message into a successful async reply.
+// returns TRUE if successful; FALSE if out of memory.
+BOOL com_call::FormulateAsyncReply()
+{
+
+ STHREADCALLINFO::FormulateAsyncReply();
+
+ // setup reply to original; royal kludge: this is what all async
+ // calls expect; only a return value.
+ pmessage->cbBuffer = sizeof(Outbound_Header) + 4;
+
+ if (pmessage->rpcFlags & RPCFLG_LOCAL_CALL)
+ {
+ pmessage->Buffer = PrivMemAlloc8(pmessage->cbBuffer);
+ if (pmessage->Buffer == NULL)
+ return FALSE;
+ }
+ else
+ {
+ if (I_RpcGetBuffer((RPC_MESSAGE *) pmessage) != RPC_S_OK)
+ return FALSE;
+ }
+
+ // NOTE: the debugger will follow the thread of execution into the
+ // async routine. The reply is made to the caller without debug
+ // information. This is simplest for now and may need to be changed.
+
+ // simulate success in method call
+ ((Outbound_Header*)pmessage->Buffer)->rejected = SERVERCALL_ISHANDLED;
+ ((Outbound_Header*)pmessage->Buffer)->debug_data_size = 0;
+ *(SCODE *)((Outbound_Header *)pmessage->Buffer + 1) =S_OK;
+
+ return TRUE;
+}
+
+
+/***************************************************************************/
+STDMETHODIMP_(ULONG) CRpcChannelBuffer::AddRef( THIS )
+{
+ // can't call AssertValid(FALSE) since it is used in asserts
+ InterlockedIncrement( (long *) &ref_count );
+ return ref_count;
+}
+
+/***************************************************************************/
+// Static, but the compiler doesn't like to see that here.
+
+#if DBG == 1
+DWORD AppInvoke_break = 0;
+DWORD AppInvoke_count = 0;
+#endif
+HRESULT CRpcChannelBuffer::AppInvoke( STHREADCALLINFO *thread )
+{
+ com_call *call = (com_call *) thread;
+ RPCOLEMESSAGE *message = (RPCOLEMESSAGE *) call->pmessage;
+ CHeaderBrain fixup;
+
+ void *orig_buffer = message->Buffer;
+ ULONG orig_buffer_size = message->cbBuffer;
+ void *orig_stub_buffer;
+ HRESULT result;
+#if DBG == 1
+ IID iidBeingCalled = ((Inbound_Header *) orig_buffer)->iid;
+ DWORD dwMethod = ((Inbound_Header *) orig_buffer)->proc_num;
+#endif
+
+ // If the debugger is active or if there is debug data in the packet,
+ // notify the debugger.
+ fixup.SetBase( message->Buffer );
+ fixup.SetDebugSize( ((Inbound_Header *) message->Buffer)->debug_data_size );
+ message->iMethod = ((Inbound_Header *) message->Buffer)->proc_num;
+ if (!IsWOWThread() && (fixup.GetDebugSize() != 0 || DoDebuggerHooks))
+ {
+ void *iface;
+ if (!SUCCEEDED(call->stub->DebugServerQueryInterface( &iface )))
+ iface = NULL;
+ DebugORPCServerNotify( message,
+ ((Inbound_Header *)orig_buffer)->iid,
+ call->channel,
+ iface,
+ NULL,
+ fixup.GetInboundDebug(),
+ fixup.GetDebugSize(),
+ DebuggerArg,
+ DoDebuggerHooks );
+ if (iface != NULL)
+ call->stub->DebugServerRelease( iface );
+ }
+
+ // Adjust the buffer.
+ message->Buffer = fixup.GetInboundData();
+ orig_stub_buffer = message->Buffer;
+ message->cbBuffer -= sizeof(Inbound_Header) +
+ fixup.GetDebugSize();
+
+ // Call the stub.
+ _try
+ {
+ TRACECALL(TRACE_RPC, "CRpcChannelBuffer::StubInvoke");
+#if DBG == 1
+ //
+ // On a debug build, we are able to break on a call by serial number.
+ // This isn't really 100% thread safe, but is still extremely useful
+ // when debugging a problem.
+ //
+ DWORD dwBreakCount = ++AppInvoke_count;
+
+ CairoleDebugOut((DEB_CHANNEL, "AppInvoke(0x%x) calling method 0x%x iid %I\n",
+ dwBreakCount,dwMethod, &iidBeingCalled));
+
+ if(AppInvoke_break == dwBreakCount)
+ {
+ DebugBreak();
+ }
+
+#endif
+ result = call->stub->Invoke( message, call->channel );
+ }
+ _except(AppInvokeExceptionFilter( GetExceptionInformation()))
+ {
+ result = RPC_E_SERVERFAULT;
+ call->server_fault = GetExceptionCode();
+
+#if DBG == 1
+ //
+ // OLE catches exceptions when the server generates them. This is so we can
+ // cleanup properly, and allow the client to continue.
+ //
+ if (call->server_fault == STATUS_ACCESS_VIOLATION ||
+ call->server_fault == 0xC0000194 /*STATUS_POSSIBLE_DEADLOCK*/ ||
+ call->server_fault == 0xC00000AA /*STATUS_INSTRUCTION_MISALIGNMENT*/ ||
+ call->server_fault == 0x80000002 /*STATUS_DATATYPE_MISALIGNMENT*/ )
+ {
+
+ WCHAR iidName[256];
+ iidName[0] = 0;
+ char achProgname[256];
+ achProgname[0] = 0;
+
+ GetModuleFileNameA(NULL,achProgname,sizeof(achProgname));
+
+ GetInterfaceName(iidBeingCalled,iidName);
+
+ CairoleDebugOut((DEB_FORCE,
+ "OLE has caught a fault 0x%08x on behalf of the server %s\n",
+ call->server_fault,
+ achProgname));
+
+ CairoleDebugOut((DEB_FORCE,
+ "The fault occured when OLE called the interface %I (%ws) method 0x%x\n",
+ &iidBeingCalled,iidName,dwMethod));
+
+ Win4Assert(!"The server application has faulted processing an inbound RPC request. Check the kernel debugger for useful output. OLE can continue but you probably want to stop and debug the application.");
+ }
+#endif
+
+ }
+
+ // For local calls, just free the in buffer.
+ if (call->pmessage->rpcFlags & RPCFLG_LOCAL_CALL)
+ PrivMemFree( orig_buffer );
+
+ // If an exception occurred before a new buffer was allocated,
+ // set the Buffer field to point to the original buffer.
+ if (message->Buffer == orig_stub_buffer)
+ {
+ // The buffer pointer in the message must be correct so RPC can free it.
+ if (call->pmessage->rpcFlags & RPCFLG_LOCAL_CALL)
+ message->Buffer = NULL;
+ else
+ message->Buffer = orig_buffer;
+ }
+
+ // An out buffer exists, get the pointer to the channel header.
+ else
+ {
+ Win4Assert( message->Buffer );
+ Win4Assert( (ULONG) orig_buffer > (ULONG) message->Buffer ||
+ (ULONG) message->Buffer > (ULONG) orig_buffer + orig_buffer_size );
+ fixup.SetOutboundData( message->Buffer );
+ message->Buffer = fixup.GetBase();
+ message->cbBuffer += sizeof(Outbound_Header) + fixup.GetDebugSize();
+
+ // If the call failed and the call is local, free the out buffer.
+ if (result != S_OK &&
+ call->pmessage->rpcFlags & RPCFLG_LOCAL_CALL)
+ {
+ PrivMemFree( message->Buffer );
+ message->Buffer = NULL;
+ }
+ }
+
+ // If successful, adjust the buffer.
+ if (result == S_OK)
+ {
+ ((Outbound_Header *) message->Buffer)->rejected = S_OK;
+
+ // If the packet contains space for debugger data, let the debugger
+ // fill it.
+ if (fixup.GetDebugSize() != 0)
+ {
+ void *iface;
+ if (!SUCCEEDED(call->stub->DebugServerQueryInterface( &iface )))
+ iface = NULL;
+ DebugORPCServerFillBuffer(
+ message,
+ ((Inbound_Header *)orig_buffer)->iid,
+ call->channel,
+ iface,
+ NULL,
+ fixup.GetOutboundDebug(),
+ fixup.GetDebugSize(),
+ DebuggerArg,
+ DoDebuggerHooks );
+ if (iface != NULL)
+ call->stub->DebugServerRelease( iface );
+ }
+ }
+ return result;
+}
+
+
+/***************************************************************************/
+// Static, but the compiler doesn't like to see that here.
+HRESULT CRpcChannelBuffer::ComInvoke( STHREADCALLINFO *thread )
+{
+ TRACECALL(TRACE_RPC, "CRpcChannelBuffer::ComInvoke");
+
+ com_call *call = (com_call *) thread;
+ RPCOLEMESSAGE *message = (RPCOLEMESSAGE *) call->pmessage;
+ Inbound_Header *header = (Inbound_Header *) message->Buffer;
+ INTERFACEINFO32 iface; // holds addref'd pUnkServer
+ void *saved_buffer;
+ RPC_STATUS status;
+ DISPATCHDATA mf_data;
+ HRESULT result;
+
+ CairoleDebugOut((DEB_CHANNEL, "CRpcChannelBuffer::ComInvoke callinfo:%x header:%x buffer:%x ChannelId:%x\n",
+ thread, header, message->Buffer, header->channel_id));
+
+ // NOTE: return only by going to or falling through exit !!!!
+
+ // Unmarshal the channel id and get a channel pointer.
+ call->stub = NULL; // NULL out for error case
+ iface.pUnk = NULL; // NULL out for error case
+ call->channel = ChannelList.Lookup( header->channel_id, FALSE, TRUE );
+ if (call->channel == NULL || call->channel->IsConnected() != S_OK)
+ {
+ // channel gone or not connected
+ result = RPC_E_DISCONNECTED;
+ goto exit;
+ }
+
+ // Set the caller TID. This is needed by some interop code in order
+ // to do focus management via tying queues together. We first save the
+ // current one so we can restore later to deal with nested calls
+ // correctly.
+
+ DWORD TIDCallerSaved;
+ BOOL fLocalSaved;
+ TLSSetCallerTID(call->channel->GetClientTID(), call->channel->local,
+ &TIDCallerSaved, &fLocalSaved);
+
+ // Get the stub pointer from the channel. This holds the real server alive
+ // (by not allowing the RH to release its pointers) and is similar to what
+ // we did in 16bit OLE to stablize the app object during incoming calls.
+ // This call must be balanced with a call to IRH::FinishCall.
+ MadeCalls = TRUE;
+ call->stub = call->channel->GetRH()->LookupStub(
+ header->iid,
+ &iface.pUnk,
+ &result);
+
+ // the stub is held alive by the RH which is held alive by the channel
+ // which is held alive because we addref'd it (in Lookup above).
+
+ if (call->stub == NULL)
+ {
+ Win4Assert(result != S_OK);
+ Win4Assert(iface.pUnk == NULL);
+ goto exit;
+ }
+
+ // In multithreaded mode, call the app directly
+
+ if (FreeThreading)
+ result = AppInvoke( call );
+
+ // In singlethreaded mode, go through the call controller.
+ else
+
+ {
+ iface.iid = header->iid;
+ iface.wMethod = header->proc_num;
+ iface.callcat = (CALLCATEGORY) header->callcat;
+ mf_data.pData = call;
+
+ // change the dispatch fn to AppInvoke and save the old one.
+ DISPATCH_FN fnPrev = call->ResetDispatchFn(AppInvoke);
+
+ result = call->channel->GetControl()
+ ->GetCallControl()->HandleDispatchCall(
+ call->channel->GetClientTID(),
+ call->lid(),
+ &iface,
+ &mf_data );
+
+ // If the call was rejected, send the request back.
+ if (result == RPC_E_SERVERCALL_REJECTED ||
+ result == RPC_E_SERVERCALL_RETRYLATER)
+ {
+ // restore the original dispatch fn because we might call back in
+ // the reject or retry later case, and the STHREADCALLINFO is shared
+ // when SwitchCOMThread is used.
+ call->ResetDispatchFn(fnPrev);
+
+ // Note - Rather then copy the entire message twice, the inbound
+ // header and all the data is sent back. ThreadSendReceive and
+ // CRpcChannelBuffer::SendReceive detect this condition.
+
+ // Reuse the same buffer for local calls, copy it for remote calls.
+ if ((call->pmessage->rpcFlags & RPCFLG_LOCAL_CALL) == 0)
+ {
+ // Note that runtime does not free the original buffer until this
+ // function returns.
+ saved_buffer = message->Buffer;
+
+ // Note - We don't need to set reserved1 on the server side (unlike
+ // we do on the client side where we need to restore it before we
+ // reuse the buffer).
+ status = I_RpcGetBuffer( (RPC_MESSAGE *) message );
+ if (status != RPC_S_OK)
+ {
+ result = MAKE_WIN32( status );
+ goto exit;
+ }
+ memcpy( message->Buffer, saved_buffer, message->cbBuffer );
+ ((Outbound_Header *) message->Buffer)->rejected = result;
+ }
+ }
+ }
+
+exit:
+
+ // restore the caller TID. The latter two params are just
+ // dummy placeholders.
+ TLSSetCallerTID(TIDCallerSaved, fLocalSaved,
+ &TIDCallerSaved, &fLocalSaved);
+
+ if (call->channel != NULL)
+ {
+ call->channel->GetRH()->FinishCall(call->stub, iface.pUnk);
+ call->channel->Release();
+ }
+ return result;
+}
+
+/***************************************************************************/
+CRpcChannelBuffer::CRpcChannelBuffer( IRemoteHdlr *rh,
+ CRpcService *service,
+ DWORD dwClientTID,
+ CChannelControl *chc,
+ EChannelState eState )
+{
+ // Note that server_apt and controller are set correctly on the client
+ // side by UnmarshalInterface.
+ ref_count = 1;
+ _pRH = rh;
+ if (eState == server_cs)
+ {
+ // on server, we hold the rh alive so stub stay alive; released in dtor
+ rh->AddRef();
+ }
+ state = eState;
+ _pService = service;
+ _ChannelID = BAD_CHANNEL_ID;
+ _ulMarshalCnt = 0;
+ _fStrongConn = TRUE;
+ _dwClientTID = dwClientTID;
+ my_thread = GetCurrentThreadId();
+ server_apt = my_thread;
+ controller = chc;
+ connect_sync = NULL;
+
+ // The local flag is not valid on the client side till UnmarshalInterface
+ // is called. Chicago does not use local calls, but it still uses the
+ // local flag in the message structure for async calls.
+ local = service == LocalService();
+ if (controller != NULL)
+ controller->AddRef();
+ if (service != NULL)
+ service->AddRef();
+
+}
+
+/***************************************************************************/
+CRpcChannelBuffer::~CRpcChannelBuffer()
+{
+ DisconnectObject(0); // this call releases the controller and service objects
+
+ if (state == server_cs)
+ {
+ // on server we hold the rh alive through here because it simlifies error
+ // handling by making the server channel case look like other cases
+ // (which always have a valid _pRH).
+ _pRH->Release();
+ }
+}
+
+/***************************************************************************/
+STDMETHODIMP CRpcChannelBuffer::FreeBuffer( RPCOLEMESSAGE *pMessage )
+{
+ TRACECALL(TRACE_RPC, "CRpcChannelBuffer::FreeBuffer");
+ CHeaderBrain fixup;
+
+ AssertValid(FALSE, TRUE);
+ Win4Assert(state != disconnected_cs);
+
+ if (pMessage->Buffer == NULL)
+ return S_OK;
+
+ // If SendReceive has not been called, remove the inbound header.
+ if (pMessage->reserved2[1] != NULL)
+ {
+ fixup.SetInboundData( pMessage->Buffer );
+ pMessage->Buffer = fixup.GetBase();
+ DeallocateBuffer(pMessage);
+ }
+
+ // Remove the outbound header.
+ else
+ {
+ fixup.SetOutboundData( pMessage->Buffer );
+ pMessage->Buffer = fixup.GetBase();
+ pMessage->reserved2[1] = &the_client_if;
+
+ DeallocateBuffer(pMessage);
+
+ // Release the AddRef we did earlier. Note that we cant do this until
+ // after DeallocateBuffer since it may release a binding handle that
+ // I_RpcFreeBuffer needs.
+
+ _pRH->UnLockClient();
+ }
+
+ pMessage->Buffer = NULL;
+
+ return S_OK;
+}
+
+/***************************************************************************/
+/*
+ This routine allocates buffers for proxies and stubs. It is called on
+both the client and server side. It is called for both process local and
+process remote calls. By contract with RPC, if it fails it should not change
+the buffer pointer in the message.
+*/
+STDMETHODIMP CRpcChannelBuffer::GetBuffer( RPCOLEMESSAGE *pMessage,
+ REFIID riid )
+{
+ TRACECALL(TRACE_RPC, "CRpcChannelBuffer::GetBuffer");
+
+ RPC_STATUS status;
+ CHeaderBrain fixup;
+ ULONG method;
+ CALLCATEGORY callCat = CALLCAT_SYNCHRONOUS;
+ void *buffer;
+
+ Win4Assert(state != disconnected_cs);
+
+ // Check the thread.
+ if (!FreeThreading && GetCurrentThreadId() != my_thread)
+ return RPC_E_WRONG_THREAD;
+
+ AssertValid(FALSE, TRUE);
+
+ // On the client side, compute the call category and add space for the
+ // Inbound_Header.
+ if (state == client_cs)
+ {
+ // Fetch the call category from the RPC message structure
+
+ if (pMessage->rpcFlags & RPCFLG_ASYNCHRONOUS)
+ {
+ // only allow async for these two interfaces for now
+ if (riid != IID_IAdviseSink && riid != IID_IAdviseSink2)
+ return E_UNEXPECTED;
+
+ callCat = CALLCAT_ASYNC;
+ }
+ else if (pMessage->rpcFlags & RPCFLG_INPUT_SYNCHRONOUS)
+ {
+ callCat = CALLCAT_INPUTSYNC;
+ }
+
+ // Note - RPC requires that the 16th bit of the proc num be set because
+ // we use the rpcFlags field of the RPC_MESSAGE struct.
+ method = pMessage->iMethod & ~RPC_FLAGS_VALID_BIT;
+ pMessage->iMethod = RPC_FLAGS_VALID_BIT;
+
+ // if service object of destination is in same process, definitely local
+ // calls; async calls are also forced to be local.
+ if (local)
+ pMessage->rpcFlags |= RPCFLG_LOCAL_CALL;
+
+ // Find out if we need debug data.
+ if (!IsWOWThread() && DoDebuggerHooks)
+ fixup.SetDebugSize(
+ DebugORPCClientGetBufferSize( pMessage, riid, NULL, NULL,
+ DebuggerArg, DoDebuggerHooks ) );
+
+ // Adjust the rest of the message.
+ if ((pMessage->rpcFlags & RPCFLG_LOCAL_CALL) == 0)
+ pMessage->reserved1 = _pService->GetRpcHdl();
+ /*
+ else
+ Why allocate the RPC resources for the local case?
+ */
+ pMessage->cbBuffer += sizeof(Inbound_Header) +
+ fixup.GetDebugSize();
+ pMessage->reserved2[1] = &the_client_if;
+ }
+
+ // On the server side add space for the Outbound_Header.
+ else
+ {
+ // Find out if we need debug data.
+ fixup.SetInboundData( pMessage->Buffer );
+ if (!IsWOWThread() && DoDebuggerHooks)
+ {
+ HRESULT result;
+ void *iface;
+ Inbound_Header *header;
+
+ header = (Inbound_Header *) fixup.GetBase();
+
+ // NOTE: don't get pUnkServer because we don't need it and we don't
+ // want any server code to execute yet
+ IRpcStubBuffer *stub = _pRH->LookupStub(
+ header->iid,
+ NULL,
+ &result);
+ if (SUCCEEDED(result))
+ result = stub->DebugServerQueryInterface( &iface );
+ if (!SUCCEEDED(result))
+ iface = NULL;
+ fixup.SetDebugSize(
+ DebugORPCServerGetBufferSize( pMessage, header->iid, this, iface,
+ NULL, DebuggerArg, DoDebuggerHooks ) );
+ if (iface != NULL)
+ stub->DebugServerRelease( iface );
+ }
+ else
+ fixup.SetDebugSize( 0 );
+
+ // Adjust the buffer size.
+ pMessage->cbBuffer += sizeof(Outbound_Header) + fixup.GetDebugSize();
+ }
+
+ // Get a buffer.
+ if (pMessage->rpcFlags & RPCFLG_LOCAL_CALL)
+ {
+ // NDR_DREP_ASCII | NDR_DREP_LITTLE_ENDIAN | NDR_DREP_IEEE
+ pMessage->dataRepresentation = 0x00 | 0x10 | 0x0000;
+ buffer = PrivMemAlloc8( pMessage->cbBuffer );
+ if (buffer == NULL)
+ status = RPC_S_OUT_OF_MEMORY;
+ else
+ {
+ status = RPC_S_OK;
+ pMessage->Buffer = buffer;
+ }
+ }
+ else
+ {
+ TRACECALL(TRACE_RPC, "I_RpcGetBuffer");
+ status = I_RpcGetBuffer( (RPC_MESSAGE *) pMessage );
+
+ }
+
+ if (status != RPC_S_OK)
+ {
+ pMessage->cbBuffer = 0;
+ TLSSetFault( MAKE_WIN32( status ) );
+ return MAKE_WIN32( status );
+ }
+
+ // On the client side, stick the channel id in the buffer and adjust
+ // the buffer pointer past the Inbound_Header.
+ fixup.SetBase( pMessage->Buffer );
+ if (state == client_cs)
+ {
+ ((Inbound_Header *) pMessage->Buffer)->channel_id = _ChannelID;
+ // NOTE: logical thread is set the first time the message is sent
+ ((Inbound_Header *) pMessage->Buffer)->iid = riid;
+ ((Inbound_Header *) pMessage->Buffer)->proc_num = method;
+ ((Inbound_Header *) pMessage->Buffer)->callcat = callCat;
+
+ // BUGBUG: for some reason, the (WORD) cast did not strip high word in all
+ // cases.
+
+ // Note - RPC requires that the 17th bit of the proc num be set because
+ // we use the rpcFlags field of the RPC_MESSAGE struct.
+ pMessage->Buffer = (char *) fixup.GetInboundData();
+ pMessage->cbBuffer -= sizeof(Inbound_Header) - fixup.GetDebugSize();
+ }
+
+ // On the server side, adjust the pointer past the Outbound_Header.
+ else
+ {
+ pMessage->Buffer = fixup.GetOutboundData();
+ pMessage->cbBuffer -= sizeof(Outbound_Header) - fixup.GetDebugSize();
+ }
+ return S_OK;
+}
+
+/***************************************************************************/
+STDMETHODIMP CRpcChannelBuffer::GetDestCtx( DWORD FAR* lpdwDestCtx,
+ LPVOID FAR* lplpvDestCtx )
+{
+ TRACECALL(TRACE_RPC, "CRpcChannelBuffer::GetDestCtx");
+
+ AssertValid(FALSE, FALSE);
+
+ Win4Assert(state != disconnected_cs);
+
+ if (_pService)
+ {
+ _pService->GetDestCtx(lpdwDestCtx, lplpvDestCtx);
+ }
+ else
+ {
+#ifdef _CAIRO_
+ // CODEWORK: must determine proper destination context
+ *lpdwDestCtx = MSHCTX_NOSHAREDMEM;
+#else
+ *lpdwDestCtx = MSHCTX_LOCAL;
+#endif
+
+ if (lplpvDestCtx != NULL)
+ *lplpvDestCtx = NULL;
+ }
+ return S_OK;
+}
+
+/***************************************************************************/
+STDMETHODIMP CRpcChannelBuffer::IsConnected( THIS )
+{
+ // must be on right thread because because of a possible disconnect
+ // (this routine is primarily called on the client side anyway).
+ AssertValid(FALSE, TRUE);
+ Win4Assert(state != disconnected_cs); // don't allow here
+
+ if (_pService != NULL && _pService->IsConnected())
+ {
+ return S_OK;
+ }
+ else if (state == client_cs)
+ {
+ // known not connected, ensure cleaned up by disconnecting
+ // BUGBUG - Why is DisconnectObject called here?
+ _pRH->Disconnect();
+ return S_FALSE;
+ }
+ // BUGBUG - If you were to call DisconnectObject on a server channel,
+ // you would have to remove it from the channel list.
+ else
+ return S_FALSE;
+}
+
+/***************************************************************************/
+STDMETHODIMP CRpcChannelBuffer::QueryInterface( THIS_ REFIID riid, LPVOID FAR* ppvObj)
+{
+ AssertValid(FALSE, FALSE);
+
+ // IMarshal is queried more frequently than any other interface, so
+ // check for that first.
+
+ if (IsEqualIID(riid, IID_IMarshal))
+ {
+ *ppvObj = (IMarshal *) this;
+ }
+ else if (IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IRpcChannelBuffer))
+ {
+ *ppvObj = (IRpcChannelBuffer *) this;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+ return S_OK;
+}
+
+/***************************************************************************/
+STDMETHODIMP_(ULONG) CRpcChannelBuffer::Release( THIS )
+{
+ // can't call AssertValid(FALSE) since it is used in asserts
+ ULONG retval = ref_count - 1;
+
+ if (InterlockedDecrement( (long*) &ref_count ) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ else
+ {
+ return retval;
+ }
+}
+
+
+/***************************************************************************/
+// BUGBUG: needs to be removed for the real product
+//
+
+//IOleWindow
+#define GetWindow 3
+
+//IOleInplaceActiveobject
+#define iTranslateAccelerator 5
+#define OnFrameWindowActivate 6
+#define OnDocWindowActivate 7
+#define ResizeBorder 8
+
+// IOleInplaceUIWindow
+#define GetBorder 5
+#define RequestBorderSpace 6
+#define SetBorderSpace 7
+
+// IOleInplaceFrame
+#define SetMenu 10
+#define SetStatusText 12
+
+// IOleInplacObject
+#define SetObjectsRect 7
+
+CALLCATEGORY CRpcChannelBuffer::GetCallCategory(REFIID refiid, WORD wMethod)
+{
+ // instead of doing 6 GUID compares, we take advantage of the
+ // similarity of the GUID values for the interfaces we are interested
+ // in, and switch on the part that is unique.
+ //
+ // IID_IAdviseSink, 0000010f-0000-0000-C000-000000000046
+ // IID_IOleInplaceObject, 00000113-0000-0000-C000-000000000046
+ // IID_IOleWindow, 00000114-0000-0000-C000-000000000046
+ // IID_IOleInPlaceUIWindow, 00000115-0000-0000-C000-000000000046
+ // IID_IOleInPlaceFrame, 00000116-0000-0000-C000-000000000046
+ // IID_IOleInPlaceActiveObject 00000117-0000-0000-C000-000000000046
+
+ DWORD *ptr = (DWORD *) &refiid;
+
+
+ Win4Assert(wMethod > 2 && "Incorrect remoting of IUnknown");
+
+ // the last 3 dwords are the same for all the interfaces
+ if (*(ptr+1) == 0x00000000 &&
+ *(ptr+2) == 0x000000C0 &&
+ *(ptr+3) == 0x46000000)
+ {
+ switch (*ptr)
+ {
+ case 0x0000010f: // IID_IAdviseSink
+
+ Win4Assert(IsEqualIID(refiid, IID_IAdviseSink));
+
+ Win4Assert(wMethod < 8);
+ // all async calls
+ return CALLCAT_ASYNC;
+
+ case 0x00000113: // IID_IOleInPlaceObject
+
+ Win4Assert(IsEqualIID(refiid, IID_IOleInPlaceObject));
+ Win4Assert(wMethod < 9);
+
+ if (wMethod == SetObjectsRect ||
+ wMethod == GetWindow)
+ {
+ return CALLCAT_INPUTSYNC;
+ }
+ break;
+
+ case 0x00000114: // IID_IOleWindow
+
+ Win4Assert(IsEqualIID(refiid,IID_IOleWindow));
+
+ Win4Assert(wMethod < 5);
+
+ if (wMethod == GetWindow)
+ {
+ return CALLCAT_INPUTSYNC;
+ }
+ break;
+
+
+ case 0x00000115: // IID_IOleInPlaceUIWindow
+
+ Win4Assert(IsEqualIID(refiid, IID_IOleInPlaceUIWindow));
+
+ Win4Assert(wMethod < 9);
+
+ if (wMethod == GetBorder ||
+ wMethod == RequestBorderSpace ||
+ wMethod == SetBorderSpace ||
+ wMethod == GetWindow)
+ {
+ return CALLCAT_INPUTSYNC;
+ }
+ break;
+
+ case 0x00000116: // IID_IOleInPlaceFrame
+
+ Win4Assert(IsEqualIID(refiid, IID_IOleInPlaceFrame));
+
+ Win4Assert(wMethod < 15);
+
+ // IOleInPlaceFrame inherits from IOleInplaceUIWindow
+ // which in turn inherits from IOleWindow
+ if (wMethod == SetMenu ||
+ wMethod == SetStatusText ||
+ wMethod == GetBorder ||
+ wMethod == RequestBorderSpace ||
+ wMethod == SetBorderSpace ||
+ wMethod == GetWindow)
+ {
+ return CALLCAT_INPUTSYNC;
+ }
+ break;
+
+ case 0x00000117: // IID_IOleInplaceActiveObject
+
+ Win4Assert(IsEqualIID(refiid, IID_IOleInPlaceActiveObject));
+
+ Win4Assert(wMethod < 10);
+
+ if (wMethod == OnFrameWindowActivate ||
+ wMethod == iTranslateAccelerator ||
+ wMethod == OnDocWindowActivate ||
+ wMethod == ResizeBorder ||
+ wMethod == GetWindow)
+ {
+ return CALLCAT_INPUTSYNC;
+ }
+ break;
+
+ case 0x00000119: // IID_IOleInPlaceSite
+
+ Win4Assert(IsEqualIID(refiid, IID_IOleInPlaceSite));
+
+ Win4Assert(wMethod < 15);
+
+ // IID_IOleInplaceSite inherits from IOleWindow so it has
+ // one input sync call.
+ if (wMethod == GetWindow)
+ {
+ return CALLCAT_INPUTSYNC;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return CALLCAT_SYNCHRONOUS;
+}
+
+/***************************************************************************/
+STDMETHODIMP CRpcChannelBuffer::SendReceive( THIS_ RPCOLEMESSAGE *pMessage,
+ ULONG *status )
+{
+ TRACECALL(TRACE_RPC, "CRpcChannelBuffer::SendReceive");
+
+ AssertValid(FALSE, TRUE);
+ Win4Assert( state == client_cs );
+
+ HRESULT result;
+ CHeaderBrain fixup;
+ BOOL sent_debug_data = FALSE;
+ working_call *call;
+ IID iid;
+ Inbound_Header *header;
+
+ // Allocate a call record.
+ call = CallCache.Get();
+ if (call == NULL)
+ {
+ FreeBuffer(pMessage);
+
+ *status = (ULONG) RPC_E_OUT_OF_RESOURCES;
+ return RPC_E_FAULT;
+ }
+
+ // we must ensure that we dont go away during this call. we will Release
+ // ourselves in the FreeBuffer call, or in the error handling at the
+ // end of this function.
+ _pRH->LockClient();
+
+ // Adjust the buffer pointer before the Inbound_Header and send it.
+ fixup.SetInboundData( pMessage->Buffer );
+ pMessage->Buffer = fixup.GetBase();
+ pMessage->cbBuffer += sizeof(Inbound_Header) + fixup.GetDebugSize();
+ header = (Inbound_Header *) pMessage->Buffer;
+ iid = header->iid;
+ // DWORD *tmp = (DWORD *) &iid;
+ // CairoleDebugOut((DEB_CHANNEL, "SendReceive calling method 0x%x iid %08x%08x%08x%08x\n",
+ // header->proc_num, tmp[0], tmp[1], tmp[2], tmp[3] ));
+
+ // If the debugger wants to put in data, call the debugger back.
+ if (fixup.GetDebugSize() != 0)
+ {
+ sent_debug_data = TRUE;
+ DebugORPCClientFillBuffer(
+ pMessage,
+ iid,
+ NULL,
+ NULL,
+ fixup.GetInboundDebug(),
+ fixup.GetDebugSize(),
+ DebuggerArg,
+ DoDebuggerHooks );
+ }
+
+ // Fill in the call information. Common case is ThreadSendReceive.
+ call->working_call::working_call(ThreadSendReceive,
+ (CALLCATEGORY)header->callcat,
+ server_apt);
+
+ call->SetCalledIID(header->iid);
+ call->message = *pMessage;
+ call->pmessage = &call->message;
+ call->service = _pService;
+ call->first_try = TRUE;
+ call->channel_id = _ChannelID;
+ _pService->AddRef();
+
+ // In the local case, switch directly to the server thread. Otherwise
+ // get to a RPC thread and call I_RpcSendReceive
+ if (pMessage->rpcFlags & RPCFLG_LOCAL_CALL)
+ {
+ Win4Assert(controller != NULL);
+ call->pmessage->reserved2[3] = NULL;
+ call->ResetDispatchFn(ComInvoke);
+
+ result = controller->SwitchCOMThread( (STHREADCALLINFO **) &call );
+ }
+ else
+ {
+ Win4Assert(controller == NULL);
+ result = CChannelControl::GetOffCOMThread( (STHREADCALLINFO **) &call );
+ }
+
+ // Call succeeded.
+ if (result == S_OK)
+ {
+ // The first assignment is a sneaky flag to let FreeBuffer know that
+ // the message now contains an out buffer rather then an in buffer.
+ pMessage->reserved2[1] = NULL;
+ pMessage->reserved1 = call->message.reserved1;
+ pMessage->Buffer = call->message.Buffer;
+ pMessage->cbBuffer = call->message.cbBuffer;
+
+#ifdef _CHICAGO_
+ // No buffer was returned for async calls.
+ if (pMessage->rpcFlags & RPCFLG_ASYNCHRONOUS)
+ {
+ // since no buffer was returned, FreeBuffer wont be called, and
+ // hence we need to unlock the client here.
+ _pRH->UnLockClient();
+ }
+ else
+#endif
+ {
+ // If the debugger is active or if the packet contains debug data,
+ // call the debugger.
+ fixup.SetOutboundBase( pMessage->Buffer );
+ if (!IsWOWThread() && (fixup.GetDebugSize() != 0 || DoDebuggerHooks))
+ {
+ DebugORPCClientNotify(
+ pMessage,
+ iid,
+ NULL,
+ NULL,
+ S_OK,
+ fixup.GetOutboundDebug(),
+ fixup.GetDebugSize(),
+ DebuggerArg,
+ DoDebuggerHooks );
+ }
+
+ // Adjust the buffer.
+ pMessage->Buffer = fixup.GetOutboundData();
+ pMessage->cbBuffer -= sizeof(Outbound_Header) - fixup.GetDebugSize();
+ }
+
+ call->pmessage = NULL; // don't free the message in the dtor
+
+ *status = S_OK;
+ }
+ else
+ {
+ // CODEWORK: may need to free the marshaled data here (say in the REJECTED
+ // case) if the server never unmarshaled it.
+
+ // If the result is server fault, get the exception code from the com_call.
+ if (result == RPC_E_SERVERFAULT)
+ {
+ *status = call->server_fault;
+
+ // Buffer already freed or will be freed by RPC;prevent dtor from doing so
+ call->pmessage = NULL;
+ }
+ // Everything else is a comm fault.
+ else
+ {
+ *status = result;
+
+ // If the call was rejected or the server requested a retry, free the
+ // return buffer in dtor. Note that CallRunModalLoop and
+ // HandleDispatchCall return different values to indicate reject.
+ if (result == RPC_E_CALL_REJECTED || result == RPC_E_RETRY)
+ {
+ // leave call->pmessage alone to get buffer freed
+ }
+
+ else if (result == RPC_E_CALL_CANCELED)
+ {
+ // if canceled, buffer (and whole call packet) already freed
+ }
+ else
+ {
+ // Only return server fault, comm fault, retried, rejected, or canceled.
+ result = RPC_E_FAULT;
+ call->pmessage = NULL;
+ }
+ }
+
+ if (!IsWOWThread() &&
+ (fixup.GetDebugSize() != 0 || DoDebuggerHooks || sent_debug_data))
+ {
+ DebugORPCClientNotify(
+ pMessage,
+ iid,
+ NULL,
+ NULL,
+ result,
+ NULL,
+ 0,
+ DebuggerArg,
+ DoDebuggerHooks );
+ }
+
+ TLSSetFault( *status );
+ _pRH->UnLockClient();
+
+ // since result is almost always mapped to RPC_E_FAULT, display the
+ // real error here to assist debugging.
+
+ CairoleDebugOut((DEB_CHANNEL, "ORPC call failed. status = %x\n", *status));
+ }
+
+ // If the call was not canceled, free the working_call structure.
+ if (*status != RPC_E_CALL_CANCELED)
+ {
+ // rather than destroying the packet only to allocate a new one later,
+ // we call the destructor and save the packet. The destructor will
+ // free the message buffer if the pointer is not NULL'd above.
+
+ call->working_call::~working_call();
+
+ CallCache.Free( call );
+ }
+ return result;
+}
+
+
+#if DBG == 1
+//+-------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::AssertValid
+//
+// Synopsis: Validates that the state of the object is consistent.
+//
+// History: 25-Jan-94 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+void CRpcChannelBuffer::AssertValid(BOOL fKnownDisconnected,
+ BOOL fMustBeOnCOMThread)
+{
+ if (fKnownDisconnected)
+ {
+ // for better asserts when shutting down the RH
+ Win4Assert(state == client_cs || state == disconnected_cs || state == server_cs);
+ Win4Assert(_pService == NULL);
+ Win4Assert(_ChannelID == BAD_CHANNEL_ID);
+ }
+ if (fMustBeOnCOMThread && !FreeThreading)
+ Win4Assert(FreeThreading || my_thread == GetCurrentThreadId());
+
+ if (state == client_cs)
+ {
+ if (_pService == NULL)
+ {
+ // client, disconnected
+ if (ref_count >=1)
+ {
+ Win4Assert(_pRH->GetChannel(FALSE) == this);
+ }
+ Win4Assert(_ChannelID == BAD_CHANNEL_ID);
+ Win4Assert(_ulMarshalCnt == 0);
+ Win4Assert(_fStrongConn);
+ Win4Assert(connect_sync == 0);
+ Win4Assert(controller == NULL);
+ }
+ else
+ {
+ // client, connected
+
+ // _pService is not strictly an interface, but close enough
+ Win4Assert(ref_count >= 1);
+
+ _pService->AssertValid();
+ Win4Assert(_pRH->GetChannel(FALSE) == this);
+ Win4Assert(_ChannelID != BAD_CHANNEL_ID);
+ // can't validate _ChannelID since the value is only valid
+ // in the server process.
+ Win4Assert(_ulMarshalCnt > 0);
+ Win4Assert(_fStrongConn);
+ Win4Assert(connect_sync == 0);
+
+ if (local)
+ {
+ Win4Assert(controller != NULL);
+ }
+ else
+ {
+ Win4Assert(controller == NULL);
+ }
+ }
+ }
+ else if (state == connecting_cs)
+ {
+ // CODEWORK: fill in
+ Win4Assert(_pRH->GetChannel(FALSE) == this);
+ }
+ else if (state == disconnected_cs)
+ {
+ Win4Assert(_pService == NULL);
+ Win4Assert(_pRH->GetChannel(FALSE) == this);
+ Win4Assert(_ChannelID == BAD_CHANNEL_ID);
+ Win4Assert(_ulMarshalCnt == 0);
+ Win4Assert(_fStrongConn);
+ Win4Assert(connect_sync == 0);
+ Win4Assert(controller == NULL);
+ }
+ else if (state == server_cs)
+ {
+ // ref count can be 0 in various stages of connection and disconnection
+ Win4Assert(ref_count < 0x7fff && "Channel ref count unreasonably high");
+
+ if (_pService == NULL)
+ {
+ // server side, disconnected (connection in the midst of closing)
+ // Marshal count on other threads can change during this call.
+ if (fMustBeOnCOMThread)
+ {
+ Win4Assert(_ulMarshalCnt == 0);
+ Win4Assert(_ChannelID == BAD_CHANNEL_ID);
+ }
+
+ // CODEWORK: could assert that the channel is not in the channel list
+ }
+ else
+ {
+ // server side, connected
+ // Marshal count on other threads can change during this call.
+ if (fMustBeOnCOMThread)
+ {
+ Win4Assert(_ulMarshalCnt > 0);
+
+ _pService->AssertValid();
+ Win4Assert(controller != NULL);
+ }
+ }
+
+ // the _pRH pointer can not be NULL
+ Win4Assert(IsValidInterface(_pRH));
+ Win4Assert(_pRH->GetChannel(FALSE) != this);
+
+ Win4Assert(_fStrongConn == TRUE || _fStrongConn == FALSE);
+
+ Win4Assert(connect_sync == 0);
+ }
+ else
+ {
+ Win4Assert(!"Channel Object with invalid state");
+ }
+}
+#endif // DBG == 1
+
+
+/***************************************************************************/
+STDAPI_(ULONG) DebugCoGetRpcFault()
+{
+ return TLSGetFault();
+}
+
+/***************************************************************************/
+STDAPI_(void) DebugCoSetRpcFault( ULONG fault )
+{
+ TLSSetFault( fault );
+}
+
+/***************************************************************************/
+extern "C"
+BOOL _stdcall DllDebugObjectRPCHook( BOOL trace, LPORPC_INIT_ARGS pass_through )
+{
+ if (!IsWOWThread())
+ {
+ DoDebuggerHooks = trace;
+ DebuggerArg = pass_through;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/***************************************************************************/
+/* This routine returns both comm status and server faults to the runtime
+ by raising exceptions. Some time in the future, the macro
+ RETURN_COMM_STATUS can be changed so this function returns comm status
+ values as its result. If FreeThreading is true, ComInvoke will throw
+ exceptions to indicate server faults. These will not be caught and will
+ propogate directly to the runtime. If FreeThreading is false, this routine
+ will communicate to the main thread using a thread_switch_data record which
+ will contain both the comm status and server fault indications.
+ NOTE:
+ This function switches to the 32 bit stack under WIN95.
+ An exception has to be caught while switched to the 32 bit stack.
+ The exceptions has to be pass as a value and rethrown again on the
+ 16 bit stack (see SSInvoke in stkswtch.cxx)
+*/
+
+#ifdef _CHICAGO_
+DWORD
+#else
+void
+#endif
+SSAPI(ThreadInvoke)(RPC_MESSAGE *message )
+{
+ TRACECALL(TRACE_RPC, "ThreadInvoke");
+
+ BOOL success;
+ Inbound_Header *header;
+ HRESULT result;
+
+ // RPC currently does not always set the flags on the server side.
+ message->RpcFlags = 0;
+
+ // If thread aware, just call ComInvoke. ComInvoke will not catch
+ // exceptions so they will fall straight through to the runtime.
+ header = (Inbound_Header *) message->Buffer;
+
+ // NOTE: we throw exceptions and routines we call can throw them so beware!
+ com_call call(
+ CRpcChannelBuffer::ComInvoke,
+ (CALLCATEGORY) header->callcat,
+ header->logical_thread);
+
+ call.pmessage = (RPCOLEMESSAGE *) message;
+ call.service = NULL;
+
+ if (FreeThreading)
+ {
+ success = TLSSetLogicalThread( ((Inbound_Header *) message->Buffer)->logical_thread );
+ if (!success)
+ result = RPC_E_SYS_CALL_FAILED;
+ else
+ result = CRpcChannelBuffer::ComInvoke( &call );
+
+ // CODEWORK: the above routine can throw exceptions; we probably want to
+ // catch them here, cleanup and re-throw them.
+ }
+
+ // Pass the message to the app thread.
+ else
+ {
+ CChannelControl *controller;
+
+ controller = ChannelList.LookupControl( header->channel_id );
+ if (controller != NULL)
+ {
+ result = controller->GetToCOMThread( &call );
+ controller->Release();
+ }
+ else
+ {
+ result = RPC_E_SERVER_DIED_DNE;
+ }
+ }
+
+ call.pmessage = NULL; // that was not our message; must not free
+
+ // NOTE: these exceptions will avoid the com_call destructor, so we call it
+
+ // For comm and server faults, generate an exception. Otherwise the buffer
+ // is set up correctly. Sometimes GetToCOMThread will rethrow
+ // server faults.
+ if (result == RPC_E_SERVERFAULT)
+ {
+#if !defined(_CHICAGO_)
+ call.com_call::~com_call();
+#endif
+ RETURN_COMM_STATUS( (ULONG)RPC_E_SERVERFAULT );
+ }
+ else if (result != RPC_E_SERVERCALL_REJECTED &&
+ result != RPC_E_SERVERCALL_RETRYLATER &&
+ result != S_OK)
+ {
+#if !defined(_CHICAGO_)
+ call.com_call::~com_call();
+#endif
+ RETURN_COMM_STATUS( result );
+ }
+ // else dtor called normally
+#ifdef _CHICAGO_
+ return 0;
+#endif //_CHICAGO_
+
+
+}
+
+
+/***************************************************************************/
+HRESULT ThreadSendReceive( STHREADCALLINFO *thread )
+{
+ TRACECALL(TRACE_RPC, "ThreadSendReceive");
+
+ working_call *call = (working_call *) thread;
+ HRESULT result;
+ RPCOLEMESSAGE *message = call->pmessage;
+ RPC_MESSAGE free_me;
+ RPC_STATUS status;
+
+ // The first time this is transmitted, fill in the logical thread id.
+ if (call->first_try)
+ {
+ // Save the logical thread. Also, set the first_try field so the next
+ // time this routine is called with this call data it will retransmit
+ // the data.
+ call->first_try = FALSE;
+ ((Inbound_Header *) message->Buffer)->logical_thread = call->lid();
+ }
+
+ // Get a new buffer. Copy the reply. Free the reply.
+ else
+ {
+ // Note: this reply was generated in CRpcChannelBuffer::ComInvoke.
+ // The Inbound header is still present, except for the first field as noted.
+
+ free_me = *((RPC_MESSAGE *) message);
+ message->reserved1 = call->service->GetRpcHdl();
+ status = I_RpcGetBuffer( (RPC_MESSAGE *) message );
+ if (status != RPC_S_OK)
+ {
+ I_RpcFreeBuffer( (RPC_MESSAGE *) &free_me );
+ return MAKE_WIN32( status );
+ }
+ memcpy( message->Buffer, free_me.Buffer, message->cbBuffer );
+
+ // Note: On reject/retry the first field is overwritten with the return
+ // code (see CRpcChannelBuffer::ComInvoke). Here we restore it.
+ ((Inbound_Header *) message->Buffer)->channel_id = call->channel_id;
+ I_RpcFreeBuffer( (RPC_MESSAGE *) &free_me );
+ }
+
+ // Call the runtime. In the future, detect server faults and
+ // change the value of result to RPC_E_SERVERFAULT.
+ {
+#ifdef _CHICAGO_
+ TRACECALL(TRACE_RPC, "I_RpcAsyncSendReceive");
+ result = I_RpcAsyncSendReceive( (RPC_MESSAGE *) message, thread );
+#else
+ TRACECALL(TRACE_RPC, "I_RpcSendReceive");
+ result = I_RpcSendReceive( (RPC_MESSAGE *) message );
+#endif
+ }
+
+ // If the result is small, it is probably a Win32 code.
+ if (result != 0)
+ {
+ if ((ULONG) result > 0xfffffff7 || (ULONG) result < 0x2000)
+ result = MAKE_WIN32( result );
+ if (result != MAKE_WIN32( RPC_S_CALL_CANCELLED ))
+ message->Buffer = NULL;
+
+ // Tell the call destructor not to free the message if it was canceled.
+ else
+ {
+ call->pmessage = NULL;
+ result = RPC_E_CALL_CANCELED;
+ }
+ }
+
+ // Check to see if the packet was rejected by the message filter.
+ else
+ {
+#ifdef _CHICAGO_
+ // No buffer is returned for asynchronous calls.
+ if ((message->rpcFlags & RPCFLG_ASYNCHRONOUS) == 0)
+#endif
+ result = ((Outbound_Header *) message->Buffer)->rejected;
+ }
+ return result;
+}
+
+/***************************************************************************/
+void CCallCache::Cleanup()
+{
+ DWORD i;
+
+ // Release everything.
+ lock.Request();
+ if (next <= CALLCACHE_SIZE)
+ {
+ for (i = 0; i < next; i++)
+ if (list[i] != NULL)
+ {
+ // use (void *) to avoid cast to real CPrivAlloc
+ PrivMemFree( (void *)list[i] );
+ list[i] = NULL;
+ }
+
+ // Make sure no late frees get cached.
+ next = CALLCACHE_SIZE + 1;
+ }
+ lock.Release();
+}
+
+/***************************************************************************/
+// given a destroyed working_call, put it on the free list or just free it.
+void CCallCache::Free( working_call *call )
+{
+ // Add the structure to the list if the list is not full.
+ lock.Request();
+ if (next < CALLCACHE_SIZE)
+ {
+ list[next] = call;
+ next += 1;
+ }
+
+ // Otherwise just free it.
+ else
+ {
+ // use (void *) to avoid cast to real CPrivAlloc
+ PrivMemFree( (void *)call );
+ }
+ lock.Release();
+}
+
+/***************************************************************************/
+// returns unconstructed working_call
+working_call *CCallCache::Get()
+{
+ working_call *call;
+
+ // Get the last entry from the cache.
+ lock.Request();
+ if (next > 0 && next < CALLCACHE_SIZE+1)
+ {
+ next -= 1;
+ call = list[next];
+ list[next] = NULL;
+ }
+
+ // If there are none, allocate a new one.
+ else
+ call = (working_call *) PrivMemAlloc(sizeof(*call));
+ lock.Release();
+ return call;
+}
+
+/***************************************************************************/
+void CCallCache::Initialize()
+{
+ // Zero everything.
+ lock.Request();
+ next = 0;
+ memset( list, 0, sizeof(list) );
+ lock.Release();
+}
diff --git a/private/ole32/com/remote/channelb.hxx b/private/ole32/com/remote/channelb.hxx
new file mode 100644
index 000000000..26285f6b6
--- /dev/null
+++ b/private/ole32/com/remote/channelb.hxx
@@ -0,0 +1,369 @@
+
+#ifndef _CHANNELB_HXX_
+#define _CHANNELB_HXX_
+
+#include <olesem.hxx>
+#include <rpc.h>
+#include <rpcndr.h>
+#include <dd.hxx>
+#include <service.hxx>
+#include <olerem.h>
+#include <chancont.hxx>
+#include <tls.h>
+
+extern "C"
+{
+#include "orpc_dbg.h"
+}
+
+#ifndef POBJCTX
+typedef void *POBJCTX;
+#endif
+
+
+/* Type definitions. */
+typedef enum EChannelState
+{
+ client_cs,
+ connecting_cs,
+ server_cs,
+ disconnected_cs
+} EChannelState;
+
+
+// CODEWORK: move to rpcdcep.h someday...
+
+// marks RPC_MESSAGE struct (a.k.a. RPCOLEMESSAGE) as local; normally we can
+// tell by comparing the _pService below to LocalService(), but in the async
+// case, we convert a remote call into a local one
+#define RPCFLG_LOCAL_CALL 0x10000000UL
+
+
+/***************************************************************************/
+
+
+// KLUDGE: code to tell RH that connect happens; triggers proxy hookup
+// (so RH doesn't have to keep state indicating if the connect happened);
+// this never gets pased outside of the RH because the RH is the only
+// one to call the channel for unmarshaling.
+#define CHAN_S_RECONNECT MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0xffff)
+
+extern RPC_SERVER_INTERFACE the_server_if;
+
+
+//+----------------------------------------------------------------
+//
+// Class: CRpcChannelBuffer
+//
+// Purpose: Three distinct uses:
+// Client side channel; currently embedded in CRemoteHdlr;
+// can connect (unmarshal) and disconnect many times.
+// State:
+// When not connected (after create and after disconnect):
+// ref_count 1 + 1 per addref during pending
+// calls that were in progress during
+// a disconnect.
+// _pRH back pointer to rh; not Addref'd
+// _pService NULL
+// state client_cs
+// _ChannelID BAD_CHANNEL_ID
+// _ulMarshalCnt 0
+// _fStrongConn N/A
+// connect_sync NULL
+// channel_control NULL
+// my_thread client's thread id
+// server_apt invalid
+//
+// When connected (after unmarshal):
+// ref_count 1 + 1 for each proxy
+// _pRH same
+// _pService non-NULL
+// state client_cs
+// _ChannelID valid in server process
+// _ulMarshalCnt valid
+// _fStrongConn N/A
+// connect_sync NULL
+// channel_control non-NULL
+// my_thread client's thread id
+// server_apt server's apartment id
+//
+// When in the middle of connecting (in unmarshal):
+// state connecting_cs
+// ... BUGBUG ...
+// connect_sync may be non-NULL
+//
+// Marshal helper; server side; embedded in CRemodeHdlr;
+// only used by the remote hdlr; never really connected;
+// disconnect does nothing.
+// State:
+// ref_count 1
+// _pRH same
+// _pService NULL
+// state disconnected_cs
+// _ChannelID BAD_CHANNEL_ID
+// _ulMarshalCnt 0
+// _fStrongConn N/A
+// connect_sync NULL
+// channel_control NULL
+// my_thread server's thread id
+// server_apt server's apartment id
+//
+// Server side channel; free standing; comes and goes with each
+// connection; addref owned disconnected via last release.
+// State:
+// ref_count > 0
+// _pRH pointer to other rh; AddRef'd
+// _pService non-NULL
+// state server_cs
+// _ChannelID valid;
+// list[_ChannelID&CLIST_ID_MASK] == this
+// _ulMarshalCnt non-zero
+// _fStrongConn TRUE/FALSE
+// connect_sync NULL
+// channel_control non-NULL
+// my_thread server's thread id
+// server_apt server's apartment id
+//
+// BUGBUG: my_thread and server_apt are not very meaningful when
+// FreeThreading is active, but they are set and used anyway.
+//
+// Interface: IRpcChannelBuffer, IMarshal
+//
+// History: ??-???-?? ??????? Created.
+// 20-Jan-94 CraigWi Documented better and added asserts
+//
+//-----------------------------------------------------------------
+
+class CChannelList;
+
+class CRpcChannelBuffer : public IRpcChannelBuffer,
+ public IMarshal,
+ public CPrivAlloc
+{
+ friend void RpcInvoke ( RPCOLEMESSAGE * );
+ friend HRESULT ThreadSendReceive ( STHREADCALLINFO * );
+ friend class CChannelList;
+
+ public:
+ STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) ( void );
+ STDMETHOD_(ULONG,Release) ( void );
+ STDMETHOD ( GetBuffer ) ( RPCOLEMESSAGE *pMessage, REFIID );
+ STDMETHOD ( FreeBuffer ) ( RPCOLEMESSAGE *pMessage );
+ STDMETHOD ( SendReceive ) ( RPCOLEMESSAGE *pMessage, ULONG * );
+ STDMETHOD ( GetDestCtx ) ( DWORD FAR* lpdwDestCtx,
+ LPVOID FAR* lplpvDestCtx );
+ STDMETHOD ( IsConnected ) ( void );
+
+ // IMarshal methods
+
+ STDMETHOD( GetUnmarshalClass )(REFIID riid, void *pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid);
+ STDMETHOD( GetMarshalSizeMax )(REFIID riid, void *pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize);
+ STDMETHOD( MarshalInterface ) (IStream *pStm, REFIID riid, void *pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD( UnmarshalInterface )(IStream *pStm, REFIID riid, void **ppv);
+ STDMETHOD( ReleaseMarshalData )(IStream *pStm);
+ STDMETHOD( DisconnectObject ) (DWORD dwReserved);
+
+
+
+ static HRESULT AppInvoke ( STHREADCALLINFO * );
+ static HRESULT ComInvoke ( STHREADCALLINFO * );
+#if DBG==1
+ void DebugCheckMarshalCnt( DWORD );
+ void DebugCheckOIDEndPointApt(REFOID, SEndPoint *, HAPT );
+#endif
+ CChannelControl *GetControl ( void );
+ DWORD GetID ( void ) { return _ChannelID; }
+ void SetID ( DWORD id ) { _ChannelID = id; }
+ DWORD GetClientTID ( void ) { return _dwClientTID; }
+ ULONG GetMarshalCnt ( void ) { return _ulMarshalCnt; }
+ HAPT GetServerApt ( void ) { return server_apt; }
+ IRemoteHdlr *GetRH ( void );
+ CRpcService *GetService ( void );
+
+ void IncMarshalCnt ( void );
+ INTERNAL TransferMarshalConnection(void);
+ void LockConnection(void);
+ void UnlockConnection(BOOL fLastUnlockCloses);
+
+#if DBG == 1
+ void AssertValid(BOOL fKnownDisconnected, BOOL fMustBeOnCOMThread);
+#else
+ void AssertValid(BOOL fKnownDisconnected, BOOL fMustBeOnCOMThread) { }
+#endif
+
+ static CALLCATEGORY GetCallCategory(REFIID iid, WORD wMethod);
+
+ // CODEWORK: these two methods should be moved to IRpcChannelBuffer
+ INTERNAL QueryObjectInterface(REFIID riid);
+ INTERNAL LockObjectConnection(BOOL fLock, BOOL fLastUnlockCloses);
+
+ CRpcChannelBuffer( IRemoteHdlr *,
+ CRpcService *,
+ DWORD dwClientTID,
+ CChannelControl *,
+ EChannelState eState);
+ ~CRpcChannelBuffer();
+
+ private:
+
+ void CheckDestCtx(void *pDestProtseq );
+
+ ULONG ref_count;
+ IRemoteHdlr *_pRH;
+ CRpcService *_pService;
+ CChannelControl *controller;
+ EChannelState state;
+ DWORD _ChannelID;
+ DWORD _dwClientTID;
+ ULONG _ulMarshalCnt;
+ BOOL _fStrongConn;
+ HAPT server_apt;
+ DWORD my_thread;
+ HANDLE connect_sync;
+ BOOL local;
+};
+
+inline void DeallocateBuffer(RPCOLEMESSAGE *message )
+{
+ if (message->rpcFlags & RPCFLG_LOCAL_CALL)
+ PrivMemFree( message->Buffer );
+ else
+ I_RpcFreeBuffer( (RPC_MESSAGE *) message );
+}
+
+// returns the channel control object; not addref'd.
+inline CChannelControl *CRpcChannelBuffer::GetControl()
+{
+ Win4Assert( controller != NULL );
+ return controller;
+}
+
+// returns the remote handler object; not addref'd.
+inline IRemoteHdlr *CRpcChannelBuffer::GetRH()
+{
+ AssertValid(FALSE, FALSE);
+ Win4Assert( _pRH != NULL );
+ return _pRH;
+}
+
+
+// returns the service object; may be NULL if server side channel and
+// disconnected; not addref'd.
+inline CRpcService *CRpcChannelBuffer::GetService()
+{
+ AssertValid(FALSE, FALSE);
+ Win4Assert( _pService != NULL );
+ return _pService;
+};
+
+
+inline void CRpcChannelBuffer::IncMarshalCnt( void )
+{
+ // must be client only
+ Win4Assert(state == connecting_cs || state == client_cs);
+ AssertValid(FALSE, FALSE);
+ InterlockedIncrement((long*)&_ulMarshalCnt);
+};
+
+
+#if DBG==1
+inline void CRpcChannelBuffer::DebugCheckMarshalCnt( DWORD count )
+{
+ AssertValid(FALSE, FALSE);
+ Win4Assert(state == server_cs);
+ Win4Assert( _ulMarshalCnt == count );
+}
+
+inline void CRpcChannelBuffer::DebugCheckOIDEndPointApt(REFOID roid,
+ SEndPoint *pEndPoint, HAPT hapt)
+{
+ AssertValid(FALSE, FALSE);
+ Win4Assert(state == server_cs);
+
+ OID oid;
+ _pRH->GetObjectID(&oid);
+ Win4Assert(IsEqualGUID(roid, oid));
+ Win4Assert(LocalService()->IsEqualEp(pEndPoint));
+ Win4Assert(FreeThreading || server_apt == hapt );
+}
+#endif
+
+
+
+//+----------------------------------------------------------------
+//
+// Class: CChannelList
+//
+// Purpose: maintain a list of channels
+//
+//+----------------------------------------------------------------
+
+#define BAD_CHANNEL_ID 0xffffffff
+#define CLIST_START_SIZE 8
+#define CLIST_EXPAND_SIZE 16
+#define CLIST_SEQUENCE_MASK 0xff000000
+#define CLIST_SEQUENCE_INC 0x01000000
+#define CLIST_ID_MASK (~CLIST_SEQUENCE_MASK)
+
+class CChannelList : public CPrivAlloc
+{
+public:
+ CChannelList(void);
+ ~CChannelList(void);
+
+ DWORD Add ( CRpcChannelBuffer *pChannel );
+ void AdjustSequence ( DWORD dwVal );
+ void Cleanup ( void );
+ void DisconnectHdlr ( IRemoteHdlr *pRH );
+ void DisconnectService( CRpcService * );
+ CRpcChannelBuffer *Lookup ( DWORD id, BOOL fRemove, BOOL fAddref );
+ DWORD LookupIdByOid ( OID object, CRpcService *service,
+ DWORD tid );
+ CChannelControl *LookupControl ( DWORD id );
+
+private:
+ static HRESULT DisconnectServiceHere( STHREADCALLINFO * );
+
+ DWORD Grow(ULONG ulNewSize);
+
+ static CRpcChannelBuffer **_pList;
+ static DWORD _ulLength;
+ static DWORD _dwSequence;
+ static DWORD _dwFree;
+ static COleStaticMutexSem _lock;
+};
+
+inline void CChannelList::AdjustSequence(DWORD dwVal)
+{
+ _dwSequence += dwVal << 24;
+}
+
+
+inline CChannelList::CChannelList()
+{
+ _dwSequence &= CLIST_SEQUENCE_MASK;
+}
+
+inline CChannelList::~CChannelList()
+{
+ PrivMemFree(_pList);
+}
+
+
+// List of channels.
+extern CChannelList ChannelList;
+
+
+/* Externals. */
+extern COleStaticMutexSem ChannelLock;
+
+
+#endif //_CHANNELB_HXX_
+
diff --git a/private/ole32/com/remote/coapi.cxx b/private/ole32/com/remote/coapi.cxx
new file mode 100644
index 000000000..14ec0311d
--- /dev/null
+++ b/private/ole32/com/remote/coapi.cxx
@@ -0,0 +1,1318 @@
+//+-------------------------------------------------------------------
+//
+// File: coapi.cxx
+//
+// Contents: Public COM remote subsystem APIs
+//
+// Classes: CStaticMarshaler (private)
+//
+// Functions: CoGetStandardMarshal - returns IMarshal for given object
+// CoGetMarshalSizeMax - returns max size buffer needed
+// CoMarshalInterface - marshals an interface
+// CoUnmarshalInterface - unmarshals an interface
+// CoReleaseMarshalData - releases data from marshaled iface
+// CoLockObjectExternal - keeps object alive
+// CoDisconnectObject - kills sessions held by remote clients
+//
+// History: 23-Nov-92 Rickhi
+// 11-Dec-93 CraigWi Switched to identity object
+// 05-Jul-94 BruceMa Check for end of stream
+//
+//--------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include <olerem.h>
+#include <iface.h>
+
+
+// function prototypes
+INTERNAL_(IMarshal *) FindOrCreateStdMarshal(IUnknown *pUnk, BOOL fCreate);
+INTERNAL_(IMarshal *) GetStaticMarshaler(void);
+INTERNAL_(void) RewriteHeader(IStream *pStm, void *pv, ULONG cb, ULARGE_INTEGER ulSeekStart);
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CoGetStandardMarshal
+//
+// Synopsis: Returns an instance of the standard IMarshal for the
+// specifed object. See comment about aggregated id objects
+// in FindOrCreateStdMarshal().
+//
+// Algorithm: lookup or create a remote hdlr for the object.
+//
+// History: 23-Nov-92 Rickhi Created
+// 11-Dec-93 CraigWi Switched to identity object
+//
+//--------------------------------------------------------------------
+STDAPI CoGetStandardMarshal(REFIID riid, IUnknown *pUnk,
+ DWORD dwDestContext, void *pvDestContext,
+ DWORD mshlflags, IMarshal **ppMarshal)
+{
+ OLETRACEIN((API_CoGetStandardMarshal,
+ PARAMFMT("riid= %I, pUnk= %p, dwDestContext= %x, pvDestContext= %p, mshlflags= %x, ppMarshal= %p"),
+ &riid, pUnk, dwDestContext, pvDestContext, mshlflags, ppMarshal));
+
+ TRACECALL(TRACE_MARSHAL, "CoGetStandardMarshal");
+
+ HRESULT sc = S_OK;
+ IMarshal *pIM;
+
+ if (!IsApartmentInitialized())
+ {
+ sc = CO_E_NOTINITIALIZED;
+ goto errRtn;
+ }
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,riid,&pUnk);
+
+ if (pUnk == NULL)
+ {
+ // this is the unmarshal side
+ // sc = CreateIdentityHandler(pUnk, PSTDMARSHAL, IID_IMarshal,
+ // (void**) &pIM);
+ pIM = GetStaticMarshaler();
+ }
+ else
+ {
+ // this is the marshal side
+ pIM = FindOrCreateStdMarshal(pUnk, TRUE);
+ }
+ *ppMarshal = pIM; // fill in the return parameters
+
+ if (SUCCEEDED(sc) && !pIM)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+
+ CairoleDebugOut((DEB_ITRACE, "CoGetStandardMarshal: pUnk=%x pIM=%x sc=%x\n",
+ pUnk, *ppMarshal, sc));
+errRtn:
+ OLETRACEOUT((API_CoGetStandardMarshal, sc));
+
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CoGetMarshalSizeMax
+//
+// synopsis: returns the max size needed to marshal the specified
+// interface.
+//
+// History: 23-Nov-92 Rickhi Created
+// 11-Dec-93 CraigWi Switched to static marshaler
+//
+//--------------------------------------------------------------------
+STDAPI CoGetMarshalSizeMax(ULONG *pulSize, REFIID riid, IUnknown *pUnk,
+ DWORD dwDestCtx, void *pvDestCtx,
+ DWORD mshlflags)
+{
+ OLETRACEIN((API_CoGetMarshalSizeMax,
+ PARAMFMT("pulSize= %p, riid= %I, pUnk= %p, dwDestCtx= %x, pvDestCtx= %p, mshlflags= %x"),
+ pulSize, &riid, pUnk, dwDestCtx, pvDestCtx, mshlflags));
+
+ TRACECALL(TRACE_MARSHAL, "CoGetMarshalSizeMax");
+
+ Win4Assert(MARSHALINTERFACE_MIN >= sizeof(SMiApiDataHdr) + sizeof(CLSID));
+
+ HRESULT sc = S_OK;
+ IMarshal *pIM = NULL;
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,riid,&pUnk);
+
+ if (!IsApartmentInitialized())
+ {
+ sc = CO_E_NOTINITIALIZED;
+ goto errRtn;
+ }
+
+ // find the IMarshal interface, or create a RH for the object
+ if (FAILED(pUnk->QueryInterface(IID_IMarshal, (void **)&pIM)))
+ {
+ // uses standard marshalling; cheaply get marshaler
+ pIM = GetStaticMarshaler();
+ Win4Assert(pIM);
+ }
+
+ if (pIM)
+ {
+ sc = pIM->GetMarshalSizeMax(riid, (void *)pUnk, dwDestCtx,
+ pvDestCtx, mshlflags, pulSize);
+
+ // BUGBUG: may need to release this specialy for custom marshalers
+
+ pIM->Release();
+
+ // add in the size of the stuff CoMarshalInterface will write;
+ // may not, in fact, write clsid, but this conservative.
+ (*pulSize) += sizeof(SMiApiDataHdr) + sizeof(CLSID);
+ }
+ else
+ {
+ sc = E_UNEXPECTED;
+ }
+
+ CairoleDebugOut((DEB_ITRACE, "CoGetMarshalSizeMax: pUnk=%x size=%x dwDest=%x pvDest=%x flags=%x sc=%x\n",
+ pUnk, *pulSize, dwDestCtx, pvDestCtx, mshlflags, sc));
+
+errRtn:
+ OLETRACEOUT((API_CoGetMarshalSizeMax, sc));
+
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CoMarshalInterface, public
+//
+// Synopsis: fill stream with marshal info for pUnk/iid;
+//
+// Algorithm:
+//
+// History: 23-Nov-92 Rickhi
+// 11-Dec-93 CraigWi Switched to identity object and
+// new marshaling format
+//
+//--------------------------------------------------------------------
+
+STDAPI CoMarshalInterface(IStream *pStm,
+ REFIID riid,
+ IUnknown *pUnk,
+ DWORD dwDestCtx,
+ void *pvDestCtx,
+ DWORD mshlflags)
+{
+ OLETRACEIN((API_CoMarshalInterface,
+ PARAMFMT("pStm= %p, riid= %I, pUnk= %p, dwDestCtx= %x, pvDestCtx= %p, mshlflags= %x"),
+ pStm, &riid, pUnk, dwDestCtx, pvDestCtx, mshlflags));
+
+ TRACECALL(TRACE_MARSHAL, "CoMarshalInterface");
+
+ HRESULT sc;
+ IMarshal *pIM = NULL;
+
+ if (!IsApartmentInitialized())
+ {
+ sc = CO_E_NOTINITIALIZED;
+ goto errRtn;
+ }
+
+ // Some parameter checking
+ if (pUnk == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,riid,(IUnknown **)&pUnk);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pStm);
+
+ // Make sure object supports the requested interface. This has the
+ // side effect that if this is a request for a marshal interface and
+ // the object is a proxy for which we have never gotten the interface,
+ // we will get it now and the marshal will work.
+ IUnknown *punkVerifyIf;
+
+ if (pUnk->QueryInterface(riid, (void **) &punkVerifyIf) != NOERROR)
+ {
+ sc = E_NOINTERFACE;
+ goto errRtn;
+ }
+
+ // find the IMarshal interface, or create a RH for the object
+ if (FAILED(pUnk->QueryInterface(IID_IMarshal, (void **)&pIM)))
+ {
+ // returns NULL if failed
+ pIM = FindOrCreateStdMarshal(pUnk, TRUE);
+ }
+
+ if (pIM)
+ {
+ // setup the marshal info structure
+ SMiApiDataHdr ifp;
+ CLSID clsid;
+
+ ifp.dwflags = mshlflags & MIAPIFLAGS_TABLE;
+
+ sc = pIM->GetUnmarshalClass(riid, pUnk, dwDestCtx, pvDestCtx,
+ mshlflags, &clsid);
+
+ if (IsEqualGUID(clsid, CLSID_IdentityUnmarshal))
+ {
+ ifp.dwflags |= MIAPIFLAGS_STDIDENTITY;
+ }
+ else if (IsEqualGUID(clsid, CLSID_InProcFreeMarshaler))
+ {
+ ifp.dwflags |= MIAPIFLAGS_IPFM;
+ }
+
+
+ if (SUCCEEDED(sc))
+ {
+ // write the marshal info into the stream
+ sc = pStm->Write(&ifp, sizeof(ifp), NULL);
+ }
+
+ if (SUCCEEDED(sc)
+ && (ifp.dwflags & (MIAPIFLAGS_STDIDENTITY | MIAPIFLAGS_IPFM)) == 0)
+ {
+ // write non-standard unmarshaler clsid
+ sc = pStm->Write(&clsid, sizeof(clsid), NULL);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ sc = pIM->MarshalInterface(pStm, riid, pUnk, dwDestCtx,
+ pvDestCtx, mshlflags);
+ }
+
+ pIM->Release();
+ }
+ else
+ {
+ sc = E_OUTOFMEMORY;
+ }
+
+ // Release the interface we used to verify that the interface was supported
+ // here because if we succeeded we have multiple AddRefs to the interface
+ // and therefore the object will not go away.
+ punkVerifyIf->Release();
+
+ CairoleDebugOut((DEB_ITRACE, "CoMarshalInterface: pUnk=%x pIM=%x dwDest=%x pvDest=%x flags=%x sc=%x\n",
+ pUnk, pIM, dwDestCtx, pvDestCtx, mshlflags, sc));
+errRtn:
+ OLETRACEOUT((API_CoMarshalInterface, sc));
+
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CoUnMarshalInterface, public
+//
+// Algorithm:
+//
+// Notes: when a controlling unknown is supplied, it is assumed that
+// the HANDLER for the class has done a CreateInstance and wants
+// to aggregate just the remote handler, ie. we dont want to
+// instantiate a new class handler (the default unmarshalling
+// behaviour).
+//
+// History: 23-Nov-92 Rickhi
+// 11-Dec-93 CraigWi Switched to static marshaler and
+// new marshaling format
+//
+//--------------------------------------------------------------------
+
+STDAPI CoUnmarshalInterfaceEx(IStream *pStm, REFIID riid, void **ppv, BOOL f);
+
+STDAPI CoUnmarshalInterface(IStream *pStm,
+ REFIID riid,
+ void **ppv)
+{
+ OLETRACEIN((API_CoUnmarshalInterface, PARAMFMT("pStm= %p, riid= %I, ppv= %p"), pStm, &riid, ppv));
+
+ HRESULT hr;
+
+ hr = CoUnmarshalInterfaceEx(pStm, riid, ppv, TRUE /*fNormalDoesRelease*/);
+
+ OLETRACEOUT((API_CoUnmarshalInterface, hr));
+
+ return hr;
+}
+
+
+// This variation allows control over whether the normal marshal case does
+// the release marshal data. This is useful for nested marshaled pointers
+// which need to be released once when the outer marshaling is released.
+STDAPI CoUnmarshalInterfaceEx(IStream *pStm,
+ REFIID riid,
+ void **ppv,
+ BOOL fNormalDoesRelease)
+{
+ TRACECALL(TRACE_MARSHAL, "CoUnmarshalInterface");
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pStm);
+
+ if (!IsApartmentInitialized())
+ return CO_E_NOTINITIALIZED;
+
+ HRESULT sc;
+ IMarshal *pIM = NULL;
+
+ *ppv = NULL;
+
+ SMiApiDataHdr ifp;
+ CLSID clsid;
+ sc = StRead(pStm, &ifp, sizeof(ifp));
+
+ if (SUCCEEDED(sc) && (ifp.dwflags & MIAPIFLAGS_RELEASED) != 0)
+ {
+ // already released, this is an error on the caller's part
+ sc = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(sc)
+ && (ifp.dwflags & (MIAPIFLAGS_STDIDENTITY | MIAPIFLAGS_IPFM)) == 0)
+ {
+ sc = StRead(pStm, &clsid, sizeof(clsid));
+ }
+
+ // deal with extension
+ if (SUCCEEDED(sc) && (ifp.dwflags & MIAPIFLAGS_EXTENSION) != 0)
+ sc = SkipMarshalExtension(pStm);
+
+ if (SUCCEEDED(sc))
+ {
+ // create an instance of the specified class and ask it to do
+ // the unmarshalling. note that since standard marshalling is so
+ // common, we cook up an instance at init time and just always
+ // use that guy to do the unmarshalling.
+
+ if ((ifp.dwflags & MIAPIFLAGS_STDIDENTITY) != 0)
+ {
+ // uses standard marshalling; cheaply get unmarshaler
+ pIM = GetStaticMarshaler();
+ Win4Assert(pIM);
+ }
+ else if ((ifp.dwflags & MIAPIFLAGS_IPFM) != 0)
+ {
+ // Get the in process standard free marshaler.
+ sc = GetInProcFreeMarshaler(&pIM);
+ }
+ else
+ {
+ // uses custom marshalling, create an instance
+ sc = CoCreateInstance(clsid, NULL, CLSCTX_INPROC,
+ IID_IMarshal, (void **)&pIM);
+ }
+
+ if (SUCCEEDED(sc) && pIM)
+ {
+ ULARGE_INTEGER ulSeekStart;
+ LARGE_INTEGER libMove;
+
+ if ((ifp.dwflags & MIAPIFLAGS_TABLE) == MSHLFLAGS_NORMAL)
+ {
+ // save current seek pointer for ReleaseMarshalData
+ LISet32(libMove, 0x00000000);
+ pStm->Seek(libMove, STREAM_SEEK_CUR, &ulSeekStart);
+ }
+
+ // unmarshal the interface
+ sc = pIM->UnmarshalInterface(pStm, riid, ppv);
+
+ // release the marshal data if we are supposed to.
+ // ignore errors because they cant affect that fact that
+ // we already successfully unmarshalled the interface.
+
+ if ((ifp.dwflags & MIAPIFLAGS_TABLE) == MSHLFLAGS_NORMAL &&
+ fNormalDoesRelease)
+ {
+ ULARGE_INTEGER ulSeekEnd;
+ pStm->Seek(libMove, STREAM_SEEK_CUR, &ulSeekEnd);
+ libMove.LowPart = ulSeekStart.LowPart;
+ libMove.HighPart = ulSeekStart.HighPart;
+ if (SUCCEEDED(pStm->Seek(libMove, STREAM_SEEK_SET, &ulSeekStart)))
+ {
+ pIM->ReleaseMarshalData(pStm);
+ }
+ libMove.LowPart = ulSeekEnd.LowPart;
+ libMove.HighPart = ulSeekEnd.HighPart;
+ pStm->Seek(libMove, STREAM_SEEK_SET, NULL);
+ }
+ }
+ }
+
+ if (pIM)
+ pIM->Release();
+
+ CairoleDebugOut((DEB_ITRACE, "CoUnmarshalInterface: pUnk=%x sc=%x\n",
+ *ppv, sc));
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CoReleaseMarshalData, public
+//
+// Synopsis: release the reference created by CoMarshalInterface
+//
+// Algorithm:
+//
+// History: 23-Nov-92 Rickhi
+// 11-Dec-93 CraigWi Switched to static marshaler and
+// new marshaling format
+//
+//--------------------------------------------------------------------
+
+STDAPI CoReleaseMarshalData(IStream *pStm)
+{
+ OLETRACEIN((API_CoReleaseMarshalData, PARAMFMT("pStm= %p"), pStm));
+
+ TRACECALL(TRACE_MARSHAL, "CoReleaseMarshalData");
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pStm);
+
+ HRESULT sc;
+ IMarshal *pIM = NULL;
+ SMiApiDataHdr ifp;
+ CLSID clsid;
+ ULARGE_INTEGER ulSeekStart;
+ LARGE_INTEGER libMove;
+
+ if (!IsApartmentInitialized())
+ {
+ sc = CO_E_NOTINITIALIZED;
+ goto errRtn;
+ }
+
+ // save the current stream seek pointer
+ LISet32(libMove, 0x00000000);
+ sc = pStm->Seek(libMove, STREAM_SEEK_CUR, &ulSeekStart);
+
+ if (SUCCEEDED(sc))
+ sc = StRead(pStm, &ifp, sizeof(ifp));
+
+ // ensure this marshalled data has not already been released.
+ if (SUCCEEDED(sc) && (ifp.dwflags & MIAPIFLAGS_RELEASED) != 0)
+ {
+ // already released, this is an error. Stream in undefined
+ // position on errors.
+ sc = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(sc)
+ && ((ifp.dwflags & (MIAPIFLAGS_STDIDENTITY | MIAPIFLAGS_IPFM)) == 0))
+ sc = StRead(pStm, &clsid, sizeof(clsid));
+
+ // deal with extension
+ if (SUCCEEDED(sc) && (ifp.dwflags & MIAPIFLAGS_EXTENSION) != 0)
+ sc = SkipMarshalExtension(pStm);
+
+ if (SUCCEEDED(sc))
+ {
+ // create an instance of the specified class and ask it to do
+ // the unmarshalling. note that since standard marshalling is so
+ // common, we cook up an instance at init time and just always
+ // use that guy to do the unmarshalling.
+
+ if ((ifp.dwflags & MIAPIFLAGS_STDIDENTITY) != 0)
+ {
+ // uses standard marshalling; cheaply get unmarshaler
+ pIM = GetStaticMarshaler();
+ Win4Assert(pIM); // cant fail!!!
+ }
+ else if ((ifp.dwflags & MIAPIFLAGS_IPFM) != 0)
+ {
+ // Uses the free threaded marshaler. So we get it directly.
+ // This really can only fail with out of memory.
+ IUnknown *punk;
+
+ // Get the IUnknown for the free threaded marshaler
+ sc = CoCreateFreeThreadedMarshaler(NULL, &punk);
+
+ if (SUCCEEDED(sc))
+ {
+ // Get the IMarshal interface
+ sc = punk->QueryInterface(IID_IMarshal, (void **) &pIM);
+
+ // We release this no matter what since we no longer need it.
+ punk->Release();
+ }
+ }
+ else
+ {
+ // uses custom marshalling, create an instance
+ sc = CoCreateInstance(clsid, NULL, CLSCTX_INPROC,
+ IID_IMarshal, (void **)&pIM);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ sc = pIM->ReleaseMarshalData(pStm);
+
+ if (pIM)
+ pIM->Release();
+ }
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ // if overall success...
+ // to ensure we dont allow ReleaseMarshalData multiple times we
+ // mark a bit in the stream to indicate we've already Released it.
+ // UnmarshalInterface will return an error if this bit is set.
+ ifp.dwflags |= MIAPIFLAGS_RELEASED;
+ RewriteHeader(pStm, &ifp, sizeof(ifp), ulSeekStart);
+ }
+
+ CairoleDebugOut((DEB_ITRACE, "CoReleaseMarshalData pIM=%x sc=%x.\n",
+ pIM, sc));
+errRtn:
+ OLETRACEOUT((API_CoReleaseMarshalData, sc));
+
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CoLockObjectExternal
+//
+// synopsis: adds/revokes a strong reference count to/from the
+// identity for the given object.
+//
+// parameters: [punkObject] - IUnknown of the object
+// [fLock] - lock/unlock the object
+// [fLastUR] - last unlock releases.
+//
+// History: 23-Nov-92 Rickhi Created
+// 11-Dec-93 CraigWi Switched to identity object
+//
+//--------------------------------------------------------------------
+
+STDAPI CoLockObjectExternal(IUnknown *punkObject, BOOL fLock, BOOL fLastUR)
+{
+ OLETRACEIN((API_CoLockObjectExternal, PARAMFMT("punkObject= %p, fLock= %B, fLastUR= %B"),
+ punkObject, fLock, fLastUR));
+
+ TRACECALL(TRACE_MARSHAL, "CoLockObjectExternal");
+
+ // REF COUNTING: inc or dec external ref count
+
+ HRESULT sc = E_INVALIDARG;
+ IStdIdentity *pStdID;
+
+ if (!IsValidInterface(punkObject))
+ goto errRtn;
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&punkObject);
+
+ switch (sc = LookupIDFromUnk(punkObject, fLock, &pStdID))
+ {
+ case S_OK:
+ if (pStdID->GetServer(FALSE) == NULL)
+ {
+ // attempt to lock handler, return error!
+ // BUGBUG: debug printouts
+ sc = E_UNEXPECTED;
+ }
+ else if (fLock)
+ sc = pStdID->AddConnection(EXTCONN_STRONG, 0);
+ else
+ sc = pStdID->ReleaseConnection(EXTCONN_STRONG, 0, fLastUR);
+
+ pStdID->Release();
+ break;
+
+ case CO_E_OBJNOTREG:
+ // unlock when not registered; 16bit code returned NOERROR;
+ // disconnected handler goes to S_OK case above.
+ sc = S_OK;
+ break;
+
+ case E_OUTOFMEMORY:
+ break;
+
+ default:
+ sc = E_UNEXPECTED;
+ break;
+ }
+
+errRtn:
+ CairoleDebugOut((DEB_ITRACE, "CoLockObjectExternal pStdID=%x fLock=%x sc=%x.\n",
+ pStdID, fLock, sc));
+
+ OLETRACEOUT((API_CoLockObjectExternal, sc));
+
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CoDisconnectObject
+//
+// synopsis: disconnects all clients of an object by marking their
+// connections as terminted abnormaly.
+//
+// History: 04-Oct-93 Rickhi Created
+// 11-Dec-93 CraigWi Switched to identity object
+//
+//--------------------------------------------------------------------
+
+STDAPI CoDisconnectObject(IUnknown *punkObject, DWORD dwReserved)
+{
+ OLETRACEIN((API_CoDisconnectObject, PARAMFMT("punkObject= %p, dwReserved= %x"), punkObject, dwReserved));
+
+ TRACECALL(TRACE_MARSHAL, "CoDisconnectObject");
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&punkObject);
+
+ HRESULT sc = S_OK;
+ IMarshal *pIM = NULL;
+
+ sc = punkObject->QueryInterface(IID_IMarshal, (void **)&pIM);
+ if (FAILED(sc))
+ {
+ // object does not support IMarshal directly. Find its standard
+ // marshaler if there is one, otherwise return an error.
+
+ pIM = FindOrCreateStdMarshal(punkObject, FALSE);
+ }
+
+ if (pIM)
+ {
+ sc = pIM->DisconnectObject(dwReserved);
+ pIM->Release();
+ }
+ else
+ {
+ // couldn't get std marshal; must be disconnected already
+ sc = NOERROR;
+ }
+
+ CairoleDebugOut((DEB_ITRACE, "CoDisconnectObject pIM=%x sc=%x.\n",
+ pIM, sc));
+
+ OLETRACEOUT((API_CoDisconnectObject, sc));
+
+ return sc;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CoIsHandlerConnected
+//
+// Synopsis: Returns whether or not handler is connected to remote
+//
+// Algorithm: QueryInterface to IProxyManager. If this is supported,
+// then this is a handler. We ask the handler
+// for its opinion otherwise we simply return TRUE.
+//
+// History: 04-Oct-93 Rickhi Created
+//
+// Notes: The answer of this routine may be wrong by the time
+// the routine returns. This is correct behavior as
+// this routine is primilary to cleanup state associated
+// with connections.
+//
+//--------------------------------------------------------------------
+
+STDAPI_(BOOL) CoIsHandlerConnected(LPUNKNOWN pUnk)
+{
+ OLETRACEIN((API_CoIsHandlerConnected, PARAMFMT("pUnk= %p"), pUnk));
+
+ IProxyManager *pPM;
+
+ // Assume it is connected
+ BOOL fResult = TRUE;
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&pUnk);
+ // Handler should be support IProxyManager
+ if (SUCCEEDED(pUnk->QueryInterface(IID_IProxyManager, (void **) &pPM)))
+ {
+ // We have something that thinks its is an Ole handler so we ask
+ fResult = pPM->IsConnected();
+
+ // Release the interface we used
+ pPM->Release();
+ }
+
+ OLETRACEOUTEX((API_CoIsHandlerConnected, RETURNFMT("%B"), fResult));
+
+ return fResult;
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: FindOrCreateStdMarshal, private
+//
+// Synopsis: looks up or creates the std identity for the object
+// and returns the IMarshal aspect of it. It is assumed
+// that the ID object is not aggregated to the server
+// (BUGBUG: can we assert that???) because we need to QI
+// for IMarshal. When the id object is aggregated, the
+// caller is supposed to use IStdIdentity::GetStdRemMarshal()
+// instead.
+//
+// Arguments: [pUnk] -- The object in question; not necessaryily the
+// controlling unknown.
+// [fCreate] -- TRUE -> creates identity object if it does
+// not exist.
+//
+// Returns: NULL if out of memory; pMarshal otherwise
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+INTERNAL_(IMarshal *)FindOrCreateStdMarshal(IUnknown *pUnk, BOOL fCreate)
+{
+ IStdIdentity *pStdID;
+ if (LookupIDFromUnk(pUnk, fCreate, &pStdID) != NOERROR)
+ // only possible return in this case is E_OUTOFMEMORY.
+ return NULL;
+
+ HRESULT hr;
+ IMarshal *pMarshal;
+ hr = pStdID->QueryInterface(IID_IMarshal, (void **)&pMarshal);
+ pStdID->Release();
+ AssertSz(hr == NOERROR, "What, no IMarshal on an identity object?");
+ CALLHOOKOBJECTCREATE(hr,CLSID_NULL,IID_IMarshal,(IUnknown **)&pMarshal);
+ return (hr == NOERROR) ? pMarshal : NULL;
+}
+
+
+//+----------------------------------------------------------------
+//
+// Class: CStaticMarshaler, private
+//
+// Purpose: Used for three rather disjoint purposes:
+// 1. unmarshaling normal identity packet
+// 2. release marshal data of same and table packets
+// 3. get marshal size max
+//
+// This class exists solely to make the code in the Co*
+// APIs cleaner. It is not integrated into the real
+// identity object itself to avoid confusing the two
+// roles (initial unmarshaler and the real identity).
+//
+// Interface: IMarshal::GetMarshalSizeMax, IMarshal::UnmarshalInterface
+// and IMarshal::ReleaseMarshal; other methods of IMarshal
+// return E_UNEXPECTED.
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+// Note: There is only one instance of this class (for speed) and
+// thus many short cuts are taken.
+//
+//-----------------------------------------------------------------
+
+class CStaticMarshaler : public IMarshal
+{
+public:
+ STDMETHOD(QueryInterface) (REFIID riid, LPVOID *ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ // IMarshal
+ STDMETHOD(GetUnmarshalClass)(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax)(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(LPSTREAM pStm, REFIID riid,
+ LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(LPSTREAM pStm, REFIID riid,
+ VOID **ppv);
+ STDMETHOD(ReleaseMarshalData)(LPSTREAM pStm);
+ STDMETHOD(DisconnectObject)(DWORD dwReserved);
+
+private:
+#if DBG == 1
+ DWORD m_refs; // for the AddRef/Release return value
+#endif
+
+} sg_StaticMarshaler;
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStaticMarshaler::QueryInterface, public
+//
+// Synopsis: shouldn't be called.
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStaticMarshaler::QueryInterface(REFIID riid, VOID **ppvObj)
+{
+ AssertSz(FALSE, "This QI should not be called");
+ *ppvObj = NULL;
+ return E_UNEXPECTED;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStaticMarshaler::AddRef, Release, public
+//
+// Synopsis: maintains ref count in debug version only.
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CStaticMarshaler::AddRef(void)
+{
+#if DBG == 1
+ return ++m_refs;
+#else
+ return 0;
+#endif
+}
+
+
+STDMETHODIMP_(ULONG) CStaticMarshaler::Release(void)
+{
+#if DBG == 1
+ return --m_refs;
+#else
+ return 0;
+#endif
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStaticMarshaler::GetUnmarshalClass, public
+//
+// Synopsis: shouldn't be called.
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStaticMarshaler::GetUnmarshalClass(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid)
+{
+ AssertSz(FALSE, "This GetUnmarshalClass should not be called");
+
+ return E_UNEXPECTED;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStaticMarshaler::GetMarshalSizeMax, public
+//
+// Synopsis: Quickly gets an upper bound on the amount of data for
+// a standard marshal (no app data).
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStaticMarshaler::GetMarshalSizeMax(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize)
+{
+ // object doesn't have own imarshal and thus it will use all
+ // standard marshaling (coapi, id, remhdlr, channel).
+ // size is: sizeof id, sizeof rh, upper bound on size of channel
+
+ // don't want to be fancy about this since we want this to be fast;
+ // include handler CLSID since we don't want to check if it is needed.
+
+ *pSize = sizeof(SIdentityDataHdr) + sizeof(CLSID) +
+ sizeof(SHandlerDataHdr) + /* CLSID_RpcChannelBuffer + */
+ sizeof(SChannelDataHdr)
+ + 1024;
+
+ //
+ // BUGBUG: (RichardW, 14 Oct 94, for RickHi, bug # 25942)
+ //
+ // Someone trashed this calculation, adding this random 512 byte pad
+ // on the end. RickHi will apply the correct fix, but for now, for
+ // cairo builds, I have bumped it to 1024.
+ //
+
+
+ // CODEWORK: later when channel is indexable from the dest context,
+ // we use that for the last component of the size. This is also
+ // important to do since we don't really know an upper bound on the
+ // channel data size.
+
+ // When table marshaling differs from normal marshaling, this
+ // routine will have to encode how the size gets calculated.
+ // In both cases some code will be shared (procedures) with std id.
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStaticMarshaler::MarshalInterface, public
+//
+// Synopsis: shouldn't be called.
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStaticMarshaler::MarshalInterface(LPSTREAM pStm,
+ REFIID riid, LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ AssertSz(FALSE, "This MarshalInterface should not be called");
+
+ return E_UNEXPECTED;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: ReadIdentityHeader, private
+//
+// Synopsis: Reads the identity data header and the clsid;
+// if fTransparent, skips back to the beginning;
+// else, skips over extention if present.
+//
+// History: 14-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+INTERNAL ReadIdentityHeader(IStream *pStm, SIdentityDataHdr *pidh,
+ CLSID *pclsidHandler, BOOL fTransparent)
+{
+ HRESULT hr;
+ ULARGE_INTEGER ulSeekStart;
+ LARGE_INTEGER libMove;
+
+ if (fTransparent)
+ {
+ // save current position so that we can set it back here
+ LISet32(libMove, 0x00000000);
+ hr = pStm->Seek(libMove, STREAM_SEEK_CUR, &ulSeekStart);
+ if (FAILED(hr))
+ return hr;
+ }
+
+ hr = StRead(pStm, pidh, sizeof(*pidh));
+
+ if (FAILED(hr))
+ return hr;
+
+ if ((pidh->dwflags & IDENFLAGS_STDMARSHAL) != 0)
+ {
+ // std marshal case
+ *pclsidHandler = CLSID_StdMarshal;
+ }
+ else
+ {
+ hr = StRead(pStm, pclsidHandler, sizeof(*pclsidHandler));
+
+ if (FAILED(hr))
+ return hr;
+ }
+
+ if (fTransparent)
+ {
+ // skip back to the beginning of what was just read
+
+ libMove.LowPart = ulSeekStart.LowPart;
+ libMove.HighPart = ulSeekStart.HighPart;
+ hr = pStm->Seek(libMove, STREAM_SEEK_SET, NULL);
+ }
+ else
+ {
+ // read extension and leave seek pointer after header
+ if (pidh->dwflags & IDENFLAGS_EXTENSION)
+ hr = SkipMarshalExtension(pStm);
+ }
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStaticMarshaler::UnmarshalInterface, public
+//
+// Synopsis: First part of unmarshaling an identity object; looks
+// for an existing object and if not found creates one
+// of type clsidHandler and CLSCTX_INPROC_HANDLER. In
+// all cases, skips back to the beginning of the identity
+// information and forwards the unmarshal call on to the
+// identified object. Thus it is the responsibility of
+// handlers that support identity to make sure the identity
+// information is consumed first.
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStaticMarshaler::UnmarshalInterface(LPSTREAM pStm,
+ REFIID riid, VOID **ppv)
+{
+ // BUGBUG PERF: can we call into identity object directly or bypass it
+ // by getting it's followon marshaler?
+
+ HRESULT hr;
+ SIdentityDataHdr idh;
+ CLSID clsidHandler;
+
+ // read data header and optional clsidHandler; seek back;
+ hr = ReadIdentityHeader(pStm, &idh, &clsidHandler, TRUE /*fTransparent*/);
+ if (FAILED(hr))
+ return hr;
+
+ // lookup id; if exists, feed data to it
+ // else create handler for clsidHandler and feed data to it
+ // works for both normal and table marshal
+
+ IStdIdentity *pStdID;
+ IMarshal *pMarshal;
+ if (LookupIDFromID(idh.ObjectID, TRUE, &pStdID) == NOERROR)
+ {
+ // identity exists; we are holding it alive
+ hr = pStdID->QueryInterface(IID_IMarshal, (void**)&pMarshal);
+ pStdID->Release();
+ if (hr != NOERROR)
+ // something which supports identity must also support custom
+ // marshaling.
+ return E_UNEXPECTED;
+ }
+ else
+ {
+ // identity doesn't not exist; create object; add to table will be in
+ // the unmarshal below.
+
+ // CODEWORK: can we get check for duplicate identity here so
+ // the contention is easier to recover from??? Possibly we
+ // can create a dummy id which indicates we will register one
+ // or remove the dummy. Other thread could wait on that object
+ // and if that object went away, could then create its own
+ // dummy id and continue. All that would happen in LookupIDFromID.
+
+ // NOTE: this CLSCTX_INPROC_HANDLER is significant since we don't
+ // want to confuse an inproc server with what we know must be
+ // a handler. Besides, the 16bit code did it this way.
+
+ // if clsidHandler == CLSID_StdMarshal: create identity handler
+ // BUGBUG: should make the class object code do this (it did in 16bit)
+ if (IsEqualGUID(clsidHandler, CLSID_StdMarshal))
+ {
+UseStdMarshal:
+ hr = CreateIdentityHandler(NULL, PSTDMARSHAL,
+ IID_IMarshal, (void **)&pMarshal);
+ }
+ else
+ {
+ hr = CoCreateInstance(clsidHandler, NULL, CLSCTX_INPROC_HANDLER,
+ IID_IMarshal, (void **)&pMarshal);
+ // if not registered, use StdMarshal
+ if (hr == REGDB_E_CLASSNOTREG)
+ {
+ clsidHandler = CLSID_StdMarshal;
+ goto UseStdMarshal;
+ }
+ }
+
+ // NOTE: this pMarshal must consume the identity information first.
+ // the most common way for people to do that is to expose the IMarshal
+ // on the identity object as the IMarshal of the handler.
+
+ if (hr != NOERROR)
+ return hr;
+ }
+
+ hr = pMarshal->UnmarshalInterface(pStm, riid, ppv);
+ pMarshal->Release();
+
+ // CODEWORK: multithread issue: if already registered,skip back and try again.
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStaticMarshaler::ReleaseMarshalData, public
+//
+// Synopsis: First part of releasing the marshal data for an identity
+// object. Very much like UnmarshalInterface above.
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStaticMarshaler::ReleaseMarshalData(LPSTREAM pStm)
+{
+ // CODEWORK PERF: if normal, we have to re-lookup the the identity;
+ // an alternative is to have the ::UnmarshalInteface method above
+ // do the release and mark the stream as released (perhaps even
+ // moving the HDLRFLAGS_RELEASED bit here); we would still have to
+ // return an error since we cannot actually consume the data. This
+ // works fine for the cases that matter (Unmarshal followed by
+ // Release).
+
+ HRESULT hr;
+ SIdentityDataHdr idh;
+ CLSID clsidHandler;
+
+ // read data header and optional clsidHandler; seek back;
+ hr = ReadIdentityHeader(pStm, &idh, &clsidHandler, TRUE /*fTransparent*/);
+ if (FAILED(hr))
+ return hr;
+
+ // lookup id; if exists, feed data to it
+ // else error (object already released)
+ // works for both normal and table marshal
+
+ // CODEWORK: when table marshaling changes, this code will have to
+ // change too.
+
+ IStdIdentity *pStdID;
+ IMarshal *pMarshal;
+ if (LookupIDFromID(idh.ObjectID, TRUE, &pStdID) == NOERROR)
+ {
+ // identity exists; we are holding it alive
+ hr = pStdID->QueryInterface(IID_IMarshal, (void**)&pMarshal);
+ pStdID->Release();
+ if (hr != NOERROR)
+ // something which supports identity must also support custom
+ // marshaling.
+ return E_UNEXPECTED;
+ }
+ else
+ {
+ // identity doesn't not exist; error
+
+ // BUGBUG: should do better here since this may happen in the
+ // error case. We would create an instance of the handler
+ // just for the destruction of the marshal data.
+ // Happened in bug 13086 before CStdIdentity::IsConnected was changed.
+ // If we don't do this, the marshal connection will not be released
+ // on the server side and the object may not shutdown as it should.
+
+ return CO_E_OBJNOTREG;
+ }
+
+ hr = pMarshal->ReleaseMarshalData(pStm);
+ pMarshal->Release();
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStaticMarshaler::DisconnectObject, public
+//
+// Synopsis: shouldn't be called.
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStaticMarshaler::DisconnectObject(DWORD dwReserved)
+{
+ AssertSz(FALSE, "This DisconnectObject should not be called");
+
+ return E_UNEXPECTED;
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: GetStaticMarshaler, private
+//
+// Synopsis: Returns the single instance of the std identity unmarshaler.
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+INTERNAL_(IMarshal *) GetStaticMarshaler()
+{
+#if DBG == 1
+ sg_StaticMarshaler.AddRef();
+#endif
+ return &sg_StaticMarshaler;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: SkipMarshalExtension, private
+//
+// Synopsis: Skips the marshaling extension (DWORD cb, rgcb).
+//
+// Returns: stm errors if problem
+//
+// History: 14-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+INTERNAL SkipMarshalExtension(IStream *pStm)
+{
+ HRESULT hr;
+ DWORD cb;
+
+ hr = StRead(pStm, &cb, sizeof(cb));
+ if (FAILED(hr))
+ return hr;
+
+ LARGE_INTEGER li;
+ LISet32(li, cb);
+ return pStm->Seek(li, STREAM_SEEK_CUR, NULL);
+}
+
+
+
+
+//+------------------------------------------------------------------------
+//
+// Function: RewriteHeader, private
+//
+// Synopsis: Writes the given data at the offset given and restores the
+// stream to the position it was on entry.
+//
+// Arguments: [pStm] -- The stream into which we write the data
+// [pb] -- The data
+// [cb] -- The amount of data
+// [ulSeekStart] -- The place to write the data
+//
+// History: 15-May-94 CraigWi Created
+//
+//-------------------------------------------------------------------------
+
+INTERNAL_(void) RewriteHeader(IStream *pStm, void *pv, ULONG cb, ULARGE_INTEGER ulSeekStart)
+{
+ LARGE_INTEGER libMove;
+ ULARGE_INTEGER ulSeekEnd;
+
+ LISet32(libMove, 0x00000000);
+ if (SUCCEEDED(pStm->Seek(libMove, STREAM_SEEK_CUR, &ulSeekEnd)))
+ {
+ // go back to the starting position
+ libMove.LowPart = ulSeekStart.LowPart;
+ libMove.HighPart = ulSeekStart.HighPart;
+ if (SUCCEEDED(pStm->Seek(libMove, STREAM_SEEK_SET, NULL)))
+ {
+ // set the header bit and write it back into the stream
+ pStm->Write(pv, cb, NULL);
+ }
+
+ // regardless of whether the write worked, restore the stream
+ // back to the ending positon. ignore any errors generated here.
+
+ libMove.LowPart = ulSeekEnd.LowPart;
+ libMove.HighPart = ulSeekEnd.HighPart;
+ pStm->Seek(libMove, STREAM_SEEK_SET, NULL);
+ }
+}
diff --git a/private/ole32/com/remote/daytona/makefile b/private/ole32/com/remote/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/remote/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/remote/daytona/sources b/private/ole32/com/remote/daytona/sources
new file mode 100644
index 000000000..344c0b325
--- /dev/null
+++ b/private/ole32/com/remote/daytona/sources
@@ -0,0 +1,88 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= remote
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES = ..\..\..\common\daytona;..\..\..\ih;..;..\..\inc;..\..\idl\daytona;..\..\class;..\..\objact
+
+!include ..\..\..\daytona.inc
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+
+SOURCES= \
+ ..\channelb.cxx \
+ ..\chancont.cxx \
+ ..\callcont.cxx \
+ ..\callmain.cxx \
+ ..\imchnl.cxx \
+ ..\sichnl.cxx \
+ ..\service.cxx \
+ ..\endpnt.cxx \
+ ..\remhdlr.cxx \
+ ..\coapi.cxx \
+ ..\dd.cxx \
+ ..\stdid.cxx \
+ ..\threads.cxx \
+ ..\idtable.cxx \
+ ..\orpc_dbg.c \
+ ..\rpchelp.cxx \
+ ..\ipmrshl.cxx \
+ ..\islocalp.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+
+!include ..\..\precomp2.inc
diff --git a/private/ole32/com/remote/dd.cxx b/private/ole32/com/remote/dd.cxx
new file mode 100644
index 000000000..be3c69a08
--- /dev/null
+++ b/private/ole32/com/remote/dd.cxx
@@ -0,0 +1,95 @@
+//+-------------------------------------------------------------------
+//
+// File: dd.cxx
+//
+// Contents: Destructors for CListEntry and CListHead
+//
+// Classes: None.
+//
+// Functions: CListEntry::~CListEntry -- destructor for entry in list
+// CListHead::~CListHead -- destructor for entire list
+//
+// History: 02-Jan-92 Ricksa Created
+//
+//--------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include "dd.hxx"
+
+//+-------------------------------------------------------------------
+//
+// Member: CListEntry::~CListEntry
+//
+// Synopsis: Free list entry
+//
+// Effects: Item is removed from list and the entry is freed.
+//
+// Arguments: None.
+//
+// Requires: A valid list entry.
+//
+// Returns: Nothing.
+//
+// Signals: None.
+//
+// Modifies: Makes object point to itself.
+//
+// Derivation: None.
+//
+// Algorithm: Call delete_self method and then free memory.
+//
+// History: 02-Jan-92 Ricksa Created
+//
+// Notes: This destructor is virtual to allow derived class
+// objects to be deleted by a pointer to CListEntry.
+//
+//--------------------------------------------------------------------
+EXPORTIMP CListEntry::~CListEntry(void)
+{
+ delete_self();
+}
+
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CListHead::~CListHead
+//
+// Synopsis: Destructor for list head class
+//
+// Effects: All objects pointed to by the list are freed.
+//
+// Arguments: None.
+//
+// Requires: Valid CListHead object
+//
+// Returns: Nothing.
+//
+// Signals: None.
+//
+// Modifies: Calls destructors for all entries in the list.
+//
+// Derivation: None.
+//
+// Algorithm: While there are items in the list, call delete.
+//
+// History: 02-Jan-92 Ricksa Created
+//
+// Notes: This destructor leverages off the fact that
+// the CListEntry destructor is virtual so that
+// the destructor for the derived class object
+// will be called.
+//
+//--------------------------------------------------------------------
+CListHead::~CListHead(void)
+{
+ CListEntry *linkp;
+
+ while ((linkp = first()) != NULL)
+ {
+ delete linkp;
+ }
+}
diff --git a/private/ole32/com/remote/dd.hxx b/private/ole32/com/remote/dd.hxx
new file mode 100644
index 000000000..38e9c7b16
--- /dev/null
+++ b/private/ole32/com/remote/dd.hxx
@@ -0,0 +1,374 @@
+//+-------------------------------------------------------------------
+//
+// File: dd.hxx
+//
+// Contents: Defintions of classes for simply doubly linked list.
+//
+// Classes: CListEntry -- entry in doubly linked list.
+// CListHead -- head of doubly linked list.
+// DERIVED_LIST_HEAD -- macro for defining lists of things.
+//
+// Functions: CListEntry::next -- get next entry after the this entry.
+// CListEntry::prev -- get entry previous to the this entry.
+// CListEntry::insert_after -- insert after this entry.
+// CListEntry::insert_before -- intert before this entry.
+// CListEntry::delete_self -- remove this entry from list.
+// CListHead::insert_at_end -- insert at end of list
+// CListHead::insert_at_head -- insert at list beginning
+// CListHead::first -- return pointer to first item in list
+// CListHead::next -- return pointer to next item in list
+//
+// History: 02-Jan-92 Ricksa Created
+
+//
+//--------------------------------------------------------------------
+#ifndef __DD__
+#define __DD__
+
+
+
+//+-------------------------------------------------------------------
+//
+// Class: CListEntry
+//
+// Purpose: Provide entry into doubly linked list.
+//
+// Interface: next -- return pointer to next item in the list
+// prev -- return pointer to previous item in the list
+// insert_after -- insert after this item.
+// insert_before -- insert before this item.
+// delete_self -- delete this item from this list.
+//
+// History: 02-Jan-92 Ricksa Created
+//
+// Notes: This class implments an individual entry in a doubly
+// linked circular list and must be used in conjunction
+// with the CListHead class for proper behavior.
+//
+//--------------------------------------------------------------------
+class CListEntry
+{
+public:
+
+ CListEntry(void);
+
+ EXPORTDEF virtual ~CListEntry(void);
+
+ CListEntry * next(void);
+
+ CListEntry * prev(void);
+
+ void insert_after(CListEntry *new_node);
+
+ void insert_before(CListEntry *new_node);
+
+ void delete_self(void);
+
+ BOOL connected(void);
+
+private:
+
+ CListEntry * _next;
+
+ CListEntry * _prev;
+
+};
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CListEntry::CListEntry
+//
+// Synopsis: Initialize and entry's pointers
+//
+// History: 02-Jan-92 Ricksa Created
+//
+//--------------------------------------------------------------------
+inline CListEntry::CListEntry(void)
+{
+ _prev = _next = this;
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CListEntry::next
+//
+// Synopsis: Get next entry in list
+//
+// History: 02-Jan-92 Ricksa Created
+//
+//--------------------------------------------------------------------
+inline CListEntry *CListEntry::next(void)
+{
+ return _next;
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CListEntry::prev
+//
+// Synopsis: Get previous entry in list
+//
+// History: 02-Jan-92 Ricksa Created
+//
+//--------------------------------------------------------------------
+inline CListEntry *CListEntry::prev(void)
+{
+ return _prev;
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CListEntry::insert_after
+//
+// Synopsis: Insert new entry after this entry
+//
+// History: 02-Jan-92 Ricksa Created
+//
+//--------------------------------------------------------------------
+inline void CListEntry::insert_after(CListEntry *new_node)
+{
+ new_node->_next = _next;
+ new_node->_prev = this;
+ _next = (new_node->_next)->_prev = new_node;
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CListEntry::insert_before
+//
+// Synopsis: Insert new entry before this entry
+//
+// History: 02-Jan-92 Ricksa Created
+//
+//--------------------------------------------------------------------
+inline void CListEntry::insert_before(CListEntry *new_node)
+{
+ new_node->_next = this;
+ new_node->_prev = _prev;
+ _prev = (new_node->_prev)->_next = new_node;
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CListEntry::delete_self
+//
+// Synopsis: Remove this entry from the list
+//
+// History: 02-Jan-92 Ricksa Created
+//
+//--------------------------------------------------------------------
+inline void CListEntry::delete_self(void)
+{
+ _prev->_next = _next;
+ _next->_prev = _prev;
+ _next = this;
+ _prev = this;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CListEntry::connected
+//
+// Synopsis: returns TRUE if the entry is in a list, FALSE otherwise
+//
+// History: 02-Jan-92 Ricksa Created
+//
+//--------------------------------------------------------------------
+inline BOOL CListEntry::connected(void)
+{
+ return (_next != this);
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Class: CListHead
+//
+// Purpose: Head of list of CListEntry
+//
+// Interface: insert_at_end -- insert entry at the end of the list
+// insert_at_head -- insert entry at be head of the list
+// first -- return first entry in the list
+// next -- return next entry in the list
+//
+// History: 02-Jan-92 Ricksa Created
+//
+// Notes: For enumeration of the list, this object must be
+// used for correct behavior.
+//
+//--------------------------------------------------------------------
+class CListHead
+{
+public:
+
+ CListHead(void) { }
+
+ virtual ~CListHead(void);
+
+ void insert_at_end(CListEntry *objp);
+
+ void insert_at_head(CListEntry *objp);
+
+ void no_cleanup( void );
+
+ CListEntry *first(void);
+
+ CListEntry *next(CListEntry *objp);
+
+private:
+
+ CListEntry _head;
+
+};
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CListHead::insert_at_end
+//
+// Synopsis: Insert entry at end of the list.
+//
+// History: 02-Jan-92 Ricksa Created
+//
+//--------------------------------------------------------------------
+inline void CListHead::insert_at_end(CListEntry *objp)
+{
+ (_head.prev())->insert_after(objp);
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CListHead::insert_at_head
+//
+// Synopsis: Insert entry at the beginning of the list
+//
+// History: 02-Jan-92 Ricksa Created
+//
+//--------------------------------------------------------------------
+inline void CListHead::insert_at_head(CListEntry *objp)
+{
+ (_head.next())->insert_before(objp);
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CListHead::no_cleanup
+//
+// Synopsis: Leak the list so its destructors don't get called.
+// This is useful on process detach when you don't want
+// to do any cleanup (because someone else might crash).
+//
+// History: 7 Nov 94 AlexMit Created
+//
+//--------------------------------------------------------------------
+inline void CListHead::no_cleanup()
+{
+ _head.delete_self();
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CListHead::first
+//
+// Synopsis: Get the first item in the list
+//
+// History: 02-Jan-92 Ricksa Created
+//
+//--------------------------------------------------------------------
+inline CListEntry *CListHead::first(void)
+{
+ CListEntry *np = _head.next();
+
+ return (np != &_head) ? np : NULL;
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CListHead::next
+//
+// Synopsis: Get the next item on the list
+//
+// History: 02-Jan-92 Ricksa Created
+//
+//--------------------------------------------------------------------
+inline CListEntry *CListHead::next(CListEntry *objp)
+{
+ CListEntry *np = objp->next();
+
+ return (np != &_head) ? np : NULL;
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Class: DERIVED_LIST_HEAD
+//
+// Purpose: Template macro for defining classes which want
+// to return list entries as their "real" identities
+// rather than a pointer to a list entry.
+//
+// Interface: first -- return pointer to first entry in list
+// next -- return pointer to next entry in list
+//
+// History: 02-Jan-92 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+#define DERIVED_LIST_HEAD(name, classn) \
+class name : public CListHead \
+{ \
+public: \
+\
+ name(void) { } \
+\
+ ~name(void) { } \
+\
+ classn *first(void) \
+ { \
+ return (classn *) CListHead::first(); \
+ } \
+\
+ classn *next(classn *objp) \
+ { \
+ return (classn *) CListHead::next(objp); \
+ } \
+};
+
+#endif // __DD__
diff --git a/private/ole32/com/remote/dde/client/cnct_tbl.cxx b/private/ole32/com/remote/dde/client/cnct_tbl.cxx
new file mode 100644
index 000000000..bc7200223
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/cnct_tbl.cxx
@@ -0,0 +1,182 @@
+// cnct_tbl.cpp
+//
+// class CConnectionTable
+//
+// CConnectionTable maps connection numbers (as returned by ::Advise())
+// to clipformat's for DDE advise connections.
+
+#include "ddeproxy.h"
+#include "cnct_tbl.h"
+
+ASSERTDATA
+
+#define grfMemFlags (GMEM_MOVEABLE | GMEM_ZEROINIT)
+
+// number of INFO entries to grow by
+#define cinfoBlock 10
+
+typedef struct INFO
+{
+ BOOL fUsed; // is this table entry used?
+ DWORD dwConnection; // search key
+ CLIPFORMAT cf; // corresponding cf, for use in DDE_(UN)ADVISE
+ DWORD grfAdvf; // ON_CHANGE or ON_SAVE or ON_CLOSE
+} INFO, FAR* PINFO;
+
+
+
+CDdeConnectionTable::CDdeConnectionTable ()
+{
+ m_h = GlobalAlloc (grfMemFlags, cinfoBlock * sizeof(INFO));
+ Assert (m_h);
+ m_cinfo=cinfoBlock;
+}
+
+
+CDdeConnectionTable::~CDdeConnectionTable ()
+{
+ Assert(m_h);
+ m_h =GlobalFree (m_h);
+ Assert (m_h==NULL);
+ m_cinfo=0;
+}
+
+
+
+
+INTERNAL CDdeConnectionTable::Add
+ (DWORD dwConnection,
+ CLIPFORMAT cf,
+ DWORD grfAdvf)
+{
+ Start:
+ PINFO rginfo;
+
+ if (NULL==(rginfo = (PINFO) GlobalLock(m_h)))
+ {
+ Puts ("ERROR: CDdeConnectionTable::Add out of memory\n");
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ // Look for an empty table entry
+ for (DWORD i=0; i<m_cinfo; i++)
+ {
+ if (!rginfo[i].fUsed)
+ {
+ rginfo[i].fUsed = TRUE;
+ rginfo[i].dwConnection = dwConnection;
+ rginfo[i].cf = cf;
+ rginfo[i].grfAdvf = grfAdvf;
+ break;
+ }
+ else
+ {
+ Assert (rginfo[i].dwConnection != dwConnection);
+ }
+ }
+ GlobalUnlock (m_h);
+ if (i==m_cinfo) // if no empty entry found
+ {
+ Puts ("Growing the connection table\n");
+ m_h = GlobalReAlloc (m_h,(m_cinfo += cinfoBlock) * sizeof(INFO),
+ grfMemFlags);
+ if (m_h==NULL)
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ goto Start;
+ }
+ else
+ {
+ return NOERROR;
+ }
+}
+
+
+
+
+INTERNAL CDdeConnectionTable::Subtract
+ (DWORD dwConnection,
+ CLIPFORMAT FAR* pcf, // out parm
+ DWORD FAR* pgrfAdvf) // out parm
+{
+ PINFO rginfo;
+ if (dwConnection==0)
+ {
+ Puts ("CDdeConnectionTable::Subtract called with dwConnection==0\n");
+ return ReportResult(0, E_INVALIDARG, 0, 0);
+ }
+
+ if (NULL==(rginfo = (PINFO) GlobalLock(m_h)))
+ {
+ Assert (0);
+ Puts ("ERROR: CDdeConnectionTable::Subtract out of memory\n");
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ for (DWORD i=0; i<m_cinfo; i++)
+ {
+ if (rginfo[i].fUsed && rginfo[i].dwConnection == dwConnection)
+ {
+ Assert (pcf);
+ *pcf = rginfo[i].cf;
+ Assert (pgrfAdvf);
+ *pgrfAdvf = rginfo[i].grfAdvf;
+ rginfo[i].fUsed = FALSE; // remove this connection
+ GlobalUnlock (m_h);
+ return NOERROR;
+ }
+ }
+ GlobalUnlock (m_h);
+ return ReportResult(0, S_FALSE, 0, 0); // not found
+}
+
+
+
+
+INTERNAL CDdeConnectionTable::Lookup
+ (CLIPFORMAT cf, // search key
+ LPDWORD pdwConnection) // out parm. May be NULL on input
+{
+ PINFO rginfo;
+
+ if (NULL==(rginfo = (PINFO) GlobalLock(m_h)))
+ {
+ Puts ("ERROR: CDdeConnectionTable::Lookup out of memory\n");
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ for (DWORD i=0; i<m_cinfo; i++)
+ {
+ if (rginfo[i].fUsed &&
+ rginfo[i].cf == cf)
+ {
+ if (pdwConnection)
+ *pdwConnection = rginfo[i].dwConnection;
+ GlobalUnlock (m_h);
+ return NOERROR;
+ }
+ }
+ GlobalUnlock (m_h);
+ return ReportResult(0, S_FALSE, 0, 0); // not found
+}
+
+
+
+INTERNAL CDdeConnectionTable::Erase
+ (void)
+{
+ PINFO rginfo;
+ Assert (wIsValidHandle(m_h, NULL));
+ if (NULL==(rginfo = (PINFO) GlobalLock(m_h)))
+ {
+ Puts ("ERROR: CDdeConnectionTable::Lookup out of memory\n");
+ Assert (0);
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ for (DWORD i=0; i<m_cinfo; i++)
+ {
+ rginfo[i].fUsed = FALSE;
+ }
+ GlobalUnlock (m_h);
+ return NOERROR;
+}
+
diff --git a/private/ole32/com/remote/dde/client/cnct_tbl.h b/private/ole32/com/remote/dde/client/cnct_tbl.h
new file mode 100644
index 000000000..656b9ce89
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/cnct_tbl.h
@@ -0,0 +1,27 @@
+// cnct_tbl.h
+
+// CConnectionTable maps connection numbers (as returned by ::Advise())
+// to clipformat's for DDE advise connections.
+
+#ifndef fCnct_tbl_h
+#define fCnct_tbl_h
+
+class FAR CDdeConnectionTable : public CPrivAlloc
+{
+ public:
+ CDdeConnectionTable();
+ ~CDdeConnectionTable();
+
+ INTERNAL Add (DWORD dwConnection, CLIPFORMAT cf, DWORD grfAdvf);
+ INTERNAL Subtract (DWORD dwConnection, CLIPFORMAT FAR* pcf, DWORD FAR* pgrfAdvf);
+ INTERNAL Lookup (CLIPFORMAT cf, LPDWORD pdwConnection);
+ INTERNAL Erase (void);
+
+ private:
+ HANDLE m_h; // handle to the table
+ DWORD m_cinfo; // total number of INFO entries
+};
+
+
+#endif
+
diff --git a/private/ole32/com/remote/dde/client/daytona/makefile b/private/ole32/com/remote/dde/client/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/remote/dde/client/daytona/sources b/private/ole32/com/remote/dde/client/daytona/sources
new file mode 100644
index 000000000..468aff4b2
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/daytona/sources
@@ -0,0 +1,83 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= ddecli
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES = ..\..\server;..\..\..\..\..\common\daytona;..\..\..\..\..\ih;..\..\..;..\..\..\..\inc;..\..\..\..\idl\daytona;..\..\..\..\class;..\..\..\..\objact;..\..\..\..\..\ole232\inc;..\..\..;
+
+!include ..\..\..\..\..\daytona.inc
+
+C_DEFINES= -DOLE_DDE_NO_GLOBAL_TRACKING=1\
+ $(C_DEFINES) \
+
+
+SOURCES= \
+ ..\cnct_tbl.cxx \
+ ..\ddedo.cxx \
+ ..\ddeioc.cxx \
+ ..\ddemnker.cxx \
+ ..\ddeoo.cxx \
+ ..\ddeproxy.cxx \
+ ..\ddechc.cxx \
+ ..\ddestg.cxx \
+ ..\ddewnd.cxx \
+ ..\ddeworkr.cxx \
+ ..\modallp.cxx \
+ ..\packmnkr.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+# PRECOMPILED_INCLUDE= ..\headers.cxx
+
+
diff --git a/private/ole32/com/remote/dde/client/ddechc.cxx b/private/ole32/com/remote/dde/client/ddechc.cxx
new file mode 100644
index 000000000..0034b5ef3
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/ddechc.cxx
@@ -0,0 +1,265 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: DdeChC.cxx
+//
+// Contents: CDdeChannelControl implementation for DDE. This
+// implementation requires no instance data, therefore it is
+// intended to be static.
+//
+// Functions:
+//
+// History: 08-May-94 Johann Posch (johannp) Created
+// 10-May-94 KevinRo Made simpler
+// 29-May-94 KevinRo Added DDE Server support
+//
+//--------------------------------------------------------------------------
+#include "ddeproxy.h"
+
+//
+// All threads can use a single instance of this class. Therefore, we
+// provide the following global variable that generates the instance.
+//
+
+CDdeChannelControl g_CDdeChannelControl;
+
+STDMETHODIMP CDdeChannelControl::QueryInterface( THIS_ REFIID riid, LPVOID FAR* ppvObj)
+{
+ if (IsEqualIID(riid, IID_IUnknown)
+// || IsEqualIID(riid, IID_IChannelControl)
+ )
+ {
+ *ppvObj = (IChannelControl *) this;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP_(ULONG) CDdeChannelControl::Release( THIS )
+{
+ return(1);
+}
+
+STDMETHODIMP_(ULONG) CDdeChannelControl::AddRef( THIS )
+{
+ return 1;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeChannelControl::DispatchCall
+//
+// Synopsis: DispatchCall is called to handle incoming calls.
+//
+// Effects: Dispatches a call to the specified in the DispatchData.
+// This function is the result of a call in OnData(), which
+// processes incoming calls from the OLE 1.0 server.
+//
+// Arguments: [pDispData] -- Points to the dispatch data structure
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-16-94 JohannP Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CDdeChannelControl::DispatchCall( PDISPATCHDATA pDispData )
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeChannelControl::DispatchCall(%x,pDispData=%x)\n",
+ this,
+ pDispData));
+
+ intrAssert(pDispData != NULL);
+ POLE1DISPATCHDATA pData = (POLE1DISPATCHDATA)pDispData->pData;
+ intrAssert(pData != NULL);
+
+ switch (pData->wDispFunc)
+ {
+ case DDE_DISP_SENDONDATACHANGE: // OnDataChange
+ {
+ PDDEDISPATCHDATA pDData = (PDDEDISPATCHDATA)pDispData->pData;
+ return pDData->pCDdeObject->SendOnDataChange(pDData->iArg);
+ }
+
+ case DDE_DISP_OLECALLBACK: // OleCallBack
+ {
+ PDDEDISPATCHDATA pDData = (PDDEDISPATCHDATA)pDispData->pData;
+ return pDData->pCDdeObject->OleCallBack(pDData->iArg,NULL);
+ }
+
+ //
+ // The server window has an incoming call. Look in dde\server\srvr.cxx
+ //
+ case DDE_DISP_SRVRWNDPROC:
+ return(SrvrDispatchIncomingCall((PSRVRDISPATCHDATA)pDispData->pData));
+ //
+ // This dispatches to a Document window
+ //
+ case DDE_DISP_DOCWNDPROC:
+ return(DocDispatchIncomingCall((PDOCDISPATCHDATA)pDispData->pData));
+
+ default:
+ intrAssert(!"Unknown wDispFunc");
+ }
+ return E_FAIL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeChannelControl::OnEvent
+//
+// Synopsis: OnEvent should never be called on this channel
+//
+// Effects:
+//
+// Arguments: [pCallData] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-16-94 JohannP Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CDdeChannelControl::OnEvent( PCALLDATA pCallData )
+{
+ // should be never called
+
+ intrAssert(!"CDdeChannelControl::OnEvent( PCALLDATA pCallData ) not implemented\n");
+ return E_FAIL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeChannelControl::TransmitCall
+//
+// Synopsis: Transmit the parameters to the server.
+//
+// Effects: This function transmits the pCallData to the server. This
+// may be called multiple times, if a retry is required.
+//
+// A by product of the way the DDE channel was implemented
+// atop existing code is that the existing code may transmit
+// the first round of data on its own. If it does this, it
+// will set the fInitialSend to TRUE. Therefore, if this
+// routine sees the flag as true, it will not send the data,
+// but will set the flag to FALSE for a possible retry later.
+//
+// Arguments: [pCallData] -- Points to the DDE specific call data
+//
+// Requires:
+//
+// Returns: If the Post fails, this function returns E_FAIL
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-16-94 JohannP Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CDdeChannelControl::TransmitCall( PCALLDATA pCallData )
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeChannelControl::TransmitCall(%x,pCallData=%x)\n",
+ this,
+ pCallData));
+ // reset the event
+ pCallData->Event = 0;
+ pCallData->fDirectedYield = FALSE;
+
+ PDDECALLDATA pDdeCD = (PDDECALLDATA)pCallData->pRpcMsg;
+
+ //
+ // If the routine wPostServerMessage has already posted the
+ // first send, then fInitialSend will be TRUE. In that case,
+ // don't TransmitCall() this time, but reset the flag for
+ // future retries.
+ //
+
+ if (!pDdeCD->fInitialSend)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::TransmitCall(%x) PostMessage(%x,%x,%x,%x)\n",
+ this,
+ pDdeCD->hwndSvr,
+ pDdeCD->wMsg,
+ (WPARAM) pDdeCD->hwndCli,
+ pDdeCD->lParam));
+
+ if(!PostMessage (pDdeCD->hwndSvr,
+ pDdeCD->wMsg,
+ (WPARAM) pDdeCD->hwndCli,
+ pDdeCD->lParam))
+ {
+ return(E_FAIL);
+ }
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::TransmitCall(%x) Already Posted Message\n",
+ this));
+
+ pDdeCD->fInitialSend = FALSE;
+ }
+
+ //
+ // Figure out if we want the call control to do a directed yield.
+ // Do this only if the server is in the same VDM as us.
+ //
+
+
+ if (IsWOWProcess())
+ {
+ DWORD dwPID, dwTID;
+ dwTID = GetWindowThreadProcessId(pDdeCD->hwndSvr, &dwPID);
+
+ if (dwPID == GetCurrentProcessId())
+ {
+ // Make sure we have the right thread id to yield to
+ pCallData->TIDCallee = dwTID;
+
+ // same VDM so do directed yield
+ pCallData->fDirectedYield = TRUE;
+ }
+ }
+
+ return NOERROR;
+}
diff --git a/private/ole32/com/remote/dde/client/ddechc.hxx b/private/ole32/com/remote/dde/client/ddechc.hxx
new file mode 100644
index 000000000..d896f2378
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/ddechc.hxx
@@ -0,0 +1,135 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: DdeChC.cxx
+//
+// Contents: CDdeChannelControl implementation for DDE. This
+// implementation requires no instance data, therefore it is
+// intended to be static.
+//
+// Functions:
+//
+// History: 08-May-94 Johann Posch (johannp) Created
+// 10-May-94 KevinRo Made simpler and commented
+//
+//--------------------------------------------------------------------------
+#ifndef __DDECHC_HXX__
+#define __DDECHC_HXX__
+
+class CDdeObject;
+//
+// The following are the possible callbacks that would be supported by
+// the CDdeObject
+//
+
+typedef enum
+{
+ DDE_DISP_SENDONDATACHANGE = 1,
+ DDE_DISP_OLECALLBACK = 2 ,
+ DDE_DISP_SRVRWNDPROC = 3 ,
+ DDE_DISP_DOCWNDPROC = 4
+} DDE_DISPATCH_FUNC;
+
+
+//
+// The following defines a base class for the OLE 1.0 support
+//
+
+typedef struct tagOLE1DISPATCHDATA
+{
+ DDE_DISPATCH_FUNC wDispFunc;
+}OLE1DISPATCHDATA, *POLE1DISPATCHDATA;
+
+//
+// The following structure is used by OLE 1.0 server support code
+//
+
+typedef struct tagDDEDISPATCHDATA : public CPrivAlloc, public OLE1DISPATCHDATA
+{
+ CDdeObject *pCDdeObject;
+ UINT iArg;
+} DDEDISPATCHDATA, *PDDEDISPATCHDATA;
+
+
+//
+// The following structure is used by the OLE 1.0 client support code
+// to dispatch incoming calls to Execute from the server window.
+//
+
+typedef struct tagSRVRDISPATCHDATA : public OLE1DISPATCHDATA,public CPrivAlloc
+{
+ HWND hwnd;
+ HANDLE hData;
+ HWND wParam;
+ LPSRVR lpsrvr;
+} SRVRDISPATCHDATA, *PSRVRDISPATCHDATA;
+
+INTERNAL SrvrDispatchIncomingCall(PSRVRDISPATCHDATA psdd);
+
+
+//
+// The following structure is used by the OLE 1.0 client support code
+// to dispatch incoming calls to a document window
+//
+
+typedef struct tagDOCDISPATCHDATA : public OLE1DISPATCHDATA,public CPrivAlloc
+{
+ HWND hwnd;
+ ULONG msg;
+ WPARAM wParam;
+ LPARAM lParam;
+ HANDLE hdata; // If already determined, these two hold
+ ATOM aItem; // valid data. All depends on the message
+ LPCLIENT lpclient;
+} DOCDISPATCHDATA, *PDOCDISPATCHDATA;
+
+INTERNAL DocDispatchIncomingCall(PDOCDISPATCHDATA psdd);
+
+
+
+//
+// DDECALLDATA is all the information needed to transmit the outbound call
+// to the server. Since this DDE channel uses PostMessage, the members
+// should look amazingly alot like the parameters to PostMessage.
+//
+// The hwndCli is used for setting callback information.
+// fInitialSend is used by IChannelControl::Transmit().
+//
+typedef struct tagDDECALLDATA : public CPrivAlloc
+{
+ HWND hwndSvr; // Server DDE window
+ WORD wMsg; // Post parameters
+ WPARAM wParam;
+ LPARAM lParam;
+
+ HWND hwndCli; // Handle to client side window
+ BOOL fInitialSend; // True if the first post has been made
+ // already.
+} DDECALLDATA, *PDDECALLDATA;
+
+
+class CDdeChannelControl : public IChannelControl
+{
+ public:
+ // IUnknown methods
+ STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) ( void );
+ STDMETHOD_(ULONG,Release) ( void );
+
+ // IChannelControl
+ STDMETHOD (DispatchCall)( PDISPATCHDATA );
+ STDMETHOD (OnEvent) ( PCALLDATA );
+ STDMETHOD (TransmitCall)( PCALLDATA );
+};
+
+//
+// All threads can use a single instance of this class. Therefore, we
+// provide the following global variable
+//
+
+extern CDdeChannelControl g_CDdeChannelControl;
+
+#endif // __DDECHC__HXX__
+
diff --git a/private/ole32/com/remote/dde/client/ddecnvrt.cxx b/private/ole32/com/remote/dde/client/ddecnvrt.cxx
new file mode 100644
index 000000000..119c67d15
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/ddecnvrt.cxx
@@ -0,0 +1,348 @@
+
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddecnvrt.cpp
+
+Abstract:
+
+ This module contains the code to read/write PBrush, MSDraw native data
+ formats. This module also contains PBrush native format <->DIbFile stream,
+ and MSDraw native format <-> placeable metafile stream conversion routines.
+
+Author:
+
+ Srini Koppolu (srinik) 06/29/1993
+
+Revision History:
+
+--*/
+
+#ifndef _MAC
+
+
+/************************ FILE FORMATS **********************************
+
+
+Normal Metafile (memory or disk based):
+
+ ------------ ---------------
+ | METAHEADER | Metafile bits |
+ ------------ ---------------
+
+Placeable Metafile:
+
+ --------------------- -----------------
+ | PLACEABLEMETAHEADER | Normal metafile |
+ --------------------- -----------------
+
+Memory Based DIB:
+
+ ------------------ --------------- ----------
+ | BITMAPINFOHEADER | RGBQUAD array | DIB bits |
+ ------------------ --------------- ----------
+
+DIB file format:
+
+ ------------------ ------------------
+ | BITMAPFILEHEADER | Memory based DIB |
+ ------------------ ------------------
+
+Ole10NativeStream Format:
+
+ -------- ----------------------
+ | dwSize | Object's Native data |
+ -------- ----------------------
+
+PBrush Native data format:
+
+ -----------------
+ | Dib File format |
+ -----------------
+
+MSDraw Native data format:
+
+ --------------------- ------------- ------------- -----------------
+ | mapping mode (WORD) | xExt (WORD) | yExt (WORD) | Normal metafile |
+ --------------------- ------------- ------------- -----------------
+
+
+*****************************************************************************/
+
+#include <ole2int.h>
+
+INTERNAL UtGetHMFPICTFromMSDrawNativeStm
+ (LPSTREAM pstm, DWORD dwSize, HANDLE FAR* lphdata)
+{
+ HRESULT error;
+ WORD mfp[3]; // mm, xExt, yExt
+ HMETAFILE hMF = NULL;
+
+ *lphdata = NULL;
+
+ if (error = pstm->Read(mfp, sizeof(mfp), NULL))
+ return error;
+
+ dwSize -= sizeof(mfp);
+
+ if (error = UtGetHMFFromMFStm(pstm, dwSize, FALSE, (void **)&hMF))
+ return error;
+
+ AssertSz(mfp[0] == MM_ANISOTROPIC, "invalid map mode in MsDraw native data");
+
+ if (*lphdata = UtGetHMFPICT(hMF, TRUE, (int) mfp[1], (int) mfp[2]))
+ return NOERROR;
+
+ return ResultFromScode(E_OUTOFMEMORY);
+}
+
+
+INTERNAL UtPlaceableMFStmToMSDrawNativeStm
+ (LPSTREAM pstmPMF, LPSTREAM pstmMSDraw)
+{
+ DWORD dwSize; // size of metafile bits excluding the placeable MF header
+ LONG xExt;
+ LONG yExt;
+ WORD wBuf[5]; // dwSize(DWORD), mm(int), xExt(int), yExt(int)
+ HRESULT error;
+
+ if (error = UtGetSizeAndExtentsFromPlaceableMFStm(pstmPMF, &dwSize,
+ &xExt, &yExt))
+ return error;
+
+ *((DWORD FAR*) wBuf) = dwSize + 3*sizeof(WORD);
+ wBuf[2] = MM_ANISOTROPIC;
+ wBuf[3] = (int) xExt;
+ wBuf[4] = (int) yExt;
+
+ if (error = pstmMSDraw->Write(wBuf, sizeof(wBuf), 0))
+ return error;
+
+ ULARGE_INTEGER ularge_int;
+ ULISet32(ularge_int, dwSize);
+ if ((error = pstmPMF->CopyTo(pstmMSDraw, ularge_int,
+ NULL, NULL)) == NOERROR)
+ StSetSize(pstmMSDraw);
+
+ return error;
+
+}
+
+
+INTERNAL UtDIBFileStmToPBrushNativeStm
+ (LPSTREAM pstmDIBFile, LPSTREAM pstmPBrush)
+{
+ BITMAPFILEHEADER bfh;
+ HRESULT error;
+
+ if (error = pstmDIBFile->Read(&bfh, sizeof(bfh), 0))
+ return error;
+
+ // seek to the begining of the stream
+ LARGE_INTEGER large_int;
+ LISet32( large_int, 0);
+ if (error = pstmDIBFile->Seek(large_int, STREAM_SEEK_SET, 0))
+ return error;
+
+ if (error = pstmPBrush->Write(&(bfh.bfSize), sizeof(DWORD), 0))
+ return error;
+
+ ULARGE_INTEGER ularge_int;
+ ULISet32(ularge_int, bfh.bfSize);
+
+ if ((error = pstmDIBFile->CopyTo(pstmPBrush, ularge_int,
+ NULL, NULL)) == NOERROR)
+ StSetSize(pstmPBrush);
+
+ return error;
+}
+
+
+
+INTERNAL UtContentsStmTo10NativeStm
+ (LPSTORAGE pstg, REFCLSID rclsid, BOOL fDeleteSrcStm, UINT FAR* puiStatus)
+{
+ CLIPFORMAT cf;
+ LPOLESTR lpszUserType = NULL;
+ HRESULT error;
+ LPSTREAM pstmSrc = NULL;
+ LPSTREAM pstmDst = NULL;
+
+ *puiStatus = NULL;
+
+ if (error = ReadFmtUserTypeStg(pstg, &cf, &lpszUserType))
+ return error;
+
+
+ if (! ((cf == CF_DIB && rclsid == CLSID_PBrush)
+ || (cf == CF_METAFILEPICT && rclsid == CLSID_MSDraw))) {
+ error = ResultFromScode(DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+
+ if (error = pstg->OpenStream(CONTENTS_STREAM, NULL,
+ (STGM_READ|STGM_SHARE_EXCLUSIVE),
+ 0, &pstmSrc)) {
+ *puiStatus |= CONVERT_NOSOURCE;
+
+ // check whether OLE10_NATIVE_STREAM exists
+ if (pstg->OpenStream(OLE10_NATIVE_STREAM, NULL,
+ (STGM_READ|STGM_SHARE_EXCLUSIVE), 0, &pstmDst))
+ *puiStatus |= CONVERT_NODESTINATION;
+ else {
+ pstmDst->Release();
+ pstmDst = NULL;
+ }
+
+ goto errRtn;
+ }
+
+ if (error = OpenOrCreateStream(pstg, OLE10_NATIVE_STREAM, &pstmDst)) {
+ *puiStatus |= CONVERT_NODESTINATION;
+ goto errRtn;
+ }
+
+ if (cf == CF_METAFILEPICT)
+ error = UtPlaceableMFStmToMSDrawNativeStm(pstmSrc, pstmDst);
+ else
+ error = UtDIBFileStmToPBrushNativeStm(pstmSrc, pstmDst);
+
+errRtn:
+ if (pstmDst)
+ pstmDst->Release();
+
+ if (pstmSrc)
+ pstmSrc->Release();
+
+ if (error == NOERROR) {
+ LPOLESTR lpszProgId = NULL;
+ ProgIDFromCLSID(rclsid, &lpszProgId);
+
+ error = WriteFmtUserTypeStg(pstg,
+ RegisterClipboardFormat(lpszProgId),
+ lpszUserType);
+
+ if (lpszProgId)
+ delete lpszProgId;
+ }
+
+ if (error == NOERROR) {
+ if (fDeleteSrcStm)
+ pstg->DestroyElement(CONTENTS_STREAM);
+ } else {
+ pstg->DestroyElement(OLE10_NATIVE_STREAM);
+ }
+
+ if (lpszUserType)
+ delete lpszUserType;
+
+ return error;
+}
+
+
+
+INTERNAL Ut10NativeStmToContentsStm
+ (LPSTORAGE pstg, REFCLSID rclsid, BOOL fDeleteSrcStm)
+{
+ extern CLIPFORMAT cfPBrush;
+ extern CLIPFORMAT cfMSDraw;
+
+ CLIPFORMAT cfOld;
+ CLIPFORMAT cfNew;
+ LPOLESTR lpszUserType = NULL;
+ HRESULT error;
+ LPSTREAM pstmSrc = NULL;
+ LPSTREAM pstmDst = NULL;
+
+
+ if (error = ReadFmtUserTypeStg(pstg, &cfOld, &lpszUserType))
+ return error;
+
+ if (rclsid == CLSID_StaticDib)
+ cfNew = CF_DIB;
+ else if (rclsid == CLSID_StaticMetafile)
+ cfNew = CF_METAFILEPICT;
+ else {
+ AssertSz(FALSE, "Internal Error: this routine shouldn't have been called for this class");
+ return ResultFromScode(E_FAIL);
+ }
+
+ if (cfOld == cfPBrush) {
+ if (cfNew != CF_DIB) {
+ error = ResultFromScode(DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+ } else if (cfOld == cfMSDraw) {
+ if (cfNew != CF_METAFILEPICT) {
+ error = ResultFromScode(DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+ } else {
+ // Converted to static object from some class other than PBrush or
+ // MSDraw. The data must be in a proper format in the CONTENTS
+ // stream.
+ return NOERROR;
+ }
+
+ if (error = pstg->OpenStream(OLE10_NATIVE_STREAM, NULL,
+ (STGM_READ|STGM_SHARE_EXCLUSIVE),
+ 0, &pstmSrc))
+ goto errRtn;
+
+ if (error = OpenOrCreateStream(pstg, CONTENTS_STREAM, &pstmDst))
+ goto errRtn;
+
+ DWORD dwSize;
+ if (error = pstmSrc->Read(&dwSize, sizeof(DWORD), NULL))
+ goto errRtn;
+
+ if (cfOld == cfMSDraw) {
+ WORD mfp[3]; // mm, xExt, yExt
+
+ if (error = pstmSrc->Read(mfp, sizeof(mfp), NULL))
+ goto errRtn;
+
+ dwSize -= sizeof(mfp);
+
+ error = UtMFStmToPlaceableMFStm(pstmSrc, dwSize,
+ (LONG) mfp[1], (LONG) mfp[2], pstmDst);
+
+ } else {
+ // The PBrush native data format is DIB File format. So all we got to
+ // do is CopyTo.
+
+ ULARGE_INTEGER ularge_int;
+ ULISet32(ularge_int, dwSize);
+ if ((error = pstmSrc->CopyTo(pstmDst, ularge_int, NULL,
+ NULL)) == NOERROR)
+ StSetSize(pstmDst);
+ }
+
+errRtn:
+ if (pstmDst)
+ pstmDst->Release();
+
+ if (pstmSrc)
+ pstmSrc->Release();
+
+ if (error == NOERROR) {
+ error = WriteFmtUserTypeStg(pstg, cfNew, lpszUserType);
+
+ if (fDeleteSrcStm)
+ pstg->DestroyElement(OLE10_NATIVE_STREAM);
+
+ } else {
+ pstg->DestroyElement(CONTENTS_STREAM);
+ }
+
+ if (lpszUserType)
+ delete lpszUserType;
+
+ return error;
+}
+
+#endif
+
diff --git a/private/ole32/com/remote/dde/client/ddedo.cxx b/private/ole32/com/remote/dde/client/ddedo.cxx
new file mode 100644
index 000000000..b982d6245
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/ddedo.cxx
@@ -0,0 +1,954 @@
+/*
+ddedo.cpp
+DDE Data Object
+
+copyright (c) 1992 Microsoft Corporation
+
+Abstract:
+
+ This module contains the methods for DdeObject::DataObject
+
+Author:
+
+ Jason Fuller (jasonful) 24-July-1992
+
+*/
+
+#include "ddeproxy.h"
+#include <stddef.h>
+#include "trgt_dev.h"
+
+
+#define f10UserModel
+// Should we ignore a request by a 2.0 client to get advise-on-change,
+// so that the user must do an explicit File/Update or File/Close?
+// Probably yes, because:
+// 1) Advise-on-change can be expensive for apps like PaintBrush.
+// 2) It is confusing if the container asks for change updates
+// ONLY on presentation and not on native because when the user
+// closes the server and is asked "Do you want to update?" he'll say no
+// because the picture LOOKS correct even though the container does not
+// have the native data.
+// 3) Excel: if A1 is the first cell you create, changes to other cells
+// will not be sent to the client until you change A1 again.
+// If advises are only sent explicitly, then all the cells extant at that
+// time will be considered part of the object.
+
+
+ASSERTDATA
+
+
+//
+// DataObject methods
+//
+
+STDUNKIMPL_FORDERIVED(DdeObject, DataObjectImpl)
+
+
+static inline INTERNAL_(BOOL) NotEqual
+ (DVTARGETDEVICE FAR* ptd1,
+ DVTARGETDEVICE FAR* ptd2)
+{
+ if (NULL==ptd1 && NULL==ptd2)
+ return FALSE;
+ else if ((ptd1 && !ptd2)
+ || (ptd2 && !ptd1)
+ || (ptd1->tdSize != ptd2->tdSize))
+ {
+ return TRUE;
+ }
+ else
+#ifdef WIN32
+ return 0 != memcmp(ptd1, ptd2, (size_t)ptd1->tdSize);
+#else
+ return 0 != _fmemcmp(ptd1, ptd2, (size_t)ptd1->tdSize);
+#endif
+}
+
+
+
+// GetData
+//
+// The data is copied out of a private cache consisting of
+// DdeObject::m_hNative, DdeObject::m_hPict, and DdeObject::m_hExtra.
+// If the cache is empty, data is requested using WM_DDE_REQUEST.
+// The cache should only be empty before the first DDE_DATA message
+// is received.
+// See DdeObject::KeepData()
+//
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::GetData
+ (LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetData(%x,pformatetcIn=%x)\n",
+ this,pformatetcIn));
+
+lStart:
+ intrDebugOut((DEB_ITRACE,"::GetData(%x)lStart\n",this));
+
+ LPSTR lpGlobal=NULL;
+ HRESULT hres;
+ VDATEPTROUT (pmedium, STGMEDIUM);
+ pmedium->tymed = TYMED_NULL;
+ pmedium->pUnkForRelease = NULL;
+
+ if ((hres = wVerifyFormatEtc (pformatetcIn)) != NOERROR)
+ {
+ goto exitRtn;
+ }
+
+ hres = E_UNEXPECTED; // assume error unless a clipboard format is found.
+
+ if (DVASPECT_ICON & pformatetcIn->dwAspect)
+ {
+ hres = GetDefaultIcon(m_pDdeObject->m_clsid, NULL, &pmedium->hGlobal);
+ if (hres != NOERROR)
+ {
+ goto exitRtn;
+ }
+ hres = NOERROR;
+ goto lDone;
+ }
+ if (m_pDdeObject->m_fGotCloseData)
+ {
+ // If we already got DDE_DATA on close, don't try requesting more
+ // data. (MSDraw will give a bogus metafile.)
+ hres=OLE_E_NOTRUNNING;
+ goto exitRtn;
+ }
+
+ if (NotEqual (pformatetcIn->ptd, m_pDdeObject->m_ptd))
+ {
+ // If caller is asking for a different target device
+ // (We assume a different pointer points to a different target device)
+
+ if (NOERROR!=m_pDdeObject->SetTargetDevice (pformatetcIn->ptd))
+ {
+ // 1.0 server did not accept target device
+ hres=DATA_E_FORMATETC;
+ goto exitRtn;
+ }
+
+ Assert (hres!=NOERROR); // Must do RequestData with new target device
+ }
+ else
+ {
+ // Pick a member handle (H) to return, based on clipboard format CF.
+ // If caller did not pass in its own medium, we must allocate a new
+ // handle.
+
+
+ #define macro(CF,H) \
+ if (pformatetcIn->cfFormat == CF) { \
+ if (m_pDdeObject->H) { \
+ if (pmedium->tymed == TYMED_NULL) { \
+ intrDebugOut((DEB_ITRACE,"::GetData giving cf==%x hData=%x\n",CF,m_pDdeObject->H)); \
+ pmedium->hGlobal = m_pDdeObject->H; \
+ m_pDdeObject->H = NULL; \
+ } \
+ hres = NOERROR; /* found data in right format */ \
+ } \
+ }
+
+ macro (g_cfNative, m_hNative)
+ else macro (m_pDdeObject->m_cfPict, m_hPict )
+ else macro (m_pDdeObject->m_cfExtra,m_hExtra )
+
+ // If we gave away our picture, we must forget its format.
+ if (pformatetcIn->cfFormat == m_pDdeObject->m_cfPict)
+ m_pDdeObject->m_cfPict = 0;
+ #undef macro
+ }
+
+ if (hres!=NOERROR)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::GetData(%x) posting DDE_REQUEST for cf==%x\n",
+ this,
+ (ULONG)pformatetcIn->cfFormat));
+
+ // Didn't find a handle for the requested format,
+ // or handle was NULL, so request it.
+ // The sequence should be:
+ // GetData -> DDE_REQUEST -> DDE_DATA -> OnData -> return to GetData
+
+ if (hres=m_pDdeObject->RequestData (pformatetcIn->cfFormat) != NOERROR)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::GetData(%x) RequestData returns error %x\n",
+ this,hres));
+
+ hres = DV_E_CLIPFORMAT;
+ goto exitRtn;
+ }
+
+ // By now, a KeepData() should have been done with the right cf,
+ // so try again.
+ intrDebugOut((DEB_ITRACE,
+ "::GetData(%x) KeepData should have been called. Go again\n",
+ this));
+
+ Puts ("KeepData should have been called. Trying GetData again.\n");
+ goto lStart;
+ }
+ lDone:
+ Puts ("pmedium->hGlobal =="); Puth(pmedium->hGlobal); Putn();
+ pmedium->pUnkForRelease = NULL; // Let caller release medium
+ // Must set tymed _after_ the goto loop.
+ // Otherwise it'll be changed the second time around.
+
+ // tell caller what we're returning
+ pmedium->tymed = UtFormatToTymed (pformatetcIn->cfFormat);
+
+
+ intrDebugOut((DEB_ITRACE,
+ "::GetData(%x)tymed=%x cfFormat=%x hGlobal=%x\n",
+ this,
+ pmedium->tymed,
+ (USHORT)pformatetcIn->cfFormat,
+ pmedium->hGlobal));
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "::GetData(%x)hres=%x\n",
+ this,
+ hres));
+ return hres;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::GetDataHere
+ (LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetDataHere(%x,pformatetcIn=%x)\n",
+ this,
+ pformatetcIn));
+
+ HRESULT hresult = NOERROR;
+ STGMEDIUM medium;
+ if (!(pformatetcIn->tymed & TYMED_HGLOBAL))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::GetDataHere(%x)DV_E_TYMED(%x)\n",
+ this,DV_E_TYMED));
+ // Cannot GetDataHere for GDI objects
+ hresult = DV_E_TYMED;
+ goto exitRtn;
+ }
+ RetErr (GetData (pformatetcIn, &medium));
+ if (medium.tymed != TYMED_HGLOBAL)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::GetDataHere(%x)medium.tymed != TYMED_HGLOBAL\n",
+ this));
+ hresult = ResultFromScode (DV_E_TYMED);
+ goto errRtn;
+ }
+ pmedium->tymed = medium.tymed;
+ pmedium->pUnkForRelease = medium.pUnkForRelease;
+ ErrRtnH (wHandleCopy (pmedium->hGlobal, medium.hGlobal));
+
+ errRtn:
+ ReleaseStgMedium (&medium);
+
+ exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetDataHere(%x) returning %x\n",
+ this,hresult));
+ return hresult;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::QueryGetData
+ (LPFORMATETC pformatetcIn)
+{
+ HRESULT hr;
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDdeObject::QueryGetData(pformatetcIn=%x)\n",
+ this,
+ pformatetcIn));
+
+ hr = wVerifyFormatEtc (pformatetcIn);
+
+ if (hr != NOERROR)
+ {
+ goto exitRtn;
+ }
+ if (pformatetcIn->cfFormat == g_cfEmbeddedObject
+ || pformatetcIn->cfFormat == g_cfEmbedSource
+ || pformatetcIn->cfFormat == g_cfLinkSource
+ || pformatetcIn->cfFormat == g_cfFileName
+ || pformatetcIn->cfFormat == g_cfCustomLinkSource
+ || pformatetcIn->cfFormat == g_cfObjectDescriptor
+ || pformatetcIn->cfFormat == g_cfLinkSrcDescriptor)
+ {
+ hr = S_FALSE;
+ }
+
+ hr = m_pDdeObject->IsFormatAvailable (pformatetcIn);
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDdeObject::QueryGetData returning %x\n",
+ this,hr));
+ return(hr);
+
+}
+
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::SetData
+ (LPFORMATETC pformatetc,
+ STGMEDIUM FAR* pmedium,
+ BOOL fRelease)
+{
+ HANDLE hDdePoke;
+ HRESULT hresult;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDdeObject::SetData(pformatetc=%x)\n",
+ this,
+ pformatetc));
+
+ hresult = wVerifyFormatEtc (pformatetc);
+
+ if (hresult != NOERROR)
+ {
+ goto exitRtn;
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%x ::SetData(pformatetc->cfFormat=%x)\n",
+ this,
+ (ULONG)pformatetc->cfFormat));
+
+ if (pformatetc->dwAspect & DVASPECT_ICON)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%x ::SetData dwAspect & DVASPECT_ICON\n",
+ this));
+ hresult = DV_E_DVASPECT;
+ goto exitRtn;
+ }
+
+
+ if (pformatetc->ptd != m_pDdeObject->m_ptd)
+ {
+ // If caller is setting with a different target device
+ // (We assume a different pointer points to a different target device)
+
+ if (NOERROR != m_pDdeObject->SetTargetDevice (pformatetc->ptd))
+ {
+ intrDebugOut((DEB_IERROR,
+ "%x ::SetData server did not accept target device\n",
+ this));
+ hresult = DV_E_DVTARGETDEVICE;
+ goto exitRtn;
+ }
+ }
+
+ if (hDdePoke = wPreparePokeBlock (pmedium->hGlobal,
+ pformatetc->cfFormat,
+ m_pDdeObject->m_aClass,
+ m_pDdeObject->m_bOldSvr))
+ {
+ hresult = m_pDdeObject->Poke (m_pDdeObject->m_aItem, hDdePoke);
+ if (fRelease)
+ ReleaseStgMedium (pmedium);
+ goto exitRtn;
+ }
+ else
+ {
+ hresult = E_OUTOFMEMORY;
+ }
+exitRtn:
+
+ intrDebugOut((DEB_ITRACE,"%x _OUT ::SetData returns %x\n",this,hresult));
+ return(hresult);
+
+}
+
+
+
+
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::DAdvise
+ (FORMATETC FAR* pformatetc,
+ DWORD grfAdvf,
+ IAdviseSink FAR* pAdvSink,
+ DWORD FAR* pdwConnection)
+{
+ HRESULT hresult;
+ HRESULT hresLookup;
+ FORMATETC formatetc;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDdeObject::DAdvise(pformatetc=%x,grfAdvf=%x,pAdvSink=%x)\n",
+ this,
+ pformatetc,
+ grfAdvf,
+ pAdvSink));
+
+ VDATEPTROUT (pdwConnection, DWORD);
+ *pdwConnection = 0;
+
+ wNormalize (pformatetc, &formatetc);
+
+ hresult =wVerifyFormatEtc (&formatetc);
+
+ if ( hresult != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "%x ::DAdvise pformatetc->cfFormat=%x\n",
+ this,
+ pformatetc->cfFormat));
+
+ if (NotEqual (formatetc.ptd, m_pDdeObject->m_ptd))
+ {
+ if (NOERROR != m_pDdeObject->SetTargetDevice (formatetc.ptd))
+ {
+ hresult= DV_E_DVTARGETDEVICE;
+ goto errRtn;
+ }
+ }
+
+ hresLookup = m_pDdeObject->m_ConnectionTable.Lookup (formatetc.cfFormat, NULL);
+ if (hresLookup != NOERROR)
+ {
+ // We have not already done a DDE advise for this format
+
+ Puts (" m_iAdvChange = "); Puti (m_pDdeObject->m_iAdvChange); Puts("\n");
+
+ if (m_pDdeObject->m_ulObjType == OT_LINK)
+ {
+ ErrRtnH (m_pDdeObject->AdviseOn (formatetc.cfFormat, ON_CHANGE));
+ ErrRtnH (m_pDdeObject->AdviseOn (formatetc.cfFormat, ON_SAVE));
+ }
+ else
+ {
+ ErrRtnH (m_pDdeObject->AdviseOn (formatetc.cfFormat, ON_SAVE));
+ ErrRtnH (m_pDdeObject->AdviseOn (formatetc.cfFormat, ON_CLOSE));
+ }
+ }
+
+ ErrZS (m_pDdeObject->m_pDataAdvHolder, E_OUTOFMEMORY);
+ hresult = m_pDdeObject->m_pDataAdvHolder->Advise (this, pformatetc, grfAdvf,
+ pAdvSink, pdwConnection);
+
+ m_pDdeObject->m_ConnectionTable.Add (*pdwConnection, formatetc.cfFormat,
+ grfAdvf);
+
+ errRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDdeObject::DAdvise hresult=%x\n",
+ this,
+ hresult));
+ return hresult;
+}
+
+
+
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::DUnadvise
+ (DWORD dwConnection)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::DUnadvise(%x,dwConnection=%x)\n",
+ this,
+ dwConnection));
+
+ CLIPFORMAT cf;
+ HRESULT hres;
+ DWORD grfAdvf;
+
+ // Remove connection from table. Lookup the cf for this connection.
+ if (m_pDdeObject->m_ConnectionTable.Subtract (dwConnection, &cf, &grfAdvf)
+ == NOERROR)
+ {
+ // If there is not another connection that needs this format
+ if (m_pDdeObject->m_ConnectionTable.Lookup (cf, NULL) != NOERROR)
+ {
+ // We did a DDE advise for this connection, so undo it.
+ if (m_pDdeObject->m_ulObjType == OT_LINK)
+ {
+ if (NOERROR != (hres=m_pDdeObject->UnAdviseOn (cf, ON_CHANGE)))
+ {
+ intrDebugOut((DEB_IWARN,
+ "::DUnadvise(%x,dwConnection=%x) ON_CHANGE failed\n",
+ this,
+ dwConnection));
+ }
+ if (NOERROR != (hres=m_pDdeObject->UnAdviseOn (cf, ON_SAVE)))
+ {
+ intrDebugOut((DEB_IWARN,
+ "::DUnadvise(%x,dwConnection=%x) ON_SAVE failed\n",
+ this,
+ dwConnection));
+ }
+ }
+ else
+ {
+ if (NOERROR != (hres=m_pDdeObject->UnAdviseOn (cf, ON_SAVE)))
+ {
+ intrDebugOut((DEB_IWARN,
+ "::DUnadvise(%x,dwConnection=%x) ON_SAVE failed\n",
+ this,
+ dwConnection));
+ }
+ if (NOERROR != (hres=m_pDdeObject->UnAdviseOn (cf, ON_CLOSE)))
+ {
+ intrDebugOut((DEB_IWARN,
+ "::DUnadvise(%x,dwConnection=%x) ON_CLOSE failed\n",
+ this,
+ dwConnection));
+ }
+ }
+ }
+ }
+
+ // Delegate rest of the work to the DataAdviseHolder
+ RetZS (m_pDdeObject->m_pDataAdvHolder, E_OUTOFMEMORY);
+ return m_pDdeObject->m_pDataAdvHolder->Unadvise (dwConnection);
+}
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::EnumDAdvise
+ (THIS_ LPENUMSTATDATA FAR* ppenumAdvise)
+{
+ RetZS (m_pDdeObject->m_pDataAdvHolder, E_OUTOFMEMORY);
+ return m_pDdeObject->m_pDataAdvHolder->EnumAdvise(ppenumAdvise);
+}
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::EnumFormatEtc
+ (DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc)
+{
+ return OleRegEnumFormatEtc (m_pDdeObject->m_clsid, dwDirection,
+ ppenumFormatEtc);
+}
+
+
+
+
+STDMETHODIMP NC(CDdeObject,CDataObjectImpl)::GetCanonicalFormatEtc
+(LPFORMATETC pformatetc, LPFORMATETC pformatetcOut)
+{
+ VDATEPTROUT (pformatetcOut, FORMATETC);
+ memcpy (pformatetcOut, pformatetc, sizeof (FORMATETC));
+ return ReportResult(0, DATA_S_SAMEFORMATETC, 0, 0);
+ // We must be very conservative and assume data will be different for
+ // every formatetc
+}
+
+
+
+INTERNAL CDdeObject::RequestData
+ (CLIPFORMAT cf)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::RequestData(%x,cf=%x)\n",
+ this,cf));
+
+ LPARAM lparam;
+ RetZ (m_pDocChannel);
+ intrAssert(wIsValidAtom(m_aItem));
+ ATOM aItem = wDupAtom (m_aItem);
+ intrAssert(wIsValidAtom(aItem));
+
+ lparam = MAKE_DDE_LPARAM (WM_DDE_REQUEST,cf, aItem);
+
+ if (!wPostMessageToServer (m_pDocChannel,
+ WM_DDE_REQUEST,
+ lparam,
+ TRUE))
+ {
+
+ if (aItem)
+ GlobalDeleteAtom (aItem);
+
+ return RPC_E_SERVER_DIED;
+ }
+
+ return WaitForReply(m_pDocChannel, AA_REQUEST);
+}
+
+
+// special name
+const char achSpecialName[] = "DISPLAY";
+
+//
+// Return a 1.0 target device for the screen
+//
+
+static INTERNAL DefaultTargetDevice (HANDLE FAR* ph)
+{
+ intrDebugOut((DEB_ITRACE,
+ "DefaultTargetDevice(ph=%x)\n",ph));
+
+ VDATEPTROUT ((LPVOID) ph, HANDLE);
+ LPOLETARGETDEVICE p1=NULL;
+ *ph = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, sizeof (*p1) + 10);
+ RetZS (*ph, E_OUTOFMEMORY);
+ p1 = (LPOLETARGETDEVICE) GlobalLock (*ph);
+ RetZS (p1, E_OUTOFMEMORY);
+ p1->otdDeviceNameOffset = 8;
+ p1->otdDriverNameOffset = 0; // The driver name is at otdData
+ p1->otdPortNameOffset = 9;
+ p1->otdExtDevmodeOffset = 0;
+ p1->otdExtDevmodeSize = 0;
+ p1->otdEnvironmentOffset= 0;
+ p1->otdEnvironmentSize = 0;
+
+ //
+ // Note that memcpy is moving a constant string. Therefore, sizeof()
+ // will include the NULL terminator
+ //
+ //
+ memcpy((LPSTR)p1->otdData, achSpecialName,sizeof(achSpecialName));
+ p1->otdData[8] = 0; // NULL the otdDeviceName
+ p1->otdData[9] = 0; // NULL the PortNameOffset
+ GlobalUnlock (*ph);
+ return NOERROR;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: Convert20TargetDevice
+//
+// Synopsis: Converts a 2.0 TargetDevice into a 1.0 OLETARGETDEVICE
+//
+// Effects: First converts the 2.0 UNICODE target device into ANSI,
+// then converts that into a 1.0 OLETARGETDEVICE. The astute
+// reader would say: Why not just 2.0 UNICODE to OLETARGETDEVICE?
+//
+// Two reasons: time before we ship vs time needed elsewhere.
+//
+// If you can spare some time, please change this to go
+// directly from one to the other.
+//
+// Arguments: [ptd] --
+// [phTD1] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-03-94 kevinro Created
+//
+// Notes:
+//
+// BUGBUG: the NT version of the OLE 1.0 used UINT as the size of the
+// structures members. This was baaaad, since we really need them to be
+// a fixed size. I am currently in the works of changing the NT 1.0 header
+// file to reflect what we really need it to be, which is USHORT's
+//
+//
+// We have a DVTARGETDEVICE, but we want a OLETARGETDEVICE, which looks like
+//
+// typedef struct _OLETARGETDEVICE {
+// USHORT otdDeviceNameOffset;
+// USHORT otdDriverNameOffset;
+// USHORT otdPortNameOffset;
+// USHORT otdExtDevmodeOffset;
+// USHORT otdExtDevmodeSize;
+// USHORT otdEnvironmentOffset;
+// USHORT otdEnvironmentSize;
+// BYTE otdData[1];
+// } OLETARGETDEVICE;
+//
+// A couple things to note:
+//
+// 1) The Names in the OLETARGETDEVICE need to be Ansi
+// 2) The Environment member doens't exist in the DVTARGETDEVICE, and will
+// be created in this conversion
+// 3) The ExtDevmode also needs to be ANSI
+//
+//----------------------------------------------------------------------------
+INTERNAL Convert20TargetDevice
+ (const DVTARGETDEVICE FAR* ptd, // in parm
+ HANDLE FAR* phTD1) // out parm
+{
+ const size_t cbHeader = SIZEOF_DVTARGETDEVICE_HEADER;
+ HRESULT hr;
+ LPOLETARGETDEVICE ptd1 = NULL;
+ size_t cbTD1;
+ size_t cbDevmode;
+ size_t cbOffset;
+ LPDEVMODEA pdevmode;
+
+ intrDebugOut((DEB_ITRACE,
+ "Convert20TargetDevice(ptd=%x)\n",ptd));
+
+ VDATEPTROUT ((LPVOID) phTD1, HANDLE);
+ *phTD1 = NULL;
+
+ //
+ // If no device specified, then return the default
+ //
+
+ if (NULL==ptd)
+ {
+ return DefaultTargetDevice (phTD1);
+ }
+
+ //
+ // Compute information for doing conversion using routines in utils.cpp
+ // The following structure will get the sizes
+ //
+
+ DVTDINFO dvtdInfo;
+
+ hr = UtGetDvtd32Info(ptd,&dvtdInfo);
+
+ if (hr != NOERROR)
+ {
+ return DV_E_DVTARGETDEVICE;
+ }
+
+ //
+ // The conversion routines require us to allocate memory to pass in.
+ //
+
+ DVTARGETDEVICE *pdvtdAnsi = (DVTARGETDEVICE *) PrivMemAlloc(dvtdInfo.cbConvertSize);
+
+ if (pdvtdAnsi == NULL)
+ {
+ return(E_OUTOFMEMORY);
+ }
+
+ //
+ // Convert the UNICODE target device into an ANSI target device
+ //
+
+ hr = UtConvertDvtd32toDvtd16(ptd,&dvtdInfo,pdvtdAnsi);
+
+ if (hr != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ //
+ // pdvtdAnsi now holds an ANSI version of the DVTARGETDEVICE. Turns
+ // out the structure we really want is the DVTARGETDEVICE, plus a
+ // couple of extra header bytes. Therefore, we can just do a block
+ // copy of the DVTARGETDEVICE's data, and fix up our OLETARGETDEVICE
+ // header to have the correct offsets in the data.
+ //
+ // offset of data block from beginning of 2.0 target device
+ //
+ cbOffset = offsetof (DVTARGETDEVICE, tdData);
+
+ //
+ // Calculate a pointer to the DEVMODEA
+ //
+ pdevmode = pdvtdAnsi->tdExtDevmodeOffset ?
+ (LPDEVMODEA)((LPBYTE)pdvtdAnsi + pdvtdAnsi->tdExtDevmodeOffset)
+ : NULL;
+
+ //
+ // Quick sanity check on the resulting pointer.
+ //
+ if (pdevmode && IsBadReadPtr (pdevmode, sizeof(DEVMODEA)))
+ {
+ hr = DV_E_DVTARGETDEVICE;
+ goto errRtn;
+ }
+
+ //
+ // Calculate the size of the devmode part.
+ //
+
+ cbDevmode = (pdevmode ? pdevmode->dmSize + pdevmode->dmDriverExtra:0);
+
+ //
+ // Calculate the total size needed. The DVTARGETDEVICE header has 12 bytes,
+ // and the OLETARGETDEVICE has 14 bytes. We also need to make an extra copy
+ // of the cbDevmode structure to fill in the environment. Therefore, there is
+ // an extra cbDevmode, and a sizeof(USHORT) added to the size. The size includes
+ // the size of the DVTARGETHEADER
+ //
+
+ cbTD1 = (size_t) pdvtdAnsi->tdSize +
+ cbDevmode + // For extra Environment data
+ sizeof (USHORT); // for Environment Size field
+
+ *phTD1 = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, cbTD1);
+ if (NULL== *phTD1)
+ {
+ intrAssert (!"GlobalAlloc Failed");
+ hr = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ ptd1 = (LPOLETARGETDEVICE) GlobalLock (*phTD1);
+ if (NULL== ptd1)
+ {
+ intrAssert (!"GlobalLock Failed");
+ hr = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ // Set x1 (1.0 offset) based on x2 (2.0 offset)
+ //
+ // Note that the OLETARGETDEVICE offsets are relative to the array of bytes,
+ // where the DVTARGETDEVICE is relative to the start of the structure. Thats
+ // why cbOffset is subtracted
+ //
+
+ #define ConvertOffset(x1, x2) (x1 = (x2 ? x2 - cbOffset : 0))
+
+ //
+ // Using the above macro, and assuming
+ //
+
+ ConvertOffset (ptd1->otdDeviceNameOffset, pdvtdAnsi->tdDeviceNameOffset);
+ ConvertOffset (ptd1->otdDriverNameOffset, pdvtdAnsi->tdDriverNameOffset);
+ ConvertOffset (ptd1->otdPortNameOffset , pdvtdAnsi->tdPortNameOffset );
+ ConvertOffset (ptd1->otdExtDevmodeOffset, pdvtdAnsi->tdExtDevmodeOffset);
+ ptd1->otdExtDevmodeSize = cbDevmode;
+
+ //
+ // I found this in the OLE 2 information on OLETARGETDEVICE:
+ //
+ // The otdDeviceNameOffset, otdDriverNameOffset, and otdPortNameOffset
+ // members should be null-terminated. In Windows 3.1, the ability to
+ // connect multiple printers to one port has made the environment
+ // obsolete. The environment information retrieved by the
+ // GetEnvironment function can occasionally be incorrect. To ensure that the
+ // OLETARGETDEVICE structure is initialized correctly, the application
+ // should copy information from the DEVMODEA structure retrieved by a
+ // call to the ExtDeviceMode function to the environment position of
+ // the OLETARGETDEVICE structure.
+ //
+ //
+
+ //
+ // Adjust the environment offset to the end of the converted structure, and
+ // set the size. the sizeof(USHORT) accounts for the addition of the
+ // otdEnvironmentSize field. The offsetof accounts for the fact that the
+ // OLETARGETDEVICE offsets are based from the otdData array.
+ //
+ ptd1->otdEnvironmentOffset = (USHORT) pdvtdAnsi->tdSize +
+ sizeof(USHORT) -
+ offsetof(OLETARGETDEVICE,otdData);
+
+ ptd1->otdEnvironmentSize = cbDevmode;
+
+ // Copy data block
+ if(IsBadWritePtr (ptd1->otdData, (size_t) pdvtdAnsi->tdSize - cbHeader))
+ {
+ hr = E_UNEXPECTED;
+ goto errRtn;
+ }
+ memcpy (ptd1->otdData, pdvtdAnsi->tdData, (size_t) pdvtdAnsi->tdSize - cbHeader);
+
+ if (cbDevmode != 0)
+ {
+ if(IsBadWritePtr (ptd1->otdData, sizeof (DEVMODEA)))
+ {
+ hr = E_UNEXPECTED;
+ goto errRtn;
+ }
+
+ // Copy 2.0 Devmode into 1.0 environment
+
+ memcpy (ptd1->otdData + ptd1->otdEnvironmentOffset,
+ pdvtdAnsi->tdData + pdvtdAnsi->tdExtDevmodeOffset,
+ cbDevmode);
+ }
+
+ hr = NOERROR;
+
+errRtn:
+
+ if (ptd1 != NULL)
+ {
+ GlobalUnlock(*phTD1);
+ }
+
+ if (pdvtdAnsi != NULL)
+ {
+ PrivMemFree(pdvtdAnsi);
+ }
+ intrDebugOut((DEB_ITRACE,
+ "Convert20TargetDevice(ptd=%x) returns %x\n",ptd,hr));
+ return(hr);
+}
+
+
+
+static INTERNAL CopyTargetDevice
+ (const DVTARGETDEVICE FAR* ptd,
+ DVTARGETDEVICE FAR* FAR* pptd)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CopyTargetDevice(ptd=%x)\n",ptd));
+
+ if (*pptd)
+ {
+ delete *pptd; // delete old target device
+ }
+ if (NULL==ptd)
+ {
+ *pptd = NULL;
+ }
+ else
+ {
+ *pptd = (DVTARGETDEVICE FAR*) operator new ((size_t) (ptd->tdSize));
+ if (NULL==*pptd)
+ {
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ _fmemcpy (*pptd, ptd, (size_t) ptd->tdSize);
+ }
+ return NOERROR;
+}
+
+
+
+INTERNAL CDdeObject::SetTargetDevice
+ (const DVTARGETDEVICE FAR* ptd)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::SetTargetDevice(%x,ptd=%x)\n",
+ this,
+ ptd));
+
+ HANDLE hTD1 = NULL;
+ HANDLE hDdePoke=NULL;
+
+ RetErr (Convert20TargetDevice (ptd, &hTD1));
+
+ Assert (hTD1);
+ Verify (hDdePoke = wPreparePokeBlock (hTD1, g_cfBinary, m_aClass, m_bOldSvr));
+ if (hTD1)
+ {
+ GlobalFree (hTD1);
+ }
+ // Poke new target device to 1.0 server
+ aStdTargetDevice = GlobalAddAtom (L"StdTargetDevice");
+ intrAssert(wIsValidAtom(aStdTargetDevice));
+ RetErr (Poke (aStdTargetDevice, hDdePoke));
+
+ // Remember current target device
+ RetErr (CopyTargetDevice (ptd, &m_ptd));
+ // Flush the cache because it contains a picture for the wrong
+ // target device.
+ if (m_hPict)
+ wFreeData (m_hPict, m_cfPict);
+ m_cfPict = (CLIPFORMAT)0;
+ m_hPict = NULL;
+
+ return NOERROR;
+}
diff --git a/private/ole32/com/remote/dde/client/ddeioc.cxx b/private/ole32/com/remote/dde/client/ddeioc.cxx
new file mode 100644
index 000000000..cb97a244b
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/ddeioc.cxx
@@ -0,0 +1,213 @@
+/*
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddeLink.cpp
+
+Abstract:
+
+ This module contains the DdeObject::OleItemContainer methods
+ and other Link-related code
+
+Author:
+
+ Jason Fuller (jasonful) 19-October-1992
+
+*/
+
+#include "ddeproxy.h"
+// #include <limits.h>
+// #include <utils.h>
+// #include <moniker.h>
+
+
+ASSERTDATA
+
+
+
+STDUNKIMPL_FORDERIVED (DdeObject, OleItemContainerImpl)
+
+
+static INTERNAL_(void) wSkipDelimiter
+ (LPOLESTR * psz)
+{
+ if (wcschr (L"!\"'*+,./:;<=>?@[\\]`|" , **psz))
+ (*psz)++;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject, COleItemContainerImpl)::ParseDisplayName
+ (LPBC pbc,
+ LPOLESTR lpszDisplayName,
+ ULONG * pchEaten,
+ LPMONIKER * ppmkOut)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::ParseDisplayName(%x,lpsz=%ws)\n",
+ this,
+ lpszDisplayName));
+
+ LPUNKNOWN pUnk = NULL;
+ VDATEPTROUT(ppmkOut,LPMONIKER);
+ *ppmkOut = NULL;
+ VDATEIFACE(pbc);
+ VDATEPTRIN(lpszDisplayName, char);
+ VDATEPTROUT(pchEaten,ULONG);
+
+ *pchEaten = lstrlenW(lpszDisplayName);
+ wSkipDelimiter (&lpszDisplayName);
+ // Validate the item name
+ RetErr (GetObject (lpszDisplayName, BINDSPEED_INDEFINITE, pbc,
+ IID_IUnknown, (LPLPVOID) &pUnk));
+ if (pUnk)
+ pUnk->Release();
+ return CreateItemMoniker (L"!", lpszDisplayName, ppmkOut);
+}
+
+
+
+STDMETHODIMP NC(CDdeObject, COleItemContainerImpl)::EnumObjects
+ (DWORD grfFlags,
+ LPENUMUNKNOWN FAR* ppenumUnk)
+
+{
+ // OLE 1.0 provides no way to enumerate all the items in a document.
+ // This method is unlikely to be called since our implementation of
+ // file and item monikers does not call it.
+ Puts ("OleItemContainer::EnumObjects\r\n");
+ if (ppenumUnk)
+ {
+ *ppenumUnk = NULL;
+ return E_NOTIMPL;
+ }
+
+ return E_INVALIDARG;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject, COleItemContainerImpl)::LockContainer
+ (BOOL fLock)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::LockContainer(%x,fLock=%x)\n",
+ this,
+ fLock));
+
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject, COleItemContainerImpl)::GetObject
+ (LPOLESTR lpszItem,
+ DWORD dwSpeedNeeded,
+ LPBINDCTX pbc,
+ REFIID riid,
+ LPVOID * ppvObject)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetObject(%x,szItem=%ws)\n",
+ this,
+ lpszItem));
+
+
+ HRESULT hresult = NOERROR;
+ VDATEPTROUT (ppvObject, LPVOID);
+ *ppvObject=NULL;
+ LPUNKNOWN pUnk = NULL; // These refer to the
+ CDdeObject FAR* pdde = NULL; // same object
+
+ RetZS (pUnk =CDdeObject::Create (NULL,m_pDdeObject->m_clsid,OT_LINK,
+ m_pDdeObject->m_aTopic,lpszItem,&pdde),
+ E_OUTOFMEMORY);
+
+ // For handling invisible updates--propagate information from document
+ // to item.
+ pdde->DeclareVisibility (m_pDdeObject->m_fVisible);
+ pdde->m_fDidLaunchApp = m_pDdeObject->m_fDidLaunchApp;
+ pdde->m_fDidStdOpenDoc = m_pDdeObject->m_fDidStdOpenDoc;
+
+ intrAssert(wIsValidAtom(pdde->m_aItem));
+ ErrZ (0==lstrcmpW(lpszItem, wAtomName(pdde->m_aItem)));
+
+ // OPTIMIZATION: Could use a mini Running Object Table to map lpszItem to
+ // LPUNKNOWN and avoiding the Connect() and DDE_REQUEST.
+
+ // Open a DocChannel
+ ErrRtnH (pdde->m_ProxyMgr.Connect (IID_NULL, CLSID_NULL));
+
+ // Request Native data in order to see if the item name is valid
+ Assert (pdde->m_pDocChannel);
+ LPARAM lp;
+ if (!wPostMessageToServer (pdde->m_pDocChannel,
+ WM_DDE_REQUEST,
+ lp=MAKE_DDE_LPARAM (WM_DDE_REQUEST,g_cfNative, wDupAtom(pdde->m_aItem)),TRUE))
+ {
+ Assert (pdde->m_refs==1);
+ hresult = ResultFromScode (MK_E_NOOBJECT);
+ goto errRtn;
+ }
+ if (NOERROR != pdde->WaitForReply (pdde->m_pDocChannel, AA_REQUESTAVAILABLE))
+ {
+ // Try metafile. Excel can't render large metafiles
+ // but it can render native.
+ if (!wPostMessageToServer (pdde->m_pDocChannel,
+ WM_DDE_REQUEST,
+ lp=MAKE_DDE_LPARAM (WM_DDE_REQUEST,CF_METAFILEPICT, wDupAtom(pdde->m_aItem)),TRUE))
+ {
+ Assert (pdde->m_refs==1);
+ hresult = ResultFromScode (MK_E_NOOBJECT);
+ goto errRtn;
+ }
+ if (NOERROR != pdde->WaitForReply (pdde->m_pDocChannel, AA_REQUESTAVAILABLE))
+ {
+ Assert (pdde->m_refs==1);
+ hresult = ResultFromScode (MK_E_NOOBJECT);
+ goto errRtn;
+ }
+ }
+
+ // Item name is valid
+ hresult = pdde->m_pUnkOuter->QueryInterface (riid, (LPLPVOID) ppvObject);
+ if (NOERROR==hresult)
+ {
+ m_pDdeObject->m_fDidGetObject = TRUE;
+ }
+ errRtn:
+ if (pUnk)
+ pUnk->Release();
+ return hresult;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject, COleItemContainerImpl)::GetObjectStorage
+ (LPOLESTR lpszItem,
+ LPBINDCTX ptc,
+ REFIID riid,
+ LPVOID * ppvStorage)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetObjectStorage(%x,szItem=%ws)\n",
+ this,
+ lpszItem));
+ return MK_E_NOSTORAGE;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject, COleItemContainerImpl)::IsRunning
+ (LPOLESTR szItem)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::IsRunning(%x,szItem=%ws)\n",
+ this,
+ szItem));
+
+ // By definition, all items are running
+ return NOERROR;
+}
diff --git a/private/ole32/com/remote/dde/client/ddemnker.cxx b/private/ole32/com/remote/dde/client/ddemnker.cxx
new file mode 100644
index 000000000..2331b02ad
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/ddemnker.cxx
@@ -0,0 +1,527 @@
+/*
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddeLink.cpp
+
+Abstract:
+
+ This module implements:
+ DdeBindToObject
+ DdeIsRunning
+
+Author:
+
+ Jason Fuller (jasonful) 19-October-1992
+
+*/
+#include "ddeproxy.h"
+// #include <ctype.h>
+
+
+INTERNAL DdeBindToObject
+ (LPCOLESTR szFileIn,
+ REFCLSID clsid,
+ BOOL fPackageLink,
+ REFIID iid,
+ LPLPVOID ppv)
+{
+ intrDebugOut((DEB_ITRACE,
+ "DdeBindToObject szFileIn(%ws) fPackageLink(%x)\n",
+ szFileIn,
+ fPackageLink));
+
+
+ LPUNKNOWN punk;
+ *ppv = NULL;
+ CDdeObject FAR* pdde=NULL;
+ HRESULT hresult = E_UNEXPECTED;
+ BOOL fSysConnection = FALSE;
+ WCHAR wszTmpFile [MAX_STR+5];
+
+ //
+ // This protocol doesn't handle the fact that there are two names for
+ // every file. This is a bit of a problem. So, we are going to choose
+ // the short name as the one to look for. This means that DDE objects
+ // using the long filename will not work very well.
+ //
+ WCHAR szFile[MAX_PATH];
+ if ((lstrlenW(szFileIn) == 0) || (GetShortPathName(szFileIn,szFile,MAX_PATH) == 0))
+ {
+ //
+ // Unable to determine a short path for this object. Use whatever we were
+ // handed.
+ //
+ intrDebugOut((DEB_ITRACE,"No conversion for short path. Copy szFileIn\n"));
+ lstrcpyW(szFile,szFileIn);
+ }
+ intrDebugOut((DEB_ITRACE,"Short file szFile(%ws)\n",szFile));
+
+ RetZS (punk=CDdeObject::Create (NULL,clsid,OT_LINK,wGlobalAddAtom(szFile),
+ NULL,&pdde),E_OUTOFMEMORY);
+ RetZ (pdde);
+
+ // Document already running?
+
+ if (NOERROR != (hresult = pdde->DocumentLevelConnect (NULL) ))
+ {
+ if (GetScode (hresult) != S_FALSE)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "DdeBindToObject szFile(%ws) DLC returns %x \n",
+ szFile,hresult));
+ goto exitRtn;
+ }
+
+
+ // If not already running, try to make a sys level connection
+
+ if (!pdde->m_pSysChannel) {
+ if (!pdde->AllocDdeChannel (&pdde->m_pSysChannel, SYS_CLASSA))
+ {
+ intrAssert( !"Out of memory");
+ hresult = E_OUTOFMEMORY;
+ goto exitRtn;
+ }
+ }
+
+ hresult = ReportResult (0, E_UNEXPECTED, 0, 0);
+
+ if (fPackageLink) {
+ lstrcpyW (wszTmpFile, szFile);
+ lstrcatW (wszTmpFile, L"/Link");
+ pdde->SetTopic (wGlobalAddAtom(wszTmpFile));
+ }
+
+ if (pdde->InitSysConv())
+ {
+ fSysConnection = TRUE;
+
+ // Try to make the server open the document
+ ErrRtnH (pdde->PostSysCommand (pdde->m_pSysChannel, (LPSTR)&achStdOpenDocument,FALSE));
+ pdde->m_fDidStdOpenDoc = TRUE;
+
+ }
+ else
+ {
+ // launch the server
+ if (!pdde->LaunchApp())
+ {
+ hresult = CO_E_APPNOTFOUND;
+ goto errRtn;
+ }
+ }
+
+ if (fPackageLink)
+ pdde->SetTopic (wGlobalAddAtom(szFile));
+
+ // Connect to document
+ hresult = pdde->m_ProxyMgr.Connect (IID_NULL, CLSID_NULL);
+ if (hresult != NOERROR)
+ {
+ // Excel does not register its document in time if it loads
+ // startup macros. So we force it to open the document.
+ if (pdde->InitSysConv())
+ {
+ fSysConnection = TRUE;
+ // Try to make the server open the document.
+ ErrRtnH (pdde->PostSysCommand (pdde->m_pSysChannel,
+ (LPSTR)&achStdOpenDocument,
+ FALSE));
+ pdde->m_fDidStdOpenDoc = TRUE;
+ }
+ else
+ {
+ ErrRtnH (ResultFromScode (CO_E_APPDIDNTREG));
+ }
+ // Try connecting to document again. Should succeed.
+ hresult = pdde->m_ProxyMgr.Connect (IID_NULL, CLSID_NULL);
+ }
+ }
+ else
+ {
+ // Already running, so assume visible
+ pdde->DeclareVisibility (TRUE);
+ }
+
+errRtn:
+ if (pdde->m_pSysChannel) {
+ if (fSysConnection)
+ pdde->TermConv (pdde->m_pSysChannel);
+ else
+ pdde->DeleteChannel (pdde->m_pSysChannel);
+ }
+
+ if (hresult == NOERROR) {
+ hresult = punk->QueryInterface (iid, ppv);
+ }
+ pdde->m_pUnkOuter->Release();
+ if (hresult!=NOERROR)
+ {
+ Warn ("DdeBindToObject failed");
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "DdeBindToObject szFile(%ws) returns %x \n",
+ szFile,hresult));
+
+ return hresult;
+}
+
+
+//
+// BUGBUG: This won't work in a multi-threaded world.
+//
+static LPOLESTR szOriginalUNCName;
+static WCHAR cOriginalDrive;
+
+static INTERNAL InitializeIterator
+ (LPCOLESTR wszFile)
+{
+ WCHAR wszDrive[] = L"A:\\";
+
+ if ((wszFile == NULL) || (wszFile[1] != ':'))
+ {
+ return(S_FALSE);
+ }
+
+ wszDrive[0] = (WCHAR)CharUpperW((LPWSTR)wszFile[0]);
+
+ if (GetDriveType(wszDrive) == DRIVE_REMOTE)
+ {
+
+ DWORD cb = MAX_STR;
+ wszDrive[2] = '\0';
+ if (NULL==szOriginalUNCName)
+ {
+ szOriginalUNCName = new WCHAR [MAX_STR];
+ }
+
+
+ if (WN_SUCCESS == OleWNetGetConnection (wszDrive, szOriginalUNCName, &cb))
+ {
+ cOriginalDrive = (WCHAR)CharUpperW((LPWSTR)wszFile[0]);
+ return NOERROR;
+ }
+ }
+ // szFile is not a network file
+ return ReportResult (0, S_FALSE, 0, 0);
+}
+
+
+
+// NextEquivalentNetDrive
+//
+// Change the drive letter of szFile to the next (modulo 'Z') drive letter
+// that is connected to the same net drive
+// Return S_FALSE when there are no more equivalent drives
+//
+static INTERNAL NextEquivalentNetDrive
+ (LPOLESTR szFile)
+{
+ #define incr(c) (c=='Z' ? c='A' : ++c)
+ WCHAR wszDrive[3]= L"A:";
+ Assert (szFile && szFile[1]==':');
+
+ char cDrive = (char)CharUpperW((LPWSTR)szFile[0]);
+
+ while (cOriginalDrive != incr(cDrive))
+ {
+
+ DWORD cb = MAX_PATH;
+ WCHAR szUNCName [MAX_PATH];
+ wszDrive[0] = cDrive;
+
+ Assert (cDrive >= 'A' && cDrive <= 'Z');
+ Assert (szOriginalUNCName);
+
+ if (WN_SUCCESS == OleWNetGetConnection (wszDrive,szUNCName, &cb) &&
+ (0 == lstrcmpW (szUNCName, szOriginalUNCName)))
+ {
+ szFile[0] = cDrive;
+ return NOERROR;
+ }
+ }
+ // We've gone through all the drives
+ return ReportResult (0, S_FALSE, 0, 0);
+}
+
+
+
+// Dde_IsRunning
+//
+// Attempt to open a document-level conversation using the
+// filename as a topic. If the conversation is established we
+// know the file is running and terminate the conversation.
+// Otherwise it is not running.
+//
+INTERNAL DdeIsRunning
+ (CLSID clsid,
+ LPCOLESTR szFileIn,
+ LPBC pbc,
+ LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning)
+{
+ intrDebugOut((DEB_ITRACE,
+ "DdeIsRunning szFileIn(%ws)\n",szFileIn));
+
+ ATOM aTopic;
+ CDdeObject FAR* pdde=NULL;
+ HRESULT hres = ReportResult(0, S_FALSE, 0, 0);
+
+ if (NULL==szFileIn || '\0'==szFileIn[0])
+ {
+ // A NULL filename is invalid for our purposes.
+ // But if we did a DDE_INITIATE, NULL would mean "any topic",
+ // and if we were called by RunningMoniker() with CLSID_NULL,
+ // then we would be INITIATEing on "any app, any topic" and
+ // SHELL (if not others) would respond.
+ intrDebugOut((DEB_ITRACE,
+ "DdeIsRunning NULL szFileIn\n"));
+
+ hres = S_FALSE;
+ goto exitRtn;
+ }
+ //
+ // This protocol doesn't handle the fact that there are two names for
+ // every file. This is a bit of a problem. So, we are going to choose
+ // the short name as the one to look for. This means that DDE objects
+ // using the long filename will not work very well.
+ //
+ WCHAR szFile[MAX_PATH];
+ if ((lstrlenW(szFileIn) == 0) || (GetShortPathName(szFileIn,szFile,MAX_PATH) == 0))
+ {
+ //
+ // Unable to determine a short path for this object. Use whatever we were
+ // handed.
+ //
+ intrDebugOut((DEB_ITRACE,"No conversion for short path. Copy szFileIn\n"));
+ lstrcpyW(szFile,szFileIn);
+ }
+ intrDebugOut((DEB_ITRACE,"Short file szFile(%ws)\n",szFile));
+
+#ifdef KEVINRO_OLDCODE
+
+We have removed SzFixNet from the system, since the file system is
+capable of dealing with UNC names now. Therefore, I have removed the
+following lines. I am pretty sure this is going to work, but I am
+leaving this code here until we decide that it is a good decision.
+If you find this, and I haven't removed it, chances are that I forgot
+to remove this code.
+ HRESULT hresFixNet;
+ UINT dummy;
+
+ // If UNC name, change to drive letter
+ LPOLESTR szFile = NULL;
+ dummy = 0xFFFF;
+
+ hresFixNet = SzFixNet (pbc, szFile, &szFile, &dummy);
+ // SzFixNet may return NOERROR and szFile==NULL
+ if (szFile==NULL || hresFixNet != NOERROR)
+ {
+ aTopic = wGlobalAddAtom(szFile);
+ intrAssert(wIsValidAtom(aTopic));
+ }
+ else
+ {
+ aTopic = wGlobalAddAtom (szFile);
+ intrAssert(wIsValidAtom(aTopic));
+ delete szFile;
+ }
+#else
+ aTopic = wGlobalAddAtom (szFile);
+ intrAssert(wIsValidAtom(aTopic));
+#endif // KEVINRO_OLDCODE
+
+
+ ErrZ (CDdeObject::Create (NULL, clsid, OT_LINK, aTopic, NULL, &pdde));
+
+ if (NOERROR == pdde->DocumentLevelConnect (pbc))
+ {
+ // It is running!
+ // Immediately terminate conversation. We just wanted to know
+ // if it was running.
+ hres = NOERROR;
+ }
+ else
+ {
+ // Not running
+ hres = ReportResult(0, S_FALSE, 0, 0);
+ }
+
+ errRtn:
+
+ if (aTopic)
+ intrAssert(wIsValidAtom(aTopic));
+ GlobalDeleteAtom (aTopic);
+ if (pdde)
+ {
+ Assert (pdde->m_refs==1);
+ pdde->m_pUnkOuter->Release();
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "DdeIsRunning szFile(%ws) returns %x\n",szFile,hres));
+ return hres;
+}
+
+
+#if 0
+INTERNAL DdeIsRunning
+ (CLSID clsid,
+ LPCSTR cszFile,
+ LPBC pbc,
+ LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning)
+{
+ HRESULT hresult = NOERROR;
+ LPSTR szFile = NULL;
+
+ // Normal case
+ if (NOERROR == Dde_IsRunning (clsid, cszFile, pbc, pmkToLeft,
+ pmkNewlyRunning))
+ {
+ return NOERROR;
+ }
+
+ if (cszFile[0]=='\\' && cszFile[1]=='\\')
+ {
+ RetErr (SzFixNet (pbc, (LPSTR)cszFile, &szFile));
+ // Try with a drive letter instead of a UNC name
+ if (NOERROR==Dde_IsRunning (clsid, szFile, pbc, pmkToLeft,
+ pmkNewlyRunning))
+ {
+ hresult = NOERROR;
+ goto errRtn;
+ }
+ }
+ else
+ {
+ szFile = UtDupString (cszFile); // so it can be deleted
+ }
+
+ // If failure, see if the file is running under a different net
+ // drive letter that is mapped to the same drive.
+
+ if (InitializeIterator (szFile) != NOERROR)
+ {
+ // file is probably not on a network drive
+ hresult = ResultFromScode (S_FALSE);
+ goto errRtn;
+ }
+
+ while (NOERROR==NextEquivalentNetDrive (szFile))
+ {
+ if (NOERROR == Dde_IsRunning (clsid, szFile, pbc, pmkToLeft,
+ pmkNewlyRunning))
+ {
+ hresult = NOERROR;
+ goto errRtn;
+ }
+ }
+ // not running
+ hresult = ResultFromScode (S_FALSE);
+
+ errRtn:
+ delete szFile;
+ return hresult;
+}
+#endif
+
+
+
+// CDdeObject::DocumentLevelConnect
+//
+// Try to connect to document (m_aTopic) even if the document is running
+// under a different drive letter that is mapped to the same network drive.
+//
+INTERNAL CDdeObject::DocumentLevelConnect
+ (LPBINDCTX pbc)
+{
+ ATOM aOriginal;
+ ATOM aTopic;
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::DocumentLevelConnect(%x)\n",this));
+ HRESULT hresult = NOERROR;
+
+ // Normal case
+ if (NOERROR==m_ProxyMgr.Connect (IID_NULL, CLSID_NULL))
+ {
+ goto exitRtn;
+ }
+
+
+ WCHAR szFile[MAX_STR];
+ WCHAR szUNCFile[MAX_STR];
+
+ Assert (wIsValidAtom (m_aTopic));
+ if (GlobalGetAtomName (m_aTopic, szFile, MAX_STR) == 0)
+ {
+ hresult = E_UNEXPECTED;
+ goto exitRtn;
+ }
+ aOriginal = wDupAtom (m_aTopic);
+ intrAssert(wIsValidAtom(aOriginal));
+
+ intrDebugOut((DEB_ITRACE,
+ "::DocumentLevelConnect(szFile=%ws)\n",this,szFile));
+ if (NOERROR != InitializeIterator (szFile))
+ {
+ // szFile probably not a network file
+ hresult = ResultFromScode (S_FALSE);
+ goto errRtn;
+ }
+
+ while (NOERROR == NextEquivalentNetDrive (szFile))
+ {
+ SetTopic (aTopic = wGlobalAddAtom (szFile));
+ if (NOERROR==m_ProxyMgr.Connect (IID_NULL, CLSID_NULL))
+ {
+ // Inform client of new drive letter
+ ChangeTopic (wAtomNameA(aTopic));
+ hresult = NOERROR;
+ goto errRtn;
+ }
+ else
+ {
+ SetTopic ((ATOM)0);
+ }
+ }
+
+ // Try with full UNC name
+ lstrcpyW (szUNCFile, szOriginalUNCName);
+ lstrcatW (szUNCFile, szFile+2); // skip X:
+ SetTopic (aTopic = wGlobalAddAtom (szUNCFile));
+ if (NOERROR==m_ProxyMgr.Connect (IID_NULL, CLSID_NULL))
+ {
+ // Inform client of new name
+ ChangeTopic (wAtomNameA(aTopic));
+ hresult = NOERROR;
+ goto errRtn;
+ }
+ else
+ {
+ SetTopic ((ATOM)0);
+ }
+
+ // Not running
+ hresult = S_FALSE;
+
+errRtn:
+ if (NOERROR != hresult)
+ SetTopic (aOriginal);
+ delete szOriginalUNCName;
+ szOriginalUNCName = NULL;
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::DocumentLevelConnect(%x) returns %x\n",
+ this,hresult));
+
+ return hresult;
+}
diff --git a/private/ole32/com/remote/dde/client/ddeoo.cxx b/private/ole32/com/remote/dde/client/ddeoo.cxx
new file mode 100644
index 000000000..491756634
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/ddeoo.cxx
@@ -0,0 +1,770 @@
+/*
+ddeoo.cpp
+DDE Ole Object
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddeoo.cpp
+
+Abstract:
+
+ This module contains the methods for DdeObject::OleObject
+
+Author:
+
+ Jason Fuller (jasonful) 24-July-1992
+
+*/
+
+#include "ddeproxy.h"
+#include <limits.h>
+
+ASSERTDATA
+
+//
+// OleObject methods
+//
+
+STDUNKIMPL_FORDERIVED(DdeObject, OleObjectImpl)
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::SetClientSite
+ (IOleClientSite FAR* pClientSite)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::SetClientSite(%x,pClientSite=%x)\n",
+ this,
+ pClientSite));
+
+ ChkD (m_pDdeObject);
+
+ if (m_pDdeObject->m_pOleClientSite)
+ m_pDdeObject->m_pOleClientSite->Release();
+
+ // we've decided to keep the pointer that's been passed to us. So we
+ // must AddRef()
+ if (m_pDdeObject->m_pOleClientSite = pClientSite)
+ pClientSite->AddRef();
+
+ // this pointer need not be sent to the server, because we will always
+ // send our &m_MyDataSite as the client site
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::GetClientSite
+ (IOleClientSite FAR* FAR* ppClientSite)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetClientSite(%x)\n",
+ this));
+
+ ChkD (m_pDdeObject);
+ // we've been asked to give the pointer so we should AddRef()
+ if (*ppClientSite = m_pDdeObject->m_pOleClientSite)
+ m_pDdeObject->m_pOleClientSite->AddRef();
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::EnumVerbs
+ (IEnumOLEVERB FAR* FAR* ppenumOleVerb)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::EnumVerbs(%x)\n",
+ this));
+
+ ChkD (m_pDdeObject);
+ return ReportResult(0, OLE_S_USEREG, 0, 0);
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::Update
+( void )
+{
+ HRESULT hr;
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::Update(%x)\n",
+ this));
+
+ ChkD (m_pDdeObject);
+
+ hr = m_pDdeObject->Update(TRUE);
+ if (hr == NOERROR)
+ {
+ hr = m_pDdeObject->Save(m_pDdeObject->m_pstg);
+ }
+
+ return hr;
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::IsUpToDate
+( void )
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::IsUpToDate(%x)\n",
+ this));
+
+ ChkD (m_pDdeObject);
+ // There is no way to know if a 1.0 server has edited its embedded
+ // object, so we assume it has, to be on the safe side.
+ return ResultFromScode (m_pDdeObject->m_ulObjType==OT_EMBEDDED
+ ? S_FALSE : S_OK);
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::GetUserClassID
+ (CLSID FAR* pClsid)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetUserClassID(%x)\n",
+ this));
+
+ *pClsid = m_pDdeObject->m_clsid;
+ return NOERROR;
+}
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::GetUserType
+ (DWORD dwFormOfType,
+ LPOLESTR * pszUserType)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetUserType(%x)\n",
+ this));
+
+ return ReportResult (0, OLE_S_USEREG, 0, 0);
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::SetExtent
+( DWORD dwAspect, LPSIZEL lpsizel)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::SetExtent(%x)\n",
+ this));
+
+ HANDLE hDdePoke;
+ LPRECT16 lprc;
+
+ ChkD (m_pDdeObject);
+ Puts ("OleObject::SetExtent\n");
+ if (!(dwAspect // at least one bit
+ && !(dwAspect & (dwAspect-1)) // exactly one bit
+ && (dwAspect & DVASPECT_CONTENT))) // a bit we support
+ {
+ return ResultFromScode (DV_E_DVASPECT);
+ }
+
+#ifdef OLD
+ m_pDdeObject->m_cxContentExtent = lpsizel->cx;
+ m_pDdeObject->m_cyContentExtent = lpsizel->cy;
+#endif
+
+ if (!m_pDdeObject->m_pDocChannel)
+ {
+ return OLE_E_NOTRUNNING;
+ }
+
+ lprc = (LPRECT16) wAllocDdePokeBlock (sizeof(RECT16), g_cfBinary, &hDdePoke);
+ lprc->left = lprc->right = (SHORT) min(INT_MAX,lpsizel->cx);
+ lprc->top = lprc->bottom= (SHORT) min(INT_MAX,lpsizel->cy);
+ aStdDocDimensions = GlobalAddAtom (OLESTR("StdDocDimensions"));
+ intrAssert(wIsValidAtom(aStdDocDimensions));
+ GlobalUnlock (hDdePoke);
+ return m_pDdeObject->Poke(aStdDocDimensions, hDdePoke);
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::GetExtent
+( DWORD dwAspect, LPSIZEL lpsizel)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetExtent(%x)\n",
+ this));
+
+ ChkD (m_pDdeObject);
+
+
+#ifdef OLD
+ VDATEPTROUT (lpsizel, SIZEL);
+ if (!(dwAspect // at least one bit
+ && !(dwAspect & (dwAspect-1)) // exactly one bit
+ && !(dwAspect & (DVASPECT_CONTENT | DVASPECT_ICON)))) // a bit we support
+ {
+ return ResultFromScode (DV_E_DVASPECT);
+ }
+
+ if (dwAspect & DVASPECT_CONTENT)
+ {
+ lpsizel->cx = m_pDdeObject->m_cxContentExtent;
+ lpsizel->cy = m_pDdeObject->m_cyContentExtent;
+ }
+
+ return NOERROR;
+#endif
+ return ResultFromScode(E_NOTIMPL);
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::DoVerb
+//
+// Synopsis: Send the server a message asking it to do a verb.
+//
+// Effects: OLE1.0 servers only know how to do a couple of
+// verbs. Specifically, it will respond to PRIMARY,
+// HIDE, OPEN, and SHOW. All others return error
+//
+//
+// Arguments: [iVerb] -- Verb number
+// [lpmsg] -- Window message (ignored)
+// [pActiveSite] -- ActiveSite (ignored)
+// [lindex] -- Index (ignored)
+// [hwndParent] -- (ignored)
+// [lprcPosRect] -- (ignored)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+//
+// Notes:
+//
+// ANSI ALERT!
+//
+// The server is going to accept a command string from us. This string
+// needs to be done in ANSI, since we are going to pass it to old
+// servers. Therefore, the following code generates an ANSI string
+// The following are the supported verb strings
+//
+// [StdShowItem("aItem",FALSE)]
+// [StdDoVerbItem("aItem",verb,FALSE,FALSE)]
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::DoVerb
+ (LONG iVerb, LPMSG lpmsg, LPOLECLIENTSITE pActiveSite,
+ LONG lindex, HWND hwndParent, const RECT FAR* lprcPosRect)
+{
+ WORD len;
+ ULONG size;
+ LPSTR lpdata = NULL;
+ LPSTR lpdataStart = NULL;
+ HANDLE hdata = NULL;
+ BOOL bShow;
+ HRESULT hresult;
+
+ ChkD (m_pDdeObject);
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::DoVerb(%x,iVerb=%x,lindex=%x)\n",
+ this,iVerb,lindex));
+
+ if (iVerb < OLEIVERB_HIDE)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::DoVerb(%x)Returning invalid verb\n",
+ this));
+ return OLEOBJ_E_INVALIDVERB;
+ }
+
+
+ if (iVerb == OLEIVERB_HIDE)
+ {
+ intrDebugOut((DEB_ITRACE,"::DoVerb(%x) OLEIVERB_HIDE\n",this));
+
+ if (m_pDdeObject->m_fVisible || OT_LINK==m_pDdeObject->m_ulObjType)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::DoVerb(%x) CANNOT_DOVERB_NOW\n",this));
+ return OLEOBJ_S_CANNOT_DOVERB_NOW;
+ }
+
+ intrDebugOut((DEB_ITRACE,"::DoVerb(%x) returns NOERROR\n",this));
+ return NOERROR;
+ }
+
+ //
+ // Calculate the number of bytes needed to pass the
+ // execute command to the server.
+ //
+ if (bShow = (iVerb == OLEIVERB_SHOW
+ || iVerb == OLEIVERB_OPEN
+ || m_pDdeObject->m_bOldSvr))
+ {
+ //
+ // [StdShowItem("aItem",FALSE)]
+ //
+
+ len = 23 + wAtomLenA (m_pDdeObject->m_aItem) + 1;
+
+ }
+ else
+ {
+ // [StdDoVerbItem("aItem",verb,FALSE,FALSE)]
+ len = 32 + 10 /* for verb */ + wAtomLenA (m_pDdeObject->m_aItem) + 1;
+
+ }
+
+ if (!(hdata = GlobalAlloc (GMEM_DDESHARE, size = len)))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::DoVerb(%x) cannot alloc %x bytes\n",
+ this,size));
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+
+ if (!(lpdata = (LPSTR)GlobalLock (hdata)))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::DoVerb(%x) cannot lock\n",
+ this));
+ GlobalFree (hdata);
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ lpdataStart = lpdata;
+
+
+ strcpy (lpdata, bShow ? "[StdShowItem(\"" : "[StdDoVerbItem(\"");
+ len = strlen (lpdata);
+ lpdata += len;
+
+ // For links
+ if (m_pDdeObject->m_aItem)
+ lpdata += GlobalGetAtomNameA (m_pDdeObject->m_aItem, lpdata, size - len);
+
+ if (!bShow) {
+ wsprintfA (lpdata,"\",%lu,TRUE,FALSE)]", iVerb);
+ } else {
+ strcpy (lpdata, "\")]");
+ // apps like excel and wingraph do not support activate at item level.
+ }
+
+ intrDebugOut((DEB_ITRACE,"::DoVerb(%x)lpdata(%s)\n",this,lpdataStart));
+
+ Assert (strlen(lpdata) < size);
+
+ GlobalUnlock (hdata);
+
+ hresult = m_pDdeObject->Execute (m_pDdeObject->m_pDocChannel, hdata);
+
+ if (NOERROR==hresult)
+ {
+ // Assume doing a verb makes the server visible.
+ // This is not strictly true.
+ m_pDdeObject->DeclareVisibility (TRUE);
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::DoVerb(%x)Execute returned %x\n",
+ this,
+ hresult));
+ }
+ return hresult;
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::SetHostNames
+//
+// Synopsis: Sets the host names
+//
+// Effects:
+//
+// Arguments: [szContainerApp] -- Name of container app
+// [szContainerObj] -- Name of contained object
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+//
+// Notes:
+// ANSI ALERT!
+//
+// The server is going to accept a command string from us. This string
+// needs to be done in ANSI, since we are going to pass it to old
+// servers. Therefore, the following code generates an ANSI string
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::SetHostNames
+(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::SetHostNames(%x,App=%ws,Obj=%ws)\n",
+ this,szContainerApp,szContainerObj));
+
+ WORD cbName;
+ WORD wSize;
+ LPSTR lpBuf;
+ HANDLE hDdePoke;
+
+ ChkD (m_pDdeObject);
+
+ VDATEPTRIN (szContainerApp, char);
+
+ if (!m_pDdeObject->m_pDocChannel)
+ return NOERROR;
+ if (szContainerObj==NULL)
+ szContainerObj=OLESTR("");
+
+ if (szContainerApp[0]=='\0')
+ szContainerApp = OLESTR("Container Application");
+
+ //
+ // The OLE 1.0 server is going to want ANSI strings.
+ // convert the two that we have
+ //
+
+ char pszContainerApp[MAX_STR];
+ char pszContainerObj[MAX_STR];
+
+ if (WideCharToMultiByte(CP_ACP,
+ 0,
+ szContainerApp,
+ -1,
+ pszContainerApp,
+ MAX_STR,
+ NULL,
+ NULL) == FALSE)
+ {
+ intrDebugOut((DEB_ERROR,
+ "::SetHostNames(%x) can't convert szContainerApp(%ws) err=%x\n",
+ this,szContainerApp,GetLastError()));
+
+ //
+ // Couldn't convert string
+ //
+ return(E_UNEXPECTED);
+ }
+ if (WideCharToMultiByte(CP_ACP,
+ 0,
+ szContainerObj,
+ -1,
+ pszContainerObj,
+ MAX_STR,
+ NULL,
+ NULL) == FALSE)
+ {
+ intrDebugOut((DEB_ERROR,
+ "::SetHostNames(%x) can't convert szContainerObj(%ws) err=%x\n",
+ this,szContainerObj,GetLastError));
+
+ //
+ // Couldn't convert string
+ //
+ return(E_UNEXPECTED);
+ }
+
+
+ //
+ // We have found through experience that some OLE applications, like
+ // Clipart, use a fixed size buffer for these names. Therefore, we
+ // are going to limit the sizes of the strings, in case they are
+ // too long to send. We do this by always sticking a NULL at offset
+ // 80 in the file.
+ //
+ pszContainerApp[80]=0;
+ pszContainerObj[80]=0;
+
+ WORD cbObj;
+
+ wSize = (cbName = strlen(pszContainerApp)+1)
+ + (cbObj = strlen(pszContainerObj)+1)
+ + 2 * sizeof(WORD); // for the two offsets
+
+ lpBuf = wAllocDdePokeBlock ((DWORD)wSize, g_cfBinary, &hDdePoke);
+ ((WORD FAR*)lpBuf)[0] = 0;
+ ((WORD FAR*)lpBuf)[1] = cbName;
+ lpBuf += 2*sizeof(WORD);
+ memcpy (lpBuf,pszContainerApp,cbName);
+ memcpy (lpBuf+cbName, pszContainerObj,cbObj);
+ GlobalUnlock (hDdePoke);
+ aStdHostNames = GlobalAddAtom (OLESTR("StdHostNames"));
+ intrAssert(wIsValidAtom(aStdHostNames));
+ m_pDdeObject->Poke(aStdHostNames, hDdePoke);
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::Close
+ (DWORD dwSaveOption)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::Close(%x,dwSaveOption=%x)\n",
+ this,dwSaveOption));
+
+
+ ChkDR (m_pDdeObject);
+
+ HRESULT hresult;
+ if (m_pDdeObject->m_fDidSendOnClose)
+ return ResultFromScode (RPC_E_CANTCALLOUT_INASYNCCALL);
+
+ if (((OLECLOSE_SAVEIFDIRTY == dwSaveOption) ||
+ (OLECLOSE_PROMPTSAVE==dwSaveOption)) &&
+ (m_pDdeObject->m_clsid != CLSID_Package))
+ {
+ // Packager gives truncated native data (header info with no
+ // actual embedded file) if you DDE_REQUEST it. Bug 3103
+ Update(); // IOleObject::Update
+ m_pDdeObject->OleCallBack (ON_SAVE,NULL);
+ }
+ RetZ (m_pDdeObject->m_pDocChannel);
+ hresult=m_pDdeObject->Execute (m_pDdeObject->m_pDocChannel,
+ wNewHandle ((LPSTR)&achStdCloseDocument,sizeof(achStdCloseDocument)),
+ TRUE);
+ if (NOERROR==hresult)
+ m_pDdeObject->m_fDidStdCloseDoc = TRUE;
+
+ // Client sends StdCloseDocument. Srvr sends ACK. Srvr may or may not
+ // send Terminate. We may interpret the TERMINATE the server sends
+ // as the reply to ours even if he posted first. But since some servers
+ // post first and others wait for the client, this is what we need to do.
+
+ BOOL fVisible = m_pDdeObject->m_fWasEverVisible; // TermConv clears this flag
+ m_pDdeObject->TermConv (m_pDdeObject->m_pDocChannel);
+ if (!fVisible)
+ m_pDdeObject->MaybeUnlaunchApp();
+
+ return hresult;
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::SetMoniker
+ (DWORD dwWhichMoniker, LPMONIKER pmk)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::SetMoniker(%x,dwWhichMoniker=%x)\n",
+ this,dwWhichMoniker));
+
+ ChkD (m_pDdeObject);
+ Puts ("OleObject::SetMoniker\r\n");
+ // we ignore this always
+ return NOERROR;
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::GetMoniker
+ (DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER FAR* ppmk)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetMoniker(%x,dwWhichMoniker=%x)\n",
+ this,dwWhichMoniker));
+
+ ChkD (m_pDdeObject);
+ if (m_pDdeObject->m_pOleClientSite)
+ return m_pDdeObject->m_pOleClientSite->GetMoniker(dwAssign,
+ dwWhichMoniker, ppmk);
+ else {
+ // no client site
+ *ppmk = NULL;
+ return ReportResult(0, E_UNSPEC, 0, 0);
+ }
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::InitFromData
+ (LPDATAOBJECT pDataObject, BOOL fCreation, DWORD dwReserved)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::InitFromData(%x)\n",
+ this));
+
+ Puts ("OleObject::InitFromData\r\n");
+ return ReportResult(0, E_NOTIMPL, 0, 0);
+}
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::GetClipboardData
+ (DWORD dwReserved, LPDATAOBJECT FAR* ppDataObject)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetClipboardData(%x)\n",
+ this));
+
+ Puts ("OleObject::GetClipboardData\r\n");
+ return ReportResult(0, E_NOTIMPL, 0, 0);
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::Advise
+ (IAdviseSink FAR* pAdvSink,
+ DWORD FAR* pdwConnection)
+{
+ HRESULT hres;
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::Advise(%x)\n",
+ this));
+
+ ChkD (m_pDdeObject);
+ Puts ("OleObject::Advise\n");
+ // Esstablish a DDE advise connection.
+ if (m_pDdeObject->m_ulObjType == OT_EMBEDDED
+ && !m_pDdeObject->m_fDidAdvNative)
+ {
+ // Embedded case.
+ // Always advise on Save and Close.
+ if (hres = m_pDdeObject->AdviseOn (g_cfNative, ON_SAVE))
+ return hres;
+ if (hres = m_pDdeObject->AdviseOn (g_cfNative, ON_CLOSE))
+ return hres;
+ if (m_pDdeObject->m_clsid == CLSID_MSDraw)
+ {
+ // MSDraw has (another) bug. If you do not do an Advise on
+ // presentation, then File.Update does not work, and you
+ // cannot close the app unless you answer "no" to the update
+ // dialog. This would happen when you "Display As Icon"
+ // because ordinarily there is no need to advise on presentation.
+ // The following "unnecessary" advise fixes this problem.
+ if (hres = m_pDdeObject->AdviseOn (CF_METAFILEPICT, ON_SAVE))
+ return hres;
+ if (hres = m_pDdeObject->AdviseOn (CF_METAFILEPICT, ON_CLOSE))
+ return hres;
+ }
+ }
+ else {
+ /* Linked case */
+ if (hres = m_pDdeObject->AdviseOn (g_cfBinary, ON_RENAME))
+ return hres;
+ }
+ RetZS (m_pDdeObject->m_pOleAdvHolder, E_OUTOFMEMORY);
+ return m_pDdeObject->m_pOleAdvHolder->Advise (pAdvSink, pdwConnection);
+}
+
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::Unadvise
+ (DWORD dwConnection)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::Unadvise(%x,dwConnection=%x)\n",
+ this,dwConnection));
+
+ HRESULT hres;
+ ChkD (m_pDdeObject);
+
+ // Terminate the DDE advise connection
+ if (m_pDdeObject->m_ulObjType == OT_EMBEDDED)
+ {
+ // Embedded case.
+ if (hres = m_pDdeObject->UnAdviseOn (g_cfNative, ON_SAVE))
+ return hres;
+ if (hres = m_pDdeObject->UnAdviseOn (g_cfNative, ON_CLOSE))
+ return hres;
+ }
+ else
+ {
+ /* Linked case */
+ if (hres = m_pDdeObject->UnAdviseOn (g_cfBinary, ON_RENAME))
+ return hres;
+ }
+ RetZS (m_pDdeObject->m_pOleAdvHolder, E_OUTOFMEMORY);
+ return m_pDdeObject->m_pOleAdvHolder->Unadvise (dwConnection);
+}
+
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::EnumAdvise
+ (THIS_ LPENUMSTATDATA FAR* ppenumAdvise)
+{
+ ChkD (m_pDdeObject);
+ RetZS (m_pDdeObject->m_pOleAdvHolder, E_OUTOFMEMORY);
+ return m_pDdeObject->m_pOleAdvHolder->EnumAdvise(ppenumAdvise);
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::GetMiscStatus
+ (DWORD dwAspect,
+ DWORD FAR* pdwStatus)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::GetMiscStatus(%x)\n",
+ this));
+
+ VDATEPTRIN (pdwStatus, DWORD);
+ *pdwStatus = 0L;
+ return ResultFromScode (OLE_S_USEREG);
+}
+
+
+
+STDMETHODIMP NC(CDdeObject,COleObjectImpl)::SetColorScheme
+ (LPLOGPALETTE lpLogpal)
+{
+ HANDLE hDdePoke;
+ LPLOGPALETTE lptmpLogpal;
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::SetColorScheme(%x)\n",
+ this));
+
+ ChkD (m_pDdeObject);
+
+ if (!m_pDdeObject->m_pDocChannel)
+ return NOERROR;
+
+ aStdColorScheme = GlobalAddAtom (OLESTR("StdColorScheme"));
+ intrAssert(wIsValidAtom(aStdColorScheme));
+
+ DWORD dwSize = (lpLogpal->palNumEntries - 1) * sizeof(PALETTEENTRY)
+ + sizeof(LOGPALETTE);
+ lptmpLogpal = (LPLOGPALETTE) wAllocDdePokeBlock (dwSize, g_cfBinary, &hDdePoke);
+ memcpy(lptmpLogpal, lpLogpal, dwSize);
+ GlobalUnlock(hDdePoke);
+
+ return m_pDdeObject->Poke(aStdColorScheme, hDdePoke);
+}
+
+
+
+#ifdef _DEBUG
+STDMETHODIMP_(void) NC(CDdeObject,CDebug)::Dump( IDebugStream FAR * pdbstm)
+{
+}
+
+STDMETHODIMP_(BOOL) NC(CDdeObject,CDebug)::IsValid( BOOL fSuspicious )
+{
+ if( m_pDdeObject->m_refs > 0 && m_pDdeObject->m_chk == chkDdeObj )
+ return TRUE;
+ else
+ return FALSE;
+}
+#endif
diff --git a/private/ole32/com/remote/dde/client/ddeproxy.cxx b/private/ole32/com/remote/dde/client/ddeproxy.cxx
new file mode 100644
index 000000000..f02ee8137
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/ddeproxy.cxx
@@ -0,0 +1,2899 @@
+/*
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddeproxy.cpp
+
+Abstract:
+
+ This module contains the code for the dde proxy (wrapper)
+
+Author:
+
+ Srini Koppolu (srinik) 22-June-1992
+ Jason Fuller (jasonful) 24-July-1992
+*/
+#include "ddeproxy.h"
+#include <tls.h>
+
+DebugOnly (static UINT v_cDdeObjects=0;)
+/*
+ * IMPLEMENTATION of CDdeObject
+ *
+ */
+
+#ifdef OLD
+#define UpdateExtent(old,new) do { if ((long)new!=old) {old=(long)new; } } while (0)
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateDdeClientHwnd
+//
+// Synopsis: Creates a per thread ClientDde window.
+//
+// Effects: This window is created so we can keep a list of windows that
+// need to be cleaned up in the event the thread dies or OLE32 is
+// unloaded. In the case of DLL unload, we will fault if we don't
+// cleanup this window, since user will dispatch messages to
+// non-existant code. The easy way to track these windows is to
+// make them children of a common per thread window.
+//
+// This routine is called by the TLSGetDdeClient() routine to
+// create a window per thread. This window doesn't need to respond
+// to DDE Initiates.
+//
+// Arguments: [void] --
+//
+// Returns: HWND to DdeClientWindow.
+//
+// History: 12-10-94 kevinro Created
+//
+//----------------------------------------------------------------------------
+
+HWND CreateDdeClientHwnd(void)
+{
+ return SSCreateWindowExA(0,"STATIC","DdeClientHwnd",WS_DISABLED,
+ 0,0,0,0,NULL,NULL,hinstSO,NULL);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetDdeCallControlInterface
+//
+// Synopsis: Gets the thread specific instance of the DDE CallControl
+//
+// Effects: If there is already a per thread CallControl interface,
+// AddRef() it and return the value. Otherwise, get one and
+// set it in the TLS data structure. The TLS structure is
+// a global per thread structure that contains various values.
+//
+// Each threads per instance version of the CallControl will
+// be stored in a global place. ReleaseDdeCallControlInterface
+// is used to free up instances of the interface.
+//
+// Arguments: (none)
+//
+// Requires:
+//
+// Returns: Per thread instance of ICallControl. NULL if error
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-13-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+PCALLCONTROL GetDdeCallControlInterface()
+{
+ PCALLCONTROL pDdeControl = (PCALLCONTROL)TLSGetDdeCallControl();
+
+ if (pDdeControl != NULL)
+ {
+ pDdeControl->AddRef();
+ return(pDdeControl);
+ }
+ //
+ // There wasn't one in the TLS data. Create one, and return it.
+ //
+ ORIGINDATA origindata;
+
+ //
+ // There is a single channel control (static implementation)
+ // for all DDE windows in the process. The hwndCli is set
+ // to NULL, since DDE messages are handled specially by
+ // the MessageFilter code.
+ //
+ origindata.pChCont = (PCHANNELCONTROL)&g_CDdeChannelControl;
+ origindata.CallOrigin = CALLORIGIN_DDE;
+ origindata.hwnd = (HWND)0;
+ origindata.wFirstMsg = WM_DDE_FIRST;
+ origindata.wLastMsg = WM_DDE_LAST;
+
+ if(CoGetCallControl(&origindata, &pDdeControl) == NOERROR)
+ {
+ TLSSetDdeCallControl(pDdeControl);
+ }
+ else
+ {
+ intrAssert(!"Could not CoGetCallControl");
+ pDdeControl = NULL;
+ }
+ return(pDdeControl);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReleaseDdeCallControlInterface
+//
+// Synopsis: This function will release the per thread CallControl
+// interface. If the Release() returns zero, then the
+// function will set the per thread instance to NULL.
+//
+// Effects:
+//
+// Arguments: (none)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-13-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void ReleaseDdeCallControlInterface()
+{
+ PCALLCONTROL pDdeControl = (PCALLCONTROL)TLSGetDdeCallControl();
+
+ intrAssert(pDdeControl != NULL);
+#if DBG == 1
+ if (pDdeControl == NULL)
+ {
+ DebugBreak();
+ }
+#endif
+ if ((pDdeControl != NULL) && (pDdeControl->Release() == 0))
+ {
+ TLSSetDdeCallControl(NULL);
+ }
+}
+
+
+// CreateDdeProxy
+//
+// This corresponds to ProxyManager::Create in 2.0
+//
+
+
+INTERNAL_ (LPUNKNOWN) CreateDdeProxy
+ (IUnknown * pUnkOuter,
+ REFCLSID clsid)
+{
+ LPUNKNOWN punk;
+ intrDebugOut((DEB_ITRACE,"CreateDdeProxy(pUnkOuter=%x)\n",pUnkOuter));
+ punk = CDdeObject::Create (pUnkOuter, clsid);
+ intrDebugOut((DEB_ITRACE,
+ "CreateDdeProxy(pUnkOuter=%x) returns %x\n",
+ pUnkOuter,
+ punk));
+ return punk;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::Create
+//
+// Synopsis: Creates a CDdeObject
+//
+// Effects:
+//
+// Arguments: [pUnkOuter] -- Controlling IUnknown
+// [clsid] -- OLE1 ClassID
+// [ulObjType] -- Object type. Optional: def to OT_EMBEDDED
+// [aTopic] -- Atom of link. Optional: def to NULL
+// [szItem] -- String for link object (def to NULL)
+// [ppdde] -- Output pointer to CDdeObject (def to NULL)
+// [fAllowNullClsid] -- Is NULL clsid OK? Default: false
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(LPUNKNOWN) CDdeObject::Create
+ (IUnknown * pUnkOuter,
+ REFCLSID clsid,
+ ULONG ulObjType,// optional, default OT_EMBEDDED
+ ATOM aTopic, // optional, only relevant if ulObjType==OT_LINK
+ LPOLESTR szItem, // optional, only relevant if ulObjType==OT_LINK
+ CDdeObject * * ppdde, // optional, thing created
+ BOOL fAllowNullClsid) // default FALSE
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::Create(%x,ulObjType=%x)\n",
+ pUnkOuter,
+ ulObjType));
+
+ CDdeObject * pDdeObject;
+ static int iTopic=1; // used to make topic names unique
+ WCHAR szTopic[30];
+ Assert (ulObjType==OT_LINK || ulObjType==OT_EMBEDDED);
+
+ Assert (ulObjType != OT_LINK || wIsValidAtom(aTopic));
+ if (ppdde)
+ *ppdde = NULL;
+
+ if (NULL==(pDdeObject = new CDdeObject (pUnkOuter))
+ || NULL == pDdeObject->m_pDataAdvHolder
+ || NULL == pDdeObject->m_pOleAdvHolder)
+ {
+ Assert (!"new CDdeObject failed");
+ return NULL;
+ }
+
+ pDdeObject->m_refs = 1;
+ pDdeObject->m_clsid = clsid;
+ pDdeObject->m_aClass = wAtomFromCLSID(clsid);
+
+#ifdef OLE1INTEROP
+
+ pDdeObject->m_fOle1interop = TRUE;
+
+#endif
+
+ if (ulObjType==OT_LINK)
+ {
+
+ pDdeObject->m_aTopic = wDupAtom (aTopic);
+ pDdeObject->m_aItem = wGlobalAddAtom (szItem);
+ // Never close a linked document
+ pDdeObject->m_fNoStdCloseDoc = TRUE;
+ }
+ else
+ {
+ // This string may actually be visible in the Window Title Bar for a sec.
+ InterlockedIncrement((long *)&iTopic);
+ wsprintf (szTopic,OLESTR("Embedded Object #%u"), iTopic);
+ Assert (lstrlenW(szTopic) < 30);
+ pDdeObject->m_aItem = NULL;
+ pDdeObject->m_aTopic = wGlobalAddAtom (szTopic);
+ }
+ pDdeObject->m_bOldSvr = wIsOldServer (pDdeObject->m_aClass);
+ pDdeObject->m_ulObjType = ulObjType;
+
+ // we can only run if we have a MFI
+ pDdeObject->m_aExeName = wGetExeNameAtom(clsid);
+
+ intrDebugOut((DEB_ITRACE,
+ "::Create(%x,aTopic=%x,aItem=%x,szItem=%ws,aExeName=%x)\n",
+ pDdeObject,
+ pDdeObject->m_aTopic,
+ pDdeObject->m_aItem,
+ szItem?szItem:L"<NULL>",
+ pDdeObject->m_aExeName));
+
+ if (ppdde)
+ *ppdde = pDdeObject;
+ return &pDdeObject->m_Unknown;
+}
+
+
+
+// Constructor
+CDdeObject::CDdeObject (IUnknown * pUnkOuter) :
+ m_Unknown(this),
+ CONSTRUCT_DEBUG
+ m_Data(this),
+ m_Ole(this),
+ m_PersistStg(this),
+ m_ProxyMgr(this),
+ m_OleItemContainer(this)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::CDdeObject(%x)\n",this));
+ if (!pUnkOuter)
+ pUnkOuter = &m_Unknown;
+
+ m_pUnkOuter = pUnkOuter;
+ m_bRunning = FALSE;
+ m_pOleClientSite = NULL;
+ m_pstg = NULL;
+ m_pSysChannel = NULL;
+ m_pDocChannel = NULL;
+ m_bInitNew = NULL;
+ m_hNative = NULL;
+ m_hPict = NULL;
+ m_hExtra = NULL;
+ m_cfExtra = NULL;
+ m_cfPict = 0;
+ m_aItem = NULL;
+ m_iAdvSave = 0;
+ m_iAdvClose = 0;
+ m_iAdvChange = 0;
+ m_fDidAdvNative = FALSE;
+ m_pOleAdvHolder = NULL;
+ m_pDataAdvHolder = NULL;
+ m_fDidSendOnClose = FALSE;
+ m_fNoStdCloseDoc = FALSE;
+ m_fDidStdCloseDoc = FALSE;
+ m_fDidStdOpenDoc = FALSE;
+ m_fDidGetObject = FALSE;
+ m_fDidLaunchApp = FALSE;
+ m_fUpdateOnSave = TRUE;
+ m_fVisible = FALSE;
+ m_fWasEverVisible = FALSE;
+ m_fCalledOnShow = FALSE;
+ m_fGotCloseData = FALSE;
+ m_cLocks = 1; // connections are initially locked
+ m_chk = chkDdeObj;
+ m_ptd = NULL;
+ m_fDoingSendOnDataChange = FALSE;
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ _DelayDelete = NoDelay;
+#endif // _CHICAGO_
+
+ CreateOleAdviseHolder (&m_pOleAdvHolder);
+ Assert (m_pOleAdvHolder);
+ CreateDataAdviseHolder (&m_pDataAdvHolder);
+ Assert (m_pDataAdvHolder);
+
+#ifdef OLD
+ m_cxContentExtent = 2000; // 2 centimeters , totally random default
+ m_cyContentExtent = 2000;
+#endif
+
+ m_wTerminate = Terminate_None;
+
+ DebugOnly (v_cDdeObjects++;)
+ Putsi (v_cDdeObjects);
+}
+
+
+
+CDdeObject::~CDdeObject
+ (void)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::~CDdeObject(%x)\n",this));
+
+ if (m_pDocChannel)
+ {
+ intrDebugOut((DEB_IWARN , "Abnormal situation: Doc Channel not deleted. Server died?"));
+ delete m_pDocChannel;
+ }
+ if (m_pSysChannel)
+ {
+ Warn ("Abnormal situation: Sys Channel not deleted. Server died?");
+ delete m_pSysChannel;
+ }
+ if (m_hNative)
+ {
+ GlobalFree(m_hNative);
+ }
+
+ if (m_hPict)
+ {
+ wFreeData (m_hPict, m_cfPict, TRUE);
+ }
+
+ if (m_hExtra)
+ {
+ wFreeData (m_hExtra, m_cfExtra, TRUE);
+ }
+
+ // release all the pointers that we remember
+
+ if (m_pOleClientSite)
+ {
+ DeclareVisibility (FALSE);
+ m_pOleClientSite->Release();
+ }
+
+ if (m_pDataAdvHolder)
+ m_pDataAdvHolder->Release();
+
+ if (m_pOleAdvHolder)
+ m_pOleAdvHolder->Release();
+
+ if (m_pstg)
+ m_pstg->Release();
+
+ if (m_aExeName)
+ GlobalDeleteAtom (m_aExeName);
+
+ if (m_aClass)
+ GlobalDeleteAtom (m_aClass);
+
+ if (m_aTopic)
+ GlobalDeleteAtom (m_aTopic);
+
+ if (m_aItem)
+ GlobalDeleteAtom (m_aItem);
+
+ if (m_ptd)
+ delete m_ptd;
+
+ m_chk = 0;
+ DebugOnly (v_cDdeObjects--;)
+ Putsi (v_cDdeObjects);
+}
+
+
+
+
+// Handles WM_DDE_ACKs received while in initiate state. If this is the first
+// reply, save its window handle. If multiple replies are received, take the
+// one with the prefered instance, if there is one. Keep a count of
+// WM_DDE_TERMINATEs we send so that we don't shut the window until we get
+// all of the responses for WM_DDE_TERMINATEs.
+
+
+INTERNAL_(void) CDdeObject::OnInitAck (LPDDE_CHANNEL pChannel, HWND hwndSvr)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::OnInitAck(%x,hwndSvr=%x)\n",this,hwndSvr));
+#ifdef _MAC
+#else
+ if (!IsWindow (hwndSvr))
+ {
+ Assert (0);
+ return;
+ }
+ if (pChannel->hwndSvr) { // if we already have a handle
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::OnInitAck(%x,hwndSvr=%x) Already have hwndSvr=%x\n",
+ this,
+ hwndSvr,
+ pChannel->hwndSvr));
+ // just take the very first one. Direct post is OK
+ MPostWM_DDE_TERMINATE(hwndSvr,pChannel->hwndCli);
+ // Expect an extra WM_DDE_TERMINATE
+ ++pChannel->iExtraTerms;
+ } else {
+ // this is the server we want
+ pChannel->hwndSvr = hwndSvr;
+ pChannel->iExtraTerms = NULL;
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::OnInitAck(%x,hwndSvr=%x) Established Connection\n",
+ this,
+ hwndSvr,
+ pChannel->hwndSvr));
+ }
+#endif _MAC
+}
+
+INTERNAL_(BOOL) CDdeObject::OnAck (LPDDE_CHANNEL pChannel, LONG lParam)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::OnAck(%x,lParam=%x)\n",this,lParam));
+
+ BOOL retval = TRUE;
+ ATOM aItem;
+ WORD wStatus;
+ HANDLE hData;
+
+ if( pChannel->iAwaitAck == AA_EXECUTE)
+ {
+ wStatus = GET_WM_DDE_EXECACK_STATUS( NULL, lParam );
+ hData = GET_WM_DDE_EXECACK_HDATA( NULL, lParam );
+ }
+ else
+ {
+ wStatus = GET_WM_DDE_ACK_STATUS( NULL, lParam );
+ aItem = GET_WM_DDE_ACK_ITEM( NULL, lParam );
+ }
+
+
+ // check for busy bit
+ if (wStatus & 0x4000)
+ {
+ // we got busy from the server.
+ pChannel->fRejected = TRUE;
+ // tell the wait loop that we got a busy ack
+ //CoSetAckState(pChannel->pCI , FALSE,TRUE, SERVERCALLEX_RETRYLATER);
+ intrDebugOut((DEB_ITRACE,"::OnAck(%x) Busy SetCallState(SERVERCALLEX_RETRYLATER)\n",this));
+ pChannel->pCallCont->SetCallState(pChannel->pCD, SERVERCALLEX_RETRYLATER, NOERROR);
+ return TRUE;
+ }
+
+ // just reset the flag always
+ m_wTerminate = Terminate_None;
+
+ intrDebugOut((DEB_ITRACE,
+ "::OnAck(%x)aItem=%x(%ws) wStatus=\n",
+ this,
+ aItem,
+ wAtomName(aItem),
+ wStatus));
+
+ if (pChannel->iAwaitAck == AA_EXECUTE)
+ {
+ GlobalFree (hData);
+ pChannel->hCommands = NULL;
+ }
+ else
+ {
+ if (hData)
+ GlobalDeleteAtom ((ATOM)hData);
+ }
+
+
+ // even if the client got terminate we have to go thru this path.
+
+ if (pChannel->wTimer) {
+ KillTimer (pChannel->hwndCli, 1);
+ pChannel->wTimer = 0;
+ }
+
+
+ if (pChannel->iAwaitAck == AA_POKE)
+ // We have to free the data first. OnAck can trigger
+ // another Poke (like pokehostnames)
+ wFreePokeData (pChannel, (m_bOldSvr && m_aClass==aMSDraw));
+
+
+ if (!(wStatus & POSITIVE_ACK))
+ {
+ intrDebugOut((DEB_ITRACE,"::OnAck(%x) OnAck got an ack with fAck==FALSE.\n",this));
+
+ // A negative ack is OK when doing a temporary advise from
+ // IsFormatAvailable(). Also, apps don't seem to positively
+ // ack all unadvises.
+
+ // review: johannp : this is the case were have to inform the reply rejected call
+
+ retval = FALSE;
+ // we got the ack and can leave the wait loop
+ //CoSetAckState(pChannel->pCI, FALSE);
+
+ intrDebugOut((DEB_ITRACE,
+ "::OnAck(%x) ***_ NACK _*** SetCallState(ISHANDLED,RPC_E_DDE_NACK)\n",
+ this));
+
+ pChannel->pCallCont->SetCallState(pChannel->pCD, SERVERCALLEX_ISHANDLED, RPC_E_DDE_NACK);
+
+ // MSDraw frees hOptions even on a NACK, despite official DDE rules.
+ if (pChannel->iAwaitAck == AA_ADVISE && m_clsid != CLSID_MSDraw)
+ GlobalFree (pChannel->hopt);
+ }
+ else
+ {
+ // we got the ack and can leave the wait loop
+ // CoSetAckState(pChannel->pCI, FALSE);
+ intrDebugOut((DEB_ITRACE,
+ "::OnAck(%x) POSITIVE_ACK SetCallState(SERVERCALLEX_ISHANDLED)\n",
+ this));
+ pChannel->pCallCont->SetCallState(pChannel->pCD, SERVERCALLEX_ISHANDLED, NOERROR);
+ }
+
+ pChannel->hopt = NULL;
+ pChannel->iAwaitAck = NULL;
+ return retval;
+
+}
+
+
+
+
+
+INTERNAL_(void) CDdeObject::OnTimer (LPDDE_CHANNEL pChannel)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::OnTimer(%x)\n",this));
+ // Since there is only one timer for each client, just
+ // repost the message and delete the timer.
+#ifdef _MAC
+#else
+ KillTimer (pChannel->hwndCli, 1);
+ pChannel->wTimer = 0;
+
+ if (wPostMessageToServer(pChannel, pChannel->wMsg, pChannel->lParam,FALSE))
+ return ;
+
+ // Postmessage failed. We need to getback to the main stream of
+ // commands for the object.
+ OnAck (pChannel, pChannel->lParam);
+#endif _MAC
+}
+
+
+
+// Called when we get a WM_DDE_DATA message in reponse to
+// a DDE_REQUEST we sent to check if a format is available.
+//
+INTERNAL CDdeObject::OnDataAvailable
+ (LPDDE_CHANNEL pChannel,
+ HANDLE hDdeData,
+ ATOM aItem)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::OnDataAvailable(%x)\n",this));
+ CLIPFORMAT cf;
+ Assert (AA_REQUESTAVAILABLE == pChannel->iAwaitAck);
+ intrAssert( wIsValidAtom(aItem));
+
+ DDEDATA * pDdeData = (DDEDATA *) GlobalLock (hDdeData);
+ RetZS (pDdeData, E_OUTOFMEMORY);
+ if (!pDdeData->fAckReq && aItem)
+ {
+ GlobalDeleteAtom (aItem);
+ }
+ cf = pDdeData->cfFormat;
+ GlobalUnlock (hDdeData);
+ wFreeData (wHandleFromDdeData (hDdeData), cf);
+ return NOERROR;
+}
+
+
+
+// Called for WM_DDE_DATA message. If data is from an ADVISE-ON-CLOSE and this
+// is there are no more outstanding ADVISE-ON-CLOSE requests, close the
+// document and end the conversation.
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::OnData
+//
+// Synopsis: Called when a WM_DDE_DATA message is recieved. If the data
+// is from an ADVISE_ON_CLOSE, and there are no more
+// outstanding ADVISE_ON_CLOSE request, close the document
+// and end the conversation.
+//
+// Effects: The effects of this routine are complex.
+//
+// Wow! What else can be said. This routine does alot of stuff in response
+// to an incoming WM_DDE_DATA message. There are basically two flavors of
+// response here. First is when we were expecting to get this result,
+// in which case we know what we wanted to do with the data. Second is
+// when the data just arrives, but we didn't expect it. These cases could
+// indicate that the server is shutting down.
+//
+//
+// Arguments: [pChannel] -- The DDE channel recieving the message
+// [hDdeData] -- Handle to the data
+// [aItem] -- Atom to the item
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-16-94 kevinro Restructured and commented
+//
+// Notes:
+//
+//
+// Be extra careful you change this routine.
+// This is especially neccesary if you are going to exit early. The
+// way that hDdeData is free'd or kept should be understood before
+// changing.
+//
+//
+//----------------------------------------------------------------------------
+INTERNAL CDdeObject::OnData
+ (LPDDE_CHANNEL pChannel,
+ HANDLE hDdeData,
+ ATOM aItem)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::OnData(%x,pChannel=%x,hDdeData=%x,aItem=%x(%s)iAwaitAck=%x\n",
+ this,
+ pChannel,
+ hDdeData,
+ aItem,
+ wAtomNameA(aItem),
+ pChannel->iAwaitAck));
+#ifdef _MAC
+#else
+ DDEDATA * lpDdeData = NULL;
+ BOOL fAck = TRUE;
+ int iAdvOpt;
+ BOOL fCallBack;
+ HRESULT hresult = NOERROR;
+
+ ICallControl *lpCallCont = pChannel->pCallCont;
+ intrAssert(lpCallCont != NULL);
+ BOOL fRequested = FALSE;
+
+ intrAssert(wIsValidAtom(aItem));
+
+ int iAwaitAck = pChannel->iAwaitAck;
+
+ //
+ // If we were waiting for this data, then we are sitting in the
+ // modal loop. Set the call state on the call control interface
+ // to indicate that a response was recieved. Pass NOERROR to indicate
+ // that there was success. If an error is determined later, then
+ // the state will be set a second time.
+ //
+
+ if ((AA_REQUEST == iAwaitAck) || (AA_REQUESTAVAILABLE == iAwaitAck))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::OnData(%x) AA_REQUEST/AVAILABLE pCD->id=%x\n",
+ this,
+ pChannel->pCD?pChannel->pCD->id:0xBAD));
+
+ //
+ // Regardless of the outcome of this call, we have recieved a
+ // response. Set the Awaiting Ack state to nothing.
+ //
+ pChannel->iAwaitAck = AA_NONE;
+
+ //
+ // Determine if this channels call data is valid, and is in use.
+ // If the channel is in use, then then its id will not be
+ // CALLDATAID_UNUSED. If the call data isn't valid, then something
+ // is wrong, but there isn't a good way to recover.
+ //
+
+ if (pChannel->pCD && (pChannel->pCD->id != CALLDATAID_UNUSED))
+ {
+ // call only if there is a call id
+ //CoSetAckState(pChannel->pCI, FALSE); // clear waiting flag
+ intrDebugOut((DEB_ITRACE,"::OnData(%x) SetCallState(SERVERCALLEX_ISHANDLED)\n",this));
+ pChannel->pCallCont->SetCallState(pChannel->pCD,
+ SERVERCALLEX_ISHANDLED,
+ NOERROR);
+ }
+ }
+
+
+ //
+ // Check the string for aItem, looking for advise options. The variable
+ // iAdvOpt will be set to indicate what type of data we just got, such
+ // as ON_CHANGE, etc. If the option is invalid, then we won't know
+ // what to do with it.
+ //
+
+ if ((hresult=wScanItemOptions (aItem, (int *) &iAdvOpt)) != NOERROR)
+ {
+ intrAssert(!"Item found with unknown advise option\n");
+ LPARAM lp;
+ if(!wPostMessageToServer (pChannel,
+ WM_DDE_ACK,
+ lp = MAKE_DDE_LPARAM (WM_DDE_ACK,NEGATIVE_ACK, aItem),TRUE))
+ {
+ hresult = RPC_E_SERVER_DIED;
+
+ }
+
+ //
+ // Did we need to free hDdeData here? No, according to the DDE spec, if the
+ // receiever responds with a NACK, then the sender is responsible for
+ // freeing the data.
+ //
+ return hresult;
+ }
+
+ //
+ // If the server sent no data, there ain't much we can do about it.
+ //
+
+ if (hDdeData == NULL)
+ {
+ intrDebugOut((DEB_IERROR,
+ "::OnData(%x)hDdeData is NULL!\n",
+ this));
+
+ return(RPC_E_INVALID_PARAMETER);
+ }
+
+ //
+ // Lock the data into memory so we can use it. Be careful, the way
+ // this routine was written originally, there are places that free
+ // and realloc hDdeData. Specifically, the call to KeepData. Carefully
+ // evaluate each place where you are returning, to insure the memory
+ // isn't leaked. (if you have time, please restructure this routine
+ // so it is easier to understand.
+ //
+ if (!(lpDdeData = (DDEDATA FAR *) GlobalLock(hDdeData)))
+ {
+ intrDebugOut((DEB_IERROR,
+ "::OnData(%x)GlobalLock on lpDdeData failed\n",
+ this));
+ //
+ // BUGBUG: (KevinRo)Did we need to free hDdeData here? I think
+ // we should have if the fRelease flag was set. The old code
+ // didn't. Need to research this further (ie you figure it out!)
+ //
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+
+ intrDebugOut((INTR_DDE,
+ "::OnData(%x) lpDdeData->cfFormat=%x\n",
+ this,
+ (UINT)lpDdeData->cfFormat));
+
+ //
+ // The server will set fAckReq if it wants a response.
+ // don't call HIC for call where not acknoewledge is requested
+ //
+ fAck = lpDdeData->fAckReq;
+
+ if (pChannel->bTerminating) {
+ intrDebugOut((INTR_DDE,"::OnData(%x) Got DDE_DATA in terminate sequence\n",this));
+ //
+ // BUGBUG: this is very dangerous since the pointer on the
+ // hDocWnd does not get deleted and a further will
+ // DDE message will GPF - we need to fix this!!!
+ //
+ GlobalUnlock (hDdeData);
+ GlobalFree (hDdeData);
+ goto exitRtn;
+ }
+
+ //
+ // (KevinRo) Found this comment:
+ //
+ // important that we post the acknowledge first. Otherwise the
+ // messages are not in sync.
+ //
+ // The above comment might be intended to mean that the acknowledge needs to be
+ // send now, because we may call one of the advise functions below, which in
+ // turn may send another message to the OLE 1.0 server. Therefore, we ACK now,
+ // so the messages to the OLE 1.0 server are in the correct order.
+ //
+ if (fAck)
+ {
+ LPARAM lp;
+ if(!wPostMessageToServer (pChannel,
+ WM_DDE_ACK,
+ lp=MAKE_DDE_LPARAM(WM_DDE_ACK,POSITIVE_ACK, aItem),TRUE))
+ {
+ return(RPC_E_SERVER_DIED);
+ }
+ }
+
+ //
+ // this call is now an async call and can not be rejected be HandleIncomingMessage
+ //
+
+ if ((AA_REQUESTAVAILABLE == pChannel->iAwaitAck) && (lpDdeData->fResponse))
+ {
+ //
+ // For some reasons, OnDataAvailable will be the one to delete this data.
+ // I don't understand it, but lets roll with it. (KevinRo)
+ //
+ GlobalUnlock (hDdeData);
+ return OnDataAvailable (pChannel, hDdeData, aItem);
+ }
+
+ //
+ // If the clipboard format is binary, and the topic is aStdDocName, then this
+ // OnData is a RENAME
+ //
+ if (lpDdeData->cfFormat == (short)g_cfBinary && aItem== aStdDocName)
+ {
+ // ON_RENAME
+ //
+ // The data should be the new name, in ANSI.
+ //
+ ChangeTopic ((LPSTR)lpDdeData->Value);
+ GlobalUnlock (hDdeData);
+ GlobalFree (hDdeData);
+ return(NOERROR);
+ }
+
+ //
+ // Based on iAdvOpt, determine if we can callback. This one is a little
+ // hard to understand. I don't either. CanCallBack appears to return
+ // true if the count is 0,1, or 3, but returns FALSE if its 2 or
+ // greater than 3. There are no comments in the old code as to why
+ // this is. I am leaving it, since it must have been put there for
+ // a reason. See CanCallBack in ddeworker.cxx for futher (ie no) details
+ //
+ switch (iAdvOpt)
+ {
+ case ON_SAVE:
+ fCallBack = CanCallBack(&m_iAdvSave);
+ intrDebugOut((INTR_DDE,
+ "::OnData(%x)ON_SAVE m_iAdvSave=%x\n",
+ this,
+ m_iAdvSave));
+
+ break;
+ case ON_CLOSE:
+ fCallBack = CanCallBack(&m_iAdvClose);
+ intrDebugOut((INTR_DDE,
+ "::OnData(%x)ON_CLOSE m_iAdvClose=%x\n",
+ this,
+ m_iAdvClose));
+ break;
+ case ON_CHANGE:
+ fCallBack = TRUE;
+ intrDebugOut((INTR_DDE,
+ "::OnData(%x)ON_CHANGE m_iAdvClose=%x\n",
+ this,
+ m_iAdvClose));
+ break;
+ default:
+ intrAssert( !"Unknown iAdvOpt: Somethings really broke");
+ }
+
+ // Keep the data in a cache for a future GetData call
+ // which may be triggered a few lines later by the
+ // SendOnDataChange().
+
+ fRequested = lpDdeData->fResponse;
+
+
+ // The call to KeepData will change hDdeData and
+ // invalidate lpDdeData. Check out KeepData for details. The net
+ // result is that hDdeData is no longer valid
+
+ GlobalUnlock (hDdeData);
+ lpDdeData=NULL;
+
+ hresult = KeepData (pChannel, hDdeData);
+
+ //
+ // This is unpleasant, but if KeepData fails, we need to
+ // call SetCallState again, resetting the error code. This
+ // code is such a mess that rearranging it to do
+ // it in a rational way is going to be too much work given
+ // the amount of time I have until shipping.
+ //
+ // If you have time, please simplify this code. Thanks
+ //
+ if (hresult != NOERROR)
+ {
+ //
+ // At this point, hDdeData has been unlocked, and deleted by
+ // the KeepData routine. Therefore, the return here doesn't
+ // need to be concerned with cleaning up after hDdeData
+ //
+ intrDebugOut((DEB_ITRACE,
+ "::OnData(%x) KeepData failed %x\n",
+ this,
+ hresult));
+ //
+ // Reset the error code on the call control
+ //
+ if ((AA_REQUEST == iAwaitAck) || (AA_REQUESTAVAILABLE == iAwaitAck))
+ {
+ if (pChannel->pCD && (pChannel->pCD->id != CALLDATAID_UNUSED))
+ {
+ pChannel->pCallCont->SetCallState(pChannel->pCD,
+ SERVERCALLEX_ISHANDLED,
+ hresult);
+ }
+ }
+ goto exitRtn;
+ }
+
+ if (fRequested)
+ {
+ // We REQUESTed the data. So, we are no longer waiting.
+ // Do NOT call SendOnDataChange because the data hasn't
+ // really changed again, we just requested it to satisfy
+ // a call to GetData, which was probably called by the
+ // real SendOnDataChange.
+ intrDebugOut((INTR_DDE,
+ "::OnData(%x) fRequested DATA\n",
+ this));
+
+ iAwaitAck = NULL;
+ hresult = NOERROR;
+ goto exitRtn;
+
+ }
+
+ //
+ // Now we have decided this is data we had not asked for. This makes
+ // it a change/close/saved notificiation.
+ //
+ intrDebugOut((INTR_DDE,"::OnData(%x) Non requested DATA\n",this));
+ pChannel->AddReference();
+ if (fCallBack && iAdvOpt != ON_CHANGE)
+ {
+ // ON_CHANGE will be handled by OleCallback, below
+
+ intrDebugOut((INTR_DDE,
+ "::OnData(%x)Dispatching SendOnDataChange\n",
+ this));
+
+
+ //
+ // There are a couple of things to note about the following. First,
+ // the iid of the call doesn't matter. Since OLE 1.0 servers don't
+ // do nested calls, the original LID (Logical ID) can be any random
+ // value. Therefore, we don't initalize it.
+ //
+ // According to JohannP, the calltype of these calls is supposed
+ // to be CALLTYPE_SYNC. I don't fully understand why they are.
+ // I am taking is decision on faith.
+ //
+ // Using the new call control interfaces, we do the following.
+ //
+ IID iid;
+
+ DDEDISPATCHDATA ddedispdata;
+ DISPATCHDATA dispatchdata;
+ INTERFACEINFO32 ifInfo;
+
+ ifInfo.pUnk = m_pDataAdvHolder;
+ ifInfo.iid = IID_IDataAdviseHolder;
+ //
+ // We are about to call method #6 in the interface,
+ // which is SendOnDataChange
+ //
+ ifInfo.wMethod = 6;
+ ifInfo.callcat = CALLCAT_SYNCHRONOUS;
+
+ //dispatchdata.scode = S_OK;
+ dispatchdata.pData = (LPVOID) &ddedispdata;
+
+ ddedispdata.pCDdeObject = this;
+ ddedispdata.wDispFunc = DDE_DISP_SENDONDATACHANGE;
+ ddedispdata.iArg = iAdvOpt;
+
+ lpCallCont->HandleDispatchCall((DWORD)GetWindowTask(pChannel->hwndSvr),
+ iid,
+ &ifInfo,
+ &dispatchdata);
+
+ }
+ if (fCallBack && (pChannel->pCallCont != NULL))
+ {
+ // in 1.0 ON_CLOSE comes with data
+ if (iAdvOpt==ON_CLOSE)
+ {
+
+ intrDebugOut((INTR_DDE,
+ "::OnData(%x) iAdvOpt == ON_CLOSE, send ON_SAVE\n",
+ this));
+
+ m_fGotCloseData = TRUE;
+
+ hresult = OleCallBack(ON_SAVE,pChannel);
+ if (hresult != NOERROR)
+ {
+ goto errRel;
+ }
+
+ //ErrRtnH (DdeHandleIncomingCall(pChannel->hwndSvr, CALLTYPE_TOPLEVEL) );
+ //ErrRtnH (OleCallBack (ON_SAVE));
+ }
+
+ // check if app can handle this call
+ // we do not need to call HIC for SendOnClose
+
+ hresult = OleCallBack (iAdvOpt,pChannel);
+ }
+
+errRel:
+ // Don't use pChannel after this. It can get deleted. (srinik)
+ if (pChannel->ReleaseReference() == 0)
+ {
+ m_pDocChannel = NULL;
+ }
+
+exitRtn:
+ if (!fAck && aItem)
+ {
+ GlobalDeleteAtom (aItem);
+ }
+ return hresult;
+#endif _MAC
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::OleCallBack
+//
+// Synopsis: Send all the right notifications whan a Save or Close happens.
+//
+// Effects: OleCallBack is a double duty function. It is called in two
+// different cases.
+//
+// First, is to setup the callback, and call HandleIncomingCall.
+// Second is from DispatchCall() in the CDdeChannelControl.
+//
+// The reason for doing it this way is we localize the setup
+// and processing of these calls to one routine. Therefore,
+// we can go to one spot in the code to find all of the call
+// back information.
+//
+// Arguments: [iAdvOpt] -- Which Advise operation to perform
+// [pChannel] -- Which channel is being called back
+//
+// Requires: pChannel == NULL, and the AdviseHolders are called.
+// pChannel != NULL, and the call is setup, and HandleIncomingCall
+// is setup.
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-23-94 kevinro Created
+//
+// Notes:
+//
+// WARNING: This code sucks completely. One of the major problems you need
+// to know about is that the CDdeObject may go away as part of the normal
+// processing of some of the below. Be very careful about any processing
+// that might occur after an ON_CLOSE
+//
+//----------------------------------------------------------------------------
+INTERNAL CDdeObject::OleCallBack (int iAdvOpt, LPDDE_CHANNEL pChannel)
+{
+ HRESULT hresult = NOERROR;
+ IID iid;
+ DDEDISPATCHDATA ddedispdata;
+ DISPATCHDATA dispatchdata;
+ INTERFACEINFO32 ifInfo;
+ ICallControl *lpCallCont = NULL;
+
+ //
+ // If the channel isn't NULL, then setup the data structures for calling
+ // off to the call control.
+ //
+ if (pChannel != NULL)
+ {
+ lpCallCont = pChannel->pCallCont;
+
+ if (lpCallCont == NULL)
+ {
+ return(E_UNEXPECTED);
+ }
+ //
+ // Only do this work if we really have to
+ //
+
+ dispatchdata.scode = S_OK;
+ dispatchdata.pData = (LPVOID) &ddedispdata;
+ ddedispdata.pCDdeObject = this;
+ ddedispdata.wDispFunc = DDE_DISP_OLECALLBACK;
+ ddedispdata.iArg = iAdvOpt;
+
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::OleCallBack(%x,iAdvOpt=%x,pChannel=%x,lpCallCont=%x)\n",
+ this,
+ iAdvOpt,
+ pChannel,
+ lpCallCont));
+
+ //
+ // Determine what needs to be done, based on the iAdvOpt. This should be
+ // one of the handled cases below, otherwise its an error.
+ //
+ switch (iAdvOpt)
+ {
+ case ON_CLOSE:
+ if (pChannel != NULL)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::OleCallBack(%x) setup for ON_CLOSE\n",
+ this));
+
+ ifInfo.pUnk = m_pOleAdvHolder;
+ ifInfo.iid = IID_IOleAdviseHolder;
+ // IOleAdviseHolder::SendOnClose is method 8
+ ifInfo.wMethod = 8;
+ ifInfo.callcat = CALLCAT_SYNCHRONOUS;
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE,"::OleCallBack(%x) ON_CLOSE\n",this));
+ DeclareVisibility (FALSE);
+ RetZ (!m_fDidSendOnClose); // This SendOnClose should happen 1st
+ // Don't let OnTerminate() do it too
+ hresult = SendOnClose();
+
+ //
+ // WARNING WARNING WARNING: SendOnClose() may have caused the
+ // destruction of this CDdeObject. Touch nothing on the way
+ // out. Actually, if you have time, which I currently don't,
+ // see what you can do with reference counting tricks to
+ // insure this object doesn't die during this callback.
+ // Its a tricky problem, and we are shipping in 2 weeks.
+ // (KevinRo 8/6/94)
+ //
+ }
+ break;
+
+ case ON_SAVE:
+ if (pChannel != NULL)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::OleCallBack(%x) setup for ON_SAVE\n",
+ this));
+
+ if (m_pOleClientSite == NULL)
+ {
+ ifInfo.pUnk = m_pOleClientSite;
+ ifInfo.iid = IID_IOleClientSite;
+ // IOleClientSite::SaveObject method 7
+ ifInfo.wMethod = 7;
+ ifInfo.callcat = CALLCAT_SYNCHRONOUS;
+ }
+ else
+ {
+ // Going to call the IOleAdviseHolder
+
+ ifInfo.pUnk = m_pOleAdvHolder;
+ ifInfo.iid = IID_IOleAdviseHolder;
+ // IOleAdviseHolder::SendOnSave method 7
+ // (Yes, same ordinal as above, I double checked)
+ ifInfo.wMethod = 7;
+ ifInfo.callcat = CALLCAT_SYNCHRONOUS;
+ }
+ }
+ else
+ {
+
+ intrDebugOut((DEB_ITRACE,"::OleCallBack(%x) ON_SAVE\n",this));
+ if (m_pOleClientSite)
+ {
+ // We just got data from the server, so we don't want to
+ // ask him for it again when the container does a save.
+ m_fUpdateOnSave = FALSE;
+ m_pOleClientSite->SaveObject();
+ // SendOnSave is called in PS::SaveCompleted
+ m_fUpdateOnSave = TRUE;
+ }
+ else
+ {
+ // Link case
+ RetZS (m_pOleAdvHolder, E_OUTOFMEMORY);
+ m_pOleAdvHolder->SendOnSave();
+ }
+ }
+ break;
+
+ case ON_CHANGE:
+ if (pChannel != NULL)
+ {
+ // Going to call the IDataAdviseHolder
+
+ ifInfo.pUnk = m_pDataAdvHolder;
+ ifInfo.iid = IID_IDataAdviseHolder;
+ // IDataAdviseHolder::SendOnDataChange method 6
+ ifInfo.wMethod = 6;
+ ifInfo.callcat = CALLCAT_SYNCHRONOUS;
+
+ }
+ else
+ {
+ RetZS (m_pDataAdvHolder, E_OUTOFMEMORY);
+ intrDebugOut((DEB_ITRACE,"::OleCallBack(%x) ON_CHANGE\n",this));
+ hresult = SendOnDataChange (ON_CHANGE);
+ }
+ break;
+
+ default:
+
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::OleCallBack(%x,iAdvOpt=%x) UNKNOWN iAdvOpt\n",
+ this,
+ iAdvOpt));
+ intrAssert(!"Unexpected iAdvOpt");
+ return(E_UNEXPECTED);
+ break;
+ }
+
+ //
+ // There are a couple of things to note about the following. First,
+ // the iid of the call doesn't matter. Since OLE 1.0 servers don't
+ // do nested calls, the original LID (Logical ID) can be any random
+ // value. Therefore, we don't initalize it.
+ //
+ // According to JohannP, the calltype of these calls is supposed
+ // to be CALLTYPE_SYNCHRONOUS. I don't fully understand why they are.
+ // I am taking is decision on faith.
+ //
+ //
+ // Its possible that during the handling of this call that this object
+ // will get deleted. This is a pain in the butt. This means that anything
+ // used after this call MUST be protected. lpCallCont happens to be one of
+ // these. We have been having problems with lpCallCont being released as
+ // part of the object cleanup. The call control code will access member
+ // variables on its way out of the HandleDispatch. We need to bracket
+ // the call below so this doesn't happen.
+ //
+ if (pChannel != NULL)
+ {
+ //
+ // We normally keep a per thread copy of the call control interface.
+ // When the reference count for that copy goes to zero, we need to
+ // flush that copy. We can do the addref here, because the current
+ // reference is the same value that would be returned by
+ // GetDdeCallControlInterface. The balancing call, however, needs
+ // to be ReleaseDdeCallControlInterface, since it may need to flush
+ // the TLS value.
+ //
+
+ lpCallCont->AddRef();
+
+ hresult = lpCallCont->HandleDispatchCall((DWORD)GetWindowTask(pChannel->hwndSvr),
+ iid,
+ &ifInfo,
+ &dispatchdata);
+
+ ReleaseDdeCallControlInterface();
+ }
+
+ return hresult;
+}
+
+
+INTERNAL CDdeObject::SendOnDataChange
+ (int iAdvOpt)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::SendOnDataChange(%x)\n",this));
+ HRESULT hresult;
+ RetZS (m_pDataAdvHolder, E_OUTOFMEMORY);
+ m_fDoingSendOnDataChange = TRUE;
+ hresult = m_pDataAdvHolder->SendOnDataChange (&m_Data,
+ DVASPECT_CONTENT,
+ 0);
+ if (ON_CLOSE==iAdvOpt)
+ {
+ hresult = m_pDataAdvHolder->SendOnDataChange (&m_Data,
+ DVASPECT_CONTENT,
+ ADVF_DATAONSTOP);
+ }
+ m_fDoingSendOnDataChange = FALSE;
+ return hresult;
+}
+
+
+
+
+INTERNAL CDdeObject::SendOnClose
+ (void)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::SendOnClose(%x)\n",this));
+ RetZS (m_pOleAdvHolder, E_OUTOFMEMORY);
+ m_fDidSendOnClose = TRUE;
+ RetErr (m_pOleAdvHolder->SendOnClose() );
+ return NOERROR;
+}
+
+
+
+
+INTERNAL CDdeObject::OnTerminate
+ (LPDDE_CHANNEL pChannel,
+ HWND hwndPost)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::OnTerminate(%x,pChannel=%x,hwndPost=%x)\n",
+ this,
+ pChannel,
+ hwndPost));
+
+ //
+ // If the hwndPost and hwndSvr are different, then it is one of two
+ // cases. We could have recieved more than one Acknowlege during our
+ // initiate, in which case the count iExtraTerms would have been
+ // incremented, and this terminate is accounted for iExtraTerms.
+ //
+ // The other case is that we were terminated by a window that was
+ // NOT the window we were conversing with.
+ //
+ if (pChannel->hwndSvr != hwndPost)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::OnTerminate(%x) Extra terms is 0x%x \n",
+ this,
+ pChannel->iExtraTerms));
+
+ //
+ // iExtraTerms shouldn't go below zero. If it does, something
+ // has gone wrong. We have been seeing some problems with the
+ // HWND mapping layer in the past. If the following condition
+ // ever trips, then it is possible that another mapping
+ // problem has been seen.
+ //
+#if DBG == 1
+ if((pChannel->iExtraTerms == 0 ) &&
+ (((DWORD)pChannel->hwndSvr) & (0xffff)) == ((DWORD)hwndPost & (0xffff)))
+ {
+ intrDebugOut((DEB_ERROR,
+ "*** OnTerminate expected hwnd=%x got hwnd=%x ***\n",
+ pChannel->hwndSvr,hwndPost));
+
+ intrDebugOut((DEB_ERROR,
+ "\n*** Call KevinRo or SanfordS ***\n\n",
+ pChannel->hwndSvr,hwndPost));
+
+ }
+#endif
+ --pChannel->iExtraTerms;
+
+ intrAssert((pChannel->iExtraTerms >= 0) && "Call KevinRo or SanfordS");
+ return NOERROR;
+ }
+ if (m_wTerminate == Terminate_Detect) {
+ // we should only detect the call but not execute the code
+ // set the state to Received
+ m_wTerminate = Terminate_Received;
+ pChannel->iAwaitAck = NULL;
+ // Since Excel incorrectly did not send an ACK, we need to
+ // delete the handle in the DDE message ourselves.
+ if (pChannel->hCommands)
+ {
+ GlobalFree (pChannel->hCommands);
+ pChannel->hCommands = NULL;
+ }
+ //CoSetAckState(pChannel->pCI, FALSE);
+ intrDebugOut((DEB_ITRACE,
+ "::OnTerminate(%x) Terminate_Detect SERVERCALLEX_ISHANDLED\n",
+ this));
+ pChannel->pCallCont->SetCallState(pChannel->pCD, SERVERCALLEX_ISHANDLED, RPC_E_SERVER_DIED);
+ return NOERROR;
+ }
+
+ RetZ (pChannel);
+ ChkDR (this);
+
+ if (!pChannel->bTerminating)
+ {
+ // Got unprompted terminate
+ BOOL bBusy;
+
+ // Necessary safety bracket
+ m_pUnkOuter->AddRef();
+
+ bBusy = wClearWaitState (pChannel);
+
+ if (pChannel->iAwaitAck || bBusy)
+ {
+ pChannel->iAwaitAck = NULL;
+ //CoSetAckState(pChannel->pCI, FALSE);
+ intrDebugOut((DEB_ITRACE,"::OnTerminate(%x) !bTerminating SERVERCALLEX_ISHANDLED,RPC_E_DDE_UNEXP_MSG\n",this));
+ pChannel->pCallCont->SetCallState(pChannel->pCD, SERVERCALLEX_ISHANDLED, RPC_E_DDE_UNEXP_MSG);
+ }
+
+ if (!m_fDidSendOnClose)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::OnTerminate(%x) SendOnClose from terminate\n",
+ this));
+
+ BOOL f= m_fNoStdCloseDoc;
+ m_fNoStdCloseDoc = TRUE;
+
+ DeclareVisibility (FALSE);
+ SendOnClose();
+
+ m_fNoStdCloseDoc = f;
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::OnTerminate(%x) Already did SendOnClose\n",
+ this));
+ Puts ("Already did SendOnClose\n");
+ }
+ intrDebugOut((DEB_ITRACE,
+ "::OnTerminate(%x) Posting DDE_TERMINATE as reply\n",
+ this));
+
+ wPostMessageToServer (pChannel, WM_DDE_TERMINATE, NULL,FALSE);
+
+ // The terminate that we are sending itself is a reply, so we don't
+ // need to do WaitForReply.
+ DeleteChannel (pChannel);
+
+ // Necessary safety bracket
+ m_pUnkOuter->Release();
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::OnTerminate(%x) Received DDE_TERMINATE in reply\n",
+ this));
+
+ // We sent the WM_DDE_TERMINATE and we got the acknowledge for it
+ pChannel->hwndSvr = NULL;
+ pChannel->iExtraTerms == NULL;
+ pChannel->iAwaitAck = NULL;
+ //CoSetAckState(pChannel->pCI, FALSE);
+ intrDebugOut((DEB_ITRACE,"::OnTerminate(%x) bTerminating SERVERCALLEX_ISHANDLED\n",this));
+ pChannel->pCallCont->SetCallState(pChannel->pCD, SERVERCALLEX_ISHANDLED, NOERROR);
+ }
+ Puts ("OnTerminate() done.\n");
+ return NOERROR;
+}
+
+
+
+
+INTERNAL_(BOOL) CDdeObject::AllocDdeChannel
+ (LPDDE_CHANNEL * lplpChannel, LPSTR lpszWndClass)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::AllocDdeChannel(%x,WndClass=%s)\n",
+ this,
+ lpszWndClass));
+
+ //
+ // Try to get the global call control interface
+ //
+
+ PCALLCONTROL pCallCont = GetDdeCallControlInterface();
+
+ if (pCallCont == NULL)
+ {
+ //
+ // Couldn't allocate a CallControl. Fail.
+ //
+
+ intrAssert(pCallCont != NULL);
+ return(FALSE);
+ }
+
+ //
+ // Now try to allocate a channel
+ //
+
+ if (!(*lplpChannel = (LPDDE_CHANNEL) new DDE_CHANNEL ))
+ {
+ //
+ // This failed, so give back the CallControl
+ //
+ intrAssert(*lplpChannel != NULL);
+ ReleaseDdeCallControlInterface();
+ return FALSE;
+ }
+
+ (*lplpChannel)->m_cRefs = 1;
+ (*lplpChannel)->hwndSvr = NULL;
+ (*lplpChannel)->bTerminating = FALSE;
+ (*lplpChannel)->wTimer = NULL;
+ (*lplpChannel)->hDdePoke = NULL;
+ (*lplpChannel)->hCommands = NULL;
+ (*lplpChannel)->hopt = NULL;
+ (*lplpChannel)->dwStartTickCount= 0;
+ (*lplpChannel)->msgFirst = 0;
+ (*lplpChannel)->msgLast = 0;
+ (*lplpChannel)->fRejected = FALSE;
+ (*lplpChannel)->wChannelDeleted = 0;
+ //(*lplpChannel)->pCI = NULL;
+ (*lplpChannel)->pCD = NULL;
+ (*lplpChannel)->pCallCont = pCallCont;
+ (*lplpChannel)->pChanCont = &g_CDdeChannelControl;
+
+ if (!((*lplpChannel)->hwndCli = SSCreateWindowExA(0,
+ lpszWndClass,
+ "DDE Channel",
+ WS_CHILD,
+ 0,0,0,0,
+ (HWND)TLSGetDdeClientWindow(),
+ NULL,
+ hinstSO,
+ NULL)))
+ {
+ intrAssert (!"Could not create AllocDdeChannel window");
+
+ //
+ // DeleteChannel will give back the CallControl
+ //
+
+ DeleteChannel(*lplpChannel);
+ *lplpChannel = NULL;
+ return FALSE;
+ }
+
+ SetWindowLong ((*lplpChannel)->hwndCli, 0, (LONG) this);
+ return TRUE;
+}
+
+
+
+INTERNAL_(BOOL) CDdeObject::InitSysConv()
+{
+ DWORD dwResult;
+ intrDebugOut((DEB_ITRACE,"CDdeObject::InitSysConv(%x)\n",this));
+
+ dwResult = wInitiate (m_pSysChannel, m_aClass, aOLE);
+ if (!dwResult)
+ {
+ intrDebugOut((DEB_ITRACE,"\t::InitSysConv(%x) Try aSysTopic\n",this));
+ dwResult = wInitiate (m_pSysChannel, m_aClass, aSysTopic);
+ }
+
+ if (!dwResult)
+ {
+ intrDebugOut((DEB_ITRACE,"\t::InitSysConv(%x) is failing\n",this));
+ }
+ return(dwResult);
+}
+
+
+
+INTERNAL_(void) CDdeObject::SetTopic(ATOM aTopic)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::SetTopic(%x)\n",this));
+ intrAssert(wIsValidAtom(aTopic));
+ if (m_aTopic)
+ GlobalDeleteAtom (m_aTopic);
+
+ m_aTopic = aTopic;
+}
+
+
+
+INTERNAL CDdeObject::TermConv
+ (LPDDE_CHANNEL pChannel,
+ BOOL fWait) // Default==TRUE. FALSE only in ProxyManager::Disconnect
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::TermConv(%x,pChannel=%x)\n",
+ this,
+ pChannel));
+
+ HRESULT hres;
+ if (!pChannel)
+ {
+ return NOERROR;
+ }
+
+ if (!wPostMessageToServer (pChannel, WM_DDE_TERMINATE, 0,FALSE))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::TermConv(%x) Server Probably Died\n",
+ this));
+ hres = RPC_E_SERVER_DIED;
+ }
+ else
+ {
+ pChannel->bTerminating = TRUE;
+ Putsi (fWait);
+ hres = fWait ? WaitForReply (pChannel,
+ AA_TERMINATE,
+ /*fStdCloseDoc*/FALSE,
+ /*fDetectTerminate*/ FALSE) : NOERROR;
+ if (pChannel==m_pDocChannel)
+ {
+ DeclareVisibility (FALSE);
+ if (!m_fDidSendOnClose)
+ {
+ SendOnClose();
+ }
+ }
+ }
+
+ DeleteChannel (pChannel);
+ intrDebugOut((DEB_ITRACE,"::TermConv(%x) returns %x\n",this,hres));
+ return hres;
+}
+
+
+
+
+INTERNAL_(void) CDdeObject::DeleteChannel (LPDDE_CHANNEL pChannel)
+{
+ BOOL fDocChannel = FALSE;
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::DeleteChannel(%x,pChannel=%x)\n",
+ this,
+ pChannel));
+
+ if (pChannel == NULL)
+ {
+ return;
+ }
+
+ if (pChannel == m_pDocChannel)
+ fDocChannel = TRUE;
+
+
+
+ // delete any data if we were in busy mode.
+ wClearWaitState (pChannel);
+
+ if (pChannel == m_pDocChannel)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::DeleteChannel(%x)Clean up pDocChannel\n",
+ this));
+
+ // Cleanup per-conversation information
+ m_fDidSendOnClose = FALSE;
+ m_fDidStdCloseDoc = FALSE;
+ m_ConnectionTable.Erase();
+ m_iAdvSave = 0;
+ m_iAdvClose= 0;
+ m_fWasEverVisible = FALSE;
+ m_fGotCloseData = FALSE;
+ if (m_ptd)
+ {
+ delete m_ptd;
+ m_ptd = NULL;
+ }
+ if (m_pstg)
+ {
+ m_pstg->Release();
+ m_pstg = NULL;
+ }
+ if (m_pDataAdvHolder)
+ {
+ Verify (0==m_pDataAdvHolder->Release());
+ }
+ CreateDataAdviseHolder (&m_pDataAdvHolder);
+ if (m_pOleAdvHolder)
+ {
+ m_pOleAdvHolder->Release(); // may not return 0 if we are
+ // in a SendOnClose
+ }
+ CreateOleAdviseHolder (&m_pOleAdvHolder);
+ }
+
+ if (pChannel->hwndCli)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::DeleteChannel(%x)Destroy hwndCli(%x)\n",
+ this,
+ pChannel->hwndCli));
+
+ Assert (IsWindow (pChannel->hwndCli));
+ Assert (this==(CDdeObject *)GetWindowLong (pChannel->hwndCli, 0));
+ Verify (SSDestroyWindow (pChannel->hwndCli));
+ }
+
+ if (pChannel == m_pDocChannel)
+ {
+ m_pDocChannel = NULL;
+ }
+ else
+ {
+ intrAssert(pChannel == m_pSysChannel);
+ m_pSysChannel = NULL;
+ }
+
+
+ if (pChannel->pCallCont != NULL)
+ {
+ ReleaseDdeCallControlInterface();
+ pChannel->pCallCont = NULL;
+ }
+
+ // Channel will be deleted in the modallp.cpp
+ // if flag is on.
+
+ if (pChannel->wChannelDeleted == Channel_InModalloop)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::DeleteChannel(%x) Channel(%x) in Modal Loop\n",
+ this,pChannel));
+
+ pChannel->wChannelDeleted = Channel_DeleteNow;
+ }
+ else
+ {
+ if (pChannel->ReleaseReference() == 0)
+ pChannel = NULL;
+ }
+
+ if (fDocChannel)
+ m_pDocChannel = pChannel;
+}
+
+const WCHAR EMB_STR[]= OLESTR(" -Embedding ") ;
+
+INTERNAL_(BOOL) CDdeObject::LaunchApp (void)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::LaunchApp(%x)\n",this));
+
+ STARTUPINFO startInfo;
+ PROCESS_INFORMATION procInfo;
+ BOOL fProcStarted;
+ WCHAR cmdline[MAX_PATH + sizeof(EMB_STR)];
+ WCHAR exeName[MAX_PATH + sizeof(cmdline)];
+ //
+ // Init all fields of startInfo to zero
+ //
+ memset((void *)&startInfo,0,sizeof(startInfo));
+
+ //
+ // The normal startup is set here.
+ //
+ startInfo.wShowWindow = SW_NORMAL;
+ startInfo.dwFlags = STARTF_USESHOWWINDOW;
+
+ m_fDidLaunchApp = FALSE;
+
+
+ DWORD dw;
+
+ //
+ // Do our best to find the path
+ //
+ intrAssert(wIsValidAtom(m_aExeName));
+
+ if (m_aExeName == 0)
+ {
+ //
+ // There is no exe name to execute. Can't start it.
+ //
+ return(FALSE);
+ }
+
+ dw = SearchPath(NULL,wAtomName(m_aExeName),NULL,MAX_PATH,exeName, NULL);
+
+ if ((dw == 0) || (dw > MAX_PATH))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::LaunchApp(%x) SearchPath failed. Do Default",this));
+ //
+ // SearchPath failed. Use the default
+ //
+ GlobalGetAtomName (m_aExeName, exeName, MAX_PATH);
+ }
+
+ memcpy(cmdline, EMB_STR,sizeof(EMB_STR));
+
+ if (m_ulObjType == OT_LINK)
+ {
+ intrAssert(wIsValidAtom(m_aTopic));
+ // File name
+ Assert (wAtomName (m_aTopic));
+
+ lstrcatW (cmdline, wAtomName (m_aTopic));
+ }
+
+ if (m_clsid == CLSID_ExcelWorksheet // Stupid apps that show themselves
+ || m_clsid == CLSID_ExcelMacrosheet // when they're not supposed to
+ || m_clsid == CLSID_ExcelChart
+ || m_clsid == CLSID_PBrush)
+ {
+ startInfo.wShowWindow = SW_SHOWMINNOACTIVE;
+ }
+
+ //
+ // According to the spec, the most robust way to start the app is to
+ // only use a cmdline that consists of the exe name, followed by the
+ // command line arguments.
+ //
+
+ lstrcatW(exeName,cmdline);
+
+ Assert((lstrlenW(exeName)+1) < sizeof(exeName));
+
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::LaunchApp(%x) Starting '%ws' \n",
+ this,
+ exeName));
+
+ if (IsWOWThreadCallable())
+ {
+ HRESULT hr;
+
+ hr = g_pOleThunkWOW->WinExec16(exeName, startInfo.wShowWindow);
+
+ fProcStarted = SUCCEEDED(hr);
+
+#if DBG==1
+ if (!fProcStarted)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::LaunchApp(%x) in Wow FAILED(%x) TO START %ws \n",
+ this,
+ hr,
+ exeName));
+ }
+#endif
+ }
+ else
+ {
+ fProcStarted = CreateProcess(NULL,
+ exeName,
+ NULL,
+ NULL,
+ FALSE,
+ 0,
+ NULL,
+ NULL,
+ &startInfo,
+ &procInfo);
+ if (fProcStarted)
+ {
+ //
+ // Let's give the server a chance to register itself. On NT,
+ // CreateProcess gets the other process going, but returns
+ // to let it run asynchronously. This isn't good, since we
+ // need some way of knowing when it has started, so we can
+ // send the DDE_INITIATES 'after' they create their DDE
+ // window.
+ //
+ // Maximum timeout we want here shall be set at 30 seconds.
+ // This should give enough time for even a 16bit WOW app to
+ // start. This number was picked by trial and error. Normal
+ // apps that go into an InputIdle state will return as soon
+ // as they are ready. Therefore, we normally won't wait
+ // the full duration.
+ //
+
+ ULONG ulTimeoutDuration = 30000L;
+
+ //
+ // Now modify this start time to handle classes
+ // that have known problems. This list includes:
+ //
+
+ switch(WaitForInputIdle(procInfo.hProcess, ulTimeoutDuration))
+ {
+ case 0:
+ intrDebugOut((DEB_ITRACE,
+ "::LaunchApp, %ws started\n",
+ exeName));
+ break;
+ case WAIT_TIMEOUT:
+ intrDebugOut((DEB_ITRACE,
+ "::LaunchApp, %ws wait timeout at %u (dec) ms. Go Anyway\n",
+ exeName,
+ ulTimeoutDuration));
+ break;
+ default:
+ intrDebugOut((DEB_ITRACE,
+ "::LaunchApp, %ws unknown condition (%x)\n",
+ exeName,
+ GetLastError()));
+ }
+ //
+ // We are already done with the Process and Thread handles
+ //
+ CloseHandle(procInfo.hProcess);
+ CloseHandle(procInfo.hThread);
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::LaunchApp(%x) FAILED(%x) TO START %ws \n",
+ this,
+ GetLastError(),
+ exeName));
+ }
+ }
+
+ if (fProcStarted)
+ {
+ // If we ran the server, it should not be visible yet.
+ DeclareVisibility (FALSE);
+ m_fDidLaunchApp = TRUE;
+ }
+
+ return fProcStarted;
+}
+
+
+INTERNAL CDdeObject::MaybeUnlaunchApp (void)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::MaybeUnlaunchApp(%x)\n",this));
+ if (m_fDidLaunchApp
+ && !m_fDidGetObject
+ && (m_clsid == CLSID_ExcelWorksheet
+ || m_clsid == CLSID_ExcelMacrosheet
+ || m_clsid == CLSID_ExcelChart))
+ {
+ return UnlaunchApp();
+ }
+ return NOERROR;
+}
+
+
+
+
+INTERNAL CDdeObject::UnlaunchApp (void)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::UnlaunchApp(%x)\n",this));
+ HANDLE hCommands;
+ HRESULT hresult = NOERROR;
+ RetZS (AllocDdeChannel (&m_pSysChannel, SYS_CLASSA), E_OUTOFMEMORY);
+ ErrZS (InitSysConv(), E_UNEXPECTED);
+ ErrRtnH (PostSysCommand (m_pSysChannel,(LPSTR) &achStdExit, /*bStdNew*/FALSE,
+ /*fWait*/FALSE));
+ hCommands = m_pSysChannel->hCommands;
+ hresult = TermConv (m_pSysChannel);
+
+ // Since Excel incorrectly did not send an ACK, we need to
+ // delete the handle ("[StdExit]") in the DDE message ourselves.
+ if (hCommands)
+ GlobalFree (hCommands);
+
+ return hresult;
+
+ errRtn:
+ DeleteChannel (m_pSysChannel);
+ return hresult;
+}
+
+
+
+
+INTERNAL CDdeObject::Execute
+ (LPDDE_CHANNEL pChannel,
+ HANDLE hdata,
+ BOOL fStdCloseDoc,
+ BOOL fWait,
+ BOOL fDetectTerminate)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::Execute(%x,hdata=%x)\n",this,hdata));
+
+ LPARAM lp;
+
+#ifdef _CHICAGO_
+ //POSTPPC
+ if (fWait && (CanMakeOutCall(pChannel) == FALSE))
+ {
+ intrDebugOut((DEB_ERROR, "::Execute(%x) can not call out\n", this));
+ GlobalFree (hdata);
+ return ResultFromScode (E_UNEXPECTED);
+ }
+#endif
+
+ if (wPostMessageToServer (pChannel,
+ WM_DDE_EXECUTE,
+ lp=MAKE_DDE_LPARAM(WM_DDE_EXECUTE,0, hdata),TRUE))
+ {
+ if (fStdCloseDoc)
+ {
+ // Prepare to free the handle if Excel does not send an Ack
+ pChannel->hCommands = hdata;
+ }
+ return fWait ? WaitForReply (pChannel, AA_EXECUTE, fStdCloseDoc,
+ fDetectTerminate)
+ : NOERROR ;
+ }
+ GlobalFree (hdata);
+ return ReportResult(0, RPC_E_DDE_POST, 0, 0);
+}
+
+
+
+
+INTERNAL_(HRESULT) CDdeObject::AdviseOn (CLIPFORMAT cfFormat, int iAdvOn)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::AdviseOn(%x,cfFormat=%x,iAdvOn=%x)\n",
+ this,
+ cfFormat,
+ iAdvOn));
+
+ HANDLE hopt=NULL;
+ DDEADVISE * lpopt=NULL;
+ ATOM aItem=(ATOM)0;
+ HRESULT hresult = ReportResult(0, E_UNEXPECTED, 0, 0);
+
+ RetZ (m_pDocChannel);
+
+ if (NOERROR == m_ConnectionTable.Lookup (cfFormat, NULL))
+ {
+ // We already got a call to DataObject::Advise on this format.
+ intrDebugOut((DEB_ITRACE,
+ "::AdviseOn(%x) Advise had been done on cfFormat=%x\n",
+ this,
+ cfFormat));
+ return NOERROR;
+ }
+
+ UpdateAdviseCounts (cfFormat, iAdvOn, +1);
+
+ if (m_fDidSendOnClose)
+ {
+ intrDebugOut((DEB_ITRACE,"::AdviseOn(%x)Ignoring Advise because we are closing\n",this));
+ return NOERROR;
+ }
+
+ if (!(hopt = GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT, sizeof(DDEADVISE))))
+ {
+ intrDebugOut((DEB_ITRACE,"::AdviseOn(%x)GlobalAlloc returned NULL\n",this));
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+
+ if (!(lpopt = (DDEADVISE FAR *) GlobalLock (hopt)))
+ {
+ intrDebugOut((DEB_ITRACE,"::AdviseOn(%x)GlobalLock returned NULL\n",this));
+ GlobalFree (hopt);
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ lpopt->fAckReq = TRUE;
+ lpopt->fDeferUpd = FALSE;
+ lpopt->cfFormat = cfFormat;
+ m_pDocChannel->hopt = hopt;
+
+ if (iAdvOn == ON_RENAME)
+ {
+ aItem = wDupAtom (aStdDocName);
+ intrAssert(wIsValidAtom(aItem));
+ }
+ else
+ {
+ intrAssert(wIsValidAtom(m_aItem));
+ aItem = wExtendAtom (m_aItem, iAdvOn);
+ intrAssert(wIsValidAtom(aItem));
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "::AdviseOn(%x) lpopt->cfFormat = %x, aItem=%x (%ws)\n",
+ this,
+ lpopt->cfFormat,
+ aItem,
+ wAtomName(aItem)));
+
+ GlobalUnlock (hopt);
+
+ LPARAM lp;
+ if (FALSE==wPostMessageToServer (m_pDocChannel, WM_DDE_ADVISE,
+ lp=MAKE_DDE_LPARAM(WM_DDE_ADVISE,hopt,aItem),TRUE))
+ {
+ intrDebugOut((DEB_ITRACE,"::AdviseOn(%x)wPostMessageToServer failed\n",this));
+ if (aItem)
+ GlobalDeleteAtom (aItem);
+ if (hopt)
+ GlobalFree (hopt);
+ return ResultFromScode (RPC_E_DDE_POST);
+ }
+ ErrRtnH (WaitForReply (m_pDocChannel, AA_ADVISE));
+
+ return NOERROR;
+
+errRtn:
+ hresult = (RPC_E_DDE_NACK == hresult) ? DV_E_CLIPFORMAT : hresult;
+ intrDebugOut((DEB_ITRACE,
+ "::AdviseOn(%x) errRet, AdviseRejected, returning %x\n",
+ this,hresult));
+ return hresult;
+}
+
+INTERNAL CDdeObject::UpdateAdviseCounts
+ (CLIPFORMAT cf,
+ int iAdvOn,
+ signed int cDelta)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::UpdateAdviseCounts(%x)\n",this));
+ if (cf==g_cfBinary)
+ return NOERROR;
+
+ // Update m_iAdv* flags
+ #define macro(Notif, NOTIF) \
+ if (iAdvOn == ON_##NOTIF) \
+ m_iAdv##Notif += cDelta; \
+ if (m_iAdv##Notif < 0) \
+ m_iAdv##Notif = 0; \
+ else if (m_iAdv##Notif > 2) \
+ m_iAdv##Notif = 2;
+
+ macro (Close, CLOSE)
+ macro (Save, SAVE)
+ macro (Change,CHANGE)
+ #undef macro
+
+ Assert (m_iAdvClose < 3 && m_iAdvSave < 3 && m_iAdvChange < 3);
+ Assert (m_iAdvClose >= 0 && m_iAdvSave >= 0 && m_iAdvChange >= 0);
+
+ if (cf == g_cfNative)
+ {
+ if (iAdvOn != ON_CHANGE)
+ m_fDidAdvNative = (cDelta > 0);
+ else
+ intrDebugOut((DEB_ITRACE,
+ "::UpdateAdviseCounts(%x)Asked advise on cfNative\n",
+ this));
+ }
+
+ return NOERROR;
+}
+
+
+
+
+INTERNAL CDdeObject::UnAdviseOn (CLIPFORMAT cfFormat, int iAdvOn)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::UnAdviseOn(%x,cfFormat=%x,iAdvOn=%x)\n",
+ this,cfFormat,iAdvOn));
+ HRESULT hr;
+ ATOM aItem= (ATOM)0;
+
+ RetZ (m_pDocChannel);
+ UpdateAdviseCounts (cfFormat, iAdvOn, -1);
+ if (m_fDidSendOnClose)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::UnAdviseOn(%x) Ignored because closing\n",
+ this));
+ return NOERROR;
+ }
+ if (wTerminateIsComing (m_pDocChannel))
+ {
+ // We already did a StdCloseDocument, so the server is not willing
+ // to do an unadvise even though the default hanlder asked us to.
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::UnAdviseOn(%x) Terminate coming\n",
+ this));
+ return NOERROR;
+ }
+
+ if (iAdvOn == ON_RENAME)
+ {
+ aItem = wDupAtom (aStdDocName);
+ intrAssert(wIsValidAtom(aItem));
+ }
+ else
+ {
+ intrAssert(wIsValidAtom(m_aItem));
+ aItem = wExtendAtom (m_aItem, iAdvOn);
+ intrAssert(wIsValidAtom(aItem));
+ }
+
+
+ if (!wPostMessageToServer(m_pDocChannel, WM_DDE_UNADVISE,
+ MAKE_DDE_LPARAM (WM_DDE_UNADVISE,cfFormat,aItem),FALSE))
+ {
+ if (aItem)
+ GlobalDeleteAtom (aItem);
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::UnAdviseOn(%x) wPostMessage failed\n",
+ this));
+ return RPC_E_DDE_POST;
+ }
+
+ // Wait For Reply
+ hr = WaitForReply (m_pDocChannel, AA_UNADVISE, FALSE);
+ if (hr != NOERROR && hr != RPC_E_DDE_NACK)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::UnAdviseOn(%x)WaitForReply returns %x\n",
+ this));
+ return hr;
+ }
+
+
+ if (cfFormat==m_cfPict)
+ {
+ if (m_hPict)
+ {
+ // Invalidate the cache so when someone explicitly asks for
+ // the data, they will get fresh data.
+ wFreeData (m_hPict, m_cfPict, TRUE);
+ m_hPict = (HANDLE)0;
+ m_cfPict = 0;
+ }
+ }
+
+ // Due to a bug in the OLE1 libraries, unadvising on a presentation
+ // format effectively unadvises on native.
+ if (cfFormat != g_cfNative && m_fDidAdvNative)
+ {
+ if (iAdvOn == ON_SAVE)
+ {
+ // to reflect the fact that the native advise connection was lost
+ m_iAdvSave--;
+ m_fDidAdvNative = FALSE;
+ RetErr (AdviseOn (g_cfNative, ON_SAVE)); // re-establish
+ }
+ else if (iAdvOn == ON_CLOSE)
+ {
+ // to reflect the fact that the native advise connection was lost
+ m_iAdvClose--;
+ m_fDidAdvNative = FALSE;
+ RetErr (AdviseOn (g_cfNative, ON_CLOSE));
+ }
+ }
+
+ return NOERROR;
+}
+
+
+//
+// Post a message to a 1.0 server (callee) and wait for the acknowledge
+//
+
+
+INTERNAL CDdeObject::Poke
+ (ATOM aItem, HANDLE hDdePoke)
+{
+ HRESULT hr;
+
+ intrDebugOut((DEB_ITRACE,"CDdeObject::Poke(%x)\n",this));
+
+ ATOM aTmpItem;
+
+ intrAssert(wIsValidAtom(aItem));
+
+ aTmpItem = wDupAtom (aItem);
+
+ intrAssert(wIsValidAtom(aTmpItem));
+
+ m_pDocChannel->hDdePoke = hDdePoke;
+
+ LPARAM lp;
+ if (hr = wPostMessageToServer (m_pDocChannel,
+ WM_DDE_POKE,
+ lp=MAKE_DDE_LPARAM(WM_DDE_POKE,hDdePoke,aTmpItem),TRUE))
+ {
+ hr = WaitForReply (m_pDocChannel, AA_POKE);
+ intrDebugOut((DEB_ITRACE,"::Poke(%x) returning %x\n",this,hr));
+ return hr;
+ }
+
+ intrDebugOut((DEB_ITRACE,"::Poke(%x)wPostMessage failed %x\n",this,hr));
+ // Error case
+ if (aTmpItem)
+ GlobalDeleteAtom (aTmpItem);
+ wFreePokeData (m_pDocChannel, m_bOldSvr && m_aClass==aMSDraw);
+ hr = RPC_E_DDE_POST;
+ intrDebugOut((DEB_ITRACE,"::Poke(%x)wPostMessage returns %x\n",this,hr));
+ return hr;
+
+}
+
+INTERNAL CDdeObject::PostSysCommand
+ (LPDDE_CHANNEL pChannel,
+ LPCSTR szCmd,
+ BOOL fStdNew,
+ BOOL fWait)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::PostSysCommand(%x,szCmd=%s,fStdNew=%x,fWait=%x)\n",
+ this,
+ szCmd,
+ fStdNew,
+ fWait));
+
+ ULONG size;
+ WORD len;
+ LPSTR lpdata= NULL;
+ HANDLE hdata = NULL;
+ HRESULT hresult;
+
+
+ #define LN_FUDGE 16 // [],(), 3 * 3 (2 double quotes and comma)
+
+ len = strlen (szCmd);
+
+ // for StdNewDocument command add class name
+ if (fStdNew)
+ len += wAtomLenA (m_aClass);
+
+ // Now add the document length.
+ len += wAtomLenA (m_aTopic);
+
+ // now add the fudge factor for the Quotes etc.
+ len += LN_FUDGE;
+
+ // allocate the buffer and set the command.
+ if (!(hdata = GlobalAlloc (GMEM_DDESHARE, size = len)))
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+ if (!(lpdata = (LPSTR)GlobalLock (hdata))) {
+ Assert (0);
+ GlobalFree (hdata);
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ strcpy (lpdata, (LPSTR)"["); // [
+ strcat (lpdata, szCmd); // [StdCmd
+ if (strcmp (szCmd, "StdExit"))
+ {
+ strcat (lpdata, "(\""); // [StdCmd("
+
+ if (fStdNew)
+ {
+ len = strlen (lpdata);
+ GlobalGetAtomNameA (m_aClass, (LPSTR)lpdata + len, size-len);
+ // [StdCmd("class
+ strcat (lpdata, "\",\""); // [StdCmd("class","
+ }
+
+ len = strlen (lpdata);
+ // now get the topic name.
+ GlobalGetAtomNameA (m_aTopic, lpdata + len, (WORD)size - len);
+ // [StdCmd("class","topic
+ strcat (lpdata, "\")"); // [StdCmd("class","topic")
+ }
+ strcat (lpdata, "]");
+ Assert (strlen(lpdata) < size);
+ intrDebugOut((DEB_ITRACE,"::PostSysCommand(%x) hData(%s)\n",this,lpdata));
+ GlobalUnlock (hdata);
+
+ // return Execute (m_pSysChannel, hdata, /*fStdClose*/FALSE, fWait);
+ // REVIEW: this fixed bug 1856 (johannp)
+ // JasonFul - does it break something else?
+
+ hresult = Execute (m_pSysChannel,
+ hdata,
+ /*fStdClose*/FALSE,
+ fWait,
+ /*fDetectTerminate*/ TRUE);
+
+ intrDebugOut((DEB_ITRACE,"::PostSysCommand(%x) returns \n",this,hresult));
+ return hresult;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::KeepData
+//
+// Synopsis: Given the DDEDATA structure from a WM_DDE_DATA message, extract
+// the real data and keep it till GetData or Save is done.
+//
+//
+// Effects:
+//
+// Arguments: [pChannel] --
+// [hDdeData] --
+//
+// Requires:
+//
+// Returns: E_OUTOFMEMORY or E_HANDLE if failure, NOERROR if success
+//
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-14-94 kevinro Commented
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CDdeObject::KeepData
+ (LPDDE_CHANNEL pChannel, HANDLE hDdeData)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::KeepData(%x)\n",this));
+
+ DDEDATA * lpDdeData = NULL;
+ HANDLE hData;
+ CLIPFORMAT cfFormat;
+
+
+
+ if (!(lpDdeData = (DDEDATA *) (GlobalLock (hDdeData))))
+ {
+ return E_OUTOFMEMORY;;
+ }
+
+
+ cfFormat = lpDdeData->cfFormat;
+ intrDebugOut((DEB_ITRACE,
+ "::KeepData(%x) Keeping cfFormat=%x\n",
+ this,
+ cfFormat));
+
+ GlobalUnlock (hDdeData);
+
+ // Possible Side effect of wHandleFromDdeData() is the freeing of hDdeData
+ if (!(hData = wHandleFromDdeData (hDdeData))
+ || !wIsValidHandle (hData, cfFormat) )
+ {
+ Assert(0);
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ if (cfFormat == g_cfNative) {
+ if (m_hNative)
+ GlobalFree (m_hNative);
+ // Keep the native data
+ RetErr (wTransferHandle (&m_hNative, &hData, cfFormat));
+ }
+ else if (cfFormat == CF_METAFILEPICT ||
+ cfFormat == CF_BITMAP ||
+ cfFormat == CF_DIB)
+ {
+ if (m_hPict)
+ wFreeData (m_hPict, m_cfPict, TRUE);
+ m_cfPict = cfFormat;
+ // Keep the presentation data
+ RetErr (wTransferHandle (&m_hPict, &hData, cfFormat));
+
+#ifdef OLD
+ // Remember size of picture so we can return
+ // a reasonable answer for GetExtent
+ if (cfFormat == CF_METAFILEPICT)
+ {
+ LPMETAFILEPICT lpMfp = (LPMETAFILEPICT) GlobalLock (m_hPict);
+ if (NULL==lpMfp)
+ return E_HANDLE;
+ UpdateExtent (m_cxContentExtent, lpMfp->xExt);
+ UpdateExtent (m_cyContentExtent, lpMfp->yExt);
+ GlobalUnlock (m_hPict);
+ }
+ else if (cfFormat==CF_BITMAP)
+ {
+ BITMAP bm;
+ if (0==GetObject (m_hPict, sizeof(BITMAP), (LPVOID) &bm))
+ return E_HANDLE;
+ UpdateExtent (m_cxContentExtent,
+ wPixelsToHiMetric (bm.bmWidth, giPpliX));
+ UpdateExtent (m_cyContentExtent,
+ wPixelsToHiMetric (bm.bmHeight,giPpliY));
+ }
+ else if (cfFormat==CF_DIB)
+ {
+ BITMAPINFOHEADER * pbminfohdr;
+ pbminfohdr = (BITMAPINFOHEADER *) GlobalLock (m_hPict);
+ if (NULL==pbminfohdr)
+ return E_HANDLE;
+ UpdateExtent (m_cxContentExtent,
+ wPixelsToHiMetric (pbminfohdr->biWidth, giPpliX));
+ UpdateExtent (m_cyContentExtent,
+ wPixelsToHiMetric (pbminfohdr->biHeight,giPpliY));
+ GlobalUnlock (m_hPict);
+ }
+#endif
+
+ }
+ else
+ {
+ if (m_hExtra)
+ wFreeData (m_hExtra, m_cfExtra, TRUE);
+ m_cfExtra = cfFormat;
+ wTransferHandle (&m_hExtra, &hData, cfFormat);
+ }
+
+ return NOERROR;
+}
+
+
+// IsFormatAvailable
+//
+// Does a temporary DDE_REQUEST to see if server supports a format
+// Returns NOERROR if format is available.
+//
+
+
+INTERNAL CDdeObject::IsFormatAvailable
+ (LPFORMATETC pformatetc)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::IsFormatAvailable(%x)\n",this));
+ ATOM aItem=(ATOM)0;
+ HRESULT hresult;
+
+ Puts ("DdeObject::IsFormatAvailable\n");
+
+ if (!HasValidLINDEX(pformatetc))
+ {
+ intrDebugOut((DEB_IERROR, "\t!HasValidLINDEX(pformatetc)\n"));
+ return(DV_E_LINDEX);
+ }
+
+ if (0==pformatetc->cfFormat)
+ return ResultFromScode (E_INVALIDARG);
+
+ if (pformatetc->dwAspect & DVASPECT_ICON)
+ {
+ if (pformatetc->cfFormat==CF_METAFILEPICT)
+ {
+ // This is always available. we get it from the exe.
+ return NOERROR;
+ }
+ // an icon must be a metafile
+ return ResultFromScode (S_FALSE);
+ }
+ if (!(pformatetc->dwAspect & (DVASPECT_CONTENT | DVASPECT_DOCPRINT)))
+ {
+ // 1.0 does not support Thumb.
+ return ReportResult(0, S_FALSE, 0, 0);
+ }
+
+ if (NOERROR == (hresult=m_ConnectionTable.Lookup (pformatetc->cfFormat, NULL)))
+ {
+ // We already got a call to DataObject::Advise on this format,
+ // so it must be available.
+ Puts ("DataObject::Advise had been done on this format.\n");
+ return NOERROR;
+ }
+ else
+ {
+ // Lookup () didn't find this format.
+ ErrZ (GetScode(hresult)==S_FALSE);
+ }
+
+ intrAssert(wIsValidAtom(m_aItem));
+ aItem = wDupAtom (m_aItem);
+ intrAssert(wIsValidAtom(aItem));
+
+ LPARAM lp;
+ if(!wPostMessageToServer (m_pDocChannel, WM_DDE_REQUEST,
+ lp = MAKE_DDE_LPARAM (WM_DDE_REQUEST,pformatetc->cfFormat,aItem),TRUE))
+ {
+
+ return(RPC_E_DDE_POST);
+ }
+
+ if (NOERROR==WaitForReply (m_pDocChannel, AA_REQUESTAVAILABLE))
+ return NOERROR;
+
+ // Last ditch effort: Advise
+ if (NOERROR== AdviseOn (pformatetc->cfFormat, ON_SAVE))
+ {
+ // We cannot Unadvise because an OLE 1.0 bug
+ // terminates DDE advise connections for ALL formats.
+ //// UnAdviseOn (pformatetc->cfFormat, ON_SAVE);
+ // Instead, just remember we did this advise.
+ m_ConnectionTable.Add (0, pformatetc->cfFormat, ADVFDDE_ONSAVE);
+ return NOERROR;
+ }
+ return ResultFromScode (S_FALSE);
+
+errRtn:
+ AssertSz (0, "Error in CDdeObject::IsFormatAvailable");
+ Puth (hresult); Putn();
+ if (aItem)
+ GlobalDeleteAtom (aItem);
+
+ return hresult;
+}
+
+
+
+
+INTERNAL CDdeObject::ChangeTopic
+ (LPSTR lpszTopic)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::ChangeTopic(%x,lpszTopic=%s)\n",this,lpszTopic));
+ HRESULT hresult;
+ LPMONIKER pmkFile=NULL;
+ LPMONIKER pmkItem=NULL;
+ LPMONIKER pmkComp=NULL;
+ LPMONIKER pmkNewName=NULL;
+ ATOM aTopic = wGlobalAddAtomA (lpszTopic);
+ intrAssert(wIsValidAtom(aTopic));
+
+ // Yet-Another-Excel-Hack
+ // Excel 4.0 sends StdDocumentName every time it saves,
+ // whether or not the file name has actually changed. Bug 2957
+ if (aTopic != m_aTopic)
+ {
+ ErrRtnH (CreateOle1FileMoniker (wAtomName(aTopic), m_clsid, &pmkFile));
+ if (m_aItem)
+ {
+ intrAssert (wIsValidAtom (m_aItem));
+ ErrRtnH (CreateItemMoniker (OLESTR("!"), wAtomName (m_aItem), &pmkItem));
+ ErrRtnH (CreateGenericComposite (pmkFile, pmkItem, &pmkComp));
+ (pmkNewName = pmkComp)->AddRef();
+ }
+ else
+ {
+ (pmkNewName = pmkFile)->AddRef();
+ }
+ RetZS (m_pOleAdvHolder, E_OUTOFMEMORY);
+ RetZ (pmkNewName);
+ ErrRtnH (m_pOleAdvHolder->SendOnRename (pmkNewName));
+ }
+ SetTopic (aTopic);
+ hresult = NOERROR;
+
+ errRtn:
+ if (pmkFile)
+ pmkFile->Release();
+ if (pmkItem)
+ pmkItem->Release();
+ if (pmkComp)
+ pmkComp->Release();
+ if (pmkNewName)
+ pmkNewName->Release();
+ return hresult;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::ChangeItem
+//
+// Synopsis: Changes the m_aItem atom, using an Ansi string
+//
+// Effects:
+//
+// Arguments: [szItem] -- Ansi string for the new item
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(void) CDdeObject::ChangeItem
+ (LPSTR szItem)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::ChangeItem(%x,szItem=%s)\n",this,szItem));
+ intrAssert(wIsValidAtom(m_aItem));
+ if (m_aItem)
+ GlobalDeleteAtom (m_aItem);
+ m_aItem = wGlobalAddAtomA (szItem);
+ intrAssert(wIsValidAtom(m_aItem));
+}
+
+
+
+
+INTERNAL CDdeObject::DeclareVisibility
+ (BOOL f,
+ BOOL fCallOnShowIfNec)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::DelcareVisibility(%x)\n",this));
+ if (f)
+ m_fWasEverVisible = TRUE;
+ if ((f && (!m_fVisible || !m_fCalledOnShow)) ||
+ (!f && m_fVisible))
+ {
+ if (m_pOleClientSite && fCallOnShowIfNec && m_clsid != CLSID_Package)
+ {
+ m_pOleClientSite->OnShowWindow (f);
+ m_fCalledOnShow = f;
+ }
+ m_fVisible = f;
+ }
+ return NOERROR;
+}
+
+
+
+INTERNAL CDdeObject::Update
+ (BOOL fRequirePresentation)
+{
+ intrDebugOut((DEB_ITRACE,
+ "CDdeObject::Update(%x,fRequiredPresentation=%x)\n",
+ this,
+ fRequirePresentation));
+ // Get latest data
+ // OLE 1.0 spec says servers must supply metafile format.
+ HRESULT hresult = RequestData (m_cfPict ? m_cfPict : CF_METAFILEPICT);
+ if (fRequirePresentation && hresult!=NOERROR)
+ return hresult;
+ RetErr (RequestData (g_cfNative));
+ SendOnDataChange (ON_CHANGE);
+ return NOERROR;
+}
+
+
+
+INTERNAL CDdeObject::Save
+ (LPSTORAGE pstg)
+{
+ intrDebugOut((DEB_ITRACE,"CDdeObject::Save(%x)\n",this));
+ VDATEIFACE (pstg);
+#ifdef OLE1INTEROP
+ RetErr (StSave10NativeData (pstg, m_hNative, m_fOle1interop));
+#else
+ RetErr (StSave10NativeData (pstg, m_hNative, FALSE));
+#endif
+ if (m_aItem)
+ {
+ intrAssert(wIsValidAtom(m_aItem));
+ RetErr (StSave10ItemName (pstg, wAtomNameA (m_aItem)));
+ }
+ RetErr (wWriteFmtUserType (pstg, m_clsid));
+ return NOERROR;
+}
+
+/*
+ * IMPLEMENTATION of CUnknownImpl
+ *
+ */
+
+
+
+STDMETHODIMP_(ULONG) NC(CDdeObject,CUnknownImpl)::AddRef()
+{
+ ChkD(m_pDdeObject);
+
+ return InterlockedAddRef(&(m_pDdeObject->m_refs));
+}
+
+
+STDMETHODIMP_(ULONG) NC(CDdeObject,CUnknownImpl)::Release()
+{
+ ChkD(m_pDdeObject);
+ Assert (m_pDdeObject->m_refs != 0);
+ ULONG ul;
+
+ if ((ul=InterlockedRelease(&(m_pDdeObject->m_refs))) == 0) {
+ m_pDdeObject->m_ProxyMgr.Disconnect();
+
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ // the object can not be delete if guarded
+ // which is the case if DelayDelete state is 'DelayIt'
+ //
+ if (m_pDdeObject->_DelayDelete == DelayIt)
+ {
+ // set the state to ReadyToDelete and
+ // the object will be deleted at the
+ // UnGuard call
+ m_pDdeObject->_DelayDelete = ReadyToDelete;
+ intrDebugOut((DEB_IWARN ,"Can not release CDdeObject\n"));
+ return 1;
+ }
+#endif //_CHICAGO_
+ delete m_pDdeObject;
+ return 0;
+ }
+ return ul;
+}
+
+
+
+
+STDMETHODIMP NC(CDdeObject,CUnknownImpl)::QueryInterface(REFIID iid, LPLPVOID ppv)
+{
+ ChkD(m_pDdeObject);
+ if (iid == IID_IUnknown) {
+ *ppv = (void FAR *)&m_pDdeObject->m_Unknown;
+ AddRef();
+ return NOERROR;
+ }
+ else if (iid == IID_IOleObject)
+ *ppv = (void FAR *) &(m_pDdeObject->m_Ole);
+ else if (iid == IID_IDataObject)
+ *ppv = (void FAR *) &(m_pDdeObject->m_Data);
+ else if (iid == IID_IPersist || iid == IID_IPersistStorage)
+ *ppv = (void FAR *) &(m_pDdeObject->m_PersistStg);
+ else if (iid == IID_IProxyManager)
+ *ppv = (void FAR *) &(m_pDdeObject->m_ProxyMgr);
+ else if (iid == IID_IOleItemContainer
+ || iid == IID_IOleContainer
+ || iid == IID_IParseDisplayName)
+ *ppv = (void FAR *) &(m_pDdeObject->m_OleItemContainer);
+ else {
+ Puts ("INTERFACE NOT FOUND \r\n");
+ *ppv = NULL;
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+
+ m_pDdeObject->m_pUnkOuter->AddRef();
+ return NOERROR;
+}
+
diff --git a/private/ole32/com/remote/dde/client/ddeproxy.h b/private/ole32/com/remote/dde/client/ddeproxy.h
new file mode 100644
index 000000000..8f55b6dd2
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/ddeproxy.h
@@ -0,0 +1,608 @@
+/* ddeproxy.h
+
+ Used by ddeproxy.cpp ddeDO.cpp ddeOO.cpp
+
+ Author: Jason Fuller jasonful 24-July-1992
+
+*/
+#ifndef fDdeProxy_h
+#define fDdeProxy_h
+
+//
+// One of the oleint.h routines redefines GlobalAlloc and friends
+// to perform some memory tracking functions.
+//
+// This doesn't work in these files, since the tracking functions
+// add tail checking, and size to the data structures. GlobalSize
+// is a common function to use to determine how much data to
+// serialize, plus it turns out that the other side of a DDE
+// connection will often be the caller to free the memory.
+//
+// Therefore, OLE_DDE_NO_GLOBAL_TRACKING is used to disable this in the
+// global header file ih\memapi.hxx. Check to insure this
+// flag is set on the compile line
+//
+#if !defined(OLE_DDE_NO_GLOBAL_TRACKING)
+error OLE_DDE_OLE_DDE_NO_GLOBAL_TRACKING must be defined to build this directory
+#endif
+
+
+#include <ole2int.h>
+#include <callcont.hxx>
+#include <ddeint.h>
+#include <dde.h>
+#include <olerem.h>
+#include <ole1cls.h>
+#include <limits.h>
+// For fDdeCodeInOle2Dll flag
+#include <ddeatoms.h>
+#include <ddepack.h>
+#include <ddedebug.h>
+
+#ifdef OLE_DEBUG_EXT
+#include <ntsdexts.h>
+#endif OLE_DEBUG_EXT
+
+#include "ddechc.hxx"
+#define LPCALLINFO LPVOID
+#include "ddeerr.h"
+#include "cnct_tbl.h"
+
+#define MAX_STR 256
+
+// number of .01 mm per inch
+#define HIMETRIC_PER_INCH 2540
+
+//#define fDebugOutput
+
+// callback notifications
+#define ON_CHANGE 0
+#define ON_SAVE 1
+#define ON_CLOSE 2
+#define ON_RENAME 3
+
+// AwaitAck values
+#define AA_NONE 0
+#define AA_REQUEST 1
+#define AA_ADVISE 2
+#define AA_POKE 3
+#define AA_EXECUTE 4
+#define AA_UNADVISE 5
+#define AA_INITIATE 6
+#define AA_TERMINATE 7
+// A DDE_REQUEST to see if a format is available, not to keep the data.
+#define AA_REQUESTAVAILABLE 8
+
+// Bits for Positive WM_DDE_ACK
+//#define POSITIVE_ACK 0x8000
+//#define NEGATIVE_ACK 0x0000
+
+
+
+typedef DWORD CHK;
+const DWORD chkDdeObj = 0xab01; // magic cookie
+
+
+typedef struct tagDDE_CHANNEL : public CPrivAlloc {
+ ULONG AddReference()
+ {
+ return ++m_cRefs;
+ }
+ ULONG ReleaseReference()
+ {
+ if (--m_cRefs == 0)
+ {
+ delete this;
+ return(0);
+ }
+ return(m_cRefs);
+ }
+ ULONG m_cRefs;
+ HWND hwndCli;
+ HWND hwndSvr;
+ BOOL bTerminating;
+ int iExtraTerms;
+ WORD wTimer;
+ DWORD dwStartTickCount;
+ WORD msgFirst;
+ WORD msgLast;
+ HWND msghwnd; //
+ BOOL fRejected; // because fBusy flag set in DDE_ACK
+ WORD wMsg;
+ LONG lParam;
+ int iAwaitAck;
+ HRESULT hres;
+ HANDLE hopt; // Memory blocks I may have to free for DDE_ADVISE
+ HANDLE hDdePoke; // for DDE_POKE
+ HANDLE hCommands; // for DDE_EXECUTE
+ WORD wChannelDeleted;
+ PCALLDATA pCD;
+ PCALLCONTROL pCallCont;
+ CDdeChannelControl *pChanCont;
+} DDE_CHANNEL;
+
+
+#define Channel_InModalloop 1
+#define Channel_DeleteNow 2
+
+
+typedef DDE_CHANNEL * LPDDE_CHANNEL;
+extern BOOL bWndClassesRegistered;
+
+#define hinstSO g_hmodOLE2
+extern HMODULE g_hmodOLE2;
+
+extern INTERNAL_(BOOL) wRegisterClasses (void);
+
+#ifndef _MAC
+extern CLIPFORMAT g_cfNative;
+extern CLIPFORMAT g_cfBinary;
+#endif
+
+#ifdef _CHICAGO_
+//Note:POSTPPC
+//
+// DelayDelete is used to delay deleting the CDdeObject
+// Guard will set it to DelayIt
+// UnGuard will reset it to NoDelay or delete the object
+// if state is ReadyToDelete
+//
+typedef enum
+{
+ NoDelay = 0, // normal state
+ DelayIt = 1, // object is protected and deleting will be delayed
+ ReadyToDelete = 2 // object was is DelayIt state and can be deleted
+} DelayDelete;
+
+#endif // _CHICAGO_
+
+/*
+ * Definition of CDdeObject
+ *
+ */
+class CMsgFilterInfo;
+class CDdeObject;
+
+class CDdeObject : public CPrivAlloc
+{
+public:
+
+ static INTERNAL_(LPUNKNOWN) Create (IUnknown * pUnkOuter,
+ REFCLSID clsidClass,
+ ULONG ulObjType = OT_EMBEDDED,
+ ATOM aTopic = NULL,
+ LPOLESTR szItem = NULL,
+ CDdeObject * * ppdde = NULL,
+ BOOL fAllowNullClsid = FALSE);
+
+ INTERNAL_(void) OnInitAck (LPDDE_CHANNEL pChannel, HWND hwndSvr);
+ INTERNAL_(BOOL) OnAck (LPDDE_CHANNEL pChannel, LONG lParam);
+ INTERNAL_(void) OnTimer (LPDDE_CHANNEL pChannel);
+ INTERNAL OnData (LPDDE_CHANNEL pChannel, HANDLE hData,ATOM aItem);
+ INTERNAL OnDataAvailable (LPDDE_CHANNEL pChannel, HANDLE hData,ATOM aItem);
+ INTERNAL OnTerminate (LPDDE_CHANNEL pChannel, HWND hwndPost);
+
+ INTERNAL_(LPDDE_CHANNEL) GetSysChannel(void)
+ { return m_pSysChannel; }
+
+ INTERNAL_(LPDDE_CHANNEL) GetDocChannel(void)
+ { return m_pDocChannel; }
+
+ INTERNAL_(BOOL) AllocDdeChannel(LPDDE_CHANNEL * lpChannel, LPSTR lpszWndClass);
+ INTERNAL_(BOOL) InitSysConv (void);
+ INTERNAL_(void) SetTopic (ATOM aTopic);
+
+ INTERNAL SendOnDataChange (int iAdvOpt);
+ INTERNAL OleCallBack (int iAdvOpt,LPDDE_CHANNEL pChannel);
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ INTERNAL_(void) Guard()
+ {
+ intrDebugOut((DEB_IWARN ,"CDdeObject: %x DelayDelete is set to 'DelayIt'\n", this));
+ _DelayDelete = DelayIt;
+ }
+ INTERNAL_(BOOL) UnGuard()
+ {
+ if (_DelayDelete == ReadyToDelete)
+ {
+ intrDebugOut((DEB_IWARN ,"CDdeObject: %x DelayDelete it set 'ReadyToDelete'\n", this));
+ delete this;
+ intrDebugOut((DEB_IWARN ,"CDdeObject: %x was deleted\n", this));
+ return TRUE;
+ }
+ else
+ {
+ intrDebugOut((DEB_IWARN ,"CDdeObject: %x DelayDelete set to 'NoDelay'\n", this));
+ _DelayDelete = NoDelay;
+ }
+
+ return FALSE;
+ }
+#endif // _CHICAGO_
+
+ BOOL m_fDoingSendOnDataChange;
+ ULONG m_cRefCount;
+
+private:
+
+ CDdeObject (IUnknown * pUnkOuter);
+ ~CDdeObject (void);
+ INTERNAL TermConv (LPDDE_CHANNEL pChannel, BOOL fWait=TRUE);
+ INTERNAL_(void) DeleteChannel (LPDDE_CHANNEL pChannel);
+ INTERNAL_(BOOL) LaunchApp (void);
+ INTERNAL MaybeUnlaunchApp (void);
+ INTERNAL UnlaunchApp (void);
+ INTERNAL Execute (LPDDE_CHANNEL pChannel,
+ HANDLE hdata,
+ BOOL fStdCloseDoc=FALSE,
+ BOOL fWait=TRUE,
+ BOOL fDetectTerminate = TRUE);
+ INTERNAL Advise(void);
+ INTERNAL AdviseOn (CLIPFORMAT cfFormat, int iAdvOn);
+ INTERNAL UnAdviseOn (CLIPFORMAT cfFormat, int iAdvOn);
+ INTERNAL Poke (ATOM aItem, HANDLE hDdePoke);
+ INTERNAL PostSysCommand (LPDDE_CHANNEL pChannel,
+ LPCSTR szCmd,
+ BOOL bStdNew=FALSE,
+ BOOL fWait=TRUE);
+
+#ifdef _CHICAGO_
+ //POSTPPC
+ INTERNAL_(BOOL) CanMakeOutCall(LPDDE_CHANNEL pChannel);
+#endif
+
+ INTERNAL WaitForReply (LPDDE_CHANNEL pChannel,
+ int iAwaitAck,
+ BOOL fStdCloseDoc = FALSE,
+ BOOL fDetectTerminate = TRUE);
+ INTERNAL KeepData (LPDDE_CHANNEL pChannel, HANDLE hDdeData);
+ INTERNAL ChangeTopic (LPSTR lpszTopic);
+ INTERNAL_(void) ChangeItem (LPSTR lpszItem);
+ INTERNAL IsFormatAvailable (LPFORMATETC);
+ INTERNAL_(BOOL) CanCallBack(LPINT);
+ INTERNAL RequestData (CLIPFORMAT);
+ INTERNAL SetTargetDevice (const DVTARGETDEVICE *);
+ INTERNAL DocumentLevelConnect (LPBINDCTX pbc);
+ INTERNAL SendOnClose (void);
+ INTERNAL UpdateAdviseCounts (CLIPFORMAT cf,
+ int iAdvOn,
+ signed int cDelta);
+ INTERNAL DeclareVisibility (BOOL fVisible,
+ BOOL fCallOnShowIfNec=TRUE);
+ INTERNAL Save (LPSTORAGE);
+ INTERNAL Update (BOOL fRequirePresentation);
+
+implementations:
+
+ STDUNKDECL(CDdeObject,DdeObject)
+ STDDEBDECL(CDdeObject,DdeObject)
+
+
+ implement COleObjectImpl : IOleObject
+ {
+ public:
+ COleObjectImpl (CDdeObject * pDdeObject)
+ { m_pDdeObject = pDdeObject; }
+
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) ( REFIID riid, LPVOID * ppvObj);
+ STDMETHOD_(ULONG,AddRef) ();
+ STDMETHOD_(ULONG,Release) ();
+
+ // *** IOleObject methods ***
+ STDMETHOD(SetClientSite) ( LPOLECLIENTSITE pClientSite);
+ STDMETHOD(GetClientSite) ( LPOLECLIENTSITE * ppClientSite);
+ STDMETHOD(SetHostNames) ( LPCOLESTR szContainerApp, LPCOLESTR szContainerObj);
+ STDMETHOD(Close) ( DWORD reserved);
+ STDMETHOD(SetMoniker) ( DWORD dwWhichMoniker, LPMONIKER pmk);
+ STDMETHOD(GetMoniker) ( DWORD dwAssign, DWORD dwWhichMoniker,LPMONIKER * ppmk);
+ STDMETHOD(InitFromData) ( LPDATAOBJECT pDataObject,BOOL fCreation,DWORD dwReserved);
+ STDMETHOD(GetClipboardData) ( DWORD dwReserved,LPDATAOBJECT * ppDataObject);
+
+ STDMETHOD(DoVerb) ( LONG iVerb,
+ LPMSG lpmsg,
+ LPOLECLIENTSITE pActiveSite,
+ LONG lindex,
+ HWND hwndParent,
+ const RECT * lprcPosRect);
+
+ STDMETHOD(EnumVerbs) ( IEnumOLEVERB * * ppenumOleVerb);
+ STDMETHOD(Update) ();
+ STDMETHOD(IsUpToDate) ();
+ STDMETHOD(GetUserClassID) ( CLSID * pClsid);
+ STDMETHOD(GetUserType) ( DWORD dwFormOfType, LPOLESTR * pszUserType);
+ STDMETHOD(SetExtent) ( DWORD dwDrawAspect, LPSIZEL lpsizel);
+ STDMETHOD(GetExtent) ( DWORD dwDrawAspect, LPSIZEL lpsizel);
+ STDMETHOD(Advise)( IAdviseSink * pAdvSink, DWORD * pdwConnection) ;
+ STDMETHOD(Unadvise) ( DWORD dwConnection);
+ STDMETHOD(EnumAdvise) ( LPENUMSTATDATA * ppenumAdvise);
+ STDMETHOD(GetMiscStatus) ( DWORD dwAspect, DWORD * pdwStatus);
+ STDMETHOD(SetColorScheme) ( LPLOGPALETTE lpLogpal);
+
+ private:
+ CDdeObject * m_pDdeObject;
+ };
+
+
+ implement CDataObjectImpl : IDataObject
+ {
+ public:
+ CDataObjectImpl (CDdeObject * pDdeObject)
+ { m_pDdeObject = pDdeObject; }
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) ( REFIID riid, LPVOID * ppvObj);
+ STDMETHOD_(ULONG,AddRef) () ;
+ STDMETHOD_(ULONG,Release) ();
+
+ STDMETHOD(GetData) ( LPFORMATETC pformatetcIn,LPSTGMEDIUM pmedium );
+ STDMETHOD(GetDataHere) ( LPFORMATETC pformatetc,LPSTGMEDIUM pmedium );
+ STDMETHOD(QueryGetData) ( LPFORMATETC pformatetc );
+ STDMETHOD(GetCanonicalFormatEtc) ( LPFORMATETC pformatetc,LPFORMATETC pformatetcOut);
+ STDMETHOD(SetData) ( LPFORMATETC pformatetc, STGMEDIUM * pmedium, BOOL fRelease);
+ STDMETHOD(EnumFormatEtc) ( DWORD dwDirection, LPENUMFORMATETC * ppenumFormatEtc);
+ STDMETHOD(DAdvise) ( FORMATETC * pFormatetc, DWORD advf, LPADVISESINK pAdvSink, DWORD * pdwConnection) ;
+ STDMETHOD(DUnadvise) ( DWORD dwConnection) ;
+ STDMETHOD(EnumDAdvise) ( LPENUMSTATDATA * ppenumAdvise) ;
+
+ private:
+ CDdeObject * m_pDdeObject;
+ };
+
+
+ implement CPersistStgImpl : IPersistStorage
+ {
+ public:
+ CPersistStgImpl (CDdeObject * pDdeObject)
+ { m_pDdeObject = pDdeObject; }
+
+ STDMETHOD(QueryInterface) ( REFIID iid, LPVOID * ppvObj);
+ STDMETHOD_(ULONG,AddRef) ();
+ STDMETHOD_(ULONG,Release) ();
+ STDMETHOD(GetClassID) ( LPCLSID pClassID);
+ STDMETHOD(IsDirty) (void);
+ STDMETHOD(InitNew) ( LPSTORAGE pstg);
+ STDMETHOD(Load) ( LPSTORAGE pstg);
+ STDMETHOD(Save) ( LPSTORAGE pstgSave, BOOL fSameAsLoad);
+ STDMETHOD(SaveCompleted) ( LPSTORAGE pstgNew);
+ STDMETHOD(HandsOffStorage) (void);
+
+ private:
+ CDdeObject * m_pDdeObject;
+ };
+
+
+ implement CProxyManagerImpl : IProxyManager
+ {
+ public:
+ CProxyManagerImpl (CDdeObject * pDdeObject)
+ { m_pDdeObject = pDdeObject; }
+
+ STDMETHOD(QueryInterface) ( REFIID iid, LPVOID * ppvObj);
+ STDMETHOD_(ULONG,AddRef) ();
+ STDMETHOD_(ULONG,Release) ();
+
+ STDMETHOD(CreateServer)(REFCLSID rclsid, DWORD clsctx, void *pv);
+ STDMETHOD_(BOOL, IsConnected)(void);
+ STDMETHOD(LockConnection)(BOOL fLock, BOOL fLastUnlockReleases);
+ STDMETHOD_(void, Disconnect)();
+
+
+ STDMETHOD(Connect)(OID oid, REFCLSID rclsid);
+ STDMETHOD(EstablishIID)(REFIID iid, LPVOID FAR* ppv);
+
+ STDMETHOD(CreateServerWithHandler)(REFCLSID rclsid, DWORD clsctx, void *pv,
+ REFCLSID rclsidHandler, IID iidSrv, void **ppv,
+ IID iidClnt, void *pClientSiteInterface);
+
+ private:
+ CDdeObject * m_pDdeObject;
+ };
+
+
+ implement COleItemContainerImpl : IOleItemContainer
+ {
+ public:
+ COleItemContainerImpl (CDdeObject * pDdeObject)
+ { m_pDdeObject = pDdeObject; }
+
+ STDMETHOD(QueryInterface) ( REFIID iid, LPVOID * ppvObj);
+ STDMETHOD_(ULONG,AddRef) ();
+ STDMETHOD_(ULONG,Release) ();
+
+ // IParseDisplayName method
+ STDMETHOD(ParseDisplayName) ( LPBC pbc,
+ LPOLESTR lpszDisplayName,
+ ULONG * pchEaten,
+ LPMONIKER * ppmkOut) ;
+
+ // IOleContainer methods
+ STDMETHOD(EnumObjects) ( DWORD grfFlags,LPENUMUNKNOWN * ppenumUnk);
+
+ STDMETHOD(LockContainer) (BOOL fLock);
+
+ // IOleItemContainer methods
+ STDMETHOD(GetObject) ( LPOLESTR lpszItem,
+ DWORD dwSpeedNeeded,
+ LPBINDCTX pbc,
+ REFIID riid,
+ LPVOID * ppvObject) ;
+ STDMETHOD(GetObjectStorage) ( LPOLESTR lpszItem,
+ LPBINDCTX pbc,
+ REFIID riid,
+ LPVOID * ppvStorage) ;
+
+ STDMETHOD(IsRunning) ( LPOLESTR lpszItem) ;
+
+ private:
+ CDdeObject * m_pDdeObject;
+ };
+
+
+
+ DECLARE_NC(CDdeObject, COleObjectImpl)
+ DECLARE_NC(CDdeObject, CDataObjectImpl)
+ DECLARE_NC(CDdeObject, CPersistStgImpl)
+ DECLARE_NC(CDdeObject, CProxyManagerImpl)
+ DECLARE_NC(CDdeObject, COleItemContainerImpl)
+
+ COleObjectImpl m_Ole;
+ CDataObjectImpl m_Data;
+ CPersistStgImpl m_PersistStg;
+ CProxyManagerImpl m_ProxyMgr;
+ COleItemContainerImpl m_OleItemContainer;
+
+shared_state:
+ ULONG m_refs;
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ DelayDelete _DelayDelete;
+#endif // _CHICAGO_
+ ULONG m_ulObjType;
+ CLSID m_clsid;
+ ATOM m_aClass;
+ ATOM m_aExeName;
+ ATOM m_aTopic;
+ ATOM m_aItem;
+ BOOL m_bRunning;
+ IUnknown * m_pUnkOuter;
+ IOleClientSite * m_pOleClientSite;
+ LPSTORAGE m_pstg;
+ BOOL m_bInitNew;
+ BOOL m_bOldSvr;
+ HANDLE m_hNative;
+ HANDLE m_hPict;
+ HANDLE m_hExtra;
+ CLIPFORMAT m_cfPict;
+ CLIPFORMAT m_cfExtra;
+
+ BOOL m_fDidSendOnClose;
+ BOOL m_fNoStdCloseDoc;
+ BOOL m_fDidStdCloseDoc;
+ BOOL m_fDidStdOpenDoc;
+ BOOL m_fDidGetObject;
+ BOOL m_fDidLaunchApp;
+ BOOL m_fUpdateOnSave;
+ BOOL m_fGotCloseData;
+
+#ifdef OLE1INTEROP
+ BOOL m_fOle1interop;
+#endif
+
+ // Invisible update stuff
+ ULONG m_cLocks; // PM::LockConnection lock count (init 1)
+ BOOL m_fVisible; // is server visible (as best we know)?
+ BOOL m_fWasEverVisible;
+ BOOL m_fCalledOnShow; // Did we call IOleClientSite::OnShow
+
+ CHK m_chk;
+ DVTARGETDEVICE * m_ptd;
+
+ // m_iAdvClose and m_iAdvSave are counts (1 or 2) of the number of formats
+ // that have advise connections of a given type (Save or Close)
+ int m_iAdvClose;
+ int m_iAdvSave;
+ int m_iAdvChange;
+
+ BOOL m_fDidAdvNative;
+
+ // Extent info
+#ifdef OLD
+ long m_cxContentExtent;
+ long m_cyContentExtent;
+#endif
+
+ // terminate info - only used to detect a premature WM_DDE_TERMINATE
+ WORD m_wTerminate;
+
+ IDataAdviseHolder * m_pDataAdvHolder;
+ IOleAdviseHolder * m_pOleAdvHolder;
+ CDdeConnectionTable m_ConnectionTable;
+
+
+ // DDE window related stuff
+ LPDDE_CHANNEL m_pSysChannel;
+ LPDDE_CHANNEL m_pDocChannel;
+
+ friend INTERNAL DdeBindToObject
+ (LPCOLESTR szFile,
+ REFCLSID clsid,
+ BOOL fPackageLink,
+ REFIID iid,
+ LPLPVOID ppv);
+
+ friend INTERNAL DdeIsRunning
+ (CLSID clsid,
+ LPCOLESTR szFile,
+ LPBC pbc,
+ LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning);
+#ifdef OLE_DEBUG_EXT
+
+#endif OLE_DEBUG_EXT
+};
+//
+// Note: WM_DDE_TERMINATE
+// A state machine is used to delay the executing of a premature WM_DDE_TERMINTE
+// message, which is send by some apps instead of WM_DDE_ACK (or alike).
+// The code is in WaitForReply() and in OnTerminate()
+typedef enum {
+ Terminate_None = 0, // default state - terminate code is executed
+ Terminate_Detect = 1, // window proc will NOT execute terminate code
+ Terminate_Received = 2 // wait loop does not need to run, execute terminate code now
+} TERMINATE_DOCUMENT;
+
+
+
+INTERNAL_(BOOL) wPostMessageToServer(LPDDE_CHANNEL pChannel,
+ WORD wMsg,
+ LONG lParam,
+ BOOL fFreeOnError);
+
+INTERNAL_(ATOM) wAtomFromCLSID(REFCLSID rclsid);
+INTERNAL_(ATOM) wGetExeNameAtom (REFCLSID rclsid);
+INTERNAL_(BOOL) wIsWindowValid (HWND hwnd);
+INTERNAL_(void) wFreeData (HANDLE hData, CLIPFORMAT cfFormat,
+ BOOL fFreeNonGdiHandle=TRUE);
+INTERNAL_(BOOL) wInitiate (LPDDE_CHANNEL pChannel, ATOM aLow, ATOM aHigh);
+INTERNAL wScanItemOptions (ATOM aItem, int * lpoptions);
+INTERNAL_(BOOL) wClearWaitState (LPDDE_CHANNEL pChannel);
+INTERNAL_(HANDLE) wStdCloseDocumentHandle (void);
+INTERNAL_(ATOM) wExtendAtom (ATOM aIitem, int iAdvOn);
+INTERNAL_(int) wAtomLen (ATOM atom);
+INTERNAL_(int) wAtomLenA (ATOM atom);
+INTERNAL_(LPDDE_CHANNEL) wAllocDdeChannel(void);
+INTERNAL_(HANDLE) wHandleFromDdeData(HANDLE hDdeData);
+INTERNAL_(BOOL) wIsOldServer (ATOM aClass);
+INTERNAL_(LPSTR) wAllocDdePokeBlock (DWORD dwSize, CLIPFORMAT cfFormat,LPHANDLE phDdePoke);
+INTERNAL_(void) wFreePokeData (LPDDE_CHANNEL pChannel, BOOL fMSDrawBug);
+INTERNAL_(HANDLE) wPreparePokeBlock (HANDLE hData, CLIPFORMAT cfFormat,
+ ATOM aClass, BOOL bOldSvr);
+INTERNAL_(HANDLE) wNewHandle (LPSTR lpstr, DWORD cb);
+INTERNAL wDupData (LPHANDLE ph, HANDLE h, CLIPFORMAT cf);
+INTERNAL wHandleCopy (HANDLE hDst, HANDLE hSrc);
+INTERNAL wGetRequestResponse (LPDDE_CHANNEL pChannel, CLIPFORMAT cf, ATOM aItem);
+INTERNAL wGetItemFromClipboard (ATOM * paItem);
+INTERNAL GetDefaultIcon (REFCLSID clsidIn, LPCOLESTR szFile, HANDLE * phmfp);
+INTERNAL_(BOOL) wTerminateIsComing (LPDDE_CHANNEL);
+INTERNAL wTimedGetMessage (LPMSG pmsg, HWND hwnd, WORD wFirst, WORD wLast);
+
+INTERNAL_(ATOM) wGlobalAddAtom(LPCOLESTR sz);
+INTERNAL_(ATOM) wGlobalAddAtomA(LPCSTR sz);
+
+INTERNAL wVerifyFormatEtc (LPFORMATETC pformatetc);
+INTERNAL wNormalize (LPFORMATETC pfetc, LPFORMATETC pfetcOut);
+INTERNAL wTransferHandle (LPHANDLE phDst, LPHANDLE phSrc, CLIPFORMAT cf);
+INTERNAL wClassesMatch (REFCLSID clsidIn, LPOLESTR szFile);
+
+#if DBG == 1
+INTERNAL_(BOOL) wIsValidHandle (HANDLE h, CLIPFORMAT cf);
+INTERNAL_(BOOL) wIsValidAtom (ATOM a);
+#endif
+
+const char achStdCloseDocument[]="[StdCloseDocument]";
+const char achStdOpenDocument[]="StdOpenDocument";
+const char achStdExit[]="StdExit";
+const char achStdNewDocument[]="StdNewDocument";
+const char achStdEditDocument[]="StdEditDocument";
+
+#endif // ddeproxy.h
diff --git a/private/ole32/com/remote/dde/client/ddestg.cxx b/private/ole32/com/remote/dde/client/ddestg.cxx
new file mode 100644
index 000000000..657b9c2fe
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/ddestg.cxx
@@ -0,0 +1,535 @@
+/*
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddeStg.cpp
+
+Abstract:
+
+ This module contains the DdeObject::PersistStg and
+ DdeObject::ProxyManager methods
+
+Author:
+
+ Srini Koppolu (srinik) 22-June-1992
+ Jason Fuller (jasonful) 24-July-1992
+
+*/
+
+#include "ddeproxy.h"
+ASSERTDATA
+
+
+/*
+ * IMPLEMENTATION of CPersistStgImpl methods
+ *
+ */
+
+
+STDUNKIMPL_FORDERIVED(DdeObject, PersistStgImpl)
+
+
+#pragma SEG(CDdeObject_CPersistStgImpl_GetClassID)
+STDMETHODIMP NC(CDdeObject,CPersistStgImpl)::GetClassID (CLSID FAR* pClassID)
+{
+ *pClassID = m_pDdeObject->m_clsid;
+ return NOERROR;
+}
+
+
+#pragma SEG(CDdeObject_CPersistStgImpl_IsDirty)
+STDMETHODIMP NC(CDdeObject,CPersistStgImpl)::IsDirty ()
+{
+ return NOERROR;
+}
+
+
+
+#pragma SEG(CDdeObject_CPersistStgImpl_InitNew)
+STDMETHODIMP NC(CDdeObject,CPersistStgImpl)::InitNew
+ (IStorage FAR* pstg)
+{
+ HRESULT hres;
+ intrDebugOut((DEB_ITRACE,
+ "DdeObejct::InitNew(%x,pstg=%x)\n",
+ this,
+ pstg));
+
+ if (hres = m_pDdeObject->PostSysCommand (m_pDdeObject->m_pSysChannel,
+ (LPSTR)&achStdNewDocument,
+ TRUE))
+ return hres;
+
+ if (hres = m_pDdeObject->m_ProxyMgr.Connect (IID_NULL, CLSID_NULL))
+ return hres;
+
+ RetErr (m_pDdeObject->TermConv (m_pDdeObject->m_pSysChannel));
+ if (m_pDdeObject->m_pstg)
+ {
+ m_pDdeObject->m_pstg->Release();
+ }
+ m_pDdeObject->m_pstg = pstg;
+ pstg->AddRef();
+ return hres;
+}
+
+
+
+#pragma SEG(CDdeObject_CPersistStgImpl_Load)
+STDMETHODIMP NC(CDdeObject,CPersistStgImpl)::Load (IStorage FAR* pstg)
+{
+ LPSTR lpBuf=NULL;
+ HANDLE hDdePoke = NULL;
+ DWORD dwSize;
+ CStmBufRead StmRead;
+ CStmBufRead StmReadItem;
+ HRESULT hresult;
+
+ intrDebugOut((DEB_ITRACE,"CDdeObject::Load(%x,pstg=%x)\n",this,pstg));
+
+ {
+
+ if (hresult = StmRead.OpenStream(pstg, OLE10_NATIVE_STREAM))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) OpenStream failed(%x)\n",
+ this,
+ hresult));
+ return hresult;
+ }
+
+
+ if (hresult = StmRead.Read(&dwSize, sizeof(DWORD)))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) StRead failed(%x)\n",
+ this,
+ hresult));
+
+ goto errRtn;
+ }
+
+
+ lpBuf = wAllocDdePokeBlock (dwSize, g_cfNative, &hDdePoke);
+
+ if (lpBuf == NULL)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) wAllocDdePokeBlock failed(%x)\n",
+ this,
+ hresult));
+
+ hresult = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ if (hresult = StmRead.Read(lpBuf, dwSize))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) StRead of cfNative failed(%x)\n",
+ this,
+ hresult));
+ goto errRtn;
+ }
+
+ if (m_pDdeObject->m_hNative)
+ {
+ GlobalFree (m_pDdeObject->m_hNative);
+ }
+ m_pDdeObject->m_hNative = wNewHandle (lpBuf, dwSize);
+
+ if (m_pDdeObject->m_hNative == NULL)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) m_hNative NULL\n",
+ this));
+ }
+ }
+
+ GlobalUnlock (hDdePoke); // done with lpBuf
+
+ if (hresult = m_pDdeObject->PostSysCommand (m_pDdeObject->m_pSysChannel,
+ (LPSTR)&achStdEditDocument,
+ FALSE))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) PostSysCommand %s failed (%x)\n",
+ this,
+ &achStdEditDocument,
+ hresult));
+ goto errRtn;
+ }
+
+
+ // Read Item Name, if there is one
+ if (NOERROR == StmReadItem.OpenStream(pstg, OLE10_ITEMNAME_STREAM))
+ {
+ LPSTR szItemName = NULL;
+
+ ErrRtnH (ReadStringStreamA (StmReadItem, &szItemName));
+ m_pDdeObject->ChangeItem (szItemName);
+ PubMemFree(szItemName);
+ }
+
+ if (hresult = m_pDdeObject->m_ProxyMgr.Connect (IID_NULL, CLSID_NULL))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) ProxyMgr.Connect failed(%x)\n",
+ this,
+ hresult));
+ goto errRtn;
+ }
+
+
+ if ((hresult = m_pDdeObject->Poke(m_pDdeObject->m_aItem, hDdePoke))
+ != NOERROR)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) Poke failed(%x)\n",
+ this,
+ hresult));
+
+ // the Poke calls frees the Poke data even in case of failure.
+#ifdef LATER
+
+ if (hresult = m_pDdeObject->Execute (m_pDdeObject->m_pDocChannel,
+ wNewHandle ((LPSTR)achStdCloseDocument,sizeof(achStdCloseDocument)));
+ goto errDoc;
+#elseif
+ goto errDoc;
+#endif
+ }
+
+ hresult = m_pDdeObject->TermConv (m_pDdeObject->m_pSysChannel);
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Load(%x) TermConv on SysChannel failed(%x)\n",
+ this,
+ hresult));
+ goto errRtn;
+ }
+
+
+ if (m_pDdeObject->m_pstg)
+ {
+ m_pDdeObject->m_pstg->Release();
+ }
+
+ m_pDdeObject->m_pstg = pstg;
+ pstg->AddRef();
+ goto LExit;
+
+errRtn:
+ if (hDdePoke)
+ GlobalFree (hDdePoke);
+ if (m_pDdeObject->m_pDocChannel)
+ m_pDdeObject->TermConv (m_pDdeObject->m_pDocChannel);
+LExit:
+ StmReadItem.Release();
+ StmRead.Release();
+
+ intrDebugOut((DEB_ITRACE,"::Load(%x) returning (%x)\n",this,hresult));
+ return hresult;
+}
+
+
+#pragma SEG(CDdeObject_CPersistStgImpl_Save)
+STDMETHODIMP NC(CDdeObject,CPersistStgImpl)::Save
+ (IStorage FAR* pstgSave, BOOL fSameAsLoad)
+{
+ intrDebugOut((DEB_ITRACE,
+ "DdeObject::Save(%x,pstgSave=%x)\n",
+ this,
+ pstgSave));
+
+
+ HRESULT hresult=NOERROR;
+
+ if (m_pDdeObject->m_fUpdateOnSave
+ && (m_pDdeObject->m_clsid != CLSID_Package
+ || m_pDdeObject->m_hNative == NULL))
+ {
+ // Get latest data from server, if it is not shutting down
+ // or telling us to Save, in which case it just gave us data.
+ // (If it is shutting down, it probably won't respond.
+ // Draw does respond, but gives bad data.)
+ // Packager gives truncated native data (header info with no
+ // actual embedded file) if you DDE_REQUEST it. Bug 3103
+ m_pDdeObject->Update (FALSE);
+ }
+
+ if (m_pDdeObject->m_hNative == NULL)
+ {
+ // we still have nothing to save
+ return ResultFromScode (E_BLANK);
+ }
+
+ hresult = m_pDdeObject->Save (pstgSave);
+
+ Puts ("PersistStg::Save done\n");
+ return hresult;
+}
+
+
+#pragma SEG(CDdeObject_CPersistStgImpl_SaveCompleted)
+STDMETHODIMP NC(CDdeObject,CPersistStgImpl)::SaveCompleted
+ (IStorage FAR* pstgNew)
+{
+ intrDebugOut((DEB_ITRACE,
+ "DdeObejct::SaveCompleted(%x,pstgNew=%x)\n",
+ this,
+ pstgNew));
+
+ RetZ (m_pDdeObject->m_pOleAdvHolder);
+ m_pDdeObject->m_pOleAdvHolder->SendOnSave();
+ if (pstgNew)
+ {
+ if (m_pDdeObject->m_pstg)
+ m_pDdeObject->m_pstg->Release();
+ m_pDdeObject->m_pstg = pstgNew;
+ pstgNew->AddRef();
+ }
+ return NOERROR;
+}
+
+
+#pragma SEG(CDdeObject_CPersistStgImpl_HandsOffStorage)
+STDMETHODIMP NC(CDdeObject,CPersistStgImpl)::HandsOffStorage(void)
+{
+ intrDebugOut((DEB_ITRACE,"DdeObejct::HandsOffStorage(%x)\n",this));
+ if (m_pDdeObject->m_pstg)
+ {
+ m_pDdeObject->m_pstg->Release();
+ m_pDdeObject->m_pstg = NULL;
+ }
+ return NOERROR;
+}
+
+
+/*
+ * IMPLEMENTATION of CProxyManagerImpl methods
+ *
+ */
+
+
+STDUNKIMPL_FORDERIVED(DdeObject, ProxyManagerImpl)
+
+
+
+#pragma SEG(CDdeObject_CProxyManagerImpl_CreateServer)
+STDMETHODIMP NC(CDdeObject, CProxyManagerImpl)::CreateServer(REFCLSID rclsid,
+ DWORD clsctx,
+ void *pv)
+{
+ intrDebugOut((DEB_ITRACE,"DdeObejct::CreateServer(%x)\n",this));
+ HRESULT hresult = NOERROR;
+
+ if (m_pDdeObject->m_pSysChannel)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::CreateServer(%x)m_pSysChannel exists\n",
+ this));
+ return NOERROR;
+ }
+
+ if (m_pDdeObject->m_aExeName == NULL)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::CreateServer(%x) Class Not Registered\n",
+ this));
+ return(REGDB_E_CLASSNOTREG);
+ }
+
+
+ if (!m_pDdeObject->AllocDdeChannel(&m_pDdeObject->m_pSysChannel,SYS_CLASSA))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::CreateServer(%x)AllocDdeChannel is failing\n",
+ this));
+ return ReportResult(0, E_OUTOFMEMORY,0,0);
+ }
+
+ if (!m_pDdeObject->InitSysConv())
+ {
+ if (!(m_pDdeObject->LaunchApp()))
+ {
+ intrDebugOut((DEB_IERROR,"::CreateServer Could not launch app\n"));
+ hresult = ResultFromScode (CO_E_APPNOTFOUND);
+ goto errRtn;
+ }
+
+ if (!m_pDdeObject->InitSysConv())
+ {
+ intrDebugOut((DEB_IERROR,"::CreateServer Second init failed\n"));
+ hresult = ResultFromScode (CO_E_APPDIDNTREG);
+ goto errRtn;
+ }
+ }
+
+ return NOERROR;
+
+errRtn:
+ intrDebugOut((DEB_ITRACE,"DdeObejct::CreateServer(%x) is failing(%x)\n",this,hresult));
+ m_pDdeObject->DeleteChannel (m_pDdeObject->m_pSysChannel);
+ Assert (hresult != NOERROR); // This is an error path
+ return hresult;
+
+}
+
+
+#pragma SEG(CDdeObject_CProxyManagerImpl_Connect)
+STDMETHODIMP NC(CDdeObject, CProxyManagerImpl)::Connect(OID oid, REFCLSID rclsid)
+{
+ intrDebugOut((DEB_ITRACE,"DdeObject::Connect(%x)\n",this));
+
+ if (m_pDdeObject->m_pDocChannel)
+ return NOERROR;
+
+ if (!m_pDdeObject->AllocDdeChannel (&m_pDdeObject->m_pDocChannel,CLIENT_CLASSA))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "::Connect(%x) AllocDdeChannel failed, return E_OUTOFMEMORY\n",
+ this));
+ return ReportResult(0, E_OUTOFMEMORY,0,0);
+ }
+
+ // Bug 3701
+ m_pDdeObject->m_fDidSendOnClose = FALSE;
+ if (wInitiate (m_pDdeObject->m_pDocChannel, m_pDdeObject->m_aClass,
+ m_pDdeObject->m_aTopic))
+ {
+ return NOERROR;
+ }
+
+ intrDebugOut((DEB_ITRACE,"::Connect(%x) wInitiate failed\n",this));
+ m_pDdeObject->DeleteChannel (m_pDdeObject->m_pDocChannel);
+ return ResultFromScode (E_FAIL);
+}
+
+
+#pragma SEG(CDdeObject_CProxyManagerImpl_LockConnection)
+STDMETHODIMP NC(CDdeObject, CProxyManagerImpl)::LockConnection(BOOL fLock, BOOL fLastUnlockReleases)
+{
+ intrDebugOut((DEB_ITRACE,
+ "DdeObject::LockConnection(%x,fLock=%x,fLastUnlockReleases=%x)\n",
+ this,
+ fLock,
+ fLastUnlockReleases));
+
+ if (fLock)
+ m_pDdeObject->m_cLocks++;
+ else
+ {
+ if (m_pDdeObject->m_cLocks!=0 && 0 == --m_pDdeObject->m_cLocks &&
+ fLastUnlockReleases && !m_pDdeObject->m_fVisible)
+ (void)m_pDdeObject->m_Ole.Close (OLECLOSE_SAVEIFDIRTY);
+ }
+ return NOERROR;
+}
+
+
+#ifdef NOTNEEDED
+#pragma SEG(CDdeObject_CProxyManagerImpl_GetClassID)
+STDMETHODIMP_(void) NC(CDdeObject, CProxyManagerImpl)::GetClassID(CLSID FAR* pClsid)
+{
+ *pClsid = m_pDdeObject->m_clsid;
+}
+
+
+#pragma SEG(CDdeObject_CProxyManagerImpl_GetOID)
+STDMETHODIMP_(OID) NC(CDdeObject, CProxyManagerImpl)::GetOID()
+{
+ if (m_pDdeObject->m_pSysChannel)
+ return (OID) m_pDdeObject->m_pSysChannel;
+
+ if (m_pDdeObject->m_pDocChannel)
+ return (OID) m_pDdeObject->m_pDocChannel;
+
+ return NULL;
+}
+#endif
+
+#pragma SEG(CDdeObject_CProxyManagerImpl_IsConnected)
+STDMETHODIMP_(BOOL) NC(CDdeObject, CProxyManagerImpl)::IsConnected(void)
+{
+ return m_pDdeObject->m_pDocChannel != NULL;
+}
+
+
+#pragma SEG(CDdeObject_CProxyManagerImpl_EstablishIID)
+STDMETHODIMP NC(CDdeObject, CProxyManagerImpl)::EstablishIID(REFIID iid, LPVOID FAR* ppv)
+{
+ // REVIEW: this is correct, but can we be smarter like in the real PM?
+ return QueryInterface(iid, ppv);
+}
+
+
+#pragma SEG(wTerminateIsComing)
+INTERNAL_(BOOL) wTerminateIsComing (LPDDE_CHANNEL pChannel)
+{
+ MSG msg;
+ return SSPeekMessage (&msg, pChannel->hwndCli, 0, 0, PM_NOREMOVE)
+ && msg.message == WM_DDE_TERMINATE
+ && (HWND)msg.wParam==pChannel->hwndSvr;
+}
+
+
+#pragma SEG(CDdeObject_CProxyManagerImpl_Disconnect)
+STDMETHODIMP_(void) NC(CDdeObject, CProxyManagerImpl)::Disconnect()
+{
+ intrDebugOut((DEB_ITRACE,"DdeObject::Disonnect(%x)\n",this));
+ #define p m_pDdeObject
+ if (m_pDdeObject->m_pDocChannel)
+ {
+ BOOL fTermComing = wTerminateIsComing (m_pDdeObject->m_pDocChannel);
+ if ((!m_pDdeObject->m_fNoStdCloseDoc
+ || (!m_pDdeObject->m_fWasEverVisible // invisible update or
+ && !m_pDdeObject->m_fDidGetObject // link from file case.
+ && m_pDdeObject->m_fDidStdOpenDoc)) // only do StdClose if did StdOpen
+ && !m_pDdeObject->m_fDidStdCloseDoc
+ && !fTermComing)
+ {
+ m_pDdeObject->Execute (m_pDdeObject->m_pDocChannel,
+ wNewHandle ((LPSTR)&achStdCloseDocument,sizeof(achStdCloseDocument)),
+ /*fStdClose*/TRUE,
+ /*fWait*/TRUE,
+ /*fDetectTerminate*/TRUE);
+
+ m_pDdeObject->m_fDidStdCloseDoc = TRUE;
+ }
+ if (!m_pDdeObject->m_fDidSendOnClose /*|| fTermComing*/)
+ {
+ // if we did not call SendOnClose() then Disconnect() was called
+ // by a Release method, not by SendOnClose().
+ // This happens when user deletes object in container.
+ BOOL fVisible = m_pDdeObject->m_fWasEverVisible; // TermConv clears this flag
+ m_pDdeObject->TermConv (m_pDdeObject->m_pDocChannel);
+ if (!fVisible)
+ m_pDdeObject->MaybeUnlaunchApp();
+ }
+ }
+
+ if (m_pDdeObject->m_pSysChannel)
+ {
+ intrDebugOut((DEB_IWARN,"Terminating system conversation in Disconnect()\n"));
+ // This should never happen, I think.
+ m_pDdeObject->TermConv (m_pDdeObject->m_pSysChannel);
+ }
+ #undef p
+}
+
+//
+// There is no ServerHandler with DDE servers. Therefore, this function returns E_NOTIMPL
+// back to the handler.
+//
+STDMETHODIMP NC(CDdeObject, CProxyManagerImpl)::CreateServerWithHandler (REFCLSID rclsid, DWORD clsctx, void *pv,
+ REFCLSID rclsidHandler, IID iidSrv, void **ppv,
+ IID iidClnt, void *pClientSiteInterface)
+{
+ return E_NOTIMPL;
+}
+
+
diff --git a/private/ole32/com/remote/dde/client/ddewnd.cxx b/private/ole32/com/remote/dde/client/ddewnd.cxx
new file mode 100644
index 000000000..a3a6725a0
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/ddewnd.cxx
@@ -0,0 +1,363 @@
+/*++
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddewnd.cpp
+
+Abstract:
+
+ This module contains the code for the dde window procs
+
+Author:
+
+ Srini Koppolu (srinik) 20-June-1992
+
+Revision History:
+
+--*/
+#include "ddeproxy.h"
+
+
+
+#define SYS_MSG 0
+#define DOC_MSG 1
+
+// SysWndProc: Window Procedure for System Topic DDE conversations
+// wndproc for system topic
+
+
+STDAPI_(LRESULT) SysWndProc (
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+)
+{
+ StackAssert(SSOnSmallStack());
+ CDdeObject FAR* pDdeObj = NULL;
+ LPDDE_CHANNEL pChannel = NULL;
+
+ if (message>=WM_DDE_FIRST && message <= WM_DDE_LAST)
+ {
+ if (pDdeObj = (CDdeObject FAR*) GetWindowLong (hwnd, 0))
+ {
+ pChannel = pDdeObj->GetSysChannel();
+ }
+
+ if (pChannel == NULL)
+ {
+ intrAssert(pChannel != NULL);
+ return SSDefWindowProc (hwnd, message, wParam, lParam);
+ }
+ }
+ if ( pChannel
+ && ( pChannel->iAwaitAck == AA_EXECUTE
+ || pChannel->iAwaitAck == AA_INITIATE) )
+ {
+ MSG msg;
+ BOOL fDisp = FALSE;
+ while (SSPeekMessage(&msg, hwnd, WM_DDE_ACK, WM_DDE_ACK, PM_REMOVE | PM_NOYIELD) )
+ {
+ intrDebugOut((DEB_WARN, "DDE SysWndProc: dispatching WM_DDE_ACK message (%x)\n",pChannel));
+ SSDispatchMessage(&msg);
+ fDisp = TRUE;
+ }
+ if (fDisp && (pDdeObj = (CDdeObject FAR*) GetWindowLong (hwnd, 0)))
+ {
+ pChannel = pDdeObj->GetSysChannel();
+ }
+
+ if (pChannel == NULL)
+ {
+ intrAssert(pChannel != NULL);
+ return SSDefWindowProc (hwnd, message, wParam, lParam);
+ }
+ }
+
+ switch (message){
+ case WM_DDE_ACK:
+ intrDebugOut((DEB_ITRACE,
+ "SWP: WM_DDE_ACK pChannel(%x)\n",pChannel));
+ if (pChannel->bTerminating)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "SWP: pChannel->bTerminating: no action\n"));
+
+ break;
+ }
+
+ switch (pChannel->iAwaitAck) {
+ case AA_INITIATE:
+ pDdeObj->OnInitAck (pChannel, (HWND)wParam);
+ if (LOWORD(lParam))
+ GlobalDeleteAtom (LOWORD(lParam));
+ if (HIWORD(lParam))
+ GlobalDeleteAtom (HIWORD(lParam));
+ break;
+
+ case AA_EXECUTE:
+ pDdeObj->OnAck (pChannel, lParam);
+ break;
+
+ default:
+ intrDebugOut((DEB_ITRACE,
+ "SWP: WM_DDE_ACK UnhandledpChannel(%x)\n",pChannel));
+ break;
+ }
+ break;
+
+ case WM_TIMER:
+ pDdeObj->OnTimer (pChannel);
+ break;
+
+ case WM_DDE_TERMINATE:
+ intrDebugOut((DEB_ITRACE,
+ "SWP: WM_DDE_TERMINATE pChannel(%x)\n",pChannel));
+ pDdeObj->OnTerminate (pChannel, (HWND)wParam);
+ break;
+
+ default:
+ return SSDefWindowProc (hwnd, message, wParam, lParam);
+ }
+
+ return 0L;
+}
+
+
+// ClientDocWndProc: Window procedure used to document DDE conversations
+STDAPI_(LRESULT) ClientDocWndProc (
+ HWND hwnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+)
+{
+ StackAssert(SSOnSmallStack());
+ CDdeObject FAR* pDdeObj = NULL;
+ LPDDE_CHANNEL pChannel = NULL;
+ HANDLE hData;
+ ATOM aItem;
+
+ if (message>=WM_DDE_FIRST && message <= WM_DDE_LAST)
+ {
+
+ if (pDdeObj = (CDdeObject FAR*) GetWindowLong (hwnd, 0))
+ pChannel = pDdeObj->GetDocChannel();
+
+ if (pChannel == NULL)
+ {
+ //
+ // pChannel == NULL. Something is very wrong! But, lets
+ // not fault on it.
+ //
+ //intrAssert(pChannel != NULL);
+ return SSDefWindowProc (hwnd, message, wParam, lParam);
+ }
+
+ }
+ if ( pChannel
+ && ( pChannel->iAwaitAck == AA_EXECUTE
+ || pChannel->iAwaitAck == AA_INITIATE
+ || pChannel->iAwaitAck == AA_REQUESTAVAILABLE
+ || pChannel->iAwaitAck == AA_REQUEST
+ || pChannel->iAwaitAck == AA_UNADVISE
+ || pChannel->iAwaitAck == AA_EXECUTE
+ || pChannel->iAwaitAck == AA_ADVISE
+ || pChannel->iAwaitAck == AA_POKE) )
+ {
+ MSG msg;
+ BOOL fDisp = FALSE;
+ while (SSPeekMessage(&msg, hwnd, WM_DDE_ACK, WM_DDE_ACK, PM_REMOVE | PM_NOYIELD) )
+ {
+ intrDebugOut((DEB_WARN, "DDE DocWndProc: dispatching WM_DDE_ACK message (%x)\n",pChannel));
+ SSDispatchMessage(&msg);
+ fDisp = TRUE;
+ }
+
+ if (fDisp && (pDdeObj = (CDdeObject FAR*) GetWindowLong (hwnd, 0)))
+ {
+ pChannel = pDdeObj->GetDocChannel();
+ }
+
+ if (pChannel == NULL)
+ {
+ intrAssert(pChannel != NULL);
+ return SSDefWindowProc (hwnd, message, wParam, lParam);
+ }
+ }
+
+ switch (message)
+ {
+ case WM_DDE_ACK:
+
+ intrDebugOut((DEB_ITRACE,
+ "ClientWndProc: WM_DDE_ACK pChannel(%x)\n",
+ pChannel));
+ if (pChannel->bTerminating){
+ // ### this error recovery may not be correct.
+ DEBUG_OUT ("No action due to termination process",0)
+ break;
+ }
+
+ switch(pChannel->iAwaitAck){
+ case AA_INITIATE:
+ pDdeObj->OnInitAck (pChannel, (HWND)wParam);
+ if (LOWORD(lParam))
+ GlobalDeleteAtom (LOWORD(lParam));
+ if (HIWORD(lParam))
+ GlobalDeleteAtom (HIWORD(lParam));
+ break;
+
+ case AA_REQUESTAVAILABLE:
+ case AA_REQUEST:
+ case AA_UNADVISE:
+ case AA_EXECUTE:
+ case AA_ADVISE:
+ pDdeObj->OnAck (pChannel, lParam);
+ break;
+
+ case AA_POKE:
+ // freeing pokedata is done in handleack
+ pDdeObj->OnAck (pChannel, lParam);
+ break;
+
+ default:
+ intrDebugOut((DEB_IERROR,
+ "ClientWndProc: WM_DDE_ACK unhandled\n"));
+ break;
+
+ } // end of switch
+ break;
+
+ case WM_DDE_DATA:
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ pDdeObj->Guard();
+#endif // _CHICAGO_
+ hData = GET_WM_DDE_DATA_HDATA(wParam,lParam);
+ aItem = GET_WM_DDE_DATA_ITEM(wParam,lParam);
+ intrDebugOut((DEB_ITRACE,
+ "CWP: WM_DDE_DATA pChannel(%x) hData(%x) aItem(%x)\n",
+ pChannel,hData,aItem));
+ pDdeObj->OnData (pChannel, hData, aItem);
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ if (pDdeObj->UnGuard())
+ {
+ SetWindowLong(hwnd, 0, (LONG)0);
+ intrDebugOut((DEB_IWARN, "DDE ClientDocWndProc Release on pUnkOuter == 0 (this:%x, hwnd:%x\n",pDdeObj, hwnd ));
+ }
+#endif // _CHICAGO_
+
+ break;
+
+ case WM_DDE_TERMINATE:
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ pDdeObj->Guard();
+#endif // _CHICAGO_
+ intrDebugOut((DEB_ITRACE,
+ "CWP: WM_DDE_TERMINATE pChannel(%x)\n",pChannel));
+
+
+ if (pDdeObj->m_fDoingSendOnDataChange)
+ {
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ BOOL fPostMsg = TRUE;
+#endif
+ //
+ // Cheese alert! This protocol is very bad. The original
+ // 16 bit code something even more worse, so we are stuck
+ // to do something roughly compatible.
+ //
+ // If fDoingSendOnDataChange, the client may be asking for
+ // additional information from the server. The way the code
+ // is structured, it doesn't handle OnTerminate gracefully
+ // in this case.
+ //
+ // To fix this, we first tell the call control that
+ // the server has died. Then we repost the terminate
+ // message so we can handle it later.
+ //
+ // The old code did a
+ // pDdeObj->QueueMsg (hwnd, message, wParam, lParam);
+ //
+ // and the old SendOnDataChange removed the message.
+ // This probably didn't work either, but was never
+ // actually encountered.
+ //
+
+ intrDebugOut((DEB_ITRACE,
+ "CWP: term doing SendOnDataChange \n"));
+ //
+ // If we got here, there should be a CallData assigned
+ // to the channel.
+ //
+ if ((pChannel->pCD) && (pChannel->pCallCont))
+ {
+ intrDebugOut((DEB_ITRACE,"CWP: Setting call state\n"));
+
+ pChannel->pCallCont->SetCallState(pChannel->pCD,
+ SERVERCALLEX_ISHANDLED,
+ RPC_E_SERVER_DIED);
+
+ }
+ else
+ {
+ //
+ // If there is no call data, then we aren't waiting in
+ // the channel. Terminate the conversation.
+ //
+
+ intrDebugOut((DEB_ERROR,"CWP: No call state exists\n"));
+ pDdeObj->OnTerminate (pChannel, (HWND)wParam);
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ fPostMsg = FALSE;
+#else
+ break;
+#endif //
+ }
+
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ if (fPostMsg)
+ {
+#endif
+ //
+ // Repost the message and try again.
+ //
+ intrDebugOut((DEB_ITRACE,"CWP: Reposting WM_DDE_TERMINATE\n"));
+ PostMessage(hwnd,message,wParam,lParam);
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ }
+#else
+ break;
+#endif
+
+ }
+ else
+ {
+ pDdeObj->OnTerminate (pChannel, (HWND)wParam);
+ }
+#ifdef _CHICAGO_
+ //Note:POSTPPC
+ if (pDdeObj->UnGuard())
+ {
+ SetWindowLong(hwnd, 0, (LONG)0);
+ intrDebugOut((DEB_IWARN, "DDE ClientDocWndProc Release on pUnkOuter == 0 (this:%x, hwnd:%x\n",pDdeObj, hwnd ));
+ }
+#endif // _CHICAGO_
+ break;
+
+ default:
+ return SSDefWindowProc (hwnd, message, wParam, lParam);
+
+ }
+
+ return 0L;
+}
diff --git a/private/ole32/com/remote/dde/client/ddeworkr.cxx b/private/ole32/com/remote/dde/client/ddeworkr.cxx
new file mode 100644
index 000000000..9d117db18
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/ddeworkr.cxx
@@ -0,0 +1,1331 @@
+/*++
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddeworkr.cpp
+
+Abstract:
+
+ This module contains the code for the worker routines
+
+Author:
+
+ Srini Koppolu (srinik) 22-June-1992
+ Jason Fuller (jasonful) 24-July-1992
+
+Revision History:
+ Kevin Ross (KevinRo) 10-May-1994
+ Mostly added comments, and attempted to clean
+ it up.
+
+--*/
+#include "ddeproxy.h"
+
+ASSERTDATA
+
+/*
+ * WORKER ROUTINES
+ *
+ */
+
+
+INTERNAL_(BOOL) wPostMessageToServer(LPDDE_CHANNEL pChannel,
+ WORD wMsg,
+ LONG lParam,
+ BOOL fFreeOnError)
+{
+ int c=0;
+ intrDebugOut((DEB_ITRACE,
+ "wPostMessageToServer(pChannel=%x,wMsg=%x,lParam=%x,fFreeOnError=%x\n",
+ pChannel,
+ wMsg,
+ lParam,
+ fFreeOnError));
+ if (NULL==pChannel)
+ {
+ AssertSz (0, "Channel missing");
+ return FALSE;
+ }
+ pChannel->wMsg = wMsg;
+ pChannel->lParam = lParam;
+ pChannel->hres = NOERROR;
+
+ while (TRUE && c<10 )
+ {
+ if (!IsWindow (pChannel->hwndSvr))
+ {
+ intrDebugOut((DEB_IWARN,
+ "wPostMessageToServer: invalid window %x\n",
+ pChannel->hwndSvr));
+ goto errRet;
+ }
+ if (wTerminateIsComing (pChannel)
+ && wMsg != WM_DDE_ACK
+ && wMsg != WM_DDE_TERMINATE)
+ {
+ intrDebugOut((DEB_IWARN,"Server sent terminate, cannot post\n"));
+ goto errRet;
+ }
+ if (!PostMessage (pChannel->hwndSvr, wMsg, (WPARAM) pChannel->hwndCli, lParam))
+ {
+ intrDebugOut((DEB_IWARN,
+ "wPostMessageToServer: PostMessageFailed, yielding\n"));
+ Yield ();
+ c++;
+ }
+ else
+ return TRUE;
+ }
+ AssertSz (0, "PostMessage failed");
+
+errRet:
+ intrDebugOut((DEB_IWARN,"wPostMessageToServer returns FALSE\n"));
+ if (fFreeOnError)
+ {
+ DDEFREE(wMsg,lParam);
+ }
+
+ return FALSE;
+}
+
+
+// call Ole1ClassFromCLSID then global add atom; returns NULL if error.
+INTERNAL_(ATOM) wAtomFromCLSID(REFCLSID rclsid)
+{
+ WCHAR szClass[MAX_STR];
+ ATOM aCls;
+
+ if (Ole1ClassFromCLSID2(rclsid, szClass, sizeof(szClass)) == 0)
+ return NULL;
+ aCls = wGlobalAddAtom(szClass);
+ intrAssert(wIsValidAtom(aCls));
+ return aCls;
+}
+
+INTERNAL_(ATOM) wGlobalAddAtom(LPCOLESTR sz)
+{
+ if (sz==NULL || sz[0] == '\0')
+ {
+ return NULL;
+ }
+
+ ATOM a = GlobalAddAtom(sz);
+ intrAssert(wIsValidAtom(a));
+ return a;
+}
+
+INTERNAL_(ATOM) wGlobalAddAtomA(LPCSTR sz)
+{
+ if (sz==NULL || sz[0] == '\0')
+ return NULL;
+ ATOM a = GlobalAddAtomA(sz);
+ intrAssert(wIsValidAtom(a));
+ return a;
+}
+
+
+INTERNAL_(ATOM) wGetExeNameAtom (REFCLSID rclsid)
+{
+ LONG cb = MAX_STR;
+ WCHAR key[MAX_STR];
+ ATOM a;
+
+ if (Ole1ClassFromCLSID2(rclsid, key, sizeof(key)) == 0)
+ return NULL;
+
+ lstrcatW (key, OLESTR("\\protocol\\StdFileEditing\\server"));
+
+ if (RegQueryValue (HKEY_CLASSES_ROOT, key, key, &cb))
+ {
+ Puts ("ERROR: wGetExeNameAtom failed\n");
+ return NULL;
+ }
+ a = wGlobalAddAtom (key);
+ intrAssert(wIsValidAtom(a));
+ return a;
+}
+
+INTERNAL_(void) wFreeData (HANDLE hData, CLIPFORMAT cfFormat,
+ BOOL fFreeNonGdiHandle)
+{
+ intrDebugOut((DEB_ITRACE,
+ "wFreeData(hData=%x,cfFormat=%x,FreeNonGDIHandle=%x\n",
+ hData,
+ (USHORT)cfFormat,
+ fFreeNonGdiHandle));
+
+ AssertSz (hData != NULL, "Trying to free NULL handle");
+ AssertSz (hData != (HANDLE) 0xcccccccc, "Trying to free handle from a deleted object");
+
+ switch (cfFormat) {
+ case CF_METAFILEPICT:
+ LPMETAFILEPICT lpMfp;
+
+ if (lpMfp = (LPMETAFILEPICT) GlobalLock (hData))
+ {
+ intrDebugOut((DEB_ITRACE,
+ "wFreeData freeing metafile %x\n",
+ lpMfp->hMF));
+
+ OleDdeDeleteMetaFile(lpMfp->hMF);
+ GlobalUnlock (hData);
+ }
+ GlobalFree (hData);
+ break;
+
+ case CF_BITMAP:
+ case CF_PALETTE:
+ Verify(DeleteObject (hData));
+ break;
+
+ case CF_DIB:
+ GlobalFree (hData);
+ break;
+
+ default:
+ if (fFreeNonGdiHandle)
+ GlobalFree (hData);
+ break;
+ }
+}
+
+
+
+INTERNAL_(BOOL) wInitiate (LPDDE_CHANNEL pChannel, ATOM aLow, ATOM aHigh)
+{
+ intrDebugOut((DEB_ITRACE,"wInitiate(pChannel=%x,aLow=%x,aHigh=%x)\n",
+ pChannel, aLow, aHigh));
+
+ intrAssert(wIsValidAtom(aLow));
+ if (aLow == (ATOM)0)
+ {
+ intrDebugOut((DEB_IERROR,"wInitiate Failed, aLow == 0\n"));
+ return FALSE;
+ }
+
+ pChannel->iAwaitAck = AA_INITIATE;
+
+ SSSendMessage ((HWND)-1, WM_DDE_INITIATE, (WPARAM) pChannel->hwndCli,
+ MAKE_DDE_LPARAM (WM_DDE_INITIATE, aLow, aHigh));
+
+ pChannel->iAwaitAck = NULL;
+
+ intrDebugOut((DEB_ITRACE,
+ "wInitiate pChannel->hwndSrvr = %x\n",
+ pChannel->hwndSvr));
+
+ return (pChannel->hwndSvr != NULL);
+}
+
+
+
+INTERNAL_(HRESULT) wScanItemOptions (ATOM aItem, int FAR* lpoptions)
+{
+ ATOM aModifier;
+ LPOLESTR lpbuf;
+ WCHAR buf[MAX_STR];
+
+ *lpoptions = ON_CHANGE; // default
+
+ if (!aItem) {
+ // NULL item with no modifier means ON_CHANGE for NULL item
+ return NOERROR;
+ }
+
+ intrAssert(wIsValidAtom(aItem));
+ GlobalGetAtomName (aItem, buf, MAX_STR);
+ lpbuf = buf;
+
+ while ( *lpbuf && *lpbuf != '/')
+ IncLpch (lpbuf);
+
+ // no modifier same as /change
+
+ if (*lpbuf == NULL)
+ return NOERROR;
+
+ *lpbuf++ = NULL; // seperate out the item string
+ // We are using this in the caller.
+
+ if (!(aModifier = GlobalFindAtom (lpbuf)))
+ {
+ Puts ("ERROR: wScanItemOptions found non-atom modifier\n");
+ return ReportResult(0, RPC_E_DDE_SYNTAX_ITEM, 0, 0);
+ }
+
+ intrAssert(wIsValidAtom(aModifier));
+
+ if (aModifier == aChange)
+ return NOERROR;
+
+ // Is it a save?
+ if (aModifier == aSave){
+ *lpoptions = ON_SAVE;
+ return NOERROR;
+ }
+ // Is it a Close?
+ if (aModifier == aClose){
+ *lpoptions = ON_CLOSE;
+ return NOERROR;
+ }
+
+ // unknown modifier
+ Puts ("ERROR: wScanItemOptions found bad modifier\n");
+ return ReportResult(0, RPC_E_DDE_SYNTAX_ITEM, 0, 0);
+}
+
+
+INTERNAL_(BOOL) wClearWaitState (LPDDE_CHANNEL pChannel)
+{
+ Assert (pChannel);
+ // kill if any timer active.
+ if (pChannel->wTimer) {
+ KillTimer (pChannel->hwndCli, 1);
+ pChannel->wTimer = 0;
+
+ if (pChannel->hDdePoke) {
+ GlobalFree (pChannel->hDdePoke);
+ pChannel->hDdePoke = NULL;
+ }
+
+ if (pChannel->hopt) {
+ GlobalFree (pChannel->hopt);
+ pChannel->hopt = NULL;
+ }
+
+ //
+ // If the channel is waiting on an Ack, and there is an
+ // lParam, then we may need to cleanup the data.
+
+ if (pChannel->iAwaitAck && (pChannel->lParam)) {
+ if (pChannel->iAwaitAck == AA_EXECUTE)
+ {
+ //
+ // KevinRo: Found the following comment in the code.
+ // ; // BUGBUG32 - get hData from GET_WM_DDE_EXECUTE_HADATA ??
+ // It appears, by looking at what the 16-bit code does,
+ // that the goal is to free the handle that was passed as
+ // part of the EXECUTE message. Judging by what the 16-bit
+ // code did, I have determined that this is correct.
+ //
+ // The macro used below wanted two parameters. The first was
+ // the WPARAM, the second the LPARAM. We don't have the WPARAM.
+ // However, it isn't actually used by the macro, so I have
+ // cheated and provided 0 as a default
+ //
+ GlobalFree(GET_WM_DDE_EXECUTE_HDATA(0,pChannel->lParam));
+
+#ifdef KEVINRO_HERE_IS_THE_16_BIT_CODE
+ GlobalFree (HIWORD (pChannel->lParam));
+#endif
+ }
+ else
+ {
+ //
+ // All of the other DDE messages pass an Atom in the high word.
+ // Therefore, we should delete the atom.
+ //
+ //
+ ATOM aTmp;
+
+ aTmp = MGetDDElParamHi(pChannel->wMsg,pChannel->lParam);
+
+ intrAssert(wIsValidAtom(aTmp));
+ if (aTmp)
+ {
+ GlobalDeleteAtom (aTmp);
+ }
+ }
+ DDEFREE(pChannel->wMsg,pChannel->lParam);
+
+ // we want to wipe out the lParam
+ pChannel->lParam = 0x0;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+// wNewHandle (LPSTR, DWORD)
+//
+// Copy cb bytes from lpstr into a new memory block and return a handle to it.
+// If lpstr is an ASCIIZ string, cb must include 1 for the null terminator.
+//
+
+INTERNAL_(HANDLE) wNewHandle (LPSTR lpstr, DWORD cb)
+{
+
+ HANDLE hdata = NULL;
+ LPSTR lpdata = NULL;
+
+ hdata = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, cb);
+ if (hdata == NULL || (lpdata = (LPSTR) GlobalLock (hdata)) == NULL)
+ goto errRtn;
+
+ memcpy (lpdata, lpstr, cb);
+ GlobalUnlock (hdata);
+ return hdata;
+
+errRtn:
+ Puts ("ERROR: wNewHandle\n");
+ Assert (0);
+ if (lpdata)
+ GlobalUnlock (hdata);
+
+ if (hdata)
+ GlobalFree (hdata);
+ return NULL;
+}
+
+
+
+// wDupData
+//
+// Copy data from handle h into a new handle which is returned as *ph.
+//
+
+INTERNAL wDupData (LPHANDLE ph, HANDLE h, CLIPFORMAT cf)
+{
+ Assert (ph);
+ RetZ (wIsValidHandle(h, cf));
+ *ph = OleDuplicateData (h, cf, GMEM_DDESHARE | GMEM_MOVEABLE);
+ RetZ (wIsValidHandle (*ph, cf));
+ return NOERROR;
+}
+
+
+// wTransferHandle
+//
+//
+INTERNAL wTransferHandle
+ (LPHANDLE phDst,
+ LPHANDLE phSrc,
+ CLIPFORMAT cf)
+{
+ RetErr (wDupData (phDst, *phSrc, cf));
+ wFreeData (*phSrc, cf, TRUE);
+ *phSrc = (HANDLE)0;
+ return NOERROR;
+}
+
+
+// wHandleCopy
+//
+// copy data from hSrc to hDst.
+// Both handles must already have memory allocated to them.
+//
+
+INTERNAL wHandleCopy (HANDLE hDst, HANDLE hSrc)
+{
+ LPSTR lpDst, lpSrc;
+ DWORD dwSrc;
+
+ if (NULL==hDst || NULL==hSrc)
+ return ResultFromScode (E_INVALIDARG);
+ if (GlobalSize(hDst) < (dwSrc=GlobalSize(hSrc)))
+ {
+ HANDLE hDstNew = GlobalReAlloc (hDst, dwSrc, GMEM_DDESHARE | GMEM_MOVEABLE);
+ if (hDstNew != hDst)
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+ if (!(lpDst = (LPSTR) GlobalLock(hDst)))
+ {
+ intrAssert(!"ERROR: wHandleCopy hDst");
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ if (!(lpSrc = (LPSTR) GlobalLock(hSrc)))
+ {
+ GlobalUnlock(hDst);
+ intrAssert (!"ERROR: wHandleCopy hSrc");
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ memcpy (lpDst, lpSrc, dwSrc);
+ GlobalUnlock(hDst);
+ GlobalUnlock(hSrc);
+ return NOERROR;
+}
+
+
+// ExtendAtom: Create a new atom, which is the old one plus extension
+
+INTERNAL_(ATOM) wExtendAtom (ATOM aItem, int iAdvOn)
+{
+ WCHAR buffer[MAX_STR+1];
+ LPOLESTR lpext;
+
+ buffer[0] = 0;
+ // aItem==NULL for embedded objects.
+ // If so, there is no item name before the slash.
+ if (aItem)
+ GlobalGetAtomName (aItem, buffer, MAX_STR);
+
+ switch (iAdvOn) {
+ case ON_CHANGE:
+ lpext = OLESTR("");
+ break;
+
+ case ON_SAVE:
+ lpext = OLESTR("/Save");
+ break;
+
+ case ON_CLOSE:
+ lpext = OLESTR("/Close");
+ break;
+
+ default:
+ AssertSz (FALSE, "Unknown Advise option");
+ break;
+
+ }
+
+ lstrcatW (buffer, lpext);
+ if (buffer[0])
+ return wGlobalAddAtom (buffer);
+ else
+ return NULL;
+ // not an error. For embedded object on-change, aItem==NULL
+}
+
+
+
+
+INTERNAL_(ATOM) wDupAtom (ATOM a)
+{
+ WCHAR sz[MAX_STR];
+
+ if (!a)
+ return NULL;
+
+ Assert (wIsValidAtom (a));
+ GlobalGetAtomName (a, sz, MAX_STR);
+ return wGlobalAddAtom (sz);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: wAtomLen
+//
+// Synopsis: Return the length, in characters, of the atom name.
+// The length includes the NULL. This function returns the
+// length of the UNICODE version of the atom.
+//
+// Effects:
+//
+// Arguments: [atom] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(int) wAtomLen (ATOM atom)
+{
+ WCHAR buf[MAX_STR];
+
+ if (!atom)
+ return NULL;
+
+ return (GlobalGetAtomName (atom, buf, MAX_STR));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: wAtomLenA
+//
+// Synopsis: Return the length, in characters, of the atom name.
+// The length includes the NULL This function returns the
+// length of the ANSI version of the atom,
+//
+// Effects:
+//
+// Arguments: [atom] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(int) wAtomLenA (ATOM atom)
+{
+ char buf[MAX_STR];
+
+ if (!atom)
+ return NULL;
+
+ return (GlobalGetAtomNameA (atom, (LPSTR)buf, MAX_STR));
+}
+
+
+
+// NOTE: returns address of static buffer. Use return value immediately.
+//
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: wAtomName
+//
+// Synopsis: Returns a STATIC BUFFER that holds the string name of the
+// atom.
+//
+// Effects:
+//
+// Arguments: [atom] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Commented
+//
+// Notes:
+//
+// WARNING: This uses a static buffer, so don't depend on the pointer for
+// very long.
+//
+//----------------------------------------------------------------------------
+INTERNAL_(LPOLESTR) wAtomName (ATOM atom)
+{
+ static WCHAR buf[MAX_STR];
+
+ if (!atom)
+ return NULL;
+
+ if (0==GlobalGetAtomName (atom, buf, MAX_STR))
+ return NULL;
+
+ return buf;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: wAtomName
+//
+// Synopsis: Returns a STATIC BUFFER that holds the string name of the
+// atom.
+//
+// Effects:
+//
+// Arguments: [atom] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Commented
+//
+// Notes:
+//
+// WARNING: This uses a static buffer, so don't depend on the pointer for
+// very long.
+//
+//----------------------------------------------------------------------------
+INTERNAL_(LPSTR) wAtomNameA (ATOM atom)
+{
+ static char buf[MAX_STR];
+
+ if (!atom)
+ return NULL;
+
+ if (0==GlobalGetAtomNameA (atom, (LPSTR)buf, MAX_STR))
+ return NULL;
+
+ return buf;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: wHandleFromDdeData
+//
+// Synopsis: Return a handle from the DDEDATA passed in.
+//
+// Effects: This function will return the correct data from the
+// DDEDATA that is referenced by the handle passed in.
+//
+// DDEDATA is a small structure that is used in DDE to
+// specify the data type of the buffer, its release
+// semantics, and the actual data.
+//
+// In the case of a known format, the handle to the
+// data is extracted from the DDEDATA structure, and
+// the hDdeData is released.
+//
+// If its a Native format, the data is either moved
+// within the memory block allocated, or is copied to
+// another block, depending on the fRelease flag in
+// the hDdeData.
+//
+// Arguments: [hDdeData] -- Handle to DDEDATA
+//
+// Requires:
+//
+// Returns: A handle to the data. hDdeData will be invalidated
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-13-94 kevinro Commented
+//
+// Notes:
+//
+// hDdeData is invalid after calling this function
+//
+//----------------------------------------------------------------------------
+
+
+INTERNAL_(HANDLE) wHandleFromDdeData
+ (HANDLE hDdeData)
+{
+ intrDebugOut((DEB_ITRACE,"wHandleFromDdeData(%x)\n",hDdeData));
+ BOOL fRelease;
+ HGLOBAL h = NULL; // return value
+
+ DDEDATA FAR* lpDdeData = (DDEDATA FAR *) GlobalLock (hDdeData);
+
+ //
+ // If the handle is invalid, then the lpDdeData will be NULL
+ //
+ if (!lpDdeData)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "\twHandleFromDdeData(%x) invalid handle\n",
+ hDdeData));
+ return NULL;
+ }
+
+
+ //
+ // The header section of a DDEDATA consists of 2 shorts.
+ // That makes it 4 bytes. Due to the new packing values,
+ // it turns out that doing a sizeof(DDEDATA) won't work,
+ // because the size gets rounded up to a multple of 2
+ //
+ // We will just hard code the 4 here, since it cannot change
+ // for all time anyway.
+ //
+ #define cbHeader 4
+ Assert (cbHeader==4);
+
+ //
+ // If the cfFormat is BITMAP or METAFILEPICT, then the
+ // handle will be retrieved from the first DWORD of the
+ // buffer
+ //
+ if (lpDdeData->cfFormat == CF_BITMAP ||
+ lpDdeData->cfFormat == CF_METAFILEPICT)
+ {
+ //
+ // The alignment here should be fine, since the Value
+ // field is DWORD aligned. So, we trust this cast
+ //
+ h = *(LPHANDLE)lpDdeData->Value;
+ Assert (GlobalFlags(h) != GMEM_INVALID_HANDLE);
+ fRelease = lpDdeData->fRelease;
+ GlobalUnlock (hDdeData);
+ if (fRelease)
+ {
+ GlobalFree (hDdeData);
+ }
+
+ return h;
+ }
+ else if (lpDdeData->cfFormat == CF_DIB)
+ {
+ //
+ // The alignment here should be fine, since the Value
+ // field is DWORD aligned.
+ //
+ // This changes the memory from fixed to moveable.
+ //
+ h = GlobalReAlloc (*(LPHANDLE)lpDdeData->Value, 0L,
+ GMEM_MODIFY|GMEM_MOVEABLE);
+ Assert (GlobalFlags(h) != GMEM_INVALID_HANDLE);
+ fRelease = lpDdeData->fRelease;
+ GlobalUnlock (hDdeData);
+ if (fRelease)
+ GlobalFree (hDdeData);
+ return h;
+ }
+
+
+ // Native and other data case
+ // dwSize = size of Value array, ie, size of the data itself
+ const DWORD dwSize = GlobalSize (hDdeData) - cbHeader;
+
+ if (lpDdeData->fRelease)
+ {
+ // Move the Value data up over the DDE_DATA header flags.
+ memcpy ((LPSTR)lpDdeData, ((LPSTR)lpDdeData)+cbHeader, dwSize);
+ GlobalUnlock (hDdeData);
+ h = GlobalReAlloc (hDdeData, dwSize, GMEM_MOVEABLE);
+ Assert (GlobalFlags(h) != GMEM_INVALID_HANDLE);
+ return h;
+ }
+ else
+ {
+ // Duplicate the data because the server will free the original.
+ h = wNewHandle (((LPSTR)lpDdeData)+cbHeader, dwSize);
+ Assert (GlobalFlags(h) != GMEM_INVALID_HANDLE);
+ GlobalUnlock (hDdeData);
+ return h;
+ }
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDdeObject::CanCallBack
+//
+// Synopsis: This routine apparently was supposed to determine if a
+// call back could be made. However, the PeekMessage stuff
+// was commented out.
+//
+// So, it returns TRUE if 0 or 1, FALSE but increments lpCount
+// if 2, returns true but decrements lpCount if > 3. Why?
+// Dunno. Need to ask JasonFul
+//
+// Effects:
+//
+// Arguments: [lpCount] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-16-94 kevinro Commented, confused, and disgusted
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(BOOL) CDdeObject::CanCallBack (LPINT lpCount)
+{
+ switch (*lpCount) {
+ case 0:
+ case 1:
+ return TRUE;
+
+ case 2:
+ {
+// MSG msg;
+ if (0)
+ //!PeekMessage (&msg, m_pDocChannel->hwndCli,0,0, PM_NOREMOVE) ||
+ // msg.message != WM_DDE_DATA)
+ {
+ Puts ("Server only sent one format (hopefully presentation)\n");
+ return TRUE;
+ }
+ else
+ {
+ ++(*lpCount);
+ return FALSE;
+ }
+ }
+
+ case 3:
+ --(*lpCount);
+ return TRUE;
+
+ default:
+ AssertSz (FALSE, "012345" + *lpCount);
+ return FALSE;
+ }
+}
+
+
+INTERNAL_(BOOL) wIsOldServer (ATOM aClass)
+{
+ LONG cb = MAX_STR;
+ WCHAR key[MAX_STR];
+ int len;
+
+ if (aClass==(ATOM)0)
+ return FALSE;
+
+ if (!GlobalGetAtomName (aClass, key, sizeof(key)))
+ return TRUE;
+
+ lstrcatW (key, OLESTR("\\protocol\\StdFileEditing\\verb\\"));
+ len = lstrlenW (key);
+ key [len++] = (char) ('0');
+ key [len++] = 0;
+
+ if (RegQueryValue (HKEY_CLASSES_ROOT, key, key, &cb))
+ return TRUE; // no verbs registered
+
+ return FALSE;
+}
+
+
+
+
+INTERNAL_(void) wFreePokeData
+ (LPDDE_CHANNEL pChannel,
+ BOOL fMSDrawBug)
+{
+ DDEPOKE FAR * lpdde;
+
+ if (!pChannel )
+ return;
+
+ if (!pChannel->hDdePoke)
+ return;
+
+ if (lpdde = (DDEPOKE FAR *) GlobalLock (pChannel->hDdePoke)) {
+
+ // The old version of MSDraw expects the _contents_ of METAFILEPICT
+ // structure, rather than the handle to it, to be part of DDEPOKE.
+
+ if (fMSDrawBug && lpdde->cfFormat==CF_METAFILEPICT) {
+ intrDebugOut((DEB_ITRACE,
+ "wFreePokeData is accomodating MSDraw bug\n"));
+ //
+ // This meta file was created in 32-bits, and was not passed
+ // into us by DDE. Therefore, this metafile should not need to
+ // call WOW to be free'd.
+ //
+ DeleteMetaFile (((LPMETAFILEPICT) ((LPVOID) &lpdde->Value))->hMF);
+ }
+ // If there is a normal metafile handle in the Value field,
+ // it will be freed (if necessary) by the ReleaseStgMedium()
+ // in DO::SetData
+ GlobalUnlock (pChannel->hDdePoke);
+ }
+ GlobalFree (pChannel->hDdePoke);
+ pChannel->hDdePoke = NULL;
+}
+
+
+
+
+INTERNAL_(HANDLE) wPreparePokeBlock
+ (HANDLE hData, CLIPFORMAT cfFormat, ATOM aClass, BOOL bOldSvr)
+{
+ HANDLE hDdePoke;
+ LPSTR lpBuf;
+
+ if (!hData)
+ return NULL;
+
+ // The old version of MSDraw expects the contents of METAFILEPICT
+ // structure to be part of DDEPOKE, rather than the handle to it.
+ if ((cfFormat==CF_METAFILEPICT && !(aClass==aMSDraw && bOldSvr))
+ || (cfFormat == CF_DIB)
+ || (cfFormat == CF_BITMAP)) {
+
+ Verify (lpBuf = wAllocDdePokeBlock (4, cfFormat, &hDdePoke));
+ *((HANDLE FAR*)lpBuf) = hData;
+
+ }
+ else {
+ // Handle the non-metafile case and the MS-Draw bug
+ DWORD dwSize = GlobalSize (hData);
+
+ if ((aClass == aMSDraw) && bOldSvr)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "wPreparePokeBlock is accomodating MSDraw bug\n"));
+ }
+
+ if (lpBuf = wAllocDdePokeBlock (dwSize, cfFormat, &hDdePoke)) {
+ memcpy (lpBuf, GlobalLock(hData), dwSize);
+ GlobalUnlock (hData);
+ }
+ }
+ GlobalUnlock (hDdePoke);
+ return hDdePoke;
+}
+
+
+// wAllocDdePokeBlock
+// The caller must unlock *phDdePoke when it is done using the return value
+// of this function but before a DDe message is sent using *phDdePoke.
+//
+
+INTERNAL_(LPSTR) wAllocDdePokeBlock
+ (DWORD dwSize, CLIPFORMAT cfFormat, LPHANDLE phDdePoke)
+{
+ HANDLE hdde = NULL;
+ DDEPOKE FAR * lpdde = NULL;
+
+ if (!(hdde = GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT,
+ (dwSize + sizeof(DDEPOKE) - sizeof(BYTE) ))))
+ return NULL;
+
+ if (!(lpdde = (DDEPOKE FAR*)GlobalLock (hdde))) {
+ GlobalFree (hdde);
+ return NULL;
+ }
+ // hdde will be UnLock'ed in wPreparePokeBlock and Free'd in wFreePokeData
+ lpdde->fRelease = FALSE;
+ lpdde->cfFormat = cfFormat;
+ *phDdePoke = hdde;
+ return (LPSTR) &(lpdde->Value);
+}
+
+
+#ifdef OLD
+INTERNAL_(ULONG) wPixelsToHiMetric
+ (ULONG cPixels,
+ ULONG cPixelsPerInch)
+{
+ return cPixels * HIMETRIC_PER_INCH / cPixelsPerInch;
+}
+#endif
+
+// Can ask for icon based on either CLSID or filename
+//
+
+INTERNAL GetDefaultIcon (REFCLSID clsidIn, LPCOLESTR szFile, HANDLE FAR* phmfp)
+{
+ if (!(*phmfp = OleGetIconOfClass(clsidIn, NULL, TRUE)))
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ return NOERROR;
+}
+
+#ifdef OLD
+ VDATEPTROUT (phmfp, HICON);
+ VDATEPTRIN (szFile, char);
+ WCHAR szExe[MAX_STR];
+ HICON hicon;
+ HDC hdc;
+ METAFILEPICT FAR* pmfp=NULL;
+ HRESULT hresult;
+ static int cxIcon = 0;
+ static int cyIcon = 0;
+ static int cxIconHiMetric = 0;
+ static int cyIconHiMetric = 0;
+
+ *phmfp = NULL;
+ CLSID clsid;
+ if (clsidIn != CLSID_NULL)
+ {
+ clsid = clsidIn;
+ }
+ else
+ {
+ RetErr (GetClassFile (szFile, &clsid));
+ }
+ ATOM aExe = wGetExeNameAtom (clsid);
+ if (0==GlobalGetAtomName (aExe, szExe, MAX_STR))
+ {
+ Assert (0);
+ return ReportResult(0, E_UNEXPECTED, 0, 0);
+ }
+ hicon = ExtractIcon (hmodOLE2, szExe, 0/*first icon*/);
+ if (((HICON) 1)==hicon || NULL==hicon)
+ {
+ // ExtractIcon failed, so we can't support DVASPECT_ICON
+ return ResultFromScode (DV_E_DVASPECT);
+ }
+ *phmfp = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, sizeof(METAFILEPICT));
+ ErrZS (*phmfp, E_OUTOFMEMORY);
+ pmfp = (METAFILEPICT FAR*) GlobalLock (*phmfp);
+ ErrZS (pmfp, E_OUTOFMEMORY);
+ if (0==cxIcon)
+ {
+ // In units of pixels
+ Verify (cxIcon = GetSystemMetrics (SM_CXICON));
+ Verify (cyIcon = GetSystemMetrics (SM_CYICON));
+ // In units of .01 millimeter
+ cxIconHiMetric = (int)(long)wPixelsToHiMetric (cxIcon, giPpliX) ;
+ cyIconHiMetric = (int)(long)wPixelsToHiMetric (cyIcon, giPpliY) ;
+ }
+ pmfp->mm = MM_ANISOTROPIC;
+ pmfp->xExt = cxIconHiMetric;
+ pmfp->yExt = cyIconHiMetric;
+ hdc = CreateMetaFile (NULL);
+ SetWindowOrg (hdc, 0, 0);
+ SetWindowExt (hdc, cxIcon, cyIcon);
+ DrawIcon (hdc, 0, 0, hicon);
+ pmfp->hMF = CloseMetaFile (hdc);
+ ErrZ (pmfp->hMF);
+ Assert (wIsValidHandle (pmfp->hMF, NULL));
+ GlobalUnlock (*phmfp);
+ Assert (wIsValidHandle (*phmfp, CF_METAFILEPICT));
+ return NOERROR;
+
+ errRtn:
+ if (pmfp)
+ GlobalUnlock (*phmfp);
+ if (*phmfp)
+ GlobalFree (*phmfp);
+ return hresult;
+}
+#endif
+
+#define DWTIMEOUT 1000L
+
+INTERNAL wTimedGetMessage
+ (LPMSG pmsg,
+ HWND hwnd,
+ WORD wFirst,
+ WORD wLast)
+{
+ DWORD dwStartTickCount = GetTickCount();
+ while (!SSPeekMessage (pmsg, hwnd, wFirst, wLast, PM_REMOVE))
+ {
+ if (GetTickCount() - dwStartTickCount > DWTIMEOUT)
+ {
+ if (!IsWindow (hwnd))
+ return ResultFromScode (RPC_E_CONNECTION_LOST);
+ else
+ return ResultFromScode (RPC_E_SERVER_DIED);
+ }
+ }
+ return NOERROR;
+}
+
+
+INTERNAL wNormalize
+ (LPFORMATETC pformatetcIn,
+ LPFORMATETC pformatetcOut)
+{
+ if (pformatetcIn->cfFormat == 0
+ && pformatetcIn->ptd == NULL // Is WildCard
+ && pformatetcIn->dwAspect == -1L
+ && pformatetcIn->lindex == -1L
+ && pformatetcIn->tymed == -1L)
+ {
+ pformatetcOut->cfFormat = CF_METAFILEPICT;
+ pformatetcOut->ptd = NULL;
+ pformatetcOut->dwAspect = DVASPECT_CONTENT;
+ pformatetcOut->lindex = DEF_LINDEX;
+ pformatetcOut->tymed = TYMED_MFPICT;
+ }
+ else
+ {
+ memcpy (pformatetcOut, pformatetcIn, sizeof(FORMATETC));
+ }
+ return NOERROR;
+}
+
+
+
+INTERNAL wVerifyFormatEtc
+ (LPFORMATETC pformatetc)
+{
+ intrDebugOut((DEB_ITRACE,
+ "wVerifyFormatEtc(pformatetc=%x)\n",
+ pformatetc));
+
+ VDATEPTRIN (pformatetc, FORMATETC);
+ if (!HasValidLINDEX(pformatetc))
+ {
+ intrDebugOut((DEB_IERROR, "\t!HasValidLINDEX(pformatetc)\n"));
+ return(DV_E_LINDEX);
+ }
+
+ if (0==(pformatetc->tymed & (TYMED_HGLOBAL | TYMED_MFPICT | TYMED_GDI)))
+ {
+ intrDebugOut((DEB_IERROR,
+ "\t0==(pformatetc->tymed & (TYMED_HGLOBAL | TYMED_MFPICT | TYMED_GDI))\n"));
+ return ResultFromScode (DV_E_TYMED);
+ }
+ if (0==(UtFormatToTymed (pformatetc->cfFormat) & pformatetc->tymed))
+ {
+ intrDebugOut((DEB_IERROR,
+ "\t0==(UtFormatToTymed (pformatetc->cfFormat) & pformatetc->tymed)\n"));
+ return ResultFromScode (DV_E_TYMED);
+ }
+ if (0==(pformatetc->dwAspect & (DVASPECT_CONTENT | DVASPECT_ICON)))
+ {
+ intrDebugOut((DEB_IERROR,
+ "\t0==(pformatetc->dwAspect & (DVASPECT_CONTENT | DVASPECT_ICON))\n"));
+
+ return ResultFromScode (DV_E_DVASPECT);
+ }
+ if (pformatetc->dwAspect & DVASPECT_ICON)
+ {
+ if (CF_METAFILEPICT != pformatetc->cfFormat)
+ {
+ intrDebugOut((DEB_IERROR,
+ "\tCF_METAFILEPICT != pformatetc->cfFormat\n"));
+ return ResultFromScode (DV_E_CLIPFORMAT);
+ }
+
+ if (0==(pformatetc->tymed & TYMED_MFPICT))
+ {
+ intrDebugOut((DEB_IERROR,
+ "\t0==(pformatetc->tymed & TYMED_MFPICT)\n"));
+ return ResultFromScode (DV_E_TYMED);
+ }
+ }
+ if (pformatetc->ptd)
+ {
+ if (IsBadReadPtr (pformatetc->ptd, sizeof (DWORD))
+ || IsBadReadPtr (pformatetc->ptd, (size_t)pformatetc->ptd->tdSize))
+ {
+ intrDebugOut((DEB_IERROR,"\tDV_E_DVTARGETDEVICE\n"));
+
+ return ResultFromScode (DV_E_DVTARGETDEVICE);
+ }
+ }
+ return NOERROR;
+}
+
+
+
+INTERNAL wClassesMatch
+ (REFCLSID clsidIn,
+ LPOLESTR szFile)
+{
+ CLSID clsid;
+ if (NOERROR==GetClassFile (szFile, &clsid))
+ {
+ return clsid==clsidIn ? NOERROR : ResultFromScode (S_FALSE);
+ }
+ else
+ {
+ // If we can't determine the class of the file (because it's
+ // not a real file) then OK. Bug 3937.
+ return NOERROR;
+ }
+}
+
+
+
+#ifdef KEVINRO_DUPLICATECODE
+
+This routine also appears in ole1.lib in the OLE232\OLE1 directory
+
+INTERNAL wWriteFmtUserType
+ (LPSTORAGE pstg,
+ REFCLSID clsid)
+{
+ HRESULT hresult = NOERROR;
+ LPOLESTR szProgID = NULL;
+ LPOLESTR szUserType = NULL;
+
+ ErrRtnH (ProgIDFromCLSID (clsid, &szProgID));
+ ErrRtnH (OleRegGetUserType (clsid, USERCLASSTYPE_FULL, &szUserType));
+ ErrRtnH (WriteFmtUserTypeStg (pstg, RegisterClipboardFormat (szProgID),
+ szUserType));
+ errRtn:
+ delete szProgID;
+ delete szUserType;
+ return hresult;
+}
+#endif
+
+#if DBG == 1
+
+INTERNAL_(BOOL) wIsValidHandle
+ (HANDLE h,
+ CLIPFORMAT cf) // cf==NULL means normal memory
+{
+ LPVOID p;
+ if (CF_BITMAP == cf)
+ {
+ BITMAP bm;
+ return (0 != GetObject (h, sizeof(BITMAP), (LPVOID) &bm));
+ }
+ if (CF_PALETTE == cf)
+ {
+ WORD w;
+ return (0 != GetObject (h, sizeof(w), (LPVOID) &w));
+ }
+ if (!(p=GlobalLock(h)))
+ {
+ Puts ("Invalid handle");
+ Puth (h);
+ Putn();
+ return FALSE;
+ }
+ if (IsBadReadPtr (p, (WPARAM) min (UINT_MAX, GlobalSize(h))))
+ {
+ GlobalUnlock (h);
+ return FALSE;
+ }
+ GlobalUnlock (h);
+ return TRUE;
+}
+INTERNAL_(BOOL) wIsValidAtom (ATOM a)
+{
+ WCHAR sz[MAX_STR];
+ if (a==0)
+ return TRUE;
+ if (a < 0xC000)
+ return FALSE;
+ if (0==GlobalGetAtomName (a, sz, MAX_STR))
+ return FALSE;
+ if ('\0'==sz[0])
+ return FALSE;
+ return TRUE;
+}
+
+
+// A "gentle" assert used in reterr.h
+//
+
+
+INTERNAL_(void) wWarn
+ (LPSTR sz,
+ LPSTR szFile,
+ int iLine)
+{
+ intrDebugOut((DEB_WARN,
+ "Warning: %s:%u %s\n",
+ szFile,iLine,sz));
+}
+
+#endif // DBG
+
+
diff --git a/private/ole32/com/remote/dde/client/dirs b/private/ole32/com/remote/dde/client/dirs
new file mode 100644
index 000000000..94c45c76c
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/dirs
@@ -0,0 +1,37 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+
+
diff --git a/private/ole32/com/remote/dde/client/modallp.cxx b/private/ole32/com/remote/dde/client/modallp.cxx
new file mode 100644
index 000000000..d6d79a806
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/modallp.cxx
@@ -0,0 +1,201 @@
+/*
+
+copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ modallp.cpp
+
+Abstract:
+
+ This module contains the code to wait for reply on a remote call.
+
+Author:
+ Johann Posch (johannp) 01-March-1993 modified to use CoRunModalLoop
+
+*/
+
+#include "ddeproxy.h"
+
+
+#define DebWarn(x)
+#define DebError(x)
+#define DebAction(x)
+#if DBG==1
+static unsigned iCounter=0;
+#endif
+//
+// Called after posting a message (call) to a server
+//
+#pragma SEG(CDdeObject_WaitForReply)
+
+
+
+#ifdef _CHICAGO_
+ //POSTPPC
+INTERNAL_(BOOL) CDdeObject::CanMakeOutCall(LPDDE_CHANNEL pChannel)
+{
+ intrDebugOut((DEB_ITRACE,"::CanMakeOutCall (%x) returns %d \n",pChannel,
+ (pChannel->pCD && (pChannel->pCD->id != CALLDATAID_UNUSED)) ? FALSE : TRUE));
+ return (pChannel->pCD && (pChannel->pCD->id != CALLDATAID_UNUSED)) ? FALSE : TRUE;
+}
+#endif
+
+
+INTERNAL CDdeObject::WaitForReply
+ (LPDDE_CHANNEL pChannel, int iAwaitAck, BOOL fStdCloseDoc, BOOL fDetectTerminate)
+{
+#ifdef _MAC
+#else
+ CALLDATA CD;
+ IID iid = CLSID_NULL;
+ DDECALLDATA DdeCD;
+ MSG PrevMsg;
+ BOOL fPending;
+ HRESULT hres;
+
+
+
+#if DBG == 1
+ unsigned iAutoCounter;
+ intrDebugOut((INTR_DDE,
+ "DdeObject::WaitForReply(%x) Call#(%x) awaiting %x\n",
+ this,
+ iAutoCounter=++iCounter,
+ iAwaitAck));
+#endif
+
+ if (pChannel->pCD && (pChannel->pCD->id != CALLDATAID_UNUSED)) {
+ // this callinfo is in use
+ intrDebugOut((DEB_ERROR,
+ "DdeObject::WaitForReply(%x)ERROR: DDE: callinfo is used\n", this));
+ return ResultFromScode (E_UNEXPECTED);
+ }
+
+
+ // Note: this is to detect a premature DDE_TERMINATE
+ // here we care about if we receive a WM_DDE_TERMINATE instead ACK
+ // the next call to WaitForReply will detect this state and return
+ // since the terminate was send prematurly (Excel is one of this sucker)
+ //
+ if ( fDetectTerminate ) {
+ Assert(m_wTerminate == Terminate_None);
+ // if this flag is on terminate should not execute the default code
+ // in the window procedure
+ m_wTerminate = Terminate_Detect;
+ }
+
+ pChannel->iAwaitAck = iAwaitAck;
+ pChannel->dwStartTickCount = GetTickCount();
+
+ // start looking only for dde messages first
+ pChannel->msgFirst = WM_DDE_FIRST;
+ pChannel->msgLast = WM_DDE_LAST;
+ pChannel->msghwnd = pChannel->hwndCli;
+ PrevMsg.message = 0;
+ PrevMsg.time = 0;
+
+ pChannel->fRejected = FALSE;
+ // see if there is a thread window for lrpc communication
+ // if so we have to dispatch this messages as well
+ fPending = FALSE;
+
+ intrDebugOut((DEB_ITRACE,
+ "+++ Waiting for reply: server: %x, client %x Call#(%x) +++\n",
+ pChannel->hwndSvr,
+ pChannel->hwndCli,
+ iAutoCounter));
+
+ // prepare and enter the modal loop
+ DdeCD.hwndSvr = pChannel->hwndSvr;
+ DdeCD.hwndCli = pChannel->hwndCli;
+ DdeCD.wMsg = pChannel->wMsg;
+ DdeCD.wParam = (WPARAM) pChannel->hwndCli,
+ DdeCD.lParam = pChannel->lParam;
+ DdeCD.fInitialSend = TRUE;
+
+ CD.id = CALLDATAID_UNUSED;
+ CD.lid = iid;
+ CD.TIDCallee = 0;
+ CD.pRpcMsg = (LPVOID) &DdeCD;
+ CD.CallCat = CALLCAT_SYNCHRONOUS;
+ CD.Event = 0;
+
+ pChannel->pCD = &CD;
+
+ //
+ // Setting this value tells DeleteChannel NOT to delete itself.
+ // If the value changes to Channel_DeleteNow while we are in
+ // the modal loop, this routine will delete the channel
+ //
+ pChannel->wChannelDeleted = Channel_InModalloop;
+
+ //
+ // hres will be the return code from the message
+ // handlers, or from the channel itself. The return
+ // code comes from calls to SetCallState. Most of the
+ // time, it will be things like RPC_E_DDE_NACK. However,
+ // it may also return OUTOFMEMORY, or other ModalLoop
+ // problems.
+ //
+
+ hres = pChannel->pCallCont->CallRunModalLoop(&CD);
+
+ if (hres != NOERROR)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "**************** CallRunModalLoop returns %x ***\n",
+ hres));
+ }
+
+ if (m_wTerminate == Terminate_Received) {
+ intrAssert(fDetectTerminate);
+ //
+ // There really wasn't an error, its just that the server decided
+ // to terminate. If we return an error here, the app may decide
+ // that things have gone awry. Excel, for example, will decide
+ // that the object could not be activated, even though it has
+ // already updated its cache information.
+ //
+ hres = NOERROR;
+ intrDebugOut((DEB_ITRACE,
+ "::WaitForReply setting hres=%x\n",
+ hres));
+ intrDebugOut((DEB_ITRACE,
+ "::WaitForReply posting TERMINATE to self hwnd=%x\n",
+ DdeCD.hwndCli));
+ // set state to normal and repost message
+ Verify (PostMessage (DdeCD.hwndCli, WM_DDE_TERMINATE,
+ (WPARAM)DdeCD.hwndSvr, (LPARAM)0));
+ }
+ m_wTerminate = Terminate_None;
+
+ //
+ // If the channel is to be deleted, then do it now. This flag would
+ // have been set in the DeleteChannel routine.
+ //
+ if (pChannel->wChannelDeleted == Channel_DeleteNow)
+ {
+ intrDebugOut((INTR_DDE,
+ "::WaitForReply(%x) Channel_DeleteNow pChannel(%x)\n",
+ pChannel));
+
+ pChannel->ReleaseReference();
+
+ // Excel will send TERMINATE before sending an ACK to StdCloseDoc
+ return ResultFromScode (fStdCloseDoc ? S_OK : RPC_E_DDE_POST);
+ }
+ pChannel->wChannelDeleted = 0;
+
+ pChannel->iAwaitAck = 0;
+ pChannel->pCD = NULL;
+
+ intrDebugOut((DEB_ITRACE,
+ "### Waiting for reply done: server: %x, client %x hres(%x)###\n",
+ pChannel->hwndSvr,
+ pChannel->hwndCli,
+ hres));
+
+ return hres;
+#endif _MAC
+}
diff --git a/private/ole32/com/remote/dde/client/packmnkr.cxx b/private/ole32/com/remote/dde/client/packmnkr.cxx
new file mode 100644
index 000000000..b4642bb8c
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/packmnkr.cxx
@@ -0,0 +1,273 @@
+/*
+ PackMnkr.cpp
+ PackageMoniker
+
+ This module implements the CPackagerMoniker class and
+ CreatePackagerMoniker()
+
+ Author:
+ Jason Fuller jasonful Nov-2-1992
+
+ Copyright (c) 1992 Microsoft Corporation
+*/
+
+#include <ole2int.h>
+#include "packmnkr.h"
+#include "..\server\ddedebug.h"
+#include <ole1cls.h>
+
+ASSERTDATA
+
+
+STDMETHODIMP CPackagerMoniker::QueryInterface
+ (REFIID riid, LPVOID * ppvObj)
+{
+ M_PROLOG(this);
+ VDATEIID (riid);
+ VDATEPTROUT (ppvObj, LPVOID);
+
+ if ((riid == IID_IMoniker) || (riid == IID_IUnknown) ||
+ (riid == IID_IPersistStream) || (riid == IID_IInternalMoniker))
+ {
+ *ppvObj = this;
+ ++m_refs;
+ return NOERROR;
+ }
+ AssertSz (0, "Could not find interface\r\n");
+ *ppvObj = NULL;
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+}
+
+
+
+STDMETHODIMP_(ULONG) CPackagerMoniker::AddRef()
+{
+ M_PROLOG(this);
+ return ++m_refs;
+}
+
+
+
+STDMETHODIMP_(ULONG) CPackagerMoniker::Release()
+{
+ M_PROLOG(this);
+ Assert (m_refs > 0);
+ if (0 == --m_refs)
+ {
+ m_pmk->Release();
+ delete m_szFile;
+ delete this;
+ return 0;
+ }
+ return m_refs;
+}
+
+
+
+STDMETHODIMP CPackagerMoniker::GetClassID (THIS_ LPCLSID lpClassID)
+{
+ M_PROLOG(this);
+ *lpClassID = CLSID_PackagerMoniker;
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP CPackagerMoniker::BindToObject (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID * ppvResult)
+{
+ M_PROLOG(this);
+ WIN32_FIND_DATA fd;
+ HRESULT hr;
+
+ // The following code ensures that the file exists before we try to bind it.
+ HANDLE hFind = FindFirstFile(m_szFile, &fd);
+ if (hFind != INVALID_HANDLE_VALUE)
+ {
+ hr = DdeBindToObject (m_szFile, CLSID_Package, m_fLink, riidResult, ppvResult);
+ FindClose(hFind);
+ }
+ else
+ hr = MK_E_CANTOPENFILE;
+ return hr;
+}
+
+STDMETHODIMP CPackagerMoniker::IsRunning (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning)
+{
+ M_PROLOG(this);
+ VDATEIFACE (pbc);
+
+ if (pmkToLeft)
+ VDATEIFACE (pmkToLeft);
+ if (pmkNewlyRunning)
+ VDATEIFACE (pmkNewlyRunning);
+
+ // There is no way to tell if a packaged object is running
+ return ReportResult (0, S_FALSE, 0, 0);
+}
+
+
+STDAPI CreatePackagerMoniker(LPOLESTR szFile, LPMONIKER * ppmk, BOOL fLink )
+{
+ return CPackagerMoniker::Create (szFile, ppmk, fLink);
+}
+
+HRESULT CPackagerMoniker::Create(LPOLESTR szFile,LPMONIKER * ppmk, BOOL fLink )
+{
+ HRESULT hresult;
+ VDATEPTROUT (ppmk, LPMONIKER);
+ *ppmk = NULL;
+
+ CPackagerMoniker * pmkPack = new CPackagerMoniker;
+ if (NULL==pmkPack)
+ return ReportResult (0, E_OUTOFMEMORY, 0, 0);
+ ErrRtnH (CreateFileMoniker (szFile, &(pmkPack->m_pmk)));
+
+ pmkPack->m_szFile = new WCHAR [lstrlenW(szFile)+1];
+ lstrcpyW (pmkPack->m_szFile, szFile);
+
+ pmkPack->m_fLink = fLink;
+ pmkPack->m_refs = 1;
+
+ *ppmk = pmkPack;
+ return NOERROR;
+
+errRtn:
+ Assert (0);
+ delete pmkPack;
+ return hresult;
+}
+
+
+
+/////////////////////////////////////////////////////////////////////
+// The rest of these methods just delegate to m_pmk
+// or return some error code.
+
+
+STDMETHODIMP CPackagerMoniker::IsDirty (THIS)
+{
+ M_PROLOG(this);
+ return ReportResult(0, S_FALSE, 0, 0);
+ // monikers are immutable so they are either always dirty or never dirty.
+ //
+}
+
+STDMETHODIMP CPackagerMoniker::Load (THIS_ LPSTREAM pStm)
+{
+ M_PROLOG(this);
+ return m_pmk->Load(pStm);
+}
+
+
+STDMETHODIMP CPackagerMoniker::Save (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty)
+{
+ M_PROLOG(this);
+ return m_pmk->Save(pStm, fClearDirty);
+}
+
+
+STDMETHODIMP CPackagerMoniker::GetSizeMax (THIS_ ULARGE_INTEGER * pcbSize)
+{
+ M_PROLOG(this);
+ return m_pmk->GetSizeMax (pcbSize);
+}
+
+ // *** IMoniker methods ***
+STDMETHODIMP CPackagerMoniker::BindToStorage (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID * ppvObj)
+{
+ M_PROLOG(this);
+ *ppvObj = NULL;
+ return ReportResult(0, E_NOTIMPL, 0, 0);
+}
+
+STDMETHODIMP CPackagerMoniker::Reduce (THIS_ LPBC pbc, DWORD dwReduceHowFar, LPMONIKER *
+ ppmkToLeft, LPMONIKER * ppmkReduced)
+{
+ M_PROLOG(this);
+ return m_pmk->Reduce (pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced);
+}
+
+STDMETHODIMP CPackagerMoniker::ComposeWith (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNotGeneric,
+ LPMONIKER * ppmkComposite)
+{
+ M_PROLOG(this);
+ return m_pmk->ComposeWith (pmkRight, fOnlyIfNotGeneric, ppmkComposite);
+}
+
+STDMETHODIMP CPackagerMoniker::Enum (THIS_ BOOL fForward, LPENUMMONIKER * ppenumMoniker)
+{
+ M_PROLOG(this);
+ return m_pmk->Enum (fForward, ppenumMoniker);
+}
+
+STDMETHODIMP CPackagerMoniker::IsEqual (THIS_ LPMONIKER pmkOtherMoniker)
+{
+ M_PROLOG(this);
+ return m_pmk->IsEqual (pmkOtherMoniker);
+}
+
+STDMETHODIMP CPackagerMoniker::Hash (THIS_ LPDWORD pdwHash)
+{
+ M_PROLOG(this);
+ return m_pmk->Hash (pdwHash);
+}
+
+STDMETHODIMP CPackagerMoniker::GetTimeOfLastChange (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME * pfiletime)
+{
+ M_PROLOG(this);
+ return m_pmk->GetTimeOfLastChange (pbc, pmkToLeft, pfiletime);
+}
+
+STDMETHODIMP CPackagerMoniker::Inverse (THIS_ LPMONIKER * ppmk)
+{
+ M_PROLOG(this);
+ return m_pmk->Inverse (ppmk);
+}
+
+STDMETHODIMP CPackagerMoniker::CommonPrefixWith (LPMONIKER pmkOther, LPMONIKER *
+ ppmkPrefix)
+{
+ M_PROLOG(this);
+ return m_pmk->CommonPrefixWith (pmkOther, ppmkPrefix);
+}
+
+STDMETHODIMP CPackagerMoniker::RelativePathTo (THIS_ LPMONIKER pmkOther, LPMONIKER *
+ ppmkRelPath)
+{
+ M_PROLOG(this);
+ return m_pmk->RelativePathTo (pmkOther, ppmkRelPath);
+}
+
+STDMETHODIMP CPackagerMoniker::GetDisplayName (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPOLESTR * lplpszDisplayName)
+{
+ M_PROLOG(this);
+ return m_pmk->GetDisplayName (pbc, pmkToLeft, lplpszDisplayName);
+}
+
+STDMETHODIMP CPackagerMoniker::ParseDisplayName (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPOLESTR lpszDisplayName, ULONG * pchEaten,
+ LPMONIKER * ppmkOut)
+{
+ M_PROLOG(this);
+ return m_pmk->ParseDisplayName (pbc, pmkToLeft, lpszDisplayName, pchEaten,
+ ppmkOut);
+}
+
+
+STDMETHODIMP CPackagerMoniker::IsSystemMoniker (THIS_ LPDWORD pdwMksys)
+{
+ M_PROLOG(this);
+ VDATEPTROUT (pdwMksys, DWORD);
+
+ *pdwMksys = MKSYS_NONE;
+ return NOERROR;
+}
+
+
+
diff --git a/private/ole32/com/remote/dde/client/packmnkr.h b/private/ole32/com/remote/dde/client/packmnkr.h
new file mode 100644
index 000000000..bc312bfab
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/packmnkr.h
@@ -0,0 +1,63 @@
+/*
+ packmnkr.h
+*/
+
+class CPackagerMoniker : public IMoniker
+{
+ public:
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) ( REFIID riid, LPVOID * ppvObj) ;
+ STDMETHOD_(ULONG,AddRef) () ;
+ STDMETHOD_(ULONG,Release) () ;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) ( LPCLSID lpClassID) ;
+
+ // *** IPersistStream methods ***
+ STDMETHOD(IsDirty) () ;
+ STDMETHOD(Load) ( LPSTREAM pStm) ;
+ STDMETHOD(Save) ( LPSTREAM pStm,
+ BOOL fClearDirty) ;
+ STDMETHOD(GetSizeMax) ( ULARGE_INTEGER * pcbSize) ;
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) ( LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID * ppvResult) ;
+ STDMETHOD(BindToStorage) ( LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID * ppvObj) ;
+ STDMETHOD(Reduce) ( LPBC pbc, DWORD dwReduceHowFar, LPMONIKER *
+ ppmkToLeft, LPMONIKER * ppmkReduced) ;
+ STDMETHOD(ComposeWith) ( LPMONIKER pmkRight, BOOL fOnlyIfNotGeneric,
+ LPMONIKER * ppmkComposite) ;
+ STDMETHOD(Enum) ( BOOL fForward, LPENUMMONIKER * ppenumMoniker)
+ ;
+ STDMETHOD(IsEqual) ( LPMONIKER pmkOtherMoniker) ;
+ STDMETHOD(Hash) ( LPDWORD pdwHash) ;
+ STDMETHOD(IsRunning) ( LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+ pmkNewlyRunning) ;
+ STDMETHOD(GetTimeOfLastChange) ( LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME * pfiletime) ;
+ STDMETHOD(Inverse) ( LPMONIKER * ppmk) ;
+ STDMETHOD(CommonPrefixWith) ( LPMONIKER pmkOther, LPMONIKER *
+ ppmkPrefix) ;
+ STDMETHOD(RelativePathTo) ( LPMONIKER pmkOther, LPMONIKER *
+ ppmkRelPath) ;
+ STDMETHOD(GetDisplayName) ( LPBC pbc, LPMONIKER pmkToLeft,
+ LPOLESTR * lplpszDisplayName) ;
+ STDMETHOD(ParseDisplayName) ( LPBC pbc, LPMONIKER pmkToLeft,
+ LPOLESTR lpszDisplayName, ULONG * pchEaten,
+ LPMONIKER * ppmkOut) ;
+ STDMETHOD(IsSystemMoniker) ( LPDWORD pdwMksys) ;
+
+ static HRESULT Create ( LPOLESTR szFile, LPMONIKER * ppmk, BOOL fLink) ;
+
+ private:
+
+ ULONG m_refs;
+ LPOLESTR m_szFile;
+ LPMONIKER m_pmk;
+ BOOL m_fLink;
+
+
+};
+
diff --git a/private/ole32/com/remote/dde/client/trgt_dev.h b/private/ole32/com/remote/dde/client/trgt_dev.h
new file mode 100644
index 000000000..a2de2d4b3
--- /dev/null
+++ b/private/ole32/com/remote/dde/client/trgt_dev.h
@@ -0,0 +1,19 @@
+// trgt_dev.h
+
+// OLE 1.0 Target Device
+
+typedef struct _OLETARGETDEVICE
+{
+ USHORT otdDeviceNameOffset;
+ USHORT otdDriverNameOffset;
+ USHORT otdPortNameOffset;
+ USHORT otdExtDevmodeOffset;
+ USHORT otdExtDevmodeSize;
+ USHORT otdEnvironmentOffset;
+ USHORT otdEnvironmentSize;
+ BYTE otdData[1];
+} OLETARGETDEVICE;
+
+typedef OLETARGETDEVICE const FAR* LPCOLETARGETDEVICE;
+typedef OLETARGETDEVICE FAR* LPOLETARGETDEVICE;
+
diff --git a/private/ole32/com/remote/dde/dirs b/private/ole32/com/remote/dde/dirs
new file mode 100644
index 000000000..8d723ece9
--- /dev/null
+++ b/private/ole32/com/remote/dde/dirs
@@ -0,0 +1,36 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS= client server
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS=
+
diff --git a/private/ole32/com/remote/dde/server/daytona/makefile b/private/ole32/com/remote/dde/server/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/remote/dde/server/daytona/sources b/private/ole32/com/remote/dde/server/daytona/sources
new file mode 100644
index 000000000..f557ef159
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/daytona/sources
@@ -0,0 +1,83 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= ddesvr
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES = ..\.;..\..\client;..\..\..\..\..\common\daytona;..\..\..\..\..\ih;..\..\..;..\..\..\..\inc;..\..\..\..\idl\daytona;..\..\..\..\class;..\..\..\..\objact;..\..\..\..\..\ole232\inc
+
+!include ..\..\..\..\..\daytona.inc
+
+C_DEFINES= -DOLE_DDE_NO_GLOBAL_TRACKING=1\
+ $(C_DEFINES) \
+
+
+SOURCES= \
+ ..\ddeadv.cxx \
+ ..\ddesink.cxx \
+ ..\ddesite.cxx \
+ ..\ddesrvr.cxx \
+ ..\ddeutils.cxx \
+ ..\doc.cxx \
+ ..\item.cxx \
+ ..\item2.cxx \
+ ..\itemutil.cxx \
+ ..\srvr.cxx \
+ ..\srvrmain.cxx
+
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+# PRECOMPILED_INCLUDE= ..\headers.cxx
+
+
diff --git a/private/ole32/com/remote/dde/server/ddeadv.cxx b/private/ole32/com/remote/dde/server/ddeadv.cxx
new file mode 100644
index 000000000..0d03789ed
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/ddeadv.cxx
@@ -0,0 +1,132 @@
+// ddeadv.cpp
+//
+// Mapping from DDE advise to/from OLE 2.0 advises
+//
+// Author:
+// Jason Fuller jasonful 8-16-92
+//
+// Copyright (c) 1992 Microsoft Corporation
+
+#include "ole2int.h"
+#include "srvr.h"
+#include "ddedebug.h"
+ASSERTDATA
+
+
+INTERNAL CDefClient::DoOle20Advise
+ (OLE_NOTIFICATION options,
+ CLIPFORMAT cf)
+{
+ HRESULT hresult = NOERROR;
+ FORMATETC formatetc;
+ formatetc.cfFormat = cf;
+ formatetc.ptd = m_ptd;
+ formatetc.lindex = DEF_LINDEX;
+ formatetc.dwAspect = DVASPECT_CONTENT;
+ // only types 1.0 client wants
+ formatetc.tymed = TYMED_HGLOBAL | TYMED_MFPICT | TYMED_GDI;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::DoOle20Advise(options=%x,cf=%x)\n",
+ this,
+ options,
+ (ULONG)cf));
+ ChkC(this);
+ switch (options)
+ {
+ case OLE_CHANGED:
+#ifdef UPDATE
+ case OLE_SAVED:
+#endif
+ if (0 == m_dwConnectionDataObj)
+ {
+ Assert (m_lpdataObj);
+ RetErr (m_lpdataObj->DAdvise (&formatetc,0/* ADVF_PRIMEFIRST*/,
+ &m_AdviseSink,
+ &m_dwConnectionDataObj));
+ Assert (m_dwConnectionDataObj != 0);
+ }
+ // Fall through:
+ // Even for OLE_CHANGED do an Ole Advise so we get OnClose
+ // notifications for linked objects.
+
+#ifndef UPDATE
+ case OLE_SAVED:
+#endif
+ case OLE_RENAMED: // Link case
+ case OLE_CLOSED:
+ Assert (m_lpoleObj);
+ // Only do one OleObject::Advise even if 1.0 client asks
+ // for two advises for two different formats and two events,
+ // i.e., native and metafile, save and close.
+ if (m_lpoleObj && 0==m_dwConnectionOleObj)
+ {
+ Puts ("Calling OleObject::Advise\r\n");
+ Assert (m_dwConnectionOleObj == 0L);
+ hresult = m_lpoleObj->Advise (&m_AdviseSink, &m_dwConnectionOleObj);
+ if (hresult != NOERROR)
+ {
+ goto errRtn;
+ }
+ }
+ Assert (m_dwConnectionOleObj != 0);
+ break;
+
+ default:
+ Assert(0);
+ break;
+ }
+
+errRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::DoOle20Advise hresult=%x\n",
+ this,hresult));
+
+
+ return NOERROR;
+}
+
+
+
+
+INTERNAL CDefClient::DoOle20UnAdviseAll
+ (void)
+{
+ HRESULT hr;
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::DoOle20UnAdviseAll\n",
+ this));
+
+ ChkC(this);
+ if (m_dwConnectionOleObj != 0L)
+ {
+ if (m_lpoleObj)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%x ::DoOle20UnAdviseAll unadvise OLE obj\n",
+ this));
+ Puts ("Unadvising ole obj\r\n");
+ hr = m_lpoleObj->Unadvise (m_dwConnectionOleObj);
+ intrAssert(hr == NOERROR);
+ m_dwConnectionOleObj = 0L;
+ }
+ }
+ if (m_dwConnectionDataObj != 0L)
+ {
+ if (m_lpdataObj)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%x ::DoOle20UnAdviseAll unadvise DATA obj\n",
+ this));
+ Puts ("Unadvising data obj\r\n");
+ hr = m_lpdataObj->DUnadvise (m_dwConnectionDataObj);
+ intrAssert(hr == NOERROR);
+ m_dwConnectionDataObj = 0L;
+ }
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::DoOle20UnAdviseAll\n",
+ this));
+
+ return NOERROR;
+}
diff --git a/private/ole32/com/remote/dde/server/ddeatoms.h b/private/ole32/com/remote/dde/server/ddeatoms.h
new file mode 100644
index 000000000..ba105ba17
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/ddeatoms.h
@@ -0,0 +1,42 @@
+/* ddeatoms.h */
+
+//This is here because the file is #included by both client and server files
+#define fDdeCodeInOle2Dll 1
+
+// These atoms are defined in srvrmain.cpp
+extern ATOM aEditItems;
+extern ATOM aFormats;
+extern ATOM aOLE;
+extern ATOM aProtocols;
+extern ATOM aStatus;
+extern ATOM aStdClose;
+extern ATOM aStdCreate;
+extern ATOM aStdCreateFromTemplate;
+extern ATOM aStdEdit;
+extern ATOM aStdExit;
+extern ATOM aStdOpen;
+extern ATOM aStdShowItem;
+extern ATOM aSysTopic;
+extern ATOM aTopics;
+
+// defined in ddewnd.cpp
+extern ATOM aChange;
+extern ATOM aClose;
+extern ATOM aMSDraw;
+extern ATOM aNullArg;
+extern ATOM aOle;
+extern ATOM aSave;
+extern ATOM aStdColorScheme;
+extern ATOM aStdDocDimensions;
+extern ATOM aStdDocName;
+extern ATOM aStdHostNames;
+extern ATOM aStdTargetDevice ;
+extern ATOM aSystem;
+
+// defined in ddewnd.cpp
+extern CLIPFORMAT cfBinary; // "Binary format"
+extern CLIPFORMAT cfNative; // "NativeFormat"
+
+// defined in srvrmain.cpp
+extern CLIPFORMAT cfLink; // "ObjectLink"
+extern CLIPFORMAT cfOwnerLink; // "Ownerlink"
diff --git a/private/ole32/com/remote/dde/server/ddedebug.h b/private/ole32/com/remote/dde/server/ddedebug.h
new file mode 100644
index 000000000..dfb7401e6
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/ddedebug.h
@@ -0,0 +1,99 @@
+// ddeDebug.h
+//
+// Generic debug routines
+//
+// Author:
+// Jason Fuller jasonful 8-16-92
+//
+
+#ifndef fDdedebug_h
+#define fDdedebug_h
+
+#define INTR_DDE 0x00010000
+#define INTR_CHNL 0x00020000
+#define INTR_PARAM 0x00040000
+
+//#define fDebugOutput
+#define WIDECHECK(x) (x?x:L"<NULL>")
+#define ANSICHECK(x) (x?x:"<NULL>")
+
+#if DBG == 1
+#define DEBUG_GUIDSTR(name,guid) WCHAR name [48]; StringFromGUID2( *guid , name , sizeof( name ));
+#else
+#define DEBUG_GUIDSTR(name,guid)
+#endif
+#ifdef _DEBUG
+
+ // defined in clientddeworkr.cpp
+ BOOL wIsValidHandle (HANDLE, CLIPFORMAT);
+ BOOL wIsValidAtom (ATOM);
+
+ #define DebugOnly(x) x
+ #define ChkC(p) Assert (p && p->m_chk==chkDefClient)
+ #define ChkS(p) Assert (p && p->m_chk==chkDdeSrvr)
+ #define ChkD(p) Assert ((p) && (p)->m_chk==chkDdeObj)
+ #define AssertIsDoc(p) Assert ((p) && (p)->m_pdoc==(p) && (p)->m_bContainer)
+
+ #define ChkCR(p) RetZ (p && p->m_chk==chkDefClient)
+ #define ChkSR(p) RetZ (p && p->m_chk==chkDdeSrvr)
+ #define ChkDR(p) RetZ ((p) && (p)->m_chk==chkDdeObj)
+ #define AssertIsDocR(p) RetZ ((p) && (p)->m_pdoc==(p) && (p)->m_bContainer)
+
+ #ifdef fDebugOutput
+
+ #define Puti(i) do {char sz[50]; wsprintf(sz, " %lu ", (unsigned long) (i)); Puts(sz);} while(0)
+ #define Puth(i) do {char sz[50]; wsprintf(sz, " 0x%lx ", (unsigned long) (i)); Puts(sz);} while(0)
+ #define Puta(a) do {char sz[50]="NULL"; if (a) GlobalGetAtomName(a,sz,50); \
+ Puth(a); Puts("\""); Puts(sz); Puts("\" "); } while(0)
+ #define Putsi(i) do { Puts(#i " = "); Puti(i); Puts("\n");} while (0)
+ #define Putn() Puts("\r\n")
+
+ #else
+
+ #undef Puts
+ #define Puts(i) ((void)0)
+ #define Puti(i) ((void)0)
+ #define Puth(i) ((void)0)
+ #define Puta(a) ((void)0)
+ #define Putsi(i) ((void)0)
+ #define Putn() ((void)0)
+
+ #endif // fDebugOutput
+ #define DEBUG_OUT(a,b) OutputDebugStringA(a);
+#else
+ #define DEBUG_OUT(a,b)
+ #define Puti(i) ((void)0)
+ #define Puth(i) ((void)0)
+ #define Puta(a) ((void)0)
+ #define Putsi(i) ((void)0)
+ #define Putn() ((void)0)
+ #define wIsValidHandle(h,cf) (TRUE)
+ #define wIsValidAtom(a) (TRUE)
+ #define DebugOnly(x)
+ #define ChkC(p)
+ #define ChkS(p)
+ #define ChkD(p)
+ #define AssertIsDoc(p)
+ #define ChkCR(p)
+ #define ChkSR(p)
+ #define ChkDR(p)
+ #define AssertIsDocR(p)
+
+#endif // _DEBUG
+
+
+// Stuff common to both client and server directories
+
+#define POSITIVE_ACK (0x8000)
+#define NEGATIVE_ACK (0x0000)
+
+#include <reterr.h>
+
+INTERNAL_(LPOLESTR) wAtomName (ATOM atom);
+INTERNAL_(LPSTR) wAtomNameA (ATOM atom);
+INTERNAL_(ATOM) wDupAtom (ATOM aSrc);
+
+INTERNAL wClassesMatch (REFCLSID clsid, LPOLESTR szFile);
+INTERNAL wWriteFmtUserType (LPSTORAGE, REFCLSID);
+
+#endif // fDdedebug_h
diff --git a/private/ole32/com/remote/dde/server/ddeerr.h b/private/ole32/com/remote/dde/server/ddeerr.h
new file mode 100644
index 000000000..f35a88b63
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/ddeerr.h
@@ -0,0 +1,78 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ddeerr.h
+//
+// Contents: Error codes from the previous release
+//
+// Classes:
+//
+// Functions:
+//
+// History: 4-26-94 kevinro Commented/cleaned
+//
+// This is actually the contents from ole2anac.h, with some parts removed.
+// Specifically, including ole2anac.h renamed DAdvise and friends, which
+// is bad.
+//----------------------------------------------------------------------------
+#if !defined( _OLE2ANAC_H_ )
+#define _OLE2ANAC_H_
+
+typedef enum tagSTGSTATE
+{
+ STGSTATE_DOC = 1,
+ STGSTATE_CONVERT = 2,
+ STGSTATE_FILESTGSAME = 4
+} STGSTATE;
+
+
+#define MK_E_EXCEEDED_DEADLINE MK_E_EXCEEDEDDEADLINE
+#define MK_E_NEED_GENERIC MK_E_NEEDGENERIC
+#define MK_E_INVALID_EXTENSION MK_E_INVALIDEXTENSION
+#define MK_E_INTERMEDIATE_INTERFACE_NOT_SUPPORTED \
+ MK_E_INTERMEDIATEINTERFACENONOT_SUPPORTED
+#define MK_E_NOT_BINDABLE MK_E_NOTBINDABLE
+#define S_TRUE S_OK
+
+#define E_BLANK OLE_E_BLANK
+#define E_STATIC OLE_E_STATIC
+#define E_NOTRUNNING OLE_E_NOTRUNNING
+#define E_FORMAT DV_E_CLIPFORMAT
+#define OLE_E_CLSID REGDB_E_CLASSNOTREG
+#define OLE_E_NOTSUPPORTED E_NOTIMPL
+#define OLE_E_REGDB_KEY REGDB_E_KEYMISSING
+#define OLE_E_REGDB_FMT REGDB_E_INVALIDVALUE
+
+
+#define OLEVERB_PRIMARY OLEIVERB_PRIMARY
+#define OLEVERB_SHOW OLEIVERB_SHOW
+
+// these DDE error codes are not returned anymore; these definitions are
+// here just to make existing code compile without changes.
+#define RPC_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_RPC, 0x000)
+#define RPC_E_DDE_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_RPC, 0x100)
+
+#define RPC_E_DDE_BUSY (RPC_E_DDE_FIRST + 0x0)
+#define RPC_E_DDE_CANT_UPDATE (RPC_E_DDE_FIRST + 0x1)
+#define RPC_E_DDE_INIT (RPC_E_DDE_FIRST + 0x2)
+#define RPC_E_DDE_NACK E_FAIL
+#define RPC_E_DDE_LAUNCH CO_E_APPNOTFOUND
+#define RPC_E_DDE_POST RPC_E_SERVER_DIED
+#define RPC_E_DDE_PROTOCOL (RPC_E_DDE_FIRST + 0x6)
+#define RPC_E_DDE_REVOKE (RPC_E_DDE_FIRST + 0x7)
+#define RPC_E_DDE_SYNTAX_EXECUTE RPC_E_INVALID_PARAMETER
+#define RPC_E_DDE_SYNTAX_ITEM RPC_E_INVALID_PARAMETER
+#define RPC_E_DDE_UNEXP_MSG (RPC_E_DDE_FIRST + 0xa)
+#define RPC_E_DDE_DATA RPC_E_INVALID_PARAMETER
+
+
+#define RPC_E_CONNECTION_LOST (RPC_E_FIRST + 0x6)
+#define RPC_E_BUSY (RPC_E_FIRST + 0x0)
+#define RPC_E_MSG_REJECTED (RPC_E_FIRST + 0x1)
+#define RPC_E_CANCELLED (RPC_E_FIRST + 0x2)
+#define RPC_E_DISPATCH_ASYNCCALL (RPC_E_FIRST + 0x4)
+
+
+#endif // _OLE2ANAC_H_
diff --git a/private/ole32/com/remote/dde/server/ddeint.h b/private/ole32/com/remote/dde/server/ddeint.h
new file mode 100644
index 000000000..d99fb29f3
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/ddeint.h
@@ -0,0 +1,179 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ddeint.h
+//
+// Contents: This file contains shared macros/state between the server
+// and client directories
+// Classes:
+//
+// Functions:
+//
+// History: 5-04-94 kevinro Commented/cleaned
+//
+//----------------------------------------------------------------------------
+
+//
+// BUGBUG: (KevinRo) The new definition of DVTARGETDEVICE uses an unsized array
+// of bytes at the end. Therefore, the sizeof operator no longer works. So, I
+// have calculated the size of the cbHeader by accounting for each member of
+// the structure independently. I am not too proud of this at the moment,
+// but need to move on.
+//
+
+#define DEB_DDE_INIT (DEB_ITRACE|DEB_USER1)
+
+// names of the DDE window classes
+#ifdef _CHICAGO_
+// Note: we have to create a unique string so that get
+// register a unique class for each 16 bit app.
+// The class space is global on chicago.
+//
+extern LPSTR szSYS_CLASSA;
+extern LPSTR szCLIENT_CLASSA;
+extern LPSTR szSRVR_CLASSA;
+extern LPSTR szDOC_CLASSA;
+extern LPSTR szITEM_CLASSA;
+extern LPSTR szCOMMONCLASSA;
+
+#define DOC_CLASSA szDOC_CLASSA
+#define SYS_CLASSA szSYS_CLASSA
+#define CLIENT_CLASSA szCLIENT_CLASSA
+
+#define SYS_CLASS szSYS_CLASSA
+#define CLIENT_CLASS szCLIENT_CLASSA
+#define SRVR_CLASS szSRVR_CLASSA
+#define SRVR_CLASS szSRVR_CLASSA
+#define DOC_CLASS szDOC_CLASSA
+#define ITEM_CLASS szITEM_CLASSA
+#define COMMONCLASS szCOMMONCLASSA
+
+
+#define DDEWNDCLASS WNDCLASSA
+#define DdeRegisterClass RegisterClassA
+#define DdeUnregisterClass UnregisterClassA
+#define DdeCreateWindowEx SSCreateWindowExA
+
+#else
+
+#define SYS_CLASS L"Ole2SysWndClass"
+#define SYS_CLASSA "Ole2SysWndClass"
+
+#define CLIENT_CLASS L"Ole2ClientWndClass"
+#define CLIENT_CLASSA "Ole2ClientWndClass"
+
+#define SRVR_CLASS (OLESTR("SrvrWndClass"))
+#define SRVR_CLASSA ("SrvrWndClass")
+
+#define DOC_CLASS (OLESTR("ViewObjWndClass"))
+#define DOC_CLASSA ("ViewObjWndClass")
+
+#define ITEM_CLASS (OLESTR("ItemWndClass"))
+
+#define DDEWNDCLASS WNDCLASS
+#define DdeRegisterClass RegisterClass
+#define DdeUnregisterClass UnregisterClass
+#define DdeCreateWindowEx CreateWindowEx
+
+#endif // !_CHICAGO_
+
+STDAPI_(LRESULT) DocWndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+STDAPI_(LRESULT) SrvrWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+STDAPI_(LRESULT) SysWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+STDAPI_(LRESULT) ClientDocWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+BOOL SendMsgToChildren (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+#define SIZEOF_DVTARGETDEVICE_HEADER (sizeof(DWORD) + (sizeof(WORD) * 4))
+
+// forward declarations
+class CDefClient;
+typedef CDefClient FAR *LPCLIENT;
+
+class CDDEServer;
+typedef CDDEServer FAR *LPSRVR;
+typedef CDDEServer FAR *HDDE; // used by ClassFactory table
+
+
+PCALLCONTROL GetDdeCallControlInterface();
+void ReleaseDdeCallControlInterface();
+
+//
+// The wire representation of STDDOCDIMENSIONS is a 16-bit
+// format. This means instead of 4 longs, there are
+// 4 shorts. This structure is used below to pick the data
+// from the wire representation. Amazingly stupid, but
+// backward compatible is the name of the game.
+//
+typedef struct tagRECT16
+{
+ SHORT left;
+ SHORT top;
+ SHORT right;
+ SHORT bottom;
+
+} RECT16, *LPRECT16;
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertToFullHWND
+//
+// Synopsis: This function is used to convert a 16-bit HWND into a 32-bit
+// hwnd
+//
+// Effects: When running in a VDM, depending on who dispatches the message
+// we can end up with either a 16 or 32 bit window message. This
+// routine is used to make sure we always deal with a 32bit
+// HWND. Otherwise, some of our comparisions are incorrect.
+//
+// Arguments: [hwnd] -- HWND to convert. 16 or 32 bit is fine
+//
+// Returns: Always returns a 32 bit HWND
+//
+// History: 8-03-94 kevinro Created
+//
+// Notes:
+// This routine calls a private function given to use by OLETHK32
+//
+//----------------------------------------------------------------------------
+inline
+HWND ConvertToFullHWND(HWND hwnd)
+{
+ if (IsWOWThreadCallable() &&
+ ((((ULONG)hwnd & 0xFFFF0000) == 0) ||
+ (((ULONG)hwnd & 0xFFFF0000) == 0xFFFF0000)))
+ {
+ return(g_pOleThunkWOW->ConvertHwndToFullHwnd(hwnd));
+ }
+ return(hwnd);
+}
+
+inline
+void OleDdeDeleteMetaFile(HANDLE hmf)
+{
+ intrDebugOut((DEB_ITRACE,
+ "OleDdeDeleteMetaFile(%x)\n",
+ hmf));
+ if (IsWOWThreadCallable())
+ {
+ intrDebugOut((DEB_ITRACE,
+ "InWow: calling WOWFreeMetafile(%x)\n",
+ hmf));
+
+ if (!g_pOleThunkWOW->FreeMetaFile(hmf))
+ {
+ return;
+ }
+ intrDebugOut((DEB_ITRACE,
+ "WOWFreeMetafile(%x) FAILED\n",
+ hmf));
+ }
+ intrDebugOut((DEB_ITRACE,
+ "Calling DeleteMetaFile(%x)\n",
+ hmf));
+
+ DeleteMetaFile((HMETAFILE)hmf);
+}
diff --git a/private/ole32/com/remote/dde/server/ddepack.h b/private/ole32/com/remote/dde/server/ddepack.h
new file mode 100644
index 000000000..ef250cafb
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/ddepack.h
@@ -0,0 +1,20 @@
+
+#ifdef WIN32
+extern "C"
+{
+#include <port1632.h>
+}
+
+#define MAKE_DDE_LPARAM(msg,lo,hi) PackDDElParam(msg,(UINT)lo,(UINT)hi)
+
+#else
+
+#define GET_WM_DDE_EXECUTE_HDATA(wParam,lParam) ((HANDLE) HIWORD(lParam))
+#define GET_WM_DDE_DATA_HDATA(wParam,lParam) ((HANDLE) LOWORD(lParam))
+#define GET_WM_DDE_REQUEST_ITEM(wParam,lParam) ((ATOM) HIWORD(lParam))
+#define GET_WM_DDE_DATA_ITEM(wParam,lParam) ((ATOM) HIWORD(lParam))
+#define MAKE_DDE_LPARAM(msg,lo,hi) MAKELONG(lo,hi)
+#define DDEFREE(msg,lParam)
+
+#endif
+
diff --git a/private/ole32/com/remote/dde/server/ddesink.cxx b/private/ole32/com/remote/dde/server/ddesink.cxx
new file mode 100644
index 000000000..302db683e
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/ddesink.cxx
@@ -0,0 +1,251 @@
+// ddesink.cpp
+//
+// Methods for CDefClient::CAdviseSinkImpl
+//
+// Author:
+// Jason Fuller jasonful 8-16-92
+//
+// Copyright (c) 1990, 1991 Microsoft Corporation
+
+
+#include <ole2int.h>
+#include "srvr.h"
+#include "ddedebug.h"
+
+
+ASSERTDATA
+
+STDUNKIMPL_FORDERIVED (DefClient, AdviseSinkImpl)
+
+ BOOL PeekOneMessage
+ (MSG FAR* pmsg,
+ HWND hwnd,
+ UINT message)
+{
+ // We have to verify pmsg->message because PeekMessage will return
+ // WM_QUIT even if you didn't ask for it.
+
+ if (SSPeekMessage (pmsg, hwnd, message, message, PM_REMOVE))
+ {
+ if (pmsg->message==message)
+ return TRUE;
+ else
+ {
+ AssertSz (pmsg->message == WM_QUIT, "Unexpected message");
+ if (WM_QUIT==pmsg->message)
+ {
+ // Put message back
+ PostQuitMessage (pmsg->wParam);
+ }
+ return FALSE;
+ }
+ }
+ else
+ return FALSE;
+}
+
+
+
+
+
+
+STDMETHODIMP_(void) NC(CDefClient,CAdviseSinkImpl)::OnClose
+ (void)
+{
+ MSG msg;
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::OnClose\n",
+ this));
+
+ ChkC(m_pDefClient);
+
+ m_pDefClient->m_fInOnClose = TRUE;
+ // AddRef/Release safety bracket. Do not remove.
+ m_pDefClient->m_pUnkOuter->AddRef();
+
+ #ifdef _DEBUG
+ if (m_pDefClient->m_bContainer)
+ {
+ if (NOERROR != m_pDefClient->NoItemConnections())
+ Warn ("OnClose called on document before item");
+ }
+ #endif
+
+ if (m_pDefClient->m_ExecuteAck.f)
+ {
+ // in case the server closes in the middle of a DoVerb, send the ACK
+ // for the EXECUTE now to keep the messages in order.
+ m_pDefClient->SendExecuteAck (NOERROR);
+ }
+
+ if (!m_pDefClient->m_fGotStdCloseDoc)
+ {
+ // if client sent us StdCloseDocument, then he certainly
+ // is not in a state to receive callbacks
+ m_pDefClient->ItemCallBack (OLE_CLOSED);
+ }
+
+ // We have to check the message field because PeekMessage will return
+ // WM_QUIT even if you didn't ask for it.
+ if (PeekOneMessage (&msg, m_pDefClient->m_hwnd, WM_DDE_EXECUTE))
+ {
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_ACK,POSITIVE_ACK,
+ GET_WM_DDE_EXECUTE_HDATA(msg.wParam,msg.lParam));
+
+ intrDebugOut((DEB_ITRACE,
+ "%x ::OnClose found StdCloseDocument in queue\n",
+ this));
+
+ if(!PostMessageToClient ((HWND)msg.wParam,
+ WM_DDE_ACK,
+ (UINT) m_pDefClient->m_hwnd,
+ lp))
+ {
+ DDEFREE(WM_DDE_ACK,lp);
+ }
+
+ }
+
+
+ ChkC (m_pDefClient);
+
+ if (m_pDefClient->m_bContainer)
+ {
+ // If the document (container) is closing, then we
+ // should send a TERMINATE to the client windows.
+ // We don't do this for items because a client window
+ // may still be connected to another item.
+ // Items within one document share one window.
+
+ m_pDefClient->SendTerminateMsg ();
+ ChkC (m_pDefClient);
+ AssertIsDoc (m_pDefClient);
+ m_pDefClient->ReleaseAllItems();
+ }
+ else
+ {
+ m_pDefClient->RemoveItemFromItemList ();
+ }
+
+ // If item was deleted in client app, m_lpoleObj could be NULL
+ m_pDefClient->ReleaseObjPtrs ();
+
+ // If "this" is an item, get the doc that contains this item
+ LPCLIENT pdoc = m_pDefClient->m_pdoc;
+ Assert (pdoc);
+
+ Assert (pdoc->m_chk==chkDefClient);
+ if (pdoc->m_chk==chkDefClient && pdoc->m_fRunningInSDI)
+ if (pdoc->m_fRunningInSDI)
+ {
+ Puts ("Running in SDI\r\n");
+ // The server app never registered a class factory, so no
+ // RevokeClassFactory will trigger the destruction of the
+ // CDdeServer, so we do it here if there are no other clients
+ // connected to that CDdeServer
+ if (pdoc->m_psrvrParent->QueryRevokeClassFactory())
+ {
+ // Assert (No sibling documents)
+ Verify (NOERROR==pdoc->m_psrvrParent->Revoke());
+ pdoc->m_psrvrParent = NULL;
+ }
+ }
+ m_pDefClient->m_fInOnClose = FALSE;
+
+ // AddRef/Release safety bracket. Do not remove.
+ // Do not use m_pDefClient after this Release.
+ m_pDefClient->m_pUnkOuter->Release();
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::OnClose\n",
+ this));
+}
+
+
+
+
+STDMETHODIMP_(void) NC(CDefClient,CAdviseSinkImpl)::OnSave
+ (THIS)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::OnSave\n",
+ this));
+
+ ChkC(m_pDefClient);
+ if (!m_pDefClient->m_fInOleSave)
+ {
+ // If we called OleSave to get the native data, then of course
+ // we will get an OnSave notification.
+ m_pDefClient->ItemCallBack (OLE_SAVED);
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::OnSave\n",
+ this));
+}
+
+
+
+STDMETHODIMP_(void) NC(CDefClient,CAdviseSinkImpl)::OnDataChange
+ (THIS_ FORMATETC FAR* pFormatetc,
+ STGMEDIUM FAR* pStgmed)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::OnDataChange pFormatetc=%x\n",
+ this,
+ pFormatetc));
+ // note we are ignoring both the pformatetc and the pStgMed.
+ // ItemCallBack will ask (using GetData) for the data the client wants.
+ // We are treating a call to this function as a simple Ping.
+
+ ChkC(m_pDefClient);
+ m_pDefClient->ItemCallBack (OLE_CHANGED);
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::OnDataChange\n",
+ this));
+}
+
+
+
+STDMETHODIMP_(void) NC(CDefClient,CAdviseSinkImpl)::OnRename
+ (THIS_ LPMONIKER pmk)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::OnRename pmk=%x\n",
+ this,pmk));
+
+ LPOLESTR szFile=NULL;
+
+ ChkC(m_pDefClient);
+ if (Ole10_ParseMoniker (pmk, &szFile, NULL) != NOERROR)
+ {
+ // Wrong type of moniker
+ intrDebugOut((DEB_IERROR,
+ "%x ::OnRename pmk=%x wrong moniker\n",
+ this,pmk));
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%x ::OnRename pmk=%x pmk.Name=(%ws)\n",
+ this,
+ pmk,
+ WIDECHECK(szFile)));
+ // Notify client
+ m_pDefClient->ItemCallBack (OLE_RENAMED, szFile);
+ CoTaskMemFree(szFile);
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::OnRename\n",
+ this));
+}
+
+
+
+STDMETHODIMP_(void) NC(CDefClient,CAdviseSinkImpl)::OnViewChange
+ (THIS_ DWORD aspects, LONG lindex)
+{
+ // Response to IViewObjectAdvise::Advise, which we do not do
+}
+
+
diff --git a/private/ole32/com/remote/dde/server/ddesite.cxx b/private/ole32/com/remote/dde/server/ddesite.cxx
new file mode 100644
index 000000000..6f1a4e503
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/ddesite.cxx
@@ -0,0 +1,89 @@
+// ddesite.cpp
+//
+// Methods for CDefClient::COleClientSiteImpl
+//
+// Author:
+// Jason Fuller jasonful 8-16-92
+//
+// Copyright (c) 1990, 1991 Microsoft Corporation
+
+
+#include <ole2int.h>
+#include "srvr.h"
+#include "ddedebug.h"
+
+ASSERTDATA
+
+STDUNKIMPL_FORDERIVED (DefClient, OleClientSiteImpl)
+
+
+STDMETHODIMP NC(CDefClient,COleClientSiteImpl)::SaveObject
+ (void)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::SaveObject\n",
+ this));
+
+ ChkC(m_pDefClient);
+
+ if (!m_pDefClient->m_fGotStdCloseDoc)
+ m_pDefClient->ItemCallBack (OLE_SAVED);
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::SaveObject\n",
+ this));
+ return NOERROR;
+}
+
+
+
+STDMETHODIMP NC(CDefClient,COleClientSiteImpl)::GetContainer
+ (LPOLECONTAINER FAR * lplpContainer)
+{
+ VDATEPTROUT( lplpContainer, LPOLECONTAINER);
+ *lplpContainer = NULL;
+
+ ChkC(m_pDefClient);
+ return ResultFromScode (E_NOTIMPL);
+}
+
+
+
+STDMETHODIMP NC(CDefClient,COleClientSiteImpl)::GetMoniker
+ (DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER FAR* ppmk)
+{
+ VDATEPTROUT( ppmk, LPMONIKER);
+ *ppmk = NULL;
+
+ ChkC(m_pDefClient);
+ // OLE 1.0 does not support linking to embeddings
+ return ReportResult(0, E_NOTIMPL, 0, 0);
+}
+
+STDMETHODIMP NC(CDefClient,COleClientSiteImpl)::ShowObject
+ (void)
+{
+ ChkC(m_pDefClient);
+ Puts ("OleClientSite::ShowObject\r\n");
+ // REVIEW: what are we supposed do?
+ return ResultFromScode (E_NOTIMPL);
+}
+
+STDMETHODIMP NC(CDefClient,COleClientSiteImpl)::OnShowWindow
+ (BOOL fShow)
+{
+ ChkC(m_pDefClient);
+ Puts ("OleClientSite::OnShowWindow\r\n");
+ // REVIEW: what are we supposed do?
+ return NOERROR;
+}
+
+STDMETHODIMP NC(CDefClient,COleClientSiteImpl)::RequestNewObjectLayout(void)
+{
+ ChkC(m_pDefClient);
+ Puts ("OleClientSite::RequestNewObjectLayout\r\n");
+ return ReportResult(0, S_FALSE, 0, 0);
+}
+
+
+
diff --git a/private/ole32/com/remote/dde/server/ddesrvr.cxx b/private/ole32/com/remote/dde/server/ddesrvr.cxx
new file mode 100644
index 000000000..aa9c4f2fd
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/ddesrvr.cxx
@@ -0,0 +1,839 @@
+/*
+ ddesrvr.cpp
+
+ Author:
+ Jason Fuller jasonful 8-11-92
+*/
+
+#include <ole2int.h>
+#include <dde.h>
+#include <olerem.h>
+#include "srvr.h"
+#include "ddeatoms.h"
+#include "ddesrvr.h"
+#include "ddedebug.h"
+#include "map_up.h"
+
+#include "map_dwp.h"
+
+ASSERTDATA
+
+// Dde Common Window stuff
+
+UINT cCommonWindows = 0;
+
+#ifdef _CHICAGO_
+// Note: we have to create a unique string so that get
+// register a unique class for each 16 bit app.
+// The class space is global on chicago.
+//
+LPSTR szSYS_CLASSA = "Ole2SysWndClass 0x######## ";
+LPSTR szCLIENT_CLASSA = "Ole2ClientWndClass 0x######## ";
+LPSTR szSRVR_CLASSA = "SrvrWndClass 0x######## ";
+LPSTR szDOC_CLASSA = "ViewObjWndClass 0x######## ";
+LPSTR szITEM_CLASSA = "ItemWndClass 0x######## ";
+LPSTR szCOMMONCLASSA = "DdeCommonWindowClass 0x######## ";
+
+LPSTR szDdeServerWindow = "DDE Server Window";
+#define szDdeCommonWindowClass szCOMMONCLASSA
+#else
+const LPOLESTR szDdeServerWindow = OLESTR("DDE Server Window");
+const LPOLESTR szDdeCommonWindowClass = OLESTR("DdeCommonWindowClass");
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateDdeSrvrWindow
+//
+// Synopsis: When CoRegisterClassObject is called, this function
+// is called to create a DDE window to listen for DDE messages
+// from a 1.0 client.
+//
+// Effects:
+//
+// Arguments: [clsid] --
+// [aClass] --
+// [phwnd] --
+// [fIsRunning] --
+// [aOriginalClass] --
+// [cnvtyp] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-27-94 kevinro Commented/cleaned
+// 13-Jul-94 BruceMa Make register/unregister dde window class
+// thread safe
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CreateDdeSrvrWindow
+ (REFCLSID clsid,
+ ATOM aClass,
+ HWND FAR* phwnd, // optional out parm: created window
+ BOOL fIsRunning, // Is the item atom a file in the ROT?
+ ATOM aOriginalClass, // for TreatAs/ConvertTo case
+ CNVTYP cnvtyp)
+{
+ intrDebugOut((DEB_DDE_INIT,"0 _IN CreateDdeSrvrWindow\n"));
+
+ VDATEHEAP();
+ HWND hwnd = NULL;
+
+ HRESULT hresult = NOERROR;
+
+ DdeClassInfo ddeClassInfo;
+
+ ddeClassInfo.dwContextMask = CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER;
+ ddeClassInfo.fClaimFactory = FALSE;
+
+ // Null out parameter in case of error
+ if (phwnd)
+ {
+ *phwnd = NULL;
+ }
+
+ intrAssert (wIsValidAtom (aClass));
+
+ //
+ // See if this process is registered as a class server for
+ // the requested class. If it isn't, then check for a running
+ // object.
+ //
+ if (GetClassInformationForDde(clsid,&ddeClassInfo) == FALSE)
+ {
+ intrDebugOut((DEB_DDE_INIT,
+ "CreateDdeSrvrWindow No class information available\n"));
+
+ //
+ // The ClassObject was not found in the table.
+ //
+
+ if (fIsRunning)
+ {
+ // Link case.
+ // An SDI app was launched by the user (without "-Embedding").
+ // It did not register its class factory. (It never does.)
+ // Meanwhile, a DDE_INIT with a filename as an item atom was
+ // broadcasted.
+ // We are in the task of the SDI app that loaded that filename,
+ // so this function was called.
+ // So we need to create the window even though no class factory
+ // was registered.
+ // Call CDDEServer::Create with a lot of NULLs.
+ // Once the DDE_INIT is passed along to the server window, it
+ // should immediately cause a doc window to be created.
+ // Must be SDI or we wouldn't have this problem.
+ //
+ // This works because we are going to attempt to 'bind' to the
+ // object which is the subject of the link. If the link object
+ // was registered as running, we will find it. Otherwise, the
+ // attempt to create via the class factory will fail, since the
+ // class factory doesn't exist.
+ //
+
+ intrDebugOut((DEB_DDE_INIT,
+ "::CreateDdeServerWindow fIsRunning - override dwFlags\n"));
+
+ //
+ // NULL out the entire structure, then set only the flags
+ //
+ memset(&ddeClassInfo,0,sizeof(ddeClassInfo));
+ ddeClassInfo.dwFlags = REGCLS_SINGLEUSE;
+
+
+ }
+ else
+ {
+ intrDebugOut((DEB_DDE_INIT,
+ "CreateDdeServerWindow Returning FALSE\n"));
+
+ hresult = S_FALSE;
+ goto errRtn;
+ }
+ }
+ intrDebugOut((DEB_DDE_INIT,
+ "::CreateDdeServerWindow found class\n"));
+ // Create() does the real work: creates a CDDEServer and the window.
+ WCHAR szClass[MAX_STR];
+ lstrcpyW (szClass, wAtomName (aClass));
+ Assert (szClass[0]);
+
+ hresult = CDDEServer::Create(szClass,
+ clsid,
+ &ddeClassInfo,
+ &hwnd,
+ aOriginalClass,
+ cnvtyp);
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "CreateDdeServerWindow CDDEServer::Create returns %x\n",
+ hresult));
+ goto errRtn;
+ }
+
+ Assert (IsWindowValid(hwnd));
+
+ // Fill in out parameter
+ if (phwnd)
+ {
+ *phwnd = hwnd;
+ }
+
+
+errRtn:
+ VDATEHEAP();
+ intrDebugOut((DEB_DDE_INIT,
+ "0 _OUT CreateDdeSrvrWindow %x\n",
+ hresult));
+ return hresult;
+
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DestroyDdeSrvrWindow
+//
+// Synopsis: Destroy a DDE server window
+//
+// Effects:
+//
+// Arguments: [hwnd] -- Window to destroy
+// [aClass] -- Class for server
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-24-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL DestroyDdeSrvrWindow
+ (HWND hwnd,
+ ATOM aClass)
+{
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN DestroyDdeSrvrWindow\n"));
+ VDATEHEAP();
+ Assert (IsAtom (aClass));
+
+ // Make sure it is a server window
+ RetZ (IsWindowValid (hwnd));
+ RetZ (GetWindowWord (hwnd, WW_LE) == WC_LE);
+
+
+ // Get the Common window for this task.
+
+ HWND hwndCommonServer = (HWND)TLSGetDdeServer();
+
+ if (hwndCommonServer == NULL)
+ {
+ intrDebugOut((DEB_IERROR,"hwndCommonServer != NULL\n"));
+ return(E_UNEXPECTED);
+ }
+ if (!IsWindow(hwndCommonServer))
+ {
+ intrAssert(IsWindow(hwndCommonServer));
+ return(E_UNEXPECTED);
+ }
+
+ // Get the map from the common window
+ CMapUintPtr FAR *pmapClassToHwnd;
+ Assert (sizeof (CMapUintPtr FAR *)==sizeof(LONG));
+ pmapClassToHwnd = (CMapUintPtr FAR *) GetWindowLong (hwndCommonServer, 0);
+ Assert (pmapClassToHwnd);
+
+ // Make sure the window we're deleting is the server window for this class
+ void *hwndSrvr;
+ RetZ (pmapClassToHwnd->Lookup (aClass,hwndSrvr) && hwndSrvr == hwnd);
+
+ RetZ (SSDestroyWindow (hwnd));
+
+ // Remove this window from the map
+ pmapClassToHwnd->RemoveKey (aClass);
+
+ VDATEHEAP();
+ intrDebugOut((DEB_ITRACE,
+ "0 _OUT DestroyDdeSrvrWindow\n"));
+
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DdeCommonWndProc
+//
+// Synopsis: Window proc for the common dde server window that
+// listens for all WM_DDE_INITIATEs
+//
+// Effects: When a DDE_INITIATE comes in, this routine will determine
+// the class of the object being requested. If the class is
+// served by this thread, then it will create a window to
+// converse with the server.
+//
+// Arguments: [hWnd] -- hWnd of Common DDE
+// [wMsg] -- msg
+// [wParam] -- Return Window to converse with
+// [lParam] -- HIWORD(aItem) LOWORD(aClass)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-27-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+// When running in a VDM, it is possible that this window was dispatched
+// without having a full window handle. This happens when the getmessage
+// was dispatched from 16-bit. Therefore, we need to convert the hwnd to
+// a full hwnd before doing any comparision functions.
+//
+//----------------------------------------------------------------------------
+STDAPI_(LRESULT)
+DdeCommonWndProc(HWND hwndIn, UINT wMsg, WPARAM wParam, LPARAM lParam)
+{
+
+ switch (wMsg)
+ {
+ case WM_DDE_INITIATE:
+ {
+ VDATEHEAP();
+ ATOM aClass = LOWORD(lParam);
+ ATOM aItem = HIWORD(lParam);
+ HWND hwnd;
+
+ CNVTYP cnvtyp = cnvtypNone;
+
+ BOOL fIsFile= FALSE; // Must initialize
+ BOOL fIsRunning= FALSE; // Must initialize
+ BOOL fUnsavedDoc = FALSE; // Is the "file" really an unsaved doc
+ HWND hwndServer;
+ HRESULT hresult;
+
+
+ //
+ // From this point forward, we need to insure we are using a
+ // FULL hwnd.
+ //
+ hwnd = ConvertToFullHWND(hwndIn);
+
+ //
+ // The following should already be initialized
+ //
+ intrAssert (aOLE != NULL);
+ intrAssert (aSysTopic != NULL);
+
+ if (aItem==aOLE || aItem==aSysTopic
+ || (fIsFile=IsFile (aItem, &fUnsavedDoc)))
+ {
+
+
+ intrDebugOut((DEB_DDE_INIT,
+ "DdeCommonWndProc:hWnd(%x) DDE_INITIATE cls(%ws)\n",
+ hwnd,
+ wAtomName(aClass)));
+
+ //
+ // Get the ClassToHwnd map for this thread
+ //
+ CMapUintPtr FAR *pmapClassToHwnd;
+ Assert (sizeof (CMapUintPtr FAR *)==sizeof(LONG));
+ pmapClassToHwnd = (CMapUintPtr FAR *) GetWindowLong (hwnd, 0);
+ Assert (pmapClassToHwnd);
+
+
+ // Convert atom to CLSID, taking into account
+ // TreatAs and AutoConvert.
+ CLSID clsid;
+ ATOM aOriginalClass = aClass;
+
+ if (CLSIDFromAtomWithTreatAs (&aClass, &clsid, &cnvtyp) != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,"Could not get clsid for this class\n"));
+ return 0L;
+ }
+
+ void *pServerTmp;
+ if (TRUE == pmapClassToHwnd->Lookup (aClass, pServerTmp))
+ {
+ //
+ // Since a server window for this class already exists, but is a child window
+ // of ours, we will send it this message directly.
+ //
+
+ intrDebugOut((DEB_DDE_INIT,
+ "DdeCommonWndProc Server cls exists. Forwarding to %x\n",
+ pServerTmp));
+
+ return SSSendMessage ((HWND)pServerTmp, WM_DDE_INITIATE, wParam,lParam);
+
+ }
+
+ if (CoIsOle1Class (clsid))
+ {
+ // We have no business intercepting Initiates sent
+ // to 1.0 servers
+ intrDebugOut((DEB_DDE_INIT,
+ "DdeCommonWndProc: Its a OLE 1.0 class\n"));
+ return 0L;
+ }
+
+ if (fIsFile)
+ {
+ // Link case
+ WCHAR szFile[MAX_STR];
+
+ WORD cb=GlobalGetAtomName (aItem, szFile, MAX_STR);
+ Assert (cb>0 && cb < MAX_STR-1);
+ intrDebugOut((DEB_DDE_INIT,
+ "Looking for file %ws\n",szFile));
+
+ IsRunningInThisTask (szFile, &fIsRunning);
+ }
+
+ // If it's not a file, it can't be running, obviously.
+ intrAssert (fIsFile || !fIsRunning);
+
+ if (NOERROR == (hresult=(CreateDdeSrvrWindow (clsid,
+ aClass,
+ &hwndServer,
+ fIsRunning,
+ aOriginalClass,
+ cnvtyp))))
+ {
+
+ // Indicate that we have created a server window
+ // for this class. We could have used any value in
+ // place of hwndServer_. It's just a flag.
+ // REVIEW jasonful: how to handle OOM?
+
+ pmapClassToHwnd->SetAt (wDupAtom(aClass), hwndServer);
+
+#if DBG == 1
+ // Verify the SetAt we just did.
+ void FAR* pv;
+ Verify (pmapClassToHwnd->Lookup(aClass, pv));
+ Assert (pv == hwndServer);
+#endif
+ // Pass the INITIATE along to the real,
+ // newly-created server window and forge
+ // the sender's hwnd to be whoever called
+ // the common server window.
+ // SendMessage should return 1L is doc is running,
+ // indicating an ACK was sent.
+ Assert (IsWindowValid (hwndServer));
+ SSSendMessage (hwndServer, WM_DDE_INITIATE, wParam,lParam);
+ intrDebugOut((DEB_DDE_INIT,
+ "DdeCommonWndProc:hWnd(%x) DDE_INITIATE complete(%ws)\n",
+ hwnd,
+ wAtomName(aClass)));
+ VDATEHEAP();
+ }
+ else
+ {
+ if (S_FALSE!=GetScode(hresult))
+ {
+ intrDebugOut((DEB_IERROR,
+ "DCWP: CreateDdeSrvrWindow failed %x\n",
+ hresult));
+ }
+ }
+ }
+ else
+ {
+ //
+ // We have a DDE_INITIATE message that needs to be forwarded to our
+ // child window.
+ //
+ return SendMsgToChildren(hwnd,wMsg,wParam,lParam);
+ }
+ return 0L;
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ //
+ // When this window is destroyed, we cleanup the
+ // windows attached data.
+ //
+
+ CMapUintPtr FAR *pmapClassToHwnd;
+ pmapClassToHwnd = (CMapUintPtr FAR *) GetWindowLong (hwndIn, 0);
+
+ //
+ // Make sure there are no server windows
+ // created by this common window still extant. If there are, print out
+ // a message on a debug build. Otherwise, there really isn't much we
+ // can do about it. We are already closing down. The DDE emulation layer
+ // will send appropriate terminate messages.
+ //
+
+ #if DBG == 1
+ if (pmapClassToHwnd && !pmapClassToHwnd->IsEmpty())
+ {
+ intrDebugOut((DEB_ERROR,
+ "DCDW Leaking active OLE 1.0 clients\n"));
+ intrDebugOut((DEB_ERROR,
+ "There were active OLE 1.0 connections at shutdown\n"));
+ }
+ #endif
+ delete pmapClassToHwnd;
+ return(0);
+ }
+
+
+
+ default:
+ return SSDefWindowProc (hwndIn, wMsg, wParam, lParam);
+ }
+}
+
+
+
+
+ COleStaticMutexSem commonDdeMutex;
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateCommonDdeWindow
+//
+// Synopsis: Creates a DDE window for initiating conversations with this
+// threads objects.
+//
+// Effects: Creates a window that responds to DDE_INITIATE messages, and
+// determines if it needs to respond to the INITIATE. This
+// routine is called by OleInitializeEx()
+//
+// The handle to the created window is placed in the TLS
+// structure.
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-27-94 kevinro Converted to OLE32
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CreateCommonDdeWindow
+ (void)
+{
+ intrDebugOut((DEB_ITRACE,"%p _IN CreateCommonDdeWindow\n",0));
+
+ HRESULT hr = NOERROR;
+ HWND hwndDdeServer;
+ //
+ // If a DdeServer window already exists, then return NOERROR.
+ // If Com has been initialized but Ole has not, then we dont
+ // create a window, we just return NOERROR. This way, COM-only
+ // servers dont start serving OLE1 clients.
+ //
+
+ COleTls tls;
+ hwndDdeServer = tls->hwndDdeServer;
+ if ( hwndDdeServer != NULL || tls->cOleInits == 0)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "CreateCommonDocWindow: HWND(%x) cOleInits(%x)\n",
+ hwndDdeServer,
+ tls->cOleInits));
+ goto exitRtn;
+ }
+
+ //
+ // Only need to register the window class once per
+ // process so we protect it via a critical section
+ //
+ {
+ COleStaticLock lck(commonDdeMutex);
+
+ if (0 == cCommonWindows)
+ {
+ // Register "DDE Common window" class
+ //
+ DDEWNDCLASS wc;
+ wc.style = 0;
+ wc.lpfnWndProc = DdeCommonWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = sizeof (CMapUintPtr FAR*);
+ Assert (g_hmodOLE2);
+ wc.hInstance = g_hmodOLE2;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = szDdeCommonWindowClass;
+
+ if (!DdeRegisterClass(&wc) )
+ {
+ //
+ // It is possible that the register has failed because
+ // the class was previously registered, but failed to
+ // unregister. We are ignoring it, because if the
+ // class really couldn't register, then the CreateWindow
+ // will fail, which is what we really care about anyway.
+ //
+ intrDebugOut((DEB_IERROR,
+ "RegisterClass() %s has failed %x\n", szDdeCommonWindowClass,
+ GetLastError()));
+ intrAssert(!"CreateCommonDdeWindow register failed.");
+
+ }
+ }
+
+ cCommonWindows++;
+ }
+
+ if (!(hwndDdeServer = DdeCreateWindowEx(0, szDdeCommonWindowClass,
+ szDdeServerWindow,
+ WS_POPUP,0,0,0,0,
+ NULL,NULL,
+ g_hmodOLE2, NULL)))
+ {
+ intrDebugOut((DEB_IERROR,
+ "CreateCommonDocWindow() has failed %x\n",
+ GetLastError()));
+
+ hr = E_OUTOFMEMORY;
+ goto exitRtn;
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "CreateCommonDocWindow() hwndDdeServer=%x\n",
+ hwndDdeServer));
+
+ // Give the common window a map from classes to server windows
+
+ CMapUintPtr FAR *pmapClassToHwnd;
+
+ Assert (sizeof(LONG)==sizeof (CMapUintPtr FAR*));
+
+ if ((pmapClassToHwnd = new CMapUintPtr) == NULL)
+ {
+ intrDebugOut((DEB_ERROR,"pmapClassToHwnd != NULL\n"));
+ hr = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ SetWindowLong (hwndDdeServer, 0, (LONG)pmapClassToHwnd);
+ //
+ // Set the pointer to the server in the TLS data
+ //
+ tls->hwndDdeServer = hwndDdeServer;
+
+ hr = NOERROR;
+
+exitRtn:
+
+ intrDebugOut((DEB_ITRACE,"%p _OUT CreateCommonDocWindow (%x)\n",0,hr));
+
+ return(hr);
+
+ //
+ // In the error case, if the hwnDdeServer != NULL, then destroy it
+ //
+errRtn:
+ if (hwndDdeServer != NULL)
+ {
+ SSDestroyWindow(hwndDdeServer);
+ }
+
+ goto exitRtn;
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DestroyCommonDdeWindow
+//
+// Synopsis: Destroys the common DDE Server window
+//
+// Effects:
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-27-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL DestroyCommonDdeWindow
+ (void)
+{
+ intrDebugOut((DEB_ITRACE,"%p _IN DestroyCommonDdeWindow\n",0));
+
+ HRESULT hr = NOERROR;
+ HWND hwndDdeServer = (HWND)TLSGetDdeServer();
+
+ if (hwndDdeServer == NULL)
+ {
+ hr = E_UNEXPECTED;
+ goto errRtn;
+ }
+#if 0
+ // We do not need to validate this window since we created it!
+ if (!IsWindowValid(hwndDdeServer))
+ {
+ intrAssert(!"IsWindowValid");
+ hr = E_UNEXPECTED;
+ goto errRtn;
+ }
+#endif
+ //
+ // Get the map from the common window
+ //
+
+
+ //
+ // If destroying this window fails, there isn't much we can
+ // do about it.
+ //
+ if(!SSDestroyWindow (hwndDdeServer))
+ {
+ intrAssert(!"DestroyWindow");
+ hr = E_UNEXPECTED;
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE,
+ "DestroyCommonDocWindow() hwndDdeServer=%x\n",
+ hwndDdeServer));
+
+ // Must take a mutex around unregistering the class because another
+ // thread may be trying to register the window class at the same time
+ COleStaticLock lck(commonDdeMutex);
+
+ cCommonWindows--;
+
+ if (cCommonWindows == 0)
+ {
+ if(!DdeUnregisterClass (szDdeCommonWindowClass, g_hmodOLE2))
+ {
+ intrDebugOut((DEB_ERROR,
+ "DestroyCommonDocWindow(): UnregisterClass has failed error:>%x<\n",
+ GetLastError()));
+ intrAssert(!"DestroyCommonDdeWindow unregister failed.");
+ //
+ // If unregistering the class fails, there isn't a
+ // whole lot we can do about it. Its possible that
+ // there were still active client windows.
+ //
+ hr = E_UNEXPECTED;
+ }
+ }
+ }
+
+ if(!TLSSetDdeServer(NULL))
+ {
+ intrAssert(!"TLSSetDdeServer failed\n");
+ hr = E_UNEXPECTED;
+ }
+errRtn:
+ intrDebugOut((DEB_ITRACE,"%p _OUT DestroyCommonDdeWindow %x\n",0,hr));
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsRunningInThisTask
+//
+// Synopsis: Determine if the given file is running in the current task
+//
+// Effects: Calls a special function in the ROT to determine if the
+// file szFile is loaded as a moniker in the current task
+//
+// Arguments: [szFile] -- Filename
+// [pf] -- Points to a BOOL. Returned TRUE if running
+//
+// History: 6-29-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL IsRunningInThisTask(LPOLESTR szFileIn,BOOL FAR* pf) // out parm
+{
+ HRESULT hresult;
+
+ intrDebugOut((DEB_DDE_INIT,
+ "IsRunninginThisTask szFileIn=%ws\n",
+ WIDECHECK(szFileIn)));
+
+ //
+ // The RunningObjectTable always stores LONG filenames, therefore we
+ // need to convert this name to the long name for the lookup.
+ //
+
+ WCHAR szFile[MAX_PATH];
+ if ((lstrlenW(szFileIn) == 0) || (GetLongPathNameW(szFileIn,szFile,MAX_PATH) == 0))
+ {
+ //
+ // Unable to determine a long path for this object. Use whatever we were
+ // handed.
+ //
+ intrDebugOut((DEB_DDE_INIT,"No conversion to long path. Copy szFileIn\n"));
+ lstrcpyW(szFile,szFileIn);
+ }
+
+ intrDebugOut((DEB_DDE_INIT,"Long file szFile(%ws)\n",szFile));
+
+ hresult = GetLocalRunningObjectForDde(szFile,NULL);
+
+ *pf = (hresult == S_OK);
+
+ intrDebugOut((DEB_DDE_INIT,
+ "IsRunninginThisTask szFile=%ws returns %s\n",
+ WIDECHECK(szFile),
+ *pf?"TRUE":"FALSE"));
+ return NOERROR;
+}
diff --git a/private/ole32/com/remote/dde/server/ddesrvr.h b/private/ole32/com/remote/dde/server/ddesrvr.h
new file mode 100644
index 000000000..291b2c389
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/ddesrvr.h
@@ -0,0 +1,26 @@
+/*
+ ddesrvr.h
+ Header file for ddesrvr.cpp
+
+ Author:
+ Jason Fuller jasonful 8-11-92
+*/
+
+#ifndef fDdesrvr_h
+#define fDdesrvr_h
+
+// Defined in cftable.cpp
+STDAPI RemGetInfoForCid
+ (REFCLSID clsid,
+ LPDWORD pgrf,
+ LPCLASSFACTORY FAR* ppCF,
+ LPHANDLE FAR* pphwndDde,
+ BOOL FAR* FAR* ppfAvail,
+ BOOL fEvenIfHidden=FALSE);
+
+INTERNAL DestroyDdeSrvrWindow (HWND hwnd, ATOM aClass);
+INTERNAL CreateCommonDdeWindow (void);
+INTERNAL DestroyCommonDdeWindow (void);
+
+INTERNAL IsRunningInThisTask (LPOLESTR szFile, BOOL FAR* pf);
+#endif
diff --git a/private/ole32/com/remote/dde/server/ddeutils.cxx b/private/ole32/com/remote/dde/server/ddeutils.cxx
new file mode 100644
index 000000000..272a6a2f1
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/ddeutils.cxx
@@ -0,0 +1,1015 @@
+/****************************** Module Header ******************************\
+* Module Name: ddeutils.c
+*
+* Purpose: Conatains all the utility routines
+*
+* Created: 1990
+*
+* Copyright (c) 1990, 1991 Microsoft Corporation
+*
+* History:
+* Raor, Srinik (../../1990) Designed and coded
+*
+\***************************************************************************/
+#include <windows.h>
+#include "ole2int.h"
+//#include "cmacs.h"
+#include <dde.h>
+#include "srvr.h"
+#include "ddesrvr.h"
+#include "ddedebug.h"
+ASSERTDATA
+
+
+#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
+#define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
+
+
+
+#define KB_64 65536
+
+extern ATOM aTrue;
+extern ATOM aFalse;
+
+extern ATOM aStdCreateFromTemplate;
+extern ATOM aStdCreate;
+extern ATOM aStdOpen;
+extern ATOM aStdEdit;
+extern ATOM aStdShowItem;
+extern ATOM aStdClose;
+extern ATOM aStdExit;
+extern ATOM aStdDoVerbItem;
+
+
+//ScanBoolArg: scans the argument which is not included in
+//the quotes. These args could be only TRUE or FALSE for
+//the time being. !!!The scanning routines should be
+//merged and it should be generalized.
+
+INTERNAL_(LPSTR) ScanBoolArg
+(
+LPSTR lpstr,
+BOOL FAR *lpflag
+)
+{
+
+
+ LPSTR lpbool;
+ ATOM aShow;
+ char ch;
+
+ lpbool = lpstr;
+
+ // !!! These routines does not take care of quoted quotes.
+
+ while((ch = *lpstr) && (!(ch == ')' || ch == ',')))
+ lpstr++;
+
+ if(ch == NULL)
+ return NULL;
+
+ *lpstr++ = NULL; // terminate the arg by null
+
+ // if terminated by paren, then check for end of command
+ // syntax.
+
+ // Check for the end of the command string.
+ if (ch == ')') {
+ if (*lpstr++ != ']')
+ return NULL;
+
+ if(*lpstr != NULL)
+ return NULL; //finally should be terminated by null.
+
+ }
+
+ aShow = GlobalFindAtomA (lpbool);
+ if (aShow == aTrue)
+ *lpflag = TRUE;
+
+ else {
+ if (aShow ==aFalse)
+ *lpflag = FALSE;
+ else
+ return NULL;;
+ }
+ return lpstr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateUnicodeFromAnsi
+//
+// Synopsis: Creates a UNICODE string from an ANSI string
+//
+// Effects: Makes a new UNICODE string from the given ANSI string.
+// The new UNICODE string is returned. Memory is allocated
+// using PrivMemAlloc
+//
+// Arguments: [lpAnsi] -- Ansi version of string
+//
+// Requires:
+//
+// Returns: NULL if cannot create new string.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-07-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+LPOLESTR CreateUnicodeFromAnsi( LPCSTR lpAnsi)
+{
+ WCHAR buf[MAX_PATH];
+ ULONG ccbuf;
+ LPOLESTR lpWideStr;
+
+ if ((ccbuf=MultiByteToWideChar(CP_ACP,0,lpAnsi,-1,buf,MAX_PATH))
+ == FALSE)
+ {
+ intrAssert(!"Unable to convert characters");
+ return NULL;
+ }
+
+ lpWideStr = (LPOLESTR) PrivMemAlloc(ccbuf * sizeof(WCHAR));
+
+ if (lpWideStr != NULL)
+ {
+ memcpy(lpWideStr,buf,ccbuf*sizeof(WCHAR));
+ }
+ return(lpWideStr);
+}
+//+---------------------------------------------------------------------------
+//
+// Function: CreateAnsiFromUnicode
+//
+// Synopsis: Creates an Ansi string from a UNICODE string
+//
+// Effects: Makes a new ANSI string from the given UNICODE string.
+// The new string is returned. Memory is allocated
+// using PrivMemAlloc
+//
+// Arguments: [lpUnicode] -- Unicode version of string
+//
+// Requires:
+//
+// Returns: NULL if cannot create new string.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-07-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+LPSTR CreateAnsiFromUnicode( LPCOLESTR lpUnicode)
+{
+ char buf[MAX_PATH];
+ ULONG ccbuf;
+ LPSTR lpAnsiStr;
+
+ ccbuf = WideCharToMultiByte(CP_ACP,
+ 0,
+ lpUnicode,
+ -1,
+ buf,
+ MAX_PATH,
+ NULL,
+ NULL);
+
+
+ if (ccbuf == FALSE)
+ {
+ intrAssert(!"Unable to convert characters");
+ return NULL;
+ }
+
+ lpAnsiStr = (LPSTR) PrivMemAlloc(ccbuf * sizeof(char));
+
+ if (lpAnsiStr != NULL)
+ {
+ memcpy(lpAnsiStr,buf,ccbuf);
+ }
+ return(lpAnsiStr);
+}
+
+//ScannumArg: Checks for the syntax of num arg in Execute and if
+//the arg is syntactically correct, returns the ptr to the
+//beginning of the next arg and also, returns the number
+//Does not take care of the last num arg in the list.
+
+INTERNAL_(LPSTR) ScanNumArg
+(
+LPSTR lpstr,
+LPINT lpnum
+)
+{
+
+ WORD val = 0;
+ char ch;
+
+ while((ch = *lpstr++) && (ch != ',')) {
+ if (ch < '0' || ch >'9')
+ return NULL;
+ val += val * 10 + (ch - '0');
+
+ }
+
+ if(!ch)
+ return NULL;
+
+ *lpnum = val;
+ return lpstr;
+}
+
+
+
+
+//ScanArg: Checks for the syntax of arg in Execute and if
+//the arg is syntactically correct, returns the ptr to the
+//beginning of the next arg or to the end of the excute string.
+
+INTERNAL_(LPSTR) ScanArg
+(
+LPSTR lpstr
+)
+{
+
+
+ // !!! These routines does not take care of quoted quotes.
+
+ // first char should be quote.
+
+ if (*(lpstr-1) != '\"')
+ return NULL;
+
+ while(*lpstr && *lpstr != '\"')
+ lpstr++;
+
+ if(*lpstr == NULL)
+ return NULL;
+
+ *lpstr++ = NULL; // terminate the arg by null
+
+ if(!(*lpstr == ',' || *lpstr == ')'))
+ return NULL;
+
+
+ if(*lpstr++ == ','){
+
+ if(*lpstr == '\"')
+ return ++lpstr;
+ // If it is not quote, leave the ptr on the first char
+ return lpstr;
+ }
+
+ // terminated by paren
+ // already skiped right paren
+
+ // Check for the end of the command string.
+ if (*lpstr++ != ']')
+ return NULL;
+
+ if(*lpstr != NULL)
+ return NULL; //finally should be terminated by null.
+
+ return lpstr;
+}
+
+// ScanCommand: scanns the command string for the syntax
+// correctness. If syntactically correct, returns the ptr
+// to the first arg or to the end of the string.
+
+INTERNAL_(WORD) ScanCommand
+(
+LPSTR lpstr,
+WORD wType,
+LPSTR FAR * lplpnextcmd,
+ATOM FAR * lpAtom
+)
+{
+ // !!! These routines does not take care of quoted quotes.
+ // and not taking care of blanks arround the operators
+
+ // !!! We are not allowing blanks after operators.
+ // Should be allright! since this is arestricted syntax.
+
+ char ch;
+ LPSTR lptemp = lpstr;
+
+
+ while(*lpstr && (!(*lpstr == '(' || *lpstr == ']')))
+ lpstr++;
+
+ if(*lpstr == NULL)
+ return NULL;
+
+ ch = *lpstr;
+ *lpstr++ = NULL; // set the end of command
+
+ *lpAtom = GlobalFindAtomA (lptemp);
+
+ if (!IsOleCommand (*lpAtom, wType))
+ return NON_OLE_COMMAND;
+
+ if (ch == '(') {
+ ch = *lpstr++;
+
+ if (ch == ')') {
+ if (*lpstr++ != ']')
+ return NULL;
+ }
+ else {
+ if (ch != '\"')
+ return NULL;
+ }
+
+ *lplpnextcmd = lpstr;
+ return OLE_COMMAND;
+ }
+
+ // terminated by ']'
+
+ if (*(*lplpnextcmd = lpstr)) // if no nul termination, then it is error.
+ return NULL;
+
+ return OLE_COMMAND;
+}
+
+
+//MakeDataAtom: Creates a data atom from the item string
+//and the item data otions.
+
+INTERNAL_(ATOM) MakeDataAtom
+(
+ATOM aItem,
+int options
+)
+{
+ WCHAR buf[MAX_STR];
+
+ if (options == OLE_CHANGED)
+ return DuplicateAtom (aItem);
+
+ if (!aItem)
+ buf[0] = NULL;
+ else
+ GlobalGetAtomName (aItem, buf, MAX_STR);
+
+ if (options == OLE_CLOSED)
+ lstrcatW (buf, OLESTR("/Close"));
+ else {
+ if (options == OLE_SAVED)
+ lstrcatW (buf, OLESTR("/Save"));
+ else
+ AssertSz (0, "Bad option\n");
+ }
+
+ Puts ("MakeDataAtom "); Puts(buf); Putn();
+ if (buf[0])
+ return wGlobalAddAtom (buf);
+ else
+ return NULL;
+}
+
+//DuplicateAtom: Duplicates an atom
+INTERNAL_(ATOM) DuplicateAtom
+(
+ATOM atom
+)
+{
+ WCHAR buf[MAX_STR];
+
+ if (!atom)
+ return NULL;
+
+ GlobalGetAtomName (atom, buf, MAX_STR);
+ return wGlobalAddAtom (buf);
+}
+
+// MakeGlobal: makes global out of strings.
+// works only for << 64k
+
+INTERNAL_(HANDLE) MakeGlobal
+(
+LPSTR lpstr
+)
+{
+
+ int len = 0;
+ HANDLE hdata = NULL;
+ LPSTR lpdata = NULL;
+
+ len = strlen (lpstr) + 1;
+
+ hdata = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE, len);
+
+ if (hdata == NULL || (lpdata = (LPSTR) GlobalLock (hdata)) == NULL)
+ goto errRtn;
+
+
+ memcpy(lpdata, lpstr, (DWORD)len);
+ GlobalUnlock (hdata);
+ return hdata;
+
+errRtn:
+ Assert (0);
+ if (lpdata)
+ GlobalUnlock (hdata);
+
+
+ if (hdata)
+ GlobalFree (hdata);
+
+ return NULL;
+
+}
+
+
+INTERNAL_(BOOL) CLSIDFromAtom(ATOM aClass, LPCLSID lpclsid)
+{
+ WCHAR szProgID[MAX_STR];
+ if (!ISATOM (aClass))
+ return FALSE;
+ WORD cb=GlobalGetAtomName (aClass, szProgID, MAX_STR);
+ Assert (cb>0 && cb < (MAX_STR - 1));
+
+ return CLSIDFromProgID(szProgID, lpclsid) == S_OK;
+}
+
+// CLSIDFromAtomWithTreatAs
+//
+// Input: *paClass
+// Output: *pclsid == corresponding CLSID, taking into account TreatAs and
+// AutoConvert
+// *paClass == atom correpsonding to *pclsid
+//
+#pragma SEG(CLSIDFromAtomWithTreatAs)
+INTERNAL CLSIDFromAtomWithTreatAs
+ (ATOM FAR* paClass,
+ LPCLSID pclsid,
+ CNVTYP FAR* pcnvtyp)
+{
+ HRESULT hr;
+
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CLSIDFromAtomWithTreatAs(paClass=%x,"
+ "pclsid=%x,pcnvtyp=%x)\n",0,
+ paClass,pclsid,pcnvtyp));
+
+ LPOLESTR szProgID = NULL;
+ CLSID clsidNew;
+
+ if (!CLSIDFromAtom (*paClass, pclsid))
+ {
+ hr = S_FALSE;
+ goto exitRtn;
+ }
+
+ DEBUG_GUIDSTR(clsidStr,pclsid);
+
+ intrDebugOut((DEB_ITRACE,"Guid %ws",clsidStr));
+ if (CoGetTreatAsClass (*pclsid, &clsidNew) == NOERROR)
+ {
+ DEBUG_GUIDSTR(newStr,pclsid);
+
+ intrDebugOut((DEB_ITRACE," cnvtypTreatAs %ws\n",newStr));
+ if (pcnvtyp)
+ *pcnvtyp = cnvtypTreatAs;
+ }
+ else if (OleGetAutoConvert (*pclsid, &clsidNew) == NOERROR)
+ {
+ DEBUG_GUIDSTR(newStr,pclsid);
+ intrDebugOut((DEB_ITRACE," cnvtypConvertTo %ws\n",newStr));
+ if (pcnvtyp)
+ *pcnvtyp = cnvtypConvertTo;
+ }
+ else
+ {
+ intrDebugOut((DEB_ITRACE," no conversion\n"));
+ if (pcnvtyp)
+ *pcnvtyp = cnvtypNone;
+ clsidNew = *pclsid; // no translation
+ }
+
+ hr = ProgIDFromCLSID(clsidNew, &szProgID);
+ if (FAILED(hr))
+ {
+ intrDebugOut((DEB_ITRACE," ProgIDFromCLSID failed\n"));
+ goto exitRtn;
+ }
+
+ intrDebugOut((DEB_ITRACE,"ProgIDFromCLSID returns %ws\n",szProgID));
+ *paClass = GlobalAddAtom (szProgID);
+ *pclsid = clsidNew;
+ CoTaskMemFree(szProgID);
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%p OUT CLSIDFromAtomWithTreatAs returns %x\n",
+ 0,hr));
+
+ return hr;
+}
+
+
+INTERNAL_(BOOL) PostMessageToClientWithReply
+(
+HWND hWnd,
+UINT wMsg,
+WPARAM wParam, // posting window
+LPARAM lParam,
+UINT wReplyMsg
+)
+{
+ MSG msg;
+
+ if (!IsWindowValid (hWnd))
+ {
+ AssertSz(FALSE, "Client's window is missing");
+ return FALSE;
+ }
+
+ if (!IsWindowValid ((HWND)wParam))
+ {
+ AssertSz (0, "Posting window is invalid");
+ return FALSE;
+ }
+
+ // Post message to client failed. Treat it as if we got the reply.
+ if (!PostMessageToClient (hWnd, wMsg, wParam, lParam))
+ return FALSE;
+
+ return NOERROR == wTimedGetMessage (&msg, (HWND)wParam, WM_DDE_TERMINATE,
+ WM_DDE_TERMINATE);
+}
+
+
+
+INTERNAL_(BOOL) PostMessageToClient
+(
+ HWND hWnd,
+ UINT wMsg,
+ WPARAM wParam,
+ LPARAM lParam
+)
+{
+ UINT c=0;
+
+ while (c < 10)
+ {
+ if (!IsWindowValid (hWnd)) {
+ Warn ("Client's window is missing");
+ return FALSE;
+ }
+ Puts ("Posting"); Puth(wMsg); Puts("to"); Puth(hWnd); Putn();
+ if (PostMessage (hWnd, wMsg, wParam, lParam))
+ return TRUE; // success
+ else
+ {
+ Yield();
+ c++; // try again
+ }
+ }
+ return FALSE;
+}
+
+
+INTERNAL_(BOOL) IsWindowValid
+ (HWND hwnd)
+{
+ HTASK htask;
+
+ if (!IsWindow (hwnd))
+ return FALSE;
+
+ htask = GetWindowThreadProcessId(hwnd, NULL);
+
+#ifndef WIN32
+ if (IsTask(htask))
+#endif
+ return TRUE;
+
+ return FALSE;
+}
+
+
+
+INTERNAL_(BOOL) UtilQueryProtocol
+(
+ATOM aClass,
+LPOLESTR lpprotocol
+)
+{
+ HKEY hKey;
+ WCHAR key[MAX_STR];
+ WCHAR cclass[MAX_STR];
+
+ if (!aClass)
+ return FALSE;
+
+ if (!GlobalGetAtomName (aClass, cclass, MAX_STR))
+ return FALSE;
+
+ lstrcpyW (key, cclass);
+ lstrcatW (key, OLESTR("\\protocol\\"));
+ lstrcatW (key, lpprotocol);
+ lstrcatW (key, OLESTR("\\server"));
+ if (RegOpenKey (HKEY_CLASSES_ROOT, key, &hKey) != ERROR_SUCCESS)
+ return FALSE;
+ RegCloseKey (hKey);
+ return TRUE;
+}
+
+
+
+INTERNAL_(BOOL) IsOleCommand
+(
+ATOM aCmd,
+WORD wType
+)
+{
+ if (wType == WT_SRVR) {
+ if ((aCmd == aStdCreateFromTemplate)
+ || (aCmd == aStdCreate)
+ || (aCmd == aStdOpen)
+ || (aCmd == aStdEdit)
+ || (aCmd == aStdShowItem)
+ || (aCmd == aStdClose)
+ || (aCmd == aStdExit))
+ return TRUE;
+ }
+ else {
+ if ((aCmd == aStdClose)
+ || (aCmd == aStdDoVerbItem)
+ || (aCmd == aStdShowItem))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+INTERNAL wFileBind
+ (LPOLESTR szFile,
+ LPUNKNOWN FAR* ppUnk)
+{
+ HRESULT hresult = NOERROR;
+ LPBC pbc = NULL;
+ LPMONIKER pmk = NULL;
+ *ppUnk = NULL;
+ ErrRtnH (CreateBindCtx (0, &pbc));
+ ErrRtnH (CreateFileMoniker (szFile, &pmk));
+ ErrRtnH (pmk->BindToObject (pbc, NULL, IID_IUnknown, (LPLPVOID) ppUnk));
+ errRtn:
+// AssertOutPtrIface(hresult, *ppUnk);
+ if (pbc)
+ pbc->Release();
+ if (pmk)
+ pmk->Release();
+ return hresult;
+}
+
+// SynchronousPostMessage
+//
+// Post a message and wait for the ack.
+// (jasonful)
+//
+INTERNAL SynchronousPostMessage
+ (HWND hWndTo, // also who you expect the reply from
+ UINT wMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+#ifdef _MAC
+#else
+
+ HRESULT hresult = NOERROR;
+
+ static unsigned iCounter;
+
+
+ HWND hWndFrom = (HWND) wParam;
+
+
+
+ RetZ (IsWindowValid(hWndFrom));
+ RetZ (IsWindowValid(hWndTo));
+
+ Assert (wMsg != WM_DDE_INITIATE); // can't check for positive ack.
+
+ RetZS (PostMessage (hWndTo, wMsg, wParam, lParam), RPC_E_SERVER_DIED);
+
+ MSG msg;
+ RetErr (wTimedGetMessage (&msg, hWndFrom, WM_DDE_ACK, WM_DDE_ACK));
+ Assert (msg.message == WM_DDE_ACK);
+ if (!( GET_WM_DDE_ACK_STATUS(msg.wParam,msg.lParam) & POSITIVE_ACK))
+ hresult = ResultFromScode (RPC_E_DDE_NACK);
+ if (msg.hwnd != hWndFrom)
+ hresult = ResultFromScode (RPC_E_DDE_UNEXP_MSG);
+
+
+
+ return hresult;
+#endif _MAC
+}
+
+
+INTERNAL wFileIsRunning
+ (LPOLESTR szFile)
+{
+ LPMONIKER pmk = NULL;
+ LPBINDCTX pbc=NULL;
+ HRESULT hresult;
+
+ RetErr (CreateBindCtx (0, &pbc));
+ ErrRtnH (CreateFileMoniker (szFile, &pmk));
+ hresult = pmk->IsRunning (pbc, NULL, NULL);
+ errRtn:
+ if (pbc)
+ pbc->Release();
+ if (pmk)
+ pmk->Release();
+ return hresult;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsFile
+//
+// Synopsis: Given a handle to an atom, determine if it is a file
+//
+// Effects: Attempts to get the files attributes. If there are no
+// attributes, then the file doesn't exist.
+//
+// Arguments: [a] -- Atom for filename
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-03-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_ (BOOL) IsFile
+ (ATOM a, BOOL FAR* pfUnsavedDoc)
+{
+ LPMONIKER pmk = NULL;
+ LPBC pbc = NULL;
+ LPRUNNINGOBJECTTABLE pROT=NULL;
+
+ WCHAR szFile [MAX_STR];
+ if (0==GlobalGetAtomName (a, szFile, MAX_STR))
+ return FALSE;
+
+ DWORD dwAttribs = GetFileAttributes(szFile);
+
+ /* flags prevent sharing violation*/
+ if (dwAttribs != 0xFFFFFFFF)
+ {
+ if (pfUnsavedDoc)
+ *pfUnsavedDoc = FALSE;
+ return TRUE;
+ }
+ // This will deal with unsaved documents in the ROT.
+ // We do NOT want to call pmk->IsRunning because if a 2.0 client called
+ // DdeIsRunning, we do not want call it here, because then we get stuck
+ // in an infinite loop. We only care about true 2.0 running objects.
+
+
+ //
+ // BUGBUG: KevinRo There is a function (GetPathFromRot) that could replace
+ // the following code sequence.
+ //
+
+ BOOL f= NOERROR==CreateBindCtx (0, &pbc) &&
+ NOERROR==CreateFileMoniker (szFile, &pmk) &&
+ NOERROR==pbc->GetRunningObjectTable (&pROT) &&
+ NOERROR==pROT->IsRunning (pmk) ;
+ if (pROT)
+ pROT->Release();
+ if (pmk)
+ pmk->Release();
+ if (pbc)
+ pbc->Release();
+ if (pfUnsavedDoc)
+ *pfUnsavedDoc = TRUE;
+ return f;
+
+
+}
+
+// wCompatibleClasses
+//
+// Determine if class "aClient" is Auto-Converted to class "aSrvr" or
+// Treated-As class "aSrvr".
+// (Does not check if aClient==aSrvr)
+//
+#pragma SEG(wCompatibleClasses)
+INTERNAL wCompatibleClasses
+ (ATOM aClient,
+ ATOM aSrvr)
+{
+ CLSID clsidClient, clsidSrvr, clsidTo;
+ HRESULT hresult;
+ RetZS (CLSIDFromAtom (aClient, &clsidClient), S_FALSE);
+ RetZS (CLSIDFromAtom (aSrvr, &clsidSrvr ), S_FALSE);
+ if (NOERROR==OleGetAutoConvert (clsidClient, &clsidTo)
+ && clsidTo == clsidSrvr)
+ {
+ // aClient is Auto-Converted to aSrvr
+ return NOERROR;
+ }
+ hresult = CoGetTreatAsClass(clsidClient, &clsidTo);
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "wCompatibleClasses CoGetTreatAs returns %x\n",
+ hresult));
+ return(hresult);
+ }
+
+ if (clsidTo == clsidSrvr)
+ {
+ // aClient is Treated-As aSrvr
+ return NOERROR;
+ }
+ return ResultFromScode (S_FALSE); // not compatible
+}
+
+
+
+// wCreateStgAroundNative
+//
+// Build an OLE2 storage around 1.0 native data by putting it in
+// stream "\1Ole10Native" and creating valid CompObj and OLE streams.
+// Return the IStorage and the ILockBytes it is built on.
+//
+INTERNAL wCreateStgAroundNative
+ (HANDLE hNative,
+ ATOM aClassOld,
+ ATOM aClassNew,
+ CNVTYP cnvtyp,
+ ATOM aItem,
+ LPSTORAGE FAR* ppstg,
+ LPLOCKBYTES FAR* pplkbyt)
+{
+ HRESULT hresult;
+ LPSTORAGE pstg = NULL;
+ LPLOCKBYTES plkbyt = NULL;
+ LPOLESTR szUserType = NULL;
+ WCHAR szClassOld [256];
+ CLSID clsid;
+ ATOM aClass;
+ *ppstg = NULL;
+
+ intrDebugOut((DEB_ITRACE,
+ "%p wCreateStgAroundNative(hNative=%x,aClassOld=%x"
+ ",aClassNew=%x cnvtyp=%x,aItem=%x)\n",
+ 0,hNative,aClassOld,aClassNew,cnvtyp,aItem));
+
+ // Create temporary docfile on our ILockBytes
+ ErrRtnH (CreateILockBytesOnHGlobal (NULL,/*fDeleteOnRelease*/TRUE,&plkbyt));
+
+ Assert (plkbyt);
+
+ ErrRtnH (StgCreateDocfileOnILockBytes (plkbyt, grfCreateStg, 0, &pstg));
+
+ RetZ (pstg);
+ Assert (NOERROR==StgIsStorageILockBytes(plkbyt));
+
+ aClass = (cnvtyp == cnvtypConvertTo)?aClassNew:aClassOld;
+
+ if (CLSIDFromAtom (aClass,(LPCLSID)&clsid) == FALSE)
+ {
+ hresult = REGDB_E_CLASSNOTREG;
+ goto errRtn;
+ }
+
+ ErrRtnH (WriteClassStg (pstg, clsid));
+
+ // The UserType always corresponds to the clsid.
+ ErrRtnH (OleRegGetUserType (clsid, USERCLASSTYPE_FULL, &szUserType));
+
+ // The format is always the 1.0 format (classname/progid)
+ ErrZS (GlobalGetAtomName (aClassOld, szClassOld, 256), E_UNEXPECTED);
+
+ ErrRtnH (WriteFmtUserTypeStg (pstg, RegisterClipboardFormat(szClassOld),
+ szUserType));
+
+
+ if (cnvtyp == cnvtypConvertTo)
+ {
+ // SetConvertStg also writes a complete default Ole Stream
+ ErrRtnH (SetConvertStg (pstg, TRUE));
+ }
+ else
+ {
+ ErrRtnH (WriteOleStg (pstg, NULL, (CLIPFORMAT)0, NULL));
+ }
+ ErrRtnH (StSave10NativeData (pstg, hNative, FALSE));
+ if (aItem)
+ {
+ ErrRtnH (StSave10ItemName (pstg, wAtomNameA (aItem)));
+ }
+ *ppstg = pstg;
+ *pplkbyt = plkbyt;
+ return NOERROR;
+
+ errRtn:
+ if (pstg)
+ pstg->Release();
+ if (plkbyt)
+ plkbyt->Release();
+ CoTaskMemFree(szUserType);
+ return hresult;
+}
+
+
+#ifdef _DEBUG
+
+
+INTERNAL_ (BOOL) IsAtom (ATOM a)
+{
+ WCHAR sz[256]= {0};
+ if (a < 0xc000)
+ return FALSE;
+ WORD cb=GlobalGetAtomName (a, sz, 256);
+ Assert (lstrlenW(sz) == (int) cb);
+ return cb>0 && cb < MAX_STR;
+}
+
+
+#include <limits.h>
+#undef GlobalFree
+
+
+
+
+INTERNAL_(HANDLE) wGlobalFree (HANDLE h)
+{
+ LPVOID p;
+ Assert ((GlobalFlags(h) & GMEM_LOCKCOUNT)==0);
+ if (!(p=GlobalLock(h)))
+ {
+ Puts ("Cannot free handle");
+ Puth (h);
+ Putn();
+ AssertSz(0, "Invalid Handle\r\n");
+ }
+ Assert (!IsBadReadPtr (p, (UINT) min (UINT_MAX, GlobalSize(h))));
+ Assert (GlobalUnlock(h)==0);
+ Verify (!GlobalFree (h));
+ Puts ("FREEING ");
+ Puth (h);
+ Putn ();
+ return NULL; // success
+}
+
+
+
+#undef GlobalDeleteAtom
+
+INTERNAL_(ATOM) wGlobalDeleteAtom (ATOM a)
+{
+ WCHAR sz[256];
+ Assert (0 != GlobalGetAtomName (a, sz, 256));
+ Assert (0==GlobalDeleteAtom (a));
+ return (ATOM)0;
+}
+
+INTERNAL_(int) wCountChildren
+ (HWND h)
+{
+ int c = 0;
+ HWND hwndChild = GetWindow (h, GW_CHILD);
+ while (hwndChild)
+ {
+ c++;
+ hwndChild = GetWindow (hwndChild, GW_HWNDNEXT);
+ }
+ return c;
+}
+
+
+#endif // _DEBUG
diff --git a/private/ole32/com/remote/dde/server/dirs b/private/ole32/com/remote/dde/server/dirs
new file mode 100644
index 000000000..94c45c76c
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/dirs
@@ -0,0 +1,37 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+
+
diff --git a/private/ole32/com/remote/dde/server/doc.cxx b/private/ole32/com/remote/dde/server/doc.cxx
new file mode 100644
index 000000000..3975d4d3e
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/doc.cxx
@@ -0,0 +1,1680 @@
+/***************************************************************************\
+* Module Name: Doc.c Document Main module
+*
+* Purpose: Includes All the document level object communication related.
+*
+* Created: Oct 1990.
+*
+* Copyright (c) 1990, 1991 Microsoft Corporation
+*
+* History:
+* Raor (../10/1990) Designed, coded (modified for 2.0)
+*
+\***************************************************************************/
+
+#include "ole2int.h"
+//#include "cmacs.h"
+#include <dde.h>
+
+#include "srvr.h"
+#include "ddedebug.h"
+#include "valid.h"
+ASSERTDATA
+
+extern ATOM aStdClose;
+extern ATOM aStdShowItem;
+extern ATOM aStdDoVerbItem;
+extern ATOM aStdDocName;
+extern ATOM aTrue;
+extern ATOM aFalse;
+
+extern HINSTANCE hdllInst;
+extern HANDLE hddeRename;
+extern HWND hwndRename;
+
+
+// HRESULT DdeHandleIncomingCall(HWND hwndCli, WORD wCallType);
+
+//
+// Call CoHandleIncomingCall which will call the message filter
+// Note: only call this functions with:
+// - CALLTYPE_TOPLEVEL ... for synchranous calls
+// - CALLTYPE_ASYNC ... for async calls
+//
+HRESULT DdeHandleIncomingCall(HWND hwndCli, WORD wCallType)
+{
+
+ Assert(!"DdeHandleIncomingCall not implemented");
+
+ return(RPC_E_CALL_REJECTED);
+
+ // Review: bug: get the correcr hwnd
+ switch ( /* CoHandleIncomingCall(hwndCli, wCallType, NULL) */ wCallType) {
+ default:
+ case SERVERCALL_ISHANDLED: // call can be proccesed
+ return NOERROR;
+
+ case SERVERCALL_REJECTED: // call rejected
+ return ResultFromScode(RPC_E_CALL_REJECTED);
+
+ case SERVERCALL_RETRYLATER: // call should be retried later
+ return ResultFromScode(RPC_E_DDE_BUSY);
+ }
+}
+
+
+INTERNAL CDefClient::Create
+(
+ LPSRVR lhOLESERVER,
+ LPUNKNOWN lpunkObj,
+ LPOLESTR lpdocName,
+ const BOOL fSetClientSite,
+ const BOOL fDoAdvise,
+ const BOOL fRunningInSDI, // optional
+ HWND FAR* phwnd // optional
+)
+{
+ LPSRVR lpsrvr = NULL;
+ LPCLIENT lpclient = NULL;
+ HANDLE hclient = NULL;
+ HRESULT hresult = NOERROR;
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN CDefClient::Create(lpsrvr=%x,lpdocName=%ws)\n",
+ lhOLESERVER,WIDECHECK(lpdocName)));
+
+ // REVIEW: server's termination has already started. Are
+ // we going to see this condition in the synchronous mode.
+ lpsrvr = (LPSRVR)lhOLESERVER;
+ if (lpsrvr && lpsrvr->m_bTerminate)
+ {
+ Assert(0);
+ return ReportResult(0, RPC_E_DDE_REVOKE, 0, 0);
+ }
+
+#ifdef FIREWALLS
+ PROBE_READ(lpunkObj);
+ PROBE_READ(lpmkObj);
+ PROBE_WRITE(lplhobj);
+#endif
+
+ lpclient = new CDefClient (/*pUnkOuter==*/NULL);;
+
+ lpclient->m_pCallControl = GetDdeCallControlInterface();
+
+ intrAssert(lpclient->m_pCallControl != NULL);
+
+ if (lpclient->m_pCallControl == NULL)
+ {
+ intrDebugOut((DEB_IWARN,
+ "CDefClient::Create(%ws) CallControlGet failed\n",
+ WIDECHECK(lpdocName)));
+
+ goto errRtn;
+ }
+
+
+ Assert(lpclient->m_pUnkOuter);
+
+ lpclient->m_aItem = wGlobalAddAtom (/*lpszObjName*/lpdocName);
+ lpclient->m_fRunningInSDI = fRunningInSDI;
+ lpclient->m_psrvrParent = lpsrvr;
+ // A doc has itself as its containing document
+ lpclient->m_pdoc = lpclient;
+
+ ErrRtnH (lpunkObj->QueryInterface (IID_IOleObject,
+ (LPLPVOID) &lpclient->m_lpoleObj));
+
+ ErrRtnH (lpunkObj->QueryInterface (IID_IDataObject,
+ (LPLPVOID) &lpclient->m_lpdataObj));
+
+ // Lock object; do after the QI so that ReleaseObjPtrs will unlock correctly
+ lpclient->m_fLocked =
+ (NOERROR==CoLockObjectExternal (lpunkObj, TRUE, /*dont care*/ FALSE));
+
+ if (!(lpclient->m_hwnd = SSCreateWindowExA(0, DOC_CLASSA,"DDE ViewObj",
+ WS_CHILD,0,0,0,0,lpsrvr->m_hwnd,NULL, hdllInst, NULL)))
+ {
+ intrDebugOut((DEB_ITRACE,"CDefClient::Create() couldn't create window\n"));
+ goto errRtn;
+ }
+
+
+ if (fDoAdvise)
+ {
+ // This is for Packager, in particular, and manual links.
+ // If client does not advise on any data, we still need
+ // to do an OLE advise so we can get OnClose notifications.
+ ErrRtnH (lpclient->DoOle20Advise (OLE_CLOSED, (CLIPFORMAT)0));
+ }
+
+ intrDebugOut((DEB_ITRACE," Doc window %x created\n",lpclient->m_hwnd));
+
+ // Set out parm (window)
+ if (phwnd != NULL)
+ {
+ *phwnd = lpclient->m_hwnd;
+ }
+
+ if (fSetClientSite)
+ {
+ // Should not set the client site if the object has not been
+ // initialized yet, by BindMoniker (i.e. PersistFile::Load)
+ // or PersistStorage::Load
+ if (lpclient->SetClientSite() != NOERROR)
+ {
+ goto errRtn;
+ }
+ }
+
+ Putsi(lpclient->m_cRef);
+
+ SetWindowLong (lpclient->m_hwnd, 0, (LONG)lpclient);
+ SetWindowWord (lpclient->m_hwnd, WW_LE, WC_LE);
+ SetWindowLong (lpclient->m_hwnd,WW_HANDLE,
+ (GetWindowLong (lpsrvr->m_hwnd, WW_HANDLE)));
+
+ hresult = NOERROR;
+
+exitRtn:
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _OUT CDefClient::Create(lpsrvr=%x,lpdocName=%ws) hr=%x\n",
+ lhOLESERVER,
+ WIDECHECK(lpdocName),
+ hresult));
+
+
+ return(hresult);
+errRtn:
+ intrDebugOut((DEB_ITRACE,"CDefClient::Create() in error handling routine\n"));
+ if (lpclient)
+ {
+ if (lpclient->m_pCallControl)
+ ReleaseDdeCallControlInterface();
+
+ if (lpclient->m_hwnd)
+ SSDestroyWindow (lpclient->m_hwnd);
+
+ if (lpclient->m_aItem)
+ GlobalDeleteAtom (lpclient->m_aItem);
+ delete lpclient;
+ }
+ hresult = E_OUTOFMEMORY;
+ goto exitRtn;
+}
+
+
+
+INTERNAL CDefClient::Revoke (BOOL fRelease)
+{
+ Puts ("DefClient::Revoke "); Puth(this); Puta(m_aItem); Putn();
+
+ ChkC(this);
+
+
+ ReleaseObjPtrs();
+
+ // We are done with this CDefClient but someone may still have a reference
+ // to an instance of one of our nested classes. In particular, an advise
+ // holder may be holding on to our sink, or an item may have a pointer
+ // to us if we are its parent document. So we cannot actually do a
+ // "delete this".
+ // The corresponding AddRef is in CDefClient::Create
+ // or CDefClient::RegisterItem
+
+ m_pUnkOuter->Release();
+
+ Puts ("DefClient::Revoke done\r\n");
+ return NOERROR;
+}
+
+
+
+INTERNAL CDefClient::ReleaseObjPtrs
+ (void)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CDefClient::ReleaseObjPtrs\n",
+ this));
+
+ ULONG ulResult;
+
+ if (m_lpoleObj && m_fLocked)
+ {
+ // Unlock object. Set m_fLocked to FALSE first to prevent reentrant
+ // problems (unlock causes close which causes this routine to be called)
+
+ m_fLocked = FALSE;
+ CoLockObjectExternal(m_lpoleObj, FALSE, TRUE);
+ }
+ if (m_lpoleObj)
+ {
+ if (m_fDidSetClientSite)
+ m_lpoleObj->SetClientSite(NULL);
+ DoOle20UnAdviseAll();
+ Assert (m_lpoleObj);
+ if (m_lpoleObj)
+ {
+ ulResult = m_lpoleObj->Release();
+ m_lpoleObj = NULL;
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT ::ReleaseObjPtrs lpoleObj ulResult=%x\n",
+ this,ulResult));
+ }
+ if (m_lpdataObj)
+ {
+ // Must do it this way because the Release can cause recursion
+ LPDATAOBJECT pdata = m_lpdataObj;
+ m_lpdataObj = NULL;
+ ulResult = pdata->Release();
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT ::ReleaseObjPtrs pdata ulResult=%x\n",
+ this,ulResult));
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT CDefClient::ReleaseObjPtrs\n",
+ this));
+ return NOERROR;
+}
+#if 000
+//RevokeAllDocs : revokes all the doc objects attached to a given
+//server.
+
+INTERNAL_(HRESULT) CDDEServer::RevokeAllDocObjs ()
+{
+
+ HWND hwnd;
+ HWND hwndnext;
+ LPCLIENT lpclient;
+ Puts ("RevokeAllDocObjs\r\n");
+ ChkS(this);
+
+ hwnd = GetWindow (m_hwnd, GW_CHILD);
+
+ // Go thru each of the child windows and revoke the corresponding
+ // document. Doc windows are child windows for the server window.
+
+ while (hwnd){
+ // sequence is important
+ hwndnext = GetWindow (hwnd, GW_HWNDNEXT);
+ lpclient = ((LPCLIENT)GetWindowLong (hwnd, 0));
+ lpclient->Revoke();
+ hwnd = hwndnext;
+ }
+ return NOERROR;
+}
+#endif
+
+// FindDoc: Given a doc obj, searches for the doc obj
+// in the given class factory tree. returns true if the
+// doc obj is available.
+
+
+INTERNAL_(LPCLIENT) CDDEServer::FindDocObj
+(
+LPSTR lpdocname
+)
+{
+ ATOM aItem;
+ HWND hwnd;
+ LPCLIENT lpclient;
+
+ ChkS(this);
+ aItem = (ATOM)GlobalFindAtomA (lpdocname);
+ Assert (IsWindowValid (m_hwnd));
+ hwnd = GetWindow (m_hwnd, GW_CHILD);
+ Assert (NULL==hwnd || IsWindowValid (hwnd));
+
+ while (hwnd)
+ {
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+ if (lpclient->m_aItem == aItem)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "FindDocObj found %s lpclient=%x\n",
+ lpdocname,
+ lpclient));
+ return lpclient;
+ }
+ hwnd = GetWindow (hwnd, GW_HWNDNEXT);
+ }
+ return NULL;
+}
+
+BOOL PostAckToClient(HWND hwndClient,HWND hwndServer,ATOM aItem,DWORD retval)
+{
+ HRESULT hr = TRUE;
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN PostAckToClient(hwndClient=%x,hwndServer=%x,aItem=%x(%ws)\n",
+ hwndClient,
+ hwndServer,
+ aItem,
+ wAtomName(aItem)));
+
+ DWORD status = 0;
+ SET_MSG_STATUS (retval, status);
+
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
+
+ if (!PostMessageToClient (hwndClient,
+ WM_DDE_ACK,
+ (UINT)hwndServer,
+ lp))
+ {
+ DDEFREE(WM_DDE_ACK,lp);
+ hr = FALSE;
+ }
+ intrDebugOut((DEB_ITRACE,
+ "0 _OUT PostAckToClient returns %x\n",
+ hr));
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DocHandleIncomingCall
+//
+// Synopsis: Setup and call the CallControl to dispatch a call to the doc
+//
+// Effects: A call has been made from the client that requires us to call
+// into our server. This must be routed through the call control.
+// This routine sets up the appropriate data structures, and
+// calls into the CallControl. The CallControl will in turn
+// call DocDispatchIncomingCall to actually process the call.
+//
+// This routine should only be called by the DocWndProc
+//
+//
+// Arguments: [pDocData] -- Points to DOCDISPATCHDATA for this call
+// This contains all required information for
+// handling the message.
+//
+// Requires:
+//
+// Returns: If an error is returned, it is assumed that the Dispatch
+// routine was not reached. DocDispatchIncomingCall() should
+// not be returning an error.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-05-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+// This is a co-routine with DocDispatchIncomingCall. See that routine
+// for more details
+//
+//----------------------------------------------------------------------------
+INTERNAL DocHandleIncomingCall(PDOCDISPATCHDATA pDocData)
+{
+ HRESULT hresult = NOERROR;
+ DISPATCHDATA dispatchdata;
+ INTERFACEINFO32 ifInfo;
+
+ IID iid; // Currently, we have a random iid, based on whatever is on
+ // the stack. These calls do not nest, so this isn't supposed
+ // to matter.
+
+
+ intrAssert(pDocData != NULL);
+
+ ICallControl *lpCallCont = pDocData->lpclient->m_pCallControl;
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN DocHandleIncomingCall lpclient=%x pDocData=%x\n",
+ pDocData->lpclient,
+ pDocData));
+
+ //
+ // It would be very bad if this didn't exist.
+ //
+ intrAssert(lpCallCont);
+
+ //
+ // There is no information to provide here
+ // By setting pUnk to NULL, the CallControl will pass the
+ // message filter a NULL ifInfo.
+ //
+
+ ifInfo.pUnk = NULL;
+ ifInfo.wMethod=0;
+
+ //
+ // TERMINATE messages must always be handled ASYNC, and cannot
+ // be rejected.
+ //
+ if (pDocData->msg == WM_DDE_TERMINATE)
+ {
+ ifInfo.callcat = CALLCAT_ASYNC;
+ }
+ else
+ {
+ ifInfo.callcat = CALLCAT_SYNCHRONOUS;
+ }
+
+ dispatchdata.pData = (LPVOID) pDocData;
+ pDocData->wDispFunc = DDE_DISP_DOCWNDPROC;
+
+ hresult = lpCallCont->HandleDispatchCall((DWORD)GetWindowTask(pDocData->hwnd),
+ iid,
+ &ifInfo,
+ &dispatchdata);
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _OUT DocHandleIncomingCall hresult=%x\n",
+ hresult));
+
+ return(hresult);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DocDispatchIncomingCall
+//
+// Synopsis: Dispatch a call into the client.
+//
+// Effects: This is a co-routine to DocHandleIncomingCall. This routine
+// is called to implement functions that call into the CDefClient
+// object. It is dispatched by the call control stuff, and helps
+// to insure the server is ready to accept these calls.
+//
+// This routine is coded as a continuation of the DocWndProc.
+// There is a switch on the message. Each message does slightly
+// different things. The code to handle each message was snatched
+// from the original DocWndProc, before it was converted to the
+// new call control mechanism.
+//
+//
+// Arguments: [pDocData] -- Points to Doc Dispatch Data, which are the
+// parameters to DocWndProc which need processing
+//
+// Requires:
+// pDocData cannot be NULL
+//
+// Returns:
+// This routine will always return NOERROR. There are no useful
+// error returns to be made from here. If you decide to return
+// an error, check the DocHandleIncomingCall and DocWndProc to be
+// sure the error paths are correctly handled. Some of the
+// cases do additional error processing in the DocWndProc on
+// error.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-05-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL DocDispatchIncomingCall(PDOCDISPATCHDATA pDocData)
+{
+ LPCLIENT lpclient = pDocData->lpclient;
+ BOOL fack;
+ HANDLE hdata = pDocData->hdata;
+ ATOM aItem = pDocData->aItem;
+ WPARAM wParam = pDocData->wParam;
+ HWND hwnd = pDocData->hwnd;
+ HRESULT retval;
+
+
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN DocDispatchIncomingCall pDocData(%x)\n",
+ pDocData));
+
+ intrAssert(pDocData);
+
+ //
+ // This switch statement is intended to continue the functionality found
+ // in the DocWndProc. These routines are directly interrelated to the
+ // same cases in DocWndProc, and need special care before changing.
+ //
+ switch (pDocData->msg)
+ {
+ case WM_DDE_TERMINATE:
+ {
+ intrDebugOut((DEB_ITRACE,
+ "DDIC: WM_DDE_TERMINATE hwnd=%x \n",
+ pDocData->hwnd));
+
+ //
+ // Here is a fine hack for you. 32-bit applications appear to shut
+ // down slightly differently than 16-bit applications. There is a
+ // problem with Lotus Notes interacting with 32-bit OFFICE apps.
+ // When notes has done an OleCreateFromFile, it starts the
+ // 32-bit hidden, and does a normal DDE conversation. However,
+ // on termination, the 32-bit Doc Window was going away during
+ // this routine. Since the world is now multi-tasking, Lotus
+ // Notes was seeing its server window die because we get
+ // pre-empted during DeleteItemsFromList giving the 16-bit app a
+ // chance to run. Since Lotus is in the
+ // standard OleQueryReleaseStatus() loop, it will detect that the
+ // server has shutdown BEFORE it gets the terminate message.
+ // Go figure. So, insure that we post the reply DDE_TERMINATE
+ // before destroying our window, or the 16-bit applications
+ // won't like us.
+ //
+ PostMessageToClient ((HWND)wParam, WM_DDE_TERMINATE,
+ (UINT) hwnd, NULL);
+
+ // Client initiated the termination. So, we should remove
+ // his window from any of our doc or items' lists.
+ lpclient->DeleteFromItemsList ((HWND)wParam
+ /*, lpclient->m_fEmbed*/);
+
+ ChkC (lpclient);
+
+
+ // REVIEW: If the termination is sent from the client side,
+ // lpoleObj will not be NULL.
+ if (lpclient->m_cClients == 0 && lpclient->m_fEmbed)
+ {
+ Assert (lpclient->m_chk==chkDefClient);
+ lpclient->ReleaseAllItems ();
+ Assert (lpclient->m_chk==chkDefClient);
+ Assert (NULL==lpclient->m_lpoleObj &&
+ NULL==lpclient->m_lpdataObj) ;
+
+ }
+ break;
+ }
+
+ case WM_DDE_EXECUTE:
+ {
+
+ intrDebugOut((DEB_ITRACE,
+ "DDIC: WM_DDE_EXECUTE hwnd=%x hdata=%x\n",
+ pDocData->hwnd,
+ pDocData->hdata));
+
+ //
+ // The following state variables appear to be used by
+ // the execute code.
+ //
+ lpclient->m_ExecuteAck.f = TRUE; // assume we will need to
+ lpclient->m_ExecuteAck.hdata = hdata;
+ lpclient->m_ExecuteAck.hwndFrom = (HWND)wParam;
+ lpclient->m_ExecuteAck.hwndTo = hwnd;
+
+ //
+ // In the event that the command is a StdClose, we need
+ // to force the client to stay around for the duration of
+ // the call.
+ //
+ lpclient->m_pUnkOuter->AddRef();
+
+ retval = lpclient->DocExecute (hdata);
+
+ if (lpclient->m_ExecuteAck.f)
+ {
+ lpclient->SendExecuteAck (retval);
+ }
+
+ lpclient->m_pUnkOuter->Release();
+ break;
+
+ }
+ case WM_DDE_POKE:
+ {
+ int iStdItem;
+ intrDebugOut((DEB_ITRACE,
+ "DDIC: WM_DDE_POKE hwnd=%x aItem=%x(%ws) hdata=%x\n",
+ hwnd,
+ aItem,
+ wAtomName(aItem),
+ hdata));
+
+ if (iStdItem = GetStdItemIndex (aItem))
+ {
+ retval = lpclient->PokeStdItems ((HWND)wParam,
+ aItem,
+ hdata,
+ iStdItem);
+ }
+ else
+ {
+ retval = lpclient->PokeData ((HWND)wParam,
+ aItem,
+ hdata);
+ // This is allowed to fail. PowerPoint tries to poke
+ // data with cfFormat=="StdSave" and "StdFont"
+ }
+
+ if (!PostAckToClient((HWND)wParam,hwnd,aItem,retval))
+ {
+ goto errRtn;
+ }
+ break;
+ }
+ case WM_DDE_ADVISE:
+ {
+ intrDebugOut((DEB_ITRACE,
+ "DDIC: WM_DDE_ADVISE hwnd=%x aItem=%x(%ws) hdata=%x\n",
+ hwnd,
+ aItem,
+ wAtomName(aItem),
+ hdata));
+
+ if (IsAdviseStdItems (aItem))
+ {
+ retval = lpclient->AdviseStdItems ((HWND)wParam,
+ aItem,
+ hdata,
+ (BOOL FAR *)&fack);
+ }
+ else
+ {
+ retval = lpclient->AdviseData ((HWND)wParam,
+ aItem,
+ hdata,
+ (BOOL FAR *)&fack);
+ }
+
+ if (fack)
+ {
+ if (!PostAckToClient((HWND)wParam,hwnd,aItem,retval))
+ {
+ GlobalFree(hdata);
+ }
+ }
+ else if (aItem != NULL)
+ {
+ GlobalDeleteAtom (aItem);
+ }
+ break;
+ }
+ case WM_DDE_UNADVISE:
+ {
+ intrDebugOut((DEB_ITRACE,
+ "DDIC: WM_DDE_UNADVISE hwnd=%x aItem=%x(%ws)\n",
+ hwnd,
+ aItem,
+ wAtomName(aItem)));
+
+ retval = lpclient->UnAdviseData ((HWND)wParam, aItem);
+
+ if (!PostAckToClient((HWND)wParam,hwnd,aItem,retval))
+ {
+ goto errRtn;
+ }
+ break;
+ }
+ case WM_DDE_REQUEST:
+ {
+ intrDebugOut((DEB_ITRACE,
+ "DDIC: WM_DDE_REQUEST hwnd=%x aItem=%x(%ws) cfFormat=%x\n",
+ hwnd,
+ aItem,
+ wAtomName(aItem),
+ (USHORT)LOWORD(pDocData->lParam)));
+
+ retval = lpclient->RequestData ((HWND)wParam,
+ aItem,
+ LOWORD(pDocData->lParam),
+ (HANDLE FAR *)&hdata);
+
+ if (retval == NOERROR)
+ {
+ // post the data message and we are not asking for any
+ // acknowledge.
+
+ intrDebugOut((DEB_ITRACE,
+ "DDIC: posting WM_DDE_DATA\n"));
+
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_DATA,hdata,aItem);
+ if (!PostMessageToClient ((HWND)wParam, WM_DDE_DATA, (UINT) hwnd,lp))
+ {
+ // hdata will be freed by the client because fRelease
+ // was set to true by MakeDdeData (called by RequestData)
+
+ DDEFREE(WM_DDE_DATA,lp);
+ goto errRtn;
+ }
+ }
+ else
+ {
+ if (!PostAckToClient((HWND)wParam,hwnd,aItem,retval))
+ {
+ goto errRtn;
+ }
+ }
+ break;
+ }
+ default:
+ //
+ // Whoops, this is very bad. We should never get here.
+ //
+ intrAssert(!"Unknown MSG in DocWndProc: Very Bad indeed");
+
+
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "0 _OUT DocDispatchIncomingCall pDocData(%x) hr = 0\n",
+ pDocData));
+
+ return(NOERROR);
+errRtn:
+ intrDebugOut((DEB_IERROR,
+ "***** ERROR DDIC pDocData(%x) Post ACK failed. \n",
+ pDocData));
+
+ if (aItem != NULL)
+ {
+ GlobalDeleteAtom (aItem);
+ }
+ goto exitRtn;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: DocWndProc
+//
+// Synopsis: Document Window Procedure
+//
+// Effects: Processes DDE messages for a document window.
+//
+// Arguments: [hwnd] --
+// [msg] --
+// [wParam] --
+// [lParam] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-05-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+// When running in a VDM, it is possible that this window was dispatched
+// without having a full window handle. This happens when the getmessage
+// was dispatched from 16-bit. Therefore, we need to convert the hwnd to
+// a full hwnd before doing any comparision functions.
+//
+//----------------------------------------------------------------------------
+STDAPI_(LRESULT) DocWndProc (
+HWND hwndIn,
+UINT msg,
+WPARAM wParam,
+LPARAM lParam
+)
+{
+
+ //
+ // Since this is the DocWndProc, we aren't going to initialize
+ // any of the local variables. This function is called as a WNDPROC,
+ // which is pretty often.
+ //
+
+ DOCDISPATCHDATA docData;
+ LPCLIENT lpclient;
+ WORD status=0;
+ HANDLE hdata;
+ ATOM aItem;
+ HRESULT retval;
+ LPOLEOBJECT lpoleObj;
+ HWND hwnd;
+ DebugOnly (HWND hwndClient;)
+
+ // REVIEW: We need to take care of the bug, related to
+ // Excel. Excel does the sys level connection and sends
+ // terminates immediately before making the connection
+ // to the doc level. If we send release to classfactory
+ // app may revoke the classfactory.
+
+
+ // REVIEW: It may not be necessary to do the blocking.
+ // ReVIEW: For fixing the ref count right way for
+ // CreateInstance Vs. WM_DDE_INIT
+
+#ifdef LATER
+ if (AddMessage (hwnd, msg, wParam, lParam, WT_DOC))
+ return 0L;
+#endif
+
+ switch (msg){
+
+ case WM_CREATE:
+ intrDebugOut((DEB_ITRACE,
+ "DocWndProc: CreateWindow hwndIn=%x\n",
+ hwndIn));
+ break;
+
+
+ case WM_DDE_INITIATE:
+ hwnd = ConvertToFullHWND(hwndIn);
+ intrAssert(IsWindowValid(hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+
+ intrDebugOut((DEB_ITRACE,
+ "DocWndProc: WM_DDE_INITIATE hwnd=%x\n",
+ hwnd));
+
+ ChkC(lpclient);
+
+
+ // REVIEW: We may not allow initiates to get thru
+ // while we are waiting for terminates. So, this case
+ // may not arise
+
+ // Need to verify that m_pCI is not NULL during incoming
+ // calls from the client.
+ //
+ if (lpclient->m_pCallData)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "DocWndProc: No initiates while waiting on terminate\n"));
+
+ break;
+ }
+ // if we are the document then respond.
+
+ if (! (lpclient->m_aItem == (ATOM)(HIWORD(lParam))))
+ {
+ break;
+ }
+
+ // We can enterain this client. Put this window in the client list
+ // and acknowledge the initiate.
+
+ if (!AddClient ((LPHANDLE)&lpclient->m_hcli, (HWND)wParam, (HWND)wParam))
+ {
+ break;
+ }
+
+
+ // post the acknowledge
+ DuplicateAtom (LOWORD(lParam));
+ DuplicateAtom (HIWORD(lParam));
+ SSSendMessage ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lParam);
+
+ lpclient->m_cClients++;
+ lpclient->m_fCreatedNotConnected = FALSE;
+ lpoleObj = lpclient->m_lpoleObj;
+
+ // we have added an addref because of createinstance.
+
+ if (lpclient->m_bCreateInst)
+ {
+ lpclient->m_bCreateInst = FALSE;
+ }
+
+ return 1L; // fAckSent
+ break;
+
+
+ case WM_DDE_EXECUTE:
+ {
+ hwnd = ConvertToFullHWND(hwndIn);
+ intrAssert(IsWindowValid(hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+
+ hdata = GET_WM_DDE_EXECUTE_HDATA(wParam,lParam);
+ intrDebugOut((DEB_ITRACE,
+ "DocWndProc: WM_DDE_EXECUTE hwnd=%x hdata=%x\n",
+ hwnd,
+ hdata));
+
+ ChkC(lpclient);
+
+#ifdef FIREWALLS
+ // find the client in the client list.
+ hwndClient = FindClient (lpclient->m_hcli, (HWND)wParam, FALSE);
+ AssertSz (hwndClient, "Client is missing from the server");
+#endif
+ if (!IsWindowValid ((HWND)wParam) || lpclient->m_pCallData)
+ {
+ if (lpclient->m_pCallData)
+ {
+ // This means the terminate has already been sent
+ // to this window (from AdviseSink::OnClose) so
+ // we can ignore the StdCloseDocument.
+ }
+ else
+ {
+ intrAssert(!"Execute received from dead sending window");
+ }
+ // Since we are not sending an ACK, the sender will not
+ // have the chance to free the hCommands handle.
+ DDEFREE(WM_DDE_ACK,lParam);
+ // GlobalFree (hdata);
+ break;
+ }
+
+ //
+ // Fill in the used items in DocData
+ //
+ docData.hwnd = hwnd;
+ docData.msg = msg;
+ docData.wParam = wParam;
+ docData.hdata = hdata;
+ docData.lpclient = lpclient;
+
+ retval = DocHandleIncomingCall(&docData);
+
+ //
+ // If error return, then we didn't call DocDispatchIncomingCall
+ // and therefore need to send a NACK
+ //
+ if (retval != NOERROR)
+ {
+ lpclient->SendExecuteAck (retval);
+ }
+ break;
+ }
+ case WM_DDE_TERMINATE:
+ hwnd = ConvertToFullHWND(hwndIn);
+ intrAssert(IsWindowValid(hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+
+ intrDebugOut((DEB_ITRACE,
+ "DocWndProc: WM_DDE_TERMINATE hwnd=%x\n",
+ hwnd));
+
+ ChkC(lpclient);
+
+ //
+ // If m_pCallData, then we are are waiting for a terminate, which
+ // means we generated the original terminate message. If
+ // this is so, then we are waiting for a reply to the
+ // terminate. Set the AckState and break;
+ //
+ if (lpclient->m_pCallData)
+ {
+ intrAssert(lpclient->m_pCallControl != NULL);
+ if (lpclient->m_pCallControl != NULL)
+ {
+ lpclient->m_pCallControl->SetCallState(lpclient->m_pCallData,
+ SERVERCALLEX_ISHANDLED,
+ NOERROR);
+ }
+ break;
+ }
+
+
+#ifdef _DEBUG
+ // find the client in the client list.
+ hwndClient = (HWND)FindClient (lpclient->m_hcli,(HWND)wParam, FALSE);
+ AssertSz(hwndClient, "Client is missing from the server");
+#endif
+ AssertIsDoc (lpclient);
+ Assert (lpclient->m_cClients > 0);
+ lpclient->m_cClients--;
+
+ // Necessary safety bracket
+ lpclient->m_pUnkOuter->AddRef();
+
+ // terminate has to be handled always
+ // The DocHandleIncomingCall() routine will set the
+ // calltype to be CALLTYPE_ASYNC
+ // async calls are never rejected
+
+ docData.hwnd = hwnd;
+ docData.msg = msg;
+ docData.wParam = wParam;
+ docData.lpclient = lpclient;
+
+ retval = DocHandleIncomingCall(&docData);
+
+ intrAssert(retval == NOERROR);
+
+ // Necessary safety bracket
+ lpclient->m_pUnkOuter->Release();
+ break;
+
+ case WM_DESTROY:
+
+ intrDebugOut((DEB_ITRACE,
+ "DocWndProc: WM_DESTROY\n"));
+ break;
+
+ case WM_DDE_POKE:
+ {
+ hwnd = ConvertToFullHWND(hwndIn);
+ intrAssert(IsWindowValid(hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+ hdata = GET_WM_DDE_POKE_HDATA(wParam,lParam);
+ aItem = GET_WM_DDE_POKE_ITEM(wParam,lParam);
+ ChkC(lpclient);
+
+ if (!IsWindowValid ((HWND) wParam) || lpclient->m_pCallData)
+ {
+ // The sending window is invalid or we have already sent a
+ // TERMINATE to it (as indicated by m_pCI != NULL).
+ // We cannot ACK the message, so we must free any
+ // handles or atoms.
+ Warn ("Ignoring message");
+
+ FreePokeData (hdata);
+LDeleteAtom:
+
+ if (aItem != NULL)
+ {
+ GlobalDeleteAtom (aItem);
+ }
+ break;
+ }
+
+ docData.hwnd = hwnd;
+ docData.msg = msg;
+ docData.wParam = wParam;
+ docData.hdata = hdata;
+ docData.aItem = aItem;
+ docData.lpclient = lpclient;
+
+ retval = DocHandleIncomingCall(&docData);
+ if (retval != NOERROR)
+ {
+ SET_MSG_STATUS (retval, status);
+
+ // !!! If the fRelease is false and the post fails
+ // then we are not freeing the hdata. Are we supposed to
+
+ // REVIEW: The assumption is
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
+ if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (UINT) hwnd,lp))
+ {
+ DDEFREE(WM_DDE_ACK,lp);
+ goto LDeleteAtom;
+ }
+ }
+ // johannp: set the busy bit here in the status word
+ break;
+ }
+
+
+ case WM_DDE_ADVISE:
+ {
+ hwnd = ConvertToFullHWND(hwndIn);
+ intrAssert(IsWindowValid(hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+ HANDLE hOptions = GET_WM_DDE_ADVISE_HOPTIONS(wParam,lParam);
+ aItem = GET_WM_DDE_ADVISE_ITEM(wParam,lParam);
+
+ ChkC(lpclient);
+ if (!IsWindowValid ((HWND)wParam) || lpclient->m_pCallData)
+ {
+AdviseErr:
+ Warn ("Ignoring advise message");
+ //
+ // GlobalFree wants a handle, we are giving it a DWORD.
+ //
+ GlobalFree (hOptions);
+ break;
+ }
+ docData.hwnd = hwnd;
+ docData.msg = msg;
+ docData.wParam = wParam;
+ docData.hdata = hOptions;
+ docData.aItem = aItem;
+ docData.lpclient = lpclient;
+
+ retval = DocHandleIncomingCall(&docData);
+
+ if (retval != NOERROR)
+ {
+ SET_MSG_STATUS (retval, status);
+
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
+
+ if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (UINT) hwnd,lp))
+ {
+ DDEFREE(WM_DDE_ACK,lp);
+ goto AdviseErr;
+ }
+ }
+ break;
+ }
+ case WM_DDE_UNADVISE:
+ {
+ hwnd = ConvertToFullHWND(hwndIn);
+ intrAssert(IsWindowValid(hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+
+ aItem = HIWORD(lParam);
+ ChkC(lpclient);
+ if (!IsWindowValid ((HWND)wParam) || lpclient->m_pCallData)
+ {
+ goto LDeleteAtom;
+ }
+ docData.hwnd = hwnd;
+ docData.msg = msg;
+ docData.wParam = wParam;
+ docData.aItem = aItem;
+ docData.lpclient = lpclient;
+
+ retval = DocHandleIncomingCall(&docData);
+
+ if (retval != NOERROR)
+ {
+ SET_MSG_STATUS (retval, status);
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
+
+ if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (UINT) hwnd,lp))
+ {
+ DDEFREE(WM_DDE_ACK,lp);
+ goto LDeleteAtom;
+ }
+ }
+
+ break;
+ }
+ case WM_DDE_REQUEST:
+ {
+ hwnd = ConvertToFullHWND(hwndIn);
+ intrAssert(IsWindowValid(hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+
+ aItem = HIWORD(lParam);
+
+ ChkC(lpclient);
+ if (!IsWindowValid ((HWND) wParam) || lpclient->m_pCallData)
+ {
+ goto LDeleteAtom;
+ }
+ docData.hwnd = hwnd;
+ docData.msg = msg;
+ docData.wParam = wParam;
+ docData.lParam = lParam;
+ docData.aItem = aItem;
+ docData.lpclient = lpclient;
+
+ retval = DocHandleIncomingCall(&docData);
+ if (retval != NOERROR)
+ {
+ if (retval == RPC_E_DDE_BUSY)
+ {
+ status = 0x4000;
+ }
+ else
+ {
+ status = 0; // negative acknowledge
+ }
+
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_ACK,status,aItem);
+ // if request failed, then acknowledge with error.
+ if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK, (UINT) hwnd,lp))
+ {
+ DDEFREE(WM_DDE_ACK,lp);
+ goto LDeleteAtom;
+ }
+ }
+ break;
+ }
+ default:
+ return SSDefWindowProc (hwndIn, msg, wParam, lParam);
+
+ }
+
+ return 0L;
+
+}
+
+
+
+
+INTERNAL_(void) CDefClient::SendExecuteAck
+ (HRESULT hresult)
+{
+ AssertIsDoc (this);
+ WORD status = NULL;
+ SET_MSG_STATUS (hresult, status);
+
+ m_ExecuteAck.f = FALSE;
+
+ LPARAM lParam = MAKE_DDE_LPARAM (WM_DDE_ACK,status,
+ (UINT) m_ExecuteAck.hdata);
+ // Post the acknowledge to the client
+ if (!PostMessageToClient (m_ExecuteAck.hwndFrom, WM_DDE_ACK,
+ (UINT) m_ExecuteAck.hwndTo, lParam))
+ {
+ Assert (0);
+ // the window either died or post failed, delete the data
+ DDEFREE (WM_DDE_ACK,lParam);
+ GlobalFree (m_ExecuteAck.hdata);
+ }
+}
+
+
+
+//DocExecute: Interprets the execute command for the
+//document conversation.
+
+
+INTERNAL CDefClient::DocExecute
+ (HANDLE hdata)
+{
+
+ ATOM acmd;
+ BOOL fShow;
+ BOOL fActivate;
+
+ HANDLE hdup = NULL;
+ HRESULT retval = ReportResult(0, S_OOM, 0, 0);
+
+ LPSTR lpitemname;
+ LPSTR lpopt;
+ LPSTR lpnextarg;
+ LPSTR lpdata = NULL;
+ LPSTR lpverb = NULL;
+ INT verb;
+ WORD wCmdType;
+
+ ChkC(this);
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CDefClient::DocExecute(hdata=%x)\n",
+ this,
+ hdata));
+
+ // !!!Can we modify the string which has been passed to us
+ // rather than duplicating the data. This will get some speed
+ // and save some space.
+
+ if(!(hdup = UtDupGlobal(hdata,GMEM_MOVEABLE)))
+ goto errRtn;
+
+ if (!(lpdata = (LPSTR)GlobalLock (hdup)))
+ goto errRtn;
+
+ retval = ReportResult(0, RPC_E_DDE_SYNTAX_EXECUTE, 0, 0);
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CDefClient::DocExecute command=(%s)\n",
+ this,
+ lpdata));
+
+ if(*lpdata++ != '[') // commands start with the left sqaure bracket
+ goto errRtn;
+
+ // scan the command and scan upto the first arg.
+ if (!(wCmdType = ScanCommand(lpdata, WT_DOC, &lpnextarg, &acmd)))
+ goto errRtn;
+
+ if (wCmdType == NON_OLE_COMMAND) {
+
+#ifdef LATER
+ if (lpsrvr = (LPSRVR) GetWindowLong (GetParent (hwnd), 0)) {
+ if (!UtilQueryProtocol (lpsrvr->aClass, PROTOCOL_EXECUTE))
+ retval = OLE_ERROR_PROTOCOL;
+ else {
+#ifdef FIREWALLS
+ if (!CheckPointer (lpoledoc, WRITE_ACCESS))
+ AssertSz (0, "Invalid LPOLESERVERDOC");
+ else if (!CheckPointer (lpoledoc->lpvtbl, WRITE_ACCESS))
+ AssertSz (0, "Invalid LPOLESERVERDOCVTBL");
+ else
+ AssertSz (lpoledoc->lpvtbl->Execute,
+ "Invalid pointer to Execute method");
+#endif
+
+ retval = (*lpoledoc->lpvtbl->Execute) (lpoledoc, hdata);
+ }
+
+ }
+#endif
+ AssertSz(0, "Doc level execute is being called");
+
+ goto errRtn;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdCloseDocument]
+ //
+ //////////////////////////////////////////////////////////////////////////
+ if (acmd == aStdClose){
+
+ LPCLIENT lpclient=NULL;
+ // if not terminated by NULL error
+ if (*lpnextarg)
+ goto errRtn;
+
+ if ((retval = FindItem (NULL, (LPCLIENT FAR *)&lpclient)) != NOERROR)
+ return retval;
+
+
+ lpclient->m_fGotStdCloseDoc = TRUE;
+ retval = lpclient->m_lpoleObj->Close (OLECLOSE_SAVEIFDIRTY);
+ goto end;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdDoVerbItem("itemname", verb, BOOL, BOOL]
+ //
+ //////////////////////////////////////////////////////////////////////////
+ if (acmd == aStdDoVerbItem){
+ lpitemname = lpnextarg;
+
+ if(!(lpverb = ScanArg(lpnextarg)))
+ goto errRtn;
+
+
+ if(!(lpnextarg = ScanNumArg(lpverb, &verb)))
+ goto errRtn;
+
+#ifdef FIREWALLS
+ AssertSz (verb < 9 , "Unexpected verb number");
+#endif
+
+ // now scan the show BOOL
+
+ if (!(lpnextarg = ScanBoolArg (lpnextarg, (BOOL FAR *)&fShow)))
+ goto errRtn;
+
+ fActivate = FALSE;
+
+ // if activate BOOL is present, scan it.
+
+ if (*lpnextarg) {
+ if (!(lpnextarg = ScanBoolArg (lpnextarg, (BOOL FAR *)&fActivate)))
+ goto errRtn;
+ }
+
+ if (*lpnextarg)
+ goto errRtn;
+
+ if (m_fEmbed)
+ {
+ // This is a totally bogus call to SetHostNames whose only
+ // purpose is to notify the server that this is an embedded
+ // (not linked) object.
+ if (!m_fDidRealSetHostNames)
+ {
+ Puts ("Bogus call to SetHostNames before DoVerb\r\n");
+ m_lpoleObj->SetHostNames (OLESTR("Container"), OLESTR("Object"));
+ }
+ }
+ // REVIEW: We are assuming that calling the Docdoverb method
+ // will not post any more DDE messahes.
+
+ retval = DocDoVerbItem (lpitemname, verb, fShow, !fActivate);
+ goto end;
+ }
+
+
+
+
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdShowItem("itemname"[, "true"])]
+ //
+ //////////////////////////////////////////////////////////////////////////
+ if (acmd != aStdShowItem)
+ goto errRtn;
+
+ lpitemname = lpnextarg;
+
+ if(!(lpopt = ScanArg(lpitemname)))
+ goto errRtn;
+
+ // Now scan for optional parameter.
+
+ fActivate = FALSE;
+
+ if (*lpopt) {
+
+ if(!(lpnextarg = ScanBoolArg (lpopt, (BOOL FAR *)&fActivate)))
+ goto errRtn;
+
+ if (*lpnextarg)
+ goto errRtn;
+
+
+ }
+
+ if (m_fEmbed)
+ {
+ // This is a totally bogus call to SetHostNames whose only
+ // purpose is to notify the server that this is an embedded
+ // (not linked) object.
+ // REVIEW LINK
+ if (!m_fDidRealSetHostNames)
+ {
+ Puts ("Bogus call to SetHostNames before ShowItem\r\n");
+ m_lpoleObj->SetHostNames (OLESTR("Container"), OLESTR("Object"));
+ }
+ }
+
+ retval = DocShowItem (lpitemname, !fActivate);
+
+end:
+errRtn:
+ if (lpdata)
+ GlobalUnlock (hdup);
+
+ if (hdup)
+ GlobalFree (hdup);
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT CDefClient::DocExecute(hdata=%x) hresult=%x\n",
+ this,
+ hdata,
+ retval));
+
+ return (HRESULT)retval;
+}
+
+
+
+INTERNAL_(HRESULT) CDefClient::DocShowItem
+(
+LPSTR lpAnsiitemname,
+BOOL fAct
+)
+{
+ LPCLIENT lpclient;
+ HRESULT retval;
+ LPOLEOBJECT lpoleObj;
+
+ ChkC(this);
+ WCHAR lpitemname[MAX_STR];
+
+ if (MultiByteToWideChar(CP_ACP,0,lpAnsiitemname,-1,lpitemname,MAX_STR) == FALSE)
+ {
+ Assert(!"Unable to convert characters");
+ return(E_UNEXPECTED);
+ }
+
+ if ((retval = FindItem (lpitemname, (LPCLIENT FAR *)&lpclient))
+ != NOERROR)
+ return retval;
+
+ ChkC(lpclient);
+
+ lpoleObj = lpclient->m_lpoleObj;
+
+
+#ifdef FIREWALLS1
+ if (!CheckPointer (lpoleObj->lpvtbl, WRITE_ACCESS))
+ AssertSz (0, "Invalid LPOLEOBJECTVTBL");
+ else
+ AssertSz (lpoleObj->lpvtbl->DoVerb,
+ "Invalid pointer to DoVerb method");
+#endif
+
+ // protocol sends false for activating and TRUE for not activating.
+ // for api send TRUE for avtivating and FALSE for not activating.
+ return lpclient->m_lpoleObj->DoVerb(OLEVERB_SHOW, NULL, NULL, NULL, NULL, NULL);
+}
+
+
+
+INTERNAL_(HRESULT) CDefClient::DocDoVerbItem
+(
+LPSTR lpAnsiitemname,
+WORD verb,
+BOOL fShow,
+BOOL fAct
+)
+{
+ LPCLIENT lpclient;
+ HRESULT retval;
+
+ WCHAR lpitemname[MAX_STR];
+
+ if (MultiByteToWideChar(CP_ACP,0,lpAnsiitemname,-1,lpitemname,MAX_STR) == FALSE)
+ {
+ Assert(!"Unable to convert characters");
+ return(E_UNEXPECTED);
+ }
+
+ ChkC(this);
+ Puts ("DefClient::DocDoVerbItem\r\n");
+ if ((retval = FindItem (lpitemname, (LPCLIENT FAR *)&lpclient))
+ != NOERROR)
+ return retval;
+ ChkC(lpclient);
+
+#ifdef FIREWALLS1
+ if (!CheckPointer (lpclient->lpoleObj->lpvtbl, WRITE_ACCESS))
+ AssertSz (0, "Invalid LPOLEOBJECTVTBL");
+ else
+ AssertSz (lpclient->lpoleObj->lpvtbl->DoVerb,
+ "Invalid pointer to DoVerb method");
+#endif
+
+ // pass TRUE to activate and False not to activate. Differnt from
+ // protocol.
+
+ retval = lpclient->m_lpoleObj->DoVerb(verb, NULL, &m_OleClientSite, NULL, NULL, NULL);
+ // Apparently an obsolete version of Lotus Notes is the only
+ // container (other than Cltest) that sets fShow=FALSE
+ if (!fShow && lpclient->m_lpoleObj && lpclient->m_fEmbed)
+ lpclient->m_lpoleObj->DoVerb(OLEIVERB_HIDE, NULL, &m_OleClientSite, NULL, NULL, NULL);
+ return retval;
+}
+
+INTERNAL CDefClient::DoInitNew()
+{
+ HRESULT hresult;
+ ATOM aClass;
+ LPPERSISTSTORAGE pPersistStg=NULL;
+
+ hresult = m_lpoleObj->QueryInterface(IID_IPersistStorage,
+ (LPLPVOID)&pPersistStg);
+ if (hresult == NOERROR)
+ {
+ CLSID clsid;
+ RetZ (pPersistStg);
+ ErrRtnH (CreateILockBytesOnHGlobal ((HGLOBAL)NULL,
+ /*fDeleteOnRelease*/ TRUE,
+ &m_plkbytNative));
+ ErrZS (m_plkbytNative, E_OUTOFMEMORY);
+
+ ErrRtnH (StgCreateDocfileOnILockBytes
+ (m_plkbytNative,
+ grfCreateStg, 0,
+ &m_pstgNative));
+
+ ErrZS (m_pstgNative, E_OUTOFMEMORY);
+
+ aClass = m_psrvrParent->m_cnvtyp == cnvtypTreatAs ? m_psrvrParent->m_aOriginalClass
+ : m_psrvrParent->m_aClass;
+ // Write appropriate class tag
+ ErrZS (CLSIDFromAtom (aClass,(LPCLSID)&clsid),
+ REGDB_E_CLASSNOTREG);
+ ErrRtnH (WriteClassStg (m_pstgNative, clsid));
+
+ // Provide server with a storage to use for its persistent
+ // storage, i.e., native data. We remember this IStorage and the
+ // ILockBytes it is built on.
+ ErrRtnH (pPersistStg->InitNew(m_pstgNative));
+ m_fGotEditNoPokeNativeYet = FALSE;
+
+ // Now that we have initialized the object, we are allowed to
+ // set the client site, and advise.
+ ErrRtnH (SetClientSite());
+
+ // This is for Packager, in particular. If client does not advise
+ // on any data, we still need to do an OLE advise so we can get
+ // OnClose notifications.
+ DoOle20Advise (OLE_CLOSED, (CLIPFORMAT)0);
+ }
+ else
+ {
+ AssertSz (0, "Can't get IPersistStorage from OleObj\r\n");
+ }
+
+ m_fEmbed = TRUE;
+
+errRtn:
+ if (pPersistStg)
+ pPersistStg->Release();
+ return hresult;
+}
+
+
+// FreePokeData: Frees the poked dats.
+INTERNAL_(void) FreePokeData
+(
+HANDLE hdde
+)
+{
+ DDEPOKE FAR * lpdde;
+ Puts ("FreePokeData\r\n");
+
+ if (hdde) {
+ if (lpdde = (DDEPOKE FAR *) GlobalLock (hdde)) {
+ GlobalUnlock (hdde);
+ FreeGDIdata (*(LPHANDLE)lpdde->Value, lpdde->cfFormat);
+ }
+
+ GlobalFree (hdde);
+ }
+}
+
+
+
+// Returns TRUE if GDI format else returns FALSE
+
+INTERNAL_(BOOL) FreeGDIdata
+(
+HANDLE hData,
+CLIPFORMAT cfFormat
+)
+{
+ Puts ("FreeGDIData\r\n");
+ if (cfFormat == CF_METAFILEPICT) {
+ LPMETAFILEPICT lpMfp;
+
+ if (lpMfp = (LPMETAFILEPICT) GlobalLock (hData)) {
+ GlobalUnlock (hData);
+ DeleteMetaFile (lpMfp->hMF);
+ }
+
+ GlobalFree (hData);
+ }
+ else if (cfFormat == CF_BITMAP)
+ DeleteObject (hData);
+ else if (cfFormat == CF_DIB)
+ GlobalFree (hData);
+ else
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/private/ole32/com/remote/dde/server/item.cxx b/private/ole32/com/remote/dde/server/item.cxx
new file mode 100644
index 000000000..f268cdbcc
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/item.cxx
@@ -0,0 +1,1210 @@
+/****************************** Module Header ******************************\
+* Module Name: Item.c Object(item) main module
+*
+* Purpose: Includes All the object releated routiens.
+*
+* Created: Oct 1990.
+*
+* Copyright (c) 1990, 1991 Microsoft Corporation
+*
+* History:
+* Raor (../10/1990) Designed, coded
+*
+*
+\***************************************************************************/
+
+
+#include "ole2int.h"
+//#include "cmacs.h"
+#include <dde.h>
+#include "ddeatoms.h"
+#include "ddedebug.h"
+#include "srvr.h"
+#include "itemutil.h"
+
+ASSERTDATA
+
+
+// !!!change child enumeration.
+// !!!No consistency in errors (Sometimes Bools and sometimes HRESULT).
+
+
+//SearchItem: Searches for a given item in a document tree.
+//If found, returns the corresponding client ptr.
+
+INTERNAL_(LPCLIENT) CDefClient::SearchItem
+(
+LPOLESTR lpitemname
+)
+
+{
+ ATOM aItem;
+ LPCLIENT lpclient;
+
+ ChkC(this);
+ Assert (m_pdoc==this);
+ Assert (m_bContainer);
+
+ Puts ("DefClient::SearchItem\r\n");
+ // If the item passed is an atom, get its name.
+ if (!HIWORD(lpitemname))
+ aItem = (ATOM) (LOWORD((DWORD)lpitemname));
+ else if (!lpitemname[0])
+ aItem = NULL;
+ else
+ aItem = GlobalFindAtom (lpitemname);
+
+ // walk thru the items list and mtach for the itemname.
+ lpclient = this;
+
+ while (lpclient) {
+ ChkC(lpclient);
+ if (lpclient->m_aItem == aItem)
+ return lpclient;
+ // The NULL item is the client that is a container (the whole doc).
+ // REVIEW: jasonful
+ if (lpclient->m_bContainer && aItem==NULL)
+ return lpclient;
+ lpclient = lpclient->m_lpNextItem;
+ }
+
+ Puts ("SearchItem failed\r\n");
+ return NULL;
+
+}
+
+
+
+// FindItem: Given the itemname and the doc obj ptr,
+// searches for the the item (object) in the document tree.
+// Items are lonked to the doc obj.
+
+INTERNAL_(HRESULT) CDefClient::FindItem
+(
+LPOLESTR lpitemname,
+LPCLIENT FAR * lplpclient
+)
+{
+ LPCLIENT lpclient;
+ WCHAR buf[MAX_STR];
+
+ Puts ("DefClient::FindItem "); Puts (lpitemname); Putn();
+ ChkC(this);
+
+ if (lpclient = SearchItem (lpitemname)) {
+ // we found the item window
+
+ ChkC(lpclient);
+ *lplpclient = lpclient;
+ return NOERROR;
+
+ }
+
+ if (!HIWORD(lpitemname)){
+ if (LOWORD(lpitemname))
+ GlobalGetAtomName ((ATOM)LOWORD((DWORD)lpitemname),
+ buf, MAX_STR);
+ else
+ buf[0] = NULL;
+
+ lpitemname = buf;
+ }
+
+ // Item (object)window is not created yet. Let us create one.
+ return RegisterItem (lpitemname, lplpclient, TRUE);
+}
+
+
+
+//RegisterItem: Given the document handle and the item string
+//creates item with the given name in the doc obj list..
+
+INTERNAL CDefClient::RegisterItem
+ (LPOLESTR lpitemname,
+ LPCLIENT FAR * lplpclient,
+ BOOL bSrvr)
+{
+ LPCLIENT pitemNew = NULL;
+ HRESULT hresult = ReportResult(0, E_UNEXPECTED, 0, 0);
+ LPOLEOBJECT lpoleObj = NULL;
+ LPOLEITEMCONTAINER lpcontainer;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::RegisterItem(%ws)\n",
+ this,WIDECHECK(lpitemname)));
+ ChkC(this);
+ AssertIsDoc(this);
+ *lplpclient = NULL;
+
+ ErrZS (pitemNew = new CDefClient(NULL), E_OUTOFMEMORY);
+
+ pitemNew->m_bTerminate = FALSE;
+ pitemNew->m_bContainer = FALSE; // not a container, i.e.,document
+
+
+ // Set containing document
+ pitemNew->m_pdoc = this;
+ m_pUnkOuter->AddRef(); // item keeps its document alive
+ // Corresponding Release is in CDefClient::~CDefClient
+
+ if (!HIWORD(lpitemname)) {
+ AssertSz (!bSrvr, "invalid lpitemname in RegisterItem\r\n");
+ pitemNew->m_aItem = LOWORD((DWORD)lpitemname);
+ }
+ else if (!lpitemname[0])
+ pitemNew->m_aItem = NULL;
+ else
+ pitemNew->m_aItem = wGlobalAddAtom (lpitemname);
+
+ lpoleObj = m_lpoleObj;
+
+ // Call the server if the item is not one of the standard items.
+ if (bSrvr) {
+
+ // Call the server app for container interface
+ hresult = lpoleObj->QueryInterface (IID_IOleItemContainer, (LPVOID FAR *)&lpcontainer);
+
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "%x ::RegisterItem(%ws) No IOleContainer intr\n",
+ this,WIDECHECK(lpitemname)));
+ goto errRtn;
+ }
+
+ hresult = lpcontainer->GetObject(lpitemname, BINDSPEED_INDEFINITE, 0,
+ IID_IOleObject, (LPLPVOID)&pitemNew->m_lpoleObj);
+
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_ERROR,
+ "IOleItemContainer::GetObject(%ws,...) failed (hr=%x)\n",
+ lpitemname,
+ hresult));
+ }
+
+ lpcontainer->Release ();
+ if (hresult != NOERROR)
+ goto errRtn;
+
+ hresult = pitemNew->m_lpoleObj->QueryInterface (IID_IDataObject, (LPLPVOID)
+ &pitemNew->m_lpdataObj);
+
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_ERROR,
+ "::QueryInterface(IID_IDataObject) failed (hr=%x)\n",
+ hresult));
+ pitemNew->m_lpoleObj->Release();
+ goto errRtn;
+ }
+
+
+ // This is for Packager, in particular. If client does not advise
+ // on any data, we still need to do an OLE advise so we can get
+ // OnClose notifications.
+ pitemNew->DoOle20Advise (OLE_CLOSED, (CLIPFORMAT)0);
+ }
+
+
+
+ // This keeps the CDefClient alive until _we_ are done with it
+ // The corresponding Release is in CDefClient::Revoke
+ pitemNew->m_pUnkOuter->AddRef();
+
+ pitemNew->m_lpNextItem = m_lpNextItem;
+ pitemNew->m_hwnd = m_hwnd; // set the window handle to
+ // same as the doc level window
+
+ m_lpNextItem = pitemNew;
+ *lplpclient = pitemNew;
+
+ hresult = NOERROR;
+ goto exitRtn;
+
+errRtn:
+ if (pitemNew) {
+ delete pitemNew;
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x CDefClient::RegisterItem(%ws) hresult=%x\n",
+ this,WIDECHECK(lpitemname),hresult));
+
+
+ return(hresult);
+}
+
+
+
+// Return NOERROR if "this" document has no items which have connections
+// (client windows).
+//
+INTERNAL CDefClient::NoItemConnections (void)
+{
+ PCLINFO pclinfo = NULL;
+ HANDLE hcliPrev = NULL;
+ HANDLE hcli;
+ PCLILIST pcli;
+ HANDLE *phandle;
+
+ ChkCR (this);
+ AssertIsDoc (this);
+ LPCLIENT pitem;
+ for (pitem = m_lpNextItem;
+ pitem;
+ pitem = pitem->m_lpNextItem)
+ {
+ ChkCR (pitem);
+ if (pitem->m_aItem == aStdDocName)
+ continue;
+ hcli = pitem->m_hcliInfo;
+ while (hcli)
+ {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ return ResultFromScode (S_FALSE);
+
+ phandle = (HANDLE *) (pcli->info);
+ while (phandle < (HANDLE *)(pcli + 1))
+ {
+ if (*phandle)
+ {
+ LocalUnlock (hcli);
+ return ResultFromScode (S_FALSE);
+ }
+ else
+ {
+ phandle++;
+ phandle++;
+ }
+ }
+
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ }
+ }
+ return NOERROR;
+}
+
+
+
+INTERNAL_(void) CDefClient::DeleteAdviseInfo (void)
+{
+
+
+ PCLINFO pclinfo = NULL;
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+ HANDLE hcli;
+ HANDLE hcliInfo;
+
+ Puts ("DefClient::DeleteAdviseInfo\r\n");
+ ChkC(this);
+ hcli = m_hcliInfo;
+ while (hcli) {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ return;
+
+ phandle = (HANDLE *) (pcli->info);
+ while (phandle < (HANDLE *)(pcli + 1)) {
+ if (*phandle) {
+ *phandle++ = 0;
+
+ // delete the printer dev info block
+ if(pclinfo = (PCLINFO)LocalLock ((hcliInfo = *phandle++))){
+ if(pclinfo->hdevInfo)
+ GlobalFree (pclinfo->hdevInfo);
+
+ LocalUnlock (hcliInfo);
+ // no free if lock failed
+ LocalFree (hcliInfo);
+ }
+ } else {
+ phandle++;
+ phandle++;
+
+ }
+ }
+
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ LocalFree (hcliPrev); // free the block;
+ }
+ m_hcliInfo = NULL;
+}
+
+
+
+//DeleteFromItemsList: Deletes a client from the object lists of
+//all the objects of a given document. Thie client possibly
+//is terminating the conversation with our doc window.
+//
+INTERNAL_(void) CDefClient::DeleteFromItemsList
+ (HWND hwndClient)
+{
+ HANDLE hclinfo;
+ PCLINFO pclinfo;
+ LPCLIENT lpclient;
+ LPCLIENT FAR* ppitemLast = NULL;
+ BOOL fRevokedDoc = FALSE;
+ static int staticcounter;
+ int counter = ++staticcounter;
+
+ Puts ("DefClient::DeleteFromItemsList "); Puti(counter); Putn();
+ AssertIsDoc(this);
+ lpclient = this;
+ ppitemLast = &m_lpNextItem;
+ while (lpclient)
+ {
+ ChkC(lpclient);
+ BOOL fDoc = (lpclient==this);
+ if (fDoc)
+ {
+ AssertIsDoc (lpclient);
+ // Remove window from doc's master list
+ HWND hwnd = (HWND) FindClient (lpclient->m_hcli, hwndClient, /*fDelete*/TRUE);
+ Assert (hwnd==hwndClient);
+ }
+
+ hclinfo = FindClient (lpclient->m_hcliInfo, hwndClient, /*fDelete*/TRUE);
+ LPCLIENT pitemNext = lpclient->m_lpNextItem;
+
+ // We must make sure no other client is connected (linked)
+ // to this item before deleting.
+ if (!fDoc && AreNoClients (lpclient->m_hcliInfo))
+ {
+ Assert (ppitemLast);
+ if (ppitemLast && !fDoc)
+ {
+ // Remove from linked list
+ *ppitemLast = lpclient->m_lpNextItem;
+ }
+ fRevokedDoc |= fDoc;
+ lpclient->Revoke ();
+ }
+ else
+ {
+ ppitemLast = &(lpclient->m_lpNextItem);
+ }
+ if (hclinfo)
+ {
+ if(pclinfo = (PCLINFO)LocalLock (hclinfo))
+ {
+ if(pclinfo->hdevInfo)
+ GlobalFree (pclinfo->hdevInfo);
+ LocalUnlock (hclinfo);
+ }
+ LocalFree (hclinfo);
+ }
+ lpclient = pitemNext;
+ }
+
+ // Handle invisible update
+ if (!fRevokedDoc && !m_fEmbed //&& !m_fGotDdeAdvise
+ && NOERROR ==NoItemConnections()
+ && AreNoClients (m_hcliInfo)
+ && AreNoClients (m_hcli) )
+ {
+ ChkC (this);
+ Assert (m_lpoleObj);
+ Assert (m_lpdataObj);
+ ReleaseObjPtrs();
+ }
+
+ Puts ("DefClient::DeleteFromItemsList Done "); Puti(counter); Putn();
+}
+
+
+INTERNAL_(void) CDefClient::RemoveItemFromItemList
+ (void)
+{
+ // Make sure it's an item
+ Assert (m_pdoc != this && !m_bContainer);
+
+ LPCLIENT lpclient = m_pdoc;
+ ChkC (lpclient);
+ LPCLIENT FAR* ppitemLast = &(m_pdoc->m_lpNextItem);
+
+ while (lpclient)
+ {
+ ChkC(lpclient);
+ if (lpclient==this)
+ {
+ // Remove from linked list
+ *ppitemLast = lpclient->m_lpNextItem;
+ break;
+ }
+ ppitemLast = &(lpclient->m_lpNextItem);
+ lpclient = lpclient->m_lpNextItem;
+ }
+ Revoke();
+}
+
+
+
+
+INTERNAL_(void) CDefClient::ReleaseAllItems ()
+{
+ LPCLIENT lpclient;
+
+ Puts ("DefClient::ReleaseAllItems\r\n");
+ AssertIsDoc(this);
+
+ // leave the doc level object.
+ lpclient = m_lpNextItem;
+
+ while (lpclient)
+ {
+ ChkC(this);
+ LPCLIENT pitemNext = lpclient->m_lpNextItem;
+ lpclient->Revoke();
+ lpclient = pitemNext;
+ }
+ // After revoking all the items, we can't keep any refernces to them.
+ m_lpNextItem = NULL;
+}
+
+
+
+INTERNAL_(void) CDefClient::DeleteAllItems ()
+{
+ LPCLIENT lpclient;
+
+ Puts ("DefClient::DeleteAllItems\r\n");
+ AssertIsDoc(this);
+
+ // leave the doc level object.
+ lpclient = m_lpNextItem;
+
+ while (lpclient)
+ {
+ ChkC(lpclient);
+ if (ISATOM(lpclient->m_aItem))
+ GlobalDeleteAtom (lpclient->m_aItem);
+ // Delete client advise info
+ lpclient->DeleteAdviseInfo ();
+
+ lpclient = lpclient->m_lpNextItem;
+ }
+}
+
+
+
+
+// PokeData: Prepares and gives the data to the server app thru
+// the SetData object method.
+
+INTERNAL CDefClient::PokeData(HWND hwndClient,ATOM aItem,HANDLE hPoke)
+{
+ HRESULT hresult = ReportResult(0, E_UNEXPECTED, 0, 0);
+ DDEPOKE FAR * lpPoke = NULL;
+ int format;
+ BOOL fRelease = FALSE;
+ LPPERSISTSTORAGE pPersistStg=NULL;
+ FORMATETC formatetc;
+ STGMEDIUM medium;
+
+ // Due to a C7 bug, do not use a structure initialization for STGMEDIUM
+ medium.tymed = TYMED_HGLOBAL;
+ medium.hGlobal = NULL; // invalid
+ medium.pUnkForRelease= NULL;
+
+ intrDebugOut((DEB_ITRACE,
+ "%p CDefClient::PokeData(hwndClient=%x,aItem=%x,hPoke=%x)\n",
+ this,hwndClient,aItem,hPoke));
+
+ ChkC(this);
+ AssertIsDoc (this);
+
+
+ // Until now, m_aItem had been the client-generated (ugly) document name.
+ // Now it becomes the actual item name, which will almost always be NULL.
+ // Only in the TreatAs/ConvertTo case will it be non-NULL.
+ m_aItem = aItem;
+
+ formatetc.cfFormat = 0; /* invalid */
+ formatetc.ptd = m_ptd;
+ formatetc.lindex = DEF_LINDEX;
+ formatetc.dwAspect = DVASPECT_CONTENT;
+ formatetc.tymed = TYMED_HGLOBAL;
+
+ ErrZS (hPoke && (lpPoke = (DDEPOKE FAR *) GlobalLock (hPoke)),
+ E_OUTOFMEMORY);
+
+ format = formatetc.cfFormat = (UINT)(unsigned short)lpPoke->cfFormat;
+ Assert (format);
+ fRelease = lpPoke->fRelease;
+
+ // We found the item. Now prepare the data to be given to the object
+ // MakeItemData returns a newly allocated handle.
+ if (!(medium.hGlobal = MakeItemData (lpPoke, hPoke, format)))
+ goto errRtn;
+
+ // Change type acording to format (not that default has been set above)
+ if (format == CF_METAFILEPICT)
+ formatetc.tymed = medium.tymed = TYMED_MFPICT;
+ else
+ if (format == CF_BITMAP)
+ formatetc.tymed = medium.tymed = TYMED_GDI;
+
+ // Now send the data to the object
+
+
+ if (formatetc.cfFormat==g_cfNative)
+ {
+ m_fGotEditNoPokeNativeYet = FALSE;
+
+ // Cannot do SetData. Must do PersisStg::Load on an IStorage
+ // made from the native data, i.e., medium.hGlobal.
+
+ Assert (m_plkbytNative==NULL);
+ ErrRtnH (CreateILockBytesOnHGlobal (medium.hGlobal,
+ /*fDeleteOnRelease*/TRUE,
+ &m_plkbytNative));
+
+ Assert (m_pstgNative==NULL);
+
+ if (NOERROR==StgIsStorageILockBytes(m_plkbytNative))
+ {
+ // This is a flattened 2.0 storage
+ ErrRtnH (StgOpenStorageOnILockBytes (m_plkbytNative,
+ (LPSTORAGE)NULL,
+ STGM_READWRITE| STGM_SHARE_EXCLUSIVE| STGM_DIRECT,
+ (SNB)NULL,
+ 0,
+ &m_pstgNative));
+ }
+ else
+ {
+ // It is a raw 1.0 Native handle.
+ // This is the TreatAs/ ConvertTo case.
+ LPLOCKBYTES plkbyt = NULL;
+ Assert (m_psrvrParent->m_aOriginalClass);
+
+ ErrRtnH (wCreateStgAroundNative (medium.hGlobal,
+ m_psrvrParent->m_aOriginalClass,
+ m_psrvrParent->m_aClass,
+ m_psrvrParent->m_cnvtyp,
+ m_aItem,
+ &m_pstgNative,
+ &plkbyt));
+
+
+ Assert (m_plkbytNative);
+ if (m_plkbytNative)
+ {
+ // This should free the original native hGlobal also.
+ m_plkbytNative->Release();
+ medium.hGlobal = NULL;
+ }
+ m_plkbytNative = plkbyt;
+
+ }
+
+ RetZ (m_pstgNative);
+ Assert (m_lpoleObj);
+ ErrRtnH (m_lpoleObj->QueryInterface (IID_IPersistStorage,
+ (LPLPVOID) &pPersistStg));
+ hresult = pPersistStg->Load (m_pstgNative);
+ pPersistStg->Release();
+ pPersistStg=NULL;
+ ErrRtnH (hresult);
+
+ // Now that we have initialized the object, we can call SetClientSite
+ ErrRtnH (SetClientSite() );
+
+ // This is for Packager, in particular. If client does not advise
+ // on any data, we still need to do an OLE advise so we can get
+ // OnClose notifications.
+ ErrRtnH (DoOle20Advise (OLE_CLOSED, (CLIPFORMAT)0));
+ }
+ else
+ {
+ if (m_fGotEditNoPokeNativeYet)
+ {
+ // We got StdEdit, but instead of getting Poke for native data,
+ // we got poke for someother format. So we want to generate
+ // InitNew() call for the object.
+
+ ErrRtnH (DoInitNew()); // the function clears the flag
+ }
+
+ // Not native format, do SetData
+ // Callee frees medium, i.e., the hglobal returned by MakeItemData
+ Assert (m_lpdataObj);
+ hresult = m_lpdataObj->SetData (&formatetc, &medium, TRUE);
+#ifdef _DEBUG
+ if (hresult != NOERROR)
+ {
+ Puts ("****WARNING: SetData failed. cfFormat==");
+ WCHAR sz[100];
+ GetClipboardFormatName (formatetc.cfFormat, sz, 100);
+ Puts (sz);
+ Putn();
+ }
+#endif
+ // We free the data if server deos not return NOERROR.
+ // Otherwise server must've deleted it.
+ if (hresult == NOERROR)
+ medium.hGlobal = NULL;
+ }
+
+
+errRtn:
+ GlobalUnlock (hPoke);
+
+ if (fRelease && hPoke)
+ GlobalFree (hPoke);
+
+// Do NOT free medium.hGlobal, because it becomes the hGlobal on which
+// m_plkbytNative (and therefore m_pstgNative) is based.
+// It will be freed when m_plkbytNative is Release().
+// if (medium.hGlobal)
+// ReleaseStgMedium(&medium);
+
+ if (pPersistStg)
+ pPersistStg->Release();
+
+ return hresult;
+}
+
+
+
+INTERNAL_(HRESULT) CDefClient::UnAdviseData
+ (HWND hwndClient,
+ ATOM aItem)
+{
+ WCHAR buf[MAX_STR];
+ int options;
+ LPCLIENT lpclient;
+ HRESULT hresult = ReportResult(0, E_UNEXPECTED, 0, 0);
+ HANDLE hclinfo = NULL;
+ PCLINFO pclinfo = NULL;
+
+ Puts ("DefClient::UnadviseData\r\n");
+ ChkC(this);
+
+ if (aItem == NULL)
+ {
+ buf[0] = NULL;
+ }
+ else
+ {
+ GlobalGetAtomName (aItem, buf, MAX_STR);
+ }
+
+ // Scan for the advise options like "Close", "Save" etc
+ // at the end of the item.
+
+ ErrRtnH (ScanItemOptions (buf, (int far *)&options));
+
+ // Now get the corresponding object.
+ ErrRtnH (FindItem (buf, (LPCLIENT FAR *)&lpclient));
+
+ // Find the client structure to be attached to the object.
+ if ((hclinfo = FindClient (lpclient->m_hcliInfo, hwndClient, FALSE)) == NULL ||
+ (pclinfo = (PCLINFO) LocalLock (hclinfo)) == NULL )
+ {
+ hresult = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ goto errRtn;
+ }
+
+ pclinfo->options &= (~(0x0001 << options));
+
+errRtn:
+ if (pclinfo)
+ LocalUnlock (hclinfo);
+ return hresult;
+
+}
+
+
+
+// AdviseStdItems: This routine takes care of the DDEADVISE for a
+//particular object in given document. Creates a client strutcure
+//and attaches to the property list of the object window.
+
+INTERNAL_(HRESULT) CDefClient::AdviseStdItems
+(
+
+HWND hwndClient,
+ATOM aItem,
+HANDLE hopt,
+BOOL FAR * lpfack
+)
+{
+
+ DDEADVISE FAR *lpopt;
+ HRESULT hresult = ReportResult(0, E_UNEXPECTED, 0, 0);
+
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::AdviseStdItems(hwndClient=%x,aItem=%x(%ws),hopt=%x)\n",
+ this,
+ hwndClient,
+ aItem,
+ wAtomName(aItem),
+ hopt));
+
+ ChkC(this);
+ ErrZS (lpopt = (DDEADVISE FAR *) GlobalLock (hopt), E_OUTOFMEMORY);
+
+ AssertSz (aItem == aStdDocName, "AdviseStdItem is not Documentname");
+
+ *lpfack = lpopt->fAckReq;
+ hresult = (HRESULT)SetStdInfo (hwndClient, OLESTR("StdDocumentName"), NULL);
+
+
+ if (lpopt)
+ GlobalUnlock (hopt);
+
+errRtn:
+
+ if (hresult == NOERROR)
+ {
+ // Rules say to free handle if ACK will be positive
+ GlobalFree (hopt);
+ }
+ Assert (hresult==NOERROR);
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::AdviseStdItems hresult=%x\n",
+ this,
+ hresult));
+
+ return hresult;
+}
+
+
+
+//AdviseData: This routine takes care of the DDE_ADVISE for a
+//particular object in given document. Creates a client strutcure
+//and attaches to the property list of the object window.
+
+INTERNAL CDefClient::AdviseData
+(
+HWND hwndClient,
+ATOM aItem,
+HANDLE hopt,
+BOOL FAR * lpfack
+)
+{
+ DDEADVISE FAR *lpopt = NULL;
+ int format = NULL;
+ WCHAR buf[MAX_STR];
+ OLE_NOTIFICATION options;
+ LPCLIENT lpclient;
+ HRESULT hresult = ReportResult(0, E_UNEXPECTED, 0, 0);
+ HANDLE hclinfo = NULL;
+ PCLINFO pclinfo = NULL;
+ BOOL fAllocatedClInfo = FALSE;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::AdviseData(hwndClient=%x,aItem=%x(%ws),hopt=%x)\n",
+ this,
+ hwndClient,
+ aItem,
+ wAtomName(aItem),
+ hopt));
+ ChkC(this);
+ if (m_fGotEditNoPokeNativeYet) {
+ // We got StdEdit, but instead of getting Poke for native data,
+ // we got advise. So we want to generate InitNew() call for
+ // the object.
+
+ DoInitNew(); // the function clears the flag
+ }
+
+ m_fGotDdeAdvise = TRUE;
+
+ ErrZS (lpopt = (DDEADVISE FAR *) GlobalLock (hopt), E_OUTOFMEMORY);
+
+ if (!aItem)
+ buf[0] = NULL;
+ else
+ GlobalGetAtomName (aItem, buf, MAX_STR);
+
+ // Scan for the advise options like "Close", "Save" etc
+ // at the end of the item.
+
+ // ack flag should be set before the error return. Otherwise the
+ // the atom is getting deleted.
+
+ *lpfack = lpopt->fAckReq;
+ ErrRtnH (ScanItemOptions (buf, (int far *)&options));
+
+ // Now get the corresponding item.
+ ErrRtnH (FindItem (buf, (LPCLIENT FAR *)&lpclient));
+
+ if (!IsFormatAvailable ((CLIPFORMAT)(unsigned short)lpopt->cfFormat)){
+ hresult = ReportResult(0, DV_E_CLIPFORMAT, 0, 0); // this format is not supported;
+ goto errRtn;
+ }
+
+ lpclient->DoOle20Advise (options, (CLIPFORMAT)(unsigned short)lpopt->cfFormat);
+
+
+ // Create the client structure to be attcahed to the object.
+ if (!(hclinfo = FindClient (lpclient->m_hcliInfo, hwndClient, FALSE)))
+ {
+ hclinfo = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof (CLINFO));
+ fAllocatedClInfo = TRUE;
+ }
+
+
+ if (hclinfo == NULL || (pclinfo = (PCLINFO) LocalLock (hclinfo)) == NULL){
+ hresult = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ goto errRtn;
+ }
+
+ // Remember the client window (Needed for sending DATA later on
+ // when the data change message comes from the server)
+
+ pclinfo->hwnd = hwndClient;
+ if ((CLIPFORMAT)(unsigned short)lpopt->cfFormat == g_cfNative)
+ pclinfo->bnative = TRUE;
+ else
+ pclinfo->format = (CLIPFORMAT)(unsigned short)lpopt->cfFormat;
+
+ // Remeber the data transfer options
+ pclinfo->options |= (1 << options) ;
+
+ pclinfo->bdata = !lpopt->fDeferUpd;
+ LocalUnlock (hclinfo);
+ pclinfo = NULL;
+
+ // if the entry exists already, delete it.
+ FindClient (lpclient->m_hcliInfo, hwndClient, /*fDelete*/TRUE);
+
+ // Now add this client to item client list
+ // !!! This error recovery is not correct.
+ if(!AddClient ((LPHANDLE)&lpclient->m_hcliInfo, hwndClient, hclinfo))
+ goto errRtn;
+
+
+errRtn:
+ if (lpopt)
+ GlobalUnlock (hopt);
+
+ if (pclinfo)
+ LocalUnlock (hclinfo);
+
+ if (hresult==NOERROR)
+ {
+ // hresult==NOERROR iff we will send a postive ACK, so we must
+ // free the hOptions handle.
+ GlobalFree (hopt);
+ }
+ else
+ {
+ intrDebugOut((DEB_IERROR,
+ "%x ::AdviseData() failing.\n",this));
+ // We free hclinfo because it was not stored in the item's
+ // client list via the AddClient just before the errRtn label.
+ if (hclinfo && fAllocatedClInfo)
+ LocalFree (hclinfo);
+
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::AdviseData() returns hresult = %x\n",
+ this, hresult));
+
+ return hresult;
+
+}
+
+
+
+
+
+INTERNAL_(BOOL) CDefClient::IsFormatAvailable
+ (CLIPFORMAT cfFormat)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::IsFormatAvailable(cfFormat=%x)\n",
+ this, cfFormat));
+
+ ChkC(this);
+
+ BOOL f = ((cfFormat==g_cfNative) || UtIsFormatSupported (m_lpdataObj, DATADIR_GET, cfFormat));
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::IsFormatAvailable(cfFormat=%x) returning %x\n",
+ this, cfFormat,f));
+
+ return f;
+}
+
+
+//RequestData: Sends data in response to a DDE Request message.
+// for agiven doc and an object.
+
+INTERNAL_(HRESULT) CDefClient::RequestData
+(
+HWND hwndClient,
+ATOM aItem,
+USHORT cfFormat,
+LPHANDLE lphdde
+)
+{
+
+ HRESULT hresult = NOERROR;
+ LPCLIENT lpclient;
+ FORMATETC formatetc;
+ STGMEDIUM medium;
+ // Due to a C7 bug, do not use a structure initialization for STGMEDIUM
+ medium.tymed = TYMED_NULL;
+ medium.hGlobal = 0;
+ medium.pUnkForRelease= NULL;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::RequestData(hwndClient=%x,aItem=%x(%ws),cfFormat=%x,lphdde=%x)\n",
+ this,
+ hwndClient,
+ aItem,
+ wAtomName(aItem),
+ cfFormat,
+ lphdde));
+ ChkC(this);
+
+ // If edit environment Send data if we can
+ if (aItem == aEditItems)
+ {
+ hresult = RequestDataStd (aItem, lphdde);
+ goto exitRtn;
+ }
+
+ hresult = FindItem ((LPOLESTR) MAKEINTATOM(aItem),(LPCLIENT FAR *)&lpclient);
+ if (hresult != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ ChkC (lpclient);
+
+ formatetc.cfFormat = cfFormat;
+ formatetc.ptd = lpclient->m_ptd;
+ formatetc.lindex = DEF_LINDEX;
+ formatetc.dwAspect = DVASPECT_CONTENT;
+ formatetc.tymed = TYMED_HGLOBAL;
+
+
+ hresult = ReportResult(0, DV_E_FORMATETC, 0, 0);
+ if (!lpclient->IsFormatAvailable (formatetc.cfFormat))
+ {
+ goto errRtn;
+ }
+
+
+ // Now ask the item for the given format data
+
+ SendDevInfo (hwndClient);
+
+ wSetTymed (&formatetc);
+ hresult = lpclient->GetData (&formatetc, &medium);
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "GetData returns hresult=%x\n",
+ hresult));
+ goto errRtn;
+ }
+ if (medium.tymed & ~(TYMED_HGLOBAL | TYMED_MFPICT | TYMED_GDI))
+ {
+ AssertSz (0, "Got a storage medium of type other than hGlobal");
+ goto errRtn;
+ }
+ if (cfFormat == CF_METAFILEPICT)
+ {
+ ChangeOwner (medium.hGlobal);
+ }
+
+
+ // Duplicate the DDE data
+ // medium.hGlobal is freed by MakeDdeData or by the client once the
+ // DDE_DATA is posted with *lphdde.
+ if (MakeDDEData (medium.hGlobal, cfFormat, lphdde, TRUE)){
+ // !!! Why do we have to duplicate the atom
+ DuplicateAtom (aItem);
+ hresult = NOERROR;
+ }
+ else
+ hresult = E_OUTOFMEMORY;
+
+errRtn:
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::RequestData() returning %x\n",
+ this, hresult));
+
+ return hresult;
+}
+
+
+
+// REVIEW: needs review. Item callvback has to be split
+
+// ItemCallback: Calback routine for the server to inform the
+// data changes. When the change message is received, DDE data
+// message is sent to each of the clients depending on the
+// options.
+
+INTERNAL_(HRESULT) CDefClient::ItemCallBack
+(
+ int msg, // notification message
+ LPOLESTR szNewName // for OLE_RENAMED notification
+)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::ItemCallBack(msg=%x,szNewName=%x)\n",
+ this,
+ szNewName));
+
+ HRESULT hresult = NOERROR;
+ BOOL bSaved;
+ LPCLIENT lpclientRename;
+ LPCLIENT lpclient;
+
+ ChkC(this);
+
+ if (msg == OLE_RENAMED) {
+
+ Assert (szNewName);
+ intrDebugOut((DEB_ITRACE,
+ "%x ::ItemCallBack(szNewName=(%ws))\n",
+ WIDECHECK(szNewName)));
+
+
+ if (!m_bContainer)
+ {
+ lpclient = (LPCLIENT)GetWindowLong (m_hwnd, 0);
+ Assert (lpclient==m_pdoc);
+ }
+ else
+ lpclient = this;
+
+ Assert (lpclient->m_chk==chkDefClient);
+
+ // Replace the internally-stored name
+ if (lpclient->m_aItem)
+ {
+ GlobalDeleteAtom (lpclient->m_aItem);
+ lpclient->m_aItem = wGlobalAddAtom (szNewName);
+ }
+
+
+ // find if any StdDocName item is present at all
+ if (lpclientRename =
+ lpclient->SearchItem ((LPOLESTR) MAKEINTATOM(aStdDocName)))
+ {
+ HANDLE hDdeData=NULL;
+
+ //
+ // We have a new name in UNICODE. Need to create a new
+ // name in ANSI.
+ //
+ LPSTR lpName = CreateAnsiFromUnicode(szNewName);
+
+ HANDLE hNewName = wNewHandle (lpName, strlen(lpName) + 1);
+
+ PrivMemFree(lpName);
+
+ // hNewName is freed by MakeDDEData
+
+ if (!MakeDDEData (hNewName, (int)g_cfBinary, &hDdeData, FALSE))
+ {
+ hresult = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ goto errrtn;
+ }
+
+ Assert (hDdeData);
+ lpclientRename->SendRenameMsgs (hDdeData);
+ GlobalFree (hDdeData);
+
+ // Post termination for each of the doc clients that did not
+ // advise on rename
+ lpclient->TerminateNonRenameClients (lpclientRename);
+ }
+
+
+ Assert (FALSE == lpclient->m_fEmbed);
+
+ // REVIEW: what is this?
+ //lpclient->m_fEmbed = FALSE;
+
+ hresult = NOERROR;
+
+ errrtn:
+ Assert (hresult == NOERROR);
+ goto exitRtn;
+
+ } else {
+
+ // Enumerate all the clients and send DDE_DATA if necessary.
+ bSaved = SendDataMsg (msg);
+
+ // REVIEW: Hack from 1.0 for old pre-OLE-library apps
+ if ((msg == OLE_SAVED) && m_fEmbed && !bSaved)
+ return ReportResult(0, RPC_E_DDE_CANT_UPDATE, 0, 0);
+
+ hresult = NOERROR;
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::ItemCallBack() returning hresult=%x\n",
+ this,hresult));
+
+ return(hresult);
+}
+
+
+// This func should definitely be replaced by use of MFC map. (IsEmpty)
+INTERNAL_(BOOL) AreNoClients (HANDLE hcli)
+{
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+
+ while (hcli) {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ {
+ Puth (hcli);
+ Putn();
+ Assert(0);
+ return TRUE;
+ }
+
+ phandle = (HANDLE *) pcli->info;
+ while (phandle < (HANDLE *)(pcli + 1))
+ {
+ if (*phandle)
+ {
+ LocalUnlock (hcli);
+ return FALSE;
+ }
+ phandle++;
+ phandle++;
+ }
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ }
+ return TRUE;
+}
+
+
+#ifdef _DEBUG
+// For use in CodeView
+// NOTE: Returns a static string
+INTERNAL_(LPOLESTR) a2s (ATOM a)
+{
+ static WCHAR sz[256];
+ GlobalGetAtomName (a, sz, 256);
+ return sz;
+}
+#endif
diff --git a/private/ole32/com/remote/dde/server/item2.cxx b/private/ole32/com/remote/dde/server/item2.cxx
new file mode 100644
index 000000000..20def4815
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/item2.cxx
@@ -0,0 +1,1400 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: item2.cxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 6-07-94 kevinro Converted to NT and commented
+//
+//----------------------------------------------------------------------------
+
+#include "ole2int.h"
+#include <dde.h>
+#include "ddeatoms.h"
+#include "ddedebug.h"
+#include "srvr.h"
+#include "itemutil.h"
+#include "trgt_dev.h"
+#include <stddef.h>
+#ifndef WIN32
+// #include <print.h>
+#endif
+
+ASSERTDATA
+
+
+INTERNAL_(void) CDefClient::TerminateNonRenameClients
+(
+LPCLIENT lprenameClient
+)
+{
+
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+ HANDLE hcli;
+ HWND hwndClient;
+ LPCLIENT lpdocClient;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::TerminateNonRenameClients(lprenClient=%x)\n",
+ this,
+ lprenameClient));
+
+ // items also keep the parents window handle.
+ hwndClient = m_hwnd;
+ lpdocClient = (LPCLIENT)GetWindowLong (m_hwnd, 0);
+
+
+ hcli = m_hcliInfo;
+ while (hcli)
+ {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ {
+ break;
+ }
+
+ phandle = (HANDLE *) (pcli->info);
+ while (phandle < (HANDLE *)(pcli + 1))
+ {
+ if (*phandle)
+ {
+ // This client is in the rename list. So, no termination
+ if(!FindClient (lprenameClient->m_hcliInfo, *phandle, FALSE))
+ {
+
+#ifdef KEVINRO_I_CHANGED_THIS
+//
+// BUGBUG: (KevinRo) I don't understand why this didn't just call Terminate() instead.
+// There may be the potential for problems on this PostMessageToClient, since it doesn't
+// do the ModalLoop stuff. It is going to busy wait by doing Peeks
+//
+// I have changed this to call Terminate
+//
+ PostMessageToClientWithReply ((HWND)*phandle,
+ WM_DDE_TERMINATE,
+ (UINT) hwndClient, NULL,
+ WM_DDE_TERMINATE);
+#endif
+ //
+ // Terminate will send a WM_DDE_TERMINATE at the client
+ //
+ Terminate((HWND)*phandle,hwndClient);
+
+ // delete this client from all the items lists.
+ lpdocClient->DeleteFromItemsList ((HWND)*phandle);
+ }
+ }
+ phandle++;
+ phandle++;
+ }
+
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::TerminateNonRenameClients\n",
+ this));
+
+}
+
+
+
+INTERNAL CDefClient::Terminate
+ (HWND hwndTo,
+ HWND hwndFrom)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::Terminate hwndTo=%x hwndFrom=%x\n",
+ this,
+ hwndTo,
+ hwndFrom));
+
+ CALLDATA CD;
+ IID iid = CLSID_NULL;
+ DDECALLDATA DdeCD;
+ HRESULT hresult;
+
+ DdeCD.hwndSvr = hwndTo;
+ DdeCD.hwndCli = hwndFrom;
+ DdeCD.wMsg = WM_DDE_TERMINATE;
+ DdeCD.wParam = (WPARAM)hwndFrom,
+ DdeCD.lParam = 0;
+ DdeCD.fInitialSend = FALSE;
+
+ CD.id = CALLDATAID_UNUSED;
+ CD.lid = iid;
+ CD.TIDCallee = 0;
+ CD.pRpcMsg = (LPVOID) &DdeCD;
+ CD.CallCat = CALLCAT_SYNCHRONOUS;
+ CD.Event = 0;
+
+ //
+ // Setting the pCallData variable effects the way that the
+ // DocWndProc handles WM_DDE_TERMINATE. If it is set, then this
+ // object initiated the terminate, and will not reply to the
+ // TERMINATE. It will allow us to leave the CallRunModalLoop
+ //
+ m_pCallData = &CD;
+
+ hresult = m_pCallControl->CallRunModalLoop(&CD);
+
+ m_pCallData = NULL;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::Terminate hresult = %x\n",
+ this,hresult));
+
+ return(hresult);
+}
+
+
+INTERNAL_(void) CDefClient::SendTerminateMsg ()
+{
+
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+ HANDLE hcli;
+ HWND hwnd;
+ LPCLIENT lpdocClient;
+ static int staticcounter;
+ int counter = ++staticcounter;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::SendTerminateMsg\n",
+ this));
+
+ // items also keep the document's window handle
+
+ Assert (IsWindow (m_hwnd));
+
+ if (!IsWindow (m_hwnd))
+ {
+ goto exitRtn;
+ }
+
+ hwnd = m_hwnd;
+
+ lpdocClient = (LPCLIENT)GetWindowLong (m_hwnd, 0);
+
+ Assert (lpdocClient);
+
+ if (NULL==lpdocClient)
+ {
+ goto exitRtn;
+ }
+
+ Assert (lpdocClient==m_pdoc);
+ AssertIsDoc (lpdocClient);
+ // If "this" is a document (container) then iterate through
+ // and terminate all its client windows. If "this" is an item
+ // just terminate that item's client windows.
+ hcli = m_bContainer ? lpdocClient->m_hcli : m_hcliInfo;
+ while (hcli)
+ {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ {
+ goto exitRtn;
+ }
+ phandle = (HANDLE *) (pcli->info);
+ while (phandle < (HANDLE *)(pcli + 1))
+ {
+ if ((HWND)*phandle)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%x ::SendTerminateMsg on hwnd=%x\n",
+ this,
+ (HWND)*phandle));
+
+ Terminate ((HWND)*phandle, hwnd);
+
+ Assert (lpdocClient->m_cClients > 0);
+
+ lpdocClient->m_cClients--;
+
+ HWND hwndClient = *(HWND *)phandle;
+ // This window is no longer a client.
+
+ // Remove window from document's master list
+ // and its item's list.
+ lpdocClient->DeleteFromItemsList (hwndClient);
+ }
+ //
+ // (KevinRo): Don't understand why the phandle is
+ // incremented twice. This is the same as the original
+ // code. Leaving it for now, since I don't have enough
+ // information.
+ //
+ phandle++;
+ phandle++;
+ }
+
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::SendTerminateMsg\n",
+ this));
+
+}
+
+
+
+// SendRenameMsg: enumerates the clients for the rename item
+// and sends rename message for all the clients.
+
+INTERNAL_(void) CDefClient::SendRenameMsgs
+(
+HANDLE hddeRename
+)
+{
+ ATOM aData = NULL;
+ HANDLE hdde = NULL;
+ PCLINFO pclinfo = NULL;
+ HWND hwndClient;
+
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+ HANDLE hcli;
+ HANDLE hcliInfo;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::SendRenameMsgs(hddeRename=%x)\n",
+ this,
+ hddeRename));
+
+ hcli = m_hcliInfo;
+ LPARAM lp;
+ while (hcli)
+ {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ {
+ goto exitRtn;
+ }
+
+
+ phandle = (HANDLE *) (pcli->info);
+ while (phandle < (HANDLE *)(pcli + 1))
+ {
+ if (*phandle++)
+ {
+ hdde = NULL;
+ aData = NULL;
+
+ if (!(pclinfo = (PCLINFO) LocalLock (hcliInfo = *phandle++)))
+ {
+ goto exitRtn;
+ }
+
+
+ // Make the item atom with the options.
+ aData = DuplicateAtom (aStdDocName);
+ hdde = UtDupGlobal (hddeRename,GMEM_MOVEABLE);
+
+ hwndClient = pclinfo->hwnd;
+ LocalUnlock (hcliInfo);
+
+ // Post the message
+
+ lp = MAKE_DDE_LPARAM(WM_DDE_DATA,hdde,aData);
+
+ if (!PostMessageToClient (hwndClient,
+ WM_DDE_DATA,
+ (UINT) m_hwnd,
+ lp))
+ {
+ DDEFREE(WM_DDE_DATA,lp);
+ if (hdde)
+ GlobalFree (hdde);
+ if (aData)
+ GlobalDeleteAtom (aData);
+ }
+ }
+ else
+ {
+ phandle++;
+ }
+
+ }
+
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::SendRenameMsgs void return\n",
+ this));
+
+}
+
+
+
+INTERNAL_(BOOL) CDefClient::SendDataMsg
+(
+WORD msg // notification message
+)
+{
+
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+ HANDLE hcli;
+ BOOL bSaved = FALSE;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::SendDataMsg(msg=%x)\n",
+ this,
+ msg));
+
+ hcli = m_hcliInfo;
+ while (hcli)
+ {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ {
+ break;
+ }
+ phandle = (HANDLE *) (pcli->info);
+ while (phandle < (HANDLE *)(pcli + 1)) {
+ if (*phandle++)
+ bSaved = SendDataMsg1 (*phandle++, msg);
+ else
+ phandle++;
+ }
+
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::SendDataMsg() returns %x)\n",
+ this,bSaved));
+
+ return bSaved;
+}
+
+
+
+//SendDataMsg: Send data to the clients, if the data change options
+//match the data advise options.
+
+INTERNAL_(BOOL) CDefClient::SendDataMsg1
+(
+HANDLE hclinfo, // handle of the client info
+WORD msg // notification message
+)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::SendDataMsg1(hclinfo=%x,msg=%x)\n",
+ this,
+ hclinfo,
+ msg));
+
+ PCLINFO pclinfo = NULL;
+ HANDLE hdde = NULL;
+ ATOM aData = NULL;
+ HRESULT retval;
+ BOOL bSaved = FALSE;
+
+
+ ChkC (this);
+ if (m_lpdataObj == NULL) goto errRtn;
+
+ // LATER: Allow server to give us other tymed's beside HGLOBAL and do
+ // the conversion ourselves, e.g., IStorageToHGlobal()
+
+ FORMATETC formatetc;// = {0, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
+ STGMEDIUM medium;// = {TYMED_NULL, NULL, NULL};
+ formatetc.ptd = m_ptd;
+ formatetc.dwAspect = DVASPECT_CONTENT;
+ formatetc.lindex = DEF_LINDEX;
+ formatetc.tymed = TYMED_HGLOBAL;
+ medium.tymed = TYMED_NULL;
+ medium.hGlobal=0; // not really necessary
+ medium.pUnkForRelease = NULL;
+
+ if (!(pclinfo = (PCLINFO) LocalLock (hclinfo)))
+ {
+ goto errRtn;
+ }
+
+ // if the client dead, then no message
+ if (!IsWindowValid(pclinfo->hwnd))
+ {
+ goto errRtn;
+ }
+
+
+ //
+ // (KevinRo) UPDATE was not defined in the OLE 2.01 code base
+ //
+#ifdef UPDATE
+ // OLE_SAVED is what 1.0 clients expect to get for embedded objects.
+ if (msg==OLE_CHANGED && m_fEmbed)
+ msg=OLE_SAVED;
+#endif
+
+ if (pclinfo->options & (0x0001 << msg))
+ {
+ bSaved = TRUE;
+ SendDevInfo (pclinfo->hwnd);
+
+ // send message if the client needs data for every change or
+ // only for the selective ones he wants.
+
+ // now look for the data option.
+ if (pclinfo->bnative){
+ // prepare native data
+ if (pclinfo->bdata){
+
+ // Wants the data with DDE_DATA message
+ // Get native data from the server.
+
+ // GetData
+ formatetc.cfFormat = g_cfNative;
+ wSetTymed (&formatetc);
+ retval = GetData (&formatetc, &medium);
+
+ if (retval != NOERROR)
+ {
+ Assert(0);
+ goto errRtn;
+ }
+ Assert (medium.tymed==TYMED_HGLOBAL);
+ Assert (medium.hGlobal);
+
+ // Prepare the DDE data block.
+ // REVIEW: MakeDDEData frees medium.hGlobal manually, but should
+ // really call ReleaseStgMedium.
+ if(!MakeDDEData (medium.hGlobal, (int)g_cfNative, (LPHANDLE)&hdde, FALSE))
+ {
+ goto errRtn;
+ }
+ }
+
+
+ // Make the item atom with the options.
+ aData = MakeDataAtom (m_aItem, msg);
+
+ intrDebugOut((DEB_ITRACE,
+ "%x ::SendDataMsg1 send NativeData to hwnd=%x"
+ "format %x\n",
+ this,
+ pclinfo->hwnd,
+ pclinfo->format));
+
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_DATA,hdde,aData);
+ if (!PostMessageToClient(pclinfo->hwnd,
+ WM_DDE_DATA,
+ (UINT) m_hwnd,
+ lp))
+
+
+ {
+ DDEFREE(WM_DDE_DATA,lp);
+ //
+ // The two data items will be free'd on exit
+ //
+ goto errRtn;
+ }
+ hdde = NULL;
+ aData = NULL;
+ }
+
+
+ // Now post the data for the display format
+
+ if (pclinfo->format)
+ {
+ if (pclinfo->bdata)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%x ::SendDataMsg1 GetData on cf = %x\n",
+ pclinfo->format));
+ // Must reset because previous call to GetData set it.
+ medium.tymed = TYMED_NULL;
+
+ // GetData
+ formatetc.cfFormat = pclinfo->format;
+ wSetTymed (&formatetc);
+ Assert (IsValidInterface (m_lpdataObj));
+ retval = m_lpdataObj->GetData (&formatetc, &medium);
+
+ if (retval != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "m_lpdataObj->GetData returns %x\n",
+ retval));
+ goto errRtn;
+ }
+
+
+ if (pclinfo->format == CF_METAFILEPICT)
+ ChangeOwner (medium.hGlobal);
+
+ if(!MakeDDEData (medium.hGlobal, pclinfo->format, (LPHANDLE)&hdde, FALSE))
+ goto errRtn;
+
+ }
+
+ // atom is deleted. So, we need to duplicate for every post
+ aData = MakeDataAtom (m_aItem, msg);
+ // now post the message to the client;
+ intrDebugOut((DEB_ITRACE,
+ "%x ::SendDataMsg1 send PresentationData to hwnd=%x"
+ " cf=%x\n",
+ this,
+ pclinfo->hwnd,
+ pclinfo->format));
+
+ LPARAM lp = MAKE_DDE_LPARAM(WM_DDE_DATA,hdde,aData);
+
+ if (!PostMessageToClient(pclinfo->hwnd,
+ WM_DDE_DATA,
+ (UINT) m_hwnd,
+ lp))
+ {
+ DDEFREE(WM_DDE_DATA,lp);
+ goto errRtn;
+ }
+
+ hdde = NULL;
+ aData = NULL;
+ }
+
+ }
+
+
+errRtn:
+ if (pclinfo)
+ LocalUnlock (hclinfo);
+
+ if (hdde)
+ GlobalFree (hdde);
+
+ if (aData)
+ GlobalDeleteAtom (aData);
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::SendDataMsg1() returns %x\n",
+ this,bSaved));
+
+
+ return bSaved;
+
+}
+
+
+
+// FixWriteBug
+//
+// `Write' gives a target device that is missing a NULL between
+// the device name and the driver name. This function creates
+// a fixed 1.0 target device.
+//
+// REVIEW: There is another Write bug we should work around.
+// Write does not send the "extra bytes" that are supposed to follow
+// the DEVMODE. It puts the Environment immediately after the DEVMODE.
+// So the driver will read the Environment thinking it is the extra bytes.
+// To fix this, FixWriteBug() should zero out the Environment bytes; the
+// 2.0 target device does not use them anyway.
+//
+ INTERNAL FixWriteBug
+ (HANDLE hTD,
+ LPHANDLE ph)
+{
+ HRESULT hresult;
+ LPBYTE pChunk2;
+ LPBYTE pNewChunk2;
+ const LPCOLETARGETDEVICE ptd1 = (LPCOLETARGETDEVICE) GlobalLock (hTD);
+ RetZS (ptd1, E_OUTOFMEMORY);
+
+ HANDLE hNew = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE,
+ GlobalSize (hTD) + 1);
+ RetZS (hNew, E_OUTOFMEMORY);
+ const LPBYTE pNew = (LPBYTE) GlobalLock (hNew);
+ RetZS (pNew, E_OUTOFMEMORY);
+ ULONG cbChunk1 = 7 * sizeof(UINT) + ptd1->otdDriverNameOffset;
+ ULONG cbChunk2 = GlobalSize (hTD) - cbChunk1;
+ ErrZS (!IsBadWritePtr (pNew, (UINT)cbChunk1), E_OUTOFMEMORY);
+ memcpy (pNew, ptd1, cbChunk1);
+ pNew[cbChunk1] = '\0'; // insert the missing NULL
+
+ pNewChunk2 = pNew + cbChunk1 + 1;
+ pChunk2 = (LPBYTE)ptd1 + cbChunk1;
+ ErrZS (!IsBadWritePtr (pNewChunk2, (UINT)cbChunk2), E_OUTOFMEMORY);
+ Assert (!IsBadReadPtr (pChunk2, (UINT)cbChunk2));
+ memcpy (pNewChunk2, pChunk2, cbChunk2);
+
+ // Fix up the offsets to accomodate the added NULL
+ #define macro(x) if (ptd1->otd##x##Offset > ptd1->otdDeviceNameOffset)\
+ ((LPOLETARGETDEVICE)pNew)->otd##x##Offset++;
+ macro (DriverName)
+ macro (PortName)
+ macro (ExtDevmode)
+ macro (Environment)
+ #undef macro
+
+ GlobalUnlock (hNew);
+ GlobalUnlock (hTD);
+ *ph = hNew;
+ return NOERROR;
+
+ errRtn:
+ if (pNew)
+ GlobalUnlock (hNew);
+ if (ptd1)
+ GlobalUnlock (hTD);
+ return hresult;
+}
+
+
+
+
+
+
+// Convert10TargetDevice
+//
+INTERNAL Convert10TargetDevice
+ (HANDLE hTD, // 1.0 Target Device
+ DVTARGETDEVICE FAR* FAR* pptd2) // Out parm, corresponding 2.0 TD
+{
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN Convert10TargetDevice hTD=%x\n",hTD));
+
+ ULONG cbData1, cbData2;
+
+ if (NULL==hTD)
+ {
+ Assert(0);
+ return ReportResult(0, E_INVALIDARG, 0, 0);
+ }
+
+ if (*pptd2)
+ {
+ // delete old target device
+ PrivMemFree(*pptd2);
+ *pptd2 = NULL;
+ }
+
+ LPOLETARGETDEVICE ptd1 = (LPOLETARGETDEVICE) GlobalLock (hTD);
+
+ RetZS (ptd1, E_OUTOFMEMORY);
+
+ if ((ptd1->otdDeviceNameOffset < ptd1->otdDriverNameOffset)
+ && (ptd1->otdDeviceNameOffset
+ + strlen (LPSTR(((BYTE *)ptd1->otdData) +
+ ptd1->otdDeviceNameOffset)) + 1 > ptd1->otdDriverNameOffset))
+ {
+ // No NULL between device and driver name
+ HANDLE hNew;
+ GlobalUnlock (hTD);
+ RetErr (FixWriteBug (hTD, &hNew));
+ HRESULT hresult = Convert10TargetDevice (hNew, pptd2);
+ Verify (0==GlobalFree (hNew));
+ return hresult;
+ }
+ // Word Bug
+ DEVMODEA UNALIGNED *pdevmode = (DEVMODEA UNALIGNED *)
+ (((BYTE *)ptd1->otdData)+ ptd1->otdExtDevmodeOffset);
+
+ if ( HIBYTE(pdevmode->dmSpecVersion) < 3
+ || HIBYTE(pdevmode->dmSpecVersion) > 6
+ || pdevmode->dmDriverExtra > 0x1000)
+ {
+ if (0==ptd1->otdEnvironmentSize)
+ {
+ // Sometimes Word does not give an environment.
+ ptd1->otdExtDevmodeOffset = 0;
+ ptd1->otdExtDevmodeSize = 0;
+ }
+ else
+ {
+ // DevMode is garbage, use environment instead.
+ ptd1->otdExtDevmodeOffset = ptd1->otdEnvironmentOffset;
+ ptd1->otdExtDevmodeSize = ptd1->otdEnvironmentSize;
+ }
+ }
+
+ // These next assert does not HAVE to be true,
+ // but it's a sanity check.
+ Assert (ptd1->otdDeviceNameOffset
+ + strlen (LPSTR(((BYTE *)ptd1->otdData) +
+ ptd1->otdDeviceNameOffset)) + 1
+ == ptd1->otdDriverNameOffset);
+
+
+ // Excel has zeroes for DevMode and Environment offsets and sizes
+
+ // Calculate size of Data block. Many 1.0 clients don't make their
+ // target device data block big enough for the DEVMODE.dmDriverExtra
+ // bytes (and they don't copy those bytes either). We can't reconstruct
+ // the bytes out of thin air, but we can at least make sure there's not
+ // a GP fault when the printer driver tries to access those bytes in
+ // a call to CreateDC. Any extra bytes are zeroed.
+ cbData2 = ptd1->otdExtDevmodeOffset + ptd1->otdExtDevmodeSize;
+
+ if (ptd1->otdExtDevmodeOffset != 0)
+ {
+ cbData2 += ((DEVMODEA UNALIGNED *)((LPBYTE)ptd1->otdData +
+ ptd1->otdExtDevmodeOffset))->dmDriverExtra;
+ }
+
+ cbData2 = max (cbData2,
+ ptd1->otdPortNameOffset + strlen (LPCSTR(
+ ((BYTE *)ptd1->otdData) + ptd1->otdPortNameOffset)) + 1);
+
+ // Calculate size of OLE2 Target Device
+ //
+ // Its the size of the DVTARGETDEVICE header, plus the cbData2
+ // The definition of DVTARGETDEVICE currently uses an unsized array
+ // of bytes at the end, therefore we can not just do a sizeof().
+ //
+
+ ULONG cbTD2 = SIZEOF_DVTARGETDEVICE_HEADER + cbData2;
+
+ // Allocate OLE2 Target Device
+ *pptd2 = (DVTARGETDEVICE FAR*) PrivMemAlloc(cbTD2);
+ if (IsBadWritePtr (*pptd2, cbTD2)
+ || IsBadWritePtr ((*pptd2)->tdData, cbData2))
+ {
+ AssertSz (0, "out of memory");
+ GlobalUnlock (hTD);
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+ _fmemset (*pptd2, '\0', cbTD2);
+
+ // OLE2 offsets are from the beginning of the DVTARGETDEVICE
+ const ULONG cbOffset = offsetof (DVTARGETDEVICE, tdData);
+
+ // Fill in new Target Device
+
+ (*pptd2)->tdSize = cbTD2;
+
+ #define Convert(a) \
+ ((*pptd2)->td##a##Offset = (USHORT)(ptd1->otd##a##Offset + cbOffset))
+
+ Convert (DeviceName);
+ Convert (DriverName);
+ Convert (PortName);
+ if (ptd1->otdExtDevmodeOffset != 0)
+ Convert (ExtDevmode);
+ else // Excel uses 0
+ (*pptd2)->tdExtDevmodeOffset = 0;
+
+ // Calculate size of 1.0 data block in case the 1.0 target
+ // device is incorrectly not big enough.
+ cbData1 = (size_t) GlobalSize(hTD) - offsetof (OLETARGETDEVICE, otdData);
+
+ #undef Convert
+ _fmemcpy ((*pptd2)->tdData, ptd1->otdData, min(cbData1, cbData2));
+
+ GlobalUnlock (hTD);
+
+ //
+ // At this point, pptd2 holds an ANSI version of a DVTARGET device
+ //
+ // Now, we need to convert it to a UNICODE version. There are routines
+ // for doing this in the UTILS.H file.
+ //
+
+ DVTDINFO dvtdInfo;
+ DVTARGETDEVICE * pdvtd32 = NULL;
+ HRESULT hr;
+
+ hr = UtGetDvtd16Info(*pptd2, &dvtdInfo);
+ if (hr != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ pdvtd32 = (DVTARGETDEVICE *) PrivMemAlloc(dvtdInfo.cbConvertSize);
+
+ if (pdvtd32 == NULL)
+ {
+ goto errRtn;
+ }
+
+ hr = UtConvertDvtd16toDvtd32(*pptd2, &dvtdInfo, pdvtd32);
+
+ if (hr != NOERROR)
+ {
+ PrivMemFree(pdvtd32);
+ pdvtd32=NULL;
+ }
+
+errRtn:
+
+ PrivMemFree(*pptd2);
+ *pptd2 = pdvtd32;
+
+ return hr;
+}
+//+---------------------------------------------------------------------------
+//
+// Method: CDefClient::PokeStdItems
+//
+// Synopsis: Pokes the data for the standard items.
+//
+// Effects:
+//
+// For StdHostnames, StdDocDimensions and SetColorScheme the data is
+// sent immediately and for the the StdTargetDeviceinfo the
+// data is set in each client block and the data is sent just
+// before the GetData call for rendering the right data.
+//
+// Arguments: [hwndClient] --
+// [aItem] --
+// [hdata] --
+// [index] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 6-07-94 kevinro Commented
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CDefClient::PokeStdItems(HWND hwndClient,
+ ATOM aItem,
+ HANDLE hdata,
+ int index)
+{
+ DDEDATA FAR * lpdata = NULL;
+ HANDLE hnew = NULL;
+ LPHOSTNAMES lphostnames;
+ HRESULT retval = E_OUTOFMEMORY;
+ WORD format;
+ BOOL fRelease;
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CDefClient::PokeStdItems(hwndClient=%x,aItem=%x(%ws)hdata=%x,index=%x)\n",
+ this,
+ hwndClient,
+ aItem,
+ wAtomName(aItem),
+ hdata,
+ index));
+
+ if (m_fGotEditNoPokeNativeYet)
+ {
+ // We got StdEdit, but instead of getting Poke for native data,
+ // we got poke for some std items. So we want to generate InitNew()
+ // call for the object.
+
+ DoInitNew(); // the function clears the flag
+ }
+
+ if(!(hdata && (lpdata = (DDEDATA FAR *)GlobalLock (hdata))))
+ {
+ goto errRtn;
+ }
+
+ format = lpdata->cfFormat;
+ fRelease = lpdata->fRelease;
+
+ AssertSz (format == (int)g_cfBinary, "Format is not binary");
+
+ // we have extracted the data successfully.
+ m_lpoleObj = m_lpoleObj;
+
+ if (index == STDHOSTNAMES)
+ {
+ lphostnames = (LPHOSTNAMES)lpdata->Value;
+ //
+ // The client should have sent the HOSTNAMES in ANSI. This
+ // means we need to convert them to UNICODE before we can
+ // use them.
+ //
+ LPOLESTR lpstrClient = CreateUnicodeFromAnsi((LPSTR)(lphostnames->data) + lphostnames->clientNameOffset);
+ LPOLESTR lpstrDoc = CreateUnicodeFromAnsi((LPSTR)(lphostnames->data) + lphostnames->documentNameOffset);
+
+ intrDebugOut((DEB_ITRACE,
+ "%p ::PokeStdItems setting hostnames Client(%ws) Doc(%ws) \n",
+ this,
+ lpstrClient,
+ lpstrDoc));
+
+ retval = (HRESULT)m_lpoleObj->SetHostNames(lpstrClient,lpstrDoc);
+
+ if (retval==NOERROR)
+ {
+ m_fDidRealSetHostNames = TRUE;
+ }
+
+ PrivMemFree(lpstrClient);
+ PrivMemFree(lpstrDoc);
+
+ goto end;
+ }
+
+
+ if (index == STDDOCDIMENSIONS)
+ {
+
+ SIZEL size;
+ size.cy = ((LPRECT16)(lpdata->Value))->top;
+ size.cx = ((LPRECT16)(lpdata->Value))->left;
+ intrDebugOut((DEB_ITRACE,
+ "%p ::PokeStdItems STDDOCDIMENSIONS cy=%x cx=%x\n",
+ this,
+ size.cy,
+ size.cx));
+ retval = m_lpoleObj->SetExtent (DVASPECT_CONTENT, &size);
+
+ goto end;
+
+ }
+
+
+ if (index == STDCOLORSCHEME) {
+ intrDebugOut((DEB_ITRACE,
+ "%p ::PokeStdItems setting STDCOLORSCHEME\n",this));
+
+ retval = m_lpoleObj->SetColorScheme((LPLOGPALETTE)(lpdata->Value));
+
+ goto end;
+ }
+
+ // Target Device
+ if (index == STDTARGETDEVICE)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%p ::PokeStdItems setting STDTARGETDEVICE\n",this));
+
+ if (!(hnew = MakeItemData ((DDEPOKE FAR *)lpdata, hdata, format)))
+ goto errRtn;
+
+ retval = Convert10TargetDevice (hnew, &m_ptd);
+ goto end;
+
+ }
+ retval = E_UNEXPECTED;
+
+ intrAssert(!"::PokeStdItems - Unknown index\n");
+
+ //
+ // (KevinRo) Found the following line already commented out.
+ //
+ //(HRESULT)SetStdInfo (hwndClient, (LPOLESTR) (MAKELONG(STDTARGETDEVICE,0)),hnew);
+
+end:
+errRtn:
+ if (hnew)
+ // can only be global memory block
+ GlobalFree (hnew);
+
+ if (lpdata) {
+ GlobalUnlock (hdata);
+ if (retval == NOERROR && fRelease)
+ GlobalFree (hdata);
+ }
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT CDefClient::PokeStdItems() hresult = %x\n",
+ this,
+ retval));
+
+ return retval;
+}
+
+
+
+
+
+
+// SetStdInfo: Sets the targetdevice info. Creates a client
+// for "StdTargetDevice". This item is created only within the
+// lib and it is never visible in server app. When the change
+// message comes from the server app, before we ask for
+// the data, we send the targetdevice info if there is
+// info for the client whom we are trying to send the data
+// on advise.
+
+
+INTERNAL_(HRESULT) CDefClient::SetStdInfo
+(
+HWND hwndClient,
+LPOLESTR lpitemname,
+HANDLE hdata
+)
+{
+ HANDLE hclinfo = NULL;
+ PCLINFO pclinfo = NULL;
+ LPCLIENT lpclient;
+ HRESULT retval = NOERROR;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::SetStdInfo(hwndClient=%x,ItemName=(%ws),hdata=%x)\n",
+ this,
+ hwndClient,
+ lpitemname,
+ hdata));
+ //
+ // first create/find the StdTargetDeviceItem.
+ //
+
+ if ((lpclient = SearchItem (lpitemname)) == NULL)
+ {
+ retval = (HRESULT)RegisterItem (lpitemname,(LPCLIENT FAR *)&lpclient, FALSE);
+ if (retval != NOERROR)
+ {
+ goto errRtn;
+ }
+ }
+
+ if(hclinfo = FindClient (lpclient->m_hcliInfo, hwndClient, FALSE))
+ {
+ if (pclinfo = (PCLINFO) LocalLock (hclinfo))
+ {
+ if (pclinfo->hdevInfo)
+ GlobalFree (pclinfo->hdevInfo);
+ pclinfo->bnewDevInfo = TRUE;
+ if (hdata)
+ pclinfo->hdevInfo = UtDupGlobal (hdata,GMEM_MOVEABLE);
+ else
+ pclinfo->hdevInfo = NULL;
+ pclinfo->hwnd = hwndClient;
+ LocalUnlock (hclinfo);
+
+ // We do not have to reset the client because we did not
+ // change the handle it self.
+ }
+ }
+ else
+ {
+ // Create the client structure to be attcahed to the object.
+ hclinfo = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof (CLINFO));
+ if (hclinfo == NULL || (pclinfo = (PCLINFO) LocalLock (hclinfo)) == NULL)
+ goto errRtn;
+
+ pclinfo->bnewDevInfo = TRUE;
+ if (hdata)
+ pclinfo->hdevInfo = UtDupGlobal (hdata,GMEM_MOVEABLE);
+ else
+ pclinfo->hdevInfo = NULL;
+
+ pclinfo->hwnd = hwndClient;
+ LocalUnlock (hclinfo);
+
+
+ // Now add this client to item client list
+ // !!! This error recovery is not correct.
+ if (!AddClient ((LPHANDLE)&lpclient->m_hcliInfo, hwndClient, hclinfo))
+ goto errRtn;
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::SetStdInfo() hresult=%x\n",
+ this,retval));
+
+ return retval;
+errRtn:
+ Assert(0);
+ if (pclinfo)
+ LocalUnlock (hclinfo);
+
+ if (hclinfo)
+ LocalFree (hclinfo);
+
+ retval = E_OUTOFMEMORY;
+ goto exitRtn;
+}
+
+
+// SendDevInfo: Sends targetdevice info to the the object.
+// Caches the last targetdevice info sent to the object.
+// If the targetdevice block is same as the one in the
+// cache, then no targetdevice info is sent.
+// (!!! There might be some problem here getting back
+// the same global handle).
+
+INTERNAL_(void) CDefClient::SendDevInfo
+(
+HWND hWndCli
+)
+{
+
+ HANDLE hclinfo = NULL;
+ PCLINFO pclinfo = NULL;
+ HANDLE hdata;
+ LPCLIENT lpdocClient;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::SendDevInfo(hwndCli=%x)\n",
+ this,
+ hWndCli));
+#if 0
+ if (!m_bContainer)
+ lpdocClient = (LPCLIENT)GetWindowLong (m_hwnd, 0);
+ else
+ lpdocClient = this;
+#endif
+
+ // find if any StdTargetDeviceInfo item is present at all
+ AssertIsDoc(m_pdoc);
+ lpdocClient = m_pdoc->SearchItem ((LPOLESTR) (MAKELONG(STDTARGETDEVICE, 0)));
+ if (lpdocClient == NULL)
+ {
+ goto exitRtn;
+ }
+
+ hclinfo = FindClient (lpdocClient->m_hcliInfo, hWndCli, FALSE);
+
+ // This client has not set any target device info. no need to send
+ // any stdtargetdevice info
+ if (hclinfo != NULL) {
+ if (!(pclinfo = (PCLINFO)LocalLock (hclinfo)))
+ goto end;
+
+ // if we cached it, do not send it again.
+ if ((!pclinfo->bnewDevInfo) && pclinfo->hdevInfo == m_hdevInfo)
+ goto end;
+
+ pclinfo->bnewDevInfo = FALSE;
+ if(!(hdata = UtDupGlobal (pclinfo->hdevInfo,GMEM_MOVEABLE)))
+ goto end;
+ } else {
+
+ // already screen
+ if (!m_hdevInfo)
+ goto end;
+
+ //for screen send NULL.
+ hdata = NULL;
+ }
+
+
+
+ if (pclinfo)
+ {
+ m_hdevInfo = pclinfo->hdevInfo;
+ }
+ else
+ {
+ m_hdevInfo = NULL;
+ }
+
+
+
+ // !!! error case who frees the data?'
+
+end:
+ if (pclinfo)
+ LocalUnlock (hclinfo);
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::SendDevInfo(hwndCli=%x)\n",
+ this,
+ hWndCli));
+ return;
+}
+
+
+
+
+// Constructor
+CDefClient::CDefClient (LPUNKNOWN pUnkOuter): m_Unknown (this),
+ m_OleClientSite (this),
+ m_AdviseSink (this)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::CDefClient(pUnkOuter=%x)\n",
+ this,
+ pUnkOuter));
+
+ m_pUnkOuter = pUnkOuter ? pUnkOuter : &m_Unknown;
+ m_bContainer = TRUE;
+ m_lpoleObj = NULL;
+ m_lpdataObj = NULL;
+ m_bCreateInst = FALSE;
+ m_bTerminate = FALSE;
+ m_termNo = 0;
+ m_hcli = NULL;
+ m_lpNextItem = NULL;
+ m_cRef = 0;
+ m_hwnd = (HWND)0;
+ m_hdevInfo = NULL;
+ m_hcliInfo = NULL;
+ m_fDidRealSetHostNames= FALSE;
+ m_fDidSetClientSite = FALSE;
+ m_fGotDdeAdvise = FALSE;
+ m_fCreatedNotConnected = FALSE;
+ m_fInOnClose = FALSE;
+ m_fInOleSave = FALSE;
+ m_dwConnectionOleObj = 0L;
+ m_dwConnectionDataObj = 0L;
+ m_fGotStdCloseDoc = FALSE;
+ m_fEmbed = FALSE;
+ m_cClients = 0;
+ m_plkbytNative = NULL;
+ m_pstgNative = NULL;
+ m_fRunningInSDI = FALSE;
+ m_psrvrParent = NULL;
+ m_ptd = NULL;
+ m_pdoc = NULL;
+ m_chk = chkDefClient;
+ m_ExecuteAck.f = FALSE;
+ m_fGotEditNoPokeNativeYet = FALSE;
+ m_fLocked = FALSE;
+ m_pCallData = NULL;
+ m_pCallControl = NULL;
+ // CDefClient::Create does all the real work.
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::CDefClient(pUnkOuter=%x)\n",
+ this,
+ pUnkOuter));
+
+}
+
+
+CDefClient::~CDefClient (void)
+{
+ // This should be more object-oriented.
+ // But right now, this BOOL tells us what kind of obj
+ // (doc or item) "this" is
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::~CDefClient\n",
+ this));
+
+ Puts ("~CDefClient "); Puta(m_aItem); Putn();
+ BOOL fDoc = (m_pdoc==this);
+
+ Assert (m_chk==chkDefClient);
+
+ ReleaseObjPtrs ();
+
+ if (m_pdoc && !fDoc)
+ {
+ Assert (m_pdoc->m_chk==chkDefClient);
+ m_pdoc->m_pUnkOuter->Release();
+ }
+ if (fDoc)
+ {
+ // delete all the items(objects) for this doc
+ DeleteAllItems ();
+ if (m_fRunningInSDI && m_psrvrParent
+ && m_psrvrParent->QueryRevokeClassFactory())
+ {
+ m_psrvrParent->Revoke();
+ }
+
+ }
+
+ if (ISATOM(m_aItem))
+ GlobalDeleteAtom (m_aItem);
+ if (m_plkbytNative)
+ {
+ m_plkbytNative->Release();
+ Assert (m_pstgNative);
+ // They always go together
+ }
+ if (m_pstgNative)
+ m_pstgNative->Release();
+ if (m_ptd)
+ PrivMemFree(m_ptd);
+
+ // Delete client advise info
+ DeleteAdviseInfo ();
+ if (fDoc && IsWindow(m_hwnd))
+ {
+ SSDestroyWindow (m_hwnd);
+ }
+ if (m_pCallControl)
+ {
+ ReleaseDdeCallControlInterface();
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDefClient::~CDefClient\n",
+ this));
+
+}
+
+
+//
+// Unknown Implementation
+//
+
+STDMETHODIMP NC(CDefClient,CUnknownImpl)::QueryInterface
+ (REFIID iid,
+ LPVOID FAR* ppv)
+{
+ intrDebugOut((DEB_ITRACE,"%p CDefClient::QueryInterface()\n",this));
+
+ if (iid == IID_IUnknown)
+ {
+ *ppv = (LPVOID) &m_pDefClient->m_Unknown;
+ AddRef();
+ return NOERROR;
+ }
+ else if (iid==IID_IAdviseSink)
+ *ppv = (LPVOID) &m_pDefClient->m_AdviseSink;
+ else if (iid==IID_IOleClientSite)
+ *ppv = (LPVOID) &m_pDefClient->m_OleClientSite;
+ else
+ {
+ *ppv = NULL;
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+ m_pDefClient->m_pUnkOuter->AddRef();
+
+ return NOERROR;
+}
+
+
+STDMETHODIMP_(ULONG) NC(CDefClient,CUnknownImpl)::AddRef()
+{
+ intrDebugOut((DEB_ITRACE,
+ "%p CDefClient::AddRef() returns %x\n",
+ this,
+ m_pDefClient->m_cRef+1));
+
+ return ++m_pDefClient->m_cRef;
+}
+
+
+STDMETHODIMP_(ULONG) NC(CDefClient,CUnknownImpl)::Release()
+{
+ AssertSz (m_pDefClient->m_cRef, "Release is being called on ref count of zero");
+ if (--m_pDefClient->m_cRef == 0)
+ {
+ delete m_pDefClient;
+ intrDebugOut((DEB_ITRACE,
+ "%p CDefClient::Release() returns 0\n",
+ this));
+ return 0;
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%p CDefClient::Release() returns %x\n",
+ this,
+ m_pDefClient->m_cRef));
+
+ return m_pDefClient->m_cRef;
+}
diff --git a/private/ole32/com/remote/dde/server/itemutil.cxx b/private/ole32/com/remote/dde/server/itemutil.cxx
new file mode 100644
index 000000000..c0ba1b0f0
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/itemutil.cxx
@@ -0,0 +1,516 @@
+// itemutil.h//
+// routines used by item.cpp
+// They used to be in item.cpp but it got too big.
+
+
+#include "ole2int.h"
+#include "srvr.h"
+#include "itemutil.h"
+#include "ddedebug.h"
+
+ASSERTDATA
+
+
+//ScanItemOptions: Scan for the item options like Close/Save etc.
+
+INTERNAL_(HRESULT) ScanItemOptions
+(
+LPOLESTR lpbuf,
+int far *lpoptions
+)
+{
+
+ ATOM aModifier;
+
+ *lpoptions = OLE_CHANGED;
+ while ( *lpbuf && *lpbuf != '/') lpbuf++;
+
+ // no modifier same as /change
+
+ if (*lpbuf == NULL)
+ return NOERROR;
+
+ *lpbuf++ = NULL; // seperate out the item string
+ // We are using this in the caller.
+
+ if (!(aModifier = GlobalFindAtom (lpbuf)))
+ return ReportResult(0, RPC_E_DDE_SYNTAX_ITEM, 0, 0);
+
+ if (aModifier == aChange)
+ return NOERROR;
+
+ // Is it a save?
+ if (aModifier == aSave){
+ *lpoptions = OLE_SAVED;
+ return NOERROR;
+ }
+ // Is it a Close?
+ if (aModifier == aClose){
+ *lpoptions = OLE_CLOSED;
+ return NOERROR;
+ }
+
+ // unknow modifier
+ return ReportResult(0, RPC_E_DDE_SYNTAX_ITEM, 0, 0);
+
+}
+
+
+
+
+//MakeDDEData: Create a Global DDE data handle from the server
+// app data handle.
+
+INTERNAL_(BOOL) MakeDDEData
+(
+HANDLE hdata,
+int format,
+LPHANDLE lph,
+BOOL fResponse
+)
+{
+ DWORD size;
+ HANDLE hdde = NULL;
+ DDEDATA FAR *lpdata= NULL;
+ BOOL bnative;
+ LPSTR lpdst;
+ LPSTR lpsrc;
+
+ Puts ("MakeDDEData\r\n");
+
+ if (!hdata) {
+ *lph = NULL;
+ return TRUE;
+ }
+
+
+ if (bnative = !(format == CF_METAFILEPICT
+ || format == CF_DIB
+ || format == CF_BITMAP))
+ {
+ // g_cfNative, CF_TEXT, g_cfBinary
+ size = GlobalSize (hdata) + sizeof (DDEDATA);
+ }
+ else
+ size = sizeof (LONG) + sizeof (DDEDATA);
+
+
+ hdde = (HANDLE) GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT, size);
+ if (hdde == NULL || (lpdata = (DDEDATA FAR *) GlobalLock (hdde)) == NULL)
+ goto errRtn;
+
+ // set the data otions. Ask the client to delete
+ // it always.
+
+ lpdata->fAckReq = FALSE;
+ lpdata->fRelease = TRUE; // release the data
+ lpdata->cfFormat = format;
+ lpdata->fResponse = fResponse;
+
+ if (!bnative)
+ // If not native, stick in the handle what the server gave us.
+ *(LPHANDLE)lpdata->Value = hdata;
+
+ else {
+ // copy the native data junk here.
+ lpdst = (LPSTR)lpdata->Value;
+ if(!(lpsrc = (LPSTR)GlobalLock (hdata)))
+ goto errRtn;
+
+ size -= sizeof (DDEDATA);
+ memcpy (lpdst, lpsrc, size);
+ GlobalUnlock (hdata);
+ GlobalFree (hdata);
+
+ }
+
+ GlobalUnlock (hdde);
+ *lph = hdde;
+ return TRUE;
+
+errRtn:
+ if (lpdata)
+ GlobalUnlock (hdde);
+
+ if (hdde)
+ GlobalFree (hdde);
+
+ if (bnative)
+ GlobalFree (hdata);
+
+ return FALSE;
+}
+
+
+
+// IsAdviseStdItems: returns true if the item is one of the standard items
+// StdDocName;
+INTERNAL_(BOOL) IsAdviseStdItems (
+ATOM aItem
+)
+{
+
+ if ( aItem == aStdDocName)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+
+
+// GetStdItemIndex: returns index to Stditems in the "stdStrTable" if the item
+// is one of the standard items StdHostNames, StdTargetDevice,
+// StdDocDimensions, StdColorScheme
+WCHAR * stdStrTable[STDHOSTNAMES+1] = {NULL,
+ OLESTR("StdTargetDevice"),
+ OLESTR("StdDocDimensions"),
+ OLESTR("StdColorScheme"),
+ OLESTR("StdHostNames")};
+
+INTERNAL_(int) GetStdItemIndex (
+ATOM aItem
+)
+{
+
+ WCHAR str[MAX_STR];
+
+ if (!aItem)
+ return NULL;
+
+ if (!GlobalGetAtomName (aItem, str, MAX_STR))
+ return NULL;
+
+ if (!lstrcmpiW (str, stdStrTable[STDTARGETDEVICE]))
+ return STDTARGETDEVICE;
+ else if (!lstrcmpiW (str, stdStrTable[STDHOSTNAMES]))
+ return STDHOSTNAMES;
+ else if (!lstrcmpiW (str, stdStrTable[STDDOCDIMENSIONS]))
+ return STDDOCDIMENSIONS;
+ else if (!lstrcmpiW (str, stdStrTable[STDCOLORSCHEME]))
+ return STDCOLORSCHEME;
+
+ return NULL;
+}
+
+
+
+
+void ChangeOwner
+ (HANDLE hmfp)
+{
+
+#ifndef WIN32
+ LPMETAFILEPICT lpmfp;
+ if (lpmfp = (LPMETAFILEPICT) GlobalLock (hmfp))
+ {
+ SetMetaFileBitsBetter (lpmfp->hMF);
+ GlobalUnlock (hmfp);
+ }
+#endif
+}
+
+
+INTERNAL_(HANDLE) MakeItemData
+(
+DDEPOKE FAR * lpPoke,
+HANDLE hPoke,
+CLIPFORMAT cfFormat
+)
+{
+ HANDLE hnew;
+ LPBYTE lpnew;
+ DWORD dwSize;
+
+ Puts ("MakeItemData\r\n");
+
+ if (cfFormat == CF_METAFILEPICT)
+ return DuplicateMetaFile (*(LPHANDLE)lpPoke->Value);
+
+ if (cfFormat == CF_BITMAP)
+ return (HANDLE)DuplicateBitmap (*(HBITMAP *)lpPoke->Value);
+
+ if (cfFormat == CF_DIB)
+ return UtDupGlobal (*(LPHANDLE)lpPoke->Value,GMEM_MOVEABLE);
+
+ // Now we are dealing with normal case
+ if (!(dwSize = GlobalSize (hPoke)))
+ return NULL;
+
+ dwSize -= sizeof (DDEPOKE) - sizeof(BYTE);
+
+ // Use GMEM_ZEROINIT so there is no garbage after the data in field Value.
+ // This may be important when making an IStorage from native data,
+ // but I'm not sure.
+ // Note that the Value field itself could have garbage
+ // at the end if the hData of the DDE_POKE message is bigger than
+ // necessary, i.e.,
+ // GlobalSize(hData) > sizeof(DDEPOKE) - sizeof(Value) + realsize(Value)
+
+ // A DocFile is of size 512n
+ DebugOnly (
+ if (cfFormat==g_cfNative && dwSize%512 != 0)
+ {
+ Putsi(dwSize);
+ Puts ("DDE_POKE.Value not of size 512n\r\n");
+ }
+ )
+
+ if (hnew = GlobalAlloc (GMEM_MOVEABLE|GMEM_ZEROINIT, dwSize)) {
+ if (lpnew = (LPBYTE) GlobalLock (hnew)) {
+ memcpy (lpnew, lpPoke->Value, dwSize);
+ GlobalUnlock (hnew);
+ }
+ else {
+ GlobalFree (hnew);
+ hnew = NULL;
+ }
+ }
+
+ return hnew;
+}
+
+
+
+INTERNAL_(HANDLE) DuplicateMetaFile
+(
+HANDLE hSrcData
+)
+{
+ LPMETAFILEPICT lpSrcMfp;
+ LPMETAFILEPICT lpDstMfp = NULL;
+ HANDLE hMF = NULL;
+ HANDLE hDstMfp = NULL;
+
+ Puts ("DuplicateMetaFile\r\n");
+
+ if (!(lpSrcMfp = (LPMETAFILEPICT) GlobalLock(hSrcData)))
+ return NULL;
+
+ GlobalUnlock (hSrcData);
+
+ if (!(hMF = CopyMetaFile (lpSrcMfp->hMF, NULL)))
+ return NULL;
+
+ if (!(hDstMfp = GlobalAlloc (GMEM_MOVEABLE, sizeof(METAFILEPICT))))
+ goto errMfp;
+
+ if (!(lpDstMfp = (LPMETAFILEPICT) GlobalLock (hDstMfp)))
+ goto errMfp;
+
+ GlobalUnlock (hDstMfp);
+
+ *lpDstMfp = *lpSrcMfp;
+ lpDstMfp->hMF = (HMETAFILE)hMF;
+ return hDstMfp;
+errMfp:
+ //
+ // The following Metafile was created in this
+ // process. Therefore, the delete shouldn't need to
+ // call the DDE functions for deleting the DDE pair
+ //
+ if (hMF)
+ DeleteMetaFile ((HMETAFILE)hMF);
+
+ if (hDstMfp)
+ GlobalFree (hDstMfp);
+
+ return NULL;
+}
+
+
+
+INTERNAL_(HBITMAP) DuplicateBitmap
+(
+HBITMAP hold
+)
+{
+ HBITMAP hnew;
+ HANDLE hMem;
+ LPBYTE lpMem;
+ LONG retVal = TRUE;
+ DWORD dwSize;
+ BITMAP bm;
+
+ // !!! another way to duplicate the bitmap
+
+ Puts ("DuplicateBitmap\r\n");
+
+ GetObject (hold, sizeof(BITMAP), (LPSTR) &bm);
+ dwSize = ((DWORD) bm.bmHeight) * ((DWORD) bm.bmWidthBytes) *
+ ((DWORD) bm.bmPlanes) * ((DWORD) bm.bmBitsPixel);
+
+ if (!(hMem = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize)))
+ return NULL;
+
+ if (!(lpMem = (LPBYTE) GlobalLock (hMem))){
+ GlobalFree (hMem);
+ return NULL;
+ }
+
+ GetBitmapBits (hold, dwSize, lpMem);
+ if (hnew = CreateBitmap (bm.bmWidth, bm.bmHeight,
+ bm.bmPlanes, bm.bmBitsPixel, NULL))
+ retVal = SetBitmapBits (hnew, dwSize, lpMem);
+
+ GlobalUnlock (hMem);
+ GlobalFree (hMem);
+
+ if (hnew && (!retVal)) {
+ DeleteObject (hnew);
+ hnew = NULL;
+ }
+
+ return hnew;
+}
+
+
+
+
+// CDefClient::GetData
+//
+// Perform a normal GetData on m_lpdataObj, but if g_cfNative is requested,
+// do an OleSave onto our IStorage implemented
+// on top of an ILockBytes, then convert the ILockBytes to an hGlobal.
+// This flattened IStorage will be used as the native data.
+//
+INTERNAL CDefClient::GetData
+ (LPFORMATETC pformatetc,
+ LPSTGMEDIUM pmedium)
+{
+ LPPERSISTSTORAGE pPersistStg=NULL;
+ HANDLE hNative =NULL;
+ HANDLE hNativeDup =NULL;
+ HRESULT hresult =NOERROR;
+ BOOL fFreeHNative = FALSE;
+ CLSID clsid;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDefClient::GetData(%x,%x)\n",
+ this,
+ pformatetc,
+ pmedium));
+
+ intrDebugOut((DEB_ITRACE,
+ " ::GetData format=%x\n",
+ pformatetc->cfFormat));
+
+ if (pformatetc->cfFormat==g_cfNative)
+ {
+ ErrRtnH (m_lpdataObj->QueryInterface (IID_IPersistStorage,
+ (LPLPVOID) &pPersistStg));
+ ErrZ (pPersistStg);
+ if (NULL==m_pstgNative)
+ {
+ // Embed from file case
+ Assert (NULL==m_plkbytNative);
+ ErrRtnH (CreateILockBytesOnHGlobal (NULL,
+ /*fDeleteOnRelease*/TRUE,
+ &m_plkbytNative));
+
+ Assert (m_plkbytNative);
+
+ ErrRtnH (StgCreateDocfileOnILockBytes (m_plkbytNative,
+ grfCreateStg, 0, &m_pstgNative));
+
+ ErrZ (m_pstgNative);
+ Assert (NOERROR==StgIsStorageILockBytes(m_plkbytNative));
+
+ m_fInOleSave = TRUE;
+ hresult = OleSave (pPersistStg, m_pstgNative, FALSE);
+ pPersistStg->SaveCompleted(NULL);
+ m_fInOleSave = FALSE;
+ ErrRtnH (hresult);
+ }
+ else
+ {
+ // Get the native data by calling OleSave
+ m_fInOleSave = TRUE;
+ hresult = OleSave (pPersistStg, m_pstgNative, TRUE);
+ pPersistStg->SaveCompleted(NULL);
+ m_fInOleSave = FALSE;
+ ErrRtnH (hresult);
+ }
+ ErrRtnH (ReadClassStg (m_pstgNative, &clsid));
+ if (CoIsOle1Class (clsid))
+ {
+ // TreatAs case:
+ // Get Native data from "\1Ole10Native" stream
+ fFreeHNative = TRUE;
+ ErrRtnH (StRead10NativeData (m_pstgNative, &hNative));
+ }
+ else
+ {
+
+ Assert (NOERROR==StgIsStorageILockBytes (m_plkbytNative));
+
+ ErrRtnH (GetHGlobalFromILockBytes (m_plkbytNative, &hNative));
+ }
+
+ ErrZ (wIsValidHandle (hNative, g_cfNative));
+
+ // Must duplicate because we let the client free the handle,
+ // so it can't be the one our ILockBytes depends on.
+ hNativeDup = UtDupGlobal (hNative, GMEM_DDESHARE | GMEM_MOVEABLE);
+ ErrZ (wIsValidHandle (hNativeDup, g_cfNative));
+
+ if (GlobalSize(hNativeDup) % 512 != 0)
+ {
+ Puts ("WARNING:\r\n\t");
+ Putsi (GlobalSize(hNativeDup));
+ }
+
+ pmedium->tymed = TYMED_HGLOBAL;
+ pmedium->hGlobal = hNativeDup;
+ pmedium->pUnkForRelease = NULL;
+
+ pPersistStg->Release();
+ hresult = NOERROR;
+ goto exitRtn;
+ }
+ else
+ {
+ // Anything but native
+ hresult = m_lpdataObj->GetData (pformatetc, pmedium);
+// AssertOutStgmedium(hresult, pmedium);
+ goto exitRtn;
+ }
+
+
+errRtn:
+ if (hNative && fFreeHNative)
+ GlobalFree (hNative);
+ if (pPersistStg)
+ pPersistStg->Release();
+
+ pmedium->tymed = TYMED_NULL;
+ pmedium->pUnkForRelease = NULL;
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x OUT CDefClient::GetData() return %x\n",
+ this,
+ hresult));
+ return hresult;
+}
+
+
+// Set pformatetc->tymed based on pformatetc->cfFormat
+//
+INTERNAL wSetTymed
+ (LPFORMATETC pformatetc)
+{
+ if (pformatetc->cfFormat == CF_METAFILEPICT)
+ {
+ pformatetc->tymed = TYMED_MFPICT;
+ }
+ else if (pformatetc->cfFormat == CF_PALETTE ||
+ pformatetc->cfFormat == CF_BITMAP)
+ {
+ pformatetc->tymed = TYMED_GDI;
+ }
+ else
+ {
+ pformatetc->tymed = TYMED_HGLOBAL;
+ }
+ return NOERROR;
+}
diff --git a/private/ole32/com/remote/dde/server/itemutil.h b/private/ole32/com/remote/dde/server/itemutil.h
new file mode 100644
index 000000000..e9af61df2
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/itemutil.h
@@ -0,0 +1,14 @@
+// itemutil.h
+//
+// Corresponds to itemutil.cpp
+
+void ChangeOwner (HANDLE hmfp);
+INTERNAL ScanItemOptions (LPSTR lpbuf, int far *lpoptions);
+INTERNAL_(BOOL) MakeDDEData (HANDLE hdata, int format, LPHANDLE lph, BOOL fResponse);
+INTERNAL_(BOOL) IsAdviseStdItems (ATOM aItem);
+INTERNAL_(int) GetStdItemIndex (ATOM aItem);
+void ChangeOwner (HANDLE hmfp);
+INTERNAL_(HANDLE) MakeItemData (DDEPOKE FAR *lpPoke, HANDLE hPoke, CLIPFORMAT cfFormat);
+INTERNAL_(HANDLE) DuplicateMetaFile (HANDLE hSrcData);
+INTERNAL_(HBITMAP) DuplicateBitmap (HBITMAP hold);
+INTERNAL wSetTymed (LPFORMATETC pformatetc);
diff --git a/private/ole32/com/remote/dde/server/srvr.cxx b/private/ole32/com/remote/dde/server/srvr.cxx
new file mode 100644
index 000000000..7027bf8df
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/srvr.cxx
@@ -0,0 +1,2369 @@
+
+/****************************** Module Header ******************************\
+* Module Name: Srvr.c Server Main module
+*
+* Purpose: Includes All the server communication related routines.
+*
+* Created: Oct 1990.
+*
+* Copyright (c) 1985, 1986, 1987, 1988, 1989 Microsoft Corporation
+*
+* History:
+* Raor: Wrote the original version.
+*
+*
+\***************************************************************************/
+
+#include "ole2int.h"
+//#include <shellapi.h>
+// #include "cmacs.h"
+#include <dde.h>
+
+// for RemDdeRevokeClassFactory and HDDESRVR
+#include <olerem.h>
+
+#include "srvr.h"
+#include "ddedebug.h"
+#include "ddesrvr.h"
+ASSERTDATA
+
+extern HINSTANCE hdllInst;
+
+#define WM_DONOTDESTROY WM_USER+1
+
+#ifdef FIREWALLS
+BOOL bShowed = FALSE;
+void ShowVersion (void);
+#endif
+
+#ifdef _CHICAGO_
+#define DdeCHAR CHAR
+#define Ddelstrcmp lstrcmpA
+#define DdeGetClassName GetClassNameA
+#define szCDDEServer "CDDEServer"
+#else
+#define DdeCHAR WCHAR
+#define Ddelstrcmp lstrcmpW
+#define DdeGetClassName GetClassName
+#define szCDDEServer OLESTR("CDDEServer")
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDDEServer::Create
+//
+// Synopsis: Create a server window to service a particular class
+//
+// Effects: Using lpclass, and the information in lpDdeInfo, create
+// a server window that is ready to respond to initiate
+// messages from this class.
+//
+// Arguments: [lpclass] -- Class name
+// [rclsid] -- Class ID
+// [lpDdeInfo] -- Class Object information
+// [phwnd] -- Out pointer for new window
+// [aOriginalClass] -- For TreatAs/Convert to case
+// [cnvtyp] -- Conversion type
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-28-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CDDEServer::Create
+ (LPOLESTR lpclass,
+ REFCLSID rclsid,
+ LPDDECLASSINFO lpDdeInfo,
+ HWND FAR * phwnd,
+ ATOM aOriginalClass,
+ CNVTYP cnvtyp)
+{
+ // REVIEW what happens if we have two MDI servers register the
+ // same class factory?.
+
+ LPSRVR lpDDEsrvr = NULL;
+ ATOM aExe = NULL;
+
+ intrDebugOut((DEB_DDE_INIT,
+ "0 _IN CDDEServer::Create(lpclass=%ws)\n",
+ lpclass));
+
+ // add the app atom to global list
+ if (!ValidateSrvrClass (lpclass, &aExe))
+ {
+ intrDebugOut((DEB_IWARN,
+ "CDDEServer::Create(%ws) Invalid Class\n",
+ lpclass));
+
+ return OLE_E_CLSID;
+ }
+
+ lpDDEsrvr = new CDDEServer;
+ RetZS (lpDDEsrvr, E_OUTOFMEMORY);
+
+
+ lpDDEsrvr->m_pCallControl = GetDdeCallControlInterface();
+
+ intrAssert(lpDDEsrvr->m_pCallControl != NULL);
+
+ if (lpDDEsrvr->m_pCallControl == NULL)
+ {
+ intrDebugOut((DEB_IWARN,
+ "CDDEServer::Create(%ws) CallControlGet failed\n",
+ lpclass));
+
+ goto errReturn;
+ }
+
+ // set the signature handle and the app atom.
+ lpDDEsrvr->m_chk = chkDdeSrvr;
+ lpDDEsrvr->m_aClass = wGlobalAddAtom (lpclass);
+ lpDDEsrvr->m_clsid = rclsid; // Class ID (already TreatAs'd)
+ lpDDEsrvr->m_aOriginalClass = wDupAtom (aOriginalClass);
+ lpDDEsrvr->m_pClassFactory = NULL;
+ lpDDEsrvr->m_dwClassFactoryKey = lpDdeInfo->dwRegistrationKey;
+ lpDDEsrvr->m_aExe = aExe;
+ lpDDEsrvr->m_cnvtyp = cnvtyp;
+ lpDDEsrvr->m_fcfFlags = lpDdeInfo->dwFlags;
+
+ lpDDEsrvr->m_bTerminate = FALSE; // Set if we are terminating.
+ lpDDEsrvr->m_hcli = NULL; // handle to the first block of clients list
+ lpDDEsrvr->m_termNo = 0; // termination count
+ lpDDEsrvr->m_cSrvrClients= 0; // no of clients;
+ lpDDEsrvr->m_fDoNotDestroyWindow= 0;
+
+
+
+
+
+#ifdef FIREWALLS
+ AssertSz(lpDdeInfo.dwFlags <= REGCLS_MULTI_SEPARATE, "invalid server options");
+#endif
+
+ // Create the server window and do not show it.
+ //
+ // We are explicitly calling CreateWindowA here.
+ // The DDE tracking layer will attempt to convert hCommands to UNICODE
+ // if the two windows in the conversation are both UNICODE.
+ // This window is created as a child of the common server window for this
+ // thread. When this thread dies, the common server window is destroyed if
+ // it exists, which will cause all of the child windows to be destroyed also.
+ //
+ //
+ if (!(lpDDEsrvr->m_hwnd = DdeCreateWindowEx (0, SRVR_CLASS,
+ szCDDEServer,
+ WS_OVERLAPPED | WS_CHILD,
+ 0,0,0,0,
+ (HWND)TLSGetDdeServer(),
+ NULL,
+ hdllInst, NULL)))
+ {
+ goto errReturn;
+
+ }
+
+ //
+ // The following will inform the class object in the class registration table
+ // that this window should be notified when the class object is revoked. This
+ // enables the window to shutdown properly.
+ //
+ // If there isn't a class factory, which happens for single instance servers
+ // which were launched with a filename, then m_dwClassFactory will be 0,
+ // in which case we don't make the set call.
+ //
+ if(lpDDEsrvr->m_dwClassFactoryKey != 0)
+ {
+ if(!SetDdeServerWindow(lpDDEsrvr->m_dwClassFactoryKey,lpDDEsrvr->m_hwnd))
+ {
+ intrDebugOut((DEB_IERROR,
+ "0 CDDEServer::Create unable to SetDdeServerWindow\n"));
+ goto errReturn;
+ }
+ }
+
+ intrDebugOut((DEB_DDE_INIT,
+ "DDE Server window for %ws created in task %x\n",
+ lpclass,GetCurrentThreadId()));
+
+ // save the ptr to the server struct in the window.
+ SetWindowLong (lpDDEsrvr->m_hwnd, 0, (LONG)lpDDEsrvr);
+
+ // Set the signature.
+ SetWindowWord (lpDDEsrvr->m_hwnd, WW_LE, WC_LE);
+
+ *phwnd = lpDDEsrvr->m_hwnd;
+
+
+ intrDebugOut((DEB_DDE_INIT,
+ "0 _OUT CDDEServer::Create returns %x\n",
+ NOERROR));
+ return NOERROR;
+
+errReturn:
+ AssertSz (0, "CDDEServer::Create errReturn");
+ if (lpDDEsrvr)
+ {
+ if (lpDDEsrvr->m_pCallControl)
+ ReleaseDdeCallControlInterface();
+
+ if (lpDDEsrvr->m_hwnd)
+ SSDestroyWindow (lpDDEsrvr->m_hwnd);
+
+ if (lpDDEsrvr->m_aClass)
+ GlobalDeleteAtom (lpDDEsrvr->m_aClass);
+
+ if (lpDDEsrvr->m_aExe)
+ GlobalDeleteAtom (lpDDEsrvr->m_aExe);
+ delete lpDDEsrvr;
+ }
+
+ intrDebugOut((DEB_IERROR,
+ "0 _OUT CDDEServer::Create returns %x\n",
+ E_OUTOFMEMORY));
+
+ return E_OUTOFMEMORY;
+}
+
+
+
+// ValidateSrvrClass checks whether the given server class is valid by
+// looking in the registration database.
+
+INTERNAL_(BOOL) ValidateSrvrClass (
+LPOLESTR lpclass,
+ATOM FAR * lpAtom
+)
+{
+ WCHAR buf[MAX_STR];
+ LONG cb = MAX_STR;
+ WCHAR key[MAX_STR];
+ LPOLESTR lptmp;
+ LPOLESTR lpbuf;
+ WCHAR ch;
+ CLSID clsid;
+
+ if (CLSIDFromProgID (lpclass, &clsid) != NOERROR)
+ {
+ // ProgId is not correctly registered in reg db
+ return FALSE;
+ }
+
+ lstrcpyW (key, lpclass);
+ lstrcatW (key, OLESTR("\\protocol\\StdFileEditing\\server"));
+
+ if (RegQueryValue (HKEY_CLASSES_ROOT, key, buf, &cb))
+ return TRUE;
+
+ if (!buf[0])
+ {
+ AssertSz (0, "ValidateSrvrClass failed.");
+ return FALSE;
+ }
+
+ // Get exe name without path and then get an atom for that
+ lptmp = lpbuf = buf;
+ while (ch = *lptmp)
+ {
+ lptmp++;
+ if (ch == '\\' || ch == ':')
+ lpbuf = lptmp;
+ }
+ *lpAtom = wGlobalAddAtom (lpbuf);
+
+ return TRUE;
+}
+
+
+
+INTERNAL RemDdeRevokeClassFactory
+ (LPSRVR lpsrvr)
+{
+ HRESULT hr;
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN RemDdeRevokeClassFactory(%x)\n",
+ lpsrvr));
+
+ ChkS(lpsrvr);
+ hr = lpsrvr->Revoke();
+ intrDebugOut((DEB_ITRACE,
+ "0 OUT RemDdeRevokeClassFactory(%x) %x\n",
+ lpsrvr,hr));
+ return(hr);
+}
+
+
+
+INTERNAL CDDEServer::Revoke ()
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDDEServer::Revoke() m_cSrvrClients=%x\n",
+ this,
+ m_cSrvrClients));
+ HRESULT hr;
+
+ ChkS(this);
+
+ //
+ // Can't revoke if there are still clients. QueryRevokeCLassFactory
+ // determines if there are still clients attached.
+ //
+ if (!QueryRevokeClassFactory ())
+ {
+ intrDebugOut((DEB_IERROR,
+ "QueryRevokeClassFactory failed!"));
+ hr = RPC_E_DDE_REVOKE;
+ goto exitRtn;
+ }
+
+ if (m_cSrvrClients)
+ {
+ m_bTerminate = TRUE;
+ // if there are any clients connected to this classfactory,
+ // send terminates.
+ SendServerTerminateMsg ();
+ m_bTerminate = FALSE;
+ }
+
+ hr = FreeSrvrMem ();
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x OUT CDDEServer::Revoke(%x) hr = %x\n",
+ this, hr));
+ return hr;
+}
+
+INTERNAL_(void) CDDEServer::SendServerTerminateMsg ()
+{
+
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+ HANDLE hcli;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDDEServer::SendServerTerminateMsg\n",
+ this));
+
+ hcli = m_hcli;
+ while (hcli) {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ {
+ Assert(0);
+ goto exitRtn;
+ }
+
+ phandle = (HANDLE *) (pcli->info);
+ while (phandle < (HANDLE *)(pcli + 1)) {
+ if (*phandle)
+ {
+ PostMessageToClientWithReply ((HWND)(*phandle), WM_DDE_TERMINATE,
+ (WPARAM) m_hwnd, NULL, WM_DDE_TERMINATE);
+ Assert (m_cSrvrClients);
+ m_cSrvrClients--;
+ }
+ phandle++;
+ phandle++;
+ }
+
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+ }
+
+exitRtn:
+ intrDebugOut((DEB_ITRACE,
+ "%x OUT CDDEServer::SendServerTerminateMsg\n",
+ this));
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDDEServer::FreeSrvrMem
+//
+// Synopsis: Free's up a CDDEServer.
+//
+// Effects:
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 6-26-94 kevinro Commented
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CDDEServer::FreeSrvrMem
+ (void)
+{
+ HRESULT hr;
+ // REVIEW: Not clear how this works in the synchronous mode
+ // Release for class factory is called only when everything is
+ // cleaned and srvr app can post WM_QUIT at this stage
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDDEServer::FreeSrvrMem\n",
+ this));
+
+ PCLILIST pcliPrev;
+ HANDLE hcli, hcliPrev;
+
+ if (m_bTerminate)
+ {
+ AssertSz (0, "terminate flag is not FALSE");
+ }
+
+
+ if (m_aExe)
+ {
+ GlobalDeleteAtom (m_aExe);
+ }
+
+
+ // We deliberately do not call this->Lock (FALSE)
+ // If the server has revoked his class object without
+ // waiting for his Lock count to go to zero, then
+ // presumably he doesn't need us to unlock him. In fact,
+ // doing such an unlock might confuse a server who then
+ // tries to call CoRevokeClassObject recursively.
+ if (m_pClassFactory)
+ {
+ m_pClassFactory->Release();
+ m_pClassFactory = NULL;
+ }
+
+ hcli = m_hcli;
+ while (hcli)
+ {
+ hcliPrev = hcli;
+ if (pcliPrev = (PCLILIST) LocalLock (hcliPrev))
+ {
+ hcli = pcliPrev->hcliNext;
+ }
+ else
+ {
+ AssertSz (0, "Corrupt internal data structure or out-of-memory");
+ hcli = NULL;
+ }
+ Verify (0==LocalUnlock (hcliPrev));
+ Verify (NULL==LocalFree (hcliPrev));
+ }
+
+ hr = DestroyDdeSrvrWindow(m_hwnd,m_aClass);
+ if (hr != NOERROR)
+ {
+ //
+ // Well now, if DestroyWindow fails, there isn't a whole heck of
+ // alot we can do about it. It could mean that the window was
+ // destroyed previously, or the parent window was destroyed during
+ // thread shutdown. We should still continue to cleanup
+ //
+ intrDebugOut((DEB_IERROR,
+ "%x CDDEServer::FreeSrvrMem DestroyDdeSrvrWindow failed %x\n",
+ this,
+ hr));
+ }
+
+ if (m_aClass)
+ {
+ GlobalDeleteAtom (m_aClass);
+ }
+
+ if (m_pCallControl)
+ {
+ ReleaseDdeCallControlInterface();
+ }
+
+ delete this;
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDDEServer::FreeSrvrMem\n",
+ this));
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SrvrHandleIncomingCall
+//
+// Synopsis: Setup and call the CallControl to dispatch a call to the server
+//
+// Effects: A call has been made from the client that requires us to call
+// into our server. This must be routed through the call control.
+// This routine sets up the appropriate data structures, and
+// calls into the CallControl. The CallControl will in turn
+// call SrvrDispatchIncomingCall to actuall process the call.
+//
+// This routine should only be called by the SrvrWndProc
+//
+//
+// Arguments: [lpsrvr] -- Points to the server
+// [hwnd] -- hwnd of server
+// [hdata] -- Handle to data
+// [wParam] -- hwnd of client
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-05-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL SrvrHandleIncomingCall(LPSRVR lpsrvr,
+ HWND hwnd,
+ HANDLE hdata,
+ HWND wParam)
+{
+ VDATEHEAP();
+ HRESULT hresult = NOERROR;
+ IID iid;
+ SRVRDISPATCHDATA srvrdispdata;
+ DISPATCHDATA dispatchdata;
+ INTERFACEINFO32 ifInfo;
+ ICallControl *lpCallCont = lpsrvr->m_pCallControl;
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN SrvrHandleIncomingCall lpsrvr=%x hwnd=%x hdata=%x wParam=%x\n",
+ lpsrvr,
+ hwnd,
+ hdata,
+ wParam));
+
+ //
+ // It would be very bad if this didn't exist.
+ //
+ intrAssert(lpCallCont);
+
+ //
+ // There is no information to provide here
+ // By setting pUnk to NULL, the CallControl will pass the
+ // message filter a NULL ifInfo.
+ //
+
+ ifInfo.pUnk = NULL;
+ ifInfo.wMethod=0;
+ ifInfo.callcat = CALLCAT_SYNCHRONOUS;
+
+ dispatchdata.pData = (LPVOID) &srvrdispdata;
+
+ srvrdispdata.wDispFunc = DDE_DISP_SRVRWNDPROC;
+ srvrdispdata.hwnd = hwnd;
+ srvrdispdata.hData = hdata;
+ srvrdispdata.wParam = wParam;
+ srvrdispdata.lpsrvr = lpsrvr;
+
+ hresult = lpCallCont->HandleDispatchCall((DWORD)GetWindowTask(hwnd),
+ iid,
+ &ifInfo,
+ &dispatchdata);
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _OUT SrvrHandleIncomingCall hresult=%x\n",
+ hresult));
+
+ return(hresult);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SrvrDispatchIncomingCall
+//
+// Synopsis: Dispatch a call into the server.
+//
+// Effects: At the moment, the only incoming call that requires handling
+// by the server window is Execute. This routine dispatchs to it,
+// and returns.
+//
+// Arguments: [psdd] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-05-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL SrvrDispatchIncomingCall(PSRVRDISPATCHDATA psdd)
+{
+ VDATEHEAP();
+ HRESULT hr;
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN SrvrDispatchIncomingCall psdd(%x)\n",psdd));
+
+ hr = psdd->lpsrvr->SrvrExecute (psdd->hwnd,
+ psdd->hData,
+ (HWND)(psdd->wParam));
+
+ intrDebugOut((DEB_ITRACE,
+ "0 _OUT SrvrDispatchIncomingCall psdd(%x) hr =%x\n",
+ psdd,
+ hr));
+
+ return(hr);
+}
+
+
+// REVIEW: Revoking Class Factory will not be successful if
+// any clients are either connected to the classfactory
+// or to the object instances.
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SrvrWndProc
+//
+// Synopsis: This is the server window procedure.
+//
+// Effects:
+//
+// Arguments: [hwndIn] -- Window handle (may not be full. See note)
+// [msg] --
+// [wParam] --
+// [lParam] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 8-03-94 kevinro Created
+//
+// Notes:
+//
+// When running in a VDM, it is possible that this window was dispatched
+// without having a full window handle. This happens when the getmessage
+// was dispatched from 16-bit. Therefore, we need to convert the hwnd to
+// a full hwnd before doing any comparision functions.
+//
+//----------------------------------------------------------------------------
+STDAPI_(LRESULT) SrvrWndProc (
+HWND hwndIn,
+UINT msg,
+WPARAM wParam,
+LPARAM lParam
+)
+{
+ BOOL fRevoke=FALSE;
+ LPSRVR lpsrvr;
+ WORD status = NULL;
+ HANDLE hdata;
+ ATOM aItem;
+ HRESULT retval;
+
+ //
+ // The following hwnd variable is used to determine the full HWND, in the
+ // event we were dispatched in a 16 bit process.
+ //
+ HWND hwnd;
+
+#ifdef FIREWALLS
+ HWND hwndClient;
+#endif
+
+
+ switch (msg){
+
+ case WM_DDE_INITIATE:
+ VDATEHEAP();
+#ifdef FIREWALLS
+ AssertSz (lpsrvr, "No server window handle in server window");
+#endif
+ hwnd = ConvertToFullHWND(hwndIn);
+
+ lpsrvr = (LPSRVR)GetWindowLong (hwnd, 0);
+ if (lpsrvr->m_bTerminate){
+ // we are terminating, no more connections
+ break;
+ }
+
+ // class is not matching, so it is not definitely for us.
+ // for apps sending the EXE for initiate, do not allow if the app
+ // is mutiple instance (Bug fix for winworks).
+
+ if (!(lpsrvr->m_aClass == (ATOM)(LOWORD(lParam)) ||
+ (NOERROR==wCompatibleClasses (LOWORD(lParam), lpsrvr->m_aClass)) ||
+ (lpsrvr->m_aExe == (ATOM)(LOWORD(lParam)) && IsSingleServerInstance() )))
+ {
+ break;
+ }
+
+ intrDebugOut((DEB_DDE_INIT,"::SrvrWndProc INITIATE\n"));
+
+
+ if (!lpsrvr->HandleInitMsg (lParam))
+ {
+ if (!(aSysTopic == (ATOM)(HIWORD(lParam))))
+ {
+ //
+ // If this isn't a sys topic, then it must be a request for
+ // a specific document. Send a message to the
+ // children windows, asking for the document. If one of them
+ // may send an ACK to the client.
+ //
+
+ // if the server window is not the right window for
+ // DDE conversation, then try with the doc windows.
+ BOOL fAckSent = SendInitMsgToChildren (hwnd, msg, wParam, lParam);
+
+#ifdef KEVINRO_OLDCODE
+ The following code was removed, because I don't belive it is required
+ any longer. I am not 100% sure yet, so I have left it in. If you find it,
+ you can probably remove it.
+ It appears to be trying to claim the SINGLE_USE class factory from the class
+ factory table. It does this when a child document window sends an ACK to the
+ client, claiming to support the document being asked for. It really doesn't
+ make too much sense here, since a single use server would have already removed
+ its class factory if there was an open document.
+
+ Anyway, the 16-bit version had a direct hack into the class factory table. We
+ don't have that anymore, so this code wouldn't work anyway.
+
+ if (lpsrvr->m_fcfFlags==REGCLS_SINGLEUSE)
+ {
+ if (lpsrvr->m_pfAvail)
+ {
+ // Hide the entry in the class factory table so that no 2.0
+ // client can connect to the same server.
+ Assert (!IsBadWritePtr (lpsrvr->m_pfAvail, sizeof(BOOL)));
+ *(lpsrvr->m_pfAvail) = FALSE;
+ }
+ }
+#endif // KEVINRO_OLDCODE
+ intrDebugOut((DEB_DDE_INIT,"SrvrWndProc Child Init\n"));
+ return fAckSent;
+ }
+ break;
+ }
+
+ // We can enterain this client. Put him in our client list
+ // and acknowledge the initiate.
+
+ if (!AddClient ((LPHANDLE)&lpsrvr->m_hcli, (HWND)wParam,(HWND)/*fLocked*/FALSE))
+ {
+ break;
+ }
+
+ //
+ // Now its time to grab up the class factory from the class
+ // factory table. When this window was created, the class factory
+ // was available. However, it is possible that it has already
+ // been claimed by someone else. So, we try grabbing it (which
+ // normally should succeed). If it fails, then delete the client
+ // and don't acknowledge.
+ //
+
+ if (lpsrvr->m_pClassFactory == NULL)
+ {
+ DdeClassInfo ddeInfo;
+ ddeInfo.dwContextMask = CLSCTX_LOCAL_SERVER |
+ CLSCTX_INPROC_SERVER;
+ intrDebugOut((DEB_DDE_INIT,"SrvrWndProc getting class factory\n"));
+ //
+ // The following asks for control of the class
+ // factory in the case of a single use class
+ //
+ ddeInfo.fClaimFactory = TRUE;
+ ddeInfo.dwRegistrationKey = lpsrvr->m_dwClassFactoryKey;
+
+ if (GetClassInformationFromKey(&ddeInfo) == FALSE)
+ {
+ intrDebugOut((DEB_IERROR,"SrvrWndProc failed to get class factory\n"));
+ //
+ // Whoops, we were not able to grab the class factory
+ // Cleanup and hop out
+ if (!FindClient ((LPHANDLE)lpsrvr->m_hcli,(HWND)wParam, TRUE))
+ {
+ intrAssert(!"FindClient failed\n");
+ }
+ return(0);
+ }
+ lpsrvr->m_pClassFactory = (IClassFactory *)ddeInfo.punk;
+ lpsrvr->m_fcfFlags = ddeInfo.dwFlags;
+ }
+
+ intrAssert(lpsrvr->m_pClassFactory != NULL);
+
+ lpsrvr->m_cSrvrClients++;
+
+ lpsrvr->Lock (TRUE, (HWND)wParam);
+
+ // Post acknowledge
+ DuplicateAtom (LOWORD(lParam));
+ DuplicateAtom (HIWORD(lParam));
+ SSSendMessage ((HWND)wParam, WM_DDE_ACK, (WPARAM)hwnd, lParam);
+
+
+ return 1L; // fAckSent==TRUE
+ VDATEHEAP();
+ break;
+
+
+ case WM_DDE_EXECUTE:
+ VDATEHEAP();
+ hwnd = ConvertToFullHWND(hwndIn);
+
+ lpsrvr = (LPSRVR)GetWindowLong (hwnd, 0);
+
+ hdata = GET_WM_DDE_EXECUTE_HDATA(wParam,lParam);
+
+#ifdef FIREWALLS
+ AssertSz (lpsrvr, "No server handle in server window");
+#endif
+
+ intrDebugOut((DEB_ITRACE,"SrvrWndProc WM_DDE_EXECUTE\n"));
+
+#ifdef FIREWALLS
+ // find the client in the client list.
+ hwndClient = FindClient (lpsrvr->m_hcli, (HWND)wParam, FALSE);
+ AssertSz (hwndClient, "Client is missing from the server")
+#endif
+ // Are we terminating
+ if (lpsrvr->m_bTerminate) {
+ intrDebugOut((DEB_ITRACE,
+ "SrvrWndProc WM_DDE_EXECUTE ignored for TERMINATE\n"));
+ // !!! are we supposed to free the data
+ GlobalFree (hdata);
+ break;
+ }
+
+ retval = SrvrHandleIncomingCall(lpsrvr,hwnd,hdata,(HWND)wParam);
+
+ if (NOERROR!=retval)
+ {
+ intrDebugOut((DEB_IERROR,
+ "SrvrWndProc SrvrHandleIncomingCall fail %x\n",
+ retval));
+ }
+ SET_MSG_STATUS (retval, status)
+
+ if (!lpsrvr->m_bTerminate)
+ {
+ // REVIEW: We are making an assumption that, we will not be posting
+ // any DDE messages because of calling the SrvrExecute.
+ // If we post any messages, before we post the acknowledge
+ // we will be in trouble.
+
+ lParam = MAKE_DDE_LPARAM(WM_DDE_ACK,status,(UINT) hdata);
+
+ intrDebugOut((DEB_ITRACE,
+ "SrvrWndProc WM_DDE_EXECUTE sending %x for ack\n",status));
+
+ // Post the acknowledge to the client
+ if (!PostMessageToClient ((HWND) wParam,
+ WM_DDE_ACK, (UINT) hwnd, lParam)) {
+ // if the window died or post failed, delete the atom.
+ GlobalFree (hdata);
+ DDEFREE(WM_DDE_ACK,lParam);
+ }
+ }
+ VDATEHEAP();
+ break;
+
+
+
+ case WM_DDE_TERMINATE:
+ intrDebugOut((DEB_ITRACE,
+ "SrvrWndProc WM_DDE_TERMINATE\n"));
+
+ hwnd = ConvertToFullHWND(hwndIn);
+
+ lpsrvr = (LPSRVR)GetWindowLong (hwnd, 0);
+
+#ifdef FIREWALLS
+ // find the client in the client list.
+ hwndClient = FindClient (lpsrvr->m_hcli, (HWND)wParam, FALSE);
+ AssertSz (hwndClient, "Client is missing from the server")
+#endif
+ Putsi (lpsrvr->m_bTerminate);
+ if (lpsrvr->m_bTerminate)
+ {
+ AssertSz (0, "Unexpected code path");
+ }
+ else
+ {
+ // If client initiated the terminate. post matching terminate
+ PostMessageToClient ((HWND)wParam,
+ WM_DDE_TERMINATE,
+ (UINT) hwnd,
+ NULL);
+ --lpsrvr->m_cSrvrClients;
+ if (0==lpsrvr->m_cSrvrClients
+ && lpsrvr->QueryRevokeClassFactory())
+ {
+#ifdef KEVINRO_OLD_CODE
+ if (lpsrvr->m_phwndDde)
+ {
+ // Remove from class factory table
+ *(lpsrvr->m_phwndDde) = (HWND)0;
+ }
+#endif // KEVINRO_OLD_CODE
+ fRevoke = TRUE;
+ }
+
+ lpsrvr->Lock (FALSE, (HWND)wParam); // Unlock server
+ FindClient (lpsrvr->m_hcli, (HWND)wParam, /*fDelete*/TRUE);
+
+ if (fRevoke)
+ {
+ lpsrvr->Revoke();
+ }
+ }
+ break;
+
+
+ case WM_DDE_REQUEST:
+ aItem = GET_WM_DDE_REQUEST_ITEM(wParam,lParam);
+
+ hwnd = ConvertToFullHWND(hwndIn);
+
+ lpsrvr = (LPSRVR)GetWindowLong (hwnd, 0);
+
+ intrDebugOut((DEB_ITRACE,
+ "SrvrWndProc WM_DDE_REQUEST(aItem=%x)\n",aItem));
+
+ if (lpsrvr->m_bTerminate || !IsWindowValid ((HWND) wParam))
+ {
+ goto RequestErr;
+ }
+
+ if(RequestDataStd (aItem, (HANDLE FAR *)&hdata) != NOERROR)
+ {
+
+ lParam = MAKE_DDE_LPARAM(WM_DDE_ACK,0x8000,aItem);
+
+ // if request failed, then acknowledge with error.
+ if (!PostMessageToClient ((HWND)wParam, WM_DDE_ACK,
+ (UINT) hwnd, lParam))
+ {
+ DDEFREE(WM_DDE_ACK,lParam);
+RequestErr:
+ if (aItem)
+ {
+ GlobalDeleteAtom (aItem);
+ }
+
+ }
+ }
+ else
+ {
+ lParam = MAKE_DDE_LPARAM(WM_DDE_REQUEST,
+ (UINT) hdata,(UINT) aItem);
+
+ // post the data message and we are not asking for any
+ // acknowledge.
+
+ if (!PostMessageToClient ((HWND)wParam, WM_DDE_DATA,
+ (UINT) hwnd, lParam))
+ {
+ GlobalFree (hdata);
+ DDEFREE(WM_DDE_REQUEST,lParam);
+ goto RequestErr;
+ }
+ }
+ break;
+
+ case WM_DONOTDESTROY:
+ intrDebugOut((DEB_ITRACE,
+ "SrvrWndProc WM_DONOTDESTROY %x\n",
+ wParam));
+
+ //
+ // This message is only sent by 32-bit code that has been
+ // given our full handle
+ //
+
+ lpsrvr = (LPSRVR)GetWindowLong (hwndIn, 0);
+
+ //
+ // The WM_DONOTDESTROY message tells the server how to
+ // handle the following WM_USER message. If wParam is set,
+ // then the m_fDoNotDestroyWindow flag will be set, which
+ // keeps us from destroying the server window. If cleared,
+ // it will enable the destruction. This message is sent
+ // from the MaybeCreateDocWindow routine
+ //
+
+ lpsrvr->m_fDoNotDestroyWindow = wParam;
+ return 0;
+ break;
+
+ case WM_USER:
+ intrDebugOut((DEB_ITRACE,
+ "SrvrWndProc WM_USER\n"));
+ //
+ // This message is only sent by 32-bit code that has been
+ // given our full handle
+ //
+
+ lpsrvr = (LPSRVR)GetWindowLong (hwndIn, 0);
+
+ // cftable.cpp sends a WM_USER message to destory the DDE
+ // server window when a 2.0 client has connected to a
+ // SDI 2.0 server (and no 1.0 client should be allowed to also
+ // connect.
+ // cftable.cpp cannot call RemDdeRevokeClassFactory directly
+ // becuase they may be in different processes.
+ //
+ // The m_fDoNotDestroyWindow flag is used by
+ // MaybeCreateDocWindow in the case that the server is a
+ // single use server, and revokes its class factory when
+ // an object is created. MaybeCreateDocWindow will set this
+ // flag, telling us to ignore the message.
+ //
+ // returning 0 means we did destroy, 1 means we did not.
+
+ if (!lpsrvr->m_fDoNotDestroyWindow)
+ {
+ RemDdeRevokeClassFactory(lpsrvr);
+ return(0);
+ }
+ return 1;
+ break;
+
+ default:
+ return SSDefWindowProc (hwndIn, msg, wParam, lParam);
+ }
+
+ return 0L;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDDEServer::HandleInitMsg
+//
+// Synopsis: Determine if we are going to handle the INITIATE message.
+//
+// Effects:
+//
+// Arguments: [lParam] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-28-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL_(BOOL) CDDEServer::HandleInitMsg(LPARAM lParam)
+{
+
+ // If it is not system or Ole, this is not the server.
+ if (!((aSysTopic == (ATOM)(HIWORD(lParam))) || (aOLE == (ATOM)(HIWORD(lParam)))))
+ {
+ return FALSE;
+ }
+ Assert (m_fcfFlags<=REGCLS_MULTI_SEPARATE);
+
+ // single instance MDI accept
+ if (m_fcfFlags != REGCLS_SINGLEUSE)
+ {
+ return TRUE;
+ }
+
+ // this server is multiple instance. So, check for any clients or docs.
+ if (!GetWindow (m_hwnd, GW_CHILD) && 0==m_cSrvrClients)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+
+// AddClient: Adds a client entry to the list.
+// Each client entry is a pair of handles; key handle
+// and data handle. Ecah list entry contains space for
+// MAX_LIST of pairs of handles.
+
+INTERNAL_(BOOL) AddClient
+(
+LPHANDLE lphead, // ptr to loc which contains the head handle
+HANDLE hkey, // key
+HANDLE hdata // hdata
+)
+{
+
+ HANDLE hcli = NULL;
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+
+
+ hcli = *lphead;
+
+ // if the entry is already present, return error.
+ if (hcli && FindClient (hcli, hkey, FALSE))
+ return FALSE;
+
+ while (hcli) {
+ if (hcliPrev)
+ LocalUnlock (hcliPrev);
+
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ return FALSE;
+
+ phandle = (HANDLE *) pcli->info;
+ while (phandle < (HANDLE *)(pcli + 1)) {
+ if (*phandle == NULL) {
+ *phandle++ = hkey;
+ *phandle++ = hdata;
+ LocalUnlock (hcli);
+ return TRUE;
+ }
+ phandle++;
+ phandle++;
+ }
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ lphead = (LPHANDLE)&pcli->hcliNext;
+ }
+
+ // not in the list.
+ hcli = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof (CLILIST));
+ if (hcli == NULL)
+ goto errRtn;
+
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ goto errRtn;
+
+ // set the link to this handle in the previous entry
+ *lphead = hcli;
+ if (hcliPrev)
+ LocalUnlock (hcliPrev);
+
+ phandle = (HANDLE *) pcli->info;
+ *phandle++ = hkey;
+ *phandle++ = hdata;
+ LocalUnlock (hcli);
+ return TRUE;
+
+errRtn:
+
+ if (hcliPrev)
+ LocalUnlock (hcliPrev);
+
+ if (hcli)
+ LocalFree (hcli);
+
+ return FALSE;
+
+}
+
+
+// FindClient: finds a client and deletes the client if necessary.
+INTERNAL_(HANDLE) FindClient
+(
+HANDLE hcli,
+HANDLE hkey,
+BOOL bDelete
+)
+{
+ HANDLE hcliPrev = NULL;
+ PCLILIST pcli;
+ HANDLE *phandle;
+ HANDLE hdata;
+
+ while (hcli) {
+ if ((pcli = (PCLILIST) LocalLock (hcli)) == NULL)
+ return FALSE;
+
+ phandle = (HANDLE *) pcli->info;
+ while (phandle < (HANDLE *)(pcli + 1)) {
+ if (*phandle == hkey) {
+ if (bDelete)
+ *phandle = NULL;
+
+ hdata = *++phandle;
+ LocalUnlock (hcli);
+ return hdata;
+ }
+ phandle++;
+ phandle++;
+ }
+ hcliPrev = hcli;
+ hcli = pcli->hcliNext;
+ LocalUnlock (hcliPrev);
+
+ }
+ return NULL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDDEServer::SrvrExecute
+//
+// Synopsis: takes care of the WM_DDE_EXECUTE for the server.
+//
+// Effects: Parses the EXECUTE string, and determines what it should be
+// done.
+//
+// Arguments: [hwnd] -- Server window
+// [hdata] -- Handle to EXECUTE string
+// [hwndClient] -- Client window
+//
+// Requires:
+// hdata is an ANSI string. It was passed to us by a DDE client.
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 6-05-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CDDEServer::SrvrExecute
+(
+HWND hwnd,
+HANDLE hdata,
+HWND hwndClient
+)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%x _IN CDDESrvr::SrvrExecute(hwnd=%x,hdata=%x,hwndClient=%x)\n",
+ this,
+ hwnd,
+ hdata,
+ hwndClient));
+
+ ATOM aCmd;
+ BOOL fActivate;
+
+ LPSTR lpdata = NULL;
+ HANDLE hdup = NULL;
+ HRESULT hresult = E_UNEXPECTED;
+
+ LPSTR lpdocname;
+ LPSTR lptemplate;
+ LPCLIENT lpdocClient = NULL;
+ LPSTR lpnextarg;
+ LPSTR lpclassname;
+ LPSTR lpitemname;
+ LPSTR lpopt;
+ CLSID clsid;
+ WORD wCmdType;
+ BOOL bCreateInst = FALSE;
+ LPUNKNOWN pUnk = NULL;
+
+ LPPERSISTSTORAGE pPersistStg=NULL;
+
+ // REVIEW: if any methods called on the objects genarate DDE messages
+ // before we return from Execute, we will be in trouble.
+
+
+ // REVIEW: this code can be lot simplified if we do the argument scanning
+ // seperately and return the ptrs to the args. Rewrite later on.
+
+ ErrZS (hdup = UtDupGlobal (hdata,GMEM_MOVEABLE), E_OUTOFMEMORY);
+
+ ErrZS (lpdata = (LPSTR)GlobalLock (hdup), E_OUTOFMEMORY);
+
+ intrDebugOut((DEB_ITRACE,
+ "CDDESrvr::SrvrExecute(lpdata = %s)\n",lpdata));
+
+ if (*lpdata++ != '[') // commands start with the left sqaure bracket
+ {
+ hresult = ResultFromScode (RPC_E_DDE_SYNTAX_EXECUTE);
+ goto errRtn;
+ }
+
+ hresult = ReportResult(0, RPC_E_DDE_SYNTAX_EXECUTE, 0, 0);
+ // scan upto the first arg
+ if (!(wCmdType = ScanCommand (lpdata, WT_SRVR, &lpdocname, &aCmd)))
+ goto errRtn;
+
+ if (wCmdType == NON_OLE_COMMAND)
+ {
+ if (!UtilQueryProtocol (m_aClass, PROTOCOL_EXECUTE))
+ hresult = ReportResult(0, RPC_E_DDE_PROTOCOL, 0, 0);
+ else {
+ // REVIEW: StdExecute has to be mapped on to the StdCommandProtocol
+ // What command do we map on to?
+
+ AssertSz (0, "StdExecute is being called for server");
+ }
+
+ goto errRtn1;
+ }
+
+ if (aCmd == aStdExit)
+ {
+ if (*lpdocname)
+ goto errRtn1;
+
+ hresult = NOERROR;
+ // REVIEW: Do we have to initiate any terminations from the
+ // the servr side? Check how this works with excel.
+ goto end2;
+ }
+
+ // scan the next argument.
+ if (!(lpnextarg = ScanArg(lpdocname)))
+ goto errRtn;
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdShowItem("docname", "itemname"[, "true"])]
+ //
+ //////////////////////////////////////////////////////////////////////////
+
+ if (aCmd == aStdShowItem) {
+
+ // first find the documnet. If the doc does not exist, then
+ // blow it off.
+
+ if (!(lpdocClient = FindDocObj (lpdocname)))
+ goto errRtn1;
+
+ lpitemname = lpnextarg;
+
+ if( !(lpopt = ScanArg(lpitemname)))
+ goto errRtn1;
+
+ // scan for the optional parameter
+ // Optional can be only TRUE or FALSE.
+
+ fActivate = FALSE;
+ if (*lpopt) {
+
+ if( !(lpnextarg = ScanBoolArg (lpopt, (BOOL FAR *)&fActivate)))
+ goto errRtn1;
+
+ if (*lpnextarg)
+ goto errRtn1;
+
+ }
+
+
+ // scan it. But, igonre the arg.
+ hresult = lpdocClient->DocShowItem (lpitemname, !fActivate);
+ goto end2;
+
+
+
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdCloseDocument ("docname")]
+ //
+ //////////////////////////////////////////////////////////////////////////
+
+ if (aCmd == aStdClose) {
+ if (!(lpdocClient = FindDocObj (lpdocname)))
+ goto errRtn1;
+
+ if (*lpnextarg)
+ goto errRtn1;
+
+ // REVIEW: Do we have to do anything for shutting down the
+ // the app? Is the client going to initiate the terminate?.
+ // if we need to initiate the terminates, make sure we post
+ // the ACK first.
+
+ lpdocClient->Revoke();
+ goto end2;
+ }
+
+
+ if (aCmd == aStdOpen)
+ {
+ // find if any doc level object is already registerd.
+ // if the object is registerd, then no need to call srvr app.
+ if (FindDocObj (lpdocname))
+ {
+ // A client has already opened the document or user opened the
+ // doc. We should do an addref to the docobj
+
+#ifdef TRY
+ if (m_cSrvrClients == 0)
+ // Why are we doing this?
+ hresult = lpdocClient->m_lpoleObj->AddRef();
+ else
+#endif
+ hresult = NOERROR;
+ goto end1;
+ }
+ }
+
+ if (aCmd == aStdCreate || aCmd == aStdCreateFromTemplate) {
+ lpclassname = lpdocname;
+ lpdocname = lpnextarg;
+ if( !(lpnextarg = ScanArg(lpdocname)))
+ goto errRtn1;
+
+ }
+
+ // check whether we can create/open more than one doc.
+
+ if ((m_fcfFlags == REGCLS_SINGLEUSE) &&
+ GetWindow (m_hwnd, GW_CHILD))
+ goto errRtn;
+
+
+ ErrZ (CLSIDFromAtom(m_aClass, &clsid));
+
+
+ //
+ // Generate a wide version of the name
+ //
+
+ WCHAR awcWideDocName[MAX_STR];
+
+ if (MultiByteToWideChar(CP_ACP,0,lpdocname,-1,awcWideDocName,MAX_STR) == FALSE)
+ {
+ Assert(!"Unable to convert characters");
+ hresult = E_UNEXPECTED;
+ goto errRtn;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdOpenDocument ("docname")]
+ //
+ //////////////////////////////////////////////////////////////////////////
+
+ // Document does not exist.
+ if (aCmd == aStdOpen)
+ {
+ ErrRtnH (wClassesMatch (clsid, awcWideDocName));
+ ErrRtnH (wFileBind (awcWideDocName, &pUnk));
+ }
+
+
+ ErrRtnH (CreateInstance (clsid, awcWideDocName, lpdocname, pUnk, &lpdocClient, hwndClient));
+ bCreateInst = TRUE;
+
+ if (aCmd == aStdOpen)
+ {
+ // Temporary flag to indicate someone will INITIATE on this doc.
+ // The flag is reset after the INITITATE.
+ // This is Yet-Another-Excel-Hack. See ::QueryRevokeClassFactory
+ lpdocClient->m_fCreatedNotConnected = TRUE;
+ }
+ else
+ {
+ lpdocClient->m_fEmbed = TRUE;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdNewDocument ("classname", "docname")]
+ //
+ //////////////////////////////////////////////////////////////////////////
+
+ if (aCmd == aStdCreate)
+ {
+ hresult = lpdocClient->DoInitNew();
+ lpdocClient->m_fCreatedNotConnected = TRUE;
+ goto end;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdNewFormTemplate ("classname", "docname". "templatename)]
+ //
+ //////////////////////////////////////////////////////////////////////////
+ if (aCmd == aStdCreateFromTemplate)
+ {
+ ErrRtnH (lpdocClient->DoInitNew());
+ lpdocClient->m_fCreatedNotConnected = TRUE;
+ IPersistFile FAR * lpPF;
+ lptemplate = lpnextarg;
+
+ if(!(lpnextarg = ScanArg(lpnextarg)))
+ {
+ goto errRtn;
+ }
+
+
+ hresult = lpdocClient->m_lpoleObj->QueryInterface(IID_IPersistFile,(LPLPVOID)&lpPF);
+ if (hresult == NOERROR)
+ {
+ WCHAR awcWideTemplate[MAX_STR];
+
+ if (MultiByteToWideChar(CP_ACP,0,lpdocname,-1,awcWideTemplate,MAX_STR) != FALSE)
+ {
+ hresult = lpPF->Load(awcWideTemplate, 0);
+ }
+ else
+ {
+ Assert(!"Unable to convert characters");
+ lpPF->Release();
+ hresult = E_UNEXPECTED;
+ goto end;
+ }
+
+ lpPF->Release();
+ lpdocClient->m_fEmbed = TRUE;
+ }
+ else
+ {
+ goto end;
+ }
+ }
+ //////////////////////////////////////////////////////////////////////////
+ //
+ // [StdEditDocument ("docname")]
+ //
+ //////////////////////////////////////////////////////////////////////////
+ // REVIEW: Do we have to call InitNew for editing an embedded object
+
+ if (aCmd == aStdEdit)
+ {
+ lpdocClient->m_fEmbed = TRUE;
+ lpdocClient->m_fGotEditNoPokeNativeYet = TRUE;
+ lpdocClient->m_fCreatedNotConnected = TRUE;
+ goto end;
+ }
+
+ intrDebugOut((DEB_IERROR,
+ "%x CDDESrvr::SrvrExecute Unknown command\n",
+ this));
+
+end:
+
+ if (hresult != NOERROR)
+ goto errRtn;
+end1:
+ // make sure that the srg string is indeed terminated by
+ // NULL.
+ if (*lpnextarg)
+ {
+ hresult = RPC_E_DDE_SYNTAX_EXECUTE;
+ }
+errRtn:
+
+ if ( hresult != NOERROR)
+ {
+ if (bCreateInst && lpdocClient)
+ {
+ lpdocClient->DestroyInstance ();
+ lpdocClient = NULL; //DestroyInstance invalidates the pointer
+ }
+ }
+
+end2:
+errRtn1:
+
+ if (lpdata)
+ GlobalUnlock (hdup);
+
+ if (hdup)
+ GlobalFree (hdup);
+ if (pUnk)
+ pUnk->Release();
+
+ if (pPersistStg)
+ pPersistStg->Release();
+
+ Assert (GetScode(hresult) != E_UNEXPECTED);
+
+ intrDebugOut((DEB_ITRACE,
+ "%x _OUT CDDESrvr::SrvrExecute hresult=%x\n",
+ this,
+ hresult));
+
+ return hresult;
+}
+
+
+
+
+// Maybe CreateDocWindow
+//
+// Return NOERROR only if a doc window was created and it sent an ACK.
+//
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: MaybeCreateDocWindow
+//
+// Synopsis: Determine if a DocWindow should be created
+//
+// Effects: Given a class, and a filename atom, determine if this thread
+// should be the server for this request.
+//
+// Arguments: [aClass] -- Class of object (PROGID)
+// [aFile] -- Filename (ATOM)
+// [hwndDdeServer] -- HWND of CDDEServer
+// [hwndSender] -- HWND of new requesting client
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-29-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+ INTERNAL MaybeCreateDocWindow
+ (ATOM aClass,
+ ATOM aFile,
+ HWND hwndDdeServer,
+ HWND hwndSender)
+{
+ CLSID clsid = CLSID_NULL;
+ LPUNKNOWN pUnk = NULL;
+ HWND hwndClient = NULL;
+ ULONG fAckSent = FALSE;
+ LPSRVR pDdeSrvr = NULL;
+ WCHAR szFile [MAX_STR];
+ BOOL fTrue = TRUE;
+ BOOL fRunningInSDI = FALSE;
+ HRESULT hresult = NOERROR;
+ IClassFactory *pcf = NULL;
+ IPersistFile *ppf = NULL;
+ DdeClassInfo ddeClassInfo;
+
+ intrDebugOut((DEB_DDE_INIT,
+ "MaybeCreateDocWindow(aClass=%x(%ws),aFile=%x,"
+ "hwndDdeServer=%x,hwndSender=%x\n",
+ aClass,wAtomName(aClass),aFile,hwndDdeServer,hwndSender));
+
+ //
+ // If the window isn't valid, it would be very bad.
+ //
+ if (!IsWindowValid(hwndDdeServer))
+ {
+ intrDebugOut((DEB_DDE_INIT,
+ "MaybeCreateDocWindow: hwndDdeServer is invalid\n"));
+ hresult = E_UNEXPECTED;
+ goto exitRtn;
+ }
+
+ //
+ // We need the filename, which is passed in an Atom
+ //
+ Assert (IsFile (aFile));
+ if (GlobalGetAtomName(aFile,szFile,MAX_STR) == 0)
+ {
+ //
+ // The filename was not valid
+ //
+ hresult = S_FALSE;
+ intrDebugOut((DEB_IERROR,
+ "MaybeCreateDocWindow Invalid file atom\n"));
+ goto exitRtn;
+ }
+
+ intrDebugOut((DEB_DDE_INIT,
+ "MaybeCreateDocWindow File=(%ws)\n",
+ WIDECHECK(szFile)));
+
+ //
+ // Get the class of the object. The class was passed as an atom
+ // in the INITIATE message.
+ //
+ if (CLSIDFromAtomWithTreatAs (&aClass, &clsid, NULL))
+ {
+ intrDebugOut((DEB_IERROR,
+ "MaybeCreateDocWindow CLSIDFromAtom failed\n"));
+
+ hresult = S_FALSE;
+ goto exitRtn;
+ }
+
+ if (CoIsOle1Class(clsid))
+ {
+ // we shouldn't even be looking at this INIT message
+ hresult = S_FALSE;
+ intrDebugOut((DEB_DDE_INIT,
+ "MaybeCreateDocWindow Its an OLE 1.0 class\n"));
+ goto exitRtn;
+ }
+
+ //
+ // First of three cases is to see if the object is running in our
+ // local apartment. If it is, then this is the object we need to create
+ // a DDEServer for.
+ //
+ // Otherwise, We are going to try and load this file.
+ // Therefore, we need the class factory from the CFT.
+ //
+ // GetClassInformationForDde won't find a match if the class factory was
+ // single use, and is now hidden or invalid.
+ //
+ // If there was no class information available, then we are going to
+ // check to see if the object is in the local ROT. If it is in the
+ // local ROT, then we will use it, since it is registered and
+ // available for use by others
+ //
+
+ ddeClassInfo.dwContextMask = CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_SERVER;
+ ddeClassInfo.fClaimFactory = TRUE;
+
+ if ( GetLocalRunningObjectForDde(szFile, &pUnk) == NOERROR)
+ {
+ intrDebugOut((DEB_DDE_INIT,
+ "Found %ws in ROT\n",WIDECHECK(szFile)));
+ //
+ // Elsewhere in the code, we need to know if this is an SDI server.
+ // The old code determined this by detecting that there is a running
+ // object, and there was no class factory registered.
+ // This is sick, and obscene. Compatibilities says we need to get the
+ // class info anyway. However, we don't want to claim it.
+ //
+
+ ddeClassInfo.fClaimFactory = FALSE;
+ fRunningInSDI = !GetClassInformationForDde(clsid,&ddeClassInfo);
+ }
+ else if (!GetClassInformationForDde(clsid,&ddeClassInfo))
+ {
+ intrDebugOut((DEB_IERROR,
+ "No class registered for %ws\n",WIDECHECK(szFile)));
+
+ hresult = S_FALSE;
+ goto exitRtn;
+ }
+ else
+ {
+ //
+ // Otherwise, we are registered as the server for this class. This
+ // means we can create this object.
+ //
+ // A 1.0 client will have launched the server with a command line
+ // like server.exe -Embedding filename The server ignored the filename
+ // so now we must make it load the file by binding the moniker.
+ //
+ // KevinRo: The old code did a bind moniker here, on the filename,
+ // which went through the ROT, didn't find the object, so went for
+ // a server. This isn't terribly safe, since we could end up binding
+ // out of process when we really didn't mean to. So, I have made this
+ // routine just use the ClassFactory we retrieve from the
+ // local class factory table.
+ //
+
+ intrDebugOut((DEB_DDE_INIT,
+ "Found classinfo: Loading %ws\n",WIDECHECK(szFile)));
+
+
+ //
+ // Need to insure that the server doesn't go away on us. The following
+ // tells the server not to destroy itself.
+ //
+ SSSendMessage(hwndDdeServer,WM_DONOTDESTROY,TRUE,0);
+
+ intrAssert(ddeClassInfo.punk != NULL);
+ pcf = (IClassFactory *) ddeClassInfo.punk;
+
+ hresult = pcf->CreateInstance(NULL,IID_IUnknown,(void **)&pUnk);
+
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "MaybeCreateDocWindow CreateInstancefailed File=(%ws)\n",
+ WIDECHECK(szFile)));
+ goto sndMsg;
+ }
+
+ //
+ // Get the IPersistFile interface, and ask the object to load
+ // itself.
+ //
+ hresult = pUnk->QueryInterface(IID_IPersistFile,(void **)&ppf);
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "MaybeCreateDocWindow QI IPF failed File=(%ws)\n",
+ WIDECHECK(szFile)));
+ goto sndMsg;
+ }
+ //
+ // Attempt to load the object. The flags STGM_READWRITE are the
+ // same default values used by a standard bind context.
+ //
+ hresult = ppf->Load(szFile,STGM_READWRITE);
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "MaybeCreateDocWindow ppf->Load(%ws) failed %x\n",
+ WIDECHECK(szFile),
+ hresult));
+ goto sndMsg;
+ }
+sndMsg:
+ SSSendMessage(hwndDdeServer,WM_DONOTDESTROY,FALSE,0);
+ if (hresult != NOERROR)
+ {
+ goto exitRtn;
+
+ }
+ intrDebugOut((DEB_DDE_INIT,
+ "Loading %ws complete\n",WIDECHECK(szFile)));
+
+ }
+
+
+ intrAssert(IsWindowValid(hwndDdeServer));
+ intrAssert (pUnk);
+
+ pDdeSrvr = (LPSRVR) GetWindowLong (hwndDdeServer, 0);
+ if (pDdeSrvr == NULL)
+ {
+ intrAssert(pDdeSrvr != NULL);
+ hresult = E_UNEXPECTED;
+ goto exitRtn;
+ }
+
+ // This actually creates the doc window as a child of the server window
+ // Do not set the client site becuase this is a link.
+ hresult = CDefClient::Create (pDdeSrvr,
+ pUnk,
+ szFile,
+ /*fSetClientSite*/FALSE,
+ /*fDoAdvise*/TRUE,
+ fRunningInSDI,
+ &hwndClient);
+
+ if (hresult != NOERROR)
+ {
+ intrDebugOut((DEB_IERROR,
+ "MaybeCreateDocWindow CDefClient::Create failed %x\n",
+ hresult));
+ goto exitRtn;
+ }
+
+ Assert (IsWindowValid (hwndClient));
+
+ //
+ // Pass along the original DDE_INIT to the newly created window.
+ // That window should respond by sending an ACK to the 1.0 client.
+ //
+ fAckSent = SSSendMessage (hwndClient,
+ WM_DDE_INITIATE,
+ (UINT) hwndSender,
+ MAKELONG(aClass, aFile));
+ if (!fAckSent)
+ {
+ intrDebugOut((DEB_IERROR,
+ "MaybeCreateDocWindow !fAckSent\n"));
+ hresult = CO_E_APPDIDNTREG;
+ }
+
+exitRtn:
+
+ if (ppf)
+ {
+ ppf->Release();
+ }
+ if (pUnk)
+ {
+ pUnk->Release();
+ }
+ if (pcf)
+ {
+ pcf->Release();
+ }
+
+ intrDebugOut((DEB_DDE_INIT,
+ "MaybeCreateDocWindow returns %x\n",
+ hresult));
+ return hresult;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SendMsgToChildren
+//
+// Synopsis: This routine sends the msg to all child windows.
+//
+// Arguments: [hwnd] -- Hwnd of parent window
+// [msg] -- Message and parameters to send
+// [wParam] --
+// [lParam] --
+//
+// Notes: This routine will stop on the first non-zero return code.
+//
+//----------------------------------------------------------------------------
+BOOL SendMsgToChildren (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ intrDebugOut((DEB_ITRACE,
+ "0 _IN SendMsgToChildren(hwnd=%x,msg=%x,wParam=%x,lParam=%x)\n",
+ hwnd,msg,wParam,lParam));
+
+ BOOL fAckSent = FALSE;
+
+ hwnd = GetWindow(hwnd, GW_CHILD);
+
+ //
+ // This routine is to be called only from one place, which is
+ // in the handling of WM_DDE_INITIATE. Because of that, we will terminate
+ // the loop on the first non-zero return code.
+ //
+ Assert (msg == WM_DDE_INITIATE);
+
+ while (hwnd)
+ {
+ intrDebugOut((DEB_ITRACE," SendMsgToChildren send to hwnd=%x\n",hwnd));
+
+ if (fAckSent = (1L==SSSendMessage (hwnd, msg, wParam, lParam)))
+ {
+ break;
+ }
+
+ hwnd = GetWindow (hwnd, GW_HWNDNEXT);
+ }
+
+ intrDebugOut((DEB_ITRACE,"0 OUT SendMsgToChildren returns %x\n",fAckSent));
+ return(fAckSent);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: SendInitMsgToChildren
+//
+// Synopsis: Sends an init message to all child windows of the hwnd
+//
+// Effects: This routine will send an init message to all children
+// of the given window. It is assuming that the lParam is
+// the atom that contains the topic (ie filename) of the
+// object being looked for.
+//
+// Arguments: [hwnd] -- hwnd of server window
+// [msg] -- MSG to send
+// [wParam] -- hwnd of client window
+// [lParam] -- HIWORD(lParam) is atom of filename
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 6-28-94 kevinro Commented
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL SendInitMsgToChildren (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ intrDebugOut((DEB_DDE_INIT,
+ "0 _IN SendInitMsgToChildren(hwnd=%x,msg=%x,wParam=%x,lParam=%x)\n",
+ hwnd,msg,wParam,lParam));
+
+ BOOL fAckSent = FALSE;
+
+ fAckSent = SendMsgToChildren(hwnd,msg,wParam,lParam);
+
+ //
+ // If no windows acknowledged, then we might need to create a doc window
+ //
+ if (!fAckSent)
+ {
+ ATOM aTopic = HIWORD(lParam);
+ Assert (IsAtom(aTopic));
+
+ // if someone's trying to initiate on a filename, i.e., for a link
+ // then create the doc window on demand because 2.0 servers do not
+ // register doc windows. They don't even accept "-Embedding filename"
+ // on the command line
+ if (aTopic != aOLE && aTopic != aSysTopic && IsFile (aTopic))
+ {
+ intrDebugOut((DEB_DDE_INIT," Initiate for link %ws\n",wAtomName(aTopic)));
+ HRESULT hresult = MaybeCreateDocWindow (LOWORD(lParam), aTopic,
+ hwnd, (HWND)wParam);
+
+ fAckSent = (NOERROR==hresult);
+ }
+ }
+ intrDebugOut((DEB_DDE_INIT,
+ "0 _OUT SendInitMsgToChildren fAckSent=%x\n",fAckSent));
+ return fAckSent;
+}
+
+
+
+INTERNAL_(HRESULT) RequestDataStd
+(
+ATOM aItem,
+LPHANDLE lphdde
+)
+{
+
+
+ HANDLE hnew = NULL;
+
+ if (!aItem)
+ goto errRtn;
+
+ if (aItem == aEditItems){
+ hnew = MakeGlobal ("StdHostNames\tStdDocDimensions\tStdTargetDevice");
+ goto PostData;
+
+ }
+
+ if (aItem == aProtocols) {
+ hnew = MakeGlobal ("Embedding\tStdFileEditing");
+ goto PostData;
+ }
+
+ if (aItem == aTopics) {
+ hnew = MakeGlobal ("Doc");
+ goto PostData;
+ }
+
+ if (aItem == aFormats) {
+ hnew = MakeGlobal ("Picture\tBitmap");
+ goto PostData;
+ }
+
+ if (aItem == aStatus) {
+ hnew = MakeGlobal ("Ready");
+ goto PostData;
+ }
+
+ // format we do not understand.
+ goto errRtn;
+
+PostData:
+
+ // Duplicate the DDE data
+ if (MakeDDEData (hnew, CF_TEXT, lphdde, TRUE)){
+ // !!! why are we duplicating the atom.
+ DuplicateAtom (aItem);
+ return NOERROR;
+ }
+errRtn:
+ return ReportResult(0, S_FALSE, 0, 0);
+}
+
+
+//IsSingleServerInstance: returns true if the app is single server app else
+//false.
+
+INTERNAL_(BOOL) IsSingleServerInstance ()
+{
+ HWND hwnd;
+ WORD cnt = 0;
+ HTASK hTask;
+ DdeCHAR buf[MAX_STR];
+
+ hwnd = GetWindow (GetDesktopWindow(), GW_CHILD);
+ hTask = GetCurrentThreadId();
+
+ while (hwnd) {
+ if (hTask == ((HTASK) GetWindowThreadProcessId (hwnd,NULL))) {
+ DdeGetClassName (hwnd, buf, MAX_STR);
+ if (Ddelstrcmp (buf, SRVR_CLASS) == 0)
+ cnt++;
+ }
+ hwnd = GetWindow (hwnd, GW_HWNDNEXT);
+ }
+#ifdef FIREWALLS
+ AssertSz (cnt > 0, "srvr window instance count is zero");
+#endif
+ if (cnt == 1)
+ return TRUE;
+ else
+ return FALSE;
+
+}
+
+
+// QueryRevokeClassFactory: returns FALSE if there are clients
+// connected tothis class factory;
+INTERNAL_(BOOL) CDDEServer::QueryRevokeClassFactory ()
+{
+
+ HWND hwnd;
+ LPCLIENT lpclient;
+
+ Assert (IsWindow (m_hwnd));
+ hwnd = GetWindow (m_hwnd, GW_CHILD);
+ while (hwnd)
+ {
+ Assert (IsWindow (hwnd));
+ lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
+ if (lpclient->m_cClients != 0 || lpclient->m_fCreatedNotConnected)
+ return FALSE;
+ hwnd = GetWindow (hwnd, GW_HWNDNEXT);
+ }
+ return TRUE;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDDEServer::CreateInstance
+//
+// Synopsis: Create an instance of a document
+//
+// Effects:
+//
+// Arguments: [lpclassName] --
+// [lpWidedocName] --
+// [lpdocName] --
+// [pUnk] --
+// [lplpdocClient] --
+// [hwndClient] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 5-30-94 kevinro Commented/cleaned
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+INTERNAL CDDEServer::CreateInstance
+(
+REFCLSID lpclassName,
+LPOLESTR lpWidedocName,
+LPSTR lpdocName,
+LPUNKNOWN pUnk,
+LPCLIENT FAR* lplpdocClient,
+HWND hwndClient)
+{
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CDDEServer::CreateInstance(lpWidedocName=%ws,hwndClient=%x)\n",
+ this,
+ WIDECHECK(lpWidedocName),
+ hwndClient));
+
+
+ LPUNKNOWN pUnk2=NULL;
+ LPOLEOBJECT lpoleObj= NULL; // unknown object
+ HRESULT hresult;
+
+ ChkS(this);
+
+ if (NULL==pUnk)
+ {
+ Assert (m_pClassFactory);
+ hresult = m_pClassFactory->CreateInstance (NULL, IID_IUnknown, (LPLPVOID)&pUnk2);
+
+ if (hresult != NOERROR)
+ {
+ return hresult;
+ }
+
+ // Now that we have *used* the DDE server window, we can unlock
+ // the server.
+ // The OLE1 OleLockServer API opens a dummy DDE system channel
+ // and just leaves it open until OleunlockServer is called.
+ // Since we have now used this channel, we know it was not created
+ // for the purpose of locking the server.
+ this->Lock (FALSE, hwndClient);
+
+ // if it is an SDI app, we must revoke the ClassFactory after using it
+ // it is only good for "one-shot" createinstance call.
+ if (m_fcfFlags == REGCLS_SINGLEUSE)
+ {
+ m_pClassFactory->Release(); // done with the ClassFactory
+ Puts ("NULLing m_pCF\r\n");
+ m_pClassFactory = NULL;
+ }
+ }
+ else
+ {
+ pUnk2 = pUnk;
+ pUnk->AddRef();
+ }
+
+ hresult = CDefClient::Create ((LPSRVR)this,
+ pUnk2,
+ lpWidedocName,
+ /*fSetClientSite*/FALSE,
+ /*fDoAdvise*/pUnk!=NULL);
+
+ intrAssert (pUnk2 != NULL);
+ if (pUnk2 != NULL)
+ {
+ pUnk2->Release();
+ }
+
+ pUnk2 = NULL;
+
+ // REVIEW: error recovery
+ if (!(*lplpdocClient = FindDocObj (lpdocName)))
+ {
+ intrAssert(!"Document created but not found");
+ }
+ else
+ {
+ // set the server instance flag so that WM_DDE_INITIATE will not icrement
+ // the ref count. (EXCEL BUG)
+ (*lplpdocClient)->m_bCreateInst = TRUE;
+ }
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT CDDEServer::CreateInstance hresult=%x\n",
+ this,hresult));
+ return hresult;
+}
+
+
+INTERNAL_(void) CDDEServer::Lock
+ (BOOL fLock, // lock or unlock?
+ HWND hwndClient) // on behalf of which window?
+{
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN CDDEServer::Lock(fLock=%x,hwndCient=%x)\n",
+ this,
+ fLock,
+ hwndClient));
+
+ VDATEHEAP();
+ BOOL fIsLocked = (BOOL) FindClient (m_hcli, hwndClient, /*fDelete*/FALSE);
+
+ if (fLock && !fIsLocked)
+ {
+ if (m_pClassFactory)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%p ::Locking %x\n",
+ this,
+ m_pClassFactory));
+
+ m_pClassFactory->LockServer (TRUE);
+ // Only way to change the data associated with a client window
+ // is to delete it and re-add it with the new data.
+ FindClient (m_hcli, hwndClient, /*fDelete*/ TRUE);
+ AddClient (&m_hcli, hwndClient, (HANDLE) TRUE); // mark as locked
+ }
+ }
+ else if (!fLock && fIsLocked)
+ {
+ if (m_pClassFactory)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%p ::UnLocking %x\n",
+ this,
+ m_pClassFactory));
+ m_pClassFactory->LockServer (FALSE);
+ FindClient (m_hcli, hwndClient, /*fDelete*/ TRUE);
+ AddClient (&m_hcli, hwndClient, (HANDLE) FALSE); //mark as unlocked
+ }
+ }
+ VDATEHEAP();
+ intrDebugOut((DEB_ITRACE,
+ "%p _OUT CDDEServer::Lock(fLock=%x,hwndCient=%x)\n",
+ this,
+ fLock,
+ hwndClient));
+}
+
+
+
+
+
+INTERNAL CDefClient::DestroyInstance
+ (void)
+{
+ Puts ("DestroyInstance\r\n");
+ // We just created the instance. we ran into error.
+ // just call Release.
+ m_pUnkOuter->AddRef();
+ ReleaseObjPtrs();
+ Verify (0==m_pUnkOuter->Release());
+ // "this" should be deleted now
+ return NOERROR;
+}
+
+
+
+INTERNAL CDefClient::SetClientSite
+ (void)
+{
+ HRESULT hresult = m_lpoleObj->SetClientSite (&m_OleClientSite);
+ if (hresult==NOERROR)
+ {
+ m_fDidSetClientSite = TRUE;
+ }
+ else
+ {
+ Warn ("SetClientSite failed");
+ }
+ return hresult;
+}
+
+
+
diff --git a/private/ole32/com/remote/dde/server/srvr.h b/private/ole32/com/remote/dde/server/srvr.h
new file mode 100644
index 000000000..e599fb019
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/srvr.h
@@ -0,0 +1,522 @@
+/****************************** Module Header ******************************\
+* Module Name: srvr.h
+*
+* PURPOSE: Private definitions file for server code
+*
+* Created: 1990
+*
+* Copyright (c) 1990, 1991 Microsoft Corporation
+*
+* History:
+* Raor (../../90,91) Original
+*
+\***************************************************************************/
+//
+// One of the oleint.h routines redefines GlobalAlloc and friends
+// to perform some memory tracking functions.
+//
+// This doesn't work in these files, since the tracking functions
+// add tail checking, and size to the data structures. GlobalSize
+// is a common function to use to determine how much data to
+// serialize, plus it turns out that the other side of a DDE
+// connection will often be the caller to free the memory.
+//
+// Therefore, OLE_DDE_NO_GLOBAL_TRACKING is used to disable this in the
+// global header file ih\memapi.hxx. Check to insure this
+// flag is set on the compile line
+//
+#if !defined(OLE_DDE_NO_GLOBAL_TRACKING)
+error OLE_DDE_OLE_DDE_NO_GLOBAL_TRACKING must be defined to build this directory
+#endif
+
+#include <dde.h>
+#include <ddeerr.h>
+#include "ddeatoms.h"
+#include "ddepack.h"
+#include <callcont.hxx>
+#include <ddeint.h>
+#include <ddechc.hxx>
+#include <longname.h>
+
+//#define UPDATE
+/*
+ if UPDATE is defined it means:
+ If a 1.0 client advises on save, also do a data advise.
+ This way the client will always
+ have an up-to-date picture (and native data) with respect to a
+ 2.0 server, like 2.0 clients do.
+ If a 1.0 client is prepared to accept data at save time
+ it should be able to handle data on each change: it is exactly
+ as if the user chose File.Update after each change.
+ In fact the item atom is appended with /Save, (see SendDataMsg1)
+ which is sort of a lie, but is what a 1.0 client expects for an
+ embedded object.
+ This is a UI issue.
+*/
+
+#define DEFSTD_ITEM_INDEX 0
+#define STDTARGETDEVICE 1
+#define STDDOCDIMENSIONS 2
+#define STDCOLORSCHEME 3
+#define STDHOSTNAMES 4
+
+
+#define PROTOCOL_EDIT (OLESTR("StdFileEditing"))
+#define PROTOCOL_EXECUTE (OLESTR("StdExecute"))
+
+#define ISATOM(a) ((a >= 0xC000) && (a <= 0xFFFF))
+
+// same limit as in OLE 1.0
+#define MAX_STR 124
+
+#define WW_LPTR 0 // ptr tosrvr/doc/item
+#define WW_HANDLE 4 // instance handle
+#define WW_LE 8 // signature
+
+
+#define WC_LE 0x4c45 // LE chars
+
+
+// Signatures for validity checking
+typedef enum
+{
+ chkDdeSrvr = 0x1234,
+ chkDefClient = 0x5678
+} CHK;
+
+
+const DWORD grfCreateStg = STGM_READWRITE | STGM_SHARE_EXCLUSIVE
+ | STGM_DIRECT | STGM_CREATE ;
+
+
+// If we running under WLO, the HIGHWORD of version number will be >= 0x0A00
+#define VER_WLO 0x0A00
+
+extern "C" WORD CheckPointer (LPVOID, int);
+
+#define READ_ACCESS 0
+#define WRITE_ACCESS 1
+
+#define PROBE_READ(lp){\
+ if (!CheckPointer(lp, READ_ACCESS))\
+ return ReportResult(0, E_INVALIDARG, 0, 0); \
+}
+
+#define PROBE_WRITE(lp){\
+ if (!CheckPointer(lp, WRITE_ACCESS))\
+ return ReportResult(0, E_INVALIDARG, 0, 0); \
+}
+
+#define OLE_COMMAND 1
+#define NON_OLE_COMMAND 2
+
+
+#define WT_SRVR 0 // server window
+#define WT_DOC 1 // document window
+
+#define PROBE_BLOCK(lpsrvr) { \
+ if (lpsrvr->bBlock) \
+ return ReportResult(0, S_SERVER_BLOCKED, 0, 0); \
+}
+
+
+#define SET_MSG_STATUS(retval, status) { \
+ if (!FAILED (GetScode (retval))) \
+ status |= 0x8000; \
+ if (GetScode(retval) == RPC_E_SERVERCALL_RETRYLATER)\
+ status |= 0x4000; \
+}
+
+
+/* Codes for CallBack events */
+typedef enum {
+ OLE_CHANGED, /* 0 */
+ OLE_SAVED, /* 1 */
+ OLE_CLOSED, /* 2 */
+ OLE_RENAMED, /* 3 */
+} OLE_NOTIFICATION;
+
+typedef enum { cnvtypNone, cnvtypConvertTo, cnvtypTreatAs } CNVTYP;
+
+typedef struct _QUE : public CPrivAlloc { // nodes in Block/Unblock queue
+ HWND hwnd; //***
+ UINT msg; // window
+ WPARAM wParam; // procedure parameters
+ LPARAM lParam; //***
+ HANDLE hqNext; // handle to next node
+} QUE;
+
+typedef QUE NEAR * PQUE;
+typedef QUE FAR * LPQUE;
+
+// structure for maintaining the client info.
+#define LIST_SIZE 10
+typedef struct _CLILIST : public CPrivAlloc {
+ HANDLE hcliNext;
+ HANDLE info[LIST_SIZE * 2];
+}CLILIST;
+
+typedef CLILIST FAR *LPCLILIST;
+typedef CLILIST *PCLILIST;
+
+
+class FAR CDDEServer
+{
+ public:
+ static HRESULT Create (LPOLESTR lpclass,
+ REFCLSID rclsid,
+ LPDDECLASSINFO lpDdeInfo,
+ HWND FAR * phwnd,
+ ATOM aOriginalClass,
+ CNVTYP cnvtyp);
+
+ INTERNAL_(BOOL) HandleInitMsg (LPARAM);
+ INTERNAL SrvrExecute (HWND, HANDLE, HWND);
+ INTERNAL Revoke (void);
+ INTERNAL_(BOOL) QueryRevokeClassFactory (void);
+ INTERNAL_(LPCLIENT) FindDocObj (LPSTR lpDoc);
+ INTERNAL_(void) Lock (BOOL fLock, HWND hwndClient);
+
+
+ CLSID m_clsid; // Class ID
+ DWORD m_dwClassFactoryKey; // Class factory reg key
+ LPCLASSFACTORY m_pClassFactory; // class factory
+ ICallControl * m_pCallControl; // Call control interface
+ BOOL m_bTerminate; // Set if we are terminating.
+ HWND m_hwnd; // corresponding window
+ HANDLE m_hcli; // handle to the first block of clients list
+ int m_termNo; // termination count
+ int m_cSrvrClients; // no of clients;
+ DWORD m_fcfFlags; // Class factory instance usage flags
+ CNVTYP m_cnvtyp;
+ CHK m_chk;
+
+ ATOM m_aClass; // class atom
+ ATOM m_aOriginalClass; // for TreatAs/ConvertTo case
+ ATOM m_aExe;
+
+ BOOL m_fDoNotDestroyWindow; // When set, server wnd ingores WM_USER
+
+ private:
+ INTERNAL_(void) SendServerTerminateMsg (void);
+ INTERNAL RevokeAllDocObjs (void);
+ INTERNAL FreeSrvrMem (void);
+ INTERNAL CreateInstance (REFCLSID clsid, LPOLESTR lpWidedocName, LPSTR lpdocName,
+ LPUNKNOWN pUnk, LPCLIENT FAR* lplpdocClient,
+ HWND hwndClient);
+
+
+};
+
+
+
+
+BOOL SendInitMsgToChildren (HWND, UINT msg, WPARAM wParam, LPARAM lParam);
+
+INTERNAL RequestDataStd (ATOM, HANDLE FAR *);
+INTERNAL_(BOOL) ValidateSrvrClass (LPOLESTR, ATOM FAR *);
+INTERNAL_(ATOM) GetExeAtom (LPOLESTR);
+INTERNAL_(BOOL) AddClient (LPHANDLE, HANDLE, HANDLE);
+INTERNAL_(HANDLE) FindClient (HANDLE hCli, HANDLE hkey, BOOL fDelete);
+
+INTERNAL_(BOOL) IsSingleServerInstance (void);
+
+INTERNAL_(void) UtilMemCpy (LPSTR, LPSTR, DWORD);
+INTERNAL_(HANDLE) DuplicateData (HANDLE);
+INTERNAL_(LPSTR) ScanBoolArg (LPSTR, BOOL FAR *);
+INTERNAL_(LPSTR) ScanNumArg (LPSTR, LPINT);
+INTERNAL_(LPSTR) ScanArg(LPSTR);
+INTERNAL_(ATOM) MakeDataAtom (ATOM, int);
+INTERNAL_(ATOM) DuplicateAtom (ATOM);
+INTERNAL_(BOOL) CLSIDFromAtom(ATOM aClass, LPCLSID lpclsid);
+INTERNAL CLSIDFromAtomWithTreatAs (ATOM FAR* paClass, LPCLSID lpclsid,
+ CNVTYP FAR* pcnvtyp);
+INTERNAL wFileIsRunning (LPOLESTR szFile);
+INTERNAL wFileBind (LPOLESTR szFile, LPUNKNOWN FAR* ppUnk);
+INTERNAL wCreateStgAroundNative (HANDLE hNative,
+ ATOM aClassOld,
+ ATOM aClassNew,
+ CNVTYP cnvtyp,
+ ATOM aItem,
+ LPSTORAGE FAR* ppstg,
+ LPLOCKBYTES FAR* pplkbyt);
+INTERNAL wCompatibleClasses (ATOM aClient, ATOM aSrvr);
+
+
+
+
+typedef struct FARSTRUCT : public CPrivAlloc {
+ BOOL f; // do we need to send an ack?
+ // If this is FALSE, other fields don't matter
+ HGLOBAL hdata;
+ HWND hwndFrom; // who sent the execute?
+ HWND hwndTo;
+} EXECUTEACK;
+
+
+// client struct definitions.
+
+
+
+class FAR CDefClient : public CPrivAlloc
+{
+ public:
+ static INTERNAL Create
+ (LPSRVR pDdeSrvr,
+ LPUNKNOWN lpunkObj,
+ LPOLESTR lpdocName,
+ const BOOL fSetClientSite,
+ const BOOL fDoAdvise,
+ const BOOL fRunningInSDI = FALSE,
+ HWND FAR* phwnd = NULL);
+
+ INTERNAL DocExecute (HANDLE);
+ INTERNAL DocDoVerbItem (LPSTR, WORD, BOOL, BOOL);
+ INTERNAL DocShowItem (LPSTR, BOOL);
+ INTERNAL DestroyInstance ();
+ INTERNAL_(void) DeleteFromItemsList (HWND h);
+ INTERNAL_(void) RemoveItemFromItemList (void);
+ INTERNAL_(void) ReleasePseudoItems (void);
+ INTERNAL_(void) ReleaseAllItems ();
+ INTERNAL PokeStdItems (HWND, ATOM, HANDLE,int);
+ INTERNAL PokeData (HWND, ATOM, HANDLE);
+ INTERNAL AdviseData (HWND, ATOM, HANDLE, BOOL FAR *);
+ INTERNAL AdviseStdItems (HWND, ATOM, HANDLE, BOOL FAR *);
+ INTERNAL UnAdviseData (HWND, ATOM);
+ INTERNAL RequestData (HWND, ATOM, USHORT, HANDLE FAR *);
+ INTERNAL Revoke (BOOL fRelease=TRUE);
+ INTERNAL ReleaseObjPtrs (void);
+ INTERNAL_(void) DeleteAdviseInfo ();
+ INTERNAL DoOle20Advise (OLE_NOTIFICATION, CLIPFORMAT);
+ INTERNAL DoOle20UnAdviseAll (void);
+ INTERNAL SetClientSite (void);
+ INTERNAL NoItemConnections (void);
+ INTERNAL_(void) SendExecuteAck (HRESULT hresult);
+ INTERNAL DoInitNew(void);
+ INTERNAL Terminate(HWND, HWND);
+
+ CHK m_chk; // signature
+ ICallControl * m_pCallControl; // Call control for this doc
+ IUnknown FAR* m_pUnkOuter;
+ LPOLEOBJECT m_lpoleObj; // corresponding oleobj
+ LPDATAOBJECT m_lpdataObj; // corresponding dataobj
+ BOOL m_bCreateInst; // instance is just created.
+ BOOL m_bTerminate; // REVIEW: The next two fields may not be necessary.
+ int m_termNo;
+ ATOM m_aItem; // item atom or index for some std items
+ HANDLE m_hcli; // handle to the first block of clients list (Document only)
+ CDefClient FAR *m_lpNextItem; // ptr to the next item.
+ BOOL m_bContainer; // Is document?
+ BOOL m_cRef;
+ HWND m_hwnd; // doc window (only needed in document)
+ HANDLE m_hdevInfo; // latest printer dev info sent
+ HANDLE m_hcliInfo; // advise info for each of the clients
+ BOOL m_fDidRealSetHostNames;
+ BOOL m_fDidSetClientSite;
+ BOOL m_fGotDdeAdvise;
+ BOOL m_fCreatedNotConnected;
+ BOOL m_fInOnClose;
+ BOOL m_fInOleSave;
+ EXECUTEACK m_ExecuteAck;
+ DWORD m_dwConnectionOleObj;
+ DWORD m_dwConnectionDataObj;
+ LPLOCKBYTES m_plkbytNative; // These two fields always refer to
+ LPSTORAGE m_pstgNative; // to the same bits:
+ // The server's persistent storage is
+ // used as its native data.
+ BOOL m_fRunningInSDI;// Link case: file was already open in
+ // an SDI app which does not register a
+ // class factory.
+ LPSRVR m_psrvrParent; // (Document only)
+ DVTARGETDEVICE FAR* m_ptd;
+ BOOL m_fGotStdCloseDoc;
+ BOOL m_fGotEditNoPokeNativeYet;
+ BOOL m_fLocked; // locked by CoLockObjectExternal ?
+
+ // If not zero, then we are waiting for a matching TERMINATE
+
+ CALLDATA * m_pCallData;
+
+
+
+
+
+ // REVIEW: These fields might be necssary for doc (old) level object
+ BOOL m_fEmbed; // embedded object (Document only)
+ int m_cClients; // (Document only)
+ LPCLIENT m_pdoc; // containing document (for items) or self (for docs)
+
+
+implementations:
+
+ STDUNKDECL (CDefClient,DefClient);
+
+ /*** IOleClientSite ***/
+ implement COleClientSiteImpl : IOleClientSite
+ {
+ public:
+ // Constructor
+ COleClientSiteImpl (CDefClient FAR* pDefClient)
+ { m_pDefClient = pDefClient;
+ }
+ STDMETHOD(QueryInterface) (REFIID, LPVOID FAR *);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ /*** IOleClientSite methods ***/
+ STDMETHOD(SaveObject) (THIS);
+ STDMETHOD(GetMoniker) (THIS_ DWORD dwAssign, DWORD dwWhichMoniker,
+ LPMONIKER FAR* ppmk);
+ STDMETHOD(GetContainer) (THIS_ LPOLECONTAINER FAR* ppContainer);
+ STDMETHOD(ShowObject) (THIS);
+ STDMETHOD(OnShowWindow) (THIS_ BOOL fShow);
+ STDMETHOD(RequestNewObjectLayout) (THIS);
+
+ private:
+ CDefClient FAR* m_pDefClient;
+ };
+
+ DECLARE_NC (CDefClient, COleClientSiteImpl)
+ COleClientSiteImpl m_OleClientSite;
+
+
+
+ /*** IAdviseSink ***/
+ implement CAdviseSinkImpl : IAdviseSink
+ {
+ public:
+ // Constructor
+ CAdviseSinkImpl (CDefClient FAR* pDefClient)
+ { m_pDefClient = pDefClient;
+ }
+
+ STDMETHOD(QueryInterface) (REFIID, LPVOID FAR *);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ /**** IAdviseSink methods ****/
+ STDMETHOD_(void,OnDataChange)(THIS_ FORMATETC FAR* pFormatetc,
+ STGMEDIUM FAR* pStgmed) ;
+ STDMETHOD_(void,OnViewChange)(THIS_ DWORD aspects, LONG lindex) ;
+ STDMETHOD_(void,OnExtentChange)(DWORD dwAspect, LPSIZEL lpsizel) {}
+ STDMETHOD_(void,OnRename)(THIS_ LPMONIKER pmk) ;
+ STDMETHOD_(void,OnSave)(THIS) ;
+ STDMETHOD_(void,OnClose)(THIS) ;
+
+ private:
+ CDefClient FAR* m_pDefClient;
+ };
+
+ DECLARE_NC (CDefClient, CAdviseSinkImpl)
+ CAdviseSinkImpl m_AdviseSink;
+
+ctor_dtor:
+ CDefClient (LPUNKNOWN pUnkOuter);
+ ~CDefClient (void);
+
+private:
+ INTERNAL ItemCallBack (int msg, LPOLESTR szNewName = NULL);
+ INTERNAL_(void) SendTerminateMsg ();
+ INTERNAL_(BOOL) SendDataMsg1 (HANDLE, WORD);
+ INTERNAL_(BOOL) SendDataMsg (WORD);
+ INTERNAL_(void) TerminateNonRenameClients (LPCLIENT);
+ INTERNAL_(void) SendRenameMsgs (HANDLE);
+ INTERNAL RegisterItem (LPOLESTR, LPCLIENT FAR *, BOOL);
+ INTERNAL FindItem (LPOLESTR, LPCLIENT FAR *);
+ INTERNAL_(LPCLIENT) SearchItem (LPOLESTR);
+ INTERNAL_(void) DeleteAllItems ();
+ INTERNAL SetStdInfo (HWND, LPOLESTR, HANDLE);
+ INTERNAL_(void) SendDevInfo (HWND);
+ INTERNAL_(BOOL) IsFormatAvailable (CLIPFORMAT);
+ INTERNAL GetData (LPFORMATETC, LPSTGMEDIUM);
+};
+
+
+
+
+typedef struct _CLINFO : public CPrivAlloc { /*clInfo*/ // client transaction info
+ HWND hwnd; // client window handle
+ BOOL bnative; // doe sthis client require native
+ int format; // dusplay format
+ int options; // transaction advise time otipns
+ BOOL bdata; // need wdat with advise?
+ HANDLE hdevInfo; // device info handle
+ BOOL bnewDevInfo; // new device info
+} CLINFO;
+
+typedef CLINFO *PCLINFO;
+
+
+
+INTERNAL_(BOOL) MakeDDEData (HANDLE, int, LPHANDLE, BOOL);
+INTERNAL_(HANDLE) MakeGlobal (LPSTR);
+INTERNAL ScanItemOptions (LPOLESTR, int far *);
+INTERNAL_(int) GetStdItemIndex (ATOM);
+INTERNAL_(BOOL) IsAdviseStdItems (ATOM);
+INTERNAL_(HANDLE) MakeItemData (DDEPOKE FAR *, HANDLE, CLIPFORMAT);
+INTERNAL_(BOOL) AddMessage (HWND, unsigned, WORD, LONG, int);
+
+
+
+#define ITEM_FIND 1 // find the item
+#define ITEM_DELETECLIENT 2 // delete the client from item clients
+#define ITEM_DELETE 3 // delete th item window itself
+#define ITEM_SAVED 4 // item saved
+
+// host names data structcure
+typedef struct _HOSTNAMES : public CPrivAlloc {
+ WORD clientNameOffset;
+ WORD documentNameOffset;
+ BYTE data[1];
+} HOSTNAMES;
+
+typedef HOSTNAMES FAR * LPHOSTNAMES;
+
+
+// routines in UTILS.C
+LPOLESTR CreateUnicodeFromAnsi( LPCSTR lpAnsi);
+LPSTR CreateAnsiFromUnicode( LPCOLESTR lpAnsi);
+INTERNAL_(HANDLE) DuplicateData (HANDLE);
+INTERNAL_(LPSTR) ScanLastBoolArg (LPSTR);
+INTERNAL_(LPSTR) ScanArg(LPSTR);
+INTERNAL_(WORD) ScanCommand(LPSTR, WORD, LPSTR FAR *, ATOM FAR *);
+INTERNAL_(ATOM) MakeDataAtom (ATOM, int);
+INTERNAL_(ATOM) DuplicateAtom (ATOM);
+INTERNAL_(WORD) StrToInt (LPOLESTR);
+INTERNAL_(BOOL) PostMessageToClientWithReply (HWND, UINT, WPARAM, LPARAM, UINT);
+INTERNAL_(BOOL) PostMessageToClient (HWND, UINT, WPARAM, LPARAM);
+INTERNAL_(BOOL) IsWindowValid (HWND);
+INTERNAL_(BOOL) IsOleCommand (ATOM, WORD);
+INTERNAL_(BOOL) UtilQueryProtocol (ATOM, LPOLESTR);
+INTERNAL SynchronousPostMessage (HWND, UINT, WPARAM, LPARAM);
+INTERNAL_(BOOL) IsAtom (ATOM);
+INTERNAL_(BOOL) IsFile (ATOM a, BOOL FAR* pfUnsavedDoc = NULL);
+
+
+// routines for queueing messages and posting them
+INTERNAL_(BOOL) UnblockPostMsgs(HWND, BOOL);
+INTERNAL_(BOOL) BlockPostMsg (HWND, WORD, WORD, LONG);
+INTERNAL_(BOOL) IsBlockQueueEmpty (HWND);
+
+// routine in GIVE2GDI.ASM
+extern "C" HANDLE FAR PASCAL GiveToGDI (HANDLE);
+
+
+// routine in item.c
+INTERNAL_(HBITMAP) DuplicateBitmap (HBITMAP);
+INTERNAL_(HANDLE) DuplicateMetaFile (HANDLE);
+INTERNAL_(BOOL) AreNoClients (HANDLE hcli);
+#ifdef _DEBUG
+INTERNAL_(LPOLESTR) a2s (ATOM);
+#endif
+
+// routines in doc.c
+INTERNAL_(void) FreePokeData (HANDLE);
+INTERNAL_(BOOL) FreeGDIdata (HANDLE, CLIPFORMAT);
+INTERNAL DdeHandleIncomingCall(HWND hwndCli, WORD wCallType);
+
+
+// in ddeworkr.cpp
+INTERNAL_(HANDLE) wNewHandle (LPSTR lpstr, DWORD cb);
+INTERNAL wTimedGetMessage (LPMSG pmsg, HWND hwnd, WORD wFirst, WORD wLast);
+INTERNAL_(ATOM) wGlobalAddAtom (LPCOLESTR sz);
diff --git a/private/ole32/com/remote/dde/server/srvrmain.cxx b/private/ole32/com/remote/dde/server/srvrmain.cxx
new file mode 100644
index 000000000..546cb34c0
--- /dev/null
+++ b/private/ole32/com/remote/dde/server/srvrmain.cxx
@@ -0,0 +1,388 @@
+/****************************** Module Header ******************************\
+* Module Name: Srvrmain.c Server Main module
+*
+* Purpose: Includes server intialization and termination code.
+*
+* Created: Oct 1990.
+*
+* Copyright (c) 1990, 1991 Microsoft Corporation
+*
+* History:
+* Raor (../10/1990) Designed, coded
+* Raor (03/../1992) Modified for OLE 2.0
+*
+\***************************************************************************/
+
+#include "ole2int.h"
+#include <dde.h>
+// #include "cmacs.h"
+#include "srvr.h"
+#include "ddeatoms.h"
+#include "ddedebug.h"
+ASSERTDATA
+
+ATOM aStdExit = NULL; // "StdExit"
+ATOM aStdCreate = NULL; // "StdNewDicument"
+ATOM aStdOpen = NULL; // "StdOpenDocument"
+ATOM aStdEdit = NULL; // "StdOpenDocument"
+ATOM aStdCreateFromTemplate = NULL; // "StdNewFromTemplate"
+ATOM aStdClose = NULL; // "StdCloseDocument"
+ATOM aStdShowItem = NULL; // "StdShowItem"
+ATOM aStdDoVerbItem = NULL; // "StddoVerbItem"
+ATOM aSysTopic = NULL; // "System"
+ATOM aOLE = NULL; // "OLE"
+ATOM aProtocols = NULL; // "Protocols"
+ATOM aTopics = NULL; // "Topics"
+ATOM aFormats = NULL; // "Formats"
+ATOM aStatus = NULL; // "Status"
+ATOM aEditItems = NULL; // "Edit items
+ATOM aTrue = NULL; // "True"
+ATOM aFalse = NULL; // "False"
+
+
+ATOM aStdHostNames;
+ATOM aStdTargetDevice ;
+ATOM aStdDocDimensions;
+ATOM aStdColorScheme;
+ATOM aChange;
+ATOM aSave;
+ATOM aClose;
+ATOM aStdDocName;
+ATOM aMSDraw;
+
+
+HINSTANCE hdllInst = NULL;
+
+UINT cOleInitializeCalled = 0;
+
+INTERNAL_(BOOL) DDELibMain (
+ HANDLE hInst,
+ WORD wDataSeg,
+ WORD cbHeapSize,
+ LPOLESTR lpszCmdLine
+)
+{
+ DDEWNDCLASS wc;
+
+ intrDebugOut((DEB_ITRACE,
+ "%p _IN DDELibMain hInst=%x\n",
+ 0,
+ hInst));
+
+ InterlockedIncrement((LONG *)&cOleInitializeCalled);
+
+ if (cOleInitializeCalled > 1)
+ {
+ intrDebugOut((DEB_ITRACE,
+ "%p OUT DDELibMain cOleIinitalizedCalled > 1\n",0));
+
+
+ // we already did the "once-per-machine" initialization
+ return TRUE;
+ }
+
+ hdllInst = (HINSTANCE)hInst;
+
+#ifdef _NT1X_
+ if( !aStdExit )
+ {
+
+ // On NT3.51, user preregisters all of these formats for us,
+ // thus giving us a big speed improvement during startup (because
+ // these atoms never change).
+ // Chicago and Cairo do not yet have this functionality.
+
+ aStdExit = GlobalFindAtom(OLESTR("StdExit"));
+
+ aStdCreate = aStdExit + 1;
+ Assert(aStdCreate == GlobalFindAtom (OLESTR("StdNewDocument")));
+
+ aStdOpen = aStdExit + 2;
+ Assert(aStdOpen == GlobalFindAtom (OLESTR("StdOpenDocument")));
+
+ aStdEdit = aStdExit + 3;
+ Assert(aStdEdit == GlobalFindAtom (OLESTR("StdEditDocument")));
+
+ aStdCreateFromTemplate = aStdExit + 4;
+ Assert(aStdCreateFromTemplate ==
+ GlobalFindAtom(OLESTR("StdNewfromTemplate")));
+
+ aStdClose = aStdExit + 5;
+ Assert(aStdClose == GlobalFindAtom (OLESTR("StdCloseDocument")));
+
+ aStdShowItem = aStdExit + 6;
+ Assert(aStdShowItem == GlobalFindAtom (OLESTR("StdShowItem")));
+
+ aStdDoVerbItem = aStdExit + 7;
+ Assert(aStdDoVerbItem == GlobalFindAtom (OLESTR("StdDoVerbItem")));
+
+ aSysTopic = aStdExit + 8;
+ Assert(aSysTopic == GlobalFindAtom (OLESTR("System")));
+
+ aOLE = aStdExit + 9;
+ Assert(aOLE == GlobalFindAtom (OLESTR("OLEsystem")));
+
+ aStdDocName = aStdExit + 10;
+ Assert(aStdDocName == GlobalFindAtom (OLESTR("StdDocumentName")));
+
+ aProtocols = aStdExit + 11;
+ Assert(aProtocols == GlobalFindAtom (OLESTR("Protocols")));
+
+ aTopics = aStdExit + 12;
+ Assert(aTopics == GlobalFindAtom (OLESTR("Topics")));
+
+ aFormats = aStdExit + 13;
+ Assert(aFormats == GlobalFindAtom (OLESTR("Formats")));
+
+ aStatus = aStdExit + 14;
+ Assert(aStatus == GlobalFindAtom (OLESTR("Status")));
+
+ aEditItems = aStdExit + 15;
+ Assert(aEditItems == GlobalFindAtom (OLESTR("EditEnvItems")));
+
+ aTrue = aStdExit + 16;
+ Assert(aTrue == GlobalFindAtom (OLESTR("True")));
+
+ aFalse = aStdExit + 17;
+ Assert(aFalse == GlobalFindAtom (OLESTR("False")));
+
+ aChange = aStdExit + 18;
+ Assert(aChange == GlobalFindAtom (OLESTR("Change")));
+
+ aSave = aStdExit + 19;
+ Assert(aSave == GlobalFindAtom (OLESTR("Save")));
+
+ aClose = aStdExit + 20;
+ Assert(aClose == GlobalFindAtom (OLESTR("Close")));
+
+ aMSDraw = aStdExit + 21;
+ Assert(aMSDraw == GlobalFindAtom (OLESTR("MSDraw")));
+
+ }
+
+#else // !_NT1X_
+
+ aStdExit = GlobalAddAtomA("StdExit");
+
+ aStdCreate = GlobalAddAtomA("StdNewDocument");
+ aStdOpen = GlobalAddAtomA("StdOpenDocument");
+ aStdEdit = GlobalAddAtomA("StdEditDocument");
+ aStdCreateFromTemplate = GlobalAddAtomA("StdNewfromTemplate");
+
+ aStdClose = GlobalAddAtomA("StdCloseDocument");
+ aStdShowItem = GlobalAddAtomA("StdShowItem");
+ aStdDoVerbItem = GlobalAddAtomA("StdDoVerbItem");
+ aSysTopic = GlobalAddAtomA("System");
+ aOLE = GlobalAddAtomA("OLEsystem");
+ aStdDocName = GlobalAddAtomA("StdDocumentName");
+
+ aProtocols = GlobalAddAtomA("Protocols");
+ aTopics = GlobalAddAtomA("Topics");
+ aFormats = GlobalAddAtomA("Formats");
+ aStatus = GlobalAddAtomA("Status");
+ aEditItems = GlobalAddAtomA("EditEnvItems");
+
+ aTrue = GlobalAddAtomA("True");
+ aFalse = GlobalAddAtomA("False");
+
+ aChange = GlobalAddAtomA("Change");
+ aSave = GlobalAddAtomA("Save");
+ aClose = GlobalAddAtomA("Close");
+ aMSDraw = GlobalAddAtomA("MSDraw");
+
+#endif // !_NT1X_
+
+
+ wc.style = NULL;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = sizeof(LPVOID) + //Ask for extra space for storing the
+ //ptr to srvr/doc/iteminfo.
+ sizeof (ULONG) + // for LE chars
+ sizeof (HANDLE); // for keeping the hDLLInst.
+
+ wc.hInstance = hdllInst;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+
+
+#ifdef _CHICAGO_
+ if (IsWOWThread())
+ {
+ DWORD dwThreadId= GetCurrentThreadId();
+ wsprintfA(szSYS_CLASSA ,"Ole2SysWndClass %08X",
+ CoGetCurrentProcess());
+ wsprintfA(szCLIENT_CLASSA,"Ole2ClientWndClass %08X",
+ CoGetCurrentProcess());
+ wsprintfA(szSRVR_CLASSA ,"SrvrWndClass %08X",
+ CoGetCurrentProcess());
+ wsprintfA(szDOC_CLASSA ,"ViewObjWndClass %08X",
+ CoGetCurrentProcess());
+ wsprintfA(szITEM_CLASSA ,"ItemWndClass %08X",
+ CoGetCurrentProcess());
+ wsprintfA(szCOMMONCLASSA ,"DdeCommonWindowClass %08X",
+ CoGetCurrentProcess());
+ }
+#endif // _CHICAGO_
+
+ //
+ // Here we are going to register our Window classes. Because it is
+ // possible that a previous application failed to unregister these
+ // classes, we are going to ignore registration errors. If we get
+ // to the point where we are really going to create a window, and the
+ // window isn't registered, the CreateWindow call will fail.
+ //
+
+ // Srvr window class
+ wc.lpfnWndProc = (WNDPROC)SrvrWndProc;
+ wc.lpszClassName= SRVR_CLASS;
+
+ if (!DdeRegisterClass(&wc))
+ {
+ intrDebugOut((DEB_IERROR,
+ "RegisterClass SrvrWndProc failed %x\n",
+ GetLastError()));
+ intrAssert(!"RegisterClass SrvrWndProc failed %x\n");
+ }
+
+
+
+ // document window class
+ wc.lpfnWndProc = (WNDPROC)DocWndProc;
+ wc.lpszClassName = DOC_CLASS;
+
+ if (!DdeRegisterClass(&wc))
+ {
+ intrDebugOut((DEB_IERROR,
+ "RegisterClass SrvrWndProc failed %x\n",
+ GetLastError()));
+ intrAssert(!"RegisterClass SrvrWndProc failed %x\n");
+ }
+
+ //
+ // The following supports code in the client directory.
+ //
+ wc.lpfnWndProc = (WNDPROC) ClientDocWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = sizeof(LONG); //we are storing longs
+ wc.lpszClassName= CLIENT_CLASS;
+
+ if (!DdeRegisterClass(&wc))
+ {
+ intrDebugOut((DEB_IERROR,
+ "RegisterClass ClientDocWndProc failed %x\n",
+ GetLastError()));
+ }
+ wc.lpfnWndProc = (WNDPROC) SysWndProc;
+ wc.lpszClassName = SYS_CLASS;
+
+ if (!DdeRegisterClass(&wc))
+ {
+ intrDebugOut((DEB_IERROR,
+ "RegisterClass ClientDocWndProc failed %x\n",
+ GetLastError()));
+ intrAssert(!"RegisterClass SrvrWndProc failed %x\n");
+ }
+
+
+ return TRUE;
+}
+
+
+INTERNAL_(void) DDEWEP (
+ BOOL fSystemExit
+)
+{
+
+ Puts("DdeWep\r\n");
+
+ //* protect against bogous calls to
+
+ if (0==cOleInitializeCalled) return;
+
+ if (--cOleInitializeCalled > 0)
+ {
+ // not done yet
+ return;
+ }
+
+ if (fSystemExit != WEP_FREE_DLL)
+ {
+ AssertSz (0, "Bad parm to Wep");
+ return;
+ }
+
+ // free the global atoms.
+
+ // on NT3.51, these atoms were pre-allocated for us by user, we do
+ // not need to free them.
+#ifndef _NT1X_
+
+ if (aStdExit)
+ GlobalDeleteAtom (aStdExit);
+ if (aStdCreate)
+ GlobalDeleteAtom (aStdCreate);
+ if (aStdOpen)
+ GlobalDeleteAtom (aStdOpen);
+ if (aStdEdit)
+ GlobalDeleteAtom (aStdEdit);
+ if (aStdCreateFromTemplate)
+ GlobalDeleteAtom (aStdCreateFromTemplate);
+ if (aStdClose)
+ GlobalDeleteAtom (aStdClose);
+ if (aStdShowItem)
+ GlobalDeleteAtom (aStdShowItem);
+ if (aStdDoVerbItem)
+ GlobalDeleteAtom (aStdDoVerbItem);
+ if (aSysTopic)
+ GlobalDeleteAtom (aSysTopic);
+ if (aOLE)
+ GlobalDeleteAtom (aOLE);
+ if (aStdDocName)
+ GlobalDeleteAtom (aStdDocName);
+
+ if (aProtocols)
+ GlobalDeleteAtom (aProtocols);
+ if (aTopics)
+ GlobalDeleteAtom (aTopics);
+ if (aFormats)
+ GlobalDeleteAtom (aFormats);
+ if (aStatus)
+ GlobalDeleteAtom (aStatus);
+ if (aEditItems)
+ GlobalDeleteAtom (aEditItems);
+
+ if (aTrue)
+ GlobalDeleteAtom (aTrue);
+ if (aFalse)
+ GlobalDeleteAtom (aFalse);
+
+ if (aChange)
+ GlobalDeleteAtom (aChange);
+ if (aSave)
+ GlobalDeleteAtom (aSave);
+ if (aClose)
+ GlobalDeleteAtom (aClose);
+
+ if (aMSDraw)
+ GlobalDeleteAtom (aMSDraw);
+
+#endif // !_NT1X_
+
+ //
+ // We aren't checking error codes here. Because the server application
+ // can shut down on a whim, its possible that we had outstanding windows
+ // At this point, there isn't a thing we can do about it.
+ //
+
+ //
+ // No reason to add a bunch of new code to only Unregister
+ // the class at the right moment when Chicago will clean up
+ // for us.
+ //
+ DdeUnregisterClass (SRVR_CLASS, hdllInst);
+ DdeUnregisterClass (DOC_CLASS, hdllInst);
+ DdeUnregisterClass (SYS_CLASS, hdllInst);
+ DdeUnregisterClass (CLIENT_CLASS, hdllInst);
+}
diff --git a/private/ole32/com/remote/dirs b/private/ole32/com/remote/dirs
new file mode 100644
index 000000000..b42819102
--- /dev/null
+++ b/private/ole32/com/remote/dirs
@@ -0,0 +1,36 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS= dde
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+
diff --git a/private/ole32/com/remote/endpnt.cxx b/private/ole32/com/remote/endpnt.cxx
new file mode 100644
index 000000000..17cba755c
--- /dev/null
+++ b/private/ole32/com/remote/endpnt.cxx
@@ -0,0 +1,1109 @@
+//+-------------------------------------------------------------------
+//
+// File: endpnt.cxx
+//
+// Contents: class for managing endpoint structures. both the local
+// and remote service object instances use this class.
+//
+// local service object uses RegisterAllProtseqs to register
+// all available protocol sequences with Rpc, and to accquire
+// the list of full string bingings.
+//
+// the remote service object uses it to select, from amongst
+// the many string bindings, the most preffered, to bind to.
+//
+// Classes: CEndPoint
+//
+// Functions: GoodSEp
+//
+// History: 23-Nov-92 Rickhi Created
+// 31-Dec-93 ErikGav Chicago port
+// 28-Jun-94 BruceMa Memory sift fixes
+// 03-Mar-95 JohannP Delaying rpc initialize
+//
+//--------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <endpnt.hxx> // class definition
+#include <compname.hxx> // CComputerName
+
+extern CComputerName g_CompName;
+
+
+
+
+// static class data members
+ULONG CEndPoint::s_ulLocalBindingCount = 0;
+WCHAR CEndPoint::s_wszLocalProtseq[MAX_BINDINGS][MAX_PROTSEQ_STRLEN];
+WCHAR CEndPoint::s_wszLocalNetworkAddr[MAX_BINDINGS][MAX_NETWORKADDR_STRLEN];
+
+#ifdef _CAIRO_
+
+//
+// [richardw] -- See comment down in CEndPoint::RegisterProtseq
+//
+SECURITY_DESCRIPTOR TemporarySecurityDescriptor;
+BOOL fTempSDInitialized = FALSE;
+#endif
+
+
+#ifdef _CHICAGO_
+ULONG GetOleNotificationWnd();
+#else
+#define GetOleNotificationWnd() 0
+#endif // _CHICAGO_
+
+// this is here to help debug some heap corruption problems.
+#if DBG==1
+void MyRpcStringFree(LPWSTR *ppwszString)
+{
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::RpcStringFree %x %ws\n", *ppwszString, *ppwszString));
+ if (*ppwszString)
+ {
+ RpcStringFree(ppwszString);
+ }
+}
+
+
+#else
+
+#define MyRpcStringFree(x) RpcStringFree(x)
+//#define ValidateStringBinding(x)
+
+#endif // DBG==1
+
+
+// attempts to validate the string binding
+void ValidateStringBinding(LPWSTR pwszSB)
+{
+ LPWSTR pwszProtseq = NULL;
+ LPWSTR pwszNetworkAddr = NULL;
+
+ RPC_STATUS sc = RpcStringBindingParse(pwszSB,
+ NULL,
+ &pwszProtseq,
+ &pwszNetworkAddr,
+ NULL,
+ NULL);
+ if (RPC_S_OK == sc)
+ {
+ // verify the protseq is reasonable
+ sc = RpcNetworkIsProtseqValid(pwszProtseq);
+ if (RPC_S_OK != sc)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "Invalid protseq sc:%x pwsz:%ws pwsz:%ws\n",
+ sc, pwszProtseq, pwszSB));
+ }
+
+ MyRpcStringFree(&pwszProtseq);
+ MyRpcStringFree(&pwszNetworkAddr);
+ }
+ else
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "RpcStringBindingParse failed:sc:%x pwsz:%ws\n", sc, pwszSB));
+ }
+}
+
+
+
+inline
+WCHAR * WideStringCopy(WCHAR *pwz)
+{
+ ULONG cbStr;
+ WCHAR *pStr;
+ pStr = (WCHAR *)PrivMemAlloc(cbStr=((lstrlenW(pwz)+1)*sizeof(WCHAR)));
+ if (pStr != NULL)
+ {
+ memcpy(pStr,pwz,cbStr);
+ }
+ return(pStr);
+}
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::SelectStringBinding
+//
+// Purpose: selects a stringbinding from the array of string bindings.
+// sets up _pwszPrefStringBinding, _pwszPrefProtseq, and
+// _eNetworkAddr with copies of the strings.
+//
+// Algorithm: if we can, choose lrpc, else try tcp, else whatever is
+// first in the list.
+//
+// History: 08-Sep-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+void CEndPoint::SelectStringBinding(void)
+{
+ TRACECALL(TRACE_INITIALIZE, "SelectStringBinding");
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::SelectStringBinding Enter \n"));
+ Win4Assert(_pSEp && "Illformed CEndPoint Object");
+
+#ifdef _CHICAGO_
+ if( _pSEp && _pSEp->ulStrLen != 0)
+ {
+ LPWSTR pwszStringBinding = _pSEp->awszEndPoint;
+
+ // there is a valid endpoint
+ // just copy the endpoint string to
+ if (_pwszPrefStringBinding)
+ {
+ PrivMemFree(_pwszPrefStringBinding);
+ }
+ _pwszPrefStringBinding = WideStringCopy(pwszStringBinding);
+ if (_pwszPrefProtseq)
+ {
+ PrivMemFree(_pwszPrefProtseq); // free old one
+ }
+ _pwszPrefProtseq = (LPWSTR)PrivMemAlloc(32);
+ if (_pwszPrefProtseq )
+ {
+ memcpy(_pwszPrefProtseq,LOCAL_PROTSEQ,sizeof(LOCAL_PROTSEQ));
+ }
+ _eNetworkAddr = NA_SAME_MACHINE;
+ }
+ else
+ {
+ // no valid endpoint
+ if (_pwszPrefStringBinding == NULL)
+ {
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::SelectStringBinding Generating fake StringBinding\n"));
+ _pwszPrefStringBinding = (LPWSTR)PrivMemAlloc(128);
+ if (_pwszPrefStringBinding)
+ {
+ wsprintf(_pwszPrefStringBinding, L"%ws:%ws[OLE%-08.8X]",
+ LOCAL_PROTSEQ,g_CompName.GetComputerName(),CoGetCurrentProcess());
+
+ }
+ }
+ if(_pwszPrefProtseq == NULL)
+ {
+ _pwszPrefProtseq = (LPWSTR)PrivMemAlloc(64);
+ if (_pwszPrefProtseq )
+ {
+ memcpy(_pwszPrefProtseq,LOCAL_PROTSEQ,sizeof(LOCAL_PROTSEQ));
+ }
+ }
+ _eNetworkAddr = NA_SAME_MACHINE;
+ CairoleDebugOut((DEB_ENDPNT, " PrefStringBinding: %ws\n", _pwszPrefStringBinding));
+ CairoleDebugOut((DEB_ENDPNT, " PrefProtseq: %ws\n", _pwszPrefProtseq));
+ }
+
+#else
+
+ // examine each Rpc string binding to ensure we can support it.
+ // we also scan to see if we can use our favourite protocol sequence
+ // as it is assumed to be the fastest one.
+
+ LPWSTR pwszStringBinding = _pSEp->awszEndPoint;
+ LPWSTR pwszLastStringBinding = pwszStringBinding + _pSEp->ulStrLen;
+
+ BOOL fDone = FALSE;
+ while (!fDone && pwszStringBinding < pwszLastStringBinding)
+ {
+ LPWSTR pwszProtseq = NULL;
+ LPWSTR pwszNetworkAddr = NULL;
+
+ CairoleDebugOut((DEB_ENDPNT, "RpcStringBindParse: wszStringBind: %ws \n", pwszStringBinding));
+ if (S_OK == RpcStringBindingParse(pwszStringBinding,
+ NULL,
+ &pwszProtseq,
+ &pwszNetworkAddr,
+ NULL,
+ NULL))
+ {
+ CairoleDebugOut((DEB_ENDPNT, "RpcStringBindParse: pwszProtseq=%x pwszNetWorkAddr=%x\n", pwszProtseq, pwszNetworkAddr));
+ CairoleDebugOut((DEB_ENDPNT, "RpcStringBindParse: pwszProtseq=%ws pwszNetWorkAddr=%ws\n", pwszProtseq, pwszNetworkAddr));
+
+ // is this protocol sequence supported on our machine?
+ if (RpcNetworkIsProtseqValid(pwszProtseq) == S_OK)
+ {
+ if (!lstrcmpW(pwszProtseq, LOCAL_PROTSEQ))
+ {
+#ifdef _CHICAGO_
+ //
+ // BUGBUG: Chico registry broken
+ // RPC broken too
+ // Avalanche of BUGBUG's ends here
+ //
+ // THE HACK STOPS HERE
+ // --Erik & Alex & Rick & Dave
+ //
+ if (1)
+#else
+ if (!lstrcmpW(pwszNetworkAddr, g_CompName.GetComputerName()))
+#endif
+ {
+ if (_pwszPrefStringBinding)
+ {
+ PrivMemFree(_pwszPrefStringBinding);
+ }
+ _pwszPrefStringBinding = WideStringCopy(pwszStringBinding);
+ if (_pwszPrefProtseq)
+ MyRpcStringFree(&_pwszPrefProtseq); // free old one
+ _pwszPrefProtseq = pwszProtseq;
+ _eNetworkAddr = NA_SAME_MACHINE;
+ fDone = TRUE;
+ }
+ else
+ {
+ _eNetworkAddr = NA_DIFF_MACHINE;
+ MyRpcStringFree(&pwszProtseq); // free it
+ }
+ }
+#ifdef _CAIRO_
+ else
+ {
+ // CODEWORK: if we assume that there is always lrpc
+ // available, then we can delete the following code for
+ // setting the _eNetworkAddr and just loop until we hit
+ // that protseq above.
+
+ if (_eNetworkAddr == NA_DONT_KNOW)
+ {
+ // first, set _eNetworkAddr correctly. Find the local
+ // protseq that matches this protseq and then compare
+ // the corresponding network addresses.
+
+ for (ULONG i=0; i<s_ulLocalBindingCount; i++)
+ {
+ if (!lstrcmpW(&s_wszLocalProtseq[i][0], pwszProtseq))
+ {
+ // found matching protseq, compare networkaddr
+ if (!lstrcmpW(&s_wszLocalNetworkAddr[i][0],
+ pwszNetworkAddr))
+ {
+ _eNetworkAddr = NA_SAME_MACHINE;
+ }
+ else
+ {
+ _eNetworkAddr = NA_DIFF_MACHINE;
+ }
+
+ // done
+ break;
+ }
+ }
+ }
+
+ if (!lstrcmpW(pwszProtseq, L"ncacn_ip_tcp"))
+ {
+ if (_pwszPrefStringBinding)
+ {
+ PrivMemFree(_pwszPrefStringBinding);
+ }
+ _pwszPrefStringBinding = WideStringCopy(pwszStringBinding);
+
+ MyRpcStringFree(&_pwszPrefProtseq); // free old one
+ _pwszPrefProtseq = pwszProtseq;
+ }
+ else if (!_pwszPrefStringBinding)
+ {
+ _pwszPrefStringBinding = WideStringCopy(pwszStringBinding);
+ _pwszPrefProtseq = pwszProtseq;
+ }
+ }
+#endif // _CAIRO_
+ }
+ else
+ {
+ // not valid, so free it.
+ MyRpcStringFree(&pwszProtseq);
+ }
+
+ // release the returned strings. we keep the Protseq until
+ // it gets replaced above, or until the object destructor is
+ // called.
+ MyRpcStringFree(&pwszNetworkAddr);
+ }
+ else
+ {
+ CairoleDebugOut((DEB_ENDPNT, "RpcStringBindParse: pwszProtseq=%x pwszNetWorkAddr=%x\n", pwszProtseq, pwszNetworkAddr));
+ }
+
+ // get next binding string
+ pwszStringBinding += lstrlenW(pwszStringBinding) + 1;
+ }
+
+ ValidateStringBinding(_pwszPrefStringBinding);
+ Win4Assert((_eNetworkAddr != NA_DONT_KNOW) && "DiffMachine() not computed!");
+#endif // !_CHICAGO_
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::SelectStringBinding Exit\n"));
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::RegisterProtseq
+//
+// Purpose: register a protocol with Rpc, and determine and record
+// our complete stringbindings for each protocol.
+//
+// Algorithm: we create a static endpoint for mswmsg and let RPC assign
+// dynamic endpoints for other protocols,
+// then we go update the list of string bindings (SEP) used by
+// the marshalling code.
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------
+HRESULT CEndPoint::RegisterProtseq(WCHAR *pwszProtseq)
+{
+ TRACECALL(TRACE_INITIALIZE, "RegisterProtseq");
+ CairoleDebugOut((DEB_ENDPNT,"CEndPoint::RegisterProtseq %x %ws\n", pwszProtseq, pwszProtseq));
+
+ HRESULT rc = S_OK;
+ BOOL fRegistered = FALSE;
+ WCHAR pwszEndPoint[12];
+ pwszEndPoint[0] = 0;
+
+#ifndef _CHICAGO_
+ // make sure we have not registered this protseq before.
+ for (ULONG i=0; i<s_ulLocalBindingCount; i++)
+ {
+ if (!lstrcmpW(pwszProtseq, &s_wszLocalProtseq[i][0]))
+ {
+ fRegistered = TRUE;
+ break;
+ }
+ }
+#endif
+
+ if (!fRegistered)
+ {
+
+ // Create a static endpoint for mswmsg.
+ if (lstrcmpW( pwszProtseq, LOCAL_PROTSEQ ) == 0)
+ {
+ // Get a unique number and convert it to a string endpoint.
+ wsprintf(pwszEndPoint, L"OLE%-08.8X",CoGetCurrentProcess());
+
+#ifdef _CAIRO_
+ //
+ // Since Cairo has servers running as different principals,
+ // the default dacl for a process doesn't do us any good. For
+ // the curios, the default dacl generally specifies System and
+ // the principal itself. Since we want other principals to be
+ // able to connect to these servers, we explicitly set the dacl
+ // to NULL, which means all access.
+ //
+ // richardw, 22 Dec 94
+ //
+ if (!fTempSDInitialized)
+ {
+ //
+ // Since this is static storage, and we always initialize it
+ // to the same values, it does not need to be MT safe.
+ //
+ InitializeSecurityDescriptor(&TemporarySecurityDescriptor,
+ SECURITY_DESCRIPTOR_REVISION);
+ SetSecurityDescriptorDacl(&TemporarySecurityDescriptor,
+ TRUE, NULL, FALSE);
+ fTempSDInitialized = TRUE;
+ }
+#endif
+ // register the protocol
+ rc = RpcServerUseProtseqEp(pwszProtseq,
+ RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
+ pwszEndPoint,
+#ifdef _CAIRO_
+ &TemporarySecurityDescriptor);
+#else
+ NULL);
+#endif
+ CairoleDebugOut((DEB_ENDPNT,"CEndPoint::RegisterProtseq Seq:%ws endpoint:%ws\n", pwszProtseq, pwszEndPoint));
+
+
+ // If the endpoint is already registered, then OLE must have been
+ // uninitialized and reinitialized.
+ if (rc == RPC_S_DUPLICATE_ENDPOINT)
+ rc = RPC_S_OK;
+
+ }
+
+ // Register a dynamic endpoint for other protocols.
+ else
+#ifndef _CHICAGO_
+ rc = RpcServerUseProtseq(pwszProtseq,
+ RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
+ NULL);
+#else
+ rc = E_FAIL;
+#endif
+ // On Win95 UpdateSEp can be eliminated since only one
+ // protocoll seq is used.
+ if (rc == RPC_S_OK)
+ {
+ // update our SEP
+ rc = UpdateSEP( pwszEndPoint );
+ CairoleDebugOut((DEB_ENDPNT, "CEndpoint::Registered\n ProtSeq %ws on Endpoint: %ws; SEp: %ws\n",
+ pwszProtseq,
+ pwszEndPoint,
+ _pSEp->awszEndPoint));
+
+ }
+ }
+ else if (!_pSEp)
+ {
+ rc = UpdateSEP( pwszEndPoint );
+ }
+
+ CairoleDebugOut((DEB_ENDPNT,"CEndPoint::RegisterProtseq done rc=%x\n", rc));
+ return rc;
+}
+
+#ifdef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Method: CEndPoint::RemoveDefaultProtseq
+//
+// Synopsis: Removes an endpoint; on Win95 endpoints are per thread
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 3-15-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CEndPoint::RemoveDefaultProtseq(void)
+{
+ CairoleDebugOut((DEB_ENDPNT,"CEndPoint::RemoveDefaultProtseq\n"));
+ HRESULT rc = S_OK;
+ WCHAR *pwszProtseq = LOCAL_PROTSEQ;
+ WCHAR pwszEndPoint[12];
+ pwszEndPoint[0] = 0;
+
+ {
+ // Create the same endpoint string
+ wsprintf(pwszEndPoint, L"OLE%-08.8X", CoGetCurrentProcess());
+ // remove the endpoint
+ rc = I_RpcServerUnregisterEndpointW(pwszProtseq, pwszEndPoint);
+ }
+
+ CairoleDebugOut((DEB_ENDPNT,"CEndPoint::RemoveDefaultProtseq Seq:%ws endpoint:%ws\n", pwszProtseq, pwszEndPoint));
+ return rc;
+}
+#endif // _CHICAGO_
+
+#ifndef _CHICAGO_
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::UpdateSEP
+//
+// Purpose: updates the SEP structure with the current list of
+// endpoints. This is called after registering a new
+// protocol sequence, so that subsequently marshalled
+// interfaces will contain the new endpoint.
+//
+// History: 23-Nov-92 Rickhi Created
+//
+// Note: it is very important that the order of string bindings
+// in the SEp does not change after registering a new
+// protocol sequence, otherwise clients would start creating
+// two different service objects. currently this is valid
+// because Rpc returns the handles in the binding vector in
+// the same order.
+//
+//--------------------------------------------------------------------
+HRESULT CEndPoint::UpdateSEP( LPWSTR unused )
+{
+ TRACECALL(TRACE_INITIALIZE, "UpdateSEP");
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::UpdateSEP Enter\n"));
+
+ // inquire all binding handles. there is one per registered
+ // protocol sequence.
+
+ RPC_BINDING_VECTOR *pBindVect = NULL;
+ RPC_STATUS rc = RpcServerInqBindings(&pBindVect);
+
+ if (rc == S_OK)
+ {
+ LPWSTR pwszFullStringBinding[MAX_BINDINGS];
+ ULONG ulStrLen[MAX_BINDINGS];
+ ULONG ulTotalStrLen = 0; // total string lengths
+ ULONG j = 0; // BindString we're using
+
+ // CODEWORK: this just prevents a GP if the max is exceeded. should
+ // revisit for Cairo and keep only the string bindings in which the
+ // protseqs are unique...thus keeping the marshalled data sizes small.
+ if (pBindVect->Count > MAX_BINDINGS)
+ {
+ CairoleDebugOut((DEB_WARN, "Excessive BindingHandle count\n"));
+ pBindVect->Count = MAX_BINDINGS;
+ }
+
+ // iterate over the handles to get the string bindings
+ // and dynamic endpoints for all available protocols.
+
+ for (ULONG i=0; i<pBindVect->Count; i++)
+ {
+ LPWSTR pwszStringBinding = NULL;
+ pwszFullStringBinding[j] = NULL;
+ ulStrLen[j] = 0;
+
+ rc = RpcBindingToStringBinding(pBindVect->BindingH[i],
+ &pwszStringBinding);
+ Win4Assert(rc == S_OK && "RpcBindingToStringBinding");
+
+
+ if (rc == S_OK)
+ {
+ CairoleDebugOut((DEB_ENDPNT, "pwszStringBinding=%x\n", pwszStringBinding));
+
+ LPWSTR pwszEndPoint = NULL;
+ LPWSTR pwszObjectUUID = NULL;
+ LPWSTR pwszProtseq = NULL;
+ LPWSTR pwszNetworkAddr = NULL;
+
+ // parse the string binding, then recompose with the
+ // endpoint added on, and store it in the array
+
+ rc = RpcStringBindingParse(pwszStringBinding,
+ &pwszObjectUUID,
+ &pwszProtseq,
+ &pwszNetworkAddr,
+ &pwszEndPoint,
+ NULL);
+ Win4Assert(rc == S_OK && "RpcStringBindingParse");
+
+ if (rc == S_OK)
+ {
+ CairoleDebugOut((DEB_ENDPNT, "pwszObjectUUID=%x\n", pwszObjectUUID));
+ CairoleDebugOut((DEB_ENDPNT, "pwszProtseq=%x\n", pwszProtseq));
+ CairoleDebugOut((DEB_ENDPNT, "pwszNetworkAddr=%x\n", pwszNetworkAddr));
+ CairoleDebugOut((DEB_ENDPNT, "pwszEndPoint=%x\n", pwszEndPoint));
+
+ pwszFullStringBinding[j] = pwszStringBinding;
+
+ // record the string lengths for later. include room
+ // for the NULL terminator.
+
+ ulStrLen[j] = lstrlenW(pwszFullStringBinding[j])+1;
+ ulTotalStrLen += ulStrLen[j];
+
+ // store the protseq & network addr stings
+ // in the static variables
+
+ Win4Assert(lstrlenW(pwszProtseq) < MAX_PROTSEQ_STRLEN);
+ Win4Assert(lstrlenW(pwszNetworkAddr) < MAX_NETWORKADDR_STRLEN);
+ lstrcpyW(&s_wszLocalProtseq[j][0], pwszProtseq);
+ lstrcpyW(&s_wszLocalNetworkAddr[j][0], pwszNetworkAddr);
+ j++;
+
+ // free the intermediate strings
+ MyRpcStringFree(&pwszObjectUUID);
+ MyRpcStringFree(&pwszProtseq);
+ MyRpcStringFree(&pwszNetworkAddr);
+ MyRpcStringFree(&pwszEndPoint);
+ }
+ }
+ } // for
+
+
+ s_ulLocalBindingCount = j;
+
+
+ // now that all the string bindings and endpoints have been
+ // accquired, allocate an SEndPoint large enough to hold them
+ // all and copy them into the structure.
+
+ if (ulTotalStrLen > 0)
+ {
+ SEndPoint *pSEp = (SEndPoint *) PrivMemAlloc(NEWSEPSIZE(ulTotalStrLen));
+ if (pSEp)
+ {
+ pSEp->ulStrLen = ulTotalStrLen;
+
+ // copy in the strings
+ LPWSTR pwszNext = pSEp->awszEndPoint;
+ for (i=0; i<j; i++)
+ {
+ lstrcpyW(pwszNext, pwszFullStringBinding[i]);
+ pwszNext += ulStrLen[i];
+ }
+
+ // replace the old pSEP with the new one
+ PrivMemFree(_pSEp);
+ _pSEp = pSEp;
+ }
+ else
+ {
+ rc = E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ // no binding strings. this is an error.
+ CairoleDebugOut((DEB_ERROR, "No Rpc ProtSeq/EndPoints Generated\n"));
+ rc = E_FAIL;
+ }
+
+ // free the full string bindings we allocated above
+ for (i=0; i<j; i++)
+ {
+ // free the old strings
+ MyRpcStringFree(&pwszFullStringBinding[i]);
+ }
+
+ // free the binding vector allocated above
+ RpcBindingVectorFree(&pBindVect);
+ }
+
+#if DBG==1
+ // display our binding strings on the debugger
+ DisplayAllStringBindings();
+#endif
+
+ CairoleDebugOut((DEB_ENDPNT,"CEndPoint::UpdateSEP Exit rc=%x\n", rc));
+ return rc;
+}
+#else
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::UpdateSEP
+//
+// Purpose: Updates the SEP structure with the current endpoint.
+// This is called after registering the protocol sequence,
+// so that subsequently marshalled
+// interfaces will contain the new endpoint.
+//
+// History: 2 Aug 94 AlexMit Created
+//
+// Note: This is a Chicago only version where each thread has one
+// endpoint. Consequently the ordering problem in the NT version
+// does not apply.
+//
+//--------------------------------------------------------------------
+
+HRESULT CEndPoint::UpdateSEP( LPWSTR pwszDesiredEndPoint )
+{
+ TRACECALL(TRACE_INITIALIZE, "UpdateSEP");
+ CairoleDebugOut((DEB_ITRACE | DEB_ENDPNT, "CEndPoint::UpdateSEP Enter\n"));
+
+ RPC_BINDING_VECTOR *pBindVect = NULL;
+ LPWSTR pwszStringBinding = NULL;
+ LPWSTR pwszEndPoint = NULL;
+ ULONG ulStrLen = 0; // string length
+ BOOL fFound = FALSE;
+ RPC_STATUS rc;
+ ULONG i;
+
+ rc = RpcServerInqBindings(&pBindVect);
+ Win4Assert(rc == S_OK && "RpcServerInqBindings");
+
+ if (rc == S_OK)
+ {
+
+ // iterate over the handles to get the string bindings
+ // for the specified endpoint
+
+ for (i=0; i<pBindVect->Count; i++)
+ {
+ rc = RpcBindingToStringBinding(pBindVect->BindingH[i],
+ &pwszStringBinding);
+ Win4Assert(rc == S_OK && "RpcBindingToStringBinding");
+
+
+ if (rc == S_OK)
+ {
+ CairoleDebugOut((DEB_ITRACE, "pwszStringBinding=%x\n", pwszStringBinding));
+
+
+ // parse the string binding
+
+ rc = RpcStringBindingParse(pwszStringBinding,
+ NULL,
+ NULL,
+ NULL,
+ &pwszEndPoint,
+ NULL);
+
+ Win4Assert(rc == S_OK && "RpcStringBindingParse");
+
+ if (rc == S_OK)
+ {
+ CairoleDebugOut((DEB_ITRACE, "pwszEndPoint=%ws\n", pwszEndPoint));
+
+ fFound = lstrcmpW( pwszEndPoint, pwszDesiredEndPoint ) == 0;
+
+ // free the intermediate strings
+
+ MyRpcStringFree(&pwszEndPoint);
+
+ if (fFound)
+ {
+ ulStrLen = lstrlenW( pwszStringBinding ) + 1;
+ SEndPoint *pSEp = (SEndPoint *)
+ PrivMemAlloc(NEWSEPSIZE(ulStrLen));
+
+ if (pSEp)
+ {
+ pSEp->ulStrLen = ulStrLen;
+
+ lstrcpyW(pSEp->awszEndPoint, pwszStringBinding);
+ MyRpcStringFree(&pwszStringBinding);
+
+ if (pSEp->ulStrLen == 0)
+ {
+ // no binding strings. this is an error.
+ CairoleDebugOut((DEB_ERROR,"No Rpc ProtSeq/EndPoints Generated\n"));
+ rc = E_FAIL;
+ break;
+ }
+ else
+ {
+ PrivMemFree(_pSEp);
+#ifdef _CHICAGO_
+ pSEp->ulhwnd = 0;
+#endif
+ _pSEp = pSEp;
+ break;
+ }
+ }
+ }
+ }
+ MyRpcStringFree(&pwszStringBinding);
+ }
+ } // for
+
+ // free the binding vector
+ RpcBindingVectorFree(&pBindVect);
+ }
+
+#if DBG==1
+ // display our binding strings on the debugger
+ DisplayAllStringBindings();
+#endif
+
+ CairoleDebugOut((DEB_ITRACE | DEB_ENDPNT,"CEndPoint::UpdateSEP Exit rc=%x\n", rc));
+ return rc;
+}
+#endif
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::CEndPoint, public
+//
+// Synopsis: constructor for endpoint object. this simply stores
+// a pointer to the SEndPoint structure.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+CEndPoint::CEndPoint(SEndPoint *pSEp, HRESULT &hr, BOOL fCopy) :
+ _fCopy(fCopy),
+ _pwszPrefStringBinding(NULL),
+ _pwszPrefProtseq(NULL),
+ _fRegActiveProtseq(FALSE),
+ _eNetworkAddr(NA_DONT_KNOW)
+{
+ hr = S_OK; // assume success
+
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::CEndPoint ctor fCopy:%d; pSEp:%x\n", fCopy, _pSEp));
+ _fFakeInit = FALSE;
+ if (_fCopy && pSEp)
+ {
+ _pSEp = (SEndPoint *) PrivMemAlloc(SEPSIZE(pSEp));
+ if (_pSEp)
+ {
+ memcpy(_pSEp, pSEp, COPYSEPSIZE(pSEp));
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ _pSEp = pSEp;
+ }
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::CEndPoint %x _pSEp=%x\n", this, _pSEp));
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::~CEndPoint, public
+//
+// Synopsis: destructor for the endpoint object. this deletes the
+// pointer to the SEndPoint structure only if a copy was
+// made.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+CEndPoint::~CEndPoint(void)
+{
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::~CEndPoint _pSEp=%x\n", _pSEp));
+ if (_fFakeInit)
+ {
+ PrivMemFree(_pSEp);
+ PrivMemFree(_pwszPrefStringBinding);
+ PrivMemFree(_pwszPrefProtseq);
+ }
+ else
+ {
+ if (_fCopy)
+ {
+ PrivMemFree(_pSEp);
+ }
+ PrivMemFree(_pwszPrefStringBinding);
+ if (_pwszPrefProtseq)
+ {
+#ifdef _CHICAGO_
+ PrivMemFree(_pwszPrefProtseq);
+#else
+ MyRpcStringFree(&_pwszPrefProtseq);
+#endif
+ }
+ }
+}
+
+#ifdef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Method: CEndPoint::CreateFakeSEp
+//
+// Synopsis: creates a fake endpoint structur on Win95
+// the endpoint
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 3-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+SCODE CEndPoint::CreateFakeSEp(void)
+{
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::CreateFakeSEp _pSEp=%x\n", _pSEp));
+ SCODE sc = RPC_S_OK;
+
+ if(!GetSEp() || GetStrLen() == 0)
+ {
+ // create a fake endpoint
+ ULONG ulStrLen = 0; // string length
+ WCHAR pwszStringBinding[128];
+ pwszStringBinding[0] = 0;
+
+ wsprintf(pwszStringBinding, L"%ws:%ws[OLE%-08.8X]",
+ LOCAL_PROTSEQ,g_CompName.GetComputerName(),CoGetCurrentProcess());
+
+ ulStrLen = lstrlenW( pwszStringBinding ) + 1;
+ SEndPoint *pSEp = (SEndPoint *)
+ PrivMemAlloc(NEWSEPSIZE(ulStrLen));
+
+ if (pSEp)
+ {
+ pSEp->ulStrLen = ulStrLen;
+ lstrcpyW(pSEp->awszEndPoint, pwszStringBinding);
+ if (pSEp->ulStrLen == 0)
+ {
+ // no binding strings. this is an error.
+ CairoleDebugOut((DEB_ERROR,"No Rpc ProtSeq/EndPoints Generated\n"));
+ sc = E_FAIL;
+ }
+ else
+ {
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::CreateFakeSEp New pSEp=%x \n", pSEp));
+#ifdef _CHICAGO_
+ pSEp->ulhwnd = GetOleNotificationWnd();
+#endif
+ SetNewSEp(pSEp);
+ _fFakeInit = TRUE;
+ }
+ }
+ }
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::CreateFakeSEp _pSEp=%x done\n", _pSEp));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CEndPoint::SetNewSEp
+//
+// Synopsis:
+//
+// Arguments: [pSEp] --
+//
+// Returns:
+//
+// History: 3-24-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+SCODE CEndPoint::SetNewSEp(SEndPoint *pSEp)
+{
+ Win4Assert(pSEp);
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::SetNewSEp _pSEp=%x pSEp=%x\n", _pSEp, pSEp));
+ SCODE sc = E_OUTOFMEMORY;
+
+ if (pSEp)
+ {
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::SetNewSEp pSEp->awsEndPoint=%ws\n", pSEp->awszEndPoint));
+ // if the old _pSEp was a copy, free it
+ PrivMemFree(_pSEp);
+ // point at the new one
+ _pSEp = pSEp;
+
+ sc = S_OK;
+ }
+
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::SetNewSEp done rc=%x\n", sc));
+ return sc;
+}
+
+#endif // _CHICAGO_
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::Replace, public
+//
+// Synopsis: replaces the SEndPoint with a new one.
+// called from RpcService::RegisterProtseq after getting
+// a new SEp from the remote machine while marshalling a
+// proxy.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+SCODE CEndPoint::Replace(SEndPoint *pSEp)
+{
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::Replace _pSEp=%x pSEp=%x\n", _pSEp, pSEp));
+ Win4Assert(pSEp);
+
+ // allocate a new pSEp
+ SEndPoint *pSEpTmp = (SEndPoint *) PrivMemAlloc(SEPSIZE(pSEp));
+
+ if (pSEpTmp)
+ {
+ // copy in the data
+ memcpy(pSEpTmp, pSEp, COPYSEPSIZE(pSEp));
+
+ // if the old _pSEp was a copy, free it
+ if (_fCopy)
+ PrivMemFree(_pSEp);
+
+ // point at the new one
+ _pSEp = pSEpTmp;
+ _fCopy = TRUE;
+
+ // we now need to reselect our favourite string binding, since
+ // _pwszPrefStringBinding points into the array in pSEp.
+
+ SelectStringBinding();
+ return (_pwszPrefStringBinding) ? S_OK : E_OUTOFMEMORY;
+ }
+ else
+ {
+ return E_OUTOFMEMORY;
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::IsEqual, public
+//
+// Synopsis: compares two SEndPoint structures and returns TRUE if
+// they are equal.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Note: just compare the first string in each structure. if
+// they are equal, then they refer to the same process.
+//
+//--------------------------------------------------------------------
+BOOL CEndPoint::IsEqual(SEndPoint *pSEp)
+{
+ if (pSEp == _pSEp)
+ return TRUE; // ptrs are same, -> equal
+
+ if (!pSEp || !_pSEp)
+ return FALSE; // only one of them is NULL, -> not equal
+
+ return !(lstrcmpW(pSEp->awszEndPoint, _pSEp->awszEndPoint));
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::CopySEp, public
+//
+// Synopsis: returns a pointer to a new copy of the SEndPoint structure.
+// or NULL if out of memory
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+SEndPoint *CEndPoint::CopySEp(void)
+{
+ Win4Assert(_pSEp && "Illformed CEndPoint object");
+ SEndPoint *pSEp = (SEndPoint *) PrivMemAlloc(GetSEpSize());
+ if (pSEp)
+ {
+ memcpy(pSEp, _pSEp, COPYSEPSIZE(_pSEp));
+ }
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::CopySEP pSEp=%x %ws\n", pSEp, pSEp));
+ return pSEp;
+}
+
+
+#if DBG==1
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::DisplayAllStringBindings, public
+//
+// Synopsis: prints the stringbindings to the debugger
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+void CEndPoint::DisplayAllStringBindings(void)
+{
+ if (_pSEp)
+ {
+ LPWSTR pwszNext = _pSEp->awszEndPoint;
+ LPWSTR pwszEnd = pwszNext + _pSEp->ulStrLen;
+
+ while (pwszNext < pwszEnd)
+ {
+ CairoleDebugOut((DEB_ENDPNT, "pSEp=%x %ws\n", pwszNext, pwszNext));
+ pwszNext += lstrlenW(pwszNext) + 1;
+ }
+ }
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: GoodSEp, public
+//
+// Synopsis: validates that the given SEP is OK.
+//
+// History: 23-Nov-93 AlexMit Created
+//
+//--------------------------------------------------------------------
+BOOL GoodSEp(SEndPoint *pSEp)
+{
+ Win4Assert(pSEp);
+
+ ULONG ulLen = pSEp->ulStrLen;
+ ULONG i = 0;
+
+ while (i < ulLen && ((pSEp->awszEndPoint[i] & 0xff) != 0xbd) &&
+ ((pSEp->awszEndPoint[i] & 0xff00) != 0xbd00))
+ i++;
+ return i == ulLen;
+}
+
+#endif // DBG
diff --git a/private/ole32/com/remote/endpnt.hxx b/private/ole32/com/remote/endpnt.hxx
new file mode 100644
index 000000000..904791ca5
--- /dev/null
+++ b/private/ole32/com/remote/endpnt.hxx
@@ -0,0 +1,340 @@
+//+-------------------------------------------------------------------
+//
+// File: endpnt.hxx
+//
+// Contents: class for managing endpoint structures. both the local
+// and remote service object instances use this class.
+//
+// local service object uses RegisterAllProtseqs to register
+// all available protocol sequences with Rpc, and to accquire
+// the list of full string bingings.
+//
+// the remote service object uses it to select, from amongst
+// the many string bindings, the most preffered to bind to.
+//
+// Structs: SEndPoint
+//
+// Classes: CEndPoint
+//
+// Functions: None
+//
+// History: 23-Nov-92 Rickhi Created
+// 31-Dec-93 ErikGav Chicago port
+// 03-Mar-95 JohannP Delaying rpc initialize
+//
+//--------------------------------------------------------------------
+
+#ifndef __ENDPOINT__
+#define __ENDPOINT__
+
+#include <olesem.hxx>
+#include <iface.h>
+
+
+// macro to compute the size of an endpoint structure. we align the size
+// on an 8-byte boundary in order to facilitate aligment in the buffer
+// when the channel marshals two of them (ie the middle-man case). otherwise
+// the channel unmarshaller does not get the structure aligned correctly.
+
+#define NEWSEPSIZE(ulStrLen) \
+ ((sizeof(ULONG) + sizeof(ULONG) + (ulStrLen) * sizeof(WCHAR) + 7) & 0xfffffff8)
+
+#define SEPSIZE(pSEp) NEWSEPSIZE(pSEp->ulStrLen)
+
+#define COPYSEPSIZE(pSEp) \
+ (sizeof(ULONG) + sizeof(ULONG) + (pSEp)->ulStrLen * sizeof(WCHAR))
+#ifdef _CHICAGO_
+#define MAX_BINDINGS 1 // max string bindings we can handle
+#else
+#define MAX_BINDINGS 15 // max string bindings we can handle
+#endif
+#define MAX_PROTSEQ_STRLEN 20 // max protseqs string length
+#define MAX_NETWORKADDR_STRLEN 40 // max network addr string length
+
+
+#if DBG==1
+// function prototype
+BOOL GoodSEp( SEndPoint *sep );
+#endif
+
+// enumeration for the network address type.
+
+typedef enum tagEnumNA
+{
+ NA_SAME_MACHINE = 1, // NetworkAddr is this machine
+ NA_DIFF_MACHINE = 2, // NetworkAddr is different machine
+ NA_DONT_KNOW = 3, // NetworkAddr is unknown
+} EnumNA;
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CEndPoint (CEp)
+//
+// Purpose: Rpc endpoint array class. This makes it easier to deal with
+// the SEndPoint structure, and isolates changes to it.
+//
+// Interface:
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------------
+class CEndPoint : public CPrivAlloc
+{
+public:
+ CEndPoint(SEndPoint *pSEp, HRESULT &hr, BOOL fCopy = FALSE);
+ ~CEndPoint(void);
+
+ SCODE Replace(SEndPoint *pSEp);
+ BOOL IsEqual(SEndPoint *pSEp);
+ SEndPoint *GetSEp(void);
+ SEndPoint *CopySEp(void);
+ ULONG GetSEpSize(void);
+ ULONG GetStrLen(void);
+ WCHAR *GetStrings(void);
+
+ HRESULT RegisterDefaultProtseq(void);
+#ifdef _CHICAGO_
+ HRESULT RemoveDefaultProtseq(void);
+ SCODE CreateFakeSEp(void);
+ SCODE SetNewSEp(SEndPoint *pSEp);
+#endif // _CHICAGO_
+
+ HRESULT RegisterProtseq(WCHAR *pwszProtseq);
+ LPWSTR GetStringBinding(void);
+ BOOL GetActiveProtseq(LPWSTR *pwszProtseq);
+ void SetActiveProtseq(void);
+ BOOL DiffMachine(void);
+
+private:
+ void SelectStringBinding(void);
+ HRESULT UpdateSEP( LPWSTR pwszEndPoint );
+#if DBG==1
+ void DisplayAllStringBindings(void);
+#endif
+
+ SEndPoint *_pSEp; // endpoint structure
+ LPWSTR _pwszPrefStringBinding; // preferred local string
+ LPWSTR _pwszPrefProtseq; // preferred local string
+ BOOL _fCopy; // copy or original?
+ BOOL _fRegActiveProtseq; // registered active protseq?
+ EnumNA _eNetworkAddr; // tells if same machine, diff
+ // machine, or dont know yet
+ BOOL _fFakeInit; // fake initialized
+
+
+ static ULONG s_ulLocalBindingCount;
+ static WCHAR s_wszLocalProtseq[MAX_BINDINGS][MAX_PROTSEQ_STRLEN];
+ static WCHAR s_wszLocalNetworkAddr[MAX_BINDINGS][MAX_NETWORKADDR_STRLEN];
+
+};
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::GetSEp, public
+//
+// Synopsis: returns a pointer to the SEndPoint structure.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline SEndPoint *CEndPoint::GetSEp(void)
+{
+ return _pSEp;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::GetStrings, public
+//
+// Synopsis: returns a pointer to the strings in the SEndPoint array.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline WCHAR *CEndPoint::GetStrings(void)
+{
+ Win4Assert(_pSEp && "Illformed CEndPoint object");
+ return &(_pSEp->awszEndPoint[0]);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::GetSEpSize, public
+//
+// Synopsis: returns the size of the EndPoint structure stored in
+// this endpoint object. This is used to calculate the
+// size of buffer needed when marshalling an interface.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline ULONG CEndPoint::GetSEpSize(void)
+{
+ Win4Assert(_pSEp && "Illformed CEndPoint object");
+ return SEPSIZE(_pSEp);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::GetStrLen, public
+//
+// Synopsis: returns the size of the EndPoint strings stored in
+// this endpoint object. This is used to calculate the
+// end of the data.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline ULONG CEndPoint::GetStrLen(void)
+{
+ Win4Assert(_pSEp && "Illformed CEndPoint object");
+ return _pSEp->ulStrLen;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::RegisterDefaultProtseq
+//
+// Purpose: register default protocols with Rpc. For now this is
+// just lrpc.
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline HRESULT CEndPoint::RegisterDefaultProtseq(void)
+{
+ // RPC does not provide a way to unload a protocol once registered. If
+ // the same protseq is registered twice with RPC, you get two binding
+ // handles and two string bindings.
+ //
+ // It is often the case that ole32.dll gets loaded/unloaded dynamically
+ // (especially in the VDM) while rpcrt4 stays loaded, so we cant just
+ // rely on internal state in ole32 to detect if the protocols we need
+ // have already been registered, we need to ask RPC.
+ //
+ // First call UpdateSEP to find out if any protocols have already been
+ // registered and to get their string bindings. RegisterProtseq will
+ // then detect any duplicates and avoid registering the same protocol
+ // again.
+
+#ifndef _CHICAGO_
+ UpdateSEP( NULL );
+#endif
+ return RegisterProtseq(LOCAL_PROTSEQ);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::GetStringBinding
+//
+// Purpose: selects, from the array of string bindings, the most
+// preferred choice.
+//
+// Algorithm:
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+inline LPWSTR CEndPoint::GetStringBinding(void)
+{
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::GetStringBinding\n"));
+ if (!_pwszPrefStringBinding)
+ {
+ SelectStringBinding();
+ }
+
+ Win4Assert(_pwszPrefStringBinding);
+ CairoleDebugOut((DEB_ENDPNT, "CEndPoint::GetStringBinding %ws\n", _pwszPrefStringBinding));
+ return _pwszPrefStringBinding;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::GetActiveProtseq
+//
+// Purpose: selects, from the array of string bindings, the most
+// preferred choice, and returns the protseq of that choice.
+//
+// Algorithm:
+//
+// History: 23-Nov-92 Rickhi Created
+//
+// Notes: This is used by the marshalling code to ensure that when
+// we marshal an interface to a remote server for the first
+// time, we have also registered ourselves with the right
+// protocol to talk to that server.
+//
+//--------------------------------------------------------------------
+inline BOOL CEndPoint::GetActiveProtseq(LPWSTR *ppwszProtseq)
+{
+ if (ppwszProtseq)
+ {
+ if (!_pwszPrefProtseq)
+ {
+ SelectStringBinding();
+ }
+
+ Win4Assert(_pwszPrefProtseq);
+ *ppwszProtseq = _pwszPrefProtseq;
+ }
+
+ return _fRegActiveProtseq;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::SetActiveProtseq
+//
+// Purpose:
+//
+// Algorithm:
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline void CEndPoint::SetActiveProtseq(void)
+{
+ _fRegActiveProtseq = TRUE;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CEndPoint::DiffMachine
+//
+// Purpose: Determine if this endpoint is on another machine
+//
+// Algorithm:
+//
+// Notes: The caller is responsible for thread safety.
+//
+// History: 23-Nov-92 Rickhi Created
+// 24-Nov-93 AlexMit Compute flag on first call
+//
+//--------------------------------------------------------------------
+inline BOOL CEndPoint::DiffMachine(void)
+{
+ if (_eNetworkAddr == NA_DONT_KNOW)
+ {
+ SelectStringBinding();
+ }
+
+ Win4Assert(_pwszPrefStringBinding);
+ return (_eNetworkAddr == NA_DIFF_MACHINE);
+}
+
+
+#endif // __ENDPOINT__
+
+
diff --git a/private/ole32/com/remote/filelist.mk b/private/ole32/com/remote/filelist.mk
new file mode 100644
index 000000000..c69313e63
--- /dev/null
+++ b/private/ole32/com/remote/filelist.mk
@@ -0,0 +1,58 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = remote.lib
+
+RELEASE =
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES = \
+ .\channelb.cxx \
+ .\chancont.cxx \
+ .\callcont.cxx \
+ .\callmain.cxx \
+ .\imchnl.cxx \
+ .\sichnl.cxx \
+ .\service.cxx \
+ .\endpnt.cxx \
+ .\remhdlr.cxx \
+ .\remapi.cxx \
+ .\coapi.cxx \
+ .\dd.cxx \
+ .\stdid.cxx \
+ .\idtable.cxx
+
+CFILES = .\orpc_dbg.c
+
+#
+# Libraries and other object files to link.
+#
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PXXFILE = headers.cxx
+PFILE =
+
+CINC = $(CINC) -I..\inc -I..\idl -I..\class -I..\objact $(TRACELOG)
+
+MTHREAD = 1
+
+MULTIDEPEND = MERGED
diff --git a/private/ole32/com/remote/idtable.cxx b/private/ole32/com/remote/idtable.cxx
new file mode 100644
index 000000000..d27bf998f
--- /dev/null
+++ b/private/ole32/com/remote/idtable.cxx
@@ -0,0 +1,653 @@
+//+-------------------------------------------------------------------
+//
+// File: idtable.cxx
+//
+// Contents: identity table
+//
+// Functions:
+//
+// History: 1-Dec-93 CraigWi Created
+//
+//--------------------------------------------------------------------
+
+// CODEWORK: lookup from party apartment should not get individual apartments;
+// but lookup from individual apartments should get party. Currently
+// we only support individual apartments or a single party apartment, not both.
+
+#include <ole2int.h>
+
+#include <idtable.hxx>
+
+CIDArray sg_idtable;
+
+COleStaticMutexSem sg_mxsTable; // global mutext semaphore for id table
+
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: LookupIDFromUnk, private
+//
+// Synopsis: Looks up and may create the identity object for the given
+// object. If the identity object is created, it is not
+// aggregated to the given object.
+//
+// Identity lookup is based on pUnkControl.
+//
+// Effects: Due to multiple threads, it is possible for two identity
+// objects to temporaily exist for the given object. Given that
+// we don't aggregate the identity object in this routine, we are
+// able to use any other identity object created in another
+// thread. See CreateStdIdentity for more information.
+//
+// Arguments: [pUnk] -- the object; not necessarily the controlling unknown
+// [fCreate] -- if the identity does not exist, create one.
+// [ppStgID] -- when S_OK is returned, this is the identity
+// object. This pointer doesn't necessarily hold
+// the object alive. If the identity object was
+// aggregated to the object, it will; if not, it will
+// not. Only marshaling or lock connection will
+// ensure the object stays alive.
+//
+// Returns: S_OK - identity now exists (whether created here or not)
+//
+// CO_E_OBJNOTREG - no identity and !fCreate
+//
+// BUGBUG - the identity GUID could not be created
+//
+// E_OUTOFMEMORY -
+//
+// E_UNEXPECTED - at least: no controlling unknown
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+INTERNAL LookupIDFromUnk(IUnknown *pUnk, BOOL fCreate, IStdIdentity **ppStdID)
+{
+ // QI for IStdID; if ok, return that
+ if (pUnk->QueryInterface(IID_IStdIdentity, (void **)ppStdID) == NOERROR)
+ return NOERROR;
+
+#if DBG == 1
+
+ if (*ppStdID != NULL)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "LookupIDFromUnk QI returned error but didn't null output\n"));
+ }
+
+#endif // DBG == 1
+
+ // NOTE: other thread may create id on object before we check again
+
+ IUnknown *pUnkControl;
+ // QI for controlling unk; should succeed
+ if (pUnk->QueryInterface(IID_IUnknown, (void **)&pUnkControl) != NOERROR)
+ return E_UNEXPECTED;
+
+ IStdIdentity *pStdID = NULL;
+ sg_mxsTable.Request();
+ // scan for value in map; may find one attached to object created by now
+ int iID;
+
+ if (FreeThreading)
+ iID = sg_idtable.IndexOf((void *)&pUnkControl,
+ sizeof(pUnkControl), offsetof(IDENTRY, m_pUnkControl));
+ else
+ {
+ IDENTRY identry;
+
+ identry.m_tid = GetCurrentThreadId();
+ identry.m_pUnkControl = pUnkControl;
+ iID = sg_idtable.IndexOf((void *)&identry.m_tid,
+ sizeof(identry.m_tid) + sizeof(identry.m_pUnkControl),
+ offsetof(IDENTRY, m_tid));
+ }
+
+ // if found, addref pStdID which holds the identity alive
+ if (iID != -1)
+ {
+ pStdID = sg_idtable[iID].m_pStdID;
+ pStdID->AddRef();
+
+#if DBG == 1
+ // verify correctness of entry
+ OID oidT;
+
+ Assert(pUnkControl == sg_idtable[iID].m_pUnkControl);
+ pStdID->GetObjectID(&oidT);
+ Assert(IsEqualGUID(oidT, sg_idtable[iID].m_oid));
+
+ if (FreeThreading)
+ Assert(sg_idtable[iID].m_tid == NULL);
+ else
+ Assert(sg_idtable[iID].m_tid == GetCurrentThreadId());
+#endif
+ }
+ sg_mxsTable.Release();
+
+ // We don't hold the mutex since CreateStdIdentity can call the server
+ // object, which we must assume can be expensive. CreateStdIdentity
+ // object calls SetObjectID() which gets the mutex again.
+
+ // CODEWORK: however, we must hold the mutex long enough so that two
+ // threads in the party apartment don't try to create the same id twice.
+
+ HRESULT hr;
+
+ // pStdID != NULL if found.
+ *ppStdID = pStdID;
+ if (pStdID != NULL)
+ hr = NOERROR;
+
+ // one didn't exist (when we checked a little bit ago) and we can't create;
+ // *ppStdID already == NULL.
+ else if (!fCreate)
+ hr = CO_E_OBJNOTREG;
+
+ // create identity; may return success with already created id; will
+ // never fail if id created by the time we register the newly created one
+ else
+ hr = CreateStdIdentity(NULL, pUnkControl, PSTDMARSHAL,
+ IID_IStdIdentity, (void **)ppStdID);
+
+ // we need to do this release via IWR if supported so it won't shutdown
+ // the server
+ if (hr != NOERROR)
+ {
+ // no identity to help in error case; for now, just let it shutdown
+ // this seems reasonsable since there may be no other time that it
+ // would shutdown.
+ pUnkControl->Release();
+ }
+ else
+ {
+ (*ppStdID)->ReleaseKeepAlive(pUnkControl, 0);
+ }
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: LookupIDFromID, private
+//
+// Synopsis: Lookup an identity object based on an OID; does not create.
+//
+// Arguments: [oid] -- The identity
+// [ppStdID] -- The cooresponding identity object if successful
+//
+// Returns: S_OK - have the identity object
+//
+// CO_E_OBJNOTREG - not present (when we looked)
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+INTERNAL LookupIDFromID(REFOID oid, BOOL fAddRef, IStdIdentity **ppStdID)
+{
+ *ppStdID = NULL;
+ sg_mxsTable.Request();
+ // scan for value in map; may find one attached to object created by now
+ int iID;
+ if (FreeThreading)
+ iID = sg_idtable.IndexOf((void *)&oid, sizeof(oid), offsetof(IDENTRY, m_oid));
+ else
+ {
+ IDENTRY identry;
+
+ identry.m_oid = oid;
+ identry.m_tid = GetCurrentThreadId();
+ iID = sg_idtable.IndexOf((void *)&identry.m_oid,
+ sizeof(identry.m_oid) + sizeof(identry.m_tid),
+ offsetof(IDENTRY, m_oid));
+ }
+
+
+ // if found, addref pStdID which holds the identity alive
+ if (iID != -1)
+ {
+ *ppStdID = sg_idtable[iID].m_pStdID;
+
+ if (fAddRef)
+ // I sure hope the apps doesn't try anything fancy in AddRef
+ // that would cause a deadlock here! (That is, in the aggregated
+ // case we will run app code).
+ (*ppStdID)->AddRef();
+
+#if DBG == 1
+ // verify correctness of entry
+ Assert(IsEqualGUID(oid, sg_idtable[iID].m_oid));
+
+ OID oidT;
+ (*ppStdID)->GetObjectID(&oidT);
+ Assert(IsEqualGUID(oid, oidT));
+
+ if (FreeThreading)
+ Assert(sg_idtable[iID].m_tid == NULL);
+ else
+ Assert(sg_idtable[iID].m_tid == GetCurrentThreadId());
+
+#ifdef BUGBUG
+can't do this yet since this occurs in dtors with unstable ref count;
+e.g., CAdvBnd::~CAdvBnd does prot->Revoke which does CoUnmarshalInterface.
+in 16bit OLE2 we required such dtors to artifically bump the ref count.
+ IUnknown *pUnkControl;
+ Verify(sg_idtable[iID].m_pUnkControl->QueryInterface(IID_IUnknown,
+ (void **)&pUnkControl) == NOERROR);
+
+ Assert(pUnkControl == sg_idtable[iID].m_pUnkControl);
+ pUnkControl->Release();
+#endif // BUGBUG
+#endif
+ }
+ sg_mxsTable.Release();
+
+ return *ppStdID == NULL ? CO_E_OBJNOTREG : NOERROR;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: SetObjectID, private
+//
+// Synopsis: Called by the object id creation and unmarshal functions
+// to establish the identity for an object (handler or server).
+// Can fail if we discover an existing identity.
+//
+// Identity lookup is based on pUnkControl.
+//
+// Arguments: [oid] -- The id for the object
+// [pUnkControl] -- The controlling uknown of the object being
+// identitified.
+// [pStdID] -- The identity object itself.
+// [ppStdIDExisting] -- If another identity object go created
+// since we (this thread) checked last, this is
+// where that object is returned. May be NULL
+// indicating that the caller doesn't care about
+// an existing id.
+//
+// Returns: S_OK - identity was set successfully
+//
+// CO_E_OBJISREG - object was already registered (as determined
+// by pUnkControl); *ppStdIDExisting set (if requested).
+//
+// E_OUTOFMEMORY -
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+INTERNAL SetObjectID(REFOID oid, IUnknown *pUnkControl, IStdIdentity *pStdID,
+ IStdIdentity **ppStdIDExisting)
+{
+ HRESULT hr = NOERROR;
+
+ Assert(!IsEqualGUID(oid, OID_NULL));
+
+ sg_mxsTable.Request();
+ // scan for value in map; may find one attached to object created by now
+ int iID;
+
+ if (FreeThreading)
+ iID = sg_idtable.IndexOf((void *)&pUnkControl,
+ sizeof(pUnkControl), offsetof(IDENTRY, m_pUnkControl));
+ else
+ {
+ IDENTRY identry;
+
+ identry.m_tid = GetCurrentThreadId();
+ identry.m_pUnkControl = pUnkControl;
+ iID = sg_idtable.IndexOf((void *)&identry.m_tid,
+ sizeof(identry.m_tid) + sizeof(identry.m_pUnkControl),
+ offsetof(IDENTRY, m_tid));
+ }
+
+ // if found, another thread created identity for same object;
+ // addref pStdID and return it if requested
+ if (iID != -1)
+ {
+ if (ppStdIDExisting)
+ {
+ *ppStdIDExisting = sg_idtable[iID].m_pStdID;
+ (*ppStdIDExisting)->AddRef();
+ }
+
+ hr = CO_E_OBJISREG;
+
+#if DBG == 1
+ // verify correctness of entry
+ OID oidT;
+
+ Assert(pUnkControl == sg_idtable[iID].m_pUnkControl);
+ sg_idtable[iID].m_pStdID->GetObjectID(&oidT);
+ Assert(IsEqualGUID(oidT, sg_idtable[iID].m_oid));
+
+ if (FreeThreading)
+ Assert(sg_idtable[iID].m_tid == NULL);
+ else
+ Assert(sg_idtable[iID].m_tid == GetCurrentThreadId());
+#endif
+ }
+ else
+ {
+ if (ppStdIDExisting)
+ *ppStdIDExisting = NULL;
+
+ // no id yet; add at end; no addrefs
+ IDENTRY identry;
+ identry.m_oid = oid;
+ identry.m_tid = FreeThreading ? NULL : GetCurrentThreadId();
+ identry.m_pUnkControl = pUnkControl;
+ identry.m_pStdID = pStdID;
+
+ if (sg_idtable.Add(identry) == -1)
+ hr = E_OUTOFMEMORY;
+ }
+ sg_mxsTable.Release();
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: ClearObjectUnk, private
+//
+// Synopsis: Called during the disconnect of the id only. Clears
+// the pUnkControl entry for the identity.
+//
+// Identity lookup is based on oid.
+//
+// Arguments: [oid] -- The identity; used for asserts only.
+// [pUnkControl] -- The object for which the identity is being
+// revoked; used for asserts only.
+// [pStdID] -- The identity object; used for asserts only.
+//
+// Returns: S_OK - removed successfully
+//
+// CO_E_OBJNOTREG - not present (often ignored).
+//
+// History: 02-May-94 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+INTERNAL ClearObjectUnk(REFOID oid, IUnknown *pUnkControl, IStdIdentity *pStdID)
+{
+ HRESULT hr = NOERROR;
+
+ sg_mxsTable.Request();
+ // scan for value in map; may find one attached to object created by now
+ int iID;
+
+ if (FreeThreading)
+ iID = sg_idtable.IndexOf((void *)&oid, sizeof(oid), offsetof(IDENTRY, m_oid));
+ else
+ {
+ IDENTRY identry;
+
+ identry.m_oid = oid;
+ identry.m_tid = GetCurrentThreadId();
+ iID = sg_idtable.IndexOf((void *)&identry.m_oid,
+ sizeof(identry.m_oid) + sizeof(identry.m_tid),
+ offsetof(IDENTRY, m_oid));
+ }
+
+ // if found, clear the pUnkControl field
+ if (iID != -1)
+ {
+#if DBG == 1
+ // verify correctness of entry
+ OID oidT;
+
+ Assert(pUnkControl == sg_idtable[iID].m_pUnkControl);
+ pStdID->GetObjectID(&oidT);
+ Assert(IsEqualGUID(oidT, sg_idtable[iID].m_oid));
+ Assert(pStdID == sg_idtable[iID].m_pStdID);
+ if (FreeThreading)
+ Assert(sg_idtable[iID].m_tid == NULL);
+ else
+ Assert(sg_idtable[iID].m_tid == GetCurrentThreadId());
+#endif
+
+ sg_idtable[iID].m_pUnkControl = NULL;
+ }
+ else
+ hr = CO_E_OBJNOTREG;
+ sg_mxsTable.Release();
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: ClearObjectID, private
+//
+// Synopsis: Called during the revokation of the id only. Clears
+// the identity entry in the table.
+//
+// Identity lookup is based on oid.
+//
+// Arguments: [oid] -- The identity; used for asserts only.
+// [pUnkControl] -- The object for which the identity is being
+// revoked; used for asserts only.
+// [pStdID] -- The identity object; used for asserts only.
+//
+// Returns: S_OK - removed successfully
+//
+// CO_E_OBJNOTREG - not present (often ignored).
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+INTERNAL ClearObjectID(REFOID oid, IUnknown *pUnkControl, IStdIdentity *pStdID)
+{
+ HRESULT hr = NOERROR;
+
+ sg_mxsTable.Request();
+ // scan for value in map; may find one attached to object created by now
+ int iID;
+
+ if (FreeThreading)
+ iID = sg_idtable.IndexOf((void *)&oid, sizeof(oid), offsetof(IDENTRY, m_oid));
+ else
+ {
+ IDENTRY identry;
+
+ identry.m_oid = oid;
+ identry.m_tid = GetCurrentThreadId();
+ iID = sg_idtable.IndexOf((void *)&identry.m_oid,
+ sizeof(identry.m_oid) + sizeof(identry.m_tid),
+ offsetof(IDENTRY, m_oid));
+ }
+
+ // if found, remove it.
+ if (iID != -1)
+ {
+#if DBG == 1
+ // verify correctness of entry
+ OID oidT;
+
+# ifndef _CAIRO_
+ // BUGBUG [mikese] There is a race during shutdown of a
+ // multithreaded server which renders this assertion invalid.
+ // CraigWi is fixing the race (see CODEWORK in stdid.cxx l 1570)
+ // but in the mean time we disable the assert for Cairo builds.
+ Assert(pUnkControl == sg_idtable[iID].m_pUnkControl);
+# endif
+ pStdID->GetObjectID(&oidT);
+ Assert(IsEqualGUID(oidT, sg_idtable[iID].m_oid));
+ Assert(pStdID == sg_idtable[iID].m_pStdID);
+ if (FreeThreading)
+ Assert(sg_idtable[iID].m_tid == NULL);
+ else
+ Assert(sg_idtable[iID].m_tid == GetCurrentThreadId());
+#endif
+
+ Assert(sg_idtable.GetSize() != 0);
+ int iLast = sg_idtable.GetSize() - 1;
+ if (iID != iLast)
+ {
+ // element removed is not last; copy last element to current
+ sg_idtable[iID] = sg_idtable[iLast];
+ }
+
+ // now setsize to one less to remove the now unused last element
+
+ sg_idtable.SetSize(iLast);
+ }
+ else
+ hr = CO_E_OBJNOTREG;
+ sg_mxsTable.Release();
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: IDTableUninitialize, private
+//
+// Synopsis: Clears the id table memory for the current thread (or all
+// if party model). This involves scanning the table and for
+// entries on the current thread, calling
+// IMarshal::DisconnectObject.
+//
+// The purpose of this routine is to simulate inter-thread rundown
+// as well as clean up memory.
+//
+// History: 23-Dec-93 CraigWi Created.
+// 26-Apr-94 CraigWi Now called per-thread and disconnects
+//
+// Note: This function should only be called when the IDTable
+// really needs to be uninitialized. For the party model, this
+// means that it should only be called when the last thread
+// is exiting.
+//
+// This function must NOT assume that it is being called within
+// a critical section.
+//
+//--------------------------------------------------------------------
+
+INTERNAL_(void) IDTableThreadUninitialize(void)
+{
+ // We should never get here if we are free threading. Any and all
+ // clean up must happen when the last CoUninitialize happens for the
+ // process in free threading.
+ Win4Assert(!FreeThreading
+ && "IDTableThreadUninitialize called and Free Threading");
+
+ DWORD tid = GetCurrentThreadId(); // CODEWORK get apartment for thread
+
+ // CODEWORK: we will hold this for each entry; this needs to be changed
+ // later since we could skip an entry if another thread
+ // deleted an entry before our point in the list.
+ sg_mxsTable.Request();
+
+ for (int i = 0; i < sg_idtable.GetSize(); i++)
+ {
+ if (FreeThreading || sg_idtable[i].m_tid == tid)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "Object at %lx still has connections\n",
+ sg_idtable[i].m_pUnkControl));
+
+
+ // NOTE: for party apartment model, we don't have to check
+ // for valid entry since we only scan it once, at process exit.
+
+ Assert(IsValidInterface(sg_idtable[i].m_pStdID));
+ IStdIdentity *pStdID = sg_idtable[i].m_pStdID;
+ pStdID->AddRef();
+
+ // release semaphore for this period since the disconnect
+ // could take a long time and the revoke id needs access to
+ // the table (even though it won't find anything).
+ sg_mxsTable.Release();
+
+ IMarshal *pMarshal;
+ if (pStdID->QueryInterface(IID_IMarshal, (void **)&pMarshal) == NOERROR)
+ {
+ pMarshal->DisconnectObject(0);
+ pMarshal->Release();
+ }
+
+ pStdID->RevokeObjectID();
+ pStdID->Release();
+
+ // re-request the table since we need to guard the GetSize above
+ sg_mxsTable.Request();
+ }
+ }
+
+ sg_mxsTable.Release();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IDTableProcessUninitialize
+//
+// Synopsis: Process specific IDTable uninitialization
+//
+// Effects: Frees up table memory
+//
+// Requires: All thread specific uninitialization already complete. This
+// function assumes that the caller is holding the
+// g_mxsSingleThreadOle mutex (so that no other thread is trying
+// to use the table while we clean it up).
+//
+// Modifies: sg_idtable
+//
+// History: 29-Jun-94 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) IDTableProcessUninitialize(void)
+{
+ sg_idtable.RemoveAll();
+}
+
+#if DBG == 1
+
+//+-------------------------------------------------------------------
+//
+// Function: Dbg_FindRemoteHdlr
+//
+// Synopsis: finds a remote object handler for the specified object,
+// and returns an instance of IMarshal on it. This is debug
+// code for assert that reference counts are as expected.
+//
+// Exceptions: None
+//
+// History: 23-Nov-93 Rickhi Created
+// 23-Dec-93 CraigWi Changed to identity object
+//
+//--------------------------------------------------------------------
+
+extern "C"
+IMarshal * _stdcall Dbg_FindRemoteHdlr(IUnknown *punkObj)
+{
+ // validate input parms
+ Win4Assert(punkObj);
+
+ IMarshal *pIM = NULL;
+ IStdIdentity *pStdID;
+ if (LookupIDFromUnk(punkObj, FALSE, &pStdID) == NOERROR)
+ {
+ (void)pStdID->QueryInterface(IID_IMarshal, (void **)&pIM);
+ pStdID->Release();
+ }
+ return pIM;
+}
+
+#endif // DBG == 1
diff --git a/private/ole32/com/remote/idtable.hxx b/private/ole32/com/remote/idtable.hxx
new file mode 100644
index 000000000..32c4aedbb
--- /dev/null
+++ b/private/ole32/com/remote/idtable.hxx
@@ -0,0 +1,72 @@
+//+-------------------------------------------------------------------
+//
+// File: idtable.hxx
+//
+// Contents: internal identity table definitions.
+//
+// Description:
+// The table consists, logically, of two different
+// keys which map to the same value. The two
+// keys are the object identity (oid) and the
+// controlling unknown (pUnkControl). The value
+// is the pointer to the identity interface.
+//
+// Additionally, if the apartment model is in use,
+// the thread forms an additional part of both keys.
+//
+// Presently this is implemented as an array of the
+// three values and linear scans are used for lookup.
+// Neither of the pointers are addref'd (as far as the
+// table is concerned). Lookup does addref and return
+// a pointer to the identity object. The pUnkControl
+// is used solely for lookup.
+//
+// Possible changes: use two separate maps, one of
+// which is keyed by the oid and the other keyed
+// by pUnkControl. The value in the first map is
+// the hKey of value in the second map. The id object
+// would hold the hKey of the value in the first map
+// to save on space. Using two maps increases the
+// speed of lookup for large numbers of ids, but
+// increases the cost per id from 40bytes to 48bytes.
+// (40 = 2 GUIDS + 2 far pointers; 48 = 1 GUID +
+// 3 hKeys/ptrs + 16 bytes overhead for two hash
+// buckets)
+//
+// It is also possible to use one map (keyed by
+// the oid) and trim the array by the GUID. The
+// cost per id is 40bytes (1 GUID + 1 hKey + 3 ptr +
+// 8 bytes overhead for one hash bucket).
+//
+//
+// History: 1-Dec-93 CraigWi Created
+//
+//--------------------------------------------------------------------
+
+#ifndef __IDTABLE__
+#define __IDTABLE__
+
+#include <olerem.h>
+
+// entry in id array; the array is packed (no NULL holes)
+// NOTE: when looking up for the apartment model, we pair the two fields
+// m_oid/m_tid and m_tid/m_pUnkControl;
+struct IDENTRY
+{
+ OID m_oid;
+ DWORD m_tid;
+ IUnknown *m_pUnkControl; // not addref'd directly
+ IStdIdentity *m_pStdID; // not addref'd directly
+};
+
+#include <array_id.h>
+
+// other functions declared in olerem.h
+
+INTERNAL SetObjectID(REFOID oid, IUnknown *pUnkControl, IStdIdentity *pStdID,
+ IStdIdentity **ppStdIDExisting);
+INTERNAL ClearObjectID(REFOID oid, IUnknown *pUnkControl, IStdIdentity *pStdID);
+INTERNAL ClearObjectUnk(REFOID oid, IUnknown *pUnkControl, IStdIdentity *pStdID);
+
+
+#endif // __IDTABLE__
diff --git a/private/ole32/com/remote/imchnl.cxx b/private/ole32/com/remote/imchnl.cxx
new file mode 100644
index 000000000..4bab80565
--- /dev/null
+++ b/private/ole32/com/remote/imchnl.cxx
@@ -0,0 +1,990 @@
+//+-------------------------------------------------------------------
+//
+// File: imchnl.cxx
+//
+// Contents: imarshal on channel implementation
+//
+// Classes: CRpcChannelBuffer - channel buffer
+//
+// History: 23-Nov-92 Rickhi Created
+// 31-Dec-93 ErikGav Chicago port
+// 05-Jul-94 BruceMa Check for end of stream
+// 19 Jul 94 CraigWi Added support for ASYNC calls
+//
+//--------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include <channelb.hxx> // CRpcChannelBuffer
+#include <service.hxx> // CRpcService
+
+#include "callmain.hxx" // to determine if async or input sync
+
+// translates MSHLFLAGS to EXTCONN
+static UINT sg_mapMFtoEC[] =
+{
+ EXTCONN_STRONG | EXTCONN_CALLABLE, // MSHLFLAGS_NORMAL
+ EXTCONN_STRONG, // MSHLFLAGS_TABLESTRONG
+ EXTCONN_WEAK, // MSHLFLAGS_TABLEWEAK
+};
+
+
+// CODEWORK: move to common header
+INTERNAL_(void) RewriteHeader(IStream *pStm, void *pv, ULONG cb, ULARGE_INTEGER ulSeekStart);
+
+
+// size of stack channel stack buffer
+#define CHNL_STACKBUFSIZE 512
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::GetUnmarshalClass, public
+//
+// Synopsis: returns the class of the code used to unmarshal this
+// object
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRpcChannelBuffer::GetUnmarshalClass(REFIID riid, void *pv,
+ DWORD dwDestContext, void *pvDestContext,
+ DWORD mshlflags, LPCLSID pClassid)
+{
+ AssertValid(FALSE, TRUE);
+ Win4Assert(state != server_cs); // can't happen
+
+ memcpy (pClassid, &CLSID_RpcChannelBuffer, sizeof(CLSID));
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::GetMarshalSizeMax, public
+//
+// Synopsis: returns the maximum sized buffer needed to marshal this
+// object
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRpcChannelBuffer::GetMarshalSizeMax(REFIID riid, void *pv,
+ DWORD dwDestCtx, void *pvDestCtx,
+ DWORD mshlflags, DWORD *pSize)
+{
+ AssertValid(FALSE, TRUE);
+ Win4Assert(state != server_cs); // can't happen
+
+ // check the destination context first as it may affect the
+ // size of the SEp.
+
+ if (dwDestCtx == MSHCTX_DIFFERENTMACHINE && pvDestCtx)
+ {
+ CheckDestCtx( pvDestCtx );
+ }
+
+ *pSize = sizeof(SChannelDataHdr) + // channel data struct
+ LocalService()->GetSEpSize(); // endpoint string size
+
+ if (state == client_cs)
+ {
+ // we are a proxy for a remote object, so include the info
+ // to tell the unmarshaller how to call us back.
+ // CODEWORK: do we need to specify channel id?
+
+ *pSize += _pService->GetSEpSize(); // endpoint string size
+ }
+
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::MarshalInterface, public
+//
+// Synopsis: marshalls the specified interface into the given stream
+//
+// History: 23-Nov-93 Rickhi Created
+// 16-May-94 CraigWi Removed middle man case
+//
+// Note: The format of the data is {ChannelDataHdr [,Data]} where
+// Data is optional (may be and endpoint or a context handle).
+// When marshalling a proxy, a second {Data} is written into
+// the stream that tells the unmarshaller how to connect back
+// to the marshaller in order it that it is safe to Release
+// his proxy, since the unmarshaller has now got his own
+// connection to the real object.
+//
+// CODEWORK: CRpcChannelBuffer::MarshalInterface complete for context handle
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRpcChannelBuffer::MarshalInterface(IStream *pStm, REFIID riid,
+ void *pv, DWORD dwDestCtx, void *pvDestCtx, DWORD mshlflags)
+{
+ HRESULT sc = S_OK;
+ SChannelDataHdr cdh;
+
+ AssertValid(FALSE, TRUE);
+ Win4Assert(state != server_cs); // can't happen
+
+ // check the destination context
+ if (dwDestCtx == MSHCTX_DIFFERENTMACHINE && pvDestCtx)
+ {
+ CheckDestCtx( pvDestCtx );
+ }
+
+ // if table, must be on server side
+ if (mshlflags != MSHLFLAGS_NORMAL && state != disconnected_cs)
+ return E_INVALIDARG;
+
+ // if server, write LocalService() end point
+ // if client, write _pService end point followed by LocalService() end point
+
+ // store the channel identifier in the data
+ cdh.ulDataSize = sizeof(SChannelDataHdr) /* + end point */;
+ cdh.dwFlags = (mshlflags & CHNLFLAGS_TABLE) | CHNLFLAGS_ENDPNT;
+ cdh.aptServer = server_apt;
+
+ if (state == client_cs)
+ {
+ // we're a proxy for a remote object.
+ cdh.ulDataSize += _pService->GetSEpSize();
+ }
+ else
+ {
+ // we're in the server's process.
+ if (LocalService()->GetSEp() != NULL)
+ {
+ cdh.ulDataSize += LocalService()->GetSEpSize();
+ }
+ else
+ {
+ return E_OUTOFMEMORY;
+ }
+ }
+
+ // write the channel data header into the stream
+ sc = pStm->Write(&cdh, sizeof(cdh), NULL);
+
+ if (SUCCEEDED(sc))
+ {
+ // if marshalling an object in this process, just write the string
+ // bindings of this process.
+
+ // if marshalling an object as a middleman, write the string
+ // bindings of the real server.
+ if (state == client_cs)
+ {
+ Win4Assert(GoodSEp(_pService->GetSEp()));
+ sc = pStm->Write(_pService->GetSEp(),
+ _pService->GetSEpSize(), NULL);
+ }
+ else
+ {
+ Win4Assert(GoodSEp(LocalService()->GetSEp()));
+ sc = pStm->Write(LocalService()->GetSEp(),
+ LocalService()->GetSEpSize(), NULL);
+ }
+ }
+
+ // REF COUNTING:
+ // now that the marshaling has completed, we AddConnection
+ // to hold this stuff alive.
+
+ if (SUCCEEDED(sc))
+ {
+ // marshalled successfully. AddConection. This will
+ // addref the identity (so we stick around) and for
+ // strong connections (NORMAL and TABLE_STRONG), increment
+ // the strong count. For clients, we call the server and to
+ // the AddConnection there.
+
+ // This AddConnection is balanced by a ReleaseConnection in the
+ // following places and for the following reasons:
+ // normal, client or server side marshal:
+ // unmarshal server side: release in disconected_cs channel RMD
+ // unmarshal client side: release via server_cs channel disconnect
+ // (after creation of server_cs channel and setting marshl cnt)
+ // error on server side: release in disconected_cs channel RMD
+ // error on client side: release in client_cs channel RMD
+ //
+ // table, server side marshal:
+ // unmarshal any: none
+ // RMD server side: release in disconnected_cs channel RMD
+ //
+ // table, client side marshal: CODEWORK: does not work, by design.
+ // could be made to work easily since we now contact the server
+ // during marshaling to AddConnection.
+
+ // CODEWORK: when we precompute the channel, we would increment
+ // the marshal count on that channel and thus eliminate
+ // the incmarshalcnt call from the client unmarshal; in that case
+ // this AddConnection would logically be done by that other channel.
+
+ // NOTE: what if object already marshaled to another process
+ // say A. Then table marshal here; unmarshal in process A;
+ // we get an AddConnection for the table marshal,
+ // but no inc marshal cnt on the corresponding channel.
+ // Actually this is ok since the ReleaseConn is in release
+ // marshal data and otherwise the marshal and connetion counts
+ // don't change. If the table unmarshal caused the first
+ // connection, there would be an AddConnection for that
+ // and the marshal counts on both sides would end up 1.
+
+ if (state == client_cs)
+ {
+ // contact server and to the add connection there; may fail;
+ // checks end point and apartment while we are at it.
+ // CODEWORK: when we precompute the channel at marshal time,
+ // we have to replace all of the remhdlr/channel marshaling
+ // with a call to the server, not just this part.
+ OID oid;
+ _pRH->GetObjectID( &oid );
+ sc = _pService->AddMarshalConnection(_ChannelID, server_apt, oid);
+ }
+ else
+ {
+ // server side: just add connection here
+ sc = _pRH->AddConnection(sg_mapMFtoEC[mshlflags], 0);
+ }
+ }
+
+
+ return sc;
+}
+
+
+/*-------------------------------------------------------------------
+
+ Member: CRpcChannelBuffer::UnmarshalInterface, public
+
+ Synopsis: unmarshalls the interface from the given stream
+
+ History: 23-Nov-93 Rickhi Created
+ 27-Nov-94 AlexMit Move context handle to service and
+ add sync code.
+ 16-May-94 CraigWi Removed middle man case
+
+ Note: riid must be IID_NULL and ppv must be NULL for now. The
+ code doesn't currently use them (and the RH was passing the wrong thing
+ anyway).
+
+ In the multithreaded mode multiple threads entiring this routine
+ will be blocked in the lock loop at the top. The first thread will get
+ though. After it succeeds or fails it will wake up the others. If it
+ succeeded they will all be released. If it failed, one will try again
+ and the others will block.
+
+ In the single threaded mode only one thread at a time may use this
+ channel. However, this routine is reentrant at the point where it gets
+ the channel id. Thus at that point the routine checks to see if the
+ unmarshal was completed by a nested call.
+
+--------------------------------------------------------------------*/
+
+STDMETHODIMP CRpcChannelBuffer::UnmarshalInterface(
+ IStream *pStm,
+ REFIID riid,
+ void **ppv)
+{
+ AssertValid(FALSE, TRUE);
+ Win4Assert(state != server_cs); // can't happen
+
+ SChannelDataHdr cdh;
+ OID object_id;
+ BOOL success;
+ BYTE abData[CHNL_STACKBUFSIZE];
+ BYTE *pbData = abData;
+ HRESULT sc = S_OK;
+ BOOL fDidConnect = FALSE;
+ BOOL fMshlTransfered = FALSE;
+ CRpcService *service_copy = NULL;
+ CChannelControl *controller_copy = NULL;
+
+ Win4Assert(IsEqualGUID(riid, IID_NULL) && ppv == NULL);
+
+ // save for possible re-write of header
+ ULARGE_INTEGER ulSeekStart;
+ LARGE_INTEGER libMove;
+ LISet32(libMove, 0x00000000);
+ if (FAILED(sc = pStm->Seek(libMove, STREAM_SEEK_CUR, &ulSeekStart)))
+ return sc;
+
+ // read the channel header from the stream
+ // to extract the variable data size.
+
+ if (FAILED(sc = StRead(pStm, &cdh, sizeof(cdh))))
+ return sc;
+
+ // Determine what's going on. If some other thread is unmarshalling for
+ // the first time on the client side, we have to loop here because they
+ // may fail.
+ ChannelLock.Request();
+ while (TRUE)
+ {
+
+ // If there have been no successful unmarshals, change the state and
+ // try now
+ if (state == client_cs && _pService == NULL)
+ {
+ state = connecting_cs;
+ break;
+ }
+
+ // If some thread is trying to unmarshal for the first time,
+ // wait here and give it a chance.
+ else if (state == connecting_cs && FreeThreading)
+ {
+ if (connect_sync == NULL)
+ {
+#ifdef _CHICAGO_ //Chicago ANSI optimization
+ connect_sync = CreateEventA( NULL, TRUE, FALSE, NULL );
+#else // _CHICAGO_
+ connect_sync = CreateEvent( NULL, TRUE, FALSE, NULL );
+#endif //_CHICAGO_
+
+ if (connect_sync == NULL)
+ {
+ ChannelLock.Release();
+ return E_OUTOFMEMORY;
+ }
+ }
+
+ // Ignore errors waiting since the object may be removed before
+ // wait is called.
+ ChannelLock.Release();
+ WaitForSingleObject( connect_sync, INFINITE );
+ ChannelLock.Request();
+ }
+
+ // No need to take a lock.
+ else
+ break;
+ }
+ ChannelLock.Release();
+
+ // If this is the first time anything has been unmarshalled on this channel,
+ // read the data to find the service object. Get the context handle and
+ // channel id.
+ if (state == connecting_cs)
+ {
+ // Read the string bindings from the buffer.
+ server_apt = cdh.aptServer;
+ if (cdh.ulDataSize > CHNL_STACKBUFSIZE)
+ {
+ pbData = (BYTE *) PrivMemAlloc(cdh.ulDataSize-sizeof(SChannelDataHdr));
+ if (pbData == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ goto connect_failed;
+ }
+ }
+ sc = StRead(pStm, pbData, cdh.ulDataSize-sizeof(SChannelDataHdr));
+ if (FAILED(sc))
+ goto connect_failed;
+
+ // Put switch on data type here.
+ Win4Assert((cdh.dwFlags & CHNLFLAGS_ENDPNT) != 0 &&
+ "Invalid Channel DataTypeid");
+
+ // Find or create a service object.
+ service_copy = _pService = FindSRVFromEP((SEndPoint *)pbData, TRUE);
+ if (_pService == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ goto connect_failed;
+ }
+
+ // Get the channel controller. This test will always fail on Chicago
+ // because no channel is created for objects on the same thread.
+ if (_pService == LocalService())
+ {
+ local = TRUE;
+ controller_copy = controller = CChannelControl::Lookup( cdh.aptServer );
+ if (controller == NULL)
+ {
+ sc = RPC_E_SERVER_DIED;
+ goto connect_failed;
+ }
+ }
+ else
+ local = FALSE;
+
+ // Get the context handle. This is reentrant on Chicago. A reentrant
+ // call may finish connecting and then disconnect this channel.
+ sc = _pService->CheckContextHdl( cdh.aptServer );
+ if (FAILED(sc) || _pService == NULL)
+ goto connect_failed;
+
+ // Get the channel id.
+ // if we're on the client side, make sure that we have connected
+ // to the server and have a context handle for this object. this
+ // is important to do now incase we unmarshalled from a table, so
+ // that our connection holds the server alive.
+ _pRH->GetObjectID( &object_id );
+ sc = _pService->GetChannelId( object_id, cdh.dwFlags, cdh.aptServer,
+ &_ChannelID );
+ if (FAILED(sc))
+ goto connect_failed;
+
+ Win4Assert(_ChannelID != BAD_CHANNEL_ID);
+
+ // Only update the reference counts if it hasn't already been done.
+ if (state == connecting_cs)
+ {
+ Win4Assert(ref_count == 1 && "Shouldn't have proxies connected yet");
+ Win4Assert(_ulMarshalCnt == 0 && "Shouldn't have marshal cnt yet");
+
+ fDidConnect = TRUE;
+ if ((cdh.dwFlags & CHNLFLAGS_TABLE) == MSHLFLAGS_NORMAL)
+ // GetChannelId does this; table marshal adds a new connection
+ // and transfers it; the connection due to the original marshal
+ // is left in tact.
+ fMshlTransfered = TRUE;
+
+ IncMarshalCnt();
+
+ // Restore state.
+ ChannelLock.Request();
+ state = client_cs;
+
+ // If FreeThreading free any threads that may be waiting.
+ if (connect_sync != NULL)
+ {
+ success = SetEvent( connect_sync );
+ Win4Assert( success );
+ success = CloseHandle( connect_sync );
+ Win4Assert( success );
+ connect_sync = NULL;
+ }
+ ChannelLock.Release();
+ }
+
+ // If the unmarshalling was completed in a reentrant call, release
+ // the original reference counts on the service and channel controller.
+ else
+ {
+ service_copy->Release();
+ if (controller_copy != NULL)
+ controller_copy->Release();
+ }
+ }
+ else
+ {
+ // Otherwise, skip the rest of the data.
+ LISet32(libMove, cdh.ulDataSize-sizeof(SChannelDataHdr));
+ sc = pStm->Seek(libMove, STREAM_SEEK_CUR, NULL);
+ if (FAILED(sc))
+ goto cleanup_exit;
+ }
+
+ Win4Assert(SUCCEEDED(sc)); // all failure cases jump below
+
+ if (state == client_cs)
+ {
+ // REF COUNTING
+
+ // for first connect of all kinds; set ulMarshalCnt to 1 above;
+ // nothing done here; this is because the acquision of the
+ // channel transfer the marshal connection to the channel.
+ //
+ // for subsequent normal unmarshal (proxy or not), call to server to
+ // transfer marshal count to the server-side channel object.
+ // (this doesn't do AddConnection since that part was done in the
+ // original marshal normal); CODEWORK: later this will only do a local
+ // increment marshal cnt since the precompuation of the channel will
+ // increment the marshal cnt in the server process.
+ //
+ // for table unmarshaling, do nothing since the current proxy
+ // marshal doesn't contact server and table unmarhsl may be done
+ // any number of times without contacting server.
+
+ if (!fDidConnect && ((cdh.dwFlags & CHNLFLAGS_TABLE) == MSHLFLAGS_NORMAL))
+ {
+ HRESULT hr = _pService->TransferMarshalConnection( _ChannelID );
+
+ if (hr == NOERROR)
+ {
+ IncMarshalCnt();
+ fMshlTransfered = TRUE; // just completed this successfully
+ }
+ else
+ {
+ CairoleDebugOut((DEB_WARN,
+ "Could not increment server marshal count. hr:%x\n.", hr));
+ }
+ }
+ }
+
+ AssertValid(FALSE, TRUE);
+
+ goto cleanup_exit;
+
+connect_failed:
+ // Clear out the channel id and service pointer. Set the state back
+ // to client_cs and release any waiting threads.
+ ChannelLock.Request();
+ if (_pService != NULL)
+ {
+ _pService->Release();
+ _pService = NULL;
+ }
+ _ChannelID = BAD_CHANNEL_ID;
+ state = client_cs;
+ if (controller != NULL)
+ {
+ controller->Release();
+ controller = NULL;
+ }
+ if (connect_sync != NULL)
+ {
+ success = SetEvent( connect_sync );
+ Win4Assert( success );
+ success = CloseHandle( connect_sync );
+ Win4Assert( success );
+ connect_sync = NULL;
+ }
+ ChannelLock.Release();
+
+cleanup_exit:
+ // if we allocated the data buffer, free it here.
+ if (pbData != abData)
+ {
+ PrivMemFree(pbData);
+ }
+
+ if (fMshlTransfered)
+ {
+ cdh.dwFlags |= CHNLFLAGS_MSHLTRANSFERED;
+ RewriteHeader(pStm, &cdh, sizeof(cdh), ulSeekStart);
+ }
+
+ // if connected this time, tell RH by returning special code
+ return sc == NOERROR && fDidConnect ? CHAN_S_RECONNECT : sc;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::CheckDestCtx, private
+//
+// Synopsis: register any server-side rpc protocol we need to use
+// to let the other guy talk to us.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+void CRpcChannelBuffer::CheckDestCtx(void *pvDestCtx)
+{
+ AssertValid(FALSE, FALSE);
+
+ // the destination context refers to a Rpc protocol sequence.
+ // make sure we have registered the server side of the protseq
+ // we are using to talk to him.
+
+ LocalService()->RegisterProtseq((WCHAR *)pvDestCtx);
+
+ // if we are marshalling the proxy of an object on this machine
+ // to a remote machine, and the server has not already registered
+ // the requested protseq, go tell it to do that now.
+
+ if (state == client_cs)
+ {
+ _pService->RemoteRegisterProtseq((WCHAR *)pvDestCtx);
+ }
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::ReleaseMarshalData, public
+//
+// Synopsis: Releases any internal state kept around for marshalled
+// interfaces.
+//
+// History: 23-Nov-93 Rickhi Created
+// 16-May-94 CraigWi Removed middle man case and fixed
+// error case so that we always correctly
+// release the connection.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRpcChannelBuffer::ReleaseMarshalData(IStream *pStm)
+{
+ AssertValid(FALSE, TRUE);
+ Win4Assert(state != server_cs); // can't happen
+
+ // read our data size from the stream.
+ SChannelDataHdr cdh;
+ HRESULT sc = StRead(pStm, &cdh, sizeof(cdh));
+
+ if (FAILED(sc))
+ return sc;
+
+ // REF COUNTING:
+
+ // Release the connection due to the marshaling. In the case of normal
+ // marshaling, it may have already been released (actually transfered).
+ // The only other time connections are removed is in DisconnectObject
+ // below. See CRpcChannelBuffer::MarshalInterface (avove) and
+ // CStdIdentity (stdid.cxx) for more information.
+
+ if (cdh.dwFlags & CHNLFLAGS_TABLE)
+ {
+ // marshalled for a table. this is never called during unmarshal.
+ // we just reverse whatever marshall did.
+
+ // this shouldn't happen with table marshal packets
+ Win4Assert((cdh.dwFlags & CHNLFLAGS_MSHLTRANSFERED) == 0);
+
+ // We don't handle the case when this ReleaseMarshalData is on
+ // the client side.
+ if (state != disconnected_cs)
+ // BUGBUG: assert or catch at higher level
+ return E_UNEXPECTED;
+
+ _pRH->ReleaseConnection(sg_mapMFtoEC[cdh.dwFlags & HDLRFLAGS_TABLE], 0, TRUE);
+
+ CairoleDebugOut((DEB_ITRACE, "ReleasedData Table Marshal %x\n", this));
+ }
+ else if ((cdh.dwFlags & CHNLFLAGS_MSHLTRANSFERED) == 0)
+ {
+ // normal marshal which did not get properly unmarshaled. This
+ // could be an error on the client side or how it happens normally
+ // on the server side. In both cases, we simply need to reverse
+ // what happened in the ::MarshalInterface above.
+
+ if (state == disconnected_cs)
+ {
+ // on server side, just release connection here;
+ // use fLastReleaseClose == FALSE so that we don't disturb the
+ // container connection; ideally we would use FALSE for all
+ // marshals bound for container and TRUE for everyone else.
+ _pRH->ReleaseConnection(EXTCONN_STRONG | EXTCONN_CALLABLE, 0,FALSE);
+
+ CairoleDebugOut((DEB_ITRACE, "ReleasedDate Local Marshal %x\n", this));
+ }
+ else
+ {
+ // on client side; contact server; may fail
+ Win4Assert(state == client_cs);
+ sc = _pService->RemoveMarshalConnection(_ChannelID);
+
+ CairoleDebugOut((DEB_ITRACE, "ReleasedData Remote Marshal %x\n", this));
+ }
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ // just seek to the end of the our data
+ LARGE_INTEGER libMove;
+ LISet32(libMove, cdh.ulDataSize-sizeof(SChannelDataHdr));
+ sc = pStm->Seek(libMove, STREAM_SEEK_CUR, NULL);
+ }
+
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::DisconnectObject, public
+//
+// Synopsis: Disconnects channel; for client, this restores channel
+// such that an Unmarshal will reconnect; for server,
+// this just releases the connections pending a full
+// release of the server channel.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRpcChannelBuffer::DisconnectObject(DWORD dwReserved)
+{
+ AssertValid(FALSE, TRUE);
+
+ CairoleDebugOut((DEB_CHANNEL, "DisconnectObject pChannel:%x\n", this));
+
+ // CODEWORK: thread safety: need to block multiple calls here.
+
+ if (state == client_cs)
+ {
+ // REF COUNTING:
+
+ // Release channel which causes disconnect
+ // on server which releases connections
+
+ if (_pService != NULL && _ChannelID != BAD_CHANNEL_ID)
+ {
+ // if current call being processed is input sync or async, release
+ // must be async. We check the these cases to avoid deadlock.
+ // If we are in an input sync call, it is possible that the callee
+ // is as well and we want to avoid the possibility of dead lock.
+ // If we are not in an input sync call, it is still possible for
+ // callee here is, but the thread of execution has to be unrelated
+ // because once a call sequence turns into input sync, all nested
+ // calls must be input sync as well. Any more general dead lock
+ // problem would likely be a dead lock problem without this test.
+ // This is the way that 16bit OLE behaved (with the tests on the
+ // calling side).
+
+
+#ifndef _CHICAGO_
+ // There is potentially a problem with a deadlock occuring in NT if
+ // we are in thread detach and doing this operation as clean
+ // up with some object in the same process because of the special
+ // rules for thread deatch. Therefore, Since we are in thread
+ // detach and we don't care to hear the response from the caller
+ // anyway, we make all the releases async so we can get through the
+ // exit without being called back.
+ BOOL fDoReleaseAsync = FALSE;
+
+ if ((_pService == LocalService()) || IsWOWThread())
+ {
+ fDoReleaseAsync = TLSGetThreadDetach();
+ }
+
+#endif // !_CHICAGO_
+
+ // CODEWORK: may want to have a more abstract way to get this info
+ CALLCATEGORY callcat =
+ GetCallMainControlForThread()->GetCallCatOfInCall();
+
+ _pService->ReleaseChannel(this, callcat == CALLCAT_ASYNC ||
+ callcat == CALLCAT_INPUTSYNC ||
+ callcat == CALLCAT_INTERNALINPUTSYNC ||
+ InSendMessage()
+#ifdef _CHICAGO_
+
+ // For Chicago we don't need special logic for detach
+ );
+
+#else // !_CHICAGO_
+
+ // For NT we need special logic at thread detach.
+ || fDoReleaseAsync);
+
+#endif // _CHICAGO_
+
+ _ChannelID = BAD_CHANNEL_ID;
+ _ulMarshalCnt = 0;
+ }
+ }
+ else if (state == server_cs)
+ {
+ // REF COUNTING: release all connections due to this channel
+
+ DWORD extconn = _fStrongConn ? EXTCONN_STRONG : EXTCONN_WEAK;
+ extconn |= EXTCONN_CALLABLE;
+ while (_ulMarshalCnt != 0)
+ {
+ _ulMarshalCnt--; // decrement now in case we get reentered
+
+ // Note that release connection also does a release on the ID.
+ _pRH->ReleaseConnection( extconn, 0, TRUE );
+ }
+
+ // the channel is marked disconnected by the lack of a service
+ // object (released below). The _pRH is retained until the dtor.
+ // This channel has already been removed from the channel list.
+ }
+
+ if (_pService != NULL)
+ {
+ _pService->Release();
+ _pService = NULL;
+ }
+ if (controller != NULL)
+ {
+ controller->Release();
+ controller = NULL;
+ }
+
+ AssertValid(TRUE, TRUE);
+
+ return S_OK;
+}
+
+
+
+//+------------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::TransferMarshalConnection, public
+//
+// Synopsis: Moves the responsibility of releasing one marshal connection
+// to this channel. If the channel is currently weak (i.e., this
+// is the connection from the container process), then the
+// connection is made weak.
+//
+// History: 14-May-94 CraigWi Created
+//
+// CODEWORK: multi-threading: bind _fStronConn + strength of conn + _ulM..Cnt.
+//
+//-------------------------------------------------------------------------
+
+INTERNAL CRpcChannelBuffer::TransferMarshalConnection(void)
+{
+ HRESULT hr;
+
+ // BUGBUG: since the marshal count can be large, it would be better
+ // if we released extra strong connections on the object here rather
+ // than counting another one. In the multi-threaded case, this
+ // would have to be in a critical section.
+
+ if (!_fStrongConn)
+ {
+ // convert strong into weak; don't shutdown server if only strong
+ if (FAILED(hr = _pRH->AddConnection(EXTCONN_WEAK | EXTCONN_CALLABLE, 0)))
+ return hr;
+
+ _pRH->ReleaseConnection(EXTCONN_STRONG | EXTCONN_CALLABLE, 0, FALSE);
+ }
+ InterlockedIncrement((long*)&_ulMarshalCnt);
+
+ AssertValid(FALSE, TRUE);
+
+ return S_OK;
+}
+
+
+//+------------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::LockConnection, public
+//
+// Synopsis: Locks the connection by making all marshaled connections
+// strong. Connections start out strong and the only way
+// currently to demote them is via OleSetContainedObject.
+//
+// History: 14-May-94 CraigWi Created
+//
+// CODEWORK: multi-threading: bind _fStronConn + strength of conn
+//
+//-------------------------------------------------------------------------
+
+void CRpcChannelBuffer::LockConnection(void)
+{
+ AssertValid(FALSE, TRUE);
+
+ Win4Assert(!_fStrongConn && "Connection lock can only be toggled");
+
+ if (!_fStrongConn)
+ {
+ for (DWORD i = 0; i < _ulMarshalCnt; i++)
+ {
+ if (FAILED(_pRH->AddConnection(EXTCONN_STRONG | EXTCONN_CALLABLE, 0)))
+ {
+ // can't add a strong connection; don't bother; on single
+ // threaded systems, this loop will be atomic;
+ // CODEWORK: for multi-threaded cases, we must guard against
+ // a disconnect happening here.
+
+ Win4Assert(i == 0 && "Partially converted connection");
+ return;
+ }
+
+ _pRH->ReleaseConnection(EXTCONN_WEAK | EXTCONN_CALLABLE, 0, TRUE);
+ }
+ _fStrongConn = TRUE;
+ }
+}
+
+
+//+------------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::UnlockConnection, public
+//
+// Synopsis: Unlocks the connection by making all marshaled connections
+// weak. Connections start out strong and the only way
+// currently to demote them is via OleSetContainedObject.
+//
+// Arguments: [fLastUnlockCloses] -- passed on to the release strong
+//
+// History: 14-May-94 CraigWi Created
+//
+//-------------------------------------------------------------------------
+
+void CRpcChannelBuffer::UnlockConnection(BOOL fLastUnlockCloses)
+{
+ AssertValid(FALSE, TRUE);
+
+ Win4Assert(_fStrongConn && "Connection lock can only be toggled");
+
+ if (_fStrongConn)
+ {
+ _fStrongConn = FALSE; // set now so that reentrant disconnect
+ // on last strong connection going
+ // knows to release weak connections.
+ for (DWORD i = 0; i < _ulMarshalCnt; i++)
+ {
+ if (FAILED(_pRH->AddConnection(EXTCONN_WEAK | EXTCONN_CALLABLE, 0)))
+ {
+ // can't add a weak connection; don't bother; on single
+ // threaded systems, this loop will be atomic;
+ // CODEWORK: for multi-threaded cases, we must guard against
+ // a disconnect happening here.
+
+ Win4Assert(i == 0 && "Partially converted connection");
+ _fStrongConn = TRUE; // didn't convert anything
+ return;
+ }
+
+ _pRH->ReleaseConnection(EXTCONN_STRONG | EXTCONN_CALLABLE, 0, fLastUnlockCloses);
+ }
+ }
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::QueryObjectInterface, public
+//
+// Synopsis: queries the remote side to get a new interface on
+// the object.
+//
+// Exceptions: none
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+INTERNAL CRpcChannelBuffer::QueryObjectInterface(REFIID riid)
+{
+ AssertValid(FALSE, FALSE);
+
+ if (_pService == NULL)
+ return CO_E_OBJNOTCONNECTED;
+
+ return _pService->QueryObjectInterface(_ChannelID, riid);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcChannelBuffer::LockObjectConnection, public
+//
+// Synopsis: locks or unlocks the connection by calling via service object
+// to remote process.
+//
+// History: 14-May-94 CraigWi Created
+//
+//--------------------------------------------------------------------
+
+INTERNAL CRpcChannelBuffer::LockObjectConnection(BOOL fLock, BOOL fLastUnlockCloses)
+{
+ AssertValid(FALSE, FALSE);
+
+ if (_pService == NULL)
+ return CO_E_OBJNOTCONNECTED;
+
+ return _pService->LockObjectConnection(_ChannelID, fLock, fLastUnlockCloses);
+}
+
+
diff --git a/private/ole32/com/remote/ipmrshl.cxx b/private/ole32/com/remote/ipmrshl.cxx
new file mode 100644
index 000000000..adb431bf6
--- /dev/null
+++ b/private/ole32/com/remote/ipmrshl.cxx
@@ -0,0 +1,659 @@
+//+-------------------------------------------------------------------
+//
+// File: ipmrshl.cpp
+//
+// Contents: Code the implements the standard free thread in process
+// marshaler.
+//
+// Classes: CFreeMarshaler
+// CFmCtrlUnknown
+//
+// Functions: CoCreateFreeThreadedMarshaler
+//
+// History: 03-Nov-94 Ricksa
+//
+//--------------------------------------------------------------------
+#include <ole2int.h>
+
+INTERNAL_(IMarshal *) FindOrCreateStdMarshal(IUnknown *pUnk, BOOL fCreate);
+
+
+//+-------------------------------------------------------------------
+//
+// Class: CFreeMarshaler
+//
+// Synopsis: Generic marshaling class
+//
+// Methods: IUnknown
+// IMarshal
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+class CFreeMarshaler : public IMarshal, public CPrivAlloc
+{
+public:
+ CFreeMarshaler(IUnknown *punk);
+
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, void FAR * FAR * ppv);
+ STDMETHODIMP_(ULONG) AddRef(void);
+ STDMETHODIMP_(ULONG) Release(void);
+
+ // IMarshal Interface
+ STDMETHODIMP GetUnmarshalClass(
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags,
+ CLSID *pCid);
+
+ STDMETHODIMP GetMarshalSizeMax(
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags,
+ DWORD *pSize);
+
+ STDMETHODIMP MarshalInterface(
+ IStream __RPC_FAR *pStm,
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags);
+
+ STDMETHODIMP UnmarshalInterface(
+ IStream *pStm,
+ REFIID riid,
+ void **ppv);
+
+ STDMETHODIMP ReleaseMarshalData(IStream *pStm);
+
+ STDMETHODIMP DisconnectObject(DWORD dwReserved);
+
+private:
+
+ friend class CFmCtrlUnknown;
+
+ // Pointer to the controlling unknown.
+ IUnknown * _punkCtrl;
+
+};
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Class: CFmCtrlUnknown
+//
+// Synopsis: Controlling IUnknown for generic marshaling class.
+//
+// Methods: IUnknown
+// IMarshal
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+class CFmCtrlUnknown : public IUnknown, public CPrivAlloc
+{
+ // IUnknown
+ STDMETHODIMP QueryInterface(REFIID iid, void **ppv);
+
+ STDMETHODIMP_(ULONG) AddRef(void);
+
+ STDMETHODIMP_(ULONG) Release(void);
+
+private:
+
+ friend HRESULT CoCreateFreeThreadedMarshaler(
+ IUnknown *punkCtrl,
+ IUnknown **punkMarshal);
+
+ friend HRESULT GetInProcFreeMarshaler(IMarshal **ppIM);
+
+ CFmCtrlUnknown(void);
+
+ ~CFmCtrlUnknown(void);
+
+ CFreeMarshaler * _pfm;
+
+ ULONG _cRefs;
+};
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CoCreateFreeThreadedMarshaler, public
+//
+// Synopsis: Create the controlling unknown for the marshaler
+//
+// Arguments: [punkOuter] - controlling unknown
+// [ppunkMarshal] - controlling unknown for marshaler.
+//
+// Returns: NOERROR
+// E_INVALIDARG
+// E_OUTOFMEMORY
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+HRESULT CoCreateFreeThreadedMarshaler(
+ IUnknown *punkOuter,
+ IUnknown **ppunkMarshal)
+{
+ OLETRACEIN((API_CoCreateFreeThreadedMarshaler, PARAMFMT("punkOuter= %p, ppunkMarshal= %p"),
+ punkOuter, ppunkMarshal));
+
+ HRESULT hr = E_INVALIDARG;
+
+ // Validate the parameters
+ if (((punkOuter == NULL) || IsValidInterface(punkOuter))
+ && IsValidPtrOut(ppunkMarshal, sizeof(IUnknown *)))
+ {
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&punkOuter);
+ // Assume failure
+ *ppunkMarshal = NULL;
+
+ hr = E_OUTOFMEMORY;
+
+ // Allocate new free marshal object
+ CFmCtrlUnknown *pfmc = new CFmCtrlUnknown();
+
+ if (pfmc != NULL)
+ {
+ if (punkOuter == NULL)
+ {
+ // Caller wants a non-aggreagated object
+ punkOuter = pfmc;
+ }
+
+ // Initialize the pointer
+ pfmc->_pfm = new CFreeMarshaler(punkOuter);
+
+ if (pfmc->_pfm != NULL)
+ {
+ *ppunkMarshal = pfmc;
+ CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_IUnknown,
+ (IUnknown **)ppunkMarshal);
+ hr = S_OK;
+ }
+ else
+ {
+ delete pfmc;
+ }
+ }
+ }
+
+ OLETRACEOUT((API_CoCreateFreeThreadedMarshaler, hr));
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: GetInProcFreeMarshaler, public
+//
+// Synopsis: Create the controlling unknown for the marshaler
+//
+// Arguments: [ppIM] - where to put inproc marshaler
+//
+// Returns: NOERROR
+// E_OUTOFMEMORY
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+HRESULT GetInProcFreeMarshaler(IMarshal **ppIM)
+{
+ HRESULT hr = E_OUTOFMEMORY;
+
+ // Allocate new free marshal object
+ CFmCtrlUnknown *pfmc = new CFmCtrlUnknown();
+
+ if (pfmc != NULL)
+ {
+ // Initialize the pointer
+ pfmc->_pfm = new CFreeMarshaler(pfmc);
+
+ if (pfmc->_pfm != NULL)
+ {
+ *ppIM = pfmc->_pfm;
+ CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_IMarshal,
+ (IUnknown **)ppIM);
+ hr = S_OK;
+ }
+ else
+ {
+ delete pfmc;
+ }
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFmCtrlUnknown::CFmCtrlUnknown
+//
+// Synopsis: The constructor for controling IUnknown of free marshaler
+//
+// Arguments: None
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+CFmCtrlUnknown::CFmCtrlUnknown(void) : _cRefs(1), _pfm(NULL)
+{
+ // Header does all the work.
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFmCtrlUnknown::~CFmCtrlUnknown
+//
+// Synopsis: The destructor for controling IUnknown of free marshaler
+//
+// Arguments: None
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+CFmCtrlUnknown::~CFmCtrlUnknown(void)
+{
+ delete _pfm;
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFmCtrlUnknown::QueryInterface
+//
+// Returns: S_OK
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFmCtrlUnknown::QueryInterface(REFIID iid, void **ppv)
+{
+ *ppv = NULL;
+ HRESULT hr = E_NOINTERFACE;
+
+ if (IsEqualGUID(iid, IID_IUnknown))
+ {
+ *ppv = this;
+ AddRef();
+ hr = S_OK;
+ }
+ else if (IsEqualGUID(iid, IID_IMarshal))
+ {
+ *ppv = _pfm;
+ _pfm->AddRef();
+ hr = S_OK;
+ }
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFmCtrlUnknown::AddRef
+//
+// Synopsis: Standard stuff
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CFmCtrlUnknown::AddRef(void)
+{
+ InterlockedIncrement((LONG *) &_cRefs);
+
+ return _cRefs;
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFmCtrlUnknown::Release
+//
+// Synopsis: Standard stuff
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CFmCtrlUnknown::Release(void)
+{
+ ULONG cRefs = InterlockedDecrement((LONG *) &_cRefs);
+
+ if (cRefs == 0)
+ {
+ delete this;
+ }
+
+ return cRefs;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::CFreeMarshaler()
+//
+// Synopsis: The constructor for CFreeMarshaler.
+//
+// Arguments: None
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+CFreeMarshaler::CFreeMarshaler(IUnknown *punkCtrl)
+ : _punkCtrl(punkCtrl)
+{
+ // Header does all the work.
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::QueryInterface
+//
+// Synopsis: Pass QI to our controlling IUnknown
+//
+// Returns: S_OK
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFreeMarshaler::QueryInterface(REFIID iid, void **ppv)
+{
+ return _punkCtrl->QueryInterface(iid, ppv);
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::AddRef
+//
+// Synopsis: Pass AddRef to our controlling IUnknown
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CFreeMarshaler::AddRef(void)
+{
+ return _punkCtrl->AddRef();
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::Release
+//
+// Synopsis: Pass release to our controlling IUnknown
+//
+// History: 15-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CFreeMarshaler::Release(void)
+{
+ return _punkCtrl->Release();
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::GetUnmarshalClass
+//
+// Synopsis: Return the unmarshaling class
+//
+// History: 08-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFreeMarshaler::GetUnmarshalClass(
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags,
+ CLSID *pCid)
+{
+ // Inprocess context?
+ if (dwDestContext == MSHCTX_INPROC)
+ {
+ // If this is an inproc marshal then we are the class
+ // that can unmarshal.
+ *pCid = CLSID_InProcFreeMarshaler;
+ return S_OK;
+ }
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ IMarshal *pmrshlStd = FindOrCreateStdMarshal((IUnknown *) pv, TRUE);
+
+ if (pmrshlStd != NULL)
+ {
+ hr = pmrshlStd->GetUnmarshalClass(riid, pv, dwDestContext,
+ pvDestContext, mshlflags, pCid);
+
+ pmrshlStd->Release();
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::GetMarshalSizeMax
+//
+// Synopsis: Return maximum bytes need for marshaling
+//
+// History: 08-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFreeMarshaler::GetMarshalSizeMax(
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags,
+ DWORD *pSize)
+{
+ // Inprocess context?
+ if (dwDestContext == MSHCTX_INPROC)
+ {
+ // If this is an inproc marshal then we know the size
+ *pSize = sizeof(this);
+ return S_OK;
+ }
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ IMarshal *pmrshlStd = FindOrCreateStdMarshal((IUnknown *) pv, TRUE);
+
+ if (pmrshlStd != NULL)
+ {
+ hr = pmrshlStd->GetMarshalSizeMax(riid, pv, dwDestContext,
+ pvDestContext, mshlflags, pSize);
+
+ pmrshlStd->Release();
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::MarshalInterface
+//
+// Synopsis: Marshal the interface
+//
+// History: 08-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFreeMarshaler::MarshalInterface(
+ IStream *pStm,
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags)
+{
+ HRESULT hr;
+
+ // Inprocess context?
+ if (dwDestContext == MSHCTX_INPROC)
+ {
+ // Write the marshal flags into the stream
+ hr = pStm->Write(&mshlflags, sizeof(mshlflags), NULL);
+
+ if (hr == NOERROR)
+ {
+ // Write the pointer into the stream
+ ULONG cb;
+
+ hr = pStm->Write(&pv, sizeof(pv), NULL);
+
+ // Bump reference count based on type of marshal
+ if ((hr == NOERROR)
+ && ((mshlflags == MSHLFLAGS_NORMAL)
+ || (mshlflags == MSHLFLAGS_TABLESTRONG)))
+ {
+ ((IUnknown *) pv)->AddRef();
+ }
+ }
+
+ return hr;
+ }
+
+ hr = E_OUTOFMEMORY;
+
+ IMarshal *pmrshlStd = FindOrCreateStdMarshal((IUnknown *) pv, TRUE);
+
+ if (pmrshlStd != NULL)
+ {
+ hr = pmrshlStd->MarshalInterface(pStm, riid, pv, dwDestContext,
+ pvDestContext, mshlflags);
+
+ pmrshlStd->Release();
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::UnmarshalInterface
+//
+// Synopsis: Unmarshal the interface
+//
+// History: 08-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFreeMarshaler::UnmarshalInterface(
+ IStream *pStm,
+ REFIID riid,
+ void **ppv)
+{
+ HRESULT hr;
+
+ // The marshal flags will tell us if we have to AddRef the object
+ DWORD mshlflags;
+
+ hr = pStm->Read(&mshlflags, sizeof(mshlflags), NULL);
+
+ if (hr == NOERROR)
+ {
+ // If Inprocess, we just read the pointer out of the stream
+ hr = pStm->Read(ppv, sizeof(*ppv), NULL);
+
+ // AddRef the pointer if marshaled tableweak.
+ if ((hr == NOERROR)
+ && ((mshlflags == MSHLFLAGS_TABLEWEAK)
+ || (mshlflags == MSHLFLAGS_TABLESTRONG)))
+ {
+ ((IUnknown *) *ppv)->AddRef();
+ }
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::ReleaseMarshalData
+//
+// Synopsis: Release the marshaled data
+//
+// History: 08-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFreeMarshaler::ReleaseMarshalData(IStream *pStm)
+{
+ // Get the marshal flags
+ DWORD mshlflags;
+
+ HRESULT hr = pStm->Read(&mshlflags, sizeof(mshlflags), NULL);
+
+ if ((hr == NOERROR) && (mshlflags == MSHLFLAGS_TABLESTRONG))
+ {
+ IUnknown *punk;
+
+ // If Inprocess, we just read the pointer out of the stream
+ hr = pStm->Read(&punk, sizeof(punk), NULL);
+
+ if (hr == NOERROR)
+ {
+ // Dump the extra AddRef we put on when we put the object
+ // in the table.
+ punk->Release();
+ }
+ }
+
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CFreeMarshaler::DisconnectObject
+//
+// Synopsis: Disconnect the object
+//
+// History: 08-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CFreeMarshaler::DisconnectObject(DWORD dwReserved)
+{
+ HRESULT hr = E_OUTOFMEMORY;
+
+ IMarshal *pmrshlStd = FindOrCreateStdMarshal(_punkCtrl, TRUE);
+
+ if (pmrshlStd != NULL)
+ {
+ hr = pmrshlStd->DisconnectObject(dwReserved);
+
+ pmrshlStd->Release();
+ }
+
+ return hr;
+}
diff --git a/private/ole32/com/remote/islocalp.cxx b/private/ole32/com/remote/islocalp.cxx
new file mode 100644
index 000000000..3e9ae2c78
--- /dev/null
+++ b/private/ole32/com/remote/islocalp.cxx
@@ -0,0 +1,243 @@
+//+-------------------------------------------------------------------
+//
+// File: islocalp.cxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 21-Nov-94 Ricksa
+//
+//--------------------------------------------------------------------
+#include <ole2int.h>
+
+#include <service.hxx> // class definition
+
+#ifdef _CHICAGO_
+
+CLocalServiceList lslLocalServices;
+
+const DWORD dwDefaultSize = 8;
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLocalServiceList::Init
+//
+// Synopsis: Initialize the object
+//
+// Returns: [TRUE] - initial construction worked
+// [FALSE] - initial construction failed
+//
+// History: 21-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CLocalServiceList::Init(void)
+{
+ SetSize(dwDefaultSize, dwDefaultSize);
+ return GetSize() != 0;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLocalServiceList::Uninit
+//
+// Synopsis: Free Data associated with the object
+//
+// History: 21-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+void CLocalServiceList::Uninit(void)
+{
+ SetSize(0, 0);
+ _dwSlotsUsed = 0;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLocalServiceList::Add
+//
+// Synopsis: Add a server to the list of local servers
+//
+// Arguments: [prpcsrv] - entry to add to the list
+//
+// Returns: [TRUE] - object was added.
+// [FALSE] - object could not be added.
+//
+// History: 21-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CLocalServiceList::Add(CRpcService *prpcsrv)
+{
+ // Lock from updates till we are done
+ COleStaticLock lck(_mxs);
+
+ // Result of this function
+ BOOL fResult = FALSE;
+
+ // Search for an empty entry
+ CRpcService **pprpcsrv = (CRpcService **) GetAt(0);
+
+ ULONG cMax = GetSize();
+
+ if (_dwSlotsUsed < cMax)
+ {
+ // empty slot in table so use it
+ Win4Assert(pprpcsrv[_dwSlotsUsed] == 0); // should be empty!
+ pprpcsrv[_dwSlotsUsed] = prpcsrv;
+ fResult = TRUE;
+ }
+ else
+ {
+ // No room so bump the size of the table
+ fResult = SetAtGrow(_dwSlotsUsed, &prpcsrv);
+ }
+
+ if (fResult)
+ {
+ _dwSlotsUsed++;
+ }
+
+ return fResult;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLocalServiceList::Remove
+//
+// Synopsis: Remove a server from this list
+//
+// Arguments: [prpcsrv] - entry to remove from the list
+//
+// Returns: [TRUE] - object was removed.
+// [FALSE] - object could not be removed.
+//
+// History: 21-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CLocalServiceList::Remove(CRpcService *prpcsrv)
+{
+ // Lock from updates till we are done
+ COleStaticLock lck(_mxs);
+
+ // Result of this function
+ BOOL fResult = FALSE;
+
+ // Search for an empty entry
+ CRpcService **pprpcsrv = (CRpcService **) GetAt(0);
+
+ for (DWORD i = 0; i < _dwSlotsUsed; i++)
+ {
+ if (pprpcsrv[i] == prpcsrv)
+ {
+ if (i != (_dwSlotsUsed - 1))
+ {
+ pprpcsrv[i] = pprpcsrv[_dwSlotsUsed - 1];
+ pprpcsrv[_dwSlotsUsed - 1] = NULL; // as a debug aid
+ }
+ else
+ {
+ pprpcsrv[i] = NULL;
+ }
+ _dwSlotsUsed--;
+ fResult = TRUE;
+ break;
+ }
+ }
+
+ return fResult;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLocalServiceList::Find
+//
+// Synopsis: Add an object to the bag
+//
+// Arguments: [rcep] - endpoint to search for on the list
+//
+// Returns: [TRUE] - object was added.
+// [FALSE] - object could not be added.
+//
+// History: 21-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CLocalServiceList::Find(CEndPoint *pcep)
+{
+ // Lock from updates till we are done
+ COleStaticLock lck(_mxs);
+
+ // Result of this function
+ BOOL fResult = FALSE;
+
+ // Search for an empty entry
+ CRpcService **prpcsrv = (CRpcService **) GetAt(0);
+
+ for (DWORD i = 0; i < _dwSlotsUsed; i++)
+ {
+ if (pcep->IsEqual(prpcsrv[i]->GetSEp()))
+ {
+ fResult = TRUE;
+ break;
+ }
+ }
+
+ return fResult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsInLocalProcess
+//
+// Synopsis: Determine if endpoint string refers to this process
+//
+// Arguments: [pcep] - endpoint to search for on the list
+//
+// Returns: [TRUE] - Is in this process
+// [FALSE] - Not in this process
+//
+// History: 21-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL IsInLocalProcess(CEndPoint *pcep)
+{
+ return lslLocalServices.Find(pcep);
+}
+
+#else
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsInLocalProcess
+//
+// Synopsis: Determine if endpoint string refers to this process
+//
+// Arguments: [pcep] - endpoint to search for on the list
+//
+// Returns: [TRUE] - Is in this process
+// [FALSE] - Not in this process
+//
+// History: 21-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL IsInLocalProcess(CEndPoint *pcep)
+{
+ return (CRpcService::sg_pLocalSrv != NULL)
+ ? pcep->IsEqual(CRpcService::sg_pLocalSrv->GetSEp())
+ : FALSE;
+}
+
+
+
+#endif // _CHICAGO_
diff --git a/private/ole32/com/remote/islocalp.hxx b/private/ole32/com/remote/islocalp.hxx
new file mode 100644
index 000000000..3176be2da
--- /dev/null
+++ b/private/ole32/com/remote/islocalp.hxx
@@ -0,0 +1,104 @@
+//+-------------------------------------------------------------------
+//
+// File: islocalp.hxx
+//
+// Contents: Helpers for helping set whether a service object is
+// in the current process or not.
+//
+// Classes: CLocalServiceList
+//
+// Functions: IsInLocalProcess
+//
+// History: 21-Nov-94 Ricksa
+//
+//--------------------------------------------------------------------
+#ifndef _ISLOCALP_HXX_
+#define _ISLOCALP_HXX_
+
+// Function to hide how we determine if the end point is local to the process.
+BOOL IsInLocalProcess(CEndPoint *pep);
+
+#ifdef _CHICAGO_
+
+//+-------------------------------------------------------------------------
+//
+// Class: CLocalServiceList (lsl)
+//
+// Purpose: Provide of list of service objects local to this process
+//
+// Interface: Init - Get this object ready for use
+// Add - add an item to the list
+// Remove - remove an item from the list
+// Find - find an end point on the list
+//
+// History: 21-Nov-94 Ricksa Created
+//
+// Notes: This class *must* be statically allocated, as it contains
+// a COleStaticMutexSem object.
+//
+//--------------------------------------------------------------------------
+class CLocalServiceList : private CArrayFValue, public CPrivAlloc
+{
+public:
+ CLocalServiceList(void);
+
+ BOOL Init(void);
+
+ void Uninit(void);
+
+ BOOL Add(CRpcService *prpcsrv);
+
+ BOOL Remove(CRpcService *prpcsrv);
+
+ BOOL Find(CEndPoint *pcep);
+
+ COleStaticMutexSem & GetMutex(void);
+
+private:
+
+ DWORD _dwSlotsUsed;
+
+ COleStaticMutexSem _mxs;
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLocalServiceList::CLocalServiceList
+//
+// Synopsis: Create an empty list
+//
+// History: 21-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CLocalServiceList::CLocalServiceList(void)
+ : CArrayFValue(sizeof(CRpcService *)), _dwSlotsUsed(0)
+{
+ Win4Assert (g_fDllState == DLL_STATE_STATIC_CONSTRUCTING);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLocalServiceList::GetMutex
+//
+// Synopsis: returns reference to list mutext. This is needed by the
+// CRpcService object Release method.
+//
+// History: 12-Dec-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+inline COleStaticMutexSem & CLocalServiceList::GetMutex()
+{
+ return _mxs;
+}
+
+
+
+
+
+// Global service list object
+extern CLocalServiceList lslLocalServices;
+
+#endif // _CHICAGO_
+
+#endif _ISLOCALP_HXX_
diff --git a/private/ole32/com/remote/makefile b/private/ole32/com/remote/makefile
new file mode 100644
index 000000000..e09078703
--- /dev/null
+++ b/private/ole32/com/remote/makefile
@@ -0,0 +1,24 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+!include $(CAIROLE)\com\makefile
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/com/remote/mapdwp.hxx b/private/ole32/com/remote/mapdwp.hxx
new file mode 100644
index 000000000..76f904e95
--- /dev/null
+++ b/private/ole32/com/remote/mapdwp.hxx
@@ -0,0 +1,108 @@
+//+-------------------------------------------------------------------
+//
+// File: mapdwp.hxx
+//
+// Contents: Class to map thread id to thread local storage ptr
+//
+// Classes: CMapDword
+//
+// Notes: This class is needed soley for debug builds and then only
+// because we dont get THREAD_DETACH notification for all
+// threads when a process exits. This allows us to clean up
+// the tls so we dont report memory leaks.
+//
+// In order to keep the implementation simple, we use a fixed
+// array of entries, meaning we (may) get memory leaks
+// reported if we ever have more than MAP_MAX_SIZE threads
+// alive at any given time.
+//
+//+-------------------------------------------------------------------
+
+#if !defined(_CAIRO_) && DBG==1
+
+#define MAP_MAX_SIZE 100
+
+class CMapDword : public CPrivAlloc
+{
+public:
+ CMapDword(void);
+ ~CMapDword(void);
+
+ void SetAt(DWORD tid, void *pData);
+ void RemoveKey(DWORD tid);
+ void RemoveAll(void);
+
+private:
+
+ DWORD _tid[MAP_MAX_SIZE];
+ void * _pData[MAP_MAX_SIZE];
+ DWORD _index;
+};
+
+
+CMapDword::CMapDword(void)
+{
+ _index = 0;
+ memset(_tid, 0, MAP_MAX_SIZE * sizeof(DWORD));
+}
+
+CMapDword::~CMapDword(void)
+{
+ RemoveAll();
+}
+
+void CMapDword::SetAt(DWORD tid, void *pData)
+{
+ for (ULONG i=_index; i<MAP_MAX_SIZE; i++)
+ {
+ if (_tid[i] == 0)
+ {
+ _tid[i] = tid;
+ _pData[i] = pData;
+ _index = i;
+ return;
+ }
+ }
+
+ for (i=0; i<_index; i++)
+ {
+ if (_tid[i] == 0)
+ {
+ _tid[i] = tid;
+ _pData[i] = pData;
+ _index = i;
+ return;
+ }
+ }
+
+ Win4Assert(!"Tls Table is FULL");
+}
+
+
+void CMapDword::RemoveKey(DWORD tid)
+{
+ for (ULONG i=0; i<MAP_MAX_SIZE; i++)
+ {
+ if (_tid[i] == tid)
+ {
+ _tid[i] = 0;
+ return;
+ }
+ }
+}
+
+
+void CMapDword::RemoveAll(void)
+{
+ for (ULONG i=0; i<MAP_MAX_SIZE; i++)
+ {
+ if (_tid[i] != 0)
+ {
+ PrivMemFree(_pData[i]);
+ _tid[i] = 0;
+ }
+ }
+}
+
+
+#endif // !defined(_CAIRO_) && DBG==1
diff --git a/private/ole32/com/remote/notify.cxx b/private/ole32/com/remote/notify.cxx
new file mode 100644
index 000000000..04a4641db
--- /dev/null
+++ b/private/ole32/com/remote/notify.cxx
@@ -0,0 +1,171 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: notify.cxx
+//
+// Contents: Implements the notification window for starting RPC lazily
+// on Win95
+//
+// History: 3-24-95 JohannP (Johann Posch) Created
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include <service.hxx>
+
+// Various things used for special single threaded DLL processing
+
+// Note: we have to create a unique string so that get
+// register a unique class for each 16 bit app.
+// The class space is global on chicago.
+//
+
+extern LPSTR ptszOleMainThreadWndClass;
+
+#define DllWNDCLASS WNDCLASSA
+#define DllRegisterClass RegisterClassA
+#define DllUnregisterClass UnregisterClassA
+#define DllCreateWindowEx SSCreateWindowExA
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetOleNotificationWnd
+//
+// Synopsis: returns the notification window where the process
+// can receive message to initialize e.g rpc
+//
+// Effects: The OleRpcNotification window is used to delay the initialize
+// of RPC. Each time an interface is marshalled, we return it
+// this pointer.
+//
+// Returns: NULL if the window cannot be created.
+//
+// Arguments: (none)
+//
+// History: 3-23-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+ULONG GetOleNotificationWnd()
+{
+ HWND hwndOleRpcNotify;
+ char achWindowName[24];
+
+ HRESULT hr;
+ COleTls tls(hr);
+ if (FAILED(hr))
+ {
+ return(NULL);
+ }
+
+ //
+ // First, check to see if the window already exists. If so,
+ // just return it.
+ //
+
+ if (tls->hwndOleRpcNotify != NULL)
+ {
+ return (ULONG)tls->hwndOleRpcNotify;
+ }
+
+ //
+ // Each thread gets its own window.
+ //
+
+ wsprintfA(achWindowName,"OleRpcNotify0x%08x",GetCurrentThreadId());
+
+ CairoleDebugOut((DEB_ENDPNT,
+ "GetOleRpcNotifyWnd() creating window %s\n",
+ achWindowName));
+
+ //
+ // Create a main window for this application instance.
+ //
+ // must use WS_POPUP so the window does not get assigned
+ // a hot key by user. Child windows don't get DDE
+ // broadcasts
+ //
+ tls->hwndOleRpcNotify = DllCreateWindowEx(
+ 0,
+ ptszOleMainThreadWndClass,
+ achWindowName,
+ (WS_DISABLED | WS_POPUP | WS_CHILD),
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ NULL,
+ NULL,
+ g_hinst,
+ NULL);
+ if (tls->hwndOleRpcNotify == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "GetOleRpcNotifyWnd Create(%s) has failed %x\n",
+ achWindowName, GetLastError()));
+
+ }
+
+ return (ULONG) tls->hwndOleRpcNotify;
+}
+//+---------------------------------------------------------------------------
+//
+// Method: OleNotificationProc
+//
+// Synopsis: the ole notification windows proc receives
+// messages send by other apps initialize e.g rpc
+//
+// Arguments: [wMsg] --
+// [wParam] -- notification enum type
+// [lParam] --
+//
+// Returns:
+//
+// History: 3-23-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(LRESULT) OleNotificationProc(UINT wMsg, WPARAM wParam, LPARAM lParam)
+{
+ CairoleDebugOut((DEB_ENDPNT, "OleNotificationProc: %x %lx\n", wParam, lParam));
+ CRpcService *pService = LocalService();
+
+ if (pService)
+ {
+ pService->Listen(TRUE);
+ }
+
+ CairoleDebugOut((DEB_ENDPNT, "OleNotificationProc done\n"));
+ return 0;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: NotifyToInitializeRpc
+//
+// Synopsis: Sends a notification message to another app. tp
+// initialize rpc completly
+//
+// Arguments: [hwnd] --
+//
+// Returns:
+//
+// History: 3-23-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL NotifyToInitializeRpc(HWND hwnd)
+{
+ CairoleDebugOut((DEB_ENDPNT, "NotifyToInitializeRpc() hwnd:%d\n", hwnd));
+ if (hwnd)
+ {
+ SSSendMessage(hwnd, WM_OLE_ORPC_NOTIFY, 0, 0L);
+ }
+ CairoleDebugOut((DEB_ENDPNT, "NotifyToInitializeRpc() done\n"));
+ return TRUE;
+}
diff --git a/private/ole32/com/remote/orpc_dbg.c b/private/ole32/com/remote/orpc_dbg.c
new file mode 100644
index 000000000..194634c1f
--- /dev/null
+++ b/private/ole32/com/remote/orpc_dbg.c
@@ -0,0 +1,644 @@
+//--------------------------------------------------------------------------
+// ORPC_DBG.C (tabs 4)
+//
+// !!!!!!!!! !!!!!!!!! NOTE NOTE NOTE NOTE !!!!!!!!! !!!!!!!!!!
+//
+// SEND MAIL TO SANJAYS IF YOU MODIFY THIS FILE!
+// WE MUST KEEP OLE AND LANGUAGES IN SYNC!
+//
+// !!!!!!!!! !!!!!!!!! NOTE NOTE NOTE NOTE !!!!!!!!! !!!!!!!!!!
+//
+// Created 08-Oct-1993 by Mike Morearty. The master copy of this file
+// is in the LANGAPI project owned by the Languages group.
+//
+// Helper functions for OLE RPC debugging.
+//--------------------------------------------------------------------------
+
+#include <windows.h>
+#ifndef _CHICAGO_
+#include <tchar.h>
+#endif
+
+#include "orpc_dbg.h"
+
+static TCHAR tszAeDebugName[] = TEXT("AeDebug");
+static TCHAR tszAutoName[] = TEXT("Auto");
+static TCHAR tszOldAutoName[] = TEXT("OldAuto");
+static TCHAR tszDebugObjectRpcEnabledName[] =
+#ifdef _CHICAGO_
+ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\DebugObjectRPCEnabled";
+#else
+ TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\DebugObjectRPCEnabled");
+#endif
+
+// Emit the ORPC signature into the bytestream of the function
+#define ORPC_EMIT_SIGNATURE() 'M', 'A', 'R', 'B',
+
+// Emit a LONG into the bytestream
+#define ORPC_EMIT_LONG(l) \
+ ((l >> 0) & 0xFF), \
+ ((l >> 8) & 0xFF), \
+ ((l >> 16) & 0xFF), \
+ ((l >> 24) & 0xFF),
+
+// Emit a WORD into the bytestream
+#define ORPC_EMIT_WORD(w) \
+ ((w >> 0) & 0xFF), \
+ ((w >> 8) & 0xFF),
+
+// Emit a BYTE into the bytestream
+#define ORPC_EMIT_BYTE(b) \
+ b,
+
+// Emit a GUID into the bytestream
+#define ORPC_EMIT_GUID(l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ ORPC_EMIT_LONG(l) \
+ ORPC_EMIT_WORD(w1) ORPC_EMIT_WORD(w2) \
+ ORPC_EMIT_BYTE(b1) ORPC_EMIT_BYTE(b2) \
+ ORPC_EMIT_BYTE(b3) ORPC_EMIT_BYTE(b4) \
+ ORPC_EMIT_BYTE(b5) ORPC_EMIT_BYTE(b6) \
+ ORPC_EMIT_BYTE(b7) ORPC_EMIT_BYTE(b8)
+
+BYTE rgbClientGetBufferSizeSignature[] =
+{
+ ORPC_EMIT_SIGNATURE()
+ ORPC_EMIT_GUID(0x9ED14F80, 0x9673, 0x101A, 0xB0, 0x7B,
+ 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x11)
+ ORPC_EMIT_LONG(0)
+};
+
+BYTE rgbClientFillBufferSignature[] =
+{
+ ORPC_EMIT_SIGNATURE()
+ ORPC_EMIT_GUID(0xDA45F3E0, 0x9673, 0x101A, 0xB0, 0x7B,
+ 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x11)
+ ORPC_EMIT_LONG(0)
+};
+
+BYTE rgbClientNotifySignature[] =
+{
+ ORPC_EMIT_SIGNATURE()
+ ORPC_EMIT_GUID(0x4F60E540, 0x9674, 0x101A, 0xB0, 0x7B,
+ 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x11)
+ ORPC_EMIT_LONG(0)
+};
+
+BYTE rgbServerNotifySignature[] =
+{
+ ORPC_EMIT_SIGNATURE()
+ ORPC_EMIT_GUID(0x1084FA00, 0x9674, 0x101A, 0xB0, 0x7B,
+ 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x11)
+ ORPC_EMIT_LONG(0)
+};
+
+BYTE rgbServerGetBufferSizeSignature[] =
+{
+ ORPC_EMIT_SIGNATURE()
+ ORPC_EMIT_GUID(0x22080240, 0x9674, 0x101A, 0xB0, 0x7B,
+ 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x11)
+ ORPC_EMIT_LONG(0)
+};
+
+BYTE rgbServerFillBufferSignature[] =
+{
+ ORPC_EMIT_SIGNATURE()
+ ORPC_EMIT_GUID(0x2FC09500, 0x9674, 0x101A, 0xB0, 0x7B,
+ 0x00, 0xDD, 0x01, 0x11, 0x3F, 0x11)
+ ORPC_EMIT_LONG(0)
+};
+
+// Macro to deal with assigning refiid for both C and C++.
+#if defined(__cplusplus)
+#define ASSIGN_REFIID(orpc_all, iid) ((orpc_all).refiid = &iid)
+#else
+#define ASSIGN_REFIID(orpc_all, iid) ((orpc_all).refiid = iid)
+#endif
+
+#pragma code_seg(".orpc")
+
+//--------------------------------------------------------------------------
+// SzSubStr()
+//
+// Find str2 in str2
+//--------------------------------------------------------------------------
+
+static LPTSTR SzSubStr(LPTSTR str1, LPTSTR str2)
+{
+ CharLower(str1);
+ CharLower(str2);
+
+#ifdef _CHICAGO_
+ return strstr(str1, str2);
+#else
+ return _tcsstr(str1, str2);
+#endif
+}
+
+//--------------------------------------------------------------------------
+// DebugORPCSetAuto()
+//
+// Sets the "Auto" value in the "AeDebug" key to "1", and saves info
+// necessary to restore the previous value later.
+//--------------------------------------------------------------------------
+
+BOOL WINAPI DebugORPCSetAuto(VOID)
+{
+ HKEY hkey;
+ TCHAR rgtchDebugger[256]; // 256 is the length NT itself uses for this
+ TCHAR rgtchAuto[256];
+ TCHAR rgtchOldAuto[2]; // don't need to get the whole thing
+
+ // If the "DebugObjectRPCEnabled" key does not exist, then do not
+ // cause any notifications
+ if (RegOpenKey(HKEY_LOCAL_MACHINE, tszDebugObjectRpcEnabledName, &hkey))
+ return FALSE;
+ RegCloseKey(hkey);
+
+ // If the AeDebug debugger string does not exist, or if it contains
+ // "drwtsn32" anywhere in it, then don't cause any notifications,
+ // because Dr. Watson is not capable of fielding OLE notifications.
+ if (!GetProfileString(tszAeDebugName, TEXT("Debugger"), TEXT(""),
+ rgtchDebugger, sizeof(rgtchDebugger)) ||
+ SzSubStr(rgtchDebugger, TEXT("drwtsn32")) != NULL)
+ {
+ return FALSE;
+ }
+
+ // Must ensure that the "Auto" value in the AeDebug registry key
+ // is set to "1", so that the embedded INT 3 below will cause the
+ // debugger to be automatically spawned if it doesn't already
+ // exist.
+
+ // Get old "Auto" value
+ GetProfileString(tszAeDebugName, tszAutoName, TEXT(""),
+ rgtchAuto, sizeof(rgtchAuto));
+
+ // If "OldAuto" already existed, then it's probably left over from
+ // a previous invocation of the debugger, so don't overwrite it.
+ // Otherwise, copy "Auto" value to "OldAuto"
+ if (!GetProfileString(tszAeDebugName, tszOldAutoName, TEXT(""),
+ rgtchOldAuto, sizeof(rgtchOldAuto)))
+ {
+ if (!WriteProfileString(tszAeDebugName, tszOldAutoName, rgtchAuto))
+ return FALSE;
+ }
+
+ // Change "Auto" value to "1"
+ if (!WriteProfileString(tszAeDebugName, tszAutoName, TEXT("1")))
+ return FALSE;
+
+ return TRUE;
+}
+
+//--------------------------------------------------------------------------
+// DebugORPCRestoreAuto()
+//
+// Restores the previous value of the "Auto" value in the AeDebug key.
+//--------------------------------------------------------------------------
+
+VOID WINAPI DebugORPCRestoreAuto(VOID)
+{
+ TCHAR rgtchAuto[256];
+
+ // Restore old Auto value (or delete it if it didn't exist before).
+ // Very minor bug here: if "Auto" was previously "", then we will
+ // now delete it. That's not a big deal though, as an empty "Auto"
+ // and a nonexistent one have the same effect.
+ GetProfileString(tszAeDebugName, tszOldAutoName, TEXT(""),
+ rgtchAuto, sizeof(rgtchAuto));
+
+ WriteProfileString(tszAeDebugName, tszAutoName,
+ rgtchAuto[0] ? rgtchAuto : NULL);
+
+ // Delete OldAuto value
+ WriteProfileString(tszAeDebugName, tszOldAutoName, NULL);
+}
+
+ // This pragma is necessary in case the compiler chooses not to inline these
+// functions (e.g. in a debug build, when optimizations are off).
+
+#pragma code_seg(".orpc")
+
+__inline DWORD WINAPI OrpcBreakpointFilter(
+ LPEXCEPTION_POINTERS lpExcptPtr,
+ BOOL *lpAeDebugAttached ) \
+{
+ BOOL fAeDebugAttached = FALSE;
+ DWORD dwRet;
+
+ if ( lpExcptPtr->ExceptionRecord->ExceptionCode == EXCEPTION_ORPC_DEBUG )
+ {
+ if ( UnhandledExceptionFilter(lpExcptPtr) == EXCEPTION_CONTINUE_SEARCH )
+ {
+ // It is important that we don't return EXCEPTION_CONTINUE_SEARCH.
+ // This is because there might an handler up the stack which could
+ // handle this exception. Just set the flag indicating that a
+ // debugger is now attached.
+
+ fAeDebugAttached = TRUE;
+ }
+ dwRet = EXCEPTION_EXECUTE_HANDLER;
+ }
+ else
+ {
+ // Not one of our exceptions.
+ dwRet = EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ if ( lpAeDebugAttached != NULL )
+ (*lpAeDebugAttached) = fAeDebugAttached;
+
+ return dwRet;
+}
+
+ULONG WINAPI DebugORPCClientGetBufferSize(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ void * reserved,
+ IUnknown * pUnkProxyMgr,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled)
+{
+ ULONG cbBuffer = 0;
+ ORPC_DBG_ALL orpc_all = {0};
+ ORPC_DBG_ALL * lpOrpcAll = &orpc_all;
+
+ if (!fHookEnabled)
+ return 0; // We should be able to assert that this never happens.
+
+ orpc_all.pSignature = rgbClientGetBufferSizeSignature;
+ orpc_all.pMessage = pMessage;
+ orpc_all.reserved = reserved;
+ orpc_all.pUnkProxyMgr = pUnkProxyMgr;
+ orpc_all.lpcbBuffer = &cbBuffer;
+ ASSIGN_REFIID(orpc_all, iid);
+
+ if ( lpInitArgs == NULL || lpInitArgs->lpIntfOrpcDebug == NULL )
+ {
+ // Do Orpc debug notification using an exception.
+ __try
+ {
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+ __except(OrpcBreakpointFilter(GetExceptionInformation(), NULL))
+ {
+ // this just goes down to the to the return.
+ }
+ }
+ else
+ {
+ IOrpcDebugNotify __RPC_FAR *lpIntf = lpInitArgs->lpIntfOrpcDebug;
+
+ // call the appropriate method in the registered interface
+ // ( this is typically used by in-proc debuggers)
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ lpIntf->ClientGetBufferSize(lpOrpcAll);
+#else
+ lpIntf->lpVtbl->ClientGetBufferSize(lpIntf, lpOrpcAll);
+#endif
+
+ }
+
+ return cbBuffer;
+}
+
+//--------------------------------------------------------------------------
+
+void WINAPI DebugORPCClientFillBuffer(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ void * reserved,
+ IUnknown * pUnkProxyMgr,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled)
+{
+ ORPC_DBG_ALL orpc_all = {0};
+ ORPC_DBG_ALL * lpOrpcAll = &orpc_all;
+
+ if (!fHookEnabled)
+ return; // We should be able to assert that this never happens
+
+ orpc_all.pSignature = rgbClientFillBufferSignature;
+
+ orpc_all.pMessage = pMessage;
+ orpc_all.reserved = reserved;
+ orpc_all.pUnkProxyMgr = pUnkProxyMgr;
+ ASSIGN_REFIID(orpc_all, iid);
+
+ orpc_all.pvBuffer = pvBuffer;
+ orpc_all.cbBuffer = cbBuffer;
+
+
+ if ( lpInitArgs == NULL || lpInitArgs->lpIntfOrpcDebug == NULL )
+ {
+ // Do Orpc debug notification using an exception.
+ __try
+ {
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+ __except(OrpcBreakpointFilter(GetExceptionInformation(), NULL))
+ {
+ // this just returns.
+ }
+ }
+ else
+ {
+ IOrpcDebugNotify __RPC_FAR *lpIntf = lpInitArgs->lpIntfOrpcDebug;
+
+ // call the appropriate method in the registered interface
+ // ( this is typically used by in-proc debuggers)
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ lpIntf->ClientFillBuffer(lpOrpcAll);
+#else
+ lpIntf->lpVtbl->ClientFillBuffer(lpIntf, lpOrpcAll);
+#endif
+ }
+}
+
+//--------------------------------------------------------------------------
+
+// This special value is to ensure backward compatibility with VC 2.0.
+// It is not exposed in the header files. The behavior if this is the value
+// in the first four bytes of the debug packet, should be identical to
+// ORPC_DEBUG_ALWAYS.
+
+#define ORPC_COMPATIBILITY_CODE (0x4252414DL)
+
+void WINAPI DebugORPCClientNotify(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ void * reserved,
+ IUnknown * pUnkProxyMgr,
+ HRESULT hresult,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled)
+{
+ ORPC_DBG_ALL orpc_all = {0};
+ ORPC_DBG_ALL * lpOrpcAll = &orpc_all;
+ BOOL fRethrow = FALSE;
+
+ // First check to see if the debugger on the other side
+ // wants us to notify this side if the hook is not enabled.
+ if (!fHookEnabled)
+ {
+ if (cbBuffer >= 4)
+ {
+ LONG orpcCode = *(LONG *)pvBuffer;
+ if ( orpcCode == ORPC_DEBUG_IF_HOOK_ENABLED)
+ return; // No notification in this case.
+ }
+ }
+
+ orpc_all.pSignature = rgbClientNotifySignature;
+
+ orpc_all.pMessage = pMessage;
+ orpc_all.reserved = reserved;
+ orpc_all.pUnkProxyMgr = pUnkProxyMgr;
+ orpc_all.hresult = hresult;
+ ASSIGN_REFIID(orpc_all, iid);
+
+ orpc_all.pvBuffer = pvBuffer;
+ orpc_all.cbBuffer = cbBuffer;
+
+ if ( lpInitArgs == NULL || lpInitArgs->lpIntfOrpcDebug == NULL )
+ {
+ if (DebugORPCSetAuto())
+ {
+ // Do Orpc debug notification using an exception.
+ __try
+ {
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+ __except(OrpcBreakpointFilter(GetExceptionInformation(), &fRethrow))
+ {
+ // Fall through.
+ }
+
+ if (fRethrow)
+ {
+ // At this point we are sure that a debugger is attached
+ // so we raise this exception outside of a __try block.
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+
+ DebugORPCRestoreAuto();
+ }
+
+ }
+ else
+ {
+ IOrpcDebugNotify __RPC_FAR *lpIntf = lpInitArgs->lpIntfOrpcDebug;
+
+ // call the appropriate method in the registered interface
+ // ( this is typically used by in-proc debuggers)
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ lpIntf->ClientNotify(lpOrpcAll);
+#else
+ lpIntf->lpVtbl->ClientNotify(lpIntf, lpOrpcAll);
+#endif
+ }
+
+}
+
+//--------------------------------------------------------------------------
+
+void WINAPI DebugORPCServerNotify(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ IRpcChannelBuffer * pChannel,
+ void * pInterface,
+ IUnknown * pUnkObject,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled)
+
+{
+ ORPC_DBG_ALL orpc_all = {0};
+ ORPC_DBG_ALL * lpOrpcAll = &orpc_all;
+ BOOL fRethrow = FALSE;
+
+ // First check to see if the debugger on the other side
+ // wants us to notify this side if the hook is not enabled.
+ if (!fHookEnabled)
+ {
+ if (cbBuffer >= 4)
+ {
+ LONG orpcCode = *(LONG *)pvBuffer;
+ if ( orpcCode == ORPC_DEBUG_IF_HOOK_ENABLED)
+ return; // No notification in this case.
+ }
+ }
+
+ orpc_all.pSignature = rgbServerNotifySignature;
+
+ orpc_all.pMessage = pMessage;
+ orpc_all.pChannel = pChannel;
+ orpc_all.pInterface = pInterface;
+ orpc_all.pUnkObject = pUnkObject;
+ ASSIGN_REFIID(orpc_all, iid);
+
+ orpc_all.pvBuffer = pvBuffer;
+ orpc_all.cbBuffer = cbBuffer;
+
+ if ( lpInitArgs == NULL || lpInitArgs->lpIntfOrpcDebug == NULL )
+ {
+ if (DebugORPCSetAuto())
+ {
+ // Do Orpc debug notification using an exception.
+ __try
+ {
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+ __except(OrpcBreakpointFilter(GetExceptionInformation(), &fRethrow))
+ {
+ // Fall through
+ }
+
+ if (fRethrow)
+ {
+ // At this point we are sure that a debugger is attached
+ // so we raise this exception outside of a __try block.
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+
+ DebugORPCRestoreAuto();
+ }
+
+ }
+ else
+ {
+ IOrpcDebugNotify __RPC_FAR *lpIntf = lpInitArgs->lpIntfOrpcDebug;
+
+ // call the appropriate method in the registered interface
+ // ( this is typically used by in-proc debuggers)
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ lpIntf->ServerNotify(lpOrpcAll);
+#else
+ lpIntf->lpVtbl->ServerNotify(lpIntf, lpOrpcAll);
+#endif
+ }
+
+}
+
+//--------------------------------------------------------------------------
+
+ULONG WINAPI DebugORPCServerGetBufferSize(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ IRpcChannelBuffer * pChannel,
+ void * pInterface,
+ IUnknown * pUnkObject,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled)
+
+{
+ ULONG cbBuffer = 0;
+ ORPC_DBG_ALL orpc_all = {0};
+ ORPC_DBG_ALL * lpOrpcAll = &orpc_all;
+
+ if (!fHookEnabled)
+ return 0; // We should be able to assert that this never happens.
+
+ orpc_all.pSignature = rgbServerGetBufferSizeSignature;
+
+ orpc_all.pMessage = pMessage;
+ orpc_all.pChannel = pChannel;
+ orpc_all.pInterface = pInterface;
+ orpc_all.pUnkObject = pUnkObject;
+ orpc_all.lpcbBuffer = &cbBuffer;
+ ASSIGN_REFIID(orpc_all, iid);
+
+ if ( lpInitArgs == NULL || lpInitArgs->lpIntfOrpcDebug == NULL )
+ {
+ // Do Orpc debug notification using an exception.
+ __try
+ {
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+ __except(OrpcBreakpointFilter(GetExceptionInformation(), NULL))
+ {
+ // this just goes down to the return.
+ }
+ }
+ else
+ {
+ IOrpcDebugNotify __RPC_FAR *lpIntf = lpInitArgs->lpIntfOrpcDebug;
+
+ // call the appropriate method in the registered interface
+ // ( this is typically used by in-proc debuggers)
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ lpIntf->ServerGetBufferSize(lpOrpcAll);
+#else
+ lpIntf->lpVtbl->ServerGetBufferSize(lpIntf, lpOrpcAll);
+#endif
+ }
+
+ return cbBuffer;
+}
+
+//--------------------------------------------------------------------------
+
+void WINAPI DebugORPCServerFillBuffer(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ IRpcChannelBuffer * pChannel,
+ void * pInterface,
+ IUnknown * pUnkObject,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled)
+{
+ ORPC_DBG_ALL orpc_all = {0};
+ ORPC_DBG_ALL * lpOrpcAll = &orpc_all;
+
+ if (!fHookEnabled)
+ return; // We should be able to assert that this never happens.
+
+ orpc_all.pSignature = rgbServerFillBufferSignature;
+
+ orpc_all.pMessage = pMessage;
+ orpc_all.pChannel = pChannel;
+ orpc_all.pInterface = pInterface;
+ orpc_all.pUnkObject = pUnkObject;
+ ASSIGN_REFIID(orpc_all, iid);
+
+ orpc_all.pvBuffer = pvBuffer;
+ orpc_all.cbBuffer = cbBuffer;
+
+ if ( lpInitArgs == NULL || lpInitArgs->lpIntfOrpcDebug == NULL )
+ {
+ // Do Orpc debug notification using an exception.
+ __try
+ {
+ RaiseException(EXCEPTION_ORPC_DEBUG, 0, 1, (LPDWORD)&lpOrpcAll);
+ }
+ __except(OrpcBreakpointFilter(GetExceptionInformation(), NULL))
+ {
+ // this just returns.
+ }
+ }
+ else
+ {
+ IOrpcDebugNotify __RPC_FAR *lpIntf = lpInitArgs->lpIntfOrpcDebug;
+
+ // call the appropriate method in the registered interface
+ // ( this is typically used by in-proc debuggers)
+#if defined(__cplusplus) && !defined(CINTERFACE)
+ lpIntf->ServerFillBuffer(lpOrpcAll);
+#else
+ lpIntf->lpVtbl->ServerFillBuffer(lpIntf, lpOrpcAll);
+#endif
+ }
+}
+
+// WARNING: there is no way to "pop" to the previously active code_seg:
+// this will revert to what the code seg was when compilation began.
+#pragma code_seg()
+
+
diff --git a/private/ole32/com/remote/orpc_dbg.h b/private/ole32/com/remote/orpc_dbg.h
new file mode 100644
index 000000000..62b512df7
--- /dev/null
+++ b/private/ole32/com/remote/orpc_dbg.h
@@ -0,0 +1,219 @@
+//--------------------------------------------------------------------------
+// ORPC_DBG.H (tabs 4)
+//
+// !!!!!!!!! !!!!!!!!! NOTE NOTE NOTE NOTE !!!!!!!!! !!!!!!!!!!
+//
+// SEND MAIL TO SANJAYS IF YOU MODIFY THIS FILE!
+// WE MUST KEEP OLE AND LANGUAGES IN SYNC!
+//
+// !!!!!!!!! !!!!!!!!! NOTE NOTE NOTE NOTE !!!!!!!!! !!!!!!!!!!
+//
+// Created 07-Oct-1993 by Mike Morearty. The master copy of this file
+// is in the LANGAPI project owned by the Languages group.
+//
+// Macros and functions for OLE RPC debugging. For a detailed explanation,
+// see OLE2DBG.DOC.
+//
+//--------------------------------------------------------------------------
+
+
+#ifndef __ORPC_DBG__
+#define __ORPC_DBG__
+
+//--------------------------------------------------------------------------
+// Public:
+//--------------------------------------------------------------------------
+
+// This structure is the information packet which OLE sends the debugger
+// when it is notifying it about an OLE debug event. The first field in this
+// structure points to the signature which identifies the type of the debug
+// notification. The consumer of the notification can then get the relevant
+// information from the struct members. Note that for each OLE debug notification
+// only a subset of the struct members are meaningful.
+
+
+typedef struct ORPC_DBG_ALL
+{
+ BYTE * pSignature;
+ RPCOLEMESSAGE * pMessage;
+ const IID * refiid;
+ IRpcChannelBuffer * pChannel;
+ IUnknown * pUnkProxyMgr;
+ void * pInterface;
+ IUnknown * pUnkObject;
+ HRESULT hresult;
+ void * pvBuffer;
+ ULONG cbBuffer;
+ ULONG * lpcbBuffer;
+ void * reserved;
+} ORPC_DBG_ALL;
+
+typedef ORPC_DBG_ALL __RPC_FAR *LPORPC_DBG_ALL;
+
+// Interface definition for IOrpcDebugNotify
+
+typedef interface IOrpcDebugNotify IOrpcDebugNotify;
+
+typedef IOrpcDebugNotify __RPC_FAR * LPORPCDEBUGNOTIFY;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOrpcDebugNotify : public IUnknown
+ {
+ public:
+ virtual VOID __stdcall ClientGetBufferSize (LPORPC_DBG_ALL) = 0;
+ virtual VOID __stdcall ClientFillBuffer (LPORPC_DBG_ALL) = 0;
+ virtual VOID __stdcall ClientNotify (LPORPC_DBG_ALL) = 0;
+ virtual VOID __stdcall ServerNotify (LPORPC_DBG_ALL) = 0;
+ virtual VOID __stdcall ServerGetBufferSize (LPORPC_DBG_ALL) = 0;
+ virtual VOID __stdcall ServerFillBuffer (LPORPC_DBG_ALL) = 0;
+ };
+
+#else /* C style interface */
+
+ typedef struct IOrpcDebugNotifyVtbl
+ {
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOrpcDebugNotify __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOrpcDebugNotify __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOrpcDebugNotify __RPC_FAR * This);
+
+ VOID ( __stdcall __RPC_FAR *ClientGetBufferSize)(
+ IOrpcDebugNotify __RPC_FAR * This,
+ LPORPC_DBG_ALL lpOrpcDebugAll);
+
+ VOID ( __stdcall __RPC_FAR *ClientFillBuffer)(
+ IOrpcDebugNotify __RPC_FAR * This,
+ LPORPC_DBG_ALL lpOrpcDebugAll);
+
+ VOID ( __stdcall __RPC_FAR *ClientNotify)(
+ IOrpcDebugNotify __RPC_FAR * This,
+ LPORPC_DBG_ALL lpOrpcDebugAll);
+
+ VOID ( __stdcall __RPC_FAR *ServerNotify)(
+ IOrpcDebugNotify __RPC_FAR * This,
+ LPORPC_DBG_ALL lpOrpcDebugAll);
+
+ VOID ( __stdcall __RPC_FAR *ServerGetBufferSize)(
+ IOrpcDebugNotify __RPC_FAR * This,
+ LPORPC_DBG_ALL lpOrpcDebugAll);
+
+ VOID ( __stdcall __RPC_FAR *ServerFillBuffer)(
+ IOrpcDebugNotify __RPC_FAR * This,
+ LPORPC_DBG_ALL lpOrpcDebugAll);
+
+ } IOrpcDebugNotifyVtbl;
+
+ interface IOrpcDebugNotify
+ {
+ CONST_VTBL struct IOrpcDebugNotifyVtbl __RPC_FAR *lpVtbl;
+ };
+
+#endif
+
+// This is the structure that is passed by the debugger to OLE when it enables ORPC
+// debugging.
+typedef struct ORPC_INIT_ARGS
+{
+ IOrpcDebugNotify __RPC_FAR * lpIntfOrpcDebug;
+ void * pvPSN; // contains ptr to Process Serial No. for Mac ORPC debugging.
+ DWORD dwReserved1; // For future use, must be 0.
+ DWORD dwReserved2;
+} ORPC_INIT_ARGS;
+
+typedef ORPC_INIT_ARGS __RPC_FAR * LPORPC_INIT_ARGS;
+
+// Function pointer prototype for the "DllDebugObjectRPCHook" function.
+typedef BOOL (WINAPI* ORPCHOOKPROC)(BOOL, LPORPC_INIT_ARGS);
+
+// The first four bytes in the debug specific packet are interpreted by the
+// ORPC debug layer. The valid values are the ones defined below.
+
+#define ORPC_DEBUG_ALWAYS (0x00000000L) // Notify always.
+#define ORPC_DEBUG_IF_HOOK_ENABLED (0x00000001L) // Notify only if hook enabled.
+
+
+// This exception code indicates that the exception is really an
+// ORPC debug notification.
+
+#define EXCEPTION_ORPC_DEBUG (0x804f4c45)
+
+
+//--------------------------------------------------------------------------------------
+// Private: Declarations below this point are related to the implementation and should
+// be removed from the distributable version of the header file.
+//--------------------------------------------------------------------------------------
+
+
+// Helper routines to set & restore the "Auto" value in the registry
+
+BOOL WINAPI DebugORPCSetAuto(VOID);
+VOID WINAPI DebugORPCRestoreAuto(VOID);
+
+ ULONG WINAPI DebugORPCClientGetBufferSize(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ void * reserved,
+ IUnknown * pUnkProxyMgr,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled);
+
+void WINAPI DebugORPCClientFillBuffer(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ void * reserved,
+ IUnknown * pUnkProxyMgr,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled);
+
+void WINAPI DebugORPCClientNotify(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ void * reserved,
+ IUnknown * pUnkProxyMgr,
+ HRESULT hresult,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled);
+
+void WINAPI DebugORPCServerNotify(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ IRpcChannelBuffer * pChannel,
+ void * pInterface,
+ IUnknown * pUnkObject,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled);
+
+ULONG WINAPI DebugORPCServerGetBufferSize(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ IRpcChannelBuffer * pChannel,
+ void * pInterface,
+ IUnknown * pUnkObject,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled);
+
+void WINAPI DebugORPCServerFillBuffer(
+ RPCOLEMESSAGE * pMessage,
+ REFIID iid,
+ IRpcChannelBuffer * pChannel,
+ void * pInterface,
+ IUnknown * pUnkObject,
+ void * pvBuffer,
+ ULONG cbBuffer,
+ LPORPC_INIT_ARGS lpInitArgs,
+ BOOL fHookEnabled);
+
+#endif // __ORPC_DBG__
diff --git a/private/ole32/com/remote/remhdlr.cxx b/private/ole32/com/remote/remhdlr.cxx
new file mode 100644
index 000000000..d399c8a04
--- /dev/null
+++ b/private/ole32/com/remote/remhdlr.cxx
@@ -0,0 +1,1645 @@
+//+-------------------------------------------------------------------
+//
+// File: remhdlr.cxx
+//
+// Contents: remote object handler implementation
+//
+// Classes: CRemoteHdlr - remote object handler
+// CPSIX - proxy/stub interface wrapper
+//
+// History: 23-Nov-92 Rickhi Created
+// 05-Jul-94 BruceMa Check for end of stream
+//
+//--------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include <scm.h> // Get internal CLSCTX.
+
+#include <remhdlr.hxx> // CRemoteHdlr
+
+COleStaticMutexSem CRemoteHdlr::_mxs; // global mutext semaphore
+
+
+#pragma warning(disable:4355) // 'this' used in base member init list
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::CRemoteHdlr, public
+//
+// Synopsis: constructor for the remote handler object
+//
+// History: 23-Nov-93 Rickhi Created
+// 01-Aug-94 Alexgo Allocate the ChannelBuffer and
+// return failure if E_OUTOFMEMORY
+//
+//--------------------------------------------------------------------
+
+CRemoteHdlr::CRemoteHdlr(IUnknown *punkObj, // object ptr
+ IStdIdentity *pStdID, // identity
+ DWORD dwFlags, // flags
+ HRESULT &hr) // return code
+ : _punkObj(punkObj),
+ _pstdID(pStdID),
+ _dwFlags(dwFlags),
+ _cReferences(1),
+ _cCallsInProgress(0),
+ _pChannel(NULL)
+{
+ Win4Assert(IsValidInterface(_punkObj));
+
+ // create an Rpc Channel for this object. we need to tell it if this is
+ // for a local object, or a remote object, so that the channel can point
+ // to the correct service object.
+
+ _pChannel = new CRpcChannelBuffer(this, NULL, 0, NULL,
+ IS_LOCAL_RH ? disconnected_cs : client_cs);
+ if (_pChannel == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ return;
+ }
+
+ if (IS_LOCAL_RH)
+ {
+ // we (now) addref this as long as we hold its value; disconnect
+ // is the only place that releases it and set it to NULL; many places
+ // check for NULL.
+ _punkObj->AddRef();
+ }
+
+ hr = S_OK;
+ AssertValid();
+
+ CairoleDebugOut((DEB_MARSHAL,
+ "New CRemoteHdlr pRH:%x pChannel:%x\n",
+ this, _pChannel));
+}
+#pragma warning(default:4355) // 'this' used in base member init list
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::QueryInterface, public
+//
+// Synopsis: returns internally supported interfaces
+//
+// Exceptions: CException if input parameters are bad or
+// cant create the interface proxy.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Notes: IUnknown and IMarshal are always private interfaces when
+// this object is aggregated, hence QI, AddRef, Release do not
+// get forwarded to the controlling unknown.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRemoteHdlr::QueryInterface(REFIID riid, void **ppv)
+{
+ HRESULT sc = S_OK;
+
+ AssertValid();
+
+ if (IsEqualIID(riid, IID_IMarshal) || // more common than IUnknown
+ IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppv = (IMarshal *) this;
+ AddRef();
+ }
+ else if (IsEqualIID(riid, IID_IRemoteHdlr))
+ {
+ *ppv = (IRemoteHdlr *) this;
+ AddRef();
+ }
+ else
+ {
+ // don't expect this on the local side.
+ Assert(!IS_LOCAL_RH);
+
+ // find or create the interface we are looking for, and AddRef it
+
+ // BUGBUG: we probably want to stablize this QI here per new rules
+ // i.e., _pUnkObj->AddRef(), Release() around the FindIX call.
+
+ // call sets ppv and sc per normal rules (e.g., *ppv == NULL on error).
+ (void)FindIX(riid, ppv, FLG_QUERYINTERFACE, &sc);
+ }
+
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::AddRef, public
+//
+// Synopsis: increments the reference count on the object.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CRemoteHdlr::AddRef(void)
+{
+ AssertValid();
+
+ return InterlockedAddRef(&_cReferences);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::Release, public
+//
+// Synopsis: decrements the reference count and deletes the object if
+// it reaches zero.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CRemoteHdlr::Release(void)
+{
+ DWORD refs;
+ AssertValid();
+
+ if ((refs = InterlockedRelease(&_cReferences)) == 0)
+ {
+ delete this;
+ return 0;
+ }
+
+ return refs;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::GetChannel, public
+//
+// Synopsis: Returns the channel; DBG only.
+//
+// History: 06-Jan-94 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(IRpcChannelBuffer *) CRemoteHdlr::GetChannel(BOOL fAddRef)
+{
+#if DBG == 1
+ // can't call AssertValid() since it is used by the service object asserts
+
+ // don't support fAddRef yet because the channel object is part of the RH
+ Assert(!fAddRef);
+
+ return _pChannel;
+#else // !DBG
+ return 0;
+#endif
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::LockClient, public
+//
+// Synopsis: prevents the client RH, and hence all attached proxies and
+// channels, from vanishing during an Rpc call. We hold
+// pUnkOuter of the aggregate and the whole aggregate must
+// persist if any piece of it does.
+//
+// NOTE: nothing is done on the server side; the server side
+// channel addref's the RH for the duration of the connection.
+// We can't do that on the client side since the pointer
+// from the channel to the RH is a back pointer (which are
+// not normally addref'd and further more the channel is embedded
+// in the RH and thus its ref count is not too meaningful).
+//
+// CODEWORK: since this is really only interesting on the client side,
+// we can make this much simpler if the channel was an independent object
+// (by just addref'ing the channel object only).
+//
+// History: 23-Nov-93 Rickhi Created
+// 21-Dec-93 CraigWi Distinguish between local and remote
+// 7-Apr-94 CraigWi Only works remotely now
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CRemoteHdlr::LockClient(void)
+{
+ AssertValid();
+
+ if (!IS_LOCAL_RH && _punkObj != NULL)
+ {
+ InterlockedIncrement(&_cCallsInProgress);
+ return _punkObj->AddRef();
+ }
+ else
+ return 0;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::UnLockClient, public
+//
+// Synopsis: See LockClient() above.
+//
+// History: 23-Nov-93 Rickhi Created
+// 21-Dec-93 CraigWi Distinguish between local and remote
+// 7-Apr-94 CraigWi Only works remotely now
+//
+// Note: Special magic that was required in the past is not longer
+// necessary since the RH is never has non-addref'd pointers
+// to it. This complexity is now in the identity object.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CRemoteHdlr::UnLockClient(void)
+{
+ AssertValid();
+
+ if (!IS_LOCAL_RH && _punkObj != NULL)
+ {
+ if ((InterlockedDecrement(&_cCallsInProgress) == 0) &&
+ _dwFlags & RHFLAGS_PENDINGDISCONNECT)
+ {
+ // disconnect was pending, now do the real disconnect
+ DisconnectObject(0);
+ }
+ return _punkObj->Release();
+ }
+ else
+ return 0;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::ClearIdentity, public
+//
+// Synopsis: Clears the _pstdID during identity destruction.
+//
+// History: 21-Dec-93 CraigWi Created
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(void) CRemoteHdlr::ClearIdentity(void)
+{
+ AssertValid();
+
+ // don't clear this on the client side since we may need it again
+ if (IS_LOCAL_RH)
+ _pstdID = NULL;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::DoesSupportIID, public
+//
+// Synopsis: returns TRUE if the interface is supported; works
+// on both client and server sides.
+//
+// Arguments: [riid] -- The iid in question
+//
+// History: 13-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(BOOL) CRemoteHdlr::DoesSupportIID(REFIID riid)
+{
+ HRESULT hr;
+ AssertValid();
+
+ return FindIX(riid, NULL, IS_LOCAL_RH ? FLG_MARSHAL : FLG_QUERYINTERFACE, &hr) != NULL;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::AddConnection, private
+//
+// Synopsis: forwards call to identity object
+//
+// History: 23-Nov-93 Rickhi Created
+// 21-Dec-93 CraigWi Changed to handle weak as well
+// 20-Apr-94 CraigWi Change to forward to id object
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRemoteHdlr::AddConnection(DWORD extconn, DWORD reserved)
+{
+ AssertValid();
+
+ if (_pstdID != NULL)
+ return _pstdID->AddConnection(extconn, reserved);
+ else
+ return CO_E_OBJNOTCONNECTED;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::ReleaseConnection, private
+//
+// Synopsis: records the removal of a connection (weak or strong)
+//
+// History: 23-Nov-93 Rickhi Created
+// 21-Dec-93 CraigWi Changed to handle weak as well
+// 20-Apr-94 CraigWi Change to forward to id object
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRemoteHdlr::ReleaseConnection(DWORD extconn,
+ DWORD reserved, BOOL fLastReleaseCloses)
+{
+ AssertValid();
+
+ if (_pstdID != NULL)
+ return _pstdID->ReleaseConnection(extconn, reserved,fLastReleaseCloses);
+ else
+ return CO_E_OBJNOTCONNECTED;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::IsConnected, private
+//
+// Synopsis: Returns TRUE if most likely connected; FALSE if definitely
+// not connected. If returns FALSE, cleans up.
+//
+// History: 14-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(BOOL) CRemoteHdlr::IsConnected(void)
+{
+ AssertValid();
+ Assert(!IS_LOCAL_RH);
+
+ if (_pChannel->IsConnected() == S_OK)
+ {
+ return TRUE;
+ }
+ else
+ {
+ // clean up our data (channel already did)
+ _IXList.DisconnectProxies();
+
+ // BUGBUG: not sure about the fMustBeOnCOMThread setting
+ _pChannel->AssertValid(TRUE, FALSE); // known disconnected
+ return FALSE;
+ }
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::Disconnect, private
+//
+// Synopsis: same as IMarshal::Disconnect(0); this method is
+// present for the convenience of the identity object.
+//
+// History: 14-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(void) CRemoteHdlr::Disconnect(void)
+{
+ AssertValid();
+ Assert(!IS_LOCAL_RH);
+
+ DisconnectObject(0);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::LockConnection, private
+//
+// Synopsis: pass through to channel
+//
+// History: 14-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRemoteHdlr::LockConnection(BOOL fLock, BOOL fLastUnlockReleases)
+{
+ AssertValid();
+ Assert(!IS_LOCAL_RH);
+
+ return _pChannel->LockObjectConnection(fLock, fLastUnlockReleases);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::GetUnmarshalClass, public
+//
+// Synopsis: returns the class of the code used to unmarshal this
+// object
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRemoteHdlr::GetUnmarshalClass(REFIID riid, void *pv,
+ DWORD dwDestCtx, void *pvDestCtx,
+ DWORD mshlflags, LPCLSID pClassid)
+{
+ AssertValid();
+
+ *pClassid = CLSID_StdMarshal;
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::GetMarshalSizeMax, public
+//
+// Synopsis: returns the maximum sized buffer needed to marshal this
+// object
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRemoteHdlr::GetMarshalSizeMax(REFIID riid, void *pv,
+ DWORD dwDestCtx, void *pvDestCtx,
+ DWORD mshlflags, DWORD *pSize)
+{
+ AssertValid();
+
+ // get the size that the channel needs
+ HRESULT sc = _pChannel->GetMarshalSizeMax(riid, pv, dwDestCtx,
+ pvDestCtx, mshlflags, pSize);
+
+ // add in the size the handler needs (assume clsid Channel)
+#ifdef CODEWORK
+ *pSize += sizeof(SHandlerDataHdr) + sizeof(CLSID);
+#else
+ *pSize += sizeof(SHandlerDataHdr);
+#endif
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::MarshalInterface, public
+//
+// Synopsis: marshalls the specified interface into the given stream
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Note: The format of the data is {SHandlerDataHdr,<channel Data>}
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRemoteHdlr::MarshalInterface(IStream *pStm, REFIID riid, void *pv,
+ DWORD dwDestCtx, void *pvDestCtx, DWORD mshlflags)
+
+{
+ TRACECALL(TRACE_MARSHAL, "CRemoteHdlr::MarshalInterface");
+
+ AssertValid();
+
+ SHandlerDataHdr hdh;
+ HRESULT sc = E_NOINTERFACE;
+
+ // make sure we have a stub setup for this interface. we check for
+ // IUnknown specially because there is no proxy/stub for it, it is
+ // handled by us directly.
+
+ // BUGBUG: This call to FindIX is kind of strange for the client side;
+ // the riid should already exist; if it doesn't (e.g., we weren't pass
+ // such a pointer), we will assert in CreateInterfaceStub and then
+ // proceed to create a stub on the remote side!!
+
+ if (IsEqualIID(IID_IUnknown, riid) || FindIX(riid, NULL, FLG_MARSHAL, &sc))
+ {
+#ifdef CODEWORK
+ // get the channel classid
+ CLSID clsidChannel;
+
+ sc = _pChannel->GetUnmarshalClass(riid, pv, dwDestCtx, pvDestCtx,
+ mshlflags, &clsidChannel);
+ if (FAILED(sc))
+ return sc;
+
+ if (clsidChannel == CLSID_StdChannel)
+ set bit in hdh.dwflags;
+#else
+ // since we are single channel, we always have the same clsid; verify
+#if DBG == 1
+ CLSID clsidChannel;
+ sc = _pChannel->GetUnmarshalClass(riid, pv, dwDestCtx, pvDestCtx,
+ mshlflags, &clsidChannel);
+ Assert(sc == NOERROR && IsEqualGUID(clsidChannel, CLSID_RpcChannelBuffer));
+#endif
+#endif
+
+ // store the marshal flags. these are needed for unmarshal and
+ // release data in order to adjust the reference counts
+ // appropriately.
+
+ hdh.dwflags = (mshlflags & HDLRFLAGS_TABLE) | HDLRFLAGS_STDRPCCHNL;
+
+ // store the interface iid in the data
+ memcpy(&hdh.iid, &riid, sizeof(hdh.iid));
+
+ // write the interface header into the stream
+ sc = pStm->Write(&hdh, sizeof(hdh), NULL);
+
+ if (SUCCEEDED(sc))
+ {
+ // now marshal the channel data
+ sc = _pChannel->MarshalInterface(pStm, riid, pv, dwDestCtx,
+ pvDestCtx, mshlflags);
+ }
+ }
+
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::UnmarshalInterface, public
+//
+// Synopsis: reads the SHandlerDataHdr from the stream, locates or
+// creates the appropriate handler for this object, and
+// passes the work off to that handler.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRemoteHdlr::UnmarshalInterface(
+ IStream *pStm,
+ REFIID riid,
+ void **ppv)
+{
+ TRACECALL(TRACE_MARSHAL, "CRemoteHdlr::UnmarshalInterface");
+
+ AssertValid();
+
+ // read the object data from the stream, and ensure
+ // that this object has not already been released.
+
+ SHandlerDataHdr hdh;
+ CLSID clsidChannel;
+ HRESULT sc = StRead(pStm, &hdh, sizeof(hdh));
+
+ // deal with channel clsid (probably pass to Unmarshal below)
+ if (SUCCEEDED(sc) && (hdh.dwflags & HDLRFLAGS_STDRPCCHNL) == 0)
+ sc = StRead(pStm, &clsidChannel, sizeof(clsidChannel));
+
+#ifdef CODEWORK
+ must use clsidChannel
+#else
+ // single channel; just verify clsid
+ Assert((hdh.dwflags & HDLRFLAGS_STDRPCCHNL) != 0 ||
+ IsEqualGUID(clsidChannel, CLSID_RpcChannelBuffer));
+#endif
+
+ // deal with extension
+ if (hdh.dwflags & HDLRFLAGS_EXTENSION)
+ SkipMarshalExtension(pStm);
+
+ if (SUCCEEDED(sc))
+ {
+ // ask helper routine to do the rest of the work
+ sc = Unmarshal(pStm, riid, hdh, ppv);
+ }
+
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::Unmarshal, private
+//
+// Parameters: [pStm] - stream to unmarshal data from
+//
+// Synopsis: does the unmarshalling for a particular handler. asks
+// the channel to unmarshal his part, finds or creates
+// the appropriate interfaces, and tweaks the reference
+// counts.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// CODEWORK: merge into ::UnmarshalInterface above. The reasons for
+// this routine being separate have gone.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRemoteHdlr::Unmarshal(
+ IStream *pStm,
+ REFIID riid,
+ SHandlerDataHdr &hdh,
+ void **ppv)
+{
+ // CODEWORK: fix for multiple channels
+ Assert(hdh.dwflags & HDLRFLAGS_STDRPCCHNL);
+
+ // unmarshal the channel data; KLUDGE: don't care about iid/ppv;
+ // we certainly don't want to pass the riid/ppv from above.
+ // CODEWORK: will probably change this when we lookup channel based on
+ // destination context.
+ HRESULT sc = _pChannel->UnmarshalInterface(pStm, IID_NULL, NULL);
+
+ if (SUCCEEDED(sc))
+ {
+ if (sc == CHAN_S_RECONNECT)
+ {
+ // connect proxies
+ _dwFlags &= ~RHFLAGS_DISCONNECTED; // no longer disconnected
+ _IXList.ConnectProxies(_pChannel);
+ }
+
+ sc = S_OK; // don't want to propagate random success codes
+
+ // look for the interface that was actually marshalled by the
+ // other side. if not present, create an interface proxy for it.
+
+ CPSIX *pIX = NULL;
+ if (!IsEqualIID(IID_IUnknown, hdh.iid))
+ {
+ pIX = FindIX(hdh.iid, NULL, FLG_UNMARSHAL, &sc);
+ // ignore these errors; a subsequent QI will detect the problem;
+ // the main point about passing the iid back and forth is
+ // to tell the client that a certain interface is support
+ // and avoid an RPC call to the server process.
+ }
+
+
+ // since the RH is just a middle man in the unmarshaling process,
+ // we don't allow any interface to be returned; another way
+ // to look at this is the RH must be precreated in the right place.
+
+ if (!IsEqualIID(riid, IID_NULL) || ppv != NULL)
+ sc = E_UNEXPECTED;
+ }
+
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::ReleaseMarshalData, public
+//
+// Synopsis: finds the handler for this object and calls it to release
+// its internal state.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Invocation: This is called by CoUnmarshalInterface when mshlflags
+// are NORMAL, and by application code when mshlflags are
+// TABLESTRONG or TABLEWEAK.
+//
+// Notes: So we dont ever unmarshal this data again, we set the
+// HDLRFLAGS_RELEASED bit in the SHandlerDataHdr. Unmarshal
+// ensures this is not set, and errors if so.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRemoteHdlr::ReleaseMarshalData(IStream *pStm)
+{
+ TRACECALL(TRACE_MARSHAL, "CRemoteHdlr::ReleaseMarshalData");
+
+ AssertValid();
+
+ SHandlerDataHdr hdh;
+ CLSID clsidChannel;
+
+ // read the marshal data from the stream
+ HRESULT sc = StRead(pStm, &hdh, sizeof(hdh));
+ if (FAILED(sc))
+ return sc;
+
+ // deal with channel clsid (probably pass to Unmarshal below)
+ if ((hdh.dwflags & HDLRFLAGS_STDRPCCHNL) == 0)
+ {
+ sc = StRead(pStm, &clsidChannel, sizeof(clsidChannel));
+ if (FAILED(sc))
+ return sc;
+ }
+
+#ifdef CODEWORK
+ must use clsidChannel
+#else
+ // single channel; just verify clsid
+ Assert((hdh.dwflags & HDLRFLAGS_STDRPCCHNL) != 0 ||
+ IsEqualGUID(clsidChannel, CLSID_RpcChannelBuffer));
+#endif
+
+ // deal with extension
+ if (hdh.dwflags & HDLRFLAGS_EXTENSION)
+ {
+ sc = SkipMarshalExtension(pStm);
+ if (FAILED(sc))
+ return sc;
+ }
+
+ // we are the remote handler for the object to be released
+ sc = ReleaseData(pStm, hdh);
+
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::ReleaseData, private
+//
+// Synopsis: Releases any internal state kept around for marshalled
+// interfaces on this particular handler.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// CODEWORK: merge into ::UnmarshalInterface above. The reasons for
+// this routine being separate have gone.
+//
+//+-------------------------------------------------------------------
+
+STDMETHODIMP CRemoteHdlr::ReleaseData(IStream *pStm, SHandlerDataHdr &hdh)
+{
+ CairoleDebugOut((DEB_MARSHAL, "CRemoteHdlr::ReleasMarshalData %x\n", this));
+
+ // CODEWORK: fix for multiple channels
+ Assert(hdh.dwflags & HDLRFLAGS_STDRPCCHNL);
+
+ // call ReleaseMarshalData on the channel
+ return _pChannel->ReleaseMarshalData(pStm);
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::DisconnectObject, public
+//
+// Synopsis:
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CRemoteHdlr::DisconnectObject(DWORD dwReserved)
+{
+ AssertValid();
+
+ // CODEWORK: thread safety: need to block multiple calls here and
+ // block out other code which tries to use the data changed here (_punkObj)
+
+ if (_dwFlags & RHFLAGS_DISCONNECTED)
+ {
+ // already disconnected, nothing to do
+ return S_OK;
+ }
+
+ if (_cCallsInProgress != 0)
+ {
+ // we dont allow disconnect to occur inside a nested call, but we
+ // remember that we want to disconnect and will do it when the
+ // stack unwinds.
+ _dwFlags |= RHFLAGS_PENDINGDISCONNECT;
+ return S_OK;
+ }
+
+ // No calls in progress, OK to really disconnect.
+
+ if (!IS_LOCAL_RH) // client side
+ {
+ _IXList.DisconnectProxies();
+
+ // client side: disconnect this one channel from the server
+ _pChannel->DisconnectObject(dwReserved);
+
+ // NOTE: on Client side we did not AddRef the _punkObj in the ctor and
+ // thus no Release (because _punkObj is our pUnkOuter, which might just
+ // be the id obj). Also, _punkObj is always valid as long as we are
+ // alive.
+ }
+ else // server side
+ {
+ // server side:
+ // walk the list of clients, killing off their channel ids.
+ // when they make a subsequent call, they will get an Rpc error.
+
+ ChannelList.DisconnectHdlr(this);
+
+ // release our main hold on the object; use WR if supported
+ if (_punkObj != NULL)
+ {
+ _IXList.DisconnectStubs();
+ SafeReleaseAndNULL(&_punkObj);
+ }
+
+ Win4Assert(_IXList.CountStubRefs() == 0);
+ }
+
+ _dwFlags |= RHFLAGS_DISCONNECTED; // turn on disconnected
+ _dwFlags &= ~RHFLAGS_PENDINGDISCONNECT; // turn off pending disconnect
+
+ _pChannel->AssertValid(TRUE, TRUE); // known disconnected
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::FindIX, private
+//
+// Synopsis: finds or creates an interface object for the given
+// interface.
+//
+// Returns: Pointer to CPSIX for requested interface; NULL if error
+// ppv place to put proxy QI result; must be NULL on server
+// side; may be NULL for client side.
+// *phr always holds result of call.
+//
+//
+// History: 23-Nov-93 Rickhi Created
+// 7-May-94 CraigWi Added HRESULT out param
+//
+// Notes: this code is thread safe
+//
+//--------------------------------------------------------------------
+
+CPSIX * CRemoteHdlr::FindIX(REFIID riid, void **ppv, DWORD dwFlag, HRESULT *phr)
+{
+ TRACECALL(TRACE_MARSHAL, "CRemoteHdlr::FindIX");
+
+ AssertValid();
+
+ if (ppv)
+ *ppv = NULL; // null return value in case of error
+
+ // validate input parms. there are no proxies/stubs for these
+ // interfaces...
+ Win4Assert(! (IsEqualIID(riid, IID_NULL) ||
+ IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IMarshal)));
+
+ // check for disconnected server on local side
+ if (_punkObj == NULL || _dwFlags & (RHFLAGS_DISCONNECTED))
+ {
+ *phr = CO_E_OBJNOTCONNECTED;
+ return NULL;
+ }
+
+ // single thread access to this routine
+ _mxs.Request();
+
+ // find the IX with the matching IID
+ CPSIX* pIX;
+ IUnknown *pUnkProxy = NULL;
+
+ if (IS_LOCAL_RH)
+ {
+ pIX = _IXList.FindStubIX(riid);
+ }
+ else
+ {
+ pIX = _IXList.FindProxyIX(riid, (void **)&pUnkProxy);
+ }
+ *phr = S_OK;
+
+ if (pIX == NULL)
+ {
+ // this will take a while. instead of blocking all RHs in the
+ // process, we will mark this RH as busy and release the mutex
+
+ _dwFlags |= RHFLAGS_GETTINGIX;
+ _mxs.Release();
+
+ // no IX in the list. figure out what we should do based on the
+ // flags that were passed in.
+
+ switch (dwFlag)
+ {
+ case FLG_QUERYINTERFACE:
+ // called by QueryInterface. we must call the remote object to
+ // tell it to instantiate a stub for the requested interface.
+
+ if ((*phr = _pChannel->QueryObjectInterface(riid)) != NOERROR)
+ {
+ break;
+ }
+
+ // fallthru into UNMARSHAL case
+
+ case FLG_UNMARSHAL:
+ // called by the unmarshalling code. the server side is known to
+ // have instantiated an interface stub already, so we just create
+ // an interface proxy here.
+
+ pIX = CreateInterfaceProxy(riid, (void **)&pUnkProxy, phr);
+ break;
+
+ case FLG_MARSHAL:
+ // called by marshalling code. we create an interface stub for
+ // the interface.
+
+ pIX = CreateInterfaceStub(riid, phr);
+ break;
+ }
+
+ // need to take the mutex again to protect the list.
+ _mxs.Request();
+ _dwFlags &= ~RHFLAGS_GETTINGIX;
+
+ // add the interface to the list
+ if (pIX)
+ {
+ _IXList.AddToList(pIX);
+ }
+ }
+
+ // release the mutex
+ _mxs.Release();
+
+ // if pUnkProxy and asked for one, return it; else release.
+ if (pUnkProxy != NULL)
+ {
+ Win4Assert(pIX != NULL); // only makes sense if we succeed
+ if (ppv != NULL)
+ *ppv = (void **)pUnkProxy; // transfer addref
+ else
+ pUnkProxy->Release(); // not needed
+ }
+
+ return pIX;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CreateInterfaceProxy, public
+//
+// Synopsis: creates an interface proxy and wraps it in a CPSIX
+//
+// Exceptions: none
+//
+// History: 23-Nov-93 Rickhi Created
+// 7-May-94 CraigWi Added HRESULT out param
+//
+//--------------------------------------------------------------------
+
+CPSIX * CRemoteHdlr::CreateInterfaceProxy(REFIID riid, void **ppv, HRESULT *phr)
+{
+ TRACECALL(TRACE_MARSHAL, "CreateInterfaceProxy");
+
+ AssertValid();
+ Assert((_dwFlags & RHFLAGS_LOCAL) == 0);
+ Win4Assert(_punkObj != NULL);
+ Win4Assert(ppv != NULL);
+
+ *ppv = NULL;
+
+ IPSFactoryBuffer *pIPSF = NULL;
+ IRpcProxyBuffer *pIProxy = NULL;
+ CPSIX *pIX = NULL;
+ CLSID clsid;
+
+
+ // map iid to classid
+ HRESULT sc = CoGetPSClsid(riid, &clsid);
+
+ if (SUCCEEDED(sc))
+ {
+ DWORD dwContext = IsRequestedByWOW(riid) ?
+ CLSCTX_INPROC_SERVER16 : CLSCTX_INPROC_SERVER | CLSCTX_PS_DLL;
+
+ // load the dll and get the PS class object
+ sc = ICoGetClassObject(clsid, dwContext, NULL, IID_IPSFactoryBuffer,
+ (void **)&pIPSF);
+ AssertOutPtrIface(sc, pIPSF);
+
+ if (SUCCEEDED(sc))
+ {
+ sc = pIPSF->CreateProxy(_punkObj, riid, &pIProxy, ppv);
+ AssertOutPtrIface(sc, pIProxy);
+ AssertOutPtrIface(sc, *ppv);
+ pIPSF->Release();
+ }
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ // create an IX wrapper for this interface proxy
+
+ pIX = new CPSIX(riid, pIProxy);
+ if (pIX == NULL)
+ {
+ // release below will release proxy (and disconnect)
+ sc = E_OUTOFMEMORY;
+
+ ((IUnknown *)*ppv)->Release();
+ *ppv = NULL;
+ }
+
+ // connect the proxy to the channel
+ pIProxy->Connect(_pChannel);
+ }
+
+ if (pIProxy)
+ pIProxy->Release();
+
+#if DBG == 1
+ if (!pIX)
+ {
+ WCHAR wszGuid[50];
+ StringFromGUID2(riid, wszGuid, sizeof(wszGuid)/sizeof(WCHAR));
+ CairoleDebugOut((DEB_ERROR, "No Proxy for interface %ws; error = %lx\n" , wszGuid, sc));
+ }
+#endif
+
+ Win4Assert((sc == S_OK) == (pIX != NULL));
+ Win4Assert((sc == S_OK) == (*ppv != NULL));
+ *phr = sc;
+ return pIX;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CreateInterfaceStub, public
+//
+// Synopsis: creates an interface stub and wraps it in a CPSIX
+//
+// Exceptions: none
+//
+// History: 23-Nov-93 Rickhi Created
+// 7-May-94 CraigWi Added HRESULT out param
+//
+//--------------------------------------------------------------------
+CPSIX * CRemoteHdlr::CreateInterfaceStub(REFIID riid, HRESULT *phr)
+{
+ TRACECALL(TRACE_MARSHAL, "CreateInterfaceStub");
+
+ AssertValid();
+ Assert(_dwFlags & RHFLAGS_LOCAL);
+ Win4Assert(_punkObj != NULL);
+
+#if DBG == 1
+ // convert riid to string for debug messages
+ WCHAR wszGuid[50];
+ StringFromGUID2(riid, wszGuid, sizeof(wszGuid)/sizeof(WCHAR));
+#endif
+
+ // first, make sure the object supports the given interface, so we
+ // dont waste a bunch of effort creating a stub if the interface is
+ // not supported.
+
+ IUnknown *punkIf = NULL;
+ HRESULT sc = _punkObj->QueryInterface(riid, (void **)&punkIf);
+
+ if (FAILED(sc))
+ {
+ // the server does not support the requested interface.
+ CairoleDebugOut((DEB_MARSHAL,
+ "Server Object does not support Interface:%ws\n", wszGuid));
+ *phr = sc;
+ return NULL;
+ }
+
+ // Determine whether the thing we're getting back is a custom WOW proxy
+ // or not so we know whether to load 16-bit custom proxy code if necessary
+ BOOL fWowCustom = FALSE;
+ IThunkManager *pthkmgr;
+
+ if (IsWOWThreadCallable() &&
+ g_pOleThunkWOW->GetThunkManager(&pthkmgr) == NOERROR)
+ {
+ fWowCustom = pthkmgr->IsCustom3216Proxy(punkIf, riid);
+ pthkmgr->Release();
+ }
+
+ punkIf->Release();
+
+
+ IPSFactoryBuffer *pIPSF = NULL;
+ IRpcStubBuffer *pIStub = NULL;
+ CPSIX *pIX = NULL;
+ CLSID clsid;
+
+ // map iid to classid
+ sc = CoGetPSClsid(riid, &clsid);
+
+ if (SUCCEEDED(sc))
+ {
+ DWORD dwContext;
+
+ dwContext = fWowCustom
+ ? CLSCTX_INPROC_SERVER16 : CLSCTX_INPROC_SERVER | CLSCTX_PS_DLL;
+
+ // load the dll and get the PS class object
+ sc = ICoGetClassObject(clsid, dwContext, NULL, IID_IPSFactoryBuffer,
+ (void **)&pIPSF);
+ AssertOutPtrIface(sc, pIPSF);
+
+ if (SUCCEEDED(sc))
+ {
+ sc = pIPSF->CreateStub(riid, _punkObj, &pIStub);
+#ifndef _CAIRO_ // BUGBUG [mikese] CMIDL stubs don't obey the convention
+ AssertOutPtrIface(sc, pIStub);
+#endif
+ pIPSF->Release();
+ }
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ pIX = new CPSIX(riid, pIStub);
+ if (pIX == NULL)
+ // release below will release stub (and disconnect)
+ sc = E_OUTOFMEMORY;
+
+ pIStub->Release();
+ }
+ else
+ {
+ CairoleDebugOut((DEB_WARN, "No Stub for interface %ws; error = %lx\n" , wszGuid, sc));
+ }
+
+ // verify that all is well
+ _IXList.AssertValid(IS_LOCAL_RH);
+
+ Win4Assert((sc == S_OK) == (pIX != NULL));
+ *phr = sc;
+ return pIX;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::LookupStub, public
+//
+// Synopsis: Returns the stub for the requested IID; this pointer is
+// not AddRefd and so callers must hold on to the rh longer
+// than they hold this; i.e., the lifetime of a stub pointer
+// from this call is no longer than the rh from which it was gotten
+//
+// Also returns an addref'd pointer on the server to stablize it
+// during calls. If such a pointer is returned, the caller must
+// call FinishCall with the same pointer when done.
+//
+// History: 27-Nov-93 AlexMit Created
+// 31-May-94 CraigWi Now paired with FinishCall method.
+//
+//--------------------------------------------------------------------
+
+IRpcStubBuffer *CRemoteHdlr::LookupStub(REFIID riid,
+ IUnknown **ppUnkServer, HRESULT *phr )
+{
+ IRpcStubBuffer *pStub;
+
+ AssertValid();
+ Win4Assert(IS_LOCAL_RH);
+
+ // find the IX with the matching IID
+ // need to create the stub if it is not present;
+ // returns error if not connected
+ CPSIX* pIX = FindIX(riid, NULL, FLG_MARSHAL, phr);
+ AssertOutPtrParam(*phr, pIX);
+ if (pIX == NULL)
+ {
+ pStub = NULL;
+ if (ppUnkServer != NULL)
+ *ppUnkServer = NULL;
+ }
+ else
+ {
+ pStub = pIX->GetIStub();
+ if (ppUnkServer != NULL && pStub != NULL)
+ {
+ // get server interface from stub; this is a new use of
+ // DebugServerQueryInterface and we may want to change the
+ // name of that method someday.
+
+ HRESULT hr;
+ hr = pStub->DebugServerQueryInterface((void **)ppUnkServer);
+ AssertOutPtrIface(hr, *ppUnkServer);
+
+ if (hr == NOERROR)
+ {
+ // don't need to addref the pointer here since the stub will
+ // keep ptr until it is disconnected and we don't disconnect
+ // stub until after the calls complete;
+ // CODEWORK: assert in stub that DebugServerRelease
+ // doesn't happen after disconnect.
+
+ InterlockedIncrement(&_cCallsInProgress);
+ }
+ }
+ }
+
+ return pStub;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::FinishCall, public
+//
+// Synopsis: Releases the pUnk previously returned from LookupStub
+// and also finishes pending releases.
+// If the object supports weak connections, we use
+// IWeakRef to release and keep the server alive.
+//
+// Arguments: [pStub] -- The stub upon which the call was made
+// [pUnkServer] -- The IUnknown on which the call was made
+//
+// History: 31-May-94 CraigWi Created
+//
+//--------------------------------------------------------------------
+
+void CRemoteHdlr::FinishCall(IRpcStubBuffer *pStub, IUnknown *pUnkServer)
+{
+ AssertValid();
+ Win4Assert(IS_LOCAL_RH);
+
+ Win4Assert((pStub == NULL) == (pUnkServer == NULL));
+
+ // check the pUnkServer argument since there could be a very, very rare
+ // case when we got a stub, but no server object.
+ if (pUnkServer != NULL)
+ {
+ pStub->DebugServerRelease(pUnkServer);
+
+ // one less pending call; check for pending disconnect
+ if (InterlockedDecrement(&_cCallsInProgress) == 0 &&
+ _dwFlags & RHFLAGS_PENDINGDISCONNECT)
+ {
+ DisconnectObject(0);
+ }
+ }
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::GetObjectId, public
+//
+// Synopsis: returns the remote handlers identity
+//
+// History: 10-Jan-94 AlexMit Created
+//
+//--------------------------------------------------------------------
+
+void CRemoteHdlr::GetObjectID( OID * pOid )
+{
+ AssertValid();
+
+ // this is only called on the client side presently and so this assert is ok
+ Win4Assert( _pstdID );
+ _pstdID->GetObjectID( pOid );
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::IsRequestedByWOW, public
+//
+// Synopsis: return TRUE if requested by WOW app
+//
+// History: 03-May-94 JohannP Created
+//
+//--------------------------------------------------------------------
+
+BOOL CRemoteHdlr::IsRequestedByWOW(REFIID riid)
+{
+ AssertValid();
+ BOOL fRet = FALSE;
+
+ if(IsWOWThreadCallable())
+ {
+ // dll used by WOW app
+ // query for the thunkmanager
+ IThunkManager *pThkMgr;
+ if (g_pOleThunkWOW->GetThunkManager(&pThkMgr) == NOERROR)
+ {
+ fRet = pThkMgr->IsIIDRequested(riid);
+ pThkMgr->Release();
+ }
+ else
+ {
+ Win4Assert(FALSE && L"pUnk in WOW does not support IThunkManager.");
+ }
+ }
+ return fRet;
+}
+
+
+#if DBG == 1
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::AssertValid
+//
+// Synopsis: Validates that the state of the object is consistent.
+//
+// History: 25-Jan-94 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+void CRemoteHdlr::AssertValid()
+{
+ Win4Assert((_dwFlags & ~(RHFLAGS_LOCAL | RHFLAGS_GETTINGIX |
+ RHFLAGS_PENDINGDISCONNECT | RHFLAGS_DISCONNECTED)) == 0);
+
+ Win4Assert(_cReferences < 0x7fff && "RemoteHdlr ref count unreasonably high");
+
+ if (_punkObj != NULL)
+ {
+ // if we have a pointer, it should be valid.
+ Win4Assert(IsValidInterface(_punkObj));
+
+ // NOTE: can't AddRef/Release _punkObj since we may been in a
+ // situation where there are only weak refs
+
+ }
+
+ if (!IS_LOCAL_RH)
+ {
+ Win4Assert(_punkObj != NULL);
+ }
+
+ if (_pstdID != NULL)
+ {
+ Win4Assert(IsValidInterface(_pstdID));
+ if (IS_LOCAL_RH && _punkObj != NULL
+ && (_dwFlags & RHFLAGS_PENDINGDISCONNECT) == 0)
+ // on remote side or when disconnected, GetServer returns NULL.
+ Win4Assert(_pstdID->GetServer(FALSE) == _punkObj);
+ }
+
+ Win4Assert(IsValidInterface(_pChannel));
+ _pChannel->AssertValid(FALSE, FALSE);
+
+ _IXList.AssertValid(IS_LOCAL_RH);
+}
+#endif // DBG == 1
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CIXList::FindProxyIX
+//
+// Synopsis: finds an interface proxy object supporting the specified
+// interface and returns that pointer on the proxy. Returns
+// NULL indicating no existing proxy supports the interface.
+//
+// History: 23-Nov-93 Rickhi Created
+// 21-Jul-94 CraigWi Less abstract form of original FindIX
+//
+// Note: This code is called by the channel dispatch.
+// Thread synchronization is the responsibility of the caller.
+//
+//--------------------------------------------------------------------
+
+CPSIX *CIXList::FindProxyIX(REFIID riid, void **ppv)
+{
+ // validate input parms
+ Win4Assert(!IsEqualIID(riid, IID_NULL));
+
+ // starting from the list head
+ CPSIX *pIX = first();
+
+ while (pIX)
+ {
+ // we should only find proxies
+ Win4Assert(pIX->_pIProxy != NULL);
+
+ if (pIX->_pIProxy->QueryInterface(riid, ppv) == NOERROR)
+ return pIX;
+
+ pIX = next(pIX);
+ }
+
+ *ppv = NULL;
+ return NULL;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CIXList::FindStubIX
+//
+// Synopsis: finds an interface stub object supporting the specified
+// interface. Returns NULL indicating no existing proxy
+// supports the interface.
+//
+// History: 23-Nov-93 Rickhi Created
+// 21-Jul-94 CraigWi Less abstract form of original FindIX
+//
+// Note: This code is called by the channel dispatch.
+// Thread synchronization is the responsibility of the caller.
+//
+//--------------------------------------------------------------------
+
+CPSIX *CIXList::FindStubIX(REFIID riid)
+{
+ // validate input parms
+ Win4Assert(!IsEqualIID(riid, IID_NULL));
+
+ // starting from the list head
+ CPSIX *pIX = first();
+
+ while (pIX)
+ {
+ Win4Assert(pIX->_pIProxy == NULL);
+
+ if (IsEqualIID( riid, pIX->_iid ))
+ return pIX;
+
+ pIX = next(pIX);
+ }
+
+ return NULL;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CIXList::ConnectProxies
+//
+// Synopsis: walks the list of proxy IXs and connects each of them
+//
+// History: 27-Jan-94 CraigWi Created
+//
+// Note: Thread synchronization is the responsibility of the caller.
+//
+//--------------------------------------------------------------------
+
+void CIXList::ConnectProxies(IRpcChannelBuffer *pChannel)
+{
+ // validate input parms
+ Win4Assert(IsValidInterface(pChannel));
+
+ // starting from the list head
+ CPSIX *pIX = first();
+
+ while (pIX)
+ {
+ Win4Assert(pIX->_pIProxy != NULL);
+ HRESULT sc = pIX->_pIProxy->Connect(pChannel);
+ Win4Assert(SUCCEEDED(sc) && "Proxy Connect Failed");
+ pIX = next(pIX);
+ }
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CIXList::CountStubRefs
+//
+// Synopsis: walks the list of IXs and sum up the refs
+//
+// History: 1-June-94 CraigWi Created
+//
+// Note: Thread synchronization is the responsibility of the caller.
+//
+// CODEWORK: could keep running sum in IXList rather than computing it
+//
+//--------------------------------------------------------------------
+
+DWORD CIXList::CountStubRefs(void)
+{
+ // starting from the list head
+ CPSIX *pIX = first();
+ DWORD cRefs = 0;
+
+ while (pIX)
+ {
+ Win4Assert(pIX->_pIProxy == NULL);
+ Win4Assert(pIX->_cRefs == -1 || pIX->_cRefs == pIX->_pStub->CountRefs());
+ cRefs += pIX->_pStub->CountRefs();
+ pIX = next(pIX);
+ }
+
+ return cRefs;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CIXList::DisconnectStubs
+//
+// Synopsis: walks the list of IXs and disconnects each of them
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Note: Thread synchronization is the responsibility of the caller.
+//
+//--------------------------------------------------------------------
+
+void CIXList::DisconnectStubs(void)
+{
+ // starting from the list head
+ CPSIX *pIX = first();
+
+ while (pIX)
+ {
+ Win4Assert(pIX->_pIProxy == NULL);
+ pIX->_pStub->Disconnect();
+#if DBG==1
+ pIX->_cRefs = (DWORD)-1;
+#endif
+ pIX = next(pIX);
+ }
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CIXList::DisconnectProxies
+//
+// Synopsis: walks the list of IXs and disconnects each of them
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Note: Thread synchronization is the responsibility of the caller.
+//
+//--------------------------------------------------------------------
+
+void CIXList::DisconnectProxies(void)
+{
+ // starting from the list head
+ CPSIX *pIX = first();
+
+ while (pIX)
+ {
+ Win4Assert(pIX->_pIProxy != NULL);
+ pIX->_pIProxy->Disconnect();
+ pIX = next(pIX);
+ }
+}
+
+
+#if DBG == 1
+//+-------------------------------------------------------------------
+//
+// Member: CIXList::AssertValid
+//
+// Synopsis: Validates that the state of the object is consistent.
+//
+// History: 25-Jan-94 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+void CIXList::AssertValid(BOOL fLocal)
+{
+ // check IX list
+ CPSIX *pIX = first();
+ BOOL fStubsConnected;
+
+ // determine if all stubs are supposed to connected or disconnected
+ // (this shouldn't be called during the disconnect steps)
+ if (pIX != NULL && pIX->_pIProxy == NULL && pIX->_cRefs != -1)
+ fStubsConnected = TRUE;
+ else
+ fStubsConnected = FALSE;
+
+ while (pIX)
+ {
+ // local means stubs and we must have only stubs or only proxies
+ Win4Assert(!!fLocal == (pIX->_pIProxy == NULL));
+
+ if (pIX->_pIProxy)
+ {
+ Win4Assert(IsValidInterface(pIX->_pIProxy));
+ Win4Assert(pIX->_pStub == NULL);
+ Win4Assert(IsEqualGUID(pIX->_iid, IID_NULL));
+ }
+ else
+ {
+ Win4Assert(IsValidInterface(pIX->_pStub));
+ if (pIX->_cRefs != -1)
+ {
+ Win4Assert(fStubsConnected);
+ Win4Assert(pIX->_cRefs == pIX->_pStub->CountRefs());
+ }
+ else
+ {
+ Win4Assert(!fStubsConnected);
+ Win4Assert(0 == pIX->_pStub->CountRefs());
+ }
+ }
+ pIX = next(pIX);
+ }
+}
+#endif // DBG == 1
diff --git a/private/ole32/com/remote/remhdlr.hxx b/private/ole32/com/remote/remhdlr.hxx
new file mode 100644
index 000000000..220a1e059
--- /dev/null
+++ b/private/ole32/com/remote/remhdlr.hxx
@@ -0,0 +1,463 @@
+//+-------------------------------------------------------------------
+//
+// File: remhdlr.hxx
+//
+// Contents: remote object handler definition
+//
+// Classes: CPSIX - proxy/stub interface record
+// CIXList - list of CPSIX records
+// CRemoteHdlr - remote object handler
+//
+// History: 23-Nov-92 Rickhi Modified from Ole2 sources
+//
+// The general architecture is thus...
+//
+// [ CRemoteHdlr ]--->[ CPSIX ]-->[ CPSIX ]--->[ CPSIX ]
+// |
+// [ CRemoteHdlr ]--->[ CPSIX ]-->[ CPSIX ]
+//
+// There is one RH per remote object. The RHs are accessed via the identity
+// object. The CPSIX is a wrapper class for an interface stub or proxy.
+// They are chained off the RHs, one per interface.
+//
+// The RHs implement the IMarshal interface and take care of marshalling
+// and unmarshalling interfaces on the objects.
+//
+// The RH is never aggregated; the identity object is the only creator of
+// the RH and the two interfaces it supports (IRemoteHdlr and IMarshal) can
+// *never* be passed outside the aggregate in which the identity object exists.
+//
+// The RH gets a punk (_punkObj below) when created. In the local case this is
+// the actual server object and is addref'd always. In the remote case the
+// pointer is the pointer to the controlling unknown of the aggregate in which
+// the identity object exists (and is not addref'd). As mentioned, the RH is
+// not aggregated, but the proxy objects are; the _punkObj becomes the
+// controlling unknown of the proxy objects so their interfaces can be passed
+// outside the identity (really handler) aggregate.
+//
+//--------------------------------------------------------------------
+
+#ifndef __REMHDLR__
+#define __REMHDLR__
+
+// forward declaration of classes
+class CPSIX; // interface wrapper
+class CIXList; // list of interface wrappers
+class CRemoteHdlr; // remote handler
+
+#include <olesem.hxx> // COleCommonMutexSem, COleStaticLock
+#include <dd.hxx> // doubly linked list class
+#include <iface.h> // SHandlerDataHdr
+#include <olerem.h> // GUIDs
+#include <channelb.hxx> // CRpcChannelBuffer
+
+
+//+-------------------------------------------------------------------
+//
+// Class: CPSIX
+//
+// Purpose: This class provides a wrapper around the interface
+// proxies and stubs, insulating higher-level code from
+// knowing whether an interface is a proxy or a stub, and
+// insulating the proxies from knowing the internals of the
+// remote object handling implementation.
+//
+// Interface:
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+class CPSIX : public CListEntry
+{
+ friend CIXList;
+
+public:
+
+ // Constructor & Destructor
+ CPSIX(REFIID riid,
+ IRpcProxyBuffer *pIProxy);
+
+ CPSIX(REFIID riid,
+ IRpcStubBuffer *pStub);
+
+ ~CPSIX(void);
+
+ IRpcStubBuffer *GetIStub(void); // used by marshalling code
+#if DBG == 1
+ void VerifyReconnect(IUnknown *);
+#endif
+
+private:
+ // CODEWORK: make this a union
+ IRpcProxyBuffer *_pIProxy; // proxy interface
+
+ IRpcStubBuffer *_pStub; // stub entry
+ IID _iid; // only needed for stubs
+#if DBG==1
+ DWORD _cRefs; // number of refs held by stub
+#endif
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CIXListBase (xlb)
+//
+// Purpose: Base class for Head list of interface objects.
+//
+// Interface: first -- get first item in the list.
+// next -- get next item in the list.
+//
+// History: 23-Nov-92 Rickhi Created
+//
+// Notes: See dd.hxx for details of this macro.
+//
+//--------------------------------------------------------------------------
+DERIVED_LIST_HEAD(CIXListBase, CPSIX);
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CIXList (ixl)
+//
+// Purpose: Head list of interface objects.
+//
+// Interface: AddToList -- add an entry to a list of proxies
+//
+// History: 23-Nov-92 Rickhi Created
+//
+// Notes: This class adds a few methods to its macro defined base class.
+//
+//--------------------------------------------------------------------------
+class CIXList : public CIXListBase
+{
+public:
+
+ CPSIX *FindProxyIX(REFIID riid, void**ppv);
+ // search for proxy IX
+ CPSIX *FindStubIX(REFIID riid); // search for stub IX
+
+ void AddToList(CPSIX *pIXToAdd); // add IX to list
+ void ConnectProxies(IRpcChannelBuffer *channel);// connect proxies
+ DWORD CountStubRefs(); // number of refs held by stubs
+ void DisconnectStubs(void); // disconnect stub IXs
+ void DisconnectProxies(void); // disconnect proxy IXs
+
+#if DBG == 1
+ void AssertValid(BOOL fLocal);
+#else
+ void AssertValid(BOOL fLocal) { }
+#endif
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CRemoteHdlr (RH)
+//
+// Purpose: remote object handler.
+//
+// Interface:
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------------
+class CRemoteHdlr : public IRemoteHdlr, public IMarshal
+{
+public:
+ CRemoteHdlr(IUnknown *punkObj,
+ IStdIdentity *pStdID, DWORD dwFlags, HRESULT &hr);
+
+ // IUnknown methods. I dont inherit tracking because i have
+ // special processing to do when the refcnt goes to zero.
+
+ STDMETHOD(QueryInterface)(REFIID riid, void **ppv);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+
+ // IMarshal methods
+ STDMETHOD(GetUnmarshalClass) (REFIID riid, void *pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax) (REFIID riid, void *pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize);
+ STDMETHOD(MarshalInterface) (IStream *pStm, REFIID riid, void *pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(IStream *pStm, REFIID riid, void **ppv);
+ STDMETHOD(ReleaseMarshalData)(IStream *pStm);
+ STDMETHOD(DisconnectObject)(DWORD dwReserved);
+
+
+ // IRemoteHdlr methods
+ STDMETHOD_(IRpcChannelBuffer *, GetChannel)(BOOL fAddRef);
+
+ // used by the channel to lock the RH during an Rpc call.
+ STDMETHOD_(ULONG, LockClient)(void);
+ STDMETHOD_(ULONG, UnLockClient)(void);
+
+ // used during destruction of the identity object to clear the RH ptr.
+ STDMETHOD_(void, ClearIdentity)(void);
+
+ // returns TRUE if iid is supported; like QueryInterface except no
+ // interface pointer returned; also works on both client and server sides.
+ STDMETHOD_(BOOL, DoesSupportIID)(REFIID riid);
+
+ // add/subtract a reference; vectors to identity; may return error
+ STDMETHOD(AddConnection)(DWORD extconn, DWORD reserved);
+ STDMETHOD(ReleaseConnection)(DWORD extconn, DWORD reserved, BOOL fLastReleaseCloses);
+
+ STDMETHOD_(BOOL, IsConnected)(void);
+ STDMETHOD_(void, Disconnect)(void);
+ STDMETHOD(LockConnection)(BOOL fLock, BOOL fLastUnlockReleases);
+
+ STDMETHOD_(IRpcStubBuffer *, LookupStub)(REFIID, IUnknown **, HRESULT *phr);
+ STDMETHOD_(void, FinishCall)( IRpcStubBuffer *pStub, IUnknown *pUnkServer);
+ STDMETHOD_(void, GetObjectID)( OID * );
+
+#if DBG == 1
+ void AssertValid();
+#else
+ void AssertValid() { }
+#endif
+
+private:
+ // Internal methods to find or create an interface proxy or stub
+ CPSIX *FindIX(REFIID riid, void **ppv, DWORD dwFlag, HRESULT *phr);
+
+ // internal unmarshalling and releasing functions
+ STDMETHOD(Unmarshal)(IStream *pStm, REFIID riid,
+ SHandlerDataHdr &ifh, void **ppv);
+
+ STDMETHOD(ReleaseData)(IStream *pStm, SHandlerDataHdr &ifh);
+
+ CPSIX *CreateInterfaceProxy(REFIID riid, void **ppv, HRESULT *phr);
+ CPSIX *CreateInterfaceStub(REFIID riid, HRESULT *phr);
+ STDMETHOD_(BOOL, IsRequestedByWOW)( REFIID riid );
+
+ ~CRemoteHdlr(void); // callable only from Release
+
+ DWORD _dwFlags; // internal flags
+ ULONG _cReferences; // reference count
+ LONG _cCallsInProgress;// number of calls in progress
+
+ // controlling unknown of object; if local, the object is separate and
+ // we addref always; if remote, the object is the handler and we never
+ // addref it. Disconnect on server side sets it to NULL. See more above.
+ IUnknown *_punkObj;
+
+ IStdIdentity *_pstdID; // identity; never addref'd
+
+ CRpcChannelBuffer *_pChannel; // ptr to channel used by ...
+ CIXList _IXList; // list of IXs on this interface
+
+ static COleStaticMutexSem _mxs; // global mutext
+};
+
+
+
+
+// Definition of values for RHFlags
+typedef enum tagRHFLAGS
+{
+ RHFLAGS_LOCAL = 1, // object is local to this process
+ RHFLAGS_PENDINGDISCONNECT = 2, // Disconnect during a call; delay releases
+ RHFLAGS_GETTINGIX = 4, // RH is busy getting a proxy or stub
+ RHFLAGS_DISCONNECTED = 8 // RH is really disconnected
+} RHFLAGS;
+
+// Definition of values for RFlags
+typedef enum tagRFLAGS
+{
+ FLG_QUERYINTERFACE = 1, // called from QueryInterface
+ FLG_MARSHAL = 2, // called from MarshalInterface
+ FLG_UNMARSHAL = 4 // called from UnmarshalInterface
+} RFLAGS;
+
+
+// macros to determine if the CRemoteHdlr is for a LOCAL or REMOTE object
+#define IS_LOCAL_RH (_dwFlags & RHFLAGS_LOCAL)
+#define IS_REMOTE_RH !(IS_LOCAL_RH)
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRemoteHdlr::~CRemoteHdlr, public
+//
+// Synopsis: destructor for the remote handler object
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+inline CRemoteHdlr::~CRemoteHdlr(void)
+{
+ CairoleDebugOut((DEB_MARSHAL,
+ "Delete CRemoteHdlr pRH:%x pChannel:%x\n",
+ this, _pChannel));
+
+ // don't need to disconnect here since the identity destruction did that.
+
+ Win4Assert(_cCallsInProgress == 0);
+
+ // can't assert RH valid since identity is gone; can assert channel
+ _pChannel->AssertValid(TRUE, FALSE);
+ _IXList.AssertValid(IS_LOCAL_RH);
+
+ // release the channel. note that it might still be around until
+ // all the proxies disconnect from it, which is done in the _IXList
+ // destructor.
+
+ // safe release of channel
+ _pChannel->Release();
+ _pChannel = NULL;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPSIX::CPSIX, public
+//
+// Synopsis: constructor for Proxy interface wrapper
+//
+// History: 23-Nov-92 Rickhi Created
+//
+// Exceptions: CException if QueryInterface fails
+//
+// Notes: the object interface in the case of a proxy is the
+// interface on the proxy itself.
+//
+//--------------------------------------------------------------------
+inline CPSIX::CPSIX(REFIID riid, IRpcProxyBuffer *pIProxy)
+ : _pIProxy(pIProxy),
+ _pStub(NULL),
+ _iid(IID_NULL)
+#if DBG==1
+ , _cRefs((DWORD)-1)
+#endif
+{
+ // validate input parms
+ Win4Assert(_pIProxy && "Improperly Constructed CPSIX");
+
+ _pIProxy->AddRef(); // keep the proxy
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPSIX::CPSIX, public
+//
+// Synopsis: constructor for stub interface wrapper
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline CPSIX::CPSIX(REFIID riid, IRpcStubBuffer *pStub)
+ : _pStub(pStub),
+ _pIProxy(NULL),
+ _iid(riid)
+#if DBG==1
+ , _cRefs(pStub->CountRefs())
+#endif
+{
+ // validate input parms
+ Win4Assert(_pStub && "Improperly Constructed CPSIX");
+ Win4Assert(_cRefs && "Stub not connected in CPSIX ctor");
+
+ _pStub->AddRef(); // keep the stub
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPSIX::~CPSIX, public
+//
+// Synopsis:
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+inline CPSIX::~CPSIX(void)
+{
+ if (_pIProxy)
+ {
+ _pIProxy->Disconnect(); // disconnect the proxy from channel
+ ULONG ul = _pIProxy->Release(); // release interface proxy
+ Win4Assert(ul == 0);
+ }
+ else
+ {
+ _pStub->Release(); // release interface stub
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPSIX::GetIStub, public
+//
+// Synopsis:
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------
+
+inline IRpcStubBuffer *CPSIX::GetIStub(void)
+{
+ Win4Assert(_pIProxy == NULL);
+ return _pStub;
+}
+
+
+#if DBG == 1
+//+-------------------------------------------------------------------
+//
+// Member: CPSIX::VerifyReconnect, public
+//
+// Synopsis: Verify that the stub disconnec and reconnect work and
+// that the ref counts remain the same.
+//
+// History: 1-Jun-94 CraigWi Created
+//
+//--------------------------------------------------------------------
+
+inline void CPSIX::VerifyReconnect(IUnknown *pUnkServer)
+{
+ Win4Assert(_pIProxy == NULL); // for stub only
+ Win4Assert(_cRefs != -1); // for connected stubs only
+ _pStub->Disconnect();
+ Win4Assert(_pStub->Connect(pUnkServer) == NOERROR);
+
+ Win4Assert(_pStub->CountRefs() == _cRefs);
+}
+#endif
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CIXList::AddToList
+//
+// Synopsis: adds a Stub object to list of Stub objects
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Note: Thread synchronization is the responsibility of the caller.
+//
+//--------------------------------------------------------------------
+
+inline void CIXList::AddToList(CPSIX *pIXToAdd)
+{
+ // validate input parms
+ Win4Assert(pIXToAdd);
+
+ CairoleDebugOut((DEB_MARSHAL, "New IX addr: %x\n", pIXToAdd));
+ insert_at_end(pIXToAdd);
+}
+
+#endif // __REMHDLR__
diff --git a/private/ole32/com/remote/rpchelp.cxx b/private/ole32/com/remote/rpchelp.cxx
new file mode 100644
index 000000000..bd2b44cb0
--- /dev/null
+++ b/private/ole32/com/remote/rpchelp.cxx
@@ -0,0 +1,88 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: rpchelp.cxx
+//
+// Contents: Helpers for internal RPC to use when it calls public
+// methods on objects.
+//
+// Functions: CanAppHandleCall
+//
+// History: 07-Jul-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include <tls.h>
+
+#include "callcont.hxx"
+#include "callmain.hxx"
+#include "rpchelp.hxx"
+
+//+-------------------------------------------------------------------------
+//
+// Function: CanAppHandleCall
+//
+// Synopsis: Asks app whether it can take a call on an interface
+//
+// Arguments: [dwTIDCaller] - caller's thread id
+// [lid] - Logical thread id
+// [punk] - IUnknown for interface to make call
+// [riid] - Interface ID
+// [wMethod] - Offset in interface of operation
+//
+// Returns: S_OK - call to interface should go through
+// RPC_E_SERVERCALL_REJECTED - message filter refuses call
+// RPC_E_SERVERCALL_RETRYLATER - try again later
+// RPC_E_UNEXPECTED - message filter gave an invalid response
+//
+// Algorithm: Get the call control main object. Use that to get the
+// current message filter. If there is a current message
+// filter, then create the appropriate parameters for
+// a HandleInComingCall and pass them to the message filter.
+// Translate the result from the message filter into an
+// appropriate error return.
+//
+// History: 07-Jul-94 Ricksa Created
+// 18-Aug-94 AlexT Add caller's thread id
+//
+// Notes: This is designed to be called from internal RPCs when
+// they are using interfaces on objects that the server
+// might want to be able to reject.
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT CanAppHandleCall(
+ DWORD dwTIDCaller,
+ REFLID lid,
+ IUnknown *punk,
+ REFIID riid,
+ WORD wMethod,
+ CALLCATEGORY callcat)
+{
+ // Default to success
+ HRESULT hr = S_OK;
+
+ CCallMainControl *pcmc = (CCallMainControl *) TLSGetCallControl();
+
+ // If we have a call control then ask it if we can allow the call through
+ if (pcmc != NULL)
+ {
+ INTERFACEINFO32 ifinfo;
+
+ ifinfo.pUnk = punk;
+ ifinfo.iid = riid;
+ ifinfo.wMethod = wMethod;
+ ifinfo.callcat = callcat;
+
+ // save the call state
+ CALLTYPE ctSaved = pcmc->GetCallType();
+
+ hr = pcmc->CanHandleIncomingCall(dwTIDCaller, lid, &ifinfo);
+
+ // restore the call state
+ pcmc->SetCallType(ctSaved);
+ }
+
+ return hr;
+}
diff --git a/private/ole32/com/remote/rpchelp.hxx b/private/ole32/com/remote/rpchelp.hxx
new file mode 100644
index 000000000..2e164b136
--- /dev/null
+++ b/private/ole32/com/remote/rpchelp.hxx
@@ -0,0 +1,56 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: rpchelp.hxx
+//
+// Contents: Helper interface defintions for internal RPC to use when it
+// calls public methods on objects.
+//
+// Functions: CanAppHandleCall
+//
+// History: 07-Jul-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef _RPCHELP_HXX_
+#define _RPCHELP_HXX_
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CanAppHandleCall
+//
+// Synopsis: Asks app whether it can take a call on an interface
+//
+// Arguments: [lid] - Logical thread id
+// [punk] - IUnknown for interface to make call
+// [riid] - Interface ID
+// [wMethod] - Offset in interface of operation
+// [callcat] - call category
+//
+// Returns: S_OK - call to interface should go through
+// RPC_E_SERVERCALL_REJECTED - message filter refuses call
+// RPC_E_SERVERCALL_RETRYLATER - try again later
+// RPC_E_UNEXPECTED - message filter gave an invalid response
+//
+// Algorithm: <see rpchelp.cxx>
+//
+// History: 07-Jul-94 Ricksa Created
+// 18-Aug-94 AlexT Add caller's thread id
+//
+// Notes: This is designed to be called from internal RPCs when
+// they are using interfaces on objects that the server
+// might want to be able to reject.
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT CanAppHandleCall(
+ DWORD dwTIDCaller,
+ REFLID lid,
+ IUnknown *punk,
+ REFIID riid,
+ WORD wMethod,
+ CALLCATEGORY callcat);
+
+#endif // _RPCHELP_HXX_
diff --git a/private/ole32/com/remote/rpcspy.hxx b/private/ole32/com/remote/rpcspy.hxx
new file mode 100644
index 000000000..d13f724ff
--- /dev/null
+++ b/private/ole32/com/remote/rpcspy.hxx
@@ -0,0 +1,204 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: rpcspy.hxx
+//
+// Contents: A primitive rpc spy with output to debug terminal
+//
+// Classes:
+//
+// Functions:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+// Note: Can be turned on via CairOle InfoLelevel mask 0x08000000
+//
+//----------------------------------------------------------------------------
+
+#ifndef _RPCSPY_HXX_
+#define _RPCSPY_HXX_
+
+#if DBG==1
+//
+// switch on to trace rpc calls
+// by setting CairoleInfoLevel = DEB_USER1;
+//
+//
+#define NESTING_SPACES 32
+#define SPACES_PER_LEVEL 2
+static char achSpaces[NESTING_SPACES+1] = " ";
+WORD wlevel = 0;
+char tabs[128];
+
+//+---------------------------------------------------------------------------
+//
+// Method: PushLevel
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void PushLevel()
+{
+ wlevel++;
+}
+//+---------------------------------------------------------------------------
+//
+// Method: PopLevel
+//
+// Synopsis:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void PopLevel()
+{
+ if (wlevel)
+ wlevel--;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: NestingSpaces
+//
+// Synopsis:
+//
+// Arguments: [psz] --
+//
+// Returns:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void NestingSpaces(char *psz)
+{
+ int iSpaces, i;
+
+ iSpaces = wlevel * SPACES_PER_LEVEL;
+
+ while (iSpaces > 0)
+ {
+ i = min(iSpaces, NESTING_SPACES);
+ memcpy(psz, achSpaces, i);
+ psz += i;
+ *psz = 0;
+ iSpaces -= i;
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: GetTabs
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+LPSTR GetTabs()
+{
+ static char ach[256];
+ char *psz;
+
+ wsprintfA(ach, "%2d:", wlevel);
+ psz = ach+strlen(ach);
+
+ if (sizeof(ach)/SPACES_PER_LEVEL <= wlevel)
+ {
+ strcpy(psz, "...");
+ }
+ else
+ {
+ NestingSpaces(psz);
+ }
+ return ach;
+}
+
+
+typedef enum
+{
+ CALLIN_BEGIN =1,
+ CALLIN_TRACE,
+ CALLIN_ERROR,
+ CALLIN_END,
+ CALLOUT_BEGIN,
+ CALLOUT_TRACE,
+ CALLOUT_ERROR,
+ CALLOUT_END
+} RPCSPYMODE;
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: RpcSpyOutput
+//
+// Synopsis:
+//
+// Arguments: [mode] -- in or out call
+// [iid] -- interface id
+// [dwMethod] -- called method
+// [hres] -- hresult of finished call
+//
+// Returns:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void RpcSpyOutput(RPCSPYMODE mode , REFIID iid, DWORD dwMethod, HRESULT hres)
+{
+ switch (mode)
+ {
+ case CALLIN_BEGIN:
+ CairoleDebugOut((DEB_RPCSPY,"%s <<< %lx, %d \n",GetTabs(), iid.Data1, dwMethod));
+ PushLevel();
+ break;
+ case CALLIN_TRACE:
+ break;
+ case CALLIN_ERROR:
+ break;
+ case CALLIN_END:
+ PopLevel();
+ CairoleDebugOut((DEB_RPCSPY,"%s === %lx, %d (%lx) \n",GetTabs(), iid.Data1, dwMethod, hres));
+ break;
+ case CALLOUT_BEGIN:
+ CairoleDebugOut((DEB_RPCSPY,"%s >>> %lx, %d \n",GetTabs(), iid.Data1, dwMethod));
+ PushLevel();
+ break;
+ case CALLOUT_TRACE:
+ break;
+ case CALLOUT_ERROR:
+ CairoleDebugOut((DEB_RPCSPY,"%s !!! %lx, %d, error:%lx \n",GetTabs(), iid.Data1, dwMethod, hres));
+ break;
+ case CALLOUT_END:
+ PopLevel();
+ CairoleDebugOut((DEB_RPCSPY,"%s +++ %lx, %d (%lx) \n",GetTabs(), iid.Data1, dwMethod, hres));
+ break;
+ }
+}
+
+#define RpcSpy(x) RpcSpyOutput x
+
+#else
+
+#define RpcSpy(x)
+
+#endif // DBG==1
+
+
+#endif // _RPCSPY_HXX_
diff --git a/private/ole32/com/remote/service.cxx b/private/ole32/com/remote/service.cxx
new file mode 100644
index 000000000..665d602f2
--- /dev/null
+++ b/private/ole32/com/remote/service.cxx
@@ -0,0 +1,1839 @@
+//+-------------------------------------------------------------------
+//
+// File: service.cxx
+//
+// Contents: Rpc service object implementation
+//
+// Classes: CRpcService - Rpc service object
+// CSrvList - list of Rpc service objects
+//
+// Functions:
+//
+// History: 23-Nov-92 Rickhi
+// 31-Dec-93 ErikGav Chicago port
+// 28-Jun-94 BruceMa Memory sift fixes
+// 19 Jul 94 CraigWi Added support for ASYNC calls
+// 03-Mar-95 JohannP Delaying rpc initialize
+//
+// CODEWORK: should a call to the remote object fail on the given binding,
+// we could try to call on another binding. Ideally, the
+// CEndPoint code would bind to all strings, then ask the
+// Rpc runtime to select one of the protocols for us, which
+// is really where the endpoint selection belongs.
+//
+//--------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include <objsrv.h>
+
+#include <service.hxx> // class definition
+#include <ichnl.h> // IChannelService_ServerIfHandle
+#include <channelb.hxx>
+#include <sichnl.hxx>
+#include <getif.h>
+
+#ifdef _CHICAGO_
+#include <callmain.hxx>
+
+BOOL NotifyToInitializeRpc(HWND hwnd);
+
+#else
+
+// global variables
+CSrvList sg_SrvList; // list of svc objects in process
+// static class members
+CRpcService *CRpcService::sg_pLocalSrv = NULL; // local service object
+BOOL CRpcService::_fListening = FALSE;
+#endif
+
+BOOL sg_fServerRegisterIf = FALSE;
+
+COleStaticMutexSem sg_SrvListLock;
+
+
+// Rpc does not return SCODES with the status bit set.
+#define RPC_ERROR_MASK 0x000fffff
+#define MAX_RETRIES 2 // max Rpc attempts
+
+#ifdef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Method: StartLocalService
+//
+// Synopsis: Starts up the rpc for the current thread
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: 3-23-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL StartLocalService()
+{
+ CairoleDebugOut((DEB_ENDPNT, "StartLocalService()\n"));
+ LocalService()->Listen(TRUE);
+ CairoleDebugOut((DEB_ENDPNT, "StartLocalService() done\n"));
+ return TRUE;
+}
+#endif // _CHICAGO_
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::CRpcService, public
+//
+// Synopsis: constructor for an Rpc service object
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+CRpcService::CRpcService(SEndPoint *pSEp, HRESULT &hr) :
+ _CEp(pSEp, hr, TRUE), // TRUE means copy the SEp
+ _pContext(NULL),
+ _eState(client_ss),
+ _ulRefCnt(1)
+{
+ CairoleDebugOut((DEB_ENDPNT, "CRpcService::CRpcService %x pSEp %x\n", this, pSEp));
+ // AssertValid in callers because sg_pLocalSrv not set yet
+
+ // If the endpoint strings being passed in are NULL then this is
+ // definitely in this process. Otherwise, check our lists.
+ _fThisProcess = (pSEp != NULL) ? IsInLocalProcess(&_CEp) : TRUE;
+
+#ifdef _CHICAGO_
+ _fListening = FALSE;
+ _fListenNow = FALSE;
+
+ // Add to global list of endpoints local to this process for
+ // Chicago. In daytona, we only have one end point.
+ if (_fThisProcess)
+ {
+ lslLocalServices.Add(this);
+ }
+#endif // _CHICAGO_
+ CairoleDebugOut((DEB_ENDPNT, "CRpcService::CRpcService %x pSEp %x\n done", this, pSEp));
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::~CRpcService, public
+//
+// Synopsis: destructor for an Rpc service object
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+CRpcService::~CRpcService(void)
+{
+ // If the service object is not already disconnected, rundown all the
+ // channels using it.
+ // If the service object was a client, the dtor for the CRpcBindingHandle
+ // will unbind. We can't check _hRpc or _pContext more than the
+ // AssertValid function.
+
+ // If the service object was a server, the rundown routine would have been
+ // called before this point
+
+ if (_pContext != NULL)
+ {
+ RpcSmDestroyClientContext( &_pContext );
+ _pContext = NULL;
+ }
+
+ // remove from the service list. This must be done while holding
+ // the lock for the list, hence we ask the list object to do it.
+ // the object may or may not still be on the list.
+
+#ifdef _CHICAGO_
+ if (_fListening)
+ {
+ _CEp.RemoveDefaultProtseq();
+ }
+
+ // Remove the endpoint from list of local endpoints since it
+ // is going away.
+ lslLocalServices.Remove(this);
+#else
+ // On Chicago AssertValid references TLS. Since this destructor may be
+ // called at process detach, don't AssertValid on Chicago.
+ AssertValid();
+#endif
+ _eState = deleted_ss;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::AddRef, public
+//
+// Synopsis: increment reference count
+//
+// History: 1 Dec 93 AlexMit Created
+//
+//--------------------------------------------------------------------
+ULONG CRpcService::AddRef(void)
+{
+ Win4Assert( _ulRefCnt >= 1 );
+ ULONG ulRefCnt = InterlockedIncrement( (long *) &_ulRefCnt );
+ return ulRefCnt;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::Release, public
+//
+// Synopsis: decrement reference count
+//
+// History: 1 Dec 93 AlexMit Created
+//
+//--------------------------------------------------------------------
+ULONG CRpcService::Release(void)
+{
+ // Prevent this object from being found after it is deleted.
+ sg_SrvListLock.Request();
+
+ ULONG ulRefCnt = _ulRefCnt - 1;
+
+ if (InterlockedDecrement( (long*) &_ulRefCnt ) == 0)
+ {
+#ifdef _CHICAGO_
+ CSrvList *pSrvList = (CSrvList *) TLSGetServiceList();
+ Win4Assert( pSrvList != NULL );
+ pSrvList->RemoveFromList(this);
+#else
+ sg_SrvList.RemoveFromList(this);
+#endif
+ sg_SrvListLock.Release();
+ delete this;
+ return 0;
+ }
+ else
+ {
+ sg_SrvListLock.Release();
+ return ulRefCnt;
+ }
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::Bind, public
+//
+// Synopsis: Selects the most appropriate endpoint from the array
+// of endpoints and binds to it, getting an Rpc handle.
+// This is called only once per RpcService object, the
+// handle is subsequently cached.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Note: this is only called if this is a remote service object.
+//
+// Exceptions: None
+//
+// Notes: This code is thread safe, so only one bind occurs.
+//
+//--------------------------------------------------------------------
+SCODE CRpcService::Bind(void)
+{
+ TRACECALL(TRACE_RPC, "CRpcService::Bind");
+ CairoleDebugOut((DEB_ENDPNT, "CRpcService::Bind %p\n", this));
+ AssertValid();
+
+ // single thread access to the binding code
+ CLock sms(_mxs);
+
+#ifndef _CHICAGO_
+ Win4Assert(this != sg_pLocalSrv);
+#endif
+ Win4Assert(_CEp.GetSEp() != NULL);
+
+ if (_hRpc.Handle() != NULL)
+ {
+ // we took the semaphore & when we returned, the bind had
+ // already happened, so there is nothing more for us to do.
+ return S_OK;
+ }
+
+ if (_eState == disconnected_ss)
+ return RPC_E_SERVER_DIED_DNE;
+
+#ifdef _CHICAGO_
+ // Initialize rpc on server and local thread
+ NotifyServerOfSEp();
+ LocalService()->Listen(TRUE);
+#endif
+
+ // try binding to the preferred strings first.
+ SCODE sc = _hRpc.BindByString(_CEp.GetStringBinding());
+ if (FAILED(sc))
+ {
+ _eState = disconnected_ss;
+ CairoleDebugOut((DEB_ERROR, "CRpcService Failed to Bind %x\n", sc));
+ }
+#ifdef _CHICAGO_
+ else
+ {
+ CairoleDebugOut((DEB_CHANNEL | DEB_ENDPNT, "CRpcService - Created binding handle %ws\n",
+ _CEp.GetStringBinding() ));
+ CairoleDebugOut((DEB_CHANNEL | DEB_ENDPNT, " handle 0x%x thread 0x%x\n",
+ _hRpc.Handle(), GetCurrentThreadId() ));
+ sc = I_RpcBindingSetAsync( _hRpc.Handle(), OleModalLoopBlockFn );
+ }
+#endif
+
+ CairoleDebugOut((DEB_ENDPNT, "CRpcService::Bind %p done \n", this));
+ return sc;
+}
+
+//
+// The following manifest maps the specific error RPC_S_TYPE_ALREADY_REGISTERED to sc
+//
+#define MAP_REGISTERIF_ERROR(sc) ((sc == RPC_S_TYPE_ALREADY_REGISTERED)? sc = RPC_S_OK: sc)
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::Listen, public
+//
+// Synopsis: this starts the Rpc service listening. this is required
+// in order to marshal interfaces. it is executed lazily,
+// that is, we dont start listening until someone tries to
+// marshal a local object interface. this is done so we dont
+// spawn a thread unnecessarily.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Note: this is only called if this is the local service object.
+// This code is thread safe so only one listen occurs.
+//
+//--------------------------------------------------------------------
+SCODE CRpcService::Listen(BOOL fListenNow)
+{
+ TRACECALL(TRACE_RPC, "CRpcService::Listen");
+ CairoleDebugOut((DEB_CHANNEL, "CRpcService::Listen %p\n", this));
+ CairoleDebugOut((DEB_ENDPNT, "CRpcService::Listen (fListenNow:%d) on %p\n", fListenNow, this));
+ AssertValid();
+ Win4Assert (this == LocalService());
+
+
+ RPC_STATUS sc = RPC_S_OK;
+
+ // single thread access to this code.
+ CLock sms(_mxs);
+#ifdef _CHICAGO_
+ if (fListenNow)
+ {
+ _fListenNow = fListenNow;
+ }
+
+ if(_fListenNow == FALSE)
+ {
+ sc = _CEp.CreateFakeSEp();
+ }
+ else
+#endif // _CHICAGO_
+ if (!IsServiceListen())
+ {
+ //Win4Assert (FALSE && "CRpcService::StartListe calling");
+
+#ifdef _CHICAGO_
+ CChannelControl *pChannelControl;
+
+ // make sure the channelcontroller is initialized
+ GetLocalChannelControl( pChannelControl );
+ if (!pChannelControl)
+ {
+ HRESULT hres;
+ hres = InitChannelControl();
+ if (hres != S_OK)
+ {
+ CairoleDebugOut((DEB_ERROR, "CRpcServer - InitChannelControl failed:%x\n", hres));
+ }
+ }
+#endif _CHICAGO_
+
+ // register protocol sequences with Rpc
+ sc = _CEp.RegisterDefaultProtseq();
+
+ if (sc == S_OK)
+ {
+ // register the IChannelService interface and the main
+ // incoming call interface with Rpc
+
+#ifdef _CHICAGO_
+ if (sg_fServerRegisterIf != FALSE)
+ {
+ CairoleDebugOut((DEB_ENDPNT,"CRpcListen: sg_fServerRegisterIf != FALSE\n"));
+ goto exitNow;
+ }
+#endif
+ sc = RpcServerRegisterIf(IChannelService_ServerIfHandle, NULL, NULL);
+
+ if(MAP_REGISTERIF_ERROR(sc) != RPC_S_OK)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "RpcListen IChannelService_ServerIfHandle %x\n",
+ sc));
+ goto exitNow;
+ }
+ sc = RpcServerRegisterIf(&the_server_if, NULL, NULL);
+ if(MAP_REGISTERIF_ERROR(sc) != RPC_S_OK)
+ {
+ CairoleDebugOut((DEB_ERROR,"RpcListen the_server_if %x\n",sc));
+ goto exitNow;
+ }
+
+ sc = RpcServerRegisterIf(IObjServer_ServerIfHandle, 0, 0);
+ if(MAP_REGISTERIF_ERROR(sc) != RPC_S_OK)
+ {
+ CairoleDebugOut((DEB_ERROR,"IObjServer_ServerIfHandle %x\n",sc));
+ goto exitNow;
+ }
+
+
+ sc = RpcServerRegisterIf(IInterfaceFromWindowProp_ServerIfHandle,0,0);
+
+ if(MAP_REGISTERIF_ERROR(sc) != RPC_S_OK)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "IInterfaceFromWindowProp_ServerIfHandle %x\n",
+ sc));
+ goto exitNow;
+ }
+
+ if ( sc == RPC_S_OK)
+ {
+ sg_fServerRegisterIf = TRUE;
+ // turn off context handle serialization, as this causes
+ // deadlocks in recursive Rpc calls.
+ I_RpcSsDontSerializeContext();
+
+ // start listening for Rpc calls.
+ sc = RpcServerListen(1, // min call threads
+ 0xffff, // max calls
+ 1); // dont wait
+
+#if defined (_CAIRO_) || defined(_CHICAGO_)
+ // Under Cairo, some services are both an ordinary RPC server
+ // and an OLE server, and may issue their own RpcServerListen
+ // before OLE. Therefore, treat "already listening" as a
+ // successful operation
+ if ( sc == RPC_S_ALREADY_LISTENING )
+ sc = RPC_S_OK;
+#endif
+
+ if (sc == RPC_S_OK)
+ {
+ // wait until we are really listening before telling the
+ // world that we are ready to accept calls.
+
+ while ((sc = RpcMgmtIsServerListening(NULL)) == RPC_S_NOT_LISTENING)
+ {
+ CairoleDebugOut((DEB_MARSHAL,"RpcMgmtIsServerListening=%x\n",sc));
+ Sleep(1); // yield to let Rpc go.
+ }
+ }
+ else
+ {
+ CairoleDebugOut((DEB_ERROR, "RpcServerListen failed:%x\n", sc));
+ }
+ }
+ else
+ {
+ CairoleDebugOut((DEB_ERROR, "RpcServerRegisterIf failed:%x\n", sc));
+ }
+ }
+ else
+ {
+ CairoleDebugOut((DEB_ERROR, "CRpcService::Listen RegisterDefaultProtseq failed:%x\n", sc));
+ }
+
+exitNow:
+
+ if (sc == RPC_S_OK)
+ {
+ SetThreadListening(TRUE);
+ }
+ else
+ {
+ sc = HRESULT_FROM_WIN32(sc);
+ }
+ }
+
+ CairoleDebugOut((DEB_CHANNEL | DEB_ENDPNT, "CRpcService::Listen done\n"));
+ return sc;
+}
+
+#ifdef _CHICAGO_
+
+//+---------------------------------------------------------------------------
+//
+// Method: CRpcService::NotifyServerOfSEp
+//
+// Synopsis: notifies the server of the endpoit to start listen
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 3-24-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL CRpcService::NotifyServerOfSEp(void)
+{
+ CairoleDebugOut((DEB_ENDPNT, "CRpcService::NotifyServerOfSEp %p\n", this));
+ BOOL fRet = TRUE;
+
+ SEndPoint *pSE = _CEp.GetSEp();
+ if (pSE)
+ {
+ NotifyToInitializeRpc((HWND)pSE->ulhwnd);
+ }
+
+ CairoleDebugOut((DEB_ENDPNT, "CRpcService::NotifyServerOfSEp %p done fRet:%d\n", this,fRet));
+ return fRet;
+}
+#endif // _CHICAGO_
+
+//+-------------------------------------------------------------------
+//
+// Function: StopListen
+//
+// Synopsis: this stops the Rpc service listening. In multithreaded
+// mode it can safely wait for all calls to complete without
+// deadlocking. In the apartment mode the channel controller
+// will already have completed all calls and blocked new calls.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+SCODE StopListen(void)
+{
+ CairoleDebugOut((DEB_ITRACE, "StopListen\n"));
+ SCODE sc = S_OK;
+ RPC_STATUS status;
+
+#ifdef _CHICAGO_
+ if (sg_fServerRegisterIf == FALSE)
+ {
+ return sc;
+ }
+#endif
+
+ // unregister IChannelService with RPC - wait for calls to complete
+ RpcServerUnregisterIf(IChannelService_ServerIfHandle, 0, 1);
+
+ // unregister the main incoming call interface with RPC - wait for calls
+ RpcServerUnregisterIf(&the_server_if, 0, 1);
+
+ sg_fServerRegisterIf = FALSE;
+
+ if ( LocalService()
+ && IsThreadListening())
+ {
+ // Stop the Rpc server listening. This will tell Rpc to complete
+ // the remaining calls, at which point, the RpcServerListen thread
+ // will return from the bowels of the Rpc runtime and will exit.
+
+ status = RpcMgmtStopServerListening(NULL);
+
+ if (status != RPC_S_OK)
+ {
+ CairoleDebugOut((DEB_ERROR, "RpcMgmtStopServerListening failed sc=%x\n", status));
+ sc = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, status );
+ }
+ else
+ {
+ // Wait for all calls to complete.
+ status = RpcMgmtWaitServerListen();
+#if DBG == 1
+ if (status != RPC_S_OK)
+ {
+ CairoleDebugOut((DEB_ERROR, "RpcMgmtWaitServerListening failed sc=%x\n", status));
+ }
+#endif
+ }
+ SetThreadListening(FALSE);
+ }
+
+ return sc;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::GetDestCtx
+//
+// Synopsis: returns the destination context for purposes of
+// marshalling an interface. the destination context
+// for now is just the protseq we need to talk on.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+void CRpcService::GetDestCtx(DWORD *pdwDestCtx, void **ppvDestCtx)
+{
+ AssertValid();
+ CLock lck(_mxs);
+
+ if (_CEp.DiffMachine())
+ {
+ // different network address, so we are marshalling for a
+ // different machine.
+
+ *pdwDestCtx = MSHCTX_DIFFERENTMACHINE;
+ if (_CEp.GetActiveProtseq((WCHAR **)ppvDestCtx))
+ {
+ // if the protocol specified by GetActiveProtseq has not
+ // been registered, specify context, otherwise set it to
+ // NULL so that MarshalInterface in the channel avoids
+ // another check. The win here will become obvious when
+ // pvDestCtx becomes an interface derived from IUnknown
+ // and the marshalling code has to do lots of work to
+ // figure things out.
+
+ if (ppvDestCtx)
+ {
+ *ppvDestCtx = NULL;
+ }
+ }
+ }
+ else
+ {
+ // same machine, specify local context
+
+ // Check if this is an inprocess marshal that is not in WOW.
+ if ((_eState == client_ss)
+ && _fThisProcess
+ && !IsWOWThread())
+ {
+ *pdwDestCtx = MSHCTX_INPROC;
+ }
+ else
+ {
+ // Interprocess case
+ *pdwDestCtx = MSHCTX_LOCAL;
+ }
+
+ if (ppvDestCtx)
+ {
+ *ppvDestCtx = NULL;
+ }
+ }
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::RegisterProtseq, public
+//
+// Synopsis: registers a protseq with Rpc
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+SCODE CRpcService::RegisterProtseq(WCHAR *pwszProtseq)
+{
+ // local server, register the protseq here
+ AssertValid();
+ CLock lck(_mxs);
+ return _CEp.RegisterProtseq(pwszProtseq);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::RemoteRegisterProtseq, public
+//
+// Synopsis: registers a protseq with Rpc in the process this SO represents
+//
+// History: 23-Nov-93 Rickhi Created
+// 24-Nov-94 AlexMit Hacked from RegisterProtseq
+//
+// Note: Since this doesn't call user code on the server side,
+// it doesn't have to get off the client thread.
+//
+//--------------------------------------------------------------------
+SCODE CRpcService::RemoteRegisterProtseq(WCHAR *pwszProtseq)
+{
+ HRESULT sc = S_OK;
+
+ AssertValid();
+
+ // remote server, tell the other side to register the protseq
+ // then update our endpoint structure.
+
+ if (_CEp.DiffMachine())
+ {
+ if (_eState == disconnected_ss)
+ return RPC_E_SERVER_DIED_DNE;
+
+ SEndPoint *pSEp = NULL;
+ ULONG cRetry = 0;
+
+ // make sure we have a handle to call on
+ handle_t RpcHdl = GetRpcHdl();
+ if (!RpcHdl)
+ return E_HANDLE;
+
+ do
+ {
+ // Rpc call to remote RpcServiceObject
+ error_status_t errstat = 0;
+ sc = _ICS_RegisterProtseq(RpcHdl, pwszProtseq, &pSEp, &errstat);
+
+ if (errstat != 0)
+ {
+ // convert RPC return code to HRESULT incase we
+ // exit the loop
+ sc = HRESULT_FROM_WIN32(errstat);
+
+ if (errstat == RPC_S_SERVER_TOO_BUSY ||
+ errstat == RPC_S_NOT_LISTENING ||
+ errstat == RPC_S_SERVER_UNAVAILABLE)
+ {
+ // normal (?) errors. sleep and retry
+ Sleep(SERVER_BUSY_SLEEP_MS);
+ continue;
+ }
+ }
+
+ CairoleDebugOut((DEB_MARSHAL, "ICS_RegisterProtseq %ws = %x\n",
+ pwszProtseq, sc));
+ break;
+
+ } while (++cRetry < MAX_RETRIES);
+
+ if (SUCCEEDED(sc) && pSEp)
+ {
+ CLock lck(_mxs);
+ _CEp.Replace(pSEp);
+ MIDL_user_free(pSEp);
+ }
+ }
+
+ return sc;
+}
+
+
+
+/*-------------------------------------------------------------------
+
+ Member: ActuallyCallGetContextHdl
+
+ Synopsis: calls the remote service object to generate a context
+ handle.
+
+ To avoid being recalled when the call controller wants to
+retransmit, this function never returns RPC_E_SERVERCALL_RETRYLATER or
+RPC_E_SERVERCALL_REJECTED which are the only errors the call controller
+retries.
+
+ History: 2 Aug 94 AlexMit Hacked
+
+--------------------------------------------------------------------*/
+
+HRESULT ActuallyCallGetContextHdl( STHREADCALLINFO *call )
+{
+ SCODE sc;
+ POBJCTX pContext;
+ ULONG cRetry = 0;
+ SGetContextHdl *params = (SGetContextHdl *) call;
+ error_status_t errstat = 0;
+
+ // make sure we have a handle to call on
+ handle_t RpcHdl = params->service->GetRpcHdl();
+
+ if (!RpcHdl)
+ sc = E_FAIL;
+
+ else
+ {
+ do
+ {
+ // Rpc call to remote RpcServiceObject
+
+ sc = _ICS_GetContextHdl(RpcHdl,
+ params->psepClient,
+ &pContext,
+ &errstat);
+
+ if (errstat != 0)
+ {
+ // Convert RPC return code to HRESULT incase we
+ // exit the loop!
+ sc = MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, (errstat) );
+ // Retry on RPC_S_CALL_FAILED only because that is the return
+ // code RPC gives if we are trying string bindings for a
+ // process that are a duplicate of string bindings that we
+ // still hold for another process (that has gone away).
+
+ if (errstat == RPC_S_SERVER_TOO_BUSY ||
+ errstat == RPC_S_NOT_LISTENING ||
+ errstat == RPC_S_SERVER_UNAVAILABLE ||
+ errstat == RPC_S_CALL_FAILED)
+ {
+ // normal (?) errors. sleep and retry
+ Sleep(SERVER_BUSY_SLEEP_MS);
+ continue;
+ }
+
+#if DBG == 1
+ // Make it easier to print out an error message
+#endif // DBG
+
+ }
+
+ CairoleDebugOut((DEB_MARSHAL, "ICS_GetContextHdl pHdl=%x\n",
+ pContext));
+
+#if DBG == 1
+ if (pContext == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR, "ICS_GetContextHdl failed: %x\n", sc));
+ }
+ else
+ {
+ DWORD *tmp = (DWORD *) pContext;
+ CairoleDebugOut((DEB_MARSHAL, "ICS_GetContextHdl Hdl=%x%x%x%x%x\n",
+ tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]));
+ }
+#endif // DBG
+
+ // An error occurred
+ break;
+
+ } while (++cRetry < MAX_RETRIES);
+
+ // If ICS_GetContextHdl succeeded, save the result.
+ if (sc == S_OK)
+ {
+ sc = params->service->SetContextHdl( pContext );
+
+ // If a context handle was already saved, free this one.
+ if (sc != S_OK)
+ {
+ ICS_ReleaseContextHdl( &pContext, &errstat );
+ Win4Assert( pContext == NULL || errstat != RPC_S_OK );
+ if (errstat != RPC_S_OK)
+ RpcSmDestroyClientContext( &pContext );
+ sc = S_OK;
+ }
+ }
+ }
+
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: ~SGetContextHdl
+//
+// Synopsis: Called when ActuallyGetContextHdl is canceled. Releases
+// service.
+//
+// Exceptions: none
+//
+// History: 2 Aug 94 AlexMit Created
+//
+// Notes: Thread safe; client/server safe (only used on client side now)
+//
+//--------------------------------------------------------------------
+
+SGetContextHdl::~SGetContextHdl( )
+{
+ service->Release();
+ PrivMemFree( psepClient );
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::CheckContextHdl
+//
+// Synopsis: calls the remote service object to generate a context
+// handle.
+//
+// Exceptions: none
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Notes: Thread safe
+//
+//--------------------------------------------------------------------
+SCODE CRpcService::CheckContextHdl( HAPT server )
+{
+ CairoleDebugOut((DEB_ENDPNT, "CRpcService::CheckContextHdl %p\n", this));
+ TRACECALL(TRACE_RPC, "CRpcService::CheckContextHdl");
+ AssertValid();
+
+ SCODE sc;
+ SGetContextHdl *params;
+
+ // single thread access
+ _mxs.Request();
+
+
+ if (this == LocalService())
+ {
+ _mxs.Release();
+ return S_OK;
+ }
+
+ if (_eState == disconnected_ss)
+ {
+ _mxs.Release();
+ return RPC_E_SERVER_DIED_DNE;
+ }
+
+ // Don't do anything if the context handle is already set.
+ if (_pContext != NULL)
+ {
+ _mxs.Release();
+ return S_OK;
+ }
+
+
+#ifdef _CHICAGO_
+ // initialize rpc for this thread
+ LocalService()->Listen(TRUE);
+ Win4Assert (IsThreadListening() == TRUE && "RpcService of this thread still not listen\n");
+#else
+ // make sure the remote protocols are registered locally if needed
+ if (DiffMachine())
+ {
+ WCHAR *pwszProtseq;
+ GetActiveProtseq(&pwszProtseq);
+ LocalService()->RegisterProtseq(pwszProtseq);
+ }
+
+#endif // _CHICAGO_
+
+ _mxs.Release();
+
+ // Get a parameter block.
+ params = new SGetContextHdl(ActuallyCallGetContextHdl,
+ CALLCAT_INTERNALINPUTSYNC, server);
+ if (params == NULL)
+ return E_OUTOFMEMORY;
+
+ // Fill in the parameters.
+ params->psepClient = LocalService()->CopySEp();
+ params->service = this;
+ AddRef();
+
+ // Switch threads.
+ if (params->psepClient != NULL)
+ sc = CChannelControl::GetOffCOMThread( (STHREADCALLINFO **) &params );
+ else
+ sc = E_OUTOFMEMORY;
+
+ // Free the parameter block.
+ if (sc != RPC_E_CALL_CANCELED)
+ {
+ delete params;
+ }
+ CairoleDebugOut((DEB_ENDPNT, "CRpcService::CheckContextHdl %p done\n", this));
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: ActuallyCallGetChannelId
+//
+// Synopsis: calls the remote service object to generate a channel
+// and return its id.
+//
+// This function is a channel control dispatch function. To avoid being
+// recalled when the call controller wants to retransmit, this function
+// never returns
+// RPC_E_SERVERCALL_RETRYLATER or RPC_E_SERVERCALL_REJECTED which are the
+// only errors the call controller retries.
+//
+// History: 27 Nov 93 AlexMit Hacked
+//
+//--------------------------------------------------------------------
+HRESULT ActuallyCallGetChannelId( STHREADCALLINFO *call )
+{
+ SGetChannelId *params = (SGetChannelId *) call;
+ ULONG cRetry = 0;
+ HRESULT result = S_OK;
+
+ // Make sure we have a handle to call on.
+ POBJCTX context = params->service->GetContextHdl();
+ params->channel_id = BAD_CHANNEL_ID;
+
+ if (!context)
+ {
+ result = E_HANDLE;
+ }
+ else if (params->psepClient == NULL)
+ {
+ result = E_OUTOFMEMORY;
+ }
+ else
+ do
+ {
+#if DBG==1
+ DWORD *tmp = (DWORD *) context;
+ CairoleDebugOut((DEB_MARSHAL,
+ "Calling ICS_GetChannelID Context=%x%x%x%x%x\n",
+ tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]));
+#endif
+
+ // Rpc call to remote RpcServiceObject
+ error_status_t errstat;
+
+ // Rpc call to remote RpcServiceObject
+ result = _ICS_GetChannelId(&context,
+ params->psepClient,
+ params->object_id,
+ params->flags,
+ params->server,
+ call->lid(),
+ params->dwClientTID,
+ &params->channel_id,
+ &errstat);
+
+ if (errstat != 0)
+ {
+ // Convert RPC return code to HRESULT incase we
+ // exit the loop!
+ result = HRESULT_FROM_WIN32(errstat);
+
+ // Should we retry the error?
+ if ((errstat == RPC_S_SERVER_TOO_BUSY))
+ {
+ continue;
+ }
+ }
+
+ // We only do this once unless there is an RPC error that
+ // encourages us to retry
+ break;
+
+ } while (++cRetry < MAX_RETRIES);
+
+ Win4Assert( (result == S_OK && params->channel_id != BAD_CHANNEL_ID) ||
+ (result != S_OK && params->channel_id == BAD_CHANNEL_ID) );
+ return result;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: SGetChannelId dtor
+//
+// Synopsis: Called when ActuallyGetChannelId is canceled. Releases
+// service.
+//
+// Exceptions: none
+//
+// History: 26 June 94 AlexMit Created
+// 7 July 94 CraigWi Changed to destructor
+//
+// Notes: Thread safe; client/server safe (only used on client side now)
+//
+//--------------------------------------------------------------------
+SGetChannelId::~SGetChannelId( )
+{
+ service->Release();
+ PrivMemFree(psepClient);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::GetChannelId
+//
+// Synopsis: calls the remote service object to generate a channel
+// and return its id.
+//
+// Exceptions: none
+//
+// History: 27-Nov-93 AlexMit Created
+//
+// Notes: Thread safe
+//
+//--------------------------------------------------------------------
+SCODE CRpcService::GetChannelId( OID ObjectId, DWORD dwFlags, HAPT hapt,
+ DWORD *pChannelId )
+{
+ TRACECALL(TRACE_RPC, "CRpcService::GetChannelId");
+ AssertValid();
+
+ SGetChannelId *params;
+ HRESULT result;
+
+ CairoleDebugOut((DEB_MARSHAL, "ICS_GetChannelId\n"));
+
+ // Get a parameter block.
+ *pChannelId = BAD_CHANNEL_ID;
+ params = new SGetChannelId(ActuallyCallGetChannelId,
+ CALLCAT_INTERNALINPUTSYNC, hapt);
+
+ if (params == NULL)
+ return E_OUTOFMEMORY;
+
+ // Fill in the parameters.
+ params->object_id = ObjectId;
+ params->flags = dwFlags;
+ params->dwClientTID = GetCurrentThreadId();
+ params->channel_id = BAD_CHANNEL_ID;
+ params->psepClient = LocalService()->CopySEp();
+ params->service = this;
+ AddRef(); // released in SGetChannelId dtor
+
+ // If local, just switch threads.
+ if (this == LocalService())
+ {
+ params->ResetDispatchFn(ThreadGetChannelId);
+ result = CChannelControl::SwitchCOMThread( hapt,
+ (STHREADCALLINFO **) &params );
+ }
+
+ // If remote, dispatch on some RPC thread.
+ else
+ {
+ params->server = hapt;
+ result = CChannelControl::GetOffCOMThread( (STHREADCALLINFO **) &params );
+ }
+
+ // return results and free packet
+ if (result != RPC_E_CALL_CANCELED)
+ {
+ *pChannelId = params->channel_id;
+ delete params;
+ }
+ Win4Assert( (result == S_OK && *pChannelId != BAD_CHANNEL_ID) ||
+ (result != S_OK && *pChannelId == BAD_CHANNEL_ID) );
+ return result;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: ActuallyCallReleaseChannel
+//
+// Synopsis: calls the remote channel service to release a proxy
+// for the object.
+//
+// History: 9 Nov 93 AlexMit Hacked
+// 3-31-95 JohannP Made call really sync or async
+//
+//
+// Note: For protocol wmsg the call is made sync or async by
+// calling the correct raw rpc call.
+// On other protocolls this is done on the server side
+// by choosing the correct mechanism to switch to the
+// appropriate thread form the rpc thread.
+//
+//--------------------------------------------------------------------
+HRESULT ActuallyCallReleaseChannel( STHREADCALLINFO *call )
+{
+
+ CairoleDebugOut((DEB_CHANNEL | DEB_ENDPNT , "ActuallyCallReleaseChannel()\n"));
+
+ SReleaseChannel *params = (SReleaseChannel *) call;
+ ULONG cRetry = 0;
+ HRESULT result;
+
+ // make sure we have a handle to call on
+ handle_t RpcHdl = params->service->GetRpcHdl();
+
+ if (!RpcHdl)
+ {
+ return E_HANDLE;
+ }
+
+ do
+ {
+ // Rpc call to remote RpcServiceObject
+ error_status_t errstat;
+
+#ifdef _CHICAGO_
+ if (params->async)
+ {
+
+ result = RPC_S_OK;
+ errstat = 0;
+ _ICS_AsyncReleaseChannel(RpcHdl, params->channel_id,
+ params->count, params->async,
+ call->lid());
+ }
+ else
+#endif // _CHICAGO_
+ {
+ CairoleDebugOut((DEB_CHANNEL | DEB_ENDPNT , "Calling _ICS_ReleaseChannel\n"));
+ result = _ICS_ReleaseChannel(RpcHdl, params->channel_id,
+ params->count, params->async,
+ call->lid(), &errstat);
+ CairoleDebugOut((DEB_CHANNEL | DEB_ENDPNT , "Calling _ICS_ReleaseChannel done errstat: %x\n",errstat));
+
+ if (errstat != 0)
+ {
+ // Convert RPC return code to HRESULT incase we
+ // exit the loop
+ result = HRESULT_FROM_WIN32(errstat);
+
+ // Should we retry the error?
+ if ((errstat == RPC_S_SERVER_TOO_BUSY))
+ {
+ continue;
+ }
+ }
+ }
+
+ // We only do this once unless there is an RPC error that
+ // encourages us to retry
+ break;
+
+ } while (++cRetry < MAX_RETRIES);
+ CairoleDebugOut((DEB_CHANNEL | DEB_ENDPNT , "ActuallyCallReleaseChannel() done \n"));
+ return result;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: SReleaseChannel dtor
+//
+// Synopsis: Called when ActuallyReleaseChannel is canceled. Releases
+// service.
+//
+// Exceptions: none
+//
+// History: 26 June 94 AlexMit Created
+// 7 July 94 CraigWi Changed to destructor
+//
+// Notes: Thread safe; client/server safe and called on both sides
+//
+//--------------------------------------------------------------------
+SReleaseChannel::~SReleaseChannel( )
+{
+ // NULL in the async case (server side)
+ if (service != NULL)
+ service->Release();
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::ReleaseChannel
+//
+// Synopsis: calls the remote channel service to release a proxy
+// for the object.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+SCODE CRpcService::ReleaseChannel(CRpcChannelBuffer *pChannel,
+ BOOL fAsyncRelease)
+{
+ TRACECALL(TRACE_RPC, "CRpcService::ReleaseChannel");
+ SReleaseChannel *params;
+ HRESULT hr;
+
+ // Check the state of this service object.
+ AssertValid();
+ if (_eState == disconnected_ss)
+ return RPC_E_SERVER_DIED_DNE;
+
+ // Get a parameter block.
+ params = new SReleaseChannel(
+ ActuallyCallReleaseChannel,
+ fAsyncRelease ? CALLCAT_ASYNC : CALLCAT_INTERNALSYNC,
+ pChannel->GetServerApt());
+
+ if (params == NULL)
+ return E_OUTOFMEMORY;
+
+ CairoleDebugOut((DEB_MARSHAL, "ICS_ReleaseChannel channel id=%x\n",
+ pChannel->GetID()));
+
+ // Fill in the parameters.
+ params->count = pChannel->GetMarshalCnt();
+ params->service = this;
+ AddRef(); // released in SReleaseChannel dtor
+ params->async = fAsyncRelease;
+ params->channel_id = pChannel->GetID();
+
+ // If local, just switch threads.
+ if (this == LocalService())
+ {
+ params->ResetDispatchFn(ThreadReleaseChannel);
+
+ // lookup and AddRef the channel controller for this channel id.
+ CChannelControl *pChanCtrl = ChannelList.LookupControl(params->channel_id);
+
+ if (pChanCtrl)
+ {
+ hr = pChanCtrl->SwitchCOMThread( (STHREADCALLINFO **) &params );
+ pChanCtrl->Release();
+ }
+ else
+ {
+ CairoleDebugOut((DEB_WARN, "ReleaseChannel: cant find pChanCtrl\n"));
+ hr = E_HANDLE;
+ }
+ }
+
+ // If remote, dispatch on some RPC thread.
+ else
+ {
+ hr = CChannelControl::GetOffCOMThread( (STHREADCALLINFO **) &params );
+ }
+
+ if (hr != RPC_E_CALL_CANCELED)
+ {
+ delete params;
+ }
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: ActuallyCallDoChannelOperation
+//
+// Synopsis: calls the remote channel service to do a channel operation
+//
+// History: 12 May 94 CraigWi Created
+//
+//--------------------------------------------------------------------
+HRESULT ActuallyCallDoChannelOperation( STHREADCALLINFO *call )
+{
+ SDoChannelOperation *params = (SDoChannelOperation *) call;
+ ULONG cRetry = 0;
+ HRESULT result;
+
+ // make sure we have a handle to call on
+ handle_t RpcHdl = params->service->GetRpcHdl();
+
+ if (!RpcHdl)
+ {
+ return E_HANDLE;
+ }
+
+ do
+ {
+ // Rpc call to remote RpcServiceObject
+ error_status_t errstat;
+
+ // Rpc call to remote RpcServiceObject
+ if (call->GetCallCat() == CALLCAT_SYNCHRONOUS)
+ result = _ICS_SyncChannelOp(RpcHdl,
+ params->channel_id,
+ call->lid(),
+ params->chop,
+ params->hapt,
+ &params->guid,
+ &errstat);
+ else
+ result = _ICS_InputSyncChannelOp(RpcHdl,
+ params->channel_id,
+ call->lid(),
+ params->chop,
+ params->hapt,
+ &params->guid,
+ &errstat);
+
+ if (errstat != 0)
+ {
+ // Convert RPC return code to HRESULT incase we exit
+ // the loop
+ result = HRESULT_FROM_WIN32(errstat);
+
+ // Should we retry the error?
+ if ((errstat == RPC_S_SERVER_TOO_BUSY))
+ {
+ continue;
+ }
+ }
+
+ // We only do this once unless there is an RPC error that
+ // encourages us to retry
+ break;
+
+ } while (++cRetry < MAX_RETRIES);
+ return result;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: SDoChannelOperation dtor
+//
+// Synopsis: Called when ActuallyDoChannelOperation is canceled. Releases
+// service.
+//
+// Exceptions: none
+//
+// History: 26 June 94 AlexMit Created
+// 7 July 94 CraigWi Changed to destructor
+//
+// Notes: Thread safe; client/server side safe
+//
+//--------------------------------------------------------------------
+SDoChannelOperation::~SDoChannelOperation()
+{
+ if (service)
+ service->Release();
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::DoChannelOperation
+//
+// Synopsis: calls the remote channel service to do a channel operation
+//
+// Parameters: [dwChannelId] -
+// [chop] - channel operation
+// [pEndPoint] - our endpoint
+// [hapt] - server apartment id
+// [pguid] - IID for DoesSupportIID
+//
+// History: 12 May 94 CraigWi Created
+//
+//--------------------------------------------------------------------
+SCODE CRpcService::DoChannelOperation(DWORD dwChannelID, DWORD chop,
+ HAPT hapt, const GUID *pguid)
+{
+ TRACECALL(TRACE_RPC, "CRpcService::DoChannelOperation");
+ HRESULT result;
+ AssertValid();
+
+ // Fail if this service object has been disconnected.
+ if (_eState == disconnected_ss)
+ return RPC_E_SERVER_DIED_DNE;
+
+ // Allocate memory to pass the parameters.
+ SDoChannelOperation *params;
+
+ // match the decision in CRpcService::DoChannelOperation
+ CALLCATEGORY callcat;
+ if ((chop & CHOP_OPERATION) <= CHOP_TRANSFER_MARSHALCONNECTION)
+ callcat = CALLCAT_INTERNALINPUTSYNC;
+ else
+ callcat = CALLCAT_SYNCHRONOUS;
+
+ params = new SDoChannelOperation(
+ ActuallyCallDoChannelOperation,
+ callcat,
+ hapt);
+
+ if (params == NULL)
+ return E_OUTOFMEMORY;
+
+ CairoleDebugOut((DEB_MARSHAL, "ICS_DoChannelOperation channel id=%x\n",
+ dwChannelID));
+
+ if (pguid != NULL)
+ params->guid = *pguid;
+ params->chop = chop;
+ params->hapt = hapt;
+ params->service = this;
+ params->channel_id = dwChannelID;
+
+ AddRef(); // released in SDoChannelOperation dtor
+
+ // If local, just switch threads.
+ if (this == LocalService())
+ {
+ params->ResetDispatchFn(ThreadDoChannelOperation);
+ CChannelControl *pChanCtrl = ChannelList.LookupControl(dwChannelID);
+
+ if (pChanCtrl)
+ {
+ result = pChanCtrl->SwitchCOMThread( (STHREADCALLINFO **) &params );
+ pChanCtrl->Release();
+ }
+ else
+ {
+ CairoleDebugOut((DEB_WARN, "DoChannelOp Cant find pChanCtrl\n"));
+ result = E_HANDLE;
+ }
+ }
+
+ // If remote, dispatch on some RPC thread.
+ else
+ {
+ result = CChannelControl::GetOffCOMThread( (STHREADCALLINFO **) &params );
+ }
+
+ if (result != RPC_E_CALL_CANCELED)
+ {
+ delete params;
+ }
+ return result;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::TransferMarshalConnection
+//
+// Synopsis: calls the remote channel service increment marshal count.
+//
+// History: 27-Nov-93 AlexMit Created
+// 12-May-94 CraigWi Funneled through DoChannelOperation
+//
+//--------------------------------------------------------------------
+SCODE CRpcService::TransferMarshalConnection( DWORD dwChannelID )
+{
+ TRACECALL(TRACE_RPC, "CRpcService::TransferMarshalConnection");
+ AssertValid();
+
+ return DoChannelOperation(dwChannelID, CHOP_TRANSFER_MARSHALCONNECTION,
+ haptNULL, NULL);
+}
+
+
+//+------------------------------------------------------------------------
+//
+// Member: CRpcService::AddMarshalConnection, public
+//
+// Synopsis: does the part of normal marshaling that we can't do on the client
+//
+// History: 14-May-94 CraigWi Created
+//
+//-------------------------------------------------------------------------
+SCODE CRpcService::AddMarshalConnection(DWORD dwChannelID, HAPT hapt, REFOID roid)
+{
+ TRACECALL(TRACE_RPC, "CRpcService::AddMarshalConnection");
+ AssertValid();
+
+ return DoChannelOperation(dwChannelID,
+ CHOP_ADD_MARSHALCONNECTION | CHOPFLAG_CHECK_OID_ENDPOINT_APT,
+ hapt, &roid);
+}
+
+
+//+------------------------------------------------------------------------
+//
+// Member: CRpcService::RemoveMarshalConnection, public
+//
+// Synopsis:
+//
+// History: 14-May-94 CraigWi Created
+//
+//-------------------------------------------------------------------------
+SCODE CRpcService::RemoveMarshalConnection(DWORD dwChannelID)
+{
+ TRACECALL(TRACE_RPC, "CRpcService::RemoveMarshalConnection");
+ AssertValid();
+
+ return DoChannelOperation(dwChannelID, CHOP_REMOVE_MARSHALCONNECTION,
+ haptNULL, NULL);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::QueryObjectInterface
+//
+// Synopsis: calls the remote object to instantiate a new interface
+// on the object.
+//
+// History: 23-Nov-93 Rickhi Created
+// 12-May-94 CraigWi Funneled through DoChannelOperation
+//
+//--------------------------------------------------------------------
+SCODE CRpcService::QueryObjectInterface(DWORD channel_id, REFIID riid)
+{
+ TRACECALL(TRACE_RPC, "CRpcService::QueryObjectInterface");
+ AssertValid();
+
+ return DoChannelOperation(channel_id, CHOP_DOESSUPPORTIID,
+ haptNULL, &riid);
+}
+
+
+//+------------------------------------------------------------------------
+//
+// Member: CRpcService::LockObjectConnection, public
+//
+// Synopsis: locks/unlocks the connection for the container
+//
+// History: 14-May-94 CraigWi Created
+//
+//-------------------------------------------------------------------------
+SCODE CRpcService::LockObjectConnection(DWORD dwChannelID, BOOL fLock, BOOL fLastUnlockCloses)
+{
+ TRACECALL(TRACE_RPC, "CRpcService::LockObjectConnection");
+ AssertValid();
+
+ DWORD chop = (fLock ? CHOP_LOCK_CONNECTION : CHOP_UNLOCK_CONNECTION);
+ if (fLastUnlockCloses)
+ chop |= CHOPFLAG_LASTUNLOCKCLOSES;
+
+ return DoChannelOperation(dwChannelID, chop, haptNULL, NULL);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::Disconnect, public
+//
+// Synopsis: Called by rundown and at CoUninitialize; simulates
+// a simulatneous disconnect by all clients for which
+// this service object represents.
+//
+// History: 27-Nov-93 AlexMit Created (was in Rundown)
+// 22-Feb-94 CraigWi Separated out Disconnect
+//
+//--------------------------------------------------------------------
+void CRpcService::Disconnect()
+{
+ AssertValid();
+
+ {
+ // single thread access
+ CLock lck(_mxs);
+
+ _eState = disconnected_ss;
+
+ // At this point the lock goes out of scope. We must not hold it
+ // across DisconnectService since that may switch threads.
+ }
+
+ // this works even during shutdown since before the channel list is cleaned
+ // up, the semaphores and the channel control state (which prevents thread
+ // switches after shutdown is called) keep things working correctly.
+ // After the channel list is cleared, the disconnect won't find a match.
+
+ ChannelList.DisconnectService(this);
+}
+
+
+#if DBG == 1
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::AssertValid
+//
+// Synopsis: Validates that the state of the object is consistent.
+//
+// History: 21-Jan-94 CraigWi Created.
+//
+//--------------------------------------------------------------------
+void CRpcService::AssertValid()
+{
+ Win4Assert(_ulRefCnt < 0x7fff && "Service ref count unreasonably high");
+
+ if (this == LocalService())
+ {
+ if (IsServiceListen())
+ {
+ if (_CEp.GetSEp() != NULL)
+ {
+ Win4Assert(GoodSEp(_CEp.GetSEp()));
+ }
+ }
+
+#ifndef _CHICAGO_
+ Win4Assert(_hRpc.Handle() == NULL);
+ Win4Assert(_pContext == NULL);
+ Win4Assert(_eState == client_ss);
+#endif
+ }
+ else if (_eState == client_ss)
+ {
+#ifndef _CHICAGO_
+ Win4Assert(_CEp.GetSEp() != NULL);
+#endif
+ if (_CEp.GetSEp() != NULL)
+ {
+ Win4Assert(GoodSEp(_CEp.GetSEp()));
+ }
+
+ // if _pContext is set, must have binding handle
+ if (_pContext != NULL)
+ Win4Assert(_hRpc.Handle() != NULL);
+
+ if (_hRpc.Handle() != NULL)
+ {
+ unsigned int timeout;
+ Win4Assert(RpcMgmtInqComTimeout(_hRpc.Handle(), &timeout) == RPC_S_OK);
+ }
+ }
+ else if (_eState == disconnected_ss)
+ {
+ }
+ else
+ {
+ Win4Assert(!"Service Object with invalid state");
+ }
+}
+#endif // DBG == 1
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CSrvList::FindSRVFromEP
+//
+// Synopsis: finds an Rpc service object using the specified Endpoint
+//
+// Arguments: [pSEP] - endpoint structure for the service object
+// [fCreate] - TRUE means create if not found
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Notes: Thread Safe
+//
+//--------------------------------------------------------------------
+CRpcService * CSrvList::FindSRVFromEP(SEndPoint *pSEp, BOOL fCreate)
+{
+ CairoleDebugOut((DEB_ENDPNT, "CSrvList::FindSRVFromEP this:%p; pSEp:%p\n", this, pSEp));
+ // single thread access to this code
+ COleStaticLock lck(sg_SrvListLock);
+
+ // starting from the list head
+ CRpcService *pSrv = _List.first();
+
+ while (pSrv)
+ {
+ // look for a match in the endpoints; do not find disconnected
+ // service objects; this may occur during shutdown.
+ if (pSrv->_eState != disconnected_ss && pSrv->IsEqualEp(pSEp))
+ {
+ Win4Assert( pSrv->_eState != disconnected_ss );
+ pSrv->AddRef();
+ pSrv->AssertValid();
+ return pSrv;
+ }
+ pSrv = _List.next(pSrv);
+ }
+
+ // no match found, make a new one
+ if (fCreate)
+ {
+ HRESULT hr = E_OUTOFMEMORY;
+ pSrv = new CRpcService(pSEp, hr);
+ if (SUCCEEDED(hr))
+ {
+#if DBG==1
+ if (LocalService() != NULL)
+ pSrv->AssertValid();
+#endif
+ _List.insert_at_end(pSrv);
+ }
+ else if (pSrv)
+ {
+ // allocation succeeded, but there was some other
+ // constructor error
+ delete pSrv;
+ pSrv = NULL;
+ }
+ }
+
+ CairoleDebugOut((DEB_ENDPNT, "CSrvList::FindSRVFromEP this:%p; pSerive:%p done\n", this, pSrv));
+ return pSrv;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CSrvList::FindSRVFromContext
+//
+// Synopsis: finds an Rpc service object using the specifed
+// context handle.
+//
+// Arguments: [hObjCtx] - Context handle provided by RPC
+// [fRemove] - TRUE means remove the object from the list
+//
+// Returns: NULL - handle could not be validated by us.
+// ~NULL - we found the object.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Notes: Thread Safe
+//
+//--------------------------------------------------------------------
+CRpcService *CSrvList::FindSRVFromContext(POBJCTX phObjCtx, BOOL fRemove)
+{
+ // the context handle should be a pointer to a service object.
+ CRpcService *pSrv = (CRpcService *)phObjCtx;
+
+ // single thread access to this code
+ COleStaticLock lck(sg_SrvListLock);
+
+ CRpcService *linkp = _List.first();
+
+ while (linkp != NULL)
+ {
+ if (linkp == pSrv)
+ {
+ linkp->AddRef();
+
+ if (fRemove)
+ {
+ // remove this service object from the list
+ linkp->delete_self();
+ }
+
+ break;
+ }
+
+ linkp = _List.next(linkp);
+ }
+
+ return linkp;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CSrvList::Cleanup
+//
+// Synopsis: Releases the service objects in the list.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Notes: C++ rules dictate that the class destructor gets called
+// before member destructors, which get called before base
+// class destructors.
+//
+// Notes: Thread Safe
+//
+//--------------------------------------------------------------------
+void CSrvList::Cleanup(void)
+{
+ COleStaticLock lck(sg_SrvListLock);
+
+ CRpcService *linkp;
+
+ // The rundown routine will validate its pointer from the RPC runtime
+ // and takes a mutex which will exclude this object from being Released
+ // until the call completes.
+
+ while ((linkp = _List.first()) != NULL)
+ {
+ linkp->Release();
+ }
+}
+//+-------------------------------------------------------------------
+//
+// Member: CSrvList::~CSrvList
+//
+// Synopsis: Leaks the entire list without freeing memory or calling
+// destructors. Since the service list is static, it
+// gets destroyed after all DLLs are uninitialized. This
+// causes some DLLs to crash.
+//
+// The destructor is only called at process detach. The
+// list gets cleaned up by CoUninitialize.
+//
+// History: 7 Nov 94 AlexMit Created
+//
+//--------------------------------------------------------------------
+CSrvList::~CSrvList()
+{
+ // Yes, this is really what I want to do. Read the header.
+ _List.no_cleanup();
+}
diff --git a/private/ole32/com/remote/service.hxx b/private/ole32/com/remote/service.hxx
new file mode 100644
index 000000000..12b125b95
--- /dev/null
+++ b/private/ole32/com/remote/service.hxx
@@ -0,0 +1,678 @@
+//+-------------------------------------------------------------------
+//
+// File: service.hxx
+//
+// Contents: Rpc service class definition
+//
+// Classes: CRpcService - Rpc service object
+//
+// Functions:
+//
+// History: 23-Nov-92 Rickhi Created
+// 31-Dec-93 ErikGav Chicago port
+//
+// Notes: there are two kinds of service objects, local and remote.
+//
+// only one local service object exists. it registers the
+// IChannelService interface with Rpc and spawns a thread to
+// listen for incomming requests.
+//
+// there is one remote service object for each processe that
+// we are communicating with. they talk to the other processes
+// via Rpc calls on IChannelService to open and close context
+// handles to objects within a process.
+//
+// each service object has a chain of channels. the service
+// that a channel is chained off indicates which process
+// the channel talks to.
+//
+//--------------------------------------------------------------------
+#ifndef __SERVICE__
+#define __SERVICE__
+
+// forward declarations for the classes defined herein
+class CRpcService;
+class CSrvList;
+class CRpcChannelBuffer;
+
+// global ptrs to the service object list & local service object
+#ifndef _CHICAGO_
+extern CSrvList sg_SrvList;
+#endif
+
+
+#include <olesem.hxx> // COleCommonMutexSem, COleStaticLock
+#include <sem.hxx> // CMutexSem, CLock
+#include <objerror.h> // Rpc errors
+#include <dd.hxx> // CListEntry
+#include <thread.hxx> // CThread
+#include <iface.h> // PPOBJCTX
+#include <endpnt.hxx> // CEndPoint, SEndPoint
+#include <rpcbind.hxx> // CRpcBindHandle
+#include <olerem.h>
+#include <islocalp.hxx> // For telling if service is local
+
+
+extern COleStaticMutexSem sg_SrvListLock;
+
+// Prototypes.
+SCODE StopListen( void );
+
+// Service object state. The first three bytes are the string "svc".
+typedef enum EServiceState
+{
+ client_ss = 0x73766300,
+ server_ss,
+ disconnected_ss,
+ deleted_ss
+} EServiceState;
+
+
+// sleep timeout before rety when receiving a SERVER_TOO_BUSY error.
+// time is in milliseconds.
+#define SERVER_BUSY_SLEEP_MS 50
+
+//+-------------------------------------------------------------------------
+//
+// Class: CRpcService (svc)
+//
+// Purpose: Rpc service object. This maintains the endpoint and Rpc
+// binding handle to an Rpc service. Note that there is an
+// Rpc service for the local process as well, though we do
+// not bind to it.
+//
+// Notes: The two kinds of service objects are:
+// Local (sg_pLocalSrv and in sg_SrvList).
+// Created at startup; logically, sg_SrvList owns
+// the ref count that keeps it alive; released at shutdown
+// State:
+// _CEp only available if listening
+// _hRpc == NULL (never connected to a server)
+// _pContext == NULL ( " " " " " )
+// _eState == client_ss
+//
+// Remote (only in sg_SrvList)
+// Created each time we contact a new process (which is
+// identified by its string binding). When acting as a
+// client, the channel keeps an addref'd pointer; that
+// pointer is released when the channel is disconnected or
+// destroyed. When acting as a server (possibly the same
+// instance doing both), the existance of the context handle
+// keeps a ref; i.e., when the context handle is freed
+// (via the rundown), the service object is released.
+// State:
+// _CEp passed in at creation
+// _hRpc set when connected to a server
+// _pContext set when received ctx hdl from srv
+// (it is this that logically holds the service object
+// in the server process alive)
+// _eState == client_ss
+//
+// Disconnected_ss is used to mark a Remote service object that
+// has been disconnect (received a rundown from its client or
+// was connected at the time of CoUnintialize); in this case,
+// the state associated with the server, if any, is also
+// cleared.
+// State:
+// _CEp meaningless, but present
+// _hRpc == NULL
+// _pContext == NULL
+// _eState == disconnected_ss
+//
+// Server_ss is not used currently.
+//
+// History: 23-Nov-92 Rickhi Created
+// 19-Jan-94 Alexmit Moved context handles here
+// 20-Jan-94 Craigwi Tried to document better and add asserts
+//
+//--------------------------------------------------------------------------
+class CRpcService : public CListEntry
+{
+ friend CSrvList;
+ friend CRpcService *LocalService (void);
+ friend void SetLocalService ( CRpcService * );
+ friend BOOL IsInLocalProcess(CEndPoint *pcep);
+
+public:
+ CRpcService(SEndPoint *pSEp, HRESULT &hr);
+ ~CRpcService(void);
+
+ // used by compobj to start the Rpc server if not already done
+ SCODE StartListen(void);
+
+ // used by channel code to start/stop the Rpc server
+ SCODE Listen(BOOL fListenNow = FALSE); // do RpcServerListen
+ SCODE RegisterProtseq(WCHAR *pwszProtseq);
+ SCODE RemoteRegisterProtseq(WCHAR *pwszProtseq);
+
+ // IChannelServer interface used by channels
+ SCODE CheckContextHdl( HAPT server );
+ POBJCTX GetContextHdl( void );
+ SCODE SetContextHdl( POBJCTX );
+ SCODE GetChannelId( OID ObjectId, DWORD dwFlags, HAPT server,
+ DWORD *dwChannelId );
+ SCODE ReleaseChannel(CRpcChannelBuffer *pChannel,
+ BOOL fAsyncRelease);
+ SCODE TransferMarshalConnection(DWORD dwChannelID);
+ SCODE AddMarshalConnection(DWORD dwChannelID, HAPT hapt, REFOID roid);
+ SCODE RemoveMarshalConnection(DWORD dwChannelID);
+ SCODE QueryObjectInterface(DWORD dwChannelID, REFIID riid);
+ SCODE LockObjectConnection(DWORD dwChannelID, BOOL fLock,
+ BOOL fLastReleaseCloses);
+
+ handle_t GetRpcHdl(void);
+ BOOL IsConnected(void);
+ void Disconnect(void);
+
+ // used by marshalling/unmarshalling code
+ void GetDestCtx(DWORD *pdwDestCtx, void **);
+ BOOL IsEqualEp(SEndPoint *pEp);
+ SEndPoint *GetSEp(void);
+ SEndPoint *CopySEp(void);
+ ULONG GetSEpSize(void);
+
+ LPWSTR GetStringBinding(void);
+ BOOL GetActiveProtseq(WCHAR **ppwszProtseq);
+ void SetActiveProtseq(void);
+ BOOL DiffMachine(void);
+ ULONG AddRef(void);
+ ULONG Release(void);
+ BOOL IsServiceListen() { return _fListening; }
+ void SetServiceListen(BOOL fListen) {_fListening = fListen; }
+
+#ifdef _CHICAGO_
+ BOOL NotifyServerOfSEp(void);
+ void SetSEp(SEndPoint *pSEp)
+ {
+ _CEp.SetNewSEp(pSEp);
+ }
+#endif
+
+#if DBG == 1
+ void AssertValid();
+#else
+ void AssertValid() { }
+#endif
+
+private:
+
+ SCODE Bind(void); // bind to the appropriate endpoint
+ SCODE DoChannelOperation(DWORD dwChannelID, DWORD chop,
+ HAPT hapt, const IID *piid);
+
+ CEndPoint _CEp; // Rpc end point
+ CRpcBindHandle _hRpc; // Rpc binding handle
+ CMutexSem _mxs; // mutex semaphore
+ POBJCTX _pContext; // Context Handle
+ EServiceState _eState; // State of object
+ ULONG _ulRefCnt; // Reference count
+ BOOL _fThisProcess; // Ep is in this process
+ BOOL _fListenNow;
+#ifdef _CHICAGO_
+ BOOL _fListening;
+#else
+
+ static BOOL _fListening;
+ static CRpcService *sg_pLocalSrv;
+#endif
+};
+
+
+//+-------------------------------------------------------------------
+//
+// Member: LocalService, public
+//
+// Synopsis: Get the local service object. For NT each process has a
+// service object. For Chicago each thread has a service
+// object.
+//
+// History: 3-Aug-94 AlexMit Created
+//
+//--------------------------------------------------------------------
+
+inline CRpcService *LocalService()
+{
+#ifdef _CHICAGO_
+ return (CRpcService *) TLSGetService();
+#else
+ return CRpcService::sg_pLocalSrv;
+#endif
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: SetLocalService, public
+//
+// Synopsis: Saves a service pointer in the service objects global
+//
+// History: 3-Aug-94 AlexMit Created
+//
+//--------------------------------------------------------------------
+inline void SetLocalService( CRpcService *pService )
+{
+#ifdef _CHICAGO_
+ TLSSetService(pService);
+#else
+ CRpcService::sg_pLocalSrv = pService;
+#endif
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::StartListen, public
+//
+// Synopsis: starts the Rpc service listening if it is not
+// doing so already.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline SCODE CRpcService::StartListen(void)
+{
+ Win4Assert( this == LocalService() );
+ AssertValid();
+
+ if (!IsServiceListen())
+ {
+ // not already listening, start it listening now
+ return Listen();
+ }
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::GetRpcHdl, public
+//
+// Synopsis: returns the Rpc handle for the remote Rpc service. This
+// is used when an Rpc call is made to the remote service.
+// We dont bind until someone asks for the handle.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline handle_t CRpcService::GetRpcHdl(void)
+{
+ AssertValid();
+ if (_hRpc.Handle() == NULL)
+ {
+ Bind(); // have not bound yet, do it now
+ }
+ return _hRpc.Handle();
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::GetContextHdl, public
+//
+// Synopsis: returns the Rpc context for the remote Rpc service. This
+// is used when an Rpc call is made to the remote service.
+//
+// History: 29-Nov-93 AlexMit Created
+//
+//--------------------------------------------------------------------
+inline POBJCTX CRpcService::GetContextHdl(void)
+{
+ AssertValid();
+ CLock lck(_mxs);
+ if (_eState == disconnected_ss)
+ return NULL;
+
+ return _pContext;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::SetContextHdl, public
+//
+// Synopsis: Set the context handle if it has not yet been set.
+//
+// History: 2-Aug-94 AlexMit Created
+//
+//--------------------------------------------------------------------
+
+inline SCODE CRpcService::SetContextHdl(POBJCTX pContext)
+{
+ AssertValid();
+ CLock lck(_mxs);
+ if (_pContext == NULL)
+ {
+ _pContext = pContext;
+ return S_OK;
+ }
+ else
+ return E_FAIL;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::IsEqualEp, public
+//
+// Synopsis: returns TRUE if the given EndPoint matches the one used
+// by this service object.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline BOOL CRpcService::IsEqualEp(SEndPoint *pSEp)
+{
+ Win4Assert(pSEp && "Invalid parameter");
+ AssertValid();
+ return _CEp.IsEqual(pSEp);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::GetSEpSize, public
+//
+// Synopsis: returns the size of the EndPoint structure stored in
+// this service object. This is used to calculate the
+// size of buffer needed when marshalling an interface.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline ULONG CRpcService::GetSEpSize(void)
+{
+ AssertValid();
+ if (!IsServiceListen() && this == LocalService())
+ {
+ // this is the local service object, and we need to start the
+ // server listening so we can marshal this interface
+ if (StartListen() != S_OK)
+ return 0;
+ }
+ return _CEp.GetSEpSize();
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::GetSEp, public
+//
+// Synopsis: returns the EndPoint structure stored in this service
+// object.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline SEndPoint *CRpcService::GetSEp(void)
+{
+ AssertValid();
+ if (!IsServiceListen() && this == LocalService())
+ {
+ // this is the local service object, and we need to start the
+ // server listening so we can marshal this interface
+ StartListen();
+ }
+ return _CEp.GetSEp();
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::CopySEp, public
+//
+// Synopsis: returns a copy of the EndPoint structure stored in
+// this service object.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline SEndPoint * CRpcService::CopySEp(void)
+{
+ AssertValid();
+ CLock lck(_mxs);
+ if (!IsServiceListen() && this == LocalService())
+ {
+ // this is the local service object, and we need to start the
+ // server listening so we can marshal this interface
+ if (StartListen() != S_OK)
+ {
+ return NULL;
+ }
+ }
+ return _CEp.CopySEp();
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::DiffMachine
+//
+// Synopsis: asks the endpoint whether or not it refers to this machine
+//
+// History: 23-Nov-93 Rickhi Created
+// 24-Nov-93 AlexMit Implemented
+//
+//--------------------------------------------------------------------
+inline BOOL CRpcService::DiffMachine()
+{
+ AssertValid();
+ return _CEp.DiffMachine();
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::GetStringBinding
+//
+// Synopsis: returns the most favoured string binding for this
+// service object
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline LPWSTR CRpcService::GetStringBinding(void)
+{
+ AssertValid();
+ if (!IsServiceListen() && this == LocalService())
+ {
+ // this is the local service object, and we need to start the
+ // server listening so we can marshal this interface
+ if (StartListen() != S_OK)
+ return NULL;
+ }
+ return _CEp.GetStringBinding();
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::IsConnected
+//
+// Synopsis: quickly determines if this service is probably connected
+// to its twin in the other process. The negative answer
+// is definitive (i.e., we know when we are definitely not
+// connected). This method is really only useful if the
+// service object has ever acted as a server (i.e., gave
+// out a context handle). This will be true in lots and lots
+// of cases (e.g., ole embeddings).
+//
+// History: 08-Feb-94 CraigWi Created
+//
+//--------------------------------------------------------------------
+inline BOOL CRpcService::IsConnected()
+{
+ AssertValid();
+
+ // we can't check _hRpc or _pContext because they are not set
+ // in a service object which is servicing a remote process and which
+ // is not acting as a client of that process.
+ return _eState != disconnected_ss;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcService::Get/SetActiveProtseq, public
+//
+// Synopsis: returns the protocol sequence we are using to talk to
+// a remote server. This is needed when we marshal an interface
+// to pass back to the server to make sure we have registered
+// that protocol sequence with Rpc.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+//--------------------------------------------------------------------
+inline BOOL CRpcService::GetActiveProtseq(WCHAR **ppwszProtseq)
+{
+ AssertValid();
+ return _CEp.GetActiveProtseq(ppwszProtseq);
+}
+
+inline void CRpcService::SetActiveProtseq(void)
+{
+ AssertValid();
+ _CEp.SetActiveProtseq();
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSrvListBase ()
+//
+// Purpose: Base class for Head list of Rpc service objects
+//
+// Interface: first -- get first item in the list.
+// next -- get next item in the list.
+//
+// History: 23-Nov-92 Rickhi Created
+//
+// Notes: See dd.hxx for details of this macro.
+//
+//--------------------------------------------------------------------------
+DERIVED_LIST_HEAD(CSrvListBase, CRpcService);
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSrvList ()
+//
+// Purpose: Head list of Rpc service objects
+//
+// Interface: AddToList -- add an entry to a list of remote handlers
+//
+// History: 23-Nov-92 Rickhi Created
+//
+// Notes: This class adds a few methods to its macro defined base
+// class. It requires a destructor so that it can clean up any
+// remaining entries in the base list BEFORE the destructor
+// for the mutex is called.
+//
+//--------------------------------------------------------------------------
+class CSrvList
+{
+public:
+ CSrvList(void) {}
+ ~CSrvList();
+
+ CRpcService *FindSRVFromEP(SEndPoint *pSEp, BOOL fCreate);
+ CRpcService *FindSRVFromContext(POBJCTX hObjCtx, BOOL fRemove);
+
+ void RemoveFromList(CRpcService *pSrv);
+ void Cleanup(void);
+
+private:
+
+ CSrvListBase _List;
+};
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CSrvList::RemoveFromList
+//
+// Synopsis: removes an Rpc service object from the list of service
+// objects. called by the service objects destructors to
+// remove themselves from the list in a thread safe way.
+//
+// History: 23-Nov-93 Rickhi Created
+//
+// Notes: Thread Safe
+//
+//--------------------------------------------------------------------
+inline void CSrvList::RemoveFromList(CRpcService *pSRVToRemove)
+{
+ // validate input parms
+ Win4Assert(pSRVToRemove);
+
+ if (pSRVToRemove->connected())
+ {
+ COleStaticLock lck(sg_SrvListLock);
+ pSRVToRemove->delete_self();
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: FindSRVFromEP
+//
+// Synopsis: Calls FindSRVFromEP on the service list for the current
+// thread.
+//
+// History: 6 Sept 94 AlexMit Created
+//
+//--------------------------------------------------------------------
+#ifndef _CHICAGO_
+inline CRpcService *FindSRVFromEP(SEndPoint *pSEp, BOOL fCreate)
+{
+ return sg_SrvList.FindSRVFromEP( pSEp, fCreate );
+}
+#else
+inline CRpcService *FindSRVFromEP(SEndPoint *pSEp, BOOL fCreate)
+{
+ CSrvList *pSrvList = (CSrvList *) TLSGetServiceList();
+
+ if (pSrvList != NULL)
+ return pSrvList->FindSRVFromEP( pSEp, fCreate );
+ else
+ return NULL;
+}
+#endif
+
+//+-------------------------------------------------------------------
+//
+// Function: FindSRVFromContext
+//
+// Synopsis: Calls FindSRVFromContext on the service list for the current
+// thread.
+//
+// History: 6 Sept 94 AlexMit Created
+//
+//--------------------------------------------------------------------
+#ifndef _CHICAGO_
+inline CRpcService *FindSRVFromContext(POBJCTX hObjCtx, BOOL fRemove)
+{
+ return sg_SrvList.FindSRVFromContext( hObjCtx, fRemove );
+}
+#else
+inline CRpcService *FindSRVFromContext(POBJCTX hObjCtx, BOOL fRemove)
+{
+ CSrvList *pSrvList = (CSrvList *) TLSGetServiceList();
+
+ if (pSrvList != NULL)
+ return pSrvList->FindSRVFromContext( hObjCtx, fRemove );
+ else
+ return NULL;
+}
+#endif
+
+inline BOOL IsThreadListening(void)
+{
+ return LocalService()->IsServiceListen();
+}
+inline void SetThreadListening(BOOL fListen)
+{
+ LocalService()->SetServiceListen(fListen);
+}
+
+#endif // __SERVICE__
diff --git a/private/ole32/com/remote/sichnl.cxx b/private/ole32/com/remote/sichnl.cxx
new file mode 100644
index 000000000..fe783256e
--- /dev/null
+++ b/private/ole32/com/remote/sichnl.cxx
@@ -0,0 +1,918 @@
+//+-------------------------------------------------------------------
+//
+// File: sichnl.cxx
+//
+// Contents: stub implementation for remoting IChannelService
+//
+// Classes: none
+//
+// Functions: ICS_GetObjectHdl - get object handle
+// ICS_ReleaseObject - release object
+// POBJCTX_Rundown - rundown on dropped connections
+//
+// History: 23-Nov-92 Rickhi Created
+// 31-Dec-93 ErikGav Chicago port
+// 19 Jul 94 CraigWi Added support for ASYNC calls
+//
+//--------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include <olerem.h>
+#include <channelb.hxx> // CRpcChannelBuffer
+#include <ichnl.h> // midl generated interface definitions
+#include <objact.hxx> // gdllcacheInprocSrv
+#include <sichnl.hxx>
+
+#include "callmain.hxx" // for access to callcat of outgoing call
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ThreadGetChannelId
+//
+// Synopsis: Creates a channel for the specified remote handler and
+// service object.
+//
+// Arguments: rh - remote handler to call
+//
+// Returns: S_OK, E_HANDLE
+//
+// History: 30 Nov 93 AlexMit Created
+// 12 May 94 CraigWi Removed middle man case
+//
+// Notes: This must run on the server thread because the RH release
+// can cause the object to be released (if the context handle
+// ran down during the call).
+//
+// REF COUNTING:
+//
+// We always increment the marshal count (i.e., set it to 1) because
+// then clients don't have to make a separate call to get it incremented.
+//
+// In all normal cases we already did the AddConnection; in the middle man
+// case, this was done during marshaling by calling over to the server. This
+// was important to ensure the object stays alive in the face of other
+// disconnects. In the table case we always need the AddConnection since the
+// marshal just did AddConnection for the marshal itself.
+//
+// CODEWORK: when we precompute the channel, this routine would only be used
+// for the table case (since we would need to get the right channel created).
+//
+//--------------------------------------------------------------------------
+
+HRESULT ThreadGetChannelId( STHREADCALLINFO *call )
+{
+ SGetChannelId *params = (SGetChannelId *) call;
+ IStdIdentity *pStdId = NULL;
+ IMarshal *pIM = NULL;
+ IRemoteHdlr *pRH = NULL;
+ CRpcChannelBuffer *pChannel = NULL;
+ CChannelControl *controller;
+ HRESULT hr = E_INVALIDARG;
+ BOOL fAddedConnection = FALSE;
+
+ // See if the client (the app that made this call) died before we got
+ // here.
+ if (!params->service->IsConnected())
+ {
+ // It doesn't matter what is returned since the caller is dead.
+ return E_FAIL;
+ }
+
+ // See if the channel has already been created. The client can attempt
+ // to unmarshal the same channel twice when it yields to get the
+ // the channel id.
+ params->channel_id = ChannelList.LookupIdByOid( params->object_id,
+ params->service,
+ params->dwClientTID );
+ if (params->channel_id != BAD_CHANNEL_ID)
+ {
+ return S_OK;
+ }
+
+ BEGIN_BLOCK
+
+ // Find the remote handler. Since the identity holds the remote
+ // handler alive, it can not be released till the remote handler has
+ // been released.
+
+ hr = LookupIDFromID(params->object_id, TRUE, &pStdId);
+
+ if (FAILED(hr))
+ {
+ EXIT_BLOCK;
+ }
+
+ if ((pIM = pStdId->GetStdRemMarshal()) == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ EXIT_BLOCK;
+ }
+
+ hr = pIM->QueryInterface(IID_IRemoteHdlr, (void **) &pRH);
+
+ if (FAILED(hr))
+ {
+ EXIT_BLOCK;
+ }
+
+ if ((params->flags & HDLRFLAGS_TABLE) != MSHLFLAGS_NORMAL)
+ {
+ // this is always strong since we are adding the
+ // connection that is normally added at marshal time
+ // Note: we count on the fact this only updates the
+ // identity object and makes no call to the channel.
+ hr = pStdId->AddConnection(EXTCONN_STRONG | EXTCONN_CALLABLE, 0);
+
+ if (FAILED(hr))
+ {
+ EXIT_BLOCK;
+ }
+
+ fAddedConnection = TRUE;
+ }
+
+ // Create the channel.
+ GetLocalChannelControl(controller);
+
+ pChannel = new CRpcChannelBuffer(pRH, params->service,
+ params->dwClientTID, controller, server_cs);
+
+ if (pChannel == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ EXIT_BLOCK;
+ }
+
+ // Add the channel to the list; AddRefs the channel ptr
+ params->channel_id = ChannelList.Add(pChannel);
+
+ if (params->channel_id == BAD_CHANNEL_ID)
+ {
+ hr = E_OUTOFMEMORY;
+ EXIT_BLOCK;
+ }
+
+
+ // do this after the above add connection because the
+ // TransferMarshalConnection may convert it to a
+ // weak count if this is the container connection.
+ pChannel->TransferMarshalConnection();
+
+ // now that the channel is in a consistent state, we can test it
+ pChannel->AssertValid(FALSE, TRUE);
+
+ // If we made it to here, we succeeded
+ hr = S_OK;
+
+ END_BLOCK;
+
+ if (pChannel != NULL)
+ {
+ pChannel->Release();
+ }
+
+ if (pRH != NULL)
+ {
+ pRH->Release();
+ }
+
+ if (pIM != NULL)
+ {
+ pIM->Release();
+ }
+
+ if (FAILED(hr))
+ {
+ params->channel_id = BAD_CHANNEL_ID;
+
+ if (fAddedConnection)
+ {
+ // Note: we don't say last release closes because this
+ // might be marshal table weak and we don't want to
+ // remove it just because of a transitory out of memory.
+ pStdId->ReleaseConnection(EXTCONN_STRONG | EXTCONN_CALLABLE, 0,
+ FALSE);
+ }
+ }
+
+ if (pStdId != NULL)
+ {
+ pStdId->Release();
+ }
+
+ CairoleDebugOut((DEB_MARSHAL,
+ "ICS_GetChannelId pSRV=%x pRH=%x pChannel=%x ChannelID=%x\n",
+ params->service, pRH, pChannel, params->channel_id));
+
+ Win4Assert( (hr == S_OK && params->channel_id != BAD_CHANNEL_ID) ||
+ (hr != S_OK && params->channel_id == BAD_CHANNEL_ID) );
+ return hr;
+}
+
+
+//+------------------------------------------------------------------------
+//
+// Function: SReleaseChannel::MakeAsyncCopy
+//
+// Synopsis: Does the copy operation for async release
+//
+// Arguments: [thread] -- NULL ; indicates that we are to allocate a new one
+//
+// History: 26-June-94 CraigWi Created
+// 12-July-94 CraigWi Made into method on SReleaseChannel
+//
+//-------------------------------------------------------------------------
+
+STHREADCALLINFO *SReleaseChannel::MakeAsyncCopy(STHREADCALLINFO *thread)
+{
+ Win4Assert(thread == NULL);
+
+ // allocate unconstructed packet
+ SReleaseChannel *prelchan = (SReleaseChannel *)PrivMemAlloc(sizeof(SReleaseChannel));
+
+ if (prelchan == NULL)
+ return NULL;
+
+ prelchan->SReleaseChannel::SReleaseChannel(init_vtable);
+
+ // call base class to initialize its part of the instance
+ if (STHREADCALLINFO::MakeAsyncCopy(prelchan) == NULL)
+ {
+ PrivMemFree(prelchan);
+ return NULL;
+ }
+
+ // NOTE: we transfer the responsiblity of releasing the channel
+ // to the copy and thus do not AddRef.
+
+ prelchan->count = count;
+ prelchan->async = async;
+ prelchan->channel_id = channel_id;
+
+ // NULL out this pointer so the destroy function can tell the difference
+ // between the client side (where cancel is called) and the server side
+ // (where async is called).
+ prelchan->service = NULL;
+
+ return prelchan;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ThreadReleaseChannel
+//
+// Synopsis: Decrements strong count. Called on the correct thread for
+// the server
+//
+// Arguments: params - remote handler to call and count
+//
+// Returns: S_OK, E_HANDLE
+//
+// History: 8 Nov 93 AlexMit Created
+//
+// Notes: This must run on the server thread because the RH release
+// may call release on the server object.
+//
+//--------------------------------------------------------------------------
+HRESULT ThreadReleaseChannel( STHREADCALLINFO *call )
+{
+ SReleaseChannel *params = (SReleaseChannel *) call;
+
+ // lookup, AddRef, and remove the channel from the channel list.
+ CRpcChannelBuffer *pChnl = ChannelList.Lookup(params->channel_id, TRUE, TRUE);
+
+ if (pChnl)
+ {
+#if DBG==1
+ pChnl->DebugCheckMarshalCnt( params->count );
+#endif
+ // do a disconnect here since there may be other uses of the
+ // channel pending. the channel has already been removed from the
+ // channel list
+ pChnl->DisconnectObject(0);
+
+ // This release of the channel will make it go away since it has already
+ // been removed from the channel list which released it.
+ pChnl->Release();
+ return S_OK;
+ }
+ else
+ {
+ CairoleDebugOut((DEB_MARSHAL, "ThreadReleaseChannel pChnl not found\n"));
+ return E_HANDLE;
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ThreadDoChannelOperation
+//
+// Synopsis: Does channel operation. Called on the correct thread for
+// the server.
+//
+// Arguments: params - object id to release
+//
+// Returns: S_OK, E_HANDLE
+//
+// History: 12 May 94 CraigWi Created
+//
+//--------------------------------------------------------------------------
+
+HRESULT ThreadDoChannelOperation( STHREADCALLINFO *call )
+{
+ SDoChannelOperation *params = (SDoChannelOperation *) call;
+ IRemoteHdlr *pRH;
+ BOOL bDoesSupport = FALSE;
+ HRESULT result = S_OK;
+
+
+ // find the channel and AddRef it
+ CRpcChannelBuffer *pChnl = ChannelList.Lookup(params->channel_id, FALSE, TRUE);
+
+ if (pChnl == NULL)
+ {
+ CairoleDebugOut((DEB_WARN, "ThreadDoChannelOp pChnl not found\n"));
+ return E_HANDLE;
+ }
+
+ if (pChnl->IsConnected() != S_OK)
+ {
+ pChnl->Release();
+ return CO_E_OBJNOTCONNECTED;
+ }
+
+#if DBG == 1
+// BUGBUG: To enable this debug check we would have to pass the parameters here.
+// if (params->chop & CHOPFLAG_CHECK_OID_ENDPOINT_APT)
+// pChnl->DebugCheckOIDEndPointApt(params->guid, params->pEndPoint, params->hapt);
+#endif
+
+ pRH = pChnl->GetRH();
+
+ switch (params->chop & CHOP_OPERATION)
+ {
+ case CHOP_TRANSFER_MARSHALCONNECTION:
+ // REF COUNTING
+ // This transfers responsibility for a single strong connection
+ // (that is added during marshaling) to the server channel.
+
+ // CODEWORK: when we precompute channel, this call would no longer be
+ // necessary since the marshal did the increment in the normal case
+ // and the table marshal doesn't change the count (either locally
+ // or remotely).
+
+ result = pChnl->TransferMarshalConnection();
+ break;
+
+ case CHOP_ADD_MARSHALCONNECTION:
+ // REF COUNTING
+ // marshaling on client; simulate what marshaling on server does
+ result = pRH->AddConnection(EXTCONN_STRONG | EXTCONN_CALLABLE, 0);
+ break;
+
+ case CHOP_REMOVE_MARSHALCONNECTION:
+ // REF COUNTING
+ // marshaling on client; undo above
+ // fLastReleaseClose == FALSE on purpose; ignore errors; see imchnl.cxx.
+ pRH->ReleaseConnection(EXTCONN_STRONG | EXTCONN_CALLABLE,0,FALSE);
+ break;
+
+ case CHOP_LOCK_CONNECTION:
+ pChnl->LockConnection();
+ break;
+
+ case CHOP_UNLOCK_CONNECTION:
+ pChnl->UnlockConnection(params->chop&CHOPFLAG_LASTUNLOCKCLOSES);
+ break;
+
+ case CHOP_DOESSUPPORTIID:
+ bDoesSupport = pRH->DoesSupportIID(params->guid);
+
+ if (!bDoesSupport)
+ result = E_NOINTERFACE;
+ // else S_OK set above
+ break;
+
+ default:
+ Win4Assert(!"Bad chop in DoChannelOperation");
+ result = E_UNEXPECTED;
+ break;
+ }
+
+ // this balances the lookup done above
+ pChnl->Release();
+ return result;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ICS_GetContextHdl
+//
+// Synopsis: server side of RPC GetObjectHdl function. generates
+// a context handle for the object.
+//
+// Arguments: [hRpcBind] - Rpc bind handle
+// [ChannelID] - channel (and hence object) identifier
+// [dwflags] - marshal flags
+// [ppObjCtx] - object context handle to return
+//
+// Returns: S_OK, E_HANDLE
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------------
+
+extern "C" HRESULT ICS_GetContextHdl(
+ handle_t hRpcBind, // rpc handle call was made on
+ SEndPoint *caller_bindings,// string bindings of caller
+ PPOBJCTX ppObjCtx, // returned ctx hdl
+ error_status_t *perrstat) // RPC error status
+{
+ // Make sure this does not get inadvertently set by us
+ *perrstat = 0;
+ HRESULT hr;
+
+ CairoleDebugOut((DEB_ENDPNT, "ICS_GetContextHdl SEp:%p\n", caller_bindings));
+
+ // Find or create a service object.
+ CRpcService *pService = FindSRVFromEP(caller_bindings, TRUE);
+ CairoleDebugOut((DEB_ENDPNT, "ICS_GetContextHdl RpcService:%p\n", pService));
+
+ if (pService)
+ {
+ // here we give the AddRef on the service object away with the context
+ // handle; the only way this is released is via the rundown.
+
+ *ppObjCtx = pService;
+ hr = S_OK;
+ }
+ else
+ {
+ *ppObjCtx = NULL;
+ hr = E_OUTOFMEMORY;
+ }
+
+ CairoleDebugOut((DEB_MARSHAL, "ICS_GetContextHdl pSRV:%x hr:%x\n", pService, hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ICS_ReleaseContextHdl
+//
+// Synopsis: Releases a context handle.
+//
+// Arguments: [ppObjCtx] - object context handle to return
+//
+// Returns: S_OK
+//
+// History: 2 Aug 94 AlexMit Created
+//
+//--------------------------------------------------------------------------
+
+extern "C" HRESULT ICS_ReleaseContextHdl(
+ PPOBJCTX ppObjCtx, // released ctx hdl
+ error_status_t *perrstat) // RPC error status
+{
+ // Make sure this does not get inadvertently set by us
+ *perrstat = 0;
+ *ppObjCtx = NULL;
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ICS_GetChannelId
+//
+// Synopsis: server side of RPC GetChannelId function. Creates
+// channel and returns channel id.
+//
+// Arguments: see comments below
+//
+// Returns: S_OK, E_HANDLE
+//
+// History: 27 Nov 93 AlexMit Created
+//
+//--------------------------------------------------------------------------
+
+extern "C" HRESULT ICS_GetChannelId(
+ PPOBJCTX ppObjCtx, // context handle
+ SEndPoint *caller_bindings, // string bindings of caller
+ OID ObjectId, // object id
+ DWORD dwFlags, // marshal flags
+ HAPT server_apt, // server apartment
+ GUID logical_thread, // logical thread of caller
+ DWORD dwClientTID, // callers thread id
+ DWORD *dwChannelId, // channel id
+ error_status_t *prpcstat) // RPC error status
+{
+ // Make sure this does not get inadvertently set by us
+ *prpcstat = 0;
+ *dwChannelId = BAD_CHANNEL_ID;
+
+ // Make sure this service object exists. Leave it on the list if found.
+ CRpcService *pSrv = FindSRVFromContext(*ppObjCtx, FALSE);
+
+ // If the service object doesn't exists, create it.
+ if (pSrv == NULL)
+ {
+ CairoleDebugOut((DEB_CHANNEL,
+ "ICS_GetChannelId Service Object not found *ppObjCtx=%x\n",
+ *ppObjCtx));
+ pSrv = FindSRVFromEP(caller_bindings, TRUE);
+ *ppObjCtx = pSrv;
+
+ // Add a reference count for the pointer held by the context handle.
+ if (pSrv != NULL)
+ pSrv->AddRef();
+ }
+
+ if (pSrv)
+ {
+ SGetChannelId params(
+ ThreadGetChannelId,
+ CALLCAT_INTERNALINPUTSYNC,
+ logical_thread);
+
+ // Get to the server thread to make this call.
+ params.service = pSrv; // transfer addref; release in dtor
+ params.object_id = ObjectId;
+ params.flags = dwFlags;
+ params.dwClientTID = dwClientTID;
+ params.channel_id = BAD_CHANNEL_ID;
+ HRESULT result = CChannelControl::GetToCOMThread(server_apt, &params);
+
+ // fill in the return parameters
+ *dwChannelId = params.channel_id;
+
+ Win4Assert( (result == S_OK && *dwChannelId != BAD_CHANNEL_ID) ||
+ (result != S_OK && *dwChannelId == BAD_CHANNEL_ID) );
+ return result;
+ }
+ else
+ {
+ return E_OUTOFMEMORY;
+ }
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ICS_ReleaseChannel
+//
+// Synopsis: server side of RPC ReleaseChannelHdl function. releases the
+// object and frees the context handle for the interface.
+//
+// Arguments: [hRpcBind] - rpc handle call was made on
+// [ChannelID] - channel to do the release on
+// [ulMarshalCnt] - count of references to Release
+// [logical_thread] - logical thread id
+//
+// Returns: S_OK, E_HANDLE
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------------
+
+extern "C" HRESULT ICS_ReleaseChannel(
+ handle_t hRpcBind, // rpc handle call was made on
+ DWORD ChannelID, // id for channel to release
+ ULONG ulMarshalCnt, // count to release
+ BOOL fAsync, // TRUE -> async (returns immediately)
+ GUID logical_thread, // logical thread id of caller
+ error_status_t *perrstat) // RPC error status
+{
+ CairoleDebugOut((DEB_CHANNEL, "ICS_ReleaseChannel for ChannelID=%x\n", ChannelID));
+
+ HRESULT hr = E_HANDLE;
+
+ // Make sure this does not get inadvertently set by us
+ *perrstat = 0;
+
+ // look for the channel id in the channel list, and return the
+ // channel controller AddRef'd. if not there, return an error.
+
+ CChannelControl *pChanCtrl = ChannelList.LookupControl(ChannelID);
+
+ if (pChanCtrl)
+ {
+ CairoleDebugOut((DEB_MARSHAL | DEB_CHANNEL,
+ "ICS_ReleaseChannel ChannelID=%x\n", ChannelID ));
+
+
+ SReleaseChannel params(
+ ThreadReleaseChannel,
+ fAsync ? CALLCAT_ASYNC : CALLCAT_INTERNALSYNC,
+ logical_thread);
+
+ params.channel_id = ChannelID;
+ params.count = ulMarshalCnt;
+ params.service = NULL;
+
+ hr = pChanCtrl->GetToCOMThread( &params );
+ pChanCtrl->Release();
+ }
+#if DBG==1
+ else
+ {
+ CairoleDebugOut((DEB_WARN,
+ "ICS_ReleaseChannel ChanCtrl not found for ChannelID=%x\n", ChannelID));
+ }
+#endif
+
+ CairoleDebugOut((DEB_CHANNEL,
+ "ICS_ReleaseChannel ChanCtrl for ChannelID=%x done \n", ChannelID));
+ return hr;
+}
+
+#ifdef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Method: ICS_AsyncReleaseChannel
+//
+// Synopsis: Used for wmsg protocolls where the call is made async
+// by the protocoll itself.
+//
+// Arguments: [hRpcBind] --
+// [ChannelID] --
+// [ulMarshalCnt] --
+// [fAsync] --
+// [immediately] --
+// [logical_thread] --
+//
+// Returns: void
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+extern "C" void ICS_AsyncReleaseChannel(
+ handle_t hRpcBind, // rpc handle call was made on
+ DWORD ChannelID, // id for channel to release
+ ULONG ulMarshalCnt, // count to release
+ BOOL fAsync, // TRUE -> async (returns immediately)
+ GUID logical_thread) // logical thread id of caller
+{
+ CairoleDebugOut((DEB_CHANNEL, "ICS_AsyncReleaseChannel for ChannelID=%x\n", ChannelID));
+ error_status_t errstat; // RPC error status
+
+ ICS_ReleaseChannel(
+ hRpcBind,
+ ChannelID,
+ ulMarshalCnt,
+ fAsync,
+ logical_thread,
+ &errstat);
+
+ CairoleDebugOut((DEB_CHANNEL,
+ "ICS_AsyncReleaseChannel ChanCtrl for ChannelID=%x done \n", ChannelID));
+}
+#endif // _CHICAGO_
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ICS_SyncChannelOp
+//
+// Synopsis: server side of RPC DoChannelOperation function.
+// Increments marshal count for channel
+//
+// Arguments: [hRpcBind] - rpc handle call was made on
+// [ChannelID] - channel to do the release on
+//
+// Returns: S_OK, E_HANDLE
+//
+// History: 27-Nov-92 AlexMit Created
+//
+//--------------------------------------------------------------------------
+
+extern "C" HRESULT ICS_SyncChannelOp(
+ handle_t hRpcBind, // rpc handle call was made on
+ DWORD ChannelID, // id for channel to release
+ GUID logical_thread, // logical thread id of caller
+ DWORD chop, // CHOP_* : what to do
+ HAPT hapt, // server apartment to chk
+ const IID *pguid, // for CHOP_DOESSUPPORTIID
+ error_status_t *perrstat) // RPC error status
+{
+ // Make sure this does not get inadvertently set by us
+ *perrstat = 0;
+
+ // look for the channel id in the channel list and get the controller.
+ // if not there, return an error.
+
+ CChannelControl *pChanCtrl = ChannelList.LookupControl(ChannelID);
+
+ if (pChanCtrl)
+ {
+ CairoleDebugOut((DEB_MARSHAL,
+ "ICS_DoChannelOperation ChannelID=%x\n", ChannelID ));
+
+ CALLCATEGORY callcat = CALLCAT_SYNCHRONOUS;
+
+ SDoChannelOperation params(
+ ThreadDoChannelOperation,
+ callcat,
+ logical_thread);
+
+ params.chop = chop;
+ params.guid = *pguid;
+ params.service = NULL;
+ params.channel_id = ChannelID;
+
+ HRESULT hr = pChanCtrl->GetToCOMThread( &params );
+ pChanCtrl->Release();
+
+ // The channel was released in ThreadDoChannelOperation since the
+ // connection could have rundown during this call causing the
+ // channel to go away.
+
+ return hr;
+ }
+ else
+ {
+ CairoleDebugOut((DEB_WARN,
+ "ICS_DoChannelOperation Channel not found ChannelID=%x\n",
+ ChannelID));
+ return E_HANDLE;
+ }
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ICS_InputSyncChannelOp
+//
+// Synopsis: server side of RPC DoChannelOperation function.
+// Increments marshal count for channel
+//
+// Arguments: [hRpcBind] - rpc handle call was made on
+// [ChannelID] - channel to do the release on
+//
+// Returns: S_OK, E_HANDLE
+//
+// History: 27-Nov-92 AlexMit Created
+//
+//--------------------------------------------------------------------------
+
+extern "C" HRESULT ICS_InputSyncChannelOp(
+ handle_t hRpcBind, // rpc handle call was made on
+ DWORD ChannelID, // id for channel to release
+ GUID logical_thread, // logical thread id of caller
+ DWORD chop, // CHOP_* : what to do
+ HAPT hapt, // server apartment to chk
+ const IID *pguid, // for CHOP_DOESSUPPORTIID
+ error_status_t *perrstat) // RPC error status
+{
+ // Make sure this does not get inadvertently set by us
+ *perrstat = 0;
+
+ // look for the channel id in the channel list and get the controller.
+ // if not there, return an error.
+
+ CChannelControl *pChanCtrl = ChannelList.LookupControl(ChannelID);
+
+ if (pChanCtrl)
+ {
+ CairoleDebugOut((DEB_MARSHAL,
+ "ICS_DoChannelOperation ChannelID=%x\n", ChannelID ));
+
+ // We force the call type to input sync because we may be unmarshaling
+ // an interface on behalf of an input sync call and we will deadlock
+ // if we post a message. This is done for transfer, add and remove
+ // marshal connection.
+ CALLCATEGORY callcat = CALLCAT_INTERNALINPUTSYNC;
+
+ SDoChannelOperation params(
+ ThreadDoChannelOperation,
+ callcat,
+ logical_thread);
+
+ params.chop = chop;
+ params.guid = *pguid;
+ params.service = NULL;
+ params.channel_id = ChannelID;
+
+ HRESULT hr = pChanCtrl->GetToCOMThread( &params );
+ pChanCtrl->Release();
+
+ // The channel was released in ThreadDoChannelOperation since the
+ // connection could have rundown during this call causing the
+ // channel to go away.
+
+ return hr;
+ }
+ else
+ {
+ CairoleDebugOut((DEB_WARN,
+ "ICS_DoChannelOperation Channel not found ChannelID=%x\n",
+ ChannelID));
+ return E_HANDLE;
+ }
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ICS_RegisterProtseq
+//
+// Synopsis: server side of RPC RegisterProtseq function. ensures
+// that the protseq is registered and returns a new SEndPoint
+//
+// Arguments: [hRpcBind] - rpc handle call was made on
+// [pwszProtseq] - protseq to register
+// [ppSEp] - returned array of string bindings
+//
+// Returns: S_OK,
+//
+// History: 23-Nov-92 Rickhi Created
+//
+//--------------------------------------------------------------------------
+
+extern "C" HRESULT ICS_RegisterProtseq(
+ handle_t hRpcBind, // rpc handle call was made on
+ WCHAR *pwszProtseq, // protseq to register
+ SEndPoint **ppSEp, // endpoint structure to return
+ error_status_t *perrstat) // RPC error status
+{
+ HRESULT sc;
+
+ // Make sure this does not get inadvertently set by us
+ *perrstat = 0;
+
+#ifndef _CHICAGO_
+ sc = LocalService()->RegisterProtseq(pwszProtseq);
+
+ *ppSEp = LocalService()->CopySEp();
+#else
+ sc = E_FAIL;
+#endif
+
+ CairoleDebugOut((DEB_MARSHAL, "ICS_RegisterProtseq %ws\n", pwszProtseq));
+
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: POBJCTX_rundown
+//
+// Synopsis: The routine to rundown and destroy state associated with a
+// context that dies. Called by RPC runtime when a session
+// closes, etc.
+//
+// Arguments: [phObj] - context handle (pointer to service object)
+//
+// History: 14-Apr-93 Rickhi Created.
+//
+// Notes: A connection has been lost. We've got outstanding state,
+// pService, that we need to clean up. The cleanup consists
+// of finding all channels using the service object and telling
+// them that their connection is gone.
+//
+//--------------------------------------------------------------------------
+
+extern "C" void POBJCTX_rundown(POBJCTX phObj)
+{
+ CairoleDebugOut((DEB_MARSHAL, "POBJCTX_rundown called with: %p on thread %x\n",
+ phObj, GetCurrentThreadId()));
+
+ CRpcService *pService = NULL;
+
+ if (phObj != 0)
+ {
+ // Make sure we know about the context pointer. If we find it,
+ // Remove the service object from the list so that there are
+ // no races between Rundown and CoUninitialize.
+
+ pService = FindSRVFromContext(phObj, TRUE);
+
+ if (pService)
+ {
+ // disconnect channels using this object. Do not hold any
+ // locks across this call, since it might switch threads.
+ pService->Disconnect();
+
+ // here we Release one AddRef since this rundown call
+ // indicates that the context handle is now destroyed.
+ pService->Release();
+
+ // here we Release the AddRef done by FindSRVFromContext above.
+ pService->Release();
+ }
+ }
+}
diff --git a/private/ole32/com/remote/sichnl.hxx b/private/ole32/com/remote/sichnl.hxx
new file mode 100644
index 000000000..efbf5b48c
--- /dev/null
+++ b/private/ole32/com/remote/sichnl.hxx
@@ -0,0 +1,111 @@
+//+-------------------------------------------------------------------
+//
+// File: sichnl.hxx
+//
+// Contents: IChannelService data structures
+//
+// Functions:
+//
+// History: 14 April 1994 AlexMit Created
+//
+// Notes: This file contains data structures used when thread
+// switching for the IChannelService interface.
+//
+//--------------------------------------------------------------------
+
+#ifndef __SICHNL__
+#define __SICHNL__
+
+#include <olerem.h>
+#include <channelb.hxx>
+
+struct SGetContextHdl : STHREADCALLINFO
+{
+ SGetContextHdl (TRANSMIT_FN fn,CALLCATEGORY callcat,DWORD tid=0)
+ : STHREADCALLINFO(fn, callcat, tid) { }
+ SGetContextHdl (DISPATCH_FN fn,CALLCATEGORY callcat,REFLID lid)
+ : STHREADCALLINFO(fn, callcat, lid) { }
+ virtual ~SGetContextHdl();
+
+ CRpcService *service;
+
+ // Client side only.
+ SEndPoint *psepClient;
+};
+
+struct SGetChannelId : STHREADCALLINFO
+{
+ SGetChannelId (TRANSMIT_FN fn,CALLCATEGORY callcat,DWORD tid=0)
+ : STHREADCALLINFO(fn, callcat, tid) { psepClient = NULL; }
+ SGetChannelId (DISPATCH_FN fn,CALLCATEGORY callcat,REFLID lid)
+ : STHREADCALLINFO(fn, callcat, lid) { psepClient = NULL; }
+ virtual ~SGetChannelId();
+#if DBG == 1
+ virtual STHREADCALLINFO *MakeAsyncCopy(STHREADCALLINFO *)
+ { Win4Assert(!"GetChannelId cannot be async"); return NULL; }
+#endif
+
+ CRpcService *service;
+ OID object_id;
+ DWORD flags;
+ DWORD channel_id;
+ DWORD dwClientTID;
+
+ // Client side only.
+ HAPT server;
+ SEndPoint *psepClient;
+};
+
+struct SReleaseChannel : STHREADCALLINFO
+{
+ SReleaseChannel (TRANSMIT_FN fn,CALLCATEGORY callcat,DWORD tid=0)
+ : STHREADCALLINFO(fn, callcat, tid) { }
+ SReleaseChannel (DISPATCH_FN fn,CALLCATEGORY callcat,REFLID lid)
+ : STHREADCALLINFO(fn, callcat, lid) { }
+ virtual ~SReleaseChannel ();
+ virtual STHREADCALLINFO *MakeAsyncCopy(STHREADCALLINFO *);
+
+ ULONG count;
+ BOOL async;
+ DWORD channel_id;
+
+ // Client side only
+ CRpcService *service; // (NULL on server side)
+
+protected:
+ // this ctor is used in conjunction with MakeAsyncCopy and sets up the vtable
+ // pointer; MakeAsyncCopy actually initializes the instance. A normal copy
+ // constructor isn't used because they aren't virtual.
+ SReleaseChannel(INIT_VTABLE i) : STHREADCALLINFO(i) { }
+};
+
+
+struct SDoChannelOperation : STHREADCALLINFO
+{
+ SDoChannelOperation(TRANSMIT_FN fn,CALLCATEGORY callcat,DWORD tid=0)
+ : STHREADCALLINFO(fn, callcat, tid) { }
+ SDoChannelOperation(DISPATCH_FN fn,CALLCATEGORY callcat,REFLID lid)
+ : STHREADCALLINFO(fn, callcat, lid) { }
+ virtual ~SDoChannelOperation();
+#if DBG == 1
+ virtual STHREADCALLINFO *MakeAsyncCopy(STHREADCALLINFO *)
+ { Win4Assert(!"GetChannelId cannot be async"); return NULL; }
+#endif
+
+ DWORD chop;
+ GUID guid;
+ DWORD channel_id;
+
+ // Client side only
+ CRpcService *service; // (NULL on server side)
+ HAPT hapt;
+};
+
+
+// Prototypes.
+HRESULT ThreadGetChannelId ( STHREADCALLINFO *call );
+HRESULT ThreadReleaseChannel ( STHREADCALLINFO *call );
+HRESULT ThreadDoChannelOperation( STHREADCALLINFO *call );
+
+#endif // __SICHNL__
+
diff --git a/private/ole32/com/remote/stdid.cxx b/private/ole32/com/remote/stdid.cxx
new file mode 100644
index 000000000..dc9b18f56
--- /dev/null
+++ b/private/ole32/com/remote/stdid.cxx
@@ -0,0 +1,2288 @@
+//+-------------------------------------------------------------------
+//
+// File: stdid.cxx
+//
+// Contents: identity object and creation function
+// identity unmarshaler (only one instance) and access function
+//
+// History: 1-Dec-93 CraigWi Created
+//
+//--------------------------------------------------------------------
+
+#include <ole2int.h>
+
+#include "..\objact\objact.hxx" // used in IProxyManager::CreateServer
+
+// temporary until the RH interface is abstracted; once that is done,
+// the creation routine will be in olerem.h
+#include <remhdlr.hxx>
+#include <idtable.hxx>
+
+// CODEWORK: FAILED .vs. != NOERROR tests
+
+INTERNAL ReadIdentityHeader(IStream *pStm, SIdentityDataHdr *pidh,
+ CLSID *pclsidHandler, BOOL fTransparent);
+
+INTERNAL ScmCreateObjectInstance(
+ REFCLSID rclsid,
+ DWORD dwContext,
+ void * pv,
+ InterfaceData **ppIFD);
+
+//+----------------------------------------------------------------
+//
+// Class: CStdIdentity (stdid)
+//
+// Purpose: To be the representative of the identity of the object
+// and to coordinate marshaling
+//
+// Interface: IStdIdentity, IMarshal
+//
+// History: 11-Dec-93 CraigWi Created.
+// 21-Apr-94 CraigWi Stubmgr addref's object; move strong cnt
+// 10-May-94 CraigWi IEC called for strong connections
+// 17-May-94 CraigWi Container weak connections
+// 31-May-94 CraigWi Tell object of weak pointers
+//
+// Details:
+//
+// on server side, two main cases:
+// 1. id object aggregated to server object; server must ensure that
+// two threads don't try to create different notions of identity;
+// follow on marshal can be std or not; app can add data or not.
+// a. no data at all (rare)
+// CreateStdIdentity(pUnkOuter, pUnkOuter, NULL, iid, ppv);
+//
+// b. std marshaling; no app data
+// CreateStdIdentity(pUnkOuter, pUnkOuter,PSTDMARSHAL,iid,ppv);
+//
+// c. app marshaling data in addition to std marshaling data;
+// app calls GetStdRemMarshaler() during marshaling.
+// CreateStdIdentity(pUnkOuter, pUnkOuter, pMarshal, iid, ppv);
+//
+// d. app marshaling data instead of std marshaling data.
+// CreateStdIdentity(pUnkOuter, pUnkOuter, pMarshal, iid, ppv);
+//
+// 2. id object stand alone; two threads can simultaneously create
+// this identity and the first one wins;
+// follow on marshal is *only* std marshaling.
+// CreateStdIdentity(NULL, pUnkControl, PSTDMARSHAL, iid, ppv);
+//
+// on client side, we have matching cases:
+// 1a. id object and app object; no app data and no std marshaling
+// CreateIdentityHandler(<any>, NULL, iid, ppv);
+//
+// 1b. id object combined with remoting object; no app marshaling,
+// allthough app may intercept IMarshal methods to know when
+// unmarshal happens; most common case
+// CreateIdentityHandler(<any>, PSTDMARSHAL, iid, ppv);
+// pCFStdMarshal->CI(<any>, iid, ppv);
+//
+// 1c. id object combined with remoting object; app adds data;
+// app calls GetStdRemMarshaler() during marshaling.
+// CreateIdentityHandler(<any>, pMarshal, iid, ppv);
+//
+// 1d. id object aggregated in with app object; no std remoting
+// CreateIdentityHandler(<any>, pMarshal, iid, ppv);
+//
+// 2. same as 1b.
+//
+// In all cases where the id object is aggregated, client and server, the
+// external IMarshal implementation must respond with the identity clsid
+// and the identity data must be first. The simplest way to do that is
+// to expose the IMarshal of the identity object.
+//
+// the remote handler piece (separate from the identity object) is created
+// under the following external conditions:
+// server side (value of pMarshal parameter):
+// NULL: never
+// PSTDMARSHAL: on first marshal (table or normal);
+// later this will be changed to occur only on the
+// first normal marshal (table marshaling would be completely
+// handled by the identity object).
+// pMarshal: when GetStdRemMarshaler() is called.
+//
+// client side:
+// NULL: never
+// PSTDMARSHAL: on first unmarshal (internally translated into
+// GetStdRemMarshaler() call).
+// pMarshal: when GetStdRemMarshaler() is called.
+//
+// (internally, the remote handler piece is always and only created within
+// GetRH(). The remote handler piece, once created, it not released
+// until the identity object is released. Thus pointers to it
+// are stable as long as the identity object is stable.)
+//
+// the identity is determined:
+// server side: on creation of the identity object
+// client side: on first unmarshal
+//
+// the clsid on the server side is (for the value of pMarshal):
+// NULL: CLSID_NULL
+// PSTDMARSHAL: IStdMarshalInfo::GetClassForHandler
+// if not supported or returns NULL, CLSID_StdMarshal;
+// this determination is made once at startup.
+// pMarshal: pMarshal->GetUnmarshalClass; this determination is made
+// each time the unmarshal clsid is needed.
+//
+// the clsid on the client side is determined by:
+// NULL: CLSID_NULL
+// PSTDMARSHAL: first unmarshal
+// pMarshal: pMarshal->GetUnmarshalClass.
+//
+// NOTE: IStdMarshalInfo is not as useful as it was once thought to be. The
+// problem is that handlers don't support this interface and it doesn't seem
+// worth it to extend that mechanism to get per-destctx clsids. Part of the
+// problem is that the documentation tells people to check the pvDestCtx
+// which prevents us from using our normal dest context anyway. Thus, the
+// rule is: if you want the handler clsid to different depending on context,
+// you must support custom marshaling and then if you want std identity ,
+// you must aggregate the std identity object; if further you want std
+// remoting, you must delegate to IStdIdentity::GetStdRemMarshal().
+//
+// relationship to identity table:
+// Creation function adds to table; pointer in table is not addref'd
+// Each use of the identity (lock external, marshaling, etc.) addrefs
+// Last release removes from table
+//
+// the IProxyManager interface is supported by the identity object because
+// the RH code was too difficult to change to support this directly. In
+// particular, this would have meant sometimes aggregating the RH to the
+// identity object (client side) and sometimes not (server side).
+//
+// REF COUNTING
+//
+// The identity of an object is held alive by calling AddConnection on the
+// the identity object or the RH. In turn, this call AddRef's the identity
+// object. Each AddConnection is balanced by a ReleaseConnection (which
+// Releases the identity object). The medium level events that increment
+// the connection count are:
+// CoMarshalInterface
+// CoLockObjectExternal(..., TRUE, ...);
+// rpc connect for table case
+//
+// The events which decrement the connection count are:
+// CoReleaseMarshalData MSHLFLAGS_TABLE* (including in the normal case)
+// CoLockObjectExternal(..., FALSE, ...);
+// rpc disconnect all cases (including rpc rundown)
+//
+// The identity object contains the count of strong connections. This number is
+// only incremented with AddConnection and decremented with ReleaseConnection.
+// On the server side, the strong count starts out at zero and when it reaches
+// zero, we disconnect (with certain restrictions). On the client side, the
+// strong count starts out at 1 to represent the fact that the client connection
+// is initially a strong one. The client strong connection count is buffered
+// and the server channel associated with that client is only notified when the
+// count was zero or becomes zero. Normally, the only way for the client count
+// to change is IRunnableObject::LockRunning and
+// IRunnableObject::SetContainedObject. We currently don't expose IStdIdentity
+// and don't implement IExternalConnetion in the handler.
+//
+// If the server object supports IWeakRef, the identity object
+// communicates to the object the number of pointers that are held it. As
+// of this writing, there are two and only two (IUnknown *, IWR *).
+//
+// CoDisconnectObject forces the termination of all connections, weak or strong
+// and releases all pointers on the object held by the remoting system. This
+// call can be made while executing a method on the object since the object is
+// temporarily held alive during the call by the dispatch code.
+//
+// CODEWORK: if we decide to expose the identity object, we will have to
+// chose the way(s) in which it can be created. Two ways come to mind:
+// CoCreateStdIdentity(...) and CoCreateIdentityHandler;
+// CoCreateInstance(CLSID_StdMarshal, ...) must map to CoCreateIdentityHandler
+// for compatibility with 16bit OLE2. CoGetStandardMarshal() is equalivalent
+// to CoCreateStdIdentity w/o aggregation.
+//--------------------------------------------------------------------
+
+
+#define DECLARE_INTERNAL_UNK() \
+ class CInternalUnk : public IUnknown \
+ { \
+ public: \
+ /* *** IUnknown methods *** */ \
+ STDMETHOD(QueryInterface)(REFIID riid, VOID **ppvObj); \
+ STDMETHOD_(ULONG,AddRef)(void) ; \
+ STDMETHOD_(ULONG,Release)(void); \
+ }; \
+ friend CInternalUnk; \
+ CInternalUnk m_InternalUnk;
+
+
+typedef enum tagSTDID_FLAGS
+{
+ STDID_SERVER = 0, // on server side
+ STDID_CLIENT = 1, // on client side (non-local in RH terms)
+ STDID_STDMARSHAL = 2, // was created with PSTDMARSHAL
+ STDID_HASEC = 4, // server supports IEC for connections
+#if DBG == 1
+ STDID_INDESTRUCTOR = 256, // dtor entered; assert on AddRef and others
+#endif
+} STDID_FLAGS;
+
+
+class CStdIdentity : public IStdIdentity, public IMarshal, public IProxyManager
+{
+public:
+ friend INTERNAL CreateStdIdentity(IUnknown *pUnkOuter,
+ IUnknown *pUnkControl, IMarshal *pMarshal,
+ REFIID riid, void **ppv);
+
+ friend INTERNAL CreateIdentityHandler(IUnknown *pUnkOuter,
+ IMarshal *pMarshal, REFIID riid, void **ppv);
+
+ // IUnknown
+ STDMETHOD(QueryInterface) (REFIID riid, LPVOID *ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ // IStdIdentity
+ STDMETHOD_(void, GetObjectID)(OID *pOid);
+ STDMETHOD_(IUnknown *, GetServer)(BOOL fAddRef);
+ STDMETHOD_(void, RevokeObjectID)(void);
+ STDMETHOD_(IMarshal *, GetStdRemMarshal)(void);
+ STDMETHOD(AddConnection)(DWORD extconn, DWORD reserved);
+ STDMETHOD(ReleaseConnection)(DWORD extconn, DWORD reserved, BOOL fLastReleaseCloses);
+ STDMETHOD_(ULONG,ReleaseKeepAlive)(IUnknown *pUnkToRelease, DWORD reserved);
+
+ // IMarshal
+ STDMETHOD(GetUnmarshalClass)(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax)(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(LPSTREAM pStm, REFIID riid,
+ LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(LPSTREAM pStm, REFIID riid,
+ VOID **ppv);
+ STDMETHOD(ReleaseMarshalData)(LPSTREAM pStm);
+ STDMETHOD(DisconnectObject)(DWORD dwReserved);
+
+ // IProxyManager (only if client side)
+ STDMETHOD(CreateServer)(REFCLSID rclsid, DWORD clsctx, void *pv);
+ STDMETHOD_(BOOL, IsConnected)(void);
+ STDMETHOD(LockConnection)(BOOL fLock, BOOL fLastUnlockReleases);
+ STDMETHOD_(void, Disconnect)();
+
+ STDMETHOD(CreateServerWithHandler)(REFCLSID rclsid, DWORD clsctx, void *pv,
+ REFCLSID rclsidHandler, IID iidSrv, void **ppv,
+ IID iidClnt, void *pClientSiteInterface);
+
+implementations:
+ CStdIdentity(DWORD flags, IUnknown *pUnkOuter,
+ IUnknown *pUnkControl, REFOID oid, REFCLSID clsid,
+ IMarshal *pMarshal, IUnknown **ppUnkInternal);
+ ~CStdIdentity();
+
+ // internal unknown
+ DECLARE_INTERNAL_UNK()
+
+ // CODEWORK: DECLARE_DEBUG()
+
+#if DBG == 1
+ void AssertValid();
+#else
+ void AssertValid() { }
+#endif
+
+ // private to ::CreateServer
+ INTERNAL_(BOOL) MiIsForClsid(InterfaceData *pIFD,
+ REFCLSID clsidGiven, DWORD *pcbSkipToIdenHdr);
+
+shared_state:
+ // if appropriate, it is noted below if the state of a member variable
+ // is correllated to whether this identity (client or server) is
+ // connected or not.
+
+ DWORD m_refs; // number of pointer refs
+ IUnknown *m_pUnkOuter; // controlling unknown; set once.
+
+ CMutexSem m_mxsRelease; // controls shutdown order (::Release only)
+
+ DWORD m_flags; // see STDID_* values above; set once.
+
+ OID m_oid; // the identity
+ CLSID m_clsidHandler; // the clsid of the handler; see flags
+ // these values are NULL when disconnected
+ // and non-NULL if connected.
+
+ IUnknown *m_pUnkControl; // the controlling unk of the object;
+ // this member has three possible values:
+ // pUnkOuter - client side; not addref'd
+ // pUnkControl - server side (which may
+ // be pUnkOuter if aggregated); addref'd
+ // NULL - server side, disconnected
+
+ void *m_pWRorECServer; // server side only; set if the server
+ // supports IWR or IEC.
+
+ DWORD m_cStrongCnt; // number of strong connections; when
+ // this count goes to zero, we release
+ // our refs to the object; see ReleaseConnection
+
+ DWORD m_cPendingStrongRelease;// makes CoDisconnect during last strong
+ // release work
+
+ INTERNAL_(IMarshal *) GetMarshalNext();
+ IMarshal *m_pMarshalNext; // the way in which the object is marshalled;
+ // three cases: NULL, PSTDMARSHAL, pMarshal; see above;
+ // NEVER AddRef'd. NULL and PSTDMARSHAL are cases are replaced
+ // by a real pMarshal the first time used.
+ // NOTE: same value if connected or disconnected.
+
+ INTERNAL_(IRemoteHdlr *) GetRH(void);
+ IRemoteHdlr *m_pRH; // the RH for this identity; has ref count
+ // although it has our m_pUnkOuter, it is not aggregated to us.
+ // NOTE: value not dependent upon whether connected or disconnected.
+
+ // CODEWORK: this will change when we move to a separate strong counting
+ // object; see below.
+
+ BOOL IsClient() { return m_flags & STDID_CLIENT; }
+ BOOL StdMarshalNext() { return m_flags & STDID_STDMARSHAL; }
+#if DBG == 1
+ void SetNowInDestructor() { m_flags |= STDID_INDESTRUCTOR; }
+ BOOL IsInDestructor() { return m_flags & STDID_INDESTRUCTOR; }
+#else
+ void SetNowInDestructor() { }
+#endif
+ // returns IExternalConnection* ptr (not addref'd);
+ BOOL HasEC() { return m_flags & STDID_HASEC; }
+ IExternalConnection *GetEC()
+ { Assert(HasEC());
+ return (IExternalConnection *)m_pWRorECServer;
+ }
+};
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::CStdIdentity, private
+//
+// Synopsis: The part of the identity object creation which cannot fail.
+//
+// Arguments: for all but the last param, see CreateStdIdentity and
+// CreateIdentityHandler.
+// [ppUnkInternal] --
+// when aggregated, this the internal unknown;
+// when not aggregated, this is the controlling unknown
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+CStdIdentity::CStdIdentity(DWORD flags, IUnknown *pUnkOuter,
+ IUnknown *pUnkControl, REFOID oid, REFCLSID clsid,
+ IMarshal *pMarshal, IUnknown **ppUnkInternal)
+{
+ m_refs = 1;
+ m_pUnkOuter = pUnkOuter ? pUnkOuter : &m_InternalUnk;
+ m_flags = flags;
+ if (pMarshal == PSTDMARSHAL)
+ m_flags |= STDID_STDMARSHAL;
+
+ m_oid = oid; // NULL on client side
+ Assert(!!IsClient() == (IsEqualGUID(oid, OID_NULL)));
+
+ m_clsidHandler = clsid; // NULL on client side
+ Assert(!!IsClient() == (IsEqualGUID(clsid, CLSID_NULL)));
+
+ m_pUnkControl = pUnkControl;// NULL -> use pUnkOuter
+ Assert(!!IsClient() == (m_pUnkControl == NULL));
+ if (m_pUnkControl == NULL)
+ m_pUnkControl = m_pUnkOuter;
+
+ m_cPendingStrongRelease = 0;
+
+ if (IsClient())
+ {
+ m_cStrongCnt = 1; // see comments above
+ m_pWRorECServer = NULL;
+ Assert((m_flags & (STDID_HASEC)) == 0);
+ }
+ else
+ {
+ m_cStrongCnt = 0; // see comments above
+ m_pUnkControl->AddRef();
+ m_pWRorECServer = NULL; // set below if IWR or IEC
+
+ // find out of server supports IWeakRef (we prefer it over IEC)
+ HRESULT hresult;
+ // find out if server supports IExternalConnection;
+ // Initialize to 1 to better detect improperly written servers.
+ IExternalConnection FAR* pECServer = (IExternalConnection FAR*)(unsigned long)1;
+ hresult = m_pUnkControl->QueryInterface(IID_IExternalConnection,(LPVOID FAR*)&pECServer);
+#ifndef _CAIRO_
+ // BUGBUG: this assert far too annoying on Cairo right now [mikese]
+ // remove when we convert to MIDL 2.0 for ctypes.
+ AssertOutPtrIface(hresult, pECServer);
+#endif
+ if (hresult == NOERROR)
+ {
+ m_pWRorECServer = pECServer; // transfer addref
+ m_flags |= STDID_HASEC;
+ }
+ }
+
+ Assert(pMarshal != NULL); // don't handle NULL yet (if ever)
+ m_pMarshalNext = pMarshal;// NEVER addref'd
+
+ *ppUnkInternal = &m_InternalUnk; // this is what the m_refs=1 is for
+
+ m_pRH = NULL;
+
+ // AssertValid by callers
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::~CStdIdentity, private
+//
+// Synopsis: Final destruction of the identity object. ID has been
+// revoked by now (in internal ::Release). Here we disconnect
+// on server.
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+CStdIdentity::~CStdIdentity()
+{
+ Assert(m_refs == 0);
+ m_refs++; // simple guard against reentry of dtor
+ SetNowInDestructor(); // debug flag which enables asserts to detect
+
+ // strong count can be non-zero on client dtor
+ Assert(IsClient() || m_cStrongCnt == 0);
+ Assert(m_cPendingStrongRelease == 0);
+ DisconnectObject(0);
+
+ RevokeObjectID();
+
+ // m_pMarshalNext - no release
+
+ if (m_pRH != NULL)
+ {
+ // client RH must go away now since it has our punkOuter.
+ // IRH::Lock locks _punkObj for client so that the whole aggregate
+ // stays alive. Server side RH can persist, but might very well be
+ // disconnected and live only until calls unwind.
+#if DBG == 1
+ if (IsClient())
+ Assert(m_pRH->Release() == 0);
+ else
+#endif
+ m_pRH->Release();
+ }
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::GetRH, private
+//
+// Synopsis: Gets the RH for this identity (there is only one); may create;
+// Not addref'd.
+//
+// Returns: RH if successful; NULL when out of memory.
+//
+// History: 11-Dec-93 CraigWi Created.
+// 01-Aug-94 AlexGo handle out of memory cases
+//
+//--------------------------------------------------------------------
+
+INTERNAL_(IRemoteHdlr *)CStdIdentity::GetRH()
+{
+ if (m_pRH == NULL && m_pUnkControl != NULL)
+ {
+ // if server, give controlling unknown of object (which when
+ // agregated is also our pUnkOuter). If client, m_pUnkControl
+ // is our m_pUnkOuter.
+
+ HRESULT hr = E_OUTOFMEMORY;
+ m_pRH = new CRemoteHdlr(m_pUnkControl,
+ this, IsClient() ? 0 /*remote*/ : RHFLAGS_LOCAL, hr);
+
+ if(hr != NOERROR)
+ {
+ delete m_pRH;
+ m_pRH = NULL;
+ }
+ }
+
+ return m_pRH;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::GetMarshalNext, private
+//
+// Synopsis: Returns the next marshaler in the chain.
+//
+// Effects: If the m_pMarshalNext is PSTDMARSHAL, we return the
+// the IMarshal of the RH. Updates m_pMarshalNext.
+//
+// Returns: Marshal next if successful; NULL if out of memory. Not AddRef'd.
+//
+// History: 11-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+INTERNAL_(IMarshal *) CStdIdentity::GetMarshalNext()
+{
+ Assert(m_pMarshalNext != NULL);
+
+ if (m_pMarshalNext == PSTDMARSHAL)
+ {
+ // get std remoting marshal; NULL for oom; is Addref'd.
+ IMarshal *pMarshalNext = GetStdRemMarshal();
+ if (pMarshalNext == NULL)
+ return NULL;
+
+ // save ptr so we don't have to do this again; lifetime is
+ // governed by m_pRH (which we don't release until our destructor)
+ // and because we don't normally have a ref on this pointer, release.
+ m_pMarshalNext = pMarshalNext;
+ m_pMarshalNext->Release();
+ }
+
+ return m_pMarshalNext;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::CInternalUnk::QueryInterface, private
+//
+// Synopsis: internal QI for the identity object; responds to:
+// IUnknown
+// IMarshal
+// IStdIdentity
+// IProxyManager - if client
+// <any supported server interface when on client side>
+//
+// Returns: Normal QI values.
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStdIdentity::CInternalUnk::QueryInterface(REFIID iid, VOID **ppv)
+{
+ CStdIdentity *pStdID = GETPPARENT(this, CStdIdentity, m_InternalUnk);
+
+ pStdID->AssertValid();
+
+ if (IsEqualGUID(iid, IID_IUnknown))
+ *ppv = this;
+ else if (IsEqualGUID(iid, IID_IMarshal))
+ *ppv = (IMarshal *)pStdID;
+ else if (IsEqualGUID(iid, IID_IStdIdentity))
+ *ppv = (IStdIdentity *)pStdID;
+ else if (pStdID->IsClient())
+ {
+ if (IsEqualGUID(iid, IID_IProxyManager))
+ // on client side we also support IProxyManager
+ *ppv = (IProxyManager *)pStdID;
+
+ // else try client-side RH
+ else if (pStdID->m_pRH != NULL)
+ return pStdID->m_pRH->QueryInterface(iid, ppv);
+
+ else
+ goto NoInterface;
+ }
+ else
+ {
+NoInterface:
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ ((IUnknown *)*ppv)->AddRef();
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::CInternalUnk::AddRef, public
+//
+// Synopsis: Nothing special.
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CStdIdentity::CInternalUnk::AddRef(void)
+{
+ CStdIdentity *pStdID = GETPPARENT(this, CStdIdentity, m_InternalUnk);
+
+ pStdID->AssertValid();
+
+ AssertSz(!pStdID->IsInDestructor(), "CStdIdentity AddRef'd during destruction");
+
+ return InterlockedAddRef(&pStdID->m_refs);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::CInternalUnk::Release, public
+//
+// Synopsis: Releases the identity object. When the ref count goes
+// to zero, revokes the id and destroyes the object. This
+// method is thread safe (and BUGBUG: the rest code will
+// be made to synchronize with it).
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CStdIdentity::CInternalUnk::Release(void)
+{
+ CStdIdentity *pStdID = GETPPARENT(this, CStdIdentity, m_InternalUnk);
+ DWORD refs;
+
+ pStdID->AssertValid();
+
+ // get sem for rel; can get addrefs and revoke id, but releases are blocked
+ // BUGBUG: this seems awfully expensive, but this release count might
+ // not change that often (release marshal data, unlock external, rundown,
+ // rpc disconnect, etc.).
+ pStdID->m_mxsRelease.Request();
+
+ // BUGBUG: probably need to use this semaphore in places where we
+ // don't want to do work during/after shutdown (e.g., create RH,
+ // marshal interface, etc.)
+
+ if ((refs = InterlockedRelease(&pStdID->m_refs)) == 0)
+ {
+ // at this moment in time, refs is 0; this triggers revoking
+ // the id; we may still get addrefs and revoke id.
+
+ // clear all non-ref counted pointers (that we know about);
+ // currently this consists of the idtable and the remote handler.
+ pStdID->RevokeObjectID();
+
+ // if other pointers still present, we can get addref in here.
+ // if no other pointers, m_refs will still be zero
+
+ if (pStdID->m_refs == 0)
+ {
+ // no one possibly pointing to this object; release sem
+ // and delete (which also disconnects)
+ pStdID->m_mxsRelease.Release();
+ delete pStdID;
+ return 0;
+ }
+
+ // refs not zero; other addref'd pointers still exist
+ refs = pStdID->m_refs;
+ }
+
+ pStdID->m_mxsRelease.Release();
+
+ // allow releases; which may trigger the final release of the identity
+
+ return refs;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::IUnknown methods, public
+//
+// Synopsis: External IUnknown methods; delegates to m_pUnkOuter.
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStdIdentity::QueryInterface(REFIID riid, VOID **ppvObj)
+{
+ AssertValid();
+
+ return m_pUnkOuter->QueryInterface(riid, ppvObj);
+}
+
+
+STDMETHODIMP_(ULONG) CStdIdentity::AddRef(void)
+{
+ AssertValid();
+
+ return m_pUnkOuter->AddRef();
+}
+
+
+STDMETHODIMP_(ULONG) CStdIdentity::Release(void)
+{
+ AssertValid();
+
+ return m_pUnkOuter->Release();
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::GetObjectID, public
+//
+// Synopsis: Returns the GUID identity of the object; OID_NULL if revoked.
+//
+// Arguments: [pOid] -- The place for the ID
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(void) CStdIdentity::GetObjectID(OID *pOid)
+{
+ // can't call AssertValid() because this is used within the asserts
+
+ // NULL if not set yet (before first unmarshal in client or after revoke)
+ *pOid = m_oid;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::GetServer, public
+//
+// Synopsis: Returns a pUnk for the identified object; NULL on client side
+//
+// The pointer is optionally addrefed depending upon fAddRef
+//
+// Arguments: [fAddRef] -- whether to addref the ptr
+//
+// Returns: The pUnk on the object.
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(IUnknown *) CStdIdentity::GetServer(BOOL fAddRef)
+{
+ // CODEWORK: not multi-threaded; protect against simulataneous call to disconnect.
+
+ // can't call AssertValid() because the RH assert uses it
+
+ if (IsClient() || m_pUnkControl == NULL)
+ return NULL;
+
+ // Verify validity
+ Assert(IsValidInterface(m_pUnkControl));
+
+ if (fAddRef)
+ m_pUnkControl->AddRef();
+ return m_pUnkControl;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::RevokeObjectID, public
+//
+// Synopsis: Disassociates the OID and the object (handler or server).
+// Various other methods will fail (e.g., MarshalInterface).
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(void) CStdIdentity::RevokeObjectID(void)
+{
+ AssertValid();
+
+ // no need to work about multiple threading here; ClearObjectID just
+ // returns an error when the id is already gone
+
+ (void)ClearObjectID(m_oid, m_pUnkControl, this);
+ m_oid = OID_NULL;
+ m_clsidHandler = CLSID_NULL;
+
+ // NOTE: we do not disconnect here. If this routine is called
+ // by the object, that means the identity is aggregated and
+ // CoDisconnectObject still works (since it QI's for IStdIdentity).
+ // The only other call to this routine is in shutdown
+ // which will eventually cause a disconnect (in the destructor).
+
+ // That is, we want to avoid a call to this method which
+ // will prevent the object from disconnecting successfully.
+
+ // clear id pointer in RH (easier with shared weak ref struct)
+ // CODEWORK: what if the RH is created during this routine?
+ // CODEWORK: may change if we keep a identity count separte from the ref count.
+ if (m_pRH != NULL)
+ m_pRH->ClearIdentity();
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::GetStdRemMarshal, public
+//
+// Synopsis: Returns an internal pointer to the std remoting marshaler
+// part; this pointer cannot be passed outside the aggregate!
+//
+// Returns: AddRef'd pointer to std rem marshaler; NULL if out of memory.
+//
+// History: 14-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(IMarshal *) CStdIdentity::GetStdRemMarshal(void)
+{
+ AssertValid();
+
+ IRemoteHdlr *pRH = GetRH(); // creates if necessary; NOTE: no addref
+ IMarshal *pMarshal;
+
+ if (pRH != NULL &&
+ pRH->QueryInterface(IID_IMarshal, (void **)&pMarshal) == NOERROR)
+ return pMarshal;
+ else
+ return NULL;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::AddConnection, ReleaseConnection, public
+//
+// Synopsis: Add or release a connection (strong or weak); for now
+// forwards on to RH; CODEWORK: may move counts here.
+//
+// The AddRef/Release is avoided on the client side because it
+// messes up the client's notion of the ref count. In the
+// future we may keep the weak count separate from the
+// ref count and could maintain the count on both the
+// client and server.
+//
+// Returns: S_OK if successful; error code otherwise.
+// For clients, failures occurs only during the remote call.
+// For server AddConnection, the only failure is disconnected.
+//
+// Arguments: same as IExternalConnection methods.
+//
+// History: 15-Dec-93 CraigWi Created.
+// 16-May-94 CraigWi Added weak container connections
+// 19-Jul-94 AlexT Don't pass new extconn flags to WOW
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStdIdentity::AddConnection(DWORD extconn, DWORD reserved)
+{
+ AssertValid();
+
+ // we only allow these connection flags at present
+ Assert((extconn & ~(EXTCONN_STRONG|EXTCONN_WEAK|EXTCONN_CALLABLE)) == 0);
+
+ if (m_pUnkControl == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "Marshaling or locking a disconnected object"));
+ return CO_E_OBJNOTCONNECTED;
+ }
+
+ AssertSz(IsValidInterface(m_pUnkControl), "Invalid interface for marshaling or locking");
+
+ if (extconn&EXTCONN_STRONG)
+ {
+ // bump strong count and weak count (ref on identity itself)
+ InterlockedIncrement((long *)&m_cStrongCnt);
+ if (!IsClient())
+ AddRef();
+
+ // inform object of one more strong connection; do it after the
+ // increment so that any renentrant calls already have the new
+ // count. Nothing is expected at present, but better safe than
+ // sorry.
+ if (HasEC())
+ {
+ // 16-bit OLE only knew about EXTCONN_STRONG, so if we're in
+ // WOW we mask off the other EXTCONN flags. This allows
+ // 16-bit OLE apps which were incorrectly doing binary
+ // compares on the first parameter to run correctly.
+
+ GetEC()->AddConnection(IsWOWThread() ? (extconn & EXTCONN_STRONG) :
+ extconn,
+ NULL);
+ }
+
+
+ if (IsClient() && m_cStrongCnt == 1)
+ {
+ Assert((m_flags & (STDID_HASEC)) == 0);
+ Assert(m_pWRorECServer == NULL);
+ // client count went from 0 to 1; lock connection on server
+
+ HRESULT hr;
+ IRemoteHdlr *pRH = GetRH(); // creates if necessary; NOTE: no addref
+ if (pRH == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ {
+ // client strong count was zero, now one: tell server
+ hr = pRH->LockConnection(TRUE, FALSE);
+ }
+
+ if (FAILED(hr))
+ {
+ InterlockedDecrement((long *)&m_cStrongCnt);
+ if (!IsClient())
+ Release();
+ return hr;
+ }
+ }
+
+ CairoleDebugOut((DEB_ITRACE, "Inc [%x] StrongCnt of ID %x\n", m_cStrongCnt, this));
+ Win4Assert(m_cStrongCnt > 0);
+ return S_OK;
+ }
+ else if (extconn&EXTCONN_WEAK)
+ {
+ // we don't keep a separate count of weak connections
+
+ CairoleDebugOut((DEB_ITRACE, "Inc WeakCnt of ID %x\n", this));
+
+ // also hold alive the identity (which holds this RH alive)
+ if (!IsClient())
+ AddRef();
+ return S_OK;
+ }
+ else
+ {
+ return E_UNEXPECTED;
+ }
+
+}
+
+
+STDMETHODIMP CStdIdentity::ReleaseConnection(DWORD extconn,
+ DWORD reserved, BOOL fLastReleaseCloses)
+{
+ AssertValid();
+
+ // we only allow these connection flags at present
+ Assert((extconn & ~(EXTCONN_STRONG|EXTCONN_WEAK|EXTCONN_CALLABLE)) == 0);
+
+ // NOTE: it is ok to call this method for disconnected objects (to
+ // adjust the reg counts.
+
+ // for now, must have fLastUR with tableweak. This is because
+ // we can't keep the identity around and thus not release the server
+ // object when there are no strong and no weak connections.
+ Assert((extconn&EXTCONN_WEAK) == 0 || fLastReleaseCloses);
+
+ AssertSz(m_pUnkControl == NULL || IsValidInterface(m_pUnkControl),
+ "Invalid interface for unmarshaling or unlocking");
+
+ if (extconn&EXTCONN_STRONG)
+ {
+ Win4Assert(m_cStrongCnt > 0 && "CoLockObjectExternal(FALSE) probably called too many times");
+
+ // CODEWORK: this is not thread safe since we may get an increment
+ // after the decrement and decision to release and since this
+ // release (_punkObj) may in fact be the one to close the object
+
+ CairoleDebugOut((DEB_ITRACE, "Dec [%x] StrongCnt of ID %x\n",
+ m_cStrongCnt - 1, this));
+
+ // inform object of one less strong connection; do it before the
+ // decrement so that the count is stable during any reentrant calls.
+ if (m_pWRorECServer != NULL)
+ {
+ Assert((m_flags & STDID_HASEC) != 0);
+ DWORD cRefsBefore = m_cStrongCnt;
+
+ m_cPendingStrongRelease++; // for reentrant Disconnect
+
+ Assert(m_cPendingStrongRelease <= m_cStrongCnt);
+
+ // 16-bit OLE only knew about EXTCONN_STRONG, so if we're in
+ // WOW we mask off the other EXTCONN flags. This allows
+ // 16-bit OLE apps which were incorrectly doing binary
+ // compares on the first parameter to run correctly.
+
+ Verify(GetEC()->ReleaseConnection(
+ IsWOWThread() ?
+ (extconn & EXTCONN_STRONG) :
+ extconn,
+ NULL,
+ fLastReleaseCloses)
+ >= cRefsBefore-m_cPendingStrongRelease);
+
+ m_cPendingStrongRelease--; // balance above
+ }
+
+ // if last strong ref, on server side, still connected and allowed
+ // to disconnect, do so. Disconnect will release all refs we
+ // have to object. We include the m_pWRorECServer in the test so that
+ // we remain connected when IEC or IWR is supported (but not for Wow,
+ // since Wow apps weren't expecting this). This is important
+ // so that a simple addref on the object can keep it alive *AND*
+ // the connection from this identity to the object remain. If
+ // we disconnected here under all conditions, a simple addref
+ // would keep the object alive, but separte the identity from the
+ // object. By implementing IEC, an object says that it knows how to
+ // shutdown correctly when the strong count goes to zero.
+ // CODEWORK: make thread safe
+ LONG lRefs = InterlockedDecrement((long*)&m_cStrongCnt);
+ HRESULT hr = S_OK;
+
+ if (0 == lRefs && m_pUnkControl != NULL &&
+ (IsWOWThread() || m_pWRorECServer == NULL))
+ {
+ // client: no strong refs (other conditions always true of clients)
+ // server: no strong refs, still connected, IWR/IEC not supported
+
+ if (!IsClient())
+ {
+ // server
+ if (fLastReleaseCloses)
+ {
+ // strong count now zero; disconect server object if flag
+ DisconnectObject(0);
+ }
+ }
+ else
+ {
+ // strong ref count now zero, tell server that connection is wk;
+ // only tell server if we think we are connected; if we later
+ // connect, we will make the same call there.
+ if (IsConnected())
+ {
+ IRemoteHdlr *pRH = GetRH();// NOTE: no addref
+ if (pRH == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ {
+ // client strong count was one, now zero: tell server
+ hr = pRH->LockConnection(FALSE, fLastReleaseCloses);
+ }
+ }
+
+ // if failed, oh well. Connection still weak.
+ }
+ }
+
+ // release hold on identity; ID may be gone now
+ if (!IsClient())
+ Release();
+
+ return hr;
+ }
+ else if (extconn&EXTCONN_WEAK)
+ {
+ // we don't keep a separate count of weak connections
+
+ CairoleDebugOut((DEB_ITRACE, "Dec WeakCnt of ID %x\n", this));
+
+ // don't need the identity (which might release this ID)
+ if (!IsClient())
+ Release();
+ return S_OK;
+ }
+ else
+ {
+ return E_UNEXPECTED;
+ }
+}
+
+
+//+------------------------------------------------------------------------
+//
+// Member: CStdIdentity::ReleaseKeepAlive, public
+//
+// Synopsis: Releases given pointer via IWeakRef if object supports it
+//
+// Arguments: [pUnkToRelease] -- The pUnk to release; must be on the
+// object in question;
+//
+// History: 2-June-94 CraigWi Created
+//
+//-------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CStdIdentity::ReleaseKeepAlive(IUnknown *pUnkToRelease, DWORD reserved)
+{
+ // client side or server which doesn't support IWR or disconnected
+ return pUnkToRelease->Release();
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::GetUnmarshalClass, public
+//
+// Synopsis: Returns the identity unmarshal class.
+//
+// Returns: S_OK - class is returned
+//
+// BUGBUG: error for unknown context
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStdIdentity::GetUnmarshalClass(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid)
+{
+ AssertValid();
+
+ // BUGBUG: better understand all contexts!
+
+ *pCid = CLSID_IdentityUnmarshal;
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::GetMarshalSizeMax, public
+//
+// Synopsis: Returns the max marshal size for the given context. Adds
+// together the identity overhead and the size of the
+// follow on marshaler.
+//
+// Returns: S_OK - size set
+//
+// E_OUTOFMEMORY
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStdIdentity::GetMarshalSizeMax(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize)
+{
+ AssertValid();
+
+ // size of us + follow on marshal
+ HRESULT hr;
+ IMarshal *pMarshalNext = GetMarshalNext(); // NOTE: not Addref'd
+
+ if (pMarshalNext == NULL)
+ return E_OUTOFMEMORY;
+
+ hr = pMarshalNext->GetMarshalSizeMax(riid, pv, dwDestContext,
+ pvDestContext, mshlflags, pSize);
+
+ // add in the size we need: header + clsid if not std marshal.
+ *pSize += sizeof(SIdentityDataHdr) +
+ (!IsEqualGUID(m_clsidHandler, CLSID_StdMarshal) ? sizeof(CLSID) : 0);
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::MarshalInterface, public
+//
+// Synopsis: Marshal this identity to the context given.
+//
+// Effects: Writes a the marshal data for the identity and then
+// asks the follow on marshaler to write its data.
+//
+// Returns: S_OK - done
+//
+// E_OUTOFMEMORY
+//
+// IStream errors
+//
+// GetUnmarshalClass errors
+//
+// other errors in follow on marshal
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStdIdentity::MarshalInterface(LPSTREAM pStm, REFIID riid,
+ LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ AssertValid();
+
+ HRESULT hr;
+ IMarshal *pMarshalNext = GetMarshalNext(); // NOTE: not Addref'd
+ SIdentityDataHdr idh;
+ CLSID clsidHandler;
+
+ if (pMarshalNext == NULL)
+ return E_OUTOFMEMORY;
+
+ // CODEWORK: multi-thread: should prevent revoked and/or disconnected
+ // identity from being marshaled.
+ if (IsEqualGUID(m_oid, OID_NULL))
+ return CO_E_OBJNOTREG;
+
+ idh.dwflags = mshlflags & IDENFLAGS_TABLE;
+
+ // if PSTDMARSHAL, we use existing clsid (better not be NULL)
+ // else we get the clsid from pMarshalNext since it might be
+ // determined by the destcontext.
+
+ // NOTE: this call can't delegate the 'stdandard marshal' since we
+ // would end up in an infnite loop. If the app supplied a pMarshalNext
+ // (at creation time), it must use IStdIdentity::GetStdRemMarshal()
+ // for contexts it doesn't understand.
+
+ if (StdMarshalNext())
+ {
+ Assert(!IsEqualGUID(m_clsidHandler, CLSID_NULL));
+ clsidHandler = m_clsidHandler;
+ }
+ else
+ {
+ hr = pMarshalNext->GetUnmarshalClass(IID_IUnknown, NULL,
+ dwDestContext, pvDestContext, mshlflags, &clsidHandler);
+ if (FAILED(hr))
+ return hr;
+ }
+
+ if (IsEqualGUID(clsidHandler, CLSID_StdMarshal))
+ idh.dwflags |= IDENFLAGS_STDMARSHAL;
+
+ // store the object id in the data
+ memcpy(&idh.ObjectID, &m_oid, sizeof(idh.ObjectID));
+
+ // write the interface header into the stream
+ hr = pStm->Write(&idh, sizeof(idh), NULL);
+
+ // write clsid if not std marshal
+ if (SUCCEEDED(hr) && (idh.dwflags & IDENFLAGS_STDMARSHAL) == 0)
+ hr = pStm->Write(&clsidHandler, sizeof(clsidHandler), NULL);
+
+ if (SUCCEEDED(hr))
+ hr = pMarshalNext->MarshalInterface(pStm, riid, pv, dwDestContext,
+ pvDestContext, mshlflags);
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::UnmarshalInterface, public
+//
+// Synopsis: Second stage in unmarshaling an identity object; first
+// part is handled by the static marshaler in coapi.cxx.
+//
+// Effects: Reads the identity header, records the identity (if not
+// done as of yet), passes the rest of the data on to
+// the follow on marshaler and then returns the requested
+// interface.
+//
+// Returns: S_OK
+//
+// E_OUTOFMEMORY
+//
+// IStream errors
+//
+// CO_E_OBJNOTCONNECTED - trying to unmarshal on the server
+// side, but the object was disconnected.
+//
+// E_UNEXPECTED - at least: this object already a different
+// identity.
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStdIdentity::UnmarshalInterface(LPSTREAM pStm, REFIID riid,
+ VOID **ppv)
+{
+ AssertValid();
+
+ HRESULT hr;
+ IMarshal *pMarshalNext = GetMarshalNext(); // NOTE: not Addref'd
+ SIdentityDataHdr idh;
+ CLSID clsid;
+ BOOL fSetObjectID = FALSE;
+
+ if (ppv)
+ *ppv = NULL;
+
+ if (pMarshalNext == NULL)
+ return E_OUTOFMEMORY;
+
+ hr = ReadIdentityHeader(pStm, &idh, &clsid, FALSE /*fTransparent*/);
+
+ if (FAILED(hr))
+ return hr;
+
+ if (!IsEqualGUID(m_oid, GUID_NULL))
+ {
+ // make sure id matches
+ if (!IsEqualGUID(idh.ObjectID, m_oid))
+ return E_UNEXPECTED;
+
+ // on the clsid: this clsid was used to create the handler which
+ // aggregated the std remoting stuff. if std marshaling is next,
+ // it should be the same as the current m_clsidHandler. otherwise
+ // we can't check.
+
+ if (StdMarshalNext() && !IsEqualGUID(clsid, m_clsidHandler))
+ return E_UNEXPECTED;
+ }
+ else
+ {
+ // become this identity; may fail because of multi-threading;
+ // if two threads unmarshal a pointer to the same object at the
+ // same time, the first one to complete SetObjectID wins. Since
+ // very little of the initialization has taken place, the static
+ // marshaler detects this and simply releases the duplicate and
+ // reunmarshals the data with the newly created one.
+ // CODEWORK: there is a possibility of an inifinite loop if the
+ // winning identity is released before during the subsequent lookup.
+
+ Assert(IsClient()); // can only happen on client side
+
+ m_oid = idh.ObjectID;
+
+ if (StdMarshalNext())
+ m_clsidHandler = clsid;
+ // else determined by next marshal
+
+ hr = SetObjectID(idh.ObjectID, m_pUnkOuter, this, NULL);
+ fSetObjectID = TRUE; // we cleanup even if this SetObjectID fails
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // this object cannot return a new identity; we specify this
+ // by passing IID_NULL (and expect success and no crashes!)
+ hr = pMarshalNext->UnmarshalInterface(pStm, IID_NULL, NULL);
+ }
+
+ // ah, got the object fully (re)initialized; now get the requested iface
+ if (SUCCEEDED(hr))
+ {
+ if (m_pUnkControl == NULL)
+ {
+ // server disconnected
+ hr = CO_E_OBJNOTCONNECTED;
+
+ // BUGBUG debug info from 16bit OLE
+ }
+ else if (IsEqualGUID(riid, IID_NULL))
+ // for CreateServer's benefit
+ hr = NOERROR;
+ else
+ {
+ // connected server or client
+ hr = m_pUnkControl->QueryInterface(riid, ppv);
+ }
+ }
+ else
+ {
+ // SetObjectID or unmarshaling failed; revoke id (no error if already
+ // revoked or not set).
+ if (fSetObjectID)
+ RevokeObjectID();
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::ReleaseMarshalData, public
+//
+// Synopsis: Releases identity marshal data.
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStdIdentity::ReleaseMarshalData(LPSTREAM pStm)
+{
+ AssertValid();
+
+ HRESULT hr;
+ IMarshal *pMarshalNext = GetMarshalNext(); // NOTE: not Addref'd
+ SIdentityDataHdr idh;
+ CLSID clsid;
+
+ if (pMarshalNext == NULL)
+ return E_OUTOFMEMORY;
+
+ // BUGBUG: make sure we are not doing release table marshal on client side
+
+ hr = ReadIdentityHeader(pStm, &idh, &clsid, FALSE /*fTransparent*/);
+
+ if (FAILED(hr))
+ return hr;
+
+ // if we have an id, verify that it is the same as the one in the header
+ if (!IsEqualGUID(m_oid, OID_NULL))
+ {
+ // make sure id matches
+ if (!IsEqualGUID(idh.ObjectID, m_oid))
+ return E_UNEXPECTED;
+
+ if (StdMarshalNext() && !IsEqualGUID(clsid, m_clsidHandler))
+ return E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ // pass on; remote handler deals with table marshaling, etc.
+ hr = pMarshalNext->ReleaseMarshalData(pStm);
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::DisconnectObject, public
+//
+// Synopsis: Disconnects the server object from the identity and
+// remoting systems.
+//
+// This code is safe for reentrant calls.
+//
+// Effects: Further marshaling, connect, lock will result in an error.
+//
+// Returns: S_OK
+//
+// see docs.
+//
+// History: 15-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStdIdentity::DisconnectObject(DWORD dwReserved)
+{
+ AssertValid();
+
+ HRESULT hr;
+ // BUGBUG: prevent creation of RH if not yet created!
+ IMarshal *pMarshalNext = GetMarshalNext(); // NOTE: not Addref'd
+
+ if (pMarshalNext != NULL)
+ hr = pMarshalNext->DisconnectObject(dwReserved);
+ else // no RH, not connected there.
+ hr = NOERROR;
+
+ // since the marshal next disconnected sucessfully, disconnect us;
+ // for clients, revoke id too since the server may shutdown; for
+ // servers, release m_pUnkControl.
+ if (SUCCEEDED(hr))
+ {
+ if (IsClient())
+ // client side: remove from global id table; leave 'connected'
+ // since m_pUnkControl is really our pUnkOuter.
+ RevokeObjectID();
+ else
+ {
+ // server side: release m_pUnkControl;
+ // prevent problem on recursive disconnect
+ if (m_pUnkControl != NULL)
+ {
+ AssertSz(IsValidInterface(m_pUnkControl), "Invalid IUnknown interface during disconnect");
+
+ void *pWRorECSave = m_pWRorECServer;
+ DWORD flagsSave = m_flags;
+
+ Assert((m_pWRorECServer != NULL) ==
+ ((m_flags & (STDID_HASEC)) != 0));
+
+ if (m_pWRorECServer != NULL)
+ {
+ // disconnect is in effect release of all external
+ // connections (a later connect, which isn't really
+ // supported now, would add back any remaining
+ // connections.) We need to maintain the connection
+ // count (i.e., not change it here) so that we can do the
+ // proper thing on reconnect and not assert when the app
+ // removes the external connections (e.g., via
+ // CoLockObjectExternal(FALSE)). A key point about later
+ // calls to lock/unlock is that we set m_pWRorECServer to
+ // NULL which will not communicate the lock to the
+ // server. CoDisconnectObject, for example, calls this
+ // method and then releases all lrpc connections, some of
+ // which may be strong and thus call ReleaseRegConn which
+ // we don't want to call the server.
+
+ AssertSz(IsValidInterface(m_pWRorECServer), "Invalid IWR/IEC interface during disconnect");
+
+ // clear these together so reentrant calls are simpler
+ m_pWRorECServer = NULL;
+ m_flags &= ~(STDID_HASEC);
+
+ Assert(m_cPendingStrongRelease <= m_cStrongCnt);
+
+ DWORD cRefsConn = m_cStrongCnt - m_cPendingStrongRelease;
+ while (cRefsConn-- != 0)
+ {
+ // CODEWORK: how many are callable??
+ Verify(((IExternalConnection *)pWRorECSave)->
+ ReleaseConnection(EXTCONN_STRONG,
+ NULL, FALSE) >= cRefsConn);
+ }
+
+ // CODEWORK: the above code needs some changes to handle
+ // multiple threads
+ }
+
+ IUnknown *pUnkControl = m_pUnkControl;
+ m_pUnkControl = NULL;
+
+ // CODEWORK: for thread safety, pass &m_pUnkControl to
+ // ClearObjectUnk and clear it while holding the semaphore
+ // for the table; do the same for the call to ClearObjectID;
+ // this prevents a race condition from triggering an
+ // (important) assert within those routines.
+
+ // clear id table so a reuse of pUnkControl will not find it
+ (void)ClearObjectUnk(m_oid, pUnkControl, this);
+
+ // have released all pointers (except perhaps some in the RH
+ // due to a delayed disconnect) and now we release the
+ // final one or two.
+ // IExternalConnection case or nothing
+ if (flagsSave & STDID_HASEC)
+ ((IExternalConnection *)pWRorECSave)->Release();
+ pUnkControl->Release();
+ }
+ }
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::MiIsForClsid, private
+//
+// Synopsis: Determines if the marshaled interface uses std remoting
+// and the handler for the clsid given.
+//
+// Arguments: [pIFD] -- The raw marshaled interface data
+// [clsidGiven] -- The one to check agains
+// [pcbSkipToIdenHdr] -- The amount of data before the identity hdr
+//
+// Returns: The result of the condition above.
+//
+// History: 06-Jan-94 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+INTERNAL_(BOOL) CStdIdentity::MiIsForClsid(InterfaceData *pIFD,
+ REFCLSID clsidGiven, DWORD *pcbSkipToIdenHdr)
+{
+ BYTE *pb = &pIFD->abData[0];
+
+ AssertValid();
+
+ if ((((SMiApiDataHdr *)pb)->dwflags & MIAPIFLAGS_STDIDENTITY) == 0)
+ // not std identity
+ return FALSE;
+
+ // NOTE: because of the above test, there is no clsid after the data hdr
+
+ DWORD cbExtension = 0;
+ if (((SMiApiDataHdr *)pb)->dwflags & MIAPIFLAGS_EXTENSION)
+ cbExtension = sizeof(DWORD) + *(DWORD *)(pb + sizeof(SMiApiDataHdr));
+
+ *pcbSkipToIdenHdr = sizeof(SMiApiDataHdr) + cbExtension;
+ pb += *pcbSkipToIdenHdr;
+
+ // pb now points to identity hdr; extract clsid for handler
+
+ CLSID clsidHdlr;
+ if (((SIdentityDataHdr *)pb)->dwflags & IDENFLAGS_STDMARSHAL)
+ // uses std marshal; clsid is CLSID_StdMarshal
+ clsidHdlr = CLSID_StdMarshal;
+ else
+ clsidHdlr = *(CLSID *)(pb + sizeof(SIdentityDataHdr));
+
+ // allow clsidHdlr to be the stdmarshal since that is a subset of
+ // all handlers which use std remoting.
+ return IsEqualGUID(clsidHdlr, CLSID_StdMarshal) ||
+ IsEqualGUID(clsidGiven, clsidHdlr);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::CreateServer, public
+//
+// Synopsis: Creates the server clsid in the given context and
+// attaches it to this handler.
+//
+// History: 16-Dec-93 CraigWi Created.
+//
+// NOTE : remote aggregation requires that a client
+// be able to dtermine the clsid up front for the handler. This
+// generally means that some published clsid is used (in 16bit OLE2
+// this was always the same as the object itself). In particular,
+// this means that remote aggregation requires the use of std remoting;
+// the exact nature of the restriction is yet to be detailed.
+//
+// CODEWORK: this code is not thread safe
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStdIdentity::CreateServer(REFCLSID rclsid, DWORD clsctx, void *pv)
+{
+ HRESULT hr;
+ InterfaceData *pIFD;
+
+ AssertValid();
+
+ Assert(IsClient()); // must be client side
+ Assert(IsValidInterface(m_pUnkControl)); // must be valid
+ Assert(!IsConnected());
+
+ // Loop trying to get object from the server. Because the server can be
+ // in the process of shutting down and respond with a marshaled interface,
+ // we will retry this call if unmarshaling fails assuming that the above
+ // is true.
+ const int MAX_SERVER_TRIES = 3;
+
+ for (int i = 0; i < MAX_SERVER_TRIES; i++)
+ {
+
+ // create object and get back marshaled pointer
+ if (FAILED(hr = ScmCreateObjectInstance(rclsid, clsctx, pv, &pIFD)) ||
+ hr > SCM_S_HANDLER)
+ {
+ // If an error occurred, return that otherwise convert a wierd
+ // success into E_FAIL. The point here is to return an error that
+ // the caller can figure out what happened.
+ return FAILED(hr) ? hr : E_FAIL;
+ }
+
+ // NOTE: this requires the ability to ReleaseMarshalData on error and
+ // have it work!!
+ CXmitRpcStream xrpc(pIFD);
+ LARGE_INTEGER li;
+ DWORD cbSkipToIdenHdr;
+
+ // marshaled interface must be std marshaling and clsid must match
+ if (!MiIsForClsid(pIFD, rclsid, &cbSkipToIdenHdr))
+ hr = E_FAIL; // BUGBUG real error
+ else
+ {
+ // skip SMiDataHdr + extension; length calculated above
+ LISet32(li, cbSkipToIdenHdr);
+ xrpc.Seek(li, STREAM_SEEK_SET, NULL);
+
+ // just unmarshal as normal (in case there is app data).
+ hr = UnmarshalInterface(&xrpc, IID_NULL, NULL);
+
+ if (FAILED(hr))
+ {
+ CairoleDebugOut((DEB_ERROR, "ScmCreateObjectInstance Result FAiled unmarshal\n"));
+ }
+
+ // NOTE: the above routine returns an error if, for some reason, the
+ // identity already exists in this process (via call to SetObjectID).
+ }
+
+ // rewind stream, release marshaled data and free data
+ LISet32(li, 0);
+ xrpc.Seek(li, STREAM_SEEK_SET, NULL);
+ CoReleaseMarshalData(&xrpc);
+ MIDL_user_free(pIFD);
+
+ // If either this worked or we got a packet we couldn't unmarshal
+ // at all we give up. Otherwise, we will hope that recontacting the
+ // SCM will fix things.
+ if (SUCCEEDED(hr) || (hr == E_FAIL))
+ {
+ break;
+ }
+ }
+
+ // if no locks, tell stub mgr about weak connection; ignore errors
+ if (hr == NOERROR && m_cStrongCnt == 0)
+ {
+ Assert(IsConnected());
+
+ IRemoteHdlr *pRH = GetRH();// NOTE: no addref
+ if (pRH != NULL)
+ {
+ // client strong count is zero and we are now conected: tell server
+ pRH->LockConnection(FALSE, FALSE);
+ }
+ }
+
+ // CODEWORK: could fail because other thread created identity??
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::IsConnected, public
+//
+// Synopsis: Indicates if the client is connected to the server.
+// Only the negative answer is definitive because we
+// might not be able to tell if the server is connected
+// and even if we could, the answer might be wrong by
+// the time the caller acted on it.
+//
+// If we answer FALSE, we clean up the identity (part of a
+// disconnect). Each level of the IsConnected calls cleans
+// up similarly.
+//
+// Returns: TRUE if the server might be connected; FALSE if
+// definitely not.
+//
+// History: 16-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(BOOL) CStdIdentity::IsConnected(void)
+{
+ Assert(IsClient()); // must be client side
+ AssertValid();
+
+ if (m_pRH && m_pRH->IsConnected())
+ {
+ return TRUE;
+ }
+ else
+ {
+ RevokeObjectID();
+ AssertValid();
+ return FALSE;
+ }
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::LockConnection, public
+//
+// Synopsis: Locks or unlocks the connection. Used only for container
+// connections now. May want to change if we expose.
+//
+// Effects: Changes the behavior in the RH on the server side
+// such that this connection, while it causes the RH
+// to addref the pUnk, it does not come into play in
+// the strong count.
+//
+// Returns:
+//
+// History: 16-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP CStdIdentity::LockConnection(BOOL fLock, BOOL fLastUnlockReleases)
+{
+ HRESULT hr;
+
+ Assert(IsClient()); // must be client side
+
+ AssertValid();
+
+ if (fLock)
+ hr = AddConnection(EXTCONN_STRONG, 0);
+ else
+ hr = ReleaseConnection(EXTCONN_STRONG, 0, fLastUnlockReleases);
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::Disconnect, public
+//
+// Synopsis: Disconnects the client from the server.
+//
+// Effects: Releases the rpc channel and tells the proxy object to do so.
+//
+// Returns:
+//
+// History: 16-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+STDMETHODIMP_(void) CStdIdentity::Disconnect()
+{
+ Assert(IsClient()); // must be client side
+
+ DisconnectObject(0);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CStdIdentity::CreateServerWithHandler
+//
+// Synopsis: Creates a dummy function that returns E_NOTIMPL
+//
+// Effects: The CreateServerWithHandler functionality is only supported
+// in DCOM. DCOMREM actually implements this functionality.
+//
+// Arguments: [rclsid] --
+// [clsctx] --
+// [pv] --
+// [rclsidHandler] --
+// [iidSrv] --
+// [ppv] --
+// [iidClnt] --
+// [pClientSiteInterface] --
+//
+//
+// History: 11-29-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CStdIdentity::CreateServerWithHandler(REFCLSID rclsid, DWORD clsctx, void *pv,
+ REFCLSID rclsidHandler, IID iidSrv, void **ppv,
+ IID iidClnt, void *pClientSiteInterface)
+{
+ return E_NOTIMPL;
+}
+
+
+
+#if DBG == 1
+//+-------------------------------------------------------------------
+//
+// Member: CStdIdentity::AssertValid
+//
+// Synopsis: Validates that the state of the object is consistent.
+//
+// History: 26-Jan-94 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+void CStdIdentity::AssertValid()
+{
+ AssertSz(m_refs < 0x7fff, "Identity ref count unreasonable");
+
+ // ensure we have the controlling unknown
+ Assert(IsValidInterface(m_pUnkOuter)); // must be valid
+
+ // NOTE: don't carelessly AddRef/Release because of weak references
+
+ Assert((m_flags & ~(STDID_SERVER | STDID_CLIENT | STDID_STDMARSHAL |
+ STDID_HASEC | STDID_INDESTRUCTOR)) == 0);
+
+ Assert((m_pWRorECServer != NULL) ==
+ ((m_flags & (STDID_HASEC)) != 0));
+
+ if (!IsEqualGUID(m_oid, OID_NULL) && StdMarshalNext())
+ {
+ Assert(!IsEqualGUID(m_clsidHandler, CLSID_NULL));
+ // CODEWORK: could get clsid again and check
+ }
+
+ if (IsEqualGUID(m_oid, OID_NULL))
+ Assert(IsEqualGUID(m_clsidHandler, CLSID_NULL));
+ else
+ {
+ IStdIdentity *pStdID;
+ Verify(LookupIDFromID(m_oid, FALSE /*fAddRef*/, &pStdID) == NOERROR);
+ Assert(pStdID == (IStdIdentity *)this);
+ // pStdID not addref'd
+ }
+
+ if (IsClient())
+ Assert(m_pUnkControl == m_pUnkOuter);
+
+ // must have RH tell identity when object goes away so we can NULL this
+ if (m_pUnkControl != NULL)
+ Assert(IsValidInterface(m_pUnkControl)); // must be valid
+
+ Assert(m_pMarshalNext != NULL);
+ if (m_pMarshalNext == PSTDMARSHAL)
+ Assert(StdMarshalNext());
+
+ if (StdMarshalNext())
+ {
+ if (m_pRH == NULL)
+ {
+ // haven't converted to real pointer yet
+ Assert(m_pMarshalNext == PSTDMARSHAL);
+ }
+ else if (m_pMarshalNext != PSTDMARSHAL)
+ {
+ // verify pointer we have is from RH
+ Assert(m_pMarshalNext == (IMarshal *)(CRemoteHdlr *)m_pRH);
+ }
+ }
+
+ // NOTE: if this cast is not correct, the asserts will fire wildly
+ // because the this pointer will be off by at least 4 bytes.
+ if (m_pRH)
+ ((CRemoteHdlr *)m_pRH)->AssertValid();
+}
+#endif // DBG == 1
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CreateStdIdentity
+//
+// Synopsis: Creates a new identity object, possibly aggregated.
+// When not aggregated, same as CoGetStandardMarshal().
+//
+// Effects: The identity object is normaly the lead marshaler in a
+// chain of marshalers. The pMarshal determines the next
+// marshaler in the chain. The std marshaler is always
+// retrievable with the GetStdRemMarshaler() method. If
+// this is a new identity, we figure out the clsidHandler
+// up front.
+//
+// Arguments: [pUnkOuter] -- The controlling unknown if aggregated
+// [pUnkControl] -- Controlling unknown if not aggregated.
+// These two cannot both be NULL. If they are both non-NULL,
+// they must be the same.
+// [pMarshal] - one of NULL, PSTDMARSHAL or real pMarshal.
+// See above.
+// [riid, ppv] - interface requested and place for pointer to
+// that interface.
+//
+// Returns: S_OK - new identity created and if pUnkOuter specified,
+// aggregated. If pUnkOuter == NULL, it was possible
+// that another thread created the identity and that
+// we simply reused it.
+//
+// E_NOINTERFACE - interface not supported; only returned
+// when not aggregated and indicates that the identity
+// object does not support the interface.
+//
+// E_OUTOFMEMORY -
+//
+// CO_E_OBJISREG - pUnkOuter was specified and another thread
+// had already created the identity.
+//
+// BUGBUG - the identity GUID could not be created
+//
+// E_UNEXPECTED - pUnkOuter != NULL and riid != IID_IUnknown
+//
+// BUGBUG: curently we combine server side with id creation. Consider
+// separting it for docfile. They can't just use CreateIdentityHandler
+// always because it doesn't allocate an oid.
+//
+// History: 1-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+INTERNAL CreateStdIdentity(IUnknown *pUnkOuter, IUnknown *pUnkControl,
+ IMarshal *pMarshal, REFIID riid, void **ppv)
+{
+ HRESULT hr;
+ // BUGBUG: validiate parameters more ???
+
+ // ensure initialized; checked by caller
+ Assert(IsApartmentInitialized());
+
+ *ppv = NULL;
+
+ if (pMarshal == NULL)
+ // we don't handle the NULL case yet (if we ever do, we would
+ // use a static null marshaler).
+ return E_INVALIDARG;
+
+ if (pUnkOuter == NULL)
+ {
+ // not aggregated;
+ if (pUnkControl == NULL)
+ return E_INVALIDARG;
+ }
+ else
+ {
+ // aggregated
+ if (!IsEqualGUID(riid, IID_IUnknown))
+ return E_UNEXPECTED;
+
+ Assert(pUnkControl == NULL || pUnkControl == pUnkOuter);
+ pUnkControl = pUnkOuter;
+ }
+
+#if DBG == 1
+ // the caller should have a strong reference and so these tests
+ // should not disturb the object.
+
+ // addref/release pUnkControl; shouldn't go away (i.e.,
+ // should be other ref to it).
+ pUnkControl->AddRef();
+ Verify(pUnkControl->Release() != 0);
+
+ // verify that pUnkControl is in fact the controlling unknown
+ IUnknown *pUnkT;
+ Verify(pUnkControl->QueryInterface(IID_IUnknown,(void **)&pUnkT)==NOERROR);
+ Assert(pUnkControl == pUnkT);
+ Verify(pUnkT->Release() != 0);
+
+ if (pMarshal != PSTDMARSHAL)
+ {
+ // addref/release pMarshal; shouldn't go away (i.e.,
+ // should be other ref to it).
+ pMarshal->AddRef();
+ Verify(pMarshal->Release() != 0);
+ }
+#endif
+
+ // create oid
+ OID oid;
+ CLSID clsidHandler;
+
+#if defined(_CHICAGO_)
+ RPC_STATUS rpcStat = CoCreateAlmostGuid((UUID *)&oid);
+#else
+ RPC_STATUS rpcStat = UuidCreate((UUID *)&oid);
+#endif
+
+ // determine clsid
+ if (pMarshal == PSTDMARSHAL)
+ {
+ // if defined, get class from IStdMarshalInfo::GetClassForHandler;
+ // if not, use persistant class id; use CLSID_NULL if error.
+ IStdMarshalInfo FAR* pStdMarshalInfo;
+ if ((hr = pUnkControl->QueryInterface(IID_IStdMarshalInfo,
+ (LPVOID FAR*)&pStdMarshalInfo)) == NOERROR) {
+ // has standard marshal info; i.e., wants or needs to override
+ // default behavior of using persistant clsid.
+ hr = pStdMarshalInfo->GetClassForHandler(NULL, NULL,
+ &clsidHandler);
+ pStdMarshalInfo->Release();
+
+ // NOTE: we don't call this for each context; see note above.
+ }
+#if DBG == 1
+ else {
+# ifndef _CAIRO_
+ // BUGBUG: this assert far too annoying for Cairo right now [mikese]
+ // remove when we convert to MIDL 2.0 for ctypes.
+
+ AssertOutPtrFailed(pStdMarshalInfo);
+# endif
+ }
+#endif
+
+ // if queries or calls to get clsid resulted in error or
+ // handler NULL (compatibility with 16bit code), use
+ // CLSID_StdMarshal.
+ if (hr != NOERROR || IsEqualGUID(clsidHandler, CLSID_NULL))
+ clsidHandler = CLSID_StdMarshal;
+ }
+ else
+ {
+ AssertSz(FALSE, "pMarshal != PSTDMARSHAL case not tested");
+
+ // unmarshal class comes from pMarshal; retrieved at each
+ // marshal interface call.
+ clsidHandler = CLSID_NULL;
+ }
+
+ // create object
+ IStdIdentity *pStdID;
+ IUnknown *pUnkID;
+ pStdID = new CStdIdentity(STDID_SERVER, pUnkOuter, pUnkControl, oid,
+ clsidHandler, pMarshal, &pUnkID);
+ if (pStdID == NULL)
+ return E_OUTOFMEMORY;
+
+ // we now have two pointers to the object: pStdID which has no ref count
+ // (for the aggregation case this is necessary since it is an external
+ // interface); pUnkID which is the internal unknown and has the only ref
+ // count.
+
+ IStdIdentity *pStdIDExisting;
+ switch (SetObjectID(oid, pUnkControl, pStdID, &pStdIDExisting))
+ {
+ default:
+ Assert(FALSE);
+ pUnkID->Release();
+ return E_UNEXPECTED;
+
+ case E_OUTOFMEMORY:
+ Assert(pStdIDExisting == NULL);
+ pUnkID->Release();
+ return E_OUTOFMEMORY;
+
+ case CO_E_OBJISREG:
+ // another object got registered since we last looked; use it if
+ // we are not trying to aggregate this one.
+
+ pUnkID->Release();
+ if (pUnkOuter != NULL)
+ {
+ pStdIDExisting->Release();
+ return CO_E_OBJISREG;
+ }
+
+ // make like the success case.
+ pUnkID = pStdIDExisting; // this has the ref count
+ pStdID = pStdIDExisting; // no ref count
+#if DBG == 1
+ pStdIDExisting = NULL;
+#endif
+ // fall through
+
+ case S_OK:
+ Assert(pStdIDExisting == NULL);
+
+ ((CStdIdentity *)pStdID)->AssertValid();
+
+ // NOTE: for the aggregated case, this will QI for IID_IUnknown
+ // which will re-retrive the internal unknown. Similarly,
+ // for IID_IStdIdentity, we will re-retrieve the pStdID. This
+ // method is less code and nearly as fast.
+ hr = pUnkID->QueryInterface(riid, ppv);
+ pUnkID->Release();
+ return hr;
+ }
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CreateIdentityHandler, private
+//
+// Synopsis: Creates a client side identity object (one which is
+// initialized by the first unmarshal).
+//
+// Arguments: [pUnkOuter] -- controlling unknown if aggregated
+// [pMarshal] -- same as above.
+// [riid, ppv] - interface requested and place for pointer to
+// that interface.
+//
+// History: 16-Dec-93 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+INTERNAL CreateIdentityHandler(IUnknown *pUnkOuter, IMarshal *pMarshal,
+ REFIID riid, void **ppv)
+{
+ // BUGBUG: validiate parameters more ???
+
+ // ensure initialized; checked by caller
+ Assert(IsApartmentInitialized());
+
+ *ppv = NULL;
+
+ if (pMarshal == NULL)
+ // we don't handle the NULL case yet (if we ever do, we would
+ // use a static null marshaler).
+ return E_INVALIDARG;
+
+ if (pUnkOuter != NULL && !IsEqualGUID(riid, IID_IUnknown))
+ return E_UNEXPECTED;
+
+#if DBG == 1
+ if (pUnkOuter != NULL)
+ {
+ // addref/release pUnkOuter; shouldn't go away (i.e.,
+ // should be other ref to it).
+ pUnkOuter->AddRef();
+ Verify(pUnkOuter->Release() != 0);
+
+ // verify that pUnkOuter is in fact the controlling unknown
+ IUnknown *pUnkT;
+ Verify(pUnkOuter->QueryInterface(IID_IUnknown,(void**)&pUnkT)==NOERROR);
+ Assert(pUnkOuter == pUnkT);
+ Verify(pUnkT->Release() != 0);
+ }
+
+ if (pMarshal != PSTDMARSHAL)
+ {
+ AssertSz(FALSE, "pMarshal != PSTDMARSHAL case not tested");
+
+ // addref/release pMarshal; shouldn't go away (i.e.,
+ // should be other ref to it).
+ pMarshal->AddRef();
+ Verify(pMarshal->Release() != 0);
+ }
+#endif
+
+ // create object with no identity; will get on first unmarshal
+ IStdIdentity *pStdID;
+ IUnknown *pUnkID;
+ pStdID = new CStdIdentity(STDID_CLIENT, pUnkOuter, NULL, OID_NULL,
+ CLSID_NULL, pMarshal, &pUnkID);
+ if (pStdID == NULL)
+ return E_OUTOFMEMORY;
+
+ ((CStdIdentity *)pStdID)->AssertValid();
+
+ // NOTE: for the aggregated case, this will QI for IID_IUnknown
+ // which will re-retrive the internal unknown. Similarly,
+ // for IID_IStdIdentity, we will re-retrieve the pStdID. This
+ // method is less code and nearly as fast.
+ HRESULT hr = pUnkID->QueryInterface(riid, ppv);
+ pUnkID->Release();
+
+ CALLHOOKOBJECTCREATE(hr,CLSID_NULL,riid,(IUnknown **)ppv);
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: ScmCreateObjectInstance, private
+//
+// Synopsis: Calls the SCM to get a marshaled interfacer pointer to
+// a new instance of the clsid specified.
+//
+// Arguments: [rclsid] -- Clsid of the server
+// [dwContext] -- the context in class object should be
+// located (LOCAL, REMOTE).
+// [pv] -- extra info for context; LATER: machine name, etc.
+// [ppIFD] -- the returned interface data
+//
+// Returns: S_OK
+//
+// History: 06-Jan-94 CraigWi Created.
+//
+//--------------------------------------------------------------------
+
+INTERNAL ScmCreateObjectInstance(
+ REFCLSID rclsid,
+ DWORD dwContext,
+ void * pv,
+ InterfaceData **ppIFD)
+{
+ // Dll ignored here since we are just doing this to get
+ // the remote handler.
+ WCHAR *pwszDllPath = NULL;
+ DWORD dwDllType = FreeThreading ? FREE_THREADED : APT_THREADED;
+
+ *ppIFD = NULL; // this call requires this
+
+#ifdef DCOM
+ HRESULT hrinterface;
+ HRESULT hr = gResolver.CreateInstance( NULL, rclsid, dwContext, 1,
+ (IID *)&IID_IUnknown, (MInterfacePointer **)ppIFD, &hrinterface,
+ &dwDllType, &pwszDllPath, NULL, NULL, NULL );
+#else
+ // The first three NULLs (pwszFrom, pstgFrom, pwszNew) trigger a
+ // simple creation.
+ HRESULT hr = gResolver.CreateObject(rclsid, dwContext, 0,
+ NULL, NULL, NULL, ppIFD, &dwDllType, &pwszDllPath, NULL);
+#endif
+
+ if (pwszDllPath != NULL)
+ {
+ MIDL_user_free(pwszDllPath);
+ }
+
+ return hr;
+}
diff --git a/private/ole32/com/remote/threads.cxx b/private/ole32/com/remote/threads.cxx
new file mode 100644
index 000000000..90a525d62
--- /dev/null
+++ b/private/ole32/com/remote/threads.cxx
@@ -0,0 +1,335 @@
+//+-------------------------------------------------------------------
+//
+// File: threads.cxx
+//
+// Contents: Rpc thread cache
+//
+// Classes: CRpcThread - single thread
+// CRpcThreadCache - cache of threads
+//
+// Notes: This code represents the cache of Rpc threads used to
+// make outgoing calls in the SINGLETHREADED object Rpc
+// model.
+//
+// History: Rickhi Created
+// 07-31-95 Rickhi Fix event handle leak
+//
+//+-------------------------------------------------------------------
+#include <ole2int.h>
+#include <olerem.h>
+#include <chancont.hxx> // ThreadDispatch
+#include <threads.hxx>
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThreadCache::RpcWorkerThreadEntry
+//
+// Purpose: Entry point for an Rpc worker thread.
+//
+// Returns: nothing, it never returns.
+//
+// Callers: Called ONLY by a worker thread.
+//
+//+-------------------------------------------------------------------
+DWORD _stdcall CRpcThreadCache::RpcWorkerThreadEntry(void *param)
+{
+ // First thing we need to do is LoadLibrary ourselves in order to
+ // prevent our code from going away while this worker thread exists.
+ // The library will be freed when this thread exits.
+
+ HINSTANCE hInst = LoadLibrary(L"OLE32.DLL");
+
+
+ // construct a thread object on the stack, and call the main worker
+ // loop. Do this in nested scope so the dtor is called before ExitThread.
+
+ {
+ CRpcThread Thrd(param);
+ Thrd.WorkerLoop();
+ }
+
+
+ // Simultaneously free our Dll and exit our thread. This allows us to
+ // keep our Dll around incase a remote call was cancelled and the
+ // worker thread is still blocked on the call, and allows us to cleanup
+ // properly when all threads are done with the code.
+
+ FreeLibraryAndExitThread(hInst, 0);
+
+ // compiler wants a return value
+ return 0;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThread::CRpcThread
+//
+// Purpose: Constructor for a thread object.
+//
+// Notes: Allocates a wakeup event.
+//
+// Callers: Called ONLY by a worker thread.
+//
+//+-------------------------------------------------------------------
+CRpcThread::CRpcThread(void *param) :
+ _param(param),
+ _pNext(NULL),
+ _fDone(FALSE)
+{
+ // create the Wakeup event. Do NOT use the event cache, as there are
+ // some exit paths that leave this event in the signalled state!
+
+#ifdef _CHICAGO_ // Chicago ANSI optimization
+ _hWakeup = CreateEventA(NULL, FALSE, FALSE, NULL);
+#else //_CHICAGO_
+ _hWakeup = CreateEvent(NULL, FALSE, FALSE, NULL);
+#endif //_CHICAGO_
+
+ CairoleDebugOut((DEB_CHANNEL,
+ "CRpcThread::CRpcThread pThrd:%x _hWakeup:%x\n", this, _hWakeup));
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThread::~CRpcThread
+//
+// Purpose: Destructor for an Rpc thread object.
+//
+// Notes: When threads are exiting, they place the CRpcThread
+// object on the delete list. The main thread then later
+// pulls it from the delete list and calls this destructor.
+//
+// Callers: Called ONLY by a worker thread.
+//
+//+-------------------------------------------------------------------
+CRpcThread::~CRpcThread()
+{
+ // close the event handle. Do NOT use the event cache, since not all
+ // exit paths leave this event in the non-signalled state. Also, do
+ // not close NULL handle.
+
+ if (_hWakeup)
+ {
+ CloseHandle(_hWakeup);
+ }
+
+ CairoleDebugOut((DEB_CHANNEL,
+ "CRpcThread::~CRpcThread pThrd:%x _hWakeup:%x\n", this, _hWakeup));
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: CRpcThread::WorkerLoop
+//
+// Purpose: Entry point for a new Rpc call thread.
+//
+// Notes: This dispatches a call to the function ThreadDispatch. That
+// code signals an event that the COM thread is waiting on, then
+// returns to us. We put the thread on the free list, and wait
+// for more work to do.
+//
+// When there is no more work after some timeout period, we
+// pull it from the free list and exit.
+//
+// Callers: Called ONLY by worker thread.
+//
+//+-------------------------------------------------------------------
+void CRpcThread::WorkerLoop()
+{
+ // Main worker loop where we do some work then wait for more.
+ // When the thread has been inactive for some period of time
+ // it will exit the loop.
+
+ while (!_fDone)
+ {
+ // Dispatch the call.
+ CChannelControl::ThreadDispatch((STHREADCALLINFO **)&_param, TRUE);
+
+ if (!_hWakeup)
+ {
+ // we failed to create an event in the ctor so we cant
+ // get put on the freelist to be re-awoken later with more
+ // work. Just exit.
+ break;
+ }
+
+ // put the thread object on the free list
+ RpcThreadCache.AddToFreeList(this);
+
+ // Wait for more work or for a timeout.
+ while (WaitForSingleObjectEx(_hWakeup, THREAD_INACTIVE_TIMEOUT, 0)
+ == WAIT_TIMEOUT)
+ {
+ // try to remove ourselves from the queue of free threads.
+ // if _fDone is still FALSE, it means someone is about to
+ // give us more work to do (so go wait for that to happen).
+
+ RpcThreadCache.RemoveFromFreeList(this);
+
+ if (_fDone)
+ {
+ // OK to exit and let this thread die.
+ break;
+ }
+ }
+ }
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThreadCache::Dispatch
+//
+// Purpose: Finds the first free thread, and dispatches the request
+// to that thread, or creates a new thread if none are
+// available.
+//
+// Returns: S_OK if dispatched OK
+// Win32 error if it cant create a thread.
+//
+// Callers: Called ONLY by the main thread.
+//
+//+-------------------------------------------------------------------
+HRESULT CRpcThreadCache::Dispatch(void *param)
+{
+ HRESULT hr = S_OK;
+
+ _mxs.Request();
+
+ // grab the first thread from the list
+ CRpcThread *pThrd = _pFreeList;
+
+ if (pThrd)
+ {
+ // update the free list pointer
+ _pFreeList = pThrd->GetNext();
+ _mxs.Release();
+
+ // dispatch the call
+ pThrd->Dispatch(param);
+ }
+ else
+ {
+ _mxs.Release();
+
+ // no free threads, spin up a new one and dispatch directly to it.
+ DWORD dwThrdId;
+ HANDLE hThrd = CreateThread(NULL, 0,
+ RpcWorkerThreadEntry,
+ param, 0,
+ &dwThrdId);
+
+ if (hThrd)
+ {
+ // close the thread handle since we dont need it for anything.
+ CloseHandle(hThrd);
+ }
+ else
+ {
+ CairoleDebugOut((DEB_ERROR,"CreatThread failed:%x\n", GetLastError()));
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThreadCache::RemoveFromFreeList
+//
+// Purpose: Tries to pull a thread from the free list.
+//
+// Returns: pThrd->_fDone TRUE if it was successfull and thread can exit.
+// pThrd->_fDone FALSE otherwise.
+//
+// Callers: Called ONLY by a worker thread.
+//
+//+-------------------------------------------------------------------
+void CRpcThreadCache::RemoveFromFreeList(CRpcThread *pThrd)
+{
+ CairoleDebugOut((DEB_CHANNEL,
+ "CRpcThreadCache::RemoveFromFreeList pThrd:%x\n", pThrd));
+
+ COleStaticLock lck(_mxs);
+
+ // pull pThrd from the free list. if it is not on the free list
+ // then either it has just been dispatched OR ClearFreeList has
+ // just removed it, set _fDone to TRUE, and kicked the wakeup event.
+
+ CRpcThread *pPrev = NULL;
+ CRpcThread *pCurr = _pFreeList;
+
+ while (pCurr && pCurr != pThrd)
+ {
+ pPrev = pCurr;
+ pCurr = pCurr->GetNext();
+ }
+
+ if (pCurr == pThrd)
+ {
+ // remove it from the free list.
+ if (pPrev)
+ pPrev->SetNext(pThrd->GetNext());
+ else
+ _pFreeList = pThrd->GetNext();
+
+ // tell the thread to wakeup and exit
+ pThrd->WakeAndExit();
+ }
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThreadCache::ClearFreeList
+//
+// Purpose: Cleans up all threads on the free list.
+//
+// Notes: For any threads still on the free list, it pulls them
+// off the freelist, sets their _fDone flag to TRUE, and
+// kicks their event to wake them up. When the threads
+// wakeup, they will exit.
+//
+// We do not free active threads. The only way for a thread
+// to still be active at this time is if it was making an Rpc
+// call and was cancelled by the message filter and the thread has
+// still not returned to us. We cant do much about that until
+// Rpc supports cancel for all protocols. If the thread ever
+// does return to us, it will eventually idle-out and delete
+// itself. This is safe because the threads LoadLibrary OLE32.
+//
+// Callers: Called ONLY by the last COM thread during
+// ProcessUninitialize.
+//
+//+-------------------------------------------------------------------
+void CRpcThreadCache::ClearFreeList(void)
+{
+ CairoleDebugOut((DEB_CHANNEL, "CRpcThreadCache::ClearFreeList\n"));
+
+ {
+ COleStaticLock lck(_mxs);
+
+ CRpcThread *pThrd = _pFreeList;
+ while (pThrd)
+ {
+ // use temp variable incase thread exits before we call GetNext
+ CRpcThread *pThrdNext = pThrd->GetNext();
+ pThrd->WakeAndExit();
+ pThrd = pThrdNext;
+ }
+
+ _pFreeList = NULL;
+
+ // the lock goes out of scope at this point. we dont want to hold
+ // it while we sleep.
+ }
+
+ // yield to let the other threads run if necessary.
+ Sleep(0);
+}
diff --git a/private/ole32/com/remote/threads.hxx b/private/ole32/com/remote/threads.hxx
new file mode 100644
index 000000000..f6fc15386
--- /dev/null
+++ b/private/ole32/com/remote/threads.hxx
@@ -0,0 +1,190 @@
+//+-------------------------------------------------------------------
+//
+// File: threads.hxx
+//
+// Contents: Rpc thread cache
+//
+// Classes: CRpcThread - single thread
+// CRpcThreadCache - cache of threads
+//
+// Notes: This code represents the cache of Rpc threads used to
+// make outgoing calls in the APARTMENT object Rpc
+// model.
+//
+// History: Rickhi Created
+// 07-31-95 Rickhi Fix event handle leak
+//
+//+-------------------------------------------------------------------
+#ifndef __THREADS_HXX__
+#define __THREADS_HXX__
+
+#include <olesem.hxx>
+
+
+// inactive thread timeout. this is how long a thread will sit idle
+// in the thread cache before deleting itself.
+
+#define THREAD_INACTIVE_TIMEOUT 30000 // in milliseconds
+
+
+//+-------------------------------------------------------------------
+//
+// Class: CRpcThread
+//
+// Purpose: Represents one thread in the cache of Rpc callout
+// threads.
+//
+// Notes: In order to make Rpc calls in the OLE Single-Threaded
+// model, we must leave the main thread and perform the
+// blocking Rpc call on a worker thread. This object
+// represents such a worker thread.
+//
+//+-------------------------------------------------------------------
+class CRpcThread
+{
+public:
+ CRpcThread(void *param);
+ ~CRpcThread();
+
+ // dispatch methods
+ void Dispatch(void *param);
+ void WorkerLoop();
+ CRpcThread * GetNext(void) { return _pNext; }
+ void SetNext(CRpcThread *pNext) { _pNext = pNext; }
+
+ // cleanup methods
+ void WakeAndExit();
+
+private:
+
+ HANDLE _hWakeup; // thread wakeup event
+ BOOL _fDone; // completion flag
+
+ void * _param; // parameter packet
+ CRpcThread * _pNext; // next thread in free list
+};
+
+
+//+-------------------------------------------------------------------
+//
+// Class: CRpcThreadCache
+//
+// Purpose: Holds a cache of Rpc threads. It finds the first
+// free CRpcThread or creates a new one and dispatches
+// the call to it.
+//
+// Notes: the free list is kept in a most recently used order
+// so that uneeded threads can time out and go away.
+//
+//+-------------------------------------------------------------------
+class CRpcThreadCache
+{
+public:
+ CRpcThreadCache(void) { _pFreeList = NULL; }
+ // no dtor since nothing to do
+
+ // dispatch methods
+ HRESULT Dispatch(void *param);
+ void AddToFreeList(CRpcThread *pThrd);
+
+ // cleanup methods
+ void RemoveFromFreeList(CRpcThread *pThrd);
+ void ClearFreeList(void);
+
+private:
+
+ static DWORD _stdcall RpcWorkerThreadEntry(void *param);
+
+ CRpcThread * _pFreeList; // list of free threads
+ COleStaticMutexSem _mxs; // for list manipulation
+};
+
+
+// Rpc SendReceive thread pool. This must be static to handle Rpc threads
+// that block and dont return until after CoUninitialize has been called.
+
+extern CRpcThreadCache RpcThreadCache;
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThread::Dispatch
+//
+// Purpose: wakes up a thread blocked in WorkerLoop.
+//
+// Notes: folks who want to execute code on another thread
+// call this method. It fills in the parameter packet
+// and wakes up the sleeping thread.
+//
+// Callers: Called ONLY by the COM thread.
+//
+//+-------------------------------------------------------------------
+inline void CRpcThread::Dispatch(void *param)
+{
+ CairoleDebugOut((DEB_CHANNEL,
+ "Dispatch pThrd:%x param:%x\n", this, param));
+
+ // set the call info and the completion event
+ _param = param;
+
+ // signal the Rpc thread to wakeup
+ SetEvent(_hWakeup);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThread::WakeAndExit
+//
+// Purpose: Tells the thread object to free itself
+//
+// Note: This is called by CRpcThreadCache::RemoveFromFreeList
+// when we want to free this thread, eg at ProcessUninitialize.
+//
+// Callers: Called by the COM thread OR worker thread.
+//
+//+-------------------------------------------------------------------
+inline void CRpcThread::WakeAndExit()
+{
+ // _fDone should only be set inside this function and in the
+ // constructor. _fDone must only ever transition from FALSE
+ // to TRUE and that must only happen once in the life of this
+ // object.
+
+ Win4Assert(_fDone == FALSE);
+ _fDone = TRUE;
+
+ CairoleDebugOut((DEB_CHANNEL,
+ "CRpcThreadCache:WakeAndExit pThrd:%x _hWakeup:%x\n", this, _hWakeup));
+
+ SetEvent(_hWakeup);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CRpcThreadCache::AddToFreeLlist
+//
+// Purpose: puts a thread back onto the free list after the
+// thread has completed its job.
+//
+// Callers: Called ONLY by worker thread.
+//
+//+-------------------------------------------------------------------
+inline void CRpcThreadCache::AddToFreeList(CRpcThread *pThrd)
+{
+ COleStaticLock lck(_mxs);
+
+ // place this thread on the front of the free list. it is
+ // important that we add and remove only from the front of
+ // the list so that unused threads will eventually time out
+ // and release themselves...that is, it keeps our thread pool
+ // as small as possible.
+
+ pThrd->SetNext(_pFreeList);
+ _pFreeList = pThrd;
+}
+
+
+#endif // __THREADS_HXX__
diff --git a/private/ole32/com/rot/access.cxx b/private/ole32/com/rot/access.cxx
new file mode 100644
index 000000000..1ea28da50
--- /dev/null
+++ b/private/ole32/com/rot/access.cxx
@@ -0,0 +1,293 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: access.cxx
+//
+// Contents: Methods used for building a security descriptor.
+//
+// History: 02-May-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntseapi.h>
+}
+
+#include <rpc.h>
+#include <windows.h>
+#include <except.hxx>
+#include <ole2.h>
+
+#include <memapi.hxx>
+#include <access.hxx>
+
+extern PSID psidMySid;
+
+//+-------------------------------------------------------------------------
+//
+// Member: CAccessInfo::~CAccessInfo
+//
+// Synopsis: Clean up buffers allocated for building the security
+// descriptor
+//
+// History: 08-Jun-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+CAccessInfo::~CAccessInfo (
+ void
+ )
+{
+ if (_pAbsoluteSdBuffer != NULL)
+ {
+ PrivMemFree (_pAbsoluteSdBuffer);
+ }
+
+ if (_pDace != NULL && _pDace != (PACCESS_ALLOWED_ACE)&_aDace[0])
+ {
+ PrivMemFree (_pDace);
+ }
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CAccessInfo::IdentifyAccess
+//
+// Synopsis: Build a security descriptor that identifies who has what
+// access
+//
+// Arguments: [fScmIsOwner] - whether SCM is the owner
+// [AppAccessMask] - access mask for the OLE application
+// [ScmAccessMask] - access mask for the SCM
+//
+// Returns: NULL - an error has occurred
+// ~NULL - pointer to the resulting security descriptor
+//
+// History: 08-Jun-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+PSECURITY_DESCRIPTOR
+CAccessInfo::IdentifyAccess (
+ BOOL fScmIsOwner,
+ ACCESS_MASK AppAccessMask,
+ ACCESS_MASK ScmAccessMask
+ )
+{
+ NTSTATUS NtStatus;
+
+ //
+ // Pointer to memory dynamically allocated by this routine to hold
+ // the absolute security descriptor, the DACL, the SACL, and all the ACEs.
+ //
+
+ //
+ // A security descriptor is of opaque data type but
+ // SECURITY_DESCRIPTOR_MIN_LENGTH is the right size.
+ //
+
+ DWORD dwAbsoluteSdLength = SECURITY_DESCRIPTOR_MIN_LENGTH;
+ PACL lpDacl = NULL; // Pointer to DACL portion of sid buffer
+ ULONG dwSize;
+
+ ULONG dwAppSid;
+ ULONG dwScmSid;
+
+ //
+ // Compute the total size of the DACL and SACL ACEs and the maximum
+ // size of any ACE.
+ //
+
+ dwAppSid = RtlLengthSid (_pAppSid);
+ dwScmSid = RtlLengthSid (psidMySid);
+
+ dwSize = sizeof(ACL) +
+ dwAppSid +
+ dwScmSid +
+ 2 * sizeof(ACCESS_ALLOWED_ACE);
+
+ dwAbsoluteSdLength += dwSize;
+
+ _pAbsoluteSdBuffer = (PSECURITY_DESCRIPTOR) PrivMemAlloc (
+ dwAbsoluteSdLength
+ );
+
+ if (_pAbsoluteSdBuffer == NULL)
+ {
+ return NULL;
+ }
+
+ //
+ // Initialize the Dacl and Sacl
+ //
+
+ lpDacl = (PACL)((PCHAR)_pAbsoluteSdBuffer + SECURITY_DESCRIPTOR_MIN_LENGTH);
+
+ NtStatus = RtlCreateAcl (lpDacl, dwSize, ACL_REVISION);
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ return NULL;
+ }
+
+ //
+ // Get a buffer big enough for the biggest ACE.
+ //
+
+ dwSize = max(dwAppSid, dwScmSid) + sizeof(ACCESS_ALLOWED_ACE);
+
+ if (dwSize <= DACE_BUFFER_LENGTH)
+ {
+ _pDace = (PACCESS_ALLOWED_ACE)&_aDace[0];
+ }
+ else
+ {
+ _pDace = (PACCESS_ALLOWED_ACE) PrivMemAlloc (dwSize);
+
+ if (_pDace == NULL)
+ {
+ return NULL;
+ }
+ }
+
+ //
+ // Initialize each ACE, and append it onto the end of the DACL.
+ //
+
+ _pDace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
+ _pDace->Header.AceSize = (USHORT)(dwAppSid + sizeof(ACCESS_ALLOWED_ACE));
+ _pDace->Header.AceFlags = 0;
+ _pDace->Mask = AppAccessMask;
+
+ NtStatus = RtlCopySid (
+ dwAppSid, // ULONG DestinationSidLength
+ &(_pDace->SidStart), // PSID DestinationSid
+ _pAppSid // PSID SourceSid
+ );
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ return NULL;
+ }
+
+ NtStatus = RtlAddAce(
+ lpDacl, // PACL Acl
+ ACL_REVISION, // ULONG AceRevision
+ MAXULONG, // ULONG StartingAceIndex
+ _pDace, // PVOID AceList
+ dwAppSid + sizeof(ACCESS_ALLOWED_ACE) // ULONG AceListLength
+ );
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ return NULL;
+ }
+
+ _pDace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
+ _pDace->Header.AceSize = (USHORT)(dwScmSid + sizeof(ACCESS_ALLOWED_ACE));
+ _pDace->Header.AceFlags = 0;
+ _pDace->Mask = ScmAccessMask;
+
+ NtStatus = RtlCopySid (
+ dwScmSid, // ULONG DestinationSidLength
+ &(_pDace->SidStart), // PSID DestinationSid
+ psidMySid // PSID SourceSid
+ );
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ return NULL;
+ }
+
+ NtStatus = RtlAddAce(
+ lpDacl, // PACL Acl
+ ACL_REVISION, // ULONG AceRevision
+ MAXULONG, // ULONG StartingAceIndex
+ _pDace, // PVOID AceList
+ dwScmSid + sizeof(ACCESS_ALLOWED_ACE) // ULONG AceListLength
+ );
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ return NULL;
+ }
+
+ //
+ // Create the security descriptor with absolute pointers to SIDs
+ // and ACLs.
+ //
+ // Owner = Sid of SCM
+ // Group = Sid of SCM
+ // Dacl = lpDacl
+ // Sacl = nothing
+ //
+
+ NtStatus = RtlCreateSecurityDescriptor (
+ _pAbsoluteSdBuffer, // PSECURITY_DESCRIPTOR SecurityDescriptor
+ SECURITY_DESCRIPTOR_REVISION // ULONG Revision
+ );
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ return NULL;
+ }
+
+ if (fScmIsOwner)
+ {
+ NtStatus = RtlSetOwnerSecurityDescriptor (
+ _pAbsoluteSdBuffer, // PSECURITY_DESCRIPTOR SecurityDescriptor
+ psidMySid, // PSID Owner
+ FALSE // BOOLEAN OwnerDefaulted
+ );
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ return NULL;
+ }
+
+ NtStatus = RtlSetGroupSecurityDescriptor (
+ _pAbsoluteSdBuffer, // PSECURITY_DESCRIPTOR SecurityDescriptor
+ psidMySid, // PSID Group
+ FALSE // BOOLEAN GroupDefaulted
+ );
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ return NULL;
+ }
+ }
+
+ NtStatus = RtlSetDaclSecurityDescriptor (
+ _pAbsoluteSdBuffer, // PSECURITY_DESCRIPTOR SecurityDescriptor
+ TRUE, // BOOLEAN DaclPresent
+ lpDacl, // PACL Dacl
+ FALSE // BOOLEAN DaclDefaulted
+ );
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ return NULL;
+ }
+
+ NtStatus = RtlSetSaclSecurityDescriptor (
+ _pAbsoluteSdBuffer, // PSECURITY_DESCRIPTOR SecurityDescriptor
+ FALSE, // BOOLEAN SaclPresent
+ NULL, // PACL Sacl
+ FALSE // BOOLEAN SaclDefaulted
+ );
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ return NULL;
+ }
+
+ return _pAbsoluteSdBuffer;
+}
+
+
diff --git a/private/ole32/com/rot/access.hxx b/private/ole32/com/rot/access.hxx
new file mode 100644
index 000000000..07c2299b3
--- /dev/null
+++ b/private/ole32/com/rot/access.hxx
@@ -0,0 +1,77 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: access.hxx
+//
+// Contents: Class used for building a security descriptor.
+//
+// Classes: CAccessInfo
+//
+// History: 08-Jun-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+#ifndef __ACCESS_HXX__
+#define __ACCESS_HXX__
+
+#define DACE_BUFFER_LENGTH (100 + sizeof(ACCESS_ALLOWED_ACE))
+
+//+-------------------------------------------------------------------------
+//
+// Class: CAccessInfo
+//
+// Purpose: Handle building a security descriptor
+//
+// History: 02-May-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+class CAccessInfo
+{
+public:
+
+ CAccessInfo (
+ PSID pAppSid
+ );
+
+ ~CAccessInfo (void);
+
+ PSECURITY_DESCRIPTOR
+ IdentifyAccess (
+ BOOL fScmIsOwner,
+ ACCESS_MASK AppAccessMask,
+ ACCESS_MASK ScmAccessMask
+ );
+
+private:
+
+ PSID _pAppSid;
+ PSECURITY_DESCRIPTOR _pAbsoluteSdBuffer;
+ PACCESS_ALLOWED_ACE _pDace;
+ BYTE _aDace[DACE_BUFFER_LENGTH];
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CAccessInfo::CAccessInfo
+//
+// Synopsis: Initialize _pAppSid with the sid passed in and initialize
+// other pointer members to NULL.
+//
+// History: 08-Jun-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+inline
+CAccessInfo::CAccessInfo (
+ PSID pAppSid
+ ) :
+ _pAppSid(pAppSid),
+ _pAbsoluteSdBuffer(NULL),
+ _pDace(NULL)
+{
+}
+
+
+#endif // __CALLINFO_HXX__
diff --git a/private/ole32/com/rot/caller.cxx b/private/ole32/com/rot/caller.cxx
new file mode 100644
index 000000000..de86df691
--- /dev/null
+++ b/private/ole32/com/rot/caller.cxx
@@ -0,0 +1,187 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: callinfo.cxx
+//
+// Contents: Methods used for identifying the RPC caller.
+//
+// History: 02-May-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+#if !defined(_CHICAGO_)
+extern "C" {
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <stdio.h>
+}
+#endif
+
+#include <ole2int.h>
+
+#include <caller.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallerInfo::~CCallerInfo
+//
+// Synopsis: Clean up token handle and RPC impersonation.
+//
+// History: 02-May-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+CCallerInfo::~CCallerInfo (
+ void
+ )
+{
+ NTSTATUS NtStatus;
+
+ if (_hThreadToken != NULL)
+ {
+ NtStatus = NtClose (_hThreadToken);
+
+ Win4Assert (NT_SUCCESS(NtStatus) && "CCallerInfo::~CCallerInfo");
+ }
+
+ if (_fImpersonate)
+ {
+ NtStatus = RpcRevertToSelf ();
+
+ Win4Assert ((NtStatus == RPC_S_OK) && "CCallerInfo::~CCallerInfo");
+ }
+
+ if (_pTokenUser)
+ {
+ PrivMemFree (_pTokenUser);
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallerInfo::IdentifyCaller
+//
+// Synopsis: Obtain TOKEN_USER information of the RPC caller
+//
+// Arguments: [fSameAsSelf] - whether the caller is in the same process
+// as the callee
+//
+// Returns: NULL - an error has occurred
+// ~NULL - pointer to TOKEN_USER representing the RPC caller
+//
+// History: 02-May-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+PTOKEN_USER
+CCallerInfo::IdentifyCaller (
+ BOOL fSameAsSelf
+ )
+{
+ ULONG ulLength;
+ NTSTATUS NtStatus;
+
+ if (!fSameAsSelf)
+ {
+ NtStatus = RpcImpersonateClient (NULL);
+ if (NtStatus != RPC_S_OK)
+ {
+ return NULL;
+ }
+ _fImpersonate = TRUE;
+
+ NtStatus = NtOpenThreadToken (
+ NtCurrentThread (), // IN HANDLE ThreadHandle
+ TOKEN_QUERY, // IN ACCESS_MASK DesiredAccess
+ TRUE, // IN BOOLEAN OpenAsSelf
+ &_hThreadToken // OUT PHANDLE TokenHandle
+ );
+ }
+ else
+ {
+ NtStatus = NtOpenProcessToken (
+ NtCurrentProcess (), // IN HANDLE ProcessHandle
+ TOKEN_QUERY, // IN ACCESS_MASK DesiredAccess
+ &_hThreadToken // OUT PHANDLE TokenHandle
+ );
+ }
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ return NULL;
+ }
+
+ //
+ // TOKEN_QUERY access is needed to retrieve a TOKEN_USER data structure.
+ //
+
+ NtStatus = NtQueryInformationToken (
+ _hThreadToken, // IN HANDLE TokenHandle,
+ TokenUser, // IN TOKEN_INFORMATION_CLASS
+ // TokenInformationClass
+ (PVOID) _aTokenUser, // OUT PVOID TokenInformation
+ TOKEN_USER_BUFFER_LENGTH,
+ // IN ULONG TokenInformationLength
+ &ulLength // OUT PULONG ReturnLength
+ );
+
+ if (NtStatus == STATUS_BUFFER_TOO_SMALL)
+ {
+ _pTokenUser = (PTOKEN_USER) PrivMemAlloc (ulLength);
+
+ if (_pTokenUser == NULL)
+ {
+ return NULL;
+ }
+
+ //
+ // TOKEN_USER data structure
+ //
+ // SID_AND_ATTRIBUTES User
+ //
+
+ NtStatus = NtQueryInformationToken (
+ _hThreadToken,
+ TokenUser,
+ (PVOID) _pTokenUser,
+ ulLength,
+ &ulLength
+ );
+ }
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ return NULL;
+ }
+
+ NtStatus = NtClose (_hThreadToken);
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ return NULL;
+ }
+
+ _hThreadToken = NULL;
+
+ if (!fSameAsSelf)
+ {
+ NtStatus = RpcRevertToSelf ();
+
+ if (NtStatus != RPC_S_OK)
+ {
+ return NULL;
+ }
+ _fImpersonate = FALSE;
+ }
+
+ if (_pTokenUser != NULL)
+ {
+ return _pTokenUser;
+ }
+ else
+ {
+ return (PTOKEN_USER)&_aTokenUser[0];
+ }
+}
diff --git a/private/ole32/com/rot/caller.hxx b/private/ole32/com/rot/caller.hxx
new file mode 100644
index 000000000..3b2a07bc4
--- /dev/null
+++ b/private/ole32/com/rot/caller.hxx
@@ -0,0 +1,74 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: callinfo.hxx
+//
+// Contents: Class used for identifying the RPC caller.
+//
+// Classes: CCallerInfo
+//
+// History: 02-May-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+#ifndef __CALLER_HXX__
+#define __CALLER_HXX__
+
+#define TOKEN_USER_BUFFER_LENGTH 100
+
+//+-------------------------------------------------------------------------
+//
+// Class: CCallerInfo
+//
+// Purpose: Handle making sure reverting to self happens and thread
+// token gets closed
+//
+// History: 02-May-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+class CCallerInfo
+{
+public:
+
+ CCallerInfo (void);
+
+ ~CCallerInfo (void);
+
+ PTOKEN_USER
+ IdentifyCaller (
+ BOOL fSameAsSelf
+ );
+
+private:
+
+ BOOLEAN _fImpersonate;
+ HANDLE _hThreadToken;
+ BYTE _aTokenUser[TOKEN_USER_BUFFER_LENGTH];
+ PTOKEN_USER _pTokenUser;
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCallerInfo::CCallerInfo
+//
+// Synopsis: Initialize _fImpersonate to indicate that we are not
+// impersonating the RPC caller and _hThreadToken to
+// indicate that we have not opened the thread token.
+//
+// History: 02-May-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+inline
+CCallerInfo::CCallerInfo (
+ ) :
+ _fImpersonate(FALSE),
+ _hThreadToken(NULL),
+ _pTokenUser(NULL)
+{
+}
+
+
+#endif // __CALLER_HXX__
diff --git a/private/ole32/com/rot/crot.cxx b/private/ole32/com/rot/crot.cxx
new file mode 100644
index 000000000..5cafa9e40
--- /dev/null
+++ b/private/ole32/com/rot/crot.cxx
@@ -0,0 +1,2137 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: rot.cxx
+//
+// Contents: methods for implementation of ROT
+//
+// Functions:
+//
+//
+// History: 11-Nov-92 Ricksa Created
+// 25-Mar-94 brucema #8914 CRunningObjectTable::Register
+// uninited variable
+// 25-Mar-94 #10736 Fixed CRotMonikerEnum::Skip to
+// return S_OK if skipping remainder of
+// enumeration
+// 07-Apr-94 brucema CRunningObjectTable::Register var init
+// 24-Jun-94 BruceMa Validate ROT items when enum'ing
+// 11-Jul-94 BruceMa Marshal moniker enumeration normal
+// 28-Jul-94 BruceMa Memory sift fix
+// 09-Jan-95 BruceMa Single thread ROT creation and enum'ing
+// 30-Jan-95 Ricksa New ROT.
+// 15-May-95 BruceMa Convert DDE ROT requests to UNC-based
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#ifndef DCOM
+#include <epid.hxx>
+#endif
+#include <safeif.hxx>
+#include <rothelp.hxx>
+#include <rotdata.hxx>
+#include "crot.hxx"
+
+
+
+// Semaphore used to protect ROT
+COleStaticMutexSem g_RotSem;
+
+// Running object table object
+extern CRunningObjectTable *pROT = NULL;
+
+
+#define MEM_PUB 0 // memory allocated via CoTaskMemAlloc
+#define MEM_PRIV 1 // memory allocated via CPrivMemAlloc
+
+
+extern INTERNAL CreateCommonDdeWindow(void);
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: GetMonikerCompareBuffer, private
+//
+// Synopsis: Get a buffer appropriate for comparing
+//
+// Arguments: [pmk] - input moniker
+// [pmkeqbuf] - comparison buffer
+// [pfiletime] - time of last change (optional)
+// [pifdMoniker] - output marshaled moniker (optional)
+//
+// Returns: S_OK
+// E_OUTOFMEMORY
+//
+// Algorithm: First reduce the input moniker. Then get the last change
+// time if requested. Then we marshal the reduced moniker if
+// that was requested. Finally, we build the ROT moniker
+// comparison buffer.
+//
+// History: 27-Nov-93 Ricksa Created
+//
+// Notes: This is just a helper that is used to reduce code size.
+//
+//--------------------------------------------------------------------------
+HRESULT GetMonikerCompareBuffer(
+ IMoniker *pmk,
+ CTmpMkEqBuf *ptmpmkeqbuf,
+ FILETIME *pfiletime,
+ InterfaceData **ppifdMoniker)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN GetMonikerCompareBuffer "
+ "( %p , %p, %p , %p )\n", NULL, pmk, ptmpmkeqbuf, pfiletime,
+ ppifdMoniker));
+
+ HRESULT hr;
+
+ BEGIN_BLOCK
+
+ CSafeBindCtx sbctx;
+
+ CSafeMoniker smkReduced;
+
+ hr = CreateBindCtx(0, &sbctx);
+
+ if (hr != NOERROR)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "GetMonikerCompareBuffer CreateBindCtx failed %lX\n", hr));
+ EXIT_BLOCK;
+ }
+
+ // reduce the moniker
+ hr = pmk->Reduce(sbctx, MKRREDUCE_ALL, NULL, &smkReduced);
+
+ if (FAILED(hr))
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "GetMonikerCompareBuffer IMoniker::Reduce failed %lX\n", hr));
+ EXIT_BLOCK;
+ }
+
+ if ((IMoniker *) smkReduced == NULL)
+ {
+ smkReduced.Set(pmk);
+ }
+
+ if (pfiletime != NULL)
+ {
+ // Try to get the time of last change. We ignore the error
+ // because this was the original behavior of OLE2.
+ smkReduced->GetTimeOfLastChange(sbctx, NULL, pfiletime);
+ }
+
+ // Marshal the moniker if so requested
+ if (ppifdMoniker != NULL)
+ {
+ // Stream to put marshaled interface in
+ CXmitRpcStream xrpc;
+
+ hr = CoMarshalInterface(&xrpc, IID_IMoniker, smkReduced,
+ MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_TABLESTRONG);
+
+ if (hr != NOERROR)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "GetMonikerCompareBuffer CoMarshalInterface failed %lX\n",
+ hr));
+ EXIT_BLOCK;
+ }
+
+ xrpc.AssignSerializedInterface(ppifdMoniker);
+ }
+
+ hr = BuildRotData(
+ sbctx,
+ smkReduced,
+ ptmpmkeqbuf->GetBuf(),
+ ptmpmkeqbuf->GetSize(),
+ ptmpmkeqbuf->GetSizeAddr());
+
+ END_BLOCK;
+
+ CairoleDebugOut((DEB_ROT, "%p OUT GetMonikerCompareBuffer "
+ "( %lX ) [ %p ] \n", NULL, hr,
+ (ppifdMoniker != NULL) ? *ppifdMoniker : NULL));
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: ReleaseSCMInterfaceData
+//
+// Synopsis: Release interface data returned by the SCM
+//
+// Arguments: [pifd] - interface data to release
+//
+// Algorithm: Create an RPC stream and then pass that stream to
+// CoReleaseMarshalData to release any AddRefs and then
+// free the memory that the interface data lives in.
+//
+// History: 27-Jan-95 Ricksa Created
+//
+// Notes: This is designed specifically for processing interface
+// data returned by the SCM on Revoke from the ROT.
+//
+//--------------------------------------------------------------------------
+void ReleaseInterfaceData(InterfaceData *pifd, DWORD dwMemType)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN ReleaseInterfaceData "
+ "( %p )\n", NULL, pifd));
+
+ if (pifd != NULL)
+ {
+ // Make our interface into a stream
+ CXmitRpcStream xrpc(pifd);
+
+ // Tell RPC to release it -- error is for debugging purposes only
+ // since if this fails there isn't much we can do about it.
+#if DBG == 1
+ HRESULT hr =
+#endif // DBG
+
+ CoReleaseMarshalData(&xrpc);
+
+#if DBG == 1
+ if (hr != NOERROR)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "ReleaseInterfaceData CoReleaseMarshalData failed: %lx\n", hr));
+ }
+#endif // DBG == 1
+
+#ifdef DCOM
+ if (dwMemType == MEM_PUB)
+ CoTaskMemFree(pifd);
+ else
+ MIDL_user_free(pifd);
+#else
+ MIDL_user_free(pifd);
+#endif // DCOM
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT ReleaseInterfaceData ", NULL));
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CROTItem::~CROTItem
+//
+// Synopsis: Release data connected with the entry
+//
+// Algorithm: Clean up a rot entry by sending a revoke to the SCM for
+// the entry and taking the marshaled interfaces that the
+// SCM returns and releasing the data associated with them.
+//
+// History: 20-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CROTItem::~CROTItem(void)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CROTItem::~CROTItem\n", this));
+
+ // Make sure we are in the correct apt.
+ Win4Assert((_hApt == GetCurrentApartmentId())
+ && "CROTItem::~CROTItem from wrong apartment");
+
+ // This object is going away so we mark it invalid immediately
+ _wItemSig = 0;
+
+ // Place to put returned marshaled interfaces
+ InterfaceData *pifdObject = NULL;
+ InterfaceData *pifdName = NULL;
+
+ HRESULT hr = gResolver.IrotRevoke(&_scmregkey, TRUE, &pifdObject, &pifdName);
+
+ if (SUCCEEDED(hr))
+ {
+ if (!_fDontCallApp)
+ {
+ ReleaseInterfaceData(pifdObject, MEM_PRIV);
+ ReleaseInterfaceData(pifdName, MEM_PRIV);
+ }
+ }
+#if DBG == 1
+ else
+ {
+ CairoleDebugOut((DEB_ROT, "Revoke FAILED: %lx\n", hr));
+ }
+#endif // DBG == 1
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CROTItem::~CROTItem\n", this));
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::Create
+//
+// Synopsis: Create & initialize running object table object
+//
+// Returns: TRUE - ROT created successfully
+// FALSE - an error occurred.
+//
+// Algorithm: Create a new running ROT and check whether the creation
+// was successful.
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CRunningObjectTable::Create(void)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::Create\n", NULL));
+
+ // Need to synchronize ROT creation in a multithreaded environment
+ COleStaticLock lckSem(g_RotSem);
+
+ // The ROT may have been created by now
+ if (pROT == NULL)
+ {
+ // Create running object table
+ pROT = new CRunningObjectTable();
+
+#if DBG == 1
+
+ if (pROT == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR,"Couldn't allocate ROT!\n"));
+ }
+
+#endif // DBG == 1
+
+ // Initialize the array of registrations - FALSE means we couldn't
+ // allocate the memory.
+ if (pROT && !pROT->_afvRotList.SetSize(ROT_DEF_SIZE, ROT_DEF_SIZE))
+ {
+ CairoleDebugOut((DEB_ERROR,"Couldn't allocate ROT reg array!\n"));
+ delete pROT;
+ pROT = NULL;
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::Create"
+ "( %lX )\n", NULL, (pROT != NULL)));
+
+ return pROT != NULL;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::~CRunningObjectTable
+//
+// Synopsis: Free ROT object
+//
+// History: 11-Nov-93 Ricksa Created
+//
+// Notes: This only occurs at process exit.
+//
+//--------------------------------------------------------------------------
+CRunningObjectTable::~CRunningObjectTable(void)
+{
+ CairoleDebugOut((DEB_ROT,
+ "%p _IN CRunningObjectTable::~CRunningObjectTable\n", this));
+
+ // Get the size of the table
+ int cMax = _afvRotList.GetSize();
+
+ // Are there any entries in the table?
+ if (cMax != 0)
+ {
+ CROTItem **pprot = (CROTItem **) _afvRotList.GetAt(0);
+
+ // Clear out all the registrations
+ for (int i = 0; i < cMax; i++)
+ {
+ if (pprot[i] != NULL)
+ {
+ delete pprot[i];
+ }
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT,
+ "%p OUT CRunningObjectTable::~CRunningObjectTable\n", this));
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::QueryInterface
+//
+// Synopsis: Implements QI for the ROT object
+//
+// Arguments: [riid] - requested id
+// [ppvObj] - where to put output object.
+//
+// Returns: S_OK - interface is suppored
+// E_NOINTERFACE - requested interface is not supported
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRunningObjectTable::QueryInterface(
+ REFIID riid,
+ LPVOID FAR* ppvObj)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::QueryInterface "
+ "( %p , %p) \n", this, &riid, ppvObj));
+
+ HRESULT hr = S_OK;
+
+ *ppvObj = NULL;
+
+ if ((IsEqualIID(riid, IID_IRunningObjectTable)) ||
+ (IsEqualIID(riid, IID_IUnknown)))
+ {
+ *ppvObj = this;
+ }
+ else
+ {
+ hr = E_NOINTERFACE;
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::QueryInterface "
+ "( %lX ) [ %p ]\n", this, hr, *ppvObj));
+
+ return hr;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::AddRef
+//
+// Synopsis: Add to reference count
+//
+// Returns: Current reference count
+//
+// History: 11-Nov-93 Ricksa Created
+//
+// Notes: Reference count is ignored with respect to object deletion
+// since this is a system object and does not go away until
+// CoUninitialize is called.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CRunningObjectTable::AddRef()
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::AddRef\n", this));
+ CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::AddRef\n", this));
+
+ // Since this ignored we just return a non-zero indication
+ return 1;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::Release
+//
+// Synopsis: Dec ref count
+//
+// Returns: Current reference count
+//
+// History: 11-Nov-93 Ricksa Created
+//
+// Notes: Reference count is ignored with respect to object deletion
+// since this is a system object and does not go away until
+// CoUninitialize is called.
+//
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CRunningObjectTable::Release()
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::Release\n", this));
+ CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::Release\n", this));
+
+ // Since this ignored we just return a non-zero indication
+ return 1;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::CleanupApartment
+//
+// Synopsis: Cleans up left-over entries from the ROT when an
+// apartment exits.
+//
+// Arguments: [hApt] - apartment to cleanup
+//
+// Algorithm: Walk through the list local registrations finding each entry
+// that has a matching apartment and remove those entries. We
+// delete them (for WOW making sure we don't call back to the
+// app).
+//
+// History: 24-Jun-94 Rickhi Created
+// 29-Jun-94 AlexT Don't make yielding calls while holding
+// the mutex
+//
+//--------------------------------------------------------------------------
+HRESULT CRunningObjectTable::CleanupApartment(HAPT hApt)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::CleanupApartment"
+ "( %lX )\n", this, hApt));
+
+ // Make sure all threads are locked out during lookup
+ COleStaticLock lckSem(g_RotSem);
+
+ // Find a spot in the array for the object
+ CROTItem **pprotitm = (CROTItem **) _afvRotList.GetAt(0);
+
+ for (int i = 0; i < _afvRotList.GetSize(); i++)
+ {
+ CROTItem *protitm = pprotitm[i];
+
+ if ((protitm != NULL)
+ && (protitm->GetAptId() == hApt))
+ {
+ // Clean up the entry
+ pprotitm[i] = NULL;
+
+ if (IsWOWThread())
+ {
+ // 16-bit OLE didn't clean up stale entries; we remove
+ // them from the ROT but we don't call back to the
+ // application. Who knows what the application might do
+ // if we called them - they already have a missing Revoke.
+ protitm->DontCallApp();
+ }
+
+ delete protitm;
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::CleanupApartment"
+ "( %lX )\n", this, S_OK));
+
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::Register
+//
+// Synopsis: Register an item in the ROT
+//
+// Arguments: [grfFlags] - whether registration keeps object alive
+// [punkObject] - object to register
+// [pmkObjectName] - moniker for object to register
+// [pdwRegister] - id for revoke
+//
+// Algorithm: Validate parameters input. Then create the moniker to register,
+// the comparison buffer and the marshaled moniker to put in the
+// ROT. Then marshal the object to put in the ROT. Create a
+// new local ROT item and reserve a space for it in our local
+// table. Send registration to the SCM and exit.
+//
+// History: 11-Nov-93 Ricksa Created
+// 26-Jul-94 AndyH #20843 - restarting OLE in the shared WOW
+// 27-Jan-94 Ricksa New ROT
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRunningObjectTable::Register(
+ DWORD grfFlags,
+ LPUNKNOWN punkObject,
+ LPMONIKER pmkObjectName,
+ DWORD FAR* pdwRegister)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::Register"
+ "( %lX , %p , %p , %p )\n", this, grfFlags, punkObject, pmkObjectName,
+ pdwRegister));
+
+ COleTls Tls;
+ CROTItem *protitm = NULL;
+ HRESULT hr = S_OK;
+
+ // Place to keep marshaled moniker buffer
+ InterfaceData *pifdMoniker = NULL;
+
+ // Where to put pointer to marshaled object
+ InterfaceData *pifdObject = NULL;
+
+ // Where to put the new ROT registration - set so an invalid
+ // value to tell error exit whether it needs to be cleaned up
+ DWORD idwPutItem = 0xFFFFFFFF;
+
+ BEGIN_BLOCK
+
+ // If we want to service OLE1 clients, we need to create the
+ // common Dde window now if it has not already been done.
+ if( !(Tls->dwFlags & OLETLS_DISABLE_OLE1DDE) )
+ {
+ CreateCommonDdeWindow();
+ }
+
+ // Validate parameters
+ if ((grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE | ROTFLAGS_ALLOWANYCLIENT))
+ || !IsValidInterface(punkObject)
+ || !IsValidInterface(pmkObjectName)
+ || IsBadWritePtr(pdwRegister, sizeof(*pdwRegister)))
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CRunningObjectTable:Register Invalid Paramter\n"));
+
+ hr = E_INVALIDARG;
+
+ EXIT_BLOCK;
+ }
+
+ *pdwRegister = 0;
+
+ // So we can fill in last change time at registration in the SCM
+ FILETIME filetime;
+
+ // Get the moniker comparison buffer
+ CTmpMkEqBuf tmeb;
+
+ hr = GetMonikerCompareBuffer(pmkObjectName, &tmeb, &filetime,
+ &pifdMoniker);
+
+ if (FAILED(hr))
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CRunningObjectTable::Register get mk compare buf failed\n"));
+ EXIT_BLOCK;
+ }
+
+ //
+ // Get the marshaled interface
+ //
+
+ // Stream to put marshaled interface in
+ CXmitRpcStream xrpc;
+
+ // The way we marshal this object depends on the liveness
+ // characteristics specified by the caller of the operation.
+ hr = CoMarshalInterface(&xrpc, IID_IUnknown, punkObject,
+ MSHCTX_NOSHAREDMEM, NULL,
+ grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE
+ ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_TABLEWEAK);
+
+ if (hr != NOERROR)
+ {
+ // Exit if there is an error
+ CairoleDebugOut((DEB_ERROR,
+ "CRunningObjectTable::Register marshal object failed\n"));
+ EXIT_BLOCK;
+ }
+
+ xrpc.AssignSerializedInterface(&pifdObject);
+
+ // Create an entry for the local registration table
+ CROTItem *protitm = new CROTItem();
+
+ if (protitm == NULL)
+ {
+ // Either the allocation failed, or the constructor failed
+ CairoleDebugOut((DEB_ERROR,
+ "CRunningObjectTable::Register create ROT item failed\n"));
+ hr = E_OUTOFMEMORY;
+
+ EXIT_BLOCK;
+ }
+
+ // Temporary holder for registration ID
+ DWORD dwRotRegId;
+
+ // ROT Table entry as opposed to the entry we are creating
+ // which is called protitm.
+ CROTItem **pprotitm;
+
+ // Put it in the table and initalize signiture.
+ {
+ COleStaticLock lckSem(g_RotSem);
+
+ // We lock here so we don't accidently pass out duplicate
+ // signiture. It is important to note that we need to lock
+ // anyway to put the item in the array.
+ _wSigRotItem++;
+
+ protitm->SetSig(_wSigRotItem);
+
+ // Find a spot in the array for the object
+ pprotitm = (CROTItem **) _afvRotList.GetAt(0);
+
+ for (idwPutItem = 0; (int) idwPutItem < _afvRotList.GetSize();
+ idwPutItem++)
+ {
+ if (pprotitm[idwPutItem] == NULL)
+ {
+ break;
+ }
+ }
+
+ // Was the table full?
+ if ((int) idwPutItem < _afvRotList.GetSize())
+ {
+ // No -- use an empty slot.
+ pprotitm[idwPutItem] = protitm;
+ }
+ // Grow the array to fit the next entry.
+ else if (!_afvRotList.InsertAt(idwPutItem, &protitm))
+ {
+ // Couldn't reallocate memory
+ hr = E_OUTOFMEMORY;
+ EXIT_BLOCK;
+ }
+
+ // Build the registration ID
+ dwRotRegId = MakeRegID(_wSigRotItem, idwPutItem);
+ }
+
+#ifndef _CHICAGO_
+ WCHAR wszImageName[MAX_PATH];
+ WCHAR * pwszExeName = 0;
+
+ if ( grfFlags & ROTFLAGS_ALLOWANYCLIENT )
+ {
+ if ( ! GetModuleFileName( NULL, wszImageName, MAX_PATH ) )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ EXIT_BLOCK;
+ }
+
+ pwszExeName = wszImageName + lstrlenW(wszImageName) - 1;
+ while ( (pwszExeName != wszImageName) && (pwszExeName[-1] != L'\\') )
+ pwszExeName--;
+ }
+#endif
+
+ // Notify SCM of the registration
+ //
+ // Note that CoGetCurrentProcess is for supporting the DDE layer
+ // which needs to find objects in the same apartment only.
+ //
+ hr = gResolver.IrotRegister(
+ tmeb.GetMkEqBuf(),
+ pifdObject,
+ pifdMoniker,
+ &filetime,
+ CoGetCurrentProcess(),
+#ifndef _CHICAGO_
+ pwszExeName,
+#endif
+ protitm->GetScmRegKey());
+
+ if (SUCCEEDED(hr))
+ {
+ *pdwRegister = dwRotRegId;
+ }
+
+ END_BLOCK;
+
+ if (SUCCEEDED(hr))
+ {
+ // We pass the marshaled interface buffers off to the SCM so
+ // it actually owns the ref counting (which is why it returns
+ // copies of the buffer on Revoke. However, we still have
+ // copies of the buffer memore here which we have to free or
+ // leak memory.
+#ifdef DCOM
+ CoTaskMemFree(pifdMoniker);
+ CoTaskMemFree(pifdObject);
+#else
+ MIDL_user_free(pifdMoniker);
+ MIDL_user_free(pifdObject);
+#endif
+ }
+ else
+ {
+ // Clean up marshaled interfaces since the call has failed.
+ ReleaseInterfaceData(pifdMoniker, MEM_PUB);
+ ReleaseInterfaceData(pifdObject, MEM_PUB);
+
+ // Error clean up.
+ if (protitm != NULL)
+ {
+ if (idwPutItem != 0xFFFFFFFF)
+ {
+ // Registration failed on the SCM so clean up our local
+ // registration.
+ COleStaticLock lckSem(g_RotSem);
+
+ // We have to use GetAt because the table could have grown
+ CROTItem **pprotitm = (CROTItem **)
+ _afvRotList.GetAt(idwPutItem);
+
+ pprotitm[idwPutItem] = NULL;
+ }
+
+ // Free the item for the ROT.
+ delete protitm;
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::Register"
+ "( %lX ) [ %lX ]\n", this, hr, *pdwRegister));
+
+ return hr;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::Revoke
+//
+// Synopsis: Remove a previously registered item from the table.
+//
+// Arguments: [dwRegister] - registration id
+//
+// Returns: S_OK - item was revoked
+// E_INVALIDARG - dwRegister is invalid
+//
+// Algorithm: Convert local registration to SCM registration. Send revoke
+// to the SCM. Release data associated with SCM ROT entries.
+//
+// History: 11-Nov-93 Ricksa Created
+// 27-Nov-95 Ricksa New ROT
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRunningObjectTable::Revoke(DWORD dwRegister)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::Revoke"
+ "( %lX )\n", this, dwRegister));
+
+ // Default response to bad argument
+ HRESULT hr = E_INVALIDARG;
+
+ // Entry
+ CROTItem *protitm;
+
+ // Convert handle to pointer
+ DWORD idwIndexToEntry;
+ WORD wItemSig;
+ GetSigAndIndex(dwRegister, &wItemSig, &idwIndexToEntry);
+
+ BEGIN_BLOCK
+
+ // Lock from other processes so another simultaneous revoke
+ // will not cause something strange to happen.
+ COleStaticLock lckSem(g_RotSem);
+
+ protitm = GetRotItem(idwIndexToEntry);
+
+ if (protitm != NULL)
+ {
+ // Found an entry so verify its signiture
+ if (protitm->ValidSig(wItemSig))
+ {
+ // Entry is valid so clear it out from the table
+ CROTItem **pprotitm = (CROTItem **)
+ _afvRotList.GetAt(idwIndexToEntry);
+ *pprotitm = NULL;
+ hr = S_OK;
+ }
+ }
+
+ END_BLOCK;
+
+ // We get out of the block and unlock our list and then RPC the
+ // call to the SCM so we don't hold our lock for the duration of
+ // an RPC.
+ if (hr == S_OK)
+ {
+ // Release the ROT item's memory.
+ delete protitm;
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::Revoke"
+ "( %lX )\n", this, hr));
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::IsRunning
+//
+// Synopsis: See if object is running
+//
+// Arguments: [pmkObjectName] - name of item to search for
+//
+// Returns: S_OK - item is running
+// S_FALSE - item is not running
+//
+// Algorithm: Validate input parameters. Then build a moniker comparison
+// buffer. Then ask the ROT if there is a registration for
+// the input moniker.
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRunningObjectTable::IsRunning(LPMONIKER pmkObjectName)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::IsRunning"
+ "( %p )\n", this, pmkObjectName));
+
+ HRESULT hr = E_INVALIDARG;
+
+ // Validate input parameters
+ if (IsValidInterface(pmkObjectName))
+ {
+ // Create a buffer for the comparison
+ CTmpMkEqBuf tmpMkEqBuf;
+
+ // Get comparison buffer
+ if ((hr = GetMonikerCompareBuffer(pmkObjectName, &tmpMkEqBuf, NULL,
+ NULL)) == NOERROR)
+ {
+ // Look into the hint table for the object
+ if (IsInScm(tmpMkEqBuf.GetMkEqBuf()))
+ {
+ // Ask SCM for the object
+ hr = gResolver.IrotIsRunning(tmpMkEqBuf.GetMkEqBuf());
+ }
+ else
+ {
+ // If it isn't in the hint table, there is no reason
+ // to RPC to the ROT.
+ hr = S_FALSE;
+ }
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::IsRunning"
+ "( %lX )\n", this, hr));
+
+ return hr;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::GetObject
+//
+// Synopsis: Get an object from the ROT
+//
+// Arguments: [pmkObjectName] - name of object to search for
+// [ppunkObject] - where to put interface pointer.
+//
+// Returns: S_OK - found and returned object.
+// MK_E_UNAVAILABLE - not found
+//
+// Algorithm: Convert the local registration ID to the SCM registration
+// ID. Then send the request on to the SCM.
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRunningObjectTable::GetObject(
+ LPMONIKER pmkObjectName,
+ LPUNKNOWN *ppunkObject)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::GetObject "
+ "( %p , %p )\n", this, pmkObjectName, ppunkObject));
+
+ // Validate arguments
+ HRESULT hr = E_INVALIDARG;
+
+ // Validate input parameters
+ if (IsValidInterface(pmkObjectName)
+ && !IsBadWritePtr(ppunkObject, sizeof(*ppunkObject)))
+ {
+ *ppunkObject = NULL;
+
+ // Create a buffer for the comparison
+ CTmpMkEqBuf tmpMkEqBuf;
+
+ // Get comparison buffer
+ if ((hr = GetMonikerCompareBuffer(pmkObjectName, &tmpMkEqBuf, NULL,
+ NULL)) == NOERROR)
+ {
+ // Note: Process ID is 0 because we don't care about the
+ // process any registration will do.
+ hr = IGetObject(tmpMkEqBuf.GetMkEqBuf(), ppunkObject, 0);
+ }
+ else
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CRunningObjectTable::GetObject couldn't get comp buf\n"));
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::GetObject"
+ "( %lX ) [ %p ]\n", this, hr, *ppunkObject));
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::IGetObject
+//
+// Synopsis: Internal call to get an object from the ROT
+//
+// Arguments: [pmkObjectName] - name of object to search for
+// [ppunkObject] - where to put interface pointer.
+// [dwThreadID] - thread ID for the object
+//
+// Returns: S_OK - found and returned object.
+// MK_E_UNAVAILABLE - not found
+//
+// Algorithm: Build a moniker comparison buffer. Send request to the
+// SCM. Then unmarshal the result from the SCM. If the
+// unmarshal fails, then notify the SCM that the registration
+// is invalid.
+//
+// History: 30-Jan-95 Ricksa Created
+//
+// Notes: This exists because OLE 1.0 compatibility requires support
+// for determining whether an object is already in the ROT
+// for the given process.
+//
+// Because this is an internal call, there is no parameter
+// validation.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRunningObjectTable::IGetObject(
+ MNKEQBUF *pmkeqbuf,
+ LPUNKNOWN FAR* ppunkObject,
+ DWORD dwThreadID)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::IGetObject"
+ "( %p , %p , %lX )\n", this, pmkeqbuf, ppunkObject, dwThreadID));
+
+ // Validate arguments
+ HRESULT hr = E_INVALIDARG;
+
+ BEGIN_BLOCK
+
+ // Loop because there can be multiple bad entries in the SCM
+ // We loop 5 because we can theoretically loop forever so we
+ // want to give up after we give a good long try that should
+ // most likely work.
+ for (int i = 0; i < 5; i++)
+ {
+ // Look into the hint table for the object
+ if (!IsInScm(pmkeqbuf))
+ {
+ // If it isn't in the hint table, there is no reason
+ // to RPC to the ROT.
+ hr = MK_E_UNAVAILABLE;
+ break;
+ }
+
+ // Ask SCM for the object
+ SCMREGKEY scmregkey;
+ InterfaceData *pifdObject = NULL;
+
+ hr = gResolver.IrotGetObject(dwThreadID, pmkeqbuf,
+ &scmregkey, &pifdObject);
+
+ if (FAILED(hr))
+ {
+ // SCM couldn't find it so we are done.
+ break;
+ }
+
+ if (ppunkObject == NULL)
+ {
+ // This is really an IsRunning from DDE so we can exit
+ // now.
+ hr = NOERROR;
+
+ // free the buffer allocated
+ MIDL_user_free(pifdObject);
+
+ // Exit because we are done.
+ break;
+ }
+
+ // Now we have to unmarshal the object to really get the
+ // object.
+ CXmitRpcStream xrpc(pifdObject);
+
+ hr = CoUnmarshalInterface(&xrpc, IID_IUnknown,
+ (void **) ppunkObject);
+
+ // Whether there was an error or not we need to dump the
+ // memory that RPC allocated on our behalf.
+ MIDL_user_free(pifdObject);
+
+ if (hr == NOERROR)
+ {
+ // We got our object so we are done.
+ break;
+ }
+
+ // Tell ROT that we couldn't unmarshal this object so the entry
+ // is bad. We ignore any errors from the SCM because there isn't
+ // anything we could do about it anyway.
+
+ // Dummy parameters for revoke - we don't care about these and
+ // the SCM will not return them because we are a client and
+ // can't call CoReleaseMarshalData anyway.
+ InterfaceData *pifdDummy1 = NULL;
+ InterfaceData *pifdDummy2 = NULL;
+
+ gResolver.IrotRevoke(&scmregkey, FALSE, &pifdDummy1, &pifdDummy2);
+
+ // We couldn't get the object so we try again to see if there is
+ // another registration that we could use.
+ }
+
+ END_BLOCK;
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::IGetObject"
+ "( %lX ) [ %p ]\n", this, hr,
+ ((ppunkObject == NULL) ? NULL : *ppunkObject)));
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::NoteChangeTime
+//
+// Synopsis: Set the time of last change in the ROT
+//
+// Arguments: [dwRegister] - registration id of object
+// [pfiletime] - file time of change.
+//
+// Returns: S_OK - new time set
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRunningObjectTable::NoteChangeTime(
+ DWORD dwRegister,
+ FILETIME *pfiletime)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::NoteChangeTime"
+ "( %lX , %p )\n", this, dwRegister, pfiletime));
+
+ // Default result to bad argument.
+ HRESULT hr = E_INVALIDARG;
+
+ BEGIN_BLOCK
+
+ // Validate that parameters are valid
+ if (IsBadReadPtr(pfiletime, sizeof(FILETIME)))
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CRunningObjectTable::NoteChangeTime invalid time param\n"));
+ EXIT_BLOCK;
+ }
+
+ SCMREGKEY ScmRegKey;
+
+ {
+ // Lock from other threads so a revoke will not cause something
+ // strange to happen.
+ COleStaticLock lckSem(g_RotSem);
+
+ // Convert handle to pointer
+ DWORD idwIndexToEntry;
+ WORD wItemSig;
+ GetSigAndIndex(dwRegister, &wItemSig, &idwIndexToEntry);
+
+ CROTItem *protitm = GetRotItem(idwIndexToEntry);
+
+ if ((protitm == NULL) || !protitm->ValidSig(wItemSig))
+ {
+ // Entry is valid so clear it out from the table
+ CairoleDebugOut((DEB_ERROR,
+ "CRunningObjectTable::NoteChangeTime invalid reg key\n"));
+ EXIT_BLOCK;
+ }
+
+ ScmRegKey = *(protitm->GetScmRegKey());
+ }
+
+ // Outside the scope of the lock, call the SCM and returns
+ // it's results.
+ hr = gResolver.IrotNoteChangeTime(&ScmRegKey, pfiletime);
+
+ END_BLOCK;
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::NoteChangeTime"
+ "( %lX )\n", this, hr));
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::GetTimeOfLastChange
+//
+// Synopsis: Get time of last change for a given object
+//
+// Arguments: [pmkObjectName] - name of object
+// [pfiletime] - where to put the time of change
+//
+// Returns: S_OK - got time of last change.
+// MK_E_UNAVAILABLE - moniker is not in the table
+//
+// History: 11-Nov-93 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRunningObjectTable::GetTimeOfLastChange(
+ LPMONIKER pmkObjectName,
+ FILETIME *pfiletime)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::GetTimeOfLastChange"
+ "( %p , %p )\n", this, pmkObjectName, pfiletime));
+
+ HRESULT hr = E_INVALIDARG;
+
+ BEGIN_BLOCK
+
+ // Validate input parameters
+ if (!IsValidInterface(pmkObjectName)
+ || IsBadWritePtr(pfiletime, sizeof(pfiletime)))
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CRunningObjectTable::GetTimeOfLastChange invalid params\n"));
+ EXIT_BLOCK;
+ }
+
+ // Create a buffer for the comparison
+ CTmpMkEqBuf tmpMkEqBuf;
+
+ // Get comparison buffer
+ if ((hr = GetMonikerCompareBuffer(pmkObjectName, &tmpMkEqBuf, NULL,
+ NULL)) != NOERROR)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CRunningObjectTable::GetTimeOfLastChange couldn't get comp buf failed\n"));
+
+ EXIT_BLOCK;
+ }
+
+ // Look into the hint table for the object
+ if (!IsInScm(tmpMkEqBuf.GetMkEqBuf()))
+ {
+ // If it isn't in the hint table, there is no reason
+ // to RPC to the ROT.
+ hr = MK_E_UNAVAILABLE;
+ EXIT_BLOCK;
+ }
+
+ // Ask SCM for the object
+ SCMREGKEY scmregkey;
+ InterfaceData *pifdObject = NULL;
+
+ hr = gResolver.IrotGetTimeOfLastChange(tmpMkEqBuf.GetMkEqBuf(), pfiletime);
+
+ END_BLOCK;
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::GetTimeOfLastChange"
+ "( %lX )\n", this, hr));
+
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::EnumRunning
+//
+// Synopsis: Get an enumerator for all objects in the ROT
+//
+// Arguments: [ppenumMoniker] - where to put enumerator interface
+//
+// Returns: S_OK - successfully built enumerator
+// E_OUTOFMEMORY - could not build enumerator
+//
+// Algorithm: Constructor an enumerator object. Then get the list of
+// all running monikers from the SCM. Finally, put that list
+// into the enumerator object.
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRunningObjectTable::EnumRunning(LPENUMMONIKER *ppenumMoniker)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::EnumRunning"
+ "( %p )\n", this, ppenumMoniker));
+
+ HRESULT hr = E_INVALIDARG;
+ CRotMonikerEnum *protenumMoniker = NULL;
+ MkInterfaceList *pMkIFList = NULL;
+
+ BEGIN_BLOCK
+
+ if (IsBadWritePtr(ppenumMoniker, sizeof(*ppenumMoniker)))
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CRunningObjectTable::EnumRunning invalid params\n"));
+ EXIT_BLOCK;
+ }
+
+ protenumMoniker = new CRotMonikerEnum();
+
+ if ((protenumMoniker == NULL) || !protenumMoniker->CreatedOk())
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CRunningObjectTable::EnumRunning couldn't create enumerator\n"));
+
+ hr = E_OUTOFMEMORY;
+
+ EXIT_BLOCK;
+ }
+
+
+ hr = gResolver.IrotEnumRunning(&pMkIFList);
+
+ if (hr != NOERROR)
+ {
+ // Return the error from the SCM
+ CairoleDebugOut((DEB_ERROR,
+ "CRunningObjectTable::EnumRunning call to SCM failed\n"));
+
+ EXIT_BLOCK;
+ }
+
+ hr = protenumMoniker->LoadResultFromScm(pMkIFList);
+
+ if (hr == NOERROR)
+ {
+ *ppenumMoniker = protenumMoniker;
+ protenumMoniker = NULL;
+ }
+
+ END_BLOCK
+
+ if (protenumMoniker != NULL)
+ {
+ // If our local pointer is not NULL then we just delete it and
+ // ignore the reference count since this means an error occurred.
+ delete protenumMoniker;
+ }
+
+ if (pMkIFList != NULL)
+ {
+ // Free all the entries
+ for (DWORD i = 0; i < pMkIFList->dwSize; i++)
+ {
+ MIDL_user_free(pMkIFList->apIFDList[i]);
+ }
+
+ // Then free the structure itself
+ MIDL_user_free(pMkIFList);
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::EnumRunning"
+ "( %lX ) [ %p ]\n", this, hr, *ppenumMoniker));
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::GetObjectByPath
+//
+// Synopsis: Locate object in ROT by path
+//
+// Arguments: [lpstrPath] - path to locate in the rot
+// [ppunkObject] - where to put the object if requested
+// [dwThreadID] - what thread the object s/b in
+//
+// Returns: S_OK - successfully built enumerator
+// E_OUTOFMEMORY - could not build enumerator
+//
+// Algorithm: Build a buffer full of objects from the local table then
+// consult the ROT directory.
+//
+// History: 30-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CRunningObjectTable::IGetObjectByPath(
+ LPOLESTR lpstrPath,
+ LPUNKNOWN *ppunkObject,
+ DWORD dwThreadID)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRunningObjectTable::IGetObjectByPath"
+ "( %p , %p , %lX )\n", this, lpstrPath, ppunkObject, dwThreadID));
+
+ HRESULT hr = S_FALSE;
+
+ // Where we put the moniker we use for the moniker
+ CSafeMoniker smk;
+
+ if (ppunkObject)
+ {
+ *ppunkObject = NULL;
+ }
+
+ // Create a buffer for the comparison
+ CTmpMkEqBuf tmpMkEqBuf;
+
+ hr = CreateFileMonikerComparisonBuffer(lpstrPath, tmpMkEqBuf.GetBuf(),
+ tmpMkEqBuf.GetSize(), tmpMkEqBuf.GetSizeAddr());
+
+ if (SUCCEEDED(hr))
+ {
+ hr = IGetObject(tmpMkEqBuf.GetMkEqBuf(), ppunkObject, dwThreadID);
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRunningObjectTable::IGetObjectByPath"
+ "( %lX ) [ %p ]\n", this, hr,
+ ((ppunkObject == NULL) ? NULL : *ppunkObject)));
+
+ return hr;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: GetRunningObjectTable
+//
+// Synopsis: Get a pointer to the ROT
+//
+// Arguments: [reserved] - reserved!
+// [pprot] - where to put interface pointer
+//
+// Returns: S_OK - got pointer
+// E_UNEXPECTED - table not initialized
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDAPI GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
+{
+ OLETRACEIN((API_GetRunningObjectTable, PARAMFMT("reserved= %x, pprot= %p"), pprot));
+
+ CairoleDebugOut((DEB_ROT, "%p _IN GetRunningObjectTable"
+ "( %p )\n", NULL, pprot));
+
+ HRESULT hr = CO_E_NOTINITIALIZED;
+
+ if ((pROT == NULL) && (g_cProcessInits > 0))
+ {
+ // If we haven't created it, create it now.
+ CRunningObjectTable::Create();
+ }
+
+ *pprot = pROT; // will be NULL in error case
+
+ if (pROT != NULL)
+ {
+ hr = S_OK;
+ }
+
+ CALLHOOKOBJECTCREATE(hr,CLSID_NULL,IID_IRunningObjectTable,(IUnknown **)pprot);
+
+ CairoleDebugOut((DEB_ROT, "%p OUT GetRunningObjectTable"
+ "( %lX ) [ %p ]\n", NULL, hr, *pprot));
+
+ OLETRACEOUT((API_GetRunningObjectTable, hr));
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CleanROTForApartment
+//
+// Synopsis: Get rid of running object table entries for the current APT.
+//
+// History: 24-Jun-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+void CleanROTForApartment(void)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CleanROTForApartment"
+ "\n", NULL));
+
+ if (pROT)
+ {
+ pROT->CleanupApartment(GetCurrentApartmentId());
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CleanROTForApartment"
+ "\n", NULL));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DestroyRunningObjectTable
+//
+// Synopsis: Get rid of running object table
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+void DestroyRunningObjectTable(void)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN DestroyRunningObjectTable"
+ "\n", NULL));
+
+ // It doesn't matter what the ref count is, when OLE goes, the ROT goes too.
+ delete pROT;
+
+ pROT = NULL;
+
+#ifndef DCOM
+ // Our endpoint is history. Note that this just resides here as a
+ // convenient place for this to happen (and for historical reasons
+ // since it used to serve some practical purpose for being here).
+ epiForProcess.MakeEndpointInvalid();
+#endif
+
+ CairoleDebugOut((DEB_ROT, "%p OUT DestroyRunningObjectTable"
+ "\n", NULL));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMonikerPtrBuf::CMonikerPtrBuf
+//
+// Synopsis: Copy constructor for the buffer
+//
+// Arguments: [mkptrbuf] - buffer to copy
+//
+// History: 20-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CMonikerPtrBuf::CMonikerPtrBuf(CMonikerPtrBuf& mkptrbuf)
+ : CMonikerBag(mkptrbuf)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CMonikerPtrBuf::CMonikerPtrBuf"
+ "( %p )\n", this, &mkptrbuf));
+
+ // Now AddRef the copied monikers so they stay around
+ IMoniker **ppmk = GetArrayBase();
+
+ for (DWORD i = 0; i < GetMax(); i++)
+ {
+ ppmk[i]->AddRef();
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CMonikerPtrBuf::CMonikerPtrBuf"
+ "( %p )\n", this));
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMonikerPtrBuf::~CMonikerPtrBuf
+//
+// Synopsis: Free items
+//
+// History: 23-Dec-93 Ricksa Created
+//
+// Notes: This object assumes that it gets its monikers addref'd
+// so it is up to this object to free them.
+//
+//--------------------------------------------------------------------------
+CMonikerPtrBuf::~CMonikerPtrBuf(void)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CMonikerPtrBuf::~CMonikerPtrBuf"
+ "\n", this));
+
+ DWORD dwSize = GetMax();
+
+ if (dwSize > 0)
+ {
+ IMoniker **ppmk = GetArrayBase();
+
+ for (DWORD i = 0; i < dwSize; i++)
+ {
+ ppmk[i]->Release();
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CMonikerPtrBuf::~CMonikerPtrBuf"
+ "\n", this));
+}
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotMonikerEnum::CRotMonikerEnum
+//
+// Synopsis: Constructor for ROT moniker enumerator
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CRotMonikerEnum::CRotMonikerEnum(void)
+ : _cRefs(1), _dwOffset(0)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::CRotMonikerEnum"
+ "\n", this));
+
+ // Header does the work
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::CRotMonikerEnum"
+ "\n", this));
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotMonikerEnum::CRotMonikerEnum
+//
+// Synopsis: Copy constructor for ROT moniker enumerator
+//
+// Arguments: [rotenumMoniker] - Enumerator to copy from
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CRotMonikerEnum::CRotMonikerEnum(CRotMonikerEnum& rotenumMoniker)
+ : _cRefs(1), _dwOffset(rotenumMoniker._dwOffset),
+ _mkptrbuf(rotenumMoniker._mkptrbuf)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::CRotMonikerEnum"
+ "( %p )\n", this, &rotenumMoniker));
+
+ // Header does the work
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::CRotMonikerEnum"
+ "\n", this));
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotMonikerEnum::QueryInterface
+//
+// Synopsis: QI for ROT moniker enumerator
+//
+// Arguments: [riid] - requested interface
+// [ppvObj] - where to put requested interface
+//
+// Returns: S_OK - returned interface
+// E_NOINTERFACE - requested interface is not supported
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRotMonikerEnum::QueryInterface(REFIID riid, void **ppvObj)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::QueryInterface"
+ "( %p , %p )\n", this, &riid, ppvObj));
+
+ HRESULT hr = S_OK;
+
+ BEGIN_BLOCK
+
+ *ppvObj = NULL;
+
+ if (IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IEnumMoniker))
+ {
+ *ppvObj = (LPVOID)this;
+ AddRef();
+ EXIT_BLOCK;
+ }
+
+ hr = E_NOINTERFACE;
+
+ END_BLOCK
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::QueryInterface"
+ "( %lX ) [ %p ]\n", this, hr, *ppvObj));
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotMonikerEnum::AddRef
+//
+// Synopsis: Add to ref count
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CRotMonikerEnum::AddRef(void)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::AddRef"
+ "\n", this));
+
+ InterlockedIncrement((LONG *) &_cRefs);
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::AddRef"
+ "( %lX )\n", this, _cRefs));
+
+ return _cRefs;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotMonikerEnum::Release
+//
+// Synopsis: Release reference count
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CRotMonikerEnum::Release(void)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::Release"
+ "\n", this));
+
+ LONG lRefs = InterlockedDecrement((LONG *) &_cRefs);
+
+ if (0 == lRefs)
+ {
+ delete this;
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::Release"
+ "( %lX )\n", this, lRefs));
+
+ return (ULONG) lRefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotMonikerEnum::Next
+//
+// Synopsis: Get next number of requested monikers from the buffer
+//
+// Arguments: [celt] - number of items requested
+// [reelt] - where to put table of monikers
+// [pceltFetched] - number of monikers retrieved
+//
+// Returns: S_OK - all requested monikers successfully retrieved
+// S_FALSE - entire buffer not filled.
+//
+// Algorithm: Loop through list returning monikers.
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRotMonikerEnum::Next(
+ ULONG celt,
+ LPMONIKER *reelt,
+ ULONG *pceltFetched)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::Next"
+ "( %lX , %p , %p )\n", this, celt, reelt, pceltFetched));
+
+ // Validate pceltFetched
+ if ((celt != 1) && (pceltFetched != NULL))
+ {
+ *pceltFetched = 0;
+ }
+
+ // Loop loading monikers until request is satisfied or we run out
+ for (ULONG i = 0; i < celt; i++)
+ {
+ IMoniker *pmk = _mkptrbuf.GetItem(_dwOffset++);
+
+ if (pmk == NULL)
+ {
+ break;
+ }
+
+ reelt[i] = pmk;
+ }
+
+ if (pceltFetched != NULL)
+ {
+ *pceltFetched = i;
+ }
+
+ HRESULT hr = (i == celt) ? S_OK : S_FALSE;
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::Next"
+ "( %lX )\n", this, hr));
+
+ return hr;
+
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotMonikerEnum::Skip
+//
+// Synopsis: Skip designated number of monikers
+//
+// Arguments: [celt] - number to skip
+//
+// Returns: S_OK - skipped requested number
+// S_FALSE - # skipped greater than remaining
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRotMonikerEnum::Skip(ULONG celt)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::Skip"
+ "( %lX )\n", this, celt));
+
+ // Error return -- assume count to skip is larger than number of items
+ HRESULT hr = S_FALSE;
+
+ if (_dwOffset + celt <= _mkptrbuf.GetMax())
+ {
+ _dwOffset += celt;
+ hr = S_OK;
+ }
+ else
+ {
+ _dwOffset = _mkptrbuf.GetMax();
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::Skip"
+ "( %lX )\n", this, hr));
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotMonikerEnum::Reset
+//
+// Synopsis: Reset the enumerator
+//
+// Returns: S_OK
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRotMonikerEnum::Reset(void)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::Reset"
+ "\n", this));
+
+ _dwOffset = 0;
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::Reset"
+ "\n", this));
+
+ return S_OK;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotMonikerEnum::Clone
+//
+// Synopsis: Make a copy of the current enumerator
+//
+// Arguments: [ppenumMoniker] - where to put copy
+//
+// Returns: S_OK - moniker successfully cloned
+// E_OUTOFMEMORY - not enough memory to clone
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CRotMonikerEnum::Clone(LPENUMMONIKER FAR* ppenumMoniker)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::Clone"
+ "( %p )\n", this, ppenumMoniker));
+
+ // Error return
+ HRESULT hr = S_OK;
+
+ // Use copy constructor to create duplicate enumerator
+ CRotMonikerEnum *pcrotenumMoniker = new CRotMonikerEnum(*this);
+
+ if ((pcrotenumMoniker == NULL) || !pcrotenumMoniker->CreatedOk())
+ {
+ delete pcrotenumMoniker;
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ {
+ *ppenumMoniker = (LPENUMMONIKER) pcrotenumMoniker;
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::Clone"
+ "( %lX ) [ %p ]\n", this, hr, *ppenumMoniker));
+ return hr;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotMonikerEnum::LoadResultFromScm
+//
+// Synopsis: Add a list of monikers to enumerator from an object server
+//
+// Arguments: [pMkIFList] - list to use for input
+//
+// Returns: S_OK - moniker added
+// E_OUTOFMEMORY - could not add any more to buffer
+//
+// History: 11-Nov-93 Ricksa Created
+// 27-Jan-95 Ricksa New ROT
+//
+// Note:
+//
+//--------------------------------------------------------------------------
+HRESULT CRotMonikerEnum::LoadResultFromScm(MkInterfaceList *pMkIFList)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CRotMonikerEnum::LoadResultFromScm"
+ "( %p )\n", this, pMkIFList));
+
+ HRESULT hr = S_OK;
+
+ for (DWORD i = 0; i < pMkIFList->dwSize; i++)
+ {
+ // Where to put the unmarshaled moniker
+ IMoniker *pmk;
+
+ // Unmarshal the interface from the buffer
+ CXmitRpcStream xrpc(pMkIFList->apIFDList[i]);
+
+ hr = CoUnmarshalInterface(&xrpc, IID_IMoniker, (void **) &pmk);
+
+ if (FAILED(hr))
+ {
+ // Really two important possibilities for failure: (1) Out of
+ // memory or (2) Somekind of communication failure during the
+ // unmarshal. Out of memory means that we are pretty well dead
+ // so we will return that error and ignore the others since
+ // if the moniker is remotely served, it can actually have
+ // gone away before we got around to unmarshaling it.
+ if (hr == E_OUTOFMEMORY)
+ {
+ break;
+ }
+
+ continue;
+ }
+
+ // Put the moniker in the array
+ _mkptrbuf.Add(pmk);
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CRotMonikerEnum::LoadResultFromScm"
+ "( %lX )\n", this, hr));
+
+ return hr;
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetLocalRunningObjectForDde
+//
+// Synopsis: Searches for and optionally returns an object by path for
+// the DDE layer.
+//
+// Effects: Attempts to find an entry in the local ROT that matches
+// the provided path. If there is a hit in the table, and
+// ppunkObject is not NULL, then it also returns a pointer
+// to the object.
+//
+// Arguments: [lpstrPath] -- Path to search for
+// [ppunkObject] -- Output for the object pointer
+//
+// Returns: S_OK - Found object in local ROT
+// S_FALSE - Didn't find object in local ROT
+// OTHER - Something else happened.
+//
+// History: 6-29-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT GetLocalRunningObjectForDde(
+ LPOLESTR lpstrPath,
+ LPUNKNOWN *ppunkObject)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN GetLocalRunningObjectForDde"
+ "( %p , %p )\n", NULL, lpstrPath, ppunkObject));
+
+ HRESULT hr = S_FALSE;
+
+ // POSTPPC - We're getting close to RTM for NT/PPC, so we'll make this fix
+ // for Chicago only for now
+#ifdef _CHICAGO_
+ // We create a file moniker here to ensure that the name we test against
+ // the ROT is in UNC form
+ LPMONIKER pMnk;
+ LPBINDCTX pBc;
+ LPWSTR pwszDisplayName;
+
+ hr = CreateFileMoniker(lpstrPath, &pMnk);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ hr = CreateBindCtx(NULL, &pBc);
+ if (FAILED(hr))
+ {
+ pMnk->Release();
+ return hr;
+ }
+ hr = pMnk->GetDisplayName(pBc, NULL, &pwszDisplayName);
+ if (FAILED(hr))
+ {
+ pMnk->Release();
+ pBc->Release();
+ return hr;
+ }
+
+ // If there currently isn't a local ROT, then the object surely isn't
+ // registered.
+ if (pROT != NULL)
+ {
+ hr = pROT->IGetObjectByPath(pwszDisplayName, ppunkObject,
+ CoGetCurrentProcess());
+ }
+ else
+ {
+ hr = S_FALSE;
+ }
+
+ // Cleanup
+ pMnk->Release();
+ pBc->Release();
+ CoTaskMemFree(pwszDisplayName);
+
+
+#else
+ //
+ // If there currently isn't a local ROT, then the object surely isn't
+ // registered.
+ //
+ if (pROT != NULL)
+ {
+ hr = pROT->IGetObjectByPath(lpstrPath, ppunkObject,
+ CoGetCurrentProcess());
+ }
+
+#endif // _CHICAGO_
+
+ CairoleDebugOut((DEB_ROT, "%p OUT GetLocalRunningObjectForDde"
+ "( %lX ) [ %p ]\n", NULL, hr,
+ ((ppunkObject == NULL) ? NULL : *ppunkObject)));
+
+ return(hr);
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetObjectFromRotByPath
+//
+// Synopsis: Searches for and optionally returns an object by path for
+// pbkect binding.
+//
+// Effects: Attempts to find an entry in the ROT that matches
+// the provided path. If there is a hit in the table, and
+// ppunkObject is not NULL, then it also returns a pointer
+// to the object.
+//
+// Arguments: [lpstrPath] -- Path to search for
+// [ppunkObject] -- Output for the object pointer
+//
+// Returns: S_OK - Found object in local ROT
+// S_FALSE - Didn't find object in local ROT
+// OTHER - Something else happened.
+//
+// History: 30-Jan-95 Ricksa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT GetObjectFromRotByPath(
+ LPOLESTR lpstrPath,
+ LPUNKNOWN *ppunkObject)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN GetObjectFromRotByPath"
+ "( %p , %p )\n", NULL, lpstrPath, ppunkObject));
+
+ HRESULT hr = S_FALSE;
+
+ // Is the rot in existence yet?
+ if (pROT == NULL)
+ {
+ // No - create the ROT. Remember that pROT is real pointer to the
+ // running object table. GetRunningObjectTable returns this and
+ // initializes it if it is NULL. This is why we don't pay very much
+ // attention to prot.
+ IRunningObjectTable *prot;
+
+ GetRunningObjectTable(0, &prot);
+
+ // Note that we don't have to release the prot because the ROT
+ // doesn't care about its reference count. Its lifetime is independent
+ // of the reference count.
+ }
+
+ if (pROT != NULL)
+ {
+ hr = pROT->IGetObjectByPath(lpstrPath, ppunkObject, 0);
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT GetObjectFromRotByPath"
+ "( %lX ) [ %p ]\n", NULL, hr, *ppunkObject));
+
+ return(hr);
+}
diff --git a/private/ole32/com/rot/crot.hxx b/private/ole32/com/rot/crot.hxx
new file mode 100644
index 000000000..784caa851
--- /dev/null
+++ b/private/ole32/com/rot/crot.hxx
@@ -0,0 +1,627 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: rot.hxx
+//
+// Contents: Class/methods having to do with rot in compob32
+//
+// Classes: CROTItem
+// CRunningObjectTable
+// CMonikerPtrBuf
+// CRotMonikerEnum
+//
+// Functions:
+//
+// History: 20-Nov-93 Ricksa Created
+// 25-Mar-94 brucema #10737 CMonikerPtrBuf copy
+// constructor needed to AddRef
+// copied monikers
+// 24-Jun-94 BruceMa Add CRotItem::GetSignature ()
+// 28-Jun-92 BruceMa Memory SIFT fixes
+// 12-Jan-95 Ricksa New ROT
+//
+//--------------------------------------------------------------------------
+#ifndef __ROT_HXX__
+#define __ROT_HXX__
+
+#include <olesem.hxx>
+#include <array_fv.h>
+#include <iface.h>
+#include <irot.h>
+#include <rothelp.hxx>
+#include <resolver.hxx>
+#include <objact.hxx>
+#include <crothint.hxx>
+#include "dbag.hxx"
+
+
+
+// Default number of entries in the ROT
+#define ROT_DEF_SIZE 32
+
+
+inline DWORD MakeRegID(WORD wSig, DWORD idwIndex)
+{
+ return ((DWORD) wSig) << 16 | idwIndex;
+}
+
+
+inline void GetSigAndIndex(DWORD dwRegID, WORD *pwSig, DWORD *pdwIndex)
+{
+ *pwSig = (WORD) (dwRegID >> 16);
+ *pdwIndex = dwRegID & 0x0000FFFF;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CROTItem
+//
+// Purpose: Item in local running object table
+//
+// Interface: SetSig - set signiture for local ROT item
+// ValidSig - Make sure signiture is valid
+// GetAptId - get apt for entry
+// GetScmRegKey - get a pointer to the SCM registry key
+// DontCallApp - set so revoke doesn't call back to the app.
+//
+// History: 20-Nov-93 Ricksa Created
+// 28-Jan-95 Ricksa New ROT
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+class CROTItem : public CPrivAlloc
+{
+public:
+ CROTItem(void);
+
+ ~CROTItem(void);
+
+ void SetSig(WORD dwInSig);
+
+ BOOL ValidSig(WORD dwInSig);
+
+ HAPT GetAptId(void);
+
+ SCMREGKEY * GetScmRegKey(void);
+
+ void DontCallApp(void);
+
+private:
+
+ WORD _wItemSig;
+
+ BOOL _fDontCallApp;
+
+ SCMREGKEY _scmregkey;
+
+ HAPT _hApt;
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CROTItem::CROTItem
+//
+// Synopsis: Create an entry in the table
+//
+// History: 27-Nov-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CROTItem::CROTItem(void)
+ : _hApt(GetCurrentApartmentId()), _fDontCallApp(FALSE)
+{
+ // We make the entry location invalid.
+ _scmregkey.dwEntryLoc = SCMREG_INVALID_ENTRY_LOC;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CROTItem::GetAptId
+//
+// Synopsis: Get apartment id from the table.
+//
+// History: 24-Jun-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+inline HAPT CROTItem::GetAptId(void)
+{
+ return _hApt;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CROTItem::SetSig
+//
+// Synopsis: Set the signiture for the object
+//
+// History: 17-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CROTItem::SetSig(WORD wInSig)
+{
+ _wItemSig = wInSig;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CROTItem::ValidSig
+//
+// Synopsis: Return whether object has a valid signiture
+//
+// Returns: TRUE - signiture is valid
+// FALSE - signiture is not valid
+//
+// History: 12-Jan-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CROTItem::ValidSig(WORD dwInSig)
+{
+ // Note that the signiture could accidently match in the case of
+ // an object that we are just registering because we don't keep
+ // the table locked during the registration. Therefore, we add
+ // the additional check to see if this entry has a registration
+ // in the SCM before we say OK.
+ return (_wItemSig == dwInSig)
+ && (_scmregkey.dwEntryLoc != SCMREG_INVALID_ENTRY_LOC);
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CROTItem::GetScmRegKey
+//
+// Synopsis: Invalidate endpoint
+//
+// History: 31-Jan-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline SCMREGKEY *CROTItem::GetScmRegKey(void)
+{
+ return &_scmregkey;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CROTItem::DontCallApp
+//
+// Synopsis: Prevents this item from ever calling back to the application
+//
+// Effects: Sets flag that prevents calls to release marshal data.
+//
+// History: 29-Jun-94 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+inline void CROTItem::DontCallApp(void)
+{
+ _fDontCallApp = TRUE;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CRunningObjectTable
+//
+// Purpose: Present ROT interface to applications
+//
+// Interface: QueryInterface - return other interfaces supported by the ROT
+// AddRef - add a reference to the ROT
+// Release - release a reference to the ROT
+// Register - register an object in the ROT
+// Revoke - take an object out of the ROT
+// IsRunning - tell whether moniker is registered
+// GetObject - get object from the ROT
+// NoteChangeTime - register time of last change
+// GetTimeOfLastChange - get the time an item changed
+// EnumRunning - get an enumerator for all running objects.
+// GetObjectFromRotByPath - get object by its path name
+// Create - makes this object
+//
+// History: 20-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CRunningObjectTable : public CPrivAlloc, public IRunningObjectTable
+{
+public:
+ CRunningObjectTable(void);
+
+ ~CRunningObjectTable(void);
+
+ BOOL Initialize(void);
+
+ // *** IUnknown methods ***
+ STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppvObj);
+
+ STDMETHODIMP_(ULONG)AddRef(void);
+
+ STDMETHODIMP_(ULONG)Release(void);
+
+ // *** IRunningObjectTable methods ***
+ STDMETHODIMP Register(
+ DWORD grfFlags,
+ LPUNKNOWN punkObject,
+ LPMONIKER pmkObjectName,
+ DWORD *pdwRegister);
+
+ STDMETHODIMP Revoke(DWORD dwRegister);
+
+ STDMETHODIMP IsRunning(LPMONIKER pmkObjectName);
+
+ STDMETHODIMP GetObject(
+ LPMONIKER pmkObjectName,
+ LPUNKNOWN *ppunkObject);
+
+ STDMETHODIMP NoteChangeTime(
+ DWORD dwRegister,
+ FILETIME *pfiletime);
+
+ STDMETHODIMP GetTimeOfLastChange(
+ LPMONIKER pmkObjectName,
+ FILETIME *pfiletime);
+
+ STDMETHODIMP EnumRunning(LPENUMMONIKER *ppenumMoniker);
+
+ // *** Internal Methods ***
+
+ static BOOL Create(void);
+
+ STDMETHODIMP IGetObject(
+ MNKEQBUF *pmkeqbuf,
+ IUnknown **ppunkObject,
+ DWORD dwProcessID);
+
+ HRESULT IGetObjectByPath(
+ WCHAR *pwszPath,
+ IUnknown **ppunkObject,
+ DWORD dwProcessID);
+
+ HRESULT CleanupApartment(HAPT hApt);
+
+ BOOL IsInScm(MNKEQBUF *pmkeqbuf);
+
+#ifndef _CHICAGO_
+ HRESULT GetCliRotHintTbl(BYTE *pTbl);
+#endif
+
+private:
+
+ CROTItem * GetRotItem(int iIndex);
+
+ // Contains table of registrations local to the process.
+ CArrayFValue _afvRotList;
+
+#ifndef _CHICAGO_
+
+ // Hint table for optimizing requests to SCM in NT
+ CCliRotHintTable _crht;
+
+#endif // _CHICAGO_
+
+ // Signiture for ROT items
+ WORD _wSigRotItem;
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::CRunningObjectTable
+//
+// Synopsis: Create a running object table object
+//
+// History: 11-Nov-93 Ricksa Created
+// 26-Jan-95 Ricksa New ROT implementation
+//
+//--------------------------------------------------------------------------
+inline CRunningObjectTable::CRunningObjectTable(void)
+ : _afvRotList(sizeof(CROTItem *)),
+ _wSigRotItem(0)
+{
+ // Header does all the work.
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::GetRotItem
+//
+// Synopsis: Get an item from the rot array at a given index
+//
+// History: 26-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CROTItem *CRunningObjectTable::GetRotItem(int iIndex)
+{
+ CROTItem *protitm = NULL;
+
+ if ((iIndex >= 0) && (iIndex < _afvRotList.GetSize()))
+ {
+ protitm = *((CROTItem **) _afvRotList.GetAt(iIndex));
+ }
+
+ return protitm;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::IsInScm, private
+//
+// Synopsis: Determine whether we need to go to SCM for information
+//
+// History: 27-Jan-95 Ricksa Created
+//
+// Notes: This really exists to make the regular ROT operations more
+// readable. The hint table only exists in NT because the
+// ROT exists in shared memory in chicago.
+//
+//--------------------------------------------------------------------------
+inline BOOL CRunningObjectTable::IsInScm(MNKEQBUF *pmkeqbuf)
+{
+#ifndef _CHICAGO_
+
+ return _crht.GetIndicator(
+ ScmRotHash(&pmkeqbuf->abEqData[0], pmkeqbuf->cdwSize, 0));
+
+#else
+
+ // Get rid of any possible warnings.
+ pmkeqbuf;
+ return TRUE;
+
+#endif // _CHICAGO_
+}
+
+
+
+#ifndef _CHICAGO_
+//+-------------------------------------------------------------------------
+//
+// Member: CRunningObjectTable::GetCliRotHintTbl, private
+//
+// Synopsis: Return the client ROT hint table
+//
+// History: 01-Aug-95 BruceMa Created
+//
+// Notes: This supports MkParseDisplayName
+//
+//--------------------------------------------------------------------------
+inline HRESULT CRunningObjectTable::GetCliRotHintTbl(BYTE *pTbl)
+{
+ // Force initialization
+ _crht.GetIndicator(0);
+
+ // Make sure it's initialized
+ if (!_crht.InitOK())
+ {
+ return E_FAIL;
+ }
+
+ // return the hint table
+ return _crht.GetHintTable(pTbl);
+}
+#endif
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CMonikerBag
+//
+// Purpose: Collection of IMoniker*
+//
+// Interface: See dbag.hxx
+//
+// History: 20-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_DWORD_BAG(CMonikerBag, IMoniker*, 128)
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CMonikerPtrBuf
+//
+// Purpose: Hold a collection of IMoniker* from various sources
+//
+// Interface: Add - add an item to the list
+// GetItem - get an item from the list
+// BuildInterfaceList - build list from return from Object Server
+//
+// History: 20-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CMonikerPtrBuf : public CMonikerBag
+{
+public:
+
+ CMonikerPtrBuf(void);
+
+ CMonikerPtrBuf(CMonikerPtrBuf& mkptrbuf);
+
+ ~CMonikerPtrBuf(void);
+
+ HRESULT Add(IMoniker *pmk);
+
+ IMoniker * GetItem(DWORD dwOffset);
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMonikerPtrBuf::CMonikerPtrBuf
+//
+// Synopsis: Initialize a moniker pointer buffer
+//
+// History: 20-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CMonikerPtrBuf::CMonikerPtrBuf(void)
+{
+ // Base class does all the work
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMonikerPtrBuf::Add
+//
+// Synopsis: Add an item to the buffer
+//
+// Arguments: [pmk] - item to add
+//
+// Returns: S_OK - item added
+// E_OUTOFMEMORY - item could not be added
+//
+// History: 20-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CMonikerPtrBuf::Add(IMoniker *pmk)
+{
+ return CMonikerBag::Add(pmk) ? S_OK : E_OUTOFMEMORY;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMonikerPtrBuf::GetItem
+//
+// Synopsis: Get an tiem from the buffer
+//
+// Arguments: [dwOffset] - current offset in the buffer
+//
+// Returns: NULL - no item at offset
+// ~NULL - addref'd moniker
+//
+// History: 20-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline IMoniker *CMonikerPtrBuf::GetItem(DWORD dwOffset)
+{
+ IMoniker *pmk = NULL;
+
+ if (dwOffset < GetMax())
+ {
+ (pmk = (GetArrayBase())[dwOffset])->AddRef();
+ }
+
+ return pmk;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CRotMonikerEnum
+//
+// Purpose: ROT Moniker Enumerator
+//
+// Interface: QueryInterface - return other interfaces supported by the ROT
+// AddRef - add a reference to the ROT
+// Release - release a reference to the ROT
+// Next - next item(s) to enumerate
+// Skip - items to skip
+// Reset - reset enumeration to start
+// Clone - make a copy of this enumeration
+// LoadResultFromScm - add items returned from SCM ROT
+// CreatedOk - whether object got created ok.
+//
+// History: 20-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CRotMonikerEnum : public CPrivAlloc, public IEnumMoniker
+{
+public:
+ CRotMonikerEnum(void);
+
+ CRotMonikerEnum(CRotMonikerEnum& rotenumMoniker);
+
+ // *** IUnknown methods ***
+ STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppvObj);
+
+ STDMETHODIMP_(ULONG) AddRef(void);
+
+ STDMETHODIMP_(ULONG) Release(void);
+
+ // *** IEnumMoniker methods ***
+ STDMETHODIMP Next(
+ ULONG celt,
+ LPMONIKER *reelt,
+ ULONG *pceltFetched);
+
+ STDMETHODIMP Skip(ULONG celt);
+
+ STDMETHODIMP Reset(void);
+
+ STDMETHODIMP Clone(LPENUMMONIKER *ppenm);
+
+ HRESULT LoadResultFromScm(MkInterfaceList *pMkIFList);
+
+ BOOL CreatedOk(void);
+
+private:
+
+ // Reference count
+ DWORD _cRefs;
+
+ // Current offset
+ DWORD _dwOffset;
+
+ CMonikerPtrBuf _mkptrbuf;
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotMonikerEnum::CreatedOk
+//
+// Synopsis: Whether item got created successfully.
+//
+// History: 20-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CRotMonikerEnum::CreatedOk(void)
+{
+ // The moniker pointer buf is the only thing that could fail during
+ // creation so lets ask it.
+ return _mkptrbuf.CreatedOk();
+}
+
+#endif // __ROT_HXX__
+
diff --git a/private/ole32/com/rot/crothint.cxx b/private/ole32/com/rot/crothint.cxx
new file mode 100644
index 000000000..54faa99bf
--- /dev/null
+++ b/private/ole32/com/rot/crothint.cxx
@@ -0,0 +1,75 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: crothint.cxx
+//
+// Contents: Implementation of CCliRotHintTable class
+//
+// History: 27-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntlsa.h>
+#include <ntmsv1_0.h>
+#include <windows.h>
+#include <lmsname.h>
+#include <rpc.h>
+#include <winsecp.h>
+#include <stdio.h>
+#include <memory.h>
+#include <string.h>
+#include <winsvc.h>
+}
+
+#include <ole2int.h>
+
+
+#include <caller.hxx>
+#include <crothint.hxx>
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliRotHintTable::GetIndicator
+//
+// Synopsis: Get whether indicator for hash entry is set
+//
+// Arguments: [dwOffset] - offset we are looking for
+//
+// Returns: TRUE - entry is set
+// FALSE - entry is not set
+//
+// Algorithm: If array has not been initialized, then bind to the SCM's
+// shared memory. Then check if the offset into the table is
+// set.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CCliRotHintTable::GetIndicator(DWORD dwOffset)
+{
+ if (_pbHintArray == NULL)
+ {
+ // Open the shared memory
+ _hSm = OpenSharedFileMapping(
+ ROTHINT_NAME,
+ SCM_HASH_SIZE,
+ (void **) &_pbHintArray);
+
+ // It is OK for this to fail because the hint table doesn't
+ // really get created by the SCM until the first registration.
+ }
+
+ if (_pbHintArray != NULL)
+ {
+ return _pbHintArray[dwOffset];
+ }
+
+ return FALSE;
+}
diff --git a/private/ole32/com/rot/crothint.hxx b/private/ole32/com/rot/crothint.hxx
new file mode 100644
index 000000000..df505592c
--- /dev/null
+++ b/private/ole32/com/rot/crothint.hxx
@@ -0,0 +1,124 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: crothint.hxx
+//
+// Contents: Classes used in implementing the ROT hint table.
+//
+// Classes: CCliRotHintTable
+//
+// History: 27-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __CROTHINT_HXX__
+#define __CROTHINT_HXX__
+
+
+#ifndef _CHICAGO_
+
+#include <rothint.hxx>
+#include <smcreate.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Class: CCliRotHintTable (srht)
+//
+// Purpose: abstract client side of the rot hint table
+//
+// Interface: InitOK - whether initialization succeeded.
+// GetIndicator - get whether hash bucket has entries.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CCliRotHintTable : public CRotHintTable
+{
+public:
+ CCliRotHintTable(void);
+
+ ~CCliRotHintTable(void);
+
+ BOOL InitOK(void);
+
+ BOOL GetIndicator(DWORD dwOffset);
+
+ HRESULT GetHintTable(BYTE *pTbl);
+
+private:
+
+ HANDLE _hSm;
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliRotHintTable::CCliRotHintTable
+//
+// Synopsis: Initializes empty object
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CCliRotHintTable::CCliRotHintTable(void) : _hSm(NULL)
+{
+ // Header does all the work
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliRotHintTable::~CCliRotHintTable
+//
+// Synopsis: Clean up hint table object
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CCliRotHintTable::~CCliRotHintTable(void)
+{
+ CloseSharedFileMapping(_hSm, _pbHintArray);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliRotHintTable::InitOK
+//
+// Synopsis: Whether initialization worked
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CCliRotHintTable::InitOK(void)
+{
+ return _hSm != NULL;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCliRotHintTable::GetHintTable
+//
+// Synopsis: Copy the hint table
+//
+// History: 20-Jul-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+inline HRESULT CCliRotHintTable::GetHintTable(BYTE *pbTbl)
+{
+ if (InitOK)
+ {
+ memcpy(pbTbl, _pbHintArray, SCM_HASH_SIZE);
+ return S_OK;
+ }
+ else
+ {
+ return E_FAIL;
+ }
+}
+
+
+#endif // !_CHICAGO_
+
+#endif // __ROTHINT_HXX__
diff --git a/private/ole32/com/rot/daytona/makefile b/private/ole32/com/rot/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/rot/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/rot/daytona/sources b/private/ole32/com/rot/daytona/sources
new file mode 100644
index 000000000..40276560e
--- /dev/null
+++ b/private/ole32/com/rot/daytona/sources
@@ -0,0 +1,70 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= rot
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..;..\..\inc;
+INCLUDES= $(INCLUDES);..\..\dcomidl\daytona;..\..\objact;..\..\dcomrem;
+INCLUDES= $(INCLUDES);$(BASEDIR)\private\dcomidl\obj
+
+C_DEFINES= \
+ $(C_DEFINES)
+
+SOURCES= \
+ ..\access.cxx \
+ ..\caller.cxx \
+ ..\crot.cxx \
+ ..\crothint.cxx \
+ ..\getif.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+#!include ..\..\precomp2.inc
diff --git a/private/ole32/com/rot/dbag.hxx b/private/ole32/com/rot/dbag.hxx
new file mode 100644
index 000000000..c987d2b5e
--- /dev/null
+++ b/private/ole32/com/rot/dbag.hxx
@@ -0,0 +1,225 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dbag.hxx
+//
+// Contents: Growable array class for unordered collections of DWORD
+// size objects.
+//
+// Classes: CDwordBag
+//
+// History: 03-Dec-93 Ricksa Created
+// 25-Mar-94 brucema #10737 CDwordBag copy constructor bug
+//
+//--------------------------------------------------------------------------
+#ifndef __DBAG_HXX__
+#define __DBAG_HXX__
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDwordBag
+//
+// Purpose: Provide a holder (bag) for as many dword size objects
+// as you want to put in it.
+//
+// Interface: CreatedOk - Did object initialize correctly
+// Add - add an object to the bag
+// GetMax - get number of objects in the bag
+// GetArrayBase - get pointer to the base of the array of objects.
+//
+// History: 03-Dec-93 Ricksa Created
+//
+// Notes: Expectation is that DEFINE_DWORD_BAG macro defined below
+// will be used to provide type safety for this structure.
+//
+// A point of this object is that it allows the user of the
+// array to actually get at the array when the user needs
+// to iterate the contents of the array. This will allow the
+// maximum speed of iteration.
+//
+//--------------------------------------------------------------------------
+class CDwordBag : private CArrayFValue
+{
+public:
+ CDwordBag(DWORD dwSize);
+
+ CDwordBag(CDwordBag& dwbag, DWORD dwSize);
+
+ BOOL CreatedOk(void);
+
+ BOOL Add(DWORD dwEntry);
+
+ DWORD GetMax(void);
+
+ DWORD * GetArrayBase(void);
+
+private:
+
+ DWORD _dwSlotsUsed;
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDwordBag::CDwordBag
+//
+// Synopsis: Create an empty bag
+//
+// Arguments: [dwSize] - default number of object for bag to hold
+//
+// History: 03-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CDwordBag::CDwordBag(DWORD dwSize)
+ : CArrayFValue(sizeof(DWORD)), _dwSlotsUsed(0)
+{
+ SetSize(dwSize, dwSize);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDwordBag::CDwordBag
+//
+// Synopsis: Copy constructor for derived classes
+//
+// Arguments: [dwbag] - bag that you want to make a copy of
+// [dwGrowBy] - value to grow the array by
+//
+// History: 03-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CDwordBag::CDwordBag(CDwordBag& dwbag, DWORD dwSize)
+ : CArrayFValue(sizeof(DWORD)), _dwSlotsUsed(0)
+{
+ if (SetSize(dwbag.GetSize(), dwSize))
+ {
+ // Copy old data to new
+ _dwSlotsUsed = dwbag._dwSlotsUsed;
+ memcpy(GetAt(0), dwbag.GetAt(0), _dwSlotsUsed * sizeof(DWORD));
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDwordBag::CreatedOk
+//
+// Synopsis: Tell an outside class whether the initial construction
+// worked.
+//
+// Returns: [TRUE] - initial construction worked
+// [FALSE] - initial construction failed
+//
+// History: 03-Dec-93 Ricksa Created
+//
+// Notes: This should be called immediatedly after the construction
+// to see whether the constuctor really worked.
+//
+//--------------------------------------------------------------------------
+inline BOOL CDwordBag::CreatedOk(void)
+{
+ return GetSize() != 0;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDwordBag::Add
+//
+// Synopsis: Add an object to the bag
+//
+// Arguments: [dwEntry] - entry to add to the bag
+//
+// Returns: [TRUE] - object was added.
+// [FALSE] - object could not be added.
+//
+// History: 03-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CDwordBag::Add(DWORD dwEntry)
+{
+ BOOL fResult = SetAtGrow(_dwSlotsUsed, &dwEntry);
+
+ if (fResult)
+ {
+ _dwSlotsUsed++;
+ }
+
+ return fResult;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDwordBag::GetMax
+//
+// Synopsis: Get number of objects contained in the bag
+//
+// History: 03-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline DWORD CDwordBag::GetMax(void)
+{
+ return _dwSlotsUsed;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDwordBag::GetArrayBase
+//
+// Synopsis: Get the base of the array of objects
+//
+// History: 03-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline DWORD *CDwordBag::GetArrayBase(void)
+{
+ return (DWORD *) GetAt(0);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Macro: DEFINE_DWORD_BAG
+//
+// Purpose: Provide a type safe holder (bag) for dwordd size objects
+// as you want to put in it.
+//
+// History: 03-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#define DEFINE_DWORD_BAG(name, type, start_size) \
+class name : public CDwordBag \
+{ \
+public: \
+ \
+ inline name(void) : CDwordBag(start_size) { } \
+ \
+ inline name(name& ref) : CDwordBag(ref, start_size) { } \
+ \
+ inline type * GetArrayBase(void) \
+ { return (type *) CDwordBag::GetArrayBase(); } \
+ \
+ inline BOOL Add(type item) { return CDwordBag::Add((DWORD) item); }\
+};
+
+
+
+#endif // __DBAG_HXX__
diff --git a/private/ole32/com/rot/dirs b/private/ole32/com/rot/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/com/rot/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/com/rot/epid.cxx b/private/ole32/com/rot/epid.cxx
new file mode 100644
index 000000000..5cc3842c9
--- /dev/null
+++ b/private/ole32/com/rot/epid.cxx
@@ -0,0 +1,168 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: epid.cxx
+//
+// Contents: Members that implement the CEndPointID class
+//
+// History: 16-Feb-95 Ricksa Created
+//
+// Notes: In the old implementation of the ROT this class was
+// used extensively. Now, it is no longer used except in
+// getif.cxx support for drag and drop.
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+
+#include <service.hxx>
+#include <endpnt.hxx>
+#include <channelb.hxx>
+#include "epid.hxx"
+
+#ifndef _CHICAGO_
+DWORD CEndPointID::s_dwEndPointID = ENDPOINT_ID_INVALID;
+#endif
+
+CEndPointID epiForProcess;
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEndPointID::MakeEndpointInvalid
+//
+// Synopsis: Reset endpoint to invalid when CoUninitialize is called
+//
+// History: 15-Mar-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+void CEndPointID::MakeEndpointInvalid(void)
+{
+#ifdef _CHICAGO_
+
+ // If this fails then no TLS exists. The initial value for the endpoint is
+ // invalid so the failure case can be ignored.
+ DWORD *pEndPoint = TLSGetEndPointPtr();
+ if (pEndPoint != NULL)
+ {
+ *pEndPoint = ENDPOINT_ID_INVALID;
+ }
+
+#else
+
+ s_dwEndPointID = ENDPOINT_ID_INVALID;
+
+#endif
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEndPointID::ConvertEndPointToDword
+//
+// Synopsis: Convert end point string to DWORD id for ROT
+//
+// Arguments: [pwszBindString] - Binding string
+//
+// Returns: DWORD that represents the binding string
+//
+// Algorithm: Uses internal knowledge of how the RPC runtimes dynamically
+// assign addresses to find the embedded integer and converts
+// that integer from being a string to a DWORD.
+//
+// History: 11-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+DWORD CEndPointID::ConvertEndPointToDword(LPWSTR pwszBindString)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN ConvertEndPointToDword "
+ "( %p )\n", NULL, pwszBindString));
+
+ // THIS CODE ONLY WORKS FOR NT 1.0 LPRC TRANSPORT!!!
+ // The format of the endpoint is:
+ // mswmsg:<server>[OLEnnnnnnnn] on Chicago and
+ // ncalrpc:<server>[OLEnnnnnnnn] on NT
+ // We will dig out the nnnnnnn field and convert it to a
+ // dword.
+
+ DWORD dwResult = ENDPOINT_ID_INVALID;
+
+ // Get the the '[' in the string
+ WCHAR *pwszId = wcschr(pwszBindString, '[');
+
+ if (pwszId != NULL)
+ {
+ // Dig out the id from the string -- see above comment for the
+ // reason for the magic number '4'.
+ dwResult = wcstol (&pwszId[4], NULL, 16);
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT ConvertEndPointToDword "
+ "( %lX )\n", NULL, dwResult));
+
+ return dwResult;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEndPointID::GetEndpointID
+//
+// Synopsis: Get the endpoint ID for this server
+//
+// Arguments: [dwEndPointID] - what end point id should be
+//
+// History: 20-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+DWORD CEndPointID::GetEndpointID(void)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN ConvertEndPointToDword\n", NULL));
+
+#ifdef _CHICAGO_
+
+ DWORD *pEndPoint = TLSGetEndPointPtr();
+ CairoleAssert( pEndPoint != NULL );
+
+#else
+
+ DWORD *pEndPoint = &s_dwEndPointID;
+
+#endif
+
+ if (*pEndPoint == ENDPOINT_ID_INVALID)
+ {
+ // If endpoint is not set, create it. First get our local endpoint.
+ CairoleAssert(LocalService() && "RPC Server not defined");
+
+#ifdef _CHICAGO_
+ if (IsThreadListening())
+ {
+ CairoleDebugOut((DEB_ENDPNT, "CEndPointID::GetEndPointID this:%p\n", this));
+ LocalService()->Listen();
+ }
+#endif
+ LPWSTR pwszBindString = LocalService()->GetStringBinding();
+
+ if (pwszBindString)
+ {
+ // Note: this logic is end point dependent. This is why
+ // there is a call to a routine here -- we are localizing
+ // the effects of changing end points.
+ *pEndPoint = ConvertEndPointToDword(pwszBindString);
+ }
+ else
+ {
+ CairoleDebugOut((DEB_WARN, "No local endpoint\n"));
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT ConvertEndPointToDword ( %lX )\n",
+ NULL, *pEndPoint));
+
+ return *pEndPoint;
+}
diff --git a/private/ole32/com/rot/epid.hxx b/private/ole32/com/rot/epid.hxx
new file mode 100644
index 000000000..24ca270f4
--- /dev/null
+++ b/private/ole32/com/rot/epid.hxx
@@ -0,0 +1,58 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: epid.hxx
+//
+// Contents:
+//
+// Classes: CEndPointAtom
+//
+// History: 16-Feb-95 Ricksa Created
+//
+// Notes: In the old implementation of the ROT this class was
+// used extensively. Now, it is no longer used except in
+// getif.cxx support for drag and drop.
+//
+//--------------------------------------------------------------------------
+#ifndef __EPID_HXX__
+#define __EPID_HXX__
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CEndPointID (epi)
+//
+// Purpose: Abstract server's endpoint id to allow delayed retrieval.
+//
+// Interface: MakeEndpointInvalid
+//
+// History: 16-Mar-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CEndPointID : public CPrivAlloc
+{
+public:
+
+ void MakeEndpointInvalid(void);
+
+ DWORD GetEndpointID(void);
+
+private:
+
+ DWORD ConvertEndPointToDword(LPWSTR pwszBindString);
+
+#ifndef _CHICAGO_
+
+ static DWORD s_dwEndPointID;
+
+#endif
+
+};
+
+// The one and only of these objects for the process
+extern CEndPointID epiForProcess;
+
+#endif // __EPID_HXX_
diff --git a/private/ole32/com/rot/filelist.mk b/private/ole32/com/rot/filelist.mk
new file mode 100644
index 000000000..aaaa1802a
--- /dev/null
+++ b/private/ole32/com/rot/filelist.mk
@@ -0,0 +1,61 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = rot.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES = \
+ .\dirrot.cxx \
+ .\dirrot1.cxx \
+ .\dirrot2.cxx \
+ .\getif.cxx \
+ .\hrotrpc.cxx \
+ .\rot.cxx \
+ .\rotres.cxx \
+ .\rotres2.cxx \
+ .\sysrot.cxx \
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PXXFILE = .\headers.cxx
+PFILE =
+
+CINC = $(CINC) -I..\inc -I..\objact -I..\idl -I..\remote -I..\..\h $(TRACELOG)
+
+MTHREAD = 1
+
+MULTIDEPEND = MERGED
diff --git a/private/ole32/com/rot/getif.cxx b/private/ole32/com/rot/getif.cxx
new file mode 100644
index 000000000..20ada39b4
--- /dev/null
+++ b/private/ole32/com/rot/getif.cxx
@@ -0,0 +1,1154 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: getif.cxx
+//
+// Contents: APIs used to get an interface from a window
+//
+// Classes: CEndPointAtom
+//
+// Functions: AssignEndpointProperty
+// GetInterfaceFromWindowProp
+// PrivDragDrop
+// UnmarshalDragDataObject
+//
+// History:
+// 29-Dec-93 Ricksa Created
+// 01-Feb-94 alexgo fixed a bug in multiple registration
+// 29-Mar-94 brucema GetInterfaceFromWindowProp returns E_FAIL
+// for invalid endpoint
+// 18-May-94 alexgo fixed race condition in
+// RemGetInterfaceFromWindowProp
+// 15-Jun-94 JohannP added apartment support
+// 28-Jul-94 BruceMa Memory sift fix
+// 30-Sep-94 Ricksa Drag/Drop optimization
+// 08-Nov-94 alexgo added PrivDragDrop protocol
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include <crot.hxx>
+#include <getif.h>
+#include <getif.hxx>
+#include <dragopt.h>
+#include <resolver.hxx>
+
+
+#define ENDPOINT_PROP_NAME L"OleEndPointID"
+#define OLEDRAG_DATAOBJ_PROP L"Drag_DataObj_Prop"
+
+
+static WCHAR *apwszValidProperties[] = { OLE_DROP_TARGET_PROP,
+ CLIPBOARD_DATA_OBJECT_PROP };
+const int MAX_PROPERTIES = sizeof(apwszValidProperties) / sizeof(WCHAR *);
+
+extern ATOM g_aDropTarget;
+
+HRESULT UnmarshalFromEndpointProperty(HWND hWnd,
+ IInterfaceFromWindowProp **ppIFWP,
+ BOOL *pfLocal);
+
+//+-------------------------------------------------------------------------
+//
+// Class: CInterfaceFromWindowProp
+//
+// Purpose: Passes back interface pointers stored on windows for drag drop
+//
+// Interface: IInterfaceFromWindowProp
+//
+// History: dd-mmm-yy Author Comment
+// 14 May 95 AlexMit Created
+//
+//--------------------------------------------------------------------------
+class CInterfaceFromWindowProp : public IInterfaceFromWindowProp,
+ public CPrivAlloc
+{
+public:
+ CInterfaceFromWindowProp();
+
+ STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) ( void );
+ STDMETHOD_(ULONG,Release) ( void );
+
+ STDMETHOD (GetInterfaceFromWindowProp)(
+ DWORD hWnd,
+ REFIID riid,
+ IUnknown **ppunk,
+ WCHAR *pwszPropertyName );
+
+ STDMETHOD (PrivDragDrop)(
+ DWORD hWnd,
+ InterfaceData *pIFDDataObject,
+ DWORD dop,
+ DWORD grfKeyState,
+ POINTL pt,
+ DWORD *pdwEffect,
+ DWORD dwSmId,
+ IDataObject *pRealDataObject,
+ DWORD hwndSource );
+
+private:
+ ULONG _ulRefCnt; // Reference count
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: CInterfaceFromWindowProp::CInterfaceFromWindowProp, public
+//
+// Synopsis: construction
+//
+// History: 10 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+CInterfaceFromWindowProp::CInterfaceFromWindowProp() : _ulRefCnt(1)
+{
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CInterfaceFromWindowProp::AddRef, public
+//
+// Synopsis: increment reference count
+//
+// History: 10 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+ULONG CInterfaceFromWindowProp::AddRef(void)
+{
+ InterlockedIncrement((long *)&_ulRefCnt);
+ return _ulRefCnt;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CInterfaceFromWindowProp::Release, public
+//
+// Synopsis: decrement reference count
+//
+// History: 10 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+ULONG CInterfaceFromWindowProp::Release(void)
+{
+ ULONG RefCnt = _ulRefCnt-1;
+ if (InterlockedDecrement((long*)&_ulRefCnt) == 0)
+ {
+ delete this;
+ return 0;
+ }
+
+ return RefCnt;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CInterfaceFromWindowProp::QueryInterface, public
+//
+// Synopsis: returns supported interfaces
+//
+// History: 10 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------
+STDMETHODIMP CInterfaceFromWindowProp::QueryInterface(REFIID riid, void **ppv)
+{
+ if (IsEqualIID(riid, IID_IInterfaceFromWindowProp) || // more common than IUnknown
+ IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppv = (IInterfaceFromWindowProp *) this;
+ AddRef();
+ return S_OK;
+ }
+
+ *ppv = NULL;
+ return E_NOINTERFACE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: SDDInfo
+//
+// Purpose: caches information across drag drop calls
+//
+// Interface:
+//
+// History: dd-mmm-yy Author Comment
+// 08-Jan-95 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+struct SDDInfo : public CPrivAlloc
+{
+ BOOL fLocal;
+ IInterfaceFromWindowProp *pIFWP;
+
+ SDDInfo(HWND hWnd, HRESULT& hr);
+ ~SDDInfo();
+};
+
+//+-------------------------------------------------------------------------
+//
+// Member: SDDInfo::SDDInfo
+//
+// Synopsis: constructor
+//
+// Effects:
+//
+// Arguments: [hr] -- the return result
+//
+// History: dd-mmm-yy Author Comment
+// 10-Jan-95 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+inline SDDInfo::SDDInfo(HWND hWnd, HRESULT& hr)
+{
+ hr = UnmarshalFromEndpointProperty(hWnd,
+ &pIFWP,
+ &fLocal);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: SDDInfo::SDDInfo
+//
+// Synopsis: destructor
+//
+// Effects:
+//
+// History: dd-mmm-yy Author Comment
+// 14 May 95 AlexMit Destroyed
+//
+//--------------------------------------------------------------------------
+inline SDDInfo::~SDDInfo()
+{
+ if (pIFWP != NULL)
+ {
+ pIFWP->Release();
+ pIFWP = NULL;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CEndPointAtom
+//
+// Purpose: Abstract way of init/delete global atom for end point property
+//
+// Interface: GetPropPtr - get atom of appropriate type to pass to prop APIs
+//
+// History: 31-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CEndPointAtom
+{
+public:
+ ~CEndPointAtom(void);
+
+ LPCWSTR GetPropPtr(void);
+
+private:
+
+ static ATOM s_AtomProp;
+};
+
+// make this static since there is only one of them and so we dont have
+// to run a ctor at process intialization time.
+
+ATOM CEndPointAtom::s_AtomProp = 0;
+
+// Atom for endpoint property string
+CEndPointAtom epatm;
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEndPointAtom::~CEndPointAtom
+//
+// Synopsis: Clean up atom at destruction of object
+//
+// History: 31-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CEndPointAtom::~CEndPointAtom(void)
+{
+ if (s_AtomProp != 0)
+ {
+ //
+ // 16-bit WinWord is evil and does not call UnregisterDragDrop
+ // before terminating. When a window is destroyed under Win95,
+ // all attached properties are removed and atoms deleted. This
+ // causes a problem with other applications when more deletes than
+ // adds are performed. This 'hack' will disable the deletion of
+ // the EndPointAtom under Chicago. Not a big deal since the
+ // Explorer will keep this Atom alive anyways.
+ //
+#if !defined(_CHICAGO_)
+ GlobalDeleteAtom(s_AtomProp);
+#endif
+ s_AtomProp = NULL;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEndPointAtom::GetPropPtr
+//
+// Synopsis: Return an atom suitable for passing to prop APIs
+//
+// Returns: Endpoint string as atom or NULL.
+//
+// History: 31-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline LPCWSTR CEndPointAtom::GetPropPtr(void)
+{
+ if (s_AtomProp == 0)
+ {
+ s_AtomProp = GlobalAddAtom(ENDPOINT_PROP_NAME);
+ }
+
+ return (LPCWSTR) s_AtomProp;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: AssignEndpointProperty
+//
+// Synopsis: Assigns a end point as a property of a window
+//
+// Arguments: [hWnd] - window to assign the endpoint property
+//
+// Returns: S_OK - end point successfully added to the window
+// E_INVALIDARG - property could not be set
+//
+// Algorithm: Get the endpoint Id and assign it as a property to the
+// window.
+//
+// History:
+// 26-Jul-94 AndyH #20843 - restarting OLE in the shared WOW
+// 01-Feb-94 alexgo fixed a bug to ensure that
+// RpcServerRegisterIf gets called only
+// once.
+// 29-Dec-93 Ricksa Created
+// 22-Jan-95 Rickhi marshaled interface stored in SCM
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT AssignEndpointProperty(HWND hWnd)
+{
+ ComDebOut((DEB_ROT, "AssignEndpointProperty hWnd:%x\n", hWnd));
+
+ // Create an object for this window.
+ CInterfaceFromWindowProp *pIFWP = new CInterfaceFromWindowProp;
+ if (pIFWP == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // Marshal the interface into the OBJREF
+ DWORD dwCookie;
+ OBJREF objref;
+ HRESULT hr = MarshalObjRef(objref, IID_IInterfaceFromWindowProp, pIFWP,
+ MSHLFLAGS_TABLESTRONG);
+
+ if (SUCCEEDED(hr))
+ {
+ OXID_INFO oxidInfo;
+ hr = FillLocalOXIDInfo(objref, oxidInfo);
+
+ if (SUCCEEDED(hr))
+ {
+ // register the STDOBJREF part of the marshaled interface with the SCM
+ hr = gResolver.RegisterWindowPropInterface(hWnd,
+ &objref.u_objref.u_standard.std,
+ &oxidInfo,
+ &dwCookie);
+ if (SUCCEEDED(hr))
+ {
+ // Stuff the magic values in properties on the window.
+ if (!SetProp(hWnd, epatm.GetPropPtr(), (void *) dwCookie))
+ {
+ hr = E_INVALIDARG;
+ }
+ }
+
+ // Free the resources containing the String Bindings.
+ CoTaskMemFree(oxidInfo.psa);
+ }
+
+ // release the resources held by the objref.
+ FreeObjRef(objref);
+ }
+
+ // The stub holds the object alive until UnAssignEndpointProperty
+ // is called. Get rid of the extra reference.
+ pIFWP->Release();
+
+ ComDebOut((DEB_ROT, "AssignEndpointProperty hr:%x dwCookie:%x\n", hr, dwCookie));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UnAssignEndpointProperty
+//
+// Synopsis: Remove end point property
+//
+// Arguments: [hWnd] - window to remove the endpoint property
+// [dwAssignAptID] - Apartment that Assigned the Endpoint Property
+//
+// Returns: S_OK - end point successfully removed from the window
+// E_INVALIDARG - property could not be removed
+//
+// Algorithm: Remove the end point id property from the window.
+//
+// History: 30-Dec-93 Ricksa Created
+// 22-Jan-95 Rickhi marshaled interface stored in SCM
+// 15-Apr-96 Rogerg Added dwAssignThreadID.
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT UnAssignEndpointProperty(HWND hWnd,DWORD* dwAssignAptID)
+{
+ ComDebOut((DEB_ROT, "UnAssignEndpointProperty hWnd:%x\n", hWnd));
+
+ // Read the cookie value from the window property and remove the
+ // property from the window.
+
+ DWORD dwCookie = (DWORD) GetProp(hWnd, epatm.GetPropPtr());
+ BOOL fSuccess = (RemoveProp(hWnd, epatm.GetPropPtr()) != NULL);
+
+ // use the cookie to extract and release the STDOBJREF entry from the SCM
+
+ OBJREF objref;
+ OXID_INFO oxidInfo;
+ memset(&oxidInfo, 0, sizeof(oxidInfo));
+
+ HRESULT hr = gResolver.GetWindowPropInterface(hWnd, dwCookie,
+ TRUE, // fRevoke
+ &objref.u_objref.u_standard.std,
+ &oxidInfo);
+ if (SUCCEEDED(hr))
+ {
+ BOOL fLocal;
+
+ hr = CompleteObjRef(objref, oxidInfo, IID_IInterfaceFromWindowProp, &fLocal);
+
+ MIDL_user_free(oxidInfo.psa);
+
+ if (SUCCEEDED(hr))
+ {
+ // release the marshal data and free resources on the ObjRef
+ hr = ReleaseMarshalObjRef(objref);
+ FreeObjRef(objref);
+ }
+ }
+
+ if (!fSuccess && SUCCEEDED(hr))
+ {
+ hr = E_INVALIDARG;
+ }
+
+ *dwAssignAptID = SUCCEEDED(hr) ? oxidInfo.dwTid : 0;
+
+ ComDebOut((DEB_ROT, "UnAssignEndpointProperty hr:%x\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UnmarshalFromEndpointProperty
+//
+// Synopsis: Get the IInterfaceFromWindowProp interface from the window
+//
+// Arguments: [hWnd] - window to get the endpoint property
+//
+// Returns: S_OK - end point successfully removed from the window
+// E_INVALIDARG - property could not be removed
+//
+// Algorithm:
+//
+// History: 22-Jan-95 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT UnmarshalFromEndpointProperty(HWND hWnd,
+ IInterfaceFromWindowProp **ppIFWP,
+ BOOL *pfLocal)
+{
+ HRESULT hr = E_INVALIDARG;
+ *ppIFWP = NULL;
+
+ // get the magic cookie from the window
+ DWORD dwCookie = (DWORD) GetProp(hWnd, epatm.GetPropPtr());
+
+ if (dwCookie != NULL)
+ {
+ // Get a proxy to the CInterfaceFromWindowProp object. Note
+ // that if this is the thread that object is on, it will just
+ // return the real object.
+
+ OBJREF objref;
+ OXID_INFO oxidInfo;
+ memset(&oxidInfo, 0, sizeof(oxidInfo));
+
+ hr = gResolver.GetWindowPropInterface(hWnd, dwCookie,
+ FALSE, // fRevoke
+ &objref.u_objref.u_standard.std,
+ &oxidInfo);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = CompleteObjRef(objref, oxidInfo, IID_IInterfaceFromWindowProp, pfLocal);
+
+ MIDL_user_free(oxidInfo.psa);
+
+ if (SUCCEEDED(hr))
+ {
+ // unmarshal and release resouces on the ObjRef
+ hr = UnmarshalObjRef(objref, (void **) ppIFWP);
+ FreeObjRef(objref);
+ }
+ }
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetInterfaceFromWindowProp
+//
+// Synopsis: Get an interface that is assigned to a window as a property
+//
+// Arguments: [hWnd] - window of interest
+// [riid] - interface we want back
+// [ppunk] - where to put the requested interface pointer
+// [pwszPropertyName] - name of property holding interface.
+//
+// Returns: S_OK - got the interface
+// E_INVALIDARG - no endpoint property
+//
+// Algorithm: Get the end point from the window and then convert that
+// end point to a proxy. Then call the remote
+// get interface call to get the actual interface.
+//
+// History: 29-Dec-93 Ricksa Created
+// 20-Jul-94 alexgo Optimization for same-thread case
+// 22-Jan-95 Rickhi marshaled interface stored in SCM
+//
+//--------------------------------------------------------------------------
+extern "C" GetInterfaceFromWindowProp(
+ HWND hWnd,
+ REFIID riid,
+ IUnknown **ppunk,
+ LPOLESTR pwszPropertyName)
+{
+ ComDebOut((DEB_ROT,
+ "GetInterfaceFromWindowProp hWnd:%x ppunk:%x riid:%I pszPropName%ws\n",
+ hWnd, ppunk, &riid, pwszPropertyName));
+
+ *ppunk = NULL;
+
+ BOOL fLocal;
+ IInterfaceFromWindowProp *pIFWP;
+ HRESULT hr = UnmarshalFromEndpointProperty(hWnd, &pIFWP, &fLocal);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = pIFWP->GetInterfaceFromWindowProp((DWORD) hWnd,
+ riid, ppunk,
+ pwszPropertyName);
+ pIFWP->Release();
+ }
+
+ ComDebOut((DEB_ROT,
+ "GetInterfaceFromWindowProp *ppunk:%x hr:%x\n", *ppunk, hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CInterfaceFromWindowProp::GetInterfaceFromWindowProp, public
+//
+// Synopsis: Get information from object server ROT
+//
+// Arguments: [pData] - data for call
+//
+// Returns: S_OK - got information
+// S_FALSE - entry for moniker not found in the ROT
+// E_INVALIDARG - bad arguments
+//
+// Algorithm: Unmarshal the moniker interface. Then look up the object
+// in the ROT. If found, return the requested data.
+//
+// History: 15-Dec-93 Ricksa Created
+// 18-May-94 alexgo fixed race condition, this function now
+// fetches the interface from the hwnd
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CInterfaceFromWindowProp::GetInterfaceFromWindowProp(
+ DWORD hWnd,
+ REFIID riid,
+ IUnknown **ppunk,
+ WCHAR *pwszPropertyName )
+{
+ HRESULT hr;
+
+ // Validate the requested property
+ for (int i = 0; i < MAX_PROPERTIES; i++)
+ {
+ if (lstrcmpW(apwszValidProperties[i], pwszPropertyName) == 0)
+ {
+ break;
+ }
+ }
+
+ if (i == MAX_PROPERTIES)
+ {
+ *ppunk = NULL;
+ return E_INVALIDARG;
+ }
+
+ // Get the interface pointer from the window
+ *ppunk = (IUnknown *) GetProp((HWND) hWnd, pwszPropertyName);
+
+ // Could we get the property requested?
+ if (*ppunk != NULL)
+ {
+ hr = S_OK;
+ (*ppunk)->AddRef();
+ }
+ else
+ {
+ // No property -- this can happen when the object got shutdown
+ // during the time that the client was trying to get the property.
+ hr = E_FAIL;
+ }
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CInterfaceFromWindowProp::PrivDragDrop, public
+//
+// Synopsis: interprets the DragOp parameter and makes the appropriate
+// call to the drop target.
+//
+// Effects:
+//
+// Arguments: [hwnd] -- the target window
+// [dop] -- the drag drop op
+// [grfKeyState] -- the keyboard state
+// [ptl] -- the mouse position
+// [pdwEffects] -- the drag drop effects
+// [pIFDataObject] -- interface data for the drag data object
+// [dwSmId] -- shared memory ID for the data formats
+// [hwndSource] -- the window handle to the drag drop source
+// (i.e. our private dragdrop/clipboard
+// window)
+//
+// Requires: pIFDataObject && dwSmId must be NULL if pRealDataObj is
+// not NULL.
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+// finds the drop target and calls it according to 'dop'
+// (the drag drop op code)
+//
+// for DRAGOP_ENTER:
+// create the psuedo-data object for returning enumerated
+// formats. Stuff this data object as a property on the
+// target window. Then through to the actual drag enter
+// object.
+//
+// for DRAGOP_OVER:
+// simply call IDropTarget::DragOver
+//
+// for DRAGOP_LEAVE
+// remove the data object from the target window
+// and call IUnknown->Release(); Then call IDropTarget::
+// DragLeave
+//
+// for DRAGOP_DROP
+// remove the data object from the target window and
+// pass it into IDropTarget::Drop call. Once the call
+// completes, Release the data object
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-94 alexgo author
+//
+// Notes:
+// HACK ALERT!! It is important that we use the same data object
+// for DragEnter and Drop calls. Some 16bit apps (like
+// MS PowerPoint) check to see if the data object pointer value
+// is the same--if it's not, then they fail the drop call.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CInterfaceFromWindowProp::PrivDragDrop(
+ DWORD hwnd,
+ InterfaceData *pIFDataObject,
+ DWORD dop,
+ DWORD grfKeyState,
+ POINTL ptl,
+ DWORD * pdwEffects,
+ DWORD dwSmId,
+ IDataObject *pRealDataObject,
+ DWORD hwndSource )
+{
+ IDropTarget *pIDropTarget;
+ IDataObject *pIDataObject;
+ HRESULT hr = E_FAIL;
+
+
+#if DBG == 1
+ if( pRealDataObject != NULL )
+ {
+ Assert(!pIFDataObject);
+ }
+#endif // DBG == 1
+
+ pIDropTarget = (IDropTarget *)GetProp((HWND) hwnd, (LPCWSTR)g_aDropTarget);
+
+ if (pIDropTarget != NULL)
+ {
+ // check the drag drop op code and do the right thing
+
+ switch( dop )
+ {
+ case DRAGOP_ENTER:
+ // Create a data object for use in the Drag Enter if we
+ // weren't given one
+
+ if( pRealDataObject == NULL )
+ {
+ InterfaceData *pIFTemp = NULL;
+
+ Assert(pIFDataObject);
+
+ if( pIFDataObject )
+ {
+ // we need to make a copy of the interface data, as
+ // the fake data object may use it after this function
+ // returns (see ido.cpp)
+
+ pIFTemp = (InterfaceData *)PrivMemAlloc(
+ IFD_SIZE(pIFDataObject));
+
+ if( !pIFTemp )
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ memcpy(pIFTemp, pIFDataObject,
+ IFD_SIZE(pIFDataObject));
+ }
+ hr = CreateDragDataObject(pIFTemp, dwSmId,
+ &pIDataObject);
+ }
+ else
+ {
+ pIDataObject = pRealDataObject;
+ pIDataObject->AddRef();
+ hr = NOERROR;
+ }
+
+ if (hr == NOERROR)
+ {
+ // Call through to the drop target
+ hr = pIDropTarget->DragEnter(
+ pIDataObject,
+ grfKeyState,
+ ptl,
+ pdwEffects);
+
+ // Bug#12835 Win16 set the DROPEFFECT to none on an error returned by DragEnter
+ // but continued the drag within the window
+ if ( (NOERROR != hr) && IsWOWThread() )
+ {
+ *pdwEffects = DROPEFFECT_NONE;
+ hr = NOERROR;
+ }
+
+ SetProp((HWND) hwnd, OLEDRAG_DATAOBJ_PROP, pIDataObject);
+ }
+
+ break;
+
+ case DRAGOP_OVER:
+
+ hr = pIDropTarget->DragOver(grfKeyState, ptl, pdwEffects);
+
+ break;
+
+ case DRAGOP_LEAVE:
+
+ pIDataObject = (IDataObject *)RemoveProp((HWND) hwnd,
+ OLEDRAG_DATAOBJ_PROP);
+
+ if( pIDataObject )
+ {
+ pIDataObject->Release();
+ }
+
+ hr = pIDropTarget->DragLeave();
+
+ break;
+
+ case DRAGOP_DROP:
+
+ pIDataObject = (IDataObject *)RemoveProp((HWND) hwnd,
+ OLEDRAG_DATAOBJ_PROP);
+
+
+ if( pIDataObject )
+ {
+ DWORD pidSource;
+ DWORD tidSource;
+ BOOL fAttached = FALSE;
+
+ // HACK ALERT!!! Some 16bit apps (like Word) try to
+ // become the foreground window via SetActiveWindow.
+ // However, if a 32bit app is the source, it is the
+ // foreground *thread*; SetActiveWindow only makes the
+ // window the foreground window for the current input
+ // queue.
+ // In order to maket this work, if we are a 16bit target
+ // and the source exists in a different process (either
+ // a 32bit process or a different VDM), then attach
+ // our input queue to the source's input queue.
+ //
+ // Within one VDM the thread's queues are already attached
+
+ if( IsWOWThread() && hwndSource != NULL )
+ {
+ tidSource = GetWindowThreadProcessId((HWND)hwndSource,
+ &pidSource);
+
+ if( pidSource != GetCurrentProcessId() )
+ {
+ AttachThreadInput(GetCurrentThreadId(), tidSource,
+ TRUE);
+ fAttached = TRUE;
+ }
+ }
+
+ hr = pIDropTarget->Drop( pIDataObject, grfKeyState, ptl,
+ pdwEffects);
+
+ if( fAttached == TRUE )
+ {
+ AttachThreadInput(GetCurrentThreadId(), tidSource,
+ FALSE);
+ }
+
+ pIDataObject->Release();
+ }
+
+ break;
+
+ default:
+ Assert(0);
+ hr = E_UNEXPECTED;
+
+ }
+
+ // HACK ALERT!! Well, it turns out that 16bit OLE used
+ // "CurScrollMove" for the Scroll-NoDrop cursor. Better yet,
+ // MFC *depends* on this in their drag drop implementation.
+ // An MFC target doing scroll-move will actually return
+ // drop effect scroll-nodrop.
+ //
+ // So if we are in a 16bit app as the target, munge the
+ // effect to better match 16bit OLE behavior.
+
+ if( IsWOWThread() && pdwEffects )
+ {
+ // test for SCROLL-NODROP
+ if( *pdwEffects == DROPEFFECT_SCROLL )
+ {
+ *pdwEffects |= DROPEFFECT_MOVE;
+ }
+ }
+
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: PrivDragDrop
+//
+// Synopsis: Package up drag enter to be sent to the drop target.
+//
+// Arguments: [hWnd]- handle to the window to get target from
+// [dop] - the drag drop operation to perform
+// [IDOBuffer] - the marshalled buffer for the data object
+// [pIDataObject] - data object from source
+// [grfKeyState] - current key state
+// [ptl] - point where drop would occur
+// [pdwEffect] - proposed valid effects
+// [hwndSource] - the handle to OLE's drag drop source window
+// [phDDInfo] -- pointer to a DragDropInfo handle, for
+// caching rpc info about the drop target.
+// May not be NULL, but on DragEnter,
+// should be a pointer to NULL.
+//
+// Returns: S_OK - call succeeded
+// Other - call failed
+//
+// Algorithm: First determine if the the window is for the current thread
+// If it is, then immediately interpret the drag op. If not,
+// get the end point from the window and package up
+// the call to be dispatched to RPC.
+//
+// History: 30-Sep-94 Ricksa Created
+// 08-Nov-94 alexgo modified to use DRAGOP's
+// 08-Jan-95 alexgo added caching of RPC binding handles via
+// DDInfo handles
+//
+//--------------------------------------------------------------------------
+HRESULT PrivDragDrop(
+ HWND hWnd,
+ DRAGOP dop,
+ IFBuffer IDOBuffer,
+ IDataObject *pIDataObject,
+ DWORD grfKeyState,
+ POINTL ptl,
+ DWORD *pdwEffect,
+ HWND hwndSource,
+ DDInfo *phDDInfo)
+{
+ HRESULT hr = S_FALSE; // If the endpoint is invalid
+ SDDInfo *pddinfo = *(SDDInfo **)phDDInfo;
+
+ InterfaceData *pIFData = (InterfaceData *)IDOBuffer;
+
+#if DBG == 1
+ Assert(phDDInfo);
+ if( dop == DRAGOP_ENTER )
+ {
+ Assert(*phDDInfo == NULL);
+ }
+ // we can't assert the reverse case because phDDInfo will be NULL
+ // in DROPOP_OVER, etc if we are drag drop'ing to the same thread...
+
+#endif // DBG == 1
+
+
+ // If we don't have any cached information (i.e. pddinfo == NULL),
+ // then get the endpoint id from the window and construct a
+ // PrivDragDrop data structure. If the window is on the current
+ // thread, the PrivDragDrop structure will end up with a pointer
+ // to the CInterfaceFromWindowProp object rather then a proxy.
+
+ if( pddinfo == NULL )
+ {
+ {
+ pddinfo = new SDDInfo(hWnd, hr);
+
+ if( pddinfo == NULL )
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ if( hr != NOERROR )
+ {
+ delete pddinfo;
+ return E_FAIL;
+ }
+
+ *phDDInfo = (DDInfo)pddinfo;
+ }
+ }
+
+ if( pddinfo != NULL )
+ {
+ hr = pddinfo->pIFWP->PrivDragDrop( (DWORD) hWnd,
+ (pddinfo->fLocal) ? NULL : pIFData,
+ dop,
+ grfKeyState, ptl,
+ (pdwEffect) ? pdwEffect : DROPEFFECT_NONE,
+ GetCurrentThreadId(),
+ (pddinfo->fLocal) ? pIDataObject : NULL,
+ (DWORD) hwndSource );
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UnmarshalDragDataObject
+//
+// Synopsis: Unmarshal the drag source's data object
+//
+// Arguments: [pvMarshaledDataObject] - pointer to interface buffer
+//
+// Returns: NULL - unmarshal failed
+// ~NULL - got the real data object on source
+//
+// Algorithm: Unmarshal interface and return whether we got an interface
+// back.
+//
+// History: 30-Sep-94 Ricksa Created
+//
+// Note: This call really exists so that the drag code over in
+// ole232/drag won't have to copy in all the marshaling stuff.
+//
+//--------------------------------------------------------------------------
+IDataObject *UnmarshalDragDataObject(void *pvMarshaledDataObject)
+{
+ InterfaceData *pIFD = (InterfaceData *) pvMarshaledDataObject;
+
+ // Convert returned interface to a stream
+ CXmitRpcStream xrpc(pIFD);
+
+ IDataObject *pIDataObject;
+
+ HRESULT hr = CoUnmarshalInterface(
+ &xrpc,
+ IID_IDataObject,
+ (void **) &pIDataObject);
+
+ return (SUCCEEDED(hr)) ? pIDataObject : NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetMarshalledInterfaceBuffer
+//
+// Synopsis: marshals the given interface into an allocated buffer. The
+// buffer is returned
+//
+// Effects:
+//
+// Arguments: [refiid] -- the iid of the interface to marshal
+// [punk] -- the IUnknown to marshal
+// [pIFBuf] -- where to return the buffer
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: calls CoMarshalInterface(MSHFLAGS_TABLESTRONG)
+//
+// History: dd-mmm-yy Author Comment
+// 03-Dec-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT GetMarshalledInterfaceBuffer( REFIID riid, IUnknown *punk, IFBuffer
+ *pIFBuf)
+{
+ HRESULT hr;
+
+ InterfaceData *pIFD = NULL;
+
+ CXmitRpcStream xrpc;
+
+ hr = CoMarshalInterface(&xrpc, riid, punk, MSHCTX_NOSHAREDMEM, NULL,
+ MSHLFLAGS_TABLESTRONG);
+
+ if( hr == NOERROR )
+ {
+ xrpc.AssignSerializedInterface(&pIFD);
+ }
+
+ *pIFBuf = (IFBuffer)pIFD;
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReleaseMarshalledInterfaceBuffer
+//
+// Synopsis: releases the buffer allocated by GetMarshalledInterfaceBuffer
+//
+// Effects:
+//
+// Arguments: [IFBuf] -- the interface buffer to release
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: calls CoReleaseMarshalData to undo the TABLE_STRONG
+// marshalling
+//
+// History: dd-mmm-yy Author Comment
+// 03-Dec-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT ReleaseMarshalledInterfaceBuffer( IFBuffer IFBuf )
+{
+ HRESULT hr = E_INVALIDARG;
+
+ if( IFBuf )
+ {
+ CXmitRpcStream xrpc( (InterfaceData *)IFBuf );
+
+ hr = CoReleaseMarshalData(&xrpc);
+
+ CoTaskMemFree((void *)IFBuf);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: FreeDragDropInfo
+//
+// Synopsis: frees the SPrivDragDrop structure
+//
+// Effects:
+//
+// Arguments: [hDDInfo] -- pointer to free
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 07-Jan-95 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+void FreeDragDropInfo( DDInfo hDDInfo )
+{
+ SDDInfo *pddinfo = (SDDInfo *)hDDInfo;
+
+ delete pddinfo;
+}
+
diff --git a/private/ole32/com/rot/hrotrpc.cxx b/private/ole32/com/rot/hrotrpc.cxx
new file mode 100644
index 000000000..3c89aa7c4
--- /dev/null
+++ b/private/ole32/com/rot/hrotrpc.cxx
@@ -0,0 +1,70 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: hrotrpc.cxx
+//
+// Contents: Non-inline methods for binding to rot RPC end point
+//
+// History: 21-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+
+#include "hrotrpc.hxx"
+
+#include <compname.hxx>
+
+static CComputerName s_CompName;
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: COsRotRpcHandle::COsRotRpcHandle
+//
+// Synopsis: Create a handle to an object server
+//
+// Arguments: [dwEndPointId] - id for the endpoint
+// [hr] - result of calls.
+//
+// Algorithm: Build a string to bind to the server and then use that
+// string to create a binding handle.
+//
+// History: 15-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+COsRotRpcHandle::COsRotRpcHandle(DWORD dwEndPointId, HRESULT& hr)
+{
+ // Convert DWORD endpoint into endpoint of object server. This is
+ // extremely transport dependent. For NT we use LRPC.
+ WCHAR pwszEndPoint[SYSROT_EP_STR_SIZE];
+
+ wsprintf(pwszEndPoint, SYSROT_ID_TO_EP_STR, dwEndPointId);
+
+ hr = _rpcbstr.CreateBindString(SYSROT_PROTOCOL, s_CompName.GetComputerName(),
+ pwszEndPoint);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = _hRpc.BindByString(_rpcbstr.GetStringPtr());
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: COsRotRpcHandle::COsRotRpcHandle
+//
+// Synopsis: Create a NULL handle
+//
+// History: 29-Aug-94 CraigWi Created
+//
+//--------------------------------------------------------------------------
+COsRotRpcHandle::COsRotRpcHandle(void)
+{
+ // all done by ctors
+}
diff --git a/private/ole32/com/rot/hrotrpc.hxx b/private/ole32/com/rot/hrotrpc.hxx
new file mode 100644
index 000000000..f7a173aea
--- /dev/null
+++ b/private/ole32/com/rot/hrotrpc.hxx
@@ -0,0 +1,78 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: hrotrpc.hxx
+//
+// Contents: Class for binding to rot RPC end point
+//
+// Classes: COsRotRpcHandle
+//
+// History: 21-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __HROTRPC_HXX__
+#define __HROTRPC_HXX__
+
+#include <rpcbind.hxx>
+
+#define SYSROT_EP_STR_SIZE 12
+#define SYSROT_PROTOCOL LOCAL_PROTSEQ
+#ifdef DCOM
+#define SYSROT_ID_TO_EP_STR L"OLE%X"
+#else
+#define SYSROT_ID_TO_EP_STR L"OLE%-08.8X"
+#endif
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: COsRotRpcHandle
+//
+// Purpose: Used to create handle to object server ROTs
+//
+// Interface: GetHandle - get RPC handle to requested server
+//
+// History: 15-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class COsRotRpcHandle : public CPrivAlloc
+{
+public:
+
+ // Create empty object
+ COsRotRpcHandle(DWORD dwEndPointId, HRESULT& hr);
+
+ // Free resources
+ COsRotRpcHandle(void);
+
+ handle_t GetHandle();
+
+private:
+
+ CRpcBindString _rpcbstr;
+
+ CRpcBindHandle _hRpc;
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: COsRotRpcHandle::GetHandle
+//
+// Synopsis: Return handle to object server for the ROT
+//
+// History: 15-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline handle_t COsRotRpcHandle::GetHandle(void)
+{
+ return _hRpc.Handle();
+}
+
+
+#endif // __HROTRPC_HXX__
diff --git a/private/ole32/com/rot/makefile b/private/ole32/com/rot/makefile
new file mode 100644
index 000000000..75b4046da
--- /dev/null
+++ b/private/ole32/com/rot/makefile
@@ -0,0 +1,23 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+!include $(CAIROLE)\com\makefile
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/com/rot/mshif.hxx b/private/ole32/com/rot/mshif.hxx
new file mode 100644
index 000000000..018e3649d
--- /dev/null
+++ b/private/ole32/com/rot/mshif.hxx
@@ -0,0 +1,312 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: mshif.hxx
+//
+// Contents: A class for marshaled buffer conversion
+//
+// Classes: CMarshaledInterface
+//
+// Functions: CMarshaledInterface::CMarshaledInterface
+// CMarshaledInterface::~CMarshaledInterface
+// CMarshaledInterface::Unmarshal
+// CMarshaledInterface::GetBufferPtrAddr
+// CMarshaledInterface::GetBuffer
+//
+// History: 30-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __MSHIF_HXX__
+#define __MSHIF_HXX__
+
+#include <xmit.hxx>
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CMarshaledInterface
+//
+// Purpose: Make conversion from/to marshaled interface easier
+//
+// Interface: Unmarshal - unmarshal an interface buffer
+// GetBufferPtrAddr - get pointer to address buffer pointer
+// GetBuffer - get buffer for marshaled interface
+//
+// History: 30-Nov-93 Ricksa Create
+//
+//--------------------------------------------------------------------------
+class CMarshaledInterface : public CPrivAlloc
+{
+public:
+ CMarshaledInterface(void);
+
+ CMarshaledInterface(InterfaceData *pIFD);
+
+ CMarshaledInterface(
+ REFIID riid,
+ IUnknown *punk,
+ DWORD dwmshctx,
+ DWORD mshlflags,
+ HRESULT& hr);
+
+ ~CMarshaledInterface(void);
+
+ HRESULT Unmarshal(IUnknown **ppunk, REFIID riid);
+
+ InterfaceData ** GetBufferPtrAddr(void);
+
+ InterfaceData * GetBuffer(void);
+
+protected:
+
+ InterfaceData * _pIFD;
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshaledInterface::CMarshaledInterface
+//
+// Synopsis: Create an empty object
+//
+// History: 30-Nov-93 Ricksa Create
+//
+//--------------------------------------------------------------------------
+inline CMarshaledInterface::CMarshaledInterface(void) : _pIFD(NULL)
+{
+ // Header does the work
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshaledInterface::CMarshaledInterface
+//
+// Synopsis: Create object using input buffer
+//
+// Arguments: [pIFD] - pointer to interface data
+//
+// History: 30-Nov-93 Ricksa Create
+//
+//--------------------------------------------------------------------------
+inline CMarshaledInterface::CMarshaledInterface(InterfaceData *pIFD)
+ : _pIFD(pIFD)
+{
+ // Header does the work
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshaledInterface::CMarshaledInterface
+//
+// Synopsis: Create marshaled interface from an interface pointer
+//
+// Arguments: [riid] - reference to interface to marshal
+// [punk] - pointer to interface to marshal
+// [dwMshCtx] - marshal context
+// [dwMshlFlags] - marshal flags
+// [hr] - error code if any
+//
+// History: 30-Nov-93 Ricksa Create
+//
+//--------------------------------------------------------------------------
+inline CMarshaledInterface::CMarshaledInterface(
+ REFIID riid,
+ IUnknown *punk,
+ DWORD dwMshCtx,
+ DWORD dwMshlFlags,
+ HRESULT& hr)
+ : _pIFD(NULL)
+{
+ if (punk != NULL)
+ {
+ // Stream to put marshaled interface in
+ CXmitRpcStream xrpc;
+
+ hr = CoMarshalInterface(&xrpc, riid, punk,
+ dwMshCtx, NULL, dwMshlFlags);
+
+ if (SUCCEEDED(hr))
+ {
+ xrpc.AssignSerializedInterface(&_pIFD);
+ }
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshaledInterface::~CMarshaledInterface
+//
+// Synopsis: Free marshaled buffer
+//
+// History: 30-Nov-93 Ricksa Create
+//
+//--------------------------------------------------------------------------
+inline CMarshaledInterface::~CMarshaledInterface(void)
+{
+ // BUGBUG: this is only valid for MSHLFLAGS_NORMAL when the unmarshal
+ // was attempted.
+
+ MIDL_user_free(_pIFD);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshaledInterface::Unmarshal
+//
+// Synopsis: Unmarshal buffer into an interface
+//
+// Arguments: [ppunk] - where to put interface pointer
+// [riid] - what interface to create
+//
+// History: 30-Nov-93 Ricksa Create
+//
+//--------------------------------------------------------------------------
+inline HRESULT CMarshaledInterface::Unmarshal(IUnknown **ppunk, REFIID riid)
+{
+ // Convert returned interface to a stream
+ CXmitRpcStream xrpc(_pIFD);
+
+ HRESULT hr = CoUnmarshalInterface(&xrpc, riid, (void **) ppunk);
+
+ return hr;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshaledInterface::GetBufferPtrAddr
+//
+// Synopsis: Get address of buffer
+//
+// History: 30-Nov-93 Ricksa Create
+//
+//--------------------------------------------------------------------------
+inline InterfaceData **CMarshaledInterface::GetBufferPtrAddr(void)
+{
+ return &_pIFD;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshaledInterface::GetBuffer
+//
+// Synopsis: Get pointer to buffer
+//
+// History: 30-Nov-93 Ricksa Create
+//
+//--------------------------------------------------------------------------
+inline InterfaceData *CMarshaledInterface::GetBuffer(void)
+{
+ return _pIFD;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CMshlTabInterface
+//
+// Purpose: Make conversion from/to marshaled table weak interface easier
+//
+// History: 17-Dec-93 Ricksa Create
+//
+//--------------------------------------------------------------------------
+class CMshlTabInterface : public CMarshaledInterface
+{
+public:
+ CMshlTabInterface(
+ REFIID riid,
+ IUnknown *punk,
+ DWORD mshlflags,
+ HRESULT& hr);
+
+ ~CMshlTabInterface(void);
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMshlTabInterface::~CMshlTabInterface
+//
+// Synopsis: Marshal an interface for a table
+//
+// Arguments: [riid] - what to marshal the interace to
+// [punk] - what interface to marshal table weak
+// [mshlflags] - how to marshal the interface for a table
+// [hr] - error result from marshal
+//
+// History: 17-Dec-93 Ricksa Create
+//
+//--------------------------------------------------------------------------
+// CODEWORK: Must determine proper destination context
+inline CMshlTabInterface::CMshlTabInterface(
+ REFIID riid,
+ IUnknown *punk,
+ DWORD mshlflags,
+ HRESULT& hr) : CMarshaledInterface(riid, punk, MSHCTX_LOCAL, mshlflags, hr)
+{
+ // Header does all the work
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMshlTabInterface::~CMshlTabInterface
+//
+// Synopsis: Clean up the marshaled table weak interface
+//
+// History: 17-Dec-93 Ricksa Create
+//
+//--------------------------------------------------------------------------
+inline CMshlTabInterface::~CMshlTabInterface(void)
+{
+ // Make sure the data is released appropriately
+ if (_pIFD != NULL)
+ {
+ // Make our interface into a stream
+ CXmitRpcStream xrpc(_pIFD);
+
+ // Tell RPC to release it -- error is for debugging purposes only
+ // since if this fails there isn't much we can do about it.
+#if DBG == 1
+ HRESULT hr =
+#endif // DBG
+
+ CoReleaseMarshalData(&xrpc);
+
+#if DBG == 1
+ // this can't be an assert since the idtable gets cleared before
+ // the ROT is destroyed (which uses this class) and thus all
+ // normally marshaled entires that are left would product the assert
+ if (hr != NOERROR)
+ CairoleDebugOut((DEB_ROT,
+ "MSHIF CoReleaseMarshalData failed: %lx\n", hr));
+#endif // DBG
+ }
+}
+
+#endif // __MSHIF_HXX__
diff --git a/private/ole32/com/rot/safeif.hxx b/private/ole32/com/rot/safeif.hxx
new file mode 100644
index 000000000..9fcdac31f
--- /dev/null
+++ b/private/ole32/com/rot/safeif.hxx
@@ -0,0 +1,55 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: safeif.hxx
+//
+// Contents: Safe interface pointers for various common interfaces.
+//
+// Classes: CSafeBindCtx
+// CSafeMoniker
+//
+// History: 14-Dec-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __SAFEIF_HXX__
+#define __SAFEIF_HXX__
+
+#include <safepnt.hxx>
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSafeBindCtx (sbctx)
+//
+// Purpose: Create reference to bind context that is automatically
+// released.
+//
+// Interface: see safepnt.hxx
+//
+// History: 14-Dec-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+SAFE_INTERFACE_PTR(CSafeBindCtx, IBindCtx)
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSafeMoniker (smk)
+//
+// Purpose: Create reference to moniker that is automatically
+// released.
+//
+// Interface: see safepnt.hxx
+//
+// History: 14-Dec-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+SAFE_INTERFACE_PTR(CSafeMoniker, IMoniker)
+
+
+#endif // __SAFEIF_HXX__
diff --git a/private/ole32/com/rot/scmrotif.hxx b/private/ole32/com/rot/scmrotif.hxx
new file mode 100644
index 000000000..5421166ec
--- /dev/null
+++ b/private/ole32/com/rot/scmrotif.hxx
@@ -0,0 +1,61 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: scmrotif.hxx
+//
+// Contents: Interface Functions for SCM to use the ROT
+//
+// History: 04-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __SCMROTIF_HXX__
+#define __SCMROTIF_HXX__
+
+
+#include <iface.h>
+
+#ifdef _CHICAGO_SCM_
+
+class CHandlerList;
+class CInProcList;
+class CLocSrvList;
+class CClassCacheList;
+class CStringID;
+
+//---------------------------------------------------------------------
+// OLE without SCM -- shared memory access
+//---------------------------------------------------------------------
+
+class ROOT_SHARED_DATA
+{
+public:
+ CHandlerList * gpCHandlerList;
+ CInProcList * gpCInProcList;
+ CLocSrvList * gpCLocSrvList;
+ CClassCacheList * gpCClassCacheList;
+
+ LONG lSharedObjId;
+};
+
+HRESULT InitRotDir(ROOT_SHARED_DATA **pprsd);
+#else
+HRESULT InitRotDir(void);
+#endif
+
+void CleanUpRotDir(void);
+
+HRESULT GetObjectFromRot(
+ const GUID *pguidThreadId,
+ InterfaceData * pIFDMoniker,
+ WCHAR *pwszPath,
+ DWORD dwHash,
+ InterfaceData **ppIFDunk,
+ LPDWORD lpdwEndpointToExclude);
+
+
+void CleanUpRotDir(void);
+
+#endif //__SCMROTIF_HXX__
diff --git a/private/ole32/com/surrogat/filelist.mk b/private/ole32/com/surrogat/filelist.mk
new file mode 100644
index 000000000..fd4ab1870
--- /dev/null
+++ b/private/ole32/com/surrogat/filelist.mk
@@ -0,0 +1,53 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = surrogat.exe
+
+TARGET_DESCRIPTION = "$(PLATFORM) $(BUILDTYPE) Surrogate Server for DLLs"
+
+RELEASE = 1
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES = .\surrogat.cxx \
+ .\loadcls.cxx
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+LIBS = \
+ $(COMMON)\src\ole\$(OBJDIR)\olecom.lib \
+ $(CAIROLIB)
+
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PXXFILE =
+PFILE =
+
+CINC = -I..\inc $(CINC)
+
+MTHREAD = 1
diff --git a/private/ole32/com/surrogat/loadcls.cxx b/private/ole32/com/surrogat/loadcls.cxx
new file mode 100644
index 000000000..6a9ec5169
--- /dev/null
+++ b/private/ole32/com/surrogat/loadcls.cxx
@@ -0,0 +1,455 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: loadcls.cxx
+//
+// Contents: Methods implementing classes defined in loadcls.hxx
+//
+// Functions:
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <windows.h>
+#include <ole2.h>
+#include <olecom.h>
+#include "loadcls.hxx"
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLoadedClassEntry::Init
+//
+// Synopsis: Initialize a class entry object by getting the application
+// class object from the DLL.
+//
+// Arguments: [pszCmdLine] - command line with class ID as first entry
+// [lpfngetclassobject] - DllGetClassObject entry point
+//
+// Returns: TRUE - Succeeded
+// FALSE - FAILED
+//
+// Algorithm: Read the string class id from the command line and
+// then ask the DLL to create a class object for the
+// class. Then register the class.
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CLoadedClassEntry::Init(
+ LPSTR& pszCmdLine,
+ LPFNGETCLASSOBJECT lpfngetclassobject)
+{
+ // Get guid from string
+ GUID guidClass;
+ char *pszClassID = pszCmdLine;
+ char *pszNextSpace = strchr(pszCmdLine, ' ');
+
+ if (pszNextSpace)
+ {
+ // This is not the last GUID in the string, NULL terminate
+ // the string.
+ *pszNextSpace = '\0';
+ }
+
+ CairoleDebugOut((DEB_TRACE, "Registering Class: %s\n", pszClassID));
+
+ // Convert guid in string to binary
+ sscanf(pszCmdLine, "%08lX%04X%04X",
+ &guidClass.Data1, &guidClass.Data2, &guidClass.Data3);
+
+ for (int i = 0; i < 8; i++)
+ {
+ int tmp;
+ sscanf(pszCmdLine + 16 + (i * 2), "%02X", &tmp);
+ guidClass.Data4[i] = (char) tmp;
+ }
+
+
+ // Point to next item in string if any
+ pszCmdLine = (pszNextSpace != NULL) ? pszNextSpace + 1 : NULL;
+
+ // Ask DLL to create class object
+ SCODE sc = (*lpfngetclassobject)(guidClass, IID_IUnknown, (void **) &_punk);
+
+ if (SUCCEEDED(sc))
+ {
+ // Register the class object with the component object system
+ sc = CoRegisterClassObject(guidClass, _punk,
+ CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &_dwRegistration);
+
+ if (FAILED(sc))
+ {
+ if (sc == CO_E_OBJISREG)
+ {
+ // If object is registered, the DLL must have registered
+ // itself and since compobj.dll doesn't know about the
+ // DLL, it will assume that the load is for a remotely
+ // shared object which is what we want. So it is safe
+ // to ignore this error here.
+ sc = S_OK;
+ }
+ else
+ {
+ Win4Assert(SUCCEEDED(sc) &&
+ "Surrogat: CoRegisterClassObject failed");
+ }
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ // Registration bumps reference count so we don't have to keep
+ // our reference.
+ _punk->Release();
+ }
+ }
+
+ return (SUCCEEDED(sc)) ? TRUE : FALSE;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLoadedClassList::~CLoadedClassList
+//
+// Synopsis: Free all loaded class objects and frees each one.
+//
+// Algorithm: Loops through list of list. Each item in the list is
+// freed and then the succeeding item is processed.
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CLoadedClassList::~CLoadedClassList(void)
+{
+ CLoadedClassEntryIter ldclsiter(*this);
+
+ // For each DLL revoke each DLL object
+ while(!AtEnd(ldclsiter))
+ {
+ // Get pointer to object to free
+ CLoadedClassEntry *pldcls = ldclsiter.GetEntry();
+
+ // Advance iterator to next object
+ Advance(ldclsiter);
+
+ // Free current object
+ delete pldcls;
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLoadedClassList::Init
+//
+// Synopsis: Initialise the class list for a DLL by having it process
+// all the class ids for the DLL.
+//
+// Arguments: [pszCmdLine] - command line with count of class ids for class
+// [lpfngetclassobject] - DllGetClassObject entry point
+//
+// Returns: TRUE - at least one class was registered
+// FALSE - no class was registered for the DLL.
+//
+// Algorithm: Get count of class ids from the list and then create
+// a class entry object for each entry in the list.
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CLoadedClassList::Init(
+ LPSTR& pszCmdLine,
+ LPFNGETCLASSOBJECT lpfngetclassobject)
+{
+ // Assume we will not be able to initialize any classes
+ BOOL fResult = FALSE;
+
+ // Get number of class entries for this DLL
+ char *pszNoClasses = pszCmdLine;
+ char *pszNextSpace = strchr(pszCmdLine, ' ');
+
+ if (pszNextSpace == NULL)
+ {
+ // Invalid command line -- there have to be guids following
+ // the the count otherwise why load the DLL?
+ return FALSE;
+ }
+
+ *pszNextSpace = 0;
+
+ CairoleDebugOut((DEB_TRACE, "Number of classes: %s\n", pszNoClasses));
+
+ int cClassObjects = atoi(pszNoClasses);
+
+ if (cClassObjects == 0)
+ {
+ // Either an invalid string or 0 in either case an error
+ return FALSE;
+ }
+
+ // Update string to point to the next token in the string
+ pszCmdLine = pszNextSpace + 1;
+
+ for (int i = 0; i < cClassObjects; i++)
+ {
+ // Create DLL object
+ CLoadedClassEntry *pldcls = new CLoadedClassEntry;
+
+ if (pldcls->Init(pszCmdLine, lpfngetclassobject))
+ {
+ // DLL object initialized so put it on the list
+ _Push(pldcls);
+
+ // We were able to initialize at least one class
+ fResult = TRUE;
+ }
+ else
+ {
+ // Free class object that could not be initialized.
+ delete pldcls;
+ }
+ }
+
+ return fResult;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLoadedClassList::CanExit
+//
+// Synopsis: Determine whether the class list thinks that it can exit
+//
+// Returns: TRUE - all classes in list think exit is OK
+// FALSE - a class in the list did not want to exit.
+//
+// Algorithm: Loop through the list of classes asking each list
+// in turn if exit is ok. If any class says no, break
+// the loop and return FALSE.
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CLoadedClassList::CanExit(void)
+{
+ CLoadedClassEntryIter ldclsiter(*this);
+
+ // Assume that we can exit
+ BOOL fFinalResult = TRUE;
+
+ // For each DLL revoke each DLL object
+ while(!AtEnd(ldclsiter))
+ {
+ if (!ldclsiter->CanExit())
+ {
+ // DLL said that it could not exit so we will not exit.
+ fFinalResult = FALSE;
+ break;
+ }
+
+ Advance(ldclsiter);
+ }
+
+ return fFinalResult;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllEntry::Init
+//
+// Synopsis: Initialize a DLL object
+//
+// Arguments: [pszCmdLine] - command line
+//
+// Returns: TRUE - object was successfully initialized
+// FALSE - initialization failed.
+//
+// Algorithm: Get the DLL name from the command line and then
+// initialize the DLL object by loading the DLL and
+// getting the file name. Then create a class list
+// using the rest of the commmand line.
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CDllEntry::Init(LPSTR& pszCmdLine)
+{
+ // Get DLL name from the string
+ char *pszDllName = pszCmdLine;
+ char *pszNextSpace = strchr(pszDllName, ' ');
+
+ if (pszNextSpace == NULL)
+ {
+ // Nothing after the command line. This is hosed.
+ return FALSE;
+ }
+
+ // NULL terminate the name of the DLL
+ *pszNextSpace = 0;
+
+ // Point to next item in string if any
+ pszCmdLine = (pszNextSpace != NULL) ? pszNextSpace + 1 : NULL;
+
+ CairoleDebugOut((DEB_TRACE, "Loading DLL: %s\n", pszDllName));
+
+ // Load library
+ if (!_dll.Init(pszDllName))
+ {
+ // If the DLL cannot be loaded, there is no point in continuing.
+ CairoleDebugOut((DEB_TRACE, "Load of Dll Failed\n", pszDllName));
+ return FALSE;
+ }
+
+ // Get class creation entry point
+ LPFNGETCLASSOBJECT lpfngetclassobject = _dll.GetDllGetClassObjectAddress();
+
+ if (lpfngetclassobject == NULL)
+ {
+ // If the DLL does not have the right entry point there is
+ // no point in continuing.
+ CairoleDebugOut((DEB_TRACE, "No DllGetClass EP\n", pszDllName));
+ return FALSE;
+ }
+
+ // NOTE: with current design we do not care about DllCanUnloadNow
+ // for two reasons: (1) Not all DLLs will have the entry point
+ // so it doesn't do us any good and (2) Even with the entry point,
+ // the class object would have to be released which is registered.
+
+ // Return result of initializing classes
+ return _clslist.Init(pszCmdLine, lpfngetclassobject);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLoadedClassTable::LoadClassObjects
+//
+// Synopsis: Load all classes for this instance of surrogate.
+//
+// Arguments: [pszCmdLine] - command line
+//
+// Returns: TRUE - at least one class got loaded
+// FALSE - no classes got loaded.
+//
+// Algorithm: For each DLL entry in the list create a DLL object
+// and have it create the class objects.
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CLoadedClassTable::LoadClassObjects(char *pszCmdLine)
+{
+ // Assume we will not be able to initialize any DLLs
+ BOOL fResult = FALSE;
+
+ do
+ {
+ // Create DLL object
+ CDllEntry *pdll = new CDllEntry;
+
+ if (pdll->Init(pszCmdLine))
+ {
+ // DLL object initialized so put it on the list
+ _Push(pdll);
+
+ // We were able to initialize at least one DLL
+ fResult = TRUE;
+ }
+ else
+ {
+ break;
+ }
+
+ // Create class objects under dll
+ } while (pszCmdLine != NULL);
+
+ return fResult;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLoadedClassTable::CanExit
+//
+// Synopsis: Determine whether the server wishes to exit.
+//
+// Returns: TRUE - server can exit.
+// FALSE - server cannot exit.
+//
+// Algorithm: Loop through all DLL entry objects asking them if they
+// can exit.
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CLoadedClassTable::CanExit(void)
+{
+ CDllEntryIter dlliter(*this);
+
+ // Assume that we can exit
+ BOOL fFinalResult = TRUE;
+
+ // For each DLL revoke each DLL object
+ while(!AtEnd(dlliter))
+ {
+ if (!dlliter->CanExit())
+ {
+ // DLL said that it could not exit so we will not exit.
+ fFinalResult = FALSE;
+ }
+
+ Advance(dlliter);
+ }
+
+ return fFinalResult;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLoadedClassTable::RevokeClasses
+//
+// Synopsis: Revokie all classes registered by this server
+//
+// Algorithm: Loop through each DLL object and delete it which in
+// turn unregisters all classes registered for that
+// DLL.
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+void CLoadedClassTable::RevokeClasses(void)
+{
+ CDllEntryIter dlliter(*this);
+
+ // For each DLL revoke each DLL object
+ while(!AtEnd(dlliter))
+ {
+ // Get the object to free
+ CDllEntry *pdll = dlliter.GetEntry();
+
+ // Point to the next object
+ Advance(dlliter);
+
+ // Delete the current object
+ delete pdll;
+ }
+}
diff --git a/private/ole32/com/surrogat/loadcls.hxx b/private/ole32/com/surrogat/loadcls.hxx
new file mode 100644
index 000000000..398b8e348
--- /dev/null
+++ b/private/ole32/com/surrogat/loadcls.hxx
@@ -0,0 +1,434 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: loadcls.hxx
+//
+// Contents: Class definitions for list of classes loaded into surrogat.
+//
+// Classes: CLoadedClassEntry
+// CLoadedClassList
+// CLoadedClassEntryIter
+// CDll
+// CDllEntry
+// CDllEntryIter
+// CLoadedClassTable
+//
+// Functions: CLoadedClassEntry::CLoadedClassEntry
+// CLoadedClassEntry::~CLoadedClassEntry
+// CLoadedClassEntry::CanExit
+// CDll::CDll
+// CDll::~CDll
+// CDll::Init
+// CDll::GetDllGetClassObjectAddress
+// CDllEntry::CanExit
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __LOADCLS_HXX__
+#define __LOADCLS_HXX__
+
+#include <dlink.hxx>
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Template: DlinkListIter
+//
+// Purpose: Provide template for defining class specific iterators
+// for the CDoubleList class
+//
+// Interface: operator->
+// GetEntry
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#define DlinkListIter(nclass) \
+class nclass##Iter : public CForwardIter \
+{ \
+public: \
+ \
+ nclass##Iter(CDoubleList& dbllst) \
+ : CForwardIter(dbllst) {} \
+ \
+ nclass * operator->(void) {return (nclass *) _pLinkCur;} \
+ \
+ \
+ nclass * GetEntry(void) {return (nclass *) _pLinkCur;} \
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CLoadedClassEntry
+//
+// Purpose: Object which keeps track of a loaded class object
+//
+// Interface: Init
+// CanExit
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CLoadedClassEntry : public CDoubleLink
+{
+public:
+ // Initialize empty object
+ CLoadedClassEntry(void);
+
+ // Free registration
+ ~CLoadedClassEntry(void);
+
+ // Process command line for class
+ BOOL Init(
+ LPSTR& pszCmdLine,
+ LPFNGETCLASSOBJECT lpfngetclassobject);
+
+ // Indicates whether this class object can exit.
+ BOOL CanExit(void);
+
+private:
+
+ // Class factory for the class. We use this to
+ // determine whether the class object has been
+ // AddRef'd which implies that the
+ IUnknown * _punk;
+
+ ULONG _dwRegistration;
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLoadedClassEntry::CLoadedClassEntry
+//
+// Synopsis: Initialize empty loaded class object
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CLoadedClassEntry::CLoadedClassEntry(void)
+ : _punk(NULL), _dwRegistration(0)
+{
+ // Header does all the work
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLoadedClassEntry::~CLoadedClassEntry
+//
+// Synopsis: Revoke class object
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CLoadedClassEntry::~CLoadedClassEntry(void)
+{
+ if (_dwRegistration)
+ {
+#if DBG == 1
+ SCODE sc =
+#endif // DBG == 1
+
+ CoRevokeClassObject(_dwRegistration);
+ Win4Assert(SUCCEEDED(sc) && "Revoke of class object failed!");
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLoadedClassEntry::CanExit
+//
+// Synopsis: Figure out whether it is ok to exit the server
+//
+// Returns: TRUE - it is ok to exit
+// FALSE - class needs server to continue running
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+ // Indicates whether this class object can exit.
+BOOL CLoadedClassEntry::CanExit(void)
+{
+ _punk->AddRef();
+ ULONG ulRefs = _punk->Release();
+
+ return (ulRefs == 1) ? TRUE : FALSE;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CLoadedClassList
+//
+// Purpose: Keep a list of class objects for a DLL.
+//
+// Interface: Init
+// CanExit
+//
+// History: 12-Jul-93 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+class CLoadedClassList : public CDoubleList
+{
+public:
+ // Free all items in list on destruction
+ ~CLoadedClassList(void);
+
+ // Process command line for class
+ BOOL Init(LPSTR& pszCmdLine,
+ LPFNGETCLASSOBJECT lpfngetclassobject);
+
+ // Indicates whether this class object can exit.
+ BOOL CanExit(void);
+
+private:
+
+ // Base class provides all necessary data.
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CLoadedClassEntryIter
+//
+// Purpose: Provide iterator for a list of CLoadedClassEntry
+//
+// Interface: operator->
+// GetEntry
+//
+// History: 12-Jul-93 Ricksa Created
+//
+// Notes: See DlinkListIter definition at beginning of this file
+// for details of class definition.
+//
+//--------------------------------------------------------------------------
+DlinkListIter(CLoadedClassEntry)
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDll
+//
+// Purpose: Abstract the class dll
+//
+// Interface: Init
+// GetDllGetClassObjectAddress
+//
+// History: 12-Jul-93 Ricksa Created
+//
+// Notes: This really exists so we can guarantee that the DLL is
+// not unloaded before all the class objects are revoked.
+//
+//--------------------------------------------------------------------------
+class CDll
+{
+public:
+ // Create the empty object
+ CDll(void);
+
+ // Initialize the class object
+ BOOL Init(char *pszPath);
+
+ // Get the entry point for creating class objects
+ LPFNGETCLASSOBJECT GetDllGetClassObjectAddress(void);
+
+private:
+
+ // Handle to DLL
+ HINSTANCE _hLib;
+
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDll::CDll
+//
+// Synopsis: Initialize an unloaded DLL object
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CDll::CDll(void) : _hLib(NULL)
+{
+ // Header does the work
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDll::Init
+//
+// Synopsis: Load the library.
+//
+// Arguments: [pszPath] - path to dll
+//
+// Returns: TRUE - load succeeded
+// FALSE - load failed
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CDll::Init(char *pszPath)
+{
+ // Load library
+ return ((_hLib = LoadLibraryA(pszPath)) != NULL);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDll::GetDllGetClassObjectAddress
+//
+// Synopsis: Get the entry point for creation of class objects
+//
+// Returns: Entry point for creation of class objects
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+LPFNGETCLASSOBJECT CDll::GetDllGetClassObjectAddress(void)
+{
+ return (LPFNGETCLASSOBJECT) GetProcAddress(_hLib, "DllGetClassObject");
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDllEntry
+//
+// Purpose: Provide an object which controls a DLL
+//
+// Interface: Init
+// CanExit
+//
+// History: 12-Jul-93 Ricksa Created
+//
+// Notes: Default constructor and destructor are used since
+// sub-objects do all that work.
+//
+//--------------------------------------------------------------------------
+class CDllEntry : public CDoubleLink
+{
+public:
+ // Process command line
+ BOOL Init(LPSTR& pszCmdLine);
+
+ // Whether
+ BOOL CanExit(void);
+
+private:
+
+ // List of classes implemented by DLL.
+ CLoadedClassList _clslist;
+
+ // Object that abstracts the DLL
+ CDll _dll;
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDllEntry::CanExit
+//
+// Synopsis: Whether all classes in the DLL think it can exit.
+//
+// Returns: TRUE - yes all classes think it is ok to exit
+// FALSE - no it is not ok to exit.
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CDllEntry::CanExit(void)
+{
+ return _clslist.CanExit();
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDllEntryIter
+//
+// Purpose: Allow list of CDllEntrys to be enumerated
+//
+// Interface: operator->
+// GetEntry
+//
+// History: 12-Jul-93 Ricksa Created
+//
+// Notes: See definition of DlinkListIter at beginning of this file.
+//
+//--------------------------------------------------------------------------
+DlinkListIter(CDllEntry)
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CLoadedClassTable
+//
+// Purpose: Provides list of all class objects used by surrogat
+//
+// Interface: LoadClassObjects
+// CanExit
+// RevokeClasses
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CLoadedClassTable : public CDoubleList
+{
+public:
+
+ BOOL LoadClassObjects(char *pszCmdLine);
+
+ BOOL CanExit(void);
+
+ void RevokeClasses(void);
+
+private:
+
+ // Base class provides all necessary data
+
+};
+
+#endif // __LOADCLS_HXX__
diff --git a/private/ole32/com/surrogat/makefile b/private/ole32/com/surrogat/makefile
new file mode 100644
index 000000000..811b6b49f
--- /dev/null
+++ b/private/ole32/com/surrogat/makefile
@@ -0,0 +1,18 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+!include $(NTMAKEENV)\makefile.def
+
+!else # NTMAKEENV
+
+!include $(CAIROLE)\com\makefile
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/com/surrogat/oleinit.hxx b/private/ole32/com/surrogat/oleinit.hxx
new file mode 100644
index 000000000..528a237bb
--- /dev/null
+++ b/private/ole32/com/surrogat/oleinit.hxx
@@ -0,0 +1,85 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: oleinit.hxx
+//
+// Contents: class to make OleInitialize/Uninitialize more convenient
+//
+// Classes: COleInit
+//
+// Functions: COleInit::COleInit
+// COleInit::~COleInit
+//
+// History: 20-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __OLEINIT_HXX__
+#define __OLEINIT_HXX__
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: COleInit
+//
+// Purpose: class to make OleInitialize/Uninitialize more convenient
+//
+// History: 20-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class COleInit
+{
+public:
+ COleInit(void);
+
+ ~COleInit(void);
+private:
+
+ // No private data
+};
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: COleInit::COleInit
+//
+// Synopsis: Call OleInitialize
+//
+// History: 20-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline COleInit::COleInit(void)
+{
+ HRESULT hr = OleInitialize(NULL);
+
+ if (HR_FAILED(hr))
+ {
+ THROW(CException(0));
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: COleInit::~COleInit
+//
+// Synopsis: Call OleUninitialize
+//
+// History: 20-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline COleInit::~COleInit(void)
+{
+ // Do the clean up
+ OleUninitialize();
+}
+
+#endif // __OLEINIT_HXX__
diff --git a/private/ole32/com/surrogat/surrogat.cxx b/private/ole32/com/surrogat/surrogat.cxx
new file mode 100644
index 000000000..4cc58b317
--- /dev/null
+++ b/private/ole32/com/surrogat/surrogat.cxx
@@ -0,0 +1,427 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: surrogat.cxx
+//
+// Contents: Main driver for surrogat process for loading DLLs in a
+// process external to client requesting bind.
+//
+// Classes: CShutdown
+//
+// Functions: CShutdown::CShutdown
+// CShutdown::CreateTimer
+// CShutdown::DeleteTimer
+// CShutdown::CanShutdown
+// SurrogatWndProc
+// CreateSurrogatWindow
+// MessagePump
+// WinMain
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <windows.h>
+#include <ole2.h>
+#include <olecom.h>
+#include "oleinit.hxx"
+#include "loadcls.hxx"
+
+
+STDAPI_(BOOL) RemConnectionsExist(void);
+
+DECLARE_INFOLEVEL(Cairole)
+
+// Name of window class
+const WCHAR *wszSurrogatClassName = L"Surrogate";
+
+// Timer constants
+const UINT SHUTDOWN_TIMER = 1;
+const UINT SHUTDOWN_CHECK_TIME = 60000;
+
+// Number of times to sample
+const int _cMaxSamples = 5;
+
+// Indicate surrogat died with unexpected error
+const UINT SURROGAT_DISASTER_EXIT = 0xFFFFFFFF;
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CShutdown
+//
+// Purpose: Used to compute when to shutdown surrogat
+//
+// Interface: CreateTimer
+// DeleteTimer
+// CanShutdown
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CShutdown
+{
+public:
+ CShutdown(void);
+
+ void CreateTimer(HWND hwnd);
+
+ void DeleteTimer(void);
+
+ void CanShutdown(void);
+
+private:
+
+ HWND _hwnd;
+
+ int _cSamplesNoConnections;
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CShutdown::CShutdown
+//
+// Synopsis: Initializes shutdown object
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CShutdown::CShutdown(void) : _cSamplesNoConnections(0)
+{
+ // Header does the work.
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CShutdown::CreateTimer
+//
+// Synopsis: Initializes timer used by shutdown processing
+//
+// History: 15-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CShutdown::CreateTimer(HWND hwnd)
+{
+ _hwnd = hwnd;
+
+ UINT uRes = SetTimer(_hwnd, SHUTDOWN_TIMER, SHUTDOWN_CHECK_TIME, NULL);
+
+ Win4Assert((uRes != 0) && "Timer creation failed");
+
+ if (uRes == 0)
+ {
+ // Timer creation failed. It is extremely hard to imagine
+ // how this could occur. It would probably be a situation
+ // where we are very close to the limits of virtual memory
+ // in the system. In any case, we can do nothing but die and
+ // wait for the SCM to notice we are dead.
+ ExitProcess(SURROGAT_DISASTER_EXIT);
+ }
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CShutdown::DeleteTimer
+//
+// Synopsis: Removes timer used by shutdown processing
+//
+// History: 15-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CShutdown::DeleteTimer(void)
+{
+#if DBG == 1
+ // The result of KillTimer is really a don't care situation
+ // since the process will be exiting but during debugging we
+ // want to know when this fails.
+ BOOL fKillTimerSucceeded =
+#endif // DBG == 1
+
+ KillTimer(_hwnd, SHUTDOWN_TIMER);
+
+ Win4Assert(fKillTimerSucceeded && "Kill Timer Failed");
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CShutdown::CanShutdown
+//
+// Synopsis: Determine whether it is time for surrogat to shutdown.
+//
+// Algorithm: If we determine that there are currently connections
+// to surrogat, we reset out count of periods of no connections.
+// Otherwise, we bump the count and see whether this exceeds
+// the maximum. If the maximum is exceeded we post a quit
+// message for the window.
+//
+// History: 12-Jul-93 Ricksa Created
+//
+// Notes: This returns its value by posting a quit message to
+// the window which will in turn shutdown surrogat.
+//
+//--------------------------------------------------------------------------
+inline void CShutdown::CanShutdown(void)
+{
+ // Are there any connections?
+ SCODE sc = RemConnectionsExist();
+
+ if (sc != S_FALSE)
+ {
+ // Yes reset the connection count
+ _cSamplesNoConnections = 0;
+ }
+ else
+ {
+ // We exceeded the maximum number time periods without
+ // finding a connection so we are ready to stop.
+ if (++_cSamplesNoConnections > _cMaxSamples)
+ {
+ CairoleDebugOut((DEB_TRACE, "Shutting down\n"));
+ PostQuitMessage(0);
+ }
+ }
+}
+
+// Global object used to determine when surrogat shuts down
+CShutdown g_SurrogatShutdown;
+
+// Global object for classes stored in DLLs.
+CLoadedClassTable g_SurrogatClasses;
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: SurrogatWndProc
+//
+// Synopsis: Process messages to the surrogat window.
+//
+// Arguments: [hWnd] - window handle
+// [message] - message to the window
+// [wParam] - wParam for message
+// [lParam] - lParam for message.
+//
+// Returns: 0
+//
+// Algorithm: On window create this sets up a timer. The only messages
+// that should really come to this window are timer messages
+// which are passed to the timer object for determination
+// as to whether the server should stop or not.
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+long SurrogatWndProc(
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_CREATE:
+
+ g_SurrogatShutdown.CreateTimer(hWnd);
+ break;
+
+ case WM_TIMER:
+ // Check if shutdown is possible
+ g_SurrogatShutdown.CanShutdown();
+ break;
+
+ case WM_CLOSE:
+
+ g_SurrogatShutdown.DeleteTimer();
+ break;
+
+ default:
+
+ // Default actions for all other messages.
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+
+ return 0;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateSurrogatWindow
+//
+// Synopsis: Creates window used by shutdown logic.
+//
+// Arguments: [hInstance] - handle to process.
+//
+// Returns: [TRUE] - window was created successfully
+// [FALSE] - window creation failed
+//
+// Algorithm: First register window class and then create the invisible
+// window.
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CreateSurrogatWindow(HINSTANCE hInstance)
+{
+ WNDCLASS wc;
+ HWND hWnd; // Main window handle.
+
+ /* Fill in window class structure with parameters that describe the */
+ /* main window. */
+
+ wc.style = 0;
+ wc.lpfnWndProc = SurrogatWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInstance;
+ wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = wszSurrogatClassName;
+
+ /* Register the window class and return success/failure code. */
+ if (!RegisterClass(&wc))
+ {
+ return FALSE;
+ }
+
+ // Create a main window for this application instance.
+ hWnd = CreateWindow(
+ wszSurrogatClassName,
+ wszSurrogatClassName,
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ NULL,
+ NULL,
+ hInstance,
+ NULL
+ );
+
+ // If window could not be created, return "failure"
+
+ return (hWnd) ? TRUE : FALSE;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: MessagePump
+//
+// Synopsis: Process messages and pass them on to appropriate window.
+//
+// Returns: wParam from quite message.
+//
+// Algorithm: Get the message and translate it and pass it on.
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+int MessagePump(void)
+{
+ MSG msg;
+
+ while(GetMessage(&msg, NULL, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ return msg.wParam;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: WinMain
+//
+// Synopsis: Main driver for surrogat
+//
+// Arguments: [hinst] - handle to process
+// [hinstPrev] - handle to previous instance
+// [pszCmdLine] - command line for the process
+// [nCmdShow] - how to show the main window
+//
+// Returns: Whatever was in quit message
+//
+// Algorithm: This creates the windows for the surrogat shotdown
+// processing first. Then the command line is parsed to
+// get classes and DLLs supported by this surrogat. The
+// classes are then registered and the message pump
+// kicks in. Finally, when a quit message is recieved
+// all registered classes are revoked and the process
+// exits.
+//
+// History: 12-Jul-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+int WINAPI WinMain(
+ HINSTANCE hinst,
+ HINSTANCE hinstPrev,
+ char *pszCmdLine,
+ int nCmdShow)
+{
+ CairoleInfoLevel = 0xFFFFFFFF;
+
+ CairoleDebugOut((DEB_TRACE, "Command Line: %s\n", pszCmdLine));
+
+ // Create a hidden window that messages can be sent to particualarly
+ // quit and timer messages.
+ // BUGBUG: What should we do if this fails in the retail product?
+
+#if DBG == 1
+ BOOL fResult =
+#endif // DBG == 1
+
+ CreateSurrogatWindow(hinst);
+
+ Win4Assert(fResult && "Surrogate window creation failed");
+
+ // Call OleInitalize so classes don't have to.
+ COleInit oleinit;
+
+ // Load the list of classes and DLLs provided by the service
+ // controller at startup and register classes objects with compobj.
+#if DBG == 1
+ fResult =
+#endif // DBG == 1
+
+ g_SurrogatClasses.LoadClassObjects(pszCmdLine);
+
+ Win4Assert(fResult && "LoadClassObjects failed");
+
+ // Create a message pump
+ int retval = MessagePump();
+
+ // Deregister class objects
+ g_SurrogatClasses.RevokeClasses();
+
+ return retval;
+}
diff --git a/private/ole32/com/util/daytona/makefile b/private/ole32/com/util/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/util/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/util/daytona/sources b/private/ole32/com/util/daytona/sources
new file mode 100644
index 000000000..9ab04058d
--- /dev/null
+++ b/private/ole32/com/util/daytona/sources
@@ -0,0 +1,73 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= util
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..;..\..\..\common\daytona;..\..\..\ih;..\..\inc;..\..\..\common
+INCLUDES = $(INCLUDES);..\..\dcomidl\daytona;..\..\class;..\..\objact;
+INCLUDES = $(INCLUDES);$(BASEDIR)\private\dcomidl\obj
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -D_TRACKLINK_=1
+
+SOURCES= \
+ ..\spyclnt.cxx \
+ ..\olespy.cxx \
+ ..\time.cxx \
+ ..\w32new.cxx \
+ ..\info.cxx \
+ ..\exports.cxx \
+ ..\task.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
diff --git a/private/ole32/com/util/dirs b/private/ole32/com/util/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/com/util/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/com/util/exports.cxx b/private/ole32/com/util/exports.cxx
new file mode 100644
index 000000000..e48c67c65
--- /dev/null
+++ b/private/ole32/com/util/exports.cxx
@@ -0,0 +1,793 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: exports.cxx
+//
+//
+// History: 20-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+#pragma hdrstop
+
+#if DBG==1
+
+const char *g_pscExportNames[] =
+{
+ "CoInitialize"
+, "CoUninitialize"
+, "CoGetClassObject"
+, "CoRegisterClassObject"
+, "CoRevokeClassObject"
+, "CoMarshalInterface"
+, "CoUnmarshalInterface"
+, "CoReleaseMarshalData"
+, "CoDisconnectObject"
+, "CoLockObjectExternal"
+, "CoGetStandardMarshal"
+, "CoIsHandlerConnected"
+, "CoFreeAllLibraries"
+, "CoFreeUnusedLibraries"
+, "CoCreateInstance"
+, "CLSIDFromString"
+, "CoIsOle1Class"
+, "ProgIDFromCLSID"
+, "CLSIDFromProgID"
+, "CoCreateGuid"
+, "CoFileTimeToDosDateTime"
+, "CoDosDateTimeToFileTime"
+, "CoFileTimeNow"
+, "CoRegisterMessageFilter"
+, "CoGetTreatAsClass"
+, "CoTreatAsClass"
+, "DllGetClassObject"
+, "StgCreateDocfile"
+, "StgCreateDocfileOnILockBytes"
+, "StgOpenStorage"
+, "StgOpenStorageOnILockBytes"
+, "StgIsStorageFile"
+, "StgIsStorageILockBytes"
+, "StgSetTimes"
+, "CreateDataAdviseHolder"
+, "CreateDataCache"
+, "BindMoniker"
+, "MkParseDisplayName"
+, "MonikerRelativePathTo"
+, "MonikerCommonPrefixWith"
+, "CreateBindCtx"
+, "CreateGenericComposite"
+, "GetClassFile"
+, "CreateFileMoniker"
+, "CreateItemMoniker"
+, "CreateAntiMoniker"
+, "CreatePointerMoniker"
+, "GetRunningObjectTable"
+, "ReadClassStg"
+, "WriteClassStg"
+, "ReadClassStm"
+, "WriteClassStm"
+, "WriteFmtUserTypeStg"
+, "ReadFmtUserTypeStg"
+, "OleInitialize"
+, "OleUninitialize"
+, "OleQueryLinkFromData"
+, "OleQueryCreateFromData"
+, "OleCreate"
+, "OleCreateFromData"
+, "OleCreateLinkFromData"
+, "OleCreateStaticFromData"
+, "OleCreateLink"
+, "OleCreateLinkToFile"
+, "OleCreateFromFile"
+, "OleLoad"
+, "OleSave"
+, "OleLoadFromStream"
+, "OleSaveToStream"
+, "OleSetContainedObject"
+, "OleNoteObjectVisible"
+, "RegisterDragDrop"
+, "RevokeDragDrop"
+, "DoDragDrop"
+, "OleSetClipboard"
+, "OleGetClipboard"
+, "OleFlushClipboard"
+, "OleIsCurrentClipboard"
+, "OleCreateMenuDescriptor"
+, "OleSetMenuDescriptor"
+, "OleDestroyMenuDescriptor"
+, "OleDraw"
+, "OleRun"
+, "OleIsRunning"
+, "OleLockRunning"
+, "CreateOleAdviseHolder"
+, "OleCreateDefaultHandler"
+, "OleCreateEmbeddingHelper"
+, "OleRegGetUserType"
+, "OleRegGetMiscStatus"
+, "OleRegEnumFormatEtc"
+, "OleRegEnumVerbs"
+, "OleConvertIStorageToOLESTREAM"
+, "OleConvertOLESTREAMToIStorage"
+, "OleConvertIStorageToOLESTREAMEx"
+, "OleConvertOLESTREAMToIStorageEx"
+, "OleDoAutoConvert"
+, "OleGetAutoConvert"
+, "OleSetAutoConvert"
+, "GetConvertStg"
+, "SetConvertStg"
+, "ReadOleStg"
+, "WriteOleStg"
+, "CoGetCallerTID"
+, "CoGetState"
+, "CoSetState"
+, "CoMarshalHresult"
+, "CoUnmarshalHresult"
+, "CoGetCurrentLogicalThreadId"
+, "CoGetPSClsid"
+, "CoMarshalInterThreadInterfaceInStream"
+, "IIDFromString"
+, "StringFromCLSID"
+, "StringFromIID"
+, "StringFromGUID2"
+, "CoBuildVersion"
+, "CoGetMalloc"
+, "CoInitializeWOW"
+, "CoUnloadingWOW"
+, "CoTaskMemAlloc"
+, "CoTaskMemFree"
+, "CoTaskMemRealloc"
+, "CoFreeLibrary"
+, "CoLoadLibrary"
+, "CoCreateFreeThreadedMarshaler"
+, "OleInitializeWOW"
+, "OleDuplicateData"
+, "OleGetIconOfFile"
+, "OleGetIconOfClass"
+, "OleMetafilePictFromIconAndLabel"
+, "OleTranslateAccelerator"
+, "ReleaseStgMedium"
+, "ReadStringStream"
+, "WriteStringStream"
+, "OpenOrCreateStream"
+, "IsAccelerator"
+, "CreateILockBytesOnHGlobal"
+, "GetHGlobalFromILockBytes"
+, "SetDocumentBitStg"
+, "GetDocumentBitStg"
+, "CreateStreamOnHGlobal"
+, "GetHGlobalFromStream"
+, "CoGetInterfaceAndReleaseStream"
+, "CoGetCurrentProcess"
+, "CoQueryReleaseObject"
+, "CoRegisterMallocSpy"
+, "CoRevokeMallocSpy"
+, "CoGetMarshalSizeMax"
+, "CoGetObject"
+, "CreateClassMoniker"
+};
+
+const char *g_pscInterfaceNames[] =
+{
+ "API",
+ "IUnknown",
+ "IClassFactory",
+ "IMarshal"
+};
+
+const char *g_pscIUnknownNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+};
+const char *g_pscIClassFactoryNames[] =
+{
+ "CreateInstance"
+, "LockServer"
+};
+const char *g_pscIMarshalNames[] =
+{
+ "GetUnmarshalClass"
+, "GetMarshalSizeMax"
+, "MarshalInterface"
+, "UnmarshalInterface"
+, "ReleaseMarshalData"
+, "DisconnectObject"
+};
+
+const char *g_pscIStdMarshalInfoNames[] =
+{
+ "GetClassForHandler"
+};
+
+const char *g_pscIMessageFilterNames[] =
+{
+ "HandleInComingCall"
+, "RetryRejectedCall"
+, "MessagePending"
+};
+
+const char *g_pscIExternalConnectionNames[] =
+{
+ "AddConnection"
+, "ReleaseConnection"
+};
+
+const char *g_pscIEnumStringNames[] =
+{
+ "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+
+const char *g_pscIEnumUnknownNames[] =
+{
+ "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+
+const char *g_pscIEnumSTATSTGNames[] =
+{
+ "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+
+const char *g_pscILockBytesNames[] =
+{
+ "ReadAt"
+, "WriteAt"
+, "Flush"
+, "SetSize"
+, "LockRegion"
+, "UnlockRegion"
+, "Stat"
+};
+
+const char *g_pscIStreamNames[] =
+{
+ "Read"
+, "Write"
+, "Seek"
+, "SetSize"
+, "CopyTo"
+, "Commit"
+, "Revert"
+, "LockRegion"
+, "UnlockRegion"
+, "Stat"
+, "Clone"
+};
+
+const char *g_pscIStorageNames[] =
+{
+ "CreateStream"
+, "OpenStream"
+, "CreateStorage"
+, "OpenStorage"
+, "CopyTo"
+, "MoveElementTo"
+, "Commit"
+, "Revert"
+, "EnumElements"
+, "DestroyElement"
+, "RenameElement"
+, "SetElementTimes"
+, "SetClass"
+, "SetStateBits"
+, "Stat"
+};
+
+const char *g_pscIRootStorageNames[] =
+{
+ "SwitchToFile"
+};
+
+const char *g_pscIEnumFORMATETCNames[] =
+{
+ "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+
+const char *g_pscIEnumSTATDATANames[] =
+{
+ "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+
+const char *g_pscIDataObjectNames[] =
+{
+ "GetData"
+, "GetDataHere"
+, "QueryGetData"
+, "GetCanonicalFormatEtc"
+, "SetData"
+, "EnumFormatEtc"
+, "DAdvise"
+, "DUnadvise"
+, "EnumDAdvise"
+};
+
+const char *g_pscIViewObjectNames[] =
+{
+ "Draw"
+, "GetColorSet"
+, "Freeze"
+, "Unfreeze"
+, "SetAdvise"
+, "GetAdvise"
+};
+
+const char *g_pscIViewObject2Names[] =
+{
+ "Draw"
+, "GetColorSet"
+, "Freeze"
+, "Unfreeze"
+, "SetAdvise"
+, "GetAdvise"
+, "GetExtent"
+};
+
+const char *g_pscIAdviseSinkNames[] =
+{
+ "OnDataChange"
+, "OnViewChange"
+, "OnRename"
+, "OnSave"
+, "OnClose"
+};
+
+const char *g_pscIAdviseSink2Names[] =
+{
+ "OnDataChange"
+, "OnViewChange"
+, "OnRename"
+, "OnSave"
+, "OnClose"
+, "OnLinkSrcChange"
+};
+
+const char *g_pscIDataAdviseHolderNames[] =
+{
+ "Advise"
+, "Unadvise"
+, "EnumAdvise"
+, "SendOnDataChange"
+};
+
+const char *g_pscIOleCacheNames[] =
+{
+ "Cache"
+, "Uncache"
+, "EnumCache"
+, "InitCache"
+, "SetData"
+};
+
+const char *g_pscIOleCache2Names[] =
+{
+ "Cache"
+, "Uncache"
+, "EnumCache"
+, "InitCache"
+, "SetData"
+, "UpdateCache"
+, "DiscardCache"
+};
+
+const char *g_pscIOleCacheControlNames[] =
+{
+ "OnRun"
+, "OnStop"
+};
+
+const char *g_pscIDropTargetNames[] =
+{
+ "DragEnter"
+, "DragOver"
+, "DragLeave"
+, "Drop"
+};
+
+const char *g_pscIDropSourceNames[] =
+{
+ "QueryContinueDrag"
+, "GiveFeedback"
+};
+
+const char *g_pscIPersistNames[] =
+{
+ "GetClassID"
+};
+
+const char *g_pscIPersistStorageNames[] =
+{
+ "GetClassID"
+, "IsDirty"
+, "InitNew"
+, "Load"
+, "Save"
+, "SaveCompleted"
+, "HandsOffStorage"
+};
+
+const char *g_pscIPersistStreamNames[] =
+{
+ "GetClassID"
+, "IsDirty"
+, "Load"
+, "Save"
+, "GetSizeMax"
+};
+
+const char *g_pscIPersistFileNames[] =
+{
+ "GetClassID"
+, "IsDirty"
+, "Load"
+, "Save"
+, "SaveCompleted"
+, "GetCurFile"
+};
+
+const char *g_pscIBindCtxNames[] =
+{
+ "RegisterObjectBound"
+, "RevokeObjectBound"
+, "ReleaseBoundObjects"
+, "SetBindOptions"
+, "GetBindOptions"
+, "GetRunningObjectTable"
+, "RegisterObjectParam"
+, "GetObjectParam"
+, "EnumObjectParam"
+, "RevokeObjectParam"
+};
+
+const char *g_pscIMonikerNames[] =
+{
+ "GetClassID"
+, "IsDirty"
+, "Load"
+, "Save"
+, "GetSizeMax"
+, "BindToObject"
+, "BindToStorage"
+, "Reduce"
+, "ComposeWith"
+, "Enum"
+, "IsEqual"
+, "Hash"
+, "IsRunning"
+, "GetTimeOfLastChange"
+, "Inverse"
+, "CommonPrefixWith"
+, "RelativePathTo"
+, "GetDisplayName"
+, "ParseDisplayName"
+, "IsSystemMoniker"
+};
+
+const char *g_pscIRunningObjectTableNames[] =
+{
+ "Register"
+, "Revoke"
+, "IsRunning"
+, "GetObject"
+, "NoteChangeTime"
+, "GetTimeOfLastChange"
+, "EnumRunning"
+};
+
+const char *g_pscIEnumMonikerNames[] =
+{
+ "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+
+const char *g_pscIEnumOLEVERBNames[] =
+{
+ "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+
+const char *g_pscIOleObjectNames[] =
+{
+ "SetClientSite"
+, "GetClientSite"
+, "SetHostNames"
+, "Close"
+, "SetMoniker"
+, "GetMoniker"
+, "InitFromData"
+, "GetClipboardData"
+, "DoVerb"
+, "EnumVerbs"
+, "Update"
+, "IsUpToDate"
+, "GetUserClassID"
+, "GetUserType"
+, "SetExtent"
+, "GetExtent"
+, "Advise"
+, "Unadvise"
+, "EnumAdvise"
+, "GetMiscStatus"
+, "SetColorScheme"
+};
+
+const char *g_pscIOleClientSiteNames[] =
+{
+ "SaveObject"
+, "GetMoniker"
+, "GetContainer"
+, "ShowObject"
+, "OnShowWindow"
+, "RequestNewObjectLayout"
+};
+
+const char *g_pscIRunnableObjectNames[] =
+{
+ "GetRunningClass"
+, "Run"
+, "IsRunning"
+, "LockRunning"
+, "SetContainedObject"
+};
+
+const char *g_pscIParseDisplayNameNames[] =
+{
+ "ParseDisplayName"
+};
+
+const char *g_pscIOleContainerNames[] =
+{
+ "ParseDisplayName"
+, "EnumObjects"
+, "LockContainer"
+};
+
+const char *g_pscIOleItemContainerNames[] =
+{
+ "ParseDisplayName"
+, "EnumObjects"
+, "LockContainer"
+, "GetObject"
+, "GetObjectStorage"
+, "IsRunning"
+};
+
+const char *g_pscIOleAdviseHolderNames[] =
+{
+ "Advise"
+, "Unadvise"
+, "EnumAdvise"
+, "SendOnRename"
+, "SendOnSave"
+, "SendOnClose"
+};
+
+const char *g_pscIOleLinkNames[] =
+{
+ "SetUpdateOptions"
+, "GetUpdateOptions"
+, "SetSourceMoniker"
+, "GetSourceMoniker"
+, "SetSourceDisplayName"
+, "GetSourceDisplayName"
+, "BindToSource"
+, "BindIfRunning"
+, "GetBoundSource"
+, "UnbindSource"
+, "Update"
+};
+
+const char *g_pscIOleWindowNames[] =
+{
+ "GetWindow"
+, "ContextSensitiveHelp"
+};
+
+const char *g_pscIOleInPlaceObjectNames[] =
+{
+ "GetWindow"
+, "ContextSensitiveHelp"
+, "InPlaceDeactivate"
+, "UIDeactivate"
+, "SetObjectRects"
+, "ReactivateAndUndo"
+};
+
+const char *g_pscIOleInPlaceActiveObjectNames[] =
+{
+ "GetWindow"
+, "ContextSensitiveHelp"
+, "TranslateAccelerator"
+, "OnFrameWindowActivate"
+, "OnDocWindowActivate"
+, "ResizeBorder"
+, "EnableModeless"
+};
+
+const char *g_pscIOleInPlaceUIWindowNames[] =
+{
+ "GetWindow"
+, "ContextSensitiveHelp"
+, "GetBorder"
+, "RequestBorderSpace"
+, "SetBorderSpace"
+, "SetActiveObject"
+};
+
+const char *g_pscIOleInPlaceFrameNames[] =
+{
+ "GetWindow"
+, "ContextSensitiveHelp"
+, "GetBorder"
+, "RequestBorderSpace"
+, "SetBorderSpace"
+, "SetActiveObject"
+, "InsertMenus"
+, "SetMenu"
+, "RemoveMenus"
+, "SetStatusText"
+, "EnableModeless"
+, "TranslateAccelerator"
+};
+
+const char *g_pscIOleInPlaceSiteNames[] =
+{
+ "GetWindow"
+, "ContextSensitiveHelp"
+, "CanInPlaceActivate"
+, "OnInPlaceActivate"
+, "OnUIActivate"
+, "GetWindowContext"
+, "Scroll"
+, "OnUIDeactivate"
+, "OnInPlaceDeactivate"
+, "DiscardUndoState"
+, "DeactivateAndUndo"
+, "OnPosRectChange"
+};
+
+const char *g_pscIRpcChannelBufferNames[] =
+{
+ "GetBuffer"
+, "SendReceive"
+, "FreeBuffer"
+, "GetDestCtx"
+, "IsConnected"
+};
+
+const char *g_pscIRpcProxyBufferNames[] =
+{
+ "Connect"
+, "Disconnect"
+};
+
+const char *g_pscIRpcStubBufferNames[] =
+{
+ "Connect"
+, "Disconnect"
+, "Invoke"
+, "IsIIDSupported"
+, "CountRefs"
+, "DebugServerQueryInterface"
+, "DebugServerRelease"
+};
+
+const char *g_pscIPSFactoryBufferNames[] =
+{
+ "CreateProxy"
+, "CreateStub"
+};
+
+const char *g_pscIRpcChannelNames[] =
+{
+ "GetStream"
+, "Call"
+, "GetDestCtx"
+, "IsConnected"
+};
+
+const char *g_pscIRpcProxyNames[] =
+{
+ "Connect"
+, "Disconnect"
+};
+
+const char *g_pscIRpcStubNames[] =
+{
+ "Connect"
+, "Disconnect"
+, "Invoke"
+, "IsIIDSupported"
+, "CountRefs"
+};
+
+const char *g_pscIPSFactoryNames[] =
+{
+ "CreateProxy"
+, "CreateStub"
+};
+
+const char **g_ppNameTables[] =
+{
+ g_pscExportNames,
+ g_pscIUnknownNames,
+ g_pscIClassFactoryNames,
+ g_pscIMarshalNames,
+ g_pscIStdMarshalInfoNames,
+ g_pscIMessageFilterNames,
+ g_pscIExternalConnectionNames,
+ g_pscIEnumStringNames,
+ g_pscIEnumUnknownNames,
+ g_pscIEnumSTATSTGNames,
+ g_pscILockBytesNames,
+ g_pscIStreamNames,
+ g_pscIStorageNames,
+ g_pscIRootStorageNames,
+ g_pscIEnumFORMATETCNames,
+ g_pscIEnumSTATDATANames,
+ g_pscIDataObjectNames,
+ g_pscIViewObjectNames,
+ g_pscIViewObject2Names,
+ g_pscIAdviseSinkNames,
+ g_pscIAdviseSink2Names,
+ g_pscIDataAdviseHolderNames,
+ g_pscIOleCacheNames,
+ g_pscIOleCache2Names,
+ g_pscIOleCacheControlNames,
+ g_pscIDropTargetNames,
+ g_pscIDropSourceNames,
+ g_pscIPersistNames,
+ g_pscIPersistStorageNames,
+ g_pscIPersistStreamNames,
+ g_pscIPersistFileNames,
+ g_pscIBindCtxNames,
+ g_pscIMonikerNames,
+ g_pscIRunningObjectTableNames,
+ g_pscIEnumMonikerNames,
+ g_pscIEnumOLEVERBNames,
+ g_pscIOleObjectNames,
+ g_pscIOleClientSiteNames,
+ g_pscIRunnableObjectNames,
+ g_pscIParseDisplayNameNames,
+ g_pscIOleContainerNames,
+ g_pscIOleItemContainerNames,
+ g_pscIOleAdviseHolderNames,
+ g_pscIOleLinkNames,
+ g_pscIOleWindowNames,
+ g_pscIOleInPlaceObjectNames,
+ g_pscIOleInPlaceActiveObjectNames,
+ g_pscIOleInPlaceUIWindowNames,
+ g_pscIOleInPlaceFrameNames,
+ g_pscIOleInPlaceSiteNames,
+ g_pscIRpcChannelBufferNames,
+ g_pscIRpcProxyBufferNames,
+ g_pscIRpcStubBufferNames,
+ g_pscIPSFactoryBufferNames,
+ g_pscIRpcChannelNames,
+ g_pscIRpcProxyNames,
+ g_pscIRpcStubNames,
+ g_pscIPSFactoryNames
+};
+
+#endif // DBG==1
diff --git a/private/ole32/com/util/filelist.mk b/private/ole32/com/util/filelist.mk
new file mode 100644
index 000000000..6c8edd74d
--- /dev/null
+++ b/private/ole32/com/util/filelist.mk
@@ -0,0 +1,61 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = util.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES = .\utstream.cxx \
+ .\time.cxx \
+ .\utils.cxx \
+ .\w32new.cxx \
+ .\info.cxx \
+!if "$(OPSYS)" == "DOS" && "$(PLATFORM)" == "i386"
+ .\widewrap.cxx
+!endif
+
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PXXFILE = headers.cxx
+PFILE =
+
+
+CINC = $(CINC) -I..\inc $(LRPC) $(TRACELOG)
+
+MTHREAD = 1
+
+MULTIDEPEND = MERGED
diff --git a/private/ole32/com/util/ifnames.cxx b/private/ole32/com/util/ifnames.cxx
new file mode 100644
index 000000000..d3df9abd4
--- /dev/null
+++ b/private/ole32/com/util/ifnames.cxx
@@ -0,0 +1,886 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: IfNames.cxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 05-10-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+char *apszIUnknownNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+};
+char *apszIClassFactoryNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "CreateInstance"
+, "LockServer"
+};
+char *apszIMarshalNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetUnmarshalClass"
+, "GetMarshalSizeMax"
+, "MarshalInterface"
+, "UnmarshalInterface"
+, "ReleaseMarshalData"
+, "DisconnectObject"
+};
+char *apszIStdMarshalInfoNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassForHandler"
+};
+char *apszIMessageFilterNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "HandleInComingCall"
+, "RetryRejectedCall"
+, "MessagePending"
+};
+char *apszIExternalConnectionNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "AddConnection"
+, "ReleaseConnection"
+};
+char *apszIEnumStringNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIEnumUnknownNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIEnumSTATSTGNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszILockBytesNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "ReadAt"
+, "WriteAt"
+, "Flush"
+, "SetSize"
+, "LockRegion"
+, "UnlockRegion"
+, "Stat"
+};
+char *apszIStreamNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Read"
+, "Write"
+, "Seek"
+, "SetSize"
+, "CopyTo"
+, "Commit"
+, "Revert"
+, "LockRegion"
+, "UnlockRegion"
+, "Stat"
+, "Clone"
+};
+char *apszIStorageNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "CreateStream"
+, "OpenStream"
+, "CreateStorage"
+, "OpenStorage"
+, "CopyTo"
+, "MoveElementTo"
+, "Commit"
+, "Revert"
+, "EnumElements"
+, "DestroyElement"
+, "RenameElement"
+, "SetElementTimes"
+, "SetClass"
+, "SetStateBits"
+, "Stat"
+};
+char *apszIRootStorageNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "SwitchToFile"
+};
+char *apszIEnumFORMATETCNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIEnumSTATDATANames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIDataObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetData"
+, "GetDataHere"
+, "QueryGetData"
+, "GetCanonicalFormatEtc"
+, "SetData"
+, "EnumFormatEtc"
+, "DAdvise"
+, "DUnadvise"
+, "EnumDAdvise"
+};
+char *apszIViewObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Draw"
+, "GetColorSet"
+, "Freeze"
+, "Unfreeze"
+, "SetAdvise"
+, "GetAdvise"
+};
+char *apszIViewObject2Names[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Draw"
+, "GetColorSet"
+, "Freeze"
+, "Unfreeze"
+, "SetAdvise"
+, "GetAdvise"
+, "GetExtent"
+};
+char *apszIAdviseSinkNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "OnDataChange"
+, "OnViewChange"
+, "OnRename"
+, "OnSave"
+, "OnClose"
+};
+char *apszIAdviseSink2Names[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "OnDataChange"
+, "OnViewChange"
+, "OnRename"
+, "OnSave"
+, "OnClose"
+, "OnLinkSrcChange"
+};
+char *apszIDataAdviseHolderNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Advise"
+, "Unadvise"
+, "EnumAdvise"
+, "SendOnDataChange"
+};
+char *apszIOleCacheNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Cache"
+, "Uncache"
+, "EnumCache"
+, "InitCache"
+, "SetData"
+};
+char *apszIOleCache2Names[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Cache"
+, "Uncache"
+, "EnumCache"
+, "InitCache"
+, "SetData"
+, "UpdateCache"
+, "DiscardCache"
+};
+char *apszIOleCacheControlNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "OnRun"
+, "OnStop"
+};
+char *apszIDropTargetNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "DragEnter"
+, "DragOver"
+, "DragLeave"
+, "Drop"
+};
+char *apszIDropSourceNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "QueryContinueDrag"
+, "GiveFeedback"
+};
+char *apszIPersistNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+};
+char *apszIPersistStorageNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+, "IsDirty"
+, "InitNew"
+, "Load"
+, "Save"
+, "SaveCompleted"
+, "HandsOffStorage"
+};
+char *apszIPersistStreamNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+, "IsDirty"
+, "Load"
+, "Save"
+, "GetSizeMax"
+};
+char *apszIPersistFileNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+, "IsDirty"
+, "Load"
+, "Save"
+, "SaveCompleted"
+, "GetCurFile"
+};
+char *apszIBindCtxNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "RegisterObjectBound"
+, "RevokeObjectBound"
+, "ReleaseBoundObjects"
+, "SetBindOptions"
+, "GetBindOptions"
+, "GetRunningObjectTable"
+, "RegisterObjectParam"
+, "GetObjectParam"
+, "EnumObjectParam"
+, "RevokeObjectParam"
+};
+char *apszIMonikerNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+, "IsDirty"
+, "Load"
+, "Save"
+, "GetSizeMax"
+, "BindToObject"
+, "BindToStorage"
+, "Reduce"
+, "ComposeWith"
+, "Enum"
+, "IsEqual"
+, "Hash"
+, "IsRunning"
+, "GetTimeOfLastChange"
+, "Inverse"
+, "CommonPrefixWith"
+, "RelativePathTo"
+, "GetDisplayName"
+, "ParseDisplayName"
+, "IsSystemMoniker"
+};
+char *apszIRunningObjectTableNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Register"
+, "Revoke"
+, "IsRunning"
+, "GetObject"
+, "NoteChangeTime"
+, "GetTimeOfLastChange"
+, "EnumRunning"
+};
+char *apszIEnumMonikerNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIEnumOLEVERBNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIOleObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "SetClientSite"
+, "GetClientSite"
+, "SetHostNames"
+, "Close"
+, "SetMoniker"
+, "GetMoniker"
+, "InitFromData"
+, "GetClipboardData"
+, "DoVerb"
+, "EnumVerbs"
+, "Update"
+, "IsUpToDate"
+, "GetUserClassID"
+, "GetUserType"
+, "SetExtent"
+, "GetExtent"
+, "Advise"
+, "Unadvise"
+, "EnumAdvise"
+, "GetMiscStatus"
+, "SetColorScheme"
+};
+char *apszIOleClientSiteNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "SaveObject"
+, "GetMoniker"
+, "GetContainer"
+, "ShowObject"
+, "OnShowWindow"
+, "RequestNewObjectLayout"
+};
+char *apszIRunnableObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetRunningClass"
+, "Run"
+, "IsRunning"
+, "LockRunning"
+, "SetContainedObject"
+};
+char *apszIParseDisplayNameNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "ParseDisplayName"
+};
+char *apszIOleContainerNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "ParseDisplayName"
+, "EnumObjects"
+, "LockContainer"
+};
+char *apszIOleItemContainerNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "ParseDisplayName"
+, "EnumObjects"
+, "LockContainer"
+, "GetObject"
+, "GetObjectStorage"
+, "IsRunning"
+};
+char *apszIOleAdviseHolderNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Advise"
+, "Unadvise"
+, "EnumAdvise"
+, "SendOnRename"
+, "SendOnSave"
+, "SendOnClose"
+};
+char *apszIOleLinkNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "SetUpdateOptions"
+, "GetUpdateOptions"
+, "SetSourceMoniker"
+, "GetSourceMoniker"
+, "SetSourceDisplayName"
+, "GetSourceDisplayName"
+, "BindToSource"
+, "BindIfRunning"
+, "GetBoundSource"
+, "UnbindSource"
+, "Update"
+};
+char *apszIOleWindowNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+};
+char *apszIOleInPlaceObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "InPlaceDeactivate"
+, "UIDeactivate"
+, "SetObjectRects"
+, "ReactivateAndUndo"
+};
+char *apszIOleInPlaceActiveObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "TranslateAccelerator"
+, "OnFrameWindowActivate"
+, "OnDocWindowActivate"
+, "ResizeBorder"
+, "EnableModeless"
+};
+char *apszIOleInPlaceUIWindowNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "GetBorder"
+, "RequestBorderSpace"
+, "SetBorderSpace"
+, "SetActiveObject"
+};
+char *apszIOleInPlaceFrameNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "GetBorder"
+, "RequestBorderSpace"
+, "SetBorderSpace"
+, "SetActiveObject"
+, "InsertMenus"
+, "SetMenu"
+, "RemoveMenus"
+, "SetStatusText"
+, "EnableModeless"
+, "TranslateAccelerator"
+};
+char *apszIOleInPlaceSiteNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "CanInPlaceActivate"
+, "OnInPlaceActivate"
+, "OnUIActivate"
+, "GetWindowContext"
+, "Scroll"
+, "OnUIDeactivate"
+, "OnInPlaceDeactivate"
+, "DiscardUndoState"
+, "DeactivateAndUndo"
+, "OnPosRectChange"
+};
+char *apszIRpcChannelBufferNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetBuffer"
+, "SendReceive"
+, "FreeBuffer"
+, "GetDestCtx"
+, "IsConnected"
+};
+char *apszIRpcProxyBufferNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Connect"
+, "Disconnect"
+};
+char *apszIRpcStubBufferNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Connect"
+, "Disconnect"
+, "Invoke"
+, "IsIIDSupported"
+, "CountRefs"
+, "DebugServerQueryInterface"
+, "DebugServerRelease"
+};
+char *apszIPSFactoryBufferNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "CreateProxy"
+, "CreateStub"
+};
+char *apszIRpcChannelNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetStream"
+, "Call"
+, "GetDestCtx"
+, "IsConnected"
+};
+char *apszIRpcProxyNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Connect"
+, "Disconnect"
+};
+char *apszIRpcStubNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Connect"
+, "Disconnect"
+, "Invoke"
+, "IsIIDSupported"
+, "CountRefs"
+};
+char *apszIPSFactoryNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "CreateProxy"
+, "CreateStub"
+};
+
+char *apszIServerHandlerNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "RunAndInitialize"
+, "RunAndDoVerb"
+, "DoVerb"
+};
+
+char *apszIClientSiteHandlerNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "PrivQueryInterface"
+, "PrivAddRef"
+, "PrivRelease"
+, "SaveObject"
+, "GetMoniker"
+, "GetContainer"
+, "ShowObject"
+, "OnShowWindow"
+, "RequestNewObjectLayout"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "CanInPlaceActivate"
+, "OnInPlaceActivate"
+, "OnUIActivate"
+, "GetWindowContext"
+, "Scroll"
+, "OnUIDeactivate"
+, "OnInPlaceDeactivate"
+, "DiscardUndoState"
+, "DeactivateAndUndo"
+, "OnPosRectChange"
+, "StartInPlaceActivation"
+, "DoInPlace"
+, "UndoInPlace"
+};
+
+
+
+char *apszIRpcServiceNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "CheckContextHdl"
+, "GetChannelId"
+, "ReleaseChannel"
+, "DoChannelOperation"
+, "DoChnlOp_ADD_MARSHALCONNECTION"
+, "DoChnlOp_REMOVE_MARSHALCONNECTION"
+, "DoChnlOp_TRANSFER_MARSHALCONNECTION"
+, "DoChnlOp_LOCK_CONNECTION"
+, "DoChnlOp_UNLOCK_CONNECTION"
+, "DoChnlOp_DOESSUPPORTIID"
+, "DoChnlOp_OPERATION"
+};
+
+char *apszIRpcSCMNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassObject"
+, "CreateObject"
+, "ActivateObject"
+};
+
+char *apszIRpcCoAPINames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "CoGetActiveClassObject"
+, "CoActivateObject"
+, "CoCreateObject"
+};
+
+char *apszInterfaceFromWindowProp[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetInterfaceFromWindowProp"
+, "PrivDragDrop"
+};
+
+char *apszIDSCM[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "SCMGetClassObject"
+, "SCMCreateInstance"
+, "SCMGetPersistentInstance"
+};
+
+char *apszIObjServer[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "ObjectServerGetClassObject"
+, "ObjectServerCreateInstance"
+, "ObjectServerGetInstance"
+};
+char *apszIRemUnknown[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "RemQueryInterface"
+, "RemAddRef"
+, "RemRelease"
+};
+char *apszIRundown[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "RemQueryInterface"
+, "RemAddRef"
+, "RemRundownOid"
+};
+
+
+
+
+IIDMethodNames IidMethodNames[] =
+{
+ { &IID_IUnknown, "IUnknown", apszIUnknownNames }
+ ,{ &IID_IClassFactory, "IClassFactory", apszIClassFactoryNames }
+ ,{ &IID_IMarshal, "IMarshal", apszIMarshalNames }
+ ,{ &IID_IStdMarshalInfo, "IStdMarshalInfo", apszIStdMarshalInfoNames }
+ ,{ &IID_IMessageFilter, "IMessageFilter", apszIMessageFilterNames }
+ ,{ &IID_IExternalConnection, "IExternalConnection", apszIExternalConnectionNames }
+ ,{ &IID_IEnumString, "IEnumString", apszIEnumStringNames }
+ ,{ &IID_IEnumUnknown, "IEnumUnknown", apszIEnumUnknownNames }
+ ,{ &IID_IEnumSTATSTG, "IEnumSTATSTG", apszIEnumSTATSTGNames }
+ ,{ &IID_ILockBytes, "ILockBytes", apszILockBytesNames }
+ ,{ &IID_IStream, "IStream", apszIStreamNames }
+ ,{ &IID_IStorage, "IStorage", apszIStorageNames }
+ ,{ &IID_IRootStorage, "IRootStorage", apszIRootStorageNames }
+ ,{ &IID_IEnumFORMATETC, "IEnumFORMATETC", apszIEnumFORMATETCNames }
+ ,{ &IID_IEnumSTATDATA, "IEnumSTATDATA", apszIEnumSTATDATANames }
+ ,{ &IID_IDataObject, "IDataObject", apszIDataObjectNames }
+ ,{ &IID_IViewObject, "IViewObject", apszIViewObjectNames }
+ ,{ &IID_IViewObject2, "IViewObject2", apszIViewObject2Names }
+ ,{ &IID_IAdviseSink, "IAdviseSink", apszIAdviseSinkNames }
+ ,{ &IID_IAdviseSink2, "IAdviseSink2", apszIAdviseSink2Names }
+ ,{ &IID_IDataAdviseHolder, "IDataAdviseHolder", apszIDataAdviseHolderNames }
+ ,{ &IID_IOleCache, "IOleCache", apszIOleCacheNames }
+ ,{ &IID_IOleCache2, "IOleCache2", apszIOleCache2Names }
+ ,{ &IID_IOleCacheControl, "IOleCacheControl", apszIOleCacheControlNames }
+ ,{ &IID_IDropTarget, "IDropTarget", apszIDropTargetNames }
+ ,{ &IID_IDropSource, "IDropSource", apszIDropSourceNames }
+ ,{ &IID_IPersist, "IPersist", apszIPersistNames }
+ ,{ &IID_IPersistStorage, "IPersistStorage", apszIPersistStorageNames }
+ ,{ &IID_IPersistStream, "IPersistStream", apszIPersistStreamNames }
+ ,{ &IID_IPersistFile, "IPersistFile", apszIPersistFileNames }
+ ,{ &IID_IBindCtx, "IBindCtx", apszIBindCtxNames }
+ ,{ &IID_IMoniker, "IMoniker", apszIMonikerNames }
+ ,{ &IID_IRunningObjectTable, "IRunningObjectTable", apszIRunningObjectTableNames }
+ ,{ &IID_IEnumMoniker, "IEnumMoniker", apszIEnumMonikerNames }
+ ,{ &IID_IEnumOLEVERB, "IEnumOLEVERB", apszIEnumOLEVERBNames }
+ ,{ &IID_IOleObject, "IOleObject", apszIOleObjectNames }
+ ,{ &IID_IOleClientSite, "IOleClientSite", apszIOleClientSiteNames }
+ ,{ &IID_IRunnableObject, "IRunnableObject", apszIRunnableObjectNames }
+ ,{ &IID_IParseDisplayName, "IParseDisplayName", apszIParseDisplayNameNames }
+ ,{ &IID_IOleContainer, "IOleContainer", apszIOleContainerNames }
+ ,{ &IID_IOleItemContainer, "IOleItemContainer", apszIOleItemContainerNames }
+ ,{ &IID_IOleAdviseHolder, "IOleAdviseHolder", apszIOleAdviseHolderNames }
+ ,{ &IID_IOleLink, "IOleLink", apszIOleLinkNames }
+ ,{ &IID_IOleWindow, "IOleWindow", apszIOleWindowNames }
+ ,{ &IID_IOleInPlaceObject, "IOleInPlaceObject", apszIOleInPlaceObjectNames }
+ ,{ &IID_IOleInPlaceActiveObject,"IOleInPlaceActiveObject", apszIOleInPlaceActiveObjectNames }
+ ,{ &IID_IOleInPlaceUIWindow, "IOleInPlaceUIWindow", apszIOleInPlaceUIWindowNames }
+ ,{ &IID_IOleInPlaceFrame, "IOleInPlaceFrame", apszIOleInPlaceFrameNames }
+ ,{ &IID_IOleInPlaceSite, "IOleInPlaceSite", apszIOleInPlaceSiteNames }
+ ,{ &IID_IRpcChannelBuffer, "IRpcChannelBuffer", apszIRpcChannelBufferNames }
+ ,{ &IID_IRpcProxyBuffer, "IRpcProxyBuffer", apszIRpcProxyBufferNames }
+ ,{ &IID_IRpcStubBuffer, "IRpcStubBuffer", apszIRpcStubBufferNames }
+ ,{ &IID_IPSFactoryBuffer, "IPSFactoryBuffer", apszIPSFactoryBufferNames }
+ ,{ &IID_IRpcChannel, "IRpcChannel", apszIRpcChannelNames }
+ ,{ &IID_IRpcProxy, "IRpcProxy", apszIRpcProxyNames }
+ ,{ &IID_IRpcStub, "IRpcStub", apszIRpcStubNames }
+ ,{ &IID_IPSFactory, "IPSFactory", apszIPSFactoryNames }
+ ,{ &IID_IServerHandler, "IServerHandler", apszIServerHandlerNames }
+ ,{ &IID_IClientSiteHandler, "IClientSiteHandler", apszIClientSiteHandlerNames }
+ ,{ &IID_IRpcService, "IRpcService", apszIRpcServiceNames }
+ ,{ &IID_IRpcSCM, "IRpcSCM", apszIRpcSCMNames }
+ ,{ &IID_IRpcCoAPI, "IRpcCoAPI", apszIRpcCoAPINames }
+#ifdef DCOM
+ ,{ &IID_IInterfaceFromWindowProp,"InterfaceFromWindowProp", apszInterfaceFromWindowProp }
+ ,{ &IID_IDSCM, "IDSCM", apszIDSCM }
+ ,{ &IID_IObjServer, "IObjServer", apszIObjServer }
+ ,{ &IID_IRemUnknown, "IRemUnknown", apszIRemUnknown }
+ ,{ &IID_IRundown, "IRundown", apszIRundown }
+#endif
+};
+
diff --git a/private/ole32/com/util/info.cxx b/private/ole32/com/util/info.cxx
new file mode 100644
index 000000000..0f8cdfd7a
--- /dev/null
+++ b/private/ole32/com/util/info.cxx
@@ -0,0 +1,62 @@
+#include <ole2int.h>
+#include <debnot.h>
+#include <except.hxx>
+
+#ifdef CAIROLE_DOWNLEVEL
+
+// For downlevel do not define the down level debugging class stuff.
+#undef MAKE_CINFOLEVEL
+
+#define MAKE_CINFOLEVEL(comp)
+
+// BUGBUG: Temporary definitions of functions these probably can be removed
+// as they are probably obsolete.
+
+extern "C"
+{
+ EXPORTDEF void APINOT
+ RegisterWithCommnot(void);
+
+ EXPORTDEF void APINOT
+ DeRegisterWithCommnot(void);
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: RegisterWithCommnot
+//
+// Synopsis: Used by Cairo to work around DLL unloading problems
+//
+// Arguments: <none>
+//
+// History: 06-Oct-92 BryanT Created
+//
+//--------------------------------------------------------------------
+EXPORTIMP void APINOT
+RegisterWithCommnot( void )
+{
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: DeRegisterWithCommnot
+//
+// Synopsis: Used by Cairo to work around DLL unloading problems
+//
+// Arguments: <none>
+//
+// History: 06-Oct-92 BryanT Created
+//
+// Notes: BUGBUG: Keep in touch with BryanT to see if this is
+// obsolete.
+//
+//--------------------------------------------------------------------
+
+EXPORTIMP void APINOT
+DeRegisterWithCommnot( void )
+{
+}
+
+#endif
+
+DECLARE_INFOLEVEL(Cairole)
diff --git a/private/ole32/com/util/makefile b/private/ole32/com/util/makefile
new file mode 100644
index 000000000..e09078703
--- /dev/null
+++ b/private/ole32/com/util/makefile
@@ -0,0 +1,24 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+!include $(CAIROLE)\com\makefile
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/com/util/olespy.cxx b/private/ole32/com/util/olespy.cxx
new file mode 100644
index 000000000..3e9257e3e
--- /dev/null
+++ b/private/ole32/com/util/olespy.cxx
@@ -0,0 +1,582 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: rpcspy.cxx
+//
+// Contents: rpcspy functions
+//
+// Classes:
+//
+// Functions:
+//
+// History: 7-06-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+#include <ole2int.h>
+#pragma hdrstop
+#if DBG==1
+
+#include <smmutex.hxx>
+
+#ifdef DCOM
+#include <dscm.h>
+#include <getif.h>
+#include <objsrv.h>
+#include <remunk.h>
+#include <odeth.h>
+#endif // DCOM
+
+#include <outfuncs.h>
+
+#include "srvhdl.h"
+#include "OleSpy.hxx"
+#include "SpyClnt.hxx"
+
+#include <trace.hxx>
+
+void SetTraceInfoLevel(DWORD dwLevel);
+int OleSpySendEntry(char * szOutBuf);
+
+
+char szOutBuffer[2048];
+
+typedef enum
+{
+ OleSpy_None = 0
+ ,OleSpy_Rpc = 1
+ ,OleSpy_API = 2
+ ,OleSpy_Method = 4
+ ,OleSpy_OleThk = 8
+} OleSpy;
+
+// OleSpy output options
+typedef enum
+{
+ OleSpyOut_None = 0
+ ,OleSpyOut_Debugger = 1
+ ,OleSpyOut_OleSpy = 2
+} OleSpyOut;
+
+// interface to interface name and method mapping
+typedef struct _tagIIDMethodNames
+{
+ IID const *piid;
+ char *pszInterface;
+ char **ppszMethodNames;
+} IIDMethodNames;
+
+
+DWORD nInCount = 0;
+DWORD nOutCount = 0;
+
+DWORD OleSpyOpt = OleSpy_None;
+DWORD OleSpyOutput = OleSpyOut_None;
+DWORD OleSpyBreakForUnknownCalls = 0;
+
+
+// internal interfaces
+IID IID_IRpcService = {0x0000001aL, 0, 0};
+IID IID_IRpcSCM = {0x0000001bL, 0, 0};
+IID IID_IRpcCoAPI = {0x0000001cL, 0, 0};
+IID IID_IRpcDragDrop= {0x0000001dL, 0, 0};
+
+CHAR szSendBuf[OUT_BUF_SIZE] = ""; // Buffer used to modify message.
+IIDMethodNames *GetIIDMethodName(REFIID riid);
+
+//
+// switch on to trace rpc calls
+// by setting CairoleInfoLevel = DEB_USER1;
+//
+//
+#define NESTING_SPACES 32
+#define SPACES_PER_LEVEL 3
+static char achSpaces[NESTING_SPACES+1] = " ";
+WORD wlevel = 0;
+char tabs[128];
+
+//+---------------------------------------------------------------------------
+//
+// Method: PushLevel
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void PushLevel()
+{
+ wlevel++;
+}
+//+---------------------------------------------------------------------------
+//
+// Method: PopLevel
+//
+// Synopsis:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void PopLevel()
+{
+ if (wlevel)
+ wlevel--;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: NestingSpaces
+//
+// Synopsis:
+//
+// Arguments: [psz] --
+//
+// Returns:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void NestingSpaces(char *psz)
+{
+ int iSpaces, i;
+
+ iSpaces = wlevel * SPACES_PER_LEVEL;
+
+ while (iSpaces > 0)
+ {
+ i = min(iSpaces, NESTING_SPACES);
+ memcpy(psz, achSpaces, i);
+ psz += i;
+ *psz = 0;
+ iSpaces -= i;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: GetTabs
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+LPSTR GetTabs()
+{
+ static char ach[256];
+ char *psz;
+
+ wsprintfA(ach, "%2d:", wlevel);
+ psz = ach+strlen(ach);
+
+ if (sizeof(ach)/SPACES_PER_LEVEL <= wlevel)
+ {
+ strcpy(psz, "...");
+ }
+ else
+ {
+ NestingSpaces(psz);
+ }
+ return ach;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: UninitializeOleSpy
+//
+// Synopsis:
+//
+// Arguments: [dwLevel] --
+//
+// Returns:
+//
+// History: 11-22-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT UninitializeOleSpy(DWORD dwLevel)
+{
+ if (dwLevel == OLESPY_TRACE)
+ {
+ CleanupTraceInfo();
+ }
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: InitializeOleSpy
+//
+// Synopsis:
+//
+// Arguments: [dwReserved] --
+//
+// Returns:
+//
+// History: 11-18-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT InitializeOleSpy(DWORD dwLevel)
+{
+ CHAR szOleSpyInfo[] = "OleSpy";
+ CHAR szServerName[SERVERNAMEMAX] = ".";
+ CHAR *pszServerName = szServerName;
+ CHAR szValue[20];
+ DWORD cbValue = sizeof(szValue);
+ ULONG ulValue = 0x0003;
+
+ if (dwLevel == OLESPY_TRACE)
+ {
+ InitializeTraceInfo();
+ return NOERROR;
+ }
+
+ if (GetProfileStringA(szOleSpyInfo,"Output","",szServerName,SERVERNAMEMAX) )
+ {
+ // check if debugger was specified
+ if (_stricmp(szServerName, "debugger") == 0)
+ {
+ // output should go to the debugger
+ OleSpyOutput = OleSpyOut_Debugger;
+ AddOutputFunction((StringOutFunc) OutputDebugStringA);
+
+ }
+ else
+ {
+ pszServerName = szServerName;
+ // "." means OleSpy on local machine
+ // strip of the leading backslash
+ while(*pszServerName == '\\')
+ {
+ pszServerName++;
+ }
+ if (strlen(pszServerName))
+ {
+ OleSpyOutput = OleSpyOut_OleSpy;
+ AddOutputFunction((StringOutFunc) SendEntry);
+
+ }
+ }
+ }
+
+ if (OleSpyOutput == OleSpyOut_None)
+ {
+ // nothing to do
+ return NOERROR;
+ }
+
+ //
+ if (GetProfileStringA(szOleSpyInfo, "TraceRpc", "0x0000", szValue,cbValue))
+ {
+ ulValue = strtoul (szValue, NULL, 16);
+ if (ulValue)
+ {
+ OleSpyOpt |= OleSpy_Rpc;
+ }
+ }
+ if (GetProfileStringA(szOleSpyInfo, "TraceAPI", "0x0000", szValue,cbValue))
+ {
+ ulValue = strtoul (szValue, NULL, 16);
+ if (ulValue)
+ {
+ OleSpyOpt |= OleSpy_API;
+ SetTraceInfoLevel(ulValue);
+ }
+
+ }
+ if (GetProfileStringA(szOleSpyInfo, "TraceMethod", "0x0000", szValue,cbValue))
+ {
+ ulValue = strtoul (szValue, NULL, 16);
+ if (ulValue)
+ {
+ OleSpyOpt |= OleSpy_Method;
+ }
+ }
+ if (GetProfileStringA(szOleSpyInfo, "TraceOlethk", "0x0000", szValue,cbValue))
+ {
+ ulValue = strtoul (szValue, NULL, 16);
+ if (ulValue)
+ {
+ OleSpyOpt |= OleSpy_OleThk;
+ }
+ }
+
+ if (GetProfileStringA(szOleSpyInfo, "BreakForUnknownCalls", "0x0000", szValue,cbValue))
+ {
+ ulValue = strtoul (szValue, NULL, 16);
+ if (ulValue)
+ {
+ OleSpyBreakForUnknownCalls = 1;
+ }
+ }
+
+ if (OleSpyOutput == OleSpyOut_OleSpy)
+ {
+ // initialize client if output goes to OleSpy
+ InitClient(pszServerName);
+ }
+
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OutputToOleSpy
+//
+// Synopsis:
+//
+// Arguments: [iOption] --
+// [pscFormat] --
+//
+// Returns:
+//
+// History: 11-18-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void OutputToOleSpy(int iOption, const char *pscFormat, ...)
+{
+ va_list args;
+ va_start(args, pscFormat);
+ wvsprintfA(szOutBuffer, pscFormat, args);
+ va_end(args);
+
+ switch (OleSpyOutput)
+ {
+ default:
+ case OleSpyOut_None:
+ break;
+ case OleSpyOut_Debugger:
+ OutputDebugStringA(szSendBuf);
+
+ break;
+ case OleSpyOut_OleSpy:
+ SendEntry(szOutBuffer);
+ break;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: RpcSpyOutput
+//
+// Synopsis:
+//
+// Arguments: [mode] -- in or out call
+// [iid] -- interface id
+// [dwMethod] -- called method
+// [hres] -- hresult of finished call
+//
+// Returns:
+//
+// History: 3-31-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void RpcSpyOutput(RPCSPYMODE mode , LPVOID pv, REFIID iid, DWORD dwMethod, HRESULT hres)
+{
+ WCHAR wszName[100];
+
+ if(OleSpyOutput == OleSpyOut_None)
+ {
+ // nothing to do
+ return;
+ }
+
+ // turn of the 800xx in dwMethod
+ WORD wMethod = (WORD) (dwMethod & 0x000000FF);
+ char * szInterfaceName = "Unknown";
+ char * szMethodName = "Unknown";
+ IIDMethodNames *pIidMethName = 0;
+
+ if (pIidMethName = GetIIDMethodName(iid) )
+ {
+ szInterfaceName = pIidMethName->pszInterface;
+ if (wMethod > 32)
+ {
+ szMethodName = "InvalidMethod";
+ }
+ else
+ {
+ szMethodName = pIidMethName->ppszMethodNames[wMethod];
+ }
+ }
+ else
+ {
+ if (OleSpyBreakForUnknownCalls)
+ {
+ DebugBreak();
+ }
+ }
+
+ switch (mode)
+ {
+ default:
+ return;
+
+ case CALLIN_BEGIN:
+ wsprintfA(szSendBuf,"%4ld,%s<<< %s (%lx), %s \n",nInCount, GetTabs(), szInterfaceName, pv, szMethodName );
+ PushLevel();
+ nInCount++;
+ break;
+ case CALLIN_END:
+ PopLevel();
+ wsprintfA(szSendBuf,"%4ld,%s=== %s (%lx), %s (%lx) \n", nInCount-1, GetTabs(), szInterfaceName, pv, szMethodName, hres);
+ break;
+ case CALLIN_TRACE:
+ wsprintfA(szSendBuf," %s\n",(LPSTR) hres);
+ break;
+ case CALLIN_QI:
+ {
+ PopLevel();
+ wsprintfA(szSendBuf," %s!!! QI for: %s, %s (%lx) \n",GetTabs(), szInterfaceName, dwMethod ? "S_OK" : "E_NOINTERFACE", hres);
+ PushLevel();
+ }
+ break;
+ case CALLIN_ERROR:
+ break;
+ case CALLOUT_BEGIN:
+ wsprintfA(szSendBuf,"%4ld,%s>>> %s (%lx), %s \n",nOutCount, GetTabs(), szInterfaceName, pv, szMethodName );
+ nOutCount++;
+ PushLevel();
+ break;
+ case CALLOUT_TRACE:
+ break;
+ case CALLOUT_ERROR:
+ wsprintfA(szSendBuf,"%s!!! %s, %s, error:%lx \n",GetTabs(), szInterfaceName, szMethodName, hres);
+ break;
+ case CALLOUT_END:
+ PopLevel();
+ wsprintfA(szSendBuf,"%4ld,%s=== %s (%lx), %s (%lx) \n",nOutCount-1,GetTabs(), szInterfaceName, pv, szMethodName, hres);
+ break;
+ }
+
+ switch (OleSpyOutput)
+ {
+ default:
+ case OleSpyOut_None:
+ break;
+ case OleSpyOut_Debugger:
+ OutputDebugStringA(szSendBuf);
+ break;
+ case OleSpyOut_OleSpy:
+ SendEntry(szSendBuf);
+ break;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleSpySendEntry
+//
+// Synopsis:
+//
+// Arguments: [szOutBuf] --
+//
+// Returns:
+//
+// History: 09-22-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+int OleSpySendEntry(char * szOutBuf)
+{
+ switch (OleSpyOutput)
+ {
+ default:
+ case OleSpyOut_None:
+ break;
+ case OleSpyOut_Debugger:
+ OutputDebugStringA(szOutBuf);
+ break;
+ case OleSpyOut_OleSpy:
+ SendEntry(szOutBuf);
+ break;
+ }
+
+ return 1;
+}
+
+#include "ifnames.cxx"
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetIIDMethodName
+//
+// Synopsis:
+//
+// Arguments: [riid] --
+//
+// Returns:
+//
+// History: 06-18-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+IIDMethodNames *GetIIDMethodName(REFIID riid)
+{
+ int idx;
+ int cElements = sizeof(IidMethodNames) / sizeof(IidMethodNames[0]);
+
+ for (idx = 0; idx < cElements; idx++)
+ {
+ if (IsEqualIID(riid, *IidMethodNames[idx].piid))
+ {
+ return &(IidMethodNames[idx]);
+ }
+ }
+ return NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetInterfaceName
+//
+// Synopsis:
+//
+// Arguments: [iid] --
+//
+// Returns:
+//
+// History: 06-18-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+LPSTR GetInterfaceName(REFIID iid)
+{
+ IIDMethodNames *pIidMethName = 0;
+ LPSTR szInterfaceName = NULL;
+
+ if (pIidMethName = GetIIDMethodName(iid) )
+ {
+ szInterfaceName = pIidMethName->pszInterface;
+ }
+ if (szInterfaceName == NULL)
+ {
+ // look up the interface name in the registry
+ }
+
+ return szInterfaceName;
+}
+
+#endif // DBG==1
+
diff --git a/private/ole32/com/util/spyclnt.cxx b/private/ole32/com/util/spyclnt.cxx
new file mode 100644
index 000000000..5ebbf4d25
--- /dev/null
+++ b/private/ole32/com/util/spyclnt.cxx
@@ -0,0 +1,301 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: spyclnt.cxx
+//
+// Contents: Funktionality for OleSpy client.
+//
+// Classes:
+//
+// Functions:
+//
+// History: 8-16-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+#include <ole2int.h>
+#pragma hdrstop
+#if DBG==1
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "SpyClnt.hxx"
+
+#define APPMAXLEN 512
+
+
+static HANDLE hPipe; // File or Pipe handle.
+static OVERLAPPED OverLapWrt; // Overlapped structure
+static HANDLE hEventWrt; // Event handle for overlapped writes.
+
+
+#undef wsprintf
+#undef wsprintfA
+#define wsprintf wsprintfA
+#undef MessageBoxA
+#undef MessageBox
+#define MessageBox MessageBoxA
+
+#undef CreateFileA
+#undef CreateFile
+#define CreateFile CreateFileA
+#define GetModuleName GetModuleNameA
+
+LPSTR GetAppName();
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetAppName
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: 8-16-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+LPSTR GetAppName()
+{
+ static CHAR szAppName[APPMAXLEN];
+ LPSTR psz, psz1;
+ GetModuleFileNameA(NULL, szAppName, APPMAXLEN);
+ psz = strrchr(szAppName, '\\');
+ psz++;
+ psz1 = strchr(psz,'.');
+ *psz1 = '\0';
+ return psz;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SendEntry
+//
+// Synopsis:
+//
+// Arguments: [szOutBuf] --
+//
+// Returns:
+//
+// History: 9-29-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+int SendEntry(char * szOutBuf)
+{
+ DWORD dwRet;
+ char szSendBuf[OUT_BUF_SIZE] = "";
+ DWORD cbWritten;
+
+ wsprintf (szSendBuf, "%s: %s\n", GetAppName(), szOutBuf);
+ dwRet = WriteFile (hPipe, szSendBuf, strlen(szSendBuf), &cbWritten, &OverLapWrt);
+
+ if (!dwRet)
+ {
+ DWORD dwLastError;
+ dwLastError = GetLastError();
+
+ // If Error = IO_PENDING, wait until the event signals success.
+ if (dwLastError == ERROR_IO_PENDING)
+ {
+ WaitForSingleObject (hEventWrt, (DWORD)-1);
+ }
+ }
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: InitClient
+//
+// Synopsis:
+//
+// Arguments: [pszShrName] --
+//
+// Returns:
+//
+// History: 9-29-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+int InitClient(char *pszShrName)
+{
+ CHAR szSendBuf[OUT_BUF_SIZE] = "";
+ CHAR szFileName[LINE_LEN+NAME_SIZE+2];
+ DWORD dwRet;
+ DWORD dwLastError;
+ DWORD dwThreadID;
+ DWORD cbWritten;
+
+ if (pszShrName == NULL)
+ {
+ return -1;
+ }
+
+ // Construct file/pipe name.
+ wsprintf (szFileName, "%s%s%s", "\\\\", pszShrName, "\\PIPE\\OleSpy");
+
+ // CreateFile() to connect to the named pipe. Generic access, read/write.
+ hPipe = CreateFile(szFileName, GENERIC_WRITE | GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE ,
+ NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+
+
+ // Do some error checking.
+ if ((DWORD)hPipe == 0xFFFFFFFF)
+ {
+ dwRet = GetLastError();
+
+ // This error means pipe wasn't found.
+ if ((dwRet == ERROR_SEEK_ON_DEVICE) || (dwRet == ERROR_FILE_NOT_FOUND))
+ {
+ MessageBox(NULL,"CANNOT FIND PIPE: Assure OleSpy is started on server.",
+ "", MB_OK);
+ }
+ else
+ {
+ CHAR szErrorBuf[LINE_LEN] = "";
+ // Flagging unknown errors.
+ wsprintf (szErrorBuf,"CreateFile() on pipe failed, see winerror.h error #%d.",dwRet);
+ MessageBox (NULL, szErrorBuf, "", MB_ICONINFORMATION | MB_OK | MB_APPLMODAL);
+ }
+ return -1;
+ }
+
+ // Create and init overlapped structure for writes.
+ hEventWrt = CreateEvent (NULL, TRUE, FALSE, NULL);
+ OverLapWrt.hEvent = hEventWrt;
+
+ {
+ LPSTR szStr = GetAppName();
+
+ // Write the client name to server.
+ dwRet = WriteFile(hPipe, szStr, strlen(szStr), &cbWritten, &OverLapWrt);
+ }
+
+ if (!dwRet)
+ {
+ dwLastError = GetLastError();
+
+ // Wait on overlapped if need be.
+ if (dwLastError == ERROR_IO_PENDING)
+ {
+ WaitForSingleObject(hEventWrt, (DWORD)-1);
+ }
+ }
+
+ // Create a thread to read the pipe.
+ CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)ReadPipe,
+ (LPVOID)&hPipe, 0, &dwThreadID);
+
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: UninitClient
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: 9-29-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void UninitClient()
+{
+ CloseHandle (hPipe);
+ CloseHandle (hEventWrt);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReadPipe
+//
+// Synopsis:
+//
+// Arguments: [hPipe] --
+//
+// Returns:
+//
+// History: 9-29-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+VOID ReadPipe (HANDLE *hPipe)
+{
+ CHAR inBuf[IN_BUF_SIZE] = "";// Input buffer.
+ DWORD bytesRead; // Used for ReadFile()
+ DWORD dwRet; // Used to trap return codes.
+ DWORD dwLastError; // Used to trap returns from GetLastError.
+
+ HANDLE hEventRd; // Event handle for overlapped reads.
+ OVERLAPPED OverLapRd; // Overlapped structure.
+ DWORD bytesTrans; // Bytes transferred in read.
+
+ // Create and init overlap structure.
+ hEventRd = CreateEvent (NULL, TRUE, FALSE, NULL);
+ memset (&OverLapRd, 0, sizeof(OVERLAPPED));
+ OverLapRd.hEvent = hEventRd;
+
+ // Loop, reading the named pipe until it is broken. The ReadFile() uses
+ // an overlapped structure. When the event handle signals a completed
+ // read, this loop writes the message to the larger edit field.
+
+ do {
+ dwRet = ReadFile (*hPipe, inBuf, IN_BUF_SIZE, &bytesRead, &OverLapRd);
+ // Do some error checking.
+ if (!dwRet)
+ {
+ dwLastError = GetLastError();
+
+ if (dwLastError == ERROR_IO_PENDING)
+ {
+ // If Error = IO_PENDING, wait for event
+ // handle to signal success.
+ WaitForSingleObject (hEventRd, (DWORD)-1);
+ }
+ else
+ {
+ // If pipe is broken, tell user and break.
+ if (dwLastError == (DWORD)ERROR_BROKEN_PIPE)
+ {
+ MessageBox (NULL,
+ "The connection to this client has been broken.", "", MB_OK);
+ }
+ else
+ {
+ // Or flag unknown errors, and break.
+ CHAR szErrorBuf[80];
+ wsprintf (szErrorBuf,
+ "ReadFile() on pipe failed, see winerror.h error #%d",GetLastError());
+ MessageBox (NULL, szErrorBuf, "", MB_OK);
+ }
+ break;
+ }
+ }
+ // NULL terminate string.
+ GetOverlappedResult (*hPipe, &OverLapRd, &bytesTrans, FALSE);
+ inBuf[bytesTrans] = '\0';
+
+ } while(1);
+
+ ExitThread(0);
+}
+
+#endif // DBG==1
+
+
diff --git a/private/ole32/com/util/spyclnt.hxx b/private/ole32/com/util/spyclnt.hxx
new file mode 100644
index 000000000..6b65d140b
--- /dev/null
+++ b/private/ole32/com/util/spyclnt.hxx
@@ -0,0 +1,13 @@
+// Various buffer sizes
+#define IN_BUF_SIZE 1000
+#define OUT_BUF_SIZE 1000
+#define LINE_LEN 80
+#define NAME_SIZE 25
+
+#define SERVERNAMEMAX 64
+
+int InitClient(char *pszShrName);
+int SendEntry(char * szOutBuf);
+void UninitClient();
+void ReadPipe (HANDLE *hPipe);
+extern DWORD dwSpyFlag;
diff --git a/private/ole32/com/util/stkclip.cxx b/private/ole32/com/util/stkclip.cxx
new file mode 100644
index 000000000..f6361f867
--- /dev/null
+++ b/private/ole32/com/util/stkclip.cxx
@@ -0,0 +1,142 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: stkclip.cpp
+//
+// Contents: Ole stack switching api's for Clipboard operations
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-16-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+#include <ole2int.h>
+// Note: Enable including native user APIs
+// for stack switching
+#include <userapis.h>
+
+
+BOOL WINAPI SSOpenClipboard(HWND hWndNewOwner)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on Openclipboard\n"));
+ return SSCall(4 ,SSF_SmallStack, (LPVOID) OpenClipboard, (DWORD)hWndNewOwner);
+ }
+ else
+ {
+ return(OpenClipboard(hWndNewOwner));
+ }
+}
+BOOL WINAPI SSCloseClipboard(VOID)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on CloseClipboard\n"));
+ return SSCall(0 ,SSF_SmallStack, (LPVOID) CloseClipboard, 0);
+ }
+ else
+ {
+ return(CloseClipboard());
+ }
+}
+HWND WINAPI SSGetClipboardOwner(VOID)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on GetClipboardOwner\n"));
+ return (HWND)SSCall(0 ,SSF_SmallStack, (LPVOID) GetClipboardOwner, 0);
+ }
+ else
+ {
+ return(GetClipboardOwner());
+ }
+}
+HANDLE WINAPI SSSetClipboardData(UINT uFormat,HANDLE hMem)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on SetClipboardData\n"));
+ return (HANDLE)SSCall(8 ,SSF_SmallStack, (LPVOID)SetClipboardData, (DWORD) uFormat, hMem);
+ }
+ else
+ {
+ return(SetClipboardData(uFormat, hMem));
+ }
+}
+HANDLE WINAPI SSGetClipboardData(UINT uFormat)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on GetClipboardData\n"));
+ return (HANDLE) SSCall(4 ,SSF_SmallStack, (LPVOID) GetClipboardData, (DWORD) uFormat);
+ }
+ else
+ {
+ return(GetClipboardData(uFormat));
+ }
+}
+UINT WINAPI SSRegisterClipboardFormatA(LPCSTR lpszFormat)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on RegisterClipboardFormatA\n"));
+ return SSCall(4 ,SSF_SmallStack, (LPVOID) RegisterClipboardFormatA, (DWORD)lpszFormat);
+ }
+ else
+ {
+ return(RegisterClipboardFormatA(lpszFormat));
+ }
+}
+UINT WINAPI SSEnumClipboardFormats(UINT format)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on EnumClipboardFormats\n"));
+ return SSCall(4 ,SSF_SmallStack, (LPVOID)EnumClipboardFormats, (DWORD) format);
+ }
+ else
+ {
+ return(EnumClipboardFormats(format));
+ }
+}
+int WINAPI SSGetClipboardFormatNameA(UINT format,LPSTR lpszFormatName,int cchMaxCount)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on GetClipboardFormatNameA\n"));
+ return SSCall(12 ,SSF_SmallStack, (LPVOID)GetClipboardFormatNameA, (DWORD)format,lpszFormatName, cchMaxCount);
+ }
+ else
+ {
+ return(GetClipboardFormatNameA( format, lpszFormatName, cchMaxCount));
+ }
+}
+BOOL WINAPI SSEmptyClipboard(VOID)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on EmptyClipboard\n"));
+ return SSCall(0 ,SSF_SmallStack, (LPVOID) EmptyClipboard, 0);
+ }
+ else
+ {
+ return(EmptyClipboard());
+ }
+}
+BOOL WINAPI SSIsClipboardFormatAvailable(UINT format)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on IsClipboardFormatAvailable\n"));
+ return SSCall(4 ,SSF_SmallStack, (LPVOID)IsClipboardFormatAvailable, (DWORD) format);
+ }
+ else
+ {
+ return(IsClipboardFormatAvailable( format));
+ }
+}
diff --git a/private/ole32/com/util/stkswtch.cxx b/private/ole32/com/util/stkswtch.cxx
new file mode 100644
index 000000000..62cf42e7f
--- /dev/null
+++ b/private/ole32/com/util/stkswtch.cxx
@@ -0,0 +1,672 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: stkswtch.cxx
+//
+// Contents: Stack Switching function for Win95.
+// Alls functions switch either to the 32 bit stack or
+// back to the 16 bit stack.
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Note: This fumctions are called on chicago only.
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+// Note: Enable including native user APIs
+// for stack switching
+#include <userapis.h>
+
+DWORD SSAPI(ThreadInvoke)( RPC_MESSAGE *message );
+STDAPI SSAPI(DoDragDrop)(LPDATAOBJECT pDataObject,
+ LPDROPSOURCE pDropSource, DWORD dwOKEffects,
+ DWORD FAR *pdwEffect);
+STDAPI SSAPI(CoInitializeEx)(LPVOID pvReserved, ULONG flags);
+STDAPI_(void) SSAPI(CoUninitialize)(void);
+STDAPI SSAPI(InitChannelControl)(void);
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSSendMessage
+//
+// Synopsis: Switches to 16 bit stack and calls SendMessages
+//
+// Arguments: [hWnd] -- see SendMessage
+// [Msg] --
+// [wParam] --
+// [lParam] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+LRESULT WINAPI SSSendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ StackDebugOut((DEB_ITRACE, "SSSendMessage\n"));
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on SendMessage\n"));
+ return SSCall(16 ,SSF_SmallStack, (LPVOID)SendMessageA , (DWORD)hWnd,
+ (DWORD)Msg, wParam, lParam);
+ }
+ else
+ return SendMessage(hWnd, Msg, wParam, lParam);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSReplyMessage
+//
+// Synopsis: Switches to 16 bit stack and calls ReplyMessage
+//
+// Arguments: [lResult] -- see ReplyMessage
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL WINAPI SSReplyMessage(LRESULT lResult)
+{
+ StackDebugOut((DEB_ITRACE, "SSReplyMessage\n"));
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on ReplyMessage\n"));
+ return SSCall(4 ,SSF_SmallStack, (LPVOID)ReplyMessage , (DWORD)lResult);
+ }
+ else
+ return ReplyMessage(lResult);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSCallWindowProc
+//
+// Synopsis: Switches to 16 bit stack and calls CallWindowProc
+//
+// Arguments: [lpPrevWndFunc] -- see CallWindowProc
+// [hWnd] --
+// [Msg] --
+// [wParam] --
+// [lParam] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+LRESULT WINAPI SSCallWindowProc(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg,
+ WPARAM wParam, LPARAM lParam)
+{
+ StackDebugOut((DEB_ITRACE, "SSCallWindowProc\n"));
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on CallWindowProc\n"));
+ return SSCall(20 ,SSF_SmallStack, (LPVOID)CallWindowProcA,
+ (DWORD)lpPrevWndFunc, hWnd, Msg, wParam, lParam);
+ }
+ else
+ return CallWindowProc( lpPrevWndFunc, hWnd, Msg, wParam, lParam);
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSDefWindowProc
+//
+// Synopsis: Switches to 16 bit stack and calls DefWindowProc
+//
+// Arguments: [hWnd] -- see DefWindowProc
+// [Msg] --
+// [wParam] --
+// [lParam] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+LRESULT WINAPI SSDefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ StackDebugOut((DEB_ITRACE, "SSDefWindowProc\n"));
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on DefWindowProc\n"));
+ return SSCall(16 ,SSF_SmallStack, (LPVOID)DefWindowProcA,
+ (DWORD)hWnd, Msg, wParam, lParam);
+ }
+ else
+ return DefWindowProc( hWnd, Msg, wParam, lParam);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSPeekMessage
+//
+// Synopsis: Switches to 16 bit stack and calls PeekMessage
+//
+// Arguments: [lpMsg] -- see PeekMessage
+// [hWnd] --
+// [wMsgFilterMin] --
+// [UINT] --
+// [wRemoveMsg] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL WINAPI SSPeekMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin,
+ UINT wMsgFilterMax,UINT wRemoveMsg)
+{
+ StackDebugOut((DEB_ITRACE, "SSPeekMessage\n"));
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on PeekMessage\n"));
+ return SSCall(20 ,SSF_SmallStack, (LPVOID)PeekMessageA , (DWORD)lpMsg,
+ (DWORD)hWnd, (DWORD)wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
+ }
+ else
+ return PeekMessage(lpMsg, hWnd, wMsgFilterMin,
+ wMsgFilterMax, wRemoveMsg);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSGetMessage
+//
+// Synopsis: Switches to 16 bit stack and calls GetMessage
+//
+// Arguments: [lpMsg] -- see GetMessage
+// [hWnd] --
+// [wMsgFilterMin] --
+// [wMsgFilterMax] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL WINAPI SSGetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin,
+ UINT wMsgFilterMax)
+{
+ StackDebugOut((DEB_ITRACE, "SSGetMessage\n"));
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on GetMessage\n"));
+ return SSCall(16 ,SSF_SmallStack, (LPVOID)GetMessageA, (DWORD)lpMsg,
+ hWnd, wMsgFilterMin, wMsgFilterMax);
+ }
+ else
+ return GetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSDispatchMessage
+//
+// Synopsis: Switches to 16 bit stack and calls DispatchMessage
+//
+// Arguments: [lpMsg] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+LONG WINAPI SSDispatchMessage(CONST MSG *lpMsg)
+{
+ StackDebugOut((DEB_ITRACE, "SSDispatchMessage\n"));
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on DispatchMessage\n"));
+ return SSCall(4 ,SSF_SmallStack, (LPVOID)DispatchMessageA, (DWORD)lpMsg);
+ }
+ else
+ return DispatchMessage(lpMsg);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSWaitMessage
+//
+// Synopsis: Switches to 16 bit stack and calls WaitMessage
+//
+// Arguments: [VOID] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL WINAPI SSWaitMessage(VOID)
+{
+ StackDebugOut((DEB_ITRACE, "SSWaitMessage\n"));
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on WaitMessage\n"));
+ return SSCall(0 ,SSF_SmallStack, (LPVOID)WaitMessage, 0);
+ }
+ else
+ return WaitMessage();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSDialogBoxParam
+//
+// Synopsis:
+//
+// Arguments: [hInstance] --
+// [lpTemplateName] --
+// [hWndParent] --
+// [lpDialogFunc] --
+// [dwInitParam] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+int WINAPI SSDialogBoxParam(HINSTANCE hInstance, LPCSTR lpTemplateName,
+ HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "Stack switch(16) on DialogBoxParam\n"));
+ return SSCall(20 ,SSF_SmallStack, (LPVOID)DialogBoxParam,
+ (DWORD)hInstance, (DWORD)lpTemplateName, hWndParent,
+ lpDialogFunc, dwInitParam);
+ }
+ else
+ return DialogBoxParam( hInstance, lpTemplateName, hWndParent,
+ lpDialogFunc, dwInitParam);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSDialogBoxIndirectParam
+//
+// Synopsis:
+//
+// Arguments: [hInstance] --
+// [hDialogTemplate] --
+// [hWndParent] --
+// [lpDialogFunc] --
+// [dwInitParam] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+int WINAPI SSDialogBoxIndirectParam(HINSTANCE hInstance,
+ LPCDLGTEMPLATEA hDialogTemplate, HWND hWndParent,
+ DLGPROC lpDialogFunc, LPARAM dwInitParam)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "SSDialogBoxIndirectParam 32->16\n"));
+ return SSCall(24 ,SSF_SmallStack, (LPVOID)DialogBoxIndirectParam,
+ (DWORD)hInstance, (DWORD)hDialogTemplate,
+ hWndParent, lpDialogFunc, dwInitParam);
+ }
+ else
+ return DialogBoxIndirectParam( hInstance, hDialogTemplate,
+ hWndParent, lpDialogFunc, dwInitParam);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSMessageBox
+//
+// Synopsis: Switches to 16 bit stack and calls MessageBox
+//
+// Arguments: [LPCSTR] -- see MessageBox
+// [LPCSTR] --
+// [lpCaption] --
+// [uType] --
+//
+// Returns:
+//
+// History: 12-12-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+int WINAPI SSMessageBox(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption, UINT uType)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "SSMessageBox 32->16\n"));
+ return SSCall(24 ,SSF_SmallStack, (LPVOID)MessageBoxA, (DWORD)hWnd, lpText, lpCaption, uType);
+ }
+ else
+ return MessageBoxA(hWnd, lpText, lpCaption, uType);
+}
+//+---------------------------------------------------------------------------
+//
+// Method: SSCreateWindowExA
+//
+// Synopsis:
+//
+// Arguments: [dwExStyle] --
+// [lpClassName] --
+// [lpWindowName] --
+// [dwStyle] --
+// [X] --
+// [Y] --
+// [nWidth] --
+// [nHeight] --
+// [hWndParent] --
+// [hMenu] --
+// [hInstance] --
+// [lpParam] --
+//
+// Returns:
+//
+// History: 12-12-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HWND WINAPI SSCreateWindowExA(DWORD dwExStyle, LPCSTR lpClassName,
+ LPCSTR lpWindowName, DWORD dwStyle, int X, int Y,
+ int nWidth, int nHeight, HWND hWndParent, HMENU hMenu,
+ HINSTANCE hInstance, LPVOID lpParam)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "SSCreateWindowExA 32->16\n"));
+ return (HWND)SSCall(48 ,SSF_SmallStack, (LPVOID)CreateWindowExA,
+ dwExStyle, (DWORD)lpClassName, (DWORD)lpWindowName,
+ dwStyle, X, Y, nWidth, nHeight, (DWORD)hWndParent,
+ (DWORD)hMenu, (DWORD)hInstance, (DWORD)lpParam);
+ }
+ else
+ return CreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle,
+ X, Y, nWidth, nHeight, hWndParent, hMenu,
+ hInstance, lpParam);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSCreateWindowExW
+//
+// Synopsis:
+//
+// Arguments: [dwExStyle] --
+// [lpClassName] --
+// [lpWindowName] --
+// [dwStyle] --
+// [X] --
+// [Y] --
+// [nWidth] --
+// [nHeight] --
+// [hWndParent] --
+// [hMenu] --
+// [hInstance] --
+// [lpParam] --
+//
+// Returns:
+//
+// History: 12-12-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HWND WINAPI SSCreateWindowExW(DWORD dwExStyle, LPCWSTR lpClassName,
+ LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y,
+ int nWidth, int nHeight, HWND hWndParent, HMENU hMenu,
+ HINSTANCE hInstance, LPVOID lpParam)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "SSCreateWindowExX 32->16\n"));
+ return (HWND)SSCall(48 ,SSF_SmallStack, (LPVOID)CreateWindowExX,
+ dwExStyle, (DWORD)lpClassName, (DWORD)lpWindowName,
+ dwStyle, X, Y, nWidth, nHeight, (DWORD)hWndParent,
+ (DWORD)hMenu, (DWORD)hInstance, (DWORD)lpParam);
+ }
+ else
+ return CreateWindowExX(dwExStyle, lpClassName, lpWindowName, dwStyle,
+ X, Y, nWidth, nHeight, hWndParent, hMenu,
+ hInstance, lpParam);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSDestroyWindow
+//
+// Synopsis:
+//
+// Arguments: [hWnd] --
+//
+// Returns:
+//
+// History: 12-12-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL WINAPI SSDestroyWindow(HWND hWnd)
+{
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "SSDestrayWindow 32->16\n"));
+ return SSCall(4 ,SSF_SmallStack, (LPVOID)DestroyWindow,(DWORD)hWnd);
+ }
+ else
+ return DestroyWindow(hWnd);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: DoDragDrop
+//
+// Synopsis:
+//
+// Arguments: [LPDROPSOURCE] --
+// [pDropSource] --
+// [DWORD] --
+// [pdwEffect] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI DoDragDrop(LPDATAOBJECT pDataObject,LPDROPSOURCE pDropSource,
+ DWORD dwOKEffects,DWORD FAR *pdwEffect)
+{
+ StackDebugOut((DEB_ITRACE, "DoDragDrop\n"));
+ HRESULT hres;
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "SWDoDragDrop: 32->16\n"));
+ hres = SSCall(20, SSF_SmallStack, (LPVOID)SSDoDragDrop,
+ (DWORD)pDataObject, pDropSource,
+ dwOKEffects, pdwEffect);
+ StackDebugOut((DEB_STCKSWTCH,
+ "SWDoDragDrop 16<-32 done; hres:%ld\n", hres));
+ }
+ else
+ {
+ hres = SSDoDragDrop(pDataObject, pDropSource, dwOKEffects, pdwEffect);
+ }
+ return hres;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: ThreadInvoke
+//
+// Synopsis: Switches to 32 bit stack and calls ThreadInvoke
+//
+// Arguments: [message] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void ThreadInvoke( RPC_MESSAGE *message )
+{
+ DWORD dwRet;
+ StackDebugOut((DEB_ITRACE, "ThreadInvoke\n"));
+ if (SSONSMALLSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "SSThreadInvoke: 16->32\n"));
+ dwRet = SSCall(4, SSF_BigStack, (LPVOID)SSThreadInvoke, (DWORD)message);
+
+ StackDebugOut((DEB_STCKSWTCH, "SWThreadInvoke 16<-32 done\n"));
+ }
+ else
+ {
+ dwRet = SSThreadInvoke(message);
+ }
+ if ( (dwRet == RPC_E_SERVERFAULT)
+ || ( dwRet != RPC_E_SERVERCALL_REJECTED
+ && dwRet != RPC_E_SERVERCALL_RETRYLATER
+ && dwRet != S_OK))
+ {
+ RpcRaiseException( dwRet );
+ }
+}
+//+---------------------------------------------------------------------------
+//
+// Method: CoInitializeEx
+//
+// Synopsis:
+//
+// Arguments: [pvReserved] --
+// [flags] --
+//
+// Returns:
+//
+// History: 1-05-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoInitializeEx(LPVOID pvReserved, ULONG flags)
+{
+ StackDebugOut((DEB_ITRACE, "CoInitializeEx\n"));
+ HRESULT hres;
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "SSCoInitializeEx: 32->16\n"));
+ hres = SSCall(8, SSF_SmallStack, (LPVOID)SSCoInitializeEx,
+ (DWORD)pvReserved, flags);
+ StackDebugOut((DEB_STCKSWTCH,
+ "CoInitializeEx 16<-32 done; hres:%ld\n", hres));
+ }
+ else
+ {
+ hres = SSCoInitializeEx(pvReserved, flags);
+ }
+ return hres;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CoUninitialize
+//
+// Synopsis:
+//
+// Arguments: [pvReserved] --
+// [flags] --
+//
+// Returns:
+//
+// History: 1-05-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(void) CoUninitialize(void)
+{
+ StackDebugOut((DEB_ITRACE, "CoUninitialize\n"));
+ HRESULT hres;
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "SSCoUninitialize: 32->16\n"));
+ hres = SSCall(0, SSF_SmallStack, (LPVOID)SSCoUninitialize,(DWORD)NULL);
+ StackDebugOut((DEB_STCKSWTCH,
+ "CoInitializeEx 16<-32 done; hres:%ld\n", hres));
+ }
+ else
+ {
+ SSCoUninitialize();
+ }
+ return;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: InitChannelControl
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: 4-07-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT InitChannelControl()
+{
+ StackDebugOut((DEB_ITRACE, "InitChannelControl\n"));
+ HRESULT hres;
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "SSInitChannelControl: 32->16\n"));
+ hres = SSCall(0, SSF_SmallStack, (LPVOID)SSInitChannelControl,(DWORD)NULL);
+ StackDebugOut((DEB_STCKSWTCH,
+ "InitChannelControl 16<-32 done; hres:%ld\n", hres));
+ }
+ else
+ {
+ hres = SSInitChannelControl();
+ }
+ return hres;
+}
+
+
diff --git a/private/ole32/com/util/task.cxx b/private/ole32/com/util/task.cxx
new file mode 100644
index 000000000..ffa2796bb
--- /dev/null
+++ b/private/ole32/com/util/task.cxx
@@ -0,0 +1,75 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: Task.cxx
+//
+// Contents: Helper function to determine the current task
+//
+// Functions: IsTaskName
+//
+// History: 28-Mar-95 scottsk Created
+//
+//--------------------------------------------------------------------------
+
+#include <ole2int.h>
+
+// Helper function for IsTaskName
+inline BOOL IsPathSeparator( WCHAR ch )
+{
+ return (ch == L'\\' || ch == L'/');
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsTaskName
+//
+// Synopsis: Determines if the passed name is the current task
+//
+// Effects:
+//
+// Arguments: [lpszIn] -- Task name
+//
+// Returns: TRUE, FALSE
+//
+// History: dd-mmm-yy Author Comment
+// 03-Mar-95 Scottsk Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+FARINTERNAL_(BOOL) IsTaskName(LPCWSTR lpszIn)
+{
+ WCHAR awszImagePath[MAX_PATH];
+ BOOL retval = FALSE;
+
+ if (GetModuleFileName(NULL, awszImagePath, MAX_PATH))
+ {
+ // Get last component of path
+
+ WCHAR * pch;
+
+ //
+ // Find the end of the string and determine the string length.
+ //
+
+ for (pch=awszImagePath; *pch; pch++);
+
+ DecLpch (awszImagePath, pch); // pch now points to the last real character
+
+ while (!IsPathSeparator(*pch))
+ {
+ DecLpch (awszImagePath, pch);
+ }
+
+ // we're at the last separator. is the last component EXCEL?
+
+ if (!lstrcmpiW(pch+1, lpszIn))
+ {
+ retval = TRUE;
+ }
+ }
+
+ return retval;
+}
diff --git a/private/ole32/com/util/time.cxx b/private/ole32/com/util/time.cxx
new file mode 100644
index 000000000..052b3154b
--- /dev/null
+++ b/private/ole32/com/util/time.cxx
@@ -0,0 +1,415 @@
+//+------------------------------------------------------------
+//
+// File: time.cxx
+//
+// Contents: Component object model time utilities
+//
+// Functions: CoFileTimeToDosDateTime
+// CoDosDateTimeToFileTime
+// CoFileTimeNow
+//
+// History: 5-Apr-94 brucema Created
+//
+//-------------------------------------------------------------
+#include <ole2int.h>
+
+#if defined (WIN32)
+
+STDAPI_(BOOL) CoFileTimeToDosDateTime(
+ FILETIME FAR* lpFileTime, LPWORD lpFatDate, LPWORD lpFatTime)
+{
+ OLETRACEIN((API_CoFileTimeToDosDateTime, PARAMFMT("lpFileTime= %tf, lpFatDate= %p, lpFatTime= %p"),
+ lpFileTime, lpFatDate, lpFatTime));
+ BOOL fRet= FALSE;
+
+ if ((lpFileTime != NULL) &&
+ IsValidPtrIn(lpFileTime, sizeof(*lpFileTime)) &&
+ IsValidPtrOut(lpFatDate, sizeof(*lpFatDate)) &&
+ IsValidPtrOut(lpFatTime, sizeof(*lpFatTime)))
+ {
+ fRet = FileTimeToDosDateTime(lpFileTime, lpFatDate, lpFatTime);
+ }
+
+ OLETRACEOUTEX((API_CoFileTimeToDosDateTime, RETURNFMT("%B"), fRet));
+ return fRet;
+}
+
+STDAPI_(BOOL) CoDosDateTimeToFileTime(
+ WORD nDosDate, WORD nDosTime, FILETIME FAR* lpFileTime)
+{
+ OLETRACEIN((API_CoDosDateTimeToFileTime, PARAMFMT("nDosDate=%x, nDosTime=%x, lpFileTime=%p"),
+ nDosDate, nDosTime, lpFileTime));
+
+ BOOL fRet= FALSE;
+
+ if (IsValidPtrOut(lpFileTime, sizeof(*lpFileTime)))
+ {
+ fRet = DosDateTimeToFileTime(nDosDate, nDosTime, lpFileTime);
+ }
+
+ OLETRACEOUTEX((API_CoDosDateTimeToFileTime, RETURNFMT("%B"), fRet));
+ return fRet;
+}
+
+#else
+
+#include <dos.h>
+// 64 bit representation of 100ns units between 1-1-1601 and (excluding) 1-1-80
+// in two 32 bit values (H1980:L1980) and
+// in four 16 bit values (HH1980:HL1980:LH1980:LL1980)
+//
+#define H1980 0x01A8E79F
+#define L1980 0xE1D59586
+#define HH1980 0x01A8
+#define HL1980 0xE79F
+#define LH1980 0xE1D5
+#define LL1980 0x9586
+
+// Number of 100ns units in one second represented as one 32 bit value
+//
+#define ONESEC 10000000
+
+// ONESEC0 * ONESEC1 = ONESEC both are 16 bits values
+//
+#define ONESEC0 4000
+#define ONESEC1 2500
+
+// Non-leap year accumulating days, excluding current month, jan is month[0]
+static const UINT MonthTab[] = {0,31,59,90,120,151,181,212,243,273,304,334};
+
+// Leap year accumulating days, excluding current month, jan is month[0]
+static const UINT LeapmTab[] = {0,31,60,91,121,152,182,213,244,274,305,335};
+
+// Accumulating days, excluding current year, year[0] is leap year
+static const UINT YearTab[] = {0,366,731,1096};
+
+// Number of days in a four years period that includes a leap year
+static const UINT FourYear = 1461;
+
+// Number of days in a 100 years period that does not start with a leap year
+static const DWORD HundredYear = 36524;
+
+// Number of days in a 400 years period (starts with a leap year)
+static const DWORD FourHundredYear = 146097;
+
+
+#pragma SEG(CoFileTimeToDosDateTime)
+STDAPI_(BOOL) CoFileTimeToDosDateTime(
+ FILETIME FAR* lpFileTime, LPWORD lpFatDate, LPWORD lpFatTime)
+{
+ DWORD Year,Month,Day,Hour,Min,Sec;
+ DWORD Days, Seconds;
+ DWORD LowNs, HighNs;
+ int i;
+
+ if ((lpFileTime == NULL) ||
+ !IsValidPtrIn(lpFileTime, sizeof(*lpFileTime)) ||
+ !IsValidPtrOut(lpFatDate, sizeof(*lpFatDate)) ||
+ !IsValidPtrOut(lpFatTime, sizeof(*lpFatTime)))
+ {
+ return(FALSE);
+ }
+
+ LowNs = lpFileTime->dwLowDateTime;
+ HighNs = lpFileTime->dwHighDateTime;
+
+ i = 1;
+
+ // Note that the following code works because 2000 is a leap year
+ // and DosDate year range is 1980 - 2099
+ //
+ _asm {
+ mov ax,word ptr LowNs
+ mov bx,word ptr LowNs+2
+ mov cx,word ptr HighNs
+ mov dx,word ptr HighNs+2 ; (dx:cx:bx:ax) = time in NT format
+ sub ax,LL1980
+ sbb bx,LH1980
+ sbb cx,HL1980
+ sbb dx,HH1980 ; (dx:cx:bx:ax) = 100ns since 1-1-1980
+ jc cvt0 ; Before the beginning of DosDateTime
+
+ ; Divide (dx:cx:bx:ax) by ONESEC.
+ ; Note that for any time before year 2100 the bumber of 100ns
+ ; since 1-1-1980 divided by ONESEC0 < 2^48 (that is can be stored
+ ; in three registers) and that the result divided by ONESEC1 < 2^32
+ ;
+ mov si,cx ; (dx:si:bx:ax) = 100ns since 1-1-1980
+ mov cx,ONESEC0
+ mov di,ax ; (dx:si:bx:di) = 100ns since 1-1-1980
+ mov ax,dx ; divide
+ xor dx,dx
+ div cx ; ax = q (should be 0) dx = r (used in next div)
+ or ax,ax
+ jnz cvt0 ; past 1-1-2100
+ mov ax,si
+ div cx ; ax = q (should be 0) dx = r (used in next div)
+ mov si,ax
+ mov ax,bx
+ div cx
+ mov bx,ax
+ mov ax,di
+ div cx
+ mov di,ax ; (si:bx:di) = 100ns since 1-1-1980 / ONESEC0
+ mov ax,si
+ mov cx,ONESEC1
+ xor dx,dx
+ div cx ; ax = q (should be 0) dx = r (used in next div)
+ or ax,ax
+ jnz cvt0 ; past 1-1-2100
+ mov ax,bx
+ div cx
+ mov word ptr Seconds+2,ax
+ mov ax,di
+ div cx
+ mov word ptr Seconds,ax
+ mov i,0 ; No error
+cvt0:
+ }
+
+ if (i)
+ return FALSE;
+
+ // Min, Hour, Days since 1980
+ //
+ Sec = Seconds % 60;
+ Seconds /= 60;
+ Min = Seconds % 60;
+ Seconds /= 60;
+ Hour = Seconds % 24;
+ Days = Seconds / 24;
+
+ // Find year number (1980 = 0)
+ //
+ Year = (Days / FourYear) * 4;
+ Days %= FourYear;
+
+ for (i = 1; i < 4; i++)
+ if (Days < YearTab[i])
+ break;
+
+ i--;
+ Year += i;
+ Days -= YearTab[i];
+
+ if (Year + 1980 > 2099)
+ return FALSE;
+
+ // Find month (jan == 1)
+ //
+ if (Year % 4) { // Non Leap year
+ for (i = 1; i < 12; i++)
+ if (Days < MonthTab[i])
+ break;
+
+ Month = i;
+ Day = Days - MonthTab[i - 1] + 1;
+ }
+ else {
+ for (i = 1; i < 12; i++)
+ if (Days < LeapmTab[i])
+ break;
+
+ Month = i;
+ Day = Days - LeapmTab[i - 1] + 1;
+ }
+
+ // The Dos time and date are stored in two packed 16-bit words
+ // as follows:
+ // Date: | 9-15 Year | 5-8 Month | 0-4 Day |
+ // Time: | 11-15 Hour| 5-10 Min | 0-4 Sec |
+ // Year 1980 = 0
+ // Month jan = 1
+ // Day first = 1
+ // Hours 0-23
+ // Min 0-59
+ // Seconds are delinated in 2sec increments (0-29).
+ //
+ *lpFatTime= (WORD) ((Hour << 11) + (Min << 5) + Sec / 2);
+ *lpFatDate= (WORD) ((Year << 9) + (Month << 5) + Day);
+
+ return (TRUE);
+}
+
+#pragma SEG(CoDosDateTimeToFileTime)
+STDAPI_(BOOL) CoDosDateTimeToFileTime(
+ WORD nDosDate, WORD nDosTime, FILETIME FAR* lpFileTime)
+{
+ DWORD Year,Month,Day,Hour,Min,Sec;
+ DWORD Days, Seconds;
+ DWORD LowNs, HighNs;
+
+ if (!IsValidPtrOut(lpFileTime, sizeof(*lpFileTime))
+ {
+ return(FALSE);
+ }
+
+ // Note that the following code works because 2000 is a leap year
+ // and DosDate year range is 1980 - 2099
+ //
+ // All operations done in Seconds, then multiply by 10^7.
+ //
+ // The Dos time and date are stored in two packed 16-bit words
+ // as follows:
+ // Date: | 9-15 Year | 5-8 Month | 0-4 Day |
+ // Time: | 11-15 Hour| 5-10 Min | 0-4 Sec |
+ // Year 1980 = 0
+ // Month jan = 1
+ // Day first = 1
+ // Hours 0-23
+ // Min 0-59
+ // Seconds are delinated in 2sec increments (0-29).
+ //
+
+ Year = ((nDosDate >> 9) & 0x0000007f);
+ Month = ((nDosDate >> 5) & 0x0000000f) - 1;
+ Day = ((nDosDate) & 0x0000001f) - 1;
+
+ Hour = ((nDosTime >> 11) & 0x0000001f);
+ Min = ((nDosTime >> 5) & 0x0000003f);
+ Sec = ((nDosTime << 1) & 0x0000003e);
+
+ if (Year < 0 || Month < 0 || Day < 0 || Hour < 0 || Min < 0 || Sec < 0 ||
+ Month > 11 || Day > 30 || Hour > 23 || Min > 59 || Sec > 59)
+ return FALSE;
+
+ if (Year + 1980 > 2099)
+ return FALSE;
+
+ //
+ // Calculate days since 1980
+
+
+ Days = (Year / 4) * FourYear + YearTab[Year % 4] +
+ ((Year % 4) ? MonthTab[Month] : LeapmTab[Month]) + Day;
+
+ Seconds = ((Days * 24 + Hour) * 60 + Min) * 60 + Sec;
+
+ LowNs = L1980;
+ HighNs = H1980;
+
+ _asm {
+ mov ax,word ptr Seconds
+ mov bx,word ptr Seconds+2
+
+ ; Multiply (bx:ax) by ONESEC.
+ ; Note that for any time before year 2100 the bumber of seconds
+ ; since 1-1-1980 multiplied by ONESEC0 < 2^48 (that is can be stored
+ ; in three registers)
+ ;
+ mov cx,ONESEC0
+ mul cx
+ mov di,dx
+ mov si,ax ; di:si = ax * ONESEC0
+ mov ax,bx
+ xor bx,bx
+ mul cx ; dx:ax = bx * ONESEC0
+ add di,ax
+ adc bx,dx ; bx:di:si = Seconds * ONESEC0
+ mov ax,si
+ mov cx,ONESEC1
+ mul cx
+ add word ptr LowNs,ax
+ adc word ptr LowNs+2,dx
+ adc word ptr HighNs,0
+ adc word ptr HighNs+2,0
+ mov ax,di
+ mul cx
+ add word ptr LowNs+2,ax
+ adc word ptr HighNs,dx
+ adc word ptr HighNs+2,0
+ mov ax,bx
+ mul cx
+ add word ptr HighNs,ax
+ adc word ptr HighNs+2,dx
+ }
+
+ lpFileTime->dwLowDateTime = LowNs;
+ lpFileTime->dwHighDateTime= HighNs;
+
+ return (TRUE);
+}
+
+#endif // WIN32
+
+#pragma SEG(CoFileTimeNow)
+
+//
+// Get the current UTC time, in the FILETIME format.
+//
+
+STDAPI CoFileTimeNow(FILETIME *pfiletime )
+{
+
+ // Validate the input
+
+ if (!IsValidPtrOut(pfiletime, sizeof(*pfiletime)))
+ {
+ return(E_INVALIDARG);
+ }
+
+#ifdef WIN32
+
+ // Get the time in SYSTEMTIME format.
+
+ SYSTEMTIME stNow;
+ GetSystemTime(&stNow);
+
+ // Convert it to FILETIME format.
+
+ if( !SystemTimeToFileTime(&stNow, pfiletime) )
+ {
+ pfiletime->dwLowDateTime = 0;
+ pfiletime->dwHighDateTime = 0;
+ return( HRESULT_FROM_WIN32( GetLastError() ));
+ }
+ else
+ return( NOERROR );
+
+#else // WIN32
+
+ static struct _dosdate_t date; // declared static so it will be in
+ static struct _dostime_t time;
+
+ WORD wDate;
+ WORD wTime;
+ DWORD dw;
+ BOOL fHighBitSet;
+
+ _dos_getdate( &date );
+ _dos_gettime( &time );
+
+ // build wDate
+ wDate = date.day;
+ wDate |= (date.month << 5);
+ wDate |= ((date.year - 1980) << 9);
+
+ // build wTime;
+ wTime = time.second / 2;
+ wTime |= (time.minute << 5);
+ wTime |= (time.hour << 11);
+
+
+ if (!CoDosDateTimeToFileTime( wDate, wTime, pfiletime ))
+ {
+ return E_UNSPEC;
+ }
+
+ // so far our resolution is only 2 seconds.
+ dw = (time.second % 2)*100 + time.hsecond;
+ dw *= 10000;
+ // add the difference and check for carry
+
+ fHighBitSet = (((pfiletime->dwLowDateTime)& 0x80000000) != 0);
+ pfiletime->dwLowDateTime += dw;
+ if (fHighBitSet && ((pfiletime->dwLowDateTime & 0x80000000) == 0))
+ {
+ pfiletime->dwHighDateTime++;
+ }
+
+ return NOERROR;
+
+#endif // WIN32
+
+}
+
diff --git a/private/ole32/com/util/utexcept.cxx b/private/ole32/com/util/utexcept.cxx
new file mode 100644
index 000000000..df1f40bb4
--- /dev/null
+++ b/private/ole32/com/util/utexcept.cxx
@@ -0,0 +1,55 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: utexcept.cxx
+//
+// Contents: Functions used to make exception handling nicer.
+//
+// Functions: SafeIUnknownRelease
+//
+// History: 22-Jan-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: SafeIUnknownRelease
+//
+// Synopsis: Guarantees that an IUnknown can be released without
+// causing an to be thrown outside of this routine.
+//
+// Arguments: [pUnk] - pointer to interface instance to release
+//
+// Algorithm: Verify pointer is not NULL then call its Release operation
+// inside of a try block.
+//
+// History: 22-Jan-93 Ricksa Created
+//
+// Notes: This exists because we are working under the assumption
+// that Release (like close on a file) cannot really fail.
+// And that if it does fail it should be ignored. This function
+// isn't really necessary, its purpose is simply to make code
+// smaller and easier to write by not duplicating thousands
+// of tiny try blocks throughout code which must clean up
+// interfaces before an exit.
+//
+//--------------------------------------------------------------------------
+void SafeIUnknownRelease(IUnknown *pUnk)
+{
+ TRY
+ {
+ if (pUnk)
+ {
+ pUnk->Release();
+ }
+ }
+ CATCH(CException, e)
+ {
+ HandleException(e);
+ }
+ END_CATCH
+}
diff --git a/private/ole32/com/util/utils.cxx b/private/ole32/com/util/utils.cxx
new file mode 100644
index 000000000..b25c0604b
--- /dev/null
+++ b/private/ole32/com/util/utils.cxx
@@ -0,0 +1,44 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ utils.cpp
+
+Abstract:
+
+ This module contains the code for the utility routines
+
+Author:
+
+ Srini Koppolu (srinik) 02-Mar-1992
+
+Revision History:
+
+ Erik Gavriluk (erikgav) 31-Dec-1993 Chicago port
+
+--*/
+
+#include <ole2int.h>
+
+
+#pragma SEG(UtDupString)
+// copies string using the TASK allocator; returns NULL on out of memory
+FARINTERNAL_(LPWSTR) UtDupString(LPCWSTR lpszIn)
+{
+ LPWSTR lpszOut = NULL;
+ IMalloc FAR* pMalloc;
+
+ if (CoGetMalloc(MEMCTX_TASK, &pMalloc) == S_OK) {
+
+ if ((lpszOut =
+ (LPWSTR)pMalloc->Alloc(
+ (lstrlenW(lpszIn)+1) * sizeof(WCHAR))) != NULL)
+ lstrcpyW(lpszOut, lpszIn);
+
+ pMalloc->Release();
+ }
+
+ return lpszOut;
+}
diff --git a/private/ole32/com/util/utstream.cxx b/private/ole32/com/util/utstream.cxx
new file mode 100644
index 000000000..47cdb98d7
--- /dev/null
+++ b/private/ole32/com/util/utstream.cxx
@@ -0,0 +1,209 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ utstream.cpp
+
+Abstract:
+
+ This module contains the code for the stream utility routines
+
+Author:
+
+ Srini Koppolu (srinik) 14-Mar-1992
+
+Revision History:
+ (SriniK) 6/23/92 Moved ReadStringStream, WriteStringStream and
+ OpenOrCreateStream from "api.cpp, ole2.cpp"
+
+ (ErikGav) 12/31/93 Chicago port
+
+--*/
+
+
+#include <ole2int.h>
+
+#include <limits.h>
+
+#define MAX_STR 256
+
+
+#pragma SEG(OpenOrCreateStream)
+STDAPI OpenOrCreateStream( IStorage FAR * pstg, OLECHAR const FAR * pwcsName,
+ IStream FAR* FAR* ppstm)
+{
+ HRESULT error;
+ error = pstg->CreateStream(pwcsName,
+ STGM_SALL | STGM_FAILIFTHERE, 0, 0, ppstm);
+ if (GetScode(error) == STG_E_FILEALREADYEXISTS)
+ error = pstg->OpenStream(pwcsName, NULL, STGM_SALL, 0, ppstm);
+
+ return error;
+}
+
+
+#pragma SEG(ReadStringStream)
+// returns S_OK when string read and allocated (even if zero length)
+STDAPI ReadStringStream( LPSTREAM pstm, LPOLESTR FAR * ppsz )
+{
+ ULONG cb;
+ HRESULT hresult;
+
+ *ppsz = NULL;
+
+ if ((hresult = StRead(pstm, (void FAR *)&cb, sizeof(ULONG))) != NOERROR)
+ return hresult;
+
+ if (cb == NULL)
+ // NULL string case
+ return NOERROR;
+
+ if ((LONG)cb < 0 || cb > INT_MAX)
+ // out of range
+ return ReportResult(0, E_UNSPEC, 0, 0);
+
+ if (!(*ppsz = new FAR OLECHAR[(int)cb]))
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+ if ((hresult = StRead(pstm, (void FAR *)(*ppsz), cb)) != NOERROR)
+ goto errRtn;
+
+ return NOERROR;
+
+errRtn:
+ delete *ppsz;
+ *ppsz = NULL;
+ return hresult;
+}
+
+
+#pragma SEG(WriteStringStream)
+
+//+-------------------------------------------------------------------------
+//
+// Function: WriteStringStream
+//
+// Synopsis: Write a null-terminated string out to a stream.
+//
+// Effects:
+//
+// Arguments: pstm, the stream to write to.
+// psz, the string to write out.
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+// Writes out a count (in bytes) and then the string, including NULL termination.
+// E.G.:
+// psz == NULL: writes out a 0, followed by zero bytes.
+// psz == "": writes out a 1, followed by the zero termination.
+// psz == "dog": writes out a 4, followed by "dog", followed by zero termination
+//
+//--------------------------------------------------------------------------
+
+STDAPI WriteStringStream( LPSTREAM pstm, LPCOLESTR psz )
+{
+ HRESULT error;
+ ULONG cb = NULL;
+
+ if (psz)
+ cb = (1 + _xstrlen(psz)) * sizeof(OLECHAR);
+
+ if (error = pstm->Write((VOID FAR *)&cb, sizeof(ULONG), NULL))
+ goto errRtn;
+
+ if (psz == NULL)
+ // we are done writing the string
+ return NOERROR;
+
+ if (error = pstm->Write((VOID FAR *)psz, cb, NULL))
+ goto errRtn;
+errRtn:
+ return error;
+}
+
+#pragma SEG(StRead)
+// REVIEW: spec issue 313 requests that IStream::Read return S_FALSE when end
+// of file; this change eliminate the need for this routine.
+FARINTERNAL_(HRESULT) StRead (IStream FAR * lpstream, LPVOID lpBuf, ULONG ulLen)
+{
+ HRESULT error;
+ ULONG cbRead;
+
+ if ((error = lpstream->Read( lpBuf, ulLen, &cbRead)) != NOERROR)
+ return error;
+
+ return ((cbRead != ulLen) ? ReportResult(0, S_FALSE , 0, 0): NOERROR);
+}
+
+
+#pragma SEG(StSave10NativeData)
+FARINTERNAL_(HRESULT) StSave10NativeData(IStorage FAR* pstgSave, HANDLE hNative)
+{
+ LPOLESTR lpNative;
+ DWORD dwSize;
+ LPSTREAM lpstream = NULL;
+ HRESULT error;
+
+ if (!hNative)
+ return ReportResult(0, E_UNSPEC, 0, 0);
+
+ if (!(dwSize = GlobalSize (hNative)))
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+ if (!(lpNative = (LPOLESTR) GlobalLock (hNative)))
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ GlobalUnlock (hNative);
+
+ if (error = OpenOrCreateStream(pstgSave, OLE10_NATIVE_STREAM, &lpstream))
+ return error;
+
+ if (error = StWrite (lpstream, &dwSize, sizeof(DWORD)))
+ goto errRtn;
+
+
+ if (error = StWrite (lpstream, lpNative, dwSize))
+ goto errRtn;
+
+errRtn:
+ if (lpstream)
+ lpstream->Release();
+
+ return error;
+}
+
+
+
+#pragma SEG(StSave10ItemName)
+FARINTERNAL StSave10ItemName
+ (IStorage FAR* pstg,
+ LPCOLESTR szItemName)
+{
+ LPSTREAM lpstream = NULL;
+ HRESULT hresult;
+
+ if ((hresult = OpenOrCreateStream (pstg, OLE10_ITEMNAME_STREAM, &lpstream))
+ != NOERROR)
+ {
+ return hresult;
+ }
+
+ hresult = WriteStringStream (lpstream, szItemName);
+
+ if (lpstream)
+ lpstream->Release();
+
+ return hresult;
+}
diff --git a/private/ole32/com/util/w32new.cxx b/private/ole32/com/util/w32new.cxx
new file mode 100644
index 000000000..0663521ae
--- /dev/null
+++ b/private/ole32/com/util/w32new.cxx
@@ -0,0 +1,47 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: w32new.cxx
+//
+// Contents: memory management
+//
+// Functions: operator new
+// operator delete
+//--------------------------------------------------------------------------
+#include <ole2int.h>
+#include <memapi.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Function: operator new, public
+//
+// Synopsis: Global operator new which does not throw exceptions.
+//
+// Arguments: [size] -- Size of the memory to allocate.
+//
+// Returns: A pointer to the allocated memory. Is *NOT* initialized to 0!
+//
+//----------------------------------------------------------------------------
+void* _CRTAPI1
+operator new (size_t size)
+{
+ return(PrivMemAlloc(size));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ::operator delete
+//
+// Synopsis: Free a block of memory
+//
+// Arguments: [lpv] - block to free.
+//
+//--------------------------------------------------------------------------
+
+void _CRTAPI1 operator delete(void FAR* lpv)
+{
+ PrivMemFree(lpv);
+}
+
diff --git a/private/ole32/com/util/widewrap.cxx b/private/ole32/com/util/widewrap.cxx
new file mode 100644
index 000000000..205681f32
--- /dev/null
+++ b/private/ole32/com/util/widewrap.cxx
@@ -0,0 +1,2068 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: widewrap.cxx
+//
+// Contents: Unicode wrapper API, used only on Chicago
+//
+// Functions: About fifty Win32 function wrappers
+//
+// Notes: 'sz' is used instead of the "correct" hungarian 'psz'
+// throughout to enhance readability.
+//
+// Not all of every Win32 function is wrapped here. Some
+// obscurely-documented features may not be handled correctly
+// in these wrappers. Caller beware.
+//
+// These are privately exported for use by the Shell.
+//
+// History: 28-Dec-93 ErikGav Created
+// 06-14-94 KentCe Various Chicago build fixes.
+// 21-Dec-94 BruceMa Use olewcstombs + other fixes
+// 21-Feb-95 BruceMa Add support for AreFileApisANSI
+// 29-Feb-96 JeffE Add lots of wide character rtns
+//
+//----------------------------------------------------------------------------
+
+#include <ole2int.h>
+#include <winbase.h>
+#include "memapi.hxx"
+
+#ifdef _CHICAGO_
+
+#define HFINDFILE HANDLE
+#define ERR ((char*) -1)
+
+
+//
+// BUGBUG: 9869
+//
+// The length of a Unicode string (in chars) and a DBCS string are not
+// always equal. We need to review all WideChar to MultiByte conversions
+// logic to verify that the proper result buffer size is used.
+//
+// Make the below Win95 only change to get the Win95 FE build out.
+//
+
+int UnicodeToAnsi(LPSTR sz, LPCWSTR pwsz, LONG cb)
+{
+ int ret;
+
+ ret = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, pwsz, -1, sz, cb, NULL, NULL);
+
+#if DBG==1
+ CairoleAssert(ret != 0 && "Lost characters in Unicode->Ansi conversion");
+ if (ret == 0)
+ {
+ DebugBreak();
+ }
+#endif
+
+ return ret;
+}
+
+
+int UnicodeToAnsiOem(LPSTR sz, LPCWSTR pwsz, LONG cb)
+{
+ int ret;
+
+ if (AreFileApisANSI())
+ {
+ ret = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, pwsz, -1, sz,
+ cb, NULL, NULL);
+ }
+ else
+ {
+ ret = WideCharToMultiByte(CP_OEMCP, WC_COMPOSITECHECK, pwsz, -1, sz,
+ cb, NULL, NULL);
+ }
+
+#if DBG==1
+ CairoleAssert(ret != 0 && "Lost characters in Unicode->Ansi conversion");
+ if (ret == 0)
+ {
+ DebugBreak();
+ }
+#endif
+
+ return ret;
+}
+
+
+
+#if DBG==1
+int AnsiToUnicode(LPWSTR pwsz, LPCSTR sz, LONG cb)
+{
+ int ret;
+ DWORD WindowsError;
+
+ ret = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, sz, -1, pwsz, cb);
+ if (ret == 0) {
+ WindowsError = GetLastError ();
+ }
+ CairoleAssert(ret != 0 && "Lost characters in Ansi->Unicode conversion");
+ if (ret == 0)
+ {
+ DebugBreak();
+ }
+
+ return ret;
+}
+#else
+#define AnsiToUnicode(pwsz,sz,cb) MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, sz, -1, pwsz, cb)
+#endif
+
+
+
+int AnsiToUnicodeOem(LPWSTR pwsz, LPCSTR sz, LONG cb)
+{
+ int ret;
+
+ if (AreFileApisANSI())
+ {
+ ret = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, sz, cb, pwsz, cb);
+ }
+ else
+ {
+ ret = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, sz, cb, pwsz, cb);
+ }
+
+#if DBG==1
+ CairoleAssert(ret != 0 && "Lost characters in Ansi->Unicode conversion");
+ if (ret == 0)
+ {
+ DebugBreak();
+ }
+#endif
+
+ return ret;
+}
+
+
+
+
+LPSTR Convert(LPCWSTR pwsz)
+{
+ LONG len;
+ LPSTR sz = NULL;
+
+ if (pwsz == NULL)
+ goto Exit;
+
+#if DBG==1
+ // some Win32 API accept atoms in their string parameters
+ CairoleAssert(HIWORD(pwsz)!=0 && "ATOM passed to Convert -- GP fault coming");
+#endif
+
+ len = (lstrlenW(pwsz) + 1) * 2;
+
+ sz = new CHAR[len];
+ if (sz==NULL)
+ {
+ sz = ERR;
+ goto Exit;
+ }
+
+ __try
+ {
+ UnicodeToAnsi(sz, pwsz, len);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+#if DBG==1
+ MessageBoxA(NULL, "GP fault in unicode conversion -- caught",
+ NULL, MB_OK);
+#endif
+ if (sz)
+ delete sz;
+ sz = ERR;
+ }
+
+Exit:
+ return sz;
+}
+
+
+
+
+
+
+
+
+
+LPSTR ConvertOem(LPCWSTR pwsz)
+{
+ LONG len;
+ LPSTR sz = NULL;
+
+ if (pwsz == NULL)
+ goto Exit;
+
+#if DBG==1
+ // some Win32 API accept atoms in their string parameters
+ CairoleAssert(HIWORD(pwsz)!=0 && "ATOM passed to Convert -- GP fault coming");
+#endif
+
+ len = (lstrlenW(pwsz) + 1) * 2;
+
+ sz = new CHAR[len];
+ if (sz==NULL)
+ {
+ sz = ERR;
+ goto Exit;
+ }
+
+ __try
+ {
+ UnicodeToAnsiOem(sz, pwsz, len);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+#if DBG==1
+ MessageBoxA(NULL, "GP fault in unicode conversion -- caught",
+ NULL, MB_OK);
+#endif
+ if (sz)
+ delete sz;
+ sz = ERR;
+ }
+
+Exit:
+ return sz;
+}
+
+
+
+
+
+HANDLE WINAPI CreateFileX(LPCWSTR pwsz, DWORD fdwAccess, DWORD fdwShareMask,
+ LPSECURITY_ATTRIBUTES lpsa, DWORD fdwCreate, DWORD fdwAttrsAndFlags,
+ HANDLE hTemplateFile)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("CreateFile\n");
+ #endif
+
+ CHAR sz[MAX_PATH * 2];
+ UnicodeToAnsiOem(sz, pwsz, sizeof(sz));
+
+ return CreateFileA(sz, fdwAccess, fdwShareMask, lpsa, fdwCreate,
+ fdwAttrsAndFlags, hTemplateFile);
+}
+
+BOOL WINAPI DeleteFileX(LPCWSTR pwsz)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("DeleteFile\n");
+ #endif
+
+ CHAR sz[MAX_PATH * 2];
+ UnicodeToAnsi(sz, pwsz, sizeof(sz));
+
+ return DeleteFileA(sz);
+}
+
+UINT WINAPI RegisterClipboardFormatX(LPCWSTR pwszFormat)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("RegisterClipboardFormat\n");
+ #endif
+
+ UINT ret;
+#if 0
+ LPSTR sz;
+
+ sz = Convert(pwszFormat);
+ if (sz == ERR)
+ {
+ return 0;
+ }
+#else
+ // BUGBUG: CairOLE calls this from libmain -- have to use static buffer
+
+ CHAR sz[200];
+
+ UnicodeToAnsi(sz, pwszFormat, sizeof(sz));
+#endif
+
+ ret = SSRegisterClipboardFormatA(sz);
+#if 0
+ delete sz;
+#endif
+ return ret;
+}
+
+int WINAPI GetClipboardFormatNameX(UINT format, LPWSTR pwsz,
+ int cchMaxCount)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GetClipboardFormatName\n");
+ #endif
+
+ LPSTR sz;
+ int i;
+
+ sz = new CHAR[cchMaxCount];
+ if (sz == NULL)
+ {
+ return 0;
+ }
+
+ i = SSGetClipboardFormatNameA(format, sz, cchMaxCount);
+
+ if (i)
+ {
+ AnsiToUnicode(pwsz, sz, lstrlenA(sz) + 1);
+ }
+ if (sz)
+ delete sz;
+ return i;
+}
+
+LONG APIENTRY RegOpenKeyX(HKEY hKey, LPCWSTR pwszSubKey, PHKEY phkResult)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("RegOpenKey\n");
+ #endif
+
+ LONG ret;
+ LPSTR sz;
+
+ sz = Convert(pwszSubKey);
+
+ if (sz == ERR)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ ret = RegOpenKeyA(hKey, sz, phkResult);
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+LONG APIENTRY RegQueryValueX(HKEY hKey, LPCWSTR pwszSubKey, LPWSTR pwszValue,
+ PLONG lpcbValue)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("RegQueryValue\n");
+ #endif
+
+ LONG cb, ret;
+ LPSTR szValue = NULL;
+ LPSTR sz;
+
+ sz = Convert(pwszSubKey);
+ if (sz == ERR)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ ret = RegQueryValueA(hKey, sz, NULL, &cb);
+
+ // If the caller was just asking for the size of the value, jump out
+ // now, without actually retrieving and converting the value.
+
+ if (pwszValue == NULL)
+ {
+ // Adjust size of buffer to report, to account for CHAR -> WCHAR
+ *lpcbValue = cb * sizeof(WCHAR);
+ goto Exit;
+ }
+
+
+ if (ret == ERROR_SUCCESS)
+ {
+ // If the caller was asking for the value, but allocated too small
+ // of a buffer, set the buffer size and jump out.
+
+ if (*lpcbValue < (LONG) (cb * sizeof(WCHAR)))
+ {
+ // Adjust size of buffer to report, to account for CHAR -> WCHAR
+ *lpcbValue = cb * sizeof(WCHAR);
+ ret = ERROR_MORE_DATA;
+ goto Exit;
+ }
+
+ // Otherwise, retrieve and convert the value.
+
+ szValue = new CHAR[cb];
+ if (szValue == NULL)
+ {
+ ret = ERROR_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ ret = RegQueryValueA(hKey, sz, szValue, &cb);
+
+ if (ret == ERROR_SUCCESS)
+ {
+ AnsiToUnicode(pwszValue, szValue, cb);
+
+ // Adjust size of buffer to report, to account for CHAR -> WCHAR
+ *lpcbValue = cb * sizeof(WCHAR);
+ }
+ }
+
+Exit:
+ if (szValue)
+ delete szValue;
+ if (sz)
+ delete sz;
+
+ return ret;
+}
+
+LONG APIENTRY RegSetValueX(HKEY hKey, LPCWSTR lpSubKey, DWORD dwType,
+ LPCWSTR lpData, DWORD cbData)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("RegSetValue\n");
+ #endif
+
+ LPSTR szKey = NULL;
+ LPSTR szValue = NULL;
+ LONG ret = ERROR_OUTOFMEMORY;
+
+ szKey = Convert(lpSubKey);
+ if (szKey == ERR)
+ {
+ szKey = NULL;
+ goto Exit;
+ }
+
+ szValue = Convert(lpData);
+ if (szValue == ERR)
+ {
+ szValue = NULL;
+ goto Exit;
+ }
+
+ ret = RegSetValueA(hKey, szKey, dwType, szValue, cbData);
+
+Exit:
+ if (szKey)
+ delete szKey;
+ if (szValue)
+ delete szValue;
+ return ret;
+}
+
+UINT WINAPI RegisterWindowMessageX(LPCWSTR lpString)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("RegisterWindowMessage\n");
+ #endif
+
+ UINT ret;
+#if 0
+ LPSTR sz;
+
+ sz = Convert(lpString);
+ if (sz == ERR)
+ {
+ return 0;
+ }
+#else
+ // BUGBUG: CairOLE calls this from libmain -- have to use static buffer
+
+ CHAR sz[200];
+ UnicodeToAnsi(sz, lpString, sizeof(sz));
+#endif
+
+ ret = RegisterWindowMessageA(sz);
+#if 0
+ delete sz;
+#endif
+ return ret;
+}
+
+LONG
+APIENTRY
+RegOpenKeyExX (
+ HKEY hKey,
+ LPCWSTR lpSubKey,
+ DWORD ulOptions,
+ REGSAM samDesired,
+ PHKEY phkResult
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("RegOpenKeyEx\n");
+ #endif
+
+ LONG ret;
+ LPSTR sz;
+
+ sz = Convert(lpSubKey);
+ if (sz == ERR)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ ret = RegOpenKeyExA(hKey, sz, ulOptions, samDesired, phkResult);
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+LONG
+APIENTRY
+RegQueryValueExX(
+ HKEY hKey,
+ LPWSTR lpValueName,
+ LPDWORD lpReserved,
+ LPDWORD lpType,
+ LPBYTE lpData,
+ LPDWORD lpcbData
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("RegQueryValueEx\n");
+ #endif
+
+ LPBYTE lpTempBuffer;
+ DWORD dwTempType;
+ DWORD cb, cbRequired;
+ LONG ret;
+ LPSTR sz;
+ LPWSTR pwszTempWide;
+ LPSTR pszTempNarrow;
+ ULONG ulStringLength;
+
+ sz = Convert(lpValueName);
+ if (sz == ERR)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ ret = RegQueryValueExA(hKey, sz, lpReserved, &dwTempType, NULL, &cb);
+
+ // If the caller was just asking for the size of the value, jump out
+ // now, without actually retrieving and converting the value.
+
+ if (lpData == NULL)
+ {
+ switch (dwTempType)
+ {
+ case REG_EXPAND_SZ:
+ case REG_MULTI_SZ:
+ case REG_SZ:
+
+ // Adjust size of buffer to report, to account for CHAR -> WCHAR
+
+ if (lpcbData != NULL)
+ *lpcbData = cb * sizeof(WCHAR);
+ break;
+
+ default:
+
+ if (lpcbData != NULL)
+ *lpcbData = cb;
+ break;
+ }
+
+ // Set the type, if required.
+ if (lpType != NULL)
+ {
+ *lpType = dwTempType;
+ }
+
+ goto Exit;
+ }
+
+
+ if (ret == ERROR_SUCCESS)
+ {
+ //
+ // Determine the size of buffer needed
+ //
+
+ switch (dwTempType)
+ {
+ case REG_EXPAND_SZ:
+ case REG_MULTI_SZ:
+ case REG_SZ:
+
+ cbRequired = cb * sizeof(WCHAR);
+ break;
+
+ default:
+
+ cbRequired = cb;
+ break;
+ }
+
+ // If the caller was asking for the value, but allocated too small
+ // of a buffer, set the buffer size and jump out.
+
+ if (lpcbData != NULL && *lpcbData < cbRequired)
+ {
+ // Adjust size of buffer to report, to account for CHAR -> WCHAR
+ *lpcbData = cbRequired;
+
+ // Set the type, if required.
+ if (lpType != NULL)
+ {
+ *lpType = dwTempType;
+ }
+
+ ret = ERROR_MORE_DATA;
+ goto Exit;
+ }
+
+ // Otherwise, retrieve and convert the value.
+
+ switch (dwTempType)
+ {
+ case REG_EXPAND_SZ:
+ case REG_MULTI_SZ:
+ case REG_SZ:
+
+ lpTempBuffer = new BYTE[cbRequired];
+ if (lpTempBuffer == NULL)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ ret = RegQueryValueExA(hKey,
+ sz,
+ lpReserved,
+ &dwTempType,
+ lpTempBuffer,
+ &cb);
+
+ if (ret == ERROR_SUCCESS)
+ {
+ switch (dwTempType)
+ {
+ case REG_EXPAND_SZ:
+ case REG_SZ:
+
+ AnsiToUnicode((LPWSTR) lpData, (LPSTR) lpTempBuffer, cb);
+
+ // Adjust size of buffer to report, to account for CHAR -> WCHAR
+ *lpcbData = cbRequired;
+
+ // Set the type, if required.
+ if (lpType != NULL)
+ {
+ *lpType = dwTempType;
+ }
+ break;
+
+ case REG_MULTI_SZ:
+
+ pszTempNarrow = (LPSTR) lpTempBuffer;
+ pwszTempWide = (LPWSTR) lpData;
+
+ while (*pszTempNarrow != NULL)
+ {
+ ulStringLength = strlen(pszTempNarrow) + 1;
+ AnsiToUnicode(pwszTempWide,
+ pszTempNarrow,
+ ulStringLength);
+
+ // Compiler will scale appropriately here
+ pszTempNarrow += ulStringLength;
+ pwszTempWide += ulStringLength;
+ }
+ break;
+ }
+ }
+
+ if (lpTempBuffer)
+ delete lpTempBuffer;
+
+ break;
+
+ default:
+
+ //
+ // No conversion of out parameters needed. Just call narrow
+ // version with args passed in, and return directly.
+ //
+
+ ret = RegQueryValueExA(hKey,
+ sz,
+ lpReserved,
+ lpType,
+ lpData,
+ lpcbData);
+
+ }
+ }
+
+Exit:
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+HWND
+WINAPI
+CreateWindowExX( DWORD dwExStyle,
+ LPCWSTR lpClassName,
+ LPCWSTR lpWindowName,
+ DWORD dwStyle,
+ int X,
+ int Y,
+ int nWidth,
+ int nHeight,
+ HWND hWndParent ,
+ HMENU hMenu,
+ HINSTANCE hInstance,
+ LPVOID lpParam )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("CreateWindowEx\n");
+ #endif
+
+ HWND ret = NULL;
+ LPSTR szClass;
+ LPSTR szWindow;
+ BOOL fAtom = FALSE;
+
+ if (HIWORD(lpClassName) == 0)
+ {
+ // is it an atom?
+
+ szClass = (LPSTR) lpClassName;
+ fAtom = TRUE;
+ }
+ else
+ {
+ // otherwise convert the string
+
+ szClass = Convert(lpClassName);
+ if (szClass == ERR)
+ {
+ szClass = NULL;
+ goto Exit;
+ }
+ }
+
+ szWindow = Convert(lpWindowName);
+ if (szWindow == ERR)
+ {
+ szWindow = NULL;
+ goto Exit;
+ }
+
+ ret = SSCreateWindowExA (dwExStyle, szClass, szWindow, dwStyle, X, Y,
+ nWidth, nHeight, hWndParent, hMenu, hInstance,
+ lpParam);
+
+Exit:
+ if (!fAtom)
+ if (szClass)
+ delete szClass;
+ if (szWindow)
+ delete szWindow;
+ return ret;
+}
+
+
+HWND
+WINAPI
+CreateWindowX( LPCWSTR lpClassName,
+ LPCWSTR lpWindowName,
+ DWORD dwStyle,
+ int X,
+ int Y,
+ int nWidth,
+ int nHeight,
+ HWND hWndParent ,
+ HMENU hMenu,
+ HINSTANCE hInstance,
+ LPVOID lpParam )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("CreateWindow\n");
+ #endif
+
+ return CreateWindowExX(0, lpClassName, lpWindowName, dwStyle, X, Y,
+ nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
+}
+
+
+ATOM
+WINAPI
+RegisterClassX(
+ CONST WNDCLASSW *lpWndClass)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("RegisterClass\n");
+ #endif
+
+ WNDCLASSA wc;
+ ATOM ret;
+ BOOL fAtom = FALSE;
+
+ Win4Assert(sizeof(WNDCLASSA) == sizeof(WNDCLASSW));
+
+ memcpy(&wc, lpWndClass, sizeof(WNDCLASS));
+
+ wc.lpszMenuName = Convert(lpWndClass->lpszMenuName);
+ if (wc.lpszMenuName==ERR)
+ {
+ return NULL;
+ }
+
+ if (HIWORD(lpWndClass->lpszClassName) == 0)
+ {
+ wc.lpszClassName = (LPSTR) lpWndClass->lpszClassName;
+ fAtom = TRUE;
+ }
+ else
+ {
+ wc.lpszClassName = Convert(lpWndClass->lpszClassName);
+ if (wc.lpszClassName==ERR)
+ {
+ if ((LPSTR) wc.lpszMenuName)
+ delete (LPSTR) wc.lpszMenuName;
+ return NULL;
+ }
+ }
+
+ ret = RegisterClassA(&wc);
+ if ((LPSTR) wc.lpszMenuName)
+ delete (LPSTR) wc.lpszMenuName;
+ if (!fAtom) delete (LPSTR) wc.lpszClassName;
+ return ret;
+}
+
+BOOL
+WINAPI
+UnregisterClassX(
+ LPCWSTR lpClassName,
+ HINSTANCE hInstance)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("UnregisterClass\n");
+ #endif
+
+ LPSTR sz;
+ BOOL ret;
+ BOOL fAtom = FALSE;
+
+ if (HIWORD(lpClassName) == 0)
+ {
+ sz = (LPSTR) lpClassName;
+ fAtom = TRUE;
+ }
+ else
+ {
+ sz = Convert(lpClassName);
+ if (sz == ERR)
+ return FALSE;
+ }
+
+ ret = UnregisterClassA(sz, hInstance);
+ if (!fAtom) delete sz;
+ return ret;
+}
+
+HANDLE
+WINAPI
+GetPropX(
+ HWND hWnd,
+ LPCWSTR lpString)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GetProp\n");
+ #endif
+
+ HANDLE ret;
+ LPSTR sz;
+ BOOL fAtom = FALSE;
+
+ if (HIWORD(lpString)==0)
+ {
+ fAtom = TRUE;
+ sz = (LPSTR) lpString;
+ }
+ else
+ {
+ sz = Convert(lpString);
+ if (sz == ERR)
+ return NULL;
+ }
+
+ ret = GetPropA(hWnd, sz);
+ if (!fAtom) delete sz;
+ return ret;
+}
+
+
+BOOL
+WINAPI
+SetPropX(
+ HWND hWnd,
+ LPCWSTR lpString,
+ HANDLE hData)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("SetProp\n");
+ #endif
+
+ BOOL ret;
+ LPSTR sz;
+ BOOL fAtom = FALSE;
+
+ if (HIWORD(lpString)==0)
+ {
+ sz = (LPSTR) lpString;
+ fAtom = TRUE;
+ }
+ else
+ {
+ sz = Convert(lpString);
+ if (sz == ERR)
+ return NULL;
+ }
+
+ ret = SetPropA(hWnd, sz, hData);
+ if (!fAtom) delete sz;
+ return ret;
+}
+
+
+HANDLE
+WINAPI
+RemovePropX(
+ HWND hWnd,
+ LPCWSTR lpString)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("RemoveProp\n");
+ #endif
+
+ HANDLE ret;
+ LPSTR sz;
+ BOOL fAtom = FALSE;
+
+ if (HIWORD(lpString)==0)
+ {
+ sz = (LPSTR) lpString;
+ fAtom = TRUE;
+ }
+ else
+ {
+ sz = Convert(lpString);
+ if (sz == ERR)
+ return NULL;
+ }
+
+ ret = RemovePropA(hWnd, sz);
+ if (!fAtom) delete sz;
+ return ret;
+}
+
+
+UINT
+WINAPI
+GetProfileIntX(
+ LPCWSTR lpAppName,
+ LPCWSTR lpKeyName,
+ INT nDefault
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GetProfileInt\n");
+ #endif
+
+ LPSTR szApp;
+ LPSTR szKey;
+ UINT ret;
+
+ szApp = Convert(lpAppName);
+ if (szApp==ERR)
+ {
+ return nDefault;
+ }
+
+ szKey = Convert(lpKeyName);
+ if (szApp==ERR)
+ {
+ if (szApp)
+ delete szApp;
+ return nDefault;
+ }
+
+ ret = GetProfileIntA(szApp, szKey, nDefault);
+ if (szApp)
+ delete szApp;
+ if (szKey)
+ delete szKey;
+ return ret;
+}
+
+ATOM
+WINAPI
+GlobalAddAtomX(
+ LPCWSTR lpString
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GlobalAddAtom\n");
+ #endif
+
+ ATOM ret;
+ LPSTR sz;
+
+ sz = Convert(lpString);
+ if (sz==ERR)
+ {
+ return NULL;
+ }
+
+ ret = GlobalAddAtomA(sz);
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+UINT
+WINAPI
+GlobalGetAtomNameX(
+ ATOM nAtom,
+ LPWSTR pwszBuffer,
+ int nSize
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GlobalGetAtomName\n");
+ #endif
+
+ LPSTR sz;
+ UINT ret;
+
+ sz = new CHAR[nSize];
+ if (sz == NULL)
+ {
+ return 0;
+ }
+
+ ret = GlobalGetAtomNameA(nAtom, sz, nSize);
+ if (ret)
+ {
+ AnsiToUnicode(pwszBuffer, sz, lstrlenA(sz) + 1);
+ }
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+
+DWORD
+WINAPI
+GetModuleFileNameX(
+ HINSTANCE hModule,
+ LPWSTR pwszFilename,
+ DWORD nSize
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GetModuleFileName\n");
+ #endif
+
+ LPSTR sz;
+ DWORD ret;
+
+ sz = new CHAR[nSize];
+ if (sz == NULL)
+ {
+ return 0;
+ }
+
+ ret = GetModuleFileNameA(hModule, sz, nSize);
+ if (ret)
+ {
+ AnsiToUnicode(pwszFilename, sz, lstrlenA(sz) + 1);
+ }
+
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+
+LPWSTR
+WINAPI
+CharPrevX(
+ LPCWSTR lpszStart,
+ LPCWSTR lpszCurrent)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("CharPrev\n");
+ #endif
+
+ if (lpszCurrent == lpszStart)
+ {
+ return (LPWSTR) lpszStart;
+ }
+ else
+ {
+ return (LPWSTR) lpszCurrent - 1;
+ }
+}
+
+HFONT WINAPI CreateFontX(int a, int b, int c, int d, int e, DWORD f,
+ DWORD g, DWORD h, DWORD i, DWORD j, DWORD k,
+ DWORD l, DWORD m, LPCWSTR pwsz)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("CreateFont\n");
+ #endif
+
+ LPSTR sz;
+ HFONT ret;
+
+ sz = Convert(pwsz);
+ if (sz == ERR)
+ {
+ return NULL;
+ }
+
+ ret = CreateFontA(a,b,c,d,e,f,g,h,i,j,k,l,m,sz);
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+
+HINSTANCE
+WINAPI
+LoadLibraryX(
+ LPCWSTR pwszFileName
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("LoadLibrary\n");
+ #endif
+
+ HINSTANCE ret;
+ LPSTR sz;
+
+ sz = Convert(pwszFileName);
+ if (sz == ERR)
+ {
+ return NULL;
+ }
+
+ ret = LoadLibraryA(sz);
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+
+HMODULE
+WINAPI
+LoadLibraryExX(
+ LPCWSTR lpLibFileName,
+ HANDLE hFile,
+ DWORD dwFlags
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("LoadLibrary\n");
+ #endif
+
+ HINSTANCE ret;
+ LPSTR sz;
+
+ sz = ConvertOem(lpLibFileName);
+ if (sz == ERR)
+ {
+ return NULL;
+ }
+
+ ret = LoadLibraryExA(sz, hFile, dwFlags);
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+
+
+LONG
+APIENTRY
+RegDeleteKeyX(
+ HKEY hKey,
+ LPCWSTR pwszSubKey
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("RegDeleteKey\n");
+ #endif
+
+ LONG ret;
+ LPSTR sz;
+
+ sz = Convert(pwszSubKey);
+ if (sz == ERR)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ ret = RegDeleteKeyA(hKey, sz);
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+BOOL
+APIENTRY
+CreateProcessX(
+ LPCWSTR lpApplicationName,
+ LPWSTR lpCommandLine,
+ LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ BOOL bInheritHandles,
+ DWORD dwCreationFlags,
+ LPVOID lpEnvironment,
+ LPCWSTR lpCurrentDirectory,
+ LPSTARTUPINFOW lpStartupInfo,
+ LPPROCESS_INFORMATION lpProcessInformation
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("CreateProcess\n");
+ #endif
+
+ STARTUPINFOA si;
+ BOOL ret = FALSE;
+ LPSTR szApp = NULL;
+ LPSTR szCommand = NULL;
+ LPSTR szDir = NULL;
+
+ memcpy(&si, lpStartupInfo, sizeof(STARTUPINFO));
+
+ si.lpTitle = NULL;
+
+ si.lpDesktop = Convert(lpStartupInfo->lpDesktop);
+ if (si.lpDesktop == ERR)
+ {
+ si.lpDesktop = NULL;
+ goto Error;
+ }
+ si.lpTitle = Convert(lpStartupInfo->lpTitle);
+ if (si.lpTitle == ERR)
+ {
+ si.lpTitle = NULL;
+ goto Error;
+ }
+
+ szApp = Convert(lpApplicationName);
+ if (szApp == ERR)
+ {
+ szApp = NULL;
+ goto Error;
+ }
+ szCommand = ConvertOem(lpCommandLine);
+ if (szCommand == ERR)
+ {
+ szCommand = NULL;
+ goto Error;
+ }
+ szDir = Convert(lpCurrentDirectory);
+ if (szDir == ERR)
+ {
+ szDir = NULL;
+ goto Error;
+ }
+
+ ret = CreateProcessA(szApp, szCommand, lpProcessAttributes,
+ lpThreadAttributes, bInheritHandles, dwCreationFlags,
+ lpEnvironment, szDir, &si, lpProcessInformation);
+
+Error:
+ if (si.lpDesktop)
+ delete si.lpDesktop;
+ if (si.lpTitle)
+ delete si.lpTitle;
+
+ if (szApp)
+ delete szApp;
+ if (szCommand)
+ delete szCommand;
+ if (szDir)
+ delete szDir;
+
+ return ret;
+}
+
+LONG
+APIENTRY
+RegEnumKeyExX(
+ HKEY hKey,
+ DWORD dwIndex,
+ LPWSTR lpName,
+ LPDWORD lpcbName,
+ LPDWORD lpReserved,
+ LPWSTR lpClass,
+ LPDWORD lpcbClass,
+ PFILETIME lpftLastWriteTime
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("RegEnumKeyEx\n");
+ #endif
+
+ LPSTR szName;
+ LPSTR szClass = NULL;
+ LONG ret = ERROR_OUTOFMEMORY;
+
+ szName = new CHAR[*lpcbName];
+ if (szName == NULL)
+ goto Exit;
+
+ if (lpClass != NULL)
+ {
+ szClass = new CHAR[*lpcbClass + 1];
+ if (szName == NULL)
+ goto Exit;
+ }
+
+ //
+ // Return lengths do not include zero char.
+ //
+ ret = RegEnumKeyExA(hKey, dwIndex, szName, lpcbName, lpReserved,
+ szClass, lpcbClass, lpftLastWriteTime);
+
+ if (ret == ERROR_SUCCESS)
+ {
+ AnsiToUnicode(lpName, szName, *lpcbName + 1);
+
+ if (szClass)
+ {
+ AnsiToUnicode(lpClass, szClass, *lpcbClass + 1);
+ }
+ }
+
+Exit:
+ return ret;
+}
+
+BOOL
+WINAPI
+AppendMenuX(
+ HMENU hMenu,
+ UINT uFlags,
+ UINT uIDnewItem,
+ LPCWSTR lpnewItem
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("AppendMenu\n");
+ #endif
+
+ BOOL ret;
+ LPSTR sz;
+
+ if (uFlags == MF_STRING)
+ {
+ sz = Convert(lpnewItem);
+ if (sz==ERR)
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ sz = (LPSTR) lpnewItem;
+ }
+
+ ret = AppendMenuA(hMenu, uFlags, uIDnewItem, sz);
+
+ if (uFlags == MF_STRING)
+ {
+ if (sz)
+ delete sz;
+ }
+
+ return ret;
+}
+
+HANDLE
+WINAPI
+OpenEventX(
+ DWORD dwDesiredAccess,
+ BOOL bInheritHandle,
+ LPCWSTR lpName
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("OpenEvent\n");
+ #endif
+
+ LPSTR sz;
+ HANDLE ret;
+
+ sz = Convert(lpName);
+ if (sz == ERR)
+ {
+ return NULL;
+ }
+
+ ret = OpenEventA(dwDesiredAccess, bInheritHandle, sz);
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+HANDLE
+WINAPI
+CreateEventX(
+ LPSECURITY_ATTRIBUTES lpEventAttributes,
+ BOOL bManualReset,
+ BOOL bInitialState,
+ LPCWSTR lpName
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("CreateEvent\n");
+ #endif
+
+ LPSTR sz;
+ HANDLE ret;
+
+ sz = Convert(lpName);
+ if (sz == ERR)
+ {
+ return NULL;
+ }
+
+ ret = CreateEventA(lpEventAttributes, bManualReset, bInitialState, sz);
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+UINT
+WINAPI
+GetDriveTypeX(
+ LPCWSTR lpRootPathName
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GetDriveType\n");
+ #endif
+
+ LPSTR sz;
+ UINT ret;
+
+ sz = Convert(lpRootPathName);
+ if (sz == ERR)
+ {
+ return 0;
+ }
+
+ ret = GetDriveTypeA(sz);
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+DWORD
+WINAPI
+GetFileAttributesX(
+ LPCWSTR lpFileName
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GetFileAttributes\n");
+ #endif
+
+ LPSTR sz;
+ DWORD ret;
+
+ sz = ConvertOem(lpFileName);
+ if (sz == ERR)
+ return 0xFFFFFFFF;
+
+ ret = GetFileAttributesA(sz);
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+LONG
+APIENTRY
+RegEnumKeyX(
+ HKEY hKey,
+ DWORD dwIndex,
+ LPWSTR lpName,
+ DWORD cbName
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("RegEnumKey\n");
+ #endif
+
+ CHAR sz[MAX_PATH+1];
+ LONG ret;
+
+ //
+ // Return lengths do not include zero char.
+ //
+ ret = RegEnumKeyA(hKey, dwIndex, sz, cbName);
+ if (ret == ERROR_SUCCESS)
+ {
+ AnsiToUnicode(lpName, sz, lstrlenA(sz) + 1);
+ }
+ return ret;
+}
+
+HFINDFILE
+WINAPI
+FindFirstFileX(
+ LPCWSTR lpFileName,
+ LPWIN32_FIND_DATAW pwszFd
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("FindFirstFile\n");
+ #endif
+
+ WIN32_FIND_DATAA fd;
+ CHAR sz[MAX_PATH * 2];
+ HFINDFILE ret;
+ int len = lstrlenW(lpFileName) + 1;
+
+ UnicodeToAnsiOem(sz, lpFileName, sizeof(sz));
+ ret = FindFirstFileA(sz, &fd);
+ if (ret != INVALID_HANDLE_VALUE)
+ {
+ memcpy(pwszFd, &fd, sizeof(FILETIME)*3 + sizeof(DWORD)*5);
+ AnsiToUnicodeOem(pwszFd->cFileName, fd.cFileName,
+ lstrlenA(fd.cFileName) + 1);
+ AnsiToUnicodeOem(pwszFd->cAlternateFileName, fd.cAlternateFileName,
+ 14);
+ }
+
+ return ret;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: wsprintfX
+//
+// Synopsis: Nightmare string function
+//
+// Arguments: [pwszOut] --
+// [pwszFormat] --
+// [...] --
+//
+// Returns:
+//
+// History: 1-06-94 ErikGav Created
+//
+// Notes: If you're reading this, you're probably having a problem with
+// this function. Make sure that your "%s" in the format string
+// says "%ws" if you are passing wide strings.
+//
+// %s on NT means "wide string"
+// %s on Chicago means "ANSI string"
+//
+//----------------------------------------------------------------------------
+
+int WINAPIV wsprintfX(LPWSTR pwszOut, LPCWSTR pwszFormat, ...)
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("wsprintf\n");
+ #endif
+
+ LPSTR szFormat;
+ LPWSTR pwszTemp = NULL;
+ int i = 0;
+
+ // Convert the format string over
+
+ szFormat = Convert(pwszFormat);
+ if (szFormat == ERR)
+ {
+ szFormat = NULL;
+ goto Exit;
+ }
+
+ // magic voodoo follows:
+ //
+ // 1. Call wvsprintf passing the varargs
+ // 2. Use the pwszOut as a temp buffer to hold the ANSI output
+ // 3. Save the returned characters
+
+ i = wvsprintfA((LPSTR) pwszOut, szFormat,
+ (LPSTR) ((BYTE*)&pwszFormat) + sizeof(pwszFormat));
+
+ // allocate a buffer for the Ansi to Unicode conversion
+
+ pwszTemp = new WCHAR[i+1];
+
+ // convert the string
+
+ AnsiToUnicode(pwszTemp, (LPSTR) pwszOut, i+1);
+
+ // copy it to the out buffer
+
+ lstrcpynW(pwszOut, pwszTemp, i+1);
+
+Exit:
+ if (pwszTemp)
+ delete pwszTemp;
+ if (szFormat)
+ delete szFormat;
+ return i;
+}
+
+BOOL
+WINAPI
+GetComputerNameX(
+ LPWSTR pwszName,
+ LPDWORD lpcchBuffer
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GetComputerName\n");
+ #endif
+
+ BOOL ret;
+ LPSTR sz;
+ DWORD OldSize = *lpcchBuffer;
+
+ sz = new CHAR[*lpcchBuffer];
+ ret = GetComputerNameA(sz, &OldSize);
+
+ if (ret)
+ {
+ DWORD NewSize = AnsiToUnicode(pwszName, sz, *lpcchBuffer);
+ if (NewSize) {
+ *lpcchBuffer = NewSize - 1;
+ } else {
+ *lpcchBuffer = 0;
+ }
+ }
+
+ if (sz)
+ delete sz;
+ return ret;
+}
+
+DWORD
+WINAPI
+GetFullPathNameX(
+ LPCWSTR lpFileName,
+ DWORD cchBuffer,
+ LPWSTR lpPathBuffer,
+ LPWSTR *lppFilePart
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GetFullPathName\n");
+ #endif
+
+ LPSTR szFileName;
+ CHAR szPathBuffer[MAX_PATH];
+ LPSTR szFilePart;
+ DWORD ret;
+
+
+ szFileName = ConvertOem(lpFileName);
+ if (szFileName == ERR)
+ return 0;
+
+ ret = GetFullPathNameA(szFileName, cchBuffer, szPathBuffer, &szFilePart);
+
+ AnsiToUnicode(lpPathBuffer, szPathBuffer, cchBuffer);
+
+ *lppFilePart = lpPathBuffer + (szFilePart - szPathBuffer);
+
+ if (szFileName)
+ delete szFileName;
+
+ return ret;
+}
+
+
+DWORD
+WINAPI
+GetShortPathNameX(
+ LPCWSTR lpszFullPath,
+ LPWSTR lpszShortPath,
+ DWORD cchBuffer
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GetShortPathName\n");
+ #endif
+
+ LPSTR szFullPath;
+ CHAR szShortBuffer[MAX_PATH];
+ DWORD ret;
+
+
+ szFullPath = Convert(lpszFullPath);
+ if (szFullPath == ERR)
+ return 0;
+
+ if (lpszShortPath == NULL)
+ {
+ ret = GetShortPathNameA(szFullPath, NULL, cchBuffer);
+ }
+ else
+ {
+ ret = GetShortPathNameA(szFullPath, szShortBuffer, sizeof(szShortBuffer));
+
+ //
+ // Only convert the actual data, not the whole buffer.
+ //
+ if (cchBuffer > ret + 1)
+ cchBuffer = ret + 1;
+
+ AnsiToUnicode(lpszShortPath, szShortBuffer, cchBuffer);
+ }
+
+ delete szFullPath;
+
+ return ret;
+}
+
+
+DWORD
+WINAPI
+SearchPathX(
+ LPCWSTR lpPath,
+ LPCWSTR lpFileName,
+ LPCWSTR lpExtension,
+ DWORD nBufferLength,
+ LPWSTR lpBuffer,
+ LPWSTR *lpFilePart
+ )
+{
+ LPSTR lpszFileName;
+ CHAR szBuffer[MAX_PATH];
+ DWORD ret;
+
+
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("SearchPath\n");
+ #endif
+
+ lpszFileName = Convert(lpFileName);
+ if (lpszFileName == ERR)
+ return 0;
+
+ ret = SearchPathA(NULL, lpszFileName, NULL, sizeof(szBuffer), szBuffer, NULL);
+
+ AnsiToUnicode(lpBuffer, szBuffer, lstrlenA(szBuffer) + 1);
+
+ delete lpszFileName;
+
+ return ret;
+}
+
+
+ATOM
+WINAPI
+GlobalFindAtomX(
+ LPCWSTR lpString
+ )
+{
+ LPSTR lpszString;
+ ATOM retAtom;
+
+
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GlobalFindAtom\n");
+ #endif
+
+ lpszString = Convert(lpString);
+ if (lpszString == ERR)
+ return 0;
+
+ retAtom = GlobalFindAtomA(lpszString);
+
+ delete lpszString;
+
+ return retAtom;
+}
+
+
+int
+WINAPI
+GetClassNameX(
+ HWND hWnd,
+ LPWSTR lpClassName,
+ int nMaxCount)
+{
+ LPSTR lpszClassName;
+ int ret;
+
+
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GetClassName\n");
+ #endif
+
+ lpszClassName = Convert(lpClassName);
+ if (lpszClassName == ERR)
+ return 0;
+
+ ret = GetClassNameA(hWnd, lpszClassName, nMaxCount);
+
+ delete lpszClassName;
+
+ return ret;
+}
+
+
+LPWSTR
+WINAPI
+CharLowerX(
+ LPWSTR lpsz)
+{
+ if (((DWORD)lpsz & 0xffff0000) == 0)
+ {
+ return (LPWSTR)towlower ((wchar_t)lpsz);
+ } else {
+ return _wcslwr (lpsz);
+ }
+}
+
+LPWSTR
+WINAPI
+CharUpperX(
+ LPWSTR lpsz)
+{
+ if (((DWORD)lpsz & 0xffff0000) == 0)
+ {
+ return (LPWSTR)towupper ((wchar_t)lpsz);
+ } else {
+ return _wcsupr (lpsz);
+ }
+}
+
+BOOL
+WINAPI
+GetStringTypeX(
+ DWORD dwInfoType,
+ LPCWSTR lpSrcStr,
+ int cchSrc,
+ LPWORD lpCharType)
+{
+ // Convert the source string to MBS. If we don't get the same number
+ // of characters, this algorithm doesn't work.
+
+ int OriginalLength = cchSrc == -1 ? lstrlenW (lpSrcStr) + 1 : cchSrc;
+ LPSTR lpConvertedString = new CHAR[OriginalLength+1];
+
+ if (lpConvertedString == NULL)
+ {
+ SetLastError (ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+
+ if (WideCharToMultiByte (CP_ACP,
+ WC_COMPOSITECHECK,
+ lpSrcStr,
+ cchSrc,
+ lpConvertedString,
+ OriginalLength,
+ NULL,
+ NULL) != OriginalLength)
+ {
+ delete lpConvertedString;
+ SetLastError (ERROR_NO_UNICODE_TRANSLATION);
+ return FALSE;
+ }
+
+ BOOL Result;
+
+ Result = GetStringTypeA (GetThreadLocale (),
+ dwInfoType,
+ lpConvertedString,
+ OriginalLength,
+ lpCharType);
+ delete lpConvertedString;
+ return Result;
+}
+
+BOOL
+WINAPI
+IsCharAlphaX(
+ WCHAR ch)
+{
+ return iswctype (ch, _UPPER | _LOWER);
+}
+
+BOOL
+WINAPI
+IsCharAlphaNumericX(
+ WCHAR ch)
+{
+ return iswctype (ch, _UPPER | _LOWER | _DIGIT);
+}
+
+
+LPWSTR
+WINAPI
+lstrcatX(
+ LPWSTR lpString1,
+ LPCWSTR lpString2
+ )
+{
+ LPWSTR lpDest = lpString1;
+
+ while (*lpDest) {
+ lpDest++;
+ }
+
+ while (*lpDest++ = *lpString2++) ;
+
+ return lpString1;
+}
+
+int
+WINAPI
+lstrcmpX(
+ LPCWSTR lpString1,
+ LPCWSTR lpString2
+ )
+{
+ return wcscmp(lpString1, lpString2);
+}
+
+LPWSTR
+WINAPI
+lstrcpyX(
+ LPWSTR lpString1,
+ LPCWSTR lpString2
+ )
+{
+ LPWSTR lpDest = lpString1;
+
+ while( *lpDest++ = *lpString2++ )
+ ;
+
+ return lpString1;
+}
+
+LPWSTR
+WINAPI
+lstrcpynX(
+ LPWSTR lpString1,
+ LPCWSTR lpString2,
+ int iMaxLength
+ )
+{
+ LPWSTR dst;
+
+ if (iMaxLength)
+ {
+ dst = lpString1;
+
+ while (iMaxLength && *lpString2)
+ {
+ *dst++ = *lpString2++;
+ iMaxLength--;
+ }
+ if (iMaxLength)
+ {
+ *dst = L'\0';
+ }
+ else
+ {
+ dst[-1] = L'\0';
+ }
+ }
+
+ return lpString1;
+}
+
+int
+WINAPI
+lstrcmpiX(
+ LPCWSTR lpString1,
+ LPCWSTR lpString2
+ )
+{
+ return _wcsicmp(lpString1, lpString2);
+}
+
+HANDLE
+WINAPI
+CreateFileMappingX(
+ HANDLE hFile,
+ LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
+ DWORD flProtect,
+ DWORD dwMaximumSizeHigh,
+ DWORD dwMaximumSizeLow,
+ LPCWSTR lpName
+ )
+{
+ LPSTR lpszAName;
+ HANDLE ret;
+
+
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("CreateFileMapping\n");
+ #endif
+
+ lpszAName = Convert(lpName);
+
+ if (lpszAName == ERR)
+ {
+ return 0;
+ }
+
+ ret = CreateFileMappingA(
+ hFile,
+ lpFileMappingAttributes,
+ flProtect,
+ dwMaximumSizeHigh,
+ dwMaximumSizeLow,
+ lpszAName);
+
+ delete lpszAName;
+
+ return ret;
+}
+
+
+HANDLE
+WINAPI
+OpenFileMappingX(
+ DWORD dwDesiredAccess,
+ BOOL bInheritHandle,
+ LPCWSTR lpName
+ )
+{
+ LPSTR lpszAName;
+ HANDLE ret;
+
+
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("CreateFileMapping\n");
+ #endif
+
+ lpszAName = Convert(lpName);
+
+ if (lpszAName == ERR)
+ {
+ return 0;
+ }
+
+ ret = OpenFileMappingA(
+ dwDesiredAccess,
+ bInheritHandle,
+ lpszAName);
+
+ delete lpszAName;
+
+ return ret;
+}
+
+#endif // CHICAGO
diff --git a/private/ole32/com/wx86grpa/daytona/makefile b/private/ole32/com/wx86grpa/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/com/wx86grpa/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/com/wx86grpa/daytona/sources b/private/ole32/com/wx86grpa/daytona/sources
new file mode 100644
index 000000000..6fa41adab
--- /dev/null
+++ b/private/ole32/com/wx86grpa/daytona/sources
@@ -0,0 +1,68 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= wx86grpa
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= .;..\..\..\ih;$(BASEDIR)\public\sdk\inc
+
+!if $(386)
+C_DEFINES= \
+ $(C_DEFINES)
+!else
+C_DEFINES= \
+ $(C_DEFINES) -DWX86OLE
+!endif
+
+
+SOURCES= ..\wx86grpa.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
diff --git a/private/ole32/com/wx86grpa/dirs b/private/ole32/com/wx86grpa/dirs
new file mode 100644
index 000000000..820fa2392
--- /dev/null
+++ b/private/ole32/com/wx86grpa/dirs
@@ -0,0 +1,37 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ daytona
diff --git a/private/ole32/com/wx86grpa/makefile b/private/ole32/com/wx86grpa/makefile
new file mode 100644
index 000000000..75b4046da
--- /dev/null
+++ b/private/ole32/com/wx86grpa/makefile
@@ -0,0 +1,23 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+!include $(CAIROLE)\com\makefile
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/com/wx86grpa/wx86grpa.cxx b/private/ole32/com/wx86grpa/wx86grpa.cxx
new file mode 100644
index 000000000..f06649480
--- /dev/null
+++ b/private/ole32/com/wx86grpa/wx86grpa.cxx
@@ -0,0 +1,482 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ wx86grpa.cpp
+
+Abstract:
+
+ Ole interface into Wx86
+
+Author:
+
+ 29-Sep-1995 AlanWar
+
+Revision History:
+
+--*/
+
+#ifdef WX86OLE
+
+#ifndef UNICODE
+#define UNICODE
+#endif
+
+extern "C" {
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntpsapi.h>
+}
+
+#include <ole2.h>
+
+#include <wx86grpa.hxx>
+
+CWx86 gcwx86;
+
+CWx86::CWx86()
+/*++
+
+Routine Description:
+
+ Constructor for Ole interface into Wx86. This routine assumes that
+ Wx86 is already loaded.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ HMODULE hModule;
+ PFNWX86LOADWHOLE32 pfnWx86LoadWhole32;
+ PFNWX86UNLOADWHOLE32 pfnWx86UnloadWhole32;
+
+//
+// Consults the registry to determine if Wx86 is enabled in the system
+// NOTE: this should be changed post SUR to call kernel32 which maintanes
+// this information, Instead of reading the registry each time.
+//
+
+ LONG Error;
+ HKEY hKey;
+ WCHAR ValueBuffer[MAX_PATH];
+ DWORD ValueSize;
+ DWORD dwType;
+
+ Error = RegOpenKeyW(HKEY_LOCAL_MACHINE,
+ L"System\\CurrentControlSet\\Control\\Wx86",
+ &hKey
+ );
+
+ if (Error != ERROR_SUCCESS)
+ {
+ _fIsWx86Installed = FALSE;
+ }
+ else
+ {
+
+ ValueSize = sizeof(ValueBuffer);
+ Error = RegQueryValueExW(hKey,
+ L"cmdline",
+ NULL,
+ &dwType,
+ (LPBYTE)ValueBuffer,
+ &ValueSize
+ );
+ RegCloseKey(hKey);
+
+ _fIsWx86Installed = (Error == ERROR_SUCCESS &&
+ dwType == REG_SZ &&
+ ValueSize &&
+ *ValueBuffer
+ );
+ }
+
+//
+//
+//
+
+ if ((Wx86CurrentTib()) && (hModule = GetModuleHandle(L"WX86")))
+ {
+ pfnWx86LoadWhole32 = (PFNWX86LOADWHOLE32)GetProcAddress(hModule,
+ "Wx86LoadWhole32");
+ if (pfnWx86LoadWhole32 != NULL)
+ {
+ // Obtain and check size of whole32 function table
+ _apvWholeFuncs = (*pfnWx86LoadWhole32)();
+ }
+ } else {
+ _apvWholeFuncs = NULL;
+ }
+}
+
+CWx86::~CWx86()
+/*++
+
+Routine Description:
+
+ Destructor for Ole interface into Wx86. This routine assumes that
+ wx86 is still loaded.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PFNWX86UNLOADWHOLE32 pfnWx86UnloadWhole32;
+ HMODULE hModule;
+
+ if ((_apvWholeFuncs != NULL) &&
+ (hModule = GetModuleHandle(L"WX86")))
+ {
+ _apvWholeFuncs = NULL;
+ pfnWx86UnloadWhole32 = (PFNWX86UNLOADWHOLE32)GetProcAddress(hModule,
+ "Wx86UnloadWhole32");
+ if (pfnWx86UnloadWhole32 != NULL)
+ {
+ (*pfnWx86UnloadWhole32)();
+ }
+ }
+}
+
+
+BOOL CWx86::IsModuleX86(HMODULE hModule)
+/*++
+
+Routine Description:
+
+ Determines if module specified is x86 code
+
+Arguments:
+
+ hModule is handle for the module
+
+Return Value:
+
+ TRUE if module marked as x86 code
+
+--*/
+{
+ PIMAGE_NT_HEADERS NtHeader;
+
+ if (Wx86CurrentTib() == NULL)
+ {
+ // if no wx86 then module can't be x86
+ return(FALSE);
+ }
+ NtHeader = RtlImageNtHeader(hModule);
+ return(NtHeader && NtHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_I386);
+}
+
+BOOL CWx86::IsWx86Enabled(void)
+/*++
+
+Routine Description:
+
+ Determines if Wx86 is enabled for this process
+
+Arguments:
+
+Return Value:
+ TRUE if Wx86 is enabled for this process
+
+--*/
+{
+ return(Wx86CurrentTib() != NULL);
+}
+
+
+PFNDLLGETCLASSOBJECT CWx86::TranslateDllGetClassObject(
+ PFNDLLGETCLASSOBJECT pv
+ )
+/*++
+
+Routine Description:
+
+ Translates an x86 entrypoint to DllGetClassObject to a thunk that can
+ be called by Risc Ole32.
+
+Arguments:
+
+ pv is the x86 entrypoint returned from GetProcAddress. It is assumed
+ to be an x86 address.
+
+Return Value:
+
+ Risc callable entrypoint or NULL if thunk cannot be created
+
+--*/
+{
+ if (_apvWholeFuncs)
+ {
+ return(((WX86PFNGCA)_apvWholeFuncs[WholeThunkDllGetClassObjectIdx])((PVOID)pv));
+ }
+
+ // Wx86 is not loaded so we don't try to create a thunk
+ return((PFNDLLGETCLASSOBJECT)NULL);
+}
+
+PFNDLLCANUNLOADNOW CWx86::TranslateDllCanUnloadNow(
+ PFNDLLCANUNLOADNOW pv
+ )
+/*++
+
+Routine Description:
+
+ Translates an x86 entrypoint to DllCanUnloadNow to a thunk that can
+ be called by Risc Ole32
+
+Arguments:
+
+ pv is the x86 entrypoint returned from GetProcAddress. It is assumed
+ to be an x86 address
+
+Return Value:
+
+ Risc callable entrypoint or NULL if thunk cannot be created
+
+--*/
+{
+ if (_apvWholeFuncs)
+ {
+ return(((WX86PFNCUN)_apvWholeFuncs[WholeThunkDllCanUnloadNowIdx])((PVOID)pv));
+ }
+
+ // Wx86 is not loaded so we don't try to create a thunk
+ return((PFNDLLCANUNLOADNOW)NULL);
+}
+
+void CWx86::SetStubInvokeFlag(UCHAR bFlag)
+/*++
+
+Routine Description:
+
+ Set/Reset a flag in the Wx86 thread environment to let the thunk layer
+ know that the call is a stub invoked call and allow any in or out
+ custom interface pointers to be thunked as IUnknown rather than rejecting
+ the call. Since all interface pointer parameters of a stub invoked call
+ must be marshalled or unmarshalled only the IUnknown methods must be
+ thunked.
+
+Arguments:
+
+ bFlag is the value to set flag to
+
+Return Value:
+
+--*/
+{
+ PWX86TIB pWx86Tib = Wx86CurrentTib();
+
+ if (pWx86Tib != NULL)
+ {
+ (UCHAR)(pWx86Tib->OleStubInvoked) = bFlag;
+ }
+}
+
+BOOL CWx86::NeedX86PSFactory(IUnknown *punkObj, REFIID riid)
+/*++
+
+Routine Description:
+
+ Calls Wx86 to determine if an x86 PSFactory is required.
+
+Arguments:
+ punkObj is IUnknown for which a stub would be created
+ riid is the IID for which a proxy would need to be created
+
+Return Value:
+
+ TRUE if x86 PSFactory is required
+
+--*/
+{
+ BOOL b = FALSE;
+
+ if (_apvWholeFuncs)
+ {
+ b = ((WX86PFNNXPSF)_apvWholeFuncs[WholeNeedX86PSFactoryIdx])(punkObj, riid);
+ }
+ return(b);
+}
+
+
+BOOL CWx86::IsN2XProxy(IUnknown *punk)
+/*++
+
+Routine Description:
+
+ Calls Wx86 to determine if punk is actually a Native calling X86 proxy
+
+Arguments:
+
+Return Value:
+
+ TRUE if punk is N2X proxy
+
+--*/
+{
+ BOOL b = FALSE;
+
+ if (_apvWholeFuncs)
+ {
+ b = ((WX86PFNIN2XP)_apvWholeFuncs[WholeIsN2XProxyIdx])(punk);
+ }
+ return(b);
+}
+
+BOOL CWx86::SetLoadAsX86(BOOL bFlag)
+/*++
+
+Routine Description:
+
+ Set/Reset a flag in the Wx86 thread environment to let the loader know
+ that dll is an x86 dll or not. Flag should be set whenever dll is obtained
+ from InprocServerX86 or InprocHandlerX86 keys so the loader knows to look
+ for an x86 dll first.
+
+Arguments:
+
+ bFlag is the value to set flag to
+
+Return Value:
+ Previous value of flag
+
+--*/
+{
+ PWX86TIB pWx86Tib = Wx86CurrentTib();
+ BOOL b = FALSE;
+
+ if (pWx86Tib != NULL)
+ {
+ b = pWx86Tib->UseKnownWx86Dll;
+ pWx86Tib->UseKnownWx86Dll = bFlag;
+ }
+ return(b);
+}
+
+BOOL CWx86::IsWx86Calling(void)
+/*++
+
+Routine Description:
+
+ Returns a flag that is set in the whole32 thunks when a Wx86 thread calls
+ CoGetState and CoSetState. Note that once the flag is read it is reset.
+
+Arguments:
+
+
+Return Value:
+
+--*/
+{
+ BOOL b = FALSE;
+ PWX86TIB pwx86tib = Wx86CurrentTib();
+
+ if (pwx86tib != NULL)
+ {
+ b = pwx86tib->EmulateInitialPc;
+ pwx86tib->EmulateInitialPc = FALSE;
+ }
+
+ return(b);
+}
+
+BOOL CWx86::SetIsWx86Calling(BOOL bFlag)
+/*++
+
+Routine Description:
+
+ Set the flag in the Wx86TIB that would indicate that CoSetState or
+ CoGetState was called from a Wx86 thread.
+
+Arguments:
+
+
+Return Value:
+
+--*/
+{
+ PWX86TIB pwx86tib = Wx86CurrentTib();
+ BOOL b = (pwx86tib != NULL);
+
+ if (b)
+ {
+ pwx86tib->EmulateInitialPc = bFlag;
+ }
+
+ return(b);
+}
+
+
+PVOID CWx86::UnmarshalledInSameApt(PVOID pv, REFIID piid)
+/*++
+
+Routine Description:
+
+ Call Wx86 to inform it that an interface was unmarshalled in the same
+ apartment that it was marshalled. If in this case Wx86 notices that it
+ is an interface that is being passed between a PSThunk pair then it will
+ establish a new PSThunk pair for the interface and return the proxy
+ pointer. Ole32 should then clean up the ref counts in the tables normally
+ but return the new interface pointer.
+
+Arguments:
+
+ pv is the interface that was unmarshalled into the same apartment
+ piid is the IID for the interface being unmarshalled
+
+Return Value:
+
+ NULL if wx86 doesn't know about the interface; Ole32 will proceed as
+ normal
+ (PVOID)-1 if wx86 does know about the interface, but cannot establish
+ a PSThunk. Ole should return an error from the Unmarshalling code
+ != NULL then PSThunk proxy to return to caller
+
+--*/
+{
+ if (_apvWholeFuncs)
+ {
+ pv = ((WHOLEUNMARSHALLEDINSAMEAPT)_apvWholeFuncs[WholeUnmarshalledInSameApt])(pv, piid);
+ } else {
+ pv = NULL;
+ }
+
+ return(pv);
+}
+
+void CWx86::AggregateProxy(IUnknown *punkControl, IUnknown *punk)
+/*++
+
+Routine Description:
+
+ Call Wx86 Ole thunk layer to have it aggreagate punk to punkControl if
+punk is a N2X proxy. This needs to be done to ensure that the N2X proxy
+represented by punk has the same lifetime as punkControl.
+
+Arguments:
+
+ punkControl is the controlling unknown of the proxy
+ punk is the proxy to be aggregated to punkControl
+
+
+Return Value:
+
+
+--*/
+{
+ if (_apvWholeFuncs)
+ {
+ ((WHOLEAGGREGATEPROXY)_apvWholeFuncs[WholeAggregateProxy])(punkControl, punk);
+ }
+}
+
+
+#endif
+
diff --git a/private/ole32/common/assert.cxx b/private/ole32/common/assert.cxx
new file mode 100644
index 000000000..55b0d995f
--- /dev/null
+++ b/private/ole32/common/assert.cxx
@@ -0,0 +1,419 @@
+//+---------------------------------------------------------------------------
+// Copyright (C) 1991, Microsoft Corporation.
+//
+// File: assert.cxx
+//
+// Contents: Debugging output routines for idsmgr.dll
+//
+// Functions: Assert
+// PopUpError
+//
+// History: 23-Jul-91 KyleP Created.
+// 09-Oct-91 KevinRo Major changes and comments added
+// 18-Oct-91 vich moved debug print routines out
+// 10-Jun-92 BryanT Switched to w4crt.h instead of wchar.h
+// 30-Sep-93 KyleP DEVL obsolete
+//
+//----------------------------------------------------------------------------
+
+#pragma hdrstop
+
+//
+// This one file **always** uses debugging options
+//
+
+#if DBG == 1
+
+// needed for CT TOM assert events trapping
+#include <assert.hxx>
+
+#include <stdarg.h>
+#include <stdio.h>
+
+
+# include <dprintf.h> // w4printf, w4dprintf prototypes
+# include <debnot.h>
+# ifdef FLAT
+# include <olesem.hxx>
+# endif // FLAT
+
+extern "C"
+{
+
+# ifdef FLAT
+# undef FAR
+# undef NEAR
+# else
+# define MessageBoxA MessageBox
+# endif
+
+# include <windows.h>
+}
+#ifdef _CHICAGO_
+int WINAPI SSMessageBox(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption, UINT uType);
+#endif // _CHICAGO_
+
+
+extern BOOL gfService = FALSE;
+
+unsigned long Win4InfoLevel = DEF_INFOLEVEL;
+unsigned long Win4InfoMask = 0xffffffff;
+#ifdef _CAIRO_
+unsigned long Win4AssertLevel = ASSRT_MESSAGE | ASSRT_BREAK;
+#else
+unsigned long Win4AssertLevel = ASSRT_MESSAGE | ASSRT_BREAK | ASSRT_POPUP;
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: _asdprintf
+//
+// Synopsis: Calls vdprintf to output a formatted message.
+//
+// History: 18-Oct-91 vich Created
+//
+//----------------------------------------------------------------------------
+inline void _CRTAPI1
+_asdprintf(
+ char const *pszfmt, ...)
+{
+ va_list va;
+ va_start(va, pszfmt);
+
+ vdprintf(DEB_FORCE, "Assert", pszfmt, va);
+
+ va_end(va);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: _Win4Assert, private
+//
+// Synopsis: Display assertion information
+//
+// Effects: Called when an assertion is hit.
+//
+// History: 12-Jul-91 AlexT Created.
+// 05-Sep-91 AlexT Catch Throws and Catches
+// 19-Oct-92 HoiV Added events for TOM
+//
+//----------------------------------------------------------------------------
+
+
+STDAPI_(void) Win4AssertEx(
+ char const * szFile,
+ int iLine,
+ char const * szMessage)
+{
+#if defined( FLAT )
+ //
+ // This code is for the CT Lab only. When running in the lab,
+ // all assert popups will be trapped and notifications will
+ // be sent to the manager. If running in the office (non-lab
+ // mode), the event CTTOMTrapAssertEvent will not exist and
+ // consequently, no event will be pulsed.
+ //
+
+ HANDLE hTrapAssertEvent,
+ hThreadStartEvent;
+
+ if (hTrapAssertEvent = OpenEvent(EVENT_ALL_ACCESS,
+ FALSE,
+ CAIRO_CT_TOM_TRAP_ASSERT_EVENT))
+ {
+ SetEvent(hTrapAssertEvent);
+
+ //
+ // This event is to allow TOM Manager time to perform
+ // a CallBack to the dispatcher.
+ //
+ if (hThreadStartEvent = OpenEvent(EVENT_ALL_ACCESS,
+ FALSE,
+ CAIRO_CT_TOM_THREAD_START_EVENT))
+ {
+ //
+ // Wait until it's ok to popup or until timed-out
+ //
+ WaitForSingleObject(hThreadStartEvent, TWO_MINUTES);
+ }
+ }
+#endif
+
+ if (Win4AssertLevel & ASSRT_MESSAGE)
+ {
+# ifdef FLAT
+ DWORD tid = GetCurrentThreadId();
+
+ _asdprintf("%s File: %s Line: %u, thread id %d\n",
+ szMessage, szFile, iLine, tid);
+# else // FLAT
+ _asdprintf("%s File: %s Line: %u\n", szMessage, szFile, iLine);
+# endif // FLAT
+ }
+
+ if (Win4AssertLevel & ASSRT_POPUP)
+ {
+ int id = PopUpError(szMessage,iLine,szFile);
+
+ if (id == IDCANCEL)
+ {
+#ifdef FLAT
+ DebugBreak();
+#else
+ _asm int 3;
+#endif
+ }
+ }
+ else if (Win4AssertLevel & ASSRT_BREAK)
+ {
+#ifdef FLAT
+ DebugBreak();
+#else
+ _asm int 3;
+#endif
+ }
+
+}
+
+
+//+------------------------------------------------------------
+// Function: SetWin4InfoLevel(unsigned long ulNewLevel)
+//
+// Synopsis: Sets the global info level for debugging output
+// Returns: Old info level
+//
+//-------------------------------------------------------------
+
+EXPORTIMP unsigned long APINOT
+SetWin4InfoLevel(
+ unsigned long ulNewLevel)
+{
+ unsigned long ul;
+
+ ul = Win4InfoLevel;
+ Win4InfoLevel = ulNewLevel;
+ return(ul);
+}
+
+
+//+------------------------------------------------------------
+// Function: _SetWin4InfoMask(unsigned long ulNewMask)
+//
+// Synopsis: Sets the global info mask for debugging output
+// Returns: Old info mask
+//
+//-------------------------------------------------------------
+
+EXPORTIMP unsigned long APINOT
+SetWin4InfoMask(
+ unsigned long ulNewMask)
+{
+ unsigned long ul;
+
+ ul = Win4InfoMask;
+ Win4InfoMask = ulNewMask;
+ return(ul);
+}
+
+
+//+------------------------------------------------------------
+// Function: _SetWin4AssertLevel(unsigned long ulNewLevel)
+//
+// Synopsis: Sets the global assert level for debugging output
+// Returns: Old assert level
+//
+//-------------------------------------------------------------
+
+EXPORTIMP unsigned long APINOT
+SetWin4AssertLevel(
+ unsigned long ulNewLevel)
+{
+ unsigned long ul;
+
+ ul = Win4AssertLevel;
+ Win4AssertLevel = ulNewLevel;
+ return(ul);
+}
+
+//+------------------------------------------------------------
+// Function: PopUpError
+//
+// Synopsis: Displays a dialog box using provided text,
+// and presents the user with the option to
+// continue or cancel.
+//
+// Arguments:
+// szMsg -- The string to display in main body of dialog
+// iLine -- Line number of file in error
+// szFile -- Filename of file in error
+//
+// Returns:
+// IDCANCEL -- User selected the CANCEL button
+// IDOK -- User selected the OK button
+//-------------------------------------------------------------
+
+STDAPI_(int) PopUpError(
+ char const *szMsg,
+ int iLine,
+ char const *szFile)
+{
+
+ int id;
+ static char szAssertCaption[128];
+ static char szModuleName[128];
+
+ DWORD tid = GetCurrentThreadId();
+ DWORD pid = GetCurrentProcessId();
+ char * pszModuleName;
+
+ if (GetModuleFileNameA(NULL, szModuleName, 128))
+ {
+ pszModuleName = strrchr(szModuleName, '\\');
+ if (!pszModuleName)
+ {
+ pszModuleName = szModuleName;
+ }
+ else
+ {
+ pszModuleName++;
+ }
+ }
+ else
+ {
+ pszModuleName = "Unknown";
+ }
+
+ wsprintfA(szAssertCaption,"Process: %s File: %s line %u, thread id %d.%d",
+ pszModuleName, szFile, iLine, pid, tid);
+
+
+ DWORD dwMessageFlags = MB_SETFOREGROUND | MB_TASKMODAL |
+ MB_ICONEXCLAMATION | MB_OKCANCEL;
+
+#ifndef _CHICAGO_
+ // Since this code is also used by SCM.EXE, we pass
+ // in the following flag which causes Service pop ups
+ // to appear on the desktop correctly
+
+ if (gfService)
+ {
+ dwMessageFlags |= MB_SERVICE_NOTIFICATION | MB_DEFAULT_DESKTOP_ONLY;
+ }
+
+ id = MessageBoxA(NULL,(char *) szMsg, (LPSTR) szAssertCaption,
+ dwMessageFlags);
+
+# ifdef _CAIRO_
+ // Other processes which are services also use this code, but they
+ // have no access to set gfService, so if the above failed with an
+ // access denied error (meaning no access to the default desktop)
+ // retry as a service popup. Also, remember that we are a service
+ // so we don't waste attempts later.
+ if ( !gfService && !id
+ && (GetLastError() == ERROR_ACCESS_DENIED) )
+ {
+ gfService = TRUE;
+ dwMessageFlags |= MB_SERVICE_NOTIFICATION | MB_DEFAULT_DESKTOP_ONLY;
+ id = MessageBoxA(NULL,(char *) szMsg, (LPSTR) szAssertCaption,
+ dwMessageFlags);
+ }
+# endif
+
+#else
+ id = SSMessageBox(NULL, (char *) szMsg, (LPSTR) szAssertCaption,
+ dwMessageFlags);
+
+#endif
+
+ // If id == 0, then an error occurred. There are two possibilities
+ // that can cause the error: Access Denied, which means that this
+ // process does not have access to the default desktop, and everything
+ // else (usually out of memory). Oh well.
+
+ return id;
+}
+
+//+------------------------------------------------------------
+// Function: vdprintf
+//
+// Synopsis: Prints debug output using a pointer to the
+// variable information. Used primarily by the
+// xxDebugOut macros
+//
+// Arguements:
+// ulCompMask -- Component level mask used to determine
+// output ability
+// pszComp -- String const of component prefix.
+// ppszfmt -- Pointer to output format and data
+//
+//-------------------------------------------------------------
+
+//
+// This semaphore is *outside* vdprintf because the compiler isn't smart
+// enough to serialize access for construction if it's function-local and
+// protected by a guard variable.
+//
+// KyleP - 20 May, 1993
+//
+
+
+static COleDebugMutexSem mxs;
+
+STDAPI_(void) vdprintf(
+ unsigned long ulCompMask,
+ char const *pszComp,
+ char const *ppszfmt,
+ va_list pargs)
+{
+ if ((ulCompMask & DEB_FORCE) == DEB_FORCE ||
+ ((ulCompMask | Win4InfoLevel) & Win4InfoMask))
+ {
+#if defined( FLAT )
+ mxs.Request();
+ DWORD tid = GetCurrentThreadId();
+ DWORD pid = GetCurrentProcessId();
+ if ((Win4InfoLevel & (DEB_DBGOUT | DEB_STDOUT)) != DEB_STDOUT)
+#endif // FLAT
+ {
+ if (! (ulCompMask & DEB_NOCOMPNAME))
+ {
+#ifdef FLAT
+#if defined(_CHICAGO_)
+ //
+ // Hex Process/Thread ID's are better for Chicago since both
+ // are memory addresses.
+ //
+ w4dprintf( "%08x.%08x> ", pid, tid );
+#else
+ w4dprintf( "%d.%03d> ", pid, tid );
+#endif
+#endif // FLAT
+ w4dprintf("%s: ", pszComp);
+ }
+ w4vdprintf(ppszfmt, pargs);
+ }
+
+#if defined( FLAT )
+ if (Win4InfoLevel & DEB_STDOUT)
+ {
+ if (! (ulCompMask & DEB_NOCOMPNAME))
+ {
+ w4printf( "%03d> ", tid );
+ w4printf("%s: ", pszComp);
+ }
+ w4vprintf(ppszfmt, pargs);
+ }
+
+ mxs.Release();
+#endif // FLAT
+ }
+}
+
+#else
+
+int assertDontUseThisName(void)
+{
+ return 1;
+}
+
+#endif // DBG == 1
diff --git a/private/ole32/common/buffer.cxx b/private/ole32/common/buffer.cxx
new file mode 100644
index 000000000..15ae39265
--- /dev/null
+++ b/private/ole32/common/buffer.cxx
@@ -0,0 +1,121 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: buffer.cxx
+//
+// Contents: An ASCII text-buffer for outputting to a debug stream
+//
+// Classes: CTextBufferA
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//
+//----------------------------------------------------------------------------
+#include <windows.h>
+#include "buffer.hxx"
+
+// *** CTextBufferA ***
+//+-------------------------------------------------------------------------
+//
+// Member: CTextBufferA::operator<< (const char *)
+//
+// Synopsis: String Insertion operator
+//
+// Arguments: [pStr] - string to insert into stream
+//
+// Returns: reference to this stream
+//
+// Algorithm: inserts pStr into buffer, if not enough room, flushes buffer
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+CTextBufferA &CTextBufferA::operator<<(const char *pStr)
+{
+ char *pszEnd;
+
+ pszEnd = m_szBuffer+cBufferSize;
+
+ // copy until we hit a null byte, flushing the buffer as we go if we fill up
+ while((*m_pszPos++ = *pStr++) != '\0')
+ {
+ if(m_pszPos == pszEnd)
+ {
+ Flush(); // resets m_pszPos
+ }
+ }
+
+ // we subtract one from m_pszPos because we don't want the null byte
+ // to be printed out!
+ m_pszPos--;
+
+ return *this;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTextBufferA::Insert
+//
+// Synopsis: Counted String Insertion operator
+//
+// Arguments: [pStr] - string to insert into stream
+// [nCount] - number of characters to insert into stream
+//
+//
+// Algorithm: inserts pStr into buffer, if not enough room, flushes buffer
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+void CTextBufferA::Insert(const char *pStr, size_t nCount)
+{
+ char *pszEnd;
+
+ pszEnd = m_szBuffer+cBufferSize;
+
+ // copy until we hit a null byte, flushing the buffer as we go if we fill up
+ while(nCount > 0)
+ {
+ *m_pszPos++ = *pStr++;
+ nCount--;
+
+ if(m_pszPos == pszEnd)
+ {
+ Flush(); // resets m_pszPos
+ }
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTextBufferA::Revert
+//
+// Synopsis: Revert to a previous state of the buffer, if there have
+// been no flushes since then
+//
+// Arguments: [bc] - a buffer context to retrieve the previous state from
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+BOOL CTextBufferA::Revert(const BufferContext &bc)
+{
+ if(bc.wRef == m_wFlushes)
+ {
+ // we haven't flushed since this snapshot, we can revert
+ if(((char *) bc.dwContext) < m_szBuffer || ((char *) bc.dwContext) >= (m_szBuffer+cBufferSize))
+ {
+ return FALSE; // still can't revert, because the pointer is not correct!
+ }
+
+ m_pszPos = (char *) bc.dwContext;
+
+ *(m_pszPos+1) = '\0';
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/private/ole32/common/buffer.hxx b/private/ole32/common/buffer.hxx
new file mode 100644
index 000000000..5a8ff28fd
--- /dev/null
+++ b/private/ole32/common/buffer.hxx
@@ -0,0 +1,190 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: buffer.hxx
+//
+// Contents: An ASCII text-buffer for outputting to a debug stream
+//
+// Classes: CTextBufferA
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//
+//----------------------------------------------------------------------------
+#ifndef __BUFFER_HXX__
+#define __BUFFER_HXX__
+
+#include "outfuncs.h"
+
+// The size of our text buffer
+const size_t cBufferSize = 1024;
+
+// A value that defines a "snapshot" of the buffer, in order to go back to
+// the way it was if we made a mistake.
+struct BufferContext
+{
+ DWORD dwContext; // snapshot of the buffer's context
+ WORD wRef; // the reference no of the context
+};
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTextBufferA
+//
+// Purpose: ASCII text buffer for outputting to some stream
+//
+// Interface: CTextBufferA
+// ~CTextBufferA
+// operator<< (insertion operator)
+// Flush
+// Clear
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+class CTextBufferA
+{
+ public:
+ inline CTextBufferA();
+ inline ~CTextBufferA();
+
+ CTextBufferA &operator<<(const char *pStr);
+ inline CTextBufferA &operator<<(char cChar);
+
+ // insertion operator which only does 'n' bytes
+ void Insert(const char *pStr, size_t nCount);
+
+ inline void Flush();
+
+ inline void Clear();
+
+ inline void SnapShot(BufferContext &bc) const;
+
+ // Note that if the buffer has flushed since the last snap shot
+ // it is assumed that the old buffer context is invalid, and this does nothing
+ BOOL Revert(const BufferContext &bc);
+
+ private:
+ char m_szBuffer[cBufferSize+1]; // plus one so we have space to tag on NULL byte
+ char *m_pszPos;
+ WORD m_wFlushes; // the number of times we've flushed
+};
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTextBufferA::CTextBufferA
+//
+// Synopsis: Constructor
+//
+// Arguments:
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+inline CTextBufferA::CTextBufferA()
+{
+ m_pszPos = m_szBuffer;
+ m_wFlushes = 0;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTextBufferA::~CTextBufferA
+//
+// Synopsis: Destructor
+//
+// Algorithm: calls Flush() before destroying object
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+inline CTextBufferA::~CTextBufferA()
+{
+ Flush(); // flush our buffer out before we're done
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTextBufferA::operator<< (char)
+//
+// Synopsis: Character Insertion operator
+//
+// Arguments: [cChar] - char to insert into stream
+//
+// Returns: reference to this stream
+//
+// Algorithm: inserts pStr into buffer, if not enough room, flushes buffer
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+inline CTextBufferA &CTextBufferA::operator<<(char cChar)
+{
+ *m_pszPos++ = cChar;
+
+ if(m_pszPos == m_szBuffer+cBufferSize)
+ {
+ Flush(); // flush our output
+ }
+
+ return *this;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTextBufferA::Clear
+//
+// Synopsis: Clear (reset) buffer
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+inline void CTextBufferA::Clear()
+{
+ m_pszPos = m_szBuffer;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTextBufferA::Flush
+//
+// Synopsis: Flushes buffer to output
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+inline void CTextBufferA::Flush()
+{
+ // tag on NULL byte
+ *(m_pszPos+1) = '\0';
+
+ // Call output functions to dump the string
+ CallOutputFunctions(m_szBuffer);
+
+ m_wFlushes++;
+
+ Clear();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTextBufferA::SnapShot
+//
+// Synopsis: Takes a snap shot of the current buffer, so that
+// it may be reverted to later
+//
+// Arguments: [bc] - a buffer context to store the snap shot into
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+inline void CTextBufferA::SnapShot(BufferContext &bc) const
+{
+ bc.dwContext = (DWORD) m_pszPos;
+ bc.wRef = m_wFlushes;
+}
+
+#endif
+
diff --git a/private/ole32/common/ccompapi.cxx b/private/ole32/common/ccompapi.cxx
new file mode 100644
index 000000000..9598e7b82
--- /dev/null
+++ b/private/ole32/common/ccompapi.cxx
@@ -0,0 +1,250 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: ccompapi.cxx
+//
+// Contents: common compobj API Worker routines used by com, stg, scm etc
+//
+// Classes:
+//
+// Functions:
+//
+// History: 31-Dec-93 ErikGav Chicago port
+//
+//----------------------------------------------------------------------------
+
+#include <windows.h>
+#include <ole2sp.h>
+#include <ole2com.h>
+
+
+NAME_SEG(CompApi)
+ASSERTDATA
+
+static const BYTE GuidMap[] = { 3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-',
+ 8, 9, '-', 10, 11, 12, 13, 14, 15 };
+
+static const WCHAR wszDigits[] = L"0123456789ABCDEF";
+
+LPVOID WINAPI PrivHeapAlloc(HANDLE hHeap, DWORD dwFlags, DWORD dwBytes);
+BOOL WINAPI PrivHeapFree (HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
+
+HANDLE g_hHeap = 0;
+HEAP_ALLOC_ROUTINE *pfnHeapAlloc = PrivHeapAlloc;
+HEAP_FREE_ROUTINE *pfnHeapFree = PrivHeapFree;
+
+//+-------------------------------------------------------------------------
+//
+// Function: PrivHeapAlloc (internal)
+//
+// Synopsis: Allocate memory from the heap.
+//
+// Notes: This function handles the first call to PrivMemAlloc.
+// This function changes pfnHeapAlloc so that subsequent calls
+// to PrivMemAlloc will go directly to HeapAlloc.
+//
+//--------------------------------------------------------------------------
+LPVOID WINAPI PrivHeapAlloc(HANDLE hHeap, DWORD dwFlags, DWORD dwBytes)
+{
+ g_hHeap = GetProcessHeap();
+
+ //GetProcessHeap should never fail.
+ Win4Assert(g_hHeap != 0 && "GetProcessHeap failed");
+
+ pfnHeapFree = HeapFree;
+ pfnHeapAlloc = HeapAlloc;
+ return HeapAlloc(g_hHeap, dwFlags, dwBytes);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: PrivHeapFree (internal)
+//
+// Synopsis: Free memory from the heap.
+//
+// Notes: lpMem should always be zero. We assume that memory
+// freed via PrivMemFree has been allocated via PrivMemAlloc.
+// The first call to PrivMemAlloc changes pfnHeapFree.
+// Subsequent calls to PrivMemFree go directly to HeapFree.
+// Therefore PrivHeapFree should never be called with a
+// non-zero lpMem.
+//
+//--------------------------------------------------------------------------
+BOOL WINAPI PrivHeapFree (HANDLE hHeap, DWORD dwFlags, LPVOID lpMem)
+{
+ Win4Assert(lpMem == 0 && "PrivMemFree requires PrivMemAlloc.");
+ return FALSE;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wStringFromUUID (internal)
+//
+// Synopsis: converts UUID into xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+//
+// Arguments: [rguid] - the guid to convert
+// [lpszy] - buffer to hold the results
+//
+// Returns: Number of characters copied to the buffer.
+//
+//--------------------------------------------------------------------------
+INTERNAL wStringFromUUID(REFGUID rguid, LPWSTR lpsz)
+{
+ int i;
+ LPWSTR p = lpsz;
+
+ const BYTE * pBytes = (const BYTE *) &rguid;
+
+ for (i = 0; i < sizeof(GuidMap); i++)
+ {
+ if (GuidMap[i] == '-')
+ {
+ *p++ = L'-';
+ }
+ else
+ {
+ *p++ = wszDigits[ (pBytes[GuidMap[i]] & 0xF0) >> 4 ];
+ *p++ = wszDigits[ (pBytes[GuidMap[i]] & 0x0F) ];
+ }
+ }
+
+ *p = L'\0';
+
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wStringFromGUID2 (internal)
+//
+// Synopsis: converts GUID into {...} form without leading identifier;
+//
+// Arguments: [rguid] - the guid to convert
+// [lpszy] - buffer to hold the results
+// [cbMax] - sizeof the buffer
+//
+// Returns: amount of data copied to lpsz if successful
+// 0 if buffer too small.
+//
+//--------------------------------------------------------------------------
+INTERNAL_(int) wStringFromGUID2(REFGUID rguid, LPWSTR lpsz, int cbMax)
+{
+ int i;
+ LPWSTR p = lpsz;
+
+ if(cbMax < GUIDSTR_MAX)
+ return 0;
+
+ *p++ = L'{';
+
+ wStringFromUUID(rguid, p);
+
+ p += 36;
+
+ *p++ = L'}';
+ *p = L'\0';
+
+ return GUIDSTR_MAX;
+}
+
+static const CHAR szDigits[] = "0123456789ABCDEF";
+//+-------------------------------------------------------------------------
+//
+// Function: wStringFromGUID2A (internal)
+//
+// Synopsis: Ansi version of wStringFromGUID2 (for Win95 Optimizations)
+//
+// Arguments: [rguid] - the guid to convert
+// [lpszy] - buffer to hold the results
+// [cbMax] - sizeof the buffer
+//
+// Returns: amount of data copied to lpsz if successful
+// 0 if buffer too small.
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(int) wStringFromGUID2A(REFGUID rguid, LPSTR lpsz, int cbMax) // internal
+{
+ int i;
+ LPSTR p = lpsz;
+
+ const BYTE * pBytes = (const BYTE *) &rguid;
+
+ *p++ = '{';
+
+ for (i = 0; i < sizeof(GuidMap); i++)
+ {
+ if (GuidMap[i] == '-')
+ {
+ *p++ = '-';
+ }
+ else
+ {
+ *p++ = szDigits[ (pBytes[GuidMap[i]] & 0xF0) >> 4 ];
+ *p++ = szDigits[ (pBytes[GuidMap[i]] & 0x0F) ];
+ }
+ }
+ *p++ = '}';
+ *p = '\0';
+
+ return GUIDSTR_MAX;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: FormatHexNumA
+//
+// Synopsis: Given a value, and a count of characters, translate
+// the value into a hex string. This is the ANSI version
+//
+// Arguments: [ulValue] -- Value to convert
+// [chChars] -- Number of characters to format
+// [pchStr] -- Pointer to output buffer
+//
+// Requires: pwcStr must be valid for chChars
+//
+// History: 12-Dec-95 KevinRo Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void FormatHexNumA( unsigned long ulValue, unsigned long chChars, char *pchStr)
+{
+ while(chChars--)
+ {
+ pchStr[chChars] = (char) szDigits[ulValue & 0xF];
+ ulValue = ulValue >> 4;
+ }
+}
+//+---------------------------------------------------------------------------
+//
+// Function: FormatHexNumW
+//
+// Synopsis: Given a value, and a count of characters, translate
+// the value into a hex string. This is the WCHAR version
+//
+// Arguments: [ulValue] -- Value to convert
+// [chChars] -- Number of characters to format
+// [pwcStr] -- Pointer to output buffer
+//
+// Requires: pwcStr must be valid for chChars
+//
+// History: 12-Dec-95 KevinRo Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void FormatHexNumW( unsigned long ulValue, unsigned long chChars, WCHAR *pwcStr)
+{
+ while(chChars--)
+ {
+ pwcStr[chChars] = (char) wszDigits[ulValue & 0xF];
+ ulValue = ulValue >> 4;
+ }
+}
+
diff --git a/private/ole32/common/comsrgt.cxx b/private/ole32/common/comsrgt.cxx
new file mode 100644
index 000000000..0b3ed9045
--- /dev/null
+++ b/private/ole32/common/comsrgt.cxx
@@ -0,0 +1,18 @@
+///+---------------------------------------------------------------------------
+//
+// File: comsrgt.cxx
+//
+// Contents: Implementation of CCOMSurrogate class for synchronizing access
+// to this process's ISurrogate
+//
+// Functions: all inline -- see the header file
+//
+// History: 21-Oct-96 t-adame
+//
+//----------------------------------------------------------------------------
+
+#include <comsrgt.hxx>
+
+LPSURROGATE CCOMSurrogate::_pSurrogate = NULL;
+
+
diff --git a/private/ole32/common/cruntime/crt0dat.c b/private/ole32/common/cruntime/crt0dat.c
new file mode 100644
index 000000000..3b93ce0e6
--- /dev/null
+++ b/private/ole32/common/cruntime/crt0dat.c
@@ -0,0 +1,518 @@
+/***
+*crt0dat.c - 32-bit C run-time initialization/termination routines
+*
+* Copyright (c) 1986-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module contains the routines _cinit, exit, and _exit
+* for C run-time startup and termination. _cinit and exit
+* are called from the _astart code in crt0.asm.
+* This module also defines several data variables used by the
+* runtime.
+*
+* [NOTE: Lock segment definitions are at end of module.]
+*
+* *** FLOATING POINT INITIALIZATION AND TERMINATION ARE NOT ***
+* *** YET IMPLEMENTED IN THIS FILE ***
+*
+*Revision History:
+* 06-28-89 PHG Module created, based on asm version
+* 04-09-90 GJF Added #include <cruntime.h>. Made calling type
+* explicit (_CALLTYPE1 or _CALLTYPE4). Also, fixed
+* the copyright.
+* 04-10-90 GJF Fixed compiler warnings (-W3).
+* 05-21-90 GJF Added #undef _NFILE_ (temporary hack) and fixed the
+* indents.
+* 08-31-90 GJF Removed 32 from API names.
+* 09-25-90 GJF Merged tree version with local (8-31 and 5-21 changes).
+* 10-08-90 GJF New-style function declarators.
+* 10-12-90 GJF Removed divide by 0 stuff.
+* 10-18-90 GJF Added _pipech[] array.
+* 11-05-90 GJF Added _umaskval.
+* 12-04-90 GJF Added _osfinfo[] definition for Win32 target. Note that
+* the Win32 support is still incomplete!
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-04-90 SRW Added _osfile back for win32. Changed _osfinfo from
+* an array of structures to an array of 32-bit handles
+* (_osfhnd)
+* 12-28-90 SRW Added _CRUISER_ conditional around pack pragmas
+* 01-29-91 GJF ANSI naming.
+* 01-29-91 SRW Added call to GetFileType [_WIN32_]
+* 02-18-91 SRW Removed duplicate defintion of _NFILE_ (see os2dll.h)
+* 04-04-91 GJF Added definitions for _base[version|major|minor]
+* (_WIN32_).
+* 04-08-91 GJF Temporary hack for Win32/DOS folks - added HeapDestroy
+* call to doexit to tear down the OS heap used by C
+* heap.
+* 04-09-91 PNT Added _MAC_ conditional
+* 04-26-91 SRW Removed level 3 warnings
+* 07-16-91 GJF Added fp initialization test-and-call [_WIN32_].
+* 07-26-91 GJF Revised initialization and termination stuff. In
+* particular, removed need for win32ini.c [_WIN32_].
+* 08-07-91 GJF Added init. for FORTRAN runtime, if present [_WIN32_].
+* 08-21-91 GJF Test _prmtmp against NULL, not _prmtmp().
+* 08-21-91 JCR Added _exitflag, _endstdio, _cpumode, etc.
+* 09-09-91 GJF Revised _doinitterm for C++ init. support and to make
+* _onexit/atexit compatible with C++ needs.
+* 09-16-91 GJF Must test __onexitend before calling _doinitterm.
+* 10-29-91 GJF Force in floating point initialization for MIPS
+* compiler [_WIN32_].
+* 11-13-91 GJF FORTRAN needs _onexit/atexit init. before call thru
+* _pFFinit.
+* 01-10-92 GJF Merged. Also, added _C_Termination_Done [_WIN32_].
+* 02-13-92 GJF Moved all lowio initialization to ioinit.c for Win32.
+* 03-12-92 SKS Major changes to initialization/termination scheme
+* 04-16-92 DJM POSIX support.
+* 04-17-92 SKS Export _initterm() for CRTDLL model
+* 05-07-92 DJM Removed _exit() from POSIX build.
+* 06-03-92 GJF Temporarily restored call to FORTRAN init.
+* 08-26-92 SKS Add _osver, _winver, _winmajor, _winminor
+* 08-28-92 GJF Use unistd.h for POSIX build.
+* 09-02-92 SKS Fix _onexit table traversal to be LIFO.
+* Since table is built forward (my changes 03-12-92)
+* the table must be traversed in reverse order.
+* 10-30-92 TVB Force in floating point initialization for ALPHA
+* compiler as was done for MIPS. [_WIN32_].
+* 11-12-92 SKS Remove hard-coded call to FORTRAN initializer
+* 05-11-93 SKS _C_Termination_Done is now used by DLLs in LIBC/LIBCMT
+* models, not just in CRTDLL.DLL.
+* Remove obsolete variable _child.
+* 07-16-93 SRW ALPHA Merge
+*
+*******************************************************************************/
+
+#include <windows.h>
+#include <cruntime.h>
+#include <internal.h>
+#include <os2dll.h>
+
+
+/* callable exit flag */
+char _exitflag = 0;
+
+/*
+ * flag indicating if C runtime termination has been done. set if exit,
+ * _exit, _cexit or _c_exit has been called. checked when _CRTDLL_INIT
+ * or user DLL's _CRT_INIT is called with DLL_PROCESS_DETACH.
+ */
+int _C_Termination_Done = FALSE;
+
+/*
+ * useful type for initialization and termination declarations
+ */
+typedef void (_CALLTYPE1 *PF)(void);
+
+
+/*
+ * NOTE: THE USE OF THE POINTERS DECLARED BELOW DEPENDS ON THE PROPERTIES
+ * OF C COMMUNAL VARIABLES. SPECIFICALLY, THEY ARE NON-NULL IFF THERE EXISTS
+ * A DEFINITION ELSEWHERE INITIALIZING THEM TO NON-NULL VALUES.
+ */
+
+/*
+ * pointers to initialization functions
+ */
+
+PF _FPinit; /* floating point init. */
+
+/*
+ * pointers to initialization sections
+ */
+
+extern PF __xi_a[], __xi_z[]; /* C initializers */
+extern PF __xc_a[], __xc_z[]; /* C++ initializers */
+extern PF __xp_a[], __xp_z[]; /* C pre-terminators */
+extern PF __xt_a[], __xt_z[]; /* C terminators */
+
+#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+/*
+ * For MIPS or ALPHA compilers, must explicitly force in and call the floating
+ * point initialization (those system always have floating-point hardware).
+ */
+extern void _CALLTYPE1 _fpmath(void);
+#endif
+
+/*
+ * pointers to the start and finish of the _onexit/atexit table
+ */
+PF *__onexitbegin;
+PF *__onexitend;
+
+
+/*
+ * static (internal) function that walks a table of function pointers,
+ * calling each entry between the two pointers, skipping NULL entries
+ *
+ * Needs to be exported for CRT DLL so that C++ initializers in the
+ * client EXE / DLLs can be initialized
+ */
+
+void _CALLTYPE4 _initterm(PF *, PF *);
+
+
+#pragma data_seg()
+
+/***
+*_cinit - C initialization
+*
+*Purpose:
+* This routine performs the shared DOS and Windows initialization.
+* The following order of initialization must be preserved -
+*
+ifdef MTHREAD
+* 0. Call OS2 to bump max file count (mthread only)
+endif
+* 1. Check for devices for file handles 0 - 2
+* 2. Integer divide interrupt vector setup
+* 3. General C initializer routines
+*
+*Entry:
+* No parameters: Called from __crtstart and assumes data
+* set up correctly there.
+*
+*Exit:
+* Initializes C runtime data.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _cinit (
+ void
+ )
+{
+
+ /*
+ * initialize floating point package, if present
+ */
+#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+ /*
+ * The Mips, Alpha, and PPC compilers don't emit external reference to
+ * _fltused. Therefore, must always force in the floating point
+ * initialization.
+ */
+ _fpmath();
+#else
+ if ( _FPinit != NULL )
+ (*_FPinit)();
+#endif
+
+ /*
+ * do initializations
+ */
+ _initterm( __xi_a, __xi_z );
+
+ /*
+ * do C++ initializations
+ */
+ _initterm( __xc_a, __xc_z );
+
+
+}
+
+
+/***
+*exit(status), _exit(status), _cexit(void), _c_exit(void) - C termination
+*
+*Purpose:
+*
+* Entry points:
+*
+* exit(code): Performs all the C termination functions
+* and terminates the process with the return code
+* supplied by the user.
+*
+* _exit(code): Performs a quick exit routine that does not
+* do certain 'high-level' exit processing. The _exit
+* routine terminates the process with the return code
+* supplied by the user.
+*
+* _cexit(): Performs the same C lib termination processing
+* as exit(code) but returns control to the caller
+* when done (i.e., does NOT terminate the process).
+*
+* _c_exit(): Performs the same C lib termination processing
+* as _exit(code) but returns control to the caller
+* when done (i.e., does NOT terminate the process).
+*
+* Termination actions:
+*
+* exit(), _cexit():
+*
+* 1. call user's terminator routines
+* 2. call C runtime preterminators
+*
+* _exit(), _c_exit():
+*
+* 3. call C runtime terminators
+* 4. return to DOS or caller
+*
+* Notes:
+*
+* The termination sequence is complicated due to the multiple entry
+* points sharing the common code body while having different entry/exit
+* sequences.
+*
+* Multi-thread notes:
+*
+* 1. exit() should NEVER be called when mthread locks are held.
+* The exit() routine can make calls that try to get mthread locks.
+*
+* 2. _exit()/_c_exit() can be called from anywhere, with or without locks held.
+* Thus, _exit() can NEVER try to get locks (otherwise, deadlock
+* may occur). _exit() should always 'work' (i.e., the process
+* should always terminate successfully).
+*
+* 3. Only one thread is allowed into the exit code (see _lockexit()
+* and _unlockexit() routines).
+*
+*Entry:
+* exit(), _exit()
+* int status - exit status (0-255)
+*
+* _cexit(), _c_exit()
+* <no input>
+*
+*Exit:
+* exit(), _exit()
+* <EXIT to DOS>
+*
+* _cexit(), _c_exit()
+* Return to caller
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+/* worker routine prototype */
+static void _CALLTYPE4 doexit (int code, int quick, int retcaller);
+
+void _CALLTYPE1 exit (
+ int code
+ )
+{
+ doexit(code, 0, 0); /* full term, kill process */
+}
+
+#ifndef _POSIX_
+
+void _CALLTYPE1 _exit (
+ int code
+ )
+{
+ doexit(code, 1, 0); /* quick term, kill process */
+}
+
+void _CALLTYPE1 _cexit (
+ void
+ )
+{
+ doexit(0, 0, 1); /* full term, return to caller */
+}
+
+void _CALLTYPE1 _c_exit (
+ void
+ )
+{
+ doexit(0, 1, 1); /* quick term, return to caller */
+}
+
+#endif /* _POSIX_ */
+
+
+static void _CALLTYPE4 doexit (
+ int code,
+ int quick,
+ int retcaller
+ )
+{
+ _lockexit(); /* assure only 1 thread in exit path */
+
+
+ /* save callable exit flag (for use by terminators) */
+ _exitflag = (char) retcaller; /* 0 = term, !0 = callable exit */
+
+ if (!quick) {
+
+ /*
+ * do _onexit/atexit() terminators
+ * (if there are any)
+ *
+ * These terminators MUST be executed in reverse order (LIFO)!
+ *
+ * NOTE:
+ * This code assumes that __onexitbegin points
+ * to the first valid onexit() entry and that
+ * __onexitend points past the last valid entry.
+ * If __onexitbegin == __onexitend, the table
+ * is empty and there are no routines to call.
+ */
+
+ if (__onexitbegin) {
+ PF * pfend = __onexitend;
+
+ while ( -- pfend >= __onexitbegin )
+ /*
+ * if current table entry is non-NULL,
+ * call thru it.
+ */
+ if ( *pfend != NULL )
+ (**pfend)();
+ }
+
+ /*
+ * do pre-terminators
+ */
+ _initterm(__xp_a, __xp_z);
+ }
+
+ /*
+ * do terminators
+ */
+ _initterm(__xt_a, __xt_z);
+
+
+/********** FLOATING POINT TERMINATION SHOULD GO HERE ************/
+
+ /* return to OS/2 or to caller */
+ if (retcaller) {
+ _unlockexit(); /* unlock the exit code path */
+ return;
+ }
+
+ ExitProcess(code);
+
+}
+
+/***
+* _lockexit - Aquire the exit code lock
+*
+*Purpose:
+* Makes sure only one thread is in the exit code at a time.
+* If a thread is already in the exit code, it must be allowed
+* to continue. All other threads must pend.
+*
+* Notes:
+*
+* (1) It is legal for a thread that already has the lock to
+* try and get it again(!). That is, consider the following
+* sequence:
+*
+* (a) program calls exit()
+* (b) thread locks exit code
+* (c) user onexit() routine calls _exit()
+* (d) same thread tries to lock exit code
+*
+* Since _exit() must ALWAYS be able to work (i.e., can be called
+* from anywhere with no regard for locking), we must make sure the
+* program does not deadlock at step (d) above.
+*
+* (2) If a thread executing exit() or _exit() aquires the exit lock,
+* other threads trying to get the lock will pend forever. That is,
+* since exit() and _exit() terminate the process, there is not need
+* for them to unlock the exit code path.
+*
+* (3) Note that onexit()/atexit() routines call _lockexit/_unlockexit
+* to protect mthread access to the onexit table.
+*
+* (4) The _lockexit/_unlockexit routines are very complicated in 286
+* OS/2 since a thread that held a lock could not request the lock again.
+* The 32-bit OS/2 semaphore calls DO allow a single thread to aquire the
+* same lock multiple times* thus, this version is straight forward.
+*
+*Entry: <none>
+*
+*Exit:
+* Calling thread has exit code path locked on return.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _lockexit (
+ void
+ )
+{
+ _mlock(_EXIT_LOCK1);
+}
+
+/***
+* _unlockexit - Release exit code lock
+*
+*Purpose:
+* [See _lockexit() description above.]
+*
+* This routine is called by _cexit(), _c_exit(), and onexit()/atexit().
+* The exit() and _exit() routines never unlock the exit code path since
+* they are terminating the process.
+*
+*Entry:
+* Exit code path is unlocked.
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CALLTYPE1 _unlockexit (
+ void
+ )
+{
+ _munlock(_EXIT_LOCK1);
+}
+
+
+/***
+* static void _initterm(PF * pfbegin, PF * pfend) - call entries in
+* function pointer table
+*
+*Purpose:
+* Walk a table of function pointers, calling each entry, as follows:
+*
+* 1. walk from beginning to end, pfunctbl is assumed to point
+* to the beginning of the table, which is currently a null entry,
+* as is the end entry.
+* 2. skip NULL entries
+* 3. stop walking when the end of the table is encountered
+*
+*Entry:
+* PF *pfbegin - pointer to the beginning of the table (first valid entry).
+* PF *pfend - pointer to the end of the table (after last valid entry).
+*
+*Exit:
+* No return value
+*
+*Notes:
+* This routine must be exported in the CRT DLL model so that the client
+* EXE and client DLL(s) can call it to initialize their C++ constructors.
+*
+*Exceptions:
+* If either pfbegin or pfend is NULL, or invalid, all bets are off!
+*
+*******************************************************************************/
+
+void _CALLTYPE4 _initterm (
+ PF * pfbegin,
+ PF * pfend
+ )
+{
+ /*
+ * walk the table of function pointers from the bottom up, until
+ * the end is encountered. Do not skip the first entry. The initial
+ * value of pfbegin points to the first valid entry. Do not try to
+ * execute what pfend points to. Only entries before pfend are valid.
+ */
+ while ( pfbegin < pfend )
+ {
+ /*
+ * if current table entry is non-NULL, call thru it.
+ */
+ if ( *pfbegin != NULL )
+ (**pfbegin)();
+ ++pfbegin;
+ }
+}
+
diff --git a/private/ole32/common/cruntime/crt0init.c b/private/ole32/common/cruntime/crt0init.c
new file mode 100644
index 000000000..9dd53b8b0
--- /dev/null
+++ b/private/ole32/common/cruntime/crt0init.c
@@ -0,0 +1,70 @@
+/***
+*crt0init.c - Initialization segment declarations.
+*
+* Copyright (c) 1992-1994, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Do initialization segment declarations.
+*
+*Notes:
+* In the 16-bit C world, the X*B and X*E segments were empty except for
+* a label. This will not work with COFF since COFF throws out empty
+* sections. Therefore we must put a zero value in them. (Zero because
+* the routine to traverse the initializers will skip over zero entries.)
+*
+*Revision History:
+* 03-19-92 SKS Module created.
+* 03-24-92 SKS Added MIPS support (NO_UNDERSCORE)
+* 08-06-92 SKS Revised to use new section names and macros
+* 10-19-93 SKS Add .DiRECTiVE section for MIPS, too!
+* 10-28-93 GJF Rewritten in C
+* 10-28-94 SKS Add user32.lib as a default library
+* 02-27-95 CFW Remove user32.lib as a default library
+*
+*******************************************************************************/
+
+#ifdef _MSC_VER
+
+
+#include <stdio.h>
+#include <internal.h>
+
+#pragma data_seg(".CRT$XIA")
+_PVFV __xi_a[] = { NULL };
+
+
+#pragma data_seg(".CRT$XIZ")
+_PVFV __xi_z[] = { NULL };
+
+
+#pragma data_seg(".CRT$XCA")
+_PVFV __xc_a[] = { NULL };
+
+
+#pragma data_seg(".CRT$XCZ")
+_PVFV __xc_z[] = { NULL };
+
+
+#pragma data_seg(".CRT$XPA")
+_PVFV __xp_a[] = { NULL };
+
+
+#pragma data_seg(".CRT$XPZ")
+_PVFV __xp_z[] = { NULL };
+
+
+#pragma data_seg(".CRT$XTA")
+_PVFV __xt_a[] = { NULL };
+
+
+#pragma data_seg(".CRT$XTZ")
+_PVFV __xt_z[] = { NULL };
+
+
+#pragma data_seg(".drectve")
+static char __drectve_win32lib[] =
+ "-merge:.CRT=.rdata -ignore:4078";
+#pragma data_seg() /* reset */
+
+#endif /* _MSC_VER */
+
diff --git a/private/ole32/common/cruntime/crt32.def b/private/ole32/common/cruntime/crt32.def
new file mode 100644
index 000000000..abfbf0a61
--- /dev/null
+++ b/private/ole32/common/cruntime/crt32.def
@@ -0,0 +1,34 @@
+####
+#crt32.def - definitions for the crt32 build
+#
+# Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+#
+#Purpose:
+# This file is included in the 'sources' files in this tree
+#
+# Key to CRT32 environment variables:
+#
+#
+################################################################################
+
+NTDEBUG=
+
+NTLEGO=1
+
+TARGETNAMESUFFIX=mt
+TARGETTYPE=LIBRARY
+MTOPTION=-DMTHREAD -D_MT
+C_DEFINES1=-D_WIN32_=1 -D_INTL -D_MBCS -D_KANJI
+ASM_DEFINES1=-D_WIN32_=1 -D_INTL
+INCLUDES=..\h
+
+!IF "$(CRTLIBDEBUG)" == ""
+C_DEFINES=-DNDEBUG $(C_DEFINES1) $(MTOPTION) $(MBCS_DEFINES)
+ASM_DEFINES=$(ASM_DEFINES1) $(MTOPTION) $(MBCS_DEFINES)
+!ELSE
+C_DEFINES=$(C_DEFINES1) -DDEBUG=1 $(MTOPTION) $(MBCS_DEFINES)
+ASM_DEFINES=$(ASM_DEFINES1) -DDEBUG=1 $(MTOPTION) $(MBCS_DEFINES)
+!ENDIF
+
+# Disable intrinsics on Alpha as it will not allow redefinition of intrinsics
+ALPHA_OPTIMIZATION=/Ox /Oi-
diff --git a/private/ole32/common/cruntime/cruntime.h b/private/ole32/common/cruntime/cruntime.h
new file mode 100644
index 000000000..de8549076
--- /dev/null
+++ b/private/ole32/common/cruntime/cruntime.h
@@ -0,0 +1,277 @@
+/***
+*cruntime.h - definitions specific to the target operating system and
+* hardware
+*
+* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This header file contains widely used definitions specific to the
+* host operating system and hardware. It is included by every C source
+* and most every other header file.
+* [Internal]
+*
+*Revision History:
+* 02-27-90 GJF File created
+* 03-06-90 GJF Added register macros (REG1,...,etc.)
+* 04-11-90 GJF Set _CALLTYPE1 and _CALLTYPE4 to _stdcall.
+* 10-30-90 GJF Added macros defining variable args interface.
+* 10-31-90 GJF Added definition of _JBLEN (from setjmp.h).
+* 11-13-90 GJF Revised #ifdef-s, now use symbolic constants
+* representing target OS and target processor, with
+* #error directives for unsupported targets. Note the
+* general grouping of only OS-dependent definitions
+* followed by OS and processor dependent definitions.
+* 02-25-91 SRW Move _JBLEN definition back to setjmp.h [_WIN32_]
+* 04-09-91 PNT Added _MAC_ definitions
+* 05-09-91 GJF Restored _JBLEN definitions. Also fixed the macros
+* defining the target processor so both Stevewo's stuff
+* and mine would work.
+* 05-13-91 GJF Changed _CALLTYPE1 and _CALLTYPE4 to _cdecl for
+* Cruiser (_CRUISER_).
+* 08-28-91 JCR ANSI keywords
+* 11-01-91 GDP _JBLEN back to setjmp.h, stdarg macros back to stdarg.h
+* 03-30-92 DJM POSIX support.
+* 08-07-92 GJF Revised various macros.
+* 09-08-92 GJF Restored definition of _MIPS_ (temporarily).
+* 11-09-92 GJF Revised preprocessing conditionals for MIPS.
+* 01-09-93 SRW Remove usage of MIPS and ALPHA to conform to ANSI
+* Use _MIPS_ and _ALPHA_ instead.
+* 02-01-93 GJF Removed support for C6-386.
+*
+****/
+
+#ifndef _INC_CRUNTIME
+
+/*
+ * Some CRT sources have code conditioned on _MIPS_. Continue to define
+ * _MIPS_ when MIPS is defined until these sources are fixed.
+ */
+#if defined(MIPS) && !defined(_MIPS_)
+#define _MIPS_
+#endif
+
+#if defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+#define UNALIGNED __unaligned
+#else
+#define UNALIGNED
+#endif
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl /* User-visible CRT function */
+#define _CRTAPI2 __cdecl /* User-visible CRT function */
+#define _CRTAPI3 __cdecl /* Internal CRT function */
+#define _CRTVAR1 /* C global variable */
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+#define _CRTAPI3
+#define _CRTVAR1
+
+#endif
+
+/*
+ * Old function calling type and variable type qualifier macros
+ */
+#define _CALLTYPE1 _CRTAPI1
+#define _CALLTYPE2 _CRTAPI2
+#define _CALLTYPE4 _CRTAPI3
+#define _VARTYPE1 _CRTVAR1
+
+
+#ifdef _CRUISER_
+
+/*
+ * DEFINITIONS FOR CRUISER (AKA OS/2 2.0).
+ */
+
+#define _CALLTYPE3 __syscall /* OS API functions */
+
+
+/*
+ * Macros for register variable declarations
+ */
+
+#define REG1 register
+#define REG2 register
+#define REG3 register
+#define REG4
+#define REG5
+#define REG6
+#define REG7
+#define REG8
+#define REG9
+
+/*
+ * Macros for varargs support
+ */
+
+#define _VA_LIST_T char *
+
+#else /* ndef _CRUISER_ */
+
+#ifdef _WIN32_
+
+/*
+ * DEFINITIONS FOR WIN32
+ */
+
+#ifdef _ALPHA_
+#define _VA_LIST_T \
+ struct { \
+ char *a0; /* pointer to first homed integer argument */ \
+ int offset; /* byte offset of next parameter */ \
+ }
+#else
+#define _VA_LIST_T char *
+#endif
+
+#if defined(_M_IX86)
+/*
+ * 386/486
+ */
+#define REG1 register
+#define REG2 register
+#define REG3 register
+#define REG4
+#define REG5
+#define REG6
+#define REG7
+#define REG8
+#define REG9
+
+#elif defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+/*
+ * MIPS or ALPHA
+ */
+#define REG1 register
+#define REG2 register
+#define REG3 register
+#define REG4 register
+#define REG5 register
+#define REG6 register
+#define REG7 register
+#define REG8 register
+#define REG9 register
+
+#else
+
+#error ERROR - SUPPORT FOR WIN32 NT-X86, NT-MIPS, NT-ALPHA, AND NT-PPC ONLY
+
+#endif
+
+#else /* ndef _WIN32_ */
+
+#ifdef _POSIX_
+/*
+ * DEFINITIONS FOR POSIX
+ */
+
+
+#ifdef _ALPHA_
+
+#define _VA_LIST_T \
+ struct { \
+ char *a0; /* pointer to first homed integer argument */ \
+ int offset; /* byte offset of next parameter */ \
+ }
+#else
+
+#define _VA_LIST_T char *
+
+#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
+
+#define _VA_START(ap,v) ap = (va_list)&v + _INTSIZEOF(v)
+#define _VA_ARG(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
+#define _VA_END(ap) ap = (va_list)0
+
+#endif
+
+#if defined(_M_IX86)
+/*
+ * 386/486
+ */
+#define REG1 register
+#define REG2 register
+#define REG3 register
+#define REG4
+#define REG5
+#define REG6
+#define REG7
+#define REG8
+#define REG9
+
+#elif defined(_M_MRX000) || defined(_M_ALPHA) || defined(_M_PPC)
+/*
+ * MIPS/Alpha/PPC
+ */
+#define REG1 register
+#define REG2 register
+#define REG3 register
+#define REG4 register
+#define REG5 register
+#define REG6 register
+#define REG7 register
+#define REG8 register
+#define REG9 register
+
+#else
+
+#error ERROR - SUPPORT FOR POSIX NT-X86, NT-MIPS, NT-ALPHA, AND NT_PPC ONLY
+
+#endif
+
+#else /* ndef _POSIX_ */
+
+#ifdef _MAC_
+
+/*
+ * DEFINITIONS FOR MAC.
+ */
+
+/*
+ * Macros for register variable declarations
+ */
+
+#define REG1
+#define REG2
+#define REG3
+#define REG4
+#define REG5
+#define REG6
+#define REG7
+#define REG8
+#define REG9
+
+/*
+ * Macros for varargs support
+ */
+
+#define _VA_LIST_T char *
+
+#else /* ndef _MAC_ */
+
+#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED!
+
+#endif /* _MAC_ */
+
+#endif /* _WIN32_ */
+
+#endif /* _POSIX_ */
+
+#endif /* _CRUISER_ */
+
+#define _INC_CRUNTIME
+#endif /* _INC_CRUNTIME */
diff --git a/private/ole32/common/cruntime/cruntime.inc b/private/ole32/common/cruntime/cruntime.inc
new file mode 100644
index 000000000..bbd96710b
--- /dev/null
+++ b/private/ole32/common/cruntime/cruntime.inc
@@ -0,0 +1,826 @@
+;***
+;cruntime.inc - multi-model assembly macros for interfacing to HLLs
+;
+; Copyright (c) 1988-1992, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; This file defines the current memory model being used.
+;
+;Revision History:
+; 08-04-88 SJM Initial version to handle all four memory models
+; in 16-bit mode and small model in 32-bit mode
+; 08-08-88 JCR Added CPDIST, ?WIN, PCS, ISHIFT/LSHIFT, OS2,
+; DNPTR/DFPTR, DFLOAT/DDOUBLE/DLDOUBLE
+; 08-16-88 PHG Added FPES, LFPES, CBI, ZXAL, ZXBL, ZXCL, ZXDL
+; 08-17-88 JCR Added CAXDX, modified FPSIZE
+; 08-20-88 PHG Added diagnostic messages, removed 386 16-bit support
+; and 386 large code/data support, added mucho comments,
+; PSS now defined as es: only if SS_NEQ_GROUP defined
+; 08-24-88 JCR Added RBXSAVE and RBXONLY for use in 'proc uses'
+; 08-25-88 JCR Added savereg macro, removed rbxsave/rbxonly...
+; 08-26-88 GJF Added codeseg (text) macro
+; 09-15-88 JCR Corrected savelist/reglist macro to go with new MASM
+; 09-21-88 WAJ Added JS*, static*, global*, and label*, and lab macros
+; 09-22-88 JCR Change 'plm' to 'pascal' in label macro
+; 09-26-88 WAJ Added PUSH16 which will do a 16 bit push in a USE32 seg.
+; 09-28-88 WAJ Added CPWORD and DPWORD
+; 09-29-88 WAJ Added JMPFAR16 macro
+; 10-12-88 JCR Made PCS evaluate to 'cs:' for 16/32 stub testbed
+; 04-24-89 JCR Added 'assume seg:flat' for 386 to avoid masm/link bug
+; 05-25-89 GJF Added APIEXT, a macro that expands to the proper extrn
+; declaration for an API function
+; 06-13-89 JCR Added 'flat:' to DCPTR and DDPTR
+; 09-15-89 JCR Added DCPTR? and DDPTR?, always use "FLAT" not "flat"
+; 10-27-92 SKS Miscellaneous minor changes for MASM 6.10 compatibility
+;
+;*******************************************************************************
+
+;==============================================================================
+;
+;Use the following defines to control processor/segment model
+;
+; -DI86 8086/8088 processor
+; -DI286 80286 processor
+; -DI386 80386 processor with 32-bit code/data segment
+;
+; -Dmem_S Small memory model (near code, near data)
+; -Dmem_M Medium memory model (far code, near data)
+; -Dmem_C Compact memory model (near code, fat data)
+; -Dmem_L Large memory model (far code, far data)
+;
+; -DSS_NEQ_DGROUP SS and DS point to different segments
+;
+; default is -DI86 -Dmem_S
+;
+;==============================================================================
+;
+;The following variables are defined by this file:
+; cpu 86, 286, or 386
+; sizeC code distance; 1 = far code, 0 = near code
+; sizeD data distance; 1 = far data, 0 = near data
+; mmodel english name of the memory model, i.e. "Medium"
+; ISIZE, LSIZE, NSIZE size of ints, longs, shorts
+; FLTSIZE, DBLSIZE, LDBLSIZE size of float, double, long double
+; NPSIZE, FPSIZE size of near/far pointers
+; CPSIZE, DPSIZE size of code/data pointers
+; ISHIFT, LSHIFT bits to shift to convert byte to int/long
+;
+;The following macros allow easy writing of combined 16/32 bit code:
+;
+; 16/32 bit registers:
+; rax, rbx, rcx, rdx, expand to native registers (rax = eax or ax)
+; rsi, rdi, rsp, rbp
+; 16/32 bit register instructions:
+; JRCXZ jump when rcx is zero
+; CBI convert byte to int (al to rax)
+; CAXDX convert rax to rax:rdx
+; ZXAL, ZXBL, ZXCL, ZXDL zero extend al,bl,cl,dl to rax,rbx,rcx,rdx
+; Pointer instructions:
+; LPDS, LPES load data pointer with ES or DS
+; PDS, PES segment overrides when pointer loaded as above
+; PCS, PSS segment override to get at code/stack segment
+; LFPDS, LFPES load far pointer with ES or DS
+; FPDS, FPES segment overrides when pointer loaded as above
+; CPTR data type of code pointer
+; CPDIST distance of code (near/far)
+; DNPTR, DFPTR define near/far pointer
+; DCPTR, DDPTR define code/data pointer
+; DCPTR?, DDPTR? define uninitialized code/data pointer
+; CPWORD, DPWORD data type of code or data pointer
+; Numeric type instructions:
+; IWORD, LWORD, SWORD data type of int, long, short
+; DINT, DLONG, DSHORT define int, long, short
+; DFLOAT, DDOUBLE, DLDOUBLE define float, double, long double
+; Offsets:
+; codeoffset, dataoffset offsets from code and data segments
+; API calls:
+; APIDIST distance of API calls (near/far)
+; APIEXT ApiName extrn declaration for an API function
+;
+;The following utility macros are provided:
+; codeseg define/declare code segment
+; error <msg> stop assembly with message
+; display <msg> display a message, unless QUIET defined
+; savelist [<reg> ...] init list of regs to be save by 'proc uses'
+; _if cond <instruction> assemble instruction only if cond is TRUE
+; _ife cond <instruction> assemble instruction only if cond is FALSE
+; _ifd symbol <instruction> assemble instruction only if symbol defined
+; _ifnd symbol <instruction> assemble instruction only if symbol not defined
+;
+; lab LabelName assembles to "LabelName:" If DEBUG is defined
+; LabelName is made public
+;
+; JS* (ex. JSE,JSZ,JSB ...) assemble to "je short","jz short","jb short"
+;
+; Cmacro look alikes
+; static* Name, InitialValue, Repeat defines a static variable of type *
+; global* Name, InitialValue, Repeat defines a global variable of type *
+; label* Name, {PUBLIC,PASCAL,C} defines a label of type *
+;
+; PUSH16 SegmentReg pushes 16 bits in a use32 segment
+; JMPFAR16 label will do a far 16:16 jmp from a use32 segment
+;
+;==============================================================================
+
+; error <msg> - Output message and generate error
+
+error MACRO msg
+if2 ;; only on pass 2 can we generate errors
+ %out **********************************************************
+ %out *** E r r o r -- msg
+ %out **********************************************************
+ .err
+endif
+ ENDM
+
+; display msg - Output message unless QUIET defined
+
+display MACRO msg
+ifndef QUIET ;; only when quiet flag not set
+if1 ;; and on pass 1, then display message
+ %out msg
+endif
+endif
+ ENDM
+
+; One line conditionals:
+; here we create the capability of writing code lines like
+;
+; _if sizeD <push ds> as opposed to if sizeD
+; push ds
+; endif
+
+_if MACRO cond,text
+ if cond
+ text
+ endif
+ ENDM
+
+_ife MACRO cond,text
+ ife cond
+ text
+ endif
+ ENDM
+
+_ifd MACRO cond,text
+ ifdef cond
+ text
+ endif
+ ENDM
+
+_ifnd MACRO cond,text
+ ifndef cond
+ text
+ endif
+ ENDM
+
+; set windows flag to 0
+
+ ?WIN equ 0 ; disable windows-specific code
+
+; check for MTHREAD, requires 286 or greater processor
+
+ifdef MTHREAD
+ifndef I386
+ifndef I286
+; MTHREAD implies 286 processor
+display <Multi-thread specified - assuming 80286 processor>
+I286 equ <>
+endif
+endif
+endif
+
+; Process memory-model arguments
+
+ifdef mem_M
+ ; Medium model
+ sizeC equ 1
+ sizeD equ 0
+ mmodel equ <Medium>
+elseifdef mem_C
+ ; Compact model
+ sizeC equ 0
+ sizeD equ 1
+ mmodel equ <Compact>
+elseifdef mem_L
+ ; Large model
+ sizeC equ 1
+ sizeD equ 1
+ mmodel equ <Large>
+else
+ ; Small model - default
+ sizeC equ 0
+ sizeD equ 0
+ mmodel equ <Small>
+endif
+
+; Process processor arguments
+
+ifdef I286
+ display <Processor: 80286>
+ cpu equ 286
+ .286
+elseifdef I386
+ display <Processor: 80386>
+ cpu equ 386
+ OS2 equ <> ; Define "OS2" since 386 can only run on that OS
+ .386
+else
+ display <Processor: 8086/8088>
+ cpu equ 86
+ .8086
+endif
+
+; 386 32-bit checking. Currently we are only expecting small model
+; 32 bit segments, so we make a few checks to be sure nothing is
+; incorrectly being defined.
+
+ifdef I386
+ if sizeC or sizeD
+ error <Must use Small memory model for 386 version.>
+ endif
+
+ ifdef _LOAD_DGROUP
+ error <No loading DGROUP in 386 version.>
+ endif
+
+ ifdef SS_NEQ_DGROUP
+ error <SS always equals DGROUP in 386 version.>
+ endif
+endif
+
+; Set memory model
+
+% display <Memory model: mmodel>
+% .model mmodel, C
+
+;
+; *** Temporary Workaround ***
+; Currently, MASM will not recognize the 'FLAT' keyword unless it previously
+; appears in an 'assume' statement. Presumably, when the '.model FLAT' feature
+; is implemented, this will go away. [Use 'gs:' since we never use that
+; segment register.
+;
+
+ifdef I386
+ ; ensure that MASM recognizes 'FLAT'
+ assume gs:FLAT
+endif
+
+
+; Define registers:
+; Instead of using the "word" registers directly, we will use a set of
+; text equates. This will allow you to use the native word size instead of
+; hard coded to 16 bit words. We also have some instruction equates for
+; instruction with the register type hard coded in.
+
+ifdef I386
+
+ rax equ <eax>
+ rbx equ <ebx>
+ rcx equ <ecx>
+ rdx equ <edx>
+ rdi equ <edi>
+ rsi equ <esi>
+ rbp equ <ebp>
+ rsp equ <esp>
+
+ JRCXZ equ <jecxz>
+ CBI equ <movsx eax, al> ; convert byte to int (al to rax)
+ CAXDX equ <cdq> ; convert rax to rdx:rax
+ ZXAL equ <movzx eax, al> ; zero extend al
+ ZXBL equ <movzx ebx, bl> ; zero extend bl
+ ZXCL equ <movzx ecx, cl> ; zero extend cl
+ ZXDL equ <movzx edx, dl> ; zero extend dl
+
+else
+
+ rax equ <ax>
+ rbx equ <bx>
+ rcx equ <cx>
+ rdx equ <dx>
+ rdi equ <di>
+ rsi equ <si>
+ rbp equ <bp>
+ rsp equ <sp>
+
+ JRCXZ equ <jcxz>
+ CBI equ <cbw> ; convert byte to int (al to rax)
+ CAXDX equ <cwd> ; convert rax to rdx:rax
+ ZXAL equ <xor ah, ah> ; zero extend al
+ ZXBL equ <xor bh, bh> ; zero extend bl
+ ZXCL equ <xor ch, ch> ; zero extend cl
+ ZXDL equ <xor dh, dh> ; zero extend dl
+
+endif
+
+; The following equates deal with the differences in near versus
+; far data pointers, and segment overrides.
+;
+; Use LPES and PES when loading a default size pointer -- it loads
+; a 16-bit pointer register in 286 Small/Medium model,
+; a 16-bit pointer register and 16-bit segment register in 8086/286
+; Compact/Large model, and a 32-bit pointer register in 386 mode.
+;
+; Use LFPES and FPES when loading an always far pointer -- it loads a
+; 16-bit pointer register and 16-bit segment register in 8086/286,
+; all models; a 32-bit pointer register in 386 mode.
+
+if sizeD
+ LPES equ <les>
+ LPDS equ <lds>
+ PDS equ <ds:>
+ PES equ <es:>
+else
+ LPES equ <mov>
+ LPDS equ <mov>
+ PDS equ <>
+ PES equ <>
+endif
+
+ifdef I386
+ LFPES equ <mov>
+ LFPDS equ <mov>
+ FPES equ <>
+ FPDS equ <>
+else
+ LFPES equ <les>
+ LFPDS equ <lds>
+ FPES equ <es:>
+ FPDS equ <ds:>
+endif
+
+if sizeC or @WordSize eq 2
+ PCS equ <cs:> ; large code model or non-386
+else
+ IF 1 ;*** TEMP 16/32 TESTBED ***
+ PCS equ <cs:>
+ ELSE
+ PCS equ <> ; 386 small code model
+ ENDIF ;*** END TEMP CODE
+endif
+
+ifdef SS_NEQ_DGROUP
+ PSS equ <ss:> ; SS != DS
+else
+ PSS equ <> ; SS == DS
+endif
+
+; Define offset macros:
+; The 32-bit segments will not have 'groups'
+
+ifdef I386
+ codeoffset equ <offset FLAT:>
+ dataoffset equ <offset FLAT:>
+else
+ codeoffset equ <offset @code:>
+ dataoffset equ <offset DGROUP:>
+endif
+
+; The next set of equates deals with the size of SHORTS, INTS, LONGS, and
+; pointers in the 16 and 32 bit versions.
+
+ifdef I386 ;--- 32 bit segment ---
+
+ ; parameters and locals
+ IWORD equ <dword>
+ LWORD equ <dword>
+if @Version LT 600
+ SWORD equ <word>
+endif
+
+ ; static storage
+ DINT equ <dd>
+ DLONG equ <dd>
+ DSHORT equ <dw>
+
+ ; sizes for fixing SP, stepping through tables, etc.
+ ISIZE equ 4
+ LSIZE equ 4
+ SSIZE equ 2
+ NPSIZE equ 4
+ FPSIZE equ 4
+
+ ; bit shift count to convert byte cnt/ptr to int/long cnt/ptr
+ ISHIFT equ 2 ; byte-to-int shift count
+ LSHIFT equ 2 ; byte-to-long shift count
+
+ ; sizes dependent upon memory model. dq -vs- df is not yet clear
+ DNPTR equ <dd> ; near pointer
+ DFPTR equ <dd> ; far pointer
+
+ DCPTR equ <dd offset FLAT:>; 32 bit offset only
+ DCPTR? equ <dd> ; No seg override for uninitialized values
+ CPSIZE equ 4
+ CPDIST equ <near> ; code pointers are near
+ CPTR equ <near ptr>
+
+ DDPTR equ <dd offset FLAT:>
+ DDPTR? equ <dd>
+ DPSIZE equ 4
+
+ CPWORD equ <dword> ; code pointers are dwords
+ DPWORD equ <dword> ; data pointers are dwords
+
+ APIDIST equ <near> ; all API calls are NEAR in the 32 bit model
+
+; macro to declare API functions
+EXTAPI macro apiname
+ extrn pascal apiname:near
+endm
+
+else ;--- 16-bit segment ---
+
+ ; parameters and locals
+ IWORD equ <word>
+ LWORD equ <dword>
+if @Version LT 600
+ SWORD equ <word>
+endif
+
+ ; static storage
+ DINT equ <dw>
+ DLONG equ <dd>
+ DSHORT equ <dw>
+
+ ; sizes for fixing SP, stepping through tables, etc
+ ISIZE equ 2
+ LSIZE equ 4
+ SSIZE equ 2
+ NPSIZE equ 2
+ FPSIZE equ 4
+
+ ; bit shift count to convert byte cnt/ptr to int/long cnt/ptr
+ ISHIFT equ 1 ; byte-to-int shift count
+ LSHIFT equ 2 ; byte-to-long shift count
+
+ ; sizes dependent upon memory model
+ DNPTR equ <dw> ; near pointer
+ DFPTR equ <dd> ; far pointer
+
+ if sizeC
+ DCPTR equ <dd> ; 16 bit segment and 16 bit offset
+ DCPTR? equ <dd>
+ CPSIZE equ 4
+ CPDIST equ <far> ; code pointers are far
+ CPTR equ <far ptr>
+ CPWORD equ <dword> ; code pointers are dwords
+ else
+ DCPTR equ <dw> ; 16 bit offset only
+ DCPTR? equ <dw>
+ CPSIZE equ 2
+ CPDIST equ <near> ; code pointers are near
+ CPTR equ <near ptr>
+ CPWORD equ <word> ; code pointers are words
+ endif
+
+ if sizeD
+ DDPTR equ <dd>
+ DDPTR? equ <dd>
+ DPSIZE equ 4
+ DPWORD equ <dword> ; data pointers are dwords
+ else
+ DDPTR equ <dw>
+ DDPTR? equ <dw>
+ DPSIZE equ 2
+ DPWORD equ <word> ; data pointers are words
+ endif
+
+ APIDIST equ <far> ; API calls are FAR in 16 bit model
+
+; macro to declare API functions
+EXTAPI macro apiname
+ extrn pascal apiname:far
+endm
+
+endif ; --- 16/32 segment ---
+
+; Float/double definitions
+; (currently the same for 16- and 32-bit segments)
+
+FLTSIZE equ 4 ; float
+DBLSIZE equ 8 ; double
+LDBLSIZE equ 10 ; long double
+
+DFLOAT equ <dd>
+DDOUBLE equ <dq>
+DLDOUBLE equ <dt>
+
+;
+; savelist - Generate a list of regs to be saved by the proc 'uses' option.
+;
+; Input:
+; reg1, reg2, reg3, reg4 = registers to be saved across function
+; Output:
+; reglist = text string of registers that can be passed to the 'uses'
+; option on the 'proc' command.
+;
+
+savelist MACRO reg1, reg2, reg3, reg4
+ local ws, listsize
+ ws catstr < > ; whitespace char
+
+ IFNDEF I386
+ rbx equ <> ; 8086/286 don't save rbx
+ ENDIF
+
+ IFNB <reg4>
+ reglist catstr reg1, ws, reg2, ws, reg3, ws, reg4
+ ELSEIFNB <reg3>
+ reglist catstr reg1, ws, reg2, ws, reg3, ws
+ ELSEIFNB <reg2>
+ reglist catstr reg1, ws, reg2, ws, ws
+ ELSEIFNB <reg1>
+ reglist catstr reg1, ws, ws, ws
+ ELSE
+ reglist catstr <>
+ ENDIF
+
+ listsize sizestr reglist ; size of register list
+
+ IF listsize LE 3 ; if list is only the 3 ws chars...
+ reglist catstr <>
+ ENDIF
+
+ IFNDEF I386
+ rbx equ <bx> ; restore rbx
+ ENDIF
+
+ ENDM ; savelist
+
+;
+; codeseg - Define/declare the standard code segment. Maps to the proper
+; form of the .code directive.
+;
+; Input:
+;
+; Output:
+; .code _TEXT ; for large code models
+; .code ; for small code models
+; assume cs:FLAT ; for 386
+; assume ds:FLAT ; for 386
+; assume es:FLAT ; for 386
+; assume ss:FLAT ; for 386
+;
+
+codeseg MACRO
+
+if sizeC
+ .code _TEXT
+else
+ .code
+endif
+
+ifdef I386
+if @Version LT 600
+ assume cs:FLAT
+endif ;@Version LT 600
+ assume ds:FLAT
+ assume es:FLAT
+ assume ss:FLAT
+endif
+
+ ENDM
+
+;***************************************************************
+;*
+;* Debug lab macro
+;*
+;***************************************************************
+
+lab macro name
+ifdef DEBUG
+ public pascal name ;; define label public for Symdeb
+endif
+name:
+ endm
+
+
+;***************************************************************
+;*
+;* Conditional jump short macros
+;*
+;***************************************************************
+
+
+ irp x,<Z,NZ,E,NE,S,NS,C,NC,P,NP,PE,PO,A,AE,B,BE,NB,G,GE,L,LE>
+JS&x equ <j&x short>
+ endm
+
+
+;***************************************************************
+;*
+;* Global data definition macros
+;*
+;* Usage:
+;* globalI Name, InitialValue, Repeat
+;*
+;***************************************************************
+
+
+MakeGlobal macro suffix, DataType ;; makes all of the global* macros
+
+global&suffix macro name, data, rep
+public name
+ifb <rep>
+ _repeat = 1
+else
+ _repeat = (rep)
+endif
+
+name &DataType _repeat dup( data )
+ endm
+
+ endm
+
+
+ MakeGlobal T, dt ; globalT
+ MakeGlobal Q, dq ; globalQ
+ MakeGlobal D, dd ; globalD
+ MakeGlobal W, dw ; globalW
+ MakeGlobal B, db ; globalB
+
+% MakeGlobal I, <DINT> ; globalI
+
+% MakeGlobal DP, <DDPTR> ; globalDP
+% MakeGlobal CP, <DCPTR> ; globalCP
+% MakeGlobal FP, <DFPTR> ; globalFP
+% MakeGlobal NP, <DNPTR> ; globalNP
+
+
+
+;***************************************************************
+;*
+;* Static data definition macros
+;*
+;* Usage:
+;* staticI Name, InitialValue, Repeat
+;*
+;***************************************************************
+
+
+MakeStatic macro suffix, DataType ;; makes all of the static* macros
+
+static&suffix macro name, data, rep
+
+ifdef DEBUG
+ public pascal name ;; make statics public if DEBUG
+endif
+
+ifb <rep>
+ _repeat = 1
+else
+ _repeat = (rep)
+endif
+
+name &DataType _repeat dup( data )
+ endm
+
+ endm
+
+
+ MakeStatic T, dt ; staticT
+ MakeStatic Q, dq ; staticQ
+ MakeStatic D, dd ; staticD
+ MakeStatic W, dw ; staticW
+ MakeStatic B, db ; staticB
+
+% MakeStatic I, <DINT> ; staticI
+
+% MakeStatic DP, <DDPTR> ; staticDP
+% MakeStatic CP, <DCPTR> ; staticCP
+% MakeStatic FP, <DFPTR> ; staticFP
+% MakeStatic NP, <DNPTR> ; staticNP
+
+;***************************************************************
+;*
+;* Label definition macros
+;*
+;***************************************************************
+;*
+;* Label definition macros
+;*
+;* Usage:
+;* labelI Name, {PUBLIC, PASCAL, C}
+;*
+;***************************************************************
+
+__MakePublic macro name, option ;; decides if a label should be
+ifidni <option>, <PUBLIC> ;; made public
+ public name
+elseifidni <option>, <PASCAL>
+ public pascal name
+elseifidni <option>, <C>
+ public C name
+elseifb <option>
+ ifdef DEBUG
+ public pascal name ;; make public if DEBUG
+ endif
+endif
+ endm
+
+
+if @Version GE 600
+
+MakeLabel macro suffix, LabelType ;; makes all of the label* macros
+
+%@CatStr(<label>,<suffix>) macro name, option
+ __MakePublic <name>,<option>
+name label &LabelType
+ endm
+
+ endm
+
+else ;!(@Version GE 600)
+
+MakeLabel macro suffix, LabelType ;; makes all of the label* macros
+
+label&suffix macro name, option
+ __MakePublic <name>,<option>
+name label &LabelType
+ endm
+
+ endm
+
+endif ;!(@Version GE 600)
+
+
+ MakeLabel T, tbyte ; make labelT
+ MakeLabel Q, qword ; make labelQ
+ MakeLabel D, dword ; make labelD
+ MakeLabel W, word ; make labelW
+ MakeLabel B, byte ; make labelB
+
+ MakeLabel P, proc ; make labelP
+ MakeLabel FP, far ; make labelFP
+ MakeLabel NP, near ; make labelNP
+
+% MakeLabel I, IWORD ; make labelI
+
+
+labelDP macro name, option ;; labelDP
+ __MakePublic <name>,<option>
+ifdef I386
+ if sizeD
+ name label fword
+ else
+ name label dword
+ endif
+else ;not I386
+ if sizeD
+ name label dword
+ else
+ name label word
+ endif
+endif ;not I386
+ endm
+
+labelCP macro name, option ;; labelCP
+ __MakePublic <name>,<option>
+ifdef I386
+ if sizeC
+ name label fword
+ else
+ name label dword
+ endif
+else ;not I386
+ if sizeC
+ name label dword
+ else
+ name label word
+ endif
+endif ;not I386
+ endm
+
+
+;*
+;* PUSH16 SegReg - pushes 16 bits in a use32 segment
+;*
+
+PUSH16 macro SegReg
+
+ifdef I386
+ nop
+ db 66h ; operand size over-ride
+endif ; I386
+
+ push SegReg
+ endm
+
+
+;*
+;* JMPFAR16 label - jmps far from a use32 to a use16 segment
+;*
+
+JMPFAR16 macro label
+
+ifndef I386
+ error <JMPFAR16 can only be used in a use32 code segment>
+endif ;I386
+
+ nop
+ db 66h ;; operand size over-ride
+ db 0eah ;; jmp far immediate op code
+ dw offset label
+ dw seg label
+ endm
diff --git a/private/ole32/common/cruntime/ctype.c b/private/ole32/common/cruntime/ctype.c
new file mode 100644
index 000000000..d259bd1fd
--- /dev/null
+++ b/private/ole32/common/cruntime/ctype.c
@@ -0,0 +1,163 @@
+/***
+*ctype.c - _ctype definition file
+*
+* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* _ctype definition file of character classification data. This file
+* initializes the array used by the character classification macros
+* in ctype.h.
+*
+*Revision History:
+* 06-08-89 PHG Module created, based on asm version
+* 08-28-89 JCR Corrected _ctype declaration to match ctype.h
+* 04-06-90 GJF Added #include <cruntime.h>. Also, fixed the copyright.
+* 10-08-91 ETC _ctype table is unsigned short under _INTL.
+* 11-11-91 ETC Declare _pctype and _pwctype under _INTL.
+* 12-16-91 ETC Make ctype table width independent of _INTL, use
+* _NEWCTYPETABLE for short table, else char.
+* 04-06-92 KRS Remove _INTL switches.
+* 01-19-03 CFW Move to _NEWCTYPETABLE, remove switch.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <ctype.h>
+
+unsigned short * _pctype = _ctype+1; /* pointer to table for char's */
+unsigned short * _pwctype = _ctype+1; /* pointer to table for wchar_t's */
+
+unsigned short _VARTYPE1 _ctype[257] = {
+ 0, /* -1 EOF */
+ _CONTROL, /* 00 (NUL) */
+ _CONTROL, /* 01 (SOH) */
+ _CONTROL, /* 02 (STX) */
+ _CONTROL, /* 03 (ETX) */
+ _CONTROL, /* 04 (EOT) */
+ _CONTROL, /* 05 (ENQ) */
+ _CONTROL, /* 06 (ACK) */
+ _CONTROL, /* 07 (BEL) */
+ _CONTROL, /* 08 (BS) */
+ _SPACE+_CONTROL, /* 09 (HT) */
+ _SPACE+_CONTROL, /* 0A (LF) */
+ _SPACE+_CONTROL, /* 0B (VT) */
+ _SPACE+_CONTROL, /* 0C (FF) */
+ _SPACE+_CONTROL, /* 0D (CR) */
+ _CONTROL, /* 0E (SI) */
+ _CONTROL, /* 0F (SO) */
+ _CONTROL, /* 10 (DLE) */
+ _CONTROL, /* 11 (DC1) */
+ _CONTROL, /* 12 (DC2) */
+ _CONTROL, /* 13 (DC3) */
+ _CONTROL, /* 14 (DC4) */
+ _CONTROL, /* 15 (NAK) */
+ _CONTROL, /* 16 (SYN) */
+ _CONTROL, /* 17 (ETB) */
+ _CONTROL, /* 18 (CAN) */
+ _CONTROL, /* 19 (EM) */
+ _CONTROL, /* 1A (SUB) */
+ _CONTROL, /* 1B (ESC) */
+ _CONTROL, /* 1C (FS) */
+ _CONTROL, /* 1D (GS) */
+ _CONTROL, /* 1E (RS) */
+ _CONTROL, /* 1F (US) */
+ _SPACE+_BLANK, /* 20 SPACE */
+ _PUNCT, /* 21 ! */
+ _PUNCT, /* 22 " */
+ _PUNCT, /* 23 # */
+ _PUNCT, /* 24 $ */
+ _PUNCT, /* 25 % */
+ _PUNCT, /* 26 & */
+ _PUNCT, /* 27 ' */
+ _PUNCT, /* 28 ( */
+ _PUNCT, /* 29 ) */
+ _PUNCT, /* 2A * */
+ _PUNCT, /* 2B + */
+ _PUNCT, /* 2C , */
+ _PUNCT, /* 2D - */
+ _PUNCT, /* 2E . */
+ _PUNCT, /* 2F / */
+ _DIGIT+_HEX, /* 30 0 */
+ _DIGIT+_HEX, /* 31 1 */
+ _DIGIT+_HEX, /* 32 2 */
+ _DIGIT+_HEX, /* 33 3 */
+ _DIGIT+_HEX, /* 34 4 */
+ _DIGIT+_HEX, /* 35 5 */
+ _DIGIT+_HEX, /* 36 6 */
+ _DIGIT+_HEX, /* 37 7 */
+ _DIGIT+_HEX, /* 38 8 */
+ _DIGIT+_HEX, /* 39 9 */
+ _PUNCT, /* 3A : */
+ _PUNCT, /* 3B ; */
+ _PUNCT, /* 3C < */
+ _PUNCT, /* 3D = */
+ _PUNCT, /* 3E > */
+ _PUNCT, /* 3F ? */
+ _PUNCT, /* 40 @ */
+ _UPPER+_HEX, /* 41 A */
+ _UPPER+_HEX, /* 42 B */
+ _UPPER+_HEX, /* 43 C */
+ _UPPER+_HEX, /* 44 D */
+ _UPPER+_HEX, /* 45 E */
+ _UPPER+_HEX, /* 46 F */
+ _UPPER, /* 47 G */
+ _UPPER, /* 48 H */
+ _UPPER, /* 49 I */
+ _UPPER, /* 4A J */
+ _UPPER, /* 4B K */
+ _UPPER, /* 4C L */
+ _UPPER, /* 4D M */
+ _UPPER, /* 4E N */
+ _UPPER, /* 4F O */
+ _UPPER, /* 50 P */
+ _UPPER, /* 51 Q */
+ _UPPER, /* 52 R */
+ _UPPER, /* 53 S */
+ _UPPER, /* 54 T */
+ _UPPER, /* 55 U */
+ _UPPER, /* 56 V */
+ _UPPER, /* 57 W */
+ _UPPER, /* 58 X */
+ _UPPER, /* 59 Y */
+ _UPPER, /* 5A Z */
+ _PUNCT, /* 5B [ */
+ _PUNCT, /* 5C \ */
+ _PUNCT, /* 5D ] */
+ _PUNCT, /* 5E ^ */
+ _PUNCT, /* 5F _ */
+ _PUNCT, /* 60 ` */
+ _LOWER+_HEX, /* 61 a */
+ _LOWER+_HEX, /* 62 b */
+ _LOWER+_HEX, /* 63 c */
+ _LOWER+_HEX, /* 64 d */
+ _LOWER+_HEX, /* 65 e */
+ _LOWER+_HEX, /* 66 f */
+ _LOWER, /* 67 g */
+ _LOWER, /* 68 h */
+ _LOWER, /* 69 i */
+ _LOWER, /* 6A j */
+ _LOWER, /* 6B k */
+ _LOWER, /* 6C l */
+ _LOWER, /* 6D m */
+ _LOWER, /* 6E n */
+ _LOWER, /* 6F o */
+ _LOWER, /* 70 p */
+ _LOWER, /* 71 q */
+ _LOWER, /* 72 r */
+ _LOWER, /* 73 s */
+ _LOWER, /* 74 t */
+ _LOWER, /* 75 u */
+ _LOWER, /* 76 v */
+ _LOWER, /* 77 w */
+ _LOWER, /* 78 x */
+ _LOWER, /* 79 y */
+ _LOWER, /* 7A z */
+ _PUNCT, /* 7B { */
+ _PUNCT, /* 7C | */
+ _PUNCT, /* 7D } */
+ _PUNCT, /* 7E ~ */
+ _CONTROL, /* 7F (DEL) */
+ /* and the rest are 0... */
+};
+
+
diff --git a/private/ole32/common/cruntime/daytona/dummy.c b/private/ole32/common/cruntime/daytona/dummy.c
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/private/ole32/common/cruntime/daytona/dummy.c
@@ -0,0 +1 @@
+
diff --git a/private/ole32/common/cruntime/daytona/i386/atlssup.asm b/private/ole32/common/cruntime/daytona/i386/atlssup.asm
new file mode 100644
index 000000000..590930817
--- /dev/null
+++ b/private/ole32/common/cruntime/daytona/i386/atlssup.asm
@@ -0,0 +1,15 @@
+; SCCSID = \%Z\%\%M\%:\%I\%
+
+;hnt = -D_WIN32_ -Dsmall32 -Dflat32 -Mx $this;
+
+.xlist
+include cruntime.inc
+.list
+
+; This symbol is being defined in the C language model
+; and will have an extra underscore character prepended.
+
+ public _tls_array
+_tls_array equ 2Ch ; TEB.ThreadLocalStoragePointer
+
+end
diff --git a/private/ole32/common/cruntime/daytona/makefile b/private/ole32/common/cruntime/daytona/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ole32/common/cruntime/daytona/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/common/cruntime/daytona/sources b/private/ole32/common/cruntime/daytona/sources
new file mode 100644
index 000000000..348053737
--- /dev/null
+++ b/private/ole32/common/cruntime/daytona/sources
@@ -0,0 +1,69 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+ jeffrob 29-sep-1990, use crt32.def
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=crt
+MINORCOMP=cruntime
+
+TARGETNAME=cruntime
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+386_STDCALL=0
+
+!INCLUDE ..\crt32.def
+
+C_DEFINES=$(C_DEFINES) -D_MT=1 -D_NTSUBSET_
+
+INCLUDES=..; \
+ ..\..\..\ih
+
+SOURCES=\
+ dummy.c
+
+I386_SOURCES= \
+ ..\crt0dat.c \
+ ..\crt0init.c \
+ ..\ctype.c \
+ ..\dllcrt0.c \
+ ..\isctype.c \
+ ..\mlock.c \
+ ..\nlsdata1.c \
+ ..\nlsdata2.c \
+ ..\onexit.c \
+ ..\purevirt.c \
+ ..\qsort.c \
+ ..\strtol.c \
+ ..\tidtable.c \
+ ..\xtow.c \
+ ..\i386\chkstk.asm \
+ ..\i386\llshr.asm
+
+
+
+
+
+
+
+
+
diff --git a/private/ole32/common/cruntime/daytona/tlssup.c b/private/ole32/common/cruntime/daytona/tlssup.c
new file mode 100644
index 000000000..783ef0d3a
--- /dev/null
+++ b/private/ole32/common/cruntime/daytona/tlssup.c
@@ -0,0 +1,52 @@
+#ifdef _MSC_VER
+
+
+/* tlssup.c - Thread Local Storage runtime support module */
+
+#include <nt.h>
+
+/* Thread Local Storage index for this .EXE or .DLL */
+
+ULONG _tls_index = 0;
+
+/* Special symbols to mark start and end of Thread Local Storage area.
+ * By convention, we initialize each with a pointer to it's own address.
+ */
+
+#pragma data_seg(".tls")
+
+PVOID _tls_start = &_tls_start;
+
+#pragma data_seg(".tls$ZZZ")
+
+PVOID _tls_end = &_tls_end;
+
+/* Start and end sections for Threadl Local Storage CallBack Array.
+ * Actual array is constructed using .CRT$XLA, .CRT$XLC, .CRT$XLL,
+ * .CRT$XLU, .CRT$XLZ similar to the way global
+ * static initializers are done for C++.
+ */
+
+#pragma data_seg(".CRT$XLA")
+
+PIMAGE_TLS_CALLBACK __xl_a = 0;
+
+#pragma data_seg(".CRT$XLZ")
+
+PIMAGE_TLS_CALLBACK __xl_z = 0;
+
+
+#pragma data_seg(".rdata$T")
+
+IMAGE_TLS_DIRECTORY _tls_used =
+{
+ (ULONG) &_tls_start, // start of tls data
+ (ULONG) &_tls_end, // end of tls data
+ &_tls_index, // address of tls_index
+ &__xl_a, // pointer to call back array
+ (ULONG) 0, // size of tls zero fill
+ (ULONG) 0 // characteristics
+};
+
+
+#endif /* _MSC_VER */
diff --git a/private/ole32/common/cruntime/dirs b/private/ole32/common/cruntime/dirs
new file mode 100644
index 000000000..4439f3f8b
--- /dev/null
+++ b/private/ole32/common/cruntime/dirs
@@ -0,0 +1,37 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS= \
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ daytona
diff --git a/private/ole32/common/cruntime/dllcrt0.c b/private/ole32/common/cruntime/dllcrt0.c
new file mode 100644
index 000000000..41d1cd102
--- /dev/null
+++ b/private/ole32/common/cruntime/dllcrt0.c
@@ -0,0 +1,207 @@
+
+/***
+*dllcrt0.c - C runtime initialization routine for a DLL with linked-in C R-T
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This the startup routine for a DLL which is linked with its own
+* C run-time code. It is similar to the routine _mainCRTStartup()
+* in the file CRT0.C, except that there is no main() in a DLL.
+*
+*Revision History:
+* 05-04-92 SKS Based on CRT0.C (start-up code for EXE's)
+* 08-26-92 SKS Add _osver, _winver, _winmajor, _winminor
+* 09-16-92 SKS This module used to be enabled only in LIBCMT.LIB,
+* but it is now enabled for LIBC.LIB as well!
+* 09-29-92 SKS _CRT_INIT needs to be WINAPI, not cdecl
+* 10-16-92 SKS Call _heap_init before _mtinit (fix copied from CRT0.C)
+* 10-24-92 SKS Call to _mtdeletelocks() must be under #ifdef MTHREAD!
+* 04-16-93 SKS Call _mtterm instead of _mtdeletelocks on
+* PROCESS_DETACH to do all multi-thread cleanup
+* It will call _mtdeletelocks and free up the TLS index.
+* 04-27-93 GJF Removed support for _RT_STACK, _RT_INTDIV,
+* _RT_INVALDISP and _RT_NONCONT.
+* 05-11-93 SKS Add _DllMainCRTStartup to co-exist with _CRT_INIT
+* _mtinit now returns 0 or 1, no longer calls _amsg_exit
+* Delete obsolete variable _atopsp
+* 06-03-93 GJF Added __proc_attached flag.
+* 06-08-93 SKS Clean up failure handling in _CRT_INIT
+* 12-13-93 SKS Free up per-thread CRT data on DLL_THREAD_DETACH
+* using a call to _freeptd() in _CRT_INIT()
+*
+*******************************************************************************/
+
+#include <windows.h>
+#include <cruntime.h>
+#include <internal.h>
+#include <process.h>
+
+
+/*
+ * flag set iff _CRTDLL_INIT was called with DLL_PROCESS_ATTACH
+ */
+static int __proc_attached = 0;
+
+
+#pragma data_seg()
+
+/*
+ * User routine DllMain is called on all notifications
+ */
+
+extern BOOL WINAPI DllMain(
+ HANDLE hDllHandle,
+ DWORD dwReason,
+ LPVOID lpreserved
+ ) ;
+
+
+/***
+*BOOL WINAPI _CRT_INIT(hDllHandle, dwReason, lpreserved) - C Run-Time
+* initialization for a DLL linked with a C run-time library.
+*
+*Purpose:
+* This routine does the C run-time initialization.
+* For the multi-threaded run-time library, it also cleans up the
+* multi-threading locks on DLL termination.
+*
+*Entry:
+*
+*Exit:
+*
+*NOTES:
+* This routine should either be the entry-point for the DLL
+* or else be called by the entry-point routine for the DLL.
+*
+*******************************************************************************/
+
+BOOL WINAPI _CRT_INIT(
+ HANDLE hDllHandle,
+ DWORD dwReason,
+ LPVOID lpreserved
+ )
+{
+ /*
+ * Start-up code only gets executed when the process is initialized
+ */
+ if ( dwReason != DLL_PROCESS_ATTACH ) {
+
+ if ( dwReason == DLL_PROCESS_DETACH ) {
+ /*
+ * make sure there has been prior process attach
+ * notification!
+ */
+ if ( __proc_attached > 0 ) {
+ __proc_attached--;
+
+ if ( _C_Termination_Done == FALSE )
+ /* do exit() time clean-up */
+ _cexit();
+ /*
+ * Any basic clean-up code that goes here must be duplicated
+ * below in _DllMainCRTStartup for the case where the user's
+ * DllMain() routine fails on a Process Attach notification.
+ * This does not include calling user C++ destructors, etc.
+ */
+ /* delete MT locks, free TLS index, etc. */
+ _mtterm();
+ }
+ else
+ /* no prior process attach, just return */
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /*
+ * increment flag to indicate process attach notification has been
+ * received
+ */
+ __proc_attached++;
+
+ if(!_mtinit()) /* initialize multi-thread */
+ return FALSE; /* fail to load DLL */
+
+ _cinit(); /* do C data initialize */
+
+ return TRUE; /* initialization succeeded */
+}
+
+
+/***
+*BOOL WINAPI _DllMainCRTStartup(hDllHandle, dwReason, lpreserved) -
+* C Run-Time initialization for a DLL linked with a C run-time library.
+*
+*Purpose:
+* This routine does the C run-time initialization or termination
+* and then calls the user code notification handler "DllMain".
+* For the multi-threaded run-time library, it also cleans up the
+* multi-threading locks on DLL termination.
+*
+*Entry:
+*
+*Exit:
+*
+*NOTES:
+* This routine should be the entry point for the DLL if
+* the user is not supplying one and calling _CRT_INIT.
+*
+*******************************************************************************/
+BOOL WINAPI _DllMainCRTStartup(
+ HANDLE hDllHandle,
+ DWORD dwReason,
+ LPVOID lpreserved
+ )
+{
+ BOOL retcode = TRUE;
+
+ /*
+ * If this is a process attach notification, increment the process
+ * attached flag. If this is a process detach notification, check
+ * that there has been a prior process attach notification.
+ */
+ if ( dwReason == DLL_PROCESS_ATTACH ) {
+ __proc_attached++;
+ } else if ( dwReason == DLL_PROCESS_DETACH ) {
+ if ( __proc_attached > 0 )
+ __proc_attached--;
+ else
+ /*
+ * no prior process attach notification. just return
+ * without doing anything.
+ */
+ return FALSE;
+ }
+
+ if ( dwReason == DLL_PROCESS_ATTACH || dwReason == DLL_THREAD_ATTACH )
+ retcode = _CRT_INIT(hDllHandle, dwReason, lpreserved);
+
+ if ( retcode )
+ retcode = DllMain(hDllHandle, dwReason, lpreserved);
+
+ /*
+ * If _CRT_INIT successfully handles a Process Attach notification
+ * but the user's DllMain routine returns failure, we need to do
+ * clean-up of the C run-time similar to what _CRT_INIT does on a
+ * Process Detach Notification.
+ */
+
+ if ( retcode == FALSE && dwReason == DLL_PROCESS_ATTACH )
+ {
+ /* Failure to attach DLL - must clean up C run-time */
+ _mtterm();
+ }
+
+ if ( dwReason == DLL_PROCESS_DETACH || dwReason == DLL_THREAD_DETACH )
+ {
+ if ( _CRT_INIT(hDllHandle, dwReason, lpreserved) == FALSE )
+ retcode = FALSE ;
+ }
+
+ return retcode ;
+}
+
+
+
diff --git a/private/ole32/common/cruntime/i386/chkstk.asm b/private/ole32/common/cruntime/i386/chkstk.asm
new file mode 100644
index 000000000..e538e58e2
--- /dev/null
+++ b/private/ole32/common/cruntime/i386/chkstk.asm
@@ -0,0 +1,126 @@
+ page ,132
+ title chkstk - C stack checking routine
+;***
+;chkstk.asm - C stack checking routine
+;
+; Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; Provides support for automatic stack checking in C procedures
+; when stack checking is enabled.
+;
+;Revision History:
+; 04-21-87 SKS Added conditional assembly switch for STKHQQ = 0
+; 07-23-87 MAG [1] Added run-time CS:IP error processing for QC
+; 08-17-87 JLS [2] Remove all references to DGROUP
+; 08-25-87 JLS [3] Shift include files
+; 11-13-87 SKS OS/2 Reentrant version, add thread ID check
+; 11-18-87 SKS Make STKHQQ an array (oops!)
+; 12-14-87 SKS add .286p to allow PUSH immediate value
+; 02-19-88 SKS Change minimum bottom limit to STACKSLOP, not 0
+; 06-01-88 PHG Merge DLL and normal versions
+; 09-21-88 WAJ initial 386 version
+; 10-18-88 JCR Chkstk was trashing bx... not good on 386
+; 06-06-89 JCR 386 mthread support
+; 06-20-89 JCR 386: Removed _LOAD_DGROUP code
+; 04-06-90 GJF Fixed the copyright.
+; 06-21-90 GJF Rewritten to probe pages
+; 10-15-90 GJF Restored _end and STKHQQ.
+; 03-19-91 GJF Revised to preserve all registers except eax. Note
+; this is _rchkstk functionality so there is no longer
+; a separate _rchkstk routine.
+; 08-01-91 GJF Got rid of _end and STKHQQ, except for Cruiser
+; (probably not needed for Cruiser either) [_WIN32_].
+; 09-27-91 JCR Merged Stevewo' changes from NT tree
+;
+;*******************************************************************************
+
+.xlist
+ include cruntime.inc
+.list
+
+; size of a page of memory
+
+_PAGESIZE_ equ 1000h
+
+
+ifdef _CRUISER_
+
+ .data
+
+extrn pascal _end:dword ; stack bottom
+
+ifndef MTHREAD
+
+public pascal STKHQQ ; used by parasitic heap
+STKHQQ dd dataoffset _end+STACKSLOP ; initial value
+
+endif ;MTHREAD
+
+endif ;_CRUISER_
+
+ CODESEG
+
+page
+;***
+;_chkstk - check stack upon procedure entry
+;
+;Purpose:
+; Provide stack checking on procedure entry. Method is to simply probe
+; each page of memory required for the stack in descending order. This
+; causes the necessary pages of memory to be allocated via the guard
+; page scheme, if possible. In the event of failure, the OS raises the
+; _XCPT_UNABLE_TO_GROW_STACK exception.
+;
+; NOTE: Currently, the (EAX < _PAGESIZE_) code path falls through
+; to the "lastpage" label of the (EAX >= _PAGESIZE_) code path. This
+; is small; a minor speed optimization would be to special case
+; this up top. This would avoid the painful save/restore of
+; ecx and would shorten the code path by 4-6 instructions.
+;
+;Entry:
+; EAX = size of local frame
+;
+;Exit:
+; ESP = new stackframe, if successful
+;
+;Uses:
+; EAX
+;
+;Exceptions:
+; _XCPT_GUARD_PAGE_VIOLATION - May be raised on a page probe. NEVER TRAP
+; THIS!!!! It is used by the OS to grow the
+; stack on demand.
+; _XCPT_UNABLE_TO_GROW_STACK - The stack cannot be grown. More precisely,
+; the attempt by the OS memory manager to
+; allocate another guard page in response
+; to a _XCPT_GUARD_PAGE_VIOLATION has
+; failed.
+;
+;*******************************************************************************
+
+labelP _alloca_probe, PUBLIC
+labelP _chkstk, PUBLIC
+
+ push ecx ; save ecx
+ mov ecx,esp ; compute new stack pointer in ecx
+ add ecx,8 ; correct for return address and saved
+ ; ecx value
+probepages:
+ cmp eax,_PAGESIZE_ ; more than one page requested?
+ jb short lastpage ; no
+ sub ecx,_PAGESIZE_ ; yes, move down a page and...
+ or dword ptr [ecx],0 ; ...probe it
+ sub eax,_PAGESIZE_ ; adjust request
+ jmp probepages
+
+lastpage:
+ sub ecx,eax ; move stack down by eax and do a...
+ or dword ptr [ecx],0 ; ...probe in case a page was crossed
+ mov eax,esp ; save pointer to current tos
+ mov esp,ecx ; set the new stack pointer
+ mov ecx,dword ptr [eax] ; recover ecx
+ mov eax,dword ptr [eax + 4] ; recover return address
+ jmp eax ; return
+
+ end
diff --git a/private/ole32/common/cruntime/i386/llshr.asm b/private/ole32/common/cruntime/i386/llshr.asm
new file mode 100644
index 000000000..055bf6545
--- /dev/null
+++ b/private/ole32/common/cruntime/i386/llshr.asm
@@ -0,0 +1,91 @@
+ title llshr - long shift right
+;***
+;llshr.asm - long shift right
+;
+; Copyright (c) 1985-1994, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; define signed long shift right routine
+; __allshr
+;
+;Revision History:
+; 11-??-83 HS initial version
+; 11-30-83 DFW added medium model support
+; 03-12-84 DFW broke apart; added long model support
+; 06-01-84 RN modified to use cmacros
+; 11-28-89 GJF Fixed copyright
+; 11-19-93 SMK Modified to work on 64 bit integers
+; 01-17-94 GJF Minor changes to build with NT's masm386.
+; 07-08-94 GJF Faster, fatter version for NT.
+; 07-13-94 GJF Further improvements from JonM.
+;
+;*******************************************************************************
+
+
+.xlist
+include cruntime.inc
+include mm.inc
+.list
+
+;***
+;llshr - long shift right
+;
+;Purpose:
+; Does a signed Long Shift Right
+; Shifts a long right any number of bits.
+;
+;Entry:
+; EDX:EAX - long value to be shifted
+; CL - number of bits to shift by
+;
+;Exit:
+; EDX:EAX - shifted value
+;
+;Uses:
+; CL is destroyed.
+;
+;Exceptions:
+;
+;*******************************************************************************
+
+ CODESEG
+
+_allshr PROC NEAR
+
+;
+; Handle shifts of 64 bits or more (if shifting 64 bits or more, the result
+; depends only on the high order bit of edx).
+;
+ cmp cl,64
+ jae short RETSIGN
+
+;
+; Handle shifts of between 0 and 31 bits
+;
+ cmp cl, 32
+ jae short MORE32
+ shrd eax,edx,cl
+ sar edx,cl
+ ret
+
+;
+; Handle shifts of between 32 and 63 bits
+;
+MORE32:
+ mov eax,edx
+ sar edx,31
+ and cl,31
+ sar eax,cl
+ ret
+
+;
+; Return double precision 0 or -1, depending on the sign of edx
+;
+RETSIGN:
+ sar edx,31
+ mov eax,edx
+ ret
+
+_allshr ENDP
+
+ end
diff --git a/private/ole32/common/cruntime/internal.h b/private/ole32/common/cruntime/internal.h
new file mode 100644
index 000000000..8609f63bc
--- /dev/null
+++ b/private/ole32/common/cruntime/internal.h
@@ -0,0 +1,359 @@
+/***
+*internal.h - contains declarations of internal routines and variables
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Declares routines and variables used internally by the C run-time.
+* [Internal]
+*
+*Revision History:
+* 05-18-87 SKS Module created
+* 07-15-87 JCR Added _old_pfxlen and _tempoff
+* 08-05-87 JCR Added _getbuf (corrected by SKS)
+* 11-05-87 JCR Added _buferr
+* 11-18-87 SKS Add __tzset(), made _isindst() near, remove _dtoxmode
+* 01-26-88 SKS Make __tzset, _isindst, _dtoxtime near/far for QC
+* 02-10-88 JCR Cleaned up white space
+* 06-22-88 SKS _canonic/_getcdrv are now used by all models
+* 06-29-88 JCR Removed static buffers _bufout and _buferr
+* 08-18-88 GJF Revised to also work for the 386 (small model only).
+* 09-22-88 GJF Added declarations for _freebuf, _stbuf and _ftbuf.
+* 01-31-89 JCR Removed _canonic, _getcdrv, _getcdwd (see direct.h)
+* 06-07-89 PHG Added _dosret for i860 (N10) version of libs
+* 07-05-89 PHG Changed above to _dosmaperr, added startup variables
+* 08-17-89 GJF Cleanup, removed stuff not needed for 386
+* 10-25-89 JCR Added prototype for _getpath()
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 03-01-90 GJF Added #ifndef _INC_INTERNAL and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessing
+* directives.
+* 03-21-90 GJF Put _CALLTYPE1 into prototypes.
+* 03-26-90 GJF Added prototypes for _output() and _input(). Filled
+* out the prototype for _openfile
+* 04-05-90 GJF Added prototype for __NMSG_WRITE() (C source build
+* only).
+* 04-10-90 GJF Added prototypes for startup functions.
+* 05-28-90 SBM Added _flush()
+* 07-11-90 SBM Added _commode, removed execload()
+* 07-20-90 SBM Changes supporting clean -W3 compiles (added _cftoe
+* and _cftof prototypes)
+* 08-01-90 SBM Moved _cftoe() and _cftof() to new header
+* <fltintrn.h>, formerly named <struct.h>
+* 08-21-90 GJF Changed prototypes for _amsg_exit() and _NMSG_WRITE().
+* 11-29-90 GJF Added some defs/decls for lowio under Win32.
+* 12-04-90 SRW Added _osfile back for win32. Changed _osfinfo from
+* an array of structures to an array of 32-bit handles
+* (_osfhnd)
+* 04-06-91 GJF Changed _heapinit to _heap_init.
+* 08-19-91 JCR Added _exitflag
+* 08-20-91 JCR C++ and ANSI naming
+* 01-05-92 GJF Added declaration for termination done flag [_WIN32_]
+* 01-08-92 GJF Added prototype for _GetMainArgs.
+* 01-18-92 GJF Added _aexit_rtn.
+* 01-22-92 GJF Fixed definitions of _acmdln and _aexit_rtn for the
+* of crtdll.dll, crtdll.lib.
+* 01-29-92 GJF Added support for linked-in options equivalent to
+* commode.obj and setargv.obj (i.e., special declarations
+* for _commode and _dowildcard).
+* 02-14-92 GJF Replace _nfile with _nhandle for Win32. Also, added
+* #define-s for _NHANDLE_.
+* 03-17-92 GJF Removed declaration of _tmpoff for Win32.
+* 03-30-92 DJM POSIX support.
+* 04-27-92 GJF Added prototypes for _ValidDrive (in stat.c).
+* 05-28-92 GJF Added prototype for _mtdeletelocks() for Win32.
+* 06-02-92 SKS Move prototype for _pgmptr to <DOS.H>
+* 06-02-92 KRS Added prototype for _woutput().
+* 08-06-92 GJF Function calling type and variable type macros.
+* 08-17-92 KRS Added prototype for _winput().
+* 08-21-92 GJF Merged last two changes above.
+* 08-24-92 PBS Added _dstoffset for posix TZ
+* 10-24-92 SKS Add a fourth parameter to _GetMainArgs: wildcard flag
+* _GetMainArgs => __GetMainArgs: 2 leading _'s = internal
+* 10-24-92 SKS Remove two unnecessary parameters from _cenvarg()
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 03-30-93 GJF __gmtotime_t supercedes _dtoxtime.
+* 04-17-93 SKS Add _mtterm
+* 05-11-93 SKS _mtinit now returns success (1) or failure (0)
+* _C_Termination_Done needed in all models (for DLLs)
+* 06-02-93 CFW Add _flswbuf, _filwbuf protos.
+* 07-15-93 SRW Added _capture_argv function prototype
+* 09-22-93 CFW Test for invalid MB chars using global preset flag.
+*
+****/
+
+#ifndef _INC_INTERNAL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <cruntime.h>
+
+/* Define function type used in several startup sources */
+
+typedef void (__cdecl *_PVFV)(void);
+
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+#ifdef _DLL
+#define _commode (*_commode_dll)
+extern int * _commode_dll;
+#else
+#ifdef CRTDLL
+#define _commode _commode_dll
+#endif
+extern int _commode;
+#endif
+
+#ifdef _WIN32_
+
+/*
+ * Define the number of supported handles. This definition must exactly match
+ * the one in os2dll.h.
+ */
+#ifdef MTHREAD
+#define _NHANDLE_ 256
+#else
+#define _NHANDLE_ 64
+#endif
+
+extern int _nhandle; /* == _NHANDLE_, set in ioinit.c */
+
+#else /* ndef _WIN32_ */
+
+extern int _nfile;
+
+#endif /* _WIN32_ */
+
+extern char _osfile[];
+
+#ifdef _WIN32_
+extern long _osfhnd[];
+int _CRTAPI1 _alloc_osfhnd(void);
+int _CRTAPI1 _free_osfhnd(int);
+int _CRTAPI1 _set_osfhnd(int,long);
+#endif /* _WIN32_ */
+
+#ifdef _POSIX_
+extern long _dstoffset;
+#endif /* _POSIX_ */
+
+extern char __dnames[];
+extern char __mnames[];
+
+extern int _days[];
+extern int _lpdays[];
+
+#ifndef _TIME_T_DEFINED
+typedef long time_t; /* time value */
+#define _TIME_T_DEFINED /* avoid multiple def's of time_t */
+#endif
+
+extern time_t _CRTAPI1 __gmtotime_t(int, int, int, int, int, int);
+
+#ifdef _TM_DEFINED
+extern int _CRTAPI1 _isindst(struct tm *);
+#endif
+
+extern void _CRTAPI1 __tzset(void);
+#ifdef _POSIX_
+extern void _CRTAPI1 _tzset(void);
+#endif
+
+extern int _CRTAPI1 _ValidDrive(unsigned);
+
+
+/**
+** This variable is in the C start-up; the length must be kept synchronized
+** It is used by the *cenvarg.c modules
+**/
+
+extern char _acfinfo[]; /* "_C_FILE_INFO=" */
+
+#define CFI_LENGTH 12 /* "_C_FILE_INFO" is 12 bytes long */
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+#ifndef _VA_LIST_DEFINED
+#if defined(_ALPHA_)
+typedef struct {
+ char *a0; /* pointer to first homed integer argument */
+ int offset; /* byte offset of next parameter */
+} va_list;
+#else
+typedef char * va_list;
+#endif
+#define _VA_LIST_DEFINED
+#endif
+
+/*
+ * stdio internals
+ */
+#ifdef _FILE_DEFINED
+
+extern FILE * _lastiob;
+
+FILE * _CRTAPI1 _getstream(void);
+#ifdef _POSIX_
+FILE * _CRTAPI1 _openfile(const char *, const char *, FILE *);
+#else
+FILE * _CRTAPI1 _openfile(const char *, const char *, int, FILE *);
+#endif
+void _CRTAPI1 _getbuf(FILE *);
+int _CRTAPI1 _filwbuf (FILE *);
+int __cdecl _flswbuf(int, FILE *);
+void _CRTAPI1 _freebuf(FILE *);
+int _CRTAPI1 _stbuf(FILE *);
+void _CRTAPI1 _ftbuf(int, FILE *);
+int _CRTAPI1 _output(FILE *, const char *, va_list);
+int _CRTAPI1 _woutput(FILE *, const wchar_t *, va_list);
+int _CRTAPI1 _input(FILE *, const unsigned char *, va_list);
+int _CRTAPI1 _winput(FILE *, const wchar_t *, va_list);
+int _CRTAPI1 _flush(FILE *);
+void _CRTAPI1 _endstdio(void);
+
+#endif
+
+extern int __invalid_mb_chars;
+
+extern int _cflush;
+
+#ifdef _CRUISER_
+extern unsigned int _tmpoff;
+#endif /* _CRUISER_ */
+
+extern unsigned int _tempoff;
+
+extern unsigned int _old_pfxlen;
+
+extern int _umaskval; /* the umask value */
+
+extern char _pipech[]; /* pipe lookahead */
+
+extern char _exitflag; /* callable termination flag */
+
+#if defined(_WIN32_)
+extern int _C_Termination_Done; /* termination done flag */
+#endif /* _WIN32_ */
+
+char * _CRTAPI1 _getpath(const char *, char *, unsigned);
+
+/* startup set values */
+extern char **__argv; /* argument vector */
+extern int __argc; /* argument count */
+extern char *_aenvptr; /* environment ptr */
+
+/* command line */
+#ifdef _DLL
+#define _acmdln (*_acmdln_dll)
+extern char **_acmdln_dll;
+#else
+#ifdef CRTDLL
+#define _acmdln _acmdln_dll
+#endif
+extern char *_acmdln;
+#endif
+
+/*
+ * prototypes for internal startup functions
+ */
+int _CRTAPI1 _cwild(void); /* wild.c */
+char * _CRTAPI1 _find(char *); /* stdarg.asm or stdargv.c */
+#ifdef MTHREAD
+int _CRTAPI1 _mtinit(void); /* tidtable.asm */
+void _CRTAPI1 _mtinitlocks(void); /* mlock.asm */
+void _CRTAPI1 _mtterm(void); /* tidtable.asm */
+void _CRTAPI1 _mtdeletelocks(void); /* mlock.asm */
+#endif
+
+/*
+ * C source build only!!!!
+ *
+ * more prototypes for internal startup functions
+ */
+void _CRTAPI1 _amsg_exit(int); /* crt0.c */
+void _CRTAPI1 _cinit(void); /* crt0dat.c */
+void _CRTAPI1 __doinits(void); /* astart.asm */
+void _CRTAPI1 __doterms(void); /* astart.asm */
+void _CRTAPI1 __dopreterms(void); /* astart.asm */
+void _CRTAPI1 _FF_MSGBANNER(void);
+void _CRTAPI1 _fptrap(void); /* crt0fp.c */
+void _CRTAPI1 _heap_init(void);
+#ifdef _WIN32_
+void _CRTAPI1 _ioinit(void); /* crt0.c, crtlib.c */
+#endif /* _WIN32_ */
+void _CRTAPI1 _NMSG_WRITE(int);
+void _CRTAPI1 _setargv(void); /* setargv.c, stdargv.c */
+void _CRTAPI1 __setargv(void); /* stdargv.c */
+void _CRTAPI1 _setenvp(void); /* stdenvp.c */
+
+#ifdef _DLL
+#define _aexit_rtn (*_aexit_rtn_dll)
+extern void (_CRTAPI1 ** _aexit_rtn_dll)(int);
+#else
+#ifdef CRTDLL
+#define _aexit_rtn _aexit_rtn_dll
+#endif
+extern void (_CRTAPI1 * _aexit_rtn)(int);
+#endif
+
+#ifdef _WIN32_
+#if defined(_DLL) || defined(CRTDLL)
+void _CRTAPI1 __GetMainArgs(int *, char ***, char ***, int);
+#endif
+#endif /* _WIN32_ */
+
+/*
+ * C source build only!!!!
+ *
+ * map OS/2 errors into Xenix errno values -- for modules written in C
+ */
+extern void _CRTAPI1 _dosmaperr(unsigned long);
+
+/*
+ * internal routines used by the exec/spawn functions
+ */
+
+extern int _CRTAPI1 _dospawn(int, const char *, char *, char *);
+extern int _CRTAPI1 _cenvarg(const char * const *, const char * const *,
+ char **, char **, const char *);
+extern char ** _CRTAPI1 _capture_argv(
+ va_list *,
+ const char *,
+ char **,
+ size_t
+ );
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_INTERNAL
+#endif /* _INC_INTERNAL */
diff --git a/private/ole32/common/cruntime/isctype.c b/private/ole32/common/cruntime/isctype.c
new file mode 100644
index 000000000..944d6dfdf
--- /dev/null
+++ b/private/ole32/common/cruntime/isctype.c
@@ -0,0 +1,116 @@
+/***
+*isctype.c - support is* ctype functions/macros for two-byte multibyte chars
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines _isctype.c - support is* ctype functions/macros for
+* two-byte multibyte chars.
+*
+*Revision History:
+* 10-11-91 ETC Created.
+* 12-08-91 ETC Updated api; added multhread lock; check char masks.
+* 04-06-92 KRS Fix logic error in return value.
+* 08-07-92 GJF _CALLTYPE4 (bogus usage) -> _CRTAPI1 (legit).
+* 01-19-93 CFW Change C1_* to new names, call new APIs.
+* 03-04-93 CFW Removed CTRL-Z.
+* 04-01-93 CFW Remove EOF test (handled by array), return masked.
+* 06-02-93 SRW ignore _INTL if _NTSUBSET_ defined.
+*
+*******************************************************************************/
+#include <windows.h>
+#include <cruntime.h>
+#include <setlocal.h>
+
+#if defined(_INTL) && !defined(_NTSUBSET_)
+
+/*
+ * Use GetCharType() API so check that character type masks agree between
+ * ctype.h and winnls.h
+ */
+#if _UPPER != C1_UPPER || \
+ _LOWER != C1_LOWER || \
+ _DIGIT != C1_DIGIT || \
+ _SPACE != C1_SPACE || \
+ _PUNCT != C1_PUNCT || \
+ _CONTROL != C1_CNTRL
+#error Character type masks do not agree in ctype and winnls
+#endif
+
+/***
+*_isctype - support is* ctype functions/macros for two-byte multibyte chars
+*
+*Purpose:
+* This function is called by the is* ctype functions/macros
+* (e.g. isalpha()) when their argument is a two-byte multibyte char.
+* Returns true or false depending on whether the argument satisfies
+* the character class property encoded by the mask.
+*
+*Entry:
+* int c - the multibyte character whose type is to be tested
+* unsigned int mask - the mask used by the is* functions/macros
+* corresponding to each character class property
+*
+* The leadbyte and the trailbyte should be packed into the int c as:
+*
+* H.......|.......|.......|.......L
+* 0 0 leadbyte trailbyte
+*
+*Exit:
+* Returns non-zero if c is of the character class.
+* Returns 0 if c is not of the character class.
+*
+*Exceptions:
+* Returns 0 on any error.
+*
+*******************************************************************************/
+
+int _CRTAPI1 _isctype (
+ int c,
+ int mask
+ )
+{
+ wchar_t widechar[2], chartype;
+ char buffer[3];
+
+ /* c valid between -1 and 255 */
+ if (((unsigned)(c + 1)) <= 256)
+ return _pctype[c] & mask;
+
+// _mlock (_LC_CTYPE_LOCK);
+
+ if (isleadbyte(c>>8 & 0xff))
+ {
+ buffer[0] = (c>>8 & 0xff); /* put lead-byte at start of str */
+ buffer[1] = (char)c;
+ buffer[2] = 0;
+ }
+ else
+ {
+ buffer[0] = (char)c;
+ buffer[1] = 0;
+ }
+ if (MultiByteToWideChar(_lc_codepage, MB_PRECOMPOSED,
+ buffer, -1, widechar, 2) == 0)
+ return 0;
+
+// _munlock (_LC_CTYPE_LOCK);
+
+ if (GetStringTypeW(CT_CTYPE1, widechar, 2, &chartype) != NO_ERROR) {
+ return 0;
+ }
+
+ return (int)(chartype & mask);
+}
+
+#else /* defined(_INTL) && !defined(_NTSUBSET_) */
+
+int _CRTAPI1 _isctype (
+ int c,
+ int mask
+ )
+{
+ return 0;
+}
+
+#endif /* _INTL */
diff --git a/private/ole32/common/cruntime/mlock.c b/private/ole32/common/cruntime/mlock.c
new file mode 100644
index 000000000..a72fbeed7
--- /dev/null
+++ b/private/ole32/common/cruntime/mlock.c
@@ -0,0 +1,206 @@
+#ifdef MTHREAD
+
+/***
+*mlock.c - Multi-thread locking routines
+*
+* Copyright (c) 1987-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 05-07-90 JCR Module created.
+* 06-04-90 GJF Changed error message interface.
+* 08-08-90 GJF Removed 32 from API names.
+* 08-08-90 SBM _lockmap no longer 8 times required size
+* 10-08-90 GJF New-style function declarators. Removed questionable
+* return statements from void functions (weren't needed
+* and the compiler was bitching).
+* 10-09-90 GJF Thread ids are unsigned longs.
+* 06-06-91 GJF Adapted for Win32 [_WIN32_].
+* 09-29-91 GJF Fixed infinite recursion problem with DEBUG version
+* of _lock [_WIN32_].
+* 03-06-92 GJF Removed _[un]lock_fh() and _[un]lock_stream for Win32
+* targets.
+* 05-28-92 GJF Added _mtdeletelocks() for Win32 for DLLs with contain
+* the C runtime (e.g., crtdll.dll).
+* 10-06-92 SRW Make _locktable an array of PCRITICAL_SECTION pointers
+* instead of structures. Allocate each critical section
+* as it is needed.
+* 02-25-93 GJF Substantially revised. Restored static critical section
+* structures for some locks. Replaced bit-array scheme
+* of keeping track of locks. Removed Cruiser support and
+* replaced obsolete DEBUG code.
+* 03-03-93 GJF Made CRITICAL_SECTION structure for _HEAP_LOCK static.
+* 03-08-93 SKS Fix ptr use error in DEBUG version of _mtdeletelocks
+* 03-08-93 SKS Fix deletion of the special critical sections,
+* especially the heap lock.
+* 05-05-93 GJF Turned DEBUG code off.
+* 06-03-93 SRW Disable FPO optimizations for this file so it can call
+* CriticalSection routines on a checked build even though
+* the C Runtimes are compiled free.
+*
+*******************************************************************************/
+
+#include <windows.h>
+#include <cruntime.h>
+#include <internal.h>
+#include <os2dll.h>
+#include <assert.h>
+
+
+/*
+ * Local routines
+ */
+void _CRTAPI3 _lockerr_exit(char *);
+
+
+/*
+ * Global Data
+ */
+
+/*
+ * Statically allocated critical section structures for _LOCKTAB_LOCK,
+ * _EXIT_LOCK1.
+ */
+static CRITICAL_SECTION xlcritsect;
+
+/*
+ * Lock Table
+ * This table contains a pointer to the critical section management structure
+ * for each lock.
+ */
+PCRITICAL_SECTION _locktable[_TOTAL_LOCKS] = {
+ NULL, /* 0 == no lock defined *** OBSOLETE *** */
+ &xlcritsect /* 1 == _EXIT_LOCK1 */
+ };
+
+#pragma data_seg()
+
+#pragma optimize("y",off)
+
+/***
+*_mtinitlocks() - Initialize multi-thread lock scheme
+*
+*Purpose:
+* Perform whatever initialization is required for the multi-thread
+* locking (synchronization) scheme. This routine should be called
+* exactly once, during startup, and this must be before any requests
+* are made to assert locks.
+*
+* NOTES: In Win32, the multi-thread locks are created individually,
+* each upon its first use. That is when any particular lock is asserted
+* for the first time, the underlying critical section is then allocated,
+* initialized and (finally) entered. This allocation and initialization
+* is protected under _LOCKTAB_LOCK. It is _mtinitlocks' job to set up
+* _LOCKTAB_LOCK. _EXIT_LOCK1 is also set up by _mtinitlock
+*
+*Entry:
+* <none>
+*
+*Exit:
+* returns on success
+* calls _amsg_exit on failure
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _mtinitlocks (
+ void
+ )
+{
+
+ /*
+ * All we need to do is initialize _EXIT_LOCK1.
+ */
+ InitializeCriticalSection( _locktable[_EXIT_LOCK1] );
+}
+
+
+/***
+*_mtdeletelocks() - Delete all initialized locks
+*
+*Purpose:
+* Walks _locktable[] and _lockmap, and deletes every 'lock' (i.e.,
+* critical section) which has been initialized.
+*
+* This function is intended for use in DLLs containing the C runtime
+* (i.e., crtdll.dll and user DLLs built using libcmt.lib and the
+* special startup objects). It is to be called from within the DLL's
+* entrypoint function when that function is called with
+* DLL_PROCESS_DETACH.
+*
+*Entry:
+* <none>
+*
+*Exit:
+*
+*Exceptions:
+* behavior undefined/unknown if a lock is being held when this routine
+* is called.
+*
+*******************************************************************************/
+
+void _CRTAPI1 _mtdeletelocks(
+ void
+ )
+{
+ DeleteCriticalSection( _locktable[_EXIT_LOCK1] );
+}
+
+
+/***
+* _lock - Acquire a multi-thread lock
+*
+*Purpose:
+* Note that it is legal for a thread to aquire _EXIT_LOCK1
+* multiple times.
+*
+*Entry:
+* locknum = number of the lock to aquire
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _lock (
+ int locknum
+ )
+{
+ assert (_locktable[locknum]);
+
+ EnterCriticalSection( _locktable[locknum] );
+}
+
+
+/***
+* _unlock - Release multi-thread lock
+*
+*Purpose:
+* Note that it is legal for a thread to aquire _EXIT_LOCK1
+* multiple times.
+*
+*Entry:
+* locknum = number of the lock to release
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _unlock (
+ int locknum
+ )
+{
+ /*
+ * leave the critical section.
+ */
+ LeaveCriticalSection( _locktable[locknum] );
+}
+
+#pragma optimize("y",)
+
+#endif /* MTHREAD */
diff --git a/private/ole32/common/cruntime/mm.inc b/private/ole32/common/cruntime/mm.inc
new file mode 100644
index 000000000..9510eaa42
--- /dev/null
+++ b/private/ole32/common/cruntime/mm.inc
@@ -0,0 +1,38 @@
+;***
+;mm.inc - macros to write memory model dependent code
+;
+; Copyright (c) 1987-1994, Microsoft Corporation. All rights reserved.
+;
+;Purpose:
+; This file contains definitions of a number of macros which
+; make the writing of memory model dependent code for the
+; 386 a little easier and more portable.
+;
+;Revision History:
+; 05-18-89 SKS Removed ES references from pointer macros -- DS is used
+; 09-01-89 GJF Fixed copyright date.
+; 11-19-93 SMK Modified for 32 bit hosting.
+;
+;*******************************************************************************
+
+; general code & data size constants & macros
+
+DAT_ADDR_SZ = 4
+BDAT_ADDR_SZ = 2
+
+TXT_ADDR_SZ = 4
+
+; Big/Little Endian Definitions for Long Integers
+
+ifdef bigend ; Big Endian (hi word at low address)
+LOWORD equ [4]
+HIWORD equ [0]
+else ; Little Endian (low word at low address)
+LOWORD equ [0]
+HIWORD equ [4]
+endif
+
+
+; All Model Definitions
+
+BPARGBAS equ TXT_ADDR_SZ+4 ; offset from BP to first argument
diff --git a/private/ole32/common/cruntime/nlsdata1.c b/private/ole32/common/cruntime/nlsdata1.c
new file mode 100644
index 000000000..14e9f5f03
--- /dev/null
+++ b/private/ole32/common/cruntime/nlsdata1.c
@@ -0,0 +1,23 @@
+/***
+*nlsdata1.c - globals for international library - small globals
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module contains the globals: __mb_cur_max, _decimal_point,
+* _decimal_point_length. This module is always required.
+* This module is separated from nlsdatax.c for granularity.
+*
+*Revision History:
+* 12-01-91 ETC Created.
+* 04-03-92 PLM Changes tdef.h to tchar.h
+* 08-18-92 KRS Rip out _tflag--not used.
+*
+*******************************************************************************/
+
+
+/*
+ * Value of MB_CUR_MAX macro.
+ */
+unsigned short __mb_cur_max = 1;
+
diff --git a/private/ole32/common/cruntime/nlsdata2.c b/private/ole32/common/cruntime/nlsdata2.c
new file mode 100644
index 000000000..98cc58640
--- /dev/null
+++ b/private/ole32/common/cruntime/nlsdata2.c
@@ -0,0 +1,24 @@
+/***
+*nlsdata2.c - globals for international library - locale handles and code page
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module defines the locale handles and code page. The handles are
+* required by almost all locale dependent functions. This module is
+* separated from nlsdatax.c for granularity.
+*
+*Revision History:
+* 12-01-91 ETC Created.
+*
+*******************************************************************************/
+
+#include <windows.h>
+#include <setlocal.h>
+
+/*
+ * Code page.
+ */
+UINT _lc_codepage = _CLOCALECP; /* CP_ACP */
+
+#pragma data_seg()
diff --git a/private/ole32/common/cruntime/onexit.c b/private/ole32/common/cruntime/onexit.c
new file mode 100644
index 000000000..1d6bcdf89
--- /dev/null
+++ b/private/ole32/common/cruntime/onexit.c
@@ -0,0 +1,137 @@
+/***
+*onexit.c - save function for execution on exit
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _onexit(), atexit() - save function for execution at exit
+*
+
+*Revision History:
+* 06-30-89 PHG module created, based on asm version
+* 03-15-90 GJF Replace _cdecl with _CALLTYPE1, added #include
+* <cruntime.h> and fixed the copyright. Also,
+* cleaned up the formatting a bit.
+* 05-21-90 GJF Fixed compiler warning.
+* 10-04-90 GJF New-style function declarators.
+* 12-28-90 SRW Added casts of func for Mips C Compiler
+* 01-21-91 GJF ANSI naming.
+* 09-09-91 GJF Revised for C++ needs.
+* 03-20-92 SKS Revamped for new initialization model
+* 04-23-92 DJM POSIX support.
+* 12-02-93 SKS Add __dllonexit for DLLs using CRTDLL.DLL
+*
+*******************************************************************************/
+
+#include <windows.h>
+#include <stdlib.h>
+#include <cruntime.h>
+#include <internal.h>
+#include <os2dll.h>
+
+
+#ifndef _CHICAGO_
+extern void DbgBreakPoint();
+#endif
+
+typedef void (_CALLTYPE1 *PF)(void); /* pointer to function */
+
+
+//
+// Keep this really simple: just have a vector of functions to be
+// called. We use a fixed length vector, since this is a special
+// application
+//
+
+#define MAX_EXIT_NOTIFICATIONS 48
+
+PF NotificationTable[MAX_EXIT_NOTIFICATIONS];
+
+extern PF * __onexitbegin;
+extern PF * __onexitend;
+
+
+/*
+ * Define increment (in entries) for growing the _onexit/atexit table
+ */
+#define ONEXITTBLINCR 4
+
+
+/***
+*_onexit(func), atexit(func) - add function to be executed upon exit
+*
+*Purpose:
+* The _onexit/atexit functions are passed a pointer to a function
+* to be called when the program terminate normally. Successive
+* calls create a register of functions that are executed last in,
+* first out.
+*
+*Entry:
+* void (*func)() - pointer to function to be executed upon exit
+*
+*Exit:
+* onexit:
+* Success - return pointer to user's function.
+* Error - return NULL pointer.
+* atexit:
+* Success - return 0.
+* Error - return non-zero value.
+*
+*Notes:
+* This routine depends on the behavior of _initterm() in CRT0DAT.C.
+* Specifically, _initterm() must not skip the address pointed to by
+* its first parameter, and must also stop before the address pointed
+* to by its second parameter. This is because _onexitbegin will point
+* to a valid address, and _onexitend will point at an invalid address.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+_onexit_t _CALLTYPE1 _onexit (
+ _onexit_t func
+ )
+
+{
+ PF *p;
+
+ _lockexit(); /* lock the exit code */
+
+ // If the notification table hasn't been initialized, do so
+
+ if (__onexitbegin == NULL) {
+ __onexitbegin = __onexitend = NotificationTable;
+ } else if (__onexitend >= &NotificationTable[MAX_EXIT_NOTIFICATIONS]) {
+ // No space...
+#if DBG
+ OutputDebugString ("(common\\cruntime\\onexit.c\\_onexit) Too many exit notifications!\n");
+ DebugBreak ();
+#endif
+ return NULL;
+ }
+
+
+ //
+ // Put the new entry into the table and update the end-of-table
+ // pointer.
+ //
+
+ *(__onexitend++) = (PF)func;
+
+ _unlockexit();
+
+ return func;
+
+}
+
+int _CALLTYPE1 atexit (
+ PF func
+ )
+{
+ return (_onexit((_onexit_t)func) == NULL) ? -1 : 0;
+}
+
+
+
+
diff --git a/private/ole32/common/cruntime/os2dll.h b/private/ole32/common/cruntime/os2dll.h
new file mode 100644
index 000000000..d7bc303df
--- /dev/null
+++ b/private/ole32/common/cruntime/os2dll.h
@@ -0,0 +1,131 @@
+/***
+*os2dll.h - DLL/Multi-thread include
+*
+* Copyright (c) 1987-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+* 10-27-87 JCR Module created.
+* 11-13-87 SKS Added _HEAP_LOCK
+* 12-15-87 JCR Added _EXIT_LOCK
+* 01-07-88 BCM Added _SIGNAL_LOCK; upped MAXTHREADID from 16 to 32
+* 02-01-88 JCR Added _dll_mlock/_dll_munlock macros
+* 05-02-88 JCR Added _BHEAP_LOCK
+* 06-17-88 JCR Corrected prototypes for special mthread debug routines
+* 08-15-88 JCR _check_lock now returns int, not void
+* 08-22-88 GJF Modified to also work for the 386 (small model only)
+* 06-05-89 JCR 386 mthread support
+* 06-09-89 JCR 386: Added values to _tiddata struc (for _beginthread)
+* 07-13-89 JCR 386: Added _LOCKTAB_LOCK
+* 08-17-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 01-02-90 JCR Moved a bunch of definitions from os2dll.inc
+* 04-06-90 GJF Added _INC_OS2DLL stuff and #include <cruntime.h>. Made
+* all function _CALLTYPE2 (for now).
+* 04-10-90 GJF Added prototypes for _[un]lockexit().
+* 08-16-90 SBM Made _terrno and _tdoserrno int, not unsigned
+* 09-14-90 GJF Added _pxcptacttab, _pxcptinfoptr and _fpecode fields
+* to _tiddata struct.
+* 10-09-90 GJF Thread ids are of type unsigned long.
+* 12-06-90 SRW Added _OSFHND_LOCK
+* 06-04-91 GJF Win32 version of multi-thread types and prototypes.
+* 08-15-91 GJF Made _tdoserrno an unsigned long for Win32.
+* 08-20-91 JCR C++ and ANSI naming
+* 09-29-91 GJF Conditionally added prototypes for _getptd_lk
+* and _getptd1_lk for Win32 under DEBUG.
+* 10-03-91 JCR Added _cvtbuf to _tiddata structure
+* 02-17-92 GJF For Win32, replaced _NFILE_ with _NHANDLE_ and
+* _NSTREAM_.
+* 03-06-92 GJF For Win32, made _[un]mlock_[fh|stream]() macros
+* directly call _[un]lock().
+* 03-17-92 GJF Dropped _namebuf field from _tiddata structure for
+* Win32.
+* 08-05-92 GJF Function calling type and variable type macros.
+* 12-03-91 ETC Added _wtoken to _tiddata, added intl LOCK's;
+* added definition of wchar_t (needed for _wtoken).
+* 08-14-92 KRS Port ETC's _wtoken change from other tree.
+* 08-21-92 GJF Merged 08-05-92 and 08-14-92 versions.
+* 12-03-92 KRS Added _mtoken field for MTHREAD _mbstok().
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+* 02-25-93 GJF Purged Cruiser support and many outdated definitions
+* and declarations.
+* 12-14-93 SKS Add _freeptd(), which frees per-thread CRT data
+*
+****/
+
+#ifndef _INC_OS2DLL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <cruntime.h>
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+
+/* Lock symbols */
+
+#define _EXIT_LOCK1 1 /* lock #1 for exit code */
+
+#define _TOTAL_LOCKS (_EXIT_LOCK1+1) /* Total number of locks */
+
+#define _LOCK_BIT_INTS (_TOTAL_LOCKS/(sizeof(unsigned)*8))+1 /* # of ints to hold lock bits */
+
+
+/* need wchar_t for _wtoken field in _tiddata */
+#ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+
+/* macros */
+
+#define _mlock(l) _lock(l)
+#define _munlock(l) _unlock(l)
+
+
+/* multi-thread routines */
+
+void _CRTAPI1 _lock(int);
+void _CRTAPI1 _lockexit(void);
+void _CRTAPI1 _unlock(int);
+void _CRTAPI1 _unlockexit(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_OS2DLL
+#endif /* _INC_OS2DLL */
+
+
+
+
+
+
+
diff --git a/private/ole32/common/cruntime/process.h b/private/ole32/common/cruntime/process.h
new file mode 100644
index 000000000..946545f7c
--- /dev/null
+++ b/private/ole32/common/cruntime/process.h
@@ -0,0 +1,244 @@
+/***
+*process.h - definition and declarations for process control functions
+*
+* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the modeflag values for spawnxx calls.
+* Only P_WAIT and P_OVERLAY are currently implemented on MS-DOS.
+* Also contains the function argument declarations for all
+* process control related routines.
+*
+*Revision History:
+* 08/24/87 JCR Added P_NOWAITO
+* 10/20/87 JCR Removed "MSC40_ONLY" entries and "MSSDK_ONLY" comments
+* 12-11-87 JCR Added "_loadds" functionality
+* 12-18-87 JCR Added _FAR_ to declarations
+* 01-11-88 JCR Added _beginthread/_endthread
+* 01-15-88 JCR Got rid of _p_overlay for MTRHEAD/DLL
+* 02-10-88 JCR Cleaned up white space
+* 05-08-88 SKS Removed bogus comment about "DOS 4"; Added "P_DETACH"
+* 08-22-88 GJF Modified to also work for the 386 (small model only)
+* 09-14-88 JCR Added _cexit and _c_exit declarations
+* 05-03-89 JCR Added _INTERNAL_IFSTRIP for relinc usage
+* 06-08-89 JCR 386 _beginthread does NOT take a stackpointer arg
+* 08-01-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat model)
+* 10-30-89 GJF Fixed copyright
+* 11-02-89 JCR Changed "DLL" to "_DLL"
+* 11-17-89 GJF Added const attribute to appropriate arg types
+* 03-01-90 GJF Added #ifndef _INC_PROCESS and #include <cruntime.h>
+* stuff. Also, removed some (now) useless preprocessor
+* directives.
+* 03-21-90 GJF Replaced _cdecl with _CALLTYPE1 or _CALLTYPE2 in
+* prototypes.
+* 04-10-90 GJF Replaced remaining instances of _cdecl (with _CALLTYPE1
+* or _VARTYPE1, as appropriate).
+* 10-12-90 GJF Changed return type of _beginthread() to unsigned long.
+* 01-17-91 GJF ANSI naming.
+* 08-20-91 JCR C++ and ANSI naming
+* 08-26-91 BWM Added prototypes for _loaddll, unloaddll, and
+* _getdllprocaddr.
+* 09-28-91 JCR ANSI names: DOSX32=prototypes, WIN32=#defines for now
+* 07-22-92 GJF Deleted references to _wait for Win32.
+* 08-05-92 GJF Function calling type and variable type macros.
+* 08-28-92 GJF #ifdef-ed out for POSIX.
+* 09-03-92 GJF Merged two changes above.
+* 01-21-93 GJF Removed support for C6-386's _cdecl.
+*
+****/
+
+#ifndef _INC_PROCESS
+
+#ifndef _POSIX_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _INTERNAL_IFSTRIP_
+#include <cruntime.h>
+#endif /* _INTERNAL_IFSTRIP_ */
+
+/*
+ * Conditional macro definition for function calling type and variable type
+ * qualifiers.
+ */
+#if ( (_MSC_VER >= 800) && (_M_IX86 >= 300) )
+
+/*
+ * Definitions for MS C8-32 (386/486) compiler
+ */
+#define _CRTAPI1 __cdecl
+#define _CRTAPI2 __cdecl
+
+#else
+
+/*
+ * Other compilers (e.g., MIPS)
+ */
+#define _CRTAPI1
+#define _CRTAPI2
+
+#endif
+
+
+/* modeflag values for _spawnxx routines */
+
+#ifndef MTHREAD
+extern int _CRTVAR1 _p_overlay;
+#endif
+
+#define _P_WAIT 0
+#define _P_NOWAIT 1
+#ifdef MTHREAD
+#define _P_OVERLAY 2
+#else
+#define _P_OVERLAY _p_overlay
+#endif
+#define _OLD_P_OVERLAY 2
+#define _P_NOWAITO 3
+#define _P_DETACH 4
+
+
+/* Action codes for _cwait(). The action code argument to _cwait is ignored
+ on Win32 though it is accepted for compatibilty with OS/2 */
+
+#define _WAIT_CHILD 0
+#define _WAIT_GRANDCHILD 1
+
+
+/* function prototypes */
+
+#ifdef MTHREAD
+unsigned long _CRTAPI1 _beginthread (void (_CRTAPI1 *) (void *),
+ unsigned, void *);
+void _CRTAPI1 _endthread(void);
+#endif
+void _CRTAPI1 abort(void);
+void _CRTAPI1 _cexit(void);
+void _CRTAPI1 _c_exit(void);
+int _CRTAPI1 _cwait(int *, int, int);
+int _CRTAPI2 _execl(const char *, const char *, ...);
+int _CRTAPI2 _execle(const char *, const char *, ...);
+int _CRTAPI2 _execlp(const char *, const char *, ...);
+int _CRTAPI2 _execlpe(const char *, const char *, ...);
+int _CRTAPI1 _execv(const char *, const char * const *);
+int _CRTAPI1 _execve(const char *, const char * const *, const char * const *);
+int _CRTAPI1 _execvp(const char *, const char * const *);
+int _CRTAPI1 _execvpe(const char *, const char * const *, const char * const *);
+void _CRTAPI1 exit(int);
+void _CRTAPI1 _exit(int);
+int _CRTAPI1 _getpid(void);
+int _CRTAPI2 _spawnl(int, const char *, const char *, ...);
+int _CRTAPI2 _spawnle(int, const char *, const char *, ...);
+int _CRTAPI2 _spawnlp(int, const char *, const char *, ...);
+int _CRTAPI2 _spawnlpe(int, const char *, const char *, ...);
+int _CRTAPI1 _spawnv(int, const char *, const char * const *);
+int _CRTAPI1 _spawnve(int, const char *, const char * const *,
+ const char * const *);
+int _CRTAPI1 _spawnvp(int, const char *, const char * const *);
+int _CRTAPI1 _spawnvpe(int, const char *, const char * const *,
+ const char * const *);
+int _CRTAPI1 system(const char *);
+#ifndef _WIN32_
+int _CRTAPI1 _wait(int *);
+#endif
+int _CRTAPI1 _loaddll(char *);
+int _CRTAPI1 _unloaddll(int);
+int (_CRTAPI1 * _CRTAPI1 _getdllprocaddr(int, char *, int))();
+
+#ifdef _DECL_DLLMAIN
+/*
+ * Declare DLL notification (initialization/termination) routines
+ * The preferred method is for the user to provide DllMain() which will
+ * be called automatically by the DLL entry point defined by the C run-
+ * time library code. If the user wants to define the DLL entry point
+ * routine, the user's entry point must call _CRT_INIT on all types of
+ * notifications, as the very first thing on attach notifications and
+ * as the very last thing on detach notifications.
+ */
+#ifdef _WINDOWS_ /* Use types from WINDOWS.H */
+BOOL WINAPI DllMain(HANDLE, DWORD, LPVOID);
+BOOL WINAPI _CRT_INIT(HANDLE, DWORD, LPVOID);
+#else
+#ifdef _M_IX86
+int __stdcall DllMain(void *, unsigned, void *);
+int __stdcall _CRT_INIT(void *, unsigned, void *);
+#else
+int DllMain(void *, unsigned, void *);
+int _CRT_INIT(void *, unsigned, void *);
+#endif
+#endif /* _WINDOWS_ */
+#endif /* _DECL_DLLMAIN */
+
+#if !__STDC__
+/* Non-ANSI names for compatibility */
+
+#define P_WAIT _P_WAIT
+#define P_NOWAIT _P_NOWAIT
+#define P_OVERLAY _P_OVERLAY
+#define OLD_P_OVERLAY _OLD_P_OVERLAY
+#define P_NOWAITO _P_NOWAITO
+#define P_DETACH _P_DETACH
+
+#define WAIT_CHILD _WAIT_CHILD
+#define WAIT_GRANDCHILD _WAIT_GRANDCHILD
+
+#ifndef _DOSX32_
+#define cwait _cwait
+#define execl _execl
+#define execle _execle
+#define execlp _execlp
+#define execlpe _execlpe
+#define execv _execv
+#define execve _execve
+#define execvp _execvp
+#define execvpe _execvpe
+#define getpid _getpid
+#define spawnl _spawnl
+#define spawnle _spawnle
+#define spawnlp _spawnlp
+#define spawnlpe _spawnlpe
+#define spawnv _spawnv
+#define spawnve _spawnve
+#define spawnvp _spawnvp
+#define spawnvpe _spawnvpe
+#ifndef _WIN32_
+#define wait _wait
+#endif
+#else
+int _CRTAPI1 cwait(int *, int, int);
+int _CRTAPI2 execl(const char *, const char *, ...);
+int _CRTAPI2 execle(const char *, const char *, ...);
+int _CRTAPI2 execlp(const char *, const char *, ...);
+int _CRTAPI2 execlpe(const char *, const char *, ...);
+int _CRTAPI1 execv(const char *, const char * const *);
+int _CRTAPI1 execve(const char *, const char * const *, const char * const *);
+int _CRTAPI1 execvp(const char *, const char * const *);
+int _CRTAPI1 execvpe(const char *, const char * const *, const char * const *);
+int _CRTAPI1 getpid(void);
+int _CRTAPI2 spawnl(int, const char *, const char *, ...);
+int _CRTAPI2 spawnle(int, const char *, const char *, ...);
+int _CRTAPI2 spawnlp(int, const char *, const char *, ...);
+int _CRTAPI2 spawnlpe(int, const char *, const char *, ...);
+int _CRTAPI1 spawnv(int, const char *, const char * const *);
+int _CRTAPI1 spawnve(int, const char *, const char * const *,
+ const char * const *);
+int _CRTAPI1 spawnvp(int, const char *, const char * const *);
+int _CRTAPI1 spawnvpe(int, const char *, const char * const *,
+ const char * const *);
+#ifndef _WIN32_
+int _CRTAPI1 wait(int *);
+#endif
+#endif
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _POSIX_ */
+
+#define _INC_PROCESS
+#endif /* _INC_PROCESS */
diff --git a/private/ole32/common/cruntime/purevirt.c b/private/ole32/common/cruntime/purevirt.c
new file mode 100644
index 000000000..cde73acc3
--- /dev/null
+++ b/private/ole32/common/cruntime/purevirt.c
@@ -0,0 +1,43 @@
+/***
+*purevirt.c - stub to trap pure virtual function calls
+*
+* Copyright (c) 1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines _purecall() -
+*
+*Revision History:
+* 09-30-92 GJF Module created
+*
+*******************************************************************************/
+
+#include <windows.h>
+#include <cruntime.h>
+
+/***
+*void _purecall(void) -
+*
+*Purpose:
+*
+*Entry:
+* No arguments
+*
+*Exit:
+* Never returns
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _purecall(
+ void
+ )
+{
+#if DBG==1
+ MessageBoxA (NULL
+ "Pure virtual function call attempted",
+ "OLE runtime error",
+ MB_ICONSTOP | MB_OK | MB_TASKMODAL);
+#endif
+}
+
diff --git a/private/ole32/common/cruntime/qsort.c b/private/ole32/common/cruntime/qsort.c
new file mode 100644
index 000000000..30e15e6fd
--- /dev/null
+++ b/private/ole32/common/cruntime/qsort.c
@@ -0,0 +1,329 @@
+/***
+*qsort.c - quicksort algorithm; qsort() library function for sorting arrays
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* To implement the qsort() routine for sorting arrays.
+*
+*Revision History:
+* 06-22-84 RN author
+* 03-25-85 RN added pre-check for elements already in order to
+* eliminate worst-case behavior.
+* 05-18-86 TC changed to recurse on the smallest piece to avoid
+* piece. unneccesary stack usage, and to iterate on
+* largest
+* 01-09-87 BCM fixed huge-array case where (num-1) * wid computation
+* was overflowing (large/compact models only)
+* 06-13-89 PHG made more efficient, many more comments, removed
+* recursion
+* 10-30-89 JCR Added _cdecl to prototypes
+* 03-15-90 GJF Replaced _cdecl with _CALLTYPE1 and added #include
+* <cruntime.h>. Also, fixed the copyright.
+* 04-05-90 GJF Made shortsort() and swap() _CALLTYPE4. Also, added
+* #include <search.h>.
+* 10-04-90 GJF New-style function declarators.
+* 12-28-90 SRW Added _CRUISER_ conditional around check_stack pragmas
+* 01-24-91 SRW Added missing close comment in swap procedure
+* 11-19-91 GJF Do the swap one character at a time to avoid alignment
+* woes.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <search.h>
+
+/* prototypes for local routines */
+static void _CALLTYPE4 shortsort(char *lo, char *hi, unsigned width,
+ int (_CALLTYPE1 *comp)(const void *, const void *));
+static void _CALLTYPE4 swap(char *p, char *q, unsigned int width);
+
+/* this parameter defines the cutoff between using quick sort and
+ insertion sort for arrays; arrays with lengths shorter or equal to the
+ below value use insertion sort */
+
+#define CUTOFF 8 /* testing shows that this is good value */
+
+
+/***
+*qsort(base, num, wid, comp) - quicksort function for sorting arrays
+*
+*Purpose:
+* quicksort the array of elements
+* side effects: sorts in place
+*
+*Entry:
+* char *base = pointer to base of array
+* unsigned num = number of elements in the array
+* unsigned width = width in bytes of each array element
+* int (*comp)() = pointer to function returning analog of strcmp for
+* strings, but supplied by user for comparing the array elements.
+* it accepts 2 pointers to elements and returns neg if 1<2, 0 if
+* 1=2, pos if 1>2.
+*
+*Exit:
+* returns void
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+#ifdef _CRUISER_
+#pragma check_stack(on) /* lots of locals */
+#endif /* ndef _CRUISER_ */
+
+/* sort the array between lo and hi (inclusive) */
+
+void _CALLTYPE1 qsort (
+ void *base,
+ unsigned num,
+ unsigned width,
+ int (_CALLTYPE1 *comp)(const void *, const void *)
+ )
+{
+ char *lo, *hi; /* ends of sub-array currently sorting */
+ char *mid; /* points to middle of subarray */
+ char *loguy, *higuy; /* traveling pointers for partition step */
+ unsigned size; /* size of the sub-array */
+ char *lostk[30], *histk[30];
+ int stkptr; /* stack for saving sub-array to be processed */
+
+ /* Note: the number of stack entries required is no more than
+ 1 + log2(size), so 30 is sufficient for any array */
+
+ if (num < 2 || width == 0)
+ return; /* nothing to do */
+
+ stkptr = 0; /* initialize stack */
+
+ lo = base;
+ hi = (char *)base + width * (num-1); /* initialize limits */
+
+ /* this entry point is for pseudo-recursion calling: setting
+ lo and hi and jumping to here is like recursion, but stkptr is
+ prserved, locals aren't, so we preserve stuff on the stack */
+recurse:
+
+ size = (hi - lo) / width + 1; /* number of el's to sort */
+
+ /* below a certain size, it is faster to use a O(n^2) sorting method */
+ if (size <= CUTOFF) {
+ shortsort(lo, hi, width, comp);
+ }
+ else {
+ /* First we pick a partititioning element. The efficiency of the
+ algorithm demands that we find one that is approximately the
+ median of the values, but also that we select one fast. Using
+ the first one produces bad performace if the array is already
+ sorted, so we use the middle one, which would require a very
+ wierdly arranged array for worst case performance. Testing shows
+ that a median-of-three algorithm does not, in general, increase
+ performance. */
+
+ mid = lo + (size / 2) * width; /* find middle element */
+ swap(mid, lo, width); /* swap it to beginning of array */
+
+ /* We now wish to partition the array into three pieces, one
+ consisiting of elements <= partition element, one of elements
+ equal to the parition element, and one of element >= to it. This
+ is done below; comments indicate conditions established at every
+ step. */
+
+ loguy = lo;
+ higuy = hi + width;
+
+ /* Note that higuy decreases and loguy increases on every iteration,
+ so loop must terminate. */
+ for (;;) {
+ /* lo <= loguy < hi, lo < higuy <= hi + 1,
+ A[i] <= A[lo] for lo <= i <= loguy,
+ A[i] >= A[lo] for higuy <= i <= hi */
+
+ do {
+ loguy += width;
+ } while (loguy <= hi && comp(loguy, lo) <= 0);
+
+ /* lo < loguy <= hi+1, A[i] <= A[lo] for lo <= i < loguy,
+ either loguy > hi or A[loguy] > A[lo] */
+
+ do {
+ higuy -= width;
+ } while (higuy > lo && comp(higuy, lo) >= 0);
+
+ /* lo-1 <= higuy <= hi, A[i] >= A[lo] for higuy < i <= hi,
+ either higuy <= lo or A[higuy] < A[lo] */
+
+ if (higuy < loguy)
+ break;
+
+ /* if loguy > hi or higuy <= lo, then we would have exited, so
+ A[loguy] > A[lo], A[higuy] < A[lo],
+ loguy < hi, highy > lo */
+
+ swap(loguy, higuy, width);
+
+ /* A[loguy] < A[lo], A[higuy] > A[lo]; so condition at top
+ of loop is re-established */
+ }
+
+ /* A[i] >= A[lo] for higuy < i <= hi,
+ A[i] <= A[lo] for lo <= i < loguy,
+ higuy < loguy, lo <= higuy <= hi
+ implying:
+ A[i] >= A[lo] for loguy <= i <= hi,
+ A[i] <= A[lo] for lo <= i <= higuy,
+ A[i] = A[lo] for higuy < i < loguy */
+
+ swap(lo, higuy, width); /* put partition element in place */
+
+ /* OK, now we have the following:
+ A[i] >= A[higuy] for loguy <= i <= hi,
+ A[i] <= A[higuy] for lo <= i < higuy
+ A[i] = A[lo] for higuy <= i < loguy */
+
+ /* We've finished the partition, now we want to sort the subarrays
+ [lo, higuy-1] and [loguy, hi].
+ We do the smaller one first to minimize stack usage.
+ We only sort arrays of length 2 or more.*/
+
+ if ( higuy - 1 - lo >= hi - loguy ) {
+ if (lo + width < higuy) {
+ lostk[stkptr] = lo;
+ histk[stkptr] = higuy - width;
+ ++stkptr;
+ } /* save big recursion for later */
+
+ if (loguy < hi) {
+ lo = loguy;
+ goto recurse; /* do small recursion */
+ }
+ }
+ else {
+ if (loguy < hi) {
+ lostk[stkptr] = loguy;
+ histk[stkptr] = hi;
+ ++stkptr; /* save big recursion for later */
+ }
+
+ if (lo + width < higuy) {
+ hi = higuy - width;
+ goto recurse; /* do small recursion */
+ }
+ }
+ }
+
+ /* We have sorted the array, except for any pending sorts on the stack.
+ Check if there are any, and do them. */
+
+ --stkptr;
+ if (stkptr >= 0) {
+ lo = lostk[stkptr];
+ hi = histk[stkptr];
+ goto recurse; /* pop subarray from stack */
+ }
+ else
+ return; /* all subarrays done */
+}
+
+#ifdef _CRUISER_
+#pragma check_stack() /* revert to command line behaviour */
+#endif /* ndef _CRUISER_ */
+
+
+/***
+*shortsort(hi, lo, width, comp) - insertion sort for sorting short arrays
+*
+*Purpose:
+* sorts the sub-array of elements between lo and hi (inclusive)
+* side effects: sorts in place
+* assumes that lo < hi
+*
+*Entry:
+* char *lo = pointer to low element to sort
+* char *hi = pointer to high element to sort
+* unsigned width = width in bytes of each array element
+* int (*comp)() = pointer to function returning analog of strcmp for
+* strings, but supplied by user for comparing the array elements.
+* it accepts 2 pointers to elements and returns neg if 1<2, 0 if
+* 1=2, pos if 1>2.
+*
+*Exit:
+* returns void
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CALLTYPE4 shortsort (
+ char *lo,
+ char *hi,
+ unsigned width,
+ int (_CALLTYPE1 *comp)(const void *, const void *)
+ )
+{
+ char *p, *max;
+
+ /* Note: in assertions below, i and j are alway inside original bound of
+ array to sort. */
+
+ while (hi > lo) {
+ /* A[i] <= A[j] for i <= j, j > hi */
+ max = lo;
+ for (p = lo+width; p <= hi; p += width) {
+ /* A[i] <= A[max] for lo <= i < p */
+ if (comp(p, max) > 0) {
+ max = p;
+ }
+ /* A[i] <= A[max] for lo <= i <= p */
+ }
+
+ /* A[i] <= A[max] for lo <= i <= hi */
+
+ swap(max, hi, width);
+
+ /* A[i] <= A[hi] for i <= hi, so A[i] <= A[j] for i <= j, j >= hi */
+
+ hi -= width;
+
+ /* A[i] <= A[j] for i <= j, j > hi, loop top condition established */
+ }
+ /* A[i] <= A[j] for i <= j, j > lo, which implies A[i] <= A[j] for i < j,
+ so array is sorted */
+}
+
+
+/***
+*swap(a, b, width) - swap two elements
+*
+*Purpose:
+* swaps the two array elements of size width
+*
+*Entry:
+* char *a, *b = pointer to two elements to swap
+* unsigned width = width in bytes of each array element
+*
+*Exit:
+* returns void
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+static void _CALLTYPE4 swap (
+ char *a,
+ char *b,
+ unsigned width
+ )
+{
+ char tmp;
+
+ if ( a != b )
+ /* Do the swap one character at a time to avoid potential alignment
+ problems. */
+ while ( width-- ) {
+ tmp = *a;
+ *a++ = *b;
+ *b++ = tmp;
+ }
+}
diff --git a/private/ole32/common/cruntime/setlocal.h b/private/ole32/common/cruntime/setlocal.h
new file mode 100644
index 000000000..df90551b6
--- /dev/null
+++ b/private/ole32/common/cruntime/setlocal.h
@@ -0,0 +1,44 @@
+/***
+*setlocal.h - internal definitions used by locale-dependent functions.
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains internal definitions/declarations for locale-dependent
+* functions, in particular those required by setlocale().
+* [Internal]
+*
+*Revision History:
+* 10-16-91 ETC 32-bit version created from 16-bit setlocal.c
+* 12-20-91 ETC Removed GetLocaleInfo structure definitions.
+* 08-18-92 KRS Make _CLOCALEHANDLE == LANGNEUTRAL HANDLE = 0.
+* 12-17-92 CFW Added LC_ID, LCSTRINGS, and GetQualifiedLocale
+* 12-17-92 KRS Change value of NLSCMPERROR from 0 to INT_MAX.
+* 01-08-93 CFW Added LC_*_TYPE and _getlocaleinfo (wrapper) prototype.
+* 01-13-93 KRS Change LCSTRINGS back to LC_STRINGS for consistency.
+* Change _getlocaleinfo prototype again.
+* 02-08-93 CFW Added time defintions from locale.h, added 'const' to
+* GetQualifiedLocale prototype, added _lconv_static_*.
+* 02-16-93 CFW Changed time defs to long and short.
+* 03-17-93 CFW Add language and country info definitions.
+* 03-23-93 CFW Add _ to GetQualifiedLocale prototype.
+* 03-24-93 CFW Change to _get_qualified_locale.
+*
+****/
+
+#ifndef _INC_SETLOCAL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define _CLOCALECP CP_ACP /* "C" locale Code page (ANSI 8859) */
+
+extern UINT _lc_codepage; /* code page */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_SETLOCAL
+#endif /* _INC_SETLOCAL */
diff --git a/private/ole32/common/cruntime/strtol.c b/private/ole32/common/cruntime/strtol.c
new file mode 100644
index 000000000..f5410c5d5
--- /dev/null
+++ b/private/ole32/common/cruntime/strtol.c
@@ -0,0 +1,224 @@
+/***
+*strtol.c - Contains C runtimes strtol and strtoul
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* strtol - convert ascii string to long signed integer
+* strtoul - convert ascii string to long unsigned integer
+*
+*Revision History:
+* 06-05-89 PHG Module created, based on strtol.asm
+* 03-06-90 GJF Fixed calling type, added #include <cruntime.h>
+* and fixed the copyright. Also, cleaned up the
+* formatting a bit.
+* 03-07-90 GJF Fixed compiler warnings (added const qualifier to
+* an arg type and local var type).
+* 03-23-90 GJF Made strtoxl() _CALLTYPE4.
+* 08-13-90 SBM Compiles cleanly with -W3
+* 09-27-90 GJF New-style function declarators.
+* 10-24-91 GJF Had to cast LONG_MAX to unsigned long in expr. to
+* mollify MIPS compiler.
+* 10-21-92 GJF Made char-to-int conversions unsigned.
+* 04-21-93 GJF Removed assumption that LONG_MIN == -LONG_MAX.
+* 05-10-93 GJF Fixed error check.
+* 05-20-93 GJF Nothing like taking ugly code and making prettier...
+* and wrong. Fixed bug introduced on 5-10.
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <ctype.h>
+
+
+/***
+*strtol, strtoul(nptr,endptr,ibase) - Convert ascii string to long un/signed
+* int.
+*
+*Purpose:
+* Convert an ascii string to a long 32-bit value. The base
+* used for the caculations is supplied by the caller. The base
+* must be in the range 0, 2-36. If a base of 0 is supplied, the
+* ascii string must be examined to determine the base of the
+* number:
+* (a) First char = '0', second char = 'x' or 'X',
+* use base 16.
+* (b) First char = '0', use base 8
+* (c) First char in range '1' - '9', use base 10.
+*
+* If the 'endptr' value is non-NULL, then strtol/strtoul places
+* a pointer to the terminating character in this value.
+* See ANSI standard for details
+*
+*Entry:
+* nptr == NEAR/FAR pointer to the start of string.
+* endptr == NEAR/FAR pointer to the end of the string.
+* ibase == integer base to use for the calculations.
+*
+* string format: [whitespace] [sign] [0] [x] [digits/letters]
+*
+*Exit:
+* Good return:
+* result
+*
+* Overflow return:
+* strtol -- LONG_MAX or LONG_MIN
+* strtoul -- ULONG_MAX
+*
+* No digits or bad base return:
+* 0
+* endptr = nptr*
+*
+*Exceptions:
+* None.
+*******************************************************************************/
+
+/* flag values */
+#define FL_UNSIGNED 1 /* strtoul called */
+#define FL_NEG 2 /* negative sign found */
+#define FL_OVERFLOW 4 /* overflow occured */
+#define FL_READDIGIT 8 /* we've read at least one correct digit */
+
+
+static unsigned long _CRTAPI3 strtoxl (
+ const char *nptr,
+ const char **endptr,
+ int ibase,
+ int flags
+ )
+{
+ const char *p;
+ char c;
+ unsigned long number;
+ unsigned digval;
+ unsigned long maxval;
+
+ p = nptr; /* p is our scanning pointer */
+ number = 0; /* start with zero */
+
+ c = *p++; /* read char */
+ while ( isspace((int)(unsigned char)c) )
+ c = *p++; /* skip whitespace */
+
+ if (c == '-') {
+ flags |= FL_NEG; /* remember minus sign */
+ c = *p++;
+ }
+ else if (c == '+')
+ c = *p++; /* skip sign */
+
+ if (ibase < 0 || ibase == 1 || ibase > 36) {
+ /* bad base! */
+ if (endptr)
+ /* store beginning of string in endptr */
+ *endptr = nptr;
+ return 0L; /* return 0 */
+ }
+ else if (ibase == 0) {
+ /* determine base free-lance, based on first two chars of
+ string */
+ if (c != '0')
+ ibase = 10;
+ else if (*p == 'x' || *p == 'X')
+ ibase = 16;
+ else
+ ibase = 8;
+ }
+
+ if (ibase == 16) {
+ /* we might have 0x in front of number; remove if there */
+ if (c == '0' && (*p == 'x' || *p == 'X')) {
+ ++p;
+ c = *p++; /* advance past prefix */
+ }
+ }
+
+ /* if our number exceeds this, we will overflow on multiply */
+ maxval = ULONG_MAX / ibase;
+
+
+ for (;;) { /* exit in middle of loop */
+ /* convert c to value */
+ if ( isdigit((int)(unsigned char)c) )
+ digval = c - '0';
+ else if ( isalpha((int)(unsigned char)c) )
+ digval = toupper(c) - 'A' + 10;
+ else
+ break;
+ if (digval >= (unsigned)ibase)
+ break; /* exit loop if bad digit found */
+
+ /* record the fact we have read one digit */
+ flags |= FL_READDIGIT;
+
+ /* we now need to compute number = number * base + digval,
+ but we need to know if overflow occured. This requires
+ a tricky pre-check. */
+
+ if (number < maxval || (number == maxval &&
+ (unsigned long)digval <= ULONG_MAX % ibase)) {
+ /* we won't overflow, go ahead and multiply */
+ number = number * ibase + digval;
+ }
+ else {
+ /* we would have overflowed -- set the overflow flag */
+ flags |= FL_OVERFLOW;
+ }
+
+ c = *p++; /* read next digit */
+ }
+
+ --p; /* point to place that stopped scan */
+
+ if (!(flags & FL_READDIGIT)) {
+ /* no number there; return 0 and point to beginning of
+ string */
+ if (endptr)
+ /* store beginning of string in endptr later on */
+ p = nptr;
+ number = 0L; /* return 0 */
+ }
+ else if ( (flags & FL_OVERFLOW) ||
+ ( !(flags & FL_UNSIGNED) &&
+ ( ( (flags & FL_NEG) && (number > -LONG_MIN) ) ||
+ ( !(flags & FL_NEG) && (number > LONG_MAX) ) ) ) )
+ {
+ /* overflow or signed overflow occurred */
+ if ( flags & FL_UNSIGNED )
+ number = ULONG_MAX;
+ else if ( flags & FL_NEG )
+ number = (unsigned long)(-LONG_MIN);
+ else
+ number = LONG_MAX;
+ }
+
+ if (endptr != NULL)
+ /* store pointer to char that stopped the scan */
+ *endptr = p;
+
+ if (flags & FL_NEG)
+ /* negate result if there was a neg sign */
+ number = (unsigned long)(-(long)number);
+
+ return number; /* done. */
+}
+
+long _CRTAPI1 strtol (
+ const char *nptr,
+ char **endptr,
+ int ibase
+ )
+{
+ return (long) strtoxl(nptr, endptr, ibase, 0);
+}
+
+unsigned long _CRTAPI1 strtoul (
+ const char *nptr,
+ char **endptr,
+ int ibase
+ )
+{
+ return strtoxl(nptr, endptr, ibase, FL_UNSIGNED);
+}
diff --git a/private/ole32/common/cruntime/tidtable.c b/private/ole32/common/cruntime/tidtable.c
new file mode 100644
index 000000000..880df0ea8
--- /dev/null
+++ b/private/ole32/common/cruntime/tidtable.c
@@ -0,0 +1,126 @@
+
+/***
+*tidtable.c - Access thread data table
+*
+* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This module contains the following routines for multi-thread
+* data support:
+*
+* _mtinit = Initialize the mthread data
+* _getptd = get the pointer to the per-thread data structure for
+* the current thread
+* _freeptd = free up a per-thread data structure and its
+* subordinate structures
+* __threadid = return thread ID for the current thread
+* __threadhandle = return pseudo-handle for the current thread
+*
+*Revision History:
+* 05-04-90 JCR Translated from ASM to C for portable 32-bit OS/2
+* 06-04-90 GJF Changed error message interface.
+* 07-02-90 GJF Changed __threadid() for DCR 1024/2012.
+* 08-08-90 GJF Removed 32 from API names.
+* 10-08-90 GJF New-style function declarators.
+* 10-09-90 GJF Thread ids are of type unsigned long! Also, fixed a
+* bug in __threadid().
+* 10-22-90 GJF Another bug in __threadid().
+* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h>
+* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals.
+* 05-31-91 GJF Win32 version [_WIN32_].
+* 07-18-91 GJF Fixed many silly errors [_WIN32_].
+* 09-29-91 GJF Conditionally added _getptd_lk/_getptd1_lk so that
+* DEBUG version of mlock doesn't infinitely recurse
+* the first time _THREADDATA_LOCK is asserted [_WIN32_].
+* 01-30-92 GJF Must init. _pxcptacttab field to _XcptActTab.
+* 02-25-92 GJF Initialize _holdrand field to 1.
+* 02-13-93 GJF Revised to use TLS API. Also, purged Cruiser support.
+* 03-26-93 GJF Initialize ptd->_holdrand to 1L (see thread.c).
+* 04-16-93 SKS Add _mtterm to do multi-thread termination
+* Set freed __tlsindex to -1 again to prevent mis-use
+* 12-13-93 SKS Add _freeptd(), which frees up the per-thread data
+* maintained by the C run-time library.
+*
+*******************************************************************************/
+
+#include <windows.h>
+#include <cruntime.h>
+#include <internal.h>
+
+/****
+*_mtinit() - Init multi-thread data bases
+*
+*Purpose:
+* (1) Call _mtinitlocks to create/open all lock semaphores.
+* (2) Allocate a TLS index to hold pointers to per-thread data
+* structure.
+*
+* NOTES:
+* (1) Only to be called ONCE at startup
+* (2) Must be called BEFORE any mthread requests are made
+*
+*Entry:
+* <NONE>
+*Exit:
+* returns TRUE on success
+* returns FALSE on failure
+* user code should call _amsg_exit if failure is returned
+*
+*Uses:
+* <any registers may be modified at init time>
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 _mtinit (
+ void
+ )
+{
+
+
+ /*
+ * Initialize the mthread lock data base
+ */
+
+ _mtinitlocks();
+
+ return TRUE;
+}
+
+
+/****
+*_mtterm() - Clean-up multi-thread data bases
+*
+*Purpose:
+* (1) Call _mtdeletelocks to free up all lock semaphores.
+* (2) Free up the TLS index used to hold pointers to
+* per-thread data structure.
+*
+* NOTES:
+* (1) Only to be called ONCE at termination
+* (2) Must be called AFTER all mthread requests are made
+*
+*Entry:
+* <NONE>
+*Exit:
+* returns
+*
+*Uses:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void _CRTAPI1 _mtterm (
+ void
+ )
+{
+ /*
+ * Clean up the mthread lock data base
+ */
+
+ _mtdeletelocks();
+
+}
+
diff --git a/private/ole32/common/cruntime/xtow.c b/private/ole32/common/cruntime/xtow.c
new file mode 100644
index 000000000..e4d5f0d61
--- /dev/null
+++ b/private/ole32/common/cruntime/xtow.c
@@ -0,0 +1,55 @@
+/***
+*xtow.c - convert integers/longs to wide char string
+*
+* Copyright (c) 1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* The module has code to convert integers/longs to wide char strings.
+*
+*Revision History:
+* 09-10-93 CFW Module created, based on ASCII version.
+*
+*******************************************************************************/
+
+#include <windows.h>
+#include <stdlib.h>
+
+#define INT_SIZE_LENGTH 20
+#define LONG_SIZE_LENGTH 40
+
+/***
+*wchar_t *_itow, *_ltow, *_ultow(val, buf, radix) - convert binary int to wide
+* char string
+*
+*Purpose:
+* Converts an int to a wide character string.
+*
+*Entry:
+* val - number to be converted (int, long or unsigned long)
+* int radix - base to convert into
+* wchar_t *buf - ptr to buffer to place result
+*
+*Exit:
+* calls ASCII version to convert, converts ASCII to wide char into buf
+* returns a pointer to this buffer
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CRTAPI1 _ultow (
+ unsigned long val,
+ wchar_t *buf,
+ int radix
+ )
+{
+ char astring[LONG_SIZE_LENGTH];
+
+ _ultoa (val, astring, radix);
+ MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, astring, -1,
+ buf, LONG_SIZE_LENGTH);
+
+ return (buf);
+}
+
+
diff --git a/private/ole32/common/daytona/makefile b/private/ole32/common/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/common/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/common/daytona/sources b/private/ole32/common/daytona/sources
new file mode 100644
index 000000000..c8b07c81f
--- /dev/null
+++ b/private/ole32/common/daytona/sources
@@ -0,0 +1,79 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = common
+
+!include ..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= common
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..\..\ih;..;..\..\com\inc;$(BASEDIR)\private\dcomidl\obj
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ /D_TRACKLINK_=1
+
+SOURCES= \
+ ..\assert.cxx \
+ ..\ccompapi.cxx \
+ ..\dprintf.c \
+ ..\eqguid.cxx \
+ ..\olesem.cxx \
+ ..\output.c \
+ ..\printf.c \
+ ..\sprintf.c \
+ ..\buffer.cxx \
+ ..\oleprint.cxx \
+ ..\oletype.cxx \
+ ..\dynload.cxx \
+ ..\outfuncs.c \
+ ..\trace.cxx \
+ ..\olescm.cxx \
+ ..\comsrgt.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
diff --git a/private/ole32/common/dirs b/private/ole32/common/dirs
new file mode 100644
index 000000000..b38618402
--- /dev/null
+++ b/private/ole32/common/dirs
@@ -0,0 +1,39 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS= \
+ cruntime
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/common/dprintf.c b/private/ole32/common/dprintf.c
new file mode 100644
index 000000000..71acbcaeb
--- /dev/null
+++ b/private/ole32/common/dprintf.c
@@ -0,0 +1,15 @@
+/***
+*dprintf.c - print formatted to debug port
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4dprintf() - print formatted data to debug port
+* defines w4vdprintf() - print formatted output to debug port, get data
+* from an argument ptr instead of explicit args.
+*******************************************************************************/
+
+#include "dprintf.h" // function prototypes
+
+#define _W4DPRINTF_
+#include "printf.h"
diff --git a/private/ole32/common/dprintf.h b/private/ole32/common/dprintf.h
new file mode 100644
index 000000000..f4af83504
--- /dev/null
+++ b/private/ole32/common/dprintf.h
@@ -0,0 +1,33 @@
+//+---------------------------------------------------------------------------
+// Copyright (C) 1991, Microsoft Corporation.
+//
+// File: dprintf.h
+//
+// Contents: Debugging output routine function prototypes
+//
+// Functions: w4printf
+// w4vprintf
+// w4dprintf
+// w4vdprintf
+//
+// History: 18-Oct-91 vich Created
+//
+//----------------------------------------------------------------------------
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef WIN32
+int _cdecl w4printf(const char *format, ...);
+int _cdecl w4vprintf(const char *format, va_list arglist);
+#endif
+
+int _cdecl w4dprintf(const char *format, ...);
+int _cdecl w4vdprintf(const char *format, va_list arglist);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/private/ole32/common/dynload.cxx b/private/ole32/common/dynload.cxx
new file mode 100644
index 000000000..246112262
--- /dev/null
+++ b/private/ole32/common/dynload.cxx
@@ -0,0 +1,656 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dynload.cxx
+//
+// Contents: APIs from dynamically loaded system dlls. These APIs
+// are rarely used and there are only 1 or 2 per system
+// Dll so we dynamically load the Dll so that we improve
+// the load time of OLE32.DLL
+//
+// Functions: OleWNetGetConnection
+// OleWNetGetUniversalName
+// OleExtractIcon
+// OleGetShellLink
+// OleSymInitialize
+// OleSymCleanup
+// OleSymGetSymFromAddr
+// OleSymUnDName
+//
+// History: 10-Jan-95 Rickhi Created
+// 10-Mar-95 BillMo Added OleGetShellLink-creates a shortcut object.
+// 12-Jul-95 t-stevan Added OleSym* routines
+// 22-Nov-95 MikeHill Use Unicode IShellLink object in NT.
+//
+//--------------------------------------------------------------------------
+#include <windows.h>
+#include <shellapi.h>
+#include <imagehlp.h>
+#include <ole2sp.h>
+#include <ole2com.h>
+
+#ifdef _CAIRO_
+#include <shlguid.h>
+#endif
+
+// Entry Points from MPR.DLL
+HINSTANCE hInstMPR = NULL;
+
+typedef DWORD (* PFN_WNETGETCONNECTION)(LPCTSTR lpLocalName, LPTSTR lpRemoteName, LPDWORD lpnLength);
+PFN_WNETGETCONNECTION pfnWNetGetConnection = NULL;
+
+#ifdef _CHICAGO_
+#define WNETGETCONNECTION_NAME "WNetGetConnectionA"
+#else
+#define WNETGETCONNECTION_NAME "WNetGetConnectionW"
+#define WNETGETUNIVERSALNAME_NAME "WNetGetUniversalNameW"
+typedef DWORD (* PFN_WNETGETUNIVERSALNAME)(LPCWSTR szLocalPath, DWORD dwInfoLevel, LPVOID lpBuffer, LPDWORD lpBufferSize);
+PFN_WNETGETUNIVERSALNAME pfnWNetGetUniversalName = NULL;
+#endif
+
+
+// Entry Points from GDI32p.DLL
+#ifndef _CHICAGO_
+HINSTANCE hInstGDI32p = NULL;
+
+typedef HBRUSH (* PFN_GDICONVERTBRUSH)(HBRUSH hbrush);
+typedef HBRUSH (* PFN_GDICREATELOCALBRUSH)(HBRUSH hbrushRemote);
+PFN_GDICONVERTBRUSH pfnGdiConvertBrush = NULL;
+PFN_GDICREATELOCALBRUSH pfnGdiCreateLocalBrush = NULL;
+
+#define GDICONVERTBRUSH_NAME "GdiConvertBrush"
+#define GDICREATELOCALBRUSH_NAME "GdiCreateLocalBrush"
+#endif
+
+#ifdef _TRACKLINK_
+
+#ifndef _CAIRO_ // !_CAIRO_
+// BUGBUG: BillMo. Get Chicago guids to work until later.
+#undef DEFINE_GUID
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID CDECL name \
+ = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
+#define DEFINE_SHLGUID(name, l, w1, w2) DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)
+DEFINE_SHLGUID(CLSID_ShellLink, 0x00021401L, 0, 0);
+#ifdef _CHICAGO_
+DEFINE_SHLGUID(IID_IShellLink, 0x000214EEL, 0, 0);
+#else
+DEFINE_SHLGUID(IID_IShellLink, 0x000214F9L, 0, 0);
+#endif // _CHICAGO_
+#undef DEFINE_GUID
+#endif // !_CAIRO_
+
+IClassFactory *g_pcfShellLink = NULL;
+#endif // _TRACKLINK_
+
+#ifdef _CAIRO_
+HINSTANCE hDsys = NULL;
+#endif
+
+// Entry Points from SHELL32.DLL
+HINSTANCE hInstSHELL32 = NULL;
+
+typedef HICON (* PFN_EXTRACTICON)(HINSTANCE hInst, LPCTSTR szExeName, UINT nIconIndex);
+PFN_EXTRACTICON pfnExtractIcon = NULL;
+#ifdef _CHICAGO_
+#define EXTRACTICON_NAME "ExtractIconA"
+#else
+#define EXTRACTICON_NAME "ExtractIconW"
+#endif
+
+typedef HICON (* PFN_EXTRACTASSOCIATEDICON)(HINSTANCE hInst, LPCTSTR szExeName,
+ LPWORD pIndex);
+PFN_EXTRACTASSOCIATEDICON pfnExtractAssociatedIcon = NULL;
+
+#ifdef _CHICAGO_
+#define EXTRACTASSOCIATEDICON_NAME "ExtractAssociatedIconA"
+#else
+#define EXTRACTASSOCIATEDICON_NAME "ExtractAssociatedIconW"
+#endif
+
+typedef DWORD (* PFN_SHGETFILEINFO)(LPCTSTR pszPath, DWORD dwFileAttributes,
+ SHFILEINFO FAR *psfi, UINT cbFileInfo, UINT uFlags);
+PFN_SHGETFILEINFO pfnSHGetFileInfo = NULL;
+
+#ifdef _CHICAGO_
+#define SHGETFILEINFO_NAME "SHGetFileInfoA"
+#else
+#define SHGETFILEINFO_NAME "SHGetFileInfoW"
+#endif
+
+// Entry Points from IMAGEHLP.DLL
+HINSTANCE hInstIMAGEHLP = NULL;
+
+typedef BOOL (*PFN_SYMINITIALIZE)(HANDLE hProcess, LPSTR UserSearchPath,
+ BOOL fInvadeProcess);
+PFN_SYMINITIALIZE pfnSymInitialize = NULL;
+
+#define SYMINITIALIZE_NAME "SymInitialize"
+
+typedef BOOL (*PFN_SYMCLEANUP)(HANDLE hProcess);
+PFN_SYMCLEANUP pfnSymCleanup = NULL;
+
+#define SYMCLEANUP_NAME "SymCleanup"
+
+typedef BOOL (*PFN_SYMGETSYMFROMADDR)(HANDLE hProcess,
+ DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_SYMBOL pSym);
+PFN_SYMGETSYMFROMADDR pfnSymGetSymFromAddr = NULL;
+
+#define SYMGETSYMFROMADDR_NAME "SymGetSymFromAddr"
+
+typedef BOOL (*PFN_SYMUNDNAME)(PIMAGEHLP_SYMBOL sym, LPSTR lpname, DWORD dwmaxLength);
+PFN_SYMUNDNAME pfnSymUnDName = NULL;
+
+#define SYMUNDNAME_NAME "SymUnDName"
+
+//+---------------------------------------------------------------------------
+//
+// Function: LoadSystemProc
+//
+// Synopsis: Loads the specified DLL if necessary and finds the specified
+// entry point.
+//
+// Returns: TRUE: the entry point function ptr is valid
+// FALSE: the entry point function ptr is not valid
+//
+// History: 10-Jan-95 Rickhi Created
+//
+//----------------------------------------------------------------------------
+BOOL LoadSystemProc(LPSTR szDll, LPCSTR szProc,
+ HINSTANCE *phInst, FARPROC *ppfnProc)
+{
+ if (*phInst == NULL)
+ {
+ //
+ // BUGBUG: BillMo, would it be a good idea to form an absolute path
+ // to the dll based on GetSystemDirectory and use
+ // LOAD_WITH_ALTERED_SEARCH_PATH in LoadLibraryEx ?
+ //
+
+ // Dll not loaded yet, load it now.
+ if ((*phInst = LoadLibraryA(szDll)) == NULL)
+ return GetLastError();
+ }
+
+ // load the entry point
+ if ((*ppfnProc = GetProcAddress(*phInst, szProc)) == NULL)
+ return GetLastError();
+
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: FreeSystemDLLs
+//
+// Synopsis: Frees any system Dlls that we dynamically loaded.
+//
+// History: 10-Jan-95 Rickhi Created
+//
+//----------------------------------------------------------------------------
+void FreeSystemDLLs()
+{
+ if (hInstMPR)
+ FreeLibrary(hInstMPR);
+
+ if (hInstSHELL32)
+ FreeLibrary(hInstSHELL32);
+
+#ifndef _CHICAGO_
+ if (hInstGDI32p)
+ FreeLibrary(hInstGDI32p);
+#endif // _CHICAGO_
+
+#ifdef _CAIRO_
+ if (hDsys)
+ FreeLibrary(hDsys);
+#endif // _CAIRO_
+
+ if(hInstIMAGEHLP != NULL && hInstIMAGEHLP != INVALID_HANDLE_VALUE)
+ {
+ FreeLibrary(hInstIMAGEHLP);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleWNetGetConnection
+//
+// Synopsis: OLE internal implementation of WNetGetConnection
+//
+// History: 10-Jan-95 Rickhi Created
+//
+//----------------------------------------------------------------------------
+DWORD OleWNetGetConnection(LPCWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD lpnLength)
+{
+ if (pfnWNetGetConnection == NULL)
+ {
+ DWORD rc = LoadSystemProc("MPR.DLL", WNETGETCONNECTION_NAME,
+ &hInstMPR, (FARPROC *)&pfnWNetGetConnection);
+ if (rc != 0)
+ return rc;
+ }
+
+#ifdef _CHICAGO_
+ // For Chicago we need to do the Unicode to Ansi conversions.
+
+ CHAR szRemote[MAX_PATH];
+ CHAR szLocal[MAX_PATH];
+
+ WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, lpLocalName, -1, szLocal, MAX_PATH, NULL, NULL);
+
+ DWORD rc = (pfnWNetGetConnection)(szLocal, szRemote, lpnLength);
+
+ if (rc == NO_ERROR)
+ {
+ MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, szRemote, -1, lpRemoteName, lstrlenA(szRemote)+1);
+ }
+
+ return rc;
+#else
+
+ return (pfnWNetGetConnection)(lpLocalName, lpRemoteName, lpnLength);
+
+#endif
+}
+
+#ifndef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Function: OleWNetGetUniversalName
+//
+// Synopsis: OLE internal implementation of WNetGetUniversalName
+//
+// History: 10-Jan-95 Rickhi Created
+//
+//----------------------------------------------------------------------------
+DWORD OleWNetGetUniversalName(LPCWSTR szLocalPath, DWORD dwInfoLevel,
+ LPVOID lpBuffer, LPDWORD lpBufferSize)
+{
+ if (pfnWNetGetUniversalName == NULL)
+ {
+ DWORD rc = LoadSystemProc("MPR.DLL", WNETGETUNIVERSALNAME_NAME,
+ &hInstMPR, (FARPROC *)&pfnWNetGetUniversalName);
+ if (rc != 0)
+ return rc;
+ }
+
+ return (pfnWNetGetUniversalName)(szLocalPath, dwInfoLevel, lpBuffer, lpBufferSize);
+}
+#endif
+
+
+#ifndef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Function: OleGdiConvertBrush
+//
+// Synopsis: OLE internal implementation of GdiConvertBrush
+//
+// History: 7-Feb-95 GregJen Created
+//
+//----------------------------------------------------------------------------
+HBRUSH OleGdiConvertBrush(HBRUSH hbrush)
+{
+ if (pfnGdiConvertBrush == NULL)
+ {
+ DWORD rc = LoadSystemProc("GDI32P.DLL", GDICONVERTBRUSH_NAME,
+ &hInstGDI32p, (FARPROC *)&pfnGdiConvertBrush);
+ if (rc != 0)
+ return NULL;
+ }
+
+ return (pfnGdiConvertBrush)(hbrush);
+}
+#endif
+
+
+#ifndef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Function: OleGdiCreateLocalBrush
+//
+// Synopsis: OLE internal implementation of GdiConvertBrush
+//
+// History: 7-Feb-95 GregJen Created
+//
+//----------------------------------------------------------------------------
+HBRUSH OleGdiCreateLocalBrush(HBRUSH hbrushRemote)
+{
+ if (pfnGdiCreateLocalBrush == NULL)
+ {
+ DWORD rc = LoadSystemProc("GDI32P.DLL", GDICREATELOCALBRUSH_NAME,
+ &hInstGDI32p, (FARPROC *)&pfnGdiCreateLocalBrush);
+ if (rc != 0)
+ return NULL;
+ }
+
+ return (pfnGdiCreateLocalBrush)(hbrushRemote);
+}
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleExtractIcon
+//
+// Synopsis: OLE internal implementation of ExtractIcon
+//
+// History: 10-Jan-95 Rickhi Created
+//
+//----------------------------------------------------------------------------
+HICON OleExtractIcon(HINSTANCE hInst, LPCWSTR wszExeName, UINT nIconIndex)
+{
+ if (pfnExtractIcon == NULL)
+ {
+ DWORD rc = LoadSystemProc("SHELL32.DLL", EXTRACTICON_NAME,
+ &hInstSHELL32, (FARPROC *)&pfnExtractIcon);
+ if (rc != 0)
+ return NULL;
+ }
+
+#ifdef _CHICAGO_
+ // For Chicago, we need to do the Unicode to Ansi conversion
+
+ CHAR szExeName[MAX_PATH];
+ WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, wszExeName, -1, szExeName, MAX_PATH, NULL, NULL);
+
+ return (pfnExtractIcon)(hInst, szExeName, nIconIndex);
+#else
+ return (pfnExtractIcon)(hInst, wszExeName, nIconIndex);
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleExtractAssociatedIcon
+//
+// Synopsis: OLE internal implementation of ExtractIcon
+//
+// History: 225-Jan-95 Alexgo Created
+//
+//----------------------------------------------------------------------------
+HICON OleExtractAssociatedIcon(HINSTANCE hInst, LPCWSTR pszFileName,
+ LPWORD pIndex)
+{
+ if (pfnExtractAssociatedIcon == NULL)
+ {
+ DWORD rc = LoadSystemProc("SHELL32.DLL", EXTRACTASSOCIATEDICON_NAME,
+ &hInstSHELL32,
+ (FARPROC *)&pfnExtractAssociatedIcon);
+ if (rc != 0)
+ return NULL;
+ }
+
+#ifdef _CHICAGO_
+ // For Chicago, we need to do the Unicode to Ansi conversion
+
+ CHAR szFileName[MAX_PATH];
+ WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, pszFileName, -1, szFileName, MAX_PATH, NULL, NULL);
+
+ return (pfnExtractAssociatedIcon)(hInst, szFileName, pIndex);
+#else
+ return (pfnExtractAssociatedIcon)(hInst, pszFileName, pIndex);
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleSHGetFileInfo
+//
+// Synopsis: OLE internal implementation of ExtractIcon
+//
+// History: 02-Feb-95 Scottsk Created
+//
+//----------------------------------------------------------------------------
+DWORD OleSHGetFileInfo(LPCWSTR pszPath, DWORD dwFileAttributes,
+ SHFILEINFO FAR *psfi, UINT cbFileInfo, UINT uFlags)
+{
+ if (pfnSHGetFileInfo == NULL)
+ {
+ DWORD rc = LoadSystemProc("SHELL32.DLL", SHGETFILEINFO_NAME,
+ &hInstSHELL32,
+ (FARPROC *)&pfnSHGetFileInfo);
+ if (rc != 0)
+ return NULL;
+ }
+
+// this nested #ifdef is here so that when this functinality is available
+// on NT, simply removing the outer #ifdef will do the right thing.
+#ifdef _CHICAGO_
+ // For Chicago, we need to do the Unicode to Ansi conversion
+
+ CHAR szPath[MAX_PATH];
+
+ WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, pszPath, -1, szPath, MAX_PATH, NULL, NULL);
+
+ return (pfnSHGetFileInfo)(szPath, dwFileAttributes, psfi, cbFileInfo, uFlags);
+#else
+ return (pfnSHGetFileInfo)(pszPath, dwFileAttributes, psfi, cbFileInfo, uFlags);
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleGetShellLink
+//
+// Synopsis: Get an instance of the shell's shell link object.
+//
+//----------------------------------------------------------------------------
+
+#ifdef _TRACKLINK_
+VOID * OleGetShellLink()
+{
+ HRESULT hr;
+ VOID *pShellLink;
+
+ if (g_pcfShellLink == NULL)
+ {
+ LPFNGETCLASSOBJECT pfn;
+ DWORD rc = LoadSystemProc("SHELL32.DLL", "DllGetClassObject",
+ &hInstSHELL32,
+ (FARPROC *)&pfn);
+ if (rc != 0)
+ return NULL;
+
+ hr = (*pfn)(CLSID_ShellLink, IID_IClassFactory, (void**)&g_pcfShellLink);
+
+ if (hr != S_OK)
+ {
+ // BUGBUG: BillMo, cleanup hInstSHELL32.
+ // Its not cleaned up anywhere else in
+ // this file, so I'll leave this to you, Kevin.
+
+ return(NULL);
+ }
+ }
+
+ Win4Assert(g_pcfShellLink != NULL);
+
+ hr = g_pcfShellLink->CreateInstance(NULL, IID_IShellLink, &pShellLink);
+
+ return(hr == S_OK ? pShellLink : NULL);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleSymInitialize
+//
+// Synopsis: OLE internal implementation of SymInitialize
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+BOOL OleSymInitialize(HANDLE hProcess, LPSTR UserSearchPath,
+ BOOL fInvadeProcess)
+{
+ if(hInstIMAGEHLP == (HINSTANCE) -1)
+ {
+ // we already tried loading the DLL, give up
+ return FALSE;
+ }
+
+ if (pfnSymInitialize == NULL)
+ {
+ DWORD rc;
+
+ rc = LoadSystemProc("IMAGEHLP.DLL", SYMINITIALIZE_NAME,
+ &hInstIMAGEHLP, (FARPROC *)&pfnSymInitialize);
+ if (rc != 0)
+ {
+ hInstIMAGEHLP = (HINSTANCE) -1;
+ return FALSE;
+ }
+ }
+
+ return (pfnSymInitialize)(hProcess, UserSearchPath, fInvadeProcess);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleSymCleanup
+//
+// Synopsis: OLE internal implementation of SymCleanup
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+BOOL OleSymCleanup(HANDLE hProcess)
+{
+ if(hInstIMAGEHLP == (HINSTANCE) -1)
+ {
+ // we already tried loading the DLL, give up
+ return FALSE;
+ }
+
+ if (pfnSymCleanup == NULL)
+ {
+ DWORD rc;
+
+ rc = LoadSystemProc("IMAGEHLP.DLL", SYMCLEANUP_NAME,
+ &hInstIMAGEHLP, (FARPROC *)&pfnSymCleanup);
+ if (rc != 0)
+ {
+ hInstIMAGEHLP = (HINSTANCE) -1;
+ return FALSE;
+ }
+ }
+
+ return (pfnSymCleanup)(hProcess);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleSymGetSymFromAddr
+//
+// Synopsis: OLE internal implementation of SymGetSymFromAddr
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+BOOL OleSymGetSymFromAddr(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_SYMBOL pSym)
+{
+ if(hInstIMAGEHLP == (HINSTANCE) -1)
+ {
+ // we already tried loading the DLL, give up
+ return NULL;
+ }
+
+ if (pfnSymGetSymFromAddr == NULL)
+ {
+ DWORD rc;
+
+ rc = LoadSystemProc("IMAGEHLP.DLL", SYMGETSYMFROMADDR_NAME,
+ &hInstIMAGEHLP, (FARPROC *)&pfnSymGetSymFromAddr);
+ if (rc != 0)
+ {
+ hInstIMAGEHLP = (HINSTANCE) -1;
+ return NULL;
+ }
+ }
+
+ return (pfnSymGetSymFromAddr)(hProcess, dwAddr, pdwDisplacement, pSym);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleSymUnDName
+//
+// Synopsis: OLE internal implementation of SymUnDName
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+BOOL OleSymUnDName(PIMAGEHLP_SYMBOL pSym, LPSTR lpname, DWORD dwmaxLength)
+{
+ if(hInstIMAGEHLP == (HINSTANCE) -1)
+ {
+ // we already tried loading the DLL, give up
+ return FALSE;
+ }
+
+ if (pfnSymUnDName== NULL)
+ {
+ DWORD rc;
+
+ rc = LoadSystemProc("IMAGEHLP.DLL", SYMUNDNAME_NAME,
+ &hInstIMAGEHLP, (FARPROC *)&pfnSymUnDName);
+ if (rc != 0)
+ {
+ hInstIMAGEHLP = (HINSTANCE) -1;
+ return FALSE;
+ }
+ }
+
+ return (pfnSymUnDName)(pSym, lpname, dwmaxLength);
+}
+
+#ifdef _CAIRO_
+//+---------------------------------------------------------------------------
+//
+// Function: GetHandleServerInfo, public
+//
+// Synopsis: Wrapper for DfsGetHandleServerInfo
+//
+// Arguments: same as DfsGetHandleServerInfo
+//
+// Returns: Appropriate status code
+//
+// History: 06-Nov-95 Henrylee created
+//
+//----------------------------------------------------------------------------
+
+STDAPI GetHandleServerInfo(
+ IN HANDLE hFile,
+ IN OUT LPWSTR lpServerName,
+ IN OUT LPDWORD lpcbServerName,
+ IN OUT LPWSTR lpReplSpecificPath,
+ IN OUT LPDWORD lpcbReplSpecificPath)
+{
+ static (*pDfsGetHandleServerInfo) (HANDLE,
+ LPWSTR, LPDWORD, LPWSTR, LPDWORD) = NULL;
+
+ // BUGBUG lock
+ if (hDsys == NULL || pDfsGetHandleServerInfo == NULL)
+ {
+ DWORD dw = LoadSystemProc ("DSYS.DLL", "DfsGetHandleServerInfo",
+ &hDsys, (FARPROC *) &pDfsGetHandleServerInfo);
+
+ if (dw != ERROR_SUCCESS)
+ {
+ // BUGBUG unlock
+ return HRESULT_FROM_WIN32 (dw);
+ }
+ }
+ // BUGBUG unlock
+
+ return (*pDfsGetHandleServerInfo) (hFile,
+ lpServerName,
+ lpcbServerName,
+ lpReplSpecificPath,
+ lpcbReplSpecificPath);
+}
+#endif // _CAIRO_
diff --git a/private/ole32/common/eqguid.cxx b/private/ole32/common/eqguid.cxx
new file mode 100644
index 000000000..41223a16a
--- /dev/null
+++ b/private/ole32/common/eqguid.cxx
@@ -0,0 +1,54 @@
+
+#include <windows.h>
+#include <ole2.h>
+#include <stdlib.h>
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsEqualGUID (public)
+//
+// Synopsis: compares two guids for equality
+//
+// Arguments: [guid1] - the first guid
+// [guid2] - the second guid to compare the first one with
+//
+// Returns: TRUE if equal, FALSE if not.
+//
+// Note:
+// Only reason we have this function is because we exported it originally
+// from OLE32.DLL and forgot to take it out when we made it an inline
+// function in objbase.h. Somebody out there may be relying on it being
+// available. Internally we must use wIsEqualGUID.
+//
+//--------------------------------------------------------------------------
+#undef IsEqualGUID // undo the #define in objbase.h
+extern "C" BOOL __stdcall IsEqualGUID(GUID &guid1, GUID &guid2)
+{
+ return (
+ ((PLONG) &guid1)[0] == ((PLONG) &guid2)[0] &&
+ ((PLONG) &guid1)[1] == ((PLONG) &guid2)[1] &&
+ ((PLONG) &guid1)[2] == ((PLONG) &guid2)[2] &&
+ ((PLONG) &guid1)[3] == ((PLONG) &guid2)[3]);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wIsEqualGUID (internal)
+//
+// Synopsis: compares two guids for equality
+//
+// Arguments: [guid1] - the first guid
+// [guid2] - the second guid to compare the first one with
+//
+// Returns: TRUE if equal, FALSE if not.
+//
+//--------------------------------------------------------------------------
+
+BOOL __fastcall wIsEqualGUID(REFGUID guid1, REFGUID guid2)
+{
+ return (
+ ((PLONG) &guid1)[0] == ((PLONG) &guid2)[0] &&
+ ((PLONG) &guid1)[1] == ((PLONG) &guid2)[1] &&
+ ((PLONG) &guid1)[2] == ((PLONG) &guid2)[2] &&
+ ((PLONG) &guid1)[3] == ((PLONG) &guid2)[3]);
+}
diff --git a/private/ole32/common/oleprint.cxx b/private/ole32/common/oleprint.cxx
new file mode 100644
index 000000000..265457cca
--- /dev/null
+++ b/private/ole32/common/oleprint.cxx
@@ -0,0 +1,650 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: oleprint.cxx
+//
+// Contents: printf for API/Method trace
+//
+// Functions: oleprintf
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+#include <windows.h>
+#include <stdarg.h>
+#include <ole2sp.h>
+#include <ole2com.h>
+#if DBG==1
+#include "outfuncs.h"
+#include "oleprint.hxx"
+
+// *** Constants ***
+const char *pscTabString = " "; // 3 space tabs
+
+// *** Types and Enums ***
+// Enumeration of basic types
+enum
+{
+ TYP_INT = 0,
+ TYP_UNSIGNED,
+ TYP_HEX,
+ TYP_HEXCAPS,
+ TYP_LARGE,
+ TYP_BOOL,
+ TYP_BOOLCAPS,
+ TYP_POINTER,
+ TYP_POINTERCAPS,
+ TYP_HANDLE,
+ TYP_HANDLECAPS,
+ TYP_STR,
+ TYP_WIDESTR,
+ TYP_GUID,
+ TYP_STRUCT,
+ NO_TYPE
+};
+
+// Type of parameter printing functions
+typedef void (*ParamFunc) (CTextBufferA &buf, va_list &param, char *&ppstr);
+
+// Enumeration of Structure types
+enum
+{
+ STRUCT_BIND_OPTS=0,
+ STRUCT_DVTARGETDEVICE,
+ STRUCT_FORMATETC,
+ STRUCT_FILETIME,
+ STRUCT_INTERFACEINFO,
+ STRUCT_LOGPALETTE,
+ STRUCT_MSG,
+ STRUCT_OLEINPLACEFRAMEINFO,
+ STRUCT_OLEMENUGROUPWIDTHS,
+ STRUCT_POINT,
+ STRUCT_RECT,
+ STRUCT_STGMEDIUM,
+ STRUCT_STATSTG,
+ STRUCT_SIZE,
+ NO_STRUCT
+};
+
+// Type of structure printing functions
+typedef void (*WriteFunc) (CTextBufferA &buf, void *pParam);
+
+// *** Prototypes ***
+// Functions to handle writing out parameters
+static void WriteInt(CTextBufferA &buf, va_list &, char *&);
+static void WriteUnsigned(CTextBufferA &buf, va_list &, char *&);
+static void WriteHex(CTextBufferA &buf, va_list &, char *&);
+static void WriteHexCaps(CTextBufferA &buf, va_list &, char *&);
+static void WriteLarge(CTextBufferA &buf, va_list &, char *&);
+static void WriteBool(CTextBufferA &buf, va_list &, char *&);
+static void WriteBoolCaps(CTextBufferA &buf, va_list &, char *&);
+static void WritePointer(CTextBufferA &buf, va_list &, char *&);
+static void WritePointerCaps(CTextBufferA &buf, va_list &, char *&);
+static void WriteString(CTextBufferA &buf, va_list &, char *&);
+static void WriteWideString(CTextBufferA &buf, va_list &, char *&);
+static void WriteGUID(CTextBufferA &buf, va_list &, char *&);
+static void WriteStruct(CTextBufferA &buf, va_list &, char *&);
+
+// *** Global Data ***
+char gPidString[20];
+
+// this table holds the functions for writing base types
+static ParamFunc g_pFuncs[] = {WriteInt, WriteUnsigned, WriteHex,
+ WriteHexCaps, WriteLarge, WriteBool,
+ WriteBoolCaps,WritePointer,WritePointerCaps,
+ WriteHex,WriteHexCaps,WriteString,
+ WriteWideString, WriteGUID, WriteStruct,
+ NULL};
+
+// this table starts at 'A' == 65
+// This is the base type lookup table -> tells what kind of base type to print out
+static const BYTE g_tcLookup[] = {NO_TYPE, TYP_BOOLCAPS, NO_TYPE, TYP_INT, NO_TYPE, // 'A' - 'E'
+ NO_TYPE, NO_TYPE, NO_TYPE, TYP_GUID, NO_TYPE, // 'F' - 'J'
+ NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, // 'K' - 'O'
+ TYP_POINTERCAPS, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, // 'P' - 'T'
+ TYP_UNSIGNED, NO_TYPE, NO_TYPE, TYP_HEXCAPS, NO_TYPE, // 'U' - 'Y'
+ NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, // 'Z' - '^'
+ NO_TYPE, NO_TYPE, NO_TYPE, TYP_BOOL, NO_TYPE, // '_' - 'c'
+ TYP_INT, NO_TYPE, NO_TYPE, NO_TYPE, TYP_HANDLE, // 'd' - 'h'
+ NO_TYPE, NO_TYPE, NO_TYPE, TYP_LARGE, NO_TYPE, // 'i' - 'm'
+ NO_TYPE, NO_TYPE, TYP_POINTER, NO_TYPE, NO_TYPE, // 'n' - 'r'
+ TYP_STR, TYP_STRUCT, TYP_UNSIGNED, NO_TYPE, TYP_WIDESTR, // 's' - 'w'
+ TYP_HEX, NO_TYPE, NO_TYPE}; // 'x' - 'z'
+
+// This holds the functions for writing out structures
+static WriteFunc g_pStructFuncs[] = {(WriteFunc) WriteBIND_OPTS, (WriteFunc) WriteDVTARGETDEVICE,
+ (WriteFunc) WriteFORMATETC, (WriteFunc) WriteFILETIME,
+ (WriteFunc) WriteINTERFACEINFO, (WriteFunc) WriteLOGPALETTE,
+ (WriteFunc) WriteMSG, (WriteFunc) WriteOLEINPLACEFRAMEINFO,
+ (WriteFunc) WriteOLEMENUGROUPWIDTHS, (WriteFunc) WritePOINT,
+ (WriteFunc) WriteRECT, (WriteFunc) WriteSTGMEDIUM, (WriteFunc) WriteSTATSTG,
+ (WriteFunc) WriteSIZE, NULL };
+
+// this table starts at 'a' == 97
+// this table holds what type of structure to print out
+static const BYTE g_structLookup[] = {NO_STRUCT, STRUCT_BIND_OPTS, NO_STRUCT, STRUCT_DVTARGETDEVICE, // 'a' - 'd'
+ STRUCT_FORMATETC, STRUCT_FILETIME, NO_STRUCT, NO_STRUCT, // 'e' - 'h'
+ STRUCT_INTERFACEINFO, NO_STRUCT, NO_STRUCT, STRUCT_LOGPALETTE, // 'i' - 'l'
+ STRUCT_MSG, NO_STRUCT, STRUCT_OLEINPLACEFRAMEINFO, STRUCT_POINT,// 'm' - 'p'
+ NO_STRUCT, STRUCT_RECT, STRUCT_STGMEDIUM, STRUCT_STATSTG , // 'q' - 't'
+ NO_STRUCT, NO_STRUCT, STRUCT_OLEMENUGROUPWIDTHS, NO_STRUCT, // 'u' - 'x'
+ NO_STRUCT, STRUCT_SIZE }; // 'y' - 'z'
+
+//+---------------------------------------------------------------------------
+//
+// Function: oleprintf
+//
+// Synopsis: Prints out trace information using a given function, given a
+// nesting depth (for indenting), an API/Method name, a format string,
+// and a variable number of arguments
+//
+// Arguments: [depth] - nesting/indentation level
+// [pscApiName] - name of API/Method traced
+// [pscFormat] - format string
+// [argptr] - variable argument list
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void __cdecl oleprintf(int depth, const char *pscApiName, const char *pscFormat, va_list argptr)
+{
+ // buffer all output so that multithreaded traces look right
+ CTextBufferA buf;
+ char temp[20];
+ char *pscPos;
+
+ // first print out the process id
+ buf << gPidString;
+
+ buf << '.';
+
+ // now print out the thread id
+ _itoa(GetCurrentThreadId(), temp, 10);
+
+ buf << temp;
+ buf << "> ";
+
+ // tab to nesting/indent depth
+ while(depth-- > 0)
+ {
+ buf << pscTabString;
+ }
+
+ // now print out API name
+ buf << pscApiName;
+
+ // now we are ready to print out what was passed
+ pscPos = strchr(pscFormat, '%');
+
+ while(pscPos != NULL)
+ {
+ // insert the text up to the found '%' character into the buffer
+ buf.Insert(pscFormat, pscPos-pscFormat);
+
+ if(*(pscPos+1) == '%') // this is '%%', we only print one '%' and don't print an argument
+ {
+ buf << *pscPos;
+ pscFormat = pscPos+2;
+ }
+ else
+ {
+ BYTE argType = NO_TYPE;
+
+ // advance pscPos to type specifier
+ pscPos++;
+
+ // we need to take an argument and handle it
+ if(*pscPos >= 'A' && *pscPos <= 'z')
+ {
+ argType = g_tcLookup[*pscPos- 'A'];
+ }
+
+ if(argType != NO_TYPE)
+ {
+ // handle argument
+ // function will advance pscPos past format specifier
+ g_pFuncs[argType](buf, argptr, pscPos);
+ }
+ else
+ {
+ // assume we've got a one character format specifier
+ pscPos++;
+ // unknown type, assume size of int
+ va_arg(argptr, int);
+ }
+
+ // advance search pointer past type specifier
+ pscFormat = pscPos;
+ }
+
+ pscPos = strchr(pscFormat, '%');
+ }
+
+ // print out remainder of string
+ buf << pscFormat;
+
+ // destructor will flush buffer for us
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteHex
+//
+// Synopsis: Prints out a lower case hex value
+//
+// Arguments: [buf] - reference to text buffer to write text to
+// [param] - reference to variable argument list
+// [pFormat] - reference to a char * to the format string,
+// used to advance string past specifier string
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteHex(CTextBufferA &buf, va_list &param, char *&pFormat)
+{
+ WriteHexCommon(buf, va_arg(param, unsigned long), FALSE);
+
+ //advance format pointer
+ pFormat++;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteHexCaps
+//
+// Synopsis: Prints out an upper case hex value
+//
+// Arguments: [buf] - reference to text buffer to write text to
+// [param] - reference to variable argument list
+// [pFormat] - reference to a char * to the format string,
+// used to advance string past specifier string
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteHexCaps(CTextBufferA &buf, va_list &param, char *&pFormat)
+{
+ WriteHexCommon(buf, va_arg(param, unsigned long), TRUE);
+
+ //advance format pointer
+ pFormat++;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteInt
+//
+// Synopsis: Prints out a signed integer value
+//
+// Arguments: [buf] - reference to text buffer to write text to
+// [param] - reference to variable argument list
+// [pFormat] - reference to a char * to the format string,
+// used to advance string past specifier string
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteInt(CTextBufferA &buf, va_list &param, char *&pFormat)
+{
+ WriteIntCommon(buf, va_arg(param, unsigned int), FALSE);
+
+ // advance pointer
+ pFormat++;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteUnsigned
+//
+// Synopsis: Prints out a unsigned value, may be 64 bit or 32 bit
+// depending on next character in format specifier
+//
+// Arguments: [buf] - reference to text buffer to write text to
+// [param] - reference to variable argument list
+// [pFormat] - reference to a char * to the format string,
+// used to advance string past specifier string
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteUnsigned(CTextBufferA &buf, va_list &param, char *&pFormat)
+{
+ switch(*(pFormat+1)) // next character determines type
+ {
+ case 'd': // 32-bit
+ case 'D':
+ WriteIntCommon(buf, va_arg(param, unsigned long), TRUE);
+
+ // Advance format pointer
+ pFormat+=2;
+ break;
+
+ case 'l': // 64-bit
+ case 'L':
+ WriteLargeCommon(buf, va_arg(param, __int64 *), TRUE);
+
+ // advance format pointer
+ if(*(pFormat+2) == 'd' || *(pFormat+2) == 'D')
+ {
+ pFormat+=3;
+ }
+ else
+ {
+ pFormat+=2;
+ }
+ break;
+
+ default:
+ pFormat++; // assume it's just one char-type specifier
+ break;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WritePointer
+//
+// Synopsis: Prints out a lower case pointer value,
+// checks to make sure pointer is good value
+// prints out symbol if a symbol maps to pointer
+//
+// Arguments: [buf] - reference to text buffer to write text to
+// [param] - reference to variable argument list
+// [pFormat] - reference to a char * to the format string,
+// used to advance string past specifier string
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WritePointer(CTextBufferA &buf, va_list &param, char *&pFormat)
+{
+ if(*(pFormat+1) != 'p')
+ {
+ WritePointerCommon(buf, va_arg(param, void *), FALSE, FALSE, FALSE);
+
+
+ pFormat++;
+ }
+ else
+ {
+ void **pPointer;
+ BufferContext bc;
+
+ // take snapshot of buffer
+ buf.SnapShot(bc);
+
+ // write pointer to pointer
+ // first validate this pointer
+ __try
+ {
+ pPointer = va_arg(param, void **);
+
+ WritePointerCommon(buf, *pPointer, FALSE, FALSE, FALSE);
+ }
+ __except(ExceptionFilter(_exception_code()))
+ {
+ // try to revert buffer
+ buf.Revert(bc);
+
+ WritePointerCommon(buf, pPointer, FALSE, TRUE, FALSE);
+ }
+
+ pFormat +=2;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WritePointerCaps
+//
+// Synopsis: Prints out an upper case pointer value,
+// checks to make sure pointer is good value
+// prints out symbol if a symbol maps to pointer
+//
+// Arguments: [buf] - reference to text buffer to write text to
+// [param] - reference to variable argument list
+// [pFormat] - reference to a char * to the format string,
+// used to advance string past specifier string
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WritePointerCaps(CTextBufferA &buf, va_list &param, char *&pFormat)
+{
+ WritePointerCommon(buf, va_arg(param, void *), TRUE, FALSE, FALSE);
+
+ pFormat++;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteLarge
+//
+// Synopsis: Prints out a 64-bit integer
+//
+// Arguments: [buf] - reference to text buffer to write text to
+// [param] - reference to variable argument list
+// [pFormat] - reference to a char * to the format string,
+// used to advance string past specifier string
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteLarge(CTextBufferA &buf, va_list &param, char *&pFormat)
+{
+ WriteLargeCommon(buf, va_arg(param, __int64 *), FALSE);
+
+ if(*(pFormat+1) == 'd' || *(pFormat+1) == 'D')
+ {
+ pFormat+=2;
+ }
+ else
+ {
+ pFormat++;
+ }
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteBool
+//
+// Synopsis: Prints out a lower case boolean value
+//
+// Arguments: [buf] - reference to text buffer to write text to
+// [param] - reference to variable argument list
+// [pFormat] - reference to a char * to the format string,
+// used to advance string past specifier string
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteBool(CTextBufferA &buf, va_list &param, char *&pFormat)
+{
+ WriteBoolCommon(buf, va_arg(param, BOOL), FALSE);
+
+ pFormat++;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteBoolCaps
+//
+// Synopsis: Prints out an upper case boolean value
+//
+// Arguments: [buf] - reference to text buffer to write text to
+// [param] - reference to variable argument list
+// [pFormat] - reference to a char * to the format string,
+// used to advance string past specifier string
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteBoolCaps(CTextBufferA &buf, va_list &param, char *&pFormat)
+{
+ WriteBoolCommon(buf, va_arg(param, BOOL), TRUE);
+
+ pFormat++;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteString
+//
+// Synopsis: Prints out an ASCII string
+//
+// Arguments: [buf] - reference to text buffer to write text to
+// [param] - reference to variable argument list
+// [pFormat] - reference to a char * to the format string,
+// used to advance string past specifier string
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteString(CTextBufferA &buf, va_list &param, char *&pFormat)
+{
+ WriteStringCommon(buf, va_arg(param, const char *));
+
+ // Advance format pointer
+ pFormat++;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteWideString
+//
+// Synopsis: Prints out a UNICODE string, but only supports ASCII characters
+// if character > 256 is encountered, an "unprintable character" char
+// is printed
+//
+// Arguments: [buf] - reference to text buffer to write text to
+// [param] - reference to variable argument list
+// [pFormat] - reference to a char * to the format string,
+// used to advance string past specifier string
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteWideString(CTextBufferA &buf, va_list &param, char *&pFormat)
+{
+ WriteWideStringCommon(buf, va_arg(param, const WCHAR *));
+
+ // Advance format pointer
+ if(*(pFormat+1) == 's')
+ {
+ pFormat+=2;
+ }
+ else
+ {
+ pFormat++;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteGUID
+//
+// Synopsis: Prints out a GUID
+//
+// Arguments: [buf] - reference to text buffer to write text to
+// [param] - reference to variable argument list
+// [pFormat] - reference to a char * to the format string,
+// used to advance string past specifier string
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteGUID(CTextBufferA &buf, va_list &param, char *&pFormat)
+{
+ WriteGUIDCommon(buf, va_arg(param, GUID *));
+
+ // Advance format pointer
+ pFormat++;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteStuct
+//
+// Synopsis: Prints out a structure. If structure expansion is enabled
+// expands the structure depending on it's type
+//
+// Arguments: [buf] - reference to text buffer to write text to
+// [param] - reference to variable argument list
+// [pFormat] - reference to a char * to the format string,
+// used to advance string past specifier string
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteStruct(CTextBufferA &buf, va_list &param, char *&pFormat)
+{
+ void *pArg;
+ BYTE bType = NO_STRUCT;
+
+ pArg = va_arg(param, void *);
+
+ if(*(pFormat+1) >= 'a' && *(pFormat+1) <= 'z')
+ {
+ bType = g_structLookup[*(pFormat+1) - 'a'];
+ }
+
+ if(bType != NO_STRUCT) // only print out known structures
+ {
+ BufferContext bc;
+
+ buf.SnapShot(bc); // take a snapshot of the buffer
+
+ __try
+ {
+ g_pStructFuncs[bType](buf, pArg);
+ }
+ __except (ExceptionFilter(_exception_code()))
+ {
+ buf.Revert(bc); // try to revert to the old buffer
+
+ // bad pointer
+ WritePointerCommon(buf, pArg, FALSE, TRUE, FALSE);
+ }
+ }
+ else
+ {
+ // write out the pointer
+ WritePointerCommon(buf, pArg, FALSE, FALSE, FALSE);
+ }
+
+ // increment format pointer
+ pFormat += 2;
+}
+
+#endif // DBG==1
diff --git a/private/ole32/common/oleprint.hxx b/private/ole32/common/oleprint.hxx
new file mode 100644
index 000000000..7f74c925b
--- /dev/null
+++ b/private/ole32/common/oleprint.hxx
@@ -0,0 +1,74 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: oleprint.hxx
+//
+// Contents: internal header for oleprint.cxx
+//
+// Functions: print functions for writing OLE types
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+#ifndef __OLEPRINT_HXX__
+#define __OLEPRINT_HXX__
+
+#include "buffer.hxx"
+
+// *** Defines, Constants, and Macros ***
+
+// *** Function Prototypes
+// our actual print function
+void __cdecl oleprintf(int depth, const char *pscApiName, const char *pscFormat, va_list args);
+
+// OLE type writing functions
+void WriteIntCommon(CTextBufferA& buf, unsigned int param, BOOL fUnsigned);
+void WritePointerCommon(CTextBufferA& buf, void *pPointer, BOOL fCaps, BOOL fKnownBad, BOOL fXlatSym);
+void WriteLargeCommon(CTextBufferA& buf, const __int64 *pInt, BOOL fUnsigned);
+void WriteHexCommon(CTextBufferA& buf, ULONG param, BOOL fCaps);
+void WriteBoolCommon(CTextBufferA& buf, BOOL param, BOOL fCaps);
+void WriteStringCommon(CTextBufferA& buf, const char *pString, BOOL fQuote=FALSE);
+void WriteWideStringCommon(CTextBufferA& buf, const WCHAR *pwString, BOOL fQuote=FALSE);
+void WriteGUIDCommon(CTextBufferA &buf, const GUID *pGUID);
+
+// OLE structure writing functions
+void WriteFILETIME(CTextBufferA& buf, FILETIME *pFileTime);
+void WriteRECT(CTextBufferA& buf, RECT *pRect);
+void WriteSIZE(CTextBufferA& buf, SIZE *pSize);
+void WriteLOGPALETTE(CTextBufferA& buf, LOGPALETTE *plp);
+void WritePOINT(CTextBufferA& buf, POINT *pPoint);
+void WriteMSG(CTextBufferA& buf, MSG *pMsg);
+void WriteSTGMEDIUM(CTextBufferA& buf, STGMEDIUM *pStg);
+void WriteFORMATETC(CTextBufferA& buf, FORMATETC *pFte);
+void WriteDVTARGETDEVICE(CTextBufferA& buf, DVTARGETDEVICE *pDvtdv);
+void WriteBIND_OPTS(CTextBufferA& buf, BIND_OPTS *pOpts);
+void WriteSTATSTG(CTextBufferA& buf, STATSTG *pStat);
+void WriteOLEINPLACEFRAMEINFO(CTextBufferA& buf, OLEINPLACEFRAMEINFO *pInfo);
+void WriteOLEMENUGROUPWIDTHS(CTextBufferA& buf, OLEMENUGROUPWIDTHS *pWidths);
+void WriteINTERFACEINFO(CTextBufferA &buf, INTERFACEINFO *pInfo);
+
+// *** Inline Functions ***
+//+---------------------------------------------------------------------------
+//
+// Function: ExceptionFilter
+//
+// Synopsis: Catches exceptions which result from a bad pointer
+//
+// Arguments: [code] - exception code
+//
+// Returns: 1 if this exception is to be processed, 0 otherwise
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+inline int ExceptionFilter(DWORD code)
+{
+ return (code == EXCEPTION_ACCESS_VIOLATION)
+ || (code == EXCEPTION_ARRAY_BOUNDS_EXCEEDED)
+ || (code == EXCEPTION_DATATYPE_MISALIGNMENT)
+ || (code == EXCEPTION_PRIV_INSTRUCTION);
+}
+
+#endif
diff --git a/private/ole32/common/olescm.cxx b/private/ole32/common/olescm.cxx
new file mode 100644
index 000000000..ecfafb1cf
--- /dev/null
+++ b/private/ole32/common/olescm.cxx
@@ -0,0 +1,367 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: olescm.cxx
+//
+// Contents: Functions shared between OLE32 and the SCM
+//
+// Classes:
+//
+// Functions:
+//
+// History: 10-03-95 kevinro Created
+//
+//----------------------------------------------------------------------------
+
+#include <windows.h>
+#include <ole2sp.h>
+#include <ole2com.h>
+
+static const TCHAR tszOle32Dll[] = TEXT("OLE32.DLL");
+
+#define OLE32_DLL tszOle32Dll
+#define OLE32_BYTE_LEN sizeof(OLE32_DLL)
+#define OLE32_CHAR_LEN (sizeof(OLE32_DLL) / sizeof(TCHAR) - 1)
+
+//
+// Threading Model Registry Constants
+//
+
+const TCHAR tszDllThreadModel[] = TEXT("ThreadingModel");
+
+const TCHAR tszAptModel[] = TEXT("Apartment");
+const TCHAR tszBothModel[] = TEXT("Both");
+const TCHAR wszFreeModel[] = TEXT("Free");
+
+// Thread model match table. The table's first index is the threading
+// model of the process and can be either APT_THREADED or
+// FREE_THREADED. The second index is any one of the types of threading
+// model's for DLLs.
+BOOL afThreadModelMatch[2][4] =
+ {{TRUE, FALSE, TRUE, TRUE},
+ {FALSE, TRUE, FALSE, TRUE}};
+//+---------------------------------------------------------------------------
+//
+// Function: CompareDllName
+//
+// Synopsis: Give a DLL path, this sees if the path is equal to a given
+// DLL name or the last component of the is the same as the
+// DLL name.
+//
+// Arguments: [pwszPath] -- DLL path
+// [pwszDllName] -- name of DLL to compare with
+//
+// Returns: TRUE - The input path is equal or its last component is equal
+// to the input Dll name.
+// FALSE - Not equal at all.
+//
+// History: 6-15-95 ricksa Created
+//
+// Notes: This is a helper function used by the routines that convert
+// ole2.dll to ole32.dll and to convert paths that end in ole32.dll
+// into ole32.dll.
+//
+//----------------------------------------------------------------------------
+BOOL
+wCompareDllName(LPCTSTR ptszPath, LPCTSTR ptszDllName, DWORD dwDllNameLen)
+{
+ BOOL fResult = TRUE;
+
+ if (lstrcmpi(ptszDllName, ptszPath) != 0)
+ {
+ // Check if the last component is the same path
+ DWORD dwPathLen = lstrlen(ptszPath);
+
+ if (dwPathLen > dwDllNameLen)
+ {
+ // Point to the last where the slash would be if the substitute
+ // path is the last component
+ LPCTSTR ptszLastComponent = ptszPath + dwPathLen - (dwDllNameLen + 1);
+
+ // Is there a slash in that position
+ if ((*ptszLastComponent == '\\') || (*ptszLastComponent == '/'))
+ {
+ // Point to where the last component should be
+ ptszLastComponent++;
+
+ // Does the last component match?
+ if (lstrcmpi(ptszLastComponent, ptszDllName) == 0)
+ {
+ goto CompareDllName_Exit;
+ }
+ }
+ }
+
+ fResult = FALSE;
+ }
+
+CompareDllName_Exit:
+
+ return fResult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wThreadModelMatch
+//
+// Synopsis: Determines whether caller and DLL thread models match
+//
+// Arguments: [dwCallerThreadModel] - Caller thread model
+// [dwDllThreadModel] - DLL thread model
+//
+// Returns: TRUE - DLL can be loaded caller
+// FALSE - DLL cannot be loaded into caller.
+//
+// Algorithm: If the caller's thread model is apartment, then check
+// whether the DLL is one of apartment, single threaded or
+// both threaded. If it is, then return TRUE. Otherwise,
+// for free threading return TRUE if the DLL model is either
+// both or free threaded. If neither of the above is TRUE
+// then return FALSE.
+//
+// History: 10-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL wThreadModelMatch(
+ DWORD dwCallerThreadModel,
+ DWORD dwDllThreadModel,
+ DWORD dwContext)
+{
+ BOOL fResult = afThreadModelMatch[dwCallerThreadModel] [dwDllThreadModel];
+
+ if (dwContext & CLSCTX_PS_DLL)
+ {
+ fResult = TRUE;
+ }
+
+ return fResult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wQueryStripRegValue
+//
+// Synopsis: Get the DLL information for a 32 bit DLL and
+// strip off any leading and trailing "
+//
+// Arguments: [hkey] - class handle
+// [pwszSubKey] - key to open
+// [pwszValue] - where to return data
+// [pcbValue] - length of above buffer in bytes
+//
+// Returns: ERROR_SUCCESS - read DLL path information
+// Other - registry entries could not be found
+//
+// Algorithm: Read the value requested.
+// If first character is not ", exit
+// Otherwise, copy data after quote to beginning of buffer.
+//
+//
+// History: 05-Jan-94 BillMo Created
+// 26-Sep-95 BruceMa Support environment variable expansion
+// for shell viewers
+//
+//--------------------------------------------------------------------------
+
+LONG
+wQueryStripRegValue(HKEY hKey, // handle of key to query
+ LPCTSTR ptszSubKey, // address of name of subkey to query
+ LPTSTR ptszValue, // address of buffer for returned string
+ PLONG pcbValue) // address of buffer for size of returned string
+{
+ HKEY hSubKey;
+ DWORD dwType;
+ LONG lErr ;
+
+ Win4Assert(ptszValue != NULL);
+ Win4Assert(pcbValue != NULL);
+
+ //
+ // Open the subkey if there is a string
+ //
+ if (ptszSubKey != NULL)
+ {
+ lErr = RegOpenKeyExT(hKey, ptszSubKey, NULL, KEY_READ, &hSubKey);
+ }
+ else
+ {
+ hSubKey = hKey;
+ lErr = ERROR_SUCCESS;
+ }
+
+ // Read the value into the user's buffer
+ if (lErr == ERROR_SUCCESS)
+ {
+ lErr = RegQueryValueExT(hSubKey, NULL , NULL, &dwType,
+ (BYTE *) ptszValue, (ULONG *) pcbValue);
+ if (lErr == ERROR_SUCCESS)
+ {
+ TCHAR *ptszScan = ptszValue; // used to scan along string
+ TCHAR *ptszDest = ptszValue; // used as destination when copying
+
+ // if the name is quoted then ...
+ if (*ptszScan == '\"')
+ {
+ ptszScan++;
+
+ // copy all non-quote characters down to base of buffer
+ // until end of quoted string
+ while (*ptszScan != '\0' && *ptszScan != '\"')
+ {
+ *ptszDest++ = *ptszScan++;
+ }
+
+ // terminate string and get length in bytes including nul
+ *ptszDest++ = '\0';
+ *pcbValue = (ptszDest - ptszValue) * sizeof(TCHAR);
+ }
+
+ // find first non-white space character
+ ptszScan = ptszValue;
+ while (_istspace(*ptszScan))
+ ptszScan++;
+
+ // if there are no non-white space characters this will be true
+ if (*ptszScan == L'\0')
+ {
+ lErr = ERROR_FILE_NOT_FOUND;
+ *pcbValue = 0;
+ }
+
+ // Chicago does not support ExpandEnvironmentStrings
+#ifndef _CHICAGO_
+ // If the value type is REG_EXPAND_SZ then do environment variable
+ // expansion
+ if (dwType == REG_EXPAND_SZ)
+ {
+ // Expand any embedded environemnt variable expressions
+ TCHAR tszTemp[MAX_PATH];
+
+ lstrcpy(tszTemp, ptszValue);
+ *pcbValue = ExpandEnvironmentStrings(tszTemp, ptszValue,MAX_PATH);
+ }
+#endif // !_CHICAGO_
+ }
+
+ //
+ // Only close the sub key if we actually opened it.
+ //
+ if (hSubKey != hKey)
+ {
+ RegCloseKey(hSubKey);
+ }
+
+ }
+ return lErr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetDllInfo
+//
+// Synopsis: Get the DLL information for a 32 bit DLL
+//
+// Arguments: [hClsRegEntry] - class handle
+// [pwszKey] - key to open
+// [pwszDllName] - where to return DLL path
+// [pclDllName] - length of above buffer
+// [pulDllThreadType] - where to return DLL threading information
+//
+// Returns: ERROR_SUCCESS - read DLL path information
+// Other - registry entries could not be found
+//
+// Algorithm: Open the DLL key. Then read the DLL path name. Finally read
+// the threading model information if it is specified.
+//
+// History: 09-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+LONG wGetDllInfo(
+ HKEY hClsRegEntry,
+ LPCTSTR ptszKey,
+ LPTSTR ptszDllName,
+ LONG *pclDllName,
+ ULONG *pulDllThreadType)
+{
+ HKEY hDllEntry = NULL;
+
+ // Open the registry key
+ LONG lerr = RegOpenKeyT(hClsRegEntry, ptszKey, &hDllEntry);
+
+ if (ERROR_SUCCESS == lerr)
+ {
+ // Read the DLL name
+ lerr = wQueryStripRegValue(hDllEntry, NULL, ptszDllName, pclDllName);
+
+ // Is there a DLL path?
+ if (ERROR_SUCCESS == lerr)
+ {
+ if (wCompareDllName(ptszDllName,OLE32_DLL,OLE32_CHAR_LEN))
+ {
+ memcpy(ptszDllName,OLE32_DLL,OLE32_BYTE_LEN);
+ *pclDllName = OLE32_CHAR_LEN;
+ // Ole32 DLL will work anywhere
+ *pulDllThreadType = BOTH_THREADED;
+ }
+ else
+ {
+
+ // Assume there is no registry entry
+ *pulDllThreadType = SINGLE_THREADED;
+
+ // Buffer to hold entry for the registry data.
+ TCHAR tszModelBuf[MAX_PATH];
+ DWORD cdwModelBuf = sizeof(tszModelBuf);
+ DWORD dwRegEntType;
+
+ // Read the DLL threading model from the registry
+
+ lerr = RegQueryValueExT(hDllEntry, tszDllThreadModel, NULL,
+ &dwRegEntType, (LPBYTE) &tszModelBuf[0], &cdwModelBuf);
+
+ // Is there an thread model descriptor
+ if (ERROR_SUCCESS == lerr)
+ {
+ if ( REG_SZ != dwRegEntType)
+ {
+ // If it wasn't a string, bail
+ }
+ // Is it apartment model?
+
+ else if (lstrcmpi(tszAptModel, tszModelBuf) == 0)
+ {
+ *pulDllThreadType = APT_THREADED;
+ }
+ // Is is both threaded?
+ else if (lstrcmpi(tszBothModel, tszModelBuf) == 0)
+ {
+ *pulDllThreadType = BOTH_THREADED;
+ }
+ else if (lstrcmpi(wszFreeModel, tszModelBuf) == 0)
+ {
+ *pulDllThreadType = FREE_THREADED;
+ }
+ else
+ {
+ // BUGBUG: Should print a warning here
+ }
+
+ // If neither then we fall back to single threaded
+ // since this is guaranteed to be safe for the DLL.
+ }
+
+ // When we get to this point, we got a DLL entry so we remap
+ // any errors to success because they only mean that we could
+ // not get a model from the registry.
+ lerr = ERROR_SUCCESS;
+ }
+ }
+ RegCloseKey(hDllEntry);
+ }
+
+ return lerr;
+}
+
+
diff --git a/private/ole32/common/olesem.cxx b/private/ole32/common/olesem.cxx
new file mode 100644
index 000000000..66eb68b3d
--- /dev/null
+++ b/private/ole32/common/olesem.cxx
@@ -0,0 +1,175 @@
+///+---------------------------------------------------------------------------
+//
+// File: olesem.cxx
+//
+// Contents: Implementation of semaphore classes for use in OLE code
+//
+// Functions: COleStaticMutexSem::Destroy
+// COleStaticMutexSem::Request
+// COleStaticMutexSem::Init
+// COleDebugMutexSem::COleDebugMutexSem
+//
+// History: 14-Dec-95 Jeffe Initial entry, derived from
+// sem32.hxx by AlexT.
+//
+//
+//----------------------------------------------------------------------------
+
+#include <windows.h>
+#include <debnot.h>
+#include <olesem.hxx>
+
+//
+// Global state for the mutex package
+//
+
+//
+// List of initialized static mutexes (which must be destroyed
+// during DLL exit). We know that PROCESS_ATTACH and PROCESS_DETACH
+// are thread-safe, so we don't protect this list with a critical section.
+//
+
+COleStaticMutexSem * g_pInitializedStaticMutexList = NULL;
+
+
+#if DBG
+
+//
+// Flag used to indicate if we're past executing the C++ constructors
+// during DLL initialization
+//
+
+DLL_STATE g_fDllState = DLL_STATE_STATIC_CONSTRUCTING;
+
+#endif
+
+
+
+//
+// Semaphore used to protect the creation of other semaphores
+//
+
+CRITICAL_SECTION g_OleMutexCreationSem;
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: COleStaticMutexSem::Destroy
+//
+// Synopsis: Releases a semaphore's critical section.
+//
+// History: 14-Dec-1995 Jeffe
+//
+//----------------------------------------------------------------------------
+
+void COleStaticMutexSem::Destroy()
+{
+ if (_fInitialized)
+ {
+ DeleteCriticalSection (&_cs);
+ _fInitialized = FALSE;
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: COleStaticMutexSem::Request
+//
+// Synopsis: Acquire the semaphore. If another thread already has it,
+// wait until it is released. Initialize the semaphore if it
+// isn't already initialized.
+//
+// History: 14-Dec-1995 Jeffe
+//
+//----------------------------------------------------------------------------
+
+void COleStaticMutexSem::Request()
+{
+ if (!_fInitialized)
+ {
+ EnterCriticalSection (&g_OleMutexCreationSem);
+ if (!_fInitialized) {
+ Init();
+ }
+ LeaveCriticalSection (&g_OleMutexCreationSem);
+ }
+ EnterCriticalSection (&_cs);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: COleStaticMutexSem::Init
+//
+// Synopsis: Initialize semaphore's critical section
+//
+// History: 14-Dec-1995 Jeffe
+//
+//----------------------------------------------------------------------------
+
+void COleStaticMutexSem::Init()
+{
+ InitializeCriticalSection (&_cs);
+ _fInitialized = TRUE;
+ if (!_fAutoDestruct)
+ {
+ //
+ // We don't need to protect this list with a mutex, since it's only
+ // manipulated during DLL attach/detach, which is single threaded by
+ // the platform.
+ //
+
+ pNextMutex = g_pInitializedStaticMutexList;
+ g_pInitializedStaticMutexList = this;
+ }
+}
+
+
+#ifdef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Member: COleStaticMutexSem::ReleaseFn
+//
+// Synopsis: Release the semaphore(non inline version) used only by rpccall.asm
+//
+// History: 14-Dec-1995 Jeffe
+//
+//----------------------------------------------------------------------------
+
+void COleStaticMutexSem::ReleaseFn()
+{
+ LeaveCriticalSection (&_cs);
+}
+#endif
+
+
+
+#if DBG==1
+
+//+---------------------------------------------------------------------------
+//
+// Member: COleDebugMutexSem::COleDebugMutexSem
+//
+// Synopsis: Mark the mutex as dynamic...which will prevent it from being
+// added to the static mutex cleanup list on DLL unload.
+//
+// History: 14-Dec-1995 Jeffe
+//
+// Notes: We don't care that this has a constructor, as it won't be run
+// in retail builds.
+//
+//----------------------------------------------------------------------------
+
+COleDebugMutexSem::COleDebugMutexSem()
+{
+ Win4Assert (g_fDllState == DLL_STATE_STATIC_CONSTRUCTING);
+ _fAutoDestruct = TRUE;
+ _fInitialized = FALSE;
+}
+
+#endif // DBG==1
+
diff --git a/private/ole32/common/oletype.cxx b/private/ole32/common/oletype.cxx
new file mode 100644
index 000000000..5a9d8ed7d
--- /dev/null
+++ b/private/ole32/common/oletype.cxx
@@ -0,0 +1,1359 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: oletype.cxx
+//
+// Contents: individual methods for priting OLE types
+//
+// Functions: see oleprint.hxx
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+#include <windows.h>
+#include <ole2sp.h>
+#include <ole2com.h>
+#if DBG==1
+#include "oleprint.hxx"
+#include "sym.hxx"
+
+// temporary string buffer size
+#define TEMP_SIZE 64
+
+// our constant strings
+const char *pscNullString = "<NULL>";
+const char *pscTrue = "true";
+const char *pscTRUE = "TRUE";
+const char *pscFalse = "false";
+const char *pscFALSE = "FALSE";
+
+const char *pscHexPrefix = "0x";
+const char *pscPointerPrefix = "<";
+const char *pscBadPointerPrefix = "BAD PTR : ";
+const char *pscPointerSuffix = ">";
+
+const char *pscStructPrefix = "{ ";
+const char *pscStructDelim = " , ";
+const char *pscStructSuffix = " }";
+
+// These functions are in com\util\guid2str.c
+extern "C" void FormatHexNum( unsigned long ulValue, unsigned long chChars, char *pchStr);
+extern "C" int StrFromGUID(REFGUID rguid, char * lpsz, int cbMax);
+
+// *** Global Data ***
+CSym *g_pSym = NULL; // manage symbol stuff
+
+//+---------------------------------------------------------------------------
+//
+// Function: FormatHex
+//
+// Synopsis: Wrapper around FormatHexNum to control if leading zeros are printed
+//
+// Arguments: [ulValue] - DWORD value to print out
+// [chChars] - number of characters to print out, starting from right of number
+// [fLeadZeros] - whether or not to print leading zeros
+// [pchStr] - pointer of string to put printed out value, must have room for
+// chChars+1 chars (chChars digits and null byte)
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void FormatHex(unsigned long ulValue, unsigned long chChars, BOOL fLeadZeros, char *pchStr)
+{
+ if(!fLeadZeros)
+ {
+ unsigned long ulmask = 0xf<<((chChars-1)<<4);
+
+ // determine how many leading zeros there are
+ while(!(ulValue & ulmask) && (chChars > 1))
+ {
+ chChars--;
+ ulmask >>=4;
+ }
+
+ FormatHexNum(ulValue, chChars, pchStr);
+
+ // tag on null byte
+ pchStr[chChars] = '\0';
+
+ }
+ else
+ {
+ FormatHexNum(ulValue, chChars, pchStr);
+
+ // tag on null byte
+ pchStr[chChars] = '\0';
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IntToString
+//
+// Synopsis: Prints out a integer to a string (base 10)
+//
+// Arguments: [n] - integer to print out
+// [pStr] - pointer of string to put printed out value
+// [nMax] - maximum number of characters
+// [fUnsigned] - whether or not value is unsigned
+//
+// Returns: pStr
+//
+// History: 15-Jul-95 t-stevan Created
+//
+// NOtes: nMax should be enough to hold the printed out string
+//----------------------------------------------------------------------------
+char *IntToString(unsigned long n, char *pStr, int nMax, BOOL fUnsigned)
+{
+ char *pChar;
+ BOOL fSign= FALSE;
+ int nCount;
+
+ // Special case, n = 0
+ if(n == 0)
+ {
+ *pStr = '0';
+ *(pStr+1) = '\0';
+
+ return pStr;
+ }
+
+ if(!fUnsigned)
+ {
+ // if the value is signed, figure out what the sign of it is, and
+ // then take absolute value
+ if((fSign = ((int) n) < 0))
+ {
+ n = -((int)n);
+ }
+ }
+
+
+ // initialize pChar to point to the last character in pStr
+ pChar = &(pStr[nMax-1]);
+ // tag on null byte
+ *pChar = '\0';
+ pChar--;
+ // null byte counts!
+ nCount=1;
+
+ // loop until n == 0
+ while(n && nCount <= nMax)
+ {
+ // write digit
+ *pChar = '0'+(char)(n%10);
+ // move to next digit
+ pChar--;
+ // increase digit count
+ nCount++;
+ // divide n by 10
+ n/=10;
+ }
+
+ if(nCount > nMax)
+ {
+ return pStr; // we failed, but still return pStr
+ }
+
+ if(fSign)
+ {
+ *pStr = '-'; // tag on sign
+ memmove(pStr+1, pChar+1, nCount); // move string to front
+ }
+ else
+ {
+ memmove(pStr, pChar+1, nCount); // move string to front
+ }
+
+ return pStr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteIntCommon
+//
+// Synopsis: Common functionality for printing out integer values
+//
+// Arguments: [buf] - text buffer to print text to
+// [param] - integer to print
+// [fUnsigned] - whether or not value is unsigned
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteIntCommon(CTextBufferA &buf, unsigned int param, BOOL fUnsigned)
+{
+ char temp[TEMP_SIZE];
+
+ IntToString(param, temp, TEMP_SIZE, fUnsigned);
+ // _ltoa((int) param, temp, 10);
+
+ // do write op
+ buf << temp;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WritePointerCommon
+//
+// Synopsis: Common functionality for printing pointers
+//
+// Arguments: [buf] - text buffer to print text to
+// [pPointer] - pointer to print out
+// [fCaps] - whether or not to use capitalized hex digits (ABCDEF)
+// [fKnownBad] - whether or not the pointer is known to be bad
+// [fXlatSym] - whether or not we should attempt to address->symbol
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WritePointerCommon(CTextBufferA &buf, void *pPointer, BOOL fCaps, BOOL fKnownBad, BOOL fXlatSym)
+{
+ char temp[TEMP_SIZE];
+
+ if(pPointer == NULL)
+ {
+ buf << pscNullString;
+ return;
+ }
+
+ if(fKnownBad)
+ {
+ // we know it's a bad pointer
+ buf << pscPointerPrefix;
+ buf << pscBadPointerPrefix;
+ }
+ else
+ {
+ buf << pscPointerPrefix;
+
+ // validate pointer
+ __try
+ {
+ // try a read operation
+ temp[0] = *((char *)pPointer);
+ }
+ __except (ExceptionFilter(_exception_code()))
+ {
+ // bad pointer
+ buf << pscBadPointerPrefix;
+ fKnownBad = TRUE;
+ }
+ }
+
+ if(!fKnownBad && fXlatSym)
+ {
+ // see if we can find a symbol for the pointer
+ char symbol[MAXNAMELENGTH];
+ DWORD dwDisplacement;
+
+ if(g_pSym != NULL)
+ {
+ if (g_pSym->GetSymNameFromAddr((DWORD) pPointer, &dwDisplacement, symbol, MAXNAMELENGTH))
+ {
+ // found a symbol. Woo hoo!
+ WriteStringCommon(buf, symbol);
+
+ if(dwDisplacement != 0)
+ {
+ buf << '+';
+
+ buf << pscHexPrefix;
+
+ // no leading zeros
+ FormatHex((unsigned long) dwDisplacement, 8, FALSE, temp);
+
+ buf << temp;
+ }
+
+ buf << pscPointerSuffix;
+
+ return;
+ }
+ }
+ }
+
+ // add the hex prefix
+ buf << pscHexPrefix;
+
+ FormatHex((unsigned long) pPointer, 8, TRUE, temp);
+
+ if(fCaps)
+ {
+ CharUpperBuffA (temp, lstrlenA (temp));
+ }
+ else
+ {
+ CharLowerBuffA (temp, lstrlenA (temp));
+ }
+
+ // do write op
+ buf << temp;
+
+ // write suffix
+ buf << pscPointerSuffix;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteLargeCommon
+//
+// Synopsis: Common functionality for printing out a 64-bitinteger values
+//
+// Arguments: [buf] - text buffer to print text to
+// [param] - integer to print
+// [fUnsigned] - whether or not value is unsigned (currently ignored)
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+// Note: currently 64-bit integers are printed out as unsigned hex numbers
+//----------------------------------------------------------------------------
+void WriteLargeCommon(CTextBufferA &buf, const __int64 *pInt, BOOL fUnsigned)
+{
+ char temp[TEMP_SIZE];
+
+ __try // catch bad pointers
+ {
+ // right now we ignore the fUnsigned parameter and print out
+ // as an unsigned hex integer
+ FormatHex((unsigned long) ((*pInt)>>32), 8, FALSE, temp);
+
+ buf << pscHexPrefix;
+ buf << temp;
+
+ FormatHex((unsigned long) ((*pInt)&0xffffffff), 8, TRUE, temp);
+
+ buf << temp;
+ }
+ __except (ExceptionFilter(_exception_code()))
+ {
+ // bad pointer, just print out the pointer passed
+ WritePointerCommon(buf, (void *) pInt, FALSE, TRUE, FALSE);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteHexCommon
+//
+// Synopsis: Common functionality for printing out hex integer values
+//
+// Arguments: [buf] - text buffer to print text to
+// [param] - integer to print
+// [fCaps] - whether or not to print capital hex digits (ABCDEF)
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteHexCommon(CTextBufferA &buf, ULONG param, BOOL fCaps)
+{
+ char temp[TEMP_SIZE];
+
+ buf << pscHexPrefix;
+
+ // write out number
+ FormatHex((unsigned long) param, 8, TRUE, temp);
+
+ if(fCaps)
+ {
+ CharUpperBuffA (temp, lstrlenA (temp));
+ }
+ else
+ {
+ CharLowerBuffA (temp, lstrlenA (temp));
+ }
+
+ // do write op
+ buf << temp;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteBoolCommon
+//
+// Synopsis: Common functionality for printing out boolean values
+//
+// Arguments: [buf] - text buffer to print text to
+// [param] - integer to print
+// [fCaps] - whether or not to print capital characters
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteBoolCommon(CTextBufferA &buf, BOOL param, BOOL fCaps)
+{
+ const char *pTrue, *pFalse;
+
+ if(fCaps)
+ {
+ pTrue = pscTRUE;
+ pFalse = pscFALSE;
+ }
+ else
+ {
+ pTrue = pscTrue;
+ pFalse = pscFalse;
+ }
+
+ if(param)
+ {
+ buf << pTrue;
+ }
+ else
+ {
+ buf << pFalse;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteStringCommon
+//
+// Synopsis: Common functionality for printing out ASCII strings
+//
+// Arguments: [buf] - text buffer to print text to
+// [pString] - pointer to ASCII string
+// [fQuote] - whether or not to enclose the string in quotes
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteStringCommon(CTextBufferA &buf, const char *pString, BOOL fQuote)
+{
+ BufferContext bc;
+
+ // take a snapshot of the buffer first
+ buf.SnapShot(bc);
+
+ __try
+ {
+ if(fQuote)
+ {
+ buf << '\"';
+ }
+
+ buf << pString;
+
+ if(fQuote)
+ {
+ buf << '\"';
+ }
+ }
+ __except (ExceptionFilter(_exception_code()))
+ {
+ // bad pointer
+ // first try to rever the buffer
+ buf.Revert(bc);
+
+ WritePointerCommon(buf, (void *) pString, FALSE, TRUE, FALSE);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteWideStringCommon
+//
+// Synopsis: Common functionality for printing out Unicode strings
+//
+// Arguments: [buf] - text buffer to print text to
+// [pwsStr] - pointer to Unicode string
+// [fQuote] - whether or not to enclose the string in quotes
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteWideStringCommon(CTextBufferA& buf, const WCHAR *pwsStr, BOOL fQuote)
+{
+ BufferContext bc;
+
+ // take a snapshot of the buffer first
+ buf.SnapShot(bc);
+
+ __try
+ {
+ if(fQuote)
+ {
+ buf << '\"';
+ }
+
+ while(*pwsStr != 0)
+ {
+ if(*pwsStr & 0xff00)
+ {
+ // if high byte has info, set to
+ // 0x13, which is two !'s
+ buf << (char) 0x13;
+ }
+ else
+ {
+ buf << (char) (*pwsStr &0xff);
+ }
+
+ pwsStr++;
+ }
+
+ if(fQuote)
+ {
+ buf << '\"';
+ }
+ }
+ __except (ExceptionFilter(_exception_code()))
+ {
+ // bad pointer
+ // try to revert the buffer
+ buf.Revert(bc);
+
+ WritePointerCommon(buf, (void *) pwsStr, FALSE, TRUE, FALSE);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteGUIDCommon
+//
+// Synopsis: Common functionality for printing out GUIDs
+//
+// Arguments: [buf] - text buffer to print text to
+// [pGUID] - pointer to GUID to print
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteGUIDCommon(CTextBufferA& buf, const GUID *pGUID)
+{
+ char temp[GUIDSTR_MAX+1];
+ BufferContext bc;
+
+ // take a snapshot of the buffer first
+ buf.SnapShot(bc);
+
+ __try
+ {
+ StrFromGUID(*pGUID, temp, GUIDSTR_MAX);
+
+ // tack on null byte
+ temp[GUIDSTR_MAX - 1] = '\0';
+
+ // write the string out
+ buf << temp;
+ }
+ __except (ExceptionFilter(_exception_code()))
+ {
+ // bad pointer
+ // try to revert the buffer
+ buf.Revert(bc);
+
+ WritePointerCommon(buf, (void *) pGUID, FALSE, TRUE, FALSE);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteFILETIME
+//
+// Synopsis: Prints out a FILETIME structure
+//
+// Arguments: [buf] - text buffer to print text to
+// [pFileTime] - pointer to FILETIME structure
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteFILETIME(CTextBufferA& buf, FILETIME *pFileTime)
+{
+ SYSTEMTIME sysTime;
+
+ buf << pscStructPrefix;
+
+ if(FileTimeToSystemTime(pFileTime, &sysTime))
+ {
+ char temp[TEMP_SIZE];
+
+ IntToString(sysTime.wMonth, temp, TEMP_SIZE, TRUE);
+
+ buf << temp;
+ buf << '/';
+
+ IntToString(sysTime.wDay, temp, TEMP_SIZE, TRUE);
+
+ buf << temp;
+ buf << '/';
+
+ IntToString(sysTime.wYear, temp, TEMP_SIZE, TRUE);
+
+ buf << temp;
+ buf << ' ';
+
+ IntToString(sysTime.wHour, temp, TEMP_SIZE, TRUE);
+
+ buf << temp;
+ buf << ':';
+
+ if(sysTime.wMinute == 0)
+ {
+ buf << "00";
+ }
+ else
+ {
+ IntToString(sysTime.wMinute, temp, TEMP_SIZE, TRUE);
+
+ buf << temp;
+ }
+ }
+ else
+ {
+ buf << "dwLowDateTime= ";
+
+ WriteHexCommon(buf, pFileTime->dwLowDateTime, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "dwHighDateTime= ";
+
+ WriteHexCommon(buf, pFileTime->dwHighDateTime, FALSE);
+
+ }
+
+ buf << pscStructSuffix;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteRECT
+//
+// Synopsis: Prints out a RECT structure
+//
+// Arguments: [buf] - text buffer to print text to
+// [pRECT] - pointer to RECT structure
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteRECT(CTextBufferA& buf, RECT *pRect)
+{
+ buf << pscStructPrefix;
+
+ buf << "left= ";
+
+ WriteIntCommon(buf, pRect->left, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "top= ";
+
+ WriteIntCommon(buf, pRect->top, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "right= ";
+
+ WriteIntCommon(buf, pRect->right, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "bottom= ";
+
+ WriteIntCommon(buf, pRect->bottom, FALSE);
+
+ buf << pscStructSuffix;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteSIZE
+//
+// Synopsis: Prints out a SIZE structure
+//
+// Arguments: [buf] - text buffer to print text to
+// [pSIZE] - pointer to SIZE structure
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteSIZE(CTextBufferA& buf, SIZE *pSize)
+{
+ buf << pscStructPrefix;
+
+ buf << "cx= ";
+
+ WriteIntCommon(buf, pSize->cx, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "cy= ";
+
+ WriteIntCommon(buf, pSize->cy, FALSE);
+
+ buf << pscStructSuffix;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteLOGPALETTE
+//
+// Synopsis: Prints out a LOGPALETTE structure
+//
+// Arguments: [buf] - text buffer to print text to
+// [pLOGPALETTE] - pointer to LOGPALETTE structure
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteLOGPALETTE(CTextBufferA& buf, LOGPALETTE *pPal)
+{
+ buf << pscStructPrefix;
+
+ buf << "palVersion= ";
+
+ WriteHexCommon(buf, pPal->palVersion, TRUE);
+
+ buf << pscStructDelim;
+
+ buf << "palNumEntries= ";
+
+ WriteIntCommon(buf, pPal->palNumEntries, TRUE);
+
+ buf << pscStructDelim;
+
+ buf << "palPalEntry[]= ";
+
+ WritePointerCommon(buf, pPal->palPalEntry, FALSE, FALSE, FALSE);
+
+ buf << pscStructSuffix;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WritePOINT
+//
+// Synopsis: Prints out a POINT structure
+//
+// Arguments: [buf] - text buffer to print text to
+// [pPOINT] - pointer to POINT structure
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WritePOINT(CTextBufferA& buf, POINT *pPoint)
+{
+ buf << pscStructPrefix;
+
+ buf << "x= ";
+
+ WriteIntCommon(buf, pPoint->x, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "y= ";
+
+ WriteIntCommon(buf, pPoint->y, FALSE);
+
+ buf << pscStructSuffix;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteMSG
+//
+// Synopsis: Prints out a MSG structure
+//
+// Arguments: [buf] - text buffer to print text to
+// [pMSG] - pointer to MSG structure
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteMSG(CTextBufferA& buf, MSG *pMsg)
+{
+ buf << pscStructPrefix;
+
+ buf << "hwnd= ";
+
+ WriteHexCommon(buf, (ULONG) pMsg->hwnd, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "message= ";
+
+ WriteIntCommon(buf, pMsg->message, TRUE);
+
+ buf << pscStructDelim;
+
+ buf << "wParam= ";
+
+ WriteHexCommon(buf, pMsg->wParam, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "lParam= ";
+
+ WriteHexCommon(buf, pMsg->lParam, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "time= ";
+
+ WriteIntCommon(buf, pMsg->time, TRUE);
+
+ buf << pscStructDelim;
+
+ buf << "pt= ";
+
+ WritePOINT(buf, &(pMsg->pt));
+
+ buf << pscStructSuffix;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteTYMED
+//
+// Synopsis: Prints out a TYMED enumeration
+//
+// Arguments: [buf] - text buffer to print text to
+// [tymed] - TYMED value
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteTYMED(CTextBufferA &buf, DWORD tymed)
+{
+ switch(tymed)
+ {
+ case TYMED_NULL:
+ buf << "TYMED_NULL";
+ break;
+
+ case TYMED_GDI:
+ buf << "TYMED_GDI";
+ break;
+
+ case TYMED_MFPICT:
+ buf << "TYMED_MFPICT";
+ break;
+
+ case TYMED_ENHMF:
+ buf << "TYMED_ENHMF";
+ break;
+
+ case TYMED_HGLOBAL:
+ buf << "TYMED_HGLOBAL";
+ break;
+
+ case TYMED_FILE:
+ buf << "TYMED_FILE";
+ break;
+
+ case TYMED_ISTREAM:
+ buf << "TYMED_ISTREAM";
+ break;
+
+ case TYMED_ISTORAGE:
+ buf << "TYMED_ISTORAGE";
+ break;
+
+ default:
+ {
+ char temp[TEMP_SIZE];
+
+ _ultoa(tymed, temp, 10);
+
+ buf << temp;
+ }
+ break;
+ } // switch
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteSTGMEDIUM
+//
+// Synopsis: Prints out a STGMEDIUM structure
+//
+// Arguments: [buf] - text buffer to print text to
+// [pSTGMEDIUM] - pointer to STGMEDIUM structure
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteSTGMEDIUM(CTextBufferA& buf, STGMEDIUM *pStg)
+{
+ buf << pscStructPrefix;
+
+ buf << "tymed= ";
+
+ WriteTYMED(buf, pStg->tymed);
+
+ buf << pscStructDelim;
+
+ switch(pStg->tymed)
+ {
+ case TYMED_GDI:
+ buf << "hBitmap= ";
+ WriteHexCommon(buf, (ULONG) pStg->hBitmap, FALSE);
+ break;
+
+ case TYMED_MFPICT:
+ buf << "hMetaFilePict= ";
+ WriteHexCommon(buf, (ULONG) pStg->hMetaFilePict, FALSE);
+ break;
+
+ case TYMED_ENHMF:
+ buf << "hEnhMetaFile= ";
+ WriteHexCommon(buf, (ULONG) pStg->hEnhMetaFile, FALSE);
+ break;
+
+ case TYMED_HGLOBAL:
+ buf << "hGlobal= ";
+ WriteHexCommon(buf, (ULONG) pStg->hGlobal, FALSE);
+ break;
+
+ case TYMED_FILE:
+ buf << "lpszFileName= ";
+ WriteWideStringCommon(buf, pStg->lpszFileName, TRUE);
+ break;
+
+ case TYMED_ISTREAM:
+ buf << "pstm= ";
+ WritePointerCommon(buf, (void *) pStg->pstm, FALSE, FALSE, FALSE);
+ break;
+
+ case TYMED_ISTORAGE:
+ buf << "pstg= ";
+ WritePointerCommon(buf, (void *) pStg->pstg, FALSE, FALSE, FALSE);
+ break;
+
+ default:
+ buf << "?= ????????";
+ break;
+ } // switch
+
+ buf << pscStructDelim;
+
+ buf << "pUnkForRelease= ";
+
+ WritePointerCommon(buf, (void *) pStg->pUnkForRelease, FALSE, FALSE, FALSE);
+
+ buf << pscStructSuffix;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteFORMATETC
+//
+// Synopsis: Prints out a FORMATETC structure
+//
+// Arguments: [buf] - text buffer to print text to
+// [pFORMATETC] - pointer to FORMATETC structure
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteFORMATETC(CTextBufferA& buf, FORMATETC *pETC)
+{
+ buf << pscStructPrefix;
+
+ // TODO: write out enum?
+ buf << "cfFormat= ";
+
+ if (NULL == pETC)
+ {
+ buf << "NULL";
+ }
+ else
+ {
+ WriteIntCommon(buf, pETC->cfFormat, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "ptd= ";
+
+ WritePointerCommon(buf, (void *) pETC->ptd, FALSE, FALSE, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "dwAspect= ";
+
+ WriteIntCommon(buf, pETC->dwAspect, TRUE);
+
+ buf << pscStructDelim;
+
+ buf << "lindex= ";
+
+ WriteIntCommon(buf, pETC->lindex, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "tymed= ";
+
+ WriteTYMED(buf, pETC->tymed);
+ }
+
+ buf << pscStructSuffix;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteDVTARGETDEVICE
+//
+// Synopsis: Prints out a DVTARGETDEVICE structure
+//
+// Arguments: [buf] - text buffer to print text to
+// [pDVTARGETDEVICE] - pointer to DVTARGETDEVICE structure
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteDVTARGETDEVICE(CTextBufferA& buf, DVTARGETDEVICE *ptd)
+{
+ buf << pscStructPrefix;
+
+ buf << "tdSize= ";
+
+ WriteIntCommon(buf, ptd->tdSize, TRUE);
+
+ buf << pscStructDelim;
+
+ if(ptd->tdDriverNameOffset != 0)
+ {
+ buf << "tdDriverName= ";
+
+ WriteStringCommon(buf, (const char *) (((BYTE *)ptd)+ptd->tdDriverNameOffset), TRUE);
+ }
+ else
+ {
+ buf << "tdDriverNameOffset= 0";
+ }
+
+ buf << pscStructDelim;
+
+ if(ptd->tdDeviceNameOffset != 0)
+ {
+ buf << "tdDeviceName= ";
+
+ WriteStringCommon(buf, (const char *) (((BYTE *)ptd)+ptd->tdDeviceNameOffset), TRUE);
+ }
+ else
+ {
+ buf << "tdDeviceNameOffset= 0";
+ }
+
+ buf << pscStructDelim;
+
+ if(ptd->tdPortNameOffset != 0)
+ {
+ buf << "tdPortName= ";
+
+ WriteStringCommon(buf, (const char *) (((BYTE *)ptd)+ptd->tdPortNameOffset), TRUE);
+ }
+ else
+ {
+ buf << "tdPortNameOffset= 0";
+ }
+
+
+ buf << pscStructDelim;
+
+ if(ptd->tdExtDevmodeOffset != 0)
+ {
+ buf << "&tdExtDevmode= ";
+
+ WritePointerCommon(buf, (void *) (((BYTE *)ptd)+ptd->tdExtDevmodeOffset), FALSE, FALSE, FALSE);
+ }
+ else
+ {
+ buf << "tdExtDevmodeOffset= 0";
+ }
+
+ buf << pscStructSuffix;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteBIND_OPTS
+//
+// Synopsis: Prints out a BIND_OPTS structure
+//
+// Arguments: [buf] - text buffer to print text to
+// [pBIND_OPTS] - pointer to BIND_OPTS structure
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteBIND_OPTS(CTextBufferA& buf, BIND_OPTS *pOpts)
+{
+ buf << pscStructPrefix;
+
+ buf << "cbStruct= ";
+
+ WriteIntCommon(buf, pOpts->cbStruct, TRUE);
+
+ buf << pscStructDelim;
+
+ buf << "grfFlags= ";
+
+ WriteHexCommon(buf, pOpts->grfFlags, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "grfMode= ";
+
+ WriteHexCommon(buf, pOpts->grfMode, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "dwTickCountDeadLine= ";
+
+ WriteIntCommon(buf, pOpts->dwTickCountDeadline, TRUE);
+
+ buf << pscStructSuffix;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteSTATSTG
+//
+// Synopsis: Prints out a STATSTG structure
+//
+// Arguments: [buf] - text buffer to print text to
+// [pSTATSTG] - pointer to STATSTG structure
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteSTATSTG(CTextBufferA& buf, STATSTG *pStat)
+{
+ buf << pscStructPrefix;
+
+ buf << "pwcsName= ";
+
+ WriteWideStringCommon(buf, pStat->pwcsName, TRUE);
+
+ buf << pscStructDelim;
+
+ buf << "type= ";
+
+ WriteHexCommon(buf, pStat->type, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "cbSize= ";
+
+ WriteLargeCommon(buf, (__int64 *) &(pStat->cbSize), TRUE);
+
+ buf << pscStructDelim;
+
+ buf << "mtime= ";
+
+ WriteFILETIME(buf, &(pStat->mtime));
+
+ buf << pscStructDelim;
+
+ buf << "ctime= ";
+
+ WriteFILETIME(buf, &(pStat->ctime));
+
+ buf << pscStructDelim;
+
+ buf << "atime= ";
+
+ WriteFILETIME(buf, &(pStat->atime));
+
+ buf << pscStructDelim;
+
+ buf << "grfMode= ";
+
+ WriteHexCommon(buf, pStat->grfMode, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "grfLocksSupported= ";
+
+ WriteHexCommon(buf, pStat->grfLocksSupported, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "clsid= ";
+
+ WriteGUIDCommon(buf, (const GUID *) &(pStat->clsid));
+
+ buf << pscStructDelim;
+
+ buf << "grfStateBits= ";
+
+ WriteHexCommon(buf, pStat->grfStateBits, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "Reserved= ";
+
+ WriteHexCommon(buf, pStat->reserved, FALSE);
+
+ buf << pscStructSuffix;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteOLEINPLACEFRAMEINFO
+//
+// Synopsis: Prints out a OLEINPLACEFRAMEINFO structure
+//
+// Arguments: [buf] - text buffer to print text to
+// [pOLEINPLACEFRAMEINFO] - pointer to OLEINPLACEFRAMEINFO structure
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteOLEINPLACEFRAMEINFO(CTextBufferA& buf, OLEINPLACEFRAMEINFO *pInfo)
+{
+ buf << pscStructPrefix;
+
+ buf << "cb= ";
+
+ WriteIntCommon(buf, pInfo->cb, TRUE);
+
+ buf << pscStructDelim;
+
+ buf << "fMDIApp= ";
+
+ WriteBoolCommon(buf, pInfo->fMDIApp, TRUE);
+
+ buf << pscStructDelim;
+
+ buf << "hwndFrame= ";
+
+ WriteHexCommon(buf, (ULONG) pInfo->hwndFrame, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "haccel= ";
+
+ WriteHexCommon(buf, (ULONG) pInfo->haccel, FALSE);
+
+ buf << pscStructDelim,
+
+ buf << "cAccelEntries= ";
+
+ WriteIntCommon(buf, pInfo->cAccelEntries, TRUE);
+
+ buf << pscStructSuffix;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteOLEMENUGROUPWIDTHS
+//
+// Synopsis: Prints out a OLEMENUGROUPWIDTHS structure
+//
+// Arguments: [buf] - text buffer to print text to
+// [pOLEMENUGROUPWIDTHS] - pointer to OLEMENUGROUPWIDTHS structure
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteOLEMENUGROUPWIDTHS(CTextBufferA& buf, OLEMENUGROUPWIDTHS *pWidths)
+{
+ buf << pscStructPrefix;
+
+ for(int i = 0; i < 5; i++)
+ {
+ WriteIntCommon(buf, pWidths->width[i], FALSE);
+
+ buf << pscStructDelim;
+ }
+
+ WriteIntCommon(buf, pWidths->width[5], FALSE);
+
+ buf << pscStructSuffix;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteINTERFACEINFO
+//
+// Synopsis: Prints out a INTERFACEINFO structure
+//
+// Arguments: [buf] - text buffer to print text to
+// [pINTERFACEINFO] - pointer to INTERFACEINFO structure
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void WriteINTERFACEINFO(CTextBufferA &buf, INTERFACEINFO *pInfo)
+{
+ buf << pscStructPrefix;
+
+ buf << "pUnk= ";
+
+ WritePointerCommon(buf, pInfo->pUnk, FALSE, FALSE, FALSE);
+
+ buf << pscStructDelim;
+
+ buf << "iid= ";
+
+ WriteGUIDCommon(buf, (const GUID *) &(pInfo->iid));
+
+ buf << pscStructDelim;
+
+ buf << "wMethod= ";
+
+ WriteIntCommon(buf, pInfo->wMethod, TRUE);
+
+ buf << pscStructSuffix;
+}
+
+#endif // DBG==1
diff --git a/private/ole32/common/outfuncs.c b/private/ole32/common/outfuncs.c
new file mode 100644
index 000000000..26d1938b7
--- /dev/null
+++ b/private/ole32/common/outfuncs.c
@@ -0,0 +1,323 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: outfuncs.cxx
+//
+// Contents: functions for log/trace output
+//
+// Functions: AddOutputFunction
+// DelOutputFunction
+// CallOutputFunctions
+//
+// History: 09-Jan-96 murthys Created
+//
+//----------------------------------------------------------------------------
+#include <windows.h>
+#include <stdarg.h>
+#include <tchar.h>
+#if DBG==1
+#include "outfuncs.h"
+
+// *** Global Data ***
+static StringOutFunc debugscrfn = (StringOutFunc)OutputDebugStringA;
+StringOutFunc gpfunc[BUFFER_MAX_FUNCTIONS] = {
+ (StringOutFunc)OutputDebugStringA,
+ NULL
+ };
+HANDLE ghLogFile = INVALID_HANDLE_VALUE;
+CRITICAL_SECTION g_LogFileCS;
+
+//+---------------------------------------------------------------------------
+//
+// Function: AddOutputFunction
+//
+// Synopsis:
+//
+// Arguments: [pfunc] --
+//
+// Returns:
+//
+// History: 09-Jan-96 murthys Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void AddOutputFunction(StringOutFunc pfunc)
+{
+ int i, at = -1;
+
+ for (i = 0; i < BUFFER_MAX_FUNCTIONS; i++)
+ {
+ if ((at == -1) && (gpfunc[i] == NULL))
+ {
+ at = i; // Insert it here
+ }
+ else
+ {
+ if (gpfunc[i] == pfunc) // check for dups
+ {
+ return;
+ }
+ }
+ }
+ if (at != -1)
+ {
+ gpfunc[at] = pfunc;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DelOutputFunction
+//
+// Synopsis:
+//
+// Arguments: [pfunc]
+//
+// Returns:
+//
+// History: 09-Jan-96 murthys Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void DelOutputFunction(StringOutFunc pfunc)
+{
+ int i;
+
+ for (i = 0; i < BUFFER_MAX_FUNCTIONS; i++)
+ {
+ if (gpfunc[i] == pfunc)
+ {
+ gpfunc[i] = NULL;
+ }
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CallOutputFunctions
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: 09-Jan-96 murthys Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void CallOutputFunctions(const char *buffer)
+{
+ int i;
+
+ for (i = 0; i < BUFFER_MAX_FUNCTIONS; i++)
+ {
+ if (gpfunc[i] != NULL)
+ {
+ gpfunc[i](buffer);
+ }
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteToDebugScreen
+//
+// Synopsis:
+//
+// Arguments: [flag] - TRUE/FALSE to turn ON/OFF
+//
+// Returns:
+//
+// History: 09-Jan-96 murthys Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void WriteToDebugScreen(BOOL flag)
+{
+ if (flag)
+ {
+ AddOutputFunction(debugscrfn);
+ }
+ else
+ {
+ DelOutputFunction(debugscrfn);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteToLogFile
+//
+// Synopsis:
+//
+// Arguments: [logfile] - path of file to write to
+//
+// Returns:
+//
+// History: 09-Jan-96 murthys Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void WriteToLogFile(LPCTSTR lpfn)
+{
+ EnterCriticalSection(&g_LogFileCS);
+
+ if (ghLogFile != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(ghLogFile);
+ DelOutputFunction(OutputLogFileA);
+ ghLogFile = INVALID_HANDLE_VALUE;
+ }
+ if ((lpfn) && (lpfn[0] != _TEXT('\0')))
+ {
+ SECURITY_ATTRIBUTES sattr;
+
+ sattr.nLength = sizeof(sattr);
+ sattr.lpSecurityDescriptor = NULL;
+ sattr.bInheritHandle = FALSE;
+
+#ifdef _CHICAGO_
+ ghLogFile = CreateFileA(lpfn, GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ &sattr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+#else
+ ghLogFile = CreateFile(lpfn, GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ &sattr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+#endif // _CHICAGO_
+ if (ghLogFile == INVALID_HANDLE_VALUE)
+ {
+ OutputDebugStringA("OLE (WriteToLogFile):Unable to open log file!\n");
+ }
+ else
+ {
+ AddOutputFunction(OutputLogFileA);
+ }
+ }
+
+ LeaveCriticalSection(&g_LogFileCS);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OutputLogFileA
+//
+// Synopsis:
+//
+// Arguments: [buf] - NULL terminated ANSI string to write
+//
+// Returns:
+//
+// History: 09-Jan-96 murthys Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void OutputLogFileA(const char *buf)
+{
+ DWORD dwtowrite = strlen(buf);
+ DWORD dwwritten;
+ LONG loffhigh = 0, lofflow;
+
+ EnterCriticalSection(&g_LogFileCS);
+ // Goto EOF, Lock, Write and Unlock
+ lofflow = (LONG) SetFilePointer(ghLogFile, 0, &loffhigh, FILE_END);
+ LockFile(ghLogFile, lofflow, loffhigh, dwtowrite, 0);
+ WriteFile(ghLogFile, buf, dwtowrite, &dwwritten, NULL);
+ UnlockFile(ghLogFile, lofflow, loffhigh, dwtowrite, 0);
+ LeaveCriticalSection(&g_LogFileCS);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OpenDebugSinks()
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns:
+//
+// History: 26-Jan-96 murthys Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void OpenDebugSinks()
+{
+ // Get LogFile name
+ char tmpstr[MAX_PATH];
+ DWORD cbtmpstr = sizeof(tmpstr);
+ LPTSTR lptstr;
+
+ InitializeCriticalSection(&g_LogFileCS);
+ GetProfileStringA("CairOLE InfoLevels", // section
+ "LogFile", // key
+ "", // default value
+ tmpstr, // return buffer
+ cbtmpstr);
+ if (tmpstr[0] != '\0')
+ {
+#ifdef _CHICAGO_
+ lptstr = tmpstr;
+
+ WriteToLogFile(lptstr);
+#else
+ // convert ansi to unicode
+ WCHAR wtmpstr[MAX_PATH];
+
+ lptstr = wtmpstr;
+ if (MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, tmpstr, -1, wtmpstr, MAX_PATH))
+ {
+ WriteToLogFile(lptstr);
+ }
+ else
+ {
+ OutputDebugStringA("OLE32: MultiByteToWideChar failed for logfile!\n");
+ }
+#endif
+ }
+
+ // See if Debug Screen should be turned off
+ GetProfileStringA("CairOLE InfoLevels", // section
+ "DebugScreen", // key
+ "Yes", // default value
+ tmpstr, // return buffer
+ cbtmpstr);
+ if ((tmpstr[0] == 'n') || (tmpstr[0] == 'N'))
+ {
+ WriteToDebugScreen(FALSE); // turn off output to debugger screen
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CloseDebugSinks()
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns:
+//
+// History: 26-Jan-96 murthys Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void CloseDebugSinks()
+{
+ // close log file (if any)
+ WriteToLogFile(NULL);
+
+ DeleteCriticalSection(&g_LogFileCS);
+}
+#endif // DBG == 1
diff --git a/private/ole32/common/outfuncs.h b/private/ole32/common/outfuncs.h
new file mode 100644
index 000000000..5055ec499
--- /dev/null
+++ b/private/ole32/common/outfuncs.h
@@ -0,0 +1,25 @@
+#ifndef __OUTFUNCS_H__
+#define __OUTFUNCS_H__
+// Array of callback functions which will be called to print buffer
+#define BUFFER_MAX_FUNCTIONS 5
+
+typedef VOID (*StringOutFunc) (const char *);
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+void AddOutputFunction(StringOutFunc pfunc);
+void DelOutputFunction(StringOutFunc pfunc);
+void CallOutputFunctions(const char *buffer);
+void OutputLogFileA(const char *buf);
+void WriteToDebugScreen(BOOL flag);
+void WriteToLogFile(LPCTSTR lpfn);
+void OpenDebugSinks();
+void CloseDebugSinks();
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // __OUTFUNCS_H__
diff --git a/private/ole32/common/output.c b/private/ole32/common/output.c
new file mode 100644
index 000000000..5e4233282
--- /dev/null
+++ b/private/ole32/common/output.c
@@ -0,0 +1,964 @@
+/***
+*output.c - printf style output to a struct w4io
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the code that does all the work for the
+* printf family of functions. It should not be called directly, only
+* by the *printf functions. We don't make any assumtions about the
+* sizes of ints, longs, shorts, or long doubles, but if types do overlap, we
+* also try to be efficient. We do assume that pointers are the same size
+* as either ints or longs.
+*
+*Revision History:
+* 06-01-89 PHG Module created
+* 08-28-89 JCR Added cast to get rid of warning (no object changes)
+* 02-15-90 GJF Fixed copyright
+* 10-03-90 WHB Defined LOCAL(x) to "static x" for local procedures
+* 06-05-95 SVA Added support for printing GUIDs.
+*
+*******************************************************************************/
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <stdarg.h>
+#include "wchar.h"
+#include "w4io.h"
+
+
+/* this macro defines a function which is private and as fast as possible: */
+/* for example, in C 6.0, it might be static _fastcall <type>. */
+#define LOCAL(x) static x // 100390--WHB
+
+#define NOFLOATS // Win 4 doesn't need floating point
+
+/* int/long/short/pointer sizes */
+
+/* the following should be set depending on the sizes of various types */
+// FLAT or LARGE model is assumed
+#ifdef FLAT
+# define LONG_IS_INT 1 /* 1 means long is same size as int */
+# define SHORT_IS_INT 0 /* 1 means short is same size as int */
+# define PTR_IS_INT 1 /* 1 means ptr is same size as int */
+# define PTR_IS_LONG 0 /* 1 means ptr is same size as long */
+#else // LARGE model
+# define LONG_IS_INT 0 /* 1 means long is same size as int */
+# define SHORT_IS_INT 1 /* 1 means short is same size as int */
+# define PTR_IS_INT 0 /* 1 means ptr is same size as int */
+# define PTR_IS_LONG 1 /* 1 means ptr is same size as long */
+#endif
+#define LONGDOUBLE_IS_DOUBLE 0 /* 1 means long double is same as double */
+
+#if LONG_IS_INT
+ #define get_long_arg(x) (long)get_int_arg(x)
+#endif
+
+#if PTR_IS_INT
+ #define get_ptr_arg(x) (void *)get_int_arg(x)
+#elif PTR_IS_LONG
+ #define get_ptr_arg(x) (void *)get_long_arg(x)
+#else
+ #error Size of pointer must be same as size of int or long
+#endif
+
+#ifndef NOFLOATS
+/* These are "fake" double and long doubles to fool the compiler,
+ so we don't drag in floating point. */
+typedef struct {
+ char x[sizeof(double)];
+} DOUBLE;
+typedef struct {
+ char x[sizeof(long double)];
+} LONGDOUBLE;
+#endif
+
+
+/* CONSTANTS */
+
+//#define BUFFERSIZE CVTBUFSIZE /* buffer size for maximum double conv */
+#define BUFFERSIZE 20
+
+/* flag definitions */
+#define FL_SIGN 0x0001 /* put plus or minus in front */
+#define FL_SIGNSP 0x0002 /* put space or minus in front */
+#define FL_LEFT 0x0004 /* left justify */
+#define FL_LEADZERO 0x0008 /* pad with leading zeros */
+#define FL_LONG 0x0010 /* long value given */
+#define FL_SHORT 0x0020 /* short value given */
+#define FL_SIGNED 0x0040 /* signed data given */
+#define FL_ALTERNATE 0x0080 /* alternate form requested */
+#define FL_NEGATIVE 0x0100 /* value is negative */
+#define FL_FORCEOCTAL 0x0200 /* force leading '0' for octals */
+#define FL_LONGDOUBLE 0x0400 /* long double value given */
+#define FL_WIDE 0x0800 /* wide character/string given */
+
+/* state definitions */
+enum STATE {
+ ST_NORMAL, /* normal state; outputting literal chars */
+ ST_PERCENT, /* just read '%' */
+ ST_FLAG, /* just read flag character */
+ ST_WIDTH, /* just read width specifier */
+ ST_DOT, /* just read '.' */
+ ST_PRECIS, /* just read precision specifier */
+ ST_SIZE, /* just read size specifier */
+ ST_TYPE /* just read type specifier */
+};
+#define NUMSTATES (ST_TYPE + 1)
+
+/* character type values */
+enum CHARTYPE {
+ CH_OTHER, /* character with no special meaning */
+ CH_PERCENT, /* '%' */
+ CH_DOT, /* '.' */
+ CH_STAR, /* '*' */
+ CH_ZERO, /* '0' */
+ CH_DIGIT, /* '1'..'9' */
+ CH_FLAG, /* ' ', '+', '-', '#' */
+ CH_SIZE, /* 'h', 'l', 'L', 'N', 'F' */
+ CH_TYPE /* type specifying character */
+};
+
+/* static data (read only, since we are re-entrant) */
+char *nullstring = "(null)"; /* string to print on null ptr */
+
+/* The state table. This table is actually two tables combined into one. */
+/* The lower nybble of each byte gives the character class of any */
+/* character; while the uper nybble of the byte gives the next state */
+/* to enter. See the macros below the table for details. */
+/* */
+/* The table is generated by maketab.c -- use the maketab program to make */
+/* changes. */
+
+/* Brief description of the table, since I can't find maketab.c - t-stevan */
+/* Each entry in form 0xYZ. Here Z is a character class used in the macro */
+/* find_char_class defined below. The character classes are defined in the */
+/* CHARTYPE enum. For example, 'I' maps to CH_TYPE. To find a particular entry */
+/* Subtract the ASCI value for the space char from the character, and that is */
+/* the index to look up. The Y value is holds state transition information. */
+/* It is used in the macro find_next_state. */
+static char lookuptable[] = {
+ 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00,
+ 0x10, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x10,
+ 0x04, 0x45, 0x45, 0x45, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x35, 0x30, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x28, 0x38, 0x50, 0x58, 0x07, 0x08,
+ 0x00, 0x38, 0x30, 0x30, 0x57, 0x50, 0x07, 0x00,
+ 0x00, 0x20, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00,
+ 0x00, 0x70, 0x70, 0x78, 0x78, 0x78, 0x78, 0x08,
+ 0x07, 0x08, 0x00, 0x00, 0x07, 0x00, 0x08, 0x08,
+ 0x08, 0x00, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07,
+ 0x08
+};
+
+#define find_char_class(c) \
+ ((c) < ' ' || (c) > 'x' ? \
+ CH_OTHER \
+ : \
+ lookuptable[(c)-' '] & 0xF)
+
+#define find_next_state(class, state) \
+ (lookuptable[(class) * NUMSTATES + (state)] >> 4)
+
+#if !LONG_IS_INT
+LOCAL(long) get_long_arg(va_list *pargptr);
+#endif
+LOCAL(int) get_int_arg(va_list *pargptr);
+LOCAL(void) writestring(char *string,
+ int len,
+ struct w4io *f,
+ int *pcchwritten,
+ int fwide);
+
+#ifndef NOFLOATS
+/* extern float convert routines */
+typedef int (* PFI)();
+extern PFI _cfltcvt_tab[5];
+#define _cfltcvt(a,b,c,d,e) (*_cfltcvt_tab[0])(a,b,c,d,e)
+#define _cropzeros(a) (*_cfltcvt_tab[1])(a)
+#define _fassign(a,b,c) (*_cfltcvt_tab[2])(a,b,c)
+#define _forcdecpt(a) (*_cfltcvt_tab[3])(a)
+#define _positive(a) (*_cfltcvt_tab[4])(a)
+#define _cldcvt(a,b,c,d,e) (*_cfltcvt_tab[5])(a,b,c,d,e)
+#endif
+
+/* Defines for printing out GUIDs */
+#ifndef GUID_DEFINED
+#define GUID_DEFINED
+ /* size is 16 */
+typedef struct _GUID
+ {
+ unsigned long Data1;
+ unsigned short Data2;
+ unsigned short Data3;
+ unsigned char Data4[ 8 ];
+ } GUID;
+
+#endif // !GUID_DEFINED
+
+#ifndef _REFGUID_DEFINED
+#define _REFGUID_DEFINED
+#define REFGUID const GUID * const
+#endif // !_REFGUID_DEFINED
+
+/* This is actually one less than the normal GUIDSTR_MAX */
+/* Because we don't tag on a NULL byte */
+#define OUTPUT_GUIDSTR_MAX (1+ 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 /* + 1 */)
+
+/* Make sure our buffer size is big enough to hold a GUID */
+#if BUFFERSIZE < OUTPUT_GUIDSTR_MAX
+#undef BUFFERSIZE
+#define BUFFERSIZE OUTPUT_GUIDSTR_MAX
+#endif
+
+/* Function used to write a GUID to a string */
+int StrFromGUID(REFGUID rguid, char * lpsz, int cbMax);
+
+/***
+*int w4iooutput(f, format, argptr)
+*
+*Purpose:
+* Output performs printf style output onto a stream. It is called by
+* printf/fprintf/sprintf/vprintf/vfprintf/vsprintf to so the dirty
+* work. In multi-thread situations, w4iooutput assumes that the given
+* stream is already locked.
+*
+* Algorithm:
+* The format string is parsed by using a finite state automaton
+* based on the current state and the current character read from
+* the format string. Thus, looping is on a per-character basis,
+* not a per conversion specifier basis. Once the format specififying
+* character is read, output is performed.
+*
+*Entry:
+* struct w4io *f - stream for output
+* char *format - printf style format string
+* va_list argptr - pointer to list of subsidiary arguments
+*
+*Exit:
+* Returns the number of characters written, or -1 if an output error
+* occurs.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _cdecl w4iooutput(struct w4io *f, const char *format, va_list argptr)
+{
+ int hexadd; /* offset to add to number to get 'a'..'f' */
+ char ch; /* character just read */
+ wchar_t wc; /* wide character temp */
+ wchar_t *pwc; /* wide character temp pointer */
+ int flags; /* flag word -- see #defines above for flag values */
+ enum STATE state; /* current state */
+ enum CHARTYPE chclass; /* class of current character */
+ int radix; /* current conversion radix */
+ int charsout; /* characters currently written so far, -1 = IO error */
+ int fldwidth; /* selected field with -- 0 means default */
+ int fwide;
+ int precision; /* selected precision -- -1 means default */
+ char prefix[2]; /* numeric prefix -- up to two characters */
+ int prefixlen; /* length of prefix -- 0 means no prefix */
+ int capexp; /* non-zero = 'E' exponent signifiet, zero = 'e' */
+ int no_output; /* non-zero = prodcue no output for this specifier */
+ char *text; /* pointer text to be printed, not zero terminated */
+ int textlen; /* length of the text to be printed */
+ char buffer[BUFFERSIZE]; /* buffer for conversions */
+
+ charsout = 0; /* no characters written yet */
+ state = ST_NORMAL; /* starting state */
+
+ /* main loop -- loop while format character exist and no I/O errors */
+ while ((ch = *format++) != '\0' && charsout >= 0) {
+ chclass = find_char_class(ch); /* find character class */
+ state = find_next_state(chclass, state); /* find next state */
+
+ /* execute code for each state */
+ switch (state) {
+
+ case ST_NORMAL:
+ /* normal state -- just write character */
+ f->writechar(ch, 1, f, &charsout);
+ break;
+
+ case ST_PERCENT:
+ /* set default value of conversion parameters */
+ prefixlen = fldwidth = no_output = capexp = 0;
+ flags = 0;
+ precision = -1;
+ fwide = 0;
+ break;
+
+ case ST_FLAG:
+ /* set flag based on which flag character */
+ switch (ch) {
+ case '-':
+ flags |= FL_LEFT; /* '-' => left justify */
+ break;
+ case '+':
+ flags |= FL_SIGN; /* '+' => force sign indicator */
+ break;
+ case ' ':
+ flags |= FL_SIGNSP; /* ' ' => force sign or space */
+ break;
+ case '#':
+ flags |= FL_ALTERNATE; /* '#' => alternate form */
+ break;
+ case '0':
+ flags |= FL_LEADZERO; /* '0' => pad with leading zeros */
+ break;
+ }
+ break;
+
+ case ST_WIDTH:
+ /* update width value */
+ if (ch == '*') {
+ /* get width from arg list */
+ fldwidth = get_int_arg(&argptr);
+ if (fldwidth < 0) {
+ /* ANSI says neg fld width means '-' flag and pos width */
+ flags |= FL_LEFT;
+ fldwidth = -fldwidth;
+ }
+ }
+ else {
+ /* add digit to current field width */
+ fldwidth = fldwidth * 10 + (ch - '0');
+ }
+ break;
+
+ case ST_DOT:
+ /* zero the precision, since dot with no number means 0
+ not default, according to ANSI */
+ precision = 0;
+ break;
+
+ case ST_PRECIS:
+ /* update precison value */
+ if (ch == '*') {
+ /* get precision from arg list */
+ precision = get_int_arg(&argptr);
+ if (precision < 0)
+ precision = -1; /* neg precision means default */
+ }
+ else {
+ /* add digit to current precision */
+ precision = precision * 10 + (ch - '0');
+ }
+ break;
+
+ case ST_SIZE:
+ /* just read a size specifier, set the flags based on it */
+ switch (ch) {
+#if !LONG_IS_INT
+ case 'l':
+ flags |= FL_LONG; /* 'l' => long int */
+ break;
+#endif
+
+#if !LONGDOUBLE_IS_DOUBLE
+ case 'L':
+ flags |= FL_LONGDOUBLE; /* 'L' => long double */
+ break;
+#endif
+
+#if !SHORT_IS_INT
+ case 'h':
+ flags |= FL_SHORT; /* 'h' => short int */
+ break;
+#endif
+ case 'w':
+ flags |= FL_WIDE; /* 'w' => wide character */
+ break;
+ case 't':
+#ifdef _UNICODE
+ flags |= FL_WIDE;
+#endif
+ break;
+
+ }
+ break;
+
+ case ST_TYPE:
+ /* we have finally read the actual type character, so we */
+ /* now format and "print" the output. We use a big switch */
+ /* statement that sets 'text' to point to the text that should */
+ /* be printed, and 'textlen' to the length of this text. */
+ /* Common code later on takes care of justifying it and */
+ /* other miscellaneous chores. Note that cases share code, */
+ /* in particular, all integer formatting is doen in one place. */
+ /* Look at those funky goto statements! */
+
+ switch (ch) {
+
+ case 'c': {
+ /* print a single character specified by int argument */
+ wc = (wchar_t) get_int_arg(&argptr); /* get char to print */
+ * (wchar_t *) buffer = wc;
+ text = buffer;
+ textlen = 1; /* print just a single character */
+ }
+ break;
+
+ case 'S': {
+ /* print a Counted String */
+
+ struct string {
+ short Length;
+ short MaximumLength;
+ char *Buffer;
+ } *pstr;
+
+ pstr = get_ptr_arg(&argptr);
+ if (pstr == NULL || pstr->Buffer == NULL) {
+ /* null ptr passed, use special string */
+ text = nullstring;
+ textlen = strlen(text);
+ flags &= ~FL_WIDE;
+ } else {
+ text = pstr->Buffer;
+ /* The length field is a count of bytes, not characters. */
+ if (flags & FL_WIDE)
+ textlen = pstr->Length / sizeof( wchar_t );
+ else
+ textlen = pstr->Length;
+ if (precision != -1)
+ textlen = min( textlen, precision );
+ }
+
+ }
+ break;
+
+ case 's': {
+ /* print a string -- */
+ /* ANSI rules on how much of string to print: */
+ /* all if precision is default, */
+ /* min(precision, length) if precision given. */
+ /* prints '(null)' if a null string is passed */
+
+ int i;
+ char *p; /* temps */
+
+ text = get_ptr_arg(&argptr);
+ if (text == NULL) {
+ /* null ptr passed, use special string */
+ text = nullstring;
+ flags &= ~FL_WIDE;
+ }
+
+ /* At this point it is tempting to use strlen(), but */
+ /* if a precision is specified, we're not allowed to */
+ /* scan past there, because there might be no null */
+ /* at all. Thus, we must do our own scan. */
+
+ i = (precision == -1) ? INT_MAX : precision;
+
+ /* scan for null upto i characters */
+ if (flags & FL_WIDE) {
+ pwc = (wchar_t *) text;
+ while (i-- && (wc = *pwc) && (wc & 0x00ff)) {
+ ++pwc;
+ if (wc & 0xff00) { // if high byte set,
+ break; // error will be indicated
+ }
+ }
+ textlen = pwc - (wchar_t *) text; /* length of string */
+ } else {
+ p = text;
+ while (i-- && *p) {
+ ++p;
+ }
+ textlen = p - text; /* length of the string */
+ }
+ }
+ break;
+
+ /* print a GUID */
+ case 'I':
+ {
+ void *p; /* temp */
+
+ p = get_ptr_arg(&argptr);
+
+ if (p == NULL)
+ {
+ /* null ptr passed, use special string */
+ text = nullstring;
+ textlen = strlen(nullstring);
+ }
+ else
+ {
+ textlen = StrFromGUID(p, buffer, BUFFERSIZE);
+ text = buffer;
+ }
+ }
+ break;
+
+ case 'n': {
+ /* write count of characters seen so far into */
+ /* short/int/long thru ptr read from args */
+
+ void *p; /* temp */
+
+ p = get_ptr_arg(&argptr);
+
+ /* store chars out into short/long/int depending on flags */
+#if !LONG_IS_INT
+ if (flags & FL_LONG)
+ *(long *)p = charsout;
+ else
+#endif
+
+#if !SHORT_IS_INT
+ if (flags & FL_SHORT)
+ *(short *)p = (short) charsout;
+ else
+#endif
+ *(int *)p = charsout;
+
+ no_output = 1; /* force no output */
+ }
+ break;
+
+#ifndef NOFLOATS
+ case 'E':
+ case 'G':
+ capexp = 1; /* capitalize exponent */
+ ch += 'a' - 'A'; /* convert format char to lower */
+ /* DROP THROUGH */
+ case 'e':
+ case 'f':
+ case 'g': {
+ /* floating point conversion -- we call cfltcvt routines */
+ /* to do the work for us. */
+ flags |= FL_SIGNED; /* floating point is signed conversion */
+ text = buffer; /* put result in buffer */
+ flags &= ~FL_WIDE; /* 8 bit string */
+
+ /* compute the precision value */
+ if (precision < 0)
+ precision = 6; /* default precision: 6 */
+ else if (precision == 0 && ch == 'g')
+ precision = 1; /* ANSI specified */
+
+#if !LONGDOUBLE_IS_DOUBLE
+ /* do the conversion */
+ if (flags & FL_LONGDOUBLE) {
+ _cldcvt(argptr, text, ch, precision, capexp);
+ va_arg(argptr, LONGDOUBLE);
+ }
+ else
+#endif
+ {
+ _cfltcvt(argptr, text, ch, precision, capexp);
+ va_arg(argptr, DOUBLE);
+ }
+
+ /* '#' and precision == 0 means force a decimal point */
+ if ((flags & FL_ALTERNATE) && precision == 0)
+ _forcdecpt(text);
+
+ /* 'g' format means crop zero unless '#' given */
+ if (ch == 'g' && !(flags & FL_ALTERNATE))
+ _cropzeros(text);
+
+ /* check if result was negative, save '-' for later */
+ /* and point to positive part (this is for '0' padding) */
+ if (*text == '-') {
+ flags |= FL_NEGATIVE;
+ ++text;
+ }
+
+ textlen = strlen(text); /* compute length of text */
+ }
+ break;
+#endif // NOFLOATS
+
+ case 'd':
+ case 'i':
+ /* signed decimal output */
+ flags |= FL_SIGNED;
+ radix = 10;
+ goto COMMON_INT;
+
+ case 'u':
+ radix = 10;
+ goto COMMON_INT;
+
+ case 'p':
+ /* write a pointer -- this is like an integer or long */
+ /* except we force precision to pad with zeros and */
+ /* output in big hex. */
+
+ precision = 2 * sizeof(void *); /* number of hex digits needed */
+#if !PTR_IS_INT
+ flags |= FL_LONG; /* assume we're converting a long */
+#endif
+ /* DROP THROUGH to hex formatting */
+
+ case 'C':
+ case 'X':
+ /* unsigned upper hex output */
+ hexadd = 'A' - '9' - 1; /* set hexadd for uppercase hex */
+ goto COMMON_HEX;
+
+ case 'x':
+ /* unsigned lower hex output */
+ hexadd = 'a' - '9' - 1; /* set hexadd for lowercase hex */
+ /* DROP THROUGH TO COMMON_HEX */
+
+ COMMON_HEX:
+ radix = 16;
+ if (flags & FL_ALTERNATE) {
+ /* alternate form means '0x' prefix */
+ prefix[0] = '0';
+ prefix[1] = (char)('x' - 'a' + '9' + 1 + hexadd); /* 'x' or 'X' */
+ prefixlen = 2;
+ }
+ goto COMMON_INT;
+
+ case 'o':
+ /* unsigned octal output */
+ radix = 8;
+ if (flags & FL_ALTERNATE) {
+ /* alternate form means force a leading 0 */
+ flags |= FL_FORCEOCTAL;
+ }
+ /* DROP THROUGH to COMMON_INT */
+
+ COMMON_INT: {
+ /* This is the general integer formatting routine. */
+ /* Basically, we get an argument, make it positive */
+ /* if necessary, and convert it according to the */
+ /* correct radix, setting text and textlen */
+ /* appropriately. */
+
+ unsigned long number; /* number to convert */
+ int digit; /* ascii value of digit */
+ long l; /* temp long value */
+
+ /* 1. read argument into l, sign extend as needed */
+#if !LONG_IS_INT
+ if (flags & FL_LONG)
+ l = get_long_arg(&argptr);
+ else
+#endif
+
+#if !SHORT_IS_INT
+ if (flags & FL_SHORT) {
+ if (flags & FL_SIGNED)
+ l = (short) get_int_arg(&argptr); /* sign extend */
+ else
+ l = (unsigned short) get_int_arg(&argptr); /* zero-extend*/
+ }
+ else
+#endif
+ {
+ if (flags & FL_SIGNED)
+ l = get_int_arg(&argptr); /* sign extend */
+ else
+ l = (unsigned int) get_int_arg(&argptr); /* zero-extend*/
+ }
+
+ /* 2. check for negative; copy into number */
+ if ( (flags & FL_SIGNED) && l < 0) {
+ number = -l;
+ flags |= FL_NEGATIVE; /* remember negative sign */
+ }
+ else {
+ number = l;
+ }
+
+ /* 3. check precision value for default; non-default */
+ /* turns off 0 flag, according to ANSI. */
+ if (precision < 0)
+ precision = 1; /* default precision */
+ else
+ flags &= ~FL_LEADZERO;
+
+ /* 4. Check if data is 0; if so, turn off hex prefix */
+ if (number == 0)
+ prefixlen = 0;
+
+ /* 5. Convert data to ASCII -- note if precision is zero */
+ /* and number is zero, we get no digits at all. */
+
+ text = &buffer[BUFFERSIZE-1]; // last digit at end of buffer
+ flags &= ~FL_WIDE; // 8 bit characters
+
+ while (precision-- > 0 || number != 0) {
+ digit = (int)(number % radix) + '0';
+ number /= radix; /* reduce number */
+ if (digit > '9') {
+ /* a hex digit, make it a letter */
+ digit += hexadd;
+ }
+ *text-- = (char)digit; /* store the digit */
+ }
+
+ textlen = (char *)&buffer[BUFFERSIZE-1] - text; /* compute length of number */
+ ++text; /* text points to first digit now */
+
+
+ /* 6. Force a leading zero if FORCEOCTAL flag set */
+ if ((flags & FL_FORCEOCTAL) && (text[0] != '0' || textlen == 0)) {
+ *--text = '0';
+ ++textlen; /* add a zero */
+ }
+ }
+ break;
+ }
+
+ /* At this point, we have done the specific conversion, and */
+ /* 'text' points to text to print; 'textlen' is length. Now we */
+ /* justify it, put on prefixes, leading zeros, and then */
+ /* print it. */
+
+ if (!no_output) {
+ int padding; /* amount of padding, negative means zero */
+
+ if (flags & FL_SIGNED) {
+ if (flags & FL_NEGATIVE) {
+ /* prefix is a '-' */
+ prefix[0] = '-';
+ prefixlen = 1;
+ }
+ else if (flags & FL_SIGN) {
+ /* prefix is '+' */
+ prefix[0] = '+';
+ prefixlen = 1;
+ }
+ else if (flags & FL_SIGNSP) {
+ /* prefix is ' ' */
+ prefix[0] = ' ';
+ prefixlen = 1;
+ }
+ }
+
+ /* calculate amount of padding -- might be negative, */
+ /* but this will just mean zero */
+ padding = fldwidth - textlen - prefixlen;
+
+ /* put out the padding, prefix, and text, in the correct order */
+
+ if (!(flags & (FL_LEFT | FL_LEADZERO))) {
+ /* pad on left with blanks */
+ f->writechar(' ', padding, f, &charsout);
+ }
+
+ /* write prefix */
+ writestring(prefix, prefixlen, f, &charsout, 0);
+
+ if ((flags & FL_LEADZERO) && !(flags & FL_LEFT)) {
+ /* write leading zeros */
+ f->writechar('0', padding, f, &charsout);
+ }
+
+ /* write text */
+ writestring(text, textlen, f, &charsout, flags & FL_WIDE);
+
+ if (flags & FL_LEFT) {
+ /* pad on right with blanks */
+ f->writechar(' ', padding, f, &charsout);
+ }
+
+ /* we're done! */
+ }
+ break;
+ }
+ }
+
+ return charsout; /* return value = number of characters written */
+}
+
+
+/***
+*int get_int_arg(va_list pargptr)
+*
+*Purpose:
+* Gets an int argument off the given argument list and updates *pargptr.
+*
+*Entry:
+* va_list pargptr - pointer to argument list; updated by function
+*
+*Exit:
+* Returns the integer argument read from the argument list.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+LOCAL(int) get_int_arg(va_list *pargptr)
+{
+ return va_arg(*pargptr, int);
+}
+
+/***
+*long get_long_arg(va_list pargptr)
+*
+*Purpose:
+* Gets an long argument off the given argument list and updates pargptr.
+*
+*Entry:
+* va_list pargptr - pointer to argument list; updated by function
+*
+*Exit:
+* Returns the long argument read from the argument list.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+#if !LONG_IS_INT
+LOCAL(long) get_long_arg(va_list *pargptr)
+{
+ return va_arg(*pargptr, long);
+}
+#endif
+
+
+
+/***
+*void writestring(char *string, int len, struct w4io *f, int *pcchwritten, int fwide)
+*
+*Purpose:
+* Writes a string of the given length to the given file. If no error occurs,
+* then *pcchwritten is incremented by len; otherwise, *pcchwritten is set
+* to -1. If len is negative, it is treated as zero.
+*
+*Entry:
+* char *string - string to write (NOT null-terminated)
+* int len - length of string
+* struct w4io *f - file to write to
+* int *pcchwritten - pointer to integer to update with total chars written
+* int fwide - wide character flag
+*
+*Exit:
+* No return value.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+LOCAL(void) writestring(
+ char *string,
+ int len,
+ struct w4io *f,
+ int *pcchwritten,
+ int fwide)
+{
+ wchar_t *pwc;
+
+ //printf("string: str=%.*s, len=%d, cch=%d, f=%d\n", len, string, len, *pcchwritten, fwide);
+ if (fwide) {
+ pwc = (wchar_t *) string;
+ while (len-- > 0) {
+ if (*pwc & 0xff00) {
+ f->writechar('^', 1, f, pcchwritten);
+ }
+ f->writechar((char) *pwc++, 1, f, pcchwritten);
+ }
+ } else {
+ while (len-- > 0) {
+ f->writechar(*string++, 1, f, pcchwritten);
+ }
+ }
+}
+
+
+const wchar_t a_wcDigits[] = L"0123456789ABCDEF";
+
+//+---------------------------------------------------------------------------
+//
+// Function: FormatHexNum
+//
+// Synopsis: Given a value, and a count of characters, translate
+// the value into a hex string. This is the ANSI version
+//
+// Arguments: [ulValue] -- Value to convert
+// [chChars] -- Number of characters to format
+// [pchStr] -- Pointer to output buffer
+//
+// Requires: pwcStr must be valid for chChars
+//
+// History: 5-31-95 t-stevan Copied and Modified for use in debug output function
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void FormatHexNum( unsigned long ulValue, unsigned long chChars, char *pchStr)
+{
+ while(chChars--)
+ {
+ pchStr[chChars] = (char) a_wcDigits[ulValue & 0xF];
+ ulValue = ulValue >> 4;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: StrFromGUID (private)
+//
+// Synopsis: Converts a GUID into a string (duh!)
+//
+// Arguments: [rguid] - the guid to convert
+// [lpszy] - buffer to hold the results
+// [cbMax] - sizeof the buffer
+//
+// Returns: amount of data copied to lpsz if successful
+// 0 if buffer too small.
+//
+//--------------------------------------------------------------------------
+
+int StrFromGUID(REFGUID rguid, char * lpsz, int cbMax) // internal
+{
+ if (cbMax < OUTPUT_GUIDSTR_MAX)
+ return 0;
+
+
+// Make the GUID into"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+
+ *lpsz++ = '{';
+ FormatHexNum( rguid->Data1, 8 , lpsz);
+ lpsz += 8;
+ *lpsz++ = '-';
+
+ FormatHexNum( rguid->Data2, 4 , lpsz);
+ lpsz += 4;
+ *lpsz++ = '-';
+
+ FormatHexNum( rguid->Data3, 4 , lpsz);
+ lpsz += 4;
+ *lpsz++ = '-';
+
+ FormatHexNum( rguid->Data4[0], 2 , lpsz);
+ lpsz += 2;
+ FormatHexNum( rguid->Data4[1], 2 , lpsz);
+ lpsz += 2;
+ *lpsz++ = '-';
+
+ FormatHexNum( rguid->Data4[2], 2 , lpsz);
+ lpsz += 2;
+ FormatHexNum( rguid->Data4[3], 2 , lpsz);
+ lpsz += 2;
+ FormatHexNum( rguid->Data4[4], 2 , lpsz);
+ lpsz += 2;
+ FormatHexNum( rguid->Data4[5], 2 , lpsz);
+ lpsz += 2;
+ FormatHexNum( rguid->Data4[6], 2 , lpsz);
+ lpsz += 2;
+ FormatHexNum( rguid->Data4[7], 2 , lpsz);
+ lpsz += 2;
+
+ *lpsz++ = '}';
+ /* We don't want to tag on a NULL char because we don't need to print one out *\
+ /* *lpsz = 0; */
+
+
+ return OUTPUT_GUIDSTR_MAX;
+}
+
+
diff --git a/private/ole32/common/printf.c b/private/ole32/common/printf.c
new file mode 100644
index 000000000..9d6f6403e
--- /dev/null
+++ b/private/ole32/common/printf.c
@@ -0,0 +1,17 @@
+/***
+*printf.c - print formatted to stdout
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4printf() - print formatted data to stdout
+* defines w4vprintf() - print formatted output to stdout, get data
+* from an argument ptr instead of explicit args.
+*******************************************************************************/
+
+#ifdef FLAT
+#include "dprintf.h" // function prototypes
+
+#define _W4PRINTF_
+#include "printf.h"
+#endif
diff --git a/private/ole32/common/printf.h b/private/ole32/common/printf.h
new file mode 100644
index 000000000..70cd44655
--- /dev/null
+++ b/private/ole32/common/printf.h
@@ -0,0 +1,248 @@
+/***
+*printf.h - print formatted
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4*printf() - print formatted data
+* defines w4v*printf() - print formatted output, get data from an
+* argument ptr instead of explicit args.
+*
+*Revision History:
+* 09-02-83 RN original sprintf
+* 06-17-85 TC rewrote to use new varargs macros, and to be vsprintf
+* 04-13-87 JCR added const to declaration
+* 11-07-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-13-88 JCR Fake _iob entry is now static so that other routines
+* can assume _iob entries are in DGROUP.
+* 08-25-88 GJF Define MAXSTR to be INT_MAX (from LIMITS.H).
+* 06-06-89 JCR 386 mthread support
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 WIN32
+* model). Also fixed copyright and indents.
+* 02-16-90 GJF Fixed copyright
+*
+*******************************************************************************/
+
+#include <windows.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <limits.h>
+#include "w4io.h"
+#ifdef _W4DPRINTF_
+#include "outfuncs.h"
+#endif
+
+#if defined(_W4PRINTF_)
+ static long fh;
+// extern long GetStdHandle(long);
+// extern void WriteFile(long fh, char *s, long cch, long * pcchret, long);
+# define _PRINTF_
+#elif defined(_W4DPRINTF_)
+# define _pwritechar _dwritechar
+# define _pflushbuf _dflushbuf
+# define w4printf w4dprintf
+# define w4vprintf w4vdprintf
+# define _PRINTF_
+#elif defined(_W4SPRINTF_)
+# define _pwritechar _swritechar
+# define w4printf w4sprintf
+# define w4vprintf w4vsprintf
+#elif defined(_W4WCSPRINTF_)
+# define _TCHAR_ wchar_t
+# define _PBUF_ pwcbuf
+# define _PSTART_ pwcstart
+# define w4printf w4wcsprintf
+# define w4vprintf w4vwcsprintf
+# define _pwritechar _wwritechar
+#else
+# error configuration problem
+#endif
+
+#ifndef _TCHAR_
+# define _TCHAR_ char
+# define _PBUF_ pchbuf
+# define _PSTART_ pchstart
+#endif
+
+
+#ifdef _PRINTF_
+# ifdef WIN32
+# undef OutputDebugString
+# define OutputDebugString OutputDebugStringA
+# else
+ extern void _pascal OutputDebugString(char *);
+# endif
+ int _cdecl _pflushbuf(struct w4io *f);
+# define SPR(a)
+# define MAXSTR 128
+#else
+# define SPR(a) a,
+# define MAXSTR INT_MAX
+#endif
+
+void _cdecl _pwritechar(int ch, int num, struct w4io *f, int *pcchwritten);
+int _cdecl w4vprintf(SPR(_TCHAR_ *string) const char *format, va_list arglist);
+
+
+/***
+*int w4printf(format, ...) - print formatted data
+*
+*Purpose:
+* Prints formatted data using the format string to
+* format data and getting as many arguments as called for
+* Sets up a w4io so file i/o operations can be used.
+* w4iooutput does the real work here
+*
+*Entry:
+* char *format - format string to control data format/number
+* of arguments followed by list of arguments, number and type
+* controlled by format string
+*
+*Exit:
+* returns number of characters written
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+int _cdecl
+w4printf(SPR(_TCHAR_ *string) const char *format, ...)
+/*
+ * 'PRINT', 'F'ormatted
+ */
+{
+ va_list arglist;
+
+ va_start(arglist, format);
+ return(w4vprintf(SPR(string) format, arglist));
+}
+
+
+/***
+*int w4vprintf(format, arglist) - print formatted data from arg ptr
+*
+*Purpose:
+* Prints formatted data, but gets data from an argument pointer.
+* Sets up a w4io so file i/o operations can be used, make string look
+* like a huge buffer to it, but _flsbuf will refuse to flush it if it
+* fills up. Appends '\0' to make it a true string.
+*
+* Multi-thread: (1) Since there is no stream, this routine must never try
+* to get the stream lock (i.e., there is no stream lock either). (2)
+* Also, since there is only one staticly allocated 'fake' iob, we must
+* lock/unlock to prevent collisions.
+*
+*Entry:
+* char *format - format string, describes format of data
+* va_list arglist - varargs argument pointer
+*
+*Exit:
+* returns number of characters written
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _cdecl
+w4vprintf(SPR(_TCHAR_ *string) const char *format, va_list arglist)
+/*
+ * 'V'ariable argument 'PRINT', 'F'ormatted
+ */
+{
+ struct w4io outfile;
+ register int retval;
+#ifdef _PRINTF_
+ char string[MAXSTR + 1]; // leave room for null termination
+#else
+ int dummy;
+#endif
+
+#ifdef _W4PRINTF_
+ long ldummy;
+
+ if (fh == 0 || fh == -1)
+ {
+ ldummy = -11; // C7 bug workaround
+ if ((fh = (long)GetStdHandle(ldummy)) == 0 || fh == -1)
+ {
+ OutputDebugString("GetStdHandle in " __FILE__ " failed\n");
+ return(-1);
+ }
+ }
+#endif
+
+ outfile._PBUF_ = outfile._PSTART_ = string;
+ outfile.cchleft = MAXSTR;
+ outfile.writechar = _pwritechar;
+
+ retval = w4iooutput(&outfile, format, arglist);
+
+#ifdef _PRINTF_
+ if (_pflushbuf(&outfile) == -1) {
+ return(-1);
+ }
+#else
+ _pwritechar('\0', 1, &outfile, &dummy);
+#endif
+ return(retval);
+}
+
+
+void _cdecl _pwritechar(int ch, int num, struct w4io *f, int *pcchwritten)
+{
+ //printf(" char: ch=%c, cnt=%d, cch=%d\n", ch, num, *pcchwritten);
+ while (num-- > 0) {
+#ifdef _PRINTF_
+ if (f->cchleft < 2 && _pflushbuf(f) == -1) {
+ *pcchwritten = -1;
+ return;
+ }
+#endif
+#ifdef _W4DPRINTF_
+# ifndef WIN32
+ if (ch == '\n')
+ {
+ *f->_PBUF_++ = '\r';
+ f->cchleft--;
+ (*pcchwritten)++;
+ }
+# endif
+#endif
+ *f->_PBUF_++ = (char) ch;
+ f->cchleft--;
+ (*pcchwritten)++;
+ }
+}
+
+
+#ifdef _PRINTF_
+int _cdecl _pflushbuf(struct w4io *f)
+{
+ int cch;
+
+ if (cch = (f->pchbuf - f->pchstart))
+ {
+#ifdef _W4DPRINTF_
+ *f->pchbuf = '\0'; // null terminate
+ CallOutputFunctions(f->pchstart); // funnel through outfuncs
+#else
+ long cchret;
+
+ //*f->pchbuf = '\0'; // null terminate
+ //printf("%d chars: \"%s\"\n", cch, f->pchstart);
+ WriteFile((HANDLE)fh, f->pchstart, cch, &cchret, 0);
+ if (cch != cchret)
+ {
+ OutputDebugString("WriteFile in " __FILE__ " failed\n");
+ return(-1);
+ }
+#endif
+ f->pchbuf -= cch; // reset pointer
+ f->cchleft += cch; // reset count
+ }
+ return(0);
+}
+#endif // _PRINTF_
diff --git a/private/ole32/common/proto.h b/private/ole32/common/proto.h
new file mode 100644
index 000000000..e87cf4e7c
--- /dev/null
+++ b/private/ole32/common/proto.h
@@ -0,0 +1,15 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: proto.h
+//
+// Contents: File used to spoof idl generated h files. Used by NT1x and
+// Chicago builds.
+//
+// History: 10-Nov-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+#include <ole2.h>
diff --git a/private/ole32/common/sprintf.c b/private/ole32/common/sprintf.c
new file mode 100644
index 000000000..8fa23b0f4
--- /dev/null
+++ b/private/ole32/common/sprintf.c
@@ -0,0 +1,13 @@
+/***
+*sprintf.c - print formatted to string
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4sprintf() - print formatted data to string
+* defines w4vsprintf() - print formatted output to a string, get data
+* from an argument ptr instead of explicit args.
+*******************************************************************************/
+
+#define _W4SPRINTF_
+#include "printf.h"
diff --git a/private/ole32/common/sym.hxx b/private/ole32/common/sym.hxx
new file mode 100644
index 000000000..80272b183
--- /dev/null
+++ b/private/ole32/common/sym.hxx
@@ -0,0 +1,128 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: sym.hxx
+//
+// Contents: A C++ wrapping of a subset of the interface of imagehlp.dll
+//
+// Classes: CSym
+//
+// History: 14-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+#ifndef __SYM_HXX__
+#define __SYM_HXX__
+
+#include <imagehlp.h>
+
+#define MAXNAMELENGTH 256
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSym
+//
+// Purpose: A C++ wrapping of a subset of the interface of imagehlp.dll
+//
+// Interface: CSym
+// ~CSym
+// GetSymNameFromAddr
+//
+// History: 14-Jul-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+class CSym
+{
+ public:
+ inline CSym();
+ inline ~CSym();
+
+ inline BOOL GetSymNameFromAddr(DWORD dwAddr, PDWORD pdwDisplacement, LPSTR lpname, DWORD dwmaxLength) const;
+
+ BOOL IsInitialized() const
+ { return m_fInit; }
+
+ private:
+ BOOL m_fInit;
+};
+
+// These functions are dynamically loaded from the imagehlp.dll
+BOOL OleSymInitialize(HANDLE hProcess, LPSTR UserSearchPath, BOOL fInvade);
+BOOL OleSymCleanup(HANDLE hProcess);
+BOOL OleSymGetSymFromAddr(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_SYMBOL pSym);
+BOOL OleSymUnDName(PIMAGEHLP_SYMBOL pSym, LPSTR lpname, DWORD dwmaxLength);
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSym::CSym
+//
+// Synopsis: Constructor
+//
+// Arguments: none
+//
+// History: 14-Jul-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+inline CSym::CSym()
+{
+ m_fInit = OleSymInitialize(GetCurrentProcess(), NULL, TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSym::~CSym
+//
+// Synopsis: Destructor
+//
+// Arguments: none
+//
+// History: 14-Jul-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+inline CSym::~CSym()
+{
+ if(m_fInit)
+ {
+ OleSymCleanup(GetCurrentProcess());
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSym::GetSymNameFromAddr
+//
+// Synopsis: Finds the symbol and displacement of a given address
+//
+// Arguments: [dwAddr] - the address to find the symbol for
+// [pdwDisplacement] - somewhere to store the displacement
+// [lpname] - buffer to store symbol name
+// [dwmaxLength] - size of buffer
+//
+// Returns: a pointer to the symbol name, or NULL if not successful
+//
+// History: 14-Jul-95 t-stevan Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CSym::GetSymNameFromAddr(DWORD dwAddr, PDWORD pdwDisplacement, LPSTR lpname, DWORD dwmaxLength) const
+{
+ if(m_fInit)
+ {
+ char dump[sizeof(IMAGEHLP_SYMBOL) + MAXNAMELENGTH];
+ PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL) &dump;
+
+ // Have to do this because size of sym is dynamically determined
+ pSym->SizeOfStruct = sizeof(dump);
+ pSym->MaxNameLength = MAXNAMELENGTH;
+
+ if (OleSymGetSymFromAddr(GetCurrentProcess(), dwAddr, pdwDisplacement, pSym))
+ {
+ OleSymUnDName(pSym, lpname, dwmaxLength);
+ return(TRUE);
+ }
+ }
+
+ return FALSE;
+}
+
+#endif // __SYM_HXX__
diff --git a/private/ole32/common/trace.cxx b/private/ole32/common/trace.cxx
new file mode 100644
index 000000000..8a28f2e74
--- /dev/null
+++ b/private/ole32/common/trace.cxx
@@ -0,0 +1,563 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: trace.cxx
+//
+// Contents: TraceInfo functions
+//
+// History: 14-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+#include <stdarg.h>
+#include <ole2int.h>
+#if DBG==1
+
+#ifdef FLAT
+#include <sem.hxx>
+#include <dllsem.hxx>
+#endif // FLAT
+
+#include "oleprint.hxx"
+#include "sym.hxx"
+
+// *** Global data ***
+DWORD g_dwInfoLevel = INF_OFF;
+extern CSym *g_pSym;
+extern char gPidString[];
+
+//+---------------------------------------------------------------------------
+//
+// Function: TraceInfoEnabled
+//
+// Synopsis: Checks our trace info level to see if output of
+// trace information is enabled
+//
+// Arguments: (none)
+//
+// Returns: > 0 if enabled, 0 if not
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+inline int TraceInfoEnabled()
+{
+ return g_dwInfoLevel & INF_BASE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TraceCmnEnabled
+//
+// Synopsis: Checks our trace info level to see if output of
+// cmn api information is enabled
+//
+// Arguments: (none)
+//
+// Returns: > 0 if enabled, 0 if not
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+inline int TraceCmnEnabled()
+{
+ return g_dwInfoLevel & INF_CMN;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SymInfoEnabled
+//
+// Synopsis: Checks our trace info level to see if output of
+// symbol information is enabled
+//
+// Arguments: (none)
+//
+// Returns: > 0 if enabled, 0 if not
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+inline int SymInfoEnabled()
+{
+ return g_dwInfoLevel & INF_SYM;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StructInfoEnabled
+//
+// Synopsis: Checks our trace info level to see if output of
+// expanded structures is enabled
+//
+// Arguments: (none)
+//
+// Returns: > 0 if enabled, 0 if not
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+inline int StructInfoEnabled()
+{
+ return g_dwInfoLevel & INF_STRUCT;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSIncTraceNestingLevel
+//
+// Synopsis: Returns the current nesting level, then increments it
+//
+// Returns: nesting level for OLETRACE
+//
+// History: 13-Jul-95 t-stevan Created
+//
+// Notes:
+//----------------------------------------------------------------------------
+
+inline LONG TLSIncTraceNestingLevel()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ return (tls->cTraceNestingLevel)++;
+ }
+
+ return 0;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSDecTraceNestingLevel
+//
+// Synopsis: Decrement and return nesting level
+//
+// Returns: nesting level for OLETRACE
+//
+// History: 13-Jul-95 t-stevan Created
+//
+// Notes:
+//----------------------------------------------------------------------------
+
+inline LONG TLSDecTraceNestingLevel()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ return --(tls->cTraceNestingLevel);
+ }
+
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: vdprintf
+//
+// Synopsis:
+//
+// Arguments: [char] --
+// [pszComp] --
+// [va_list] --
+// [pargs] --
+//
+// Returns:
+//
+// History: 11-22-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+#if 0 // BUGBUG: there are two copies of this in the sources
+#ifndef _CAIRO_
+STDAPI_(void) vdprintf(unsigned long ulCompMask,char const *pszComp,
+ char const *ppszfmt,va_list pargs)
+{
+ mxs.Request();
+ oleprintf(0, "", ppszfmt, pargs);
+ mxs.Release();
+}
+#endif //_CAIRO_
+#endif
+
+
+
+// *** Inline Functions
+//+---------------------------------------------------------------------------
+//
+// Function: IsAPIID
+//
+// Synopsis: Returns whether or not an 32-bit ID is a API ID
+//
+// Arguments: [dwID] - 32-bit ID
+//
+// Returns: TRUE if it is an API ID, FALSE otherwise
+//
+// History: 04-Aug-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+BOOL IsAPIID(DWORD dwID)
+{
+ return !(dwID>>16);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetNameFromAPIID
+//
+// Synopsis: Returns a pointer to a string containing the API name
+//
+// Arguments: [dwID] - API ID
+//
+// Returns: Pointer to a string
+//
+// History: 04-Aug-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+const char *GetNameFromAPIID(DWORD dwID)
+{
+ return (g_ppNameTables[dwID>>16])[dwID&0xffff];
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetNameFromOBJID
+//
+// Synopsis: Returns a pointer to a string containing the object/method name
+//
+// Arguments: [dwID] - 32-bit ID
+//
+// Returns: Pointer to a string
+//
+// History: 04-Aug-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+const char *GetNameFromOBJID(DWORD dwID, IUnknown *pUnk, char *pBuf)
+{
+ wsprintfA(pBuf, "%s(%x)->%s", g_pscInterfaceNames[dwID>>16], pUnk, (g_ppNameTables[dwID>>16])[dwID&0xffff]);
+
+ return pBuf;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: _oletracein
+//
+// Synopsis: Prints trace information for API/Method-entry
+//
+// Arguments: [dwID] - API/Method ID
+//
+// Returns: nothing
+//
+// History: 14-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void _oletracein(DWORD dwID, ...)
+{
+ const char *pscFormat;
+ va_list args;
+ int iNestingLevel;
+
+ va_start(args, dwID);
+
+ iNestingLevel = TLSIncTraceNestingLevel();
+
+ if(TraceInfoEnabled())
+ {
+ if(IsAPIID(dwID))
+ {
+ // This is an API
+ pscFormat = va_arg(args, const char*);
+
+ oleprintf(iNestingLevel,
+ GetNameFromAPIID(dwID), pscFormat, args);
+ }
+ else
+ {
+ IUnknown *pUnk;
+ char szTemp[128];
+
+ // This is an object/method call
+ pUnk = va_arg(args, IUnknown *);
+
+ pscFormat = va_arg(args, const char *);
+
+ oleprintf(iNestingLevel,
+ GetNameFromOBJID(dwID, pUnk, szTemp), pscFormat, args);
+ }
+ }
+
+ va_end(args);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: _oletracecmnin
+//
+// Synopsis: Prints trace information for API/Method-entry
+//
+// Arguments: [dwID] - API/Method ID
+//
+// Returns: nothing
+//
+// History: 14-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void _oletracecmnin(DWORD dwID, ...)
+{
+ const char *pscFormat;
+ va_list args;
+ int iNestingLevel;
+
+ if (!TraceCmnEnabled())
+ {
+ return;
+ }
+
+ va_start(args, dwID);
+
+ iNestingLevel = TLSIncTraceNestingLevel();
+
+ if(TraceInfoEnabled())
+ {
+ if(IsAPIID(dwID))
+ {
+ // This is an API
+ pscFormat = va_arg(args, const char*);
+
+ oleprintf(iNestingLevel,
+ GetNameFromAPIID(dwID), pscFormat, args);
+ }
+ else
+ {
+ IUnknown *pUnk;
+ char szTemp[128];
+
+ // This is an object/method call
+ pUnk = va_arg(args, IUnknown *);
+
+ pscFormat = va_arg(args, const char *);
+
+ oleprintf(iNestingLevel,
+ GetNameFromOBJID(dwID, pUnk, szTemp), pscFormat, args);
+ }
+ }
+
+ va_end(args);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: _oletraceout
+//
+// Synopsis: Prints trace information for API/Method-exit. assuming
+// return value is an HRESULT
+//
+// Arguments: [dwID] - API/Method ID
+// [hr] - return value
+//
+// Returns: nothing
+//
+// History: 14-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void _oletraceout(DWORD dwID, HRESULT hr)
+{
+ _oletraceoutex(dwID, RETURNFMT("%x"), hr);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: _oletracecmnout
+//
+// Synopsis: Prints trace information for API/Method-exit. assuming
+// return value is an HRESULT
+//
+// Arguments: [dwID] - API/Method ID
+// [hr] - return value
+//
+// Returns: nothing
+//
+// History: 14-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void _oletracecmnout(DWORD dwID, HRESULT hr)
+{
+ _oletracecmnoutex(dwID, RETURNFMT("%x"), hr);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: _oletraceoutex
+//
+// Synopsis: Prints trace information for API/Method-exit, using given
+// format string for return value
+//
+// Arguments: [dwID] - API/Method ID
+//
+// Returns: nothing
+//
+// History: 14-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void _oletraceoutex(DWORD dwID, ...)
+{
+ const char *pscFormat;
+ va_list args;
+ int iNestingLevel;
+
+ va_start(args, dwID);
+
+ iNestingLevel = TLSDecTraceNestingLevel();
+
+ if(TraceInfoEnabled())
+ {
+ if(IsAPIID(dwID))
+ {
+ // This is an API
+ pscFormat = va_arg(args, const char*);
+
+ oleprintf(iNestingLevel,
+ GetNameFromAPIID(dwID), pscFormat, args);
+ }
+ else
+ {
+ IUnknown *pUnk;
+ char szTemp[128];
+
+ // This is an object/method call
+ pUnk = va_arg(args, IUnknown *);
+
+ pscFormat = va_arg(args, const char *);
+
+ oleprintf(iNestingLevel,
+ GetNameFromOBJID(dwID, pUnk, szTemp), pscFormat, args);
+ }
+ }
+
+ va_end(args);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: _oletracecmnoutex
+//
+// Synopsis: Prints trace information for API/Method-exit, using given
+// format string for return value
+//
+// Arguments: [dwID] - API/Method ID
+//
+// Returns: nothing
+//
+// History: 14-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void _oletracecmnoutex(DWORD dwID, ...)
+{
+ const char *pscFormat;
+ va_list args;
+ int iNestingLevel;
+
+ if (!TraceCmnEnabled())
+ {
+ return;
+ }
+
+ va_start(args, dwID);
+
+ iNestingLevel = TLSDecTraceNestingLevel();
+
+ if(TraceInfoEnabled())
+ {
+ if(IsAPIID(dwID))
+ {
+ // This is an API
+ pscFormat = va_arg(args, const char*);
+
+ oleprintf(iNestingLevel,
+ GetNameFromAPIID(dwID), pscFormat, args);
+ }
+ else
+ {
+ IUnknown *pUnk;
+ char szTemp[128];
+
+ // This is an object/method call
+ pUnk = va_arg(args, IUnknown *);
+
+ pscFormat = va_arg(args, const char *);
+
+ oleprintf(iNestingLevel,
+ GetNameFromOBJID(dwID, pUnk, szTemp), pscFormat, args);
+ }
+ }
+
+ va_end(args);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: InitializeTraceInfo
+//
+// Synopsis: Initializes the trace information's global variables,
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void InitializeTraceInfo()
+{
+ // get Pid string once
+ _itoa(GetCurrentProcessId(), gPidString, 10);
+
+ if(TraceInfoEnabled() && SymInfoEnabled())
+ {
+ // Initialize the symbol information
+ // CAUTION: This is very expensive to turn on!
+ g_pSym = new CSym();
+ }
+
+}
+
+void SetTraceInfoLevel(DWORD dwLevel)
+{
+ g_dwInfoLevel = dwLevel;
+
+ if(TraceInfoEnabled() && (g_pSym == NULL) && SymInfoEnabled())
+ {
+ // Initialize the symbol information
+ g_pSym = new CSym();
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CleanupTraceInfo
+//
+// Synopsis: Cleans up trace information's global variables
+//
+// Arguments: (none)
+//
+// Returns: nothing
+//
+// History: 11-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+void CleanupTraceInfo()
+{
+ if(g_pSym != NULL)
+ {
+ delete g_pSym;
+ }
+ WriteToLogFile(NULL); // Stop writing to log file
+}
+
+#endif // DBG==1
diff --git a/private/ole32/common/w4io.h b/private/ole32/common/w4io.h
new file mode 100644
index 000000000..e88fd62b4
--- /dev/null
+++ b/private/ole32/common/w4io.h
@@ -0,0 +1,49 @@
+/***
+*w4io.h - fake FILE structure for Win 4 printf/sprintf/debug printf support
+*
+*/
+
+#if defined(M_I386) || defined(WIN32)
+# ifndef WIN32
+# define WIN32
+# endif
+#elif !defined(M_I86LM)
+# error Must be FLAT or LARGE model.
+#endif
+
+#ifndef NULL
+# define NULL 0
+#endif
+
+struct w4io
+{
+ union
+ {
+ struct
+ {
+ wchar_t *_pwcbuf; // wchar_t output buffer
+ wchar_t *_pwcstart;
+ } wc;
+ struct
+ {
+ char *_pchbuf; // char output buffer
+ char *_pchstart;
+ } ch;
+ } buf ;
+ unsigned int cchleft; // output buffer character count
+ void (_cdecl *writechar)(int ch,
+ int num,
+ struct w4io *f,
+ int *pcchwritten);
+};
+
+#define pwcbuf buf.wc._pwcbuf
+#define pwcstart buf.wc._pwcstart
+#define pchbuf buf.ch._pchbuf
+#define pchstart buf.ch._pchstart
+
+#define REG1 register
+#define REG2 register
+
+/* prototypes */
+int _cdecl w4iooutput(struct w4io *stream, const char *format, va_list argptr);
diff --git a/private/ole32/common/wsprintf.c b/private/ole32/common/wsprintf.c
new file mode 100644
index 000000000..83a74fb76
--- /dev/null
+++ b/private/ole32/common/wsprintf.c
@@ -0,0 +1,14 @@
+/***
+*sprintf.c - print formatted to string
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4wcsprintf() - print formatted data to wide character string
+* defines w4vwcsprintf() - print formatted output to a wide character
+* string, get data from argument ptr instead
+* of explicit args.
+*******************************************************************************/
+
+#define _W4WCSPRINTF_
+#include "printf.h"
diff --git a/private/ole32/daytona.inc b/private/ole32/daytona.inc
new file mode 100644
index 000000000..9567f342d
--- /dev/null
+++ b/private/ole32/daytona.inc
@@ -0,0 +1,72 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ daytona.inc
+
+Abstract:
+
+ This file is included from all of the daytona sources files. It
+ is handy for doing things like turning off precompiled headers
+ to get around compiler bugs, and other such global activities.
+
+Notes:
+
+ We define _OLE32_ so that when building ole32.dll we don't have
+ DECLSPEC_IMPORT defined (see objbase.h)
+
+!ENDIF
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DNOEXCEPTIONS \
+ -DINC_OLE2 \
+ -DFLAT \
+ -DWIN32=100 \
+ -D_NT1X_=100 \
+ -DUNICODE \
+ -D_UNICODE \
+ -DCAIROLE_DOWNLEVEL \
+ -DDCOM \
+ -DMSWMSG \
+ -DDCOM_SECURITY \
+ -DNEWPROPS \
+ -DASYNC \
+ -D_TRACKLINK_=1 \
+ -DLITTLEENDIAN=1 \
+ $(TRACELOG)
+
+# DECLSPEC_IMPORT control (see objbase.h)
+!if "$(MINORCOMP)"=="com" || "$(MINORCOMP)"=="stg" || "$(MINORCOMP)"=="ole232" || \
+ "$(MINORCOMP)"=="common" || "$(MINORCOMP)"=="proxy"
+C_DEFINES= \
+ $(C_DEFINES) \
+ -D_OLE32_ \
+ -D_OLE32PRIV_
+!endif
+
+
+BLDCRT= 1
+
+# For the Daytona build, we do not want statically linked compiler runtimes,
+# so leave this commented out.
+#
+# USE_LIBCMT= 1
+
+# For the x86, we have the few C runtime routines we use self-contained.
+
+!IF $(386)
+USE_NOLIBS=1
+!ELSE
+USE_CRTDLL=1
+!ENDIF
+
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+NTLEGO=1
+
+GPCH_BUILD=daytona
+
diff --git a/private/ole32/dbgexts/daytona/makefile b/private/ole32/dbgexts/daytona/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ole32/dbgexts/daytona/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/dbgexts/daytona/sources b/private/ole32/dbgexts/daytona/sources
new file mode 100644
index 000000000..ce16e9e61
--- /dev/null
+++ b/private/ole32/dbgexts/daytona/sources
@@ -0,0 +1,112 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Bruce Mansfield (brucema) 01-Jun-1995
+
+
+!ENDIF
+
+
+#
+# The MAJORCOMP and MINORCOMP variables are defined
+# so that $(MAJORCOMP)$(MINORCOMP)filename can be used in
+# cross compiling to provide unique filenames in a flat namespace.
+#
+
+MAJORCOMP=cairole
+MINORCOMP=dbgexts
+
+#
+# The TARGETNAME variable is defined by the developer. It is the name of
+# the target (component) that is being built by this makefile. It
+# should NOT include any path or file extension information.
+#
+
+TARGETNAME=oleexts
+
+DLLBASE=0x7a000000
+
+#
+# The TARGETPATH and TARGETTYPE variables are defined by the developer.
+# The first specifies where the target is to be build. The second specifies
+# the type of target (either PROGRAM, DYNLINK, LIBRARY, UMAPPL_NOLIB or
+# BOOTPGM). UMAPPL_NOLIB is used when you're only building user-mode
+# apps and don't need to build a library.
+#
+
+TARGETPATH=obj
+
+# Pick one of the following and delete the others
+TARGETTYPE=DYNLINK
+
+DLLDEF= ..\ole.def
+
+#
+# The TARGETLIBS specifies additional libraries to link with you target
+# image. Each library path specification should contain an asterisk (*)
+# where the machine specific subdirectory name should go.
+#
+UMTYPE=console
+USE_CRTDLL=1
+LINKLIBS= $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\crtdll.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib
+
+#
+# The INCLUDES variable specifies any include paths that are specific to
+# this source directory. Separate multiple directory paths with single
+# semicolons. Relative path specifications are okay.
+#
+
+INCLUDES=..\;..\..\common\daytona;..\..\ih;..\..\com\inc;..\..\com\objact;..\..\dcom\idl\daytona;..\..\com\rot;..\..\com\dcomrem;..\..\..\dcomidl\obj
+
+
+#
+# The SOURCES variable is defined by the developer. It is a list of all the
+# source files for this component. Each source file should be on a separate
+# line using the line continuation character. This will minimize merge
+# conflicts if two developers adding source files to the same component.
+#
+
+SOURCES= \
+ ..\oleexts.cxx \
+ ..\ddllcach.cxx \
+ ..\drot.cxx \
+ ..\dvtbl.cxx \
+ ..\derror.cxx \
+ ..\dfileext.cxx \
+ ..\dfilepat.cxx \
+ ..\dpsclsid.cxx \
+ ..\dstdid.cxx \
+ ..\dchannel.cxx \
+ ..\dinfolvl.cxx \
+ ..\dmoniker.cxx \
+ ..\dtreatas.cxx \
+ ..\dclsinfo.cxx \
+ ..\dclscach.cxx \
+ ..\util.cxx \
+ ..\doxid.cxx \
+ ..\dipid.cxx \
+ ..\ole.rc
+
+
+C_DEFINES= -DNT -DWINNT \
+ $(C_DEFINES)
diff --git a/private/ole32/dbgexts/dchannel.cxx b/private/ole32/dbgexts/dchannel.cxx
new file mode 100644
index 000000000..113a0e388
--- /dev/null
+++ b/private/ole32/dbgexts/dchannel.cxx
@@ -0,0 +1,152 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: dchannel.cxx
+//
+// Contents: Ole NTSD extension routines to display the RPC channel
+// associated with a remote handler. This includes the
+// interestiong pieces of CRpcChannelBuffer, CRpcService and
+// CEndPoint.
+//
+// Functions: channelHelp
+// displayChannel
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+#include "dipid.h"
+#include "dchannel.h"
+#include "dstdid.h"
+
+
+void FormatCLSID(REFGUID rguid, LPSTR lpsz);
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: channelHelp
+//
+// Synopsis: Display a menu for the command 'ch'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void channelHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("\nch addr - Display a CRpcChannelBuffer object:\n");
+ Printf("refs stdid state clientThread processLocal? handle OXID IPID destCtx\n");
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayChannel
+//
+// Synopsis: Display an RPC channel starting from the address of the
+// CRpcChannelBuffer object
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+// [pChnlBfr] - Address of channel buffer
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayChannel(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pChannel,
+ char *arg)
+{
+ SRpcChannelBuffer chnlBfr;
+ SStdIdentity stdid;
+ SOXIDEntry oxid;
+ SIPIDEntry ipid;
+ char szClsid[CLSIDSTR_MAX];
+
+ // Check for help
+ if (arg[0] == '?')
+ {
+ Printf("refs stdid state clientThread processLocal? handle OXID IPID destCtx\n");
+ return;
+ }
+
+ // Read the rpc channel buffer
+ ReadMem(&chnlBfr, pChannel, sizeof(SRpcChannelBuffer));
+
+ // References
+ Printf("%d ", chnlBfr.ref_count);
+
+ // Standard identity object address
+ Printf("%x ", chnlBfr.pStdId);
+
+ // State
+ switch (chnlBfr.state)
+ {
+ case client_cs:
+ Printf("client_cs ");
+ break;
+
+ case proxy_cs:
+ Printf("proxy_cs ");
+ break;
+
+ case server_cs:
+ Printf("server_cs ");
+ break;
+
+ case freethreaded_cs:
+ Printf("freethreaded_cs ");
+ break;
+
+ default:
+ Printf("unknown ");
+ break;
+ }
+
+ // Client thread
+ Printf("%3x ", chnlBfr.client_thread);
+
+ // Process local
+ if (chnlBfr.process_local)
+ {
+ Printf("local ");
+ }
+ else
+ {
+ Printf("not-local ");
+ }
+
+ // Handle
+ Printf("%x ", chnlBfr.handle);
+
+ // OXID entry address
+ Printf("%x ", chnlBfr.pOXIDEntry);
+
+ // IPID entry address
+ Printf("%x ", chnlBfr.pIPIDEntry);
+
+ // Destination context
+ Printf("%x\n", chnlBfr.iDestCtx);
+}
diff --git a/private/ole32/dbgexts/dchannel.h b/private/ole32/dbgexts/dchannel.h
new file mode 100644
index 000000000..18385585e
--- /dev/null
+++ b/private/ole32/dbgexts/dchannel.h
@@ -0,0 +1,39 @@
+
+
+typedef enum EChannelState
+{
+ // The channel on the client side held by the remote handler.
+ client_cs = 1,
+
+ // The channels on the client side held by proxies.
+ proxy_cs = 2,
+
+ // The server channels held by remote handlers.
+ server_cs = 16,
+
+ // Flag to indicate that the channel may be used on any thread.
+ freethreaded_cs = 64
+} EChannelState;
+
+
+
+
+// Forward reference
+struct SStdIdentity;
+
+
+
+struct SRpcChannelBuffer
+{
+ void *_vtbl1;
+ ULONG ref_count;
+ SStdIdentity *pStdId;
+ DWORD state;
+ DWORD client_thread;
+ BOOL process_local;
+ handle_t handle;
+ SOXIDEntry *pOXIDEntry;
+ SIPIDEntry *pIPIDEntry;
+ DWORD iDestCtx;
+};
+
diff --git a/private/ole32/dbgexts/dclscach.cxx b/private/ole32/dbgexts/dclscach.cxx
new file mode 100644
index 000000000..747f9dd34
--- /dev/null
+++ b/private/ole32/dbgexts/dclscach.cxx
@@ -0,0 +1,370 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: dclscach.cxx
+//
+// Contents: Ole NTSD extension routines to display the class cache in
+// the scm
+//
+// Functions: displayClassCache
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+#include "dclscach.h"
+
+
+void FormatCLSID(REFGUID rguid, LPSTR lpsz);
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: classCacheHelp
+//
+// Synopsis: Prints a short help menu for !ole.cc
+//
+// Arguments: [lpExtensionApis] - Table of extension functions
+//
+// Returns: -
+//
+// History: 27-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void classCacheHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("cc - Display class cache info\n");
+ Printf("local-server-path[(16)] clsid debug? [handler]\n");
+ Printf(" hRpc hWnd flags PSID desktop\n");
+ Printf(" ...\n");
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayClassCache
+//
+// Synopsis: Displays the retail scm class cache
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+//
+// Returns: -
+//
+// History: 27-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayClassCache(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ ULONG addr;
+ SClassCacheList sClassCacheList;
+ SSkipListEntry sSkipListEntry;
+ SClassData sClassData;
+ SLocalServer sLocalServer;
+ SStringID sStringId;
+ WCHAR *pwszUni;
+ WCHAR wszUni[128];
+ char szAnsi[128];
+ SArrayFValue sArrayFValue;
+ SSrvRegistration *pSrvReg;
+
+ // Read the class cache
+ addr = GetExpression("scm!g_pcllClassCache");
+ ReadMem(&addr, addr, sizeof(ULONG));
+ ReadMem(&sClassCacheList, addr, sizeof(SClassCacheList));
+
+ // Read the initial skiplist entry
+ ReadMem(&sSkipListEntry, sClassCacheList._pSkipList,
+ sizeof(SSkipListEntry));
+
+ // Do over skiplist entries
+ do
+ {
+ // Just in case
+ if (CheckControlC())
+ {
+ return;
+ }
+
+ // Read the next skiplist entry
+ ReadMem(&sSkipListEntry, sSkipListEntry._apBaseForward,
+ sizeof(SSkipListEntry));
+
+ // Read the CClassData structure
+ ReadMem(&sClassData, sSkipListEntry._pvEntry, sizeof(SClassData));
+
+ // Read the CLocalServer structure
+ ReadMem(&sLocalServer, sClassData._slocalsrv, sizeof(SLocalServer));
+
+ // Print the path
+ pwszUni = (WCHAR *) OleAlloc(sLocalServer._stringId._cPath *
+ sizeof(WCHAR));
+ ReadMem(pwszUni, sLocalServer._stringId._pwszPath,
+ sLocalServer._stringId._cPath * sizeof(WCHAR));
+ Unicode2Ansi(szAnsi, pwszUni, sLocalServer._stringId._cPath *
+ sizeof(WCHAR));
+ if (sClassData._fLocalServer16)
+ {
+ Printf("%s(16) ", szAnsi);
+ }
+ else
+ {
+ Printf("%s ", szAnsi);
+ }
+ OleFree(pwszUni);
+
+ // Print the clsid
+ FormatCLSID(sClassData._clsid, szAnsi);
+ Printf("%s ", szAnsi);
+
+ // Whether activated under a debugger
+ if (sClassData._fDebug)
+ {
+ Printf("*Debug*");
+ }
+
+ // Any specified handler
+ if (sClassData._shandlr)
+ {
+ ReadMem(&sStringId, sClassData._shandlr, sizeof(SStringID));
+
+ // Print the path
+ pwszUni = (WCHAR *) OleAlloc(sStringId._cPath * sizeof(WCHAR));
+ ReadMem(pwszUni, sStringId._pwszPath,
+ sStringId._cPath * sizeof(WCHAR));
+ Unicode2Ansi(szAnsi, pwszUni, sStringId._cPath *
+ sizeof(WCHAR));
+ if (sClassData._fInprocHandler16)
+ {
+ Printf("%s(16) ", szAnsi);
+ }
+ else
+ {
+ Printf("%s ", szAnsi);
+ }
+ OleFree(pwszUni);
+ }
+
+ // Close the print line
+ Printf("\n");
+
+ // Read the endpoint registration array base
+ ReadMem(&sArrayFValue, sClassData._pssrvreg, sizeof(SArrayFValue));
+
+ // Read the array of endpoint registrations
+ pSrvReg = (SSrvRegistration *) OleAlloc(sArrayFValue.m_nSize *
+ sizeof(SSrvRegistration));
+ ReadMem(pSrvReg, sArrayFValue.m_pData,
+ sArrayFValue.m_nSize * sizeof(SSrvRegistration));
+
+ // Do over the RPC endpoints registered for this server
+ for (int cReg = 0; cReg < sArrayFValue.m_nSize; cReg++)
+ {
+ // Only look at non-empty binding handles
+ if (pSrvReg[cReg]._hRpc)
+ {
+ // The RPC binding handle
+ Printf(" %x ", pSrvReg[cReg]._hRpc);
+
+ // The window handle
+ Printf("%x ", pSrvReg[cReg]._ulWnd);
+
+ // Flags
+ Printf("%x ", pSrvReg[cReg]._dwFlags);
+
+ // Security Id
+ Printf("%x ", pSrvReg[cReg]._psid);
+
+ // The desktop
+ UINT cb = 0;
+
+ // We have to read memory one WCHAR at a time because any
+ // av prevents any reading
+ do
+ {
+ ReadMem(&wszUni[cb], &pSrvReg[cReg]._lpDesktop[cb],
+ sizeof(WCHAR));
+ cb++;
+ } until_(wszUni[cb - 1] == L'\0');
+ Unicode2Ansi(szAnsi, wszUni, cb);
+ Printf("%s\n\n", szAnsi);
+ }
+ }
+ } until_(sSkipListEntry._apBaseForward == sClassCacheList._pSkipList);
+}
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayClassCacheCk
+//
+// Synopsis: Displays the checked scm class cache
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+//
+// Returns: -
+//
+// History: 27-Jun-95 BruceMa Created
+//
+// Notes: This was necessary because certain of the class cache
+// structures different depending on retail vs. checked
+//
+//--------------------------------------------------------------------------
+void displayClassCacheCk(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ ULONG addr;
+ SClassCacheList sClassCacheList;
+ SSkipListEntry sSkipListEntry;
+ SClassDataCk sClassData;
+ SLocalServerCk sLocalServer;
+ SStringIDCk sStringId;
+ WCHAR *pwszUni;
+ WCHAR wszUni[128];
+ char szAnsi[128];
+ SArrayFValue sArrayFValue;
+ SSrvRegistration *pSrvReg;
+
+ // Read the class cache
+ addr = GetExpression("scm!g_pcllClassCache");
+ ReadMem(&addr, addr, sizeof(ULONG));
+ ReadMem(&sClassCacheList, addr, sizeof(SClassCacheList));
+
+ // Read the initial skiplist entry
+ ReadMem(&sSkipListEntry, sClassCacheList._pSkipList,
+ sizeof(SSkipListEntry));
+
+ // Do over skiplist entries
+ do
+ {
+ // Just in case
+ if (CheckControlC())
+ {
+ return;
+ }
+
+ // Read the next skiplist entry
+ ReadMem(&sSkipListEntry, sSkipListEntry._apBaseForward,
+ sizeof(SSkipListEntry));
+
+ // Read the CClassData structure
+ ReadMem(&sClassData, sSkipListEntry._pvEntry, sizeof(SClassDataCk));
+
+ // Read the CLocalServer structure
+ ReadMem(&sLocalServer, sClassData._slocalsrv, sizeof(SLocalServerCk));
+
+ // Print the path
+ pwszUni = (WCHAR *) OleAlloc(sLocalServer._stringId._cPath *
+ sizeof(WCHAR));
+ ReadMem(pwszUni, sLocalServer._stringId._pwszPath,
+ sLocalServer._stringId._cPath * sizeof(WCHAR));
+ Unicode2Ansi(szAnsi, pwszUni, sLocalServer._stringId._cPath *
+ sizeof(WCHAR));
+ if (sClassData._fLocalServer16)
+ {
+ Printf("%s(16) ", szAnsi);
+ }
+ else
+ {
+ Printf("%s ", szAnsi);
+ }
+ OleFree(pwszUni);
+
+ // Print the clsid
+ FormatCLSID(sClassData._clsid, szAnsi);
+ Printf("%s ", szAnsi);
+
+ // Whether activated under a debugger
+ if (sClassData._fDebug)
+ {
+ Printf("*Debug*");
+ }
+
+ // Any specified handler
+ if (sClassData._shandlr)
+ {
+ ReadMem(&sStringId, sClassData._shandlr, sizeof(SStringIDCk));
+
+ // Print the path
+ pwszUni = (WCHAR *) OleAlloc(sStringId._cPath * sizeof(WCHAR));
+ ReadMem(pwszUni, sStringId._pwszPath,
+ sStringId._cPath * sizeof(WCHAR));
+ Unicode2Ansi(szAnsi, pwszUni, sStringId._cPath *
+ sizeof(WCHAR));
+ if (sClassData._fInprocHandler16)
+ {
+ Printf("%s(16) ", szAnsi);
+ }
+ else
+ {
+ Printf("%s ", szAnsi);
+ }
+ OleFree(pwszUni);
+ }
+
+ // Close the print line
+ Printf("\n");
+
+ // Read the endpoint registration array base
+ ReadMem(&sArrayFValue, sClassData._pssrvreg, sizeof(SArrayFValue));
+
+ // Read the array of endpoint registrations
+ pSrvReg = (SSrvRegistration *) OleAlloc(sArrayFValue.m_nSize *
+ sizeof(SSrvRegistration));
+ ReadMem(pSrvReg, sArrayFValue.m_pData,
+ sArrayFValue.m_nSize * sizeof(SSrvRegistration));
+
+ // Do over the RPC endpoints registered for this server
+ for (int cReg = 0; cReg < sArrayFValue.m_nSize; cReg++)
+ {
+ // Only look at non-empty binding handles
+ if (pSrvReg[cReg]._hRpc)
+ {
+ // The RPC binding handle
+ Printf(" %x ", pSrvReg[cReg]._hRpc);
+
+ // The window handle
+ Printf("%x ", pSrvReg[cReg]._ulWnd);
+
+ // Flags
+ Printf("%x ", pSrvReg[cReg]._dwFlags);
+
+ // Security Id
+ Printf("%x ", pSrvReg[cReg]._psid);
+
+ // The desktop
+ UINT cb = 0;
+
+ // We have to read memory one WCHAR at a time because any
+ // av prevents any reading
+ do
+ {
+ ReadMem(&wszUni[cb], &pSrvReg[cReg]._lpDesktop[cb],
+ sizeof(WCHAR));
+ cb++;
+ } until_(wszUni[cb - 1] == L'\0');
+ Unicode2Ansi(szAnsi, wszUni, cb);
+ Printf("%s\n\n", szAnsi);
+ }
+ }
+ } until_(sSkipListEntry._apBaseForward == sClassCacheList._pSkipList);
+}
diff --git a/private/ole32/dbgexts/dclscach.h b/private/ole32/dbgexts/dclscach.h
new file mode 100644
index 000000000..08b3dd3d0
--- /dev/null
+++ b/private/ole32/dbgexts/dclscach.h
@@ -0,0 +1,109 @@
+struct SStringID
+{
+ void *_vtbl;
+ ULONG _culRefs;
+ int _cPathBytes;
+ int _cPath;
+ WCHAR *_pwszPath;
+};
+
+
+
+struct SStringIDCk
+{
+ void *_vtbl;
+ ULONG _ulSig;
+ ULONG _culRefs;
+ int _cPathBytes;
+ int _cPath;
+ WCHAR *_pwszPath;
+};
+
+
+
+struct SLocalServer
+{
+ SStringID _stringId;
+ SMutexSem _mxsProcessStart;
+ BOOL _fDebug;
+};
+
+
+
+struct SLocalServerCk
+{
+ SStringIDCk _stringId;
+ ULONG _ulSig;
+ SMutexSem _mxsProcessStart;
+ BOOL _fDebug;
+};
+
+
+
+struct SSrvRegistration
+{
+ HANDLE _hRpc;
+ ULONG _ulWnd;
+ DWORD _dwFlags;
+ PSID _psid;
+ WCHAR *_lpDesktop;
+};
+
+
+
+struct SClassData
+{
+ LPVOID _vtbl;
+ CLSID _clsid;
+ SStringID *_shandlr;
+ SStringID *_sinproc;
+ SStringID *_sinproc16;
+ SLocalServer *_slocalsrv;
+ ULONG _fActivateAtBits:1;
+ ULONG _fDebug:1;
+ ULONG _fInprocHandler16:1;
+ ULONG _fLocalServer16:1;
+ ULONG _ulInprocThreadModel:2;
+ ULONG _ulHandlerThreadModel:2;
+ HANDLE _hClassStart;
+ SArrayFValue *_pssrvreg;
+ ULONG _ulRefs;
+};
+
+
+
+struct SClassDataCk
+{
+ LPVOID _vtbl;
+ CLSID _clsid;
+ SStringIDCk *_shandlr;
+ SStringIDCk *_sinproc;
+ SStringIDCk *_sinproc16;
+ SLocalServerCk *_slocalsrv;
+ ULONG _fActivateAtBits:1;
+ ULONG _fDebug:1;
+ ULONG _fInprocHandler16:1;
+ ULONG _fLocalServer16:1;
+ ULONG _ulInprocThreadModel:2;
+ ULONG _ulHandlerThreadModel:2;
+ HANDLE _hClassStart;
+ SArrayFValue *_pssrvreg;
+ ULONG _ulRefs;
+};
+
+
+
+struct SSkipListEntry
+{
+ DWORD _UNUSED;
+ SClassData *_pvEntry;
+ SSkipListEntry *_apBaseForward;
+};
+
+
+
+struct SClassCacheList
+{
+ DWORD _UNUSED[2];
+ SSkipListEntry *_pSkipList;
+};
diff --git a/private/ole32/dbgexts/dclsinfo.cxx b/private/ole32/dbgexts/dclsinfo.cxx
new file mode 100644
index 000000000..b3d96c7bd
--- /dev/null
+++ b/private/ole32/dbgexts/dclsinfo.cxx
@@ -0,0 +1,607 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: dclassInfo.cxx
+//
+// Contents: Display registry class information
+//
+// Functions: classInfoHelp
+// displayclassInfo
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+// BUGBUG: Add threading model flags
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+#include "dinfolvl.h"
+#include "debnot.h"
+
+
+
+BOOL ScanCLSID(char *szClsid, CLSID *pClsid);
+void FormatCLSID(REFGUID rguid, LPSTR lpsz);
+
+static void GetSomeClsidValues(HKEY hKey,
+ char *szName,
+ char *szInprocHandler,
+ char *szInprocHandler32,
+ char *szInprocServer,
+ char *szInprocServer32,
+ char *szLocalServer,
+ char *szLocalServer32,
+ char *szProgid,
+ char *szTreatAs,
+ char *szAutoConvertTo,
+ char *szOle1Class);
+
+static void DisplayValues(PNTSD_EXTENSION_APIS lpExtensionApis,
+ char *szName,
+ char *szInprocHandler,
+ char *szInprocHandler32,
+ char *szInprocServer,
+ char *szInprocServer32,
+ char *szLocalServer,
+ char *szLocalServer32,
+ char *szProgid,
+ char *szTreatAs,
+ char *szAutoConvertTo,
+ char *szOle1Class);
+
+static void MungePath(char *szPath);
+
+static DWORD dwRESERVED = 0;
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: classInfoHelp
+//
+// Synopsis: Display a menu for the command 'id'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void classInfoHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("ci - Display registry class information\n");
+ Printf("ci clsid - Display registry class information for clsid\n");
+
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayclassInfo
+//
+// Synopsis: Display/set debug info levels
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+// [CLSID *] - Get info for this clsid
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+BOOL displayClassInfo(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ CLSID *pClsid)
+{
+ HKEY hKey;
+ char szCLSID[CLSIDSTR_MAX];
+ char szClsid[5 + 1 + CLSIDSTR_MAX];
+ char szName[64];
+ char szInprocHandler[64];
+ char szInprocHandler32[64];
+ char szInprocServer[64];
+ char szInprocServer32[64];
+ char szLocalServer[64];
+ char szLocalServer32[64];
+ char szProgid[64];
+ char szTreatAs[64];
+ char szAutoConvertTo[64];
+ char szOle1Class[64];
+
+
+ // Information for a specific clsid?
+ if (pClsid)
+ {
+ // Prepare to open the "...CLSID\<clsid>" key
+ FormatCLSID(*pClsid, szCLSID);
+ lstrcpy(szClsid, "CLSID\\");
+ lstrcat(szClsid, szCLSID);
+
+ // Open the key for the specified clsid
+ if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szClsid, dwRESERVED,
+ KEY_READ, &hKey) != ERROR_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ // Read interesting values for this clsid
+ GetSomeClsidValues(hKey,
+ szName,
+ szInprocHandler,
+ szInprocHandler32,
+ szInprocServer,
+ szInprocServer32,
+ szLocalServer,
+ szLocalServer32,
+ szProgid,
+ szTreatAs,
+ szAutoConvertTo,
+ szOle1Class);
+
+ // Only display "interesting" entries
+ if ((szInprocHandler[0] &&
+ _stricmp(szInprocHandler, "ole2.dll") != 0) ||
+ (szInprocHandler32[0] &&
+ _stricmp(szInprocHandler32, "ole32.dll") != 0) ||
+ (szInprocServer[0] &&
+ _stricmp(szInprocServer, "ole2.dll") != 0) ||
+ (szInprocServer32[0] &&
+ _stricmp(szInprocServer32, "ole32.dll") != 0) ||
+ szLocalServer[0] ||
+ szLocalServer32[0] ||
+ szTreatAs[0] ||
+ szAutoConvertTo[0])
+ {
+ // Display them
+ DisplayValues(lpExtensionApis,
+ szName,
+ szInprocHandler,
+ szInprocHandler32,
+ szInprocServer,
+ szInprocServer32,
+ szLocalServer,
+ szLocalServer32,
+ szProgid,
+ szTreatAs,
+ szAutoConvertTo,
+ szOle1Class);
+ }
+
+ // Close registry handle and return success
+ CloseHandle(hKey);
+ return TRUE;
+ }
+
+ // Else display all of them
+ else
+ {
+ HKEY hKey2;
+ DWORD dwErr;
+ DWORD cbSubKey = 0;
+ char szClsid[64];
+ DWORD cbClsid;
+ DWORD cbClass;
+ FILETIME sLastWrite;
+
+ // Open the key for the root "CLSID"
+ if (RegOpenKeyEx(HKEY_CLASSES_ROOT, "CLSID", dwRESERVED,
+ KEY_ENUMERATE_SUB_KEYS, &hKey) != ERROR_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ // Enumerate over the keys under "HKEY_CLASSES_ROOT\CLSID"
+ do
+ {
+ // Enumerate the next subkey
+ cbClsid = 64;
+ dwErr = RegEnumKeyEx(hKey, cbSubKey, szClsid, &cbClsid,
+ NULL, NULL, NULL, &sLastWrite);
+
+ // Prepare for next subkey
+ cbSubKey++;
+
+ // If it does look like a clsid, skip it
+ CLSID clsid;
+
+ if (!ScanCLSID(szClsid, &clsid))
+ {
+ continue;
+ }
+
+ // Open this clsid key
+ if (RegOpenKeyEx(hKey, szClsid, dwRESERVED,
+ KEY_READ, &hKey2) != ERROR_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ // Get the interesting values
+ GetSomeClsidValues(hKey2,
+ szName,
+ szInprocHandler,
+ szInprocHandler32,
+ szInprocServer,
+ szInprocServer32,
+ szLocalServer,
+ szLocalServer32,
+ szProgid,
+ szTreatAs,
+ szAutoConvertTo,
+ szOle1Class);
+
+ // Only display "interesting" entries
+ if ((szInprocHandler[0] &&
+ _stricmp(szInprocHandler, "ole2.dll") != 0) ||
+ (szInprocHandler32[0] &&
+ _stricmp(szInprocHandler32, "ole32.dll") != 0) ||
+ (szInprocServer[0] &&
+ _stricmp(szInprocServer, "ole2.dll") != 0) ||
+ (szInprocServer32[0] &&
+ _stricmp(szInprocServer32, "ole32.dll") != 0) ||
+ szLocalServer[0] ||
+ szLocalServer32[0] ||
+ szTreatAs[0] ||
+ szAutoConvertTo[0])
+ {
+ // Display the clsid
+ Printf("%s ", szClsid);
+
+ // Display its values
+ DisplayValues(lpExtensionApis,
+ szName,
+ szInprocHandler,
+ szInprocHandler32,
+ szInprocServer,
+ szInprocServer32,
+ szLocalServer,
+ szLocalServer32,
+ szProgid,
+ szTreatAs,
+ szAutoConvertTo,
+ szOle1Class);
+ }
+
+ // Close registry handle
+ CloseHandle(hKey2);
+
+ } until_(dwErr == ERROR_NO_MORE_ITEMS || dwErr != ERROR_SUCCESS);
+
+ // Close clsid registry handle
+ CloseHandle(hKey);
+
+ return TRUE;
+ }
+}
+
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetSomeClsidValues
+//
+// Synopsis: Given an open registry key to a clsid, read some of
+// the more interesting subkey values
+//
+// Arguments: [hkey] Open registry key
+// [szName] Where to store the name
+// [szInprocHandler] Where to store the InprocHandler
+// [szInprocHandler32] Where to store the InprocHandler32
+// [szInprocServer] Where to store the InprocServer
+// [szInprocServer32] Where to store the InprocServer32
+// [szLocalServer] Where to store the LocalServer
+// [szLocalServer32] Where to store the LocalServer32
+// [ProgId] Where to store the ProgId
+// [TreatAs] Where to store the TreatAs
+// [AutoConvertTo] Where to store the AutoConvertTo
+// [Ole1Class] Where to store the Ole1Class
+//
+// Returns: -
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static void GetSomeClsidValues(HKEY hKey,
+ char *szName,
+ char *szInprocHandler,
+ char *szInprocHandler32,
+ char *szInprocServer,
+ char *szInprocServer32,
+ char *szLocalServer,
+ char *szLocalServer32,
+ char *szProgId,
+ char *szTreatAs,
+ char *szAutoConvertTo,
+ char *szOle1Class)
+{
+ DWORD dwRESERVED = 0;
+ HKEY hKey2;
+ DWORD dwValueType;
+ DWORD cbValue;
+
+ // Initialize
+ szName[0] = '\0';
+ szInprocHandler[0] = '\0';
+ szInprocHandler32[0] = '\0';
+ szInprocServer[0] = '\0';
+ szInprocServer32[0] = '\0';
+ szLocalServer[0] = '\0';
+ szLocalServer32[0] = '\0';
+ szProgId[0] = '\0';
+ szTreatAs[0] = '\0';
+ szAutoConvertTo[0] = '\0';
+ szOle1Class[0] = '\0';
+
+ // Name
+ cbValue = 64;
+ if (RegQueryValueEx(hKey, NULL, NULL, &dwValueType,
+ (LPBYTE) szName, &cbValue) != ERROR_SUCCESS)
+ {
+ return;
+ }
+
+ // InprocHandler
+ if (RegOpenKeyEx(hKey, "InprocHandler", dwRESERVED,
+ KEY_READ, &hKey2) == ERROR_SUCCESS)
+ {
+ cbValue = 64;
+ RegQueryValueEx(hKey2, NULL, NULL, &dwValueType,
+ (LPBYTE) szInprocHandler, &cbValue);
+ MungePath(szInprocHandler);
+ CloseHandle(hKey2);
+ }
+
+ // InprocHandler32
+ if (RegOpenKeyEx(hKey, "InprocHandler32", dwRESERVED,
+ KEY_READ, &hKey2) == ERROR_SUCCESS)
+ {
+ cbValue = 64;
+ RegQueryValueEx(hKey2, NULL, NULL, &dwValueType,
+ (LPBYTE) szInprocHandler32, &cbValue);
+ MungePath(szInprocHandler32);
+ CloseHandle(hKey2);
+ }
+
+ // InprocServer
+ if (RegOpenKeyEx(hKey, "InprocServer", dwRESERVED,
+ KEY_READ, &hKey2) == ERROR_SUCCESS)
+ {
+ cbValue = 64;
+ RegQueryValueEx(hKey2, NULL, NULL, &dwValueType,
+ (LPBYTE) szInprocServer, &cbValue);
+ MungePath(szInprocServer);
+ CloseHandle(hKey2);
+ }
+
+ // InprocServer32
+ if (RegOpenKeyEx(hKey, "InprocServer32", dwRESERVED,
+ KEY_READ, &hKey2) == ERROR_SUCCESS)
+ {
+ cbValue = 64;
+ RegQueryValueEx(hKey2, NULL, NULL, &dwValueType,
+ (LPBYTE) szInprocServer32, &cbValue);
+ MungePath(szInprocServer32);
+ CloseHandle(hKey2);
+ }
+
+ // LocalServer
+ if (RegOpenKeyEx(hKey, "LocalServer", dwRESERVED,
+ KEY_READ, &hKey2) == ERROR_SUCCESS)
+ {
+ cbValue = 64;
+ RegQueryValueEx(hKey2, NULL, NULL, &dwValueType,
+ (LPBYTE) szLocalServer, &cbValue);
+ MungePath(szLocalServer);
+ CloseHandle(hKey2);
+ }
+
+ // LocalServer32
+ if (RegOpenKeyEx(hKey, "LocalServer32", dwRESERVED,
+ KEY_READ, &hKey2) == ERROR_SUCCESS)
+ {
+ cbValue = 64;
+ RegQueryValueEx(hKey2, NULL, NULL, &dwValueType,
+ (LPBYTE) szLocalServer32, &cbValue);
+ MungePath(szLocalServer32);
+ CloseHandle(hKey2);
+ }
+
+ // ProgId
+ if (RegOpenKeyEx(hKey, "ProgId", dwRESERVED,
+ KEY_READ, &hKey2) == ERROR_SUCCESS)
+ {
+ cbValue = 64;
+ RegQueryValueEx(hKey2, NULL, NULL, &dwValueType,
+ (LPBYTE) szProgId, &cbValue);
+ CloseHandle(hKey2);
+ }
+
+ // TreatAs
+ if (RegOpenKeyEx(hKey, "TreatAs", dwRESERVED,
+ KEY_READ, &hKey2) == ERROR_SUCCESS)
+ {
+ cbValue = 64;
+ RegQueryValueEx(hKey2, NULL, NULL, &dwValueType,
+ (LPBYTE) szTreatAs, &cbValue);
+ CloseHandle(hKey2);
+ }
+
+ // AutoConvertTo
+ if (RegOpenKeyEx(hKey, "AutoConvertTo", dwRESERVED,
+ KEY_READ, &hKey2) == ERROR_SUCCESS)
+ {
+ cbValue = 64;
+ RegQueryValueEx(hKey2, NULL, NULL, &dwValueType,
+ (LPBYTE) szAutoConvertTo, &cbValue);
+ CloseHandle(hKey2);
+ }
+
+ // Ole1Class
+ if (RegOpenKeyEx(hKey, "Ole1Class", dwRESERVED,
+ KEY_READ, &hKey2) == ERROR_SUCCESS)
+ {
+ szOle1Class[0] = '1';
+ CloseHandle(hKey2);
+ }
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DisplayValues
+//
+// Synopsis: Display the values read above
+//
+// Arguments: [hkey] Open registry key
+// [szName] Where to store the name
+// [szInprocHandler] Where to store the InprocHandler
+// [szInprocHandler32] Where to store the InprocHandler32
+// [szInprocServer] Where to store the InprocServer
+// [szInprocServer32] Where to store the InprocServer32
+// [szLocalServer] Where to store the LocalServer
+// [szLocalServer32] Where to store the LocalServer32
+// [ProgId] Where to store the ProgId
+// [TreatAs] Where to store the TreatAs
+// [AutoConvertTo] Where to store the AutoConvertTo
+// [Ole1Class] Where to store the Ole1Class
+//
+// Returns: -
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static void DisplayValues(PNTSD_EXTENSION_APIS lpExtensionApis,
+ char *szName,
+ char *szInprocHandler,
+ char *szInprocHandler32,
+ char *szInprocServer,
+ char *szInprocServer32,
+ char *szLocalServer,
+ char *szLocalServer32,
+ char *szProgId,
+ char *szTreatAs,
+ char *szAutoConvertTo,
+ char *szOle1Class)
+
+{
+ // Display the name
+ Printf("%s ", szName);
+
+ // Display ProgId (if unique)
+ if (szProgId[0] && lstrcmp(szProgId, szName) != 0)
+ {
+ Printf("%s ", szProgId);
+ }
+
+ // Display the server executable
+ if (szLocalServer[0])
+ {
+ Printf("%s ", szLocalServer32);
+ }
+ else if (szInprocServer32[0])
+ {
+ Printf("%s ", szInprocServer32);
+ }
+ else if (szLocalServer[0])
+ {
+ Printf("%s(16) ", szLocalServer);
+ }
+ else if (szInprocServer[0])
+ {
+ Printf("%s(16) ", szInprocServer);
+ }
+
+ // Display handler information
+ if (szInprocHandler32[0] &&
+ _stricmp(szInprocHandler32, "ole32.dll") != 0)
+ {
+ Printf("Hndlr: %s ", szInprocHandler32);
+ }
+ else if (szInprocHandler[0] &&
+ _stricmp(szInprocHandler, "ole2.dll") != 0)
+ {
+ Printf("Hndlr: %s(16) ", szInprocHandler);
+ }
+
+ // Display any TreatAs or AutoConvertTo information
+ if (szTreatAs[0])
+ {
+ Printf("TA: %s", szTreatAs);
+ }
+ if (szAutoConvertTo[0])
+ {
+ Printf("ACT: %s", szAutoConvertTo);
+ }
+
+ // Check if this is an ole1 class
+ if (szOle1Class[0])
+ {
+ Printf("ole1 class");
+ }
+
+ // We're done
+ Printf("\n");
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: MungePath
+//
+// Synopsis: Remove directory components from a file path
+//
+// Arguments: [szPath] Path to munge
+//
+// Returns: -
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static void MungePath(char *szPath)
+{
+ int cbLen = lstrlen(szPath);
+ DWORD cbPath;
+
+ for (cbPath = cbLen; cbPath > 0 && szPath[cbPath] != '\\'; cbPath--)
+ {
+ }
+ if (cbPath > 0)
+ {
+ lstrcpy(szPath, &szPath[cbPath + 1]);
+ }
+}
diff --git a/private/ole32/dbgexts/ddllcach.cxx b/private/ole32/dbgexts/ddllcach.cxx
new file mode 100644
index 000000000..cb1196c1f
--- /dev/null
+++ b/private/ole32/dbgexts/ddllcach.cxx
@@ -0,0 +1,232 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: ddllcach.cxx
+//
+// Contents: Ole NTSD extension routines to display a dll/class cache
+//
+// Functions: displayDllCache
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+#include "ddllcach.h"
+
+
+void FormatCLSID(REFGUID rguid, LPSTR lpsz);
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: dllCacheHelp
+//
+// Synopsis: Display a menu for the command 'ds'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void dllCacheHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("\nds - Display entire Inproc Server dll/class cache:\n");
+ Printf("dh - Display entire Inproc Handler dll/class cache:\n\n");
+ Printf("Dll's\n");
+ Printf("-----\n");
+ Printf("path hModule DllGetClassObject() DllCanUnloadNow() apt ... apt \n");
+ Printf(" CLSID\n");
+ Printf(" ...\n");
+ Printf("...\n\n");
+ Printf("LocalServers\n");
+ Printf("------------\n");
+ Printf("CLSID IUnknown* [M|S|MS] reg_key reg_@_scm\n");
+ Printf("...\n\n");
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayDllCache
+//
+// Synopsis: Formats and writes a dll/class cache structure to the
+// debugger terminal
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayDllCache(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ SDllCache *pDllCache)
+{
+ SDllPathEntry *pDllPathEntries;
+ SClassEntry *pClassEntries;
+ DWORD cbSize;
+
+// dbt("pDllCache", pDllCache, sizeof(SDllCache));
+
+ // Fetch the array of dll path entries
+ cbSize = sizeof(SDllPathEntry) * pDllCache->_cDllPathEntries;
+ pDllPathEntries = (SDllPathEntry *) OleAlloc(cbSize);
+ ReadMem(pDllPathEntries, pDllCache->_pDllPathEntries, cbSize);
+
+// dbt("pDllPathEntries", pDllPathEntries, cbSize);
+
+ // Fetch the array of class entries
+ cbSize = sizeof(SClassEntry) * pDllCache->_cClassEntries;
+ pClassEntries = (SClassEntry *) OleAlloc(cbSize);
+ ReadMem(pClassEntries, pDllCache->_pClassEntries, cbSize);
+
+// dbt("pClassEntries", pClassEntries, cbSize);
+
+ // We do the dll's first
+ Printf("Dll's:\n-----\n");
+
+ // Do over the registered dll's
+ for (DWORD dwDll = pDllCache->_nDllPathEntryInUse; dwDll != NONE;
+ dwDll = pDllPathEntries[dwDll]._dwNext)
+ {
+ // Fetch the dll path
+ WCHAR wszPath[MAX_PATH + 1];
+ CHAR szPath[2 * MAX_PATH + 1];
+
+ // We don't know the length of the path, so read one WCHAR
+ // at a time
+ INT k = -1;
+
+ do
+ {
+ k++;
+ ReadMem(&wszPath[k], &pDllPathEntries[dwDll]._pwszPath[k],
+ sizeof(WCHAR));
+ } until_(wszPath[k] == L'\0');
+ Unicode2Ansi(szPath, wszPath, 2 * MAX_PATH + 1);
+
+ // Fetch the apartment entries for this dll path entry
+ SDllAptEntry *pAptEntries;
+
+ cbSize = sizeof(SDllAptEntry) * pDllPathEntries[dwDll]._cAptEntries;
+ pAptEntries = (SDllAptEntry *) OleAlloc(cbSize);
+ ReadMem(pAptEntries, pDllPathEntries[dwDll]._pAptEntries,
+ cbSize);
+
+// dbt("pAptEntries", pAptEntries, cbSize);
+
+ // Display path
+ Printf("%s ", szPath);
+
+ // Display hModule and DllGetClassObject and DllCanUnloadNow entry
+ // points
+ Printf("%08x %08x %08x ",
+ pAptEntries[pDllPathEntries[dwDll]._nAptInUse]._hDll,
+ pDllPathEntries[dwDll]._pfnGetClassObject,
+ pDllPathEntries[dwDll]._pfnDllCanUnload);
+
+ // Display apartment id's
+ for (DWORD dwApt = pDllPathEntries[dwDll]._nAptInUse; dwApt != NONE;
+ dwApt = pAptEntries[dwApt]._dwNext)
+ {
+ Printf("%x ", pAptEntries[dwApt]._hApt);
+ }
+ Printf("\n");
+
+ // Do over CLSID's for this dll
+ for (DWORD dwCls = pDllPathEntries[dwDll]._dw1stClass; dwCls != NONE;
+ dwCls = pClassEntries[dwCls]._dwNextDllCls)
+ {
+ // Display the CLSID
+ CHAR szClsid[CLSIDSTR_MAX];
+
+ FormatCLSID(pClassEntries[dwCls]._clsid, szClsid);
+ Printf(" %s \n", szClsid);
+ }
+
+ // Release the apartment entries for this dll
+ OleFree(pAptEntries);
+
+ Printf("\n");
+ }
+
+ // Release the array of dll path entries
+ OleFree(pDllPathEntries);
+
+
+
+ // Then we do the local servers
+ Printf("Local Servers:\n----------\n");
+
+ // Do over the locally registerd local servers
+ for (DWORD dwCls = pDllCache->_nClassEntryInUse; dwCls != NONE;
+ dwCls = pClassEntries[dwCls]._dwNext)
+ {
+ // Skip class entries associated with dll's
+ if (pClassEntries[dwCls]._dwDllEnt == NONE)
+ {
+ // Display the CLSID
+ CHAR szClsid[CLSIDSTR_MAX];
+
+ FormatCLSID(pClassEntries[dwCls]._clsid, szClsid);
+ Printf(" %s ", szClsid);
+
+ // The class factory punk
+ Printf("%08x ", pClassEntries[dwCls]._pUnk);
+
+ // The flags
+ if (pClassEntries[dwCls]._dwFlags == REGCLS_SINGLEUSE)
+ {
+ Printf("S ");
+ }
+ else if (pClassEntries[dwCls]._dwFlags == REGCLS_MULTIPLEUSE)
+ {
+ Printf("M ");
+ }
+ else if (pClassEntries[dwCls]._dwFlags == REGCLS_MULTI_SEPARATE)
+ {
+ Printf("MS ");
+ }
+
+ // The registration key given to the user
+ Printf("%08x ", pClassEntries[dwCls]._dwReg);
+
+ // The registration key at the scm
+ Printf("%08x ", pClassEntries[dwCls]._dwScmReg);
+
+ // Whether this is an AtBits server
+ if (pClassEntries[dwCls]._fAtBits)
+ {
+ Printf("AtBits\n");
+ }
+ else
+ {
+ Printf("\n");
+ }
+ }
+ }
+
+ Printf("\n");
+
+ // Release the array of class entries
+ OleFree(pClassEntries);
+}
diff --git a/private/ole32/dbgexts/ddllcach.h b/private/ole32/dbgexts/ddllcach.h
new file mode 100644
index 000000000..16c4a2b9b
--- /dev/null
+++ b/private/ole32/dbgexts/ddllcach.h
@@ -0,0 +1,99 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: ddllcach.h
+//
+// Contents: Contains structure definitons for the significant dll class/
+// cache ole classes which the ntsd extensions need to access.
+// These ole classes cannot be accessed more cleanly because
+// typically the members of interest are protected.
+//
+// WARNING. IF THE REFERENCED OLE CLASSES CHANGE, THEN THESE
+// DEFINITIONS MUST CHANGE!
+//
+// History: 06-01-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+
+
+typedef HRESULT (*DLLUNLOADFNP)(void);
+
+const DWORD NONE = ~0UL;
+
+
+struct SClassEntry
+{
+ DWORD _fAtBits; // Whether server is an at bits server
+ DWORD _dwNext; // Next entry in in-use or avail list
+ DWORD _dwSig; // Marks entry as in use
+ CLSID _clsid; // Class of this server
+ IUnknown *_pUnk; // Class factory IUnknown
+ DWORD _dwContext; // Class context
+ DWORD _dwFlags; // Single vs. multiple use
+ DWORD _dwReg; // Registration key for caller
+ DWORD _dwScmReg; // Registration ID at the SCM
+ HAPT _hApt; // Thread Id
+ DWORD _cCallOut; // Count of active call outs
+ DWORD _fRevokePending;// Whether revoked while calling out
+ DWORD _dwDllEnt; // Associated dll path entry
+ DWORD _dwNextDllCls; // Next class entrry for this dll
+ HWND _hWndDdeServer; // Handle of associated DDE window
+};
+
+
+
+
+
+struct SDllAptEntry
+{
+ DWORD _dwNext; // Next entry in avail or in use list
+ DWORD _dwSig; // Unique signature for apt entries
+ HAPT _hApt; // apartment id
+ HMODULE _hDll; // module handle
+};
+
+
+
+
+
+struct SDllPathEntry
+{
+ DWORD _dwNext; // Next in-use/avail entry
+ DWORD _dwSig; // Unique signature for safty
+ LPWSTR _pwszPath; // The dll pathname
+ DWORD _dwHash; // Hash value for searching
+ LPFNGETCLASSOBJECT _pfnGetClassObject; // Create object entry point
+ DLLUNLOADFNP _pfnDllCanUnload; // DllCanUnloadNow entry point
+ DWORD _dwFlags; // Internal flags
+ DWORD _dwDllThreadModel:2; // Threading model for the DLL
+ DWORD _dw1stClass; // First class entry for dll
+ DWORD _cUsing; // Count of using threads
+ DWORD _cAptEntries; // Total apt entries
+ DWORD _nAptAvail; // List of available apt entries
+ DWORD _nAptInUse; // List of in use apt entries
+ SDllAptEntry *_pAptEntries; // Per thread info
+};
+
+
+
+
+struct SDllCache
+{
+ SMutexSem _mxsLoadLibrary; // Protects LoadLibrary calls
+ SMutexSem _mxs; // Protects from multiple threads
+ DWORD _cClassEntries; // Count of class entries
+ DWORD _nClassEntryInUse; // First in-use class entry
+ DWORD _nClassEntryAvail; // First available class entry
+ SClassEntry *_pClassEntries; // Array of class entries
+ DWORD _cDllPathEntries; // Count of dll path entries
+ DWORD _nDllPathEntryInUse; // First in-use dll path entry
+ DWORD _nDllPathEntryAvail; // First available dll path entry
+ SDllPathEntry *_pDllPathEntries; // Array of DLL path entries
+};
+
+
+
+
+
diff --git a/private/ole32/dbgexts/derror.cxx b/private/ole32/dbgexts/derror.cxx
new file mode 100644
index 000000000..cd0275afc
--- /dev/null
+++ b/private/ole32/dbgexts/derror.cxx
@@ -0,0 +1,135 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: derror.cxx
+//
+// Contents: Ole NTSD extension routines to display the error
+// message for a Win32 or OLE error code
+//
+// Functions: displayVtbl
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayHr
+//
+// Synopsis: Display the mnesage for a Win32 error or OLE HRESULT
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+//
+// Returns: -
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayHr (HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ char *arg)
+{
+ DWORD err = 0;
+ BOOL fHex = FALSE;
+
+ // Determine if it's hex or decimal. Also allow '800xxxxx' to implicitly
+ // be treated as hexadecimal
+ if (arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X'))
+ {
+ fHex = TRUE;
+ arg += 2;
+ }
+ else if (arg[0] == '8' && arg[1] == '0' && arg[2] == '0')
+ {
+ fHex = TRUE;
+ }
+ else
+ {
+ char *s = arg;
+
+ while (*s)
+ {
+ if (('a' <= *s && *s <= 'f') || ('A' <= *s && *s <= 'F'))
+ {
+ fHex = TRUE;
+ break;
+ }
+ s++;
+ }
+ }
+
+ // Parse the error number
+ if (fHex)
+ {
+ int k = 0;
+ char c;
+
+ while (c = arg[k++])
+ {
+ c = c - '0';
+ if (c > 9)
+ {
+ if (c <= 'F' && c >= 'A')
+ {
+ c = c + '0' - 'A' + 10;
+ }
+ else
+ {
+ c = c + '0' - 'a' + 10;
+ }
+ }
+ err = (16 * err) + c;
+ }
+ }
+ else
+ {
+ int k = 0;
+ char c;
+
+ while (c = arg[k++])
+ {
+ c = c - '0';
+ err = (10 * err) + c;
+ }
+ }
+
+ // Fetch the associated error message
+ int cbMsgLen;
+ char szBuffer[512];
+
+ cbMsgLen = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ err,
+ (DWORD) NULL,
+ szBuffer,
+ 511,
+ NULL);
+
+ // Output the message
+ if (cbMsgLen == 0)
+ {
+ Printf("...No such error code\n");
+ }
+ else
+ {
+ szBuffer[cbMsgLen] = '\0';
+ Printf("%s\n", szBuffer);
+ }
+}
diff --git a/private/ole32/dbgexts/dfileext.cxx b/private/ole32/dbgexts/dfileext.cxx
new file mode 100644
index 000000000..de0cca61e
--- /dev/null
+++ b/private/ole32/dbgexts/dfileext.cxx
@@ -0,0 +1,158 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: dfileext.cxx
+//
+// Contents: Ole NTSD extension routines to dump the clsid/file extensions
+// cache
+//
+// Functions: fileExtHelp
+// displayFileExtTbl
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+#include "dshrdmem.h"
+
+
+
+
+BOOL IsEqualCLSID(CLSID *pClsid1, CLSID *pClsid2);
+void FormatCLSID(REFGUID rguid, LPSTR lpsz);
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: fileExtHelp
+//
+// Synopsis: Display a menu for the command 'fe'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void fileExtHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("fe - Display entire file extensions table\n");
+ Printf("fe clsid - Display file extensions for clsid\n");
+ Printf("fe .ext - Display clsid for file extension ext\n");
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayFileExtTbl
+//
+// Synopsis: Display some or all of the file extensions table
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+// [lpFileExtTbl] - Address of file extensions table
+//
+// Returns: -
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayFileExtTbl(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ SDllShrdTbl *pShrdTbl,
+ CLSID *pClsid,
+ WCHAR *wszExt)
+{
+ SDllShrdTbl sDllTbl;
+ SExtTblHdr *pExtTblHdr;
+ SExtTblHdr sExtTblHdr;
+ BYTE *pExtEntry;
+ LPVOID pEnd;
+ CLSID oldClsid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+
+ // Read the shared table locally
+ ReadMem(&sDllTbl, pShrdTbl, sizeof(SDllShrdTbl));
+
+ // Read the table header locally
+ pExtTblHdr = sDllTbl._FileExtTbl._pTblHdr;
+ ReadMem(&sExtTblHdr, pExtTblHdr, sizeof(SExtTblHdr));
+
+ // Set up to read the entries
+ pExtEntry = sDllTbl._FileExtTbl._pStart;
+ pEnd = pExtEntry + sExtTblHdr.OffsEnd - sizeof(SExtTblHdr);
+
+ // Do over the file extension entries
+ while (pExtEntry < pEnd)
+ {
+ ULONG ulLen;
+ SExtEntry sExtEnt;
+ WCHAR slop[16];
+ char szClsid[CLSIDSTR_MAX];
+ BOOL fNL = FALSE;
+
+ // Just in case the loop gets away from us
+ if (CheckControlC())
+ {
+ return;
+ }
+
+ // Read the length of this entry
+ ReadMem(&ulLen, pExtEntry + sizeof(CLSID), sizeof(ULONG));
+
+ // Read the next entry locally
+ ReadMem(&sExtEnt, pExtEntry, ulLen);
+
+ // Print the clsid if dumping the whole table or searching by
+ // extension
+ if ((pClsid == NULL && wszExt == NULL) ||
+ (wszExt && !lstrcmpW(wszExt, sExtEnt.wszExt)))
+ {
+ FormatCLSID(sExtEnt.Clsid, szClsid);
+ Printf("%s ", szClsid);
+
+ // Save the clisd
+ oldClsid = sExtEnt.Clsid;
+
+ // Remember to printf a newline
+ fNL = TRUE;
+ }
+
+ // Print the extension if dumping the whole table or seraching
+ // by clsid
+ if ((pClsid == NULL && wszExt == NULL) ||
+ (pClsid && IsEqualCLSID(&sExtEnt.Clsid, pClsid)))
+ {
+ // Print the associated file extension
+ Printf("%ws ", sExtEnt.wszExt);
+
+ // Remember to printf a newline
+ fNL = TRUE;
+ }
+
+ // Check if we need to print a newline
+ if (fNL)
+ {
+ Printf("\n");
+ fNL = FALSE;
+ }
+
+ // Go to the next entry
+ pExtEntry += ulLen;
+ }
+}
diff --git a/private/ole32/dbgexts/dfilepat.cxx b/private/ole32/dbgexts/dfilepat.cxx
new file mode 100644
index 000000000..6508e0709
--- /dev/null
+++ b/private/ole32/dbgexts/dfilepat.cxx
@@ -0,0 +1,162 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: dfilepat.cxx
+//
+// Contents: Ole NTSD extension routines to dump the file type (bit
+// patterns) cache
+//
+// Functions: filePatHelp
+// displayFilePatTbl
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+#include "dshrdmem.h"
+
+
+
+
+BOOL IsEqualCLSID(CLSID *pClsid1, CLSID *pClsid2);
+void FormatCLSID(REFGUID rguid, LPSTR lpsz);
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: filePatHelp
+//
+// Synopsis: Display a menu for the command 'ft'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void filePatHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("ft - Display entire file type patterns table\n");
+ Printf("ft clsid - Display file type patterns for clsid\n");
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayFilePatTbl
+//
+// Synopsis: Display some or all of the file type patterns table
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+// [lpFileExtTbl] - Address of file extensions table
+// [pClsid] - Only for this clsid
+//
+// Returns: -
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayFilePatTbl(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ SDllShrdTbl *pShrdTbl,
+ CLSID *pClsid)
+{
+ SDllShrdTbl sDllTbl;
+ STblHdr *pTblHdr;
+ STblHdr sTblHdr;
+ BYTE *pStart;
+ LPVOID pEnd;
+ CLSID oldClsid = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ UINT ulCnt = 0;
+
+
+ // Read the shared table locally
+ ReadMem(&sDllTbl, pShrdTbl, sizeof(SDllShrdTbl));
+
+ // Read the table header locally
+ pTblHdr = sDllTbl._PatternTbl._pTblHdr;
+ ReadMem(&sTblHdr, pTblHdr, sizeof(STblHdr));
+
+ // Set up to read the entries
+ pStart = sDllTbl._PatternTbl._pStart;
+ pEnd = pStart + sTblHdr.OffsEnd - sizeof(STblHdr);
+
+ // Do over the file extension entries
+ while (pStart < pEnd)
+ {
+ ULONG ulLen;
+ SPatternEntry sPatEnt;
+ char szClsid[CLSIDSTR_MAX];
+
+ // Just in case the loop gets away from us
+ if (CheckControlC())
+ {
+ return;
+ }
+
+ // Read the length of this entry
+ ReadMem(&ulLen, pStart + sizeof(CLSID), sizeof(ULONG));
+
+ // Read the next entry locally
+ ReadMem(&sPatEnt, pStart, ulLen);
+
+ // Print the clsid if we haven't yet
+ if (pClsid == NULL && !IsEqualCLSID(&sPatEnt.clsid, &oldClsid))
+ {
+ FormatCLSID(sPatEnt.clsid, szClsid);
+ Printf("\n%s\n", szClsid);
+
+ // Save the clisd
+ oldClsid = sPatEnt.clsid;
+
+ // Initialize a count per clsid
+ ulCnt = 0;
+ }
+
+ // Print only if printing the whole table or at our sought clsid
+ if (pClsid == NULL || IsEqualCLSID(pClsid, &sPatEnt.clsid))
+ {
+ // Print the index of this pattern
+ Printf("%2d ", ulCnt++);
+
+ // Print the file offset
+ Printf("%d\t", sPatEnt.lFileOffset);
+
+ // Print the length of the pattern in bytes
+ Printf("%3d ", sPatEnt.ulCb);
+
+ // Print the mask
+ for (UINT k = 0; k < sPatEnt.ulCb; k++)
+ {
+ Printf("%02x", sPatEnt.abData[k]);
+ }
+ Printf(" ");
+
+ // Print the pattern
+ for (k = 0; k < sPatEnt.ulCb; k++)
+ {
+ Printf("%02x", sPatEnt.abData[sPatEnt.ulCb + k]);
+ }
+ Printf("\n");
+ }
+
+ // Go to the next entry
+ pStart += ulLen;
+ }
+}
diff --git a/private/ole32/dbgexts/dinfolvl.cxx b/private/ole32/dbgexts/dinfolvl.cxx
new file mode 100644
index 000000000..5b4644215
--- /dev/null
+++ b/private/ole32/dbgexts/dinfolvl.cxx
@@ -0,0 +1,320 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: dinfoLevel.cxx
+//
+// Contents: Display and/or set vaious debug info levels
+//
+// Functions: infoLevelHelp
+// displayInfoLevel
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+#include "dinfolvl.h"
+#include "debnot.h"
+
+
+void getArgument(LPSTR *lpArgumentString, LPSTR a);
+ULONG ScanAddr(char *lpsz);
+
+static void initInfoLevels(PNTSD_EXTENSION_APIS lpExtensionApis);
+static BOOL parseVal(char *arg, ULONG *val);
+
+
+
+STable1 debFlags[NUMDEBFLAGS] = {{"error", DEB_ERROR},
+ {"warn", DEB_WARN},
+ {"trace", DEB_TRACE},
+ {"dbgout", DEB_DBGOUT},
+ {"stdout", DEB_STDOUT},
+ {"ierror", DEB_IERROR},
+ {"iwarn", DEB_IWARN},
+ {"itrace", DEB_ITRACE},
+ {"user1", DEB_USER1},
+ {"user2", DEB_USER2},
+ {"user3", DEB_USER3},
+ {"user4", DEB_USER4},
+ {"user5", DEB_USER5},
+ {"user6", DEB_USER6},
+ {"user7", DEB_USER7},
+ {"user8", DEB_USER8},
+ {"user9", DEB_USER9},
+ {"user10", DEB_USER10},
+ {"user11", DEB_USER11},
+ {"user12", DEB_USER12},
+ {"user13", DEB_USER13},
+ {"user14", DEB_USER14},
+ {"user15", DEB_USER15}};
+
+
+STable2 infoLevel[NUMINFOLEVELS] = {{"com", NULL, "ole32!_CairoleInfoLevel"},
+ {"dd", NULL, "ole32!_DDInfoLevel"},
+ {"hep", NULL, "ole32!_heapInfoLevel"},
+ {"hk", NULL, "ole32!_hkInfoLevel"},
+ {"int", NULL, "ole32!_intrInfoLevel"},
+ {"le", NULL, "ole32!_LEInfoLevel"},
+ {"mem", NULL, "ole32!_memInfoLevel"},
+ {"mnk", NULL, "ole32!_mnkInfoLevel"},
+ {"msf", NULL, "ole32!_msfInfoLevel"},
+ {"ol", NULL, "ole32!_olInfoLevel"},
+ {"ref", NULL, "ole32!_RefInfoLevel"},
+ {"sim", NULL, "ole32!_simpInfoLevel"},
+ {"stk", NULL, "ole32!_StackInfoLevel"},
+ {"usr", NULL, "ole32!_UserNdrInfoLevel"}};
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: infoLevelHelp
+//
+// Synopsis: Display a menu for the command 'id'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void infoLevelHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("in - Display current value of all debug info levels\n");
+ Printf("in x - Display the current value of debug info level x\n");
+ Printf("in x y z ... - Set the value of debug info level x to\n");
+ Printf(" y | z | ... \n");
+ Printf("\nwhere x corresponds to:\n");
+ Printf(" --- --------------\n");
+ Printf(" com ole32!_CairoleInfoLevel\n");
+ Printf(" dd ole32!_DDInfoLevel\n");
+ Printf(" hep ole32!_heapInfoLevel\n");
+ Printf(" hk ole32!_hkInfoLevel\n");
+ Printf(" int ole32!_intrInfoLevel\n");
+ Printf(" le ole32!_LEInfoLevel\n");
+ Printf(" mem ole32!_memInfoLevel\n");
+ Printf(" mnk ole32!_mnkInfoLevel\n");
+ Printf(" msf ole32!_msfInfoLevel\n");
+ Printf(" ol ole32!_olInfoLevel\n");
+ Printf(" ref ole32!_RefInfoLevel\n");
+ Printf(" sim ole32!_simpInfoLevel\n");
+ Printf(" stk ole32!_StackInfoLevel\n");
+ Printf(" ndr ole32!_UserNdrInfoLevel\n");
+ Printf("\nand y... corresponds to:\n");
+ Printf(" ---- --------------\n");
+ Printf(" error DEB_ERROR\n");
+ Printf(" warn DEB_WARN\n");
+ Printf(" trace DEB_TRACE\n");
+ Printf(" dbgout DEB_DBGOUT\n");
+ Printf(" stdout DEB_STDOUT\n");
+ Printf(" ierror DEB_IERROR\n");
+ Printf(" iwarn DEB_IWARN\n");
+ Printf(" itrace DEB_ITRACE\n");
+ Printf(" user1 DEB_USER1\n");
+ Printf(" user2 DEB_USER2\n");
+ Printf(" user3 DEB_USER3\n");
+ Printf(" user4 DEB_USER4\n");
+ Printf(" user5 DEB_USER5\n");
+ Printf(" user6 DEB_USER6\n");
+ Printf(" user7 DEB_USER7\n");
+ Printf(" user8 DEB_USER8\n");
+ Printf(" user9 DEB_USER9\n");
+ Printf(" user10 DEB_USER10\n");
+ Printf(" user11 DEB_USER11\n");
+ Printf(" user12 DEB_USER12\n");
+ Printf(" user13 DEB_USER13\n");
+ Printf(" user14 DEB_USER14\n");
+ Printf(" user15 DEB_USER15\n");
+ Printf(" <hex>\n");
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayInfoLevel
+//
+// Synopsis: Display/set debug info levels
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+// [char *] - Command line argument(s)
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayInfoLevel(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ LPSTR lpArgumentString)
+{
+ Arg arg;
+ UINT k;
+ ULONG val;
+ ULONG argVal;
+ BOOL fSet = FALSE;
+
+ // Fetch the addresses for the various debug info levels
+ initInfoLevels(lpExtensionApis);
+
+ // Fetch the first argument
+ GetArg(arg);
+ Printf("%s %s\n", arg, lpArgumentString);
+
+ // If no argument simply display all info levels
+ if (!arg[0])
+ {
+ for (k = 0; k < NUMINFOLEVELS; k++)
+ {
+ ReadMem(&val, infoLevel[k].adr, sizeof(ULONG));
+ Printf("%s\t%08x\n", infoLevel[k].name, val);
+ }
+
+ return;
+ }
+
+ // Check the info level name
+ for (k = 0; k < NUMINFOLEVELS; k++)
+ {
+ if (lstrcmp(arg, infoLevel[k].name) == 0)
+ {
+ break;
+ }
+ }
+ if (k == NUMINFOLEVELS)
+ {
+ Printf("...unknown debug info level name\n");
+ return;
+ }
+
+ // Scan any values to set
+ val = 0;
+ for (GetArg(arg); *arg; GetArg(arg))
+ {
+ if (!parseVal(arg, &argVal))
+ {
+ Printf("...invalid flag expresson\n");
+ return;
+ }
+ val |= argVal;
+ fSet = TRUE;
+ }
+
+ // If only an info level name, then display its value
+ if (!fSet)
+ {
+ ReadMem(&val, infoLevel[k].adr, sizeof(ULONG));
+ Printf("%s\t%08x\n", infoLevel[k].name, val);
+ return;
+ }
+
+ // Otherwise we're setting an info level
+ WriteMem(infoLevel[k].adr, &val, sizeof(ULONG));
+ Printf("%s\t%08x\n", infoLevel[k].name, val);
+}
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: initInfoLevels
+//
+// Synopsis: Find the addresses of the various infolevels
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static void initInfoLevels(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ // Check whether already initialized
+ if (infoLevel[0].adr != NULL)
+ {
+ return;
+ }
+
+ // Do over the info levels
+ for (UINT k = 0; k < NUMINFOLEVELS; k++)
+ {
+ infoLevel[k].adr = GetExpression(infoLevel[k].symbol);
+ }
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: parseVal
+//
+// Synopsis: Parse the next flag expression on the command line
+//
+// Arguments: [char *] - Command line
+// [ULONG *] - Where to return the parsed value
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static BOOL parseVal(char *arg, ULONG *val)
+{
+ UINT k;
+
+ // Check whether it's a flag name
+ for (k = 0; k < NUMDEBFLAGS; k++)
+ {
+ if (lstrcmp(arg, debFlags[k].name) == 0)
+ {
+ *val = debFlags[k].flag;
+ return TRUE;
+ }
+ }
+
+ // It's not so it better be hex
+ k = 0;
+ if (arg[0] == '0' && arg[1] == 'x')
+ {
+ k += 2;
+ }
+ while (arg[k])
+ {
+ if (!(('0' <= arg[k] && arg[k] <= '9') ||
+ ('a' <= arg[k] && arg[k] <= 'f')))
+ {
+ return FALSE;
+ }
+ k++;
+ }
+ *val = ScanAddr(arg);
+ return TRUE;
+}
diff --git a/private/ole32/dbgexts/dinfolvl.h b/private/ole32/dbgexts/dinfolvl.h
new file mode 100644
index 000000000..acaa1a0c0
--- /dev/null
+++ b/private/ole32/dbgexts/dinfolvl.h
@@ -0,0 +1,53 @@
+// Because these are not defined in retail mode
+#if DBG == 0
+# define DEB_ERROR 0x00000001 // exported error paths
+# define DEB_WARN 0x00000002 // exported warnings
+# define DEB_TRACE 0x00000004 // exported trace messages
+
+# define DEB_DBGOUT 0x00000010 // Output to debugger
+# define DEB_STDOUT 0x00000020 // Output to stdout
+
+# define DEB_IERROR 0x00000100 // internal error paths
+# define DEB_IWARN 0x00000200 // internal warnings
+# define DEB_ITRACE 0x00000400 // internal trace messages
+
+# define DEB_USER1 0x00010000 // User defined
+# define DEB_USER2 0x00020000 // User defined
+# define DEB_USER3 0x00040000 // User defined
+# define DEB_USER4 0x00080000 // User defined
+# define DEB_USER5 0x00100000 // User defined
+# define DEB_USER6 0x00200000 // User defined
+# define DEB_USER7 0x00400000 // User defined
+# define DEB_USER8 0x00800000 // User defined
+# define DEB_USER9 0x01000000 // User defined
+# define DEB_USER10 0x02000000 // User defined
+# define DEB_USER11 0x04000000 // User defined
+# define DEB_USER12 0x08000000 // User defined
+# define DEB_USER13 0x10000000 // User defined
+# define DEB_USER14 0x20000000 // User defined
+# define DEB_USER15 0x40000000 // User defined
+#endif
+
+
+const UINT MAXDEBFLAG = 8;
+const UINT NUMDEBFLAGS = 23;
+const UINT NUMINFOLEVELS = 14;
+const UINT MAXSYMBOL = 32;
+
+
+struct STable1
+{
+ char name[MAXDEBFLAG];
+ ULONG flag;
+};
+
+
+
+
+struct STable2
+{
+ char name[4];
+ ULONG adr;
+ char symbol[MAXSYMBOL];
+};
+
diff --git a/private/ole32/dbgexts/dipid.cxx b/private/ole32/dbgexts/dipid.cxx
new file mode 100644
index 000000000..2ab1eb344
--- /dev/null
+++ b/private/ole32/dbgexts/dipid.cxx
@@ -0,0 +1,341 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: dipid.cxx
+//
+// Contents: Ole NTSD extension routines to display CIPID table
+//
+// Functions: ipidHelp
+// displayIpid
+//
+//
+// History: 21-Aug-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+#include "dipid.h"
+
+
+void FormatCLSID(REFGUID rguid, LPSTR lpsz);
+BOOL GetRegistryInterfaceName(REFIID iid, char *szValue, DWORD *pcbValue);
+ULONG ScanAddr(char *lpsz);
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ipidHelp
+//
+// Synopsis: Display a menu for the command 'id'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 21-Aug-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void ipidHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("\nip - Display entire IPID table:\n");
+ Printf("index IPID oxidAddr nextIPIDsameObj\n");
+ Printf("...\n\n");
+ Printf("ip ipid - Display specific IPID entry:\n");
+ Printf("PID TID seq IID ChnlBfr* prxy/stub realPv oxidAddr flags strongRefs weakRefs nextIPIDsameObj\n");
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayIpid
+//
+// Synopsis: Display the entire IPID table
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+//
+// Returns: -
+//
+// History: 21-Aug-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayIpid(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ ULONG pAdr;
+ ULONG pStart;
+ ULONG pEnd;
+ UINT cPages;
+ SIPIDEntry **pIndexTable;
+ SIPIDEntry sIPIDentry[IPIDsPerPage];
+ SOXIDEntry sOXIDentry;
+ char szGuid[CLSIDSTR_MAX];
+
+
+ // Read the IPID page index table
+ pAdr = GetExpression("ole32!CIPIDTable___pTbl");
+ ReadMem(&pStart, pAdr, sizeof(SIPIDEntry **));
+ pAdr = GetExpression("ole32!CIPIDTable___pTblEnd");
+ ReadMem(&pEnd, pAdr, sizeof(SIPIDEntry **));
+ cPages = (pEnd - pStart) / sizeof(SIPIDEntry **);
+ pIndexTable = (SIPIDEntry **) OleAlloc(cPages * sizeof(SIPIDEntry *));
+ ReadMem(pIndexTable, pStart, cPages * sizeof(SIPIDEntry *));
+
+ // Do over IPID entry pages
+ for (UINT k = 0; k < cPages; k++)
+ {
+ // Read the next page of IPID entries
+ ReadMem(sIPIDentry, pIndexTable[k], IPIDTBL_PAGESIZE);
+
+ // Do over entries within this page
+ for (UINT j = 0; j < IPIDsPerPage; j++)
+ {
+ // Only look at non-vacant entries
+ if (!(sIPIDentry[j].dwFlags & IPIDF_VACANT))
+ {
+ // Print the page/offset for this entry
+ Printf("%d.%d ", k, j);
+
+ // Print the IPID
+ if (sIPIDentry[j].ipid.page > 1000 ||
+ sIPIDentry[j].ipid.page < 0)
+ {
+ FormatCLSID((GUID &) sIPIDentry[j].ipid, szGuid);
+ Printf("%s ", szGuid);
+ }
+ else
+ {
+ Printf("[%d.%d %3x %3x %d] ",
+ sIPIDentry[j].ipid.page,
+ sIPIDentry[j].ipid.offset,
+ sIPIDentry[j].ipid.pid,
+ sIPIDentry[j].ipid.tid,
+ sIPIDentry[j].ipid.seq);
+ }
+
+ // Print the associated OXID addr
+ Printf("%x ", sIPIDentry[j].pOXIDEntry);
+
+ // Next IPID for this object
+ if (sIPIDentry[j].iNextOID != -1)
+ {
+ Printf("%d.%d\n",
+ sIPIDentry[j].iNextOID >> 16,
+ sIPIDentry[j].iNextOID & 0xffff);
+ }
+ else
+ {
+ Printf("NULL\n");
+ }
+ }
+ }
+ }
+
+ // Release resources
+ OleFree(pIndexTable);
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayIpidEntry
+//
+// Synopsis: Display an entry in the IPID table
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+// [arg] - IPID of entry to display
+//
+// Returns: -
+//
+// History: 21-Aug-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayIpidEntry(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ char *arg)
+{
+ char *s;
+ IPID ipid;
+ ULONG ppIPIDentry;;
+ SIPIDEntry *pIPIDentry;
+ SIPIDEntry sIPIDentry;
+ char szGuid[CLSIDSTR_MAX];
+ SOXIDEntry sOXID;
+
+
+ // Check for help
+ if (arg[0] == '?')
+ {
+ Printf("PID TID seq IID ChnlBfr* prxy/stub realPv oxidAddr flags strongRefs weakRefs nextIPIDsameObj\n");
+ return;
+ }
+
+ // arg may be either page.offset or a hex address
+ BOOL fAdr = TRUE;
+ for (s = arg; *s; s++)
+ {
+ if (*s == '.')
+ {
+ fAdr = FALSE;
+ }
+ }
+
+ // The argument is a hex address
+ if (fAdr)
+ {
+ pIPIDentry = (SIPIDEntry *) ScanAddr(arg);
+ }
+
+ // The argment has the form page.offset
+ else
+ {
+ // Make sure the argument looks like an IPID
+ BOOL fOk = TRUE;
+ UINT cPoint = 0;
+ if (!IsDecimal(arg[0]))
+ {
+ fOk = FALSE;
+ }
+ for (s = arg; *s; s++)
+ {
+ if (*s != '.' && !IsDecimal(*s))
+ {
+ fOk = FALSE;
+ }
+ if (*s == '.')
+ {
+ cPoint++;
+ }
+ }
+ if (!IsDecimal(*(s - 1)))
+ {
+ fOk = FALSE;
+ }
+ if (!(fOk && cPoint == 1))
+ {
+ Printf("...%s is not an IPID\n", arg);
+ return;
+ }
+
+ // Convert the argument to an IPID
+ for (ipid.page = 0; *arg && *arg != '.'; arg++)
+ {
+ ipid.page = 10 * ipid.page + *arg - '0';
+ }
+ for (arg++, ipid.offset = 0; *arg; arg++)
+ {
+ ipid.offset = 10 * ipid.offset + *arg - '0';
+ }
+
+ // Read the address of the page containing the entry we want
+ ppIPIDentry = GetExpression("ole32!CIPIDTable___pTbl");
+ ReadMem(&ppIPIDentry, ppIPIDentry, sizeof(SIPIDEntry **));
+ ppIPIDentry += ipid.page * sizeof(SIPIDEntry **);
+ ReadMem(&pIPIDentry, ppIPIDentry, sizeof(SIPIDEntry *));
+
+ // Compute the address of the entry we're seeking
+ pIPIDentry += ipid.offset;
+ }
+
+ // Now read the entry
+ ReadMem(&sIPIDentry, pIPIDentry, sizeof(SIPIDEntry));
+
+ // Check whether the entry is vacant
+ if (sIPIDentry.dwFlags & IPIDF_VACANT)
+ {
+ Printf("VACANT\n");
+ return;
+ }
+
+ // The ipid may just be a GUID; e.g. client side scm interfaces
+ if (sIPIDentry.ipid.page >> 1000 || sIPIDentry.ipid.page < 0)
+ {
+ FormatCLSID((GUID &) sIPIDentry.ipid, szGuid);
+ Printf("%s ", szGuid);
+ }
+ else
+ {
+ // Server PID
+ Printf("%3x ", sIPIDentry.ipid.pid);
+
+ // Server TID
+ Printf("%3x ", sIPIDentry.ipid.tid);
+
+ // Sequence number
+ Printf("%d ", sIPIDentry.ipid.seq);
+ }
+
+ // IID
+ DWORD cbValue;
+ if (!GetRegistryInterfaceName(sIPIDentry.iid, szGuid, &cbValue))
+ {
+ FormatCLSID(sIPIDentry.iid, szGuid);
+ }
+ Printf("%s ", szGuid);
+
+ // CRpcChannelBuffer *
+ Printf("%x ", sIPIDentry.pChnl);
+
+ // Address of proxy/stub
+ Printf("%x ", sIPIDentry.pStub);
+
+ // Real interface pinter
+ Printf("%x ", sIPIDentry.pv);
+
+ // Associated OXID
+ Printf("%x ", sIPIDentry.pOXIDEntry);
+
+ // Flags
+ if (sIPIDentry.dwFlags & IPIDF_CONNECTING)
+ {
+ Printf("C");
+ }
+ if (sIPIDentry.dwFlags & IPIDF_DISCONNECTED)
+ {
+ Printf("D");
+ }
+ if (sIPIDentry.dwFlags & IPIDF_SERVERENTRY)
+ {
+ Printf("S");
+ }
+ if (sIPIDentry.dwFlags & IPIDF_NOPING)
+ {
+ Printf("N");
+ }
+ Printf(" ole32!CCacheEnum__Skip+0x82");
+
+ // Strong references
+ Printf("%d ", sIPIDentry.cStrongRefs);
+
+ // Weak references
+ Printf("%d ", sIPIDentry.cWeakRefs);
+
+ // Next IPID for this object (if any)
+ if (sIPIDentry.iNextOID != -1)
+ {
+ Printf("%d.%d\n",
+ sIPIDentry.iNextOID >> 16,
+ sIPIDentry.iNextOID & 0xffff);
+ }
+ else
+ {
+ Printf("NULL\n");
+ }
+}
diff --git a/private/ole32/dbgexts/dipid.h b/private/ole32/dbgexts/dipid.h
new file mode 100644
index 000000000..3bdba1c06
--- /dev/null
+++ b/private/ole32/dbgexts/dipid.h
@@ -0,0 +1,107 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: dipid.h
+//
+// Contents: Contains structure definitons for the significant OXID and
+// IPID structures which the ntsd extensions need to access.
+// These ole classes cannot be accessed more cleanly because
+// typically the members of interest are protected.
+//
+// WARNING. IF THE REFERENCED OLE CLASSES CHANGE, THEN THESE
+// DEFINITIONS MUST CHANGE!
+//
+// History: 08-11-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+
+
+
+typedef GUID OXID;
+
+
+struct IPID
+{
+ WORD offset; // These are reversed because of little-endian
+ WORD page; // These are reversed because of little-endian
+ DWORD pid;
+ DWORD tid;
+ DWORD seq;
+};
+
+
+struct STRINGARRAY
+{
+ unsigned long size;
+ unsigned short awszStringArray[1];
+};
+
+
+
+struct SOXIDEntry
+{
+ struct SOXIDEntry *pPrev; // previous entry on inuse list
+ struct SOXIDEntry *pNext; // next entry on free/inuse list
+ DWORD dwPid; // process id of server
+ DWORD dwTid; // thread id of server
+ OXID oxid; // object exporter identifier
+ STRINGARRAY *psa; // ptr to server obj exp string arrary
+ DWORD dwFlags; // state flags
+ handle_t hServer; // rpc binding handle of server
+ void *pRU; // proxy for Remote Unknown
+ IPID ipidRundown;// IPID of IRundown and Remote Unknown
+ LONG cRefs; // count of IPIDs using this OXIDEntry
+};
+
+
+
+
+typedef enum tagOXIDFLAGS
+{
+ OXIDF_REGISTERED = 1, // oxid is registered with Resolver
+ OXIDF_MACHINE_LOCAL = 2, // oxid is local to this machine
+ OXIDF_STOPPED = 4, // thread can no longer receive calls
+ OXIDF_PENDINGRELEASE= 8 // oxid entry is already being released
+} OXIDFLAGS;
+
+
+#define OXIDTBL_PAGESIZE 4096
+
+
+// Forward reference
+struct SRpcChannelBuffer;
+
+
+struct SIPIDEntry
+{
+ IPID ipid; // interface pointer identifier
+ IID iid; // interface iid
+ SRpcChannelBuffer *pChnl; // channel pointer
+ IUnknown *pStub; // proxy or stub pointer
+ void *pv; // real interface pointer
+ SOXIDEntry *pOXIDEntry; // ptr to OXIDEntry in OXID Table
+ DWORD dwFlags; // flags (see IPIDFLAGS)
+ ULONG cStrongRefs;// strong reference count
+ ULONG cWeakRefs; // weak reference count
+ LONG iNextOID; // next entry in this table for same object
+};
+
+
+
+typedef enum tagIPIDFLAGS
+{
+ IPIDF_CONNECTING = 1, // ipid is being connected
+ IPIDF_DISCONNECTED = 2, // ipid is disconnected
+ IPIDF_SERVERENTRY = 4, // SERVER IPID vs CLIENT IPID
+ IPIDF_NOPING = 8, // dont need to ping the server or release
+ IPIDF_VACANT = 128 // entry is vacant (ie available to reuse)
+} IPIDFLAGS;
+
+
+#define IPIDTBL_PAGESIZE 4096
+#define IPIDTBL_PAGESHIFT 16
+#define IPIDTBL_PAGEMASK 0x0000ffff
+
+#define IPIDsPerPage (IPIDTBL_PAGESIZE / sizeof(SIPIDEntry))
diff --git a/private/ole32/dbgexts/dirs b/private/ole32/dbgexts/dirs
new file mode 100644
index 000000000..52db9fdb2
--- /dev/null
+++ b/private/ole32/dbgexts/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ BruceMa 01-Jun-1995
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ daytona \
+
+
diff --git a/private/ole32/dbgexts/dmoniker.cxx b/private/ole32/dbgexts/dmoniker.cxx
new file mode 100644
index 000000000..c07b2b7e4
--- /dev/null
+++ b/private/ole32/dbgexts/dmoniker.cxx
@@ -0,0 +1,931 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: dmoniker.cxx
+//
+// Contents: Interpret a moniker object
+//
+// Functions: monikersHelp
+// displayMonikers
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+#include "dmoniker.h"
+
+
+
+
+
+static void displayFileMoniker(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker);
+
+static void displayFileMonikerCk(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker);
+
+static void displayItemMoniker(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker);
+
+static void displayItemMonikerCk(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker);
+
+static void displayCompositeMoniker(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker);
+
+static void displayCompositeMonikerCk(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker);
+
+static void displayPointerMoniker(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker);
+
+static void displayPointerMonikerCk(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker);
+
+static void displayAntiMoniker(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker);
+
+static void displayAntiMonikerCk(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker);
+
+static enum mnkType findMnkType(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker);
+
+
+extern BOOL fInScm;
+static BOOL fRetail;
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: monikerHelp
+//
+// Synopsis: Display a menu for the command 'mk'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void monikerHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("mk addr - Interpret addr as a moniker\n");
+}
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayMoniker
+//
+// Synopsis: Display a moniker
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+BOOL displayMoniker(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker)
+{
+ ULONG pAdr;
+ enum mnkType mType;
+
+ // Determine if this is checked or retail ole
+ if (fInScm)
+ {
+ pAdr = GetExpression("scm!_CairoleInfoLevel");
+ }
+ else
+ {
+ pAdr = GetExpression("ole32!_CairoleInfoLevel");
+ }
+ fRetail = pAdr == NULL ? TRUE : FALSE;
+
+
+ mType = findMnkType(hProcess, lpExtensionApis, pMoniker);
+ switch (mType)
+ {
+ case NOMNK:
+ return FALSE;
+
+ case FILEMNK:
+ if (fRetail)
+ {
+ displayFileMoniker(hProcess, lpExtensionApis, pMoniker);
+ }
+ else
+ {
+ displayFileMonikerCk(hProcess, lpExtensionApis, pMoniker);
+ }
+ return TRUE;
+
+ case POINTERMNK:
+ if (fRetail)
+ {
+ displayPointerMoniker(hProcess, lpExtensionApis, pMoniker);
+ }
+ else
+ {
+ displayPointerMonikerCk(hProcess, lpExtensionApis, pMoniker);
+ }
+ return TRUE;
+
+ case ITEMMNK:
+ if (fRetail)
+ {
+ displayItemMoniker(hProcess, lpExtensionApis, pMoniker);
+ }
+ else
+ {
+ displayItemMonikerCk(hProcess, lpExtensionApis, pMoniker);
+ }
+ return TRUE;
+
+ case ANTIMNK:
+ if (fRetail)
+ {
+ displayAntiMoniker(hProcess, lpExtensionApis, pMoniker);
+ }
+ else
+ {
+ displayAntiMonikerCk(hProcess, lpExtensionApis, pMoniker);
+ }
+ return TRUE;
+
+ case COMPOSITEMNK:
+ if (fRetail)
+ {
+ displayCompositeMoniker(hProcess, lpExtensionApis, pMoniker);
+ }
+ else
+ {
+ displayCompositeMonikerCk(hProcess, lpExtensionApis, pMoniker);
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayFileMoniker
+//
+// Synopsis: Display a retail file moniker
+//
+// Arguments: [ULONG] - The moniker
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static void displayFileMoniker(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker)
+{
+ SFileMonikerCk file;
+ WCHAR *pwszPath;
+
+ // Fetch the moniker
+ ReadMem(&file, pMoniker, sizeof(SFileMoniker));
+
+ // It's a file moniker
+ Printf("File Moniker\n");
+
+ // The current references
+ Printf("refs = %d\n", file.m_refs);
+
+ // The path
+ pwszPath = (WCHAR *) OleAlloc(2 * (file.m_ccPath + 1));
+ ReadMem(pwszPath, file.m_szPath, 2 * (file.m_ccPath + 1));
+ Printf("%ws", pwszPath);
+ OleFree(pwszPath);
+ if (file.m_fHashValueValid)
+ {
+ Printf(" (%d)\n", file.m_dwHashValue);
+ }
+ else
+ {
+ Printf("\n");
+ }
+
+ // The version
+ if (file.m_ole1 == ole1)
+ {
+ Printf("ole1\n");
+ }
+
+ // The anti count (if any)
+ if (file.m_cAnti)
+ {
+ Printf("CAnti count = %d\n", file.m_cAnti);
+ }
+
+ // The extents (if any)
+ if (file.m_ExtentList.m_cbMonikerExtents)
+ {
+ BYTE *pExtent;
+ BYTE *pEnd ;
+ ULONG cbExtentBytes;
+
+ // A header
+ Printf("Extents:\n");
+
+ // Read all the extents
+ pExtent = (BYTE *) OleAlloc(file.m_ExtentList.m_cbMonikerExtents);
+ ReadMem(pExtent, file.m_ExtentList.m_pchMonikerExtents,
+ file.m_ExtentList.m_cbMonikerExtents);
+ pEnd = pExtent;
+
+ // Do over the extents
+ while (pExtent < pEnd)
+ {
+ // Fetch length
+ cbExtentBytes = (*pExtent++ << 16) | *pExtent++;
+
+ // Fetch and display key
+ switch (*pExtent++)
+ {
+ case mnk_MAC:
+ Printf("mnk_MAC ");
+ break;
+
+ case mnk_DFS:
+ Printf("mnk_DFS ");
+ break;
+
+ case mnk_UNICODE:
+ Printf("mnk_UNICODE ");
+ break;
+
+ case mnk_MacPathName:
+ Printf("mnk_MacPathName ");
+ break;
+
+ case mnk_ShellLink:
+ Printf("mnk_ShellLink ");
+ break;
+
+ default:
+ Printf("%15d ");
+ }
+
+ // Display the extent in hexadecimal
+ UINT k = 0;
+
+ while (cbExtentBytes--)
+ {
+ Printf("%2x ", *pExtent++);
+ k++;
+ if (k % 16 == 0)
+ {
+ Printf("\n ");
+ k = 0;
+ }
+ }
+ if (k % 8 != 0)
+ {
+ Printf("\n");
+ }
+ }
+
+ // Release the allocated extent buffer
+ OleFree(pExtent);
+ }
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayFileMonikerCk
+//
+// Synopsis: Display a checked file moniker
+//
+// Arguments: [ULONG] - The moniker
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static void displayFileMonikerCk(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker)
+{
+ SFileMonikerCk file;
+ WCHAR *pwszPath;
+
+ // Fetch the moniker
+ ReadMem(&file, pMoniker, sizeof(SFileMonikerCk));
+
+ // It's a file moniker
+ Printf("File Moniker\n");
+
+ // The current references
+ Printf("refs = %d\n", file.m_refs);
+
+ // The path
+ pwszPath = (WCHAR *) OleAlloc(2 * (file.m_ccPath + 1));
+ ReadMem(pwszPath, file.m_szPath, 2 * (file.m_ccPath + 1));
+ Printf("%ws", pwszPath);
+ OleFree(pwszPath);
+ if (file.m_fHashValueValid)
+ {
+ Printf(" (%d)\n", file.m_dwHashValue);
+ }
+ else
+ {
+ Printf("\n");
+ }
+
+ // The version
+ if (file.m_ole1 == ole1)
+ {
+ Printf("ole1\n");
+ }
+
+ // The anti count (if any)
+ if (file.m_cAnti)
+ {
+ Printf("CAnti count = %d\n", file.m_cAnti);
+ }
+
+ // The extents (if any)
+ if (file.m_ExtentList.m_cbMonikerExtents)
+ {
+ BYTE *pExtent;
+ BYTE *pEnd ;
+ ULONG cbExtentBytes;
+
+ // A header
+ Printf("Extents:\n");
+
+ // Read all the extents
+ pExtent = (BYTE *) OleAlloc(file.m_ExtentList.m_cbMonikerExtents);
+ ReadMem(pExtent, file.m_ExtentList.m_pchMonikerExtents,
+ file.m_ExtentList.m_cbMonikerExtents);
+ pEnd = pExtent;
+
+ // Do over the extents
+ while (pExtent < pEnd)
+ {
+ // Fetch length
+ cbExtentBytes = (*pExtent++ << 16) | *pExtent++;
+
+ // Fetch and display key
+ switch (*pExtent++)
+ {
+ case mnk_MAC:
+ Printf("mnk_MAC ");
+ break;
+
+ case mnk_DFS:
+ Printf("mnk_DFS ");
+ break;
+
+ case mnk_UNICODE:
+ Printf("mnk_UNICODE ");
+ break;
+
+ case mnk_MacPathName:
+ Printf("mnk_MacPathName ");
+ break;
+
+ case mnk_ShellLink:
+ Printf("mnk_ShellLink ");
+ break;
+
+ default:
+ Printf("%15d ");
+ }
+
+ // Display the extent in hexadecimal
+ UINT k = 0;
+
+ while (cbExtentBytes--)
+ {
+ Printf("%2x ", *pExtent++);
+ k++;
+ if (k % 16 == 0)
+ {
+ Printf("\n ");
+ k = 0;
+ }
+ }
+ if (k % 8 != 0)
+ {
+ Printf("\n");
+ }
+ }
+
+ // Release the allocated extent buffer
+ OleFree(pExtent);
+ }
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayItemMoniker
+//
+// Synopsis: Display a retail item moniker
+//
+// Arguments: [ULONG] - The moniker
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static void displayItemMoniker(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker)
+{
+ SItemMonikerCk item;
+ WCHAR *pwszItem;
+ WCHAR *pwszDelimiter;
+
+ // Fetch the moniker
+ ReadMem(&item, pMoniker, sizeof(SItemMoniker));
+
+ // It's an item moniker
+ Printf("Item Moniker\n");
+
+ // The current references
+ Printf("refs = %d\n", item.m_refs);
+
+ // The delimiter plus item
+ pwszDelimiter = (WCHAR *) OleAlloc(2 * (item.m_ccDelimiter + 1));
+ ReadMem(pwszDelimiter, item.m_lpszDelimiter, 2 * (item.m_ccDelimiter + 1));
+ pwszItem = (WCHAR *) OleAlloc(2 * (item.m_ccItem + 1));
+ ReadMem(pwszItem, item.m_lpszItem, 2 * (item.m_ccItem + 1));
+ Printf("item = %ws%ws\n", pwszDelimiter, pwszItem);
+ OleFree(pwszItem);
+
+ // The hash value
+ if (item.m_fHashValueValid)
+ {
+ Printf("hash = %d\n", item.m_dwHashValue);
+ }
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayItemMonikerCk
+//
+// Synopsis: Display a checked item moniker
+//
+// Arguments: [ULONG] - The moniker
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static void displayItemMonikerCk(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker)
+{
+ SItemMonikerCk item;
+ WCHAR *pwszItem;
+ WCHAR *pwszDelimiter;
+
+ // Fetch the moniker
+ ReadMem(&item, pMoniker, sizeof(SItemMonikerCk));
+
+ // It's an item moniker
+ Printf("Item Moniker\n");
+
+ // The current references
+ Printf("refs = %d\n", item.m_refs);
+
+ // The delimiter plus item
+ pwszDelimiter = (WCHAR *) OleAlloc(2 * (item.m_ccDelimiter + 1));
+ ReadMem(pwszDelimiter, item.m_lpszDelimiter, 2 * (item.m_ccDelimiter + 1));
+ pwszItem = (WCHAR *) OleAlloc(2 * (item.m_ccItem + 1));
+ ReadMem(pwszItem, item.m_lpszItem, 2 * (item.m_ccItem + 1));
+ Printf("item = %ws%ws\n", pwszDelimiter, pwszItem);
+ OleFree(pwszItem);
+
+ // The hash value
+ if (item.m_fHashValueValid)
+ {
+ Printf("hash = %d\n", item.m_dwHashValue);
+ }
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayCompositeMoniker
+//
+// Synopsis: Display a retail composite moniker
+//
+// Arguments: [ULONG] - The moniker
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static void displayCompositeMoniker(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker)
+{
+ SCompositeMonikerCk composite;
+
+ // Fetch the moniker
+ ReadMem(&composite, pMoniker, sizeof(SCompositeMoniker));
+
+ // It's a composite moniker
+ Printf("Composite Moniker\n");
+
+ // The current references
+ Printf("refs = %d\n", composite.m_refs);
+
+ // Reduced?
+ if (composite.m_fReduced)
+ {
+ Printf("reduced\n");
+ }
+
+ // The left component
+ Printf("\nleft component\n");
+ Printf("--------------\n");
+ if (composite.m_pmkLeft)
+ {
+ displayMoniker(hProcess, lpExtensionApis,
+ (ULONG) composite.m_pmkLeft);
+ }
+ else
+ {
+ Printf("NULL\n");
+ }
+
+ // The right component
+ Printf("\nright component\n");
+ Printf("---------------\n");
+ if (composite.m_pmkRight)
+ {
+ displayMoniker(hProcess, lpExtensionApis,
+ (ULONG) composite.m_pmkRight);
+ }
+ else
+ {
+ Printf("NULL\n");
+ }
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayCompositeMonikerCk
+//
+// Synopsis: Display a checked composite moniker
+//
+// Arguments: [ULONG] - The moniker
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static void displayCompositeMonikerCk(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker)
+{
+ SCompositeMonikerCk composite;
+
+ // Fetch the moniker
+ ReadMem(&composite, pMoniker, sizeof(SCompositeMonikerCk));
+
+ // It's a composite moniker
+ Printf("Composite Moniker\n");
+
+ // The current references
+ Printf("refs = %d\n", composite.m_refs);
+
+ // Reduced?
+ if (composite.m_fReduced)
+ {
+ Printf("reduced\n");
+ }
+
+ // The left component
+ Printf("\nleft component\n");
+ Printf("--------------\n");
+ if (composite.m_pmkLeft)
+ {
+ displayMoniker(hProcess, lpExtensionApis,
+ (ULONG) composite.m_pmkLeft);
+ }
+ else
+ {
+ Printf("NULL\n");
+ }
+
+ // The right component
+ Printf("\nright component\n");
+ Printf("---------------\n");
+ if (composite.m_pmkRight)
+ {
+ displayMoniker(hProcess, lpExtensionApis,
+ (ULONG) composite.m_pmkRight);
+ }
+ else
+ {
+ Printf("NULL\n");
+ }
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayPointerMoniker
+//
+// Synopsis: Display a retail pointer moniker
+//
+// Arguments: [ULONG] - The moniker
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static void displayPointerMoniker(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker)
+{
+ SPointerMoniker pointer;
+
+ // Fetch the moniker
+ ReadMem(&pointer, pMoniker, sizeof(SPointerMoniker));
+
+ // It's a pointer moniker
+ Printf("Pointer Moniker\n");
+
+ // The current references
+ Printf("refs = %d\n", pointer.m_refs);
+
+ // The pointer
+ Printf("IUnknown = %08x\n", pointer.m_pUnk);
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayPointerMonikerCk
+//
+// Synopsis: Display a checked pointer moniker
+//
+// Arguments: [ULONG] - The moniker
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static void displayPointerMonikerCk(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker)
+{
+ SPointerMonikerCk pointer;
+
+ // Fetch the moniker
+ ReadMem(&pointer, pMoniker, sizeof(SPointerMonikerCk));
+
+ // It's a pointer moniker
+ Printf("Pointer Moniker\n");
+
+ // The current references
+ Printf("refs = %d\n", pointer.m_refs);
+
+ // The pointer
+ Printf("IUnknown = %08x\n", pointer.m_pUnk);
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayAntiMoniker
+//
+// Synopsis: Display a retail anti moniker
+//
+// Arguments: [ULONG] - The moniker
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static void displayAntiMoniker(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker)
+{
+ SAntiMoniker anti;
+
+ // Fetch the moniker
+ ReadMem(&anti, pMoniker, sizeof(SAntiMoniker));
+
+ // It's a pointer moniker
+ Printf("Anti Moniker\n");
+
+ // The current references
+ Printf("refs = %d\n", anti.m_refs);
+
+ // The count
+ Printf("count = %d\n", anti.m_count);
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayAntiMonikerCk
+//
+// Synopsis: Display a checked anti moniker
+//
+// Arguments: [ULONG] - The moniker
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static void displayAntiMonikerCk(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker)
+{
+ SAntiMonikerCk anti;
+
+ // Fetch the moniker
+ ReadMem(&anti, pMoniker, sizeof(SAntiMonikerCk));
+
+ // It's a pointer moniker
+ Printf("Anti Moniker\n");
+
+ // The current references
+ Printf("refs = %d\n", anti.m_refs);
+
+ // The count
+ Printf("count = %d\n", anti.m_count);
+}
+
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: findMnkType
+//
+// Synopsis: Given a moniker, compute its type
+//
+// Arguments: [HANDLE] - process handle
+// [PNTSD_EXTENSION_APIS] Convenience routines
+// [ULONG] - The moniker
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+static enum mnkType findMnkType(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker)
+{
+ void *vtbl;
+ char szSymbol[128];
+ DWORD dwOffset;
+
+ // Read the symbol for the first element in the first vtbl
+ ReadMem(&vtbl, pMoniker, sizeof(ULONG));
+ ReadMem(&vtbl, vtbl, sizeof(ULONG));
+ szSymbol[0] = '\0';
+ GetSymbol(vtbl, (UCHAR *) szSymbol, &dwOffset);
+
+ // We better be looking at a QueryInterface on a moniker
+ if (dwOffset != 0)
+ {
+ return NOMNK;
+ }
+ if (lstrcmp(szSymbol, "ole32!CFileMoniker__QueryInterface") == 0)
+ {
+ return FILEMNK;
+ }
+ else if (lstrcmp(szSymbol, "ole32!CItemMoniker__QueryInterface") == 0)
+ {
+ return ITEMMNK;
+ }
+ else if (lstrcmp(szSymbol, "ole32!CCompositeMoniker__QueryInterface") == 0)
+ {
+ return COMPOSITEMNK;
+ }
+ else if (lstrcmp(szSymbol, "ole32!CPointerMoniker__QueryInterface") == 0)
+ {
+ return POINTERMNK;
+ }
+ else if (lstrcmp(szSymbol, "ole32!CAntiMoniker__QueryInterface") == 0)
+ {
+ return ANTIMNK;
+ }
+ else
+ {
+ return NOMNK;
+ }
+}
diff --git a/private/ole32/dbgexts/dmoniker.h b/private/ole32/dbgexts/dmoniker.h
new file mode 100644
index 000000000..70ad42a6e
--- /dev/null
+++ b/private/ole32/dbgexts/dmoniker.h
@@ -0,0 +1,215 @@
+enum mnkType {NOMNK, FILEMNK, POINTERMNK, ITEMMNK, ANTIMNK, COMPOSITEMNK};
+
+
+
+enum olever {undetermined, ole1, ole2 };
+
+
+
+enum ExtentKeys
+{
+ mnk_MAC = 1,
+ mnk_DFS = 2,
+ mnk_UNICODE = 3,
+ mnk_MacPathName = 4,
+ mnk_ShellLink = 5
+};
+
+
+
+struct SExtentList
+{
+ ULONG m_cbMonikerExtents;
+ BYTE *m_pchMonikerExtents;
+};
+
+
+
+struct SFileMoniker
+{
+ void *vtbl1;
+ void *vtbl2;
+ ULONG m_refs;
+ void *vtbl3;
+ ULONG m_marshal;
+ CLSID m_clsid;
+ SExtentList m_ExtentList;
+ WCHAR *m_szPath;
+ char *m_pszAnsiPath;
+ USHORT m_ccPath;
+ USHORT m_cbAnsiPath;
+ DWORD m_dwHashValue;
+ ULONG m_fUnicodeExtent:1;
+ ULONG m_fClassVerified:1;
+ ULONG m_fHashValueValid:1;
+ USHORT m_cAnti;
+ USHORT m_endServer;
+ enum olever m_ole1;
+};
+
+
+
+struct SFileMonikerCk
+{
+ void *vtbl1;
+ void *vtbl2;
+ ULONG m_refs;
+ void *vtbl3;
+ ULONG m_marshal;
+ void *vtbl4;
+ ULONG m_debug;
+ CLSID m_clsid;
+ SExtentList m_ExtentList;
+ WCHAR *m_szPath;
+ char *m_pszAnsiPath;
+ USHORT m_ccPath;
+ USHORT m_cbAnsiPath;
+ DWORD m_dwHashValue;
+ ULONG m_fUnicodeExtent:1;
+ ULONG m_fClassVerified:1;
+ ULONG m_fHashValueValid:1;
+ USHORT m_cAnti;
+ USHORT m_endServer;
+ enum olever m_ole1;
+};
+
+
+
+
+struct SPointerMoniker
+{
+ void *vtbl1;
+ void *vtbl2;
+ ULONG m_refs;
+ void *vtbl3;
+ ULONG m_marshal;
+ LPUNKNOWN m_pUnk;
+};
+
+
+
+
+struct SPointerMonikerCk
+{
+ void *vtbl1;
+ void *vtbl2;
+ ULONG m_refs;
+ void *vtbl3;
+ ULONG m_marshal;
+ void *vtbl4;
+ ULONG m_debug;
+ LPUNKNOWN m_pUnk;
+};
+
+
+
+
+struct SItemMoniker
+{
+ void *vtbl1;
+ void *vtbl2;
+ ULONG m_refs;
+ void *vtbl3;
+ ULONG m_marshal;
+ WCHAR *m_lpszItem;
+ char *m_pszAnsiItem;
+ USHORT m_ccItem;
+ USHORT m_cbAnsiItem;
+ WCHAR *m_lpszDelimiter;
+ char *m_pszAnsiDelimiter;
+ USHORT m_ccDelimiter;
+ USHORT m_cbAnsiDelimiter;
+ ULONG m_fHashValueValid:1;
+ DWORD m_dwHashValue;
+};
+
+
+
+
+struct SItemMonikerCk
+{
+ void *vtbl1;
+ void *vtbl2;
+ ULONG m_refs;
+ void *vtbl3;
+ ULONG m_marshal;
+ void *vtbl4;
+ ULONG m_debug;
+ WCHAR *m_lpszItem;
+ char *m_pszAnsiItem;
+ USHORT m_ccItem;
+ USHORT m_cbAnsiItem;
+ WCHAR *m_lpszDelimiter;
+ char *m_pszAnsiDelimiter;
+ USHORT m_ccDelimiter;
+ USHORT m_cbAnsiDelimiter;
+ ULONG m_fHashValueValid:1;
+ DWORD m_dwHashValue;
+};
+
+
+
+
+
+struct SAntiMoniker
+{
+ void *vtbl1;
+ void *vtbl2;
+ ULONG m_refs;
+ void *vtbl3;
+ ULONG m_marshal;
+ ULONG m_count;
+};
+
+
+
+
+
+struct SAntiMonikerCk
+{
+ void *vtbl1;
+ void *vtbl2;
+ ULONG m_refs;
+ void *vtbl3;
+ ULONG m_marshal;
+ void *vtbl4;
+ ULONG m_debug;
+ ULONG m_count;
+};
+
+
+
+
+
+struct SCompositeMoniker
+{
+ void *vtbl1;
+ void *vtbl2;
+ ULONG m_refs;
+ void *vtbl3;
+ ULONG m_marshal;
+ LPMONIKER m_pmkLeft;
+ LPMONIKER m_pmkRight;
+ BOOL m_fReduced;
+};
+
+
+
+
+
+struct SCompositeMonikerCk
+{
+ void *vtbl1;
+ void *vtbl2;
+ ULONG m_refs;
+ void *vtbl3;
+ ULONG m_marshal;
+ void *vtbl4;
+ ULONG m_debug;
+ LPMONIKER m_pmkLeft;
+ LPMONIKER m_pmkRight;
+ BOOL m_fReduced;
+};
+
+
+
diff --git a/private/ole32/dbgexts/doxid.cxx b/private/ole32/dbgexts/doxid.cxx
new file mode 100644
index 000000000..44ef0f637
--- /dev/null
+++ b/private/ole32/dbgexts/doxid.cxx
@@ -0,0 +1,261 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: doxid.cxx
+//
+// Contents: Ole NTSD extension routines to display COXID table
+//
+// Functions: oxidHelp
+// displayOxid
+//
+//
+// History: 21-Aug-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+#include "dipid.h"
+
+
+void FormatCLSID(REFGUID rguid, LPSTR lpsz);
+BOOL ScanCLSID(LPSTR lpsz, CLSID *pClsid);
+ULONG ScanAddr(char *lpsz);
+
+
+
+static char *aszProtSeq[] = {/* 0x00 */ 0,
+ /* 0x01 */ "mswmsg",
+ /* 0x02 */ 0,
+ /* 0x03 */ 0,
+ /* 0x04 */ "ncacn_dnet_dsp",
+ /* 0x05 */ 0,
+ /* 0x06 */ 0,
+ /* 0x07 */ "ncacn_ip_tcp",
+ /* 0x08 */ "ncadg_ip_udp",
+ /* 0x09 */ "ncacn_nb_tcp",
+ /* 0x0a */ 0,
+ /* 0x0b */ 0,
+ /* 0x0c */ "ncacn_spx",
+ /* 0x0d */ "ncacn_nb_ipx",
+ /* 0x0e */ "ncadg_ipx",
+ /* 0x0f */ "ncacn_np",
+ /* 0x10 */ "ncalrpc",
+ /* 0x11 */ 0,
+ /* 0x12 */ 0,
+ /* 0x13 */ "ncacn_nb_nb"};
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: oxidHelp
+//
+// Synopsis: Display a menu for the command 'id'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 21-Aug-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void oxidHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("\nox - Display entire OXID table:\n");
+ Printf("addr oxid\n");
+ Printf("...\n\n");
+ Printf("ox addr - Display specific OXID entry:\n");
+ Printf("oxid serverPid serverTid flags hRpc IRemUnknown* runDownIPID refs stringBindings\n");
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayOxid
+//
+// Synopsis: Display the entire OXID table
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+//
+// Returns: -
+//
+// History: 21-Aug-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayOxid(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ ULONG pAdr;
+ SOXIDEntry *pOXIDentry;
+ SOXIDEntry *pFirstOXIDentry;
+ SOXIDEntry sOXIDentry;
+ char szGuid[CLSIDSTR_MAX];
+ STRINGARRAY *pBindings;
+ ULONG ulSize;
+
+
+ // Read the address of the first in use OXID entry
+ pAdr = GetExpression("ole32!COXIDTable___InUseHead");
+ pFirstOXIDentry = (SOXIDEntry *) pAdr;
+ ReadMem(&pOXIDentry, pAdr + sizeof(ULONG), sizeof(SOXIDEntry *));
+
+ // Do over in use OXID entries
+ do
+ {
+ // Read the next OXID entry
+ ReadMem(&sOXIDentry, pOXIDentry, sizeof(SOXIDEntry));
+
+ // Print the address
+ Printf("%x ", pOXIDentry);
+
+ // Print the OXID
+ FormatCLSID((GUID &) sOXIDentry.oxid, szGuid);
+ Printf("%s\n", szGuid);
+
+ // Go to the next in use OXID entry
+ pOXIDentry = sOXIDentry.pNext;
+
+ // Just in case
+ if (CheckControlC())
+ {
+ return;
+ }
+ } until_(pOXIDentry == pFirstOXIDentry);
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayOxidEntry
+//
+// Synopsis: Display an entry in the OXID table
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+// [arg] - OXID of entry to display
+//
+// Returns: -
+//
+// History: 21-Aug-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayOxidEntry(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ char *arg)
+{
+ OXID oxid;
+ ULONG pAdr;
+ SOXIDEntry *pOXIDentry;
+ SOXIDEntry *pFirstOXIDentry;
+ SOXIDEntry sOXIDentry;
+ char szGuid[CLSIDSTR_MAX];
+ STRINGARRAY *pBindings;
+ ULONG ulSize;
+
+
+ // Check for help
+ if (arg[0] == '?')
+ {
+ Printf("oxid serverPid serverTid flags hRpc IRemUnknown* runDownIPID refs stringBindings\n");
+ return;
+ }
+
+ // Convert the argument to an OXID
+ pAdr = ScanAddr(arg);
+
+ // Read the OXID entry
+ ReadMem(&sOXIDentry, pAdr, sizeof(SOXIDEntry));
+
+ // OXID
+ FormatCLSID((GUID &) sOXIDentry.oxid, szGuid);
+ Printf("%s ", szGuid);
+
+ // Server PID
+ Printf("%3x ", sOXIDentry.dwPid);
+
+ // Server TID
+ Printf("%3x ", sOXIDentry.dwTid);
+
+ // Flags
+ if (sOXIDentry.dwFlags & OXIDF_REGISTERED)
+ {
+ Printf("R");
+ }
+ if (sOXIDentry.dwFlags & OXIDF_MACHINE_LOCAL)
+ {
+ Printf("L");
+ }
+ if (sOXIDentry.dwFlags & OXIDF_STOPPED)
+ {
+ Printf("S");
+ }
+ if (sOXIDentry.dwFlags & OXIDF_PENDINGRELEASE)
+ {
+ Printf("P");
+ }
+ Printf(" ");
+
+ // RPC binding handle
+ Printf("%x ", sOXIDentry.hServer);
+
+ // Proxy for RemUnknown
+ Printf("%x ", sOXIDentry.pRU);
+
+ // IPID of IRunDown and Remote Unknown
+ Printf("[%d.%d %3x %3x %d] ",
+ sOXIDentry.ipidRundown.page,
+ sOXIDentry.ipidRundown.offset,
+ sOXIDentry.ipidRundown.pid,
+ sOXIDentry.ipidRundown.tid,
+ sOXIDentry.ipidRundown.seq);
+
+ // References
+ Printf("%d\n ", sOXIDentry.cRefs);
+
+ // Print the string bindings
+ ReadMem(&ulSize, sOXIDentry.psa, sizeof(ULONG));
+ pBindings = (STRINGARRAY *) OleAlloc(ulSize * sizeof(WCHAR));
+ ReadMem(pBindings, sOXIDentry.psa, ulSize * sizeof(WCHAR));
+
+ // Do over protocol sequence/network address pairs
+ for (UINT k = 0; k < ulSize - 2 ||
+ pBindings->awszStringArray[k] == 0; )
+ {
+ char *pszProtSeq;
+
+ // The protocol sequence
+ pszProtSeq = aszProtSeq[pBindings->awszStringArray[k]];
+ if (pszProtSeq == NULL)
+ {
+ Printf("%d", pBindings->awszStringArray[k]);
+ }
+ else
+ {
+ Printf("%s", pszProtSeq);
+ }
+ k++;
+
+ // The network address
+ Printf("%ws ", &pBindings->awszStringArray[k]);
+ k += lstrlenW(&pBindings->awszStringArray[k]) + 1;
+ }
+ Printf("\n");
+ OleFree(pBindings);
+}
diff --git a/private/ole32/dbgexts/dpsclsid.cxx b/private/ole32/dbgexts/dpsclsid.cxx
new file mode 100644
index 000000000..b48dc01b3
--- /dev/null
+++ b/private/ole32/dbgexts/dpsclsid.cxx
@@ -0,0 +1,334 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: dpsclsid.cxx
+//
+// Contents: Ole NTSD extension routines to dump the proxy/stub
+// clsid cache
+//
+// Functions: psClsidHelp
+// displayPsClsidTbl
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+#include "dshrdmem.h"
+
+
+
+
+BOOL IsEqualCLSID(CLSID *pClsid1, CLSID *pClsid2);
+void FormatCLSID(REFGUID rguid, LPSTR lpsz);
+BOOL GetRegistryInterfaceName(REFIID iid, char *szValue, DWORD *pcbValue);
+BOOL GetRegistryClsidKey(REFCLSID clsid, char *szKey,
+ char *szValue, DWORD *pcbValue);
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: psClsidHelp
+//
+// Synopsis: Display a menu for the command 'ps'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void psClsidHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("ps - Display infomation for all IID's\n");
+ Printf("ps IID - Display infomation for IID\n");
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayPsClsidTbl
+//
+// Synopsis: Given an interface IID display the CLSID of the
+// associated proxy/stub handler dll
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+// [lpFileExtTbl] - Address of file extensions table
+// [pClsid] - Only for this clsid
+//
+// Returns: -
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayPsClsidTbl(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ SDllShrdTbl *pShrdTbl,
+ IID *pIid)
+{
+ SDllShrdTbl sDllTbl;
+ GUIDMAP sGuidMap;
+ GUIDPAIR *pGuidPair;
+ DWORDPAIR *pDwordPair;
+ IID iid = {0, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}};
+ char szClsid[CLSIDSTR_MAX];
+ char szName[129];
+ DWORD cbValue;
+
+ // Read the shared table locally
+ ReadMem(&sDllTbl, pShrdTbl, sizeof(SDllShrdTbl));
+
+ // Read the guid map locally
+ ReadMem(&sGuidMap, sDllTbl._PSClsidTbl._pGuidMap, sizeof(GUIDMAP));
+
+ // Allocate for the guid pair list
+ pGuidPair = (GUIDPAIR *) OleAlloc(sGuidMap.ulCntLong * sizeof(GUIDPAIR));
+
+ // Allocate for the dword pair list
+ pDwordPair = (DWORDPAIR *) OleAlloc(sGuidMap.ulCntShort *
+ sizeof(DWORDPAIR));
+
+ // Read the guid pair list
+ ReadMem(pGuidPair, sDllTbl._PSClsidTbl._pLongList -
+ (sGuidMap.ulCntLong - 1),
+ sGuidMap.ulCntLong * sizeof(GUIDPAIR));
+
+ // Read the dword pair list
+ ReadMem(pDwordPair, sDllTbl._PSClsidTbl._pShortList,
+ sGuidMap.ulCntShort * sizeof(DWORDPAIR));
+
+ // Are we looking for a specific IID?
+ if (pIid != NULL)
+ {
+ // Search the short list first
+ for (UINT cCnt = 0; cCnt < sGuidMap.ulCntShort; pDwordPair++, cCnt++)
+ {
+ if (pIid->Data1 == pDwordPair->dw1)
+ {
+ iid.Data1 = pIid->Data1;
+
+ // Fetch and print the interface name
+ cbValue = 64;
+ if(GetRegistryInterfaceName(iid, szName, &cbValue))
+ {
+ Printf("%s\t", szName);
+ }
+ else
+ {
+ Printf("-\t");
+ }
+
+ // The clsid
+ iid.Data1 = pDwordPair->dw2;
+ FormatCLSID(iid, szClsid);
+ Printf("%s\t", szClsid);
+
+ // Fetch and print the proxy/stub handler dll
+ cbValue = 128;
+ if (GetRegistryClsidKey(iid, "InprocServer32", szName,
+ &cbValue))
+ {
+ Printf("%s\n", szName);
+ }
+ else if(GetRegistryClsidKey(iid, "InprocServer", szName,
+ &cbValue))
+ {
+ Printf("%s(16)\n", szName);
+ }
+ else
+ {
+ Printf("-\n");
+ }
+
+ return;
+ }
+ }
+
+ // Search the long list next
+ for (cCnt = 0; cCnt < sGuidMap.ulCntLong; pGuidPair++, cCnt++)
+ {
+ if (IsEqualCLSID(pIid, &pGuidPair->guid1))
+ {
+ // Fetch and print the interface name
+ cbValue = 64;
+ if(GetRegistryInterfaceName(pGuidPair->guid1, szName,
+ &cbValue))
+ {
+ Printf("%s\t", szName);
+ }
+ else
+ {
+ Printf("-\t");
+ }
+
+ // The clsid
+ FormatCLSID(pGuidPair->guid2, szClsid);
+ Printf("%s\t", szClsid);
+
+ // Fetch and print the proxy/stub handler dll
+ cbValue = 128;
+ if (GetRegistryClsidKey(pGuidPair->guid2, "InprocServer32",
+ szName,
+ &cbValue))
+ {
+ Printf("%s\n", szName);
+ }
+ else if(GetRegistryClsidKey(pGuidPair->guid2, "InprocServer",
+ szName, &cbValue))
+ {
+ Printf("%s(16)\n", szName);
+ }
+ else
+ {
+ Printf("-\n");
+ }
+
+ return;
+ }
+ }
+ }
+
+ // Else dump everything
+ else
+ {
+ // Print header
+ Printf("where -. = '-0000-0000-C000-000000000046}'\n\n");
+ Printf(" IID interface clsid p/s dll\n");
+ Printf("----------- ------------------ ----------- ---------\n");
+ // Do over the short list
+ for (UINT cCnt = 0 ; cCnt < sGuidMap.ulCntShort; pDwordPair++, cCnt++)
+ {
+ // Print the IID
+ iid.Data1 = pDwordPair->dw1;
+ FormatCLSID(iid, szClsid);
+ if (lstrcmp(&szClsid[9], "-0000-0000-C000-000000000046}") == 0)
+ {
+ szClsid[9] = '\0';
+ Printf("%s-.", szClsid);
+ }
+ else
+ {
+ Printf("%s\n", szClsid);
+ }
+
+ // Fetch and print the interface name
+ cbValue = 64;
+ if(GetRegistryInterfaceName(iid, szName, &cbValue))
+ {
+ Printf(" %s", szName);
+ }
+ else
+ {
+ Printf(" -");
+ }
+
+ // Do some pretty printing alignment
+ for (UINT cCh = 24 - lstrlen(szName); cCh > 0; cCh--)
+ {
+ Printf(" ");
+ }
+ Printf(" ");
+
+ // The clsid
+ iid.Data1 = pDwordPair->dw2;
+ FormatCLSID(iid, szClsid);
+ if (lstrcmp(&szClsid[9], "-0000-0000-C000-000000000046}") == 0)
+ {
+ szClsid[9] = '\0';
+ Printf("%s-.\t", szClsid);
+ }
+ else
+ {
+ Printf("%s\t", szClsid);
+ }
+
+ // Fetch and print the proxy/stub handler dll
+ cbValue = 128;
+ if (GetRegistryClsidKey(iid, "InprocServer32", szName, &cbValue))
+ {
+ Printf("%s\n", szName);
+ }
+ else if(GetRegistryClsidKey(iid, "InprocServer", szName,
+ &cbValue))
+ {
+ Printf("%s(16)\n", szName);
+ }
+ else
+ {
+ Printf("-\n");
+ }
+ }
+
+ // Do over the long list
+ for (cCnt = 0; cCnt < sGuidMap.ulCntLong; pGuidPair++, cCnt++)
+ {
+ // Print the IID
+ FormatCLSID(pGuidPair->guid1, szClsid);
+ Printf("%s ", szClsid);
+
+ // Fetch and print the interface name
+ cbValue = 64;
+ if(GetRegistryInterfaceName(pGuidPair->guid1, szName, &cbValue))
+ {
+ Printf(" %s", szName);
+ }
+ else
+ {
+ Printf(" -");
+ }
+
+ // Do some pretty printing alignment
+ for (UINT cCh = 24 - lstrlen(szName); cCh > 0; cCh--)
+ {
+ Printf(" ");
+ }
+ Printf(" ");
+
+ // The clsid
+ FormatCLSID(pGuidPair->guid2, szClsid);
+ if (lstrcmp(&szClsid[9], "-0000-0000-C000-000000000046}") == 0)
+ {
+ szClsid[9] = '\0';
+ Printf("%s-.\t", szClsid);
+ }
+ else
+ {
+ Printf("%s\t", szClsid);
+ }
+
+ // Fetch and print the proxy/stub handler dll
+ cbValue = 128;
+ if (GetRegistryClsidKey(pGuidPair->guid2, "InprocServer32",
+ szName, &cbValue))
+ {
+ Printf("%s\n", szName);
+ }
+ else if(GetRegistryClsidKey(iid, "InprocServer32", szName,
+ &cbValue))
+ {
+ Printf("%s(16)\n", szName);
+ }
+ else
+ {
+ Printf("-\n");
+ }
+ }
+ }
+
+ // Release allocated resources
+ OleFree(pGuidPair);
+ OleFree(pDwordPair);
+}
diff --git a/private/ole32/dbgexts/drot.cxx b/private/ole32/dbgexts/drot.cxx
new file mode 100644
index 000000000..d6b654424
--- /dev/null
+++ b/private/ole32/dbgexts/drot.cxx
@@ -0,0 +1,322 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: drot.cxx
+//
+// Contents: Ole NTSD extension routines to display the ROT
+//
+// Functions: displayRot
+//
+//
+// History: 06-01-95 BruceMa Created
+// 06-26-95 BruceMa Add SCM ROT support
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+#include "drot.h"
+
+
+void FormatCLSID(REFGUID rguid, LPSTR lpsz);
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: cliRotHelp
+//
+// Synopsis: Display a menu for the command 'rt'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void cliRotHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("rt - Display the Running Object Table:\n");
+ Printf("Client side ROT\n");
+ Printf("sig\tcall?\t(scmLoc scmId)\thApt\n");
+ Printf("...\n\n");
+ Printf("Client side hint table\n");
+ Printf("<indices of set indicators>\n");
+}
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: scmRotHelp
+//
+// Synopsis: Display a menu for the command 'rt'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void scmRotHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("rt - Display the Running Object Table:\n");
+ Printf("Client side ROT\n");
+ Printf("sig\tcall?\t(scmLoc scmId)\thApt\n");
+ Printf("...\n\n");
+ Printf("Client side hint table\n");
+ Printf("<indices of set indicators>\n");
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayCliRot
+//
+// Synopsis: Formats and writes an ole processes' version of the
+// ROT to the debug terminal
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+//
+// Returns: -
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayCliRot(HANDLE hProcess, PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ ULONG padr;
+ SRunningObjectTable *psRot;
+ SRunningObjectTable sRot;
+ SRotItem sRotItm;
+ SRotItem **ppsRotItm;
+ SRotItem *psRotItm;
+ int cSize;
+
+ // Read the CRunningObjectTable
+ padr = GetExpression("ole32!pRot");
+ ReadMem(&psRot, padr, sizeof(SRunningObjectTable *));
+ ReadMem(&sRot, psRot, sizeof(SRunningObjectTable));
+
+ // Read the array of pointers to ROT items
+ UINT ulSize = sRot._afvRotList.m_nSize * sizeof(SRotItem *);
+
+ ppsRotItm = (SRotItem **) OleAlloc(ulSize);
+ ReadMem(ppsRotItm, sRot._afvRotList.m_pData, ulSize);
+
+ // Display the ROT items in the table
+ Printf("Client side ROT\n");
+ for (cSize = 0; cSize < sRot._afvRotList.m_nSize; cSize++)
+ {
+ psRotItm = ppsRotItm[cSize];
+ if (psRotItm != NULL)
+ {
+ // Fetch the next ROT item
+ ReadMem(&sRotItm, psRotItm, sizeof(SRotItem));
+
+ // Display this ROT item
+ if (sRotItm._fDontCallApp)
+ {
+ Printf("%d\tTRUE\t(%x %x)\t%x\n",
+ sRotItm._wItemSig,
+ sRotItm._scmregkey.dwEntryLoc,
+ sRotItm._scmregkey.dwScmId,
+ sRotItm._hApt);
+ }
+ else
+ {
+ Printf("%d\tFALSE\t(%x %x)\t%x\n",
+ sRotItm._wItemSig,
+ sRotItm._scmregkey.dwEntryLoc,
+ sRotItm._scmregkey.dwScmId,
+ sRotItm._hApt);
+ }
+ }
+ }
+
+
+ // Display the client side ROT hint table
+ BYTE *pHint;
+ UINT k, l;
+
+ // Read the client side ROT hint table
+ pHint = (BYTE *) OleAlloc(SCM_HASH_SIZE * sizeof(DWORD));
+ ReadMem(pHint, sRot._crht._pbHintArray, SCM_HASH_SIZE * sizeof(BYTE));
+
+ // Display the client side hint table
+ Printf("\nClient side hint table\n");
+ for (l = 0, k = 0; k < SCM_HASH_SIZE; k++)
+ {
+ if (l == 16)
+ {
+ Printf("\n");
+ l = 0;
+ }
+ if (pHint[k])
+ {
+ Printf("%02d ", k);
+ l++;
+ }
+ }
+ if (l > 1)
+ {
+ Printf("\n");
+ }
+
+
+ // Delete resources
+ OleFree(ppsRotItm);
+ OleFree(pHint);
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayScmRot
+//
+// Synopsis: Formats and writes the full ROT to the debug terminal
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+//
+// Returns: -
+//
+// History: 26-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayScmRot(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ ULONG addr;
+ UINT cEnt;
+ char szClsid[CLSIDSTR_MAX];
+ SPerMachineROT sPerMachineRot;
+ SRotAcctEntry sRotAcctEntry;
+ SScmRot sScmRot;
+ SScmRotEntry **ppScmHashTbl;
+ SScmRotEntry *pScmRotEntry;
+ SScmRotEntry sScmRotEntry;
+ WCHAR wszSID[64];
+ char szSID[64];
+ MNKEQBUF *pMnkEqBfr;
+ IFData sIFData;
+ SYSTEMTIME sSystemTime;
+
+ // Get the address of the per machine ROT global
+ addr = GetExpression("scm!pPerMachineRot");
+
+ // Read the CPerMachineRot
+ ReadMem(&addr, addr, sizeof(ULONG));
+ ReadMem(&sPerMachineRot, addr, sizeof(SPerMachineROT));
+
+ // Read the first CRotAcctEntry
+ ReadMem(&sRotAcctEntry, sPerMachineRot._safvRotAcctTable.m_pData,
+ sizeof(SRotAcctEntry));
+
+ // Read the CScmRot table
+ ReadMem(&sScmRot, sRotAcctEntry.pscmrot, sizeof(SScmRot));
+
+ // Read the hash table of CScmRotEntry *'s
+ ppScmHashTbl = (SScmRotEntry **) OleAlloc(sScmRot._sht._ndwHashTableSize *
+ sizeof(SScmRotEntry *));
+ ReadMem(ppScmHashTbl, sScmRot._sht._apsheHashTable,
+ sScmRot._sht._ndwHashTableSize * sizeof(SScmRotEntry *));
+
+ // A header
+ ReadMem(wszSID, sRotAcctEntry.unicodestringSID, 64);
+ Unicode2Ansi(szSID, wszSID, 64);
+ szSID[32] = '\0';
+ Printf("\nSCM side ROT for SID %s\n\n", szSID);
+
+ // Do over entries in the hash table
+ for (cEnt = 0, pScmRotEntry = ppScmHashTbl[0];
+ cEnt < sScmRot._sht._ndwHashTableSize;
+ cEnt++, pScmRotEntry = ppScmHashTbl[cEnt])
+ {
+ // Only look at non-empty entries
+ while (pScmRotEntry)
+ {
+ // Read the CScmRotEntry
+ ReadMem(&sScmRotEntry, pScmRotEntry, sizeof(SScmRotEntry));
+
+ // Read the moniker comparison buffer
+ ULONG ulSize;
+
+ ReadMem(&ulSize, sScmRotEntry._pmkeqbufKey, sizeof(ULONG));
+ pMnkEqBfr = (MNKEQBUF *) OleAlloc(sizeof(ULONG) + ulSize);
+ ReadMem(pMnkEqBfr, sScmRotEntry._pmkeqbufKey,
+ sizeof(ULONG) + ulSize);
+
+ // Read the interface data buffer
+ ReadMem(&sIFData, sScmRotEntry._pifdObject,
+ sizeof(IFData));
+
+ // The registration Id
+ Printf("RegID: %x\n", sScmRotEntry._dwScmRotId);
+
+ // The moniker display name
+ Unicode2Ansi(szSID, pMnkEqBfr->_wszName, 64);
+ Printf("Display Name: %s\n", szSID);
+
+ // The last time changed
+ FileTimeToSystemTime(&sScmRotEntry._filetimeLastChange,
+ &sSystemTime);
+ Printf("Last Change: %2d:%02d:%02d %2d/%2d/%2d\n",
+ sSystemTime.wHour - 7,
+ sSystemTime.wMinute,
+ sSystemTime.wSecond,
+ sSystemTime.wMonth,
+ sSystemTime.wDay,
+ sSystemTime.wYear - 1900);
+
+ // The clsid of the moniker
+ FormatCLSID(pMnkEqBfr->_clsid, szClsid);
+ Printf("Moniker Type: %s\n", szClsid);
+
+ // The server unique id (from CoGetCurrentProcess())
+ Printf("Server ID: %d\n", sScmRotEntry._dwProcessID);
+
+ // The RPC end point
+ Unicode2Ansi(szSID, sIFData._wszEndPoint, 64);
+ Printf("Endpoint: %s\n", szSID);
+
+ // The object ID
+ FormatCLSID(sIFData._oid, szClsid);
+ Printf("Object OID: %s\n", szClsid);
+
+ // The IID of the object
+ FormatCLSID(sIFData._iid, szClsid);
+ Printf("Object IID: %s\n\n", szClsid);
+
+ // The hash table entry can be a list, i.e. a hash bucket, of
+ // ROT entries having the same hash value
+ pScmRotEntry = sScmRotEntry._sheNext;
+
+ // Release the moniker compare buffer
+ OleFree(pMnkEqBfr);
+ }
+ }
+
+ OleFree(ppScmHashTbl);
+}
diff --git a/private/ole32/dbgexts/drot.h b/private/ole32/dbgexts/drot.h
new file mode 100644
index 000000000..fb9d651ab
--- /dev/null
+++ b/private/ole32/dbgexts/drot.h
@@ -0,0 +1,160 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: drot.h
+//
+// Contents: Contains structure definitons for the significant ROT
+// classes which the ntsd extensions need to access.
+// These ole classes cannot be accessed more cleanly because
+// typically the members of interest are private.
+//
+// WARNING. IF THE REFERENCED OLE CLASSES CHANGE, THEN THESE
+// DEFINITIONS MUST CHANGE!
+//
+// History: 06-01-95 BruceMa Created
+// 06-26-95 BruceMa Add SCM ROT support
+//
+//--------------------------------------------------------------------------
+
+
+#define SCM_HASH_SIZE 251
+
+
+struct SCMREGKEY
+{
+ DWORD dwEntryLoc;
+ DWORD dwScmId;
+};
+
+
+
+
+struct SRotItem
+{
+ WORD _wItemSig;
+ BOOL _fDontCallApp;
+ SCMREGKEY _scmregkey;
+ HAPT _hApt;
+};
+
+
+
+
+
+struct SCliRotHintTable
+{
+ BYTE *_pbHintArray;
+ HANDLE _hSm;
+};
+
+
+
+
+
+struct SRunningObjectTable
+{
+ LPVOID _vtbl;
+ SArrayFValue _afvRotList;
+ SCliRotHintTable _crht;
+ WORD _wSigRotItem;
+};
+
+
+
+
+struct SPerMachineROT
+{
+ SMutexSem _mxs;
+ DWORD _dwTotalAcctsReg;
+ SArrayFValue _safvRotAcctTable;
+};
+
+
+
+
+struct SScmRotHintTable
+{
+ HANDLE _hSm;
+};
+
+
+
+
+struct MNKEQBUF
+{
+ DWORD _cbSize;
+ CLSID _clsid;
+ WCHAR _wszName[1];
+};
+
+
+
+
+struct IFData
+{
+ DWORD _UNUSED[3];
+ GUID _oid;
+ DWORD _UNUSED2;
+ IID _iid;
+ DWORD _UNUSED3[4];
+ WCHAR _wszEndPoint[64];
+};
+
+
+
+
+struct SScmRotEntry
+{
+ LPVOID _vtbl;
+ SScmRotEntry *_sheNext;
+ DWORD _dwSig;
+ DWORD _dwScmRotId;
+ DWORD _dwProcessID;
+ FILETIME _filetimeLastChange;
+ IFData *_pifdObject;
+ MNKEQBUF *_pmkeqbufKey;
+ IFData *_pifdObjectName;
+ BYTE _ab[1];
+};
+
+
+
+
+struct SScmHashEntry
+{
+ SScmHashEntry * _sheNext;
+};
+
+
+
+
+struct SScmHashTable
+{
+ DWORD UNUSED;
+ SScmHashEntry **_apsheHashTable;
+ DWORD _ndwHashTableSize;
+ DWORD _ndwCount;
+};
+
+
+
+
+struct SScmRot
+{
+ SMutexSem _mxs;
+ DWORD _dwIdCntr;
+ SScmRotHintTable _rht;
+ SScmHashTable _sht;
+};
+
+
+
+
+struct SRotAcctEntry
+{
+ DWORD UNUSED;
+ WCHAR *unicodestringSID;
+ SScmRot *pscmrot;
+};
diff --git a/private/ole32/dbgexts/dshrdmem.h b/private/ole32/dbgexts/dshrdmem.h
new file mode 100644
index 000000000..27aa83adc
--- /dev/null
+++ b/private/ole32/dbgexts/dshrdmem.h
@@ -0,0 +1,179 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: dshrdmem.h
+//
+// Contents: Contains structure definitons for the significant file
+// extensions table classes which the ntsd extensions need
+// to access. These ole classes cannot be accessed more
+// cleanly because typically the members of interest are private.
+//
+// WARNING. IF THE REFERENCED OLE CLASSES CHANGE, THEN THESE
+// DEFINITIONS MUST CHANGE!
+//
+// History: 06-01-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+
+
+
+
+
+struct DWORDPAIR
+{
+ DWORD dw1; // IID
+ DWORD dw2; // CLSID
+};
+
+
+
+
+struct GUIDPAIR
+{
+ GUID guid1; // IID
+ GUID guid2; // CLSID
+};
+
+
+
+
+struct GUIDMAP
+{
+ ULONG ulSize; // size of table
+ ULONG ulFreeSpace; // Free space in table
+ ULONG ulCntShort; // number of entries in the short list
+ ULONG ulCntLong; // number of entries in the long list
+};
+
+
+
+struct SShrdTblHdr
+{
+ DWORD dwSeqNum; // update sequence number
+ ULONG OffsIIDTbl; // offset of the start of IID table
+ ULONG OffsPatTbl; // offset to start of file pattern table
+ ULONG OffsExtTbl; // offset to file extension table
+ ULONG OffsClsTbl; // offset to start of CLSID table
+ ULONG pad[1]; // pad to 8 byte boundary
+};
+
+
+
+
+struct SSharedMemoryBlock
+{
+ HANDLE _hMem;
+ BYTE *_pbBase;
+ ULONG _culCommitSize; // current commit size
+ ULONG _culInitCommitSize; // initial commit size
+ BOOL _fCreated; // mem created vs already existed
+ BOOL _fReadWrite; // want read/write access
+};
+
+
+
+
+struct SSmMutex
+{
+ BOOL _fCreated;
+ HANDLE _hMutex;
+};
+
+
+
+
+struct SPSClsidTbl
+{
+ GUIDMAP * _pGuidMap; // ptr to table header
+ DWORDPAIR * _pShortList; // list of OLE style guids
+ GUIDPAIR * _pLongList; // list of non OLE style guids
+};
+
+
+
+
+struct STblHdr
+{
+ ULONG ulSize; // size of pattern table
+ ULONG cbLargest; // largest pattern size
+ ULONG OffsStart; // offset to start of entries
+ ULONG OffsEnd; // offset to end of entries
+};
+
+
+
+
+struct SPatternEntry
+{
+ CLSID clsid; // index of clsid the pattern maps to
+ ULONG ulEntryLen; // length of this entry
+ LONG lFileOffset; // offset in file where pattern begins
+ ULONG ulCb; // count bytes in pattern
+ BYTE abData[128]; // start of mask & pattern strings
+};
+
+
+
+
+struct SPatternTbl
+{
+ STblHdr *_pTblHdr; // ptr to table header struct
+ BYTE *_pStart; // ptr to first entry in the memory block
+};
+
+
+
+
+struct SExtTblHdr
+{
+ ULONG ulSize; // table size
+ ULONG cEntries; // count of entries in table
+ ULONG OffsStart; // offset to start of entries
+ ULONG OffsEnd; // offset to end of entries
+};
+
+
+
+
+
+struct SExtEntry
+{
+ CLSID Clsid; // clsid the extension maps to
+ ULONG ulEntryLen; // length of this entry
+ WCHAR wszExt[1]; // start of filename extension
+};
+
+
+
+
+
+struct SFileExtTbl
+{
+ SExtTblHdr *_pTblHdr; // ptr to table header structure
+ BYTE *_pStart; // ptr to first entry in the memory block
+};
+
+
+
+
+struct SDllShrdTbl
+{
+ SSharedMemoryBlock _smb; // shared memory block
+ SSmMutex _mxs; // shared mutex
+ HANDLE _hRegEvent; // shared event handle
+
+ SPSClsidTbl _PSClsidTbl; // proxy stub clsid table
+ SPatternTbl _PatternTbl; // file pattern table
+ SFileExtTbl _FileExtTbl; // file extension table
+
+ SShrdTblHdr *_pShrdTblHdr; // shared mem copy of table
+ DWORD _dwSeqNum; // sequence number
+};
+
+
+
+
+
+
diff --git a/private/ole32/dbgexts/dstdid.cxx b/private/ole32/dbgexts/dstdid.cxx
new file mode 100644
index 000000000..cf9319ec1
--- /dev/null
+++ b/private/ole32/dbgexts/dstdid.cxx
@@ -0,0 +1,186 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: dstdid.cxx
+//
+// Contents: Ole NTSD extension routines to display CStdIdentity table
+//
+// Functions: stdidHelp
+// displayStdid
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+#include "dipid.h"
+#include "dchannel.h"
+#include "dstdid.h"
+
+
+void FormatCLSID(REFGUID rguid, LPSTR lpsz);
+ULONG ScanAddr(char *lpsz);
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: stdidHelp
+//
+// Synopsis: Display a menu for the command 'id'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void stdidHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("\nid - Display entire CStdIdentity table:\n");
+ Printf("addr oid tid pUnkControl\n");
+ Printf("...\n\n");
+ Printf("\nid <stdidAdr> - Display CStdIdentity entry:\n");
+ Printf("oid mrshlFlags 1stIPID chnlBfr nestedCalls mrshlTime pUnkOuter [pIEC] strongRefs\n");
+ Printf("...\n\n");
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayStdid
+//
+// Synopsis: Display the CStdIdentify table
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayStdid(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG p)
+{
+ SIDArray stdidtbl;
+ int nEnt;
+ IDENTRY *pStdEntries;
+ IDENTRY stdEntry;
+ SStdIdentity stdid;
+ char szOID[CLSIDSTR_MAX];
+ SRpcChannelBuffer chanBfr;
+
+ // Read the standard identity table
+ ReadMem(&stdidtbl, p, sizeof(SIDArray));
+
+ // Do over entries in this table
+ for (nEnt = 0, pStdEntries = (IDENTRY *) stdidtbl.m_afv.m_pData;
+ nEnt < stdidtbl.m_afv.m_nSize;
+ nEnt++, pStdEntries++)
+ {
+ // Read the next entry
+ ReadMem(&stdEntry, pStdEntries, sizeof(IDENTRY));
+
+ // CStdIdentity address
+ Printf("%x ", stdEntry.m_pStdID);
+
+ // Display the object identifier
+ FormatCLSID(stdEntry.m_oid, szOID);
+ Printf("%s ", szOID);
+
+ // The thread ID
+ Printf("%3x ", stdEntry.m_tid);
+
+ // pUnkControl
+ Printf("%x\n", stdEntry.m_pUnkControl);
+ }
+
+ Printf("\n");
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayStdidEntry
+//
+// Synopsis: Display an entry in the CStdIdentify table
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayStdidEntry(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG p,
+ char *arg)
+{
+ ULONG pAdr;
+ SStdIdentity stdid;
+ char szOID[CLSIDSTR_MAX];
+
+
+ // Check for help
+ if (arg[0] == '?')
+ {
+ Printf("oid mrshlFlags 1stIPID chnlBfr nestedCalls mrshlTime pUnkOuter [pIEC] strongRefs\n");
+ return;
+ }
+
+ // Read the standard identity entry
+ pAdr = ScanAddr(arg);
+ ReadMem(&stdid, pAdr, sizeof(SStdIdentity));
+
+ // Display the object identifier
+ FormatCLSID(stdid.m_oid, szOID);
+ Printf("%s ", szOID);
+
+ // Marshal flags
+ Printf("%08x ", stdid._dwFlags);
+
+ // First IPID
+ Printf("%d.%d ", stdid._iFirstIPID >> 16, stdid._iFirstIPID & 0xffff);
+
+ // Address of CRpcChannelBuffer
+ Printf("%x ", stdid._pChnl);
+
+ // Count of nested calls
+ Printf("%d ", stdid._cNestedCalls);
+
+ // Marshal time
+ Printf("%d ", stdid._dwMarshalTime);
+
+ // Address of pUnkOuter
+ Printf("%x ", stdid.m_pUnkOuter);
+
+ // Address of IExternalConnection (if present)
+ if (stdid.m_pIEC)
+ {
+ Printf("%x ", stdid.m_pIEC);
+ }
+
+ // Count of strong references
+ Printf("%d\n", stdid.m_cStrongRefs);
+}
diff --git a/private/ole32/dbgexts/dstdid.h b/private/ole32/dbgexts/dstdid.h
new file mode 100644
index 000000000..a37b98b50
--- /dev/null
+++ b/private/ole32/dbgexts/dstdid.h
@@ -0,0 +1,55 @@
+typedef enum tagSTDID_FLAGS
+{
+ STDID_SERVER = 0, // on server side
+ STDID_CLIENT = 1, // on client side (non-local in RH terms)
+ STDID_STDMARSHAL = 2, // was created with PSTDMARSHAL
+ STDID_HASEC = 4, // server supports IEC for connections
+} STDID_FLAGS;
+
+
+
+
+
+struct SIDArray
+{
+ SArrayFValue m_afv;
+};
+
+
+
+
+
+struct IDENTRY
+{
+ OID m_oid;
+ DWORD m_tid;
+ IUnknown *m_pUnkControl;
+ IStdIdentity *m_pStdID;
+};
+
+
+// Forward reference
+struct SRpcChannelBuffer;
+
+
+struct SStdIdentity
+{
+ void *vtbl1;
+ void *vtbl2;
+ DWORD _dwFlags;
+ LONG _iFirstIPID;
+ SStdIdentity *_pStdId;
+ SRpcChannelBuffer *_pChnl;
+ CLSID _clsidHandler;
+ LONG _cNestedCalls;
+ DWORD _dwMarshalTime;
+ void *vtbl3;
+ DWORD m_refs;
+ DWORD m_flags;
+ IUnknown *m_pUnkOuter;
+ IUnknown *m_pUnkControl;
+ OID m_oid;
+ IExternalConnection *m_pIEC;
+ ULONG m_cStrongRefs;
+};
+
diff --git a/private/ole32/dbgexts/dtreatas.cxx b/private/ole32/dbgexts/dtreatas.cxx
new file mode 100644
index 000000000..e9c76a80b
--- /dev/null
+++ b/private/ole32/dbgexts/dtreatas.cxx
@@ -0,0 +1,142 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: dtreatas.cxx
+//
+// Contents: Ole NTSD extension routines to display a dll/class cache
+//
+// Functions: displayTreatAsCache
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+#include "dtreatas.h"
+
+
+extern BOOL fInScm;
+
+
+void FormatCLSID(REFGUID rguid, LPSTR lpsz);
+BOOL IsEqualCLSID(CLSID *pClsid1, CLSID *pClsid2);
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: treatAsCacheHelp
+//
+// Synopsis: Display a menu for the command 'ds'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void treatAsCacheHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("ta - Display entire TreatAs class cache:\n");
+ Printf("ta clsid - Display Treat As class for clsid (if any)\n");
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayTreatAsCache
+//
+// Synopsis: Formats and writes all or part of the TreatAs class cache
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+// [REFCLSID] - If not CLSID_NULL only for this clsid
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayTreatAsCache(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ CLSID *clsid)
+{
+ ULONG pAdr;
+ BOOL fRetail;
+ ULONG gptrtlstTreatClasses;
+ ULONG pTreatAs;
+ STreatList sTreatList;
+ STreatEntry *pTreatEntry;
+ BOOL fInit = TRUE;
+ char szClsid[CLSIDSTR_MAX];
+
+ // Determine if this is checked or retail ole
+ if (fInScm)
+ {
+ pAdr = GetExpression("scm!_CairoleInfoLevel");
+ }
+ else
+ {
+ pAdr = GetExpression("ole32!_CairoleInfoLevel");
+ }
+ fRetail = pAdr == NULL ? TRUE : FALSE;
+
+ // Read the pointer to the TreatAs class cache
+ gptrtlstTreatClasses = GetExpression("ole32!gptrtlstTreatClasses");
+ ReadMem(&pTreatAs, gptrtlstTreatClasses, sizeof(ULONG));
+ if (pTreatAs == NULL)
+ {
+ return;
+ }
+
+ // Read the TreatAs cache header
+ ReadMem(&sTreatList, pTreatAs, sizeof(STreatList));
+
+ Printf(" clsid is treated as clsid\n");
+ Printf("-------------------------------------- --------------------------------------\n");
+
+ if (sTreatList._centries > 0)
+ {
+ // Read the array of entries
+ pTreatEntry = (STreatEntry *) OleAlloc(sTreatList._centries *
+ sizeof(STreatEntry));
+ ReadMem(pTreatEntry, sTreatList._array.m_pData,
+ sTreatList._centries * sizeof(STreatEntry));
+
+ for (DWORD i = 0; i < sTreatList._centries; i++)
+ {
+ // Display the clsid and the TreatAs clsid
+ if (clsid == NULL)
+ {
+ FormatCLSID(pTreatEntry[i]._clsid, szClsid);
+ Printf("%s ", szClsid);
+ FormatCLSID(pTreatEntry[i]._treatAsClsid, szClsid);
+ Printf("%s\n", szClsid);
+ }
+
+ // We are looking for a particular clsid
+ else if (IsEqualCLSID(clsid, &pTreatEntry[i]._clsid))
+ {
+ FormatCLSID(pTreatEntry[i]._clsid, szClsid);
+ Printf("%s ", szClsid);
+ FormatCLSID(pTreatEntry[i]._treatAsClsid, szClsid);
+ Printf("%s\n", szClsid);
+ return;
+ }
+ }
+ }
+}
+
diff --git a/private/ole32/dbgexts/dtreatas.h b/private/ole32/dbgexts/dtreatas.h
new file mode 100644
index 000000000..77ed4ed85
--- /dev/null
+++ b/private/ole32/dbgexts/dtreatas.h
@@ -0,0 +1,14 @@
+struct STreatEntry
+{
+ CLSID _clsid;
+ CLSID _treatAsClsid;
+};
+
+
+
+struct STreatList
+{
+ SArrayFValue _array;
+ DWORD UNUSED[7];
+ DWORD _centries;
+};
diff --git a/private/ole32/dbgexts/dvtbl.cxx b/private/ole32/dbgexts/dvtbl.cxx
new file mode 100644
index 000000000..cf1327489
--- /dev/null
+++ b/private/ole32/dbgexts/dvtbl.cxx
@@ -0,0 +1,131 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: dvtbl.cxx
+//
+// Contents: Ole NTSD extension routines to dump a vtbl
+//
+// Functions: displayVtbl
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: vtblHelp
+//
+// Synopsis: Display a menu for the command 'vt'
+//
+// Arguments: -
+//
+// Returns: -
+//
+// History: 07-Mar-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void vtblHelp(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("vt obj - Interpret vtbl for object obj:\n");
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: displayVtbl
+//
+// Synopsis: Given an object interpret its vtbl
+//
+// Arguments: [hProcess] - Handle of this process
+// [lpExtensionApis] - Table of extension functions
+//
+// Returns: -
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void displayVtbl(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ void *lpObj)
+{
+ DWORD lpVtbl = 0xdeaddead;
+ DWORD dwVtblOffset;
+ char achSymbol[256];
+
+
+ // Get the address of the vtbl
+ ReadMem(&lpVtbl, lpObj, sizeof(LPVOID));
+
+ // Check for some reasonableness
+ if (lpVtbl == 0 || lpVtbl == 0xdededede || lpVtbl == 0xedededed ||
+ lpVtbl == 0xdeaddead)
+ {
+ if (lpVtbl == 0xdeaddead)
+ {
+ Printf("...vtbl pointer could not be read\n");
+ }
+ else
+ {
+ Printf("...vtbl pointer == 0x%x is unreasonable\n", lpVtbl);
+ }
+ return;
+ }
+
+ // vtbl entries should always point at functions. Therefore, we should
+ // always have a displacement of zero. To check for the end of the table
+ // we will reevaluate the vtbl pointer. If the offset isn't what we
+ // expected, then we are done.
+
+ DWORD dwIndex;
+ for (dwIndex = 0 ; dwIndex < 512 ; dwIndex += 4, lpVtbl += 4)
+ {
+ DWORD dwVtblEntry;
+
+ // Just in case the loop gets away from us
+ if (CheckControlC())
+ {
+ return;
+ }
+
+ // Read the next vtbl entry
+ ReadMem(&dwVtblEntry, lpVtbl, sizeof(dwVtblEntry));
+
+ // If the function is at zero, then must be at end of table
+ if (dwVtblEntry == 0)
+ {
+ return;
+ }
+
+ // Now, determine the symbol for the entry in the vtbl
+ GetSymbol((LPVOID) dwVtblEntry, (UCHAR *) achSymbol, &dwVtblOffset);
+
+ // If it doesn't point to the start of a routine, then it
+ // probably isn't part of the vtbl
+ if (dwVtblOffset != 0)
+ {
+ return;
+ }
+
+ // Print the vtbl entry symbolically
+ Printf(" 0x%08x %s\n", dwVtblEntry, achSymbol);
+ }
+}
diff --git a/private/ole32/dbgexts/ole.def b/private/ole32/dbgexts/ole.def
new file mode 100644
index 000000000..ee5f49e67
--- /dev/null
+++ b/private/ole32/dbgexts/ole.def
@@ -0,0 +1,29 @@
+NAME OLE
+
+DESCRIPTION Ole32 Debugger Extensions
+
+EXPORTS
+ cc
+ ch
+ ci
+ ck
+ dh
+ ds
+ er
+ fe
+ ft
+ help
+ id
+ in
+ ip
+ mk
+ ox
+ pg
+ pl
+ ps
+ rt
+ ta
+ ts
+ vt
+
+
diff --git a/private/ole32/dbgexts/ole.h b/private/ole32/dbgexts/ole.h
new file mode 100644
index 000000000..4d7bf715e
--- /dev/null
+++ b/private/ole32/dbgexts/ole.h
@@ -0,0 +1,107 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: ole.h
+//
+// Contents: Implements ntsd extensions to dump ole tables
+//
+// Functions:
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+
+#include <ntsdexts.h>
+
+
+////////////////////////////////////////////////////////
+const UINT MAX_ARG = 64;
+const UINT MAX_FILESIZE = 128;
+
+////////////////////////////////////////////////////////
+typedef char Arg[MAX_ARG];
+
+
+
+
+////////////////////////////////////////////////////////
+#define until_(x) while(!(x))
+
+#define DEFINE_EXT(e) void e(HANDLE hProcess,HANDLE hThread,DWORD dwPc,PNTSD_EXTENSION_APIS lpExtensionApis,LPSTR lpArgumentString)
+
+#define Printf (*(lpExtensionApis->lpOutputRoutine))
+
+#define CheckForScm() checkForScm(lpExtensionApis)
+
+#define GetExpression (*(lpExtensionApis->lpGetExpressionRoutine))
+
+#define GetSymbol (*(lpExtensionApis->lpGetSymbolRoutine))
+
+#define CheckControlC (*(lpExtensionApis->lpCheckControlCRoutine))
+
+#define ReadMem(a,b,c) readMemory(hProcess, lpExtensionApis, (BYTE *) (a), (BYTE *) (b), (c))
+
+#define WriteMem(a,b,c) writeMemory(hProcess, lpExtensionApis, (BYTE *) (a), (BYTE *) (b), (c))
+
+#define OleAlloc(n) HeapAlloc(GetProcessHeap(),0,(n))
+
+#define OleFree(p) HeapFree(GetProcessHeap(),0,(p))
+
+#define GetArg(a) getArgument(&lpArgumentString, a)
+
+#define IsDecimal(x) ('0' <= (x) && (x) <= '9')
+
+#define Unicode2Ansi(x, y, z) AreFileApisANSI?WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, y, -1, x, z, NULL, NULL):WideCharToMultiByte(CP_OEMCP, WC_COMPOSITECHECK, y, -1, x, z, NULL, NULL);
+
+#define NOTINSCM if(fInScm){NotInScm(lpExtensionApis);return;}
+#define NOTINOLE if(!fInScm){NotInOle(lpExtensionApis);return;}
+
+#define dbt(a, b, c) dbTrace(a, (DWORD *) b, (c) / (sizeof(DWORD)), lpExtensionApis)
+
+#define NOTIMPLEMENTED Printf("...Not implemented yet!\n");
+
+
+
+
+////////////////////////////////////////////////////////
+void dbTrace(char *sz, DWORD *adr, ULONG amt,
+ PNTSD_EXTENSION_APIS lpExtensionApis);
+void getArgument(LPSTR lpArgumentString, LPSTR a);
+void FormatCLSID(REFGUID rguid, LPWSTR lpsz);
+void readMemory(HANDLE hProcess, PNTSD_EXTENSION_APIS lpExtensionApis,
+ BYTE *to, BYTE *from, INT cbSize);
+void writeMemory(HANDLE hProcess, PNTSD_EXTENSION_APIS lpExtensionApis,
+ BYTE *to, BYTE *from, INT cbSize);
+
+
+
+// Common structures
+struct SMutexSem
+{
+ CRITICAL_SECTION _cs;
+};
+
+
+
+
+struct SArrayFValue
+{
+ BYTE **m_pData;
+ UINT m_cbValue;
+ int m_nSize;
+ int m_nMaxSize;
+ int m_nGrowBy;
+};
+
+
+
+
+
+
+
diff --git a/private/ole32/dbgexts/ole.rc b/private/ole32/dbgexts/ole.rc
new file mode 100644
index 000000000..576fd9852
--- /dev/null
+++ b/private/ole32/dbgexts/ole.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Ole32 Debug Extensions"
+#define VER_INTERNALNAME_STR "oleexts.dll"
+#define VER_ORIGINALFILENAME_STR "oleexts.dll"
+
+#include "common.ver"
+
diff --git a/private/ole32/dbgexts/oleexts.cxx b/private/ole32/dbgexts/oleexts.cxx
new file mode 100644
index 000000000..36fa30072
--- /dev/null
+++ b/private/ole32/dbgexts/oleexts.cxx
@@ -0,0 +1,1145 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: ole.cxx
+//
+// Contents: Implements ntsd extensions to dump ole tables
+//
+// Functions:
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include <ole2.h>
+#include "ole.h"
+#include "ddllcach.h"
+#include "dshrdmem.h"
+
+
+#define OLE_VERSION "1.0"
+
+
+void getArgument(LPSTR *lpArgumentString, LPSTR a);
+void checkForScm(PNTSD_EXTENSION_APIS lpExtensionApis);
+void NotInScm(PNTSD_EXTENSION_APIS lpExtensionApis);
+void NotInOle(PNTSD_EXTENSION_APIS lpExtensionApis);
+ULONG ScanAddr(char *lpsz);
+
+void channelHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayChannel(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pChannel,
+ char *arg);
+
+void classCacheHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayClassCache(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayClassCacheCk(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis);
+
+void classInfoHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+BOOL displayClassInfo(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ CLSID *clsid);
+
+void dllCacheHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayDllCache(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ SDllCache *p);
+
+
+void displayHr(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ char *arg);
+
+void fileExtHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayFileExtTbl(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ SDllShrdTbl *pShrdTbl,
+ CLSID *pClsid,
+ WCHAR *wszExt);
+
+void filePatHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayFilePatTbl(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ SDllShrdTbl *pShrdTbl,
+ CLSID *pClsid);
+
+void stdidHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayStdidEntry(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG p,
+ char *arg);
+void displayStdid(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG p);
+
+void infoLevelHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayInfoLevel(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ LPSTR lpArgumentString);
+
+void monikerHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+BOOL displayMoniker(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ ULONG pMoniker);
+
+void psClsidHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayPsClsidTbl(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ SDllShrdTbl *pShrdTbl,
+ CLSID *clisd);
+
+void ipidHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayIpid(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayIpidEntry(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ char *arg);
+
+void oxidHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayOxid(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayOxidEntry(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ char *arg);
+
+void displayCliRot(HANDLE hProcess, PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayScmRot(HANDLE hProcess, PNTSD_EXTENSION_APIS lpExtensionApis);
+void cliRotHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+void scmRotHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+
+void vtblHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayVtbl(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ void *lpObj);
+
+void treatAsCacheHelp(PNTSD_EXTENSION_APIS lpExtensionApis);
+void displayTreatAsCache(HANDLE hProcess,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ CLSID *clsid);
+
+
+
+void determineIfScm(void);
+BOOL ScanCLSID(LPSTR lpsz, LPGUID pguid);
+void FormatCLSID(REFGUID rguid, LPSTR lpsz);
+
+
+BOOL fScmNeedsInit = TRUE;
+BOOL fInScm = FALSE;
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.help
+//
+// Synopsis: Display a help menu of all the supported extensions
+// in this dll
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(help)
+{
+ Arg arg;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ // Help menu for an OLE client or server
+ if (!fInScm)
+ {
+ // Check for any argument
+ GetArg(arg);
+
+ // CRpcChannelBuffer help
+ if (lstrcmpA(arg, "ch") == 0)
+ {
+ channelHelp(lpExtensionApis);
+ }
+
+ // Class information help
+ else if (lstrcmpA(arg, "ci") == 0)
+ {
+ classInfoHelp(lpExtensionApis);
+ }
+
+ // DllCache help
+ else if (lstrcmpA(arg, "ds") == 0 || lstrcmpA(arg, "dh") == 0)
+ {
+ dllCacheHelp(lpExtensionApis);
+ }
+
+ // File extension cache help
+ else if (lstrcmpA(arg, "fe") == 0)
+ {
+ fileExtHelp(lpExtensionApis);
+ }
+
+ // File type patterns cache help
+ else if (lstrcmpA(arg, "ft") == 0)
+ {
+ filePatHelp(lpExtensionApis);
+ }
+
+ // Standard identity table
+ else if (lstrcmpA(arg, "id") == 0)
+ {
+ stdidHelp(lpExtensionApis);
+ }
+
+ // Debug info levels
+ else if (lstrcmpA(arg, "in") == 0)
+ {
+ infoLevelHelp(lpExtensionApis);
+ }
+
+ // IPID table
+ else if (lstrcmpA(arg, "ip") == 0)
+ {
+ ipidHelp(lpExtensionApis);
+ }
+
+ // A moniker
+ else if (lstrcmpA(arg, "mk") == 0)
+ {
+ monikerHelp(lpExtensionApis);
+ }
+
+ // OXID table
+ else if (lstrcmpA(arg, "ox") == 0)
+ {
+ oxidHelp(lpExtensionApis);
+ }
+
+ // IID to class mapping
+ else if (lstrcmpA(arg, "ps") == 0)
+ {
+ psClsidHelp(lpExtensionApis);
+ }
+
+ // ROT help
+ else if (lstrcmpA(arg, "rt") == 0)
+ {
+ cliRotHelp(lpExtensionApis);
+ }
+
+ // TreatAs help
+ else if (lstrcmpA(arg, "ta") == 0)
+ {
+ treatAsCacheHelp(lpExtensionApis);
+ }
+
+ // Vtbl help
+ else if (lstrcmpA(arg, "vt") == 0)
+ {
+ vtblHelp(lpExtensionApis);
+ }
+
+ // Print the full help menu
+ else
+ {
+ Printf("Ole32 NTSD extensions - Version %s\n\n", OLE_VERSION);
+
+ Printf("ch addr - Decode addr as an RPC channel\n");
+ Printf("ci [clsid] - Display registry class information\n");
+ Printf("ck - Is this a checked or retail version of ole32?\n");
+ Printf("dh - Display Inproc Handler dll/class cache\n");
+ Printf("ds - Display Inproc Server dll/class cache\n");
+ Printf("ep - Display current RPC endpoints\n");
+ Printf("er err - Display the message for error number err \n");
+ Printf("fe [e|c] - Display file extensions cache\n");
+ Printf("ft [clsid] - Display file type pattern(s)\n");
+ Printf("help [cmd] - Display this menu or specific help\n");
+ Printf("id - Display CStdIdentity table\n");
+ Printf("in - Set/reset debug info level\n");
+ Printf("ip - Display IPID table information\n");
+ Printf("mk addr - Decode addr as a moniker\n");
+ Printf("ox - Display OXID table information\n");
+ Printf("pg addr - Display addr as a guid\n");
+ Printf("pl - Display platform information\n");
+ Printf("ps - Display proxy/stub clsid cache\n");
+ Printf("rh addr - Decode addr as a remote handler\n");
+ Printf("rt - Display Running Object Table\n");
+ Printf("ta [clsid] - Display TreatAs cache\n");
+ Printf("vt obj - Interpret vtbl for object obj\n");
+ }
+ }
+
+
+ // Help menu for the scm
+ else
+ {
+ // Check for any argument
+ GetArg(arg);
+
+ if (lstrcmp(arg, "rt") == 0)
+ {
+ scmRotHelp(lpExtensionApis);
+ }
+
+ if (lstrcmp(arg, "cc") == 0)
+ {
+ classCacheHelp(lpExtensionApis);
+ }
+
+ // Print the full help menu
+ else
+ {
+ Printf("Ole32 NTSD extensions - Version %s\n\n", OLE_VERSION);
+
+ Printf("cc - Display class cache info\n");
+ Printf("ck - Is this a checked or retail version of scm?\n");
+ Printf("ep - Display current RPC endpoints\n");
+ Printf("er err - Display the message for error number err \n");
+ Printf("help [cmd] - Display this menu or specific help\n");
+ Printf("in - Set/reset debug info level\n");
+ Printf("mk addr - Decode addr as a moniker\n");
+ Printf("pg addr - Display addr as a guid\n");
+ Printf("rh - Display active remote handlers\n");
+ Printf("rt - Display Running Object Table\n");
+ Printf("ts - Display thread information\n");
+ Printf("vt obj - Interpret vtbl for object obj\n");
+ }
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.cc
+//
+// Synopsis: Display the scm class cache
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(cc)
+{
+ ULONG padr;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ NOTINOLE
+
+ // Determine if thisis checked or retail scm
+ padr = GetExpression("scm!_CairoleInfoLevel");
+
+ // Display the scm's class cache
+ if (padr == NULL)
+ {
+ displayClassCache(hProcess, lpExtensionApis);
+ }
+ else
+ {
+ displayClassCacheCk(hProcess, lpExtensionApis);
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.ch
+//
+// Synopsis: Display a channel controller
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(ch)
+{
+ Arg arg;
+ ULONG addr;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ NOTINSCM
+
+ // Fetch the argument
+ GetArg(arg);
+ if (!arg[0])
+ {
+ Printf("...use !ole.ch <address CRpcChannelBuffer>\n");
+ return;
+ }
+
+ // Parse it as a hexadecimal address
+ if (arg[0] != '?')
+ {
+ addr = ScanAddr(arg);
+ if (addr == NULL)
+ {
+ Printf("...%s is not a valid address\n", arg);
+ return;
+ }
+ }
+
+ // BUGBUG: Check that this is indeed an CRpcChannelBuffer
+ // Display the parsed address as a CRpcChannelBuffer
+ displayChannel(hProcess, lpExtensionApis, addr, arg);
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.ci
+//
+// Synopsis: Display registry class information
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(ci)
+{
+ Arg arg;
+ CLSID clsid;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ // Fetch the argument
+ GetArg(arg);
+
+ // Parse it as a clsid
+ if (arg[0])
+ {
+ if (!ScanCLSID(arg, &clsid))
+ {
+ Printf("...%s is not a valid clsid\n", arg);
+ return;
+ }
+ }
+
+ // Display all or particular registry class information
+ if (arg[0])
+ {
+ displayClassInfo(hProcess, lpExtensionApis, &clsid);
+ }
+ else
+ {
+ displayClassInfo(hProcess, lpExtensionApis, NULL);
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.ck
+//
+// Synopsis: Is this the checked or retail version of OLE?
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(ck)
+{
+ ULONG padr;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ if (fInScm)
+ {
+ padr = GetExpression("scm!_CairoleInfoLevel");
+ }
+ else
+ {
+ padr = GetExpression("ole32!_CairoleInfoLevel");
+ }
+ if (padr == NULL)
+ {
+ Printf("Retail\n");
+ }
+ else
+ {
+ Printf("Checked\n");
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.dh
+//
+// Synopsis: Display the dll/class cache for inproc handlers
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(dh)
+{
+ SDllCache dllCache;
+ ULONG padr;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ NOTINSCM
+
+ // Fetch the dll/class cache object
+ padr = GetExpression("ole32!gdllcacheHandler");
+ ReadMem((void *) &dllCache, padr, sizeof(SDllCache));
+ Printf("Dll/class cache for in-process handlers\n\n");
+ displayDllCache(hProcess, lpExtensionApis, &dllCache);
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.ds
+//
+// Synopsis: Display the dll/class cache for inproc servers
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(ds)
+{
+ SDllCache dllCache;
+ ULONG padr;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ padr = GetExpression("ole32!gdllcacheInprocSrv");
+ ReadMem(&dllCache, padr, sizeof(SDllCache));
+ Printf("Dll/class cache for in-process servers\n\n");
+ displayDllCache(hProcess, lpExtensionApis, &dllCache);
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.er
+//
+// Synopsis: Display a Win32 or OLE error message
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(er)
+{
+ Arg arg;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ GetArg(arg);
+ displayHr(hProcess, lpExtensionApis, arg);
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.fe
+//
+// Synopsis: Display file extension information
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(fe)
+{
+ Arg arg;
+ ULONG pAdr;
+ SDllShrdTbl *pShrdTbl;
+ CLSID clsid;
+ WCHAR wszExt[16];
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ NOTINSCM
+
+ // Check for any argument
+ GetArg(arg);
+ if (arg[0])
+ {
+ if (arg[0] == '{')
+ {
+ if(!ScanCLSID(arg, &clsid))
+ {
+ Printf("...%s is not a valid CLSID\n", arg);
+ return;
+ }
+ }
+ else if (arg[0] == '.')
+ {
+ if (!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, arg, -1, wszExt,
+ 16 * sizeof(WCHAR)))
+ {
+ Printf("..%ws\n", wszExt);
+ Printf("...invalid extension %s\n", arg);
+ return;
+ }
+ }
+ else
+ {
+ Printf("...can't understand argument\n");
+ }
+ }
+
+ // Fetch the address of the shared memory table
+ pAdr = GetExpression("ole32!g_pShrdTbl");
+ ReadMem(&pShrdTbl, pAdr, sizeof(ULONG));
+ if (arg[0])
+ {
+ if (arg[0] == '{')
+ {
+ displayFileExtTbl(hProcess, lpExtensionApis, pShrdTbl, &clsid,
+ NULL);
+ }
+ else
+ {
+ displayFileExtTbl(hProcess, lpExtensionApis, pShrdTbl, NULL,
+ wszExt);
+ }
+ }
+ else
+ {
+ displayFileExtTbl(hProcess, lpExtensionApis, pShrdTbl, NULL, NULL);
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.ft
+//
+// Synopsis: Display file type patterns
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(ft)
+{
+ Arg arg;
+ ULONG pAdr;
+ SDllShrdTbl *pShrdTbl;
+ CLSID clsid;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ NOTINSCM
+
+ // Check for an argument
+ GetArg(arg);
+ if (arg[0])
+ {
+ if (arg[0] == '{')
+ {
+ if(!ScanCLSID(arg, &clsid))
+ {
+ Printf("...%s is not a valid CLSID\n", arg);
+ return;
+ }
+ }
+ else
+ {
+ Printf("...%s is not a valid CLSID\n", arg);
+ return;
+ }
+ }
+
+ // Fetch the address of the shared memory table
+ pAdr = GetExpression("ole32!g_pShrdTbl");
+ ReadMem(&pShrdTbl, pAdr, sizeof(ULONG));
+ if (arg[0] == '{')
+ {
+ displayFilePatTbl(hProcess, lpExtensionApis, pShrdTbl, &clsid);
+ }
+ else
+ {
+ displayFilePatTbl(hProcess, lpExtensionApis, pShrdTbl, NULL);
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.id
+//
+// Synopsis: Display the CStdIdentity taable
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(id)
+{
+ ULONG pAdr;
+ Arg arg;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ NOTINSCM
+
+ // Fetch the address of the standard identity table
+ pAdr = GetExpression("ole32!sg_idtable");
+
+ // Check for any argument
+ GetArg(arg);
+
+ // Display all or one entry
+ if (arg[0])
+ {
+ displayStdidEntry(hProcess, lpExtensionApis, pAdr, arg);
+ }
+ else
+ {
+ displayStdid(hProcess, lpExtensionApis, pAdr);
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.in
+//
+// Synopsis: Display/change debug info levels
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(in)
+{
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ // Set/display an info level
+ displayInfoLevel(hProcess, lpExtensionApis, lpArgumentString);
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.ip
+//
+// Synopsis: Display IPID table
+//
+// History: 11-Aug-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(ip)
+{
+ Arg arg;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ NOTINSCM
+
+ // Check for an argument
+ GetArg(arg);
+
+ // The whole table or a single entry
+ if (arg[0])
+ {
+ displayIpidEntry(hProcess, lpExtensionApis, arg);
+ }
+ else
+ {
+ displayIpid(hProcess, lpExtensionApis);
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.mk
+//
+// Synopsis: Interpret a moniker object
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(mk)
+{
+ Arg arg;
+ ULONG pAdr;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ // Scan the argument
+ GetArg(arg);
+ if (!arg[0])
+ {
+ Printf("...use !ole.mk <moniker address>\n");
+ return;
+ }
+ pAdr = ScanAddr(arg);
+
+ // Interpret this address as a moniker
+ if (!displayMoniker(hProcess, lpExtensionApis, pAdr))
+ {
+ Printf("...%08x isn't a system moniker\n", pAdr);
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.ox
+//
+// Synopsis: Display OXID table
+//
+// History: 11-Aug-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(ox)
+{
+ Arg arg;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ NOTINSCM
+
+ // Check for an argument
+ GetArg(arg);
+
+ // The whole table or a single entry
+ if (arg[0])
+ {
+ displayOxidEntry(hProcess, lpExtensionApis, arg);
+ }
+ else
+ {
+ displayOxid(hProcess, lpExtensionApis);
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.pg
+//
+// Synopsis: Pretty print a guid
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(pg)
+{
+ Arg arg;
+ ULONG addr;
+ GUID guid;
+ char szGuid[CLSIDSTR_MAX];
+
+ // Fetch the argument
+ GetArg(arg);
+ if (!arg[0])
+ {
+ Printf("...requires an addr argument\n");
+ return;
+ }
+ addr = ScanAddr(arg);
+
+ // Fetch the guid
+ ReadMem(&guid, addr, sizeof(GUID));
+
+ // Format and print the guid
+ FormatCLSID((GUID &) guid, szGuid);
+ Printf("%s\n", szGuid);
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.pl
+//
+// Synopsis: Display platform information
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(pl)
+{
+ OSVERSIONINFO osInfo;
+
+ osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (GetVersionEx(&osInfo))
+ {
+ Printf("Cairo %d.%d Build %d\n",
+ osInfo.dwMajorVersion,
+ osInfo.dwMinorVersion,
+ osInfo.dwBuildNumber);
+ }
+ else
+ {
+ Printf("...Unable to get version/platform info\n");
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.ps
+//
+// Synopsis: Display CLSID of proxy/stub handler dll for given IID
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(ps)
+{
+ Arg arg;
+ ULONG pAdr;
+ SDllShrdTbl *pShrdTbl;
+ IID iid;
+ WCHAR wszExt[16];
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ NOTINSCM
+
+ // Check for any argument
+ GetArg(arg);
+ if (arg[0])
+ {
+ if(!ScanCLSID(arg, &iid))
+ {
+ Printf("...%s is not a valid CLSID\n", arg);
+ return;
+ }
+ }
+
+ // Fetch the address of the shared memory table
+ pAdr = GetExpression("ole32!g_pShrdTbl");
+ ReadMem(&pShrdTbl, pAdr, sizeof(ULONG));
+ if (arg[0])
+ {
+ displayPsClsidTbl(hProcess, lpExtensionApis, pShrdTbl, &iid);
+ }
+ else
+ {
+ displayPsClsidTbl(hProcess, lpExtensionApis, pShrdTbl, NULL);
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.rt
+//
+// Synopsis: Display the ROT
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(rt)
+{
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ if (fInScm)
+ {
+ displayScmRot(hProcess, lpExtensionApis);
+ }
+ else
+ {
+ displayCliRot(hProcess, lpExtensionApis);
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.ta
+//
+// Synopsis: Display TreatAs cache
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(ta)
+{
+ Arg arg;
+ CLSID clsid;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ // Check whether a clsid was supplied
+ GetArg(arg);
+ if (arg[0])
+ {
+ if (!ScanCLSID(arg, &clsid))
+ {
+ Printf("..%s is not a valid CLSID\n", arg);
+ return;
+ }
+ displayTreatAsCache(hProcess, lpExtensionApis, &clsid);
+ }
+
+ // Display the entire TreatAs class cache
+ else
+ {
+ displayTreatAsCache(hProcess, lpExtensionApis, NULL);
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.ts
+//
+// Synopsis: Display thread information
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(ts)
+{
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ Printf("...NOT IMPLEMENTED YET\n");
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Extension: !ole.vt
+//
+// Synopsis: Display a vtbl
+//
+// History: 01-Jun-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+DEFINE_EXT(vt)
+{
+ Arg arg;
+ DWORD dwObj = NULL;
+ char *s;
+
+ // Check whether debuggee is the scm
+ CheckForScm();
+
+ // Get the object
+ GetArg(arg);
+ for (s = arg; *s; s++)
+ {
+ dwObj = 16 * dwObj + *s - '0';
+ if ('A' <= *s && *s <= 'F')
+ {
+ dwObj -= 7;
+ }
+ if ('a' <= *s && *s <= 'f')
+ {
+ dwObj -= 39;
+ }
+ }
+
+ // Display the vtbl
+ if (dwObj != NULL)
+ {
+ displayVtbl(hProcess, lpExtensionApis, (LPVOID) dwObj);
+ }
+ else
+ {
+ Printf("...vtbl address of NULL is not meaningful\n");
+ }
+}
diff --git a/private/ole32/dbgexts/util.cxx b/private/ole32/dbgexts/util.cxx
new file mode 100644
index 000000000..255dd2d9f
--- /dev/null
+++ b/private/ole32/dbgexts/util.cxx
@@ -0,0 +1,543 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995
+//
+// File: ole.cxx
+//
+// Contents: Implements ntsd extensions to dump ole tables
+//
+// Functions:
+//
+//
+// History: 06-01-95 BruceMa Created
+//
+//
+//--------------------------------------------------------------------------
+
+
+#include <ole2int.h>
+#include <windows.h>
+#include "ole.h"
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: readMemory
+//
+// Synopsis: Transfer memory from debuggee virtual space to a local
+// kernel memory
+//
+// Arguments: [lpArgumentString] - command line string
+// [a] - where to return next argument
+//
+// Returns: -
+//
+//--------------------------------------------------------------------------
+void readMemory(HANDLE hProcess, PNTSD_EXTENSION_APIS lpExtensionApis,
+ BYTE *to, BYTE *from, INT cbSize)
+{
+ __try
+ {
+ NtReadVirtualMemory(hProcess, (void *) from, (void *) to,
+ cbSize , NULL);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ Printf("...Exception reading %08x-%08x\n", from, from + cbSize - 1);
+ }
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: writeMemory
+//
+// Synopsis: Transfer memory from local memoryto debuggee virtual space
+//
+// Arguments:
+//
+// Returns: -
+//
+//--------------------------------------------------------------------------
+void writeMemory(HANDLE hProcess, PNTSD_EXTENSION_APIS lpExtensionApis,
+ BYTE *to, BYTE *from, INT cbSize)
+{
+ __try
+ {
+ NtWriteVirtualMemory(hProcess, (void *) to, (void *) from,
+ cbSize, NULL);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ Printf("...Exception writing %08x-%08x\n", to, to + cbSize - 1);
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: getArgument
+//
+// Synopsis: Return next command line argument
+//
+// Arguments: [lpArgumentString] - command line string
+// [a] - where to return next argument
+//
+// Returns: -
+//
+//--------------------------------------------------------------------------
+void getArgument(LPSTR *lpArgumentString, LPSTR a)
+{
+ char *s = *lpArgumentString;
+
+ // Skip whitespace
+ while (*s && (*s == ' ' || *s == '\t'))
+ {
+ s++;
+ }
+ while (*s && *s != ' ' && *s != '\t')
+ {
+ *a++ = *s++;
+ }
+ *a = '\0';
+ *lpArgumentString = s;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsEqualGUID
+//
+// Synopsis: Compares two guids for equality
+//
+// Arguments: [pClsid1] - the first clsid
+// [pClsid2] - the second clsid to compare the first one with
+//
+// Returns: TRUE if equal, FALSE if not.
+//
+//--------------------------------------------------------------------------
+
+BOOL IsEqualCLSID(CLSID *pClsid1, CLSID *pClsid2)
+{
+ return !memcmp((void *) pClsid1,(void *) pClsid2, sizeof(CLSID));
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ScanAddr
+//
+// Synopsis: Parse the indput string as a hexadecimal address
+//
+// Arguments: [lpsz] - the hex string to convert
+//
+// Returns: TRUE for success
+//
+//--------------------------------------------------------------------------
+ULONG ScanAddr(char *lpsz)
+{
+ ULONG val = NULL;
+
+ // Peel off any leading "0x"
+ if (lpsz[0] == '0' && lpsz[1] == 'x')
+ {
+ lpsz += 2;
+ }
+
+ // Parse as a hex address
+ while (*lpsz)
+ {
+ if (*lpsz >= '0' && *lpsz <= '9')
+ {
+ val = (val << 4) + *lpsz - '0';
+ }
+ else if (*lpsz >= 'A' && *lpsz <= 'F')
+ {
+ val = (val << 4) + *lpsz - 'A' + 10;
+ }
+ else if (*lpsz >= 'a' && *lpsz <= 'f')
+ {
+ val = (val << 4) + *lpsz - 'a' + 10;
+ }
+ else
+ {
+ return NULL;
+ }
+
+ lpsz++;
+ }
+
+ return val;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: HexStringToDword
+//
+// Synopsis: scan lpsz for a number of hex digits (at most 8); update lpsz
+// return value in Value; check for chDelim;
+//
+// Arguments: [lpsz] - the hex string to convert
+// [Value] - the returned value
+// [cDigits] - count of digits
+//
+// Returns: TRUE for success
+//
+//--------------------------------------------------------------------------
+static BOOL HexStringToDword(LPSTR &lpsz, DWORD &Value,
+ int cDigits, WCHAR chDelim)
+{
+ int Count;
+
+ Value = 0;
+ for (Count = 0; Count < cDigits; Count++, lpsz++)
+ {
+ if (*lpsz >= '0' && *lpsz <= '9')
+ Value = (Value << 4) + *lpsz - '0';
+ else if (*lpsz >= 'A' && *lpsz <= 'F')
+ Value = (Value << 4) + *lpsz - 'A' + 10;
+ else if (*lpsz >= 'a' && *lpsz <= 'f')
+ Value = (Value << 4) + *lpsz - 'a' + 10;
+ else
+ return(FALSE);
+ }
+
+ if (chDelim != 0)
+ return *lpsz++ == chDelim;
+ else
+ return TRUE;
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CLSIDFromString
+//
+// Synopsis: Parse above format; always writes over *pguid.
+//
+// Arguments: [lpsz] - the guid string to convert
+// [pguid] - guid to return
+//
+// Returns: TRUE if successful
+//
+//--------------------------------------------------------------------------
+BOOL ScanCLSID(LPSTR lpsz, CLSID *pClsid)
+{
+ DWORD dw;
+ if (*lpsz++ != '{')
+ return FALSE;
+
+ if (!HexStringToDword(lpsz, pClsid->Data1, sizeof(DWORD)*2, '-'))
+ return FALSE;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
+ return FALSE;
+
+ pClsid->Data2 = (WORD)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
+ return FALSE;
+
+ pClsid->Data3 = (WORD)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pClsid->Data4[0] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '-'))
+ return FALSE;
+
+ pClsid->Data4[1] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pClsid->Data4[2] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pClsid->Data4[3] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pClsid->Data4[4] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pClsid->Data4[5] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pClsid->Data4[6] = (BYTE)dw;
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, /*(*/ '}'))
+ return FALSE;
+
+ pClsid->Data4[7] = (BYTE)dw;
+
+ return TRUE;
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: FormatCLSID
+//
+// Synopsis: converts GUID into {...} form without leading identifier;
+//
+// Arguments: [rguid] - the guid to convert
+// [lpszy] - buffer to hold the results
+// [cbMax] - sizeof the buffer
+//
+// Returns: amount of data copied to lpsz if successful
+// 0 if buffer too small.
+//
+//--------------------------------------------------------------------------
+void FormatCLSID(REFGUID rguid, LPSTR lpsz)
+{
+ wsprintf(lpsz, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\0",
+ rguid.Data1, rguid.Data2, rguid.Data3,
+ rguid.Data4[0], rguid.Data4[1],
+ rguid.Data4[2], rguid.Data4[3],
+ rguid.Data4[4], rguid.Data4[5],
+ rguid.Data4[6], rguid.Data4[7]);
+}
+
+
+
+
+
+
+extern BOOL fScmNeedsInit;
+extern BOOL fInScm;
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CheckForScm
+//
+// Synopsis: Checks whether the debuggee is 'scm'
+//
+// Arguments: -
+//
+// Returns: Sets global boolean fInScm to TRUE if this is the scm;
+// FALSE otherwise
+//
+//--------------------------------------------------------------------------
+void checkForScm(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ ULONG padr = NULL;
+
+ if (fScmNeedsInit)
+ {
+ fScmNeedsInit = FALSE;
+ padr = GetExpression("scm!CPerMachineROT__CPerMachineROT");
+ fInScm = padr != NULL ? TRUE : FALSE;
+ }
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: NotInScm
+//
+// Synopsis: Prints error message
+//
+// Arguments: -
+//
+// Returns:
+//
+//--------------------------------------------------------------------------
+void NotInScm(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("...not meaningful in the scm\n");
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: NotInOle
+//
+// Synopsis: Prints error message
+//
+// Arguments: -
+//
+// Returns:
+//
+//--------------------------------------------------------------------------
+void NotInOle(PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ Printf("...only meaningful in the scm\n");
+}
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////
+// F O R D E B U G G I N G
+
+
+void dbTrace(char *sz, DWORD *adr, ULONG amt,
+ PNTSD_EXTENSION_APIS lpExtensionApis)
+{
+ UINT k;
+
+ Printf("\n%s", sz);
+ for (k = 0; k < amt; k++)
+ {
+ if (k % 8 == 0)
+ {
+ Printf("\n");
+ }
+ Printf("%08x ", *adr++);
+ }
+ Printf("\n");
+}
+
+
+
+
+
+
+
+
+
+//+--------------------------------------------------------
+//
+// Function: GetRegistryInterfaceName
+//
+// Algorithm: Fetch the name from the registry for the specified interface
+//
+// History: 21-Jun-95 BruceMa Created
+//
+//---------------------------------------------------------
+BOOL GetRegistryInterfaceName(REFIID iid, char *szValue, DWORD *pcbValue)
+{
+ DWORD dwRESERVED = 0;
+ HKEY hKey;
+ char szIID[CLSIDSTR_MAX];
+ char szInterface[32 + 1 + CLSIDSTR_MAX];
+ DWORD dwValueType;
+ HKEY hClsidKey;
+ HKEY hInproc32Key;
+
+ // Prepare to open the "...Interface\<iid>" key
+ FormatCLSID(iid, szIID);
+ lstrcpy(szInterface, "Interface\\");
+ lstrcat(szInterface, szIID);
+
+ // Open the key for the specified interface
+ if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szInterface, dwRESERVED,
+ KEY_READ, &hKey) != ERROR_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ // Read the value as the interface name
+ if (RegQueryValueEx(hKey, NULL, NULL, &dwValueType,
+ (LPBYTE) szValue, pcbValue) != ERROR_SUCCESS)
+ {
+ CloseHandle(hKey);
+ return FALSE;
+ }
+
+ // Close registry handle and return success
+ CloseHandle(hKey);
+ return TRUE;
+}
+
+
+
+
+
+
+
+
+
+//+--------------------------------------------------------
+//
+// Function: GetRegistryClsidKey
+//
+// Algorithm: Fetch the value from the registry for the specified clsid
+// and key
+//
+// History: 21-Jun-95 BruceMa Created
+//
+//---------------------------------------------------------
+BOOL GetRegistryClsidKey(REFCLSID clsid, char *szKey,
+ char *szValue, DWORD *pcbValue)
+{
+ DWORD dwRESERVED = 0;
+ HKEY hKey;
+ char szCLSID[CLSIDSTR_MAX];
+ char szClsid[5 + 1 + CLSIDSTR_MAX + 1 + 32];
+ DWORD dwValueType;
+ HKEY hClsidKey;
+ HKEY hInproc32Key;
+
+ // Prepare to open the "...Interface\<clsid>" key
+ FormatCLSID(clsid, szCLSID);
+ lstrcpy(szClsid, "CLSID\\");
+ lstrcat(szClsid, szCLSID);
+ lstrcat(szClsid,"\\");
+ lstrcat(szClsid, szKey);
+
+ // Open the key for the specified clsid and key
+ if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szClsid, dwRESERVED,
+ KEY_READ, &hKey) != ERROR_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ // Read the value for the specified key
+ if (RegQueryValueEx(hKey, NULL, NULL, &dwValueType,
+ (LPBYTE) szValue, pcbValue) != ERROR_SUCCESS)
+ {
+ CloseHandle(hKey);
+ return FALSE;
+ }
+
+ // Close registry handle and return success
+ CloseHandle(hKey);
+ return TRUE;
+}
diff --git a/private/ole32/dcom95/docs/dcom95.doc b/private/ole32/dcom95/docs/dcom95.doc
new file mode 100644
index 000000000..61b09a26a
--- /dev/null
+++ b/private/ole32/dcom95/docs/dcom95.doc
Binary files differ
diff --git a/private/ole32/dcom95/lib/readme.txt b/private/ole32/dcom95/lib/readme.txt
new file mode 100644
index 000000000..0abdd77f9
--- /dev/null
+++ b/private/ole32/dcom95/lib/readme.txt
@@ -0,0 +1,6 @@
+This directory contains the libraries that should be used for DCOM95 OLE32 development. All other libraries must
+come from \nt\public\sdk\lib\i386. If you get the urge to add Win95 libraries to this library resist it. If the
+urge just doesn't go away update this file to indicate its heritage and checkin the library.
+=================================================================================================================
+kernel32.lib Win95QFE 03/16/96 murthys
+wow32.lib Win95QFE 03/16/96 murthys \ No newline at end of file
diff --git a/private/ole32/dcom95/mstools/readme.txt b/private/ole32/dcom95/mstools/readme.txt
new file mode 100644
index 000000000..7d2d7951b
--- /dev/null
+++ b/private/ole32/dcom95/mstools/readme.txt
@@ -0,0 +1,4 @@
+This directory contains Win95 specific tools necessary for DCOM95 OLE32 development. If you add a tool
+update this document to indicate its heritage and check the tool in.
+=======================================================================================================
+mapsym.exe 03/16/96 murthys Win95QFE
diff --git a/private/ole32/dcomss/dcomss.h b/private/ole32/dcomss/dcomss.h
new file mode 100644
index 000000000..230ed08c2
--- /dev/null
+++ b/private/ole32/dcomss/dcomss.h
@@ -0,0 +1,99 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ dcomss.h
+
+Abstract:
+
+ Common services provided by core the orpcss service.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 06-14-95 Bits 'n pieces
+
+--*/
+
+#ifndef __DCOMSS_H
+#define __DCOMSS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <nt.h>
+#include <ntdef.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <rpc.h>
+#include <winsvc.h>
+
+#if DBG && !defined(DEBUGRPC)
+#define DEBUGRPC
+#endif
+
+// Endpoint related functions
+
+RPC_STATUS InitializeEndpointManager(VOID);
+USHORT GetProtseqId(PWSTR Protseq);
+USHORT GetProtseqIdAnsi(PSTR Protseq);
+PWSTR GetProtseq(USHORT ProtseqId);
+PWSTR GetEndpoint(USHORT ProtseqId);
+RPC_STATUS UseProtseqIfNecessary(USHORT id);
+RPC_STATUS DelayedUseProtseq(USHORT id);
+VOID CompleteDelayedUseProtseqs();
+BOOL IsLocal(USHORT ProtseqId);
+DWORD RegisterAuthInfoIfNecessary();
+
+// Must be given dedicated a thread after startup.
+
+DWORD ObjectExporterWorkerThread(PVOID);
+
+// Update service state
+
+VOID UpdateState(DWORD dwNewState);
+
+// TRUE when NOT running as a service.
+extern BOOL gfDebugMode;
+
+extern BOOL gfRegisteredAuthInfo;
+
+extern BOOL s_fEnableDCOM; // Set by StartObjectExporter.
+
+// Each component subservice supplies a start function. These
+// functions should check gfDebugMode before doing a service
+// manager releated stuff. (calling UpdateState() is ok.)
+
+DWORD StartEndpointMapper(VOID);
+DWORD StartObjectExporter(VOID);
+DWORD InitializeSCM(VOID);
+void InitializeSCMAfterListen(VOID);
+
+// Shared by wrapper\epts.c and olescm\clsdata.cxx.
+
+typedef enum {
+ STOPPED = 1,
+ START,
+ STARTED
+ } PROTSEQ_STATE;
+
+typedef struct {
+ PROTSEQ_STATE state;
+ PWSTR pwstrProtseq;
+ PWSTR pwstrEndpoint;
+ } PROTSEQ_INFO;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/private/ole32/dcomss/dcomtest/makefile b/private/ole32/dcomss/dcomtest/makefile
new file mode 100644
index 000000000..51f351a0e
--- /dev/null
+++ b/private/ole32/dcomss/dcomtest/makefile
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS LINE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/dcomss/dcomtest/makefile.inc b/private/ole32/dcomss/dcomtest/makefile.inc
new file mode 100644
index 000000000..fb7fcb632
--- /dev/null
+++ b/private/ole32/dcomss/dcomtest/makefile.inc
@@ -0,0 +1,33 @@
+!ifndef MIDL
+MIDL = midl.exe
+!endif
+
+MIDL_FLAGS= \
+ -Zp8 \
+ -I$(INCLUDES) \
+ -Os \
+ -oldnames \
+ -char unsigned \
+ -error allocation \
+ -ms_ext -c_ext \
+ -DMIDL_PASS \
+ $(C_DEFINES) \
+ -prefix server _ \
+ -cpp_cmd $(TARGET_CPP) \
+ -cpp_opt "-nologo -DMIDL_PASS $(C_DEFINES) -I$(INCLUDES) -E -Tc"
+
+obj\uor.h: uor.idl
+ $(MIDL) $(MIDL_FLAGS) -header $@ $**
+
+odeth_s.c : $(BASEDIR)\private\dcomidl\odeth_s.c
+ copy $? .
+
+testidl: obj\uor.h odeth_s.c
+
+clean:
+ -erase obj\uor.h >NUL 2>NUL
+
+
+
+
+
diff --git a/private/ole32/dcomss/dcomtest/ortest.c b/private/ole32/dcomss/dcomtest/ortest.c
new file mode 100644
index 000000000..249b5d3b1
--- /dev/null
+++ b/private/ole32/dcomss/dcomtest/ortest.c
@@ -0,0 +1,1521 @@
+/*++
+
+Copyright (c) 1996 Microsoft Corporation
+
+Module Name:
+
+ ortest.c
+
+Abstract:
+
+ Simple test application for testing OR features directly.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 1/24/1996 Bits 'n pieces
+
+--*/
+
+#include <or.h>
+#include <stdio.h>
+#include <umisc.h>
+#include <uor.h>
+#include <epmp.h>
+
+typedef struct {
+ ID oid;
+ BOOL fReady;
+ BOOL fForceSecond;
+ } RundownRecord;
+
+// Constants
+
+const PWSTR pwstrOr = L"ncalrpc:[epmapper]";
+
+// Globals
+
+HANDLE hLocalOr = 0;
+HANDLE hServerOrTest = 0;
+PHPROCESS hMyProcess = 0;
+
+BOOL fServer = TRUE;
+BOOL fInternet = FALSE;
+
+DWORD TestCase = 0;
+DWORD Errors = 0;
+
+OXID aOxids[5]; /* shared \ */
+OXID_INFO aOxidInfo[5]; /* shared > between client and server */
+OID aOids[100]; /* shared / */
+
+RundownRecord aRundowns[100];
+DWORD dwlimRundowns = 0;
+
+OID reservedBase;
+
+DUALSTRINGARRAY *pdsaMyExpandedStringBindings;
+DUALSTRINGARRAY *pdsaMyCompressedSecurityBindings;
+DUALSTRINGARRAY *pdsaMyTestBindings;
+
+DUALSTRINGARRAY *pdsaLocalOrBindings;
+MID gLocalMid;
+
+void SyncWithClient(DWORD testcase);
+error_status_t SyncWithServer(DWORD testcase);
+void AddRundown(ID oid, BOOL fRundownTwice);
+void WaitForAllRundowns();
+RPC_STATUS ConnectToLocalOr();
+RPC_STATUS Startup(PSZ, PSZ);
+
+// Test events
+
+HANDLE hServerEvent;
+HANDLE hClientEvent;
+HANDLE hRundownEvent;
+
+
+//
+// Intenet port tests - not really related to DCOM
+// but is just a client to the endpoint mapper process
+// so it runs fine here.
+//
+// Assumes the following config: (regini dcomtest.ini)
+//
+
+extern RPC_STATUS RPC_ENTRY
+I_RpcServerAllocatePort(DWORD, PUSHORT);
+
+RPC_STATUS
+RunInternetPortTests()
+{
+ RPC_STATUS status;
+ long allocstatus;
+ PVOID process1, process2, process3;
+ unsigned short port;
+ int i;
+
+ for (i = 0; i < 2; i++)
+ {
+ process1 = process2 = process3 = 0;
+
+ if (hLocalOr == 0)
+ {
+ status =
+ RpcBindingFromStringBinding(pwstrOr, &hLocalOr);
+ ASSERT(status == RPC_S_OK);
+ }
+
+ status = OpenEndpointMapper(hLocalOr,
+ &process1);
+
+ ASSERT(status == RPC_S_OK);
+
+ status = OpenEndpointMapper(hLocalOr,
+ &process2);
+
+ ASSERT(status == RPC_S_OK);
+
+ status = OpenEndpointMapper(hLocalOr,
+ &process3);
+
+ ASSERT(status == RPC_S_OK);
+ status = AllocateReservedIPPort(process1,
+ PORT_DEFAULT,
+ &allocstatus,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(allocstatus, RPC_S_OK);
+ EQUAL(port, 1026);
+
+ status = AllocateReservedIPPort(process1,
+ PORT_INTERNET,
+ &allocstatus,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(allocstatus, RPC_S_OK);
+ EQUAL(port, 1028);
+
+ status = AllocateReservedIPPort(process1,
+ PORT_INTERNET,
+ &allocstatus,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(allocstatus, RPC_S_OK);
+ EQUAL(port, 1029);
+
+ status = AllocateReservedIPPort(process2,
+ PORT_INTRANET,
+ &allocstatus,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(allocstatus, RPC_S_OK);
+ EQUAL(port, 499);
+
+ status = AllocateReservedIPPort(process2,
+ PORT_INTRANET,
+ &allocstatus,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(allocstatus, RPC_S_OK);
+ EQUAL(port, 500);
+
+ status = AllocateReservedIPPort(process2,
+ PORT_INTRANET,
+ &allocstatus,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(allocstatus, RPC_S_OK);
+ EQUAL(port, 501);
+
+ status = AllocateReservedIPPort(process2,
+ PORT_INTRANET,
+ &allocstatus,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(allocstatus, RPC_S_OK);
+ EQUAL(port, 502);
+
+
+ status = AllocateReservedIPPort(process2,
+ PORT_INTRANET,
+ &allocstatus,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(allocstatus, RPC_S_OK);
+ EQUAL(port, 1025);
+
+
+ status = AllocateReservedIPPort(process2,
+ PORT_INTRANET,
+ &allocstatus,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(allocstatus, RPC_S_OK);
+ EQUAL(port, 1027);
+
+
+ status = AllocateReservedIPPort(process2,
+ PORT_INTRANET,
+ &allocstatus,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(allocstatus, RPC_S_OUT_OF_RESOURCES);
+ EQUAL(port, 0);
+
+
+ status = AllocateReservedIPPort(process3,
+ PORT_INTRANET,
+ &allocstatus,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(allocstatus, RPC_S_OUT_OF_RESOURCES);
+ EQUAL(port, 0);
+
+ status = AllocateReservedIPPort(process3,
+ PORT_INTERNET,
+ &allocstatus,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(allocstatus, RPC_S_OK);
+ EQUAL(port, 1030);
+
+ status =
+ RpcSmDestroyClientContext(&process2);
+ ASSERT(status == RPC_S_OK);
+
+ status =
+ RpcSmDestroyClientContext(&process3);
+ ASSERT(status == RPC_S_OK);
+
+ status =
+ RpcSmDestroyClientContext(&process1);
+ ASSERT(status == RPC_S_OK);
+
+ status =
+ RpcBindingFree(&hLocalOr);
+ ASSERT(status == RPC_S_OK);
+ }
+
+ status = I_RpcServerAllocatePort(RPC_C_USE_INTERNET_PORT,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(port, 1026);
+
+ status = I_RpcServerAllocatePort(0,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(port, 1028);
+
+
+ status = I_RpcServerAllocatePort(RPC_C_USE_INTRANET_PORT,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(port, 499);
+
+ status = I_RpcServerAllocatePort(RPC_C_USE_INTRANET_PORT,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(port, 500);
+
+ status = I_RpcServerAllocatePort(RPC_C_USE_INTRANET_PORT,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(port, 501);
+
+ status = I_RpcServerAllocatePort(RPC_C_USE_INTRANET_PORT,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(port, 502);
+
+ status = I_RpcServerAllocatePort(RPC_C_USE_INTRANET_PORT,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(port, 1025);
+
+ status = I_RpcServerAllocatePort(RPC_C_USE_INTRANET_PORT,
+ &port);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(port, 1027);
+
+ status = I_RpcServerAllocatePort(RPC_C_USE_INTRANET_PORT,
+ &port);
+
+ ASSERT(status == RPC_S_OUT_OF_RESOURCES);
+ EQUAL(port, 0);
+
+ status = I_RpcServerAllocatePort( RPC_C_USE_INTERNET_PORT
+ | RPC_C_USE_INTRANET_PORT,
+ &port);
+ ASSERT(status == RPC_S_INVALID_ARG);
+ EQUAL(port, 0);
+
+ return(RPC_S_OK);
+}
+// Server side
+
+RPC_STATUS
+RunServer()
+{
+ RPC_STATUS status;
+ DWORD t;
+ OXID_INFO oi;
+ OID oidT;
+ int i;
+ OID aOidDels[2];
+
+ SyncWithClient(++TestCase);
+
+ // Allocate Oxids and Oids
+
+ aOxidInfo[0].dwTid = 1;
+ aOxidInfo[0].dwPid = 42;
+ aOxidInfo[0].dwAuthnHint = 4;
+ aOxidInfo[0].psa = 0;
+
+ status = UuidCreate(&aOxidInfo[0].ipidRemUnknown);
+ ASSERT(status == RPC_S_OK);
+
+ status = ServerAllocateOXIDAndOIDs(
+ hLocalOr,
+ hMyProcess,
+ &aOxids[0],
+ FALSE,
+ 5,
+ &aOids[0],
+ &t,
+ &aOxidInfo[0],
+ pdsaMyExpandedStringBindings,
+ pdsaMyCompressedSecurityBindings);
+
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(t, 5);
+
+ status = ServerAllocateOIDs(
+ hLocalOr,
+ hMyProcess,
+ &aOxids[0],
+ 5,
+ &aOids[5],
+ &t);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(t, 5);
+
+ PrintToConsole("Allocated oxid %I64x with OIDs:\n", aOxids[0]);
+ for(i = 0; i < 10; i++)
+ {
+ PrintToConsole("\t%I64x\n", aOids[i]);
+ }
+
+ aOxidInfo[1].dwTid = 2;
+ aOxidInfo[1].dwPid = 42;
+ aOxidInfo[1].dwAuthnHint = 99;
+ aOxidInfo[1].psa = 0;
+
+ status = UuidCreate(&aOxidInfo[1].ipidRemUnknown);
+ ASSERT(status == RPC_S_OK);
+
+ status = ServerAllocateOXIDAndOIDs(
+ hLocalOr,
+ hMyProcess,
+ &aOxids[1],
+ FALSE,
+ 10,
+ &aOids[10],
+ &t,
+ &aOxidInfo[1],
+ pdsaMyExpandedStringBindings,
+ pdsaMyTestBindings);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(t, 10);
+
+ PrintToConsole("Allocated oxid %I64x with OIDs:\n", aOxids[1]);
+ for(i = 10; i < 20; i++)
+ {
+ PrintToConsole("\t%I64x\n", aOids[i]);
+ }
+
+ aOxidInfo[2].dwTid = 3;
+ aOxidInfo[2].dwPid = 42;
+ aOxidInfo[2].dwAuthnHint = 17171717;
+ aOxidInfo[2].psa = 0;
+
+ status = UuidCreate(&aOxidInfo[2].ipidRemUnknown);
+ ASSERT(status == RPC_S_OK);
+
+ status = ServerAllocateOXIDAndOIDs(
+ hLocalOr,
+ hMyProcess,
+ &aOxids[2],
+ FALSE,
+ 10,
+ &aOids[20],
+ &t,
+ &aOxidInfo[2],
+ pdsaMyExpandedStringBindings,
+ pdsaMyTestBindings);
+
+ ASSERT(status == RPC_S_OK);
+ EQUAL(t, 10);
+
+ PrintToConsole("Allocated oxid %I64x with OIDs:\n", aOxids[2]);
+ for(i = 20; i < 30; i++)
+ {
+ PrintToConsole("\t%I64x\n", aOids[i]);
+ }
+
+ SyncWithClient(++TestCase);
+
+ status = ServerFreeOXIDAndOIDs(
+ hLocalOr,
+ hMyProcess,
+ aOxids[1],
+ 10,
+ &aOids[10]
+ );
+
+ ASSERT(status == OR_OK);
+
+ status = ServerFreeOXIDAndOIDs(
+ hLocalOr,
+ hMyProcess,
+ aOxids[2],
+ 10,
+ &aOids[20]
+ );
+
+ ASSERT(status == OR_OK);
+
+ PrintToConsole("Freed OXID %I64x and %I64x\n", aOxids[1], aOxids[2]);
+
+ SyncWithClient(++TestCase);
+
+ // Wait for rundowns on oxid 0 of OIDs 0, 1, 7 and 9
+
+ AddRundown(aOids[0], FALSE);
+ AddRundown(aOids[1], FALSE);
+ AddRundown(aOids[7], FALSE);
+ AddRundown(aOids[9], FALSE);
+
+ WaitForAllRundowns();
+
+ SyncWithClient(++TestCase);
+
+ TestCase = ~0;
+ SyncWithClient(TestCase);
+
+ // Free OID 3 it shouldn't rundown after this; and an invalid oid.
+
+ aOidDels[0] = aOids[3];
+ aOidDels[1] = reservedBase;
+
+ status =
+ BulkUpdateOIDs(hLocalOr,
+ hMyProcess,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 2,
+ aOidDels,
+ 0,
+ 0
+ );
+
+ // Wait for rundowns on oxid 0 of OIDs 2, 4, 5, 6 and 8
+ // Client has exited
+
+ AddRundown(aOids[2], FALSE);
+ AddRundown(aOids[4], TRUE);
+ AddRundown(aOids[5], FALSE);
+ AddRundown(aOids[6], FALSE);
+ AddRundown(aOids[8], TRUE);
+
+ WaitForAllRundowns();
+
+ return(RPC_S_OK);
+}
+
+// Client side
+RPC_STATUS
+RunClient()
+{
+ RPC_STATUS status;
+ DUALSTRINGARRAY *pdaRemoteOrBindings = 0;
+ OXID_INFO oi;
+ MID mid;
+ int i;
+ OXID_OID_PAIR aUpdates[10];
+ OID_MID_PAIR aDeletes[6];
+ OXID_REF aoxidRefs[2];
+ LONG aStatus[10];
+
+ SyncWithServer(++TestCase);
+
+ // Server has allocated oxids and oids
+
+ status =
+ GetState(hServerOrTest,
+ 3,
+ 30,
+ 3,
+ aOxids,
+ aOids,
+ aOxidInfo,
+ &pdaRemoteOrBindings);
+
+ ASSERT(status == RPC_S_OK);
+ ASSERT(pdaRemoteOrBindings);
+ EQUAL(aOxidInfo[0].psa, 0);
+
+ // Resolve OXID 0
+ oi.psa =0;
+
+ status =
+ ClientResolveOXID(hLocalOr,
+ hMyProcess,
+ &aOxids[0],
+ pdaRemoteOrBindings,
+ FALSE,
+ &oi,
+ &mid);
+
+ ASSERT(status == RPC_S_OK);
+ PrintToConsole("Resolved OXID: %I64x on MID %I64x\n", aOxids[0], mid);
+ EQUAL( ( (oi.dwTid == aOxidInfo[0].dwTid) || oi.dwTid == 0), 1);
+ EQUAL( ( (oi.dwPid == aOxidInfo[0].dwPid) || oi.dwPid == 0), 1);
+ EQUAL(oi.dwAuthnHint, aOxidInfo[0].dwAuthnHint);
+ if (memcmp(&oi.ipidRemUnknown, &aOxidInfo[0].ipidRemUnknown, sizeof(IPID)) != 0)
+ {
+ EQUAL(0, 1);
+ }
+ PrintDualStringArray("Expanded binding", oi.psa, FALSE);
+ MIDL_user_free(oi.psa);
+
+ // Add some valid and invalid oids
+ for (i = 0; i < 10; i++)
+ {
+ aUpdates[i].mid = mid;
+ aUpdates[i].oxid = aOxids[0];
+ aUpdates[i].oid = aOids[i];
+ }
+
+ aUpdates[9].mid = reservedBase;
+ aUpdates[8].oxid = reservedBase;
+ aUpdates[7].oid = reservedBase;
+
+ status =
+ BulkUpdateOIDs(hLocalOr,
+ hMyProcess,
+ 10,
+ aUpdates,
+ aStatus,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0);
+
+ ASSERT(status == OR_PARTIAL_UPDATE);
+ for(i = 0; i < 7; i++)
+ {
+ EQUAL(aStatus[i], 0);
+ }
+ EQUAL(aStatus[7], 0); // Okay to register unknown OID
+ EQUAL(aStatus[8], OR_BADOXID);
+ EQUAL(aStatus[9], OR_BADOXID);
+
+ // Delete a few
+
+ // Add three not added last call
+ // .oxid and .mid correct
+ aUpdates[0].oid = aOids[8];
+ aUpdates[1].oid = aOids[9];
+
+ // Remove 2 added last call, 1 from this call and 2 invalid
+ for(i = 0; i < 6; i++)
+ {
+ aDeletes[i].oid = aOids[i];
+ aDeletes[i].mid = mid;
+ }
+ aDeletes[2].oid = aOids[9];
+ aDeletes[3].oid = reservedBase;
+ aDeletes[4].mid = reservedBase;
+ aDeletes[5].oid = aOids[6];
+
+ status =
+ BulkUpdateOIDs(hLocalOr,
+ hMyProcess,
+ 2,
+ aUpdates,
+ aStatus,
+ 6,
+ aDeletes,
+ 0,
+ 0,
+ 0,
+ 0);
+
+ ASSERT(status == OR_OK);
+ EQUAL(aStatus[0], OR_OK);
+ EQUAL(aStatus[1], OR_OK);
+
+ // 6 has been added and deleted, add it again.
+ aUpdates[0].oid = aOids[6];
+ status =
+ BulkUpdateOIDs(hLocalOr,
+ hMyProcess,
+ 1,
+ aUpdates,
+ aStatus,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0);
+ ASSERT(status == OR_OK);
+ EQUAL(aStatus[0], OR_OK);
+
+ // Final state: D - added and deleted, A - added, E - D + added, N not added
+ // OID: 0 1 2 3 4 5 6 7 8 9
+ // State: D D A A A A E N A D
+
+ // Resolve OXID 1
+
+ if (mid != gLocalMid)
+ {
+ MID mid2;
+ // No resolve required for local machine.
+
+ PrintToConsole("Remote server; resolving second OXID\n");
+ oi.psa = 0;
+ status =
+ ClientResolveOXID(hLocalOr,
+ hMyProcess,
+ &aOxids[1],
+ pdaRemoteOrBindings,
+ FALSE,
+ &oi,
+ &mid2);
+
+ ASSERT(status == RPC_S_OK);
+ PrintToConsole("Resolved OXID: %I64x on MID %I64x\n", aOxids[1], mid);
+ EQUAL(mid, mid2);
+ EQUAL(oi.dwTid, 0);
+ EQUAL(oi.dwPid, 0);
+ EQUAL(oi.dwAuthnHint, aOxidInfo[1].dwAuthnHint);
+ if (memcmp(&oi.ipidRemUnknown, &aOxidInfo[1].ipidRemUnknown, sizeof(IPID)) != 0)
+ {
+ EQUAL(0, 1);
+ }
+ PrintDualStringArray("Expanded binding", oi.psa, FALSE);
+ MIDL_user_free(oi.psa);
+ }
+
+ // Add some of the oids.
+ for (i = 0; i < 5; i++)
+ {
+ aUpdates[i].mid = mid;
+ aUpdates[i].oxid = aOxids[1];
+ aUpdates[i].oid = aOids[i+10];
+ }
+
+ // Release our processes hold on the oxids, this is okay since the OIDs
+ // are keeping them alive.
+
+ for (i = 0; i < 2; i++)
+ {
+ aoxidRefs[i].oxid = aOxids[i];
+ aoxidRefs[i].mid = mid;
+ }
+ aoxidRefs[0].refs = 1;
+ aoxidRefs[1].refs = 4; // invalid, will cause an DbgPrint in checked or.
+
+ status =
+ BulkUpdateOIDs(hLocalOr,
+ hMyProcess,
+ 5,
+ aUpdates,
+ aStatus,
+ 0,
+ 0,
+ 0,
+ 0,
+ 2,
+ aoxidRefs);
+
+ ASSERT(status == OR_OK);
+ for(i = 0; i < 5; i++)
+ {
+ EQUAL(aStatus[i], 0);
+ }
+
+ SyncWithServer(++TestCase);
+
+ // Server has freed oxids and oids
+
+ // Can't test that adding an invalid OID is caught, because it
+ // isn't until the client actually pings the real server.
+
+ // Since the client has already resolved oxid1 we can re-resolve it.
+
+ // Try to lookup oxid 2 which has also been freed, it should fail.
+
+ oi.psa = 0;
+
+ status =
+ ClientResolveOXID(hLocalOr,
+ hMyProcess,
+ &aOxids[2],
+ pdaRemoteOrBindings,
+ FALSE,
+ &oi,
+ &mid);
+
+ ASSERT(status == OR_BADOXID);
+ EQUAL(oi.psa,0);
+
+ SyncWithServer(++TestCase);
+
+ // Server waited for first set of rundowns
+
+ SyncWithServer(++TestCase);
+
+ SyncWithServer(~0);
+
+ // Server will wait for the last set of rundowns.
+
+ return(RPC_S_OK);
+}
+
+
+int main (int argc, char *argv[])
+{
+ RPC_STATUS status;
+ PSZ pszProtseq, pszServer;
+
+ argc--;
+ argv++;
+
+ pszServer = 0;
+ pszProtseq = "ncalrpc";
+
+ while(argc)
+ {
+ switch(argv[0][1])
+ {
+ case 't':
+ pszProtseq = argv[1];
+ argc--;
+ argv++;
+ break;
+ case 'l':
+ case 'c':
+ fServer = FALSE;
+ break;
+ case 'i':
+ fInternet = TRUE;
+ break;
+ case 's':
+ pszServer = argv[1];
+ argc--;
+ argv++;
+ break;
+ default:
+ PrintToConsole("Usage: ortest [client|-client] [-internet] [-t protseq ] [-s server addr]\n"
+ );
+ return(0);
+ }
+ argc--;
+ argv++;
+ }
+
+ PrintToConsole("OrTest: %s starting...\n", fInternet ? "internet test" :
+ ( fServer ? "server" : "client") );
+
+ if (fInternet)
+ {
+ status = RunInternetPortTests();
+ }
+ else
+ {
+ status = Startup(pszProtseq, pszServer);
+ ASSERT(status == RPC_S_OK);
+
+ status = ConnectToLocalOr();
+ ASSERT(status == RPC_S_OK);
+
+ if (fServer)
+ {
+ status = RunServer();
+ }
+ else
+ {
+ status = RunClient();
+ }
+ }
+ if (status == RPC_S_OK)
+ {
+ PrintToConsole("Test Passed\n");
+ }
+ else
+ {
+ PrintToConsole("Test Failed %d\n", Errors);
+ }
+
+ if (hLocalOr) RpcBindingFree(&hLocalOr);
+ if (hMyProcess) RpcSsDestroyClientContext(&hMyProcess);
+ if (hServerOrTest) RpcBindingFree(&hServerOrTest);
+ Sleep(1000);
+ return(0);
+}
+
+// Shared initialization code
+
+RPC_STATUS
+Startup(PSZ protseq, PSZ server)
+{
+ RPC_STATUS status;
+ DUALSTRINGARRAY *pdsaT, *pdsaT2;
+ RPC_BINDING_VECTOR *pbv;
+
+ pdsaMyExpandedStringBindings = (DUALSTRINGARRAY *)MIDL_user_allocate(500*2);
+ pdsaMyCompressedSecurityBindings = (DUALSTRINGARRAY *)MIDL_user_allocate(4 + 6*2);
+ pdsaMyTestBindings = (DUALSTRINGARRAY *)MIDL_user_allocate(4 + 19*2);
+ ASSERT( pdsaMyExpandedStringBindings
+ && pdsaMyCompressedSecurityBindings
+ && pdsaMyTestBindings);
+
+ pdsaMyCompressedSecurityBindings->wNumEntries = 6;
+ pdsaMyCompressedSecurityBindings->wSecurityOffset = 2;
+ pdsaMyCompressedSecurityBindings->aStringArray[0] = 0;
+ pdsaMyCompressedSecurityBindings->aStringArray[1] = 0;
+ pdsaMyCompressedSecurityBindings->aStringArray[2] = 10; // authn winnt
+ pdsaMyCompressedSecurityBindings->aStringArray[3] = -1; // authz none
+ pdsaMyCompressedSecurityBindings->aStringArray[4] = 0;
+ pdsaMyCompressedSecurityBindings->aStringArray[5] = 0;
+
+ _UseProtseq(0, L"ncalrpc", &pdsaT, &pdsaT2); // inits psaMyExpandedStringBindings
+ EQUAL( (pdsaT != 0), 1);
+ EQUAL( (pdsaT2 != 0), 1);
+ MIDL_user_free(pdsaT);
+ MIDL_user_free(pdsaT2);
+
+ pdsaMyTestBindings->wNumEntries = 19;
+ pdsaMyTestBindings->wSecurityOffset = 2;
+ memcpy(pdsaMyTestBindings->aStringArray,
+ L"\0\0\x7\xff" L"APrincipal\0\x9\xD\0\0",
+ 19*2);
+
+ if (fServer)
+ {
+
+ // Listen to the remote (if any) protseq. Not part of the bindings
+ // registered with the OR until a callback to UseProtseq is made.
+ if (protseq)
+ {
+ status = RpcServerUseProtseqA(protseq, 0, 0);
+ ASSERT(status == RPC_S_OK);
+ }
+
+ status = RpcServerInqBindings(&pbv);
+ ASSERT(status == RPC_S_OK);
+
+ status =
+ RpcEpRegister(_IOrTest_ServerIfHandle, pbv, 0, 0);
+ ASSERT(status == RPC_S_OK);
+
+ status =
+ RpcBindingVectorFree(&pbv);
+ ASSERT(status == RPC_S_OK);
+
+ // Register UseProtseq callback IF
+ status =
+ RpcServerRegisterIf(_IOrCallback_ServerIfHandle, 0, 0);
+ ASSERT(status == RPC_S_OK);
+
+ // Register test to test IF
+ status =
+ RpcServerRegisterIf(_IOrTest_ServerIfHandle, 0, 0);
+ ASSERT(status == RPC_S_OK);
+
+ // Register rundown OID (fake ORPC) callback IF
+ status =
+ RpcServerRegisterIf(_IRundown_ServerIfHandle, 0, 0);
+ ASSERT(status == RPC_S_OK);
+
+ status =
+ RpcServerListen(1, 10, TRUE);
+ ASSERT(status == RPC_S_OK);
+
+ hServerEvent = CreateEvent(0, FALSE, FALSE, 0);
+ hClientEvent = CreateEvent(0, FALSE, FALSE, 0);
+ hRundownEvent = CreateEvent(0, FALSE, FALSE, 0);
+
+ ASSERT(hServerEvent && hClientEvent && hRundownEvent);
+
+ PrintToConsole("\tWaiting for client...\n");
+
+ SyncWithClient(++TestCase);
+
+ status = RPC_S_OK;
+ }
+ else
+ {
+ PSZ stringbinding;
+
+ // Make binding to remote OR
+
+ status =
+ RpcStringBindingComposeA(0, protseq, server, 0, 0, &stringbinding);
+ ASSERT(status == RPC_S_OK);
+
+ status =
+ RpcBindingFromStringBindingA(stringbinding, &hServerOrTest);
+
+ if (status == RPC_S_OK)
+ {
+ status = TestBinding(hServerOrTest);
+ if (status != RPC_S_OK)
+ {
+ PrintToConsole("Connect to server failed %d\n", status);
+ return(status);
+ }
+ status = SyncWithServer(++TestCase);
+ }
+ }
+
+ return(status);
+}
+
+RPC_STATUS
+ConnectToLocalOr()
+{
+ RPC_STATUS status;
+ DWORD timeout;
+ OXID reservedOxid;
+ BOOL disable;
+ DWORD authn;
+ DWORD imp;
+ BOOL mutual;
+ BOOL secref;
+ DWORD cServerSvc = 0;
+ PUSHORT pServerSvc = 0;
+ DWORD cClientSvc = 0;
+ PUSHORT pClientSvc = 0;
+ int i;
+ PWSTR pwstrLegacy = 0;
+ DWORD cAuthId = 0;
+ PSZ pszAuthId = 0;
+ DWORD flags, pid, scm_pid, tokenid;
+
+ status =
+ RpcBindingFromStringBinding(pwstrOr, &hLocalOr);
+
+ EQUAL(status, RPC_S_OK);
+
+ status = Connect(hLocalOr,
+ &hMyProcess,
+ &timeout,
+ &pdsaLocalOrBindings,
+ &gLocalMid,
+ 5,
+ &reservedBase,
+ &flags,
+ &pwstrLegacy,
+ &authn,
+ &imp,
+ &cServerSvc,
+ &pServerSvc,
+ &cClientSvc,
+ &pClientSvc,
+ &pid,
+ &scm_pid,
+ &tokenid);
+
+ ASSERT(status == RPC_S_OK);
+ ASSERT(pdsaLocalOrBindings);
+ ASSERT(pServerSvc);
+ ASSERT(pClientSvc);
+
+ PrintToConsole("Connected to local object resolver:\n\tFlags:\n");
+ if (flags & CONNECT_DISABLEDCOM)
+ {
+ flags &= ~CONNECT_DISABLEDCOM;
+ PrintToConsole("\t\tDCOM DISABLED");
+ }
+ else
+ PrintToConsole("\t\tDCOM enabled");
+
+ if (flags & CONNECT_MUTUALAUTH)
+ {
+ flags &= ~CONNECT_MUTUALAUTH;
+ PrintToConsole("\tMutal authn");
+ }
+ else
+ PrintToConsole("\tNo Mutal authn");
+
+ if (flags & CONNECT_SECUREREF)
+ {
+ flags &= ~CONNECT_SECUREREF;
+ PrintToConsole("\tSecure reference counting\n");
+ }
+ else
+ PrintToConsole("\tStandard reference counting\n");
+
+
+ PrintToConsole("\tSecurity: authn: %d, imp: %d, legacy %S\n", authn, imp, pwstrLegacy);
+ PrintToConsole("\tTimeout %d seconds, mid %I64x\n"
+ "\tpid %d, scm pid %d, token id: %d\n",
+ timeout, gLocalMid, pid, scm_pid, tokenid);
+ PrintToConsole("\tReserved 5 oids, starting at %I64x\n", reservedBase);
+ PrintToConsole("\tServer security services: %d\n", cServerSvc);
+ for (i = 0; i < cServerSvc; i++ )
+ {
+ PrintToConsole("\t\tService: %d is %d\n", i, pServerSvc[i]);
+ }
+ PrintToConsole("\tClient security services: %d\n", cClientSvc);
+ for (i = 0; i < cClientSvc; i++ )
+ {
+ PrintToConsole("\t\tService: %d is %d\n", i, pClientSvc[i]);
+ }
+ PrintDualStringArray("Local OR bindings", pdsaLocalOrBindings, TRUE);
+ PrintToConsole("\n\n");
+
+ MIDL_user_free(pServerSvc);
+ MIDL_user_free(pClientSvc);
+ return(RPC_S_OK);
+}
+
+// Synchronization between ortest clients and servers
+
+void
+SyncWithClient(DWORD Test)
+// Called by server thread at start of each test sequence
+{
+ DWORD status;
+
+ if (Test > 1) SetEvent(hClientEvent);
+
+ PrintToConsole("Waiting for client sync: Test case %d\n", Test);
+
+ // Wait for the client to finish his test case
+ status = WaitForSingleObject(hServerEvent, 120*1000);
+
+ if (status == WAIT_TIMEOUT)
+ {
+ ASSERT(("Client never called back", 0));
+ }
+
+ if (Test == ~0)
+ {
+ SetEvent(hClientEvent);
+ Sleep(1000);
+ }
+ return;
+}
+
+// Managers for ortest servers
+
+error_status_t
+_TestBinding(
+ handle_t hClient
+ )
+{
+ return(RPC_S_OK);
+}
+
+error_status_t
+_WaitForNextTest(handle_t hClient,
+ DWORD Test)
+// Called by client after each test sequence.
+{
+ DWORD status;
+
+ if (Test != TestCase)
+ {
+ ASSERT(("Test case sync wrong", 0));
+ }
+
+ SetEvent(hServerEvent);
+
+ PrintToConsole("Client ready for test case %d\n", Test);
+
+ status = WaitForSingleObject(hClientEvent, 60*20*1000);
+
+ if (status == WAIT_TIMEOUT)
+ {
+ ASSERT(("Server never finished test case", 0));
+ }
+
+}
+
+error_status_t
+SyncWithServer(DWORD Test)
+{
+ RPC_STATUS status;
+
+ status = WaitForNextTest(hServerOrTest, Test);
+
+ EQUAL(status, RPC_S_OK);
+ return(status);
+}
+
+error_status_t
+_GetState(
+ handle_t hClient,
+ long cOxids,
+ long cOids,
+ long cOxidInfos,
+ OXID aoxids[],
+ OID aoids[],
+ OXID_INFO aois[],
+ DUALSTRINGARRAY **ppdsaRemoteOrBindings
+ )
+{
+ int i;
+ for (i = 0; i < cOxids; i++)
+ {
+ aoxids[i] = aOxids[i];
+ }
+ for (i = 0; i < cOids; i++)
+ {
+ aoids[i] = aOids[i];
+ }
+ for(i = 0; i < cOxidInfos; i++)
+ {
+ aois[i].dwTid = aOxidInfo[i].dwTid;
+ aois[i].dwPid = aOxidInfo[i].dwPid;
+ aois[i].dwAuthnHint = aOxidInfo[i].dwAuthnHint;
+ memcpy(&aois[i].ipidRemUnknown, &aOxidInfo[i].ipidRemUnknown, sizeof(IPID));
+ aois[i].psa = 0;
+ }
+ *ppdsaRemoteOrBindings = MIDL_user_allocate(4 + pdsaLocalOrBindings->wNumEntries * 2);
+ memcpy(*ppdsaRemoteOrBindings, pdsaLocalOrBindings, 4 + pdsaLocalOrBindings->wNumEntries * 2);
+ return(RPC_S_OK);
+}
+
+// Managers for OR callbacks
+
+error_status_t
+_UseProtseq(
+ IN handle_t hRpc,
+ IN PWSTR pwstrProtseq,
+ OUT DUALSTRINGARRAY **ppdsa,
+ OUT DUALSTRINGARRAY **ppdsaSecurity
+ )
+{
+ RPC_STATUS status;
+ BOOL f;
+ DWORD t;
+ HANDLE hT;
+ TOKEN_USER *ptu;
+ BYTE buffer[512];
+ WCHAR buffer1[256];
+
+ if (hRpc)
+ {
+ status = RpcImpersonateClient(0);
+ ASSERT(status == RPC_S_OK);
+
+ f = OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_QUERY, TRUE, &hT);
+ EQUAL(f, TRUE);
+ CloseHandle(hT);
+
+ f = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hT);
+ EQUAL(f, TRUE);
+ }
+ else
+ {
+ f = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hT);
+ EQUAL(f, TRUE);
+ }
+
+ f = GetTokenInformation(hT,
+ TokenUser,
+ buffer,
+ 512,
+ &t);
+ EQUAL(f, TRUE);
+ ptu = (TOKEN_USER *)buffer;
+
+ CloseHandle(hT);
+
+ t = 256;
+ f = GetUserNameW(buffer1, &t);
+ if (f == FALSE)
+ {
+ PrintToConsole("Get user name failed %d\n", GetLastError());
+ }
+
+ PrintToConsole("UseProtseq %S called by %S:\n\t", pwstrProtseq, buffer1);
+ PrintSid(ptu->User.Sid);
+
+ RpcRevertToSelf();
+
+ if (!fServer && _wcsicmp(pwstrProtseq, L"ncalrpc") != 0)
+ {
+ ASSERT(0);
+ }
+
+ status = RpcServerUseProtseqW(pwstrProtseq, 0, 0);
+ ASSERT(status == RPC_S_OK);
+
+ // Construct new bindings array.
+ {
+ RPC_BINDING_VECTOR * pbv;
+ int i, j = 0;
+ PWSTR pT = pdsaMyExpandedStringBindings->aStringArray;
+
+ status = RpcServerInqBindings(&pbv);
+ EQUAL(status, RPC_S_OK);
+
+ for(i = 0; i < pbv->Count; i++)
+ {
+ PWSTR pStringBinding = 0;
+ status = RpcBindingToStringBinding(pbv->BindingH[i], &pStringBinding);
+ EQUAL(status, RPC_S_OK);
+
+ wcscpy(pT, pStringBinding);
+ j += wcslen(pT) + 1;
+ pT = wcschr(pT, 0);
+ pT++;
+
+ status = RpcStringFree(&pStringBinding);
+ EQUAL(status, RPC_S_OK);
+ EQUAL(pStringBinding, 0);
+ }
+
+ *pT = 0;
+ pdsaMyExpandedStringBindings->wNumEntries = j + 1 + 2;
+ pdsaMyExpandedStringBindings->wSecurityOffset = j + 1;
+ pT[1] = 0; // no security
+ pT[2] = 0;
+ }
+
+ *ppdsa = MIDL_user_allocate(sizeof(DUALSTRINGARRAY) + pdsaMyExpandedStringBindings->wNumEntries * 2);
+
+ ASSERT(*ppdsa);
+
+ (*ppdsa)->wNumEntries = pdsaMyExpandedStringBindings->wNumEntries;
+ (*ppdsa)->wSecurityOffset = pdsaMyExpandedStringBindings->wSecurityOffset;
+ memcpy((*ppdsa)->aStringArray,
+ pdsaMyExpandedStringBindings->aStringArray,
+ pdsaMyExpandedStringBindings->wNumEntries * 2);
+
+
+ *ppdsaSecurity = MIDL_user_allocate(sizeof(DUALSTRINGARRAY) + 6*2);
+ ASSERT(*ppdsaSecurity);
+
+ (*ppdsaSecurity)->wNumEntries = 6;
+ (*ppdsaSecurity)->wSecurityOffset = 2;
+ (*ppdsaSecurity)->aStringArray[0] = 0;
+ (*ppdsaSecurity)->aStringArray[1] = 0;
+ (*ppdsaSecurity)->aStringArray[2] = 10; // authn winnt
+ (*ppdsaSecurity)->aStringArray[3] = -1; // authz none
+ (*ppdsaSecurity)->aStringArray[4] = 0;
+ (*ppdsaSecurity)->aStringArray[5] = 0;
+
+ return(0);
+}
+
+error_status_t
+_RawRundownOid(
+ handle_t hRpc,
+ ORPCTHIS *pthis,
+ LOCALTHIS *plocalthis,
+ ORPCTHAT *pthat,
+ ULONG cOid,
+ OID aOid[],
+ UCHAR afOk[]
+ )
+{
+ int i, j;
+ RPC_STATUS status;
+ BOOL fFound;
+ IPID ipidT;
+ UCHAR buffer[512];
+ WCHAR buffer1[256];
+ DWORD t;
+ BOOL f;
+ HANDLE hT;
+ TOKEN_USER *ptu;
+
+ ASSERT(cOid);
+ ASSERT(plocalthis->callcat == CALLCAT_SYNCHRONOUS);
+ ASSERT(plocalthis->dwClientThread == 0);
+ ASSERT(pthis->extensions == 0);
+ ASSERT(pthis->version.MajorVersion == COM_MAJOR_VERSION);
+ ASSERT(pthis->version.MinorVersion == COM_MINOR_VERSION);
+ ASSERT(pthis->flags == ORPCF_LOCAL);
+ ASSERT(pthis->reserved1 == 0);
+ ASSERT(pthat->extensions == 0);
+ pthat->flags = 0;
+
+ status = RpcImpersonateClient(0);
+ ASSERT(status == RPC_S_OK);
+
+ t = 256;
+ f = GetUserNameW(buffer1, &t);
+ if (f == FALSE)
+ {
+ PrintToConsole("Get user name failed %d\n", GetLastError());
+ }
+
+ f = OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_QUERY, TRUE, &hT);
+ EQUAL(f, TRUE);
+ CloseHandle(hT);
+
+ f = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hT);
+ EQUAL(f, TRUE);
+
+ f = GetTokenInformation(hT,
+ TokenUser,
+ buffer,
+ 512,
+ &t);
+ EQUAL(f, TRUE);
+ ptu = (TOKEN_USER *)buffer;
+
+ CloseHandle(hT);
+
+ status = RpcBindingInqObject(hRpc, &ipidT);
+ ASSERT(status == RPC_S_OK);
+
+ PrintToConsole("Rundown of %d oids called by %S:\n\t", cOid, buffer1);
+ PrintSid(ptu->User.Sid);
+
+ for (j = 0; j < cOid; j++)
+ {
+ fFound = FALSE;
+
+ PrintToConsole("Oid %I64x randown\n", aOid[j]);
+
+ for(i = 0; i < dwlimRundowns; i++)
+ {
+ if (aOid[j] == aRundowns[i].oid)
+ {
+ fFound = TRUE;
+ if (aRundowns[i].fForceSecond)
+ {
+ aRundowns[i].fForceSecond = FALSE;
+ afOk[j] = 0;
+ }
+ else
+ {
+ afOk[j] = 1;
+ EQUAL(aRundowns[i].fReady, TRUE);
+ aRundowns[i].fReady = FALSE;
+
+ aRundowns[i].oid = aRundowns[dwlimRundowns - 1].oid;
+ aRundowns[i].fReady = aRundowns[dwlimRundowns - 1].fReady;
+ aRundowns[i].fForceSecond = aRundowns[dwlimRundowns - 1].fForceSecond;
+ dwlimRundowns--;
+
+ SetEvent(hRundownEvent);
+ }
+ }
+ }
+
+ if (!fFound)
+ {
+ PrintToConsole("Unexpected oid rundown: %I64x\n", aOid[j]);
+ afOk[j] = 1;
+ }
+ }
+
+ RpcRevertToSelf();
+ return(0);
+
+}
+
+// Unimplement IRundown base methods
+
+HRESULT
+_DummyQueryInterfaceIOSCM(
+ handle_t rpc,
+ ORPCTHIS *pthis,
+ LOCALTHIS *plocalthis,
+ ORPCTHAT *pthat,
+ DWORD dummy)
+{
+ ASSERT(0);
+}
+
+HRESULT
+_DummyAddRefIOSCM(
+ handle_t rpc,
+ ORPCTHIS *pthis,
+ LOCALTHIS *plocalthis,
+ ORPCTHAT *pthat,
+ DWORD dummy)
+{
+ ASSERT(0);
+}
+
+HRESULT
+_DummyReleaseIOSCM(
+ handle_t rpc,
+ ORPCTHIS *pthis,
+ LOCALTHIS *plocalthis,
+ ORPCTHAT *pthat,
+ DWORD dummy)
+{
+ ASSERT(0);
+}
+
+HRESULT
+_DummyRemQuery(
+ handle_t handle
+ )
+{
+ ASSERT(0);
+}
+
+
+HRESULT
+_DummyRemAddRef(
+ handle_t handle
+ )
+{
+ ASSERT(0);
+}
+
+
+HRESULT
+_DummyRemRelease(
+ handle_t handle
+ )
+{
+ ASSERT(0);
+}
+
+HRESULT
+_DummyRemChangeRef(
+ handle_t handle
+ )
+{
+ ASSERT(0);
+}
+
+// Rundown helpers
+
+void
+AddRundown(ID oid, BOOL fRundownTwice)
+{
+ aRundowns[dwlimRundowns].oid = oid;
+ aRundowns[dwlimRundowns].fReady = TRUE;
+ aRundowns[dwlimRundowns].fForceSecond = fRundownTwice;
+
+ dwlimRundowns++;
+}
+
+void WaitForAllRundowns()
+{
+ DWORD status;
+ int i;
+ BOOL fDone;
+
+ PrintToConsole("Waiting for rundowns...\n");
+
+ for(;;)
+ {
+ status = WaitForSingleObject(hRundownEvent, 19 * 60 * 1000);
+
+ if (status == WAIT_TIMEOUT)
+ {
+ PrintToConsole("Wait for rundowns took a long time...\n");
+ ASSERT(0);
+ }
+
+ fDone = TRUE;
+
+ for(i = 0; i < dwlimRundowns; i++)
+ {
+ if (aRundowns[i].fReady)
+ {
+ fDone = FALSE;
+ }
+ }
+
+ if (fDone)
+ {
+ return;
+ }
+ }
+}
+
+// Needs to link rtifs.lib, but shouldn't be called..
+void FixupForUniquePointerServers(void *p)
+{
+ ASSERT(0);
+}
diff --git a/private/ole32/dcomss/dcomtest/sources b/private/ole32/dcomss/dcomtest/sources
new file mode 100644
index 000000000..26c46cc9e
--- /dev/null
+++ b/private/ole32/dcomss/dcomtest/sources
@@ -0,0 +1,56 @@
+!IF 0
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Revision History:
+
+!ENDIF
+
+TARGETNAME=ortest
+TARGETTYPE=PROGRAM
+TARGETPATH=bin
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\rpcrt4.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib \
+
+LINKLIBS=$(BASEDIR)\private\dcomidl\obj\*\dcomidl.lib \
+ $(BASEDIR)\private\rpc\runtime\rtifs\*\rtifs.lib
+
+INCLUDES=$(BASEDIR)\private\types\idl;$(BASEDIR)\private\dcomidl;$(BASEDIR)\private\dcomidl\obj;.;..;..\objex;obj
+INCLUDES=$(INCLUDES);$(BASEDIR)\private\rpc\runtime\rtifs\obj
+
+BLDCRT=1
+MSC_WARNING_LEVEL=/WX
+USE_MSVCRT=1
+
+SOURCES= \
+ uor.rc \
+ umisc.cxx \
+ uor_c.c \
+ uor_s.c \
+ odeth_s.c \
+ ortest.c
+
+RPCENV=-DNTENV -DWIN32RPC -DNTWIN32RPC
+
+C_DEFINES=$(RPCENV) $(RPCTARGETENV) -DUNICODE
+
+UMTYPE=console
+UMAPPL=
+UMINCL=
+UMLIBS=
+UMRES=
+
+NTTARGETFILE0=testidl
+
diff --git a/private/ole32/dcomss/dcomtest/umisc.cxx b/private/ole32/dcomss/dcomtest/umisc.cxx
new file mode 100644
index 000000000..4d91351f7
--- /dev/null
+++ b/private/ole32/dcomss/dcomtest/umisc.cxx
@@ -0,0 +1,384 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ UMisc.C
+
+Abstract:
+
+ Helper functions for OR test applications.
+
+Author:
+
+ Mario Goertzel [mariogo] Apr-23-95
+
+Revision History:
+
+--*/
+
+#include <or.hxx>
+#include <stdio.h>
+#include <umisc.h>
+
+// Copied from string.cxx
+
+// Types
+
+struct PROTSEQ_MAPPING {
+ USHORT iProtseqId;
+ USHORT *pwszProtseq;
+ };
+
+// Globals
+
+static const PROTSEQ_MAPPING
+Mappings[] =
+ {
+ { 0x00, 0 },
+ { 0x01, L"mswmsg" },
+ { 0x02, 0 },
+ { 0x03, 0 },
+ { 0x04, L"ncacn_dnet_dsp" },
+ { 0x05, 0 },
+ { 0x06, 0 },
+ { 0x07, L"ncacn_ip_tcp" },
+ { 0x08, L"ncadg_ip_udp" },
+ { 0x09, L"ncacn_nb_tcp" },
+ { 0x0A, 0 },
+ { 0x0B, 0 },
+ { 0x0C, L"ncacn_spx" },
+ { 0x0D, L"ncacn_nb_ipx"},
+ { 0x0E, L"ncadg_ipx" },
+ { 0x0F, L"ncacn_np"},
+ { 0x10, L"ncalrpc"},
+ { 0x11, 0},
+ { 0x12, L"ncacn_nb_nb"},
+ };
+
+#define PROTSEQ_IDS (sizeof(Mappings)/sizeof(PROTSEQ_MAPPING) - 1)
+
+// Public functions
+
+PWSTR
+GetProtseq(
+ IN USHORT ProtseqId
+ )
+{
+ ASSERT(ProtseqId != 0);
+
+ if (ProtseqId > PROTSEQ_IDS)
+ {
+ return 0;
+ }
+ wchar_t *pwszProtseq = Mappings[ProtseqId].pwszProtseq;
+
+ ASSERT(ProtseqId == Mappings[ProtseqId].iProtseqId);
+
+ return(pwszProtseq);
+}
+
+USHORT
+GetProtseqId(
+ IN PWSTR pwszProtseq
+ )
+{
+ ASSERT(pwszProtseq);
+
+ for (USHORT i = 0; i <= PROTSEQ_IDS; i++)
+ {
+ if ( Mappings[i].pwszProtseq
+ && 0 == wcscmp(Mappings[i].pwszProtseq, pwszProtseq) )
+ {
+ ASSERT(Mappings[i].iProtseqId == i);
+ return(i);
+ }
+ }
+ return(0);
+}
+
+
+#if 0
+// Construct/Transform various STRINGARRAYS
+
+ORSTATUS ConvertStringArray(
+ IN STRINGARRAY *psa,
+ OUT STRINGARRAY **ppsaNew,
+ IN BOOL fHasIds
+ )
+/* ++
+
+Parameters
+
+ psa - Original array in compressed or regular form.
+ Note: Maybe written to and restored during copy.
+
+ ppsaNew - Will contain the new compressed or regular
+ form of psa.
+
+ fHasIds - If TRUE, psa is assumed to be compressed and
+ ppsaNew will contain the regular (non-compressed) version.
+ If FALSE, psa is assume to be regular and ppsaNew is compressed.
+
+-- */
+{
+ int i, size;
+ USHORT *p1, *p2, *p3;
+ PWSTR pwstr;
+
+ // Compute size
+
+ size = 1; // final null terminator.
+
+ p1 = psa->awszStringArray;
+
+ if (*p1 == 0)
+ {
+ // ASSERT(psa->size == 2); // bogus for padded (0 mod 8) arrays
+ size = 2; // two null terminators ONLY.
+ }
+
+ while(*p1)
+ {
+ int sizeT = wcslen(p1);
+
+ if (fHasIds == TRUE)
+ {
+ pwstr = GetProtseq(*p1);
+ if (pwstr != 0)
+ {
+ size += sizeT + wcslen(pwstr) + 1;
+ }
+ else
+ {
+ // Except for interop with future platforms, this
+ // should not be hit.
+ ASSERT(pwstr);
+ // This string will be thrown away from the result.
+ }
+ }
+ else
+ {
+ p2 = wcschr(p1, L':'); // ':' is not valid in protseq.
+ if (p2)
+ {
+ size += sizeT + 1 - (p2 - p1); // proseq len (p2 - p1) become 1 for Id.
+ }
+ else
+ {
+ ASSERT(p2);
+ }
+ }
+
+ p1 = wcschr(p1, 0);
+ ASSERT(*p1 == 0);
+ p1++; // Start of next string or final NULL.
+ }
+
+ *ppsaNew = (STRINGARRAY *)MIDL_user_allocate(sizeof(STRINGARRAY) + size * sizeof(USHORT));
+
+ if (0 == *ppsaNew)
+ {
+ return(OR_NOMEM);
+ }
+
+ (*ppsaNew)->size = size;
+ p3 = (*ppsaNew)->awszStringArray;
+ *p3 = 0;
+
+ p1 = psa->awszStringArray;
+
+ if (*p1 == 0)
+ {
+ // Two null terminators only.
+ ASSERT(size == 2);
+ *(p3 + 1) = 0;
+ return(0);
+ }
+
+ while(*p1)
+ {
+ if (fHasIds == TRUE)
+ {
+ pwstr = GetProtseq(*p1);
+ p1++;
+ if (pwstr != 0)
+ {
+ wcscpy(p3, pwstr);
+ wcscat(p3, L":");
+ wcscat(p3, p1);
+
+ // Move p3 to start of next string (if any);
+ p3 = wcschr(p3, 0);
+ p3++;
+ }
+ else
+ {
+ // String not used, don't know protseq.
+ // Would ASSERT during sizing.
+ }
+ }
+ else
+ {
+ // Must change the protseq to a protseq ID.
+
+ p2 = wcschr(p1, L':');
+ if (p2)
+ {
+ *p2 = 0;
+ *p3 = GetProtseqId(p1);
+ *p2 = L':';
+ if (*p3 != 0)
+ {
+ p3++;
+ p1 = p2 + 1; // Just after ':'
+ wcscpy(p3, p1);
+
+ // Move p3 to start of next string (if any)
+ p3 = wcschr(p3, 0);
+ p3++;
+
+ }
+ }
+ }
+
+ p1 = wcschr(p1, 0);
+ ASSERT(*p1 == 0);
+ p1++; // Start of next string or final NULL.
+ }
+
+ // Second terminator, p3 already points to it.
+ *p3 = 0;
+
+ return(OR_OK);
+}
+#endif
+
+void StringArrayEqual(DUALSTRINGARRAY *pa1, DUALSTRINGARRAY *pa2)
+{
+ wchar_t *p1, *p2;
+ EQUAL(pa1->wNumEntries, pa2->wNumEntries);
+
+ p1 = pa1->aStringArray;
+ while(*p1)
+ {
+ p2 = pa2->aStringArray;
+ while(*p2)
+ {
+ if (wcscmp(p1, p2) == 0)
+ {
+ break;
+ }
+
+ // Try next string.
+ while (*p2)
+ {
+ p2++;
+ }
+
+ if (*(p2 + 1) == 0)
+ {
+ // End of array, didn't find it.
+ EQUAL(0,1);
+ return;
+ }
+ }
+
+ // Next string
+ while(*p1)
+ {
+ p1++;
+ }
+ }
+ return;
+}
+
+void UuidsEqual(UUID *p, UUID *p2)
+{
+ EQUAL(memcmp(p, p2, sizeof(UUID)), 0);
+}
+
+void PrintDualStringArray(
+ IN PSZ pszComment,
+ IN DUALSTRINGARRAY *pdsaIn,
+ IN BOOL fCompressed
+ )
+{
+ RPC_STATUS status;
+ DUALSTRINGARRAY *pdsa = pdsaIn;
+ PrintToConsole("%s: dual string array of %d words:\n", pszComment, pdsa->wNumEntries);
+ PrintToConsole("\tString Bindings:\n");
+
+ PWSTR pProtseq;
+ PWSTR pT = pdsa->aStringArray;
+ while(*pT != 0)
+ {
+ if (fCompressed)
+ {
+ pProtseq = GetProtseq(*pT);
+ PrintToConsole("\t%S:%S\n", pProtseq, pT + 1);
+ }
+ else
+ {
+ PrintToConsole("\t%S\n", pT);
+ }
+ pT = wcschr(pT, 0);
+ pT++;
+ }
+ PrintToConsole("\t0\n");
+
+
+ PrintToConsole("\tSecurity Bindings:\n");
+ pT = &pdsa->aStringArray[pdsa->wSecurityOffset];
+ while(*pT != 0)
+ {
+ PrintToConsole("\tAuthn %i, Authz %i, Principal %S\n", pT[0], pT[1], &pT[2]);
+ pT = wcschr(pT, 0);
+ pT++;
+ }
+ PrintToConsole("\t0\n");
+}
+
+void PrintSid(SID *psid)
+{
+ BYTE *p;
+ int i;
+ __int64 idauth = 0;
+
+ printf("\tS-%u", psid->Revision);
+
+ p = (PBYTE) GetSidIdentifierAuthority(psid);
+
+ for (i = 0; i < 6; i++, p++ )
+ {
+ *(((PBYTE)&idauth) + 5 - i) = *p;
+ }
+
+ printf("-%u", (DWORD)idauth);
+
+ p = GetSidSubAuthorityCount(psid);
+
+ for(i = 0; i < *p; i++)
+ {
+ PDWORD pdw;
+ pdw = GetSidSubAuthority(psid, i);
+ printf("-%u", *pdw);
+ }
+
+ printf("\n");
+ return;
+}
+
+
+LPVOID __RPC_USER MIDL_user_allocate(UINT size)
+{
+ return(HeapAlloc(GetProcessHeap(), 0, size));
+}
+
+void __RPC_USER MIDL_user_free(LPVOID p)
+{
+ HeapFree(GetProcessHeap(), 0, p);
+}
+
+
diff --git a/private/ole32/dcomss/dcomtest/umisc.h b/private/ole32/dcomss/dcomtest/umisc.h
new file mode 100644
index 000000000..b768cc716
--- /dev/null
+++ b/private/ole32/dcomss/dcomtest/umisc.h
@@ -0,0 +1,57 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ UMisc.H
+
+Abstract:
+
+ Header file for OR test applications.
+
+Author:
+
+ Mario Goertzel [mariogo] Apr-23-95
+
+Revision History:
+
+--*/
+
+#ifndef __UMISC_H
+#define __UMISC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PrintToConsole printf
+
+extern ULONG Errors;
+#define EQUAL(X,Y) if ((X)!=(Y)) {PrintToConsole("%s(%d): Error %d: %s (%ld, 0x%lx) != %s (%ld, 0x%lx)\n", __FILE__, __LINE__, ++Errors, #X, (X), (X), #Y, (Y), (Y)); Errors++; }
+#undef ASSERT
+#define ASSERT(X) if (! (X) ) {PrintToConsole("%s(%d): Error %d: Assertion %s not true\n", __FILE__, __LINE__, ++Errors, #X); DebugBreak(); Errors++; }
+
+void StringArrayEqual(
+ IN DUALSTRINGARRAY *,
+ IN DUALSTRINGARRAY *
+ );
+
+void UuidsEqual(
+ IN UUID *,
+ IN UUID *
+ );
+
+void PrintDualStringArray(
+ IN PSZ pszComment,
+ IN DUALSTRINGARRAY *pdsa,
+ IN BOOL fCompressed
+ );
+
+void PrintSid(SID *psid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __UMISC_H
diff --git a/private/ole32/dcomss/dcomtest/uor.acf b/private/ole32/dcomss/dcomtest/uor.acf
new file mode 100644
index 000000000..9bc1a76b3
--- /dev/null
+++ b/private/ole32/dcomss/dcomtest/uor.acf
@@ -0,0 +1,5 @@
+interface IOrTest
+{
+ [comm_status, fault_status] TestBinding();
+ [comm_status, fault_status] WaitForNextTest();
+}
diff --git a/private/ole32/dcomss/dcomtest/uor.idl b/private/ole32/dcomss/dcomtest/uor.idl
new file mode 100644
index 000000000..9773b2028
--- /dev/null
+++ b/private/ole32/dcomss/dcomtest/uor.idl
@@ -0,0 +1,31 @@
+[
+uuid(0cca4990-7ead-11ce-aea2-524153480001),
+version(1.0)
+]
+interface IOrTest
+{
+
+ import "obase.idl";
+
+ // Interface between OR test applications
+
+ error_status_t
+ TestBinding(
+ [in] handle_t binding);
+
+ error_status_t
+ WaitForNextTest(
+ [in] handle_t binding,
+ [in] unsigned long test);
+
+ error_status_t GetState(
+ [in] handle_t binding,
+ [in] long cOxids,
+ [in] long cOids,
+ [in] long cOxidInfos,
+ [out, size_is(cOxids)] OXID aOxids[],
+ [out, size_is(cOids)] OID aOids[],
+ [out, size_is(cOxidInfos)] OXID_INFO aOxidInfos[],
+ [out] DUALSTRINGARRAY **ppdaRemoteOrBindings
+ );
+}
diff --git a/private/ole32/dcomss/dcomtest/uor.rc b/private/ole32/dcomss/dcomtest/uor.rc
new file mode 100644
index 000000000..d0df89af9
--- /dev/null
+++ b/private/ole32/dcomss/dcomtest/uor.rc
@@ -0,0 +1,10 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "DCOM Testing Stuff"
+#define VER_INTERNALNAME_STR ""
+#define VER_ORIGINALFILENAME_STR ""
+
+#include "common.ver"
diff --git a/private/ole32/dcomss/dirs b/private/ole32/dcomss/dirs
new file mode 100644
index 000000000..f5cecbe68
--- /dev/null
+++ b/private/ole32/dcomss/dirs
@@ -0,0 +1,30 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=\
+ olescm \
+ objex \
+ wrapper
+
+OPTIONAL_DIRS=\
+ dcomtest
+
diff --git a/private/ole32/dcomss/objex/blist.cxx b/private/ole32/dcomss/objex/blist.cxx
new file mode 100644
index 000000000..d87f166fa
--- /dev/null
+++ b/private/ole32/dcomss/objex/blist.cxx
@@ -0,0 +1,136 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ BList.cxx
+
+Abstract:
+
+ Implements out of line methods on blists.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 95-03-02 Bits 'n pieces
+ MarioGo 95-09-07 Was blist.inl, change from template to generic class for PPC.
+--*/
+
+#include<or.hxx>
+
+ULONG
+CBList::Hash(PVOID p)
+{
+ ULONG t = (ULONG)p;
+
+ return ( ((t << 9) ^ (t >> 5) ^ (t >> 15)) % _ulmaxData);
+}
+
+ORSTATUS
+CBList::Insert(PVOID p)
+{
+ if ( _data == 0
+ || _ulcElements > (_ulmaxData - (_ulmaxData/8 + 1)))
+ {
+ // Table getting full, grow it.
+ // See Kenuth on linear probe hash performance as the table fills.
+
+ ULONG i, ulmaxOldData = _ulmaxData;
+ PVOID *ppOldData = _data;
+ _data = new PVOID[_ulmaxData * 2];
+
+ if (0 == _data)
+ {
+ _data = ppOldData;
+ return(OR_NOMEM);
+ }
+
+ _ulmaxData *= 2;
+ _ulcElements = 0;
+
+ OrMemorySet(_data, 0, _ulmaxData*4);
+
+ if (ppOldData)
+ {
+ for(i = 0; i < ulmaxOldData; i++)
+ {
+ if (ppOldData[i])
+ {
+ ORSTATUS status = Insert(ppOldData[i]);
+ ASSERT(status == OR_OK);
+ }
+ }
+
+ delete ppOldData;
+ }
+ }
+
+ register ULONG i = Hash(p);
+
+ while(_data[i])
+ {
+ i = (i + 1) % _ulmaxData;
+ }
+
+ _data[i] = p;
+ _ulcElements++;
+
+ return(OR_OK);
+}
+
+PVOID
+CBList::Remove(PVOID p)
+{
+ register ULONG i, hash;
+
+ if (_data)
+ {
+ i = hash = Hash(p);
+
+ if (_data[i] != p)
+ {
+ do
+ {
+ i = (i + 1) % _ulmaxData;
+ }
+ while(_data[i] != p && i != hash);
+ }
+
+ if (_data[i] == p)
+ {
+ _data[i] = 0;
+ _ulcElements--;
+ return(p);
+ }
+
+ ASSERT(i == hash);
+ }
+
+ return(0);
+}
+
+BOOL
+CBList::Member(PVOID p)
+{
+ int i, hash;
+
+ if (0 == _data)
+ return(FALSE);
+
+ i = hash = Hash(p);
+ if (_data[i] == p)
+ return(TRUE);
+
+ do
+ {
+ i = (i + 1) % _ulmaxData;
+ }
+ while(_data[i] != p && i != hash);
+
+ return(_data[i] == p);
+}
+
diff --git a/private/ole32/dcomss/objex/blist.hxx b/private/ole32/dcomss/objex/blist.hxx
new file mode 100644
index 000000000..e87af34f8
--- /dev/null
+++ b/private/ole32/dcomss/objex/blist.hxx
@@ -0,0 +1,127 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ BList.hxx
+
+Abstract:
+
+ Generic list of pointers class.
+
+ List elements are treated as four byte values.
+
+
+Note:
+ It is acceptable to insert the same pointer into the list
+ several times. Some usage depends on this.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 95-03-02 Bits 'n pieces
+ MarioGo 95-09-07 Changed from a template to a generic class for PPC.
+
+--*/
+
+#ifndef __BLIST_HXX
+#define __BLIST_HXX
+
+class CBListIterator;
+
+class CBList
+ {
+
+ friend class CBListIterator;
+
+ private:
+
+ ULONG Hash(PVOID p);
+
+ protected:
+
+ ULONG _ulmaxData;
+ ULONG _ulcElements;
+ PVOID *_data;
+
+ public:
+
+ CBList(USHORT cElement = 8)
+ {
+ // It's going to grow next time.
+ ASSERT(cElement > 1);
+ _ulmaxData = cElement/2;
+ _ulcElements = 0;
+ _data = 0;
+ }
+
+ ~CBList()
+ {
+ delete _data;
+ }
+
+ ORSTATUS
+ Insert(IN PVOID p);
+
+ PVOID
+ Remove(IN PVOID p);
+
+ BOOL
+ Member(IN PVOID p);
+
+ ULONG
+ Size()
+ {
+ return(_ulcElements);
+ }
+
+ };
+
+class CBListIterator
+ {
+ private:
+ CBList *_pblist;
+ LONG _next;
+
+ public:
+
+ CBListIterator(CBList *head) :
+ _pblist(head),
+ _next(-1)
+ { }
+
+ PVOID
+ Next()
+ {
+ if (_pblist->_data)
+ {
+ do
+ {
+ _next++;
+ }
+ while(_next < (LONG)_pblist->_ulmaxData && 0 == _pblist->_data[_next]);
+
+ if (_next < (LONG)_pblist->_ulmaxData)
+ {
+ ASSERT(_pblist->_data[_next] != 0);
+ return(_pblist->_data[_next]);
+ }
+ }
+ return(0);
+ }
+
+ void
+ Reset(CBList *head)
+ {
+ // Could just assign the new head if there is a use for that.
+ ASSERT(head == _pblist);
+ _next = -1;
+ }
+ };
+
+#endif / __BLIST_HXX
+
diff --git a/private/ole32/dcomss/objex/callid.cxx b/private/ole32/dcomss/objex/callid.cxx
new file mode 100644
index 000000000..3d291f477
--- /dev/null
+++ b/private/ole32/dcomss/objex/callid.cxx
@@ -0,0 +1,113 @@
+/*++
+
+Copyright (c) 1996 Microsoft Corporation
+
+Module Name:
+
+ callid.cxx
+
+Abstract:
+
+ Implements a cache of callids used for running down OIDs
+
+ This is almost twice as fast as UuidCreate() but that doesn't
+ mean much. UuidCreate takes 3 microseconds, this 1.4 (hit) or
+ 4.2 (miss) on a P90.
+
+ This codes real advantage would be on MP machines. But it is
+ not performance critical and is probably overkill.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 1/18/1996 Bits 'n pieces
+
+--*/
+
+#include <or.hxx>
+
+enum CacheState { CallidEmpty = 0,
+ CallidAllocated = 1,
+ CallidFree = -1 };
+
+struct CacheElement
+ {
+ CacheState _state;
+ UUID _callid;
+ };
+
+CacheElement CallidCache[4] = { CallidEmpty, {0},
+ CallidEmpty, {0},
+ CallidEmpty, {0},
+ CallidEmpty, {0} };
+
+
+INT
+AllocateCallId(
+ OUT UUID &Callid
+ )
+{
+ INT i;
+ LONG l;
+ RPC_STATUS status;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (CallidCache[i]._state != CallidAllocated)
+ {
+ l = InterlockedExchange((PLONG)&CallidCache[i]._state, CallidAllocated);
+
+ switch(l)
+ {
+ case CallidAllocated:
+ continue;
+
+ case CallidFree:
+ Callid = CallidCache[i]._callid;
+ return(i);
+
+ case CallidEmpty:
+ status = UuidCreate(&Callid);
+ VALIDATE((status, RPC_S_UUID_LOCAL_ONLY, RPC_S_OK, 0));
+ CallidCache[i]._callid = Callid;
+ return(i);
+ }
+ }
+ }
+ status = UuidCreate(&Callid);
+ VALIDATE((status, RPC_S_UUID_LOCAL_ONLY, RPC_S_OK, 0));
+ return(-1);
+ }
+
+
+void
+FreeCallId(
+ IN INT hint
+ )
+/*++
+
+Routine Description:
+
+ Frees a callid previously allcoated with AllocateCallId().
+
+Arguments:
+
+ hint - The hint value returned by the previous call to AllocateCallId().
+
+Return Value:
+
+ None
+
+--*/
+{
+ ASSERT(hint > -2 & hint < 4);
+
+ if (hint >= 0)
+ {
+ CallidCache[hint]._state = CallidFree;;
+ }
+}
+
diff --git a/private/ole32/dcomss/objex/callid.hxx b/private/ole32/dcomss/objex/callid.hxx
new file mode 100644
index 000000000..52406961c
--- /dev/null
+++ b/private/ole32/dcomss/objex/callid.hxx
@@ -0,0 +1,35 @@
+/*++
+
+Copyright (c) 1996 Microsoft Corporation
+
+Module Name:
+
+ callid.hxx
+
+Abstract:
+
+ Implements a cache of callids used for running down OIDs
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 1/18/1996 Bits 'n pieces
+
+--*/
+
+#ifndef __CALLID_HXX
+#define __CALLID_HXX
+
+INT AllocateCallId(
+ OUT UUID &Callid
+ );
+
+void FreeCallId(
+ IN INT hint
+ );
+
+#endif // __CALLID_HXX
+
diff --git a/private/ole32/dcomss/objex/coid.hxx b/private/ole32/dcomss/objex/coid.hxx
new file mode 100644
index 000000000..39c7491be
--- /dev/null
+++ b/private/ole32/dcomss/objex/coid.hxx
@@ -0,0 +1,138 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ coid.hxx
+
+Abstract:
+
+ CClientOid objects represent OIDs referenced by one of more processes on
+ this machine running as the same user.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 04-08-95 Bits 'n pieces
+ MarioGo 12-21-95 Rewrite - OIDs are not universally unique
+
+--*/
+
+#ifndef __COID_HXX
+#define __COID_HXX
+
+class CClientOid : public CId3TableElement
+/*++
+
+Class Description:
+
+ Each instance of this class represtents an object being
+ used on this or another machine by a one or more processes
+ owned by a particular local identity on this machine.
+
+Members:
+
+ _pOxid - Pointer to the OXID exporting this OID
+
+ _pSet - Pointer to the set which owns this OID
+
+ _cClients - The number of client processes actually
+ using this object.
+ Note: This value may only be changed with the
+ client lock held exclusively.
+ Note, also, that the set will not release its
+ reference unless this value is zero. The
+ effective reference count is _references
+ + _cClients.
+
+ REVIEW: We could write our own Reference
+ and Release methods. Then the client
+ set could delete (rather then Release()) the
+ oids directly.
+
+ _fIn:1 - A flag to indicate whether this object has
+ already been added to the remote set.
+
+--*/
+ {
+ private :
+
+ CClientOxid *_pOxid;
+ CClientSet *_pSet;
+ DWORD _cClients;
+ BOOL _fIn:1; // Is this OID in the remote set.
+
+ public :
+
+ CClientOid(ID &oid,
+ ID &mid,
+ CToken *pToken,
+ CClientOxid *pOxid,
+ CClientSet *pSet) :
+ CId3TableElement(oid, mid, pToken),
+ _pOxid(pOxid),
+ _pSet(pSet),
+ _fIn(FALSE),
+ _cClients(1)
+ {
+ // Token is held by the set which we reference,
+ // no need for us to reference it ourself.
+ _pOxid->Reference();
+ _pSet->Reference();
+ }
+
+ ~CClientOid();
+
+ BOOL In()
+ {
+ return(_fIn);
+ }
+
+ void Added()
+ {
+ ASSERT(gpClientLock->HeldExclusive());
+ _fIn = TRUE;
+ }
+
+ void Deleted()
+ {
+ ASSERT(gpClientLock->HeldExclusive());
+ _fIn = FALSE;
+ }
+
+ void ClientReference()
+ {
+ ASSERT(gpClientLock->HeldExclusive());
+ _cClients++;
+ if (_cClients == 1)
+ {
+ // Rereferenced.
+ _pSet->ObjectUpdate(this);
+ }
+ }
+
+ void
+ ClientRelease()
+ {
+ ASSERT(gpClientLock->HeldExclusive());
+ _cClients--;
+ if (_cClients == 0)
+ {
+ // Not referenced
+ _pSet->ObjectUpdate(this); // May release this.
+ }
+ // This pointer maybe invalid.
+ }
+
+ BOOL Out() {
+ return(_cClients == 0);
+ }
+
+ };
+
+#endif // __COID_HXX
+
diff --git a/private/ole32/dcomss/objex/coxid.hxx b/private/ole32/dcomss/objex/coxid.hxx
new file mode 100644
index 000000000..7cffafccb
--- /dev/null
+++ b/private/ole32/dcomss/objex/coxid.hxx
@@ -0,0 +1,123 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ COxid.hxx
+
+Abstract:
+
+ CClientOxid objects represent OXIDs which are in use by one or more clients
+ on this machine. These are referenced by
+ is pinging the server of the OXID. These objects maybe kept around
+ after the last client reference to improve performance.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-16-95 Bits 'n pieces
+ MarioGo 04-04-95 Split client and server.
+ MarioGo 01-06-96 Locally unique IDs
+
+--*/
+
+#ifndef __COXID_HXX
+#define __COXID_HXX
+
+class CClientOxid : public CId2TableElement
+/*++
+
+Class Description:
+
+ Represtents an OXID on some machine.
+
+Members:
+
+ _plist - Embedded CPList element used to store CClientOxids
+ in gpOxidPList.
+
+ _oxidInfo - Static information about this OXID and its
+ string + security bindings.
+
+ _pMid - Pointer to the machine ID for this OXID, we
+ own a reference.
+
+ _fLocal - non-Zero if this OXID is on this machine. Need only 1 bit.
+
+ _fApartment - non-Zero if this process is prefers apartment model.
+ Meaning less for non-local OXIDs. Need only 1 bit.
+
+--*/
+{
+ private:
+ CPListElement _plist;
+ OXID_INFO _oxidInfo;
+ CMid *_pMid;
+ USHORT _wProtseq; // 0 means local
+ USHORT _iStringBinding; // ~0 means unknown
+ BOOL _fApartment:8;
+
+ public:
+
+ CClientOxid(OXID &oxid,
+ CMid *pMid,
+ USHORT wProtseq,
+ BOOL fApartment) :
+ CId2TableElement(oxid, pMid->Id()),
+ _pMid(pMid), // We get a refernce.
+ _wProtseq(wProtseq),
+ _iStringBinding(0xFFFF),
+ _fApartment(fApartment)
+ {
+ _oxidInfo.psa = 0;
+ ASSERT(wProtseq != 0 || pMid->IsLocal());
+ }
+
+ ~CClientOxid()
+ {
+ ASSERT(gpClientLock->HeldExclusive());
+ gpClientOxidTable->Remove(this);
+ delete _oxidInfo.psa;
+ _pMid->Release();
+ }
+
+ ORSTATUS GetInfo(BOOL fApartment,
+ OXID_INFO *);
+
+ ORSTATUS UpdateInfo(OXID_INFO *);
+
+ CMid *GetMid() {
+ return(_pMid);
+ }
+
+ void Reference();
+
+ DWORD Release();
+
+ static CClientOxid *ContainingRecord(CListElement *ple) {
+ return CONTAINING_RECORD(ple, CClientOxid, _plist);
+ }
+
+ void Insert() {
+ gpClientOxidPList->Insert(&_plist);
+ }
+
+ CPListElement *Remove() {
+ return(gpClientOxidPList->Remove(&_plist));
+ }
+
+ void Reset() {
+ gpClientOxidPList->Reset(&_plist);
+ }
+
+ BOOL IsLocal() {
+ return(_wProtseq == 0);
+ }
+};
+
+#endif // __COXID_HXX
+
diff --git a/private/ole32/dcomss/objex/cset.hxx b/private/ole32/dcomss/objex/cset.hxx
new file mode 100644
index 000000000..74d287684
--- /dev/null
+++ b/private/ole32/dcomss/objex/cset.hxx
@@ -0,0 +1,148 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ csets.hxx
+
+Abstract:
+
+ CClientSet objects represent sets of OIDs which are referenced by
+ one or more local client processes.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 04-08-95 Bits 'n pieces
+ MarioGo 12-28-95 Locally unique ids
+
+--*/
+
+#ifndef __CSET_HXX
+#define __CSET_HXX
+
+class CClientSet : public CId2TableElement
+/*++
+
+Class Description:
+
+ Represents a set of OIDs in use by a local user on a remote
+ (or local) machine. Instances are indexed by machine ID
+ and the a pointer to the users CToken objec.
+
+Memebers:
+
+ _setid - A uuid allocated by the server during the first
+ update ping. Uniqueness is not required by the client.
+
+ _lastping - Time of last successful ping.
+
+ _sequence - The sequence number of the last successful ping.
+
+ // _factor - Power of two multiplier for ping period. Not implemented.
+
+ _fChange - The set of OIDs has changed since the last update ping.
+
+ _hServer - current saved binding handle to the server.
+
+ _pMid - Pointer to the CMid instance for this user. We own a reference.
+
+ _blistOids - A CBList instance containing pointers to all the OIDs
+ owned by this set. The set holds a reference on each.
+
+ _plist - CPListElement instance used by the worker thread to maintain
+ sets in time sorted order.
+
+--*/
+ {
+ private:
+
+ SETID _setid;
+ CTime _lastping;
+ CMid *_pMid;
+ RPC_BINDING_HANDLE _hServer;
+ USHORT _iBinding;
+ USHORT _sequence;
+ USHORT _cFailedPings;
+ USHORT _fChange:1;
+ USHORT _fSecure:1;
+ CBList _blistOids;
+ CPListElement _plist;
+
+ public:
+
+ CClientSet(
+ IN CMid *pMid,
+ IN CToken *pToken
+ ) :
+ CId2TableElement(pMid->Id(), (ID)pToken),
+ _blistOids(16),
+ _sequence(0),
+ _cFailedPings(0),
+ _setid(0),
+ _hServer(0),
+ _fChange(TRUE),
+ _fSecure(TRUE)
+ {
+ // Client lock held shared.
+ pToken->Reference();
+ _pMid = pMid;
+ _pMid->Reference();
+ }
+
+ CClientSet::~CClientSet()
+ {
+ ASSERT(gpClientLock->HeldExclusive());
+ ASSERT(_blistOids.Size() == 0);
+
+ // REVIEW: make sure the linker throws out all copies of this except
+ // the inline versions. Otherwise, make this out-of-line and rethink
+ // other inline d'tors.
+
+ _pMid->Release();
+
+ CToken *pToken = (CToken *)Id2();
+
+ pToken->Release();
+
+ gpClientSetTable->Remove(this);
+
+ }
+
+ ORSTATUS RegisterObject(CClientOid *);
+
+ void ObjectUpdate(CClientOid *pOid)
+ {
+ ASSERT(gpClientLock->HeldExclusive());
+
+ _fChange = TRUE;
+ }
+
+ ORSTATUS PingServer();
+
+ void NextPing(CTime &ctimePing)
+ {
+ ctimePing = _lastping;
+ ctimePing += BasePingInterval;
+ }
+
+ static CClientSet *ContainingRecord(CListElement *ple) {
+ return CONTAINING_RECORD(ple, CClientSet, _plist);
+ }
+
+ void Insert() {
+ gpClientSetPList->Insert(&_plist);
+ }
+
+ CPListElement * Remove() {
+ return(gpClientSetPList->Remove(&_plist));
+ }
+
+ };
+
+#endif // __CSET_HXX
+
diff --git a/private/ole32/dcomss/objex/daytona/makefile b/private/ole32/dcomss/objex/daytona/makefile
new file mode 100644
index 000000000..51f351a0e
--- /dev/null
+++ b/private/ole32/dcomss/objex/daytona/makefile
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS LINE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/dcomss/objex/daytona/sources b/private/ole32/dcomss/objex/daytona/sources
new file mode 100644
index 000000000..ba96b613d
--- /dev/null
+++ b/private/ole32/dcomss/objex/daytona/sources
@@ -0,0 +1,45 @@
+!IF 0
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Revision History:
+
+!ENDIF
+
+!include ..\sources.inc
+
+TARGETPATH=..\..\lib\daytona
+TARGETLIBS=
+
+PRECOMPILED_INCLUDE=..\or.hxx
+
+SOURCES= \
+ ..\locks.cxx \
+ ..\misc.cxx \
+ ..\callid.cxx \
+ ..\string.cxx \
+ ..\plist.cxx \
+ ..\blist.cxx \
+ ..\gentable.cxx \
+ ..\mid.cxx \
+ ..\token.cxx \
+ ..\process.cxx \
+ ..\objex.cxx \
+ ..\orclnt.cxx \
+ ..\orsvr.cxx \
+ ..\worker.cxx \
+ ..\manager.cxx
+
+
diff --git a/private/ole32/dcomss/objex/dirs b/private/ole32/dcomss/objex/dirs
new file mode 100644
index 000000000..6decee351
--- /dev/null
+++ b/private/ole32/dcomss/objex/dirs
@@ -0,0 +1,28 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=
+
+OPTIONAL_DIRS= \
+ daytona \
+ \
+
diff --git a/private/ole32/dcomss/objex/gentable.cxx b/private/ole32/dcomss/objex/gentable.cxx
new file mode 100644
index 000000000..58e3b5d47
--- /dev/null
+++ b/private/ole32/dcomss/objex/gentable.cxx
@@ -0,0 +1,429 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Table.cxx
+
+Abstract:
+
+ Implementation of the CHashTable and CTableElement.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-15-95 Bits 'n pieces
+ MarioGo 12-18-95 Changed from UUID to generic object keys
+
+--*/
+
+#include<or.hxx>
+
+CTableElement *
+CTableElement::RemoveMatching(
+ IN CTableKey &tk,
+ OUT CTableElement **ppRemoved)
+/*++
+
+Routine Description:
+
+ Helper function used to remove an element from a
+ bucket in the hash table.
+
+Arguments:
+
+ tk - Key to find the element being removed.
+
+ ppRemoved - Contains the element removed or NULL upon return.
+
+Return Value:
+
+ Pointer to the remaining elements in the list if any. Use
+ to replace the current pointer in the bucket.
+
+--*/
+{
+ CTableElement *pcurrent = this;
+ CTableElement *psaved = 0;
+ CTableElement *pfirst = this;
+
+ while(pcurrent)
+ {
+ if (pcurrent->Compare(tk))
+ {
+ *ppRemoved = pcurrent;
+ if (0 != psaved)
+ {
+ psaved->_pnext = pcurrent->_pnext;
+ pcurrent->_pnext = 0;
+ return(pfirst);
+ }
+ else
+ {
+ // removing the first element in the list
+ ASSERT(pcurrent == pfirst);
+ psaved = pcurrent->_pnext;
+ pcurrent->_pnext = 0;
+ return(psaved);
+ }
+ }
+
+ psaved = pcurrent;
+ pcurrent = pcurrent->_pnext;
+ }
+
+ *ppRemoved = 0;
+ return(pfirst);
+}
+
+
+CTableElement *
+CTableElement::RemoveMatching(
+ IN CTableElement *pte,
+ OUT CTableElement **ppRemoved)
+/*++
+
+Routine Description:
+
+ Helper function used to remove an element from a bucket in the hash table.
+
+Arguments:
+
+ pte - Element to be removed, compared by pointer value.
+
+ ppRemoved - Contains the element removed or NULL upon return.
+
+Return Value:
+
+ Pointer to the remaining elements in the list if any. Use
+ to replace the current pointer in the bucket.
+
+--*/
+{
+ CTableElement *pcurrent = this;
+ CTableElement *psaved = 0;
+ CTableElement *pfirst = this;
+
+ while(pcurrent)
+ {
+ if (pcurrent == pte)
+ {
+ *ppRemoved = pcurrent;
+ if (0 != psaved)
+ {
+ psaved->_pnext = pcurrent->_pnext;
+ pcurrent->_pnext = 0;
+ return(pfirst);
+ }
+ else
+ {
+ // removing the first element in the list
+ ASSERT(pcurrent == pfirst);
+ psaved = pcurrent->_pnext;
+ pcurrent->_pnext = 0;
+ return(psaved);
+ }
+ }
+
+ psaved = pcurrent;
+ pcurrent = pcurrent->_pnext;
+ }
+
+ *ppRemoved = 0;
+ return(pfirst);
+}
+
+CHashTable::CHashTable(ORSTATUS &status, UINT start_size)
+{
+ _cBuckets = start_size;
+ _cElements = 0;
+ _last = 0;
+
+ _buckets = new CTableElement *[start_size];
+
+ if (0 == _buckets)
+ {
+ status = OR_NOMEM;
+ return;
+ }
+
+ for(UINT i = 0; i < _cBuckets; i++)
+ {
+ _buckets[i] = NULL;
+ }
+
+ status = OR_OK;
+}
+
+
+CHashTable::~CHashTable()
+{
+#if 0
+#if DBG
+ for(UINT i = 0; i < _cBuckets; i++)
+ ASSERT(_buckets[i] == 0);
+#endif
+ delete _buckets;
+#endif
+ ASSERT(0); // D'tor unused 12/95
+}
+
+CTableElement *
+CHashTable::Lookup(
+ IN CTableKey &id
+ )
+{
+ DWORD hash = id.Hash();
+ CTableElement *it;
+
+ it = _buckets[hash % _cBuckets];
+
+ while(it)
+ {
+ if (it->Compare(id))
+ {
+ return(it);
+ }
+
+ it = it->Next();
+ }
+
+ return(0);
+}
+
+void
+CHashTable::Add(
+ IN CTableElement *pElement
+ )
+{
+ DWORD hash = pElement->Hash();
+
+ hash %= _cBuckets;
+
+ _buckets[hash] = _buckets[hash]->Insert(pElement);
+
+ _cElements++;
+
+ if (_cElements > _cBuckets)
+ {
+ // Try to grow the table. If the allocation fails no need to worry,
+ // everything still works but might be a bit slower.
+
+ CTableElement **ppte = new CTableElement *[_cBuckets * 2];
+
+ if (ppte)
+ {
+ UINT i, uiBucketsOld = _cBuckets;
+ CTableElement *pteT1, *pteT2;
+ CTableElement **ppteOld = _buckets;
+
+ OrDbgDetailPrint(("OR: Growing table: %p\n", this));
+
+ // Change to the larger array of buckets.
+ _cBuckets *= 2;
+ for(i = 0; i < _cBuckets; i++)
+ {
+ ppte[i] = NULL;
+ }
+ _buckets = ppte;
+
+ // Move every element from the old table into the large table.
+ for(i = 0; i < uiBucketsOld; i++)
+ {
+ pteT1 = ppteOld[i];
+
+ while(pteT1)
+ {
+ pteT2 = pteT1->Next();
+ pteT1->Unlink();
+
+ // Same as calling Add() but don't update _cElements.
+ hash = pteT1->Hash();
+ hash %= _cBuckets;
+ _buckets[hash] = _buckets[hash]->Insert(pteT1);
+
+ pteT1 = pteT2;
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+CTableElement *
+CHashTable::Remove(
+ IN CTableKey &id
+ )
+/*++
+
+Routine Description:
+
+ Looks up and removes an element from the table.
+
+Arguments:
+
+ id - The key to match the element to be removed
+
+Return Value:
+
+ NULL - The element was not in the table
+
+ non-NULL - A pointer to the element which was removed.
+
+--*/
+
+{
+ DWORD hash = id.Hash();
+ CTableElement *pte;
+
+ hash %= _cBuckets;
+
+ _buckets[hash] = (_buckets[hash])->RemoveMatching(id, &pte);
+
+ if (pte)
+ {
+ _cElements--;
+
+ if (_last == pte)
+ {
+ _last = _buckets[hash];
+ }
+ }
+
+ return pte;
+}
+
+void
+CHashTable::Remove(
+ IN CTableElement *pElement
+ )
+/*++
+
+Routine Description:
+
+ Used to remove an element from the table given a pointer to it.
+
+Arguments:
+
+ pElement - the element to be removed. This pointer value,
+ keys are not compared.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ DWORD hash = pElement->Hash();
+ CTableElement *pte;
+
+ hash %= _cBuckets;
+
+ _buckets[hash] = (_buckets[hash])->RemoveMatching(pElement, &pte);
+
+ if (pte)
+ {
+ ASSERT(pte == pElement);
+
+ _cElements--;
+
+ if (_last == pElement)
+ {
+ _last = _buckets[hash];
+ }
+ }
+
+ return;
+}
+
+CTableElement *
+CHashTable::Another(
+ )
+/*++
+
+Routine Description:
+
+ Returns an element from the table. Usually this will be
+ element found after the element last returned from this
+ function. It may, due to races not solved here, repeat
+ an element or skip an element.
+
+ Races occur when accessing the "_last" memeber; this
+ function is called while holding a shared lock. (More
+ then one thread may call it at a time.)
+
+ This isn't as bad as it sounds. _last can only
+ be set to null in Remove() which requires exclusive
+ access.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ NULL or a pointer to an element in the table.
+
+--*/
+
+{
+ CTableElement *panother;
+ int i, end;
+
+ if (_cElements == 0)
+ {
+ return(0);
+ }
+
+ if (_last)
+ {
+ if (panother = _last->Next())
+ {
+ if (panother)
+ {
+ _last = panother;
+ return(panother);
+ }
+ }
+
+ ASSERT(panother == 0);
+
+ // no next, start looking from just after last's hash.
+
+ i = _last->Hash();
+
+ // Exersise for the reader (x + y) mod n == ( x mod n + y mod n ) mod n
+
+ end = i = (i + 1) % _cBuckets;
+ }
+ else
+ {
+ // no last, start from the start.
+ i = 0;
+ end = _cBuckets - 1;
+ }
+
+ do
+ {
+ if (_buckets[i])
+ {
+ panother = _buckets[i];
+ ASSERT(panother);
+ _last = panother;
+ return(panother);
+ }
+ i = (i + 1) % _cBuckets;
+ }
+ while (i != end);
+
+ // Doesn't mean the table is empty, just that we didn't find
+ // another element. These are not the same thing.
+ return(0);
+}
+
diff --git a/private/ole32/dcomss/objex/gentable.hxx b/private/ole32/dcomss/objex/gentable.hxx
new file mode 100644
index 000000000..4a14402d7
--- /dev/null
+++ b/private/ole32/dcomss/objex/gentable.hxx
@@ -0,0 +1,116 @@
+
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ GenTable.hxx
+
+Abstract:
+
+ Generic wrapper for a bucket hash class.
+ Used for ID, ID[2], ID[3] and string index tables.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 12-13-95 Pulled from uuid index hash table
+ MarioGo 12-18-95 Changed to use generic keys.
+
+--*/
+
+#ifndef __GENERIC_TABLE_HXX
+#define __GENERIC_TABLE_HXX
+
+class CTableKey {
+
+ public:
+
+ virtual DWORD Hash() = 0;
+ virtual BOOL Compare(CTableKey &tk) = 0;
+};
+
+class CHashTable;
+
+class CTableElement : public CReferencedObject
+{
+ friend class CHashTable;
+
+ public:
+
+ CTableElement() : _pnext(0) {}
+ ~CTableElement() { ASSERT(_pnext == 0); }
+
+ virtual DWORD Hash() = 0;
+
+ virtual BOOL Compare(CTableKey &tk) = 0;
+
+ virtual BOOL Compare(CONST CTableElement *element) = 0;
+
+ protected:
+
+ void
+ Unlink() {
+ _pnext = 0;
+ }
+
+ CTableElement *
+ Next() {
+ return(_pnext);
+ }
+
+ CTableElement *
+ Insert(IN CTableElement *pElement) {
+ // Can be called on a null this pointer.
+ pElement->_pnext = this;
+ return(pElement);
+ }
+
+ CTableElement *
+ RemoveMatching(CTableKey &tkRemove,
+ CTableElement **ppRemoved);
+
+ CTableElement *
+ RemoveMatching(CTableElement *pRemove,
+ CTableElement **ppRemoved
+ );
+
+ private:
+
+ CTableElement *_pnext;
+};
+
+typedef CTableElement *pCTableElement;
+
+class CHashTable
+ {
+ public:
+
+ CHashTable(ORSTATUS &status, UINT start_size = 32 );
+
+ ~CHashTable();
+
+ void Add(pCTableElement element);
+ CTableElement *Lookup(CTableKey &tk);
+ CTableElement *Remove(CTableKey &tk);
+ void Remove(CTableElement *pElement);
+ CTableElement *Another();
+ DWORD Size() { return(_cElements); }
+
+ private:
+
+ CTableElement *
+ RemoveHelper(DWORD hash);
+
+ DWORD _cBuckets;
+ DWORD _cElements;
+ CTableElement **_buckets;
+ CTableElement *_last;
+ };
+
+#endif // __GENERIC_TABLE_HXX
+
diff --git a/private/ole32/dcomss/objex/idtable.hxx b/private/ole32/dcomss/objex/idtable.hxx
new file mode 100644
index 000000000..00e6bb401
--- /dev/null
+++ b/private/ole32/dcomss/objex/idtable.hxx
@@ -0,0 +1,208 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ IdTable.hxx
+
+Abstract:
+
+ Generic tables indexed by 1, 2 or 2.5 64bit IDs.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 12-13-95 Bits 'n pieces
+
+--*/
+
+#ifndef __ID_TABLE_HXX
+#define __ID_TABLE_HXX
+
+class CIdTableElement;
+class CId2TableElement;
+class CId3TableElement;
+
+class CIdKey : public CTableKey
+{
+ friend CIdTableElement;
+
+ public:
+
+ CIdKey(const ID id) : _id(id) { }
+
+ virtual DWORD
+ Hash() {
+ return((DWORD)_id ^ (*((DWORD *)&_id + 1)));
+ }
+
+ virtual BOOL
+ Compare(CTableKey &tk) {
+ CIdKey &idk = (CIdKey &)tk;
+ return(idk._id == _id);
+ }
+
+ protected:
+ ID _id;
+};
+
+class CId2Key : public CIdKey
+{
+ friend CId2TableElement;
+
+ public:
+
+ CId2Key(const ID id, const ID id2) : CIdKey(id), _id2(id2) { }
+
+ virtual DWORD
+ Hash() {
+ return( (DWORD)_id2 ^ (*((DWORD *)&_id2 + 1))
+ ^ (DWORD)_id ^ (*((DWORD *)&_id + 1)) );
+ }
+
+ virtual BOOL
+ Compare(CTableKey &tk) {
+ CId2Key &idk = (CId2Key &)tk;
+ return(idk._id2 == _id2
+ && this->CIdKey::Compare(tk));
+ }
+
+ protected:
+
+ ID _id2;
+};
+
+class CId3Key : public CId2Key
+{
+ friend CId3TableElement;
+
+ public:
+
+ CId3Key(const ID id, const ID id2, const PVOID id3) : CId2Key(id,id2), _id3(id3) { }
+
+ virtual DWORD
+ Hash() {
+ return( (DWORD)_id3
+ ^ (DWORD)_id2 ^ (*((DWORD *)&_id2 + 1))
+ ^ (DWORD)_id ^ (*((DWORD *)&_id + 1)) );
+ }
+
+ virtual BOOL
+ Compare(CTableKey &tk) {
+ CId3Key &idk = (CId3Key &)tk;
+ return(idk._id3 == _id3
+ && this->CId2Key::Compare(tk));
+ }
+
+ protected:
+
+ PVOID _id3;
+};
+
+class CIdTableElement : public CTableElement
+{
+ public:
+ CIdTableElement(ID id) : _id(id) {}
+
+ ID
+ Id() {
+ return(_id);
+ }
+
+ virtual DWORD
+ Hash() {
+ return(((DWORD)_id) ^ (*((DWORD *)&_id + 1)));
+ }
+
+ virtual BOOL
+ Compare(CTableKey &tk) {
+ CIdKey &idk = (CIdKey &)tk;
+ return( _id == idk._id );
+ }
+
+ virtual BOOL
+ Compare(CONST CTableElement *pElement) {
+ CIdTableElement *pidte = (CIdTableElement *)pElement;
+ return(_id == pidte->_id);
+ }
+
+ private:
+ ID _id;
+};
+
+class CId2TableElement : public CIdTableElement
+{
+ public:
+
+ CId2TableElement(ID id, ID id2) : CIdTableElement(id), _id2(id2) {}
+
+ ID
+ Id2() {
+ return(_id2);
+ }
+
+ virtual DWORD
+ Hash() {
+ return( this->CIdTableElement::Hash()
+ ^ ((DWORD)_id2) ^ (*((DWORD *)&_id2 + 1)) );
+ }
+
+ virtual BOOL
+ Compare(CTableKey &tk) {
+ CId2Key &idk = (CId2Key &)tk;
+ return( _id2 == idk._id2
+ && this->CIdTableElement::Compare(tk));
+ }
+
+ virtual BOOL
+ Compare(CONST CTableElement *pElement) {
+ CId2TableElement *pidte = (CId2TableElement *)pElement;
+ return(_id2 == pidte->_id2
+ && this->CIdTableElement::Compare(pElement));
+ }
+
+ private:
+ ID _id2;
+};
+
+class CId3TableElement : public CId2TableElement
+{
+ public:
+
+ CId3TableElement(ID id, ID id2, PVOID id3) : CId2TableElement(id, id2), _id3(id3) {}
+
+ PVOID
+ Id3() {
+ return(_id3);
+ }
+
+ virtual DWORD
+ Hash() {
+ return( this->CId2TableElement::Hash()
+ ^ (DWORD)_id3);
+ }
+
+ virtual BOOL
+ Compare(CTableKey &tk) {
+ CId3Key &idk = (CId3Key &)tk;
+ return( _id3 == idk._id3
+ && this->CId2TableElement::Compare(tk));
+ }
+
+ virtual BOOL
+ Compare(CONST CTableElement *pElement) {
+ CId3TableElement *pidte = (CId3TableElement *)pElement;
+ return(_id3 == pidte->_id3
+ && this->CId2TableElement::Compare(pElement));
+ }
+
+ private:
+ PVOID _id3;
+};
+
+#endif
+
diff --git a/private/ole32/dcomss/objex/list.hxx b/private/ole32/dcomss/objex/list.hxx
new file mode 100644
index 000000000..36e8f7fbf
--- /dev/null
+++ b/private/ole32/dcomss/objex/list.hxx
@@ -0,0 +1,180 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ List.hxx
+
+Abstract:
+
+ Base class for an embeddable doubly linked list class.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 12/20/1995 Broke plist.hxx into two parts
+
+--*/
+
+#ifndef __LIST_HXX
+#define __LIST_HXX
+
+class CList;
+
+class CListElement
+{
+ friend CList;
+
+ public:
+
+ CListElement() :
+#if DBG
+ fInList(FALSE),
+#endif
+ _flink(0), _blink(0) { }
+
+ ~CListElement() {
+ // PERF: Make sure this disappears on retail
+ ASSERT(NotInList());
+ }
+
+ CListElement *Next() {
+ return(_flink);
+ }
+
+ CListElement *Previous() {
+ return(_blink);
+ }
+
+ private:
+ CListElement *_flink;
+ CListElement *_blink;
+
+#if DBG
+ BOOL fInList;
+
+ public:
+ void Inserted() { fInList = TRUE; }
+ void Removed() { fInList = FALSE; }
+ BOOL NotInList() { return(fInList == FALSE); }
+ BOOL InList() { return(fInList == TRUE); }
+#endif
+
+ protected:
+
+ void
+ Insert(
+ IN CListElement *p
+ )
+ {
+ // Insert new element (p) after this element.
+ ASSERT(this);
+ ASSERT(p->_flink == 0 && p->_blink == 0);
+
+ if (_flink)
+ {
+ ASSERT(_flink->_blink == this);
+ _flink->_blink = p;
+ }
+ p->_flink = _flink;
+ p->_blink = this;
+ _flink = p;
+ }
+
+ void
+ Unlink()
+ {
+ if (_flink)
+ {
+ ASSERT(_flink->_blink == this);
+ _flink->_blink = _blink;
+ }
+ if (_blink)
+ {
+ ASSERT(_blink->_flink == this);
+ _blink->_flink = _flink;
+ _blink = 0;
+ }
+ _flink = 0;
+ }
+};
+
+class CList
+{
+ private:
+
+ CListElement *_first;
+ CListElement *_last;
+
+ public:
+
+ CList() : _first(0), _last(0) { }
+
+ ~CList() {
+ ASSERT((_first == 0) && (_last == 0));
+ }
+
+ void
+ Insert( IN CListElement *p ) {
+ if (_last)
+ {
+ _last->Insert(p);
+ _last = p;
+ }
+ else
+ {
+ ASSERT(0 == _first);
+ _first = _last = p;
+ }
+#if DBG
+ p->Inserted();
+#endif
+ }
+
+ CListElement *
+ Remove(CListElement *p) {
+ if (0 == p)
+ {
+ return(0);
+ }
+
+ if (p == _first)
+ {
+ _first = _first->Next();
+ ASSERT(p != _first);
+ }
+
+ if (p == _last)
+ {
+ _last = _last->Previous();
+ ASSERT(p != _last);
+ }
+
+ ASSERT((_first == 0) ? (_last == 0) : 1);
+ ASSERT((_last == 0) ? (_first == 0) : 1);
+
+ // Take the element out of the list.
+ p->Unlink();
+
+ #if DBG
+ p->Removed();
+ #endif
+
+ return(p);
+ }
+
+ CListElement *First() {
+ return(_first);
+ }
+
+ CListElement *Last() {
+ return(_last);
+ }
+};
+
+#endif
+
diff --git a/private/ole32/dcomss/objex/locks.cxx b/private/ole32/dcomss/objex/locks.cxx
new file mode 100644
index 000000000..d6eaf5d98
--- /dev/null
+++ b/private/ole32/dcomss/objex/locks.cxx
@@ -0,0 +1,148 @@
+/*++
+
+Copyright (c) 1995-1996 Microsoft Corporation
+
+Module Name:
+
+ Locks.cxx
+
+Abstract:
+
+ Out of line methods for some of the syncronization classes
+ defined in locks.hxx.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 03-14-95 Moved from misc.cxx.
+ MarioGo 01-27-96 Changed from busy (Sleep(0)) wait to event
+
+--*/
+
+#include <or.hxx>
+
+//
+// CShareLock methods
+//
+
+#ifdef NTENV
+// extern DWORD GetCurrentThreadId(void);
+#define GetCurrentThreadId() ((DWORD)NtCurrentTeb()->ClientId.UniqueThread)
+#endif
+
+CSharedLock::CSharedLock(ORSTATUS &status)
+{
+ exclusive_owner = 0;
+ hevent = 0;
+ status = RtlInitializeCriticalSection(&lock);
+ if (NT_SUCCESS(status))
+ {
+ hevent = CreateEvent(0, FALSE, FALSE, 0);
+ if (0 == hevent)
+ {
+ status = OR_NOMEM;
+ }
+ }
+}
+
+CSharedLock::~CSharedLock()
+{
+ // Cannot be deleted if it failed to initialize
+ NTSTATUS status = RtlDeleteCriticalSection(&lock);
+ ASSERT(NT_SUCCESS(status));
+ if (hevent) CloseHandle(hevent);
+}
+
+void
+CSharedLock::LockShared()
+{
+ readers++;
+
+ if (writers)
+ {
+ if ((readers--) == 0)
+ {
+ SetEvent(hevent);
+ }
+
+ EnterCriticalSection(&lock);
+ readers++;
+ LeaveCriticalSection(&lock);
+ }
+
+ exclusive_owner = 0;
+}
+
+void
+CSharedLock::UnlockShared(void)
+{
+ ASSERT((LONG)readers > 0);
+ ASSERT(exclusive_owner == 0);
+
+ if ( (readers--) == 0 && writers)
+ {
+ SetEvent(hevent);
+ }
+}
+
+void
+CSharedLock::LockExclusive(void)
+{
+ EnterCriticalSection(&lock);
+ writers++;
+ while(readers)
+ {
+ WaitForSingleObject(hevent, INFINITE);
+ }
+ ASSERT(writers);
+ exclusive_owner = GetCurrentThreadId();
+}
+
+void
+CSharedLock::UnlockExclusive(void)
+{
+ ASSERT(HeldExclusive());
+ ASSERT(writers);
+ writers--;
+ exclusive_owner = 0;
+ LeaveCriticalSection(&lock);
+}
+
+void
+CSharedLock::Unlock()
+{
+ // Either the lock is held exclusively by this thread or the thread
+ // has a shared lock. (or the caller has a bug).
+
+ if (HeldExclusive())
+ {
+ UnlockExclusive();
+ }
+ else
+ {
+ UnlockShared();
+ }
+}
+
+void
+CSharedLock::ConvertToExclusive(void)
+{
+ ASSERT((LONG)readers > 0);
+ ASSERT(exclusive_owner == 0);
+
+ if ( (readers--) == 0 && writers )
+ SetEvent(hevent);
+
+ EnterCriticalSection(&lock);
+ writers++;
+ while(readers)
+ {
+ WaitForSingleObject(hevent, INFINITE);
+ }
+ ASSERT(writers);
+ exclusive_owner = GetCurrentThreadId();
+}
+
diff --git a/private/ole32/dcomss/objex/locks.hxx b/private/ole32/dcomss/objex/locks.hxx
new file mode 100644
index 000000000..456e537a8
--- /dev/null
+++ b/private/ole32/dcomss/objex/locks.hxx
@@ -0,0 +1,137 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Locks.hxx
+
+Abstract:
+
+ Several small class (CInterlockedInteger, CMutexLock and CSharedLock
+ which are wrappers for Win32 APIs.
+
+ CInterlockedInteger is a simple wrapper for win32 interlockedm integer APis.
+
+ CMutexLock is a wrapper designed to automatically constructed around
+ win32 critical sections. They never forget to release the lock.
+
+ CSharedLocks are similar to NT resources, they allow shared (multiple readers)
+ and exclusive (single writer) access to the resource. They are different
+ in the following ways:
+ CSharedLocks don't starve exclusive threads.
+ Exclusive threads spin (Sleep(0)) while waiting for readers to finish.
+ Exclusive threads will deadlock trying to gain shared access.
+ Exclusive threads trying to recursively take the lock may deadlock.
+ They always block if they can't get access.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 03-14-95 Moved from misc.?xx
+
+--*/
+
+#ifndef __LOCKS_HXX
+#define __LOCKS_HXX
+
+class CInterlockedInteger
+ {
+ private:
+ LONG i;
+
+ public:
+
+ CInterlockedInteger(LONG i = 0) : i(i) {}
+
+ LONG operator++(int)
+ {
+ return(InterlockedIncrement(&i));
+ }
+
+ LONG operator--(int)
+ {
+ return(InterlockedDecrement(&i));
+ }
+
+ operator LONG()
+ {
+ return(i);
+ }
+ };
+
+class CMutexLock
+ {
+ private:
+
+ CRITICAL_SECTION *pCurrentLock;
+ int owned;
+
+ public:
+
+ CMutexLock(CRITICAL_SECTION *pLock) : owned(0), pCurrentLock(pLock) {
+ Lock();
+ }
+
+ ~CMutexLock() {
+ if (owned)
+ Unlock();
+#if DBG
+ pCurrentLock = 0;
+#endif
+ }
+
+ void Lock()
+ {
+ ASSERT(!owned);
+ EnterCriticalSection(pCurrentLock);
+ owned = 1;
+ }
+
+ void Unlock()
+ {
+ ASSERT(owned);
+ LeaveCriticalSection(pCurrentLock);
+ owned = 0;
+ }
+ };
+
+
+class CSharedLock
+ {
+ private:
+ CRITICAL_SECTION lock;
+ HANDLE hevent;
+ CInterlockedInteger readers;
+ CInterlockedInteger writers;
+ DWORD exclusive_owner;
+
+ public:
+
+ CSharedLock(ORSTATUS &status);
+
+ ~CSharedLock();
+
+ void LockShared(void);
+
+ void UnlockShared(void);
+
+ void LockExclusive(void);
+
+ void UnlockExclusive(void);
+
+ void Unlock(void);
+
+ void ConvertToExclusive(void);
+
+ BOOL HeldExclusive()
+ {
+ return(exclusive_owner == GetCurrentThreadId());
+ }
+ };
+
+#endif // __LOCKS_HXX
+
diff --git a/private/ole32/dcomss/objex/manager.cxx b/private/ole32/dcomss/objex/manager.cxx
new file mode 100644
index 000000000..0edefdf31
--- /dev/null
+++ b/private/ole32/dcomss/objex/manager.cxx
@@ -0,0 +1,1877 @@
+/*++
+
+Copyright (c) 1995-1996 Microsoft Corporation
+
+Module Name:
+
+ Manager.cxx
+
+Abstract:
+
+ Stub/OR interface
+
+Author:
+
+ Mario Goertzel [mariogo] Feb-02-1995
+
+Revision Hist:
+
+ MarioGo 02-10-95 Bits 'n pieces
+ MarioGo 01-31-96 New local and remote interfaces
+
+--*/
+
+#include <or.hxx>
+
+//
+// Helper routines
+//
+
+void CheckRemoteSecurity(
+ IN handle_t hClient,
+ IN CToken *pToken
+ )
+/*++
+
+Routine Description:
+
+ Checks that a remote call is being made by the correct client.
+
+Arguments:
+
+ hClient - RPC binding handle (SCALL/SCONN) of the call in progress.
+ NULL indicates that the call is being made internally and is ok.
+
+ pToken - Token to check access against. If NULL, access is okay.
+
+Return Value:
+
+ Raises OR_NOACCESS on failure.
+
+--*/
+
+{
+ if (hClient && pToken)
+ {
+ // BUGBUG
+ ASSERT(0);
+ }
+
+ return;
+}
+
+void
+CheckLocalSecurity(
+ IN handle_t hClient,
+ IN CProcess *pProcess
+ )
+/*++
+
+Routine Description:
+
+ Checks that a client is correctly calling one of the local
+ (lclor.idl) methods.
+
+Arguments:
+
+ hClient - Rpc binding handle (SCALL) of the call in progress. If NULL,
+ then the call is being made internally and is okay.
+
+ pProcess - Context handle passed in by the client. Must not be zero.
+
+Return Value:
+
+ Raises OR_NOACCESS if not okay.
+
+--*/
+
+{
+ UINT type;
+
+ if ( (0 != hClient)
+ && ( (I_RpcBindingInqTransportType(hClient, &type) != RPC_S_OK)
+ || (type != TRANSPORT_TYPE_LPC)
+ || (0 == pProcess) ) )
+ {
+ RpcRaiseException(OR_NOACCESS);
+ }
+
+ // pProcess is not needed here. On LRPC the RPC runtime
+ // prevents a different local clients from using a context handle
+ // of another client.
+
+ return;
+}
+
+//
+// Manager (server-side) calls to the local OR interface. lclor.idl
+//
+
+error_status_t
+_Connect(
+ IN handle_t hClient,
+ OUT PHPROCESS *phProcess,
+ OUT DWORD *pTimeoutInSeconds,
+ OUT DUALSTRINGARRAY **ppdsaOrBindings,
+ OUT MID *pLocalMid,
+ IN LONG cIdsToReserve,
+ OUT ID *pidReservedBase,
+ OUT DWORD *pfConnectFlags,
+ OUT WCHAR **pLegacySecurity,
+ OUT DWORD *pAuthnLevel,
+ OUT DWORD *pImpLevel,
+ OUT DWORD *pcServerSvc,
+ OUT USHORT **aServerSvc,
+ OUT DWORD *pcClientSvc,
+ OUT USHORT **aClientSvc,
+ OUT DWORD *pThreadID,
+ OUT DWORD *pScmProcessID,
+ OUT DWORD *pSignature
+ )
+{
+ ORSTATUS status;
+ CProcess *pProcess;
+ CToken *pToken;
+
+ OrDbgDetailPrint(("OR: Client connected\n"));
+
+ *pfConnectFlags = 0;
+
+ // Fill in security parameters.
+ if (s_fEnableDCOM == FALSE) *pfConnectFlags |= CONNECT_DISABLEDCOM;
+ if (s_fMutualAuth) *pfConnectFlags |= CONNECT_MUTUALAUTH;
+ if (s_fSecureRefs) *pfConnectFlags |= CONNECT_SECUREREF;
+ *pLegacySecurity = s_pLegacySecurity;
+ *pAuthnLevel = s_lAuthnLevel;
+ *pImpLevel = s_lImpLevel;
+ *pcServerSvc = s_cServerSvc;
+ *aServerSvc = s_aServerSvc;
+ *pcClientSvc = s_cClientSvc;
+ *aClientSvc = s_aClientSvc;
+
+ *pSignature = 0;
+
+ status = StartListeningIfNecessary();
+
+ if (status != OR_OK)
+ {
+ return(status);
+ }
+
+ ASSERT(pdsaMyBindings);
+
+ status = RegisterAuthInfoIfNecessary();
+
+ if (status != OR_OK)
+ {
+ return(status);
+ }
+
+ // Do client specific stuff
+
+ gpClientLock->LockShared();
+
+ status = LookupOrCreateToken(hClient, TRUE, &pToken); // Will check security
+
+ if (OR_OK == status)
+ {
+ pProcess = 0;
+
+ // Must be a local client.
+
+ *ppdsaOrBindings = (DUALSTRINGARRAY *)MIDL_user_allocate(
+ pdsaMyBindings->wNumEntries * sizeof(WCHAR)
+ + sizeof(DUALSTRINGARRAY) );
+
+ if (*ppdsaOrBindings)
+ {
+ dsaCopy(*ppdsaOrBindings, pdsaMyBindings);
+ }
+ else
+ {
+ status = OR_NOMEM;
+ }
+
+ if (status == OR_OK)
+ {
+ pProcess = new CProcess(pToken, status);
+ if (pProcess && status == OR_OK)
+ {
+ *phProcess = (void *)pProcess;
+ }
+ else
+ {
+ ReleaseProcess(pProcess);
+ // Will cause the process to rundown and release the token.
+ pToken = 0;
+ status = OR_NOMEM;
+ }
+ }
+ else
+ {
+ status = OR_NOMEM;
+ }
+
+ if (status != OR_OK)
+ {
+ gpClientLock->ConvertToExclusive();
+ MIDL_user_free(*ppdsaOrBindings);
+ *ppdsaOrBindings = 0;
+ *phProcess = 0;
+ if ( pToken )
+ pToken->Release();
+ *pSignature = 0;
+ gpClientLock->UnlockExclusive();
+ return(OR_NOMEM);
+ }
+
+ *pSignature = (ULONG) pProcess;
+ }
+
+ *pTimeoutInSeconds = BaseTimeoutInterval;
+ *pLocalMid = gLocalMid;
+
+ ASSERT( (*phProcess == 0 && *ppdsaOrBindings == 0) || status == OR_OK);
+
+ _AllocateReservedIds(0,
+ cIdsToReserve,
+ pidReservedBase);
+
+ *pScmProcessID = GetCurrentProcessId();
+ *pThreadID = InterlockedExchangeAdd((long *)&gNextThreadID,1);
+
+ gpClientLock->UnlockShared();
+
+ return(status);
+}
+
+
+error_status_t
+_AllocateReservedIds(
+ IN handle_t hClient,
+ IN LONG cIdsToReserve,
+ OUT ID *pidReservedBase
+ )
+/*++
+
+Routine Description:
+
+ // Called by local clients to reserve a range of IDs which will
+ // not conflict with any other local IDs.
+
+Arguments:
+
+ hClient - 0 or the connection of the client.
+
+ cIdsToReserve - Number of IDs to reserve.
+
+ pidReservedBase - Starting value of the reserved IDs. The
+ lower DWORD of this can be increatmented to generate
+ cIdsToReserve unique IDs.
+
+Return Value:
+
+ OR_OK
+
+--*/
+{
+ UINT type;
+
+ if (hClient)
+ {
+ if ( (I_RpcBindingInqTransportType( hClient, &type) != RPC_S_OK)
+ || (type != TRANSPORT_TYPE_LPC) )
+ {
+ RpcRaiseException(OR_NOACCESS);
+ }
+ }
+
+ if (cIdsToReserve > 10 || cIdsToReserve < 0)
+ {
+ cIdsToReserve = 10;
+ }
+
+ *pidReservedBase = AllocateId(cIdsToReserve);
+ return(OR_OK);
+}
+
+
+error_status_t
+_ClientResolveOXID(
+ IN handle_t hClient,
+ IN PHPROCESS phProcess,
+ IN OXID *poxidServer,
+ IN DUALSTRINGARRAY *pdsaServerBindings,
+ IN LONG fApartment,
+ OUT OXID_INFO *poxidInfo,
+ OUT MID *pDestinationMid
+ )
+/*++
+
+Routine Description:
+
+ Discovers the OXID_INFO for an oxid. Will find local
+ OXIDs without any help. It needs OR bindings in order
+ to discover remote OXIDs.
+
+Arguments:
+
+ phProcess - The context handle of the process.
+
+ poxidServer - The OXID (a uuid) to resolve.
+
+ pdsaServerBindings - Compressed string bindings to
+ the OR on the server's machine.
+
+ fApartment - non-zero if the client is aparment model.
+ REVIEW: What to do with mixed model clients?
+ What to do when auto registering an OID?
+
+
+ poxidInfo - If successful this will contain information about the oxid and
+ an expanded string binding to the server oxid's process.
+
+Return Value:
+
+ OR_NOMEM - Common.
+
+ OR_BADOXID - Unable to resolve it.
+
+ OR_OK - Success.
+
+--*/
+{
+ // REVIEW: no security check here. OXID info
+ // is not private and you can allocate memory in
+ // your process, too. If we needed to store some
+ // info in the client process then a security
+ // is needed
+
+ return ResolveClientOXID( hClient,
+ phProcess,
+ poxidServer,
+ pdsaServerBindings,
+ fApartment,
+ 0,
+ poxidInfo,
+ pDestinationMid );
+}
+
+error_status_t
+ResolveClientOXID(
+ handle_t hClient,
+ PHPROCESS phProcess,
+ OXID *poxidServer,
+ DUALSTRINGARRAY *pdsaServerBindings,
+ LONG fApartment,
+ USHORT wProtseqId,
+ OXID_INFO *poxidInfo,
+ MID *pDestinationMid
+ )
+/*++
+
+Routine Description:
+
+ Discovers the OXID_INFO for an oxid. Will find local
+ OXIDs without any help. It needs OR bindings in order
+ to discover remote OXIDs.
+
+Arguments:
+
+ phProcess - The context handle of the process.
+ Since this is called from SCM directly this function
+ CAN BE called on the same process by more then one
+ thread at a time.
+
+ poxidServer - The OXID (a uuid) to resolve.
+
+ pdsaServerBindings - Compressed string bindings to
+ the OR on the server's machine.
+
+ fApartment - non-zero if the client is aparment model.
+ REVIEW: What to do with mixed model clients?
+ What to do when auto registering an OID?
+
+
+ poxidInfo - If successful this will contain information about the oxid and
+ an expanded string binding to the server oxid's process.
+
+Return Value:
+
+ OR_NOMEM - Common.
+
+ OR_BADOXID - Unable to resolve it.
+
+ OR_OK - Success.
+
+--*/
+{
+ CProcess *pProcess;
+ CClientOxid *pOxid;
+ CServerOxid *pServerOxid;
+ CMid *pMid;
+ ORSTATUS status = OR_OK;
+ BOOL fReference;
+ BOOL fServerApartment = FALSE;
+ BOOL fRetry = TRUE;
+ BOOL fReset = FALSE;
+
+ pProcess = ReferenceProcess(phProcess);
+ ASSERT(pProcess);
+
+ if (! dsaValid(pdsaServerBindings))
+ {
+ return(OR_BADPARAM);
+ }
+
+ // Attempt to lookup MID and OXID
+
+ gpClientLock->LockExclusive();
+
+ CMidKey midkey(pdsaServerBindings);
+
+ pMid = (CMid *)gpMidTable->Lookup(midkey);
+
+ if (0 == pMid)
+ {
+ fReference = TRUE;
+ pMid = new(pdsaServerBindings->wNumEntries * sizeof(WCHAR)) CMid(pdsaServerBindings, FALSE);
+ if (pMid)
+ {
+ gpMidTable->Add(pMid);
+ }
+
+ if (0 == pMid)
+ {
+ status = OR_NOMEM;
+ }
+ }
+ else
+ {
+ fReference = FALSE;
+ }
+
+ if (status == OR_OK)
+ {
+ CId2Key oxidkey(*poxidServer, pMid->Id());
+
+ pOxid = (CClientOxid *)gpClientOxidTable->Lookup(oxidkey);
+
+ if (0 == pOxid)
+ {
+ if (!fReference)
+ {
+ pMid->Reference();
+ fReference = TRUE;
+ }
+
+ // Need to allocate the OXID. First step is too resolve it
+ // either locally or remotly.
+
+ gpClientLock->UnlockExclusive();
+
+ if (pMid->IsLocal())
+ {
+ // Local OXID, lookup directly
+
+ gpServerLock->LockShared();
+
+ CIdKey key(*poxidServer);
+ pServerOxid = (CServerOxid *)gpServerOxidTable->Lookup(key);
+
+ if (pServerOxid)
+ {
+ status = pServerOxid->GetInfo(poxidInfo, TRUE);
+ fServerApartment = pServerOxid->Apartment();
+ }
+ else
+ {
+ status = OR_BADOXID;
+ }
+ ASSERT(status != OR_OK || dsaValid(poxidInfo->psa));
+ gpServerLock->UnlockShared();
+
+ }
+ else if (0 == poxidInfo->psa)
+ {
+ // Remote OXID, call ResolveOxid
+
+ USHORT cProtseqs;
+ USHORT *aProtseqs;
+ USHORT tmpProtseq;
+ handle_t hRemoteOr;
+ USHORT iBinding;
+
+ // BUGBUG: Only sending the protseq we're calling on,
+ // this should be fixed to send in the whole list if
+ // it includes the protseq we're calling on.
+ // This is a workaround for a Cairo setup problem.
+
+ cProtseqs = 1;
+ aProtseqs = &tmpProtseq;
+ poxidInfo->psa = 0;
+
+ status = OR_NOMEM;
+
+ while (hRemoteOr = pMid->GetBinding(iBinding))
+ {
+
+ tmpProtseq = pMid->ProtseqOfServer(iBinding);
+
+ if (pMid->IsSecure())
+ {
+ status = RpcImpersonateClient(hClient);
+
+ if (status == RPC_S_OK)
+ {
+ RPC_SECURITY_QOS qos;
+ qos.Version = RPC_C_SECURITY_QOS_VERSION;
+ qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
+ qos.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC;
+ qos.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
+
+ status = RpcBindingSetAuthInfoEx(hRemoteOr,
+ 0,
+ RPC_C_AUTHN_LEVEL_CONNECT,
+ RPC_C_AUTHN_WINNT,
+ 0,
+ 0,
+ &qos);
+ }
+
+ if (status != RPC_S_OK)
+ {
+ OrDbgPrint(("OR: Unable to setup secure connection %d\n",
+ status));
+ }
+
+ fReset = FALSE;
+ }
+ else
+ {
+ fReset = TRUE;
+ }
+
+ fRetry = TRUE;
+
+ for(;;)
+ {
+ status = ResolveOxid(hRemoteOr,
+ poxidServer,
+ cProtseqs,
+ aProtseqs,
+ &poxidInfo->psa,
+ &poxidInfo->ipidRemUnknown,
+ &poxidInfo->dwAuthnHint
+ );
+
+ if (status == OR_OK)
+ {
+ if (dsaValid(poxidInfo->psa))
+ {
+ wProtseqId = tmpProtseq;
+ }
+ else
+ {
+ OrDbgPrint(("OR: Server %s returned a bogus string array: %p\n",
+ pMid->PrintableName(), poxidInfo->psa));
+ ASSERT(0);
+ if (poxidInfo->psa)
+ {
+ MIDL_user_free(poxidInfo->psa);
+ poxidInfo->psa = 0;
+ }
+ status = OR_BADOXID;
+ }
+ break;
+ }
+
+ if ( fRetry
+ && (status == RPC_S_UNKNOWN_IF))
+ {
+ status = RpcBindingReset(hRemoteOr);
+ if (status != RPC_S_OK)
+ {
+ OrDbgPrint(("OR: RpcBindingReset failed %d\n", status));
+ }
+ fRetry = FALSE;
+ continue;
+ }
+
+ if ( !fReset
+ && ( status == RPC_S_ACCESS_DENIED
+ || status == RPC_S_UNKNOWN_AUTHN_SERVICE
+ || status == RPC_S_UNKNOWN_AUTHZ_SERVICE
+ || status == RPC_S_SEC_PKG_ERROR ) )
+ {
+ status = RpcBindingSetAuthInfo(hRemoteOr,
+ 0,
+ RPC_C_AUTHN_LEVEL_NONE,
+ RPC_C_AUTHN_NONE,
+ 0,
+ 0);
+ if (status != RPC_S_OK)
+ {
+ OrDbgPrint(("OR: RpcBindingSetAuthInfo to NONE failed!! %d\n",
+ status));
+ }
+
+ // Even if the reset failed, don't try it again.
+ fReset = TRUE;
+ continue;
+ }
+
+ OrDbgPrint(("OR: Remote resolve OXID failed %d\n", status));
+ break;
+ }
+
+ if ( status == OR_OK
+ || status == OR_BADOXID
+ || status == OR_NOMEM )
+ {
+ break;
+ }
+
+ RpcBindingFree(&hRemoteOr);
+ pMid->BindingFailed(iBinding);
+ }
+
+ if (hRemoteOr)
+ {
+ RPC_STATUS tstatus = RpcBindingFree(&hRemoteOr);
+ ASSERT(tstatus == RPC_S_OK);
+ }
+ }
+ // Else it's a remote MID, but we were given the OXID info
+ // and protseq id from the SCM after a remote activation.
+
+ gpClientLock->LockExclusive();
+
+ ASSERT(fReference);
+
+ if ( OR_OK == status
+ && FALSE == fRetry)
+ {
+ OrDbgDetailPrint(("OR: Machine %S, retry ok, assuming dynamic\n",
+ pMid->PrintableName() ));
+ pMid->UseDynamicEndpoints();
+ }
+
+ if ( OR_OK == status
+ && TRUE == fReset )
+ {
+ OrDbgDetailPrint(("OR: Machine %S, unsecure retry ok, assuming no sec\n",
+ pMid->PrintableName() ));
+ pMid->SecurityFailed();
+ }
+
+ if (status == OR_OK)
+ {
+ // Lookup the oxid again to make sure it hasn't been added in the meantime.
+
+ pOxid = (CClientOxid *)gpClientOxidTable->Lookup(oxidkey);
+
+ if (0 == pOxid)
+ {
+ ASSERT(dsaValid(poxidInfo->psa));
+ pOxid = new CClientOxid(*poxidServer,
+ pMid,
+ wProtseqId,
+ fServerApartment);
+
+ if (0 != pOxid)
+ {
+ status = pOxid->UpdateInfo(poxidInfo);
+
+ if (OR_OK == status)
+ {
+ gpClientOxidTable->Add(pOxid);
+
+ // Will be references by the process and by other
+ // OIDs are it is used. Will be refernced again
+ // before we leave the lock if successful.
+ pOxid->Release();
+ }
+ else
+ {
+ // Will release mid, will also remove it (unnecessarily)
+ // from the table.
+ delete pOxid;
+ }
+ }
+ else
+ {
+ status = OR_NOMEM;
+ pMid->Release(); // May actually go away..
+ }
+ }
+ else
+ {
+ // Release our now extra reference on the MID
+ DWORD t = pMid->Release();
+ ASSERT(t > 0);
+ }
+
+ MIDL_user_free(poxidInfo->psa);
+ poxidInfo->psa = 0;
+ }
+ else
+ {
+ // Resolve failed, get rid of our extra reference.
+ pMid->Release();
+ }
+ }
+ else
+ {
+ // Found the OXID, must also have found the MID
+ ASSERT(fReference == FALSE);
+
+ if ( poxidInfo->psa )
+ {
+ MIDL_user_free(poxidInfo->psa);
+ poxidInfo->psa = 0;
+ }
+ }
+ }
+
+ ASSERT( (status != OR_OK) || (pOxid && pMid) );
+
+ if ( status == OR_OK
+ && pOxid->IsLocal() == FALSE)
+ {
+ status = pProcess->AddRemoteOxid(pOxid);
+ }
+
+ gpClientLock->UnlockExclusive();
+
+ if (status == OR_OK)
+ {
+ *pDestinationMid = pMid->Id();
+
+ status = pOxid->GetInfo(fApartment, poxidInfo);
+
+ if ( status != OR_OK
+ && pOxid->IsLocal() == FALSE)
+ {
+ gpClientLock->LockExclusive();
+ pProcess->RemoveRemoteOxid(pOxid);
+ gpClientLock->UnlockExclusive();
+ }
+ }
+
+ return(status);
+}
+
+
+error_status_t
+_BulkUpdateOIDs(
+ IN handle_t hClient,
+ IN PHPROCESS phProcess,
+ IN ULONG cOidsToBeAdded,
+ IN OXID_OID_PAIR aOidsToBeAdded[],
+ OUT LONG aStatusOfAdds[],
+ IN ULONG cOidsToBeRemoved,
+ IN OID_MID_PAIR aOidsToBeRemoved[],
+ IN ULONG cServerOidsToFree,
+ IN OID aServerOidsToFree[],
+ IN ULONG cClientOxidsToFree,
+ IN OXID_REF aClientOxidsToFree[]
+ )
+/*++
+
+Routine Description:
+
+ Updates the set of remote OIDs in use by a process.
+
+Note:
+
+ An OID maybe removed before it is added. This means that
+ the client was using it and is no longer using it. In
+ this case a single delete from set ping is made to keep
+ the object alive. This is only needed if the client
+ has remarshalled a pointer to the object.
+
+Arguments:
+
+ phProcess - Context handle for the process.
+
+ cOidsToBeAdded - Count of aOidsToBeAdded and aStatusOfAdds
+
+ aOidsToBeAdded - OID-OXID-MID pairs representing the
+ oids and the owning oxids to add.
+
+ aStatusOfAdds - Some adds may succeed when other fail.
+ OR_NOMEM - couldn't allocate storage
+ OR_BADOXID - OXID doesn't exist.
+ OR_OK (0) - added to set
+
+ cOidsToBeRemoved - Count of entries in aOidsToBeRemoved.
+
+ aOidsToBeRemoved - OID-MID pairs to be removed.
+
+ cServerOidsToFree - Count of entries in aServerOidsToFree
+
+ aServerOidsToFree - OIDs allocated by the client process
+ and no longer needed.
+
+ cClientOxidsToFree - COunt of enties in aClientOxidsToFree
+
+ aClientOxidsToFree - OXIDs owned by a process (due to a direct
+ or indirect call to ClientResolveOxid) which are no longer
+ in use by the client.
+
+Return Value:
+
+ OR_OK - All updates completed ok.
+
+ OR_PARTIAL_UPDATE - At least one entry in aStatusOfAdds is not OR_OK
+
+--*/
+{
+ CProcess *pProcess;
+ CClientOxid *pOxid;
+ CClientOid *pOid;
+ CClientSet *pSet;
+ CMid *pMid;
+ CToken *pToken;
+ BOOL fPartial = FALSE;
+ BOOL fNewSet = FALSE;
+ INT i;
+
+ pProcess = ReferenceProcess(phProcess);
+ ASSERT(pProcess);
+
+ CheckLocalSecurity(hClient, pProcess);
+
+ if (cOidsToBeAdded || cOidsToBeRemoved || cClientOxidsToFree)
+ {
+ gpClientLock->LockExclusive();
+ }
+
+ // /////////////////////////////////////////////////////////////////
+ // Process Adds.
+
+ for (i = 0; i < cOidsToBeAdded; i++)
+ {
+ // Lookup up the oxid owning this new oid.
+
+ CId2Key oxidkey(aOidsToBeAdded[i].oxid, aOidsToBeAdded[i].mid);
+
+ pOxid = (CClientOxid *)gpClientOxidTable->Lookup(oxidkey);
+
+ if (0 == pOxid)
+ {
+ OXID_INFO infoT;
+ ORSTATUS status;
+ MID mid;
+
+ gpClientLock->UnlockExclusive();
+
+ infoT.psa = 0;
+ status = _ClientResolveOXID(hClient,
+ phProcess,
+ &aOidsToBeAdded[i].oxid,
+ pdsaMyBindings,
+ TRUE,
+ &infoT,
+ &mid);
+
+ gpClientLock->LockExclusive();
+
+ if (status == OR_OK)
+ {
+ ASSERT(infoT.psa);
+ ASSERT(mid == gLocalMid);
+ MIDL_user_free(infoT.psa);
+ pOxid = (CClientOxid *)gpClientOxidTable->Lookup(oxidkey);
+ if (pOxid == 0)
+ {
+ OrDbgDetailPrint(("OR: Auto resolving oxid %p failed, wrong machine\n",
+ &oxidkey));
+ status = OR_BADOXID;
+ }
+ }
+
+ if (status != OR_OK)
+ {
+ aStatusOfAdds[i] = OR_BADOXID;
+ fPartial = TRUE;
+ continue;
+ }
+ }
+
+
+ // Find or create the set.
+
+ CId2Key setkey(aOidsToBeAdded[i].mid, (ID)pProcess->GetToken());
+
+ pSet = (CClientSet *)gpClientSetTable->Lookup(setkey);
+
+ if (pSet == 0)
+ {
+ pSet = new CClientSet(pOxid->GetMid(), pProcess->GetToken());
+
+ if (pSet == 0)
+ {
+ aStatusOfAdds[i] = OR_NOMEM;
+ fPartial = TRUE;
+ continue;
+ }
+ else
+ {
+ gpClientSetTable->Add(pSet);
+ pSet->Insert();
+ fNewSet = TRUE;
+ }
+ }
+
+ // Find or create the oid. If we create it, add a reference
+ // to the oxid for the new oid.
+
+ CId3Key oidkey(aOidsToBeAdded[i].oid, aOidsToBeAdded[i].mid, pProcess->GetToken());
+
+ pOid = (CClientOid *)gpClientOidTable->Lookup(oidkey);
+
+ if (0 == pOid)
+ {
+ pOid = new CClientOid(aOidsToBeAdded[i].oid,
+ aOidsToBeAdded[i].mid,
+ pProcess->GetToken(),
+ pOxid,
+ pSet
+ );
+ if (fNewSet)
+ {
+ // pOid either owns a refernce now or we need to
+ // cleanup the set anyway.
+ pSet->Release();
+ fNewSet = FALSE;
+ }
+
+ if (pOid)
+ {
+
+ aStatusOfAdds[i] = pSet->RegisterObject(pOid);
+
+ if (aStatusOfAdds[i] == OR_OK)
+ {
+ gpClientOidTable->Add(pOid);
+ }
+ else
+ {
+ pOid->Release();
+ pOid = 0;
+ }
+ }
+ else
+ {
+ aStatusOfAdds[i] = OR_NOMEM;
+ fPartial = TRUE;
+ continue;
+ }
+
+ }
+ else
+ {
+ ASSERT(fNewSet == FALSE);
+ pOid->ClientReference();
+ }
+
+ // If this fails it will release the oid.
+ aStatusOfAdds[i] = pProcess->AddOid(pOid);
+ if (aStatusOfAdds[i] != OR_OK)
+ {
+ fPartial = TRUE;
+ }
+ } // for oids to add
+
+ // /////////////////////////////////////////////////////////////////
+ // Process deletes
+
+ for (i = 0; i < cOidsToBeRemoved; i++)
+ {
+ CId3Key oidkey(aOidsToBeRemoved[i].oid,
+ aOidsToBeRemoved[i].mid,
+ pProcess->GetToken());
+
+ pOid = (CClientOid *)gpClientOidTable->Lookup(oidkey);
+
+ if (pOid)
+ {
+ CClientOid *pT = pProcess->RemoveOid(pOid);
+
+ if (pT == 0)
+ {
+ OrDbgPrint(("OR: Client process %p tried to remove oid %p which"
+ "it didn't own\n", pProcess, &aOidsToBeRemoved[i]));
+ }
+ else
+ ASSERT(pT == pOid);
+ }
+ else
+ OrDbgDetailPrint(("OR: Client %p removed an OID that doesn't exist\n", pProcess));
+
+ } // for oids to delete
+
+ // ////////////////////////////////////////////////////////////
+ // Process client oxid deletes
+
+ if (cClientOxidsToFree)
+ {
+ CClientOxid *pOxid;
+ for (i = 0; i < cClientOxidsToFree; i++)
+ {
+ CId2Key oxidKey(aClientOxidsToFree[i].oxid,
+ aClientOxidsToFree[i].mid);
+
+ pOxid = (CClientOxid *)gpClientOxidTable->Lookup(oxidKey);
+ if (pOxid)
+ {
+ for (int j = 0; j < aClientOxidsToFree[i].refs; j++)
+ {
+ pProcess->RemoveRemoteOxid(pOxid);
+ }
+ }
+ else
+ {
+ OrDbgPrint(("OR: Process %p freed oxid %p which didn't exist\n",
+ pProcess, &aClientOxidsToFree[i]));
+ ASSERT(0);
+ }
+ }
+ }
+
+ if (cOidsToBeAdded || cOidsToBeRemoved || cClientOxidsToFree)
+ {
+ gpClientLock->UnlockExclusive();
+ }
+
+ // /////////////////////////////////////////////////////////////////
+ // Process server deletes
+
+ if (cServerOidsToFree)
+ {
+ CServerOid *pOid;
+ CServerOxid *pOxid;
+
+ gpServerLock->LockExclusive();
+
+ for (i = 0; i < cServerOidsToFree; i++)
+ {
+ CIdKey oidkey(aServerOidsToFree[i]);
+
+ pOid = (CServerOid *)gpServerOidTable->Lookup(oidkey);
+ if (pOid && pOid->IsRunningDown() == FALSE)
+ {
+ pOxid = pOid->GetOxid();
+ ASSERT(pOxid);
+ if (pProcess->IsOwner(pOxid))
+ {
+ if (pOid->References() == 0)
+ {
+ pOid->Remove();
+ pOid->SetRundown();
+ delete pOid;
+ }
+ else
+ {
+ pOid->Free();
+ }
+ }
+ else
+ {
+ OrDbgPrint(("OR: Process %p tried to free OID %p it didn't own\n",
+ pProcess, pOid));
+ }
+ }
+ else
+ {
+ OrDbgPrint(("OR: Process %p freed OID %p that didn't exist\n",
+ pProcess, &aServerOidsToFree[i]));
+ }
+ }
+
+ gpServerLock->UnlockExclusive();
+ }
+
+ // Done
+
+ if (fPartial)
+ {
+ return(OR_PARTIAL_UPDATE);
+ }
+
+ return(OR_OK);
+}
+
+error_status_t
+_ServerAllocateOXIDAndOIDs(
+ IN handle_t hClient,
+ IN PHPROCESS phProcess,
+ OUT OXID *poxidServer,
+ IN LONG fApartment,
+ IN ULONG cOids,
+ OUT OID aOid[],
+ OUT PULONG pOidsAllocated,
+ IN OXID_INFO *poxidInfo, // No bindings
+ IN DUALSTRINGARRAY *pdsaStringBindings, // Expanded
+ IN DUALSTRINGARRAY *pdsaSecurityBindings // Compressed
+ )
+/*++
+
+Routine Description:
+
+ Allocates an OXID and 0 or more OIDs from the OR.
+
+Arguments:
+
+ phProcess - The context handle of the process containing the OXID.
+
+ poxidServer - The OXID to register. May only register once.
+
+ cOids - Count of apOids
+
+ apOid - The OIDs to register within the OXID.
+
+ pcOidsAllocated - The number of OIDs actually allocated. Usually the
+ same as cOids unless a resource failure occures. Maybe 0.
+
+ poxidInfo - The OXID_INFO structure for the OXID without bindings.
+
+ pdsaStringBindings - Expanded string binding of the server.
+
+ pdsaSecurityBindings - The compressed security bindings of the server.
+
+ pOidsAllocated - The number of OIDs actually allocated. >= 0 and <= cOids.
+
+Return Value:
+
+ OR_OK - success. Returned even if some OID allocations fail. See the
+ pOidsAllocated parameter.
+
+ OR_NOMEM - Allocation of OXID failed.
+
+ OR_ACCESS_DENIDED - Raised if non-local client
+
+ OR_BADPARAM - if string arrays are incorrect.
+
+--*/
+{
+ ORSTATUS status = OR_OK;
+ CServerOxid *pNewOxid;
+ CProcess *pProcess = ReferenceProcess(phProcess);
+ ASSERT(pProcess);
+
+ CheckLocalSecurity(hClient, pProcess);
+
+ gpServerLock->LockExclusive();
+
+ // Save the string bindings back to the process
+
+ if (!dsaValid(pdsaStringBindings) )
+ {
+ status = OR_BADPARAM;
+ }
+
+ if (!dsaValid(pdsaSecurityBindings))
+ {
+ status = OR_BADPARAM;
+ }
+
+ if (status == OR_OK)
+ {
+ status = pProcess->ProcessBindings(pdsaStringBindings,
+ pdsaSecurityBindings);
+ }
+
+ VALIDATE((status, OR_NOMEM, OR_BADPARAM, 0));
+
+ if (status != OR_OK)
+ {
+ gpServerLock->UnlockExclusive();
+ return(status);
+ }
+
+ pNewOxid = new CServerOxid(pProcess,
+ fApartment,
+ poxidInfo
+ );
+
+ if (0 == pNewOxid)
+ {
+ gpServerLock->UnlockExclusive();
+ return(OR_NOMEM);
+ }
+
+ // Add to process and lookup table.
+
+ status = pProcess->AddOxid(pNewOxid);
+
+ VALIDATE((status, OR_NOMEM, 0));
+
+ pNewOxid->Release(); // process has a reference now or failed
+
+ gpServerLock->UnlockExclusive();
+
+ if (status == OR_OK)
+ {
+ *poxidServer = pNewOxid->Id();
+
+ status = _ServerAllocateOIDs(0,
+ phProcess,
+ poxidServer,
+ cOids,
+ aOid,
+ pOidsAllocated);
+ }
+
+ return(status);
+}
+
+error_status_t _ServerAllocateOIDs(
+ IN handle_t hClient,
+ IN PHPROCESS phProcess,
+ IN OXID *poxidServer,
+ IN ULONG cOids,
+ OUT OID aOids[],
+ OUT PULONG pOidsAllocated
+ )
+/*++
+
+Routine Description:
+
+ Registers additional OIDs on behalf of an existing OXID.
+
+Arguments:
+
+ phProcess - The context handle of the process containing the OXID and OIDs.
+
+ poxidServer - The OXID associated with the OIDs.
+
+ cOids - Count of apOids
+
+ aOids - The OIDs to register within the OXID.
+
+ pOidsAllocate - Contains the number of OIDs actually allocated
+ when this function returns success.
+
+Return Value:
+
+ OR_OK (0) - Success.
+
+ OR_PARTIAL_UPDATE - No all elements in aStatus are 0.
+
+ OR_NOMEM - OXID or one or more OIDs
+
+--*/
+{
+ ORSTATUS status = OR_OK;
+ CServerOxid *pOxid;
+ CServerOid *pOid;
+ BOOL fPartial = FALSE;
+ CProcess *pProcess = ReferenceProcess(phProcess);
+ ASSERT(pProcess);
+
+ CheckLocalSecurity(hClient, pProcess);
+
+ gpServerLock->LockExclusive();
+
+ CIdKey oxidkey(*poxidServer);
+
+ pOxid = (CServerOxid *)gpServerOxidTable->Lookup(oxidkey);
+
+ if (0 == pOxid)
+ {
+ gpServerLock->UnlockExclusive();
+ status = OR_BADOXID;
+ return(status);
+ }
+
+ *pOidsAllocated = 0;
+
+ for (INT i = 0; i < cOids; i++)
+ {
+ pOid = new CServerOid(pOxid);
+
+ if (0 != pOid)
+ {
+ (*pOidsAllocated)++;
+ aOids[i] = pOid->Id();
+ gpServerOidTable->Add(pOid);
+
+ // The server doesn't want to keep the OID alive.
+ // This will cause the OID to rundown in six minutes
+ // unless a set references it in the meantime...
+
+ pOid->Release();
+
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ gpServerLock->UnlockExclusive();
+
+ ASSERT(status == OR_OK);
+
+ return(status);
+}
+
+error_status_t
+_ServerFreeOXIDAndOIDs(
+ IN handle_t hClient,
+ IN PHPROCESS phProcess,
+ IN OXID oxidServer,
+ IN ULONG cOids,
+ IN OID aOids[])
+{
+ CServerOxid *pOxid;
+ CServerOid *pOid;
+ CProcess *pProcess = ReferenceProcess(phProcess);
+ ORSTATUS status;
+ UINT i;
+
+ ASSERT(pProcess);
+
+ CheckLocalSecurity(hClient, pProcess);
+
+ gpServerLock->LockExclusive();
+
+ CIdKey oxidkey(oxidServer);
+
+ pOxid = (CServerOxid *)gpServerOxidTable->Lookup(oxidkey);
+
+ if (0 != pOxid)
+ {
+ if (pProcess->RemoveOxid(pOxid) == TRUE)
+ {
+ // Found the OXID and this caller owns it.
+ status = OR_OK;
+ }
+ else
+ {
+ // Found but not owned by this caller.
+ status = OR_NOACCESS;
+ }
+ }
+ else
+ {
+ // Oxid not found.
+ status = OR_BADOXID;
+ }
+
+ // Note pOxid maybe invalid once the last OID is removed.
+
+ if (status == OR_OK)
+ {
+ for (i = 0; i < cOids; i++)
+ {
+ CIdKey key(aOids[i]); // PERF REVIEW
+
+ pOid = (CServerOid *)gpServerOidTable->Lookup(key);
+
+ if ( (0 != pOid)
+ && (pOid->IsRunningDown() == FALSE)
+ && (pOid->GetOxid() == pOxid) )
+ {
+ if (pOid->References() == 0)
+ {
+ // Unreferenced by any sets; run it down now..
+ pOid->Remove();
+ pOid->SetRundown();
+ delete pOid;
+ }
+ // else - marking it as Free() not need as Oxid is
+ // now marked as not running.
+ }
+ else
+ {
+ ASSERT(pOid == 0 || pOxid == pOid->GetOxid());
+ }
+ }
+ }
+
+ gpServerLock->UnlockExclusive();
+
+ return(status);
+}
+
+//
+// Manager (server-side) calls to the remote OR interface. objex.idl
+//
+
+error_status_t
+_ResolveOxid(
+ IN handle_t hRpc,
+ IN OXID *poxid,
+ IN USHORT cRequestedProtseqs,
+ IN USHORT aRequestedProtseqs[],
+ OUT DUALSTRINGARRAY **ppdsaOxidBindings,
+ OUT IPID *pipidRemUnknown,
+ OUT DWORD *pAuthnHint
+ )
+{
+ ORSTATUS status;
+ BOOL fDidLazy;
+ CServerOxid *pServerOxid;
+ OXID_INFO oxidInfo;
+
+ oxidInfo.psa = 0;
+
+ // No security check required (possible?). OXID info is not private.
+
+#if DBG
+ UINT fLocal;
+ status = I_RpcBindingIsClientLocal(hRpc, &fLocal);
+
+ if (status != OR_OK)
+ {
+ fLocal = FALSE;
+ }
+ ASSERT(fLocal == FALSE); // Shouldn't be called locally...
+#endif
+
+ fDidLazy = FALSE;
+
+ gpServerLock->LockShared();
+
+ for(;;)
+ {
+ CIdKey key(*poxid);
+
+ pServerOxid = (CServerOxid *)gpServerOxidTable->Lookup(key);
+
+ if (!pServerOxid)
+ {
+ status = OR_BADOXID;
+ break;
+ }
+
+ status = pServerOxid->GetRemoteInfo(&oxidInfo,
+ cRequestedProtseqs,
+ aRequestedProtseqs);
+
+ if ( status == OR_I_NOPROTSEQ
+ && FALSE == fDidLazy )
+ {
+ // Ask the server to start listening, but only try this once.
+
+ fDidLazy = TRUE;
+
+ status =
+ pServerOxid->LazyUseProtseq(cRequestedProtseqs,
+ aRequestedProtseqs
+ );
+
+ ASSERT(gpServerLock->HeldExclusive()); // Changed during UseProtseq!
+
+ if (status == OR_OK)
+ {
+ continue;
+ }
+ }
+ else if (status == OR_I_NOPROTSEQ)
+ {
+ // We didn't manage to use a matching protseq.
+ // Since the client managed to call us why didn't this work?
+ OrDbgPrint(("OR: Failed to use a matching protseq: %p %p\n",
+ pServerOxid, aRequestedProtseqs));
+ ASSERT(0);
+ status = OR_NOSERVER;
+ }
+ break;
+ }
+
+ gpServerLock->Unlock();
+
+ if (status == OR_OK)
+ {
+ *pipidRemUnknown = oxidInfo.ipidRemUnknown;
+ *ppdsaOxidBindings = oxidInfo.psa;
+ *pAuthnHint = oxidInfo.dwAuthnHint;
+ }
+
+ return(status);
+}
+
+error_status_t
+_SimplePing(
+ IN handle_t hRpc,
+ IN SETID *pSetId
+ )
+{
+ ORSTATUS status;
+ CServerSet *pServerSet;
+ BOOL fShared = TRUE;
+
+ if (*pSetId == 0)
+ {
+ OrDbgPrint(("Client %p simple pinged with a setid of 0\n",
+ hRpc, pSetId));
+ return(OR_BADSET);
+ }
+
+ gpServerLock->LockShared();
+
+ pServerSet = (CServerSet *)gpServerSetTable->Lookup(*pSetId);
+
+ if (pServerSet)
+ {
+ fShared = pServerSet->Ping(TRUE);
+ // The lock maybe exclusive now.
+ status = OR_OK;
+ }
+ else
+ {
+ status = OR_BADSET;
+ }
+
+ // See if another set in the table needs to rundown.
+ // PERF REVIEW - how often should I do this? 0 mod 4?
+
+ // Similar code in worker threads.
+
+ ID setid = gpServerSetTable->CheckForRundowns();
+
+ if (setid)
+ {
+ if (fShared)
+ {
+ gpServerLock->ConvertToExclusive();
+ fShared = FALSE;
+ }
+
+ gpServerSetTable->RundownSetIfNeeded(setid);
+ }
+
+ gpServerLock->Unlock();
+
+ return(status);
+}
+
+error_status_t
+_ComplexPing(
+ IN handle_t hRpc,
+ IN SETID *pSetId,
+ IN USHORT SequenceNum,
+ IN USHORT cAddToSet,
+ IN USHORT cDelFromSet,
+ IN OID AddToSet[],
+ IN OID DelFromSet[],
+ OUT USHORT *pPingBackoffFactor
+ )
+/*++
+
+Routine Description:
+
+ Processes a complex (delta to set) ping for a given set. This call
+ will create the set if necessary. The call will only be processed
+ if the caller is in fact the creator of the set.
+
+ algorithm:
+
+ if set is not allocated
+ lookup security info if possible
+ allocate set
+ else
+ lookup set
+
+
+ if found or created a set
+ do a standard ping, updating time stamp and sequence number.
+ else return failure.
+
+ if oids to add, add each one.
+ ignore unknown OIDs
+ if resource allocation fails, abort.
+
+ if oids to delete, process each one.
+ ignore unknown OIDs
+
+ if resource failure in adds, return OR_BADOID
+ else return success.
+
+Arguments:
+
+ hRpc - Handle (SCONN/SCALL) of client. Used to check security. If it is
+ NULL the call is local and is assumed to be secure.
+
+ REVIEW:
+ Since the OR _only_ uses NT system security providers it is assumed
+ that impersonation will work. Other security providers will not.
+
+ We need a generic way to ask for a token and compare tokens in a
+ security provider independent way.
+
+ pSetId - The setid to ping. If it is NULL a new set will be created,
+ otherwise, it is assumed to be a set previously allocated by a
+ call with a NULL setid to this server.
+
+ SequenceNum - A sequence number shared between the client and server
+ to make sure old and out-of-order pings are not processed in a
+ non-healthy way. Note that pings are usually datagram RPC calls
+ which are marked as idempotent.
+
+ cAddToSet
+ cDelFromSet - The count of element in AddTo/DelFromSet parameter.
+
+ AddToSet
+ DelFromSet - OID mostly likly belonging to servers on this machine
+ to Add/Remove from the set of OIDs in use by this client.
+
+ pPingBackoffFactor - Maybe set by servers which want to reduce the
+ ping load on the server. Serves only as a HINT for the client.
+ Clients do not to ping more offten then:
+ (1<<*pPingBackoffFactor)*BasePingInterval seconds.
+ Clients may choose to assume this parameter is always 0.
+
+Return Value:
+
+ OR_OK - completed normally
+
+ OR_BADSET - non-zero and unknown setid.
+
+ OR_NOMEM - unable to allocate a resource. Note that
+ on the first ping a set maybe allocated (setid is non-zero
+ after call) but some OIDs failed to be allocated.
+
+ OR_BADOID - everything went okay, but some OIDs added where
+ not recognized.
+
+--*/
+
+{
+ CServerSet *pServerSet;
+ BOOL fProcessPing;
+ BOOL fBad = FALSE;
+ PSID psid = 0;
+ ORSTATUS status = OR_OK;
+
+ gpServerLock->LockExclusive();
+
+ // Lookup the set
+
+ if (0 != *pSetId)
+ {
+ pServerSet = (CServerSet *)gpServerSetTable->Lookup(*pSetId);
+ if (0 == pServerSet)
+ {
+ status = OR_BADSET;
+ }
+
+ if (status == OR_OK)
+ {
+ if (pServerSet->CheckSecurity(hRpc) != TRUE)
+ {
+ OrDbgPrint(("OR: Security check on set failed! (%d)\n", GetLastError()));
+ status = OR_NOACCESS;
+ }
+ }
+ }
+ else if (hRpc == 0)
+ {
+ // Local client
+ psid = 0;
+ pServerSet = gpServerSetTable->Allocate(SequenceNum,
+ psid,
+ hRpc == 0,
+ *pSetId);
+
+ if (0 == pServerSet)
+ status = OR_NOMEM;
+ else
+ status = OR_OK;
+
+ }
+ else
+ {
+ HANDLE hT;
+ BOOL f;
+ // Unallocated set, lookup security info and allocate the set.
+
+ OrDbgDetailPrint(("OR: New client started pinging: %p\n", hRpc));
+
+ status = RpcImpersonateClient(hRpc);
+
+ if (status == RPC_S_OK)
+ {
+ f = OpenThreadToken(GetCurrentThread(),
+ TOKEN_IMPERSONATE | TOKEN_QUERY,
+ TRUE,
+ &hT);
+
+ if (!f)
+ {
+ status = GetLastError();
+ }
+ else
+ {
+ status = RPC_S_OK;
+ }
+
+ }
+
+ if (status != RPC_S_OK)
+ {
+ OrDbgPrint(("OR: Unsecure client started pinging: %d %p\n",
+ status, hRpc));
+ status = OR_OK;
+ }
+ else
+ {
+ ULONG needed = DEBUG_MIN(1, 24);
+ PTOKEN_USER ptu;
+
+ do
+ {
+ ptu = (PTOKEN_USER)alloca(needed);
+ ASSERT(ptu);
+
+ f = GetTokenInformation(hT,
+ TokenUser,
+ (PBYTE)ptu,
+ needed,
+ &needed);
+
+ } while( f == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
+
+ if (f)
+ {
+ ASSERT(needed > sizeof(SID));
+ psid = new(needed - sizeof(SID)) SID;
+ if (psid)
+ {
+ f = CopySid(needed, psid, ptu->User.Sid);
+ ASSERT(f == TRUE);
+ }
+ else
+ {
+ status = OR_NOMEM;
+ }
+ }
+ else
+ {
+ OrDbgPrint(("OR: Error %d from GetTokenInformation\n", GetLastError()));
+ ASSERT(0);
+ // Why did this happen. Either return failure to client or
+ // continue and make the set unsecure.
+ status = OR_NOMEM;
+ }
+
+ CloseHandle(hT);
+ }
+
+ // Allocate the set
+
+ if (status == OR_OK)
+ {
+ pServerSet = gpServerSetTable->Allocate(SequenceNum,
+ psid,
+ hRpc == 0,
+ *pSetId);
+
+ if (0 == pServerSet)
+ {
+ status = OR_NOMEM;
+ }
+ }
+ }
+
+ if (status != OR_OK)
+ {
+ VALIDATE((status, OR_NOMEM, OR_BADSET, OR_NOACCESS, 0));
+ gpServerLock->UnlockExclusive();
+ return(status);
+ }
+
+ ASSERT(pServerSet);
+
+ fProcessPing = pServerSet->CheckAndUpdateSequenceNumber(SequenceNum);
+
+ if (fProcessPing)
+ {
+ // Do regular ping
+
+ pServerSet->Ping(FALSE);
+
+ *pPingBackoffFactor = 0;
+
+ // Process Add's
+ for(int i = cAddToSet; i ; i--)
+ {
+ status = pServerSet->AddObject(AddToSet[i - 1]);
+
+ if (status == OR_BADOID)
+ {
+ fBad = TRUE;
+ }
+ else if ( status != OR_OK )
+ {
+ break;
+ }
+ }
+
+ // Process Deletes - even some adds failed!
+
+ for(i = cDelFromSet; i; i--)
+ {
+ // Removing can't fail, no way to cleanup.
+ pServerSet->RemoveObject(DelFromSet[i - 1]);
+ }
+ }
+
+ gpServerLock->UnlockExclusive();
+
+ if (status == OR_OK && fBad)
+ {
+ return(OR_BADOID);
+ }
+
+ return(status);
+}
+
+
+error_status_t
+_ServerAlive(
+ RPC_BINDING_HANDLE hServer
+ )
+/*++
+
+Routine Description:
+
+ Pign API for the client to validate a binding. Used when the client
+ is unsure of the correct binding for the server. (Ie. If the server
+ has multiple IP addresses).
+
+Arguments:
+
+ hServer - RPC call binding
+
+Return Value:
+
+ OR_OK
+
+--*/
+{
+ return(OR_OK);
+}
+
+
+
+void __RPC_USER PHPROCESS_rundown(LPVOID ProcessKey)
+{
+ CProcess *pProcess = ReferenceProcess(ProcessKey);
+
+ OrDbgDetailPrint(("OR: Client died\n"));
+
+ ASSERT(pProcess);
+
+ ReleaseProcess(pProcess);
+
+ return;
+}
+
+
+
diff --git a/private/ole32/dcomss/objex/mid.cxx b/private/ole32/dcomss/objex/mid.cxx
new file mode 100644
index 000000000..98866261b
--- /dev/null
+++ b/private/ole32/dcomss/objex/mid.cxx
@@ -0,0 +1,143 @@
+/*++
+
+Copyright (c) 1995-1996 Microsoft Corporation
+
+Module Name:
+
+ Mid.cxx
+
+Abstract:
+
+ Implements the CMid class.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 12-13-95 Bits 'n pieces
+ MarioGo 02-01-96 Move binding handles out of mid
+
+--*/
+
+#include<or.hxx>
+
+CRITICAL_SECTION gcsMidLock;
+
+
+RPC_BINDING_HANDLE
+CMid::GetBinding(
+ OUT USHORT &index
+ )
+/*++
+
+Routine Description:
+
+ Gets an RPC binding handle to the remote machine.
+
+Arguments:
+
+ index - index into the string array contianed within
+ this MID structure which can be passed to BindingFailed().
+ Maybe modified even on failure.
+
+Return Value:
+
+ 0 - when no more binding are available.
+
+ non-zero - A binding to the machine.
+
+--*/
+{
+ PWSTR pwstrT;
+ RPC_BINDING_HANDLE hserver;
+
+ if (IsLocal())
+ {
+ return(0);
+ }
+
+ CMutexLock lock(&gcsMidLock);
+
+ // Loop until we get a binding handle or run out of string bindings.
+ for (;;)
+ {
+ pwstrT = &_dsa.aStringArray[_iStringBinding];
+ if (*pwstrT == 0)
+ {
+ // Reached the end of the string bindings; give up..
+ _iStringBinding = 0;
+ return(0);
+ }
+
+ index = pwstrT - _dsa.aStringArray;
+
+ lock.Unlock();
+
+ if (_fDynamic)
+ {
+ // Create binding without an endpoint.
+ hserver = ::GetBinding(pwstrT);
+ }
+ else
+ {
+ hserver = GetBindingToOr(pwstrT);
+ }
+
+ if (hserver != 0)
+ {
+ // index is already correct.
+ return(hserver);
+ }
+
+ lock.Lock();
+ BindingFailed(index);
+ }
+
+ ASSERT(0);
+}
+
+void
+CMid::BindingFailed(
+ IN USHORT Index
+ )
+/*++
+
+Routine Description:
+
+ What a call on a binding handle associated with an index
+ returned from GetBinding() fails this routine must be
+ call before the next call to GetBinding() to update
+ the internal state.
+
+Arguments:
+
+ Index - An index updated by a previous call to GetBinding().
+
+
+Notes:
+
+ Maybe called with the gcsMidLock already held.
+
+Return Value:
+
+ None
+
+--*/
+{
+ USHORT newIndex;
+ PWSTR pwstrT = &_dsa.aStringArray[Index];
+
+ pwstrT = OrStringSearch(pwstrT, 0) + 1;
+
+ newIndex = pwstrT - _dsa.aStringArray;
+
+ CMutexLock lock(&gcsMidLock);
+
+ if (newIndex > _iStringBinding)
+ {
+ _iStringBinding = newIndex;
+ }
+}
+
diff --git a/private/ole32/dcomss/objex/mid.hxx b/private/ole32/dcomss/objex/mid.hxx
new file mode 100644
index 000000000..e6ad761ae
--- /dev/null
+++ b/private/ole32/dcomss/objex/mid.hxx
@@ -0,0 +1,208 @@
+/*++
+
+Copyright (c) 1995-1996 Microsoft Corporation
+
+Module Name:
+
+ Mid.hxx
+
+Abstract:
+
+ Class representing string bindings and security bindings for a particular
+ machine. Provides a mapping between the bindings and a local machine
+ unique ID for that machine.
+
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 12-13-95 Bits 'n pieces
+ MarioGo 02-01-96 Move binding handles out of mid.
+
+--*/
+
+#ifndef __MID_HXX
+#define __MID_HXX
+
+extern CRITICAL_SECTION gcsMidLock;
+
+class CMidKey : public CTableKey
+{
+ public:
+
+ CMidKey(DUALSTRINGARRAY *pdsa) : _pdsa(pdsa) { }
+
+ DWORD
+ Hash() {
+ return(dsaHash(_pdsa));
+ }
+
+ BOOL
+ Compare(CTableKey &tk) {
+ CMidKey &mk = (CMidKey &)tk;
+ return(dsaCompare(mk._pdsa, _pdsa));
+ }
+
+ BOOL operator==(DUALSTRINGARRAY &dsa){
+ return(dsaCompare(_pdsa, &dsa));
+ }
+
+ private:
+
+ DUALSTRINGARRAY *_pdsa;
+};
+
+class CMid : public CTableElement
+/*++
+
+Class Description:
+
+ Represents the local and remote machines. Each unique (different)
+ set of string bindings and security bindings are assigned a unique
+ local ID. This ID is used along with the OID and OXID of the remote
+ machine objects index these objects locally. Instances of this class
+ are referenced by CClientSets which are referenced by CClientOids.
+ This class is indexed by string and security bindings. There is no
+ index by MID.
+
+Members:
+
+ _id - The locally unique ID of this set of bindings.
+
+ _iStringBinding - Index into _dsa->aStringArray of the
+ compressed string binding used to create _hMachine.
+
+ _iSecurityBinding - Index into _dsaSecurityArray of the
+
+ _fLocal - TRUE if these are bindings for the local machine.
+
+ _fDynamic - TRUE if we believe the remote machine's OR
+ is not running in the endpoint mapper process.
+
+ _dsa - The set of compressed bindings.
+
+--*/
+{
+
+ public:
+
+ CMid(DUALSTRINGARRAY *pdsa,
+ BOOL fLocal,
+ ID OldMid = 0) :
+ _fLocal(fLocal),
+ _fDynamic(FALSE),
+ _iStringBinding(0),
+ _iSecurityBinding(0)
+ {
+ // this must be allocated to include the size of the embedded dsa.
+ dsaCopy(&_dsa, pdsa);
+
+ PWSTR pwstrT = &_dsa.aStringArray[_dsa.wSecurityOffset];
+
+ // Set _iSecurityBinding iff we find windows NT security in the
+ // dual string array.
+
+ while(*pwstrT)
+ {
+ if (*pwstrT == RPC_C_AUTHN_WINNT)
+ {
+ _iSecurityBinding = pwstrT - _dsa.aStringArray;
+ break;
+ }
+
+ pwstrT = OrStringSearch(pwstrT, 0) + 1;
+ }
+
+ if (OldMid)
+ {
+ _id = OldMid;
+ ASSERT(fLocal);
+ }
+ else
+ {
+ _id = AllocateId();
+ }
+ }
+
+ ~CMid() {
+ ASSERT(gpClientLock->HeldExclusive());
+
+ gpMidTable->Remove(this);
+ }
+
+ virtual DWORD
+ Hash() {
+ return(dsaHash(&_dsa));
+ }
+
+ virtual BOOL
+ Compare(CTableKey &tk) {
+ CMidKey &mk = (CMidKey &)tk;
+ return( mk == _dsa );
+ }
+
+ virtual BOOL
+ Compare(CONST CTableElement *pte) {
+ CMid *pmid = (CMid *)pte;
+ return(dsaCompare(&_dsa, &pmid->_dsa));
+ }
+
+ DUALSTRINGARRAY *
+ GetStrings() {
+ // Must be treated as read-only.
+ return(&_dsa);
+ }
+
+ BOOL IsSecure() {
+ // REVIEW V2/CAIRO, calling code will only user RPC_C_AUTHN_WINNT.
+ return(_fLocal == FALSE && _iSecurityBinding);
+ }
+
+ RPC_BINDING_HANDLE GetBinding(USHORT &index);
+
+ USHORT ProtseqOfServer(USHORT index) {
+ return(_dsa.aStringArray[index]);
+ }
+
+ BOOL IsLocal() {
+ return(_fLocal);
+ }
+
+ ID Id() {
+ return(_id);
+ }
+
+ void BindingFailed(USHORT index);
+
+ void UseDynamicEndpoints() {
+ _fDynamic = TRUE;
+ }
+
+ void SecurityFailed() {
+ // A call using security failed with a security related error
+ // and a futher call w/o security succeeded. Turn off security
+ // to this machine.
+ _iSecurityBinding = 0;
+ }
+
+#if DBG
+ PWSTR PrintableName() {
+ return(&_dsa.aStringArray[_iStringBinding + 1]);
+ }
+#endif
+
+ private:
+
+ ID _id;
+ USHORT _iStringBinding;
+ USHORT _iSecurityBinding;
+ BOOL _fLocal:1;
+ BOOL _fDynamic:1;
+ DUALSTRINGARRAY _dsa;
+};
+
+#endif // __MID_HXX
+
diff --git a/private/ole32/dcomss/objex/misc.cxx b/private/ole32/dcomss/objex/misc.cxx
new file mode 100644
index 000000000..1b6ee3539
--- /dev/null
+++ b/private/ole32/dcomss/objex/misc.cxx
@@ -0,0 +1,695 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Misc.cxx
+
+Abstract:
+
+ Initalization, Heap, debug, thread manager for OR
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-11-95 Bits 'n pieces
+
+--*/
+
+#include <or.hxx>
+
+BOOL fListened = FALSE;
+
+ORSTATUS
+StartListeningIfNecessary()
+/*++
+
+Routine Description:
+
+ If the process has not successfully listened to remote
+ protocols this routine will try do to so.
+
+ BUGBUG: Should really have a named event signaled by
+ the system when the network is started.
+
+ BUGBUG: Should interact with plug-n-play and DHCP better.
+
+Note:
+
+ Will not add ncacn_np to the list of supported Network OLE
+ protocols because RpcBindingServerFromClient() doesn't
+ work on named pipes and is required to unmarshal an in
+ interface pointer.
+
+Arguments:
+
+ n/a
+
+Return Value:
+
+ OR_OK - Success.
+
+ OR_NOMEM - Resource problems.
+
+--*/
+
+{
+ RPC_STATUS status;
+ PWSTR pwstr = gpwstrProtseqs;
+ USHORT id;
+
+ if (fListened == TRUE)
+ {
+ return(OR_OK);
+ }
+
+ gpClientLock->LockExclusive();
+
+ if (fListened == TRUE)
+ {
+ gpClientLock->UnlockExclusive();
+ return(OR_OK);
+ }
+
+ if (pwstr)
+ {
+ while(*pwstr)
+ {
+ id = GetProtseqId(pwstr);
+
+ if (0 != id)
+ {
+ status = UseProtseqIfNecessary(id);
+ if (status == RPC_S_OK)
+ {
+ fListened = TRUE;
+ }
+ }
+
+ pwstr = OrStringSearch(pwstr, 0) + 1;
+ }
+ }
+
+ if ( FALSE == fListened
+ && 0 != gLocalMid)
+ {
+ // Didn't manage to listen to anything new, no need to
+ // recompute all the global arrays.
+
+ gpClientLock->UnlockExclusive();
+ return(OR_OK);
+ }
+
+ // ??? limit to only those protseqs listed in the registry,
+ // if the another service used more protseqs they would show up here.
+
+ RPC_BINDING_VECTOR *pbv;
+ PWSTR pwstrT;
+ DUALSTRINGARRAY *pdsaT;
+ PWSTR *aAddresses;
+ USHORT *aProtseqs;
+ DWORD psaLen;
+ DWORD i;
+
+ status = RpcServerInqBindings(&pbv);
+
+ if (RPC_S_OK == status)
+ {
+ aAddresses = new PWSTR[pbv->Count];
+ aProtseqs = new USHORT[pbv->Count];
+
+ if ( !aAddresses
+ || !aProtseqs)
+ {
+ RpcBindingVectorFree(&pbv);
+ delete aAddresses; // 0 or allocated.
+ delete aProtseqs; // 0 or allocated.
+ status = OR_NOMEM;
+ }
+ }
+ else
+ status = OR_NOMEM;
+
+ if (status != OR_OK)
+ {
+ gpClientLock->UnlockExclusive();
+ return(status);
+ }
+
+ // Build array of protseqs id's and addresses we're listening to.
+
+ for(psaLen = 0, i = 0; i < pbv->Count; i++)
+ {
+ PWSTR pwstrStringBinding;
+
+ status = RpcBindingToStringBinding(pbv->BindingH[i], &pwstrStringBinding);
+ if (status != RPC_S_OK)
+ {
+ break;
+ }
+ ASSERT(pwstrStringBinding);
+
+ status = RpcStringBindingParse(pwstrStringBinding,
+ 0,
+ &pwstrT,
+ &aAddresses[i],
+ 0,
+ 0);
+
+ RPC_STATUS statusT = RpcStringFree(&pwstrStringBinding);
+ ASSERT(statusT == RPC_S_OK && pwstrStringBinding == 0);
+
+ if (status != RPC_S_OK)
+ {
+ break;
+ }
+
+ aProtseqs[i] = GetProtseqId(pwstrT);
+
+ status = RpcStringFree(&pwstrT);
+ ASSERT(status == RPC_S_OK && pwstrT == 0);
+
+ if (!IsLocal(aProtseqs[i]) && aProtseqs[i] != ID_NP)
+ {
+ // Only hand out remote non-named pipes protseqs.
+ psaLen += 1 + OrStringLen(aAddresses[i]) + 1;
+ }
+ }
+
+ if (status != RPC_S_OK)
+ {
+ delete aAddresses;
+ delete aProtseqs;
+ status = RpcBindingVectorFree(&pbv);
+ ASSERT(pbv == 0 && status == RPC_S_OK);
+ gpClientLock->UnlockExclusive();
+ return(status);
+ }
+
+ // string bindings final null, authn and authz service and two final nulls
+
+ if (psaLen == 0)
+ {
+ // No remote bindings
+ psaLen = 1;
+ }
+ psaLen += 1 + 2 + 2;
+
+ pdsaT = new(psaLen * sizeof(WCHAR)) DUALSTRINGARRAY;
+
+ pdsaT->wNumEntries = psaLen;
+ pdsaT->wSecurityOffset = psaLen - 4;
+ pwstrT = pdsaT->aStringArray;
+
+ for (i = 0; i < pbv->Count; i++)
+ {
+ if (!IsLocal(aProtseqs[i]) && aProtseqs[i] != ID_NP)
+ {
+ *pwstrT = aProtseqs[i];
+ pwstrT++;
+ OrStringCopy(pwstrT, aAddresses[i]);
+
+ pwstrT = OrStringSearch(pwstrT, 0) + 1; // next
+ }
+
+ status = RpcStringFree(&aAddresses[i]);
+ ASSERT(status == RPC_S_OK);
+ }
+
+ if (psaLen == 6)
+ {
+ // No remote bindings, put in first null.
+ pdsaT->aStringArray[0] = 0;
+ pwstrT++;
+ }
+
+ // Zero final terminator
+ *pwstrT = 0;
+
+ // Security authn service
+ pwstrT++;
+ *pwstrT = RPC_C_AUTHN_WINNT;
+
+ // Authz service, -1 means none
+ pwstrT++;
+ *pwstrT = -1;
+
+ // Final, final NULLS
+ pwstrT++;
+ pwstrT[0] = 0;
+ pwstrT[1] = 0;
+
+ ASSERT(dsaValid(pdsaT));
+
+ USHORT cRemoteProtseqs = 0;
+
+ // Convert aProtseqs into remote only array of protseqs and count them.
+ for(i = 0; i < pbv->Count; i++)
+ {
+ if (IsLocal(aProtseqs[i]) == FALSE && aProtseqs[i] != ID_NP)
+ {
+ aProtseqs[cRemoteProtseqs] = aProtseqs[i];
+ cRemoteProtseqs++;
+ }
+ }
+
+ delete aAddresses;
+ status = RpcBindingVectorFree(&pbv);
+ ASSERT(pbv == 0 && status == RPC_S_OK);
+
+ CMid *pMid = new(pdsaT->wNumEntries * sizeof(WCHAR)) CMid(pdsaT, TRUE, gLocalMid);
+ if (pMid)
+ {
+ gpMidTable->Add(pMid);
+ }
+ else
+ {
+ delete pdsaT;
+ delete aProtseqs;
+ gpClientLock->UnlockExclusive();
+ return(OR_NOMEM);
+ }
+
+ // Update globals
+ aMyProtseqs = aProtseqs;
+ cMyProtseqs = cRemoteProtseqs;
+ pdsaMyBindings = pdsaT;
+ gLocalMid = pMid->Id();
+
+ gpClientLock->UnlockExclusive();
+
+ return(OR_OK);
+}
+
+DWORD
+RegisterAuthInfoIfNecessary()
+{
+ DWORD Status;
+
+ //
+ // No locks, doesn't matter if we call RegisterAuthInfo more than
+ // once by chance.
+ //
+
+ if ( gfRegisteredAuthInfo )
+ return ERROR_SUCCESS;
+
+ Status = RpcServerRegisterAuthInfo(NULL,
+ RPC_C_AUTHN_WINNT,
+ NULL,
+ NULL);
+
+ if ( Status == RPC_S_OK )
+ gfRegisteredAuthInfo = TRUE;
+
+ if ( Status == RPC_S_UNKNOWN_AUTHN_SERVICE )
+ {
+ Status = RPC_S_OK;
+ }
+
+ return Status;
+}
+
+//
+// Local ID allocation
+//
+
+
+ID
+AllocateId(
+ IN LONG cRange
+ )
+/*++
+
+Routine Description:
+
+ Allocates a unique local ID.
+
+ This id is 64bits. The low 32 bits are a sequence number which
+ is incremented with each call. The high 32bits are seconds
+ since 1980. The ID of 0 is not used.
+
+Limitations:
+
+ No more then 2^32 IDs can be generated in a given second without a duplicate.
+
+ When the time stamp overflows, once every >126 years, the sequence numbers
+ are likely to be generated in such a way as to collide with those from 126
+ years ago.
+
+ There is no prevision in the code to deal with overflow or duplications.
+
+Arguments:
+
+ cRange - Number to allocate in sequence, default is 1.
+
+Return Value:
+
+ A 64bit id.
+
+--*/
+{
+ static LONG sequence = 1;
+ FILETIME ft;
+ LARGE_INTEGER id;
+ DWORD seconds;
+ BOOL fSuccess;
+
+ ASSERT(cRange > 0 && cRange < 11);
+
+ GetSystemTimeAsFileTime(&ft);
+
+ fSuccess = RtlTimeToSecondsSince1980((PLARGE_INTEGER)&ft,
+ &seconds);
+
+ ASSERT(fSuccess); // Only fails when time is <1980 or >2115
+
+ do
+ {
+ id.HighPart = seconds;
+ id.LowPart = InterlockedExchangeAdd(&sequence, cRange);
+ }
+ while (id.QuadPart == 0 );
+
+ return(id.QuadPart);
+}
+
+//
+// Global Heaps
+//
+
+HANDLE hProcessHeap;
+HANDLE hObjHeap;
+HANDLE hSetHeap;
+
+//
+// The OR uses three heaps:
+//
+// The process heap is used for MIDL_user_allocate and free. Objects in
+// this heap are short lived. It maybe accessed by several threads at
+// once.
+//
+// The object heap is used for PROCESS, OXID and OID structures.
+// This heap is serialized and is used for long lived objects.
+//
+// The set heap is used for SET objects (both local and remote).
+// Access is serialized with the SET table lock. Objects are long
+// lived and accessed regularly (every ping period).
+//
+
+#if DBG
+typedef struct DbgBlock {
+ struct DbgBlock *Next;
+ struct DbgBlock *Previous;
+ DWORD Tag;
+ DWORD Size;
+ // Data // User sized, no pad.
+ UCHAR Guard[4]; // after the data in real block.
+ } DBG_BLOCK;
+
+DBG_BLOCK *OrDbgHeapList = 0;
+CRITICAL_SECTION DbgHeapLock;
+#endif
+
+//
+
+ORSTATUS InitHeaps()
+{
+ ORSTATUS Status = OR_OK;
+#if DBG
+ static int heapinit = 0;
+ ASSERT(!heapinit);
+ heapinit++;
+#endif
+
+ hProcessHeap = GetProcessHeap();
+
+ ASSERT(hProcessHeap);
+
+ hSetHeap = 0; // HeapCreate(HEAP_NO_SERIALIZE, 2*4096 - 100, 0);
+
+ hObjHeap = HeapCreate(0, 2*4096 - 100, 0);
+
+
+ if (!hObjHeap)
+ {
+ // Not catastrophic
+ hObjHeap = hProcessHeap;
+ }
+
+ if (!hSetHeap)
+ {
+ // Not catastrophic
+ hSetHeap = hProcessHeap;
+ }
+
+#if DBG
+ InitializeCriticalSection(&DbgHeapLock);
+#endif
+
+ return(Status);
+}
+
+#if DBG
+void DbgCheckHeap(BOOL quick = TRUE)
+{
+ DBG_BLOCK *pblock;
+ UINT size;
+ INT count = -1;
+ if (quick)
+ {
+ count = 3;
+ }
+
+ CMutexLock lock(&DbgHeapLock);
+
+ pblock = OrDbgHeapList;
+
+ while(pblock && count != 0)
+ {
+ size = pblock->Size;
+ ASSERT(pblock->Guard[size+0] == 0xce);
+ ASSERT(pblock->Guard[size+1] == 0xfa);
+ ASSERT(pblock->Guard[size+2] == 0xbe);
+ ASSERT(pblock->Guard[size+3] == 0xba);
+ ASSERT((pblock->Tag & 0xFFFF0000) == 0xA1A10000);
+ if (pblock->Next)
+ {
+ ASSERT(pblock->Next->Previous == pblock);
+ }
+ pblock = pblock->Next;
+ count--;
+ }
+}
+#endif
+
+inline LPVOID OrAlloc(UINT size, USHORT tag)
+{
+ LPVOID p;
+ HANDLE h;
+#if DBG
+ DBG_BLOCK *pblock;
+ DbgCheckHeap();
+ ASSERT( ((LONG)size) >= 0 );
+ ASSERT( ((ULONG)size) < (ULONG)(1<<30) );
+ size+= sizeof(struct DbgBlock);
+#endif
+
+ switch(tag)
+ {
+ case PROC_TAG:
+ h = hProcessHeap;
+ break;
+ case OBJ_TAG:
+ h = hObjHeap;
+ break;
+ case SET_TAG:
+ h = hSetHeap;
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ p = HeapAlloc(h, 0, size);
+
+#if DBG
+ size -= sizeof(struct DbgBlock);
+ if (p)
+ {
+ pblock = (DBG_BLOCK *)p;
+ pblock->Size = size;
+ pblock->Tag = 0xA1A10000 | tag;
+ pblock->Guard[size+0] = 0xce;
+ pblock->Guard[size+1] = 0xfa;
+ pblock->Guard[size+2] = 0xbe;
+ pblock->Guard[size+3] = 0xba;
+ pblock->Previous = 0;
+
+ CMutexLock lock(&DbgHeapLock);
+ pblock->Next = OrDbgHeapList;
+ if (pblock->Next)
+ {
+ pblock->Next->Previous = pblock;
+ }
+ OrDbgHeapList = pblock;
+ p = &pblock->Guard[0];
+ }
+ else
+ {
+ p = NULL;
+ }
+#endif
+
+ return(p);
+}
+
+inline void OrFree(PVOID p, USHORT tag)
+{
+ HANDLE h;
+
+#if DBG
+ DBG_BLOCK *pblock;
+
+ ASSERT(p);
+ p = pblock = (DBG_BLOCK *)(((UCHAR *)p) - sizeof(DBG_BLOCK) + 4);
+ ASSERT(pblock->Tag == (0xA1A10000 | tag));
+ DbgCheckHeap();
+
+ CMutexLock lock(&DbgHeapLock);
+ pblock->Tag = 0xFEFE0000 | ~tag;
+
+ if (pblock == OrDbgHeapList)
+ {
+ OrDbgHeapList = OrDbgHeapList->Next;
+ }
+ if (pblock->Next)
+ {
+ pblock->Next->Previous = pblock->Previous;
+ }
+ if (pblock->Previous)
+ {
+ pblock->Previous->Next = pblock->Next;
+ }
+ lock.Unlock();
+#endif
+
+ switch(tag)
+ {
+ case PROC_TAG:
+ h = hProcessHeap;
+ break;
+ case OBJ_TAG:
+ h = hObjHeap;
+ break;
+ case SET_TAG:
+ h = hSetHeap;
+ break;
+ default:
+ ASSERT(0);
+ }
+
+ HeapFree(h, 0, p);
+
+ return;
+}
+
+void * _CRTAPI1
+operator new (
+ IN size_t size
+ )
+{
+ return(OrAlloc(size, OBJ_TAG));
+}
+
+void * _CRTAPI1
+operator new (
+ IN size_t size,
+ IN size_t extra
+ )
+{
+ return(OrAlloc(size + extra, OBJ_TAG));
+}
+
+void _CRTAPI1
+operator delete (
+ IN void * obj
+ )
+{
+ if (obj == 0) return;
+ OrFree(obj, OBJ_TAG);
+}
+
+
+//
+// Debug helper(s)
+//
+
+#if DBG
+
+int __cdecl __RPC_FAR ValidateError(
+ IN ORSTATUS Status,
+ IN ...)
+/*++
+Routine Description
+
+ Tests that 'Status' is one of an expected set of error codes.
+ Used on debug builds as part of the VALIDATE() macro.
+
+Example:
+
+ VALIDATE( (Status,
+ OR_BADSET,
+ // more error codes here
+ OR_OK,
+ 0) // list must be terminated with 0
+ );
+
+ This function is called with the OrStatus and expected errors codes
+ as parameters. If OrStatus is not one of the expected error
+ codes and it not zero a message will be printed to the debugger
+ and the function will return false. The VALIDATE macro ASSERT's the
+ return value.
+
+Arguments:
+
+ Status - Status code in question.
+
+ ... - One or more expected status codes. Terminated with 0 (OR_OK).
+
+Return Value:
+
+ TRUE - Status code is in the list or the status is 0.
+
+ FALSE - Status code is not in the list.
+
+--*/
+{
+ RPC_STATUS CurrentStatus;
+ va_list Marker;
+
+ if (Status == 0) return(TRUE);
+
+ va_start(Marker, Status);
+
+ while(CurrentStatus = va_arg(Marker, RPC_STATUS))
+ {
+ if (CurrentStatus == Status)
+ {
+ return(TRUE);
+ }
+ }
+
+ va_end(Marker);
+
+ OrDbgPrint(("OR Assertion: unexpected failure %lu (0x%p)\n",
+ (unsigned long)Status, (unsigned long)Status));
+
+ return(FALSE);
+}
+
+#endif
+
diff --git a/private/ole32/dcomss/objex/misc.hxx b/private/ole32/dcomss/objex/misc.hxx
new file mode 100644
index 000000000..32cd5fc90
--- /dev/null
+++ b/private/ole32/dcomss/objex/misc.hxx
@@ -0,0 +1,46 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Misc.hxx
+
+Abstract:
+
+ Header for random helpers functions.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-11-95 Bits 'n pieces
+
+--*/
+
+#ifndef __MISC_HXX
+#define __MISC_HXX
+
+extern ORSTATUS StartListeningIfNecessary();
+extern ORSTATUS InitHeaps(void);
+
+extern ID AllocateId(LONG cRange = 1);
+
+extern error_status_t ResolveClientOXID(
+ handle_t hClient,
+ PHPROCESS phProcess,
+ OXID *poxidServer,
+ DUALSTRINGARRAY *pdsaServerBindings,
+ LONG fApartment,
+ USHORT wProtseqId,
+ OXID_INFO *poxidInfo,
+ MID *pDestinationMid );
+
+extern void * _CRTAPI1 operator new(size_t);
+extern void * _CRTAPI1 operator new(size_t,size_t);
+extern void _CRTAPI1 operator delete(void *);
+
+#endif // __MISC_HXX
+
diff --git a/private/ole32/dcomss/objex/objex.cxx b/private/ole32/dcomss/objex/objex.cxx
new file mode 100644
index 000000000..3906debd2
--- /dev/null
+++ b/private/ole32/dcomss/objex/objex.cxx
@@ -0,0 +1,506 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ObjEx.cxx
+
+Abstract:
+
+ Main entry point for the object exporter service.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-28-95 Bits 'n pieces
+
+--*/
+
+
+#include <or.hxx>
+
+extern "C"
+{
+#define SECURITY_WIN32 // Used by sspi.h
+#include <sspi.h> // EnumerateSecurityPackages
+}
+
+//
+// Process globals - read-only except during init.
+//
+
+// MID of the string bindings for this machine.
+MID gLocalMid = 0;
+
+// Contains the buffer of protseq's to listen on from the registry
+PWSTR gpwstrProtseqs = 0;
+
+// Contains compressed remote protseqs and network addresses for this process.
+DUALSTRINGARRAY *pdsaMyBindings = 0;
+
+// Number of remote protseqs used by this process.
+USHORT cMyProtseqs = 0;
+
+// ProtseqIds of the remote protseqs used by this process.
+USHORT *aMyProtseqs = 0;
+
+//
+// Process globals - read-write
+//
+
+CSharedLock *gpServerLock = 0;
+CSharedLock *gpClientLock = 0;
+
+CHashTable *gpServerOxidTable = 0;
+
+CHashTable *gpClientOxidTable = 0;
+CPList *gpClientOxidPList = 0;
+
+CHashTable *gpServerOidTable = 0;
+CServerOidPList *gpServerOidPList = 0;
+
+CHashTable *gpClientOidTable = 0;
+
+CServerSetTable *gpServerSetTable = 0;
+
+CHashTable *gpClientSetTable = 0;
+CPList *gpClientSetPList = 0;
+
+CHashTable *gpMidTable = 0;
+
+CList *gpTokenList = 0;
+
+DWORD gNextThreadID = 1;
+
+//+-------------------------------------------------------------------------
+//
+// Function: ComputeSecurity
+//
+// Synopsis: Looks up some registry keys and enumerates the security
+// packages on this machine.
+//
+//--------------------------------------------------------------------------
+// These variables hold values read out of the registry and cached.
+// s_fEnableDCOM is false if DCOM is disabled. The others contain
+// authentication information for legacy applications.
+BOOL s_fEnableDCOM;
+DWORD s_lAuthnLevel;
+DWORD s_lImpLevel;
+BOOL s_fMutualAuth;
+BOOL s_fSecureRefs;
+WCHAR *s_pLegacySecurity;
+
+// s_sServerSvc is a list of security providers that OLE servers can use.
+// s_aClientSvc is a list of security providers that OLE clients can use.
+// The difference is that Chicago only supports the client side of some
+// security providers and OLE servers must know how to determine the
+// principal name for the provider. Clients get the principal name from
+// the server.
+DWORD s_cServerSvc = 0;
+USHORT *s_aServerSvc = NULL;
+DWORD s_cClientSvc = 0;
+USHORT *s_aClientSvc = NULL;
+
+extern void DbgCheckHeap( BOOL );
+void ComputeSecurity()
+{
+#if DBG==1
+ DbgCheckHeap( TRUE );
+#endif
+
+ SecPkgInfo *pAllPkg;
+ SecPkgInfo *pNext;
+ HRESULT hr;
+ DWORD i;
+ DWORD lMaxLen;
+ HKEY hKey;
+ DWORD lType;
+ DWORD lData;
+ DWORD lDataSize;
+
+ // Get the list of security packages.
+ s_cClientSvc = 0;
+ s_cServerSvc = 0;
+ hr = EnumerateSecurityPackages( &lMaxLen, &pAllPkg );
+ if (hr == 0)
+ {
+ // Allocate memory for both service lists.
+ s_aServerSvc = new USHORT[lMaxLen];
+ s_aClientSvc = new USHORT[lMaxLen];
+ if (s_aServerSvc == NULL || s_aClientSvc == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ delete s_aServerSvc;
+ delete s_aClientSvc;
+ s_aServerSvc = NULL;
+ s_aClientSvc = NULL;
+ }
+ else
+ {
+ // Check all packages.
+ pNext = pAllPkg;
+ for (i = 0; i < lMaxLen; i++)
+ {
+ // Determine if clients can use the package.
+ if ((pNext->fCapabilities & (SECPKG_FLAG_DATAGRAM |
+ SECPKG_FLAG_CONNECTION)))
+ {
+ s_aClientSvc[s_cClientSvc++] = pNext->wRPCID;
+ }
+
+ // BUGBUG - Add flag for NT principal names
+ // Determine is servers can use the package.
+ if ( (pNext->fCapabilities & (SECPKG_FLAG_DATAGRAM |
+ SECPKG_FLAG_CONNECTION)) &&
+ ~(pNext->fCapabilities & (SECPKG_FLAG_CLIENT_ONLY)))
+ {
+ s_aServerSvc[s_cServerSvc++] = pNext->wRPCID;
+ }
+ pNext++;
+ }
+ }
+
+ // Release the list of security packages.
+ FreeContextBuffer( pAllPkg );
+ }
+
+ // Set all the security flags to their default values.
+#ifdef _CAIRO_
+ s_fEnableDCOM = TRUE;
+#else
+ s_fEnableDCOM = FALSE;
+#endif
+ s_pLegacySecurity = NULL;
+ s_lAuthnLevel = RPC_C_AUTHN_LEVEL_CONNECT;
+ s_lImpLevel = RPC_C_IMP_LEVEL_IDENTIFY;
+ s_fMutualAuth = FALSE;
+ s_fSecureRefs = FALSE;
+
+ // Open the security key.
+ hr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\OLE",
+ NULL, KEY_QUERY_VALUE, &hKey );
+ if (hr != ERROR_SUCCESS)
+ return;
+
+ // Query the value for DisableDCOM.
+ lDataSize = sizeof(lData );
+ hr = RegQueryValueEx( hKey, L"EnableDCOM", NULL, &lType,
+ (unsigned char *) &lData, &lDataSize );
+ if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0)
+ {
+ if (*((WCHAR *) &lData) == L'y' ||
+ *((WCHAR *) &lData) == L'Y')
+ s_fEnableDCOM = TRUE;
+ }
+
+ // Query the value for the legacy services.
+ lDataSize = 0;
+ hr = RegQueryValueEx( hKey, L"LegacyAuthenticationService", NULL,
+ &lType, NULL, &lDataSize );
+ if (hr == ERROR_SUCCESS && lType == REG_BINARY &&
+ lDataSize >= sizeof(SECURITYBINDING))
+ {
+ s_pLegacySecurity = (WCHAR *) new BYTE[lDataSize];
+ if (s_pLegacySecurity != NULL)
+ {
+ hr = RegQueryValueEx( hKey, L"LegacyAuthenticationService", NULL,
+ &lType, (unsigned char *) s_pLegacySecurity,
+ &lDataSize );
+
+ // Verify that the data is a security binding.
+ if (hr != ERROR_SUCCESS ||
+ lType != REG_BINARY ||
+ lDataSize < sizeof(SECURITYBINDING) ||
+ s_pLegacySecurity[1] != 0 ||
+ s_pLegacySecurity[(lDataSize >> 1) - 1] != 0)
+ {
+ delete s_pLegacySecurity;
+ s_pLegacySecurity = NULL;
+ }
+ }
+ }
+
+ // Query the value for the authentication level.
+ lDataSize = sizeof(lData);
+ hr = RegQueryValueEx( hKey, L"LegacyAuthenticationLevel", NULL,
+ &lType, (unsigned char *) &lData, &lDataSize );
+ if (hr == ERROR_SUCCESS && lType == REG_DWORD)
+ {
+ s_lAuthnLevel = lData;
+ }
+
+ // Query the value for the impersonation level.
+ lDataSize = sizeof(lData);
+ hr = RegQueryValueEx( hKey, L"LegacyImpersonationLevel", NULL,
+ &lType, (unsigned char *) &lData, &lDataSize );
+ if (hr == ERROR_SUCCESS && lType == REG_DWORD)
+ {
+ s_lImpLevel = lData;
+ }
+
+ // Query the value for mutual authentication.
+ lDataSize = sizeof(lData);
+ hr = RegQueryValueEx( hKey, L"LegacyMutualAuthentication", NULL,
+ &lType, (unsigned char *) &lData, &lDataSize );
+ if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0)
+ {
+ if (*((WCHAR *) &lData) == L'y' ||
+ *((WCHAR *) &lData) == L'Y')
+ s_fMutualAuth = TRUE;
+ }
+
+ // Query the value for secure interface references.
+ lDataSize = sizeof(lData);
+ hr = RegQueryValueEx( hKey, L"LegacySecureReferences", NULL,
+ &lType, (unsigned char *) &lData, &lDataSize );
+ if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0)
+ {
+ if (*((WCHAR *) &lData) == L'y' ||
+ *((WCHAR *) &lData) == L'Y')
+ s_fSecureRefs = TRUE;
+ }
+
+ // Close the registry key.
+ RegCloseKey( hKey );
+#if DBG==1
+ DbgCheckHeap( TRUE );
+#endif
+
+}
+
+//
+// Startup
+//
+
+static CONST PWSTR gpwstrProtocolsPath = L"Software\\Microsoft\\Rpc";
+static CONST PWSTR gpwstrProtocolsValue = L"DCOM Protocols";
+
+DWORD StartObjectExporter(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Starts the object resolver service.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ORSTATUS status;
+ int i;
+ DWORD tid;
+ HANDLE hThread;
+ RPC_BINDING_VECTOR *pbv;
+
+ status = InitHeaps();
+
+ if (status != RPC_S_OK)
+ {
+ return(OR_NOMEM);
+ }
+
+ InitializeCriticalSection(&gcsFastProcessLock);
+ InitializeCriticalSection(&gcsProcessManagerLock);
+ InitializeCriticalSection(&gcsTokenLock);
+ InitializeCriticalSection(&gcsMidLock);
+
+ // Allocate locks
+ gpClientLock = new CSharedLock(status);
+ gpServerLock = new CSharedLock(status);
+
+ if (OR_OK != status)
+ {
+ return(OR_NOMEM);
+ }
+
+ // Lookup security data.
+ ComputeSecurity();
+ UpdateState(SERVICE_START_PENDING);
+
+ // Allocate tables
+
+ status = OR_OK;
+
+ // Assume 16 exporting processes/threads.
+ gpServerOxidTable = new CHashTable(status, DEBUG_MIN(16,4));
+ if (status != OR_OK)
+ {
+ delete gpServerOxidTable;
+ gpServerOxidTable = 0;
+ }
+
+ // Assume 11 exported OIDs per process/thread.
+ gpServerOidTable = new CHashTable(status, 11*(DEBUG_MIN(16,4)));
+ if (status != OR_OK)
+ {
+ delete gpServerOidTable;
+ gpServerOidTable = 0;
+ }
+
+ gpServerSetTable = new CServerSetTable(status);
+ if (status != OR_OK)
+ {
+ delete gpServerSetTable;
+ gpServerSetTable = 0;
+ }
+
+ // Assume < 16 imported OXIDs
+ gpClientOxidTable = new CHashTable(status, DEBUG_MIN(16,4));
+ if (status != OR_OK)
+ {
+ delete gpClientOxidTable;
+ gpClientOxidTable = 0;
+ }
+
+ // Assume an average of 4 imported object ids per imported oxid
+ gpClientOidTable = new CHashTable(status, 4*DEBUG_MIN(16,4));
+ if (status != OR_OK)
+ {
+ delete gpClientOidTable;
+ gpClientOidTable = 0;
+ }
+
+ // Assume <16 servers (remote machines) in use per client.
+ gpClientSetTable = new CHashTable(status, DEBUG_MIN(16,4));
+ if (status != OR_OK)
+ {
+ delete gpClientSetTable;
+ gpClientSetTable = 0;
+ }
+
+ gpMidTable = new CHashTable(status, DEBUG_MIN(16,2));
+ if (status != OR_OK)
+ {
+ delete gpMidTable;
+ gpMidTable = 0;
+ }
+
+
+ // Allocate lists
+ gpClientOxidPList = new CPList(BasePingInterval);
+ gpServerOidPList = new CServerOidPList();
+ gpClientSetPList = new CPList(BasePingInterval);
+ gpTokenList = new CList();
+ gpProcessList = new CBList(DEBUG_MIN(128,4));
+
+ if ( status != OR_OK
+ || !gpServerLock
+ || !gpClientLock
+ || !gpServerOxidTable
+ || !gpClientOxidTable
+ || !gpClientOxidPList
+ || !gpServerOidTable
+ || !gpServerOidPList
+ || !gpClientOidTable
+ || !gpMidTable
+ || !gpServerSetTable
+ || !gpClientSetTable
+ || !gpClientSetPList
+ || !gpTokenList
+ || !gpProcessList
+ )
+ {
+ return(OR_NOMEM);
+ }
+
+ // Read protseqs from the registry
+
+ DWORD dwType;
+ DWORD dwLenBuffer = 118;
+ HKEY hKey;
+
+ status =
+ RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ gpwstrProtocolsPath,
+ 0,
+ KEY_READ,
+ &hKey);
+
+ ASSERT(gpwstrProtseqs == 0);
+
+ if (status == ERROR_SUCCESS)
+ {
+ do
+ {
+ delete gpwstrProtseqs;
+ gpwstrProtseqs = new WCHAR[(dwLenBuffer + 1 )/2];
+ if (gpwstrProtseqs)
+ {
+ status = RegQueryValueEx(hKey,
+ gpwstrProtocolsValue,
+ 0,
+ &dwType,
+ (PBYTE)gpwstrProtseqs,
+ &dwLenBuffer
+ );
+ }
+ else
+ {
+ return(OR_NOMEM);
+ }
+
+ }
+ while (status == ERROR_MORE_DATA);
+
+ RegCloseKey(hKey);
+ }
+
+ if ( status != ERROR_SUCCESS
+ || dwType != REG_MULTI_SZ )
+ {
+ OrDbgPrint(("OR: No protseqs configured\n"));
+ delete gpwstrProtseqs;
+ gpwstrProtseqs = 0;
+ }
+
+ // Always listen to local protocols
+ // If this fails, the service should fail.
+ status = UseProtseqIfNecessary(GetProtseqId(L"ncalrpc"));
+ if (status != RPC_S_OK)
+ {
+ return(status);
+ }
+
+ UpdateState(SERVICE_START_PENDING);
+
+ // Construct remote protseq id and compressed binding arrays.
+
+ status = StartListeningIfNecessary();
+
+ if (status != OR_OK)
+ {
+ return(status);
+ }
+
+ UpdateState(SERVICE_START_PENDING);
+
+ // Register OR server interfaces.
+
+ status =
+ RpcServerRegisterIf(_ILocalObjectExporter_ServerIfHandle, 0, 0);
+
+ ASSERT(status == RPC_S_OK);
+
+ status =
+ RpcServerRegisterIf(_IObjectExporter_ServerIfHandle, 0, 0);
+
+ ASSERT(status == RPC_S_OK);
+
+ return(status);
+}
+
+
+
diff --git a/private/ole32/dcomss/objex/or.h b/private/ole32/dcomss/objex/or.h
new file mode 100644
index 000000000..65c098810
--- /dev/null
+++ b/private/ole32/dcomss/objex/or.h
@@ -0,0 +1,130 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ or.h
+
+Abstract:
+
+ General include file for C things the OR. This file is pre-compiled.
+
+Author:
+
+ Mario Goertzel [mariogo] Feb-10-95
+
+Revision History:
+
+--*/
+
+#ifndef __OR_H
+#define __OR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <dcomss.h>
+
+#include <stddef.h>
+#include <malloc.h> // alloca
+
+#include <lclor.h> // Local OR if from private\dcomidl
+#include <objex.h> // Remote OR if from private\dcomidl
+#include <orcb.h> // Callback if from private\dcomidl
+#include <rawodeth.h> // Raw RPC -> ORPC OID rundown interface
+
+#define IN
+#define OUT
+#define CONST const
+
+#define OrStringCompare(str1, str2, len) wcscmp((str1), (str2), (len))
+#define OrStringLen(str) wcslen(str)
+#define OrStringCat(str1, str2) wcscat((str1), (str2))
+#define OrStringCopy(str1, str2) wcscpy((str1), (str2))
+#define OrMemorySet(p, value, len) memset((p), (value), (len))
+#define OrMemoryCompare(p1, p2, len) memcmp((p1), (p2), (len))
+#define OrMemoryCopy(dest, src, len) memcpy((dest), (src), (len))
+// OrStringSearch in or.hxx
+
+//
+// The OR uses Win32 (RPC) error codes.
+//
+
+typedef LONG ORSTATUS;
+
+// When the OR code asigns and error it uses
+// one of the following mappings:
+// There are no internal error codes.
+
+#define OR_OK RPC_S_OK
+#define OR_NOMEM RPC_S_OUT_OF_MEMORY
+#define OR_NORESOURCE RPC_S_OUT_OF_RESOURCES
+#define OR_NOACCESS ERROR_ACCESS_DENIED
+#define OR_BADOXID OR_INVALID_OXID
+#define OR_BADOID OR_INVALID_OID
+#define OR_BADSET OR_INVALID_SET
+#define OR_NOSERVER RPC_S_SERVER_UNAVAILABLE
+#define OR_BADPARAM ERROR_INVALID_PARAMETER
+
+// Should NEVER be seen outside the OR.
+#define OR_BUGBUG RPC_S_INTERNAL_ERROR
+#define OR_INTERNAL_ERROR RPC_S_INTERNAL_ERROR
+
+// Internal codes used to indicate a special event.
+#define OR_I_RETRY 0xC0210051UL
+#define OR_I_NOPROTSEQ 0xC0210052UL
+
+#define UNUSED(_x_) ((void *)(_x_))
+
+#if DBG
+
+#define DEBUG_MIN(a,b) (min((a),(b)))
+
+extern int __cdecl ValidateError(
+ IN ORSTATUS Status,
+ IN ...);
+
+
+#define VALIDATE(X) if (!ValidateError X) ASSERT(0);
+
+#define OrDbgPrint(X) DbgPrint X
+
+#if DBG_DETAIL
+#define OrDbgDetailPrint(X) DbgPrint X
+#undef ASSERT
+#define ASSERT( exp ) \
+ if (! (exp) ) \
+ { \
+ DbgPrint("OR: Assertion failed: %s(%d) %s\n", __FILE__, __LINE__, #exp); \
+ DebugBreak(); \
+ }
+#else // DETAIL
+#define OrDbgDetailPrint(X)
+// default ASSERT
+#endif // DETAIL
+
+#else // DBG
+#define DEBUG_MIN(a,b) (max((a),(b)))
+#define VALIDATE(X)
+#define OrDbgPrint(X)
+#define OrDbgDetailPrint(X)
+#endif // DBG
+
+#define PROC_TAG (USHORT)0xaaaa // From process heap
+#define OBJ_TAG (USHORT)0xbbbb // From general serialized heap
+#define SET_TAG (USHORT)0xcccc // From setid's non-serialized heap
+
+extern LPVOID OrAlloc(UINT size, USHORT tag);
+extern void OrFree(LPVOID p, USHORT tag);
+
+extern DWORD ObjectExporterWorkerThread(LPVOID);
+extern DWORD ObjectExporterTaskThread(LPVOID);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __OR_H
+
diff --git a/private/ole32/dcomss/objex/or.hxx b/private/ole32/dcomss/objex/or.hxx
new file mode 100644
index 000000000..f2c4e90ed
--- /dev/null
+++ b/private/ole32/dcomss/objex/or.hxx
@@ -0,0 +1,153 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ or.hxx
+
+Abstract:
+
+ C++ include for C++ OR modules.
+
+Author:
+
+ Mario Goertzel [mariogo] Feb-10-95
+
+Revision History:
+
+--*/
+
+#ifndef __OR_HXX
+#define __OR_HXX
+
+#include <or.h>
+
+// Protcol defined timeouts
+
+const unsigned short BasePingInterval = 120;
+const unsigned short BaseNumberOfPings = 3;
+const unsigned short BaseTimeoutInterval = (BasePingInterval * BaseNumberOfPings);
+
+// Well known tower IDs
+
+const unsigned short ID_LPC = 0x10; // ncalrpc, IsLocal() == TRUE
+const unsigned short ID_NP = 0x0F; // ncacn_np, IsLocal() == FALSE
+
+//
+// Globals
+//
+
+extern ID gLocalMid; // MID of the string bindings of this machine.
+
+// Building blocks
+
+#include <time.hxx>
+#include <locks.hxx>
+#include <misc.hxx>
+#include <callid.hxx>
+#include <blist.hxx>
+#include <refobj.hxx>
+#include <list.hxx>
+#include <plist.hxx>
+#include <string.hxx>
+#include <gentable.hxx>
+#include <idtable.hxx>
+
+//
+// Class forward declarations
+//
+
+class CProcess;
+class CToken;
+
+class CServerSet;
+class CServerOxid;
+class CServerOid;
+
+class CClientSet;
+class CClientOxid;
+class CClientOid;
+
+class CServerSetTable;
+
+//
+// Global tables, plists and locks
+//
+
+extern CSharedLock *gpServerLock;
+extern CSharedLock *gpClientLock;
+
+extern CHashTable *gpServerOidTable;
+extern CServerOidPList *gpServerOidPList;
+
+extern CHashTable *gpClientOidTable;
+
+extern CHashTable *gpServerOxidTable;
+
+extern CHashTable *gpClientOxidTable;
+extern CPList *gpClientOxidPList;
+
+extern CServerSetTable *gpServerSetTable;
+
+extern CHashTable *gpClientSetTable;
+extern CPList *gpClientSetPList;
+
+extern CList *gpTokenList;
+
+extern CHashTable *gpMidTable;
+
+extern DWORD gNextThreadID;
+
+// Headers which may use globals
+
+#include <token.hxx>
+#include <process.hxx>
+#include <mid.hxx>
+
+#include <cset.hxx>
+#include <coxid.hxx>
+#include <coid.hxx>
+
+#include <sset.hxx>
+#include <soxid.hxx>
+#include <soid.hxx>
+
+//
+// REG_MULTI_SZ array of protseqs to listen on.
+//
+
+extern PWSTR gpwstrProtseqs;
+//
+// Compressed string bindings and security bindings to this OR.
+//
+
+extern DUALSTRINGARRAY *pdsaMyBindings;
+
+//
+// Count and array of remote protseq's used by this OR.
+//
+
+extern USHORT cMyProtseqs;
+extern USHORT *aMyProtseqs;
+
+//
+// Security data passed to processes on connect.
+//
+
+extern BOOL s_fEnableDCOM;
+extern WCHAR *s_pLegacySecurity;
+extern DWORD s_lAuthnLevel;
+extern DWORD s_lImpLevel;
+extern BOOL s_fMutualAuth;
+extern BOOL s_fSecureRefs;
+extern DWORD s_cServerSvc;
+extern USHORT *s_aServerSvc;
+extern DWORD s_cClientSvc;
+extern USHORT *s_aClientSvc;
+
+#pragma hdrstop
+
+#endif // __OR_HXX
+
+
diff --git a/private/ole32/dcomss/objex/orclnt.cxx b/private/ole32/dcomss/objex/orclnt.cxx
new file mode 100644
index 000000000..00603d1e8
--- /dev/null
+++ b/private/ole32/dcomss/objex/orclnt.cxx
@@ -0,0 +1,799 @@
+/*++
+
+Copyright (c) 1995-1996 Microsoft Corporation
+
+Module Name:
+
+ OrClnt.cxx
+
+Abstract:
+
+ Object resolver client side class implementations. CClientOxid, CClientOid,
+ CClientSet classes are implemented here.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 04-03-95 Combined many smaller .cxx files
+ MarioGo 01-05-96 Locally unique IDs
+
+--*/
+
+#include<or.hxx>
+
+//
+// CClientOid methods
+//
+
+CClientOid::~CClientOid()
+{
+ ASSERT(gpClientLock->HeldExclusive());
+ ASSERT(!In());
+ ASSERT(Out());
+ ASSERT(_pOxid);
+ ASSERT(_pSet);
+
+ _pOxid->Release();
+ _pSet->Release();
+
+ gpClientOidTable->Remove(this);
+}
+
+//
+// CClientOxid methods.
+//
+
+ORSTATUS
+CClientOxid::GetInfo(
+ IN BOOL fApartment,
+ OUT OXID_INFO *pInfo
+ )
+/*++
+
+Routine Description:
+
+ Returns the OXID_INFO structure for this oxid.
+
+ No locks are held during calls to this method, but
+ the OXID will be referenced by a process which will
+ not rundown during a call to this method.
+
+Arguments:
+
+ fApartment - TRUE iif the client is apartment model.
+
+ pInfo - Will contain the standard info, a single _expanded_
+ string binding and complete security bindings.
+ MIDL_user_allocated.
+
+Return Value:
+
+ OR_NOMEM - Unable to allocate a parameter.
+
+ OR_OK - Normally.
+
+--*/
+{
+ USHORT protseq;
+ PWSTR pwstrT;
+ ORSTATUS status = OR_OK;
+
+ ASSERT(dsaValid(_oxidInfo.psa));
+
+ if (0 == _wProtseq)
+ {
+ // Local server
+
+ protseq = ID_LPC;
+
+ pwstrT = FindMatchingProtseq(protseq, _oxidInfo.psa->aStringArray);
+
+ ASSERT(pwstrT != 0);
+
+ if (0 != pwstrT)
+ {
+ pInfo->psa =
+ GetStringBinding(pwstrT,
+ _oxidInfo.psa->aStringArray + _oxidInfo.psa->wSecurityOffset);
+
+ if (0 == pInfo->psa)
+ {
+ status = OR_NOMEM;
+ }
+ }
+ else
+ {
+ status = OR_BADOXID;
+ }
+ }
+ else
+ {
+ // Remote server, find a string binding to use.
+
+ pInfo->psa = 0;
+ PWSTR pwstrBinding = 0;
+
+ // First, check if there is a known good binding to use.
+
+ if (_iStringBinding != 0xFFFF)
+ {
+ ASSERT(_wProtseq == _oxidInfo.psa->aStringArray[_iStringBinding]);
+ pwstrBinding = &_oxidInfo.psa->aStringArray[_iStringBinding];
+ }
+ else
+ {
+
+ // If the server supports multiple bindings on the same protocol
+ // the binding must to checked by making a call to the server.
+ // (On debug builds the server is always called)
+
+ pwstrT = FindMatchingProtseq(_wProtseq, _oxidInfo.psa->aStringArray);
+
+ if (0 == pwstrT)
+ {
+ // NOTE: This may start happening if we switch to resolving with
+ // multiple client protocols. In that case we need to try
+ // all bindings in this case.
+ ASSERT(0);
+ status = OR_NOSERVER;
+ }
+ else
+ {
+ // Check if there is more then one binding supported by the remote
+ // machine for this protocol.
+
+ pwstrBinding = pwstrT;
+
+ pwstrT = FindMatchingProtseq(_wProtseq, pwstrT + 1);
+
+ if (pwstrT)
+ {
+ if (TestBinding(pwstrBinding) == FALSE)
+ {
+ // First binding failed, try the next set of bindings..
+ do
+ {
+ if (TestBinding(pwstrT) == TRUE)
+ {
+ pwstrBinding = pwstrT;
+ break;
+ }
+
+ pwstrT = FindMatchingProtseq(_wProtseq, pwstrT + 1);
+ }
+ while (pwstrT);
+
+ // If none of the bindings worked, then we'll just
+ // use the first one.
+ }
+ }
+
+ ASSERT(pwstrBinding);
+
+ _iStringBinding = pwstrBinding - _oxidInfo.psa->aStringArray;
+
+ ASSERT(pwstrBinding == &_oxidInfo.psa->aStringArray[_iStringBinding]);
+ }
+ }
+
+ #if DBG
+ // Exercise the TestBinding code on debug machines even with only
+ // a single server binding..
+ if (pwstrBinding)
+ {
+ TestBinding(pwstrBinding);
+ }
+ #endif
+
+ if (0 != pwstrBinding)
+ {
+ // Found a binding
+ pInfo->psa = GetStringBinding(pwstrBinding,
+ _oxidInfo.psa->aStringArray + _oxidInfo.psa->wSecurityOffset);
+ if (0 == pInfo->psa)
+ {
+ status = OR_NOMEM;
+ }
+ }
+ else
+ {
+ OrDbgPrint(("OR: Unable to find a binding for oxid %p (to %S)\n",
+ this, _oxidInfo.psa->aStringArray + 1));
+ status = OR_BADOXID;
+ }
+ }
+
+ if (status == OR_OK)
+ {
+ pInfo->dwTid = _oxidInfo.dwTid;
+ pInfo->dwPid = _oxidInfo.dwPid;
+ pInfo->dwAuthnHint = _oxidInfo.dwAuthnHint;
+ pInfo->ipidRemUnknown = _oxidInfo.ipidRemUnknown;
+ }
+
+ return(status);
+}
+
+ORSTATUS
+CClientOxid::UpdateInfo(OXID_INFO *pInfo)
+{
+ DUALSTRINGARRAY *pdsaT;
+
+ ASSERT(pInfo);
+ ASSERT(gpClientLock->HeldExclusive());
+
+ if (pInfo->psa)
+ {
+ ASSERT(dsaValid(pInfo->psa));
+
+ pdsaT = new(sizeof(USHORT) * pInfo->psa->wNumEntries) DUALSTRINGARRAY;
+
+ if (!pdsaT)
+ {
+ return(OR_NOMEM);
+ }
+
+ dsaCopy(pdsaT, pInfo->psa);
+
+ delete _oxidInfo.psa;
+ _oxidInfo.psa = pdsaT;
+ }
+
+ _oxidInfo.dwTid = pInfo->dwTid;
+ _oxidInfo.dwPid = pInfo->dwPid;
+ _oxidInfo.dwAuthnHint = pInfo->dwAuthnHint;
+ _oxidInfo.ipidRemUnknown = pInfo->ipidRemUnknown;
+
+ ASSERT(dsaValid(_oxidInfo.psa));
+ return(OR_OK);
+}
+
+void
+CClientOxid::Reference()
+/*++
+
+Routine Description:
+
+ As as CReferencedObject::Reference except that it knows to
+ pull the oxid out of the plist when the refcount was 0.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ BOOL fRemove = (this->References() == 0);
+
+ // We may remove something from a PList more then once;
+ // it won't hurt anything. This avoids trying to remove
+ // more often then necessary.
+
+ this->CReferencedObject::Reference();
+
+ if (fRemove)
+ {
+ CPListElement * t = Remove();
+ ASSERT(t == &this->_plist || t == 0);
+ }
+}
+
+DWORD
+CClientOxid::Release()
+/*++
+
+Routine Description:
+
+ Overrides CReferencedObject::Release since OXIDs must wait for
+ a timeout period before being deleted.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ 0 - object fully released.
+
+ non-zero - object nt fully released by you.
+
+--*/
+
+{
+ ASSERT(gpClientLock->HeldExclusive());
+
+ LONG c = CReferencedObject::Dereference();
+
+ if (c == 0)
+ {
+ Insert();
+ }
+
+ ASSERT(c >= 0);
+
+ return(c);
+}
+
+
+//
+// CClientSet methods
+//
+
+ORSTATUS
+CClientSet::RegisterObject(CClientOid *pOid)
+/*++
+
+Routine Description:
+
+ Adds a new oid to the set of oids owned by this set.
+
+Arguments:
+
+ pOid - A pointer to the OID to add to the set. The caller gives
+ his reference to this set.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ORSTATUS status;
+
+ ASSERT(gpClientLock->HeldExclusive());
+
+ ASSERT(_blistOids.Member(pOid) == FALSE);
+
+ status = _blistOids.Insert(pOid);
+
+ if (status == OR_OK)
+ {
+ ObjectUpdate(pOid);
+ _cFailedPings = 0;
+ }
+
+ VALIDATE((status, OR_NOMEM, 0));
+
+ return(status);
+}
+
+extern "C" {
+typedef error_status_t (*pfnComplexPing)(handle_t,
+ SETID *,
+ USHORT,
+ USHORT,
+ USHORT,
+ OID[],
+ OID[],
+ PUSHORT);
+}
+
+ORSTATUS
+CClientSet::PingServer()
+/*++
+
+Routine Description:
+
+ Performs a nice simple ping of the remote set.
+
+Note:
+
+ Exactly and only one thread may call this method on
+ a given instance of a CClientSet at a time.
+
+ No lock held when called.
+
+ Overview of state transitions on a CClientOid during
+ a complex ping:
+
+ In() Out() Actions before ping; after ping
+ FALSE FALSE A ; C A U
+ FALSE TRUE R ; R U
+ TRUE FALSE N ; N
+ TRUE TRUE R ; C R U
+
+ Before:
+ A - Added to list of IDs to be added.
+ N - Ignored
+ R - Added to list of IDs to be removed.
+
+ // States may change during the call.
+
+ After:
+ C - Check if ping call was successful. If not, skip next action.
+ R - If the Out() state is still TRUE, remove it.
+ N - ignored
+ A - Set In() state to TRUE
+ U - If Out() state changed during the call, set _fChange.
+
+ If three pings fail in a row, all Out()==TRUE OIDs are
+ actually Released() and no new pings are made until ObjectUpdate()
+ is called again.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ OR_OK - Pinged okay
+
+ OR_NOMEM - Resource allocation failed
+
+ OR_I_PARTIAL_UPDATE - Pinged okay, but more pings
+ are needed to fully update the remote set.
+
+ Other - Error from RPC.
+
+--*/
+{
+ ORSTATUS status;
+ USHORT cAdds = 0;
+ USHORT cDels = 0;
+ BOOL fRetry;
+ CToken *pToken;
+
+ if (_fSecure)
+ {
+ pToken = (CToken *)Id2();
+ ASSERT(pToken != 0);
+ pToken->Impersonate();
+ }
+
+ if (_fChange)
+ {
+ USHORT wBackoffFactor;
+ OID *aAdds = 0;
+ OID *aDels = 0;
+ CClientOid **apoidAdds;
+ CClientOid **apoidDels = 0;
+ CClientOid *pOid;
+
+ gpClientLock->LockShared();
+
+ // Since we own a shared lock, nobody can modify the contents
+ // of the set or change the references on an OID in the set
+ // while we do this calculation.
+
+ ASSERT(_fChange);
+ _fChange = FALSE;
+
+ DWORD debugSize = _blistOids.Size();
+ ASSERT(debugSize);
+
+ CBListIterator oids(&_blistOids);
+
+ while (pOid = (CClientOid *)oids.Next())
+ {
+ if (pOid->Out() == FALSE)
+ {
+ if (pOid->In() == FALSE)
+ {
+ // Referenced and not in set, add it.
+ cAdds++;
+ }
+ }
+ else
+ {
+ // Not referenced, remove it.
+ cDels++;
+ }
+ }
+
+ ASSERT(debugSize == _blistOids.Size());
+ oids.Reset(&_blistOids);
+
+ aAdds = (OID *)alloca(sizeof(OID) * cAdds);
+ apoidAdds = (CClientOid **)alloca(sizeof(CClientOid *) * cAdds);
+ aDels = (OID *)alloca(sizeof(OID) * cDels);
+ apoidDels = (CClientOid **)alloca(sizeof(CClientOid *) * cDels);
+
+ DWORD debugAdds = cAdds;
+ DWORD debugDels = cDels;
+
+ cAdds = cDels = 0;
+
+ while (pOid = (CClientOid *)oids.Next())
+ {
+ if (pOid->Out() == FALSE)
+ {
+ if (pOid->In() == FALSE)
+ {
+ // Referenced and not yet added
+ aAdds[cAdds] = pOid->Id();
+ apoidAdds[cAdds] = pOid;
+ cAdds++;
+ }
+ }
+ else
+ {
+ aDels[cDels] = pOid->Id();
+ apoidDels[cDels] = pOid;
+ cDels++;
+ }
+ }
+
+ ASSERT(debugSize == _blistOids.Size());
+ ASSERT(debugAdds == cAdds);
+ ASSERT(debugDels == cDels);
+
+ gpClientLock->UnlockShared();
+
+ OrDbgDetailPrint(("OR: Pinging set %p on %S, (%d, %d)\n", this,
+ _pMid->IsLocal() ? L"local" : _pMid->PrintableName(),
+ cAdds, cDels));
+
+
+ pfnComplexPing pfn;
+
+ // For local, call manager API directly.
+ if (_pMid->IsLocal())
+ {
+ pfn = _ComplexPing;
+ }
+ else
+ {
+ pfn = ComplexPing;
+ }
+
+ fRetry = TRUE;
+
+ for (;;)
+ {
+ // Allocate a connection if needed
+ if ( FALSE == _pMid->IsLocal()
+ && 0 == _hServer )
+ {
+ // GetBinding will return 0 when we've tried every binding.
+ _hServer = _pMid->GetBinding(_iBinding);
+ fRetry = TRUE;
+ if (!_hServer)
+ {
+ _iBinding = 0;
+ status = OR_NOMEM;
+ break;
+ }
+ else
+ {
+ if (_pMid->IsSecure())
+ {
+ // set security on the binding handle.
+
+ _fSecure = TRUE;
+
+ RPC_SECURITY_QOS qos;
+ qos.Version = RPC_C_SECURITY_QOS_VERSION;
+ qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
+ qos.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC;
+ qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY;
+
+ status = RpcBindingSetAuthInfoEx(_hServer,
+ 0,
+ RPC_C_AUTHN_LEVEL_CONNECT,
+ RPC_C_AUTHN_WINNT,
+ 0,
+ 0,
+ &qos);
+ }
+ else
+ {
+ _fSecure = FALSE;
+ status = OR_OK;
+ }
+ }
+ }
+ else
+ {
+ status = OR_OK;
+ }
+
+ if (OR_OK == status)
+ {
+ _sequence++;
+
+ status = (pfn)(_hServer,
+ &_setid,
+ _sequence,
+ cAdds,
+ cDels,
+ aAdds,
+ aDels,
+ &wBackoffFactor
+ );
+
+ if (fRetry && (status == RPC_S_UNKNOWN_IF))
+ {
+ status = RpcBindingReset(_hServer);
+ if (status != RPC_S_OK)
+ {
+ OrDbgPrint(("OR: RpcBindingReset failed %d\n", status));
+ }
+ fRetry = FALSE;
+ continue;
+ }
+
+ if ( status == OR_OK
+ || status == OR_BADOID
+ || status == OR_NOMEM
+ || status == RPC_S_OUT_OF_RESOURCES
+ || status == RPC_S_SERVER_TOO_BUSY )
+ {
+ break;
+ }
+
+ if (status == OR_BADSET)
+ {
+ // Set invalid; reallocate (don't free the binding).
+ ASSERT(_pMid->IsLocal() == FALSE);
+ ASSERT(_setid);
+ OrDbgPrint(("OR: Set %p invalid; recreating..\n", this));
+ _setid = 0;
+ _sequence = 0;
+ }
+ else if (FALSE == _pMid->IsLocal())
+ {
+ // General failure; free this binding and retry.
+ OrDbgDetailPrint(("OR: Ping failed, retrying %d\n", status));
+ _pMid->BindingFailed(_iBinding);
+ status = RpcBindingFree(&_hServer);
+ ASSERT(status == RPC_S_OK && _hServer == 0);
+ _sequence--;
+ }
+ else
+ {
+ break;
+ }
+ }
+ } // for loop
+
+ if (status == OR_BADOID)
+ {
+ // This is really okay, all Dels must be deleted,
+ // and if the add failed now, it will always fail.
+ OrDbgPrint(("OR: Client specified unknown OID(s). %p %p %p\n", this, aAdds, apoidAdds));
+ status = OR_OK;
+ }
+
+ pToken->Revert();
+
+ gpClientLock->LockExclusive();
+
+ this->Reference(); // Keep set alive until we finish
+
+ if (status == OR_OK)
+ {
+ int i;
+
+ if (FALSE == fRetry)
+ {
+ OrDbgDetailPrint(("OR: Machine %S, ping retry ok, assuming dynamic\n",
+ _pMid->PrintableName()));
+ _pMid->UseDynamicEndpoints();
+ }
+
+ // Success, process the adds
+
+ for(i = 0; i < cAdds; i++)
+ {
+ pOid = apoidAdds[i];
+
+ pOid->Added();
+
+ if (FALSE != pOid->Out())
+ {
+ // NOT referenced now, make sure it gets deleted next period.
+ ObjectUpdate(pOid);
+ }
+ }
+
+ // Process deletes.
+
+ for (i = 0; i < cDels; i++)
+ {
+ pOid = apoidDels[i];
+
+ pOid->Deleted();
+
+ if (FALSE != pOid->Out())
+ {
+ // Well what do you yah know, we can _finally_ delete an oid.
+
+ CClientOid *pT = (CClientOid *)_blistOids.Remove(pOid);
+ ASSERT(pT == pOid);
+
+ DWORD t = pOid->Release();
+ ASSERT(t == 0);
+ }
+ else
+ {
+ // We deleted from the set but now somebody is referencing it.
+ // Make sure we re-add it next time.
+ ObjectUpdate(pOid);
+ }
+ }
+
+ _cFailedPings = 0;
+ }
+ else
+ {
+ _fChange = TRUE;
+ }
+
+ DWORD c = this->Release();
+ if (c)
+ {
+ ASSERT(_blistOids.Size());
+ this->Insert();
+ }
+ else
+ {
+ ASSERT(cAdds == 0 && cDels != 0);
+ }
+ // Set (this) pointer maybe invalid
+
+ gpClientLock->UnlockExclusive();
+ }
+ else
+ {
+ OrDbgDetailPrint(("OR: Pinging set %p on %S.\n",
+ this,
+ _pMid->IsLocal() ? L"local" : _pMid->PrintableName()));
+
+ ASSERT(_setid != 0);
+
+ if (_pMid->IsLocal())
+ {
+ ASSERT(_cFailedPings == 0);
+ ASSERT(_hServer == 0);
+ status = _SimplePing(0, &_setid);
+ ASSERT(status == OR_OK);
+ }
+ else
+ {
+ ASSERT(_hServer);
+ if (_cFailedPings <= 3)
+ {
+ status = SimplePing(_hServer, &_setid);
+ if (status != OR_OK)
+ {
+ _cFailedPings++;
+ if (_cFailedPings > 3)
+ {
+ OrDbgPrint(("OR: Server %S (set %p) has failed 3 pings...\n",
+ _pMid->PrintableName(), this));
+ }
+ }
+ else
+ {
+ _cFailedPings = 0;
+ }
+ }
+ else
+ {
+ status = OR_OK;
+ }
+ }
+ this->Insert();
+ pToken->Revert();
+ }
+
+ // Set (this) maybe invalid.
+
+#if DBG
+ if (status != OR_OK)
+ {
+ OrDbgPrint(("OR: ping %p failed %d\n", this, status));
+ }
+#endif
+
+ return(status);
+}
+
diff --git a/private/ole32/dcomss/objex/orsvr.cxx b/private/ole32/dcomss/objex/orsvr.cxx
new file mode 100644
index 000000000..68814f1c3
--- /dev/null
+++ b/private/ole32/dcomss/objex/orsvr.cxx
@@ -0,0 +1,714 @@
+/*++
+
+Copyright (c) 1995-1996 Microsoft Corporation
+
+Module Name:
+
+ OrSvr.cxx
+
+Abstract:
+
+ Object resolver server side class implementations. CServerOxid, CServerOid,
+ CServerSet and CServerSetTable classes are implemented here.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 04-03-95 Combined many smaller .cxx files
+ MarioGo 01-12-96 Locally unique IDs
+
+--*/
+
+#include<or.hxx>
+
+
+//
+// CServerOid methods
+//
+
+void
+CServerOid::Reference()
+// Server lock held shared.
+{
+ BOOL fRemove = (this->References() == 0);
+
+ // We may remove something from a PList more then once; this won't
+ // hurt anything. fRemove is used to avoid trying to remove it more
+ // often then necessary without taking lock.
+
+ this->CIdTableElement::Reference();
+
+ if (fRemove)
+ {
+ CPListElement * t = Remove();
+ ASSERT(t == &this->_plist || t == 0);
+ }
+}
+
+DWORD
+CServerOid::Release()
+{
+ ASSERT(gpServerLock->HeldExclusive());
+
+ DWORD c = this->CReferencedObject::Dereference();
+
+ if (0 == c)
+ {
+ // If another thread is already running this down it
+ // means we got referenced and released during the rundown
+ // callback. That thread will figure out what to do.
+
+ if (IsRunningDown())
+ {
+ OrDbgPrint(("OR: Oid running down in release: %p\n", this));
+ }
+ else if (IsFreed() || this->_pOxid->IsRunning() == FALSE)
+ {
+ // Server freed this OID already; no need to run it down
+ OrDbgDetailPrint(("OR: OID %p freed by server so not rundown\n",
+ this));
+ SetRundown();
+ delete this;
+ }
+ else
+ {
+ Insert();
+ }
+ }
+
+ // this pointer maybe invalid.
+ return(c);
+}
+
+CServerOid::~CServerOid()
+{
+ ASSERT(gpServerLock->HeldExclusive());
+ ASSERT(_pOxid);
+ ASSERT(_fRunningDown);
+
+ _pOxid->Release();
+
+ gpServerOidTable->Remove(this);
+}
+
+void
+CServerOid::KeepAlive()
+// A client has removed this oid from its set. This keeps
+// the oid alive for another timeout period.
+{
+ ASSERT(gpServerLock->HeldExclusive());
+
+ if (IsRunningDown() == FALSE && References() == 0)
+ {
+ // It's in the rundown list, move it to the end.
+ CPListElement *pT = Remove();
+ ASSERT(pT == &this->_plist);
+ Insert();
+ }
+}
+
+
+//
+// CServerOidPList method
+//
+
+CServerOid *
+CServerOidPList::MaybeRemoveMatchingOxid(
+ IN CTime &when,
+ IN CServerOid *pOid
+ )
+{
+ CPListElement *ple;
+ CServerOid *poid;
+
+ CMutexLock lock(&this->_lock);
+
+ ple = (CPListElement *)CPList::First();
+
+ while( ple != 0
+ && *ple->GetTimeout() < when)
+ {
+
+ poid = CServerOid::ContainingRecord(ple);
+
+ if (poid->Match(pOid))
+ {
+ Remove(ple);
+ return(poid);
+ }
+
+ ple = ple->Next();
+ }
+ return(0);
+}
+
+
+//
+// CServerOxid methods
+//
+
+void
+CServerOxid::ProcessRelease()
+/*++
+
+Routine Desciption
+
+ The server process owning this OXID has either died
+ or deregistered this oxid. Releases the oxid and
+ nulls the pProcess pointer.
+
+Arguments:
+
+ n/a
+
+Return Value:
+
+ n/a
+
+--*/
+{
+ ASSERT(_pProcess);
+ _fRunning = FALSE;
+ Release();
+ // This pointer may now be invalid, _pProcess pointer maybe invalid.
+}
+
+CServerOxid::~CServerOxid(void)
+{
+ ASSERT(gpServerLock->HeldExclusive());
+ ASSERT(_pProcess);
+ ASSERT(!IsRunning()); // implies that the oxid has been removed from the table
+ _pProcess->Release();
+}
+
+ORSTATUS
+CServerOxid::GetInfo(
+ OUT OXID_INFO *poxidInfo,
+ IN BOOL fLocal
+ )
+// Server lock held shared.
+{
+ ORSTATUS status;
+
+ if (!IsRunning())
+ {
+ // Server crashed, info is not needed.
+ return(OR_NOSERVER);
+ }
+
+ if (fLocal)
+ {
+ poxidInfo->psa = _pProcess->GetLocalBindings();
+ }
+ else
+ {
+ poxidInfo->psa = _pProcess->GetRemoteBindings();
+ }
+
+ if (!poxidInfo->psa)
+ {
+ return(OR_NOMEM);
+ }
+
+ poxidInfo->dwTid = _info.dwTid;
+ poxidInfo->dwPid = _info.dwPid;
+ poxidInfo->dwAuthnHint = _info.dwAuthnHint;
+ poxidInfo->ipidRemUnknown = _info.ipidRemUnknown;
+
+ return(OR_OK);
+}
+
+void
+CServerOxid::RundownOids(
+ IN USHORT cOids,
+ IN OID aOids[],
+ OUT BYTE afRundownOk[]
+ )
+// Note: Returns with out the server lock held.
+{
+ ASSERT(gpServerLock->HeldExclusive());
+
+ if (IsRunning())
+ {
+ // Note: The server lock is released during the callback.
+ // Since the OID hasn't rundown yet, it will keep a reference
+ // to this OXID which in turn keeps the process object alive.
+
+ _pProcess->RundownOids(cOids, aOids, _info.ipidRemUnknown, afRundownOk);
+ return;
+ }
+
+ gpServerLock->UnlockExclusive();
+
+ for (USHORT i = 0; i < cOids; i++)
+ {
+ afRundownOk[i] = TRUE;
+ }
+}
+
+ORSTATUS
+CServerOxid::GetRemoteInfo(
+ OUT OXID_INFO *pInfo,
+ IN USHORT cClientProtseqs,
+ IN USHORT aClientProtseqs[]
+ )
+// Server lock held shared.
+{
+
+ ORSTATUS status;
+ USHORT protseq;
+
+ status = GetInfo(pInfo, FALSE);
+
+ if (OR_OK == status)
+ {
+ protseq = FindMatchingProtseq(cClientProtseqs,
+ aClientProtseqs,
+ pInfo->psa->aStringArray
+ );
+ if (0 == protseq)
+ {
+ MIDL_user_free(pInfo->psa);
+ pInfo->psa = 0;
+ status = OR_I_NOPROTSEQ;
+ }
+ }
+
+ return(status);
+
+}
+
+ORSTATUS
+CServerOxid::LazyUseProtseq(
+ IN USHORT cClientProtseqs,
+ IN USHORT *aClientProtseqs
+ )
+// Server lock held shared, returns with the server lock exclusive.
+// Note: It is possible, that after this call the OXID has been deleted.
+{
+ ORSTATUS status;
+
+ if (IsRunning())
+ {
+ // Keep this OXID process alive while making the callback. If the process
+ // crashes and this OXID has no OIDs it could be released by everybody
+ // else. This keeps the OXID and process alive until we finish.
+
+ this->Reference();
+
+ gpServerLock->UnlockShared();
+
+ status = _pProcess->UseProtseqIfNeeded(cClientProtseqs, aClientProtseqs);
+
+ gpServerLock->LockExclusive();
+
+ this->Release();
+ }
+ else
+ {
+ gpServerLock->ConvertToExclusive();
+ status = OR_NOSERVER;
+ }
+
+ // Note: The this poiner maybe BAD now.
+
+ return(status);
+}
+
+
+//
+// CServerSet methods.
+//
+
+ORSTATUS
+CServerSet::AddObject(OID &oid)
+{
+ ORSTATUS status;
+ CServerOid *pOid;
+
+ ASSERT(gpServerLock->HeldExclusive());
+
+ CIdKey key(oid);
+
+ pOid = (CServerOid *)gpServerOidTable->Lookup(key);
+
+ if (pOid)
+ {
+ ASSERT(_blistOids.Member(pOid) == FALSE);
+
+ status = _blistOids.Insert(pOid);
+
+ if (status == OR_OK)
+ {
+ pOid->Reference();
+ }
+ }
+ else
+ status = OR_BADOID;
+
+ VALIDATE((status, OR_BADOID, OR_NOMEM, 0));
+
+ return(status);
+}
+
+
+void
+CServerSet::RemoveObject(OID &oid)
+{
+ CServerOid *pOid;
+
+ ASSERT(gpServerLock->HeldExclusive());
+
+ CIdKey key(oid);
+
+ pOid = (CServerOid *)gpServerOidTable->Lookup(key);
+
+ if (pOid)
+ {
+ CServerOid *pOidTmp = (CServerOid *)_blistOids.Remove(pOid);
+
+ if (pOid == pOidTmp)
+ {
+ pOid->Release();
+ }
+ else
+ {
+ // Set doesn't contain the specified oid, treat this as an
+ // add and delete by keeping the oid alive for another timeout
+ // period.
+
+ ASSERT(pOidTmp == 0);
+
+ pOid->KeepAlive();
+ }
+ }
+}
+
+BOOL
+CServerSet::ValidateObjects(BOOL fShared)
+// fShared - Indicates if the server lock is held
+// shared (TRUE) or exclusive (FALSE).
+//
+// Return - TRUE the lock is still shared, false
+// the lock is held exclusive.
+{
+ CServerOid *pOid;
+ CBListIterator oids(&_blistOids);
+
+ // Since we own a reference on all the Oids they must still exist.
+ // No need to lock exclusive until we find something to delete.
+
+ while(pOid = (CServerOid *)oids.Next())
+ {
+ if (!pOid->IsRunning())
+ {
+ if (fShared)
+ {
+ OrDbgPrint(("OR: Cleanup in set (%p), removing dead oids.\n",
+ this, pOid));
+ gpServerLock->ConvertToExclusive();
+ fShared = FALSE;
+ oids.Reset(&_blistOids);
+ continue;
+ }
+
+ CServerOid *pOidTmp = (CServerOid *)_blistOids.Remove(pOid);
+
+ ASSERT(pOidTmp == pOid);
+ ASSERT(pOid->IsRunning() == FALSE);
+
+ pOid->Release();
+ }
+ }
+
+ return(fShared);
+}
+
+BOOL
+CServerSet::Rundown()
+// Rundown the whole set.
+{
+ CServerOid *poid;
+ CTime now;
+
+ ASSERT(gpServerLock->HeldExclusive());
+
+ if (_timeout > now)
+ {
+ // Don't rundown if we've recieved a late ping.
+ return(FALSE);
+ }
+
+ if (_fLocal && _blistOids.Size() != 0)
+ {
+ OrDbgPrint(("OR: Premature rundown of local set ignored.\n"));
+ return(FALSE);
+ }
+
+ OrDbgPrint(("OR: Set %p's client appears to have died\n", this));
+
+ CBListIterator oids(&_blistOids);
+
+ while(poid = (CServerOid *)oids.Next())
+ {
+ poid->Release();
+ }
+
+ return(TRUE);
+}
+
+
+//
+// CServerSetTable implementation
+//
+
+CServerSet *
+CServerSetTable::Allocate(
+ IN USHORT sequence,
+ IN PSID psid,
+ IN BOOL fLocal,
+ OUT ID &setid
+ )
+/*++
+
+Routine Description:
+
+ Allocates a new CServerSet and returns the setid for the new set.
+
+Arguments:
+
+ sequence - initial sequence number for the new set.
+
+ psid - pointer to an NT SID structure for the new set.
+
+ fLocal - TRUE : set is for the local client,
+ FALSE : set is for a remote client
+
+ setid - the setid of the set returned. Unchanged if return value 0.
+
+Return Value:
+
+ 0 - Unable to allocate a resource
+
+ non-zero - A pointer to the newly created set.
+
+--*/
+{
+ ASSERT(gpServerLock->HeldExclusive());
+ UINT i;
+ LARGE_INTEGER li;
+
+ ASSERT(_cAllocated <= _cMax);
+
+ if (_cAllocated == _cMax)
+ {
+ // Table is full, realloc
+
+ // Do this first, if it succeeds great even if
+ // a later allocation fails. If not, fail now.
+
+ IndexElement *pNew = new IndexElement[_cMax * 2];
+
+ if (!pNew)
+ {
+ return(0);
+ }
+
+ for (i = 0; i < _cMax; i++)
+ {
+ pNew[i] = _pElements[i];
+ }
+
+ for(i = _cMax; i < _cMax*2; i++)
+ {
+ pNew[i]._sequence = GetTickCount();
+ pNew[i]._pSet = 0;
+ }
+
+ delete _pElements;
+ _pElements = pNew;
+ _cMax *= 2;
+ }
+
+ CServerSet *pSet = new CServerSet(sequence, psid, fLocal);
+
+ if (0 == pSet)
+ {
+ return(0);
+ }
+
+ ASSERT(_pElements);
+ ASSERT(_cMax > _cAllocated);
+
+ for(i = _iFirstFree; i < _cMax; i++)
+ {
+ if (0 == _pElements[i]._pSet)
+ {
+ _pElements[i]._sequence++;
+ _pElements[i]._pSet = pSet;
+ li.HighPart = i + 1;
+ li.LowPart = _pElements[i]._sequence;
+ setid = li.QuadPart;
+ _iFirstFree = i + 1;
+ _cAllocated++;
+ return pSet;
+ }
+ }
+
+ ASSERT(0);
+ return(0);
+}
+
+
+CServerSet *
+CServerSetTable::Lookup(
+ IN ID setid
+ )
+/*++
+
+Routine Description:
+
+ Looks up an a set given the sets ID.
+
+ Server lock held shared.
+
+Arguments:
+
+ setid - the ID of the set to lookup
+
+Return Value:
+
+ 0 - set doesn't exist
+
+ non-zero - the set.
+
+--*/
+{
+ LARGE_INTEGER li;
+ li.QuadPart = setid;
+ UINT i = li.HighPart - 1;
+ DWORD sequence = setid & ~0UL;
+
+ if (i >= 0 && i < _cMax)
+ {
+ if (_pElements[i]._sequence == sequence)
+ {
+ // May still be null if it is free and has not yet be reused.
+ return(_pElements[i]._pSet);
+ }
+ }
+ return(0);
+}
+
+
+ID
+CServerSetTable::CheckForRundowns(
+ )
+/*++
+
+Routine Description:
+
+ Used by ping and worker threads to monitor for sets that should
+ be rundown. It is called with the server lock held shared.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ 0 - Didn't find a set to rundown
+
+ non-zero - ID of a set which may need to be rundown.
+
+--*/
+{
+ UINT i, end;
+ LARGE_INTEGER id;
+ id.QuadPart = 0;
+ ASSERT(_iRundown < _cMax);
+
+ if (_cAllocated == 0)
+ {
+ return(0);
+ }
+
+ i = _iRundown;
+ do
+ {
+ ASSERT(_cAllocated); // loop assumes one or more allocated elements.
+ i = (i + 1) % _cMax;
+ }
+ while(0 == _pElements[i]._pSet);
+
+ ASSERT(_pElements[i]._pSet);
+
+ if (_pElements[i]._pSet->ShouldRundown())
+ {
+ id.HighPart = i + 1;
+ id.LowPart = _pElements[i]._sequence;
+ }
+
+ _iRundown = i;
+
+ return(id.QuadPart);
+}
+
+
+BOOL
+CServerSetTable::RundownSetIfNeeded(
+ IN ID setid
+ )
+/*++
+
+Routine Description:
+
+ Rundowns down a set (or sets) if needed. Called by
+ ping and worker threads. Server lock held exclusive.
+
+Arguments:
+
+ setid - An ID previously returned from CheckForRundowns.
+
+Return Value:
+
+ TRUE - A set was actually rundown
+
+ FALSE - No sets actually rundown
+
+--*/
+{
+ ASSERT(gpServerLock->HeldExclusive());
+
+ CServerSet *pSet = Lookup(setid);
+
+ if (0 == pSet || FALSE == pSet->ShouldRundown())
+ {
+ // Set already randown or has been pinged in the meantime.
+ return(FALSE);
+ }
+
+ // PERF REVIEW this function has the option of running multiple sets,
+ // saving the worker thread from taking and leaving the lock many times
+ // when a bunch of sets all rundown. This feature is not used.
+
+ LARGE_INTEGER li;
+ li.QuadPart = setid;
+
+ UINT i = li.HighPart - 1;
+
+ if (pSet->Rundown())
+ {
+ delete pSet;
+ _cAllocated--;
+ if (i < _iFirstFree) _iFirstFree = i;
+ _pElements[i]._pSet = 0;
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
diff --git a/private/ole32/dcomss/objex/plist.cxx b/private/ole32/dcomss/objex/plist.cxx
new file mode 100644
index 000000000..c80582399
--- /dev/null
+++ b/private/ole32/dcomss/objex/plist.cxx
@@ -0,0 +1,107 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Plist.cxx
+
+Abstract:
+
+ Implementation of the CPList class.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-24-95 Bits 'n pieces
+
+--*/
+
+#include<or.hxx>
+
+void
+CPList::Insert(CPListElement *p)
+{
+ CMutexLock lock(&this->_lock);
+ CTime time;
+
+ time += _timeout;
+
+ p->SetTimeout(time);
+
+ this->CList::Insert(p);
+}
+
+BOOL
+CPList::PeekMin(CTime &timeout)
+ // inline?
+{
+ CTime *pT;
+ CMutexLock lock(&this->_lock);
+
+ CPListElement *first = (CPListElement *)this->First();
+
+ if (first && (pT = first->GetTimeout()))
+ {
+ timeout = *pT;
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
+CPListElement *
+CPList::Remove(CPListElement *p)
+// It must be safe to remove an element not actually in a list.
+{
+ CMutexLock lock(&this->_lock);
+
+ return( (CPListElement *)this->CList::Remove(p) );
+}
+
+CListElement *
+CPList::MaybeRemoveMin(
+ IN CTime &when
+ )
+{
+ CMutexLock lock(&this->_lock);
+
+ CPListElement *first = (CPListElement *)this->First();
+
+ if (first && *first->GetTimeout() < when)
+ {
+ return(Remove(first));
+ }
+
+ return(0);
+}
+
+void
+CPList::Reset(
+ IN CPListElement *p
+ )
+{
+ CMutexLock lock(&this->_lock);
+
+ ASSERT(p);
+
+ if (p->Next() == 0 && p->Previous() == 0 && First() != p)
+ {
+ ASSERT(Last() != p);
+ return;
+ }
+
+ Remove(p);
+
+ // Update timeout
+ CTime now;
+ now += _timeout;
+ p->SetTimeout(now);
+
+ Insert(p);
+ return;
+}
+
diff --git a/private/ole32/dcomss/objex/plist.hxx b/private/ole32/dcomss/objex/plist.hxx
new file mode 100644
index 000000000..fc6abf3df
--- /dev/null
+++ b/private/ole32/dcomss/objex/plist.hxx
@@ -0,0 +1,125 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ PList.hxx
+
+Abstract:
+
+ The CPList class is similar to a priority queue except that new elements
+ are ordered after all the other elments.
+
+ PList - Insert O(1) (except when the list grows..)
+ PeekMin O(1)
+ RemoveMin O(1)
+
+ PQueue - Insert O(ln 2) (except when the list grows..)
+ PeekMin O(1)
+ RemoveMin O(ln 2)
+
+ The PListElement are designed to be embedded in a larger
+ object and a macro used to get for the embedded PList element
+ back to the original object.
+
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-22-95 Bits 'n pieces
+ MarioGo 12-15-95 Change to embedded object.
+
+--*/
+
+#ifndef __PLIST_HXX
+#define __PLIST_HXX
+
+class CPList;
+
+class CPListElement : public CListElement
+ {
+
+ friend class CPList;
+ friend class CServerOidPList;
+
+ public:
+
+ CPListElement() : _timeout(0) {
+ }
+
+ private:
+ CTime _timeout;
+
+ protected:
+
+ CTime *
+ GetTimeout() { return(&_timeout); }
+
+ void
+ SetTimeout(const CTime &timeout) { _timeout = timeout; }
+
+ CPListElement *Next() {
+ return( (CPListElement *) CListElement::Next());
+ }
+
+ CPListElement *Previous() {
+ return( (CPListElement *) CListElement::Previous());
+ }
+
+ };
+
+class CServerOidPList;
+
+class CPList : public CList
+ {
+ friend class CServerOidPList;
+
+ private:
+
+ DWORD _timeout;
+ CRITICAL_SECTION _lock;
+
+ public:
+
+ CPList(DWORD timeout = BaseTimeoutInterval) :
+ _timeout(timeout)
+ {
+ InitializeCriticalSection(&_lock);
+ }
+
+ ~CPList() {
+ ASSERT(0); // Unused - would delete the critical section.
+ // And unlink all (any?) elements in the list.
+ }
+
+ void
+ Insert(
+ IN CPListElement *p
+ );
+
+ CPListElement *
+ Remove(CPListElement *);
+
+ BOOL PeekMin(CTime &timeout);
+
+ CListElement *
+ MaybeRemoveMin(CTime &when);
+
+ void Reset(CPListElement *);
+
+ CPListElement *First() {
+ return( (CPListElement *) CList::First());
+ }
+
+ CPListElement *Last() {
+ return( (CPListElement *) CList::Last());
+ }
+
+ };
+
+#endif
+
diff --git a/private/ole32/dcomss/objex/process.cxx b/private/ole32/dcomss/objex/process.cxx
new file mode 100644
index 000000000..9f90d3009
--- /dev/null
+++ b/private/ole32/dcomss/objex/process.cxx
@@ -0,0 +1,1180 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Process.cxx
+
+Abstract:
+
+ Process objects represent local clients and servers. These
+ objects live as context handles.
+
+ There are relatively few of these objects in the universe.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-20-95 Bits 'n pieces
+
+--*/
+
+#include <or.hxx>
+
+CRITICAL_SECTION gcsFastProcessLock;
+
+void
+CProcess::Rundown()
+/*++
+
+Routine Description:
+
+ The client process has rundown. This means there are no more
+ client refernces which means we are free to clean things up
+ as long as server OXIDs still holding references won't get
+ upset. They all use the server lock when accessing the process.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ CClassReg *pReg;
+ ORSTATUS status;
+
+ gpServerLock->LockExclusive();
+
+ ASSERT(_cClientReferences == 0);
+
+ OrDbgDetailPrint(("OR: Rundown of %p: %d oxids, %d oids and %d roxids left\n",
+ this,
+ _blistOxids.Size(),
+ _blistOids.Size(),
+ _blistRemoteOxids.Size() ));
+
+ // Revoke any class registrations which were registered but not already
+ // revoked.
+ while ( (pReg = (CClassReg *)_listClasses.First()) != 0 )
+ {
+ SCMRemoveRegistration( pReg->Clsid,
+ GetToken()->GetSid(),
+ pReg->Reg );
+ _listClasses.Remove((CListElement *)pReg);
+ delete pReg;
+ }
+
+ // Release any OXIDs owned by this process. This may destroy the OXID.
+ // This will release this CProcess, but won't release the last reference as
+ // the client process still owns one.
+
+
+ if (_blistOxids.Size())
+ {
+ CServerOxid *poxid;
+
+ CBListIterator oxids(&_blistOxids);
+
+ while(poxid = (CServerOxid *)oxids.Next())
+ {
+ gpServerOxidTable->Remove(poxid);
+ poxid->ProcessRelease();
+ }
+ }
+
+ // Release any OIDs is use by this processes.
+
+ // Do this now, rather then waiting for the last server oid
+ // owned by this process to get invalidated and rundown.
+
+ gpClientLock->LockExclusive();
+
+ // *** Both client and server lock held here. ***
+
+ if (_blistOids.Size())
+ {
+ CClientOid *poid;
+
+ CBListIterator oids(&_blistOids);
+
+ while(poid = (CClientOid *)oids.Next())
+ {
+ poid->ClientRelease();
+ }
+ }
+
+ if (_blistRemoteOxids.Size())
+ {
+ CClientOxid *poxid;
+
+ CBListIterator oxids(&_blistRemoteOxids);
+ while (poxid = (CClientOxid *)oxids.Next())
+ {
+ poxid->Release();
+ }
+ }
+
+ // Cleanup other process state.
+
+ _pToken->Release();
+ _pToken = 0;
+
+ gpClientLock->UnlockExclusive();
+
+ // Done, release the clients' reference, this may actually delete this
+ // process. (If an OXID still exists and has OIDs it will not be deleted
+ // until the OIDs all rundown).
+
+ this->Release();
+
+ // The this pointer maybe invalid now.
+
+ gpServerLock->UnlockExclusive();
+}
+
+
+CProcess::CProcess(
+ IN CToken *pToken,
+ OUT ORSTATUS &status
+ ) :
+ _blistOxids(4),
+ _blistOids(16),
+ _blistRemoteOxids(4),
+ _listClasses()
+/*++
+
+Routine Description:
+
+ Initalized a process object, members and add it to the
+ process list.
+
+Arguments:
+
+ pToken - The clients token. We assume we have a reference.
+
+ status - Sometimes the C'tor can fail with OR_NOMEM.
+
+Return Value:
+
+ None
+
+--*/
+{
+ _cClientReferences = 1;
+ _hProcess = NULL;
+ _fCacheFree = FALSE;
+ _pdsaLocalBindings = NULL;
+ _pdsaRemoteBindings = NULL;
+ _pToken = 0;
+
+ status = RtlInitializeCriticalSection(&_csCallbackLock);
+ _fLockValid = (status == STATUS_SUCCESS);
+
+ if (status == STATUS_SUCCESS)
+ {
+ CMutexLock lock(&gcsProcessManagerLock);
+ status = gpProcessList->Insert(this);
+ }
+
+ if (status == OR_OK)
+ _pToken = pToken;
+
+#if DBG
+ _cRundowns = 0;
+#endif
+}
+
+CProcess::~CProcess(void)
+// You probably should be looking in the ::Rundown method.
+// This process object stays alive until the last server oxid dies.
+{
+ ASSERT(gpServerLock->HeldExclusive());
+ ASSERT(_pToken == 0);
+
+ delete _pdsaLocalBindings;
+ delete _pdsaRemoteBindings;
+
+ if (_fLockValid)
+ DeleteCriticalSection(&_csCallbackLock);
+
+ if (_hProcess)
+ {
+ RPC_STATUS status = RpcBindingFree(&_hProcess);
+ ASSERT(status == RPC_S_OK);
+ ASSERT(_hProcess == 0);
+ }
+
+ return;
+}
+
+RPC_STATUS
+CProcess::ProcessBindings(
+ IN DUALSTRINGARRAY *pdsaStringBindings,
+ IN DUALSTRINGARRAY *pdsaSecurityBindings
+ )
+/*++
+
+Routine Description:
+
+ Updates the string and optionally the security
+ bindings associated with this process.
+
+Arguments:
+
+ psaStringBindings - The expanded string bindings of the process
+
+ psaSecurityBindings - compressed security bindings of the process.
+ If NULL, the current security bindings are reused.
+
+Environment:
+
+ Server lock held during call or called from an OXID with an extra
+ reference owned by the process and keeping this process alive.
+
+Return Value:
+
+ OR_NOMEM - unable to allocate storage for the new string arrays.
+
+ OR_OK - normally.
+
+--*/
+{
+ CMutexLock lock(&gcsFastProcessLock);
+ USHORT wSecSize;
+ PWSTR pwstrSecPointer;
+
+ // NULL security bindings means we should use the existing bindings.
+ if (0 == pdsaSecurityBindings)
+ {
+ ASSERT(_pdsaLocalBindings);
+ wSecSize = _pdsaLocalBindings->wNumEntries - _pdsaLocalBindings->wSecurityOffset;
+ pwstrSecPointer = _pdsaLocalBindings->aStringArray
+ + _pdsaLocalBindings->wSecurityOffset;
+ }
+ else
+ {
+ wSecSize = pdsaSecurityBindings->wNumEntries - pdsaSecurityBindings->wSecurityOffset;
+ pwstrSecPointer = &pdsaSecurityBindings->aStringArray[pdsaSecurityBindings->wSecurityOffset];
+ }
+
+ DUALSTRINGARRAY *pdsaT = CompressStringArray(pdsaStringBindings);
+ if (!pdsaT)
+ {
+ return(OR_NOMEM);
+ }
+
+ // ignore security on string binding parameter
+ pdsaT->wNumEntries = pdsaT->wSecurityOffset;
+
+ DUALSTRINGARRAY *pdsaResult = new((pdsaT->wNumEntries + wSecSize) * sizeof(WCHAR)) DUALSTRINGARRAY;
+
+ if (0 == pdsaResult)
+ {
+ delete pdsaT;
+ return(OR_NOMEM);
+ }
+
+ pdsaResult->wNumEntries = pdsaT->wNumEntries + wSecSize;
+ pdsaResult->wSecurityOffset = pdsaT->wSecurityOffset;
+
+ OrMemoryCopy(pdsaResult->aStringArray,
+ pdsaT->aStringArray,
+ pdsaT->wSecurityOffset*sizeof(WCHAR));
+
+ OrMemoryCopy(pdsaResult->aStringArray + pdsaResult->wSecurityOffset,
+ pwstrSecPointer,
+ wSecSize*sizeof(WCHAR));
+
+ ASSERT(dsaValid(pdsaResult));
+
+ delete pdsaT;
+
+ delete _pdsaLocalBindings;
+ _pdsaLocalBindings = pdsaResult;
+
+ delete _pdsaRemoteBindings;
+ _pdsaRemoteBindings = 0;
+
+ return(RPC_S_OK);
+}
+
+DUALSTRINGARRAY *
+CProcess::GetLocalBindings(void)
+// Server lock held or called within an
+// OXID with an extra reference.
+{
+ CMutexLock lock(&gcsFastProcessLock);
+
+ if (0 == _pdsaLocalBindings)
+ {
+ return(0);
+ }
+
+ DUALSTRINGARRAY *T = (DUALSTRINGARRAY *)MIDL_user_allocate(sizeof(DUALSTRINGARRAY)
+ + sizeof(USHORT) * _pdsaLocalBindings->wNumEntries);
+
+ if (0 != T)
+ {
+ dsaCopy(T, _pdsaLocalBindings);
+ }
+
+ return(T);
+}
+
+DUALSTRINGARRAY *
+CProcess::GetRemoteBindings(void)
+// Server lock held.
+{
+ CMutexLock lock(&gcsFastProcessLock);
+
+ ORSTATUS Status;
+
+ if (0 == _pdsaRemoteBindings)
+ {
+ if (0 == _pdsaLocalBindings)
+ {
+ return(0);
+ }
+
+ Status = ConvertToRemote(_pdsaLocalBindings, &_pdsaRemoteBindings);
+
+ if (Status != OR_OK)
+ {
+ ASSERT(Status == OR_NOMEM);
+ return(0);
+ }
+ ASSERT(dsaValid(_pdsaRemoteBindings));
+ }
+
+ DUALSTRINGARRAY *T = (DUALSTRINGARRAY *)MIDL_user_allocate(sizeof(DUALSTRINGARRAY)
+ + sizeof(USHORT) * _pdsaRemoteBindings->wNumEntries);
+
+ if (0 != T)
+ {
+ dsaCopy(T, _pdsaRemoteBindings);
+ }
+
+ ASSERT(dsaValid(T));
+ return(T);
+}
+
+
+ORSTATUS
+CProcess::AddOxid(CServerOxid *pOxid)
+{
+ ASSERT(gpServerLock->HeldExclusive());
+
+ pOxid->Reference();
+
+ ASSERT(_blistOxids.Member(pOxid) == FALSE);
+
+ ORSTATUS status = _blistOxids.Insert(pOxid);
+
+ if (status != OR_OK)
+ {
+ pOxid->ProcessRelease();
+ return(status);
+ }
+
+ gpServerOxidTable->Add(pOxid);
+
+ return(OR_OK);
+}
+
+BOOL
+CProcess::RemoveOxid(CServerOxid *poxid)
+{
+ ASSERT(gpServerLock->HeldExclusive());
+
+ CServerOxid *pit = (CServerOxid *)_blistOxids.Remove(poxid);
+
+ if (pit)
+ {
+ ASSERT(pit == poxid);
+ gpServerOxidTable->Remove(poxid);
+ poxid->ProcessRelease();
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
+
+ORSTATUS
+CProcess::AddRemoteOxid(
+ IN CClientOxid *poxid
+ )
+/*++
+
+Routine Description:
+
+ Adds a client OXID to the set of OXIDs in use by the client
+ process. OXIDs are added during resolve and removed during
+ bulk update or when the process dies.
+
+Arguments:
+
+ poxid - the OXID at add. Will reference the OXID if
+ successful.
+
+Return Value:
+
+ OR_NOMEM
+
+--*/
+{
+ ASSERT(gpClientLock->HeldExclusive());
+
+ poxid->Reference();
+
+ ORSTATUS status = _blistRemoteOxids.Insert(poxid);
+
+ if (status != OR_OK)
+ {
+ poxid->Release();
+ }
+
+ return(status);
+}
+
+
+void
+CProcess::RemoveRemoteOxid(
+ IN CClientOxid *poxid
+ )
+/*++
+
+Routine Description:
+
+ Removes an oxid from the set of oxids in use by this process.
+
+Arguments:
+
+ poxid - The oxid to remove.
+
+Return Value:
+
+ None
+
+--*/
+{
+ ASSERT(gpClientLock->HeldExclusive());
+
+ CClientOxid *pit = (CClientOxid *)_blistRemoteOxids.Remove(poxid);
+
+ if (pit)
+ {
+ ASSERT(pit == poxid);
+ poxid->Release();
+ }
+ else
+ {
+ OrDbgPrint(("OR: Process %p removed oxid %p which it didn't own\n",
+ this, poxid));
+ ASSERT(0); // BUGBUG
+ }
+}
+
+BOOL
+CProcess::IsOwner(CServerOxid *poxid)
+{
+ ASSERT(gpServerLock->HeldExclusive());
+
+ return (_blistOxids.Member(poxid));
+}
+
+ORSTATUS
+CProcess::AddOid(CClientOid *poid)
+/*++
+
+Routine Description:
+
+ Adds a new oid to the list of OIDs owned by this process.
+
+Arguments:
+
+ poid - the oid to add. It's reference is transferred to this
+ function. If this function fails, it must dereference the oid.
+ The caller passed a client reference to this process. The
+ process must eventually call ClientRelease() on the parameter.
+
+Return Value:
+
+ OR_OK - normally
+
+ OR_NOMEM - out of memory.
+
+--*/
+
+{
+ ORSTATUS status;
+
+ ASSERT(gpClientLock->HeldExclusive());
+
+ status = _blistOids.Insert(poid);
+
+ if (status != OR_OK)
+ {
+ ASSERT(status == OR_NOMEM);
+ poid->ClientRelease();
+ }
+
+ return(status);
+}
+
+CClientOid *
+CProcess::RemoveOid(CClientOid *poid)
+/*++
+
+Routine Description:
+
+ Removes an OID from this list of OID in use by this process.
+
+Arguments:
+
+ poid - The OID to remove.
+
+Return Value:
+
+ non-zero - the pointer actually remove. (ASSERT(retval == poid))
+ It will be released by the process before return,
+ so you should not use the pointer unless you know you
+ have another reference.
+
+ 0 - not in the list
+
+--*/
+
+{
+ ASSERT(gpClientLock->HeldExclusive());
+
+ CClientOid *pit = (CClientOid *)_blistOids.Remove(poid);
+
+ if (pit)
+ {
+ ASSERT(pit == poid);
+
+ pit->ClientRelease();
+ return(pit);
+ }
+
+ return(0);
+}
+
+void
+CProcess::AddClassReg(GUID Clsid, DWORD Reg)
+{
+ CClassReg * pReg;
+
+ pReg = new CClassReg( Clsid, Reg );
+
+ if (pReg)
+ {
+ gpServerLock->LockExclusive();
+
+ _listClasses.Insert((CListElement *)pReg);
+
+ gpServerLock->UnlockExclusive();
+ }
+}
+
+void
+CProcess::RemoveClassReg(GUID Clsid, DWORD Reg)
+{
+ CClassReg * pReg;
+
+ gpServerLock->LockExclusive();
+
+ pReg = (CClassReg *)_listClasses.First();
+
+ while ( (pReg != NULL) && (pReg->Reg != Reg) )
+ pReg = (CClassReg *)pReg->Next();
+
+ if (pReg)
+ {
+ (void)_listClasses.Remove((CListElement *)pReg);
+ delete pReg;
+ }
+
+ gpServerLock->UnlockExclusive();
+}
+
+RPC_BINDING_HANDLE
+CProcess::GetBindingHandle(
+ void
+ )
+/*++
+
+Routine Description:
+
+ If necessary, this function allocates a binding handle
+ back to process. It used either mswmsg or ncalrpc depending
+ on the apartmentness of the process.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Binding Handle, NULL if no valid handle.
+
+--*/
+{
+ RPC_STATUS status;
+
+ CMutexLock lock(&gcsFastProcessLock);
+
+ // Find ncalrpc binding.
+ PWSTR pwstr = _pdsaLocalBindings->aStringArray;
+ while(*pwstr)
+ {
+ if (*pwstr == ID_LPC)
+ {
+ break;
+ }
+ pwstr = OrStringSearch(pwstr, 0) + 1;
+ }
+
+ if (*pwstr == 0)
+ {
+ OrDbgPrint(("OR: Unable to find ncalrpc binding to server: %p %p\n",
+ _pdsaLocalBindings, this));
+ ASSERT(0);
+ return NULL;
+ }
+
+ return GetBinding(pwstr);
+}
+
+void
+CProcess::EnsureRealBinding(
+ void
+ )
+/*++
+
+Routine Description:
+
+ If necessary, this function allocates a binding handle
+ back to process. It used either mswmsg or ncalrpc depending
+ on the apartmentness of the process.
+
+ Note: Called with the server lock held -OR- from an OXID
+ with and extra reference which keeps this process alive.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ RPC_STATUS status;
+
+ CMutexLock lock(&gcsFastProcessLock);
+
+ if (0 == _hProcess)
+ {
+ _hProcess = GetBindingHandle();
+ _fCacheFree = TRUE;
+
+ if (_hProcess)
+ {
+ status = I_RpcBindingSetAsync(_hProcess, 0);
+ }
+ }
+}
+
+RPC_BINDING_HANDLE
+CProcess::AllocateBinding(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Allocates a unique binding handle for a call back
+ to the process. This binding handle will not be
+ used by another thread until it is freed.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ 0 - failure
+
+ non-zero - a binding handle to use.
+
+--*/
+{
+
+ EnsureRealBinding();
+
+ if (_hProcess == 0)
+ {
+ return(0);
+ }
+
+ CMutexLock lock(&gcsFastProcessLock);
+
+ ASSERT(_hProcess);
+
+ if (_fCacheFree)
+ {
+ _fCacheFree = FALSE;
+ return(_hProcess);
+ }
+
+ RPC_BINDING_HANDLE h;
+ RPC_STATUS status;
+
+ status = RpcBindingCopy(_hProcess, &h);
+
+ if (status != RPC_S_OK)
+ {
+ return(0);
+ }
+
+ status = I_RpcBindingSetAsync(h, 0);
+ ASSERT(status == RPC_S_OK);
+
+ return(h);
+}
+
+
+void
+CProcess::FreeBinding(
+ IN RPC_BINDING_HANDLE hBinding
+ )
+/*++
+
+Routine Description:
+
+ Frees a binding back to the process.
+
+Arguments:
+
+ hBinding - A binding back to the process previously
+ allocated with AllocateBinding().
+
+Return Value:
+
+ None
+
+--*/
+{
+ if (hBinding == _hProcess)
+ {
+ _fCacheFree = TRUE;
+ }
+ else
+ {
+ RPC_STATUS status = RpcBindingFree(&hBinding);
+ ASSERT(status == RPC_S_OK);
+ }
+}
+
+void
+CProcess::RundownOids(
+ IN USHORT cOids,
+ IN OID aOids[],
+ IN UUID ipidUnk,
+ OUT BYTE afRundownOk[]
+
+ )
+/*++
+
+Routine Description:
+
+ Attempts to callback to the process which will rundown the OIDs.
+ This is called from an OXID which will be kept alive during the
+ whole call. Multiple calls maybe made to this function by
+ one or more OXIDs at the same time. The callback itself is
+ an ORPC call, ie is must have THIS and THAT pointers.
+
+Arguments:
+
+ cOids - The number of entries in aOids and afRundownOk
+
+ aOids - An array of cOids IDs to rundown. The OIDs must
+ all be owned by the same OXID.
+
+ ipidUnk - The IPID of the IRemUnknown interface to use
+ during the callback.
+
+ afRundownOk - An array of cOids BOOLs. Upon completion if
+ an entry is TRUE, the corresponding OID in aOids has
+ been fully rundown.
+
+Return Value:
+
+ None - see afRundownOk parameter.
+
+--*/
+
+{
+ error_status_t status = OR_OK;
+ int i;
+ INT hint;
+ ORPCTHIS orpcthis;
+ LOCALTHIS localthis;
+ ORPCTHAT orpcthat;
+ RPC_BINDING_HANDLE hBinding;
+
+ gpServerLock->UnlockExclusive();
+
+ // This process will be held alive by the OXID calling
+ // us since it has an extra reference.
+
+ hBinding = AllocateBinding();
+
+ if (0 == hBinding)
+ {
+ status = OR_NOMEM;
+ }
+
+#if DBG
+ CMutexLock lock(&_csCallbackLock);
+ CTime start;
+ _cRundowns++;
+
+ if (_cRundowns == 1)
+ {
+ _timeFirstRundown.SetNow();
+ }
+
+ if (start - _timeFirstRundown > 120 || _cRundowns > 10)
+ {
+ OrDbgPrint(("OR: Process %p, first rundown %d seconds ago, %d rundown threads\n",
+ this, start - _timeFirstRundown, _cRundowns));
+ }
+ lock.Unlock();
+#endif
+
+ orpcthis.version.MajorVersion = COM_MAJOR_VERSION;
+ orpcthis.version.MinorVersion = COM_MINOR_VERSION;
+ orpcthis.flags = ORPCF_LOCAL;
+ orpcthis.reserved1 = 0;
+ orpcthis.extensions = NULL;
+ hint = AllocateCallId(orpcthis.cid);
+ localthis.dwClientThread = 0;
+ localthis.callcat = CALLCAT_SYNCHRONOUS;
+ orpcthat.flags = 0;
+ orpcthat.extensions = 0;
+
+ if (status == RPC_S_OK)
+ {
+ status = RpcBindingSetObject(hBinding, &ipidUnk);
+ }
+
+ if (status == RPC_S_OK)
+ {
+ status = RawRundownOid(
+ hBinding,
+ &orpcthis,
+ &localthis,
+ &orpcthat,
+ cOids,
+ aOids,
+ afRundownOk
+ );
+ }
+
+#if DBG
+ lock.Lock();
+ CTime end;
+ _cRundowns--;
+
+ if (_cRundowns > 0 || (end - start > 120))
+ {
+ OrDbgPrint(("OR: Process %p: rundown status %d. %d seconds for rundown, %d waiting\n",
+ this, status, _cRundowns, end - start));
+ }
+#endif
+
+ if (orpcthat.extensions)
+ {
+ for (int i = 0; i < orpcthat.extensions->size; i++)
+ {
+ MIDL_user_free(orpcthat.extensions->extent[i]);
+ }
+ MIDL_user_free(orpcthat.extensions);
+ }
+
+ if (status != RPC_S_OK)
+ {
+ OrDbgPrint(("OR: Rundown failed: (%p, %p, %p) - %d\n",
+ aOids, this, hBinding, status));
+ }
+
+ if (status == RPC_E_DISCONNECTED)
+ {
+ OrDbgPrint(("OR: Rundown returned disconnected\n"));
+ for(USHORT i = 0; i < cOids; i++)
+ {
+ afRundownOk[i] = TRUE;
+ }
+ status = RPC_S_OK;
+ }
+
+ if (status != RPC_S_OK)
+ {
+ for(USHORT i = 0; i < cOids; i++)
+ {
+ afRundownOk[i] = FALSE;
+ }
+ }
+
+ if (hBinding)
+ {
+ FreeBinding(hBinding);
+ }
+
+ FreeCallId(hint);
+}
+
+ORSTATUS
+CProcess::UseProtseqIfNeeded(
+ IN USHORT cClientProtseqs,
+ IN USHORT aClientProtseqs[]
+ )
+{
+ ORSTATUS status;
+ RPC_BINDING_HANDLE hBinding;
+ UUID NullUuid = { 0 };
+
+ hBinding = AllocateBinding();
+
+ if (0 == hBinding)
+ {
+ return(OR_NOMEM);
+ }
+
+ // This process will be held alive by the OXID calling
+ // us since it has an extra reference.
+
+ CMutexLock callback(&_csCallbackLock);
+
+ CMutexLock process(&gcsFastProcessLock);
+
+ // Another thread may have used the protseq in the mean time.
+
+ ASSERT(_pdsaLocalBindings);
+
+ USHORT protseq = FindMatchingProtseq(cClientProtseqs,
+ aClientProtseqs,
+ _pdsaLocalBindings->aStringArray
+ );
+
+ if (0 != protseq)
+ {
+ FreeBinding(hBinding);
+ return(OR_OK);
+ }
+
+ // No protseq shared between the client and the OXIDs' server.
+ // Find a matching protseq.
+
+ PWSTR pwstrProtseq = 0;
+
+ if (cClientProtseqs == 1 && IsLocal(aClientProtseqs[0]))
+ {
+ pwstrProtseq = GetProtseq(aClientProtseqs[0]);
+ ASSERT(pwstrProtseq);
+ }
+ else
+ {
+
+ USHORT i,j;
+
+ for(i = 0; i < cClientProtseqs && pwstrProtseq == 0; i++)
+ {
+ for(j = 0; j < cMyProtseqs; j++)
+ {
+ if (aMyProtseqs[j] == aClientProtseqs[i])
+ {
+ ASSERT(FALSE == IsLocal(aMyProtseqs[j]));
+
+ pwstrProtseq = GetProtseq(aMyProtseqs[j]);
+ break;
+ }
+ }
+ }
+ }
+
+ if (0 == pwstrProtseq)
+ {
+ // No shared protseq, must be a bug since the client managed to call us.
+#if DBG
+ if (cClientProtseqs == 0)
+ {
+ OrDbgPrint(("OR: Client OR not configured to use remote protseqs\n"));
+ }
+ else
+ {
+ OrDbgPrint(("OR: Client called on an unsupported protocol:"
+ "%d %p %p \n", cClientProtseqs, aClientProtseqs, aMyProtseqs));
+ ASSERT(0);
+ }
+#endif
+
+ FreeBinding(hBinding);
+ return(OR_NOSERVER);
+ }
+
+ process.Unlock();
+
+ DUALSTRINGARRAY *pdsaBinding = 0;
+ DUALSTRINGARRAY *pdsaSecurity = 0;
+
+ status = RpcBindingSetObject(hBinding, &NullUuid);
+
+ if (status == RPC_S_OK)
+ {
+ status = ::UseProtseq(hBinding,
+ pwstrProtseq,
+ &pdsaBinding,
+ &pdsaSecurity);
+ }
+
+ OrDbgPrint(("OR: Lazy use protseq: %S in process %p - %d\n",
+ pwstrProtseq, this, status));
+
+ // Update this process' state to include the new bindings.
+
+ if (!dsaValid(pdsaBinding))
+ {
+ if (pdsaBinding)
+ {
+ OrDbgPrint(("OR: Use protseq returned an invalid dsa: %p\n",
+ pdsaBinding));
+ }
+ status = OR_NOMEM;
+ }
+ else
+ {
+ ASSERT(_pdsaLocalBindings);
+ ASSERT(status == RPC_S_OK);
+ status = ProcessBindings(pdsaBinding,
+ pdsaSecurity);
+ }
+
+ if (pdsaBinding != NULL)
+ MIDL_user_free(pdsaBinding);
+ if (pdsaSecurity != NULL)
+ MIDL_user_free(pdsaSecurity);
+
+ FreeBinding(hBinding);
+ return(status);
+}
+
+CRITICAL_SECTION gcsProcessManagerLock;
+CBList *gpProcessList = 0;
+
+CProcess *
+ReferenceProcess(
+ IN PVOID key,
+ IN BOOL fNotContext)
+/*++
+
+Routine Description:
+
+ Used to find a CProcess and get a reference on it
+
+Arguments:
+
+ key - The dword key of the process allocated in _Connect.
+ fNotContext - Normally the key is stored as a context handle
+ which means locking is unnecessary. There is an extra
+ refernce which is released buring context rundown which
+ means managers using the key as a context handle
+ a) Don't need to lock the process and
+ b) Don't need to call ReleaseProcess()
+
+Return Value:
+
+ 0 - invalid key
+ non-zero - The process.
+
+--*/
+{
+ ASSERT(gpProcessList != 0);
+ CProcess *pProcess;
+
+ CMutexLock lock(&gcsProcessManagerLock);
+
+ if (gpProcessList->Member(key) == FALSE)
+ {
+ return(0);
+ }
+
+ pProcess = (CProcess *)key;
+
+ if (fNotContext)
+ {
+ if (pProcess->CheckSecurity() == FALSE)
+ {
+ OrDbgPrint(("OR: Process %p, security check failed on SCM call\n"));
+ pProcess = 0;
+ }
+ else
+ {
+ pProcess->ClientReference();
+ }
+ }
+
+ return(pProcess);
+}
+
+void ReleaseProcess(CProcess *pProcess)
+/*++
+
+Routine Description:
+
+ Releases a pProcess object. This should only be called when
+ a process object has been referenced with the fNotContext == TRUE.
+
+Arguments:
+
+ pProcess - the process to release. May actually be deleted.
+
+Return Value:
+
+ None
+
+--*/
+{
+ CMutexLock lock(&gcsProcessManagerLock);
+
+ if (pProcess->ClientRelease() == 0)
+ {
+ // Process has been completly released the process,
+ // we'll remove it from the list now since we
+ // already have the lock. It may not have been added,
+ // so this may fail.
+
+ PVOID t = gpProcessList->Remove(pProcess);
+ ASSERT(t == pProcess || t == 0);
+
+ lock.Unlock();
+
+ // The client process owns one real reference which will be
+ // released in Rundown().
+
+ pProcess->Rundown();
+ }
+}
+
diff --git a/private/ole32/dcomss/objex/process.hxx b/private/ole32/dcomss/objex/process.hxx
new file mode 100644
index 000000000..eb029be78
--- /dev/null
+++ b/private/ole32/dcomss/objex/process.hxx
@@ -0,0 +1,192 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Process.hxx
+
+Abstract:
+
+ Process objects represent local clients and servers. These
+ objects live as context handles.
+
+ There are relativly few of these objects in the universe.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-11-95 Bits 'n pieces
+ MarioGo 01-06-96 Based on CReferencedObject
+
+--*/
+
+#ifndef __PROCESS_HXX
+#define __PROCESS_HXX
+
+void CheckRemoteSecurity(
+ handle_t hClient,
+ CToken *pToken
+ );
+
+void
+CheckLocalSecurity(
+ handle_t hClient,
+ CProcess *pProcess
+ );
+
+class CClassReg;
+
+class CProcess : public CReferencedObject
+/*++
+
+Class Description:
+
+ An instance of this class is created for each process
+ using the OR as either a client or server.
+
+ The process object is referenced by server OXIDs and has
+ one implicit reference by the actual process (which is
+ dereferenced during the context rundown). Instances of
+ these objects are managed by the RPC runtime as context
+ handles.
+
+Members:
+
+ _pToken - A pointer to the CToken instance of the process.
+
+ _csCallbackLock - use to serialize callback to LazyUseProtseq
+
+ _hProcess - An RPC binding handle back to the process.
+
+ _pdsaLocalBindings - The string bindings of the process, including
+ local only protseqs
+
+ _pdsaRemoteBindings - A subset of _pdsaLocalBindings not containing
+ any local-only protseqs
+
+ _blistOxids - A CBList containing pointers to the CServerOxid's
+ owned by this process, if any.
+
+ _blistOids - A CBList of pointers to CClientOid's which this
+ process is using and referencing, if any.
+
+ _blistClasses - A CBList of registration handles for classes that
+ a server process has registered.
+
+--*/
+ {
+
+ private:
+
+ DWORD _cClientReferences;
+ CToken *_pToken;
+ RPC_BINDING_HANDLE _hProcess;
+ BOOL _fCacheFree;
+ DUALSTRINGARRAY *_pdsaLocalBindings;
+ DUALSTRINGARRAY *_pdsaRemoteBindings;
+ CBList _blistOxids;
+ CBList _blistOids;
+ CBList _blistRemoteOxids;
+ CList _listClasses;
+ CRITICAL_SECTION _csCallbackLock;
+ BOOL _fLockValid:1;
+
+#if DBG
+ // Debug members used to monitor and track rundown callbacks
+ ULONG _cRundowns;
+ CTime _timeFirstRundown;
+#endif
+
+ void EnsureRealBinding();
+
+ RPC_BINDING_HANDLE AllocateBinding();
+
+ void FreeBinding(RPC_BINDING_HANDLE);
+
+public:
+
+ CProcess(IN CToken *pToken,
+ OUT ORSTATUS &status);
+
+ ~CProcess();
+
+ RPC_STATUS ProcessBindings(DUALSTRINGARRAY *,
+ DUALSTRINGARRAY *);
+
+ DUALSTRINGARRAY *GetLocalBindings(void);
+
+ DUALSTRINGARRAY *GetRemoteBindings(void);
+
+ RPC_BINDING_HANDLE GetBindingHandle(void);
+
+ ORSTATUS AddOxid(CServerOxid *);
+
+ BOOL RemoveOxid(CServerOxid *);
+
+ ORSTATUS AddRemoteOxid(CClientOxid *);
+
+ void RemoveRemoteOxid(CClientOxid *);
+
+ BOOL IsOwner(CServerOxid *);
+
+ ORSTATUS AddOid(CClientOid *);
+
+ CClientOid *RemoveOid(CClientOid *);
+
+ void AddClassReg(GUID Clsid, DWORD Reg);
+
+ void RemoveClassReg(GUID Clsid, DWORD Reg);
+
+ void RundownOids(USHORT cOids, OID aOids[], UUID ipidUnk, BYTE aStatus[]);
+
+ ORSTATUS UseProtseqIfNeeded(USHORT cClientProtseqs, USHORT aProtseqs[]);
+
+ void Rundown();
+
+ BOOL CheckSecurity() {
+ // BUGBUG!!!
+ return(TRUE);
+ }
+
+ CToken *GetToken() {
+ return(_pToken);
+ }
+
+ void ClientReference() {
+ _cClientReferences++;
+ }
+
+ DWORD ClientRelease()
+ {
+ _cClientReferences--;
+ return(_cClientReferences);
+ }
+ };
+
+class CClassReg : public CListElement
+ {
+ public :
+ GUID Clsid;
+ DWORD Reg;
+
+ CClassReg( GUID clsid, DWORD reg ) : Clsid(clsid), Reg(reg) {}
+ };
+
+void SCMRemoveRegistration(
+ GUID Clsid,
+ PSID pSid,
+ DWORD Reg );
+
+extern CRITICAL_SECTION gcsFastProcessLock;
+
+extern CRITICAL_SECTION gcsProcessManagerLock;
+extern CBList *gpProcessList;
+
+CProcess *ReferenceProcess(PVOID key, BOOL fNotContext = FALSE);
+void ReleaseProcess(CProcess *pProcess);
+
+#endif // __PROCESS_HXX
diff --git a/private/ole32/dcomss/objex/refobj.hxx b/private/ole32/dcomss/objex/refobj.hxx
new file mode 100644
index 000000000..89e7fb382
--- /dev/null
+++ b/private/ole32/dcomss/objex/refobj.hxx
@@ -0,0 +1,70 @@
+
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ RefObj.hxx
+
+Abstract:
+
+ Generic base class for reference counted objects.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 12-15-95 Bits in the 'ol bucket
+
+--*/
+
+#ifndef __REFERENCED_OBJECTS_HXX
+#define __REFERENCED_OBJECTS_HXX
+
+class CReferencedObject
+{
+ public:
+
+ CReferencedObject() : _references(1) { }
+ virtual ~CReferencedObject() { ASSERT(_references == 0); }
+ virtual void Reference()
+ {
+ ASSERT(_references >= 0);
+ _references++;
+ }
+
+ virtual DWORD Release()
+ {
+ if ( 0 == Dereference())
+ {
+ delete this;
+ return(0);
+ }
+ // this pointer maybe invalid here.
+ return(1);
+ }
+
+ LONG Dereference()
+ // Used for objects which override Release().
+ {
+ ASSERT(_references);
+ return(_references--);
+ }
+
+ DWORD References()
+ {
+ // Must be called an exclusive lock held or it is meaningless.
+ ASSERT(_references >= 0);
+ return(_references);
+ }
+
+ private:
+
+ CInterlockedInteger _references;
+ };
+
+#endif // __REFERENCED_OBJECTS_HXX
+
diff --git a/private/ole32/dcomss/objex/shrmem/client/clt.cxx b/private/ole32/dcomss/objex/shrmem/client/clt.cxx
new file mode 100644
index 000000000..cd2c094e5
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/client/clt.cxx
@@ -0,0 +1,227 @@
+
+#include <or.hxx>
+#include <simpleLL.hxx>
+
+handle_t SMTBinding;
+
+DECLARE_INFOLEVEL(Cairole)
+
+void
+ClientSetup()
+{
+ WCHAR other[10];
+ RPC_STATUS status = 1;
+ RPC_NS_HANDLE ImportContext = NULL;
+ TCHAR * pszStringBinding = NULL;
+
+ /*
+
+ printf("Other = ");
+ scanf("%S",other);
+
+ WCHAR* entryName = catenate(TEXT("/.:/ShareTest"),other);
+
+ status = RpcNsBindingImportBegin(
+ NULL,
+ entryName,
+ SharedMemoryTest_ClientIfHandle,
+ NULL,
+ &ImportContext
+ );
+
+ printf("RpcNsBindingImportBegin returned 0x%x\n", status);
+ if (status)
+ exit(status);
+
+ if (!ImportContext) {
+ printf("No Import Context Available", status);
+ exit(1);
+ }
+
+ status = RpcNsBindingImportNext(
+ ImportContext,
+ &SMTBinding);
+
+ printf("RpcNsBindingImportNext returned 0x%x\n", status);
+
+ if (!status) {
+ RpcBindingToStringBinding(
+ SMTBinding,
+ &pszStringBinding
+ );
+
+ printf("Binding = %S\n",pszStringBinding);
+ RpcStringFree(&pszStringBinding);
+ }
+ */
+
+ status = RpcStringBindingCompose(
+ NULL,
+ TEXT("ncalrpc"),
+ NULL,
+ NULL,
+ NULL,
+ &pszStringBinding
+ );
+
+ if (!status) {
+ RpcBindingFromStringBinding(
+ pszStringBinding,
+ &SMTBinding
+ );
+ }
+
+ if (status || !SMTBinding)
+ {
+ printf("No Binding Handle Available", status);
+ exit(1);
+ }
+
+ /*
+ status = RpcNsBindingImportDone(&ImportContext);
+ */
+}
+
+
+void
+TestSimple()
+{
+ long *x = (long*) OrMemAlloc(sizeof(long));
+ *x = rand();
+
+ printf("Calling the remote procedure 'RemoteRead'\n");
+
+ long answer;
+
+ RpcTryExcept {
+ RemoteRead((ULONG)OR_OFFSET(x), &answer); // make call with user message
+ }
+ RpcExcept(1) {
+ RPC_STATUS ulCode = RpcExceptionCode();
+ printf("Runtime reported exception 0x%lx \n", ulCode);
+ exit(ulCode);
+ }
+ RpcEndExcept
+
+ if (answer == *x) printf("Simple Success!\n");
+ else printf("Failure!\n");
+}
+
+void
+TestList()
+{
+ CSimpleLinkList OR_BASED *pList = NEW_OR_BASED_SIMPLE(CSimpleLinkList);
+
+ unsigned long i;
+
+ for (i = 0; i < 10; i++)
+ {
+ unsigned long next = rand();
+ pList->insert((void*)next);
+ printf("Inserted %d\n",next);
+ }
+
+ CSimpleLinkListIterator Iter(*OR_FULL_POINTER(CSimpleLinkList,pList));
+
+ SendList((based_ptr) pList);
+
+ unsigned long answer;
+
+ for (i = 0; i < 10; i++)
+ {
+ ReadNext(&answer);
+ if (answer == (unsigned long)Iter.next()) printf("List Success for %d\n",answer);
+ }
+}
+
+void
+TestLocalResolverAPI()
+{
+ HPROCESS hProcess;
+ DWORD dwTimeoutInSeconds;
+ MID LocalMid, Mid;
+ BOOL DisableDCOM;
+ DWORD AuthnLevel;
+ DWORD ImpLevel;
+ BOOL MutualAuth;
+ DWORD cServerSvc;
+ USHORT *aServerSvc;
+ DWORD cClientSvc;
+ USHORT *aClientSvc;
+
+ ID Oxid;
+
+ ID aOids[2];
+
+ long Status;
+
+ OXID_INFO oxidInfo;
+
+ Status = ConnectDCOM(
+ &hProcess,
+ &dwTimeoutInSeconds,
+ &LocalMid,
+ &DisableDCOM,
+ &AuthnLevel,
+ &ImpLevel,
+ &MutualAuth,
+ &cServerSvc,
+ &aServerSvc,
+ &cClientSvc,
+ &aClientSvc
+ );
+
+ GetIds(&Oxid,&aOids[0]);
+
+ Status = ResolveOXID(
+ hProcess,
+ Oxid,
+ NULL,
+ FALSE,
+ oxidInfo,
+ Mid
+ );
+
+ Status = ClientAddOID(
+ hProcess,
+ aOids[0],
+ Oxid,
+ Mid
+ );
+
+ Status = ClientDropOID(
+ hProcess,
+ aOids[0],
+ Mid
+ );
+
+ ShutDown();
+}
+
+
+void __cdecl
+main()
+{
+ srand(GetCurrentTime());
+
+ ClientSetup();
+ TestLocalResolverAPI();
+
+ RPC_STATUS status = RpcBindingFree(&SMTBinding);
+ printf("RpcBindingFree returned 0x%x\n", status);
+ if (status)
+ exit(status);
+}
+
+
+/* MIDL allocate and free */
+
+void __RPC_FAR * __RPC_API midl_user_allocate(size_t len)
+{
+ return(malloc(len));
+}
+
+void __RPC_API midl_user_free(void __RPC_FAR * ptr)
+{
+ free(ptr);
+}
diff --git a/private/ole32/dcomss/objex/shrmem/client/makefile b/private/ole32/dcomss/objex/shrmem/client/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/client/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/dcomss/objex/shrmem/client/sources b/private/ole32/dcomss/objex/shrmem/client/sources
new file mode 100644
index 000000000..6df535a1c
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/client/sources
@@ -0,0 +1,109 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+!IF "$(NTDEBUG)" != "ntsd"
+CXXCPP_OPTIONS=-DDBG=0
+!else
+CXXCPP_OPTIONS=-DDBG=1
+DEBUG_DEFINES=-DLDEBUG
+MSC_OPTIMIZATION=/Od
+!endif
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= clt
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= ..\bin
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= PROGRAM
+
+PRECOMPILED_INCLUDE= ..\or.hxx
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include \nt\private\ole32\daytona.inc
+
+INCLUDES=..;..\dcom95;..\stg;C:\nt\private\ole32\dcomss;\nt\private\ole32\ih;\nt\private\ole32\com\inc;\nt\private\ole32\common\daytona;\nt\private\ole32\stg\docfile;\nt\private\ole32\stg\h;C:\nt\private\dcomidl\obj;C:\nt\private\ole32\stg\exp
+
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DMULTIHEAP
+
+SOURCES= \
+ clt.cxx \
+ test_c.c
+
+LIBDIR=$(_NTDRIVE)\nt\public\sdk\lib
+
+OLEDIR=$(_NTDRIVE)\nt\private\ole32
+
+LINKLIBS=$(LIBDIR)\*\Rpcrt4.lib \
+ $(LIBDIR)\*\RpcNdr.lib \
+ $(LIBDIR)\*\ntdll.lib \
+ $(LIBDIR)\*\uuid.lib \
+ $(LIBDIR)\*\user32.lib \
+ $(LIBDIR)\*\security.lib \
+ $(LIBDIR)\*\ole32.lib \
+ $(OLEDIR)\common\daytona\obj\*\common.lib \
+ $(OLEDIR)\com\inc\daytona\obj\*\inc.lib \
+ ..\lib\*\stg.lib \
+ ..\lib\*\dcom95.lib \
+ ..\lib\*\special.lib
+
+USE_LIBCMT=1
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+PRECOMPILED_OPTION=
+#PRECOMPILED_TARGET=..\obj\*\$(PRECOMPILED_PCH)
+PRECOMPILED_CXX=
+
diff --git a/private/ole32/dcomss/objex/shrmem/daytona.inc b/private/ole32/dcomss/objex/shrmem/daytona.inc
new file mode 100644
index 000000000..e6bcee983
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/daytona.inc
@@ -0,0 +1,39 @@
+!IF "$(NTDEBUG)" != "ntsd"
+CXXCPP_OPTIONS=-DDBG=0
+!else
+CXXCPP_OPTIONS=-DDBG=1
+DEBUG_DEFINES=-DLDEBUG
+MSC_OPTIMIZATION=/Od
+!endif
+
+MAJORCOMP= cairole
+MINORCOMP= dcom95
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+OLEDIR= $(_NTDRIVE)\nt\private\ole32
+
+!include $(OLEDIR)\daytona.inc
+
+INCLUDES= ..; \
+ ..\..; \
+ ..\..\dcom95; \
+ $(_NTDRIVE)\nt\private\ole32\ih; \
+ $(_NTDRIVE)\nt\private\ole32\com\inc; \
+ $(_NTDRIVE)\nt\private\ole32\common\daytona; \
+ $(_NTDRIVE)\nt\private\ole32\stg\h; \
+ $(_NTDRIVE)\nt\private\dcomidl\obj; \
+ $(_NTDRIVE)\nt\private\ole32\stg\exp; \
+ $(_NTDRIVE)\nt\private\ole32\com\dcomrem; \
+ $(_NTDRIVE)\nt\private\ole32\dcomss
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -D_REMOTE_OR_ \
+ -DSHRMEM_OBJEX
+
+PRECOMPILED_INCLUDE= ..\..\or.hxx
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/base.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/base.hxx
new file mode 100644
index 000000000..efb1784c0
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/base.hxx
@@ -0,0 +1,240 @@
+#ifndef __SHARE_HXX__
+#define __SHARE_HXX__
+
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+
+extern void DfReleaseSharedMemBase ();
+
+#define olAssert(exp) Win4Assert(exp)
+
+#include <sem.hxx>
+#include <smcreate.hxx>
+#include <entry.hxx>
+#include <smalloc.hxx>
+#include <df32.hxx>
+
+#ifdef _CHICAGO_
+#define gSharedAllocator g_smAllocator
+#else // _CHICAGO_
+#define gSharedAllocator gsmDCOMAllocator
+#endif // _CHICAGO_
+
+extern CSmAllocator gSharedAllocator; // global shared memory allocator
+
+extern void *pSharedBase;
+
+HRESULT InitDCOMSharedAllocator(ULONG,void*&);
+
+typedef unsigned long based_ptr;
+
+
+//+-------------------------------------------------------------------
+//
+// Function: OrMemAlloc for Memphis
+//
+// Synopsis: Allocate some shared memory from the storage heap.
+//
+// Notes: Also used in an NT version for debugging purposes
+//
+//--------------------------------------------------------------------
+inline void *OrMemAlloc(size_t size)
+{
+ return gSharedAllocator.Alloc(size);
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: OrMemFree for Memphis
+//
+// Synopsis: Free shared memory from the storage heap.
+//
+// Notes: Also used in an NT version for debugging purposes
+//
+//--------------------------------------------------------------------
+inline void OrMemFree(void * pv)
+{
+ gSharedAllocator.Free(pv);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Macros: OR_FULL_POINTER, OR_OFFSET, NEW_OR_BASED,
+// DELETE_OR_BASED and OR_BASED
+//
+// Synopsis: Typeful pointer arithmetic to adjust based pointers, and
+// satisfy the needs of new and delete operator prototypes.
+//
+// Notes: As a general policy, we do not use based pointers in
+// interfaces -- their use is confined to private members
+// of shared objects only. This policy is dictated by
+// the need to work around certain apparent compiler bugs
+// in casting based pointers, and also makes for simplicity.
+// The pragma is also part of the workaround, but disabled for now.
+//
+//--------------------------------------------------------------------
+
+
+//#pragma warning(error: 4795 4796)
+
+#ifndef _CHICAGO_
+
+#define OR_BASED __based(pSharedBase)
+
+#define OR_FULL_POINTER(TYPE,BASEDPTR) \
+ ((TYPE*) (((BASEDPTR) != 0) ? (BASEDPTR) : 0))
+
+/*
+
+inline
+void OR_BASED *
+OR_OFFSET(void *pv)
+{
+ if (pv) return (void OR_BASED *)pv;
+ else return 0;
+}
+
+*/
+
+// the following could be a template function when templates support based pointer types
+// it could also use the inline function above when the compiler loses a related bug
+// WARNING: This macro uses and hence evaluates its second parameter twice!
+#define OR_BASED_POINTER(TYPE,PTR) \
+ ((TYPE OR_BASED *) (ULONG) (((ULONG)(PTR) != 0) ? \
+ (ULONG)((ULONG)(PTR) - (ULONG)pSharedBase) : 0))
+
+#else // _CHICAGO_ -- Uses absolute pointers in the system heap
+
+#define OR_BASED
+
+#define OR_FULL_POINTER(TYPE,BASEDPTR) BASEDPTR
+
+#define OR_BASED_POINTER(TYPE,PTR) PTR
+
+#endif // _CHICAGO_
+
+inline ULONG
+OR_OFFSET(void *pv)
+{
+ return (ULONG) (OR_BASED_POINTER(void,pv));
+}
+
+
+#define NEW_OR_BASED(VAR,CLASS,PARAMS) \
+{ \
+ CLASS *nonbased_temp = new CLASS##PARAMS; \
+ VAR = OR_BASED_POINTER(CLASS, nonbased_temp); \
+}
+
+#define NEW_OR_BASED_ARRAY(VAR,CLASS,SIZE) \
+{ \
+ CLASS *nonbased_temp = new (InSharedHeap) CLASS[SIZE]; \
+ VAR = OR_BASED_POINTER(CLASS, nonbased_temp); \
+}
+
+#define DELETE_OR_BASED(TYPE,BASEDPTR) \
+ (delete OR_FULL_POINTER(TYPE,BASEDPTR))
+
+#define ALLOC_OR_BASED(VAR,TYPE,SIZE) \
+{ \
+ TYPE *nonbased_temp = (TYPE*)OrMemAlloc(SIZE); \
+ VAR = OR_BASED_POINTER(TYPE, nonbased_temp); \
+}
+
+#define DEALLOC_OR_BASED(TYPE,BASEDPTR) \
+ OrMemFree(OR_FULL_POINTER(TYPE,BASEDPTR));
+
+
+// WARNING: THIS IS A COMPILER-SPECIFIC HACK
+// The VC++ compiler keeps the array size in the first 4 bytes
+// and passes us a pointer displaced 4 bytes from the true
+// allocated block, causing misalignment and other grief
+
+#define DELETE_OR_BASED_ARRAY(TYPE,OFFSET,COUNT) \
+{ \
+ TYPE *arr = OR_FULL_POINTER(TYPE,OFFSET); \
+ for (USHORT i = 0; i < COUNT; i++) arr[i].~TYPE(); \
+ OrMemFree(((BYTE*)arr)-4); \
+}
+
+
+#if DBG
+
+//
+// Some simple sanity checking in non-stress conditions
+//
+// The assumption is that based pointers should not get
+// too big unless something goes wrong
+//
+
+#define MAX_OFFSET 0x100000 // for DBG validation checking only
+
+inline
+void IsGoodBasedPtr(void OR_BASED *pv)
+{
+#ifndef _CHICAGO_ // on Chicago, we use absolute addresses
+ ULONG offset = (ULONG)pv;
+ ASSERT((offset >= 0) && (offset < MAX_OFFSET));
+#endif // _CHICAGO_
+}
+
+//
+// A validation class template and macros
+//
+// The constructor and destructor for the ValidityCheck template call
+// a function "IsValid" on the current object of class TYPE, which is the
+// template parameter. This is meant to validate the object at entry to
+// each method and also at all exit points of the method.
+//
+//
+
+template <class TYPE>
+class ValidityCheck
+{
+private:
+
+ TYPE *thisPtr;
+
+public:
+
+ ValidityCheck(void * pv)
+ {
+ thisPtr = (TYPE *) pv;
+ thisPtr->IsValid();
+ }
+
+ ~ValidityCheck()
+ {
+ thisPtr->IsValid();
+ }
+};
+
+//
+// To use the template defined above for guarding methods in a class,
+// use the following steps
+//
+// 1. Define a public method (possibly conditionally compiled #if DBG)
+// with the name "IsValid" and no parameters. This will typically
+// ASSERT in case something is wrong.
+//
+// 2. In the private part of the class, call the macro DECLARE_VALIDITY_CLASS
+// with the name of the class as the parameter.
+//
+// 3 In each method to be guarded for validity, call the macro VALIDATE_METHOD at
+// the beginning.
+//
+
+#define DECLARE_VALIDITY_CLASS(TYPE) \
+ typedef ValidityCheck<TYPE> MyValidityCheckerClass;
+
+#define VALIDATE_METHOD \
+ MyValidityCheckerClass ValidityCheckerObject(this); \
+
+#endif // DBG
+
+#endif __SHARE_HXX__
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/callid.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/callid.cxx
new file mode 100644
index 000000000..866d373aa
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/callid.cxx
@@ -0,0 +1,113 @@
+/*++
+
+Copyright (c) 1996 Microsoft Corporation
+
+Module Name:
+
+ callid.cxx
+
+Abstract:
+
+ Implements a cache of callids used for running down OIDs
+
+ This is almost twice as fast as UuidCreate() but that doesn't
+ mean much. UuidCreate takes 3 microseconds, this 1.4 (hit) or
+ 4.2 (miss) on a P90.
+
+ This codes real advantage would be on MP machines. But it is
+ not performance critical and is probably overkill.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 1/18/1996 Bits 'n pieces
+
+--*/
+
+#include <or.hxx>
+
+enum CacheState { CallidEmpty = 0,
+ CallidAllocated = 1,
+ CallidFree = -1 };
+
+struct CacheElement
+ {
+ CacheState _state;
+ UUID _callid;
+ };
+
+CacheElement CallidCache[4] = { CallidEmpty, {0},
+ CallidEmpty, {0},
+ CallidEmpty, {0},
+ CallidEmpty, {0} };
+
+
+INT
+AllocateCallId(
+ OUT UUID &Callid
+ )
+{
+ INT i;
+ LONG l;
+ RPC_STATUS status;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (CallidCache[i]._state != CallidAllocated)
+ {
+ l = InterlockedExchange((PLONG)&CallidCache[i]._state, CallidAllocated);
+
+ switch(l)
+ {
+ case CallidAllocated:
+ continue;
+
+ case CallidFree:
+ Callid = CallidCache[i]._callid;
+ return(i);
+
+ case CallidEmpty:
+ status = UuidCreate(&Callid);
+ VALIDATE((status, RPC_S_OK, RPC_S_UUID_LOCAL_ONLY, 0));
+ CallidCache[i]._callid = Callid;
+ return(i);
+ }
+ }
+ }
+ status = UuidCreate(&Callid);
+ VALIDATE((status, RPC_S_OK, RPC_S_UUID_LOCAL_ONLY, 0));
+ return(-1);
+ }
+
+
+void
+FreeCallId(
+ IN INT hint
+ )
+/*++
+
+Routine Description:
+
+ Frees a callid previously allcoated with AllocateCallId().
+
+Arguments:
+
+ hint - The hint value returned by the previous call to AllocateCallId().
+
+Return Value:
+
+ None
+
+--*/
+{
+ ASSERT(hint > -2 & hint < 4);
+
+ if (hint >= 0)
+ {
+ CallidCache[hint]._state = CallidFree;;
+ }
+}
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/callid.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/callid.hxx
new file mode 100644
index 000000000..52406961c
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/callid.hxx
@@ -0,0 +1,35 @@
+/*++
+
+Copyright (c) 1996 Microsoft Corporation
+
+Module Name:
+
+ callid.hxx
+
+Abstract:
+
+ Implements a cache of callids used for running down OIDs
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 1/18/1996 Bits 'n pieces
+
+--*/
+
+#ifndef __CALLID_HXX
+#define __CALLID_HXX
+
+INT AllocateCallId(
+ OUT UUID &Callid
+ );
+
+void FreeCallId(
+ IN INT hint
+ );
+
+#endif // __CALLID_HXX
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/daytona/makefile b/private/ole32/dcomss/objex/shrmem/dcom95/daytona/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/daytona/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/daytona/resolver.def b/private/ole32/dcomss/objex/shrmem/dcom95/daytona/resolver.def
new file mode 100644
index 000000000..701c851ce
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/daytona/resolver.def
@@ -0,0 +1,37 @@
+LIBRARY resolver
+
+DESCRIPTION 'Microsoft (R) Local OR interface Shared Memory Development'
+
+EXPORTS
+
+
+ pSharedBase
+ ConnectDCOM
+ ClientAddOID
+ ClientDropOID
+ ResolveClientOXID
+ ServerAllocateOXID
+ ServerAllocateOID
+ ServerFreeOXID
+ RundownTimerProc
+
+ Connect
+ Disconnect
+ AllocateReservedIds
+ ClientResolveOXID
+ ServerAllocateOXIDAndOIDs
+ ServerAllocateOIDs
+ ServerFreeOXIDAndOIDs
+
+ gpNextThreadID
+ ComputeSecurity
+ ScmObjexGetThreadId
+ PingThread
+ SCMGetBindingHandle
+ OrResolveOxid
+ _ComplexPing
+ _SimplePing
+ GetRegisteredProtseqs
+ GetLocalORBindings
+ SCMRemoveClassReg
+ SCMAddClassReg
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/daytona/sources b/private/ole32/dcomss/objex/shrmem/dcom95/daytona/sources
new file mode 100644
index 000000000..824322f52
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/daytona/sources
@@ -0,0 +1,99 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= resolver
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= ..\..\lib
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= DYNLINK
+
+!include ..\..\daytona.inc
+
+SOURCES= \
+ ..\scmfuns.cxx \
+ ..\iface.cxx \
+ ..\globals.cxx \
+ ..\manager.cxx \
+ ..\misc.cxx \
+ ..\mid.cxx \
+ ..\process.cxx \
+ ..\callid.cxx \
+ ..\oxid.cxx \
+ ..\objex.cxx \
+ ..\epts.c \
+ ..\dsa.cxx \
+ ..\string.cxx \
+ ..\gentable.cxx \
+ ..\linklist.cxx \
+ ..\set.cxx
+
+
+DLLENTRY= _DllMainCRTStartup
+
+DLLBASE= @$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,kerberos
+
+LIBDIR=$(_NTDRIVE)\nt\public\sdk\lib
+
+LINKLIBS= \
+ ..\..\lib\*\stg.lib \
+ $(BASEDIR)\private\dcomidl\obj\*\dcomidl.lib \
+ $(OLEDIR)\common\daytona\obj\*\common.lib \
+ $(OLEDIR)\com\inc\daytona\obj\*\inc.lib \
+ $(LIBDIR)\*\ole32.lib \
+ $(LIBDIR)\*\rpcrt4.lib \
+ $(LIBDIR)\*\security.lib \
+ $(LIBDIR)\*\netapi32.lib \
+ $(LIBDIR)\*\advapi32.lib \
+ $(LIBDIR)\*\ntdll.lib \
+ $(LIBDIR)\*\nt.lib \
+ $(LIBDIR)\*\kernel32.lib \
+ $(LIBDIR)\*\uuid.lib \
+ $(LIBDIR)\*\user32.lib \
+
+USE_LIBCMT=1
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+UMLIBS=
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/dbg.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/dbg.cxx
new file mode 100644
index 000000000..3f585e4d0
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/dbg.cxx
@@ -0,0 +1,54 @@
+/*++
+
+Microsoft Windows NT RPC Name Service
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ debug.cxx
+
+Abstract:
+
+ This file contains the implementations for non inline member functions
+ used for debugging output via the CDbgStr class, as well as debug
+ and retail versions of midl_user_{allocate,free}.
+
+Author:
+
+ Satish Thatte (SatishT) 08/15/95 Created all the code below except where
+ otherwise indicated.
+
+--*/
+
+
+#include <or.hxx>
+
+#if DBG
+
+CDbgStr debugOut;
+
+typedef struct _tagDoubleS
+{
+ ULONG first;
+ ULONG second;
+} *PIDT;
+
+
+CDbgStr&
+CDbgStr::operator<<(
+ ID id
+ )
+{
+ PIDT p = (PIDT)&id;
+
+#ifndef _CHICAGO_
+ DbgPrint("%x ",p->second);
+ DbgPrint("%x ",p->first);
+#else // BUGBUG: Do something about this!
+#endif
+
+ return *this;
+}
+
+#endif
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/dbg.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/dbg.hxx
new file mode 100644
index 000000000..26e6aa0ef
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/dbg.hxx
@@ -0,0 +1,110 @@
+/*++
+
+Microsoft Windows NT RPC Name Service
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ debug.hxx
+
+Abstract:
+
+ This module contains
+
+ 1. a definition of the CDbgStr class which is used to
+ produce debugging output.
+
+Author:
+
+ Satish Thatte (SatishT) 08/16/95 Created all the code below except where
+ otherwise indicated.
+
+--*/
+
+
+#ifndef _DEBUG_HXX_
+#define _DEBUG_HXX_
+
+#define TRACE 1
+#define DETAIL 2
+#define SUPER_DETAIL 4
+#define RUNDOWN 8
+
+extern UINT debugLevel;
+
+#if DBG
+
+#define DBGOUT(LEVEL,MESSAGE) \
+ if ((debugLevel | LEVEL) == debugLevel) debugOut << MESSAGE
+
+
+/*++
+
+Class Definition:
+
+ CDbgStr
+
+Abstract:
+
+ This is similar to the standard ostream class, except that the
+ output goes to the debugger.
+
+--*/
+
+#define WSTRING(STR) L##STR
+
+class CDbgStr {
+
+public:
+
+ CDbgStr& operator<<(ULONG ul) {
+ WCHAR buffer[20];
+ swprintf(buffer, WSTRING(" %d "), ul);
+ OutputDebugStringW(buffer);
+ return *this;
+ }
+
+ CDbgStr& operator<<(void *ptr) {
+ WCHAR buffer[20];
+ swprintf(buffer, WSTRING(" %x "), (ULONG)ptr);
+ OutputDebugStringW(buffer);
+ return *this;
+ }
+
+ CDbgStr& operator<<(void OR_BASED *ptr) {
+ WCHAR buffer[20];
+ swprintf(buffer, WSTRING(" %x "), (ULONG)ptr);
+ OutputDebugStringW(buffer);
+ return *this;
+ }
+
+ CDbgStr& operator<<(char *sz) {
+ if (!sz) return *this;
+
+ WCHAR buffer[200];
+ swprintf(buffer, WSTRING(" %S "), sz);
+ OutputDebugStringW(buffer);
+ return *this;
+ }
+
+ CDbgStr& operator<<(WCHAR * sz) {
+ if (!sz) return *this;
+
+ OutputDebugStringW(sz);
+ return *this;
+ }
+
+ CDbgStr& operator<<(ID id);
+};
+
+extern CDbgStr debugOut;
+
+#else
+
+#define DBGOUT(LEVEL,MESSAGE)
+
+#endif
+
+
+
+#endif _DEBUG_HXX_
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/detach.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/detach.hxx
new file mode 100644
index 000000000..c8873471b
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/detach.hxx
@@ -0,0 +1,4 @@
+BOOL WINAPI DllMain (
+ HANDLE hInst,
+ ULONG ul_reason_for_call,
+ LPVOID lpReserved);
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/dirs b/private/ole32/dcomss/objex/shrmem/dcom95/dirs
new file mode 100644
index 000000000..a41d4d88e
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/dirs
@@ -0,0 +1,28 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=
+
+OPTIONAL_DIRS= \
+ \
+ daytona
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/dsa.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/dsa.cxx
new file mode 100644
index 000000000..59099dd93
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/dsa.cxx
@@ -0,0 +1,126 @@
+#include <or.hxx>
+
+//
+// CBindingIterator methods
+//
+
+PWSTR
+CBindingIterator::Next()
+{
+ if (_iCurrentIndex == 0xffff) // fresh iterator, use starting index
+ {
+ _iCurrentIndex = _iStartingIndex; // not fresh any more
+ return &_dsa->aStringArray[_iStartingIndex];
+ }
+
+ PWSTR pwstrT = &_dsa->aStringArray[_iCurrentIndex];
+
+ pwstrT = OrStringSearch(pwstrT, 0) + 1;
+
+ if (*pwstrT == 0) // the end of the string bindings was reached
+ {
+ PWSTR pwstrT = _dsa->aStringArray; // wrap around
+ }
+
+ _iCurrentIndex = pwstrT - _dsa->aStringArray;
+
+ if (_iStartingIndex != _iCurrentIndex)
+ {
+ return pwstrT;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+//
+// CDSA methods
+//
+
+ORSTATUS
+CDSA::copyDSA(DUALSTRINGARRAY *pdsa)
+{
+ VALIDATE_METHOD
+
+ DUALSTRINGARRAY *pdsaT = NULL;
+ _fOwnDSA = FALSE;
+
+ if (pdsa != NULL)
+ {
+ pdsaT = (DUALSTRINGARRAY *)
+ OrMemAlloc(pdsa->wNumEntries
+ * sizeof(WCHAR) +
+ sizeof(DUALSTRINGARRAY)
+ );
+
+ if (!pdsaT)
+ {
+ return OR_NOMEM;
+ }
+
+ dsaCopy(pdsaT, pdsa);
+ }
+
+ _pdsa = OR_BASED_POINTER(DUALSTRINGARRAY,pdsaT);
+ if (_pdsa != NULL) _fOwnDSA = TRUE;
+
+ return OR_OK;
+}
+
+ORSTATUS
+CDSA::copyDSAEx(DUALSTRINGARRAY *pdsa, BOOL fCompressed)
+{
+ VALIDATE_METHOD
+
+ ORSTATUS status = OR_OK;
+
+ if (fCompressed)
+ {
+ status = copyDSA(pdsa);
+ }
+ else
+ {
+ DUALSTRINGARRAY *pdsaT = CompressStringArray(pdsa,TRUE);
+
+ if (pdsaT)
+ {
+ Assign(pdsaT); // no copying
+ }
+ else
+ {
+ status = OR_NOMEM;
+ _pdsa = NULL;
+ }
+ }
+
+ return status;
+}
+
+
+ORSTATUS
+CDSA::ExtractRemote(CDSA &dsaLocal) // pick out remote protseqs only
+ //.this is a kind of assignment
+{
+ VALIDATE_METHOD
+
+ DUALSTRINGARRAY *pdsaT;
+
+ ORSTATUS status = ::ConvertToRemote(
+ OR_FULL_POINTER(DUALSTRINGARRAY,dsaLocal._pdsa),
+ &pdsaT
+ );
+
+ if (status == OR_OK)
+ {
+ status = copyDSA(pdsaT);
+ delete pdsaT;
+ }
+ else
+ {
+ _pdsa = NULL;
+ }
+
+ return status;
+}
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/dsa.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/dsa.hxx
new file mode 100644
index 000000000..13bf2c8b2
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/dsa.hxx
@@ -0,0 +1,312 @@
+class CDSA : public ISearchKey // BUGBUG: this is overly complex
+{
+private:
+
+ friend class BindingIterator;
+
+ DUALSTRINGARRAY OR_BASED * _pdsa; // always compressed
+ // and in shared memory
+
+ BOOL _fOwnDSA; // our own copy?
+
+ ORSTATUS copyDSA(DUALSTRINGARRAY *pdsa); // local helpers
+
+#ifndef _CHICAGO_
+ ORSTATUS copyDSA(DUALSTRINGARRAY OR_BASED *pdsa)
+ {
+ return copyDSA(OR_FULL_POINTER(DUALSTRINGARRAY,pdsa));
+ }
+#endif // _CHICAGO_
+
+ ORSTATUS copyDSAEx(DUALSTRINGARRAY *pdsa, BOOL fCompressed);
+
+public:
+
+#if DBG
+
+ void IsValid()
+ {
+ IsGoodBasedPtr(_pdsa);
+ if (_pdsa) ASSERT(Valid());
+ ASSERT(_fOwnDSA==TRUE || _fOwnDSA==FALSE);
+ }
+
+ DECLARE_VALIDITY_CLASS(CDSA)
+#endif
+
+ CDSA() // default constructor
+ {
+ _pdsa = NULL;
+ _fOwnDSA = FALSE;
+ }
+
+ CDSA(const CDSA& cdsa, ORSTATUS& status); // copy constructor
+ ORSTATUS Assign(const CDSA& cdsa); // assignment method
+
+ CDSA( // copying constructor
+ DUALSTRINGARRAY* pdsa,
+ BOOL fCompressed, // is it compressed?
+ ORSTATUS& status
+ );
+
+ ORSTATUS Assign( // corresponding assignment
+ DUALSTRINGARRAY* pdsa,
+ BOOL fCompressed // is it compressed?
+ );
+
+ CDSA(DUALSTRINGARRAY *pdsa); // noncopying constructors
+
+#ifndef _CHICAGO_
+ CDSA(DUALSTRINGARRAY OR_BASED *pdsa); // param must be compressed
+ // and in shared memory
+#endif // _CHICAGO_
+
+ void Assign(DUALSTRINGARRAY *pdsa); // corresponding assignments
+
+#ifndef _CHICAGO_
+ void Assign(DUALSTRINGARRAY OR_BASED *pdsa); // param must be compressed
+ // and in shared memory
+#endif // _CHICAGO_
+
+ // never destroyed as base object hence destructor need not be virtual
+ ~CDSA();
+
+ BOOL Valid(); // Integrity checking
+
+ DWORD Hash();
+ BOOL Compare(ISearchKey &tk);
+
+ BOOL Compare(DUALSTRINGARRAY *pdsa); // alternate compare
+
+ BOOL operator==(CDSA& dsa);
+
+ BOOL Empty(); // is DSA NULL?
+
+ operator DUALSTRINGARRAY*(); // auto conversion
+
+ DUALSTRINGARRAY* operator->(); // smart pointer
+
+ ORSTATUS ExtractRemote(CDSA &dsaLocal); // pick out remote protseqs only
+ //.this is a kind of assignment
+
+ CDSA *MergeSecurityBindings( // return a new CDSA object in which
+ CDSA security, // we replace existing security part
+ ORSTATUS status); // with that of the parameter
+};
+
+
+class CBindingIterator // this assumes a stable _dsa
+{
+public:
+
+ CBindingIterator(USHORT iStart, CDSA& dsa);
+ PWSTR Next();
+ USHORT Index();
+
+private:
+
+ // 0xffff == _iCurrentIndex iff the iterator has not been used
+ // This is not portable, but for Win95, who cares?
+
+ USHORT _iStartingIndex, _iCurrentIndex;
+ CDSA& _dsa;
+};
+
+
+//
+// Inline CBindingIterator methods
+//
+
+inline
+CBindingIterator::CBindingIterator(
+ USHORT iStart,
+ CDSA& dsa
+ )
+ : _dsa(dsa), _iStartingIndex(iStart), _iCurrentIndex(0xffff)
+{}
+
+inline
+USHORT
+CBindingIterator::Index()
+{
+ return _iCurrentIndex;
+}
+
+
+//
+// Inline CDSA methods
+//
+
+inline // copy constructor
+CDSA::CDSA(
+ const CDSA& cdsa,
+ ORSTATUS& status)
+{
+#if DBG // make valid to start with
+ _pdsa = NULL;
+ _fOwnDSA = FALSE;
+#endif
+
+ status = copyDSA(cdsa._pdsa);
+ IsValid();
+}
+
+inline
+ORSTATUS
+CDSA::Assign( // assignment method
+ const CDSA& cdsa) // preferred over operator
+{ // since it returns status
+ VALIDATE_METHOD
+ DEALLOC_OR_BASED(DUALSTRINGARRAY,_pdsa);
+ _pdsa = NULL;
+
+ return copyDSA(cdsa._pdsa);
+}
+
+
+inline
+CDSA::CDSA( // copying constructor
+ DUALSTRINGARRAY* pdsa,
+ BOOL fCompressed, // is it compressed?
+ ORSTATUS& status)
+{
+#if DBG // make valid to start with
+ _pdsa = NULL;
+ _fOwnDSA = FALSE;
+#endif
+
+ status = copyDSAEx(pdsa,fCompressed);
+ IsValid();
+}
+
+inline ORSTATUS
+CDSA::Assign( // Alternate assignment
+ DUALSTRINGARRAY* pdsa,
+ BOOL fCompressed) // is it compressed?
+{
+ VALIDATE_METHOD
+ DEALLOC_OR_BASED(DUALSTRINGARRAY,_pdsa);
+ _pdsa = NULL;
+ return copyDSAEx(pdsa,fCompressed);;
+}
+
+inline
+CDSA::CDSA( // noncopying constructor
+ DUALSTRINGARRAY *pdsa) // param must be compressed
+ // and in shared memory
+{
+ _pdsa = OR_BASED_POINTER(DUALSTRINGARRAY,pdsa);
+ _fOwnDSA = FALSE;
+ IsValid();
+}
+
+#ifndef _CHICAGO_
+
+inline
+CDSA::CDSA( // noncopying constructor
+ DUALSTRINGARRAY OR_BASED *pdsa) // param must be compressed
+ // and in shared memory
+{
+ _fOwnDSA = FALSE;
+ _pdsa = pdsa;
+ IsValid();
+}
+
+#endif // _CHICAGO_
+
+inline void
+CDSA::Assign(DUALSTRINGARRAY *pdsa) // noncopying assignment
+{ // param must be compressed
+ VALIDATE_METHOD // and in shared memory
+ DEALLOC_OR_BASED(DUALSTRINGARRAY,_pdsa);
+ _pdsa = OR_BASED_POINTER(DUALSTRINGARRAY,pdsa);
+
+}
+
+#ifndef _CHICAGO_
+
+inline void
+CDSA::Assign(DUALSTRINGARRAY OR_BASED *pdsa) // noncopying assignment
+{ // param must be compressed
+ VALIDATE_METHOD // and in shared memory
+ DEALLOC_OR_BASED(DUALSTRINGARRAY,_pdsa);
+ _pdsa = pdsa;
+}
+
+#endif // _CHICAGO_
+
+inline
+CDSA::~CDSA()
+{
+ if (_fOwnDSA)
+ {
+ DEALLOC_OR_BASED(DUALSTRINGARRAY,_pdsa);
+ }
+}
+
+
+inline
+CDSA::operator DUALSTRINGARRAY*() // auto conversion
+{
+ return OR_FULL_POINTER(DUALSTRINGARRAY,_pdsa);
+}
+
+
+inline DUALSTRINGARRAY*
+CDSA::operator->() // smart pointer
+{
+ return OR_FULL_POINTER(DUALSTRINGARRAY,_pdsa);
+}
+
+
+inline BOOL
+CDSA::Valid() // Integrity checking
+{
+ return dsaValid(OR_FULL_POINTER(DUALSTRINGARRAY,_pdsa));
+}
+
+
+inline DWORD
+CDSA::Hash()
+{
+ return dsaHash(OR_FULL_POINTER(DUALSTRINGARRAY,_pdsa));
+}
+
+
+inline BOOL
+CDSA::Compare(ISearchKey &tk)
+{
+ VALIDATE_METHOD
+ CDSA& dsaK = (CDSA&) tk; // same type of parameter
+ // must be assumed
+ return dsaCompare(
+ OR_FULL_POINTER(DUALSTRINGARRAY,_pdsa),
+ OR_FULL_POINTER(DUALSTRINGARRAY,dsaK._pdsa)
+ );
+}
+
+
+inline BOOL
+CDSA::Compare(DUALSTRINGARRAY *pdsa) // alternative direct compare
+{
+ VALIDATE_METHOD
+ return dsaCompare(
+ OR_FULL_POINTER(DUALSTRINGARRAY,_pdsa),
+ pdsa
+ );
+}
+
+
+inline BOOL // REVIEW: replace Compare by == and !=
+CDSA::operator==(CDSA& dsa)
+{
+ return Compare(dsa);
+}
+
+
+inline BOOL
+CDSA::Empty() // is DSA NULL?
+{
+ return _pdsa == NULL;
+}
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/epts.c b/private/ole32/dcomss/objex/shrmem/dcom95/epts.c
new file mode 100644
index 000000000..a7b82a272
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/epts.c
@@ -0,0 +1,461 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Epts.c
+
+Abstract:
+
+ Common code to listen to endpoints in the DCOM service.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 6/16/1995 Bits 'n pieces
+
+--*/
+
+#ifdef _CHICAGO_
+#define ASSERT( exp ) if (! (exp) ) DebugBreak();
+#endif
+
+#define WSTR(s) L##s
+
+#include <dcomss.h>
+
+// Globals
+
+// BUGBUG - this info should be read from the registry.
+
+// The index is the protseq tower id.
+
+
+PROTSEQ_INFO
+gaProtseqInfo[] =
+ {
+ /* 0x00 */ { STOPPED, 0, 0 },
+ /* 0x01 */ { STOPPED, 0, 0 },
+ /* 0x02 */ { STOPPED, 0, 0 },
+ /* 0x03 */ { STOPPED, 0, 0 },
+ /* 0x04 */ { STOPPED, L"ncacn_dnet_dsp", L"#69" },
+ /* 0x05 */ { STOPPED, 0, 0 },
+ /* 0x06 */ { STOPPED, 0, 0 },
+ /* 0x07 */ { STOPPED, L"ncacn_ip_tcp", L"135" },
+ /* 0x08 */ { STOPPED, L"ncadg_ip_udp", L"135" },
+ /* 0x09 */ { STOPPED, L"ncacn_nb_tcp", L"135" },
+ /* 0x0a */ { STOPPED, 0, 0 },
+ /* 0x0b */ { STOPPED, 0, 0 },
+ /* 0x0c */ { STOPPED, L"ncacn_spx", L"34280" },
+ /* 0x0d */ { STOPPED, L"ncacn_nb_ipx", L"135" },
+ /* 0x0e */ { STOPPED, L"ncadg_ipx", L"34280" },
+ /* 0x0f */ { STOPPED, L"ncacn_np", L"\\pipe\\epmapper" },
+ /* 0x10 */ { STOPPED, L"ncalrpc", L"epmapper" },
+ /* 0x11 */ { STOPPED, 0, 0 },
+ /* 0x12 */ { STOPPED, 0, 0 },
+ /* 0x13 */ { STOPPED, L"ncacn_nb_nb", L"135" },
+ /* 0x14 */ { STOPPED, 0, 0 },
+ /* 0x15 */ { STOPPED, 0, 0 }, // was ncacn_nb_xns - unsupported.
+ /* 0x16 */ { STOPPED, L"ncacn_at_dsp", L"Endpoint Mapper" },
+ /* 0x17 */ { STOPPED, L"ncadg_at_ddp", L"Endpoint Mapper" },
+ /* 0x18 */ { STOPPED, 0, 0 },
+ /* 0x19 */ { STOPPED, 0, 0 },
+ /* 0x1A */ { STOPPED, L"ncacn_vns_spp", L"385"}
+ };
+
+#define PROTSEQ_IDS (sizeof(gaProtseqInfo)/sizeof(PROTSEQ_INFO))
+
+
+RPC_STATUS
+UseProtseqIfNecessary(
+ IN USHORT id
+ )
+/*++
+
+Routine Description:
+
+ Listens to the well known RPC endpoint mapper endpoint
+ for the protseq. Returns very quickly if the process
+ is already listening to the protseq.
+
+Arguments:
+
+ id - the tower id of protseq. See GetProtseqId() if you don't
+ already have this valud.
+
+Return Value:
+
+ RPC_S_OK - no errors occured.
+ RPC_S_OUT_OF_RESOURCES - when we're unable to setup security for the endpoint.
+ RPC_S_INVALID_RPC_PROTSEQ - if id is unknown/invalid.
+
+ Any error from RpcServerUseProtseqEp.
+
+--*/
+{
+ RPC_STATUS status = RPC_S_OK;
+ SECURITY_DESCRIPTOR sd, *psd;
+
+ ASSERT(id);
+
+ if (id == 0 || id >= PROTSEQ_IDS)
+ {
+ ASSERT(0);
+ return(RPC_S_INVALID_RPC_PROTSEQ);
+ }
+
+ if (gaProtseqInfo[id].state == STARTED)
+ {
+ return(RPC_S_OK);
+ }
+
+ if (id == 0x10)
+ {
+ // ncalrpc needs a security descriptor.
+
+ psd = &sd;
+
+ InitializeSecurityDescriptor(
+ psd,
+ SECURITY_DESCRIPTOR_REVISION
+ );
+
+ if ( FALSE == SetSecurityDescriptorDacl (
+ psd,
+ TRUE, // Dacl present
+ NULL, // NULL Dacl
+ FALSE // Not defaulted
+ ) )
+ {
+ status = RPC_S_OUT_OF_RESOURCES;
+ }
+ }
+ else
+ {
+ psd = 0;
+ }
+
+ if (status == RPC_S_OK )
+ {
+ status = RpcServerUseProtseqEpW(gaProtseqInfo[id].pwstrProtseq,
+ RPC_C_PROTSEQ_MAX_REQS_DEFAULT + 1,
+ gaProtseqInfo[id].pwstrEndpoint,
+ psd);
+
+ // No locking is done here, the RPC runtime may return duplicate
+ // endpoint if two threads call this at the same time.
+ if (status == RPC_S_DUPLICATE_ENDPOINT)
+ {
+ ASSERT(gaProtseqInfo[id].state == STARTED);
+ status = RPC_S_OK;
+ }
+
+#ifdef DEBUGRPC
+ if (status != RPC_S_OK)
+ {
+#ifndef _CHICAGO_
+ DbgPrint("DCOMSS: Unable to listen to %S\n", gaProtseqInfo[id].pwstrProtseq);
+#endif
+ }
+#endif
+
+ if (status == RPC_S_OK)
+ {
+ gaProtseqInfo[id].state = STARTED;
+ }
+ }
+
+ return(status);
+}
+
+
+PWSTR
+GetProtseq(
+ IN USHORT ProtseqId
+ )
+/*++
+
+Routine Description:
+
+ Returns the unicode protseq give the protseqs tower id.
+
+Arguments:
+
+ ProtseqId - Tower id of the protseq in question.
+
+Return Value:
+
+ NULL if the id is invalid.
+
+ non-NULL if the id is valid - note the pointer doesn't need to be freed.
+
+--*/
+
+{
+ ASSERT(ProtseqId);
+
+ if (ProtseqId < PROTSEQ_IDS)
+ {
+ return(gaProtseqInfo[ProtseqId].pwstrProtseq);
+ }
+ return(0);
+}
+
+
+PWSTR
+GetEndpoint(
+ IN USHORT ProtseqId
+ )
+/*++
+
+Routine Description:
+
+ Returns the well known endpoint associated with the protseq.
+
+Arguments:
+
+ ProtseqId - the id (See GetProtseqId()) of the protseq in question.
+
+Return Value:
+
+ 0 - Unknown/invalid id.
+
+ !0 - The endpoint associated with the protseq.
+ note: should not be freed.
+
+--*/
+{
+ ASSERT(ProtseqId);
+
+ if (ProtseqId < PROTSEQ_IDS)
+ {
+ return(gaProtseqInfo[ProtseqId].pwstrEndpoint);
+ }
+ return(0);
+}
+
+
+USHORT
+GetProtseqId(
+ IN PWSTR Protseq
+ )
+/*++
+
+Routine Description:
+
+ Returns the tower id for a protseq.
+
+ This could be changed to a faster search, but remember that
+ eventually the table will NOT be static. (ie. we can't just
+ create a perfect hash based on the static table).
+
+Arguments:
+
+ Protseq - a unicode protseq to lookup. It is assumed
+ to be non-null.
+
+Return Value:
+
+ 0 - unknown/invalid protseq
+ non-zero - the id.
+
+--*/
+{
+ int i;
+ ASSERT(Protseq);
+
+ for(i = 1; i < PROTSEQ_IDS; i++)
+ {
+ if ( 0 != gaProtseqInfo[i].pwstrProtseq
+ && 0 == wcscmp(gaProtseqInfo[i].pwstrProtseq, Protseq))
+ {
+ return(i);
+ }
+ }
+ return(0);
+}
+
+
+USHORT
+GetProtseqIdAnsi(
+ IN PSTR pstrProtseq
+ )
+/*++
+
+Routine Description:
+
+ Returns the tower id for a protseq.
+
+ This could be changed to a faster search, but remember that
+ eventually the table will NOT be static. (ie. we can't just
+ create a perfect hash based on the static table).
+
+Arguments:
+
+ Protseq - an ansi (8 bit char) protseq to lookup. It is assumed
+ to be non-null.
+
+Return Value:
+
+ 0 - unknown/invalid protseq
+ non-zero - the id.
+
+--*/
+{
+ int i;
+ ASSERT(pstrProtseq);
+
+ for(i = 1; i < PROTSEQ_IDS; i++)
+ {
+ if (0 != gaProtseqInfo[i].pwstrProtseq)
+ {
+ PWSTR pwstrProtseq = gaProtseqInfo[i].pwstrProtseq;
+ PSTR pstrT = pstrProtseq;
+
+ while(*pstrT && *pwstrProtseq && *pstrT == *pwstrProtseq)
+ {
+ pstrT++;
+ pwstrProtseq++;
+ }
+ if (*pstrT == *pwstrProtseq)
+ {
+ return(i);
+ }
+ }
+ }
+ return(0);
+}
+
+
+RPC_STATUS
+InitializeEndpointManager(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Called when the dcom service starts.
+
+ BUGBUG: Should read the protseqs, tower IDs and endpoints from the registry.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ RPC_S_OUT_OF_MEMORY - if needed
+
+ RPC_S_OUT_OF_RESOURCES - usually on registry failures.
+
+--*/
+{
+ return(RPC_S_OK);
+}
+
+
+BOOL
+IsLocal(
+ IN USHORT ProtseqId
+ )
+/*++
+
+Routine Description:
+
+ Determines if the protseq id is local-only.
+ (ncalrpc or mswmsg).
+
+Arguments:
+
+ ProtseqId - The id of the protseq in question.
+
+Return Value:
+
+ TRUE - if the protseq id is local-only
+ FALSE - if the protseq id invalid or available remotely.
+
+--*/
+{
+ return(ProtseqId == 0x1 || ProtseqId == 0x10);
+}
+
+
+RPC_STATUS
+DelayedUseProtseq(
+ IN USHORT id
+ )
+/*++
+
+Routine Description:
+
+ If the protseq is not being used its state is changed
+ so that a callto CompleteDelayedUseProtseqs() will actually
+ cause the server to listen to the protseq.
+
+Arguments:
+
+ id - the id of the protseq you wish to listen to.
+
+Return Value:
+
+ 0 - normally
+
+ RPC_S_INVALID_RPC_PROTSEQ - if id is invalud.
+
+--*/
+{
+ if (id < PROTSEQ_IDS)
+ {
+ if (gaProtseqInfo[id].pwstrProtseq != 0)
+ {
+ if (gaProtseqInfo[id].state == STOPPED)
+ gaProtseqInfo[id].state = START;
+ return(RPC_S_OK);
+ }
+ }
+ return(RPC_S_INVALID_RPC_PROTSEQ);
+}
+
+
+VOID
+CompleteDelayedUseProtseqs(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Start listening to any protseqs previously passed
+ to DelayedUseProtseq(). No errors are returned,
+ but informationals are printed on debug builds.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ USHORT i;
+
+ for(i = 1; i < PROTSEQ_IDS; i++)
+ {
+ if (START == gaProtseqInfo[i].state)
+ {
+ RPC_STATUS status = UseProtseqIfNecessary(i);
+#ifdef DEBUGRPC
+ if (RPC_S_OK == status)
+ ASSERT(gaProtseqInfo[i].state == STARTED);
+#endif
+ }
+ }
+}
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/gentable.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/gentable.cxx
new file mode 100644
index 000000000..890ae5e21
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/gentable.cxx
@@ -0,0 +1,269 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Table.cxx
+
+Abstract:
+
+ Implementation of the CResolverHashTable and CTableElement.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-15-95 Bits 'n pieces
+ MarioGo 12-18-95 Changed from UUID to generic object keys
+ SatishT 02-12-96 Modified for use with shared memory
+
+--*/
+
+#include<or.hxx>
+
+#if DBG
+
+void
+CResolverHashTable::IsValid()
+{
+ IsGoodBasedPtr(_buckets);
+
+ ASSERT(_fInitialized == TRUE || _fInitialized == FALSE);
+ ASSERT(!_fInitialized || _cBuckets > 0);
+ ASSERT(_cBuckets > 0 || _cElements == 0);
+ ASSERT(_cBuckets >=0 && _cBuckets < MAX_BUCKETS);
+
+ if (_fInitialized)
+ {
+ for (USHORT i = 0; i < _cBuckets; i++)
+ {
+ _buckets[i].IsValid();
+ }
+ }
+}
+
+#endif
+
+ORSTATUS
+CResolverHashTable::PrivAdd( // never called before Init()
+ IN CTableElement *pElement
+ )
+{
+ VALIDATE_METHOD
+
+ ORSTATUS status = OR_OK;
+
+ ISearchKey& sk = *pElement; // auto conversion to ISearchKey
+
+ DWORD hash = sk.Hash() % _cBuckets;
+
+ ComDebOut((DEB_ITRACE, "Adding %x at hash = %d\n",
+ OR_OFFSET(pElement),hash));
+
+ _buckets[hash].Insert(status,pElement);
+
+ _cElements++;
+
+ return status;
+}
+
+
+
+CResolverHashTable::CResolverHashTable(UINT start_size)
+{
+ ComDebOut((DEB_ITRACE, "Constructing CResolverHashTable Size = %d\n",start_size));
+
+ _cBuckets = start_size;
+ _cElements = 0;
+ _buckets = NULL;
+ _fInitialized = FALSE;
+
+ VALIDATE_METHOD
+}
+
+
+ORSTATUS
+CResolverHashTable::Init()
+{
+ ORSTATUS status;
+
+ ASSERT(!_fInitialized);
+
+ VALIDATE_METHOD
+
+ NEW_OR_BASED_ARRAY(_buckets,CTableElementList,_cBuckets);
+
+ if (NULL == _buckets)
+ {
+ status = OR_NOMEM;
+ }
+ else
+ {
+ status = OR_OK;
+ _fInitialized = TRUE;
+ }
+
+ return status;
+}
+
+
+CResolverHashTable::~CResolverHashTable()
+{
+ RemoveAll();
+}
+
+
+CTableElement *
+CResolverHashTable::Lookup(
+ IN ISearchKey &id
+ )
+{
+ ComDebOut((DEB_ITRACE, "Entering Lookup\n"));
+
+ VALIDATE_METHOD
+
+ if (!_fInitialized) return NULL; // nothing to look in
+
+ DWORD hash = id.Hash();
+ hash %= _cBuckets;
+
+ return _buckets[hash].Find(id);
+}
+
+ORSTATUS
+CResolverHashTable::Add(
+ IN CTableElement *pElement
+ )
+{
+ ComDebOut((DEB_ITRACE, "Entering Add for %x in %x\n",
+ OR_OFFSET(pElement),OR_OFFSET(this)));
+
+
+ VALIDATE_METHOD
+
+ ORSTATUS status = OR_OK;
+
+ if (!_fInitialized) status = Init(); // set up buckets
+
+ if (status != OR_OK) return status;
+
+ status = PrivAdd(pElement); // do the basic Add
+
+ if (status != OR_OK) return status;
+
+ if (_cElements > _cBuckets) // now see if the table is overpopulated
+ {
+ // Try to grow the table. If the allocation fails no need to worry,
+ // everything still works but might be a bit slower.
+
+ CTableElementList OR_BASED * psll;
+ NEW_OR_BASED_ARRAY(psll,CTableElementList,_cBuckets * 2);
+
+
+ // The tricky part here is to avoid getting OR_NOMEM error while moving
+ // between tables. We do that by recycling the links in the old lists
+
+ if (psll)
+ {
+ UINT i, uiBucketsOld = _cBuckets;
+ CTableElement *pte;
+ CTableElementList::Link *pLink;
+ CTableElementList OR_BASED *psllOld = _buckets;
+
+ OrDbgDetailPrint(("OR: Growing table: %p\n", this));
+
+ // Change to the larger array of buckets.
+ _cBuckets *= 2;
+ _buckets = psll;
+
+ // Move every element from the old table into the large table.
+
+ for(i = 0; i < uiBucketsOld; i++)
+ {
+ while (pLink = psllOld[i].PopLink()) // uses specialized private operations
+ { // to avoid both memory allocation
+ // and reference counting problems
+
+ ISearchKey& sk = *pLink->_pData; // auto conversion to ISearchKey
+ _buckets[sk.Hash() % _cBuckets].PushLink(pLink);
+ }
+ }
+ }
+ }
+
+ ComDebOut((DEB_ITRACE, "Leaving Add\n"));
+
+ return status;
+}
+
+CTableElement *
+CResolverHashTable::Remove(
+ IN ISearchKey &id
+ )
+/*++
+
+Routine Description:
+
+ Looks up and removes an element from the table.
+
+Arguments:
+
+ id - The key to match the element to be removed
+
+Return Value:
+
+ NULL - The element was not in the table
+
+ non-NULL - A pointer to the element which was removed.
+
+--*/
+
+{
+ VALIDATE_METHOD
+
+ if (!_fInitialized) return NULL; // nothing to remove
+
+ DWORD hash = id.Hash() % _cBuckets;
+
+ CTableElement *pTE = _buckets[hash].Remove(id);
+
+ if (pTE)
+ {
+ _cElements--;
+ }
+
+ return pTE;
+}
+
+
+void
+CResolverHashTable::RemoveAll()
+{
+ VALIDATE_METHOD
+
+ if (!_fInitialized) return; // nothing to remove
+
+ ASSERT(_buckets);
+ DWORD _currentBucketIndex = 0;
+ CTableElement *pTE;
+
+ while (_currentBucketIndex < _cBuckets)
+ {
+ while (pTE = _buckets[_currentBucketIndex].Pop())
+ {
+ _cElements--;
+ }
+
+ _currentBucketIndex++;
+ }
+
+ ASSERT(_cElements==0);
+
+ DELETE_OR_BASED_ARRAY(CTableElementList,_buckets,_cBuckets);
+ _buckets = NULL;
+ _fInitialized = FALSE;
+}
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/gentable.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/gentable.hxx
new file mode 100644
index 000000000..9cede47f7
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/gentable.hxx
@@ -0,0 +1,297 @@
+
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ GenTable.hxx
+
+Abstract:
+
+ Generic wrapper for a bucket hash class.
+ Used for ID, ID[2], ID[3] and string index tables.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 12-13-95 Pulled from uuid index hash table
+ MarioGo 12-18-95 Changed to use generic keys.
+ SatishT 03-07-96 Considerably altered for DCOM95
+
+--*/
+
+#ifndef __GENERIC_TABLE_HXX
+#define __GENERIC_TABLE_HXX
+
+#if DBG
+#define MAX_BUCKETS 0x10000 // for DBG validation checking only
+#endif
+
+
+struct ISearchKey
+{
+ virtual DWORD Hash() = 0;
+ virtual BOOL Compare(ISearchKey &tk) = 0;
+
+ BOOL operator==(ISearchKey &tk)
+ {
+ return Compare(tk);
+ }
+
+ BOOL operator!=(ISearchKey &tk)
+ {
+ return !Compare(tk);
+ }
+};
+
+
+class CTableElement : public CReferencedObject
+{
+public:
+ virtual operator ISearchKey&() = 0;
+};
+
+
+// We don't use DEFINE_LIST here because CTableElement is an abstract class
+
+#define CTableElementList TCSafeLinkList<CTableElement>
+#define CTableElementListIterator TCSafeLinkListIterator<CTableElement>
+
+/*++
+
+Class Definition:
+
+ CResolverHashTable
+
+Abstract:
+
+ This is a simple hash table class. Items are kept in buckets reached by
+ hashing. Each bucket is a linked list object. The name is designed to
+ avoid a clash with the specialized CHashTable in ole32\com\dcomrem\hash.hxx,
+ with which we must coexist.
+
+--*/
+
+class CResolverHashTable
+{
+public:
+
+#if DBG
+ void IsValid();
+ DECLARE_VALIDITY_CLASS(CResolverHashTable)
+#endif
+
+ CResolverHashTable(UINT start_size = 32 );
+
+ ~CResolverHashTable();
+
+ void * operator new(size_t s)
+ {
+ return OrMemAlloc(s);
+ }
+
+ void operator delete(void * p) // do not inherit this!
+ {
+ OrMemFree(p);
+ }
+
+ ORSTATUS Add(CTableElement * element);
+ CTableElement *Lookup(ISearchKey &tk);
+ CTableElement *Remove(ISearchKey &tk);
+ void RemoveAll();
+ DWORD Size() { return(_cElements); }
+
+protected:
+
+ DWORD BucketSize() { return _cBuckets; }
+
+private:
+
+ friend class CResolverHashTableIterator;
+
+ ORSTATUS PrivAdd(CTableElement * element);
+ ORSTATUS Init();
+
+ DWORD _cBuckets;
+ DWORD _cElements;
+ BOOL _fInitialized;
+ CTableElementList OR_BASED *_buckets;
+};
+
+
+
+
+/*++
+
+Template Class Definition:
+
+ TCResolverHashTable
+
+Abstract:
+
+ The usual template wrapper for type safety. Data must be a subtype of
+ CTableElement. I wish I could express that constraint in the code!
+
+--*/
+
+template <class Data>
+class TCSafeResolverHashTable : private CResolverHashTable
+{
+ friend class TCSafeResolverHashTableIterator<Data>;
+
+public:
+
+#if DBG
+ void IsValid()
+ {
+ CResolverHashTable::IsValid();
+ }
+#endif // DBG
+
+ TCSafeResolverHashTable(UINT start_size = 32 )
+ : CResolverHashTable(start_size)
+ {}
+
+ void * operator new(size_t s)
+ {
+ return OrMemAlloc(s);
+ }
+
+ void operator delete(void * p) // do not inherit this!
+ {
+ OrMemFree(p);
+ }
+
+ ORSTATUS Add(Data * element)
+ {
+ return CResolverHashTable::Add(element);
+ }
+
+ Data *Lookup(ISearchKey &tk)
+ {
+ return (Data *) CResolverHashTable::Lookup(tk);
+ }
+
+ Data *Remove(ISearchKey &tk)
+ {
+ return (Data *) CResolverHashTable::Remove(tk);
+ }
+
+ void RemoveAll()
+ {
+ CResolverHashTable::RemoveAll();
+ }
+
+ DWORD Size()
+ {
+ return CResolverHashTable::Size();
+ }
+
+ BOOL IsEmpty()
+ {
+ return Size() == 0;
+ }
+
+private:
+
+ DWORD BucketSize() { return CResolverHashTable::BucketSize(); }
+};
+
+
+
+/*++
+
+Class Definition:
+
+ CResolverHashTableIterator
+
+Abstract:
+
+ This is a simple iterator class for hash tables.
+ It is assumed that the table is static during iteration.
+ Note that the iterator performs no memory allocation.
+
+--*/
+
+class CResolverHashTableIterator
+{
+private:
+
+ CResolverHashTable& _table;
+
+ DWORD _currentBucketIndex;
+
+ // iterator for the current bucket
+ CTableElementListIterator _BucketIter;
+
+ void NextBucket(); // helper -- setup next bucket iterator
+
+public:
+
+ CResolverHashTableIterator(CResolverHashTable& source)
+ : _table(source), _currentBucketIndex(0)
+ {}
+
+ IDataItem * Next()
+ {
+ if (!_table._fInitialized)
+ {
+ return NULL;
+ }
+
+ while (
+ _BucketIter.Finished()
+ && (_currentBucketIndex < _table._cBuckets)
+ )
+ {
+ _BucketIter.Init(_table._buckets[_currentBucketIndex]);
+ _currentBucketIndex++;
+ }
+
+ return _BucketIter.Next();
+ }
+};
+
+
+
+/*++
+
+Template Class Definition:
+
+ TCSafeResolverHashTableIterator
+
+Abstract:
+
+ This is the usual template wrapper for CResolverHashTableIterator
+ for type safety. Data must be a subtype of CTableElement.
+
+--*/
+
+template <class Data>
+class TCSafeResolverHashTableIterator : private CResolverHashTableIterator
+{
+
+public:
+
+ TCSafeResolverHashTableIterator(TCSafeResolverHashTable<Data>& source)
+ : CResolverHashTableIterator(source)
+ {}
+
+ Data * Next()
+ {
+ return (Data *) CResolverHashTableIterator::Next();
+ }
+};
+
+
+#define DEFINE_TABLE(DATA) \
+ typedef TCSafeResolverHashTable<DATA> DATA##Table; \
+ typedef TCSafeResolverHashTableIterator<DATA> DATA##TableIterator;
+
+
+#endif // __GENERIC_TABLE_HXX
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/globals.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/globals.cxx
new file mode 100644
index 000000000..b7cf2701e
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/globals.cxx
@@ -0,0 +1,378 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: globals.cxx
+//
+// Contents: Implementation of Class used to encapsulate shared global
+// data structures for DCOM95.
+//
+// History: 13-Feb-96 SatishT Created
+//
+//--------------------------------------------------------------------------
+#include <or.hxx>
+
+
+//
+// Helper function which initializes local DSA and string of protocol
+// sequences, and as a side effect, starts all remote protocols
+//
+
+static CONST PWSTR gpwstrProtocolsPath = L"Software\\Microsoft\\Rpc";
+static CONST PWSTR gpwstrProtocolsValue = L"DCOM Protocols";
+
+ORSTATUS
+InitRemoteProtocols(
+ OUT PWSTR &pwstrProtseqs,
+ OUT DUALSTRINGARRAY * &pdsaProtseqs,
+ OUT USHORT &cRemoteProtseqs,
+ OUT USHORT * &aRemoteProtseqs
+ )
+{
+ ORSTATUS status = OR_OK;
+ DUALSTRINGARRAY *pdsaPS = NULL;
+ pwstrProtseqs = NULL;
+
+ DWORD dwType;
+ DWORD dwLenBuffer = InitialProtseqBufferLength;
+ HKEY hKey;
+
+ status =
+ RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ gpwstrProtocolsPath,
+ 0,
+ KEY_READ,
+ &hKey);
+
+ if (status != ERROR_SUCCESS)
+ {
+ return status;
+ }
+
+ do
+ {
+ OrMemFree(pwstrProtseqs);
+ pwstrProtseqs = (WCHAR*) OrMemAlloc(dwLenBuffer);
+ if (pwstrProtseqs)
+ {
+ status = RegQueryValueEx(hKey,
+ gpwstrProtocolsValue,
+ 0,
+ &dwType,
+ (PBYTE)pwstrProtseqs,
+ &dwLenBuffer
+ );
+ }
+ else
+ {
+ return OR_NOMEM; // BUGBUG: is OR_NOMEM really likely here??
+ }
+ }
+ while (status == ERROR_MORE_DATA);
+
+ PWSTR pwstr = pwstrProtseqs;
+
+ while(*pwstr)
+ {
+ USHORT id = GetProtseqId(pwstr);
+
+ if ((0 != id) && (ID_NP != id) && !IsLocal(id))
+ {
+ status = UseProtseqIfNecessary(id);
+ }
+
+ pwstr = OrStringSearch(pwstr, 0) + 1;
+ }
+
+ RPC_BINDING_VECTOR *pbv;
+ PWSTR pwstrT;
+ USHORT psaLen = 0;
+ DWORD i;
+
+
+ status = RpcServerInqBindings(&pbv);
+
+ ASSERT(status == RPC_S_NO_BINDINGS || pbv != NULL);
+
+ if (status == RPC_S_NO_BINDINGS) return status;
+
+ PWSTR aBindings[MAX_PROTSEQ_IDS];
+ PWSTR aAddresses [MAX_PROTSEQ_IDS];
+ USHORT aProtseqs[MAX_PROTSEQ_IDS];
+
+ // Build array of protseqs id's and addresses we're listening to.
+
+ for(i = 0; i < pbv->Count; i++)
+ {
+ PWSTR pwstrStringBinding;
+
+ status = RpcBindingToStringBinding(pbv->BindingH[i], &pwstrStringBinding);
+ if (status != RPC_S_OK)
+ {
+ break;
+ }
+
+ ASSERT(pwstrStringBinding);
+
+ status = RpcStringBindingParse(pwstrStringBinding,
+ 0,
+ &pwstrT,
+ &aAddresses[i],
+ 0,
+ 0);
+
+ if (status != RPC_S_OK)
+ {
+ break;
+ }
+
+ aProtseqs[i] = GetProtseqId(pwstrT);;
+ aBindings[i] = pwstrStringBinding;
+ psaLen += OrStringLen(pwstrStringBinding) + 1;
+ cRemoteProtseqs++;
+
+ status = RpcStringFree(&pwstrT);
+ ASSERT(status == RPC_S_OK && pwstrT == 0);
+ }
+
+ status = RpcBindingVectorFree(&pbv);
+ ASSERT(pbv == 0 && status == RPC_S_OK);
+
+ if (cRemoteProtseqs == 0)
+ {
+ // No remote bindings
+ psaLen = 1;
+ }
+
+ // string bindings final null, authn and authz service and two final nulls
+
+ psaLen += 1 + 2 + 2;
+
+ pdsaPS = new (psaLen * sizeof(WCHAR)) DUALSTRINGARRAY;
+
+ aRemoteProtseqs = (USHORT *) OrMemAlloc(sizeof(USHORT)*cRemoteProtseqs);
+
+ if (pdsaPS == NULL || aRemoteProtseqs == NULL)
+ {
+ for ( i = 0; i < cRemoteProtseqs; i++ )
+ {
+ status = RpcStringFree(&aBindings[i]);
+ ASSERT(status == RPC_S_OK);
+ }
+
+ return OR_NOMEM;
+ }
+
+ pdsaPS->wNumEntries = psaLen;
+ pdsaPS->wSecurityOffset = psaLen - 4;
+ pwstrT = pdsaPS->aStringArray;
+
+ for ( i = 0; i < cRemoteProtseqs; i++ )
+ {
+ OrStringCopy(pwstrT, aBindings[i]);
+ pwstrT += OrStringLen(aBindings[i]) + 1;
+ aRemoteProtseqs[i] = aProtseqs[i];
+ status = RpcStringFree(&aBindings[i]);
+ ASSERT(status == RPC_S_OK);
+ }
+
+ if (psaLen == 6)
+ {
+ // No remote bindings, put in first null.
+ pdsaPS->aStringArray[0] = 0;
+ pwstrT++;
+ }
+
+ // Zero final terminator
+ *pwstrT = 0;
+
+ // Security authn service
+ pwstrT++;
+ *pwstrT = RPC_C_AUTHN_WINNT; // BUGBUG: need fix for generality
+
+ // Authz service, -1 means none // BUGBUG: -1 causes errors
+ pwstrT++;
+ *pwstrT = 0;
+
+ // Final, final NULLS
+ pwstrT++;
+ pwstrT[0] = 0;
+ pwstrT[1] = 0;
+
+ ASSERT(dsaValid(pdsaPS));
+
+ pdsaProtseqs = CompressStringArray(pdsaPS,TRUE);
+ delete pdsaPS;
+
+ if (pdsaProtseqs == NULL)
+ {
+ return OR_NOMEM;
+ }
+
+ ASSERT(dsaValid(pdsaProtseqs));
+ return status;
+}
+
+
+
+//
+// Helper Macro for constructor below only
+//
+
+#define AssignAndAdvance(Var,Type) \
+ Type OR_BASED * *Var = (Type OR_BASED **) pb; \
+ pb += sizeof(Type OR_BASED *);
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSharedGlobals::CSharedGlobals
+//
+// Synopsis: Create table of globals for DCOM95
+//
+// Arguments: [pwszName] - name for shared memory
+//
+// Algorithm: Create and map in shared memory for the table
+//
+// History: 13-Feb-96 SatishT Created
+//
+//--------------------------------------------------------------------------
+CSharedGlobals::CSharedGlobals(WCHAR *pwszName, ORSTATUS &status)
+/*---
+
+ NOTE: This constructor uses the shared allocator. Objects of this class
+ should not be created before the shared allocator is initialized.
+
+---*/
+{
+ BOOL fCreated;
+
+ _hSm = CreateSharedFileMapping(
+ pwszName,
+ GLOBALS_TABLE_SIZE,
+ GLOBALS_TABLE_SIZE,
+ NULL,
+ NULL,
+ PAGE_READWRITE,
+ (void **) &_pb,
+ &fCreated
+ );
+
+ Win4Assert(_hSm && _pb && "CSharedGlobals create shared file mapping failed");
+
+ BYTE * pb = _pb;
+
+ gpIdSequence = (LONG *) pb;
+ pb += sizeof(LONG);
+
+ gpdwLastCrashedProcessCheckTime = (DWORD *) pb;
+ pb += sizeof(DWORD);
+
+ gpNextThreadID = (DWORD *) pb;
+ pb += sizeof(DWORD);
+
+ gpcRemoteProtseqs = (USHORT *) pb;
+ pb += sizeof(USHORT);
+
+ AssignAndAdvance(DCOMProtseqIds,USHORT) // see macro above
+ AssignAndAdvance(DCOMProtseqs,WCHAR)
+ AssignAndAdvance(LocalDSA,DUALSTRINGARRAY)
+ AssignAndAdvance(LocalMid,CMid)
+ AssignAndAdvance(PingProcess,CProcess)
+ AssignAndAdvance(OidTable,COidTable)
+ AssignAndAdvance(OxidTable,COxidTable)
+ AssignAndAdvance(MidTable,CMidTable)
+ AssignAndAdvance(ProcessTable,CProcessTable)
+
+ if (fCreated) // if we got here first, so create the tables
+ {
+ memset(_pb, 0, GLOBALS_TABLE_SIZE);
+
+ // Initialize the sequence number for AllocateId, the last time crashed
+ // processes were detected and the thread ID sequence in shared memory
+ *gpIdSequence = 1;
+
+ *gpdwLastCrashedProcessCheckTime = 0;
+
+ *gpNextThreadID = 1;
+
+ // I know this is paranoid but I have been bitten before ..
+ gpRemoteProtseqIds = NULL;
+ gpwstrProtseqs = NULL;
+ gpLocalDSA = NULL;
+ gpLocalMid = NULL;
+ gpPingProcess = NULL;
+ gpOxidTable = NULL;
+ gpOidTable = NULL;
+ gpMidTable = NULL;
+ gpProcessTable = NULL;
+
+ // initialize remote protocol strings and
+ // the DSA bindings of local OR in shared memory
+ PWSTR pwstr;
+ DUALSTRINGARRAY *pdsa;
+ USHORT *aProtseqIds;
+
+ InitRemoteProtocols(pwstr,pdsa,*gpcRemoteProtseqs,aProtseqIds);
+
+ *DCOMProtseqIds = OR_BASED_POINTER(WCHAR,aProtseqIds);
+ *DCOMProtseqs = OR_BASED_POINTER(WCHAR,pwstr);
+ *LocalDSA = OR_BASED_POINTER(DUALSTRINGARRAY,pdsa);
+
+ // initialize local Mid object in shared memory
+ NEW_OR_BASED(*LocalMid,CMid,(OR_FULL_POINTER(DUALSTRINGARRAY,*LocalDSA),status,0));
+ if (status != OR_OK)
+ {
+ DELETE_OR_BASED(CMid,*LocalMid);
+ *LocalMid = NULL;
+ }
+
+ // initialize ping thread's process object in shared memory
+ NEW_OR_BASED(*PingProcess,CProcess,(0));
+
+ // Assume 16 exporting processes/threads.
+ NEW_OR_BASED(*OxidTable,COxidTable,(OXID_TABLE_SIZE));
+
+ // Assume 11 exported OIDs per process/thread.
+ NEW_OR_BASED(*OidTable,COidTable,(OID_TABLE_SIZE));
+
+ // Assume 16 machine locations for OXIDs.
+ NEW_OR_BASED(*MidTable,CMidTable,(MID_TABLE_SIZE));
+
+ // Assume 16 simultaneouly active local processes.
+ NEW_OR_BASED(*ProcessTable,CProcessTable,(PROCESS_TABLE_SIZE));
+
+ // Add local CMid object to global shared table
+ if (*LocalMid && *MidTable)
+ status = (*MidTable)->Add(OR_FULL_POINTER(CMid,*LocalMid));
+ }
+
+ gpRemoteProtseqIds = OR_FULL_POINTER(USHORT,*DCOMProtseqIds);
+ gpwstrProtseqs = OR_FULL_POINTER(WCHAR,*DCOMProtseqs);
+ gpLocalDSA = OR_FULL_POINTER(DUALSTRINGARRAY,*LocalDSA);
+ gpLocalMid = OR_FULL_POINTER(CMid,*LocalMid);
+ gpPingProcess = OR_FULL_POINTER(CProcess,*PingProcess);
+ gpOxidTable = OR_FULL_POINTER(COxidTable,*OxidTable);
+ gpOidTable = OR_FULL_POINTER(COidTable,*OidTable);
+ gpMidTable = OR_FULL_POINTER(CMidTable,*MidTable);
+ gpProcessTable = OR_FULL_POINTER(CProcessTable,*ProcessTable);
+}
+
+
+#ifndef _CHICAGO_
+
+/* MIDL allocate and free */
+
+void __RPC_FAR * __RPC_API midl_user_allocate(size_t len)
+{
+ return(PrivMemAlloc(len));
+}
+
+void __RPC_API midl_user_free(void __RPC_FAR * ptr)
+{
+ PrivMemFree(ptr);
+}
+
+#endif // _CHICAGO_
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/globals.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/globals.hxx
new file mode 100644
index 000000000..daa0ce419
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/globals.hxx
@@ -0,0 +1,90 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: globals.hxx
+//
+// Contents: Class used to encapsulate shared global data structures for DCOM95.
+//
+// Functions:
+//
+// History: 13-Feb-96 SatishT Created
+//
+//--------------------------------------------------------------------------
+#ifndef __GLOBALS_HXX__
+#define __GLOBALS_HXX__
+
+#define GLOBALS_TABLE_SIZE \
+ ( \
+ sizeof(USHORT) + \
+ sizeof(LONG) + \
+ 2 * sizeof(DWORD) + \
+ 9 * sizeof(void OR_BASED *) \
+ )
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSharedGlobals
+//
+// Purpose: Initializing access to shared global data
+//
+// Interface: InitOK - whether initialization succeeded.
+//
+// History: 13-Feb-96 SatishT Created
+//
+// Notes: The constructor for this class uses the shared allocator. Objects of this
+// class should not be created before the shared allocator is initialized.
+//
+//
+//--------------------------------------------------------------------------
+class CSharedGlobals
+{
+public:
+
+ CSharedGlobals(WCHAR *pwszName, ORSTATUS &status);
+
+ ~CSharedGlobals();
+
+ BOOL InitOK(void);
+
+ /* add public members for shared tables here */
+
+private:
+
+ HANDLE _hSm;
+ BYTE * _pb;
+};
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSharedGlobals::~CSharedGlobals
+//
+// Synopsis: Clean up hint table object
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CSharedGlobals::~CSharedGlobals(void)
+{
+ CloseSharedFileMapping(_hSm, _pb);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSharedGlobals::InitOK
+//
+// Synopsis: Whether initialization worked
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CSharedGlobals::InitOK(void)
+{
+ return _hSm != NULL;
+}
+
+
+#endif // __GLOBALS_HXX__
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/iface.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/iface.cxx
new file mode 100644
index 000000000..25a455a2c
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/iface.cxx
@@ -0,0 +1,346 @@
+#include <or.hxx>
+
+ error_status_t Connect(
+ OUT HPROCESS *pProcess,
+ OUT ULONG *pdwTimeoutInSeconds,
+ OUT DUALSTRINGARRAY **ppdsaOrBindings,
+ OUT MID *pLocalMid,
+ IN long cIdsToReserve,
+ OUT ID *pidReservedBase,
+ OUT ULONG *pfConnectFlags,
+ OUT DWORD *pAuthnLevel,
+ OUT DWORD *pImpLevel,
+ OUT DWORD *pcServerSvc,
+ OUT USHORT **aServerSvc,
+ OUT DWORD *pcClientSvc,
+ OUT USHORT **aClientSvc,
+ OUT DWORD *pThreadID)
+ {
+
+ ORSTATUS status;
+
+ status = ConnectDCOM(
+ pProcess,
+ pdwTimeoutInSeconds,
+ pLocalMid,
+ pfConnectFlags,
+ pAuthnLevel,
+ pImpLevel,
+ pcServerSvc,
+ aServerSvc,
+ pcClientSvc,
+ aClientSvc,
+ pThreadID
+ );
+
+ if (status == OR_OK)
+ {
+ status = AllocateReservedIds(
+ cIdsToReserve,
+ pidReservedBase
+ );
+ }
+
+ if (status == OR_OK)
+ {
+ *ppdsaOrBindings = (DUALSTRINGARRAY *) PrivMemAlloc(
+ gpLocalDSA->wNumEntries * sizeof(WCHAR)
+ + sizeof(DUALSTRINGARRAY) );
+
+ if (*ppdsaOrBindings)
+ {
+ dsaCopy(*ppdsaOrBindings, gpLocalDSA);
+ }
+ else
+ {
+ status = OR_NOMEM;
+ }
+ }
+
+ return status;
+}
+
+
+ error_status_t ClientResolveOXID(
+ IN HPROCESS phProcess,
+ IN OXID *poxidServer,
+ IN DUALSTRINGARRAY *pssaServerObjectResolverBindings,
+ IN long fApartment,
+ OUT OXID_INFO *poxidInfo,
+ OUT MID *pLocalMidOfRemote)
+ {
+ return GetOXID(
+ phProcess,
+ *poxidServer,
+ pssaServerObjectResolverBindings,
+ fApartment,
+ 0, // wProtseqId not specified
+ *poxidInfo,
+ *pLocalMidOfRemote
+ );
+ }
+
+
+
+ error_status_t ServerAllocateOXIDAndOIDs(
+ IN HPROCESS hProcess,
+ OUT OXID *poxidServer,
+ IN long fApartment,
+ IN unsigned long cOids,
+ OUT OID aOid[ ],
+ OUT unsigned long *pcOidsAllocated,
+ IN OXID_INFO *pOxidInfo,
+ IN DUALSTRINGARRAY *pdsaStringBindings,
+ IN DUALSTRINGARRAY *pdsaSecurityBindings)
+ {
+ ComDebOut((DEB_OXID, "Calling ServerAllocateOXIDAndOIDs\n"));
+
+ DUALSTRINGARRAY *pdsaMergedBindings;
+
+ ORSTATUS status = MergeBindings(
+ pdsaStringBindings,
+ pdsaSecurityBindings,
+ &pdsaMergedBindings
+ );
+
+ if (status != OR_OK) return status;
+
+ status = ServerAllocateOXID(
+ hProcess,
+ fApartment,
+ pOxidInfo,
+ pdsaMergedBindings,
+ *poxidServer
+ );
+
+ if (status == OR_OK)
+ {
+ ComDebOut((DEB_OXID, "Calling ServerAllocateOIDs\n"));
+
+ status = ServerAllocateOIDs(
+ hProcess,
+ poxidServer,
+ cOids,
+ aOid,
+ pcOidsAllocated
+ );
+ }
+ else
+ {
+ ComDebOut((DEB_OXID, "Not Calling ServerAllocateOIDs, status = %d\n",
+ status));
+ }
+
+ return status;
+ }
+
+
+
+ error_status_t ServerAllocateOIDs(
+ IN HPROCESS hProcess,
+ IN OXID *poxidServer,
+ IN unsigned long cOids,
+ OUT OID aOid[ ],
+ OUT unsigned long *pcOidsAllocated)
+ {
+ ComDebOut((DEB_ITRACE, "Entering ServerAllocateOIDs\n"));
+
+ ORSTATUS status;
+
+ *pcOidsAllocated = 0;
+
+ for (ULONG i = 0; i < cOids; i++)
+ {
+ status = ServerAllocateOID(
+ hProcess,
+ *poxidServer,
+ aOid[i]
+ );
+
+ if (status != OR_OK)
+ {
+ *pcOidsAllocated = i;
+ break;
+ }
+ else
+ {
+ (*pcOidsAllocated)++;
+ }
+ }
+
+ return status;
+ }
+
+
+
+ error_status_t ServerFreeOXIDAndOIDs(
+ IN HPROCESS hProcess,
+ IN OXID oxidServer,
+ IN unsigned long cOids,
+ IN OID aOids[ ])
+ {
+ return ServerFreeOXID(
+ hProcess,
+ oxidServer,
+ cOids,
+ aOids
+ );
+ }
+
+
+
+
+VOID CALLBACK RundownTimerProc(
+ HWND hwnd, // handle of window for timer messages
+ UINT uMsg, // WM_TIMER message
+ UINT idEvent, // timer identifier
+ DWORD dwTime // current system time
+ )
+{
+ return;
+
+ if (idEvent != IDT_DCOM_RUNDOWN) return; // shouldn't happen -- this is only
+ // used as callback for one timer
+
+ // find the OXID for this thread
+
+ COleTls tls;
+
+ ASSERT(((OXIDEntry *)tls->pOXIDEntry)->dwTid == GetCurrentThreadId());
+ ASSERT(((OXIDEntry *)tls->pOXIDEntry)->dwPid == GetCurrentProcessId());
+
+ MOXID Moxid = ((OXIDEntry *)tls->pOXIDEntry)->moxid;
+
+ OXID Oxid;
+ MID Mid;
+
+ OXIDFromMOXID(Moxid,&Oxid);
+ MIDFromMOXID(Moxid,&Mid);
+
+ CProtectSharedMemory protector; // locks through rest of lexical scope
+
+ COxid *pOxid = gpOxidTable->Lookup(CId2Key(Oxid, Mid));
+
+ ASSERT(pOxid);
+
+ ComDebOut((DEB_OXID, "Attempting Rundown in apartment OXID = %08x PID = %d\n",
+ Oxid,GetCurrentProcessId()));
+
+ // find the RemUnk for this OXID -- we want only the IRundown interface
+
+ IRundown *pRemUnk = tls->pRemoteUnk;
+
+ // If there is no RemUnk, nothing is marshalled, so forget about rundown
+ if (!pRemUnk) return;
+
+ ComDebOut((DEB_OXID, "There is a RemUnk for apartment OXID = %08x PID = %d\n",
+ Oxid,GetCurrentProcessId()));
+
+ // go and check your OIDs here
+
+ pOxid->RundownOidsIfNecessary(pRemUnk);
+}
+
+
+DWORD _stdcall
+RundownThread(void *self)
+{
+ return 0;
+
+ DWORD dwLoopCount = 0;
+
+ COxid *pSelf = (COxid*) self; // store away "this" pointer
+
+ while (TRUE)
+ {
+ ::Sleep(RUNDOWN_TIMER_INTERVAL); // BUGBUG: use Sleep() from CTime?
+
+ dwLoopCount++;
+
+ ComDebOut((DEB_OXID, "Attempting Rundown in PID = %d\n",
+ GetCurrentProcessId()));
+
+ CProtectSharedMemory protector; // locks through rest of lexical scope
+
+ IRundown *pRemUnk = gpMTARemoteUnknown;
+
+ // If there is no RemUnk, nothing is marshalled, so forget about rundown
+ if (!pRemUnk) return OR_OK;
+
+ ComDebOut((DEB_OXID, "There is a RemUnk for free OXID = %08x PID = %d\n",
+ pSelf->GetOXID(),GetCurrentProcessId()));
+
+ ASSERT(!IsBadWritePtr(pRemUnk,sizeof(CRemoteUnknown)));
+
+ pSelf->RundownOidsIfNecessary(pRemUnk);
+ }
+
+ return OR_OK;
+}
+
+
+DWORD _stdcall
+PingThread(void) // BUGBUG: need another thread to watch over this one?
+{
+ return 0;
+
+ while (TRUE)
+ {
+ Sleep(BasePingInterval);
+
+ {
+ CProtectSharedMemory protector; // locks through rest of scope except where
+ // temporarily released
+
+ ORSTATUS status;
+
+ // First do rundown detection -- this may cause deletes from ping sets
+
+ COxidTableIterator OxidIter(gpPingProcess->_MyOxids);
+
+ for (COxid *pOxid = OxidIter.Next(); pOxid != NULL; pOxid = OxidIter.Next())
+ {
+ pOxid->RundownOidsIfNecessary(NULL); // No IRundown param needed
+ }
+
+ // Then do pinging
+
+ CMidTableIterator MidIter(*gpMidTable);
+
+ for (CMid *pMid = MidIter.Next(); pMid != NULL; pMid = MidIter.Next())
+ {
+ if (pMid != gpLocalMid)
+ {
+ status = pMid->PingServer();
+ }
+ }
+ }
+ }
+
+ return OR_OK;
+}
+
+
+error_status_t
+ResolveClientOXID(
+ handle_t hClient,
+ void *hProcess,
+ OXID *poxidServer,
+ DUALSTRINGARRAY *pdsaServerBindings,
+ LONG fApartment,
+ USHORT wProtseqId,
+ OXID_INFO *poxidInfo,
+ MID *pDestinationMid
+ )
+{
+ return GetOXID(
+ (CProcess*)hProcess,
+ *poxidServer,
+ pdsaServerBindings,
+ fApartment,
+ wProtseqId,
+ *poxidInfo,
+ *pDestinationMid
+ );
+}
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/linklist.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/linklist.cxx
new file mode 100644
index 000000000..715c38a64
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/linklist.cxx
@@ -0,0 +1,173 @@
+
+/*++
+
+Microsoft Windows NT RPC Name Service
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ linklist.cxx
+
+Abstract:
+
+ This module contains definitions of non inline member functions for the
+ basic implementation class CLinkList.
+
+Author:
+
+ Satish Thatte (SatishT) 08/16/95 Created all the code below except where
+ otherwise indicated.
+
+--*/
+
+#include <or.hxx>
+
+
+USHORT
+CLinkList::Size()
+{
+ USHORT result = 0;
+
+ for (Link OR_BASED *pL = _pLnkFirst; pL != NULL; pL = pL->_pNext)
+ {
+ result++;
+ }
+
+ return result;
+}
+
+
+
+void
+CLinkList::Insert(ORSTATUS& status, IDataItem * pData)
+{
+ ASSERT(pData != NULL); // do not allow inssertion of NULL pointers
+
+ status = OR_OK;
+
+ NEW_OR_BASED(
+ _pLnkFirst,
+ Link,
+ (OR_BASED_POINTER(IDataItem,pData), _pLnkFirst)
+ );
+
+ if (!_pLnkFirst)
+ {
+ status = OR_NOMEM;
+ }
+ else
+ {
+ pData->Reference();
+ }
+}
+
+
+void
+CLinkList::Clear() { // deletes all links but not the data
+
+ Link OR_BASED * pLnkCurr = _pLnkFirst;
+
+ while (pLnkCurr)
+ {
+ Link OR_BASED * pLnkDel = pLnkCurr;
+ pLnkCurr = pLnkCurr->_pNext;
+ pLnkDel->_pData->Release();
+ DELETE_OR_BASED(Link,pLnkDel);
+ }
+
+ _pLnkFirst = NULL;
+}
+
+
+IDataItem*
+CLinkList::Pop()
+
+/*++
+Routine Description:
+
+ Delete first item in the CLinkList and return it
+
+--*/
+
+{
+ if (!_pLnkFirst) return NULL;
+
+ IDataItem* pResult = OR_FULL_POINTER(IDataItem,_pLnkFirst->_pData);
+ Link OR_BASED * oldFirst = _pLnkFirst;
+ _pLnkFirst = _pLnkFirst->_pNext;
+ DELETE_OR_BASED(Link,oldFirst);
+
+ pResult->Release();
+ return pResult;
+}
+
+IDataItem *
+CLinkList::Remove(ISearchKey& di)
+
+/*++
+Routine Description:
+
+ Remove the specified item and return it.
+
+--*/
+
+{
+ if (!_pLnkFirst) return NULL; // empty list
+
+ if (di == *OR_FULL_POINTER(IDataItem,(_pLnkFirst->_pData))) // Remove first item
+ {
+ return Pop();
+ }
+
+ Link OR_BASED * pLnkPrev = _pLnkFirst,
+ OR_BASED * pLnkCurr = _pLnkFirst->_pNext;
+
+ while (pLnkCurr && di != (*OR_FULL_POINTER(IDataItem,(pLnkCurr->_pData))))
+ {
+ pLnkPrev = pLnkCurr;
+ pLnkCurr = pLnkCurr->_pNext;
+ }
+
+ if (!pLnkCurr) return NULL; // not found
+
+ /* pLnkCurr contains the item to be removed and it is not the only
+ item in the list since it is not the first item */
+
+ pLnkPrev->_pNext = pLnkCurr->_pNext;
+
+ IDataItem * pResult = OR_FULL_POINTER(IDataItem,pLnkCurr->_pData);
+ DELETE_OR_BASED(Link,pLnkCurr);
+
+ pResult->Release();
+ return pResult;
+}
+
+
+IDataItem*
+CLinkList::Find(ISearchKey& di) // item to Find
+
+
+/*++
+Routine Description:
+
+ Unlike Remove, this method is designed to use a client-supplied
+ comparison function instead of pointer equality. The comparison
+ function is expected to behave like strcmp (returning <0 is less,
+ 0 if equal and >0 if greater).
+
+--*/
+
+{
+ if (!_pLnkFirst) return NULL; // empty list
+
+ Link OR_BASED * pLnkCurr = _pLnkFirst;
+
+ while (pLnkCurr && di != (*OR_FULL_POINTER(IDataItem,(pLnkCurr->_pData))))
+ pLnkCurr = pLnkCurr->_pNext;
+
+ if (!pLnkCurr) return NULL; // not found
+ else return OR_FULL_POINTER(IDataItem,pLnkCurr->_pData);
+}
+
+
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/linklist.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/linklist.hxx
new file mode 100644
index 000000000..ba937dd88
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/linklist.hxx
@@ -0,0 +1,389 @@
+
+/*++
+
+Microsoft Windows NT RPC Name Service
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ linklist.hxx
+
+Abstract:
+
+ This module contains definitions of class CLinkList, and templates derived
+ from it for type safety.Multithreading safety is assumed to be enforced
+ by external locking.
+
+Author:
+
+ Satish Thatte (SatishT) 03/12/96 Created all the code below except where
+ otherwise indicated.
+
+
+--*/
+
+
+
+#ifndef __LINKLIST_HXX_
+#define __LINKLIST_HXX_
+
+#include <or.hxx>
+
+// For the moment, we only permit linked lists of hash table items.
+// This may be restructured in future.
+
+struct ISearchKey;
+class CTableElement;
+
+typedef CTableElement IDataItem;
+
+
+/*++
+
+Class Definition:
+
+ CLinkList
+
+Abstract:
+
+ This is a simple linked list class. It has a private Link class.
+
+--*/
+
+
+class CLinkList
+{
+
+ friend class CLinkListIterator;
+
+ protected:
+
+ struct Link
+ {
+ Link OR_BASED * _pNext;
+ IDataItem OR_BASED * _pData;
+
+#if DBG
+ void IsValid()
+ {
+ IsGoodBasedPtr(_pNext);
+ //IsGoodBasedPtr(_pData);
+ if (_pNext) _pNext->IsValid();
+ }
+
+ DECLARE_VALIDITY_CLASS(CLinkList)
+#endif
+
+ Link(IDataItem OR_BASED * a, Link OR_BASED * n);
+
+ void * operator new(size_t s)
+ {
+ return OrMemAlloc(s);
+ }
+
+ void operator delete(void * p) // do not inherit this!
+ {
+ OrMemFree(p);
+ }
+ };
+
+ Link OR_BASED * _pLnkFirst;
+
+ // two protected functions for specialized use when reshuffling
+ // lists -- among other things, reference counts are not changed
+ // since the reference is deemed to be held by the link
+
+ Link * PopLink()
+ {
+ Link * pResult = OR_FULL_POINTER(Link,_pLnkFirst);
+
+ if (pResult != NULL)
+ {
+ _pLnkFirst = _pLnkFirst->_pNext;
+ pResult->_pNext = NULL;
+ }
+
+ return pResult;
+ }
+
+ void
+ PushLink(Link * pLink)
+ {
+ ASSERT(pLink != NULL);
+
+ pLink->_pNext = _pLnkFirst;
+ _pLnkFirst = OR_BASED_POINTER(Link,pLink);
+ }
+
+ public:
+
+#if DBG
+ void IsValid()
+ {
+ IsGoodBasedPtr(_pLnkFirst);
+ if (_pLnkFirst) _pLnkFirst->IsValid();
+ }
+
+ DECLARE_VALIDITY_CLASS(CLinkList)
+#endif
+
+ CLinkList()
+ {
+ _pLnkFirst = NULL;
+ }
+
+
+ ~CLinkList()
+ {
+ Clear();
+ }
+
+ void * operator new(size_t s)
+ {
+ return OrMemAlloc(s);
+ }
+
+ void operator delete(void * p) // do not inherit this!
+ {
+ OrMemFree(p);
+ }
+
+ // Is there anything in this list?
+
+ BOOL IsEmpty();
+
+ // Insert at the beginning
+
+ USHORT Size();
+
+ void Insert(ORSTATUS& status, IDataItem * pData);
+
+ // Remove first item and return it
+
+ IDataItem * Pop();
+
+ // Remove the specified item and return it
+
+ IDataItem * Remove(ISearchKey&);
+
+ // Find the specified item and return it
+
+ IDataItem * Find(ISearchKey&);
+
+ // delete all links, but not the data items
+
+ void Clear();
+};
+
+
+/*++
+
+Class Definition:
+
+ CLinkListIterator
+
+Abstract:
+
+ An iterator class for traversing a CLinkList.
+
+--*/
+
+
+class CLinkListIterator {
+
+ CLinkList::Link OR_BASED * _pIter; // the current link
+
+ public:
+
+ CLinkListIterator() : _pIter(NULL) {}
+
+ void Init(CLinkList& source);
+
+ IDataItem * Next(); // advance the iterator and return _pNext IDataItem
+
+ BOOL Finished(); // anything further coming?
+};
+
+
+
+/*++
+
+Template Class Definition:
+
+ TCSafeLinkList
+
+Abstract:
+
+ The template TCSafeLinkList make it easy to produce "type safe" incarnations of
+ the CLinkList classe, avoiding the use of casts in client code.
+
+ Note that Data must be a subtype of IDataItem.
+
+--*/
+
+template <class Data>
+class TCSafeLinkList : private CLinkList
+{
+
+ friend class TCSafeLinkListIterator<Data>;
+ friend class CResolverHashTable;
+
+ public:
+
+ void * operator new(size_t s)
+ {
+ return OrMemAlloc(s);
+ }
+
+ void operator delete(void * p) // do not inherit this!
+ {
+ OrMemFree(p);
+ }
+
+ void IsValid()
+ {
+ CLinkList::IsValid();
+ }
+
+
+ BOOL IsEmpty()
+ {
+ return CLinkList::IsEmpty();
+ }
+
+ USHORT Size()
+ {
+ return CLinkList::Size();
+ }
+
+ void Insert(ORSTATUS& status, Data * pData)
+ {
+ CLinkList::Insert(status, pData);
+ }
+
+ Data * Pop()
+ {
+ return (Data *) CLinkList::Pop();
+ }
+
+ Data * Remove(ISearchKey& sk)
+ {
+ return (Data *) CLinkList::Remove(sk);
+ }
+
+ Data * Find(ISearchKey& sk)
+ {
+ return (Data *) CLinkList::Find(sk);
+ }
+
+ void Clear()
+ {
+ CLinkList::Clear();
+ }
+
+ void Transfer(TCSafeLinkList& target)
+ {
+ target._pLnkFirst = _pLnkFirst;
+ _pLnkFirst = NULL;
+ }
+};
+
+
+
+/*++
+
+Template Class Definition:
+
+ TCSafeLinkListIterator
+
+Abstract:
+
+ The iterator for TCSafeLinkLists.
+
+--*/
+
+template <class Data>
+class TCSafeLinkListIterator : private CLinkListIterator {
+
+ public:
+
+ void Init(TCSafeLinkList<Data>& l)
+ {
+ CLinkListIterator::Init(l);
+ }
+
+ Data * Next()
+ {
+ return (Data *) CLinkListIterator::Next();
+ }
+
+ BOOL Finished()
+ {
+ return CLinkListIterator::Finished();
+ }
+
+};
+
+
+#define DEFINE_LIST(DATA) \
+ typedef TCSafeLinkList<DATA> DATA##List; \
+ typedef TCSafeLinkListIterator<DATA> DATA##ListIterator;
+
+
+
+//
+// Inline methods for CLinkList
+//
+
+inline
+CLinkList::Link::Link(IDataItem OR_BASED * a, Link OR_BASED * n)
+{
+ _pData = a;
+ _pNext = n;
+}
+
+
+
+inline
+BOOL
+CLinkList::IsEmpty()
+{
+ return _pLnkFirst == NULL;
+}
+
+
+//
+// Inline methods for CLinkListIterator
+//
+
+
+inline
+void
+CLinkListIterator::Init(CLinkList& source)
+{
+ _pIter = source._pLnkFirst;
+}
+
+
+
+inline
+IDataItem*
+CLinkListIterator::Next() { // advance the iterator and return _pNext IDataItem
+
+ if (!_pIter) return NULL;
+
+ IDataItem* result = OR_FULL_POINTER(IDataItem,_pIter->_pData);
+ _pIter = _pIter->_pNext;
+
+ return result;
+}
+
+inline
+BOOL
+CLinkListIterator::Finished()
+{
+ return _pIter == NULL;
+}
+
+
+#endif // __LINKLIST_HXX_
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/manager.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/manager.cxx
new file mode 100644
index 000000000..1391a4e85
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/manager.cxx
@@ -0,0 +1,766 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Manager.cxx
+
+Abstract:
+
+ InProc OR interface
+
+Author:
+
+ Satish Thatte [SatishT] Feb-07-1996
+
+Revision Hist:
+
+ SatishT 02-07-96 Created
+
+--*/
+
+
+#include <or.hxx>
+
+
+//
+// Manager (server-side) calls to the local OR interface. lclor.idl
+//
+
+error_status_t
+ConnectDCOM(
+ IN OUT HPROCESS *phProcess,
+ OUT ULONG *pdwTimeoutInSeconds,
+ OUT MID *pLocalMid,
+ OUT ULONG *pfConnectFlags,
+ OUT DWORD *pAuthnLevel,
+ OUT DWORD *pImpLevel,
+ OUT DWORD *pcServerSvc,
+ OUT USHORT **aServerSvc,
+ OUT DWORD *pcClientSvc,
+ OUT USHORT **aClientSvc,
+ OUT DWORD *pThreadID
+ )
+{
+ ORSTATUS status = OR_OK;
+ CProcess *hProcess;
+
+ StartDCOM();
+
+ *pdwTimeoutInSeconds = BaseTimeoutInterval;
+ *pLocalMid = gLocalMID;
+
+ // Fill in security parameters.
+
+ *pfConnectFlags = 0;
+
+ if (s_fEnableDCOM == FALSE) *pfConnectFlags |= CONNECT_DISABLEDCOM;
+ if (s_fMutualAuth) *pfConnectFlags |= CONNECT_MUTUALAUTH;
+ if (s_fSecureRefs) *pfConnectFlags |= CONNECT_SECUREREF;
+
+ *pAuthnLevel = s_lAuthnLevel;
+ *pImpLevel = s_lImpLevel;
+ *pcServerSvc = s_cServerSvc;
+ *aServerSvc = CopyArray(s_cServerSvc,s_aServerSvc,&status);
+ *pcClientSvc = s_cClientSvc;
+ *aClientSvc = CopyArray(s_cClientSvc,s_aClientSvc,&status);
+
+ if (status != OR_OK) return status;
+
+ CProtectSharedMemory protector; // locks through rest of lexical scope
+
+ *pThreadID = (*gpNextThreadID)++;
+
+ hProcess = new CProcess((long) *phProcess); // BUGBUG: this is a temp ID
+ // coming from bridge.cxx
+
+ if (hProcess)
+ {
+ gpProcess = *phProcess = hProcess;
+ gpProcessTable->Add(hProcess); // BUGBUG: and rundown an old process,
+ // if there is one, with the same _processID
+ }
+ else
+ {
+ status = OR_NOMEM;
+ }
+
+ OrDbgDetailPrint(("OR: Client connected\n"));
+
+ return(status);
+}
+
+
+error_status_t Disconnect(
+ IN OUT HPROCESS *phProcess
+ )
+{
+ // ASSERT(*phProcess!=NULL); // BUGBUG: the right thing to do
+ if (*phProcess == NULL) return OR_OK;
+
+ CProcess *hProcess = *phProcess;
+
+ CProtectSharedMemory protector; // locks through rest of lexical scope
+
+ hProcess->Rundown();
+ gpProcessTable->Remove(*hProcess);
+ *phProcess = NULL;
+ DCOM_Started = FALSE;
+ return OR_OK;
+}
+
+
+
+error_status_t
+AllocateReservedIds(
+ IN LONG cIdsToReserve,
+ OUT ID *pidReservedBase
+ )
+/*++
+
+Routine Description:
+
+ Called by local clients to reserve a range of IDs which will
+ not conflict with any other local IDs.
+
+Arguments:
+
+ cIdsToReserve - Number of IDs to reserve.
+
+ pidReservedBase - Starting value of the reserved IDs. The
+ lower DWORD of this can be increatmented to generate
+ cIdsToReserve unique IDs.
+
+Return Value:
+
+ OR_OK
+
+--*/
+{
+ UINT type;
+
+ if (cIdsToReserve > 10 || cIdsToReserve < 0)
+ {
+ cIdsToReserve = 10;
+ }
+
+ CProtectSharedMemory protector; // locks through rest of lexical scope
+
+ *pidReservedBase = AllocateId(cIdsToReserve);
+ return(OR_OK);
+}
+
+
+error_status_t
+GetOXID(
+ IN HPROCESS hProcess,
+ IN OXID Oxid,
+ IN DUALSTRINGARRAY *pdsaServerObjectResolverBindings,
+ IN long fApartment,
+ IN USHORT wProtseqId,
+ OUT OXID_INFO& OxidInfo,
+ OUT MID &Mid
+ )
+/*++
+
+Routine Description:
+
+ Discovers the OXID_INFO for an oxid. Will find local
+ OXIDs without any help from resolver process.
+
+ It needs OR bindings in order to resolve remote OXIDs.
+ REVIEW: Should the resolver process be involved in this?
+
+Arguments:
+
+ hProcess - The context handle of the process.
+
+ Oxid - The OXID (a uuid) to resolve.
+
+ pdsaServerObjectResolverBindings - Compressed string bindings to
+ the OR on the server's machine.
+
+ fApartment - non-zero if the client is aparment model.
+
+ OxidInfo - If successful this will contain information about the oxid and
+ an expanded string binding to the server oxid's process.
+
+ Mid - The machine ID assigned locally for the remote machine.
+ This is obviously meaningful only for remote OXIDs.
+
+Return Value:
+
+ OR_NOMEM - Common.
+
+ OR_BADOXID - Unable to resolve it.
+
+ OR_OK - Success.
+
+--*/
+{
+ ComDebOut((DEB_OXID, "ResolveClientOXID OXID = %08x\n",Oxid));
+
+ COxid *pOxid;
+ CMid *pMid;
+ ORSTATUS status = OR_OK;
+ BOOL fNewMID = FALSE;
+
+ if (wProtseqId == 0) // Normal (non SCM) call
+ {
+ // In case of failure, zero out param pointers.
+ OxidInfo.psa = NULL;
+ }
+
+ if (!pdsaServerObjectResolverBindings)
+ pdsaServerObjectResolverBindings = gpLocalDSA;
+
+ ASSERT(dsaValid(pdsaServerObjectResolverBindings));
+
+ CProtectSharedMemory protector; // locks through rest of lexical scope
+
+#if DBG
+ if (hProcess) hProcess->IsValid(); // don't validate for fake SCM calls
+#endif
+
+ if (dsaCompare(gpLocalDSA,pdsaServerObjectResolverBindings)) // local OXID
+ {
+ pMid = gpLocalMid;
+ }
+ else
+ {
+ // Attempt to lookup MID
+
+ // CMidKey makes a copy of the bindings to maintain validity
+
+ CMidKey midkey(pdsaServerObjectResolverBindings,TRUE,status);
+
+ if (status != OR_OK) return status;
+
+ pMid = gpMidTable->Lookup(midkey);
+
+ if (NULL == pMid)
+ {
+ pMid = new(pdsaServerObjectResolverBindings->wNumEntries * sizeof(WCHAR))
+ CMid(pdsaServerObjectResolverBindings, status, wProtseqId);
+
+ // We initialize local MID autologically,
+ // therefore this has to be a remote MID
+
+ if (pMid && status == OR_OK)
+ {
+ status = gpMidTable->Add(pMid);
+ if (status != OR_OK)
+ {
+ delete pMid;
+ return status;
+ }
+
+ fNewMID = TRUE;
+ }
+ else
+ {
+ return (status == OR_OK) ? OR_NOMEM : status;
+ }
+ }
+ }
+
+ ASSERT(pMid); // otherwise we would have returned by now
+
+ Mid = pMid->GetMID();
+
+ pOxid = gpOxidTable->Lookup(CId2Key(Oxid, Mid));
+
+ if (pMid->IsLocal())
+ {
+ ASSERT(!fNewMID);
+
+ if (pOxid)
+ {
+ return pOxid->GetInfo(&OxidInfo);
+ }
+ else // local OXIDs should be registered by server
+ {
+ return OR_BADOXID;
+ }
+ }
+
+ if (NULL == pOxid)
+ {
+ // Need to allocate the OXID. First step is to resolve it remotely.
+
+ if ( OxidInfo.psa == NULL ) // genuine resolve request rather
+ // than a phoney one from the SCM
+ {
+ status = pMid->ResolveRemoteOxid( // This op will also replace the
+ Oxid, // psa with one in shared memory
+ &OxidInfo
+ );
+
+ wProtseqId = pMid->ProtseqOfServer();
+ }
+
+ ASSERT( (status != OR_OK) || (OxidInfo.psa != NULL) );
+
+ if (status == OR_OK)
+ {
+ DUALSTRINGARRAY *pdsaT = dsaSMCopy(OxidInfo.psa);
+
+ if (!pdsaT)
+ {
+ return OR_NOMEM;
+ }
+
+ MIDL_user_free(OxidInfo.psa); // free the original and replace
+ OxidInfo.psa = pdsaT; // with shared memory compressed copy
+
+ pOxid = new COxid(
+ Oxid,
+ pMid,
+ wProtseqId,
+ OxidInfo
+ );
+
+ // remote OXID belongs to ping process ..
+
+ if ((NULL != pOxid) && (gpPingProcess->OwnOxid(pOxid) == OR_OK))
+ {
+ status = gpOxidTable->Add(pOxid);
+ }
+ else
+ {
+ OrMemFree(OxidInfo.psa);
+ delete pOxid;
+ return status;
+ }
+ }
+ else
+ {
+ MIDL_user_free(OxidInfo.psa);
+ return OR_BADOXID;
+ }
+ }
+
+ ASSERT( (status == OR_OK) && pOxid );
+
+ return pOxid->GetInfo(&OxidInfo);
+}
+
+
+error_status_t
+ClientAddOID(
+ IN HPROCESS hProcess,
+ IN OID Oid,
+ IN OXID Oxid,
+ IN MID Mid
+ )
+
+/*++
+
+Routine Description:
+
+ Updates the set of OIDs in use by a process.
+
+
+Arguments:
+
+ hProcess - Context handle for the process.
+
+ Oid - OID to add.
+
+ Oxid - OXID to which OID belongs.
+
+ Mid - MID for location of OXID server.
+
+Return Value:
+
+ OR_OK - All updates completed ok.
+
+ OR_BADOXID - The Oxid was not found
+
+ OR_BADOID - The Oid could not be created or found
+
+Notes:
+
+ Unlike the NT resolver, there is no possibility that the Oxid
+ is not in the gpOxidTable (since client and server Oxid objects
+ are in the same table).
+
+--*/
+{
+ ComDebOut((DEB_OXID, "ClientAddOID\nOID = %08x\nOXID = %08x\nMID = %08x\n",
+ Oid,Oxid,Mid));
+
+ ORSTATUS status = OR_OK;
+
+ // Lookup up the oxid owning this new oid.
+
+ COxid *pOxid = gpOxidTable->Lookup(CId2Key(Oxid,Mid));
+
+ if (NULL == pOxid)
+ {
+ return OR_BADOXID;
+ }
+
+ CProtectSharedMemory protector; // locks through rest of lexical scope
+
+#if DBG
+ hProcess->IsValid();
+#endif
+
+ CMid *pMid = pOxid->GetMid();
+
+ // Find or create the oid.
+
+ COid *pOid = gpOidTable->Lookup(CId2Key(Oid,Mid));
+
+ if (NULL == pOid)
+ {
+ ASSERT(!pMid->IsLocal()); // Local OID should be registered by server
+
+ pOid = new COid(Oid,pOxid);
+
+ if (NULL == pOid)
+ {
+ return OR_NOMEM;
+ }
+
+ status = gpOidTable->Add(pOid);
+ if (status != OR_OK)
+ {
+ delete pOid;
+ return status;
+ }
+
+ status = pMid->AddClientOid(pOid);
+ }
+
+ if (status == OR_OK) status = hProcess->AddOid(pOid);
+
+ return status;
+}
+
+
+error_status_t
+ClientDropOID(
+ IN HPROCESS hProcess,
+ IN OID Oid,
+ IN MID Mid
+ )
+
+/*++
+
+Routine Description:
+
+ Updates the set of remote OIDs in use by a process.
+
+
+Arguments:
+
+ hProcess - Context handle for the process.
+
+ Oid - OID to be removed.
+
+ Mid - MID to which Oid belongs.
+
+Return Value:
+
+ OR_OK - All updates completed ok.
+
+ OR_BADOID - The Oid could not be found
+
+
+--*/
+{
+ ComDebOut((DEB_OXID, "ClientDropOID\nOID = %08x\nMID = %08x\n",
+ Oid,Mid));
+
+ CProtectSharedMemory protector; // locks through rest of lexical scope
+
+#if DBG
+ hProcess->IsValid();
+#endif
+
+ COid * pOid = gpOidTable->Lookup(CId2Key(Oid,Mid));
+
+ if (pOid)
+ {
+ COid *pRemove = hProcess->DropOid(pOid);
+
+ if (pRemove == NULL)
+ {
+
+#if DBG
+ {
+ GUID Moid;
+ MOIDFromOIDAndMID(Oid,Mid,&Moid);
+ ComDebOut((DEB_OXID,"OR: Client process %d tried to remove moid %I which \
+ it didn't own\n", hProcess->GetProcessID(), &Moid));
+ }
+#endif // DBG
+
+ return OR_BADOID;
+ }
+ else
+ {
+ ASSERT(pRemove == pOid);
+ return OR_OK;
+ }
+ }
+ else
+ {
+
+#if DBG
+ {
+ GUID Moid;
+ MOIDFromOIDAndMID(Oid,Mid,&Moid);
+ ComDebOut((DEB_OXID,"OR: Client process %d tried to remove moid %I which \
+ doesn't exist\n", hProcess->GetProcessID(), &Moid));
+ }
+#endif // DBG
+
+ return OR_BADOID;
+ }
+}
+
+
+error_status_t
+ServerAllocateOXID(
+ IN HPROCESS hProcess,
+ IN long fApartment,
+ IN OXID_INFO *pOxidInfo,
+ IN DUALSTRINGARRAY *pdsaStringBindings,
+ OUT OXID &Oxid
+ )
+/*++
+
+Routine Description:
+
+ Allocates an OXID and 0 or more OIDs from the OR.
+
+Arguments:
+
+ hProcess - The context handle of the process containing the OXID.
+
+ fApartment - is the server threading model apartment or free
+
+ OxidInfo - The OXID_INFO structure for the OXID without bindings.
+
+ pdsaStringBindings - Expanded string binding of the server.
+
+ Oxid - The OXID registered and returned.
+
+Return Value:
+
+ OR_OK - success.
+
+ OR_NOMEM - Allocation of OXID failed.
+
+--*/
+{
+ ComDebOut((DEB_OXID, "ServerAllocateOXID\n"));
+
+ ORSTATUS status = OR_OK;
+
+ COxid *pNewOxid;
+
+ // Save the string bindings back to the process
+
+ ASSERT(dsaValid(pdsaStringBindings));
+
+ CProtectSharedMemory protector; // locks through rest of lexical scope
+
+#if DBG
+ hProcess->IsValid();
+#endif
+
+ status = hProcess->ProcessBindings(pdsaStringBindings);
+
+ if (status != OR_OK)
+ {
+ return(status);
+ }
+
+ pNewOxid = new COxid(
+ hProcess,
+ *pOxidInfo,
+ fApartment
+ );
+
+ if (NULL == pNewOxid)
+ {
+ return(OR_NOMEM);
+ }
+
+ Oxid = pNewOxid->GetOXID();
+
+ // Add to process and lookup table.
+
+ status = hProcess->OwnOxid(pNewOxid);
+
+ VALIDATE((status, OR_NOMEM, 0));
+
+ if (OR_OK == status)
+ {
+ status = gpOxidTable->Add(pNewOxid);
+ if (status != OR_OK)
+ {
+ delete pNewOxid;
+ return status;
+ }
+
+ ComDebOut((DEB_OXID, "OXID successfully allocated: %08x\n", Oxid));
+ }
+
+ return(status);
+}
+
+
+error_status_t
+ServerAllocateOID(
+ IN HPROCESS hProcess,
+ IN OXID Oxid,
+ OUT OID &Oid
+ )
+/*++
+
+Routine Description:
+
+ Registers an OID on behalf of an existing OXID.
+
+Arguments:
+
+ hProcess - The context handle of the process containing the OXID and OIDs.
+
+ Oxid - The OXID associated with the OID (assumed local of course).
+
+ Oid - The OID to be allocated and returned.
+
+Return Value:
+
+ OR_OK (0) - Success.
+
+ OR_NOMEM - OXID or one or more OIDs
+
+--*/
+{
+ ComDebOut((DEB_OXID, "ServerAllocateOID, OXID = %08x\n", Oxid));
+
+ CProtectSharedMemory protector; // locks through rest of lexical scope
+
+#if DBG
+ hProcess->IsValid();
+#endif
+
+ COxid *pOxid = gpOxidTable->Lookup(CId2Key(Oxid,gLocalMID));
+
+ ORSTATUS status;
+
+ if (NULL == pOxid)
+ {
+ return(OR_BADOXID);
+ }
+
+ COid *pOid = new COid(pOxid);
+
+ if (NULL == pOid)
+ {
+ return OR_NOMEM;
+ }
+
+ status = pOxid->OwnOid(pOid);
+
+ if (status == OR_OK)
+ {
+ Oid = pOid->GetOID(); // out parameter
+
+ status = gpOidTable->Add(pOid);
+ if (status != OR_OK)
+ {
+ delete pOid;
+ return status;
+ }
+
+ // If the server doesn't want to keep the OID alive,
+ // this OID may rundown in six minutes unless
+ // someone references it in the meantime...
+
+ ComDebOut((DEB_OXID, "OID successfully allocated: %08x at offset = %x\n",
+ Oid,OR_OFFSET(pOid)));
+
+ pOxid->StartRundownThreadIfNecessary();
+
+ return OR_OK;
+ }
+ else
+ {
+ return OR_NOMEM;
+ }
+}
+
+error_status_t
+ServerFreeOXID(
+ IN HPROCESS hProcess,
+ IN OXID Oxid,
+ IN ULONG cOids,
+ IN OID aOids[])
+/*++
+
+Routine Description:
+
+ Delete an OXID registered by the server, and all OIDs belonging to this OXID.
+
+Arguments:
+
+ hProcess - The context handle of the process containing the OXID and OIDs.
+
+ Oxid - The OXID to be deleted (assumed local).
+
+ cOids - The number of OIDs to be deleted.
+
+ aOids - array of OIDs to be deleted.
+
+Return Value:
+
+ OR_OK (0) - Success.
+
+ OR_BADOXID - OXID does not exist.
+
+ OR_NOACCESS - OXID does not belong to this process.
+
+ OR_BADOID - OID does not exist or does not belong to this OXID.
+
+--*/
+{
+ ComDebOut((DEB_OXID, "ServerFreeOXID: %08x MID = %x\n",
+ Oxid,gLocalMID));
+
+ CProtectSharedMemory protector; // locks through rest of lexical scope
+
+#if DBG
+ hProcess->IsValid();
+#endif
+
+ COxid *pOxid = gpOxidTable->Lookup(CId2Key(Oxid,gLocalMID));
+
+ if (NULL != pOxid)
+ {
+#if DBG
+ OXID Oxid = pOxid->GetOXID(); // get this before pOxid potentially disappears
+#endif
+
+ hProcess->DisownOxid(pOxid,TRUE); // this call is on the server's thread
+ // in the apartment case and in the server's
+ // process in both threading cases
+
+ ComDebOut((DEB_OXID, "OXID successfully removed: %08x\n",
+ Oxid));
+
+ return OR_OK;
+ }
+ else
+ {
+ return OR_BADOXID;
+ }
+}
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/mid.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/mid.cxx
new file mode 100644
index 000000000..2a47c20f9
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/mid.cxx
@@ -0,0 +1,398 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Mid.cxx
+
+Abstract:
+
+ Implements the CMid class.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ SatishT 04-13-96 Reworked from MarioGo's code
+
+--*/
+
+#include<or.hxx>
+
+
+//
+// A table for cached resolver handles
+// BUGBUG: Right now, the buckets and links for this are being
+// created in shared memory -- on Chicago, it would be
+// easy to make the allocator a parameter for tables and lists
+//
+
+CResolverHandleTable HandleTable(MID_TABLE_SIZE);
+
+
+//
+// BindingIterator methods
+//
+
+
+COrBindingIterator::COrBindingIterator(
+ CMid *pMid,
+ ORSTATUS& status
+ )
+ : _pMid(pMid),
+ _bIter(pMid->_iStringBinding,pMid->_dsa)
+{
+ if (_pMid->IsLocal())
+ {
+ ASSERT(0); // should never call
+ }
+
+ status = OR_OK;
+ RPC_BINDING_HANDLE hMachine = NULL;
+
+ _pCurrentHandle = HandleTable.Lookup(CIdKey(pMid->GetMID()));
+
+ if (_pCurrentHandle == NULL) // never talked to this OR before
+ {
+ BOOL fSecure = FALSE;
+ PWSTR pwstrT;
+
+ // REVIEW : The OR explictly uses RPC_C_AUTHN_WINNT only for secure pinging.
+
+ pwstrT = &_pMid->_dsa->aStringArray[_pMid->_dsa->wSecurityOffset];
+
+ while(*pwstrT)
+ {
+ if (*pwstrT == RPC_C_AUTHN_WINNT)
+ {
+ fSecure = TRUE;
+ break;
+ }
+ }
+
+ // make a new handle and Add it to the HandleTable
+
+ _pCurrentHandle = new CResolverHandle(pMid->GetMID(),fSecure);
+
+ if (!_pCurrentHandle || HandleTable.Add(_pCurrentHandle) != OR_OK)
+ { // couldn't allocate or couldn't Add
+ delete _pCurrentHandle;
+ _pCurrentHandle = NULL;
+ status = OR_NOMEM;
+ }
+ }
+}
+
+
+
+RPC_BINDING_HANDLE
+COrBindingIterator::Next()
+/*++
+
+Method Description:
+
+ Gets the next possible RPC binding handle to the remote machine.
+ We get here only if First finds no handle in _pCurrentHandle
+ which happens only if
+
+ 1. At the first contact with this OR.
+
+ 2. At subsequent contacts, a current handle failed (some service needed by
+ that protseq may have failed, or we have a network partition).
+ This includes the possibility that we never successfully talk to this OR.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ NULL - resource allocation or connection failure
+
+ non-NULL - A binding to the machine.
+
+--*/
+{
+ _pCurrentHandle->Clear(); // This is either not initialized or has already failed
+
+ PWSTR pwstrT;
+ RPC_BINDING_HANDLE hMachine = NULL;
+
+ while(*(pwstrT = _bIter.Next()))
+ {
+ hMachine = GetBindingToOr(pwstrT); // BUGBUG: need dynamic endpoint fallback?
+
+ if (hMachine)
+ {
+ break;
+ }
+ }
+
+ if (NULL == hMachine) // did we get anything?
+ {
+ _pCurrentHandle->Clear(); // no we did not
+ _pMid->_fBindingWorking = FALSE; // so remember that
+ }
+ else
+ {
+ _pCurrentHandle->Reset(hMachine); // OK we have it, copy it in
+ RpcBindingFree(&hMachine); // this is already copied
+ _pMid->_iStringBinding = _bIter.Index(); // remember the one that worked
+ _pMid->_fBindingWorking = TRUE; // mark this Mid as functional
+ }
+
+ return *_pCurrentHandle;
+}
+
+
+//
+// CMid methods
+//
+
+ORSTATUS
+CMid::ResolveRemoteOxid(
+ IN OXID Oxid,
+ OUT OXID_INFO *poxidInfo
+ )
+{
+ // Remote OXID, call ResolveOxid
+
+ // BUGBUG: Only sending the protseq we're calling OR on,
+ // this should be fixed to send in the whole list if
+ // it includes the protseq we're calling on.
+
+ // BUGBUG: ASSERT that the shared memory lock is held?
+
+#ifndef _REMOTE_OR_
+
+ return OR_BADOXID;
+
+#else
+
+ ORSTATUS status;
+
+ USHORT tmpProtseq;
+ RPC_BINDING_HANDLE hRemoteOr;
+
+ poxidInfo->psa = NULL;
+
+ COrBindingIterator bindIter(this,status);
+
+ if (status != OR_OK) return status;
+
+ for (hRemoteOr = bindIter.First();
+ hRemoteOr != NULL;
+ hRemoteOr = bindIter.Next()
+ )
+ {
+ tmpProtseq = ProtseqOfServer();
+
+ {
+ CTempReleaseSharedMemory temp;
+
+ poxidInfo->dwTid = poxidInfo->dwPid = 0; // marks a remote OXID
+
+ status = ::ResolveOxid(
+ hRemoteOr,
+ &Oxid,
+ 1,
+ &tmpProtseq,
+ &poxidInfo->psa,
+ &poxidInfo->ipidRemUnknown,
+ &poxidInfo->dwAuthnHint
+ );
+ }
+
+ if ((status == OR_OK) || (status == OR_BADOXID))
+ {
+ break;
+ }
+ }
+
+ if (status == OR_OK)
+ {
+ ASSERT(poxidInfo->psa && "Remote resolve succeeded but no bindings returned");
+ }
+
+ return status;
+
+#endif// _REMOTE_OR_
+
+}
+
+
+
+ORSTATUS
+CMid::PingServer()
+{
+
+ // BUGBUG: ASSERT that the shared memory lock is held?
+
+#ifndef _REMOTE_OR_
+
+ return OR_NOSERVER;
+
+#else // _REMOTE_OR_
+
+ if (_addOidList.IsEmpty() && _dropOidList.IsEmpty() && _pingSet.IsEmpty())
+ {
+ return OR_OK; // nothing to do
+ }
+
+ ORSTATUS status;
+ RPC_BINDING_HANDLE hRemoteOr;
+
+ COrBindingIterator bindIter(this,status);
+
+ if (status != OR_OK) return status;
+
+ if (!_addOidList.IsEmpty() || !_dropOidList.IsEmpty())
+ {
+ // need complex ping
+
+ USHORT cAddToSet = _addOidList.Size();
+ USHORT cDelFromSet = _dropOidList.Size();
+ COidList addOidListSent, dropOidListSent;
+
+ OID *aAddToSet = NULL;
+ OID *aDelFromSet = NULL;
+
+ if (cAddToSet > 0)
+ {
+ aAddToSet = new OID[cAddToSet];
+ if (aAddToSet == NULL)
+ {
+ return OR_NOMEM;
+ }
+
+ COidListIterator AddIter;
+ AddIter.Init(_addOidList);
+ USHORT i = 0;
+
+ for (COid *pOid = AddIter.Next(); pOid != NULL; pOid = AddIter.Next())
+ {
+ aAddToSet[i++] = pOid->GetOID();
+ }
+ }
+
+ if (cDelFromSet > 0)
+ {
+ aDelFromSet = new OID[cDelFromSet];
+ if (aDelFromSet == NULL)
+ {
+ delete aAddToSet;
+ return OR_NOMEM;
+ }
+
+ COidListIterator DropIter;
+ DropIter.Init(_dropOidList);
+ USHORT i = 0;
+
+ for (COid *pOid = DropIter.Next(); pOid != NULL; pOid = DropIter.Next())
+ {
+ aDelFromSet[i++] = pOid->GetOID();
+ }
+ }
+
+ {
+ // Transfer the current _addOidList and _dropOidList and set them to
+ // empty since we are releasing the shared memory lock.
+
+ _addOidList.Transfer(addOidListSent);
+ _dropOidList.Transfer(dropOidListSent);
+
+ // We will have to deal with failure scenarios appropriately.
+
+ // Now release the lock and ping.
+
+ // CTempReleaseSharedMemory temp;
+
+ for (hRemoteOr = bindIter.First();
+ hRemoteOr != NULL;
+ hRemoteOr = bindIter.Next()
+ )
+ {
+ status = ::ComplexPing(
+ hRemoteOr,
+ &_setID,
+ _sequenceNum++,
+ cAddToSet,
+ cDelFromSet,
+ aAddToSet,
+ aDelFromSet,
+ &_pingBackoffFactor
+ );
+
+ if (status == OR_OK || status == OR_BADSET || status == OR_BADOID)
+ {
+ break;
+ }
+ }
+ }
+
+ COidListIterator AddIter;
+ AddIter.Init(addOidListSent);
+
+ for (COid *pOid = AddIter.Next(); pOid != NULL; pOid = AddIter.Next())
+ {
+ status = _pingSet.Add(pOid);
+ if (status != OR_OK) break;
+ }
+
+ delete aAddToSet;
+ delete aDelFromSet;
+ dropOidListSent.Clear();
+
+ if (_pingSet.IsEmpty())
+ {
+ _setID = 0; // server OR will delete the set
+ }
+
+
+ // BUGBUG: several contingencies have not been handled
+ // some of these apply to simple ping as well
+ //
+ // 1. OR_BADSET, OR_BADOID, OR_NOMEM
+ // 2. RPC_S_UNKNOWN_IF (dynamic endpoints)
+ // 3. General RPC failure (binding failure)
+ // 4. RPC blocked forever -- how to detect and correct
+ // the hang, and what to do with this Mid subsequently
+ // 5. Someone wants to modify the _addOidList/_dropOidList
+ // while we are waiting for the RPC to complete
+
+ // Note that _pingSet.IsEmpty() <=> _setID == 0
+ // This must be ensured by code that deals with failures.
+ }
+
+ else if (_setID != 0)
+ {
+ // need simple ping
+ {
+ CTempReleaseSharedMemory temp;
+
+ for (hRemoteOr = bindIter.First();
+ hRemoteOr != NULL;
+ hRemoteOr = bindIter.Next()
+ )
+ {
+ status = ::SimplePing(
+ hRemoteOr,
+ &_setID
+ );
+
+ if (status == OR_OK || status == OR_BADSET || status == OR_BADOID)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ return status;
+
+#endif // _REMOTE_OR_
+
+}
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/mid.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/mid.hxx
new file mode 100644
index 000000000..b16526e98
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/mid.hxx
@@ -0,0 +1,331 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Mid.hxx
+
+Abstract:
+
+ Class representing string bindings and security bindings for a particular
+ machine. Provides a mapping between the bindings and a local machine
+ unique ID for that machine.
+
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 12-13-95 Bits 'n pieces
+
+--*/
+
+#ifndef __MID_HXX
+#define __MID_HXX
+
+class CResolverHandle : public CTableElement
+{
+public:
+
+ CResolverHandle(MID id, BOOL fSecure)
+ {
+ _Key.Init(id);
+ _hOR = NULL;
+ _fSecure = fSecure;
+ }
+
+ ~CResolverHandle()
+ {
+ Clear();
+ }
+
+ void Clear()
+ {
+ if (_hOR != NULL)
+ {
+ RpcBindingFree(&_hOR);
+ _hOR = NULL;
+ }
+ }
+
+ ORSTATUS Reset(RPC_BINDING_HANDLE hIn)
+ {
+ ASSERT(hIn != NULL);
+ Clear();
+
+ if (_fSecure)
+ {
+ RPC_STATUS status = RpcBindingSetAuthInfo(hIn,
+ 0,
+ RPC_C_AUTHN_LEVEL_CONNECT,
+ RPC_C_AUTHN_WINNT,
+ 0,
+ 0);
+
+ if (status != RPC_S_OK)
+ {
+ ComDebOut((DEB_OXID,"OR: RpcBindingSetAuthInfo failed for OR handle with %d\n",
+ status));
+
+ // Just fall back on unsecure.
+ }
+ }
+
+ return RpcBindingCopy(hIn,&_hOR);
+ }
+
+ virtual operator ISearchKey&()
+ {
+ return _Key;
+ }
+
+ operator RPC_BINDING_HANDLE&()
+ {
+ return _hOR;
+ }
+
+private:
+
+ CIdKey _Key;
+ RPC_BINDING_HANDLE _hOR;
+ BOOL _fSecure;
+};
+
+
+
+DEFINE_TABLE(CResolverHandle)
+
+typedef CDSA CMidKey;
+
+class CMid : public CTableElement
+/*++
+
+Class Description:
+
+ Represents the local and remote machines. Each unique (different)
+ set of string bindings and security bindings are assigned a unique
+ local ID. This ID is used along with the OID and OXID of the remote
+ machine objects index these objects locally. Instances of this class
+ are referenced by COids.
+
+ This class is indexed by string and security bindings. There is no
+ index by MID.
+
+Members:
+
+ _id - The locally unique ID of this set of bindings.
+
+ _iStringBinding - Index into _dsa->aStringArray of the
+ compressed string binding used to create a handle.
+
+ _iSecurityBinding - Index into _dsaSecurityArray of the
+
+ _dsa - The set of compressed bindings.
+
+--*/
+{
+
+public:
+
+ CMid(
+ DUALSTRINGARRAY *pdsa,
+ ORSTATUS& status,
+ USHORT wProtSeq // if the SCM tells us what to use
+ ) :
+ _id(AllocateId()),
+ _iStringBinding(0),
+ _iSecurityBinding(0),
+ _fBindingWorking(FALSE),
+ _dsa(pdsa,TRUE,status),
+ _setID(0)
+ {
+ if (wProtSeq > 0)
+ {
+ PWSTR pwstr = FindMatchingProtseq(wProtSeq,pdsa->aStringArray);
+
+ if (NULL != pwstr)
+ {
+ _iStringBinding = pwstr - pdsa->aStringArray;
+ }
+ }
+ }
+
+ ~CMid()
+ {
+ if (gpMidTable != NULL) // this might happen during initialization
+ { // of globals, e.g., gpLocalMid
+ gpMidTable->Remove(*this);
+ }
+ }
+
+ void * operator new(size_t s)
+ {
+ return OrMemAlloc(s);
+ }
+
+ void * operator new(size_t s, size_t extra)
+ {
+ return OrMemAlloc(s+extra);
+ }
+
+ void operator delete(void * p) // do not inherit this!
+ {
+ OrMemFree(p);
+ }
+
+ operator ISearchKey&() // allows us to be a ISearchKey
+ {
+ return _dsa;
+ }
+
+ virtual BOOL
+ Compare(ISearchKey &tk)
+ {
+ return(_dsa.Compare(tk));
+ }
+
+
+ DUALSTRINGARRAY *
+ GetStrings()
+ {
+ return(_dsa);
+ }
+
+ USHORT ProtseqOfServer()
+ {
+ if (_fBindingWorking)
+ {
+ return(_dsa->aStringArray[_iStringBinding]);
+ }
+ else
+ {
+ return(0);
+ }
+ }
+
+ BOOL IsLocal()
+ {
+ return (_id == gLocalMID);
+ }
+
+ MID GetMID()
+ {
+ return(_id);
+ }
+
+ ORSTATUS PingServer();
+
+ ORSTATUS AddClientOid(COid *pOid)
+ {
+ ORSTATUS status = OR_OK;
+
+ // this way, we have the same number of refs on the Oid
+ // as we would if we were already pinging it. The ref is
+ // held by the _addOidList instead of the _pingSet
+
+ if (_pingSet.Lookup(*pOid) == NULL)
+ {
+ _addOidList.Insert(status,pOid);
+ }
+
+ return status;
+ }
+
+ ORSTATUS DropClientOid(COid *pOid)
+ {
+ ORSTATUS status = OR_OK;
+ COid *pt;
+
+ // this way, we have the same number of refs on the Oid
+ // as we would if we were already pinging it. The ref is
+ // held by the _addOidList instead of the _pingSet
+
+ if ((pt = _pingSet.Remove(*pOid)) == pOid)
+ {
+ _dropOidList.Insert(status,pOid);
+ }
+ else if (pt == NULL)
+ {
+ ComDebOut((DEB_OXID,"Trying to stop pinging OID not belonging to MID=%08x",_id));
+ ASSERT(0);
+ }
+ else
+ {
+ ComDebOut((DEB_OXID,"Trying to stop pinging bogus COid object at MID=%08x",_id));
+ ASSERT(0);
+ }
+
+ return status;
+ }
+
+ ORSTATUS ResolveRemoteOxid(
+ OXID Oxid,
+ OXID_INFO *poxidInfo
+ );
+
+#if DBG
+ PWSTR PrintableName()
+ {
+ return(&_dsa->aStringArray[_iStringBinding + 1]);
+ }
+#endif
+
+private:
+
+ friend class COrBindingIterator;
+
+ ID _id;
+ USHORT _iStringBinding;
+ USHORT _iSecurityBinding;
+ CDSA _dsa;
+ BOOL _fBindingWorking;
+
+ COidTable _pingSet;
+ COidList _addOidList;
+ COidList _dropOidList;
+ ID _setID;
+ USHORT _sequenceNum;
+ USHORT _pingBackoffFactor;
+
+};
+
+DEFINE_TABLE(CMid)
+
+
+class COrBindingIterator
+{
+public:
+
+ COrBindingIterator(
+ CMid *pMid,
+ ORSTATUS &status
+ );
+
+ RPC_BINDING_HANDLE First()
+ {
+ RPC_BINDING_HANDLE hMachine = *_pCurrentHandle; // auto conversion
+
+ if (hMachine != NULL)
+ {
+ return hMachine; // Already have one, so try it
+ }
+ else
+ {
+ return Next();
+ }
+ }
+
+ RPC_BINDING_HANDLE Next();
+
+private:
+
+ CMid *_pMid;
+ CBindingIterator _bIter;
+ CResolverHandle *_pCurrentHandle;
+};
+
+#endif // __MID_HXX
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/misc.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/misc.cxx
new file mode 100644
index 000000000..3e176f4bf
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/misc.cxx
@@ -0,0 +1,189 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Misc.cxx
+
+Abstract:
+
+ Initalization, Heap, debug, thread manager for OR
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-11-95 Bits 'n pieces
+
+--*/
+
+#include <or.hxx>
+
+//
+//
+//
+
+WCHAR*
+catenate(
+ WCHAR* pszPrefix,
+ WCHAR* pszSuffix
+ )
+/*++
+
+Routine Description:
+
+ Concatenate the two given strings into a new string
+
+Arguments:
+
+ pszPrefix - prefix of result
+
+ pszSuffix - suffix of result
+
+Returns:
+
+ A newly allocated string.
+
+--*/
+{
+ long prefixLen = wcslen(pszPrefix);
+ long suffixLen = wcslen(pszSuffix);
+
+ WCHAR* pszResult = new WCHAR[(prefixLen+suffixLen+1)*sizeof(WCHAR)];
+ wcscpy(pszResult,pszPrefix);
+ wcscpy(pszResult+prefixLen,pszSuffix);
+ return pszResult;
+}
+
+
+//
+// Local ID allocation
+//
+
+
+ID
+AllocateId(
+ IN LONG cRange
+ )
+/*++
+
+Routine Description:
+
+ Allocates a unique local ID.
+
+ This id is 64bits. The low 32 bits are a sequence number which
+ is incremented with each call. The high 32bits are seconds
+ since 1980. The ID of 0 is not used.
+
+Limitations:
+
+ No more then 2^64 IDs can be generated in a given second without
+ a duplicate. After 2^32 there becomes a much higher change of
+ overflow.
+
+ When the time stamp overflows, once every >126 years, the sequence
+ numbers are likely to be generated in such a way as to collide
+ with those from 126 years ago.
+
+ There is no prevision in the code to deal with duplications.
+
+Arguments:
+
+ cRange - Number to allocate in sequence, default is 1.
+
+Return Value:
+
+ A 64bit id.
+
+Note: This must be called under shared memory lock!
+
+--*/
+{
+ FILETIME ft;
+ LARGE_INTEGER id;
+
+ ASSERT(cRange > 0 && cRange < 11);
+
+ do
+ {
+ id.HighPart = GetTickCount();
+ id.LowPart = *gpIdSequence;
+ *gpIdSequence += cRange;
+ }
+ while (id.QuadPart == 0 );
+
+ return(id.QuadPart);
+}
+
+//
+// Debug helper(s)
+//
+
+#if DBG
+
+int __cdecl __RPC_FAR ValidateError(
+ IN ORSTATUS Status,
+ IN ...)
+/*++
+Routine Description
+
+ Tests that 'Status' is one of an expected set of error codes.
+ Used on debug builds as part of the VALIDATE() macro.
+
+Example:
+
+ VALIDATE( (Status,
+ OR_BADSET,
+ // more error codes here
+ OR_OK,
+ 0) // list must be terminated with 0
+ );
+
+ This function is called with the OrStatus and expected errors codes
+ as parameters. If OrStatus is not one of the expected error
+ codes and it not zero a message will be printed to the debugger
+ and the function will return false. The VALIDATE macro ASSERT's the
+ return value.
+
+Arguments:
+
+ Status - Status code in question.
+
+ ... - One or more expected status codes. Terminated with 0 (OR_OK).
+
+Return Value:
+
+ TRUE - Status code is in the list or the status is 0.
+
+ FALSE - Status code is not in the list.
+
+--*/
+{
+ RPC_STATUS CurrentStatus;
+ va_list(Marker);
+
+ if (Status == 0) return(TRUE);
+
+ va_start(Marker, Status);
+
+ while(CurrentStatus = va_arg(Marker, RPC_STATUS))
+ {
+ if (CurrentStatus == Status)
+ {
+ return(TRUE);
+ }
+ }
+
+ va_end(Marker);
+
+ OrDbgPrint(("OR Assertion: unexpected failure %lu (0lx%08x)\n",
+ (unsigned long)Status, (unsigned long)Status));
+
+ return(FALSE);
+}
+
+#endif
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/misc.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/misc.hxx
new file mode 100644
index 000000000..a56598d66
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/misc.hxx
@@ -0,0 +1,120 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Misc.hxx
+
+Abstract:
+
+ Header for random helpers functions.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-11-95 Bits 'n pieces
+
+--*/
+
+#ifndef __MISC_HXX
+#define __MISC_HXX
+
+extern ID AllocateId(LONG cRange = 1);
+
+#ifndef _CHICAGO_
+
+inline
+void * _CRTAPI1
+operator new (
+ IN size_t size
+ )
+{
+ return PrivMemAlloc(size);
+}
+
+inline
+void _CRTAPI1
+operator delete (
+ IN void * obj
+ )
+{
+ PrivMemFree(obj);
+}
+
+#endif _CHICAGO_
+
+enum AllocType
+{
+ InSharedHeap,
+ InProcessHeap
+};
+
+
+// REVIEW: Do we want separate Object and Set heaps to avoid page faults?
+// probably not worthwhile for Chicago
+//
+
+
+inline
+void * _CRTAPI1
+operator new (
+ IN size_t size,
+ IN size_t extra
+ )
+{
+ return(PrivMemAlloc(size + extra));
+}
+
+inline
+void * _CRTAPI1
+operator new (
+ IN size_t size,
+ AllocType type
+ )
+{
+ if (type == InSharedHeap) return OrMemAlloc(size);
+ else return PrivMemAlloc(size);
+}
+
+inline void
+Raise(unsigned long ErrorCode) {
+ RaiseException(
+ ErrorCode,
+ EXCEPTION_NONCONTINUABLE,
+ 0,
+ NULL
+ );
+}
+
+template <class TYPE>
+TYPE * CopyArray(
+ IN DWORD size,
+ IN TYPE *pArr,
+ ORSTATUS *pStatus
+ )
+{
+ TYPE *pNew = new TYPE[size];
+ if (!pNew)
+ {
+ *pStatus = OR_NOMEM;
+ return NULL;
+ }
+ else
+ {
+ *pStatus = OR_OK;
+ }
+
+ for (DWORD i = 0; i < size; i++)
+ {
+ pNew[i] = pArr[i];
+ }
+
+ return pNew;
+}
+
+#endif // __MISC_HXX
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/mutex.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/mutex.cxx
new file mode 100644
index 000000000..a371b59c0
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/mutex.cxx
@@ -0,0 +1,104 @@
+/*++
+
+Microsoft Windows NT RPC Name Service
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ mutex.cxx
+
+Abstract:
+
+ This file contains the implementations for non inline member functions of
+ CReadWriteSection and CGlobalMutex, which implement a readers/writers
+ mutex and a multi-owner mutex, respectively.
+
+Author:
+
+ Satish Thatte (SatishT) 09/01/95 Created all the code below except where
+ otherwise indicated.
+
+--*/
+
+#define NULL 0
+
+extern "C" {
+#include <windows.h>
+}
+
+#include <mutex.hxx>
+
+
+CGlobalMutex::CGlobalMutex(
+ long lMaxCount
+ )
+/*++
+
+Routine Description:
+
+ create a semaphore and initialize the handle member pNTSem.
+
+--*/
+{
+ hGlobalMutex = CreateMutex(
+ NULL, // LPSECURITY_ATTRIBUTES lpsa
+ FALSE, // BOOL fInitialOwner
+ GLOBAL_CS // LPCTSTR lpszMutexName
+ );
+
+ //
+ // If the mutex create/open failed, then bail
+ //
+
+ if ( !hGlobalMutex )
+ {
+ return LAST_SCODE;
+ }
+
+ if ( GetLastError() == ERROR_ALREADY_EXISTS )
+ {
+ }
+}
+
+
+
+CGlobalMutex::~CGlobalMutex()
+/*++
+
+Routine Description:
+
+ close the semaphore handle.
+
+--*/
+{
+ CloseHandle(pNTSem);
+}
+
+
+void
+CGlobalMutex::Enter()
+/*++
+
+Routine Description:
+
+ Wait for the semaphore count to become nonzero.
+
+--*/
+{
+ WaitForSingleObject(pNTSem,INFINITE);
+}
+
+
+void
+CGlobalMutex::Leave(long lIncrement)
+/*++
+
+Routine Description:
+
+ Increment the semaphore count by lIncrement to release lIncrement "slots".
+
+--*/
+{
+ ReleaseSemaphore(pNTSem,lIncrement,NULL);
+}
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/mutex.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/mutex.hxx
new file mode 100644
index 000000000..90bff5821
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/mutex.hxx
@@ -0,0 +1,239 @@
+/*++
+
+Microsoft Windows NT RPC Name Service
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ mutex.hxx
+
+Abstract:
+
+ This file contains definitions of classes which provide mutual exclusion.
+ At the moment, only an InterlockedInteger and a simple (interprocess)
+ Mutex are defined, but in future, a readers/writers version may be added.
+
+Author:
+
+ Satish Thatte (SatishT) 02/22/96 Created all the code below except where
+ otherwise indicated.
+
+--*/
+
+#ifndef __MUTEX_HXX__
+#define __MUTEX_HXX__
+
+class CInterlockedInteger // created by MarioGo
+ {
+ private:
+ LONG i;
+
+ public:
+
+ CInterlockedInteger(LONG i = 0) : i(i) {}
+
+ LONG operator++(int)
+ {
+ return(InterlockedIncrement(&i));
+ }
+
+ LONG operator--(int)
+ {
+ return(InterlockedDecrement(&i));
+ }
+
+ operator LONG()
+ {
+ return(i);
+ }
+ };
+
+
+
+/*++
+
+Class Definition:
+
+ CGlobalMutex
+
+Abstract:
+
+ This class implements an inter process mutex which controls
+ access to resources and data in shared memory.
+
+--*/
+
+class CGlobalMutex {
+
+ HANDLE _hMutex; // Reference to system mutex object
+ // we are impersonating
+
+
+public:
+
+ CGlobalMutex(ORSTATUS &status);
+
+ ~CGlobalMutex();
+
+ void Enter() ;
+
+ void Leave();
+};
+
+
+
+
+
+/*++
+
+Class Definition:
+
+ CProtectSharedMemory
+
+Abstract:
+
+ A convenient way to acquire and release a lock on a CGlobalMutex.
+ Entry occurs on creation and exit on destruction of this object, and hence
+ can be made to coincide with a local scope. Especially convenient when
+ there are multiple exit points from the scope (returns, breaks, etc.).
+
+
+--*/
+
+extern CGlobalMutex *gpMutex; // global mutex to protect shared memory
+
+class CProtectSharedMemory {
+
+public:
+
+ CProtectSharedMemory() {
+ gpMutex->Enter();
+ }
+
+ ~CProtectSharedMemory() {
+ gpMutex->Leave();
+ }
+};
+
+
+
+class CTempReleaseSharedMemory {
+
+public:
+
+ CTempReleaseSharedMemory() {
+ gpMutex->Leave();
+ }
+
+ ~CTempReleaseSharedMemory() {
+ gpMutex->Enter();
+ }
+};
+
+
+
+/******** inline methods ********/
+
+
+inline
+CGlobalMutex::CGlobalMutex(ORSTATUS &status)
+/*++
+
+Routine Description:
+
+ create a mutex and initialize the handle member _hMutex.
+
+--*/
+{
+ SECURITY_DESCRIPTOR sd;
+ if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
+ {
+ status = GetLastError();
+ ComDebOut((DEB_OXID,"InitializeSecurityDescriptor Failed with %d\n",status));
+ return;
+ }
+
+ if (! SetSecurityDescriptorDacl(
+ &sd, // address of security descriptor
+ TRUE, // flag for presence of discretionary ACL
+ NULL, // address of discretionary ACL
+ FALSE // flag for default discretionary ACL
+ )
+ )
+ {
+ status = GetLastError();
+ ComDebOut((DEB_OXID,"SetSecurityDescriptorDacl Failed with %d\n",status));
+ return;
+ }
+
+ SECURITY_ATTRIBUTES sa;
+
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.lpSecurityDescriptor = &sd;
+ sa.bInheritHandle = FALSE;
+
+ _hMutex = CreateMutex(
+ &sa, // LPSECURITY_ATTRIBUTES lpsa
+ FALSE, // BOOL fInitialOwner
+ GLOBAL_MUTEX_NAME // LPCTSTR lpszMutexName
+ );
+
+ //
+ // Did the mutex create/open fail?
+ //
+
+ if ( !_hMutex )
+ {
+ status = GetLastError();
+ ComDebOut((DEB_OXID,"Global Mutex Creation Failed with %d\n",status));
+ }
+ else
+ {
+ status = OR_OK;
+ }
+}
+
+
+inline
+CGlobalMutex::~CGlobalMutex()
+/*++
+
+Routine Description:
+
+ close the mutex handle.
+
+--*/
+{
+ CloseHandle(_hMutex);
+}
+
+
+inline void
+CGlobalMutex::Enter()
+/*++
+
+Routine Description:
+
+ Wait for the mutex to be signalled.
+
+--*/
+{
+ WaitForSingleObject(_hMutex,INFINITE);
+}
+
+
+inline void
+CGlobalMutex::Leave()
+/*++
+
+Routine Description:
+
+ Signal the mutex
+
+--*/
+{
+ ReleaseMutex(_hMutex);
+}
+
+
+#endif // __MUTEX_HXX__
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/objex.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/objex.cxx
new file mode 100644
index 000000000..2bfcda32d
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/objex.cxx
@@ -0,0 +1,402 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ObjEx.cxx
+
+Abstract:
+
+ Main entry point for the object exporter service.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-28-95 Bits 'n pieces
+
+--*/
+
+
+#include <or.hxx>
+
+#ifndef _CHICAGO_
+
+DECLARE_INFOLEVEL(Cairole) // BUGBUG: strictly for private memory stuff from storage
+ // elide ASAP
+#endif // _CHICAGO_
+
+#if DBG
+#include <fstream.h>
+#endif
+
+extern "C"
+{
+#define SECURITY_WIN32 // Used by sspi.h
+#include <sspi.h> // EnumerateSecurityPackages
+}
+
+//
+// Process globals - read-only except during init.
+//
+
+// MID of the string bindings for this machine -- the bindings are phoney
+// for this shared memory version of the resolver.
+
+DUALSTRINGARRAY *gpLocalDSA;
+MID gLocalMID;
+CMid *gpLocalMid;
+CProcess *gpProcess; // pointer to our process object
+CProcess *gpPingProcess; // pointer to pinging process
+//
+// Process globals - read-write
+//
+
+void * pSharedBase;
+CSharedGlobals *GlobalBlock;
+
+#ifndef _CHICAGO_
+CSmAllocator gsmDCOMAllocator;
+#endif // _CHICAGO_
+
+COxidTable * gpOxidTable;
+COidTable * gpOidTable;
+CMidTable * gpMidTable;
+CProcessTable * gpProcessTable;
+
+USHORT *gpcRemoteProtseqs; // count of remote protseqs
+USHORT *gpRemoteProtseqIds; // array of remote protseq ids
+PWSTR gpwstrProtseqs; // remote protseqs strings catenated
+DUALSTRINGARRAY *gpdsaMyBindings; // DUALSTRINGARRAY of local OR's bindings
+
+LONG * gpIdSequence;
+
+FILETIME MyCreationTime;
+DWORD MyProcessId;
+
+DWORD *gpdwLastCrashedProcessCheckTime;
+DWORD *gpNextThreadID;
+
+CGlobalMutex *gpMutex; // global mutex to protect shared memory
+
+BOOL DCOM_Started = FALSE;
+ID ProcessMarker; // sanity checking marker for the process object
+
+CResolverHashTable *gpClientSetTable = 0;
+
+//+-------------------------------------------------------------------------
+//
+// Function: ComputeSecurity
+//
+// Synopsis: Looks up some registry keys and enumerates the security
+// packages on this machine.
+//
+//--------------------------------------------------------------------------
+// These variables hold values read out of the registry and cached.
+// s_fEnableDCOM is false if DCOM is disabled. The others contain
+// authentication information for legacy applications.
+BOOL s_fEnableDCOM;
+DWORD s_lAuthnLevel;
+DWORD s_lImpLevel;
+BOOL s_fMutualAuth;
+BOOL s_fSecureRefs;
+
+// s_sServerSvc is a list of security providers that OLE servers can use.
+// s_aClientSvc is a list of security providers that OLE clients can use.
+// The difference is that Chicago only supports the client side of some
+// security providers and OLE servers must know how to determine the
+// principal name for the provider. Clients get the principal name from
+// the server.
+DWORD s_cServerSvc = 0;
+USHORT *s_aServerSvc = NULL;
+DWORD s_cClientSvc = 0;
+USHORT *s_aClientSvc = NULL;
+BOOL fSecurityComputed = FALSE;
+
+void ComputeSecurity()
+{
+ SecPkgInfo *pAllPkg;
+ SecPkgInfo *pNext;
+ HRESULT hr;
+ DWORD i;
+ DWORD lMaxLen;
+ HKEY hKey;
+ DWORD lType;
+ DWORD lData;
+ DWORD lDataSize;
+
+ if (fSecurityComputed) return;
+
+ fSecurityComputed = TRUE;
+
+ // Get the list of security packages.
+ hr = EnumerateSecurityPackages( &lMaxLen, &pAllPkg );
+ if (hr == 0)
+ {
+ // Allocate memory for both service lists.
+ s_aServerSvc = new USHORT[lMaxLen];
+ s_aClientSvc = new USHORT[lMaxLen];
+ if (s_aServerSvc == NULL || s_aClientSvc == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ delete s_aServerSvc;
+ delete s_aClientSvc;
+ s_aServerSvc = NULL;
+ s_aClientSvc = NULL;
+ }
+ else
+ {
+ // Check all packages.
+ ASSERT((s_cClientSvc == 0) && (s_cServerSvc == 0));
+ pNext = pAllPkg;
+ for (i = 0; i < lMaxLen; i++)
+ {
+ // Determine if clients can use the package.
+ if ((pNext->fCapabilities & (SECPKG_FLAG_DATAGRAM |
+ SECPKG_FLAG_CONNECTION)))
+ {
+ s_aClientSvc[s_cClientSvc++] = pNext->wRPCID;
+ }
+
+ // BUGBUG - Add flag for NT principal names
+ // Determine is servers can use the package.
+ if ( (pNext->fCapabilities & (SECPKG_FLAG_DATAGRAM |
+ SECPKG_FLAG_CONNECTION)) &&
+ ~(pNext->fCapabilities & (SECPKG_FLAG_CLIENT_ONLY)))
+ {
+ s_aServerSvc[s_cServerSvc++] = pNext->wRPCID;
+ }
+ pNext++;
+ }
+ }
+
+ // Release the list of security packages.
+ FreeContextBuffer( pAllPkg );
+ }
+
+ // Set all the security flags to their default values.
+#ifdef _CAIRO_
+ s_fEnableDCOM = TRUE;
+#else
+ s_fEnableDCOM = FALSE;
+#endif
+ s_lAuthnLevel = RPC_C_AUTHN_LEVEL_NONE; // BUGBUG: temp workaround
+ s_lImpLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
+ s_fMutualAuth = FALSE;
+ s_fSecureRefs = FALSE;
+
+ // Open the security key.
+ hr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\OLE",
+ NULL, KEY_QUERY_VALUE, &hKey );
+ if (hr != ERROR_SUCCESS)
+ return;
+
+ // Query the value for DisableDCOM.
+ lDataSize = sizeof(lData );
+ hr = RegQueryValueEx( hKey, L"EnableDCOM", NULL, &lType,
+ (unsigned char *) &lData, &lDataSize );
+ if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0)
+ {
+ if (*((WCHAR *) &lData) == L'y' ||
+ *((WCHAR *) &lData) == L'Y')
+ s_fEnableDCOM = TRUE;
+ }
+
+ // Query the value for the authentication level.
+ lDataSize = sizeof(lData );
+ hr = RegQueryValueEx( hKey, L"LegacyAuthenticationLevel", NULL,
+ &lType, (unsigned char *) &lData, &lDataSize );
+ if (hr == ERROR_SUCCESS && lType == REG_DWORD)
+ {
+ s_lAuthnLevel = lData;
+ }
+
+ // Query the value for the impersonation level.
+ lDataSize = sizeof(lData );
+ hr = RegQueryValueEx( hKey, L"LegacyImpersonationLevel", NULL,
+ &lType, (unsigned char *) &lData, &lDataSize );
+ if (hr == ERROR_SUCCESS && lType == REG_DWORD)
+ {
+ s_lImpLevel = lData;
+ }
+
+ // Query the value for mutual authentication.
+ lDataSize = sizeof(lData );
+ hr = RegQueryValueEx( hKey, L"LegacyMutualAuthentication", NULL,
+ &lType, (unsigned char *) &lData, &lDataSize );
+ if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0)
+ {
+ if (*((WCHAR *) &lData) == L'y' ||
+ *((WCHAR *) &lData) == L'Y')
+ s_fMutualAuth = TRUE;
+ }
+
+ // Query the value for secure interface references.
+ lDataSize = sizeof(lData );
+ hr = RegQueryValueEx( hKey, L"LegacySecureReferences", NULL,
+ &lType, (unsigned char *) &lData, &lDataSize );
+ if (hr == ERROR_SUCCESS && lType == REG_SZ && lDataSize != 0)
+ {
+ if (*((WCHAR *) &lData) == L'y' ||
+ *((WCHAR *) &lData) == L'Y')
+ s_fSecureRefs = TRUE;
+ }
+
+ // Close the registry key.
+ RegCloseKey( hKey );
+}
+
+
+//
+// Startup
+//
+
+//+-------------------------------------------------------------------------
+//
+// Function: InitDCOMSharedAllocator
+//
+// Synopsis: Initialises a shared memory region for this process for DCOM use.
+//
+// Returns: status code
+//
+// History: 20-Nov-95 HenryLee Created (SatishT modifiied)
+//
+// Notes: This routine is called indirectly by DfCreateSharedAllocator
+// such a way that in most circumstances it will be executed
+// exactly once per docfile open.
+//
+//--------------------------------------------------------------------------
+
+HRESULT InitDCOMSharedAllocator(ULONG DCOMSharedHeapName, void * &pSharedBase)
+{
+ HRESULT hr = S_OK;
+
+ CSmAllocator *pMalloc = &gSharedAllocator;
+
+ if (pSharedBase == NULL) // allocate a new heap
+ {
+#ifdef MULTIHEAP
+ // reset the allocator state to initialize it properly
+ pMalloc->SetState (NULL, NULL, NULL, NULL, 0);
+#endif // MULTIHEAP
+
+ hr = pMalloc->Init (
+#ifdef MULTIHEAP
+ DCOMSharedHeapName, FALSE
+#else
+ L"DCOMResolverSharedHeap"
+#endif // MULTIHEAP
+ );
+ if ( SUCCEEDED(hr) )
+ {
+ pMalloc->AddRef();
+ pSharedBase = pMalloc->GetBase();
+ pMalloc->Alloc(8); // avoid using NULL value for based pointer
+ }
+ }
+
+ return hr;
+}
+
+static CONST PWSTR gpwstrProtocolsPath = L"Software\\Microsoft\\Rpc";
+static CONST PWSTR gpwstrProtocolsValue = L"DCOM Protocols";
+HRESULT MallocInitialize(BOOL fForceLocalAlloc);
+
+ORSTATUS StartDCOM(
+ void
+ )
+/*++
+
+Routine Description:
+
+ Primes the distributed object mechanisms, in particular by initializing
+ shared memory access and structures.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ ORSTATUS status = OR_OK;
+
+ if (DCOM_Started)
+ {
+ return OR_REPEAT_START;
+ }
+
+ // initialize process identity variables
+ MyProcessId = GetCurrentProcessId();
+
+ // create or find the global mutex
+ gpMutex = new CGlobalMutex(status);
+
+ Win4Assert((status == OR_OK) && "CSharedGlobals create global mutex failed");
+
+ {
+ CProtectSharedMemory protector; // locks throughout lexical scope
+
+ // Lookup security data.
+ ComputeSecurity();
+
+#if DBG // read names from sm.ini to avoid reboot
+#ifndef _CHICAGO_
+
+ ULONG DCOMSharedHeapName = GetProfileInt(
+ TEXT("DCOM95 Test"), // section name
+ TEXT("SharedHeapName"), // key name
+ 1111 // default name
+ );
+
+ WCHAR SharedGlobalBlockName[10];
+ swprintf(SharedGlobalBlockName,TEXT("DCOMB%d"),DCOMSharedHeapName);
+#else
+ WCHAR *SharedGlobalBlockName = DCOMSharedGlobalBlockName;
+#endif // _CHICAGO_
+#endif // DBG
+
+ // Allocate tables, but only if we are in first
+
+ ComDebOut((DEB_ITRACE,"DCOMSharedHeapName = %d\n", DCOMSharedHeapName));
+ ComDebOut((DEB_ITRACE,"SharedGlobalBlockName = %ws\n", SharedGlobalBlockName));
+
+ InitDCOMSharedAllocator(DCOMSharedHeapName,pSharedBase);
+
+ CSharedGlobals *GlobalBlock
+ = new CSharedGlobals(SharedGlobalBlockName,status);
+ }
+
+ // BUGBUG: check status, and if not good, do what??
+
+ // Allocate lists
+ gLocalMID = gpLocalMid->GetMID();
+
+ // initialize timestamp for crash checking
+ *gpdwLastCrashedProcessCheckTime = 0;
+
+ if ( status != OR_OK
+ || !gpOxidTable
+ || !gpOidTable
+ || !gpMidTable
+ || !gpLocalDSA
+ || !gpLocalMid
+ || !gpPingProcess
+ || !gpIdSequence
+ )
+ {
+ return(OR_NOMEM);
+ }
+
+
+ DCOM_Started = TRUE;
+ return(OR_OK);
+}
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/oxid.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/oxid.cxx
new file mode 100644
index 000000000..3ffdab181
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/oxid.cxx
@@ -0,0 +1,521 @@
+/*++
+
+Copyright (c) 1995-1996 Microsoft Corporation
+
+Module Name:
+
+ ids.cxx
+
+Abstract:
+
+ Object resolver client side class implementations. COxid, COid
+ classes are implemented here.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 04-03-95 Combined many smaller .cxx files
+ MarioGo 01-05-96 Locally unique IDs
+
+--*/
+
+#include<or.hxx>
+
+
+//
+// COid methods
+//
+
+void
+COid::Rundown()
+{
+ COid *pRemoved = gpOidTable->Remove(*this);
+ ASSERT(pRemoved==this);
+
+ if (!_pOxid->IsLocal())
+ {
+ _pOxid->_pMid->DropClientOid(this);
+ }
+}
+
+
+//
+// COxidInfo methods
+//
+
+
+ORSTATUS // BUGBUG: perhaps this should have OXID_INFO as the parameter type
+COxidInfo::Assign(
+ const COxidInfo& Info
+ )
+/*++
+
+Routine Desciption
+
+ Makes a copy of the incoming info, including the DUALSTRINGARRAY.
+
+Arguments:
+
+ Info - COxidInfo object to be cpied
+
+Return Values:
+
+ OR_OK
+ OR_NOMEM
+
+--*/
+{
+ _dwTid = Info._dwTid;
+ _dwPid = Info._dwPid;
+ _dwAuthnHint = Info._dwAuthnHint;
+ _ipidRemUnknown = Info._ipidRemUnknown;
+
+ return _dsaBindings.Assign(Info._dsaBindings);
+}
+
+
+//
+// COxid methods.
+//
+
+
+COxid::COxid(
+ OXID Oxid, // constructor for remote OXIDs
+ CMid *pMid,
+ USHORT wProtseq,
+ OXID_INFO &OxidInfo
+ ) :
+ _Key(Oxid, pMid->GetMID()),
+ _pProcess(OR_BASED_POINTER(CProcess,gpPingProcess)),
+ _protseq(wProtseq),
+ _fApartment(FALSE),
+ _fRunning(TRUE),
+ _fRundownThreadStarted(FALSE),
+ _pMid(OR_BASED_POINTER(CMid,pMid)),
+ _fLocal(FALSE),
+ _hRundownThread(NULL),
+ _info(OxidInfo)
+ {
+ _pMid->Reference();
+ }
+
+
+COxid::COxid( // constructor for local OXIDs
+ CProcess *pProcess,
+ OXID_INFO &OxidInfo,
+ BOOL fApartment
+ ) :
+ _Key(AllocateId(), gLocalMID),
+ _pProcess(OR_BASED_POINTER(CProcess,pProcess)),
+ _pMid(OR_BASED_POINTER(CMid,gpLocalMid)),
+ _protseq(0),
+ _fApartment(fApartment),
+ _fRunning(TRUE),
+ _fRundownThreadStarted(FALSE),
+ _fLocal(TRUE),
+ _hRundownThread(NULL),
+ _info(OxidInfo)
+ {
+ _pProcess->Reference();
+ }
+
+
+COxid::~COxid()
+{
+ // this works even if executed by nonowner thread
+ StopRundownThreadIfNecessary();
+
+ // Don't release the local CMid!
+ if (!IsLocal()) _pMid->Release();
+}
+
+
+
+COid *
+COxid::DisownOid(COid *pOid)
+{
+ COid *pMyOid = _MyOids.Remove(*pOid);// releases our reference
+
+ if (pMyOid)
+ {
+ ASSERT(pMyOid == pOid);
+ return pOid;
+ }
+
+ return NULL;
+}
+
+
+void
+COxid::StopRunning()
+{
+ ReleaseAllOids();
+ _fRunning = FALSE;
+}
+
+
+void
+COxid::ReleaseAllOids()
+{
+ if (_MyOids.Size())
+ {
+ COidTableIterator Oids(_MyOids);
+ COid *pOid;
+
+ while(pOid = Oids.Next())
+ {
+ pOid->Rundown();
+ }
+
+ _MyOids.RemoveAll();
+ }
+}
+
+
+ORSTATUS
+COxid::GetInfo(
+ OUT OXID_INFO *pInfo
+ )
+/*++
+
+Routine Description:
+
+ Returns the OXID_INFO structure for this oxid for local.
+
+Arguments:
+
+ pInfo - Will contain the standard info, a single _expanded_
+ string binding and complete security bindings.
+
+Return Value:
+
+ OR_NOMEM - Unable to allocate a parameter.
+
+ OR_OK - Normally.
+
+--*/
+
+{
+ USHORT protseq;
+ PWSTR pwstrT;
+ CDSA dsaBindings;
+
+ if (!IsRunning())
+ {
+ return OR_NOSERVER;
+ }
+
+ if (_fLocal)
+ {
+ dsaBindings.Assign(_pProcess->GetLocalBindings());
+
+#ifndef _CHICAGO_
+ protseq = ID_LPC;
+#else // always use WMSG on Win95 for local servers
+ protseq = ID_WMSG;
+#endif // _CHICAGO_
+
+ }
+ else
+ {
+ protseq = _protseq; // use the one we set when this was created
+ DUALSTRINGARRAY *pdsa = _info._dsaBindings; // auto conversion
+ dsaBindings.Assign(pdsa); // noncopying assignment
+ }
+
+ pwstrT = FindMatchingProtseq(protseq, dsaBindings->aStringArray);
+
+ ASSERT(pwstrT != NULL && "OR: Didn't find a matching binding for oxid");
+
+ pInfo->psa =
+ GetStringBinding(
+ pwstrT,
+ dsaBindings->aStringArray + dsaBindings->wSecurityOffset
+ );
+
+ if (0 == pInfo->psa)
+ {
+ return OR_NOMEM;
+ }
+
+ pInfo->dwTid = _info._dwTid;
+ pInfo->dwPid = _info._dwPid;
+ pInfo->dwAuthnHint = _info._dwAuthnHint;
+ pInfo->ipidRemUnknown = _info._ipidRemUnknown;
+
+ return(OR_OK);
+}
+
+
+
+ORSTATUS
+COxid::GetRemoteInfo(
+ IN USHORT cClientProtseqs,
+ IN USHORT *aClientProtseqs,
+ IN USHORT cInstalledProtseqs,
+ IN USHORT *aInstalledProtseqs,
+ OUT OXID_INFO *pInfo
+ )
+/*++
+
+Routine Description:
+
+ Returns the OXID_INFO structure for this oxid for remote clients.
+
+Arguments:
+
+ pInfo - Will contain the standard info, a single _expanded_
+ string binding and complete security bindings.
+
+Return Value:
+
+ OR_NOMEM - Unable to allocate a parameter.
+
+ OR_OK - Normally.
+
+--*/
+
+{
+ PWSTR pwstrT;
+ ORSTATUS status = OR_OK;
+
+ if (!IsRunning())
+ {
+ return OR_NOSERVER;
+ }
+
+ ASSERT(_fLocal); // Do not resolve remote servers for remote clients!
+
+ DUALSTRINGARRAY * pdsaBindings = _pProcess->GetLocalBindings();
+
+ pwstrT = FindMatchingProtseq(
+ cClientProtseqs,
+ aClientProtseqs,
+ pdsaBindings->aStringArray
+ );
+
+ if ( pwstrT == NULL ) // try lazy use of protseq(s)
+ {
+ status = _pProcess->UseProtseqIfNeeded(
+ cClientProtseqs,
+ aClientProtseqs,
+ cInstalledProtseqs,
+ aInstalledProtseqs
+ );
+
+ pdsaBindings = _pProcess->GetLocalBindings();
+
+ pwstrT = FindMatchingProtseq(
+ cClientProtseqs,
+ aClientProtseqs,
+ pdsaBindings->aStringArray
+ );
+
+ if ( status != OR_OK || pwstrT == NULL )
+ {
+ ComDebOut((DEB_OXID,"OR: Didn't find a matching binding for oxid %08x in mid %08x\n",
+ GetOXID(), GetMID()));
+
+ return OR_I_NOPROTSEQ;
+ }
+ }
+
+ DUALSTRINGARRAY *pdsaT =
+ GetStringBinding(
+ pwstrT,
+ pdsaBindings->aStringArray + pdsaBindings->wSecurityOffset
+ );
+
+ if (pdsaT != NULL)
+ {
+ pInfo->psa = CompressStringArray(pdsaT,FALSE);
+ MIDL_user_free(pdsaT);
+ }
+
+
+ if (NULL == pdsaT || NULL == pInfo->psa)
+ {
+ return OR_NOMEM;
+ }
+
+ pInfo->dwTid = 0;
+ pInfo->dwPid = 0;
+ pInfo->dwAuthnHint = _info._dwAuthnHint;
+ pInfo->ipidRemUnknown = _info._ipidRemUnknown;
+
+ return(status);
+}
+
+
+
+ORSTATUS
+COxid::StartRundownThreadIfNecessary()
+{
+ DWORD dwThrdId;
+
+ if (_fApartment || !IsLocal()) // rundown timer is attached to window
+ // or rundown handled by ping server
+ {
+ ASSERT(!_hRundownThread);
+ return OR_OK;
+ }
+
+ if (_fRundownThreadStarted) // BUGBUG: We do not want a rundown
+ // thread for each remote OXID
+ {
+ ASSERT(_hRundownThread);
+ return OR_OK;
+ }
+
+ _hRundownThread = CreateThread(
+ NULL, 0,
+ RundownThread,
+ this, 0, &dwThrdId);
+
+ if (_hRundownThread)
+ {
+ _fRundownThreadStarted = TRUE;
+ return OR_OK;
+ }
+ else
+ {
+ return GetLastError();
+ }
+}
+
+
+
+
+ORSTATUS
+COxid::StopRundownThreadIfNecessary()
+{
+ if (_fRundownThreadStarted)
+ {
+ ASSERT(_hRundownThread);
+
+ if (CloseHandle(_hRundownThread))
+ {
+ _fRundownThreadStarted = FALSE;
+ _hRundownThread = NULL;
+ return OR_OK;
+ }
+ else
+ {
+ return GetLastError();
+ }
+ }
+ else
+ {
+ ASSERT(!_hRundownThread);
+ return OR_OK;
+ }
+}
+
+
+ORSTATUS
+COxid::StopTimerIfNecessary() // must be called by owner thread
+{
+ ORSTATUS status = OR_OK;
+
+ if (_fApartment)
+ {
+ // find the HWND for this thread
+
+ COleTls tls;
+ HWND hWindow = (HWND)((OXIDEntry *)tls->pOXIDEntry)->hServerSTA;
+
+ if (!KillTimer(hWindow,IDT_DCOM_RUNDOWN))
+ {
+ status = GetLastError();
+ }
+ }
+
+ return status;
+}
+
+void
+CheckForCrashedProcessesIfNecessary()
+{
+ CTime CurrentTime;
+
+ // don't check too often
+ if (CurrentTime - CTime(*gpdwLastCrashedProcessCheckTime) < BasePingInterval)
+ {
+ return;
+ }
+
+ // timestamp the check
+ *gpdwLastCrashedProcessCheckTime = CurrentTime;
+
+ CProcessTableIterator procIter(*gpProcessTable);
+
+ CProcess *pNextProcess;
+
+ while (pNextProcess = procIter.Next())
+ {
+ if (pNextProcess->HasCrashed())
+ {
+ // ASSERT(0);
+
+ ComDebOut((DEB_OXID,"Process PID = %d has crashed\n",
+ pNextProcess->_processID));
+ gpProcessTable->Remove(*pNextProcess);
+ pNextProcess->Rundown();
+ }
+ else
+ {
+ ComDebOut((DEB_OXID,"Process PID = %d is running\n",
+ pNextProcess->_processID));
+ }
+ }
+}
+
+
+void
+COxid::RundownOidsIfNecessary(
+ IRundown *pRemUnk
+ )
+{
+ ::CheckForCrashedProcessesIfNecessary();
+
+ if (_MyOids.Size() == 0) return;
+
+ COidTableIterator Oids(_MyOids);
+ COid *pOid;
+
+ while(pOid = Oids.Next())
+ {
+ if (pOid->OkToRundown())
+ {
+ // ASSERT(0); // BUGBUG: to debug Rundown
+
+ // COid object says OK to run down. Try to run it down.
+
+ OID Oid = pOid->GetOID();
+ unsigned char fOkToRundown;
+
+ if (IsLocal())
+ {
+ pRemUnk->RundownOid(1,&Oid,&fOkToRundown);
+ }
+ else
+ {
+ fOkToRundown = TRUE;
+ }
+
+ // If marshaller says OK to run down, get rid of it
+
+ if (fOkToRundown)
+ {
+ pOid->Rundown();
+ COid *pRemoved = _MyOids.Remove(*pOid);
+ ASSERT(pRemoved == pOid);
+
+ // At this point, the references for pOid should drop to zero
+ }
+ }
+ }
+}
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/oxid.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/oxid.hxx
new file mode 100644
index 000000000..fc318a8a9
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/oxid.hxx
@@ -0,0 +1,437 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ oxid.hxx
+
+Abstract:
+
+ COxid objects represent OXIDs which are in use by processes on this machine.
+ These always contain a pointer to a process object and a ping set.
+
+Author:
+
+ Satish Thatte [SatishT]
+
+Revision History:
+
+ SatishT 02-07-96 Merged and simplified Client and Server Oxid classes
+
+--*/
+
+#ifndef __OXID_HXX
+#define __OXID_HXX
+
+
+struct COxidInfo
+{
+ DWORD _dwTid;
+ DWORD _dwPid;
+ IPID _ipidRemUnknown;
+ DWORD _dwAuthnHint;
+ CDSA _dsaBindings;
+
+ COxidInfo(const OXID_INFO& OxidInfo)
+ : _dwTid(OxidInfo.dwTid),
+ _dwPid(OxidInfo.dwPid),
+ _ipidRemUnknown(OxidInfo.ipidRemUnknown),
+ _dwAuthnHint(OxidInfo.dwAuthnHint), // BUGBUG: global setting OK?
+ _dsaBindings(OxidInfo.psa) // bindings are process-wide, except for remote OXIDs
+ {}
+
+ operator OXID_INFO()
+ {
+ OXID_INFO result;
+ result.dwTid = _dwTid;
+ result.dwPid = _dwPid;
+ result.ipidRemUnknown = _ipidRemUnknown;
+ result.dwAuthnHint = _dwAuthnHint;
+ result.psa = _dsaBindings;
+
+ return result;
+ }
+
+ ORSTATUS Assign(const COxidInfo& Info);
+
+
+};
+
+
+
+
+class CId2Key : public ISearchKey
+{
+public:
+
+ CId2Key(const ID id1, const ID id2) : _id1(id1), _id2(id2) { }
+
+ virtual DWORD
+ Hash()
+ {
+ return( (DWORD)_id2 ^ (*((DWORD *)&_id2 + 1))
+ ^ (DWORD)_id1 ^ (*((DWORD *)&_id1 + 1)) );
+ }
+
+ virtual BOOL
+ Compare(ISearchKey &tk)
+ {
+ CId2Key &idk = (CId2Key &)tk;
+
+ return(idk._id2 == _id2
+ && idk._id1 == _id1);
+ }
+
+ ID Id1()
+ {
+ return _id1;
+ }
+
+ ID Id2()
+ {
+ return _id2;
+ }
+
+protected:
+
+ ID _id1,_id2;
+};
+
+
+
+
+
+class COid : public CTableElement, public CTime // the time of last release, implicitly
+ // set to creation time by constructor
+/*++
+
+Class Description:
+
+ Each instance of this class represents an OID registered
+ by a client or a server on this machine.
+
+Members:
+
+ _pOxid - A pointer to the OXID to which this OID belongs.
+ We own a reference.
+
+--*/
+
+{
+ private :
+
+ COxid OR_BASED * _pOxid;
+ CId2Key _Key;
+
+ public :
+
+ COid( // complete constructor for remote OIDs
+ OID Oid,
+ COxid *pOxid
+ );
+
+ COid( // simpler constructor for local server allocation
+ COxid *pOxid
+ );
+
+ ~COid();
+
+ void * operator new(size_t s)
+ {
+ return OrMemAlloc(s);
+ }
+
+ void operator delete(void * p) // do not inherit this!
+ {
+ OrMemFree(p);
+ }
+
+ operator ISearchKey&() // this allows us to be a ISearchKey as well
+ {
+ return _Key;
+ }
+
+ virtual DWORD Release()
+ {
+ SetNow(); // timestamp the release
+ return CReferencedObject::Release();
+ }
+
+ OXID GetOID()
+ {
+ return _Key.Id1();
+ }
+
+ BOOL Match(COid *pOid) // BUGBUG: ??
+ {
+ return(pOid->_pOxid == _pOxid);
+ }
+
+ BOOL OkToRundown();
+
+ void Rundown();
+
+ COxid *GetOxid()
+ {
+ return(_pOxid);
+ }
+};
+
+
+DEFINE_TABLE(COid)
+DEFINE_LIST(COid)
+
+class COxid : public CTableElement
+/*++
+
+Class Description:
+
+ Each instance of this class represents an OXID (object exporter,
+ a process or an apartment model thread).
+
+ BUGBUG: ??
+
+ Each OXID is owned,
+ referenced, by the owning process and the OIDs registered by
+ that process for this OXID.
+
+
+Members:
+
+ _pProcess - Pointer to the process instance which owns this oxid.
+
+ _info - Info registered by the process for this oxid.
+
+ _pMid - Pointer to the machine ID for this OXID, we
+ own a reference.
+
+ _fApartment - Server is aparment model if non-zero
+
+ _fRunning - Process has not released this oxid if non-zero.
+
+--*/
+{
+ friend class CProcess;
+ friend class COid;
+
+private:
+
+ CProcess OR_BASED *_pProcess;
+ COxidInfo _info;
+ CMid OR_BASED *_pMid;
+ BOOL _fApartment:1;
+ BOOL _fRunning:1;
+ BOOL _fLocal:1;
+ BOOL _fRundownThreadStarted:1;
+ HANDLE _hRundownThread;
+ CId2Key _Key;
+ USHORT _protseq;
+
+ COidTable _MyOids;
+
+public:
+
+ COxid(
+ OXID Oxid, // constructor for remote OXIDs
+ CMid *pMid,
+ USHORT wProtseq,
+ OXID_INFO &OxidInfo
+ );
+
+ COxid( // constructor for local OXIDs
+ CProcess *pProcess,
+ OXID_INFO &OxidInfo,
+ BOOL fApartment
+ );
+
+
+
+ ~COxid();
+
+ void * operator new(size_t s)
+ {
+ return OrMemAlloc(s);
+ }
+
+ void operator delete(void * p) // do not inherit this!
+ {
+ OrMemFree(p);
+ }
+
+ operator ISearchKey&() // this allows us to be a ISearchKey as well
+ {
+ return _Key;
+ }
+
+ DWORD GetTid()
+ {
+ return(_info._dwTid);
+ }
+
+ BOOL IsRunning()
+ {
+ return(_fRunning);
+ }
+
+ BOOL IsLocal()
+ {
+ return(_fLocal);
+ }
+
+ BOOL Apartment()
+ {
+ return(_fApartment);
+ }
+
+ MID GetMID()
+ {
+ return _Key.Id2();
+ }
+
+ OXID GetOXID()
+ {
+ return _Key.Id1();
+ }
+
+ CMid *GetMid()
+ {
+ return(OR_FULL_POINTER(CMid,_pMid));
+ }
+
+ SETID GetSetid();
+
+ ORSTATUS
+ COxid::UpdateInfo(OXID_INFO *pInfo)
+ {
+ ASSERT(pInfo);
+
+ return _info.Assign(*pInfo);
+ }
+
+ ORSTATUS GetInfo(
+ OUT OXID_INFO *
+ );
+
+ ORSTATUS GetRemoteInfo(
+ IN USHORT cClientProtseqs,
+ IN USHORT *aClientProtseqs,
+ IN USHORT cInstalledProtseqs,
+ IN USHORT *aInstalledProtseqs,
+ OUT OXID_INFO *pInfo
+ );
+
+ void RundownOids(USHORT cOids,
+ OID aOids[],
+ BYTE aStatus[]);
+
+ ORSTATUS LazyUseProtseq(USHORT, USHORT[]);
+
+ void StopRunning();
+
+ ORSTATUS StartRundownThreadIfNecessary();
+
+ ORSTATUS StopRundownThreadIfNecessary();
+
+ ORSTATUS StopTimerIfNecessary(); // must be called by owner thread
+
+ ORSTATUS OwnOid(COid *pOid)
+ {
+ return _MyOids.Add(pOid); // acquires a reference
+ }
+
+ COid * DisownOid(COid *pOid);
+
+ void ReleaseAllOids();
+
+private:
+
+ friend VOID CALLBACK RundownTimerProc(
+ HWND hwnd, // handle of window for timer messages
+ UINT uMsg, // WM_TIMER message
+ UINT idEvent, // timer identifier
+ DWORD dwTime // current system time
+ );
+
+ friend DWORD _stdcall RundownThread(void *self);
+
+ friend DWORD _stdcall PingThread(void);
+
+ void RundownOidsIfNecessary(IRundown *);
+};
+
+
+DEFINE_TABLE(COxid)
+
+//
+// decl for rundown thread function -- the parameter is the self pointer
+//
+
+DWORD _stdcall RundownThread(void *pSelf);
+
+
+
+//
+// Inline COid methods which depend on COxid methods
+//
+
+
+inline
+COid::COid( // complete constructor for remote OIDs
+ OID Oid,
+ COxid *pOxid
+ ) :
+ _Key(Oid,pOxid->GetMID()),
+ _pOxid(OR_BASED_POINTER(COxid,pOxid))
+{
+ ASSERT(_pOxid);
+ _pOxid->Reference();
+}
+
+
+inline
+COid::COid( // simpler constructor for local server allocation
+ COxid *pOxid
+ ) :
+ _Key(AllocateId(),pOxid->GetMID()),
+ _pOxid(OR_BASED_POINTER(COxid,pOxid))
+{
+ ASSERT(_pOxid);
+ _pOxid->Reference();
+}
+
+
+inline
+COid::~COid()
+{
+ ASSERT(_pOxid);
+ _pOxid->Release();
+
+ COid *pt = gpOidTable->Remove(*this); // should really not be there
+ ASSERT(pt == NULL && "Oid object still in global table during destruct");
+}
+
+inline
+BOOL
+COid::OkToRundown()
+{
+ DWORD dwRefs = References();
+ ASSERT(dwRefs >= 2);
+
+ if (dwRefs > 2)
+ {
+ return FALSE;
+ }
+ else
+ {
+ // Check if the time since creation or last release is less than timeout
+ if ((CTime() - *this) < BaseTimeoutInterval)
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+#endif // __OXID_HXX
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/process.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/process.cxx
new file mode 100644
index 000000000..980aa6ee1
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/process.cxx
@@ -0,0 +1,453 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Process.cxx
+
+Abstract:
+
+ Process objects represent local clients and servers. These
+ objects live as context handles.
+
+ There are relatively few of these objects in the universe.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-20-95 Bits 'n pieces
+
+--*/
+
+#include <or.hxx>
+
+#if DBG
+
+void CProcess::IsValid()
+{
+ _MyOxids.IsValid();
+ _UsedOids.IsValid();
+ _dsaLocalBindings.IsValid();
+ _dsaRemoteBindings.IsValid();
+ References() > 0;
+}
+
+#endif // DBG
+
+
+CProcess::CProcess(long ConnectId)
+ :
+ _MyOxids(4), // BUGBUG: these constants should be declared elsewhere
+ _UsedOids(16),
+ _hProcess(NULL)
+{
+ _processID = GetCurrentProcessId();
+ _Key.Init(ConnectId);
+}
+
+
+
+RPC_BINDING_HANDLE
+CProcess::GetBindingHandle()
+{
+ VALIDATE_METHOD
+
+ USHORT protseq;
+
+ if (_hProcess) return _hProcess;
+
+#ifndef _CHICAGO_
+ protseq = ID_LPC;
+#else
+ protseq = ID_WMSG;
+#endif
+
+ PWSTR pwstrMatch = FindMatchingProtseq(protseq, _dsaLocalBindings->aStringArray);
+
+ ASSERT(pwstrMatch);
+
+ PWSTR pwstrProtseq = GetProtseq(*pwstrMatch);
+
+ int l = OrStringLen(pwstrMatch) + OrStringLen(pwstrProtseq) + 2;
+
+ PWSTR pwstrBinding = (WCHAR *) PrivMemAlloc(l * sizeof(WCHAR));
+
+ if (!pwstrBinding)
+ {
+ return (NULL);
+ }
+
+ OrStringCopy(pwstrBinding, pwstrProtseq);
+ OrStringCat(pwstrBinding, L":");
+ OrStringCat(pwstrBinding, pwstrMatch + 1);
+
+ RPC_STATUS status = RpcBindingFromStringBinding(
+ pwstrBinding,
+ &_hProcess
+ );
+
+ ASSERT(status == RPC_S_OK);
+
+ PrivMemFree(pwstrBinding);
+
+ return _hProcess;
+}
+
+void
+CProcess::Rundown()
+// The process has crashed or disconnected and this object is being cleaned up.
+{
+ COxid *pOxid;
+ COid *pOid;
+ ORSTATUS status;
+
+ CClassReg * pReg;
+
+ while ( (pReg = _RegClasses.Pop()) != NULL )
+ {
+#ifdef _CHICAGO_ // BUGBUG: not essential, don't bother with on NT shared resolver
+ SCMRemoveRegistration( pReg->_Clsid,
+ pReg->_Reg
+ );
+#endif
+ // delete pReg; BUGBUG: do not explicitly delete refcounted objects!
+ }
+
+ if (_MyOxids.Size())
+ {
+ COxidTableIterator Oxids(_MyOxids);
+
+ while(pOxid = Oxids.Next())
+ {
+ DisownOxid(pOxid,FALSE); // not the server thread
+ }
+ }
+
+ _UsedOids.RemoveAll();
+}
+
+
+// This thing has 2 kernel traps. Best not done too often.
+
+BOOL
+CProcess::HasCrashed()
+{
+ VALIDATE_METHOD
+
+ // the process doing the check is definitely alive
+
+ if (_processID == MyProcessId /* && _Key == Key */)
+ {
+ return FALSE;
+ }
+
+ HANDLE hp = OpenProcess(
+ PROCESS_QUERY_INFORMATION,
+ FALSE,
+ _processID
+ );
+
+ if (!hp) // we assume the process is terminated and gone
+ {
+ return FALSE; // BUGBUG: still not a good choice
+ }
+
+ // OK, we have a handle. Now do a sanity check to make sure this is
+ // the same process.
+
+ // BUGBUG: still no good sanity check available -- this means we may
+ // not have a handle to the right process -- therefore some crashes
+ // may go undetected. Unlikely, but possible.
+
+ // One possibility is to cache the address of gpProcess in the process
+ // object and do a ReadProcessMemory on the process handle as a sanity
+ // check -- crude but workable since Win95 has no security against it
+
+ DWORD dwExitCode;
+
+ GetExitCodeProcess(hp,&dwExitCode);
+
+ if (STILL_ACTIVE == dwExitCode)
+ {
+ return FALSE;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+
+RPC_STATUS
+CProcess::ProcessBindings(
+ IN DUALSTRINGARRAY *pdsaStringBindings
+ )
+/*++
+
+Routine Description:
+
+ Updates the string bindings associated with this process.
+
+Arguments:
+
+ psaStringBindings - The expanded string bindings of the process
+ assumed to be allocated with "new" in local (not shared) memory
+
+Return Value:
+
+ OR_NOMEM - unable to allocate storage for the new string arrays.
+
+ OR_OK - normally.
+
+--*/
+
+{
+ VALIDATE_METHOD
+
+ ORSTATUS status = OR_OK;
+
+ ASSERT(pdsaStringBindings && dsaValid(pdsaStringBindings)
+ && "Process given invalid bindings to store");
+
+ status = _dsaLocalBindings.Assign(pdsaStringBindings, FALSE); // FALSE = uncompressed
+
+ delete [] (char*)pdsaStringBindings; // Assign makes a compressed copy
+
+ ASSERT(_dsaLocalBindings.Valid());
+
+ _dsaRemoteBindings.Assign(NULL,TRUE); // wipes it out -- filled again when needed
+
+ return(OR_OK);
+}
+
+
+
+DUALSTRINGARRAY *
+CProcess::GetRemoteBindings(void)
+{
+ VALIDATE_METHOD
+
+ ORSTATUS Status;
+
+ if (_dsaRemoteBindings.Empty() && !_dsaLocalBindings.Empty())
+ {
+ Status = _dsaRemoteBindings.ExtractRemote(_dsaLocalBindings);
+
+ if (Status != OR_OK)
+ {
+ ASSERT(Status == OR_NOMEM);
+ return(NULL);
+ }
+ }
+
+ if (!_dsaRemoteBindings.Empty())
+ {
+ return _dsaRemoteBindings;
+ }
+ else return(NULL);
+}
+
+
+
+void
+CProcess::DisownOxid(COxid *pOxid, BOOL fOxidThreadCalling)
+{
+ VALIDATE_METHOD
+
+ pOxid->StopRunning();
+
+ if (fOxidThreadCalling)
+ {
+ pOxid->StopRundownThreadIfNecessary();
+ pOxid->StopTimerIfNecessary();
+ }
+
+ COxid *pIt = gpOxidTable->Remove(*pOxid);
+ ASSERT(pIt==pOxid);
+
+ pIt = _MyOxids.Remove(*pOxid);
+ ASSERT(pIt==pOxid);
+
+ // pOxid may be an invalid pointer now
+}
+
+
+
+
+COid *
+CProcess::DropOid(COid *pOid)
+
+/*++
+
+Routine Description:
+
+ Removes an OID from this list of OID in use by this process.
+
+Arguments:
+
+ pOid - The OID to remove.
+
+Return Value:
+
+ non-NULL - the pointer actually removed. (ASSERT(retval == pOid))
+ It will be released by the process before return,
+ so you should not use the pointer unless you know you
+ have another reference.
+
+ NULL - not in the list
+
+--*/
+
+{
+ VALIDATE_METHOD
+
+ COid *pIt = _UsedOids.Remove(*pOid); // releases our reference
+
+ if (pIt)
+ {
+ ASSERT(pIt == pOid);
+ return(pIt);
+ }
+
+ return(NULL);
+}
+
+
+void
+CProcess::AddClassReg(GUID Clsid, DWORD Reg)
+{
+ VALIDATE_METHOD
+
+ CClassReg * pReg = new CClassReg( Clsid, Reg );
+
+ if (pReg)
+ {
+ ORSTATUS status;
+
+ _RegClasses.Insert(status,pReg);
+ }
+}
+
+void
+CProcess::RemoveClassReg(GUID Clsid, DWORD Reg)
+{
+ VALIDATE_METHOD
+
+ CClassReg * pReg = _RegClasses.Remove(CRegKey(Reg));
+ // delete pReg; BUGBUG: do not explicitly delete refcounted objects!
+}
+
+
+
+ORSTATUS // called only within the SCMOR process
+CProcess::UseProtseqIfNeeded(
+ IN USHORT cClientProtseqs,
+ IN USHORT aClientProtseqs[],
+ IN USHORT cInstalledProtseqs,
+ IN USHORT aInstalledProtseqs[]
+ )
+{
+ VALIDATE_METHOD
+
+ ORSTATUS status;
+ PWSTR pwstrProtseq = NULL;
+
+ // Another thread may have used the protseq in the mean time.
+
+ ASSERT(!_dsaLocalBindings.Empty());
+
+ pwstrProtseq = FindMatchingProtseq(cClientProtseqs,
+ aClientProtseqs,
+ _dsaLocalBindings->aStringArray
+ );
+
+ if (NULL != pwstrProtseq)
+ {
+ return(OR_OK);
+ }
+
+ // No protseq shared between the client and the OXIDs' server.
+ // Find a matching protseq.
+
+ USHORT i,j;
+
+ for(i = 0; i < cClientProtseqs && pwstrProtseq == NULL; i++)
+ {
+ for(j = 0; j < cInstalledProtseqs; j++)
+ {
+ if (aInstalledProtseqs[j] == aClientProtseqs[i])
+ {
+ ASSERT(FALSE == IsLocal(aInstalledProtseqs[j]));
+
+ pwstrProtseq = GetProtseq(aInstalledProtseqs[j]);
+ break;
+ }
+ }
+ }
+
+ if (NULL == pwstrProtseq)
+ {
+ // No shared protseq, must be a bug since the client managed to call us.
+#if DBG
+ if (cClientProtseqs == 0)
+ {
+ ComDebOut((DEB_OXID,"OR: Client OR not configured to use remote protseqs\n"));
+ }
+ else
+ {
+ ComDebOut((DEB_OXID,"OR: Client called on an unsupported protocol: \
+ %d %p %p \n", cClientProtseqs, aClientProtseqs, aInstalledProtseqs));
+ ASSERT(0);
+ }
+#endif
+
+ return(OR_NOSERVER);
+ }
+
+ DUALSTRINGARRAY *pdsaStringBindings = NULL,
+ *pdsaSecurityBindings = NULL,
+ *pdsaMergedBindings = NULL;
+
+ {
+ CTempReleaseSharedMemory temp;
+
+ if (GetBindingHandle() != NULL) // initialize _hProcess if necessary
+ {
+ status = ::UseProtseq(_hProcess,
+ pwstrProtseq,
+ &pdsaStringBindings,
+ &pdsaSecurityBindings
+ );
+ }
+ else
+ {
+ return OR_NOSERVER; // BUGBUG: is that the right code?
+ }
+ }
+
+ if (status != RPC_S_OK) return status;
+
+ OrDbgPrint(("OR: Lazy use protseq: %S in process %p - %d\n",
+ pwstrProtseq, this, status));
+
+ // Update this process' state to include the new bindings.
+
+ status = MergeBindings(
+ pdsaStringBindings,
+ pdsaSecurityBindings,
+ &pdsaMergedBindings
+ );
+
+ ASSERT(status == OR_OK);
+ status = ProcessBindings(pdsaMergedBindings);
+ MIDL_user_free(pdsaStringBindings);
+ MIDL_user_free(pdsaSecurityBindings);
+
+ return(status);
+}
+
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/process.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/process.hxx
new file mode 100644
index 000000000..88c45df86
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/process.hxx
@@ -0,0 +1,283 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Process.hxx
+
+Abstract:
+
+ Process objects represent local clients and servers. These
+ objects live as context handles.
+
+ There are relativly few of these objects in the universe.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-11-95 Bits 'n pieces
+ MarioGo 01-06-96 Based on CReferencedObject
+
+--*/
+
+#ifndef __PROCESS_HXX
+#define __PROCESS_HXX
+
+
+// At the moment there does not seem to be any reason
+// to make this a base class for CId2Key.
+
+class CIdKey : public ISearchKey
+{
+public:
+
+ CIdKey() {}
+
+ CIdKey(const ID Id)
+ {
+ Init(Id);
+ }
+
+ void Init(const ID Id)
+ {
+ _id = Id;
+ }
+
+ virtual DWORD
+ Hash()
+ {
+ return((DWORD)_id ^ (*((DWORD *)&_id + 1)) );
+ }
+
+ virtual BOOL
+ Compare(ISearchKey &tk)
+ {
+ CIdKey &idk = (CIdKey &)tk;
+
+ return(idk._id == _id);
+ }
+
+ ID Id()
+ {
+ return _id;
+ }
+
+protected:
+
+ ID _id;
+};
+
+
+
+
+class CRegKey : public ISearchKey
+{
+public:
+
+ CRegKey(DWORD reg)
+ {
+ _reg = reg;
+ }
+
+ virtual DWORD // dummy method in this class
+ Hash()
+ {
+ return 0;
+ }
+
+ virtual BOOL
+ Compare(ISearchKey &sk)
+ {
+ CRegKey &rk = (CRegKey &)sk;
+
+ return(rk._reg == _reg);
+ }
+
+ operator DWORD()
+ {
+ return _reg;
+ }
+
+protected:
+
+ DWORD _reg;
+};
+
+
+class CClassReg : public CTableElement
+{
+public :
+
+ GUID _Clsid;
+ CRegKey _Reg;
+
+ CClassReg( GUID clsid, DWORD reg ) : _Clsid(clsid), _Reg(reg) {}
+
+ void * operator new(size_t s)
+ {
+ return OrMemAlloc(s);
+ }
+
+ void operator delete(void * p) // do not inherit this!
+ {
+ OrMemFree(p);
+ }
+
+ virtual DWORD // dummy method in this class
+ Hash()
+ {
+ return _Reg.Hash();
+ }
+
+ virtual operator ISearchKey&()
+ {
+ return _Reg;
+ }
+};
+
+
+void SCMRemoveRegistration( // BUGBUG: This should be in a proper header
+ GUID Clsid,
+ DWORD Reg
+ );
+
+class CProcess : public CTableElement
+/*++
+
+Class Description:
+
+ An instance of this class is created for each process
+ using the OR as either a client or server.
+
+ The process object is referenced by server OXIDs and has
+ one implicit reference by the actual process (which is
+ dereferenced during the context rundown). Instances of
+ these objects are managed by the RPC runtime as context
+ handles.
+
+Members:
+
+ _dsaLocalBindings - The string bindings of the process, including
+ local only protseqs
+
+ _dsaRemoteBindings - A subset of _dsaLocalBindings not containing
+ any local-only protseqs
+
+ _blistOxids - A CBList containing pointers to the COxid's
+ owned by this process, if any.
+
+ _blistOids - A CBList of pointers to COid's which this
+ process is using and referencing, if any.
+
+--*/
+
+{
+
+private:
+
+ friend void CheckForCrashedProcessesIfNecessary();
+ friend DWORD _stdcall PingThread(void);
+
+ DWORD _processID;
+ CIdKey _Key;
+
+ CDSA _dsaLocalBindings;
+ CDSA _dsaRemoteBindings;
+
+ COxidTable _MyOxids;
+ COidTable _UsedOids;
+
+ RPC_BINDING_HANDLE _hProcess; // for pingserver use only
+
+ TCSafeLinkList<CClassReg> _RegClasses;
+
+public:
+
+#if DBG
+ void IsValid();
+ DECLARE_VALIDITY_CLASS(CProcess)
+#endif
+
+ CProcess(long);
+
+ void * operator new(size_t s)
+ {
+ return OrMemAlloc(s);
+ }
+
+ void operator delete(void * p) // do not inherit this!
+ {
+ OrMemFree(p);
+ }
+
+ operator ISearchKey&()
+ {
+ return _Key;
+ }
+
+ DWORD GetProcessID() { return _processID; }
+
+ RPC_STATUS ProcessBindings(DUALSTRINGARRAY *);
+
+ RPC_BINDING_HANDLE GetBindingHandle();
+
+ DUALSTRINGARRAY *GetLocalBindings(void)
+ {
+ VALIDATE_METHOD
+
+ return _dsaLocalBindings;
+ }
+
+ DUALSTRINGARRAY *GetRemoteBindings(void);
+
+ ORSTATUS OwnOxid(COxid *pOxid)
+ {
+ VALIDATE_METHOD
+
+ return _MyOxids.Add(pOxid); // acquires a reference
+ }
+
+ void DisownOxid(COxid *pOxid, BOOL fOxidThreadCalling);
+
+ BOOL IsOwner(COxid *pOxid)
+ {
+ VALIDATE_METHOD
+
+ COxid *pFound = _MyOxids.Lookup(*pOxid);
+ ASSERT(!pFound || pFound == pOxid);
+ return pFound == pOxid;
+ }
+
+ ORSTATUS AddOid(COid *pOid)
+ {
+ VALIDATE_METHOD
+
+ return _UsedOids.Add(pOid); // this acquires a reference for us
+ }
+
+ COid *DropOid(COid *);
+
+ void AddClassReg(GUID Clsid, DWORD Reg);
+
+ void RemoveClassReg(GUID Clsid, DWORD Reg);
+
+ ORSTATUS UseProtseqIfNeeded(
+ IN USHORT cClientProtseqs,
+ IN USHORT aClientProtseqs[],
+ IN USHORT cInstalledProtseqs,
+ IN USHORT aInstalledProtseqs[]
+ );
+
+ void Rundown();
+
+ BOOL HasCrashed();
+};
+
+DEFINE_TABLE(CProcess)
+
+#endif // __PROCESS_HXX
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/refobj.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/refobj.hxx
new file mode 100644
index 000000000..745b0157c
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/refobj.hxx
@@ -0,0 +1,82 @@
+
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ RefObj.hxx
+
+Abstract:
+
+ Generic base class for reference counted objects.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 12-15-95 Bits in the 'ol bucket
+
+--*/
+
+#ifndef __REFERENCED_OBJECTS_HXX
+#define __REFERENCED_OBJECTS_HXX
+
+class CReferencedObject
+{
+public:
+
+ CReferencedObject()
+ : _references(0)
+ {
+ }
+
+ virtual ~CReferencedObject() { ASSERT(_references == 0); }
+
+ virtual void Reference()
+ {
+ ASSERT(_references >= 0);
+ _references++;
+ }
+
+ virtual DWORD Release()
+ {
+ if ( 0 == Dereference())
+ {
+ delete this;
+ return(0);
+ }
+ // this pointer maybe invalid here.
+ return(1);
+ }
+
+ LONG Dereference()
+ // Used for objects which override Release().
+ {
+ ASSERT(_references);
+ return(_references--);
+ }
+
+ DWORD References()
+ {
+ // Must be called an exclusive lock held or it is meaningless.
+ ASSERT(_references >= 0);
+ return(_references);
+ }
+
+ BOOL WillBeDeletedIfReleased()
+ {
+ return _references == 1;
+ }
+
+private:
+
+ CInterlockedInteger _references; // BUGBUG: no real need for interlocking just now
+ // since all ops happen under global lock
+
+};
+
+#endif // __REFERENCED_OBJECTS_HXX
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.cxx
new file mode 100644
index 000000000..8c02d3bd2
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.cxx
@@ -0,0 +1,202 @@
+#include <or.hxx>
+#include <scmfuns.hxx>
+
+void
+ScmProcessAddClassReg(void * hProcess, REFCLSID rclsid, DWORD dwReg)
+{
+ ASSERT(hProcess==gpProcess);
+ ((CProcess*)hProcess)->AddClassReg( rclsid, dwReg );
+}
+
+void
+ScmProcessRemoveClassReg(void * hProcess, REFCLSID rclsid, DWORD dwReg)
+{
+ ASSERT(hProcess==gpProcess);
+ ((CProcess*)hProcess)->RemoveClassReg( rclsid, dwReg );
+}
+
+void
+ScmObjexGetThreadId(LPDWORD pThreadID) // BUGBUG: Why not AllocateID??
+{
+ CProtectSharedMemory protector; // locks through rest of lexical scope
+
+ *pThreadID = (*gpNextThreadID)++;
+}
+
+RPC_BINDING_HANDLE
+SCMGetBindingHandle(long Id)
+{
+ RPC_BINDING_HANDLE hResult = NULL;
+ CIdKey Key(Id);
+ CProcess *pProcess = gpProcessTable->Lookup(Key);
+ ASSERT(pProcess);
+ RPC_BINDING_HANDLE hTemp = pProcess->GetBindingHandle();
+
+ if (hTemp != NULL)
+ {
+ RPC_STATUS status = RpcBindingCopy(hTemp,&hResult);
+
+ if (status != RPC_S_OK)
+ {
+ return NULL;
+ }
+ else
+ {
+ return hResult;
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+void
+SCMRemoveClassReg(
+ long Id,
+ GUID Clsid,
+ DWORD Reg
+ )
+{
+ CIdKey Key(Id);
+ CProcess *pProcess = gpProcessTable->Lookup(Key);
+ ASSERT(pProcess);
+ pProcess->RemoveClassReg(Clsid,Reg);
+}
+
+void
+SCMAddClassReg(
+ long Id,
+ GUID Clsid,
+ DWORD Reg
+ )
+{
+ CIdKey Key(Id);
+ CProcess *pProcess = gpProcessTable->Lookup(Key);
+ ASSERT(pProcess);
+ pProcess->AddClassReg(Clsid,Reg);
+}
+
+
+
+ORSTATUS OrResolveOxid(
+ IN OXID Oxid,
+ IN USHORT cRequestedProtseqs,
+ IN USHORT aRequestedProtseqs[],
+ IN USHORT cInstalledProtseqs,
+ IN USHORT aInstalledProtseqs[],
+ OUT OXID_INFO& OxidInfo
+ )
+{
+ ComDebOut((DEB_OXID, "_ResolveOxid OXID = %08x\n",Oxid));
+
+ COxid *pOxid;
+ ORSTATUS status = OR_OK;
+
+ CProtectSharedMemory protector; // locks through rest of lexical scope
+
+ pOxid = gpOxidTable->Lookup(CId2Key(Oxid, gLocalMID));
+
+ if (pOxid)
+ {
+ status = pOxid->GetRemoteInfo(
+ cRequestedProtseqs,
+ aRequestedProtseqs,
+ cInstalledProtseqs,
+ aInstalledProtseqs,
+ &OxidInfo
+ );
+
+ return status;
+ }
+ else // the OXID should already be registered by server
+ {
+ return OR_BADOXID;
+ }
+}
+
+
+void GetLocalORBindings(
+ DUALSTRINGARRAY * &pdsaMyBindings
+ )
+{
+ pdsaMyBindings = gpLocalDSA;
+}
+
+void
+GetRegisteredProtseqs(
+ USHORT &cMyProtseqs,
+ USHORT * &aMyProtseqs
+ )
+{
+ cMyProtseqs = *gpcRemoteProtseqs;
+ aMyProtseqs = gpRemoteProtseqIds;
+}
+
+void
+ScmGetNextBindingHandleForRemoteScm(WCHAR * pwszServerName, handle_t * phRemoteScm, LPBOOL pbsecure, int * pindex, USHORT * pprotseq, RPC_STATUS * pstatus)
+{
+
+ WCHAR * pStringBinding = NULL;
+
+ *phRemoteScm = NULL;
+ *pbsecure = FALSE;
+
+/*
+ if (*pindex == -1)
+ {
+ *pindex = 0;
+ }
+ else
+ {
+ *pindex += 1;
+ if (*pindex < cMyProtSeqs)
+ {
+ *pindex = -1;
+ return;
+ }
+ }
+*/
+
+ *pindex = -1;
+ return;
+
+/*
+ *pprotseq = aMyProtseqs[*pindex];
+ *pstatus = RpcStringBindingCompose(
+ NULL,
+ gaProtseqInfo[*pprotseq].pwstrProtseq,
+ pwszServerName,
+ gaProtseqInfo[*pprotseq].pwstrEndpoint,
+ NULL,
+ &pStringBinding );
+
+ if ( *pstatus != RPC_S_OK )
+ return;
+
+ *pstatus = RpcBindingFromStringBinding( pStringBinding, phRemoteSCM );
+
+ RpcStringFree( &pStringBinding );
+ pStringBinding = NULL;
+
+ if ( *pstatus != RPC_S_OK )
+ return;
+
+ *pbsecure = TRUE;
+
+ *pstatus = RpcBindingSetAuthInfo(
+ phRemoteSCM,
+ NULL,
+ RPC_C_AUTHN_LEVEL_CONNECT,
+ RPC_C_AUTHN_WINNT,
+ NULL,
+ 0 );
+
+ if ( *pstatus != RPC_S_OK )
+ {
+ *pbsecure = FALSE;
+ *pstatus = RPC_S_OK;
+ }
+
+*/
+}
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.hxx
new file mode 100644
index 000000000..d93ec898b
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/scmfuns.hxx
@@ -0,0 +1,38 @@
+void
+ScmProcessAddClassReg(void * phprocess, REFCLSID rclsid, DWORD dwReg);
+
+void
+ScmProcessRemoveClassReg(void * phprocess, REFCLSID rclsid, DWORD dwReg);
+
+void
+ScmObjexGetThreadId(LPDWORD pThreadID); // BUGBUG: Why not AllocateID??
+
+
+ORSTATUS OrResolveOxid(
+ IN OXID Oxid,
+ IN USHORT cRequestedProtseqs,
+ IN USHORT aRequestedProtseqs[],
+ IN USHORT cInstalledProtseqs,
+ IN USHORT aInstalledProtseqs[],
+ OUT OXID_INFO& OxidInfo
+ );
+
+void
+GetRegisteredProtseqs(
+ USHORT &cMyProtseqs,
+ USHORT * &aMyProtseqs
+ );
+
+void GetLocalORBindings(
+ DUALSTRINGARRAY * &pdsaMyBindings
+ );
+
+void
+ScmGetNextBindingHandleForRemoteScm(
+ WCHAR * pwszServerName,
+ handle_t * phRemoteScm,
+ LPBOOL pbsecure,
+ int * pindex,
+ USHORT * pprotseq,
+ RPC_STATUS * pstatus
+ );
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/set.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/set.hxx
new file mode 100644
index 000000000..5d20fe4ea
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/set.hxx
@@ -0,0 +1,104 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Manager.cxx
+
+Abstract:
+
+ InProc OR interface
+
+Author:
+
+ Satish Thatte [SatishT] Feb-07-1996
+
+Revision Hist:
+
+ SatishT 02-07-96 Created
+
+--*/
+
+
+
+
+class CPingSet : public CTableElement
+{
+public:
+
+ CPingSet(
+ SETID Id,
+ RPC_AUTHZ_HANDLE hClient, // we keep the string given, make no copy
+ ULONG AuthnLevel,
+ ULONG AuthnSvc,
+ ULONG AuthzSvc
+ )
+ : _setID(Id),
+ _hClient(hClient),
+ _AuthnLevel(AuthnLevel),
+ _AuthnSvc(AuthnSvc),
+ _AuthzSvc(AuthzSvc)
+ {
+ _dwLastPingTime = _dwCreationTime = GetCurrentTime();
+ ;
+ }
+
+ virtual operator ISearchKey&()
+ {
+ return _setID;
+ }
+
+ void
+ SimplePing()
+ {
+ _dwLastPingTime = GetCurrentTime();
+ }
+
+ RPC_AUTHZ_HANDLE
+ GetClient()
+ {
+ return _hClient;
+ }
+
+ BOOL
+ CheckAndUpdateSequenceNumber(USHORT sequence)
+ {
+ // note: this handles overflow cases, too.
+ USHORT diff = sequence - _sequence;
+
+ if (diff && diff <= BaseNumberOfPings)
+ {
+ _sequence = sequence;
+ return(TRUE);
+ }
+ return(FALSE);
+ }
+
+ ORSTATUS
+ ComplexPing(
+ USHORT sequenceNum,
+ USHORT cAddToSet,
+ USHORT cDelFromSet,
+ OID aAddToSet[],
+ OID aDelFromSet[]
+ );
+
+private:
+
+ COidTable _pingSet;
+ CIdKey _setID;
+ USHORT _sequence;
+ RPC_AUTHZ_HANDLE _hClient;
+ DWORD _dwLastPingTime;
+ DWORD _dwCreationTime;
+ ULONG _AuthnLevel;
+ ULONG _AuthnSvc;
+ ULONG _AuthzSvc;
+};
+
+
+DEFINE_TABLE(CPingSet)
+
+
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/string.cxx b/private/ole32/dcomss/objex/shrmem/dcom95/string.cxx
new file mode 100644
index 000000000..84dd0e0b2
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/string.cxx
@@ -0,0 +1,685 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ String.cxx
+
+Abstract:
+
+ Methods of construction of various kinds of DUALSTRINGARRAYs.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 04-01-95 Bits 'n pieces
+ MarioGO 01-??-96 STIRNGARRYs replaced by DUALSTRINGARRAYs
+
+--*/
+
+#include <or.hxx>
+#include <dcomss.h> // GetProtseq et al
+
+static CONST WCHAR aCallbackSecurity[] = L"Security=Identification Static True";
+static CONST DWORD dwCallbackSecurityLength = sizeof(aCallbackSecurity)/sizeof(WCHAR);
+
+RPC_BINDING_HANDLE
+GetBinding(
+ IN PWSTR pCompressedBinding
+ )
+{
+ ASSERT(pCompressedBinding);
+
+ PWSTR pwstrStringBinding;
+ PWSTR pwstrProtseq = GetProtseq(*pCompressedBinding);
+ PWSTR pwstrT;
+ RPC_STATUS Status;
+ RPC_BINDING_HANDLE bhReturn;
+ BOOL fLocal = FALSE;
+
+ if (!pwstrProtseq)
+ {
+ return(0);
+ }
+
+ int size = OrStringLen(pwstrProtseq) + OrStringLen(pCompressedBinding);
+
+ if (*pCompressedBinding == ID_LPC || *pCompressedBinding == ID_WMSG)
+ {
+ fLocal = TRUE;
+ size += dwCallbackSecurityLength + 1; // +1 for ','
+ }
+
+ pwstrStringBinding = (PWSTR) new WCHAR[size];
+ if (!pwstrStringBinding)
+ {
+ return(0);
+ }
+
+ OrStringCopy(pwstrStringBinding, pwstrProtseq);
+ pwstrT = OrStringSearch(pwstrStringBinding, 0);
+ *pwstrT = L':';
+ pwstrT++;
+ *pwstrT = 0;
+ OrStringCopy(pwstrT, pCompressedBinding + 1);
+
+ if (fLocal)
+ {
+ // We assume we have an endpoint.
+
+ pwstrT = OrStringSearch(pwstrT, 0);
+ pwstrT--;
+ if (*pwstrT != L']')
+ {
+ OrDbgPrint(("OR: Local string binding missing endpoint %S\n",
+ pwstrStringBinding));
+ ASSERT(0);
+ return(0);
+ }
+
+ *pwstrT = L',';
+ pwstrT++;
+ OrStringCopy(pwstrT, aCallbackSecurity);
+ pwstrT = OrStringSearch(pwstrT, 0);
+ *pwstrT = L']';
+ *(pwstrT + 1) = 0;
+ }
+
+ Status =
+ RpcBindingFromStringBinding( pwstrStringBinding,
+ &bhReturn);
+
+#if DBG
+ if (Status != RPC_S_OK)
+ {
+ OrDbgPrint(("OR: Unable to create binding for %S = %d\n",
+ pwstrStringBinding,
+ Status));
+ }
+#endif
+
+ return(bhReturn);
+}
+
+
+RPC_BINDING_HANDLE
+GetBindingToOr(
+ IN PWSTR pwstrCompressedBinding
+ )
+/*++
+
+Routine Description:
+
+ Gets an RPC binding to a remote object resolver given
+ a compressed string binding to the remote object resolver.
+
+Arguments:
+
+ pwstrCompressedBinding - a compressed string binding without an endpoint.
+
+Return Value:
+
+ 0 - failed to allocate memory or RpcBindingFromStringBinding failed.
+
+ non-NULL - completed okay
+
+--*/
+{
+ PWSTR protseq, endpoint;
+ PWSTR strbinding;
+ USHORT len;
+ RPC_BINDING_HANDLE bh = 0;
+
+ ASSERT(pwstrCompressedBinding);
+ ASSERT(*pwstrCompressedBinding != 0);
+
+ protseq = GetProtseq(*pwstrCompressedBinding);
+ endpoint = GetEndpoint(*pwstrCompressedBinding);
+
+ if (0 == protseq || 0 == endpoint)
+ {
+ ASSERT(0);
+ return(0);
+ }
+
+ len = 4; // ':' '[' ']' and '\0'
+ len += OrStringLen(protseq);
+ len += OrStringLen(endpoint);
+ len += OrStringLen(&pwstrCompressedBinding[1]);
+
+ strbinding = new USHORT[len];
+
+ if (strbinding)
+ {
+ PWSTR pwstrT;
+
+ OrStringCopy(strbinding, protseq); // protseq
+
+ pwstrT = OrStringSearch(strbinding, 0); // :
+ *pwstrT = L':';
+ pwstrT++;
+ *pwstrT = 0;
+
+ OrStringCat(strbinding, &pwstrCompressedBinding[1]); // network address
+
+ pwstrT = OrStringSearch(strbinding, 0); // [
+ *pwstrT = L'[';
+ pwstrT++;
+ *pwstrT = 0;
+
+ OrStringCat(strbinding, endpoint); // endpoint
+
+ pwstrT = OrStringSearch(strbinding, 0); // ]
+ *pwstrT = L']';
+ pwstrT++;
+ *pwstrT = 0;
+
+ RPC_STATUS status = RpcBindingFromStringBinding(strbinding, &bh);
+
+ ASSERT(bh == 0 || status == RPC_S_OK);
+
+ delete strbinding;
+ }
+
+ if (bh == 0)
+ {
+ OrDbgDetailPrint(("OR: Unable to bind to %S\n", pwstrCompressedBinding + 1));
+ }
+
+ return(bh);
+}
+
+
+DUALSTRINGARRAY *
+GetStringBinding(
+ IN PWSTR pwstrCompressed,
+ IN PWSTR pwstrSecurityBindings
+ )
+/*++
+
+Routine Description:
+
+ Converts the compressed string binding into an expanded
+ string binding. An enpoint maybe optionally specified.
+
+Arguments:
+
+ pwstrCompressed - a compressed string binding
+
+ pwstrSecurityBindings - optional security bindings
+ too be tacked onto the end of the expanded string binding.
+ Terminated by two nulls.
+
+Return Value:
+
+ NULL - out of memory
+
+ non-NULL - a string binding.
+--*/
+{
+ DUALSTRINGARRAY *pT;
+ PWSTR protseq;
+ USHORT seccount;
+
+ PWSTR t = pwstrSecurityBindings;
+ if (t && *t)
+ {
+ seccount = 0;
+ do
+ {
+ seccount++;
+ t++;
+
+ if (*t == 0)
+ {
+ seccount++;
+ t++;
+ }
+ }
+ while(*t);
+
+ seccount++; // final NULL
+ }
+ else
+ {
+ // Two nulls only.
+ seccount = 2;
+ }
+
+ protseq = GetProtseq(*pwstrCompressed);
+
+ int l = OrStringLen(pwstrCompressed) + OrStringLen(protseq) + seccount + 1 + 1;
+
+ pT =(DUALSTRINGARRAY *)midl_user_allocate(sizeof(DUALSTRINGARRAY) + l * sizeof(WCHAR));
+
+ if (!pT)
+ {
+ return (0);
+ }
+
+ pT->wNumEntries = l;
+ OrStringCopy(pT->aStringArray, protseq);
+ OrStringCat(pT->aStringArray, L":");
+ OrStringCat(pT->aStringArray, pwstrCompressed + 1);
+
+ if (pwstrSecurityBindings)
+ {
+ PWSTR t = pT->aStringArray;
+ t = OrStringSearch(t, 0);
+ t++;
+ *t = 0; // Second NULL on string bindings.
+ t++;
+ OrMemoryCopy(t, pwstrSecurityBindings, seccount*sizeof(WCHAR));
+ }
+ else
+ {
+ // Add three NULLs, total of four.
+ PWSTR t = pT->aStringArray;
+ t = OrStringSearch(t, 0);
+ t[1] = 0;
+ t[2] = 0;
+ t[3] = 0;
+ }
+
+ pT->wSecurityOffset = pT->wNumEntries - seccount;
+
+ ASSERT(dsaValid(pT));
+
+ return(pT);
+}
+
+
+ORSTATUS
+ConvertToRemote(
+ IN DUALSTRINGARRAY *pdsaLocal,
+ OUT DUALSTRINGARRAY **ppdsaRemote
+ )
+/* ++
+
+Parameters:
+ pdsaLocal - An array of string bindings with compressed protseqs.
+
+ ppdsaRemote - Will contain only those string bindings in pdsaLocal
+ which are not "IsLocal()".
+
+ Note: *ppdsaRemote maybe used as a flag, don't set it to non-NULL
+ until it is valid.
+
+-- */
+{
+ int iTotalSize;
+ int iSize;
+ USHORT *p1, *p2;
+ DUALSTRINGARRAY *pdsaT;
+
+ // Size remote array
+
+ // Final null terminator
+ iSize = 1;
+
+ p1 = pdsaLocal->aStringArray;
+
+ while(*p1)
+ {
+ if (! IsLocal(*p1) )
+ {
+ iSize += OrStringLen(p1) + 1;
+ }
+ p1 = OrStringSearch(p1, 0) + 1;
+ }
+
+ if (iSize == 1)
+ {
+ iSize = 2; // No non-local strings, need two terminators.
+ }
+
+ iTotalSize = iSize + (pdsaLocal->wNumEntries - pdsaLocal->wSecurityOffset);
+
+ pdsaT = new(iTotalSize * sizeof(WCHAR)) DUALSTRINGARRAY;
+
+ if (!pdsaT)
+ {
+ return(OR_NOMEM);
+ }
+
+ pdsaT->wNumEntries = iTotalSize;
+ pdsaT->wSecurityOffset = iSize;
+
+ p2 = pdsaT->aStringArray;
+
+ // Copy security bindings
+ OrMemoryCopy(p2 + iSize,
+ pdsaLocal->aStringArray + pdsaLocal->wSecurityOffset,
+ (iTotalSize - iSize) * sizeof(WCHAR));
+
+ if (iSize == 2)
+ {
+ // No non-local strings, fill in terminators and return.
+ *p2 = 0;
+ *(p2 + 1) = 0;
+ *ppdsaRemote = pdsaT;
+
+ ASSERT(dsaValid(pdsaT));
+ return(OR_OK);
+ }
+
+ p1 = pdsaLocal->aStringArray;
+
+ while(*p1)
+ {
+ if ( ! IsLocal(*p1) )
+ {
+ OrStringCopy(p2, p1);
+ p2 = OrStringSearch(p2, 0) + 1;
+ }
+
+ p1 = OrStringSearch(p1, 0) + 1;
+ }
+
+ *p2 = 0; // Second terminator.
+
+ *ppdsaRemote = pdsaT;
+
+ ASSERT(dsaValid(pdsaT));
+ return(OR_OK);
+}
+
+DUALSTRINGARRAY *
+CompressStringArray(
+ IN DUALSTRINGARRAY *pdsaExpanded,
+ IN BOOL fSharedMem
+ )
+/*++
+
+Routine Description:
+
+ Converts a stringarray of regular string bindings into a
+ compressed (protseq's replaced with WORD id's) array of
+ string bindings.
+
+Arguments:
+
+ pdsaExpanded - the string array to compress.
+ Security information is copied.
+
+Return Value:
+
+ 0 - failed to allocate memory.
+
+ non-0 - compressed string array.
+
+--*/
+{
+ int i, size;
+ USHORT *p1, *p2, *p3;
+ PWSTR pwstr;
+ DUALSTRINGARRAY *pdsaCompressed;
+
+ // Compute size of result.
+
+ p1 = pdsaExpanded->aStringArray;
+
+ size = pdsaExpanded->wNumEntries - pdsaExpanded->wSecurityOffset;
+
+ if (*p1 == 0)
+ {
+ size += 2; // two null terminators ONLY.
+ }
+ else
+ {
+ size += 1; // last null terminator
+ }
+
+ while(*p1)
+ {
+ int sizeT = OrStringLen(p1);
+
+ p2 = OrStringSearch(p1, L':'); // ':' is not valid in protseq.
+ if (p2)
+ {
+ size += sizeT + 1 - (p2 - p1); // proseq len (p2 - p1) become 1 for Id.
+ }
+ else
+ {
+ ASSERT(p2);
+ }
+
+ p1 = OrStringSearch(p1, 0) + 1;
+ }
+
+ if (fSharedMem)
+ {
+ pdsaCompressed = (DUALSTRINGARRAY*)
+ OrMemAlloc(sizeof(DUALSTRINGARRAY) + size * sizeof(WCHAR));
+ }
+ else
+ {
+ pdsaCompressed = (DUALSTRINGARRAY*)
+ midl_user_allocate(sizeof(DUALSTRINGARRAY) + size * sizeof(WCHAR));
+ }
+
+ if (0 == pdsaCompressed)
+ {
+ return(0);
+ }
+
+ pdsaCompressed->wNumEntries = size;
+ pdsaCompressed->wSecurityOffset = size - (pdsaExpanded->wNumEntries - pdsaExpanded->wSecurityOffset);
+ p3 = pdsaCompressed->aStringArray;
+ *p3 = 0;
+
+ p1 = pdsaExpanded->aStringArray;
+
+ if (*p1 == 0)
+ {
+ // Two null terminators only.
+ *(p3 + 1) = 0;
+ }
+
+ while(*p1)
+ {
+ p2 = OrStringSearch(p1, L':');
+ if (p2)
+ {
+ *p2 = 0;
+ *p3 = GetProtseqId(p1);
+ *p2 = L':';
+ if (*p3 != 0)
+ {
+ p3++;
+ p1 = p2 + 1; // Just after ':'
+ OrStringCopy(p3, p1);
+
+ // Move p3 to start of next string if any.
+ p3 = OrStringSearch(p3, 0) + 1;
+ }
+ }
+
+ // Move p1 to start of next string if any.
+ p1 = OrStringSearch(p1, 0) + 1;
+ }
+
+ // Second terminator, p3 already points to it.
+ *p3 = 0;
+
+ // Copy security bindings
+ OrMemoryCopy(p3 + 1,
+ pdsaExpanded->aStringArray + pdsaExpanded->wSecurityOffset,
+ (pdsaExpanded->wNumEntries - pdsaExpanded->wSecurityOffset) * sizeof(WCHAR));
+
+ ASSERT(dsaValid(pdsaCompressed));
+
+ return(pdsaCompressed);
+}
+
+
+PWSTR
+FindMatchingProtseq(
+ IN USHORT cClientProtseqs,
+ IN USHORT aClientProtseqs[],
+ IN PWSTR pwstrServerBindings
+ )
+/*++
+
+Routine Description:
+
+ Finds the first protseq id in aClientProtseqs which appears in any of
+ the server bindings.
+
+Arguments:
+
+ cClientProtseqs - the number of entries in aClientProtseqs.
+ aClientProtseqs - Protseq tower id's support by the client.
+ pwstrServerBindings - compressed array of bindings supported by the server
+ terminated by two NULLs.
+
+Return Value:
+
+ 0 - no match found.
+ non-0 - a pointer into the pwstrCompressedBindings.
+
+--*/
+
+// Called by server oxid's and processes when checking for lazy use protseq.
+{
+ ULONG i;
+
+ if (0 == cClientProtseqs)
+ {
+ return(0);
+ }
+
+ while(*pwstrServerBindings)
+ {
+ for(i = 0; i < cClientProtseqs; i++)
+ {
+ if (aClientProtseqs[i] == *pwstrServerBindings)
+ {
+ return(pwstrServerBindings);
+ }
+ }
+ pwstrServerBindings = OrStringSearch(pwstrServerBindings, 0) + 1;
+ }
+
+ return(NULL);
+}
+
+
+
+PWSTR
+FindMatchingProtseq(
+ IN USHORT protseq,
+ IN PWSTR pwstrCompressedBindings
+ )
+/*++
+
+Routine Description:
+
+ Searches a compressed string array for an entry which
+ matches a particular protseq.
+
+
+Arguments:
+
+ protseq - The protseq to search for.
+
+ pwstrCompressedBindings - The bindings to search.
+
+Return Value:
+
+ 0 - not found
+
+ non-0 - a pointer into the pwstrCompressedBindings
+
+--*/
+{
+ ASSERT(pwstrCompressedBindings);
+
+ while(*pwstrCompressedBindings)
+ {
+ if (*pwstrCompressedBindings == protseq)
+ {
+ return(pwstrCompressedBindings);
+ }
+ pwstrCompressedBindings = OrStringSearch(pwstrCompressedBindings, 0) + 1;
+ }
+ return(0);
+}
+
+
+
+ORSTATUS
+MergeBindings(
+ IN DUALSTRINGARRAY *pdsaStringBindings,
+ IN DUALSTRINGARRAY *pdsaSecurityBindings,
+ OUT DUALSTRINGARRAY **ppdsaMergedBindings
+ )
+/*++
+
+Routine Description:
+
+ Merges the string bindings from the first param with the security
+ bindings from the second param to create a new dualstring array.
+
+
+Arguments:
+
+ pdsaStringBindings -- The string bindings supplier
+
+ pdsaSecurityBindings -- The security bindings supplier
+
+ ppdsaMergedBindings -- the merged result
+
+Return Value:
+
+ OR_OK (0) - success
+
+ OR_NOMEM - memory allocation failed
+
+--*/
+{
+
+ ASSERT(dsaValid(pdsaStringBindings));
+ ASSERT(dsaValid(pdsaSecurityBindings));
+
+ USHORT wBindingsSize = pdsaStringBindings->wSecurityOffset;
+
+ USHORT wSecuritySize = pdsaSecurityBindings->wNumEntries -
+ pdsaSecurityBindings->wSecurityOffset;
+
+ USHORT wNumEntries = wBindingsSize + wSecuritySize;
+
+ DUALSTRINGARRAY *pdsa = (DUALSTRINGARRAY *)
+ new char[
+ sizeof(DUALSTRINGARRAY) +
+ (wNumEntries - 1) * sizeof(WCHAR)
+ ];
+
+ if (!pdsa)
+ {
+ return OR_NOMEM;
+ }
+
+ *ppdsaMergedBindings = pdsa;
+
+ pdsa->wNumEntries = wNumEntries;
+ pdsa->wSecurityOffset = wBindingsSize;
+
+ memcpy(
+ pdsa->aStringArray,
+ pdsaStringBindings->aStringArray,
+ wBindingsSize * sizeof(WCHAR)
+ );
+
+ memcpy(
+ pdsa->aStringArray + pdsa->wSecurityOffset,
+ pdsaSecurityBindings->aStringArray + pdsaSecurityBindings->wSecurityOffset,
+ sizeof(WCHAR) * wSecuritySize
+ );
+
+ return OR_OK;
+}
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/string.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/string.hxx
new file mode 100644
index 000000000..93b47970b
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/string.hxx
@@ -0,0 +1,159 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ String.hxx
+
+Abstract:
+
+ Inline Helper functions for DUALSTRINGARRAY's
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-22-95 Bits 'n pieces
+
+--*/
+
+#ifndef __STRING_HXX
+#define __STRING_HXX
+
+inline void dsaCopy(DUALSTRINGARRAY *pdsaDest, DUALSTRINGARRAY *pdsaSrc)
+{
+ pdsaDest->wNumEntries = pdsaSrc->wNumEntries;
+ pdsaDest->wSecurityOffset = pdsaSrc->wSecurityOffset;
+ OrMemoryCopy(pdsaDest->aStringArray,
+ pdsaSrc->aStringArray,
+ pdsaSrc->wNumEntries*sizeof(USHORT));
+}
+
+// make a copy in shared memory
+inline DUALSTRINGARRAY *
+dsaSMCopy(DUALSTRINGARRAY *pdsa)
+{
+ ASSERT(NULL != pdsa);
+
+ DUALSTRINGARRAY *pdsaT;
+
+ pdsaT = (DUALSTRINGARRAY *)
+ OrMemAlloc(pdsa->wNumEntries
+ * sizeof(WCHAR) +
+ sizeof(DUALSTRINGARRAY)
+ );
+
+ if (NULL != pdsaT)
+ {
+ dsaCopy(pdsaT, pdsa);
+ }
+
+ return pdsaT;
+}
+
+
+inline BOOL dsaValid(DUALSTRINGARRAY *pdsa)
+{
+ BOOL badPtr = IsBadWritePtr(pdsa->aStringArray, pdsa->wNumEntries * sizeof(WCHAR));
+
+ if ( FALSE == badPtr
+ && pdsa->wNumEntries >= 4
+ && pdsa->wSecurityOffset <= (pdsa->wNumEntries - 2)
+ && pdsa->aStringArray[(pdsa->wNumEntries - 1)] == 0
+ && pdsa->aStringArray[(pdsa->wNumEntries - 2)] == 0
+ && pdsa->aStringArray[(pdsa->wSecurityOffset - 1)] == 0
+ && pdsa->aStringArray[(pdsa->wSecurityOffset - 2)] == 0
+ )
+ {
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+inline DWORD dsaHash(DUALSTRINGARRAY *pdsa)
+// PERF WORK: Make sure the hash looks good in real world usage.
+{
+ int i, count;
+ DWORD hash, t;
+ count = i = hash = pdsa->wNumEntries;
+ hash |= pdsa->wSecurityOffset << 16;
+
+ for(count = 0; count < i/2; count++)
+ {
+ t = *(PDWORD)&pdsa->aStringArray[count * 2];
+
+ hash += hash ^ t;
+ }
+
+ // we may miss the last word, but it is null anyway.
+
+ return(hash);
+}
+
+inline DWORD dsaCompare(DUALSTRINGARRAY *pdsa, DUALSTRINGARRAY *pdsa2)
+{
+ return ( pdsa->wNumEntries == pdsa2->wNumEntries
+ && pdsa->wSecurityOffset == pdsa2->wSecurityOffset
+ && 0 == OrMemoryCompare(pdsa->aStringArray,
+ pdsa2->aStringArray,
+ pdsa->wNumEntries * sizeof(WCHAR)) );
+}
+
+inline PWSTR OrStringSearch(PWSTR string, USHORT value)
+{
+ // Faster and smaller then wcschr() for value == 0
+ if (value == 0)
+ {
+ while(*string)
+ string++;
+ return(string);
+ }
+ return(wcschr(string, value));
+}
+
+RPC_BINDING_HANDLE GetBinding(
+ IN PWSTR pCompressedBinding
+ );
+
+RPC_BINDING_HANDLE GetBindingToOr(
+ IN PWSTR pCompressedBinding
+ );
+
+DUALSTRINGARRAY *GetStringBinding(
+ IN PWSTR pwstrCompressed,
+ IN PWSTR pwstrSecurityBindings
+ );
+
+ORSTATUS ConvertToRemote(
+ IN DUALSTRINGARRAY * pdsaLocal,
+ OUT DUALSTRINGARRAY * *pdsaRemote
+ );
+
+DUALSTRINGARRAY *CompressStringArray(
+ IN DUALSTRINGARRAY *psaExpanded,
+ IN BOOL fSharedMem
+ );
+
+PWSTR FindMatchingProtseq(
+ IN USHORT cClientProtseqs,
+ IN USHORT aClientProtseqs[],
+ IN PWSTR pwstrServerBindings
+ );
+
+PWSTR FindMatchingProtseq(
+ IN USHORT protseq,
+ IN PWSTR pswstrBindings
+ );
+
+ORSTATUS MergeBindings(
+ IN DUALSTRINGARRAY *pdsaStringBindings,
+ IN DUALSTRINGARRAY *pdsaSecurityBindings,
+ OUT DUALSTRINGARRAY **ppdsaMergedBindings
+ );
+
+
+#endif // __STRING_HXX
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcom95/time.hxx b/private/ole32/dcomss/objex/shrmem/dcom95/time.hxx
new file mode 100644
index 000000000..5cbae12c2
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcom95/time.hxx
@@ -0,0 +1,113 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Time.hxx
+
+Abstract:
+
+ The CTime class represents time for this process. Instances of this class
+ should be small 4-8 bytes and cheap to create.
+
+ The current implementation is just a wrapper for GetTickCount() which
+ handles overflow.
+ (4GB milliseconds is just under 50 days. This implementation is correctly
+ compare times up to 25 days appart.).
+
+Note:
+ This class should return consistent results even if the system time
+ is set forwards or backwards.
+ (Use GetTickCount() rather then GetSystemTimeAsFileTime()).
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-23-95 Bits 'n pieces
+
+--*/
+
+#ifndef __TIME_HXX
+#define __TIME_HXX
+
+#define TICKS_PER_SECOND (1000) // Ticks are milliseconds
+
+class CTime
+ {
+ private:
+ DWORD _Time;
+
+ public:
+
+ CTime() { SetNow(); }
+
+ // Used to avoid a call to GetTickCount()
+ CTime(DWORD time) : _Time(time) { }
+
+ void
+ SetNow() {
+ _Time = GetTickCount();
+ }
+
+ void
+ Sleep()
+ {
+ DWORD diff = _Time - GetTickCount();
+ if ( diff > (2 * BaseTimeoutInterval) * 1000 )
+ {
+ // Maybe overactive under stress. We're trying to sleep until a time
+ // which has already passed.
+ OrDbgDetailPrint(("Didn't need to sleep until %d from %d\n", _Time, GetTickCount()));
+ return;
+ }
+ SleepEx(diff, FALSE);
+ }
+
+ operator DWORD()
+ {
+ return _Time;
+ }
+
+ BOOL operator< (const CTime &Time)
+ {
+ // Is _Time less then Time.
+ DWORD diff = _Time - Time._Time;
+ return( ((LONG)diff) < 0);
+ }
+
+ BOOL operator> (const CTime &Time)
+ {
+ // Is _Time greater then Time.
+ DWORD diff = Time._Time - _Time;
+ return( ((LONG)diff) < 0);
+ }
+
+ BOOL operator<= (const CTime &Time)
+ {
+ return(! operator>(Time));
+ }
+
+ BOOL operator>= (const CTime &Time)
+ {
+ return(! operator<(Time));
+ }
+
+ void operator+=(UINT mSeconds) { _Time += (mSeconds * TICKS_PER_SECOND); }
+
+ void operator-=(UINT mSeconds) { _Time -= (mSeconds * TICKS_PER_SECOND); }
+
+ DWORD operator-(const CTime &Time)
+ {
+ return((_Time - Time._Time)/TICKS_PER_SECOND);
+ }
+
+ // defualt = operator ok.
+
+ };
+
+#endif __TIME_HXX
+
diff --git a/private/ole32/dcomss/objex/shrmem/dcomss.h b/private/ole32/dcomss/objex/shrmem/dcomss.h
new file mode 100644
index 000000000..15fe0ee5d
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dcomss.h
@@ -0,0 +1,81 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ dcomss.h
+
+Abstract:
+
+ Common services provided by core the orpcss service.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 06-14-95 Bits 'n pieces
+
+--*/
+
+#ifndef __DCOMSS_H
+#define __DCOMSS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _CHICAGO_
+#include <nt.h>
+#include <ntdef.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#endif
+
+#include <windows.h>
+
+#if DBG && !defined(DEBUGRPC)
+#define DEBUGRPC
+#endif
+
+// Endpoint related functions
+
+USHORT GetProtseqId(PWSTR Protseq);
+USHORT GetProtseqIdAnsi(PSTR Protseq);
+PWSTR GetProtseq(USHORT ProtseqId);
+PWSTR GetEndpoint(USHORT ProtseqId);
+RPC_STATUS UseProtseqIfNecessary(USHORT id);
+RPC_STATUS DelayedUseProtseq(USHORT id);
+VOID CompleteDelayedUseProtseqs();
+BOOL IsLocal(USHORT ProtseqId);
+DWORD RegisterAuthInfoIfNecessary();
+
+
+extern BOOL gfRegisteredAuthInfo;
+
+extern BOOL s_fEnableDCOM; // Set by StartObjectExporter.
+
+
+// Shared by wrapper\epts.c and olescm\clsdata.cxx.
+
+typedef enum {
+ STOPPED = 1,
+ START,
+ STARTED
+ } PROTSEQ_STATE;
+
+typedef struct {
+ PROTSEQ_STATE state;
+ PWSTR pwstrProtseq;
+ PWSTR pwstrEndpoint;
+ } PROTSEQ_INFO;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/private/ole32/dcomss/objex/shrmem/dirs b/private/ole32/dcomss/objex/shrmem/dirs
new file mode 100644
index 000000000..c449681f1
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/dirs
@@ -0,0 +1,32 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS= \
+ dcom95
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS=
diff --git a/private/ole32/dcomss/objex/shrmem/intor.hxx b/private/ole32/dcomss/objex/shrmem/intor.hxx
new file mode 100644
index 000000000..41a99e066
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/intor.hxx
@@ -0,0 +1,26 @@
+#ifndef __INTOR_HXX__
+#define __INTOR_HXX__
+
+#include <or.h> // for ORSTATUS definition
+
+error_status_t __declspec(dllexport)
+ConnectDCOM(
+ OUT HPROCESS *phProcess,
+ OUT ULONG *pdwTimeoutInSeconds,
+ OUT MID *pLocalMid,
+ OUT ULONG *pfConnectFlags,
+ OUT DWORD *pAuthnLevel,
+ OUT DWORD *pImpLevel,
+ OUT DWORD *pcServerSvc,
+ OUT USHORT **aServerSvc,
+ OUT DWORD *pcClientSvc,
+ OUT USHORT **aClientSvc,
+ OUT DWORD *pThreadID
+ );
+
+ORSTATUS __declspec(dllexport)
+StartDCOM(
+ void
+ );
+
+#endif // __INTOR_HXX__
diff --git a/private/ole32/dcomss/objex/shrmem/makefil0 b/private/ole32/dcomss/objex/shrmem/makefil0
new file mode 100644
index 000000000..e6c5a5035
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/makefil0
@@ -0,0 +1,43 @@
+#
+# This is the MIDL compile phase of the build process.
+#
+# The following is where you put the name of your .idl file without
+# the .idl extension:
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.plt
+
+INCS = -I..\runtime\mtrt\nt -I..\runtime\mtrt \
+ -I$(_NTDRIVE)\nt\private\dcomidl -I$(_NTDRIVE)\nt\public\sdk\inc
+
+SHARE_MIDL = \
+ .\test.h .\test_c.c .\test_s.c
+
+TARGETS = test.h
+
+RPC_FLAGS = -ms_ext -c_ext -error allocation -oldnames -error ref
+
+CPP = -cpp_cmd "$(MIDL_CPP)" $(MIDL_FLAGS)
+
+
+allidl: $(TARGETS)
+!IF "$(BUILDMSG)" != ""
+ @ech ; $(BUILDMSG) ;
+!ENDIF
+
+clean: delete_source allidl
+
+delete_source:
+ -erase $(SHARE_MIDL)
+
+#
+# MIDL COMPILE
+#
+
+SSWITCH=-prefix sstub _
+
+test.h : test.idl
+ midl $(CPP) $(SSWITCH) $(INCS) $(RPC_FLAGS) test.idl \
+ -cstub client\test_c.c \
+ -sstub server\test_s.c
+
diff --git a/private/ole32/dcomss/objex/shrmem/or.h b/private/ole32/dcomss/objex/shrmem/or.h
new file mode 100644
index 000000000..b647a8992
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/or.h
@@ -0,0 +1,139 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ or.h
+
+Abstract:
+
+ General include file for C things the OR. This file is pre-compiled.
+
+Author:
+
+ Mario Goertzel [mariogo] Feb-10-95
+ Satish Thatte [SatishT] Feb-22-96 modified for DCOM95
+
+Revision History:
+
+--*/
+
+#ifndef __OR_H
+#define __OR_H
+
+#include <ole2int.h> // ComDebOut, etc
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _CHICAGO_
+#include <dcomss.h> // BUGBUG: reduce and copy here
+#endif
+
+#include <stddef.h>
+#include <debnot.h> // debugging stuff
+
+#include <objex.h> // Remote OR if from private\dcomidl
+#include <orcb.h> // Callback if from private\dcomidl
+#include <odeth.h> // ORPC OID rundown interface
+#include <rawodeth.h> // Raw RPC -> ORPC OID rundown interface
+#include <olerem.h> // MOXID, REFMOXID, etc
+#include <tls.h> // OLE thread local storage
+
+#define IN
+#define OUT
+#define CONST const
+
+#define WSTR(s) L##s
+
+#define OrStringCompare(str1, str2, len) wcscmp((str1), (str2), (len))
+#define OrStringLen(str) wcslen(str)
+#define OrStringCat(str1, str2) wcscat((str1), (str2))
+#define OrStringCopy(str1, str2) wcscpy((str1), (str2))
+#define OrMemorySet(p, value, len) memset((p), (value), (len))
+#define OrMemoryCompare(p1, p2, len) memcmp((p1), (p2), (len))
+#define OrMemoryCopy(dest, src, len) memcpy((dest), (src), (len))
+// OrStringSearch in or.hxx
+
+//
+// The OR uses Win32 (RPC) error codes.
+//
+
+typedef LONG ORSTATUS;
+
+// When the OR code asigns and error it uses
+// one of the following mappings:
+// There are no internal error codes.
+
+#define OR_OK RPC_S_OK
+#define OR_NOMEM RPC_S_OUT_OF_MEMORY
+#define OR_NORESOURCE RPC_S_OUT_OF_RESOURCES
+#define OR_NOACCESS ERROR_ACCESS_DENIED
+#define OR_BADOXID OR_INVALID_OXID
+#define OR_BADOID OR_INVALID_OID
+#define OR_BADSET OR_INVALID_SET
+#define OR_BAD_SEQNUM OR_INVALID_SET // BUGBUG: need to change
+#define OR_NOSERVER RPC_S_SERVER_UNAVAILABLE
+#define OR_BADPARAM ERROR_INVALID_PARAMETER
+
+// Should NEVER be seen outside the OR.
+#define OR_BUGBUG RPC_S_INTERNAL_ERROR
+#define OR_INTERNAL_ERROR RPC_S_INTERNAL_ERROR
+#define OR_BAD_LOAD_ADDR RPC_S_INTERNAL_ERROR
+#define OR_REPEAT_START RPC_S_INTERNAL_ERROR
+
+// Internal codes used to indicate a special event.
+#define OR_I_RETRY 0xC0210051UL
+#define OR_I_NOPROTSEQ 0xC0210052UL
+
+#define UNUSED(_x_) ((void *)(_x_))
+
+#if DBG
+
+extern int __cdecl ValidateError(
+ IN ORSTATUS Status,
+ IN ...);
+
+
+#define VALIDATE(X) if (!ValidateError X) ASSERT(0);
+
+#ifndef _CHICAGO_
+
+#define OrDbgPrint(X) DbgPrint X
+#define OrDbgDetailPrint(X) DbgPrint X
+
+#else
+
+#define OrDbgPrint(X)
+#define OrDbgDetailPrint(X)
+
+#endif
+
+#undef ASSERT
+#ifndef _CHICAGO_
+#define ASSERT( exp ) \
+ if (! (exp) ) \
+ { \
+ DbgPrint("OR: Assertion failed: %s(%d) %s\n", __FILE__, __LINE__, #exp); \
+ DebugBreak(); \
+ }
+#else // _CHICAGO_
+#define ASSERT( exp ) if (! (exp) ) DebugBreak();
+#endif // _CHICAGO_
+
+
+#else // DBG
+#define VALIDATE(X)
+#define OrDbgPrint(X)
+#define OrDbgDetailPrint(X)
+#endif // DBG
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __OR_H
+
diff --git a/private/ole32/dcomss/objex/shrmem/or.hxx b/private/ole32/dcomss/objex/shrmem/or.hxx
new file mode 100644
index 000000000..e9c97b7af
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/or.hxx
@@ -0,0 +1,160 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ or.hxx
+
+Abstract:
+
+ C++ include for C++ OR modules.
+
+Author:
+
+ Mario Goertzel [mariogo] Feb-10-95
+
+Revision History:
+
+--*/
+
+#ifndef __OR_HXX
+#define __OR_HXX
+
+#include <or.h>
+
+// Protcol defined timeouts
+
+const unsigned short BasePingInterval = 10;
+const unsigned short BaseNumberOfPings = 3;
+const unsigned short BaseTimeoutInterval = (BasePingInterval * BaseNumberOfPings);
+const unsigned short InitialProtseqBufferLength = 118;
+
+// Well known tower IDs
+
+const unsigned short ID_LPC = 0x10; // ncalrpc, IsLocal() == TRUE
+const unsigned short ID_WMSG = 0x01; // mswmsg, IsLoclal() == TRUE
+const unsigned short ID_NP = 0x0F; // ncacn_np, IsLocal() == FALSE
+
+// Timer ID
+
+#define IDT_DCOM_RUNDOWN 1234
+
+// Shared memory constants
+
+const ULONG DCOMSharedHeapName = 1111;
+#define DCOMSharedGlobalBlockName L"DCOMSharedGlobals12321"
+
+// Name of global mutex used to protect shred memory structures
+#define GLOBAL_MUTEX_NAME TEXT("ObjectResolverGlobalMutex")
+
+// Building blocks
+#include <base.hxx>
+
+#include <ipidtbl.hxx> // OXIDEntry, RUNDOWN_TIMER_INTERVAL
+#include <remoteu.hxx> // gpMTARemoteUnknown, CRemoteUnknown
+
+#include <memapi.hxx> // CPrivAlloc
+
+#include <smemor.hxx> // shared memory OR client interface
+#include <intor.hxx> // internal version of OR client interface
+#include <time.hxx>
+#include <mutex.hxx>
+#include <misc.hxx>
+#include <callid.hxx>
+#include <refobj.hxx>
+#include <string.hxx>
+#include <linklist.hxx>
+#include <gentable.hxx>
+#include <dsa.hxx>
+
+//
+// Class forward declarations
+//
+
+class CMid;
+class COxid;
+class COid;
+class CProcess;
+
+//
+// Global variables and constants
+//
+
+#define OXID_TABLE_SIZE 16
+#define OID_TABLE_SIZE OXID_TABLE_SIZE*11
+#define MID_TABLE_SIZE 16
+#define PROCESS_TABLE_SIZE 16
+#define MAX_PROTSEQ_IDS 100
+
+extern DWORD MyProcessId;
+extern DWORD *gpdwLastCrashedProcessCheckTime;
+extern CSmAllocator gSharedAllocator; // global shared memory allocator
+
+extern DUALSTRINGARRAY *gpLocalDSA; // phony bindings for this machine
+extern MID gLocalMID; // MID of this machine
+extern CMid *gpLocalMid; // Mid object for this machine
+
+extern PWSTR gpwstrProtseqs;
+
+extern CGlobalMutex *gpMutex; // global mutex to protect shared memory
+
+extern LONG *gpIdSequence; // shared sequence for generating IDs
+extern DWORD *gpNextThreadID; // shared apartment ID generator
+extern BOOL DCOM_Started;
+
+extern CProcess *gpProcess; // self pointer
+extern CProcess *gpPingProcess; // pointer to surrogate for ping thread
+
+extern USHORT *gpcRemoteProtseqs; // count of remote protseqs
+extern USHORT *gpRemoteProtseqIds; // array of remote protseq ids
+extern PWSTR gpwstrProtseqs; // remote protseqs strings catenated
+extern PROTSEQ_INFO gaProtseqInfo[];
+
+//
+// Security data passed to processes on connect.
+// BUGBUG: this should be in shared memory to speed startup
+//
+
+extern BOOL s_fEnableDCOM;
+extern DWORD s_lAuthnLevel;
+extern DWORD s_lImpLevel;
+extern BOOL s_fMutualAuth;
+extern BOOL s_fSecureRefs;
+extern DWORD s_cServerSvc;
+extern USHORT *s_aServerSvc;
+extern DWORD s_cClientSvc;
+extern USHORT *s_aClientSvc;
+
+
+//
+// Global tables
+//
+
+//
+// cannot use short forms for table types due to declaration order
+//
+
+extern TCSafeResolverHashTable<COxid> * gpOxidTable;
+extern TCSafeResolverHashTable<COid> * gpOidTable;
+extern TCSafeResolverHashTable<CMid> * gpMidTable;
+extern TCSafeResolverHashTable<CProcess> * gpProcessTable;
+
+// Headers which may use globals
+
+#include <oxid.hxx>
+#include <process.hxx>
+#include <mid.hxx>
+#include <set.hxx>
+#include <globals.hxx>
+
+//
+// Startup routine.
+//
+
+ORSTATUS StartDCOM(void);
+
+#pragma hdrstop
+
+#endif // __OR_HXX
+
diff --git a/private/ole32/dcomss/objex/shrmem/server/makefile b/private/ole32/dcomss/objex/shrmem/server/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/server/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/dcomss/objex/shrmem/server/serv.cxx b/private/ole32/dcomss/objex/shrmem/server/serv.cxx
new file mode 100644
index 000000000..b97f72274
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/server/serv.cxx
@@ -0,0 +1,303 @@
+#include <or.hxx>
+#include <simpleLL.hxx>
+
+DECLARE_INFOLEVEL(Cairole)
+
+DUALSTRINGARRAY *pdsaMyBindings;
+
+OXID Oxid;
+OID aOids[2];
+HPROCESS hProcess;
+
+
+DUALSTRINGARRAY *
+MakeDSA(
+ RPC_BINDING_VECTOR * pbv
+ )
+{
+ PWSTR pwstrT;
+ DUALSTRINGARRAY *pdsaT;
+ PWSTR *aStringBindings;
+ USHORT psaLen;
+ DWORD i;
+ RPC_STATUS status;
+
+ aStringBindings = new PWSTR[pbv->Count];
+
+ // Build array of string bindings for protseqs we're listening to.
+
+ for(psaLen = 0, i = 0; i < pbv->Count; i++)
+ {
+ status = RpcBindingToStringBinding(pbv->BindingH[i], &aStringBindings[i]);
+
+ if (status != RPC_S_OK)
+ {
+ break;
+ }
+
+ ASSERT(aStringBindings[i]);
+
+ psaLen += wcslen(aStringBindings[i]) + 1;
+ }
+
+
+ // string bindings, final null, and two final nulls
+
+ psaLen += 1 + 2;
+
+ pdsaT = new(psaLen * sizeof(WCHAR)) DUALSTRINGARRAY;
+
+ pdsaT->wNumEntries = psaLen;
+ pdsaT->wSecurityOffset = psaLen - 2;
+ pwstrT = pdsaT->aStringArray;
+ memset(pwstrT,0,psaLen * sizeof(WCHAR));
+
+ for (i = 0; i < pbv->Count; i++)
+
+ {
+ OrStringCopy(pwstrT, aStringBindings[i]);
+ pwstrT = OrStringSearch(pwstrT, 0) + 1; // next
+
+ status = RpcStringFree(&aStringBindings[i]);
+ ASSERT(status == RPC_S_OK);
+ }
+
+ ASSERT(dsaValid(pdsaT));
+
+ return pdsaT;
+}
+
+
+void
+ServerSetup()
+{
+ RPC_STATUS status;
+ unsigned int cMinCalls = 1;
+ unsigned int cMaxCalls = 20;
+ unsigned int fDontWait = TRUE;
+ TCHAR * pszStringBinding = NULL;
+ TCHAR * pszProtocolSequence = TEXT("ncalrpc");
+
+ ULONG i, j;
+
+ /*
+
+ WCHAR self[10];
+
+ printf("Self = ");
+ scanf("%S",self);
+ printf("Self = %S\n",self);
+
+ */
+
+ RPC_BINDING_VECTOR * BindingVector;
+
+ status = RpcServerUseProtseq(
+ pszProtocolSequence,
+ cMaxCalls,
+ NULL); // Security descriptor
+
+ /*
+ status = RpcServerUseAllProtseqs(
+ cMaxCalls,
+ NULL); // Security descriptor
+
+ printf("RpcServerUseAllProtseqs returned 0x%x\n", status);
+ if (status)
+ exit(status);
+
+ */
+
+ status = RpcServerRegisterIf(
+ _SharedMemoryTest_ServerIfHandle,
+ NULL, // MgrTypeUuid
+ NULL); // MgrEpv; null means use default
+ printf("RpcServerRegisterIf returned 0x%x\n", status);
+ if (status)
+ exit(status);
+
+ status = RpcServerInqBindings(&BindingVector);
+
+ printf("RpcServerInqBindings returned 0x%x\n", status);
+ if (status)
+ exit(status);
+
+ /*
+
+ WCHAR* entryName = catenate(TEXT("/.:/ShareTest"),self);
+
+ status = RpcNsBindingExport(
+ 0, // no name syntax specified
+ entryName,
+ _SharedMemoryTest_ServerIfHandle,
+ BindingVector,
+ NULL
+ );
+
+ printf("RpcNsBindingExport returned 0x%x\n", status);
+ if (status)
+ exit(status);
+
+ printf("Exported the following string bindings to entry %S:\n",entryName);
+
+ for (j = 0; j < BindingVector->Count; j++)
+ {
+ RpcBindingToStringBinding(
+ BindingVector->BindingH[j],
+ &pszStringBinding
+ );
+ printf("%d) %S\n",j,pszStringBinding);
+ RpcStringFree(&pszStringBinding);
+ }
+
+ */
+
+ status = RpcEpRegister(
+ _SharedMemoryTest_ServerIfHandle,
+ BindingVector,
+ NULL,
+ NULL);
+
+ printf("RpcEpRegister returned 0x%x\n", status);
+ if (status)
+ exit(status);
+
+ pdsaMyBindings = MakeDSA(BindingVector);
+
+ status = RpcServerListen(
+ cMinCalls,
+ cMaxCalls,
+ TRUE);
+ printf("RpcServerListen returned: 0x%x\n", status);
+ if (status)
+ exit(status);
+
+ HANDLE pThreadHandle;
+ unsigned long ThreadID;
+
+ printf("Creating RpcMgmtWaitServerListen Thread\n");
+ pThreadHandle = CreateThread(0, 0,
+ (LPTHREAD_START_ROUTINE) RpcMgmtWaitServerListen, NULL, 0, &ThreadID);
+}
+
+/* server prototype */
+void _RemoteRead(
+ /* [in] */ unsigned long offset,
+ /* [out] */ long __RPC_FAR *value)
+{
+ *value = *OR_FULL_POINTER(long,(int)offset);
+}
+
+CSimpleLinkList OR_BASED *pList;
+CSimpleLinkListIterator *pIter;
+
+/* server prototype */
+void _SendList(
+ /* [in] */ unsigned long list_offset)
+{
+ pIter = new CSimpleLinkListIterator(
+ *OR_FULL_POINTER(CSimpleLinkList,list_offset)
+ );
+}
+
+/* server prototype */
+void _ReadNext(
+ /* [out] */ unsigned long __RPC_FAR *value)
+{
+ *value = (unsigned long) pIter->next();
+}
+
+/* server prototype */
+void _GetIds(
+ /* [out] */ OXID __RPC_FAR *pOxid,
+ /* [out] */ OID __RPC_FAR *pOid)
+{
+ *pOxid = Oxid;
+ *pOid = aOids[0];
+}
+
+/* server prototype */
+void _ShutDown( void)
+{
+ ServerFreeOXID(
+ hProcess,
+ Oxid,
+ 2,
+ aOids
+ );
+}
+
+void
+TestLocalResolverAPI()
+{
+ DWORD dwTimeoutInSeconds;
+ MID LocalMid;
+ BOOL DisableDCOM;
+ DWORD AuthnLevel;
+ DWORD ImpLevel;
+ BOOL MutualAuth;
+ DWORD cServerSvc;
+ USHORT *aServerSvc;
+ DWORD cClientSvc;
+ USHORT *aClientSvc;
+
+ long Status;
+
+ OXID_INFO oxidInfo;
+
+ Status = ConnectDCOM(
+ &hProcess,
+ &dwTimeoutInSeconds,
+ &LocalMid,
+ &DisableDCOM,
+ &AuthnLevel,
+ &ImpLevel,
+ &MutualAuth,
+ &cServerSvc,
+ &aServerSvc,
+ &cClientSvc,
+ &aClientSvc
+ );
+
+ Status = ServerAllocateOXID(
+ hProcess,
+ FALSE,
+ oxidInfo,
+ pdsaMyBindings,
+ Oxid
+ );
+
+ Status = ServerAllocateOID(
+ hProcess,
+ Oxid,
+ aOids[0]
+ );
+
+ Status = ServerAllocateOID(
+ hProcess,
+ Oxid,
+ aOids[1]
+ );
+}
+
+void __cdecl
+main()
+{
+ ServerSetup();
+ TestLocalResolverAPI();
+
+ Sleep(INFINITE);
+}
+
+
+/* MIDL allocate and free */
+
+void __RPC_FAR * __RPC_API midl_user_allocate(size_t len)
+{
+ return(malloc(len));
+}
+
+void __RPC_API midl_user_free(void __RPC_FAR * ptr)
+{
+ free(ptr);
+}
diff --git a/private/ole32/dcomss/objex/shrmem/server/sources b/private/ole32/dcomss/objex/shrmem/server/sources
new file mode 100644
index 000000000..07efa68e9
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/server/sources
@@ -0,0 +1,109 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+!IF "$(NTDEBUG)" != "ntsd"
+CXXCPP_OPTIONS=-DDBG=0
+!else
+CXXCPP_OPTIONS=-DDBG=1
+DEBUG_DEFINES=-DLDEBUG
+MSC_OPTIMIZATION=/Od
+!endif
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= serv
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= ..\bin
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= PROGRAM
+
+#PRECOMPILED_INCLUDE= ..\or.hxx
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+LIBDIR=$(_NTDRIVE)\nt\public\sdk\lib
+
+OLEDIR=$(_NTDRIVE)\nt\private\ole32
+
+!include $(OLEDIR)\daytona.inc
+
+INCLUDES=..;..\dcom95;..\stg;$(OLEDIR)\dcomss;$(OLEDIR)\ih;$(OLEDIR)\com\inc;$(OLEDIR)\common\daytona;$(OLEDIR)\stg\docfile;$(OLEDIR)\stg\h;\nt\private\types\new_ole;C:\nt\private\dcomidl\obj;$(OLEDIR)\stg\exp
+
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DMULTIHEAP
+
+SOURCES= \
+ serv.cxx \
+ test_s.c
+
+LINKLIBS=$(LIBDIR)\*\Rpcrt4.lib \
+ $(LIBDIR)\*\RpcNdr.lib \
+ $(LIBDIR)\*\ntdll.lib \
+ $(LIBDIR)\*\uuid.lib \
+ $(LIBDIR)\*\user32.lib \
+ $(LIBDIR)\*\security.lib \
+ $(LIBDIR)\*\ole32.lib \
+ $(OLEDIR)\common\daytona\obj\*\common.lib \
+ $(OLEDIR)\com\inc\daytona\obj\*\inc.lib \
+ ..\lib\*\stg.lib \
+ ..\lib\*\dcom95.lib \
+
+USE_LIBCMT=1
+
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+PRECOMPILED_OPTION=
+#PRECOMPILED_TARGET=..\obj\*\$(PRECOMPILED_PCH)
+PRECOMPILED_CXX=
+
diff --git a/private/ole32/dcomss/objex/shrmem/smemor.hxx b/private/ole32/dcomss/objex/shrmem/smemor.hxx
new file mode 100644
index 000000000..e28e3e8a8
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/smemor.hxx
@@ -0,0 +1,127 @@
+#ifndef __SMEMOR_HXX__
+#define __SMEMOR_HXX__
+
+#define CONNECT_DISABLEDCOM ( 0x1 )
+#define CONNECT_MUTUALAUTH ( 0x2 )
+#define CONNECT_SECUREREF ( 0x4 )
+
+class CProcess;
+
+typedef CProcess *HPROCESS;
+
+error_status_t __declspec(dllexport)
+AllocateReservedIds(
+ IN long cIdsToReserve,
+ OUT ID *pidReservedBase);
+
+ error_status_t __declspec(dllexport)
+ Connect(
+ OUT HPROCESS *phProcess,
+ OUT ULONG *pdwTimeoutInSeconds,
+ OUT DUALSTRINGARRAY **ppdsaOrBindings,
+ OUT MID *pLocalMid,
+ IN long cIdsToReserve,
+ OUT ID *pidReservedBase,
+ OUT ULONG *pfConnectFlags,
+ OUT DWORD *pAuthnLevel,
+ OUT DWORD *pImpLevel,
+ OUT DWORD *pcServerSvc,
+ OUT USHORT **aServerSvc,
+ OUT DWORD *pcClientSvc,
+ OUT USHORT **aClientSvc,
+ OUT DWORD *pThreadID);
+
+error_status_t __declspec(dllexport)
+Disconnect(
+ IN OUT HPROCESS *phProcess);
+
+error_status_t __declspec(dllexport)
+ClientResolveOXID(
+ IN HPROCESS hProcess,
+ IN OXID *poxidServer,
+ IN DUALSTRINGARRAY *pssaServerObjectResolverBindings,
+ IN long fApartment,
+ OUT OXID_INFO *poxidInfo,
+ OUT MID *pLocalMidOfRemote);
+
+error_status_t __declspec(dllexport)
+ServerAllocateOXIDAndOIDs(
+ IN HPROCESS hProcess,
+ OUT OXID *poxidServer,
+ IN long fApartment,
+ IN unsigned long cOids,
+ OUT OID aOid[ ],
+ OUT unsigned long *pcOidsAllocated,
+ IN OXID_INFO *pOxidInfo,
+ IN DUALSTRINGARRAY *pdsaStringBindings,
+ IN DUALSTRINGARRAY *pdsaSecurityBindings);
+
+error_status_t __declspec(dllexport)
+ServerAllocateOIDs(
+ IN HPROCESS hProcess,
+ IN OXID *poxidServer,
+ IN unsigned long cOids,
+ OUT OID aOid[ ],
+ OUT unsigned long *pcOidsAllocated);
+
+error_status_t __declspec(dllexport)
+ServerFreeOXIDAndOIDs(
+ IN HPROCESS hProcess,
+ IN OXID oxidServer,
+ IN unsigned long cOids,
+ IN OID aOids[ ]);
+
+#define OR_PARTIAL_UPDATE ( 1003L )
+
+error_status_t __declspec(dllexport)
+ClientAddOID(
+ IN HPROCESS hProcess,
+ IN OID OidToBeAdded,
+ IN OXID OxidForOid,
+ IN MID MidForOxid
+ );
+
+error_status_t __declspec(dllexport)
+ClientDropOID(
+ IN HPROCESS hProcess,
+ IN OID OidToBeRemoved,
+ IN MID Mid
+ );
+
+error_status_t __declspec(dllexport)
+GetOXID(
+ IN HPROCESS hProcess,
+ IN OXID Oxid,
+ IN DUALSTRINGARRAY *pdsaServerObjectResolverBindings,
+ IN long fApartment,
+ IN USHORT wProtseqId,
+ OUT OXID_INFO &OxidInfo,
+ OUT MID &LocalMidOfRemote
+ );
+
+error_status_t __declspec(dllexport)
+ServerAllocateOXID(
+ IN HPROCESS hProcess,
+ IN long fApartment,
+ IN OXID_INFO *pOxidInfo,
+ IN DUALSTRINGARRAY *pdsaStringBindings,
+ OUT OXID &Oxid
+ );
+
+error_status_t __declspec(dllexport)
+ServerAllocateOID(
+ IN HPROCESS hProcess,
+ IN OXID Oxid,
+ OUT OID &Oid
+ );
+
+
+error_status_t __declspec(dllexport)
+ServerFreeOXID(
+ IN HPROCESS hProcess,
+ IN OXID oxidServer,
+ IN unsigned long cOids,
+ IN OID aOids[ ]
+ );
+
+#endif // __SMEMOR_HXX__
diff --git a/private/ole32/dcomss/objex/shrmem/stg/daytona/makefile b/private/ole32/dcomss/objex/shrmem/stg/daytona/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/stg/daytona/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/dcomss/objex/shrmem/stg/daytona/sources b/private/ole32/dcomss/objex/shrmem/stg/daytona/sources
new file mode 100644
index 000000000..efdc35fe6
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/stg/daytona/sources
@@ -0,0 +1,64 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= stg
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= ..\..\lib
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+!include ..\..\daytona.inc
+
+SOURCES= \
+ ..\simplell.cxx \
+ ..\dfdbg.cxx \
+ ..\fastlock.cxx \
+ ..\smalloc.cxx
+
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+UMLIBS=
diff --git a/private/ole32/dcomss/objex/shrmem/stg/dfdbg.cxx b/private/ole32/dcomss/objex/shrmem/stg/dfdbg.cxx
new file mode 100644
index 000000000..3e05ed8ae
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/stg/dfdbg.cxx
@@ -0,0 +1,744 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992
+//
+// File: debug.cxx
+//
+// Contents: Debugging routines
+//
+// History: 07-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <or.hxx>
+
+#include <debug.hxx>
+
+#if DBG == 1
+
+#include <stdarg.h>
+#include <dfdeb.hxx>
+#include <logfile.hxx>
+#include <df32.hxx>
+
+//+-------------------------------------------------------------
+//
+// Function: DfDebug, public
+//
+// Synopsis: Sets debugging level
+//
+//---------------------------------------------------------------
+
+DECLARE_INFOLEVEL(ol);
+
+/*
+
+#define LOGFILENAME L"logfile.txt"
+
+static CGlobalFileStream *_pgfstLogFiles = NULL;
+WCHAR gwcsLogFile[] = LOGFILENAME;
+
+STDAPI_(void) DfDebug(ULONG ulLevel, ULONG ulMSFLevel)
+{
+#if DBG == 1
+ olInfoLevel = ulLevel;
+// SetInfoLevel(ulMSFLevel);
+ _SetWin4InfoLevel(ulLevel | ulMSFLevel);
+
+ olDebugOut((DEB_ITRACE, "\n-- DfDebug(0x%lX, 0x%lX)\n",
+ ulLevel, ulMSFLevel));
+#endif
+}
+
+*/
+
+// NT and Cairo
+#ifdef WIN32
+#if 0
+// Throw Win32 error information
+#define THROW_LAST_ERROR() THROW_SC(LAST_SCODE)
+
+//+---------------------------------------------------------------------------
+//
+// Class: CDfGlobalMemory (dgm)
+//
+// Purpose: Create a fixed size chunk of globally shared memory
+//
+// Interface: See below
+//
+// History: 06-May-93 DrewB Created
+//
+// Notes: The init function is only called once when the shared
+// memory is first created.
+//
+// The end function is only called once when the last
+// reference to the global memory is released
+//
+// The reference count is added onto the global allocation
+// and kept at offset zero so the address returned to
+// client code is offset by sizeof(LONG)
+//
+//----------------------------------------------------------------------------
+
+typedef void (*DfGlobalMemoryFn)(void *);
+
+class CDfGlobalMemory
+{
+public:
+ CDfGlobalMemory(TCHAR const *ptcsName,
+ DWORD cbSize,
+ DfGlobalMemoryFn pfnInit,
+ DfGlobalMemoryFn pfnEnd);
+ ~CDfGlobalMemory(void);
+
+ inline void *GetAddress(void) const;
+
+private:
+ inline LONG *RefCount(void);
+
+ HANDLE _hMapping;
+ void *_pvMemory;
+ DfGlobalMemoryFn _pfnEnd;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDfGlobalMemory::GetAddress, public
+//
+// Synopsis: Returns the address of the shared memory
+//
+// History: 06-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void *CDfGlobalMemory::GetAddress(void) const
+{
+ return (void *)((LONG *)_pvMemory+1);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDfGlobalMemory::RefCount, private
+//
+// Synopsis: Returns a pointer to the reference count
+//
+// History: 07-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline LONG *CDfGlobalMemory::RefCount(void)
+{
+ return (LONG *)_pvMemory;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDfGlobalMemory::CDfGlobalMemory, public
+//
+// Synopsis: Creates a chunk of global memory
+//
+// Arguments: [ptcsName] - Name for sharing
+// [cbSize] - Size of chunk
+// [pfnInit] - Initialization function or NULL
+// [pfnEnd] - Shutdown function or NULL
+//
+// History: 06-May-93 DrewB Created
+//
+// Notes: Allowed to throw on failure; this is debug only code
+//
+//----------------------------------------------------------------------------
+
+CDfGlobalMemory::CDfGlobalMemory(TCHAR const *ptcsName,
+ DWORD cbSize,
+ DfGlobalMemoryFn pfnInit,
+ DfGlobalMemoryFn pfnEnd)
+{
+ BOOL fOpened;
+#if WIN32 == 100 || WIN32 > 200
+ CGlobalSecurity gs;
+ SCODE sc;
+
+ if (FAILED(sc = gs.Init()))
+ THROW_SC(sc);
+ _hMapping = CreateFileMapping((HANDLE)0xFFFFFFFF, gs, PAGE_READWRITE,
+ 0, cbSize+sizeof(LONG), (TCHAR *)ptcsName);
+#else
+ _hMapping = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE,
+ 0, cbSize+sizeof(LONG), (TCHAR *)ptcsName);
+#endif
+ if (_hMapping == NULL)
+ THROW_LAST_ERROR();
+
+ fOpened = GetLastError() == ERROR_ALREADY_EXISTS;
+
+ _pvMemory = MapViewOfFile(_hMapping, FILE_MAP_ALL_ACCESS,
+ 0, 0, 0);
+ if (_pvMemory == NULL)
+ {
+ CloseHandle(_hMapping);
+ THROW_LAST_ERROR();
+ }
+
+ if (pfnInit && !fOpened)
+ {
+ *(RefCount()) = 0;
+ pfnInit(GetAddress());
+ }
+
+ _pfnEnd = pfnEnd;
+ InterlockedIncrement(RefCount());
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDfGlobalMemory::~CDfGlobalMemory, public
+//
+// Synopsis: Releases resources for shared memory
+//
+// History: 06-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CDfGlobalMemory::~CDfGlobalMemory(void)
+{
+ if (InterlockedDecrement(RefCount()) == 0 && _pfnEnd)
+ _pfnEnd(GetAddress());
+
+ UnmapViewOfFile(_pvMemory);
+ CloseHandle(_hMapping);
+}
+#endif //0
+#endif // WIN32
+
+// Resource limits
+
+static LONG lResourceLimits[CDBRESOURCES] =
+{
+ 0x7fffffff, // DBR_MEMORY
+ 0x7fffffff, // DBR_XSCOMMITS
+ 0x0, // DBR_FAILCOUNT
+ 0x0, // DBR_FAILLIMIT
+ 0x0, // DBRQ_MEMORY_ALLOCATED
+ 0x0, // DBRI_ALLOC_LIST
+ 0x0, // DBRI_LOGFILE_LIST
+ 0x0 // DBRF_LOGGING
+};
+
+#define CBRESOURCES sizeof(lResourceLimits)
+
+#if 0
+
+static CStaticDfMutex _sdmtxResources(TSTR("DfResourceMutex"));
+
+static void ResInit(void *pvMemory)
+{
+ // Initialize limits
+ memcpy(pvMemory, lResourceLimits, CBRESOURCES);
+}
+
+static CDfGlobalMemory _dgmResourceLimits(TSTR("DfResourceMemory"),
+ CBRESOURCES,
+ ResInit,
+ NULL);
+
+#define RESLIMIT(n) \
+ (*((LONG *)_dgmResourceLimits.GetAddress()+(n)))
+
+#define TAKEMTX \
+ olVerSucc(_sdmtxResources.Take(INFINITE))
+#define RELEASEMTX \
+ _sdmtxResources.Release();
+
+#else
+
+#define RESLIMIT(n) lResourceLimits[n]
+#define TAKEMTX
+#define RELEASEMTX
+
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: DfSetResLimit, public
+//
+// Synopsis: Sets a resource limit
+//
+// History: 24-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(void) DfSetResLimit(UINT iRes, LONG lLimit)
+{
+ TAKEMTX;
+
+ RESLIMIT(iRes) = lLimit;
+
+ RELEASEMTX;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DfGetResLimit, public
+//
+// Synopsis: Gets a resource limit
+//
+// History: 24-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(LONG) DfGetResLimit(UINT iRes)
+{
+ // Doesn't need serialization
+ return RESLIMIT(iRes);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: HaveResource, private
+//
+// Synopsis: Checks to see if a resource limit is exceeded
+// and consumes resource if not
+//
+// History: 24-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+BOOL HaveResource(UINT iRes, LONG lRequest)
+{
+ if (RESLIMIT(iRes) >= lRequest)
+ {
+ TAKEMTX;
+
+ RESLIMIT(iRes) -= lRequest;
+
+ RELEASEMTX;
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ModifyResLimit, private
+//
+// Synopsis: Adds to a resource limit
+//
+// History: 24-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+LONG ModifyResLimit(UINT iRes, LONG lChange)
+{
+ LONG l;
+
+ TAKEMTX;
+
+ RESLIMIT(iRes) += lChange;
+ l = RESLIMIT(iRes);
+
+ RELEASEMTX;
+
+ return l;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SimulateFailure
+//
+// Synopsis: Check for simulated failure
+//
+// Effects: Tracks failure count
+//
+// Arguments: [failure] -- failure type
+//
+// Returns: TRUE if call should fail, FALSE if call should succeed
+//
+// Modifies: RESLIMIT(DBR_FAILCOUNT)
+//
+// Algorithm: Increment failure count, fail if count has succeeded
+// limit
+//
+// History: 21-Jan-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+BOOL SimulateFailure(DBFAILURE failure)
+{
+ LONG l;
+ BOOL fFail;
+
+ // We don't special case failure types, yet.
+
+ TAKEMTX;
+
+ RESLIMIT(DBR_FAILCOUNT)++;
+ l = RESLIMIT(DBR_FAILLIMIT);
+ fFail = RESLIMIT(DBR_FAILCOUNT) >= l;
+
+ RELEASEMTX;
+
+ if (l == 0)
+ {
+ // We're not simulating any failures; just tracking them
+ return(FALSE);
+ }
+
+ return fFail;
+}
+
+//+--------------------------------------------------------------
+//
+// Class: CChecksumBlock (cb)
+//
+// Purpose: Holds a memory block that is being checksummed
+//
+// Interface: See below
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+class CChecksumBlock
+{
+public:
+ CChecksumBlock(char *pszName,
+ void *pvAddr,
+ ULONG cBytes,
+ DWORD dwFlags,
+ CChecksumBlock *pcbNext,
+ CChecksumBlock *pcbPrev);
+ ~CChecksumBlock(void);
+
+ char *_pszName;
+ void *_pvAddr;
+ ULONG _cBytes;
+ DWORD _dwFlags;
+ CChecksumBlock *_pcbNext, *_pcbPrev;
+ ULONG _ulChecksum;
+};
+
+// Global list of checksummed blocks
+static CChecksumBlock *pcbChkBlocks = NULL;
+
+//+--------------------------------------------------------------
+//
+// Member: CChecksumBlock::CChecksumBlock, private
+//
+// Synopsis: Ctor
+//
+// Arguments: [pszName] - Block name
+// [pvAddr] - Starting addr
+// [cBytes] - Length
+// [dwFlags] - Type flags
+// [pcbNext] - Next checksum block
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CChecksumBlock::CChecksumBlock(char *pszName,
+ void *pvAddr,
+ ULONG cBytes,
+ DWORD dwFlags,
+ CChecksumBlock *pcbNext,
+ CChecksumBlock *pcbPrev)
+{
+ ULONG i;
+ char *pc;
+
+ olVerify(_pszName = new char[strlen(pszName)+1]);
+ strcpy(_pszName, pszName);
+ _pvAddr = pvAddr;
+ _cBytes = cBytes;
+ _dwFlags = dwFlags;
+ _pcbNext = pcbNext;
+ if (pcbNext)
+ pcbNext->_pcbPrev = this;
+ _pcbPrev = pcbPrev;
+ if (pcbPrev)
+ pcbPrev->_pcbNext = this;
+ _ulChecksum = 0;
+ pc = (char *)pvAddr;
+ for (i = 0; i<cBytes; i++)
+ _ulChecksum += *pc++;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CChecksumBlock::~CChecksumBlock, private
+//
+// Synopsis: Dtor
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CChecksumBlock::~CChecksumBlock(void)
+{
+ delete _pszName;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: DbgChkBlocks, private
+//
+// Synopsis: Verify checksums on all current blocks
+//
+// Arguments: [dwFlags] - Types of blocks to check
+// [pszFile] - File check was called from
+// [iLine] - Line in file
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+void DbgChkBlocks(DWORD dwFlags, char *pszFile, int iLine)
+{
+ CChecksumBlock *pcb;
+
+ for (pcb = pcbChkBlocks; pcb; pcb = pcb->_pcbNext)
+ if (pcb->_dwFlags & dwFlags)
+ {
+ ULONG i, ulSum = 0;
+ char *pc;
+
+ for (pc = (char *)pcb->_pvAddr, i = 0; i<pcb->_cBytes; i++)
+ ulSum += *pc++;
+ if (ulSum != pcb->_ulChecksum)
+ olDebugOut((DEB_ERROR, "* Bad checksum %s:%d '%s' %p:%lu *\n",
+ pszFile, iLine, pcb->_pszName,
+ pcb->_pvAddr, pcb->_cBytes));
+ else if (dwFlags & DBG_VERBOSE)
+ olDebugOut((DEB_ERROR, "* Checksum passed %s:%d"
+ " '%s' %p:%lu *\n",
+ pszFile, iLine, pcb->_pszName,
+ pcb->_pvAddr, pcb->_cBytes));
+ }
+}
+
+//+--------------------------------------------------------------
+//
+// Function: DbgAddChkBlock, private
+//
+// Synopsis: Adds a checksum block
+//
+// Arguments: [pszName] - Name of block
+// [pvAddr] - Starting addr
+// [cBytes] - Length
+// [dwFlags] - Type flags
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+void DbgAddChkBlock(char *pszName,
+ void *pvAddr,
+ ULONG cBytes,
+ DWORD dwFlags)
+{
+ CChecksumBlock *pcb;
+
+ olVerify(pcb = new CChecksumBlock(pszName, pvAddr, cBytes,
+ dwFlags, pcbChkBlocks, NULL));
+ pcbChkBlocks = pcb;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: DbgFreeChkBlock, private
+//
+// Synopsis: Removes a block from the list
+//
+// Arguments: [pvAddr] - Block's check address
+//
+// History: 10-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+void DbgFreeChkBlock(void *pvAddr)
+{
+ CChecksumBlock *pcb;
+
+ for (pcb = pcbChkBlocks; pcb; pcb = pcb->_pcbNext)
+ if (pcb->_pvAddr == pvAddr)
+ {
+ if (pcb->_pcbPrev)
+ pcb->_pcbPrev->_pcbNext = pcb->_pcbNext;
+ else
+ pcbChkBlocks = pcb->_pcbNext;
+ if (pcb->_pcbNext)
+ pcb->_pcbNext->_pcbPrev = pcb->_pcbPrev;
+ delete pcb;
+ return;
+ }
+}
+
+//+--------------------------------------------------------------
+//
+// Function: DbgFreeChkBlocks, private
+//
+// Synopsis: Frees all checksum blocks
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+void DbgFreeChkBlocks(void)
+{
+ CChecksumBlock *pcb;
+
+ while (pcbChkBlocks)
+ {
+ pcb = pcbChkBlocks->_pcbNext;
+ delete pcbChkBlocks;
+ pcbChkBlocks = pcb;
+ }
+}
+
+/*
+
+inline CGlobalFileStream *GetGlobalFileStream()
+{
+ return((CGlobalFileStream *)DfGetResLimit(DBRI_LOGFILE_LIST));
+}
+
+inline void SetGlobalFileStream(CGlobalFileStream *pgfst)
+{
+ DfSetResLimit(DBRI_LOGFILE_LIST, (LONG) pgfst);
+}
+
+SCODE GetLogFile(CFileStream **pfs)
+{
+ SCODE sc = S_OK;
+ CFileStream *pfsLoop = NULL;
+
+ *pfs = NULL;
+
+ if (GetGlobalFileStream() == NULL)
+ {
+ IMalloc *pMalloc;
+
+#ifdef WIN32
+ olHChk(DfCreateSharedAllocator(&pMalloc));
+#else
+ olHChk(CoGetMalloc(MEMCTX_SHARED, &pMalloc));
+#endif
+ SetGlobalFileStream(new (pMalloc) CGlobalFileStream(pMalloc,
+ 0, LOGFILEDFFLAGS,
+ LOGFILESTARTFLAGS));
+ pMalloc->Release();
+ }
+
+ if (GetGlobalFileStream() != NULL)
+ {
+ pfsLoop = GetGlobalFileStream()->Find(GetCurrentContextId());
+
+ if (pfsLoop == NULL)
+ {
+ IMalloc *pMalloc;
+#ifdef WIN32
+ olHChk(DfCreateSharedAllocator(&pMalloc));
+#else
+ olHChk(CoGetMalloc(MEMCTX_SHARED, &pMalloc));
+#endif
+
+ pfsLoop = new (pMalloc) CFileStream(pMalloc);
+ pMalloc->Release();
+
+ if (pfsLoop != NULL)
+ pfsLoop->InitFromGlobal(GetGlobalFileStream());
+ }
+ }
+
+EH_Err:
+ *pfs = pfsLoop;
+ return sc;
+}
+
+SCODE _FreeLogFile(void)
+{
+ CFileStream *pfsLoop = NULL;
+
+ if (GetGlobalFileStream())
+ pfsLoop = GetGlobalFileStream()->Find(GetCurrentContextId());
+
+ if (pfsLoop != NULL)
+ {
+ pfsLoop->vRelease();
+ GetGlobalFileStream()->Release();
+ SetGlobalFileStream(NULL);
+ return S_OK;
+ }
+
+ return STG_E_UNKNOWN;
+}
+
+long cLogNestings = 0;
+
+void OutputLogfileMessage(char const *format, ...)
+{
+ int length;
+ char achPreFormat[] = "PID[%lx] TID[%lx] ";
+ char achBuffer[256];
+ ULONG cbWritten;
+ CFileStream *pfs = NULL;
+ va_list arglist;
+ STATSTG stat;
+
+ if (cLogNestings > 0)
+ return;
+
+ TAKEMTX;
+ cLogNestings++;
+
+ va_start(arglist, format);
+
+ GetLogFile(&pfs);
+
+ if (NULL != pfs)
+ {
+ pfs->Init(gwcsLogFile);
+ pfs->Stat(&stat, STATFLAG_NONAME);
+
+ if (DfGetResLimit(DBRF_LOGGING) & DFLOG_PIDTID)
+ {
+ // Prepare prefix string
+ length = wsprintfA(achBuffer, "PID[%8lx] TID[%8lx] ",
+ GetCurrentProcessId(), GetCurrentThreadId());
+
+ // length does not include NULL terminator
+
+ pfs->WriteAt(stat.cbSize, achBuffer, length, &cbWritten);
+ stat.cbSize.LowPart += cbWritten;
+ }
+
+ // Write caller data to logfile
+#if WIN32 == 300
+ wsprintfA(achBuffer, format, arglist);
+#else
+ w4vsprintf(achBuffer, format, arglist);
+#endif
+
+ length = strlen(achBuffer);
+ for (int i = 0; i < length; i++)
+ {
+ if (((achBuffer[i] < 32) || (achBuffer[i] > 127)) &&
+ (achBuffer[i] != '\n') && (achBuffer[i] != '\t'))
+ {
+ achBuffer[i] = '.';
+ }
+ }
+
+ pfs->WriteAt(stat.cbSize, achBuffer, length, &cbWritten);
+ }
+
+ cLogNestings--;
+ RELEASEMTX;
+}
+
+
+*/
+
+#endif // DBG == 1
diff --git a/private/ole32/dcomss/objex/shrmem/stg/dirs b/private/ole32/dcomss/objex/shrmem/stg/dirs
new file mode 100644
index 000000000..869a606d0
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/stg/dirs
@@ -0,0 +1,27 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=
+
+OPTIONAL_DIRS= \
+ daytona
+
diff --git a/private/ole32/dcomss/objex/shrmem/stg/fastlock.cxx b/private/ole32/dcomss/objex/shrmem/stg/fastlock.cxx
new file mode 100644
index 000000000..b810a7705
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/stg/fastlock.cxx
@@ -0,0 +1,433 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992
+//
+// File: fastlock.cxx
+//
+// Contents: Implementation of CDfMutex methods for DocFiles
+//
+// History: 26-Jul-94 DonnaLi Created
+//
+//---------------------------------------------------------------
+
+#include <or.hxx>
+
+#ifdef UNICODE
+#define GLOBAL_CS L"GlobalCsMutex"
+#else
+#define GLOBAL_CS "GlobalCsMutex"
+#endif
+
+//
+// This is the number of characters to skip over in the name
+// pased to CDfMutex::Init. The name consists of the string
+// OleDfRoot followed by the hex representation of a unique
+// number for each Docfile. We skip CHARS_TO_SKIP number of
+// characters in the name to produce a related and yet unique
+// name for the file mapping containing global state for the
+// critical section.
+//
+#define CHARS_TO_SKIP 3
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDfMutex::Init, public
+//
+// Synopsis: This routine creates and initializes the global
+// critical section if it does not already exist.
+// It then attaches to the global critical section.
+//
+// Arguments: [lpName] - Supplies the critical section name
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-94 DonnaLi Created
+//
+// Algorithm: Uses a mutex to serialize global critical section
+// creation and initialization
+// The name passed in is used to create or open the
+// semaphore embedded in the global critical section.
+// The name with the first CHARS_TO_SKIP characters
+// skipped is used to create or open the file mapping
+// containing global state of the critical section.
+// If a file mapping with that name already exists,
+// it is not reinitialized. The caller instead just
+// attaches to it.
+//
+//---------------------------------------------------------------
+
+SCODE
+CDfMutex::Init(
+ TCHAR * lpName
+ )
+{
+ HANDLE hGlobalMutex;
+ SCODE scResult = S_OK;
+ DWORD dwResult;
+ LPSECURITY_ATTRIBUTES lpsa = NULL;
+
+#if WIN32 == 100 || WIN32 > 200
+ CGlobalSecurity gs;
+ if (FAILED(scResult = gs.Init())) return scResult;
+#else
+ LPSECURITY_ATTRIBUTES gs = NULL;
+#endif
+
+ //
+ // Serialize all global critical section initialization
+ //
+
+ hGlobalMutex = CreateMutex(
+ gs, // LPSECURITY_ATTRIBUTES lpsa
+ TRUE, // BOOL fInitialOwner
+ GLOBAL_CS // LPCTSTR lpszMutexName
+ );
+
+ //
+ // If the mutex create/open failed, then bail
+ //
+
+ if ( !hGlobalMutex )
+ {
+ return LAST_SCODE;
+ }
+
+ if ( GetLastError() == ERROR_ALREADY_EXISTS )
+ {
+
+ //
+ // Since the mutex already existed, the request for ownership has
+ // no effect.
+ //
+ // wait for the mutex
+ //
+
+ if ( WaitForSingleObject (hGlobalMutex, INFINITE) == WAIT_FAILED )
+ {
+ scResult = LAST_SCODE;
+ CloseHandle (hGlobalMutex);
+ return scResult;
+ }
+ }
+
+ //
+ // We now own the global critical section creation mutex. Create/Open the
+ // named semaphore.
+ //
+
+ _hLockSemaphore = CreateSemaphore (
+ gs, // LPSECURITY_ATTRIBUTES lpsa
+ 0, // LONG cSemInitial
+ MAXLONG-1, // LONG cSemMax
+ lpName // LPCTSTR lpszSemName
+ );
+
+ //
+ // If the semaphore create/open failed, then bail
+ //
+
+ if ( !_hLockSemaphore )
+ {
+ scResult = LAST_SCODE;
+ }
+ else
+ {
+ //
+ // Create/open a shared file mapping object
+ // If we created it, we need to initialize the global structure.
+ // Otherwise just point to it.
+ // The global critical section creation mutex allows us to do
+ // this safely.
+ //
+
+ _hSharedMapping = CreateFileMapping (
+ (HANDLE)0xffffffff, // HANDLE hFile
+ gs, // LPSECURITY_ATTRIBUTES lpsa
+ PAGE_READWRITE, // DWORD fdwProtect
+ 0, // DWORD dwMaximumSizeHigh
+ 1024, // DWORD dwMaximumSizeLow
+ lpName+CHARS_TO_SKIP// LPCTSTR lpszMapName
+ );
+
+ if ( !_hSharedMapping )
+ {
+ scResult = LAST_SCODE;
+ CloseHandle (_hLockSemaphore);
+ _hLockSemaphore = (HANDLE)NULL;
+ }
+ else
+ {
+ dwResult = GetLastError();
+
+ _pGlobalPortion = (PGLOBAL_SHARED_CRITICAL_SECTION)
+ MapViewOfFile (
+ _hSharedMapping, // HANDLE hMapObject
+ FILE_MAP_WRITE, // DWORD fdwAccess
+ 0, // DWORD dwOffsetHigh
+ 0, // DWORD dwOffsetLow
+ 0 // DWORD cbMap
+ );
+
+ if (!_pGlobalPortion)
+ {
+ scResult = LAST_SCODE;
+ CloseHandle (_hLockSemaphore);
+ _hLockSemaphore = (HANDLE)NULL;
+ CloseHandle (_hSharedMapping);
+ _hSharedMapping = (HANDLE)NULL;
+ }
+ else if (dwResult != ERROR_ALREADY_EXISTS )
+ {
+ //
+ // We created the file mapping, so initialize the
+ // global portion.
+ //
+
+ _pGlobalPortion->LockCount = -1;
+#ifdef SUPPORT_RECURSIVE_LOCK
+ _pGlobalPortion->RecursionCount = 0;
+ _pGlobalPortion->OwningThread = 0;
+#else
+#if DBG == 1
+ _pGlobalPortion->OwningThread = 0;
+#endif
+#endif
+ _pGlobalPortion->Reserved = 0;
+ }
+ }
+ }
+
+
+ ReleaseMutex (hGlobalMutex);
+ CloseHandle (hGlobalMutex);
+
+ return scResult;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDfMutex::~CDfMutex, public
+//
+// Synopsis: This routine detaches from an existing global
+// critical section.
+//
+// History: 26-Jul-94 DonnaLi Created
+//
+// Algorithm: Create or get the entry from the multistream
+//
+//---------------------------------------------------------------
+
+CDfMutex::~CDfMutex(
+ void
+ )
+{
+ //If we're holding the mutex, we need to get rid of it here.
+
+#ifdef SUPPORT_RECURSIVE_LOCK
+ if ((_pGlobalPortion) &&
+ (_pGlobalPortion->OwningThread == GetCurrentThreadId()))
+ {
+#else
+ if (_pGlobalPortion)
+ {
+#if DBG == 1
+ olAssert (_pGlobalPortion->OwningThread == 0 || _pGlobalPortion->OwningThread == GetCurrentThreadId());
+#endif
+#endif
+ Release();
+ }
+
+ if ( _pGlobalPortion )
+ {
+ UnmapViewOfFile (_pGlobalPortion);
+ }
+
+ if ( _hLockSemaphore )
+ {
+ CloseHandle (_hLockSemaphore);
+ }
+ if ( _hSharedMapping )
+ {
+ CloseHandle (_hSharedMapping);
+ }
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDfMutex::Take, public
+//
+// Synopsis: This routine enters the global critical section.
+//
+// Arguments: [dwTimeout] - Supplies the timeout
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-94 DonnaLi Created
+//
+// Algorithm: Enters the critical section if nobody owns it or
+// if the current thread already owns it.
+// Waits for the critical section otherwise.
+//
+//---------------------------------------------------------------
+
+SCODE
+CDfMutex::Take (
+ DWORD dwTimeout
+ )
+{
+ olAssert (_pGlobalPortion->LockCount >= -1);
+
+#ifdef SUPPORT_RECURSIVE_LOCK
+
+ olAssert (_pGlobalPortion->RecursionCount >= 0);
+
+ DWORD ThreadId;
+
+ ThreadId = GetCurrentThreadId();
+
+#endif
+
+ //
+ // Increment the lock variable. On the transition to 0, the caller
+ // becomes the absolute owner of the lock. Otherwise, the caller is
+ // either recursing, or is going to have to wait
+ //
+
+ if ( !InterlockedIncrement (&_pGlobalPortion->LockCount) )
+ {
+ //
+ // lock count went from -1 to 0, so the caller
+ // is the owner of the lock
+ //
+
+#ifdef SUPPORT_RECURSIVE_LOCK
+ _pGlobalPortion->RecursionCount = 1;
+ _pGlobalPortion->OwningThread = ThreadId;
+#else
+#if DBG == 1
+ _pGlobalPortion->OwningThread = GetCurrentThreadId();
+#endif
+#endif
+ return S_OK;
+ }
+ else
+ {
+#ifdef SUPPORT_RECURSIVE_LOCK
+ //
+ // If the caller is recursing, then increment the recursion count
+ //
+
+ if ( _pGlobalPortion->OwningThread == ThreadId )
+ {
+ _pGlobalPortion->RecursionCount++;
+ return S_OK;
+ }
+ else
+ {
+#else
+#if DBG == 1
+ olAssert (_pGlobalPortion->OwningThread != GetCurrentThreadId());
+#endif
+#endif
+ switch (WaitForSingleObject(
+ _hLockSemaphore,
+ dwTimeout
+ ))
+ {
+ case WAIT_OBJECT_0:
+ case WAIT_ABANDONED:
+#ifdef SUPPORT_RECURSIVE_LOCK
+ _pGlobalPortion->RecursionCount = 1;
+ _pGlobalPortion->OwningThread = ThreadId;
+#else
+#if DBG == 1
+ _pGlobalPortion->OwningThread = GetCurrentThreadId();
+#endif
+#endif
+ return S_OK;
+ case WAIT_TIMEOUT:
+ return STG_E_INUSE;
+ default:
+ return LAST_SCODE;
+ }
+#ifdef SUPPORT_RECURSIVE_LOCK
+ }
+#endif
+ }
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDfMutex::Release, public
+//
+// Synopsis: This routine leaves the global critical section
+//
+// History: 26-Jul-94 DonnaLi Created
+//
+// Algorithm: Leaves the critical section if this is the owning
+// thread.
+//
+//---------------------------------------------------------------
+
+VOID
+CDfMutex::Release(
+ void
+ )
+{
+#ifdef SUPPORT_RECURSIVE_LOCK
+ if ( _pGlobalPortion->OwningThread != GetCurrentThreadId() ) return;
+#else
+#if DBG == 1
+ olAssert (_pGlobalPortion->OwningThread == 0 || _pGlobalPortion->OwningThread == GetCurrentThreadId());
+#endif
+#endif
+
+ olAssert (_pGlobalPortion->LockCount >= -1);
+
+#ifdef SUPPORT_RECURSIVE_LOCK
+ olAssert (_pGlobalPortion->RecursionCount >= 0);
+
+ //
+ // decrement the recursion count. If it is still non-zero, then
+ // we are still the owner so don't do anything other than dec the lock
+ // count
+ //
+
+ if ( --_pGlobalPortion->RecursionCount )
+ {
+ InterlockedDecrement(&_pGlobalPortion->LockCount);
+ }
+ else
+ {
+ //
+ // We are really leaving, so give up ownership and decrement the
+ // lock count
+ //
+
+ _pGlobalPortion->OwningThread = 0;
+#else
+#if DBG == 1
+ _pGlobalPortion->OwningThread = 0;
+#endif
+#endif
+
+ //
+ // Check to see if there are other waiters. If so, then wake up a waiter
+ //
+
+ if ( InterlockedDecrement(&_pGlobalPortion->LockCount) >= 0 )
+ {
+ ReleaseSemaphore(
+ _hLockSemaphore, // HANDLE hSemaphore
+ 1, // LONG cReleaseCount
+ NULL // LPLONG lplPreviousCount
+ );
+ }
+#ifdef SUPPORT_RECURSIVE_LOCK
+ }
+#endif
+}
diff --git a/private/ole32/dcomss/objex/shrmem/stg/simplell.cxx b/private/ole32/dcomss/objex/shrmem/stg/simplell.cxx
new file mode 100644
index 000000000..74051a040
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/stg/simplell.cxx
@@ -0,0 +1,128 @@
+
+/*++
+
+Microsoft Windows NT RPC Name Service
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ simpleLL.cxx
+
+Abstract:
+
+ This module contains definitions of non inline member functions for the
+ CSimpleLinkList class, which is a linked list without reference counting.
+
+Author:
+
+ Satish Thatte (SatishT) 11/20/95 Created all the code below except where
+ otherwise indicated.
+
+--*/
+
+#include <or.hxx>
+#include <simpleLL.hxx>
+
+
+
+void*
+CSimpleLinkList::pop()
+
+/*++
+Routine Description:
+
+ Delete first item in the CSimpleLinkList and return it
+
+--*/
+
+{
+ if (!pLnkFirst) return NULL;
+
+ void* result = pLnkFirst->data;
+ Link OR_BASED *oldFirst = pLnkFirst;
+ pLnkFirst = pLnkFirst->next;
+ if (!pLnkFirst) pLnkLast = NULL; // nothing left
+ DELETE_OR_BASED(Link,oldFirst);
+
+ lCount--;
+ return result;
+}
+
+
+void*
+CSimpleLinkList::nth(long lOrdinal)
+
+/*++
+Routine Description:
+
+ Simply return the Nth data item -- starting the count at 0.
+
+--*/
+
+{
+ if (!pLnkFirst) return NULL; // empty list
+
+ Link OR_BASED * pLnkCurr = pLnkFirst;
+ long lCount = 0;
+
+ while (pLnkCurr && (lCount++ < lOrdinal))
+ pLnkCurr = pLnkCurr->next;
+
+ if (!pLnkCurr) return NULL; // not found
+ else return pLnkCurr->data;
+}
+
+void
+CSimpleLinkList::rotate(long lDegree)
+
+/*++
+Routine Description:
+
+ This routine imagines that the list is in fact circular and
+ rotates it by lDegree -- using pop and enque for modularity.
+ We could actually move links around, but this operation is
+ not frequent enough (once for every NS lookup). Here we pay the
+ price of not having a true circular list (we moved away from
+ the true circular list for ref counting).
+
+--*/
+
+{
+ if (!pLnkFirst) return; // nothing to rotate;
+
+ void *pCurr;
+
+ for (long i = 0; i < (lDegree % lCount); i++) {
+ pCurr = pop();
+ enque(pCurr);
+ }
+}
+
+
+
+void CSimpleLinkList::clear() { // deletes all links but not the data
+
+ Link OR_BASED * pLnkCurr = pLnkFirst;
+
+ while (pLnkCurr)
+ {
+ Link OR_BASED * pLnkDel = pLnkCurr;
+ pLnkCurr = pLnkCurr->next;
+ DELETE_OR_BASED(Link,pLnkDel);
+ }
+
+ pLnkFirst = pLnkLast = NULL;
+}
+
+
+
+void*
+CSimpleLinkListIterator::next() { // advance the iterator and return next void
+
+ if (!ptr) return NULL;
+
+ void* result = ptr->data;
+ ptr = ptr->next;
+ return result;
+}
+
diff --git a/private/ole32/dcomss/objex/shrmem/stg/simplell.hxx b/private/ole32/dcomss/objex/shrmem/stg/simplell.hxx
new file mode 100644
index 000000000..f65cdced6
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/stg/simplell.hxx
@@ -0,0 +1,180 @@
+
+/*++
+
+Microsoft Windows NT RPC Name Service
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ simpleLL.hxx
+
+Abstract:
+
+ This module contains the definition a simple linklist class
+ which avoids reference counting, and stored pointers of any kind.
+
+Author:
+
+ Satish Thatte (SatishT) 11/20/95 Created all the code below except where
+ otherwise indicated.
+
+--*/
+
+
+
+#ifndef _SimpleListType_
+#define _SimpleListType_
+
+#include <base.hxx>
+
+#define NULL 0
+
+/*++
+
+Class Definition:
+
+ CSimpleLinkList
+
+Abstract:
+
+ This is a minimal linked list class, used when a link list is required
+ for short term use and the data could be pointers of any kind, not
+ necessarily pointers to types derived from IDataItem, as required
+ for the CLinkList class.
+
+--*/
+
+class CSimpleLinkList
+{
+
+ friend class CSimpleLinkListIterator;
+
+ protected:
+
+ struct Link
+ {
+ Link OR_BASED *next;
+ void* data;
+ Link(void* a, Link OR_BASED * n)
+ {
+ data = a;
+ next = n;
+ }
+
+ ~Link() {}
+
+ void * operator new(size_t s)
+ {
+ return OrMemAlloc(s);
+ }
+
+ void operator delete(void * p) // do not inherit this!
+ {
+ OrMemFree(p);
+ }
+ };
+
+ Link OR_BASED * pLnkFirst;
+ Link OR_BASED * pLnkLast;
+
+ long lCount;
+
+ public:
+
+ CSimpleLinkList() {
+ pLnkFirst = pLnkLast = NULL;
+ lCount = 0;
+ }
+
+ void clear();
+
+ ~CSimpleLinkList() {
+ clear();
+ }
+
+ void enque(void* x)
+ {
+ if (pLnkLast)
+ {
+ NEW_OR_BASED(pLnkLast->next,Link,(x, NULL));
+ pLnkLast = pLnkLast->next;
+ }
+ else
+ {
+ NEW_OR_BASED(pLnkLast,Link,(x,NULL));
+ pLnkFirst = pLnkLast;
+ }
+
+ lCount++;
+ }
+
+ void push(void* x)
+ {
+ NEW_OR_BASED(pLnkFirst,Link,(x, pLnkFirst));
+ if (!pLnkLast) pLnkLast = pLnkFirst;
+
+ lCount++;
+ }
+
+ void insert(void* x) // at the end in this class
+ { enque(x); }
+
+ void* pop(); // remove first item and return it
+
+ void* nth(long lOrdinal);
+
+ long size() { return lCount; }
+
+ void rotate(long lDegree);
+
+ inline void *operator new(size_t);
+
+ inline void operator delete(void*); // do not inherit this!
+};
+
+
+inline void *
+CSimpleLinkList::operator new(size_t s)
+{
+ return OrMemAlloc(s);
+}
+
+inline void
+CSimpleLinkList::operator delete(void* p) // do not inherit this!
+{
+ OrMemFree(p);
+}
+
+
+/*++
+
+Class Definition:
+
+ CSimpleLinkListIterator
+
+Abstract:
+
+ An iterator class for traversing a CSimpleLinkList.
+
+--*/
+
+
+class CSimpleLinkListIterator {
+
+ CSimpleLinkList::Link OR_BASED *ptr; // the current link
+
+ public:
+
+ CSimpleLinkListIterator(CSimpleLinkList& source) {
+ ptr = source.pLnkFirst;
+ }
+
+ void* next(); // advance the iterator and return next void
+
+ int finished() { return ptr == NULL; }
+
+};
+
+
+
+#endif // _SimpleListType_
diff --git a/private/ole32/dcomss/objex/shrmem/stg/smalloc.cxx b/private/ole32/dcomss/objex/shrmem/stg/smalloc.cxx
new file mode 100644
index 000000000..9f5c13f84
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/stg/smalloc.cxx
@@ -0,0 +1,1185 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: smalloc.cxx
+//
+// Contents: Shared memory heap implementation
+//
+// Classes:
+//
+// Functions:
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+// 10-May-95 KentCe Defer Heap Destruction to the last
+// process detach.
+//
+//----------------------------------------------------------------------------
+
+#include <or.hxx>
+
+#ifdef NEWPROPS
+#define FULLIMPL
+#endif
+
+//
+// Take advantage of unique Win95 support of a shared heap.
+//
+#if defined(_CHICAGO_)
+
+#define HEAP_SHARED 0x04000000 // Secret feature of Win95 only.
+
+//
+// Locate the following in a shared data segment.
+//
+#pragma data_seg(".sdata")
+
+HANDLE gs_hSharedHeap = NULL; // hSharedHeap Handle for Win95.
+DFLUID gs_dfluid = LUID_BASE; // shared docfile global LUID
+
+#pragma data_seg()
+
+#define PRINTSTATS
+
+#else // defined(_CHICAGO_)
+
+#define DLL
+
+#define DEB_STATS 0x00010000
+#define DEB_PRINT 0x00020000
+
+#ifdef DLL
+
+#define PERCENT(a,b,c) (int)((((double)a + (double)b) / (double)c) * 100.0)
+
+#define PRINTSTATS \
+ memDebugOut((DEB_STATS, \
+ "Total size: %lu, Space: Free: %lu, Alloced: %lu"\
+ " Blocks: Free: %lu, Alloced: %lu"\
+ " Efficiency: %.2f%%\n",\
+ _cbSize,\
+ GetHeader()->_ulFreeBytes,\
+ GetHeader()->_ulAllocedBytes,\
+ GetHeader()->_ulFreeBlocks,\
+ GetHeader()->GetAllocedBlocks(),\
+ PERCENT(GetHeader()->_ulFreeBytes,\
+ GetHeader()->_ulAllocedBytes, _cbSize)));
+
+#else
+#define PRINTSTATS \
+ printf( \
+ "Total size: %lu, Free space: %lu, Alloced space: %lu"\
+ " Efficiency: %.2f%%\n",\
+ _cbSize,\
+ GetHeader()->_ulFreeBytes,\
+ GetHeader()->_ulAllocedBytes,\
+ ((double)(GetHeader()->_ulFreeBytes +\
+ GetHeader()->_ulAllocedBytes) / \
+ (double)_cbSize) * (double)100);
+#endif
+
+
+#if DBG == 1
+inline BOOL IsAligned(void *pv)
+{
+ return !((ULONG)pv & 7);
+}
+#else
+#define IsAligned(x) TRUE
+#endif
+
+
+#define SHAREDMEMBASE NULL
+
+#endif // !defined(_CHICAGO_)
+
+ULONG g_ulHeapName;
+CSmAllocator g_SmAllocator;
+CSharedMemoryBlock g_smb;
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Init, public
+//
+// Synopsis: Initialize heap for use
+//
+// Arguments: [pszName] -- Name of shared memory heap to use
+//
+// Returns: Appropriate status code
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+//
+// Remarks: Review the class destructor if you change this code.
+//
+//----------------------------------------------------------------------------
+
+#if !defined(MULTIHEAP)
+SCODE CSmAllocator::Init(LPWSTR pszName)
+#else
+SCODE CSmAllocator::Init(ULONG ulHeapName, BOOL fUnmarshal)
+#endif
+{
+ SCODE sc = S_OK;
+
+#if !defined(MULTIHEAP)
+ // Initialize the mutex
+ sc = _dmtx.Init(TEXT("DocfileAllocatorMutex"));
+ if (FAILED(sc))
+ {
+ return sc;
+ }
+
+ sc = _dmtx.Take(DFM_TIMEOUT);
+ if (FAILED(sc))
+ {
+ return sc;
+ }
+#endif
+
+#if defined(_CHICAGO_)
+ //
+ // Create a new shared heap if this is the first time thru.
+ //
+ if (gs_hSharedHeap == NULL)
+ {
+ gs_hSharedHeap = HeapCreate(HEAP_SHARED, 0, 0);
+ }
+
+ //
+ // We keep a copy of the shared heap as a flag so the destructor logic
+ // does the right thing.
+ //
+ //
+ m_hSharedHeap = gs_hSharedHeap;
+
+#else
+ CSharedMemoryBlock *psmb = NULL;
+#ifdef MULTIHEAP
+ _cbSize = 0;
+ if (!fUnmarshal && this == &g_SmAllocator) // only for main thread
+ {
+ if (g_ulHeapName != 0) // the global shared memory block is active
+ {
+ _psmb = &g_smb; // needed for GetHeader
+ _pbBase = (BYTE *)(_psmb->GetBase()); // needed for GetHeader
+ if (_pbBase != NULL && GetHeader()->GetAllocedBlocks() == 0)
+ { // its' empty reuse it
+ psmb = _psmb;
+ _ulHeapName = g_ulHeapName;
+ memDebugOut ((DEB_ITRACE, "Out CSmAllocator::Init "
+ " reuse %x\n", g_ulHeapName));
+ return sc;
+ }
+ }
+ else
+ {
+ psmb = _psmb = &g_smb; // initialize g_smb
+ }
+ }
+
+ if (psmb == NULL)
+ {
+ psmb = _psmb = new CSharedMemoryBlock ();
+ if (psmb == NULL)
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ WCHAR pszName[DOCFILE_SM_NAMELEN];
+ wsprintf(pszName, L"DfSharedHeap%X", ulHeapName);
+#else
+ psmb = &_smb;
+#endif
+ // the SMB needs a few bytes for its own header. If we request
+ // a page sized allocation, those few header bytes will cause an
+ // extra page to be allocated, so to prevent that we subtract off
+ // the header space from our requests.
+
+ sc = psmb->Init(pszName,
+ DOCFILE_SM_SIZE - psmb->GetHdrSize(), // reserve size
+ INITIALHEAPSIZE - psmb->GetHdrSize(), // commit size
+ SHAREDMEMBASE, // base address
+ NULL, // security descriptor
+ TRUE); // create if doesn't exist
+
+ if (SUCCEEDED(sc))
+ {
+ _cbSize = psmb->GetSize();
+ _pbBase = (BYTE *)(psmb->GetBase());
+#ifdef MULTIHEAP
+ _ulHeapName = ulHeapName;
+#endif
+
+ if (psmb->Created())
+ {
+ CBlockHeader *pbh = (CBlockHeader *)
+ (_pbBase + sizeof(CHeapHeader));
+
+ memAssert(IsAligned(pbh));
+ pbh->SetFree();
+ pbh->SetSize(_cbSize - sizeof(CHeapHeader));
+ pbh->SetNext(0);
+
+ memAssert((BYTE *)pbh + pbh->GetSize() == _pbBase + _cbSize);
+ GetHeader()->SetFirstFree(GetOffset(pbh));
+ GetHeader()->SetCompacted();
+ GetHeader()->ResetAllocedBlocks();
+ GetHeader()->ResetLuid();
+
+#if DBG == 1
+ GetHeader()->_ulAllocedBytes = 0;
+ GetHeader()->_ulFreeBytes =
+ pbh->GetSize() - sizeof(CBlockPreHeader);
+ GetHeader()->_ulFreeBlocks = 1;
+#endif
+ }
+
+#ifdef MULTIHEAP
+ if (psmb == &g_smb)
+ g_ulHeapName = ulHeapName; // store global heap name
+#endif
+ PRINTSTATS;
+ }
+#endif
+
+#if defined(MULTIHEAP)
+ memDebugOut ((DEB_ITRACE, "Out CSmAllocator::Init sc=%x %x\n",
+ sc, ulHeapName));
+#else
+ _dmtx.Release();
+ memDebugOut ((DEB_ITRACE, "Out CSmAllocator::Init sc=%x\n",
+ sc));
+#endif
+
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::QueryInterface, public
+//
+// Synopsis: Standard QI
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CSmAllocator::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::QueryInterface:%p()\n", this));
+
+ if (IsEqualIID(iid, IID_IMalloc) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IMalloc *) this;
+ CSmAllocator::AddRef();
+ }
+ else
+ sc = E_NOINTERFACE;
+
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::QueryInterface\n"));
+
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::AddRef, public
+//
+// Synopsis: Add reference
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CSmAllocator::AddRef(void)
+{
+#ifdef MULTIHEAP
+ return ++_cRefs;
+#else
+ return 1;
+#endif
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Release, public
+//
+// Synopsis: Release
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CSmAllocator::Release(void)
+{
+#ifdef MULTIHEAP
+ ULONG cRefs = --_cRefs;
+ if (cRefs <= 0)
+ delete this;
+ return cRefs;
+#else
+ return 0;
+#endif
+}
+
+#if !defined(_CHICAGO_)
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::FindBlock, private
+//
+// Synopsis: Find an appropriately sized block in the heap.
+//
+// Arguments: [cb] -- Size of block required
+//
+// Returns: Pointer to block, NULL on failure
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CBlockHeader * CSmAllocator::FindBlock(ULONG cb, CBlockHeader **ppbhPrev)
+{
+ CBlockHeader *pbhCurrent = GetAddress(GetHeader()->GetFirstFree());
+ *ppbhPrev = NULL;
+
+ while (pbhCurrent != NULL)
+ {
+ memAssert(IsAligned(pbhCurrent));
+
+ if ((pbhCurrent->GetSize() >= cb) && (pbhCurrent->IsFree()))
+ {
+ memAssert(pbhCurrent->GetSize() < _cbSize); //MULTIHEAP
+ memAssert((BYTE *)pbhCurrent >= _pbBase &&
+ (BYTE *)pbhCurrent < _pbBase + _cbSize); // MULTIHEAP
+ break;
+ }
+ else
+ {
+ memAssert (pbhCurrent->GetNext() <= _cbSize); // MULITHEAP
+ *ppbhPrev = pbhCurrent;
+ pbhCurrent = GetAddress(pbhCurrent->GetNext());
+ }
+ }
+ return pbhCurrent;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Reset, private
+//
+// Synopsis: Reset the heap to its original empty state.
+//
+// Returns: Appropriate status code
+//
+// History: 04-Apr-94 PhilipLa Created
+//
+// Notes: There is only one caller of this function. Hence it is
+// declared inline.
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CSmAllocator::Reset(void)
+{
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::Reset:%p()\n", this));
+#ifdef RESETOK
+#ifdef MULTIHEAP
+ CSharedMemoryBlock *psmb = _psmb;
+#else
+ CSharedMemoryBlock *psmb = &_smb;
+#endif
+ psmb->Reset();
+ _cbSize = psmb->GetSize();
+ _pbBase = (BYTE *)(psmb->GetBase());
+
+ CBlockHeader *pbh = (CBlockHeader *)
+ (_pbBase + sizeof(CHeapHeader));
+
+ pbh->SetFree();
+ pbh->SetSize(_cbSize - sizeof(CHeapHeader));
+ pbh->SetNext(0);
+
+ memAssert((BYTE *)pbh + pbh->GetSize() == _pbBase + _cbSize);
+ GetHeader()->SetFirstFree(GetOffset(pbh));
+ GetHeader()->SetCompacted();
+ GetHeader()->ResetAllocedBlocks();
+
+#if DBG == 1
+ GetHeader()->_ulAllocedBytes = 0;
+ GetHeader()->_ulFreeBytes =
+ pbh->GetSize() - sizeof(CBlockPreHeader);
+ GetHeader()->_ulFreeBlocks = 1;
+#endif
+
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::Reset\n"));
+#else
+ HeapMinimize();
+#endif
+ return S_OK;
+}
+
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Alloc, public
+//
+// Synopsis: Allocate memory
+//
+// Arguments: [cb] -- Number of bytes to allocate
+//
+// Returns: Pointer to block, NULL if failure
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(void *) CSmAllocator::Alloc (
+ ULONG cb )
+{
+ void *pv = NULL;
+
+#if !defined(_CHICAGO_)
+ CBlockHeader *pbh = NULL;
+ CBlockHeader *pbhPrev = NULL;
+ SCODE sc;
+#endif
+
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::Alloc:%p(%lu)\n", this, cb));
+
+#if defined(_CHICAGO_)
+
+ pv = HeapAlloc(m_hSharedHeap, 0, cb);
+
+#else // !defined(_CHICAGO_)
+#if !defined(MULTIHEAP)
+ CLockDfMutex lckdmtx(_dmtx);
+#endif
+
+ Sync();
+
+ //The block must be at least large enough to hold the standard
+ // header (size and free bit) and a pointer to the next block.
+ if (cb < sizeof(CBlockHeader) - sizeof(CBlockPreHeader))
+ {
+ cb = sizeof(CBlockHeader) - sizeof(CBlockPreHeader);
+ }
+
+ cb = cb + sizeof(CBlockPreHeader);
+
+ //Make cb 8 byte aligned.
+ if (cb & 7)
+ {
+ cb += (8 - (cb & 7));
+ }
+
+ memAssert((cb >= CBLOCKMIN) && "Undersized block requested.");
+ pbh = FindBlock(cb, &pbhPrev);
+
+ if (pbh == NULL)
+ {
+ if (!(GetHeader()->IsCompacted()))
+ {
+ //Do a heap merge and try to allocate again.
+ CSmAllocator::HeapMinimize();
+ pbh = FindBlock(cb, &pbhPrev);
+ }
+
+ if (pbh == NULL)
+ {
+#ifdef MULTIHEAP
+ CSharedMemoryBlock *psmb = _psmb;
+#else
+ CSharedMemoryBlock *psmb = &_smb;
+#endif
+#if DBG == 1
+ ULONG ulOldSize = psmb->GetSize();
+#endif
+ sc = psmb->Commit(_cbSize + max(cb, MINHEAPGROWTH));
+ if (SUCCEEDED(sc))
+ {
+ //Attach newly committed space to free list.
+ CBlockHeader *pbhNew = (CBlockHeader *)
+ (_pbBase + _cbSize);
+
+ _cbSize = psmb->GetSize();
+
+ memAssert((pbhPrev == NULL) || (pbhPrev->GetNext() == 0));
+ memAssert(_cbSize > ulOldSize);
+
+ if (pbhPrev != NULL)
+ {
+ pbhPrev->SetNext(GetOffset(pbhNew));
+ }
+ else
+ {
+ GetHeader()->SetFirstFree(GetOffset(pbhNew));
+ }
+
+ pbhNew->SetNext(0);
+ pbhNew->SetSize(max(cb, MINHEAPGROWTH));
+ pbhNew->SetFree();
+
+
+ memAssert((BYTE *)pbhNew + pbhNew->GetSize() ==
+ _pbBase + _cbSize);
+
+#if DBG == 1
+ GetHeader()->_ulFreeBytes +=
+ pbhNew->GetSize() - sizeof(CBlockPreHeader);
+ GetHeader()->_ulFreeBlocks += 1;
+#endif
+
+ pbh = pbhNew;
+ }
+ }
+ }
+
+ if (pbh != NULL)
+ {
+ //Allocate the found block.
+ if ((pbh->GetSize() > cb) &&
+ (pbh->GetSize() - cb > CBLOCKMIN))
+ {
+ //Split an existing block. No free list update required.
+
+ CBlockHeader *pbhNew =
+ (CBlockHeader *)((BYTE *)pbh + (pbh->GetSize() - cb));
+
+ pbhNew->SetSize(cb);
+ pbhNew->ResetFree();
+ pbhNew->SetNext(0);
+
+ pbh->SetSize(pbh->GetSize() - cb);
+#if DBG == 1
+ GetHeader()->_ulAllocedBytes += (cb - sizeof(CBlockPreHeader));
+ //The number of available free bytes decreases by the number
+ // of bytes allocated
+ GetHeader()->_ulFreeBytes -= cb;
+#endif
+ memAssert(IsAligned(pbhNew));
+ memAssert(IsAligned(pbh));
+
+ pbh = pbhNew;
+ }
+ else
+ {
+ //Use an entire block. Update free list appropriately.
+ memAssert(IsAligned(pbh));
+ pbh->ResetFree();
+ if (pbhPrev != NULL)
+ {
+ pbhPrev->SetNext(pbh->GetNext());;
+ }
+ else
+ {
+ GetHeader()->SetFirstFree(pbh->GetNext());
+ }
+#if DBG == 1
+ GetHeader()->_ulAllocedBytes += (cb - sizeof(CBlockPreHeader));
+ GetHeader()->_ulFreeBytes -= (cb - sizeof(CBlockPreHeader));
+ GetHeader()->_ulFreeBlocks--;
+#endif
+ pbh->SetNext(0);
+ }
+ }
+
+ if (pbh != NULL)
+ {
+ pv = (BYTE *)pbh + sizeof(CBlockPreHeader);
+ GetHeader()->IncrementAllocedBlocks();
+ }
+#endif // !defined(_CHICAGO_)
+
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::Alloc=> %p\n", pv));
+
+#if !defined(_CHICAGO_)
+ memAssert(IsAligned(pv));
+#endif // !defined(_CHICAGO_)
+
+ PRINTSTATS;
+
+#if DBG == 1
+ if (pv == NULL)
+ {
+#if defined(_CHICAGO_)
+ memDebugOut((DEB_ERROR,
+ "Failed allocation of %lu bytes.\n",
+ cb));
+#else // !defined(_CHICAGO_)
+ memDebugOut((DEB_ERROR,
+ "Failed allocation of %lu bytes. Heap size is %lu\n",
+ cb,
+ _cbSize));
+#endif // !defined(_CHICAGO_)
+ }
+#endif
+
+ return pv;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Realloc, public
+//
+// Synopsis: Resize the block given
+//
+// Arguments: [pv] -- Pointer to block to realloc
+// [cb] -- New size for block
+//
+// Returns: Pointer to new block, NULL if failure
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(void *) CSmAllocator::Realloc(
+ void *pv,
+ ULONG cb )
+{
+ void *pvNew = NULL;
+#ifdef FULLIMPL
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::Realloc:%p()\n", this));
+
+#if defined(_CHICAGO_)
+
+ pvNew = HeapReAlloc(m_hSharedHeap, 0, pv, cb);
+
+#else
+#if !defined(MULTIHEAP)
+ CLockDfMutex lckdmtx(_dmtx);
+#endif
+
+ if ((pv != NULL) && (cb == 0))
+ {
+ CSmAllocator::Free(pv);
+ return NULL;
+ }
+
+ pvNew = CSmAllocator::Alloc(cb);
+ if (pvNew != NULL && pv != NULL)
+ {
+ //Copy contents
+ memcpy(pvNew, pv, min(cb, CSmAllocator::GetSize(pv)));
+ CSmAllocator::Free(pv);
+ }
+#endif
+
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::Realloc\n"));
+#endif
+ PRINTSTATS;
+
+ return pvNew;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::DoFree, private
+//
+// Synopsis: Free a memory block
+//
+// Arguments: [pv] -- Pointer to block to free
+//
+// Returns: void
+//
+// History: 26-Jul-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+inline void CSmAllocator::DoFree(void *pv)
+{
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::DoFree:%p(%p)\n", this, pv));
+
+#if defined(_CHICAGO_)
+
+ if (pv != NULL)
+ {
+ HeapFree(m_hSharedHeap, 0, pv);
+ }
+
+#else
+
+ Sync();
+
+ if (pv != NULL)
+ {
+ CBlockHeader *pbh = (CBlockHeader *)
+ ((BYTE *)pv - sizeof(CBlockPreHeader));
+#ifdef MULTIHEAP
+ ULONG ulSize = pbh->GetSize(); // temporary to hold size for debug
+#endif
+
+ memAssert(IsAligned(pbh));
+ memAssert((BYTE*)pbh >= _pbBase &&
+ (BYTE*)pbh < _pbBase + _cbSize); // MULTIHEAP
+ pbh->SetFree();
+ pbh->SetNext(GetHeader()->GetFirstFree());
+
+ GetHeader()->SetFirstFree(GetOffset(pbh));
+ GetHeader()->ResetCompacted();
+ if (GetHeader()->DecrementAllocedBlocks() == 0)
+ {
+#ifdef MULTIHEAP
+ Uninit();
+#else
+
+ Reset();
+#endif
+ }
+
+#if DBG == 1
+ else
+ {
+ GetHeader()->_ulAllocedBytes -=
+ (pbh->GetSize() - sizeof(CBlockPreHeader));
+ GetHeader()->_ulFreeBytes +=
+ (pbh->GetSize() - sizeof(CBlockPreHeader));
+ GetHeader()->_ulFreeBlocks++;
+ }
+#endif
+#ifdef MULTIHEAP
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::DoFree. Freed %lu\n",
+ ulSize)); // don't access shared memory
+#else
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::DoFree. Freed %lu\n",
+ pbh->GetSize()));
+#endif
+ }
+#endif
+#if !defined(MULTIHEAP)
+ // the shared heap may have been unmapped, mustn't read it now
+ PRINTSTATS;
+#endif
+}
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Free, public
+//
+// Synopsis: Free a memory block
+//
+// Arguments: [pv] -- Pointer to block to free
+//
+// Returns: void
+//
+// History: 29-Mar-94 PhilipLa Created
+// 26-Jul-95 SusiA Moved bulk of work to DoFree to
+// share code between Free and
+// FreeNoMutex
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CSmAllocator::Free(void *pv)
+{
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::Free:%p(%p)\n", this, pv));
+
+#if !defined(_CHICAGO_)
+#if !defined(MULTIHEAP)
+ CLockDfMutex lckdmtx(_dmtx);
+#endif
+#endif
+ DoFree(pv);
+
+}
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::FreeNoMutex, public
+//
+// Synopsis: Free a memory block without first aquiring the mutex.
+// This function is equivalent to Free above, except that is does
+// not attempt to first aquire the mutex. It should be used OLNY
+// when the calling function guarantees to already have the mutex.
+//
+//
+// Arguments: [pv] -- Pointer to block to free
+//
+// Returns: void
+//
+// History: 19-Jul-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+void CSmAllocator::FreeNoMutex(void *pv)
+{
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::FreeNoMutex:%p(%p)\n", this, pv));
+
+#if !defined(_CHICAGO_)
+#if !defined(MULTIHEAP)
+ //ensure we already have the mutex
+ memAssert(_dmtx.HaveMutex());
+#endif
+#endif
+ DoFree(pv);
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::GetSize, public
+//
+// Synopsis: Return the size of the given block
+//
+// Arguments: [pv] -- Block to get size of
+//
+// Returns: Size of block pointer to by pv
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CSmAllocator::GetSize(void * pv)
+{
+#if !defined(_CHICAGO_)
+#if !defined(MULTIHEAP)
+ CLockDfMutex lckdmtx(_dmtx);
+#endif
+#endif
+
+ Sync();
+
+ ULONG ulSize = (ULONG)-1;
+#ifdef FULLIMPL
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::GetSize:%p()\n", this));
+ if (pv != NULL)
+ {
+#if defined(_CHICAGO_)
+ ulSize = HeapSize(m_hSharedHeap, 0, pv);
+#else
+ CBlockHeader *pbh;
+ pbh = (CBlockHeader *)((BYTE *)pv - sizeof(CBlockPreHeader));
+
+ ulSize = pbh->GetSize() - sizeof(CBlockPreHeader);
+#endif
+ }
+
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::GetSize\n"));
+#endif
+ return ulSize;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::DidAlloc, public
+//
+// Synopsis: Return '1' if this heap allocated pointer at pv
+//
+// Arguments: [pv] -- Pointer to block
+//
+// Returns: '1' == This heap allocated block.
+// '0' == This heap did not allocate block.
+// '-1' == Could not determine if this heap allocated block.
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(int) CSmAllocator::DidAlloc(void FAR * pv)
+{
+ int i = -1;
+#ifdef FULLIMPL
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::DidAlloc:%p()\n", this));
+#if defined(_CHICAGO_)
+ if (HeapValidate(m_hSharedHeap, 0, pv))
+ {
+ i = 1;
+ }
+ else
+ {
+ i = 0;
+ }
+#else // !defined(_CHICAGO_)
+#if !defined(MULTIHEAP)
+ CLockDfMutex lckdmtx(_dmtx);
+#endif
+
+ i = ((BYTE *)pv >= _pbBase) && ((BYTE *)pv <= (_pbBase + _cbSize));
+#endif // !defined(_CHICAGO_)
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::DidAlloc\n"));
+#endif
+ return i;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::HeapMinimize, public
+//
+// Synopsis: Minimize the heap
+//
+// Arguments: None.
+//
+// Returns: void.
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CSmAllocator::HeapMinimize(void)
+{
+#if !defined(_CHICAGO_)
+#if !defined(MULTIHEAP)
+ CLockDfMutex lckdmtx(_dmtx);
+#endif
+#endif
+
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::HeapMinimize:%p()\n", this));
+
+ PRINTSTATS;
+
+#if defined(_CHICAGO_)
+
+ HeapCompact(m_hSharedHeap, 0);
+
+#else // !defined(_CHICAGO_)
+
+ CBlockHeader *pbhCurrent;
+ CBlockHeader *pbhLast = NULL;
+ BYTE *pbEnd = _pbBase + _cbSize;
+
+#if DBG == 1
+ PrintFreeBlocks();
+ GetHeader()->_ulAllocedBytes = 0;
+ GetHeader()->_ulFreeBytes = 0;
+ GetHeader()->_ulFreeBlocks = 0;
+#endif
+
+ pbhCurrent = (CBlockHeader *)(_pbBase + sizeof(CHeapHeader));
+
+ while ((BYTE *)pbhCurrent < pbEnd)
+ {
+ memAssert(IsAligned(pbhCurrent));
+ memAssert((pbhCurrent->GetSize != 0) &&
+ "Zero size block found.");
+ if (pbhCurrent->IsFree())
+ {
+ //Check last block. If adjacent, merge them. If not,
+ // update pbhNext.
+
+ if (pbhLast == NULL)
+ {
+ GetHeader()->SetFirstFree(GetOffset(pbhCurrent));
+#if DBG == 1
+ GetHeader()->_ulFreeBlocks = 1;
+#endif
+ }
+ else
+ {
+ if (pbhLast->GetSize() + GetOffset(pbhLast) ==
+ GetOffset(pbhCurrent))
+ {
+ //Merge the blocks.
+ pbhLast->SetSize(pbhLast->GetSize() +
+ pbhCurrent->GetSize());
+ pbhCurrent = pbhLast;
+ }
+ else
+ {
+#if DBG == 1
+ GetHeader()->_ulFreeBytes +=
+ (pbhLast->GetSize() - sizeof(CBlockPreHeader));
+ GetHeader()->_ulFreeBlocks++;
+#endif
+ pbhLast->SetNext(GetOffset(pbhCurrent));
+ }
+ }
+ pbhLast = pbhCurrent;
+ }
+#if DBG == 1
+ else
+ {
+ GetHeader()->_ulAllocedBytes +=
+ (pbhCurrent->GetSize() - sizeof(CBlockPreHeader));
+ }
+#endif
+ //Move to next block.
+ pbhCurrent =
+ (CBlockHeader *)((BYTE *)pbhCurrent + pbhCurrent->GetSize());
+ }
+
+ if (pbhLast != NULL)
+ {
+
+#if DBG == 1
+ GetHeader()->_ulFreeBytes +=
+ (pbhLast->GetSize() - sizeof(CBlockPreHeader));
+#endif
+ pbhLast->SetNext(0);
+ }
+ else
+ {
+ GetHeader()->SetFirstFree(0);
+ }
+
+ GetHeader()->SetCompacted();
+#if DBG == 1
+ PrintFreeBlocks();
+#endif
+
+#endif // !defined(_CHICAGO_)
+
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::HeapMinimize\n"));
+
+ PRINTSTATS;
+}
+
+#if !defined(_CHICAGO_)
+#if DBG == 1
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::PrintFreeBlocks, private
+//
+// Synopsis: Debug code to print sizes of free blocks
+//
+// History: 25-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+void CSmAllocator::PrintFreeBlocks(void)
+{
+ CBlockHeader *pbhCurrent = GetAddress(GetHeader()->GetFirstFree());
+
+ memDebugOut((DEB_PRINT, "There are %lu total free blocks\n",
+ GetHeader()->_ulFreeBlocks));
+
+ while (pbhCurrent != NULL)
+ {
+ memDebugOut((DEB_PRINT, "Free block %p has size %lu\n", pbhCurrent,
+ pbhCurrent->GetSize()));
+ pbhCurrent = GetAddress(pbhCurrent->GetNext());
+ }
+}
+#endif
+
+#ifdef MULTIHEAP
+#if DBG == 1
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::PrintAllocatedBlocks, private
+//
+// Synopsis: Debug code to find allocated block(s) that leaked
+//
+// History: 25-Nov-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+void CSmAllocator::PrintAllocatedBlocks(void)
+{
+ CBlockHeader *pbhCurrent;
+ CBlockHeader *pbhLast = NULL;
+ BYTE *pbEnd = _pbBase + _cbSize;
+ ULONG *pul;
+
+ pbhCurrent = (CBlockHeader *)(_pbBase + sizeof(CHeapHeader));
+
+ while ((BYTE *)pbhCurrent < pbEnd)
+ {
+ memAssert(IsAligned(pbhCurrent));
+ memAssert((pbhCurrent->GetSize != 0) && "Zero size block found.");
+ if (!pbhCurrent->IsFree())
+ {
+ pul = (ULONG *)((BYTE *)pbhCurrent + sizeof(CBlockHeader));
+ memDebugOut((DEB_PRINT, "PrintAllocatedBlocks %p %8x %8x\n",
+ pul, *pul, *(pul+1)));
+
+ }
+ pbhCurrent =
+ (CBlockHeader *)((BYTE *)pbhCurrent + pbhCurrent->GetSize());
+ }
+}
+#endif // DBG == 1
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::SetState
+//
+// Synopsis: replace thread local state by PerContext state
+//
+// History: 20-Nov-95 Henrylee Created
+//
+//----------------------------------------------------------------------------
+void CSmAllocator::SetState (CSharedMemoryBlock *psmb, BYTE * pbBase,
+ ULONG ulHeapName, CPerContext ** ppcPrev,
+ CPerContext *ppcOwner)
+{
+ olDebugOut((DEB_ITRACE, "In CSmAllocator::SetState(%p, %p, %lx, %p, %p) (this == %p)\n", psmb, pbBase, ulHeapName, ppcPrev, ppcOwner, this));
+ olDebugOut((DEB_ITRACE, "Current allocator owner == %p\n", _ppcOwner));
+
+ _psmb = psmb;
+ _pbBase = pbBase;
+ _cbSize = (_psmb) ? _psmb->GetSize() : 0;
+ _ulHeapName = ulHeapName;
+ // DFBASEPTR = _pbBase;
+
+ if (ppcPrev != NULL)
+ *ppcPrev = _ppcOwner;
+ _ppcOwner = ppcOwner;
+
+ //memAssert (g_smAllocator.GetBase() == DFBASEPTR);
+ olDebugOut((DEB_ITRACE, "Out CSmAllocator::SetState()\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::GetState
+//
+// Synopsis: retrive thread local allocator state into percontext
+//
+// History: 20-Nov-95 Henrylee Created
+//
+//----------------------------------------------------------------------------
+void CSmAllocator::GetState (CSharedMemoryBlock **ppsmb,
+ BYTE ** ppbBase, ULONG *pulHeapName)
+{
+ *ppsmb = _psmb;
+ *ppbBase = _pbBase;
+ *pulHeapName = _ulHeapName;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Uninit
+//
+// Synopsis: unmap the shared memory region
+//
+// History: 20-Nov-95 Henrylee Created
+//
+//----------------------------------------------------------------------------
+SCODE CSmAllocator::Uninit ()
+{
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::Uninit\n"));
+ if (_psmb != NULL)
+ {
+ if (_psmb != &g_smb)
+ {
+ // This is last block in the heap, so we can close the heap
+ // now. There must be no shared heap accesses after this.
+ BOOL b = VirtualFree(_pbBase - sizeof(CSharedMemHeader),
+ 0, MEM_RELEASE);
+ delete _psmb;
+ }
+ else
+ {
+ Reset(); // for g_smb
+ }
+ _psmb = NULL;
+ }
+ _pbBase = NULL;
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::Uninit %x\n", _ulHeapName));
+
+ return S_OK;
+}
+#endif // MULTIHEAP
+
+#endif // !defined(_CHICAGO_)
diff --git a/private/ole32/dcomss/objex/shrmem/stg/smalloc.hxx b/private/ole32/dcomss/objex/shrmem/stg/smalloc.hxx
new file mode 100644
index 000000000..150ddf3b9
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/stg/smalloc.hxx
@@ -0,0 +1,850 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: heap.hxx
+//
+// Contents: Heap code headers
+//
+// Classes: CHeap
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+// 10-Apr095 HenryLee Added global LUID
+// 10-May-95 KentCe Defer Heap Destruction to the last
+// process detach.
+//
+//----------------------------------------------------------------------------
+
+#ifndef __HEAP_HXX__
+#define __HEAP_HXX__
+
+DECLARE_DEBUG(ol)
+
+#define olAssert(e) Win4Assert(e)
+#define olVerify(e) Win4Assert(e)
+#define olDebugOut(x) olInlineDebugOut x
+
+
+#include <smblock.hxx>
+#include <memdebug.hxx>
+#include <smmutex.hxx>
+#include <msf.hxx>
+#include <df32.hxx>
+
+#ifdef COORD
+#include <dfrlist.hxx>
+#endif
+
+//Space to reserve for heap.
+const ULONG MINHEAPGROWTH = 4096;
+const ULONG INITIALHEAPSIZE = 16384;
+
+#ifdef MULTIHEAP
+#include <ntpsapi.h>
+class CPerContext;
+
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Class: CLockDfMutex
+//
+// Purpose: Simple class to guarantee that a DfMutex is unlocked
+//
+// History: 29-Apr-95 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+class CLockDfMutex
+{
+public:
+
+ CLockDfMutex(CDfMutex& dmtx);
+
+ ~CLockDfMutex(void);
+
+private:
+
+ CDfMutex& _dmtx;
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLockDfMutex::CLockDfMutex
+//
+// Synopsis: Get mutex
+//
+// Arguments: [dmtx] -- mutex to get
+//
+// History: 29-Apr-95 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+inline CLockDfMutex::CLockDfMutex(CDfMutex& dmtx) : _dmtx(dmtx)
+{
+ _dmtx.Take(DFM_TIMEOUT);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLockDfMutex::~CLockDfMutex
+//
+// Synopsis: Release the mutex
+//
+// History: 29-Apr-95 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+inline CLockDfMutex::~CLockDfMutex(void)
+{
+ _dmtx.Release();
+}
+
+//
+// Take advantage of Windows 95 Shared Heap.
+//
+#if !defined(_CHICAGO_)
+
+//+---------------------------------------------------------------------------
+//
+// Class: CBlockPreHeader
+//
+// Purpose: Required header fields for a block
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+class CBlockPreHeader
+{
+protected:
+ ULONG _ulSize; //Size of block
+ BOOL _fFree; //TRUE if block is free
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CBlockHeader
+//
+// Purpose: Fields required for free blocks but overwritten for
+// allocated blocks.
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+class CBlockHeader: public CBlockPreHeader
+{
+public:
+ inline ULONG GetSize(void) const;
+ inline BOOL IsFree(void) const;
+ inline ULONG GetNext(void) const;
+
+ inline void SetSize(ULONG ulSize);
+ inline void SetFree(void);
+ inline void ResetFree(void);
+ inline void SetNext(ULONG ulNext);
+private:
+ ULONG _ulNext; //Pointer to next block
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CBlockHeader::GetSize, public
+//
+// Synopsis: Returns the size of the block
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CBlockHeader::GetSize(void) const
+{
+ return _ulSize;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CBlockHeader::IsFree, public
+//
+// Synopsis: Returns free state of block
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CBlockHeader::IsFree(void) const
+{
+ return _fFree;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CBlockHeader::GetNext, public
+//
+// Synopsis: Return next offset
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CBlockHeader::GetNext(void) const
+{
+ return _ulNext;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CBlockHeader::SetSize, public
+//
+// Synopsis: Set size of block
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CBlockHeader::SetSize(ULONG ulSize)
+{
+ _ulSize = ulSize;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CBlockHeader::SetFree, public
+//
+// Synopsis: Set this block to free
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CBlockHeader::SetFree(void)
+{
+ _fFree = TRUE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CBlockHeader::ResetFree, public
+//
+// Synopsis: Set this block to !free
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CBlockHeader::ResetFree(void)
+{
+ _fFree = FALSE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CBlockHeader::SetNext, public
+//
+// Synopsis: Set next offset
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CBlockHeader::SetNext(ULONG ulNext)
+{
+ _ulNext = ulNext;
+}
+
+const ULONG CBLOCKMIN = ((sizeof(CBlockHeader) & 7)
+ ? sizeof(CBlockHeader) +
+ (8 - (sizeof(CBlockHeader) & 7))
+ : sizeof(CBlockHeader));
+
+//+---------------------------------------------------------------------------
+//
+// Class: CHeapHeader
+//
+// Purpose: Header information for shared memory heap
+//
+// Interface:
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+// Notes: The size of this structure must be a multiple of 8 bytes.
+//
+//----------------------------------------------------------------------------
+
+class CHeapHeader
+{
+public:
+ inline ULONG GetFirstFree(void) const;
+ inline void SetFirstFree(ULONG ulNew);
+
+ inline BOOL IsCompacted(void) const;
+ inline void SetCompacted(void);
+ inline void ResetCompacted(void);
+
+ inline void ResetAllocedBlocks(void);
+ inline ULONG IncrementAllocedBlocks(void);
+ inline ULONG DecrementAllocedBlocks(void);
+
+ inline ULONG GetAllocedBlocks(void);
+ inline DFLUID IncrementLuid(void);
+ inline void ResetLuid(void);
+
+#if DBG == 1
+ ULONG _ulAllocedBytes;
+ ULONG _ulFreeBytes;
+ ULONG _ulFreeBlocks;
+#endif
+
+private:
+ ULONG _ulFirstFree;
+ ULONG _ulAllocedBlocks;
+ BOOL _fIsCompacted;
+ DFLUID _dfLuid;
+#if DBG == 1
+ ULONG ulPad;
+#endif
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::GetFirstFree, public
+//
+// Synopsis: Return first free information
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CHeapHeader::GetFirstFree(void) const
+{
+ return _ulFirstFree;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::SetFirstFree, public
+//
+// Synopsis: Set first free information
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CHeapHeader::SetFirstFree(ULONG ulNew)
+{
+ _ulFirstFree = ulNew;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::IsCompacted, public
+//
+// Synopsis: Return TRUE if heap is compacted
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CHeapHeader::IsCompacted(void) const
+{
+ return _fIsCompacted;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::SetCompacted, public
+//
+// Synopsis: Set compacted bit
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CHeapHeader::SetCompacted(void)
+{
+ _fIsCompacted = TRUE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::ResetCompacted, public
+//
+// Synopsis: Reset compacted bit
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CHeapHeader::ResetCompacted(void)
+{
+ _fIsCompacted = FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::IncrementLuid, public
+//
+// Synopsis: Increment the global LUID
+//
+// History: 06-Apr-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+inline ULONG CHeapHeader::IncrementLuid()
+{
+ return ++_dfLuid;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::ResetLuid, public
+//
+// Synopsis: Increment the global LUID
+//
+// History: 06-Apr-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+inline void CHeapHeader::ResetLuid()
+{
+ _dfLuid = LUID_BASE; // some LUIDs are reserved
+}
+
+#else // define(_CHICAGO_)
+
+extern HANDLE gs_hSharedHeap; // hSharedHeap Handle for Win95.
+extern DFLUID gs_dfluid; // shared docfile LUID
+
+#endif // !define(_CHICAGO_)
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSmAllocator
+//
+// Purpose: Shared memory heap implementation
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+//
+//----------------------------------------------------------------------------
+
+class CSmAllocator: public IMalloc
+{
+public:
+ inline CSmAllocator();
+ inline ~CSmAllocator();
+
+ STDMETHOD_(ULONG,AddRef) ( void );
+ STDMETHOD_(ULONG,Release) ( void );
+ STDMETHOD(QueryInterface) ( REFIID riid, void ** ppv );
+
+ STDMETHOD_(void*,Alloc) ( ULONG cb );
+ STDMETHOD_(void *,Realloc) ( void *pvCurrent, ULONG cbNeeded );
+ STDMETHOD_(void,Free) ( void *pvMemToFree );
+ STDMETHOD_(ULONG,GetSize) ( void * pv );
+ STDMETHOD_(void,HeapMinimize) ( void );
+ STDMETHOD_(int,DidAlloc) ( void * pv );
+
+ inline SCODE Sync(void);
+ inline DFLUID IncrementLuid(void);
+
+#if !defined(MULTIHEAP)
+ SCODE Init ( LPWSTR pszName );
+#else
+ SCODE Init ( ULONG ulHeapName, BOOL fUnmarshal );
+#endif
+
+ inline void * GetBase(void);
+
+ // This function is equivalent to Free above, except that is does
+ // not attempt to first acquire the mutex. It should be used ONLY
+ // when the calling function guarantees to already have the mutex.
+ void FreeNoMutex (void * pv);
+#if !defined(MULTIHEAP)
+ inline CDfMutex * GetMutex (void);
+#endif
+#ifdef MULTIHEAP
+ void SetState (CSharedMemoryBlock *psmb, BYTE * pbBase,
+ ULONG ulHeapName, CPerContext ** ppcPrev,
+ CPerContext *ppcOwner);
+ void GetState (CSharedMemoryBlock **ppsmb, BYTE ** ppbBase,
+ ULONG *pulHeapName);
+ inline const ULONG GetHeapName ();
+ SCODE Uninit ();
+ inline const ULONG GetHeapSize () { return _cbSize; };
+#endif
+
+private:
+ inline void DoFree (void *pv);
+#if !defined(MULTIHEAP)
+ CDfMutex _dmtx;
+#endif
+//
+// Take advantage of Windows 95 Shared Heap.
+//
+#if !defined(_CHICAGO_)
+
+ CBlockHeader * FindBlock(ULONG cb, CBlockHeader **ppbhPrev);
+
+ inline CHeapHeader *GetHeader(void);
+
+ inline CBlockHeader * GetAddress(ULONG ulOffset) const;
+ inline ULONG GetOffset(CBlockHeader *pbh) const;
+
+ inline SCODE Reset(void);
+#if DBG == 1
+ void PrintFreeBlocks(void);
+#ifdef MULTIHEAP
+ void PrintAllocatedBlocks(void);
+#endif
+#endif
+
+#ifdef MULTIHEAP
+ CSharedMemoryBlock *_psmb;
+ BYTE *_pbBase;
+ ULONG _cbSize;
+ CPerContext * _ppcOwner;
+ ULONG _ulHeapName;
+ ULONG _cRefs; // yes, this object has a lifetime now
+#else
+ CSharedMemoryBlock _smb;
+
+ BYTE *_pbBase;
+
+ ULONG _cbSize;
+#endif // MULTIHEAP
+
+#else // defined(_CHICAGO_)
+
+ HANDLE m_hSharedHeap;
+
+#endif // !defined(_CHICAGO_)
+};
+
+#ifdef MULTIHEAP
+extern CSmAllocator g_SmAllocator; // single-threaded allocator
+extern CSharedMemoryBlock g_smb; //performance optimization
+extern ULONG g_ulHeapName;
+extern CSmAllocator& GetTlsSmAllocator(); // all other threads
+#define g_smAllocator (GetTlsSmAllocator())
+
+#else
+extern CSmAllocator g_smAllocator;
+#endif
+extern CRITICAL_SECTION g_csScratchBuffer;
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::CSmAllocator, public
+//
+// Synopsis: Constructor
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+//
+//----------------------------------------------------------------------------
+
+inline CSmAllocator::CSmAllocator(void)
+#if !defined(_CHICAGO_)
+#ifdef MULTIHEAP
+ : _cbSize(0), _pbBase(NULL), _cRefs(1), _ulHeapName(0),
+ _psmb(NULL), _ppcOwner(NULL)
+#else
+ : _cbSize(0)
+#endif // MULTIHEAP
+#else
+ : m_hSharedHeap(NULL)
+#endif
+{
+#if !defined(MULTIHEAP)
+ InitializeCriticalSection(&g_csScratchBuffer);
+#ifdef COORD
+ InitializeCriticalSection(&g_csResourceList);
+#endif
+#endif // MULTIHEAP
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::~CSmAllocator, public
+//
+// Synopsis: Destructor
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+// 10-May-95 KentCe Defer Heap Destruction to the last
+// process detach.
+//
+//----------------------------------------------------------------------------
+
+inline CSmAllocator::~CSmAllocator(void)
+{
+#if !defined(MULTIHEAP)
+ DeleteCriticalSection(&g_csScratchBuffer);
+#ifdef COORD
+ DeleteCriticalSection(&g_csResourceList);
+#endif
+#endif // MULTIHEAP
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Sync, public
+//
+// Synopsis: Sync memory to global state.
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CSmAllocator::Sync(void)
+{
+ SCODE sc = S_OK;
+#if !defined(_CHICAGO_)
+#if !defined(MULTIHEAP)
+ if (!_smb.IsSynced())
+ {
+ CLockDfMutex lckdmtx(_dmtx);
+
+ sc = _smb.Sync();
+ _cbSize = _smb.GetSize();
+ }
+#else
+ if (!_psmb->IsSynced())
+ {
+ sc = _psmb->Sync();
+ }
+ _cbSize = _psmb->GetSize();
+#endif
+
+#endif
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::IncrementLuid, public
+//
+// Synopsis: Increments the global LUID
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+// History: 06-Apr-95 HenryLee Created
+//----------------------------------------------------------------------------
+
+inline DFLUID CSmAllocator::IncrementLuid(void)
+{
+#if !defined(MULTIHEAP)
+ CLockDfMutex lckdmx(_dmtx);
+#endif
+
+#ifdef _CHICAGO_
+ //
+ // On Chicago, we merely increment the globally available
+ // LUID to the next value.
+ //
+ return ++gs_dfluid;
+#else
+ return GetHeader()->IncrementLuid();
+#endif
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::GetBase, public
+//
+// Synopsis: Return pointer to base of heap
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+//
+//----------------------------------------------------------------------------
+
+inline void * CSmAllocator::GetBase(void)
+{
+#if defined(_CHICAGO_)
+ return NULL;
+#else
+ return _pbBase;
+#endif
+}
+
+#if !defined(MULTIHEAP)
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::GetMutex, public
+//
+// Synopsis: Return a pointer to the Mutex
+//
+// History: 19-Jul-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+inline CDfMutex * CSmAllocator::GetMutex(void)
+{
+ return &_dmtx;
+}
+#endif
+
+//
+// Take advantage of Windows 95 Shared Heap.
+//
+#if !defined(_CHICAGO_)
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::GetAddress, private
+//
+// Synopsis: Returns an address given an offset from the base
+//
+// Arguments: [ulOffset] -- Offset to convert to address
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CBlockHeader * CSmAllocator::GetAddress(ULONG ulOffset) const
+{
+ return (ulOffset == 0) ? NULL : (CBlockHeader *)(_pbBase + ulOffset);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::GetOffset
+//
+// Synopsis: Returns a byte offset from the base given a pointer
+//
+// Arguments: [pbh] -- Pointer to convert to offset
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CSmAllocator::GetOffset(CBlockHeader *pbh) const
+{
+ memAssert((BYTE *)pbh >= _pbBase && (BYTE*)pbh < _pbBase + _cbSize);
+ return (ULONG)pbh - (ULONG)_pbBase;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::GetHeader, private
+//
+// Synopsis: Return pointer to CHeapHeader for this heap
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CHeapHeader * CSmAllocator::GetHeader(void)
+{
+ return (CHeapHeader *)_pbBase;
+}
+
+#ifdef MULTIHEAP
+//+-------------------------------------------------------------------------
+//
+// Member: CSmAllocator::HeapName, public
+//
+// Synopsis: Return the luid part of the shared heap name
+//
+// History: 30-Nov-95 HenryLee Created
+//
+//--------------------------------------------------------------------------
+inline const ULONG CSmAllocator::GetHeapName()
+{
+ return _ulHeapName;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::ResetAllocedBlocks, public
+//
+// Synopsis: Reset the allocated block counter
+//
+// History: 04-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CHeapHeader::ResetAllocedBlocks(void)
+{
+ _ulAllocedBlocks = 0;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::IncrementAllocedBlocks, public
+//
+// Synopsis: Increment the allocated block count
+//
+// History: 04-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CHeapHeader::IncrementAllocedBlocks(void)
+{
+ return ++_ulAllocedBlocks;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::DecrementAllocedBlocks, public
+//
+// Synopsis: Decrement the allocated block count
+//
+// History: 04-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CHeapHeader::DecrementAllocedBlocks(void)
+{
+ return --_ulAllocedBlocks;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::GetAllocedBlocks, public
+//
+// Synopsis: Return the allocated block count
+//
+// History: 04-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CHeapHeader::GetAllocedBlocks(void)
+{
+ return _ulAllocedBlocks;
+}
+
+#endif // !defined(_CHICAGO_)
+
+#endif // #ifndef __HEAP_HXX__
+
diff --git a/private/ole32/dcomss/objex/shrmem/test.acf b/private/ole32/dcomss/objex/shrmem/test.acf
new file mode 100644
index 000000000..347a4fe9a
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/test.acf
@@ -0,0 +1,3 @@
+[ implicit_handle (handle_t SMTBinding)] interface SharedMemoryTest
+{
+}
diff --git a/private/ole32/dcomss/objex/shrmem/test.idl b/private/ole32/dcomss/objex/shrmem/test.idl
new file mode 100644
index 000000000..b6814be0c
--- /dev/null
+++ b/private/ole32/dcomss/objex/shrmem/test.idl
@@ -0,0 +1,40 @@
+[
+ uuid (7e1de6b0-5cbd-11cf-af39-00aa00b50686),
+ version (1.0),
+ pointer_default (unique)
+]
+
+interface SharedMemoryTest
+{
+
+import "obase.idl";
+
+/*
+ * Send the offset of a shared block to another process which returns the contents.
+ */
+
+void RemoteRead
+ (
+ [in] unsigned long offset,
+ [out] long * value
+ );
+
+void SendList
+ (
+ [in] unsigned long list_offset
+ );
+
+void ReadNext
+ (
+ [out] unsigned long * value
+ );
+
+void GetIds
+ (
+ [out] OXID * pOxid,
+ [out] OID * pOid
+ );
+
+void ShutDown();
+
+}
diff --git a/private/ole32/dcomss/objex/soid.hxx b/private/ole32/dcomss/objex/soid.hxx
new file mode 100644
index 000000000..7e83d1ec3
--- /dev/null
+++ b/private/ole32/dcomss/objex/soid.hxx
@@ -0,0 +1,142 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ soid.hxx
+
+Abstract:
+
+ CServerOid objects represent OIDs belonging to processes on the local machine.
+ A COid's are reference counted by CServerSets which periodically check if the
+ process is still running.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-22-95 Bits 'n pieces
+ MarioGo 04-04-95 Split client and server.
+
+--*/
+
+#ifndef __SOID_HXX
+#define __SOID_HXX
+
+
+class CServerOidPList : public CPList
+{
+public:
+ CServerOid *
+ MaybeRemoveMatchingOxid(CTime &when,
+ CServerOid *pOid);
+
+};
+
+class CServerOid : public CIdTableElement
+/*++
+
+Class Description:
+
+ Each instance of this class represents an OID registered
+ by a server on this machine. If this OID is not pinged
+ by a client for a timeout period it is rundown.
+
+Members:
+
+ _pOxid - A pointer to the OXID which registered this OID.
+ We own a reference.
+
+ _plist - A CPListElement used to manage OID which are not
+ part of a client set. The worker thread uses this
+ CPList to manage the rundown on unpinged OIDs.
+
+ _fRunningDown - Flag used to prevent multiple threads
+ from trying to rundown the same OID multiple times.
+ Only 1 bit is required.
+
+--*/
+ {
+ private :
+
+ CServerOxid *_pOxid;
+ CPListElement _plist;
+ BOOL _fRunningDown:1;
+ BOOL _fFreed:1;
+
+ public :
+
+ CServerOid(CServerOxid *oxid) :
+ CIdTableElement(AllocateId()),
+ _pOxid(oxid),
+ _fRunningDown(FALSE),
+ _fFreed(FALSE)
+ {
+ _pOxid->Reference();
+ }
+
+ ~CServerOid();
+
+ void KeepAlive();
+
+ void SetRundown(BOOL fRunningDown = TRUE)
+ {
+ ASSERT(gpServerLock->HeldExclusive());
+ ASSERT(_plist.NotInList());
+ _fRunningDown = fRunningDown;
+ }
+
+ BOOL Match(CServerOid *pOid)
+ {
+ return(pOid->_pOxid == _pOxid);
+ }
+
+ BOOL IsRunning()
+ {
+ ASSERT(_pOxid);
+ return(_pOxid->IsRunning());
+ }
+
+ BOOL IsRunningDown()
+ {
+ return(_fRunningDown);
+ }
+
+ CServerOxid *GetOxid()
+ {
+ return(_pOxid);
+ }
+
+ void Reference();
+
+ DWORD Release();
+
+ static CServerOid *ContainingRecord(CListElement *ple) {
+ return CONTAINING_RECORD(ple, CServerOid, _plist);
+ }
+
+ void Insert() {
+ ASSERT(gpServerLock->HeldExclusive());
+ ASSERT(IsRunningDown() == FALSE);
+ gpServerOidPList->Insert(&_plist);
+ }
+
+ CPListElement *Remove() {
+ return(gpServerOidPList->Remove(&_plist));
+ }
+
+ void Free() {
+ _fFreed = TRUE;
+ }
+
+ BOOL IsFreed() {
+ return(_fFreed);
+ }
+
+ };
+
+#endif // __SOID_HXX
+
diff --git a/private/ole32/dcomss/objex/sources.inc b/private/ole32/dcomss/objex/sources.inc
new file mode 100644
index 000000000..6b327c0b9
--- /dev/null
+++ b/private/ole32/dcomss/objex/sources.inc
@@ -0,0 +1,43 @@
+!IF 0
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Revision History:
+
+!ENDIF
+
+TARGETNAME=objex
+TARGETTYPE=LIBRARY
+
+INCLUDES=$(BASEDIR)\private\dcomidl;$(BASEDIR)\private\dcomidl\obj;..;..\..
+
+
+NTPROFILEINPUT=yes
+BLDCRT=1
+MSC_WARNING_LEVEL=/WX
+
+C_DEFINES=-DNTENV -DWIN32RPC -DNTWIN32RPC -DUNICODE -DMSWMSG
+
+UMTYPE=console
+UMAPPL=
+UMTEST=t*uid
+UMLIBS=$(BASEDIR)\public\sdk\lib\*\rpcrt4.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib \
+ $(BASEDIR)\public\sdk\lib\*\libcmt.lib \
+ obj\*\locks.obj \
+ obj\*\callid.obj
+
+UMRES=
+
diff --git a/private/ole32/dcomss/objex/soxid.hxx b/private/ole32/dcomss/objex/soxid.hxx
new file mode 100644
index 000000000..5f34b18e6
--- /dev/null
+++ b/private/ole32/dcomss/objex/soxid.hxx
@@ -0,0 +1,115 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ soxid.hxx
+
+Abstract:
+
+ CServerOxid objects represent OXIDs which are owned (registered) by processes
+ on this machine. These always contain a pointer to a local process and may not
+ be deleted until the local process has exited and all CServerOids have released
+ them.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-16-95 Bits 'n pieces
+ MarioGo 04-03-95 Split client and server
+
+--*/
+
+#ifndef __SOXID_HXX
+#define __SOXID_HXX
+
+class CServerOxid : public CIdTableElement
+/*++
+
+Class Description:
+
+ Each instance of this class represents an OXID (object exporter,
+ a process or an apartment model thread). Each OXID is owned,
+ referenced, by the owning process and the OIDs registered by
+ that process for this OXID.
+
+
+Members:
+
+ _pProcess - Pointer to the process instance which owns this oxid.
+
+ _info - Info registered by the process for this oxid.
+
+ _fApartment - Server is aparment model if non-zero
+
+ _fRunning - Process has not released this oxid if non-zero.
+
+--*/
+ {
+ friend CProcess;
+
+ private:
+
+ CProcess *_pProcess;
+ OXID_INFO _info;
+ BOOL _fApartment:1;
+ BOOL _fRunning:1;
+
+ public:
+
+ CServerOxid(CProcess *pProcess,
+ BOOL fApartment,
+ OXID_INFO *poxidInfo) :
+ CIdTableElement(AllocateId()),
+ _pProcess(pProcess),
+ _fApartment(fApartment),
+ _fRunning(TRUE)
+ {
+ _info.dwTid = poxidInfo->dwTid;
+ _info.dwPid = poxidInfo->dwPid;
+ _info.dwAuthnHint = poxidInfo->dwAuthnHint;
+ _info.ipidRemUnknown = poxidInfo->ipidRemUnknown;
+ _info.psa = 0;
+
+ _pProcess->Reference();
+ }
+
+ ~CServerOxid(void);
+
+ DWORD GetTid() {
+ return(_info.dwTid);
+ }
+
+ BOOL IsRunning() {
+ return(_fRunning);
+ }
+
+ BOOL Apartment() {
+ return(_fApartment);
+ }
+
+ ORSTATUS GetInfo(OXID_INFO *,
+ BOOL fLocal);
+
+ void RundownOids(USHORT cOids,
+ OID aOids[],
+ BYTE aStatus[]);
+
+ ORSTATUS GetRemoteInfo(OXID_INFO *,
+ USHORT,
+ USHORT[]);
+
+ ORSTATUS LazyUseProtseq(USHORT, USHORT[]);
+
+ protected:
+
+ void ProcessRelease(void);
+
+ };
+
+#endif // __SOXID_HXX
+
diff --git a/private/ole32/dcomss/objex/sset.hxx b/private/ole32/dcomss/objex/sset.hxx
new file mode 100644
index 000000000..f28b10af1
--- /dev/null
+++ b/private/ole32/dcomss/objex/sset.hxx
@@ -0,0 +1,282 @@
+/*++
+
+Copyright (c) 1995-96 Microsoft Corporation
+
+Module Name:
+
+ ssets.hxx
+
+Abstract:
+
+ CServerSet objects represent sets of CServerOids which are owned by
+ a particular client. The same CServerOids may appear in a large
+ number of sets.
+
+ CServerSets are mangaged by an instance of the CServerSetTable
+ class. This object (pServerSets) can be used to allocate (exclusive lock)
+ and lookup (shared lock) sets. It can also be used (shared lock) by
+ the worker thread to rundowns old CServerSet's.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-27-95 Bits 'n pieces
+ MarioGo 04-04-95 Split client and server.
+ MarioGo 01-06-96 Locally unique Ids, added new management class
+
+--*/
+
+#ifndef __SSET_HXX
+#define __SSET_HXX
+
+class CServerSet
+/*++
+
+Class Description:
+
+ Each instance for this class represtents a set of oids which are being
+ used by a particular client. This client may or may not be making secure
+ calls to this objext resolver. If the calls are secure, the SID of the
+ client is remembered and compared during any operation changing the
+ contents of the set.
+
+Members:
+
+ _timeout - The time at which this set should rundown.
+ _blistOids - List of pointers to all the CServerOids in this set.
+ _psid - Security ID of the client. NULL for non-secure set.
+ _sequence - The sequence number of the last good ping. Used to
+ avoid problems with multiple execution since pings are idempotent.
+ _period - Power of two multipler for timeout period. Not implemented.
+ _psid - Pointer to the sid of the client or NULL.
+ _fLocal - (need 1 bit) non-zero if the client is on this machine.
+
+--*/
+ {
+ private:
+ CTime _timeout;
+ PSID _psid;
+ CBList _blistOids;
+ USHORT _sequence;
+ USHORT _pings;
+ USHORT _fLocal:8; // free bits
+ // Free USHORT
+
+
+ BOOL ValidateObjects(BOOL fShared);
+
+ public:
+
+ CServerSet(USHORT sequence,
+ PSID psid,
+ BOOL fLocal) :
+ _blistOids(8),
+ _sequence(sequence - 1),
+ _psid(psid),
+ _fLocal(fLocal)
+ {
+ _timeout += BaseTimeoutInterval; // * factor
+ }
+
+ ~CServerSet()
+ {
+#if DBG
+ CTime now;
+ ASSERT(now > _timeout);
+#endif
+
+ delete _psid;
+ }
+
+ BOOL
+ Ping(BOOL fShared)
+ {
+ _timeout.SetNow();
+ _timeout += BaseTimeoutInterval; // * factor
+ _pings++;
+ if (_pings % BaseNumberOfPings == 0)
+ {
+ return(ValidateObjects(fShared));
+ }
+ return(fShared);
+ }
+
+ BOOL
+ CheckAndUpdateSequenceNumber(USHORT sequence)
+ {
+
+ // note: this handles overflow cases, too.
+ USHORT diff = sequence - _sequence;
+
+ if (diff && diff <= BaseNumberOfPings)
+ {
+ _sequence = sequence;
+ return(TRUE);
+ }
+ return(FALSE);
+ }
+
+ BOOL
+ CheckSecurity(HANDLE hRpc)
+ {
+ // Local calls are secure
+ if (0 == hRpc)
+ {
+ ASSERT(0 == _psid );
+ return(TRUE);
+ }
+
+ // No security on the set
+ if (0 == _psid)
+ {
+ return(TRUE);
+ }
+
+ BOOL f;
+ RPC_STATUS status;
+ HANDLE hT;
+
+ status = RpcImpersonateClient(hRpc);
+
+ if (status == RPC_S_OK)
+ {
+ f = OpenThreadToken(GetCurrentThread(),
+ TOKEN_IMPERSONATE | TOKEN_QUERY,
+ TRUE,
+ &hT);
+ if (!f)
+ {
+ return(FALSE);
+ }
+ }
+ else
+ {
+ #if DBG
+ SetLastError(status);
+ #endif
+
+ return(FALSE);
+ }
+
+ ULONG needed = DEBUG_MIN(1, 24);
+ PTOKEN_USER ptu;
+
+ do
+ {
+ ptu = (PTOKEN_USER)alloca(needed);
+ ASSERT(ptu);
+
+ f = GetTokenInformation(hT,
+ TokenUser,
+ (PBYTE)ptu,
+ needed,
+ &needed);
+
+ }
+ while( FALSE == f && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
+
+ CloseHandle(hT);
+
+ if (FALSE != f)
+ {
+ ASSERT(needed > sizeof(SID));
+
+ f = EqualSid(_psid, ptu->User.Sid);
+ return(f);
+ }
+
+ return(FALSE);
+ }
+
+ ORSTATUS AddObject(OID &oid);
+ void RemoveObject(OID &oid);
+ BOOL ShouldRundown() { CTime now; return(now > _timeout); }
+ BOOL Rundown();
+
+ };
+
+
+class CServerSetTable
+/*++
+
+Class Description:
+
+ Management class for allocating and looking up CServerSets.
+
+ Each set is associated with an ID which is made up of an index
+ and a sequence number. The index is used to index into _pElements
+ and the sequence number is used to avoid problems with old set ID
+ and a new server.
+
+Members:
+
+ _pElements - An array (size _cMax) of IndexElement structures
+ IndexElement-
+ _sequence - A sequence number used to detect invalid
+ referneces to a slot which has rundown and been realloc'd.
+ _pSet - A pointer to the actual CServerSet. If the
+ slot is free it is 0x80000000 & index of next free slot.
+ _cMax - The number of slots in _pElements.
+ _cAllocated - The number of slots in use.
+ _iFirstFree - (Hint) A starting place of where to look when trying
+ to insert. No elements < _iFirstFree are free.
+ _iRundown - Index of the rundown checker. It is written
+ to with a shared lock held. This is okay.
+
+--*/
+{
+ struct IndexElement {
+ DWORD _sequence;
+ CServerSet *_pSet;
+ };
+
+ public:
+
+ CServerSetTable(ORSTATUS &status) :
+ _cMax(DEBUG_MIN(16,4)),
+ _cAllocated(0),
+ _iFirstFree(0),
+ _iRundown(0)
+ {
+ _pElements = new IndexElement[_cMax];
+ if (!_pElements)
+ {
+ status = OR_NOMEM;
+ }
+ else
+ {
+ OrMemorySet(_pElements, 0, sizeof(IndexElement) * _cMax);
+ status = OR_OK;
+ }
+ }
+
+ CServerSet *Allocate(IN USHORT sequence,
+ IN PSID psid,
+ IN BOOL fLocal,
+ OUT ID &setid);
+
+ CServerSet *Lookup(IN ID setid);
+
+ DWORD Size() {
+ return(_cAllocated);
+ }
+
+ // Used for set cleanup by worker and SimplePing.
+
+ ID CheckForRundowns();
+ BOOL RundownSetIfNeeded(SETID id);
+
+ private:
+
+ IndexElement *_pElements;
+ DWORD _cMax;
+ DWORD _cAllocated;
+ DWORD _iFirstFree;
+ DWORD _iRundown;
+};
+
+#endif // __SSET_HXX
+
diff --git a/private/ole32/dcomss/objex/string.cxx b/private/ole32/dcomss/objex/string.cxx
new file mode 100644
index 000000000..4d391ea2f
--- /dev/null
+++ b/private/ole32/dcomss/objex/string.cxx
@@ -0,0 +1,683 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ String.cxx
+
+Abstract:
+
+ Methods of construction of various kinds of DUALSTRINGARRAYs.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 04-01-95 Bits 'n pieces
+ MarioGO 01-??-96 STRINGARRAYs replaced by DUALSTRINGARRAYs
+
+--*/
+
+#include <or.hxx>
+
+static CONST WCHAR aCallbackSecurity[] = L"Security=Identification Dynamic True";
+static CONST DWORD dwCallbackSecurityLength = sizeof(aCallbackSecurity)/sizeof(WCHAR);
+
+RPC_BINDING_HANDLE
+GetBinding(
+ IN PWSTR pCompressedBinding
+ )
+{
+ ASSERT(pCompressedBinding);
+
+ PWSTR pwstrStringBinding;
+ PWSTR pwstrProtseq = GetProtseq(*pCompressedBinding);
+ PWSTR pwstrT;
+ RPC_STATUS Status;
+ RPC_BINDING_HANDLE bhReturn;
+ BOOL fLocal = FALSE;
+
+ if (!pwstrProtseq)
+ {
+ return(0);
+ }
+
+ int size = OrStringLen(pwstrProtseq) + OrStringLen(pCompressedBinding);
+
+ if (*pCompressedBinding == ID_LPC)
+ {
+ fLocal = TRUE;
+ size += dwCallbackSecurityLength + 1; // +1 for ','
+ }
+
+ pwstrStringBinding = (PWSTR) alloca(size * sizeof(USHORT));
+ if (!pwstrStringBinding)
+ {
+ return(0);
+ }
+
+ OrStringCopy(pwstrStringBinding, pwstrProtseq);
+ pwstrT = OrStringSearch(pwstrStringBinding, 0);
+ *pwstrT = L':';
+ pwstrT++;
+ *pwstrT = 0;
+ OrStringCopy(pwstrT, pCompressedBinding + 1);
+
+ if (fLocal)
+ {
+ // We assume we have an endpoint.
+
+ pwstrT = OrStringSearch(pwstrT, 0);
+ pwstrT--;
+ if (*pwstrT != L']')
+ {
+ OrDbgPrint(("OR: Local string binding missing endpoint %S\n",
+ pwstrStringBinding));
+ ASSERT(0);
+ return(0);
+ }
+
+ *pwstrT = L',';
+ pwstrT++;
+ OrStringCopy(pwstrT, aCallbackSecurity);
+ pwstrT = OrStringSearch(pwstrT, 0);
+ *pwstrT = L']';
+ *(pwstrT + 1) = 0;
+ }
+
+ Status =
+ RpcBindingFromStringBinding( pwstrStringBinding,
+ &bhReturn);
+
+#if DBG
+ if (Status != RPC_S_OK)
+ {
+ OrDbgPrint(("OR: Unable to create binding for %S = %d\n",
+ pwstrStringBinding,
+ Status));
+ }
+#endif
+
+ return(bhReturn);
+}
+
+
+RPC_BINDING_HANDLE
+GetBindingToOr(
+ IN PWSTR pwstrCompressedBinding
+ )
+/*++
+
+Routine Description:
+
+ Gets an RPC binding to a remote object resolver given
+ a compressed string binding to the remote object resolver.
+
+Arguments:
+
+ pwstrCompressedBinding - a compressed string binding without an endpoint.
+
+Return Value:
+
+ 0 - failed to allocate memory or RpcBindingFromStringBinding failed.
+
+ non-NULL - completed okay
+
+--*/
+{
+ PWSTR protseq, endpoint;
+ PWSTR strbinding;
+ USHORT len;
+ RPC_BINDING_HANDLE bh = 0;
+
+ ASSERT(pwstrCompressedBinding);
+ ASSERT(*pwstrCompressedBinding != 0);
+
+ protseq = GetProtseq(*pwstrCompressedBinding);
+ endpoint = GetEndpoint(*pwstrCompressedBinding);
+
+ if (0 == protseq || 0 == endpoint)
+ {
+ ASSERT(0);
+ return(0);
+ }
+
+ len = 4; // ':' '[' ']' and '\0'
+ len += OrStringLen(protseq);
+ len += OrStringLen(endpoint);
+ len += OrStringLen(&pwstrCompressedBinding[1]);
+
+ strbinding = new USHORT[len];
+
+ if (strbinding)
+ {
+ PWSTR pwstrT;
+
+ OrStringCopy(strbinding, protseq); // protseq
+
+ pwstrT = OrStringSearch(strbinding, 0); // :
+ *pwstrT = L':';
+ pwstrT++;
+ *pwstrT = 0;
+
+ OrStringCat(strbinding, &pwstrCompressedBinding[1]); // network address
+
+ pwstrT = OrStringSearch(strbinding, 0); // [
+ *pwstrT = L'[';
+ pwstrT++;
+ *pwstrT = 0;
+
+ OrStringCat(strbinding, endpoint); // endpoint
+
+ pwstrT = OrStringSearch(strbinding, 0); // ]
+ *pwstrT = L']';
+ pwstrT++;
+ *pwstrT = 0;
+
+ RPC_STATUS status = RpcBindingFromStringBinding(strbinding, &bh);
+
+ ASSERT(bh == 0 || status == RPC_S_OK);
+
+ delete strbinding;
+ }
+
+ if (bh == 0)
+ {
+ OrDbgDetailPrint(("OR: Unable to bind to %S\n", pwstrCompressedBinding + 1));
+ }
+
+ return(bh);
+}
+
+
+DUALSTRINGARRAY *
+GetStringBinding(
+ IN PWSTR pwstrCompressed,
+ IN PWSTR pwstrSecurityBindings
+ )
+/*++
+
+Routine Description:
+
+ Converts the compressed string binding into an expanded
+ string binding. An enpoint maybe optionally specified.
+
+Arguments:
+
+ pwstrCompressed - a compressed string binding
+
+ pwstrSecurityBindings - optional security bindings
+ too be tacked onto the end of the expanded string binding.
+ Terminated by two nulls.
+
+Return Value:
+
+ NULL - out of memory
+
+ non-NULL - a string binding. Allocated with MIDL_user_allocate.
+--*/
+{
+ DUALSTRINGARRAY *pT;
+ PWSTR protseq;
+ DWORD seccount;
+
+ PWSTR t = pwstrSecurityBindings;
+ if (t && *t)
+ {
+ seccount = 0;
+ do
+ {
+ seccount++;
+ t++;
+
+ if (*t == 0)
+ {
+ seccount++;
+ t++;
+ }
+ }
+ while(*t);
+
+ seccount++; // final NULL
+ }
+ else
+ {
+ // Two nulls only.
+ seccount = 2;
+ }
+
+ protseq = GetProtseq(*pwstrCompressed);
+
+ int l = OrStringLen(pwstrCompressed) + OrStringLen(protseq) + seccount + 1 + 1;
+
+ pT =(DUALSTRINGARRAY *)MIDL_user_allocate(sizeof(DUALSTRINGARRAY) + l * sizeof(WCHAR));
+
+ if (!pT)
+ {
+ return (0);
+ }
+
+ pT->wNumEntries = l;
+ OrStringCopy(pT->aStringArray, protseq);
+ OrStringCat(pT->aStringArray, L":");
+ OrStringCat(pT->aStringArray, pwstrCompressed + 1);
+
+ if (pwstrSecurityBindings)
+ {
+ PWSTR t = pT->aStringArray;
+ t = OrStringSearch(t, 0);
+ t++;
+ *t = 0; // Second NULL on string bindings.
+ t++;
+ OrMemoryCopy(t, pwstrSecurityBindings, seccount*sizeof(WCHAR));
+ }
+ else
+ {
+ // Add three NULLs, total of four.
+ PWSTR t = pT->aStringArray;
+ t = OrStringSearch(t, 0);
+ t[1] = 0;
+ t[2] = 0;
+ t[3] = 0;
+ }
+
+ pT->wSecurityOffset = pT->wNumEntries - seccount;
+
+ ASSERT(dsaValid(pT));
+
+ return(pT);
+}
+
+
+ORSTATUS
+ConvertToRemote(
+ IN DUALSTRINGARRAY *pdsaLocal,
+ OUT DUALSTRINGARRAY **ppdsaRemote
+ )
+/* ++
+
+Parameters:
+ pdsaLocal - An array of string bindings with compressed protseqs.
+
+ ppdsaRemote - Will contain only those string bindings in pdsaLocal
+ which are not "IsLocal()".
+
+ Note: *ppdsaRemote maybe used as a flag, don't set it to non-NULL
+ until it is valid.
+
+-- */
+{
+ int iTotalSize;
+ int iSize;
+ USHORT *p1, *p2;
+ DUALSTRINGARRAY *pdsaT;
+
+ // Size remote array
+
+ // Final null terminator
+ iSize = 1;
+
+ p1 = pdsaLocal->aStringArray;
+
+ while(*p1)
+ {
+ if (! IsLocal(*p1) )
+ {
+ iSize += OrStringLen(p1) + 1;
+ }
+ p1 = OrStringSearch(p1, 0) + 1;
+ }
+
+ if (iSize == 1)
+ {
+ iSize = 2; // No non-local strings, need two terminators.
+ }
+
+ iTotalSize = iSize + (pdsaLocal->wNumEntries - pdsaLocal->wSecurityOffset);
+
+ pdsaT = new(iTotalSize * sizeof(WCHAR)) DUALSTRINGARRAY;
+
+ if (!pdsaT)
+ {
+ return(OR_NOMEM);
+ }
+
+ pdsaT->wNumEntries = iTotalSize;
+ pdsaT->wSecurityOffset = iSize;
+
+ p2 = pdsaT->aStringArray;
+
+ // Copy security bindings
+ OrMemoryCopy(p2 + iSize,
+ pdsaLocal->aStringArray + pdsaLocal->wSecurityOffset,
+ (iTotalSize - iSize) * sizeof(WCHAR));
+
+ if (iSize == 2)
+ {
+ // No non-local strings, fill in terminators and return.
+ *p2 = 0;
+ *(p2 + 1) = 0;
+ *ppdsaRemote = pdsaT;
+
+ ASSERT(dsaValid(pdsaT));
+ return(OR_OK);
+ }
+
+ p1 = pdsaLocal->aStringArray;
+
+ while(*p1)
+ {
+ if ( ! IsLocal(*p1) )
+ {
+ OrStringCopy(p2, p1);
+ p2 = OrStringSearch(p2, 0) + 1;
+ }
+
+ p1 = OrStringSearch(p1, 0) + 1;
+ }
+
+ *p2 = 0; // Second terminator.
+
+ *ppdsaRemote = pdsaT;
+
+ ASSERT(dsaValid(pdsaT));
+ return(OR_OK);
+}
+
+
+DUALSTRINGARRAY *
+CompressStringArray(
+ IN DUALSTRINGARRAY *pdsaExpanded
+ )
+/*++
+
+Routine Description:
+
+ Converts a stringarray of regular string bindings into a
+ compressed (protseq's replaced with WORD id's) array of
+ string bindings.
+
+Arguments:
+
+ pdsaExpanded - the string array to compress.
+ Security information is copied.
+
+Return Value:
+
+ 0 - failed to allocate memory.
+
+ non-0 - compressed string array.
+
+--*/
+{
+ int i, size;
+ USHORT *p1, *p2, *p3;
+ PWSTR pwstr;
+ DUALSTRINGARRAY *pdsaCompressed;
+
+ // Compute size of result.
+
+ p1 = pdsaExpanded->aStringArray;
+
+ size = pdsaExpanded->wNumEntries - pdsaExpanded->wSecurityOffset;
+
+ if (*p1 == 0)
+ {
+ size += 2; // two null terminators ONLY.
+ }
+ else
+ {
+ size += 1; // last null terminator
+ }
+
+ while(*p1)
+ {
+ int sizeT = OrStringLen(p1);
+
+ p2 = OrStringSearch(p1, L':'); // ':' is not valid in protseq.
+ if (p2)
+ {
+ size += sizeT + 1 - (p2 - p1); // proseq len (p2 - p1) become 1 for Id.
+ }
+ else
+ {
+ ASSERT(p2);
+ }
+
+ p1 = OrStringSearch(p2, 0) + 1;
+ }
+
+ pdsaCompressed = new(size * sizeof(WCHAR)) DUALSTRINGARRAY;
+
+ if (0 == pdsaCompressed)
+ {
+ return(0);
+ }
+
+ pdsaCompressed->wNumEntries = size;
+ pdsaCompressed->wSecurityOffset = size - (pdsaExpanded->wNumEntries - pdsaExpanded->wSecurityOffset);
+ p3 = pdsaCompressed->aStringArray;
+ *p3 = 0;
+
+ p1 = pdsaExpanded->aStringArray;
+
+ if (*p1 == 0)
+ {
+ // Loop won't be entered, point p3 to second null terminator
+ p3++;
+ }
+
+ while(*p1)
+ {
+ p2 = OrStringSearch(p1, L':');
+ if (p2)
+ {
+ *p2 = 0;
+ *p3 = GetProtseqId(p1);
+ *p2 = L':';
+ if (*p3 != 0)
+ {
+ p3++;
+ p1 = p2 + 1; // Just after ':'
+ OrStringCopy(p3, p1);
+
+ // Move p3 to start of next string if any.
+ p3 = OrStringSearch(p3, 0) + 1;
+ }
+ }
+
+ // Move p1 to start of next string if any.
+ p1 = OrStringSearch(p1, 0) + 1;
+ }
+
+ // Second terminator, p3 already points to it.
+ *p3 = 0;
+
+ // Copy security bindings
+ OrMemoryCopy(p3 + 1,
+ pdsaExpanded->aStringArray + pdsaExpanded->wSecurityOffset,
+ (pdsaExpanded->wNumEntries - pdsaExpanded->wSecurityOffset) * sizeof(WCHAR));
+
+ ASSERT(dsaValid(pdsaCompressed));
+
+ return(pdsaCompressed);
+}
+
+
+USHORT
+FindMatchingProtseq(
+ IN USHORT cClientProtseqs,
+ IN USHORT aClientProtseqs[],
+ IN PWSTR pwstrServerBindings
+ )
+/*++
+
+Routine Description:
+
+ Finds the first protseq id in aClientProtseqs which appears in any of
+ the server bindings.
+
+Arguments:
+
+ cClientProtseqs - the number of entries in aClientProtseqs.
+ aClientProtseqs - Protseq tower id's support by the client.
+ pwstrServerBindings - compressed array of bindings supported by the server
+ terminated by two NULLs.
+
+Return Value:
+
+ 0 - no match found.
+ non-0 - the matching protseq id.
+
+--*/
+
+// Called by server oxid's and processes when checking for lazy use protseq.
+{
+ ULONG i;
+
+ if (0 == cClientProtseqs)
+ {
+ return(0);
+ }
+
+ while(*pwstrServerBindings)
+ {
+ for(i = 0; i < cClientProtseqs; i++)
+ {
+ if (aClientProtseqs[i] == *pwstrServerBindings)
+ {
+ return(aClientProtseqs[i]);
+ }
+ }
+ pwstrServerBindings = OrStringSearch(pwstrServerBindings, 0) + 1;
+ }
+
+ return(0);
+}
+
+
+
+PWSTR
+FindMatchingProtseq(
+ IN USHORT protseq,
+ IN PWSTR pwstrCompressedBindings
+ )
+/*++
+
+Routine Description:
+
+ Searches a compressed string array for an entry which
+ matches a particular protseq.
+
+
+Arguments:
+
+ protseq - The protseq to search for.
+
+ pwstrCompressedBindings - The bindings to search.
+
+Return Value:
+
+ 0 - not found
+
+ non-0 - a pointer into the pwstrCompressedBindings
+
+--*/
+{
+ ASSERT(pwstrCompressedBindings);
+
+ while(*pwstrCompressedBindings)
+ {
+ if (*pwstrCompressedBindings == protseq)
+ {
+ return(pwstrCompressedBindings);
+ }
+ pwstrCompressedBindings = OrStringSearch(pwstrCompressedBindings, 0) + 1;
+ }
+ return(0);
+}
+
+
+BOOL
+TestBinding(
+ IN PWSTR pwstrCompressedBinding
+ )
+/*++
+
+Routine Description:
+
+ Tests that an OR can be found on the machine identified by the
+ compressed binding.
+
+Arguments:
+
+ pwstrCompressedBiding - A compressed stringing binding to the
+ server in question. May include an endpoint to something
+ other then the endpoint mapper.
+
+Return Value:
+
+ None
+
+--*/
+{
+ PWSTR pwstrT;
+ PWSTR pwstrCopy = (PWSTR)alloca( (OrStringLen(pwstrCompressedBinding) + 1)
+ * sizeof(WCHAR) );
+
+ if (pwstrCopy == 0)
+ {
+ return(FALSE);
+ }
+
+ OrStringCopy(pwstrCopy, pwstrCompressedBinding);
+
+ // We need to wack the endpoint out of the string binding.
+ // Go read the runtime's string parsing stuff if you're not
+ // sure what this is doing. Note: on Win9x this needs to
+ // be DBCS enabled...
+
+#ifndef NTENV
+ #message "Error: string.cxx(): this won't work"
+#endif
+ pwstrT = pwstrCopy;
+
+ while (*pwstrT && *pwstrT != L'[')
+ {
+ if (*pwstrT == L'\\')
+ {
+ pwstrT++;
+ }
+ pwstrT++;
+ }
+
+ if (*pwstrT)
+ {
+ ASSERT(*pwstrT == L'[');
+ *pwstrT = 0;
+ // Endpoint gone.
+ }
+
+ RPC_BINDING_HANDLE hTest = GetBindingToOr(pwstrCopy);
+
+ if (0 == hTest)
+ {
+ return(FALSE);
+ }
+
+ RPC_STATUS status = ServerAlive(hTest);
+
+ RpcBindingFree(&hTest);
+
+ if ( status == RPC_S_OK
+ || status == RPC_S_PROCNUM_OUT_OF_RANGE)
+ {
+ return(TRUE);
+ }
+
+ return(FALSE);
+}
+
diff --git a/private/ole32/dcomss/objex/string.hxx b/private/ole32/dcomss/objex/string.hxx
new file mode 100644
index 000000000..20c9aa44b
--- /dev/null
+++ b/private/ole32/dcomss/objex/string.hxx
@@ -0,0 +1,131 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ String.hxx
+
+Abstract:
+
+ Inline Helper functions for DUALSTRINGARRAY's
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-22-95 Bits 'n pieces
+
+--*/
+
+#ifndef __STRING_HXX
+#define __STRING_HXX
+
+inline void dsaCopy(DUALSTRINGARRAY *pdsaDest, DUALSTRINGARRAY *pdsaSrc)
+{
+ pdsaDest->wNumEntries = pdsaSrc->wNumEntries;
+ pdsaDest->wSecurityOffset = pdsaSrc->wSecurityOffset;
+ OrMemoryCopy(pdsaDest->aStringArray,
+ pdsaSrc->aStringArray,
+ pdsaSrc->wNumEntries*sizeof(USHORT));
+}
+
+inline BOOL dsaValid(DUALSTRINGARRAY *pdsa)
+{
+ if ( pdsa
+ && pdsa->wNumEntries >= 4
+ && FALSE == IsBadWritePtr(pdsa->aStringArray, pdsa->wNumEntries * sizeof(WCHAR))
+ && pdsa->wSecurityOffset <= (pdsa->wNumEntries - 2)
+ && pdsa->aStringArray[(pdsa->wNumEntries - 1)] == 0
+ && pdsa->aStringArray[(pdsa->wNumEntries - 2)] == 0
+ && pdsa->aStringArray[(pdsa->wSecurityOffset - 1)] == 0
+ && pdsa->aStringArray[(pdsa->wSecurityOffset - 2)] == 0
+ )
+ {
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+inline DWORD dsaHash(DUALSTRINGARRAY *pdsa)
+// PERF WORK: Make sure the hash looks good in real world usage.
+{
+ int i, count;
+ DWORD hash, t;
+ count = i = hash = pdsa->wNumEntries;
+ hash |= pdsa->wSecurityOffset << 16;
+
+ for(count = 0; count < i/2; count++)
+ {
+ t = *(PDWORD)&pdsa->aStringArray[count * 2];
+
+ hash += hash ^ t;
+ }
+
+ // we may miss the last word, but it is null anyway.
+
+ return(hash);
+}
+
+inline DWORD dsaCompare(DUALSTRINGARRAY *pdsa, DUALSTRINGARRAY *pdsa2)
+{
+ return ( pdsa->wNumEntries == pdsa2->wNumEntries
+ && pdsa->wSecurityOffset == pdsa2->wSecurityOffset
+ && 0 == OrMemoryCompare(pdsa->aStringArray,
+ pdsa2->aStringArray,
+ pdsa->wNumEntries * sizeof(WCHAR)) );
+}
+
+inline PWSTR OrStringSearch(PWSTR string, USHORT value)
+{
+ // Faster and smaller then wcschr() for value == 0
+ if (value == 0)
+ {
+ while(*string)
+ string++;
+ return(string);
+ }
+ return(wcschr(string, value));
+}
+
+RPC_BINDING_HANDLE GetBinding(
+ IN PWSTR pCompressedBinding
+ );
+
+RPC_BINDING_HANDLE GetBindingToOr(
+ IN PWSTR pCompressedBinding
+ );
+
+DUALSTRINGARRAY *GetStringBinding(
+ IN PWSTR pwstrCompressed,
+ IN PWSTR pwstrSecurityBindings
+ );
+
+ORSTATUS ConvertToRemote(
+ IN DUALSTRINGARRAY *psaLocal,
+ OUT DUALSTRINGARRAY **ppsaRemote
+ );
+
+DUALSTRINGARRAY *CompressStringArray(
+ IN DUALSTRINGARRAY *psaExpanded
+ );
+
+USHORT FindMatchingProtseq(
+ IN USHORT cClientProtseqs,
+ IN USHORT aClientProtseqs[],
+ IN PWSTR pwstrServerBindings
+ );
+
+PWSTR FindMatchingProtseq(
+ IN USHORT protseq,
+ IN PWSTR pswstrBindings
+ );
+
+BOOL TestBinding(
+ IN PWSTR pwstrCompressedBinding
+ );
+
+#endif // __STRING_HXX
+
diff --git a/private/ole32/dcomss/objex/time.hxx b/private/ole32/dcomss/objex/time.hxx
new file mode 100644
index 000000000..b9ff5e147
--- /dev/null
+++ b/private/ole32/dcomss/objex/time.hxx
@@ -0,0 +1,108 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Time.hxx
+
+Abstract:
+
+ The CTime class represents time for this process. Instances of this class
+ should be small 4-8 bytes and cheap to create.
+
+ The current implementation is just a wrapper for GetTickCount() which
+ handles overflow.
+ (4GB milliseconds is just under 50 days. This implementation is correctly
+ compare times up to 25 days appart.).
+
+Note:
+ This class should return consistent results even if the system time
+ is set forwards or backwards.
+ (Use GetTickCount() rather then GetSystemTimeAsFileTime()).
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 02-23-95 Bits 'n pieces
+
+--*/
+
+#ifndef __TIME_HXX
+#define __TIME_HXX
+
+#define TICKS_PER_SECOND (1000) // Ticks are milliseconds
+
+class CTime
+ {
+ private:
+ DWORD _Time;
+
+ public:
+
+ CTime() { SetNow(); }
+
+ // Used to avoid a call to GetTickCount()
+ CTime(DWORD time) : _Time(time) { }
+
+ void
+ SetNow() {
+ _Time = GetTickCount();
+ }
+
+ void
+ Sleep()
+ {
+ DWORD diff = _Time - GetTickCount();
+ if ( diff > (2 * BaseTimeoutInterval) * 1000 )
+ {
+ // Maybe overactive under stress. We're trying to sleep until a time
+ // which has already passed.
+ OrDbgDetailPrint(("Didn't need to sleep until %d from %d\n", _Time, GetTickCount()));
+ return;
+ }
+ SleepEx(diff, FALSE);
+ }
+
+ BOOL operator< (const CTime &Time)
+ {
+ // Is _Time less then Time.
+ DWORD diff = _Time - Time._Time;
+ return( ((LONG)diff) < 0);
+ }
+
+ BOOL operator> (const CTime &Time)
+ {
+ // Is _Time greater then Time.
+ DWORD diff = Time._Time - _Time;
+ return( ((LONG)diff) < 0);
+ }
+
+ BOOL operator<= (const CTime &Time)
+ {
+ return(! operator>(Time));
+ }
+
+ BOOL operator>= (const CTime &Time)
+ {
+ return(! operator<(Time));
+ }
+
+ void operator+=(UINT mSeconds) { _Time += (mSeconds * TICKS_PER_SECOND); }
+
+ void operator-=(UINT mSeconds) { _Time -= (mSeconds * TICKS_PER_SECOND); }
+
+ DWORD operator-(const CTime &Time)
+ {
+ return((_Time - Time._Time)/TICKS_PER_SECOND);
+ }
+
+ // defualt = operator ok.
+
+ };
+
+#endif __TIME_HXX
+
diff --git a/private/ole32/dcomss/objex/token.cxx b/private/ole32/dcomss/objex/token.cxx
new file mode 100644
index 000000000..b34f3b2bf
--- /dev/null
+++ b/private/ole32/dcomss/objex/token.cxx
@@ -0,0 +1,249 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Token.cxx
+
+Abstract:
+
+ Implementation for Windows NT security interfaces.
+
+Platform:
+
+ Windows NT user mode.
+
+Notes:
+
+ Not portable to non-Windows NT platforms.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 12/21/1995 Bits 'n pieces
+
+--*/
+
+#include <or.hxx>
+
+CRITICAL_SECTION gcsTokenLock;
+
+
+ORSTATUS
+LookupOrCreateToken(
+ IN handle_t hCaller,
+ IN BOOL fLocal,
+ OUT CToken **ppToken
+ )
+/*++
+
+Routine Description:
+
+ Finds or allocates a new token object for the caller.
+
+Arguments:
+
+ hCaller - RPC binding handle of the caller of RPCSS.
+
+ fLocal - Looking up a local client, check local security.
+
+ pToken - Upon a successful return this will hold the token.
+ It can be destroyed by calling Release();
+
+Return Value:
+
+
+ OR_OK - success
+ OR_NOACCESS - If the caller is not local, or cannot be impersonated.
+ OR_NOMEM - Unable to allocate an object.
+
+--*/
+{
+ ORSTATUS status;
+ UINT type;
+ HANDLE hClientToken;
+ PSID psid;
+ LUID luid;
+ PTOKEN_USER ptu;
+ TOKEN_STATISTICS ts;
+ BOOL fSuccess;
+
+ if (fLocal)
+ {
+ status = I_RpcBindingInqTransportType(hCaller, &type);
+
+ if (status != RPC_S_OK || type != TRANSPORT_TYPE_LPC)
+ {
+ return(OR_NOACCESS);
+ }
+ }
+
+ status = RpcImpersonateClient(hCaller);
+ if (status != RPC_S_OK)
+ {
+ return(OR_NOACCESS);
+ }
+
+ fSuccess = OpenThreadToken(GetCurrentThread(),
+ TOKEN_IMPERSONATE | TOKEN_DUPLICATE | TOKEN_QUERY,
+ TRUE,
+ &hClientToken);
+
+ if (fSuccess)
+ {
+ DWORD needed = sizeof(ts);
+ fSuccess = GetTokenInformation(hClientToken,
+ TokenStatistics,
+ &ts,
+ sizeof(ts),
+ &needed
+ );
+ if (fSuccess)
+ {
+ needed = DEBUG_MIN(1,24);
+
+ do
+ {
+ ptu = (PTOKEN_USER)alloca(needed);
+ ASSERT(ptu);
+
+ fSuccess = GetTokenInformation(hClientToken,
+ TokenUser,
+ (PBYTE)ptu,
+ needed,
+ &needed);
+ }
+ while ( fSuccess == FALSE && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
+
+ }
+
+ if (fSuccess)
+ {
+ luid = ts.AuthenticationId;
+ psid = ptu->User.Sid;
+
+ ASSERT(IsValidSid(psid) == TRUE);
+
+ CMutexLock lock(&gcsTokenLock);
+ CListElement *ple;
+ CToken *pToken;
+
+ fSuccess = FALSE;
+
+ ple = gpTokenList->First();
+
+ while(ple)
+ {
+ pToken = CToken::ContainingRecord(ple);
+
+ if (pToken->MatchLuid(luid))
+ {
+ pToken->Reference();
+ *ppToken = pToken;
+ CloseHandle(hClientToken);
+ fSuccess = TRUE;
+ break;
+ }
+ else
+ {
+ ple = ple->Next();
+ }
+ }
+
+ if (!fSuccess)
+ {
+ // Didn't find it; allocate and add to the list.
+ needed = GetLengthSid(psid) - sizeof(SID);
+ *ppToken = new(needed) CToken(hClientToken,
+ luid,
+ psid,
+ needed + sizeof(SID));
+
+ if (0 == *ppToken)
+ {
+ CloseHandle(hClientToken);
+ fSuccess = FALSE;
+ }
+ else
+ {
+ (*ppToken)->Insert();
+
+ #if DBG_DETAIL
+ {
+ DWORD d = 50;
+ WCHAR buffer[50];
+ GetUserName(buffer, &d);
+ OrDbgPrint(("OR: New user connected: %S (%p)\n", buffer, *ppToken));
+ }
+ #endif
+
+ fSuccess = TRUE;
+ }
+ }
+ }
+ else
+ {
+ OrDbgPrint(("OR: GetTokenInformation failed %d\n", GetLastError()));
+ ASSERT(GetLastError() != ERROR_INSUFFICIENT_BUFFER);
+ CloseHandle(hClientToken);
+ }
+ }
+ else
+ {
+ OrDbgPrint(("OR: OpenThreadToken failed: %d\n", GetLastError()));
+ }
+
+ status = RpcRevertToSelfEx(hCaller);
+ ASSERT(status == RPC_S_OK);
+
+ if (fSuccess == FALSE)
+ {
+ return(OR_NOMEM);
+ }
+
+ return(OR_OK);
+}
+
+
+CToken::~CToken()
+{
+ CloseHandle(_hImpersonationToken);
+}
+
+DWORD
+CToken::Release()
+{
+ CMutexLock lock(&gcsTokenLock);
+
+ if ( 0 == Dereference() )
+ {
+ Remove();
+ delete this;
+ return(0);
+ }
+ return(1);
+}
+
+void
+CToken::Impersonate()
+{
+ ASSERT(_hImpersonationToken);
+
+ BOOL f = SetThreadToken(0, _hImpersonationToken);
+ ASSERT(f);
+
+ return;
+}
+
+void
+CToken::Revert()
+{
+ BOOL f = SetThreadToken(0, 0);
+ ASSERT(f);
+ return;
+}
+
diff --git a/private/ole32/dcomss/objex/token.hxx b/private/ole32/dcomss/objex/token.hxx
new file mode 100644
index 000000000..080f6c1d9
--- /dev/null
+++ b/private/ole32/dcomss/objex/token.hxx
@@ -0,0 +1,96 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Token.hxx
+
+Abstract:
+
+ Wrapper for holding onto a particular user token.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 12/20/1995 Bits 'n pieces
+
+--*/
+
+#ifndef __TOKEN_HXX
+#define __TOKEN_HXX
+
+class CToken;
+
+extern CRITICAL_SECTION gcsTokenLock;
+
+extern ORSTATUS LookupOrCreateToken(handle_t, BOOL, CToken **);
+
+class CToken : public CReferencedObject
+{
+ public:
+
+ CToken(HANDLE hToken,
+ LUID luid,
+ PSID psid,
+ DWORD dwSize)
+ : _hImpersonationToken(hToken),
+ _luid(luid)
+ {
+ ASSERT(IsValidSid(psid));
+ ASSERT(dwSize == GetLengthSid(psid));
+ OrMemoryCopy(&_sid, psid, dwSize);
+ }
+
+ ~CToken();
+
+ DWORD Release();
+
+ void Impersonate();
+ void Revert();
+
+ LUID GetLuid() {
+ return _luid;
+ }
+
+ PSID GetSid() {
+ return &_sid;
+ }
+
+ HANDLE GetToken() {
+ return _hImpersonationToken;
+ }
+
+ BOOL MatchLuid(LUID luid) {
+ return( luid.LowPart == _luid.LowPart
+ && luid.HighPart == _luid.HighPart);
+ }
+
+ BOOL MatchSid(PSID psid) {
+ return(EqualSid(psid , &_sid));
+ }
+
+ static CToken *ContainingRecord(CListElement *ple) {
+ return CONTAINING_RECORD(ple, CToken, _list);
+ }
+
+ void Insert() {
+ gpTokenList->Insert(&_list);
+ }
+
+ CListElement *Remove() {
+ return(gpTokenList->Remove(&_list));
+ }
+
+ private:
+ CListElement _list;
+ HANDLE _hImpersonationToken;
+ LUID _luid; // Logon id
+ SID _sid; // Security (user) id, dynamically sized)
+};
+
+#endif
+
diff --git a/private/ole32/dcomss/objex/worker.cxx b/private/ole32/dcomss/objex/worker.cxx
new file mode 100644
index 000000000..5598fc493
--- /dev/null
+++ b/private/ole32/dcomss/objex/worker.cxx
@@ -0,0 +1,411 @@
+/*++
+
+Copyright (c) 1995-1996 Microsoft Corporation
+
+Module Name:
+
+ Worker.cxx
+
+Abstract:
+
+ Backgroup activies releated to running down and cleaning up OR and pinging
+ remote OR's are handled here.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 03-02-95 Bits 'n pieces
+ MarioGo 01-18-96 Locally unique IDs
+
+--*/
+
+
+#include <or.hxx>
+
+// PERF WORK: Make sure static c'tor/d'tor code isn't gross..
+static CInterlockedInteger cTaskThreads(0);
+
+#if DBG_DETAIL
+extern "C" void printf(char *, ...);
+#endif
+
+ DWORD WINAPI
+ObjectExporterWorkerThread(LPVOID /* ignored */)
+/*++
+
+Routine Description:
+
+ Main background thread for the object resolver. This thread
+ manages a number of background tasks:
+ Cleaning up the client oxid cache.
+ Running down un-pinged sets.
+ Starting task threads to rundown server OIDs and ping sets.
+
+ This thread must not block for a long time. Task threads
+ should be used for possibly blocking operations like remote
+ pinging and rundown of OIDs.
+
+
+Arguments:
+
+ Ignored
+
+Return Value:
+
+ None - should never return.
+
+--*/
+{
+ ORSTATUS status;
+ CTime now(0);
+ CTime timeout(0);
+ CTime delay(0);
+ CTime start(0);
+ BOOL fCreateThread;
+
+ for(;;)
+ {
+ now.SetNow();
+ delay = now;
+ delay += BasePingInterval;
+
+ // Cleanup old sets.
+ //
+ // Sets are usually cleaned up during processing of pings. (As one set is
+ // pinged, the next set will be checked to see if it needs to be rundown.)
+ //
+ // If there's exactly one set in the table, then it won't be run down except
+ // by this thread.
+ //
+ // NOTE: Similar code in _SimplePing().
+
+ gpServerLock->LockShared();
+
+ ID setid = gpServerSetTable->CheckForRundowns();
+
+ if (setid)
+ {
+ gpServerLock->ConvertToExclusive();
+
+ if (gpServerSetTable->RundownSetIfNeeded(setid))
+ {
+ delay.SetNow();
+ }
+
+ gpServerLock->UnlockExclusive();
+ }
+ else
+ {
+ gpServerLock->UnlockShared();
+ }
+
+ //
+ // Cleanup old Client OXIDs
+ //
+
+ if (gpClientOxidPList->PeekMin(timeout))
+ {
+ if (timeout < now)
+ {
+ CClientOxid *pOxid;
+ CListElement *ple;
+
+ gpClientLock->LockExclusive();
+
+ while (ple = gpClientOxidPList->MaybeRemoveMin(now))
+ {
+ pOxid = CClientOxid::ContainingRecord(ple);
+ delete pOxid;
+ }
+ gpClientLock->UnlockExclusive();
+
+ delay.SetNow();
+ }
+ else
+ {
+ if (delay > timeout)
+ {
+ delay = timeout;
+ }
+ }
+ }
+
+ //
+ // Make sure pinging and rundowns are proceding
+ //
+
+ fCreateThread = FALSE;
+
+ // We want to create an extra task thread if we've fallen
+ // behind on pings. As more threads are created the
+ // requirements for "behind" become harder to meet.
+
+ if (gpClientSetPList->PeekMin(timeout))
+ {
+ start = now;
+ start += (BasePingInterval + 10*cTaskThreads);
+
+ if ( cTaskThreads == 0
+ || start < timeout)
+ {
+ fCreateThread = TRUE;
+ }
+ else
+ if (delay > start)
+ {
+ delay = start;
+ }
+
+ }
+
+ // We want to create an extra task thread if we've fallen
+ // behind in running down local objects. As more threads are
+ // created the requirements for "behind" become harder to meet.
+
+ if (gpServerOidPList->PeekMin(timeout))
+ {
+ start = now;
+ start -= 10*cTaskThreads;
+ if (timeout < start)
+ {
+ fCreateThread = TRUE;
+ }
+ else
+ {
+ start = timeout;
+ start += 2*10*cTaskThreads;
+ if (delay > start)
+ {
+ delay = start;
+ }
+ }
+ }
+
+ if (fCreateThread)
+ {
+ OrDbgDetailPrint(("OR: Creating additional task thread, we're behind..\n"));
+
+ cTaskThreads++;
+
+ DWORD tid;
+ HANDLE hThread = CreateThread(0,
+ 0,
+ ObjectExporterTaskThread,
+ 0,
+ 0,
+ &tid
+ );
+ if (0 != hThread)
+ {
+ CloseHandle(hThread);
+ }
+ else
+ {
+ cTaskThreads--;
+ }
+ }
+
+
+#if DBG_DETAIL
+ printf("================================================================\n"
+ "ServerOxids: %d, ServerOids: %d, ServerSets: %d\n"
+ "ClientOxids: %d, ClientOids: %d, ClientSets: %d\n"
+ "Mids: %d, Processes %d, worker threads: %d\n"
+ "Sleeping for %d seconds...\n",
+ gpServerOxidTable->Size(),
+ gpServerOidTable->Size(),
+ gpServerSetTable->Size(),
+ gpClientOxidTable->Size(),
+ gpClientOidTable->Size(),
+ gpClientSetTable->Size(),
+ gpMidTable->Size(),
+ gpProcessList->Size(),
+ cTaskThreads,
+ delay - now + 1
+ );
+#endif
+ delay += 1;
+ delay.Sleep();
+ }
+
+ return(0);
+}
+
+ DWORD WINAPI
+ObjectExporterTaskThread(LPVOID /* ignored */)
+{
+ CTime now(0);
+ CTime delay(0);
+ CTime timeout(0);
+ ORSTATUS status;
+ CListElement *ple;
+ CClientSet *pSet;
+ CServerOid *pOid;
+
+ enum {
+ Idle, // No work to do at all.
+ Waiting, // No work to do yet.
+ Busy // Did work this iteration.
+ } eState;
+
+ for(;;)
+ {
+ now.SetNow();
+ delay = now;
+ delay += BasePingInterval;
+ eState = Idle;
+
+ // Ping remote sets.
+
+ if (gpClientSetPList->PeekMin(timeout))
+ {
+ eState = Waiting;
+
+ if (now >= timeout)
+ {
+ eState = Busy;
+
+ ple = gpClientSetPList->MaybeRemoveMin(now);
+
+ if (ple)
+ {
+ // Actually ping the set
+
+ pSet = CClientSet::ContainingRecord(ple);
+
+ pSet->PingServer();
+
+ // Set maybe invalid now.
+ }
+ }
+ else
+ {
+ // Not ready to ping yet.
+ delay = timeout;
+ }
+ }
+
+ // Process server OID rundowns
+
+ if (gpServerOidPList->PeekMin(timeout))
+ {
+ if (eState == Idle)
+ eState = Waiting;
+
+ if (now >= timeout)
+ {
+ eState = Busy;
+
+ gpServerLock->LockExclusive();
+
+ CServerOid *apOid[11];
+ OID aRundowns[11];
+ BYTE afRundownOk[11];
+ INT cOids;
+
+ ple = gpServerOidPList->MaybeRemoveMin(now);
+
+ pOid = CServerOid::ContainingRecord(ple);
+
+ if (ple && pOid->IsRunningDown() == FALSE)
+ {
+ apOid[0] = pOid;
+ aRundowns[0] = pOid->Id();
+ cOids = 1;
+ ASSERT(pOid->IsFreed() == FALSE);
+ pOid->SetRundown();
+
+ while(cOids < 11 && pOid)
+ {
+ pOid = gpServerOidPList->MaybeRemoveMatchingOxid(now, apOid[0]);
+
+ if (0 != pOid &&
+ pOid->IsRunningDown() == FALSE)
+ {
+ ASSERT(pOid->IsFreed() == FALSE);
+ pOid->SetRundown();
+ apOid[cOids] = pOid;
+ aRundowns[cOids] = pOid->Id();
+ afRundownOk[cOids] = FALSE;
+ cOids++;
+ }
+ }
+
+ ASSERT(cOids < 12 && cOids >= 1);
+ ASSERT(apOid[0]->GetOxid() == apOid[cOids - 1]->GetOxid());
+
+ // Note: This call will unlock and relock the server lock.
+ // While this happens the oids maybe added, deleted,
+ // added and deleted, added and rundown from one or more sets.
+
+ CServerOxid *pOxid = apOid[0]->GetOxid();
+ pOxid->RundownOids(cOids,
+ aRundowns,
+ afRundownOk);
+
+ ASSERT(!gpServerLock->HeldExclusive());
+ gpServerLock->LockExclusive();
+
+ for(cOids--; 0 <= cOids; cOids--)
+ {
+ pOid = apOid[cOids];
+ ASSERT(pOid);
+ if (pOid->References() != 0)
+ {
+ // Added to a set while running down and still referenced.
+ pOid->SetRundown(FALSE);
+ }
+ else if ( afRundownOk[cOids] == TRUE )
+ {
+ delete pOid;
+ }
+ else
+ {
+ OrDbgDetailPrint(("OR: Randown OID %p but the client kept it alive\n", pOid));
+ // Client want us to keep it alive and is still running.
+ pOid->SetRundown(FALSE);
+ pOid->Insert();
+ }
+ }
+ }
+
+ gpServerLock->UnlockExclusive();
+ }
+ else
+ {
+ // Not ready to rundown yet.
+ if (delay > timeout)
+ {
+ delay = timeout;
+ }
+ }
+ }
+
+ // Decide if this task thread should exit or sleep and loop.
+
+ ASSERT(eState == Idle || eState == Busy || eState == Waiting);
+
+ if ( (eState == Idle)
+ || (eState == Waiting && cTaskThreads > 2))
+ {
+ // No work or we're all caught up and have extra threads.
+ cTaskThreads--;
+ return(0);
+ }
+ else
+ {
+ if (eState == Waiting)
+ {
+ // Sleep until just after the next work item is ready.
+ delay += 1;
+ delay.Sleep();
+ }
+ }
+ }
+
+ return(0);
+}
+
diff --git a/private/ole32/dcomss/olescm/array_fv.cxx b/private/ole32/dcomss/olescm/array_fv.cxx
new file mode 100644
index 000000000..f353069d2
--- /dev/null
+++ b/private/ole32/dcomss/olescm/array_fv.cxx
@@ -0,0 +1,304 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// Implementation of Array of values
+//
+/////////////////////////////////////////////////////////////////////////////
+// NOTE: we allocate an array of 'm_nMaxSize' elements, but only
+// the current size 'm_nSize' contains properly initialized elements
+#include <headers.cxx>
+#pragma hdrstop
+
+#pragma SEG(array_fv)
+ASSERTDATA
+
+#include "scm.hxx"
+#include "scm_afv.h"
+
+#include <limits.h>
+#define SIZE_T_MAX UINT_MAX /* max size for a size_t */
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma SEG(CScmArrayFValue_ctor)
+CScmArrayFValue::CScmArrayFValue(UINT cbValue)
+{
+ m_pData = NULL;
+ m_cbValue = cbValue;
+ m_nSize = m_nMaxSize = m_nGrowBy = 0;
+}
+
+#pragma SEG(CScmArrayFValue_dtor)
+CScmArrayFValue::~CScmArrayFValue()
+{
+ ASSERT_VALID(this);
+
+ ScmMemFree(m_pData);
+}
+
+// set new size; return FALSE if OOM
+
+#pragma SEG(CScmArrayFValue_SetSize)
+BOOL CScmArrayFValue::SetSize(int nNewSize, int nGrowBy /* = -1 */)
+{
+ ASSERT_VALID(this);
+ Assert(nNewSize >= 0);
+
+ if (nGrowBy != -1)
+ m_nGrowBy = nGrowBy; // set new size
+
+ if (nNewSize == 0)
+ {
+ // shrink to nothing
+ ScmMemFree(m_pData);
+ m_pData = NULL;
+ m_nSize = m_nMaxSize = 0;
+ }
+ else if (m_pData == NULL)
+ {
+ // create one with exact size
+ Assert((long)nNewSize * m_cbValue <= SIZE_T_MAX); // no overflow
+
+ m_pData = (BYTE *) ScmMemAlloc(nNewSize * m_cbValue);
+
+ if (m_pData == NULL)
+ return FALSE;
+
+ memset(m_pData, 0, nNewSize * m_cbValue); // zero fill
+ m_nSize = m_nMaxSize = nNewSize;
+ }
+ else if (nNewSize <= m_nMaxSize)
+ {
+ // it fits
+ if (nNewSize > m_nSize)
+ {
+ // initialize the new elements
+ memset(&m_pData[m_nSize * m_cbValue], 0, (nNewSize-m_nSize) * m_cbValue);
+ }
+ m_nSize = nNewSize;
+ }
+ else
+ {
+ // Otherwise grow array
+ int nNewMax;
+ if (nNewSize < m_nMaxSize + m_nGrowBy)
+ nNewMax = m_nMaxSize + m_nGrowBy; // granularity
+ else
+ nNewMax = nNewSize; // no slush
+
+ Assert((long)nNewMax * m_cbValue <= SIZE_T_MAX); // no overflow
+
+ BYTE FAR* pNewData = (BYTE *) ScmMemAlloc(nNewMax * m_cbValue);
+
+ if (pNewData == NULL)
+ return FALSE;
+
+ // copy new data from old
+ memcpy(pNewData, m_pData, m_nSize * m_cbValue);
+
+ // construct remaining elements
+ Assert(nNewSize > m_nSize);
+ memset(&pNewData[m_nSize * m_cbValue], 0, (nNewSize-m_nSize) * m_cbValue);
+
+ // get rid of old stuff (note: no destructors called)
+ ScmMemFree(m_pData);
+ m_pData = pNewData;
+ m_nSize = nNewSize;
+ m_nMaxSize = nNewMax;
+ }
+ ASSERT_VALID(this);
+
+ return TRUE;
+}
+
+#pragma SEG(CScmArrayFValue_FreeExtra)
+void CScmArrayFValue::FreeExtra()
+{
+ ASSERT_VALID(this);
+
+ if (m_nSize != m_nMaxSize)
+ {
+ // shrink to desired size
+ Assert((long)m_nSize * m_cbValue <= SIZE_T_MAX); // no overflow
+
+ BYTE FAR* pNewData = (BYTE *) ScmMemAlloc(m_nSize * m_cbValue);
+ if (pNewData == NULL)
+ return; // can't shrink; don't to anything
+
+ // copy new data from old
+ memcpy(pNewData, m_pData, m_nSize * m_cbValue);
+
+ // get rid of old stuff (note: no destructors called)
+ ScmMemFree(m_pData);
+ m_pData = pNewData;
+ m_nMaxSize = m_nSize;
+ }
+ ASSERT_VALID(this);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma SEG(CScmArrayFValue__GetAt)
+LPVOID CScmArrayFValue::_GetAt(int nIndex) const
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0 && nIndex < m_nSize);
+ return &m_pData[nIndex * m_cbValue];
+}
+
+#pragma SEG(CScmArrayFValue_SetAt)
+void CScmArrayFValue::SetAt(int nIndex, LPVOID pValue)
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0 && nIndex < m_nSize);
+
+ memcpy(&m_pData[nIndex * m_cbValue], pValue, m_cbValue);
+}
+
+#pragma SEG(CScmArrayFValue_SetAtGrow)
+BOOL CScmArrayFValue::SetAtGrow(int nIndex, LPVOID pValue)
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0);
+ if (nIndex >= m_nSize && !SetSize(nIndex+1))
+ return FALSE;
+
+ SetAt(nIndex, pValue);
+
+ return TRUE;
+}
+
+#pragma SEG(CScmArrayFValue_InsertAt)
+BOOL CScmArrayFValue::InsertAt(int nIndex, LPVOID pValue, int nCount /*=1*/)
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0); // will expand to meet need
+ Assert(nCount > 0); // zero or negative size not allowed
+
+ if (nIndex >= m_nSize)
+ {
+ // adding after the end of the array
+ if (!SetSize(nIndex + nCount)) // grow so nIndex is valid
+ return FALSE;
+ }
+ else
+ {
+ // inserting in the middle of the array
+ int nOldSize = m_nSize;
+ if (!SetSize(m_nSize + nCount)) // grow it to new size
+ return FALSE;
+
+ // shift old data up to fill gap
+ memmove(&m_pData[(nIndex+nCount) * m_cbValue],
+ &m_pData[nIndex * m_cbValue],
+ (nOldSize-nIndex) * m_cbValue);
+
+ // re-init slots we copied from
+ memset(&m_pData[nIndex * m_cbValue], 0, nCount * m_cbValue);
+ }
+
+ // insert new value in the gap
+ Assert(nIndex + nCount <= m_nSize);
+ while (nCount--)
+ memcpy(&m_pData[nIndex++ * m_cbValue], pValue, m_cbValue);
+
+ ASSERT_VALID(this);
+
+ return TRUE;
+}
+
+#pragma SEG(CScmArrayFValue_RemoveAt)
+void CScmArrayFValue::RemoveAt(int nIndex, int nCount /* = 1 */)
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0);
+ Assert(nIndex < m_nSize);
+ Assert(nCount >= 0);
+ Assert(nIndex + nCount <= m_nSize);
+
+ // just remove a range
+ int nMoveCount = m_nSize - (nIndex + nCount);
+ if (nMoveCount)
+ memcpy(&m_pData[nIndex * m_cbValue],
+ &m_pData[(nIndex + nCount) * m_cbValue],
+ nMoveCount * m_cbValue);
+ m_nSize -= nCount;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+#pragma SEG(CScmArrayFValue_IndexOf)
+// find element given part of one; offset is offset into value; returns
+// -1 if element not found; use IndexOf(NULL, cb, offset) to find zeros;
+// will be optimized for appropriate value size and param combinations
+int CScmArrayFValue::IndexOf(LPVOID pData, UINT cbData, UINT offset)
+{
+ Assert(offset <= m_cbValue);
+ Assert(cbData <= m_cbValue);
+ Assert((long)offset + cbData <= m_cbValue);
+ Assert(!IsBadReadPtr(pData, cbData));
+
+#ifdef LATER
+ if (cbData == sizeof(WORD) && m_cbValue == sizeof(WORD))
+ {
+ int iwRet;
+ _asm
+ {
+ push di
+ les di,pData ;* get value
+ mov ax,es:[di] ;* from *(WORD FAR*)pData
+ les di,this
+ mov cx,[di].m_nSize ;* get size (in WORDs) of array
+ les di,[di].m_pData ;* get ptr to WORD array
+ repne scasw ;* look for *(WORD FAR*)pData
+ jeq retcx ;* brif found
+ xor cx,cx ;* return -1
+ retcx:
+ dec cx
+ mov iwRet,cx
+ pop di
+ }
+
+ return iwRet;
+ }
+#endif
+
+ BYTE FAR* pElement;
+ int nIndex;
+ for (pElement = m_pData, nIndex = 0; nIndex < m_nSize; pElement += m_cbValue, nIndex++)
+ {
+ if (memcmp(pElement + offset, pData, cbData) == 0)
+ return nIndex;
+ }
+
+ return -1;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+#pragma SEG(CScmArrayFValue_AssertValid)
+void CScmArrayFValue::AssertValid() const
+{
+#ifdef _DEBUG
+ if (m_pData == NULL)
+ {
+ Assert(m_nSize == 0);
+ Assert(m_nMaxSize == 0);
+ }
+ else
+ {
+ Assert(m_nSize <= m_nMaxSize);
+ Assert((long)m_nMaxSize * m_cbValue <= SIZE_T_MAX); // no overflow
+ Assert(!IsBadReadPtr(m_pData, m_nMaxSize * m_cbValue));
+ }
+
+ // some collections live as global variables in the libraries, but
+ // have their existance in some context. Also, we can't check shared
+ // collections since we might be checking the etask collection
+ // which would cause an infinite recursion.
+#endif //_DEBUG
+}
diff --git a/private/ole32/dcomss/olescm/atbits.hxx b/private/ole32/dcomss/olescm/atbits.hxx
new file mode 100644
index 000000000..c6ea9526d
--- /dev/null
+++ b/private/ole32/dcomss/olescm/atbits.hxx
@@ -0,0 +1,361 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: atbits.hxx
+//
+// Contents: Support code for at-bits activation
+//
+// Classes: CAtStorage
+//
+// History: 24-Aug-94 MikeSe Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ATBITS_HXX__
+#define __ATBITS_HXX__
+
+#include <scm.h>
+#include <rawoscm.h>
+#include <dfsapi.h>
+#include <scmscm.h>
+
+// Undo def in ole2com.h which is not applicable here.
+#undef WNetGetUniversalName
+#define WNetGetUniversalName WNetGetUniversalNameW
+
+extern WCHAR SCMMachineName[];
+
+HRESULT GetMachineName( WCHAR * pwszPath,
+ WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH+1] );
+
+//+-------------------------------------------------------------------------
+//
+// Function: SetRpcAuthentication
+//
+// Synopsis: Set up RPC authentication and identity for call
+//
+// Arguments: [hRpc] - RPC handle to set up
+//
+// Returns: ERROR_SUCCESS - everything is ready for the call
+// Other - unexpected error occurred.
+//
+// History: 10-Feb-95 Ricksa Created
+//
+// Notes: WARNING: On exit the caller is impersonating the client of the
+// SCM and it is the callers responsibility to revert back
+// to the SCM's identity.
+//
+//--------------------------------------------------------------------------
+inline RPC_STATUS SetRpcAuthentication(handle_t hRpc)
+{
+ RPC_STATUS rs = RpcBindingSetAuthInfo(
+ hRpc, // Handle to set up
+ NULL, // Principal name
+ RPC_C_AUTHN_LEVEL_CONNECT, // Authentication level
+ RPC_C_AUTHN_WINNT, // Authentication service
+ NULL, // Authtication idenity
+ 0); // Authorization service
+
+#if DBG == 1
+
+ if (rs != ERROR_SUCCESS)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "SetRpcAuthentication RpcBindingSetAuthInfo failed %lx\n", rs));
+ }
+
+#endif // DBG == 1
+
+ if (rs = ERROR_SUCCESS)
+ {
+ // Impersonate the client on the current
+ rs = RpcImpersonateClient(NULL);
+
+#if DBG == 1
+
+ if (rs != ERROR_SUCCESS)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "SetRpcAuthentication RpcImpersonateClient failed %lx\n", rs));
+ }
+
+#endif // DBG == 1
+ }
+
+ return rs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CAtStorage
+//
+// Purpose: Wrapper over DFS and RPC operations for at-bits activation
+//
+// Interface:
+//
+// History: 24-Aug-94 MikeSe Created
+//
+// Notes: Currently, all the methods of this class are inline
+// since there is only one code path which uses them. This
+// may change in the future.
+//
+//--------------------------------------------------------------------------
+
+class CAtStorage
+{
+public:
+ // Constructor, not very interesting
+ CAtStorage ()
+ :_hRpc(NULL),
+ _hrDfs(S_FALSE)
+ {};
+
+ // Destructor
+ ~CAtStorage ()
+ {
+ if ( _hRpc != NULL )
+ RpcBindingFree ( &_hRpc );
+ if ( _hrDfs == S_OK )
+ DfsGetBindingsClose ( _dwContinuation );
+ };
+
+ // Initiate at-bits activation, if required.
+ HRESULT Begin ( LPWSTR pwszPath );
+
+ // Attempt activation to currently selected replica
+ HRESULT Activate (
+ const GUID *pguidThreadId,
+ const GUID& guidForClass,
+ DWORD dwOptions,
+ DWORD grfMode,
+ WCHAR *pwszPath,
+ InterfaceData *pIFDstg,
+ DWORD Interfaces,
+ IID * pIIDs,
+ InterfaceData **ppIFD,
+ HRESULT * pHResults,
+ DWORD *pdwDllThreadType,
+ WCHAR **ppwszDllPath,
+ DWORD *pdwTIDCallee );
+
+ // Retry to next replica if possible.
+ BOOL Continue ( void );
+
+ handle_t GetBindingHandle();
+
+private:
+
+ handle_t _hRpc; // Binding to next SCM to try
+ DWORD _dwContinuation;// DFS continuation cookie
+ HRESULT _hrDfs; // Return code from last DFS call
+ error_status_t _rpcstat; // communication status
+};
+
+//+-------------------------------------------------------------------------
+//
+// Member: CAtStorage::Begin
+//
+// Synopsis: Initiate remote binding if required
+//
+// Arguments: [pwszPath] -- target path
+//
+// Returns: S_OK -- the path resolves to a remote machine
+// S_FALSE -- the path resolves to this machine
+// other -- error resolving path
+//
+//--------------------------------------------------------------------------
+
+inline HRESULT CAtStorage::Begin (
+ LPWSTR pwszPath )
+{
+ HRESULT hr;
+ WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH+1];
+
+ if ( pwszPath == NULL )
+ return S_FALSE;
+
+ hr = GetMachineName( pwszPath, wszMachineName );
+
+ //
+ // We could get an error hr from WNetGetUniversalName, or S_FALSE
+ // if the path is local.
+ //
+ if ( hr != S_OK )
+ return hr;
+
+ //
+ // Make sure the server's name is not our machine name. Fail if it is.
+ //
+ if ( lstrcmpiW(wszMachineName,SCMMachineName) == 0 )
+ return S_FALSE;
+
+ //
+ // Do the remote activation.
+ //
+
+ // We need to impersonate SCM's caller in order to get the correct
+ // access to the DFS namespace
+ RpcImpersonateClient ( NULL );
+
+ // BUGBUG: the remote activation RPC operations are not idempotent
+ // and therefore obtain no benefit from being performed over
+ // datagram RPC. In the future this may be changed
+ _hrDfs = DfsGetBindingsFirst ( 0, // not DFS_ALLOW_DATAGRAM
+ pwszPath,
+ &_hRpc,
+ &_dwContinuation );
+
+ //
+ // The return code and contents of _hRpc determine our return value.
+ // If the return code indicates an error, then this is a remote path
+ // but for some reason we cannot resolve it, or the path is somehow
+ // bad. Either way, we just propagate the error.
+ // If the return code is S_OK, then this is a replicated DFS path.
+ // If the return code is S_FALSE, and _hRpc is non-NULL this is a
+ // non-replicated remote path.
+ //
+
+ if ( SUCCEEDED(_hrDfs) )
+ {
+ if ( _hRpc == NULL )
+ {
+ hr = S_FALSE;
+ }
+ else
+ {
+#if DBG == 1
+ CairoleDebugOut((DEB_TRACE,"AtStorage activation for %ws\n",pwszPath));
+#endif
+ hr = S_OK;
+ }
+ }
+ else
+ hr = _hrDfs;
+
+ RpcRevertToSelf ( );
+
+ return hr;
+}
+
+inline HRESULT CAtStorage::Activate (
+ const GUID *pguidThreadId,
+ const GUID& guidForClass,
+ DWORD dwOptions,
+ DWORD grfMode,
+ WCHAR *pwszPath,
+ InterfaceData *pIFDstg,
+ DWORD Interfaces,
+ IID * pIIDs,
+ InterfaceData **ppIFD,
+ HRESULT * pHResults,
+ DWORD *pdwDllThreadType,
+ WCHAR **ppwszDllPath,
+ DWORD *pdwTIDCallee )
+{
+ HRESULT hr;
+ RPC_STATUS rs;
+
+ // If we have already suffered an irrecoverable DFS error, just give up.
+ if ( FAILED(_hrDfs) )
+ return _hrDfs;
+
+ if ( (rs = SetRpcAuthentication(_hRpc)) == ERROR_SUCCESS )
+ {
+ // Make up the ORPC headers.
+ ORPCTHIS orpcthis;
+ LOCALTHIS localthis;
+ ORPCTHAT orpcthat;
+
+ _rpcstat = RPC_S_OK;
+
+ orpcthis.version.MajorVersion = COM_MAJOR_VERSION;
+ orpcthis.version.MinorVersion = COM_MINOR_VERSION;
+ orpcthis.flags = ORPCF_LOCAL;
+ orpcthis.reserved1 = 0;
+ orpcthis.cid = *pguidThreadId;
+ orpcthis.extensions = NULL;
+ localthis.dwClientThread = 0;
+ localthis.callcat = CALLCAT_SYNCHRONOUS;
+
+ _try
+ {
+ hr = _SCMActivationRequest( _hRpc,
+ &orpcthis,
+ &localthis,
+ &orpcthat,
+ &guidForClass,
+ pwszPath,
+ pIFDstg,
+ 0,
+ grfMode,
+ Interfaces,
+ pIIDs,
+ ppIFD,
+ pHResults );
+ }
+ _except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ _rpcstat = GetExceptionCode();
+ }
+
+ // Revert back to our real identity
+ RpcRevertToSelf();
+
+ // For remote calls we don't bother passing the caller's
+ // thread id, and we don't use the returned callee's
+ // thread id, since it's not valid on this machine.
+
+ *pdwTIDCallee = 0;
+
+ // BUGBUG: look at rpcstat to see if this is a retryable RPC error
+ if ( _rpcstat != RPC_S_OK )
+ {
+ CairoleDebugOut((DEB_ERROR,"Rpc error %d during remote activation\n", _rpcstat ));
+ hr = CO_E_OBJSRV_RPC_FAILURE; // BUGBUG?
+ }
+ }
+ else
+ {
+ hr = HRESULT_FROM_WIN32(rs);
+ }
+
+ return hr;
+}
+
+inline BOOL CAtStorage::Continue ()
+{
+ BOOL fReturn;
+
+ // See if we can continue to another replica
+ if ( _hrDfs == S_OK )
+ {
+ if ( _rpcstat == RPC_S_OK )
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CAtStorage::Continue not continuing due to absence of communication error\n"));
+ fReturn = FALSE;
+ }
+ else
+ {
+ _hrDfs = DfsGetBindingsNext ( _dwContinuation,
+ // BUGBUG: _rpcstat to a reason code
+ REASON_UNAVAILABLE,
+ &_hRpc );
+ fReturn = SUCCEEDED(_hrDfs);
+ }
+
+ }
+ else
+ fReturn = FALSE;
+
+ return fReturn;
+}
+
+inline handle_t CAtStorage::GetBindingHandle()
+{
+ return _hRpc;
+}
+
+#endif // of ifndef __ATBITS_HXX__
diff --git a/private/ole32/dcomss/olescm/clckpath.cxx b/private/ole32/dcomss/olescm/clckpath.cxx
new file mode 100644
index 000000000..05891dfac
--- /dev/null
+++ b/private/ole32/dcomss/olescm/clckpath.cxx
@@ -0,0 +1,99 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: clckpath.cxx
+//
+// Contents: Methods for serializing binds on paths.
+//
+// History: 21-Dec-93 Ricksa Created
+// 11-Oct-94 BillMo Simplified
+//
+//--------------------------------------------------------------------------
+#include <headers.cxx>
+#pragma hdrstop
+
+#include "scm.hxx"
+#include "clckpath.hxx"
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLockPath::CLockPath
+//
+// Synopsis: Put path in lock table
+//
+// Arguments: [pwszPath] - path to lock
+// [hr] - result of construction (set only on failure)
+//
+// History: 21-Dec-93 Ricksa Created
+// 26-Sep-94 BillMo Simplified by using named mutexes.
+//
+//--------------------------------------------------------------------------
+CLockPath::CLockPath(WCHAR *pwszPath, HRESULT& hr)
+{
+ _h = NULL;
+
+ if (pwszPath != NULL)
+ {
+
+#define LOCKPREFIX TEXT("OLESCMLOCKPATH")
+
+ TCHAR tszPathUpper[MAX_PATH+1];
+ TCHAR *ptsz;
+ ULONG cSlashes = 0;
+
+ //
+ // adjust the input pointer to skip past drive letter or
+ // UNC path
+ //
+
+ if (pwszPath[0] == L'\\' && pwszPath[1] == L'\\')
+ {
+ while (*pwszPath && cSlashes < 3)
+ {
+ if (*pwszPath == L'\\')
+ cSlashes++;
+ pwszPath++;
+ }
+ }
+ else
+ if (pwszPath[0] != L'\0' &&
+ pwszPath[1] == L':' &&
+ pwszPath[2] == L'\\')
+ {
+ pwszPath += 3;
+ cSlashes = 3;
+ }
+
+ if (cSlashes == 3 && *pwszPath != L'\0')
+ {
+ _tcscpy(tszPathUpper, LOCKPREFIX);
+
+ //
+ // Copy the path onto the end of the prefix and
+ // as doing so convert \ to -, and check for buffer size
+ //
+ for (ptsz = tszPathUpper+sizeof(LOCKPREFIX)/sizeof(WCHAR)-1;
+ ptsz <= &tszPathUpper[MAX_PATH];
+ ptsz++, pwszPath++)
+ {
+ *ptsz = (TCHAR)*pwszPath;
+ if (*ptsz == L'\\')
+ *ptsz = L'-';
+ else
+ if (*ptsz == L'\0')
+ break;
+ }
+ tszPathUpper[MAX_PATH] = L'\0';
+ _tcsupr(tszPathUpper);
+ _h = CreateMutex(NULL, FALSE, tszPathUpper);
+ if (_h == NULL)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ return;
+ }
+ WaitForSingleObject(_h, INFINITE);
+ }
+ }
+}
diff --git a/private/ole32/dcomss/olescm/clckpath.hxx b/private/ole32/dcomss/olescm/clckpath.hxx
new file mode 100644
index 000000000..cd4c7087c
--- /dev/null
+++ b/private/ole32/dcomss/olescm/clckpath.hxx
@@ -0,0 +1,65 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: clckpath.hxx
+//
+// Contents: Classes and methods used for single threading binds on
+// a single path.
+//
+// Classes: CLockPath
+//
+// History: 21-Dec-93 Ricksa Created
+// 26-Sep-94 BillMo Simplified to use named mutexes
+//
+//--------------------------------------------------------------------------
+#ifndef __LCKPATH_HXX__
+#define __LCKPATH_HXX__
+
+#include "scm.hxx"
+#include <sem.hxx>
+#include <memapi.hxx>
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CLockPath
+//
+// Purpose: Handle making sure path gets locked and unlocked
+//
+// History: 21-Dec-93 Ricksa Created
+// 26-Sep-94 BillMo Simplified to use named mutexes
+//
+//--------------------------------------------------------------------------
+class CLockPath
+{
+public:
+ CLockPath(WCHAR *pwszPath, HRESULT& hr);
+ ~CLockPath(void);
+
+private:
+ HANDLE _h;
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLockPath::~CLockPath
+//
+// Synopsis: Free path lock
+//
+// History: 21-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CLockPath::~CLockPath(void)
+{
+ if (_h != NULL)
+ {
+ ReleaseMutex(_h);
+ CloseHandle(_h);
+ }
+}
+
+#endif // __LCKPATH_HXX__
diff --git a/private/ole32/dcomss/olescm/cls.cxx b/private/ole32/dcomss/olescm/cls.cxx
new file mode 100644
index 000000000..70e54bfb7
--- /dev/null
+++ b/private/ole32/dcomss/olescm/cls.cxx
@@ -0,0 +1,3942 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: cls.cxx
+//
+// Contents: Methods implementing classes defined in cls.hxx
+//
+// Functions: RetryRpc
+// CClassData::CClassData
+// CClassData::GetServer
+// CClassData::GetInProcServerInfo
+// CClassData::GetSurrogateCmdLine
+// CClassCacheList::CClassCacheList
+// CClassCacheList::GetClassData
+// CClassData::Defined
+// CClassCacheList::Add
+// CClassCacheList::SetEndPoint
+// CClassCacheList::StopServer
+//
+// History: 21-Apr-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+// 24-Mar-94 JohannP Delaying rpc initialization on Chicago
+// 10-Jan-96 BruceMa Added support for per-user registry
+//
+//--------------------------------------------------------------------------
+
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#ifdef DCOM
+#include "or.hxx"
+#endif
+
+#include "scm.hxx"
+#include <clsctx.hxx>
+#include <scmrotif.hxx>
+#include <objsrv.h>
+#include "port.hxx"
+#include <caller.hxx>
+#include <rpcdcep.h>
+#include "cls.hxx"
+
+#include "init.hxx"
+
+#ifdef DCOM
+#include <secdes.hxx>
+#include "remact.hxx"
+#endif
+
+#ifndef _CHICAGO_
+#include <dfsfsctl.h>
+#endif
+
+extern WCHAR SCMMachineName[];
+extern HKEY g_hkAppID;
+
+#ifndef _CHICAGO_
+extern SC_HANDLE hServiceController;
+extern HANDLE ghDfs;
+#endif
+
+// Number of times we will try to contact object server in the case of
+// RPC failures.
+#define MAX_OBJSRV_RETRIES 2
+
+// Maximum number of times we will let the server tell us we are busy
+#define MAX_BUSY_RETRIES 3
+
+static WCHAR wszEnableDCOM[] = L"EnableDCOM";
+static WCHAR wszPersonalClasses[] = L"PersonalClasses";
+static WCHAR wszActivationSecurity[] = L"ActivationSecurity";
+static WCHAR wszLaunchPermission[] = L"LaunchPermission";
+static WCHAR wszDefaultLaunchPermission[] = L"DefaultLaunchPermission";
+static WCHAR wszOleKey[] = L"SOFTWARE\\Microsoft\\OLE";
+static WCHAR wszSurrogateName[] = L"dllhost.exe";
+
+WCHAR wszDllSurrogatePathValue[] = L"DllSurrogate";
+
+// string to pass to CSafeLocalServer constructor
+// for creating a lock for surrogate activations
+#define wszSurrogateServerAlias L"_SURROGATE_EXE_"
+
+WCHAR wszSOFTWAREClassesCLSID[] = L"SOFTWARE\\Classes\\CLSID";
+WCHAR wszSOFTWAREClassesAppID[] = L"SOFTWARE\\Classes\\AppID";
+
+#ifndef _CHICAGO_
+extern HANDLE g_hForceWakeUpEvent;
+#endif
+
+#define MAX_CLASS_ENTRIES 256
+
+
+#ifdef DCOM
+BOOL CkIfRemoteCallAllowed(void);
+HRESULT GetUserSidHelper(PSID *ppUserSid);
+
+HRESULT GetRegistrySecDesc( HKEY hKey, WCHAR *pValue,
+ SECURITY_DESCRIPTOR **pSD );
+#endif
+
+
+CScmLock gClassCacheLock(g_hrInit);
+
+// Thread model match table. The table's first index is the threading
+// model of the process and can be either APT_THREADED or
+// FREE_THREADED. The second index is any one of the types of threading
+// model's for DLLs.
+BOOL afThreadModelMatch[2][4] =
+ {{TRUE, FALSE, TRUE, TRUE},
+ {FALSE, TRUE, FALSE, TRUE}};
+#if DBG == 1
+char *apszModelStrings[4] = {"Apartment","Free","Single","Both"};
+#define ModelStringMask 0x3
+#endif
+
+#define TRY_LOCAL_ACTIVATION 0
+#define DONT_TRY_LOCAL_ACTIVATION 1
+
+#ifdef _CHICAGO_
+BOOL StartLocalService();
+#endif // _CHICAGO_
+
+#ifdef DCOM
+//+---------------------------------------------------------------------------
+//
+// Activation
+//
+// Main entry point for both local and remote activations.
+//
+// Notes concerning CO_E_SERVER_STOPPING :
+//
+// It is possible for the SCM to Server calls to fail with
+// CO_E_SERVER_STOPPING. An example scenario:
+// Server
+// - does a CoRegisterClassObject for SINGLE USE resulting
+// in an entry in the SCM's Class cache and an entry in
+// OLE's DLL cache
+// - (acting as its own client) server proceeds to consume
+// it via CoCreateInstance. In this case the entry in the
+// DLL cache is found and consumed leaving the SCM's Class
+// cache in an inconsistent state (yes...a bug, but reality
+// intrudes). Also, because SINGLE USE was indicated entry
+// in DLL cache is marked such that it will not be handed
+// out again.
+// - if another CoCreateInstance comes along (server itself
+// or another client) the request will go to the SCM which
+// in turn will issue RemCoGetActiveClassObject to the
+// server. Server will return CO_E_SERVER_STOPPING after
+// failing to find it in the DLL cache.
+//
+// To get around this problem we continue and attempt to activate
+// a new instance of the server.
+//
+//----------------------------------------------------------------------------
+HRESULT Activation( PACTIVATION_PARAMS pActParams )
+{
+ HRESULT hr;
+ RPC_STATUS Status;
+ DWORD n;
+ BOOL ServerStarted = FALSE;
+ BOOL ActivatedRemote = FALSE;
+ BOOL fProcessReference = FALSE;
+ CClassData *pClassData;
+
+ pActParams->UnsecureActivation = FALSE;
+
+ pActParams->ORPCthis->flags = ORPCF_LOCAL;
+ pActParams->Localthis->callcat = CALLCAT_SYNCHRONOUS;
+ pActParams->ORPCthat->flags = 0;
+ pActParams->ORPCthat->extensions = NULL;
+
+ pActParams->ProtseqId = 0;
+ *pActParams->pOxidServer = 0;
+
+ for ( n = 0; n < pActParams->Interfaces; n++ )
+ pActParams->pResults[n] = E_FAIL;
+
+ if ( ! pActParams->RemoteActivation )
+ {
+ pActParams->pOxidInfo->psa = 0;
+ *pActParams->ppServerORBindings = 0;
+ }
+
+ if ( ! pActParams->RemoteActivation && ! pActParams->DynamicSecurity )
+ {
+ //
+ // A local activation passes the "magic" signature from CRpcResolver.
+ // Because ORPC calls cannot have context handles, the signature
+ // is just a pointer the process object.
+ //
+
+ pActParams->pProcess = ReferenceProcess(pActParams->ProcessSignature,
+ TRUE);
+
+ if (0 == pActParams->pProcess)
+ {
+#if DBG
+ DbgPrint("SCM: Unable to unmarshall process signature: %p, %p\n",
+ pActParams, pActParams->ProcessSignature);
+#endif
+
+ return(E_ACCESSDENIED);
+ }
+
+ pActParams->pToken = pActParams->pProcess->GetToken();
+ fProcessReference = TRUE;
+ }
+ else
+ {
+ //
+ // Remote activations don't have the token signature.
+ // We create tokens that are short lived right now. Do we want
+ // to keep them around forever?
+ //
+ Status = LookupOrCreateToken( pActParams->hRpc,
+ FALSE,
+ &pActParams->pToken );
+
+ //
+ // ERROR_ACCESS_DENIED is returned if RpcImpersonateClient fails.
+ // We will take this to mean that the remote activation is coming
+ // in unsecure. In this case we have no Token object and must do
+ // permission checks manually. We set the winsta/desktop to an
+ // empty string to distinguish this case during some ROT lookups.
+ // Yet another wonderful piece of logic in this grotesque code.
+ //
+ // Unsecure remote clients can only connect to services or RunAs
+ // servers.
+ //
+ if ( Status == ERROR_ACCESS_DENIED )
+ {
+ pActParams->pToken = 0;
+ pActParams->pwszWinstaDesktop = L"";
+ pActParams->UnsecureActivation = TRUE;
+ Status = RPC_S_OK;
+ }
+
+ if ( Status != RPC_S_OK )
+ return HRESULT_FROM_WIN32(Status);
+ }
+
+ Win4Assert( pActParams->pToken || pActParams->UnsecureActivation );
+
+ // If per-user registry is turned on we'll need our sid.
+ // If we already have seen this user then we've cached a basic
+ // sid for him. Otherwise, the initial sid we get becomes his
+ // standard sid. By using a common sid for a user we can compare
+ // with == rather than RtlEqualSid
+ //
+ // NT 5.0
+ // if (gpClassCache->GetPersonalClasses())
+ // {
+ // PSID pUserSid = gpClassCache->GetHkeyPsid(pActParams->pToken->GetSid());
+ // }
+
+ hr = gpClassCache->GetClassData(
+ *pActParams->Clsid,
+ &pClassData,
+ FALSE,
+ FALSE );
+
+ if ( pActParams->pwszServer )
+ {
+ WCHAR * pwszServerName;
+
+ pwszServerName = pActParams->pwszServer;
+ if ( pwszServerName[0] == L'\\' && pwszServerName[1] == L'\\' )
+ pwszServerName += 2;
+
+ //
+ // An explicit server machine name param equal to the machine we're
+ // on means the client doesn't want the activation to be remoted.
+ // An explicit server name other than our name implies CLSTXT_REMOTE_SERVER.
+ //
+ if ( lstrcmpiW(pwszServerName, SCMMachineName) == 0 )
+ pActParams->ClsContext &= ~CLSCTX_REMOTE_SERVER;
+ else
+ pActParams->ClsContext |= CLSCTX_REMOTE_SERVER;
+ }
+ else
+ {
+ //
+ // CLSCTX_REMOTE_SERVER is implied if either ActivateAtStorage or
+ // RemoteServerName is present on the CLSID.
+ //
+ if ( ! pActParams->RemoteActivation &&
+ pClassData &&
+ (pClassData->HasActivateAtStorage() || pClassData->HasRemoteServerName()) )
+ {
+ pActParams->ClsContext |= CLSCTX_REMOTE_SERVER;
+ }
+ }
+
+ if ( FAILED(hr) )
+ {
+ //
+ // If we don't find an entry for the CLSID then we must still try
+ // a remote activation if a server name was given.
+ //
+ // If there is no server name, we try an ActivateAtStorage. If the
+ // path is local this will fail, otherwise we'll try to activate a
+ // server on the machine where the path leads us.
+ //
+ // CLSCTX_REMOTE_SERVER is implied if a remote server name is given,
+ // but is not implied for a CLSID which is not present in the client's
+ // registry.
+ //
+ if ( (hr == REGDB_E_CLASSNOTREG) && ! pActParams->RemoteActivation )
+ {
+ //
+ // Create a skeleton class data object so we can
+ // call its methods.
+ //
+ CClassData ClassData( *pActParams->Clsid, hr );
+ BOOL Status;
+
+ if ( pActParams->pwszServer )
+ {
+ Status = ClassData.ActivateRemote( &hr, pActParams );
+
+ if ( Status == TRY_LOCAL_ACTIVATION )
+ hr = REGDB_E_CLASSNOTREG;
+ }
+ else if ( pActParams->ClsContext & CLSCTX_REMOTE_SERVER )
+ {
+ ClassData.SetActivateAtStorage();
+
+ Status = ClassData.ActivateAtStorage( &hr, pActParams );
+
+ if ( Status == TRY_LOCAL_ACTIVATION )
+ hr = REGDB_E_CLASSNOTREG;
+ }
+
+ if ( hr == S_OK )
+ hr = ResolveORInfo( pActParams, TRUE );
+ }
+
+ goto ActivationExit;
+ }
+
+ for (;;)
+ {
+ error_status_t rpcstat;
+ int BusyRetries;
+ CPortableRpcHandle rh;
+ handle_t hRpcAnonymous;
+
+ hRpcAnonymous = 0;
+
+ BOOL fSurrogate = FALSE;
+
+ //
+ // Start local server or service, or forward activation call
+ // to remote machine.
+ //
+ hr = pClassData->GetServer( pActParams, rh, ServerStarted, ActivatedRemote, fSurrogate);
+
+ //
+ // We're done and do not make a call to the server if the server launch
+ // failed, we found the object in the ROT, or we tried to make a remote
+ // activation.
+ //
+ if ( FAILED(hr) || pActParams->FoundInROT || ActivatedRemote )
+ break;
+
+ BusyRetries = 0;
+
+ //
+ // Impersonate client while making the call to the server so that the
+ // server can not impersonate local system and can identify the client
+ // if needed. The SCM-Server binding handle is created with
+ // identification level security.
+ // During unsecure activations we use an rpc handle created at
+ // impersonation level of none.
+ //
+ if ( ! pActParams->UnsecureActivation )
+ {
+ RpcImpersonateClient((RPC_BINDING_HANDLE)0);
+ }
+ else
+ {
+ pClassData->GetAnonymousHandle( rh, &hRpcAnonymous );
+ if ( ! hRpcAnonymous )
+ {
+ pClassData->DecHandleCount(rh);
+ hr = E_OUTOFMEMORY;
+ break;
+ }
+ }
+
+ //
+ // Keeping server busy retry logic for now, but do we really care?
+ //
+ do
+ {
+ switch (pActParams->MsgType)
+ {
+ case GETCLASSOBJECTEX:
+ hr = ObjectServerGetClassObject(
+ hRpcAnonymous ? hRpcAnonymous : rh.GetHandle(),
+ pActParams->ORPCthis,
+ pActParams->Localthis,
+ pActParams->ORPCthat,
+ pActParams->Clsid,
+ pActParams->pIIDs,
+ fSurrogate,
+ (MInterfacePointer **)pActParams->ppIFD,
+ &rpcstat );
+ break;
+ case CREATEINSTANCEEX:
+ hr = ObjectServerCreateInstance(
+ hRpcAnonymous ? hRpcAnonymous : rh.GetHandle(),
+ pActParams->ORPCthis,
+ pActParams->Localthis,
+ pActParams->ORPCthat,
+ pActParams->Clsid,
+ pActParams->Interfaces,
+ pActParams->pIIDs,
+ (MInterfacePointer **)pActParams->ppIFD,
+ pActParams->pResults,
+ &rpcstat );
+ break;
+ case GETPERSISTENTEX:
+ hr = ObjectServerGetInstance(
+ hRpcAnonymous ? hRpcAnonymous : rh.GetHandle(),
+ pActParams->ORPCthis,
+ pActParams->Localthis,
+ pActParams->ORPCthat,
+ pActParams->Clsid,
+ pActParams->Mode,
+ pActParams->pwszPath,
+ (MInterfacePointer *)pActParams->pIFDStorage,
+ pActParams->Interfaces,
+ pActParams->pIIDs,
+ (MInterfacePointer *)pActParams->pIFDROT,
+ (MInterfacePointer **)pActParams->ppIFD,
+ pActParams->pResults,
+ &rpcstat );
+ break;
+ }
+ }
+ while ( (rpcstat == RPC_S_SERVER_TOO_BUSY) &&
+ (BusyRetries++ < MAX_BUSY_RETRIES) );
+
+ if ( ! pActParams->UnsecureActivation )
+ RpcRevertToSelf();
+
+ //
+ // This frees the RPC binding handle for a single use
+ // registered class. Its already been removed from the
+ // class registration list.
+ //
+ rh.FreeSingleUseBinding();
+
+ //
+ // This releases our reference to this registered handle so that it
+ // can be freed if and when it is revoked or invalidated.
+ //
+ pClassData->DecHandleCount(rh);
+
+ //
+ // We get a non-zero rpcstat if there was a communication problem
+ // with the server. We get CO_E_SERVER_STOPPING if a server
+ // consumes its own single use registration (see comment in function
+ // header), or was in the process of revoking its registration when
+ // we called.
+ //
+ // We'll try the activation again if we get CO_E_SERVER_STOPPING and
+ // used a previously registered handle. If we launched a new server
+ // then something is hosed and we return.
+ //
+ if ( (rpcstat != RPC_S_OK) || (hr == CO_E_SERVER_STOPPING) )
+ {
+ //
+ // We didn't like that handle, so we blow it away.
+ // There is a bug here because it's possible the handle will not
+ // get freed. Its not a huge deal because this will be very rare.
+ // Fix it in NT 5.0.
+ //
+ pClassData->InvalidateHandle(rh);
+
+ if ( ServerStarted && (rpcstat != RPC_S_OK) )
+ {
+ // TODO: log message about rpc error talking to server
+ hr = HRESULT_FROM_WIN32(rpcstat);
+ break;
+ }
+
+ //
+ // Re-read the class information if there are no more registered
+ // binding handles left.
+ //
+ if ( ! pClassData->InUse() )
+ {
+ gClassCacheLock.WriteLock();
+ pClassData->Release();
+ gClassCacheLock.WriteUnlock();
+ pClassData = 0;
+
+ hr = gpClassCache->GetClassData(
+ *pActParams->Clsid,
+ &pClassData,
+ FALSE,
+ FALSE );
+
+ if ( FAILED(hr) )
+ goto ActivationExit;
+ }
+
+ continue;
+ }
+
+ // Success - return the result to the client.
+ break;
+ }
+
+ if ( pClassData != NULL )
+ {
+ //
+ // We need to take the write lock since the destruction
+ // of CClassData will affect the ref counted objects
+ // (such as CSafeLocalServer.)
+ //
+ gClassCacheLock.WriteLock();
+ pClassData->Release();
+ gClassCacheLock.WriteUnlock();
+ }
+
+ if ( SUCCEEDED(hr) )
+ hr = ResolveORInfo( pActParams, ActivatedRemote );
+
+ActivationExit:
+
+ if ( fProcessReference )
+ {
+ ReleaseProcess( pActParams->pProcess );
+ }
+ else
+ {
+ if ( pActParams->pToken != 0 )
+ pActParams->pToken->Release();
+ }
+
+ return hr;
+}
+
+HRESULT ResolveORInfo(
+ PACTIVATION_PARAMS pActParams,
+ BOOL ActivatedRemote )
+{
+ MInterfacePointer * pIFD;
+ OBJREF * pObjRef;
+ STDOBJREF * pStdObjRef;
+ DUALSTRINGARRAY * pORBindings;
+ DWORD DataSize;
+ RPC_STATUS sc;
+ DWORD n;
+
+ //
+ // This routine probes the interface data returned from the server's
+ // OLE during a successfull activation, but we're still going to
+ // protect ourself from bogus data.
+ //
+
+ pIFD = 0;
+ for ( n = 0; n < pActParams->Interfaces; n++ )
+ {
+ pIFD = pActParams->ppIFD[n];
+ if ( pIFD )
+ break;
+ }
+
+ Win4Assert( pIFD );
+
+ if ( pIFD->ulCntData < 2*sizeof(ULONG) )
+ {
+ Win4Assert( !"Bad interface data returned from server" );
+ return S_OK;
+ }
+
+ pObjRef = (OBJREF *)pIFD->abData;
+
+ if ( (pObjRef->signature != OBJREF_SIGNATURE) ||
+ (pObjRef->flags & ~(OBJREF_STANDARD | OBJREF_HANDLER | OBJREF_CUSTOM)) ||
+ (pObjRef->flags == 0) )
+ {
+ Win4Assert( !"Bad interface data returned from server" );
+ return S_OK;
+ }
+
+ // No OR info sent back for custom marshalled interfaces.
+ if ( pObjRef->flags == OBJREF_CUSTOM )
+ return S_OK;
+
+ DataSize = 2*sizeof(ULONG) + sizeof(GUID);
+ pStdObjRef = (STDOBJREF *)(pIFD->abData + DataSize);
+
+ DataSize += sizeof(STDOBJREF);
+ if ( pObjRef->flags == OBJREF_HANDLER )
+ DataSize += sizeof(CLSID);
+
+ pORBindings = (DUALSTRINGARRAY *)(pIFD->abData + DataSize);
+ DataSize += 2 * sizeof(USHORT);
+
+ if ( pIFD->ulCntData < DataSize )
+ {
+ Win4Assert( !"Bad interface data returned from server" );
+ return S_OK;
+ }
+
+ // If we activated the server on this machine, we need the OXID of the server.
+ if ( ! ActivatedRemote )
+ *pActParams->pOxidServer = *((OXID UNALIGNED *)&pStdObjRef->oxid);
+
+ //
+ // If we're servicing a remote activation, all we need is the server's OXID.
+ // The client will call ResolveClientOXID from its ResolveORInfo.
+ //
+ if ( pActParams->RemoteActivation )
+ return S_OK;
+
+ DataSize += pORBindings->wNumEntries * sizeof(USHORT);
+
+ if ( (pIFD->ulCntData < DataSize) ||
+ (pORBindings->wNumEntries != 0 &&
+ (pORBindings->wSecurityOffset >= pORBindings->wNumEntries)) )
+ {
+ Win4Assert( !"Bad interface data returned from server" );
+ return S_OK;
+ }
+
+ //
+ // If empty OR bindings were supplied then the server and client are
+ // both local to this machine, so use the local OR bindings.
+ //
+ if (pORBindings->wNumEntries == 0)
+ {
+ pORBindings = pdsaMyBindings;
+ }
+
+ //
+ // This was a local activation so use our string bindings for the OR
+ // binding string.
+ //
+ *pActParams->ppServerORBindings = (DUALSTRINGARRAY *)
+ MIDL_user_allocate( sizeof(DUALSTRINGARRAY) +
+ pORBindings->wNumEntries*sizeof(USHORT) );
+
+ if ( ! *pActParams->ppServerORBindings )
+ return E_OUTOFMEMORY;
+
+ dsaCopy( *pActParams->ppServerORBindings, pORBindings );
+
+ //
+ // If we did a remote activation then we already have the server's OXID and
+ // OR string bindings from the RemoteActivation call and pieces of the OXID
+ // info have been filled in.
+ //
+
+ // Could we optimize this at all for the local case?
+ sc = ResolveClientOXID( pActParams->hRpc,
+ (PVOID)pActParams->pProcess,
+ pActParams->pOxidServer,
+ *pActParams->ppServerORBindings,
+ pActParams->Apartment,
+ pActParams->ProtseqId,
+ pActParams->pOxidInfo,
+ pActParams->pLocalMidOfRemote );
+
+ return HRESULT_FROM_WIN32(sc);
+}
+#endif // DCOM
+
+#ifdef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Method: ScmStackSwitch
+//
+// Synopsis: calls CClassCacheList::SSProcessScmMessage
+//
+// Arguments: [pClsCacheList] --
+// [pbd] --
+// [pgcd] --
+//
+// Returns:
+//
+// History: 4-19-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT ScmStackSwitch(CClassCacheList *pClsCacheList, CBaseData *pbd, CGetCreateData *pgcd)
+{
+ HRESULT hres;
+ StackDebugOut((DEB_STCKSWTCH, "ScmStackSwitch 32->16 : pClsCacheList(%x), pbd(%x), pgcd(%x)\n", pClsCacheList, pbd, pgcd));
+ hres = pClsCacheList->SSProcessScmMessage(pbd, pgcd);
+ StackDebugOut((DEB_STCKSWTCH, "ScmStackSwitch 32<-16 back; hres:%x\n", hres));
+ return hres;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClassCacheList::ProcessScmMessage
+//
+// Synopsis: Switched to the 16 bit stack and calls SSProcessScmMessage
+// via ScmStackSwitch
+//
+// Arguments: [pbd] --
+// [pgcd] --
+//
+// Returns:
+//
+// History: 4-19-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CClassCacheList::ProcessScmMessage(CBaseData *pbd, CGetCreateData *pgcd)
+{
+ HRESULT hres;
+ CairoleDebugOut((DEB_STCKSWTCH, "In ProcessScmMessage this(%x), pbd(%x), pgcd(%x)\n", this, pbd, pgcd));
+ if (SSONBIGSTACK())
+ {
+ hres = SSCall(12, SSF_SmallStack, (LPVOID)ScmStackSwitch, (DWORD)this, (DWORD) pbd, (DWORD) pgcd);
+ }
+ else
+ hres = SSProcessScmMessage(pbd, pgcd);
+
+ CairoleDebugOut((DEB_STCKSWTCH, "Out ProcessScmMessage this(%x), pbd(%x), pgcd(%x) =>hres(%x)\n",
+ this, pbd, pgcd, hres));
+ return hres;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: ProcessScmMessage
+//
+// Synopsis: Generic routine to process activation related messages
+// to SCM.
+//
+// Arguments: [pbd] -- base message data for all message types
+// [pcgd] -- extended data for (Get/Create)PersistentObj
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+HRESULT CClassCacheList::SSProcessScmMessage(CBaseData *pbd, CGetCreateData *pgcd)
+{
+ // Result from trying to get server information including
+ // starting the server if necessary. This used for the
+ // return code when the call succeeds.
+ HRESULT hr;
+ int cRetries = 0;
+
+ // Usually result of contacting object server. This result
+ // is always returned when the call has failed.
+ HRESULT hr2 = S_OK;
+
+ // Whether we actually did start a server. This controls
+ // whether we actually retry. The basic idea here is that
+ // if we have started a server and it crashes, then we don't
+ // need to retry. However, if we haven't started the server
+ // and we find the RPC handle invalid, then we start the server
+ // again.
+ BOOL ServerStarted = FALSE;
+
+ BOOL ActivatedRemote;
+
+ CClassData *pccd;
+ // Retain original value of *pbd->_pdwDllType here. Calling GetServer will
+ // result in the value getting updated. Since we may end up calling
+ // GetServer multiple times, we initialize *pbd->_pdwDllType before each
+ // call with the saved value.
+ DWORD dwsavedDllType = *pbd->_pdwDllType;
+
+#ifdef DCOM
+ // Check whether the registry has changed
+ if (WaitForSingleObject(_hRegEvent, 0) == WAIT_OBJECT_0)
+ {
+ ReadRemoteActivationKeys();
+
+ // Re-arm the event
+ int err;
+
+ if ((err = RegNotifyChangeKeyValue(HKEY_LOCAL_MACHINE,
+ TRUE,
+ REG_NOTIFY_CHANGE_NAME |
+ REG_NOTIFY_CHANGE_ATTRIBUTES |
+ REG_NOTIFY_CHANGE_LAST_SET |
+ REG_NOTIFY_CHANGE_SECURITY,
+ _hRegEvent,
+ TRUE))
+ != ERROR_SUCCESS)
+ {
+ return HRESULT_FROM_WIN32(err);
+ }
+ }
+#endif
+
+ hr = GetClassData ( pbd->_guidForClass,
+ &pccd,
+ FALSE /* don't leave locked */ );
+
+#ifdef DCOM
+ if ( pbd->_pwszServer )
+ {
+ WCHAR * pwszServerName;
+
+ pwszServerName = pbd->_pwszServer;
+ if ( pwszServerName[0] == L'\\' && pwszServerName[1] == L'\\' )
+ pwszServerName += 2;
+
+ //
+ // An explicit server machine name param equal to the machine we're
+ // on means the client doesn't want the activation to be remoted.
+ // An explicit server name other than our name implies CLSTXT_REMOTE_SERVER.
+ //
+ if ( lstrcmpiW(pwszServerName, SCMMachineName) == 0 )
+ pbd->_dwContext &= ~CLSCTX_REMOTE_SERVER;
+ else
+ pbd->_dwContext |= CLSCTX_REMOTE_SERVER;
+ }
+ else
+ {
+ //
+ // CLSCTX_REMOTE_SERVER is implied if either ActivateAtStorage or
+ // RemoteServerName is present on the CLSID.
+ //
+ if ( ! pbd->_fRemoteActivation &&
+ pccd &&
+ (pccd->HasActivateAtStorage() || pccd->HasRemoteServerName()) )
+ {
+ pbd->_dwContext |= CLSCTX_REMOTE_SERVER;
+ }
+ }
+
+ if ( FAILED(hr) )
+ {
+ //
+ // If we don't find an entry for the CLSID then we must still try
+ // a remote activation if a server name was given.
+ //
+ // If there is no server name, we try an ActivateAtStorage. If the
+ // path is local this will fail, otherwise we'll try to activate a
+ // server on the machine where the path leads us.
+ //
+ // CLSCTX_REMOTE_SERVER is implied if a remote server name is given,
+ // but is not implied for a CLSID which is not present in the client's
+ // registry.
+ //
+ if ( (hr == REGDB_E_CLASSNOTREG) && ! pbd->_fRemoteActivation )
+ {
+ //
+ // Create a skeleton class data object so we can
+ // call its methods.
+ //
+ CClassData ClassData( pbd->_guidForClass, hr );
+ BOOL Status;
+
+ if ( pbd->_pwszServer )
+ {
+ Status = ClassData.ActivateRemote( &hr, pbd, pgcd );
+
+ if ( Status == TRY_LOCAL_ACTIVATION )
+ hr = REGDB_E_CLASSNOTREG;
+
+ return hr;
+ }
+
+ if ( pbd->_dwContext & CLSCTX_REMOTE_SERVER )
+ {
+ ClassData.SetActivateAtStorage();
+
+ Status = ClassData.ActivateAtStorage( &hr, pbd, pgcd );
+
+ if ( Status == TRY_LOCAL_ACTIVATION )
+ hr = REGDB_E_CLASSNOTREG;
+ }
+ }
+ return hr;
+ }
+#else
+ if ( FAILED(hr) )
+ {
+ return hr;
+ }
+#endif // DCOM
+
+#ifdef DCOM
+ // Make up the ORPC headers.
+ ORPCTHIS orpcthis;
+ LOCALTHIS localthis;
+ ORPCTHAT orpcthat;
+
+ orpcthis.version.MajorVersion = COM_MAJOR_VERSION;
+ orpcthis.version.MinorVersion = COM_MINOR_VERSION;
+ orpcthis.flags = ORPCF_LOCAL;
+ orpcthis.reserved1 = 0;
+ orpcthis.cid = *pbd->_pguidThreadId;
+ orpcthis.extensions = NULL;
+ if (pgcd != NULL)
+ localthis.dwClientThread = pgcd->_dwTIDCaller;
+ else
+ localthis.dwClientThread = GetCurrentThreadId();
+
+ if ( pbd->_ORPCthis == 0 )
+ {
+ //
+ // Setup the ORPC stuff for down level activation calls.
+ //
+ // Initializing on the stack is ok since only the SCM RPC entry
+ // points call us and they don't ever use pbd.
+ //
+ pbd->_ORPCthis = &orpcthis;
+ pbd->_Localthis = &localthis;
+ pbd->_ORPCthat = &orpcthat;
+ }
+#endif
+
+ do
+ {
+ cRetries++;
+ CPortableRpcHandle rh;
+
+ *pbd->_pdwDllType = dwsavedDllType; // restore in case not first time
+
+ //
+ // Get server DLL info, start local server, or forward activation call
+ // to remote machine.
+ //
+ hr = pccd->GetServer(pbd, pgcd, rh, ServerStarted, ActivatedRemote);
+
+ // If we did a remote activation then, success or not, we're done.
+ if ( ActivatedRemote )
+ break;
+
+ if (rh.GetHandle() == NULL)
+ {
+ // If we don't have an RPC handle then we don't need to
+ // do any communication so we are done.
+ break;
+ }
+
+ if (ServerStarted)
+ {
+ // We will break this loop if communication fails with
+ // the server.
+ cRetries = MAX_OBJSRV_RETRIES;
+ }
+
+ // plsrv will be NULL in the event of an error so it will only be
+ // set if there is indeed an object server that we need to contact.
+ error_status_t rpcstat = RPC_S_OK;
+ int cBusyRetries = 0;
+
+ do
+ {
+ _try
+ {
+ switch (pbd->_scmmsg)
+ {
+#ifndef _CHICAGO_
+ case GETCLASSOBJECTEX:
+ localthis.callcat = CALLCAT_INPUTSYNC;
+ hr2=ObjectServerGetClassObject(rh.GetHandle(),
+ &orpcthis,
+ &localthis,
+ &orpcthat,
+ &pbd->_guidForClass,
+ (MInterfacePointer **)pbd->_ppIFD);
+ break;
+ case CREATEINSTANCEEX:
+ localthis.callcat = CALLCAT_SYNCHRONOUS;
+ hr2 = ObjectServerCreateInstance(
+ rh.GetHandle(),
+ &orpcthis,
+ &localthis,
+ &orpcthat,
+ NULL,
+ &pbd->_guidForClass,
+ pgcd->_dwInterfaces,
+ pgcd->_pIIDs,
+ pgcd->_pclsidHandler,
+ pgcd->_pIFPClientSiteHandler,
+ (MInterfacePointer **)pgcd->_ppIFDunk,
+ pgcd->_pResults,
+ pgcd->_ppIFPServerHandler
+ );
+ break;
+ case GETPERSISTENTEX:
+ localthis.callcat = CALLCAT_SYNCHRONOUS;
+ hr2 = ObjectServerGetInstance(
+ rh.GetHandle(),
+ &orpcthis,
+ &localthis,
+ &orpcthat,
+ NULL,
+ &pbd->_guidForClass,
+ pgcd->_grfMode,
+ pgcd->_pwszPath,
+ (MInterfacePointer *)pgcd->_pIFDstg,
+ pgcd->_dwInterfaces,
+ (MInterfacePointer *)pgcd->_pifdFromROT,
+ pgcd->_pIIDs,
+ (MInterfacePointer **)pgcd->_ppIFDunk,
+ pgcd->_pResults );
+ break;
+#else
+ case GETCLASSOBJECT:
+ hr2=REMCOGETACTIVECLASSOBJECT(rh.GetHandle(),
+ pbd->_pguidThreadId,
+ &pbd->_guidForClass,
+ pbd->_ppIFD,
+ &rpcstat);
+ break;
+ case GETPERSISTENTOBJ:
+ hr2=REMCOACTIVATEOBJECT(rh.GetHandle(),
+ pgcd->_pwszProtseq,
+ pbd->_pguidThreadId,
+ &pbd->_guidForClass,
+ pgcd->_grfMode,
+ pgcd->_pwszPath,
+ pgcd->_pIFDstg,
+ pgcd->_dwTIDCaller,
+ pgcd->_pdwTIDCallee,
+ pgcd->_ppIFDunk,
+ pgcd->_pifdFromROT,
+ &rpcstat);
+ break;
+ case CREATEPERSISTENTOBJ:
+ hr2=REMCOCREATEOBJECT(rh.GetHandle(),
+ pgcd->_pwszProtseq,
+ pbd->_pguidThreadId,
+ &pbd->_guidForClass,
+ pgcd->_grfMode,
+ pgcd->_pwszPath,
+ pgcd->_pIFDstg,
+ pgcd->_pwszNewName,
+ pgcd->_dwTIDCaller,
+ pgcd->_pdwTIDCallee,
+ pgcd->_ppIFDunk,
+ &rpcstat);
+
+ break;
+#endif // _CHICAGO_
+ }
+
+ //
+ // Treat CO_E_SERVER_STOPPING as a special case. It is
+ // possible for something like RemCoGetActiveClassObject to
+ // fail with this error. An example scenario:
+ // Server
+ // - does a CoRegisterClassObject for SINGLE USE resulting
+ // in an entry in the SCM's Class cache and an entry in
+ // OLE's DLL cache
+ // - (acting as its own client) server proceeds to consume
+ // it via CoCreateInstance. In this case the entry in the
+ // DLL cache is found and consumed leaving the SCM's Class
+ // cache in an inconsistent state (yes...a bug, but reality
+ // intrudes). Also, because SINGLE USE was indicated entry
+ // in DLL cache is marked such that it will not be handed
+ // out again.
+ // - if another CoCreateInstance comes along (server itself
+ // or another client) the request will go to the SCM which
+ // in turn will issue RemCoGetActiveClassObject to the
+ // server. Server will return CO_E_SERVER_STOPPING after
+ // failing to find it in the DLL cache.
+ //
+ // To get around this problem we break out of the inner loop
+ // and make it go through the outer do...while which should
+ // result in the activation of a new instance of the server.
+ //
+ // Note that in the above case the SCM's class cache entry has
+ // already been invalidated by the earlier call to GetServer
+ // (because of SINGLE USE). The invalidation code is here for
+ // other cases of CO_E_SERVER_STOPPING.
+ //
+ if (hr2 == CO_E_SERVER_STOPPING)
+ {
+ if (!rh.fSingleUse())
+ {
+ pccd->InvalidateHandle(rh);
+ }
+ break;
+ }
+ }
+ _except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ rpcstat = GetExceptionCode();
+ }
+ } while(RetryRpc(cBusyRetries, rpcstat, hr2));
+
+ rh.FreeSingleUseBinding();
+
+#ifndef _CHICAGO_
+ pccd->DecHandleCount(rh);
+#endif
+
+ // Call to object server to complete the operation
+ if (FAILED(hr2))
+ {
+ // We will assume that if these errors occur that we
+ // should try to start the server because it died
+ // in some awful way.
+ if (hr2 == CO_E_OBJSRV_RPC_FAILURE)
+ {
+ BOOL fReload = FALSE;
+ if (!rh.fSingleUse())
+ {
+ CScmLockForWrite scmlckwr(gClassCacheLock);
+ // TRUE means the last registration was deleted
+ fReload = pccd->StopServer(rh);
+ if (fReload)
+ {
+ // This will release if we're the only thread.
+ pccd->Release(this);
+ pccd = NULL;
+ }
+ }
+
+ if (fReload)
+ {
+ hr = GetClassData ( pbd->_guidForClass,
+ &pccd,
+ FALSE /* don't leave locked */ );
+ if ( FAILED(hr) )
+ {
+ break;
+ }
+ }
+
+ continue;
+ }
+ else if (hr2 == CO_E_SERVER_STOPPING)
+ {
+ // This is really an RPC problem with the server
+ // If we started the server and we land up here.
+ // If we got a version of the server that is stopping
+ // we will try to restart it.
+ hr2 = CO_E_OBJSRV_RPC_FAILURE;
+ continue;
+ }
+ else if (!rh.fSingleUse())
+ {
+ Sleep (1000);
+ if (!pccd->VerifyHandle(rh))
+ continue;
+ }
+
+ // All return results from the above RPC will made 1 to 1
+ // to error returns from the SCM interface so that we don't
+ // have to remap error codes with a wasteful switch statement.
+ // BUGBUG: Make sure above is true.
+ break;
+ }
+
+ // Success - return the result to the client
+ break;
+ }
+ while(cRetries < MAX_OBJSRV_RETRIES);
+
+ {
+ CScmLockForWrite scmlckwr(gClassCacheLock);
+ //
+ // NOTE! We need to take the write lock since the destruction
+ // of CClassData will affect the ref counted objects
+ // (such as CSafeLocalServer.)
+ //
+ if (pccd != NULL)
+ pccd->Release(this);
+ }
+
+ return SUCCEEDED(hr2) ? hr : hr2;
+}
+#endif // _CHICAGO_
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ThreadModelMatch
+//
+// Synopsis: Determines whether caller and DLL thread models match
+//
+// Arguments: [dwCallerThreadModel] - Caller thread model
+// [dwDllThreadModel] - DLL thread model
+//
+// Returns: TRUE - DLL can be loaded caller
+// FALSE - DLL cannot be loaded into caller.
+//
+// Algorithm: If the caller's thread model is apartment, then check
+// whether the DLL is one of apartment, single threaded or
+// both threaded. If it is, then return TRUE. Otherwise,
+// for free threading return TRUE if the DLL model is either
+// both or free threaded. If neither of the above is TRUE
+// then return FALSE.
+//
+// History: 10-Nov-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL ThreadModelMatch(
+ DWORD dwCallerThreadModel,
+ DWORD dwDllThreadModel,
+ DWORD dwContext)
+{
+ BOOL fResult = afThreadModelMatch[dwCallerThreadModel] [dwDllThreadModel];
+
+ if (dwContext & CLSCTX_PS_DLL)
+ {
+ fResult = TRUE;
+ }
+
+ return fResult;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: RetryRpc
+//
+// Synopsis: Determines whether a request to a object server s/b retried.
+//
+// Arguments: [cRetries] - how many retries have occurred.
+// [rpcstat] - RPC status from call.
+// [sc] - Error return from the API.
+//
+// Returns: TRUE - retry call to server
+// FALSE - do not retry the RPC call.
+//
+// Algorithm: We default the retry to FALSE. Then we check the status
+// returned by RPC. If it is because the server is too
+// busy and we have not exceeded our maximum number of
+// retries, we set the retry flag to TRUE. Otherwise,
+// we give up. If the error we have gotten back is from
+// the object server, then if it is a message that
+// the server is stopping, we sleep but do not set
+// the error flag. This because we don't want to retry
+// the RPC because the server is going away. But we
+// want to make sure that it is gone and then we will
+// restart the service.
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL RetryRpc(
+ int& cRetries,
+ error_status_t rpcstat,
+ HRESULT& hr)
+{
+ // Assume we do not want to loop
+ BOOL fResult = FALSE;
+
+ if (rpcstat != 0 || hr == RPC_E_SERVER_DIED_DNE)
+ {
+ hr = CO_E_OBJSRV_RPC_FAILURE;
+
+ if (rpcstat == RPC_S_SERVER_TOO_BUSY)
+ {
+ if (cRetries++ != MAX_BUSY_RETRIES)
+ {
+ // We haven't exceeed our max so sleep and retry
+ Sleep(500);
+ fResult = TRUE;
+ }
+ }
+ }
+
+ return fResult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassData::CClassData
+//
+// Synopsis: Create service information object in the cache by
+// starting from scratch or by merging.
+//
+// Arguments: [ccd] - class ID for the object
+// [ppwszLocalSrv] - name of the local server exe
+// [fActivateAtStorage] - whether we activate the object at bits
+// [cEntries] - number of entries in the skip list.
+// [SixteenBitFlags] - Which of the above are 16-bit
+// [hr] - On error, set to error code. On success, left
+// unchanged.
+//
+// History: 21-Apr-93 Ricksa Created
+//
+// Notes:
+// There are two types of classes we must deal with. 16bit and 32bit.
+// To the SCM, the only real difference is which registry key the
+// class was found under. SixteenBitFlags indicates which registry
+// key was found to be 16-bit, and which was 32-bit.
+//--------------------------------------------------------------------------
+CClassData::CClassData(
+ const CClassID& ccd,
+ WCHAR *pwszAppID,
+ const WCHAR *pwszLocalSrv,
+ WCHAR *pwszRemoteServerName,
+ BOOL fHasService,
+ WCHAR *pwszServiceArgs,
+ WCHAR *pwszRunAsUserName,
+ WCHAR *pwszRunAsDomainName,
+#ifdef DCOM
+ // NT 5.0 PSID pUserSid,
+#endif // DCOM
+ const BOOL ActivateAtStorage,
+ const BOOL RemoteServerName,
+ const SECURITY_DESCRIPTOR * pSD,
+ const BOOL f16Bit,
+ HRESULT &hr)
+ // NT 5.0 : CClsidSid(ccd, pUserSid),
+ : CClassID(ccd),
+ _pwszAppID( pwszAppID ),
+ _slocalsrv(pwszLocalSrv, hr),
+ _pwszRemoteServer(pwszRemoteServerName),
+ _fHasService(fHasService),
+ _pwszServiceArgs(pwszServiceArgs),
+ _pwszRunAsDomainName(pwszRunAsDomainName),
+ _pwszRunAsUserName(pwszRunAsUserName),
+ _pwszSurrogateCmdLine(NULL),
+ _fActivateAtStorage(ActivateAtStorage),
+ _fRemoteServerName(RemoteServerName),
+ _pSD(pSD),
+#ifndef _CHICAGO_
+ _hClassStart(NULL),
+#endif
+ _fLocalServer16(f16Bit),
+ _pssrvreg(NULL),
+ _ulRefs(1)
+{
+ //
+ // A service name is allocated by CAppIDData class and ownership is passed
+ // to CClassData. CLocalServer allocates and copies the string, so free
+ // the one passed in.
+ //
+ if ( _fHasService )
+ ScmMemFree( (void *)pwszLocalSrv );
+
+ if (FAILED(hr))
+ return;
+
+ // rpc handle list
+ _pssrvreg = new CSrvRegList();
+
+ // even if this succeeds, the srvreglist may fail when used.
+ if (_pssrvreg == NULL)
+ {
+ CairoleDebugOut ((DEB_ERROR, "Fail to allocate memory in CClassData\n"));
+ hr = E_OUTOFMEMORY;
+ return;
+ }
+
+#ifndef _CHICAGO_
+ //
+ // Create our class start notification - note this can be automatic reset
+ // because we only allow one thread to wait on this event because we will
+ // own the server object lock when we are waiting on this event.
+ // NT uses events created now and kept around (not named.)
+ // (x86 Windows creates/destroys event when needed.)
+ //
+ _hClassStart = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ if (_hClassStart == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "CClassData::CClassData Event Create Failed %lx\n",
+ GetLastError()));
+ delete _pssrvreg;
+ _pssrvreg = NULL;
+ hr = E_OUTOFMEMORY;
+ return;
+ }
+#endif
+
+ Win4Assert(_pssrvreg != NULL);
+
+ // Make sure we set the error code correctly on success
+ hr = NOERROR;
+}
+
+CClassData::CClassData(
+ const CClassID& ccd,
+ HRESULT &hr)
+ // NT 5.0 : CClsidSid(ccd, NULL),
+ : CClassID(ccd),
+ _pwszAppID(NULL),
+ _slocalsrv(NULL, hr),
+ _pwszRemoteServer(NULL),
+ _fHasService(FALSE),
+ _pwszServiceArgs(NULL),
+ _pwszRunAsDomainName(NULL),
+ _pwszRunAsUserName(NULL),
+ _pwszSurrogateCmdLine(NULL),
+ _fActivateAtStorage(FALSE),
+ _fRemoteServerName(FALSE),
+ _pSD(NULL),
+#ifndef _CHICAGO_
+ _hClassStart(NULL),
+#endif
+ _fLocalServer16(FALSE),
+ _pssrvreg(NULL),
+ _ulRefs(1)
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassData::Release
+//
+// Synopsis: Decrement ref count and delete from list if no server regs.
+//
+// Arguments: [pccl] - list to delete from
+//
+// History: 08-Dec-94 BillMo Created
+//
+//--------------------------------------------------------------------------
+
+VOID CClassData::Release()
+{
+ Win4Assert(_ulRefs != 0);
+ _ulRefs --;
+ if (_ulRefs == 0)
+ {
+ if (!InUse())
+ {
+ // NT 5.0 Verify(NULL != gpClassCache->Remove((CClsidSid*)this));
+ Verify(NULL != gpClassCache->Remove((CClassID*)this));
+ delete this;
+ }
+ }
+}
+
+void
+LogRegisterTimeout(
+ CLSID & clsid,
+ ACTIVATION_PARAMS * pActParams )
+{
+ // %1 is the clsid
+ HANDLE LogHandle;
+ LPTSTR Strings[1]; // array of message strings.
+ WCHAR wszClsid[GUIDSTR_MAX];
+
+ // Get the clsid
+ wStringFromGUID2(clsid, wszClsid, sizeof(wszClsid));
+ Strings[0] = wszClsid;
+
+ // Get the log handle, then report then event.
+ LogHandle = RegisterEventSource( NULL,
+ SCM_EVENT_SOURCE );
+
+ if ( LogHandle )
+ {
+ ReportEvent( LogHandle,
+ EVENTLOG_ERROR_TYPE,
+ 0, // event category
+ EVENT_RPCSS_SERVER_START_TIMEOUT,
+ pActParams->pToken ? pActParams->pToken->GetSid() : NULL, // SID
+ 1, // 1 strings passed
+ 0, // 0 bytes of binary
+ (LPCTSTR *)Strings, // array of strings
+ NULL ); // no raw data
+
+ // clean up the event log handle
+ DeregisterEventSource(LogHandle);
+ }
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassData::GetServer
+//
+// Synopsis: Get the server information for a service
+//
+// Arguments: [dwContext] - context requested by client
+// [ppwszDll ] - where to put ptr to DLL name
+// [rh] - RPC handle to use for talking to object server
+// [ServerStarted] - whether we actually started the server.
+//
+// Returns: REGDB_E_CLASSNOTREG - Information for context not in DB
+//
+// Algorithm: First we check whether it is appropriate to run with
+// an inprocess server. If so we return that. If a handler
+// is appropriate for the context, we return that. Otherwise,
+// we return a server object and a handler if the object
+// requires it.
+//
+// We also allow for the case where the client wants
+// to load a 16-bit inproc server. This is used by the VDM
+// to load proxy/stub code for 16/32 interoperability.
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef _CHICAGO_
+HRESULT CClassData::GetServer(
+ ACTIVATION_PARAMS * pActParams,
+ CPortableRpcHandle &rh,
+ BOOL& ServerStarted,
+ BOOL& ActivatedRemote,
+ BOOL& fSurrogate)
+{
+#if DBG
+ WCHAR wszClass[40];
+
+ CairoleDebugOut((DEB_ITRACE,
+ "CClassData::GetServer(%x) for class %ws\n",
+ this,
+ FormatGuid(*pActParams->Clsid, wszClass)));
+#endif
+
+ HRESULT hr;
+ BOOL bStatus;
+ WCHAR * pwszSurrogateCmdLine = NULL;
+
+ ActivatedRemote = FALSE;
+
+ //
+ // If an explicit server name was specified in the remote activation
+ // call, then we don't check local class info. Note that if the server
+ // name is equal to the current machine name, the CLSCTX_REMOTE_SERVER
+ // bit gets masked out in Activation.
+ //
+ if ( pActParams->pwszServer && (pActParams->ClsContext & CLSCTX_REMOTE_SERVER) )
+ goto GET_SERVER_TRY_REMOTE;
+
+ //
+ // Next we check if this CLSID has ActivateAtStorage, and do a remote
+ // activation if the path is remote, otherwise we'll continue along.
+ //
+ if ( ActivateAtStorage( &hr, pActParams ) == DONT_TRY_LOCAL_ACTIVATION )
+ {
+ ActivatedRemote = TRUE;
+ return hr;
+ }
+
+ if ( pActParams->pwszPath != NULL )
+ {
+ //
+ // We use FoundInROT to indicate that we got an object from the
+ // ROT. We need to do this because there is no guarantee that the
+ // ROT entry will not be bad by the time we get back to the caller
+ // and therefore, the caller will want to retry in this case.
+ //
+ hr = GetObjectFromRot( pActParams->pToken,
+ pActParams->pwszWinstaDesktop,
+ pActParams->pwszPath,
+ (InterfaceData **)&pActParams->pIFDROT );
+
+ if ( hr == S_OK )
+ {
+ //
+ // Is this a call from a local client and is a single
+ // interface being requested? If so, we can return now.
+ // Otherwise we call the server because we either need more
+ // interfaces and choose to get them now, or because we are
+ // servicing a remote activation and want to get a normal
+ // marshalled interface pointer rather than the table marshalled
+ // interface pointer sitting in the ROT.
+ //
+ if ( ! pActParams->RemoteActivation && (pActParams->Interfaces == 1) )
+ {
+ // Return the marshaled interface from the ROT to the caller.
+ *pActParams->ppIFD = pActParams->pIFDROT;
+ pActParams->pResults[0] = S_OK;
+
+ // So we remember not to clean up the buffer
+ pActParams->pIFDROT = NULL;
+
+ // Let caller know that we got this from the ROT so
+ // if it doesn't work they should try again.
+ pActParams->FoundInROT = TRUE;
+
+ // We got what we came for from the ROT so we can exit.
+ CairoleDebugOut((DEB_TRACE, "Found object in the ROT\n"));
+ return S_OK;
+ }
+
+ //
+ // Because a tabled marshaled interface is not enought
+ // to get unmarshaled locally, we need to send it back
+ // to the object server to get something we can pass back
+ // to another machine. So we continue on here...
+ //
+ }
+ }
+
+ if ( pActParams->ClsContext & CLSCTX_LOCAL_SERVER )
+ {
+ PSID psid = NULL;
+
+ //
+ // We need to compare SIDs unless the server is configured as
+ // LocalService or RunAs.
+ //
+ if( !_fHasService && !_pwszRunAsUserName )
+ {
+ //
+ // Unsecure activation can only connect to services or RunAs
+ // servers.
+ //
+ if ( pActParams->UnsecureActivation )
+ return E_ACCESSDENIED;
+
+ psid = pActParams->pToken->GetSid();
+ }
+
+ // Check if the server is already registered.
+ bStatus = _pssrvreg->GetHandle( IFSECURITY(psid)
+ pActParams->pwszWinstaDesktop,
+ rh,
+ FALSE);
+
+
+ //
+ // If we didn't find a handle or IObjServer for an already running server and
+ // a local server is not in the registry for this class, we check
+ // for an inproc server to start in surrogate
+
+ if(!bStatus && !(_slocalsrv.Defined()))
+ {
+ fSurrogate =
+ SUCCEEDED(GetInProcServerInfo(&pwszSurrogateCmdLine));
+ }
+
+ // if there's no existing server running
+ if ( ! bStatus && (_slocalsrv.Defined() || fSurrogate) )
+ {
+ Win4Assert(!(_slocalsrv.Defined() && fSurrogate));
+
+ CSafeLocalServer * pslocalsrv = (fSurrogate && !_fHasService) ?
+ gpClassCache->GetSurrogateLocalServer() : &_slocalsrv;
+
+ //
+ // CPortableServerLock is to prevent multiple process creates for
+ // the same server.
+ // CPortableServerEvent is signaled when the class we're activating
+ // for gets registered.
+ //
+ CPortableServerLock sl(*pslocalsrv);
+ CPortableServerEvent se(this);
+ HANDLE hProcess = 0;
+ SC_HANDLE hService = 0;
+ SERVICE_STATUS ServiceStatus;
+ DWORD dwWaitResult;
+ BOOL ServiceFailed = FALSE;
+ HRESULT hr = S_OK;
+ error_status_t rpcstat;
+
+ if ( sl.Error() != ERROR_SUCCESS )
+ {
+ hr = sl.Error();
+ goto EXIT_START_SERVER;
+ }
+
+ if ( se.Create() != ERROR_SUCCESS )
+ {
+ hr = se.Create();
+ goto EXIT_START_SERVER;
+ }
+
+ // if this is a new surrogate, get its command line and save it
+ if(pwszSurrogateCmdLine)
+ {
+ _pwszSurrogateCmdLine = pwszSurrogateCmdLine;
+ pwszSurrogateCmdLine = NULL;
+ }
+
+ //
+ // We check the class registrations again after taking the server
+ // lock. This is stupid, but I need to redo that brain dead
+ // CPortableServerLock crap before changing this.
+ //
+ bStatus = _pssrvreg->GetHandle( IFSECURITY(psid)
+ pActParams->pwszWinstaDesktop,
+ rh,
+ FALSE);
+
+ if ( bStatus )
+ {
+ goto EXIT_START_SERVER;
+ }
+
+ // Check that we have access rights to the server
+ // irrespective of whether this is a local or remote
+ // call
+ if (FAILED(CkIfCallAllowed(pActParams)))
+ {
+ hr = E_ACCESSDENIED;
+ goto EXIT_START_SERVER;
+ }
+
+ // Local services take precedence over local servers.
+ if (_fHasService)
+ {
+ bStatus = (*pslocalsrv)->StartService(_guid,
+ pActParams->pToken,
+ _pwszServiceArgs,
+ &hService);
+ }
+ else
+ {
+ CClassData* pccdSrgt = NULL;
+
+ if(fSurrogate && gpClassCache->FindCompatibleSurrogate(
+ IFSECURITY(psid)
+ &pccdSrgt,
+ pActParams->pwszWinstaDesktop,
+ _pwszAppID,
+ rh))
+ {
+ HRESULT hrSurrogateLaunched;
+ bStatus = FALSE;
+
+ if ( ! pActParams->UnsecureActivation )
+ RpcImpersonateClient((RPC_BINDING_HANDLE)0);
+
+ hrSurrogateLaunched = ObjectServerLoadDll(
+ rh.GetHandle(),
+ pActParams->ORPCthis,
+ pActParams->Localthis,
+ pActParams->ORPCthat,
+ &_guid,
+ &rpcstat);
+
+ if ( ! pActParams->UnsecureActivation )
+ RpcRevertToSelf();
+
+ pccdSrgt->DecHandleCount(rh);
+
+ if ( FAILED(hrSurrogateLaunched) || (rpcstat != RPC_S_OK) )
+ {
+ if ( (hrSurrogateLaunched == CO_E_SERVER_STOPPING) ||
+ (rpcstat != RPC_S_OK) )
+ {
+ InvalidateHandle(rh);
+ }
+ else
+ {
+ hr = hrSurrogateLaunched;
+ goto EXIT_START_SERVER;
+ }
+ }
+ else
+ {
+ bStatus = TRUE;
+ goto EXIT_START_SERVER;
+ }
+ }
+
+ if ( ! bStatus )
+ {
+
+ bStatus = (*pslocalsrv)->StartServer(
+ _guid,
+ _pwszAppID,
+ pActParams->pToken,
+ pActParams->pwszWinstaDesktop,
+ &hProcess,
+ _pwszRunAsDomainName,
+ _pwszRunAsUserName,
+ _pwszSurrogateCmdLine,
+ fSurrogate);
+ }
+ }
+
+ if ( ! bStatus )
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "Start Server/Service failed in GetServer,"
+ "returning CO_E_SERVER_EXEC_FAILURE\n"));
+
+ hr = CO_E_SERVER_EXEC_FAILURE;
+ goto EXIT_START_SERVER;
+ }
+
+ // Let caller know that we did start a server
+ ServerStarted = TRUE;
+
+ for (;;)
+ {
+ dwWaitResult = WaitForSingleObject(
+ se.GetHandle(),
+ MAX_CLASS_START_WAIT );
+
+ if ( dwWaitResult == WAIT_OBJECT_0 )
+ break;
+
+ if ( ! _fHasService )
+ {
+ TerminateProcess(hProcess, 0);
+ break;
+ }
+
+ bStatus = ControlService( hService,
+ SERVICE_CONTROL_INTERROGATE,
+ &ServiceStatus );
+
+ if ( ! bStatus )
+ {
+ ServiceFailed = TRUE;
+ break;
+ }
+
+ switch ( ServiceStatus.dwCurrentState )
+ {
+ case SERVICE_STOPPED :
+ case SERVICE_STOP_PENDING :
+ break;
+
+ case SERVICE_START_PENDING :
+ case SERVICE_CONTINUE_PENDING :
+ continue;
+
+ case SERVICE_RUNNING :
+ case SERVICE_PAUSE_PENDING :
+ case SERVICE_PAUSED :
+ ServiceFailed = TRUE;
+ break;
+ }
+
+ break;
+ }
+
+ if ( ServiceFailed )
+ {
+ (void) ControlService( hService,
+ SERVICE_CONTROL_STOP,
+ &ServiceStatus );
+ }
+
+ if ( hProcess )
+ CloseHandle( hProcess );
+ if ( hService )
+ CloseServiceHandle( hService );
+
+ // Server is started so we can now get a handle.
+ bStatus = _pssrvreg->GetHandle( IFSECURITY(psid)
+ pActParams->pwszWinstaDesktop,
+ rh,
+ FALSE);
+
+ if ( ! bStatus )
+ {
+ // TODO: log message that server did not register w/in timeout
+ LogRegisterTimeout( _guid, pActParams );
+ CairoleDebugOut((DEB_ERROR,
+ "GetServer returning CO_E_SERVER_EXEC_FAILURE\n"));
+ hr = CO_E_SERVER_EXEC_FAILURE;
+ goto EXIT_START_SERVER;
+ }
+
+EXIT_START_SERVER:
+
+ if(pwszSurrogateCmdLine)
+ {
+ ScmMemFree(pwszSurrogateCmdLine);
+ }
+
+ if(FAILED(hr) && !bStatus)
+ {
+ return hr;
+ }
+ }
+
+ //
+ // If we got a handle from either an already running server or a
+ // newly launched server we're done. If we tried to launch a new
+ // server and it failed we will return above.
+ //
+ if ( bStatus )
+ return S_OK;
+
+ Win4Assert( ! _slocalsrv.Defined() );
+
+ //
+ // If we didn't find a handle to an already registered server and
+ // a local server is not in the registry for this class, we check
+ // for a remote server name in the registry below.
+ //
+ }
+
+GET_SERVER_TRY_REMOTE:
+
+ if ( pActParams->ClsContext & CLSCTX_REMOTE_SERVER )
+ {
+ //
+ // If this returns TRY_LOCAL_ACTIVATION it means no server name is
+ // specified in the registry and no server name was given in the
+ // activation call. So we return an error.
+ //
+ // If CLSCTX_REMOTE_SERVER was the only class context we'll return a
+ // more specific error.
+ //
+ if ( ActivateRemote( &hr, pActParams ) == TRY_LOCAL_ACTIVATION )
+ {
+ hr = (pActParams->ClsContext == CLSCTX_REMOTE_SERVER) ?
+ CO_E_CANT_REMOTE : REGDB_E_CLASSNOTREG;
+ }
+
+ //
+ // We always set this to TRUE at this point, success or not, to
+ // indicate we tried a remote activation. This will tell
+ // ProcessScmMessage to return and not make a SCM-OLE call.
+ //
+ ActivatedRemote = TRUE;
+
+ return hr;
+ }
+
+ return REGDB_E_CLASSNOTREG;
+}
+#endif
+
+//+-------------------------------------------------------------------
+//
+// Member: CClassData::ActivateAtStorage
+//
+// Synopsis: Forward remote activation request, if necessary.
+//
+// Arguments: [phr] -- set if atbits processing was done
+//
+// Returns: FALSE if it's a local activation
+//
+//--------------------------------------------------------------------
+
+BOOL CClassData::ActivateAtStorage(
+ HRESULT *phr,
+ ACTIVATION_PARAMS * pActParams )
+{
+#ifdef DCOM
+ RPC_STATUS RpcStatus;
+ HRESULT hr;
+ WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH+1];
+ WCHAR wszPathForServer[MAX_PATH+1];
+ WCHAR * pwszPathForServer;
+
+ switch (pActParams->MsgType)
+ {
+ case GETCLASSOBJECTEX :
+ case CREATEINSTANCEEX :
+ //
+ // The ActivateAtStorage key is ignored for CoGetClassObject and
+ // CoCreateInstanceEx.
+ //
+ return TRY_LOCAL_ACTIVATION;
+ break;
+ case GETPERSISTENTEX :
+ if ( ! HasActivateAtStorage() )
+ return TRY_LOCAL_ACTIVATION;
+ break;
+ }
+
+ //
+ // CLSCTX_REMOTE_SERVER must be set or a remote activation is not
+ // possible.
+ //
+ if ( ! (pActParams->ClsContext & CLSCTX_REMOTE_SERVER) )
+ {
+ return TRY_LOCAL_ACTIVATION;
+ }
+
+ //
+ // This is for DFS support. If the file hasn't been opened yet, we must
+ // open it before trying to resolve the DFS pathname in GetMachineName.
+ // This is just how DFS works. FindFirstFile results in the fewest number
+ // of network packets.
+ //
+ if ( ! pActParams->FileWasOpened )
+ {
+ HANDLE hFile;
+ WIN32_FIND_DATA Data;
+
+ RpcImpersonateClient(NULL);
+
+ hFile = FindFirstFile( pActParams->pwszPath, &Data );
+
+ if ( hFile != INVALID_HANDLE_VALUE )
+ (void) FindClose( hFile );
+
+ RpcRevertToSelf();
+
+ if ( INVALID_HANDLE_VALUE == hFile )
+ {
+ *phr = CO_E_BAD_PATH;
+ return DONT_TRY_LOCAL_ACTIVATION;
+ }
+ }
+
+ hr = GetMachineName( pActParams->pwszPath, wszMachineName, TRUE );
+
+ if ( hr == S_FALSE )
+ {
+ // We couldn't get the machine name, path must be local.
+ return TRY_LOCAL_ACTIVATION;
+ }
+ else if ( hr != S_OK )
+ {
+ // We got an error while trying to find the UNC machine name.
+ *phr = hr;
+ return DONT_TRY_LOCAL_ACTIVATION;
+ }
+
+ //
+ // Make sure the server's name is not our machine name. Return status
+ // to indicate a local activation should be tried.
+ //
+ if ( lstrcmpiW(wszMachineName,SCMMachineName) == 0 )
+ return TRY_LOCAL_ACTIVATION;
+
+ hr = GetPathForServer( pActParams->pwszPath, wszPathForServer, &pwszPathForServer );
+ if ( hr != S_OK )
+ {
+ *phr = hr;
+ return DONT_TRY_LOCAL_ACTIVATION;
+ }
+
+ *phr = RemoteActivationCall( pActParams, wszMachineName, pwszPathForServer );
+
+ return DONT_TRY_LOCAL_ACTIVATION;
+#else
+ return TRY_LOCAL_ACTIVATION;
+#endif // DCOM
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CClassData::ActivateRemote
+//
+// Synopsis: Forward remote activation request, if necessary.
+//
+// Arguments: [phr] -- set if atbits processing was done
+//
+// Returns: FALSE if it's a local activation
+//
+//--------------------------------------------------------------------
+
+BOOL CClassData::ActivateRemote(
+ HRESULT *phr,
+ ACTIVATION_PARAMS * pActParams )
+{
+#ifdef DCOM
+ handle_t hRemoteSCMHandle;
+ RPC_STATUS RpcStatus;
+ HRESULT hr;
+ WCHAR * pwszServerName;
+ WCHAR wszPathForServer[MAX_PATH+1];
+ WCHAR * pwszPathForServer;
+ BOOL ActivateRemote;
+
+ *phr = S_OK;
+
+ ActivateRemote = HasRemoteServerName() || pActParams->pwszServer;
+
+ switch (pActParams->MsgType)
+ {
+ case GETCLASSOBJECTEX :
+ case CREATEINSTANCEEX :
+ if ( ! ActivateRemote )
+ return TRY_LOCAL_ACTIVATION;
+ break;
+ case GETPERSISTENTEX :
+ if ( ! ActivateRemote )
+ return TRY_LOCAL_ACTIVATION;
+ break;
+ }
+
+ //
+ // CLSCTX_REMOTE_SERVER must be set or a remote activation is not
+ // possible.
+ //
+ if ( ! (pActParams->ClsContext & CLSCTX_REMOTE_SERVER) )
+ {
+ return TRY_LOCAL_ACTIVATION;
+ }
+
+ pwszServerName = pActParams->pwszServer;
+ if ( ! pwszServerName )
+ pwszServerName = GetRemoteServerName();
+
+ if ( pwszServerName[0] == L'\\' && pwszServerName[1] == L'\\' )
+ pwszServerName += 2;
+
+ if ( pwszServerName[0] == L'\0' )
+ {
+ *phr = CO_E_BAD_SERVER_NAME;
+ return DONT_TRY_LOCAL_ACTIVATION;
+ }
+
+ //
+ // Make sure the server's name is not our machine name.
+ //
+ // Return TRUE to indicate that no local activation should be tried in
+ // these cases.
+ //
+ if ( lstrcmpiW(pwszServerName,SCMMachineName) == 0 )
+ {
+ return TRY_LOCAL_ACTIVATION;
+ }
+
+ //
+ // Note that pActParams->pwszPath can be NULL for GetClassObject or
+ // CreateInstance remoted calls.
+ //
+ if ( pActParams->pwszPath )
+ {
+ hr = GetPathForServer( pActParams->pwszPath, wszPathForServer, &pwszPathForServer );
+ if ( hr != S_OK )
+ {
+ *phr = hr;
+ return DONT_TRY_LOCAL_ACTIVATION;
+ }
+ }
+ else
+ {
+ pwszPathForServer = 0;
+ }
+
+ *phr = RemoteActivationCall( pActParams, pwszServerName, pwszPathForServer );
+
+ return DONT_TRY_LOCAL_ACTIVATION;
+#else
+ return TRY_LOCAL_ACTIVATION;
+#endif // DCOM
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CClassData::GetSurrogateCmdLine
+//
+// Parameters: ppwszCmdLine (OUT) - a pointer to a string that will
+// be allocated by this function to hold the command line
+// Thus, *ppwszCmdLine should be freed by the caller when
+// it is no longer needed
+//
+// Synopsis: Builds a command line for the surrogate
+// Using the CLSID and Inproc Server path
+//
+// Returns: E_FAIL if the command line couldn't be built,
+// S_OK if it could
+//
+//--------------------------------------------------------------------
+
+HRESULT CClassData::GetSurrogateCmdLine(
+ WCHAR* wszSurrogatePath,
+ WCHAR** ppwszCmdLine)
+{
+ HRESULT hr = E_FAIL;
+ DWORD AllocSize;
+
+ Win4Assert(!(*ppwszCmdLine));
+
+ WCHAR wszClsid[GUIDSTR_MAX + 1]; // holds string representation of CLSID
+
+ // get the string representation of the CLSID
+ if(FAILED(wStringFromGUID2(_guid,wszClsid,GUIDSTR_MAX)))
+ {
+ return E_FAIL;
+ }
+
+ // allocate space for the command line, which will be represented as
+ // <surrogate exe name><space><CLSID><endofstring>
+
+ // if wszSurrogatePath is NULL
+ // (no surrogate was specified in the registry),
+ // we'll use the default surrogate path,
+ // which we must construct from the system directory path and the
+ // wszSurrogateName
+ if ( wszSurrogatePath[0] )
+ AllocSize = lstrlenW(wszSurrogatePath);
+ else
+ AllocSize = MAX_PATH + 1 + lstrlenW(wszSurrogateName);
+ AllocSize += 1 + GUIDSTR_MAX;
+ AllocSize *= sizeof(WCHAR);
+
+ *ppwszCmdLine = (WCHAR *) PrivMemAlloc( AllocSize );
+
+ if(!*ppwszCmdLine)
+ {
+ hr = E_OUTOFMEMORY;
+ goto cleanup_and_exit;
+ }
+
+ // if a surrogate path was not specified in the registry,
+ // use the default
+ if(wszSurrogatePath[0] == L'\0')
+ {
+#ifndef _CHICAGO_
+ if(!GetSystemDirectoryW(*ppwszCmdLine,MAX_PATH + 1))
+ {
+ goto cleanup_and_exit;
+ }
+#else // !_CHICAGO_
+
+ char szCmdLine[MAX_PATH + 1];
+ if(!GetSystemDirectory(szCmdLine,MAX_PATH + 1))
+ {
+ goto cleanup_and_exit;
+ }
+
+ if(!(MultiByteToWideChar(CP_ACP,
+ 0,
+ szCmdLine,
+ lstrlenA(szCmdLine) + 1,
+ *ppwszCmdLine,
+ MAX_PATH)))
+ {
+ goto cleanup_and_exit;
+ }
+
+ Win4Assert(lstrlenA(szCmdLine) == lstrlenW(*ppwszCmdLine));
+#endif // !_CHICAGO_
+
+ lstrcatW(*ppwszCmdLine,L"\\");
+ lstrcatW(*ppwszCmdLine,wszSurrogateName);
+ }
+ else // use the path specified in the registry
+ {
+ lstrcpyW(*ppwszCmdLine,wszSurrogatePath);
+ }
+
+ lstrcatW(*ppwszCmdLine,L" ");
+ lstrcatW(*ppwszCmdLine,wszClsid);
+
+ hr = S_OK;
+
+cleanup_and_exit:
+
+ return hr;
+}
+
+
+WCHAR * CClassData::GetRemoteServerName()
+{
+ if ( ! HasRemoteServerName() )
+ return NULL;
+
+ return _pwszRemoteServer;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CClassData::GetInProcServerinfo
+//
+// Synopsis: finds either the pathname of an unlaunched surrogate
+// executable for loading an inproc server, or finds
+// a binding handle to an existing surrogate process
+//
+// Returns: REGDB_E_CLASSNOTREG if there is no DllSurrogate key
+// in the registry
+// S_OK if the DllSurrogate key exists in the registry
+// and/or it finds an existing surrogate process that
+// has the appropriate appid and security id.
+// E_FAIL for any other errors
+//
+//--------------------------------------------------------------------
+
+HRESULT CClassData::GetInProcServerInfo(WCHAR** ppwszSurrogateCmdLine)
+{
+ HKEY hkThisClsID = NULL;
+ HKEY hkThisAppID = NULL;
+ WCHAR wszDllSurrogatePath[MAX_PATH + 1];
+ ULONG ulSize = sizeof(DWORD);
+ LONG lSize = MAX_PATH + 1;
+ DWORD dwValType;
+ DWORD dwSurrogateRegister;
+ LONG lerr;
+ BOOL fDllSurrogateValueExists;
+
+ HRESULT hr = E_FAIL;
+
+ if(_pwszSurrogateCmdLine)
+ {
+ return S_OK;
+ }
+
+ // open the correct APPID key
+ if(RegOpenKeyEx(g_hkAppID,_pwszAppID, NULL, KEY_READ, &hkThisAppID) !=
+ ERROR_SUCCESS)
+ {
+ goto cleanup_and_exit;
+ }
+
+ lSize = sizeof(wszDllSurrogatePath);
+
+ // read the path for the surrogate
+ lerr = QueryStripRegNamedValue(hkThisAppID,
+ wszDllSurrogatePathValue,
+ wszDllSurrogatePath,
+ &lSize,
+ &fDllSurrogateValueExists);
+
+ // QueryStripRegNamedValue returns ERROR_FILE_NOT_FOUND if a value
+ // does not exist or if the value is the empty string, so since we
+ // want to distinguish between those two cases, we need to test
+ // to see if the DllSurrogate key exists if we get ERROR_FILE_NOT_FOUND
+ if ((lerr == ERROR_FILE_NOT_FOUND) && !fDllSurrogateValueExists)
+ {
+ // we don't launch surrogates unless the DllSurrogate value
+ // exists in the registry
+ hr = REGDB_E_CLASSNOTREG;
+ goto cleanup_and_exit;
+ }
+
+ Win4Assert(fDllSurrogateValueExists);
+
+ // close the registry key as soon as possible
+ RegCloseKey(hkThisAppID);
+ hkThisAppID = NULL;
+
+ if(FAILED(hr = GetSurrogateCmdLine(wszDllSurrogatePath,
+ ppwszSurrogateCmdLine)))
+ {
+ goto cleanup_and_exit;
+ }
+
+
+ hr = S_OK;
+
+cleanup_and_exit:
+
+ if(hkThisAppID)
+ {
+ RegCloseKey(hkThisAppID);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassData::Defined
+//
+// Synopsis: check whether this class entry is properly initialized
+//
+// Returns: TRUE - this class entry is now properly initialized
+// FALSE - this class entry is not properly initialized
+//
+// History: 30-Aug-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+BOOL CClassData::Defined (void)
+{
+ // _pssrvreg is the last to get initialized
+ // if it is initialized, everything else is initialized as well
+ if (_pssrvreg == NULL || !_pssrvreg->CreatedOk())
+ {
+ CairoleDebugOut ((DEB_ERROR, "Fail to allocate memory in CClassData\n"));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+//+-------------------------------------------------------------------------
+//
+// Member: CClassData::InvalidateHandle
+//
+// Synopsis: Invalidate a handle in the list of handles for the class
+// Caller of GetServer concluded it is no longer valid
+//
+// Arguments: [rh] -- handle to invalidate
+//
+// Returns: None
+//
+// Algorithm: Loop through the list searching for match on handle or
+// list is exhausted
+//
+// History: 20-Sep-95 MurthyS Created
+//
+//--------------------------------------------------------------------------
+VOID CClassData::InvalidateHandle(
+ CPortableRpcHandle &rh
+)
+{
+#ifndef _CHICAGO_
+ rh.InvalidateHandle(_pssrvreg);
+#else
+ // BUGBUG: (KevinRo) What is supposed to happen here?
+ Win4Assert("Unimplemented Function");
+#endif
+}
+
+void CClassData::GetAnonymousHandle(
+ CPortableRpcHandle &rh,
+ handle_t * phRpcAnonymous )
+{
+ _pssrvreg->GetAnonymousHandle( rh, phRpcAnonymous );
+}
+
+#ifndef _CHICAGO_
+void CClassData::DecHandleCount(
+ CPortableRpcHandle &rh
+)
+{
+ _pssrvreg->DecHandleCount(rh.GetHandle());
+}
+#endif
+
+const ULONG MAX_SERVICE_ARGS = 16;
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLocalServer::StartService
+//
+// Synopsis: Start a specified system service
+//
+// Arguments: HANDLE *
+//
+// Returns: BOOL
+//
+// History: 08-Nov-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+#ifndef _CHICAGO_
+BOOL CLocalServer::StartService(
+ CLSID & clsid,
+ CToken * pClientToken,
+ WCHAR *pwszRegServiceArgs,
+ SC_HANDLE *phService)
+{
+ WCHAR *pwszServiceArgs = NULL;
+ ULONG cArgs = 0;
+ WCHAR *apwszArgs[MAX_SERVICE_ARGS];
+ BOOL Status;
+
+ *phService = OpenService( hServiceController,
+ _pwszPath,
+ GENERIC_EXECUTE | GENERIC_READ );
+
+ if ( ! *phService )
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "OpenService %ws failed, error = %#x\n",_pwszPath,GetLastError()) );
+ return FALSE;
+ }
+
+ // Formulate the arguments (if any)
+ if (pwszRegServiceArgs)
+ {
+ UINT k = 0;
+
+ // Make a copy of the service arguments
+ pwszServiceArgs = (WCHAR *) PrivMemAlloc(
+ (lstrlenW(pwszRegServiceArgs) + 1) * sizeof(WCHAR));
+ if (pwszServiceArgs == NULL)
+ {
+ CloseServiceHandle(*phService);
+ *phService = 0;
+ return FALSE;
+ }
+ lstrcpyW(pwszServiceArgs, pwszRegServiceArgs);
+
+ // Scan the arguments
+ do
+ {
+ // Scan to the next non-whitespace character
+ while(pwszServiceArgs[k] &&
+ (pwszServiceArgs[k] == L' ' ||
+ pwszServiceArgs[k] == L'\t'))
+ {
+ k++;
+ }
+
+ // Store the next argument
+ if (pwszServiceArgs[k])
+ {
+ apwszArgs[cArgs++] = &pwszServiceArgs[k];
+ }
+
+ // Scan to the next whitespace char
+ while(pwszServiceArgs[k] &&
+ pwszServiceArgs[k] != L' ' &&
+ pwszServiceArgs[k] != L'\t')
+ {
+ k++;
+ }
+
+ // Null terminate the previous argument
+ if (pwszServiceArgs[k])
+ {
+ pwszServiceArgs[k++] = L'\0';
+ }
+ } while(pwszServiceArgs[k]);
+ }
+
+ Status = ::StartService( *phService,
+ cArgs,
+ cArgs > 0 ? (LPCTSTR *) apwszArgs : NULL);
+
+ PrivMemFree(pwszServiceArgs);
+
+ if ( Status )
+ return TRUE;
+
+ CairoleDebugOut((DEB_ERROR,
+ "StartService %ws failed, error = %#x\n",_pwszPath,GetLastError()));
+ CloseServiceHandle(*phService);
+ *phService = 0;
+
+ // %1 is the error number
+ // %2 is the service name
+ // %3 is the serviceargs
+ // %4 is the clsid
+ HANDLE LogHandle;
+ LPTSTR Strings[4]; // array of message strings.
+ WCHAR wszClsid[GUIDSTR_MAX];
+ WCHAR wszErrnum[20];
+ DWORD err = GetLastError();
+
+ // Save the error number
+ wsprintf(wszErrnum, L"%lu",err );
+ Strings[0] = wszErrnum;
+
+ Strings[1] = _pwszPath;
+ Strings[2] = pwszRegServiceArgs;
+
+ // Get the clsid
+ wStringFromGUID2(clsid, wszClsid, sizeof(wszClsid));
+ Strings[3] = wszClsid;
+
+ // Get the log handle, then report then event.
+ LogHandle = RegisterEventSource( NULL,
+ SCM_EVENT_SOURCE );
+
+ if ( LogHandle )
+ {
+ ReportEvent( LogHandle,
+ EVENTLOG_ERROR_TYPE,
+ 0, // event category
+ EVENT_RPCSS_START_SERVICE_FAILURE,
+ pClientToken ? pClientToken->GetSid() : NULL, // SID
+ 4, // 4 strings passed
+ 0, // 0 bytes of binary
+ (LPCTSTR *)Strings, // array of strings
+ NULL ); // no raw data
+
+ // clean up the event log handle
+ DeregisterEventSource(LogHandle);
+ }
+
+ return FALSE;
+}
+#endif // !_CHICAGO_
+
+#ifdef DCOM
+// the constant generic mapping structure
+GENERIC_MAPPING sGenericMapping = {
+ READ_CONTROL,
+ READ_CONTROL,
+ READ_CONTROL,
+ READ_CONTROL};
+
+//+-------------------------------------------------------------------------
+//
+// Function: CheckForAccess
+//
+// Synopsis: Checks whether the passed in token is allowed by the
+// passed in Security Descriptor.
+//
+// Arguments:
+//
+// Returns: HRESULT
+//
+// History: 29-Mar-96 GregJen Created
+//
+//--------------------------------------------------------------------------
+HRESULT CheckForAccess( CToken * pToken, const SECURITY_DESCRIPTOR * pSD )
+{
+ // if we have an empty SD, deny everyone
+ if ( !pSD ) return E_ACCESSDENIED;
+
+ //
+ // pToken is NULL during an unsecure activation, in which case we check
+ // if EVERYONE is granted access in the security descriptor.
+ //
+
+ if ( pToken )
+ {
+ HANDLE hToken = pToken->GetToken();
+ BOOL fAccess = FALSE;
+ BOOL fSuccess = FALSE;
+ DWORD dwGrantedAccess;
+ PRIVILEGE_SET sPrivilegeSet;
+ DWORD dwSetLen = sizeof( sPrivilegeSet );
+
+ sPrivilegeSet.PrivilegeCount = 1;
+ sPrivilegeSet.Control = 0;
+
+ fSuccess = AccessCheck( (PSECURITY_DESCRIPTOR) pSD,
+ hToken,
+ COM_RIGHTS_EXECUTE,
+ &sGenericMapping,
+ &sPrivilegeSet,
+ &dwSetLen,
+ &dwGrantedAccess,
+ &fAccess );
+
+ if ( fSuccess && fAccess )
+ {
+ return S_OK;
+ }
+
+ if ( !fSuccess )
+ {
+ CairoleDebugOut((DEB_ERROR, "Bad Security Descriptor 0x%08x, Access Check returned 0x%x\n", pSD, GetLastError() ));
+ }
+
+ return E_ACCESSDENIED;
+ }
+ else
+ {
+ BOOL bStatus;
+ BOOL bDaclPresent;
+ BOOL bDaclDefaulted;
+ DWORD Index;
+ HRESULT hr;
+ PACL pDacl;
+ PACCESS_ALLOWED_ACE pAllowAce;
+ SID SidEveryone = { SID_REVISION,
+ 1,
+ SECURITY_WORLD_SID_AUTHORITY,
+ 0 };
+
+ bStatus = GetSecurityDescriptorDacl(
+ (void *)pSD,
+ &bDaclPresent,
+ &pDacl,
+ &bDaclDefaulted );
+
+ if ( ! bStatus )
+ return E_ACCESSDENIED;
+
+ if ( ! pDacl )
+ return S_OK;
+
+ hr = E_ACCESSDENIED;
+
+ for ( Index = 0; Index < pDacl->AceCount; Index++ )
+ {
+ bStatus = GetAce( pDacl, Index, (void **) &pAllowAce );
+
+ if ( ! bStatus )
+ break;
+
+ if ( pAllowAce->Header.AceType != ACCESS_ALLOWED_ACE_TYPE )
+ continue;
+
+ if ( ! (pAllowAce->Mask & COM_RIGHTS_EXECUTE) )
+ continue;
+
+ if ( EqualSid( (PSID)(&pAllowAce->SidStart), &SidEveryone ) )
+ {
+ hr = S_OK;
+ break;
+ }
+ }
+
+ LocalFree( pDacl );
+
+ return hr;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassData::CkIfCallAllowed
+//
+// Synopsis: Checks the global key EnableDCOM and performs
+// different logic depending on its value. Then check the
+// ACL's on various registry keys. If this is a local call
+// from the ingteractive user and none of these keys are
+// present, then return success. This is to support legacy
+// situations.
+//
+// Arguments:
+//
+// Returns: HRESULT
+//
+// History: 30-Oct-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CClassData::CkIfCallAllowed( ACTIVATION_PARAMS * pActParams )
+{
+ HRESULT hr;
+ PSID psid;
+ DWORD err;
+ DWORD dwEventID;
+
+ // If the call is remote and EnableDCOM disallows remotes,
+ // then fail
+ if ( pActParams->RemoteActivation &&
+ gpClassCache->GetEnableDCOM() == REMOTEACCESSBY_NOBODY )
+ {
+ return E_ACCESSDENIED;
+ }
+
+ // Unsecure activations have no Token object.
+ psid = pActParams->pToken ? pActParams->pToken->GetSid() : NULL;
+
+#if DBG==1
+ WCHAR wszUser[MAX_PATH];
+ ULONG cchSize = MAX_PATH;
+
+ if ( ! pActParams->UnsecureActivation )
+ {
+ RpcImpersonateClient((RPC_BINDING_HANDLE)0);
+ GetUserName(wszUser, &cchSize);
+ RpcRevertToSelf();
+ }
+ else
+ {
+ lstrcpyW(wszUser, L"Anonymous");
+ }
+ CairoleDebugOut((DEB_TRACE, "rpcss: CkIfCallAllowed on %ws\n", wszUser));
+#endif // DBG
+
+ // Assume failure
+ hr = E_ACCESSDENIED;
+
+ // If there is a local LaunchPermission key, attempt to access it
+ if (_pSD)
+ {
+ dwEventID = EVENT_RPCSS_LAUNCH_ACCESS_DENIED;
+ hr = CheckForAccess( pActParams->pToken, _pSD );
+ }
+ else
+ {
+ dwEventID = EVENT_RPCSS_DEFAULT_LAUNCH_ACCESS_DENIED;
+ hr = CheckForAccess( pActParams->pToken, gpClassCache->GetDefaultLaunchSD() );
+ }
+
+ // report access denied to event logger
+ if ( FAILED( hr ) )
+ {
+#ifndef _CHICAGO_
+ // for this message, %1 is the clsid
+ HANDLE LogHandle;
+ LPTSTR Strings[1]; // array of message strings.
+ WCHAR wszClsid[GUIDSTR_MAX];
+
+ // Get the clsid
+ wStringFromGUID2(*(pActParams->Clsid), wszClsid, sizeof(wszClsid));
+ Strings[0] = wszClsid;
+
+ // Get the log handle, then report then event.
+ LogHandle = RegisterEventSource( NULL,
+ SCM_EVENT_SOURCE );
+
+ if ( LogHandle )
+ {
+ ReportEvent( LogHandle,
+ EVENTLOG_ERROR_TYPE,
+ 0, // event category
+ dwEventID,
+ psid, // SID
+ 1, // 1 strings passed
+ 0, // 0 bytes of binary
+ (LPCTSTR *)Strings, // array of strings
+ NULL ); // no raw data
+
+ // clean up the event log handle
+ DeregisterEventSource(LogHandle);
+ }
+#endif // _CHICAGO_
+ }
+ return hr;
+}
+#endif
+
+// NT 5.0
+/***
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::SkipListCompareClassIDsPlusSids
+//
+// Synopsis: Compares class ids plus user sid's.
+//
+//--------------------------------------------------------------------------
+int SkipListCompareClassIDsPlusSids(void * pkey1, void * pkey2)
+{
+ return((CClsidSid*)pkey1)->Compare(*(const CClsidSid*)pkey2);
+}
+***/
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::SkipListCompareClassIDs
+//
+// Synopsis: Compares class ids.
+//
+//--------------------------------------------------------------------------
+int SkipListCompareClassIDs(void * pkey1, void * pkey2)
+{
+ return((CClassID*)pkey1)->Compare(*(const CClassID*)pkey2);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::SkipListDeleteClassData
+//
+// Synopsis: Deletes class data for ~CSkipList
+//
+//--------------------------------------------------------------------------
+void
+SkipListDeleteClassData(void *pdata)
+{
+ ((CClassData*)pdata)->DeleteThis(); // BUGBUG: there may be other threads around.
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::CClassCacheList
+//
+// Synopsis: Creates a class cache for service.
+//
+// History: 21-Apr-93 Ricksa Created
+// 1-Nov-94 BillMo pass in an object responsible for
+// comparisions. Depends on base address
+// of DLL being same in all processes.
+//
+//--------------------------------------------------------------------------
+
+CClassCacheList::CClassCacheList(HRESULT &hr)
+ : CSkipList(
+// NT 5.0
+//(LPFNCOMPARE)(SkipListCompareClassIDsPlusSids),
+//OFFSETBETWEEN(CClassData, CClsidSid),
+ (LPFNCOMPARE)(SkipListCompareClassIDs),
+ (LPFNDELETE)(SkipListDeleteClassData),
+ OFFSETBETWEEN(CClassData, CClassID),
+ SKIPLIST_SHARED,
+ &_ccidMax, // NOTE! even though the base CSkipList is
+ // constructed first, we can pass in
+ // the key because it is a pointer (void*)
+ MAX_CLASS_ENTRIES,
+ hr),
+ _pDefaultLaunchSD( NULL ),
+ _ccidMax((BYTE)0xff) // In x86 Windows : in shared memory
+ // In NT : in private memory
+#ifdef DCOM
+ ,
+ _aSidHkey(sizeof(SSidHkey))
+#endif // DCOM
+ ,_slsSurrogate(wszSurrogateServerAlias,hr)
+{
+ hr = S_OK;
+
+ // Fetch the values of
+ // \\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLE.EnableDCOM
+ // \\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLE.PersonalClasses
+ // We only need to do this once unless the registry changes
+ ReadRemoteActivationKeys();
+
+#ifdef DCOM
+ // Create the event so we know when the registry changes
+ SECURITY_ATTRIBUTES secattr;
+ secattr.nLength = sizeof(secattr);
+ secattr.bInheritHandle = FALSE;
+ CWorldSecurityDescriptor secd;
+ secattr.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) secd;
+ _hRegEvent = CreateEvent(&secattr, FALSE, FALSE, L"RegEvent");
+ if (_hRegEvent)
+ {
+ // Set up the event to catch registry changes to HKEY_LOCAL_MACHINE
+ int err;
+
+ if ((err = RegNotifyChangeKeyValue(HKEY_LOCAL_MACHINE,
+ TRUE,
+ REG_NOTIFY_CHANGE_NAME |
+ REG_NOTIFY_CHANGE_ATTRIBUTES |
+ REG_NOTIFY_CHANGE_LAST_SET |
+ REG_NOTIFY_CHANGE_SECURITY,
+ _hRegEvent,
+ TRUE))
+ != ERROR_SUCCESS)
+ {
+ hr = HRESULT_FROM_WIN32(err);
+ }
+ }
+ else
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+#endif // DCOM
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::GetClassData
+//
+// Synopsis: Gets a CClassData *. Loads if necessary from registry.
+//
+// Arguments: [guidForClass] - guid that identifies the class needed
+// [ppccd] - a new CClassData object that can be used
+// to perform scm operations.
+// [fLeaveLocked] - if TRUE, then when routine returns
+// gClassCacheLock will still be acquired.
+// otherwise it will not be locked.
+//
+// Returns: S_OK
+// REGDB_E_CLASSNOTREG - Information for context not in DB
+//
+// Algorithm: Acquire mutex protecting class cache list.
+// Determine whether data needs to be loaded from registry.
+// If data does not need to be loaded, copy it to [pcd]
+// and return, releasing mutex.
+// Release mutex
+// If data needs to be loaded, load it from registry.
+// Reacquire mutex
+// Determine whether data still needs to be loaded.
+// If data still needs to be loaded, put in data just loaded.
+// Release mutex.
+//
+// History: 11-Nov-94 BillMo Created
+// 09-Jan-96 BruceMa Added per-user registry support
+//
+//--------------------------------------------------------------------------
+
+HRESULT CClassCacheList::GetClassData(
+ const GUID& guidForClass,
+ CClassData **ppccd,
+ BOOL CheckTreatAs,
+ BOOL CheckAutoConvert )
+{
+ HRESULT hr = S_OK;
+ LONG err;
+ CClassID ccid(guidForClass);
+ CClassData *pccdInCache;
+ CClassRegistryReader *pcrr = NULL;
+ BOOL fLocked;
+
+ *ppccd = NULL;
+
+ //
+ // claim mutex to see if we need to reload
+ //
+
+ //
+ // first: simply lookup
+ // later: lookup after having loaded
+ // reg info to see if we need to insert.
+ //
+
+ gClassCacheLock.WriteLock(); // simple mutex
+ fLocked = TRUE;
+
+ // First look for a cached common registration
+ pccdInCache = Search(ccid
+#ifdef NT50
+ , NULL
+#endif // NT50
+ );
+
+ // NT 5.0
+ // If no common, then look for a cached per-user registration
+ // if (pccdInCache == NULL && g_pcllClassCache->GetPersonalClasses())
+ // {
+ // pccdInCache = Search(ccid, pUserSid);
+ // }
+
+ if (pccdInCache != NULL)
+ {
+ (*ppccd = pccdInCache)->AddRef();
+ hr = S_OK;
+ goto cleanup_and_exit;
+ }
+
+ gClassCacheLock.WriteUnlock();
+ fLocked = FALSE;
+
+ //
+ // Read in fresh registry data.
+ // Create object to read the registry in the heap because
+ // it maybe too big for Chicago's stacks.
+ //
+
+ pcrr = new CClassRegistryReader;
+ if (pcrr == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto cleanup_and_exit;
+ }
+
+ //
+ // read the registry into the object
+ //
+ err = pcrr->ReadSingleClass(guidForClass, CheckTreatAs, CheckAutoConvert);
+ if (NotFoundError(err))
+ {
+ hr = REGDB_E_CLASSNOTREG;
+ goto cleanup_and_exit;
+ }
+
+ if (err != ERROR_SUCCESS)
+ {
+ hr = HRESULT_FROM_WIN32(err);
+ goto cleanup_and_exit;
+ }
+
+ // now search again
+
+ gClassCacheLock.WriteLock(); // simple mutex
+ fLocked = TRUE;
+
+ // First look for a cached common registration
+ pccdInCache = Search(ccid
+#ifdef NT50
+ , NULL
+#endif // NT50
+ );
+
+ // NT 5.0
+ // If no common, then look for a cached per-user registration
+ // if (pccdInCache == NULL && g_pcllClassCache->GetPersonalClasses())
+ // {
+ // pccdInCache = Search(ccid, pUserSid);
+ // }
+
+ if (pccdInCache != NULL)
+ {
+ (*ppccd = pccdInCache)->AddRef();
+ hr = S_OK;
+ goto cleanup_and_exit;
+ }
+ //
+ // create a new CClassData from registry info
+ // and insert
+ //
+ *ppccd = pcrr->NewClassData(hr
+#ifdef DCOM
+ // NT5.0 , pUserSid
+#endif DCOM
+ );
+ if (*ppccd == NULL || FAILED(hr) || Insert(*ppccd) == NULL) // the lock is still held
+ {
+ if (SUCCEEDED(hr))
+ hr = E_OUTOFMEMORY;
+ }
+
+cleanup_and_exit:
+ if (FAILED(hr))
+ {
+ if (*ppccd != NULL)
+ {
+ if (!fLocked)
+ {
+ gClassCacheLock.WriteLock();
+ fLocked = TRUE;
+ }
+ (*ppccd)->DeleteThis(); // this should always delete since the insertion failed.
+ *ppccd = NULL;
+ }
+ }
+
+ if ( pcrr )
+ {
+ delete pcrr; // deliberately here so lock is not acquired.
+ } // whilst closing registry
+
+ if ( fLocked )
+ gClassCacheLock.WriteUnlock();
+
+ return(hr);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::SetEndPoint
+//
+// Synopsis: Set the endpoint of a server
+//
+// Arguments: [clsid] - class id that is started
+// [pwszEndPoint] - end point for the server
+// [dwFlags] - type of service object
+//
+// Returns: HRESULT
+//
+// Algorithm: Search cache of services for the class. If there is
+// no such class we return an error otherwise we update
+// the cache with the endpoint to the server.
+//
+// History: 21-Apr-93 Ricksa Created
+//
+// Notes: This is called by object servers to notify the SCM
+// that the object server is active for a class.
+//
+//--------------------------------------------------------------------------
+HRESULT CClassCacheList::SetEndPoints(
+#ifndef _CHICAGO_
+ PHPROCESS phProcess,
+#endif
+ IFSECURITY(PSID psid)
+ WCHAR *pwszWinstaDesktop,
+ RegInput * pRegInput,
+ RegOutput * pRegOutput )
+{
+ HRESULT hr;
+ CClassData *apccd[8];
+ CClassData **ppccd;
+ CClassData *pccd;
+ RegInputEntry *preginent;
+ RegOutputEnt *pregoutent;
+ DWORD Entries;
+ DWORD n;
+
+ Entries = pRegInput->dwSize;
+ preginent = pRegInput->rginent;
+ pregoutent = pRegOutput->regoutent;
+
+ if ( Entries > 8 )
+ {
+ ppccd = (CClassData **) PrivMemAlloc( Entries * sizeof(CClassData *) );
+ if ( ! ppccd )
+ return E_OUTOFMEMORY;
+ }
+ else
+ ppccd = apccd;
+
+ memset( ppccd, 0, Entries * sizeof(CClassData *) );
+
+ //
+ // Keep mutex for duration of this routine since CClassData entries
+ // can be deleted in this routine and this messes with our stupid
+ // skip list.
+ //
+ gClassCacheLock.WriteLock();
+
+ //
+ // First loop, we add all of the registrations to the class
+ // table.
+ //
+ for ( n = 0; n < Entries; n++, pregoutent++, preginent++ )
+ {
+ hr = GetClassCache().GetClassData(
+ preginent->clsid,
+ &pccd,
+ FALSE,
+ FALSE );
+
+ if (pccd == NULL)
+ {
+ CClassID ccid(preginent->clsid);
+
+ // Reset the error.
+ hr = NOERROR;
+
+ // Create a class entry with no reqistry information
+ pccd = new CClassData(ccid,
+ NULL, // No AppID
+ NULL, // No local server
+ NULL, // No remote server
+ NULL, // No service
+ NULL, // No service parameters
+ NULL, // No RunAs domain
+ NULL, // No RunAs user
+ // NT 5.0 : SID NULL,
+ FALSE, // Cannot be activate at bits
+ FALSE, // Cannot be activate remote
+ FALSE, // No AllowRemoteActivation key present
+ FALSE, // Not 16 bits
+ hr);
+
+ if (pccd == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ else if (SUCCEEDED(hr) && (Insert(pccd) == NULL))
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ if (FAILED(hr))
+ {
+ if (pccd != NULL)
+ {
+ pccd->DeleteThis();
+ pccd = NULL;
+ }
+
+ break;
+ }
+ }
+
+ ppccd[n] = pccd;
+
+#ifndef _CHICAGO_
+ //
+ // Check that the caller is allowed to register for this CLSID.
+ //
+ if ( (pccd->_pwszRunAsUserName || pccd->_fHasService) )
+ {
+ PSID pRequiredSid = NULL;
+ WCHAR * pLocalService = NULL;
+ BOOL Status;
+
+ if ( pccd->_slocalsrv.Defined() )
+ {
+ pRequiredSid = pccd->_slocalsrv->GetRunAsSid();
+
+ if ( pccd->_fHasService )
+ pLocalService = pccd->_slocalsrv->pwszPath();
+ }
+
+ Status = CertifyServer( pccd->_pwszAppID,
+ pccd->_pwszRunAsDomainName,
+ pccd->_pwszRunAsUserName,
+ pLocalService,
+ pRequiredSid,
+ psid );
+
+ if ( ! Status )
+ {
+ hr = CO_E_WRONG_SERVER_IDENTITY;
+ break;
+ }
+ }
+#endif
+
+ pregoutent->dwReg = pccd->SetEndPoint(
+ IFSECURITY(psid)
+ pwszWinstaDesktop,
+#ifndef _CHICAGO_
+ phProcess,
+ preginent->oxid,
+ preginent->ipid,
+#else
+ preginent->pwszEndPoint,
+#endif
+ preginent->dwFlags);
+
+ if ( pregoutent->dwReg )
+ {
+ hr = S_OK;
+ pregoutent->dwAtStorage = pccd->HasActivateAtStorage();
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ break;
+ }
+ } // for
+
+ //
+ // If we encountered any errors then we remove any entries which were
+ // successfully added, release any references to class data classes and
+ // return an error.
+ //
+ if ( hr != S_OK )
+ {
+ preginent = pRegInput->rginent;
+ pregoutent = pRegOutput->regoutent;
+
+ for ( n = 0; n < Entries; n++, pregoutent++, preginent++ )
+ {
+ if ( ppccd[n] )
+ {
+ if ( pregoutent->dwReg )
+ {
+ CPortableRpcHandle rh( pregoutent->dwReg );
+ ppccd[n]->InvalidateHandle( rh );
+ }
+ ppccd[n]->Release();
+ }
+ }
+
+ memset( pRegOutput->regoutent,
+ 0,
+ pRegOutput->dwSize * sizeof(RegOutputEnt) );
+ }
+
+ //
+ // On success, we now signal all of the class table events and release
+ // our class data references.
+ //
+ if ( hr == S_OK )
+ {
+ for ( n = 0; n < Entries; n++ )
+ {
+ Win4Assert( ppccd[n] );
+
+ {
+ CPortableServerEvent se(ppccd[n]);
+
+ if (se.Open() == ERROR_SUCCESS)
+ SetEvent(se.GetHandle());
+
+ ppccd[n]->Release();
+ }
+ }
+ }
+
+ gClassCacheLock.WriteUnlock();
+
+ if ( hr == S_OK )
+ {
+ preginent = pRegInput->rginent;
+ pregoutent = pRegOutput->regoutent;
+
+ for ( n = 0; n < Entries; n++, pregoutent++, preginent++ )
+ ((CProcess *)phProcess)->AddClassReg( preginent->clsid, pregoutent->dwReg );
+ }
+
+ return hr;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::StopServer
+//
+// Synopsis: Set a local server object to stopped.
+//
+// Arguments: [clsid] - class id to mark as stopped
+// [dwReg] - registration id returned by SCM
+//
+// Algorithm: Search cache for class and mark class as stopped.
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+void CClassCacheList::StopServer(
+ REFCLSID clsid,
+ IFSECURITY(PSID psid)
+ DWORD dwReg)
+{
+ HRESULT hr;
+
+ // While we are reading lock out any updates
+ CScmLockForWrite scmlckwr(gClassCacheLock);
+
+ // Get the server for the object - we don't know whether the server was
+ // launched via a user's private registration or not, so we search
+ // both ways
+ CClassID ccid(clsid);
+
+ CClassData *pccd = Search(ccid);
+
+ // NT 5.0
+ // CClassData *pccd = Search(ccid, NULL);
+ // if (pccd == NULL)
+ // pccd = Search(ccid, psid);
+
+ // Ignore the error since the caller couldn't have registered
+ // with us in the first place.
+ if (pccd != NULL)
+ {
+ CPortableRpcHandle rh(dwReg);
+ pccd->AddRef();
+ pccd->StopServer(rh); // TRUE means the last registration
+ pccd->Release(); // delete will occur when last
+ // thread exits.
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::ReadRemoteActivationKeys
+//
+// Synopsis: Reads the registry named values
+//
+// "\HKEY_LOCAL_MACHINE\SYSTEM\Software\Microsoft\OLE.EnableDCOM"
+// "\HKEY_LOCAL_MACHINE\SYSTEM\Software\Microsoft\OLE.PersonalClasses"
+//
+// History: 25-Oct-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void CClassCacheList::ReadRemoteActivationKeys(void)
+{
+
+ DWORD err;
+ HKEY hOle;
+ DWORD dwType;
+ DWORD dwPolicy;
+ DWORD dwSize;
+ WCHAR wszYN[16];
+
+ // Set the default
+ // BUGBUG: When the named value EnableDCOM is created in
+ // the setup hives, then this default might need to be changed
+ _tagRAType = REMOTEACCESSBY_NOBODY;
+ _fPersonalClasses = FALSE;
+
+ // Read the EnableDCOM value (if present) from the registry
+ if ((err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, wszOleKey, NULL, KEY_READ,
+ &hOle)) == ERROR_SUCCESS)
+ {
+ // Initialize
+ dwSize = 16;
+
+ // "EnableDCOM"
+ if ((err = RegQueryValueEx(hOle, wszEnableDCOM,
+ NULL, &dwType, (BYTE *) wszYN, &dwSize))
+ == ERROR_SUCCESS)
+ {
+ if (dwType == REG_SZ && (wszYN[0] == L'y' || wszYN[0] == L'Y'))
+ {
+ _tagRAType = (EnableDCOM) REMOTEACCESSBY_KEY;
+ }
+ }
+
+ if ( _pDefaultLaunchSD )
+ {
+ ScmMemFree( _pDefaultLaunchSD );
+ _pDefaultLaunchSD = NULL;
+ }
+
+ GetRegistrySecDesc( hOle,
+ wszDefaultLaunchPermission,
+ &_pDefaultLaunchSD);
+
+ // "PersonalClasses"
+ // NT 5.0
+ /****
+ DWORD dwSize = 16;
+ if ((err = RegQueryValueEx(hOle, wszPersonalClasses,
+ NULL, &dwType, (BYTE *) &wszYN, &dwSize))
+ == ERROR_SUCCESS)
+ {
+ if (dwType == REG_SZ &&
+ (wszYN[0] == L'y' || wszYN[0] == L'Y'))
+ {
+ _fPersonalClasses = TRUE;
+ }
+ }
+ ***/
+
+ RegCloseKey(hOle);
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::Flush
+//
+// Synopsis: flushes the cache before process exit.
+//
+// History: 07-Apr-94 Rickhi Created
+//
+// Notes: We only want to spend time flushing the cache on the debug
+// build so that we can find any other potential memory leaks.
+//
+//--------------------------------------------------------------------------
+#if DBG==1 && !defined(_CHICAGO_)
+void CClassCacheList::Flush(void)
+{
+ CClassData *pccd;
+ CSkipListEnum sle;
+
+ // Loop getting any server handles and
+ while (pccd = (CClassData *) CSkipList::First(&sle))
+ {
+ // NT 5.0 void *pv = Remove((CClsidSid*)pccd);
+ void *pv = Remove((CClassID*)pccd);
+ Win4Assert(pv == pccd);
+ pccd->DeleteThis();
+ }
+}
+#endif
+
+// NT 5.0
+/*****
+#ifdef DCOM
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::GetHkey
+//
+// Synopsis: Given a PSID, return the associated HKEY
+//
+// Arguments: PSID
+//
+// Returns: HKEY or NULL
+//
+// History: 10-Jan-96 BruceMa Created
+//
+//--------------------------------------------------------------------------
+HKEY CClassCacheList::GetHkey(PSID pUserSid)
+{
+ int cSize = _aSidHkey.GetSize();
+ PSSidHkey pSidHkey;
+
+ for (int k = 0; k < cSize; k++)
+ {
+ pSidHkey = (PSSidHkey) _aSidHkey.GetAt(k);
+ if (RtlEqualSid(pUserSid, pSidHkey->pUserSid))
+ {
+ return pSidHkey->hKey;
+ }
+ }
+
+ return NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::SetHkey
+//
+// Synopsis: Given a PSID, store its associated HKEY
+//
+// Arguments: PSID
+// HKEY
+//
+// Returns: TRUE if success
+// FALSE if failure
+//
+// History: 10-Jan-96 BruceMa Created
+//
+//--------------------------------------------------------------------------
+BOOL CClassCacheList::SetHkey(PSID pUserSid, HKEY hKey)
+{
+ int cSize = _aSidHkey.GetSize();
+ SSidHkey sSidHkey;
+
+ sSidHkey.pUserSid = pUserSid;
+ sSidHkey.hKey = hKey;
+ return _aSidHkey.InsertAt(cSize, (void *) &sSidHkey, 1);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::GetHkeyPsid
+//
+// Synopsis: Given a PSID, get its standard psid
+//
+// Arguments: PSID
+//
+// Returns: PSID if successful
+// NULL otherwise
+//
+// History: 26-Jan-96 BruceMa Created
+//
+//--------------------------------------------------------------------------
+PSID CClassCacheList::GetHkeyPsid(PSID pUserSid)
+{
+ int cSize = _aSidHkey.GetSize();
+ PSSidHkey pSidHkey;
+
+ for (int k = 0; k < cSize; k++)
+ {
+ pSidHkey = (PSSidHkey) _aSidHkey.GetAt(k);
+ if (RtlEqualSid(pUserSid, pSidHkey->pUserSid))
+ {
+ return pSidHkey->pUserSid;
+ }
+ }
+
+ return NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::FlushSidHkey
+//
+// Synopsis: Flush the
+//
+// Arguments: PSID
+// HKEY
+//
+// Returns: S_OK
+// E_OUTOFMEMORY
+//
+// Note: This releases the user SID's.
+//
+// History: 10-Jan-96 BruceMa Created
+//
+//--------------------------------------------------------------------------
+void CClassCacheList::FlushSidHkey(void)
+{
+ int cSize = _aSidHkey.GetSize();
+ PSSidHkey pSidHkey;
+
+ // Release the user SID's
+ for (int k = 0; k < cSize; k++)
+ {
+ pSidHkey = (PSSidHkey) _aSidHkey.GetAt(k);
+ DeleteUserSid(pSidHkey->pUserSid);
+ }
+
+ // Flush the table
+ _aSidHkey.SetSize(0);
+}
+#endif
+***/
+
+#ifdef DCOM
+//
+// Called from CProcess::Rundown() in OR.
+//
+void SCMRemoveRegistration(
+ GUID Clsid,
+ PSID pSid,
+ DWORD Reg )
+{
+ gpClassCache->StopServer( Clsid,
+ pSid,
+ Reg );
+}
+
+HRESULT GetMachineName(
+ WCHAR * pwszPath,
+ WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH+1],
+ BOOL bDoDfsConversion )
+{
+ WCHAR * pwszServerName;
+ BYTE Buffer[sizeof(REMOTE_NAME_INFO)+MAX_PATH*sizeof(WCHAR)];
+ DWORD BufferSize = sizeof(Buffer);
+ WCHAR Drive[4];
+ DWORD Status;
+
+ //
+ // Extract the server name from the file's path name.
+ //
+ if ( pwszPath[0] != L'\\' || pwszPath[1] != L'\\' )
+ {
+ lstrcpynW( Drive, pwszPath, 3 );
+ Drive[3] = 0;
+
+ if ( GetDriveType( Drive ) != DRIVE_REMOTE )
+ return S_FALSE;
+
+ if ( RpcImpersonateClient((RPC_BINDING_HANDLE)0) != ERROR_SUCCESS )
+ return CO_E_SCM_RPC_FAILURE;
+
+ Status = ScmWNetGetUniversalName( pwszPath,
+ UNIVERSAL_NAME_INFO_LEVEL,
+ Buffer,
+ &BufferSize );
+
+ RpcRevertToSelf();
+
+ if ( Status != NO_ERROR )
+ {
+ return CO_E_BAD_PATH;
+ }
+
+ pwszPath = ((UNIVERSAL_NAME_INFO *)Buffer)->lpUniversalName;
+
+ if ( ! pwszPath || pwszPath[0] != L'\\' || pwszPath[1] != L'\\' )
+ {
+ // Must be a local path.
+ return S_FALSE;
+ }
+ }
+
+ WCHAR wszDfsPath[MAX_PATH];
+
+ if ( bDoDfsConversion )
+ {
+ WCHAR * pwszDfsPath;
+ DWORD DfsPathLen;
+
+ pwszDfsPath = wszDfsPath;
+ DfsPathLen = sizeof(wszDfsPath);
+
+ for (;;)
+ {
+ Status = DfsFsctl(
+ ghDfs,
+ FSCTL_DFS_GET_SERVER_NAME,
+ (PVOID) &pwszPath[1],
+ lstrlenW(&pwszPath[1]) * sizeof(WCHAR),
+ (PVOID) pwszDfsPath,
+ &DfsPathLen );
+
+ if ( Status == STATUS_BUFFER_OVERFLOW )
+ {
+ Win4Assert( pwszDfsPath == wszDfsPath );
+
+ pwszDfsPath = (WCHAR *) PrivMemAlloc( DfsPathLen );
+ if ( ! pwszDfsPath )
+ return E_OUTOFMEMORY;
+ continue;
+ }
+
+ break;
+ }
+
+ if ( Status == STATUS_SUCCESS )
+ pwszPath = pwszDfsPath;
+ else
+ bDoDfsConversion = FALSE;
+ }
+
+ // Skip the "\\".
+ pwszPath += 2;
+
+ pwszServerName = wszMachineName;
+
+ while ( *pwszPath != L'\\' )
+ *pwszServerName++ = *pwszPath++;
+ *pwszServerName = 0;
+
+ if ( bDoDfsConversion && (pwszPath != wszDfsPath) )
+ PrivMemFree( pwszPath );
+
+ return S_OK;
+}
+
+HRESULT GetPathForServer(
+ WCHAR * pwszPath,
+ WCHAR wszPathForServer[MAX_PATH+1],
+ WCHAR ** ppwszPathForServer )
+{
+ BYTE Buffer[sizeof(REMOTE_NAME_INFO)+MAX_PATH*sizeof(WCHAR)];
+ WCHAR Drive[4];
+ DWORD BufferSize = sizeof(Buffer);
+ DWORD PathLength;
+ DWORD Status;
+
+ *ppwszPathForServer = 0;
+
+ if ( pwszPath &&
+ (lstrlenW(pwszPath) >= 3) &&
+ (pwszPath[1] == L':') && (pwszPath[2] == L'\\') )
+ {
+ lstrcpynW( Drive, pwszPath, 3 );
+ Drive[3] = 0;
+
+ switch ( GetDriveType( Drive ) )
+ {
+ case 0 : // Drive type can not be determined
+ case 1 : // The root directory does not exist
+ case DRIVE_CDROM :
+ case DRIVE_RAMDISK :
+ case DRIVE_REMOVABLE :
+ //
+ // We can't convert these to file names that the server will be
+ // able to access.
+ //
+ return CO_E_BAD_PATH;
+
+ case DRIVE_FIXED :
+ wszPathForServer[0] = wszPathForServer[1] = L'\\';
+ lstrcpyW( &wszPathForServer[2], SCMMachineName );
+ PathLength = lstrlenW( wszPathForServer );
+ wszPathForServer[PathLength] = L'\\';
+ wszPathForServer[PathLength+1] = pwszPath[0];
+ wszPathForServer[PathLength+2] = L'$';
+ wszPathForServer[PathLength+3] = L'\\';
+ lstrcpyW( &wszPathForServer[PathLength+4], &pwszPath[3] );
+ *ppwszPathForServer = wszPathForServer;
+ break;
+
+ case DRIVE_REMOTE :
+ if ( RpcImpersonateClient((RPC_BINDING_HANDLE)0) != ERROR_SUCCESS )
+ return CO_E_SCM_RPC_FAILURE;
+
+ Status = ScmWNetGetUniversalName( pwszPath,
+ UNIVERSAL_NAME_INFO_LEVEL,
+ Buffer,
+ &BufferSize );
+
+ RpcRevertToSelf();
+
+ if ( Status != NO_ERROR )
+ {
+ return CO_E_BAD_PATH;
+ }
+
+ Win4Assert( ((UNIVERSAL_NAME_INFO *)Buffer)->lpUniversalName );
+
+ lstrcpyW( wszPathForServer, ((UNIVERSAL_NAME_INFO *)Buffer)->lpUniversalName );
+ *ppwszPathForServer = wszPathForServer;
+
+ // BUGBUG : We're probably screwed on Banyan Vines networks.
+ Win4Assert( wszPathForServer[0] == L'\\' &&
+ wszPathForServer[1] == L'\\' );
+ break;
+ }
+ }
+ else
+ {
+ *ppwszPathForServer = pwszPath;
+ }
+
+ return S_OK;
+}
+#endif // DCOM
+
+void CheckLocalCall( handle_t hRpc )
+{
+#ifndef _CHICAGO_
+ UINT Type;
+
+ if ( (I_RpcBindingInqTransportType( hRpc, &Type) != RPC_S_OK) ||
+ ((Type != TRANSPORT_TYPE_LPC) && (Type != TRANSPORT_TYPE_WMSG)) )
+ RpcRaiseException( ERROR_ACCESS_DENIED );
+#endif
+
+ //
+ // Null method on Chicago unless we support incomming remote activation
+ // calls some day.
+ //
+}
+
+#ifndef _CHICAGO_
+BOOL
+CertifyServer( WCHAR *pwszAppId,
+ WCHAR *pwszRunAsDomainName,
+ WCHAR *pwszRunAsUserName,
+ WCHAR *pwszLocalService,
+ PSID pExpectedSid,
+ PSID pServerSid )
+{
+ PSID pRequiredSid = NULL;
+ HANDLE hToken = 0;
+ BOOL CloseToken = FALSE;
+ BOOL Status;
+
+ if ( pwszLocalService )
+ {
+ SERVICE_STATUS ServiceStatus;
+ SC_HANDLE hService;
+
+ hService = OpenService( hServiceController,
+ pwszLocalService,
+ GENERIC_READ );
+
+ if ( ! hService )
+ return FALSE;
+
+ Status = QueryServiceStatus( hService, &ServiceStatus );
+
+ if ( Status )
+ {
+ if ( (ServiceStatus.dwCurrentState == SERVICE_STOPPED) ||
+ (ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING) )
+ Status = FALSE;
+ }
+
+ CloseServiceHandle(hService);
+
+ return Status;
+ }
+
+ if ( ! pExpectedSid )
+ {
+ if ( lstrcmpiW( pwszRunAsUserName, L"Interactive User" ) == 0 )
+ hToken = GetShellProcessToken();
+ else
+ {
+ hToken = GetRunAsToken( pwszAppId,
+ pwszRunAsDomainName,
+ pwszRunAsUserName );
+ CloseToken = TRUE;
+ }
+
+ if ( hToken )
+ pExpectedSid = GetUserSid(hToken);
+ }
+
+ Status = pExpectedSid && RtlEqualSid( pServerSid, pExpectedSid );
+
+ if ( hToken && pExpectedSid )
+ DeleteUserSid( pExpectedSid );
+
+ if ( hToken && CloseToken )
+ NtClose( hToken );
+
+ return Status;
+}
+#endif
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::FindCompatibleSurrogate
+//
+//
+// Synopsis: Iterate through the CClassCacheList and to find
+// a surrogate process that has the requested appid and
+// security id.
+//
+// Arguments: psid (in) -- the desired security id
+// pwszAppID (in) -- the appid we're looking for
+// rh (in out) -- if we find an compatible surrogate process,
+// we'll set this to that surrogate's binding handle.
+//
+// Returns: TRUE
+// FALSE
+//
+// History: 21-Jun-96 t-adame created
+//
+//--------------------------------------------------------------------------
+BOOL CClassCacheList::FindCompatibleSurrogate(IFSECURITY(PSID psid)
+ CClassData** ppccdSrgt,
+ WCHAR* pwszWinstaDesktop,
+ WCHAR* pwszAppID,
+ CPortableRpcHandle &rh)
+{
+ BOOL fSuccess = FALSE;
+ CSkipListEnum psle = NULL;
+ CClassData* pCurrent;
+
+ Win4Assert(pwszAppID);
+
+ gClassCacheLock.WriteLock();
+
+ // iterate through the list
+ pCurrent = (CClassData*)First(&psle);
+
+ while(pCurrent)
+ {
+ CSrvRegList* psrvlist = NULL;
+ if(psrvlist = pCurrent->_pssrvreg)
+ {
+ // for each ClassCache entry, see if its AppID is
+ // the same as the one we're looking for, then
+ // check its server registration list for a surrogate
+ // with the appropriate security identity
+
+ if(pCurrent->_pwszAppID &&
+ (lstrcmpiW(pwszAppID,pCurrent->_pwszAppID) == 0) &&
+ psrvlist->FindCompatibleSurrogate(
+ IFSECURITY(psid)
+ pwszWinstaDesktop,
+ rh))
+ {
+ *ppccdSrgt = pCurrent;
+ fSuccess = TRUE;
+ break;
+ }
+ }
+
+ pCurrent = (CClassData*) Next(&psle);
+ }
+
+ gClassCacheLock.WriteUnlock();
+
+ return fSuccess;
+}
diff --git a/private/ole32/dcomss/olescm/cls.hxx b/private/ole32/dcomss/olescm/cls.hxx
new file mode 100644
index 000000000..293f9e633
--- /dev/null
+++ b/private/ole32/dcomss/olescm/cls.hxx
@@ -0,0 +1,858 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: cls.hxx
+//
+// Contents: Classes for cache of service information
+//
+// Classes: CClassData
+// CClassCacheList
+//
+// Functions:
+//
+// History: 21-Apr-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+// 17-May-94 BruceMa Fix scm event leak
+// 20-Oct-94 BillMo Use CSkipList instead of macros
+// 25-Oct-95 BruceMa Add Service and remote access support
+// 10-Jan-96 BruceMa Added support for per-user registry
+// 20-May-96 t-AdamE Added dll surrogate for inproc servers
+//
+//--------------------------------------------------------------------------
+
+#ifdef _CHICAGO_
+#include "chicago\cls.hxx"
+#else
+
+#ifndef __CLS_HXX__
+#define __CLS_HXX__
+
+#ifdef DCOM
+#include "or.hxx"
+#endif
+
+#include <iface.h>
+#ifdef DCOM
+#include "obase.h"
+#else
+typedef void ORPCTHIS,ORPCTHAT, LOCALTHIS;
+#endif
+#include <clskey.hxx>
+#include "olecom.h"
+#include "clsdata.hxx"
+#include "srvreg.hxx"
+#include "scmlock.hxx"
+#include <skiplist.hxx>
+
+//
+// Milliseconds to wait for a server to register its class
+// after being started.
+//
+#ifndef DBG
+#define MAX_CLASS_START_WAIT 30000
+#else
+#define MAX_CLASS_START_WAIT 60000
+#endif
+
+typedef enum
+{
+#ifndef _CHICAGO_
+ GETCLASSOBJECTEX,
+ CREATEINSTANCEEX,
+ GETPERSISTENTEX
+#else
+ GETCLASSOBJECT,
+ GETPERSISTENTOBJ,
+ CREATEPERSISTENTOBJ
+#endif
+} ScmMessageType;
+
+typedef struct _ACTIVATION_PARAMS
+{
+ handle_t hRpc;
+ PVOID ProcessSignature;
+ CProcess * pProcess;
+ CToken * pToken;
+ COAUTHINFO * pAuthInfo;
+ BOOL UnsecureActivation;
+ BOOL DynamicSecurity;
+
+ ScmMessageType MsgType;
+ const GUID * Clsid;
+ WCHAR * pwszServer;
+ WCHAR * pwszWinstaDesktop;
+ DWORD ClsContext;
+
+#ifdef DCOM
+ ORPCTHIS * ORPCthis;
+ LOCALTHIS * Localthis;
+ ORPCTHAT * ORPCthat;
+
+ BOOL RemoteActivation;
+#endif
+
+ DWORD Interfaces;
+ IID * pIIDs;
+
+ DWORD Mode;
+ BOOL FileWasOpened;
+ WCHAR * pwszPath;
+ MInterfacePointer * pIFDStorage;
+
+ MInterfacePointer * pIFDROT;
+
+#ifdef DCOM
+ long Apartment;
+ OXID * pOxidServer;
+ DUALSTRINGARRAY ** ppServerORBindings;
+ OXID_INFO * pOxidInfo;
+ MID * pLocalMidOfRemote;
+
+ USHORT ProtseqId;
+#endif
+
+ BOOL FoundInROT;
+ MInterfacePointer **ppIFD;
+ HRESULT * pResults;
+
+#ifdef _CHICAGO_
+ const GUID * pGuidThreadId;
+ DWORD TIDCaller;
+ DWORD * pTIDCallee;
+#endif
+} ACTIVATION_PARAMS, *PACTIVATION_PARAMS;
+
+typedef struct tagSidHkey
+{
+ PSID pUserSid;
+ HKEY hKey;
+} SSidHkey, *PSSidHkey;
+
+HRESULT GetMachineName(
+ WCHAR * pwszPath,
+ WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH+1],
+ BOOL bDoDfsConversion );
+
+HRESULT GetPathForServer(
+ WCHAR * pwszPath,
+ WCHAR wszPathForServer[MAX_PATH+1],
+ WCHAR ** ppwszPathForServer );
+
+HRESULT Activation( PACTIVATION_PARAMS pActParams );
+#ifdef _CHICAGO_
+HRESULT SSActivation( PACTIVATION_PARAMS pActParams );
+#endif // _CHICAGO_
+
+HRESULT ResolveORInfo(
+ PACTIVATION_PARAMS pActParams,
+ BOOL ActivatedRemote );
+
+BOOL RetryRpc(
+ int& cRetries,
+ error_status_t rpcstat,
+ HRESULT& hr );
+
+void CheckLocalCall( handle_t hRpc );
+
+#ifndef _CHICAGO_
+BOOL
+CertifyServer(
+ WCHAR *pwszAppId,
+ WCHAR *pwszRunAsDomainName,
+ WCHAR *pwszRunAsUserName,
+ WCHAR *pwszLocalService,
+ PSID pExpectedSid,
+ PSID pServerSid );
+#endif
+
+// NT 5.0
+/*******
+#ifdef DCOM
+//+-------------------------------------------------------------------------
+//
+// Class: CClsidSid
+//
+// Purpose: Wraps CClassID and a user SID to be used as the <CBase> class
+// for the <CEntry> class used in a skiplist
+//
+// Interface:
+//
+// History: 26-Jan-96 BruceMa Created
+//
+// Notes: cf. com\inc\skiplist.?xx
+//
+//--------------------------------------------------------------------------
+class CClsidSid
+{
+public:
+ CClsidSid(const CClassID& guidForClass, PSID psid);
+ int Compare(const CClsidSid& clsidSid);
+ PSID GetPsid(void);
+
+protected:
+
+ CClassID _ccid;
+ PSID _psid;
+
+};
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClsidSid::CClsidSid
+//
+// Synopsis: Constructor
+//
+// Arguments: [guidForClass] - class id key
+// [psid] - sid of user whose registry this entry
+// derived from
+//
+// Returns:
+//
+// History: 26-Jan-96 BruceMa Created
+//
+//--------------------------------------------------------------------------
+inline CClsidSid::CClsidSid(const CClassID& guidForClass, PSID psid) :
+ _ccid(guidForClass),
+ _psid(psid)
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClsidSid::Compare
+//
+// Synopsis: Compares clsid's and sid's
+//
+// Arguments: [guidForClass] - class id key
+// [psid] - user sid key
+//
+// Returns:
+//
+// History: 26-Jan-96 BruceMa Created
+//
+//--------------------------------------------------------------------------
+inline int CClsidSid::Compare(const CClsidSid& clsidSid)
+{
+ int iCmp = _ccid.Compare(clsidSid._ccid);
+
+ if (iCmp != 0)
+ {
+ return iCmp;
+ }
+ if (_psid < clsidSid._psid)
+ {
+ return -1;
+ }
+ else if (_psid == clsidSid._psid)
+ {
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClsidSid::GetPsid
+//
+// Synopsis: Fetches _psid
+//
+// Arguments: -
+//
+// Returns: PSID
+//
+// History: 26-Jan-96 BruceMa Created
+//
+//--------------------------------------------------------------------------
+inline PSID CClsidSid::GetPsid(void)
+{
+ return _psid;
+}
+#endif // DCOM
+***/
+
+//+-------------------------------------------------------------------------
+//
+// Class: CClassData (ccd)
+//
+// Purpose: Data for class.
+//
+// Interface:
+//
+// History: 21-Apr-93 Ricksa Created
+// 26-Jan-96 BruceMa Add per-user registry support
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// NT 5.0 class CClassData : public CClsidSid, public CScmAlloc
+class CClassData : public CClassID, public CScmAlloc
+{
+ //
+ // These classes encapsulate the difference in event usage on
+ // x86 Windows and NT.
+ //
+
+ friend class CPortableServerEvent;
+ friend class CPortableServerLock;
+ friend class CClassCacheList;
+
+public:
+ // Create a cache object
+ CClassData(
+ const CClassID& guidForClass,
+ WCHAR *pwszAppID,
+ const WCHAR *pwszLocalSrv,
+ WCHAR *pwszRemoteServerName,
+ BOOL fHasService,
+ WCHAR *pwszServiceArgs,
+ WCHAR *pwszRunAsUserName,
+ WCHAR *pwszRunAsDomainName,
+#ifdef DCOM
+ // NT 5.0 PSID pUserSid,
+#endif // DCOM
+ const BOOL fActivateAtStorage,
+ const BOOL fRemoteServerName,
+ const SECURITY_DESCRIPTOR * pSD,
+ const BOOL f16Bit,
+ HRESULT &hr);
+
+ CClassData( const CClassID& guidForClass, HRESULT &hr );
+
+ VOID AddRef();
+ VOID Release();
+ VOID DeleteThis();
+
+ BOOL HasActivateAtStorage();
+ BOOL HasRemoteServerName();
+ BOOL Debug();
+
+ WCHAR * GetRemoteServerName();
+ HRESULT GetInProcServerInfo(WCHAR** ppwszSurrogateCmdLine);
+
+ BOOL ActivateAtStorage(
+ HRESULT *phr,
+ ACTIVATION_PARAMS * pActParams );
+
+ BOOL ActivateRemote(
+ HRESULT *phr,
+ ACTIVATION_PARAMS * pActParams );
+
+ HRESULT GetSurrogateCmdLine(WCHAR* wszSurrogatePath,
+ WCHAR** ppwszCmdLine);
+
+ // Get class server information
+ HRESULT GetServer(
+ ACTIVATION_PARAMS * pActParams,
+ CPortableRpcHandle & rh,
+ BOOL& StartedServer,
+ BOOL& ActivatedRemote,
+ BOOL& fSurrogate);
+
+ // Any rpc registrations ?
+ BOOL InUse();
+
+ // Mark a class as registered by a server
+ DWORD SetEndPoint(
+ IFSECURITY(PSID psid)
+ WCHAR *pwszWinstaDesktop,
+#ifdef DCOM
+ PHPROCESS phProcess,
+ OXID oxid,
+ IPID ipid,
+#else
+ WCHAR *pwszEndPoint,
+#endif
+ DWORD dwFlags);
+
+ // Mark a class as stopped by its object server.
+ // TRUE if last was just stopped
+ BOOL StopServer(CPortableRpcHandle &rh);
+
+ // Verify whether a handle is still in _pssrvreg.
+ BOOL VerifyHandle (const CPortableRpcHandle &rh);
+
+
+ BOOL Defined (void);
+
+ VOID InvalidateHandle(CPortableRpcHandle &rh);
+
+ void GetAnonymousHandle(
+ CPortableRpcHandle &rh,
+ handle_t * phRpcAnonymous );
+
+#ifndef _CHICAGO_
+ void DecHandleCount(CPortableRpcHandle &rh);
+#endif
+
+ void SetActivateAtStorage();
+
+ ~CClassData(void);
+
+private:
+
+ HRESULT CkIfCallAllowed( ACTIVATION_PARAMS * pActParams );
+
+ BOOL FindCompatibleSurrogate(IFSECURITY(PSID psid)
+ WCHAR* pwszWinstaDesktop,
+ CPortableRpcHandle &rh);
+
+ CSafeLocalServer _slocalsrv;
+
+ WCHAR * _pwszRemoteServer;
+
+ WCHAR * _pwszSurrogateCmdLine;
+
+ WCHAR * _pwszAppID;
+
+ const SECURITY_DESCRIPTOR * _pSD;
+
+ BOOL _fHasService;
+ WCHAR *_pwszServiceArgs;
+
+ WCHAR *_pwszRunAsUserName;
+ WCHAR *_pwszRunAsDomainName;
+
+ ULONG _fActivateAtStorage:1;
+ ULONG _fRemoteServerName:1;
+ ULONG _fLocalServer16:1;
+
+#ifndef _CHICAGO_
+ HANDLE _hClassStart;
+
+ // In x86 Windows, the guid of the class is used for
+ // the name of the mutex and event.
+
+#endif
+
+ CSrvRegList * _pssrvreg; // BUGBUG: this should be made into a
+ // contained object.
+
+ //
+ // Reference counting note:
+ //
+ // The reference count indicates the number of threads that currently
+ // have a reference to this CClassData object. When the thread (ref)
+ // count goes to zero, then the CClassData object will be deleted from
+ // memory if and only if there are no registered binding handles in
+ // CSrvRegList.
+ //
+
+ ULONG _ulRefs;
+};
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassData::~CClassData
+//
+// Synopsis: Clean up object
+//
+// History: 04-Jan-94 Ricksa Created
+// 10-Nov-94 BillMo Added check for fIndirect which
+// prevents the temporary copy of CClassData
+// used to process a scm message from closing
+// the event handle or deleting the rpc
+// registrations.
+// 10-Dec-94 BillMo Changed to ref counting model
+//
+//--------------------------------------------------------------------------
+inline CClassData::~CClassData(void)
+{
+#ifndef _CHICAGO_
+ if (_hClassStart != NULL)
+ CloseHandle(_hClassStart);
+#endif
+
+ if (_pwszServiceArgs)
+ ScmMemFree(_pwszServiceArgs);
+ if ( _pwszRemoteServer )
+ ScmMemFree( _pwszRemoteServer );
+ if (_pwszRunAsUserName)
+ ScmMemFree(_pwszRunAsUserName);
+ if (_pwszRunAsDomainName)
+ ScmMemFree(_pwszRunAsDomainName);
+ if ( _pwszAppID )
+ ScmMemFree( _pwszAppID );
+ if ( _pwszSurrogateCmdLine )
+ ScmMemFree( _pwszSurrogateCmdLine );
+
+ if ( _pSD )
+ ScmMemFree( (void *)_pSD );
+
+ if ( _pssrvreg )
+ delete _pssrvreg;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassData::AddRef
+//
+// Synopsis: Increment reference count
+//
+// History: 14-Dec-94 BillMo Created
+//
+// Notes: Assumes mutual exclusion from Release
+//
+//--------------------------------------------------------------------------
+inline VOID CClassData::AddRef(VOID)
+{
+ _ulRefs++;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassData::DeleteThis
+//
+// Synopsis: Delete this object
+//
+// History: 14-Dec-94 BillMo Created
+//
+// Notes: Function used so C++ browser database works for dtor.
+//
+//--------------------------------------------------------------------------
+inline VOID CClassData::DeleteThis(VOID)
+{
+ delete this;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassData::HasActivateAtStorage
+//
+// Synopsis: Whether this service is activated at bits
+//
+// Returns: TRUE - yes, at bits
+// FALSE - no, not at bits
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CClassData::HasActivateAtStorage(void)
+{
+ return _fActivateAtStorage;
+}
+
+inline BOOL CClassData::HasRemoteServerName(void)
+{
+ return _fRemoteServerName;
+}
+
+inline void CClassData::SetActivateAtStorage()
+{
+ _fActivateAtStorage = TRUE;
+}
+
+inline BOOL CClassData::FindCompatibleSurrogate(IFSECURITY(PSID psid)
+ WCHAR* pwszWinstaDesktop,
+ CPortableRpcHandle &rh)
+{
+ return _pssrvreg->FindCompatibleSurrogate(IFSECURITY(psid) pwszWinstaDesktop, rh);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassData::InUse
+//
+// Synopsis: RPC handles (registrations exist) ?
+//
+// Returns: TRUE - there is supposedly an active server
+//
+// History: 04-Jan-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+inline BOOL CClassData::InUse()
+{
+ return _pssrvreg->InUse();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassData::SetEndPoint
+//
+// Synopsis: Set endpoint for a service
+//
+// Arguments: [pwszEndPoint] - RPC endpoint string
+// [dwFlags] - type of server (multiple or single use)
+//
+// Returns: 0 - Error occurred
+// ~0 - registration id for class
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+inline DWORD CClassData::SetEndPoint(
+ IFSECURITY(PSID psid)
+ WCHAR *pwszWinstaDesktop,
+#ifdef DCOM
+ PHPROCESS phProcess,
+ OXID oxid,
+ IPID ipid,
+#else
+ WCHAR *pwszEndPoint,
+#endif
+ DWORD dwFlags)
+{
+ // Add RPC end point to list of end points
+ DWORD dwReg = _pssrvreg->Insert(
+ IFSECURITY(psid)
+ pwszWinstaDesktop,
+#ifdef DCOM
+ phProcess,
+ oxid,
+ ipid,
+#else
+ pwszEndPoint,
+#endif
+ dwFlags);
+
+ return dwReg;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassData::StopServer
+//
+// Synopsis: Mark server as stopped in our list
+//
+// Arguments: [hRpc] - handle that identifies server for the class
+//
+// Returns: TRUE if no registrations left.
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CClassData::StopServer(CPortableRpcHandle &rh)
+{
+ return rh.DeleteFromSrvRegList(_pssrvreg);
+}
+
+typedef enum tagENABLEDCOM
+{
+ REMOTEACCESSBY_NOBODY = 0,
+ REMOTEACCESSBY_KEY = 1
+} EnableDCOM;
+
+//+-------------------------------------------------------------------------
+//
+// Class: CClassCacheList (ccl)
+//
+// Purpose: Key by class for searching for class information.
+//
+// Interface: Add - Creates a new entry in the list
+// GetServer - Removes an entry from the list
+//
+// History: 21-Apr-93 Ricksa Created
+//
+// Notes: See skiplist.hxx for details of CSkipList
+//
+//--------------------------------------------------------------------------
+
+class CClassCacheList : public CSkipList, public CScmAlloc
+{
+public:
+ // Creates an empty cache of class data.
+ CClassCacheList(HRESULT &hr);
+
+ // Default destructor for the class is enough
+ // as it will clean up any remaing class entries.
+
+ // Adds class information to the cache
+ CClassData * Add(
+ const GUID& guidForClass,
+ const WCHAR *pwszLocalSrv,
+ const BOOL fActivateAtStorage,
+ const BOOL f16Bit,
+ CClassData *pccdOrig,
+ HRESULT &hr);
+
+ // Gets cached class information
+ HRESULT GetClassData(
+ const GUID& guidForClass,
+ CClassData **ppccd,
+ BOOL CheckTreatAs,
+ BOOL CheckAutoConvert );
+
+ HRESULT SetEndPoints(
+#ifndef _CHICAGO_
+ PHPROCESS phProcess,
+#endif
+ IFSECURITY(PSID psid)
+ WCHAR *pwszWinstaDesktop,
+ RegInput * pRegInput,
+ RegOutput * pRegOutput );
+
+ void StopServer(
+ REFCLSID rclsid,
+ IFSECURITY(PSID psid)
+ DWORD dwReg);
+
+#if DBG==1
+ void Flush(void);
+#endif
+
+ EnableDCOM GetEnableDCOM(void);
+
+ SECURITY_DESCRIPTOR * GetDefaultLaunchSD(void);
+
+ BOOL GetPersonalClasses(void);
+
+ void ReadRemoteActivationKeys(void);
+
+ // NT 5.0
+ // HKEY GetHkey(PSID pUserSid);
+ // BOOL SetHkey(PSID pUserSid, HKEY hKey);
+ // PSID GetHkeyPsid(PSID pUserSid);
+ // void FlushSidHkey(void);
+ BOOL FindCompatibleSurrogate(IFSECURITY(PSID psid)
+ CClassData** ppccdSrgt,
+ WCHAR* pwszWinstaDesktop,
+ WCHAR* pwszAppID,
+ CPortableRpcHandle &rh);
+
+ CSafeLocalServer* GetSurrogateLocalServer();
+
+private:
+
+ // NT 5.0
+ // CClassData * Search(CClassID& ccid, PSID pUserSid);
+
+ // Searches class cache for data
+ CClassData * Search(CClassID& ccid);
+
+ CClassID _ccidMax;
+
+ EnableDCOM _tagRAType;
+
+ BOOL _fPersonalClasses;
+
+ SECURITY_DESCRIPTOR * _pDefaultLaunchSD;
+
+#ifdef DCOM
+ HANDLE _hRegEvent;
+
+ CScmArrayFValue _aSidHkey;
+#endif // DCOM
+
+ CSafeLocalServer _slsSurrogate;
+
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::Search
+//
+// Synopsis: Search service cache by class key
+//
+// Arguments: [cid] - class key
+//
+// Returns: pointer to the service object or NULL
+//
+// History: 21-Apr-93 Ricksa Created
+// 26-Jan-96 BruceMa Add per-user registry support
+//
+//--------------------------------------------------------------------------
+// NT 5.0
+/***
+inline CClassData *CClassCacheList::Search(CClassID& ccid, PSID pUserSid)
+{
+ CClsidSid clsidSid(ccid, pUserSid);
+
+ return (CClassData *) CSkipList::Search(&clsidSid);
+}
+***/
+inline CClassData *CClassCacheList::Search(CClassID& ccid)
+{
+ return (CClassData *) CSkipList::Search(&ccid);
+}
+
+#ifdef DCOM
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::GetEnableDCOM
+//
+// Synopsis: Return the EnableDCOM value
+//
+// Arguments: -
+//
+// History: 26-Oct-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+inline EnableDCOM CClassCacheList::GetEnableDCOM(void)
+{
+ return _tagRAType;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::GetDefaultLaunchSD
+//
+// Synopsis: Return the DefaultLaunchPermission value
+//
+// Arguments: -
+//
+// History: 26-Oct-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+inline SECURITY_DESCRIPTOR * CClassCacheList::GetDefaultLaunchSD(void)
+{
+ return _pDefaultLaunchSD;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::GetPersonalClasses
+//
+// Synopsis: Return the PersonalClasses value
+//
+// Arguments: -
+//
+// History: 09-Jan-96 BruceMa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CClassCacheList::GetPersonalClasses(void)
+{
+ // NT 5.0
+ return FALSE; // _fPersonalClasses;
+}
+#endif // DCOM
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassCacheList::GetSurrogateLocalServer
+//
+// Synopsis: Return a pointer to a CSafeLocalServer that can be used
+// for synchronizing access to surrogate servers
+//
+//--------------------------------------------------------------------------
+inline CSafeLocalServer* CClassCacheList::GetSurrogateLocalServer()
+{
+ return &_slsSurrogate;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClassData::VerifyHandle
+//
+// Synopsis: Whether this is still a valid handle to an object server.
+//
+// Returns: TRUE - yes, this is still a valid handle to an object server
+// FALSE - no, this is no longer a valid handle to an object server
+//
+// History: 11-May-94 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CClassData::VerifyHandle(const CPortableRpcHandle &rh)
+{
+ return(rh.VerifyHandle(_pssrvreg));
+}
+
+#endif // __CLS_HXX__
+
+#endif
diff --git a/private/ole32/dcomss/olescm/clsdata.cxx b/private/ole32/dcomss/olescm/clsdata.cxx
new file mode 100644
index 000000000..21f43f08e
--- /dev/null
+++ b/private/ole32/dcomss/olescm/clsdata.cxx
@@ -0,0 +1,1582 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: clsdata.cxx
+//
+// Contents: implements methods of classes defined in clsdata.hxx
+//
+// Functions: CLocalServer::StartServer
+// CLocalServer::SetEndPoint
+//
+// History: 21-Apr-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+// 31-Mar-94 AndyH Start EXEs in client's security Context
+// 10-Jun-94 BruceMa Fix to debug SCM as non-Service
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <scm.hxx>
+#include <scmrotif.hxx>
+#include <sem.hxx>
+#include "port.hxx"
+#include "cls.hxx"
+#include <clsdata.hxx>
+#include "access.hxx"
+#include <ntlsa.h>
+
+//
+// Private prototypes
+//
+
+BOOL
+CreateAndSetProcessToken (
+ PPROCESS_INFORMATION ProcessInformation,
+ HANDLE Token,
+ PSID psidUserSid );
+
+VOID
+DeleteUserSid (
+ PSID Sid );
+
+PSID
+GetUserSid (
+ HANDLE hUserToken );
+
+
+PSECURITY_DESCRIPTOR
+CreateUserThreadSD (
+ PSID psidUserSid,
+ PSID psidSCMSid );
+
+BOOL
+IsInteractive(
+ HANDLE hUserToken );
+
+DWORD
+GetShellProcessID();
+
+//
+// Memory macros
+//
+
+#define Alloc(c) ((PVOID)LocalAlloc(LPTR, c))
+#define ReAlloc(p, c) ((PVOID)LocalReAlloc(p, c, LPTR | LMEM_MOVEABLE))
+#define Free(p) ((VOID)LocalFree(p))
+
+//
+// Globals
+//
+
+extern PSID psidMySid;
+extern ULONG fUseSeparateWOW;
+extern CClassCacheList *gpClassCache;
+
+#ifndef _CHICAGO_
+// From ..\objex\objex.cxx
+extern USHORT cMyProtseqs;
+extern USHORT *aMyProtseqs;
+
+extern "C" {
+// From ..\wrapper\epts.c
+extern PROTSEQ_INFO gaProtseqInfo[];
+}
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLocalServer::StartServer
+//
+// Synopsis: Start a server process
+//
+// Arguments: none
+//
+// Returns: S_OK - Server started
+// CO_E_SERVER_EXEC_FAILURE - couldn't start server
+//
+// Algorithm:
+//
+// History: 21-Apr-93 Ricksa Created
+// 04-Jan-94 Ricksa Modified for class starting sync.
+// 31-Mar-94 AndyH Start processes as client
+// 09-Jun-95 SusiA Added Chicago ANSI optimization
+//
+//--------------------------------------------------------------------------
+BOOL CLocalServer::StartServer(CLSID &clsid,
+ WCHAR * pwszAppID,
+ CToken * pClientToken,
+ WCHAR * pwszWinstaDesktop,
+ HANDLE * phProcess,
+ WCHAR *pwszRunAsDomainName,
+ WCHAR *pwszRunAsUserName,
+ WCHAR* pwszSurrogatePath,
+ BOOL fSurrogate)
+{
+ *phProcess = NULL;
+
+ CairoleDebugOut((DEB_ITRACE, "CLocalServer: App Name=%ws\n", (fSurrogate ? L"Surrogate Launch" : _pwszPath)));
+
+ // Where we put the command line
+ WCHAR awszTmpCmdLine[MAX_PATH];
+ WCHAR *pwszTmpCmdLine = awszTmpCmdLine;
+ DWORD cbData;
+
+ if(!fSurrogate)
+ {
+ // size of command line buffer =
+ // size of server path
+ // size of -Embedding (including preceding blank and terminating null
+ cbData = (lstrlenW(_pwszPath) + 12) * sizeof(WCHAR);
+ }
+ else
+ {
+ // size of command line buffer =
+ // size of surrogate command line
+ // size of -Embedding (including preceding blank and terminating null
+ cbData = (lstrlenW(pwszSurrogatePath) + 12) * sizeof(WCHAR);
+ }
+
+ if (cbData > sizeof(awszTmpCmdLine))
+ {
+ pwszTmpCmdLine = (WCHAR *) PrivMemAlloc (cbData);
+
+ if (pwszTmpCmdLine == NULL)
+ {
+ return FALSE;
+ }
+ }
+
+ //
+ // Build command line for server. Use the path from the registry.
+ // This may be absolute or relative. In either case, use the path
+ // searching rules from CreateProcess.
+ //
+ lstrcpyW(pwszTmpCmdLine, fSurrogate ? pwszSurrogatePath : _pwszPath );
+ lstrcatW(pwszTmpCmdLine, L" -Embedding");
+
+#ifndef _CHICAGO_
+ // Check if this is a RunAs activation
+ if (pwszRunAsUserName != NULL)
+ {
+ return StartRunAsServer(clsid,
+ pwszAppID,
+ phProcess,
+ pClientToken,
+ pwszRunAsDomainName,
+ pwszRunAsUserName,
+ pwszTmpCmdLine,
+ fSurrogate);
+ }
+#endif // !_CHICAGO_
+
+ PROCESS_INFORMATION procinfo;
+ procinfo.hProcess = NULL;
+ procinfo.hThread = NULL;
+
+ STARTUPINFO startupinfo;
+ startupinfo.cb = sizeof(STARTUPINFO);
+ startupinfo.lpReserved = NULL;
+ startupinfo.lpDesktop = pwszWinstaDesktop;
+ startupinfo.lpTitle = fSurrogate ? pwszSurrogatePath : _pwszPath;
+ startupinfo.dwX = 40;
+ startupinfo.dwY = 40;
+ startupinfo.dwXSize = 80;
+ startupinfo.dwYSize = 40;
+ startupinfo.dwFlags = 0;
+ startupinfo.wShowWindow = SW_SHOWNORMAL;
+ startupinfo.cbReserved2 = 0;
+ startupinfo.lpReserved2 = NULL;
+
+ BOOL fResultOK;
+
+#ifndef _CHICAGO_
+
+ // Creation flags for create process
+ DWORD fdwCreationFlags = CREATE_NEW_CONSOLE | CREATE_SUSPENDED;
+
+ //
+ // Set WOW flag for CreateProces
+ //
+
+ if (SCM_FORCE_SEPARATE_WOW == fUseSeparateWOW)
+ {
+ fdwCreationFlags |= CREATE_SEPARATE_WOW_VDM;
+ }
+
+
+ RPC_STATUS RpcStatus = RpcImpersonateClient( (RPC_BINDING_HANDLE) 0 );
+ if (RpcStatus != RPC_S_OK)
+ {
+ CairoleDebugOut((DEB_ERROR, "Failed RpcImpersonateClient\n"));
+ // Bail out now!
+ if (pwszTmpCmdLine != awszTmpCmdLine)
+ {
+ PrivMemFree (pwszTmpCmdLine);
+ }
+ return FALSE;
+ }
+
+ //
+ // Initialize process security info (SDs). We need both SIDs to
+ // do this, so here is the 1st time we can. We Delete the SD right
+ // after the CreateProcess call, no matter what happens.
+ //
+ // I added the Thread SD since ntpsapi.h says that THREAD_QUERY_INFORMATION
+ // access is needed and I want to make darn sure we have that access.
+ //
+ // JimK say's it ain't so, and the code works fine without specifying
+ // sec. attributes for the thread, so I removed that code on 4/29/94.
+ //
+
+ SECURITY_ATTRIBUTES saProcess;
+ PSECURITY_DESCRIPTOR psdNewProcessSD;
+ CAccessInfo AccessInfo(pClientToken->GetSid());
+
+ psdNewProcessSD = AccessInfo.IdentifyAccess(
+ FALSE,
+ PROCESS_ALL_ACCESS,
+ PROCESS_SET_INFORMATION | // Allow primary token to be set
+ PROCESS_TERMINATE | SYNCHRONIZE // Allow screen-saver control
+ );
+
+ if (psdNewProcessSD == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR, "Failed to create SD for process\n"));
+ RpcStatus = RpcRevertToSelf();
+ Win4Assert(RPC_S_OK == RpcStatus);
+ fResultOK = FALSE;
+ goto ExitProcessing;
+ }
+
+ saProcess.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saProcess.lpSecurityDescriptor = psdNewProcessSD;
+ saProcess.bInheritHandle = FALSE;
+
+ //
+ // Do the exec while impersonating so the file access gets ACL
+ // checked correctly. Create the app suspended so we can stuff
+ // a new token and resume the process.
+ //
+
+ fResultOK = CreateProcess(NULL, // application name
+ pwszTmpCmdLine, // command line
+ &saProcess, // process sec attributes
+ NULL, // default thread sec attributes
+ // (this was &saThread, but isn't needed)
+ FALSE, // dont inherit handles
+ fdwCreationFlags, // creation flags
+ NULL, // use same enviroment block
+ NULL, // use same directory
+ &startupinfo, // startup info
+ &procinfo); // proc info returned
+
+ //
+ // Everything else we do as ourself.
+ //
+
+ RpcStatus = RpcRevertToSelf();
+ Win4Assert(RPC_S_OK == RpcStatus);
+
+ if (!fResultOK)
+ {
+ CairoleDebugOut((DEB_ERROR, "%ws failed create process. Error = %d\n",
+ pwszTmpCmdLine, GetLastError()));
+#ifndef _CHICAGO_
+ // for this message,
+ // %1 is the command line, and %2 is the error number string
+ // %3 is the CLSID
+ HANDLE LogHandle;
+ LPTSTR Strings[3]; // array of message strings.
+ WCHAR wszErrnum[20];
+ WCHAR wszClsid[GUIDSTR_MAX];
+
+ // Save the command line
+ Strings[0] = pwszTmpCmdLine;
+
+ // Save the error number
+ wsprintf(wszErrnum, L"%lu",GetLastError() );
+ Strings[1] = wszErrnum;
+
+ // Get the clsid
+ wStringFromGUID2(clsid, wszClsid, sizeof(wszClsid));
+ Strings[2] = wszClsid;
+
+ // Get the log handle, then report then event.
+ LogHandle = RegisterEventSource( NULL,
+ SCM_EVENT_SOURCE );
+
+ if ( LogHandle )
+ {
+ ReportEvent( LogHandle,
+ EVENTLOG_ERROR_TYPE,
+ 0, // event category
+ EVENT_RPCSS_CREATEPROCESS_FAILURE,
+ pClientToken->GetSid(), // SID
+ 3, // 3 strings passed
+ 0, // 0 bytes of binary
+ (LPCTSTR *)Strings, // array of strings
+ NULL ); // no raw data
+
+ // clean up the event log handle
+ DeregisterEventSource(LogHandle);
+ }
+#endif // _CHICAGO_
+ goto ExitProcessing;
+ }
+
+ //
+ // if the process was "started" in the shared WOW, we don't stuff the token
+ // or attempt to resume the thread. when a created process is in the shared
+ // wow its hThread is NULL.
+ //
+
+ if (NULL != procinfo.hThread)
+ {
+ // Set the primary token for the app
+ fResultOK = CreateAndSetProcessToken(
+ &procinfo,
+ pClientToken->GetToken(),
+ pClientToken->GetSid() );
+
+ if (!fResultOK)
+ {
+ CairoleDebugOut((DEB_ERROR, "failed to set token for process\n"));
+ }
+ else
+ {
+ if ( ResumeThread(procinfo.hThread) == -1 )
+ TerminateProcess(procinfo.hProcess, 0);
+ }
+ }
+
+ExitProcessing:
+
+ if (NULL != procinfo.hThread)
+ CloseHandle(procinfo.hThread);
+
+ if (fResultOK && procinfo.hThread != NULL)
+ {
+ *phProcess = procinfo.hProcess;
+ }
+ else if (procinfo.hProcess != NULL)
+ {
+ CloseHandle(procinfo.hProcess);
+ }
+
+ if (pwszTmpCmdLine != awszTmpCmdLine)
+ {
+ PrivMemFree (pwszTmpCmdLine);
+ }
+
+ return fResultOK;
+
+#else
+
+ //
+ // This is code we use for _CHICAGO_
+ //
+
+ //
+ // For Chicago, we just do the CreateProcess.
+ //
+
+ fResultOK = CreateProcess(NULL, // application name
+ pwszTmpCmdLine, // command line
+ NULL, // default process sec attributes
+ NULL, // default thread sec attributes
+ FALSE, // dont inherit handles
+ CREATE_NEW_CONSOLE, // creation flags
+ NULL, // use same enviroment block
+ NULL, // use same directory
+ &startupinfo, // startup info
+ &procinfo); // proc info returned
+
+ if (!fResultOK)
+ {
+ CairoleDebugOut((DEB_ERROR, "%ws failed create process. Error = %d\n",
+ pwszTmpCmdLine, GetLastError()));
+ }
+ else
+ { // CreateProcess OK
+
+ CairoleDebugOut((DEB_ITRACE,"ProcID =0x%x\n", procinfo.dwProcessId));
+ CairoleDebugOut((DEB_ITRACE,"ThreadID=0x%x\n\n", procinfo.dwThreadId));
+ CloseHandle(procinfo.hThread);
+ *phProcess = procinfo.hProcess;
+ }
+
+ if (pwszTmpCmdLine != awszTmpCmdLine)
+ {
+ PrivMemFree (pwszTmpCmdLine);
+ }
+
+ return fResultOK;
+
+#endif // _CHICAGO_
+
+}
+
+#ifndef _CHICAGO_
+
+// nothing else in this file is needed for chicago.
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLocalServer::StartRunAsServer
+//
+// Synopsis: Start a RunAs server process
+//
+// Arguments: CLSID& - clsid
+// HANDLE - process handle
+// WCHAR* - domain name
+// WCHAR* - user name
+// WCHAR* - command line
+//
+// Returns: BOOL - TRUE if successful
+//
+// Algorithm:
+//
+// History: 07-Dec-95 BruceMa Created
+//
+//--------------------------------------------------------------------------
+BOOL CLocalServer::StartRunAsServer(CLSID &clsid,
+ WCHAR *pwszAppID,
+ HANDLE *phProcess,
+ CToken *pClientToken,
+ WCHAR *pwszRunAsDomainName,
+ WCHAR *pwszRunAsUserName,
+ WCHAR *pwszCommandLine,
+ BOOL fSurrogate)
+{
+ NTSTATUS err;
+ HANDLE hToken;
+ SECURITY_ATTRIBUTES saProcess;
+ PSECURITY_DESCRIPTOR psdNewProcessSD;
+ STARTUPINFO sStartupInfo;
+ PROCESS_INFORMATION sProcInfo;
+ PSID psidUserSid = NULL;
+ BOOL Result;
+ BOOL CloseToken = FALSE;
+
+ // Initialize
+
+ hToken = NULL;
+ Result = FALSE;
+
+ *phProcess = NULL;
+
+ sStartupInfo.cb = sizeof(STARTUPINFO);
+ sStartupInfo.lpReserved = NULL;
+ sStartupInfo.lpDesktop = NULL;
+ sStartupInfo.lpTitle = fSurrogate ? NULL : _pwszPath;
+ sStartupInfo.dwFlags = 0;
+ sStartupInfo.cbReserved2 = 0;
+ sStartupInfo.lpReserved2 = NULL;
+
+ if ( lstrcmpiW( pwszRunAsUserName, L"Interactive User" ) == 0 )
+ {
+ hToken = GetShellProcessToken();
+ }
+ else
+ {
+ hToken = GetRunAsToken( pwszAppID,
+ pwszRunAsDomainName,
+ pwszRunAsUserName );
+ CloseToken = TRUE;
+ }
+
+ if ( hToken == 0 )
+ return FALSE;
+
+ // Build the security descriptor for the process we're creating
+ psidUserSid = GetUserSid(hToken);
+
+ CAccessInfo AccessInfo(psidUserSid);
+
+ // We have to get past the CAccessInfo before we can use a goto.
+
+ if ( psidUserSid == NULL )
+ {
+ CairoleDebugOut((DEB_ERROR, "Failed to get RunAs security ID\n"));
+ goto CleanupExit;
+ }
+
+ psdNewProcessSD = AccessInfo.IdentifyAccess(
+ FALSE,
+ PROCESS_ALL_ACCESS,
+ PROCESS_SET_INFORMATION | // Allow primary token to be set
+ PROCESS_TERMINATE | SYNCHRONIZE // Allow screen-saver control
+ );
+
+ if (psdNewProcessSD == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR, "Failed to create RunAs SD for process\n"));
+ goto CleanupExit;
+ }
+
+ saProcess.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saProcess.lpSecurityDescriptor = psdNewProcessSD;
+ saProcess.bInheritHandle = FALSE;
+
+ if (!CreateProcessAsUser(hToken, NULL, pwszCommandLine,
+ &saProcess, NULL,
+ FALSE, CREATE_NEW_CONSOLE, NULL, NULL,
+ &sStartupInfo, &sProcInfo))
+ {
+ CairoleDebugOut((DEB_ERROR, "Failed to create RunAs process\n"));
+
+ // for this message,
+ // %1 is the command line, and %2 is the error number string
+ // %3 is the CLSID, %4 is the RunAs domain name, %5 is the RunAs Userid
+ HANDLE LogHandle;
+ LPTSTR Strings[5]; // array of message strings.
+ WCHAR wszErrnum[20];
+ WCHAR wszClsid[GUIDSTR_MAX];
+
+ // Save the command line
+ Strings[0] = pwszCommandLine;
+
+ // Save the error number
+ wsprintf(wszErrnum, L"%lu",GetLastError() );
+ Strings[1] = wszErrnum;
+
+ // Get the clsid
+ wStringFromGUID2(clsid, wszClsid, sizeof(wszClsid));
+ Strings[2] = wszClsid;
+
+ // Put in the RunAs identity
+ Strings[3] = pwszRunAsDomainName;
+ Strings[4] = pwszRunAsUserName;
+
+ // Get the log handle, then report then event.
+ LogHandle = RegisterEventSource( NULL,
+ SCM_EVENT_SOURCE );
+
+ if ( LogHandle )
+ {
+ ReportEvent( LogHandle,
+ EVENTLOG_ERROR_TYPE,
+ 0, // event category
+ EVENT_RPCSS_RUNAS_CREATEPROCESS_FAILURE,
+ pClientToken ? pClientToken->GetSid() : NULL, // SID
+ 5, // 5 strings passed
+ 0, // 0 bytes of binary
+ (LPCTSTR *)Strings, // array of strings
+ NULL ); // no raw data
+
+ // clean up the event log handle
+ DeregisterEventSource(LogHandle);
+ }
+
+ goto CleanupExit;
+ }
+
+ Result = TRUE;
+
+ // Return the handle of the new process
+ *phProcess = sProcInfo.hProcess;
+ NtClose( sProcInfo.hThread );
+
+CleanupExit:
+
+ if ( CloseToken )
+ NtClose( hToken );
+
+ if(!fSurrogate)
+ {
+ //
+ // Don't delete the SID. We cache it to use in checks when a server
+ // registers a RunAs CLSID.
+ //
+ _pRunAsSid = psidUserSid;
+ }
+ else
+ {
+ // we need to delete the SID because surrogates share the same local server
+ DeleteUserSid(psidUserSid);
+ Win4Assert(_pRunAsSid == NULL);
+ }
+
+ return Result;
+}
+
+HANDLE
+GetRunAsToken(
+ WCHAR *pwszAppID,
+ WCHAR *pwszRunAsDomainName,
+ WCHAR *pwszRunAsUserName )
+{
+ LSA_OBJECT_ATTRIBUTES sObjAttributes;
+ HANDLE hPolicy = NULL;
+ LSA_UNICODE_STRING sKey;
+ WCHAR wszKey[CLSIDSTR_MAX+5];
+ PLSA_UNICODE_STRING psPassword;
+ HANDLE hToken;
+
+ if ( lstrcmpiW( pwszRunAsUserName, L"Interactive User" ) == 0 )
+ {
+ //
+ // Should call GetShellProcessToken() instead and not free the
+ // resulting token.
+ //
+ return 0;
+ }
+
+ if ( !pwszAppID )
+ {
+ // if we have a RunAs, we'd better have an appid....
+ return 0;
+ }
+
+ // formulate the access key
+ lstrcpyW(wszKey, L"SCM:");
+ lstrcatW(wszKey, pwszAppID );
+
+ // UNICODE_STRING length fields are in bytes and include the NULL
+ // terminator
+ sKey.Length = (lstrlenW(wszKey) + 1) * sizeof(WCHAR);
+ sKey.MaximumLength = (CLSIDSTR_MAX + 5) * sizeof(WCHAR);
+ sKey.Buffer = wszKey;
+
+ // Open the local security policy
+ InitializeObjectAttributes(&sObjAttributes, NULL, 0L, NULL, NULL);
+ if (!NT_SUCCESS(LsaOpenPolicy(NULL, &sObjAttributes,
+ POLICY_GET_PRIVATE_INFORMATION, &hPolicy)))
+ {
+ return 0;
+ }
+
+ // Read the user's password
+ if (!NT_SUCCESS(LsaRetrievePrivateData(hPolicy, &sKey, &psPassword)))
+ {
+ LsaClose(hPolicy);
+ return 0;
+ }
+
+ // Close the policy handle, we're done with it now.
+ LsaClose(hPolicy);
+
+ // Log the specifed user on
+ if (!LogonUser(pwszRunAsUserName, pwszRunAsDomainName, psPassword->Buffer,
+ LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &hToken))
+ {
+ memset(psPassword->Buffer, 0, psPassword->Length);
+
+ // for this message,
+ // %1 is the error number string
+ // %2 is the domain name
+ // %3 is the user name
+ // %4 is the CLSID
+ HANDLE LogHandle;
+ LPTSTR Strings[4]; // array of message strings.
+ WCHAR wszErrnum[20];
+ WCHAR wszClsid[GUIDSTR_MAX];
+
+ // Save the error number
+ wsprintf(wszErrnum, L"%lu",GetLastError() );
+ Strings[0] = wszErrnum;
+
+ // Put in the RunAs identity
+ Strings[1] = pwszRunAsDomainName;
+ Strings[2] = pwszRunAsUserName;
+
+ // Get the clsid
+ Strings[3] = pwszAppID;
+
+ // Get the log handle, then report then event.
+ LogHandle = RegisterEventSource( NULL,
+ SCM_EVENT_SOURCE );
+
+ if ( LogHandle )
+ {
+ ReportEvent( LogHandle,
+ EVENTLOG_ERROR_TYPE,
+ 0, // event category
+ EVENT_RPCSS_RUNAS_CANT_LOGIN,
+ NULL, // SID
+ 4, // 4 strings passed
+ 0, // 0 bytes of binary
+ (LPCTSTR *)Strings, // array of strings
+ NULL ); // no raw data
+
+ // clean up the event log handle
+ DeregisterEventSource(LogHandle);
+ }
+
+ return 0;
+ }
+
+ // Clear the password
+ memset(psPassword->Buffer, 0, psPassword->Length);
+
+ return hToken;
+}
+
+/***************************************************************************\
+* CreateAndSetProcessToken
+*
+* Set the primary token of the specified process
+* If the specified token is NULL, this routine does nothing.
+*
+* It assumed that the handles in ProcessInformation are the handles returned
+* on creation of the process and therefore have all access.
+*
+* Returns TRUE on success, FALSE on failure.
+*
+* 01-31-91 Davidc Created.
+* 31-Mar-94 AndyH Started from Winlogon; added SetToken
+\***************************************************************************/
+
+BOOL
+CreateAndSetProcessToken(
+ PPROCESS_INFORMATION ProcessInformation,
+ HANDLE hUserToken,
+ PSID psidUserSid
+ )
+{
+ NTSTATUS NtStatus, NtAdjustStatus;
+ PROCESS_ACCESS_TOKEN PrimaryTokenInfo;
+ HANDLE hTokenToAssign;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ BOOLEAN fWasEnabled;
+ PSECURITY_DESCRIPTOR psdNewProcessTokenSD;
+
+ //
+ // Check for a NULL token. (No need to do anything)
+ // The process will run in the parent process's context and inherit
+ // the default ACL from the parent process's token.
+ //
+ if (hUserToken == NULL) {
+ return(TRUE);
+ }
+
+ //
+ // Create the security descriptor that we want to put in the Token.
+ // Need to destroy it before we leave this function.
+ //
+
+ CAccessInfo AccessInfo(psidUserSid);
+
+ psdNewProcessTokenSD = AccessInfo.IdentifyAccess(
+ FALSE,
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS |
+ TOKEN_ADJUST_DEFAULT | TOKEN_QUERY |
+ TOKEN_DUPLICATE | TOKEN_IMPERSONATE | READ_CONTROL,
+ TOKEN_QUERY
+ );
+
+ if (psdNewProcessTokenSD == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR, "Failed to create SD for process token\n"));
+ return(FALSE);
+ }
+
+ //
+ // A primary token can only be assigned to one process.
+ // Duplicate the logon token so we can assign one to the new
+ // process.
+ //
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ NULL,
+ 0,
+ NULL,
+ psdNewProcessTokenSD
+ );
+
+
+ NtStatus = NtDuplicateToken(
+ hUserToken, // Duplicate this token
+ TOKEN_ASSIGN_PRIMARY, // Give me this access to the resulting token
+ &ObjectAttributes,
+ FALSE, // EffectiveOnly
+ TokenPrimary, // TokenType
+ &hTokenToAssign // Duplicate token handle stored here
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ CairoleDebugOut((DEB_ERROR, "CreateAndSetProcessToken failed to duplicate primary token for new user process, status = 0x%lx\n", NtStatus));
+ return(FALSE);
+ }
+
+ //
+ // Set the process's primary token
+ //
+
+
+ //
+ // Enable the required privilege
+ //
+
+ NtStatus = RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE,
+ FALSE, &fWasEnabled);
+ if (NT_SUCCESS(NtStatus)) {
+
+ PrimaryTokenInfo.Token = hTokenToAssign;
+ PrimaryTokenInfo.Thread = ProcessInformation->hThread;
+
+ NtStatus = NtSetInformationProcess(
+ ProcessInformation->hProcess,
+ ProcessAccessToken,
+ (PVOID)&PrimaryTokenInfo,
+ (ULONG)sizeof(PROCESS_ACCESS_TOKEN)
+ );
+
+ //
+ // if we just started the Shared WOW, the handle we get back
+ // is really just a handle to an event.
+ //
+
+ if (STATUS_OBJECT_TYPE_MISMATCH == NtStatus)
+ {
+ HANDLE hRealProcess = OpenProcess(
+ PROCESS_SET_INFORMATION | PROCESS_TERMINATE | SYNCHRONIZE,
+ FALSE,
+ ProcessInformation->dwProcessId);
+
+ if (hRealProcess)
+ {
+ NtStatus = NtSetInformationProcess(
+ hRealProcess,
+ ProcessAccessToken,
+ (PVOID)&PrimaryTokenInfo,
+ (ULONG)sizeof(PROCESS_ACCESS_TOKEN)
+ );
+ CloseHandle(hRealProcess);
+ }
+ }
+
+ //
+ // Restore the privilege to its previous state
+ //
+
+ NtAdjustStatus = RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE,
+ fWasEnabled, FALSE, &fWasEnabled);
+ if (!NT_SUCCESS(NtAdjustStatus)) {
+ CairoleDebugOut((DEB_ERROR, "failed to restore assign-primary-token privilege to previous enabled state\n"));
+ }
+
+ if (NT_SUCCESS(NtStatus)) {
+ NtStatus = NtAdjustStatus;
+ }
+ } else {
+ CairoleDebugOut((DEB_ERROR, "failed to enable assign-primary-token privilege\n"));
+ }
+
+ //
+ // We're finished with the token handle and the SD
+ //
+
+ CloseHandle(hTokenToAssign);
+
+
+ if (!NT_SUCCESS(NtStatus)) {
+ CairoleDebugOut((DEB_ERROR, "CreateAndSetProcessToken failed to set primary token for new user process, Status = 0x%lx\n", NtStatus));
+ }
+
+ return (NT_SUCCESS(NtStatus));
+}
+
+
+
+
+
+/***************************************************************************\
+* GetUserSid
+*
+* Allocs space for the user sid, fills it in and returns a pointer.
+* The sid should be freed by calling DeleteUserSid.
+*
+* Note the sid returned is the user's real sid, not the per-logon sid.
+*
+* Returns pointer to sid or NULL on failure.
+*
+* History:
+* 26-Aug-92 Davidc Created.
+* 31-Mar-94 AndyH Copied from Winlogon, changed arg from pGlobals
+\***************************************************************************/
+PSID
+GetUserSid(
+ HANDLE hUserToken
+ )
+{
+ BYTE achBuffer[100];
+ PTOKEN_USER pUser = (PTOKEN_USER) &achBuffer;
+ PSID pSid;
+ DWORD dwBytesRequired;
+ NTSTATUS NtStatus;
+ BOOL fAllocatedBuffer = FALSE;
+
+ NtStatus = NtQueryInformationToken(
+ hUserToken, // Handle
+ TokenUser, // TokenInformationClass
+ pUser, // TokenInformation
+ sizeof(achBuffer), // TokenInformationLength
+ &dwBytesRequired // ReturnLength
+ );
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ if (NtStatus != STATUS_BUFFER_TOO_SMALL)
+ {
+ Win4Assert(NtStatus == STATUS_BUFFER_TOO_SMALL);
+ return NULL;
+ }
+
+ //
+ // Allocate space for the user info
+ //
+
+ pUser = (PTOKEN_USER) Alloc(dwBytesRequired);
+ if (pUser == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR, "Failed to allocate %d bytes\n", dwBytesRequired));
+ Win4Assert(pUser != NULL);
+ return NULL;
+ }
+
+ fAllocatedBuffer = TRUE;
+
+ //
+ // Read in the UserInfo
+ //
+
+ NtStatus = NtQueryInformationToken(
+ hUserToken, // Handle
+ TokenUser, // TokenInformationClass
+ pUser, // TokenInformation
+ dwBytesRequired, // TokenInformationLength
+ &dwBytesRequired // ReturnLength
+ );
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ CairoleDebugOut((DEB_ERROR, "Failed to query user info from user token, status = 0x%lx\n", NtStatus));
+ Win4Assert(NtStatus == STATUS_SUCCESS);
+ Free((HANDLE)pUser);
+ return NULL;
+ }
+ }
+
+
+ // Alloc buffer for copy of SID
+
+ dwBytesRequired = RtlLengthSid(pUser->User.Sid);
+ pSid = Alloc(dwBytesRequired);
+ if (pSid == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR, "Failed to allocate %d bytes\n", dwBytesRequired));
+ if (fAllocatedBuffer == TRUE)
+ {
+ Free((HANDLE)pUser);
+ }
+ return NULL;
+ }
+
+ // Copy SID
+
+ NtStatus = RtlCopySid(dwBytesRequired, pSid, pUser->User.Sid);
+ if (fAllocatedBuffer == TRUE)
+ {
+ Free((HANDLE)pUser);
+ }
+
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ CairoleDebugOut((DEB_ERROR, "RtlCopySid failed, status = 0x%lx\n", NtStatus));
+ Win4Assert(NtStatus != STATUS_SUCCESS);
+ Free(pSid);
+ pSid = NULL;
+ }
+
+
+ return pSid;
+}
+
+
+/***************************************************************************\
+* DeleteUserSid
+*
+* Deletes a user sid previously returned by GetUserSid()
+*
+* Returns nothing.
+*
+* History:
+* 26-Aug-92 Davidc Created
+*
+\***************************************************************************/
+VOID
+DeleteUserSid(
+ PSID Sid
+ )
+{
+ Free(Sid);
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetUserSidHelper
+//
+// Synopsis: Helper function to return the user SID of the caller
+//
+// Arguments: &PSID - Where to store the caller's PSID
+//
+// Returns: HRESULT - S_OK if successful
+// E_FAIL otherwise
+//
+// Algorithm:
+//
+// History: 09-Jan-95 BruceMa Created
+//
+// Note: If successful and *ppUserSid is non-NULL then it returns
+// in an impersonation state
+//
+//--------------------------------------------------------------------------
+HRESULT GetUserSidHelper(PSID *ppUserSid)
+{
+ // Initialize
+ *ppUserSid = NULL;
+
+ // Impersonate the client
+ RPC_STATUS RpcStatus = RpcImpersonateClient( (RPC_BINDING_HANDLE) 0 );
+ if (RpcStatus != RPC_S_OK)
+ {
+ CairoleDebugOut((DEB_ERROR, "GetUserSidHelper: Failed RpcImpersonateClient\n"));
+ return E_FAIL;
+ }
+
+ // Get caller's token while impersonating
+ HANDLE hUserToken = NULL;
+ NTSTATUS NtStatus;
+
+ if (!NT_SUCCESS(NtOpenThreadToken(NtCurrentThread(),
+ TOKEN_DUPLICATE | TOKEN_QUERY,
+ TRUE,
+ &hUserToken)))
+ {
+ RpcRevertToSelf();
+ CairoleDebugOut((DEB_ERROR, "GetUserSidHelper: Failed NtOpenThreadToken\n"));
+ return E_FAIL;
+ }
+
+ // Get the user sid
+ *ppUserSid = GetUserSid(hUserToken);
+
+ NtClose( hUserToken );
+
+ if (*ppUserSid == NULL)
+ {
+ RpcRevertToSelf();
+ return E_FAIL;
+ }
+ else
+ {
+ return S_OK;
+ }
+}
+
+// Initialzed in InitializeSCM during boot.
+CRITICAL_SECTION ShellQueryCS;
+
+HANDLE GetShellProcessToken()
+{
+ NTSTATUS NtStatus;
+ BOOL bStatus;
+ HKEY hReg;
+ LONG RegStatus;
+ DWORD RegSize, RegType;
+ WCHAR * pwszImageName;
+ DWORD Pid;
+ BYTE StackInfoBuffer[4096];
+ PBYTE pProcessInfoBuffer;
+ ULONG ProcessInfoBufferSize;
+ ULONG TotalOffset;
+ PSYSTEM_PROCESS_INFORMATION pProcessInfo;
+
+ static HANDLE hShellProcess = 0;
+ static HANDLE hShellProcessToken = 0;
+ static WCHAR * pwszShellName = 0;
+
+ EnterCriticalSection( &ShellQueryCS );
+
+ if ( ! pwszShellName )
+ {
+ RegStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
+ 0,
+ KEY_READ,
+ &hReg );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ LeaveCriticalSection( &ShellQueryCS );
+ return 0;
+ }
+
+ // Shell will usually be explorer.exe.
+ RegSize = 13 * sizeof(WCHAR);
+ pwszShellName = (WCHAR *) PrivMemAlloc( RegSize );
+
+ if ( ! pwszShellName )
+ return 0;
+
+ RegStatus = RegQueryValueEx( hReg,
+ L"Shell",
+ 0,
+ &RegType,
+ (LPBYTE)pwszShellName,
+ &RegSize );
+
+ if ( RegStatus == ERROR_MORE_DATA )
+ {
+ PrivMemFree( pwszShellName );
+ pwszShellName = (WCHAR *) PrivMemAlloc( RegSize );
+
+ if ( ! pwszShellName )
+ return 0;
+
+ RegStatus = RegQueryValueEx( hReg,
+ L"Shell",
+ 0,
+ &RegType,
+ (LPBYTE)pwszShellName,
+ &RegSize );
+ }
+
+ RegCloseKey( hReg );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ PrivMemFree( pwszShellName );
+ pwszShellName = 0;
+ LeaveCriticalSection( &ShellQueryCS );
+ return 0;
+ }
+ }
+
+ if ( hShellProcess )
+ {
+ if ( WaitForSingleObject( hShellProcess, 0 ) == WAIT_TIMEOUT )
+ {
+ LeaveCriticalSection( &ShellQueryCS );
+ return hShellProcessToken;
+ }
+
+ CloseHandle( hShellProcessToken );
+ CloseHandle( hShellProcess );
+
+ hShellProcessToken = 0;
+ hShellProcess = 0;
+ }
+
+ Pid = 0;
+
+ pProcessInfoBuffer = StackInfoBuffer;
+ ProcessInfoBufferSize = sizeof(StackInfoBuffer);
+
+ for (;;)
+ {
+ NtStatus = NtQuerySystemInformation( SystemProcessInformation,
+ pProcessInfoBuffer,
+ ProcessInfoBufferSize,
+ NULL );
+
+ if ( NtStatus == STATUS_INFO_LENGTH_MISMATCH )
+ {
+ ProcessInfoBufferSize += 4096;
+ if ( pProcessInfoBuffer != StackInfoBuffer )
+ PrivMemFree( pProcessInfoBuffer );
+ pProcessInfoBuffer = (PBYTE) PrivMemAlloc( ProcessInfoBufferSize );
+ if ( ! pProcessInfoBuffer )
+ goto AllDone;
+ continue;
+ }
+
+ if ( ! NT_SUCCESS(NtStatus) )
+ goto AllDone;
+
+ break;
+ }
+
+ pProcessInfo = (PSYSTEM_PROCESS_INFORMATION) pProcessInfoBuffer;
+ TotalOffset = 0;
+
+ for (;;)
+ {
+ if ( pProcessInfo->ImageName.Buffer )
+ {
+ pwszImageName = &pProcessInfo->ImageName.Buffer[pProcessInfo->ImageName.Length / sizeof(WCHAR)];
+
+ while ( (pwszImageName != pProcessInfo->ImageName.Buffer) &&
+ (pwszImageName[-1] != '\\') )
+ pwszImageName--;
+
+ if ( lstrcmpiW( pwszShellName, pwszImageName ) == 0 )
+ {
+ Pid = (DWORD)pProcessInfo->UniqueProcessId;
+ break;
+ }
+ }
+
+ if ( pProcessInfo->NextEntryOffset == 0 )
+ break;
+
+ TotalOffset += pProcessInfo->NextEntryOffset;
+ pProcessInfo = (PSYSTEM_PROCESS_INFORMATION) &pProcessInfoBuffer[TotalOffset];
+ }
+
+AllDone:
+
+ if ( pProcessInfoBuffer != StackInfoBuffer )
+ PrivMemFree( pProcessInfoBuffer );
+
+ if ( Pid != 0 )
+ {
+ hShellProcess = OpenProcess( PROCESS_ALL_ACCESS,
+ FALSE,
+ Pid );
+
+ if ( hShellProcess )
+ {
+ bStatus = OpenProcessToken( hShellProcess,
+ TOKEN_ALL_ACCESS,
+ &hShellProcessToken );
+ }
+ }
+
+ LeaveCriticalSection( &ShellQueryCS );
+
+ // Callers should not close this token unless they want to hose us!
+ return hShellProcessToken;
+}
+
+#endif // large block of code ignored for _CHICAGO_
+
+//+-------------------------------------------------------------------------
+//
+// Member: CStringID::CStringID
+//
+// Synopsis: Create a string ID
+//
+// Arguments: [pwszPath] - path to use for id
+//
+// History: 21-Apr-93 Ricksa Created
+// 28-Jul-94 DavePl Changed to special-case EXE names
+// which contain trailing options
+//
+//--------------------------------------------------------------------------
+CStringID::CStringID(const WCHAR *pwszPath, HRESULT &hr)
+ : _culRefs(0), _pwszPath(NULL)
+#if DBG==1
+ ,_ulSig(STRINGSIG)
+#endif
+{
+ hr = S_OK;
+
+ // Calculate size of path in characters
+ _cPath = lstrlenW(pwszPath) + 1;
+
+ // Calculate size of path in bytes
+ _cPathBytes = _cPath * sizeof(WCHAR);
+
+ // Allocate path
+ _pwszPath = (WCHAR *) ScmMemAlloc(_cPathBytes);
+
+ if (_pwszPath == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ return;
+ }
+
+ // Copy in path
+ memcpy(_pwszPath, pwszPath, _cPathBytes);
+
+ //
+ // Don't convert the marker string (0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00)
+ // to upper case or else the CharUpperW() routine will muck it up.
+ //
+ if (_cPathBytes != 6 || *(LONG UNALIGNED *)pwszPath != ~0)
+ {
+ // If the server name contains a trailing switch, such as "/Automation", we
+ // cannot blindly upper-case the entire string, as some apps (such as Word)
+ // may do a string-sensitive compare against the switches.
+
+ if (NULL == wcschr(_pwszPath, L' ')) // Look for a space in the name
+ {
+ // If there is no space in the EXE name, there can be no trailing
+ // arguments, so we are safe to upper-case the string
+ CharUpperW(_pwszPath);
+ }
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CStringID::CStringID
+//
+// Synopsis: Copy constructor
+//
+// Arguments: [pwszPath] - path to use for id
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CStringID::CStringID(const CStringID& strid, HRESULT &hr)
+ : _culRefs(0), _pwszPath(NULL)
+#if DBG==1
+ ,_ulSig(STRINGSIG)
+#endif
+{
+ // Calculate size of path in characters
+ _cPath = strid._cPath;
+
+ // Calculate size of path in bytes
+ _cPathBytes = strid._cPathBytes;
+
+ // Allocate path
+ _pwszPath = (WCHAR *) ScmMemAlloc(_cPathBytes);
+
+ // BUGBUG: What to do when this fails
+ // Answer: check the return value and propagate to caller !
+
+ if (_pwszPath == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ return;
+ }
+
+ // Copy in path - no up case because it already is.
+ memcpy(_pwszPath, strid._pwszPath, _cPathBytes);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CStringID::Compare
+//
+// Synopsis: Compare the string keys
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+int CStringID::Compare(const CStringID& cstrid) const
+{
+ int cCmp = (_cPathBytes < cstrid._cPathBytes)
+ ? _cPathBytes : cstrid._cPathBytes;
+
+ // Note that the _cPath includes the trailing NULL so if the
+ // memcmp returns 0 the strings are equal.
+ return memcmp(_pwszPath, cstrid._pwszPath, cCmp);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CStringID::GetPath
+//
+// Synopsis: Make a copy of the path
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+void CStringID::GetPath(WCHAR **ppwszPath)
+{
+ // Allocate memory for the path
+ if (*ppwszPath = (WCHAR *) PrivMemAlloc(_cPath * sizeof(WCHAR)))
+ {
+ // Copy data into the memory
+ memcpy(*ppwszPath, _pwszPath, _cPathBytes);
+ }
+
+ return;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CStringID::Release
+//
+// Synopsis: Decrement refcnt and remove from list if zero
+//
+// History: 21-Apr-93 Ricksa Created
+// 20-Oct-94 BillMo Demacroisation
+//
+//--------------------------------------------------------------------------
+
+ULONG CStringID::Release(CStringList &sl)
+{
+ ULONG ulTmp = --_culRefs;
+
+ if (_culRefs == 0)
+ {
+ sl.Remove(this);
+ delete this;
+ }
+
+ return ulTmp;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStringList::Add
+//
+// Synopsis: Add the given string to the string list.
+//
+// Effects: If it already exists, then use an existing copy.
+//
+// Arguments: [pwszPath] -- string to copy.
+// [hr] -- HRESULT& to set on failure only.
+//
+// Returns: NULL on failure.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+CStringID * CStringList::Add(const WCHAR *pwszPath, HRESULT &hr)
+{
+ CStringID csid(pwszPath, hr);
+
+ if (FAILED(hr))
+ return(NULL);
+
+ CStringID *pString = (CStringID *) Search(&csid);
+
+ if (pString == NULL)
+ {
+ pString = new CStringID(pwszPath, hr);
+
+ if (pString == NULL ||
+ FAILED(hr) ||
+ Insert(pString) == NULL)
+ {
+ if (pString == NULL || SUCCEEDED(hr))
+ hr = E_OUTOFMEMORY;
+ delete pString;
+ return(NULL);
+ }
+ }
+
+ pString->AddRef();
+ return pString;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CLocalServer::Add
+//
+// Synopsis: Add the given local server to the server list.
+//
+// Effects: If it already exists, then use an existing copy.
+//
+// Arguments: [pwszPath] -- string to copy.
+// [hr] -- HRESULT& to set on failure only.
+//
+// Returns: NULL on failure.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+CLocalServer * CLocSrvList::Add(const WCHAR *pwszPath, HRESULT &hr)
+{
+ CStringID csid(pwszPath, hr);
+
+ if (FAILED(hr))
+ return(NULL);
+
+ CLocalServer *pLocalServer = (CLocalServer *) Search(&csid);
+
+ if (pLocalServer == NULL)
+ {
+ pLocalServer = new CLocalServer(pwszPath, hr);
+
+ if (pLocalServer == NULL ||
+ FAILED(hr) ||
+ Insert(pLocalServer) == NULL)
+ {
+ if (pLocalServer == NULL || SUCCEEDED(hr))
+ hr = E_OUTOFMEMORY;
+ delete pLocalServer;
+ return(NULL);
+ }
+ }
+
+ pLocalServer->AddRef();
+ return pLocalServer;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLocalServer::Release
+//
+// Synopsis: Decrement refcnt and remove from list if zero
+//
+// History: 21-Apr-93 Ricksa Created
+// 20-Oct-94 BillMo Demacroisation
+//
+//--------------------------------------------------------------------------
+
+ULONG CLocalServer::Release(CLocSrvList &lsl)
+{
+ ULONG ulTmp = --_culRefs;
+
+ if (_culRefs == 0)
+ {
+ lsl.Remove(this);
+ delete this;
+ }
+
+ return ulTmp;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: SkipListCompareStringIDs,
+// SkipListDeleteStringID
+// SkipListDeleteLocalServer
+//
+// Synopsis: Routines called by CStringList's CSkipList.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+int SkipListCompareStringIDs(void *pkey1, void * pkey2)
+{
+ CStringID *p1 = (CStringID*)pkey1;
+ const CStringID *p2 = (CStringID*)pkey2;
+ p1->CheckSig();
+ p2->CheckSig();
+ return(p1->Compare(*p2));
+}
+
+void SkipListDeleteStringID(void *pkey1)
+{
+ CStringID *p = (CStringID*)pkey1;
+ p->CheckSig();
+ delete p;
+}
+
+void SkipListDeleteLocalServer(void *pvLocalServer)
+{
+ CLocalServer *p = (CLocalServer*)pvLocalServer;
+ p->CheckSig();
+ delete p;
+}
+
+
+
+
diff --git a/private/ole32/dcomss/olescm/clsdata.hxx b/private/ole32/dcomss/olescm/clsdata.hxx
new file mode 100644
index 000000000..91d87b614
--- /dev/null
+++ b/private/ole32/dcomss/olescm/clsdata.hxx
@@ -0,0 +1,500 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: clsdata.hxx
+//
+// Contents: classes which implement the data for component object data
+//
+// Classes: CStringID
+// CLocSrvEntry
+// CLocalServer
+// CLocSrvList
+// CSafeLocalServer
+//
+// Functions: CStringID::CStringID
+// CStringID::~CStringID
+// CStringID::Compare
+// CStringID::GetPath
+// CStringID::AddRef
+// CStringID::Release
+// CLocalServer::CLocalServer
+// CLocalServer::RpcHandle
+// CLocalServer::StopServer
+//
+// History: 21-Apr-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+// 20-Oct-94 BillMo Demacroisation
+//
+//--------------------------------------------------------------------------
+
+#ifdef _CHICAGO_
+#include "chicago\clsdata.hxx"
+#else
+
+#ifndef __CLSDATA_HXX__
+#define __CLSDATA_HXX__
+
+#include "scm.hxx"
+#include <sem.hxx>
+#include <memapi.hxx>
+#include <skiplist.hxx>
+#include <cevent.hxx>
+
+// Maximum items we expect to cache
+#define MAX_SERVER_CACHE 128
+
+// Maximum time to wait for a server to start in seconds
+#define SERVER_MAX_START_WAIT_MSEC ((DWORD)(5 * 60 * 1000))
+
+#define STRINGSIG 0x53544944
+#define LOCALSERVERSIG 0x4c534944
+
+int SkipListCompareStringIDs(void *pStringID, void *pStringID2);
+void SkipListDeleteStringID(void *pStringID);
+void SkipListDeleteLocalServer(void *pvLocalServer);
+
+#ifdef DCOM
+PSID GetUserSid(HANDLE hUserToken);
+
+void DeleteUserSid(PSID pUserSid);
+
+HANDLE GetShellProcessToken();
+
+HANDLE GetRunAsToken(
+ WCHAR *pClsid,
+ WCHAR *pwszRunAsDomainName,
+ WCHAR *pwszRunAsUserName );
+
+class CToken;
+#endif // DCOM
+
+//+-------------------------------------------------------------------------
+//
+// Class: CStringID (csid)
+//
+// Purpose: String class for base of server list
+//
+// Interface: Compare - comparison operator on paths
+// GetPath - return path to server
+// AddRef - add a reference to this object
+// Release - release a reference to this object
+//
+// History: 21-Apr-93 Ricksa Created
+// 20-Oct-94 BillMo Demacroization
+//
+//--------------------------------------------------------------------------
+
+class CStringList;
+
+class CStringID : public CScmAlloc
+{
+public:
+ CStringID(const WCHAR *pwszPath, HRESULT &hr);
+
+ CStringID(const CStringID& strid, HRESULT &hr);
+
+ virtual ~CStringID(void);
+
+ int Compare(const CStringID& cstrid) const;
+
+ void GetPath(WCHAR **ppwszPath);
+
+ ULONG AddRef(void);
+
+ ULONG Release(CStringList &sl);
+
+ inline void CheckSig() const
+ {
+ Win4Assert(_ulSig == STRINGSIG);
+ }
+ inline WCHAR * pwszPath() { return _pwszPath;}
+
+protected:
+
+#if DBG==1
+ ULONG _ulSig;
+#endif
+
+ ULONG _culRefs;
+
+ // Length of path in bytes stored in the object
+ // for faster copies
+ int _cPathBytes;
+
+ // Size of path in characters for faster allocation
+ int _cPath;
+
+ // Buffer big enough to store the path
+ WCHAR * _pwszPath;
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CStringID::~CStringID
+//
+// Synopsis: Destroy a sting object
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CStringID::~CStringID(void)
+{
+//
+// BUGBUG RAID #26403
+//
+// The Retail build OLE32.DLL on Chicago will abort in ScmMemFree on a
+// DllEntryPoint DetachProcess. This causes the M7 Chicago release to
+// hang.
+//
+
+// BillMo: since we no longer use static CStringID objects, this can be
+// freed now.
+
+ ScmMemFree(_pwszPath);
+
+#if DBG==1
+ _ulSig = 0xF4F5F6F7;
+#endif
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CStringID::AddRef
+//
+// Synopsis: Add to reference count
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline ULONG CStringID::AddRef(void)
+{
+ return ++_culRefs;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// MACRO: DECLARE_SAFE_SERVER_ENTRY
+//
+// Purpose: This defines a class that creates server entries from paths
+//
+// Parameters: nsafe - name of this class
+// nentry - name of entry class in list
+// nlist - name of instance of list of entries
+//
+// History: 22-Apr-93 Ricksa Created
+// 20-Oct-94 BillMo Demacroization
+//
+// Notes: This is used for the various server lists implemented in this
+// file. It makes it so there is only one place to change this
+// code that will be the same for all three classes.
+//
+// The copy constructor is used to allow creation of temporary
+// ClassData objects for the duration of scm calls.
+//
+//--------------------------------------------------------------------------
+#define DECLARE_SAFE_SERVER_ENTRY(nsafe, nentry, nlist) \
+class nsafe \
+{ \
+public: \
+ nsafe(const WCHAR *pwszPath, HRESULT &hr); \
+ \
+ nsafe(const nsafe &other); \
+ \
+ ~nsafe(void); \
+ \
+ operator nentry*(void); \
+ \
+ nentry * operator->(); \
+ \
+ BOOL Defined(void); \
+ \
+private: \
+ \
+ nentry * _p##nentry; \
+}; \
+ \
+inline nsafe::nsafe(const nsafe &other) : _p##nentry(other._p##nentry) \
+{ \
+ if (_p##nentry != NULL) \
+ _p##nentry->AddRef(); \
+} \
+ \
+ \
+inline nsafe::nsafe(const WCHAR *pwszPath, HRESULT &hr) \
+ : _p##nentry(NULL) \
+{ \
+ if (pwszPath != NULL) \
+ { \
+ _p##nentry = nlist.Add(pwszPath, hr); \
+ } \
+} \
+ \
+inline nsafe::~nsafe(void) \
+{ \
+ if (_p##nentry != NULL) \
+ { \
+ _p##nentry->Release(nlist); \
+ } \
+} \
+ \
+inline nsafe::operator nentry*(void) \
+{ \
+ return _p##nentry; \
+} \
+ \
+inline nentry *nsafe::operator->(void) \
+{ \
+ return _p##nentry; \
+} \
+ \
+inline BOOL nsafe::Defined(void) \
+{ \
+ return (_p##nentry != NULL); \
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CStringList
+//
+// Purpose: Implement class of list of all server paths of a particular
+//
+// Interface: Add - add or get a previously defined entry for the path
+//
+// History: 22-Apr-93 Ricksa Created
+// 20-Oct-94 BillMo Demacroisation
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CStringList : public CSkipList, public CScmAlloc
+{
+public:
+ CStringList(HRESULT &hr);
+
+ CStringID * Add(const WCHAR *pwszPath, HRESULT &hr);
+private:
+ CStringID _maxStringID;
+};
+
+
+inline CStringList::CStringList(HRESULT &hr) :
+ CSkipList((LPFNCOMPARE)(SkipListCompareStringIDs),
+ (LPFNDELETE)(SkipListDeleteStringID),
+ 0, // OFFSETBETWEEN is zero because
+ // CInProc is a CStringID etc
+ SKIPLIST_SHARED,
+ &_maxStringID, // NOTE! since the max key is kept as
+ // a reference, the fact that
+ // _maxStringID is not constructed until
+ // after CSkipList does not matter.
+ MAX_SERVER_CACHE,
+ hr),
+ _maxStringID(L"\xFFFF\xFFFF", hr)
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CLocalServer
+//
+// Purpose: Provide object for communication with a local server
+//
+// Interface: StartServer
+// RpcHandle
+// SetEndPoint
+// StopServer
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+class CLocSrvList;
+
+class CLocalServer : public CStringID
+{
+public:
+ // Creates object
+ CLocalServer(const WCHAR *pwszPath, HRESULT &hr);
+ ~CLocalServer();
+
+ // Starts object server if necessary
+ BOOL StartServer(CLSID &clsid,
+ WCHAR * pwszAppID,
+ CToken * pClientToken,
+ WCHAR * pwszWinstaDesktop,
+ HANDLE * phProcess,
+ WCHAR *pwszRunAsDomainName,
+ WCHAR *pwszRunAsUserName,
+ WCHAR* pwszSurrogateCmdLine,
+ BOOL fSurrogate);
+
+
+#ifndef _CHICAGO_
+ BOOL StartService(CLSID &clsid,
+ CToken * pClientToken,
+ WCHAR *pwszServiceArgs,
+ SC_HANDLE *phService);
+
+ // Starts RunAs object server if necessary
+ BOOL StartRunAsServer(CLSID &clsid,
+ WCHAR * pwszAppID,
+ HANDLE *phProcess,
+ CToken *pClientToken,
+ WCHAR *pwszRunAsDomainName,
+ WCHAR *pwszRunAsUserName,
+ WCHAR *pwszCommandLine,
+ BOOL fSurrogate);
+#endif
+
+ // Get exclusive access to this object
+#ifndef _CHICAGO_
+ void LockServer(void);
+ // Release exclusive access to the object
+ void UnlockServer(void);
+#endif
+
+ inline PSID GetRunAsSid() { return _pRunAsSid; }
+
+ ULONG Release(CLocSrvList &lsl);
+
+ inline void CheckSig() const
+ {
+ Win4Assert(_ulSig == LOCALSERVERSIG);
+ }
+
+private:
+
+#if DBG==1
+ ULONG _ulSig;
+#endif
+
+#ifndef _CHICAGO_
+ CMutexSem _mxsProcessStart;
+#endif
+
+ PSID _pRunAsSid;
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLocalServer::CLocalServer
+//
+// Synopsis: Create a local server object
+//
+// Arguments: [pwszPath] - path to local server object
+//
+// History: 21-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CLocalServer::CLocalServer(const WCHAR *pwszPath, HRESULT &hr)
+ : CStringID(pwszPath, hr),
+ _pRunAsSid(0)
+#if DBG==1
+ , _ulSig(LOCALSERVERSIG)
+#endif
+{
+ // Header & subobjects do all the work
+}
+
+
+inline CLocalServer::~CLocalServer()
+{
+#if DBG==1
+ _ulSig = 0xF1F2F3F4;
+#endif
+ if ( _pRunAsSid )
+ DeleteUserSid( _pRunAsSid );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLocalServer::LockServer
+//
+// Synopsis: Get exclusive access to the server object
+//
+// History: 05-Jan-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef _CHICAGO_
+inline void CLocalServer::LockServer(void)
+{
+ _mxsProcessStart.Request();
+}
+#endif
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLocalServer::UnlockServer
+//
+// Synopsis: Release exclusive access to the server object
+//
+// History: 05-Jan-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef _CHICAGO_
+inline void CLocalServer::UnlockServer(void)
+{
+ _mxsProcessStart.Release();
+}
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Class: CLocSrvList
+//
+// Purpose: List of local server objects
+//
+// Interface: Add
+//
+// History: 21-Apr-93 Ricksa Created
+//
+// Notes: See macro at beginning of this file for implementation
+//
+//--------------------------------------------------------------------------
+
+class CLocSrvList : public CSkipList, public CScmAlloc
+{
+public:
+ inline CLocSrvList(HRESULT &hr) :
+ CSkipList((LPFNCOMPARE)(SkipListCompareStringIDs),
+ (LPFNDELETE)(SkipListDeleteLocalServer),
+ OFFSETBETWEEN(CLocalServer, CStringID),
+ SKIPLIST_SHARED,
+ &_maxStringID, // NOTE! a pointer to _maxString
+ // is stored in CSkipList so
+ // initialization can occur
+ // after skip list
+ MAX_SERVER_CACHE,
+ hr),
+ _maxStringID(L"\xFFFF\xFFFF", hr) // this could be shared between
+ // this object and CStringLists
+ {
+ }
+
+ CLocalServer * Add(const WCHAR *pwszPath, HRESULT &hr);
+private:
+ CStringID _maxStringID; // x86 Windows : shared mem
+ // NT : private mem
+};
+
+inline CLocSrvList & GetCLocSrvList(void);
+DECLARE_SAFE_SERVER_ENTRY(CSafeLocalServer, CLocalServer, GetCLocSrvList())
+
+#endif // __CLSDATA_HXX__
+
+#endif
diff --git a/private/ole32/dcomss/olescm/daytona/makefile b/private/ole32/dcomss/olescm/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/dcomss/olescm/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/dcomss/olescm/daytona/sources b/private/ole32/dcomss/olescm/daytona/sources
new file mode 100644
index 000000000..6406beb15
--- /dev/null
+++ b/private/ole32/dcomss/olescm/daytona/sources
@@ -0,0 +1,96 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= olescm
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= ..\..\lib\daytona
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..;..\..\..\com\dcomidl\daytona;..\..\..\common;
+INCLUDES= $(INCLUDES);..\..\..\com\inc;..\..\..\com\rot;..\..;..\..\objex
+INCLUDES= $(INCLUDES);$(BASEDIR)\private\dcomidl\obj;$(BASEDIR)\private\inc
+
+!if $(386)
+C_DEFINES= \
+ $(C_DEFINES)
+!else
+C_DEFINES= \
+ -DWX86OLE $(C_DEFINES)
+!endif
+
+SOURCES= \
+ ..\array_fv.cxx \
+ ..\clckpath.cxx \
+ ..\cls.cxx \
+ ..\clsdata.cxx \
+ ..\dbgprt.cxx \
+ ..\init.cxx \
+ ..\port.cxx \
+ ..\rpcalloc.cxx \
+ ..\rotif.cxx \
+ ..\scmhash.cxx \
+ ..\scmrot.cxx \
+ ..\scmsvc.cxx \
+ ..\srothint.cxx \
+ ..\srvreg.cxx \
+ ..\scmif.cxx \
+ ..\dscmif.cxx \
+ ..\remactif.cxx \
+ ..\net.cxx \
+ ..\remact.cxx \
+ ..\dfsext.cxx \
+ irot_s.c \
+ scm_s.c \
+ scm_z.c \
+ dscm_s.c \
+ objsrv_c.c
+
+UMTYPE=console
+UMAPPL=
+UMTEST=
+
+NTPROFILEINPUT=yes
+
+!include ..\scmpre.inc
diff --git a/private/ole32/dcomss/olescm/dbgprt.cxx b/private/ole32/dcomss/olescm/dbgprt.cxx
new file mode 100644
index 000000000..dc32445f5
--- /dev/null
+++ b/private/ole32/dcomss/olescm/dbgprt.cxx
@@ -0,0 +1,156 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dbgprt.hxx
+//
+// Contents: Routines to make printing trace info for debugging easier
+//
+// History: 31-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <headers.cxx>
+
+#include <dbgprt.hxx>
+
+// This file only produces code for the debug version of the SCM
+
+#if DBG == 1
+
+//+-------------------------------------------------------------------------
+//
+// Function: FormatGuid
+//
+// Synopsis: Format a binary guid for display on debugger
+//
+// Arguments: [rguid] - guid to display
+// [pwszGuid] - where to put displayable form
+//
+// Returns: pointer to guid string
+//
+// History: 01-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+WCHAR *FormatGuid(const GUID& rguid, WCHAR *pwszGuid)
+{
+
+ wsprintf(pwszGuid, L"%08lX-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X",
+ rguid.Data1, rguid.Data2, rguid.Data3, (int) rguid.Data4[0],
+ (int) rguid.Data4[1], (int) rguid.Data4[2], (int) rguid.Data4[3],
+ (int) rguid.Data4[4], (int) rguid.Data4[5],
+ (int) rguid.Data4[6], (int) rguid.Data4[7]);
+
+ return pwszGuid;
+}
+
+
+
+void DbgPrintFileTime(char *pszDesc, FILETIME *pfiletime)
+{
+ CairoleDebugOut((DEB_SCM, "%s Low: %04X High: %04X\n",
+ pszDesc, pfiletime->dwLowDateTime, pfiletime->dwHighDateTime));
+}
+
+void DbgPrintGuid(char *pszDesc, const GUID *pguid)
+{
+ WCHAR aszGuidStr[48];
+
+ CairoleDebugOut((DEB_SCM, "%s %ws\n", pszDesc,
+ FormatGuid(*pguid, &aszGuidStr[0])));
+}
+
+void DbgPrintIFD(char *pszDesc, InterfaceData *pifd)
+{
+
+ if (pifd != NULL)
+ {
+ BYTE *pb = &pifd->abData[0];
+
+ CairoleDebugOut((DEB_SCM,
+ "%s Addr %04X Len: %04X Data: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
+ pszDesc, pifd, pifd->ulCntData, pb[0], pb[1], pb[2], pb[3],
+ pb[4], pb[5], pb[6], pb[7], pb[8], pb[9], pb[10], pb[11]));
+ }
+ else
+ {
+ CairoleDebugOut((DEB_SCM, "%s Addr %04X", pszDesc, pifd));
+ }
+}
+
+void DbgPrintMkIfList(char *pszDesc, MkInterfaceList **ppMkIFList)
+{
+ CairoleDebugOut((DEB_SCM, "%s Addr: %l04X Count: %04X\n",
+ pszDesc, *ppMkIFList, (*ppMkIFList)->dwSize));
+}
+
+void DbgPrintMnkEqBuf(char *pszDesc, MNKEQBUF *pmkeqbuf)
+{
+ GUID *pguid = (GUID *) &pmkeqbuf->abEqData[0];
+ WCHAR aszGuidStr[48];
+
+ CairoleDebugOut((DEB_SCM, "%s Addr %04X Len: %04X Clsid: %ws\n",
+ pszDesc, pmkeqbuf, pmkeqbuf->cdwSize,
+ FormatGuid(*pguid, &aszGuidStr[0])));
+}
+
+void DbgPrintRegIn(char *pszDesc, RegInput *pregin)
+{
+ CairoleDebugOut((DEB_SCM, "%s Count: %04X\n", pszDesc, pregin->dwSize));
+
+ // Loop printing the registrations
+ for (DWORD i = 0; i < pregin->dwSize; i++)
+ {
+ DbgPrintGuid("CLSID: ", &pregin->rginent[i].clsid);
+#ifdef DCOM
+ ULARGE_INTEGER *puint = (ULARGE_INTEGER *)&pregin->rginent[i].oxid;
+ CairoleDebugOut((DEB_SCM, "OXID: %08x %08x\n",
+ puint->HighPart, puint->LowPart));
+ DbgPrintGuid("IPID: ", &pregin->rginent[i].ipid);
+#else
+ CairoleDebugOut((DEB_SCM, "EndPoint: %ws\n",
+ pregin->rginent[i].pwszEndPoint));
+#endif
+ CairoleDebugOut((DEB_SCM, "Flags: %04X\n",
+ pregin->rginent[i].dwFlags));
+ }
+}
+
+void DbgPrintRegOut(char *pszDesc, RegOutput **ppreg)
+{
+ CairoleDebugOut((DEB_SCM, "%s Reg: %04X\n", pszDesc, *ppreg));
+
+ if (*ppreg)
+ {
+ for (DWORD i = 0; i < (*ppreg)->dwSize; i++)
+ {
+ CairoleDebugOut((DEB_SCM, "Reg: %04X\n",
+ (*ppreg)->regoutent[i].dwReg));
+ CairoleDebugOut((DEB_SCM, "AtStorage: %04X\n",
+ (*ppreg)->regoutent[i].dwAtStorage));
+ }
+ }
+}
+
+void DbgPrintRevokeClasses(char *pszDesc, RevokeClasses *prevcls)
+{
+ CairoleDebugOut((DEB_SCM, "%s Count: %04X\n", pszDesc, prevcls->dwSize));
+
+ // Loop printing the registrations
+ for (DWORD i = 0; i < prevcls->dwSize; i++)
+ {
+ DbgPrintGuid("CLSID: ", &prevcls->revent[i].clsid);
+ CairoleDebugOut((DEB_SCM, "Reg: %04X\n",
+ prevcls->revent[i].dwReg));
+ }
+}
+
+void DbgPrintScmRegKey(char *pszDesc, SCMREGKEY *psrkRegister)
+{
+ CairoleDebugOut((DEB_SCM, "%s EntryLoc: %04X ScmId: %04X\n", pszDesc,
+ psrkRegister->dwEntryLoc, psrkRegister->dwScmId));
+}
+
+
+#endif // DBG == 1
+
diff --git a/private/ole32/dcomss/olescm/dbgprt.hxx b/private/ole32/dcomss/olescm/dbgprt.hxx
new file mode 100644
index 000000000..c7cbbe218
--- /dev/null
+++ b/private/ole32/dcomss/olescm/dbgprt.hxx
@@ -0,0 +1,45 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dbgprt.hxx
+//
+// Contents: Routines to make printing trace info for debugging easier
+//
+// History: 31-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __DBGINFO_HXX__
+#define __DBGINFO_HXX__
+
+#include <scm.h>
+#include <irot.h>
+
+#if DBG == 1
+
+WCHAR *FormatGuid(const GUID& rguid, WCHAR *pwszGuid);
+
+void DbgPrintFileTime(char *pszDesc, FILETIME *pfiletime);
+
+void DbgPrintGuid(char *pszDesc, const GUID *pguid);
+
+void DbgPrintIFD(char *pszDesc, InterfaceData *pifdObject);
+
+void DbgPrintMkIfList(char *pszDesc, MkInterfaceList **ppMkIFList);
+
+void DbgPrintMnkEqBuf(char *pszDesc, MNKEQBUF *pmkeqbuf);
+
+void DbgPrintRegIn(char *pszDesc, RegInput *pregin);
+
+void DbgPrintRegOut(char *pszDesc, RegOutput **ppreg);
+
+void DbgPrintRevokeClasses(char *pszDesc, RevokeClasses *prevcls);
+
+void DbgPrintScmRegKey(char *pszDesc, SCMREGKEY *psrkRegister);
+
+#else
+
+#endif // DBG == 1
+
+#endif // __DBGINFO_HXX__
diff --git a/private/ole32/dcomss/olescm/dfsext.cxx b/private/ole32/dcomss/olescm/dfsext.cxx
new file mode 100644
index 000000000..6dc4c2e12
--- /dev/null
+++ b/private/ole32/dcomss/olescm/dfsext.cxx
@@ -0,0 +1,140 @@
+//+----------------------------------------------------------------------------
+//
+// Copyright (C) 1996, Microsoft Corporation
+//
+// File: dfsext.cxx
+//
+// Contents: Code to see if a path refers to a Dfs path.
+//
+// Classes: None
+//
+// Functions: TranslateDfsPath
+//
+// History: June 17, 1996 Milans Created
+//
+//-----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <dfsfsctl.h>
+
+NTSTATUS
+DfsFsctl(
+ IN HANDLE DfsHandle,
+ IN ULONG FsControlCode,
+ IN PVOID InputBuffer OPTIONAL,
+ IN ULONG InputBufferLength,
+ OUT PVOID OutputBuffer OPTIONAL,
+ IN OUT PULONG OutputBufferLength);
+
+NTSTATUS
+DfsOpen(
+ IN OUT PHANDLE DfsHandle);
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DfsOpen, private
+//
+// Synopsis: Opens a handle to the Dfs driver for fsctl purposes.
+//
+// Arguments: [DfsHandle] -- On successful return, contains handle to the
+// driver.
+//
+// Returns: NTSTATUS of attempt to open the Dfs driver.
+//
+//--------------------------------------------------------------------------
+NTSTATUS
+DfsOpen(
+ IN OUT PHANDLE DfsHandle)
+{
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES objectAttributes;
+ IO_STATUS_BLOCK ioStatus;
+ UNICODE_STRING name = {
+ sizeof(DFS_DRIVER_NAME)-sizeof(UNICODE_NULL),
+ sizeof(DFS_DRIVER_NAME)-sizeof(UNICODE_NULL),
+ DFS_DRIVER_NAME};
+
+ InitializeObjectAttributes(
+ &objectAttributes,
+ &name,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ status = NtCreateFile(
+ DfsHandle,
+ SYNCHRONIZE,
+ &objectAttributes,
+ &ioStatus,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ FILE_OPEN_IF,
+ FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0);
+
+ if (NT_SUCCESS(status))
+ status = ioStatus.Status;
+
+ return status;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DfsFsctl, public
+//
+// Synopsis: Fsctl's to the Dfs driver.
+//
+// Arguments: [DfsHandle] -- Handle to the Dfs driver, usually obtained by
+// calling DfsOpen.
+// [FsControlCode] -- The FSCTL code (see private\inc\dfsfsctl.h)
+// [InputBuffer] -- InputBuffer to the fsctl.
+// [InputBufferLength] -- Length, in BYTES, of InputBuffer
+// [OutputBuffer] -- OutputBuffer to the fsctl.
+// [OutputBufferLength] -- Length, in BYTES, of OutputBuffer
+//
+// Returns: NTSTATUS of Fsctl attempt.
+//
+//--------------------------------------------------------------------------
+NTSTATUS
+DfsFsctl(
+ IN HANDLE DfsHandle,
+ IN ULONG FsControlCode,
+ IN PVOID InputBuffer OPTIONAL,
+ IN ULONG InputBufferLength,
+ OUT PVOID OutputBuffer OPTIONAL,
+ IN OUT PULONG OutputBufferLength
+)
+{
+ NTSTATUS status;
+ IO_STATUS_BLOCK ioStatus;
+
+ status = NtFsControlFile(
+ DfsHandle,
+ NULL, // Event,
+ NULL, // ApcRoutine,
+ NULL, // ApcContext,
+ &ioStatus,
+ FsControlCode,
+ InputBuffer,
+ InputBufferLength,
+ OutputBuffer,
+ *OutputBufferLength
+ );
+
+ if(NT_SUCCESS(status))
+ status = ioStatus.Status;
+
+ if (status == STATUS_BUFFER_OVERFLOW)
+ *OutputBufferLength = *((PULONG) OutputBuffer);
+
+ return status;
+}
+
+
diff --git a/private/ole32/dcomss/olescm/dirs b/private/ole32/dcomss/olescm/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/dcomss/olescm/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/dcomss/olescm/dscmif.cxx b/private/ole32/dcomss/olescm/dscmif.cxx
new file mode 100644
index 000000000..325f24d6b
--- /dev/null
+++ b/private/ole32/dcomss/olescm/dscmif.cxx
@@ -0,0 +1,315 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995.
+//
+// File:
+// dscmif.cxx
+//
+// Contents:
+// Entry points for remote activation SCM interface.
+//
+// Functions:
+// SCMGetClassObject
+// SCMCreateInstance
+// SCMGetPersistentInstance
+//
+// History:
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include "obase.h"
+#include "rawdscm.h"
+#include "remact.h"
+#include "scm.hxx"
+#include "port.hxx"
+#include "cls.hxx"
+#include "clckpath.hxx"
+#include "dbgprt.hxx"
+
+HRESULT GetUserSidHelper(PSID *ppUserSid);
+void DeleteUserSid(PSID pUserSid);
+
+extern "C" HRESULT SCMGetClassObject(
+ handle_t hRpc,
+ ORPCTHIS * ORPCthis,
+ LOCALTHIS * Localthis,
+ ORPCTHAT * ORPCthat,
+ ACTIVATION_INFO * pActivationInfo,
+ IID * pIID,
+ long Apartment,
+ OXID * pOxidServer,
+ DUALSTRINGARRAY ** ppServerORBindings,
+ OXID_INFO * pOxidInfo,
+ MID * pLocalMidOfRemote,
+ MInterfacePointer **ppIDClassFactory
+ )
+{
+ ACTIVATION_PARAMS ActParams;
+ HRESULT DummyHr;
+
+ CheckLocalCall( hRpc );
+
+ if ( (ORPCthis->version.MajorVersion != COM_MAJOR_VERSION) ||
+ (ORPCthis->version.MinorVersion > COM_MINOR_VERSION) )
+ RpcRaiseException( RPC_E_VERSION_MISMATCH );
+
+ ActParams.hRpc = hRpc;
+ ActParams.ProcessSignature = (PVOID)pActivationInfo->ProcessSignature;
+ ActParams.pProcess = 0;
+ ActParams.pToken = 0;
+ ActParams.DynamicSecurity = pActivationInfo->bDynamicSecurity;
+
+ if ( pActivationInfo->pServerInfo )
+ {
+ ActParams.pAuthInfo = pActivationInfo->pServerInfo->pAuthInfo;
+ ActParams.pwszServer = pActivationInfo->pServerInfo->pwszName;
+ }
+ else
+ {
+ ActParams.pAuthInfo = 0;
+ ActParams.pwszServer = 0;
+ }
+
+ ActParams.MsgType = GETCLASSOBJECTEX;
+ ActParams.Clsid = pActivationInfo->Clsid;
+ ActParams.pwszWinstaDesktop = pActivationInfo->pwszWinstaDesktop;
+ ActParams.ClsContext = pActivationInfo->ClsContext;
+
+ ActParams.ORPCthis = ORPCthis;
+ ActParams.Localthis = Localthis;
+ ActParams.ORPCthat = ORPCthat;
+
+ ActParams.RemoteActivation = FALSE;
+
+ ActParams.Interfaces = 1;
+ ActParams.pIIDs = pIID;
+
+ ActParams.Mode = MODE_GET_CLASS_OBJECT;
+ ActParams.FileWasOpened = FALSE;
+ ActParams.pwszPath = 0;
+ ActParams.pIFDStorage = 0;
+
+ ActParams.pIFDROT = 0;
+
+ ActParams.Apartment = Apartment;
+ ActParams.pOxidServer = pOxidServer;
+ ActParams.ppServerORBindings = ppServerORBindings;
+ ActParams.pOxidInfo = pOxidInfo;
+ ActParams.pLocalMidOfRemote = pLocalMidOfRemote;
+
+ ActParams.FoundInROT = FALSE;
+ ActParams.ppIFD = ppIDClassFactory;
+ ActParams.pResults = &DummyHr;
+
+ return Activation( &ActParams );
+}
+
+extern "C" HRESULT SCMCreateInstance(
+ handle_t hRpc,
+ ORPCTHIS * ORPCthis,
+ LOCALTHIS * Localthis,
+ ORPCTHAT * ORPCthat,
+ ACTIVATION_INFO * pActivationInfo,
+ DWORD Interfaces,
+ IID * pIIDs,
+ long Apartment,
+ OXID * pOxidServer,
+ DUALSTRINGARRAY ** ppServerORBindings,
+ OXID_INFO * pOxidInfo,
+ MID * pLocalMidOfRemote,
+ MInterfacePointer **ppInterfaceData,
+ HRESULT * pResults
+ )
+{
+ ACTIVATION_PARAMS ActParams;
+
+ CheckLocalCall( hRpc );
+
+ if ( (ORPCthis->version.MajorVersion != COM_MAJOR_VERSION) ||
+ (ORPCthis->version.MinorVersion > COM_MINOR_VERSION) )
+ RpcRaiseException( RPC_E_VERSION_MISMATCH );
+
+ ActParams.hRpc = hRpc;
+ ActParams.ProcessSignature = (PVOID)pActivationInfo->ProcessSignature;
+ ActParams.pProcess = 0;
+ ActParams.pToken = 0;
+ ActParams.DynamicSecurity = pActivationInfo->bDynamicSecurity;
+
+ if ( pActivationInfo->pServerInfo )
+ {
+ ActParams.pAuthInfo = pActivationInfo->pServerInfo->pAuthInfo;
+ ActParams.pwszServer = pActivationInfo->pServerInfo->pwszName;
+ }
+ else
+ {
+ ActParams.pAuthInfo = 0;
+ ActParams.pwszServer = 0;
+ }
+
+ ActParams.MsgType = CREATEINSTANCEEX;
+ ActParams.Clsid = pActivationInfo->Clsid;
+ ActParams.pwszWinstaDesktop = pActivationInfo->pwszWinstaDesktop;
+ ActParams.ClsContext = pActivationInfo->ClsContext;
+
+ ActParams.ORPCthis = ORPCthis;
+ ActParams.Localthis = Localthis;
+ ActParams.ORPCthat = ORPCthat;
+
+ ActParams.RemoteActivation = FALSE;
+
+ ActParams.Interfaces = Interfaces;
+ ActParams.pIIDs = pIIDs;
+
+ ActParams.Mode = 0;
+ ActParams.FileWasOpened = FALSE;
+ ActParams.pwszPath = 0;
+ ActParams.pIFDStorage = 0;
+
+ ActParams.pIFDROT = 0;
+
+ ActParams.Apartment = Apartment;
+ ActParams.pOxidServer = pOxidServer;
+ ActParams.ppServerORBindings = ppServerORBindings;
+ ActParams.pOxidInfo = pOxidInfo;
+ ActParams.pLocalMidOfRemote = pLocalMidOfRemote;
+
+ ActParams.FoundInROT = FALSE;
+ ActParams.ppIFD = ppInterfaceData;
+ ActParams.pResults = pResults;
+
+ return Activation( &ActParams );
+}
+
+extern "C" HRESULT SCMGetPersistentInstance(
+ handle_t hRpc,
+ ORPCTHIS * ORPCthis,
+ LOCALTHIS * Localthis,
+ ORPCTHAT * ORPCthat,
+ ACTIVATION_INFO * pActivationInfo,
+ WCHAR * pwszPath,
+ MInterfacePointer * pIFDStorage,
+ DWORD FileMode,
+ BOOL FileWasOpened,
+ DWORD Interfaces,
+ IID * pIIDs,
+ long Apartment,
+ OXID * pOxidServer,
+ DUALSTRINGARRAY ** ppServerORBindings,
+ OXID_INFO * pOxidInfo,
+ MID * pLocalMidOfRemote,
+ BOOL * pFoundInROT,
+ MInterfacePointer ** ppInterfaceData,
+ HRESULT * pResults
+ )
+{
+ ACTIVATION_PARAMS ActParams;
+ HRESULT hr;
+
+ CheckLocalCall( hRpc );
+
+ if ( (ORPCthis->version.MajorVersion != COM_MAJOR_VERSION) ||
+ (ORPCthis->version.MinorVersion > COM_MINOR_VERSION) )
+ RpcRaiseException( RPC_E_VERSION_MISMATCH );
+
+ *pFoundInROT = FALSE;
+
+ ActParams.hRpc = hRpc;
+ ActParams.ProcessSignature = (PVOID)pActivationInfo->ProcessSignature;
+ ActParams.pProcess = 0;
+ ActParams.pToken = 0;
+ ActParams.DynamicSecurity = pActivationInfo->bDynamicSecurity;
+
+ if ( pActivationInfo->pServerInfo )
+ {
+ ActParams.pAuthInfo = pActivationInfo->pServerInfo->pAuthInfo;
+ ActParams.pwszServer = pActivationInfo->pServerInfo->pwszName;
+ }
+ else
+ {
+ ActParams.pAuthInfo = 0;
+ ActParams.pwszServer = 0;
+ }
+
+ ActParams.MsgType = GETPERSISTENTEX;
+ ActParams.Clsid = pActivationInfo->Clsid;
+ ActParams.pwszWinstaDesktop = pActivationInfo->pwszWinstaDesktop;
+ ActParams.ClsContext = pActivationInfo->ClsContext;
+
+ ActParams.ORPCthis = ORPCthis;
+ ActParams.Localthis = Localthis;
+ ActParams.ORPCthat = ORPCthat;
+
+ ActParams.RemoteActivation = FALSE;
+
+ ActParams.Interfaces = Interfaces;
+ ActParams.pIIDs = pIIDs;
+
+ ActParams.Mode = FileMode;
+ ActParams.FileWasOpened = FileWasOpened;
+ ActParams.pwszPath = pwszPath;
+ ActParams.pIFDStorage = pIFDStorage;
+
+ ActParams.pIFDROT = 0;
+
+ ActParams.Apartment = Apartment;
+ ActParams.pOxidServer = pOxidServer;
+ ActParams.ppServerORBindings = ppServerORBindings;
+ ActParams.pOxidInfo = pOxidInfo;
+ ActParams.pLocalMidOfRemote = pLocalMidOfRemote;
+
+ ActParams.FoundInROT = FALSE;
+ ActParams.ppIFD = ppInterfaceData;
+ ActParams.pResults = pResults;
+
+ hr = Activation( &ActParams );
+
+ *pFoundInROT = ActParams.FoundInROT;
+
+ if ( ActParams.pIFDROT )
+ MIDL_user_free( ActParams.pIFDROT );
+
+ return hr;
+}
+
+extern "C" HRESULT DummyQueryInterfaceIDSCM(
+ handle_t hRpc,
+ ORPCTHIS *orpcthis,
+ LOCALTHIS *localthis,
+ ORPCTHAT *orpcthat,
+ DWORD dummy )
+{
+ CairoleDebugOut((DEB_ERROR, "DSCM Dummy function should never be called!\n"));
+ orpcthat->flags = 0;
+ orpcthat->extensions = NULL;
+ return E_FAIL;
+}
+
+extern "C" HRESULT DummyAddRefIDSCM(
+ handle_t hRpc,
+ ORPCTHIS *orpcthis,
+ LOCALTHIS *localthis,
+ ORPCTHAT *orpcthat,
+ DWORD dummy )
+{
+ CairoleDebugOut((DEB_ERROR, "DSCM Dummy function should never be called!\n"));
+ orpcthat->flags = 0;
+ orpcthat->extensions = NULL;
+ return E_FAIL;
+}
+
+extern "C" HRESULT DummyReleaseIDSCM(
+ handle_t hRpc,
+ ORPCTHIS *orpcthis,
+ LOCALTHIS *localthis,
+ ORPCTHAT *orpcthat,
+ DWORD dummy )
+{
+ CairoleDebugOut((DEB_ERROR, "DSCM Dummy function should never be called!\n"));
+ orpcthat->flags = 0;
+ orpcthat->extensions = NULL;
+ return E_FAIL;
+}
diff --git a/private/ole32/dcomss/olescm/headers.cxx b/private/ole32/dcomss/olescm/headers.cxx
new file mode 100644
index 000000000..07ead14d7
--- /dev/null
+++ b/private/ole32/dcomss/olescm/headers.cxx
@@ -0,0 +1,48 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: headers.cxx
+//
+// Contents: scm precompiled headers
+//
+// Classes:
+//
+// Functions:
+//
+// History: 11-Oct-94 BillMo Created
+//
+//----------------------------------------------------------------------------
+
+#include "..\dcomss.h"
+
+extern "C"
+{
+#include <ntlsa.h>
+#include <ntmsv1_0.h>
+#ifdef DCOM
+#include <lm.h>
+#endif
+#include <winsecp.h>
+#include <stdio.h>
+#include <memory.h>
+#include <string.h>
+}
+
+#ifndef _CHICAGO_
+#include <netevent.h>
+#endif
+
+#include <except.hxx>
+#include <ole2.h>
+#include <olecom.h>
+#include <smmutex.hxx>
+#include <scode.h>
+#include <ole2int.h>
+#include <tchar.h>
+#ifdef DCOM
+#include <rwobjsrv.h>
+#else
+#include <objsrv.h>
+#endif
diff --git a/private/ole32/dcomss/olescm/init.cxx b/private/ole32/dcomss/olescm/init.cxx
new file mode 100644
index 000000000..839710ddf
--- /dev/null
+++ b/private/ole32/dcomss/olescm/init.cxx
@@ -0,0 +1,1448 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: init.cxx
+//
+// Contents: functions to load cache from registry
+//
+// Functions: HexStringToDword
+// GUIDFromString
+// get_reg_value
+// LoadClassCache
+//
+// History: 22-Apr-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+// 03-Jan-95 BillMo Added impl for StringFromGUID2 so
+// we don't link to ole32.dll
+// 11-Sep-95 MurthyS Removed StringFromGUID2...use from
+// common.lib instead
+// 07-Dec-95 BruceMa Add RunAs support
+// 12-Jan-96 BruceMa Add per-user registry support
+//
+//--------------------------------------------------------------------------
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <scm.hxx>
+#include "port.hxx"
+#include <scm.h>
+#include "cls.hxx"
+#include "compname.hxx"
+#include "init.hxx"
+extern "C"
+{
+#include <userenv.h>
+}
+
+//
+// global keys that are opened during initialization
+//
+
+HKEY g_hkClsID = 0;
+HKEY g_hkAppID = 0;
+
+extern WCHAR wszSOFTWAREClassesCLSID[1];
+WCHAR wszLocalServer16[] = L"LocalServer";
+static WCHAR wszLocalServer[] = L"LocalServer32";
+static WCHAR wszService[] = L"LocalService";
+static WCHAR wszRunAs[] = L"RunAs";
+static WCHAR wszShared[] = L"Shared";
+static WCHAR wszAppIDName[] = L"AppID";
+
+extern WCHAR wszInProcServer[] = L"InProcServer32";
+
+//
+// Threading Model Registry Constants
+//
+
+static TCHAR tszDllThreadModel[] = TEXT("ThreadingModel");
+static TCHAR tszAptModel[] = TEXT("Apartment");
+static TCHAR tszBothModel[] = TEXT("Both");
+static TCHAR wszFreeModel[] = TEXT("Free");
+
+WCHAR wszActivateAtStorage[] = L"ActivateAtStorage";
+WCHAR wszRemoteServerName[] = L"RemoteServerName";
+WCHAR wszErrorControl[] = L"ErrorControl";
+WCHAR wszServiceParameters[] = L"ServiceParameters";
+WCHAR wszLaunchPermission[] = L"LaunchPermission";
+WCHAR wszServicesKey[] = L"SYSTEM\\CurrentControlSet\\Services";
+
+TCHAR tszOLE2[] = TEXT("SOFTWARE\\Microsoft\\OLE2");
+
+//+-------------------------------------------------------------------
+//
+// Function: GetRegistrySecDesc, internal
+//
+// Synopsis: Convert a security descriptor from self relative to
+// absolute form. Stuff in an owner and a group.
+//
+// Notes: REGDB_E_INVALIDVALUE is returned when there is something
+// at the specified value, but it is not a security descriptor.
+//
+// This is ALMOST the same as the routine by the same name in com\dcomrem,
+// but it uses ScmMemAlloc instead of PrivMemAlloc
+//
+//--------------------------------------------------------------------
+HRESULT GetRegistrySecDesc( HKEY hKey, WCHAR *pValue,
+ SECURITY_DESCRIPTOR **pSD )
+
+{
+ SID *pGroup;
+ SID *pOwner;
+ DWORD cbSD;
+ DWORD lType;
+ HRESULT hr;
+
+ // Find put how much memory to allocate for the security
+ // descriptor.
+ cbSD = 0;
+ *pSD = NULL;
+ hr = RegQueryValueEx( hKey, pValue, NULL, &lType, NULL, &cbSD );
+ if (hr != ERROR_SUCCESS)
+ return MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, hr );
+ if (lType != REG_BINARY || cbSD < sizeof(SECURITY_DESCRIPTOR))
+ return REGDB_E_INVALIDVALUE;
+
+ // Allocate memory for the security descriptor plus the owner and
+ // group SIDs.
+ *pSD = (SECURITY_DESCRIPTOR *) ScmMemAlloc( cbSD );
+ if (*pSD == NULL)
+ return E_OUTOFMEMORY;
+
+ // Read the security descriptor.
+ hr = RegQueryValueEx( hKey, pValue, NULL, &lType, (unsigned char *) *pSD,
+ &cbSD );
+ if (hr != ERROR_SUCCESS)
+ return MAKE_SCODE( SEVERITY_ERROR, FACILITY_WIN32, hr );
+ if (lType != REG_BINARY)
+ return REGDB_E_INVALIDVALUE;
+
+ // Fix up the security descriptor.
+ (*pSD)->Control &= ~SE_SELF_RELATIVE;
+ (*pSD)->Sacl = NULL;
+ if ((*pSD)->Dacl != NULL)
+ {
+ if (cbSD < sizeof(ACL) + sizeof(SECURITY_DESCRIPTOR) ||
+ (ULONG) (*pSD)->Dacl > cbSD - sizeof(ACL))
+ return REGDB_E_INVALIDVALUE;
+ (*pSD)->Dacl = (ACL *) (((char *) *pSD) + ((ULONG) (*pSD)->Dacl));
+ if ((*pSD)->Dacl->AclSize + sizeof(SECURITY_DESCRIPTOR) > cbSD)
+ return REGDB_E_INVALIDVALUE;
+ }
+
+ // Set up the owner and group SIDs.
+ if ((*pSD)->Group == 0 || ((ULONG) (*pSD)->Group) + sizeof(SID) > cbSD ||
+ (*pSD)->Owner == 0 || ((ULONG) (*pSD)->Owner) + sizeof(SID) > cbSD)
+ return REGDB_E_INVALIDVALUE;
+ (*pSD)->Group = (SID *) (((BYTE *) *pSD) + (ULONG) (*pSD)->Group);
+ (*pSD)->Owner = (SID *) (((BYTE *) *pSD) + (ULONG) (*pSD)->Owner);
+
+ // Check the security descriptor.
+#if DBG==1
+ if (!IsValidSecurityDescriptor( *pSD ))
+ return REGDB_E_INVALIDVALUE;
+#endif
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HexStringToDword
+//
+// Synopsis: Convert a character string hex digits to a DWORD
+//
+// Arguments: [lpsz] - string to convert
+// [Value] - where to put the value
+// [cDigits] - number of digits expected
+// [chDelim] - delimiter for end of string
+//
+// Returns: TRUE - string converted to a DWORD
+// FALSE - string could not be converted
+//
+// Algorithm: For each digit in the string, shift the value and
+// add the value of the digit to the output value. When
+// all the digits are processed, if a delimiter is
+// provided, make sure the last character is the delimiter.
+//
+// History: 22-Apr-93 Ricksa Created
+//
+// Notes: Lifted from CairOLE sources so that SCM will have no
+// dependency on compobj.dll.
+//
+//--------------------------------------------------------------------------
+
+#if !defined(_CHICAGO_)
+BOOL HexStringToDword(
+ LPCWSTR FAR& lpsz,
+ DWORD FAR& Value,
+ int cDigits,
+ WCHAR chDelim)
+{
+ int Count;
+
+ Value = 0;
+
+ for (Count = 0; Count < cDigits; Count++, lpsz++)
+ {
+ if (*lpsz >= '0' && *lpsz <= '9')
+ {
+ Value = (Value << 4) + *lpsz - '0';
+ }
+ else if (*lpsz >= 'A' && *lpsz <= 'F')
+ {
+ Value = (Value << 4) + *lpsz - 'A' + 10;
+ }
+ else if (*lpsz >= 'a' && *lpsz <= 'f')
+ {
+ Value = (Value << 4) + *lpsz - 'a' + 10;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+
+ if (chDelim != 0)
+ {
+ return *lpsz++ == chDelim;
+ }
+
+ return TRUE;
+}
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Function: GUIDFromString
+//
+// Synopsis: Convert a string in Registry to a GUID.
+//
+// Arguments: [lpsz] - string from registry
+// [pguid] - where to put the guid.
+//
+// Returns: TRUE - GUID conversion successful
+// FALSE - GUID conversion failed.
+//
+// Algorithm: Convert each part of the GUID string to the
+// appropriate structure member in the guid using
+// HexStringToDword. If all conversions work return
+// TRUE.
+//
+// History: 22-Apr-93 Ricksa Created
+//
+// Notes: Lifted from CairOLE sources so that SCM will have no
+// dependency on compobj.dll.
+//
+//--------------------------------------------------------------------------
+
+#if !defined(_CHICAGO_)
+BOOL GUIDFromString(LPCWSTR lpsz, LPGUID pguid)
+{
+ DWORD dw;
+
+ if (*lpsz++ != '{')
+ {
+ return FALSE;
+ }
+
+ if (!HexStringToDword(lpsz, pguid->Data1, sizeof(DWORD)*2, '-'))
+ {
+ return FALSE;
+ }
+
+ if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
+ {
+ return FALSE;
+ }
+
+ pguid->Data2 = (WORD)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
+ {
+ return FALSE;
+ }
+
+ pguid->Data3 = (WORD)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ {
+ return FALSE;
+ }
+
+ pguid->Data4[0] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '-'))
+ {
+ return FALSE;
+ }
+
+ pguid->Data4[1] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ {
+ return FALSE;
+ }
+
+ pguid->Data4[2] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ {
+ return FALSE;
+ }
+
+ pguid->Data4[3] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ {
+ return FALSE;
+ }
+
+ pguid->Data4[4] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ {
+ return FALSE;
+ }
+
+ pguid->Data4[5] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ {
+ return FALSE;
+ }
+
+ pguid->Data4[6] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, /*(*/ '}'))
+ {
+ return FALSE;
+ }
+
+ pguid->Data4[7] = (BYTE)dw;
+
+ return TRUE;
+}
+
+#endif
+
+//+-------------------------------------------------------------------
+//
+// Member: CAppIDData::CAppIDData
+//
+// Synopsis: init.
+//
+//
+//--------------------------------------------------------------------
+CAppIDData::CAppIDData()
+{
+ dwSaveErr = 0;
+
+ pwszRemoteServerName = NULL;
+
+ pSD = NULL;
+
+ fHasService = FALSE;
+ pwszLocalService = NULL;
+ pwszServiceArgs = NULL;
+ pwszRunAsUserName = NULL;
+ pwszRunAsDomainName = NULL;
+
+ fHasRemoteServerName = 0;
+ fHasService = FALSE;
+ fActivateAtStorage = FALSE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CClassRegistryReader::~CClassRegistryReader
+//
+// Synopsis: Close the registry at root of all classes and
+// free stuff.
+//
+//--------------------------------------------------------------------
+CAppIDData::~CAppIDData()
+{
+ //
+ // All allocated data is inherited by CClassData and thereafter owned
+ // and later freed by the CClassData class. Upon failure of the
+ // CClassData constructor, the CAppIDData::Cleanup method is called to
+ // free allocated data.
+ //
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CAppIDData::Cleanup
+//
+// Synopsis: Free allocated data. Should be called only if CClassData new
+// fails.
+//
+//
+//--------------------------------------------------------------------
+void
+CAppIDData::Cleanup()
+{
+ if ( pwszRemoteServerName )
+ {
+ ScmMemFree( pwszRemoteServerName );
+ pwszRemoteServerName = 0;
+ }
+ if ( pwszLocalService )
+ {
+ ScmMemFree( pwszLocalService );
+ pwszLocalService = 0;
+ }
+ if ( pwszServiceArgs )
+ {
+ ScmMemFree( pwszServiceArgs );
+ pwszServiceArgs = 0;
+ }
+ if ( pwszRunAsUserName )
+ {
+ ScmMemFree( pwszRunAsUserName );
+ pwszRunAsUserName = 0;
+ }
+ if ( pwszRunAsDomainName )
+ {
+ ScmMemFree( pwszRunAsDomainName );
+ pwszRunAsDomainName = 0;
+ }
+ if ( pSD )
+ {
+ ScmMemFree( pSD );
+ pSD = 0;
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CClassRegistryReader::CClassRegistryReader
+//
+// Synopsis: Open the registry at root of all classes and init.
+//
+// Notes: Sets errClsReg with result of RegOpenKeyEx.
+//
+//--------------------------------------------------------------------
+
+CClassRegistryReader::CClassRegistryReader()
+{
+ cName = sizeof(awName);
+ iSubKey = 0;
+ dwSaveErr = 0;
+#ifdef DCOM
+ // NT 5.0 _fShared = TRUE;
+#endif // DCOM
+ pwszLocalServer = awcsLocalServer;
+ lLocalServer = sizeof(awcsLocalServer);
+ pwszAppID = awcsAppID;
+ lAppID = sizeof(awcsAppID);
+ pAppIDData = NULL;
+
+ #ifdef _CHICAGO_
+ errClsReg = RegOpenKeyExA(HKEY_CLASSES_ROOT, tszCLSID , NULL, KEY_READ, &hClsReg);
+ #endif //_CHICAGO_
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CClassRegistryReader::~CClassRegistryReader
+//
+// Synopsis: Close the registry at root of all classes and
+// free stuff.
+//
+//--------------------------------------------------------------------
+
+CClassRegistryReader::~CClassRegistryReader()
+{
+#ifdef _CHICAGO_
+ if (errClsReg == ERROR_SUCCESS)
+ RegCloseKey(hClsReg);
+#endif
+
+ if (pwszLocalServer != awcsLocalServer)
+ {
+ ScmMemFree(pwszLocalServer);
+ }
+
+ if ( pAppIDData )
+ {
+ delete pAppIDData;
+ }
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CClassRegistryReader::InitInner
+//
+// Synopsis: Reinitialize the variables used by the loop in
+// LoadClassCache.
+//
+//--------------------------------------------------------------------
+
+void
+CClassRegistryReader::InitInner(void)
+{
+ lDebug = sizeof(awcsDebug);
+ fHasLocalServer = 0;
+ f16Bit = FALSE;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: QueryStripRegValue
+//
+// Synopsis: Get the DLL information for a 32 bit DLL and
+// strip off any leading and trailing "
+//
+// Arguments: [hkey] - class handle
+// [pwszSubKey] - key to open
+// [pwszValue] - where to return data
+// [pcbValue] - length of above buffer in bytes
+//
+// Returns: ERROR_SUCCESS - read DLL path information
+// Other - registry entries could not be found
+//
+// Algorithm: Read the value requested.
+// If first character is not ", exit
+// Otherwise, copy data after quote to beginning of buffer.
+//
+//
+// History: 05-Jan-94 BillMo Created
+// 26-Sep-95 BruceMa Support environment variable expansion
+// for shell viewers
+//
+//--------------------------------------------------------------------------
+
+LONG
+QueryStripRegValue(HKEY hkey, // handle of key to query
+ LPCWSTR pwszSubKey, // address of name of subkey to query
+ LPWSTR pwszValue, // address of buffer for returned string
+ PLONG pcbValue) // address of buffer for size of returned string
+{
+ HKEY hSubKey;
+ DWORD dwType;
+ LONG lErr;
+
+ Win4Assert(pwszValue != NULL);
+ Win4Assert(pcbValue != NULL);
+
+ // Open the subkey
+ lErr = RegOpenKeyEx(hkey, pwszSubKey, NULL, KEY_READ, &hSubKey);
+
+ // Read the value into the user's buffer
+ if (lErr == ERROR_SUCCESS)
+ {
+ lErr = RegQueryValueEx(hSubKey, NULL , NULL, &dwType,
+ (BYTE *) pwszValue, (ULONG *) pcbValue);
+ if (lErr == ERROR_SUCCESS)
+ {
+ WCHAR *pwszScan = pwszValue; // used to scan along string
+ WCHAR *pwszDest = pwszValue; // used as destination when copying
+
+ // if the name is quoted then ...
+ if (*pwszScan == L'\"')
+ {
+ pwszScan++;
+
+ // copy all non-quote characters down to base of buffer
+ // until end of quoted string
+ while (*pwszScan != L'\0' && *pwszScan != L'\"')
+ {
+ *pwszDest++ = *pwszScan++;
+ }
+
+ // terminate string and get length in bytes including nul
+ *pwszDest++ = L'\0';
+ *pcbValue = (pwszDest - pwszValue) * sizeof(WCHAR);
+ }
+
+ // find first non-white space character
+ pwszScan = pwszValue;
+ while (*pwszScan) {
+ USHORT CharType[1];
+
+ GetStringTypeW (CT_CTYPE1, pwszScan, 1, CharType);
+ if ((CharType[0] & C1_SPACE) == 0) {
+ break;
+ }
+ pwszScan++;
+ }
+
+ // if there are no non-white space characters this will be true
+ if (*pwszScan == L'\0')
+ {
+ lErr = ERROR_FILE_NOT_FOUND;
+ *pcbValue = 0;
+ }
+
+ // Chicago does not support ExpandEnvironmentStrings
+#ifndef _CHICAGO_
+ // If the value type is REG_EXPAND_SZ then do environment variable
+ // expansion
+ if (dwType == REG_EXPAND_SZ)
+ {
+ // Expand any embedded environemnt variable expressions
+ WCHAR wszTemp[MAX_PATH];
+
+ lstrcpyW(wszTemp, pwszValue);
+ *pcbValue = ExpandEnvironmentStrings(wszTemp, pwszValue,
+ MAX_PATH);
+ }
+#endif // !_CHICAGO_
+ }
+
+ RegCloseKey(hSubKey);
+ }
+ return lErr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: QueryStripRegNamedValue
+//
+// Synopsis: Get the DLL information for a 32 bit DLL and
+// strip off any leading and trailing "
+//
+// Arguments: [hkey] - class handle
+// [pwszSubKey] - named value to open
+// [pwszValue] - where to return data
+// [pcbValue] - length of above buffer in bytes
+//
+// Returns: ERROR_SUCCESS - read DLL path information
+// Other - registry entries could not be found
+//
+// Algorithm: Read the value requested.
+// If first character is not ", exit
+// Otherwise, copy data after quote to beginning of buffer.
+//
+//
+// History: 05-Jan-94 BillMo Created
+// 26-Sep-95 BruceMa Support environment variable expansion
+// for shell viewers
+//
+//--------------------------------------------------------------------------
+
+LONG
+QueryStripRegNamedValue(HKEY hkey, // handle of key to query
+ LPCWSTR pwszSubKey, // address of name of value to query
+ LPWSTR pwszValue, // address of buffer for returned string
+ PLONG pcbValue,
+ BOOL* pfValueRead) // whether or not a value was read ) // address of buffer for size of returned string
+{
+ DWORD dwType;
+ LONG lErr;
+
+ Win4Assert(pwszValue != NULL);
+ Win4Assert(pcbValue != NULL);
+
+ // Read the value into the user's buffer
+ lErr = RegQueryValueEx(hkey, pwszSubKey , NULL, &dwType,
+ (BYTE *) pwszValue, (ULONG *) pcbValue);
+ if (*pfValueRead =(lErr == ERROR_SUCCESS))
+ {
+ WCHAR *pwszScan = pwszValue; // used to scan along string
+ WCHAR *pwszDest = pwszValue; // used as destination when copying
+
+ // if the name is quoted then ...
+ if (*pwszScan == L'\"')
+ {
+ pwszScan++;
+
+ // copy all non-quote characters down to base of buffer
+ // until end of quoted string
+ while (*pwszScan != L'\0' && *pwszScan != L'\"')
+ {
+ *pwszDest++ = *pwszScan++;
+ }
+
+ // terminate string and get length in bytes including nul
+ *pwszDest++ = L'\0';
+ *pcbValue = (pwszDest - pwszValue) * sizeof(WCHAR);
+ }
+
+ // find first non-white space character
+ pwszScan = pwszValue;
+ while (*pwszScan) {
+ USHORT CharType[1];
+
+ GetStringTypeW (CT_CTYPE1, pwszScan, 1, CharType);
+ if ((CharType[0] & C1_SPACE) == 0) {
+ break;
+ }
+ pwszScan++;
+ }
+
+ // if there are no non-white space characters this will be true
+ if (*pwszScan == L'\0')
+ {
+ lErr = ERROR_FILE_NOT_FOUND;
+ *pcbValue = 0;
+ }
+
+ // Chicago does not support ExpandEnvironmentStrings
+#ifndef _CHICAGO_
+ // If the value type is REG_EXPAND_SZ then do environment variable
+ // expansion
+ if (dwType == REG_EXPAND_SZ)
+ {
+ // Expand any embedded environemnt variable expressions
+ WCHAR wszTemp[MAX_PATH];
+
+ lstrcpyW(wszTemp, pwszValue);
+ *pcbValue = ExpandEnvironmentStrings(wszTemp, pwszValue,
+ MAX_PATH);
+ }
+#endif // !_CHICAGO_
+ }
+
+ return lErr;
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CAppIDData::ReadEntries
+//
+// Synopsis: Set the state of this object by reading the
+// registry entry given by contents of awName.
+//
+//--------------------------------------------------------------------
+LONG
+CAppIDData::ReadEntries( LPOLESTR pwszAppID )
+{
+ HKEY hkThisAppID;
+ WCHAR wszYN[16];
+ WCHAR wszRemoteServer[MAX_COMPUTERNAME_LENGTH+1];
+ LONG lSize;
+ LONG lRemoteServerName;
+ DWORD dwType;
+
+ // first get open the correct AppID key
+ err = RegOpenKeyEx( g_hkAppID,
+ pwszAppID,
+ 0,
+ KEY_READ,
+ &hkThisAppID );
+
+ if ( err != ERROR_SUCCESS )
+ {
+ dwSaveErr = err;
+ return err;
+ }
+
+ // Look for the "RunAs" key
+ WCHAR wszDomainUser[256];
+ ULONG dwSize = sizeof( wszDomainUser );
+ UINT cCh;
+ BOOL fReadValue;
+
+ if (RegQueryValueEx(hkThisAppID,
+ wszRunAs,
+ NULL,
+ NULL,
+ (LPBYTE)wszDomainUser,
+ &dwSize)
+ == ERROR_SUCCESS)
+ {
+ // Parse the domain
+ for (cCh = 0;
+ wszDomainUser[cCh] && wszDomainUser[cCh] != L'\\';
+ cCh++)
+ {
+ }
+
+ // If no domain specified, use the computer name
+ if (wszDomainUser[cCh] == L'\0')
+ {
+ CComputerName compName;
+
+ cCh = lstrlenW(compName.GetComputerName()) + 1;
+ pwszRunAsDomainName = (WCHAR *) ScmMemAlloc(cCh
+ * sizeof(WCHAR));
+ if (pwszRunAsDomainName == NULL)
+ {
+ err = E_OUTOFMEMORY;
+ goto cleanup_and_exit;
+ }
+ memcpy(pwszRunAsDomainName, compName.GetComputerName(),
+ cCh * sizeof(WCHAR));
+ cCh = 0;
+ }
+
+ // Else save the specified domain
+ else
+ {
+ pwszRunAsDomainName = (WCHAR *) ScmMemAlloc((cCh + 1)
+ * sizeof(WCHAR));
+ if (pwszRunAsDomainName == NULL)
+ {
+ err = E_OUTOFMEMORY;
+ goto cleanup_and_exit;
+ }
+ wszDomainUser[cCh++] = L'\0';
+ memcpy(pwszRunAsDomainName, wszDomainUser, 2 * cCh);
+ }
+
+ // Check for user name.
+ if ( (dwSize / 2) - cCh > 1 )
+ {
+ pwszRunAsUserName = (WCHAR *) ScmMemAlloc((dwSize/2 - cCh)
+ * sizeof(WCHAR));
+ if (pwszRunAsUserName == NULL)
+ {
+ err = E_OUTOFMEMORY;
+ goto cleanup_and_exit;
+ }
+ memcpy(pwszRunAsUserName, &wszDomainUser[cCh], dwSize - 2 * cCh);
+ }
+ else
+ {
+ ScmMemFree(pwszRunAsDomainName);
+ pwszRunAsDomainName = 0;
+ }
+ }
+
+ lSize = sizeof(wszYN);
+ err = QueryStripRegNamedValue(
+ hkThisAppID,
+ wszActivateAtStorage,
+ wszYN,
+ &lSize,
+ &fReadValue);
+
+ if ( (err == ERROR_SUCCESS) &&
+ ((wszYN[0] == 'Y') || (wszYN[0] == 'y')) )
+ {
+ fActivateAtStorage = TRUE;
+ }
+
+ lRemoteServerName = sizeof(wszRemoteServer);
+
+ err = QueryStripRegNamedValue(
+ hkThisAppID,
+ wszRemoteServerName,
+ wszRemoteServer,
+ &lRemoteServerName,
+ &fReadValue);
+
+ if (err == ERROR_SUCCESS)
+ {
+ fHasRemoteServerName = TRUE;
+ pwszRemoteServerName = (WCHAR *)ScmMemAlloc((lstrlenW(wszRemoteServer)+1)*sizeof(WCHAR));
+ lstrcpyW( pwszRemoteServerName, wszRemoteServer );
+ }
+ else if (err == ERROR_MORE_DATA)
+ {
+ pwszRemoteServerName = (WCHAR *)ScmMemAlloc(lRemoteServerName);
+ if (pwszRemoteServerName == NULL)
+ {
+ err =(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup_and_exit;
+ }
+
+ err = QueryStripRegNamedValue(
+ hkThisAppID,
+ wszRemoteServerName,
+ pwszRemoteServerName,
+ &lRemoteServerName,
+ &fReadValue);
+
+ if (err != ERROR_SUCCESS)
+ {
+ CairoleDebugOut((DEB_IWARN, "Unexpected error from RegQueryValue: (local server 32) %x, %d\n", err, __LINE__));
+ dwSaveErr = err;
+ }
+ else
+ {
+ fHasRemoteServerName = TRUE;
+ }
+ }
+
+ // Now look for "Service" registrations
+ HKEY hService;
+ WCHAR wszServiceName[MAX_PATH];
+ DWORD dwErrCtrl;
+
+ // Check for a "Service" named value
+ lSize = MAX_PATH;
+ if ((err = QueryStripRegNamedValue(hkThisAppID, wszService, wszServiceName,
+ &lSize,&fReadValue)) == ERROR_SUCCESS)
+ {
+ // Validate the existence of this service before overriding any
+ // LocalServer32 name
+ HKEY hServicesKey;
+ HKEY hServiceKey;
+
+ if ((err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, wszServicesKey,
+ 0, KEY_READ, &hServicesKey)) == ERROR_SUCCESS)
+ {
+ if ((err = RegOpenKeyEx(hServicesKey, wszServiceName,
+ 0, KEY_READ, &hServiceKey)) == ERROR_SUCCESS)
+ {
+ lSize = sizeof(DWORD);
+ if ((err = RegQueryValueEx(hServiceKey, wszErrorControl, NULL,
+ &dwType, (BYTE *) &dwErrCtrl,
+ (ULONG *) &lSize)) == ERROR_SUCCESS)
+ {
+ // We have a valid, accessible service
+ fHasService = TRUE;
+ }
+ RegCloseKey(hServiceKey);
+ }
+ RegCloseKey(hServicesKey);
+ }
+
+ // Open the Service key
+ if (fHasService)
+ {
+ DWORD dwType;
+ WCHAR bCmdArgs[200];
+ DWORD dwSize = sizeof(bCmdArgs);
+
+ // Save the service name
+ pwszLocalService = (WCHAR *)ScmMemAlloc((lstrlenW(wszServiceName)+1)*sizeof(WCHAR));
+ if (pwszLocalService == NULL)
+ {
+ err = E_OUTOFMEMORY;
+ goto cleanup_and_exit;
+ }
+ lstrcpyW(pwszLocalService, wszServiceName);
+
+ // Fetch any command line argments
+ if ((err = RegQueryValueEx(hkThisAppID, wszServiceParameters,
+ NULL, &dwType, (BYTE*)bCmdArgs, &dwSize))
+ == ERROR_SUCCESS)
+ {
+ // Save the command line arguments
+ pwszServiceArgs = (WCHAR * ) ScmMemAlloc(dwSize);
+ if (pwszServiceArgs == NULL)
+ {
+ err = E_OUTOFMEMORY;
+ goto cleanup_and_exit;
+ }
+ memcpy((void *) pwszServiceArgs, bCmdArgs, dwSize);
+ }
+ }
+ }
+
+
+ // We look for the value "LaunchPermission" here and save it off for later
+ err = GetRegistrySecDesc( hkThisAppID, wszLaunchPermission, &pSD );
+
+#ifdef DCOM_WITH_PER_USER_REG
+ // Look for the named value "Shared"
+ DWORD cbSize;
+
+ cbSize = 2;
+ err = RegQueryValueEx(hkThisAppID, wszShared, NULL, &dwType,
+ (BYTE *) wszYN, &cbSize);
+ *pfShared = (err == ERROR_SUCCESS);
+#endif // DCOM
+
+cleanup_and_exit:
+ RegCloseKey(hkThisAppID);
+
+ return err;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CClassRegistryReader::ReadClassEntry
+//
+// Synopsis: Set the state of this object by reading the
+// registry entry given by contents of awName.
+//
+//--------------------------------------------------------------------
+
+LONG
+CClassRegistryReader::ReadClassEntry(
+ HKEY hKey,
+ BOOL CheckTreatAs,
+ BOOL CheckAutoConvert)
+{
+
+ HKEY hClsRegEntry;
+ WCHAR wszYN[16];
+ WCHAR wszNewClsid[40];
+ LONG lSize;
+ DWORD dwType;
+
+#ifdef _CHICAGO_
+ if ((err = RegOpenKeyExA(hKey, awName, NULL, KEY_READ, &hClsRegEntry))
+ != ERROR_SUCCESS)
+ {
+ CairoleDebugOut((DEB_IWARN, "Unexpected error from RegOpenKeyEx opening %s: %x, %d\n", awName, err, __LINE__));
+ return err;
+ }
+#else
+ if ((err = RegOpenKeyEx(hKey, awName, NULL, KEY_READ, &hClsRegEntry))
+ != ERROR_SUCCESS)
+ {
+ CairoleDebugOut((DEB_IWARN, "Unexpected error from RegOpenKeyEx opening %ws: %x, %d\n", awName, err, __LINE__));
+ return err;
+ }
+#endif
+
+ if ( CheckAutoConvert )
+ {
+ lSize = sizeof( wszNewClsid );
+ err = QueryStripRegValue(
+ hClsRegEntry,
+ L"AutoConvertTo",
+ wszNewClsid,
+ &lSize);
+
+ if ( err = ERROR_SUCCESS )
+ {
+ RegCloseKey( hClsRegEntry );
+ err = RegOpenKeyEx(hKey, wszNewClsid, NULL, KEY_READ, &hClsRegEntry);
+ if ( err != ERROR_SUCCESS )
+ return err;
+ }
+ }
+
+ if ( CheckTreatAs )
+ {
+ lSize = sizeof( wszNewClsid );
+ err = QueryStripRegValue(
+ hClsRegEntry,
+ L"TreatAs",
+ wszNewClsid,
+ &lSize);
+
+ if ( err = ERROR_SUCCESS )
+ {
+ RegCloseKey( hClsRegEntry );
+ err = RegOpenKeyEx(hKey, wszNewClsid, NULL, KEY_READ, &hClsRegEntry);
+ if ( err != ERROR_SUCCESS )
+ return err;
+ }
+ }
+
+ err = QueryStripRegValue(
+ hClsRegEntry,
+ wszLocalServer,
+ pwszLocalServer,
+ &lLocalServer);
+
+ if (err == ERROR_SUCCESS)
+ {
+ fHasLocalServer = TRUE;
+ }
+ else if (err == ERROR_MORE_DATA)
+ {
+ if (pwszLocalServer != awcsLocalServer)
+ {
+ ScmMemFree (pwszLocalServer);
+ }
+ pwszLocalServer = (WCHAR *) ScmMemAlloc (lLocalServer);
+ if (pwszLocalServer == NULL)
+ {
+ return(ERROR_NOT_ENOUGH_MEMORY);
+ }
+
+ err = QueryStripRegValue(
+ hClsRegEntry,
+ wszLocalServer,
+ pwszLocalServer,
+ &lLocalServer);
+
+ if (err != ERROR_SUCCESS)
+ {
+ CairoleDebugOut((DEB_IWARN, "Unexpected error from RegQueryValue: (local server 32) %x, %d\n", err, __LINE__));
+ dwSaveErr = err;
+ }
+
+ fHasLocalServer = TRUE;
+ }
+ else if (NotFoundError(err)) // == ERROR_FILE_NOT_FOUND)
+ {
+ err = QueryStripRegValue(
+ hClsRegEntry,
+ wszLocalServer16,
+ pwszLocalServer,
+ &lLocalServer);
+
+ if (err == ERROR_SUCCESS)
+ {
+ //
+ // The 16 bit version is the one we want. Add it to the
+ // flags.
+ //
+ f16Bit = TRUE;
+ fHasLocalServer = TRUE;
+ }
+ else if (err == ERROR_MORE_DATA)
+ {
+ if (pwszLocalServer != awcsLocalServer)
+ {
+ ScmMemFree (pwszLocalServer);
+ }
+ pwszLocalServer = (WCHAR *) ScmMemAlloc (lLocalServer);
+ if (pwszLocalServer == NULL)
+ {
+ CairoleDebugOut((DEB_ERROR, "Not enough memory, file=scm\\init.cxx, line=%d\n", __LINE__));
+ dwSaveErr = err;
+ }
+
+ err = QueryStripRegValue(
+ hClsRegEntry,
+ wszLocalServer16,
+ pwszLocalServer,
+ &lLocalServer);
+
+ if (err != ERROR_SUCCESS)
+ {
+ CairoleDebugOut((DEB_IWARN, "Unexpected error from RegQueryValue: (local server 16) %x, line=%d\n", err, __LINE__));
+ dwSaveErr = err;
+ }
+
+ //
+ // The 16 bit version is the one we want. Add it to the
+ // flags.
+ //
+ f16Bit = TRUE;
+ fHasLocalServer = TRUE;
+ }
+ else if (!NotFoundError(err)) // != ERROR_FILE_NOT_FOUND)
+ {
+ CairoleDebugOut((DEB_ERROR, "Unexpected error from RegQueryValue: (local server 16) %x, line=%d\n", err, __LINE__));
+ dwSaveErr = err;
+ }
+ }
+ else
+ {
+ CairoleDebugOut((DEB_ERROR, "Unexpected error from RegQueryValue: (local server 16) %x, line=%d\n", err, __LINE__));
+ dwSaveErr = err;
+ }
+
+ // find the AppID, if any
+ if ( RegQueryValueEx( hClsRegEntry,
+ wszAppIDName,
+ NULL,
+ &dwType,
+ (LPBYTE) pwszAppID,
+ &lAppID )
+ == ERROR_SUCCESS )
+ {
+ // Scarf up all the AppID entries
+ pAppIDData = new CAppIDData();
+
+ pAppIDData->ReadEntries( pwszAppID );
+ }
+
+ RegCloseKey(hClsRegEntry);
+ return(dwSaveErr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CClassRegistryReader::ReadSingleClass
+//
+// Synopsis: Set this objects data by reading entry for
+// given class.
+//
+// Arguments: [rclsid] -- class id of class info to read from registry.
+//
+// Returns: LONG error code.
+//
+// Algorithm: Initialize as if doing enumeration for single
+// CLSID (by setting awName) and then just read one
+// entry.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+LONG CClassRegistryReader::ReadSingleClass(
+ REFCLSID rclsid,
+ BOOL CheckTreatAs,
+ BOOL CheckAutoConvert )
+{
+#ifdef _CHICAGO_
+ if (errClsReg != ERROR_SUCCESS)
+ {
+ CairoleDebugOut((DEB_ERROR, "Unexpected error from RegOpenKeyEx: %x, line=%d\n", errClsReg, __LINE__));
+ Win4Assert(FALSE && "RegOpenKey failed!");
+ return errClsReg;
+ }
+#endif
+
+ InitInner();
+
+ guidClassID = rclsid;
+
+#ifdef _CHICAGO_
+ cName = wStringFromGUID2A(guidClassID, awName, sizeof(awName)) - 1;
+#else
+ cName = wStringFromGUID2(guidClassID, awName, sizeof(awName)) - 1;
+#endif //_CHICAGO_
+
+ // sets internal state
+ err = ReadClassEntry(g_hkClsID, CheckTreatAs, CheckAutoConvert);
+
+ // NT 5.0
+#if 0
+ /*
+ // If PersonalClasses is not turned on then read from the common part
+ // of the registry
+ if (!gpClassCache->GetPersonalClasses())
+ {
+ err = ReadClassEntry(g_hkClsID, &_fShared); // sets internal state
+ _fShared = TRUE;
+ }
+
+ // Otherwise read from the per-user part of the registry.
+ // Note that if pUserSid != NULL then we are guaranteed to be
+ // still impersonating
+ else
+ {
+ HKEY hUserClsReg;
+
+ // Check if we have the per-user registry handle cached
+ hUserClsReg = gpClassCache->GetHkey(pUserSid);
+
+ // Otherwise open the key \\HKEY_USERS\<sid>_MergedClasses\CLSID
+ // and cache the handle
+ if (hUserClsReg == NULL)
+ {
+ HANDLE hUserToken;
+ PROFILEINFOW sProfileInfo;
+ UNICODE_STRING sCurrentUserKey;
+ WCHAR wszRegPath[128];
+
+ hUserToken = 0;
+
+ // Impersonate the client
+ RpcImpersonateClient((RPC_BINDING_HANDLE) 0 );
+
+ // Get the user token while impersonating
+ NTSTATUS NtStatus = NtOpenThreadToken(NtCurrentThread(),
+ TOKEN_DUPLICATE | TOKEN_QUERY,
+ TRUE,
+ &hUserToken);
+ if (!NT_SUCCESS(NtStatus))
+ {
+ err = ERROR_NO_IMPERSONATION_TOKEN;
+ }
+
+ // Load this user's profile if it's not the interactive user
+ if (err == ERROR_SUCCESS && !fInteractiveUser)
+ {
+// if (!LoadNonInteractiveUserProfile(hUserToken, &sProfileInfo))
+//////////////////////////////////////////////////////////////////////////////
+//////////TEMPORARY TEMPORARY TEMPORARY TEMPORARY TEMPORARY TEMPORARY ///////
+ if (!LoadUserProfileW(hUserToken, &sProfileInfo))
+//////////TEMPORARY TEMPORARY TEMPORARY TEMPORARY TEMPORARY TEMPORARY ///////
+//////////////////////////////////////////////////////////////////////////////
+ {
+ err = ERROR_CANNOT_OPEN_PROFILE;
+ }
+ }
+
+ // Only if we were successful to here
+ if (err == ERROR_SUCCESS)
+ {
+ // Formulate the registry path
+ RtlFormatCurrentUserKeyPath(&sCurrentUserKey);
+ memcpy(wszRegPath, sCurrentUserKey.Buffer,
+ 2 * sCurrentUserKey.Length);
+ wszRegPath[sCurrentUserKey.Length] = L'\0';
+ RtlFreeUnicodeString(&sCurrentUserKey);
+ lstrcatW(wszRegPath, L"_MergedClasses\\");
+ lstrcatW(wszRegPath, tszCLSID);
+
+ // Open the key
+ err = RegOpenKeyEx(HKEY_USERS, wszRegPath, NULL, KEY_READ,
+ &hUserClsReg);
+
+ // Cache the per-user registry handle
+ if (err == ERROR_SUCCESS)
+ {
+ if (!gpClassCache->SetHkey(pUserSid, hUserClsReg))
+ {
+ err = ERROR_OUTOFMEMORY;
+ }
+ }
+ }
+
+ NtClose( hUserToken );
+ }
+
+ // Read the registry
+ if (err == ERROR_SUCCESS)
+ {
+ err = ReadClassEntry(hUserClsReg, &_fShared);
+ }
+
+ // Whether success or failure we're done impersonating for awhile
+ RpcRevertToSelf();
+ }
+ */
+#endif // 0
+
+ if (err != ERROR_SUCCESS)
+ {
+ CairoleDebugOut((DEB_IWARN, "Unexpected error from ReadClassEntry: %x, line=%d\n", err, __LINE__));
+ }
+ return(err);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CClassRegistryReader::NewClassData
+//
+// Synopsis: Create a CClassData with data in this object which
+// was previously set by ReadClassEntry.
+//
+// Arguments: [hr] -- Set to an error code on failure, untouched
+// otherwise.
+//
+// Returns: NULL on failure, else pointer to new CClassData allocated
+//
+//--------------------------------------------------------------------
+
+CClassData * CClassRegistryReader::NewClassData(HRESULT &hr)
+ // NT 5.0 PSID pUserSid
+{
+ CClassID ccid(guidClassID);
+
+ CClassData *pccdNew;
+
+ if ( pAppIDData )
+ {
+ WCHAR * pwszCloneAppID = 0;
+ DWORD Bytes;
+
+ Bytes = (lstrlenW(pwszAppID)+1)*sizeof(WCHAR);
+ pwszCloneAppID = (WCHAR*) ScmMemAlloc( Bytes );
+ if ( ! pwszCloneAppID )
+ {
+ hr = E_OUTOFMEMORY;
+ return NULL;
+ }
+ memcpy( pwszCloneAppID, pwszAppID, Bytes );
+
+ // Create a new class object
+ pccdNew = new CClassData(ccid,
+ pwszCloneAppID,
+ (pAppIDData->fHasService ? pAppIDData->pwszLocalService
+ : (fHasLocalServer ? pwszLocalServer : NULL)),
+ pAppIDData->pwszRemoteServerName,
+ pAppIDData->fHasService,
+ pAppIDData->fHasService ? pAppIDData->pwszServiceArgs : NULL,
+ pAppIDData->pwszRunAsUserName,
+ pAppIDData->pwszRunAsDomainName,
+#ifdef DCOM
+ // NT 5.0 _fShared ? NULL : pUserSid,
+#endif // DCOM
+ pAppIDData->fActivateAtStorage,
+ pAppIDData->fHasRemoteServerName,
+ pAppIDData->pSD,
+ f16Bit,
+ hr);
+
+ if ( ! pccdNew )
+ {
+ ScmMemFree( pwszCloneAppID );
+ pAppIDData->Cleanup();
+ }
+ }
+ else
+ {
+ // Create a new class object
+ pccdNew = new CClassData(ccid,
+ NULL,
+ fHasLocalServer ? pwszLocalServer : NULL,
+ NULL,
+ FALSE,
+ NULL,
+ NULL,
+ NULL,
+#ifdef DCOM
+ // NT 5.0 _fShared ? NULL : pUserSid,
+#endif // DCOM
+ FALSE,
+ FALSE,
+ FALSE,
+ f16Bit,
+ hr);
+ }
+
+ if ( ! pccdNew )
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ else if ( FAILED(hr) )
+ {
+ pccdNew->DeleteThis();
+ pccdNew = NULL;
+ }
+
+ return pccdNew;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: InitSCMRegistry
+//
+// Synopsis: fill in initial global keys from the registry.
+//
+// Arguments: none
+//
+// Returns: HRESULT on failure
+//
+//--------------------------------------------------------------------
+HRESULT
+InitSCMRegistry()
+{
+ HRESULT hr;
+ LONG err;
+ DWORD dwDisp;
+
+ err = RegOpenKeyEx( HKEY_CLASSES_ROOT,
+ L"ClsID",
+ 0,
+ KEY_READ,
+ &g_hkClsID );
+
+ if ( err != ERROR_SUCCESS )
+ {
+ g_hkClsID = 0;
+ Win4Assert( !"failed to open CLSID key");
+ return E_FAIL;
+ }
+
+ err = RegCreateKeyEx( HKEY_CLASSES_ROOT,
+ L"AppID",
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL,
+ &g_hkAppID,
+ &dwDisp );
+
+ if ( err != ERROR_SUCCESS )
+ {
+ g_hkAppID = 0;
+ Win4Assert(!"failed to open AppID key");
+ return E_FAIL;
+ }
+
+ return S_OK;
+
+
+}
+
+
+
+
diff --git a/private/ole32/dcomss/olescm/init.hxx b/private/ole32/dcomss/olescm/init.hxx
new file mode 100644
index 000000000..c6056bca4
--- /dev/null
+++ b/private/ole32/dcomss/olescm/init.hxx
@@ -0,0 +1,30 @@
+//+-------------------------------------------------------------------
+//
+// File: init.hxx
+//
+// Contents: Common stuff for reading OLE registry settings
+//
+// History: 20-May-96 t-adame Created
+//
+//---------------------------------------------------------------------
+
+#ifndef __INIT_HXX__
+#define __INIT_HXX__
+
+extern WCHAR wszInProcServer[]; // name of InProc server subkey
+
+LONG
+QueryStripRegValue(HKEY hkey, // handle of key to query
+ LPCWSTR pwszSubKey, // address of name of subkey to query
+ LPWSTR pwszValue, // address of buffer for returned string
+ PLONG pcbValue); // address of buffer for size of returned string
+LONG
+QueryStripRegNamedValue(HKEY hkey, // handle of key to query
+ LPCWSTR pwszSubKey, // address of name of value to query
+ LPWSTR pwszValue, // address of buffer for returned string
+ PLONG pcbValue, // address of buffer for size of returned string
+ BOOL* fValueRead); // whether or not the value was read
+
+#endif // __INIT_HXX__
+
+
diff --git a/private/ole32/dcomss/olescm/net.cxx b/private/ole32/dcomss/olescm/net.cxx
new file mode 100644
index 000000000..3b30722e7
--- /dev/null
+++ b/private/ole32/dcomss/olescm/net.cxx
@@ -0,0 +1,71 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1996.
+//
+// File: net.c
+//
+// Contents:
+// Net helper functions.
+//
+// History:
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include "scm.hxx"
+
+GET_UNIVERSAL_NAME_FUNC pfnWNetGetUniversalName = 0;
+NET_SHARE_GET_INFO_FUNC pfnNetShareGetInfo = 0;
+
+DWORD APIENTRY ScmWNetGetUniversalName(
+ LPCWSTR lpLocalPath,
+ DWORD dwInfoLevel,
+ LPVOID lpBuffer,
+ LPDWORD lpBufferSize
+ )
+{
+ HINSTANCE hLib;
+
+ if ( pfnWNetGetUniversalName == 0 )
+ {
+ hLib = LoadLibrary( L"mpr.dll" );
+ if ( ! hLib )
+ return GetLastError();
+
+ pfnWNetGetUniversalName =
+ (GET_UNIVERSAL_NAME_FUNC) GetProcAddress( hLib, "WNetGetUniversalNameW" );
+
+ if ( pfnWNetGetUniversalName == 0 )
+ return GetLastError();
+ }
+
+ return (*pfnWNetGetUniversalName)( lpLocalPath, dwInfoLevel, lpBuffer, lpBufferSize );
+}
+
+NET_API_STATUS NET_API_FUNCTION ScmNetShareGetInfo(
+ LPTSTR servername,
+ LPTSTR netname,
+ DWORD level,
+ LPBYTE *bufptr
+ )
+{
+ HINSTANCE hLib;
+
+ if ( pfnNetShareGetInfo == 0 )
+ {
+ hLib = LoadLibrary( L"netapi32.dll" );
+ if ( ! hLib )
+ return GetLastError();
+
+ pfnNetShareGetInfo =
+ (NET_SHARE_GET_INFO_FUNC) GetProcAddress( hLib, "NetShareGetInfo" );
+
+ if ( pfnNetShareGetInfo == 0 )
+ return GetLastError();
+ }
+
+ return (*pfnNetShareGetInfo)( servername, netname, level, bufptr );
+}
diff --git a/private/ole32/dcomss/olescm/port.cxx b/private/ole32/dcomss/olescm/port.cxx
new file mode 100644
index 000000000..9c37ffe59
--- /dev/null
+++ b/private/ole32/dcomss/olescm/port.cxx
@@ -0,0 +1,280 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: port.cxx
+//
+// Contents: Classes etc which encapsulate differences between NT
+// and x86 Windows for SCM.
+//
+// Classes:
+//
+// Functions:
+//
+//
+//
+// History: 17-Mar-93 BillMo Created.
+//
+// Notes:
+//
+// Codework:
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include "scm.hxx"
+#include <scmstart.hxx>
+#include <rotif.hxx>
+#include "port.hxx"
+#include "cls.hxx"
+
+HRESULT g_hrInit=S_OK;
+
+#ifndef _CHICAGO_
+#include "remact.hxx"
+
+CClassCacheList *gpClassCache = NULL;
+CLocSrvList *gpCLocSrvList = NULL;
+CRemSrvList *gpCRemSrvList = NULL;
+#else
+CClassCacheList *g_pcllClassCache = NULL;
+CHandlerList *gpCHandlerList = NULL;
+CInProcList *gpCInProcList = NULL;
+CLocSrvList *gpCLocSrvList = NULL;
+#endif
+
+#ifndef _CHICAGO_
+
+CPortableServerLock::CPortableServerLock(CClassData *pcd) : _sls(pcd->_slocalsrv)
+{
+ _sls->LockServer();
+}
+
+CPortableServerLock::CPortableServerLock(CSafeLocalServer& sls) : _sls(sls)
+{
+ _sls->LockServer();
+}
+
+CPortableServerEvent::CPortableServerEvent(CClassData *pcd) : _hEvent(pcd->_hClassStart)
+{
+ ResetEvent(_hEvent);
+}
+
+#else // !_CHICAGO_
+
+extern HRESULT (*DfCreateSharedAllocator) ( IMalloc **ppm );
+IMalloc * g_pStgAlloc;
+
+//+-------------------------------------------------------------------
+//
+// Function: ScmMemAlloc for Chicago
+//
+// Synopsis: Allocate some shared memory from the storage heap.
+//
+// Notes: Temporary until we have our own shared heap.
+//
+//--------------------------------------------------------------------
+void *ScmMemAlloc(size_t size)
+{
+ return g_pStgAlloc->Alloc(size);
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: ScmMemFree
+//
+// Synopsis: Free shared memory from the storage heap.
+//
+// Notes: Temporary until we have our own shared heap.
+//
+//--------------------------------------------------------------------
+void ScmMemFree(void * pv)
+{
+ g_pStgAlloc->Free(pv);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Function: InitSharedLists
+//
+// Synopsis: If need be, create class cache list, handler list,
+// inproc list, local server list
+//
+// Returns: TRUE if successful, FALSE otherwise.
+//
+//--------------------------------------------------------------------
+
+BOOL InitSharedLists(void)
+{
+ HRESULT hr = S_OK;
+
+ if (FAILED(hr = DfCreateSharedAllocator(&g_pStgAlloc)))
+ {
+ CairoleDebugOut((DEB_ERROR,
+ "DfCreateSharedAllocator failed %08x\n", hr));
+ return(FALSE);
+ }
+
+ //
+ // here we must create new tables iff they havn't been created yet.
+ //
+
+ if (g_post->gpCClassCacheList == NULL)
+ {
+ g_pcllClassCache = g_post->gpCClassCacheList = new CClassCacheList(hr);
+ }
+ else
+ {
+ g_pcllClassCache = g_post->gpCClassCacheList;
+ }
+
+ if (g_post->gpCHandlerList == NULL)
+ {
+ g_post->gpCHandlerList = gpCHandlerList = new CHandlerList(hr);
+ }
+ else
+ {
+ gpCHandlerList = g_post->gpCHandlerList;
+ }
+
+ if (g_post->gpCInProcList == NULL)
+ {
+ g_post->gpCInProcList = gpCInProcList = new CInProcList(hr);
+ }
+ else
+ {
+ gpCInProcList = g_post->gpCInProcList;
+ }
+
+ if (g_post->gpCLocSrvList == NULL)
+ {
+ g_post->gpCLocSrvList = gpCLocSrvList = new CLocSrvList(hr);
+ }
+ else
+ {
+ gpCLocSrvList = g_post->gpCLocSrvList;
+ }
+
+ if (g_post->pscmrot == NULL)
+ {
+ gpscmrot = g_post->pscmrot = new CScmRot(hr, NULL);
+ }
+ else
+ {
+ gpscmrot = g_post->pscmrot;
+ }
+
+ if (g_pcllClassCache == NULL ||
+ gpCHandlerList == NULL ||
+ gpCInProcList == NULL ||
+ gpCLocSrvList == NULL ||
+ gpscmrot == NULL ||
+ FAILED(hr))
+ {
+ CairoleDebugOut((DEB_ERROR, "InitSharedLists failed.\n"));
+
+ delete g_pcllClassCache;
+ delete gpCHandlerList;
+ delete gpCInProcList;
+ delete gpCLocSrvList;
+ delete gpscmrot;
+
+ g_post->gpCClassCacheList = g_pcllClassCache = NULL;
+ g_post->gpCHandlerList = gpCHandlerList = NULL;
+ g_post->gpCInProcList = gpCInProcList = NULL;
+ g_post->gpCLocSrvList = gpCLocSrvList = NULL;
+ g_post->pscmrot = gpscmrot = NULL;
+
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+CPortableServerLock::CPortableServerLock(CClassData *pcd) : _sc(ERROR_SUCCESS)
+{
+ CHAR szMutex[sizeof(MUTEXNAMEPREFIX)+GUIDSTR_MAX+1];
+
+ TCHAR tszGuid[GUIDSTR_MAX+1];
+
+ wStringFromGUID2A(pcd->_guid, tszGuid, GUIDSTR_MAX+1);
+ strcpy(szMutex, MUTEXNAMEPREFIX);
+ strcat(szMutex, tszGuid);
+ Win4Assert(strlen(szMutex)+1 <= sizeof(szMutex));
+
+ // Holder for attributes to pass in on create.
+ SECURITY_ATTRIBUTES secattr;
+ secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ secattr.lpSecurityDescriptor = NULL;
+ secattr.bInheritHandle = FALSE;
+
+ // Create the mutex object
+ _hMutex = CreateMutex(&secattr, FALSE, szMutex);
+
+ if (_hMutex == NULL)
+ {
+ _sc = HRESULT_FROM_WIN32(GetLastError());
+ CairoleDebugOut((DEB_ERROR,
+ "CPortableServerLock::CPortableServerLock couldn't create mutex hresult = %lx\n",
+ _sc));
+ return;
+ }
+
+ // Wait to acquire it - note we use MsgWaitForMultipleObjects because
+ // WaitForSingleObject is not safe to use for 16 bit apps.
+ do
+ {
+ DWORD dwWaitResult = MsgWaitForMultipleObjects(1, &_hMutex, FALSE,
+ INFINITE, QS_SENDMESSAGE);
+
+ Win4Assert(((dwWaitResult == WAIT_OBJECT_0)
+ || (dwWaitResult == (WAIT_OBJECT_0 + 1)))
+ && "CPortableServerLock invalid result MsgWaitForMultipleObjects");
+
+ //
+ // If the dwWaitResult index is beyond the array, then there
+ // is a message available.
+ //
+ if (dwWaitResult == WAIT_OBJECT_0)
+ {
+ // We got the mutex so we can exit.
+ break;
+ }
+ else if (dwWaitResult == (WAIT_OBJECT_0 + 1))
+ {
+ // We got a send message so we peek so that it can get dispatched.
+ MSG msg;
+
+ if (SSPeekMessage(&msg, 0, 0, 0, PM_NOREMOVE))
+ {
+ CairoleDebugOut((DEB_ITRACE,
+ "CPortableServerLock::CPortableServerLock got message\n" ));
+ }
+ }
+ else
+ {
+ // This is very unexpected. We have been toasted if this happens.
+ // Thus the assert above.
+ _sc = E_UNEXPECTED;
+ break;
+ }
+
+ } while (TRUE);
+}
+
+
+CPortableServerEvent::CPortableServerEvent(CClassData *pcd)
+{
+ TCHAR tszGuid[GUIDSTR_MAX+1];
+
+ wStringFromGUID2A(pcd->_guid, tszGuid, GUIDSTR_MAX+1);
+ strcpy(_tszEvent, EVENTNAMEPREFIX);
+ strcat(_tszEvent, tszGuid);
+ Win4Assert(strlen(_tszEvent)+1 <= sizeof(_tszEvent)/sizeof(_tszEvent[0]));
+}
+
+#endif // !_CHICAGO_
diff --git a/private/ole32/dcomss/olescm/port.hxx b/private/ole32/dcomss/olescm/port.hxx
new file mode 100644
index 000000000..eb25d752b
--- /dev/null
+++ b/private/ole32/dcomss/olescm/port.hxx
@@ -0,0 +1,374 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: port.hxx
+//
+// Contents: Classes which encapsulate differences between NT
+// and x86 Windows for SCM.
+//
+// Classes: CPortableRpcHandle
+// CPortableServerLock
+//
+// Functions:
+//
+// History: 07-Jun-92 BillMo Created.
+//
+//--------------------------------------------------------------------------
+
+#ifndef _SCMPORT_HXX_
+#define _SCMPORT_HXX_
+
+#include "srvreg.hxx"
+#include "smmutex.hxx"
+#include "rotif.hxx"
+#include "clsdata.hxx"
+#include <tchar.h>
+
+extern HRESULT g_hrInit;
+
+#ifdef _CHICAGO_
+//--------------------------------------------------------------------------
+// Scm out-of-process activation stubs - x86 Windows
+//--------------------------------------------------------------------------
+#define REMCOCREATEOBJECT GetToRemCoCreateObject
+#define REMCOACTIVATEOBJECT GetToRemCoActivateObject
+#define REMCOGETACTIVECLASSOBJECT GetToRemCoGetActiveClassObject
+
+HRESULT GetToRemCoGetActiveClassObject(
+ handle_t hRpc,
+ const GUID *guidThreadId,
+ const GUID *pclsid,
+ InterfaceData **ppIFD,
+ error_status_t *prpcstat);
+
+HRESULT GetToRemCoActivateObject(
+ handle_t hRpc,
+ WCHAR *pwszProtseq,
+ const GUID *guidThreadId,
+ const GUID *pclsid,
+ DWORD grfMode,
+ WCHAR *pwszPath,
+ InterfaceData *pIFDstg,
+ DWORD dwTIDCaller,
+ DWORD *pdwTIDCallee,
+ InterfaceData **ppIFD,
+ InterfaceData *pIFDFromROT,
+ error_status_t *prpcstat);
+
+HRESULT GetToRemCoCreateObject(
+ handle_t hRpc,
+ WCHAR *pwszProtseq,
+ const GUID *guidThreadId,
+ const GUID *pclsid,
+ DWORD grfMode,
+ WCHAR *pwszPathFrom,
+ InterfaceData *pIFDstgFrom,
+ WCHAR *pwszPath,
+ DWORD dwTIDCaller,
+ DWORD *pdwTIDCallee,
+ InterfaceData **ppIFD,
+ error_status_t *prpcstat);
+#endif
+
+#ifndef _CHICAGO_
+extern CClassCacheList *gpClassCache;
+extern CLocSrvList *gpCLocSrvList;
+
+inline CClassCacheList & GetClassCache(void) { return(*gpClassCache); }
+inline CLocSrvList & GetCLocSrvList(void) { return(*gpCLocSrvList); }
+#else
+extern CClassCacheList *g_pcllClassCache;
+extern CHandlerList *gpCHandlerList;
+extern CInProcList *gpCInProcList;
+extern CLocSrvList *gpCLocSrvList;
+
+inline CClassCacheList & GetClassCache(void) { return(*g_pcllClassCache); }
+inline CInProcList & GetCInProcList(void) { return(*gpCInProcList); }
+inline CHandlerList & GetCHandlerList(void) { return(*gpCHandlerList); }
+inline CLocSrvList & GetCLocSrvList(void) { return(*gpCLocSrvList); }
+#endif
+
+#ifdef _CHICAGO_
+BOOL InitSharedLists(void);
+
+LONG GetNextId(HRESULT &hr); // Get a unique id from shared memory
+#endif // _CHICAGO_
+
+class CClassData;
+
+#ifndef _CHICAGO_
+
+//
+// NT classes
+//
+
+class CPortableRpcHandle
+{
+public:
+
+ CPortableRpcHandle(VOID)
+ {
+ _hrpc = NULL;
+ _fSingleUse = FALSE;
+ }
+
+ CPortableRpcHandle(DWORD dwReg)
+ {
+ _hrpc = (handle_t)dwReg;
+ _fSingleUse = FALSE;
+ }
+
+ handle_t GetHandle(VOID)
+ {
+ return(_hrpc);
+ }
+
+ VOID FreeSingleUseBinding(VOID)
+ {
+ if (_fSingleUse)
+ {
+ RpcBindingFree(&_hrpc);
+ _hrpc = NULL;
+ }
+ }
+
+ // TRUE if last just deleted
+ BOOL DeleteFromSrvRegList(CSrvRegList *psrvreg)
+ {
+ return psrvreg->Delete(_hrpc);
+ }
+
+ BOOL VerifyHandle(CSrvRegList *psrvreg) const
+ {
+ return psrvreg->VerifyHandle(_hrpc);
+ }
+
+ VOID SetRpcCookie(handle_t hRpc, BOOL fSingleUse, IPID ipid)
+ {
+ _hrpc = hRpc;
+ _fSingleUse = fSingleUse;
+ _ipid = ipid;
+ }
+
+ BOOL fSingleUse()
+ {
+ return(_fSingleUse);
+ }
+
+ IPID Ipid()
+ {
+ return(_ipid);
+ }
+
+ VOID InvalidateHandle(CSrvRegList *psrvreg) const
+ {
+ psrvreg->InvalidateHandle(_hrpc);
+ }
+
+private:
+ handle_t _hrpc;
+ BOOL _fSingleUse;
+ IPID _ipid;
+};
+
+class CPortableServerLock
+{
+public:
+ CPortableServerLock(CClassData *pcd);
+ CPortableServerLock(CSafeLocalServer& sls);
+
+ ~CPortableServerLock()
+ {
+ _sls->UnlockServer();
+ }
+
+ DWORD Error(VOID)
+ {
+ return(ERROR_SUCCESS);
+ }
+
+private:
+ CSafeLocalServer & _sls;
+};
+
+class CPortableServerEvent
+{
+public:
+ CPortableServerEvent(CClassData *pcd);
+
+ DWORD Create(VOID)
+ {
+ return(ERROR_SUCCESS);
+ }
+
+ DWORD Open(VOID)
+ {
+ return(ERROR_SUCCESS);
+ }
+
+ HANDLE GetHandle(VOID)
+ {
+ return(_hEvent);
+ }
+private:
+ HANDLE _hEvent;
+};
+
+#else
+
+
+//
+// x86 Windows classes
+//
+
+class CPortableRpcHandle
+{
+public:
+
+ CPortableRpcHandle(VOID)
+ {
+ _pwszBindingString=NULL;
+ _fSingleUse=FALSE;
+ _hrpc=NULL;
+ }
+
+ CPortableRpcHandle(DWORD dwReg)
+ {
+ _pwszBindingString = (WCHAR*)dwReg;
+ _fSingleUse=FALSE;
+ _hrpc=NULL;
+ }
+
+ ~CPortableRpcHandle()
+ {
+ RpcBindingFree(&_hrpc);
+ }
+
+ handle_t GetHandle(VOID)
+ {
+ if (_hrpc == NULL &&
+ _pwszBindingString != NULL)
+ {
+ RpcBindingFromStringBinding(_pwszBindingString, &_hrpc);
+ }
+ return(_hrpc);
+ }
+
+ VOID FreeSingleUseBinding(VOID)
+ {
+ if (_fSingleUse)
+ {
+ ScmMemFree(_pwszBindingString);
+ RpcBindingFree(&_hrpc);
+ _pwszBindingString=NULL;
+ _hrpc=NULL;
+ }
+ }
+
+ // TRUE if last just deleted
+ BOOL DeleteFromSrvRegList(CSrvRegList *pssrvreg)
+ {
+ BOOL f = pssrvreg->Delete(_pwszBindingString);
+ _pwszBindingString = NULL;
+ return f;
+ }
+
+ BOOL VerifyHandle(CSrvRegList *psrvreg) const
+ {
+ return psrvreg->VerifyHandle(_pwszBindingString);
+ }
+
+ VOID SetRpcCookie(WCHAR *pwszBindingString, BOOL fSingleUse)
+ {
+ _fSingleUse = fSingleUse;
+ _pwszBindingString = pwszBindingString;
+ }
+
+ BOOL fSingleUse()
+ {
+ return(_fSingleUse);
+ }
+
+
+private:
+ WCHAR * _pwszBindingString;
+ BOOL _fSingleUse;
+ handle_t _hrpc;
+};
+
+#define MUTEXNAMEPREFIX "OLESCMSTARTMUTEX"
+
+class CPortableServerLock
+{
+public:
+ CPortableServerLock(CClassData *pcd);
+
+ ~CPortableServerLock();
+
+ DWORD Error(VOID);
+
+private:
+
+ HANDLE _hMutex;
+ SCODE _sc;
+};
+
+inline CPortableServerLock::~CPortableServerLock()
+{
+ // Release the mutex
+ ReleaseMutex(_hMutex);
+
+ // Free our handle.
+ CloseHandle(_hMutex);
+}
+
+inline DWORD CPortableServerLock::Error(VOID)
+{
+ return(_sc);
+}
+
+#define EVENTNAMEPREFIX "OLESCMSTARTEVENT"
+
+class CPortableServerEvent
+{
+public:
+ CPortableServerEvent(CClassData *pcd);
+
+ ~CPortableServerEvent()
+ {
+ if (_dwErr == ERROR_SUCCESS)
+ {
+ CloseHandle(_hEvent);
+ }
+ }
+
+ DWORD Create(VOID)
+ {
+ _hEvent = CreateEventA(NULL, TRUE, FALSE, _tszEvent);
+ return _dwErr = (_hEvent == NULL ? GetLastError() : ERROR_SUCCESS);
+ }
+
+ DWORD Open(VOID)
+ {
+ _hEvent = OpenEventA(EVENT_ALL_ACCESS, FALSE, _tszEvent);
+ return _dwErr = (_hEvent == NULL ? GetLastError() : ERROR_SUCCESS);
+ }
+
+ HANDLE GetHandle(VOID)
+ {
+ Win4Assert(_dwErr == ERROR_SUCCESS);
+ return(_hEvent);
+ }
+
+private:
+ TCHAR _tszEvent[sizeof(EVENTNAMEPREFIX)/sizeof(EVENTNAMEPREFIX[0])+
+ GUIDSTR_MAX+1];
+ HANDLE _hEvent;
+ DWORD _dwErr;
+};
+
+#endif
+
+#endif //header file guard
diff --git a/private/ole32/dcomss/olescm/remact.cxx b/private/ole32/dcomss/olescm/remact.cxx
new file mode 100644
index 000000000..a6677436c
--- /dev/null
+++ b/private/ole32/dcomss/olescm/remact.cxx
@@ -0,0 +1,980 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995.
+//
+// File:
+// remact.cxx
+//
+// Contents:
+//
+// Implementation of binding handle cache to remote activation services.
+//
+// History:
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include "scm.hxx"
+#include "port.hxx"
+#include "cls.hxx"
+#include "remact.hxx"
+#include "or.hxx"
+#include "remact.h"
+
+extern "C" {
+extern PROTSEQ_INFO gaProtseqInfo[];
+}
+
+CRITICAL_SECTION RemoteServerCS;
+
+void
+LogRemoteSideUnavailable(
+ ACTIVATION_PARAMS * pActParams,
+ WCHAR * pwszServerName )
+{
+ // %1 is the remote machine name
+ HANDLE LogHandle;
+ LPTSTR Strings[1]; // array of message strings.
+
+ Strings[0] = pwszServerName;
+
+ // Get the log handle, then report then event.
+ LogHandle = RegisterEventSource( NULL,
+ SCM_EVENT_SOURCE );
+
+ if ( LogHandle )
+ {
+ ReportEvent( LogHandle,
+ EVENTLOG_ERROR_TYPE,
+ 0, // event category
+ EVENT_RPCSS_REMOTE_SIDE_UNAVAILABLE,
+ pActParams->pToken->GetSid(), // SID
+ 1, // 1 strings passed
+ 0, // 0 bytes of binary
+ (LPCTSTR *)Strings, // array of strings
+ NULL ); // no raw data
+
+ // clean up the event log handle
+ DeregisterEventSource(LogHandle);
+ }
+
+}
+
+void
+LogRemoteSideFailure(
+ ACTIVATION_PARAMS * pActParams,
+ WCHAR * pwszServerName,
+ WCHAR * pwszPathForServer,
+ HRESULT hr )
+{
+ // %1 is the error number
+ // %2 is the remote machine name
+ // %3 is the clsid
+ // %4 is the PathForServer
+ HANDLE LogHandle;
+ LPTSTR Strings[4]; // array of message strings.
+ WCHAR wszClsid[GUIDSTR_MAX];
+ WCHAR wszErrnum[20];
+
+ // Save the error number
+ wsprintf(wszErrnum, L"%lu",hr );
+ Strings[0] = wszErrnum;
+
+ Strings[1] = pwszServerName;
+
+ // Get the clsid
+ wStringFromGUID2(*(pActParams->Clsid), wszClsid, sizeof(wszClsid));
+ Strings[2] = wszClsid;
+
+ Strings[3] = pwszPathForServer;
+
+ // Get the log handle, then report then event.
+ LogHandle = RegisterEventSource( NULL,
+ SCM_EVENT_SOURCE );
+
+ if ( LogHandle )
+ {
+ if ( pwszPathForServer )
+ {
+ ReportEvent( LogHandle,
+ EVENTLOG_ERROR_TYPE,
+ 0, // event category
+ EVENT_RPCSS_REMOTE_SIDE_ERROR_WITH_FILE,
+ pActParams->pToken->GetSid(), // SID
+ 4, // 4 strings passed
+ 0, // 0 bytes of binary
+ (LPCTSTR *)Strings, // array of strings
+ NULL ); // no raw data
+ }
+ else
+ {
+ ReportEvent( LogHandle,
+ EVENTLOG_ERROR_TYPE,
+ 0, // event category
+ EVENT_RPCSS_REMOTE_SIDE_ERROR,
+ pActParams->pToken->GetSid(), // SID
+ 3, // 3 strings passed
+ 0, // 0 bytes of binary
+ (LPCTSTR *)Strings, // array of strings
+ NULL ); // no raw data
+ }
+
+ // clean up the event log handle
+ DeregisterEventSource(LogHandle);
+ }
+
+
+}
+
+
+//
+// Entry point for outgoing remote activation calls.
+//
+HRESULT
+RemoteActivationCall(
+ ACTIVATION_PARAMS * pActParams,
+ WCHAR * pwszServerName,
+ WCHAR * pwszPathForServer )
+{
+ CRemoteServer * pRemoteServer;
+ BOOL NoEndpoint;
+ HRESULT hr;
+ RPC_STATUS Status;
+
+ Win4Assert( pwszServerName );
+
+ EnterCriticalSection( &RemoteServerCS );
+ pRemoteServer = gpCRemSrvList->Add( pwszServerName, hr );
+ LeaveCriticalSection( &RemoteServerCS );
+
+ if ( FAILED(hr) )
+ return hr;
+
+ if ( (Status = RpcImpersonateClient(NULL)) != ERROR_SUCCESS )
+ return HRESULT_FROM_WIN32(Status);
+
+ // try a secure activation
+ hr = pRemoteServer->Activate( &Status,pActParams,pwszPathForServer,pwszServerName,TRUE );
+
+ // if we have don't have authinfo, try an unsecure activation
+ if( (Status != RPC_S_OK) && !(pActParams->pAuthInfo) )
+ {
+ hr = pRemoteServer->Activate( &Status,pActParams,pwszPathForServer,pwszServerName,FALSE );
+ }
+
+ RpcRevertToSelf();
+
+ return hr;
+}
+
+
+HRESULT
+CRemoteServer::Activate(
+ RPC_STATUS* pStatus,
+ ACTIVATION_PARAMS* pActParams,
+ WCHAR* pwszPathForServer,
+ WCHAR* pwszServerName,
+ BOOL Secure )
+{
+ COAUTHINFO* pAuthInfo = pActParams->pAuthInfo;
+ handle_t hRemoteSCM = NULL;
+ WCHAR* pStringBinding = NULL;
+ RPC_SECURITY_QOS Qos;
+ HRESULT hr;
+ BOOL NoEndpoint;
+ hRemoteSCM = NULL;
+ pStringBinding = NULL;
+
+ // try to use a cached handle
+ hRemoteSCM = LookupHandle( pActParams->pToken,pAuthInfo,Secure );
+
+ if ( hRemoteSCM )
+ {
+ *pStatus = CallRemoteSCM( hRemoteSCM,
+ GetProtseqId( hRemoteSCM ),
+ pActParams,
+ pwszPathForServer,
+ &hr );
+
+ ReleaseHandle( hRemoteSCM );
+
+ //
+ // Check if call completed OK. The overall activation may still have
+ // failed.
+ //
+ if ( *pStatus == RPC_S_OK )
+ {
+ return hr;
+ }
+
+ // if we get an unexpected failure, get rid of this handle
+ if (!(FNonFatalRpcError(*pStatus)) )
+ {
+ InvalidateHandle( hRemoteSCM );
+ }
+ else
+ {
+ //
+ // if its an expected failure, don't bother creating a new handle
+ //
+ return HRESULT_FROM_WIN32( *pStatus );
+ }
+
+ hRemoteSCM = 0;
+ }
+
+ //
+ // using cached handle failed, now we need to create a new binding
+ // handle and try it
+ //
+ Qos.Version = RPC_C_SECURITY_QOS_VERSION;
+
+ if ( pAuthInfo )
+ {
+ Qos.Capabilities = pAuthInfo->dwCapabilities;
+ Qos.ImpersonationType = pAuthInfo->dwImpersonationLevel;
+ Qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
+ }
+ else
+ {
+ Qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
+ Qos.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
+ Qos.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC;
+ }
+
+ //
+ // try creating a new binding handle for each protocol sequence
+ // that we support
+ //
+ for ( int ProtseqIndex = 0; ProtseqIndex < cMyProtseqs; ProtseqIndex++ )
+ {
+ *pStatus = RpcStringBindingCompose(
+ NULL,
+ gaProtseqInfo[aMyProtseqs[ProtseqIndex]].pwstrProtseq,
+ pwszServerName,
+ gaProtseqInfo[aMyProtseqs[ProtseqIndex]].pwstrEndpoint,
+ NULL,
+ &pStringBinding );
+
+ // This is most likely an out of memory condition, so we'll give up.
+ if ( *pStatus != RPC_S_OK )
+ return HRESULT_FROM_WIN32(*pStatus);
+
+ *pStatus = RpcBindingFromStringBinding( pStringBinding, &hRemoteSCM );
+
+ RpcStringFree( &pStringBinding );
+ pStringBinding = 0;
+
+ // This could be a protocol specific problem, so we'll continue.
+ if ( *pStatus != RPC_S_OK )
+ continue;
+
+ NoEndpoint = FALSE;
+
+ // choose the appropriate authorization settings
+ if ( Secure )
+ {
+ if ( pAuthInfo )
+ {
+ // use supplied authorization settings
+ *pStatus = RpcBindingSetAuthInfoEx(
+ hRemoteSCM,
+ pAuthInfo->pwszServerPrincName,
+ pAuthInfo->dwAuthnLevel,
+ pAuthInfo->dwAuthnSvc,
+ pAuthInfo->pAuthIdentityData,
+ pAuthInfo->dwAuthzSvc,
+ &Qos );
+ }
+ else
+ {
+ // use default authorization settings
+ *pStatus = RpcBindingSetAuthInfoEx(
+ hRemoteSCM,
+ NULL,
+ RPC_C_AUTHN_LEVEL_CONNECT,
+ RPC_C_AUTHN_WINNT,
+ NULL,
+ 0,
+ &Qos );
+ }
+ }
+ else
+ {
+ // use unsecure authorization settings
+ *pStatus = RpcBindingSetAuthInfoEx(
+ hRemoteSCM,
+ NULL,
+ RPC_C_AUTHN_LEVEL_NONE,
+ RPC_C_AUTHN_NONE,
+ NULL,
+ 0,
+ &Qos );
+ }
+
+ if ( *pStatus != RPC_S_OK )
+ continue;
+
+ //
+ // This loop only executes twice if we need to try the call without
+ // an endpoint specified.
+ //
+ for (;;)
+ {
+ // try the call
+ *pStatus = CallRemoteSCM( hRemoteSCM,
+ aMyProtseqs[ProtseqIndex],
+ pActParams,
+ pwszPathForServer,
+ &hr );
+
+ if ( *pStatus == RPC_S_OK || FNonFatalRpcError(*pStatus) )
+ {
+ //
+ // If the call completed on the remote SCM, or if we got an
+ // "expected" error code, then we cache the binding handle.
+ // Note that this does not necessarily mean the activation
+ // was successful.
+ //
+ InsertHandle( pActParams->pToken,
+ aMyProtseqs[ProtseqIndex],
+ hRemoteSCM,
+ pAuthInfo,
+ Secure );
+
+ if ( *pStatus == RPC_S_OK )
+ {
+ // log message if hr indicates failure
+ if ( FAILED(hr) )
+ LogRemoteSideFailure( pActParams, pwszServerName, pwszPathForServer, hr );
+
+ return hr;
+ }
+
+ break;
+ }
+
+ if ( *pStatus == RPC_S_UNKNOWN_IF )
+ {
+ if ( ! NoEndpoint )
+ {
+ (void) RpcBindingReset( hRemoteSCM );
+ NoEndpoint = TRUE;
+ continue;
+ }
+ }
+
+ // if we got here, we got an unexpected error
+ RpcBindingFree(&hRemoteSCM);
+ break;
+ }
+ }
+
+ // log message indicating failure to communicate.
+ LogRemoteSideUnavailable( pActParams, pwszServerName );
+
+ return HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE);
+}
+
+BOOL
+CRemoteServer::FNonFatalRpcError( RPC_STATUS Status )
+{
+ switch( Status )
+ {
+ case RPC_S_ACCESS_DENIED:
+ case RPC_S_UNKNOWN_AUTHN_SERVICE:
+ case RPC_S_UNKNOWN_AUTHZ_SERVICE:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+
+RPC_STATUS CallRemoteSCM(
+ handle_t hRemoteSCM,
+ USHORT ProtseqId,
+ ACTIVATION_PARAMS * pActParams,
+ WCHAR * pwszPathForServer,
+ HRESULT * phr )
+{
+ RPC_STATUS Status;
+ COMVERSION ServerVersion;
+
+ pActParams->ORPCthis->flags = ORPCF_NULL;
+
+ Status = RemoteActivation(
+ hRemoteSCM,
+ pActParams->ORPCthis,
+ pActParams->ORPCthat,
+ pActParams->Clsid,
+ pwszPathForServer,
+ pActParams->pIFDStorage,
+ RPC_C_IMP_LEVEL_IDENTIFY,
+ pActParams->Mode,
+ pActParams->Interfaces,
+ pActParams->pIIDs,
+ 1,
+ &ProtseqId,
+ pActParams->pOxidServer,
+ &pActParams->pOxidInfo->psa,
+ &pActParams->pOxidInfo->ipidRemUnknown,
+ &pActParams->pOxidInfo->dwAuthnHint,
+ &ServerVersion,
+ phr,
+ pActParams->ppIFD,
+ pActParams->pResults );
+
+ //
+ // Note that this will only give us a bad status is there is a
+ // communication failure.
+ //
+ if ( Status != RPC_S_OK )
+ return Status;
+
+ //
+ // If the activation fails we return success for the communication
+ // status, but the overall operation has failed and the error will
+ // be propogated back to the client.
+ //
+ if ( FAILED(*phr) )
+ return RPC_S_OK;
+
+ pActParams->ProtseqId = ProtseqId;
+
+ return RPC_S_OK;
+}
+
+CRemoteServer::CRemoteServer(
+ const WCHAR * pwszServer,
+ HRESULT &hr
+ ) : CStringID(pwszServer, hr)
+{
+ InitializeCriticalSection( &hLock );
+
+ memset( HandleList, 0, sizeof(HandleList) );
+}
+
+CRemoteServer::~CRemoteServer()
+{
+ // these objects are never destroyed, this
+ // should never happen
+ Win4Assert("Why Am I Here?");
+}
+
+handle_t
+CRemoteServer::LookupHandle( CToken * pToken, COAUTHINFO* pAuthInfo, BOOL fSecure )
+{
+ handle_t hHandle;
+ int n;
+
+ hHandle = 0;
+
+ EnterCriticalSection( &hLock );
+
+ for ( n = 0; n < MAX_REMOTE_HANDLES; n++ )
+ {
+ if ( (HandleList[n].pToken == pToken) && HandleList[n].Valid)
+ {
+ // if we're looking for a secure handle, check the auth info
+ if ( fSecure && pAuthInfo && !(FEquivalentAuthInfo(HandleList[n].pAuthInfo,pAuthInfo)) )
+ {
+ continue;
+ }
+
+ if ( HandleList[n].fSecure == fSecure )
+ {
+ HandleList[n].Refs++;
+ hHandle = HandleList[n].hRemoteSCM;
+ break;
+ }
+ }
+ }
+
+ LeaveCriticalSection( &hLock );
+
+ return hHandle;
+}
+
+void
+CRemoteServer::ReleaseHandle( handle_t hHandle )
+{
+ int n;
+
+ EnterCriticalSection( &hLock );
+
+ for ( n = 0; n < MAX_REMOTE_HANDLES; n++ )
+ {
+ if ( HandleList[n].hRemoteSCM == hHandle )
+ {
+ HandleList[n].Refs--;
+
+ if ( (HandleList[n].Refs == 0) && ! HandleList[n].Valid )
+ {
+ RpcBindingFree( &HandleList[n].hRemoteSCM );
+ HandleList[n].hRemoteSCM = 0;
+ HandleList[n].pToken = 0;
+ }
+ }
+ }
+
+ LeaveCriticalSection( &hLock );
+}
+
+void
+CRemoteServer::InsertHandle(
+ CToken * pToken,
+ USHORT ProtseqId,
+ handle_t hHandle,
+ COAUTHINFO* pAuthInfo,
+ BOOL fSecure )
+{
+ int n;
+ int FreeSlot;
+ HRESULT hr;
+
+ FreeSlot = -1;
+
+ EnterCriticalSection( &hLock );
+
+ //
+ // First we'll search for a free slot.
+ //
+ for ( n = 0; n < MAX_REMOTE_HANDLES; n++ )
+ {
+ if ( (HandleList[n].Refs == 0) && ! HandleList[n].Valid )
+ {
+ FreeSlot = n;
+ break;
+ }
+ }
+
+ //
+ // OK if there are no free slots. We simply don't have room to cache
+ // the handle in this case.
+ //
+ if ( FreeSlot == -1 )
+ {
+ RpcBindingFree(&hHandle);
+ goto EXIT_INSERT_HANDLE;
+ }
+
+ //
+ // See if we already have another handle cached for this client.
+ //
+ for ( n = 0; n < MAX_REMOTE_HANDLES; n++ )
+ {
+ if ( (HandleList[n].pToken == pToken) && HandleList[n].Valid &&
+ (HandleList[n].fSecure == fSecure) && (FEquivalentAuthInfo(
+ HandleList[n].pAuthInfo,pAuthInfo)))
+ {
+ //
+ // Hmm, what to do. We've found another binding handle for use
+ // by the same client. We'll invalidate this one since it's probably
+ // older.
+ //
+ if ( HandleList[n].Refs == 0 )
+ {
+ RpcBindingFree( &HandleList[n].hRemoteSCM );
+ HandleList[n].hRemoteSCM = 0;
+ HandleList[n].pToken = 0;
+ }
+ HandleList[n].Valid = FALSE;
+ }
+ }
+
+ if( pAuthInfo )
+ {
+ hr = CopyAuthInfo(&(HandleList[FreeSlot].pAuthInfo),pAuthInfo);
+ if ( FAILED(hr) )
+ {
+ RpcBindingFree(&hHandle);
+ goto EXIT_INSERT_HANDLE;
+ }
+ }
+ else
+ {
+ HandleList[FreeSlot].pAuthInfo = NULL;
+ }
+
+ HandleList[FreeSlot].hRemoteSCM = hHandle;
+ HandleList[FreeSlot].ProtseqId = ProtseqId;
+ HandleList[FreeSlot].pToken = pToken;
+ HandleList[FreeSlot].Refs = 0;
+ HandleList[FreeSlot].fSecure = fSecure;
+ HandleList[FreeSlot].Valid = TRUE;
+
+EXIT_INSERT_HANDLE:
+
+ LeaveCriticalSection( &hLock );
+}
+
+void
+CRemoteServer::InvalidateHandle( handle_t hHandle )
+{
+ int n;
+
+ EnterCriticalSection( &hLock );
+
+ for ( n = 0; n < MAX_REMOTE_HANDLES; n++ )
+ {
+ if ( HandleList[n].hRemoteSCM == hHandle )
+ {
+ if ( HandleList[n].Refs == 0 )
+ {
+ RpcBindingFree( &HandleList[n].hRemoteSCM );
+ HandleList[n].hRemoteSCM = 0;
+ HandleList[n].pToken = 0;
+ }
+ HandleList[n].Valid = FALSE;
+ break;
+ }
+ }
+
+ LeaveCriticalSection( &hLock );
+}
+
+USHORT
+CRemoteServer::GetProtseqId( handle_t hHandle )
+{
+ int n;
+ USHORT id;
+
+ id = (USHORT) 0xffff;
+
+ EnterCriticalSection( &hLock );
+
+ for ( n = 0; n < MAX_REMOTE_HANDLES; n++ )
+ {
+ if ( HandleList[n].hRemoteSCM == hHandle )
+ {
+ id = HandleList[n].ProtseqId;
+ break;
+ }
+ }
+
+ LeaveCriticalSection( &hLock );
+
+ return id;
+}
+
+CRemoteServer *
+CRemSrvList::Add(const WCHAR *pwszPath, HRESULT &hr)
+{
+ CStringID csid(pwszPath, hr);
+
+ if ( FAILED(hr) )
+ return NULL;
+
+ CRemoteServer *pRemoteServer = (CRemoteServer *) Search(&csid);
+
+ if ( pRemoteServer == NULL )
+ {
+ pRemoteServer = new CRemoteServer(pwszPath, hr);
+
+ if ( pRemoteServer == NULL )
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ else if ( FAILED(hr) )
+ {
+ delete pRemoteServer;
+ }
+ else if ( Insert(pRemoteServer) == NULL )
+ {
+ hr = E_OUTOFMEMORY;
+ }
+
+ if ( FAILED(hr) )
+ return NULL;
+ }
+
+ return pRemoteServer;
+}
+
+HRESULT
+CRemoteServer::CopyAuthIdentity(
+ COAUTHIDENTITY** ppAuthIdentDest,
+ COAUTHIDENTITY* pAuthIdentSrc)
+{
+ HRESULT hr = E_OUTOFMEMORY;
+ *ppAuthIdentDest = NULL;
+
+ if ( !(*ppAuthIdentDest = (COAUTHIDENTITY*)PrivMemAlloc(sizeof(COAUTHIDENTITY))) )
+ {
+ goto COPY_AUTHIDENTITY_EXIT;
+ }
+
+ (*ppAuthIdentDest)->User = NULL;
+ (*ppAuthIdentDest)->Domain = NULL;
+ (*ppAuthIdentDest)->Password = NULL;
+
+ if ( pAuthIdentSrc->User )
+ {
+ if(!((*ppAuthIdentDest)->User = (USHORT *)
+ PrivMemAlloc((pAuthIdentSrc->UserLength+1) * sizeof(USHORT))))
+ {
+ goto COPY_AUTHIDENTITY_EXIT;
+ }
+ memcpy( (*ppAuthIdentDest)->User,
+ pAuthIdentSrc->User,
+ (pAuthIdentSrc->UserLength + 1) * sizeof(WCHAR));
+ }
+
+ if ( pAuthIdentSrc->Domain )
+ {
+ if(!((*ppAuthIdentDest)->Domain = (USHORT *)
+ PrivMemAlloc((pAuthIdentSrc->DomainLength+1) * sizeof(USHORT))))
+ {
+ goto COPY_AUTHIDENTITY_EXIT;
+ }
+ memcpy( (*ppAuthIdentDest)->Domain,
+ pAuthIdentSrc->Domain,
+ (pAuthIdentSrc->DomainLength + 1) * sizeof(WCHAR));
+ }
+
+ if ( pAuthIdentSrc->Password )
+ {
+ if(!((*ppAuthIdentDest)->Password = (USHORT *)
+ PrivMemAlloc((pAuthIdentSrc->PasswordLength+1) * sizeof(USHORT))))
+ {
+ goto COPY_AUTHIDENTITY_EXIT;
+ }
+ memcpy( (*ppAuthIdentDest)->Password,
+ pAuthIdentSrc->Domain,
+ (pAuthIdentSrc->PasswordLength + 1) * sizeof(WCHAR));
+ }
+
+ (*ppAuthIdentDest)->UserLength = pAuthIdentSrc->UserLength;
+ (*ppAuthIdentDest)->DomainLength = pAuthIdentSrc->DomainLength;
+ (*ppAuthIdentDest)->PasswordLength = pAuthIdentSrc->PasswordLength;
+ (*ppAuthIdentDest)->Flags = pAuthIdentSrc->Flags;
+
+ return S_OK;
+
+COPY_AUTHIDENTITY_EXIT:
+
+ if(*ppAuthIdentDest)
+ {
+ if((*ppAuthIdentDest)->User)
+ {
+ PrivMemFree((*ppAuthIdentDest)->User);
+ }
+
+ if((*ppAuthIdentDest)->Domain)
+ {
+ PrivMemFree((*ppAuthIdentDest)->Domain);
+ }
+
+ if((*ppAuthIdentDest)->Password)
+ {
+ PrivMemFree((*ppAuthIdentDest)->Password);
+ }
+
+ PrivMemFree(*ppAuthIdentDest);
+ }
+
+ return hr;
+}
+
+HRESULT
+CRemoteServer::CopyAuthInfo(
+ COAUTHINFO** ppAuthInfoDest,
+ COAUTHINFO* pAuthInfoSrc)
+{
+ HRESULT hr = E_OUTOFMEMORY;
+ *ppAuthInfoDest = NULL;
+
+ if ( !(*ppAuthInfoDest = (COAUTHINFO*)PrivMemAlloc(sizeof(COAUTHINFO))) )
+ {
+ goto COPY_AUTHINFO_EXIT;
+ }
+
+ // only alloc space for pwszServerPrincName if its non-null
+ if(pAuthInfoSrc->pwszServerPrincName)
+ {
+ if ( !((*ppAuthInfoDest)->pwszServerPrincName =
+ (LPWSTR)PrivMemAlloc((lstrlenW(pAuthInfoSrc->pwszServerPrincName) + 1) *
+ sizeof(WCHAR))) )
+ {
+ goto COPY_AUTHINFO_EXIT;
+ }
+ }
+ else
+ {
+ (*ppAuthInfoDest)->pwszServerPrincName = NULL;
+ }
+
+ // copy the AuthIdentity if its non-null
+ if(pAuthInfoSrc->pAuthIdentityData)
+ {
+ if ( FAILED(CopyAuthIdentity(&((*ppAuthInfoDest)->pAuthIdentityData),
+ pAuthInfoSrc->pAuthIdentityData)) )
+ {
+ goto COPY_AUTHINFO_EXIT;
+ }
+ }
+ else
+ {
+ (*ppAuthInfoDest)->pAuthIdentityData = NULL;
+ }
+
+ (*ppAuthInfoDest)->dwAuthnSvc = pAuthInfoSrc->dwAuthnSvc;
+ (*ppAuthInfoDest)->dwAuthzSvc = pAuthInfoSrc->dwAuthzSvc;
+ (*ppAuthInfoDest)->dwAuthnLevel = pAuthInfoSrc->dwAuthnLevel;
+ (*ppAuthInfoDest)->dwImpersonationLevel = pAuthInfoSrc->dwImpersonationLevel;
+ (*ppAuthInfoDest)->dwCapabilities = pAuthInfoSrc->dwCapabilities;
+
+ if(pAuthInfoSrc->pwszServerPrincName)
+ {
+ lstrcpyW((*ppAuthInfoDest)->pwszServerPrincName,pAuthInfoSrc->pwszServerPrincName);
+ }
+
+ return S_OK;
+
+COPY_AUTHINFO_EXIT:
+
+ if ( *ppAuthInfoDest )
+ {
+ if ( (*ppAuthInfoDest)->pwszServerPrincName )
+ {
+ PrivMemFree( (*ppAuthInfoDest)->pwszServerPrincName );
+ }
+ PrivMemFree( *ppAuthInfoDest );
+ }
+
+ return hr;
+}
+
+BOOL
+CRemoteServer::FEquivalentAuthIdent(
+ COAUTHIDENTITY* pAuthIdent,
+ COAUTHIDENTITY* pAuthIdentOther )
+{
+ if ( pAuthIdent->Flags != pAuthIdentOther->Flags )
+ {
+ return FALSE;
+ }
+
+ ULONG cch;
+
+ if ( pAuthIdent->User && pAuthIdentOther->User )
+ {
+ if ( (cch = pAuthIdent->UserLength) != pAuthIdentOther->UserLength )
+ {
+ return FALSE;
+ }
+
+ if ( memcmp(pAuthIdent->User,pAuthIdentOther->User,(cch+1) * sizeof(WCHAR)) != 0 )
+ {
+ return FALSE;
+ }
+ }
+ else if ( pAuthIdent->User || pAuthIdentOther->User )
+ return FALSE;
+
+ if ( pAuthIdent->Domain && pAuthIdentOther->Domain )
+ {
+ if ( (cch = pAuthIdent->DomainLength) != pAuthIdentOther->DomainLength )
+ {
+ return FALSE;
+ }
+
+ if ( memcmp(pAuthIdent->Domain,pAuthIdentOther->Domain,(cch+1) * sizeof(WCHAR)) != 0 )
+ {
+ return FALSE;
+ }
+ }
+ else if ( pAuthIdent->Domain || pAuthIdentOther->Domain )
+ return FALSE;
+
+ if ( pAuthIdent->Password && pAuthIdentOther->Password )
+ {
+ if ( (cch = pAuthIdent->PasswordLength) != pAuthIdentOther->PasswordLength )
+ {
+ return FALSE;
+ }
+
+ if ( memcmp(pAuthIdent->Password,pAuthIdentOther->Password,(cch+1) * sizeof(WCHAR)) != 0 )
+ {
+ return FALSE;
+ }
+ }
+ else if ( pAuthIdent->Password || pAuthIdentOther->Password )
+ return FALSE;
+
+ return TRUE;
+}
+
+BOOL
+CRemoteServer::FEquivalentAuthInfo(
+ COAUTHINFO* pAuthInfo,
+ COAUTHINFO* pAuthInfoOther)
+{
+ if ( pAuthInfo && pAuthInfoOther )
+ {
+ if ( (pAuthInfo->dwAuthnSvc != pAuthInfoOther->dwAuthnSvc) ||
+ (pAuthInfo->dwAuthzSvc != pAuthInfoOther->dwAuthzSvc) ||
+ (pAuthInfo->dwAuthnLevel != pAuthInfoOther->dwAuthnLevel) ||
+ (pAuthInfo->dwImpersonationLevel != pAuthInfoOther->dwImpersonationLevel) ||
+ (pAuthInfo->dwCapabilities != pAuthInfoOther->dwCapabilities) )
+ {
+ return FALSE;
+ }
+
+ // only compare pwszServerPrincName's if they're both specified
+ if(pAuthInfo->pwszServerPrincName && pAuthInfoOther->pwszServerPrincName)
+ {
+ if ( lstrcmpW(pAuthInfo->pwszServerPrincName,
+ pAuthInfoOther->pwszServerPrincName) != 0 )
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ // if one was NULL, both should be NULL for equality
+ if(pAuthInfo->pwszServerPrincName != pAuthInfoOther->pwszServerPrincName)
+ {
+ return FALSE;
+ }
+ }
+
+ if(pAuthInfo->pAuthIdentityData && pAuthInfoOther->pAuthIdentityData)
+ {
+ if (!(FEquivalentAuthIdent(pAuthInfo->pAuthIdentityData,
+ pAuthInfoOther->pAuthIdentityData)) )
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ // if either authident was NULL, they should both be NULL for equality
+ if(pAuthInfo->pAuthIdentityData != pAuthInfoOther->pAuthIdentityData)
+ {
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ if ( pAuthInfo != pAuthInfoOther )
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+void SkipListDeleteRemoteServer(void *pvRemoteServer)
+{
+ CRemoteServer *p = (CRemoteServer*)pvRemoteServer;
+ // p->CheckSig();
+ delete p;
+}
+
diff --git a/private/ole32/dcomss/olescm/remact.hxx b/private/ole32/dcomss/olescm/remact.hxx
new file mode 100644
index 000000000..d11a2b2e3
--- /dev/null
+++ b/private/ole32/dcomss/olescm/remact.hxx
@@ -0,0 +1,128 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995-1996.
+//
+// File:
+// remact.hxx
+//
+// Contents:
+//
+// Definitions for binding handle cache to remote machines.
+//
+// History:
+//
+//--------------------------------------------------------------------------
+
+#define MAX_REMOTE_HANDLES 8
+
+HRESULT
+RemoteActivationCall(
+ ACTIVATION_PARAMS * pActParams,
+ WCHAR * pwszServerName,
+ WCHAR * pwszPathForServer );
+
+RPC_STATUS
+CallRemoteSCM(
+ handle_t hRemoteSCM,
+ USHORT ProtseqId,
+ ACTIVATION_PARAMS * pActParams,
+ WCHAR * pwszPathForServer,
+ HRESULT * phr );
+
+class CRemSrvList;
+
+extern CRemSrvList *gpCRemSrvList;
+
+class CRemoteServer : public CStringID
+{
+ struct
+ {
+ handle_t hRemoteSCM;
+ USHORT ProtseqId;
+ CToken * pToken;
+ int Refs;
+ BOOL Valid;
+ BOOL fSecure;
+ COAUTHINFO* pAuthInfo;
+ } HandleList[MAX_REMOTE_HANDLES];
+
+ CRITICAL_SECTION hLock;
+
+ static BOOL FEquivalentAuthInfo(
+ COAUTHINFO* pAuthInfo,
+ COAUTHINFO* pAuthInfoOther);
+
+ static BOOL FEquivalentAuthIdent(
+ COAUTHIDENTITY* pAuthIdent,
+ COAUTHIDENTITY* pAuthIdentOther);
+
+ static HRESULT CopyAuthInfo(
+ COAUTHINFO** ppAutInfoDest,
+ COAUTHINFO* pAuthInfoSrc);
+
+ static HRESULT CopyAuthIdentity(
+ COAUTHIDENTITY** ppAuthIdentDest,
+ COAUTHIDENTITY* pAuthIdentSrc);
+
+ static BOOL FNonFatalRpcError(RPC_STATUS rpcStatus);
+
+public:
+
+ CRemoteServer( const WCHAR * pwszServer, HRESULT &hr );
+ ~CRemoteServer();
+
+ HRESULT Activate(
+ RPC_STATUS* pStatus,
+ ACTIVATION_PARAMS* pActParams,
+ WCHAR* pwszPathForServer,
+ WCHAR* pwszServerName,
+ BOOL Secure);
+
+ handle_t LookupHandle(
+ CToken * pToken,
+ COAUTHINFO* pAuthInfo,
+ BOOL fSecure);
+
+ void ReleaseHandle( handle_t hHandle );
+
+ void InsertHandle(
+ CToken * pToken,
+ USHORT ProtseqId,
+ handle_t hHandle,
+ COAUTHINFO* pAuthInfo,
+ BOOL fSecure );
+
+ void InvalidateHandle( handle_t hHandle );
+
+ USHORT GetProtseqId( handle_t hHandle );
+};
+
+void SkipListDeleteRemoteServer(void *pvRemoteServer);
+
+class CRemSrvList : public CSkipList, public CScmAlloc
+{
+public:
+ inline CRemSrvList(HRESULT &hr) :
+ CSkipList((LPFNCOMPARE)(SkipListCompareStringIDs),
+ (LPFNDELETE)(SkipListDeleteRemoteServer),
+ OFFSETBETWEEN(CRemoteServer, CStringID),
+ SKIPLIST_SHARED,
+ &_maxStringID, // NOTE! a pointer to _maxString
+ // is stored in CSkipList so
+ // initialization can occur
+ // after skip list
+ MAX_SERVER_CACHE,
+ hr),
+ _maxStringID(L"\xFFFF\xFFFF", hr) // this could be shared between
+ // this object and CStringLists
+ {
+ }
+
+ CRemoteServer * Add(const WCHAR *pwszPath, HRESULT &hr);
+private:
+ CStringID _maxStringID; // x86 Windows : shared mem
+ // NT : private mem
+};
+
+
diff --git a/private/ole32/dcomss/olescm/remactif.cxx b/private/ole32/dcomss/olescm/remactif.cxx
new file mode 100644
index 000000000..8b369f52f
--- /dev/null
+++ b/private/ole32/dcomss/olescm/remactif.cxx
@@ -0,0 +1,244 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995.
+//
+// File:
+// objexif.cxx
+//
+// Contents:
+// Entry point for remote activation call to SCM/OR.
+//
+// Functions:
+// RemoteActivation
+//
+// History:
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include "scm.hxx"
+#include "port.hxx"
+#include "cls.hxx"
+#include "remact.h"
+#include "dbgprt.hxx"
+
+extern WCHAR SCMMachineName[MAX_COMPUTERNAME_LENGTH+1];
+
+HRESULT GetServerPath( WCHAR * pwszPath, WCHAR ** pwszServerPath );
+
+extern CClassCacheList *gpClassCache;
+
+DWORD RegisterAuthInfoIfNecessary();
+
+error_status_t _RemoteActivation(
+ handle_t hRpc,
+ ORPCTHIS *ORPCthis,
+ ORPCTHAT *ORPCthat,
+ const GUID *Clsid,
+ WCHAR *pwszObjectName,
+ MInterfacePointer *pObjectStorage,
+ DWORD ClientImpLevel,
+ DWORD Mode,
+ DWORD Interfaces,
+ IID *pIIDs,
+ unsigned short cRequestedProtseqs,
+ unsigned short aRequestedProtseqs[],
+ OXID *pOxid,
+ DUALSTRINGARRAY **ppdsaOxidBindings,
+ IPID *pipidRemUnknown,
+ DWORD *pAuthnHint,
+ COMVERSION *pServerVersion,
+ HRESULT *phr,
+ MInterfacePointer **ppInterfaceData,
+ HRESULT *pResults )
+{
+ RPC_STATUS sc;
+ ACTIVATION_PARAMS ActParams;
+ LOCALTHIS Localthis;
+
+ Localthis.dwClientThread = 0;
+ Localthis.callcat = CALLCAT_SYNCHRONOUS;
+
+ ORPCthat->flags = 0;
+ ORPCthat->extensions = NULL;
+
+ pServerVersion->MajorVersion = COM_MAJOR_VERSION;
+ pServerVersion->MinorVersion = COM_MINOR_VERSION;
+
+ *pOxid = 0;
+
+ sc = RegisterAuthInfoIfNecessary();
+
+ if ( sc != ERROR_SUCCESS )
+ {
+ *phr = HRESULT_FROM_WIN32(sc);
+ return RPC_S_OK;
+ }
+
+ // Fail immediately unless "EnableDCOM" is on
+ if (gpClassCache->GetEnableDCOM() == REMOTEACCESSBY_NOBODY)
+ {
+ *phr = E_ACCESSDENIED;
+ return RPC_S_OK;
+ }
+
+ if ( pwszObjectName || pObjectStorage )
+ ActParams.MsgType = GETPERSISTENTEX;
+ else
+ ActParams.MsgType = (Mode == MODE_GET_CLASS_OBJECT) ?
+ GETCLASSOBJECTEX : CREATEINSTANCEEX;
+
+ ActParams.hRpc = hRpc;
+ ActParams.ProcessSignature = 0;
+ ActParams.pProcess = 0;
+ ActParams.pToken = 0;
+
+ ActParams.Clsid = Clsid;
+ ActParams.pwszServer = NULL;
+ ActParams.pwszWinstaDesktop = NULL;
+ ActParams.ClsContext = CLSCTX_LOCAL_SERVER;
+
+ ActParams.ORPCthis = ORPCthis;
+ ActParams.Localthis = &Localthis;
+ ActParams.ORPCthat = ORPCthat;
+
+ ActParams.RemoteActivation = TRUE;
+
+ ActParams.Interfaces = Interfaces;
+ ActParams.pIIDs = pIIDs;
+
+ ActParams.Mode = Mode;
+ ActParams.pIFDStorage = pObjectStorage;
+
+ if ( pwszObjectName )
+ {
+ *phr = GetServerPath( pwszObjectName,
+ &ActParams.pwszPath );
+
+ if ( FAILED(*phr) )
+ return RPC_S_OK;
+ }
+ else
+ {
+ ActParams.pwszPath = 0;
+ }
+
+ ActParams.pIFDROT = 0;
+
+ ActParams.pOxidServer = pOxid;
+
+ //
+ // The following OR fields are not used while servicing a
+ // remote activation.
+ //
+ ActParams.ppServerORBindings = 0;
+ ActParams.Apartment = FALSE;
+ ActParams.pOxidInfo = NULL;
+ ActParams.pLocalMidOfRemote = NULL;
+
+ ActParams.FoundInROT = FALSE;
+ ActParams.ppIFD = ppInterfaceData;
+ ActParams.pResults = pResults;
+
+ *phr = Activation( &ActParams );
+
+ if ( pwszObjectName && (ActParams.pwszPath != pwszObjectName) )
+ PrivMemFree( ActParams.pwszPath );
+
+ if ( FAILED(*phr) || (*ActParams.pOxidServer == 0) )
+ return RPC_S_OK;
+
+ sc = _ResolveOxid( hRpc,
+ ActParams.pOxidServer,
+ cRequestedProtseqs,
+ aRequestedProtseqs,
+ ppdsaOxidBindings,
+ pipidRemUnknown,
+ pAuthnHint );
+
+ *phr = HRESULT_FROM_WIN32(sc);
+ return RPC_S_OK;
+}
+
+//
+// This is to work around limitations in NT's current security/rdr.
+// If we get a UNC path to this machine, convert it into a drive based
+// path. A server activated as the client can not open any UNC path
+// file, even if local, so we make it drive based.
+//
+HRESULT GetServerPath(
+ WCHAR * pwszPath,
+ WCHAR ** pwszServerPath )
+{
+ WCHAR * pwszFinalPath;
+
+ pwszFinalPath = pwszPath;
+ *pwszServerPath = pwszPath;
+
+ if ( (pwszPath[0] == L'\\') && (pwszPath[1] == L'\\') )
+ {
+ WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH+1];
+ WCHAR * pwszShareName;
+ WCHAR * pwszShareEnd;
+ PSHARE_INFO_2 pShareInfo;
+ NET_API_STATUS Status;
+ HRESULT hr;
+
+ // It's already UNC so this had better succeed.
+ hr = GetMachineName( pwszPath, wszMachineName, FALSE );
+
+ if ( FAILED(hr) )
+ return hr;
+
+ if ( lstrcmpiW( wszMachineName, SCMMachineName ) == 0 )
+ {
+ pwszShareName = pwszPath + 2;
+ while ( *pwszShareName++ != L'\\' )
+ ;
+
+ pwszShareEnd = pwszShareName;
+ while ( *pwszShareEnd != L'\\' )
+ pwszShareEnd++;
+
+ // This is OK, we're just munching on the string the RPC stub passed us.
+ *pwszShareEnd = 0;
+
+ pShareInfo = 0;
+ Status = ScmNetShareGetInfo(
+ NULL,
+ pwszShareName,
+ 2,
+ (LPBYTE *)&pShareInfo );
+
+ if ( Status != STATUS_SUCCESS )
+ return (ULONG) CO_E_BAD_PATH;
+
+ pwszFinalPath = (WCHAR *) PrivMemAlloc( sizeof(WCHAR) * (MAX_PATH+1) );
+
+ if ( ! pwszFinalPath )
+ {
+ LocalFree( pShareInfo );
+ return (ULONG) E_OUTOFMEMORY;
+ }
+
+ lstrcpyW( pwszFinalPath, pShareInfo->shi2_path );
+ *pwszShareEnd = L'\\';
+ lstrcatW( pwszFinalPath, pwszShareEnd );
+
+ //
+ // Netapi32.dll midl_user_allocate calls LocalAlloc, so use
+ // LocalFree to free up the stuff the stub allocated.
+ //
+ LocalFree( pShareInfo );
+ }
+ }
+
+ *pwszServerPath = pwszFinalPath;
+ return S_OK;
+}
+
+
+
diff --git a/private/ole32/dcomss/olescm/rotif.cxx b/private/ole32/dcomss/olescm/rotif.cxx
new file mode 100644
index 000000000..a27026dde
--- /dev/null
+++ b/private/ole32/dcomss/olescm/rotif.cxx
@@ -0,0 +1,650 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: rotif.cxx
+//
+// Contents: Initialization for SCM ROT and RPC interface
+//
+// Functions: InitScmRot
+// IrotRegister
+// IrotRevoke
+// IrotIsRunning
+// IrotGetObject
+// IrotNoteChangeTime
+// IrotGetTimeOfLastChange
+// IrotEnumRunning
+// GetObjectFromRot
+//
+// History: 24-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <headers.cxx>
+#include <rotif.hxx>
+#include <rothelp.hxx>
+#include <irot.h>
+#include "dbgprt.hxx"
+
+CScmRot *gpscmrot = NULL;
+
+extern void CheckLocalCall( handle_t hRpc );
+
+#ifndef _CHICAGO_
+//+-------------------------------------------------------------------------
+//
+// Function: InitScmRot
+//
+// Synopsis: Initialize ROT Directory for the SCM
+// NOTE: if InitRotDir is ever called by any process other than the
+// SCM then the RpcServerRegisterIf may fail with RPC_S_TYPE_ALREADY_REGISTERED
+// in some unusal cases. Change the error checking code to ignore that error.
+//
+// Returns: S_OK - Created ROT directory successfully
+//
+// History: 17-Nov-93 Ricksa Created
+// 26-Jul-94 AndyH Added warning above while bug hunting.
+// 25-Jan-95 Ricksa New rot
+//
+// Notes: This routine is only in non-chicago builds
+//
+//--------------------------------------------------------------------------
+HRESULT InitScmRot()
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN InitScmRot \n", NULL));
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ gpscmrot = new CScmRot(hr, ROTHINT_NAME);
+
+ if (SUCCEEDED(hr))
+ {
+ SCODE sc = RpcServerRegisterIf(IROT_ServerIfHandle, 0, 0);
+
+ Win4Assert((sc == 0) && "RpcServerRegisterIf for IRotDir failed!");
+
+ if ( sc == ERROR_SUCCESS )
+ {
+ hr = S_OK;
+ }
+ else
+ {
+ hr = HRESULT_FROM_WIN32(sc);
+ delete gpscmrot;
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT InitScmRot ( %lx )\n", NULL, hr));
+
+ return hr;
+}
+#endif // !_CHICAGO_
+
+//+-------------------------------------------------------------------------
+//
+// Function: IrotRegister
+//
+// Synopsis: Main entry point for registering an item in the ROT
+//
+// Arguments: [hRpc] - rpc handle to SCM
+// [pmkeqbuf] - moniker equality buffer
+// [pifdObject] - marshaled object
+// [pifdObjectName] - marshaled moniker
+// [pfiletime] - time of last change
+// [dwProcessID] - process ID for object
+// [psrkRegister] - SCM registration ID
+// [prpcstat] - RPC communication status
+//
+// Returns: NOERROR
+//
+// History: 30-Jan-95 Ricksa Created
+//
+// Notes: The purpose of this routine is really just to make the
+// code more readable.
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT IrotRegister(
+ handle_t hRpc,
+#ifndef _CHICAGO_
+ PHPROCESS phProcess,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ MNKEQBUF *pmkeqbuf,
+ InterfaceData *pifdObject,
+ InterfaceData *pifdObjectName,
+ FILETIME *pfiletime,
+ DWORD dwProcessID,
+#ifndef _CHICAGO_
+ WCHAR *pwszServerExe,
+#endif
+ SCMREGKEY *psrkRegister,
+ error_status_t *prpcstat)
+{
+ CheckLocalCall( hRpc );
+
+ VDATEHEAP();
+
+ *prpcstat = RPC_S_OK;
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "%p _IN IrotRegister\n", NULL));
+ DbgPrintMnkEqBuf("_IN Moinker Compare Buffer:", pmkeqbuf);
+ DbgPrintIFD("_IN Object Interface Data:", pifdObject);
+ DbgPrintIFD("_IN Moniker Interface Data:", pifdObject);
+ DbgPrintFileTime("_IN FileTime: ", pfiletime);
+ CairoleDebugOut((DEB_SCM, "_IN Process ID: %lX\n", dwProcessID));
+
+#endif // DBG == 1
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ if (gpscmrot != NULL)
+ {
+ hr = gpscmrot->Register(
+#ifndef _CHICAGO_
+ ((CProcess *)phProcess)->GetToken(),
+ pwszWinstaDesktop,
+#endif
+ pmkeqbuf,
+ pifdObject,
+ pifdObjectName,
+ pfiletime,
+ dwProcessID,
+#ifndef _CHICAGO_
+ pwszServerExe,
+#endif
+ psrkRegister);
+ }
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "%p OUT IrotRegister\n", NULL));
+ CairoleDebugOut((DEB_SCM, "OUT Hresult %lX\n", hr));
+
+ if (SUCCEEDED(hr))
+ {
+ DbgPrintScmRegKey("OUT Register Key: ", psrkRegister);
+ }
+
+#endif // DBG == 1
+
+ VDATEHEAP();
+ return hr;
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IrotRevoke
+//
+// Synopsis: Main entry point for revoking an item from the ROT
+//
+// Arguments: [hRpc] - rpc handle to SCM
+// [psrkRegister] - SCM registration ID
+// [fServer] - whether object server is deregistering
+// [ppifdObject] - returned marshaled object
+// [ppifdObjectName] - returned marshaled moniker
+// [prpcstat] - RPC communication status
+//
+// Returns: NOERROR
+//
+// History: 30-Jan-95 Ricksa Created
+//
+// Notes: The purpose of this routine is really just to make the
+// code more readable.
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT IrotRevoke(
+ handle_t hRpc,
+ SCMREGKEY *psrkRegister,
+ BOOL fServer,
+ InterfaceData **ppifdObject,
+ InterfaceData **ppifdName,
+ error_status_t *prpcstat)
+{
+ CheckLocalCall( hRpc );
+
+ VDATEHEAP();
+
+ *prpcstat = RPC_S_OK;
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "%p _IN IrotRevoke\n", NULL));
+ DbgPrintScmRegKey("_IN Revoke Key: ", psrkRegister);
+ CairoleDebugOut((DEB_SCM, "_IN Server Flag: %s\n",
+ fServer ? "Server" : "Client"));
+ CairoleDebugOut((DEB_SCM, "_IN Object Interface Data Ptr: %lx\n",
+ ppifdObject));
+ CairoleDebugOut((DEB_SCM, "_IN Moniker Interface Data Ptr: %lx\n",
+ ppifdName));
+
+#endif // DBG == 1
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ if (gpscmrot != NULL)
+ {
+ hr = gpscmrot->Revoke(psrkRegister, fServer, ppifdObject, ppifdName);
+ }
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "%p OUT IrotRevoke\n", NULL));
+ CairoleDebugOut((DEB_SCM, "OUT Hresult : %lx\n", hr));
+
+ if (*ppifdObject != NULL)
+ {
+ DbgPrintIFD("OUT Object Interface Data:", *ppifdObject);
+ }
+
+ if (*ppifdName != NULL)
+ {
+ DbgPrintIFD("OUT Moniker Interface Data:", *ppifdName);
+ }
+
+#endif // DBG == 1
+
+ VDATEHEAP();
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IrotIsRunning
+//
+// Synopsis: Main entry point for determining if an entry is in the ROT
+//
+// Arguments: [hRpc] - rpc handle to SCM
+// [pmkeqbuf] - moniker equality buffer
+// [prpcstat] - RPC communication status
+//
+// Returns: NOERROR
+//
+// History: 30-Jan-95 Ricksa Created
+//
+// Notes: The purpose of this routine is really just to make the
+// code more readable.
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT IrotIsRunning(
+ handle_t hRpc,
+#ifndef _CHICAGO_
+ PHPROCESS phProcess,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ MNKEQBUF *pmkeqbuf,
+ error_status_t *prpcstat)
+{
+ CheckLocalCall( hRpc );
+
+ VDATEHEAP();
+
+ *prpcstat = RPC_S_OK;
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "%p _IN IrotIsRunning\n", NULL));
+ DbgPrintMnkEqBuf("_IN Moniker Compare Buffer:", pmkeqbuf);
+
+#endif // DBG == 1
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ if (gpscmrot != NULL)
+ {
+ hr = gpscmrot->IsRunning(
+#ifndef _CHICAGO_
+ ((CProcess *)phProcess)->GetToken(),
+ pwszWinstaDesktop,
+#endif
+ pmkeqbuf);
+ }
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "%p OUT IrotIsRunning\n", NULL));
+ CairoleDebugOut((DEB_SCM, "OUT Hresult : %lx\n", hr));
+
+#endif // DBG == 1
+
+ VDATEHEAP();
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IrotGetObject
+//
+// Synopsis: Main entry point for getting an object from the ROT
+//
+// Arguments: [hRpc] - rpc handle to SCM
+// [dwProcessID] - process id for object
+// [pmkeqbuf] - moniker equality buffer
+// [psrkRegister] - Registration ID of returned Object
+// [ppifdObject] - returned marshaled object
+// [prpcstat] - RPC communication status
+//
+// Returns: NOERROR
+//
+// History: 30-Jan-95 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT IrotGetObject(
+ handle_t hRpc,
+#ifndef _CHICAGO_
+ PHPROCESS phProcess,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ DWORD dwProcessID,
+ MNKEQBUF *pmkeqbuf,
+ SCMREGKEY *psrkRegister,
+ InterfaceData **ppifdObject,
+ error_status_t *prpcstat)
+{
+ CheckLocalCall( hRpc );
+
+ VDATEHEAP();
+
+ *prpcstat = RPC_S_OK;
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "%p _IN IrotGetObject\n", NULL));
+ CairoleDebugOut((DEB_SCM, "_IN Process ID: %lX\n", dwProcessID));
+ DbgPrintMnkEqBuf("_IN Moniker Compare Buffer:", pmkeqbuf);
+
+#endif // DBG == 1
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ if (gpscmrot != NULL)
+ {
+ hr = gpscmrot->GetObject(
+#ifndef _CHICAGO_
+ ((CProcess *)phProcess)->GetToken(),
+ pwszWinstaDesktop,
+#endif
+ dwProcessID,
+ pmkeqbuf,
+ psrkRegister,
+ ppifdObject);
+ }
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "%p OUT IrotGetObject\n", NULL));
+ CairoleDebugOut((DEB_SCM, "OUT Hresult : %lx\n", hr));
+
+ if (SUCCEEDED(hr))
+ {
+ DbgPrintScmRegKey("OUT Register Key: ", psrkRegister);
+ DbgPrintIFD("OUT Object Interface Data:", *ppifdObject);
+ }
+
+#endif // DBG == 1
+
+ VDATEHEAP();
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IrotNoteChangeTime
+//
+// Synopsis: Main entry point for setting the change time of an object
+// int the ROT.
+//
+// Arguments: [hRpc] - rpc handle to SCM
+// [psrkRegister] - Registration ID of Object to update
+// [pfiletime] - new change time for the object
+// [prpcstat] - RPC communication status
+//
+// Returns: NOERROR
+//
+// History: 30-Jan-95 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT IrotNoteChangeTime(
+ handle_t hRpc,
+ SCMREGKEY *psrkRegister,
+ FILETIME *pfiletime,
+ error_status_t *prpcstat)
+{
+ CheckLocalCall( hRpc );
+
+ VDATEHEAP();
+
+ *prpcstat = RPC_S_OK;
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "%p _IN IrotNoteChangeTime\n", NULL));
+ DbgPrintScmRegKey("_IN Revoke Key: ", psrkRegister);
+ DbgPrintFileTime("_IN FileTime: ", pfiletime);
+
+#endif // DBG == 1
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ if (gpscmrot != NULL)
+ {
+ hr = gpscmrot->NoteChangeTime(psrkRegister, pfiletime);
+ }
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "%p OUT IrotRevoke\n", NULL));
+ CairoleDebugOut((DEB_SCM, "OUT Hresult : %lx\n", hr));
+
+#endif // DBG == 1
+
+ VDATEHEAP();
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IrotGetTimeOfLastChange
+//
+// Synopsis: Main entry point for getting the change time of an object
+// int the ROT.
+//
+// Arguments: [hRpc] - rpc handle to SCM
+// [pmkeqbuf] - Moniker for object
+// [pfiletime] - new change time for the object
+// [prpcstat] - RPC communication status
+//
+// Returns: NOERROR
+//
+// History: 30-Jan-95 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT IrotGetTimeOfLastChange(
+ handle_t hRpc,
+#ifndef _CHICAGO_
+ PHPROCESS phProcess,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ MNKEQBUF *pmkeqbuf,
+ FILETIME *pfiletime,
+ error_status_t *prpcstat)
+{
+ CheckLocalCall( hRpc );
+
+ VDATEHEAP();
+
+ *prpcstat = RPC_S_OK;
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "%p _IN IrotGetTimeOfLastChange\n", NULL));
+ DbgPrintMnkEqBuf("_IN Moniker Compare Buffer:", pmkeqbuf);
+
+#endif // DBG == 1
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ if (gpscmrot != NULL)
+ {
+ hr = gpscmrot->GetTimeOfLastChange(
+#ifndef _CHICAGO_
+ ((CProcess *)phProcess)->GetToken(),
+ pwszWinstaDesktop,
+#endif
+ pmkeqbuf,
+ pfiletime);
+ }
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "%p OUT IrotGetTimeOfLastChange\n", NULL));
+ CairoleDebugOut((DEB_SCM, "OUT Hresult : %lx\n", hr));
+ DbgPrintFileTime("OUT FileTime: ", pfiletime);
+
+#endif // DBG == 1
+
+ VDATEHEAP();
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IrotEnumRunning
+//
+// Synopsis: Main entry point for getting all monikers to running objects
+// int the ROT.
+//
+// Arguments: [hRpc] - rpc handle to SCM
+// [ppMKIFList] - list of marshaled monikers to running objects
+// [prpcstat] - RPC communication status
+//
+// Returns: NOERROR
+//
+// History: 30-Jan-95 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT IrotEnumRunning(
+ handle_t hRpc,
+#ifndef _CHICAGO_
+ PHPROCESS phProcess,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ MkInterfaceList **ppMkIFList,
+ error_status_t *prpcstat)
+{
+ CheckLocalCall( hRpc );
+
+ VDATEHEAP();
+
+ *prpcstat = RPC_S_OK;
+
+ CairoleDebugOut((DEB_SCM, "%p _IN IrotEnumRunning\n", NULL));
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ if (gpscmrot != NULL)
+ {
+ hr = gpscmrot->EnumRunning(
+#ifndef _CHICAGO_
+ ((CProcess *)phProcess)->GetToken(),
+ pwszWinstaDesktop,
+#endif
+ ppMkIFList);
+ }
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "%p OUT IrotEnumRunning\n", NULL));
+ CairoleDebugOut((DEB_SCM, "OUT Hresult : %lx\n", hr));
+
+ if (SUCCEEDED(hr))
+ {
+ DbgPrintMkIfList("OUT Moniker IF List: ", ppMkIFList);
+ }
+
+#endif // DBG == 1
+
+ VDATEHEAP();
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetObjectFromRot
+//
+// Synopsis: Helper for binding to locate an object in the ROT
+//
+// Arguments: [pwszPath] - path for bind
+// [ppifdObject] - marshaled output buffer
+//
+// Returns: NOERROR
+//
+// Algorithm: Get the ROT. Create a moniker comparison buffer for searching
+// the ROT. Then try to get the object out of the ROT.
+//
+// History: 30-Jan-95 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+HRESULT GetObjectFromRot(
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ WCHAR *pwszPath,
+ InterfaceData **ppifdObject)
+{
+ VDATEHEAP();
+
+ CairoleDebugOut((DEB_ROT, "%p _IN GetObjectFromRot "
+ "( %p , %p )\n", NULL, pwszPath, ppifdObject));
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ if (gpscmrot != NULL)
+ {
+ // Create a moniker equality buffer from path
+ CTmpMkEqBuf tmeb;
+
+ hr = CreateFileMonikerComparisonBuffer(pwszPath, tmeb.GetBuf(),
+ tmeb.GetSize(), tmeb.GetSizeAddr());
+
+ if (hr == NOERROR)
+ {
+ // SCMREGKEY which we won't really use
+ SCMREGKEY srkRegister;
+
+ hr = gpscmrot->GetObject(
+#ifndef _CHICAGO_
+ pToken,
+ pwszWinstaDesktop,
+#endif
+ 0,
+ tmeb.GetMkEqBuf(),
+ &srkRegister,
+ ppifdObject );
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT GetObjectFromRot ( %lx ) [ %p ]\n",
+ NULL, hr, *ppifdObject));
+
+ return hr;
+}
+
diff --git a/private/ole32/dcomss/olescm/rotif.hxx b/private/ole32/dcomss/olescm/rotif.hxx
new file mode 100644
index 000000000..ecb7ae2b8
--- /dev/null
+++ b/private/ole32/dcomss/olescm/rotif.hxx
@@ -0,0 +1,30 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: rotif.hxx
+//
+// Contents: ROT Globals for use by SCM
+//
+// History: 24-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __ROTIF_HXX__
+#define __ROTIF_HXX__
+
+#include <scmrot.hxx>
+
+extern CScmRot *gpscmrot;
+
+HRESULT GetObjectFromRot(
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ WCHAR *pwszPath,
+ InterfaceData **ppifdObject);
+
+HRESULT InitScmRot(void);
+
+#endif // __ROTIF_HXX__
diff --git a/private/ole32/dcomss/olescm/rpcalloc.cxx b/private/ole32/dcomss/olescm/rpcalloc.cxx
new file mode 100644
index 000000000..972cae692
--- /dev/null
+++ b/private/ole32/dcomss/olescm/rpcalloc.cxx
@@ -0,0 +1,64 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: rpcalloc.cxx
+//
+// Contents: functions for RPC memory allocation
+//
+// Functions: MIDL_user_allocate
+// MIDL_user_free
+//
+// History: 24-Apr-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <headers.cxx>
+#pragma hdrstop
+#include <memapi.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Function: MIDL_user_allocate
+//
+// Synopsis: Allocate memory for RPC
+//
+// Arguments: [cNeeded] - bytes needed
+//
+// Returns: Pointer to block allocated
+//
+// History: 24-Apr-93 Ricksa Created
+// 17-Feb-94 AlexT Use PrivMemAlloc
+//
+//--------------------------------------------------------------------------
+
+extern "C" void * __RPC_API MIDL_user_allocate(size_t cb)
+{
+#if DBG==1
+#ifdef _X86_
+ // Debug X86 PrivMemAlloc does not guarantee 8 byte alignment, so
+ // make sure cb is a multiple of 8
+ cb = ((cb + 7) / 8) * 8;
+#endif // _X86_
+#endif // DBG
+
+ return(PrivMemAlloc(cb));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: MIDL_user_free
+//
+// Synopsis: Free memory allocated by call above
+//
+// Arguments: [pv] - memory block to free
+//
+// History: 24-Apr-93 Ricksa Created
+// 17-Feb-94 AlexT Use PrivMemFree
+//
+//--------------------------------------------------------------------------
+
+extern "C" void __RPC_API MIDL_user_free(void *pv)
+{
+ PrivMemFree(pv);
+}
diff --git a/private/ole32/dcomss/olescm/scm.hxx b/private/ole32/dcomss/olescm/scm.hxx
new file mode 100644
index 000000000..e7434ac8c
--- /dev/null
+++ b/private/ole32/dcomss/olescm/scm.hxx
@@ -0,0 +1,283 @@
+//+-------------------------------------------------------------------
+//
+// File: scm.hxx
+//
+// Contents: Common stuff for OLE Service (SCM)
+//
+// History: 03-Jun-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+// 03-Nov-94 BillMo ole32.dll contains scm
+// (added notes below on defs.)
+// 25-Oct-95 BruceMa Add support for Services
+//
+//---------------------------------------------------------------------
+
+#ifdef _CHICAGO_
+#include "chicago\scm.hxx"
+#else
+
+#ifndef __SCM_HXX__
+#define __SCM_HXX__
+
+#define SCM_ALLOW_SHARED_WOW 0
+#define SCM_FORCE_SEPARATE_WOW 1
+
+#define SHARED_SW L"/SHARED_WOW"
+#define SEPARATE_SW L"/SEPARATE_WOW"
+
+#include <scmmem.hxx>
+
+#define GUIDSTR_MAX (1+ 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
+
+#ifndef _CHICAGO_
+#define IFSECURITY(x) x,
+#else
+#define IFSECURITY(x)
+#endif
+
+//
+// Here are some debug only routines
+//
+#if DBG == 1
+extern char *apszModelStrings[4];
+WCHAR *FormatGuid(const GUID& rguid, WCHAR *pwszGuid);
+#endif
+
+#ifndef _CHICAGO_
+
+//---------------------------------------------------------------------
+// OLE with SCM -- prototypes
+//---------------------------------------------------------------------
+
+DWORD Update(void *);
+LONG LoadClassCache(void);
+HRESULT InitSCMRegistry();
+
+extern LPCWSTR pwszScmProtocolSequence[];
+extern LPCWSTR pwszScmEndPoint[];
+
+//
+// NT lock and mutex classes
+//
+
+typedef class CLock CPortableLock;
+typedef class CMutexSem CDynamicPortableMutex;
+typedef class COleStaticMutexSem CStaticPortableMutex;
+typedef class COleStaticLock CStaticPortableLock;
+
+typedef DWORD (APIENTRY * GET_UNIVERSAL_NAME_FUNC)(
+ LPCWSTR lpLocalPath,
+ DWORD dwInfoLevel,
+ LPVOID lpBuffer,
+ LPDWORD lpBufferSize
+ );
+
+DWORD APIENTRY ScmWNetGetUniversalName(
+ LPCWSTR lpLocalPath,
+ DWORD dwInfoLevel,
+ LPVOID lpBuffer,
+ LPDWORD lpBufferSize
+ );
+
+typedef NET_API_STATUS (NET_API_FUNCTION * NET_SHARE_GET_INFO_FUNC)(
+ LPTSTR servername,
+ LPTSTR netname,
+ DWORD level,
+ LPBYTE *bufptr
+ );
+
+NET_API_STATUS NET_API_FUNCTION ScmNetShareGetInfo(
+ LPTSTR servername,
+ LPTSTR netname,
+ DWORD level,
+ LPBYTE *bufptr
+ );
+
+NTSTATUS
+DfsFsctl(
+ HANDLE DfsHandle,
+ ULONG FsControlCode,
+ PVOID InputBuffer,
+ ULONG InputBufferLength,
+ PVOID OutputBuffer,
+ PULONG OutputBufferLength);
+
+NTSTATUS
+DfsOpen(
+ PHANDLE DfsHandle);
+
+#else
+
+//
+// x86 Windows lock and mutex classes
+//
+
+typedef class CLockSmMutex CPortableLock;
+class CDynamicPortableMutex : public CSmMutex
+{
+public:
+ inline VOID Request()
+ {
+ Get();
+ }
+};
+typedef CDynamicPortableMutex CStaticPortableMutex;
+typedef CPortableLock CStaticPortableLock;
+
+#endif
+
+#define OLE32_DLL L"OLE32.DLL"
+#define OLE32_BYTE_LEN sizeof(OLE32_DLL)
+#define OLE32_CHAR_LEN (sizeof(OLE32_DLL) / sizeof(WCHAR) - 1)
+
+#define SCM_EVENT_SOURCE L"DCOM"
+
+//+-------------------------------------------------------------------------
+//
+// Function: NotFoundError
+//
+// Synopsis: Convert registry not found errors to TRUE
+//
+// Arguments: [err] - Input error
+//
+// Returns: TRUE - registry entry was not found
+// FALSE - some other error
+//
+// History: 09-Nov-94 Ricksa Made inline and gave a header
+//
+//--------------------------------------------------------------------------
+inline BOOL NotFoundError(LONG err)
+{
+ return(err == ERROR_FILE_NOT_FOUND || err == ERROR_BAD_PATHNAME);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CAppIDData
+//
+// Purpose: Class to read registry entry for an appid.
+//
+// Interface: ReadEntries -- read the given classes info into
+// the CAppIDData.
+//
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+class CAppIDData
+{
+public:
+ CAppIDData();;
+
+ ~CAppIDData();
+
+
+ LONG ReadEntries( LPOLESTR pwszAppID );
+
+ void Cleanup();
+
+//private:
+ WCHAR *pwszRemoteServerName;
+
+ WCHAR *pwszLocalService;
+ WCHAR *pwszServiceArgs;
+
+ WCHAR *pwszRunAsUserName;
+ WCHAR *pwszRunAsDomainName;
+
+ SECURITY_DESCRIPTOR * pSD;
+
+ BOOL fHasRemoteServerName;
+ BOOL fHasService;
+ BOOL fActivateAtStorage;
+
+ LONG err;
+ LONG errClsReg;
+ LONG dwSaveErr;
+
+};
+//+-------------------------------------------------------------------------
+//
+// Class: CClassRegistryReader
+//
+// Purpose: Class to read registry. Reads one cls entrie.
+//
+// Interface: ReadSingleClass -- read the given classes info into
+// the CRegistryReader, ready to
+// by added to gcllClassCache by the
+// client calling NewClassData.
+//
+// DoAdd -- Add the values previously read by ReadSingleClass
+// to the gcllClassCache.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CClassCacheList;
+class CClassData;
+
+class CClassRegistryReader
+{
+public:
+ CClassRegistryReader(); // open CLSID section of registry
+ ~CClassRegistryReader();
+
+ LONG ReadSingleClass(
+ REFCLSID rclsid,
+ BOOL CheckTreatAs,
+ BOOL CheckAutoConvert );
+
+ CClassData * NewClassData(HRESULT &hr);
+
+private:
+
+ void InitInner();
+ LONG ReadClassEntry(HKEY hKey, BOOL CheckTreatAs, BOOL CheckAutoConvert);
+
+ FILETIME ftLastWrite;
+
+ TCHAR awName[MAX_PATH];
+
+ DWORD cName;
+ DWORD iSubKey;
+ LONG err;
+ LONG errClsReg;
+ LONG dwSaveErr;
+ HKEY hClsReg;
+#ifdef DCOM
+ // NT 5.0 BOOL _fShared;
+#endif // DCOM
+
+ WCHAR awcsLocalServer[MAX_PATH];
+ WCHAR awcsAppID[40];
+ WCHAR *pwszLocalServer;
+ LONG lLocalServer;
+ ULONG lAppID;
+ WCHAR *pwszAppID;
+#ifdef _CAIRO_
+ WCHAR awcsActivateAtBits[4];
+#endif
+ WCHAR awcsDebug[4];
+
+ GUID guidClassID;
+ LONG lDebug;
+ BOOL fHasLocalServer;
+ BOOL f16Bit;
+ CAppIDData * pAppIDData;
+};
+
+#include <scm.h>
+#ifdef DCOM
+#define IFDCOM(x) x,
+#else
+#define IFDCOM(x)
+#endif
+
+#endif // __SCM_HXX__
+
+#endif
+
+
diff --git a/private/ole32/dcomss/olescm/scm_afv.h b/private/ole32/dcomss/olescm/scm_afv.h
new file mode 100644
index 000000000..b78f3cf86
--- /dev/null
+++ b/private/ole32/dcomss/olescm/scm_afv.h
@@ -0,0 +1,73 @@
+#ifndef __SCMARRAY_FV_H__
+#define __SCMARRAY_FV_H__
+
+////////////////////////////////////////////////////////////////////////////
+// class CScmArrayFValue - an array containing fixed size elements,
+//
+////////////////////////////////////////////////////////////////////////////
+
+
+class FAR CScmArrayFValue
+{
+public:
+
+// Construction
+ CScmArrayFValue(UINT cbValue);
+ ~CScmArrayFValue();
+
+// Attributes
+ int GetSize() const
+ { return m_nSize; }
+ int GetUpperBound() const
+ { return m_nSize-1; }
+ BOOL SetSize(int nNewSize, int nGrowBy = -1);
+ int GetSizeValue() const
+ { return m_cbValue; }
+
+// Operations
+ // Clean up
+ void FreeExtra();
+ void RemoveAll()
+ { SetSize(0); }
+
+ // return pointer to element; index must be in range
+#ifdef _DEBUG
+ // with debug checks
+ LPVOID GetAt(int nIndex) const
+ { return _GetAt(nIndex); }
+#else
+ // no debug checks
+ LPVOID GetAt(int nIndex) const
+ { return &m_pData[nIndex * m_cbValue]; }
+#endif
+ LPVOID _GetAt(int nIndex) const;
+
+ // set element; index must be in range
+ void SetAt(int nIndex, LPVOID pValue);
+
+ // find element given part of one; offset is offset into value; returns
+ // -1 if element not found; use IndexOf(NULL, cb, offset) to find zeros;
+ // will be optimized for appropriate value size and param combinations
+ int IndexOf(LPVOID pData, UINT cbData, UINT offset);
+
+ // set/add element; Potentially growing the array; return FALSE/-1 if
+ // not possible (due to OOM)
+ BOOL SetAtGrow(int nIndex, LPVOID pValue);
+
+ // Operations that move elements around
+ BOOL InsertAt(int nIndex, LPVOID pValue, int nCount = 1);
+ void RemoveAt(int nIndex, int nCount = 1);
+
+ void AssertValid() const;
+
+// Implementation
+private:
+ BYTE FAR* m_pData; // the actual array of data
+ UINT m_cbValue; // size of each value (in bytes)
+ int m_nSize; // current # of elements (m_cbValue bytes in length)
+ int m_nMaxSize; // max # of elements (m_cbValue bytes in length)
+ int m_nGrowBy; // grow amount (in # elements)
+};
+
+
+#endif // !__ARRAY_FV_H__
diff --git a/private/ole32/dcomss/olescm/scmhash.cxx b/private/ole32/dcomss/olescm/scmhash.cxx
new file mode 100644
index 000000000..efd1e009f
--- /dev/null
+++ b/private/ole32/dcomss/olescm/scmhash.cxx
@@ -0,0 +1,337 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: scmhash.cxx
+//
+// Contents: Class definitions used for SCM hash table.
+//
+// History: 20-Jan-93 Ricksa Created from map_kv.cpp
+//
+// Notes: The reason for creating this file rather than using the
+// original class is that the SCM has different memory allocation
+// needs depending on whether it is built for Win95 or NT.
+//
+//--------------------------------------------------------------------------
+#include <headers.cxx>
+#include <scmhash.hxx>
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashEntry::~CScmHashEntry
+//
+// Synopsis: Clean up hash entry
+//
+// History: 16-Feb-96 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CScmHashEntry::~CScmHashEntry(void)
+{
+ // Just exists hopefully to save some space
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashTable::~CScmHashTable
+//
+// Synopsis: Free resources held by the hash table
+//
+// Algorithm: For each hash bucket, delete all member of the collison
+// list.
+//
+// History: 16-Feb-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CScmHashTable::~CScmHashTable(void)
+{
+ // Free all the objects in the table.
+
+ // Loop through each hash bucket
+ for (DWORD i = 0; i < _ndwHashTableSize; i++)
+ {
+ // For each entry in the hash bucket list delete it.
+ CScmHashEntry *pshe = _apsheHashTable[i];
+
+ while (pshe != NULL)
+ {
+ CScmHashEntry *psheNext = pshe->GetNext();
+
+ delete pshe;
+
+ pshe = psheNext;
+ }
+
+ }
+
+ // Free the table itself
+ ScmMemFree(_apsheHashTable);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashTable::Lookup
+//
+// Synopsis: Look up entry by hash and key
+//
+// Arguments: [dwHash] - hash value to use
+// [pKey] - key to use
+// [cbKey] - count of bytes in the key
+//
+// Returns: NULL - no matching entry was found
+// Pointer to first matching entry found
+//
+// Algorithm: If there is an entry for the hash bucket, search
+// through the collision entries for the first entry
+// that matches.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CScmHashEntry * CScmHashTable::Lookup(
+ DWORD dwHash,
+ LPVOID pKey,
+ UINT cbKey) const
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::Lookup "
+ "( %lx , %p , %lx )\n", this, dwHash, pKey, cbKey));
+
+ CScmHashEntry *psheFound = NULL;
+
+ // Are there any entries for this bucket?
+ if (_apsheHashTable[dwHash] != NULL)
+ {
+ CScmHashEntry *psheToSearch = _apsheHashTable[dwHash];
+
+ // Loop searching for a match
+ do
+ {
+ if (psheToSearch->IsEqual(pKey, cbKey))
+ {
+ psheFound = psheToSearch;
+ break;
+ }
+ } while ((psheToSearch = psheToSearch->GetNext()) != NULL);
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::Lookup ( %p )\n",
+ this, psheFound));
+ return psheFound;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashTable::SetAt
+//
+// Synopsis: Add a new entry
+//
+// Arguments: [dwHash] - hash value to use
+// [psheToAdd] - hash entry to add
+//
+// Algorithm: If there are no entries for the bucket, make the bucket
+// point to this entry. Otherwise, put this entry on the
+// end of the list of collisions.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+void CScmHashTable::SetAt(
+ DWORD dwHash,
+ CScmHashEntry *psheToAdd)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::SetAt "
+ "( %lx , %p )\n", this, dwHash, psheToAdd));
+
+ // Are there entries that has to this bucket?
+ if (_apsheHashTable[dwHash] != NULL)
+ {
+ // Yes -- then put this one on the end of the list
+
+ CScmHashEntry *psheToSearch = _apsheHashTable[dwHash];
+ CScmHashEntry *psheLast;
+
+ do
+ {
+
+ psheLast = psheToSearch;
+
+ } while ((psheToSearch = psheToSearch->GetNext()) != NULL);
+
+ psheLast->SetNext(psheToAdd);
+ }
+ else
+ {
+ // No entries on the list so put this one first
+ _apsheHashTable[dwHash] = psheToAdd;
+ }
+
+ _ndwCount++;
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::SetAt \n", this));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashTable::RemoveEntry
+//
+// Synopsis: Remove an entry from the list
+//
+// Arguments: [dwHash] - hash value to use
+// [psheToRemove] - hash entry to add
+//
+// Returns: TRUE - entry removed.
+// FALSE - no such entry found
+//
+// Algorithm: If bucket is not empty, if this is the first entry replace
+// it with its next. Otherwise, loop through the list searching
+// for the entry and make its previous point to the current
+// one's next.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CScmHashTable::RemoveEntry(
+ DWORD dwHash,
+ CScmHashEntry *psheToRemove)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::RemoveEntry "
+ "( %lx , %p )\n", this, dwHash, psheToRemove));
+
+ BOOL fFound = FALSE;
+
+ // Are there any entries for this bucket?
+ if (_apsheHashTable[dwHash] != NULL)
+ {
+ CScmHashEntry *psheToSearch = _apsheHashTable[dwHash];
+ CScmHashEntry *pshePrev = NULL;
+
+ while (psheToSearch != NULL)
+ {
+ if (psheToSearch == psheToRemove)
+ {
+ if (pshePrev == NULL)
+ {
+ // First entry matches so update the head of the list
+ _apsheHashTable[dwHash] = psheToSearch->GetNext();
+ }
+ else
+ {
+ // Found entry in the middle of the list so delete
+ // the previous item's next pointer
+ pshePrev->SetNext(psheToSearch->GetNext());
+ }
+
+ // Tell the caller we found the item
+ fFound = TRUE;
+ break;
+ }
+
+ pshePrev = psheToSearch;
+ psheToSearch = psheToSearch->GetNext();
+ }
+
+ if (fFound)
+ {
+ _ndwCount--;
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::RemoveEntry ( %lx )\n",
+ this, fFound));
+
+ return fFound;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashIter::FindNextBucketWithEntry
+//
+// Synopsis: Find next hash bucket that has an entry
+//
+// Returns: Entry for bucket or NULL if there are none/
+//
+// Algorithm: Beginning with the current bucket loop through the list
+// of buckets till one is not null or there are no more
+// buckets.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CScmHashEntry *CScmHashIter::FindNextBucketWithEntry(void)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmHashIter::FindNextBucketWithEntry\n",
+ this));
+
+ for (; _dwBucket < _psht->_ndwHashTableSize; _dwBucket++)
+ {
+ if ((_psheNext =_psht->_apsheHashTable[_dwBucket]) != NULL)
+ {
+ break;
+ }
+ }
+
+ // Point to the next bucket
+ _dwBucket++;
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmHashIter::FindNextBucketWithEntry "
+ "( %p )\n", this, _psheNext));
+
+ return _psheNext;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashIter::GetNext
+//
+// Synopsis: Find next hash bucket that has an entry
+//
+// Returns: Next entry in the iteration
+//
+// Algorithm: Get the next pointer from the object and then update
+// the next pointer if there are still entries to be
+// iterated.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CScmHashEntry *CScmHashIter::GetNext(void)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmHashIter::GetNext \n", this));
+
+ CScmHashEntry *psheToReturn = _psheNext;
+
+ // Search for the next entry to return
+ if (_psheNext != NULL)
+ {
+ _psheNext = _psheNext->GetNext();
+
+ if (_psheNext == NULL)
+ {
+ FindNextBucketWithEntry();
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmHashIter::GetNext "
+ "( %p )\n", this, psheToReturn));
+
+ return psheToReturn;
+}
diff --git a/private/ole32/dcomss/olescm/scmhash.hxx b/private/ole32/dcomss/olescm/scmhash.hxx
new file mode 100644
index 000000000..322c51d4c
--- /dev/null
+++ b/private/ole32/dcomss/olescm/scmhash.hxx
@@ -0,0 +1,301 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: scmhash.hxx
+//
+// Contents: Class definitions used for SCM hash table.
+//
+// History: 20-Jan-93 Ricksa Created from map_kv.h
+//
+// Notes: The reason for creating this file rather than using the
+// original class is that the SCM has different memory allocation
+// needs depending on whether it is built for Win95 or NT.
+//
+//--------------------------------------------------------------------------
+#ifndef __SCMHASH_HXX__
+#define __SCMHASH_HXX__
+
+#include <memapi.hxx>
+#include <scmmem.hxx>
+
+// Forward declaration
+class CScmHashIter;
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CScmHashEntry (she)
+//
+// Purpose: Base of hash table entries
+//
+// Interface: IsEqual - tells whether entry is equal to input key
+// GetNext - next next entry after this one
+// SetNext - set the next pointer for this etnry
+//
+// History: 20-Jan-95 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+class CScmHashEntry : public CScmAlloc
+{
+public:
+
+ CScmHashEntry(void);
+
+ virtual ~CScmHashEntry(void);
+
+ virtual BOOL IsEqual(LPVOID pKey, UINT cbKey) = 0;
+
+ CScmHashEntry * GetNext(void);
+
+ void SetNext(CScmHashEntry *);
+
+private:
+
+ // Points to next hash entry if there is one
+ // for the hash bucket.
+ CScmHashEntry * _sheNext;
+
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashEntry::CScmHashEntry
+//
+// Synopsis: Initalize base of hash entry
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CScmHashEntry::CScmHashEntry(void) : _sheNext(NULL)
+{
+ // Header does all the work
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashEntry::GetNext
+//
+// Synopsis: Get next entry in the collision list
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CScmHashEntry *CScmHashEntry::GetNext(void)
+{
+ return _sheNext;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashEntry::SetNext
+//
+// Synopsis: Set the next entry in the collision list.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CScmHashEntry::SetNext(CScmHashEntry *sheNew)
+{
+ _sheNext = sheNew;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CScmHashTable (sht)
+//
+// Purpose: Hash table class
+//
+// Interface: InitOK - whether initialization succeeded
+// GetCount - Get count of items in the list
+// IsBucketEmpty - get whether collision list is empty
+// GetBucketList - get collision list for entry
+// Lookup - lookup an entry in the hash table
+// SetAt - add entry to hash table
+// RemoveEntry - remove entry from the hash table
+//
+// History: 20-Jan-95 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+class CScmHashTable : public CScmAlloc
+{
+public:
+ CScmHashTable(DWORD nHashSize = 17);
+
+ ~CScmHashTable();
+
+ // Tell whether object got correctly initialized
+ BOOL InitOK(void) const;
+
+ // Get count of entries in the table.
+ DWORD GetCount(void) const;
+
+ // Reports whether a particular buck is empty
+ BOOL IsBucketEmpty(DWORD dwHash) const;
+
+ // Gets list associated with the bucket. This
+ // is used if there is some special search of the
+ // list required.
+ CScmHashEntry * GetBucketList(DWORD dwHash) const;
+
+ // Lookup - return pointer to entry if found
+ CScmHashEntry * Lookup(
+ DWORD dwHash,
+ LPVOID pKey,
+ UINT cbKey) const;
+
+ // Add new entry
+ void SetAt(
+ DWORD dwHash,
+ CScmHashEntry *psheToAdd);
+
+ // removing existing entry
+ BOOL RemoveEntry(
+ DWORD dwHash,
+ CScmHashEntry *psheToRemove);
+
+private:
+
+ friend CScmHashIter;
+
+ CScmHashEntry ** _apsheHashTable;
+
+ DWORD _ndwHashTableSize;
+
+ DWORD _ndwCount;
+};
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashTable::CScmHashTable
+//
+// Synopsis: Create an empty hash table
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CScmHashTable::CScmHashTable(DWORD nHashSize)
+ : _ndwHashTableSize(nHashSize), _ndwCount(0)
+{
+ DWORD dwSize = nHashSize * sizeof(CScmHashEntry *);
+
+ _apsheHashTable = (CScmHashEntry **) ScmMemAlloc(dwSize);
+
+ if (_apsheHashTable != NULL)
+ {
+ memset(_apsheHashTable, 0, dwSize);
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashTable::InitOK
+//
+// Synopsis: Determine whether the constructor succeeded
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CScmHashTable::InitOK(void) const
+{
+ return _apsheHashTable != NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashTable::GetCount
+//
+// Synopsis: Get the number of entries in the table
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline DWORD CScmHashTable::GetCount(void) const
+{
+ return _ndwCount;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashTable::IsBucketEmpty
+//
+// Synopsis: Determine whether a particular hash bucket is empty
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CScmHashTable::IsBucketEmpty(DWORD dwHash) const
+{
+ return _apsheHashTable[dwHash] == NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashTable::GetBucketList
+//
+// Synopsis: Get a list of entries associated with a particular hash
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CScmHashEntry *CScmHashTable::GetBucketList(DWORD dwHash) const
+{
+ return _apsheHashTable[dwHash];
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CScmHashIter (shi)
+//
+// Purpose: Iterate through list of hash entries sequentially
+//
+// Interface: GetNext - get next entry in the list
+//
+// History: 20-Jan-95 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+class CScmHashIter
+{
+public:
+ CScmHashIter(CScmHashTable *psht);
+
+ CScmHashEntry * GetNext(void);
+
+private:
+
+ CScmHashEntry * FindNextBucketWithEntry(void);
+
+ CScmHashTable * _psht;
+
+ DWORD _dwBucket;
+
+ CScmHashEntry * _psheNext;
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmHashIter::CScmHashIter
+//
+// Synopsis: Initialize iteration
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CScmHashIter::CScmHashIter(CScmHashTable *psht)
+ : _psht(psht), _dwBucket(0), _psheNext(NULL)
+{
+ FindNextBucketWithEntry();
+}
+
+
+#endif // __SCMHASH_HXX__
diff --git a/private/ole32/dcomss/olescm/scmif.cxx b/private/ole32/dcomss/olescm/scmif.cxx
new file mode 100644
index 000000000..6036d3642
--- /dev/null
+++ b/private/ole32/dcomss/olescm/scmif.cxx
@@ -0,0 +1,1077 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: scmif.cxx
+//
+// Contents: Entry points for scm interface.
+//
+// Functions: StartObjectService
+// SvcActivateObject
+// SvcCreateActivateObject
+// ObjectServerStarted
+// StopServer
+//
+// History: 01-May-93 Ricksa Created
+// 31-Dec-93 ErikGav Chicago port
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <scm.h>
+#include "rawdscm.h"
+#include "scm.hxx"
+#include "port.hxx"
+#include "cls.hxx"
+#include <caller.hxx>
+#include "dbgprt.hxx"
+
+#include "rotif.hxx"
+#include "clckpath.hxx"
+#include <valid.h>
+#include "or.hxx"
+
+#ifndef _CHICAGO_
+#include <shrtbl.hxx>
+extern CScmShrdTbl *g_pScmShrdTbl;
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Function: Dummy1
+//
+// Synopsis: Needed for IDL hack. Never called.
+//
+// Arguments: [hRpc] - RPC handle
+// [orpcthis] - ORPC handle
+// [localthis] - ORPC call data
+// [orpcthat] - ORPC reply data
+//
+// Returns: HRESULT
+//
+// History: 14 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT DummyQueryInterfaceIOSCM(
+ handle_t hRpc,
+ ORPCTHIS *orpcthis,
+ LOCALTHIS *localthis,
+ ORPCTHAT *orpcthat,
+ DWORD dummy )
+{
+ CairoleDebugOut((DEB_ERROR, "SCM Dummy function should never be called!\n" ));
+ orpcthat->flags = 0;
+ orpcthat->extensions = NULL;
+ return E_FAIL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: Dummy2
+//
+// Synopsis: Needed for IDL hack. Never called.
+//
+// Arguments: [hRpc] - RPC handle
+// [orpcthis] - ORPC handle
+// [localthis] - ORPC call data
+// [orpcthat] - ORPC reply data
+//
+// Returns: HRESULT
+//
+// History: 14 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT DummyAddRefIOSCM(
+ handle_t hRpc,
+ ORPCTHIS *orpcthis,
+ LOCALTHIS *localthis,
+ ORPCTHAT *orpcthat,
+ DWORD dummy )
+{
+ CairoleDebugOut((DEB_ERROR, "SCM Dummy function should never be called!\n" ));
+ orpcthat->flags = 0;
+ orpcthat->extensions = NULL;
+ return E_FAIL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: Dummy3
+//
+// Synopsis: Needed for IDL hack. Never called.
+//
+// Arguments: [hRpc] - RPC handle
+// [orpcthis] - ORPC handle
+// [localthis] - ORPC call data
+// [orpcthat] - ORPC reply data
+//
+// Returns: HRESULT
+//
+// History: 14 Apr 95 AlexMit Created
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT DummyReleaseIOSCM(
+ handle_t hRpc,
+ ORPCTHIS *orpcthis,
+ LOCALTHIS *localthis,
+ ORPCTHAT *orpcthat,
+ DWORD dummy )
+{
+ CairoleDebugOut((DEB_ERROR, "SCM Dummy function should never be called!\n" ));
+ orpcthat->flags = 0;
+ orpcthat->extensions = NULL;
+ return E_FAIL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ServerRegisterClsid
+//
+// Synopsis: Notifies SCM that server is started for a class
+//
+// Arguments: [hRpc] - RPC handle
+// [phProcess] - context handle
+// [lpDeskTop] - caller's desktop
+// [pregin] - array of registration entries
+// [ppregout] - array of registration cookies to return
+// [rpcstat] - status code
+//
+// Returns: HRESULT
+//
+// History: 01-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT ServerRegisterClsid(
+ handle_t hRpc,
+ PHPROCESS phProcess,
+ WCHAR * pwszWinstaDesktop,
+ RegInput *pregin,
+ RegOutput **ppregout,
+ error_status_t *rpcstat)
+{
+ CheckLocalCall( hRpc );
+
+ *rpcstat = 0;
+
+ HRESULT hr = S_OK;
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "_IN ObjectServerStarted\n"));
+
+#if defined(_NT1X_) && !defined(_CHICAGO_)
+
+ CairoleDebugOut((DEB_SCM, "_IN Desk Top: %s\n", pwszWinstaDesktop));
+
+#endif // _NT1X_ && !_CHICAGO_
+
+ DbgPrintRegIn("_IN Classes To Register", pregin);
+
+#endif // DBG == 1
+
+ VDATEHEAP();
+
+ // Initialize the output structure.
+ int cOutBytes = sizeof(RegOutput)
+ + (pregin->dwSize - 1) * sizeof(RegOutputEnt);
+
+ RegOutput *pregout = (RegOutput *) PrivMemAlloc(cOutBytes);
+
+ *ppregout = pregout;
+
+ if (pregout == NULL)
+ return E_OUTOFMEMORY;
+
+ memset(pregout, 0, cOutBytes);
+ pregout->dwSize = pregin->dwSize;
+
+ hr = GetClassCache().SetEndPoints(
+#ifndef _CHICAGO_
+ phProcess,
+ ((CProcess *)phProcess)->GetToken()->GetSid(),
+ pwszWinstaDesktop,
+#else
+ NULL,
+#endif
+ pregin,
+ pregout );
+
+ VDATEHEAP();
+
+#if DBG == 1
+ CairoleDebugOut((DEB_SCM, "OUT ObjectServerStarted\n"));
+ CairoleDebugOut((DEB_SCM, "OUT Hresult : %lx\n", hr));
+
+ if (SUCCEEDED(hr))
+ {
+ DbgPrintRegOut("OUT Register Information", ppregout);
+ }
+
+#endif // DBG == 1
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: StopServer
+//
+// Synopsis: Get notification that class server is stopping
+//
+// Arguments: [hRpc] - RPC handle
+// [prevcls] - list of classes/registrations to stop
+//
+// History: 01-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+extern "C" void ServerRevokeClsid(
+ handle_t hRpc,
+ PHPROCESS phProcess,
+ RevokeClasses *prevcls,
+ error_status_t *rpcstat)
+{
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "_IN StopServer\n"));
+ DbgPrintRevokeClasses("_IN RevokeClasses:", prevcls);
+
+#endif // DBG == 1
+
+ CheckLocalCall( hRpc );
+
+ VDATEHEAP();
+
+ *rpcstat = 0;
+
+ DWORD cLoops = prevcls->dwSize;
+ RevokeEntry *prevent = prevcls->revent;
+
+ for (DWORD i = 0; i < cLoops; i++, prevent++)
+ {
+ GetClassCache().StopServer(prevent->clsid,
+ IFSECURITY( ((CProcess *)phProcess)->GetToken()->GetSid() )
+ prevent->dwReg);
+
+ ((CProcess *)phProcess)->RemoveClassReg( prevent->clsid, prevent->dwReg );
+ }
+
+ VDATEHEAP();
+ CairoleDebugOut((DEB_SCM, "OUT StopServer\n"));
+}
+
+void GetThreadID(
+ handle_t hRpc,
+ DWORD * pThreadID,
+ error_status_t *prpcstat)
+{
+ CheckLocalCall( hRpc );
+
+ *prpcstat = 0;
+ *pThreadID = InterlockedExchangeAdd((long *)&gNextThreadID,1);
+}
+
+#ifndef _CHICAGO_
+//+-------------------------------------------------------------------------
+//
+// Function: UpdateShrdTbls
+//
+// Synopsis: Update the shared memory tables.
+//
+// Arguments: [hRpc] - RPC handle
+// [prpcstat] - communication status
+//
+// History: 11-Jul-94 Rickhi Created
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT UpdateShrdTbls(
+ handle_t hRpc,
+ error_status_t *prpcstat)
+{
+ CheckLocalCall( hRpc );
+
+ *prpcstat = 0;
+ CairoleDebugOut((DEB_SCM, "_IN UpdateShrdTbls\n"));
+ VDATEHEAP();
+
+ // we dont take the lock because the caller is holding it for us.
+ g_pScmShrdTbl->UpdateWithLock();
+
+ VDATEHEAP();
+ CairoleDebugOut((DEB_SCM, "OUT UpdateShrdTbls\n"));
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UpdateActivationSettings
+//
+// Synopsis: Re-read default activation settings.
+//
+// Arguments: [hRpc] - RPC handle
+// [prpcstat] - communication status
+//
+//--------------------------------------------------------------------------
+extern void ComputeSecurity();
+
+extern "C" void UpdateActivationSettings(
+ handle_t hRpc,
+ error_status_t *prpcstat)
+{
+ CheckLocalCall( hRpc );
+
+ *prpcstat = 0;
+ gpClassCache->ReadRemoteActivationKeys();
+ ComputeSecurity();
+}
+#endif // !_CHICAGO_
+
+
+#ifdef _CHICAGO_
+//+-------------------------------------------------------------------------
+//
+// Function: StartObjectService
+//
+// Synopsis: Get a class object for a client
+//
+// Arguments: [hRpc] - RPC handle
+// [orpcthis] - ORPC handle
+// [localthis] - ORPC call data
+// [orpcthat] - ORPC reply data
+// [rclsid] - class id for reequest
+// [dwCtrl] - type of server required
+// [ppIFDClassObj] - where to return the serialized class object
+// [ppwszDllToLoad] - where to return DLL path
+//
+// Returns: HRESULT
+//
+// History: 01-May-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT StartObjectService(
+ handle_t hRpc,
+ ORPCTHIS *orpcthis,
+ LOCALTHIS *localthis,
+ ORPCTHAT *orpcthat,
+ WCHAR *lpDesktop,
+ const GUID *guidCLSID,
+ DWORD dwCtrl,
+ WCHAR *pwszServer,
+ InterfaceData **ppIFDClassObj,
+ DWORD *pdwDllType,
+ WCHAR **ppwszDllToLoad )
+{
+
+ REFCLSID rclsid = *guidCLSID;
+
+#if DBG ==1
+
+ CairoleDebugOut((DEB_SCM, "_IN StartObjectServer\n"));
+ CairoleDebugOut((DEB_SCM, "_IN Desk Top: %s\n", lpDesktop));
+ DbgPrintGuid("_IN ThreadId: ", &orpcthis->cid);
+ DbgPrintGuid("_IN CLSID: ", guidCLSID);
+ CairoleDebugOut((DEB_SCM, "_IN Context: %lX\n", dwCtrl));
+ CairoleDebugOut((DEB_SCM, "_IN DLL Type: %lX\n", *pdwDllType));
+
+#endif // DBG == 1
+
+ orpcthat->flags = 0;
+ orpcthat->extensions = NULL;
+
+ VDATEHEAP();
+
+ CBaseData bd( GETCLASSOBJECT,
+ lpDesktop, &orpcthis->cid, rclsid, dwCtrl,
+ pdwDllType, ppwszDllToLoad, ppIFDClassObj,
+ NULL, FALSE, NULL, NULL, NULL, NULL,FALSE);
+
+ HRESULT hr = GetClassCache().ProcessScmMessage(&bd, NULL);
+
+ VDATEHEAP();
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "OUT StartObjectServer\n"));
+ CairoleDebugOut((DEB_SCM, "OUT Hresult : %lx\n", hr));
+
+ if (SUCCEEDED(hr))
+ {
+ if (*ppIFDClassObj)
+ {
+ DbgPrintIFD("OUT Class Obj:", *ppIFDClassObj);
+ }
+
+ if (*ppwszDllToLoad)
+ {
+ CairoleDebugOut((DEB_SCM, "OUT DLL Type: %lX\n", *pdwDllType));
+ CairoleDebugOut((DEB_SCM, "OUT DLL: %ws\n", *ppwszDllToLoad));
+ }
+ }
+
+#endif // DBG == 1
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SvcActivateObject
+//
+// Synopsis: Instantiate an object with interface
+//
+// Arguments: [hRpc] - RPC handle
+// [orpcthis] - ORPC handle
+// [localthis] - ORPC call data
+// [orpcthat] - ORPC reply data
+// [rclsid] - class id for object
+// [dwOptions] - type of server needed
+// [grfMode] - how to open file if specified
+// [pwszPath] - path to object
+// [pIFDstg] - marshaled storage
+// [pwszDllPath] - path to DLL
+//
+// Returns: HRESULT
+//
+// History: 01-May-93 Ricksa Created
+// 18-Aug-94 AlexT Add caller, callee thread id
+//
+//--------------------------------------------------------------------------
+
+// BUGBUG [mikese] The pwszServerAddress parameter is redundant, and should
+// be removed from the IDL
+
+// BUGBUG: hash value is an obsolete field as well.
+
+extern "C" HRESULT SvcActivateObject(
+ handle_t hRpc,
+ ORPCTHIS *orpcthis,
+ LOCALTHIS *localthis,
+ ORPCTHAT *orpcthat,
+ WCHAR *lpDesktop,
+ WCHAR *pwszProtseq,
+ const GUID *pclsid,
+ DWORD dwOptions,
+ DWORD grfMode,
+ DWORD dwHash,
+ WCHAR *pwszPath,
+ InterfaceData *pIFDstg,
+ InterfaceData **ppIFDunk,
+ DWORD *pdwDllType,
+ WCHAR **ppwszDllPath,
+ WCHAR *pwszServerAddress )
+{
+#if DBG ==1
+
+ CairoleDebugOut((DEB_SCM, "_IN SvcActivateObject\n"));
+ CairoleDebugOut((DEB_SCM, "_IN Desk Top: %s\n", lpDesktop));
+ CairoleDebugOut((DEB_SCM, "_IN Protocol Seq: %ws\n",
+ (pwszProtseq == NULL) ? L"None" : pwszProtseq));
+ DbgPrintGuid("_IN ThreadId: ", &orpcthis->cid);
+ DbgPrintGuid("_IN CLSID: ", pclsid);
+ CairoleDebugOut((DEB_SCM, "_IN Context: %lX\n", dwOptions));
+ CairoleDebugOut((DEB_SCM, "_IN Mode: %lX\n", grfMode));
+ CairoleDebugOut((DEB_SCM, "_IN Path: %ws\n",
+ (pwszPath == NULL) ? L"None" : pwszPath));
+ CairoleDebugOut((DEB_SCM, "_IN Stg: %lX\n", pIFDstg));
+ CairoleDebugOut((DEB_SCM, "_IN DLL Type: %lX\n", *pdwDllType));
+
+#endif // DBG == 1
+
+ orpcthat->flags = 0;
+ orpcthat->extensions = NULL;
+
+ VDATEHEAP();
+
+ HRESULT hr = S_OK;
+
+ InterfaceData *pifdFromROT = NULL;
+
+ BEGIN_BLOCK
+
+ // Lock the path so that only one path may be bound at a time
+ CLockPath lckpath(pwszPath, hr);
+
+ if (FAILED(hr))
+ {
+ // Couldn't lock the path -- memory problem maybe. Anyway, we
+ // can't go anywhere from here.
+ CairoleDebugOut((DEB_ERROR,
+ "SvcActivateObject Lock of Path Failed %lx\n", hr));
+
+ EXIT_BLOCK;
+ }
+
+ // If there is a path Look for path in the Directory ROT
+ if (pwszPath != NULL)
+ {
+ // Remember that pdwDllType is overloaded here. We use it to
+ // indicate that we got an object from the ROT. We need to do
+ // this because there is no guarantee that the ROT entry will
+ // not be bad by the time we get back to the caller and therefore,
+ // the caller will want to retry in this case.
+ if (GetObjectFromRot(pwszPath, &pifdFromROT) == S_OK)
+ {
+ // Is this a local operatoin?
+ if (pwszProtseq == NULL)
+ {
+ // Return the marshaled interface from the ROT to the
+ // caller.
+ *ppIFDunk = pifdFromROT;
+
+ // So we remember not to clean up the buffer
+ pifdFromROT = NULL;
+
+ // Let caller know that we got this from the ROT so
+ // if it doesn't work they should try again.
+ *pdwDllType = GOT_FROM_ROT;
+
+ // We got what we came for from the ROT so we can exit
+ CairoleDebugOut((DEB_TRACE, "Found object in the ROT\n"));
+ EXIT_BLOCK;
+ }
+
+ // Because a tabled marshaled interface is not enought
+ // to get unmarshaled locally, we need to send it back
+ // to the object server to get something we can pass back
+ // to another machine.
+ }
+ }
+
+ // BUGBUG - Until we can decide how to pass back the callee's thread
+ // id, just hold it here.
+ DWORD dwTIDCallee;
+ IID IIDs[1];
+ HRESULT Results[1];
+
+ IIDs[0] = IID_IUnknown;
+
+ CGetCreateData gcd(pwszProtseq, dwOptions, grfMode, pwszPath,
+ pIFDstg, NULL, ppIFDunk, localthis->dwClientThread,
+ &dwTIDCallee, pifdFromROT,
+ 1, IIDs, Results);
+
+ CBaseData bd(GETPERSISTENTOBJ,
+ lpDesktop, &orpcthis->cid, *pclsid, dwOptions, pdwDllType,
+ ppwszDllPath, ppIFDunk,
+ NULL, FALSE, NULL, NULL, NULL, NULL,FALSE);
+
+ hr = GetClassCache().ProcessScmMessage(&bd, &gcd);
+
+ END_BLOCK;
+
+ VDATEHEAP();
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "OUT SvcActivateObject\n"));
+ CairoleDebugOut((DEB_SCM, "OUT Hresult : %lx\n", hr));
+
+ if (SUCCEEDED(hr))
+ {
+ if (*ppIFDunk)
+ {
+ DbgPrintIFD("OUT Object:", *ppIFDunk);
+ }
+
+ if (*ppwszDllPath)
+ {
+ CairoleDebugOut((DEB_SCM, "OUT DLL Type: %lX\n", *pdwDllType));
+ CairoleDebugOut((DEB_SCM, "OUT DLL: %ws\n", *ppwszDllPath));
+ }
+ }
+
+#endif // DBG == 1
+
+ if (pifdFromROT != NULL)
+ {
+ MIDL_user_free(pifdFromROT);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SvcCreateActivateObject
+//
+// Synopsis: Create and activate a new object
+//
+// Arguments: [hRpc] - RPC handle
+// [orpcthis] - ORPC handle
+// [localthis] - ORPC call data
+// [orpcthat] - ORPC reply data
+// [rclsid] - class id for object to create
+// [dwOptions] - type of server required
+// [dwMode] - how to open storage
+// [pwszPath] - path to the storage
+// [pIFDstg] - marshaled storage
+// [pwszNewName] - new name of object
+// [ppIFDunk] - marshaled IUnknown to return
+// [ppwszDllPath] - path to DLL for handler or server
+//
+// Returns: HRESULT
+//
+// History: 01-May-93 Ricksa Created
+// 18-Aug-94 AlexT Add caller, callee thread id
+//
+//--------------------------------------------------------------------------
+
+// BUGBUG [mikese] The pwszServerAddress parameter is redundant, and should
+// be removed from the IDL
+
+extern "C" HRESULT SvcCreateActivateObject(
+ handle_t hRpc,
+ ORPCTHIS *orpcthis,
+ LOCALTHIS *localthis,
+ ORPCTHAT *orpcthat,
+ WCHAR * lpDesktop,
+ WCHAR *pwszProtseq,
+ const GUID *guidCLSID,
+ DWORD dwOptions,
+ DWORD dwMode,
+ WCHAR *pwszPath,
+ InterfaceData *pIFDstg,
+ WCHAR *pwszNewName,
+ InterfaceData **ppIFDunk,
+ DWORD *pdwDllType,
+ WCHAR **ppwszDllPath,
+ WCHAR *pwszServerAddress )
+{
+ REFCLSID rclsid = *guidCLSID;
+
+#if DBG ==1
+
+ CairoleDebugOut((DEB_SCM, "_IN SvcCreateActivateObject\n"));
+ CairoleDebugOut((DEB_SCM, "_IN Desk Top: %s\n", lpDesktop));
+ CairoleDebugOut((DEB_SCM, "_IN Protocol Seq: %ws\n",
+ (pwszProtseq == NULL) ? L"None" : pwszProtseq));
+ DbgPrintGuid("_IN ThreadId: ", &orpcthis->cid);
+ DbgPrintGuid("_IN CLSID: ", guidCLSID);
+ CairoleDebugOut((DEB_SCM, "_IN Context: %lX\n", dwOptions));
+ CairoleDebugOut((DEB_SCM, "_IN Mode: %lX\n", dwMode));
+ CairoleDebugOut((DEB_SCM, "_IN Path: %ws\n",
+ (pwszPath == NULL) ? L"None" : pwszPath));
+ CairoleDebugOut((DEB_SCM, "_IN Stg: %lX\n", pIFDstg));
+ CairoleDebugOut((DEB_SCM, "_IN New Path: %ws\n",
+ (pwszNewName == NULL) ? L"None" : pwszNewName));
+ CairoleDebugOut((DEB_SCM, "_IN DLL Type: %lX\n", *pdwDllType));
+
+#endif // DBG == 1
+
+ orpcthat->flags = 0;
+ orpcthat->extensions = NULL;
+
+ VDATEHEAP();
+
+ // Error return from function
+ HRESULT hr=S_OK;
+
+ // Lock the path so that only one path may be bound at a time. Note
+ // that for create we don't look in the ROT since we don't want to
+ // get an already running entry but create a new one.
+ CLockPath lckpath(pwszPath, hr);
+
+ if (FAILED(hr))
+ {
+ // Couldn't lock the path -- memory problem maybe. Anyway, we
+ // can't go anywhere from here.
+ CairoleDebugOut((DEB_ERROR, "GetClass Failed %lx\n", hr));
+
+ return hr;
+ }
+
+ // BUGBUG - Until we can decide how to pass back the callee's thread
+ // id, just hold it here.
+ DWORD dwTIDCallee;
+ IID IIDs[1];
+ HRESULT Results[1];
+
+ IIDs[0] = IID_IUnknown;
+
+ CGetCreateData gcd(pwszProtseq, dwOptions, dwMode, pwszPath, pIFDstg, pwszNewName,
+ ppIFDunk, localthis->dwClientThread, &dwTIDCallee, NULL,
+ 1, IIDs, Results );
+
+ CBaseData bd(CREATEPERSISTENTOBJ, lpDesktop, &orpcthis->cid, rclsid,
+ dwOptions, pdwDllType, ppwszDllPath, ppIFDunk,
+ NULL, FALSE, NULL, NULL, NULL, NULL,FALSE);
+
+ hr = GetClassCache().ProcessScmMessage(&bd, &gcd);
+
+ CairoleDebugOut((DEB_TRACE,
+ "Result %lx\nDll Path %ws\n", hr, *ppwszDllPath));
+
+ VDATEHEAP();
+
+#if DBG == 1
+
+ CairoleDebugOut((DEB_SCM, "OUT SvcActivateObject\n"));
+ CairoleDebugOut((DEB_SCM, "OUT Hresult : %lx\n", hr));
+
+ if (SUCCEEDED(hr))
+ {
+ if (*ppIFDunk)
+ {
+ DbgPrintIFD("OUT Object:", *ppIFDunk);
+ }
+
+ if (*ppwszDllPath)
+ {
+ CairoleDebugOut((DEB_SCM, "OUT DLL Type: %lX\n", *pdwDllType));
+ CairoleDebugOut((DEB_SCM, "OUT DLL: %ws\n", *ppwszDllPath));
+ }
+ }
+
+#endif // DBG == 1
+
+ return hr;
+}
+#endif // _CHICAGO_
+
+#ifdef DCOM
+//+-------------------------------------------------------------------------
+//
+// Structure: WIPEntry (Window Interface Property)
+//
+// Synopsis: Stores marshaled interface info associated with a given window.
+// It is an entry in the CWIPTable (see below).
+//
+// History: 22-Jan-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+typedef struct tagWIPEntry
+{
+ DWORD hWnd; // window the interface property is stored in
+ DWORD dwFlags; // flags (see WIPFLAGS)
+ STDOBJREF std; // marshaled interface data
+ OXID_INFO oxidInfo; // data needed to resolve the OXID
+} WIPEntry;
+
+typedef enum tagWIPFLAGS
+{
+ WIPF_VACANT = 0x1, // slot is vacant
+ WIPF_OCCUPIED = 0x2 // slot is occupied
+} WIPFLAGS;
+
+#define WIPTBL_GROW_SIZE 10 // grow table by 10 entries at a time
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CWIPTable (Window Interface Property Table)
+//
+// Synopsis: Stores marshaled interface info associated with a given window.
+// This is used for registering drag/drop interfaces.
+//
+// History: 22-Jan-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+class CWIPTable
+{
+public:
+ HRESULT AddEntry(DWORD hWnd, STDOBJREF *pStd, OXID_INFO *pOxidInfo, DWORD *pdwCookie);
+ HRESULT GetEntry(DWORD hWnd, DWORD dwCookie, BOOL fRevoke,
+ STDOBJREF *pStd, OXID_INFO *pOxidInfo);
+
+private:
+ DWORD Grow();
+
+ static DWORD s_cEntries; // count of entries in the table
+ static DWORD s_iNextFree; // index to first free entry in table
+ static WIPEntry *s_pTbl; // ptr to the first entry in table
+ static CMutexSem s_mxs; // critical section to protect data
+};
+
+// static data for the table (avoids running a ctor for the class)
+DWORD CWIPTable::s_cEntries = 0;
+DWORD CWIPTable::s_iNextFree = 0xffffffff;
+WIPEntry *CWIPTable::s_pTbl = NULL;
+CMutexSem CWIPTable::s_mxs;
+
+CWIPTable gWIPTbl; // global instance of the class
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CopyDualStringArray
+//
+// Synopsis: makes a copy of the given string array
+//
+// History: 22-Jan-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT CopyDualStringArray(DUALSTRINGARRAY *psa, DUALSTRINGARRAY **ppsaNew)
+{
+ ULONG ulSize = sizeof(DUALSTRINGARRAY) + (psa->wNumEntries * sizeof(WCHAR));
+
+ *ppsaNew = (DUALSTRINGARRAY *) PrivMemAlloc(ulSize);
+
+ if (*ppsaNew == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ memcpy(*ppsaNew, psa, ulSize);
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CWIPTable::AddEntry, public
+//
+// Synopsis: Adds a WIPEntry to the table.
+//
+// Arguments: [hWnd] - window handle
+// [pStd] - standard marshaled interface STDOBJREF
+// [pOxidInfo] - info needed to resolve the OXID
+// [pdwCookie] - cookie to return (to be placed on the window)
+//
+// History: 22-Jan-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT CWIPTable::AddEntry(DWORD hWnd, STDOBJREF *pStd, OXID_INFO *pOxidInfo,
+ DWORD *pdwCookie)
+{
+ // make a copy of the string array in the OxidInfo since MIDL will
+ // delete it on the way back out of the call.
+
+ DUALSTRINGARRAY *psaNew;
+ HRESULT hr = CopyDualStringArray(pOxidInfo->psa, &psaNew);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ CLock lck(s_mxs);
+
+ // find a free slot in the table
+ DWORD dwIndex = s_iNextFree;
+
+ if (dwIndex == 0xffffffff)
+ {
+ // grow the table
+ dwIndex = Grow();
+ }
+
+ if (dwIndex != 0xffffffff)
+ {
+ // get the pointer to the entry,
+ WIPEntry *pEntry = s_pTbl + dwIndex;
+
+ // update the next free index.
+ s_iNextFree = pEntry->hWnd;
+
+ // copy in the data
+ memcpy(&pEntry->std, pStd, sizeof(STDOBJREF));
+ memcpy(&pEntry->oxidInfo, pOxidInfo, sizeof(OXID_INFO));
+
+ pEntry->oxidInfo.psa = psaNew;
+ pEntry->hWnd = hWnd;
+ pEntry->dwFlags = WIPF_OCCUPIED;
+
+ // return success
+ hr = S_OK;
+ }
+ else
+ {
+ // free the allocated string array
+ PrivMemFree(psaNew);
+ }
+
+ // set the cookie to return
+ *pdwCookie = dwIndex+5000;
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CWIPTable::GetEntry, public
+//
+// Synopsis: Retrieves and optionally delets a WIPEntry from the table.
+//
+// Arguments: [hWnd] - window handle
+// [dwCookie] - cookie from the window
+// [pStd] - place to return STDOBJREF data
+// [pOxidInfo] - place to return info needed to resolve the OXID
+//
+// History: 22-Jan-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+HRESULT CWIPTable::GetEntry(DWORD hWnd, DWORD dwCookie, BOOL fRevoke,
+ STDOBJREF *pStd, OXID_INFO *pOxidInfo)
+{
+ HRESULT hr = E_INVALIDARG;
+
+ // validate the cookie
+ DWORD dwIndex = dwCookie - 5000;
+ if (dwIndex < 0 || dwIndex >= s_cEntries)
+ {
+ return hr;
+ }
+
+ CLock lck(s_mxs);
+
+ // get the pointer to the entry,
+ WIPEntry *pEntry = s_pTbl + dwIndex;
+
+ // make sure the entry is occupied
+ if (pEntry->dwFlags & WIPF_OCCUPIED)
+ {
+ DUALSTRINGARRAY *psaNew;
+ hr = CopyDualStringArray(pEntry->oxidInfo.psa, &psaNew);
+
+ if (SUCCEEDED(hr))
+ {
+ // copy out the data to return
+ memcpy(pStd, &pEntry->std, sizeof(STDOBJREF));
+ memcpy(pOxidInfo, &pEntry->oxidInfo, sizeof(OXID_INFO));
+ pOxidInfo->psa = psaNew;
+
+ if (fRevoke)
+ {
+ // free the entry by updating the flags and the next free index
+ PrivMemFree(pEntry->oxidInfo.psa);
+
+ pEntry->dwFlags = WIPF_VACANT;
+ pEntry->hWnd = s_iNextFree;
+ s_iNextFree = dwIndex;
+ }
+ }
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CWIPTable::Grow, private
+//
+// Synopsis: grows the WIPTable size.
+//
+// History: 22-Jan-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+DWORD CWIPTable::Grow()
+{
+ // compute the size and allocate a new table
+ DWORD dwSize = (s_cEntries + WIPTBL_GROW_SIZE) * sizeof(WIPEntry);
+ WIPEntry *pNewTbl = (WIPEntry *) PrivMemAlloc(dwSize);
+
+ if (pNewTbl != NULL)
+ {
+ // copy the old table in
+ memcpy(pNewTbl, s_pTbl, (s_cEntries * sizeof(WIPEntry)));
+
+ // free the old table
+ if (s_pTbl)
+ {
+ PrivMemFree(s_pTbl);
+ }
+
+ // replace the old table ptr
+ s_pTbl = pNewTbl;
+
+ // update the free list and mark the new entries as vacant
+ s_iNextFree = s_cEntries;
+
+ WIPEntry *pNext = s_pTbl + s_cEntries;
+
+ for (ULONG i=0; i< WIPTBL_GROW_SIZE; i++)
+ {
+ pNext->hWnd = ++s_cEntries;
+ pNext->dwFlags = WIPF_VACANT;
+ pNext++;
+ }
+
+ (pNext-1)->hWnd = 0xffffffff; // last entry has END_OF_LIST marker
+ }
+
+ return s_iNextFree;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: RegisterWindowPropInterface
+//
+// Synopsis: Associate a window property with a (standard) marshaled
+// interface.
+//
+// Arguments: [hRpc] - RPC handle
+// [hWnd] - window handle
+// [pStd] - standard marshaled interface STDOBJREF
+// [pOxidInfo] - info needed to resolve the OXID
+// [pdwCookie] - cookie to return (to be placed on the window)
+// [prpcstat] - communication status
+//
+// History: 22-Jan-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT RegisterWindowPropInterface(
+ handle_t hRpc,
+ DWORD hWnd,
+ STDOBJREF *pStd,
+ OXID_INFO *pOxidInfo,
+ DWORD *pdwCookie,
+ error_status_t *prpcstat)
+{
+ CheckLocalCall( hRpc );
+
+ *prpcstat = 0;
+ CairoleDebugOut((DEB_SCM,
+ "_IN RegisterWindowPropInterface hWnd:%x pStd:%x pOxidInfo:%x\n",
+ hWnd, pStd, pOxidInfo));
+ VDATEHEAP();
+
+ HRESULT hr = gWIPTbl.AddEntry(hWnd, pStd, pOxidInfo, pdwCookie);
+
+ CairoleDebugOut((DEB_SCM, "_OUT RegisterWindowPropInterface dwCookie:%x\n",
+ *pdwCookie));
+ VDATEHEAP();
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetWindowPropInterface
+//
+// Synopsis: Get the marshaled interface associated with a window property.
+//
+// Arguments: [hRpc] - RPC handle
+// [hWnd] - window handle
+// [dwCookie] - cookie from the window
+// [fRevoke] - whether to revoke entry or not
+// [pStd] - standard marshaled interface STDOBJREF to return
+// [pOxidInfo] - info needed to resolve the OXID
+// [prpcstat] - communication status
+//
+// History: 22-Jan-96 Rickhi Created
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT GetWindowPropInterface(
+ handle_t hRpc,
+ DWORD hWnd,
+ DWORD dwCookie,
+ BOOL fRevoke,
+ STDOBJREF *pStd,
+ OXID_INFO *pOxidInfo,
+ error_status_t *prpcstat)
+{
+ CheckLocalCall( hRpc );
+
+ *prpcstat = 0;
+ CairoleDebugOut((DEB_SCM,
+ "_IN GetWindowPropInterface hWnd:%x dwCookie:%x fRevoke:%x\n",
+ hWnd, dwCookie, fRevoke));
+ VDATEHEAP();
+
+ HRESULT hr = gWIPTbl.GetEntry(hWnd, dwCookie, fRevoke, pStd, pOxidInfo);
+
+ CairoleDebugOut((DEB_SCM,
+ "_OUT GetWindowPropInterface pStd:%x pOxidInfo:%x\n", pStd, pOxidInfo));
+ VDATEHEAP();
+ return hr;
+}
+
+#endif // DCOM
diff --git a/private/ole32/dcomss/olescm/scmlock.hxx b/private/ole32/dcomss/olescm/scmlock.hxx
new file mode 100644
index 000000000..7a5cef942
--- /dev/null
+++ b/private/ole32/dcomss/olescm/scmlock.hxx
@@ -0,0 +1,130 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: scmlock.hxx
+//
+// Contents: a simple mutex
+//
+// Classes: CScmLock
+// CScmLockForRead
+// CScmLockForWrite
+//
+// History: 28-Dec-93 Ricksa Created
+// 11-Nov-94 BillMo A simple mutex for !defined(_PRELOAD_CACHE_)
+// 11-Dec-94 BillMo Get rid of old implementation.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __SCMLOCK_HXX__
+#define __SCMLOCK_HXX__
+
+#include <olecom.h>
+#include <sem32.hxx>
+#include <olesem.hxx>
+#include <smmutex.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Class: CScmLock
+//
+// Purpose: Provide a simple mutex for class cache list.
+//
+// Interface: WriteLock - get a write lock
+// WriteUnlock - release the write lock
+//
+// History: 11-Nov-94 BillMo Created
+//
+// Notes: This class is currently implemented base on the assumption
+// that there will only be one write thread period. This makes
+// no promises about having multiple threads that want to
+// do update.
+//
+// This class must be allocated statically, otherwise the
+// CStaticPortableMutex needs to be changed to Dynamic.
+//
+//--------------------------------------------------------------------------
+
+class CScmLock
+{
+public:
+#ifdef _CHICAGO_
+ inline CScmLock(HRESULT &hr)
+ {
+ SCODE sc = _mutex.Init(TEXT("OLESCMLOCKMUTEX"), FALSE);
+ if (FAILED(sc))
+ hr = sc;
+ }
+#else
+ inline CScmLock(HRESULT &hr) { }
+#endif
+
+ inline void WriteLock() { _mutex.Request(); }
+
+ inline void WriteUnlock() { _mutex.Release(); }
+
+private:
+ CStaticPortableMutex _mutex;
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CScmLockForWrite
+//
+// Purpose: Provide a guaranteed write lock/unlock.
+//
+// History: 28-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CScmLockForWrite
+{
+public:
+ CScmLockForWrite(CScmLock& scmlck);
+
+ ~CScmLockForWrite(void);
+
+private:
+
+ CScmLock& _scmlck;
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmLockForWrite::CScmLockForWrite
+//
+// Synopsis: Get the write lock
+//
+// Arguments: [smlck] - the lock object to lock.
+//
+// History: 28-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CScmLockForWrite::CScmLockForWrite(CScmLock& scmlck) : _scmlck(scmlck)
+{
+ _scmlck.WriteLock();
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmLockForWrite::~CScmLockForWrite
+//
+// Synopsis: Release the write lock
+//
+// History: 28-Dec-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CScmLockForWrite::~CScmLockForWrite(void)
+{
+ _scmlck.WriteUnlock();
+}
+
+#endif // __SCMLOCK_HXX__
diff --git a/private/ole32/dcomss/olescm/scmpre.inc b/private/ole32/dcomss/olescm/scmpre.inc
new file mode 100644
index 000000000..5e43081c0
--- /dev/null
+++ b/private/ole32/dcomss/olescm/scmpre.inc
@@ -0,0 +1,15 @@
+#//+---------------------------------------------------------------
+#//
+#// File: scmpre.inc
+#//
+#// Contents: directives for scm precompiled include file
+#//
+#// History: 18-Nov-94 BillMo Created
+#//
+#//----------------------------------------------------------------
+
+PRECOMPILED_CXX=1
+PRECOMPILED_INCLUDE=..\headers.cxx
+PRECOMPILED_TARGET=..\$(GPCH_BUILD)\obj\*\scm.pch
+PRECOMPILED_OPTION=/Yuheaders.cxx /Fp..\$(GPCH_BUILD)\obj\*\scm.pch
+PRECOMPILED_OBJ=..\$(GPCH_BUILD)\obj\*\scm.obj
diff --git a/private/ole32/dcomss/olescm/scmrot.cxx b/private/ole32/dcomss/olescm/scmrot.cxx
new file mode 100644
index 000000000..81042cadc
--- /dev/null
+++ b/private/ole32/dcomss/olescm/scmrot.cxx
@@ -0,0 +1,1019 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: scmrot.hxx
+//
+// Contents: Implementation of classes for the ROT in the SCM
+//
+// Functions: RoundTo8 - round size to 8 byte boundary
+// CalcIfdSize - calculate size needed for marhaled interface
+// SizeMnkEqBufForRotEntry - calculate size for moniker eq buffer
+// AllocateAndCopy - create copy of a marshaled interface
+// GetEntryFromScmReg - convert SCMREGKEY to ROT entry ptr
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <headers.cxx>
+#include <rothelp.hxx>
+#include <scmrot.hxx>
+
+#ifdef _CHICAGO_
+CStaticPortableMutex CScmRot::_mxs; // mutex semaphore
+#endif
+
+#ifndef _CHICAGO_
+extern HKEY g_hkAppID;
+
+BOOL
+CertifyServer(
+ WCHAR *pwszAppId,
+ WCHAR *pwszRunAsDomainName,
+ WCHAR *pwszRunAsUserName,
+ WCHAR *pwszLocalService,
+ PSID pExpectedSid,
+ PSID pServerSid );
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Function: RoundTo8
+//
+// Synopsis: Round size to next 8 byte boundary
+//
+// Arguments: [sizeToRound] - Size to round
+//
+// Returns: Input rounded to the next 8 byte boundary
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline size_t RoundTo8(size_t sizeToRound)
+{
+ return (sizeToRound + 7) & ~7;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CalcIfdSize
+//
+// Synopsis: Calculate size required by a marshaled interface
+//
+// Arguments: [pifd] - interface whose size to calculate
+//
+// Returns: size required for interface
+//
+// Algorithm: Get size from the interface and round to next 8 bytes so
+// data packed following this buffer will be nicely aligned.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+size_t CalcIfdSize(InterfaceData *pifd)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CalcIfdSize ( %p )\n", NULL,
+ pifd));
+
+ size_t sizeRet = RoundTo8(IFD_SIZE(pifd));
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CalcIfdSize ( %lx )\n", NULL,
+ sizeRet));
+
+ return sizeRet;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SizeMnkEqBufForRotEntry
+//
+// Synopsis: Calculate 8 byte aligned size for moniker equality buffer
+//
+// Arguments: [pmnkeqbuf] - Moniker equality buffer
+//
+// Returns: 8 byte aligned size of moniker buffer.
+//
+// Algorithm: Calculate size for the moniker equality buffer from input
+// buffer and then round to next 8 byte boundary
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+size_t SizeMnkEqBufForRotEntry(MNKEQBUF *pmnkeqbuf)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN SizeMnkEqBufForRotEntry ( %p )\n", NULL,
+ pmnkeqbuf));
+
+ size_t sizeRet = RoundTo8((sizeof(MNKEQBUF) - 1) + pmnkeqbuf->cdwSize);
+
+ CairoleDebugOut((DEB_ROT, "%p OUT SizeMnkEqBufForRotEntry ( %lx )\n", NULL,
+ sizeRet));
+
+ return sizeRet;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: AllocateAndCopy
+//
+// Synopsis: Make a copy of the input marshaled interface
+//
+// Arguments: [pifdIn] - input marshaled interface.
+//
+// Returns: Copy of input marshaled interface.
+//
+// Algorithm: Calculate size required for marshaled interface. Allocate
+// memory for the interface and then copy input interface into
+// the new buffer.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+InterfaceData *AllocateAndCopy(InterfaceData *pifdIn)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN AllocateAndCopy ( %p )\n", NULL, pifdIn));
+
+ DWORD dwSizeObj = CalcIfdSize(pifdIn);
+
+ InterfaceData *pifd = (InterfaceData *) MIDL_user_allocate(dwSizeObj);
+
+ if (pifd)
+ {
+ // Copy all the data. Remember that pifdIn was allocated rounded
+ // to an 8 byte boundary so we will not run off the end of the
+ // memory buffer
+ memcpy(pifd, pifdIn, dwSizeObj);
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT AllocateAndCopy ( %lx )\n", NULL, pifd));
+
+ return pifd;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetEntryFromScmReg
+//
+// Synopsis: Convert SCMREGKEY into a pointer to a ROT entry if possible
+//
+// Arguments: [psrk] - Pointer to a SCMREGKEY
+//
+// Returns: NULL - psrk not valid
+// ROT entry for the given input key
+//
+// Algorithm: Take the pointer portion of the key and make sure that
+// it points to enough memory so that we can validate the
+// signiture in the object. Then validate the signiture in
+// the object and return a pointer to the object.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CScmRotEntry *GetEntryFromScmReg(SCMREGKEY *psrk)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN GetEntryFromScmReg ( %p )\n",
+ NULL, psrk));
+
+ CScmRotEntry *psreRet = NULL;
+
+ CScmRotEntry *psre = (CScmRotEntry *) psrk->dwEntryLoc;
+
+ // Make sure pointer is pointer to valid memory - it s/b read write
+ // memory since we allocated it and updated it.
+ if (!IsBadReadPtr(psre, sizeof(*psre))
+ && !IsBadWritePtr(psre, sizeof(*psre)))
+ {
+ // Make sure signitures are valid
+ if (psre->IsValid(psrk->dwScmId))
+ {
+ psreRet = psre;
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT GetEntryFromScmReg ( %lx )\n",
+ NULL, psreRet));
+
+ return psreRet;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::CScmRotEntry
+//
+// Synopsis: Create a ROT entry for a registration
+//
+// Arguments: [dwScmRotId] - signiture for item
+// [pmkeqbuf] - moniker equality buffer to use
+// [pfiletime] - file time to use
+// [dwProcessID] - process id to use
+// [pifdObject] - marshaled interface for the object
+// [pifdObjectName] - marshaled moniker for the object
+//
+// Algorithm: Initialize data and calcualte offsets into the object for
+// the variable length data.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CScmRotEntry::CScmRotEntry(
+ DWORD dwScmRotId,
+ MNKEQBUF *pmkeqbuf,
+ FILETIME *pfiletime,
+ DWORD dwProcessID,
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ InterfaceData *pifdObject,
+ InterfaceData *pifdObjectName)
+ : _dwSig(SCMROT_SIG),
+ _dwScmRotId(dwScmRotId),
+ _dwProcessID(dwProcessID),
+ _filetimeLastChange(*pfiletime),
+ _pifdObject((InterfaceData *) &_ab[0])
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmRotEntry::CScmRotEntry "
+ "( %lx , %p , %p , %lx , %p , %p )\n", this, pmkeqbuf, pfiletime,
+ dwProcessID, pifdObject, pifdObjectName));
+
+#ifndef _CHICAGO_
+ _pToken = pToken;
+ if ( _pToken )
+ _pToken->Reference();
+#endif
+
+ // Copy data for object to preallocated area
+ _pifdObject->ulCntData = pifdObject->ulCntData;
+ memcpy(&_pifdObject->abData[0], &pifdObject->abData[0],
+ _pifdObject->ulCntData);
+
+ // Calculate the location of the equality buffer in the allocated data
+ DWORD dwOffsetMnkEqBuf = CalcIfdSize(_pifdObject);
+ _pmkeqbufKey = (MNKEQBUF *) &_ab[dwOffsetMnkEqBuf];
+
+ // Copy data for moniker equality buffer into preallocated area
+ _pmkeqbufKey->cdwSize = pmkeqbuf->cdwSize;
+ memcpy(&_pmkeqbufKey->abEqData[0], &pmkeqbuf->abEqData[0],
+ _pmkeqbufKey->cdwSize);
+
+ // Calculate the location of the moniker name buffer
+ _pifdObjectName = (InterfaceData *)
+ &_ab[dwOffsetMnkEqBuf + SizeMnkEqBufForRotEntry(_pmkeqbufKey)];
+
+ // Copy in the data for the moniker name
+ _pifdObjectName->ulCntData = pifdObjectName->ulCntData;
+ memcpy(&_pifdObjectName->abData[0], &pifdObjectName->abData[0],
+ _pifdObjectName->ulCntData);
+
+#ifndef _CHICAGO_
+ if ( pwszWinstaDesktop )
+ {
+ _pwszWinstaDesktop = (WCHAR *)
+ &_ab[dwOffsetMnkEqBuf + SizeMnkEqBufForRotEntry(_pmkeqbufKey) + CalcIfdSize(_pifdObjectName)];
+ lstrcpyW( _pwszWinstaDesktop, pwszWinstaDesktop );
+ }
+ else
+ {
+ _pwszWinstaDesktop = NULL;
+ }
+#endif
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmRotEntry::CScmRotEntry \n",
+ this));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::IsEqual
+//
+// Synopsis: Determine if input key is equal to the ROT entry's key
+//
+// Arguments: [pKey] - Key to use for the test
+// [cbKey] - Count of bytes in key
+//
+// Returns: TRUE - input key equals this object's key
+// FALSE - keys are not equal
+//
+// Algorithm: If the two sizes are equal then compare the actual data
+// buffers and return the result of that compare.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CScmRotEntry::IsEqual(LPVOID pKey, UINT cbKey)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmRotEntry::IsEqual "
+ "( %p , %lx )\n", this, pKey, cbKey));
+
+ BOOL fRet = FALSE;
+
+ if (cbKey == _pmkeqbufKey->cdwSize)
+ {
+ fRet = memcmp(pKey, &_pmkeqbufKey->abEqData[0], cbKey) == 0;
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmRotEntry::IsEqual ( %lx )\n",
+ this, fRet));
+
+ return fRet;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRot::Register
+//
+// Synopsis: Add entry to the ROT
+//
+// Arguments: [pmkeqbuf] - moniker equality buffer to use
+// [pfiletime] - file time to use
+// [dwProcessID] - process id to use
+// [pifdObject] - marshaled interface for the object
+// [pifdObjectName] - marshaled moniker for the object
+//
+// Returns: NOERROR - successfully registered
+// E_OUTOFMEMORY
+//
+// Algorithm: Lock the ROT from all other threads. The create a new
+// entry and determine if there is an eqivalent entry in
+// the ROT. Calculate the hash value and then put the
+// entry into our hash table. Finally, build a registration
+// key to return to the caller.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CScmRot::Register(
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ MNKEQBUF *pmnkeqbuf,
+ InterfaceData *pifdObject,
+ InterfaceData *pifdObjectName,
+ FILETIME *pfiletime,
+ DWORD dwProcessID,
+#ifndef _CHICAGO_
+ WCHAR *pwszServerExe,
+#endif
+ SCMREGKEY *psrkRegister)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::Register "
+ "( %p , %p , %p , %p , %lx , %p )\n", this, pmnkeqbuf, pifdObject,
+ pifdObjectName, pfiletime, dwProcessID, psrkRegister));
+
+ // Assume that there is a memory problem
+ HRESULT hr = E_OUTOFMEMORY;
+
+#ifndef _CHICAGO_
+ if ( pwszServerExe )
+ {
+ HKEY hKey;
+ LONG RegStatus;
+ WCHAR wszAppId[40];
+ DWORD Size;
+
+ RegStatus = RegOpenKeyEx( g_hkAppID,
+ pwszServerExe,
+ NULL,
+ KEY_READ,
+ &hKey );
+
+ if ( RegStatus == ERROR_SUCCESS )
+ {
+ Size = sizeof(wszAppId);
+ RegStatus = RegQueryValueEx( hKey,
+ L"AppId",
+ NULL,
+ NULL,
+ (BYTE *)wszAppId,
+ &Size );
+
+ RegCloseKey( hKey );
+ }
+
+ if ( RegStatus != ERROR_SUCCESS )
+ return CO_E_WRONG_SERVER_IDENTITY;
+
+ CAppIDData AppId;
+ BOOL Access;
+
+ AppId.ReadEntries( wszAppId );
+
+ Access = CertifyServer( wszAppId,
+ AppId.pwszRunAsDomainName,
+ AppId.pwszRunAsUserName,
+ AppId.pwszLocalService,
+ NULL,
+ pToken->GetSid() );
+
+ AppId.Cleanup();
+
+ if ( ! Access )
+ return CO_E_WRONG_SERVER_IDENTITY;
+
+ //
+ // NULL these to indicate that any client can connect to this
+ // registration.
+ //
+ pwszWinstaDesktop = NULL;
+ pToken = NULL;
+ }
+#endif
+
+ // Lock for the duration of the call
+ CPortableLock lck(_mxs);
+
+ // Bump the id
+ _dwIdCntr++;
+
+ // Build a record to put into the table
+ CScmRotEntry *psreNew = new(
+#ifndef _CHICAGO_
+ pwszWinstaDesktop ? (lstrlenW(pwszWinstaDesktop)+1)*sizeof(WCHAR) : 0,
+#endif
+ CalcIfdSize(pifdObject),
+ SizeMnkEqBufForRotEntry(pmnkeqbuf),
+ CalcIfdSize(pifdObjectName))
+ CScmRotEntry(_dwIdCntr, pmnkeqbuf, pfiletime, dwProcessID,
+#ifndef _CHICAGO_
+ pToken, pwszWinstaDesktop,
+#endif
+ pifdObject, pifdObjectName);
+
+ if (psreNew != NULL)
+ {
+ DWORD dwHash;
+ CScmRotEntry * psreRunning;
+
+#ifndef _CHICAGO_
+ psreRunning = GetRotEntry( pToken, pwszWinstaDesktop, pmnkeqbuf );
+#else
+ psreRunning = GetRotEntry( pmnkeqbuf );
+#endif
+
+ dwHash = ScmRotHash(&pmnkeqbuf->abEqData[0], pmnkeqbuf->cdwSize, 0);
+
+ // Put record into the hash table
+ _sht.SetAt(dwHash, psreNew);
+
+#ifndef _CHICAGO_
+
+ // Update the hint table
+ _rht.SetIndicator(dwHash);
+
+#endif // !_CHICAGO_
+
+ // Build return value
+ psreNew->SetScmRegKey(psrkRegister);
+
+ // Map return result based on prior existence of the object.
+ hr = (psreRunning == NULL)
+ ? NOERROR : MK_S_MONIKERALREADYREGISTERED;
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::Register "
+ " ( %lx )\n", this, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRot::Revoke
+//
+// Synopsis: Remove entry from the ROT
+//
+// Arguments: [psrkRegister] - registration to revoke
+// [fServer] - whether this is the object server
+// [ppifdObject] - output marshaled interface (optional)
+// [ppifdName] - output marshaled moniker (optional)
+//
+// Returns: NOERROR - successfully removed.
+// E_INVALIDARG
+//
+// Algorithm: Convert SCMREGKEY to anentry in the ROT. Remove the
+// entry from the hash table. If this is the object server
+// for the entry, then return the marshaled interfaces
+// so the object server can release them.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CScmRot::Revoke(
+ SCMREGKEY *psrkRegister,
+ BOOL fServer,
+ InterfaceData **ppifdObject,
+ InterfaceData **ppifdName)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::Revoke "
+ "( %p , %lx , %p , %p )\n", this, fServer, ppifdObject, ppifdName));
+
+ HRESULT hr = E_INVALIDARG;
+
+ // Lock for the duration of the call
+ CPortableLock lck(_mxs);
+
+ // Verify registration key
+ CScmRotEntry *psreToRemove = GetEntryFromScmReg(psrkRegister);
+
+ if (psreToRemove != NULL)
+ {
+ // Get the has value
+ DWORD dwHash = ScmRotHash(psreToRemove->Key(), psreToRemove->cKey(), 0);
+
+ // Remove object from the list
+ _sht.RemoveEntry(dwHash, psreToRemove);
+
+ // Is this a server doing a revoke?
+ if (fServer)
+ {
+ // Error handling here - suppose these allocations fail, what
+ // can we do? The bottom line is nothing. This will cause a
+ // memory leak in the server because they can't release the
+ // marshaled data. However, this is assumed to be a rare
+ // occurance and will really only cause the moniker to live
+ // longer than it ought to which should not be too serious.
+ *ppifdObject = AllocateAndCopy(psreToRemove->GetObject());
+ *ppifdName = AllocateAndCopy(psreToRemove->GetMoniker());
+ }
+
+ // Free the entry
+ delete psreToRemove;
+
+#ifndef _CHICAGO_
+
+ // See if bucket is empty
+ if (_sht.IsBucketEmpty(dwHash))
+ {
+ // Update the hint table.
+ _rht.ClearIndicator(dwHash);
+ }
+
+#endif // !_CHICAGO_
+
+ hr = S_OK;
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::Revoke "
+ " ( %lx ) [ %p, %p ] \n", this, hr,
+ (ppifdObject != NULL) ? *ppifdObject : NULL,
+ (ppifdName != NULL) ? *ppifdName : NULL));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRot::IsRunning
+//
+// Synopsis: Determine if there is a registered entry for an item
+//
+// Arguments: [pmnkeqbuf] - Moniker equality buffer to search for
+//
+// Returns: NOERROR - moniker is registered as running
+// S_FALSE - moniker is not running.
+//
+// Algorithm: Get the entry for the moniker equality buffer if there is
+// one. If there is one, then return NOERROR otherwise return
+// S_FALSE.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CScmRot::IsRunning(
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ MNKEQBUF *pmnkeqbuf)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::IsRunning "
+ "( %p )\n", this, pmnkeqbuf));
+
+ // Lock for the duration of the call
+ CPortableLock lck(_mxs);
+
+#ifndef _CHICAGO_
+ CScmRotEntry *psreRunning = GetRotEntry( pToken, pwszWinstaDesktop, pmnkeqbuf );
+#else
+ CScmRotEntry *psreRunning = GetRotEntry(pmnkeqbuf);
+#endif
+
+ HRESULT hr = (psreRunning != NULL) ? S_OK : S_FALSE;
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::IsRunning "
+ " ( %lx ) \n", this, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRot::GetObject
+//
+// Synopsis: Get running object for input
+//
+// Arguments: [dwProcessID] - process id of object (optional)
+// [pmnkeqbuf] - moniker equality buffer
+// [psrkRegister] - output registration id.
+// [ppifdObject] - marshaled interface for registration
+//
+// Returns: NOERROR - got object
+// MK_E_UNAVAILABLE - registration could not be found
+//
+// Algorithm: If not process ID is input, then search for the first
+// matching entry that we can find. Otherwise, search the
+// hash for the entry with both the same key and the same
+// process id.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CScmRot::GetObject(
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ DWORD dwProcessID,
+ MNKEQBUF *pmnkeqbuf,
+ SCMREGKEY *psrkRegister,
+ InterfaceData **ppifdObject)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::GetObject "
+ "( %lx , %p , %p , %p )\n", this, dwProcessID, pmnkeqbuf, psrkRegister,
+ ppifdObject));
+
+ HRESULT hr = MK_E_UNAVAILABLE;
+
+ // Lock for the duration of the call
+ CPortableLock lck(_mxs);
+
+ CScmRotEntry *psreRunning;
+
+ if (dwProcessID == 0)
+ {
+#ifndef _CHICAGO_
+ psreRunning = GetRotEntry( pToken, pwszWinstaDesktop, pmnkeqbuf );
+#else
+ psreRunning = GetRotEntry(pmnkeqbuf);
+#endif
+ }
+ else
+ {
+ // Special search based on process ID - get the head of the list
+ // for the bucket
+ psreRunning = (CScmRotEntry *) _sht.GetBucketList(
+ ScmRotHash(&pmnkeqbuf->abEqData[0], pmnkeqbuf->cdwSize, 0));
+
+ // Search list for a matching entry
+ while (psreRunning != NULL)
+ {
+ if ((psreRunning->GetProcessID() == dwProcessID)
+ && psreRunning->IsEqual(&pmnkeqbuf->abEqData[0],
+ pmnkeqbuf->cdwSize))
+ {
+ // We found a match so we are done.
+ break;
+ }
+
+ // Try the next item in the bucket.
+ psreRunning = (CScmRotEntry *) psreRunning->GetNext();
+ }
+ }
+
+ if (psreRunning != NULL)
+ {
+ hr = E_OUTOFMEMORY;
+
+ *ppifdObject = AllocateAndCopy(psreRunning->GetObject());
+
+ if (*ppifdObject != NULL)
+ {
+ hr = NOERROR;
+ }
+
+ // Build return registration key
+ psreRunning->SetScmRegKey(psrkRegister);
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::GetObject "
+ " ( %lx ) [ %p ] \n", this, hr, *ppifdObject));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRot::NoteChangeTime
+//
+// Synopsis: Set the time of last change for a ROT entry
+//
+// Arguments: [psrkRegister] - ID of entry to change
+// [pfiletime] - new time for the entry.
+//
+// Returns: NOERROR - time set
+// E_INVALIDARG - ROT entry could not be found
+//
+// Algorithm: Convert SCMREGKEY into a pointer to a ROT entry and then
+// update the time of that entry.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CScmRot::NoteChangeTime(
+ SCMREGKEY *psrkRegister,
+ FILETIME *pfiletime)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::NoteChangeTime "
+ "( %p , %p )\n", this, psrkRegister, pfiletime));
+
+ HRESULT hr = E_INVALIDARG;
+
+ // Lock for the duration of the call
+ CPortableLock lck(_mxs);
+
+ CScmRotEntry *psre = GetEntryFromScmReg(psrkRegister);
+
+ if (psre != NULL)
+ {
+ psre->SetTime(pfiletime);
+ hr = S_OK;
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::NoteChangeTime "
+ " ( %lx ) \n", this, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRot::GetTimeOfLastChange
+//
+// Synopsis: Get time of last change for a moniker in the ROT
+//
+// Arguments: [pmnkeqbuf] - Moniker equality buffer
+// [pfiletime] - Where to put the time
+//
+// Returns: NOERROR - got the time
+// MK_E_UNAVAILABLE - couldn't find an entry/
+//
+// Algorithm: Search the hash for an entry with the same moniker. If
+// found, then copy out the time.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CScmRot::GetTimeOfLastChange(
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ MNKEQBUF *pmnkeqbuf,
+ FILETIME *pfiletime)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::GetTimeOfLastChange "
+ "( %p , %p )\n", this, pmnkeqbuf, pfiletime));
+
+ HRESULT hr = MK_E_UNAVAILABLE;
+
+ // Lock for the duration of the call
+ CPortableLock lck(_mxs);
+
+#ifndef _CHICAGO_
+ CScmRotEntry *psreRunning = GetRotEntry( pToken, pwszWinstaDesktop, pmnkeqbuf );
+#else
+ CScmRotEntry *psreRunning = GetRotEntry(pmnkeqbuf);
+#endif
+
+ if (psreRunning != NULL)
+ {
+ psreRunning->GetTime(pfiletime);
+ hr = S_OK;
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::GetTimeOfLastChange "
+ " ( %lx ) \n", this, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRot::EnumRunning
+//
+// Synopsis: Get a list of all the monikers that are currently running
+//
+// Arguments: [ppMkIFList] - Where to put list of monikers running
+//
+// Returns: NOERROR - got list
+// E_OUTOFMEMORY - couldn't allocate space for the list
+//
+// Algorithm: Loop through the ROT copying out the marshaled moniker buffers
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CScmRot::EnumRunning(
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ MkInterfaceList **ppMkIFList)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::EnumRunning "
+ "( %p )\n", this, ppMkIFList));
+
+ HRESULT hr = E_OUTOFMEMORY;
+
+ // Lock for the duration of the call
+ CPortableLock lck(_mxs);
+
+ *ppMkIFList = NULL;
+
+ MkInterfaceList *pMkIFList = NULL;
+
+ // This is the upper limit on how much space we'll need.
+ DWORD dwSize = sizeof(MkInterfaceList) +
+ (_sht.GetCount() - 1) * sizeof(InterfaceData *);
+
+ // Allocate buffer
+ pMkIFList = (MkInterfaceList *) MIDL_user_allocate(dwSize);
+
+ // We use this to keep track fof the number of monikers we are returning
+ DWORD dwOffset = 0;
+
+ if (pMkIFList != NULL)
+ {
+ // Iterate list getting the pointers
+ CScmHashIter shi(&_sht);
+ CScmRotEntry *psre;
+
+ while ((psre = (CScmRotEntry *) shi.GetNext()) != NULL)
+ {
+ InterfaceData *pifdForOutput;
+
+#ifndef _CHICAGO_
+ if ( psre->WinstaDesktop() &&
+ (lstrcmpW( pwszWinstaDesktop, psre->WinstaDesktop() ) != 0) )
+ continue;
+
+ if ( psre->Token() &&
+ ! RtlEqualSid( pToken->GetSid(),
+ psre->Token()->GetSid() ) )
+ continue;
+#endif
+
+ pifdForOutput = AllocateAndCopy(psre->GetMoniker());
+
+ if (pifdForOutput == NULL)
+ {
+ goto Exit;
+ }
+
+ // Put copy in the array
+ pMkIFList->apIFDList[dwOffset] = pifdForOutput;
+
+ // We bump the count because it makes clean up easier
+ dwOffset++;
+ }
+
+ // Teller caller and cleanup that everything went ok.
+ hr = S_OK;
+
+ // Set the output buffer to the buffer we have allocated.
+ *ppMkIFList = pMkIFList;
+
+ // Set the size of the object to return
+ pMkIFList->dwSize = dwOffset;
+ }
+
+Exit:
+
+ if (FAILED(hr))
+ {
+ // We failed so clean up
+ if (pMkIFList != NULL)
+ {
+ // Clean up the moniker interfaces that were allocated
+ for (DWORD i = 0; i < dwOffset; i++)
+ {
+ MIDL_user_free(pMkIFList->apIFDList[i]);
+ }
+
+ // Clean up the table structure itself
+ MIDL_user_free(pMkIFList);
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::EnumRunning "
+ " ( %lx ) [ %p ]\n", this, hr, *ppMkIFList));
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRot::GetRotEntry
+//
+// Synopsis: Search ROT for entry that matches the equality buffer input.
+//
+// Arguments: [pmnkeqbuf] - Moniker equality buffer to search for.
+//
+// Returns: NULL - no entry could be found
+// Pointer to ROT entry with matching key
+//
+// Algorithm: Calculate the hash value for the input buffer. The search
+// the hash table for the matching value.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CScmRotEntry *CScmRot::GetRotEntry(
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ MNKEQBUF *pmnkeqbuf)
+{
+ CairoleDebugOut((DEB_ROT, "%p _IN CScmRot::GetRotEntry "
+ "( %p )\n", this, pmnkeqbuf));
+
+ DWORD dwHash;
+ CScmRotEntry * psre;
+
+ dwHash = ScmRotHash(&pmnkeqbuf->abEqData[0], pmnkeqbuf->cdwSize, 0);
+ psre = (CScmRotEntry *) _sht.GetBucketList( dwHash );
+
+ for ( ; psre != NULL; psre = (CScmRotEntry *) psre->GetNext() )
+ {
+ if ( psre->IsEqual(&pmnkeqbuf->abEqData[0], pmnkeqbuf->cdwSize) )
+ {
+#ifndef _CHICAGO_
+ //
+ // Note that this routine is actually called during a Register
+ // to see if there is a duplicate moniker and also during a
+ // client Lookup. This makes things a little complicated.
+ //
+ // The winsta\desktop param can only be null in two instances.
+ // + While doing a Register from a service or RunAs server. The
+ // pToken will also be null.
+ // + While doing a ROT lookup during a secure remote activation.
+ // The pToken will be non-null. We only check that the SIDs
+ // match in this case.
+ //
+ // During an usecure activation the pToken will be NULL. The
+ // winsta/desktop will actually be "" in this case (see
+ // Activation) to allow us to distinguish just this case.
+ //
+ // The ROT entry's winsta\desktop can be null if a service or RunAs
+ // server registered a globally available object.
+ //
+
+ // Existing registration is globally available.
+ if ( ! psre->WinstaDesktop() )
+ break;
+
+ //
+ // NULL token and winsta/desktop means a server is doing a register
+ // for a globally available object, return the match.
+ // NULL token but non-null ("") winsta/desktop is a lookup from a
+ // remote unsecure client, no match.
+ //
+ if ( ! pToken )
+ {
+ if ( ! pwszWinstaDesktop )
+ break;
+ else
+ continue;
+ }
+
+ Win4Assert( psre->Token() );
+
+ if ( pwszWinstaDesktop &&
+ (lstrcmpW( pwszWinstaDesktop, psre->WinstaDesktop() ) != 0) )
+ continue;
+
+ if ( ! RtlEqualSid( pToken->GetSid(),
+ psre->Token()->GetSid() ) )
+ continue;
+#endif
+
+ break;
+ }
+ }
+
+ CairoleDebugOut((DEB_ROT, "%p OUT CScmRot::GetRotEntry "
+ " ( %p )\n", this, psre));
+
+ return psre;
+}
diff --git a/private/ole32/dcomss/olescm/scmrot.hxx b/private/ole32/dcomss/olescm/scmrot.hxx
new file mode 100644
index 000000000..0e4216019
--- /dev/null
+++ b/private/ole32/dcomss/olescm/scmrot.hxx
@@ -0,0 +1,524 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: scmrot.hxx
+//
+// Contents: Classes used in implementing the ROT in the SCM
+//
+// Functions:
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __SCMROT_HXX__
+#define __SCMROT_HXX__
+
+#include <scm.hxx>
+#include <irot.h>
+#include <olesem.hxx>
+#include <srothint.hxx>
+#include <scmhash.hxx>
+#ifndef _CHICAGO_
+#include "or.hxx"
+#endif
+
+#define SCM_HASH_SIZE 251
+#define SCMROT_SIG 0x746f7263
+
+#include <rothint.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Class: CScmRotEntry (sre)
+//
+// Purpose: Entry in the SCM's ROT
+//
+// Interface: IsEqual - tells whether entry is equal to input key
+// GetPRocessID - accessor to process ID for entry
+// SetTime - set the time for the entry
+// GetTime - get the time for the entry
+// GetObject - get the marshaled object for the entry
+// GetMoniker - get marshaled moniker for the entry
+// IsValid - determines if signitures for entry are valid
+// Key - pointer to key for the entry
+// cKey - get count of bytes in the key
+//
+// History: 20-Jan-95 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+class CScmRotEntry : public CScmHashEntry
+{
+public:
+ CScmRotEntry(
+ DWORD dwScmRotId,
+ MNKEQBUF *pmnkeqbuf,
+ FILETIME *pfiletime,
+ DWORD _dwProcessID,
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ InterfaceData *pifdObject,
+ InterfaceData *pifdObjectName);
+
+ ~CScmRotEntry(void);
+
+ BOOL IsEqual(LPVOID pKey, UINT cbKey);
+
+ DWORD GetProcessID(void);
+
+ void SetTime(FILETIME *pfiletime);
+
+ void GetTime(FILETIME *pfiletime);
+
+ InterfaceData * GetObject(void);
+
+ InterfaceData * GetMoniker(void);
+
+#ifndef _CHICAGO_
+ CToken * Token();
+
+ WCHAR * WinstaDesktop();
+#endif
+
+ BOOL IsValid(DWORD dwScmId);
+
+ BYTE * Key(void);
+
+ DWORD cKey(void);
+
+ void SetScmRegKey(SCMREGKEY *psrkOut);
+
+#if DBG == 1
+ // For debug builds we override this operator to
+ // prevent its use by causing a run time error.
+ void *operator new(size_t size);
+
+#endif // DBG
+
+ // Real new for this object.
+ void *operator new(
+ size_t size,
+#ifndef _CHICAGO_
+ size_t sizeWinstaDesktop,
+#endif
+ size_t sizeObject,
+ size_t sizeMnkEqBuf,
+ size_t sizeObjectName );
+
+private:
+
+ // Signiture for object in memory
+ DWORD _dwSig;
+
+ // SCM id for uniqueness
+ DWORD _dwScmRotId;
+
+ // Process ID for registered object. Used for
+ // internal support of finding objects that
+ // a process has registered.
+ DWORD _dwProcessID;
+
+ // Time of last change
+ FILETIME _filetimeLastChange;
+
+ // Object identifier used by client to get
+ // actual object from the object server
+ InterfaceData * _pifdObject;
+
+ // Comparison buffer.
+ MNKEQBUF * _pmkeqbufKey;
+
+ // Object name (really only used for enumeration).
+ InterfaceData * _pifdObjectName;
+
+#ifndef _CHICAGO_
+ // Token object of the registering server.
+ CToken * _pToken;
+
+ // Window station - desktop of server.
+ WCHAR * _pwszWinstaDesktop;
+#endif
+
+ // Where the data for _pifdObject, _pmkeqbufKey,
+ // _pifdObjectName, and _pwszWinstaDesktop are stored.
+ BYTE _ab[1];
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::~CScmRotEntry
+//
+// Synopsis: Clean up object and invalidate signitures
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CScmRotEntry::~CScmRotEntry(void)
+{
+ // Invalidate signiture identifiers.
+ _dwSig = 0;
+ _dwScmRotId = 0;
+
+#ifndef _CHICAGO_
+ if ( _pToken )
+ _pToken->Release();
+#endif
+
+ // Remember that all the data allocated in pointers was allocated
+ // when this object was created so the freeing of the object's memory
+ // will free all the memory for this object.
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::GetProcessID
+//
+// Synopsis: Get the process ID for the registration
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline DWORD CScmRotEntry::GetProcessID(void)
+{
+ return _dwProcessID;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::SetTime
+//
+// Synopsis: Set the time for the entry
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CScmRotEntry::SetTime(FILETIME *pfiletime)
+{
+ _filetimeLastChange = *pfiletime;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::GetTime
+//
+// Synopsis: Get the time for an entry
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CScmRotEntry::GetTime(FILETIME *pfiletime)
+{
+ *pfiletime = _filetimeLastChange;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::GetObject
+//
+// Synopsis: Return the marshaled interface for the object
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline InterfaceData *CScmRotEntry::GetObject(void)
+{
+ return _pifdObject;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::GetMoniker
+//
+// Synopsis: Return the marshaled moniker
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline InterfaceData *CScmRotEntry::GetMoniker(void)
+{
+ return _pifdObjectName;
+}
+
+#ifndef _CHICAGO_
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::Token
+//
+// Synopsis: Return the CToken.
+//
+//--------------------------------------------------------------------------
+inline CToken * CScmRotEntry::Token()
+{
+ return _pToken;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::WinstaDesktop
+//
+// Synopsis: Return the winsta\desktop string.
+//
+//--------------------------------------------------------------------------
+inline WCHAR * CScmRotEntry::WinstaDesktop()
+{
+ return _pwszWinstaDesktop;
+}
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::IsValid
+//
+// Synopsis: Validate signitures for the object
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CScmRotEntry::IsValid(DWORD dwScmId)
+{
+ return (SCMROT_SIG == _dwSig) && (_dwScmRotId == dwScmId);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::Key
+//
+// Synopsis: Get the buffer for the marshaled data
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BYTE *CScmRotEntry::Key(void)
+{
+ return &_pmkeqbufKey->abEqData[0];
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::cKey
+//
+// Synopsis: Get count of bytes in the marshaled buffer
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline DWORD CScmRotEntry::cKey(void)
+{
+ return _pmkeqbufKey->cdwSize;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::SetScmRegKey
+//
+// Synopsis: Copy out the registration key
+//
+// History: 23-Feb-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CScmRotEntry::SetScmRegKey(SCMREGKEY *psrkOut)
+{
+ psrkOut->dwEntryLoc = (DWORD) this;
+ psrkOut->dwScmId = _dwScmRotId;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::operator new
+//
+// Synopsis: Stop this class being allocated by wrong new
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#if DBG == 1
+inline void *CScmRotEntry::operator new(size_t size)
+{
+ Win4Assert(0 && "Called regular new on CScmRotEntry");
+ return NULL;
+}
+#endif // DBG
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotEntry::operator new
+//
+// Synopsis: Force contiguous allocation of data in entry
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void *CScmRotEntry::operator new(
+ size_t size,
+#ifndef _CHICAGO_
+ size_t sizeWinstaDesktop,
+#endif
+ size_t sizeObject,
+ size_t sizeMnkEqBuf,
+ size_t sizeObjectName)
+{
+#ifndef _CHICAGO_
+ return ScmMemAlloc(size + sizeWinstaDesktop + sizeObject + sizeMnkEqBuf + sizeObjectName );
+#else
+ return ScmMemAlloc(size + sizeObject + sizeMnkEqBuf + sizeObjectName );
+#endif
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CScmRot (sr)
+//
+// Purpose: Provide implementation of the ROT in the SCM
+//
+// Interface: Register - register a new entry in the ROT.
+// Revoke - remove an entry from the ROT
+// IsRunning - determine if an entry is in the ROT
+// NoteChangeTime - set time last changed in the ROT
+// GetTimeOfLastChange - get time of change in the ROT
+// EnumRunning - get all running monikers
+//
+// History: 20-Jan-95 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+class CScmRot : public CScmAlloc
+{
+public:
+ CScmRot(
+ HRESULT& hr,
+ WCHAR *pwszNameHintTable);
+
+ HRESULT Register(
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ MNKEQBUF *pmnkeqbuf,
+ InterfaceData *pifdObject,
+ InterfaceData *pifdObjectName,
+ FILETIME *pfiletime,
+ DWORD dwProcessID,
+#ifndef _CHICAGO_
+ WCHAR *pwszServerExe,
+#endif
+ SCMREGKEY *pdwRegister);
+
+ HRESULT Revoke(
+ SCMREGKEY *psrkRegister,
+ BOOL fServer,
+ InterfaceData **pifdObject,
+ InterfaceData **pifdName);
+
+ HRESULT IsRunning(
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ MNKEQBUF *pmnkeqbuf);
+
+ HRESULT GetObject(
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ DWORD dwProcessID,
+ MNKEQBUF *pmnkeqbuf,
+ SCMREGKEY *psrkRegister,
+ InterfaceData **ppifdObject);
+
+ HRESULT NoteChangeTime(
+ SCMREGKEY *psrkRegister,
+ FILETIME *pfiletime);
+
+ HRESULT GetTimeOfLastChange(
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ MNKEQBUF *pmnkeqbuf,
+ FILETIME *pfiletime);
+
+ HRESULT EnumRunning(
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ MkInterfaceList **ppMkIFList);
+
+private:
+ // This is a friend for Chicago initialization purposes.
+ friend HRESULT StartSCM(VOID);
+
+ CScmRotEntry * GetRotEntry(
+#ifndef _CHICAGO_
+ CToken *pToken,
+ WCHAR *pwszWinstaDesktop,
+#endif
+ MNKEQBUF *pmnkeqbuf);
+
+ // Mutex to protect from multithreaded update
+ // This mutex must be static so we can initialize
+ // it per process in Chicago.
+#ifdef _CHICAGO_
+ static CStaticPortableMutex _mxs;
+#else
+ CDynamicPortableMutex _mxs;
+#endif // _CHICAGO_
+
+ // ID Counter to make entries unique
+ DWORD _dwIdCntr;
+
+#ifndef _CHICAGO_
+ // Table that tells clients whether they need to
+ // contact the SCM for accurate information.
+ CScmRotHintTable _rht;
+#endif // !_CHICAGO_
+
+ // Scm Hash Table
+ CScmHashTable _sht;
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRot::CScmRot
+//
+// Synopsis: Initialize the SCM ROT
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CScmRot::CScmRot(HRESULT& hr, WCHAR *pwszNameHintTable)
+ : _dwIdCntr(0),
+#ifndef _CHICAGO_
+ _rht(pwszNameHintTable),
+#endif // _CHICAGO_
+ _sht(SCM_HASH_SIZE)
+{
+#ifdef _CHICAGO_
+
+ hr = _sht.InitOK() ? S_OK : E_OUTOFMEMORY;
+
+#else // ! _CHICAGO_
+
+ hr = (_sht.InitOK() && _rht.InitOK()) ? S_OK : E_OUTOFMEMORY;
+
+#endif // !_CHICAGO_
+}
+
+#endif __SCMROT_HXX__
diff --git a/private/ole32/dcomss/olescm/scmsvc.cxx b/private/ole32/dcomss/olescm/scmsvc.cxx
new file mode 100644
index 000000000..5b4f9833c
--- /dev/null
+++ b/private/ole32/dcomss/olescm/scmsvc.cxx
@@ -0,0 +1,332 @@
+//+-----------------------------------------------------------------------
+//
+// Microsoft Windows
+//
+// Copyright (c) Microsoft Corporation 1991 - 1992
+//
+// File: scmsvc.cxx
+//
+// Contents: Initialization for win32 service controller.
+//
+// History: 14-Jul-92 CarlH Created.
+// 31-Dec-93 ErikGav Chicago port
+//
+//------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include "scm.hxx"
+#include "port.hxx"
+#ifdef DCOM
+#include "rawdscm.h"
+#include "remact.h"
+#endif
+
+#include <scmstart.hxx>
+#include <secdes.hxx>
+#include <cevent.hxx>
+#include <thread.hxx>
+#include <scmrotif.hxx>
+#include <shrtbl.hxx>
+#include "cls.hxx"
+#ifdef DCOM
+#include "remact.hxx"
+#endif
+
+#ifdef _CAIRO_
+#include <dfsapi.h>
+#endif
+
+#if DBG == 1
+#include <outfuncs.h>
+
+extern void SetScmDefaultInfoLevel(void);
+#endif
+
+WCHAR SCMMachineName[MAX_COMPUTERNAME_LENGTH+1];
+
+#ifndef _CHICAGO_
+extern CRITICAL_SECTION ShellQueryCS;
+extern CRITICAL_SECTION RemoteServerCS;
+
+SC_HANDLE hServiceController = 0;
+HANDLE ghDfs = 0;
+#endif
+
+#ifdef _CHICAGO_
+// Windows globals.
+//
+static HINSTANCE _hinst = (HINSTANCE) INVALID_HANDLE_VALUE;
+#endif
+
+#include <cls.hxx>
+
+#ifndef _CHICAGO_
+DECLARE_INFOLEVEL(Cairole);
+#endif
+
+#ifndef _CHICAGO_
+#define SCM_CREATED_EVENT TEXT("ScmCreatedEvent")
+CScmShrdTbl * g_pScmShrdTbl = NULL;
+PSID psidMySid = NULL;
+#endif
+
+ULONG fUseSeparateWOW = SCM_ALLOW_SHARED_WOW;
+
+#define RPC_MIN_THREADS 1
+#define RPC_MAX_THREADS RPC_C_LISTEN_MAX_CALLS_DEFAULT
+#define RPC_MAX_REQS RPC_C_PROTSEQ_MAX_REQS_DEFAULT
+#define MAX_ENDPOINT_RETRY 3
+#define UPDATE_WAIT_MS 250
+
+#if DBG == 1
+//+-------------------------------------------------------------------------
+//
+// Function: SetScmDefaultInfoLevel
+//
+// Synopsis: Sets the default infolevel for the SCM
+//
+// History: 07-Jan-94 Ricksa Created
+//
+// Notes: Uses standard place in win.ini defined by KevinRo but
+// does not use the same value as compob32.dll so you don't
+// have to get all the debugging in the universe just to
+// get the SCM's debug output.
+//
+// A second point is that we don't use unicode here because
+// it is just easier to avoid the unicode headache with
+// mulitple builds between chicago and nt
+//
+//--------------------------------------------------------------------------
+char *pszInfoLevelSectionName = "Cairo InfoLevels";
+char *pszInfoLevelName = "scm";
+char *pszInfoLevelDefault = "$";
+
+#define INIT_VALUE_SIZE 16
+void SetScmDefaultInfoLevel(void)
+{
+ char aszInitValue[INIT_VALUE_SIZE];
+
+ ULONG ulRet;
+
+ ulRet = GetProfileStringA(pszInfoLevelSectionName,
+ pszInfoLevelName,
+ pszInfoLevelDefault,
+ aszInitValue,
+ INIT_VALUE_SIZE);
+
+ if ((ulRet != INIT_VALUE_SIZE - 1) && (aszInitValue[0] != L'$'))
+ {
+ if((ulRet = strtoul(aszInitValue, NULL, 16)) == 1)
+ {
+ CairoleInfoLevel = ulRet;
+ }
+ }
+}
+#endif // DBG == 1
+
+#ifndef _CHICAGO_
+//+-------------------------------------------------------------------------
+//
+// Function: InitializeSCM
+//
+// Synopsis: Initializes OLE side of orpcss.
+//
+// Arguments: None.
+//
+// Returns: Status of initialization.
+//
+//--------------------------------------------------------------------------
+DWORD
+InitializeSCM( void )
+{
+ DWORD Size;
+ NTSTATUS NtStatus;
+ SCODE sc;
+ RPC_STATUS rs;
+ SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
+
+ Size = sizeof(SCMMachineName);
+ if ( ! GetComputerName( SCMMachineName, &Size ) )
+ {
+ SCMMachineName[0] = 0;
+ DbgPrint("SCM : GetComputerName failed!\n");
+ }
+
+ InitializeCriticalSection(&ShellQueryCS);
+ InitializeCriticalSection(&RemoteServerCS);
+
+ hServiceController = OpenSCManager(NULL, NULL, GENERIC_EXECUTE);
+
+ //
+ // Get my sid
+ // This is simplified under the assumption that SCM runs as LocalSystem.
+ // We should remove this code when we incorporate OLE service into the
+ // Service Control Manager since this becomes duplicated code then.
+ //
+ NtStatus = RtlAllocateAndInitializeSid (
+ &NtAuthority,
+ 1,
+ SECURITY_LOCAL_SYSTEM_RID,
+ 0, 0, 0, 0, 0, 0, 0,
+ &psidMySid
+ );
+
+ Win4Assert(NT_SUCCESS(NtStatus) && "Failed to get SCM sid");
+
+#if DBG == 1
+ OpenDebugSinks();
+ // Set the debugging info level
+ SetScmDefaultInfoLevel();
+#endif // DBG == 1
+
+ UpdateState(SERVICE_START_PENDING);
+
+ HRESULT hr = NOERROR;
+
+ hr = InitSCMRegistry();
+
+ // Create class tables
+ gpCLocSrvList = new CLocSrvList(hr);
+
+ // BUGBUG: We need to do better!
+ Win4Assert(SUCCEEDED(hr) && "Server List Initialization Failed");
+
+ gpClassCache = new CClassCacheList(hr);
+
+ // BUGBUG: We need to do better!
+ Win4Assert(SUCCEEDED(hr) && "Class Initialization Failed");
+
+ gpCRemSrvList = new CRemSrvList(hr);
+
+ // BUGBUG: We need to do better!
+ Win4Assert(SUCCEEDED(hr) && "Remote List Initialization Failed");
+
+ // Load Proxy/Stub Clsid map
+ g_pScmShrdTbl = new CScmShrdTbl(hr);
+ Win4Assert((g_pScmShrdTbl && SUCCEEDED(hr)) && "CScmShrdTbl create failed");
+ g_pScmShrdTbl->UpdateWithLock();
+
+ UpdateState(SERVICE_START_PENDING);
+
+ // start the RPC service
+
+ CWorldSecurityDescriptor secd;
+
+ hr = InitScmRot();
+
+ Win4Assert(SUCCEEDED(hr) && "ROT Initialization Failed");
+
+ sc = RpcServerRegisterIf(ISCM_ServerIfHandle, 0, 0);
+ Win4Assert((sc == 0) && "RpcServerRegisterIf failed!");
+
+ sc = RpcServerRegisterIf(IDSCM_ServerIfHandle, 0, 0);
+ Win4Assert((sc == 0) && "RpcServerRegisterIf failed!");
+
+ sc = RpcServerRegisterIf(_IActivation_ServerIfHandle, 0, 0);
+ Win4Assert((sc == 0) && "RpcServerRegisterIf failed!");
+
+ DfsOpen( &ghDfs );
+
+ UpdateState(SERVICE_START_PENDING);
+
+ return 0;
+}
+
+void
+InitializeSCMAfterListen( void )
+{
+#ifdef _CAIRO_
+ // Now let DFS know our protocol sequences.
+ DfsRegisterSCM();
+#endif
+
+ //
+ // This is for the OLE apps which start during boot. They must wait for
+ // rpcss to start before completing OLE calls that talk to rpcss.
+ //
+ HRESULT hr;
+ HANDLE EventHandle;
+ CWorldSecurityDescriptor secd;
+ SECURITY_ATTRIBUTES secattr;
+
+ secattr.nLength = sizeof(secattr);
+ secattr.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR) secd;
+ secattr.bInheritHandle = FALSE;
+
+ EventHandle = CreateEvent( &secattr, TRUE, FALSE, SCM_CREATED_EVENT );
+ if ( EventHandle )
+ SetEvent( EventHandle );
+ else
+ DbgPrint( "Could not create ScmCreatedEvent\n" );
+}
+#endif // ifndef _CHICAGO_
+
+#ifdef _CHICAGO_
+//+-------------------------------------------------------------------------
+//
+// Function: StartSCM
+//
+// Synopsis: Win9x SCM-less OLE initialization
+//
+// History: Oct-94 BillMo Created.
+//
+// Notes: This function assumes it is in a global cross process
+// mutex (provided by compobj.cxx::CheckAndStartSCM)
+//
+//--------------------------------------------------------------------------
+HRESULT StartSCM(VOID)
+{
+ HRESULT hr;
+ ROOT_SHARED_DATA *prsd;
+
+ if (g_hrInit != S_OK)
+ {
+ return g_hrInit;
+ }
+
+#if DBG == 1
+ OpenDebugSinks();
+ // Set the debugging info level
+ SetScmDefaultInfoLevel();
+ CairoleDebugOut((DEB_TRACE, "StartSCM entererd\n"));
+#endif // DBG == 1
+
+
+ // Note: this is a no-op if already initialized.
+ hr = CSrvRegList::s_mxsSyncAccess.Init(
+ TEXT("OLESCMSRVREGLISTMUTEX"), FALSE);
+
+ if (FAILED(hr))
+ {
+ Win4Assert(!"OLESCMSRVREGLISTMUTEX Init failed");
+ return(hr);
+ }
+
+
+ hr = CSrvRegList::s_mxsOnlyOne.Init(TEXT("OLESCMGETHANDLEMUTEX"), FALSE);
+
+ if (FAILED(hr))
+ {
+ Win4Assert(!"OLESCMGETHANDLEMUTEX Init failed");
+ return(hr);
+ }
+
+ hr = CScmRot::_mxs.Init(TEXT("OLESCMROTMUTEX"), FALSE);
+
+ if (FAILED(hr))
+ {
+ Win4Assert(!"OLESCMROTMUTEX Init failed");
+ return(hr);
+ }
+
+ if (!InitSharedLists())
+ {
+ Win4Assert(!"InitSharedLists failed");
+ return(hr);
+ }
+
+ return(hr);
+}
+#endif // ifdef _CHICAGO_
diff --git a/private/ole32/dcomss/olescm/secdesc.cxx b/private/ole32/dcomss/olescm/secdesc.cxx
new file mode 100644
index 000000000..439943dc7
--- /dev/null
+++ b/private/ole32/dcomss/olescm/secdesc.cxx
@@ -0,0 +1,282 @@
+/****************************** Module Header ******************************\
+* Module Name: secdesc.cxx
+*
+* Copyright (c) 1991, Microsoft Corporation
+*
+* Routines that support creation and deletion of security descriptors
+*
+* History:
+* 02-06-92 Davidc Created.
+* 04-14-92 RichardW Changed ACE_HEADER
+* 04-01-94 AndyH Copied from winlogon. Changed to .CXX
+\***************************************************************************/
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <scm.h>
+#include <sem.hxx>
+#include <clsdata.hxx>
+#include "secdesc.h"
+
+//
+// Private prototypes
+//
+
+PACCESS_ALLOWED_ACE
+CreateAccessAllowedAce(
+ PSID Sid,
+ ACCESS_MASK AccessMask,
+ UCHAR AceFlags,
+ UCHAR InheritFlags
+ );
+
+VOID
+DestroyAce(
+ PVOID Ace
+ );
+
+
+//
+// Memory macros
+//
+
+#define Alloc(c) ((PVOID)LocalAlloc(LPTR, c))
+#define ReAlloc(p, c) ((PVOID)LocalReAlloc(p, c, LPTR | LMEM_MOVEABLE))
+#define Free(p) ((VOID)LocalFree(p))
+
+
+/***************************************************************************\
+* CreateSecurityDescriptor
+*
+* Creates a security descriptor containing an ACL containing the specified ACEs
+*
+* A SD created with this routine should be destroyed using
+* DeleteSecurityDescriptor
+*
+* Returns a pointer to the security descriptor or NULL on failure.
+*
+* 02-06-92 Davidc Created.
+\***************************************************************************/
+
+PSECURITY_DESCRIPTOR
+CreateSecurityDescriptor(
+ PMYACE MyAce,
+ ACEINDEX AceCount
+ )
+{
+ NTSTATUS Status;
+ ACEINDEX AceIndex;
+ PACCESS_ALLOWED_ACE *Ace;
+ PACL Acl = NULL;
+ PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
+ ULONG LengthAces;
+ ULONG LengthAcl;
+ ULONG LengthSd;
+
+ //
+ // Allocate space for the ACE pointer array
+ //
+
+ Ace = (PACCESS_ALLOWED_ACE *)Alloc(sizeof(PACCESS_ALLOWED_ACE) * AceCount);
+ if (Ace == NULL) {
+ CairoleDebugOut((DEB_ERROR, "Failed to allocated ACE array\n"));
+ return(NULL);
+ }
+
+ //
+ // Create the ACEs and calculate total ACE size
+ //
+
+ LengthAces = 0;
+ for (AceIndex=0; AceIndex < AceCount; AceIndex ++) {
+ Ace[AceIndex] = CreateAccessAllowedAce(MyAce[AceIndex].Sid,
+ MyAce[AceIndex].AccessMask,
+ 0,
+ MyAce[AceIndex].InheritFlags);
+ if (Ace[AceIndex] == NULL) {
+ CairoleDebugOut((DEB_ERROR, "Failed to allocated ACE\n"));
+ } else {
+ LengthAces += Ace[AceIndex]->Header.AceSize;
+ }
+ }
+
+ //
+ // Calculate ACL and SD sizes
+ //
+
+ LengthAcl = sizeof(ACL) + LengthAces;
+ LengthSd = SECURITY_DESCRIPTOR_MIN_LENGTH;
+
+ //
+ // Create the ACL
+ //
+
+ Acl = (PACL) Alloc(LengthAcl);
+
+ if (Acl != NULL) {
+
+ Status = RtlCreateAcl(Acl, LengthAcl, ACL_REVISION);
+ Win4Assert(NT_SUCCESS(Status));
+
+ //
+ // Add the ACES to the ACL and destroy the ACEs
+ //
+
+ for (AceIndex = 0; AceIndex < AceCount; AceIndex ++) {
+
+ if (Ace[AceIndex] != NULL) {
+
+ Status = RtlAddAce(Acl, ACL_REVISION, 0, Ace[AceIndex],
+ Ace[AceIndex]->Header.AceSize);
+
+ if (!NT_SUCCESS(Status)) {
+ CairoleDebugOut((DEB_ERROR, "AddAce failed, status = 0x%lx\n", Status));
+ }
+
+ DestroyAce(Ace[AceIndex]);
+ }
+ }
+
+ } else {
+ CairoleDebugOut((DEB_ERROR, "Failed to allocated ACL\n"));
+ }
+
+ //
+ // Free the ACE pointer array
+ //
+ Free(Ace);
+
+ //
+ // Create the security descriptor
+ //
+
+ SecurityDescriptor = Alloc(LengthSd);
+
+ if (SecurityDescriptor != NULL) {
+
+ Status = RtlCreateSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
+ Win4Assert(NT_SUCCESS(Status));
+
+ //
+ // Set the DACL on the security descriptor
+ //
+ Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor, TRUE, Acl, FALSE);
+ if (!NT_SUCCESS(Status)) {
+ // BUGBUG CairoleDebugOut WLPrint(("SetDACLSD failed, status = 0x%lx", Status));
+ }
+ } else {
+ // BUGBUG CairoleDebugOut WLPrint(("Failed to allocate security descriptor"));
+ }
+
+ //
+ // Return with our spoils
+ //
+ return(SecurityDescriptor);
+}
+
+
+/***************************************************************************\
+* DeleteSecurityDescriptor
+*
+* Deletes a security descriptor created using CreateSecurityDescriptor
+*
+* Returns TRUE on success, FALSE on failure
+*
+* 02-06-92 Davidc Created.
+\***************************************************************************/
+
+BOOL
+DeleteSecurityDescriptor(
+ PSECURITY_DESCRIPTOR SecurityDescriptor
+ )
+{
+ NTSTATUS Status;
+ PACL Acl;
+ BOOLEAN Present;
+ BOOLEAN Defaulted;
+
+ Win4Assert(SecurityDescriptor != NULL);
+
+ //
+ // Get the ACL
+ //
+ Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
+ &Present, &Acl, &Defaulted);
+ if (NT_SUCCESS(Status)) {
+
+ //
+ // Destroy the ACL
+ //
+ if (Present && (Acl != NULL)) {
+ Free(Acl);
+ }
+ } else {
+ // BUGBUG CairoleDebugOut WLPrint(("Failed to get DACL from security descriptor being destroyed, Status = 0x%lx", Status));
+ }
+
+ //
+ // Destroy the Security Descriptor
+ //
+ Free(SecurityDescriptor);
+
+ return(TRUE);
+}
+
+
+/***************************************************************************\
+* CreateAccessAllowedAce
+*
+* Allocates memory for an ACCESS_ALLOWED_ACE and fills it in.
+* The memory should be freed by calling DestroyACE.
+*
+* Returns pointer to ACE on success, NULL on failure
+*
+* History:
+* 12-05-91 Davidc Created
+* 04-05-94 AndyH Changed return to ACE
+\***************************************************************************/
+PACCESS_ALLOWED_ACE
+CreateAccessAllowedAce(
+ PSID Sid,
+ ACCESS_MASK AccessMask,
+ UCHAR AceFlags,
+ UCHAR InheritFlags
+ )
+{
+ ULONG LengthSid = RtlLengthSid(Sid);
+ ULONG LengthACE = sizeof(ACE_HEADER) + sizeof(ACCESS_MASK) + LengthSid;
+ PACCESS_ALLOWED_ACE Ace;
+
+ Ace = (PACCESS_ALLOWED_ACE)Alloc(LengthACE);
+ if (Ace == NULL) {
+ // BUGBUG CairoleDebugOut WLPrint(("CreateAccessAllowedAce : Failed to allocate ace"));
+ return NULL;
+ }
+
+ Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
+ Ace->Header.AceSize = (UCHAR)LengthACE;
+ Ace->Header.AceFlags = AceFlags | InheritFlags;
+ Ace->Mask = AccessMask;
+ RtlCopySid(LengthSid, (PSID)(&(Ace->SidStart)), Sid );
+
+ return(Ace);
+}
+
+
+/***************************************************************************\
+* DestroyAce
+*
+* Frees the memory allocate for an ACE
+*
+* History:
+* 12-05-91 Davidc Created
+\***************************************************************************/
+VOID
+DestroyAce(
+ PVOID Ace
+ )
+{
+ Free(Ace);
+}
+
diff --git a/private/ole32/dcomss/olescm/secdesc.h b/private/ole32/dcomss/olescm/secdesc.h
new file mode 100644
index 000000000..6fb5ab902
--- /dev/null
+++ b/private/ole32/dcomss/olescm/secdesc.h
@@ -0,0 +1,41 @@
+/****************************** Module Header ******************************\
+* Module Name: secdesc.h
+*
+* Copyright (c) 1991, Microsoft Corporation
+*
+* Defines apis and types used to implement security descriptor helper routines
+*
+* History:
+* 02-06-92 Davidc Created.
+\***************************************************************************/
+
+//
+// Types used by security descriptor helper routines
+//
+
+typedef LONG ACEINDEX;
+typedef ACEINDEX *PACEINDEX;
+
+typedef struct _MYACE {
+ PSID Sid;
+ ACCESS_MASK AccessMask;
+ UCHAR InheritFlags;
+} MYACE;
+typedef MYACE *PMYACE;
+
+
+//
+// Exported function prototypes
+//
+
+PSECURITY_DESCRIPTOR
+CreateSecurityDescriptor(
+ PMYACE MyAce,
+ ACEINDEX AceCount
+ );
+
+BOOL
+DeleteSecurityDescriptor(
+ PSECURITY_DESCRIPTOR SecurityDescriptor
+ );
+
diff --git a/private/ole32/dcomss/olescm/srothint.cxx b/private/ole32/dcomss/olescm/srothint.cxx
new file mode 100644
index 000000000..ec0be6edc
--- /dev/null
+++ b/private/ole32/dcomss/olescm/srothint.cxx
@@ -0,0 +1,78 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: srothint.cxx
+//
+// Contents: Implementation of classes used in implementing the ROT hint
+// table in the SCM.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#include <headers.cxx>
+
+#include <access.hxx>
+#include "srothint.hxx"
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotHintTable::CScmRotHintTable
+//
+// Synopsis: Create SCM ROT hint table
+//
+// Arguments: [pwszName] - name for shared memory
+// [psid] - security ID
+//
+// Algorithm: Create and map in shared memory for the hint table
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CScmRotHintTable::CScmRotHintTable(WCHAR *pwszName)
+{
+ BOOL fCreated;
+ PSECURITY_DESCRIPTOR pRotSecurityDescriptor = NULL;
+ SID_IDENTIFIER_AUTHORITY SidAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
+ PSID pSid;
+
+ pSid = 0;
+
+ fCreated = AllocateAndInitializeSid(
+ &SidAuthWorld, 1, 0, 0, 0, 0, 0, 0, 0, 0, &pSid );
+
+ Win4Assert(fCreated && "CRotHintTable::CRotHintTable No SID");
+
+ if ( ! fCreated || ! pSid )
+ return;
+
+ CAccessInfo AccessInfo(pSid);
+
+ pRotSecurityDescriptor = AccessInfo.IdentifyAccess (
+ TRUE,
+ FILE_MAP_READ,
+ FILE_MAP_ALL_ACCESS
+ );
+
+ _hSm = CreateSharedFileMapping(pwszName,
+ SCM_HASH_SIZE,
+ SCM_HASH_SIZE,
+ NULL,
+ pRotSecurityDescriptor,
+ PAGE_READWRITE,
+ (void **) &_pbHintArray,
+ &fCreated);
+
+ Win4Assert(_hSm && "CRotHintTable::CRotHintTable create SM failed");
+ Win4Assert(fCreated && "CRotHintTable::CRotHintTable Memory not created");
+
+ FreeSid( pSid );
+
+ if (_pbHintArray != NULL)
+ {
+ memset(_pbHintArray, 0, SCM_HASH_SIZE);
+ }
+}
diff --git a/private/ole32/dcomss/olescm/srothint.hxx b/private/ole32/dcomss/olescm/srothint.hxx
new file mode 100644
index 000000000..d62537d06
--- /dev/null
+++ b/private/ole32/dcomss/olescm/srothint.hxx
@@ -0,0 +1,82 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: srothint.hxx
+//
+// Contents: Classes used in implementing the ROT hint table.
+//
+// Functions:
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __SROTHINT_HXX__
+#define __SROTHINT_HXX__
+
+
+#ifndef _CHICAGO_
+
+#include <rothint.hxx>
+#include <smcreate.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Class: CScmRotHintTable (srht)
+//
+// Purpose: abstract SCM side of the hint table
+//
+// Interface: InitOK - whether initialization succeeded.
+//
+// History: 20-Jan-95 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+class CScmRotHintTable : public CRotHintTable
+{
+public:
+ CScmRotHintTable(WCHAR *pwszName);
+
+ ~CScmRotHintTable(void);
+
+ BOOL InitOK(void);
+
+private:
+
+ HANDLE _hSm;
+};
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotHintTable::~CScmRotHintTable
+//
+// Synopsis: Clean up hint table object
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CScmRotHintTable::~CScmRotHintTable(void)
+{
+ CloseSharedFileMapping(_hSm, _pbHintArray);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CScmRotHintTable::InitOK
+//
+// Synopsis: Whether initialization worked
+//
+// History: 20-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CScmRotHintTable::InitOK(void)
+{
+ return _hSm != NULL;
+}
+
+#endif // !_CHICAGO_
+
+#endif // __ROTHINT_HXX__
diff --git a/private/ole32/dcomss/olescm/srvreg.cxx b/private/ole32/dcomss/olescm/srvreg.cxx
new file mode 100644
index 000000000..c03a05414
--- /dev/null
+++ b/private/ole32/dcomss/olescm/srvreg.cxx
@@ -0,0 +1,826 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: srvreg.hxx
+//
+// Contents: Classes used for keeping track of end points for a given
+// class.
+//
+// Classes: SClsSrvHandle
+//
+// History: 03-Jan-94 Ricksa Created
+// 01-Feb-96 BruceMa Support psid checking
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include "scm.hxx"
+#include "port.hxx"
+#include "srvreg.hxx"
+#include "or.hxx"
+
+#ifdef _CHICAGO_
+BOOL NotifyToInitializeRpc(HWND hwnd);
+DWORD GetOleNotificationWnd();
+CStaticPortableMutex CSrvRegList::s_mxsOnlyOne; // mutex semaphore
+#endif
+
+
+// Mutex to protect multithreaded access to class data
+CStaticPortableMutex CSrvRegList::s_mxsSyncAccess;
+
+BOOL CSrvRegList::s_fForcedScmShutdown = FALSE;
+
+//+-------------------------------------------------------------------------
+//
+// Member: SSrvRegistration::Free
+//
+// Synopsis: Clean up array entry
+//
+// Algorithm: Loop through any handle that exists and close the
+// RPC binding on that handle.
+//
+// History: 03-Jan-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+void SSrvRegistration::Free(void)
+{
+ if (_hRpc != NULL)
+ {
+#ifndef _CHICAGO_
+ if ( _dwHandleCount == 0 )
+ {
+ RpcBindingFree(&_hRpc);
+ _hRpc = (RPC_COOKIE) NULL;
+
+ if (_hRpcAnonymous)
+ {
+ RpcBindingFree(&_hRpcAnonymous);
+ _hRpcAnonymous = 0;
+ }
+ }
+#else
+ ScmMemFree(_hRpc);
+ _hRpc = (RPC_COOKIE) NULL;
+#endif
+ }
+
+ _dwFlags = SRV_REG_INVALID;
+
+#ifndef _CHICAGO_
+
+ PrivMemFree (_psid);
+ _psid = NULL;
+ PrivMemFree (_pwszWinstaDesktop);
+ _pwszWinstaDesktop = NULL;
+
+#endif
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSrvRegList::~CSrvRegList
+//
+// Synopsis: Clean up a handle object
+//
+// Algorithm: Loop through any handle that exists and close the
+// RPC binding on that handle.
+//
+// History: 03-Jan-94 Ricksa Created
+//
+// Notes: This should only be used by the update thread so it
+// doesn't need to be locked
+//
+// BillMo: add assertion to ensure we're never removing
+// registrations that a client may need.
+// I have added a flag so that we can force the close of
+// RPC handles during a forced scm shutdown.
+//
+//--------------------------------------------------------------------------
+
+CSrvRegList::~CSrvRegList(void)
+{
+#ifdef _CHICAGO_
+ Win4Assert(!InUse());
+#else
+ if (!s_fForcedScmShutdown)
+ {
+ Win4Assert(!InUse());
+ }
+ else
+ // Search for all open RPC handles.
+ if (GetSize() > 0)
+ {
+ // Get pointer to the base of the array
+ SSrvRegistration *pssrvreg = (SSrvRegistration *) GetAt(0);
+
+ // Loop through array
+ for (int i = 0; i < GetSize(); i++, pssrvreg++)
+ {
+ // Tell RPC we no longer need the handle
+ if (pssrvreg->_hRpc != NULL)
+ {
+ pssrvreg->Free();
+ }
+ }
+ }
+#endif
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSrvRegList::Insert
+//
+// Synopsis: Insert a new registration into the list
+//
+// Arguments: [ssrvreg] - an entry for the table
+//
+// Returns: 0 - Error occurred and we could not register the handle
+// ~0 - Handle registered successfully
+//
+// Algorithm: Create a handle to an RPC bind. Then search the table for
+// a place to put the binding. Stick the bind in the first
+// available spot.
+//
+// History: 03-Jan-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+DWORD CSrvRegList::Insert(
+ IFSECURITY(PSID psid)
+ WCHAR *pwszWinstaDesktop,
+#ifdef DCOM
+ PHPROCESS phProcess,
+ OXID oxid,
+ IPID ipid,
+#else
+ WCHAR *pwszEndpoint,
+#endif
+ DWORD dwFlags)
+{
+ // Protect from multiple updates
+ CStaticPortableLock lck(s_mxsSyncAccess);
+ int iNew = 0;
+ DWORD dwReg = 0;
+ // Create an RPC bind
+ SSrvRegistration ssrvregNew;
+ ssrvregNew._dwFlags = (dwFlags == REGCLS_SURROGATE) ?
+ REGCLS_MULTIPLEUSE : dwFlags;
+ ssrvregNew._fSurrogate = (dwFlags == REGCLS_SURROGATE);
+ SSrvRegistration *pssrvreg;
+
+#ifndef _CHICAGO_
+ RPC_STATUS status;
+ // Get the string binding information from the process object.
+ ssrvregNew._hRpc = ((CProcess *)phProcess)->GetBindingHandle();
+
+ if (ssrvregNew._hRpc == 0)
+ return 0;
+
+ status = I_RpcBindingSetAsync(ssrvregNew._hRpc, 0);
+ if (status != RPC_S_OK)
+ return 0;
+
+ ssrvregNew._oxid = oxid;
+ ssrvregNew._ipid = ipid;
+
+ status = RpcBindingSetObject( ssrvregNew._hRpc, (GUID *) &ipid );
+ if (status != ERROR_SUCCESS)
+ {
+ return 0;
+ }
+
+ ssrvregNew._dwHandleCount = 0;
+
+ ssrvregNew._hRpcAnonymous = 0;
+#else // _CHICAGO_
+ ssrvregNew._hRpc = (WCHAR *)ScmMemAlloc(sizeof(WCHAR) * (lstrlenW(pwszEndpoint)+1));
+ ssrvregNew._ulWnd = GetOleNotificationWnd();
+ if (ssrvregNew._hRpc == NULL)
+ {
+ return(0);
+ }
+ lstrcpyW(ssrvregNew._hRpc, pwszEndpoint);
+#endif // _CHICAGO_
+
+#ifndef _CHICAGO_
+ ULONG ulLength;
+ NTSTATUS NtStatus;
+
+ ulLength = RtlLengthSid (psid);
+
+ ssrvregNew._psid = PrivMemAlloc (ulLength);
+
+ if (ssrvregNew._psid == NULL)
+ {
+ goto errRet;
+ }
+
+ NtStatus = RtlCopySid (ulLength, ssrvregNew._psid, psid);
+ Win4Assert (NT_SUCCESS(NtStatus) && "CSrvRegList::Insert");
+
+ if (!NT_SUCCESS(NtStatus))
+ {
+ goto errRet;
+ }
+#endif // CHICAGO
+
+ if (pwszWinstaDesktop != NULL)
+ {
+#ifdef _CHICAGO_
+ Win4Assert(FALSE);
+#endif
+ ssrvregNew._pwszWinstaDesktop =
+ (WCHAR *) PrivMemAlloc((lstrlenW(pwszWinstaDesktop) + 1) * sizeof(WCHAR));
+ if (ssrvregNew._pwszWinstaDesktop == NULL)
+ {
+ goto errRet;
+ }
+ lstrcpyW (ssrvregNew._pwszWinstaDesktop, pwszWinstaDesktop);
+ }
+ else
+ {
+ ssrvregNew._pwszWinstaDesktop = NULL;
+ }
+
+ // Put bind in our table
+ // Search for first empty bucket that we have
+ if (GetSize() > 0)
+ {
+ pssrvreg = (SSrvRegistration *) GetAt(0);
+
+ for ( ; iNew < GetSize(); iNew++, pssrvreg++)
+ {
+ if (pssrvreg->_hRpc == 0)
+ {
+ // Found an empty bucket
+ break;
+ }
+ }
+ }
+
+ if (iNew < GetSize())
+ {
+ memcpy(pssrvreg, &ssrvregNew, sizeof(ssrvregNew));
+ }
+ else if (!InsertAt(iNew, &ssrvregNew))
+ {
+ goto errRet;
+ }
+
+ CairoleDebugOut((DEB_ITRACE,
+ "CSrvRegList::Insert() -> %08X\n",
+ ssrvregNew._hRpc));
+
+ return (DWORD) ssrvregNew._hRpc;
+
+errRet:
+
+ ssrvregNew.Free();
+
+ return(0);
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSrvRegList::Delete
+//
+// Synopsis: Delete an end point from the list of registered end points
+//
+// Arguments: [dwReg] - value used for registration
+//
+// Returns: TRUE - LAST registration deleted
+// FALSE - other registrations still exist
+//
+// Algorithm: Convert the registration to the RPC handle and then
+// loop through the table of registrations to see if the
+// we can find it. If we do, tell RPC to dump the handle.
+//
+// History: 03-Jan-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+BOOL CSrvRegList::Delete(RPC_COOKIE hRpc)
+{
+ BOOL fLast = TRUE;
+
+ if (hRpc != (RPC_COOKIE)NULL)
+ {
+ // Protect from multiple updates
+ CStaticPortableLock lck(s_mxsSyncAccess);
+
+ // For Daytona, Registration is actually the RPC handle
+ // For Chicago, Registration is the strings address
+
+ // Search for matching entry in table
+ SSrvRegistration *pssrvreg = (SSrvRegistration *) GetAt(0);
+
+ for (int i = 0; i < GetSize(); i++, pssrvreg++)
+ {
+ if (pssrvreg->_hRpc == NULL)
+ {
+ continue;
+ }
+ else if (pssrvreg->_hRpc == hRpc)
+ {
+ pssrvreg->Free();
+ }
+ else
+ {
+ fLast = FALSE;
+ }
+ }
+ }
+ else
+ {
+ fLast = FALSE;
+ }
+ return fLast;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSrvRegList::GetHandle
+//
+// Synopsis: Get a handle from the list of handles for the class
+//
+// Arguments: [psid] -- security id of client process
+// [pwszWinstaDesktop]
+// [rh] -- binding handle
+// [fSurrogate] -- flag indicating that we want to find a
+// surrogate process
+//
+// Returns: NULL - could not find a valid registration
+// ~NULL - handle to a running RPC server.
+//
+// Algorithm: Loop through the list searching for the first non-null
+// entry that we can use as a handle to an object server.
+//
+// History: 03-Jan-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CSrvRegList::GetHandle(IFSECURITY(PSID psid)
+ WCHAR * pwszWinstaDesktop,
+ CPortableRpcHandle &rh,
+ BOOL fSurrogate)
+{
+ SSrvRegistration *pssrvreg = 0;
+ HWND hWnd;
+
+
+ do
+ {
+ #ifdef _CHICAGO_
+ CStaticPortableLock lckOnlyOne(s_mxsOnlyOne);
+ #endif
+ CairoleDebugOut((DEB_ITRACE,
+ "CSrvRegList::GetHandle(%x) called (%x)\n",
+ this,pssrvreg));
+
+ { // begin mutex block
+ hWnd = 0;
+ // bracket for mutex
+
+ // Protect from multiple updates
+ CStaticPortableLock lck(s_mxsSyncAccess);
+
+ // Search for first non-empty bucket that we have
+ pssrvreg = (SSrvRegistration *) GetAt(0);
+
+ for (int i = 0; i < GetSize(); i++, pssrvreg++)
+ {
+ if ( (pssrvreg->_hRpc != NULL) &&
+ (pssrvreg->_dwFlags != SRV_REG_INVALID) )
+ {
+ // if we're looking for a surrogate...
+ if(fSurrogate)
+ {
+ if(!(pssrvreg->_fSurrogate))
+ {
+ continue;
+ }
+ }
+
+#ifndef _CHICAGO_
+ //
+ // Client's SID param is null when connecting to services
+ // or RunAs servers. In those instances we just take the
+ // first binding handle we find. Only a server running in
+ // the correct security context could register a handle.
+ //
+ // For connecting to "activate as activator" server, both
+ // the SID and, for local activations, the winsta\desktop
+ // must match the server's.
+ //
+ if ( psid != NULL )
+ {
+ if ( ! RtlEqualSid(pssrvreg->_psid, psid) )
+ continue;
+
+ if ( (pwszWinstaDesktop != NULL) &&
+ (lstrcmpW(pwszWinstaDesktop, pssrvreg->_pwszWinstaDesktop) != 0) )
+ continue;
+ }
+#endif
+
+ //
+ // On Chicago there are no SIDs nor desktops, so you get
+ // the first handle in the list.
+ //
+
+ rh.SetRpcCookie( pssrvreg->_hRpc,
+ pssrvreg->_dwFlags == REGCLS_SINGLEUSE,
+ pssrvreg->_ipid );
+
+#ifndef _CHICAGO_
+ pssrvreg->_dwHandleCount++;
+#endif
+
+ // Is this a single use registration?
+ if (pssrvreg->_dwFlags == REGCLS_SINGLEUSE)
+ {
+ CairoleDebugOut((DEB_ITRACE,
+ "CSrvRegList::GetHandle(%x) REGCLS_SINGLEUSE. Nulling handle pssrvreg(%x)\n",
+ this,pssrvreg));
+
+ // For the single use class, the call owns the handle now.
+ // So, we clear it and then try to free any other data
+ // associated with the entry.
+ #ifdef _CHICAGO_
+ if (pssrvreg->_ulWnd == 0)
+ #endif // _CHICAGO_
+ {
+ pssrvreg->_hRpc = NULL;
+ pssrvreg->Free();
+ }
+ }
+
+ #ifdef _CHICAGO_
+ if(pssrvreg->_ulWnd)
+ {
+ // notify the server once to launch rpc
+ // has to be done outside of the mutex
+ hWnd = (HWND)pssrvreg->_ulWnd;
+ pssrvreg->_ulWnd = 0;
+ CairoleDebugOut((DEB_ITRACE,
+ "CSrvRegList::GetHandle(%x) found with hWnd(%d)\n",
+ this, hWnd));
+
+ // fall out of loop and notify the server
+ // outside of the mutex
+ break;
+
+ }
+ #endif // _CHICAGO_
+
+ CairoleDebugOut((DEB_ITRACE,
+ "CSrvRegList::GetHandle(%x) called (%x) done TRUE\n",
+ this,pssrvreg));
+
+ return(TRUE);
+ }
+ }
+ } // end mutex block
+ #ifdef _CHICAGO_
+ if(hWnd)
+ {
+ // notify the server once to launch rpc
+ NotifyToInitializeRpc(hWnd);
+ // find the class again; since we released the
+ // mutex the server might have disappeared
+ }
+ else
+ #endif // _CHICAGO_
+ break;
+
+ } while (TRUE);
+
+
+ CairoleDebugOut((DEB_ITRACE,
+ "CSrvRegList::GetHandle(%x) called (%x) done FALSE\n",
+ this,pssrvreg));
+
+ return(FALSE);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSrvRegList::FindCompatibleSurrogate
+//
+// Synopsis: Finds a server for an existing surrogate process
+// with the desired attributes
+//
+// Arguments: [psid] -- security id of client process
+// [rh] -- binding handle
+//
+// Returns: TRUE - it found a server with the desired
+// attributes -- the rh reference or ppIObjServer
+// is set to that of the appropriate server
+// FALSE - no appropriate server
+//
+// Algorithm: Ask GetHandle or GetProxy
+// to search for a surrogate for us with the
+// desired attributes
+//
+// 21-JUN-96 t-adame created
+//
+//--------------------------------------------------------------------------
+BOOL CSrvRegList::FindCompatibleSurrogate(IFSECURITY(PSID psid)
+ WCHAR* pwszWinstaDesktop,
+ CPortableRpcHandle &rh)
+{
+ // we set the fSurrogate parameter of GetHandle to TRUE to let
+ // GetHandle know that we need a binding handle for a surrogate
+ // process
+
+ return GetHandle(IFSECURITY(psid) pwszWinstaDesktop,rh,TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSrvRegList::InUse
+//
+// Synopsis: See whether there is anything current registration
+//
+// Returns: TRUE - server is currently registered
+// FALSE - server is not currently registered
+//
+// Algorithm: Loop through the list searching for the first non-null
+// entry. If we find one return NULL.
+//
+// History: 04-Jan-94 Ricksa Created
+//
+// Notes: This should only be used by the update thread so it
+// doesn't need to be locked
+//
+//--------------------------------------------------------------------------
+
+BOOL CSrvRegList::InUse(void)
+{
+ // Protect from multiple updates
+ CStaticPortableLock lck(s_mxsSyncAccess);
+
+ // Assume there are no current registrations.
+ BOOL fResult = FALSE;
+
+ // Search for first non-empty bucket that we have
+ SSrvRegistration *pssrvreg = (SSrvRegistration *) GetAt(0);
+
+ for (int i = 0; i < GetSize(); i++, pssrvreg++)
+ {
+ if (pssrvreg->_hRpc != NULL)
+ {
+ fResult = TRUE;
+ break;
+ }
+ }
+
+ return fResult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSrvRegList::VerifyHandle
+//
+// Synopsis: Whether this is a valid handle to an object server
+//
+// Returns: TRUE - this is still a valid handle to an object server
+// FALSE - this is no longer a valid handle to an object server
+//
+// History: 11-May-94 DonnaLi Created
+//
+// Notes: This should only be used to assist the retry logic.
+//
+//--------------------------------------------------------------------------
+
+BOOL CSrvRegList::VerifyHandle(RPC_COOKIE hRpc)
+{
+ if (hRpc == (RPC_COOKIE)NULL)
+ return FALSE;
+
+ // Protect from multiple updates
+ CStaticPortableLock lck(s_mxsSyncAccess);
+
+ // Search for first non-empty bucket that we have
+ SSrvRegistration *pssrvreg = (SSrvRegistration *) GetAt(0);
+
+ for (int i = 0; i < GetSize(); i++, pssrvreg++)
+ {
+ if ( pssrvreg->_hRpc == hRpc
+#ifndef _CHICAG0_
+ && pssrvreg->_dwFlags != SRV_REG_INVALID
+#endif
+ )
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSrvRegList::InvalidateHandle
+//
+// Synopsis: Invalidate a handle in the list of handles for the class
+// Caller of GetHandle concluded it is no longer valid
+//
+// Arguments: [hRpc] -- handle to invalidate
+//
+// Returns: None
+//
+// Algorithm: Loop through the list searching for match on handle or
+// list is exhausted
+//
+// History: 20-Sep-95 MurthyS Created
+//
+//--------------------------------------------------------------------------
+VOID CSrvRegList::InvalidateHandle(
+ RPC_COOKIE hRpc
+)
+{
+ if (hRpc == (RPC_COOKIE)NULL)
+ {
+ return;
+ }
+
+ // Protect from multiple updates
+ CStaticPortableLock lck(s_mxsSyncAccess);
+
+ // Search for first non-empty bucket that we have
+ SSrvRegistration *pssrvreg = (SSrvRegistration *) GetAt(0);
+
+ for (int i = 0; i < GetSize(); i++, pssrvreg++)
+ {
+ if (pssrvreg->_hRpc == hRpc)
+ {
+ //
+ // At least try to free it. Its remotely possible that another
+ // thread will still have a reference which will cause us to
+ // orphan this handle.
+ //
+ // But we have to NULL it now so that InUse() will work right,
+ // so that the retry logic for launching a server will work right.
+ // This is all very gross and nasty and needs to be redone from
+ // scratch.
+ //
+ // Fix it in NT 5.0.
+ //
+ pssrvreg->Free();
+ pssrvreg->_hRpc == NULL;
+ return;
+ }
+ }
+}
+
+void CSrvRegList::GetAnonymousHandle(
+ CPortableRpcHandle &rh,
+ handle_t * phRpcAnonymous )
+{
+ RPC_STATUS RpcStatus;
+ RPC_SECURITY_QOS Qos;
+ BOOL bMatch;
+
+ *phRpcAnonymous = 0;
+ bMatch = FALSE;
+
+ // Protect from multiple updates
+ CStaticPortableLock lck(s_mxsSyncAccess);
+
+ // Search for first non-empty bucket that we have
+ SSrvRegistration *pssrvreg = (SSrvRegistration *) GetAt(0);
+
+ for (int i = 0; i < GetSize(); i++, pssrvreg++)
+ {
+ if ( (pssrvreg->_hRpc == rh.GetHandle()) &&
+ (pssrvreg->_dwFlags != SRV_REG_INVALID) )
+ {
+ Win4Assert( pssrvreg->_dwHandleCount );
+
+ if ( pssrvreg->_hRpcAnonymous )
+ {
+ *phRpcAnonymous = pssrvreg->_hRpcAnonymous;
+ return;
+ }
+
+ bMatch = TRUE;
+ break;
+ }
+ }
+
+ //
+ // We continue if we don't find the handle in the table if its a single
+ // use handle because it is removed from the table in GetHandle in that
+ // case.
+ //
+ if ( ! bMatch && ! rh.fSingleUse() )
+ return;
+
+ IPID ipid;
+
+ ipid = bMatch ? pssrvreg->_ipid : rh.Ipid();
+
+ //
+ // Note that we indicate impersonation level of identify because
+ // anonymous is not supported. However specifing no authentication
+ // in SetAuthInfo will keep the server from impersonating us.
+ //
+ Qos.Version = RPC_C_SECURITY_QOS_VERSION;
+ Qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
+ Qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY;
+ Qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
+
+ RpcStatus = RpcBindingCopy(
+ rh.GetHandle(),
+ phRpcAnonymous );
+
+ if ( RpcStatus != RPC_S_OK )
+ return;
+
+ RpcStatus = I_RpcBindingSetAsync( *phRpcAnonymous, 0 );
+
+ if ( RpcStatus != RPC_S_OK )
+ goto GetAnonymousHandleExit;
+
+ RpcStatus = RpcBindingSetObject( *phRpcAnonymous, (GUID *) &ipid );
+
+ if ( RpcStatus != RPC_S_OK )
+ goto GetAnonymousHandleExit;
+
+ RpcStatus = RpcBindingSetAuthInfoEx(
+ *phRpcAnonymous,
+ NULL,
+ RPC_C_AUTHN_LEVEL_NONE,
+ RPC_C_AUTHN_WINNT,
+ NULL,
+ 0,
+ &Qos );
+
+GetAnonymousHandleExit:
+
+ if ( (RpcStatus == RPC_S_OK) && bMatch )
+ pssrvreg->_hRpcAnonymous = *phRpcAnonymous;
+
+ if ( (RpcStatus != RPC_S_OK) && *phRpcAnonymous )
+ {
+ RpcBindingFree( phRpcAnonymous );
+ *phRpcAnonymous = 0;
+ }
+}
+
+#ifndef _CHICAGO_
+VOID CSrvRegList::DecHandleCount(
+ RPC_COOKIE hRpc
+)
+{
+ if ( hRpc == (RPC_COOKIE)NULL )
+ return;
+
+ // Protect from multiple updates
+ CStaticPortableLock lck(s_mxsSyncAccess);
+
+ // Search for first non-empty bucket that we have
+ SSrvRegistration *pssrvreg = (SSrvRegistration *) GetAt(0);
+
+ for (int i = 0; i < GetSize(); i++, pssrvreg++)
+ {
+ if (pssrvreg->_hRpc == hRpc)
+ {
+ if ( pssrvreg->_dwHandleCount > 0 )
+ pssrvreg->_dwHandleCount--;
+
+ if ( (pssrvreg->_dwHandleCount == 0) &&
+ (pssrvreg->_dwFlags == SRV_REG_INVALID) &&
+ (pssrvreg->_hRpc != 0) )
+ {
+ RpcBindingFree( &pssrvreg->_hRpc );
+ pssrvreg->_hRpc == NULL;
+
+ if ( pssrvreg->_hRpcAnonymous )
+ {
+ RpcBindingFree( &pssrvreg->_hRpcAnonymous );
+ pssrvreg->_hRpcAnonymous == NULL;
+ }
+ }
+ return;
+ }
+ }
+}
+#endif
diff --git a/private/ole32/dcomss/olescm/srvreg.hxx b/private/ole32/dcomss/olescm/srvreg.hxx
new file mode 100644
index 000000000..7bae8e58d
--- /dev/null
+++ b/private/ole32/dcomss/olescm/srvreg.hxx
@@ -0,0 +1,199 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: srvreg.hxx
+//
+// Contents: Classes used for keeping track of end points for a given
+// class.
+//
+// Classes: SClsSrvHandle
+//
+// History: 03-Jan-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __SRVREG_HXX__
+#define __SRVREG_HXX__
+
+// _CHICAGO_SCM : We need our own CScmArrayFValue to allocate in shared memory
+#include "scm_afv.h"
+#include <olesem.hxx>
+#include <port.hxx>
+
+// Constants for defining the default size of our array
+#define SRV_REG_LIST_DEF_SIZE 4
+#define SRV_REG_LIST_GROW 4
+
+#define SRV_REG_INVALID 0xbeef
+
+#ifndef _CHICAGO_
+typedef handle_t RPC_COOKIE;
+#else
+typedef WCHAR * RPC_COOKIE;
+#endif
+
+class CPortableRpcHandle;
+
+//+-------------------------------------------------------------------------
+//
+// Struct: SSrvRegistration
+//
+// Purpose: Entry in the array of end points
+//
+// History: 03-Jan-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+struct SSrvRegistration
+{
+ RPC_COOKIE _hRpc;
+ DWORD _dwFlags;
+ WCHAR * _pwszWinstaDesktop;
+
+#ifdef _CHICAGO_
+ ULONG _ulWnd;
+#else
+ PSID _psid;
+ DWORD _dwHandleCount;
+ OXID _oxid;
+ IPID _ipid;
+#endif
+ handle_t _hRpcAnonymous;
+
+ // the _fSurrogate is initialized in the Insert member function of
+ // CSrvRegList
+ BOOL _fSurrogate;
+
+ // Clean up entry in table.
+ void Free(void);
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSrvRegList
+//
+// Purpose: List of registered end points for a class
+//
+// Interface: CreatedOk - object initialized correctly
+// Insert - insert a new end point
+// Delete - delete a previous registration
+// GetHandle - get a handle to an end point.
+//
+// History: 03-Jan-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CSrvRegList : private CScmArrayFValue, public CScmAlloc
+{
+public:
+ CSrvRegList(void);
+
+ ~CSrvRegList(void);
+
+ BOOL CreatedOk(void);
+
+ DWORD Insert(IFSECURITY(PSID psid)
+ WCHAR *pwszWinstaDesktop,
+#ifdef DCOM
+ PHPROCESS phProcess,
+ OXID oxid,
+ IPID ipid,
+#else
+ WCHAR *pwszBindString,
+#endif
+ DWORD dwFlags);
+
+
+ BOOL GetHandle(IFSECURITY(PSID psid)
+ WCHAR * pwszWinstaDesktop,
+ CPortableRpcHandle &rh,
+ BOOL fSurrogate);
+
+ BOOL FindCompatibleSurrogate(IFSECURITY(PSID psid)
+ WCHAR* pwszWinstaDesktop,
+ CPortableRpcHandle &rh);
+
+ BOOL InUse(void);
+
+ BOOL VerifyHandle(RPC_COOKIE hRpc);
+
+ BOOL Delete(RPC_COOKIE hRpc);
+
+ static VOID EnableForcedShutdown(VOID);
+
+ VOID InvalidateHandle(RPC_COOKIE hRpc);
+
+ void GetAnonymousHandle(
+ CPortableRpcHandle &rh,
+ handle_t * phRpcAnonymous );
+
+#ifndef _CHICAGO_
+ void DecHandleCount(RPC_COOKIE hRpc);
+#endif
+
+private:
+ //
+ //
+
+ // To protect access to all of these lists
+ static CStaticPortableMutex s_mxsSyncAccess;
+ static BOOL s_fForcedScmShutdown;
+
+#ifdef _CHICAGO_
+ static CStaticPortableMutex s_mxsOnlyOne; // mutex semaphore
+ friend HRESULT StartSCM(VOID);
+#endif
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSrvRegList::CSrvRegList
+//
+// Synopsis: Create an empty array of end points for a class
+//
+// History: 03-Jan-93 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CSrvRegList::CSrvRegList()
+ : CScmArrayFValue(sizeof(SSrvRegistration))
+{
+ SetSize(SRV_REG_LIST_DEF_SIZE, SRV_REG_LIST_GROW);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSrvRegList::EnableForcedShutdown
+//
+// Synopsis: Enable the freeing of rpc bindings during final
+// scm shutdown.
+//
+// History: 26-Jan-95 BillMo Created
+//
+//--------------------------------------------------------------------------
+inline VOID CSrvRegList::EnableForcedShutdown(VOID)
+{
+ s_fForcedScmShutdown = TRUE;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSrvRegList::CreatedOk
+//
+// Synopsis: Return whether initial creation worked.
+//
+// History: 03-Jan-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CSrvRegList::CreatedOk(void)
+{
+ return GetSize() != 0;
+}
+
+#endif // __SRVREG_HXX__
diff --git a/private/ole32/dcomss/wrapper/daytona/makefile b/private/ole32/dcomss/wrapper/daytona/makefile
new file mode 100644
index 000000000..51f351a0e
--- /dev/null
+++ b/private/ole32/dcomss/wrapper/daytona/makefile
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS LINE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/dcomss/wrapper/daytona/rpcss.prf b/private/ole32/dcomss/wrapper/daytona/rpcss.prf
new file mode 100644
index 000000000..72eca3f94
--- /dev/null
+++ b/private/ole32/dcomss/wrapper/daytona/rpcss.prf
@@ -0,0 +1,279 @@
+?UnlockExclusive@CSharedLock@@QAEXXZ
+?LockExclusive@CSharedLock@@QAEXXZ
+?Hash@CIdTableElement@@UAEKXZ
+?Release@CReferencedObject@@UAEKXZ
+NdrServerCall2@4
+I_RpcBindingInqTransportType@8
+MIDL_user_free@4
+MIDL_user_allocate@4
+?CheckLocalCall@@YGXPAX@Z
+?Reference@CReferencedObject@@UAEXXZ
+?CopyDualStringArray@@YGJPAUtagDUALSTRINGARRAY@@PAPAU1@@Z
+?GetEntry@CWIPTable@@QAEJKKHPAUtagSTDOBJREF@@PAUtagOXID_INFO@@@Z
+GetWindowPropInterface@28
+?Hash@CBList@@AAEKPAX@Z
+?Lookup@CHashTable@@QAEPAVCTableElement@@AAVCTableKey@@@Z
+?Remove@CPList@@QAEPAVCPListElement@@PAV2@@Z
+??3@YAXPAX@Z
+?ReferenceProcess@@YGPAVCProcess@@PAXH@Z
+?Member@CBList@@QAEHPAX@Z
+?CheckLocalSecurity@@YGXPAXPAVCProcess@@@Z
+?AddEntry@CWIPTable@@QAEJKPAUtagSTDOBJREF@@PAUtagOXID_INFO@@PAK@Z
+RegisterWindowPropInterface@24
+?Insert@CPList@@QAEXPAVCPListElement@@@Z
+?Compare@CIdTableElement@@UAEHAAVCTableKey@@@Z
+?Hash@CIdKey@@UAEKXZ
+?PeekMin@CPList@@QAEHAAVCTime@@@Z
+?RemoveMatching@CTableElement@@IAEPAV1@PAV1@PAPAV1@@Z
+?Remove@CHashTable@@QAEXPAVCTableElement@@@Z
+??2@YAPAXI@Z
+?ScmRotHash@@YGKPAEKK@Z
+?MaybeRemoveMin@CPList@@QAEPAVCListElement@@AAVCTime@@@Z
+?GetRotEntry@CScmRot@@AAEPAVCScmRotEntry@@PAVCToken@@PAGPAU_MnkEqBuf@@@Z
+?Add@CHashTable@@QAEXPAVCTableElement@@@Z
+??_ECServerOid@@UAEPAXI@Z
+??1CServerOid@@UAE@XZ
+?CalcIfdSize@@YGIPAUtagInterfaceData@@@Z
+?Release@CServerOid@@UAEKXZ
+?UnlockShared@CSharedLock@@QAEXXZ
+?LockShared@CSharedLock@@QAEXXZ
+?GetEntryFromScmReg@@YGPAVCScmRotEntry@@PAU_SCMREGKEY@@@Z
+??0CScmRotEntry@@QAE@KPAU_MnkEqBuf@@PAU_FILETIME@@KPAVCToken@@PAGPAUtagInterfaceData@@4@Z
+?SetAt@CScmHashTable@@QAEXKPAVCScmHashEntry@@@Z
+?Register@CScmRot@@QAEJPAVCToken@@PAGPAU_MnkEqBuf@@PAUtagInterfaceData@@3PAU_FILETIME@@K1PAU_SCMREGKEY@@@Z
+?SizeMnkEqBufForRotEntry@@YGIPAU_MnkEqBuf@@@Z
+IrotRegister@44
+?RundownOids@CServerOxid@@QAEXGQA_KQAE@Z
+?MaybeRemoveMatchingOxid@CServerOidPList@@QAEPAVCServerOid@@AAVCTime@@PAV2@@Z
+_ServerAllocateOIDs@24
+?AllocateId@@YG_KJ@Z
+?AllocateAndCopy@@YGPAUtagInterfaceData@@PAU1@@Z
+?Release@CToken@@UAEKXZ
+IrotRevoke@24
+??_ECScmRotEntry@@UAEPAXI@Z
+?Revoke@CScmRot@@QAEJPAU_SCMREGKEY@@HPAPAUtagInterfaceData@@1@Z
+?RemoveEntry@CScmHashTable@@QAEHKPAVCScmHashEntry@@@Z
+??1CScmHashEntry@@UAE@XZ
+?Insert@CBList@@QAEJPAX@Z
+?CheckForRundowns@CServerSetTable@@QAE_KXZ
+_alloca_probe
+RpcBindingSetObject@8
+?Search@CSkipList@@QAEPAXPBX@Z
+?InUse@CSrvRegList@@QAEHXZ
+?Request@COleStaticMutexSem@@QAEXXZ
+?SkipListCompareClassIDs@@YGHPAX0@Z
+?_Search@CSkipList@@AAEPAXPBXPAPAVCSkipListEntry@@@Z
+?Release@CClassData@@QAEXXZ
+?FillUpdateArray@CSkipList@@AAEPAVCSkipListEntry@@PBXPAPAV2@@Z
+GetProtseq@4
+wcscpy
+wcslen
+I_RpcBindingSetAsync@8
+RpcBindingFromStringBindingW@8
+?GetBindingHandle@CProcess@@QAEPAXXZ
+?GetBinding@@YGPAXPAG@Z
+?SkipListCompareStringIDs@@YGHPAX0@Z
+?Compare@CStringID@@QBEHABV1@@Z
+?Hash@CId2Key@@UAEKXZ
+?Remove@CBList@@QAEPAXPAX@Z
+RpcImpersonateClient@4
+?GetClassData@CClassCacheList@@QAEJABU_GUID@@PAXPAPAVCClassData@@HH@Z
+NdrClientCall2
+?ReleaseProcess@@YGXPAVCProcess@@@Z
+_AllocateReservedIds@12
+_ServerAllocateOXIDAndOIDs@40
+_Connect@72
+?Insert@CSkipList@@QAEPAXPAX@Z
+??0CClassData@@QAE@ABVCClassID@@PAGPBG1H111HHPBU_SECURITY_DESCRIPTOR@@HAAJ@Z
+GetProtseqId@4
+?SetSize@CScmArrayFValue@@QAEHHH@Z
+?LookupOrCreateToken@@YGJPAXHPAPAVCToken@@@Z
+?ReadClassEntry@CClassRegistryReader@@AAEJPAUHKEY__@@HH@Z
+??0CScmArrayFValue@@QAE@I@Z
+??0CProcess@@QAE@PAVCToken@@AAJ@Z
+??0CPortableServerEvent@@QAE@PAVCClassData@@@Z
+?SetEndPoints@CClassCacheList@@QAEJPAX0PAGPAU_RegInput@@PAU_RegOutput@@@Z
+?StartListeningIfNecessary@@YGJXZ
+?AddClassReg@CProcess@@QAEXU_GUID@@K@Z
+ServerRegisterClsid@24
+?GetSkLevel@@YGHH@Z
+??1CClassRegistryReader@@QAE@XZ
+??0CClassRegistryReader@@QAE@XZ
+?wStringFromUUID@@YGJABU_GUID@@PAG@Z
+?ReadSingleClass@CClassRegistryReader@@QAEJABU_GUID@@HH@Z
+?InitInner@CClassRegistryReader@@AAEXXZ
+?AddOxid@CProcess@@QAEJPAVCServerOxid@@@Z
+?wStringFromGUID2@@YGHABU_GUID@@PAGH@Z
+??2@YAPAXII@Z
+wcschr
+?CompressStringArray@@YGPAUtagDUALSTRINGARRAY@@PAU1@@Z
+RegisterAuthInfoIfNecessary@0
+?Insert@CSrvRegList@@QAEKPAXPAG0_KU_GUID@@K@Z
+RpcRevertToSelfEx@4
+?ProcessBindings@CProcess@@QAEJPAUtagDUALSTRINGARRAY@@0@Z
+?NewClassData@CClassRegistryReader@@QAEPAVCClassData@@AAJ@Z
+?QueryStripRegValue@@YGJPAUHKEY__@@PBGPAGPAJ@Z
+??0CStringID@@QAE@PBGAAJ@Z
+?Add@CLocSrvList@@QAEPAVCLocalServer@@PBGAAJ@Z
+?Hash@CId2TableElement@@UAEKXZ
+?Release@CClientOxid@@UAEKXZ
+?RemoveClassReg@CProcess@@QAEXU_GUID@@K@Z
+?Free@SSrvRegistration@@QAEXXZ
+ServerRevokeClsid@16
+RpcBindingFree@4
+??1CSrvRegList@@QAE@XZ
+??1CScmArrayFValue@@QAE@XZ
+??_ECClassData@@UAEPAXI@Z
+?StopServer@CClassCacheList@@QAEXABU_GUID@@PAXK@Z
+?Remove@CSkipList@@QAEPAXPAX@Z
+?Release@CLocalServer@@QAEKAAVCLocSrvList@@@Z
+??_ECLocalServer@@UAEPAXI@Z
+PHPROCESS_rundown@4
+?ProcessRelease@CServerOxid@@IAEXXZ
+?RemoveOxid@CProcess@@QAEHPAVCServerOxid@@@Z
+?Rundown@CProcess@@QAEXXZ
+_ServerFreeOXIDAndOIDs@24
+?Delete@CSrvRegList@@QAEHPAX@Z
+IrotGetTimeOfLastChange@24
+?GetTimeOfLastChange@CScmRot@@QAEJPAVCToken@@PAGPAU_MnkEqBuf@@PAU_FILETIME@@@Z
+?IsEqual@CScmRotEntry@@UAEHPAXI@Z
+?ResolveClientOXID@@YGKPAX0PA_KPAUtagDUALSTRINGARRAY@@JGPAUtagOXID_INFO@@1@Z
+RpcRevertToSelf@0
+?DecHandleCount@CSrvRegList@@QAEXPAX@Z
+?DecHandleCount@CClassData@@QAEXAAVCPortableRpcHandle@@@Z
+?FindMatchingProtseq@@YGPAGGPAG@Z
+?Hash@CMidKey@@UAEKXZ
+?Compare@CMid@@UAEHAAVCTableKey@@@Z
+?GetInfo@CClientOxid@@QAEJHPAUtagOXID_INFO@@@Z
+wcscat
+?GetServer@CClassData@@QAEJPAU_ACTIVATION_PARAMS@@AAVCPortableRpcHandle@@AAH2@Z
+?GetHandle@CSrvRegList@@QAEHPAXPAGAAVCPortableRpcHandle@@@Z
+?ActivateAtStorage@CClassData@@QAEHPAJPAU_ACTIVATION_PARAMS@@@Z
+?ResolveORInfo@@YGJPAU_ACTIVATION_PARAMS@@H@Z
+?GetStringBinding@@YGPAUtagDUALSTRINGARRAY@@PAG0@Z
+ObjectServerCreateInstance@40
+SCMCreateInstance@56
+?Activation@@YGJPAU_ACTIVATION_PARAMS@@@Z
+??0CPortableServerLock@@QAE@PAVCClassData@@@Z
+?CkIfCallAllowed@CClassData@@AAEJPAU_ACTIVATION_PARAMS@@@Z
+?StartServer@CLocalServer@@QAEHAAU_GUID@@PAGPAVCToken@@1PAPAX11@Z
+?GetLocalBindings@CProcess@@QAEPAUtagDUALSTRINGARRAY@@XZ
+?IdentifyAccess@CAccessInfo@@QAEPAXHKK@Z
+?GetInfo@CServerOxid@@QAEJPAUtagOXID_INFO@@H@Z
+_ClientResolveOXID@28
+?CheckForAccess@@YGJPAVCToken@@PBU_SECURITY_DESCRIPTOR@@@Z
+??1CAccessInfo@@QAE@XZ
+?UpdateInfo@CClientOxid@@QAEJPAUtagOXID_INFO@@@Z
+?Compare@CId2TableElement@@UAEHAAVCTableKey@@@Z
+?Hash@CId3TableElement@@UAEKXZ
+?Hash@CId3Key@@UAEKXZ
+_BulkUpdateOIDs@44
+?AddOid@CProcess@@QAEJPAVCClientOid@@@Z
+?Reference@CClientOxid@@UAEXXZ
+?RegisterObject@CClientSet@@QAEJPAVCClientOid@@@Z
+_ComplexPing@32
+?Revert@CToken@@QAEXXZ
+?Impersonate@CToken@@QAEXXZ
+?PingServer@CClientSet@@QAEJXZ
+?Reference@CServerOid@@UAEXXZ
+?AddObject@CServerSet@@QAEJAA_K@Z
+?Lookup@CServerSetTable@@QAEPAVCServerSet@@_K@Z
+??1CClientOid@@UAE@XZ
+??_GCClientOid@@UAEPAXI@Z
+?RemoveObject@CServerSet@@QAEXAA_K@Z
+?RemoveOid@CProcess@@QAEPAVCClientOid@@PAV2@@Z
+?Compare@CId3TableElement@@UAEHAAVCTableKey@@@Z
+IrotNoteChangeTime@16
+?NoteChangeTime@CScmRot@@QAEJPAU_SCMREGKEY@@PAU_FILETIME@@@Z
+?FreeBinding@CProcess@@AAEXPAX@Z
+?AllocateCallId@@YGHAAU_GUID@@@Z
+?RundownOids@CProcess@@QAEXGQA_KU_GUID@@QAE@Z
+?AllocateBinding@CProcess@@AAEPAXXZ
+?EnsureRealBinding@CProcess@@AAEXXZ
+RawRundownOid@28
+?FreeCallId@@YGXH@Z
+?Grow@CWIPTable@@AAEKXZ
+??_ECClientOxid@@UAEPAXI@Z
+?KeepAlive@CServerOid@@QAEXXZ
+?Allocate@CServerSetTable@@QAEPAVCServerSet@@GPAXHAA_K@Z
+??_ECClientSet@@UAEPAXI@Z
+?ValidateObjects@CServerSet@@AAEHH@Z
+?CreateAndSetProcessToken@@YGHPAU_PROCESS_INFORMATION@@PAX1@Z
+ObjectExporterTaskThread@4
+UuidCreate@4
+??1CProcess@@UAE@XZ
+??1CServerOxid@@UAE@XZ
+??_ECProcess@@UAEPAXI@Z
+??_ECServerOxid@@UAEPAXI@Z
+?IsRunning@CScmRot@@QAEJPAVCToken@@PAGPAU_MnkEqBuf@@@Z
+IrotIsRunning@20
+?GetObjectW@CScmRot@@QAEJPAVCToken@@PAGKPAU_MnkEqBuf@@PAU_SCMREGKEY@@PAPAUtagInterfaceData@@@Z
+IrotGetObject@32
+?Init@COleStaticMutexSem@@QAEXXZ
+?InitTbl@CScmPatternTbl@@QAEJPAK@Z
+?IsValidPattern@CScmPatternTbl@@AAEHPAGJ@Z
+?InitTbl@CScmFileExtTbl@@QAEJPAK@Z
+?ParseEntry@CScmPatternTbl@@AAEJPAGJPAUSPatternEntry@@ABU_GUID@@@Z
+?GetSharedMem@CScmShrdTbl@@AAEJK@Z
+UpdateShrdTbls@8
+?SkipToNext@CScmPatternTbl@@AAEPAGPAG@Z
+?CopyTbl@CScmFileExtTbl@@QAEPAEPAE@Z
+?Commit@CSharedMemoryBlock@@QAEJK@Z
+wcstol
+?CopyTbl@CScmPatternTbl@@QAEPAEPAE@Z
+?UpdateWithLock@CScmShrdTbl@@QAEJXZ
+?Add@CScmFileExtTbl@@AAEJPBGPAU_GUID@@@Z
+?HexStringToDword@@YGHAAPBGAAKHG@Z
+?ToHex@CScmPatternTbl@@AAEEPAG@Z
+?Add@CScmPSClsidTbl@@AAEHABU_GUID@@0@Z
+GUIDFromString@8
+?CopyTbl@CScmPSClsidTbl@@QAEPAEPAE@Z
+RpcBindingVectorFree@4
+main
+StartEndpointMapper@0
+EnumerateSecurityPackagesW@8
+ObjectExporterWorkerThread@4
+??0CScmShrdTbl@@QAE@AAJ@Z
+?InitHeaps@@YGJXZ
+InitializeSCMAfterListen@0
+_setdefaultprecision
+??0CSharedLock@@QAE@AAJ@Z
+RpcBindingToStringBindingW@8
+_onexit
+RpcStringFreeW@4
+?Init@CSmMutex@@QAEJPAGH@Z
+??0CScmRotHintTable@@QAE@PAG@Z
+??0CHashTable@@QAE@AAJI@Z
+UseProtseqIfNecessary@4
+StartObjectExporter@0
+RpcServerInqBindings@4
+RpcStringBindingParseW@24
+??0CClassCacheList@@QAE@AAJ@Z
+?PrivHeapAlloc@@YGPAXPAXKK@Z
+IsLocal@4
+?ReadRemoteActivationKeys@CClassCacheList@@QAEXXZ
+?GetRegistrySecDesc@@YGJPAUHKEY__@@PAGPAPAU_SECURITY_DESCRIPTOR@@@Z
+InitializeSCM@0
+RpcServerUseProtseqEpExW@20
+InitializeIpPortManager@0
+?CreateSharedFileMapping@@YGPAXPAGKKPAX1KPAPAXPAH@Z
+_controlfp
+?ServiceMain@@YGXKQAPAG@Z
+I_RpcServerRegisterForwardFunction@4
+?ComputeSecurity@@YGXXZ
+RpcServerRegisterIf@12
+?InitSCMRegistry@@YGJXZ
+?Init@CSharedMemoryBlock@@QAEJPAGKKPAX1H@Z
+RpcMgmtIsServerListening@4
+UpdateState@4
+FreeContextBuffer@4
+RpcServerRegisterAuthInfoW@16
+?Hash@CMid@@UAEKXZ
+??0CSkipList@@QAE@P6GHPAX0@ZP6GX0@ZHH0HAAJ@Z
+InitializeEndpointManager@0
+RpcServerListen@12
+atexit
+_setargv
+?InitScmRot@@YGJXZ
+mainCRTStartup
+_initterm
diff --git a/private/ole32/dcomss/wrapper/daytona/sources b/private/ole32/dcomss/wrapper/daytona/sources
new file mode 100644
index 000000000..d504e56da
--- /dev/null
+++ b/private/ole32/dcomss/wrapper/daytona/sources
@@ -0,0 +1,49 @@
+!IF 0
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Revision History:
+
+!ENDIF
+
+!include ..\sources.inc
+
+TARGETPATH=.
+LINKLIBS=$(BASEDIR)\private\dcomidl\obj\*\dcomidl.lib \
+ $(BASEDIR)\public\sdk\lib\*\epmap.lib \
+ ..\..\lib\daytona\*\objex.lib \
+ ..\..\..\common\daytona\obj\*\common.lib \
+ ..\..\..\com\inc\daytona\obj\*\inc.lib \
+ ..\..\..\com\rot\daytona\obj\*\rot.lib \
+ ..\..\..\ilib\daytona\obj\*\uuid.lib \
+ ..\..\lib\daytona\*\olescm.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib \
+ $(BASEDIR)\public\sdk\lib\*\userenv.lib \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib
+
+INCLUDES=..\..; \
+ ..\..\..\ih
+
+RPCENV=-DNTENV -DWIN32RPC -DNTWIN32RPC
+C_DEFINES=$(RPCENV) -DUNICODE
+
+SOURCES= \
+ ..\dcomss.rc \
+ ..\epts.c \
+ ..\start.cxx
+
+NTPROFILEINPUT=yes
+
diff --git a/private/ole32/dcomss/wrapper/dcomss.rc b/private/ole32/dcomss/wrapper/dcomss.rc
new file mode 100644
index 000000000..057ec2df8
--- /dev/null
+++ b/private/ole32/dcomss/wrapper/dcomss.rc
@@ -0,0 +1,10 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Distribute COM Services"
+#define VER_INTERNALNAME_STR "dcomss.exe"
+#define VER_ORIGINALFILENAME_STR "dcomss.exe"
+
+#include "common.ver"
diff --git a/private/ole32/dcomss/wrapper/dirs b/private/ole32/dcomss/wrapper/dirs
new file mode 100644
index 000000000..e6d458c86
--- /dev/null
+++ b/private/ole32/dcomss/wrapper/dirs
@@ -0,0 +1,28 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=
+
+OPTIONAL_DIRS= \
+ \
+ daytona
+
diff --git a/private/ole32/dcomss/wrapper/epts.c b/private/ole32/dcomss/wrapper/epts.c
new file mode 100644
index 000000000..f63281e65
--- /dev/null
+++ b/private/ole32/dcomss/wrapper/epts.c
@@ -0,0 +1,740 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Epts.c
+
+Abstract:
+
+ Common code to listen to endpoints in the DCOM service.
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 6/16/1995 Bits 'n pieces
+
+--*/
+
+#include <dcomss.h>
+#include <winsvc.h>
+#include <winsock.h>
+#include <wsipx.h>
+#include <nspapi.h>
+
+// Globals
+
+BOOL gfDelayedAdvertiseSaps = FALSE;
+
+typedef enum
+ {
+ SapStateUnknown,
+ SapStateNoServices,
+ SapStateEnabled
+ } SAP_STATE;
+
+SAP_STATE SapState = SapStateUnknown;
+
+// Prototypes
+
+void AdvertiseNameWithSap(BOOL fServiceCheck);
+
+//
+// The index is the protseq tower id.
+// BUGBUG - this info should be read from the registry.
+//
+
+PROTSEQ_INFO
+gaProtseqInfo[] =
+ {
+ /* 0x00 */ { STOPPED, 0, 0 },
+ /* 0x01 */ { STOPPED, 0, 0 },
+ /* 0x02 */ { STOPPED, 0, 0 },
+ /* 0x03 */ { STOPPED, 0, 0 },
+ /* 0x04 */ { STOPPED, L"ncacn_dnet_dsp", L"#69" },
+ /* 0x05 */ { STOPPED, 0, 0 },
+ /* 0x06 */ { STOPPED, 0, 0 },
+ /* 0x07 */ { STOPPED, L"ncacn_ip_tcp", L"135" },
+ /* 0x08 */ { STOPPED, L"ncadg_ip_udp", L"135" },
+ /* 0x09 */ { STOPPED, L"ncacn_nb_tcp", L"135" },
+ /* 0x0a */ { STOPPED, 0, 0 },
+ /* 0x0b */ { STOPPED, 0, 0 },
+ /* 0x0c */ { STOPPED, L"ncacn_spx", L"34280" },
+ /* 0x0d */ { STOPPED, L"ncacn_nb_ipx", L"135" },
+ /* 0x0e */ { STOPPED, L"ncadg_ipx", L"34280" },
+ /* 0x0f */ { STOPPED, L"ncacn_np", L"\\pipe\\epmapper" },
+ /* 0x10 */ { STOPPED, L"ncalrpc", L"epmapper" },
+ /* 0x11 */ { STOPPED, 0, 0 },
+ /* 0x12 */ { STOPPED, 0, 0 },
+ /* 0x13 */ { STOPPED, L"ncacn_nb_nb", L"135" },
+ /* 0x14 */ { STOPPED, 0, 0 },
+ /* 0x15 */ { STOPPED, 0, 0 }, // was ncacn_nb_xns - unsupported.
+ /* 0x16 */ { STOPPED, L"ncacn_at_dsp", L"Endpoint Mapper" },
+ /* 0x17 */ { STOPPED, L"ncadg_at_ddp", L"Endpoint Mapper" },
+ /* 0x18 */ { STOPPED, 0, 0 },
+ /* 0x19 */ { STOPPED, 0, 0 },
+ /* 0x1A */ { STOPPED, L"ncacn_vns_spp", L"385"}
+ };
+
+#define PROTSEQ_IDS (sizeof(gaProtseqInfo)/sizeof(PROTSEQ_INFO))
+
+#define ID_LPC (0x10)
+#define ID_IPX (0x0E)
+#define ID_SPX (0x0C)
+
+
+RPC_STATUS
+UseProtseqIfNecessary(
+ IN USHORT id
+ )
+/*++
+
+Routine Description:
+
+ Listens to the well known RPC endpoint mapper endpoint
+ for the protseq. Returns very quickly if the process
+ is already listening to the protseq.
+
+Arguments:
+
+ id - the tower id of protseq. See GetProtseqId() if you don't
+ already have this value.
+
+Return Value:
+
+ RPC_S_OK - no errors occured.
+ RPC_S_OUT_OF_RESOURCES - when we're unable to setup security for the endpoint.
+ RPC_S_INVALID_RPC_PROTSEQ - if id is unknown/invalid.
+
+ Any error from RpcServerUseProtseqEp.
+
+--*/
+{
+ RPC_STATUS status = RPC_S_OK;
+ SECURITY_DESCRIPTOR sd, *psd;
+ RPC_POLICY Policy;
+
+ Policy.Length = sizeof(RPC_POLICY);
+ Policy.EndpointFlags = 0;
+ Policy.NICFlags = RPC_C_BIND_TO_ALL_NICS;
+
+ ASSERT(id);
+
+ if (id == 0 || id >= PROTSEQ_IDS)
+ {
+ ASSERT(0);
+ return(RPC_S_INVALID_RPC_PROTSEQ);
+ }
+
+ if (gaProtseqInfo[id].state == STARTED)
+ {
+ return(RPC_S_OK);
+ }
+
+ if (id == ID_LPC)
+ {
+ // ncalrpc needs a security descriptor.
+
+ psd = &sd;
+
+ InitializeSecurityDescriptor(
+ psd,
+ SECURITY_DESCRIPTOR_REVISION
+ );
+
+ if ( FALSE == SetSecurityDescriptorDacl (
+ psd,
+ TRUE, // Dacl present
+ NULL, // NULL Dacl
+ FALSE // Not defaulted
+ ) )
+ {
+ status = RPC_S_OUT_OF_RESOURCES;
+ }
+ }
+ else
+ {
+ psd = 0;
+ }
+
+ if (status == RPC_S_OK )
+ {
+ status = RpcServerUseProtseqEpEx(gaProtseqInfo[id].pwstrProtseq,
+ RPC_C_PROTSEQ_MAX_REQS_DEFAULT + 1,
+ gaProtseqInfo[id].pwstrEndpoint,
+ psd,
+ &Policy);
+
+ // No locking is done here, the RPC runtime may return duplicate
+ // endpoint if two threads call this at the same time.
+ if (status == RPC_S_DUPLICATE_ENDPOINT)
+ {
+ ASSERT(gaProtseqInfo[id].state == STARTED);
+ status = RPC_S_OK;
+ }
+
+#ifdef DEBUGRPC
+ if (status != RPC_S_OK)
+ {
+ DbgPrint("DCOMSS: Unable to listen to %S\n", gaProtseqInfo[id].pwstrProtseq);
+ }
+#endif
+
+ if (status == RPC_S_OK)
+ {
+ gaProtseqInfo[id].state = STARTED;
+
+ if (id == ID_IPX || id == ID_SPX )
+ {
+ AdvertiseNameWithSap(TRUE);
+ }
+ }
+ }
+
+ return(status);
+}
+
+
+PWSTR
+GetProtseq(
+ IN USHORT ProtseqId
+ )
+/*++
+
+Routine Description:
+
+ Returns the unicode protseq give the protseqs tower id.
+
+Arguments:
+
+ ProtseqId - Tower id of the protseq in question.
+
+Return Value:
+
+ NULL if the id is invalid.
+
+ non-NULL if the id is valid - note the pointer doesn't need to be freed.
+
+--*/
+
+{
+ ASSERT(ProtseqId);
+
+ if (ProtseqId < PROTSEQ_IDS)
+ {
+ return(gaProtseqInfo[ProtseqId].pwstrProtseq);
+ }
+ return(0);
+}
+
+
+PWSTR
+GetEndpoint(
+ IN USHORT ProtseqId
+ )
+/*++
+
+Routine Description:
+
+ Returns the well known endpoint associated with the protseq.
+
+Arguments:
+
+ ProtseqId - the id (See GetProtseqId()) of the protseq in question.
+
+Return Value:
+
+ 0 - Unknown/invalid id.
+
+ !0 - The endpoint associated with the protseq.
+ note: should not be freed.
+
+--*/
+{
+ ASSERT(ProtseqId);
+
+ if (ProtseqId < PROTSEQ_IDS)
+ {
+ return(gaProtseqInfo[ProtseqId].pwstrEndpoint);
+ }
+ return(0);
+}
+
+
+USHORT
+GetProtseqId(
+ IN PWSTR Protseq
+ )
+/*++
+
+Routine Description:
+
+ Returns the tower id for a protseq.
+
+ This could be changed to a faster search, but remember that
+ eventually the table will NOT be static. (ie. we can't just
+ create a perfect hash based on the static table).
+
+Arguments:
+
+ Protseq - a unicode protseq to lookup. It is assumed
+ to be non-null.
+
+Return Value:
+
+ 0 - unknown/invalid protseq
+ non-zero - the id.
+
+--*/
+{
+ int i;
+ ASSERT(Protseq);
+
+ for(i = 1; i < PROTSEQ_IDS; i++)
+ {
+ if ( 0 != gaProtseqInfo[i].pwstrProtseq
+ && 0 == lstrcmpW(gaProtseqInfo[i].pwstrProtseq, Protseq))
+ {
+ return(i);
+ }
+ }
+ return(0);
+}
+
+
+USHORT
+GetProtseqIdAnsi(
+ IN PSTR pstrProtseq
+ )
+/*++
+
+Routine Description:
+
+ Returns the tower id for a protseq.
+
+ This could be changed to a faster search, but remember that
+ eventually the table will NOT be static. (ie. we can't just
+ create a perfect hash based on the static table).
+
+Arguments:
+
+ Protseq - an ansi (8 bit char) protseq to lookup. It is assumed
+ to be non-null.
+
+Return Value:
+
+ 0 - unknown/invalid protseq
+ non-zero - the id.
+
+--*/
+{
+ int i;
+ ASSERT(pstrProtseq);
+
+ for(i = 1; i < PROTSEQ_IDS; i++)
+ {
+ if (0 != gaProtseqInfo[i].pwstrProtseq)
+ {
+ PWSTR pwstrProtseq = gaProtseqInfo[i].pwstrProtseq;
+ PSTR pstrT = pstrProtseq;
+
+ while(*pstrT && *pwstrProtseq && *pstrT == *pwstrProtseq)
+ {
+ pstrT++;
+ pwstrProtseq++;
+ }
+ if (*pstrT == *pwstrProtseq)
+ {
+ return(i);
+ }
+ }
+ }
+ return(0);
+}
+
+
+RPC_STATUS
+InitializeEndpointManager(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Called when the dcom service starts.
+
+ BUGBUG: Should read the protseqs, tower IDs and endpoints from the registry.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ RPC_S_OUT_OF_MEMORY - if needed
+
+ RPC_S_OUT_OF_RESOURCES - usually on registry failures.
+
+--*/
+{
+ return(RPC_S_OK);
+}
+
+
+BOOL
+IsLocal(
+ IN USHORT ProtseqId
+ )
+/*++
+
+Routine Description:
+
+ Determines if the protseq id is local-only. (ncalrpc)
+
+Arguments:
+
+ ProtseqId - The id of the protseq in question.
+
+Return Value:
+
+ TRUE - if the protseq id is local-only
+ FALSE - if the protseq id invalid or available remotely.
+
+--*/
+{
+ return(ProtseqId == ID_LPC);
+}
+
+
+RPC_STATUS
+DelayedUseProtseq(
+ IN USHORT id
+ )
+/*++
+
+Routine Description:
+
+ If the protseq is not being used its state is changed
+ so that a callto CompleteDelayedUseProtseqs() will actually
+ cause the server to listen to the protseq.
+
+ This is called when an RPC server registers an dynamic
+ endpoint on this protocol.
+
+Arguments:
+
+ id - the id of the protseq you wish to listen to.
+
+Return Value:
+
+ 0 - normally
+
+ RPC_S_INVALID_RPC_PROTSEQ - if id is invalid.
+
+--*/
+{
+ // For IPX and SPX
+ if (id == ID_IPX || id == ID_SPX)
+ {
+ gfDelayedAdvertiseSaps = TRUE;
+ }
+
+ if (id < PROTSEQ_IDS)
+ {
+ if (gaProtseqInfo[id].pwstrProtseq != 0)
+ {
+ if (gaProtseqInfo[id].state == STOPPED)
+ gaProtseqInfo[id].state = START;
+ return(RPC_S_OK);
+ }
+
+ }
+ return(RPC_S_INVALID_RPC_PROTSEQ);
+}
+
+
+VOID
+CompleteDelayedUseProtseqs(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Start listening to any protseqs previously passed
+ to DelayedUseProtseq(). No errors are returned,
+ but informationals are printed on debug builds.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+{
+ USHORT i;
+
+ for(i = 1; i < PROTSEQ_IDS; i++)
+ {
+ if (START == gaProtseqInfo[i].state)
+ {
+ RPC_STATUS status = UseProtseqIfNecessary(i);
+#ifdef DEBUGRPC
+ if (RPC_S_OK == status)
+ ASSERT(gaProtseqInfo[i].state == STARTED);
+#endif
+ }
+ }
+
+ if (gfDelayedAdvertiseSaps)
+ {
+ gfDelayedAdvertiseSaps = FALSE;
+ AdvertiseNameWithSap(FALSE);
+ }
+}
+
+
+RPC_STATUS
+ServiceInstalled(
+ PWSTR ServiceName
+ )
+/*++
+
+Routine Description:
+
+ Tests if a service is installed.
+
+Arguments:
+
+ ServiceName - The unicode name (short or long) of the service
+ to check.
+
+Return Value:
+
+ 0 - service installed
+ ERROR_SERVICE_DOES_NOT_EXIST - service not installed
+ other - parameter or resource problem
+
+--*/
+{
+ SC_HANDLE ScHandle;
+ SC_HANDLE ServiceHandle;
+
+ ScHandle = OpenSCManagerW(0, 0, GENERIC_READ);
+
+ if (ScHandle == 0)
+ {
+ return(GetLastError());
+ }
+
+ ServiceHandle = OpenService(ScHandle, ServiceName, GENERIC_READ);
+
+ if (ServiceHandle == 0)
+ {
+ #if DBG
+ if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
+ {
+ DbgPrint("OR: Failed %d opening the %S service\n",
+ GetLastError(), ServiceName);
+ }
+ #endif
+
+ CloseServiceHandle(ScHandle);
+ return(GetLastError());
+ }
+
+ // Service installed
+
+ CloseServiceHandle(ScHandle);
+ CloseServiceHandle(ServiceHandle);
+
+ return(RPC_S_OK);
+}
+
+
+
+const GUID RPC_SAP_SERVICE_TYPE = { 0x000b0640, 0, 0, { 0xC0,0,0,0,0,0,0,0x46 } };
+
+void
+AdvertiseNameWithSap(
+ BOOL fServiceCheck
+ )
+/*++
+
+Routine Description:
+
+ Is this server is listening to IPX/SPX then, depending
+ on what services are enabled on this machine, this
+ function will enable SAPs on this machines address. This
+ allows RPC clients to resolve the pretty name of this
+ server to a raw ipx address.
+
+
+Arguments:
+
+ fServiceCheck - If true, this function will only advertise
+ with SAP if various services are installed. If false,
+ this will always turn on SAP.
+
+Return Value:
+
+ None
+
+--*/
+{
+ DWORD status;
+ DWORD ignore;
+
+ // Service paramaters
+ NT_PRODUCT_TYPE type;
+
+ // GetComputerName parameters
+ WCHAR buffer[MAX_COMPUTERNAME_LENGTH + 1];
+
+ // winsock (socket, bind, getsockname) parameters
+ SOCKADDR_IPX ipxaddr;
+ SOCKET s;
+ int err;
+ int size;
+
+ // SetService params
+ SERVICE_INFOW info;
+ SERVICE_ADDRESSES addresses;
+
+ if ( SapState == SapStateEnabled
+ || (fServiceCheck && (SapState == SapStateNoServices)) )
+ {
+ return;
+ }
+
+ if (fServiceCheck)
+ {
+ // On servers, advertise if the NwSapAgent or NWCWorkstation
+ // services are installed. On workstations, advertise if
+ // NwSapAgent service is installed.
+
+ type = NtProductWinNt;
+ RtlGetNtProductType(&type);
+
+ status = ERROR_SERVICE_DOES_NOT_EXIST;
+
+ if (type != NtProductWinNt)
+ {
+ // Server platform, try NWCWorkstation
+ status = ServiceInstalled(L"NWCWorkstation");
+ }
+
+ if (status == ERROR_SERVICE_DOES_NOT_EXIST)
+ {
+ status = ServiceInstalled(L"NwSapAgent");
+ }
+
+ if (status == ERROR_SERVICE_DOES_NOT_EXIST)
+ {
+ SapState = SapStateNoServices;
+ return;
+ }
+ }
+
+ // Get this server's name
+ ignore = MAX_COMPUTERNAME_LENGTH + 1;
+ if (!GetComputerNameW(buffer, &ignore))
+ {
+ return;
+ }
+
+ // Get this server's IPX address..blech..
+ s = socket( AF_IPX, SOCK_DGRAM, NSPROTO_IPX );
+ if (s != -1)
+ {
+ size = sizeof(ipxaddr);
+
+ memset(&ipxaddr, 0, sizeof(ipxaddr));
+ ipxaddr.sa_family = AF_IPX;
+
+ err = bind(s, (struct sockaddr *)&ipxaddr, sizeof(ipxaddr));
+ if (err == 0)
+ {
+ err = getsockname(s, (struct sockaddr *)&ipxaddr, &size);
+ }
+ }
+ else
+ {
+ err = -1;
+ }
+
+ if (err != 0)
+ {
+ #if DBG
+ DbgPrint("OR: socket/gesockname failed %d, aborting SAP setup\n",
+ GetLastError());
+ #endif
+ return;
+ }
+
+ if (s != -1)
+ {
+ closesocket(s);
+ }
+
+ // We'll register only for the endpoint mapper port. The port
+ // value is not required but should be the same to avoid
+ // confusing routers keeping track of SAPs...
+
+ ipxaddr.sa_socket = 34280;
+
+ // Fill in the service info structure.
+ info.lpServiceType = (GUID *)&RPC_SAP_SERVICE_TYPE;
+ info.lpServiceName = buffer;
+ info.lpComment = L"RPC Services";
+ info.lpLocale = L"";
+ info.dwDisplayHint = 0;
+ info.dwVersion = 0;
+ info.dwTime = 0;
+ info.lpMachineName = buffer;
+ info.lpServiceAddress = &addresses;
+ info.ServiceSpecificInfo.cbSize = 0;
+
+ // Fill in the service addresses structure.
+ addresses.dwAddressCount = 1;
+ addresses.Addresses[0].dwAddressType = AF_IPX;
+ addresses.Addresses[0].dwAddressLength = sizeof(SOCKADDR_IPX);
+ addresses.Addresses[0].dwPrincipalLength = 0;
+ addresses.Addresses[0].lpAddress = (PBYTE)&ipxaddr;
+ addresses.Addresses[0].lpPrincipal = NULL;
+
+ // Set the service.
+ status = SetServiceW(NS_SAP,
+ SERVICE_REGISTER,
+ 0,
+ &info,
+ NULL,
+ &ignore);
+
+ ASSERT(status == SOCKET_ERROR || status == 0);
+ if (status == SOCKET_ERROR)
+ {
+ status = GetLastError();
+ }
+
+ if (status == 0)
+ {
+ SapState = SapStateEnabled;
+ }
+ else
+ {
+ #if DBG
+ DbgPrint("OR: SetServiceW failed %d\n", status);
+ #endif
+ }
+
+ return;
+}
+
diff --git a/private/ole32/dcomss/wrapper/sources.inc b/private/ole32/dcomss/wrapper/sources.inc
new file mode 100644
index 000000000..1267f3af1
--- /dev/null
+++ b/private/ole32/dcomss/wrapper/sources.inc
@@ -0,0 +1,42 @@
+!IF 0
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Revision History:
+
+!ENDIF
+
+TARGETNAME=rpcss
+TARGETTYPE=PROGRAM
+TARGETLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\security.lib \
+ $(BASEDIR)\public\sdk\lib\*\wsock32.lib \
+
+BACKGROUND_USE=1
+
+NTPROFILEINPUT=yes
+BLDCRT=1
+USE_CRTDLL=1
+MSC_WARNING_LEVEL=/WX
+
+UMTYPE=console
+UMAPPL=
+UMTEST=
+UMLIBS=
+
diff --git a/private/ole32/dcomss/wrapper/start.cxx b/private/ole32/dcomss/wrapper/start.cxx
new file mode 100644
index 000000000..3c895af76
--- /dev/null
+++ b/private/ole32/dcomss/wrapper/start.cxx
@@ -0,0 +1,382 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ Start.c
+
+Abstract:
+
+ Process init and service controller interaction for dcomss.exe
+
+Author:
+
+ Mario Goertzel [MarioGo]
+
+Revision History:
+
+ MarioGo 06-14-95 Cloned from the old endpoint mapper.
+
+--*/
+
+#include <dcomss.h>
+#include <debnot.h>
+#include <olesem.hxx>
+
+
+
+// Array of service status blocks and pointers to service control
+// functions for each component service.
+
+#define SERVICE_NAME L"RPCSS"
+
+VOID WINAPI ServiceMain(DWORD, PWSTR[]);
+
+SERVICE_TABLE_ENTRY gaServiceEntryTable[] = {
+ { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain},
+ { NULL, NULL }
+ };
+
+static SERVICE_STATUS gServiceStatus;
+static SERVICE_STATUS_HANDLE ghServiceHandle;
+
+BOOL gfDebugMode = FALSE;
+
+BOOL gfRegisteredAuthInfo = FALSE;
+
+
+
+void
+ServiceHandler(
+ DWORD opCode
+ )
+/*++
+
+Routine Description:
+
+ Lowest level callback from the service controller to
+ cause this service to change our status. (stop, start, pause, etc).
+
+Arguments:
+
+ opCode - One of the service "Controls" value.
+ SERVICE_CONTROL_{STOP, PAUSE, CONTINUE, INTERROGATE, SHUTDOWN}.
+
+Return Value:
+
+ None
+
+--*/
+{
+ RPC_STATUS status;
+
+ switch(opCode) {
+
+ case SERVICE_CONTROL_STOP:
+ case SERVICE_CONTROL_PAUSE:
+ case SERVICE_CONTROL_CONTINUE:
+ default:
+#ifdef DEBUGRPC
+ DbgPrint("%S: Unexpected service control message %d.\n", SERVICE_NAME, opCode);
+#endif
+ ASSERT(0);
+ break;
+
+ case SERVICE_CONTROL_INTERROGATE:
+ // Service controller wants us to call SetServiceStatus.
+
+ UpdateState(gServiceStatus.dwCurrentState);
+ break ;
+
+ case SERVICE_CONTROL_SHUTDOWN:
+ // The machine is shutting down. We'll be killed once we return.
+ // Note, currently we don't register for these messages.
+ break;
+ }
+
+ return;
+}
+
+
+VOID
+UpdateState(
+ DWORD dwNewState
+ )
+/*++
+
+Routine Description:
+
+ Updates this services state with the service controller.
+
+Arguments:
+
+ dwNewState - The next start for this service. One of
+ SERVICE_START_PENDING
+ SERVICE_RUNNING
+
+Return Value:
+
+ None
+
+--*/
+{
+ DWORD status = ERROR_SUCCESS;
+
+ if (gfDebugMode == TRUE)
+ {
+ return;
+ }
+
+ ASSERT( (dwNewState == SERVICE_RUNNING) ||
+ (gServiceStatus.dwCurrentState != SERVICE_RUNNING) );
+
+ switch (dwNewState)
+ {
+
+ case SERVICE_RUNNING:
+ case SERVICE_STOPPED:
+ gServiceStatus.dwCheckPoint = 0;
+ gServiceStatus.dwWaitHint = 0;
+ break;
+
+ case SERVICE_START_PENDING:
+ case SERVICE_STOP_PENDING:
+ ++gServiceStatus.dwCheckPoint;
+ gServiceStatus.dwWaitHint = 30000L;
+ break;
+
+ default:
+ ASSERT(0);
+ status = ERROR_INVALID_SERVICE_CONTROL;
+ break;
+ }
+
+ if (status == ERROR_SUCCESS)
+ {
+ gServiceStatus.dwCurrentState = dwNewState;
+ if (!SetServiceStatus(ghServiceHandle, &gServiceStatus))
+ {
+ status = GetLastError();
+ }
+ }
+
+#ifdef DEBUGRPC
+ if (status != ERROR_SUCCESS)
+ {
+ DbgPrint("%S: Failed to update service state: %d\n", SERVICE_NAME, status);
+ }
+#endif
+
+ // We could return a status but how would we recover? Ignore it, the
+ // worst thing is that services will kill us and there's nothing
+ // we can about it if this call fails.
+
+ return;
+}
+
+
+VOID WINAPI
+ServiceMain(
+ DWORD argc,
+ PWSTR argv[]
+ )
+/*++
+
+Routine Description:
+
+ Callback by the service controller when starting this service.
+
+Arguments:
+
+ argc - number of arguments, usually 1
+
+ argv - argv[0] is the name of the service.
+ argv[>0] are arguments passed to the service.
+
+Return Value:
+
+ None
+
+--*/
+{
+ DWORD status = ERROR_SUCCESS;
+
+ const DWORD RPCSS_CONTROLS = 0; // SERVER_ACCEPT_STOP - we don't stop.
+
+ ASSERT( (argc >= 1 && lstrcmpiW(argv[0], SERVICE_NAME) == 0)
+ || (argc == 0 && argv == 0));
+
+#if DBG==1
+
+ // Note that we've completed running the static constructors
+
+ ASSERT(g_fDllState == DLL_STATE_STATIC_CONSTRUCTING);
+
+ g_fDllState = DLL_STATE_NORMAL;
+
+#endif
+
+
+ // Initialize the mutex package
+
+ InitializeCriticalSection (&g_OleMutexCreationSem);
+
+
+ if (FALSE == gfDebugMode)
+ {
+ gServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ gServiceStatus.dwCurrentState = SERVICE_START_PENDING;
+ gServiceStatus.dwControlsAccepted = RPCSS_CONTROLS;
+ gServiceStatus.dwWin32ExitCode = 0;
+ gServiceStatus.dwServiceSpecificExitCode = 0;
+ gServiceStatus.dwCheckPoint = 0;
+ gServiceStatus.dwWaitHint = 3000L;
+
+ ghServiceHandle = RegisterServiceCtrlHandler(SERVICE_NAME,
+ ServiceHandler);
+
+ if (0 == ghServiceHandle)
+ {
+ status = GetLastError();
+ ASSERT(status != ERROR_SUCCESS);
+ }
+ }
+
+ if (status == ERROR_SUCCESS)
+ {
+ UpdateState(SERVICE_START_PENDING);
+ }
+
+ if (status == ERROR_SUCCESS)
+ {
+ // epts.c
+ status = InitializeEndpointManager();
+ }
+
+ // Start Ep Mapper.
+ if (status == ERROR_SUCCESS)
+ {
+ // ..\epmap\server.c
+ UpdateState(SERVICE_START_PENDING);
+ status = StartEndpointMapper();
+ }
+
+ // Start object resolver
+ if (status == ERROR_SUCCESS)
+ {
+ // ..\objex\objex.cxx
+ UpdateState(SERVICE_START_PENDING);
+ status = StartObjectExporter();
+ }
+
+ // Start OLESCM
+ if (status == ERROR_SUCCESS)
+ {
+ // ..\olescm\scmsvc.cxx
+ UpdateState(SERVICE_START_PENDING);
+ status = InitializeSCM();
+ }
+
+ if (status == ERROR_SUCCESS)
+ {
+ // We continue if this fails, not the end of the world.
+ (void) RegisterAuthInfoIfNecessary();
+ }
+
+ // Start listening for RPC requests
+ if (status == ERROR_SUCCESS)
+ {
+ status = RpcServerListen(1, 1234, TRUE);
+
+ if (status == RPC_S_OK)
+ {
+ while (RpcMgmtIsServerListening(0) == RPC_S_NOT_LISTENING)
+ {
+ Sleep(100);
+ }
+ }
+ }
+
+ //
+ // There is some initialization that must be done after we
+ // have done the RpcServerListen.
+ //
+ if (status == ERROR_SUCCESS)
+ {
+ // ..\olescm\scmsvc.cxx
+ UpdateState(SERVICE_START_PENDING);
+ InitializeSCMAfterListen();
+ }
+
+ // Trim our working set - free space now at the cost of time later.
+ if (status == ERROR_SUCCESS)
+ {
+ // Since we auto-start it is unlikely that may of our pages
+ // will be needed anytime soon.
+
+ UpdateState(SERVICE_RUNNING);
+
+ if (FALSE == SetProcessWorkingSetSize(GetCurrentProcess(), ~0UL, ~0UL))
+ {
+ status = GetLastError();
+ }
+ }
+
+#ifdef DEBUGRPC
+ if (status != ERROR_SUCCESS)
+ {
+ DbgPrint("RPCSS ServiceMain failed %d (%08x)\n", status, status);
+ }
+#endif
+
+ if (status == ERROR_SUCCESS)
+ {
+ ObjectExporterWorkerThread(0);
+ ASSERT(0);
+ }
+
+ return;
+}
+
+
+int
+main(
+ int argc,
+ char *argv[]
+ )
+{
+ DWORD status;
+
+ //DebugBreak(); // Makes debugging as a service during startup possible.
+
+ if (argc == 2 && _stricmp(argv[1], "noservice") == 0)
+ {
+ gfDebugMode = TRUE;
+ }
+
+ if (gfDebugMode == FALSE)
+ {
+ if (StartServiceCtrlDispatcher(gaServiceEntryTable) == FALSE)
+ {
+#ifdef DEBUGRPC
+ DbgPrint("%S: StartServiceCtrlDispatcher failed %d\n",
+ SERVICE_NAME,
+ GetLastError()
+ );
+#endif
+ }
+ }
+ else
+ {
+ // Debug only.
+ ServiceMain(0, 0);
+ }
+
+#ifdef DEBUGRPC
+ DbgPrint("RPCSS: Service stopped.\n");
+#endif
+
+ return(0);
+}
+
diff --git a/private/ole32/dirs b/private/ole32/dirs
new file mode 100644
index 000000000..d0c5191d0
--- /dev/null
+++ b/private/ole32/dirs
@@ -0,0 +1,57 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+# WARNING: order is important. com must be built early since it generates
+# headers that other directories are dependent on. if you change
+# this, run the following script to ensure you have not broken it.
+# stg must now be built before oleprx32.
+#
+# del /s /q *.*
+# build -cZM
+
+
+DIRS= \
+ common \
+ com \
+ ilib \
+ ole232 \
+ stg \
+ oleprx32 \
+ dcomss \
+ dll \
+ stdclass \
+ olecnv32 \
+ olecnfg \
+ oleui \
+ dllhost \
+ olethunk
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS=
diff --git a/private/ole32/dll/daytona/makefile b/private/ole32/dll/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/dll/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/dll/daytona/makefile.inc b/private/ole32/dll/daytona/makefile.inc
new file mode 100644
index 000000000..6007c62e4
--- /dev/null
+++ b/private/ole32/dll/daytona/makefile.inc
@@ -0,0 +1 @@
+obj\$(TARGET_DIRECTORY)\ole32.def: ole32.src
diff --git a/private/ole32/dll/daytona/ole32.prf b/private/ole32/dll/daytona/ole32.prf
new file mode 100644
index 000000000..0f0a30906
--- /dev/null
+++ b/private/ole32/dll/daytona/ole32.prf
@@ -0,0 +1,1777 @@
+?CRetailMalloc_Alloc@@YGPAXPAUIMalloc@@K@Z
+?CRetailMalloc_Free@@YGXPAUIMalloc@@PAX@Z
+CoTaskMemAlloc@4
+?wIsEqualGUID@@YIHABU_GUID@@0@Z
+?Request@COleStaticMutexSem@@QAEXXZ
+?Release@CStdIdentity@@UAGKXZ
+?AddRef@CInternalUnk@CStdIdentity@@UAGKXZ
+?AddRef@CInternalUnk@CStdIdentity@@W3AGKXZ
+?Release@CInternalUnk@CStdIdentity@@UAGKXZ
+?AddRef@CStdIdentity@@UAGKXZ
+?Release@CInternalUnk@CStdIdentity@@W3AGKXZ
+?IsValidIndex@CPageAllocator@@QAEHJ@Z
+?Release@CStdIdentity@@W3AGKXZ
+?LookupIPID@CIPIDTable@@QAEPAUtagIPIDEntry@@ABU_GUID@@@Z
+?GetEntryPtr@CPageAllocator@@QAEPAUtagPageEntry@@J@Z
+?Release@CDfMutex@@QAEXXZ
+?SetState@CSmAllocator@@QAEXPAVCSharedMemoryBlock@@PAEKPAPAVCPerContext@@PAV3@@Z
+?Take@CDfMutex@@QAEJK@Z
+?GetTlsSmAllocator@@YGAAVCSmAllocator@@XZ
+??1CStreamCache@@QAE@XZ
+??3CMallocBased@@SGXPAX@Z
+?Free@CSmAllocator@@UAGXPAX@Z
+?Release@CSafeSem@@QAEXXZ
+?CheckName@@YGJPBG@Z
+?GetTableWithSect@CPagedVector@@QAEJKKKPAPAX@Z
+?IsEqual@CDfName@@QBEHPBV1@@Z
+?GetDirEntry@CDirectory@@QAEJKKPAPAVCDirEntry@@@Z
+?ReleaseEntry@CDirectory@@QAEXK@Z
+?FindEntry@CDirectory@@AAEJKPBVCDfName@@W4DIRENTRYOP@@PAUSEntryBuffer@@@Z
+??0CStreamCache@@QAE@XZ
+?Alloc@CSmAllocator@@UAGPAXK@Z
+?FindBlock@CSmAllocator@@AAEPAVCBlockHeader@@KPAPAV2@@Z
+?ModeToDFlags@@YGKK@Z
+??0SCacheEntry@@QAE@XZ
+??2CMallocBased@@SGPAXIQAUIMalloc@@@Z
+?VerifyPerms@@YGJK@Z
+?IsDenied@CChildInstanceList@@QAEJPBVCDfName@@KK@Z
+?GetNewLuid@PBasicEntry@@SGKPBUIMalloc@@@Z
+?NameCompare@CDirectory@@SGHPBVCDfName@@0@Z
+?OpenStream@CExposedDocFile@@UAGJPBGPAXKKPAPAUIStream@@@Z
+?OpenEntry@CExposedDocFile@@AAEJPBVCDfName@@KKPAPAX@Z
+?GetStream@CPubDocFile@@QAEJPBVCDfName@@KPAPAVCPubStream@@@Z
+??0CDirectStream@@QAE@K@Z
+?Init@CDirectStream@@QAEJPAVCStgHandle@@PBVCDfName@@H@Z
+??1CDirectStream@@QAE@XZ
+?GetStream@CDocFile@@UAEJPBVCDfName@@KPAPAVPSStream@@@Z
+IsValidInterface@4
+?DFlagsToMode@@YGKK@Z
+?vRelease@CDFBasis@@QAEXXZ
+??0CSafeMultiHeap@@QAE@PAVCPerContext@@@Z
+??1CSafeMultiHeap@@QAE@XZ
+?vRelease@CPubStream@@QAEXXZ
+?Release@CExposedStream@@UAGKXZ
+?RemoveMarshal@CMarshalList@@QAEXPAV1@@Z
+?vRelease@CSeekPointer@@QAEXXZ
+?RemoveRv@CChildInstanceList@@QAEXPAVPRevertable@@@Z
+??1CExposedStream@@QAE@XZ
+??1CAsyncConnection@@QAE@XZ
+??1CPubStream@@QAE@XZ
+?dfwcsnicmp@@YGHPBG0I@Z
+?ReadAt@CFileStream@@UAGJT_ULARGE_INTEGER@@PAXKPAK@Z
+?Init@CPubStream@@QAEXPAVPSStream@@K@Z
+?Add@CChildInstanceList@@QAEXPAVPRevertable@@@Z
+?Init@CExposedStream@@QAEJPAVCPubStream@@PAVCDFBasis@@PAVCPerContext@@HPAVCSeekPointer@@@Z
+??0CPubStream@@QAE@PAVCPubDocFile@@KPBVCDfName@@@Z
+??0CExposedStream@@QAE@XZ
+?Release@CRpcChannelBuffer@@UAGKXZ
+CoTaskMemFree@4
+??3@YAXPAX@Z
+??2@YAPAXI@Z
+NdrClientCall2
+?RetryRPC@CRpcResolver@@AAEHJ@Z
+?CheckStatus@CRpcResolver@@AAEJJ@Z
+?IndexOf@CArrayFValue@@QAEHPAXII@Z
+?Read@CExposedStream@@UAGJPAXKPAK@Z
+?FindIPIDEntry@CStdMarshal@@QAEJABU_GUID@@PAPAUtagIPIDEntry@@@Z
+?InitChannelIfNecessary@@YGJXZ
+?GetConnection@CRpcResolver@@QAEJXZ
+?FreeObjRef@@YGXAAUtagOBJREF@@@Z
+?Empty@CStreamCache@@QAEXXZ
+?AddRef@CDirectStream@@UAEXXZ
+?Init@CStreamCache@@QAEXPAVCMStream@@KPAVCDirectStream@@@Z
+?CacheSegment@CStreamCache@@AAEXPAUSSegment@@@Z
+?Contig@CFat@@QAEJPAUSSegment@@HKKPAK@Z
+?GetSect@CStreamCache@@QAEJKPAK@Z
+?GetStart@CStreamCache@@AAEJPAK@Z
+?GetSize@CDirectStream@@UAEXPAK@Z
+?ReadAt@CDirectStream@@UAEJKPAXKPAK@Z
+?Contig@CStreamCache@@QAEJKHPAUSSegment@@KPAK@Z
+?Lookup@CHashTable@@IAEPAUSHashChain@@KPBX@Z
+?GetLocalOXIDEntry@@YGPAUtagOXIDEntry@@XZ
+?GetOXIDFromObjRef@@YGPAUtagOXIDEntry@@AAUtagOBJREF@@@Z
+?LookupIDFromUnk@@YGJPAUIUnknown@@KPAPAVCStdIdentity@@@Z
+?DecOXIDRefCnt@@YGXPAUtagOXIDEntry@@@Z
+?SetSize@CArrayFValue@@QAEHHH@Z
+?PreventDisconnect@CStdMarshal@@QAEJXZ
+?HandlePendingDisconnect@CStdMarshal@@QAEJJ@Z
+?FillSTD@CStdMarshal@@QAEXPAUtagSTDOBJREF@@KKPAUtagIPIDEntry@@@Z
+?FillObjRef@CStdMarshal@@AAEXAAUtagOBJREF@@KKPAUtagIPIDEntry@@@Z
+?IncSrvIPIDCnt@CStdMarshal@@QAEJPAUtagIPIDEntry@@KKPAUtagSECURITYBINDING@@K@Z
+?MarshalIPID@CStdMarshal@@QAEJABU_GUID@@KKPAPAUtagIPIDEntry@@@Z
+?MarshalObjRef@CStdMarshal@@QAEJAAUtagOBJREF@@ABU_GUID@@PAXK@Z
+?GetServer@CStdIdentity@@QAEPAUIUnknown@@XZ
+?DecStrongCnt@CStdIdentity@@QAEXH@Z
+?FindStdMarshal@@YGJAAUtagOBJREF@@PAPAVCStdMarshal@@@Z
+?LookupOXID@COXIDTable@@QAEPAUtagOXIDEntry@@AB_K0@Z
+?SearchList@COXIDTable@@AAEPAUtagOXIDEntry@@ABU_GUID@@PAU2@@Z
+MIDL_user_free@4
+MIDL_user_allocate@4
+?Release@CInterfaceFromWindowProp@@UAGKXZ
+?Compare@CUUIDHashTable@@UAEHPBXPAUSHashChain@@K@Z
+?SetAt@CArrayFValue@@QAEXHPAX@Z
+?SetAtGrow@CArrayFValue@@QAEHHPAX@Z
+?DecSrvIPIDCnt@CStdMarshal@@QAEXPAUtagIPIDEntry@@KKPAUtagSECURITYBINDING@@K@Z
+?ReleaseMarshalObjRef@CStdMarshal@@QAEJAAUtagOBJREF@@@Z
+?FindIPIDEntryByIPID@CStdMarshal@@AAEJABU_GUID@@PAPAUtagIPIDEntry@@@Z
+?GetLocalMIDEntry@@YGJPAPAUtagMIDEntry@@@Z
+?FindOrCreateOXIDEntry@@YGJAB_KAAUtagOXID_INFO@@W4tagFOCOXID@@PAUtagDUALSTRINGARRAY@@0PAUtagMIDEntry@@PAPAUtagOXIDEntry@@@Z
+??0CRpcChannelBuffer@@QAE@PAVCStdIdentity@@PAUtagOXIDEntry@@K@Z
+?ServerGetPreRegMOID@CRpcResolver@@QAEJPAU_GUID@@@Z
+_mega_IID_Lookup@8
+?SetObjectID@@YGJABU_GUID@@PAUIUnknown@@PAVCStdIdentity@@@Z
+?AllocEntry@CPageAllocator@@QAEPAUtagPageEntry@@XZ
+?FirstMarshal@CStdMarshal@@AAEJPAUIUnknown@@K@Z
+?AddIPIDEntry@CStdMarshal@@AAEJPAUtagOXIDEntry@@PAU_GUID@@ABU3@PAVCRpcChannelBuffer@@PAUIUnknown@@PAXPAPAUtagIPIDEntry@@@Z
+?GetEntryIndex@CPageAllocator@@QAEJPAUtagPageEntry@@@Z
+?GetPSFactory@CStdMarshal@@AAEJABU_GUID@@PAUIUnknown@@HPAPAUIPSFactoryBuffer@@PAH@Z
+PrxDllGetClassObject@12
+??0CStdMarshal@@QAE@XZ
+?MakeSrvIPIDEntry@CStdMarshal@@AAEJABU_GUID@@PAPAUtagIPIDEntry@@@Z
+?IncStrongCnt@CStdIdentity@@QAEXXZ
+?CreateStub@CStdMarshal@@AAEJABU_GUID@@PAPAUIRpcStubBuffer@@PAPAXPAH@Z
+?GetLocalEntry@COXIDTable@@QAEJPAPAUtagOXIDEntry@@@Z
+?RegisterInterface@CRIFTable@@QAEJABU_GUID@@HPAU2@@Z
+??0CStdIdentity@@QAE@KPAUIUnknown@@0PAPAU1@@Z
+?IncStrongAndNotifyAct@CStdMarshal@@AAEXPAUtagIPIDEntry@@K@Z
+?GetPSClsid@CRIFTable@@QAEJABU_GUID@@PAU2@PAPAUtagRIFEntry@@@Z
+NdrDllGetClassObject@24
+?SetOID@CStdIdentity@@QAEJABU_GUID@@@Z
+?Init@CStdMarshal@@QAEXPAUIUnknown@@PAVCStdIdentity@@ABU_GUID@@K@Z
+?CreateChannel@CStdMarshal@@AAEJPAUtagOXIDEntry@@KABU_GUID@@1PAPAVCRpcChannelBuffer@@@Z
+?ClearObjectID@@YGJABU_GUID@@PAUIUnknown@@PAVCStdIdentity@@@Z
+?DisconnectObject@CStdMarshal@@UAGJK@Z
+?RevokeOID@CStdIdentity@@QAEXXZ
+?Disconnect@CStdMarshal@@QAEXXZ
+?DisconnectSrvIPIDs@CStdMarshal@@AAEXXZ
+?ReleaseCtrlUnk@CStdIdentity@@QAEXXZ
+??1CRpcChannelBuffer@@QAE@XZ
+?CompleteObjRef@@YGJAAUtagOBJREF@@AAUtagOXID_INFO@@ABU_GUID@@PAH@Z
+CStdStubBuffer_Disconnect@4
+?ReleaseEntryList@CPageAllocator@@QAEXPAUtagPageEntry@@0@Z
+?Disconnect@CStdIdentity@@UAGXXZ
+??1CStdIdentity@@QAE@XZ
+??1CStdMarshal@@QAE@XZ
+CStdStubBuffer_Release@4
+NdrCStdStubBuffer_Release@8
+?GetWindowPropInterface@CRpcResolver@@QAEJPAUHWND__@@KHPAUtagSTDOBJREF@@PAUtagOXID_INFO@@@Z
+?DecStrongAndNotifyAct@CStdMarshal@@AAEXPAUtagIPIDEntry@@K@Z
+?ReleaseEntryList@CIPIDTable@@QAEXPAUtagIPIDEntry@@0@Z
+GetWindowPropInterface@28
+UnAssignEndpointProperty@8
+?ReleaseMarshalObjRef@@YGJAAUtagOBJREF@@@Z
+?CopyStringArray@@YGJPAUtagDUALSTRINGARRAY@@0PAPAU1@@Z
+?GetStringBindings@@YGJPAPAUtagDUALSTRINGARRAY@@@Z
+?MarshalObjRef@@YGJAAUtagOBJREF@@ABU_GUID@@PAXK@Z
+StartListen@0
+I_RpcServerStartListening@4
+?RegisterWindowPropInterface@CRpcResolver@@QAEJPAUHWND__@@PAUtagSTDOBJREF@@PAUtagOXID_INFO@@PAK@Z
+RegisterWindowPropInterface@24
+??0CInterfaceFromWindowProp@@QAE@XZ
+?AddRef@CInterfaceFromWindowProp@@UAGKXZ
+AssignEndpointProperty@4
+?FillLocalOXIDInfo@@YGJAAUtagOBJREF@@AAUtagOXID_INFO@@@Z
+?QueryInterface@CInterfaceFromWindowProp@@UAGJABU_GUID@@PAPAX@Z
+?Release@CFileMoniker@@UAGKXZ
+?AddRef@CBaseMoniker@@UAGKXZ
+?vRelease@CFileStream@@QAEKXZ
+?Release@CFileStream@@UAGKXZ
+?QueryInterface@CFileStream@@UAGJABU_GUID@@PAPAX@Z
+?SetNext@CFat@@QAEJKK@Z
+??BCBasedMSFPagePtr@@QBEPAVCMSFPage@@XZ
+?Flush@CMStream@@QAEJH@Z
+?DeleteByName@CChildInstanceList@@QAEXPBVCDfName@@@Z
+?Release@CFileStream@@W3AGKXZ
+?GetNext@CFat@@QAEJKPAK@Z
+??BCBasedMSFPagePtrPtr@@QBEPAVCBasedMSFPagePtr@@XZ
+?Release@CDirectStream@@UAEXXZ
+?Stat@CExposedStream@@UAGJPAUtagSTATSTG@@K@Z
+?Stat@CPubStream@@QAEJPAUtagSTATSTG@@K@Z
+?WriteAt@CFileStream@@UAGJT_ULARGE_INTEGER@@PBXKPAK@Z
+?IsFree@CFat@@AAEJK@Z
+?WriteAtWorker@CFileStream@@AAEJT_ULARGE_INTEGER@@PBXKPAK@Z
+?CRetailMalloc_Realloc@@YGPAXPAUIMalloc@@PAXK@Z
+?SetDirty@CPagedVector@@QAEJK@Z
+?SetSizeWorker@CFileStream@@AAEJT_ULARGE_INTEGER@@@Z
+?GetFree@CFat@@QAEJKPAKH@Z
+?Write@CExposedStream@@UAGJPBXKPAK@Z
+??BCBasedFatPtr@@QBEPAVCFat@@XZ
+?SetSize@CFileStream@@UAGJT_ULARGE_INTEGER@@@Z
+?MarkSect@CFat@@AAEJPAUSGetFreeStruct@@@Z
+?FindMaxSect@CFat@@QAEJPAK@Z
+??CCBasedMSFPagePtr@@QBEPAVCMSFPage@@XZ
+?FlushHeader@CMStream@@QAEJG@Z
+?ILBFlush@@YGJPAUILockBytes@@H@Z
+?Flush@CMSFPageTable@@QAEJXZ
+?FindLast@CFat@@QAEJPAK@Z
+?WriteAt@CDirectStream@@UAEJKPBXKPAK@Z
+?MWrite@CMStream@@QAEJKHKPBXKPAVCStreamCache@@PAK@Z
+?SetSize@CDirectStream@@UAEJK@Z
+?FlushPage@CMSFPageTable@@QAEJPAVCMSFPage@@@Z
+?GetBuffer@@YGJGGPAPAEPAG@Z
+?GetSafeBuffer@@YGXGGPAPAEPAG@Z
+?FreeBuffer@@YGXPAE@Z
+?Commit@CPubStream@@QAEJK@Z
+?SetSect@CMSFPageTable@@QAEXPAVCMSFPage@@K@Z
+?GetFreePage@CMSFPageTable@@QAEJPAPAVCMSFPage@@@Z
+??0CMSFPage@@QAE@PAV0@@Z
+CoMarshalInterface@24
+?DupWCHARString@@YGJPBGAAPAGAAG@Z
+??0CMarshalImplPStream@@QAE@PAUIPersistStream@@@Z
+?EatDotDots@@YGHPAPBGPAG@Z
+??0CFileMoniker@@AAE@XZ
+?Create@CFileMoniker@@SGPAV1@PBGGG@Z
+??1CExtentList@@QAE@XZ
+?SetParent@CTrackingFileMoniker@@QAEXPAVCFileMoniker@@@Z
+?Initialize@CFileMoniker@@AAEHGPBGG@Z
+??1CFileMoniker@@AAE@XZ
+?Initialize@CFileMoniker@@AAEHGPADGPAGGG@Z
+??0CExtentList@@QAE@XZ
+?Release@CRunningObjectTable@@UAGKXZ
+GetRunningObjectTable@8
+?QueryInterface@CBaseMoniker@@UAGJABU_GUID@@PAPAX@Z
+?QueryInterface@CFileMoniker@@UAGJABU_GUID@@PAPAX@Z
+?WriteAnsiStringStream@@YGJPAUIStream@@PADK@Z
+?IsCompositeMoniker@@YGPAVCCompositeMoniker@@PAUIMoniker@@@Z
+?Commit@CSharedMemoryBlock@@QAEJK@Z
+?AddRef@CFileStream@@UAGKXZ
+?DfInitSharedMemBase@@YGXXZ
+?Init@CDfMutex@@QAEJPAG@Z
+?GetState@CSmAllocator@@QAEXPAPAVCSharedMemoryBlock@@PAPAEPAK@Z
+?InitWorker@CFileStream@@AAEJPBGH@Z
+?Init@CSmAllocator@@QAEJKH@Z
+??1CPerContext@@QAE@XZ
+??1CDfMutex@@QAE@XZ
+?Uninit@CSmAllocator@@QAEJXZ
+?IsApartmentInitialized@@YGHXZ
+?RemapClassCtxForInProcServer@@YGKK@Z
+?GetTreatAs@@YGJABU_GUID@@AAU1@@Z
+?GetTreatAs@CTreatList@@QAEJABU_GUID@@AAU2@@Z
+?IsInternalCLSID@@YGHABU_GUID@@0AAJPAPAX@Z
+?DfGetTOD@@YGJPAU_FILETIME@@@Z
+?vRelease@CPubDocFile@@QAEXXZ
+?Release@CExposedDocFile@@UAGKXZ
+?Stat@CExposedDocFile@@UAGJPAUtagSTATSTG@@K@Z
+?GetStateBits@CDocFile@@UAEJPAK@Z
+?GetClass@CDocFile@@UAEJPAU_GUID@@@Z
+_CRT_INIT@12
+_DllMainCRTStartup@12
+DllMain@12
+ThreadNotification@12
+?DoThreadSpecificCleanup@@YGXXZ
+?Init@CSharedMemoryBlock@@QAEJPAGKKPAX1H@Z
+?CreateSharedFileMapping@@YGPAXPAGKKPAX1KPAPAXPAH@Z
+??0CPubDocFile@@QAE@PAV0@PAVPDocFile@@KKPAVCDFBasis@@PBVCDfName@@IPAVCMStream@@@Z
+??0CExposedDocFile@@QAE@PAVCPubDocFile@@PAVCDFBasis@@PAVCPerContext@@H@Z
+ReadClassStg@8
+?Seek@CExposedStream@@UAGJT_LARGE_INTEGER@@KPAT_ULARGE_INTEGER@@@Z
+?ReadObjRef@@YGJPAUIStream@@AAUtagOBJREF@@@Z
+?StRead@@YGJPAUIStream@@PAXK@Z
+?Storage32DllGetClassObject@@YGJABU_GUID@@0PAPAX@Z
+DllGetClassObject@12
+CoCreateInstance@20
+CoCreateInstanceEx@24
+?wCoCreateInstance@@YGJABU_GUID@@PAUIUnknown@@K0PAPAX@Z
+?_GetAt@CArrayFValue@@QBEPAXH@Z
+?Hash@CStringHashTable@@QAEKPAUtagDUALSTRINGARRAY@@@Z
+?LookupMID@CMIDTable@@QAEPAUtagMIDEntry@@PAUtagDUALSTRINGARRAY@@PAK@Z
+?ThreadWndProc@@YGJPAUHWND__@@IIJ@Z
+I_RpcWindowProc@16
+_alloca_probe
+CStdStubBuffer_Invoke@12
+?RevertToSelf@CServerSecurity@@UAGJXZ
+?ServerNotify@CDebugChannelHook@@UAGXABU_GUID@@0KPAXK@Z
+?ServerGetSize@CDebugChannelHook@@UAGXABU_GUID@@0JPAK@Z
+?MTAInvoke@@YGJPAUtagRPCOLEMESSAGE@@KPAUIRpcStubBuffer@@PAUIRpcChannelBuffer@@PAK@Z
+?ServerGetSize@CErrorChannelHook@@UAGXABU_GUID@@0JPAK@Z
+?ThreadInvoke@@YGXPAU_RPC_MESSAGE@@@Z
+?GetBuffer@CRpcChannelBuffer@@UAGJPAUtagRPCOLEMESSAGE@@ABU_GUID@@@Z
+?AddRef@CStdIdentity@@W3AGKXZ
+I_RpcServerInqTransportType@4
+??0CServerSecurity@@QAE@PAVCChannelCallInfo@@@Z
+RpcBindingInqObject@8
+?EndCall@CServerSecurity@@QAEXXZ
+?ServerNotify@CErrorChannelHook@@UAGXABU_GUID@@0KPAXK@Z
+?ServerGetSize@@YGKABU_GUID@@PAK@Z
+?GetDestCtx@CRpcChannelBuffer@@UAGJPAKPAPAX@Z
+?AppInvoke@CRpcChannelBuffer@@AAEJPAVCChannelCallInfo@@PAUIRpcStubBuffer@@PAX2PAULocalThis@@@Z
+CoGetTIDFromIPID@4
+??0CChannelCallInfo@@QAE@W4tagCALLCATEGORY@@PAUtagRPCOLEMESSAGE@@KABU_GUID@@KPAVCRpcChannelBuffer@@K@Z
+?StubInvoke@@YGJPAUtagRPCOLEMESSAGE@@PAUIRpcStubBuffer@@PAUIRpcChannelBuffer@@PAK@Z
+?ByteSwapThis@@YGXKPATWireThis@@@Z
+?ComInvoke@@YGJPAVCChannelCallInfo@@@Z
+??1CChannelCallInfo@@QAE@XZ
+?ServerGetBuffer@CRpcChannelBuffer@@AAEJPAUtagRPCOLEMESSAGE@@ABU_GUID@@@Z
+?STAInvoke@@YGJPAUtagRPCOLEMESSAGE@@KPAUIRpcStubBuffer@@PAUIRpcChannelBuffer@@PAXPAK@Z
+?ServerNotify@@YGJABU_GUID@@PATWireThis@@KPAPAXK@Z
+I_RpcGetBuffer@4
+?VerifyThreadId@CThreadCheck@@QAEHXZ
+?IncrementNestCount@CSafeRefCount@@QAEKXZ
+?DecrementNestCount@CSafeRefCount@@QAEKXZ
+?SafeAddRef@CSafeRefCount@@QAEKXZ
+?SafeRelease@CSafeRefCount@@QAEKXZ
+?Release@CPrivUnknown@CDefObject@@UAGKXZ
+?AddRef@CPrivUnknown@CDefObject@@UAGKXZ
+?QueryInterface@CPrivUnknown@CDefObject@@UAGJABU_GUID@@PAPAX@Z
+?QueryInterface@CDefObject@@UAGJABU_GUID@@PAPAX@Z
+?QueryInterface@CDefObject@@W3AGJABU_GUID@@PAPAX@Z
+ClipboardWndProc@16
+?ClientNotify@@YGJABU_GUID@@PATWireThat@@KPAPAXKJ@Z
+I_RpcFreeBuffer@4
+??0working_call@@QAE@W4tagCALLCATEGORY@@PAUtagRPCOLEMESSAGE@@KABU_GUID@@KPAVCRpcChannelBuffer@@K@Z
+?ClientNotify@CErrorChannelHook@@UAGXABU_GUID@@0KPAXKJ@Z
+?UnLockClient@CStdMarshal@@QAEKXZ
+?CanMakeOutCall@@YGJKABU_GUID@@@Z
+?ClientGetSize@@YGKABU_GUID@@PAK@Z
+?GetBuffer@CAptRpcChnl@@UAGJPAUtagRPCOLEMESSAGE@@ABU_GUID@@@Z
+?SendReceive@CAptRpcChnl@@UAGJPAUtagRPCOLEMESSAGE@@PAK@Z
+?ThreadSendReceive@@YGJPAVCChannelCallInfo@@@Z
+?GetCallTypeForInCall@CAptCallCtrl@@QAEKPAPAVCCliModalLoop@@ABU_GUID@@K@Z
+?InitClientSideHandle@CRpcChannelBuffer@@AAEJXZ
+?SendReceive@CCliModalLoop@@QAEJPAUtagRPCOLEMESSAGE@@PAKPAVIRpcChannelBuffer2@@@Z
+?ClientGetSize@CErrorChannelHook@@UAGXABU_GUID@@0PAK@Z
+?ClientGetBuffer@CRpcChannelBuffer@@IAEJPAUtagRPCOLEMESSAGE@@ABU_GUID@@@Z
+?AddRef@CRpcChannelBuffer@@UAGKXZ
+I_RpcAsyncSendReceive@12
+??2working_call@@SGPAXI@Z
+?SendReceive2@CRpcChannelBuffer@@UAGJPAUtagRPCOLEMESSAGE@@PAK@Z
+?FreeBuffer@CRpcChannelBuffer@@UAGJPAUtagRPCOLEMESSAGE@@@Z
+?ByteSwapThat@@YGXKPATWireThat@@@Z
+?OleModalLoopBlockFn@@YGJPAX00@Z
+?ClientGetSize@CDebugChannelHook@@UAGXABU_GUID@@0PAK@Z
+?BlockFn@CCliModalLoop@@QAEJPAX@Z
+?ClientNotify@CDebugChannelHook@@UAGXABU_GUID@@0KPAXKJ@Z
+??3working_call@@SGXPAX@Z
+?TLSGetLogicalThread@@YGPAU_GUID@@XZ
+?LockClient@CStdMarshal@@QAEKXZ
+IUnknown_Release_Proxy@4
+?CreateEntry@CExposedDocFile@@AAEJPBVCDfName@@KKPAPAX@Z
+?Reserve@CFreeList@@QAEJPAUIMalloc@@II@Z
+?CreateStream@CExposedDocFile@@UAGJPBGKKKPAPAUIStream@@@Z
+?CreateStream@CPubDocFile@@QAEJPBVCDfName@@KPAPAVCPubStream@@@Z
+?IsEntry@CDocFile@@UAEJPBVCDfName@@PAUSEntryBuffer@@@Z
+?GetFree@CDirectory@@AAEJPAK@Z
+?SetSize@CDirectory@@QAEJKK@Z
+?SecureSect@CMStream@@QAEJKKH@Z
+?GetFreeContig@CFat@@QAEJKPAUSSegment@@KPAK@Z
+?SetStart@CDirectory@@QAEJKK@Z
+?SetChainLength@CFat@@QAEJKK@Z
+?CreateStream@CDocFile@@UAEJPBVCDfName@@KKPAPAVPSStream@@@Z
+?CreateEntry@CDirectory@@QAEJKPBVCDfName@@KPAK@Z
+?Allocate@CStreamCache@@QAEJPAVCFat@@KPAK@Z
+?SplitEntry@CDirectory@@AAEJPBVCDfName@@KKKKKPAK@Z
+?InsertEntry@CDirectory@@AAEJKKPBVCDfName@@@Z
+??BCBasedPubDocFilePtr@@QBEPAVCPubDocFile@@XZ
+?ReserveSects@CFat@@QAEJK@Z
+?GetESect@CStreamCache@@QAEJKPAK@Z
+?GetESect@CMStream@@QAEJKKPAK@Z
+?FlushBufferedData@CPubDocFile@@UAEJH@Z
+?FlushBufferedData@CChildInstanceList@@QAEJH@Z
+?Commit@CExposedDocFile@@UAGJK@Z
+?Commit@CPubDocFile@@UAEJK@Z
+?SetTime@CMStream@@QAEJKW4WHICHTIME@@U_FILETIME@@@Z
+?SetTime@CDocFile@@UAEJW4WHICHTIME@@U_FILETIME@@@Z
+?SetTime@CDirectory@@QAEJKW4WHICHTIME@@U_FILETIME@@@Z
+??1CSharedMemoryBlock@@QAE@XZ
+?CloseSharedFileMapping@@YGXPAX0@Z
+??CCBasedMSFPageTablePtr@@QBEPAVCMSFPageTable@@XZ
+?AddRef@CDocFile@@UAEXXZ
+?WriteObjRef@@YGJPAUIStream@@AAUtagOBJREF@@K@Z
+?MarshalInterface@CStdMarshal@@UAGJPAUIStream@@ABU_GUID@@PAXK2K@Z
+?Create@CBindCtx@@SGPAUIBindCtx@@XZ
+?GetMonikerCompareBuffer@@YGJPAUIMoniker@@PAVCTmpMkEqBuf@@PAU_FILETIME@@PAPAUtagInterfaceData@@@Z
+?ReleaseBoundObjects@CBindCtx@@UAGJXZ
+??1CBindCtx@@AAE@XZ
+?Release@CBindCtx@@UAGKXZ
+CreateBindCtx@8
+?BuildRotData@@YGJPAUIBindCtx@@PAUIMoniker@@PAEKPAK@Z
+??0CBindCtx@@AAE@XZ
+?GetIndicator@CCliRotHintTable@@QAEHK@Z
+?GenerateDisplayName@CFileMoniker@@QAEXPAG@Z
+?GetComparisonData@CFileMoniker@@UAGJPAEKPAK@Z
+?GetDisplayNameLength@CFileMoniker@@QAEKXZ
+?ScmRotHash@@YGKPAEKK@Z
+?Reduce@CFileMoniker@@UAGJPAUIBindCtx@@KPAPAUIMoniker@@1@Z
+?Release@CFileMoniker@@W3AGKXZ
+?IsFileMoniker@@YGPAVCFileMoniker@@PAUIMoniker@@@Z
+?Release@CMarshalImplPStream@@UAGKXZ
+?MnkUnicodeToMulti@@YGJPAGGAAPADAAGAAH@Z
+?GetTimeOfLastChange@CRunningObjectTable@@UAGJPAUIMoniker@@PAU_FILETIME@@@Z
+?GetRunningObjectTable@CBindCtx@@UAGJPAPAUIRunningObjectTable@@@Z
+?GetTimeOfLastChange@CFileMoniker@@UAGJPAUIBindCtx@@PAUIMoniker@@PAU_FILETIME@@@Z
+?GetMarshalSizeMax@CMarshalImplPStream@@UAGJABU_GUID@@PAXK1KPAK@Z
+?GetUnmarshalClass@CMarshalImplPStream@@UAGJABU_GUID@@PAXK1KPAU2@@Z
+?MarshalInterface@CMarshalImplPStream@@UAGJPAUIStream@@ABU_GUID@@PAXK2K@Z
+?UnlockRegion@CFileStream@@UAGJT_ULARGE_INTEGER@@0K@Z
+?IsEntry@CUpdateList@@QAE?AW4UlIsEntry@@PBVCDfName@@PAPAVCUpdate@@@Z
+?FindName@CTSSet@@QAEPAVPTSetMember@@PBVCDfName@@K@Z
+?AddRef@CTransactedStream@@W7AEXXZ
+?AddRef@CTransactedStream@@UAEXXZ
+?AddXSMember@CPubDocFile@@QAEXPAVPTSetMember@@0K@Z
+?Init@CTransactedStream@@QAEJPAVPSStream@@@Z
+?AddMember@CTSSet@@QAEXPAVPTSetMember@@@Z
+?SetInitialState@CTransactedStream@@AAEJPAVPSStream@@@Z
+??0CTransactedStream@@QAE@PBVCDfName@@KKPAVCMStream@@1@Z
+??0CDeltaList@@QAE@PAVCMStream@@0@Z
+?Release@CTransactedStream@@UAEXXZ
+??4CBasedMSFPagePtr@@QAEPAVCMSFPage@@PAV1@@Z
+?ReadAt@CTransactedStream@@UAEJKPAXKPAK@Z
+?GetStream@CWrappedDocFile@@UAEJPBVCDfName@@KPAPAVPSStream@@@Z
+?Save@CFileMoniker@@UAGJPAUIStream@@H@Z
+?GetClassID@CFileMoniker@@UAGJPAU_GUID@@@Z
+?ValidateAnsiPath@CFileMoniker@@QAEJXZ
+?Save@CExtentList@@QAEJPAUIStream@@@Z
+?LockRegion@CFileStream@@UAGJT_ULARGE_INTEGER@@0K@Z
+?GetLocksSupported@CFileStream@@UAGJPAK@Z
+?Add@CContextList@@QAEXPAVCContext@@@Z
+??0CFileStream@@QAE@QAUIMalloc@@@Z
+?ChangeXs@CPubDocFile@@IAEXKK@Z
+?Remove@CContextList@@QAEXPAVCContext@@@Z
+??1CFileStream@@QAE@XZ
+?HeapMinimize@CSmAllocator@@UAGXXZ
+?ClientResolveOXID@CRpcResolver@@QAEJAB_KPAUtagDUALSTRINGARRAY@@PAPAUtagOXIDEntry@@@Z
+?Compare@CStringHashTable@@UAEHPBXPAUSHashChain@@K@Z
+?DecMIDRefCnt@@YGXPAUtagMIDEntry@@@Z
+?MonikerDllGetClassObject@@YGJABU_GUID@@0PAPAX@Z
+?GetSize@CExtentList@@QAEKXZ
+?GetSizeMax@CFileMoniker@@UAGJPAT_ULARGE_INTEGER@@@Z
+?GetDisplayName@CFileMoniker@@UAGJPAUIBindCtx@@PAUIMoniker@@PAPAG@Z
+?Init@CFatSect@@QAEJG@Z
+??0CMSFHeader@@QAE@G@Z
+??0CMSFHeaderData@@QAE@G@Z
+?Release@CSmAllocator@@UAGKXZ
+??0CFreeList@@QAE@XZ
+??0CDirectory@@QAE@XZ
+??0CRootPubDocFile@@QAE@QAUIMalloc@@@Z
+?InitRoot@CRootPubDocFile@@QAEJPAUILockBytes@@KKPAPAGPAPAVCDFBasis@@PAK@Z
+??0CMStream@@QAE@PAUIMalloc@@PAPAUILockBytes@@HKG@Z
+?InitNotInd@CRootPubDocFile@@AAEJPAUILockBytes@@PAPAGKK@Z
+??0CGlobalContext@@QAE@PAUIMalloc@@@Z
+?InitMultipleSharedAllocator@@YGJPAPAUIMalloc@@@Z
+?DfFromLB@@YGJPAVCPerContext@@PAUILockBytes@@KKPAPAGPAPAUCExposedDocFile@@PAU_GUID@@@Z
+?InitFlags@CFileStream@@QAEJKK@Z
+?DllMultiStreamFromStream@@YGJPAUIMalloc@@PAPAVCMStream@@PAPAUILockBytes@@KK@Z
+?AddRef@CSmAllocator@@UAGKXZ
+??0CDIFat@@QAE@XZ
+??0CFat@@QAE@K@Z
+?GetSize@CFileStream@@UAGJPAT_ULARGE_INTEGER@@@Z
+?GetOpen@@YGJPAUILockBytes@@KHPAK@Z
+?DfFromName@@YGJPBGKKPAPAGPAPAUCExposedDocFile@@PAU_GUID@@@Z
+?Write@CXmitRpcStream@@UAGJPBXKPAK@Z
+?IsAbsoluteNonUNCPath@@YGHPBG@Z
+CreateFileMoniker@8
+GetLongPathNameW@12
+CoGetCurrentProcess@0
+?CreateCommonDdeWindow@@YGJXZ
+?IrotRegister@CRpcResolver@@QAEJPAU_MnkEqBuf@@PAUtagInterfaceData@@1PAU_FILETIME@@KPAGPAU_SCMREGKEY@@@Z
+IrotRegister@44
+?Register@CRunningObjectTable@@UAGJKPAUIUnknown@@PAUIMoniker@@PAK@Z
+?InitNotificationEvent@CPerContext@@QAEJXZ
+??4CBasedUpdatePtr@@QAEPAVCUpdate@@PAV1@@Z
+??1CMStream@@QAE@XZ
+??1CTSSet@@QAE@XZ
+??1CFreeList@@QAE@XZ
+?FreeNoMutex@CSmAllocator@@QAEXPAX@Z
+??1CPagedVector@@QAE@XZ
+?vdtor@CRootPubDocFile@@UAEXXZ
+?ReleaseOpen@@YGXPAUILockBytes@@KK@Z
+?SetInitialState@CWrappedDocFile@@AAEJPAVPDocFile@@@Z
+??0CFat@@QAE@PAV0@@Z
+??0CDIFat@@QAE@PAV0@@Z
+??0CMSFPageTable@@QAE@QAVCMStream@@KK@Z
+?InitCommon@CMStream@@AAEJXZ
+?InitSystem@CDirectStream@@QAEXPAVCMStream@@KK@Z
+?InitNew@CFat@@QAEJPAVCMStream@@@Z
+?Init@CMSFPageTable@@QAEJXZ
+?Init@CPagedVector@@QAEJPAVCMStream@@K@Z
+?DllGetScratchMultiStream@@YGJPAPAVCMStream@@HPAPAUILockBytes@@PAV1@@Z
+??0CMStream@@QAE@PBV0@@Z
+?InitNew@CMStream@@QAEJHT_ULARGE_INTEGER@@@Z
+?InitNew@CDIFat@@QAEJPAVCMStream@@@Z
+??1CExposedDocFile@@QAE@XZ
+?QueryInterface@CMarshalImplPStream@@UAGJABU_GUID@@PAPAX@Z
+?QueryInterface@CMonikerFactory@@UAGJABU_GUID@@PAPAX@Z
+?AddRef@CMonikerFactory@@UAGKXZ
+?CreateInstance@CFileMonikerFactory@@UAGJPAUIUnknown@@ABU_GUID@@PAPAX@Z
+?Release@CMonikerFactory@@UAGKXZ
+?Close@CPerContext@@QAEXXZ
+?Release@CFileStream@@WBA@AGKXZ
+?Empty@CDeltaList@@QAEXXZ
+?Empty@CUpdateList@@QAEXXZ
+?Release@CTransactedStream@@W7AEXXZ
+?RemoveMember@CTSSet@@QAEXPAVPTSetMember@@@Z
+??1CTransactedStream@@QAE@XZ
+?SetTime@CWrappedDocFile@@UAEJW4WHICHTIME@@U_FILETIME@@@Z
+?GetMap@CDeltaList@@QAEJKKPAK@Z
+?WriteAt@CTransactedStream@@UAEJKPBXKPAK@Z
+??BCBasedMStreamPtr@@QBEPAVCMStream@@XZ
+?SetSize@CMStream@@QAEJXZ
+?GetTime@CWrappedDocFile@@UAEJW4WHICHTIME@@PAU_FILETIME@@@Z
+?Init@CDeltaList@@QAEJKPAVCTransactedStream@@@Z
+CoTaskMemRealloc@8
+WriteClassStg@8
+?AddRef@CExposedDocFile@@UAGKXZ
+?AddExtent@CExtentList@@QAEJPBU_MONIKEREXTENT@@@Z
+?Flush@CFileStream@@UAGJXZ
+?Stat@CFileStream@@UAGJPAUtagSTATSTG@@K@Z
+?GetFatSect@CDIFat@@QAEJKPAK@Z
+?GetMaxSect@CFat@@QAEJPAK@Z
+?Write@CPubMappedStream@@QAEJXZ
+?FlushBufferedData@CPubStream@@UAEJH@Z
+?Read@CXmitRpcStream@@UAGJPAXKPAK@Z
+?IrotRevoke@CRpcResolver@@QAEJPAU_SCMREGKEY@@HPAPAUtagInterfaceData@@1@Z
+?ReleaseInterfaceData@@YGXPAUtagInterfaceData@@K@Z
+CoReleaseMarshalData@4
+IrotRevoke@24
+?Revoke@CRunningObjectTable@@UAGJK@Z
+?ReleaseMarshalData@CMarshalImplPStream@@UAGJPAUIStream@@@Z
+?deleteNoMutex@CMallocBased@@QAEXPAX@Z
+?DllReleaseMultiStream@@YGXPAVCMStream@@@Z
+??1CMSFPageTable@@QAE@XZ
+?Release@CDocFile@@UAEXXZ
+CoLockObjectExternal@12
+RegisterDragDrop@8
+RevokeDragDrop@4
+?CRetailMalloc_GetSize@@YGKPAUIMalloc@@PAX@Z
+?wStringFromUUID@@YGJABU_GUID@@PAG@Z
+StringFromGUID2@12
+?wStringFromGUID2@@YGHABU_GUID@@PAGH@Z
+?UtDupPtr@@YGPAXPAXK@Z
+?UtDupString@@YGPAGPBG@Z
+?CMalloc_Release@@YGKPAUIMalloc@@@Z
+CoGetMalloc@8
+?wRegQueryClassValue@@YGJABU_GUID@@PBGPAGH@Z
+?SetClass@CPubDocFile@@QAEJABU_GUID@@@Z
+?SetClass@CExposedDocFile@@UAGJABU_GUID@@@Z
+?SetSize@CExposedStream@@UAGJT_ULARGE_INTEGER@@@Z
+?SetColorBlack@CDirectory@@AAEJK@Z
+?Resize@CPagedVector@@QAEJK@Z
+?SetClassId@CDirectory@@QAEJKU_GUID@@@Z
+?SetClass@CDocFile@@UAEJABU_GUID@@@Z
+?Init@CDirSect@@QAEJG@Z
+?Stat@CPubDocFile@@UAEJPAUtagSTATSTG@@K@Z
+??0CStmBuf@@QAE@XZ
+??1CStmBuf@@QAE@XZ
+?Resize@CDirectory@@AAEJK@Z
+?IsConnected@CStdIdentity@@UAGHXZ
+?IsRunning@CDefObject@@UAGHXZ
+?RemIsConnected@CStdMarshal@@QAEHXZ
+?IsZombie@CSafeRefCount@@QAEHXZ
+?ReadCompObjStm@@YGJPAUIStorage@@PAVCompObjStmData@@@Z
+?OpenStream@CStmBufRead@@QAEJPAUIStorage@@PBG@Z
+?Reset@CStmBufRead@@AAEXXZ
+?Release@CStmBufRead@@QAEXXZ
+?wkProgIDFromCLSID@@YGJABU_GUID@@PAPAG@Z
+ProgIDFromCLSID@8
+?GetPrivateClipboardWindow@@YGPAUHWND__@@W4tagCLIPWINDOWFLAGS@@@Z
+?OleOpenClipboard@@YGJPAUHWND__@@PAPAU1@@Z
+ReleaseStgMedium@4
+?GetSize@CTransactedStream@@UAEXPAK@Z
+?GetClass@CWrappedDocFile@@UAEJPAU_GUID@@@Z
+?GetStateBits@CWrappedDocFile@@UAEJPAK@Z
+?GetPage@CMSFPageTable@@QAEJPAVCPagedVector@@KKKPAPAVCMSFPage@@@Z
+?FindPage@CMSFPageTable@@QAEJPAVCPagedVector@@KKPAPAVCMSFPage@@@Z
+DfOpenDocfile@28
+StgOpenStorage@24
+?Init@CMStream@@QAEJXZ
+?OpenStorage@@YGJPBGPAXPAUIStorage@@KPAPAGKPAPAU1@PAU_GUID@@@Z
+?CheckSignature@@YGJPAE@Z
+?Validate@CMSFHeader@@QBEJXZ
+?AddRef@CWrappedDocFile@@W7AEXXZ
+?GetAllTimes@CMStream@@QAEJKPAU_FILETIME@@00@Z
+?Init@CWrappedDocFile@@QAEJPAVPDocFile@@@Z
+?SetAllTimes@CWrappedDocFile@@UAEJU_FILETIME@@00@Z
+?Set@CDfName@@QAEXGPBE@Z
+?CopyTimesFrom@PTimeEntry@@QAEJPAV1@@Z
+??0CWrappedDocFile@@QAE@PBVCDfName@@KKPAVCDFBasis@@PAVCPubDocFile@@@Z
+??0CDlElement@@QAE@XZ
+?AddRef@CWrappedDocFile@@UAEXXZ
+?GetAllTimes@CDocFile@@UAEJPAU_FILETIME@@00@Z
+?GetLength@CFat@@QAEJKPAK@Z
+?Init@CDIFat@@QAEJPAVCMStream@@K@Z
+?Init@CFat@@QAEJPAVCMStream@@KH@Z
+?Init@CDirectory@@QAEJPAVCMStream@@K@Z
+DfCreateDocfile@20
+StgCreateDocfile@16
+?ExpandUNCName@@YGJPAGPAPAG0@Z
+?Stat@CRootPubDocFile@@UAEJPAUtagSTATSTG@@K@Z
+?BeginCommit@CWrappedDocFile@@UAEJK@Z
+?EndCommit@CTransactedStream@@UAEXK@Z
+?BeginCommit@CTransactedStream@@UAEJK@Z
+?EndCommit@CWrappedDocFile@@UAEXK@Z
+?ReleaseBlock@CDeltaList@@AAEXK@Z
+?Commit@CRootPubDocFile@@UAEJK@Z
+?CopyPathToUnicodeExtent@@YGJPAGKAAPAU_MONIKEREXTENT@@@Z
+?PartialWrite@CTransactedStream@@AAEJKKPBEGG@Z
+?Release@CWrappedDocFile@@UAEXXZ
+?Revert@CWrappedDocFile@@UAEXXZ
+??1CWrappedDocFile@@QAE@XZ
+?Release@CWrappedDocFile@@W7AEXXZ
+?BeginCommitFromChild@CDocFile@@UAEJAAVCUpdateList@@KPAVCWrappedDocFile@@@Z
+?GetAccess@@YGJPAUILockBytes@@KPAK@Z
+?ApplyChanges@CDocFile@@QAEJAAVCUpdateList@@@Z
+?EndCopyOnWrite@CMStream@@QAEJKK@Z
+?BeginCopyOnWrite@CMStream@@QAEJK@Z
+?BeginCommitFromChild@CDirectStream@@UAEJKPAVCDeltaList@@PAVCTransactedStream@@@Z
+?WaitForAccess@@YGJPAUILockBytes@@KPAK@Z
+?ReleaseAccess@@YGXPAUILockBytes@@KK@Z
+?EndCommitFromChild@CDirectStream@@UAEXKPAVCTransactedStream@@@Z
+?EndCommitFromChild@CDocFile@@UAEXKPAVCWrappedDocFile@@@Z
+?GetDeltaList@CDirectStream@@UAEPAVCDeltaList@@XZ
+?Create@CMemStm@@SGPAV1@PAX@Z
+??0CMemStm@@QAE@XZ
+ReleaseMemStm@8
+?Release@CMemStm@@UAGKXZ
+??1CMemStm@@QAE@XZ
+CreateStreamOnHGlobal@12
+?Seek@CMemStm@@UAGJT_LARGE_INTEGER@@KPAT_ULARGE_INTEGER@@@Z
+?Read@CMemStm@@UAGJPAXKPAK@Z
+CoFileTimeNow@4
+?CheckForWaiters@CRpcResolver@@AAEXPAUtagOXIDEntry@@@Z
+?ServerAllocMoreOIDs@CRpcResolver@@AAEJPAKPA_KPAUtagOXIDEntry@@@Z
+?WaitForOXIDEntry@CRpcResolver@@AAEJPAUtagOXIDEntry@@@Z
+?ServerAllocOIDs@CRpcResolver@@AAEJPAUtagOXIDEntry@@PAKPA_K@Z
+ServerAllocateOIDs@24
+?RemoveClipboardDataObject@@YGJPAUHWND__@@K@Z
+OleSetClipboard@4
+?SetClipboardDataObject@@YGJPAUHWND__@@PAUIDataObject@@@Z
+?SetClipboardFormats@@YGJPAUHWND__@@PAUIDataObject@@@Z
+?GetDataFromDescriptor@@YGJPAUIDataObject@@PAU_GUID@@IW4tagGETCLSIDFLAGS@@PAPAGPAK@Z
+?SetSize@CTransactedStream@@UAEJK@Z
+?CountFree@CFat@@AAEJPAK@Z
+?GetESect@CFat@@QAEJKKPAK@Z
+?Resize@CFat@@QAEJK@Z
+?GetSect@CFat@@QAEJKKPAK@Z
+?FlushCache@CFileStream@@UAGJXZ
+?DestroyEntry@CPubDocFile@@QAEJPBVCDfName@@H@Z
+?DestroyEntry@CDocFile@@UAEJPBVCDfName@@H@Z
+?DestroyChild@CDirectory@@QAEJKPBVCDfName@@@Z
+?Commit@CExposedStream@@UAGJK@Z
+NdrOleFree@4
+NdrOleAllocate@4
+?AddRef@CServerSecurity@@UAGKXZ
+?Release@CServerSecurity@@UAGKXZ
+?QueryInterface@CServerSecurity@@UAGJABU_GUID@@PAPAX@Z
+?MyPeekMessage@CCliModalLoop@@QAEHPAUtagMSG@@PAUHWND__@@IIG@Z
+?HandleWakeForMsg@CCliModalLoop@@AAEXXZ
+?GetElapsedTime@CCliModalLoop@@QAEKXZ
+?PeekRPCAndDDEMessage@CCliModalLoop@@AAEHXZ
+?IsImpersonating@CServerSecurity@@UAGHXZ
+?FindPrevCallOnLID@CCliModalLoop@@QAEPAV1@ABU_GUID@@@Z
+?FindMessage@CCliModalLoop@@AAEHK@Z
+IUnknown_AddRef_Proxy@4
+?QueryInterface@CInternalUnk@CStdIdentity@@W3AGJABU_GUID@@PAPAX@Z
+?QueryInterface@CInternalUnk@CStdIdentity@@UAGJABU_GUID@@PAPAX@Z
+?QueryMultipleInterfaces@CInternalUnk@CStdIdentity@@UAGJKPAUtagMULTI_QI@@@Z
+?CreateDelegate@CDefObject@@AAEJXZ
+?InstantiatedProxy@CStdMarshal@@QAEHABU_GUID@@PAPAXPAJ@Z
+?RotateEntry@CDirectory@@AAEJPBVCDfName@@KKPAK@Z
+?DestroyElement@CExposedDocFile@@UAGJPBG@Z
+?Release@CDefObject@@UAGKXZ
+?Release@CDefObject@@WM@AGKXZ
+?DuCacheDelegate@@YGPAXPAPAUIUnknown@@ABU_GUID@@PAPAXPAU1@@Z
+?GetOleDelegate@CDefObject@@QAEPAUIOleObject@@XZ
+STGMEDIUM_UserUnmarshal@12
+CLIPFORMAT_UserFree@8
+CLIPFORMAT_UserSize@12
+HMETAFILEPICT_UserUnmarshal@12
+HMETAFILEPICT_UserMarshal@12
+HMETAFILEPICT_UserSize@12
+CLIPFORMAT_UserMarshal@12
+STGMEDIUM_UserMarshal@12
+STGMEDIUM_UserSize@12
+CLIPFORMAT_UserUnmarshal@12
+?HandlePendingMessage@CCliModalLoop@@AAEXXZ
+DdeCommonWndProc@16
+?OnMessage@CFrameFilter@@QAEJIIJ@Z
+FrameWndFilterProc@16
+RpcBindingFree@4
+?Remove@CHashTable@@QAEXPAUSHashChain@@@Z
+?IsEntry@CWrappedDocFile@@UAEJPBVCDfName@@PAUSEntryBuffer@@@Z
+?Add@CUpdateList@@QAEPAVCUpdate@@QAUIMalloc@@PBVCDfName@@1KKPAVPTSetMember@@@Z
+?Append@CUpdateList@@QAEXPAVCUpdate@@@Z
+?CreateStream@CWrappedDocFile@@UAEJPBVCDfName@@KKPAPAVPSStream@@@Z
+??0CUpdate@@QAE@PBVCDfName@@0KKPAVPTSetMember@@@Z
+??1CUpdate@@QAE@XZ
+?SetClass@CWrappedDocFile@@UAEJABU_GUID@@@Z
+?OleMainThreadWndProc@@YGJPAUHWND__@@IIJ@Z
+?InitClsent@CDllCache@@AAEXKK@Z
+?Init@COleStaticMutexSem@@QAEXXZ
+_lock
+_unlock
+_unlockexit
+_initterm
+_lockexit
+CoSetState@4
+?STAProcessInitialize@@YGJXZ
+?DllHostProcessInitialize@@YGXXZ
+?TLSAllocData@COleTls@@AAEJXZ
+OleInitializeEx@8
+CoInitializeEx@8
+?DDELibMain@@YGHPAXGGPAG@Z
+?ProcessInitialize@@YGJXZ
+?InitMainThreadWnd@@YGHXZ
+?wCoInitializeEx@@YGJAAVCOleTls@@K@Z
+?Initialize@CDllHost@@AAEXK@Z
+?Sync@CSharedMemoryBlock@@QAEJXZ
+?AddRef@CDefObject@@UAGKXZ
+?AddRef@CDefObject@@WM@AGKXZ
+OleIsRunning@4
+CoUnmarshalInterface@12
+CoGetMarshalSizeMax@24
+?Add@CHashTable@@IAEXKPAUSHashChain@@@Z
+??0CMapKeyToValue@@QAE@IIHP6GIPAXI@ZI@Z
+?MarshalSharedMemory@@YGJPAUIStream@@PAVCPerContext@@@Z
+?MarshalInterface@CFileStream@@UAGJPAUIStream@@ABU_GUID@@PAXK2K@Z
+?GetMarshalSizeMax@CExposedDocFile@@UAGJABU_GUID@@PAXK1KPAK@Z
+?Release@CFileStream@@W7AGKXZ
+?Unmarshal@CExposedDocFile@@SGJPAUIStream@@PAPAXK@Z
+?MarshalContext@@YGJPAUIStream@@PAVCPerContext@@KPAXKHH@Z
+DfUnMarshalInterface@16
+?QueryInterface@CExposedDocFile@@UAGJABU_GUID@@PAPAX@Z
+?GetUnmarshalClass@CExposedDocFile@@UAGJABU_GUID@@PAXK1KPAU2@@Z
+?MarshalConnection@@YGJPAUIStream@@PAVCAsyncConnection@@KPAXK@Z
+?StartMarshal@@YGJPAUIStream@@ABU_GUID@@1K@Z
+?UnmarshalSharedMemory@@YGJPAUIStream@@KPAVCPerContext@@PAK@Z
+?GetUnmarshalClass@CFileStream@@UAGJABU_GUID@@PAXK1KPAU2@@Z
+?MarshalInterface@CExposedDocFile@@UAGJPAUIStream@@ABU_GUID@@PAXK2K@Z
+?GetMarshalSizeMax@CFileStream@@UAGJABU_GUID@@PAXK1KPAK@Z
+?UnmarshalConnection@@YGJPAUIStream@@PAKPAPAUIDocfileAsyncConnectionPoint@@K@Z
+?UnmarshalContext@@YGJPAUIStream@@PAVCGlobalContext@@PAPAVCPerContext@@KHHKH@Z
+?Unmarshal@CFileStream@@SGJPAUIStream@@PAPAXK@Z
+?Release@CDocfileUnmarshalFactory@@UAGKXZ
+?QueryInterface@CDocfileUnmarshalFactory@@UAGJABU_GUID@@PAPAX@Z
+?CreateInstance@CDocfileUnmarshalFactory@@UAGJPAUIUnknown@@ABU_GUID@@PAPAX@Z
+?Release@CDocfileUnmarshalFactory@@W3AGKXZ
+?Validate@CPubDocFile@@SGJPAV1@@Z
+?UnmarshalInterface@CDocfileUnmarshalFactory@@UAGJPAUIStream@@ABU_GUID@@PAPAX@Z
+?DfSyncSharedMemory@@YGJK@Z
+?Release@CExposedDocFile@@WBE@AGKXZ
+?UnmarshalPointer@@YGJPAUIStream@@PAPAX@Z
+?MarshalPointer@@YGJPAUIStream@@PAX@Z
+?_Find@CContextList@@QAEPAVCContext@@K@Z
+?FindMarshal@CMarshalList@@QBEPAV1@K@Z
+?GetStdMarshalSize@@YGJABU_GUID@@0KPAXKPAKKPAVCAsyncConnection@@HPAVCPerContext@@H@Z
+?wSaveCompleted@COleCache@@AAEJPAUIStorage@@H@Z
+?SaveCompleted@CDefObject@@UAGJPAUIStorage@@@Z
+?SaveCompleted@COleCache@@UAGJPAUIStorage@@@Z
+?Flush@CStmBufWrite@@QAEJXZ
+?Write@CStmBufWrite@@QAEJPBXK@Z
+?Reset@CStmBufWrite@@AAEXXZ
+?Release@CStmBufWrite@@QAEXXZ
+?CreateStream@CStmBufWrite@@QAEJPAUIStorage@@PBG@Z
+WriteStringStream@8
+?ANSIStrToStm@@YGJAAVCStmBufWrite@@PBD@Z
+WriteFmtUserTypeStg@12
+?ClipfmtToStm@@YGJAAVCStmBufWrite@@KKW4TXTTYPE@@@Z
+?UtPutUNICODEData@@YGJKPAGPAPADPAPAGPAK@Z
+?WriteCompObjStm@@YGJPAUIStorage@@PAVCompObjStmData@@@Z
+?PutUNICODEUserType@@YGJPAVCompObjStmData@@PAG@Z
+?PutClipFormat@@YGJPAVCompObjStmData@@KK@Z
+?PutUNICODEProgID@@YGJPAVCompObjStmData@@PAG@Z
+?GetNext@COleCache@@AAEPAVCCacheNode@@PAK@Z
+??1CItemMoniker@@AAE@XZ
+?UnInit@CItemMoniker@@AAEXXZ
+?Release@CItemMoniker@@UAGKXZ
+?QueryInterface@CItemMoniker@@UAGJABU_GUID@@PAPAX@Z
+?Initialize@CItemMoniker@@AAEHPBG0@Z
+?Initialize@CItemMoniker@@AAEXPAGGPADG0G1G@Z
+??0CItemMoniker@@AAE@XZ
+?Create@CItemMoniker@@SGPAV1@PBG0@Z
+CreateItemMoniker@12
+?GetClassID@CItemMoniker@@UAGJPAU_GUID@@@Z
+?SaveUnicodeAsAnsi@@YGJPAUIStream@@PAGGPADG@Z
+?Save@CItemMoniker@@UAGJPAUIStream@@H@Z
+?Release@CDefClassFactory@@UAGKXZ
+??0CDefClassFactory@@QAE@ABU_GUID@@@Z
+?Ole232DllGetClassObject@@YGJABU_GUID@@0PAPAX@Z
+?CreateInstance@CDefClassFactory@@UAGJPAUIUnknown@@ABU_GUID@@PAPAX@Z
+?GetTimeOfLastChange@CItemMoniker@@UAGJPAUIBindCtx@@PAUIMoniker@@PAU_FILETIME@@@Z
+?Release@CItemMoniker@@W3AGKXZ
+?GetComparisonData@CItemMoniker@@UAGJPAEKPAK@Z
+?InitResize@CDeltaList@@QAEJK@Z
+?Release@CClipDataObject@@UAGKXZ
+??0CClipDataObject@@QAE@XZ
+??1CClipDataObject@@QAE@XZ
+?Create@CClipDataObject@@SGJPAPAUIDataObject@@PAUtagFORMATETC@@K@Z
+OleGetClipboard@4
+?Release@CClipEnumFormatEtc@@UAGKXZ
+?EnumFormatEtc@CClipDataObject@@UAGJKPAPAUIEnumFORMATETC@@@Z
+?Next@CClipEnumFormatEtc@@UAGJKPAUtagFORMATETC@@PAK@Z
+??1CClipEnumFormatEtc@@AAE@XZ
+??0CClipEnumFormatEtc@@AAE@XZ
+?Create@CClipEnumFormatEtc@@SGJPAPAUIEnumFORMATETC@@PAUtagFORMATETC@@K@Z
+?wQueryEmbedFormats@@YGGPAUIDataObject@@PAG@Z
+OleQueryCreateFromData@4
+?wGetEnumFormatEtc@@YGJPAUIDataObject@@KPAPAUIEnumFORMATETC@@@Z
+?LookupIDFromID@@YGJABU_GUID@@HPAPAVCStdIdentity@@@Z
+RpcImpersonateClient@4
+?CheckAcl@@YGJPAX0@Z
+?HashSid@@YGKPAU_SID@@@Z
+RpcRevertToSelf@0
+?CacheAccessCheck@@YGHPAU_SID@@PAH@Z
+?UnmarshalObjRef@@YGJAAUtagOBJREF@@PAPAX@Z
+?UnmarshalIPID@CStdMarshal@@AAEJABU_GUID@@PAUtagSTDOBJREF@@PAUtagOXIDEntry@@PAPAX@Z
+?PreventPendingDisconnect@CStdMarshal@@QAEJXZ
+?UnmarshalObjRef@CStdMarshal@@QAEJAAUtagOBJREF@@PAPAX@Z
+?GetClientInterfaceInfo@CRIFTable@@QAEPAU_RPC_CLIENT_INTERFACE@@ABU_GUID@@@Z
+I_RpcBindingSetAsync@8
+RpcBindingSetObject@8
+RpcBindingCopy@8
+UuidCreate@4
+?SendOnDataChange@CDAHolder@@UAGJPAUIDataObject@@KK@Z
+IAdviseSink_RemoteOnDataChange_Proxy@12
+ASYNC_STGMEDIUM_UserSize@12
+ASYNC_STGMEDIUM_UserUnmarshal@12
+ASYNC_STGMEDIUM_UserMarshal@12
+IAdviseSink_OnDataChange_Stub@12
+IAdviseSink_OnDataChange_Proxy@12
+IAdviseSink_RemoteOnDataChange_Thunk@4
+STGMEDIUM_UserFree@8
+ASYNC_STGMEDIUM_UserFree@8
+?AddToList@@YGXPAUtagSOIDRegistration@@0@Z
+?EnsureWorkerThread@CRpcResolver@@AAEJXZ
+?GetIPIDEntry@@YGPAUtagIPIDEntry@@ABU_GUID@@@Z
+?GetRemUnk@COXIDTable@@QAEJPAUtagOXIDEntry@@PAPAUIRemUnknown@@@Z
+?GetUserClassID@CDefObject@@UAGJPAU_GUID@@@Z
+?GetPSDelegate@CDefObject@@QAEPAUIPersistStorage@@XZ
+?GetDataDelegate@CDefObject@@QAEPAUIDataObject@@XZ
+WriteMonikerStm@8
+WriteOleStg@16
+OpenOrCreateStream@12
+?GetMoniker@CDefObject@@UAGJKKPAPAUIMoniker@@@Z
+?GetTime@CDocFile@@UAEJW4WHICHTIME@@PAU_FILETIME@@@Z
+?GetTime@CMStream@@QAEJKW4WHICHTIME@@PAU_FILETIME@@@Z
+?Next@CEnumVerb@@EAGJKPAUtagOLEVERB@@PAK@Z
+?Reset@CEnumVerb@@EAGJXZ
+?InitMarshal@CAsyncConnection@@QAEJPAUIConnectionPointContainer@@KPAUIDocfileAsyncConnectionPoint@@@Z
+?InitMarshal@CExposedDocFile@@QAEJKPAUIDocfileAsyncConnectionPoint@@@Z
+?AddMarshal@CMarshalList@@QAEXPAV1@@Z
+?ClientRegisterOIDWithPingServer@CRpcResolver@@QAEJAB_KPAUtagOXIDEntry@@@Z
+?QueryInterface@CRpcChannelBuffer@@UAGJABU_GUID@@PAPAX@Z
+CreateIdentityHandler@16
+?Copy@CRpcChannelBuffer@@QAEPAV1@PAUtagOXIDEntry@@ABU_GUID@@1@Z
+?ConnectIPIDEntry@CStdMarshal@@AAEJPAUtagSTDOBJREF@@PAUtagOXIDEntry@@PAUtagIPIDEntry@@@Z
+??0CAptRpcChnl@@QAE@PAVCStdIdentity@@PAUtagOXIDEntry@@K@Z
+?GetNeededRefs@CStdMarshal@@AAEJPAUtagSTDOBJREF@@PAUtagOXIDEntry@@PAUtagIPIDEntry@@@Z
+??0CSafeRefCount@@QAE@XZ
+?CreateProxy@CStdMarshal@@AAEJABU_GUID@@PAPAUIRpcProxyBuffer@@PAPAXPAH@Z
+?MakeCliIPIDEntry@CStdMarshal@@AAEJABU_GUID@@PAUtagSTDOBJREF@@PAUtagOXIDEntry@@PAPAUtagIPIDEntry@@@Z
+?DisconnectCliIPIDs@CStdMarshal@@AAEXXZ
+?ReleaseCliIPIDs@CStdMarshal@@AAEXXZ
+?ClientDeRegisterOIDFromPingServer@CRpcResolver@@QAEJABU_GUID@@H@Z
+?RemoteReleaseRifRef@@YGJPAUtagOXIDEntry@@GPAUtagREMINTERFACEREF@@@Z
+?RemRelease@CRemoteUnknown@@UAGJGQAUtagREMINTERFACEREF@@@Z
+?SetHostNames@CDefObject@@UAGJPBG0@Z
+?RemoveFromList@@YGXPAUtagSOIDRegistration@@@Z
+?GetOxidsToRemove@COXIDTable@@QAEXPAU__MIDL_ILocalObjectExporter_0001@@PAK@Z
+?ClientBulkUpdateOIDWithPingServer@CRpcResolver@@AAEJXZ
+?NumOxidsToRemove@COXIDTable@@QAEKXZ
+BulkUpdateOIDs@44
+?Advise@COAHolder@@UAGJPAUIAdviseSink@@PAK@Z
+??0COAHolder@@QAE@XZ
+CreateOleAdviseHolder@4
+?wCoOpenClassKey@@YGJABU_GUID@@PAPAUHKEY__@@@Z
+?wCoGetTreatAsClass@@YGJABU_GUID@@PAU1@@Z
+CoGetTreatAsClass@8
+??0CArrayFValue@@QAE@I@Z
+?AllocClassEntry@CDllCache@@AAEKXZ
+?MakeSecDesc@@YGJPAPAU_SECURITY_DESCRIPTOR@@@Z
+?CreateStorage@CExposedDocFile@@UAGJPBGKKKPAPAUIStorage@@@Z
+?InitFromEntry@CDocFile@@QAEJPAVCStgHandle@@PBVCDfName@@H@Z
+?CreateDocFile@CPubDocFile@@QAEJPBVCDfName@@KPAPAV1@@Z
+??0PTimeEntry@@IAE@K@Z
+?CreateDocFile@CDocFile@@UAEJPBVCDfName@@KKPAPAVPDocFile@@@Z
+??0CUpdateList@@QAE@XZ
+??0CStgHandle@@QAE@XZ
+?SetStateBits@CExposedDocFile@@UAGJKK@Z
+?SetStateBits@CPubDocFile@@QAEJKK@Z
+?CopySStreamToIStream@CExposedDocFile@@AAEJPAVPSStream@@PAUIStream@@@Z
+?MakeCopyFlags@CExposedDocFile@@CGKKPBU_GUID@@@Z
+?CopyDocFileToIStorage@CExposedDocFile@@AAEJPAVPDocFile@@PAUIStorage@@PAPAGK@Z
+?CopyTo@CExposedDocFile@@UAGJKPBU_GUID@@PAPAGPAUIStorage@@@Z
+?SetStateBits@CDocFile@@UAEJKK@Z
+?SetUserFlags@CDirectory@@QAEJKKK@Z
+?SetFatSect@CDIFat@@QAEJKK@Z
+?Remap@CFat@@QAEJKKKPAK000@Z
+?InitCopy@CMStream@@QAEXPAV1@@Z
+?EmptyRegion@CStreamCache@@QAEJKK@Z
+?InitCopy@CPagedVector@@QAEXPAV1@@Z
+??CCBasedFatPtr@@QBEPAVCFat@@XZ
+?CopyPage@CMSFPageTable@@QAEJPAVCPagedVector@@PAVCMSFPage@@PAVCBasedMSFPagePtr@@@Z
+?RemapSelf@CDIFat@@QAEJXZ
+?Lookup@CDIFat@@QAEJKPAK@Z
+?InitCopy@CDirectory@@QAEXPAV1@@Z
+?Fixup@CDIFat@@QAEJPAVCMStream@@@Z
+?Remap@CDIFat@@QAEJKPAK@Z
+?InitCopy@CFat@@QAEXPAV1@@Z
+?Empty@CFat@@QAEXXZ
+?Empty@CPagedVector@@QAEXXZ
+?Empty@CMStream@@QAEXXZ
+?FreePages@CMSFPageTable@@QAEXPAVCPagedVector@@@Z
+?Empty@CDirectory@@QAEXXZ
+??BCBasedVectBitsPtr@@QBEPAUCVectBits@@XZ
+?Empty@CDIFat@@QAEXXZ
+?CopySect@CMStream@@AAEJKKFFPBEPAK@Z
+?SetElementTimes@CExposedDocFile@@UAGJPBGPBU_FILETIME@@11@Z
+?SetElementTimes@CPubDocFile@@QAEJPBVCDfName@@PBU_FILETIME@@11@Z
+?SetBase@CTransactedStream@@QAEJPAVPSStream@@@Z
+??0CBasedTSetMemberPtr@@QAE@PAVPTSetMember@@@Z
+??BCBasedTSetMemberPtr@@QBEPAVPTSetMember@@XZ
+?CreateFromUpdate@PDocFile@@SGJPAVCUpdate@@PAV1@K@Z
+??CCBasedTSetMemberPtr@@QBEPAVPTSetMember@@XZ
+?DestroyEntry@CWrappedDocFile@@UAEJPBVCDfName@@H@Z
+?OnStop@COleCache@@UAGJXZ
+?Release@CDAHolder@@UAGKXZ
+?DuLockContainer@@YGXPAUIOleClientSite@@HPAH@Z
+CoRegisterMessageFilter@8
+?ReleaseEntry@COXIDTable@@QAEXPAUtagOXIDEntry@@@Z
+?FreeCleanupEntries@COXIDTable@@QAEXXZ
+CoDisconnectObject@8
+?VerifyCallerIsClipboardOwner@@YGPAUHWND__@@XZ
+?ThreadCleanup@@YGXXZ
+?ReleaseSCMProxy@CRpcResolver@@QAEXXZ
+?ApartmentUninitialize@@YGXXZ
+?CleanUpLocalServersForApartment@CDllCache@@QAEXXZ
+ChannelThreadUninitialize@0
+ChannelProcessUninitialize@0
+?CleanUpDllsForApartment@CDllCache@@QAEXXZ
+?FreeClassEntry@CDllCache@@AAEXK@Z
+ObjactThreadUninitialize@0
+OleUninitialize@0
+?CleanupTreatAs@@YGXXZ
+?Release@CDllCache@@AAEJK@Z
+?IDTableThreadUninitialize@@YGXXZ
+?CleanUpDllsForApartment@@YGXXZ
+OleReleaseEnumVerbCache@0
+ThreadStop@0
+CoUninitialize@0
+?ReleaseLocalSTAEntry@COXIDTable@@QAEXXZ
+?DllHostProcessUninitialize@@YGXXZ
+?DDEWEP@@YGXH@Z
+??1CArrayFValue@@QAE@XZ
+?ClipboardUninitialize@@YGXXZ
+?ProcessUninitialize@@YGXXZ
+?DestroyRunningObjectTable@@YGXXZ
+?CleanUpDllsForProcess@CDllCache@@QAEXXZ
+CoSetErrorInfo@8
+?DragDropProcessUninitialize@@YGXXZ
+?CleanUpLocalServersForApartment@@YGXXZ
+?DllHostThreadUninitialize@@YGXXZ
+?CleanUpDllsForProcess@@YGXXZ
+?ServerCleanup@CDllHost@@AAEXK@Z
+?UninitMainThreadWnd@@YGXXZ
+?IDTableProcessUninitialize@@YGXXZ
+?wCoUninitialize@@YGXAAVCOleTls@@H@Z
+?DestroyCommonDdeWindow@@YGJXZ
+?Cleanup@CRpcResolver@@QAEXXZ
+?CleanROTForApartment@@YGXXZ
+?UninitializeSecurity@@YGXXZ
+?ClientCleanup@CDllHost@@AAEXXZ
+?ClipboardProcessUninitialize@@YGXXZ
+??1CObjServer@@QAE@XZ
+?FreeExpiredEntries@COXIDTable@@QAEXK@Z
+?FreeDataChain@CPlex@@QAEXXZ
+?RemoveAll@CMapKeyToValue@@QAEXXZ
+?Cleanup@CHashTable@@UAEXP6GXPAUSHashChain@@@Z@Z
+?ReleaseEntry@CPageAllocator@@QAEXPAUtagPageEntry@@@Z
+?Release@CDebugChannelHook@@UAGKXZ
+?ReleaseEntry@CMIDTable@@QAEXPAUtagMIDEntry@@@Z
+?ReleaseLocalMTAEntry@COXIDTable@@QAEXXZ
+?Cleanup@CIPIDTable@@QAEXXZ
+?Cleanup@COXIDTable@@QAEXXZ
+?Release@CObjServer@@UAGKXZ
+?Release@CErrorChannelHook@@UAGKXZ
+?CleanupApartment@CRunningObjectTable@@QAEJK@Z
+RpcServerUnregisterIf@12
+?Revoke@CDllCache@@QAEJK@Z
+?Release@CRemoteUnknown@@UAGKXZ
+?ClearFreeList@CRpcThreadCache@@QAEXXZ
+?CleanupChannelHooks@@YGXXZ
+?Cleanup@CMIDTable@@QAEXXZ
+I_RpcServerStopListening@0
+??1CRunningObjectTable@@QAE@XZ
+?Cleanup@CEventCache@@QAEXXZ
+?UnregisterDcomInterfaces@@YGJXZ
+?Cleanup@working_call@@SGXXZ
+??1CAptCallCtrl@@QAE@XZ
+?UnRegisterInterface@CRIFTable@@QAEXPAUtagRIFEntry@@@Z
+?Cleanup@CPageAllocator@@QAEXXZ
+ServerRevokeClsid@16
+??1CRemoteUnknown@@QAE@XZ
+?IDTableThreadUninitializeHelper@@YGXK@Z
+?Cleanup@CRIFTable@@QAEXXZ
+?Cleanup@CNameHashTable@@QAEXXZ
+RpcSmDestroyClientContext@4
+ServerFreeOXIDAndOIDs@24
+CoRevokeClassObject@4
+?CleanupRIFEntry@@YGXPAUSHashChain@@@Z
+?NotifyStopped@CRpcResolver@@QAEXABU_GUID@@K@Z
+?ExpireEntry@COXIDTable@@AAEXPAUtagOXIDEntry@@@Z
+?ServerFreeOXID@CRpcResolver@@QAEJPAUtagOXIDEntry@@@Z
+?Unreserve@CFreeList@@QAEXI@Z
+OleSave@12
+?Save@COleCache@@UAGJPAUIStorage@@H@Z
+?UpdateCache@COleCache@@UAGJPAUIDataObject@@KPAX@Z
+?GetClassBits@CDefObject@@AAEJPAU_GUID@@@Z
+?GetClassID@CDefObject@@UAGJPAU_GUID@@@Z
+?Save@CDefObject@@UAGJPAUIStorage@@H@Z
+?StmToClipfmt@@YGJAAVCStmBufRead@@PAK1W4TXTTYPE@@@Z
+?Read@CStmBufRead@@QAEJPAXK@Z
+ReadStringStream@8
+?ANSIStmToStr@@YGJAAVCStmBufRead@@PAPADPAK@Z
+?GetSizeMax@CItemMoniker@@UAGJPAT_ULARGE_INTEGER@@@Z
+?SearchShortList@CPSClsidTbl@@AAEPAUtagDWORDPAIR@@K@Z
+?wCoGetPSClsid@@YGJABU_GUID@@PAU1@@Z
+?GetSharedMem@CDllShrdTbl@@AAEPAUSShrdTblHdr@@XZ
+?GetSharedTbl@@YGPAVCDllShrdTbl@@XZ
+?Find@CPSClsidTbl@@QAEJABU_GUID@@PAU2@@Z
+?AddEntry@CRIFTable@@AAEJABU_GUID@@0KPAPAUtagRIFEntry@@@Z
+?RegisterServerInterface@CRIFTable@@AAEJPAUtagRIFEntry@@ABU_GUID@@@Z
+RpcServerRegisterIfEx@24
+??0CRemoteUnknown@@QAE@AAJPAU_GUID@@@Z
+??0CObjServer@@QAE@AAJ@Z
+?Init@CSmMutex@@QAEJPAGH@Z
+?DefaultStringBindings@@YGJXZ
+?AddRef@CRemoteUnknown@@UAGKXZ
+?Grow@CPageAllocator@@AAEXXZ
+?Initialize@CHashTable@@UAEXPAUSHashChain@@@Z
+?GetLegacySecDesc@@YGJPAPAU_SECURITY_DESCRIPTOR@@@Z
+STAChannelInitialize@0
+?AddRef@CDebugChannelHook@@UAGKXZ
+CoInitializeSecurity@36
+?AddMIDEntry@CMIDTable@@AAEJAB_KKPAUtagDUALSTRINGARRAY@@PAPAUtagMIDEntry@@@Z
+?SetLocalOXIDEntry@@YGXPAUtagOXIDEntry@@@Z
+?GetThreadWinstaDesktop@CRpcResolver@@QAEKXZ
+?CopySecDesc@@YGJPAU_SECURITY_DESCRIPTOR@@PAPAU1@@Z
+??0CDllShrdTbl@@QAE@AAJ@Z
+?CreateClsentLSvr@CDllCache@@AAEJKABU_GUID@@PAUIUnknown@@KKK@Z
+?AddEntry@COXIDTable@@QAEJAB_KPAUtagOXID_INFO@@PAUtagMIDEntry@@PAPAUtagOXIDEntry@@@Z
+?InitializeSecurity@@YGJXZ
+?Initialize@CRIFTable@@QAEXXZ
+?QueryInterface@CRemoteUnknown@@UAGJABU_GUID@@PAPAX@Z
+?MarshalInternalObjRef@@YGJAAUtagOBJREF@@ABU_GUID@@PAXKPAPAX@Z
+?Initialize@CMIDTable@@QAEXXZ
+ServerRegisterClsid@24
+CoRegisterClassObject@20
+?Initialize@CIPIDTable@@QAEXXZ
+?Register@CAptCallCtrl@@QAEXPAUHWND__@@II@Z
+?Create@CRunningObjectTable@@SGHXZ
+?Update@CDllShrdTbl@@AAEXXZ
+?AddRef@CObjServer@@UAGKXZ
+ServerAllocateOXIDAndOIDs@40
+?Initialize@COXIDTable@@QAEXXZ
+RpcServerUseProtseqEpW@16
+_ultow
+Connect@72
+?ThreadStart@@YGJXZ
+?FindOrCreateMIDEntry@CMIDTable@@QAEJAB_KPAUtagDUALSTRINGARRAY@@PAPAUtagMIDEntry@@@Z
+?OpenSharedFileMapping@@YGPAXPAGKPAPAX@Z
+?AddRef@CErrorChannelHook@@UAGKXZ
+?RegisterLrpc@@YGJXZ
+RpcBindingFromStringBindingW@8
+_ultoa
+?ServerRegisterOXID@CRpcResolver@@AAEJPAUtagOXIDEntry@@PAKQA_K@Z
+?RegisterServer@CDllCache@@QAEJABU_GUID@@PAUIUnknown@@KKPAK@Z
+?NotifyStarted@CRpcResolver@@QAEJPAU_RegInput@@PAPAU_RegOutput@@@Z
+?InitializeLrpcSecurity@@YGXXZ
+?QueryInterface@CObjServer@@UAGJABU_GUID@@PAPAX@Z
+??0CAptCallCtrl@@QAE@XZ
+?GetRegistrySecDesc@@YGJPAUHKEY__@@PAGPAPAU_SECURITY_DESCRIPTOR@@@Z
+ChannelProcessInitialize@0
+CoRegisterChannelHook@8
+?Initialize@CPageAllocator@@QAEXJJ@Z
+OleInitialize@4
+_onexit
+??0CDllCache@@QAE@XZ
+_mtinitlocks
+atexit
+_cinit
+?MallocInitialize@@YGJH@Z
+_mtinit
+?PrivHeapAlloc@@YGPAXPAXKK@Z
+I_RpcSetWMsgEndpoint@4
+?FindUNCEndServer@@YGXPBGPAG@Z
+?IsRunning@CRunningObjectTable@@UAGJPAUIMoniker@@@Z
+?NoteChangeTime@CRunningObjectTable@@UAGJKPAU_FILETIME@@@Z
+?IrotNoteChangeTime@CRpcResolver@@QAEJPAU_SCMREGKEY@@PAU_FILETIME@@@Z
+IrotNoteChangeTime@16
+?Init@CSimpStorage@@QAEJPBGPAUSSimpDocfileHints@@@Z
+?Init@CSimpStream@@QAEJPAUCSimpStorage@@PAXK@Z
+?DfCreateSimpDocfile@@YGJPBGKKPAPAUIStorage@@@Z
+?ConvertSect@@YGKK@Z
+?CreateStream@CSimpStorage@@UAGJPBGKKKPAPAUIStream@@@Z
+?Release@CSimpStream@@UAGKXZ
+?Release@CSimpStorage@@UAGKXZ
+?SetSize@CSimpStream@@UAGJT_ULARGE_INTEGER@@@Z
+?ReleaseCurrentStream@CSimpStorage@@QAEXXZ
+?Commit@CSimpStorage@@UAGJK@Z
+?BuildTree@CSimpStorage@@AAEKPAVCDirEntry@@KK@Z
+?Seek@CSimpStream@@UAGJT_LARGE_INTEGER@@KPAT_ULARGE_INTEGER@@@Z
+?Write@CSimpStream@@UAGJPBXKPAK@Z
+?Read@CSimpStream@@UAGJPAXKPAK@Z
+?AddRef@CSimpStorage@@UAGKXZ
+?OpenStream@CSimpStorage@@UAGJPBGPAXKKPAPAUIStream@@@Z
+?SetClass@CSimpStorage@@UAGJABU_GUID@@@Z
+?SetFileLockBytesTime@CMStream@@QAEJW4WHICHTIME@@U_FILETIME@@@Z
+?SetTime@CFileStream@@QAEJW4WHICHTIME@@U_FILETIME@@@Z
+?GetCommitInfo@CWrappedDocFile@@UAEXPAK0@Z
+?GetCommitSize@CPubDocFile@@IAEJPAK@Z
+?GetCommitInfo@CTransactedStream@@UAEXPAK0@Z
+?PrepareForOverwrite@CPubDocFile@@IAEJXZ
+?ReleaseLocks@CRootPubDocFile@@QAEXPAUILockBytes@@@Z
+?SetAllocatorState@CPerContext@@QAEJPAPAV1@PAVCSmAllocator@@@Z
+?InitNew@CDirectory@@QAEJPAVCMStream@@@Z
+??DCBasedILockBytesPtrPtr@@QBEAAPAUILockBytes@@XZ
+?vdtor@CPubDocFile@@UAEXXZ
+??CCBasedFreeBlockPtr@@QBEPAUSFreeBlock@@XZ
+?SetStateBits@CWrappedDocFile@@UAEJKK@Z
+?FindGreaterEntry@CWrappedDocFile@@UAEJPBVCDfName@@PAUSIterBuffer@@PAUtagSTATSTG@@@Z
+?RevertUpdate@CWrappedDocFile@@AAEXPAVCUpdate@@@Z
+??1CSafeRefCount@@UAE@XZ
+??_ECDAHolder@@EAEPAXI@Z
+??1CDAHolder@@EAE@XZ
+?Release@COAHolder@@UAGKXZ
+?Stop@CDefObject@@QAEJXZ
+??1COAHolder@@EAE@XZ
+??_GCOAHolder@@EAEPAXI@Z
+?Extend@CFat@@AAEJKK@Z
+StgIsStorageFile@4
+?Release@CEnumVerb@@EAGKXZ
+?InitDllent@CDllCache@@AAEXKK@Z
+?Init@CDllAptEntry@@QAEXK@Z
+?CleanUpForApartmentByDllent@CDllCache@@AAEHKAAK@Z
+?FreeAptEntry@CDllCache@@AAEXKK@Z
+?FreeDllPathEntry@CDllCache@@AAEXK@Z
+?InstallMsgFilter@CAptCallCtrl@@QAEPAUIMessageFilter@@PAU2@@Z
+?UtReleaseStatData@@YGXPAUtagSTATDATA@@@Z
+??1CEnumSTATDATA@@AAE@XZ
+?EnumAndAdvise@CDataAdviseCache@@QAEJPAUIDataObject@@H@Z
+?EnumAdvise@CDAHolder@@UAGJPAPAUIEnumSTATDATA@@@Z
+?Release@CEnumSTATDATA@@UAGKXZ
+?Next@CEnumSTATDATA@@UAGJKPAUtagSTATDATA@@PAK@Z
+?AddRef@CDAHolder@@UAGKXZ
+??0CEnumSTATDATA@@QAE@PAVCDAHolder@@H@Z
+?wCoIsOle1Class@@YGHABU_GUID@@@Z
+CoIsOle1Class@4
+?wUUIDFromString@@YGHPBGPAU_GUID@@@Z
+?wCLSIDFromString@@YGJPAGPAU_GUID@@@Z
+?wGUIDFromString@@YGHPBGPAU_GUID@@@Z
+CLSIDFromString@8
+?wStringFromCLSID@@YGJABU_GUID@@PAPAG@Z
+?wCLSIDFromOle1Class@@YGJPBGPAU_GUID@@H@Z
+StringFromCLSID@8
+CoOpenClassKey@8
+wcstol
+CreateDataAdviseHolder@4
+?UtCopyFormatEtc@@YGHPAUtagFORMATETC@@0@Z
+??0CDAHolder@@QAE@XZ
+?Advise@CDAHolder@@UAGJPAUIDataObject@@PAUtagFORMATETC@@KPAUIAdviseSink@@PAK@Z
+?Release@CDefObject@@W3AGKXZ
+?DuSetClientSite@@YGJHPAUIOleClientSite@@PAPAU1@PAH@Z
+OleRegGetUserType@12
+?GetOrLoadClass@CDllCache@@QAEPAUIUnknown@@ABU_GUID@@0HHKKAAJ@Z
+?SearchCacheOrLoadInProc@@YGPAUIUnknown@@ABU_GUID@@0HHKKAAJ@Z
+?GetClassInterface@CDllCache@@QAEPAUIUnknown@@KKABU_GUID@@0AAJ@Z
+?MakeValidInApartment@CDllCache@@AAEJK@Z
+?GetClass@CDllCache@@QAEJABU_GUID@@0HHPAPAUIUnknown@@@Z
+?Search@CDllCache@@AAEKABU_GUID@@KK@Z
+?CreateClsentInProc@CDllCache@@AAEJKKKKABU_GUID@@@Z
+?SearchForDll@CDllCache@@AAEKPBG@Z
+iswctype
+?Hash@CDllCache@@AAEKPAG@Z
+?Add@CDllCache@@QAEPAUIUnknown@@ABU_GUID@@0KPBGHHAAJ@Z
+?wQueryStripRegValue@@YGJPAUHKEY__@@PBGPAGPAJ@Z
+?wGetDllInfo@@YGJPAUHKEY__@@PBGPAGPAJPAK@Z
+?Release@CDefObject@@W7AGKXZ
+?RemQIAndUnmarshal@CStdMarshal@@AAEJGPAU_GUID@@PAUtagSQIResult@@@Z
+?GetStdIdFromIPID@@YGPAVCStdIdentity@@ABU_GUID@@@Z
+?GetSecureRemUnk@CStdMarshal@@QAEJPAPAUIRemUnknown@@PAUtagOXIDEntry@@@Z
+?RemQueryInterface@CRemoteUnknown@@UAGJABU_GUID@@KGPAU2@PAPAUtagREMQIRESULT@@@Z
+?RemoteQueryInterface@@YGJPAUIRemUnknown@@PAUtagIPIDEntry@@GPAU_GUID@@PAPAUtagREMQIRESULT@@H@Z
+OleRun@4
+?Run@CDefObject@@UAGJPAUIBindCtx@@@Z
+?OnRun@COleCache@@UAGJPAUIDataObject@@@Z
+?Advise@CDefObject@@UAGJPAUIAdviseSink@@PAK@Z
+?AddRef@CDefObject@@W7AGKXZ
+?NewAptEntries@CDllCache@@AAEHK@Z
+?Create@CDllAptEntry@@QAEXK@Z
+?AllocDllPathEntry@CDllCache@@AAEKXZ
+?CreateDllent@CDllCache@@AAEJKPBGHP6GJABU_GUID@@1PAPAX@ZP6GJXZPAUHINSTANCE__@@@Z
+?AllocAptEntry@CDllCache@@AAEKK@Z
+ReadFmtUserTypeStg@12
+??0COleCache@@QAE@PAUIUnknown@@ABU_GUID@@@Z
+?AddRef@CDefObject@@W3AGKXZ
+OleGetAutoConvert@8
+?CreateDataAdviseCache@CDataAdviseCache@@SGJPAPAV1@@Z
+?wCreateObject@@YGJU_GUID@@ABU1@PAUIOleClientSite@@PAUIStorage@@GPAPAX@Z
+??0CDataAdviseCache@@AAE@XZ
+?GrowCacheList@COleCache@@AAEHXZ
+?FindObjectFormat@COleCache@@AAEXPAUIStorage@@@Z
+?QueryRemoteInterfaces@CStdMarshal@@QAEJGPAU_GUID@@PAUtagSQIResult@@@Z
+OleRegGetMiscStatus@12
+?RegisterClientInterface@CRIFTable@@AAEJPAUtagRIFEntry@@ABU_GUID@@@Z
+?GetMiscStatus@CDefObject@@UAGJKPAK@Z
+?SetClientSite@CDefObject@@UAGJPAUIOleClientSite@@@Z
+??0CDefObject@@AAE@PAUIUnknown@@@Z
+?Create@CDefObject@@SGPAUIUnknown@@PAU2@ABU_GUID@@KPAUIClassFactory@@@Z
+?GetUserType@CDefObject@@UAGJKPAPAG@Z
+?CacheAccess@@YGXPAU_SID@@H@Z
+?ReconnectProxies@CStdMarshal@@QAEXXZ
+?CreateServer@CStdIdentity@@UAGJABU_GUID@@KPAX@Z
+?CreateInstance@CRpcResolver@@QAEJPAU_COSERVERINFO@@PAU_GUID@@KK1PAPAUtagMInterfacePointer@@PAJPAKPAPAG@Z
+?MarshalHelperMulti@@YGJPAUIUnknown@@KPAU_GUID@@PAPAUtagMInterfacePointer@@PAJ@Z
+?BindToSCMProxy@CRpcResolver@@QAEJXZ
+?CheckObjactAccess@@YGHXZ
+?ObjectServerCreateInstance@CObjServer@@UAGJPBU_GUID@@KPAU2@PAPAUtagMInterfacePointer@@PAJPAK@Z
+?GetInstanceHelperMulti@@YGJPAUIClassFactory@@KPAU_GUID@@PAPAUtagMInterfacePointer@@PAJPAPAUIUnknown@@@Z
+?Release@CAdvSinkImpl@CDefObject@@UAGKXZ
+?QueryInterface@CAdvSinkImpl@CDefObject@@UAGJABU_GUID@@PAPAX@Z
+?AddRef@CAdvSinkImpl@CDefObject@@UAGKXZ
+?InitFromGlobal@CFileStream@@QAEXPAVCGlobalFileStream@@@Z
+?GetDocFile@CWrappedDocFile@@UAEJPBVCDfName@@KPAPAVPDocFile@@@Z
+?OpenStorage@CExposedDocFile@@UAGJPBGPAUIStorage@@KPAPAGKPAPAU2@@Z
+?GetDocFile@CPubDocFile@@QAEJPBVCDfName@@KPAPAV1@@Z
+?GetDocFile@CDocFile@@UAEJPBVCDfName@@KPAPAVPDocFile@@@Z
+?Reduce@CBaseMoniker@@UAGJPAUIBindCtx@@KPAPAUIMoniker@@1@Z
+?ClipboardInitialize@@YGHXZ
+?UtGetPresStreamName@@YGXPAGH@Z
+?UtRemoveExtraOlePresStreams@@YGXPAUIStorage@@H@Z
+?GetData@CDefObject@@UAGJPAUtagFORMATETC@@PAUtagSTGMEDIUM@@@Z
+?GetData@CCacheDataImpl@COleCache@@UAGJPAUtagFORMATETC@@PAUtagSTGMEDIUM@@@Z
+?MakeFakeObjRef@@YGJAAUtagOBJREF@@PAUtagOXIDEntry@@ABU_GUID@@2@Z
+?MakeRemUnk@COXIDTable@@AAEJPAUtagOXIDEntry@@@Z
+?SetAuthnService@@YGJPAXPAUtagOXID_INFO@@PAUtagOXIDEntry@@@Z
+ClientResolveOXID@28
+RpcBindingSetAuthInfoExW@28
+?CheckClientMswmsg@@YGJPAGPAK@Z
+?ServerGetReservedID@CRpcResolver@@QAEJPA_K@Z
+?UnmarshalInternalObjRef@@YGJAAUtagOBJREF@@PAPAX@Z
+?Unadvise@COAHolder@@UAGJK@Z
+?QueryInterface@CCacheUnkImpl@COleCache@@UAGJABU_GUID@@PAPAX@Z
+?Uncache@COleCache@@UAGJK@Z
+?Detach@COleCache@@AAEPAVCCacheNode@@K@Z
+?SetAdvise@CCacheViewImpl@COleCache@@UAGJKKPAUIAdviseSink@@@Z
+?OnStop@CCacheNode@@QAEXXZ
+?DiscardHPRES@CMfObject@@UAGXXZ
+?Release@COleCache@@UAGKXZ
+?Release@COleCache@@W3AGKXZ
+?Uninitialize@CCacheNode@@AAEXXZ
+??1CCacheNode@@AAE@XZ
+?Delete@CCacheNode@@QAEXXZ
+?Unadvise@CDefObject@@UAGJK@Z
+?Release@CCacheViewImpl@COleCache@@UAGKXZ
+?Release@CCacheNode@@UAGKXZ
+?TearDownAdviseConnection@CCacheNode@@AAEJXZ
+?CanRetrieveOle2FromOle1@@YGHI@Z
+?QueryGetData@CClipDataObject@@UAGJPAUtagFORMATETC@@@Z
+?OleIsClipboardFormatAvailable@CClipDataObject@@AAEHI@Z
+?wQueryLinkFormats@@YGGPAUIDataObject@@@Z
+OleQueryLinkFromData@4
+?AddRef@CClipDataObject@@UAGKXZ
+?OnClose@CAdvSinkImpl@CDefObject@@UAGXXZ
+?SendOnClose@COAHolder@@UAGJXZ
+?Unadvise@CDAHolder@@UAGJK@Z
+IAdviseSink_RemoteOnClose_Thunk@4
+IAdviseSink_RemoteOnClose_Proxy@4
+IAdviseSink_OnClose_Stub@4
+IAdviseSink_OnClose_Proxy@4
+?Load@CDllCache@@AAEJPBGPAP6GJABU_GUID@@1PAPAX@ZPAP6GJXZHPAPAUHINSTANCE__@@@Z
+ICoGetClassObject@20
+?IsUpToDate@CDefObject@@UAGJXZ
+?IsDirty@CDefObject@@UAGJXZ
+?IsDirty@COleCache@@UAGJXZ
+?HandsOffStorage@COleCache@@UAGJXZ
+?HandsOffStorage@CDefObject@@UAGJXZ
+?IsDirty@CDefLink@@UAGJXZ
+?Release@CPrivUnknown@CDefLink@@EAGKXZ
+?Release@CDefLink@@UAGKXZ
+?Release@CCompositeMoniker@@EAGKXZ
+?QueryInterface@CCompositeMoniker@@EAGJABU_GUID@@PAPAX@Z
+?QueryInterface@CPrivUnknown@CDefLink@@EAGJABU_GUID@@PAPAX@Z
+?QueryInterface@CDefLink@@UAGJABU_GUID@@PAPAX@Z
+?QueryInterface@CDefLink@@W3AGJABU_GUID@@PAPAX@Z
+?AddRef@CPrivUnknown@CDefLink@@EAGKXZ
+??1CCompositeMoniker@@QAE@XZ
+??0CCompositeMonikerEnum@@AAE@HPAVCCompositeMoniker@@@Z
+?Enum@CCompositeMoniker@@EAGJHPAPAUIEnumMoniker@@@Z
+??1CCompositeMonikerEnum@@AAE@XZ
+?GetMoniker@CDefLink@@UAGJKKPAPAUIMoniker@@@Z
+?Release@CCompositeMonikerEnum@@UAGKXZ
+?Create@CCompositeMonikerEnum@@SGPAUIEnumMoniker@@HPAVCCompositeMoniker@@@Z
+?GetNext@CCompositeMonikerEnum@@AAEPAUIMoniker@@PAU2@@Z
+?Release@CDefLink@@W7AGKXZ
+?Pop@CCompositeMonikerEnum@@AAEPAUIMoniker@@XZ
+?AddRef@CCompositeMonikerEnum@@UAGKXZ
+?Push@CCompositeMonikerEnum@@AAEHPAVCCompositeMoniker@@@Z
+memmove
+?Next@CCompositeMonikerEnum@@UAGJKPAPAUIMoniker@@PAK@Z
+?GetUpdateOptions@CDefLink@@UAGJPAK@Z
+?SetParent@CTrackingCompositeMoniker@@QAEXPAVCCompositeMoniker@@@Z
+?IsSystemMoniker@CItemMoniker@@UAGJPAK@Z
+CreateGenericComposite@12
+?IsReduced@@YGHPAUIMoniker@@@Z
+?IsSystemMoniker@CFileMoniker@@UAGJPAK@Z
+?ComposeWith@CFileMoniker@@UAGJPAUIMoniker@@HPAPAU2@@Z
+??0CCompositeMoniker@@QAE@XZ
+?GetMonikerType@@YGKPAUIMoniker@@@Z
+?Create@CCompositeMoniker@@SGPAV1@PAUIMoniker@@0@Z
+?Initialize@CCompositeMoniker@@QAEHPAUIMoniker@@0@Z
+Concatenate@12
+?IsAntiMoniker@@YGPAVCAntiMoniker@@PAUIMoniker@@@Z
+?FindExtent@CExtentList@@QAEPAU_MONIKEREXTENT@@G@Z
+?GetClassID@CCompositeMoniker@@EAGJPAU_GUID@@@Z
+?IrotGetTimeOfLastChange@CRpcResolver@@QAEJPAU_MnkEqBuf@@PAU_FILETIME@@@Z
+IrotGetTimeOfLastChange@24
+?GetTimeOfLastChange@CCompositeMoniker@@EAGJPAUIBindCtx@@PAUIMoniker@@PAU_FILETIME@@@Z
+?Release@CCompositeMoniker@@G3AGKXZ
+?GetComparisonData@CCompositeMoniker@@EAGJPAEKPAK@Z
+?Reduce@CCompositeMoniker@@EAGJPAUIBindCtx@@KPAPAUIMoniker@@1@Z
+?AllButFirst@CCompositeMoniker@@QAEPAUIMoniker@@XZ
+?SetUpdateTimes@CDefLink@@AAEJXZ
+?ComposeWith@CItemMoniker@@UAGJPAUIMoniker@@HPAPAU2@@Z
+?IsSystemMoniker@CCompositeMoniker@@EAGJPAK@Z
+?GetAbsMkFromRel@CDefLink@@AAEJPAPAUIMoniker@@0@Z
+?AllButLast@CCompositeMoniker@@QAEPAUIMoniker@@XZ
+?Last@CCompositeMoniker@@QAEPAUIMoniker@@XZ
+?First@CCompositeMoniker@@QAEPAUIMoniker@@XZ
+?Release@CTrackingFileMoniker@@UAGKXZ
+?EnableTracking@CFileMoniker@@UAGJPAUIMoniker@@K@Z
+?Release@CTrackingCompositeMoniker@@UAGKXZ
+?EnableTracking@CDefLink@@AAEJPAUIMoniker@@K@Z
+?EnableTracking@CTrackingFileMoniker@@UAGJPAUIMoniker@@K@Z
+?EnableTracking@CTrackingCompositeMoniker@@UAGJPAUIMoniker@@K@Z
+OleSaveToStream@8
+?GetOleDelegate@CDefLink@@QAEPAUIOleObject@@XZ
+WriteClassStm@8
+?Release@CDefLink@@WM@AGKXZ
+?IsRunning@CDefLink@@UAGHXZ
+?SaveCompleted@CDefLink@@UAGJPAUIStorage@@@Z
+?DetermineUnicodePath@CFileMoniker@@QAEJPADAAPAGAAG@Z
+?ReadAnsiStringStream@@YGJPAUIStream@@AAPADAAG@Z
+?MnkMultiToUnicode@@YGJPADAAPAGKAAGI@Z
+?ExtractUnicodeString@@YGJPADGAAPAGAAG@Z
+?UnmarshalInterface@CMarshalImplPStream@@UAGJPAUIStream@@ABU_GUID@@PAPAX@Z
+?Load@CFileMoniker@@UAGJPAUIStream@@@Z
+?Load@CItemMoniker@@UAGJPAUIStream@@@Z
+?IsEqual@CFileMoniker@@UAGJPAUIMoniker@@@Z
+?UpdateRelMkFromAbsMk@CDefLink@@AAEXPAUIMoniker@@@Z
+?RelativePathTo@CFileMoniker@@UAGJPAUIMoniker@@PAPAU2@@Z
+MonikerRelativePathTo@16
+?HandsOffStorage@CDefLink@@UAGJXZ
+?Count@CCompositeMoniker@@QAEKXZ
+?SetSize@CMemStm@@UAGJT_ULARGE_INTEGER@@@Z
+?Write@CMemStm@@UAGJPBXKPAK@Z
+?Save@CCompositeMoniker@@EAGJPAUIStream@@H@Z
+?GetDataDelegate@CDefLink@@QAEPAUIDataObject@@XZ
+?GetDisplayName@CCompositeMoniker@@EAGJPAUIBindCtx@@PAUIMoniker@@PAPAG@Z
+?GetDisplayName@CItemMoniker@@UAGJPAUIBindCtx@@PAUIMoniker@@PAPAG@Z
+?GetSourceMoniker@CDefLink@@UAGJPAPAUIMoniker@@@Z
+?GetSourceDisplayName@CDefLink@@UAGJPAPAG@Z
+?PutExtent@CExtentList@@QAEJPBU_MONIKEREXTENT@@@Z
+WriteM1ClassStmBuf@8
+?Init@CStmBufWrite@@QAEXPAUIStream@@@Z
+?UpdateUserClassID@CDefLink@@AAEXXZ
+?WriteLong@CStmBufWrite@@QAEJJ@Z
+GetHGlobalFromStream@8
+?DeleteExtent@CExtentList@@QAEJG@Z
+?Save@CDefLink@@UAGJPAUIStorage@@H@Z
+?AddRef@CExposedStream@@UAGKXZ
+?UpdateAutoOnSave@CDefLink@@AAEXXZ
+?GetClassID@CDefLink@@UAGJPAU_GUID@@@Z
+?OleGetShellLink@@YGPAXXZ
+?SetPathShellLink@CFileMoniker@@AAEJXZ
+?GetShellLink@CFileMoniker@@AAEJXZ
+?GetUserClassID@CDefLink@@UAGJPAU_GUID@@@Z
+?SendOnLinkSrcChange@COAHolder@@QAEJPAUIMoniker@@@Z
+MKVDefaultHashKey@8
+?GetAssocKeyPtr@CMapKeyToValue@@ABEXPAUCAssoc@1@PAPAXPAI@Z
+?GetAssocValuePtr@CMapKeyToValue@@ABEXPAUCAssoc@1@PAPAX@Z
+?GetAssocAt@CMapKeyToValue@@ABEPAUCAssoc@1@PAXIAAI@Z
+?SetAssocValue@CMapKeyToValue@@ABEXPAUCAssoc@1@PAX@Z
+?SetAt@CMapKeyToValue@@QAEHPAXI0@Z
+?WorkerThreadLoop@CRpcResolver@@AAGKPAX@Z
+?FindGreaterEntry@CDocFile@@UAEJPBVCDfName@@PAUSIterBuffer@@PAUtagSTATSTG@@@Z
+?StatEntry@CDirectory@@QAEJKPAUSIterBuffer@@PAUtagSTATSTG@@@Z
+?FindGreaterEntry@CDirectory@@QAEJKPBVCDfName@@PAK@Z
+?wBindIfRunning@@YGXPAUIUnknown@@@Z
+?OleLoadWithoutBinding@@YGJPAUIStorage@@ABU_GUID@@PAUIOleClientSite@@PAPAX@Z
+?IsAtOrAbove@CPubDocFile@@QAEHPAV1@@Z
+?GetClipFormat@@YGJPAVCompObjStmData@@PAK1@Z
+ReadOleStg@24
+?Load@CDefObject@@UAGJPAUIStorage@@@Z
+OleDoAutoConvert@8
+?Load@COleCache@@UAGJPAUIStorage@@@Z
+CoIsHashedOle1Class@4
+?wCompareDllName@@YGHPBG0K@Z
+CoBuildVersion@0
+_cexit
+_mtdeletelocks
+??1CReservedMemory@@QAE@XZ
+?MallocUninitialize@@YGHXZ
+?IsTaskName@@YGHPBG@Z
+?Remove@CDllCache@@QAEXK@Z
+?GetAllTimes@CWrappedDocFile@@UAEJPAU_FILETIME@@00@Z
+?CreateDocFile@CWrappedDocFile@@UAEJPBVCDfName@@KKPAPAVPDocFile@@@Z
+??BCBasedFreeBlockPtr@@QBEPAUSFreeBlock@@XZ
+?RevertFromAbove@CPubDocFile@@UAEXXZ
+??1CDataAdviseCache@@QAE@XZ
+??1COleCache@@QAE@XZ
+?Release@CCacheUnkImpl@COleCache@@UAGKXZ
+?DeleteAll@COleCache@@AAEXXZ
+??1CDefObject@@EAE@XZ
+??_ECDefObject@@EAEPAXI@Z
+?CleanupForDelete@CDefObject@@AAEXXZ
+?Next@CCacheEnum@@UAGJKPAUtagSTATDATA@@PAK@Z
+?EnumCache@COleCache@@UAGJPAPAUIEnumSTATDATA@@@Z
+??0CCacheEnum@@QAE@PAVCOleCache@@KH@Z
+??1CCacheEnum@@AAE@XZ
+?DetachCacheEnum@COleCache@@AAEXPAVCCacheEnum@@@Z
+?Release@CCacheEnum@@UAGKXZ
+?Close@CDefObject@@UAGJK@Z
+?AddRef@CEnumVerb@@EAGKXZ
+?EnumVerbs@CDefObject@@UAGJPAPAUIEnumOLEVERB@@@Z
+OleRegEnumVerbs@8
+ReadMonikerStm@8
+OleLoad@16
+MakeVerbList@12
+??0CEnumVerb@@AAE@PAUVerbList@@J@Z
+IUnknown_QueryInterface_Proxy@12
+HGLOBAL_UserMarshal@12
+?WdtpGlobalUnmarshal@@YGPAEPAKPAEPAPAXH@Z
+HGLOBAL_UserSize@12
+?WdtpRemotableHandle_UserUnmarshal@@YGPAEPAKPAE0@Z
+?WdtpRemotableHandle_UserSize@@YGKPAKK0@Z
+?WdtpRemotableHandle_UserMarshal@@YGPAEPAKPAE0@Z
+HMENU_UserFree@8
+?wGetOleMenuPtr@@YGPAUtagOLEMENU@@PAX@Z
+HMENU_UserSize@12
+HMENU_UserUnmarshal@12
+HMENU_UserMarshal@12
+OleSetMenuDescriptor@20
+HWND_UserUnmarshal@12
+HWND_UserFree@8
+HWND_UserSize@12
+HWND_UserMarshal@12
+?DoVerb@CDefObject@@UAGJJPAUtagMSG@@PAUIOleClientSite@@JPAUHWND__@@PBUtagRECT@@@Z
+IsEqualGUID@8
+IsAccelerator@16
+?IsMDIAccelerator@@YGHPAUtagMSG@@PAG@Z
+OleTranslateAccelerator@12
+?OnEnterMenuMode@CFrameFilter@@QAEXXZ
+?IsObjectMenu@CFrameFilter@@QAEXII@Z
+?OnSysCommand@CFrameFilter@@QAEJIJ@Z
+?OnExitMenuMode@CFrameFilter@@QAEXXZ
+HACCEL_UserMarshal@12
+OleCreateMenuDescriptor@8
+??0CFrameFilter@@QAE@PAUHWND__@@0@Z
+?Create@CFrameFilter@@SGJPAUtagOLEMENU@@PAUHMENU__@@PAUHWND__@@2PAUIOleInPlaceFrame@@PAUIOleInPlaceActiveObject@@@Z
+HACCEL_UserUnmarshal@12
+HGLOBAL_UserFree@8
+HGLOBAL_UserUnmarshal@12
+HACCEL_UserSize@12
+HACCEL_UserFree@8
+OleDestroyMenuDescriptor@4
+??_ECFrameFilter@@UAEPAXI@Z
+?RemoveWndProc@CFrameFilter@@QAEXXZ
+??1CFrameFilter@@UAE@XZ
+?Create@CPlex@@SGPAU1@AAPAU1@II@Z
+?NewAssoc@CMapKeyToValue@@AAEPAUCAssoc@1@IPAXI0@Z
+?Advise@CDataAdviseCache@@QAEJPAUIDataObject@@PAUtagFORMATETC@@KPAUIAdviseSink@@PAK@Z
+?InitHashTable@CMapKeyToValue@@AAEHXZ
+?SetAssocKey@CMapKeyToValue@@ABEHPAUCAssoc@1@PAXI@Z
+?DAdvise@CDefObject@@UAGJPAUtagFORMATETC@@KPAUIAdviseSink@@PAK@Z
+?wValidateFormatEtcEx@@YGJKPAKPAUtagFORMATETC@@1PAPAU1@PAH@Z
+?wValidateCreateParams@@YGJKKKPAKPAUtagFORMATETC@@PAUIAdviseSink@@0PAUIOleClientSite@@PAUIStorage@@@Z
+?wValidateAdvfEx@@YGJKPAK@Z
+?SetBlanket@CClientSecurity@@UAGJPAUIUnknown@@KKPAGKKPAXK@Z
+?FindIPIDEntryByInterface@CStdMarshal@@QAEJPAXPAPAUtagIPIDEntry@@@Z
+?AddRef@CStdIdentity@@WDM@AGKXZ
+?MakeSCMProxy@@YGJPAUtagDUALSTRINGARRAY@@ABU_GUID@@PAPAX@Z
+?Release@CStdIdentity@@WDM@AGKXZ
+CoSetProxyBlanket@32
+?CMalloc_AddRef@@YGKPAUIMalloc@@@Z
+?RevertFromAbove@CPubStream@@UAEXXZ
+?OnDataChange@CCacheNode@@UAGXPAUtagFORMATETC@@PAUtagSTGMEDIUM@@@Z
+?EndCommitFromChild@CWrappedDocFile@@UAEXKPAV1@@Z
+?SaveCompleted@CCacheNode@@QAEXHH@Z
+?BeginCommitFromChild@CWrappedDocFile@@UAEJAAVCUpdateList@@KPAV1@@Z
+?Save@CCacheNode@@QAEJPAUIStorage@@HHHHPAH@Z
+?GetPresObj@CCacheNode@@QAEPAUIOlePresObj@@XZ
+?BeginCommit@CDeltaList@@QAEXPAVCTransactedStream@@@Z
+?SetPresBitsPos@CCacheNode@@AAEXPAUIStream@@@Z
+?OnRun@CCacheNode@@QAEKPAUIDataObject@@@Z
+?CreateOlePresObject@CCacheNode@@AAEJPAPAUIOlePresObj@@H@Z
+?BeginCommitFromChild@CTransactedStream@@UAEJKPAVCDeltaList@@PAV1@@Z
+CoFreeAllLibraries@0
+?SetDataWDO@CCacheNode@@QAEJPAUtagFORMATETC@@PAUtagSTGMEDIUM@@HPAUIDataObject@@@Z
+?OnChange@COleCache@@AAEXKJH@Z
+?CheckTymedCFCombination@@YGJPAUtagFORMATETC@@@Z
+?QueryInterface@CCacheNode@@UAGJABU_GUID@@PAPAX@Z
+?AddRef@CCacheNode@@UAGKXZ
+?GetFormatEtc@CCacheNode@@QAEPBUtagFORMATETC@@XZ
+?Cache@COleCache@@UAGJPAUtagFORMATETC@@KPAK@Z
+?GetPresObj@COleCache@@AAEPAUIOlePresObj@@KJGPAUtagDVTARGETDEVICE@@PAK@Z
+?GetAt@COleCache@@AAEPAVCCacheNode@@PAUtagFORMATETC@@PAK@Z
+?EndCommit@CDeltaList@@QAEXPAV1@K@Z
+OleInitializeWOW@8
+?SetColorScheme@CDefObject@@UAGJPAUtagLOGPALETTE@@@Z
+?SetOleThunkWowPtr@@YGXPAVOleThunkWOW@@@Z
+WriteClipformatStm@8
+CoInitializeWOW@8
+?CreatePresObject@CCacheNode@@QAEJPAUIDataObject@@H@Z
+CoUnmarshalHresult@8
+?Initialize@CCacheNode@@AAEXKPAVCOleCache@@@Z
+?GetAt@COleCache@@AAEPAVCCacheNode@@KJGPAUtagDVTARGETDEVICE@@PAK@Z
+CoUnloadingWOW@4
+?TLSIsWOWThread@@YGEXZ
+?TLSIsThreadDetaching@@YGEXZ
+?Attach@COleCache@@AAEKPAVCCacheNode@@@Z
+?QueryFormatSupport@CCacheNode@@AAEHPAUIDataObject@@@Z
+?SetupAdviseConnection@CCacheNode@@AAEJXZ
+?GetDeltaList@CTransactedStream@@UAEPAVCDeltaList@@XZ
+?Update@CCacheNode@@QAEJPAUIDataObject@@K@Z
+?IsValidInApartment@CDllCache@@AAEHKK@Z
+?EndCommitFromChild@CTransactedStream@@UAEXKPAV1@@Z
+?GetCopyOfHPRES@CMfObject@@AAEPAXXZ
+?Save@CMfObject@@UAGJPAUIStream@@@Z
+?IsBlank@CMfObject@@UAGHXZ
+?UtWriteOlePresStmHeader@@YGJPAUIStream@@PAUtagFORMATETC@@K@Z
+?UtHMFToMFStm@@YGJPAPAXKPAUIStream@@@Z
+?UtGetHMFPICT@@YGPAXPAUHMETAFILE__@@HKK@Z
+?UtCompareTargetDevice@@YGHPAUtagDVTARGETDEVICE@@0@Z
+?StSetSize@@YGJPAUIStream@@KH@Z
+?SetDataWDO@CMfObject@@UAGJPAUtagFORMATETC@@PAUtagSTGMEDIUM@@HPAUIDataObject@@@Z
+?MfGetSize@@YGKPAPAX@Z
+??0CMfObject@@QAE@PAVCCacheNode@@KH@Z
+?ChangeData@CMfObject@@AAEJPAXH@Z
+?GetHmfp@CMfObject@@AAEPAXXZ
+?GetData@CMfObject@@UAGJPAUtagFORMATETC@@PAUtagSTGMEDIUM@@@Z
+CLSIDFromProgID@8
+CLSIDFromOle1Class@12
+?UtGetUNICODEData@@YGJKPADPAGPAPAG@Z
+?GetUNICODEUserType@@YGJPAVCompObjStmData@@PAPAG@Z
+??0CCacheNode@@QAE@PAVCOleCache@@@Z
+?GetStg@COleCache@@AAEPAUIStorage@@XZ
+?UtReadOlePresStmHeader@@YGJPAUIStream@@PAUtagFORMATETC@@PAKPAH@Z
+SetConvertStg@8
+?UtQueryPictFormat@@YGHPAUIDataObject@@PAUtagFORMATETC@@@Z
+?CopyStatData@CCacheNode@@QAEXPAUtagSTATDATA@@@Z
+?DoConversionIfSpecialClass@CDefObject@@AAEJPAUIStorage@@@Z
+ReadClipformatStm@8
+?SetAdvf@CCacheNode@@QAEJK@Z
+?GetAdvf@CCacheNode@@QAEKXZ
+?GetStm@CCacheNode@@QAEPAUIStream@@HK@Z
+?Load@CCacheNode@@QAEJPAUIStream@@H@Z
+?SetMoniker@CDefObject@@UAGJKPAUIMoniker@@@Z
+?GetSlowTimeFactor@@YGKXZ
+?GetRefCount@CEnumVerb@@AAEKXZ
+?IsCallerLocalSystem@@YGHXZ
+CoGetCallContext@8
+CoImpersonateClient@0
+?RundownOid@CRemoteUnknown@@UAGJKQA_KQAE@Z
+RpcRevertToSelfEx@4
+CoRevertToSelf@0
+?ImpersonateClient@CServerSecurity@@UAGJXZ
+?ServerCanRundownOID@CRpcResolver@@QAEHAB_K@Z
+?UnbindSource@CDefLink@@UAGJXZ
+?DestroyAllChildren@CDirectory@@QAEJK@Z
+?OnDataChange@CAdvSinkImpl@CDefLink@@UAGXPAUtagFORMATETC@@PAUtagSTGMEDIUM@@@Z
+IAdviseSink_OnRename_Stub@8
+IAdviseSink_RemoteOnRename_Proxy@8
+IAdviseSink_OnRename_Proxy@8
+IAdviseSink_RemoteOnRename_Thunk@4
+?OnRename@CAdvSinkImpl@CDefLink@@UAGXPAUIMoniker@@@Z
+?SendOnRename@COAHolder@@UAGJPAUIMoniker@@@Z
+?Load@CExtentList@@QAEJPAUIStream@@K@Z
+?CleanupRegOIDs@@YGXPAUSHashChain@@@Z
+?Release@CAdvSinkImpl@CDefLink@@UAGKXZ
+StgSetTimes@16
+?SetElementTimes@CSimpStorage@@UAGJPBGPBU_FILETIME@@11@Z
+OleIsCurrentClipboard@4
+?Release@CDefLink@@W3AGKXZ
+?Release@CDefLink@@WBA@AGKXZ
+IDataObject_RemoteGetData_Proxy@12
+IDataObject_RemoteGetData_Thunk@4
+IDataObject_GetData_Proxy@12
+IDataObject_GetData_Stub@12
+GetInterfaceFromWindowProp@16
+??0CStreamOnMessage@@QAE@PAPAE@Z
+?WdtpInterfacePointer_UserMarshal@@YGPAEPAU_USER_MARSHAL_CB@@KPAEPAUIUnknown@@ABU_GUID@@@Z
+?GetInterfaceFromWindowProp@CInterfaceFromWindowProp@@UAGJKABU_GUID@@PAPAUIUnknown@@PAG@Z
+?RemAddRef@CRemoteUnknown@@UAGJGQAUtagREMINTERFACEREF@@PAJ@Z
+?Read@CStreamOnMessage@@UAGJPAXKPAK@Z
+?Write@CStreamOnMessage@@UAGJPBXKPAK@Z
+?WdtpInterfacePointer_UserUnmarshal@@YGPAEPAU_USER_MARSHAL_CB@@PAEPAPAUIUnknown@@ABU_GUID@@@Z
+?UnmarshalFromEndpointProperty@@YGJPAUHWND__@@PAPAUIInterfaceFromWindowProp@@PAH@Z
+?GetData@CClipDataObject@@UAGJPAUtagFORMATETC@@PAUtagSTGMEDIUM@@@Z
+?GetDataObjectForClip@CClipDataObject@@AAEXXZ
+?RemoteAddRef@@YGJPAUtagIPIDEntry@@PAUtagOXIDEntry@@KK@Z
+?wInitializeCacheEx@@YGJPAUIDataObject@@ABU_GUID@@KKPAKPAUtagFORMATETC@@PAUIAdviseSink@@2PAXPAH@Z
+?WdtpInterfacePointer_UserSize@@YGKPAU_USER_MARSHAL_CB@@KKPAUIUnknown@@ABU_GUID@@@Z
+?RenderFormat@@YGJPAUHWND__@@IPAUIDataObject@@@Z
+OleFlushClipboard@0
+?MapCFToFormatetc@@YGJPAUHWND__@@IPAUtagFORMATETC@@@Z
+?HandleFromHandle@@YGJPAUIDataObject@@PAUtagFORMATETC@@PAUtagSTGMEDIUM@@@Z
+?UtCopyTargetDevice@@YGPAUtagDVTARGETDEVICE@@PAU1@@Z
+?UtCopyStatData@@YGHPAUtagSTATDATA@@0@Z
+?CompareAssocKey@CMapKeyToValue@@ABEHPAUCAssoc@1@PAXI@Z
+?LockConnection@CStdIdentity@@UAGJHH@Z
+?LockRunning@CDefObject@@UAGJHH@Z
+?Update@CDefObject@@UAGJXZ
+?CopyTo@CExposedStream@@UAGJPAUIStream@@T_ULARGE_INTEGER@@PAT3@2@Z
+?CopyToWorker@CExposedStream@@AAEJPAUIStream@@T_ULARGE_INTEGER@@PAT3@2@Z
+IAdviseSink_OnSave_Proxy@4
+?ClientToDelegate@CDataAdviseCache@@AAEJKPAK@Z
+?OnSave@CAdvSinkImpl@CDefObject@@UAGXXZ
+?Lookup@CMapKeyToValue@@QBEHPAXI0@Z
+?WriteAt@CMemBytes@@UAGJT_ULARGE_INTEGER@@PBXKPAK@Z
+??0CBasedGlobalContextPtr@@QAE@PAVCGlobalContext@@@Z
+?Flush@CMemBytes@@UAGJXZ
+?GetAssocValue@CMapKeyToValue@@ABEXPAUCAssoc@1@PAX@Z
+?ReadAt@CMemBytes@@UAGJT_ULARGE_INTEGER@@PAXKPAK@Z
+?Release@CMemBytes@@UAGKXZ
+?wProgIDFromCLSID@@YGJABU_GUID@@PAPAG@Z
+CreateILockBytesOnHGlobal@12
+?ReleaseOleItemContainerDelegate@CDefLink@@AAEXXZ
+?EndUpdates@CDefLink@@AAEXXZ
+?OnClose@CAdvSinkImpl@CDefLink@@UAGXXZ
+?Stat@CMemBytes@@UAGJPAUtagSTATSTG@@K@Z
+??CCBasedGlobalContextPtr@@QBEPAVCGlobalContext@@XZ
+?ReleaseDataDelegate@CDefLink@@QAEXXZ
+?ReleaseOleDelegate@CDefLink@@QAEXXZ
+?SendOnSave@COAHolder@@UAGJXZ
+?GetOwnerLink@@YGJPAUIDataObject@@PAUtagSTGMEDIUM@@@Z
+StgCreateDocfileOnILockBytes@16
+?SetSize@CMemBytes@@UAGJT_ULARGE_INTEGER@@@Z
+?LookupHKey@CMapKeyToValue@@QBEHPAUHMAPKEY__@@PAX@Z
+?ReleaseRODelegate@CDefLink@@QAEXXZ
+GetHGlobalFromILockBytes@8
+?AddRef@CMemBytes@@UAGKXZ
+?GetDataFromStorage@@YGJPAUIDataObject@@PAUtagFORMATETC@@PAUtagSTGMEDIUM@@PAPAUIStorage@@@Z
+?GetDataFromStream@@YGJPAUIDataObject@@PAUtagFORMATETC@@PAUtagSTGMEDIUM@@PAPAUIStream@@@Z
+?QueryInterface@CMemBytes@@UAGJABU_GUID@@PAPAX@Z
+?Create@CMemBytes@@SGPAV1@PAX@Z
+?GetObjectLink@@YGJPAUIDataObject@@PAUtagSTGMEDIUM@@@Z
+?UtCreateStorageOnHGlobal@@YGJPAXHPAPAUIStorage@@PAPAUILockBytes@@@Z
+?GetNative@@YGJPAUIDataObject@@PAUtagSTGMEDIUM@@@Z
+IAdviseSink_OnSave_Stub@4
+IAdviseSink_RemoteOnSave_Proxy@4
+IAdviseSink_RemoteOnSave_Thunk@4
+??1CMfObject@@QAE@XZ
+?Release@CMfObject@@UAGKXZ
+IrotIsRunning@20
+?IrotIsRunning@CRpcResolver@@QAEJPAU_MnkEqBuf@@@Z
+?InitNew@COleCache@@UAGJPAUIStorage@@@Z
+OleCreateEx@48
+?wReturnCreationError@@YGJJ@Z
+OleCreate@28
+?InitNew@CDefObject@@UAGJPAUIStorage@@@Z
+??0CCacheNode@@QAE@PAUtagFORMATETC@@KPAVCOleCache@@@Z
+?BeginUpdates@CDefLink@@AAEXXZ
+?QueryInterface@CBindCtx@@UAGJABU_GUID@@PAPAX@Z
+??0CDelayUnlockContainer@@QAE@XZ
+?GetUserType@CDefLink@@UAGJKPAPAG@Z
+?AddRef@CMemStm@@UAGKXZ
+?IsEqual@CItemMoniker@@UAGJPAUIMoniker@@@Z
+?DAdvise@CDefLink@@UAGJPAUtagFORMATETC@@KPAUIAdviseSink@@PAK@Z
+?SetClientSite@CDefLink@@UAGJPAUIOleClientSite@@@Z
+CoGetInstanceFromFile@32
+??0CDefLink@@AAE@PAUIUnknown@@@Z
+?Ole10_CLSIDFromString@@YGJPBGPAU_GUID@@H@Z
+?IsReallyRunning@CDefLink@@UAGHXZ
+?IsDirty@CBaseMoniker@@UAGJXZ
+OleCreateLinkFromDataEx@48
+?RegisterObjectBound@CBindCtx@@UAGJPAUIUnknown@@@Z
+ReadClassStm@8
+?IrotGetObject@CRpcResolver@@QAEJKPAU_MnkEqBuf@@PAU_SCMREGKEY@@PAPAUtagInterfaceData@@@Z
+?GetOleItemContainerDelegate@CDefLink@@AAEPAUIOleItemContainer@@XZ
+?Create@CDefLink@@SGPAUIUnknown@@PAU2@@Z
+?SetSourceMoniker@CDefLink@@UAGJPAUIMoniker@@ABU_GUID@@@Z
+CoIsHandlerConnected@4
+?IsEqual@CCompositeMoniker@@EAGJPAUIMoniker@@@Z
+?BindToSource@CDefLink@@UAGJKPAUIBindCtx@@@Z
+?IsRunning@CCompositeMoniker@@EAGJPAUIBindCtx@@PAUIMoniker@@1@Z
+?QueryInterface@CMemStm@@UAGJABU_GUID@@PAPAX@Z
+?IsOle1Class@CFileMoniker@@AAEHPAU_GUID@@@Z
+?LoadSystemProc@@YGHPADPBDPAPAUHINSTANCE__@@PAP6GHXZ@Z
+?wQueryUseCustomLink@@YGHABU_GUID@@@Z
+?AddRef@CAdvSinkImpl@CDefLink@@UAGKXZ
+?IsRunning@CFileMoniker@@UAGJPAUIBindCtx@@PAUIMoniker@@1@Z
+?wCreateLinkEx@@YGJPAUIMoniker@@ABU_GUID@@PAUIDataObject@@1KKKPAKPAUtagFORMATETC@@PAUIAdviseSink@@3PAUIOleClientSite@@PAUIStorage@@PAPAX@Z
+?GetRODelegate@CDefLink@@QAEPAUIRunnableObject@@XZ
+OleCreateLinkFromData@28
+?GetObjectW@CRunningObjectTable@@UAGJPAUIMoniker@@PAPAUIUnknown@@@Z
+?QueryInterface@CAdvSinkImpl@CDefLink@@UAGJABU_GUID@@PAPAX@Z
+?Load@CCompositeMoniker@@EAGJPAUIStream@@@Z
+?wGetMonikerAndClassFromObject@@YGJPAUIDataObject@@PAPAUIMoniker@@PAU_GUID@@@Z
+?IsRunning@CItemMoniker@@UAGJPAUIBindCtx@@PAUIMoniker@@1@Z
+?CreateFileMonikerComparisonBuffer@@YGJPAGPAEKPAK@Z
+?GetInstanceHelper@@YGJPAU_COSERVERINFO@@PAU_GUID@@PAUIUnknown@@KKPAGPAUIStorage@@KPAUtagMULTI_QI@@@Z
+?ComposeWith@CCompositeMoniker@@EAGJPAUIMoniker@@HPAPAU2@@Z
+?RegisterContainerBound@@YGJPAUIBindCtx@@PAUIOleItemContainer@@@Z
+GetClassFileEx@12
+?Release@CDelayUnlockContainer@@UAGKXZ
+IrotGetObject@32
+?Reset@CCompositeMonikerEnum@@UAGJXZ
+?InitNew@CDefLink@@UAGJPAUIStorage@@@Z
+?GetObjectFromRotByPath@@YGJPAGPAPAUIUnknown@@@Z
+?BindSpeedFromBindCtx@@YGKPAUIBindCtx@@@Z
+??1CObjList@CBindCtx@@QAE@XZ
+?AddRef@CBindCtx@@UAGKXZ
+?IGetObjectByPath@CRunningObjectTable@@QAEJPAGPAPAUIUnknown@@K@Z
+?BindToObject@CFileMoniker@@UAGJPAUIBindCtx@@PAUIMoniker@@ABU_GUID@@PAPAX@Z
+?BindToObject@CItemMoniker@@UAGJPAUIBindCtx@@PAUIMoniker@@ABU_GUID@@PAPAX@Z
+?GetBindOptions@CBindCtx@@UAGJPAUtagBIND_OPTS@@@Z
+?BindIfRunning@CDefLink@@UAGJXZ
+?GetMiscStatus@CDefLink@@UAGJKPAK@Z
+?IGetObject@CRunningObjectTable@@QAGJPAU_MnkEqBuf@@PAPAUIUnknown@@K@Z
+?IsItemMoniker@@YGPAVCItemMoniker@@PAUIMoniker@@@Z
+?AddRef@CDelayUnlockContainer@@UAGKXZ
+?BindToObject@CCompositeMoniker@@EAGJPAUIBindCtx@@PAUIMoniker@@ABU_GUID@@PAPAX@Z
+OleLoadFromStream@12
+?Advise@CDefLink@@UAGJPAUIAdviseSink@@PAK@Z
+IOleItemContainer_GetObject_Stub@24
+IStream_Seek_Stub@20
+IOleItemContainer_GetObject_Proxy@24
+IOleItemContainer_RemoteGetObject_Thunk@4
+ISequentialStream_Read_Proxy@16
+ISequentialStream_RemoteRead_Thunk@4
+ISequentialStream_Read_Stub@16
+IStream_Seek_Proxy@20
+IOleItemContainer_RemoteGetObject_Proxy@24
+ISequentialStream_RemoteRead_Proxy@16
+IStream_RemoteSeek_Thunk@4
+IStream_RemoteSeek_Proxy@20
+?SetAllTimes@CMStream@@QAEJKU_FILETIME@@00@Z
+?SetBase@CWrappedDocFile@@QAEJPAVPDocFile@@@Z
+?SetAllTimes@CDocFile@@UAEJU_FILETIME@@00@Z
+?SetAllTimes@CDirectory@@QAEJKU_FILETIME@@00@Z
+CoInitialize@4
+?PrivHeapFree@@YGHPAXK0@Z
+CoGetClassObject@20
+IDataObject_RemoteGetDataHere_Thunk@4
+IDataObject_GetDataHere_Stub@12
+?wLoadAndInitObjectEx@@YGJPAUIDataObject@@ABU_GUID@@KKPAKPAUtagFORMATETC@@PAUIAdviseSink@@2PAUIOleClientSite@@PAUIStorage@@PAPAX@Z
+?UtGetClassID@@YGHPAUIUnknown@@PAU_GUID@@@Z
+?MatchFormatetc@CClipDataObject@@AAE?AW4FormatMatchFlag@@PAUtagFORMATETC@@PAW4tagTYMED@@@Z
+?FreeResources@CClipDataObject@@AAEXW4FreeResourcesFlags@@@Z
+OleCreateFromDataEx@48
+?OleGetClipboardData@CClipDataObject@@AAEJIPAPAX@Z
+IDataObject_GetDataHere_Proxy@12
+OleCreateFromData@28
+?GetDataHere@CClipDataObject@@UAGJPAUtagFORMATETC@@PAUtagSTGMEDIUM@@@Z
+?wCreateFromDataEx@@YGJPAUIDataObject@@ABU_GUID@@KKKPAKPAUtagFORMATETC@@PAUIAdviseSink@@2PAUIOleClientSite@@PAUIStorage@@PAPAX@Z
+IDataObject_RemoteGetDataHere_Proxy@12
+?UpdateShrdTbls@CRpcResolver@@QAEJXZ
+UpdateShrdTbls@8
+?IsLongComponent@@YGHPBGPAPAG@Z
+?DetermineDosPathNameType@@YG?AW4PATH_TYPE@@PBG@Z
+?CommonPrefixWith@CFileMoniker@@UAGJPAUIMoniker@@PAPAU2@@Z
+?wCommonPrefixWith@CFileMoniker@@EAGJPAUIMoniker@@PAPAU2@@Z
+?CopyPathFromUnicodeExtent@@YGJPAU_MONIKEREXTENT@@AAPAGAAG@Z
+??_ECDefLink@@EAEPAXI@Z
+?CleanupForDelete@CDefLink@@AAEXXZ
+??1CDefLink@@EAE@XZ
+?FreeAssocKey@CMapKeyToValue@@ABEXPAUCAssoc@1@@Z
+?Close@CDefLink@@UAGJK@Z
diff --git a/private/ole32/dll/daytona/sources b/private/ole32/dll/daytona/sources
new file mode 100644
index 000000000..e24d4ca9f
--- /dev/null
+++ b/private/ole32/dll/daytona/sources
@@ -0,0 +1,121 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Rick Sailor (Ricksa) 21-Jan-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = ole32
+
+!include ..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= ole32
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= $(BASEDIR)\public\sdk\lib
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= DYNLINK
+
+DLLDEF= obj\$(TARGET_DIRECTORY)\ole32.def
+
+DLLENTRY= _DllMainCRTStartup
+
+DLLBASE= @$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,ole32
+
+INCLUDES= ..\..\common\daytona;..\..\ih;..
+
+C_DEFINES= \
+ $(C_DEFINES)
+
+
+SOURCES= \
+ ..\ole2w32.rc
+
+UMTYPE= console
+UMTEST=
+
+LINKLIBS= \
+ ..\..\common\daytona\obj\*\common.lib \
+ ..\..\com\moniker2\daytona\obj\*\moniker.lib \
+ ..\..\com\class\daytona\obj\*\class.lib \
+ ..\..\com\coll\daytona\obj\*\coll.lib \
+ ..\..\com\debug\daytona\obj\*\debug.lib \
+ ..\..\com\dcomrem\daytona\obj\*\remote.lib \
+ ..\..\com\accctrl\daytona\obj\*\accctrl.lib \
+ ..\..\com\rot\daytona\obj\*\rot.lib \
+ ..\..\com\inc\daytona\obj\*\inc.lib \
+ ..\..\com\objact\daytona\obj\*\objact.lib \
+ ..\..\com\util\daytona\obj\*\util.lib \
+ ..\..\oleprx32\proxy\daytona\obj\*\oleprx32.lib \
+ ..\..\com\dde\client\daytona\obj\*\ddecli.lib \
+ ..\..\com\dde\server\daytona\obj\*\ddesvr.lib \
+ ..\..\ole232\advise\daytona\obj\*\advise.lib \
+ ..\..\ole232\base\daytona\obj\*\base.lib \
+ ..\..\ole232\cache\daytona\obj\*\cache.lib \
+ ..\..\ole232\clipbrd\daytona\obj\*\clipbrd.lib \
+ ..\..\ole232\debug\daytona\obj\*\debug.lib \
+ ..\..\ole232\drag\daytona\obj\*\drag.lib \
+ ..\..\ole232\inplace\daytona\obj\*\inplace.lib \
+ ..\..\ole232\stdimpl\daytona\obj\*\stdimpl.lib \
+ ..\..\ole232\ole1\daytona\obj\*\ole1.lib \
+ ..\..\ole232\util\daytona\obj\*\util.lib \
+ ..\..\stg\docfile\daytona\obj\*\docfile.lib \
+ ..\..\stg\exp\daytona\obj\*\exp.lib \
+ ..\..\stg\msf\daytona\obj\*\msf.lib \
+ ..\..\stg\simp\daytona\obj\*\simp.lib \
+ ..\..\stg\props\daytona\obj\*\props.lib \
+ ..\..\stg\async\docfile\daytona\obj\*\asyncstg.lib \
+ ..\..\ilib\daytona\obj\*\uuid.lib \
+ ..\..\common\cruntime\daytona\obj\*\cruntime.lib \
+ ..\..\com\wx86grpa\daytona\obj\*\wx86grpa.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcndr.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcns4.lib \
+ $(BASEDIR)\public\sdk\lib\*\netapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\pwin32.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib \
+ $(BASEDIR)\public\sdk\lib\*\imagehlp.lib \
+ $(BASEDIR)\private\dcomidl\obj\*\dcomidl.lib \
+
+
+NTPROFILEINPUT=yes
+
+!include ..\sources.inc
+
diff --git a/private/ole32/dll/dcopy_c.cur b/private/ole32/dll/dcopy_c.cur
new file mode 100644
index 000000000..1d94c080b
--- /dev/null
+++ b/private/ole32/dll/dcopy_c.cur
Binary files differ
diff --git a/private/ole32/dll/default.ico b/private/ole32/dll/default.ico
new file mode 100644
index 000000000..4542c57d3
--- /dev/null
+++ b/private/ole32/dll/default.ico
Binary files differ
diff --git a/private/ole32/dll/dirs b/private/ole32/dll/dirs
new file mode 100644
index 000000000..be69887d6
--- /dev/null
+++ b/private/ole32/dll/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Rick Sailor (Ricksa) 24-Jan-1994
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/dll/dlink_c.cur b/private/ole32/dll/dlink_c.cur
new file mode 100644
index 000000000..c52efe7d7
--- /dev/null
+++ b/private/ole32/dll/dlink_c.cur
Binary files differ
diff --git a/private/ole32/dll/dmove_c.cur b/private/ole32/dll/dmove_c.cur
new file mode 100644
index 000000000..9705df232
--- /dev/null
+++ b/private/ole32/dll/dmove_c.cur
Binary files differ
diff --git a/private/ole32/dll/dnone_c.cur b/private/ole32/dll/dnone_c.cur
new file mode 100644
index 000000000..b002e96b3
--- /dev/null
+++ b/private/ole32/dll/dnone_c.cur
Binary files differ
diff --git a/private/ole32/dll/ole.ico b/private/ole32/dll/ole.ico
new file mode 100644
index 000000000..ca6b6da5f
--- /dev/null
+++ b/private/ole32/dll/ole.ico
Binary files differ
diff --git a/private/ole32/dll/ole2w32.rc b/private/ole32/dll/ole2w32.rc
new file mode 100644
index 000000000..f8c07ae5c
--- /dev/null
+++ b/private/ole32/dll/ole2w32.rc
@@ -0,0 +1,25 @@
+#include <windows.h>
+
+//
+// Version resources
+//
+#include <ntverp.h>
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Microsoft OLE for Windows and Windows NT"
+#define VER_INTERNALNAME_STR "OLE32.DLL"
+#define VER_ORIGINALFILENAME_STR "OLE32.DLL"
+#include <common.ver>
+
+#include <resource.h>
+
+CURNONE CURSOR dnone_c.cur
+CURMOVE CURSOR dmove_c.cur
+CURCOPY CURSOR dcopy_c.cur
+CURLINK CURSOR dlink_c.cur
+CURSCROLLMOVE CURSOR smove_c.cur
+CURSCROLLCOPY CURSOR scopy_c.cur
+CURSCROLLLINK CURSOR slink_c.cur
+
+// used by "..\src\def\geticon.c"
+DEFICON ICON default.ico
diff --git a/private/ole32/dll/ole32.def b/private/ole32/dll/ole32.def
new file mode 100644
index 000000000..efa0a53c1
--- /dev/null
+++ b/private/ole32/dll/ole32.def
@@ -0,0 +1,523 @@
+#if 0
+
+ Microsoft Windows
+ Copyright (C) Microsoft Corporation, 1992 - 1992.
+ All rights reserved.
+
+ This .def file is preprocessed by the compiler to create the version for
+ the current build in the appropriate subdir. Basically, whatever you
+ would have used in your code to control what is compiled when can be
+ used in this file for the same purpose. The following defines are in
+ use at the time this file was written:
+
+ FLAT - Used to indicate a NT/DOS7 build
+ i386 - Intel i386/i486 build
+ MIPS - MIPS R3000/R4000 build
+ ALPHA - DEC Alpha build
+ PPC - PowerPC build
+ DBG - Used to control Debug/Retail. Set to 1 if Debug,
+ 0 if Retail.
+ WIN31 - Win16 build
+ __OS2__ - OS/2 build (used by CT mostly)
+
+ If none of these are used, it is assumed the entire file can be used
+ for all builds.
+
+#endif
+
+LIBRARY ole32
+
+DESCRIPTION 'Microsoft (R) Component OLE 2.0 Base DLL 1.00'
+
+#if defined(_CHICAGO_)
+;
+; No security under Win95, take advantage of shared data segments.
+;
+SECTIONS
+ .sdata READ WRITE SHARED
+#endif
+
+EXPORTS
+
+ OleBuildVersion=CoBuildVersion
+ OleInitialize
+ OleInitializeWOW
+ OleUninitialize
+ DllGetClassObject PRIVATE
+ DllGetClassObjectWOW=DllGetClassObject
+ OleQueryLinkFromData
+ OleQueryCreateFromData
+ OleCreateFromData
+ OleCreateFromDataEx
+ OleCreateLinkFromData
+ OleCreateLinkFromDataEx
+ OleCreate
+ OleCreateEx
+ OleCreateLink
+ OleCreateLinkEx
+ OleLoad
+ OleSave
+ OleRun
+ OleIsRunning
+ OleLockRunning
+ ReadClassStg
+ WriteClassStg
+ ReadClassStm
+ WriteClassStm
+ ReleaseStgMedium
+ ReadStringStream
+ WriteStringStream
+ RegisterDragDrop
+ RevokeDragDrop
+ DoDragDrop
+ CreateOleAdviseHolder
+ CreateDataAdviseHolder
+ OleCreateMenuDescriptor
+ OleSetMenuDescriptor
+ OleDestroyMenuDescriptor
+ OpenOrCreateStream
+ IsAccelerator
+ OleSetClipboard
+ OleGetClipboard
+ OleDuplicateData
+ OleGetIconOfFile
+ OleGetIconOfClass
+ CreateILockBytesOnHGlobal
+ GetHGlobalFromILockBytes
+ OleMetafilePictFromIconAndLabel
+ OleDraw
+ OleCreateDefaultHandler
+ OleCreateEmbeddingHelper
+ SetDocumentBitStg
+ GetDocumentBitStg
+ WriteOleStg
+ ReadOleStg
+ OleCreateFromFile
+ OleCreateFromFileEx
+ OleCreateLinkToFile
+ OleCreateLinkToFileEx
+ CreateDataCache
+ OleConvertIStorageToOLESTREAM
+ OleConvertOLESTREAMToIStorage
+ OleConvertIStorageToOLESTREAMEx
+ OleConvertOLESTREAMToIStorageEx
+ ReadFmtUserTypeStg
+ WriteFmtUserTypeStg
+ OleFlushClipboard
+ OleIsCurrentClipboard
+ OleTranslateAccelerator
+ OleDoAutoConvert
+ OleGetAutoConvert
+ OleSetAutoConvert
+ GetConvertStg
+ SetConvertStg
+ CreateStreamOnHGlobal
+ GetHGlobalFromStream
+ OleSetContainedObject
+ OleNoteObjectVisible
+ OleCreateStaticFromData
+
+ OleRegGetUserType
+ OleRegGetMiscStatus
+ OleRegEnumFormatEtc
+ OleRegEnumVerbs
+
+ CoTaskMemAlloc
+ CoTaskMemRealloc
+ CoTaskMemFree
+
+ PropVariantClear
+ PropVariantCopy
+ FreePropVariantArray
+
+ CoBuildVersion
+ CoInitialize
+ CoInitializeWOW
+ CoUnloadingWOW
+ CoUninitialize
+ CoGetMalloc
+ CoRegisterMallocSpy
+ CoRevokeMallocSpy
+ CoCreateGuid
+ CoMarshalInterface
+ CoUnmarshalInterface
+ CoReleaseMarshalData
+ CoGetStandardMarshal
+ CoGetMarshalSizeMax
+ CoMarshalHresult
+ CoUnmarshalHresult
+ CoRegisterClassObject
+ CoRevokeClassObject
+ CoGetClassObject
+ CoCreateInstance
+ CoDisconnectObject
+ CoLockObjectExternal
+ CoLoadLibrary
+ CoFreeLibrary
+ CoFreeAllLibraries
+ CoFreeUnusedLibraries
+ CoRegisterMessageFilter
+ CoFileTimeToDosDateTime
+ CoDosDateTimeToFileTime
+ GetRunningObjectTable
+ CoIsOle1Class
+ CoTreatAsClass
+ CoGetTreatAsClass
+ CoGetCurrentProcess
+ IsEqualGUID
+ StringFromCLSID
+ CLSIDFromString
+ ProgIDFromCLSID
+ CLSIDFromProgID
+ StringFromGUID2
+ IsValidPtrIn
+ IsValidPtrOut
+ IsValidInterface
+ IsValidIid
+ CoGetState
+ CoSetState
+ CoGetCallerTID
+ CoGetCurrentLogicalThreadId
+#ifdef DCOM
+ CoGetTIDFromIPID
+ CoRegisterChannelHook
+ CoRegisterSurrogate
+#endif
+#ifdef DCOM_SECURITY
+ CoInitializeSecurity
+ CoGetCallContext
+ CoQueryProxyBlanket
+ CoSetProxyBlanket
+ CoCopyProxy
+ CoQueryClientBlanket
+ CoImpersonateClient
+ CoRevertToSelf
+ CoQueryAuthenticationServices
+ CoSwitchCallContext
+#endif
+
+ CoIsHandlerConnected
+ CoFileTimeNow
+ CoGetObject
+ BindMoniker
+ MkParseDisplayName
+ CreateBindCtx
+ CreateItemMoniker
+ CreateFileMoniker
+#ifdef _CAIRO_
+ CreateFileMonikerEx
+#endif
+ CreateGenericComposite
+ CreateAntiMoniker
+ CreatePointerMoniker
+ CreateClassMoniker
+ MonikerRelativePathTo
+ GetClassFile
+ OleSaveToStream
+ OleLoadFromStream
+ MonikerCommonPrefixWith
+ CoQueryReleaseObject
+ StgCreateDocfile
+ StgCreateDocfileOnILockBytes
+ StgOpenStorage
+ StgOpenStorageOnILockBytes
+ StgIsStorageFile
+ StgIsStorageILockBytes
+ StgSetTimes
+ StgOpenAsyncDocfileOnIFillLockBytes
+ StgGetIFillLockBytesOnILockBytes
+ StgGetIFillLockBytesOnFile
+ PropSysAllocString
+ PropSysFreeString
+ CoInitializeEx
+#ifdef _CAIRO_
+ CoGetPersistentInstance
+ CoGetPersistentInstanceEx
+ StgCreateStorage
+ StgCreateStorageOnHandle
+ StgOpenStorageOnHandle
+ StgCreateStorageEx
+ StgOpenStorageEx
+ DsysStgCreateStorageEx
+ DsysStgOpenStorageEx
+ StgIsStorage
+ OleInitializeEx
+ DfIsDocfile
+ OleGetTransactionDispenser
+#endif // _CAIRO_
+#ifdef DCOM
+ CoGetInstanceFromFile
+ CoGetInstanceFromIStorage
+ CoCreateInstanceEx
+ UpdateDCOMSettings
+ CoRegisterPSClsid
+ CoAddRefServerProcess
+ CoReleaseServerProcess
+ CoSuspendClassObjects
+ CoResumeClassObjects
+#endif
+ DllDebugObjectRPCHook
+ StringFromIID
+ IIDFromString
+ CoGetPSClsid
+#ifdef _CAIRO_
+ SerializeToStream
+ DeserializeFromStream
+ SerializeSizeMax
+#endif
+#if DBG == 1
+ DumpADVFFlags
+ DumpATOM
+ DumpCLSID
+ DumpCLIPFORMAT
+ DumpCMutexSem
+ DumpDVASPECTFlags
+ DumpFILETIME
+ DumpHRESULT
+ DumpWIN32Error
+ DumpCACHELIST_ITEM
+ DumpCCacheEnum
+ DumpCCacheEnumFormatEtc
+ DumpCCacheNode
+ DumpCClipDataObject
+ DumpCClipEnumFormatEtc
+ DumpCDAHolder
+ DumpCDataAdviseCache
+ DumpCDefClassFactory
+ DumpCDefLink
+ DumpCDefObject
+ DumpCEMfObject
+ DumpCEnumFmt
+ DumpCEnumFmt10
+ DumpCEnumSTATDATA
+ DumpCEnumVerb
+ DumpCGenObject
+ DumpCMapDwordDword
+ DumpCMemBytes
+ DumpCMemStm
+ DumpCMfObject
+ DumpCOAHolder
+ DumpCOleCache
+ DumpCSafeRefCount
+ DumpCThreadCheck
+ DumpFORMATETC
+ DumpMEMSTM
+ DumpSTATDATA
+ DumpSTGMEDIUM
+
+ DfDebug
+ DfSetResLimit
+ DfGetResLimit
+ DfGetMemAlloced
+ DfPrintAllocs
+ DbgLogOpen
+ DbgLogClose
+ DbgLogOutputDebugString
+ DbgLogWrite
+ DbgLogTimeStamp
+ DbgLogWriteBanner
+ DbgDumpObject
+ DbgIsObjectValid
+ DbgDumpExternalObject
+ DbgDumpClassName
+ MakeDebugStream
+ Dbg_FindRemoteHdlr
+ DbgDllSetSiftObject PRIVATE
+ StgGetDebugFileLockBytes
+#endif // DBG == 1
+#ifdef TRACELOG
+#if defined(i386)
+ ??0CTraceCall@@QAE@KPAD@Z
+ ??1CTraceCall@@QAE@XZ
+ StartTrace
+ StopTrace
+#else // i386
+#error TraceLogs not defined for MIPS or Alpha or PPC- Rickhi
+#endif // MIPS | ALPHA | PPC
+#endif // TRACELOG
+#if DBG==1 && defined(_NT1X_) && defined(GLOBALDBG)
+ GlobalAlloc=UtGlobalAlloc
+ GlobalFree=UtGlobalFree
+ GlobalReAlloc=UtGlobalReAlloc
+ GlobalLock=UtGlobalLock
+ GlobalUnlock=UtGlobalUnlock
+#endif // DBG==1 && defined(_NT1X_) && defined(GLOBALDBG)
+
+ ;; Utility functions exported for olethk32.dll
+ UtGetDvtd16Info
+ UtConvertDvtd16toDvtd32
+ UtGetDvtd32Info
+ UtConvertDvtd32toDvtd16
+
+#if DBG==1
+ ;; DBG Utility functions exported for olethk32.dll
+ UtGlobalAlloc
+ UtGlobalFree
+ UtGlobalReAlloc
+ UtGlobalLock
+ UtGlobalUnlock
+#endif
+
+#ifdef _CAIRO_
+# ifdef i386
+
+ ;
+ ; Object tracking functions
+ ;
+
+ ?_CRefcountedObject@CRefcountedObject@@AAEXXZ
+ ?DestroyRefcounted@CRefcountedObject@@AAEXXZ
+ ?TrackClassName@CRefcountedObject@@IAEXPAD@Z
+ ?TrackAddRef@CRefcountedObject@@IAEKXZ
+ ?TrackRelease@CRefcountedObject@@IAEKXZ
+
+ #if DBG == 1
+ ?DumpTrackingInfo@CRefcountedObject@@SGXH@Z
+ ?TrackClass@CRefcountedObject@@SGXHPAD@Z
+ #endif
+
+ ;
+ ; CStdComponentObject functions
+ ;
+ ??0CStdComponentObject@@IAE@PBVCLASSDESCRIPTOR@@@Z
+ ??1CStdComponentObject@@UAE@XZ
+ ?InitInstance@CStdComponentObject@@QAEJPAUIUnknown@@ABU_GUID@@PAPAX@Z
+ ?PrimaryAddRef@CStdComponentObject@@EAGKXZ
+ ?PrimaryQueryInterface@CStdComponentObject@@EAGJABU_GUID@@PAPAX@Z
+ ?PrimaryRelease@CStdComponentObject@@EAGKXZ
+ ?_InitInstance@CStdComponentObject@@MAGJXZ
+ ?_QueryInterface@CStdComponentObject@@MAGJABU_GUID@@PAPAX@Z
+
+# else // Not x86
+
+ ;
+ ; Object tracking functions
+ ;
+
+ ?_CRefcountedObject@CRefcountedObject@@AAAXXZ
+ ?DestroyRefcounted@CRefcountedObject@@AAAXXZ
+ ?TrackAddRef@CRefcountedObject@@IAAKXZ
+ ?TrackRelease@CRefcountedObject@@IAAKXZ
+ ?TrackClassName@CRefcountedObject@@IAAXPAD@Z
+
+ #if DBG == 1
+ ?DumpTrackingInfo@CRefcountedObject@@SAXH@Z
+ ?TrackClass@CRefcountedObject@@SAXHPAD@Z
+ #endif
+
+ ;
+ ; CStdComponentObject functions
+ ;
+
+ ??0CStdComponentObject@@IAA@PBVCLASSDESCRIPTOR@@@Z
+ ??1CStdComponentObject@@UAA@XZ
+ ?InitInstance@CStdComponentObject@@QAAJPAUIUnknown@@ABU_GUID@@PAPAX@Z
+ ?PrimaryAddRef@CStdComponentObject@@EAAKXZ
+ ?PrimaryQueryInterface@CStdComponentObject@@EAAJABU_GUID@@PAPAX@Z
+ ?PrimaryRelease@CStdComponentObject@@EAAKXZ
+ ?_InitInstance@CStdComponentObject@@MAAJXZ
+ ?_QueryInterface@CStdComponentObject@@MAAJABU_GUID@@PAPAX@Z
+
+# endif // not x86
+#endif // CAIRO
+
+ CoMarshalInterThreadInterfaceInStream
+ CoGetInterfaceAndReleaseStream
+ CoCreateFreeThreadedMarshaler
+
+ ;; Entry points for HookOle
+ EnableHookObject
+ GetHookInterface
+
+ ;
+ ; Debug support routines previously in commnot.
+ ;
+#if DBG == 1
+ SetWin4AssertLevel
+ Win4AssertEx
+ SetWin4InfoLevel
+ vdprintf
+ CallOutputFunctions
+#endif
+
+ ;
+ ; Windows data types support via user marshal
+ ;
+
+ SNB_UserSize
+ SNB_UserMarshal
+ SNB_UserUnmarshal
+ SNB_UserFree
+
+ CLIPFORMAT_UserSize
+ CLIPFORMAT_UserMarshal
+ CLIPFORMAT_UserUnmarshal
+ CLIPFORMAT_UserFree
+
+ HWND_UserSize
+ HWND_UserMarshal
+ HWND_UserUnmarshal
+ HWND_UserFree
+
+ HMENU_UserSize
+ HMENU_UserMarshal
+ HMENU_UserUnmarshal
+ HMENU_UserFree
+
+ HACCEL_UserSize
+ HACCEL_UserMarshal
+ HACCEL_UserUnmarshal
+ HACCEL_UserFree
+
+ HBRUSH_UserSize
+ HBRUSH_UserMarshal
+ HBRUSH_UserUnmarshal
+ HBRUSH_UserFree
+
+ HBITMAP_UserSize
+ HBITMAP_UserMarshal
+ HBITMAP_UserUnmarshal
+ HBITMAP_UserFree
+
+ HPALETTE_UserSize
+ HPALETTE_UserMarshal
+ HPALETTE_UserUnmarshal
+ HPALETTE_UserFree
+
+ HGLOBAL_UserSize
+ HGLOBAL_UserMarshal
+ HGLOBAL_UserUnmarshal
+ HGLOBAL_UserFree
+
+ HMETAFILE_UserSize
+ HMETAFILE_UserMarshal
+ HMETAFILE_UserUnmarshal
+ HMETAFILE_UserFree
+
+ HENHMETAFILE_UserSize
+ HENHMETAFILE_UserMarshal
+ HENHMETAFILE_UserUnmarshal
+ HENHMETAFILE_UserFree
+
+ HMETAFILEPICT_UserSize
+ HMETAFILEPICT_UserMarshal
+ HMETAFILEPICT_UserUnmarshal
+ HMETAFILEPICT_UserFree
+
+ STGMEDIUM_UserSize
+ STGMEDIUM_UserMarshal
+ STGMEDIUM_UserUnmarshal
+ STGMEDIUM_UserFree
+
+ WdtpInterfacePointer_UserSize
+ WdtpInterfacePointer_UserMarshal
+ WdtpInterfacePointer_UserUnmarshal
+ WdtpInterfacePointer_UserFree
+#ifdef WX86OLE
+ CoGetIIDFromMarshaledInterface
+#endif
+
+ CreateErrorInfo=CoCreateErrorInfo PRIVATE
+ GetErrorInfo=CoGetErrorInfo PRIVATE
+ SetErrorInfo=CoSetErrorInfo PRIVATE
+
diff --git a/private/ole32/dll/scopy_c.cur b/private/ole32/dll/scopy_c.cur
new file mode 100644
index 000000000..9bcd75204
--- /dev/null
+++ b/private/ole32/dll/scopy_c.cur
Binary files differ
diff --git a/private/ole32/dll/slink_c.cur b/private/ole32/dll/slink_c.cur
new file mode 100644
index 000000000..f86c81158
--- /dev/null
+++ b/private/ole32/dll/slink_c.cur
Binary files differ
diff --git a/private/ole32/dll/smove_c.cur b/private/ole32/dll/smove_c.cur
new file mode 100644
index 000000000..b18e23bf7
--- /dev/null
+++ b/private/ole32/dll/smove_c.cur
Binary files differ
diff --git a/private/ole32/dll/sources.inc b/private/ole32/dll/sources.inc
new file mode 100644
index 000000000..797d75e1c
--- /dev/null
+++ b/private/ole32/dll/sources.inc
@@ -0,0 +1,9 @@
+SYNCHRONIZE_DRAIN=1
+
+# define WX86OLE if WX86 hooks are to be included in OLE
+!IF $(386)
+!ELSE
+C_DEFINES= \
+ /DWX86OLE $(C_DEFINES)
+!ENDIF
+
diff --git a/private/ole32/dllhost/cdllsrv.cxx b/private/ole32/dllhost/cdllsrv.cxx
new file mode 100644
index 000000000..77022eea5
--- /dev/null
+++ b/private/ole32/dllhost/cdllsrv.cxx
@@ -0,0 +1,112 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: cdllsrv.cxx
+//
+// Contents: Class that represents dll inproc servers:
+// CDllServer
+//
+//
+// History: 21-May-96 t-AdamE Created
+//
+//--------------------------------------------------------------------------
+
+#include "cdllsrv.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllServer::CDllServer()
+//
+// Synopsis: constructor for CDllServer
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+CDllServer::CDllServer(REFCLSID clsid) :
+ _clsid(clsid),
+ _pSrgtFact(NULL)
+ {}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllServer::~CDllServer()
+//
+// Synopsis: destructor for CDllServer
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+CDllServer::~CDllServer()
+{
+ if(_pSrgtFact)
+ {
+ _pSrgtFact->Release();
+ _pSrgtFact = NULL;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllServer::Revoke()
+//
+// Synopsis: revokes the class factory for this dll server
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+HRESULT CDllServer::Revoke()
+{
+ return _pSrgtFact->Revoke();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllServer::LoadServer
+//
+// Synopsis: Registers a generic class factory object as if it were
+// the real class factory for the _clsid stored serviced
+// by this object
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+HRESULT CDllServer::LoadServer()
+{
+ CSurrogateFactory* pSrgtFact = new CSurrogateFactory(_clsid);
+
+ if(!pSrgtFact)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ pSrgtFact->AddRef();
+
+ HRESULT hr;
+ if(FAILED(hr = pSrgtFact->Register()))
+ {
+ pSrgtFact->Release();
+ return hr;
+ }
+
+ _pSrgtFact = pSrgtFact;
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllServer::FIsCompatible
+//
+// Synopsis: returns TRUE if this server implements the CLSID specified
+// in the clsid argument, FALSE if not
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+BOOL CDllServer::FIsCompatible(REFCLSID clsid)
+{
+ return _clsid == clsid;
+}
diff --git a/private/ole32/dllhost/cdllsrv.hxx b/private/ole32/dllhost/cdllsrv.hxx
new file mode 100644
index 000000000..d4e4bf65e
--- /dev/null
+++ b/private/ole32/dllhost/cdllsrv.hxx
@@ -0,0 +1,55 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: cdllsrv.hxx
+//
+// Contents: Class that represents dll inproc servers:
+// CDllServer
+//
+//
+// History: 21-May-96 t-AdamE Created
+//
+//--------------------------------------------------------------------------
+
+#if !defined(__DLLSRV_HXX__)
+#define __DLLSRV_HXX__
+
+#include <windows.h>
+#include <ole2.h>
+#include "srgtfact.hxx"
+
+extern "C"
+{
+typedef HRESULT (STDAPICALLTYPE * PFNDLLCANUNLOADNOW)();
+};
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDllServer
+//
+// Purpose: Defines an inproc dll server
+//
+// History: 21-May-96 t-Adame Created
+//
+//--------------------------------------------------------------------------
+
+class CDllServer : public CSrgtMem
+{
+public:
+
+ CDllServer(REFCLSID _clsid);
+ ~CDllServer();
+ HRESULT Revoke();
+ HRESULT LoadServer();
+ BOOL FIsCompatible(REFCLSID clsid);
+
+private:
+
+ CLSID _clsid;
+ CSurrogateFactory* _pSrgtFact;
+};
+
+#endif // !defined(__DLLSRV_HXX__)
+
diff --git a/private/ole32/dllhost/cmonitor.cxx b/private/ole32/dllhost/cmonitor.cxx
new file mode 100644
index 000000000..0c6ed7720
--- /dev/null
+++ b/private/ole32/dllhost/cmonitor.cxx
@@ -0,0 +1,35 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: cmonitor.cxx
+//
+// Contents: Class that implements a monitor
+//
+//
+// History: 21-May-96 t-AdamE Created
+//
+//--------------------------------------------------------------------------
+
+#include "cmonitor.hxx"
+
+CMonitor::CMonitor()
+{
+ InitializeCriticalSection(&m_crsmon);
+}
+
+CMonitor::~CMonitor()
+{
+ DeleteCriticalSection(&m_crsmon);
+}
+
+void CMonitor::EnterMonitor()
+{
+ EnterCriticalSection(&m_crsmon);
+}
+
+void CMonitor::LeaveMonitor()
+{
+ LeaveCriticalSection(&m_crsmon);
+}
diff --git a/private/ole32/dllhost/cmonitor.hxx b/private/ole32/dllhost/cmonitor.hxx
new file mode 100644
index 000000000..dc6038780
--- /dev/null
+++ b/private/ole32/dllhost/cmonitor.hxx
@@ -0,0 +1,48 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: cmonitor.hxx
+//
+// Contents: a monitor class for staying threadsafe:
+// CMonitor
+//
+//
+// History: 03-Jun-96 t-AdamE Created
+//
+//--------------------------------------------------------------------------
+
+
+#if !defined(__CMONITOR_HXX__)
+#define __CMONITOR_HXX__
+
+#include <windows.h>
+
+//+-------------------------------------------------------------------------
+//
+// Class: CMonitor
+// Purpose: Monitor abstraction for keeping things threadsafe
+// Inherit from this class and call EnterMonitor before accessing
+// any member data, LeaveMonitor after you've completed the access
+//
+// History: 03-Jun-96 t-Adame Created
+//
+//--------------------------------------------------------------------------
+
+class CMonitor
+{
+public:
+ CMonitor();
+ ~CMonitor();
+ void EnterMonitor();
+ void LeaveMonitor();
+private:
+ CRITICAL_SECTION m_crsmon;
+};
+
+#define ENTERMONITOR EnterMonitor()
+#define LEAVEMONITOR LeaveMonitor()
+
+#endif // !defined(__CMONITOR_HXX__)
+
diff --git a/private/ole32/dllhost/csrgt.cxx b/private/ole32/dllhost/csrgt.cxx
new file mode 100644
index 000000000..3311fe05f
--- /dev/null
+++ b/private/ole32/dllhost/csrgt.cxx
@@ -0,0 +1,158 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: CSurrogate.cxx
+//
+// Contents: Class the implements the ISurrogate interface
+//
+//
+// History: 21-May-96 t-AdamE Created
+//
+//--------------------------------------------------------------------------
+
+#include "csrgt.hxx"
+
+HANDLE CSurrogate::_hEventAllLibsFree = NULL;
+CSurrogate* CSurrogate::_pSurrogate = NULL;
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogate::CSurrogate()
+//
+// Synopsis: constructor for CSurrogate
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+CSurrogate::CSurrogate() :
+ _cref(0)
+{
+ _pSurrogate = this;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogate::QueryInterface
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CSurrogate::QueryInterface(REFIID iid, LPVOID FAR * ppv)
+{
+ if(iid == IID_IUnknown)
+ {
+ *ppv = (void*)(IUnknown*)this;
+ AddRef();
+ return S_OK;
+ }
+ else if (iid == IID_ISurrogate)
+ {
+ *ppv = (void*)(ISurrogate*)this;
+ AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogate::AddRef()
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+ULONG CSurrogate::AddRef()
+{
+ InterlockedIncrement((LPLONG)&_cref);
+ Win4Assert(_cref > 0);
+ ULONG cref = _cref;
+ return cref;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogate::Release()
+//
+// Synopsis: Decrements our Reference count -- note that this
+// implementation of ISurrogate does not delete the object
+// that implements it so that we can allocate it on the stack
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+ULONG CSurrogate::Release()
+{
+ Win4Assert(_cref >0);
+ InterlockedDecrement((LPLONG)&_cref);
+ ULONG cref = _cref;
+ return cref;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogate::LoadDllServer
+//
+// Synopsis: Loads information about the dll corresponding to the specified
+// clsid into our table of loaded dlls, which implicitly
+// loads the dll into the surrogate process
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CSurrogate::LoadDllServer(
+ /* [in] */ REFCLSID rclsid)
+{
+ return m_tblibs.LoadDllServer(rclsid);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogate::FreeSurrogate
+//
+// Synopsis: called by OLE when there are no external references to clients
+// of dll servers that were loaded by this object. A call
+// to this function signals the surrogate process that it should
+// terminate
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CSurrogate::FreeSurrogate()
+{
+ return SetEvent(CSurrogate::_hEventAllLibsFree) ? S_OK : E_FAIL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogate::WaitForSafeLibraryFree
+//
+// Synopsis: sleep the main thread of the surrogate process until OLE
+// signals us via a call to FreeSurrogate that we should terminate.
+// We then clean up by revoking all class factories for dll
+// servers loaded into the surrogate process and clear all
+// information about dll servers from our library table.
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+void CSurrogate::WaitForSafeLibraryFree()
+{
+ m_tblibs.WaitForSafeLibraryFree();
+ m_tblibs.Revoke();
+ m_tblibs.Clear();
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/private/ole32/dllhost/csrgt.hxx b/private/ole32/dllhost/csrgt.hxx
new file mode 100644
index 000000000..7810e6e2c
--- /dev/null
+++ b/private/ole32/dllhost/csrgt.hxx
@@ -0,0 +1,70 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: csrgt.hxx
+//
+// Contents: classes which implement ISurrogate:
+// CSurrgate
+// CSurrogateFactory
+//
+//
+// History: 03-Jun-96 t-AdamE Created
+//
+//--------------------------------------------------------------------------
+
+#if !defined(__CSRGT_HXX__)
+#define __CSRGT_HXX__
+
+#include <windows.h>
+#include <ole2.h>
+#include "debnot.h"
+#include "libtable.hxx"
+#include "cmonitor.hxx"
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSurrogate
+//
+// Purpose: Implement the ISurrogate interface required by COM
+// for processes that act as surrogates for dll servers
+//
+// History: 21-May-96 t-Adame Created
+//
+//--------------------------------------------------------------------------
+
+// forward declaration
+class CSurrogate;
+
+class CSurrogate : public ISurrogate
+{
+public:
+
+ CSurrogate();
+
+ // IUnknown methods
+ STDMETHOD (QueryInterface)(REFIID iid, LPVOID FAR * ppv);
+ STDMETHOD_(ULONG,AddRef)();
+ STDMETHOD_(ULONG,Release)();
+
+ // ISurrogate methods
+ STDMETHOD (LoadDllServer)(/* [in] */ REFCLSID rclsid);
+ STDMETHOD (FreeSurrogate)();
+
+ // non-COM methods
+ void WaitForSafeLibraryFree();
+
+ // signaled by a call to FreeSurrogate from OLE when its time
+ // to terminate the surrogate process
+ static HANDLE _hEventAllLibsFree;
+ static CSurrogate* _pSurrogate;
+
+private:
+
+ ULONG _cref;
+ CLibTable m_tblibs;
+
+};
+
+#endif // __CSRGT_HXX__
diff --git a/private/ole32/dllhost/daytona/makefile b/private/ole32/dllhost/daytona/makefile
new file mode 100644
index 000000000..fce66757d
--- /dev/null
+++ b/private/ole32/dllhost/daytona/makefile
@@ -0,0 +1,33 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+default: all
+
+!include $(CAIROLE)\cairole.mk
+
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!endif # NTMAKEENV
+
diff --git a/private/ole32/dllhost/daytona/sources b/private/ole32/dllhost/daytona/sources
new file mode 100644
index 000000000..a113a118d
--- /dev/null
+++ b/private/ole32/dllhost/daytona/sources
@@ -0,0 +1,87 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Adam Edwards (t-adame) 21-May-1996
+
+
+Revision History:
+
+!ENDIF
+
+!include ..\..\daytona.inc
+
+#
+# The TARGETNAME variable is defined by the developer. It is the name of
+# the target (component) that is being built by this makefile. It
+# should NOT include any path or file extension information.
+#
+
+TARGETNAME=dllhost
+
+#
+# The TARGETPATH and TARGETTYPE varialbes are defined by the developer.
+# The first specifies where the target is to be build. The second specifies
+# the type of target (either PROGRAM, DYNLINK or LIBRARY)
+#
+
+TARGETPATH=.
+TARGETTYPE=PROGRAM
+
+#
+# The INCLUDES variable specifies any include paths that are specific to
+# this source directory. Separate multiple directory paths with single
+# semicolons. Relative path specifications are okay.
+#
+
+INCLUDES=
+
+
+#
+# The SOURCES variable is defined by the developer. It is a list of all the
+# source files for this component. Each source file should be on a separate
+# line using the line continuation character. This will minimize merge
+# conflicts if two developers adding source files to the same component.
+#
+
+SOURCES=\
+ ..\dllhost.rc \
+ ..\surrogat.cxx \
+ ..\libtable.cxx \
+ ..\csrgt.cxx \
+ ..\cmonitor.cxx \
+ ..\cdllsrv.cxx \
+ ..\srgtfact.cxx
+
+LINKLIBS=$(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib \
+ $(BASEDIR)\public\sdk\lib\*\msvcrt.lib \
+
+
+UMTYPE=windows
+UMENTRY=winmain
+
+
+
+
+
+
+
+
+
+
diff --git a/private/ole32/dllhost/dirs b/private/ole32/dllhost/dirs
new file mode 100644
index 000000000..1d5cba5f4
--- /dev/null
+++ b/private/ole32/dllhost/dirs
@@ -0,0 +1,43 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+# WARNING: order is important. com must be built early since it generates
+# headers that other directories are dependent on. if you change
+# this, run the following script to ensure you have not broken it.
+# stg must now be built before oleprx32.
+#
+# del /s /q *.*
+# build -cZM
+
+
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS=daytona
+
diff --git a/private/ole32/dllhost/dllhost.rc b/private/ole32/dllhost/dllhost.rc
new file mode 100644
index 000000000..a0824613e
--- /dev/null
+++ b/private/ole32/dllhost/dllhost.rc
@@ -0,0 +1,10 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "COM Surrogate"
+#define VER_INTERNALNAME_STR "dllhost.exe"
+#define VER_ORIGINALFILENAME_STR "dllhost.exe"
+
+#include "common.ver"
diff --git a/private/ole32/dllhost/libtable.cxx b/private/ole32/dllhost/libtable.cxx
new file mode 100644
index 000000000..4ab49dcd4
--- /dev/null
+++ b/private/ole32/dllhost/libtable.cxx
@@ -0,0 +1,413 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: libtable.cxx
+//
+// Contents: Classes for storing info about loaded inproc dll servers
+//
+//
+// History: 21-May-96 t-AdamE Created
+//
+//--------------------------------------------------------------------------
+
+#include <debnot.h>
+#include "csrgt.hxx"
+#include "libtable.hxx"
+
+CLibTable* CLibTable::_ptbLibs = NULL;
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllList::CDllList()
+//
+// Synopsis: constructor for CDllList
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+
+CDllList::CDllList() :
+ _pHead(NULL),
+ _pCurrent(NULL),
+ _citems(0)
+{
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllList::~CDllList()
+//
+// Synopsis: destructor for CDllList
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+
+CDllList::~CDllList()
+{
+ Clear();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllList::Clear
+//
+// Synopsis: Removes all the items in a CDllList
+//
+//
+// History: 6-21-96 t-Adame Created
+//
+// Notes: This function calls Remove on each item in the list until
+// it is empty.
+//
+//----------------------------------------------------------------------------
+
+void CDllList::Clear()
+{
+ // iterate through the list and free
+ // everything
+ while(!FIsEmpty())
+ {
+ Remove();
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllList::Revoke
+//
+// Synopsis: Revokes class factories for all dll servers in the CDllList
+//
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+
+void CDllList::Revoke()
+{
+ CDllServer* pCurrent;
+
+ Reset();
+
+ // iterate through the list and revoke
+ // everything
+ while(pCurrent = GetCurrentLib())
+ {
+ pCurrent->Revoke();
+ if(!(FMoveNext()))
+ {
+ break;
+ }
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllList::GetCurrent
+//
+// Synopsis: returns the current node in the list
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+CDllServerNode* CDllList::GetCurrent()
+{
+ return _pCurrent;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllList::Insert
+//
+// Synopsis: Inserts an item into the list and makes it the current item
+// Insertion occurs after the current item
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+
+HRESULT CDllList::Insert(REFCLSID clsid)
+{
+ CDllServerNode* pNew = new CDllServerNode(clsid);
+
+ if(!pNew)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ HRESULT hr;
+ if(FAILED(hr = pNew->GetItem()->LoadServer()))
+ {
+ delete pNew;
+ return hr;
+ }
+
+ pNew->SetNext(_pHead);
+ _pHead = pNew;
+
+ _citems++;
+
+ Reset();
+
+ return S_OK;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllList::Remove
+//
+// Synopsis: removes an item from the front of the list and deletes it
+//
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+
+HRESULT CDllList::Remove()
+{
+ if(!_pCurrent)
+ {
+ return E_FAIL;
+ }
+
+ CDllServerNode* pHeadOld = _pHead;
+
+ _pHead = pHeadOld->GetNext();
+
+ delete pHeadOld;
+
+ _citems--;
+
+ Reset();
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllList::GetCurrentLib
+//
+// Synopsis: returns the library pointed to by the lists's current pointer
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+CDllServer* CDllList::GetCurrentLib()
+{
+ return GetCurrent()->GetItem();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllList::Reset
+//
+// Synopsis: sets the current to the beginning of the list
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+void CDllList::Reset()
+{
+ _pCurrent = _pHead;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllList::FMoveNext
+//
+// Synopsis: moves the next cursor to the next item
+// returns TRUE if the function was successful, FALSE if
+// the cursor couldn't be moved forward (i.e. you're at the
+// last element already)
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+BOOL CDllList::FMoveNext()
+{
+ if(_pCurrent)
+ {
+ if(_pCurrent->GetNext())
+ {
+ _pCurrent = _pCurrent->GetNext();
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllList::FIsEmpty
+//
+// Synopsis: returns TRUE if the list is empty, false if not
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+
+BOOL CDllList::FIsEmpty()
+{
+ Win4Assert((_pHead == NULL) == (_pCurrent == NULL));
+ return _pHead == NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CDllList::CItems
+//
+// Synopsis: returns a count of items in the list
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+ULONG CDllList::CItems()
+{
+ return _citems;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLibTable::CLibTable()
+//
+// Synopsis: constructor for CLibTable
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+CLibTable::CLibTable() :
+ _clibs(0)
+{
+ CLibTable::_ptbLibs = this;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLibTable::~CLibTable()
+//
+// Synopsis: destructor for CLibTable
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+CLibTable::~CLibTable()
+{
+ m_dllCollection.Clear();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLibTable::Clear
+//
+// Synopsis: removes all libraries from the table
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+void CLibTable::Clear()
+{
+ ENTERMONITOR;
+ m_dllCollection.Clear();
+ LEAVEMONITOR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLibTable::Revoke
+//
+// Synopsis: revokes all the class factories of all libraries in the table
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+void CLibTable::Revoke()
+{
+ ENTERMONITOR;
+ m_dllCollection.Revoke();
+ LEAVEMONITOR;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLibTable::LoadDllServer
+//
+// Synopsis: inserts the dll server corresponding to the clsid parameter
+// into the table. This insertion implicitly starts that server
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+HRESULT CLibTable::LoadDllServer(REFIID clsid)
+{
+ ENTERMONITOR;
+ HRESULT hr;
+ if(FAILED(hr = m_dllCollection.Insert(clsid)))
+ {
+ LEAVEMONITOR;
+ return hr;
+ }
+
+ _clibs++;
+ LEAVEMONITOR;
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLibTable::WaitForSafeLibraryFree
+//
+// Synopsis: Sleeps the calling thread, waking periodically to free
+// unused libraries. It exits when an event signaled by a call
+// from OLE through the FreeSurrogate method of ISurrogate is
+// executed.
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+
+void CLibTable::WaitForSafeLibraryFree()
+{
+ if(!(CSurrogate::_hEventAllLibsFree = CreateEvent(NULL,FALSE,FALSE,NULL)))
+ {
+ return;
+ }
+
+ // wait for the FreeSurrogate method of ISurrogate to be called
+ while(WaitForSingleObject(CSurrogate::_hEventAllLibsFree, _dwCheckInterval)
+ == WAIT_TIMEOUT)
+ {
+ // if the wait timed-out, free any unnecessary dll's
+ CoFreeUnusedLibraries();
+ }
+
+ // the wait ended with a signal, so we're done
+ CloseHandle(CSurrogate::_hEventAllLibsFree);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLibTable::FSingleton
+//
+// Synopsis: Returns TRUE if this table has exactly one element in it,
+// FALSE if it has 0 or more than one elements.
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+BOOL CLibTable::FSingleton()
+{
+ ENTERMONITOR;
+ BOOL fSingleton = m_dllCollection.CItems() == 1;
+ LEAVEMONITOR;
+ return fSingleton;
+}
+
+
diff --git a/private/ole32/dllhost/libtable.hxx b/private/ole32/dllhost/libtable.hxx
new file mode 100644
index 000000000..4729bbfd9
--- /dev/null
+++ b/private/ole32/dllhost/libtable.hxx
@@ -0,0 +1,152 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: libtable.hxx
+//
+// Contents: Classes for storing info about loaded inproc dll servers
+//
+//
+// History: 21-May-96 t-AdamE Created
+//
+//--------------------------------------------------------------------------
+
+#if !defined(__LIBTABLE_HXX__)
+#define __LIBTABLE_HXX__
+
+#include <windows.h>
+#include <ole2.h>
+#include "cmonitor.hxx"
+#include "cdllsrv.hxx"
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDllServerNode
+//
+// Purpose: node container for CDllServers for use in linked lists
+//
+// History: 21-May-96 t-Adame Created
+//
+//--------------------------------------------------------------------------
+
+class CDllServerNode; // forward declaration
+
+class CDllServerNode : public CSrgtMem
+{
+public:
+
+ CDllServerNode(REFCLSID clsid) :
+ _srvr(clsid),
+ _pnext(NULL){}
+
+ CDllServerNode* GetNext()
+ {
+ return _pnext;
+ }
+
+ void SetNext(CDllServerNode* pnext)
+ {
+ _pnext = pnext;
+ }
+
+
+ CDllServer* GetItem()
+ {
+ return &_srvr;
+ }
+
+private:
+
+ CDllServerNode* _pnext;
+ CDllServer _srvr;
+};
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDllList
+//
+// Purpose: Linked list of CDllServer's.
+//
+// Notes: The list is manipulated with a cursor which keeps track
+// of a current object. Methods for moving the cursor
+// forward and backward are provided, as well as a method
+// for setting the position of the cursor to the beginning
+// of the list. All list operations (insert, remove, etc)
+// take place on the current object.
+//
+// History: 21-May-96 t-Adame Created
+//
+//--------------------------------------------------------------------------
+
+class CDllList
+{
+public:
+
+ CDllList();
+ ~CDllList();
+
+ void Clear();
+ void Revoke();
+
+ HRESULT Insert(REFCLSID clsid);
+ HRESULT Remove();
+
+ CDllServer* GetCurrentLib();
+
+ void Reset();
+ BOOL FMoveNext();
+ BOOL FIsEmpty();
+ ULONG CItems();
+
+private:
+
+ CDllServerNode* GetCurrent();
+ CDllServerNode* _pHead;
+ CDllServerNode* _pCurrent;
+ ULONG _citems;
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CLibTable
+//
+// Purpose: Store for information on loaded inproc dll servers
+//
+// History: 21-May-96 t-Adame Created
+//
+//--------------------------------------------------------------------------
+
+class CLibTable; // foward declaration
+
+class CLibTable : public CMonitor
+{
+
+public:
+
+ CLibTable();
+ ~CLibTable();
+
+ void Clear();
+ void Revoke();
+
+ HRESULT LoadDllServer(REFCLSID clsid);
+ BOOL FSingleton();
+ void WaitForSafeLibraryFree();
+
+ static CLibTable* _ptbLibs;
+
+private:
+
+ enum {
+ _dwCheckInterval = 60000
+ };
+
+ CDllList m_dllCollection;
+
+ ULONG _clibs;
+};
+
+
+#endif // __LIBTABLE_HXX__
diff --git a/private/ole32/dllhost/srgtfact.cxx b/private/ole32/dllhost/srgtfact.cxx
new file mode 100644
index 000000000..9ee78c02e
--- /dev/null
+++ b/private/ole32/dllhost/srgtfact.cxx
@@ -0,0 +1,401 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: srgtfact.cxx
+//
+// Contents: Class the implements the ISurrogate interface
+//
+//
+// History: 21-May-96 t-AdamE Created
+//
+//--------------------------------------------------------------------------
+
+#include <debnot.h>
+#include "csrgt.hxx"
+#include "srgtfact.hxx"
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSrgtMem::operator new
+//
+// Synopsis: uses ole's allocator to get blocks
+//
+// History: 10-30-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+void* _CRTAPI1 CSrgtMem::operator new(size_t cbsize)
+{
+ return CoTaskMemAlloc(cbsize);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSrgtMem::operator delete
+//
+// Synopsis: uses ole's allocator to free blocks
+//
+// History: 10-30-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+void _CRTAPI1 CSrgtMem::operator delete(void* pv)
+{
+ CoTaskMemFree(pv);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogateFactory::CSurrogateFactory()
+//
+// Synopsis: constructor for CSurrogateFactory
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+CSurrogateFactory::CSurrogateFactory(REFCLSID clsid) :
+ _dwRegister(0),
+ _clsid(clsid),
+ _cref(0)
+{}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogateFactory::Register()
+//
+// Synopsis: destructor for CSurrogateFactory
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+HRESULT CSurrogateFactory::Register()
+{
+ HRESULT hr;
+
+ if(FAILED(hr = CoRegisterClassObject(
+ _clsid,
+ (IUnknown*)(void*)this,
+ CLSCTX_LOCAL_SERVER,
+ REGCLS_SURROGATE,
+ &_dwRegister)))
+ {
+ return hr;
+ }
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogateFactory::Revoke()
+//
+// Synopsis: revokes this class factory object
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+HRESULT CSurrogateFactory::Revoke()
+{
+ return CoRevokeClassObject(_dwRegister);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogateFactory::QueryInterface
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CSurrogateFactory::QueryInterface(REFIID iid, LPVOID* ppv)
+{
+ if(iid == IID_IUnknown)
+ {
+ *ppv = (void*)((IUnknown*)(void*)this);
+ AddRef();
+ return S_OK;
+ }
+ else if (iid == IID_IClassFactory)
+ {
+ *ppv = (void*)(IClassFactory*)this;
+ AddRef();
+ return S_OK;
+ }
+ else if (iid == IID_IMarshal)
+ {
+ *ppv = (void*)(IMarshal*)this;
+ AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogateFactory::AddRef()
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+ULONG CSurrogateFactory::AddRef()
+{
+ InterlockedIncrement((LPLONG)&_cref);
+ ULONG cref = _cref;
+ Win4Assert(_cref > 0);
+ return cref;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogateFactory::Release()
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+ULONG CSurrogateFactory::Release()
+{
+ Win4Assert(_cref > 0);
+
+ if(!(InterlockedDecrement((LPLONG)&_cref)))
+ {
+ delete this;
+ return 0;
+ }
+
+ ULONG cref = _cref;
+
+ return cref;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogateFactory::CreateInstance
+//
+// Notes: This create instance does a CoGetClassObject to get the
+// real class factory for this clsid (the class factory
+// implemented in the dll). It then calls CreateInstance on that
+// class factory
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CSurrogateFactory::CreateInstance(IUnknown* pUnkOuter, REFIID iid, void** ppv)
+{
+ void* pcf;
+ HRESULT hr;
+
+ if(SUCCEEDED(hr = CoGetClassObject(
+ _clsid,
+ CLSCTX_INPROC_SERVER,
+ NULL,
+ IID_IClassFactory,
+ &pcf)))
+ {
+ hr = ((IClassFactory*)pcf)->CreateInstance(pUnkOuter, iid, ppv);
+ ((IClassFactory*)pcf)->Release();
+ }
+
+ if(FAILED(hr))
+ {
+ // if we can't get the real class factory, the
+ // client won't be able to use it to create an instance
+ // of the class (the one in the dll), so now we
+ // close the surrogate if this is the only class in the
+ // process
+
+ CLibTable::_ptbLibs->EnterMonitor();
+
+ if(CLibTable::_ptbLibs->FSingleton())
+ {
+ CLibTable::_ptbLibs->LeaveMonitor();
+ CSurrogate::_pSurrogate->FreeSurrogate();
+ return hr;
+ }
+
+ CLibTable::_ptbLibs->LeaveMonitor();
+ }
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogateFactory::LockServer()
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CSurrogateFactory::LockServer(BOOL fLock)
+{
+ return S_OK;
+}
+
+// REVIEW: currently, the only IMarshal methods we implement are
+// MarshalInterface and GetUnMarshalClass. If any other method on our
+// IMarshal is called, we assert and return E_NOTIMPL.
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogateFactory::GetUnMarshalClass
+//
+// Notes: This function returns CLSID_StdMarshal through the pClsid
+// parameter so that COM will use standard marshalling on
+// this interface
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CSurrogateFactory::GetUnmarshalClass(
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags,
+ CLSID *pClsid)
+{
+ *pClsid = CLSID_StdMarshal;
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogateFactory::GetMarshalSizeMax
+//
+// Notes: This function does nothing at this time.
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+//REVIEW: do we need to give this method a real implementation?
+STDMETHODIMP CSurrogateFactory::GetMarshalSizeMax(
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags,
+ DWORD *pSize)
+{
+ Win4Assert(FALSE);
+ return E_NOTIMPL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogateFactory::MarshalInterface
+//
+// Notes: Since this class factory is simply a stand-in for the dll's
+// class factory, we need to get the dll's class factory and
+// marshal it instead of this class factory for CoGetClassObject.
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CSurrogateFactory::MarshalInterface(
+ IStream *pStm,
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags)
+{
+ void* pCF = NULL;
+ HRESULT hr;
+
+ // get the real class factory object with the
+ // requested interface
+
+ if(SUCCEEDED(hr = CoGetClassObject(
+ _clsid,
+ CLSCTX_INPROC_SERVER,
+ NULL,
+ riid,
+ &pCF)))
+ {
+
+ hr = CoMarshalInterface(
+ pStm,
+ riid,
+ (IUnknown*)pCF,
+ dwDestContext,
+ pvDestContext,
+ mshlflags);
+
+ ((IUnknown*)pCF)->Release();
+ }
+
+ if(FAILED(hr))
+ {
+ // if we can't marshal the real class factory, the
+ // client won't be able to use it to create an instance
+ // of the real class (the one in the dll), so now we
+ // close the surrogate if this is the only class in the
+ // process
+
+ CLibTable::_ptbLibs->EnterMonitor();
+
+ if(CLibTable::_ptbLibs->FSingleton())
+ {
+ CLibTable::_ptbLibs->LeaveMonitor();
+ CSurrogate::_pSurrogate->FreeSurrogate();
+ return hr;
+ }
+
+ CLibTable::_ptbLibs->LeaveMonitor();
+ }
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogateFactory::UnMarshalInterface
+//
+// Notes: This function does nothing at this time.
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+//REVIEW: do we need to give this method a real implementation?
+STDMETHODIMP CSurrogateFactory::UnmarshalInterface(IStream *pStm,REFIID riid,void **ppv)
+{
+ Win4Assert(FALSE);
+ return E_NOTIMPL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogateFactory::GetUnMarshalClass
+//
+// Notes: This function does nothing at this time.
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+//REVIEW: do we need to give this method a real implementation?
+STDMETHODIMP CSurrogateFactory::ReleaseMarshalData(IStream *pStm)
+{
+ Win4Assert(FALSE);
+ return E_NOTIMPL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSurrogateFactory::DisconnectObject
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+// REVIEW: should be ok to return S_OK since we're not doing anything fancy?
+STDMETHODIMP CSurrogateFactory::DisconnectObject(DWORD dwReserved)
+{
+ return S_OK;
+}
+
+
diff --git a/private/ole32/dllhost/srgtfact.hxx b/private/ole32/dllhost/srgtfact.hxx
new file mode 100644
index 000000000..4a0039a68
--- /dev/null
+++ b/private/ole32/dllhost/srgtfact.hxx
@@ -0,0 +1,119 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: srgtfact.hxx
+//
+// Contents: Class that implements a surrogate class factory
+// for dll servers that will be instantiated in surrogate
+// processes.
+//
+//
+// History: 21-May-96 t-AdamE Created
+//
+//--------------------------------------------------------------------------
+
+#if !defined(__SRGTFACT_HXX__)
+#define __SRGTFACT_HXX__
+
+#include <windows.h>
+#include <ole2.h>
+#include "cmonitor.hxx"
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSrgtMem
+//
+// Purpose: allow classes to use new and delete with OLE's allocator
+//
+// History: 30-Oct-96 t-Adame Created
+//
+//--------------------------------------------------------------------------
+class CSrgtMem
+{
+public:
+
+ void* _CRTAPI1 operator new(size_t cbsize);
+
+ void _CRTAPI1 operator delete(void* pv);
+
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSurrogateFactory
+//
+// Purpose: Class factory that is registered via CoRegisterClassObject
+// for all classes that are to be loaded into a surrogate.
+//
+// Notes: In order to be threadsafe, this class inherits from CMonitor,
+// whose methods are used in any methods which manipulate state
+// data
+//
+// History: 21-May-96 t-Adame Created
+//
+//--------------------------------------------------------------------------
+class CSurrogateFactory : IClassFactory, public IMarshal, public CSrgtMem
+{
+public:
+
+ CSurrogateFactory(REFCLSID clsid);
+
+ // methods from IUnknown
+ STDMETHOD (QueryInterface)(REFIID iid, LPVOID* ppv);
+ STDMETHOD_(ULONG,AddRef)();
+ STDMETHOD_(ULONG,Release)();
+
+ // methods from IClassFactory
+ STDMETHOD (CreateInstance)(IUnknown* pUnkOuter, REFIID iid, void** ppv);
+ STDMETHOD (LockServer)(BOOL fLock);
+
+ // methods from IMarshal
+ STDMETHOD (GetUnmarshalClass)(
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags,
+ CLSID *pCid);
+
+ STDMETHOD (GetMarshalSizeMax)(
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags,
+ DWORD *pSize);
+
+ STDMETHOD (MarshalInterface)(
+ IStream *pStm,
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags);
+
+ STDMETHOD (UnmarshalInterface)(IStream *pStm,REFIID riid,void **ppv);
+
+ STDMETHOD (ReleaseMarshalData)(IStream *pStm);
+
+ STDMETHOD (DisconnectObject)(DWORD dwReserved);
+
+ HRESULT Register();
+ HRESULT Revoke();
+
+
+
+protected:
+
+ CLSID _clsid;
+ DWORD _dwRegister;
+ ULONG _cref;
+};
+
+
+#endif // !defined(__SRGTFACT_HXX__)
+
diff --git a/private/ole32/dllhost/surrogat.cxx b/private/ole32/dllhost/surrogat.cxx
new file mode 100644
index 000000000..4cbe010bf
--- /dev/null
+++ b/private/ole32/dllhost/surrogat.cxx
@@ -0,0 +1,321 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: surrogat.cxx
+//
+// Contents: Entry point for dll surrogate process
+//
+// Synopsis: this is the entry point for a surrogate process. It must
+// perform the following tasks
+// 1. Initialize OLE (multithreaded)
+// 2. Initialize security to use app id settings
+// 3. Create an object which implements ISurrogate, and register
+// it with COM via CoRegisterSurrogate
+// 4. Load the inproc server specified on the command line and
+// register its class factory. The command line takes the format
+// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx}. Loading is accomplished
+// via the LoadDllServer method of ISurrogate
+// 5. Wait for all loaded dlls to be unloadable
+// 6. Uninitialize OLE
+//
+// Functions: WinMain
+// GetCommandLineArguments
+// InitializeSecurity
+//
+// History: 21-May-96 t-AdamE Created
+//
+//--------------------------------------------------------------------------
+
+#include <iostream.h>
+#include <windows.h>
+#include "csrgt.hxx"
+#include "surrogat.hxx"
+
+
+int WINAPI WinMain(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nCmdShow)
+{
+ CLSID cid; // will hold the clsid of inproc server on command line
+ CSurrogate srgt; // implements ISurrogate, a requirement for surrogate processes
+ CHAR rgargv[cCmdLineArguments][MAX_PATH + 1];
+ LPSTR argv[] = {rgargv[iClsidArgument]};
+ WCHAR wszClsid[MAX_GUIDSTR_LEN + 1];
+
+ if(FAILED(CoInitializeEx(NULL,COINIT_MULTITHREADED)))
+ {
+ return 0;
+ }
+
+ srgt.AddRef();
+
+ // command line format should be:
+ // (<clsid>)
+ if(GetCommandLineArguments(lpCmdLine, argv,cCmdLineArguments,MAX_PATH) < 1)
+ {
+ goto cleanup_and_exit;
+ }
+
+ // set up security
+ if(FAILED(InitializeSecurity(argv[iClsidArgument])))
+ {
+ goto cleanup_and_exit;
+ }
+
+ // we need a unicode string in order to get a guid, so convert
+ // the ansi clsid string to unicode
+ if(!(MultiByteToWideChar(CP_ACP,
+ 0,
+ argv[iClsidArgument],
+ lstrlenA(argv[iClsidArgument]) + 1,
+ wszClsid,
+ MAX_GUIDSTR_LEN + 1)))
+ {
+ goto cleanup_and_exit;
+ }
+
+ // convert the clsid from a string to a guid
+ if(FAILED(CLSIDFromString(wszClsid,&cid)))
+ {
+ goto cleanup_and_exit;
+ }
+
+ // Register the ISurrogate so COM can use it to load
+ // additional dlls
+ if(FAILED(CoRegisterSurrogate((ISurrogate*)&srgt)))
+ {
+ return 0;
+ }
+
+ // load the inproc server specified on the command line
+ if(FAILED(srgt.LoadDllServer(cid)))
+ {
+ goto cleanup_and_exit;
+ }
+
+ // Wait for all the servers to finish
+ srgt.WaitForSafeLibraryFree();
+
+cleanup_and_exit:
+
+ srgt.Release();
+
+ CoUninitialize();
+
+ return 0;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetCommandLineArguments
+//
+// Synopsis: Parses a the application's command line into a format
+// similar to the
+// argv parameter of the entry point main for console apps
+// Spaces are the delimiters
+//
+// Arguments: [rgwszArgs] -- an array of pointers to allocated Unicode
+// buffers
+// [cMaxArgs] -- This is the size of the rgwszArgs array (the
+// maximum number of arguments the array can hold).
+// [cMaxArgLen] -- The maximum size of each buffer
+//
+// Returns: if successful, the function returns the number of arguments
+// parsed from the command line. If the length of any argument
+// exceeds cMaxArgLen, the function fails and returns 0.
+//
+// The function quits parsing and returns as soon as either of
+// the following conditions is met:
+// 1. It reaches the end of the string, or
+// 2. It parses cMaxArgs arguments.
+//
+// Notes: does not work with quoted arguments
+//
+// History: 6-21-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+// REVIEW: when we had several commandline parameters this function was
+// justified, but now that the Surrogate has only one parameter, is all this
+// really necessary?
+int GetCommandLineArguments(LPSTR szCmdLine, LPSTR rgszArgs[], int cMaxArgs, int cMaxArgLen)
+{
+ int cchlen = lstrlenA(szCmdLine);
+ int cArgsRetrieved = 0;
+ int ichStart = 0;
+
+ for(int ich = 0;ich < cchlen; ich++)
+ {
+ if(ichStart > cMaxArgLen)
+ {
+ return 0;
+ }
+
+ CHAR chcur = *(szCmdLine++);
+ if(chcur == ' ')// REVIEW: no tab delimiting -- is this good?
+ {
+ if(ichStart)
+ {
+ rgszArgs[cArgsRetrieved++][ichStart] = '\0';
+ ichStart = 0;
+
+ if(cArgsRetrieved == cMaxArgs)
+ {
+ return cArgsRetrieved;
+ }
+
+ }
+ }
+ else
+ {
+ rgszArgs[cArgsRetrieved][ichStart++] = chcur;
+ }
+ }
+
+ if(ichStart)
+ {
+ rgszArgs[cArgsRetrieved][ichStart] = '\0';
+ cArgsRetrieved++;
+ }
+
+ return cArgsRetrieved;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: InitializeSecurity
+//
+// Synopsis: Reads the registry to find the AppID for the clsid passed
+// in the szClsid param. It passes this appid to
+// CoInitializeSecurity so that the surrogate will have
+// the security settings specified under the clsid's appid
+//
+// Arguments: [szClsid] -- an ansi string representing the CLSID for
+// the surrogate
+//
+// Returns: S_OK if successful, otherwise a standard error hresult
+//
+// History: 10-17-96 t-Adame Created
+//
+//----------------------------------------------------------------------------
+HRESULT InitializeSecurity(LPSTR szClsid)
+{
+ BOOL fRetval = FALSE;
+ HKEY hkClsid = NULL;
+ HKEY hkThisClsid = NULL;
+ IID iid;
+ CHAR szAppid[MAX_GUIDSTR_LEN + 1];
+ WCHAR wszAppid[MAX_GUIDSTR_LEN + 1];
+ DWORD dwAppidSize = sizeof(szAppid);
+ HRESULT hr = E_FAIL;
+
+ // open HKEY_CLASSES_ROOT/CLSID
+ if(RegOpenKeyExA(
+ HKEY_CLASSES_ROOT,
+ szClsidKeyName,
+ 0,
+ KEY_READ,
+ &hkClsid) != ERROR_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ // open the key for the CLSID requested for this surrogate
+ if(RegOpenKeyExA(
+ hkClsid,
+ szClsid,
+ 0,
+ KEY_READ,
+ &hkThisClsid) != ERROR_SUCCESS)
+ {
+ goto cleanup_and_exit;
+ }
+
+ // read the appid value
+ if(RegQueryValueExA(
+ hkThisClsid,
+ szAppidValueName,
+ NULL,
+ NULL,
+ (LPBYTE)szAppid,
+ &dwAppidSize) != ERROR_SUCCESS)
+ {
+ goto cleanup_and_exit;
+ }
+
+ // we're done with the registry, close the keys
+ RegCloseKey(hkThisClsid);
+ hkThisClsid = NULL;
+
+ RegCloseKey(hkClsid);
+ hkClsid = NULL;
+
+ // now convert the appid string from the registry into
+ // a unicode string
+ if(!(MultiByteToWideChar(
+ CP_ACP,
+ 0,
+ szAppid,
+ lstrlenA(szAppid) + 1,
+ wszAppid,
+ MAX_GUIDSTR_LEN + 1)))
+ {
+ goto cleanup_and_exit;
+ }
+
+ // use the unicode appid string to create a guid
+ hr = IIDFromString(wszAppid,&iid);
+
+ if(FAILED(hr))
+ {
+ goto cleanup_and_exit;
+ }
+
+ // now we finally have the information we need
+ // to call CoInitializeSecurity
+
+ hr = CoInitializeSecurity(
+ (PSECURITY_DESCRIPTOR*)&iid,
+ -1,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ NULL,
+ EOAC_APPID,
+ NULL);
+
+ // if there was no security descriptor, that's ok -- we'll
+ // let COM set up security later when we marshal an interface
+ if(hr == MAKE_SCODE(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND))
+ {
+ hr = S_OK;
+ }
+
+cleanup_and_exit:
+
+ // free any active resources
+ if(hkThisClsid)
+ {
+ RegCloseKey(hkThisClsid);
+ }
+
+ if(hkClsid)
+ {
+ RegCloseKey(hkClsid);
+ }
+
+ return hr;
+
+}
+
+
+
+
+
+
diff --git a/private/ole32/dllhost/surrogat.hxx b/private/ole32/dllhost/surrogat.hxx
new file mode 100644
index 000000000..671de9f29
--- /dev/null
+++ b/private/ole32/dllhost/surrogat.hxx
@@ -0,0 +1,36 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: surrogat.hxx
+//
+// Contents: declarations for the surrogate entry point
+//
+// History: 03-Jun-96 t-AdamE Created
+//
+//--------------------------------------------------------------------------
+
+#if !defined(__SURROGAT_HXX__)
+#define __SURROGAT_HXX__
+
+#include <windows.h>
+
+#define cCmdLineArguments 1
+#define iClsidArgument 0
+
+#define MAX_GUIDSTR_LEN 40
+
+
+const CHAR szClsidKeyName[] = "CLSID";
+const CHAR szAppidValueName[] = "AppID";
+
+int GetCommandLineArguments(
+ LPSTR szCmdLine,
+ LPSTR rgszArgs[],
+ int cMaxArgs,
+ int cMaxArgLen);
+
+HRESULT InitializeSecurity(LPSTR szClsid);
+
+#endif // __SURROGAT_HXX__
diff --git a/private/ole32/filelist.mk b/private/ole32/filelist.mk
new file mode 100644
index 000000000..cb43756c6
--- /dev/null
+++ b/private/ole32/filelist.mk
@@ -0,0 +1,27 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+#
+# Makefile for the CAIROLE Project
+#
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+!if "$(OPSYS)" == "NT"
+
+# Build for cairo
+SUBDIRS = ole propset
+
+!else
+
+SUBDIRS = common ilib ole232 com
+
+!endif
diff --git a/private/ole32/ih/alocdbg.h b/private/ole32/ih/alocdbg.h
new file mode 100644
index 000000000..dcf9f594e
--- /dev/null
+++ b/private/ole32/ih/alocdbg.h
@@ -0,0 +1,108 @@
+//+---------------------------------------------------------------------------
+// File: alocdbg.h
+//
+// Contents: Heap debugging structures and routines for the heap code
+// in commnot
+//
+// History: 28-Oct-92 IsaacHe Created
+// 23-Jan-95 KevinRo Moved into cairole\ih and renamed
+//
+//----------------------------------------------------------------------------
+
+//
+// We keep a stack backtrace for each allocated block of memory. DEPTHTRACE
+// is the number of frames that we record
+//
+#define DEPTHTRACE 26 // depth of stack backtraces
+
+//
+// The AllocArena structure has this signature at its front. We put a
+// signature on the structure to allow external processes to snapshot the
+// debug information and do some minimal check to see they are looking at the
+// right stuff
+//
+const char HEAPSIG[] = { 'H', 'E', 'P', DEPTHTRACE };
+
+// We keep track of the stack backtraces of allocation calls
+// in these structues.
+
+struct HeapAllocRec {
+ DWORD sum; // checksum of stack backtrace
+ void *fTrace[ DEPTHTRACE ]; // stack backtrace
+ DWORD count; // # of un-freed allocs from this place
+ size_t bytes; // # of un-freed bytes from this place
+ struct AllocArena *paa; // points back to the beginning...
+ struct {
+ DWORD count; // # of allocs from this place
+ size_t bytes; // # of bytes from this place
+ } total;
+ union {
+ struct HeapAllocRec *next; // next bucket in the hash list
+ void *ImageBase; // base addr of containing module
+ } u;
+};
+
+struct AllocArena {
+
+ char Signature [ sizeof(HEAPSIG) ];
+ char comment[ 32 ];
+ CRITICAL_SECTION csExclusive; // ensures single writer
+
+ struct {
+ int KeepStackTrace:1; // are stack records being kept?
+ } flags;
+
+ ULONG cAllocs; // # of non zero Alloc calls
+ ULONG czAllocs; // # of Alloc calls w/zero count
+ ULONG cFrees; // # of Free calls
+ ULONG cReAllocs; // # of realloc calls
+ ULONG cMissed; // # of missed stack backtraces
+ ULONG cRecords; // index of next free AllocRec entry
+ ULONG cBytesNow; // # of bytes currently allocated
+ ULONG cBytesTotal; // # of bytes ever allocated
+ ULONG cTotalRecords; // Total # of AllocRecs
+ ULONG cPaths; // # of distinct allocation paths
+
+ struct {
+ ULONG total[ 32 ]; // total number of allocations
+ ULONG now[ 32 ]; // current # of simul allocs
+ ULONG simul[ 32 ]; // highest # of simul allocs
+ } Histogram;
+
+ struct HeapAllocRec AllocRec[1]; // vector of records starts here..
+};
+
+/*
+ * Allocators may want to associate one of these structures with every
+ * allocation...
+ */
+struct AHeader {
+ struct HeapAllocRec FAR *p;
+ size_t size;
+};
+
+STDAPI_(struct AllocArena ** )
+AllocArenaAddr( void );
+
+STDAPI_( struct AllocArena * )
+AllocArenaCreate( DWORD memctx, char FAR *comment );
+
+STDAPI_( struct HeapAllocRec FAR * )
+AllocArenaRecordAlloc( struct AllocArena *paa, size_t bytes );
+
+STDAPI_(void)
+AllocArenaRecordReAlloc( struct HeapAllocRec FAR *vp,
+ size_t oldbytes, size_t newbytes );
+
+STDAPI_(void)
+AllocArenaRecordFree( struct HeapAllocRec FAR *vp, size_t bytes );
+
+STDAPI_(void)
+AllocArenaDump( struct AllocArena *paa );
+
+STDAPI_( void )
+AllocArenaDumpRecord( struct HeapAllocRec FAR *bp );
+
+// This is our interface to symhelp for address translation
+ULONG RealTranslate ( ULONG address, LPSTR name, ULONG maxNameLength);
+
diff --git a/private/ole32/ih/chicole.reg b/private/ole32/ih/chicole.reg
new file mode 100644
index 000000000..de44b6c10
--- /dev/null
+++ b/private/ole32/ih/chicole.reg
@@ -0,0 +1,380 @@
+REGEDIT
+HKEY_CLASSES_ROOT\CLSID
+
+//
+// The values of the following keys need to be localized
+// 11-16-93
+// LANGUAGE: USA
+//
+
+; The string "Edit" below is to be localized.
+HKEY_CLASSES_ROOT\Software\Microsoft\OLE1\UnregisteredVerb = Edit
+
+; The string "Unknown" below is to be localized.
+HKEY_CLASSES_ROOT\Software\Microsoft\OLE2\UnknownUserType = Unknown
+
+; The string "Picture (Metafile)" is to be localized.
+HKEY_CLASSES_ROOT\StaticMetafile = Picture (Metafile)
+HKEY_CLASSES_ROOT\CLSID\{00000315-0000-0000-C000-000000000046} = Picture (Metafile)
+
+; The string "Picture" is to be localized.
+HKEY_CLASSES_ROOT\CLSID\{00000315-0000-0000-C000-000000000046}\AuxUserType\2 = Picture
+HKEY_CLASSES_ROOT\CLSID\{00000316-0000-0000-C000-000000000046}\AuxUserType\2 = Picture
+
+; The string "Picture (Device Independent Bitmap)" is to be localized.
+HKEY_CLASSES_ROOT\StaticDib = Picture (Device Independent Bitmap)
+HKEY_CLASSES_ROOT\CLSID\{00000316-0000-0000-C000-000000000046} = Picture (Device Independent Bitmap)
+
+; The string "Paintbrush Picture" is to be localized.
+HKEY_CLASSES_ROOT\CLSID\{0003000a-0000-0000-C000-000000000046} = Paintbrush Picture
+
+; The string "Microsoft Drawing" is to be localized.
+HKEY_CLASSES_ROOT\CLSID\{00030007-0000-0000-C000-000000000046} = Microsoft Drawing
+
+
+// -------------------- NO LOCALIZATION NECESSARY BELOW THIS LINE ------------
+
+HKEY_CLASSES_ROOT\CLSID\{00000300-0000-0000-C000-000000000046} = StdOleLink
+HKEY_CLASSES_ROOT\CLSID\{00000300-0000-0000-C000-000000000046}\InprocServer32 = ole32.dll
+HKEY_CLASSES_ROOT\CLSID\{00000301-0000-0000-C000-000000000046} = StdMemStm
+HKEY_CLASSES_ROOT\CLSID\{00000301-0000-0000-C000-000000000046}\InprocServer32 = ole32.dll
+HKEY_CLASSES_ROOT\CLSID\{00000302-0000-0000-C000-000000000046} = StdMemBytes
+HKEY_CLASSES_ROOT\CLSID\{00000302-0000-0000-C000-000000000046}\InprocServer32 = ole32.dll
+HKEY_CLASSES_ROOT\CLSID\{00000303-0000-0000-C000-000000000046} = FileMoniker
+HKEY_CLASSES_ROOT\CLSID\{00000303-0000-0000-C000-000000000046}\InprocServer32 = ole32.dll
+HKEY_CLASSES_ROOT\CLSID\{00000304-0000-0000-C000-000000000046} = ItemMoniker
+HKEY_CLASSES_ROOT\CLSID\{00000304-0000-0000-C000-000000000046}\InprocServer32 = ole32.dll
+HKEY_CLASSES_ROOT\CLSID\{00000305-0000-0000-C000-000000000046} = AntiMoniker
+HKEY_CLASSES_ROOT\CLSID\{00000305-0000-0000-C000-000000000046}\InprocServer32 = ole32.dll
+HKEY_CLASSES_ROOT\CLSID\{00000306-0000-0000-C000-000000000046} = PointerMoniker
+HKEY_CLASSES_ROOT\CLSID\{00000306-0000-0000-C000-000000000046}\InprocServer32 = ole32.dll
+HKEY_CLASSES_ROOT\CLSID\{00000308-0000-0000-C000-000000000046} = PackagerMoniker
+HKEY_CLASSES_ROOT\CLSID\{00000308-0000-0000-C000-000000000046}\InprocServer32 = ole32.dll
+HKEY_CLASSES_ROOT\CLSID\{00000309-0000-0000-C000-000000000046} = CompositeMoniker
+HKEY_CLASSES_ROOT\CLSID\{00000309-0000-0000-C000-000000000046}\InprocServer32 = ole32.dll
+HKEY_CLASSES_ROOT\CLSID\{0000030A-0000-0000-C000-000000000046} = DdeCompositeMoniker
+HKEY_CLASSES_ROOT\CLSID\{0000030A-0000-0000-C000-000000000046}\InprocServer32 = ole32.dll
+HKEY_CLASSES_ROOT\CLSID\{0000030B-0000-0000-C000-000000000046} = DfMarshal
+HKEY_CLASSES_ROOT\CLSID\{0000030B-0000-0000-C000-000000000046}\InprocServer32 = ole32.dll
+HKEY_CLASSES_ROOT\CLSID\{00000315-0000-0000-C000-000000000046} = Metafile
+HKEY_CLASSES_ROOT\CLSID\{00000315-0000-0000-C000-000000000046}\InprocServer32 = ole32.dll
+HKEY_CLASSES_ROOT\CLSID\{00000316-0000-0000-C000-000000000046} = Device Independent Bitmap
+HKEY_CLASSES_ROOT\CLSID\{00000316-0000-0000-C000-000000000046}\InprocServer32 = ole32.dll
+
+
+//
+//StaticMetafile
+//
+;Root level key
+HKEY_CLASSES_ROOT\StaticMetafile\CLSID = {00000315-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\CLSID\{00000315-0000-0000-C000-000000000046}\ProgID = StaticMetafile
+HKEY_CLASSES_ROOT\CLSID\{00000315-0000-0000-C000-000000000046}\InprocServer = ole32.dll
+
+; Default File Format = CF_METAFILEPICT
+HKEY_CLASSES_ROOT\CLSID\{00000315-0000-0000-C000-000000000046}\DataFormats\DefaultFile = 3
+; Format 0 = CF_METAFILEPICT, DVASPECT_CONTENT, TYMED_MFPICT, DATADIR_BOTH
+HKEY_CLASSES_ROOT\CLSID\{00000315-0000-0000-C000-000000000046}\DataFormats\GetSet\0 = 3,1,32,3
+; MiscStatus = OLEMISC_STATIC | OLEMISC_CANTLINKINSIDE | OLEMISC_RENDERINGISDEVICEINDEPENDENT = 8 + 16 + 512
+HKEY_CLASSES_ROOT\CLSID\{00000315-0000-0000-C000-000000000046}\MiscStatus = 536
+; Readable format = CF_METAFILEPICT
+HKEY_CLASSES_ROOT\CLSID\{00000315-0000-0000-C000-000000000046}\Conversion\Readable\Main = 3,MSDraw
+
+
+//
+//StaticDib
+//
+
+; Root level keys
+HKEY_CLASSES_ROOT\StaticDib\CLSID = {00000316-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\CLSID\{00000316-0000-0000-C000-000000000046}\ProgID = StaticDib
+HKEY_CLASSES_ROOT\CLSID\{00000316-0000-0000-C000-000000000046}\InprocServer = ole2.dll
+
+; Default File Format = CF_DIB
+HKEY_CLASSES_ROOT\CLSID\{00000316-0000-0000-C000-000000000046}\DataFormats\DefaultFile = 8
+; Format 0 = CF_DIB, DVASPECT_CONTENT, TYMED_HGLOBAL, DATADIR_BOTH
+HKEY_CLASSES_ROOT\CLSID\{00000316-0000-0000-C000-000000000046}\DataFormats\GetSet\0 = 8,1,1,3
+; MiscStatus = OLEMISC_STATIC | OLEMISC_CANTLINKINSIDE | OLEMISC_RENDERINGISDEVICEINDEPENDENT = 8 + 16 + 512
+HKEY_CLASSES_ROOT\CLSID\{00000316-0000-0000-C000-000000000046}\MiscStatus = 536
+; Readable format = CF_DIB
+HKEY_CLASSES_ROOT\CLSID\{00000316-0000-0000-C000-000000000046}\Conversion\Readable\Main = 8,PBrush
+
+
+//
+//PBrush
+//
+
+; ProgID
+HKEY_CLASSES_ROOT\PBrush\CLSID = {0003000a-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\CLSID\{0003000a-0000-0000-C000-000000000046}\ProgID = PBrush
+; Ole1Class
+HKEY_CLASSES_ROOT\CLSID\{0003000a-0000-0000-C000-000000000046}\Ole1Class = PBrush
+; MiscStatus = OLEMISC_RENDERINGISDEVICEINDEPENDENT = 512
+HKEY_CLASSES_ROOT\CLSID\{0003000a-0000-0000-C000-000000000046}\MiscStatus = 512
+; Readwritable format = CF_DIB
+HKEY_CLASSES_ROOT\CLSID\{0003000a-0000-0000-C000-000000000046}\Conversion\Readable\Main = 8
+
+//
+// MSDraw
+//
+
+; ProgID
+HKEY_CLASSES_ROOT\CLSID\{00030007-0000-0000-C000-000000000046}\ProgID = MSDraw
+; Ole1Class
+HKEY_CLASSES_ROOT\CLSID\{00030007-0000-0000-C000-000000000046}\Ole1Class = MSDraw
+; MiscStatus = OLEMISC_RENDERINGISDEVICEINDEPENDENT = 512
+HKEY_CLASSES_ROOT\CLSID\{00030007-0000-0000-C000-000000000046}\MiscStatus = 512
+
+HKEY_CLASSES_ROOT\CLSID\{6f11fe5c-2fc5-101b-9e45-00000b65c7ef} = oleprx32_PSFactory
+HKEY_CLASSES_ROOT\CLSID\{6f11fe5c-2fc5-101b-9e45-00000b65c7ef}\InprocServer32 = oleprx32.dll
+
+
+HKEY_CLASSES_ROOT\Interface
+
+HKEY_CLASSES_ROOT\Interface\{00000000-0000-0000-C000-000000000046} = IUnknown
+HKEY_CLASSES_ROOT\Interface\{00000000-0000-0000-C000-000000000046}\BaseInterface =
+HKEY_CLASSES_ROOT\Interface\{00000000-0000-0000-C000-000000000046}\NumMethods = 3
+
+HKEY_CLASSES_ROOT\Interface\{00000001-0000-0000-C000-000000000046} = IClassFactory
+HKEY_CLASSES_ROOT\Interface\{00000001-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000001-0000-0000-C000-000000000046}\NumMethods = 5
+
+HKEY_CLASSES_ROOT\Interface\{00000002-0000-0000-C000-000000000046} = IMalloc
+HKEY_CLASSES_ROOT\Interface\{00000002-0000-0000-C000-000000000046}\NumMethods = 9
+
+HKEY_CLASSES_ROOT\Interface\{00000003-0000-0000-C000-000000000046} = IMarshal
+HKEY_CLASSES_ROOT\Interface\{00000003-0000-0000-C000-000000000046}\NumMethods = 9
+
+HKEY_CLASSES_ROOT\Interface\{00000004-0000-0000-C000-000000000046} = IRpcChannel
+HKEY_CLASSES_ROOT\Interface\{00000004-0000-0000-C000-000000000046}\NumMethods = 7
+
+HKEY_CLASSES_ROOT\Interface\{00000005-0000-0000-C000-000000000046} = IRpcStub
+HKEY_CLASSES_ROOT\Interface\{00000005-0000-0000-C000-000000000046}\NumMethods = 8
+
+HKEY_CLASSES_ROOT\Interface\{00000007-0000-0000-C000-000000000046} = IRpcProxy
+HKEY_CLASSES_ROOT\Interface\{00000007-0000-0000-C000-000000000046}\NumMethods = 5
+
+HKEY_CLASSES_ROOT\Interface\{00000009-0000-0000-C000-000000000046} = IPSFactory
+HKEY_CLASSES_ROOT\Interface\{00000009-0000-0000-C000-000000000046}\NumMethods = 5
+
+HKEY_CLASSES_ROOT\Interface\{0000000a-0000-0000-C000-000000000046} = ILockBytes
+HKEY_CLASSES_ROOT\Interface\{0000000a-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{0000000A-0000-0000-C000-000000000046}\NumMethods = 10
+
+HKEY_CLASSES_ROOT\Interface\{0000000b-0000-0000-C000-000000000046} = IStorage
+HKEY_CLASSES_ROOT\Interface\{0000000b-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{0000000B-0000-0000-C000-000000000046}\NumMethods = 18
+
+HKEY_CLASSES_ROOT\Interface\{0000000c-0000-0000-C000-000000000046} = IStream
+HKEY_CLASSES_ROOT\Interface\{0000000c-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{0000000C-0000-0000-C000-000000000046}\NumMethods = 14
+
+HKEY_CLASSES_ROOT\Interface\{0000000d-0000-0000-C000-000000000046} = IEnumSTATSTG
+HKEY_CLASSES_ROOT\Interface\{0000000d-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{0000000D-0000-0000-C000-000000000046}\NumMethods = 7
+
+HKEY_CLASSES_ROOT\Interface\{0000000e-0000-0000-C000-000000000046} = IBindCtx
+HKEY_CLASSES_ROOT\Interface\{0000000e-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{0000000E-0000-0000-C000-000000000046}\NumMethods = 13
+
+HKEY_CLASSES_ROOT\Interface\{0000000f-0000-0000-C000-000000000046} = IMoniker
+HKEY_CLASSES_ROOT\Interface\{0000000f-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{0000000F-0000-0000-C000-000000000046}\BaseInterface = {00000109-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000000F-0000-0000-C000-000000000046}\NumMethods = 23
+
+HKEY_CLASSES_ROOT\Interface\{00000010-0000-0000-C000-000000000046} = IRunningObjectTable
+HKEY_CLASSES_ROOT\Interface\{00000010-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000010-0000-0000-C000-000000000046}\NumMethods = 10
+
+HKEY_CLASSES_ROOT\Interface\{00000012-0000-0000-C000-000000000046} = IRootStorage
+HKEY_CLASSES_ROOT\Interface\{00000012-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000012-0000-0000-C000-000000000046}\NumMethods = 4
+
+HKEY_CLASSES_ROOT\Interface\{00000016-0000-0000-C000-000000000046} = IMessageFilter
+HKEY_CLASSES_ROOT\Interface\{00000016-0000-0000-C000-000000000046}\NumMethods = 6
+
+HKEY_CLASSES_ROOT\Interface\{00000018-0000-0000-C000-000000000046} = IStdMarshalInfo
+HKEY_CLASSES_ROOT\Interface\{00000018-0000-0000-C000-000000000046}\NumMethods = 4
+
+HKEY_CLASSES_ROOT\Interface\{00000019-0000-0000-C000-000000000046} = IExternalConnection
+HKEY_CLASSES_ROOT\Interface\{00000019-0000-0000-C000-000000000046}\NumMethods = 5
+
+HKEY_CLASSES_ROOT\Interface\{00000100-0000-0000-C000-000000000046} = IEnumUnknown
+HKEY_CLASSES_ROOT\Interface\{00000100-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000100-0000-0000-C000-000000000046}\NumMethods = 7
+
+HKEY_CLASSES_ROOT\Interface\{00000101-0000-0000-C000-000000000046} = IEnumString
+HKEY_CLASSES_ROOT\Interface\{00000101-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000101-0000-0000-C000-000000000046}\NumMethods = 7
+
+HKEY_CLASSES_ROOT\Interface\{00000102-0000-0000-C000-000000000046} = IEnumMoniker
+HKEY_CLASSES_ROOT\Interface\{00000102-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000102-0000-0000-C000-000000000046}\NumMethods = 7
+
+HKEY_CLASSES_ROOT\Interface\{00000103-0000-0000-C000-000000000046} = IEnumFORMATETC
+HKEY_CLASSES_ROOT\Interface\{00000103-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000103-0000-0000-C000-000000000046}\NumMethods = 7
+
+HKEY_CLASSES_ROOT\Interface\{00000104-0000-0000-C000-000000000046} = IEnumOLEVERB
+HKEY_CLASSES_ROOT\Interface\{00000104-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000104-0000-0000-C000-000000000046}\NumMethods = 7
+
+HKEY_CLASSES_ROOT\Interface\{00000105-0000-0000-C000-000000000046} = IEnumSTATDATA
+HKEY_CLASSES_ROOT\Interface\{00000105-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000105-0000-0000-C000-000000000046}\NumMethods = 7
+
+HKEY_CLASSES_ROOT\Interface\{00000109-0000-0000-C000-000000000046} = IPersistStream
+HKEY_CLASSES_ROOT\Interface\{00000109-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000109-0000-0000-C000-000000000046}\BaseInterface = {0000010C-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000109-0000-0000-C000-000000000046}\NumMethods = 8
+
+HKEY_CLASSES_ROOT\Interface\{0000010a-0000-0000-C000-000000000046} = IPersistStorage
+HKEY_CLASSES_ROOT\Interface\{0000010a-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{0000010A-0000-0000-C000-000000000046}\BaseInterface = {0000010C-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000010A-0000-0000-C000-000000000046}\NumMethods = 10
+
+HKEY_CLASSES_ROOT\Interface\{0000010b-0000-0000-C000-000000000046} = IPersistFile
+HKEY_CLASSES_ROOT\Interface\{0000010b-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{0000010B-0000-0000-C000-000000000046}\BaseInterface = {0000010C-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000010B-0000-0000-C000-000000000046}\NumMethods = 9
+
+HKEY_CLASSES_ROOT\Interface\{0000010c-0000-0000-C000-000000000046} = IPersist
+HKEY_CLASSES_ROOT\Interface\{0000010c-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{0000010C-0000-0000-C000-000000000046}\NumMethods = 4
+
+HKEY_CLASSES_ROOT\Interface\{0000010D-0000-0000-C000-000000000046} = IViewObject
+HKEY_CLASSES_ROOT\Interface\{0000010D-0000-0000-C000-000000000046}\NumMethods = 9
+
+HKEY_CLASSES_ROOT\Interface\{0000010e-0000-0000-C000-000000000046} = IDataObject
+HKEY_CLASSES_ROOT\Interface\{0000010e-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{0000010E-0000-0000-C000-000000000046}\NumMethods = 12
+
+HKEY_CLASSES_ROOT\Interface\{0000010f-0000-0000-C000-000000000046} = IAdviseSink
+HKEY_CLASSES_ROOT\Interface\{0000010f-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{0000010F-0000-0000-C000-000000000046}\NumMethods = 8
+
+HKEY_CLASSES_ROOT\Interface\{00000110-0000-0000-C000-000000000046} = IDataAdviseHolder
+HKEY_CLASSES_ROOT\Interface\{00000110-0000-0000-C000-000000000046}\NumMethods = 7
+
+HKEY_CLASSES_ROOT\Interface\{00000111-0000-0000-C000-000000000046} = IOleAdviseHolder
+HKEY_CLASSES_ROOT\Interface\{00000111-0000-0000-C000-000000000046}\NumMethods = 9
+
+HKEY_CLASSES_ROOT\Interface\{00000112-0000-0000-C000-000000000046} = IOleObject
+HKEY_CLASSES_ROOT\Interface\{00000112-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000112-0000-0000-C000-000000000046}\NumMethods = 24
+
+HKEY_CLASSES_ROOT\Interface\{00000113-0000-0000-C000-000000000046} = IOleInPlaceObject
+HKEY_CLASSES_ROOT\Interface\{00000113-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000113-0000-0000-C000-000000000046}\BaseInterface = {00000114-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000113-0000-0000-C000-000000000046}\NumMethods = 9
+
+HKEY_CLASSES_ROOT\Interface\{00000114-0000-0000-C000-000000000046} = IOleWindow
+HKEY_CLASSES_ROOT\Interface\{00000114-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000114-0000-0000-C000-000000000046}\NumMethods = 5
+
+HKEY_CLASSES_ROOT\Interface\{00000115-0000-0000-C000-000000000046} = IOleInPlaceUIWindow
+HKEY_CLASSES_ROOT\Interface\{00000115-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000115-0000-0000-C000-000000000046}\BaseInterface = {00000114-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000115-0000-0000-C000-000000000046}\NumMethods = 9
+
+HKEY_CLASSES_ROOT\Interface\{00000116-0000-0000-C000-000000000046} = IOleInPlaceFrame
+HKEY_CLASSES_ROOT\Interface\{00000116-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000116-0000-0000-C000-000000000046}\NumMethods = 15
+
+HKEY_CLASSES_ROOT\Interface\{00000117-0000-0000-C000-000000000046} = IOleInPlaceActiveObject
+HKEY_CLASSES_ROOT\Interface\{00000117-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000117-0000-0000-C000-000000000046}\BaseInterface = {00000114-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000117-0000-0000-C000-000000000046}\NumMethods = 10
+
+HKEY_CLASSES_ROOT\Interface\{00000118-0000-0000-C000-000000000046} = IOleClientSite
+HKEY_CLASSES_ROOT\Interface\{00000118-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000118-0000-0000-C000-000000000046}\NumMethods = 9
+
+HKEY_CLASSES_ROOT\Interface\{00000119-0000-0000-C000-000000000046} = IOleInPlaceSite
+HKEY_CLASSES_ROOT\Interface\{00000119-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000119-0000-0000-C000-000000000046}\BaseInterface = {00000114-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000119-0000-0000-C000-000000000046}\NumMethods = 15
+
+HKEY_CLASSES_ROOT\Interface\{0000011a-0000-0000-C000-000000000046} = IParseDisplayName
+HKEY_CLASSES_ROOT\Interface\{0000011a-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{0000011a-0000-0000-C000-000000000046}\NumMethods = 4
+
+HKEY_CLASSES_ROOT\Interface\{0000011b-0000-0000-C000-000000000046} = IOleContainer
+HKEY_CLASSES_ROOT\Interface\{0000011b-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{0000011b-0000-0000-C000-000000000046}\BaseInterface = {0000011A-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000011b-0000-0000-C000-000000000046}\NumMethods = 6
+
+HKEY_CLASSES_ROOT\Interface\{0000011c-0000-0000-C000-000000000046} = IOleItemContainer
+HKEY_CLASSES_ROOT\Interface\{0000011c-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{0000011c-0000-0000-C000-000000000046}\BaseInterface = {0000011B-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000011c-0000-0000-C000-000000000046}\NumMethods = 9
+
+HKEY_CLASSES_ROOT\Interface\{0000011D-0000-0000-C000-000000000046} = IOleLink
+HKEY_CLASSES_ROOT\Interface\{0000011D-0000-0000-C000-000000000046}\NumMethods = 14
+
+HKEY_CLASSES_ROOT\Interface\{0000011E-0000-0000-C000-000000000046} = IOleCache
+HKEY_CLASSES_ROOT\Interface\{0000011E-0000-0000-C000-000000000046}\NumMethods = 8
+
+HKEY_CLASSES_ROOT\Interface\{00000121-0000-0000-C000-000000000046} = IDropSource
+HKEY_CLASSES_ROOT\Interface\{00000121-0000-0000-C000-000000000046}\NumMethods = 5
+
+HKEY_CLASSES_ROOT\Interface\{00000122-0000-0000-C000-000000000046} = IDropTarget
+HKEY_CLASSES_ROOT\Interface\{00000122-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000122-0000-0000-C000-000000000046}\NumMethods = 7
+
+HKEY_CLASSES_ROOT\Interface\{00000124-0000-0000-C000-000000000046} = IDebugStream
+HKEY_CLASSES_ROOT\Interface\{00000124-0000-0000-C000-000000000046}\NumMethods = 19
+
+HKEY_CLASSES_ROOT\Interface\{00000125-0000-0000-C000-000000000046} = IAdviseSink2
+HKEY_CLASSES_ROOT\Interface\{00000125-0000-0000-C000-000000000046}\ProxyStubClsid32 = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+HKEY_CLASSES_ROOT\Interface\{00000125-0000-0000-C000-000000000046}\BaseInterface = {0000010F-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000125-0000-0000-C000-000000000046}\NumMethods = 9
+
+HKEY_CLASSES_ROOT\Interface\{00000126-0000-0000-C000-000000000046} = IRunnableObject
+HKEY_CLASSES_ROOT\Interface\{00000126-0000-0000-C000-000000000046}\NumMethods = 8
+
+HKEY_CLASSES_ROOT\Interface\{00000127-0000-0000-C000-000000000046} = IViewObject2
+HKEY_CLASSES_ROOT\Interface\{00000127-0000-0000-C000-000000000046}\BaseInterface = {0000010D-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000127-0000-0000-C000-000000000046}\NumMethods = 10
+
+HKEY_CLASSES_ROOT\Interface\{00000128-0000-0000-C000-000000000046} = IOleCache2
+HKEY_CLASSES_ROOT\Interface\{00000128-0000-0000-C000-000000000046}\BaseInterface = {0000011E-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000128-0000-0000-C000-000000000046}\NumMethods = 10
+
+HKEY_CLASSES_ROOT\Interface\{00000129-0000-0000-C000-000000000046} = IOleCacheControl
+HKEY_CLASSES_ROOT\Interface\{00000129-0000-0000-C000-000000000046}\NumMethods = 5
+
+HKEY_CLASSES_ROOT\Interface\{00020400-0000-0000-C000-000000000046} = IDispatch
+HKEY_CLASSES_ROOT\Interface\{00020400-0000-0000-C000-000000000046}\NumMethods = 7
+HKEY_CLASSES_ROOT\Interface\{00020400-0000-0000-C000-000000000046}\ProxyStubClsid32 = {00020420-0000-0000-C000-000000000046}
+
+HKEY_CLASSES_ROOT\Interface\{00020404-0000-0000-C000-000000000046} = IEnumVARIANT
+HKEY_CLASSES_ROOT\Interface\{00020404-0000-0000-C000-000000000046}\NumMethods = 7
+HKEY_CLASSES_ROOT\Interface\{00020404-0000-0000-C000-000000000046}\ProxyStubClsid32 = {00020421-0000-0000-C000-000000000046}
+
+HKEY_CLASSES_ROOT\Interface\{00020401-0000-0000-C000-000000000046} = ITypeInfo
+HKEY_CLASSES_ROOT\Interface\{00020401-0000-0000-C000-000000000046}\NumMethods = 22
+HKEY_CLASSES_ROOT\Interface\{00020401-0000-0000-C000-000000000046}\ProxyStubClsid32 = {00020422-0000-0000-C000-000000000046}
+
+HKEY_CLASSES_ROOT\Interface\{00020402-0000-0000-C000-000000000046} = ITypeLib
+HKEY_CLASSES_ROOT\Interface\{00020402-0000-0000-C000-000000000046}\NumMethods = 13
+
+HKEY_CLASSES_ROOT\Interface\{00020403-0000-0000-C000-000000000046} = ITypeComp
+HKEY_CLASSES_ROOT\Interface\{00020403-0000-0000-C000-000000000046}\NumMethods = 5
+
+HKEY_CLASSES_ROOT\Interface\{00020405-0000-0000-C000-000000000046} = ICreateTypeInfo
+HKEY_CLASSES_ROOT\Interface\{00020405-0000-0000-C000-000000000046}\NumMethods = 26
+
+HKEY_CLASSES_ROOT\Interface\{00020406-0000-0000-C000-000000000046} = ICreateTypeLib
+HKEY_CLASSES_ROOT\Interface\{00020406-0000-0000-C000-000000000046}\NumMethods = 13
+
+HKEY_CLASSES_ROOT\Interface\{D5F56A34-593B-101A-B569-08002B2DBF7A} = IRpcProxyBuffer
+HKEY_CLASSES_ROOT\Interface\{D5F56A34-593B-101A-B569-08002B2DBF7A}\NumMethods = 5
+
+HKEY_CLASSES_ROOT\Interface\{D5F569D0-593B-101A-B569-08002B2DBF7A} = IPSFactoryBuffer
+HKEY_CLASSES_ROOT\Interface\{D5F569D0-593B-101A-B569-08002B2DBF7A}\NumMethods = 5
+
+HKEY_CLASSES_ROOT\Interface\{D5F56B60-593B-101A-B569-08002B2DBF7A} = IRpcChannelBuffer
+HKEY_CLASSES_ROOT\Interface\{D5F56B60-593B-101A-B569-08002B2DBF7A}\NumMethods = 8
+
+HKEY_CLASSES_ROOT\Interface\{D5F56AFC-593B-101A-B569-08002B2DBF7A} = IRpcStubBuffer
+HKEY_CLASSES_ROOT\Interface\{D5F56AFC-593B-101A-B569-08002B2DBF7A}\NumMethods = 10
diff --git a/private/ole32/ih/clsctx.hxx b/private/ole32/ih/clsctx.hxx
new file mode 100644
index 000000000..ff5a8f06a
--- /dev/null
+++ b/private/ole32/ih/clsctx.hxx
@@ -0,0 +1,31 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: clsctx.hxx
+//
+// Contents: Defines special CLSCTX to for 16 bit processes
+//
+// History: 6-16-95 ricksa Created
+//
+// BUGBUG: Post Win95 RTM, this should be merged into the public headers.
+// Actually, the best approach would be to look at the two
+// CLSCTX that have to do with 16 bit and merge them into one.
+//
+//----------------------------------------------------------------------------
+#ifndef __clcstx_hxx__
+#define __clsctx_hxx__
+
+// this is chicago only
+#define CLSCTX_16BIT 0x40
+
+// note that there are two more high-order bits defined in ole2com.h
+// for PS_DLL and NO_REMAP for internal use only
+#ifdef WX86OLE
+#define CLSCTX_VALID_MASK 0x000000df
+#else
+#define CLSCTX_VALID_MASK 0x0000001f
+#endif
+
+#endif // __clsctx_hxx__
diff --git a/private/ole32/ih/ddesrvr.h b/private/ole32/ih/ddesrvr.h
new file mode 100644
index 000000000..0c2da8eaf
--- /dev/null
+++ b/private/ole32/ih/ddesrvr.h
@@ -0,0 +1,24 @@
+/*
+ ddesrvr.h
+ Header file for ddesrvr.cpp
+
+ Author:
+ Jason Fuller jasonful 8-11-92
+*/
+
+#ifndef fDdesrvr_h
+#define fDdesrvr_h
+
+INTERNAL CreateDdeSrvrWindow (REFCLSID rclsid, HWND * phwnd = NULL);
+INTERNAL DestroyDdeSrvrWindow (HWND hwnd, ATOM aClass);
+
+INTERNAL CreateCommonDdeWindow (void);
+INTERNAL DestroyCommonDdeWindow (void);
+
+INTERNAL IsRunningInThisTask (LPOLESTR szFile, BOOL * pf);
+
+// Defined in cftable.cpp
+STDAPI RemGetInfoForCid(REFCLSID clsid, LPDWORD pgrf, LPCLASSFACTORY * ppCF,
+ HWND ** pphwndDde, BOOL ** ppfAvail);
+
+#endif
diff --git a/private/ole32/ih/debug.h b/private/ole32/ih/debug.h
new file mode 100644
index 000000000..5b8c75820
--- /dev/null
+++ b/private/ole32/ih/debug.h
@@ -0,0 +1,316 @@
+//+----------------------------------------------------------------------------
+//
+// File:
+// debug.h
+//
+// Contents:
+// macros and declarations for debug support--all are appropriately
+// defined to nothing when not doing debug build
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 12/30/93 - ChrisWe - added file prologue; defined _DEBUG when
+// DBG==1; added "const" to ASSERTDATA macro
+//
+//-----------------------------------------------------------------------------
+
+
+#ifndef _DEBUG_H_
+#define _DEBUG_H_
+
+#include <debnot.h>
+
+#ifndef RC_INVOKED
+#ifdef _DEBUG
+#define DBGSTATE " Debug is on"
+#else
+#define DBGSTATE " Debug is off"
+#endif
+#endif /* RC_INVOKED */
+
+#ifndef _CAIRO_
+#include <ole2dbg.h>
+#endif
+
+//these are bogus APIs (they do nothing)
+STDAPI_(BOOL) ValidateAllObjects( BOOL fSuspicious );
+STDAPI_(void) DumpAllObjects( void );
+
+#ifdef _DEBUG
+BOOL InstallHooks(void);
+BOOL UnInstallHooks(void);
+
+#undef ASSERTDATA
+#define ASSERTDATA
+
+#undef AssertSz
+#define AssertSz(a,b) ((a) ? NOERROR : FnAssert(#a, b, __FILE__, __LINE__))
+#undef Puts
+#define Puts(s) OutputDebugString(TEXT(s))
+
+#else // !_DEBUG
+
+#define ASSERTDATA
+#define AssertSz(a, b) ((void)0)
+#define Puts(s) ((void)0)
+
+#endif // _DEBUG
+
+
+// special Assert for asserts below (since the expression is so large)
+// REVIEW, shouldn't these be in the debug.h file?
+#ifdef _DEBUG
+#define AssertOut(a, b) { if (!(a)) FnAssert(szCheckOutParam, b, __FILE__, __LINE__); }
+#else
+#define AssertOut(a, b) ((void)0)
+#endif
+
+#define AssertOutPtrParam(hr, p) \
+ AssertOut(SUCCEEDED(hr) && IsValidPtrIn(p, sizeof(OLECHAR)) || \
+ FAILED(hr) && (p) == NULL, \
+ szBadOutParam)
+
+#define AssertOutPtrIface(hr, p) \
+ AssertOut(SUCCEEDED(hr) && IsValidInterface(p) || \
+ FAILED(hr) && (p) == NULL, \
+ szBadOutIface)
+
+#define AssertOutPtrFailed(p) \
+ AssertOut((p) == NULL, \
+ szNonNULLOutPtr)
+
+#define AssertOutStgmedium(hr, pstgm) \
+ AssertOut(SUCCEEDED(hr) && (pstgm)->tymed != TYMED_NULL || \
+ FAILED(hr) && (pstgm)->tymed == TYMED_NULL, \
+ szBadOutStgm)
+
+
+// assert data for above assert out macros; once per dll
+// Note that since these are only used in asserts, we leave them as ANSI
+#define ASSERTOUTDATA \
+ char szCheckOutParam[] = "check out param"; \
+ char szBadOutParam[] = "Out pointer param conventions not followed"; \
+ char szBadOutIface[] = "Out pointer interface conventions not followed"; \
+ char szNonNULLOutPtr[] = "Out pointer not NULL on error"; \
+ char szBadOutStgm[] = "Out stgmed param conventions not followed";
+
+extern char szCheckOutParam[];
+extern char szBadOutParam[];
+extern char szBadOutIface[];
+extern char szNonNULLOutPtr[];
+extern char szBadOutStgm[];
+
+
+#ifdef __cplusplus
+
+interface IDebugStream;
+
+/*
+ * Class CBool wraps boolean values in such a way that they are
+ * readily distinguishable fron integers by the compiler so we can
+ * overload the stream << operator.
+ */
+
+class FAR CBool
+{
+ BOOL value;
+public:
+ CBool (BOOL& b) {value = b;}
+ operator BOOL( void ) { return value; }
+};
+
+
+/*
+ * Class CHwnd wraps HWND values in such a way that they are
+ * readily distinguishable from UINTS by the compiler so we can
+ * overload the stream << operator
+ */
+
+class FAR CHwnd
+{
+ HWND m_hwnd;
+ public:
+ CHwnd (HWND hwnd) {m_hwnd = hwnd; }
+ operator HWND( void ) {return m_hwnd;}
+};
+
+/*
+ * Class CAtom wraps ATOM values in such a way that they are
+ * readily distinguishable from UINTS by the compiler so we can
+ * overload the stream << operator
+ */
+
+class FAR CAtom
+{
+ ATOM m_atom;
+ public:
+ CAtom (ATOM atom) {m_atom = atom; }
+ operator ATOM( void ) {return m_atom; }
+};
+
+/*
+ * IDebugStream is a stream to be used for debug output. One
+ * implementation uses the OutputDebugString function of Windows.
+ *
+ * The style is modeled on that of AT&T streams, and so uses
+ * overloaded operators. You can write to a stream in the
+ * following ways:
+ *
+ * *pdbstm << pUnk; // calls the IDebug::Dump function to
+ * display the object, if IDebug is supported.
+ * int n;
+ * *pdbstm << n; // writes n in decimal
+ *
+-
+ * *pdbstm << sz; // writes a string
+ *
+ * CBool b(TRUE);
+ * *pdbstm << b; // writes True or False
+ *
+ * void FAR * pv;
+ * *pdbstm << pv; // writes the address pv in hex
+ *
+ * TCHAR ch;
+ * *pdbstm << ch; // writes the character
+ *
+ * ATOM atom;
+ * *pdbstm << CAtom(atom); // writes the string extracted from the atom
+ *
+ * HWND hwnd;
+ * *pdbstm << CHwnd(hwnd); // writes the info about a window handle
+ *
+ * These can be chained together, as such (somewhat artificial
+ * example):
+ *
+ * REFCLSID rclsid;
+ * pUnk->GetClass(&rclsid);
+ * *pdbstm << rclsid << " at " << (void FAR *)pUnk <<':' << pUnk;
+ *
+ * This produces something like:
+ *
+ * CFoo at A7360008: <description of object>
+ *
+ * The other useful feature is the Indent and UnIndent functions
+ * which allow an object to print some information, indent, print
+ * the info on its member objects, and unindent. This gives
+ * nicely formatted output.
+ *
+ * WARNING: do not (while implementing Dump) write
+ *
+ * *pdbstm << pUnkOuter
+ *
+ * since this will do a QueryInterface for IDebug, and start
+ * recursing! It is acceptable to write
+ *
+ * *pdbstm << (VOID FAR *)pUnkOuter
+ *
+ * as this will simply write the address of pUnkOuter.
+ *
+ */
+
+
+interface IDebugStream : public IUnknown
+{
+ STDMETHOD_(IDebugStream&, operator << ) ( IUnknown FAR * pDebug ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( REFCLSID rclsid ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( int n ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( long l ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( ULONG l ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( LPCTSTR sz ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( TCHAR ch ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( void FAR * pv ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( CBool b ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( CHwnd hwnd ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( CAtom atom ) = 0;
+ STDMETHOD_(IDebugStream&, Tab )( void ) = 0;
+ STDMETHOD_(IDebugStream&, Indent )( void ) = 0;
+ STDMETHOD_(IDebugStream&, UnIndent )( void ) = 0;
+ STDMETHOD_(IDebugStream&, Return )( void ) = 0;
+ STDMETHOD_(IDebugStream&, LF )( void ) = 0;
+};
+
+STDAPI_(IDebugStream FAR*) MakeDebugStream( short margin=70, short tabsize=4, BOOL fHeader=1);
+
+
+interface IDebug
+{
+ STDMETHOD_(void, Dump )( IDebugStream FAR * pdbstm ) = 0;
+ STDMETHOD_(BOOL, IsValid )( BOOL fSuspicious = FALSE ) = 0;
+
+#ifdef NEVER
+ __export IDebug(void);
+ __export ~IDebug(void);
+private:
+
+#ifdef _DEBUG
+ IDebug FAR * pIDPrev;
+ IDebug FAR * pIDNext;
+
+ friend void STDAPICALLTYPE DumpAllObjects( void );
+ friend BOOL STDAPICALLTYPE ValidateAllObjects( BOOL fSuspicious );
+#endif // _DEBUG
+#endif // NEVER
+};
+
+/*************************************************************************
+** The following functions can be used to log debug messages to a file
+** and simutaneously write them to the dbwin debug window.
+** The CDebugStream implementation automatically writes to a debug
+** log file called "debug.log" in the current working directory.
+** NOTE: The functions are only intended for C programmers. C++
+** programmers should use the "MakeDebugStream" instead.
+*************************************************************************/
+
+// Open a log file.
+STDAPI_(HFILE) DbgLogOpen(LPCTSTR lpszFile, LPCTSTR lpszMode);
+
+// Close the log file.
+STDAPI_(void) DbgLogClose(HFILE fh);
+
+// Write to debug log and debug window (used with cvw.exe or dbwin.exe).
+STDAPI_(void) DbgLogOutputDebugString(HFILE fh, LPCTSTR lpsz);
+
+// Write to debug log only.
+STDAPI_(void) DbgLogWrite(HFILE fh, LPCTSTR lpsz);
+
+// Write the current Date and Time to the log file.
+STDAPI_(void) DbgLogTimeStamp(HFILE fh, LPCTSTR lpsz);
+
+// Write a banner separater to the log to separate sections.
+STDAPI_(void) DbgLogWriteBanner(HFILE fh, LPCTSTR lpsz);
+
+
+
+
+/*
+ * STDDEBDECL macro - helper for debug declaration
+ *
+ */
+
+#ifdef _DEBUG
+
+ #define STDDEBDECL(ignore, classname ) implement CDebug:public IDebug { public: \
+ CDebug( C##classname FAR * p##classname ) { m_p##classname = p##classname;} \
+ ~CDebug(void) {} \
+ STDMETHOD_(void, Dump)(IDebugStream FAR * pdbstm ); \
+ STDMETHOD_(BOOL, IsValid)(BOOL fSuspicious ); \
+ private: C##classname FAR* m_p##classname; }; \
+ DECLARE_NC(C##classname, CDebug) \
+ CDebug m_Debug;
+
+ #define CONSTRUCT_DEBUG m_Debug(this),
+
+#else // _DEBUG
+
+// no debugging
+#define STDDEBDECL(cclassname,classname)
+#define CONSTRUCT_DEBUG
+
+#endif // _DEBUG
+
+#endif __cplusplus
+
+#endif // !_DEBUG_H_
diff --git a/private/ole32/ih/dragopt.h b/private/ole32/ih/dragopt.h
new file mode 100644
index 000000000..e33f33589
--- /dev/null
+++ b/private/ole32/ih/dragopt.h
@@ -0,0 +1,163 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dragopt.h
+//
+// Contents: Intercomponent definitions to support the Drag/Drop optimization
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-94 alexgo added PrivDragDrop
+// 30-Sep-94 ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifndef _DRAGOPT_H
+
+//+-------------------------------------------------------------------------
+//
+// Function: UnmarshalDragDataObject
+//
+// Synopsis: Handles unmarshaling of a marshaled data object
+//
+// Arguments: [pvMarshaledDataObject] - the marshaled buffer
+//
+// Returns: NULL - could not unmarshal
+// ~NULL - remote IDataObject
+//
+// Algorithms: see com\rot\getif.cxx
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+IDataObject *UnmarshalDragDataObject(void *pvMarshaledDataObject);
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateDragDataObject
+//
+// Synopsis: Handles unmarshaling of a marshaled data object
+//
+// Arguments: [pvMarshaledDataObject] - the marshaled buffer for data object
+// [dwSmId] - id of shared memory for formats.
+// [ppIDataObject] - where to put Drag data object
+//
+// Returns: NOERROR - created a data object
+// E_OUTOFMEMORY - could not allocate the Drag data object
+//
+// Algorithms: see ole232\drag\ido.cpp
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CreateDragDataObject(
+ void *pvMarshaledDataObject,
+ DWORD dwSmId,
+ IDataObject **ppIDataObject);
+
+typedef void * DDInfo;
+
+//+-------------------------------------------------------------------------
+//
+// Function: FreeDragDropInfo
+//
+// Synopsis: frees a DDInfo handle (aka as a SPrivDragDrop struct)
+//
+// Effects:
+//
+// Arguments: [hDDInfo] -- handle to free
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 07-Jan-95 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+void FreeDragDropInfo( DDInfo hDDInfo );
+
+
+//
+// Drag Drop interpreter op codes
+//
+
+typedef enum tagDRAGOP
+{
+ DRAGOP_ENTER = 1,
+ DRAGOP_OVER = 2,
+ DRAGOP_LEAVE = 3,
+ DRAGOP_DROP = 4
+} DRAGOP;
+
+//+-------------------------------------------------------------------------
+//
+// Function: PrivDragDrop
+//
+// Synopsis: Main entry point for the private version of the OLE
+// protocol. Instead of using IDropTarget proxy/stubs,
+// we use a private rpc and do most of the work on the
+// drop target side.
+//
+// Effects:
+//
+// Arguments: [hwnd] -- the target hwnd
+// [dop] -- the drag drop operation to perform
+// [DOBuffer] -- the data object buffer to send
+// [pIDataObject] -- the data object interface (for the
+// local case)
+// [grfKeyState] -- the keyboard state
+// [ptl] -- the mouse position
+// [pdwEffect] -- the drag drop effect
+// [hwndSource] -- the window of the drag source. Used
+// to attach input queues for 16bit targets
+// [phDDInfo] -- pointer to a DragDropInfo handle, for
+// caching rpc info about the drop target.
+// May not be NULL, but on DragEnter,
+// should be a pointer to NULL.
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: see getif.cxx
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+// 08-Nov-94 alexgo modified to use DRAGOP's
+// 08-Jan-95 alexgo added caching of RPC binding handles via
+// DDInfo handles
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+HRESULT PrivDragDrop( HWND hwnd, DRAGOP dop, IFBuffer DOBuffer, IDataObject *
+ pIDataObject, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect,
+ HWND hwndSource, DDInfo *phDDInfo);
+
+#endif // _DRAGOPT_H
diff --git a/private/ole32/ih/exports.hxx b/private/ole32/ih/exports.hxx
new file mode 100644
index 000000000..4623b5a4c
--- /dev/null
+++ b/private/ole32/ih/exports.hxx
@@ -0,0 +1,211 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: exports.hxx
+//
+// Contains: API id's for all our exported functions, used by tracing macros/functions
+// ID's are 32 bit unsigned integers, with the upper 16 bits
+// defining which Interface this function belongs to (API's have a 0 here)
+// and the lower 16 bits being the actual function identifiers.
+// This limits our tracing to only handle us to 65K methods per interface, and 65K exports,
+// but if that ever happens woe to the programmer who uses OLE
+//
+// History: 20-Jul-95 t-stevan Created...
+//
+//----------------------------------------------------------------------------
+
+#ifndef __EXPORTS_HXX__
+#define __EXPORTS_HXX__
+
+// *** Global Data ***
+// This is a table of pointers to tables of strings, each table corresponding
+// to an Interface's methods, or in the zeroth table's case, APIs and exports
+// we ifdef this out with a _TRACE
+#if DBG==1
+extern const char **g_ppNameTables[];
+extern const char *g_pscInterfaceNames[];
+#endif
+
+// *** Defines and constants ***
+// This stuff is not ifdef'd out because it doesn't hurt to have it defined
+#define API_NAMETABLE 0x00000000
+#define API_START 0
+
+// APIs and exports
+#define API_CoInitialize (API_NAMETABLE|API_START)
+#define API_CoUninitialize (API_NAMETABLE|(API_START+1))
+#define API_CoGetClassObject (API_NAMETABLE|(API_START+2))
+#define API_CoRegisterClassObject (API_NAMETABLE|(API_START+3))
+#define API_CoRevokeClassObject (API_NAMETABLE|(API_START+4))
+#define API_CoMarshalInterface (API_NAMETABLE|(API_START+5))
+#define API_CoUnmarshalInterface (API_NAMETABLE|(API_START+6))
+#define API_CoReleaseMarshalData (API_NAMETABLE|(API_START+7))
+#define API_CoDisconnectObject (API_NAMETABLE|(API_START+8))
+#define API_CoLockObjectExternal (API_NAMETABLE|(API_START+9))
+#define API_CoGetStandardMarshal (API_NAMETABLE|(API_START+10))
+#define API_CoIsHandlerConnected (API_NAMETABLE|(API_START+11))
+#define API_CoFreeAllLibraries (API_NAMETABLE|(API_START+12))
+#define API_CoFreeUnusedLibraries (API_NAMETABLE|(API_START+13))
+#define API_CoCreateInstance (API_NAMETABLE|(API_START+14))
+#define API_CLSIDFromString (API_NAMETABLE|(API_START+15))
+#define API_CoIsOle1Class (API_NAMETABLE|(API_START+16))
+#define API_ProgIDFromCLSID (API_NAMETABLE|(API_START+17))
+#define API_CLSIDFromProgID (API_NAMETABLE|(API_START+18))
+#define API_CoCreateGuid (API_NAMETABLE|(API_START+19))
+#define API_CoFileTimeToDosDateTime (API_NAMETABLE|(API_START+20))
+#define API_CoDosDateTimeToFileTime (API_NAMETABLE|(API_START+21))
+#define API_CoFileTimeNow (API_NAMETABLE|(API_START+22))
+#define API_CoRegisterMessageFilter (API_NAMETABLE|(API_START+23))
+#define API_CoGetTreatAsClass (API_NAMETABLE|(API_START+24))
+#define API_CoTreatAsClass (API_NAMETABLE|(API_START+25))
+#define API_DllGetClassObject (API_NAMETABLE|(API_START+26))
+#define API_StgCreateDocfile (API_NAMETABLE|(API_START+27))
+#define API_StgCreateDocfileOnILockBytes (API_NAMETABLE|(API_START+28))
+#define API_StgOpenStorage (API_NAMETABLE|(API_START+29))
+#define API_StgOpenStorageOnILockBytes (API_NAMETABLE|(API_START+30))
+#define API_StgIsStorageFile (API_NAMETABLE|(API_START+31))
+#define API_StgIsStorageILockBytes (API_NAMETABLE|(API_START+32))
+#define API_StgSetTimes (API_NAMETABLE|(API_START+33))
+#define API_CreateDataAdviseHolder (API_NAMETABLE|(API_START+34))
+#define API_CreateDataCache (API_NAMETABLE|(API_START+35))
+#define API_BindMoniker (API_NAMETABLE|(API_START+36))
+#define API_MkParseDisplayName (API_NAMETABLE|(API_START+37))
+#define API_MonikerRelativePathTo (API_NAMETABLE|(API_START+38))
+#define API_MonikerCommonPrefixWith (API_NAMETABLE|(API_START+39))
+#define API_CreateBindCtx (API_NAMETABLE|(API_START+40))
+#define API_CreateGenericComposite (API_NAMETABLE|(API_START+41))
+#define API_GetClassFile (API_NAMETABLE|(API_START+42))
+#define API_CreateFileMoniker (API_NAMETABLE|(API_START+43))
+#define API_CreateItemMoniker (API_NAMETABLE|(API_START+44))
+#define API_CreateAntiMoniker (API_NAMETABLE|(API_START+45))
+#define API_CreatePointerMoniker (API_NAMETABLE|(API_START+46))
+#define API_GetRunningObjectTable (API_NAMETABLE|(API_START+47))
+#define API_ReadClassStg (API_NAMETABLE|(API_START+48))
+#define API_WriteClassStg (API_NAMETABLE|(API_START+49))
+#define API_ReadClassStm (API_NAMETABLE|(API_START+50))
+#define API_WriteClassStm (API_NAMETABLE|(API_START+51))
+#define API_WriteFmtUserTypeStg (API_NAMETABLE|(API_START+52))
+#define API_ReadFmtUserTypeStg (API_NAMETABLE|(API_START+53))
+#define API_OleInitialize (API_NAMETABLE|(API_START+54))
+#define API_OleUninitialize (API_NAMETABLE|(API_START+55))
+#define API_OleQueryLinkFromData (API_NAMETABLE|(API_START+56))
+#define API_OleQueryCreateFromData (API_NAMETABLE|(API_START+57))
+#define API_OleCreate (API_NAMETABLE|(API_START+58))
+#define API_OleCreateFromData (API_NAMETABLE|(API_START+59))
+#define API_OleCreateLinkFromData (API_NAMETABLE|(API_START+60))
+#define API_OleCreateStaticFromData (API_NAMETABLE|(API_START+61))
+#define API_OleCreateLink (API_NAMETABLE|(API_START+62))
+#define API_OleCreateLinkToFile (API_NAMETABLE|(API_START+63))
+#define API_OleCreateFromFile (API_NAMETABLE|(API_START+64))
+#define API_OleLoad (API_NAMETABLE|(API_START+65))
+#define API_OleSave (API_NAMETABLE|(API_START+66))
+#define API_OleLoadFromStream (API_NAMETABLE|(API_START+67))
+#define API_OleSaveToStream (API_NAMETABLE|(API_START+68))
+#define API_OleSetContainedObject (API_NAMETABLE|(API_START+69))
+#define API_OleNoteObjectVisible (API_NAMETABLE|(API_START+70))
+#define API_RegisterDragDrop (API_NAMETABLE|(API_START+71))
+#define API_RevokeDragDrop (API_NAMETABLE|(API_START+72))
+#define API_DoDragDrop (API_NAMETABLE|(API_START+73))
+#define API_OleSetClipboard (API_NAMETABLE|(API_START+74))
+#define API_OleGetClipboard (API_NAMETABLE|(API_START+75))
+#define API_OleFlushClipboard (API_NAMETABLE|(API_START+76))
+#define API_OleIsCurrentClipboard (API_NAMETABLE|(API_START+77))
+#define API_OleCreateMenuDescriptor (API_NAMETABLE|(API_START+78))
+#define API_OleSetMenuDescriptor (API_NAMETABLE|(API_START+79))
+#define API_OleDestroyMenuDescriptor (API_NAMETABLE|(API_START+80))
+#define API_OleDraw (API_NAMETABLE|(API_START+81))
+#define API_OleRun (API_NAMETABLE|(API_START+82))
+#define API_OleIsRunning (API_NAMETABLE|(API_START+83))
+#define API_OleLockRunning (API_NAMETABLE|(API_START+84))
+#define API_CreateOleAdviseHolder (API_NAMETABLE|(API_START+85))
+#define API_OleCreateDefaultHandler (API_NAMETABLE|(API_START+86))
+#define API_OleCreateEmbeddingHelper (API_NAMETABLE|(API_START+87))
+#define API_OleRegGetUserType (API_NAMETABLE|(API_START+88))
+#define API_OleRegGetMiscStatus (API_NAMETABLE|(API_START+89))
+#define API_OleRegEnumFormatEtc (API_NAMETABLE|(API_START+90))
+#define API_OleRegEnumVerbs (API_NAMETABLE|(API_START+91))
+#define API_OleConvertIStorageToOLESTREAM (API_NAMETABLE|(API_START+92))
+#define API_OleConvertOLESTREAMToIStorage (API_NAMETABLE|(API_START+93))
+#define API_OleConvertIStorageToOLESTREAMEx (API_NAMETABLE|(API_START+94))
+#define API_OleConvertOLESTREAMToIStorageEx (API_NAMETABLE|(API_START+95))
+#define API_OleDoAutoConvert (API_NAMETABLE|(API_START+96))
+#define API_OleGetAutoConvert (API_NAMETABLE|(API_START+97))
+#define API_OleSetAutoConvert (API_NAMETABLE|(API_START+98))
+#define API_GetConvertStg (API_NAMETABLE|(API_START+99))
+#define API_SetConvertStg (API_NAMETABLE|(API_START+100))
+#define API_ReadOleStg (API_NAMETABLE|(API_START+101))
+#define API_WriteOleStg (API_NAMETABLE|(API_START+102))
+#define API_CoGetCallerTID (API_NAMETABLE|(API_START+103))
+#define API_CoGetState (API_NAMETABLE|(API_START+104))
+#define API_CoSetState (API_NAMETABLE|(API_START+105))
+#define API_CoMarshalHresult (API_NAMETABLE|(API_START+106))
+#define API_CoUnmarshalHresult (API_NAMETABLE|(API_START+107))
+#define API_CoGetCurrentLogicalThreadId (API_NAMETABLE|(API_START+108))
+#define API_CoGetPSClsid (API_NAMETABLE|(API_START+109))
+#define API_CoMarshalInterThreadInterfaceInStream (API_NAMETABLE|(API_START+110))
+#define API_IIDFromString (API_NAMETABLE|(API_START+111))
+#define API_StringFromCLSID (API_NAMETABLE|(API_START+112))
+#define API_StringFromIID (API_NAMETABLE|(API_START+113))
+#define API_StringFromGUID2 (API_NAMETABLE|(API_START+114))
+#define API_CoBuildVersion (API_NAMETABLE|(API_START+115))
+#define API_CoGetMalloc (API_NAMETABLE|(API_START+116))
+#define API_CoInitializeWOW (API_NAMETABLE|(API_START+117))
+#define API_CoUnloadingWOW (API_NAMETABLE|(API_START+118))
+#define API_CoTaskMemAlloc (API_NAMETABLE|(API_START+119))
+#define API_CoTaskMemFree (API_NAMETABLE|(API_START+120))
+#define API_CoTaskMemRealloc (API_NAMETABLE|(API_START+121))
+#define API_CoFreeLibrary (API_NAMETABLE|(API_START+122))
+#define API_CoLoadLibrary (API_NAMETABLE|(API_START+123))
+#define API_CoCreateFreeThreadedMarshaler (API_NAMETABLE|(API_START+124))
+#define API_OleInitializeWOW (API_NAMETABLE|(API_START+125))
+#define API_OleDuplicateData (API_NAMETABLE|(API_START+126))
+#define API_OleGetIconOfFile (API_NAMETABLE|(API_START+127))
+#define API_OleGetIconOfClass (API_NAMETABLE|(API_START+128))
+#define API_OleMetafilePictFromIconAndLabel (API_NAMETABLE|(API_START+129))
+#define API_OleTranslateAccelerator (API_NAMETABLE|(API_START+130))
+#define API_ReleaseStgMedium (API_NAMETABLE|(API_START+131))
+#define API_ReadStringStream (API_NAMETABLE|(API_START+132))
+#define API_WriteStringStream (API_NAMETABLE|(API_START+133))
+#define API_OpenOrCreateStream (API_NAMETABLE|(API_START+134))
+#define API_IsAccelerator (API_NAMETABLE|(API_START+135))
+#define API_CreateILockBytesOnHGlobal (API_NAMETABLE|(API_START+136))
+#define API_GetHGlobalFromILockBytes (API_NAMETABLE|(API_START+137))
+#define API_SetDocumentBitStg (API_NAMETABLE|(API_START+138))
+#define API_GetDocumentBitStg (API_NAMETABLE|(API_START+139))
+#define API_CreateStreamOnHGlobal (API_NAMETABLE|(API_START+140))
+#define API_GetHGlobalFromStream (API_NAMETABLE|(API_START+141))
+#define API_CoGetInterfaceAndReleaseStream (API_NAMETABLE|(API_START+142))
+#define API_CoGetCurrentProcess (API_NAMETABLE|(API_START+143))
+#define API_CoQueryReleaseObject (API_NAMETABLE|(API_START+144))
+#define API_CoRegisterMallocSpy (API_NAMETABLE|(API_START+145))
+#define API_CoRevokeMallocSpy (API_NAMETABLE|(API_START+146))
+#define API_CoGetMarshalSizeMax (API_NAMETABLE|(API_START+147))
+#define API_CoGetObject (API_NAMETABLE|(API_START+148))
+#define API_CreateClassMoniker (API_NAMETABLE|(API_START+149))
+#define API_OleCreateEx (API_NAMETABLE|(API_START+150))
+#define API_OleCreateFromDataEx (API_NAMETABLE|(API_START+151))
+#define API_OleCreateLinkFromDataEx (API_NAMETABLE|(API_START+152))
+#define API_OleCreateLinkEx (API_NAMETABLE|(API_START+153))
+#define API_OleCreateLinkToFileEx (API_NAMETABLE|(API_START+154))
+#define API_OleCreateFromFileEx (API_NAMETABLE|(API_START+155))
+#define API_CoRegisterSurrogate (API_NAMETABLE|(API_START+156))
+#define API_COUNT (API_CoRegisterSurrogate+1)
+
+// Interface methods
+// IUnknown
+#define IFACE_IUNKNOWN 0x00010000
+
+#define IFM_IUnknown_QueryInterface (IFACE_IUNKNOWN)
+#define IFM_IUnknown_AddRef (IFACE_IUNKNOWN|1)
+#define IFM_IUnknown_Release (IFACE_IUNKNOWN|2)
+
+// IClassFactory
+#define IFACE_ICLASSFACTORY 0x00020000
+
+#define IFM_IClassFactory_CreateInstance (IFACE_ICLASSFACTORY)
+#define IFM_IClassFactory_LockServer (IFACE_ICLASSFACTORY|1)
+
+#endif // __EXPORTS_HXX__
+
diff --git a/private/ole32/ih/getif.hxx b/private/ole32/ih/getif.hxx
new file mode 100644
index 000000000..3694ec701
--- /dev/null
+++ b/private/ole32/ih/getif.hxx
@@ -0,0 +1,32 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: getif.hxx
+//
+// Contents: Declaration APIs used to get an interface from a window
+//
+// History: 29-Dec-93 Ricksa Crated
+//
+//--------------------------------------------------------------------------
+#ifndef __GETIF_HXX__
+#define __GETIF_HXX__
+
+// Assign an endpoint property to a window so interfaces can be returned
+// from properties on the window.
+extern "C" HRESULT AssignEndpointProperty(HWND hWnd);
+
+// Remove the end point property from the window
+extern "C" HRESULT UnAssignEndpointProperty(HWND hWnd,DWORD* dwAssignAptID);
+
+#define ENDPOINT_PROP_NAME L"OleEndPointID"
+
+// Get an interface from the property listed on the window
+extern "C" GetInterfaceFromWindowProp(
+ HWND hWnd,
+ REFIID riid,
+ IUnknown **ppunk,
+ LPOLESTR pwszPropertyName);
+
+#endif // __GETIF_HXX__
diff --git a/private/ole32/ih/hkldinp.h b/private/ole32/ih/hkldinp.h
new file mode 100644
index 000000000..e2f9f7fa6
--- /dev/null
+++ b/private/ole32/ih/hkldinp.h
@@ -0,0 +1,100 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994.
+//
+// File: hkLdInP.h
+//
+// Contents: Inline function to load the DLL of an inproc server
+//
+// Functions:
+//
+// History: 01-Sep-94 Don Wright Created
+// 08-Sep-94 Garry Lenz Separate into two functions
+// 14-Nov-94 Don Wright Make LogEvent messages more complete
+//
+//--------------------------------------------------------------------------
+#ifndef _LDINPROC_H_
+#define _LDINPROC_H_
+
+#include <Windows.h>
+#include <TChar.h>
+#include "hkregkey.h"
+#include "hkLogEvt.h"
+#include "hkole32x.h"
+
+#define MAX_CLSID 39 // Length of CLSID string including zero terminator
+
+enum ELOGEVENT
+{
+ eDontLogEvents,
+ eLogEvents
+};
+
+inline HINSTANCE LOADINPROCSERVER(WCHAR* wszClsid, ELOGEVENT eLog=eLogEvents)
+{
+ WCHAR szEventSource[] = L"HookOleLoadInprocServer";
+ CHAR szInProc32[] = "InprocServer32";
+ CHAR szClsidKey[MAX_PATH];
+ CHAR szDllName[MAX_PATH];
+ WCHAR wszDllName[MAX_PATH];
+ CHAR szClsid[MAX_CLSID];
+ WCHAR szMessageBuff[1024];
+ long lSize = sizeof(szDllName);
+ LONG lRegResults;
+ HINSTANCE hDll = NULL;
+
+ strcpy(szClsidKey,szCLSIDKey);
+ strcat(szClsidKey,KEY_SEP);
+
+ WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, wszClsid, -01, szClsid, sizeof (szClsid), NULL, NULL);
+
+ strcat(szClsidKey,szClsid);
+ strcat(szClsidKey,KEY_SEP);
+ strcat(szClsidKey,szInProc32);
+ lRegResults = RegQueryValueA(HKEY_CLASSES_ROOT,
+ szClsidKey,
+ szDllName,
+ &lSize);
+ if (lRegResults == ERROR_SUCCESS)
+ {
+ if (hDll == 0)
+ {
+ hDll = LoadLibraryA(szDllName);
+ if ((eLog == eLogEvents) && (hDll == 0))
+ {
+ lstrcpyW(szMessageBuff,L"Error loading library - ");
+
+ MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, szDllName, -1, wszDllName, lstrlenA(szDllName)+1);
+
+ lstrcatW(szMessageBuff,wszDllName);
+ lstrcatW(szMessageBuff,L" for CLSID ");
+ lstrcatW(szMessageBuff,wszClsid);
+ LogEvent(szEventSource,szMessageBuff);
+ }
+ }
+ }
+ else if (eLog == eLogEvents)
+ {
+ lstrcpyW(szMessageBuff,L"Error reading registry for CLSID!");
+ lstrcatW(szMessageBuff,wszClsid);
+ LogEvent(szEventSource,szMessageBuff);
+ }
+ return hDll;
+}
+
+inline HINSTANCE LOADINPROCSERVER(REFCLSID rclsid, ELOGEVENT eLog=eLogEvents)
+{
+ WCHAR szClsid[MAX_CLSID];
+ HRESULT hResult;
+ HINSTANCE hDll = NULL;
+
+ hResult = StringFromGUID2(rclsid,szClsid,sizeof(szClsid));
+ if (SUCCEEDED(hResult))
+ {
+ hDll = LOADINPROCSERVER(szClsid, eLogEvents);
+ }
+ return hDll;
+}
+
+#endif //_LDINPROC_H_
diff --git a/private/ole32/ih/hklogevt.h b/private/ole32/ih/hklogevt.h
new file mode 100644
index 000000000..4c0f3cb17
--- /dev/null
+++ b/private/ole32/ih/hklogevt.h
@@ -0,0 +1,34 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994.
+//
+// File: hkLogEvt.h
+//
+// Contents: Log an application event
+//
+// Functions:
+//
+// History: 28-Sep-94 Don Wright Created
+//
+//--------------------------------------------------------------------------
+#ifndef _LOGEVENT_H_
+#define _LOGEVENT_H_
+
+inline void LogEvent(LPWSTR pSourceString,LPWSTR pEventText)
+{
+ HANDLE hEvent = RegisterEventSourceW(NULL,pSourceString);
+ LPCWSTR *pEventStr = (LPCWSTR *)&pEventText;
+ ReportEventW(hEvent,
+ EVENTLOG_INFORMATION_TYPE,
+ 0,
+ 0,
+ NULL,
+ 1,
+ 0,
+ pEventStr,
+ NULL);
+ DeregisterEventSource(hEvent);
+}
+
+#endif // _LOGEVENT_H_
diff --git a/private/ole32/ih/hkole32.h b/private/ole32/ih/hkole32.h
new file mode 100644
index 000000000..e9278f17b
--- /dev/null
+++ b/private/ole32/ih/hkole32.h
@@ -0,0 +1,284 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994.
+//
+// File: hkOle32.h
+//
+// Contents: OLE32 Hook Header File
+//
+// Functions:
+//
+// History: 29-Nov-94 Ben Lawrence, Don Wright Created
+//
+//--------------------------------------------------------------------------
+#ifndef _OLE32HK_H_
+#define _OLE32HK_H_
+
+
+#ifndef _NOHOOKOLE /* If _NOHOOKOLE is *NOT* defined then generate support code */
+
+#ifndef INITGUID
+#define INITGUID
+#endif /* INITGUID */
+
+#include "hkole32x.h"
+#include "hkoleobj.h"
+#include "hkLdInP.h"
+#include "hkregkey.h"
+#include "hkLogEvt.h"
+#include "ictsguid.h"
+#include <windows.h>
+
+extern IHookOleObject *pHookOleObject;
+extern HINSTANCE hHookDll;
+extern IClassFactory *pcfHook;
+extern BOOL bHookEnabledOverride;
+STDAPI_(HRESULT) EnableHookObject(BOOL bEnabled, BOOL *pbPrevious);
+
+
+#define DEFHOOKOBJECT \
+ HINSTANCE hHookDll = 0; /* Handle to SpyHook DLL */\
+ IHookOleObject* pHookOleObject = 0; /* IHookInterface interface pointer */\
+ IClassFactory* pcfHook = 0; /* Hook Class factory pointer */\
+ BOOL bHookEnabledOverride = TRUE;\
+ BOOL bUninited = TRUE;
+
+#define DEFENABLEHOOKOBJECT \
+STDAPI_(HRESULT) EnableHookObject(BOOL bEnabled, BOOL* pbPrevious) \
+{ \
+ static WCHAR szEventSource[] = L"EnableHookObject"; \
+ static WCHAR szCreateFailed[] = L"pcfHook->CreateInstance failed"; \
+ static WCHAR szBadDisable[] = L"Attempt to disable without valid pointer."; \
+ static WCHAR szBadEnable[] =L"Attempt to enable without valid pointer."; \
+ HRESULT hReturn = E_UNEXPECTED; \
+ if (pbPrevious != NULL) \
+ { \
+ if (IsBadWritePtr(pbPrevious, sizeof(BOOL))) return E_INVALIDARG; \
+ /* if a valid pointer was supplied, store current state */\
+ *pbPrevious = bHookEnabledOverride; \
+ } \
+ if ((bHookEnabledOverride != bEnabled) || bUninited) /* if this is really a state change */\
+ { \
+ bUninited = FALSE; \
+ bHookEnabledOverride = bEnabled; \
+ if (bHookEnabledOverride && hHookDll && pcfHook) /* hook enabled and dll loaded and class factory found */ \
+ { \
+ hReturn = pcfHook->CreateInstance(NULL, IID_IHookOleObject, (void**)&pHookOleObject); \
+ if (hReturn != S_OK) \
+ { \
+ LogEvent(szEventSource, szCreateFailed); \
+ } \
+ } \
+ else if (!bHookEnabledOverride) \
+ { \
+ if (hHookDll && pHookOleObject) /* dll loaded and hook active */ \
+ { \
+ pHookOleObject->Release(); \
+ pHookOleObject = NULL; \
+ hReturn = S_OK; \
+ } \
+ else \
+ { \
+ LogEvent(szEventSource, szBadDisable); \
+ } \
+ } \
+ else \
+ { \
+ LogEvent(szEventSource, szBadEnable); \
+ } \
+ } \
+ else /* else this is a change to the same state */\
+ { \
+ hReturn = S_OK; /* return ok, do nothing */ \
+ } \
+ return hReturn; \
+}
+
+#define DEFGETHOOKINTERFACE \
+STDAPI_(HRESULT) GetHookInterface(IHookOleObject** ppNewHook) \
+ { \
+ if (IsBadWritePtr(ppNewHook, sizeof(IHookOleObject*))) return E_INVALIDARG; \
+ *ppNewHook = pHookOleObject; \
+ if (pHookOleObject) \
+ { \
+ pHookOleObject->AddRef(); \
+ return S_OK; \
+ } \
+ return E_NOINTERFACE; \
+ }
+
+
+// These should be removed after 4.0 RTM.
+//
+inline void CALLHOOKOBJECT(HRESULT MAC_hr, REFCLSID MAC_rclsid, REFIID MAC_riid, IUnknown** MAC_ppv)
+{
+}
+
+inline void CALLHOOKOBJECTCREATE(HRESULT MAC_hr, REFCLSID MAC_rclsid, REFIID MAC_riid, IUnknown** MAC_ppv)
+{
+}
+
+inline void INITHOOKOBJECT(HRESULT MAC_hr)
+{
+ static WCHAR szEventSource[] = L"InitHookObject";
+ static WCHAR szGetClassObjectFailed[] = L"DllGetClassObject failed";
+ static WCHAR szNoEntryPoint[] = L"Could not find DllGetClassObject in Hook dll";
+ static WCHAR szDllFailedToLoad[] = L"Hook dll failed to load";
+ static WCHAR szHookNotRegistered[] = L"Hook CLSID is not registered correctly";
+ static WCHAR szHookAlreadyRunning[] = L"Hook already installed";
+
+ if (bHookEnabledOverride && SUCCEEDED(MAC_hr) && (!pHookOleObject))
+ {
+ HRESULT hResult = S_OK;
+ if (pHookOleObject == 0)
+ {
+
+ DWORD HookEnabled = FALSE;
+ HANDLE HookEvent = OpenEventA(EVENT_ALL_ACCESS,FALSE, szHookEventName);
+
+ if ((hHookDll == 0) && HookEvent)
+ {
+ CloseHandle(HookEvent);
+
+ HKEY hRegKey;
+ LONG RegResults = RegOpenKeyA(HookBase,szHookKey,&hRegKey);
+ if (RegResults == ERROR_SUCCESS)
+ {
+ CLSID HookClsid;
+ CHAR szClsidText[MAX_PATH];
+ DWORD RegDataType;
+ DWORD Datasize;
+
+ Datasize = sizeof(szClsidText);
+ RegQueryValueExA(hRegKey,
+ szCLSIDValue,
+ NULL,
+ &RegDataType,
+ (BYTE*)&szClsidText,
+ &Datasize);
+
+ if (SUCCEEDED(CLSIDFromStringA(szClsidText,&HookClsid)))
+ {
+ hHookDll = LOADINPROCSERVER(HookClsid);
+ if (hHookDll)
+ {
+ /* The OLE Spy Hook DLL exists */
+ LPFNGETCLASSOBJECT pfnGCO;
+ pfnGCO = (LPFNGETCLASSOBJECT)GetProcAddress(hHookDll, "DllGetClassObject");
+ if (pfnGCO)
+ {
+ if ((*pfnGCO)(HookClsid, IID_IClassFactory, (void**)&pcfHook) == NOERROR)
+ {
+ EnableHookObject(TRUE,NULL);
+ }
+ else // class factory could not be found
+ {
+ LogEvent(szEventSource, szGetClassObjectFailed);
+ }
+ }
+ else // GetProcAddress failed
+ {
+ LogEvent(szEventSource, szNoEntryPoint);
+ }
+ }
+ else // dll would not load or could not be found
+ {
+ LogEvent(szEventSource, szDllFailedToLoad);
+ }
+
+ }
+ else // could not find clsid in registry
+ {
+ LogEvent(szEventSource, szHookNotRegistered);
+ }
+ RegCloseKey(hRegKey);
+ } // hook not enabled
+
+ } // hook not in registry
+ }
+ else
+ {
+ LogEvent(szEventSource, szHookAlreadyRunning);
+ }
+ }
+}
+
+
+inline void UNINITHOOKOBJECT(void)
+{
+ if (pHookOleObject)
+ {
+ if (pHookOleObject)
+ {
+ pHookOleObject->Release();
+ pHookOleObject = NULL;
+ }
+ if (pcfHook)
+ {
+ pcfHook->Release();
+ pcfHook = NULL;
+ }
+ }
+}
+
+#ifdef DEFCLSIDS
+
+//these are all undefined in ole32hk because they are private CLSIDs
+//we define them here to null
+#define GUID_NULL CLSID_HookOleObject //use this for now so it will compile
+
+#define CLSID_ItemMoniker CLSID_NULL
+#define CLSID_FileMoniker CLSID_NULL
+#define CLSID_PointerMoniker CLSID_NULL
+#define CLSID_CompositeMoniker CLSID_NULL
+#define CLSID_AntiMoniker CLSID_NULL
+#define CLSID_PSBindCtx CLSID_NULL
+
+#endif /* DEFCLSIDS */
+
+///////////////////////////////////////////////////////////////////////////////
+#else /* _NOHOOKOLE */ /* If _NOHOOKOLE *IS* defined then generate empty stubs */
+
+#include "hkoleobj.h" // still need definition of IHookOleObject
+
+#define DEFHOOKOBJECT
+
+#define DEFENABLEHOOKOBJECT \
+STDAPI_(HRESULT) EnableHookObject(BOOL bEnabled, BOOL* pbPrevious) \
+{ \
+ if (pbPrevious != NULL) \
+ { \
+ if (IsBadWritePtr(pbPrevious, sizeof(BOOL))) return E_INVALIDARG; \
+ *pbPrevious = FALSE; \
+ } \
+ return E_NOTIMPL; \
+}
+
+#define DEFGETHOOKINTERFACE \
+STDAPI_(HRESULT) GetHookInterface(IHookOleObject** ppNewHook) \
+{ \
+ if (IsBadWritePtr(ppNewHook, sizeof(IHookOleObject*))) return E_INVALIDARG; \
+ *ppNewHook = NULL; \
+ return E_NOTIMPL; \
+}
+
+inline void CALLHOOKOBJECT(HRESULT MAC_hr, REFCLSID MAC_rclsid, REFIID MAC_riid, IUnknown** MAC_ppv)
+{
+}
+
+inline void CALLHOOKOBJECTCREATE(HRESULT MAC_hr, REFCLSID MAC_rclsid, REFIID MAC_riid, IUnknown** MAC_ppv)
+{
+}
+
+inline void INITHOOKOBJECT(HRESULT MAC_hr)
+{
+}
+
+inline void UNINITHOOKOBJECT(void)
+{
+}
+
+#endif // _NOHOOKOLE
+
+#endif // _OLE32HK_H_
diff --git a/private/ole32/ih/hkole32x.h b/private/ole32/ih/hkole32x.h
new file mode 100644
index 000000000..895c0e59c
--- /dev/null
+++ b/private/ole32/ih/hkole32x.h
@@ -0,0 +1,134 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994.
+//
+// File: hkOle32x.h
+//
+// Contents: OLE 32 Extensions Header File
+//
+// Functions:
+//
+// History: 29-Nov-94 Garry Lenz Created
+//
+//--------------------------------------------------------------------------
+#ifndef _HKOLE32X_H_
+#define _HKOLE32X_H_
+
+#include <Windows.h>
+#include <TChar.h>
+
+interface IHookOleObject;
+
+STDAPI CoGetCurrentLogicalThreadId(GUID* pguidLogicalThreadId);
+STDAPI GetHookInterface(IHookOleObject** pIHookOleObject);
+STDAPI EnableHookObject(BOOL fNewState, BOOL* pfPrevState);
+
+#define GUID_STRING_LENGTH 39
+#define CLSID_STRING_LENGTH 39
+#define IID_STRING_LENGTH 39
+#define PROGID_STRING_LENGTH 40
+
+
+
+// used by INITHOOKOBJECT
+
+inline HRESULT CLSIDFromStringA(LPSTR lpsz, LPCLSID lpclsid)
+{
+ LPWSTR lpwsz = new WCHAR[(strlen(lpsz)+1)];
+ MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, lpsz, -1, lpwsz, lstrlenA(lpsz)+1);
+ HRESULT hr = CLSIDFromString(lpwsz, lpclsid);
+ delete lpwsz;
+ return hr;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef OLETOOLS
+// these are needed only by the tools, not internally by ole32. we ifdef
+// it here to maintain source compatibility.
+
+inline BOOL IsOle32ProcDefined(LPCSTR pszProcName)
+{
+ BOOL fResult = FALSE;
+ HINSTANCE hInstOle32 = LoadLibrary(__T("OLE32.DLL"));
+ if (hInstOle32)
+ {
+ if (GetProcAddress(hInstOle32, pszProcName) != NULL)
+ fResult = TRUE;
+ FreeLibrary(hInstOle32);
+ }
+ return fResult;
+}
+
+inline HINSTANCE CoLoadLibrary(LPSTR lpszLibName, BOOL bAutoFree)
+{
+ LPWSTR lpwsz = new WCHAR[(strlen(lpszLibName)+1)];
+ MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, lpszLibName, -1, lpwsz, lstrlenA(lpszLibName)+1);
+ HINSTANCE hInstance = CoLoadLibrary(lpwsz, bAutoFree);
+ delete lpwsz;
+ return hInstance;
+}
+
+inline HRESULT IIDFromString(LPSTR lpsz, LPIID lpiid)
+{
+ LPWSTR lpwsz = new WCHAR[(strlen(lpsz)+1)];
+ MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, lpsz, -1, lpwsz, lstrlenA(lpsz)+1);
+ HRESULT hr = IIDFromString(lpwsz, lpiid);
+ delete lpwsz;
+ return hr;
+}
+
+inline HRESULT StringFromIID(REFIID riid, LPSTR FAR* lplpsz)
+{
+ HRESULT hr = StringFromIID(riid, (LPWSTR*)lplpsz);
+ if (hr == S_OK)
+ {
+ WCHAR wsz[IID_STRING_LENGTH];
+ lstrcpyW(wsz, (LPWSTR)*lplpsz);
+ WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, wsz, -1, *lplpsz, lstrlenW(wsz), NULL, NULL);
+ }
+ return hr;
+}
+
+inline HRESULT StringFromCLSID(REFCLSID rclsid, LPSTR FAR* lplpsz)
+{
+ HRESULT hr = StringFromCLSID(rclsid, (LPWSTR*)lplpsz);
+ if (hr == S_OK)
+ {
+ WCHAR wsz[CLSID_STRING_LENGTH];
+ lstrcpyW(wsz, (LPWSTR)*lplpsz);
+ WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, wsz, -1, *lplpsz, lstrlenW(wsz), NULL, NULL);
+ }
+ return hr;
+}
+
+inline HRESULT ProgIDFromCLSID(REFCLSID rclsid, LPSTR FAR* lplpsz)
+{
+ HRESULT hr = ProgIDFromCLSID(rclsid, (LPWSTR*)lplpsz);
+ if (hr == S_OK)
+ {
+ WCHAR wsz[PROGID_STRING_LENGTH];
+ lstrcpyW(wsz, (LPWSTR)*lplpsz);
+ WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, wsz, -1, *lplpsz, lstrlenW(wsz), NULL, NULL);
+ }
+ return hr;
+}
+
+inline HRESULT CLSIDFromProgID(LPCSTR lpszProgID, LPCLSID lpclsid)
+{
+ LPWSTR lpwsz = new WCHAR[(strlen(lpszProgID)+1)];
+ MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, lpszProgID, -1, lpwsz, lstrlenA(lpszProgID)+1);
+ HRESULT hr = CLSIDFromProgID(lpwsz, lpclsid);
+ delete lpwsz;
+ return hr;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+#endif
+
+#endif // _HKOLE32X_H_
diff --git a/private/ole32/ih/hkoleobj.h b/private/ole32/ih/hkoleobj.h
new file mode 100644
index 000000000..06a56a777
--- /dev/null
+++ b/private/ole32/ih/hkoleobj.h
@@ -0,0 +1,71 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994.
+//
+// File: hkoleobj.h
+//
+// Contents: IHookOleObject Interface Header File
+//
+// Functions:
+//
+// History: 01-Aug-94 Garry Lenz Created
+// 20-Sep-94 Garry Lenz Added EnableRegistration
+// 13-Oct-94 Garry Lenz Derive from IUnknownEx
+// 13-Oct-94 Garry Lenz Added EnumObjects
+// 20-Oct-94 Garry Lenz Added AssociateInstance
+// 14-Dec-94 Don Wright Added fCreate param to RegisterObject
+//
+//--------------------------------------------------------------------------
+
+#ifndef _IHOOKOLEOBJECT_H_
+#define _IHOOKOLEOBJECT_H_
+
+#include <Windows.h>
+#include "hkunkex.h"
+
+interface IHookOleInstance;
+
+enum EHookEnumFlags
+{
+ HEF_Instances = 1,
+ HEF_Classes = 2,
+ HEF_Interfaces = 3
+};
+
+interface IHookOleObject : IUnknownEx
+{
+ public:
+ STDMETHOD ( EnumObjects )
+ (
+ DWORD dwEnumFlags,
+ IEnumUnknown** pIEnum
+ ) = 0;
+ STDMETHOD ( RegisterObject )
+ (
+ REFCLSID rclsid,
+ REFIID riid,
+ LPVOID pvObj,
+ BOOL fCreate
+ ) = 0;
+ STDMETHOD ( UnregisterObject )
+ (
+ LPVOID pvObj
+ ) = 0;
+ STDMETHOD ( UnregisterAll )
+ (
+ void
+ ) = 0;
+ STDMETHOD ( EnableRegistration )
+ (
+ BOOL fEnable
+ ) = 0;
+ STDMETHOD ( AssociateInstance )
+ (
+ REFIID riid,
+ LPVOID pvObj,
+ IHookOleInstance** ppIHookOleInstance
+ ) = 0;
+};
+
+#endif // _IHOOKOLEOBJECT_H_
diff --git a/private/ole32/ih/hkregkey.h b/private/ole32/ih/hkregkey.h
new file mode 100644
index 000000000..0d753b945
--- /dev/null
+++ b/private/ole32/ih/hkregkey.h
@@ -0,0 +1,76 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994.
+//
+// File: hkregkey.h
+//
+// Contents: Defines for accessing the Registry
+//
+// Functions:
+//
+// History: 01-Aug-94 Garry Lenz Created
+// 02-Aug-94 Don Wright Support Ansi/Unicode
+// 25-Oct-94 Don Wright Add Keys for HookOleLog
+//
+//--------------------------------------------------------------------------
+
+#ifndef _REGISTRYKEYS_H_
+#define _REGISTRYKEYS_H_
+
+#include <Windows.h>
+
+#define KEY_SEP "\\"
+#define WKEY_SEP L"\\"
+
+//Named Event for Global Hooking Flag
+#define szHookEventName "HookSwitchHookEnabledEvent"
+
+// Keys used by OLE32hk.h for finding HookOle dll
+#define HookBase HKEY_LOCAL_MACHINE
+#define szHookKey "Software\\Microsoft\\HookOleObject"
+#define wszHookKey L"Software\\Microsoft\\HookOleObject"
+
+// Keys used by HookOle for finding Wrappers and Filters
+#define HookConfigBase HKEY_LOCAL_MACHINE
+#define szHookConfigKey "Software\\Microsoft\\HookOleObject"
+#define wszHookConfigKey L"Software\\Microsoft\\HookOleObject"
+
+// Keys used by HookOleLog
+#define HookLogBase HKEY_LOCAL_MACHINE
+#define szHookLogKey "Software\\Microsoft\\HookOleLog"
+#define wszHookLogKey L"Software\\Microsoft\\HookOleLog"
+
+// Common sub-keys
+#define szWrappersKey "Wrappers"
+#define wszWrappersKey L"Wrappers"
+#define szFiltersKey "Filters"
+#define wszFiltersKey L"Filters"
+#define szStatisticsKey "Statistics"
+#define wszStatisticsKey L"Statistics"
+#define szCLSIDKey "CLSID"
+#define wszCLSIDKey L"CLSID"
+#define szCurrentKey "Current"
+#define wszCurrentKey L"Current"
+#define szIIDKey "Interface"
+#define wszIIDKey L"Interface"
+#define szModuleKey "Module"
+#define wszModuleKey L"Module"
+#define szDefaultKey "Default"
+#define wszDefaultKey L"Default"
+#define szIncludeOnlyKey "Include Only"
+#define wszIncludeOnlyKey L"Include Only"
+#define szExcludeKey "Exclude"
+#define wszExcludeKey L"Exclude"
+
+// Common value names
+#define szEnabledValue "Enabled"
+#define wszEnabledValue L"Enabled"
+#define szCLSIDValue "CLSID"
+#define wszCLSIDValue L"CLSID"
+#define szWrapperValue "Wrapper"
+#define wszWrapperValue L"Wrapper"
+#define szFilterValue "Filter"
+#define wszFilterValue L"Filter"
+
+#endif // _REGISTRYKEYS_H_
diff --git a/private/ole32/ih/hkunkex.h b/private/ole32/ih/hkunkex.h
new file mode 100644
index 000000000..6e989c9f4
--- /dev/null
+++ b/private/ole32/ih/hkunkex.h
@@ -0,0 +1,31 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994.
+//
+// File: khunkex.h
+//
+// Contents: Extended IUnknown Interface Header File
+//
+// Functions:
+//
+// History: 13-Oct-94 Garry Lenz Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef _IUNKNOWNEX_H_
+#define _IUNKNOWNEX_H_
+
+#include <Windows.h>
+
+interface IUnknownEx : IUnknown
+{
+ public:
+ STDMETHOD (QueryContainedInterface)
+ (
+ REFIID riid,
+ LPVOID* ppvObj
+ ) = 0;
+};
+
+#endif // _IUNKNOWNEX_H_
diff --git a/private/ole32/ih/ictsguid.h b/private/ole32/ih/ictsguid.h
new file mode 100644
index 000000000..08d1548d6
--- /dev/null
+++ b/private/ole32/ih/ictsguid.h
@@ -0,0 +1,108 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994.
+//
+// File: ICTGUID.h
+//
+// Contents: CLSIDs and IIDs for ICTS (Interface Conformance Test Suite)
+// Header File
+//
+// Functions:
+//
+// History: 15-Jun-94 Garry Lenz Created
+// 12-Oct-94 Garry Lenz Added IUnknownEx
+// 12-Oct-94 Garry Lenz Added IEnumGUID
+// 13-Oct-94 Garry Lenz Added Wrapper & Filter CLSIDs
+//
+//--------------------------------------------------------------------------
+
+#ifndef _ICTSGUID_H_
+#define _ICTSGUID_H_
+
+#include <Windows.h>
+
+//#ifdef INITGUID
+ DEFINE_OLEGUID(IID_IUnknownEx, 0x0002AD00, 0, 0);
+ DEFINE_OLEGUID(IID_IEnumGUID, 0x0002AD01, 0, 0);
+
+ DEFINE_OLEGUID(CLSID_HookOleObject, 0x0002AD10, 0, 0);
+ DEFINE_OLEGUID(IID_IHookOleObject, 0x0002AD11, 0, 0);
+ DEFINE_OLEGUID(IID_IHookOleClass, 0x0002AD12, 0, 0);
+ DEFINE_OLEGUID(IID_IHookOleInstance, 0x0002AD13, 0, 0);
+ DEFINE_OLEGUID(IID_IHookOleInterface, 0x0002AD14, 0, 0);
+ DEFINE_OLEGUID(IID_IHookOleMethod, 0x0002AD15, 0, 0);
+ DEFINE_OLEGUID(IID_IHookOleWrapper, 0x0002AD1A, 0, 0);
+ DEFINE_OLEGUID(IID_IHookOleFilter, 0x0002AD1B, 0, 0);
+
+ DEFINE_OLEGUID(CLSID_HookOleAPI, 0x0002AD20, 0, 0);
+
+ DEFINE_OLEGUID(CLSID_HookOleLog, 0x0002AD30, 0, 0);
+ DEFINE_OLEGUID(IID_IHookOleLog, 0x0002AD31, 0, 0);
+
+ DEFINE_OLEGUID(CLSID_HookOleWrapper, 0x0002ADA0, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOW_ComponentObject, 0x0002ADA1, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOW_CompoundDocument, 0x0002ADA2, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOW_DataTransfer, 0x0002ADA3, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOW_Linking, 0x0002ADA4, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOW_PersistentStorage, 0x0002ADA5, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOW_DragAndDrop, 0x0002ADA6, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOW_InPlaceActivation, 0x0002ADA7, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOW_Concurrency, 0x0002ADA8, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOW_Automation, 0x0002ADA9, 0, 0);
+
+ DEFINE_OLEGUID(CLSID_HookOleFilter, 0x0002ADB0, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOF_ComponentObject, 0x0002ADB1, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOF_CompoundDocument, 0x0002ADB2, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOF_DataTransfer, 0x0002ADB3, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOF_Linking, 0x0002ADB4, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOF_PersistentStorage, 0x0002ADB5, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOF_DragAndDrop, 0x0002ADB6, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOF_InPlaceActivation, 0x0002ADB7, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOF_Concurrency, 0x0002ADB8, 0, 0);
+ DEFINE_OLEGUID(CLSID_HOF_Automation, 0x0002ADB9, 0, 0);
+#if 0
+//#else
+ extern "C"
+ {
+ extern IID IID_IUnknownEx;
+ extern IID IID_IEnumGUID;
+
+ extern CLSID CLSID_HookOleObject;
+ extern IID IID_IHookOleObject;
+ extern IID IID_IHookOleClass;
+ extern IID IID_IHookOleInstance;
+ extern IID IID_IHookOleInterface;
+ extern IID IID_IHookOleMethod;
+ extern IID IID_IHookOleWrapper;
+ extern IID IID_IHookOleFilter;
+
+ extern CLSID CLSID_HookOleAPI;
+
+ extern CLSID CLSID_HookOleLog;
+ extern IID IID_IHookOleLog;
+
+ extern CLSID CLSID_HookOleWrapper;
+ extern CLSID CLSID_HOW_ComponentObject;
+ extern CLSID CLSID_HOW_CompoundDocument;
+ extern CLSID CLSID_HOW_DataTransfer;
+ extern CLSID CLSID_HOW_Linking;
+ extern CLSID CLSID_HOW_PersistentStorage;
+ extern CLSID CLSID_HOW_DragAndDrop;
+ extern CLSID CLSID_HOW_InPlaceActivation;
+ extern CLSID CLSID_HOW_Concurrency;
+
+ extern CLSID CLSID_HookOleFilter;
+ extern CLSID CLSID_HOF_ComponentObject;
+ extern CLSID CLSID_HOF_CompoundDocument;
+ extern CLSID CLSID_HOF_DataTransfer;
+ extern CLSID CLSID_HOF_Linking;
+ extern CLSID CLSID_HOF_PersistentStorage;
+ extern CLSID CLSID_HOF_DragAndDrop;
+ extern CLSID CLSID_HOF_InPlaceActivation;
+ extern CLSID CLSID_HOF_Concurrency;
+ }
+
+#endif /* INITGUID */
+
+#endif /* _ICTSGUID_H_ */
diff --git a/private/ole32/ih/itrkmnk.hxx b/private/ole32/ih/itrkmnk.hxx
new file mode 100644
index 000000000..5c1422ed0
--- /dev/null
+++ b/private/ole32/ih/itrkmnk.hxx
@@ -0,0 +1,49 @@
+#ifndef _ITRKMNK_HXX_
+#define _ITRKMNK_HXX_
+
+
+// Flags for the CFileMoniker::EnableTracking routine.
+// Note that these flags must remain in the lower
+// 16 bits, as the upper 16 bits are used for Track Flags
+// (see the two macros which follow).
+
+#define OT_READTRACKINGINFO 0x0001L
+#define OT_DISABLETRACKING 0x0002L
+#define OT_ENABLESAVE 0x0004L
+#define OT_DISABLESAVE 0x0008L
+#define OT_ENABLEREDUCE 0x0010L
+#define OT_DISABLEREDUCE 0x0020L
+
+#ifdef _CAIRO_
+#define OT_MAKETRACKING 0x0040L
+#endif
+
+// The following two macros allow TRACK_* flags ("olecairo.h")
+// to be piggy-backed onto the above OT flags, and vice
+// versa.
+
+#ifdef _CAIRO_
+
+#define TRACK_2_OT_FLAGS( flags ) ( flags << 16 )
+#define OT_2_TRACK_FLAGS( flags ) ( flags >> 16 )
+
+#endif // _CAIRO_
+
+
+#define DEB_TRACK DEB_ITRACE
+
+class ITrackingMoniker : public IUnknown
+{
+public:
+ virtual HRESULT __stdcall QueryInterface(
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject) = 0;
+
+ virtual ULONG __stdcall AddRef( void) = 0;
+
+ virtual ULONG __stdcall Release( void) = 0;
+
+ virtual HRESULT __stdcall EnableTracking ( IMoniker *pmkLeft, ULONG ulFlags ) = 0;
+};
+#endif
+
diff --git a/private/ole32/ih/map_kv.h b/private/ole32/ih/map_kv.h
new file mode 100644
index 000000000..3d07d8f78
--- /dev/null
+++ b/private/ole32/ih/map_kv.h
@@ -0,0 +1,116 @@
+#ifndef __MAP_KV_H__
+#define __MAP_KV_H__
+
+#include <memapi.hxx>
+
+/////////////////////////////////////////////////////////////////////////////
+// class CMapKeyToValue - a mapping from 'KEY's to 'VALUE's, passed in as
+// pv/cb pairs. The keys can be variable length, although we optmizize the
+// case when they are all the same.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+STDAPI_(UINT) MKVDefaultHashKey(LPVOID pKey, UINT cbKey);
+
+#ifdef WIN32
+DECLARE_HANDLE(HMAPKEY);
+#else
+DECLARE_HANDLE32(HMAPKEY);
+#endif
+
+typedef UINT (STDAPICALLTYPE FAR* LPFNHASHKEY)(LPVOID, UINT);
+
+class FAR CMapKeyToValue : public CPrivAlloc
+{
+public:
+ CMapKeyToValue(UINT cbValue, UINT cbKey = 0,
+ int nBlockSize=10,
+ LPFNHASHKEY lpfnHashKey = NULL,
+ UINT nHashSize = 17);
+ ~CMapKeyToValue();
+
+ // number of elements
+ int GetCount() const { return m_nCount; }
+ BOOL IsEmpty() const { return m_nCount == 0; }
+
+ // Lookup; return FALSE if not found
+ BOOL Lookup(LPVOID pKey, UINT cbKey, LPVOID pValue) const;
+ BOOL LookupHKey(HMAPKEY hKey, LPVOID pValue) const;
+ BOOL LookupAdd(LPVOID pKey, UINT cbKey, LPVOID pValue) const;
+
+ // add a new (key, value) pair; return FALSE if out of memory
+ BOOL SetAt(LPVOID pKey, UINT cbKey, LPVOID pValue);
+ BOOL SetAtHKey(HMAPKEY hKey, LPVOID pValue);
+
+ // removing existing (key, ?) pair; return FALSE if no such key
+ BOOL RemoveKey(LPVOID pKey, UINT cbKey);
+ BOOL RemoveHKey(HMAPKEY hKey);
+ void RemoveAll();
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return (m_nCount == 0) ? (POSITION)NULL : BEFORE_START_POSITION; }
+ void GetNextAssoc(POSITION FAR* pNextPosition, LPVOID pKey,
+ UINT FAR* pcbKey, LPVOID pValue) const;
+
+ // return HMAPKEY for given key; returns NULL if not currently in map
+ HMAPKEY GetHKey(LPVOID pKey, UINT cbKey) const;
+
+ void AssertValid() const;
+
+private:
+ // abstracts, somewhat, variable and fixed sized keys; size is really
+ // m_cbKeyInAssoc.
+ union CKeyWrap
+ {
+ BYTE rgbKey[sizeof(LPVOID) + sizeof(UINT)];
+ struct
+ {
+ LPVOID pKey;
+ UINT cbKey;
+ };
+ };
+
+ // Association of one key and one value; NOTE: even though in general
+ // the size of the key and value varies, for any given map,
+ // the size of an assoc is fixed.
+ struct CAssoc
+ {
+ CAssoc FAR* pNext;
+ UINT nHashValue; // needed for efficient iteration
+ CKeyWrap key; // size is really m_cbKeyInAssoc
+ // BYTE rgbValue[m_cbValue];
+ };
+
+ UINT SizeAssoc() const
+ { return sizeof(CAssoc)-sizeof(CKeyWrap) + m_cbKeyInAssoc + m_cbValue; }
+ CAssoc FAR* NewAssoc(UINT hash, LPVOID pKey, UINT cbKey, LPVOID pValue);
+ void FreeAssoc(CAssoc FAR* pAssoc);
+ BOOL CompareAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const;
+ CAssoc FAR* GetAssocAt(LPVOID pKey, UINT cbKey, UINT FAR& nHash) const;
+
+ BOOL SetAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const;
+ void GetAssocKeyPtr(CAssoc FAR* pAssoc, LPVOID FAR* ppKey,UINT FAR* pcbKey) const;
+ void FreeAssocKey(CAssoc FAR* pAssoc) const;
+ void GetAssocValuePtr(CAssoc FAR* pAssoc, LPVOID FAR* ppValue) const;
+ void GetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const;
+ void SetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const;
+
+ BOOL InitHashTable();
+
+ UINT m_cbValue;
+ UINT m_cbKey; // variable length if 0
+ UINT m_cbKeyInAssoc; // always non-zero
+
+ CAssoc FAR* FAR* m_pHashTable;
+ UINT m_nHashTableSize;
+ LPFNHASHKEY m_lpfnHashKey;
+
+ int m_nCount;
+ CAssoc FAR* m_pFreeList;
+ struct CPlex FAR* m_pBlocks;
+ int m_nBlockSize;
+};
+
+
+#endif // !__MAP_KV_H__
diff --git a/private/ole32/ih/map_up.h b/private/ole32/ih/map_up.h
new file mode 100644
index 000000000..36548a670
--- /dev/null
+++ b/private/ole32/ih/map_up.h
@@ -0,0 +1,66 @@
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+
+class FAR CMapUintPtr : public CPrivAlloc
+{
+public:
+ // Construction
+ CMapUintPtr(UINT nBlockSize=10)
+ : m_mkv(sizeof(void FAR*), sizeof(UINT), nBlockSize) { }
+
+ // Attributes
+ // number of elements
+ int GetCount() const
+ { return m_mkv.GetCount(); }
+ BOOL IsEmpty() const
+ { return GetCount() == 0; }
+
+ // Lookup
+ BOOL Lookup(UINT key, void FAR* FAR& value) const
+ { return m_mkv.Lookup((LPVOID)&key, sizeof(UINT), (LPVOID)&value); }
+
+ BOOL LookupHKey(HMAPKEY hKey, void FAR* FAR& value) const
+ { return m_mkv.LookupHKey(hKey, (LPVOID)&value); }
+
+ BOOL LookupAdd(UINT key, void FAR* FAR& value) const
+ { return m_mkv.LookupAdd((LPVOID)&key, sizeof(UINT), (LPVOID)&value); }
+
+ // Add/Delete
+ // add a new (key, value) pair
+ BOOL SetAt(UINT key, void FAR* value)
+ { return m_mkv.SetAt((LPVOID)&key, sizeof(UINT), (LPVOID)&value); }
+ BOOL SetAtHKey(HMAPKEY hKey, void FAR* value)
+ { return m_mkv.SetAtHKey(hKey, (LPVOID)&value); }
+
+ // removing existing (key, ?) pair
+ BOOL RemoveKey(UINT key)
+ { return m_mkv.RemoveKey((LPVOID)&key, sizeof(UINT)); }
+
+ BOOL RemoveHKey(HMAPKEY hKey)
+ { return m_mkv.RemoveHKey(hKey); }
+
+ void RemoveAll()
+ { m_mkv.RemoveAll(); }
+
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return m_mkv.GetStartPosition(); }
+
+ void GetNextAssoc(POSITION FAR& rNextPosition, UINT FAR& rKey, void FAR* FAR& rValue) const
+ { m_mkv.GetNextAssoc(&rNextPosition, (LPVOID)&rKey, NULL, (LPVOID)&rValue); }
+
+ HMAPKEY GetHKey(UINT key) const
+ { return m_mkv.GetHKey((LPVOID)&key, sizeof(UINT)); }
+
+#ifdef _DEBUG
+ void AssertValid() const
+ { m_mkv.AssertValid(); }
+#endif
+
+private:
+ CMapKeyToValue m_mkv;
+};
diff --git a/private/ole32/ih/memapi.hxx b/private/ole32/ih/memapi.hxx
new file mode 100644
index 000000000..d6a1a5ad6
--- /dev/null
+++ b/private/ole32/ih/memapi.hxx
@@ -0,0 +1,190 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: MemAPI.HXX
+//
+// Contents: Internal memory allocation routines
+//
+// Classes: CPrivAlloc
+//
+// Functions: PrivMemAlloc
+// PrivMemAlloc8
+// PrivMemFree
+// UtGlobalxxx
+//
+// History:
+// 25-Jan-94 alexgo added PubMemReAlloc
+// 04-Nov-93 AlexT Created
+//
+// Notes:
+//
+// For memory that the application can free with the task IMalloc, use
+// CoTaskMemAlloc and CoTaskMemFree.
+//
+// For process local memory that is used internally, use PrivMemAlloc and
+// PrivMemFree.
+//
+// For process local class instances, use CPrivAlloc as a base class.
+//
+// PubMemAlloc, PubMemRealloc, and PubMemFree are obsolete.
+//--------------------------------------------------------------------------
+
+#ifndef __MEMAPI_HXX__
+#define __MEMAPI_HXX__
+
+//PubMemAlloc is obsolete. Use CoTaskMemAlloc.
+#define PubMemAlloc(ulcb) CoTaskMemAlloc(ulcb)
+
+//PubMemRealloc is obsolete. Use CoTaskMemRealloc.
+#define PubMemRealloc(pv, ulcb) CoTaskMemRealloc(pv, ulcb)
+
+//PubMemFree is obsolete. Use CoTaskMemFree.
+#define PubMemFree(pv) CoTaskMemFree(pv)
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: PrivMemAlloc
+//
+// Synopsis: Allocate private memory block
+//
+// Arguments: [ulcb] -- size of memory block
+//
+// Returns: Pointer to memory block
+//
+//--------------------------------------------------------------------------
+extern HANDLE g_hHeap;
+
+typedef
+LPVOID (WINAPI HEAP_ALLOC_ROUTINE)(
+ HANDLE hHeap,
+ DWORD dwFlags,
+ DWORD dwBytes);
+
+extern HEAP_ALLOC_ROUTINE * pfnHeapAlloc;
+
+#if DBG==1
+# define PrivMemAlloc(ulcb) CoTaskMemAlloc(ulcb)
+#else
+# define PrivMemAlloc(ulcb) (*pfnHeapAlloc)(g_hHeap, 0, (ulcb))
+#endif //DBG==1
+
+//+-------------------------------------------------------------------------
+//
+// Function: PrivMemAlloc8
+//
+// Synopsis: Allocate private memory block aligned on 8 byte boundary
+//
+// Arguments: [ulcb] -- size of memory block
+//
+// Returns: Pointer to memory block
+//
+// History: 14 Jul 94 AlexMit Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+#define PrivMemAlloc8(ulcb) PrivMemAlloc(((ulcb)+7)&~7)
+
+//+-------------------------------------------------------------------------
+//
+// Function: PrivMemFree
+//
+// Synopsis: Frees private memory block
+//
+// Arguments: [pv] -- pointer to memory block
+//
+//--------------------------------------------------------------------------
+typedef
+BOOL (WINAPI HEAP_FREE_ROUTINE)(
+ HANDLE hHeap,
+ DWORD dwFlags,
+ LPVOID lpMem);
+
+extern HEAP_FREE_ROUTINE *pfnHeapFree;
+
+#if DBG==1
+# define PrivMemFree(pv) CoTaskMemFree(pv)
+#else
+# define PrivMemFree(pv) (*pfnHeapFree)(g_hHeap, 0, (pv))
+#endif //DBG==1
+
+//+-------------------------------------------------------------------------
+//
+// Class: CPrivAlloc
+//
+// Purpose: Base class for process local classes
+//
+// Interface: operator new
+// operator delete
+//
+// History: 04-Nov-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+class CPrivAlloc
+{
+public:
+ void *operator new(size_t size)
+ {
+ return PrivMemAlloc(size);
+ };
+
+ void operator delete(void *pv)
+ {
+ PrivMemFree(pv);
+ };
+};
+
+void FAR* _CRTAPI1 operator new(size_t size);
+void _CRTAPI1 operator delete(void FAR* ptr);
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtGlobalxxx
+//
+// Synopsis: Debugging version of global memory functions
+//
+// History: 28-Feb-94 AlexT Created
+// 10-May-94 KevinRo Disabled for DDE build
+//
+// Notes:
+//
+// DDE uses GlobalAlloc for exchanging data between 16 and 32 bit
+// servers, as well as for passing data across to other processes.
+// The routine GlobalSize() is used quite often in these routines to
+// determine the amount of data in the block. Therefore, we shouldn't go
+// adding extra data to the block, like these routines do. Therefore,
+// we won't override these routines if OLE_DDE_NO_GLOBAL_TRACKING is defined
+//
+//
+//--------------------------------------------------------------------------
+
+#if DBG==1 && defined(WIN32) && !defined(OLE_DDE_NO_GLOBAL_TRACKING)
+
+#define GlobalAlloc(uiFlag, cbBytes) UtGlobalAlloc(uiFlag, cbBytes)
+#define GlobalReAlloc(h, cb, uiFlag) UtGlobalReAlloc(h, cb, uiFlag)
+#define GlobalLock(h) UtGlobalLock(h)
+#define GlobalUnlock(h) UtGlobalUnlock(h)
+#define GlobalFree(h) UtGlobalFree(h)
+#define SetClipboardData(uFormat, hMem) UtSetClipboardData(uFormat, hMem)
+
+extern "C" HGLOBAL WINAPI UtGlobalAlloc(UINT uiFlag, DWORD cbUser);
+extern "C" HGLOBAL WINAPI UtGlobalReAlloc(HGLOBAL hGlobal, DWORD cbUser, UINT uiFlag);
+extern "C" LPVOID WINAPI UtGlobalLock(HGLOBAL hGlobal);
+extern "C" BOOL WINAPI UtGlobalUnlock(HGLOBAL hGlobal);
+extern "C" HGLOBAL WINAPI UtGlobalFree(HGLOBAL hGlobal);
+extern "C" HANDLE WINAPI UtSetClipboardData(UINT uFormat, HANDLE hMem);
+
+extern "C" void UtGlobalFlushTracking(void);
+
+#else
+
+#define UtGlobalFlushTracking() NULL
+#define UtGlobalStopTracking(hGlobal) NULL
+
+#endif // !(DBG==1 && defined(WIN32))
+
+#endif // !defined(__MEMAPI_HXX__)
diff --git a/private/ole32/ih/nt1ole.reg b/private/ole32/ih/nt1ole.reg
new file mode 100644
index 000000000..0bfdab9b4
--- /dev/null
+++ b/private/ole32/ih/nt1ole.reg
@@ -0,0 +1,576 @@
+\Registry\MACHINE\SYSTEM\CurrentControlSet\Services
+
+\Registry\MACHINE\SYSTEM\CurrentControlSet\Services\OLE
+ Type = REG_DWORD 0x10
+ Start = REG_DWORD 0x3
+ ErrorControl = REG_DWORD 0x0
+ ImagePath = REG_EXPAND_SZ %SystemRoot%\System32\scm.exe
+ ObjectName = REG_SZ LocalSystem
+
+\Registry\MACHINE\SOFTWARE\Classes\CLSID
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000300-0000-0000-C000-000000000046}
+ = StdOleLink
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000300-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000301-0000-0000-C000-000000000046}
+ = StdMemStm
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000301-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000302-0000-0000-C000-000000000046}
+ = StdMemBytes
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000302-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000303-0000-0000-C000-000000000046}
+ = FileMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000303-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000304-0000-0000-C000-000000000046}
+ = ItemMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000304-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000305-0000-0000-C000-000000000046}
+ = AntiMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000305-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000306-0000-0000-C000-000000000046}
+ = PointerMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000306-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000307-0000-0000-C000-000000000046}
+ = DdeFileMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000307-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000308-0000-0000-C000-000000000046}
+ = PackagerMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000308-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000309-0000-0000-C000-000000000046}
+ = CompositeMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000309-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000030A-0000-0000-C000-000000000046}
+ = DdeCompositeMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000030A-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000030B-0000-0000-C000-000000000046}
+ = DfMarshal
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000030B-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}
+ = Metafile
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}
+ = Device Independent Bitmap
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\StaticMetafile
+\Registry\MACHINE\SOFTWARE\Classes\StaticMetafile\CLSID
+ = {00000315-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\ProgID
+ = StaticMetafile
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\InprocServer
+ = ole32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\DataFormats
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\DataFormats\DefaultFile
+ = 3
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\DataFormats\GetSet
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\DataFormats\GetSet\0
+ = 3,1,32,3
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\MiscStatus
+ = 536
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\Conversion
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\Conversion\Readable
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\Conversion\Readable\Main
+ = 3,MSDraw
+
+
+\Registry\MACHINE\SOFTWARE\Classes\StaticDib
+\Registry\MACHINE\SOFTWARE\Classes\StaticDib\CLSID
+ = {00000316-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\ProgID
+ = StaticDib
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\InprocServer
+ = ole32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\DataFormats
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\DataFormats\DefaultFile
+ = 8
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\DataFormats
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\DataFormats\GetSet
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\DataFormats\GetSet\0
+ = 8,1,1,3
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\MiscStatus
+ = 536
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\Conversion
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\Conversion\Readable
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\Conversion\Readable\Main
+ = 8,PBrush
+
+
+\Registry\MACHINE\SOFTWARE\Classes\PBrush
+\Registry\MACHINE\SOFTWARE\Classes\PBrush\CLSID
+ = {0003000a-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0003000a-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0003000a-0000-0000-C000-000000000046}\ProgID
+ = PBrush
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0003000a-0000-0000-C000-000000000046}\Ole1Class
+ = PBrush
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0003000a-0000-0000-C000-000000000046}\MiscStatus
+ = 512
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0003000a-0000-0000-C000-000000000046}\Conversion
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0003000a-0000-0000-C000-000000000046}\Conversion\Readable
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0003000a-0000-0000-C000-000000000046}\Conversion\Readable\Main
+ = 8
+
+
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00030007-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00030007-0000-0000-C000-000000000046}\ProgID
+ = MSDraw
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00030007-0000-0000-C000-000000000046}\Ole1Class
+ = MSDraw
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00030007-0000-0000-C000-000000000046}\MiscStatus
+ = 512
+
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+ = oleprx32_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{6f11fe5c-2fc5-101b-9e45-00000b65c7ef}\InprocServer32
+ = oleprx32.dll
+
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface
+
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000000-0000-0000-C000-000000000046}
+ = IUnknown
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000000-0000-0000-C000-000000000046}\BaseInterface
+ =
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000000-0000-0000-C000-000000000046}\NumMethods
+ = 3
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000002-0000-0000-C000-000000000046}
+ = IMalloc
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000002-0000-0000-C000-000000000046}\NumMethods
+ = 9
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000003-0000-0000-C000-000000000046}
+ = IMarshal
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000003-0000-0000-C000-000000000046}\NumMethods
+ = 9
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000004-0000-0000-C000-000000000046}
+ = IRpcChannel
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000004-0000-0000-C000-000000000046}\NumMethods
+ = 7
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000005-0000-0000-C000-000000000046}
+ = IRpcStub
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000005-0000-0000-C000-000000000046}\NumMethods
+ = 8
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000007-0000-0000-C000-000000000046}
+ = IRpcProxy
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000007-0000-0000-C000-000000000046}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000009-0000-0000-C000-000000000046}
+ = IPSFactory
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000009-0000-0000-C000-000000000046}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000016-0000-0000-C000-000000000046}
+ = IMessageFilter
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000016-0000-0000-C000-000000000046}\NumMethods
+ = 6
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000018-0000-0000-C000-000000000046}
+ = IStdMarshalInfo
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000018-0000-0000-C000-000000000046}\NumMethods
+ = 4
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000019-0000-0000-C000-000000000046}
+ = IExternalConnection
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000019-0000-0000-C000-000000000046}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000100-0000-0000-C000-000000000046}
+ = IEnumUnknown
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000100-0000-0000-C000-000000000046}\NumMethods
+ = 7
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000100-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010D-0000-0000-C000-000000000046}
+ = IViewObject
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010D-0000-0000-C000-000000000046}\NumMethods
+ = 9
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000110-0000-0000-C000-000000000046}
+ = IDataAdviseHolder
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000110-0000-0000-C000-000000000046}\NumMethods
+ = 7
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000111-0000-0000-C000-000000000046}
+ = IOleAdviseHolder
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000111-0000-0000-C000-000000000046}\NumMethods
+ = 9
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011D-0000-0000-C000-000000000046}
+ = IOleLink
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011D-0000-0000-C000-000000000046}\NumMethods
+ = 14
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011E-0000-0000-C000-000000000046}
+ = IOleCache
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011E-0000-0000-C000-000000000046}\NumMethods
+ = 8
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000124-0000-0000-C000-000000000046}
+ = IDebugStream
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000124-0000-0000-C000-000000000046}\NumMethods
+ = 19
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000126-0000-0000-C000-000000000046}
+ = IRunnableObject
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000126-0000-0000-C000-000000000046}\NumMethods
+ = 8
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000127-0000-0000-C000-000000000046}
+ = IViewObject2
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000127-0000-0000-C000-000000000046}\BaseInterface
+ = {0000010D-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000127-0000-0000-C000-000000000046}\NumMethods
+ = 10
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000128-0000-0000-C000-000000000046}
+ = IOleCache2
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000128-0000-0000-C000-000000000046}\BaseInterface
+ = {0000011E-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000128-0000-0000-C000-000000000046}\NumMethods
+ = 10
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000129-0000-0000-C000-000000000046}
+ = IOleCacheControl
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000129-0000-0000-C000-000000000046}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000125-0000-0000-C000-000000000046}
+ = IAdviseSink2
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000125-0000-0000-C000-000000000046}\BaseInterface
+ = {0000010F-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000125-0000-0000-C000-000000000046}\NumMethods
+ = 9
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000125-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010f-0000-0000-C000-000000000046}
+ = IAdviseSink
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010f-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010F-0000-0000-C000-000000000046}\NumMethods
+ = 8
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000e-0000-0000-C000-000000000046}
+ = IBindCtx
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000e-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000E-0000-0000-C000-000000000046}\NumMethods
+ = 13
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000001-0000-0000-C000-000000000046}
+ = IClassFactory
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000001-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000001-0000-0000-C000-000000000046}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010e-0000-0000-C000-000000000046}
+ = IDataObject
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010e-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010E-0000-0000-C000-000000000046}\NumMethods
+ = 12
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000121-0000-0000-C000-000000000046}
+ = IDropSource
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000121-0000-0000-C000-000000000046}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000122-0000-0000-C000-000000000046}
+ = IDropTarget
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000122-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000122-0000-0000-C000-000000000046}\NumMethods
+ = 7
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000101-0000-0000-C000-000000000046}
+ = IEnumString
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000101-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000100-0000-0000-C000-000000000046}\NumMethods
+ = 7
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000102-0000-0000-C000-000000000046}
+ = IEnumMoniker
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000102-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000102-0000-0000-C000-000000000046}\NumMethods
+ = 7
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000103-0000-0000-C000-000000000046}
+ = IEnumFORMATETC
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000103-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000103-0000-0000-C000-000000000046}\NumMethods
+ = 7
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000104-0000-0000-C000-000000000046}
+ = IEnumOLEVERB
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000104-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000104-0000-0000-C000-000000000046}\NumMethods
+ = 7
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000105-0000-0000-C000-000000000046}
+ = IEnumSTATDATA
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000105-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000105-0000-0000-C000-000000000046}\NumMethods
+ = 7
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000d-0000-0000-C000-000000000046}
+ = IEnumSTATSTG
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000d-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000D-0000-0000-C000-000000000046}\NumMethods
+ = 7
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000a-0000-0000-C000-000000000046}
+ = ILockBytes
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000a-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000a-0000-0000-C000-000000000046}\NumMethods
+ = 10
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000f-0000-0000-C000-000000000046}
+ = IMoniker
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000f-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000f-0000-0000-C000-000000000046}\BaseInterface
+ = {00000109-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000f-0000-0000-C000-000000000046}\NumMethods
+ = 23
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000118-0000-0000-C000-000000000046}
+ = IOleClientSite
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000118-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000118-0000-0000-C000-000000000046}\NumMethods
+ = 9
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011b-0000-0000-C000-000000000046}
+ = IOleContainer
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011b-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011b-0000-0000-C000-000000000046}\BaseInterface
+ = {0000011a-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011b-0000-0000-C000-000000000046}\NumMethods
+ = 6
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000117-0000-0000-C000-000000000046}
+ = IOleInPlaceActiveObject
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000117-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000117-0000-0000-C000-000000000046}\BaseInterface
+ = {00000114-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000117-0000-0000-C000-000000000046}\NumMethods
+ = 10
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011c-0000-0000-C000-000000000046}
+ = IOleItemContainer
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011c-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011c-0000-0000-C000-000000000046}\BaseInterface
+ = {0000011b-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011c-0000-0000-C000-000000000046}\NumMethods
+ = 9
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000116-0000-0000-C000-000000000046}
+ = IOleInPlaceFrame
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000116-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000116-0000-0000-C000-000000000046}\NumMethods
+ = 15
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000113-0000-0000-C000-000000000046}
+ = IOleInPlaceObject
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000113-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000113-0000-0000-C000-000000000046}\BaseInterface
+ = {00000114-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000113-0000-0000-C000-000000000046}\NumMethods
+ = 9
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000114-0000-0000-C000-000000000046}
+ = IOleWindow
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000114-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000114-0000-0000-C000-000000000046}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000119-0000-0000-C000-000000000046}
+ = IOleInPlaceSite
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000119-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000119-0000-0000-C000-000000000046}\BaseInterface
+ = {00000114-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000119-0000-0000-C000-000000000046}\NumMethods
+ = 15
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000115-0000-0000-C000-000000000046}
+ = IOleInPlaceUIWindow
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000115-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000115-0000-0000-C000-000000000046}\BaseInterface
+ = {00000114-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000115-0000-0000-C000-000000000046}\NumMethods
+ = 9
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000112-0000-0000-C000-000000000046}
+ = IOleObject
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000112-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000112-0000-0000-C000-000000000046}\NumMethods
+ = 24
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011a-0000-0000-C000-000000000046}
+ = IParseDisplayName
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011a-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011a-0000-0000-C000-000000000046}\NumMethods
+ = 4
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010c-0000-0000-C000-000000000046}
+ = IPersist
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010c-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010c-0000-0000-C000-000000000046}\NumMethods
+ = 4
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010b-0000-0000-C000-000000000046}
+ = IPersistFile
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010b-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010b-0000-0000-C000-000000000046}\BaseInterface
+ = {0000010c-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010b-0000-0000-C000-000000000046}\NumMethods
+ = 9
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010a-0000-0000-C000-000000000046}
+ = IPersistStorage
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010a-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010A-0000-0000-C000-000000000046}\BaseInterface
+ = {0000010C-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010A-0000-0000-C000-000000000046}\NumMethods
+ = 10
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000109-0000-0000-C000-000000000046}
+ = IPersistStream
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000109-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000109-0000-0000-C000-000000000046}\BaseInterface
+ = {0000010C-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000109-0000-0000-C000-000000000046}\NumMethods
+ = 8
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000010-0000-0000-C000-000000000046}
+ = IRunningObjectTable
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000010-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000010-0000-0000-C000-000000000046}\NumMethods
+ = 10
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000b-0000-0000-C000-000000000046}
+ = IStorage
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000b-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000b-0000-0000-C000-000000000046}\NumMethods
+ = 18
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000c-0000-0000-C000-000000000046}
+ = IStream
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000c-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000c-0000-0000-C000-000000000046}\NumMethods
+ = 14
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000012-0000-0000-C000-000000000046}
+ = IRootStorage
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000012-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {6f11fe5c-2fc5-101b-9e45-00000b65c7ef}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000012-0000-0000-C000-000000000046}\NumMethods
+ = 4
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020400-0000-0000-C000-000000000046}
+ = IDispatch
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020400-0000-0000-C000-000000000046}\NumMethods
+ = 7
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020400-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00020420-0000-0000-C000-000000000046}
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020404-0000-0000-C000-000000000046}
+ = IEnumVARIANT
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020404-0000-0000-C000-000000000046}\NumMethods
+ = 7
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020404-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00020421-0000-0000-C000-000000000046}
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020401-0000-0000-C000-000000000046}
+ = ITypeInfo
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020401-0000-0000-C000-000000000046}\NumMethods
+ = 22
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020401-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00020422-0000-0000-C000-000000000046}
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020402-0000-0000-C000-000000000046}
+ = ITypeLib
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020402-0000-0000-C000-000000000046}\NumMethods
+ = 13
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020403-0000-0000-C000-000000000046}
+ = ITypeComp
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020403-0000-0000-C000-000000000046}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020405-0000-0000-C000-000000000046}
+ = ICreateTypeInfo
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020405-0000-0000-C000-000000000046}\NumMethods
+ = 26
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020406-0000-0000-C000-000000000046}
+ = ICreateTypeLib
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020406-0000-0000-C000-000000000046}\NumMethods
+ = 13
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F56A34-593B-101A-B569-08002B2DBF7A}
+ = IRpcProxyBuffer
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F56A34-593B-101A-B569-08002B2DBF7A}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F569D0-593B-101A-B569-08002B2DBF7A}
+ = IPSFactoryBuffer
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F569D0-593B-101A-B569-08002B2DBF7A}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F56B60-593B-101A-B569-08002B2DBF7A}
+ = IRpcChannelBuffer
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F56B60-593B-101A-B569-08002B2DBF7A}\NumMethods
+ = 8
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F56AFC-593B-101A-B569-08002B2DBF7A}
+ = IRpcStubBuffer
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F56AFC-593B-101A-B569-08002B2DBF7A}\NumMethods
+ = 10
diff --git a/private/ole32/ih/nt2ole.reg b/private/ole32/ih/nt2ole.reg
new file mode 100644
index 000000000..c8b34692f
--- /dev/null
+++ b/private/ole32/ih/nt2ole.reg
@@ -0,0 +1,780 @@
+\Registry\MACHINE\SYSTEM\CurrentControlSet\Services\SCM
+ Type = REG_DWORD 0x00000020
+ Start = REG_DWORD 0x00000002
+ ErrorControl = REG_DWORD 0x00000001
+ ImagePath = REG_EXPAND_SZ %SystemRoot%\system32\scm.exe
+ ObjectName = LocalSystem
+\Registry\MACHINE\SOFTWARE\Classes\.bb1
+ = CLSID\{00000009-0000-0008-C000-000000000049}
+\Registry\MACHINE\SOFTWARE\Classes\.bb2
+ = CLSID\{00000009-0000-0008-C000-000000000048}
+\Registry\MACHINE\SOFTWARE\Classes\.bbs
+ = CLSID\{00000009-0000-0008-C000-000000000047}
+\Registry\MACHINE\SOFTWARE\Classes\CLSID
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000009-0000-0008-C000-000000000047}
+ = BasicSrv
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000009-0000-0008-C000-000000000047}\LocalServer32
+ = testsrv.exe
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000009-0000-0008-C000-000000000048}
+ = BasicBnd2
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000009-0000-0008-C000-000000000048}\LocalServer32
+ = olesrv.exe
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000009-0000-0008-C000-000000000049}
+ = BasicBnd
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000009-0000-0008-C000-000000000049}\InprocServer32
+ = oleimpl.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000300-0000-0000-C000-000000000046}
+ = StdOleLink
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000300-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000301-0000-0000-C000-000000000046}
+ = StdMemStm
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000301-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000302-0000-0000-C000-000000000046}
+ = StdMemBytes
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000302-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000303-0000-0000-C000-000000000046}
+ = FileMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000303-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000304-0000-0000-C000-000000000046}
+ = ItemMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000304-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000305-0000-0000-C000-000000000046}
+ = AntiMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000305-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000306-0000-0000-C000-000000000046}
+ = PointerMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000306-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000307-0000-0000-C000-000000000046}
+ = DdeFileMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000307-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000308-0000-0000-C000-000000000046}
+ = PackagerMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000308-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000309-0000-0000-C000-000000000046}
+ = CompositeMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000309-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000030A-0000-0000-C000-000000000046}
+ = DdeCompositeMoniker
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000030A-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000030B-0000-0000-C000-000000000046}
+ = DfMarshal
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000030B-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}
+ = Metafile
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}
+ = Device Independent Bitmap
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000400-0001-0008-C000-000000000046}
+ = PSClassObject
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000400-0001-0008-C000-000000000046}\InprocServer32
+ = iballs.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{009000d2-0000-0008-C000-000000000046}
+ = BasicSrv
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{009000d2-0000-0008-C000-000000000046}\LocalServer32
+ = strmsrv.exe
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000013a-0001-0008-C000-000000000046}
+ = BasicSrv
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000013a-0001-0008-C000-000000000046}\LocalServer32
+ = ballsrv.exe
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000013b-0001-0008-C000-000000000046}
+ = BasicSrv
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000013b-0001-0008-C000-000000000046}\LocalServer32
+ = cubesrv.exe
+
+\Registry\MACHINE\SOFTWARE\Classes\.ut1
+ = ProgID49
+\Registry\MACHINE\SOFTWARE\Classes\.ut2
+ = ProgID48
+\Registry\MACHINE\SOFTWARE\Classes\.ut3
+ = ProgID47
+\Registry\MACHINE\SOFTWARE\Classes\ProgID49
+ = test app 1
+\Registry\MACHINE\SOFTWARE\Classes\ProgID49\CLSID
+ = {99999999-0000-0008-C000-000000000049}
+\Registry\MACHINE\SOFTWARE\Classes\ProgID48
+ = test app 2
+\Registry\MACHINE\SOFTWARE\Classes\ProgID48\CLSID
+ = {99999999-0000-0008-C000-000000000048}
+\Registry\MACHINE\SOFTWARE\Classes\ProgID47
+ = test app 3
+\Registry\MACHINE\SOFTWARE\Classes\ProgID47\CLSID
+ = {99999999-0000-0008-C000-000000000047}
+
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{99999999-0000-0008-C000-000000000048}
+ = BasicBnd2
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{99999999-0000-0008-C000-000000000048}\LocalServer32
+ = olesrv.exe
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{99999999-0000-0008-C000-000000000049}
+ = BasicBnd
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{99999999-0000-0008-C000-000000000049}\InprocServer32
+ = oleimpl.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{99999999-0000-0008-C000-000000000047}
+ = TestEmbed
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{99999999-0000-0008-C000-000000000047}\InprocHandler32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{99999999-0000-0008-C000-000000000047}\InprocServer32
+ = ole32.dll
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{99999999-0000-0008-C000-000000000047}\LocalServer32
+ = testsrv.exe
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{99999999-0000-0008-C000-000000000047}\protocol
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{99999999-0000-0008-C000-000000000047}\protocol\StdFileEditing
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{99999999-0000-0008-C000-000000000047}\protocol\StdFileEditing\server
+ = testsrv.exe
+
+
+\Registry\MACHINE\SOFTWARE\Classes\StaticMetafile
+\Registry\MACHINE\SOFTWARE\Classes\StaticMetafile\CLSID
+ = {00000315-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\ProgID
+ = StaticMetafile
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\InprocServer
+ = ole32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\DataFormats
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\DataFormats\DefaultFile
+ = 3
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\DataFormats\GetSet
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\DataFormats\GetSet\0
+ = 3,1,32,3
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\MiscStatus
+ = 536
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\Conversion
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\Conversion\Readable
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000315-0000-0000-C000-000000000046}\Conversion\Readable\Main
+ = 3,MSDraw
+
+
+\Registry\MACHINE\SOFTWARE\Classes\StaticDib
+\Registry\MACHINE\SOFTWARE\Classes\StaticDib\CLSID
+ = {00000316-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\ProgID
+ = StaticDib
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\InprocServer
+ = ole32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\DataFormats
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\DataFormats\DefaultFile
+ = 8
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\DataFormats
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\DataFormats\GetSet
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\DataFormats\GetSet\0
+ = 8,1,1,3
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\MiscStatus
+ = 536
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\Conversion
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\Conversion\Readable
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000316-0000-0000-C000-000000000046}\Conversion\Readable\Main
+ = 8,PBrush
+
+
+\Registry\MACHINE\SOFTWARE\Classes\PBrush
+\Registry\MACHINE\SOFTWARE\Classes\PBrush\CLSID
+ = {0003000a-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0003000a-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0003000a-0000-0000-C000-000000000046}\ProgID
+ = PBrush
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0003000a-0000-0000-C000-000000000046}\Ole1Class
+ = PBrush
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0003000a-0000-0000-C000-000000000046}\MiscStatus
+ = 512
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0003000a-0000-0000-C000-000000000046}\Conversion
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0003000a-0000-0000-C000-000000000046}\Conversion\Readable
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0003000a-0000-0000-C000-000000000046}\Conversion\Readable\Main
+ = 8
+
+
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00030007-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00030007-0000-0000-C000-000000000046}\ProgID
+ = MSDraw
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00030007-0000-0000-C000-000000000046}\Ole1Class
+ = MSDraw
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00030007-0000-0000-C000-000000000046}\MiscStatus
+ = 512
+
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface
+
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000000-0000-0000-C000-000000000046}
+ = IUnknown
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000000-0000-0000-C000-000000000046}\BaseInterface
+ =
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000000-0000-0000-C000-000000000046}\NumMethods
+ = 3
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000002-0000-0000-C000-000000000046}
+ = IMalloc
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000002-0000-0000-C000-000000000046}\NumMethods
+ = 9
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000003-0000-0000-C000-000000000046}
+ = IMarshal
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000003-0000-0000-C000-000000000046}\NumMethods
+ = 9
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000004-0000-0000-C000-000000000046}
+ = IRpcChannel
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000004-0000-0000-C000-000000000046}\NumMethods
+ = 7
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000005-0000-0000-C000-000000000046}
+ = IRpcStub
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000005-0000-0000-C000-000000000046}\NumMethods
+ = 8
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000007-0000-0000-C000-000000000046}
+ = IRpcProxy
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000007-0000-0000-C000-000000000046}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000009-0000-0000-C000-000000000046}
+ = IPSFactory
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000009-0000-0000-C000-000000000046}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000016-0000-0000-C000-000000000046}
+ = IMessageFilter
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000016-0000-0000-C000-000000000046}\NumMethods
+ = 6
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000018-0000-0000-C000-000000000046}
+ = IStdMarshalInfo
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000018-0000-0000-C000-000000000046}\NumMethods
+ = 4
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000019-0000-0000-C000-000000000046}
+ = IExternalConnection
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000019-0000-0000-C000-000000000046}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000100-0000-0000-C000-000000000046}
+ = IEnumUnknown
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000100-0000-0000-C000-000000000046}\NumMethods
+ = 7
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000100-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000100-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000100-0000-0000-C000-000000000046}
+ = IEnumUnknown_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000100-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010D-0000-0000-C000-000000000046}
+ = IViewObject
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010D-0000-0000-C000-000000000046}\NumMethods
+ = 9
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000110-0000-0000-C000-000000000046}
+ = IDataAdviseHolder
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000110-0000-0000-C000-000000000046}\NumMethods
+ = 7
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000111-0000-0000-C000-000000000046}
+ = IOleAdviseHolder
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000111-0000-0000-C000-000000000046}\NumMethods
+ = 9
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011D-0000-0000-C000-000000000046}
+ = IOleLink
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011D-0000-0000-C000-000000000046}\NumMethods
+ = 14
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011E-0000-0000-C000-000000000046}
+ = IOleCache
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011E-0000-0000-C000-000000000046}\NumMethods
+ = 8
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000124-0000-0000-C000-000000000046}
+ = IDebugStream
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000124-0000-0000-C000-000000000046}\NumMethods
+ = 19
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000126-0000-0000-C000-000000000046}
+ = IRunnableObject
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000126-0000-0000-C000-000000000046}\NumMethods
+ = 8
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000127-0000-0000-C000-000000000046}
+ = IViewObject2
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000127-0000-0000-C000-000000000046}\BaseInterface
+ = {0000010D-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000127-0000-0000-C000-000000000046}\NumMethods
+ = 10
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000128-0000-0000-C000-000000000046}
+ = IOleCache2
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000128-0000-0000-C000-000000000046}\BaseInterface
+ = {0000011E-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000128-0000-0000-C000-000000000046}\NumMethods
+ = 10
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000129-0000-0000-C000-000000000046}
+ = IOleCacheControl
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000129-0000-0000-C000-000000000046}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000125-0000-0000-C000-000000000046}
+ = IAdviseSink2
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000125-0000-0000-C000-000000000046}\BaseInterface
+ = {0000010F-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000125-0000-0000-C000-000000000046}\NumMethods
+ = 9
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000125-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000125-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000125-0000-0000-C000-000000000046}
+ = IAdviseSink2_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000125-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010f-0000-0000-C000-000000000046}
+ = IAdviseSink
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010f-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {0000010f-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010F-0000-0000-C000-000000000046}\NumMethods
+ = 8
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000010f-0000-0000-C000-000000000046}
+ = IAdviseSink_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000010f-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000e-0000-0000-C000-000000000046}
+ = IBindCtx
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000e-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {0000000e-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000E-0000-0000-C000-000000000046}\NumMethods
+ = 13
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000000e-0000-0000-C000-000000000046}
+ = IBindCtx_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000000e-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000001-0000-0000-C000-000000000046}
+ = IClassFactory
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000001-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000001-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000001-0000-0000-C000-000000000046}\NumMethods
+ = 5
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000001-0000-0000-C000-000000000046}
+ = IClassFactory_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000001-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010e-0000-0000-C000-000000000046}
+ = IDataObject
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010e-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {0000010e-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010E-0000-0000-C000-000000000046}\NumMethods
+ = 12
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000010e-0000-0000-C000-000000000046}
+ = IDataObject_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000010e-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000121-0000-0000-C000-000000000046}
+ = IDropSource
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000121-0000-0000-C000-000000000046}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000122-0000-0000-C000-000000000046}
+ = IDropTarget
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000122-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000122-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000122-0000-0000-C000-000000000046}\NumMethods
+ = 7
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000122-0000-0000-C000-000000000046}
+ = IDropTarget_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000122-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000101-0000-0000-C000-000000000046}
+ = IEnumString
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000101-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000101-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000100-0000-0000-C000-000000000046}\NumMethods
+ = 7
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000101-0000-0000-C000-000000000046}
+ = IEnumString_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000101-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000102-0000-0000-C000-000000000046}
+ = IEnumMoniker
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000102-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000102-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000102-0000-0000-C000-000000000046}\NumMethods
+ = 7
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000102-0000-0000-C000-000000000046}
+ = IEnumMoniker_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000102-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000103-0000-0000-C000-000000000046}
+ = IEnumFORMATETC
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000103-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000103-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000103-0000-0000-C000-000000000046}\NumMethods
+ = 7
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000103-0000-0000-C000-000000000046}
+ = IEnumFORMATETC_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000103-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000104-0000-0000-C000-000000000046}
+ = IEnumOLEVERB
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000104-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000104-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000104-0000-0000-C000-000000000046}\NumMethods
+ = 7
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000104-0000-0000-C000-000000000046}
+ = IEnumOLEVERB_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000104-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000105-0000-0000-C000-000000000046}
+ = IEnumSTATDATA
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000105-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000105-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000105-0000-0000-C000-000000000046}\NumMethods
+ = 7
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000105-0000-0000-C000-000000000046}
+ = IEnumSTATDATA_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000105-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000d-0000-0000-C000-000000000046}
+ = IEnumSTATSTG
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000d-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {0000000d-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000D-0000-0000-C000-000000000046}\NumMethods
+ = 7
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000000d-0000-0000-C000-000000000046}
+ = IEnumSTATSTG_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000000d-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000a-0000-0000-C000-000000000046}
+ = ILockBytes
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000a-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {0000000a-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000a-0000-0000-C000-000000000046}\NumMethods
+ = 10
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000000a-0000-0000-C000-000000000046}
+ = ILockBytes_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000000a-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000f-0000-0000-C000-000000000046}
+ = IMoniker
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000f-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {0000000f-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000f-0000-0000-C000-000000000046}\BaseInterface
+ = {00000109-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000f-0000-0000-C000-000000000046}\NumMethods
+ = 23
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000000f-0000-0000-C000-000000000046}
+ = IMoniker_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000000f-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000118-0000-0000-C000-000000000046}
+ = IOleClientSite
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000118-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000118-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000118-0000-0000-C000-000000000046}\NumMethods
+ = 9
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000118-0000-0000-C000-000000000046}
+ = IOleClientSite_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000118-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011b-0000-0000-C000-000000000046}
+ = IOleContainer
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011b-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {0000011b-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011b-0000-0000-C000-000000000046}\BaseInterface
+ = {0000011a-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011b-0000-0000-C000-000000000046}\NumMethods
+ = 6
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000011b-0000-0000-C000-000000000046}
+ = IOleContainer_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000011b-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000117-0000-0000-C000-000000000046}
+ = IOleInPlaceActiveObject
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000117-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000117-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000117-0000-0000-C000-000000000046}\BaseInterface
+ = {00000114-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000117-0000-0000-C000-000000000046}\NumMethods
+ = 10
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000117-0000-0000-C000-000000000046}
+ = IOleInPlaceActiveObject_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000117-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011c-0000-0000-C000-000000000046}
+ = IOleItemContainer
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011c-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {0000011c-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011c-0000-0000-C000-000000000046}\BaseInterface
+ = {0000011b-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011c-0000-0000-C000-000000000046}\NumMethods
+ = 9
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000011c-0000-0000-C000-000000000046}
+ = IOleItemContainer_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000011c-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000116-0000-0000-C000-000000000046}
+ = IOleInPlaceFrame
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000116-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000116-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000116-0000-0000-C000-000000000046}\NumMethods
+ = 15
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000116-0000-0000-C000-000000000046}
+ = IOleInPlaceFrame_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000116-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000113-0000-0000-C000-000000000046}
+ = IOleInPlaceObject
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000113-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000113-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000113-0000-0000-C000-000000000046}\BaseInterface
+ = {00000114-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000113-0000-0000-C000-000000000046}\NumMethods
+ = 9
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000113-0000-0000-C000-000000000046}
+ = IOleInPlaceObject_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000113-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000114-0000-0000-C000-000000000046}
+ = IOleWindow
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000114-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000114-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000114-0000-0000-C000-000000000046}\NumMethods
+ = 5
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000114-0000-0000-C000-000000000046}
+ = IOleWindow_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000114-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000119-0000-0000-C000-000000000046}
+ = IOleInPlaceSite
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000119-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000119-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000119-0000-0000-C000-000000000046}\BaseInterface
+ = {00000114-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000119-0000-0000-C000-000000000046}\NumMethods
+ = 15
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000119-0000-0000-C000-000000000046}
+ = IOleInPlaceSite_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000119-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000115-0000-0000-C000-000000000046}
+ = IOleInPlaceUIWindow
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000115-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000115-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000115-0000-0000-C000-000000000046}\BaseInterface
+ = {00000114-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000115-0000-0000-C000-000000000046}\NumMethods
+ = 9
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000115-0000-0000-C000-000000000046}
+ = IOleInPlaceUIWindow_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000115-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000112-0000-0000-C000-000000000046}
+ = IOleObject
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000112-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000112-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000112-0000-0000-C000-000000000046}\NumMethods
+ = 24
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000112-0000-0000-C000-000000000046}
+ = IOleObject_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000112-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011a-0000-0000-C000-000000000046}
+ = IParseDisplayName
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011a-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {0000011a-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000011a-0000-0000-C000-000000000046}\NumMethods
+ = 4
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000011a-0000-0000-C000-000000000046}
+ = IParseDisplayName_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000011a-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010c-0000-0000-C000-000000000046}
+ = IPersist
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010c-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {0000010c-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010c-0000-0000-C000-000000000046}\NumMethods
+ = 4
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000010c-0000-0000-C000-000000000046}
+ = IPersist_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000010c-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010b-0000-0000-C000-000000000046}
+ = IPersistFile
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010b-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {0000010b-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010b-0000-0000-C000-000000000046}\BaseInterface
+ = {0000010c-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010b-0000-0000-C000-000000000046}\NumMethods
+ = 9
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000010b-0000-0000-C000-000000000046}
+ = IPersistFile_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000010b-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010a-0000-0000-C000-000000000046}
+ = IPersistStorage
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010a-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {0000010a-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010A-0000-0000-C000-000000000046}\BaseInterface
+ = {0000010C-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000010A-0000-0000-C000-000000000046}\NumMethods
+ = 10
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000010a-0000-0000-C000-000000000046}
+ = IPersistStorage_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000010a-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000109-0000-0000-C000-000000000046}
+ = IPersistStream
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000109-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000109-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000109-0000-0000-C000-000000000046}\BaseInterface
+ = {0000010C-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000109-0000-0000-C000-000000000046}\NumMethods
+ = 8
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000109-0000-0000-C000-000000000046}
+ = IPersistStream_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000109-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000010-0000-0000-C000-000000000046}
+ = IRunningObjectTable
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000010-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000010-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000010-0000-0000-C000-000000000046}\NumMethods
+ = 10
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000010-0000-0000-C000-000000000046}
+ = IRunningObjectTable_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000010-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000b-0000-0000-C000-000000000046}
+ = IStorage
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000b-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {0000000b-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000b-0000-0000-C000-000000000046}\NumMethods
+ = 18
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000000b-0000-0000-C000-000000000046}
+ = IStorage_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000000b-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000c-0000-0000-C000-000000000046}
+ = IStream
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000c-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {0000000c-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{0000000c-0000-0000-C000-000000000046}\NumMethods
+ = 14
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000000c-0000-0000-C000-000000000046}
+ = IStream_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{0000000c-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000012-0000-0000-C000-000000000046}
+ = IRootStorage
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000012-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00000012-0000-0000-C000-000000000046}
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00000012-0000-0000-C000-000000000046}\NumMethods
+ = 4
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000012-0000-0000-C000-000000000046}
+ = IRootStorage_PSFactory
+\Registry\MACHINE\SOFTWARE\Classes\CLSID\{00000012-0000-0000-C000-000000000046}\InprocServer32
+ = oleprx32.dll
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020400-0000-0000-C000-000000000046}
+ = IDispatch
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020400-0000-0000-C000-000000000046}\NumMethods
+ = 7
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020400-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00020420-0000-0000-C000-000000000046}
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020404-0000-0000-C000-000000000046}
+ = IEnumVARIANT
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020404-0000-0000-C000-000000000046}\NumMethods
+ = 7
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020404-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00020421-0000-0000-C000-000000000046}
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020401-0000-0000-C000-000000000046}
+ = ITypeInfo
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020401-0000-0000-C000-000000000046}\NumMethods
+ = 22
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020401-0000-0000-C000-000000000046}\ProxyStubClsid32
+ = {00020422-0000-0000-C000-000000000046}
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020402-0000-0000-C000-000000000046}
+ = ITypeLib
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020402-0000-0000-C000-000000000046}\NumMethods
+ = 13
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020403-0000-0000-C000-000000000046}
+ = ITypeComp
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020403-0000-0000-C000-000000000046}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020405-0000-0000-C000-000000000046}
+ = ICreateTypeInfo
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020405-0000-0000-C000-000000000046}\NumMethods
+ = 26
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020406-0000-0000-C000-000000000046}
+ = ICreateTypeLib
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{00020406-0000-0000-C000-000000000046}\NumMethods
+ = 13
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F56A34-593B-101A-B569-08002B2DBF7A}
+ = IRpcProxyBuffer
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F56A34-593B-101A-B569-08002B2DBF7A}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F569D0-593B-101A-B569-08002B2DBF7A}
+ = IPSFactoryBuffer
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F569D0-593B-101A-B569-08002B2DBF7A}\NumMethods
+ = 5
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F56B60-593B-101A-B569-08002B2DBF7A}
+ = IRpcChannelBuffer
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F56B60-593B-101A-B569-08002B2DBF7A}\NumMethods
+ = 8
+
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F56AFC-593B-101A-B569-08002B2DBF7A}
+ = IRpcStubBuffer
+\Registry\MACHINE\SOFTWARE\Classes\Interface\{D5F56AFC-593B-101A-B569-08002B2DBF7A}\NumMethods
+ = 10
diff --git a/private/ole32/ih/ole1cls.h b/private/ole32/ih/ole1cls.h
new file mode 100644
index 000000000..567dc1878
--- /dev/null
+++ b/private/ole32/ih/ole1cls.h
@@ -0,0 +1,148 @@
+/*****************************************************************************\
+* *
+* ole1cls.h - Master definition of GUIDs for OLE1 classes *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+/* This file is the master definition of all GUIDs for OLE1 classes.
+
+ All such GUIDs are of the form:
+
+ 0003xxxx-0000-0000-C000-000000000046
+
+ The last parameter to DEFINE_OLE1GUID is the old 1.0 class name,
+ i.e., its key in the registration database.
+
+ Do not remove or change GUIDs.
+
+ Do not add anything to this file except comments and DEFINE_OLE1GUID macros.
+*/
+
+#ifndef DEFINE_OLE1GUID
+#define DEFINE_OLE1GUID(a,b,c,d,e) DEFINE_OLEGUID (a,b,c,d)
+#endif
+
+#ifdef WIN32
+#define LSTR(x) L##x
+#else
+#define LSTR(x) x
+#endif
+
+
+DEFINE_OLE1GUID(CLSID_ExcelWorksheet, 0x00030000, 0, 0, LSTR("ExcelWorksheet"));
+DEFINE_OLE1GUID(CLSID_ExcelChart, 0x00030001, 0, 0, LSTR("ExcelChart"));
+DEFINE_OLE1GUID(CLSID_ExcelMacrosheet, 0x00030002, 0, 0, LSTR("ExcelMacrosheet"));
+DEFINE_OLE1GUID(CLSID_WordDocument, 0x00030003, 0, 0, LSTR("WordDocument"));
+DEFINE_OLE1GUID(CLSID_MSPowerPoint, 0x00030004, 0, 0, LSTR("MSPowerPoint"));
+DEFINE_OLE1GUID(CLSID_MSPowerPointSho, 0x00030005, 0, 0, LSTR("MSPowerPointSho"));
+DEFINE_OLE1GUID(CLSID_MSGraph, 0x00030006, 0, 0, LSTR("MSGraph"));
+DEFINE_OLE1GUID(CLSID_MSDraw, 0x00030007, 0, 0, LSTR("MSDraw"));
+DEFINE_OLE1GUID(CLSID_Note_It, 0x00030008, 0, 0, LSTR("Note-It"));
+DEFINE_OLE1GUID(CLSID_WordArt, 0x00030009, 0, 0, LSTR("WordArt"));
+DEFINE_OLE1GUID(CLSID_PBrush, 0x0003000a, 0, 0, LSTR("PBrush"));
+DEFINE_OLE1GUID(CLSID_Equation, 0x0003000b, 0, 0, LSTR("Equation"));
+DEFINE_OLE1GUID(CLSID_Package, 0x0003000c, 0, 0, LSTR("Package"));
+DEFINE_OLE1GUID(CLSID_SoundRec, 0x0003000d, 0, 0, LSTR("SoundRec"));
+DEFINE_OLE1GUID(CLSID_MPlayer, 0x0003000e, 0, 0, LSTR("MPlayer"));
+
+/* test apps */
+DEFINE_OLE1GUID(CLSID_ServerDemo, 0x0003000f, 0, 0, LSTR("ServerDemo"));
+DEFINE_OLE1GUID(CLSID_Srtest, 0x00030010, 0, 0, LSTR("Srtest"));
+DEFINE_OLE1GUID(CLSID_SrtInv, 0x00030011, 0, 0, LSTR("SrtInv"));
+DEFINE_OLE1GUID(CLSID_OleDemo, 0x00030012, 0, 0, LSTR("OleDemo"));
+
+/* External ISVs */
+// Coromandel / Dorai Swamy / 718-793-7963
+DEFINE_OLE1GUID(CLSID_CoromandelIntegra,0x00030013, 0, 0, LSTR("CoromandelIntegra"));
+DEFINE_OLE1GUID(CLSID_CoromandelObjServer,0x00030014, 0, 0, LSTR("CoromandelObjServer"));
+
+// 3-d Visions Corp / Peter Hirsch / 310-325-1339
+DEFINE_OLE1GUID(CLSID_StanfordGraphics, 0x00030015, 0, 0, LSTR("StanfordGraphics"));
+
+// Deltapoint / Nigel Hearne / 408-648-4000
+DEFINE_OLE1GUID(CLSID_DGraphCHART, 0x00030016, 0, 0, LSTR("DGraphCHART"));
+DEFINE_OLE1GUID(CLSID_DGraphDATA, 0x00030017, 0, 0, LSTR("DGraphDATA"));
+
+// Corel / Richard V. Woodend / 613-728-8200 x1153
+DEFINE_OLE1GUID(CLSID_PhotoPaint, 0x00030018, 0, 0, LSTR("PhotoPaint"));
+DEFINE_OLE1GUID(CLSID_CShow, 0x00030019, 0, 0, LSTR("CShow"));
+DEFINE_OLE1GUID(CLSID_CorelChart, 0x0003001a, 0, 0, LSTR("CorelChart"));
+DEFINE_OLE1GUID(CLSID_CDraw, 0x0003001b, 0, 0, LSTR("CDraw"));
+
+// Inset Systems / Mark Skiba / 203-740-2400
+DEFINE_OLE1GUID(CLSID_HJWIN1_0, 0x0003001c, 0, 0, LSTR("HJWIN1.0"));
+
+// Mark V Systems / Mark McGraw / 818-995-7671
+DEFINE_OLE1GUID(CLSID_ObjMakerOLE, 0x0003001d, 0, 0, LSTR("ObjMakerOLE"));
+
+// IdentiTech / Mike Gilger / 407-951-9503
+DEFINE_OLE1GUID(CLSID_FYI, 0x0003001e, 0, 0, LSTR("FYI"));
+DEFINE_OLE1GUID(CLSID_FYIView, 0x0003001f, 0, 0, LSTR("FYIView"));
+
+// Inventa Corporation / Balaji Varadarajan / 408-987-0220
+DEFINE_OLE1GUID(CLSID_Stickynote, 0x00030020, 0, 0, LSTR("Stickynote"));
+
+// ShapeWare Corp. / Lori Pearce / 206-467-6723
+DEFINE_OLE1GUID(CLSID_ShapewareVISIO10, 0x00030021, 0, 0, LSTR("ShapewareVISIO10"));
+DEFINE_OLE1GUID(CLSID_ImportServer, 0x00030022, 0, 0, LSTR("ImportServer"));
+
+
+// test app SrTest
+DEFINE_OLE1GUID(CLSID_SrvrTest, 0x00030023, 0, 0, LSTR("SrvrTest"));
+
+// Special clsid for when a 1.0 client pastes an embedded object
+// that is a link.
+// **This CLSID is obsolete. Do not reuse number.
+//DEFINE_OLE1GUID(CLSID_10EmbedObj, 0x00030024, 0, 0, LSTR("OLE2_Embedded_Link"));
+
+// test app ClTest. Doesn't really work as a server but is in reg db
+DEFINE_OLE1GUID(CLSID_ClTest, 0x00030025, 0, 0, LSTR("Cltest"));
+
+// Microsoft ClipArt Gallery Sherry Larsen-Holmes
+DEFINE_OLE1GUID(CLSID_MS_ClipArt_Gallery,0x00030026, 0, 0, LSTR("MS_ClipArt_Gallery"));
+
+// Microsoft Project Cory Reina
+DEFINE_OLE1GUID(CLSID_MSProject, 0x00030027, 0, 0, LSTR("MSProject"));
+
+// Microsoft Works Chart
+DEFINE_OLE1GUID(CLSID_MSWorksChart, 0x00030028, 0, 0, LSTR("MSWorksChart"));
+
+// Microsoft Works Spreadsheet
+DEFINE_OLE1GUID(CLSID_MSWorksSpreadsheet,0x00030029, 0, 0, LSTR("MSWorksSpreadsheet"));
+
+// AFX apps - Dean McCrory
+DEFINE_OLE1GUID(CLSID_MinSvr, 0x0003002A, 0, 0, LSTR("MinSvr"));
+DEFINE_OLE1GUID(CLSID_HierarchyList, 0x0003002B, 0, 0, LSTR("HierarchyList"));
+DEFINE_OLE1GUID(CLSID_BibRef, 0x0003002C, 0, 0, LSTR("BibRef"));
+DEFINE_OLE1GUID(CLSID_MinSvrMI, 0x0003002D, 0, 0, LSTR("MinSvrMI"));
+DEFINE_OLE1GUID(CLSID_TestServ, 0x0003002E, 0, 0, LSTR("TestServ"));
+
+// Ami Pro
+DEFINE_OLE1GUID(CLSID_AmiProDocument, 0x0003002F, 0, 0, LSTR("AmiProDocument"));
+
+// WordPerfect Presentations For Windows
+DEFINE_OLE1GUID(CLSID_WPGraphics, 0x00030030, 0, 0, LSTR("WPGraphics"));
+DEFINE_OLE1GUID(CLSID_WPCharts, 0x00030031, 0, 0, LSTR("WPCharts"));
+
+
+// MicroGrafx Charisma
+DEFINE_OLE1GUID(CLSID_Charisma, 0x00030032, 0, 0, LSTR("Charisma"));
+DEFINE_OLE1GUID(CLSID_Charisma_30, 0x00030033, 0, 0, LSTR("Charisma_30"));
+DEFINE_OLE1GUID(CLSID_CharPres_30, 0x00030034, 0, 0, LSTR("CharPres_30"));
+
+// MicroGrafx Draw
+DEFINE_OLE1GUID(CLSID_Draw, 0x00030035, 0, 0, LSTR("Draw"));
+
+// MicroGrafx Designer
+DEFINE_OLE1GUID(CLSID_Designer_40, 0x00030036, 0, 0, LSTR("Designer_40"));
+
+
+#undef DEFINE_OLE1GUID
+
+/* as we discover OLE 1 servers we will add them to the end of this list;
+ there is room for 64K of them!
+*/
diff --git a/private/ole32/ih/ole2com.h b/private/ole32/ih/ole2com.h
new file mode 100644
index 000000000..056fe43d0
--- /dev/null
+++ b/private/ole32/ih/ole2com.h
@@ -0,0 +1,1001 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ole2com.h
+//
+// Contents: Common definitions shared by com and ole232
+//
+// Classes:
+//
+// Functions:
+//
+// History: 4-26-94 kevinro Created
+// 06-16-94 AlexT Add FnAssert prototype
+// 07-26-94 AlexGo Added CStabilize and CSafeRefCount
+// 21-Dec-94 BruceMa Wrap mbstowcs and wcstombs
+// 23-Jan-95 t-ScottH added Dump method to CSafeRefCount
+// 08-Sep-95 murthys Added declarations for compapi worker
+// used by com, stg, scm etc
+//
+// Notes:
+// There are two versions of ole2int.h in the project. This is
+// unfortunate, but would be a major pain in the butt to fix.
+// What I have done is to extract the share parts of the two files,
+// and put them in this file. ole2int.h then includes this file.
+//
+// Someday, somebody should reconcile all of the differences between the
+// two ole2int.h files, and rename them. Don't have time for that now,
+// so I have gone for the path of least resistance.
+// KevinRo
+//----------------------------------------------------------------------------
+#ifndef _OLE2COM_H_
+#define _OLE2COM_H_
+
+#include <memapi.hxx>
+
+//
+// common compobj API worker functions used by com, stg, scm etc
+//
+// These definitions are shared between all of the components of OLE that
+// use the common directory, such as SCM and COMPOBJ
+//
+// format for string form of GUID is (leading identifier ????)
+// ????{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}
+
+#define GUIDSTR_MAX (1+ 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
+#define CLSIDSTR_MAX (GUIDSTR_MAX)
+#define IIDSTR_MAX (GUIDSTR_MAX)
+
+
+//
+// Internal values used between OLE32 and SCM
+//
+
+#define APT_THREADED 0
+#define FREE_THREADED 1
+#define SINGLE_THREADED 2
+#define BOTH_THREADED 3
+#define GOT_FROM_ROT 0x80000000
+
+
+//
+// Internal CLSCTX used for loading Proxy/Stub DLLs
+//
+#define CLSCTX_PS_DLL 0x80000000
+
+//
+// Internal CLSCTX used for flagging that WX86 remapping should not occur
+//
+#define CLSCTX_NO_REMAP 0x40000000
+
+//
+// The following flags are used to support loading INPROC items into 16-bit DLL's
+//
+#define CLSCTX_INPROC_HANDLERS (CLSCTX_INPROC_HANDLER16 | CLSCTX_INPROC_HANDLER | CLSCTX_INPROC_HANDLERX86)
+#define CLSCTX_INPROC_SERVERS (CLSCTX_INPROC_SERVER16 | CLSCTX_INPROC_SERVER | CLSCTX_INPROC_SERVERX86 | CLSCTX_PS_DLL)
+
+// "common" compapi worker functions
+
+INTERNAL_(int) wStringFromGUID2(REFGUID rguid, LPWSTR lpsz, int cbMax);
+INTERNAL wStringFromUUID(REFGUID rguid, LPWSTR lpsz);
+void FormatHexNumW( unsigned long ulValue, unsigned long chChars, WCHAR *pwcStr);
+void FormatHexNumA( unsigned long ulValue, unsigned long chChars, char *pchStr);
+
+#ifdef _CHICAGO_
+INTERNAL_(int) wStringFromGUID2A(REFGUID rguid, LPSTR lpsz, int cbMax);
+#define wStringFromGUID2T wStringFromGUID2A
+#else
+#define wStringFromGUID2T wStringFromGUID2
+#endif
+
+BOOL wThreadModelMatch(DWORD dwCallerThreadModel,DWORD dwDllThreadModel,DWORD dwContext);
+LONG wQueryStripRegValue(HKEY hkey,LPCTSTR pwszSubKey,LPTSTR pwszValue, PLONG pcbValue);
+LONG wGetDllInfo(HKEY hClsRegEntry,LPCTSTR pwszKey,LPTSTR pwszDllName,LONG *pclDllName,ULONG *pulDllThreadType);
+BOOL wCompareDllName(LPCTSTR pwszPath, LPCTSTR pwszDllName, DWORD dwDllNameLen);
+
+// compapi worker functions
+
+INTERNAL wIsInternalProxyStubIID(REFIID riid, LPCLSID lpclsid);
+INTERNAL wCoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew);
+INTERNAL wCLSIDFromOle1Class(LPCWSTR lpsz, LPCLSID lpclsid, BOOL fForceAssign=FALSE);
+INTERNAL wCLSIDFromString(LPWSTR lpsz, LPCLSID lpclsid);
+
+#define wCLSIDFromProgID wCLSIDFromOle1Class
+
+INTERNAL_(int) wOle1ClassFromCLSID2(REFCLSID rclsid, LPWSTR lpsz, int cbMax);
+INTERNAL wCoGetTreatAsClass(REFCLSID clsidOld, LPCLSID lpClsidNew);
+INTERNAL wRegQueryPSClsid(REFIID riid, LPCLSID lpclsid);
+INTERNAL wCoGetPSClsid(REFIID riid, LPCLSID lpclsid);
+INTERNAL wCoGetClassExt(LPCWSTR pwszExt, LPCLSID pclsid);
+INTERNAL wRegGetClassExt(LPCWSTR lpszExt, LPCLSID pclsid);
+INTERNAL wCoGetClassPattern(HANDLE hfile, CLSID *pclsid);
+INTERNAL wCoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwContext, REFIID riid, LPVOID FAR* ppv);
+INTERNAL_(HRESULT) wCoMarshalInterThreadInterfaceInStream(REFIID riid, LPUNKNOWN pUnk, LPSTREAM *ppStm);
+INTERNAL_(HRESULT) wCoGetInterfaceAndReleaseStream(LPSTREAM pstm, REFIID riid, LPVOID *ppv);
+INTERNAL_(BOOL) wGUIDFromString(LPCWSTR lpsz, LPGUID pguid);
+INTERNAL_(BOOL) wUUIDFromString(LPCWSTR lpsz, LPGUID pguid);
+INTERNAL wStringFromCLSID(REFCLSID rclsid, LPWSTR FAR* lplpsz);
+INTERNAL wStringFromIID(REFIID rclsid, LPWSTR FAR* lplpsz);
+INTERNAL wIIDFromString(LPWSTR lpsz, LPIID lpiid);
+INTERNAL_(BOOL) wCoIsOle1Class(REFCLSID rclsid);
+INTERNAL wkProgIDFromCLSID(REFCLSID rclsid, LPWSTR FAR* ppszProgID);
+INTERNAL wCoOpenClassKey(REFCLSID clsid, HKEY FAR* lphkeyClsid);
+INTERNAL_(LONG) wRegQueryClassValue(REFCLSID rclsid, LPCWSTR lpszSubKey,
+ LPWSTR lpszValue, int cbMax);
+
+
+//
+// There are two sets of possible keys. There are the 32 bit, as well as
+// the 16 bit
+//
+
+#ifdef _KEVINROS_CHICAGO_CHANGES_
+const TCHAR tszOle32Dll[] = TEXT("OLE32.DLL");
+
+#define OLE32_DLL tszOle32Dll
+#define OLE32_BYTE_LEN sizeof(OLE32_DLL)
+#define OLE32_CHAR_LEN (sizeof(OLE32_DLL) / sizeof(TCHAR) - 1)
+#endif
+
+const TCHAR tszCLSID[] = TEXT("CLSID");
+
+const TCHAR tszInprocServer[] = TEXT("InprocServer32");
+const TCHAR tszInprocHandler[] = TEXT("InprocHandler32");
+const TCHAR tszLocalServer[] = TEXT("LocalServer32");
+
+const WCHAR wszActivateAtBits[] = L"ActivateAtBits";
+const WCHAR wszActivateRemote[] = L"Remote";
+const WCHAR wszDebug[] = L"Debug";
+
+const TCHAR tszLocalServer16[] = TEXT("LocalServer");
+const TCHAR tszInprocServer16[] = TEXT("InprocServer");
+const TCHAR tszInprocHandler16[] = TEXT("InprocHandler");
+
+const TCHAR tszOle2Dll[] = TEXT("OLE2.DLL");
+
+#define OLE2_DLL tszOle2Dll
+#define OLE2_BYTE_LEN sizeof(OLE2_DLL)
+#define OLE2_CHAR_LEN (sizeof(OLE2_DLL) / sizeof(TCHAR) - 1)
+
+
+const TCHAR tszCLSIDBACK[] = TEXT("CLSID\\");
+#define CLSIDBACK tszCLSIDBACK
+#define CLSIDBACK_BYTE_LEN sizeof(CLSIDBACK)
+#define CLSIDBACK_CHAR_LEN (sizeof(CLSIDBACK) / sizeof(TCHAR) - 1)
+
+#define KEY_LEN 256 // max size of registry key
+#define VALUE_LEN 256 // max size of registry value
+
+#ifdef _CAIRO_
+
+#define _DCOM_ // enable definition of Cairo OLE COM extensions
+#include <oleext.h>
+
+#else
+
+// These API's are exposed for Cairo but not for Daytona, so we declare
+// them here for internal users
+
+WINOLEAPI OleInitializeEx(LPVOID pvReserved, DWORD);
+WINOLEAPI CoGetCallerTID( LPDWORD lpdwTID );
+WINOLEAPI CoGetPersistentInstance(
+ REFIID riid,
+ DWORD dwCtrl,
+ DWORD grfMode,
+ OLECHAR *pwszName,
+ struct IStorage *pstg,
+ REFCLSID rclsidOle1,
+ BOOL * pfOle1Loaded,
+ void **ppvUnk);
+#endif
+
+
+//
+// No longer in the Cairo DEF file. We want to remove this as soon as
+// oleutest can be changed to not use it.
+//
+WINOLEAPI CoNewPersistentInstance(
+ REFCLSID rclsid,
+ REFIID riid,
+ DWORD dwCtrl,
+ DWORD grfMode,
+ OLECHAR *pwszCreateFrom,
+ struct IStorage *pstgCreateFrom,
+ OLECHAR *pwszNewName,
+ void **ppunk);
+
+#if DBG==1
+STDAPI FnAssert(LPSTR lpstrExpr, LPSTR lpstrMsg, LPSTR lpstrFileName, UINT iLine);
+#endif
+
+#if defined(_M_I86SM) || defined(_M_I86MM)
+#define _NEARDATA
+#endif
+
+#ifdef WIN32
+#define HTASK DWORD // Use Proccess id / Thread id
+#endif
+
+
+#ifdef WIN32
+// we have to define these because they have been deleted from
+// win32s, where only the ...Ex versions exist anymore.
+// Now, that's backward compatibility!
+# define SetWindowOrg(h,x,y) SetWindowOrgEx((h),(x),(y),NULL)
+# define SetWindowExt(h,x,y) SetWindowExtEx((h),(x),(y),NULL)
+# define SetViewportOrg(h,x,y) SetViewportOrgEx((h),(x),(y),NULL)
+# define SetViewportExt(h,x,y) SetViewportExtEx((h),(x),(y),NULL)
+# define SetBitmapDimension(h,x,y) SetBitmapDimensionEx((h),(x),(y),NULL)
+#endif
+
+
+#ifdef WIN32
+
+# define _xstrcpy lstrcpyW
+# define _xstrcat lstrcatW
+# define _xstrlen lstrlenW
+# define _xstrchr wcschr
+# define _xstrcmp lstrcmpW
+# define _xstricmp lstrcmpiW
+# define _xstrtok wcstok
+# define _xisdigit(c) (IsCharAlphaNumericW(c) && !IsCharAlphaW(c))
+
+#else // !WIN32
+
+# define _xstrcpy _fstrcpy
+# define _xstrcat _fstrcat
+# define _xstrlen _fstrlen
+# define _xstrchr _fstrchr
+# define _xstrcmp _fstrcmp
+# define _xstricmp _fstricmp
+# define _xstrtok _fstrtok
+# define _xisdigit(c) isdigit(c)
+
+#endif // WIN32
+
+//+----------------------------------------------------------------------------
+//
+// Macro:
+// GETPPARENT
+//
+// Synopsis:
+// Given a pointer to something contained by a struct (or
+// class,) the type name of the containing struct (or class),
+// and the name of the member being pointed to, return a pointer
+// to the container.
+//
+// Arguments:
+// [pmemb] -- pointer to member of struct (or class.)
+// [struc] -- type name of containing struct (or class.)
+// [membname] - name of member within the struct (or class.)
+//
+// Returns:
+// pointer to containing struct (or class)
+//
+// Notes:
+// Assumes all pointers are FAR.
+//
+// History:
+// 11/10/93 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+#define GETPPARENT(pmemb, struc, membname) (\
+ (struc FAR *)(((char FAR *)(pmemb))-offsetof(struc, membname)))
+
+//STDSTATIC is intended to be used for static class methods
+//only!!
+#define STDSTATIC_(type) static type EXPORT
+#define STDSTATICIMP_(type) type EXPORT
+
+#ifdef WIN32
+# define WEP_FREE_DLL 0 // BUGBUG32
+# define WEP_SYSTEM_EXIT 1
+#endif
+
+
+#ifdef WIN32
+
+inline UINT GetDriveTypeFromNumber(int i)
+{
+ TCHAR szDevice[] = TEXT("A:\\");
+
+ // Pick off the drive letter from the input path.
+ *szDevice = i + 'A';
+
+#ifdef _UNICODE
+ return(GetDriveTypeW(szDevice));
+#else
+ return(GetDriveTypeA(szDevice));
+#endif
+}
+
+#endif
+
+#ifndef _MAC
+
+/* dll's instance and module handles */
+extern HMODULE g_hmodOLE2;
+extern HINSTANCE g_hinst;
+
+/* Variables for registered clipboard formats */
+extern CLIPFORMAT g_cfObjectLink;
+extern CLIPFORMAT g_cfOwnerLink;
+extern CLIPFORMAT g_cfNative;
+extern CLIPFORMAT g_cfLink;
+extern CLIPFORMAT g_cfBinary;
+extern CLIPFORMAT g_cfFileName;
+extern CLIPFORMAT g_cfFileNameW;
+extern CLIPFORMAT g_cfNetworkName;
+extern CLIPFORMAT g_cfDataObject;
+extern CLIPFORMAT g_cfEmbeddedObject;
+extern CLIPFORMAT g_cfEmbedSource;
+extern CLIPFORMAT g_cfLinkSource;
+extern CLIPFORMAT g_cfOleDraw;
+extern CLIPFORMAT g_cfLinkSrcDescriptor;
+extern CLIPFORMAT g_cfObjectDescriptor;
+extern CLIPFORMAT g_cfCustomLinkSource;
+extern CLIPFORMAT g_cfPBrush;
+extern CLIPFORMAT g_cfMSDraw;
+extern CLIPFORMAT g_cfOlePrivateData;
+extern CLIPFORMAT g_cfScreenPicture; // used for XL and Word hack
+ // see clipapi.cpp
+
+#endif // _MAC
+
+
+#include <utstream.h>
+
+/*
+ * Warning disables:
+ *
+ * We compile with warning level 4, with the following warnings
+ * disabled:
+ *
+ * 4355: 'this' used in base member initializer list
+ *
+ * We don't see the point of this message and we do this all
+ * the time.
+ *
+ * 4505: Unreferenced local function has been removed -- the given
+ * function is local and not referenced in the body of the module.
+ *
+ * Unfortunately, this is generated for every inline function
+ * seen in the header files that is not used in the module.
+ * Since we use a number of inlines, this is a nuisance
+ * warning. It would be nice if the compiler distinguished
+ * between inlines and regular functions.
+ *
+ * 4706: Assignment within conditional expression.
+ *
+ * We use this style of programming extensively, so this
+ * warning is disabled.
+ */
+#pragma warning(disable:4355)
+#pragma warning(disable:4068)
+
+/*
+ * MACROS for Mac/PC core code
+ *
+ * The following macros reduce the proliferation of #ifdefs. They
+ * allow tagging a fragment of code as Mac only, PC only, or with
+ * variants which differ on the PC and the Mac.
+ *
+ * Usage:
+ *
+ *
+ * h = GetHandle();
+ * Mac(DisposeHandle(h));
+ *
+ *
+ * h = GetHandle();
+ * MacWin(h2 = h, CopyHandle(h, h2));
+ *
+ */
+#ifdef _MAC
+#define Mac(x) x
+#define Win(x)
+#define MacWin(x,y) x
+#else
+#define Mac(x)
+#define Win(x) x
+#define MacWin(x,y) y
+#endif
+
+// Define WX86OLE if WX86 hooks are to be included into ole and scm
+#ifndef i386
+#ifndef WX86OLE
+#define WX86OLE
+#endif
+#endif
+
+#ifdef WX86OLE
+const TCHAR tszInprocServerX86[] = TEXT("InprocServerX86");
+const TCHAR tszInprocHandlerX86[] = TEXT("InprocHandlerX86");
+#endif
+
+//
+// The following include is for an interface between OLE and Wx86
+#ifdef WX86OLE
+#include <wx86grpa.hxx>
+extern CWx86 gcwx86;
+#endif
+
+//
+// The following includes an interface that is common between the
+// WOW thunk layer, and the 32-bit version of OLE.
+//
+
+#include <thunkapi.hxx> // WOW thunking interfaces
+
+//
+// A call to CoInitializeWOW will set the following variable. When set,
+// it points to a VTABLE of functions that we can call in the thunk
+// DLL. Only used when running in a VDM.
+//
+extern LPOLETHUNKWOW g_pOleThunkWOW;
+
+
+// debug versions of interlocked increment/decrement; not accurate
+// under multi-threading conditions, but better than the return value
+// of the Interlocked increment/decrement functions.
+inline DWORD InterlockedAddRef(DWORD *pRefs)
+{
+#if DBG==1
+ DWORD refs = *pRefs + 1;
+ InterlockedIncrement((LPLONG)pRefs);
+ return refs;
+#else
+ return InterlockedIncrement((LPLONG)pRefs);
+#endif
+}
+
+inline DWORD InterlockedRelease(DWORD *pRefs)
+{
+#if DBG==1
+ DWORD refs = *pRefs - 1;
+ return InterlockedDecrement((LPLONG)pRefs) == 0 ? 0 : refs;
+#else
+ return InterlockedDecrement((LPLONG)pRefs);
+#endif
+}
+
+
+// helper for getting stable pointers during destruction or other times;
+// NOTE: not thread safe; must provide higher level synchronization
+inline void SafeReleaseAndNULL(IUnknown **ppUnk)
+{
+ if (*ppUnk != NULL)
+ {
+ IUnknown *pUnkSave = *ppUnk;
+ *ppUnk = NULL;
+ pUnkSave->Release();
+ }
+}
+
+
+
+/***********************************************************************/
+/* FILE FORMAT RELATED INFO ****/
+
+// Coponent object stream information
+
+#define COMPOBJ_STREAM OLESTR("\1CompObj")
+#define BYTE_ORDER_INDICATOR 0xfffe // for MAC it could be different
+#define COMPOBJ_STREAM_VERSION 0x0001
+
+// OLE defines values for different OSs
+#define OS_WIN 0x0000
+#define OS_MAC 0x0001
+#define OS_NT 0x0002
+
+// HIGH WORD is OS indicator, LOW WORD is OS version number
+extern DWORD gdwOrgOSVersion;
+extern DWORD gdwOleVersion;
+
+// Ole streams information
+#define OLE_STREAM OLESTR("\1Ole")
+#define OLE_PRODUCT_VERSION 0x0200 /* (HIGH BYTE major version) */
+#define OLE_STREAM_VERSION 0x0001
+
+#define OLE10_NATIVE_STREAM OLESTR("\1Ole10Native")
+#define OLE10_ITEMNAME_STREAM OLESTR("\1Ole10ItemName")
+#define OLE_PRESENTATION_STREAM OLESTR("\2OlePres000")
+#define OLE_MAX_PRES_STREAMS 1000
+#define OLE_CONTENTS_STREAM OLESTR("CONTENTS")
+#define OLE_INVALID_STREAMNUM (-1)
+
+/************************************************************************/
+/**** Storage APIs internally used ****/
+/************************************************************************/
+
+STDAPI ReadClipformatStm(LPSTREAM lpstream, DWORD FAR* lpdwCf);
+STDAPI WriteClipformatStm(LPSTREAM lpstream, CLIPFORMAT cf);
+
+STDAPI WriteMonikerStm (LPSTREAM pstm, LPMONIKER pmk);
+STDAPI ReadMonikerStm (LPSTREAM pstm, LPMONIKER FAR* pmk);
+
+STDAPI_(LPSTREAM) CreateMemStm(DWORD cb, LPHANDLE phMem);
+STDAPI_(LPSTREAM) CloneMemStm(HANDLE hMem);
+STDAPI_(void) ReleaseMemStm (LPHANDLE hMem, BOOL fInternalOnly = FALSE);
+
+STDAPI GetClassFileEx( LPCWSTR lpszFileName,
+ CLSID FAR *pcid,
+ REFCLSID clsidOle1);
+
+/*************************************************************************/
+/*** Initialization code for individual modules ***/
+/*************************************************************************/
+
+INTERNAL_(void) DDEWEP (
+ BOOL fSystemExit
+);
+
+INTERNAL_(BOOL) DDELibMain (
+ HANDLE hInst,
+ WORD wDataSeg,
+ WORD cbHeapSize,
+ LPWSTR lpszCmdLine
+);
+
+BOOL InitializeRunningObjectTable(void);
+
+HRESULT GetObjectFromRotByPath(
+ WCHAR *pwszPath,
+ IUnknown **ppvUnk);
+
+void DestroyRunningObjectTable(void);
+
+
+/**************************************************************************
+ 'lindex' related macros
+***************************************************************************/
+
+#define DEF_LINDEX (-1)
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsValidLINDEX
+//
+// Synopsis: Tests for valid combination of aspect and lindex
+//
+// Arguments: [dwAspect] -- aspect (part of FORMATETC)
+// [lindex] -- lindex (part of FORMATETC)
+//
+// Returns: TRUE for valid lindex, else FALSE
+//
+// History: 20-Jun-94 AlexT Created
+//
+// Notes: Here is the spec for lindex values:
+//
+// dwAspect lindex values
+// -------- -------------
+// DVASPECT_CONTENT -1
+// DVASPECT_DOCPRINT anything
+// DVASPECT_ICON -1
+// DVASPECT_THUMBNAIL -1
+//
+// So, we test for lindex == -1 or aspect == DOCPRINT
+//
+//--------------------------------------------------------------------------
+
+inline BOOL IsValidLINDEX(DWORD dwAspect, LONG lindex)
+{
+ return((DEF_LINDEX == lindex) || (DVASPECT_DOCPRINT == dwAspect));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HasValidLINDEX
+//
+// Synopsis: Tests for valid combination of aspect and lindex
+//
+// Arguments: [pFormatEtc] -- pFormatEtc to test
+//
+// Returns: TRUE for valid lindex, else FALSE
+//
+// History: 20-Jun-94 AlexT Created
+//
+// Notes: See IsValidLINDEX, above
+//
+//--------------------------------------------------------------------------
+
+inline BOOL HasValidLINDEX(FORMATETC const *pFormatEtc)
+{
+ return(IsValidLINDEX(pFormatEtc->dwAspect, pFormatEtc->lindex));
+}
+
+#define INIT_FORETC(foretc) { \
+ (foretc).ptd = NULL; \
+ (foretc).lindex = DEF_LINDEX; \
+ (foretc).dwAspect = DVASPECT_CONTENT; \
+}
+
+// Only DDE layer will test for these values. And only for advises on cached
+// formats do we use these values
+
+#define ADVFDDE_ONSAVE 0x40000000
+#define ADVFDDE_ONCLOSE 0x80000000
+
+
+
+
+// Used in Ole Private Stream
+typedef enum tagOBJFLAGS
+{
+ OBJFLAGS_LINK=1L,
+ OBJFLAGS_DOCUMENT=2L, // this bit is owned by container and is
+ // propogated through saves
+ OBJFLAGS_CONVERT=4L,
+} OBJFLAGS;
+
+
+/*****************************************
+ Prototypes for dde\client\ddemnker.cpp
+******************************************/
+
+INTERNAL DdeBindToObject
+ (LPCOLESTR szFile,
+ REFCLSID clsid,
+ BOOL fPackageLink,
+ REFIID iid,
+ LPLPVOID ppv);
+
+INTERNAL DdeIsRunning
+ (CLSID clsid,
+ LPCOLESTR szFile,
+ LPBC pbc,
+ LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning);
+
+
+/**************************************
+ Prototypes for moniker\mkparse.cpp
+***************************************/
+
+INTERNAL Ole10_ParseMoniker
+ (LPMONIKER pmk,
+ LPOLESTR FAR* pszFile,
+ LPOLESTR FAR* pszItem);
+
+STDAPI CreateOle1FileMoniker(LPWSTR, REFCLSID, LPMONIKER FAR*);
+
+/****************************************************************************/
+/* Utility APIs, might get exposed later */
+/****************************************************************************/
+
+STDAPI OleGetData(LPDATAOBJECT lpDataObj, LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium, BOOL fGetOwnership);
+STDAPI OleSetData(LPDATAOBJECT lpDataObj, LPFORMATETC pformatetc,
+ STGMEDIUM FAR * pmedium, BOOL fRelease);
+STDAPI OleDuplicateMedium(LPSTGMEDIUM lpMediumSrc, LPSTGMEDIUM lpMediumDest);
+
+STDAPI_(BOOL) OleIsDcMeta (HDC hdc);
+
+STDAPI SzFixNet( LPBINDCTX pbc, LPOLESTR szUNCName, LPOLESTR FAR * lplpszReturn,
+ UINT FAR * pEndServer, BOOL fForceConnection = TRUE);
+
+FARINTERNAL ReadFmtUserTypeProgIdStg
+ (IStorage FAR * pstg,
+ CLIPFORMAT FAR* pcf,
+ LPOLESTR FAR* pszUserType,
+ LPOLESTR szProgID);
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsWOWProcess(), BOOL inline
+//
+// Synopsis: Tests whether or not we are running in a WOW process
+//
+// Returns: TRUE if in WOW process, FALSE otherwise
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Nov-95 murthys created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline BOOL IsWOWProcess()
+{
+ return (BOOL) ( NULL == g_pOleThunkWOW ? FALSE : TRUE );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsWOWThread(), BOOL inline
+//
+// Synopsis: Tests whether or not we are running in a 16-bit thread in a
+// WOW process
+//
+// Returns: TRUE if in 16-bit thread in a WOW process, FALSE otherwise
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Nov-95 murthys created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+BOOLEAN TLSIsWOWThread();
+
+inline BOOL IsWOWThread()
+{
+ return (BOOL) ( IsWOWProcess() ? TLSIsWOWThread(): FALSE );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsWOWThreadCallable(), BOOL inline
+//
+// Synopsis: Tests whether or not we can call into OLETHK32.
+//
+// Returns: TRUE if WOW thread is callable, FALSE if not
+//
+// Algorithm: Tests the g_pOleThunkWOW pointer to see if it is non-zero
+// and not set to -1. -1 means we are in wow, but OLETHK32
+// has already been unloaded. Also, checks to see if we're in
+// amidst a DLL_THREAD_DETACH. We will not allow calls to 16-bit
+// side in this case as it may have already been cleaned up.
+//
+// History: dd-mmm-yy Author Comment
+// 19-mar-95 KevinRo Created
+// 15-Nov-95 MurthyS Renamed from IsWowCallable
+// 29-Jan-95 MurthyS Added check for DLL_THREAD_DETACH
+//
+// Notes:
+// Assumes that IsWOWThread() was called and returned TRUE!
+//
+//--------------------------------------------------------------------------
+
+BOOLEAN TLSIsThreadDetaching();
+
+inline BOOL IsWOWThreadCallable()
+{
+ return (BOOL) (( NULL == g_pOleThunkWOW ? FALSE :
+ ( INVALID_HANDLE_VALUE == g_pOleThunkWOW ? FALSE:TRUE)) &&
+ !(TLSIsThreadDetaching()));
+}
+
+/****************************************************************************/
+/* Stabilization classes */
+/* These are used to stabilize objects during re-entrant calls */
+/****************************************************************************/
+
+#ifndef CO_E_RELEASED
+#define CO_E_RELEASED -2147467246L
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSafeRefCount
+//
+// Purpose: A concrete class for objects like the default handler to
+// inherit from. CSafeRefCount will keep track of reference
+// counts, nesting counts, and zombie states, allowing objects
+// to easily manage the liveness of their memory images.
+//
+// Interface:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Aug-94 alexgo author
+// 23-Jan-95 t-ScottH added Dump method (_DEBUG only)
+//
+// Notes: inherits CPrivAlloc
+//
+//--------------------------------------------------------------------------
+
+class CSafeRefCount : public CPrivAlloc
+{
+public:
+ ULONG SafeAddRef();
+ ULONG SafeRelease();
+ ULONG IncrementNestCount();
+ ULONG DecrementNestCount();
+ BOOL IsZombie();
+ #ifdef _DEBUG
+ HRESULT Dump(char **ppszDumpOA, ULONG ulFlag, int nIndentLevel);
+ #endif // _DEBUG
+
+ CSafeRefCount();
+ virtual ~CSafeRefCount(); // this virtual destructor MUST be here
+ // even though it does no work.
+ // it is needed to fire derived obj's destructors
+
+private:
+
+ ULONG m_cRefs;
+ ULONG m_cNest;
+ BOOL m_fInDelete;
+};
+
+//+-------------------------------------------------------------------------
+//
+// Class: CStabilize
+//
+// Purpose: An instance of this class should be allocated on the
+// stack of every object method that makes an outgoing call.
+// The contstructor takes a pointer to the object's base
+// CSafeRefCount class.
+//
+// Interface:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Aug-94 alexgo author
+//
+// Notes: The constructor will increment the nest count of the
+// object while the destructor will decrement it.
+//
+//--------------------------------------------------------------------------
+
+class CStabilize
+{
+public:
+ inline CStabilize( CSafeRefCount *pObjSafeRefCount );
+ inline ~CStabilize();
+
+private:
+ CSafeRefCount * m_pObjSafeRefCount;
+};
+
+inline CStabilize::CStabilize( CSafeRefCount *pObjSafeRefCount )
+{
+ pObjSafeRefCount->IncrementNestCount();
+ m_pObjSafeRefCount = pObjSafeRefCount;
+}
+
+inline CStabilize::~CStabilize()
+{
+ m_pObjSafeRefCount->DecrementNestCount();
+}
+
+typedef void * IFBuffer;
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetMarshalledInterfaceBuffer
+//
+// Synopsis: marshals the given interface into an allocated buffer. The
+// buffer is returned
+//
+// Effects:
+//
+// Arguments: [refiid] -- the iid of the interface to marshal
+// [punk] -- the IUnknown to marshal
+// [pIFBuf] -- where to return the buffer
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: calls CoMarshalInterface(MSHFLAGS_TABLESTRONG)
+//
+// History: dd-mmm-yy Author Comment
+// 03-Dec-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT GetMarshalledInterfaceBuffer( REFIID riid, IUnknown *punk, IFBuffer
+ *pIFBuf);
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReleaseMarshalledInterfaceBuffer
+//
+// Synopsis: releases the buffer allocated by GetMarshalledInterfaceBuffer
+//
+// Effects:
+//
+// Arguments: [IFBuf] -- the interface buffer to release
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: calls CoReleaseMarshalData to undo the TABLE_STRONG
+// marshalling
+//
+// History: dd-mmm-yy Author Comment
+// 03-Dec-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT ReleaseMarshalledInterfaceBuffer( IFBuffer IFBuf );
+
+
+#define E_UNSPEC E_FAIL
+
+#include <widewrap.h>
+
+#include <stkswtch.h>
+#include <shellapi.h>
+
+#ifdef WIN32 // REVIEW, just using this for tracking
+# define OLE_E_NOOLE1 MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x00FE)
+#endif // WIN32
+
+
+/***********************************************************************/
+/* Wrap mbstowcs and wcstombs which are unsafe to use */
+/* since they rely on crt.dll */
+/* */
+/* Note: cCh in both cases is the output buffer size, not a */
+/* string length. */
+/* */
+/***********************************************************************/
+
+#define mbstowcs(x, y, z) DONT_USE_mbstowcs___USE_MultiByteToWideChar_INSTEAD
+#define wcstombs(x, y, z) DONT_USE_wcstombs___USE_WideCharToMultiByte_INSTEAD
+
+
+
+//------------------------------------------------------------------
+//
+// Dynamically Loaded System APIs
+//
+// OLEs implementations of these system APIs dynamically load the
+// system DLLs. Since these are rarely used APIs we dynamically
+// load them to reduce the load time of OLE32.DLL
+//
+// The implementations can be found in com\util\dynload.cxx
+//
+//------------------------------------------------------------------
+
+// From MPR.DLL
+#undef WNetGetConnection
+#define WNetGetConnection(x,y,z) USE_OleWNetGetConnection_INSTEAD
+DWORD OleWNetGetConnection(LPCWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD lpnLength);
+
+#ifndef _CHICAGO_
+#undef WNetGetUniversalName
+#define WNetGetUniversalName(w,x,y,z) USE_OleWNetGetUniversalName_INSTEAD
+DWORD OleWNetGetUniversalName(LPCWSTR szLocalPath, DWORD dwInfoLevel, LPVOID lpBuffer, LPDWORD lpBufferSize);
+#endif
+
+// From SHELL32.DLL
+#undef ExtractIcon
+#define ExtractIcon(x,y,z) USE_OleExtractIcon_INSTEAD
+HICON OleExtractIcon(HINSTANCE hInst, LPCWSTR lpszFileName, UINT nIconIndex);
+
+#undef ExtractAssociatedIcon
+#define ExtractAssociatedIcon(x,y,z) USE_OleExtractAssociatedIcon_INSTEAD
+HICON OleExtractAssociatedIcon(HINSTANCE hInst, LPCWSTR lpszFileName, LPWORD
+ pIndex);
+
+// From GDI32P.DLL
+HBRUSH OleGdiConvertBrush(HBRUSH hbrush);
+HBRUSH OleGdiCreateLocalBrush(HBRUSH hbrushRemote);
+
+
+#undef SHGetFileInfo
+#define SHGetFileInfo(v,w,x,y,z) USE_OleSHGetFileInfo_INSTEAD
+DWORD OleSHGetFileInfo(LPCWSTR pszPath, DWORD dwFileAttributes,
+ SHFILEINFO FAR *psfi, UINT cbFileInfo, UINT uFlags);
+
+// HOOK OLE macros for wrapping interface pointers
+#include <hkole32.h>
+
+// ----------------------------------------------------------------------------
+// API/Method trace output
+// ----------------------------------------------------------------------------
+
+#include <trace.hxx>
+
+#endif // _OLE2COM_H_
diff --git a/private/ole32/ih/ole2sp.h b/private/ole32/ih/ole2sp.h
new file mode 100644
index 000000000..89d38f858
--- /dev/null
+++ b/private/ole32/ih/ole2sp.h
@@ -0,0 +1,411 @@
+/* ole2sp.h - semi-private info; only for test apps within the development group
+*/
+
+#if !defined( _OLE2SP_H_ )
+#define _OLE2SP_H_
+
+#include <shellapi.h>
+
+// For MAC, M_PROLOG and M_EPILOG are macros which assist us in setting up the A5
+// world for a DLL when a method in the DLL is called from outside the DLL.
+
+#ifdef _MAC
+
+#define _MAX_PATH 260
+
+#ifdef __cplusplus
+
+class CSetA5
+{
+public:
+ CSetA5 (ULONG savedA5){ A5save = SetA5(savedA5);}
+ ~CSetA5 (){ SetA5(A5save);}
+
+private:
+ ULONG A5save;
+};
+
+pascal long GetA5(void) = 0x2E8D;
+
+#define M_PROLOG(where) CSetA5 Dummy((where)->savedA5)
+#define SET_A5 ULONG savedA5
+#define GET_A5() savedA5 = GetA5()
+
+// These macros assist Mac in manually saving/setting/restoring A5 in routines that contain
+// goto's.
+
+#define A5_PROLOG(where) ULONG A5save = SetA5(where->savedA5)
+#define RESTORE_A5() SetA5(A5save)
+
+// Lets MAC name our segments without ifdef's.
+
+#define NAME_SEG(x)
+
+#endif // ccplus
+
+#else
+
+#define M_PROLOG(where)
+#define SET_A5
+#define GET_A5()
+#define A5_PROLOG(where)
+#define RESTORE_A5()
+#define NAME_SEG(x)
+
+//
+// By defining SEG(x) to code_seg(), we make #pragma SEG(x) a nop and
+// eliminate lots of unknown pragma warnings... 02/18/94
+//
+
+#define SEG(x) code_seg()
+
+#define IGetProcAddress(a,b) GetProcAddress((a),(b))
+
+#endif
+
+
+#define ReportResult(a,b,c,d) ResultFromScode(b)
+
+
+#ifdef WIN32
+#define MAP16(v16)
+#define MAP32(v32) v32
+#define MAP1632(v16,v32) v32
+#else
+#define MAP16(v16) v16
+#define MAP32(v32)
+#define MAP1632(v16,v32) v16
+#endif
+
+
+/****** Misc defintions ***************************************************/
+
+#ifdef __TURBOC__
+#define implement struct huge
+#else
+#define implement struct
+#endif
+#define ctor_dtor private
+#define implementations private
+#define shared_state private
+
+// helpers for internal methods and functions which follow the same convention
+// as the external ones
+
+#ifdef __cplusplus
+#define INTERNALAPI_(type) extern "C" type
+#else
+#define INTERNALAPI_(type) type
+#endif
+
+#define INTERNAL HRESULT
+#define INTERNAL_(type) type
+#define FARINTERNAL HRESULT FAR
+#define FARINTERNAL_(type) type FAR
+#define NEARINTERNAL HRESULT NEAR
+#define NEARINTERNAL_(type) type NEAR
+
+
+
+//BEGIN REVIEW: We may not need all the following ones
+
+#define OT_LINK 1L
+#define OT_EMBEDDED 2L
+#define OT_STATIC 3L
+
+
+//END REVIEW .....
+
+
+/****** Old Error Codes ************************************************/
+
+#define S_OOM E_OUTOFMEMORY
+#define S_BADARG E_INVALIDARG
+#define S_BLANK E_BLANK
+#define S_FORMAT E_FORMAT
+#define S_NOT_RUNNING E_NOTRUNNING
+#define E_UNSPEC E_FAIL
+
+
+
+/****** Macros for nested clases ******************************************/
+
+/* To overcome problems with nested classes on MAC
+ *
+ * NC(a,b) is used to define a member function of a nested class:
+ *
+ * STDMETHODIMP_(type) NC(ClassName,NestedClassName)::MemberFunction(...)
+ *
+ * DECLARE_NC(a,b) is used within a class declaration to let a nested class
+ * access it container class:
+ *
+ * class ClassName {
+ * ..............
+ *
+ * class NestedClassName {
+ * .............
+ * };
+ * DECLARE_NC(ClassName,NestedClassName)
+ * ..............
+ * };
+ */
+
+#ifdef _MAC
+
+#define NESTED_CLASS(a,b) struct a##_##b
+#define NC(a,b) a##__##b
+#define NC1(a,b) a##_##b
+#define DECLARE_NC(a,b) typedef a##::##b a##__##b; friend a##__##b;
+#define DECLARE_NC2(a,b) typedef a##::a##_##b a##__##b; friend a##__##b;
+
+#else
+
+#define NC(a,b) a##::##b
+#define DECLARE_NC(a,b) friend b;
+
+#endif
+
+
+/****** More Misc defintions **********************************************/
+
+
+// LPLPVOID should not be made a typedef. typedef won't compile; worse
+// within complicated macros the compiler generates unclear error messages
+//
+#define LPLPVOID void FAR * FAR *
+
+#define UNREFERENCED(a) ((void)(a))
+
+#ifndef BASED_CODE
+#ifdef WIN32
+#define BASED_CODE
+#else
+#define BASED_CODE __based(__segname("_CODE"))
+#endif
+#endif
+
+
+/****** Standard IUnknown Implementation **********************************/
+
+/*
+ * The following macro declares a nested class CUnknownImpl,
+ * creates an object of that class in the outer class, and
+ * declares CUnknownImpl to be a friend of the outer class. After
+ * writing about 20 class headers, it became evident that the
+ * implementation of CUnknownImpl was very similar in all cases,
+ * and this macro captures the similarity. The classname
+ * parameter is the name of the outer class WITHOUT the leading
+ * "C"; i.e., for CFileMoniker, classname is FileMoniker.
+ */
+
+#define noError return NOERROR
+
+#ifdef _MAC
+
+#define STDUNKDECL(cclassname,classname) NESTED_CLASS(cclassname, CUnknownImpl):IUnknown { public: \
+ NC1(cclassname,CUnknownImpl)( cclassname FAR * p##classname ) { m_p##classname = p##classname;} \
+ STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPLPVOID ppvObj); \
+ STDMETHOD_(ULONG,AddRef)(THIS); \
+ STDMETHOD_(ULONG,Release)(THIS); \
+ private: cclassname FAR* m_p##classname; }; \
+ DECLARE_NC2(cclassname, CUnknownImpl) \
+ NC(cclassname, CUnknownImpl) m_Unknown;
+
+#else // _MAC
+
+#define STDUNKDECL( ignore, classname ) implement CUnknownImpl:IUnknown { public: \
+ CUnknownImpl( C##classname FAR * p##classname ) { m_p##classname = p##classname;} \
+ STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPLPVOID ppvObj); \
+ STDMETHOD_(ULONG,AddRef)(THIS); \
+ STDMETHOD_(ULONG,Release)(THIS); \
+ private: C##classname FAR* m_p##classname; }; \
+ DECLARE_NC(C##classname, CUnknownImpl) \
+ CUnknownImpl m_Unknown;
+#endif
+
+/*
+ * The following macro implements all the methods of a nested
+ * CUnknownImpl class EXCEPT FOR QUERYINTERFACE. This macro was
+ * written after about 20 classes were written in which the
+ * implementations of CUnknownImpl were all the same.
+ */
+
+#ifdef WIN32
+
+#define STDUNKIMPL(classname) \
+STDMETHODIMP_(ULONG) NC(C##classname,CUnknownImpl)::AddRef( void ) \
+{ \
+ InterlockedIncrement((LONG *)&m_p##classname->m_refs); \
+ \
+ return m_p##classname->m_refs; \
+} \
+ \
+STDMETHODIMP_(ULONG) NC(C##classname,CUnknownImpl)::Release( void ) \
+{ \
+ ULONG culRefs = 0; \
+ \
+ culRefs = InterlockedDecrement((LONG *)&m_p##classname->m_refs); \
+ \
+ if (culRefs == 0) \
+ { \
+ delete m_p##classname; \
+ } \
+ \
+ return culRefs; \
+}
+
+#else
+
+#define STDUNKIMPL(classname) \
+STDMETHODIMP_(ULONG) NC(C##classname,CUnknownImpl)::AddRef( void ){ \
+ return ++m_p##classname->m_refs; } \
+STDMETHODIMP_(ULONG) NC(C##classname,CUnknownImpl)::Release( void ){ \
+ if (--m_p##classname->m_refs == 0) { delete m_p##classname; return 0; } \
+ return m_p##classname->m_refs;}
+
+#endif // WIN32
+
+
+/*
+ * The following macro implements class::CUnknownImpl::QueryInterface IN
+ * THE SPECIAL CASE IN WHICH THE OUTER CLASS PRESENTS ONLY ONE INTERFACE
+ * OTHER THAN IUNKNOWN AND IDEBUG. This is not universally the case,
+ * but it is common enough that this macro will save time and space.
+ */
+
+#ifdef _DEBUG
+#define STDDEB_QI(classname) \
+ if (IsEqualGUID(iidInterface, IID_IDebug)) \
+ {*ppv = (void FAR *)&(m_p##classname->m_Debug); return 0;} else
+#else
+#define STDDEB_QI(classname)
+#endif
+
+#ifdef WIN32
+
+#define STDUNK_QI_IMPL(classname, interfacename) \
+STDMETHODIMP NC(C##classname,CUnknownImpl)::QueryInterface \
+ (REFIID iidInterface, void FAR * FAR * ppv) \
+{ \
+ HRESULT hres = S_OK; \
+ \
+ if (IsEqualIID(iidInterface,IID_IUnknown)) \
+ { \
+ *ppv = (void FAR *)&m_p##classname->m_Unknown; \
+ AddRef(); \
+ } \
+ else if (IsEqualIID(iidInterface,IID_I##interfacename)) \
+ { \
+ *ppv = (void FAR *) &(m_p##classname->m_##classname); \
+ m_p##classname->m_pUnkOuter->AddRef(); \
+ } \
+ else STDDEB_QI(classname) \
+ { \
+ *ppv = NULL; \
+ hres = ResultFromScode(E_NOINTERFACE); \
+ } \
+ \
+ return hres; \
+}
+
+#else
+
+STDMETHODIMP NC(C##classname,CUnknownImpl)::QueryInterface \
+ (REFIID iidInterface, void FAR * FAR * ppv) { \
+ if (IsEqualGUID(iidInterface,IID_IUnknown)) {\
+ *ppv = (void FAR *)&m_p##classname->m_Unknown;\
+ AddRef(); noError;\
+ } else if (IsEqualGUID(iidInterface, IID_I##interfacename)) { \
+ *ppv = (void FAR *) &(m_p##classname->m_##classname); \
+ m_p##classname->m_pUnkOuter->AddRef(); return NOERROR; \
+ } else \
+ STDDEB_QI(classname) \
+ {*ppv = NULL; return ResultFromScode(E_NOINTERFACE);} \
+}
+#endif
+
+
+/*
+ * The following macro implements the IUnknown methods inherited
+ * by the implementation of another interface. The implementation
+ * is simply to delegate all calls to m_pUnkOuter. Parameters:
+ * ocname is the outer class name, icname is the implementation
+ * class name.
+ *
+ */
+
+#define STDUNKIMPL_FORDERIVED(ocname, icname) \
+ STDMETHODIMP NC(C##ocname,C##icname)::QueryInterface \
+(REFIID iidInterface, LPLPVOID ppvObj) { \
+ return m_p##ocname->m_pUnkOuter->QueryInterface(iidInterface, ppvObj);} \
+ STDMETHODIMP_(ULONG) NC(C##ocname,C##icname)::AddRef(void) { \
+ return m_p##ocname->m_pUnkOuter->AddRef(); } \
+ STDMETHODIMP_(ULONG) NC(C##ocname,C##icname)::Release(void) { \
+ return m_p##ocname->m_pUnkOuter->Release(); }
+
+
+/****** Debug defintions **************************************************/
+
+#include <debug.h>
+
+
+/****** Other API defintions **********************************************/
+
+// low level reg.dat access (in compobj.dll)
+STDAPI CoGetInProcDll(REFCLSID rclsid, BOOL fServer, LPOLESTR lpszDll, int cbMax);
+STDAPI CoGetLocalExe(REFCLSID rclsid, LPOLESTR lpszExe, int cbMax);
+STDAPI CoGetPSClsid(REFIID iid, LPCLSID lpclsid);
+
+
+// simpler alternatives to public apis
+// WINOLEAPI_(int) StringFromGUID2(REFGUID rguid, LPOLESTR lpsz, int cbMax);
+#define StringFromCLSID2(rclsid, lpsz, cbMax) \
+ StringFromGUID2(rclsid, lpsz, cbMax)
+
+#define StringFromIID2(riid, lpsz, cbMax) \
+ StringFromGUID2(riid, lpsz, cbMax)
+
+STDAPI_(int) Ole1ClassFromCLSID2(REFCLSID rclsid, LPOLESTR lpsz, int cbMax);
+STDAPI_(BOOL) GUIDFromString(LPCOLESTR lpsz, LPGUID pguid);
+STDAPI CLSIDFromOle1Class(LPCOLESTR lpsz, LPCLSID lpclsid, BOOL fForceAssign=FALSE);
+STDAPI_(BOOL) CoIsHashedOle1Class(REFCLSID rclsid);
+STDAPI CoOpenClassKey(REFCLSID clsid, HKEY FAR* lphkeyClsid);
+
+
+// were public; now not
+STDAPI SetDocumentBitStg(LPSTORAGE pStg, BOOL fDocument);
+STDAPI GetDocumentBitStg(LPSTORAGE pStg);
+
+
+INTERNAL CreateStandardMalloc(DWORD memctx, IMalloc FAR* FAR* ppMalloc);
+
+
+/*
+ * Some docfiles stuff
+ */
+
+#define STGM_DFRALL (STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE)
+#define STGM_DFALL (STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE)
+#define STGM_SALL (STGM_READWRITE | STGM_SHARE_EXCLUSIVE)
+
+
+/*
+ * Some moniker stuff
+ */
+//REVIEW32: Should this get exported publicly??
+
+STDAPI Concatenate(LPMONIKER pmkFirst, LPMONIKER pmkRest,
+ LPMONIKER FAR * ppmkComposite );
+
+/*
+ * Drag and Drop Interface Property Name
+ */
+#define OLE_DROP_TARGET_PROP L"OleDropTargetInterface"
+#define OLE_DROP_TARGET_PROPA "OleDropTargetInterface"
+
+/*
+ * Private Clipboard Window IDataObject property name
+ */
+#define CLIPBOARD_DATA_OBJECT_PROP L"ClipboardDataObjectInterface"
+
+#endif // _OLE2SP_H_
diff --git a/private/ole32/ih/ole2ver.h b/private/ole32/ih/ole2ver.h
new file mode 100644
index 000000000..6f4feff4d
--- /dev/null
+++ b/private/ole32/ih/ole2ver.h
@@ -0,0 +1,15 @@
+/*****************************************************************************\
+* *
+* ole2ver.h - OLE 2 Version Number Info *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+#ifndef _OLE2VER_H_
+#define _OLE2VER_H_
+
+#define rmm 23
+#define rup 639
+
+#endif
diff --git a/private/ole32/ih/olecoll.h b/private/ole32/ih/olecoll.h
new file mode 100644
index 000000000..dbae67081
--- /dev/null
+++ b/private/ole32/ih/olecoll.h
@@ -0,0 +1,27 @@
+// Microsoft OLE library.
+// Copyright (C) 1992 Microsoft Corporation,
+// All rights reserved.
+
+// olecoll.h - global defines for collections and element definitions
+
+#ifndef __OLECOLL_H__
+#define __OLECOLL_H__
+
+
+// ---------------------------------------------------------------------------
+// general defines for collections
+
+typedef void FAR* POSITION;
+
+#define BEFORE_START_POSITION ((POSITION)(ULONG)-1L)
+#define _AFX_FP_OFF(thing) (*((UINT FAR*)&(thing)))
+#define _AFX_FP_SEG(lp) (*((UINT FAR*)&(lp)+1))
+
+#ifdef _DEBUG
+#define ASSERT_VALID(p) p->AssertValid()
+#else
+#define ASSERT_VALID(p)
+#endif
+
+
+#endif //!__OLECOLL_H__
diff --git a/private/ole32/ih/olepfn.hxx b/private/ole32/ih/olepfn.hxx
new file mode 100644
index 000000000..5b6ae14c2
--- /dev/null
+++ b/private/ole32/ih/olepfn.hxx
@@ -0,0 +1,39 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: olepfn.hxx
+//
+// Contents: Extern declarations for some variables needed by
+// CoQueryReleaseObject
+//
+// Classes:
+//
+// Functions:
+//
+// History: 8-15-94 kevinro Created
+//
+// This file contains a couple of extern declarations for variables required
+// by a file in com\class. This is sort of hacky, but the idea is that
+// each of these array entreis is going to be initialized to the address of a
+// classes QueryInterface method. Rather than trying to determine the
+// correct set of header files that are common across all of the files we
+// need on of these variables for, I have put them all here.
+//
+//----------------------------------------------------------------------------
+
+#ifndef __olepfn_hxx__
+#define __olepfn_hxx__
+#define QI_TABLE_CFileMoniker 0
+#define QI_TABLE_CExposedDocFile 1
+#define QI_TABLE_CCompositeMoniker 2
+#define QI_TABLE_CItemMoniker 3
+#define QI_TABLE_END 4
+
+extern "C" DWORD adwQueryInterfaceTable[QI_TABLE_END];
+
+STDAPI CoQueryReleaseObject(IUnknown *punk);
+#endif // __olepfn_hxx__
+
+
diff --git a/private/ole32/ih/olerem.h b/private/ole32/ih/olerem.h
new file mode 100644
index 000000000..4be14cf74
--- /dev/null
+++ b/private/ole32/ih/olerem.h
@@ -0,0 +1,165 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: olerem.h
+//
+// Synopsis: this file contain the base definitions for types and APIs
+// exposed by the ORPC layer to upper layers.
+//
+//+-------------------------------------------------------------------------
+#if !defined( _OLEREM_H_ )
+#define _OLEREM_H_
+
+// default transport for same-machine communication
+#ifdef _CHICAGO_
+ #define LOCAL_PROTSEQ L"mswmsg"
+#else
+ #define LOCAL_PROTSEQ L"ncalrpc"
+#endif
+
+
+// -----------------------------------------------------------------------
+// Interface for Handlers to acquire internal interfaces on the proxy mgr.
+//
+// NOTE: implemented as part of the std identity object
+//
+// -----------------------------------------------------------------------
+interface IInternalUnknown : public IUnknown
+{
+ STDMETHOD(QueryInternalInterface)(REFIID riid, void **ppv) = 0;
+};
+
+// -----------------------------------------------------------------------
+// Internal Interface used by handlers.
+//
+// NOTE: connect happens during unmarshal
+// NOTE: implemented as part of the std identity object
+//
+// -----------------------------------------------------------------------
+interface IProxyManager : public IUnknown
+{
+ STDMETHOD(CreateServer)(REFCLSID rclsid, DWORD clsctx, void *pv) = 0;
+ STDMETHOD_(BOOL, IsConnected)(void) = 0;
+ STDMETHOD(LockConnection)(BOOL fLock, BOOL fLastUnlockReleases) = 0;
+ STDMETHOD_(void, Disconnect)(void) = 0;
+ STDMETHOD(CreateServerWithHandler)(REFCLSID rclsid, DWORD clsctx, void *pv,
+ REFCLSID rclsidHandler, IID iidSrv, void **ppv,
+ IID iidClnt, void *pClientSiteInterface) = 0;
+};
+
+
+STDAPI GetInProcFreeMarshaler(IMarshal **ppIM);
+
+
+// -----------------------------------------------------------------------
+// DCOM Only Stuff
+// -----------------------------------------------------------------------
+#ifdef DCOM
+#include <obase.h> // ORPC base definitions
+
+typedef const IPID &REFIPID; // reference to Interface Pointer IDentifier
+typedef const OID &REFOID; // reference to Object IDentifier
+typedef const OXID &REFOXID; // reference to Object Exporter IDentifier
+typedef const MID &REFMID; // reference to Machine IDentifier
+
+typedef GUID MOXID; // OXID + MID
+typedef const MOXID &REFMOXID; // reference to OXID + MID
+typedef GUID MOID; // OID + MID
+typedef const MOID &REFMOID; // reference to OID + MID
+
+
+STDAPI CreateIdentityHandler(IUnknown *pUnkOuter, DWORD flags,
+ REFIID riid, void **ppv);
+
+#endif
+
+// -----------------------------------------------------------------------
+// non-DCOM Stuff
+// -----------------------------------------------------------------------
+#ifndef DCOM
+
+#define FreeThreading FALSE
+
+INTERNAL CreateStdIdentity(IUnknown *pUnkOuter, IUnknown *pUnkControl,
+ IMarshal *pMarshal, REFIID riid, void **ppv);
+
+#ifndef OID_DEFINED
+#define OID_DEFINED
+typedef GUID OID;
+#endif // OID_DEFINED
+
+typedef const GUID& REFOID;
+#define OID_NULL GUID_NULL
+
+INTERNAL SkipMarshalExtension(IStream *pStm);
+
+// IRemoteHdlr : supported by RH piece of remoting system; not public
+
+interface IRemoteHdlr : public IUnknown
+{
+ // BUGBUG: may add GetServer to allow channel to get punk to hold
+ // during calls.
+ STDMETHOD_(struct IRpcChannelBuffer *, GetChannel)(BOOL fAddRef) = 0;
+
+ // used during calls to ensure alive (only does anything on client side)
+ STDMETHOD_(ULONG, LockClient)(void) = 0;
+ STDMETHOD_(ULONG, UnLockClient)(void) = 0;
+
+ // used during destruction of the identity object to clear the RH ptr.
+ STDMETHOD_(void, ClearIdentity)(void) = 0;
+
+ // returns TRUE if iid is supported; like QueryInterface except no
+ // interface pointer returned; also works on both client and server sides.
+ STDMETHOD_(BOOL, DoesSupportIID)(REFIID riid) = 0;
+
+ // add/subtract a reference or connection
+ STDMETHOD(AddConnection)(DWORD extconn, DWORD reserved) = 0;
+ STDMETHOD(ReleaseConnection)(DWORD extconn, DWORD reserved, BOOL fLastReleaseCloses) = 0;
+
+ // isconnected, disconnect
+ STDMETHOD_(BOOL, IsConnected)(void) = 0;
+ STDMETHOD_(void, Disconnect)(void) = 0;
+ STDMETHOD(LockConnection)(BOOL fLock, BOOL fLastUnlockCloses) = 0;
+
+ // Used by channel
+ STDMETHOD_(struct IRpcStubBuffer *, LookupStub)( REFIID, IUnknown **, HRESULT *phr ) = 0;
+ STDMETHOD_(void, FinishCall)( struct IRpcStubBuffer *, IUnknown * pUnkServer) = 0;
+ STDMETHOD_(void, GetObjectID)( OID * ) = 0;
+};
+
+// NOTE: connect happens during unmarshal
+// NOTE: creation is currently by direct invocation: "new CRemoteHdlr(...)"
+
+// Identity Object / interface
+
+interface IStdIdentity : public IUnknown
+{
+ STDMETHOD_(void, GetObjectID)(OID *pOid) = 0;
+ STDMETHOD_(IUnknown *, GetServer)(BOOL fAddRef) = 0;
+ STDMETHOD_(void, RevokeObjectID)() = 0;
+ STDMETHOD_(IMarshal *, GetStdRemMarshal)() = 0;
+ STDMETHOD(AddConnection)(DWORD extconn, DWORD reserved) = 0;
+ STDMETHOD(ReleaseConnection)(DWORD extconn, DWORD reserved, BOOL fLastReleaseCloses) = 0;
+ STDMETHOD_(ULONG,ReleaseKeepAlive)(IUnknown *pUnkToRelease, DWORD reserved) = 0;
+};
+
+INTERNAL LookupIDFromUnk(IUnknown *pUnk, BOOL fCreate, IStdIdentity **ppStdId);
+INTERNAL LookupIDFromID(REFOID oid, BOOL fAddRef, IStdIdentity **ppStdId);
+
+#define PSTDMARSHAL ((IMarshal *)1)
+
+STDAPI CreateIdentityHandler(IUnknown *pUnkOuter, IMarshal *pMarshal,
+ REFIID riid, void **ppv);
+
+#endif // not DCOM
+
+
+#ifdef _CHICAGO_
+#include <..\com\idl\chicago\iface.h>
+#else
+#include <iface.h>
+#endif
+
+#endif // _OLEREM_H
diff --git a/private/ole32/ih/olesem.hxx b/private/ole32/ih/olesem.hxx
new file mode 100644
index 000000000..a19f8ade0
--- /dev/null
+++ b/private/ole32/ih/olesem.hxx
@@ -0,0 +1,305 @@
+///+---------------------------------------------------------------------------
+//
+// File: olesem.hxx
+//
+// Contents: Semaphore classes for use in OLE code
+//
+// Classes: COleStaticMutexSem - Mutex semaphore class for statically
+// allocated objects
+// COleDebugMutexSem - Mutex semaphore class for statically
+// allocated objects that are not destructed
+// on DLL unload (and thus are leaks..used
+// for trace packages and such).
+//
+// History: 14-Dec-95 Jeffe Initial entry, derived from
+// sem32.hxx by AlexT.
+//
+// Notes: This module defines a set of classes to wrap WIN32
+// Critical Sections.
+//
+// Note the distinction of allocation class: the reason for this
+// is to avoid static constructors and destructors.
+//
+// The classes in this module *must* be used for mutex semaphores
+// that are statically allocated. Use the classes in sem32.hxx
+// for dynamically allocated (from heap or on the stack) objects.
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OLESEM_HXX__
+#define __OLESEM_HXX__
+
+extern "C"
+{
+#include <windows.h>
+};
+
+
+
+//
+// List of initialized static mutexes (which must be destroyed
+// during DLL exit). We know that PROCESS_ATTACH and PROCESS_DETACH
+// are thread-safe, so we don't protect this list with a critical section.
+//
+
+class COleStaticMutexSem;
+
+extern COleStaticMutexSem * g_pInitializedStaticMutexList;
+
+
+//
+// Critical section used to protect the creation of other semaphores
+//
+
+extern CRITICAL_SECTION g_OleMutexCreationSem;
+
+
+
+#if DBG
+
+//
+// DLL states used to ensure we don't use the wrong type of
+// semaphore at the wrong time
+//
+
+typedef enum _DLL_STATE_ {
+ DLL_STATE_STATIC_CONSTRUCTING = 0,
+ DLL_STATE_NORMAL,
+ DLL_STATE_STATIC_DESTRUCTING,
+
+ DLL_STATE_COUNT
+
+} DLL_STATE, * PDLL_STATE;
+
+//
+// Flag used to indicate if we're past executing the C++ constructors
+// during DLL initialization
+//
+
+extern DLL_STATE g_fDllState;
+
+#endif
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: COleStaticMutexSem (mxs)
+//
+// Purpose: This class defines a mutual exclusion semaphore for use in
+// objects that are statically allocated (extern or static storage
+// class).
+//
+// Interface: FastRequest - acquire semaphore an already-initialized
+// semaphore
+// Request - acquire semaphore
+// Release - release semaphore
+// ReleaseFn - release semaphore (non inline version)
+//
+// History: 14-Dec-95 JeffE Initial entry.
+//
+// Notes: This class must NOT be used in dynamically allocated objects!
+//
+// This class uses the fact that static objects are initialized
+// by C++ to all zeroes.
+//
+//----------------------------------------------------------------------------
+
+
+class COleStaticMutexSem {
+public:
+
+#if DBG
+
+ COleStaticMutexSem();
+
+#endif
+
+ // This pointer *must* be the first member in this class
+
+ class COleStaticMutexSem * pNextMutex;
+ BOOLEAN _fInitialized;
+ BOOLEAN _fAutoDestruct;
+
+ void Init();
+ void Destroy();
+ inline void FastRequest();
+ void Request();
+ inline void Release();
+#ifdef _CHICAGO_
+ // This is present for rpccall.asm which cannot use the inline version
+ void ReleaseFn();
+#endif
+
+ // The following definition *should* be private...but C-10 insists on supplying
+ // an empty constructor if we use it. Since it doesn't really matter, we just
+ // don't use it in retail builds.
+
+#if DBG
+private:
+#endif
+
+ CRITICAL_SECTION _cs;
+
+};
+
+#if DBG==1
+
+//+---------------------------------------------------------------------------
+//
+// Class: COleDebugMutexSem (mxs)
+//
+// Purpose: This class defines a mutual exclusion semaphore for use in
+// objects that are statically allocated (extern or static storage
+// class) but are not destructed when the DLL unloads.
+//
+// Interface: FastRequest - acquire semaphore an already-initialized
+// semaphore
+// Request - acquire semaphore
+// Release - release semaphore
+//
+// History: 14-Dec-95 JeffE Initial entry.
+//
+// Notes: This class must only be used in staticly allocated objects!
+//
+// This class may only be used in CHECKED builds...since it doesn't
+// clean up after itself on DLL unload.
+//
+//----------------------------------------------------------------------------
+
+
+class COleDebugMutexSem : public COleStaticMutexSem {
+
+public:
+
+ COleDebugMutexSem();
+
+};
+
+#endif // DBG==1
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: COleStaticLock (lck)
+//
+// Purpose: Lock using a static (or debug) Mutex Semaphore
+//
+// History: 02-Oct-91 BartoszM Created.
+//
+// Notes: Simple lock object to be created on the stack.
+// The constructor acquires the semaphor, the destructor
+// (called when lock is going out of scope) releases it.
+//
+//----------------------------------------------------------------------------
+
+class COleStaticLock
+{
+
+public:
+ COleStaticLock ( COleStaticMutexSem& mxs );
+ ~COleStaticLock ();
+
+private:
+ COleStaticMutexSem& _mxs;
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: COleStaticMutexSem::FastRequest
+//
+// Synopsis: Acquire the semaphore without checking to see if it's
+// initialized. If another thread already has it,
+// wait until it is released.
+//
+// History: 14-Dec-1995 Jeffe
+//
+// Notes: You may only use this method on code paths where you're
+// *certain* the semaphore has already been initialized (either
+// by invoking Init, or by calling the Request method).
+//
+//----------------------------------------------------------------------------
+
+inline void COleStaticMutexSem::FastRequest()
+{
+ Win4Assert (_fInitialized && "You must use Request here, not FastRequest");
+ EnterCriticalSection (&_cs);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: COleStaticMutexSem::Release
+//
+// Synopsis: Release the semaphore.
+//
+// History: 14-Dec-1995 Jeffe
+//
+//----------------------------------------------------------------------------
+
+inline void COleStaticMutexSem::Release()
+{
+ LeaveCriticalSection (&_cs);
+}
+
+
+#if DBG
+
+//+---------------------------------------------------------------------------
+//
+// Member: COleStaticMutexSem::COleStaticMutexSem
+//
+// Synopsis: Debug constructor: ensure we weren't allocated dynamically.
+//
+// History: 14-Dec-1995 Jeffe
+//
+//----------------------------------------------------------------------------
+
+inline COleStaticMutexSem::COleStaticMutexSem()
+{
+ Win4Assert (g_fDllState == DLL_STATE_STATIC_CONSTRUCTING);
+}
+
+
+#endif
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: COleStaticLock::COleStaticLock
+//
+// Synopsis: Acquire semaphore
+//
+// History: 02-Oct-91 BartoszM Created.
+//
+//----------------------------------------------------------------------------
+
+inline COleStaticLock::COleStaticLock ( COleStaticMutexSem& mxs )
+: _mxs ( mxs )
+{
+ _mxs.Request();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COleStaticLock::~COleStaticLock
+//
+// Synopsis: Release semaphore
+//
+// History: 02-Oct-91 BartoszM Created.
+//
+//----------------------------------------------------------------------------
+
+inline COleStaticLock::~COleStaticLock ()
+{
+ _mxs.Release();
+}
+
+
+#endif // _OLESEM_HXX
+
+
+
diff --git a/private/ole32/ih/oletemp.h b/private/ole32/ih/oletemp.h
new file mode 100644
index 000000000..85730ba8b
--- /dev/null
+++ b/private/ole32/ih/oletemp.h
@@ -0,0 +1,6 @@
+// for OleCreateEmbeddingHelper flags; roles in low word; options in high word
+#define EMBDHLP_INPROC_HANDLER 0x0000L
+#define EMBDHLP_INPROC_SERVER 0x0001L
+#define EMBDHLP_CREATENOW 0x00000000L
+#define EMBDHLP_DELAYCREATE 0x00010000L
+
diff --git a/private/ole32/ih/osift.hxx b/private/ole32/ih/osift.hxx
new file mode 100644
index 000000000..6371e2880
--- /dev/null
+++ b/private/ole32/ih/osift.hxx
@@ -0,0 +1,29 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: osift.hxx
+//
+// Contents: Definition of server side sift object
+//
+// Functions: DbgDllSetSiftObject - sets up global sift pointer
+//
+// History: 6-01-94 t-chripi Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OSIFT_HXX__
+
+#define __OSIFT_HXX__
+
+#include <sift.hxx>
+
+extern ISift *g_psftSiftObject;
+
+#define SIMULATE_FAILURE( dwRes ) \
+ ((NULL != g_psftSiftObject) && \
+ (g_psftSiftObject->SimFail( ( dwRes ) ))) \
+
+#endif // __OSIFT_HXX__
+
diff --git a/private/ole32/ih/perfmnce.hxx b/private/ole32/ih/perfmnce.hxx
new file mode 100644
index 000000000..7e189531b
--- /dev/null
+++ b/private/ole32/ih/perfmnce.hxx
@@ -0,0 +1,119 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: perfmnce.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 3-06-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef _PERF_BUILD_
+#ifndef _PERFORMANCE_DEFINED_
+#define _PERFORMANCE_DEFINED_
+
+
+typedef struct perfdata
+{
+ WORD wPos;
+ char szName[32];
+ LARGE_INTEGER liStart;
+ LARGE_INTEGER liEnd;
+} PerfData;
+
+typedef struct perflist
+{
+ UINT cElements;
+ PerfData rgPerfData[32];
+} PerfRg, *PPerfRg;
+
+
+extern PerfRg perfrg;
+typedef enum
+{
+ DebugTerminal = 1,
+ Consol = 2,
+ OleStream,
+ SzStr,
+} PrintDestination;
+
+
+#undef INTERFACE
+#define INTERFACE IPerformance
+DECLARE_INTERFACE_(IPerformance, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPerformance methods ***
+ STDMETHOD (Init) (THIS_ ) PURE;
+ STDMETHOD (Print) (THIS_ DWORD PrntDest) PURE;
+ STDMETHOD (Reset) (THIS_ ) PURE;
+};
+typedef IPerformance FAR* LPPerformance, *PPerformance;
+
+
+
+#define _Perf_LoadLibraryOle 0
+#define _Perf_OleInitialize 1
+#define _Perf_CoInitialize 2
+#define _Perf_ChannelProcessInit 3
+#define _Perf_ChannelThreadInit 4
+#define _Perf_CreateFileMap 5
+#define _Perf_CreateFileMapConvert 6
+#define _Perf_CheckAndStartScm 7
+#define _Perf_EndScm 8
+#define _Perf_ISLClassCacheList 9
+#define _Perf_ISLCreateAllocator 10
+#define _Perf_ISLInProcList 11
+#define _Perf_ISLLocSrvList 12
+#define _Perf_ISLScmRot 13
+#define _Perf_InitClassCache 14
+#define _Perf_InitRot 15
+#define _Perf_InitSharedLists 16
+#define _Perf_MDFDllMain 17
+#define _Perf_ServiceListen 18
+#define _Perf_ShrdTbl 19
+#define _Perf_StartScm 20
+#define _Perf_StartScmX1 21
+#define _Perf_StartScmX2 22
+#define _Perf_StartScmX3 23
+#define _Perf_ThreadInit 24
+#define _Perf_CoUnitialzie 25
+#define _Perf_DllMain 26
+#define _Perf_RpcService 27
+#define _Perf_RpcListen 28
+#define _Perf_RpcReqProtseq 29
+#define _Perf_ChannelControl 30
+#define _Perf_27 31
+
+#define StartPerfCounter(x) \
+ QueryPerformanceCounter(&perfrg.rgPerfData[_Perf_##x].liStart);
+#define EndPerfCounter(x) \
+ QueryPerformanceCounter(&perfrg.rgPerfData[_Perf_##x].liEnd);
+
+STDAPI CoGetPerformance(PPerformance *ppPerformance);
+
+#endif // _PERFORMANCE_DEFINED_
+#else // !_PERF_BUILD_
+
+#define StartPerfCounter(x)
+#define EndPerfCounter(x)
+#define CoGetPerformance(x )
+
+#endif // !_PERF_BUILD_
+
+
+
+
+
+
diff --git a/private/ole32/ih/plex.h b/private/ole32/ih/plex.h
new file mode 100644
index 000000000..ce460cad4
--- /dev/null
+++ b/private/ole32/ih/plex.h
@@ -0,0 +1,28 @@
+// This is a part of the Microsoft Foundation Classes C++ library.
+// Copyright (C) 1992 Microsoft Corporation
+// All rights reserved.
+//
+// This source code is only intended as a supplement to the
+// Microsoft Foundation Classes Reference and Microsoft
+// QuickHelp documentation provided with the library.
+// See these sources for detailed information regarding the
+// Microsoft Foundation Classes product.
+
+#ifndef __PLEX_H__
+#define __PLEX_H__
+
+struct FAR CPlex // warning variable length structure
+{
+ CPlex FAR* pNext;
+ UINT nMax;
+ UINT nCur;
+ /* BYTE data[maxNum*elementSize]; */
+
+ INTERNAL_(void FAR*) data() { return this+1; }
+
+ static INTERNAL_(CPlex FAR*) Create(CPlex FAR* FAR& head, UINT nMax, UINT cbElement);
+
+ INTERNAL_(void) FreeDataChain(); // free this one and links
+};
+
+#endif //__PLEX_H__
diff --git a/private/ole32/ih/privguid.h b/private/ole32/ih/privguid.h
new file mode 100644
index 000000000..86938b14a
--- /dev/null
+++ b/private/ole32/ih/privguid.h
@@ -0,0 +1,239 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: privguid.h
+//
+// Contents: This file is the master definition of all OLE2 product
+// GUIDs (public and private). All GUIDs used by the ole2
+// product are of the form:
+//
+// xxxxxxxx-xxxx-xxxY-C000-000000000046
+//
+// This range is broken down as follows:
+//
+// 000000xx-0000-0000-C000-000000000046 compobj IIDs
+// 000001xx-0000-0000-C000-000000000046 ole2 IIDs
+// 000002xx-0000-0000-C000-000000000046 16bit ole2 smoke test
+// 000003xx-0000-0000-C000-000000000046 ole2 CLSIDs
+// 000004xx-0000-0000-C000-000000000046 ole2 sample apps (see DouglasH)
+//
+// Other interesting ranges are as follows:
+//
+// 0003xxxx-0000-0000-C000-000000000046 ole1 CLSIDs (ole1cls.h)
+// 0004xxxx-0000-0000-C000-000000000046 hashed ole1 CLSIDs
+//
+//
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 24-Oct-94 BruceMa Added this file header
+// 24-Oct-94 BruceMa Added IMallocSpy
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+////////////////////////////////////////////////////////////////////////////
+// Range 0x000 - 0x0ff : compobj IIDs -
+// IID_IUnknown, 0x00000000L
+// IID_IClassFactory, 0x00000001L
+// IID_IMalloc, 0x00000002L
+// IID_IMarshal, 0x00000003L
+
+// IID_ILockBytes, 0x0000000aL
+// IID_IStorage, 0x0000000bL
+// IID_IStream, 0x0000000cL
+// IID_IEnumSTATSTG, 0x0000000dL
+
+// IID_IBindCtx, 0x0000000eL
+// IID_IMoniker, 0x0000000fL
+// IID_IRunningObjectTable, 0x00000010L
+// IID_IInternalMoniker, 0x00000011L
+
+// IID_IRootStorage, 0x00000012L
+// IID_IDfReserved1, 0x00000013L
+// IID_IDfReserved2, 0x00000014L
+// IID_IDfReserved3, 0x00000015L
+
+// IID_IMessageFilter, 0x00000016L
+
+// CLSID_StdMarshal, 0x00000017L
+
+// IID_IStdMarshalInfo, 0x00000018L
+
+// IID_IExternalConnection, 0x00000019L
+
+// IID_IWeakRef, 0x0000001aL
+
+/* interface for subpieces of standard remoting */
+DEFINE_OLEGUID(IID_IStdIdentity, 0x0000001bL, 0, 0);
+DEFINE_OLEGUID(IID_IRemoteHdlr, 0x0000001cL, 0, 0);
+
+// IID_IMallocSpyf, 0x0000001dL, 0, 0);
+
+// IID_ITrackingMoniker, 0x0000001eL
+
+// IID_IMultiQI, 0x00000020L
+
+DEFINE_OLEGUID(IID_IInternalUnknown, 0x00000021L, 0, 0);
+
+// IID_ISurrogate, 0x00000022L, 0, 0);
+
+/* NOTE: LSB values 0x23 through 0xff are unused */
+
+////////////////////////////////////////////////////////////////////////////
+// Range 0x100 - 0x1ff : upper layer IIDs -
+// IID_IEnumUnknown, 0x00000100L
+// IID_IEnumString, 0x00000101L
+// IID_IEnumMoniker, 0x00000102L
+// IID_IEnumFORMATETC, 0x00000103L
+// IID_IEnumOLEVERB, 0x00000104L
+// IID_IEnumSTATDATA, 0x00000105L
+
+// IID_IEnumGeneric, 0x00000106L
+// IID_IEnumHolder, 0x00000107L
+// IID_IEnumCallback, 0x00000108L
+
+// IID_IPersistStream, 0x00000109L
+// IID_IPersistStorage, 0x0000010aL
+// IID_IPersistFile, 0x0000010bL
+// IID_IPersist, 0x0000010cL
+
+// IID_IViewObject, 0x0000010dL
+// IID_IDataObject, 0x0000010eL
+// IID_IAdviseSink, 0x0000010fL
+// IID_IDataAdviseHolder, 0x00000110L
+// IID_IOleAdviseHolder, 0x00000111L
+
+// IID_IOleObject, 0x00000112L
+// IID_IOleInPlaceObject, 0x00000113L
+// IID_IOleWindow, 0x00000114L
+// IID_IOleInPlaceUIWindow, 0x00000115L
+// IID_IOleInPlaceFrame, 0x00000116L
+// IID_IOleInPlaceActiveObject, 0x00000117L
+
+// IID_IOleClientSite, 0x00000118L
+// IID_IOleInPlaceSite, 0x00000119L
+
+// IID_IParseDisplayName, 0x0000011aL
+// IID_IOleContainer, 0x0000011bL
+// IID_IOleItemContainer, 0x0000011cL
+
+// IID_IOleLink, 0x0000011dL
+// IID_IOleCache, 0x0000011eL
+// IID_IOleManager, 0x0000011fL
+// IID_IOlePresObj, 0x00000120L
+
+// IID_IDropSource, 0x00000121L
+// IID_IDropTarget, 0x00000122L
+
+// IID_IDebug, 0x00000123L
+// IID_IDebugStream, 0x00000124L
+
+// IID_IAdviseSink2, 0x00000125L
+
+// IID_IRunnableObject, 0x00000126L
+
+// IID_IViewObject2, 0x00000127L
+// IID_IOleCache2, 0x00000128L
+// IID_IOleCacheControl, 0x00000129L
+// IID_IContinue, 0x0000012AL
+
+// IID_IDocConnect, 0x00000130L
+// IID_IRemUnknown, 0x00000131L
+// IID_IObjServer, 0x00000132L
+// IID_IOSCM, 0x00000133L
+// IID_IRundown, 0x00000134L
+// IID_InterfaceFromWindowProp, 0x00000135L
+// IID_IDSCM 0x00000136L
+// IID_ISCMSCM 0x00000137L
+
+/* NOTE: LSB values 0x2a through 0xff are unused */
+
+// IID_IPropertyStorage, 0x00000138L
+// IID_IEnumSTATPROPSTG, 0x00000139L
+// IID_IPropertySetStorage, 0x0000013AL
+// IID_IEnumSTATPROPSETSTG, 0x0000013BL
+
+// IID_IRemoteUnknown2, 0x0000013CL
+// IID_INonNDRStub, 0x0000013DL
+DEFINE_OLEGUID(IID_INonNDRStub, 0x0000013DL, 0, 0);
+
+
+// IID_IClientSecurity 0x0000013DL
+// IID_IServerSecurity 0x0000013EL
+//
+// IID_IMacDragHelper 0x0000013FL
+
+// IID_IClassActivator 0x00000140L
+// IID_IDLLHost 0x00000141L
+
+// Range 0x180 - 0x18F is reserved for the category interfaces.
+// IID_? 0x00000180L
+// IID_? 0x00000181L
+// IID_? 0x00000182L
+// IID_? 0x00000183L
+// IID_? 0x00000184L
+// IID_? 0x00000185L
+// IID_? 0x00000186L
+// IID_? 0x00000187L
+// IID_? 0x00000188L
+// IID_? 0x00000189L
+// IID_? 0x0000018AL
+// IID_? 0x0000018BL
+// IID_? 0x0000018CL
+// IID_? 0x0000018DL
+// IID_? 0x0000018EL
+// IID_? 0x0000018FL
+
+
+// BUGBUG: this will be shortly removed (until binaries using
+// these values are not in use.
+DEFINE_OLEGUID(IID_IPropertyStorage_Old, 0x66600014, 0, 8);
+DEFINE_OLEGUID(IID_IEnumSTATPROPSTG_Old, 0x66600015, 0, 8);
+DEFINE_OLEGUID(IID_IPropertySetStorage_Old, 0x66650000L, 0, 8);
+DEFINE_OLEGUID(IID_IEnumSTATPROPSETSTG_Old, 0x66650001L, 0, 8);
+
+
+////////////////////////////////////////////////////////////////////////////
+// Range 0x300 - 0x3ff : internal CLSIDs
+DEFINE_OLEGUID(CLSID_StdOleLink, 0x00000300, 0, 0);
+DEFINE_OLEGUID(CLSID_StdMemStm, 0x00000301, 0, 0);
+DEFINE_OLEGUID(CLSID_StdMemBytes, 0x00000302, 0, 0);
+DEFINE_OLEGUID(CLSID_FileMoniker, 0x00000303, 0, 0);
+DEFINE_OLEGUID(CLSID_ItemMoniker, 0x00000304, 0, 0);
+DEFINE_OLEGUID(CLSID_AntiMoniker, 0x00000305, 0, 0);
+DEFINE_OLEGUID(CLSID_PointerMoniker, 0x00000306, 0, 0);
+// NOT TO BE USED 0x00000307, 0, 0);
+DEFINE_OLEGUID(CLSID_PackagerMoniker, 0x00000308, 0, 0);
+DEFINE_OLEGUID(CLSID_CompositeMoniker, 0x00000309, 0, 0);
+// NOT TO BE USED 0x0000030a, 0, 0);
+// NOT TO BE USED (was CLSID_DfMarshal) 0x0000030b, 0, 0);
+
+// NOT TO BE USED 0x30c - 0x315 - old PS CLSID's
+
+// CLSID_Picture_Metafile, 0x00000315
+// CLSID_Picture_Dib, 0x00000316
+
+DEFINE_OLEGUID(CLSID_RemoteHdlr, 0x00000317, 0, 0);
+DEFINE_OLEGUID(CLSID_RpcChannelBuffer, 0x00000318, 0, 0);
+// CLSID_Picture_EnhMetafile,0x00000319
+DEFINE_OLEGUID(CLSID_ClassMoniker, 0x0000031A, 0, 0);
+DEFINE_OLEGUID(CLSID_ErrorObject, 0x0000031B, 0, 0);
+DEFINE_OLEGUID(ERROR_EXTENSION, 0x0000031C, 0, 0);
+
+DEFINE_OLEGUID(CLSID_PSOlePrx32, 0x00000320, 0, 0);
+DEFINE_OLEGUID(IID_ITrackingMoniker, 0x00000321, 0, 0);
+
+DEFINE_OLEGUID(CLSID_ServerHandler, 0x00020322, 0, 0);
+DEFINE_OLEGUID(CLSID_ClientSiteHandler, 0x00020323, 0, 0);
+DEFINE_OLEGUID(CLSID_PSDispatch, 0x00020420, 0, 0);
+
+/* NOTE: LSB values 0x1a through 0xff are unused */
+
+DEFINE_OLEGUID(IID_IHookOleObject, 0x0002AD11, 0, 0);
diff --git a/private/ole32/ih/privoa.h b/private/ole32/ih/privoa.h
new file mode 100644
index 000000000..452df6eda
--- /dev/null
+++ b/private/ole32/ih/privoa.h
@@ -0,0 +1,59 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: privoa.h
+//
+// Contents: Definitions for OleAut32.dll wrappers
+//
+// Classes:
+//
+// Functions: PrivSysAllocString
+// PrivSysFreeString
+// PrivSysReAllocStringLen
+// PrivSysStringLen
+//
+// History: 20-Jun-96 MikeHill Created.
+//
+// Notes:
+// This file has macros, function prototypes, and global
+// externs that enable the OleAut32 wrapper functions.
+// These functions load OleAut32.dll if necessary, and forward
+// the call.
+//
+//----------------------------------------------------------------------------
+
+#ifndef _PRIV_OA_H_
+#define _PRIV_OA_H_
+
+// OleAut32 function prototypes
+
+typedef BSTR (STDAPICALLTYPE SYS_ALLOC_STRING)(OLECHAR FAR* pwsz);
+typedef VOID (STDAPICALLTYPE SYS_FREE_STRING)(BSTR bstr);
+typedef BOOL (STDAPICALLTYPE SYS_REALLOC_STRING_LEN)(BSTR* pbstr, OLECHAR* pch, UINT cch);
+typedef UINT (STDAPICALLTYPE SYS_STRING_BYTE_LEN)(BSTR bstr);
+
+// The Wrapper routines, and function pointers for them.
+
+SYS_ALLOC_STRING LoadSysAllocString;
+EXTERN_C SYS_ALLOC_STRING *pfnSysAllocString;
+
+SYS_FREE_STRING LoadSysFreeString;
+EXTERN_C SYS_FREE_STRING *pfnSysFreeString;
+
+SYS_REALLOC_STRING_LEN LoadSysReAllocStringLen;
+EXTERN_C SYS_REALLOC_STRING_LEN *pfnSysReAllocStringLen;
+
+SYS_STRING_BYTE_LEN LoadSysStringByteLen;
+EXTERN_C SYS_STRING_BYTE_LEN *pfnSysStringByteLen;
+
+// Macros to ease the calling of the above function pointers
+
+#define PrivSysAllocString(pwsz) (*pfnSysAllocString)(pwsz)
+#define PrivSysFreeString(bstr) (*pfnSysFreeString)(bstr)
+#define PrivSysReAllocStringLen(pbstr,olestr,ui) \
+ (*pfnSysReAllocStringLen)(pbstr, olestr, ui)
+#define PrivSysStringByteLen(pbstr) (*pfnSysStringByteLen)(pbstr)
+
+#endif // ! _PRIV_OA_H_
diff --git a/private/ole32/ih/resource.h b/private/ole32/ih/resource.h
new file mode 100644
index 000000000..e61bf3721
--- /dev/null
+++ b/private/ole32/ih/resource.h
@@ -0,0 +1,10 @@
+#define CURNONE 1
+#define CURMOVE 2
+#define CURCOPY 3
+#define CURLINK 4
+#define CURSCROLLMOVE 5
+#define CURSCROLLCOPY 6
+#define CURSCROLLLINK 7
+
+// used by "..\src\def\geticon.c"
+#define DEFICON 8
diff --git a/private/ole32/ih/rothint.hxx b/private/ole32/ih/rothint.hxx
new file mode 100644
index 000000000..6ce287b0d
--- /dev/null
+++ b/private/ole32/ih/rothint.hxx
@@ -0,0 +1,124 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: rothint.hxx
+//
+// Contents: Base class for ROT hint table used in NT
+//
+// History: 24-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef __ROTHINT_HXX__
+#define __ROTHINT_HXX__
+
+// Size of the hint table and size of the SCM's hash table for the ROT.
+#define SCM_HASH_SIZE 251
+
+// Name of hint table for non-NT1X
+#define ROTHINT_NAME L"RotHintTable"
+
+#ifndef _CHICAGO_
+
+//+-------------------------------------------------------------------------
+//
+// Class: CRotHintTable (rht)
+//
+// Purpose: Base class for hint table shared between SCM and OLE32.
+// It is designed to abstract what is fundamental an array
+// of on/off switches.
+//
+// Interface: SetIndicator - set indicator byte
+// ClearIndicator - clear indicator byte
+// GetIndicator - get indicator byte.
+//
+// History: 24-Jan-93 Ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+class CRotHintTable
+{
+public:
+ CRotHintTable(void);
+
+ void SetIndicator(DWORD dwOffset);
+
+ void ClearIndicator(DWORD dwOffset);
+
+ BOOL GetIndicator(DWORD dwOffset);
+
+protected:
+
+ // This memory is allocated by the derived class.
+ // The SCM actually creates the memory while the
+ // client just opens the memory.
+ BYTE * _pbHintArray;
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotHintTable::CRotHintTable
+//
+// Synopsis: Initialize object
+//
+// History: 24-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CRotHintTable::CRotHintTable(void) : _pbHintArray(NULL)
+{
+ // Header does all the work
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotHintTable::SetIndicator
+//
+// Synopsis: Turn switch on
+//
+// History: 24-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CRotHintTable::SetIndicator(DWORD dwOffset)
+{
+ _pbHintArray[dwOffset] = TRUE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotHintTable::ClearIndicator
+//
+// Synopsis: Turn switch off
+//
+// History: 24-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CRotHintTable::ClearIndicator(DWORD dwOffset)
+{
+ _pbHintArray[dwOffset] = FALSE;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CRotHintTable::GetIndicator
+//
+// Synopsis: Get the state of the switch
+//
+// History: 24-Jan-95 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CRotHintTable::GetIndicator(DWORD dwOffset)
+{
+ return _pbHintArray[dwOffset];
+}
+
+
+
+#endif // !_CHICAGO_
+
+#endif // __ROTHINT_HXX__
diff --git a/private/ole32/ih/stkswtch.h b/private/ole32/ih/stkswtch.h
new file mode 100644
index 000000000..8a86e8e80
--- /dev/null
+++ b/private/ole32/ih/stkswtch.h
@@ -0,0 +1,200 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: stkswtch.h
+//
+// Contents: Stack Switching proto types and macros
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-10-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+#ifndef _STKSWTCH_
+#define _STKSWTCH_
+
+#ifdef _CHICAGO_
+
+extern "C" DWORD NEAR _cdecl SSCall(DWORD cbParamBytes,
+ DWORD flags,
+ LPVOID lpfnProcAddress,
+ DWORD param1,...);
+
+
+#define SSF_BigStack 1
+#define SSF_SmallStack 0
+extern "C" BOOL WINAPI SSOnBigStack(VOID);
+
+DECLARE_DEBUG(Stack)
+#define DEB_STCKSWTCH DEB_USER1
+#define SSOnSmallStack() (!SSOnBigStack())
+#if DBG==1
+
+extern BOOL fSSOn;
+#define SSONBIGSTACK() (fSSOn && IsWOWThread() && SSOnBigStack())
+#define SSONSMALLSTACK() (fSSOn && IsWOWThread() && !SSOnBigStack())
+#define StackAssert(x) ((fSSOn && IsWOWThread())? Win4Assert(x): TRUE)
+#define StackDebugOut(x) StackInlineDebugOut x
+
+#else
+
+#define SSONBIGSTACK() (IsWOWThread() && SSOnBigStack())
+#define SSONSMALLSTACK() (IsWOWThread() && !SSOnBigStack())
+#define StackAssert(x)
+#define StackDebugOut(x)
+
+#endif
+
+LRESULT WINAPI SSSendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+BOOL WINAPI SSReplyMessage(LRESULT lResult);
+LRESULT WINAPI SSCallWindowProc(WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+LRESULT WINAPI SSDefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+BOOL WINAPI SSPeekMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax,UINT wRemoveMsg);
+BOOL WINAPI SSGetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);
+LONG WINAPI SSDispatchMessage(CONST MSG *lpMsg);
+BOOL WINAPI SSWaitMessage(VOID);
+BOOL WINAPI SSDirectedYield(HTASK htask);
+int WINAPI SSDialogBoxParam(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);
+int WINAPI SSDialogBoxIndirectParam(HINSTANCE hInstance, LPCDLGTEMPLATEA hDialogTemplate, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);
+
+#define SSDialogBox(a,b,c,d) \
+ SSDialogBoxParam(a,b,c,d, 0L)
+#define SSDialogBoxIndirect(a,b,c,d) \
+ SSDialogBoxIndirectParam(a,b,c,d,e, 0L)
+
+HWND WINAPI SSCreateWindowExA(DWORD dwExStyle,
+ LPCSTR lpClassName,LPCSTR lpWindowName,
+ DWORD dwStyle,int X,int Y,int nWidth,int nHeight,
+ HWND hWndParent ,HMENU hMenu,HINSTANCE hInstance,
+ LPVOID lpParam);
+
+HWND WINAPI SSCreateWindowExW(DWORD dwExStyle,
+ LPCWSTR lpClassName,LPCWSTR lpWindowName,
+ DWORD dwStyle, int X, int Y, int nWidth,int nHeight,
+ HWND hWndParent ,HMENU hMenu,HINSTANCE hInstance,
+ LPVOID lpParam);
+
+BOOL WINAPI SSDestroyWindow(HWND hWnd);
+int WINAPI SSMessageBox(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption, UINT uType);
+
+BOOL WINAPI SSOpenClipboard(HWND hWndNewOwner);
+BOOL WINAPI SSCloseClipboard(VOID);
+HWND WINAPI SSGetClipboardOwner(VOID);
+HANDLE WINAPI SSSetClipboardData(UINT uFormat,HANDLE hMem);
+HANDLE WINAPI SSGetClipboardData(UINT uFormat);
+UINT WINAPI SSRegisterClipboardFormatA(LPCSTR lpszFormat);
+UINT WINAPI SSEnumClipboardFormats(UINT format);
+int WINAPI SSGetClipboardFormatNameA(UINT format,LPSTR lpszFormatName,int cchMaxCount);
+BOOL WINAPI SSEmptyClipboard(VOID);
+BOOL WINAPI SSIsClipboardFormatAvailable(UINT format);
+
+
+
+#undef SendMessage
+#undef ReplyMessage
+#undef CallWindowProc
+#undef DefWindowProc
+#undef PeekMessage
+#undef GetMessage
+#undef DispatchMessage
+#undef WaitMessage
+#undef DialogBoxParam
+#undef DialogBoxIndirectParam
+#undef CreateWindowExA
+#undef CreateWindowExW
+#undef DestroyWindow
+#undef MessageBox
+//
+#undef OpenClipboard
+#undef CloseClipboard
+#undef GetClipboardOwner
+#undef SetClipboardData
+#undef RegisterClipboardFormatA
+#undef EnumClipboardFormats
+#undef GetClipboardFormatNameA
+#undef EmptyClipboard
+#undef IsClipboardFormatAvailable
+
+// Define all user APIs to an undefined function to
+// force an compiling error.
+
+#define SS_STOP_STR USE_SS_API_INSTEAD /* error: Stack Switching: Please use SSxxx APIS! */
+#define SendMessage( hWnd, Msg, wParam, lParam) SS_STOP_STR
+#define ReplyMessage( lResult) SS_STOP_STR
+#define CallWindowProc( lpPrevWndFunc, hWnd, Msg, wParam, lParam) SS_STOP_STR
+#define DefWindowProc( hWnd, Msg, wParam, lParam) SS_STOP_STR
+#define PeekMessage( lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg) SS_STOP_STR
+#define GetMessage( lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax) SS_STOP_STR
+#define DispatchMessage( lpMsg) SS_STOP_STR
+#define WaitMessage() SS_STOP_STR
+#define DialogBoxParam( hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam) SS_STOP_STR
+#define DialogBoxIndirectParam( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam) SS_STOP_STR
+#define CreateWindowExA( dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent , hMenu, hInstance, lpParam) SS_STOP_STR
+#define CreateWindowExW( dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent , hMenu, hInstance, lpParam) SS_STOP_STR
+#define DestroyWindow( hWnd) SS_STOP_STR
+#define MessageBox( hWnd, lpText, lpCaption, uType) SS_STOP_STR
+//
+#define OpenClipboard( hWndNewOwner) SS_STOP_STR
+#define CloseClipboard() SS_STOP_STR
+#define GetClipboardOwner() SS_STOP_STR
+#define SetClipboardData( uFormat, hMem) SS_STOP_STR
+#define RegisterClipboardFormatA(lpszFormat) SS_STOP_STR
+#define EnumClipboardFormats( format) SS_STOP_STR
+#define GetClipboardFormatNameA( format, lpszFormatName, cchMaxCount) SS_STOP_STR
+#define EmptyClipboard() SS_STOP_STR
+#define IsClipboardFormatAvailable( format) SS_STOP_STR
+
+#else // ! _CHICAGO
+
+// For non-chicago platrforms: define all SSxxx APIs
+// back to the original user api
+
+#define SSSendMessage SendMessage
+#define SSReplyMessage ReplyMessage
+#define SSCallWindowProc CallWindowProc
+#define SSDefWindowProc DefWindowProc
+#define SSPeekMessage PeekMessage
+#define SSGetMessage GetMessage
+#define SSDispatchMessage DispatchMessage
+#define SSWaitMessage WaitMessage
+#define SSDirectedYield DirectedYield
+#define SSDialogBoxParam DialogBoxParam
+#define SSDialogBoxIndirectParam DialogBoxIndirectParam
+#define SSCreateWindowExA CreateWindowExA
+#define SSCreateWindowExW CreateWindowExW
+#define SSDestroyWindow DestroyWindow
+#define SSMessageBox MessageBox
+
+#define SSOpenClipboard OpenClipboard
+#define SSCloseClipboard CloseClipboard
+#define SSGetClipboardOwner GetClipboardOwner
+#define SSSetClipboardData SetClipboardData
+#define SSGetClipboardData GetClipboardData
+#define SSRegisterClipboardFormatA RegisterClipboardFormatA
+#define SSEnumClipboardFormats EnumClipboardFormats
+#define SSGetClipboardFormatNameA GetClipboardFormatNameA
+#define SSEmptyClipboard EmptyClipboard
+#define SSIsClipboardFormatAvailable IsClipboardFormatAvailable
+
+
+#endif // _CHICAGO_
+
+#ifdef _CHICAGO_
+
+#define SSAPI(x) SS##x
+
+#else
+
+#define SSAPI(x) x
+#define StackDebugOut(x)
+#define StackAssert(x)
+#define SSOnSmallStack()
+
+#endif // _CHICAGO_
+
+#endif // _STKSWTCH_
+
diff --git a/private/ole32/ih/thkreg.h b/private/ole32/ih/thkreg.h
new file mode 100644
index 000000000..316284f06
--- /dev/null
+++ b/private/ole32/ih/thkreg.h
@@ -0,0 +1,27 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: thkreg.cxx
+//
+// Contents: Contains constants used to read the registry for modifiable
+// WOW behavior for OLE.
+//
+// History: 22-Jul-94 Ricksa Created
+// 09-Jun-95 Susia Chicago optimization added
+//
+//--------------------------------------------------------------------------
+#ifndef _THKREG_H_
+#define _THKREG_H_
+
+
+// Name of key for OLE WOW special behavior
+#define OLETHK_KEY TEXT("OleCompatibility")
+// Factor by which to slow duration of WOW RPC calls
+#define OLETHK_SLOWRPCTIME_VALUE TEXT("SlowRpcTimeFactor")
+
+// Default factor to slow duration of WOW RPC calls
+#define OLETHK_DEFAULT_SLOWRPCTIME 4
+
+#endif // _THKREG_H_
diff --git a/private/ole32/ih/thunkapi.hxx b/private/ole32/ih/thunkapi.hxx
new file mode 100644
index 000000000..44ca0e9ba
--- /dev/null
+++ b/private/ole32/ih/thunkapi.hxx
@@ -0,0 +1,142 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: thunkapi.hxx
+//
+// Contents: Defines interfaces and methods for use by the WOW thunking
+// system. This is intended as a private interface between
+// OLE32 and the WOW thunking layer.
+//
+// Classes: OleThunkWOW
+//
+// Functions:
+//
+// History: 3-15-94 kevinro Created
+//
+//----------------------------------------------------------------------------
+#ifndef __thunkapi_hxx__
+#define __thunkapi_hxx__
+
+
+//
+// ThunkManager interface
+//
+interface IThunkManager : public IUnknown
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IThunkManager methods ***
+ STDMETHOD_(BOOL, IsIIDRequested) (THIS_ REFIID rrid) PURE;
+ STDMETHOD_(BOOL, IsCustom3216Proxy) (THIS_ IUnknown *punk,
+ REFIID riid) PURE;
+};
+
+
+//
+// The following sets up an interface between OLE32
+// and the WOW thunking system. This interface is intended to be private
+// between OLE32 and the WOW thunk layer.
+//
+
+class OleThunkWOW
+{
+public:
+
+ STDMETHOD(LoadProcDll)( LPCTSTR pszDllName,
+ LPDWORD lpvpfnGetClassObject,
+ LPDWORD lpvpfnCanUnloadNow,
+ LPDWORD lpvhmodule );
+
+ STDMETHOD(UnloadProcDll)( DWORD vhmodule );
+
+
+ STDMETHOD(CallGetClassObject)( DWORD vpfnGetClassObject,
+ REFCLSID rclsid,
+ REFIID riid,
+ LPVOID FAR *ppv );
+
+ STDMETHOD(CallCanUnloadNow)( DWORD vpfnCanUnloadNow );
+ STDMETHOD(GetThunkManager)( IThunkManager **pThkMgr);
+
+ // Used to launch OLE 1.0 servers when we're in Wow
+ STDMETHOD(WinExec16)(LPCOLESTR pszCommandLine, USHORT usShow);
+
+ //
+ // Called by the DDE code to convert incoming HWND's from
+ // 16 bit HWND's into 32-bit HWND's.
+ //
+ STDMETHOD_(HWND,ConvertHwndToFullHwnd)(HWND hwnd);
+
+ //
+ // Called by the DDE code to delete a metafile
+ //
+ STDMETHOD_(BOOL,FreeMetaFile)(HANDLE hmf);
+
+ // Called by Call Control to guarantee that a Yield happens
+ // when running in Wow.
+ STDMETHOD(YieldTask16)(void);
+
+ // Call Control Directed Yeild
+ STDMETHOD(DirectedYield)(DWORD dwCalleeTID);
+
+ // Called by OLE32 when it is shutting down (done on a per thread basis)
+ STDMETHOD_(void,PrepareForCleanup)(void);
+
+ STDMETHOD_(DWORD,GetAppCompatibilityFlags)(void);
+};
+
+typedef OleThunkWOW *LPOLETHUNKWOW,OLETHUNKWOW;
+
+//
+// OLE Thunk Application Compatability flags
+//
+
+#define OACF_CLIENTSITE_REF 0x80000000 // IOleObject::GetClientSite not ref'd
+ // Bug in Excel 5.0a
+#define OACF_RESETMENU 0x40000000 // IOleInPlaceFrame::RemoveMenu didn't
+ // do a OleSetMenuDescriptor(NULL).
+#define OACF_USEGDI 0x20000000 // Word 6 thinks bitmaps and palette
+ // objects are HGLOBALs, but they
+ // are really GDI objects. We'll patch
+ // this up for them.
+//
+// The following flag is set in olethunk\h\interop.hxx because it is used by
+// 16-bit binaries.
+// OACF_CORELTRASHMEM 0x10000000 // CorelDraw relies on the fact that
+// // OLE16 trashed memory during paste-
+// // link. Therefore, we'll go ahead
+// // and trash it for them if this
+// // flag is on.
+
+//
+// The original OLE32 version of the stdid table didn't clean up properly. Some apps cannot
+// handle the stdid calling after CoUninitialize. This flag prevents the stdid from doing so.
+// Word 6.0c is an example of this.
+//
+
+#define OACF_NO_UNINIT_CLEANUP 0x02000000 // Do not cleanup interfaces on CoUninitialize
+
+#define OACF_IVIEWOBJECT2 0x01000000 // use IViewObject2 instead IViewObject
+
+
+
+
+
+//
+// The following three routines are exported from OLE32.DLL, and
+// are called only by the WOW thunk layer.
+//
+
+STDAPI CoInitializeWOW( LPMALLOC vlpmalloc, LPOLETHUNKWOW lpthk );
+STDAPI CoUnloadingWOW(BOOL fProcessDetach);
+STDAPI OleInitializeWOW( LPMALLOC vlpmalloc, LPOLETHUNKWOW lpthk );
+STDAPI DllGetClassObjectWOW( REFCLSID rclsid, REFIID riid, LPVOID *ppv );
+
+extern void SetOleThunkWowPtr(LPOLETHUNKWOW lpthk);
+
+#endif //
diff --git a/private/ole32/ih/tls.h b/private/ole32/ih/tls.h
new file mode 100644
index 000000000..7d676347c
--- /dev/null
+++ b/private/ole32/ih/tls.h
@@ -0,0 +1,367 @@
+//+---------------------------------------------------------------------------
+//
+// File: tls.hxx
+//
+// Purpose: manage thread local storage for OLE
+//
+// Notes: The gTlsIndex is initialized at process attach time.
+// The per-thread data is allocated in CoInitialize in
+// single-threaded apartments or on first use in
+// multi-threaded apartments.
+//
+// The non-inline routines are in ..\com\class\tls.cxx
+//
+// History: 16-Jun-94 BruceMa Don't decrement 0 thread count
+// 17-Jun-94 Bradloc Added punkState for VB94
+// 20-Jun-94 Rickhi Commented better
+// 06-Jul-94 BruceMa Support for CoGetCurrentProcess
+// 19-Jul-94 CraigWi Removed TLSGetEvent (used cache instead)
+// 21-Jul-94 AlexT Add TLSIncOleInit, TLSDecOleInit
+// 21-Aug-95 ShannonC Removed TLSSetMalloc, TLSGetMalloc
+// 06-Oct-95 Rickhi Simplified. Made into a C++ class.
+// 01-Feb-96 Rickhi On Nt, access TEB directly
+// 30-May-96 ShannonC Add punkError
+//
+//----------------------------------------------------------------------------
+#ifndef _TLS_HXX_
+#define _TLS_HXX_
+
+
+#include <rpc.h> // UUID
+
+
+//+---------------------------------------------------------------------------
+//
+// forward declarations (in order to avoid type casting when accessing
+// data members of the SOleTlsData structure).
+//
+//+---------------------------------------------------------------------------
+
+class CAptCallCtrl; // see callctrl.hxx
+class CSrvCallState; // see callctrl.hxx
+class CRemoteUnknown; // see remoteu.hxx
+class CObjServer; // see sobjact.hxx
+class CSmAllocator; // see stg\h\smalloc.hxx
+class CChannelCallInfo; // see chancont.hxx
+
+
+#ifdef _CHICAGO_
+// Chicago uses the Thread Local Storage APIs
+extern DWORD gTlsIndex; // global Index for TLS
+#endif // _CHICAGO_
+
+
+//+---------------------------------------------------------------------------
+//
+// Enum: OLETLSFLAGS
+//
+// Synopsys: bit values for dwFlags field of SOleTlsData. If you just want
+// to store a BOOL in TLS, use this enum and the dwFlag field.
+//
+//+---------------------------------------------------------------------------
+typedef enum tagOLETLSFLAGS
+{
+ OLETLS_LOCALTID = 0x01, // This TID is in the current process.
+ OLETLS_UUIDINITIALIZED = 0x02, // This Logical thread is init'd.
+ OLETLS_INTHREADDETACH = 0x04, // This is in thread detach. Needed
+ // due to NT's special thread detach rules.
+ OLETLS_CHANNELTHREADINITIALZED = 0x08, // This channel has been init'd
+ OLETLS_WOWTHREAD = 0x10, // This thread is a 16-bit WOW thread.
+ OLETLS_THREADUNINITIALIZING = 0x20, // This thread is in CoUninitialize.
+ OLETLS_DISABLE_OLE1DDE = 0x40, // This thread can't use a DDE window.
+ OLETLS_APARTMENTTHREADED = 0x80, // This is an STA apartment thread
+ OLETLS_MULTITHREADED = 0x100 // This is an MTA apartment thread
+} OLETLSFLAGS;
+
+
+//+---------------------------------------------------------------------------
+//
+// Structure: SOleTlsData
+//
+// Synopsis: structure holding per thread state needed by OLE32
+//
+//+---------------------------------------------------------------------------
+typedef struct tagSOleTlsData
+{
+#if !defined(_CHICAGO_)
+ // Docfile multiple allocator support
+ void *pvThreadBase; // per thread base pointer
+ CSmAllocator *pSmAllocator; // per thread docfile allocator
+#endif
+
+ DWORD dwApartmentID; // Per thread "process ID"
+ DWORD dwFlags; // see OLETLSFLAGS above
+
+ // counters
+ DWORD cComInits; // number of per-thread inits
+ DWORD cOleInits; // number of per-thread OLE inits
+#if DBG==1
+ LONG cTraceNestingLevel; // call nesting level for OLETRACE
+#endif
+
+
+ // Object RPC data
+ UUID LogicalThreadId; // current logical thread id
+ DWORD dwTIDCaller; // TID of current calling app
+ ULONG fault; // fault value
+ LONG cORPCNestingLevel; // call nesting level (DBG only)
+#ifdef DCOM
+ CChannelCallInfo *pCallInfo; // channel call info
+ DWORD cDebugData; // count of bytes of debug data in call
+ void *pOXIDEntry; // ptr to OXIDEntry for this thread.
+ CObjServer *pObjServer; // Activation Server Object.
+ CRemoteUnknown *pRemoteUnk; // CRemUnknown for this thread.
+ CAptCallCtrl *pCallCtrl; // new call control for RPC
+ CSrvCallState *pTopSCS; // top server-side callctrl state
+ IMessageFilter *pMsgFilter; // temp storage for App MsgFilter
+ ULONG cPreRegOidsAvail; // count of server-side OIDs avail
+ unsigned hyper *pPreRegOids; // ptr to array of pre-reg OIDs
+ IUnknown *pCallContext; // call context object
+ DWORD dwAuthnLevel; // security level of current call
+#else
+ void * pChanCtrl; // channel control
+ void * pService; // per-thread service object
+ void * pServiceList;
+ void * pCallCont; // call control
+ void * pDdeCallCont; // dde call control
+ void * pCALLINFO; // callinfo
+ DWORD dwEndPoint; // endpoint id
+#ifdef _CHICAGO_
+ HWND hwndOleRpcNotify;
+#endif
+#endif // DCOM
+
+ // DDE data
+ HWND hwndDdeServer; // Per thread Common DDE server
+ HWND hwndDdeClient; // Per thread Common DDE client
+
+
+ // upper layer data
+ HWND hwndClip; // Clipboard window
+ IUnknown *punkState; // Per thread "state" object
+#ifdef WX86OLE
+ IUnknown *punkStateWx86; // Per thread "state" object for Wx86
+#endif
+ void *pDragCursors; // Per thread drag cursor table.
+
+#ifdef _CHICAGO_
+ LPVOID pWcstokContext; // Scan context for wcstok
+#endif
+
+ IUnknown *punkError; // Per thread error object.
+ ULONG cbErrorData; // Maximum size of error data.
+} SOleTlsData;
+
+
+
+//+---------------------------------------------------------------------------
+//
+// class COleTls
+//
+// Synopsis: class to abstract thread-local-storage in OLE.
+//
+// Notes: To use Tls in OLE, functions should define an instance of
+// this class on their stack, then use the -> operator on the
+// instance to access fields of the SOleTls structure.
+//
+// There are two instances of the ctor. One just Assert's that
+// the SOleTlsData has already been allocated for this thread. Most
+// internal code should use this ctor, since we can assert that if
+// the thread made it this far into our code, tls has already been
+// checked.
+//
+// The other ctor will check if SOleTlsData exists, and attempt to
+// allocate and initialize it if it does not. This ctor will
+// return an HRESULT. Functions that are entry points to OLE32
+// should use this version.
+//
+//+---------------------------------------------------------------------------
+class COleTls
+{
+public:
+ COleTls();
+ COleTls(HRESULT &hr);
+ COleTls(BOOL fDontAllocateIfNULL);
+
+ // to get direct access to the data structure
+ SOleTlsData * operator->(void) { return _pData; }
+
+ BOOL IsNULL() { return (_pData == NULL) ? TRUE : FALSE; }
+
+private:
+
+ HRESULT TLSAllocData(); // allocates an SOleTlsData structure
+
+ SOleTlsData * _pData; // ptr to OLE TLS data
+};
+
+
+#ifndef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Method: COleTls::COleTls
+//
+// Synopsis: ctor for OLE Tls object.
+//
+// Notes: Most internal code should use this version of the ctor,
+// assuming that some outer-layer function has already verified
+// the existence of the tls_data.
+//
+//+---------------------------------------------------------------------------
+inline COleTls::COleTls()
+{
+ _pData = (SOleTlsData *) NtCurrentTeb()->ReservedForOle;
+ Win4Assert(_pData && "Illegal attempt to use TLS before Initialized");
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: COleTls::COleTls
+//
+// Synopsis: ctor for OLE Tls object.
+//
+// Notes: Special version for CoUninitialize which will not allocate
+// (or assert) if the TLS is NULL. It can then be checked with
+// IsNULL member function.
+//
+//+---------------------------------------------------------------------------
+inline COleTls::COleTls(BOOL fDontAllocateIfNULL)
+{
+ _pData = (SOleTlsData *) NtCurrentTeb()->ReservedForOle;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: COleTls::COleTls
+//
+// Synopsis: ctor for OLE Tls object.
+//
+// Notes: Peripheral OLE code that can not assume that some outer-layer
+// function has already verified the existence of the SOleTlsData
+// structure for the current thread should use this version of
+// the ctor.
+//
+//+---------------------------------------------------------------------------
+inline COleTls::COleTls(HRESULT &hr)
+{
+ _pData = (SOleTlsData *) NtCurrentTeb()->ReservedForOle;
+ if (_pData)
+ hr = S_OK;
+ else
+ hr = TLSAllocData();
+}
+
+#else // _CHICAGO_ versions
+
+//+---------------------------------------------------------------------------
+//
+// Method: COleTls::COleTls
+//
+// Synopsis: ctor for OLE Tls object.
+//
+// Notes: Most internal code should use this version of the ctor,
+// assuming that some outer-layer function has already verified
+// the existence of the tls_data.
+//
+//+---------------------------------------------------------------------------
+inline COleTls::COleTls()
+{
+ _pData = (SOleTlsData *) TlsGetValue(gTlsIndex);
+ Win4Assert(_pData && "Illegal attempt to use TLS before Initialized");
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: COleTls::COleTls
+//
+// Synopsis: ctor for OLE Tls object.
+//
+// Notes: Special version for CoUninitialize which will not allocate
+// (or assert) if the TLS is NULL. It can then be checked with
+// IsNULL member function.
+//
+//+---------------------------------------------------------------------------
+inline COleTls::COleTls(BOOL fDontAllocateIfNULL)
+{
+ _pData = (SOleTlsData *) TlsGetValue(gTlsIndex);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: COleTls::COleTls
+//
+// Synopsis: ctor for OLE Tls object.
+//
+// Notes: Peripheral OLE code that can not assume that some outer-layer
+// function has already verified the existence of the SOleTlsData
+// structure for the current thread should use this version of
+// the ctor.
+//
+//+---------------------------------------------------------------------------
+inline COleTls::COleTls(HRESULT &hr)
+{
+ _pData = (SOleTlsData *) TlsGetValue(gTlsIndex);
+ if (_pData)
+ hr = S_OK;
+ else
+ hr = TLSAllocData();
+}
+#endif // _CHICAGO_
+
+
+
+typedef DWORD HAPT;
+const HAPT haptNULL = 0;
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetCurrentApartmentId
+//
+// Synopsis: Returns the apartment id that the current thread is executing
+// in. If this is the Multi-threaded apartment, it returns 0.
+//
+//+---------------------------------------------------------------------------
+inline DWORD GetCurrentApartmentId()
+{
+ COleTls Tls;
+ return (Tls->dwFlags & OLETLS_APARTMENTTHREADED) ? GetCurrentThreadId() : 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsSTAThread
+//
+// Synopsis: returns TRUE if the current thread is for a
+// single-threaded apartment, FALSE otherwise
+//
+//+---------------------------------------------------------------------------
+inline BOOL IsSTAThread()
+{
+ COleTls Tls;
+ return (Tls->dwFlags & OLETLS_APARTMENTTHREADED) ? TRUE : FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsMTAThread
+//
+// Synopsis: returns TRUE if the current thread is for a
+// multi-threaded apartment, FALSE otherwise
+//
+//+---------------------------------------------------------------------------
+inline BOOL IsMTAThread()
+{
+ COleTls Tls;
+ return (Tls->dwFlags & OLETLS_APARTMENTTHREADED) ? FALSE : TRUE;
+}
+
+BOOL IsApartmentInitialized();
+IID *TLSGetLogicalThread();
+BOOLEAN TLSIsWOWThread();
+BOOLEAN TLSIsThreadDetaching();
+
+#ifndef DCOM
+#include <tlschico.h>
+#endif
+
+#endif // _TLS_HXX_
diff --git a/private/ole32/ih/tlschico.h b/private/ole32/ih/tlschico.h
new file mode 100644
index 000000000..2e6a5d2c3
--- /dev/null
+++ b/private/ole32/ih/tlschico.h
@@ -0,0 +1,514 @@
+//+----------------------------------------------------------------
+//
+// Functions: TLSxxx functions
+//
+// Purpose: temp place for old style TLS functions until DCOM is
+// defined for Win95
+//
+// History: 02-Nov-95 Rickhi Separated from tls.h
+//
+//-----------------------------------------------------------------
+
+#define ENDPOINT_ID_INVALID 0xFFFFFFFF
+
+HWND CreateDdeClientHwnd(void);
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSGetDdeClientWindow()
+//
+// Synopsis: Returns a pointer to the per thread DdeClient window. If one
+// has not been created, it will create it and return
+//
+// Returns: Pointer to the DdeClientWindow. This window is used for per
+// thread cleanup
+//
+// History: 12-12-94 kevinro Created
+//----------------------------------------------------------------------------
+inline void * TLSGetDdeClientWindow()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ if (tls->hwndDdeClient == NULL)
+ {
+ tls->hwndDdeClient = CreateDdeClientHwnd();
+ }
+ return tls->hwndDdeClient;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSSetLogicalThread
+//
+// Synopsis: sets the logical thread id
+//
+// Arguments: [riid] - the id for the logical thread
+//
+//+---------------------------------------------------------------------------
+inline BOOL TLSSetLogicalThread(REFIID riid)
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ tls->dwFlags |= OLETLS_UUIDINITIALIZED;
+ tls->LogicalThreadId = riid;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSSetCallerTID
+//
+// Synopsis: sets the TID of current caller
+//
+// Arguments: [TIDCaller] - TID of app making the incoming call
+// [fLocal] - whether TID is in this process
+// [pTIDCallerPrev] - TID of app making the previous incoming call
+// [pfLocalPrev] - whether previous TID is in this process
+//
+// Notes: these are valid only during object RPC. They are here to
+// support focus management in IOleObject::DoVerb, where
+// app queues get linked together.
+//
+//+---------------------------------------------------------------------------
+inline BOOL TLSSetCallerTID(DWORD TIDCaller, BOOL fLocal,
+ DWORD *pTIDCallerPrev, BOOL *pfLocalPrev)
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ // save the old values
+ *pTIDCallerPrev = tls->dwTIDCaller;
+ *pfLocalPrev = (tls->dwFlags & OLETLS_LOCALTID) ? TRUE : FALSE;
+
+ // set the new values
+ tls->dwTIDCaller = TIDCaller;
+ tls->dwFlags |= (fLocal) ? OLETLS_LOCALTID : 0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSGetCallerTID
+//
+// Synopsis: gets the TID of current caller
+//
+// Arguments: [pTIDCaller] - TID of app making the incoming call
+//
+// Returns: [S_OK] - tid set, caller in same process
+// [S_FALSE] - tid set, caller in different process
+// [E_OUTOFMEMORY] - cant get TLS data
+//
+// Notes: these are valid only during object RPC. They are here to
+// support focus management in IOleObject::DoVerb, where
+// app queues get linked together.
+//
+//+---------------------------------------------------------------------------
+inline HRESULT TLSGetCallerTID(DWORD *pTIDCaller)
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ *pTIDCaller = tls->dwTIDCaller;
+ return (tls->dwFlags & OLETLS_LOCALTID) ? S_OK : S_FALSE;
+ }
+
+ return E_OUTOFMEMORY;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSGetFault
+//
+// Synopsis: returns the per thread fault state
+//
+// Arguments: none
+//
+//+---------------------------------------------------------------------------
+inline ULONG TLSGetFault()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ return tls->fault;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSSetFault
+//
+// Synopsis: sets the per thread fault state
+//
+// Arguments: [ulFault] - fault code
+//
+//+---------------------------------------------------------------------------
+inline void TLSSetFault(ULONG ulFault)
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ tls->fault = ulFault;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSSetChannelControl
+//
+// Synopsis: Sets pointer to the per thread ChannelControl
+//
+// Arguments: [pChanCont] -- Pointer to be the DDECallControl for thread
+//
+// Notes: this is not AddRef'd
+//
+//+---------------------------------------------------------------------------
+inline BOOL TLSSetChannelControl( void *pChanCont )
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ tls->pChanCtrl = pChanCont;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSGetChannelControl
+//
+// Synopsis: Gets pointer to the per thread ChannelControl
+//
+// Arguments: none
+//
+// Notes: this is not AddRef'd
+//
+//+---------------------------------------------------------------------------
+inline void * TLSGetChannelControl()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ return tls->pChanCtrl;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSSetService
+//
+// Synopsis: Sets pointer to the per thread Service
+//
+// Arguments: [pService] -- Pointer to the service for the thread.
+//
+// Notes: this is not AddRef'd
+//
+//+---------------------------------------------------------------------------
+inline BOOL TLSSetService( void *pService )
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ tls->pService = pService;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSGetService
+//
+// Synopsis: Gets pointer to the per thread Service
+//
+// Arguments: none
+//
+// Notes: this is not AddRef'd
+//
+//+---------------------------------------------------------------------------
+inline void * TLSGetService()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ return tls->pService;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSSetServiceList
+//
+// Synopsis: Sets pointer to the per thread Service List
+//
+// Arguments: [pServiceList] -- Pointer to the service list for the thread.
+//
+// Notes: this is not AddRef'd
+//
+//+---------------------------------------------------------------------------
+inline BOOL TLSSetServiceList( void *pServiceList )
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ tls->pServiceList = pServiceList;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSGetServiceList
+//
+// Synopsis: Gets pointer to the per thread Service List
+//
+// Arguments: none
+//
+// Notes: this is not AddRef'd
+//
+//+---------------------------------------------------------------------------
+inline void * TLSGetServiceList()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ return tls->pServiceList;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSGetEndPointPtr
+//
+// Synopsis: Gets pointer to the per thread endpoint
+//
+// Arguments: none
+//
+// Notes: this is not AddRef'd
+//
+//+---------------------------------------------------------------------------
+inline DWORD * TLSGetEndPointPtr()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ return &tls->dwEndPoint;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSSetCallControl
+//
+// Synopsis: Sets pointer to the per thread CallControl
+//
+// Arguments: [pCallCont] -- Pointer to be the CallControl for thread
+//
+// Notes: this is not AddRef'd
+//
+//+---------------------------------------------------------------------------
+inline BOOL TLSSetCallControl( void *pCallCont )
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ tls->pCallCont = pCallCont;
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSGetCallControl
+//
+// Synopsis: Gets pointer to the per thread CallControl
+//
+// Arguments: none
+//
+// Notes: this is not AddRef'd
+//
+//+---------------------------------------------------------------------------
+inline void * TLSGetCallControl()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ return tls->pCallCont;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSSetDdeCallControl
+//
+// Synopsis: Sets pointer to the per thread DDECallControl
+//
+// Arguments: [pDdeCallCont] -- Pointer to be the DDECallControl for thread
+//
+// History: 5-13-94 kevinro Created
+//
+// Notes:
+//
+// This is not AddRefed.
+//----------------------------------------------------------------------------
+inline BOOL TLSSetDdeCallControl( void *pDdeCallCont )
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ tls->pDdeCallCont = pDdeCallCont;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSGetDdeCallControl
+//
+// Synopsis: Returns a pointer to the per thread DDECallControl
+//
+// Returns: DDECallControl interface for thread
+//
+// History: 5-13-94 kevinro Created
+//
+// Notes:
+//
+// This is not AddRef'd
+//----------------------------------------------------------------------------
+inline void * TLSGetDdeCallControl()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ return tls->pDdeCallCont;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSSetDdeServer
+//
+// Synopsis: Sets hwnd to CommonDdeServer window
+//
+// Arguments: [hwndDdeServer] --
+//
+// History: 5-13-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+inline BOOL TLSSetDdeServer(HWND hwndDdeServer )
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ tls->hwndDdeServer = hwndDdeServer;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TLSGetDdeServer
+//
+// Synopsis: Returns a handle to the per thread DdeServer window
+//
+// Returns: hwndDdeServer for thread
+//
+// History: 5-13-94 kevinro Created
+//
+// Notes:
+//----------------------------------------------------------------------------
+inline HWND TLSGetDdeServer()
+{
+ HRESULT hr;
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ return tls->hwndDdeServer;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
diff --git a/private/ole32/ih/trace.hxx b/private/ole32/ih/trace.hxx
new file mode 100644
index 000000000..06b1e62d5
--- /dev/null
+++ b/private/ole32/ih/trace.hxx
@@ -0,0 +1,206 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: trace.hxx
+//
+// Contents: TraceInfo macros and functions
+//
+// History: 14-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+#ifndef __TRACE_HXX__
+#define __TRACE_HXX__
+
+#if DBG==1
+
+#include <exports.hxx>
+
+// Our flags for the level of information we wish to print out, need to be OR'd together
+#define INF_OFF 0x00000000 // No information printed out
+#define INF_BASE 0x00000001 // base level of information
+ // minus cmn APIs like StringFromGUID2
+#define INF_CMN 0x00000002 // cmn APIs also
+#define INF_SYM 0x00000004 // try to print out symbols
+#define INF_STRUCT 0x00000008 // expand structures
+#define INF_NOTLOADED 0x80000000 // we haven't retrieved the information level from the registry yet
+
+// *** Function Prototypes ***
+// functions to print out trace information
+void _oletracein(DWORD dwApiID, ...);
+void _oletracecmnin(DWORD dwApiID, ...);
+void _oletraceout(DWORD dwApiID, HRESULT hr);
+void _oletracecmnout(DWORD dwApiID, HRESULT hr);
+void _oletraceoutex(DWORD dwApiID,...);
+void _oletracecmnoutex(DWORD dwApiID,...);
+
+// *** Macros ***
+// ************************************************************
+// The following macros use these type specifiers in any passed format strings
+// note that I tried to keep them similar to printf in most cases, but not always
+// in general, the type specifiers are case-sensitive. Also, a caps type specifier
+// usually means that the output will be in caps, as opposed to lowercase (i.e. BOOLs
+// and HEX numbers)
+// *** Basic types
+// int, LONG -> %d, %D
+// UINT, ULONG, DWORD ->%ud, %uD, %x, %X
+// BOOL -> %b, %B
+// pointer -> %p, %P (hex)
+// string -> %s
+// wide string -> %ws
+// HANDLE -> %h
+// LARGE_INTEGER, ULARGE_INTEGER -> %ld, %uld
+// GUID -> %I
+// LPOLESTR, OLECHAR -> %ws
+
+// *** Structures
+// BIND_OPTS -> %tb
+// DVTARGETDEVICE -> %td
+// FORMATETC -> %te
+// FILETIME -> %tf
+// INTERFACEINFO -> %ti
+// LOGPALETTE -> %tl
+// MSG -> %tm
+// OLEINPLACEFRAMEINFO -> %to
+// POINT -> %tp
+// RECT -> %tr
+// STGMEDIUM -> %ts
+// STATSTG -> %tt
+// OLEMENUGROUPWIDTHS -> %tw
+// SIZE -> %tz
+
+//+---------------------------------------------------------------------------
+//
+// Macro: OLETRACEIN
+//
+// Synopsis: Handle all trace-related tasks at function entry.
+// Current tasks:
+// Print out function name and parameter list
+//
+// Arguments:
+// Note: There are two forms of this macro, determined at run time
+//
+// One form: (API)
+//
+// OLETRACEIN((API_ID, format_str, param1, ...))
+//
+// [API_ID] - the integeter API identifier
+// [format_str] - the format string to pass to oleprintf
+// [param1, ...] - the parameters to pass to oleprintf
+//
+// Second form (Method)
+//
+// OLETRACEIN((METHOD_ID, this_ptr, format_str, param1, ...))
+//
+// [METHOD_ID] - the integer object/method identifier
+// [this_ptr] - the this pointer of the object
+// the other args are the same as above
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+// Note: Which form of the function used is determined by the id passed.
+// object IDs have a non-zero value in the upper 16 bits,
+// API id's have a zero value in the upper 16 bits
+//----------------------------------------------------------------------------
+#define OLETRACEIN(args) _oletracein args
+#define OLETRACECMNIN(args) _oletracecmnin args
+
+//+---------------------------------------------------------------------------
+//
+// Macro: OLETRACEOUT
+//
+// Synopsis: Handle all trace-related tasks at function exit.
+// Current tasks:
+// Print out function name and return value
+//
+// Arguments: API form: OLETRACEOUT((API_ID, hr))
+//
+// [API_ID]- integer API identifier (API_xxx)
+// [hr] - HRESULT return value
+//
+// Method form: OLETRACEOUT((METHOD_ID, this, hr))
+//
+// [METHOD_ID]-integer object/method identifier
+// [this] - this pointer of object
+// [hr] - HRESULT return value
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+#define OLETRACEOUT(args) _oletraceout args
+#define OLETRACECMNOUT(args) _oletracecmnout args
+
+//+---------------------------------------------------------------------------
+//
+// Macro: OLETRACEOUTEX
+//
+// Synopsis: Handle all trace-related tasks at function exit.
+// Current tasks:
+// Print out function name and return value
+//
+// Arguments: API form: OLETRACEOUTEX((API_ID, format, result))
+//
+// [API_ID]- integer API identifier (API_xxx)
+// [format]- format string
+// [result]- return value
+//
+// Method form: OLETRACEOUTEX((METHOD_ID, this, hr))
+//
+// [METHOD_ID]-integer object/method identifier
+// [this] - this pointer of object
+// [format]- format string
+// [result]- return value
+//
+// Returns: nothing
+//
+// History: 15-Jul-95 t-stevan Created
+//
+//----------------------------------------------------------------------------
+#define OLETRACEOUTEX(args) _oletraceoutex args
+#define OLETRACECMNOUTEX(args) _oletracecmnoutex args
+
+// use this to make a nicely formatted parameter string
+#define PARAMFMT(paramstr) ( "("##paramstr")\n" )
+
+// use this for a functions which take no parameters
+#define NOPARAM (PARAMFMT(""))
+
+// use this to make a " returns %meef" format for OLETRACEOUT_
+#define RETURNFMT(str) ( " returned "##str##"\n" )
+
+// use this for a function which returns void
+#define NORETURN (RETURNFMT(""))
+
+
+void InitializeTraceInfo(); // function to load the trace info level on
+void CleanupTraceInfo(); // function to clean up the trace info process detatch
+
+
+#else // #ifdef _TRACE
+
+#define OLETRACEIN(X)
+#define OLETRACECMNIN(X)
+#define OLETRACEOUT(x)
+#define OLETRACECMNOUT(x)
+#define OLETRACEOUTEX(x)
+#define OLETRACECMNOUTEX(x)
+
+#define PARAMFMT(paramstr) ("")
+
+#define NOPARAM
+#define NORETURN
+
+#define RETURNFMT(str) ("")
+
+#define InitializeTraceInfo()
+#define CleanupTraceInfo()
+
+
+#endif // DBG==1
+
+#endif // #ifdef __TRACE_HXX__
diff --git a/private/ole32/ih/userapis.h b/private/ole32/ih/userapis.h
new file mode 100644
index 000000000..5f6806da7
--- /dev/null
+++ b/private/ole32/ih/userapis.h
@@ -0,0 +1,76 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: userapis.h
+//
+// Contents: Prototypes and macors for stack switching
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-30-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef _USERAPIS_
+#define _USERAPIS_
+
+#ifdef _CHICAGO_
+
+#undef SendMessage
+#undef ReplyMessage
+#undef CallWindowProc
+#undef DefWindowProc
+#undef PeekMessage
+#undef GetMessage
+#undef DispatchMessage
+#undef WaitMessage
+#undef DirectedYield
+#undef DialogBoxParam
+#undef DialogBoxIndirectParam
+#undef DestroyWindow
+#undef MessageBox
+#undef CreateWindowExA
+#undef CreateWindowExW
+
+// Clipboard apis
+#undef OpenClipboard
+#undef CloseClipboard
+#undef GetClipboardOwner
+#undef SetClipboardData
+#undef GetClipboardData
+#undef EnumClipboardFormats
+#undef EmptyClipboard
+#undef RegisterClipboardFormatA
+#undef GetClipboardFormatNameA
+#undef IsClipboardFormatAvailable
+
+//
+// Restore original definitions as in winuser.h
+//
+
+#define SendMessage SendMessageA
+#define CallWindowProc CallWindowProcA
+#define DefWindowProc DefWindowProcA
+#define PeekMessage PeekMessageA
+#define GetMessage GetMessageA
+#define DispatchMessage DispatchMessageA
+#define DialogBoxParam DialogBoxParamA
+#define DialogBoxIndirectParam DialogBoxIndirectParamA
+#define MessageBox MessageBoxA
+
+
+#undef DialogBox
+#define DialogBox(a,b,c,d) \
+ DialogBoxParamA(a,b,c,d, 0L)
+#undef DialogBoxIndirect
+#define DialogBoxIndirect(a,b,c,d) \
+ DialogBoxIndirectParamA(a,b,c,d,e, 0L)
+
+#endif // _CHICAGO_
+
+#endif // _USERAPIS_
+
diff --git a/private/ole32/ih/utils.h b/private/ole32/ih/utils.h
new file mode 100644
index 000000000..4ba770dec
--- /dev/null
+++ b/private/ole32/ih/utils.h
@@ -0,0 +1,1560 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// utils.h
+//
+// Contents:
+// prototypes and constants for OLE internal utility routines
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup begins
+// 11/29/93 - ChrisWe - remove signature for non-existent
+// function UtGlobalHandlCpy; moved manifest constants
+// to be with functions they are used with (OPCODE_*,
+// CONVERT_*); removed default parameters from functions;
+// replace '!' with '~' in STREAMTYPE_OTHER definition
+// 04/07/94 - AlexGo - added UtCreateStorageOnHGlobal
+//
+//-----------------------------------------------------------------------------
+
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+// We need to serialize the placeable metafile structure in the same format
+// that was used by WIN16, since RECT used LONGs under Win32.
+// We ensure that no padding is added by using the #pragma pack() calls.
+
+#pragma pack(1)
+typedef struct tagWIN16RECT
+{
+ WORD left;
+ WORD top;
+ WORD right;
+ WORD bottom;
+} WIN16RECT;
+
+typedef struct tagPLACEABLEMETAHEADER
+{
+ DWORD key; /* must be PMF_KEY */
+#define PMF_KEY 0x9ac6cdd7
+ WORD hmf; /* must be zero */
+ WIN16RECT bbox; /* bounding rectangle of the metafile */
+ WORD inch; /* # of metafile units per inch must be < 1440 */
+ /* most apps use 576 or 1000 */
+ DWORD reserved; /* must be zero */
+ WORD checksum;
+} PLACEABLEMETAHEADER;
+#pragma pack()
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtGetUNICODEData, PRIVATE INTERNAL
+//
+// Synopsis: Given a string length, and two pointers (one ANSI, one
+// OLESTR), returns the UNICODE version of whichever string
+// is valid.
+//
+// Effects: Memory is allocated on the caller's pointer for new OLESTR
+//
+// Arguments: [ulLength] -- length of string in CHARACTERS (not bytes)
+// (including terminator)
+// [szANSI] -- candidate ANSI string
+// [szOLESTR] -- candidate OLESTR string
+// [pstr] -- OLESTR OUT parameter
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failure
+// E_ANSITOUNICODE if ANSI cannot be converted to UNICODE
+//
+// Algorithm: If szOLESTR is available, a simple copy is performed
+// If szOLESTR is not available, szANSI is converted to UNICODE
+// and the result is copied.
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+// Notes: Only one of the two input strings (ANSI or UNICODE) should
+// be set on entry.
+//
+//--------------------------------------------------------------------------
+
+INTERNAL UtGetUNICODEData( ULONG, LPSTR, LPOLESTR, LPOLESTR *);
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtPutUNICODEData, PRIVATE INTERNAL
+//
+// Synopsis: Given an OLESTR and two possible buffer pointer, one ANSI
+// and the other OLESTR, this fn tries to convert the string
+// down to ANSI. If it succeeds, it allocates memory on the
+// ANSI ptr for the result. If it fails, it allocates memory
+// on the UNICODE ptr and copies the input string over. The
+// length of the final result (ANSI or UNICODE) is returned
+// in dwResultLen.
+//
+// Arguments: [ulLength] -- input length of OLESTR str
+// [str] -- the OLESTR to store
+// [pszANSI] -- candidate ANSI str ptr
+// [pszOLESTR] -- candidate OLESTR str ptr
+// [pdwResultLen] -- where to store the length of result
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+//--------------------------------------------------------------------------
+
+INTERNAL UtPutUNICODEData(
+ ULONG ulLength,
+ LPOLESTR str,
+ LPSTR * pszANSI,
+ LPOLESTR * pszOLESTR,
+ DWORD * pdwResultLen );
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtDupGlobal, internal
+//
+// Synopsis:
+// Duplicate the contents of an HGlobal into a new HGlobal. If
+// there is no allocated memory, no new global is allocated.
+//
+// Arguments:
+// [hsrc] -- the source HGLobal; need not be locked
+// [uiFlags] -- flags to be passed on to GlobalAlloc()
+//
+// Returns:
+// The new HGLOBAL, if successful, or NULL
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(HANDLE) UtDupGlobal(HANDLE hSrc, UINT uiFlags);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtIsFormatSupported, internal
+//
+// Synopsis:
+// Checks a data object to see if it will accept
+// IDataObject::SetData() and/or IDataObject::GetData() calls
+// on the specified format. The direction of transfer is specified
+// with the dwDirection flags. The function returns TRUE only
+// if all requested transfers are possible.
+//
+// Arguments:
+// [lpObj] -- the data object to check for the format
+// [dwDirection] -- a combination of values from DATADIR_*
+// [cfFormat] -- the format to look for
+//
+// Returns:
+// TRUE, if transfers of [cfFormat] are supported in [dwDirection],
+// FALSE otherwise
+//
+// Notes:
+//
+// History:
+// 11/29/93 - ChrisWe - file inspection and cleanup; noted that
+// enumerators are expected to be able to return
+// formats for multiple DATADIR_* flags
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(BOOL) UtIsFormatSupported(LPDATAOBJECT lpObj, DWORD dwDirection,
+ CLIPFORMAT cfFormat);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtDupString, internal
+//
+// Synopsis:
+// Copies the argument string into a new string allocated
+// using the task allocator
+//
+// Arguments:
+// [lpszIn] -- the string to duplicate
+//
+// Returns:
+// a pointer to a copy of [lpszIn], or NULL if the allocator
+// could not be acquired, or was out of memory
+//
+// History:
+// 11/28/93 - ChrisWe - file cleanup and inspection
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(LPOLESTR) UtDupString(LPCOLESTR lpszIn);
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtDupStringA
+//
+// Synopsis: Duplicates an ANSI string using the TASK allocator
+//
+// Effects:
+//
+// Arguments: [pszAnsi] -- the string to duplicate
+//
+// Requires:
+//
+// Returns: the newly allocated string duplicate or NULL
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 04-Jun-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+LPSTR UtDupStringA( LPCSTR pszAnsi );
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtCopyFormatEtc, internal
+//
+// Synopsis:
+// Copies a format etc, creating copies of data structures
+// pointed to inside (the target device descriptor.)
+//
+// Arguments:
+// [pFetcIn] -- pointer to the FORMATETC to copy
+// [pFetcCopy] -- pointer to where to copy the FORMATETC to
+//
+// Returns:
+// FALSE if pointed to data could not be copied because it
+// could not be allocated
+// TRUE otherwise
+//
+// Notes:
+//
+// History:
+// 11/01/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(BOOL) UtCopyFormatEtc(FORMATETC FAR* pFetcIn,
+ FORMATETC FAR* pFetcCopy);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtCompareFormatEtc, internal
+//
+// Synopsis:
+//
+// Arguments:
+// [pFetcLeft] -- pointer to a FORMATETC
+// [pFetcRight] -- pointer to a FORMATETC
+//
+// Returns:
+// UTCMPFETC_EQ is the two FORMATETCs match exactly
+// UTCMPFETC_NEQ if the two FORMATETCs do not match
+// UTCMPFETC_PARTIAL if the left FORMATETC is a subset of the
+// right: fewer aspects, null target device, or
+// fewer media
+//
+// Notes:
+//
+// History:
+// 11/01/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(int) UtCompareFormatEtc(FORMATETC FAR* pFetcLeft,
+ FORMATETC FAR* pFetcRight);
+#define UTCMPFETC_EQ 0 /* exact match */
+#define UTCMPFETC_NEQ 1 /* no match */
+#define UTCMPFETC_PARTIAL (-1) /* partial match; left is subset of right */
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtCompareTargetDevice, internal
+//
+// Synopsis:
+// Compares two target devices to see if they are the same
+//
+// Arguments:
+// [ptdLeft] -- pointer to a target device description
+// [ptdRight] -- pointer to a target device description
+//
+// Returns:
+// TRUE if the two devices are the same, FALSE otherwise
+//
+// Notes:
+//
+// History:
+// 11/01/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(BOOL) UtCompareTargetDevice(DVTARGETDEVICE FAR* ptdLeft,
+ DVTARGETDEVICE FAR* ptdRight);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtCopyStatData, internal
+//
+// Synopsis:
+// Copies the contents of one STATDATA into another, including
+// creating a copy of data pointed to, and incrementing the
+// reference count on the advise sink to reflect the copy.
+//
+// Arguments:
+// [pSDIn] -- the source STATDATA
+// [pSDCopy] -- where to copy the information to
+//
+// Returns:
+// FALSE if memory could not be allocated for the copy of
+// the target device, TRUE otherwise
+//
+// Notes:
+//
+// History:
+// 11/01/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(BOOL) UtCopyStatData(STATDATA FAR* pSDIn, STATDATA FAR* pSDCopy);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtReleaseStatData, internal
+//
+// Synopsis:
+// Release resources associated with the argument STATDATA; this
+// frees the device description within the FORMATETC, and releases
+// the advise sink, if there is one.
+//
+// Arguments:
+// [pStatData] -- The STATDATA to clean up
+//
+// Notes:
+//
+// History:
+// 11/01/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(void) UtReleaseStatData(STATDATA FAR* pStatData);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtDupPalette, internal
+//
+// Synopsis:
+// Creates a duplicate palette.
+//
+// Arguments:
+// [hpalette] -- the palette to duplicate
+//
+// Returns:
+// if successful, a handle to the duplicate palette; if any
+// allocations or calls fail during the duplication process, NULL
+//
+// History:
+// 11/29//93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(HPALETTE) UtDupPalette(HPALETTE hpalette);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtPaletteSize, internal
+//
+// Synopsis:
+// Returns the size of a color table for a palette given the
+// number of bits of color desired.
+//
+// Arguments:
+// [lpHeader] -- ptr to BITMAPINFOHEADER structure
+//
+// Returns:
+// Size in bytes of color information
+//
+// Notes:
+//
+// History:
+// 11/29/93 - ChrisWe - change bit count argument to unsigned,
+// and return value to size_t
+//
+// 07/18/94 - DavePl - Fixed for 16, 24, 32bpp DIBs
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(size_t) UtPaletteSize(BITMAPINFOHEADER *);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtFormatToTymed, internal
+//
+// Synopsis:
+// Maps a clipboard format to a medium used to transport it.
+//
+// Arguments:
+// [cf] -- the clipboard format to map
+//
+// Returns:
+// a TYMED_* value
+//
+// Notes:
+//
+// History:
+// 11/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(DWORD) UtFormatToTymed(CLIPFORMAT cf);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtQueryPictFormat, internal
+//
+// Synopsis:
+// Check to see if the argument data object supports one of
+// our preferred data formats for presentations:
+// CF_METAFILEPICT, CF_DIB, CF_BITMAP, in that order. Returns
+// TRUE, if success, and alters the given format descriptor
+// to match the supported format. The given format descriptor
+// is not altered if there is no match.
+//
+// Arguments:
+// [lpSrcDataObj] -- the data object to query
+// [lpforetc] - the format descriptor
+//
+// Returns:
+// TRUE if a preferred format is found, FALSE otherwise
+//
+// Notes:
+//
+// History:
+// 11/09/93 - ChrisWe - modified to not alter the descriptor
+// if no match is found
+// 11/09/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(BOOL) UtQueryPictFormat(LPDATAOBJECT lpSrcDataObj,
+ LPFORMATETC lpforetc);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtConvertDibToBitmap, internal
+//
+// Synopsis:
+// Converts a DIB to a bitmap, returning a new handle to the
+// bitmap. The original DIB is left untouched.
+//
+// Arguments:
+// [hDib] -- handle to the DIB to convert
+//
+// Returns:
+// if successful, and handle to the new bitmap
+//
+// Notes:
+// REVIEW, the function uses the screen DC when creating the
+// new bitmap. It may be the case that the bitmap was intended
+// for another target, in which case this may not be appropriate.
+// It may be necessary to alter this function to take a DC as
+// an argument.
+//
+// History:
+// 11/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(HBITMAP) UtConvertDibToBitmap(HANDLE hDib);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtConvertBitmapToDib, internal
+//
+// Synopsis:
+// Creates a Device Independent Bitmap capturing the content of
+// the argument bitmap.
+//
+// Arguments:
+// [hBitmap] -- Handle to the bitmap to convert
+// [hpal] -- color palette for the bitmap; may be null for
+// default stock palette
+//
+// Returns:
+// Handle to the DIB. May be null if any part of the conversion
+// failed.
+//
+// Notes:
+//
+// History:
+// 11/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(HANDLE) UtConvertBitmapToDib(HBITMAP hBitmap, HPALETTE hpal);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtGetClassId, internal
+//
+// Synopsis:
+// Attempt to find the class id of the object. First,
+// query for IOleObject, and if successful, call
+// IOleObject::GetUserClassID(). If that fails, query for
+// IPersist, and if successful, call IPersist::GetClassID.
+//
+// Arguments:
+// [lpUnk] -- pointer to an IUnknown instance
+// [lpClsid] -- pointer to where to copy the class id to
+//
+// Returns:
+// TRUE, if the class id was obtained, or FALSE otherwise
+// If unsuccessful, *[lpClsid] is set to CLSID_NULL
+//
+// Notes:
+//
+// History:
+// 11/29/93 - ChrisWe - change to return BOOL to indicate success
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(BOOL) UtGetClassID(LPUNKNOWN lpUnk, CLSID FAR* lpClsid);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtCopyTargetDevice, internal
+//
+// Synopsis:
+// Allocates a new target device description, and copies
+// the given one into it
+//
+// Arguments:
+// [ptd] -- pointer to a target device
+//
+// Returns:
+// NULL, if the no memory can be allocated
+//
+// Notes:
+//
+// History:
+// 11/01/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(DVTARGETDEVICE FAR*) UtCopyTargetDevice(DVTARGETDEVICE FAR* ptd);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtGetIconData, internal
+//
+// Synopsis:
+// Attempts to get the icon for an object.
+//
+// Arguments:
+// [lpSrcDataObj] -- The source data object
+// [rclsid] -- the class id the object is known to be
+// (may be CLSID_NULL)
+// [lpforetc] -- the format of the data to fetch
+// [lpstgmed] -- a place to return the medium it was fetched on
+//
+// Returns:
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+// REVIEW, this method seems to assume that the contents of
+// lpforetc are correct for fetching an icon. It passes this
+// on to [lpSrcDataObj]->GetData first, and if that fails,
+// calls OleGetIconOfClass, without checking the requested
+// format in lpforetc. This could fetch anything
+//
+// History:
+// 11/30/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtGetIconData(LPDATAOBJECT lpSrcDataObj, REFCLSID rclsid,
+ LPFORMATETC lpforetc, LPSTGMEDIUM lpstgmed);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtDoStreamOperation, internal
+//
+// Synopsis:
+// Iterate over the streams in [pstgSrc], performing the
+// operation indicated by [iOpCode] to those that are specified
+// by [grfAllowedStmTypes].
+//
+// Arguments:
+// [pstgSrc] -- source IStorage instance
+// [pstgDst] -- destination IStorage instance; may be null for
+// some operations (OPCODE_REMOVE)
+// [iOpCode] -- 1 value from the OPCODE_* values below
+// [grfAllowedStmTypes] -- a logical or of one or more of the
+// STREAMTYPE_* values below
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 11/30/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+STDAPI UtDoStreamOperation(LPSTORAGE pstgSrc, LPSTORAGE pstgDst,
+ int iOpCode, DWORD grfAllowedStmTypes);
+
+#define OPCODE_COPY 1 /* copy the stream from pstgSrc to pstgDst */
+#define OPCODE_REMOVE 2 /* delete the stream from pstgSrc */
+#define OPCODE_MOVE 3 /* move the stream from pstgSrc to pstgDst */
+#define OPCODE_EXCLUDEFROMCOPY 4
+ /* unimplemented, undocumented, intent unknown */
+
+#define STREAMTYPE_CONTROL 0x00000001 /* OLE 0x1 stream (REVIEW const) */
+#define STREAMTYPE_CACHE 0x00000002 /* OLE 0x2 stream (REVIEW const) */
+#define STREAMTYPE_CONTAINER 0x00000004 /* OLE 0x3 stream (REVIEW const) */
+#define STREAMTYPE_OTHER \
+ (~(STREAMTYPE_CONTROL | STREAMTYPE_CACHE | STREAMTYPE_CONTAINER))
+#define STREAMTYPE_ALL 0xFFFFFFFF /* all stream types are allowed */
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtGetPresStreamName, internal
+//
+// Synopsis:
+// Modify [lpszName] to be a presentation stream name based
+// on [iStreamNum].
+//
+// Arguments:
+// [lpszName] -- a copy of OLE_PRESENTATION_STREAM; see below
+// [iStreamNum] -- the number of the stream
+//
+// Notes:
+// The digit field of [lpszName] is always completely overwritten,
+// allowing repeated use of UtGetPresStreamName() on the same
+// string; this removes the need to repeatedly start with a fresh
+// copy of OLE_PRESENTATION_STREAM each time this is used in a
+// loop.
+//
+// The validity of the implementation depends on the values of
+// OLE_PRESENTATION_STREAM and OLE_MAX_PRES_STREAMS; if those
+// change, the implementation must change
+//
+// History:
+// 11/30/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(void)UtGetPresStreamName(LPOLESTR lpszName, int iStreamNum);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtRemoveExtraOlePresStreams, internal
+//
+// Synopsis:
+// Deletes presentation streams in [pstg] starting with the
+// presentation numbered [iStart]. All streams after that one
+// (numbered sequentially) are deleted, up to OLE_MAX_PRES_STREAMS.
+//
+// Arguments:
+// [pstg] -- the IStorage instance to operate on
+// [iStart] -- the number of the first stream to remove
+//
+// Returns:
+//
+// Notes:
+// The presentation stream names are generated with
+// UtGetPresStreamName().
+//
+// History:
+// 11/30/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(void) UtRemoveExtraOlePresStreams(LPSTORAGE pstg, int iStart);
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtCreateStorageOnHGlobal
+//
+// Synopsis: creates a storage on top of an HGlobal
+//
+// Effects:
+//
+// Arguments: [hGlobal] -- the memory on which to create the
+// storage
+// [fDeleteOnRelease] -- if TRUE, then delete the memory
+// ILockBytes once the storage is
+// released.
+// [ppStg] -- where to put the storage interface
+// [ppILockBytes] -- where to put the underlying ILockBytes,
+// maybe NULL. The ILB must be released.
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: create an ILockBytes on HGLOBAL and then create the docfile
+// on top of the ILockBytes
+//
+// History: dd-mmm-yy Author Comment
+// 07-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT UtCreateStorageOnHGlobal( HGLOBAL hGlobal, BOOL fDeleteOnRelease,
+ IStorage **ppStg, ILockBytes **ppILockBytes );
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtGetTempFileName
+//
+// Synopsis: retrieves a temporary filename (for use in GetData, TYMED_FILE
+// and temporary docfiles)
+//
+// Effects:
+//
+// Arguments: [pszPrefix] -- prefix of the temp filename
+// [pszTempName] -- buffer that will receive the temp path.
+// must be MAX_PATH or greater.
+//
+// Requires:
+//
+// Returns: HRESULT;
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: tries to get a file in the temp directory, failing that, in
+// the windows directory
+//
+// History: dd-mmm-yy Author Comment
+// 07-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT UtGetTempFileName( LPOLESTR pszPrefix, LPOLESTR pszTempName );
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtHGLOBALToStm, internal
+//
+// Synopsis:
+// Write the contents of an HGLOBAL to a stream
+//
+// Arguments:
+// [hdata] -- handle to the data to write out
+// [dwSize] -- size of the data to write out
+// [pstm] -- stream to write the data out to; on exit, the
+// stream is positioned after the written data
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 11/30/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+HRESULT UtHGLOBALtoStm(HANDLE hdata, DWORD dwSize, LPSTREAM pstm);
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtHGLOBALtoHGLOBAL, internal
+//
+// Synopsis: Copies the source HGLOBAL into the target HGLOBAL
+//
+// Effects:
+//
+// Arguments: [hGlobalSrc] -- the source HGLOBAL
+// [dwSize] -- the number of bytes to copy
+// [hGlobalTgt] -- the target HGLOBAL
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes: this function will fail if the target hglobal is not large
+// enough
+//
+//--------------------------------------------------------------------------
+
+HRESULT UtHGLOBALtoHGLOBAL( HGLOBAL hGlobalSrc, DWORD dwSize,
+ HGLOBAL hGlobalTgt);
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtHGLOBALtoStorage, internal
+//
+// Synopsis: Copies the source HGLOBAL into the target storage
+//
+// Effects:
+//
+// Arguments: [hGlobalSrc] -- the source HGLOBAL
+// [hpStg] -- the target storage
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes: this function will fail if the source HGLOBAL did not
+// originally have a storage layered on top of it.
+//
+//--------------------------------------------------------------------------
+
+HRESULT UtHGLOBALtoStorage( HGLOBAL hGlobalSrc, IStorage *pStg);
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtHGLOBALtoFile, internal
+//
+// Synopsis: Copies the source HGLOBAL into the target file
+//
+// Effects:
+//
+// Arguments: [hGlobalSrc] -- the source HGLOBAL
+// [dwSize] -- the number of bytes to copy
+// [pszFileName] -- the target file
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT UtHGLOBALtoFile( HGLOBAL hGlobalSrc, DWORD dwSize,
+ LPCOLESTR pszFileName);
+
+
+/*** Following routines can be found in convert.cpp *****/
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtGetHGLOBALFromStm, internal
+//
+// Synopsis:
+// Create a new HGLOBAL, and read [dwSize] bytes into it
+// from [lpstream].
+//
+// Arguments:
+// [lpstream] -- the stream to read the content of the new
+// HGLOBAL from; on exit, points just past the data read
+// [dwSize] -- the amount of material to read from the stream
+// [lphPres] -- pointer to where to return the new handle
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// In case of any error, the new handle is freed. If the
+// amount of material expected from [lpstream] is less than
+// [dwSize], nothing is returned.
+//
+// History:
+// 11/30/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtGetHGLOBALFromStm(LPSTREAM lpstream, DWORD dwSize,
+ HANDLE FAR* lphPres);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtGetHDIBFromDIBFileStm, internal
+//
+// Synopsis:
+// Produce a handle to a DIB from a file stream
+//
+// Arguments:
+// [pstm] -- the stream to read the DIB from; on exit, the
+// stream is positioned just past the data read
+// [lphdata] -- pointer to where to return the handle to the data
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 11/30/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtGetHDIBFromDIBFileStm(LPSTREAM pstm, HANDLE FAR* lphdata);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtGetHMFPICT, internal
+//
+// Synopsis:
+// Given a handle to a METAFILE, conjure up a handle to a
+// METAFILEPICT, based on the metafile
+//
+// Arguments:
+// [hMF] -- handle to the METAFILE
+// [fDeleteOnError] -- if TRUE, delete the METAFILE [hMF] in there
+// is any error
+// [xExt] -- the x extent of the desired METAFILEPICT
+// [yExt] -- the y extent of the desired METAFILEPICT
+//
+// Returns:
+// Handle to the new METAFILEPICT, if successful, or NULL
+//
+// Notes:
+//
+// History:
+// 11/30/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(HANDLE) UtGetHMFPICT(HMETAFILE hMF, BOOL fDeletOnError,
+ DWORD xExt, DWORD yExt);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtGetHMFFromMFStm, internal
+//
+// Synopsis:
+// Create a handle to a METAFILE, loaded with content from
+// the given stream
+//
+// Arguments:
+// [lpstream] -- the source stream to initialize the METAFILE with;
+// on exit, the stream is positioned just past the
+// data read
+// [dwSize] -- the amount of material to read from [lpstream]
+// [fConvert] -- if TRUE, tries to convert a Macintosh QuickDraw
+// file to METAFILE format
+// [lphPres] -- pointer to where to return the new handle to
+// the metafile
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// If [dwSize] is too large, and goes past the end of the
+// stream, the error causes everything allocated to be freed,
+// and nothing is returned in [lphPres].
+//
+// History:
+// 11/30/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtGetHMFFromMFStm(LPSTREAM lpstream, DWORD dwSize,
+ BOOL fConvert, HANDLE FAR* lphPres);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtGetSizeAndExtentsFromPlaceableMFStm, internal
+//
+// Synopsis:
+// Obtain the size, width, and height of the metafile stored
+// in a placeable metafile stream.
+//
+// Arguments:
+// [lpstream] -- the stream to read the placeable metafile
+// from; on exit, the stream is positioned at the
+// beginning of the metafile header, after the
+// placeable metafile header.
+// [pdwSize] -- a pointer to where to return the size of the
+// metafile; may be NULL
+// [plWidth] -- a pointer to where to return the width of the
+// metafile; may be NULL
+// [plHeight] -- a pointer to where to return the height of the
+// metafile; may be NULL
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 11/30/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtGetSizeAndExtentsFromPlaceableMFStm(LPSTREAM pstm,
+ DWORD FAR* dwSize, LONG FAR* plWidth, LONG FAR* plHeight);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtGetHMFPICTFromPlaceableMFStm, internal
+//
+// Synopsis:
+// Create a handle to a METAFILEPICT initialized from a
+// placeable METAFILE stream.
+//
+// Arguments:
+// [pstm] -- the stream to load the METAFILE from; on exit
+// points just past the METAFILE data
+// [lphdata] -- pointer to where to return the handle to the
+// new METAFILEPICT
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 11/30/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtGetHMFPICTFromPlaceableMFStm(LPSTREAM pstm, HANDLE FAR* lphdata);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtGetDibExtents, internal
+//
+// Synopsis:
+// Return the width and height of a DIB, in HIMETRIC units
+// per pixel.
+//
+// Arguments:
+// [lpbmi] -- pointer to a BITMAPINFOHEADER
+// [plWidth] -- pointer to where to return the width
+// REVIEW, this should be a DWORD
+// [plHeight] -- pointer to where to return the height
+// REVIEW, this should be a DWORD
+//
+// Notes:
+//
+// History:
+// 12/02/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(void) UtGetDibExtents(LPBITMAPINFOHEADER lpbmi,
+ LONG FAR* plWidth, LONG FAR* plHeight);
+#ifdef LATER
+FARINTERNAL_(void) UtGetDibExtents(LPBITMAPINFOHEADER lpbmi,
+ DWORD FAR* pdwWidth, DWORD FAR* pdwHeight);
+#endif
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtHDIBToDIBFileStm, internal
+//
+// Synopsis:
+// Given a handle to a DIB, write out out a DIB file stream.
+//
+// Arguments:
+// [hdata] -- handle to the DIB
+// [dwSize] -- the size of the DIB
+// [pstm] -- the stream to write the DIB out to; on exit, the
+// stream is positioned after the DIB data; the DIB
+// data is prepended with a BITMAPFILEHEADER
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 12/02/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtHDIBToDIBFileStm(HANDLE hdata, DWORD dwSize, LPSTREAM pstm);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtDIBStmToDIBFileStm, internal
+//
+// Synopsis:
+// copy convert a DIB in a stream to a DIB file stream
+//
+// Arguments:
+// [pstmDIB] -- the source DIB
+// REVIEW, what does CopyTo do to the stream pointer?
+// [dwSize] -- the size of the source DIB
+// [pstmDIBFile] -- where to write the converted DIB file stream;
+// should not be the same as [pstmDIB]; on exit, the
+// stream is positioned after the DIB file data
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 12/02/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtDIBStmToDIBFileStm(LPSTREAM pstmDIB, DWORD dwSize,
+ LPSTREAM pstmDIBFile);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtHDIBFileToOlePresStm, internal
+//
+// Synopsis:
+// Given a handle to a DIB file, write it out to a stream
+//
+// Arguments:
+// [hdata] -- the handle to the DIB file
+// [pstm] -- the stream to write it out to; on exit, the
+// stream is positioned after the written data
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// A small header with size information precedes the DIB file
+// data.
+//
+// History:
+// 12/02/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtHDIBFileToOlePresStm(HANDLE hdata, LPSTREAM pstm);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtHMFToMFStm, internal
+//
+// Synopsis:
+// Given a handle to a METAFILE, write it out to a METAFILE stream
+//
+// Arguments:
+// [lphMF] -- a *pointer* to a handle to a METAFILE
+// REVIEW, why the hell is this a pointer?
+// [dwSize] -- the size of the METAFILE
+// [lpstream] -- the stream to write the METAFILE out to; on
+// exit, the stream is positioned after the written data
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 12/02/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtHMFToMFStm(HANDLE FAR* lphMF, DWORD dwSize, LPSTREAM lpstream);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtHMFToPlaceableMFStm, internal
+//
+// Synopsis:
+// Given a handle to a METAFILE, write it to a stream as a
+// placeable METAFILE
+//
+// Arguments:
+// [lphMF] -- a *pointer* to a METAFILE handle
+// REVIEW, why the hell is this a pointer?
+// [dwSize] -- size of the METAFILE
+// [lWidth] -- width of the metafile
+// REVIEW, in what units?
+// REVIEW, why isn't this a DWORD?
+// [lHeight] -- height of the metafile
+// REVIEW, in what units?
+// REVIEW, why isn't this a DWORD?
+// [pstm] -- the stream to write the data to; on exit, the stream
+// is positioned after the written data
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 12/02/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtHMFToPlaceableMFStm(HANDLE FAR* lphMF, DWORD dwSize,
+ LONG lWidth, LONG lHeight, LPSTREAM pstm);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtNFStmToPlaceableMFStm, internal
+//
+// Synopsis:
+// Copy converts a METAFILE in a stream to a placeable METAFILE
+// in another stream.
+//
+// Arguments:
+// [pstmMF] -- the IStream instance from which to read the
+// original METAFILE, positioned at the METAFILE
+// REVIEW, where does CopyTo leave this stream pointer?
+// [dwSize] -- the size of the source METAFILE
+// [lWidth] -- the width of the source METAFILE
+// REVIEW, in what units?
+// REVIEW, why isn't this a DWORD?
+// [lHeight] -- the height of the source METAFILE
+// REVIEW, in what units?
+// REVIEW, why isn't this a DWORD?
+// [pstmPMF] -- the IStream instance to which to write the
+// placeable METAFILE; on exit, the stream is positioned
+// after the written data
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 12/02/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtMFStmToPlaceableMFStm(LPSTREAM pstmMF, DWORD dwSize,
+ LONG lWidth, LONG lHeight, LPSTREAM pstmPMF);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtWriteOlePresStmHeader, internal
+//
+// Synopsis:
+// Write out the header information for an Ole presentation stream.
+//
+// Arguments:
+// [lpstream] -- the stream to write to; on exit, the stream is
+// positioned after the header information
+// [pforetc] -- pointer to the FORMATETC for the presentation
+// data
+// [dwAdvf] -- the advise control flags for this presentation
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// This writes the clipboard information, the target device
+// information, if any, some FORMATETC data, and the advise
+// control flags.
+//
+// History:
+// 12/02/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtWriteOlePresStmHeader(LPSTREAM lppstream, LPFORMATETC pforetc,
+ DWORD dwAdvf);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtReadOlePresStmHeader, internal
+//
+// Synopsis:
+// Reads the presentation description information from an Ole
+// presentation stream, as written by
+// UtWriteOlePresStmHeader().
+//
+// Arguments:
+// [pstm] -- the IStream instance to read the presentation
+// description data from
+// [pforetc] -- pointer to the FORMATETC to initialize based
+// on data in the stream
+// [pdwAdvf] -- pointer to where to put the advise flags for
+// this presentation; may be NULL
+// [pfConvert] -- pointer to a flag that is set to TRUE if
+// the presentation will require conversion from
+// Macintosh PICT format.
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 12/02/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtReadOlePresStmHeader(LPSTREAM pstm, LPFORMATETC pforetc,
+ DWORD FAR* pdwAdvf, BOOL FAR* pfConvert);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtOlePresStmToContentsStm, internal
+//
+// Synopsis:
+// Copy the content of a presentation stream to a contents stream,
+// adjusting the format as necessary.
+//
+// Arguments:
+// [pstg] -- the IStorage instance in which the presentation
+// stream is, and in which to create the contents stream
+// [lpszPresStm] -- the name of the source presentation stream
+// [fDeletePresStm] -- flag that indicates that the presentation
+// stream should be deleted if the copy and convert is
+// successful. This is ignored if the source was
+// DVASPECT_ICON.
+// [puiStatus] -- pointer to a UINT where status bits from
+// the CONVERT_* values below may be returned.
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// The content stream is named by the constant OLE_CONTENTS_STREAM.
+//
+// History:
+// 12/05/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL UtOlePresStmToContentsStm(LPSTORAGE pstg, LPOLESTR lpszPresStm,
+ BOOL fDeletePresStm, UINT FAR* puiStatus);
+#define CONVERT_NOSOURCE 0x0001
+#define CONVERT_NODESTINATION 0x0002
+#define CONVERT_SOURCEISICON 0x0004
+
+
+FARINTERNAL UtGetHMFPICTFromMSDrawNativeStm(LPSTREAM pstm, DWORD dwSize,
+ HANDLE FAR* lphdata);
+
+FARINTERNAL UtPlaceableMFStmToMSDrawNativeStm(LPSTREAM pstmPMF,
+ LPSTREAM pstmMSDraw);
+
+FARINTERNAL UtDIBFileStmToPBrushNativeStm(LPSTREAM pstmDIBFile,
+ LPSTREAM pstmPBrush);
+
+FARINTERNAL UtContentsStmTo10NativeStm(LPSTORAGE pstg, REFCLSID rclsid,
+ BOOL fDeleteContents, UINT FAR* puiStatus);
+
+FARINTERNAL Ut10NativeStmToContentsStm(LPSTORAGE pstg, REFCLSID rclsid,
+ BOOL fDeleteSrcStm);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtGetHPRESFromNative, internal
+//
+// Synopsis:
+// Get a handle to a presentation from a native representation.
+//
+// Arguments:
+// [pstg] -- the storage in which the native content is
+// [cfFormat] -- the native format to attempt to read
+// [fOle10Native] -- attempt to read the OLE10_NATIVE_STREAM
+// stream in that format; if this is FALSE, we read the
+// OLE_CONTENTS_STREAM
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 12/05/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL_(HANDLE) UtGetHPRESFromNative(LPSTORAGE pstg,
+ CLIPFORMAT cfFormat, BOOL fOle10Native);
+
+//+-------------------------------------------------------------------------
+//
+// Function: ConvertPixelsToHIMETRIC
+//
+// Synopsis: Converts a pixel dimension to HIMETRIC units
+//
+// Effects:
+//
+// Arguments: [hdcRef] -- the reference DC
+// [ulPels] -- dimension in pixel measurement
+// [pulHIMETRIC] -- OUT param of converted HIMETRIC result
+// [tDimension] -- indicates XDIMENSION or YDIMENSION of input
+//
+// Returns: S_OK, E_FAIL
+//
+// Algorithm: screen_mm * input_pels HIMETRICS/
+// ---------------------- * / == HIMETRICS
+// screen_pels /mm
+//
+// History: dd-mmm-yy Author Comment
+// 04-Aug-94 Davepl Created
+//
+// Notes: We need to know whether the input size is in the X or
+// Y dimension, since the aspect ratio could vary
+//
+//--------------------------------------------------------------------------
+
+// This enumeration is used to indicate in which diretion a
+// dimension, when passed as a parameter, is to be relative to.
+// This is needed for our Pixel -> HIMETRIC conversion function,
+// since the aspect ratio could vary by dimension.
+
+typedef enum tagDIMENSION
+{
+ XDIMENSION = 'X',
+ YDIMENSION = 'Y'
+} DIMENSION;
+
+FARINTERNAL ConvertPixelsToHIMETRIC (HDC hdcRef,
+ ULONG lPels,
+ ULONG * pulHIMETRIC,
+ DIMENSION tDimension);
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsTaskName
+//
+// Synopsis: Determines if the passed name is the current task
+//
+// Effects:
+//
+// Arguments: [lpszIn] -- Task name
+//
+// Returns: TRUE, FALSE
+//
+// History: dd-mmm-yy Author Comment
+// 03-Mar-95 Scottsk Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+FARINTERNAL_(BOOL) IsTaskName(LPCWSTR lpszIn);
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtGetDvtd16Info
+// UtConvertDvtd16toDvtd32
+//
+// UtGetDvtd32Info
+// UtConvertDvtd32toDvtd16
+//
+// Synopsis: Utility functions for converting Ansi to Unicode DVTARGETDEVICEs
+//
+// Algorithm: UtGetDvtdXXInfo gets sizing data, which is then passed to
+// UtConvertDvtdXXtoDvtdXX to perform the conversion.
+//
+// History: 06-May-94 AlexT Created
+//
+// Notes: Here's a sample usage of these functions:
+//
+// // pdvtd16 is a Ansi DVTARGETDEVICE
+// DVTDINFO dvtdInfo;
+// DVTARGETDEVICE pdvtd32;
+//
+// hr = UtGetDvtd16Info(pdvtd16, &dvtdInfo);
+// // check hr
+// pdvtd32 = CoTaskMemAlloc(dvtdInfo.cbConvertSize);
+// // check pdvtd32
+// hr = UtConvertDvtd16toDvtd32(pdvtd16, &dvtdInfo, pdvtd32);
+// // check hr
+// // pdvtd32 now contains the converted data
+//
+//--------------------------------------------------------------------------
+
+typedef struct
+{
+ UINT cbConvertSize;
+ UINT cchDrvName;
+ UINT cchDevName;
+ UINT cchPortName;
+} DVTDINFO, *PDVTDINFO;
+
+extern "C" HRESULT UtGetDvtd16Info(DVTARGETDEVICE const UNALIGNED *pdvtd16,
+ PDVTDINFO pdvtdInfo);
+extern "C" HRESULT UtConvertDvtd16toDvtd32(DVTARGETDEVICE const UNALIGNED *pdvtd16,
+ DVTDINFO const *pdvtdInfo,
+ DVTARGETDEVICE *pdvtd32);
+extern "C" HRESULT UtGetDvtd32Info(DVTARGETDEVICE const *pdvtd32,
+ PDVTDINFO pdvtdInfo);
+extern "C" HRESULT UtConvertDvtd32toDvtd16(DVTARGETDEVICE const *pdvtd32,
+ DVTDINFO const *pdvtdInfo,
+ DVTARGETDEVICE UNALIGNED *pdvtd16);
+
+#endif // _UTILS_H
+
+
diff --git a/private/ole32/ih/utstream.h b/private/ole32/ih/utstream.h
new file mode 100644
index 000000000..e4a03dbcb
--- /dev/null
+++ b/private/ole32/ih/utstream.h
@@ -0,0 +1,205 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// utstream.h
+//
+// Contents:
+// Ole stream utility routines
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 12/07/93 - ChrisWe - file inspection and cleanup; removed
+// redeclarations of ReadStringStream, and
+// WriteStringStream which are declared in ole2sp.h;
+// made default params on StSetSize explicit; removed
+// signatures of obsolete (non-existent) atom reading and
+// writing routines
+//
+//-----------------------------------------------------------------------------
+
+#ifndef _UTSTREAM_H_
+#define _UTSTREAM_H_
+
+
+
+
+// REVIEW, isn't this obsolete now, as StWrite is?
+FARINTERNAL_(HRESULT) StRead(IStream FAR * lpstream, LPVOID lpBuf, ULONG ulLen);
+
+#define StWrite(lpstream, lpBuf, ulLen) lpstream->Write(lpBuf, ulLen, NULL)
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// StSetSize, internal
+//
+// Synopsis:
+// Sets the size of the stream, using IStream::SetSize(). Saves
+// the caller having to deal with the requisite ULARGE_INTEGER
+// parameter, by initializing one from the [dwSize] argument.
+//
+// Arguments:
+// [pstm] -- the stream to set the size of
+// [dwSize] -- the size to set
+// [fRelative] -- if TRUE, indicates that the size is [dwSize]
+// plus the current seek position in the stream; if
+// FALSE, sets [dwSize] as the absolute size
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// REVIEW, this seems crocked. When would you ever call
+// this with [fRelative] == TRUE, and a non-zero [dwSize]?
+//
+// History:
+// 12/07/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL StSetSize(LPSTREAM pstm, DWORD dwSize, BOOL fRelative);
+
+
+// REVIEW, are the the following functions necessary anymore?
+FARINTERNAL StSave10NativeData(IStorage FAR* pstgSave, HANDLE hNative,
+ BOOL fIsOle1Interop);
+
+FARINTERNAL StRead10NativeData(IStorage FAR* pstgSave, HANDLE FAR *phNative);
+
+FARINTERNAL StSave10ItemName(IStorage FAR* pstg, LPCSTR szItemName);
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CStmBuf, Base class.
+//
+// Synopsis: Internal buffered Streams.
+//
+// Interfaces: CStmBuf - Constructor.
+// ~CStmBuf - Destructor.
+// Release - Release interface (used with OpenStream).
+//
+// History: 20-Feb-95 KentCe Created.
+//
+// Notes: This is a simple buffered class for internal use only.
+//
+//----------------------------------------------------------------------------
+class CStmBuf
+{
+public:
+ CStmBuf();
+ ~CStmBuf();
+
+protected:
+ IStream * m_pStm; // Stream Interface to read/write.
+
+ BYTE m_aBuffer[256]; // Small read/write buffer.
+
+ PBYTE m_pBuffer; // Pointer into read/write buffer.
+ ULONG m_cBuffer; // Count of characters in read/write buffer.
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CStmBufRead
+//
+// Synopsis: Internal buffered read of Streams.
+//
+// Interfaces: Init - Defines stream to read.
+// OpenStream - Opens a stream for reading.
+// Read - Read from the stream.
+// ReadLong - Read a long value from the stream.
+// Release - Release interface (used with OpenStream).
+//
+// History: 20-Feb-95 KentCe Created.
+//
+// Notes: This is a simple buffered read class for internal use only.
+//
+//----------------------------------------------------------------------------
+class CStmBufRead : public CStmBuf
+{
+public:
+ void Init(IStream * pstm);
+ HRESULT OpenStream(IStorage * pstg, const OLECHAR * pwcsName);
+ HRESULT Read(PVOID pBuf, ULONG cBuf);
+ HRESULT ReadLong(LONG * plValue);
+ void Release();
+
+private:
+ void Reset(void);
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CStmBufWrite
+//
+// Synopsis: Internal buffered write of Streams.
+//
+// Interfaces: Init - Defines stream to write.
+// OpenOrCreateStream - Opens/Creates a stream for writing.
+// CreateStream - Creates a stream for writing.
+// Write - Write to the stream.
+// WriteLong - Write a long value to the stream.
+// Flush - Flush buffer to the disk subsystem.
+// Release - Release interface.
+//
+// History: 20-Feb-95 KentCe Created.
+//
+// Notes: This is a simple buffered write class for internal use only.
+//
+//----------------------------------------------------------------------------
+class CStmBufWrite : public CStmBuf
+{
+public:
+ void Init(IStream * pstm);
+ HRESULT OpenOrCreateStream(IStorage * pstg, const OLECHAR * pwcsName);
+ HRESULT CreateStream(IStorage * pstg, const OLECHAR * pwcsName);
+ HRESULT Write(void const * pBuf, ULONG cBuf);
+ HRESULT WriteLong(LONG lValue);
+ HRESULT Flush(void);
+ void Release();
+
+private:
+ void Reset(void);
+};
+
+
+//
+// The following was moved from the ole2sp.h file to keep stream related API's
+// in one place.
+//
+
+// Utility function not in the spec; in ole2.dll.
+// Read and write length-prefixed strings. Open/Create stream.
+// ReadStringStream does allocation, returns length of
+// required buffer (strlen + 1 for terminating null)
+
+STDAPI ReadStringStream( CStmBufRead & StmRead, LPOLESTR FAR * ppsz );
+STDAPI WriteStringStream( CStmBufWrite & StmWrite, LPCOLESTR psz );
+STDAPI OpenOrCreateStream( IStorage FAR * pstg, const OLECHAR FAR * pwcsName,
+ IStream FAR* FAR* ppstm);
+
+//
+// The following versions of StringStream are used with ANSI data
+//
+STDAPI ReadStringStreamA( CStmBufRead & StmRead, LPSTR FAR * ppsz );
+
+
+// read and write ole control stream (in ole2.dll)
+STDAPI WriteOleStg (LPSTORAGE pstg, IOleObject FAR* pOleObj,
+ DWORD dwReserved, LPSTREAM FAR* ppstmOut);
+STDAPI ReadOleStg (LPSTORAGE pstg, DWORD FAR* pdwFlags,
+ DWORD FAR* pdwOptUpdate, DWORD FAR* pdwReserved,
+ LPMONIKER FAR* ppmk, LPSTREAM FAR* pstmOut);
+STDAPI ReadM1ClassStm(LPSTREAM pstm, CLSID FAR* pclsid);
+STDAPI WriteM1ClassStm(LPSTREAM pstm, REFCLSID rclsid);
+STDAPI ReadM1ClassStmBuf(CStmBufRead & StmRead, CLSID FAR* pclsid);
+STDAPI WriteM1ClassStmBuf(CStmBufWrite & StmWrite, REFCLSID rclsid);
+
+#endif // _UTSTREAM_H
diff --git a/private/ole32/ih/valid.h b/private/ole32/ih/valid.h
new file mode 100644
index 000000000..73dcd51c3
--- /dev/null
+++ b/private/ole32/ih/valid.h
@@ -0,0 +1,323 @@
+#ifndef __IH_VALID__H__
+#define __IH_VALID__H__
+
+#if DBG==1 && defined(WIN32) && !defined(_CHICAGO_)
+#define VDATEHEAP() if( !HeapValidate(GetProcessHeap(),0,0)){ DebugBreak();}
+#else
+#define VDATEHEAP()
+#endif // DBG==1 && defined(WIN32) && !defined(_CHICAGO_)
+
+#define IsValidPtrIn(pv,cb) ((pv == NULL) || !IsBadReadPtr ((pv),(cb)))
+#define IsValidReadPtrIn(pv,cb) (!IsBadReadPtr ((pv),(cb)))
+#define IsValidPtrOut(pv,cb) (!IsBadWritePtr((pv),(cb)))
+
+STDAPI_(BOOL) IsValidInterface( void FAR* pv );
+
+
+#if DBG==1
+// for performance, do not do in retail builds
+STDAPI_(BOOL) IsValidIid( REFIID riid );
+#else
+#define IsValidIid(x) (TRUE)
+#endif
+
+#ifdef _DEBUG
+
+DECLARE_DEBUG(VDATE);
+
+#define VdateAssert(exp, msg) \
+ VDATEInlineDebugOut( DEB_FORCE, "%s:%s; File: %s Line: %d\n", #exp, msg, __FILE__, __LINE__ )
+
+//** POINTER IN validation macros:
+#define VDATEPTRIN( pv, TYPE ) \
+ if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (VdateAssert(pv, "Invalid in ptr"),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTRIN( pv, TYPE, retval) \
+ if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (VdateAssert(pv, "Invalid in ptr"), retval)
+#define VOID_VDATEPTRIN( pv, TYPE ) \
+ if (!IsValidPtrIn( (pv), sizeof(TYPE))) {\
+ VdateAssert(pv, "Invalid in ptr"); return; }
+
+//** POINTER IN validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define VDATEPTRIN_LABEL(pv, TYPE, label, retVar) \
+ if (!IsValidPtrIn((pv), sizeof(TYPE))) \
+ { retVar = (VdateAssert(pv, "Invalid in ptr"), ResultFromScode(E_INVALIDARG)); \
+ goto label; }
+#define GEN_VDATEPTRIN_LABEL(pv, TYPE, retval, label, retVar) \
+ if (!IsValidPtrIn((pv), sizeof(TYPE))) \
+ { retVar = (VdateAssert(pv, "Invalid in ptr"), retval); \
+ goto label; }
+#define VOID_VDATEPTRIN_LABEL(pv, TYPE, label) \
+ if (!IsValidPtrIn((pv), sizeof(TYPE))) \
+ { VdateAssert(pv, "Invalid in ptr"); goto label; }
+
+
+//** READ POINTER IN validation macros:
+#define VDATEREADPTRIN( pv, TYPE ) \
+ if (!IsValidReadPtrIn( (pv), sizeof(TYPE))) \
+ return (VdateAssert(pv,"Invalid in read ptr"),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEREADPTRIN( pv, TYPE, retval) \
+ if (!IsValidReadPtrIn( (pv), sizeof(TYPE))) \
+ return (VdateAssert(pv,"Invalid in read ptr"), retval)
+#define VOID_VDATEREADPTRIN( pv, TYPE ) \
+ if (!IsValidReadPtrIn( (pv), sizeof(TYPE))) {\
+ VdateAssert(pv,"Invalid in read ptr"); return; }
+
+//** READ POINTER IN validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define VDATEREADPTRIN_LABEL(pv, TYPE, label, retVar) \
+ if (!IsValidReadPtrIn((pv), sizeof(TYPE))) \
+ { retVar = (VdateAssert(pv, "Invalid in read ptr"), ResultFromScode(E_INVALIDARG)); \
+ goto label; }
+#define GEN_VDATEREADPTRIN_LABEL(pv, TYPE, retval, label, retVar) \
+ if (!IsValidReadPtrIn((pv), sizeof(TYPE))) \
+ { retVar = (VdateAssert(pv, "Invalid in read ptr"), retval); \
+ goto label; }
+#define VOID_VDATEREADPTRIN_LABEL(pv, TYPE, label) \
+ if (!IsValidReadPtrIn((pv), sizeof(TYPE))) \
+ { VdateAssert(pv, "Invalid in read ptr"); goto label; }
+
+//** READ POINTER IN validation macros for single entry/single exit functions
+//** uses a goto instead of return and a byte count instead of a TYPE
+#define VDATESIZEREADPTRIN_LABEL(pv, cb, label, retVar) \
+ if (!IsValidReadPtrIn((pv), cb)) \
+ { retVar = (VdateAssert(pv, "Invalid in read ptr"), ResultFromScode(E_INVALIDARG)); \
+ goto label; }
+#define GEN_VDATESIZEREADPTRIN_LABEL(pv, cb, retval, label, retVar) \
+ if (!IsValidReadPtrIn((pv), cb)) \
+ { retVar = (VdateAssert(pv, "Invalid in read ptr"), retval); \
+ goto label; }
+#define VOID_VDATESIZEREADPTRIN_LABEL(pv, cb, label) \
+ if (!IsValidReadPtrIn((pv), cb)) \
+ { VdateAssert(pv, "Invalid in read ptr"); goto label; }
+
+
+//** POINTER OUT validation macros:
+#define VDATEPTROUT( pv, TYPE ) \
+ if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (VdateAssert(pv,"Invalid out ptr"),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTROUT( pv, TYPE, retval ) \
+ if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (VdateAssert(pv,"Invalid out ptr"), retval)
+
+//** POINTER OUT validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define VDATEPTROUT_LABEL( pv, TYPE, label, retVar ) \
+ if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ { retVar = (VdateAssert(pv,"Invalid out ptr"),ResultFromScode(E_INVALIDARG)); \
+ goto label; }
+#define GEN_VDATEPTROUT_LABEL( pv, TYPE, retval, label, retVar ) \
+ if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ { retVar = (VdateAssert(pv,"Invalid out ptr"),retval); \
+ goto label; }
+
+//** POINTER OUT validation macros for single entry/single exit functions
+//** uses a goto instead of return and a byte count instead of a TYPE
+#define VDATESIZEPTROUT_LABEL(pv, cb, label, retVar) \
+ if (!IsValidPtrOut((pv), cb)) \
+ { retVar = (VdateAssert(pv, "Invalid out ptr"), ResultFromScode(E_INVALIDARG)); \
+ goto label; }
+#define GEN_VDATESIZEPTROUT_LABEL(pv, cb, retval, label, retVar) \
+ if (!IsValidPtrOut((pv), cb)) \
+ { retVar = (VdateAssert(pv, "Invalid out ptr"), retval); \
+ goto label; }
+
+
+//** POINTER is NULL validation macros
+#define VDATEPTRNULL_LABEL(pv, label, retVar) \
+ if ((pv) != NULL) \
+ { retVar = (VdateAssert(pv, "Ptr should be NULL"), ResultFromScode(E_INVALIDARG)); \
+ goto label; }
+#define GEN_VDATEPTRNULL_LABEL(pv, retval, label, retVar) \
+ if ((pv) != NULL) \
+ { retVar = (VdateAssert(pv, "Ptr should be NULL"), retval); \
+ goto label; }
+
+//** INTERFACE validation macro:
+#define GEN_VDATEIFACE( pv, retval ) \
+ if (!IsValidInterface(pv)) \
+ return (VdateAssert(pv,"Invalid interface"), retval)
+#define VDATEIFACE( pv ) \
+ if (!IsValidInterface(pv)) \
+ return (VdateAssert(pv,"Invalid interface"),ResultFromScode(E_INVALIDARG))
+#define VOID_VDATEIFACE( pv ) \
+ if (!IsValidInterface(pv)) {\
+ VdateAssert(pv,"Invalid interface"); return; }
+
+//** INTERFACE validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define GEN_VDATEIFACE_LABEL( pv, retval, label, retVar ) \
+ if (!IsValidInterface(pv)) \
+ { retVar = (VdateAssert(pv,"Invalid interface"),retval); \
+ goto label; }
+#define VDATEIFACE_LABEL( pv, label, retVar ) \
+ if (!IsValidInterface(pv)) \
+ { retVar = (VdateAssert(pv,"Invalid interface"),ResultFromScode(E_INVALIDARG)); \
+ goto label; }
+#define VOID_VDATEIFACE_LABEL( pv, label ) \
+ if (!IsValidInterface(pv)) {\
+ VdateAssert(pv,"Invalid interface"); goto label; }
+
+//** INTERFACE ID validation macro:
+// Only do this in debug build
+#define VDATEIID( iid ) if (!IsValidIid( iid )) \
+ return (VdateAssert(iid,"Invalid iid"),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEIID( iid, retval ) if (!IsValidIid( iid )) {\
+ VdateAssert(iid,"Invalid iid"); return retval; }
+
+//** INTERFACE ID validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define VDATEIID_LABEL( iid, label, retVar ) if (!IsValidIid( iid )) \
+ {retVar = (VdateAssert(iid,"Invalid iid"),ResultFromScode(E_INVALIDARG)); \
+ goto label; }
+#define GEN_VDATEIID_LABEL( iid, retval, label, retVar ) if (!IsValidIid( iid )) {\
+ VdateAssert(iid,"Invalid iid"); retVar = retval; goto label; }
+
+
+#else // _DEBUG
+
+
+#define VdateAssert(exp, msg) ((void)0)
+
+// --assertless macros for non-debug case
+//** POINTER IN validation macros:
+#define VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTRIN( pv, TYPE, retval ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (retval)
+#define VOID_VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) {\
+ return; }
+
+//** POINTER IN validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define VDATEPTRIN_LABEL(pv, TYPE, label, retVar) \
+ if (!IsValidPtrIn((pv), sizeof(TYPE))) \
+ { retVar = ResultFromScode(E_INVALIDARG); \
+ goto label; }
+#define GEN_VDATEPTRIN_LABEL(pv, TYPE, retval, label, retVar) \
+ if (!IsValidPtrIn((pv), sizeof(TYPE))) \
+ { retVar = retval; \
+ goto label; }
+#define VOID_VDATEPTRIN_LABEL(pv, TYPE, label) \
+ if (!IsValidPtrIn((pv), sizeof(TYPE))) \
+ { goto label; }
+
+//** POINTER IN validation macros:
+#define VDATEREADPTRIN( pv, TYPE ) if (!IsValidReadPtrIn( (pv), sizeof(TYPE))) \
+ return (ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEREADPTRIN( pv, TYPE, retval ) if (!IsValidReadPtrIn( (pv), sizeof(TYPE))) \
+ return (retval)
+#define VOID_VDATEREADPTRIN( pv, TYPE ) if (!IsValidReadPtrIn( (pv), sizeof(TYPE))) {\
+ return; }
+
+//** POINTER IN validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define VDATEREADPTRIN_LABEL(pv, TYPE, label, retVar) \
+ if (!IsValidReadPtrIn((pv), sizeof(TYPE))) \
+ { retVar = ResultFromScode(E_INVALIDARG); \
+ goto label; }
+#define GEN_VDATEREADPTRIN_LABEL(pv, TYPE, retval, label, retVar) \
+ if (!IsValidReadPtrIn((pv), sizeof(TYPE))) \
+ { retVar = retval; \
+ goto label; }
+#define VOID_VDATEREADPTRIN_LABEL(pv, TYPE, label) \
+ if (!IsValidReadPtrIn((pv), sizeof(TYPE))) \
+ { goto label; }
+
+//** READ POINTER IN validation macros for single entry/single exit functions
+//** uses a goto instead of return and a byte count instead of a TYPE
+#define VDATESIZEREADPTRIN_LABEL(pv, cb, label, retVar) \
+ if (!IsValidReadPtrIn((pv), cb)) \
+ { retVar = ResultFromScode(E_INVALIDARG); \
+ goto label; }
+#define GEN_VDATESIZEREADPTRIN_LABEL(pv, cb, retval, label, retVar) \
+ if (!IsValidReadPtrIn((pv), cb)) \
+ { retVar = retval; \
+ goto label; }
+#define VOID_VDATESIZEREADPTRIN_LABEL(pv, cb, label) \
+ if (!IsValidReadPtrIn((pv), cb)) \
+ { goto label; }
+
+
+//** POINTER OUT validation macros:
+#define VDATEPTROUT( pv, TYPE ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (ResultFromScode(E_INVALIDARG))
+
+#define GEN_VDATEPTROUT( pv, TYPE, retval ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (retval)
+
+//** POINTER OUT validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define VDATEPTROUT_LABEL( pv, TYPE, label, retVar ) \
+ if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ { retVar = ResultFromScode(E_INVALIDARG); \
+ goto label; }
+#define GEN_VDATEPTROUT_LABEL( pv, TYPE, retval, label, retVar ) \
+ if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ { retVar = retval; \
+ goto label; }
+
+//** POINTER OUT validation macros for single entry/single exit functions
+//** uses a goto instead of return and a byte count instead of a TYPE
+#define VDATESIZEPTROUT_LABEL(pv, cb, label, retVar) \
+ if (!IsValidPtrOut((pv), cb)) \
+ { retVar = ResultFromScode(E_INVALIDARG); \
+ goto label; }
+#define GEN_VDATESIZEPTROUT_LABEL(pv, cb, retval, label, retVar) \
+ if (!IsValidPtrOut((pv), cb)) \
+ { retVar = retval; \
+ goto label; }
+
+
+//** POINTER is NULL validation macros
+#define VDATEPTRNULL_LABEL(pv, label, retVar) \
+ if ((pv) != NULL) \
+ { retVar = ResultFromScode(E_INVALIDARG); \
+ goto label; }
+#define GEN_VDATEPTRNULL_LABEL(pv, retval, label, retVar) \
+ if ((pv) != NULL) \
+ { retVar = retval; \
+ goto label; }
+
+//** INTERFACE validation macro:
+#define VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return (ResultFromScode(E_INVALIDARG))
+#define VOID_VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return;
+#define GEN_VDATEIFACE( pv, retval ) if (!IsValidInterface(pv)) \
+ return (retval)
+
+//** INTERFACE validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define GEN_VDATEIFACE_LABEL( pv, retval, label, retVar ) \
+ if (!IsValidInterface(pv)) \
+ { retVar = retval; \
+ goto label; }
+#define VDATEIFACE_LABEL( pv, label, retVar ) \
+ if (!IsValidInterface(pv)) \
+ { retVar = ResultFromScode(E_INVALIDARG); \
+ goto label; }
+#define VOID_VDATEIFACE_LABEL( pv, label ) \
+ if (!IsValidInterface(pv)) {\
+ goto label; }
+
+//** INTERFACE ID validation macro:
+// do not do in retail build. This code USED to call a bogus version of
+// IsValidIID that did no work. Now we are faster and no less stable than before.
+#define VDATEIID( iid ) ((void)0)
+#define GEN_VDATEIID( iid, retval ) ((void)0);
+
+//** INTERFACE ID validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define VDATEIID_LABEL( iid, label, retVar ) if (!IsValidIid( iid )) \
+ {retVar = ResultFromScode(E_INVALIDARG); \
+ goto label; }
+#define GEN_VDATEIID_LABEL( iid, retval, label, retVar ) if (!IsValidIid( iid )) {\
+ retVar = retval; goto label; }
+
+#endif
+
+#endif // __IH_VALID_H__
+
diff --git a/private/ole32/ih/verole.h b/private/ole32/ih/verole.h
new file mode 100644
index 000000000..17149e129
--- /dev/null
+++ b/private/ole32/ih/verole.h
@@ -0,0 +1,5 @@
+#define rmj 1
+#define rmm 824
+#define rup 1
+#define szVerName ""
+#define szVerUser "kevinro"
diff --git a/private/ole32/ih/widewrap.h b/private/ole32/ih/widewrap.h
new file mode 100644
index 000000000..f01dda088
--- /dev/null
+++ b/private/ole32/ih/widewrap.h
@@ -0,0 +1,783 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1993.
+//
+// File: widewrap.h
+//
+// Contents: Wrapper functions for Win32c API used by 32-bit OLE 2
+//
+// History: 12-27-93 ErikGav Created
+// 06-14-94 KentCe Various Chicago build fixes.
+//
+//----------------------------------------------------------------------------
+
+#ifndef _WIDEWRAP_H_
+#define _WIDEWRAP_H_
+
+#ifndef RC_INVOKED
+#pragma message ("INCLUDING WIDEWRAP.H from " __FILE__)
+#endif /* RC_INVOKED */
+
+#ifdef _CHICAGO_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef WNDCLASS
+#define WNDCLASS WNDCLASSW
+#define WNDCLASST WNDCLASSA
+
+#undef STARTUPINFO
+#define STARTUPINFO STARTUPINFOW
+
+#undef WIN32_FIND_DATA
+#define WIN32_FIND_DATA WIN32_FIND_DATAW
+
+HANDLE
+WINAPI
+CreateFileX(
+ LPCWSTR lpFileName,
+ DWORD dwDesiredAccess,
+ DWORD dwShareMode,
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ DWORD dwCreationDisposition,
+ DWORD dwFlagsAndAttributes,
+ HANDLE hTemplateFile
+ );
+
+#undef CreateFile
+#define CreateFile CreateFileX
+#define CreateFileT CreateFileA
+
+BOOL
+WINAPI
+DeleteFileX(
+ LPCWSTR lpFileName
+ );
+
+#undef DeleteFile
+#define DeleteFile DeleteFileX
+#define DeleteFileT DeleteFileA
+
+UINT
+WINAPI
+RegisterClipboardFormatX(
+ LPCWSTR lpszFormat);
+
+#undef RegisterClipboardFormat
+#define RegisterClipboardFormat RegisterClipboardFormatX
+#define RegisterClipboardFormatT RegisterClipboardFormatA
+
+int
+WINAPI
+GetClipboardFormatNameX(
+ UINT format,
+ LPWSTR lpszFormatName,
+ int cchMaxCount);
+
+#undef GetClipboardFormatName
+#define GetClipboardFormatName GetClipboardFormatNameX
+#define GetClipboardFormatNameT GetClipboardFormatNameA
+
+LONG
+APIENTRY
+RegOpenKeyX (
+ HKEY hKey,
+ LPCWSTR lpSubKey,
+ PHKEY phkResult
+ );
+
+#undef RegOpenKey
+#define RegOpenKey RegOpenKeyX
+#define RegOpenKeyT RegOpenKeyA
+
+LONG
+APIENTRY
+RegQueryValueX (
+ HKEY hKey,
+ LPCWSTR lpSubKey,
+ LPWSTR lpValue,
+ PLONG lpcbValue
+ );
+
+#undef RegQueryValue
+#define RegQueryValue RegQueryValueX
+#define RegQueryValueT RegQueryValueA
+LONG
+APIENTRY
+RegSetValueX (
+ HKEY hKey,
+ LPCWSTR lpSubKey,
+ DWORD dwType,
+ LPCWSTR lpData,
+ DWORD cbData
+ );
+
+#undef RegSetValue
+#define RegSetValue RegSetValueX
+#define RegSetValueT RegSetValueA
+
+UINT
+WINAPI
+RegisterWindowMessageX(
+ LPCWSTR lpString);
+
+#undef RegisterWindowMessage
+#define RegisterWindowMessage RegisterWindowMessageX
+#define RegisterWindowMessageT RegisterWindowMessageA
+
+LONG
+APIENTRY
+RegOpenKeyExX (
+ HKEY hKey,
+ LPCWSTR lpSubKey,
+ DWORD ulOptions,
+ REGSAM samDesired,
+ PHKEY phkResult
+ );
+
+#undef RegOpenKeyEx
+#define RegOpenKeyEx RegOpenKeyExX
+#define RegOpenKeyExT RegOpenKeyExA
+
+LONG
+APIENTRY
+RegQueryValueExX (
+ HKEY hKey,
+ LPWSTR lpValueName,
+ LPDWORD lpReserved,
+ LPDWORD lpType,
+ LPBYTE lpData,
+ LPDWORD lpcbData
+ );
+
+#undef RegQueryValueEx
+#define RegQueryValueEx RegQueryValueExX
+#define RegQueryValueExT RegQueryValueExA
+
+HWND
+WINAPI
+CreateWindowExX(
+ DWORD dwExStyle,
+ LPCWSTR lpClassName,
+ LPCWSTR lpWindowName,
+ DWORD dwStyle,
+ int X,
+ int Y,
+ int nWidth,
+ int nHeight,
+ HWND hWndParent ,
+ HMENU hMenu,
+ HINSTANCE hInstance,
+ LPVOID lpParam);
+
+#undef CreateWindowEx
+#define CreateWindowEx CreateWindowExX
+#define CreateWindowExT CreateWindowExA
+
+ATOM
+WINAPI
+RegisterClassX(
+ CONST WNDCLASSW *lpWndClass);
+
+#undef RegisterClass
+#define RegisterClass RegisterClassX
+#define RegisterClassT RegisterClassA
+
+BOOL
+WINAPI
+UnregisterClassX(
+ LPCWSTR lpClassName,
+ HINSTANCE hInstance);
+
+#undef UnregisterClass
+#define UnregisterClass UnregisterClassX
+#define UnregisterClassT UnregisterClassA
+
+int WINAPIV wsprintfX(LPWSTR pwszOut, LPCWSTR pwszFormat, ...);
+
+#undef wsprintf
+#define wsprintf wsprintfX
+#define wsprintfT wsprintfA
+
+HWND
+WINAPI
+CreateWindowX(
+ LPCWSTR lpClassName,
+ LPCWSTR lpWindowName,
+ DWORD dwStyle,
+ int X,
+ int Y,
+ int nWidth,
+ int nHeight,
+ HWND hWndParent ,
+ HMENU hMenu,
+ HINSTANCE hInstance,
+ LPVOID lpParam);
+
+#undef CreateWindow
+#define CreateWindow CreateWindowX
+#define CreateWindowT CreateWindowA
+
+HANDLE
+WINAPI
+GetPropX(
+ HWND hWnd,
+ LPCWSTR lpString);
+
+#undef GetProp
+#define GetProp GetPropX
+#define GetPropT GetPropA
+
+BOOL
+WINAPI
+SetPropX(
+ HWND hWnd,
+ LPCWSTR lpString,
+ HANDLE hData);
+
+#undef SetProp
+#define SetProp SetPropX
+#define SetPropT SetPropA
+
+HANDLE
+WINAPI
+RemovePropX(
+ HWND hWnd,
+ LPCWSTR lpString);
+
+#undef RemoveProp
+#define RemoveProp RemovePropX
+#define RemovePropT RemovePropA
+
+UINT
+WINAPI
+GetProfileIntX(
+ LPCWSTR lpAppName,
+ LPCWSTR lpKeyName,
+ INT nDefault
+ );
+
+#undef GetProfileInt
+#define GetProfileInt GetProfileIntX
+#define GetProfileIntT GetProfileIntA
+
+ATOM
+WINAPI
+GlobalAddAtomX(
+ LPCWSTR lpString
+ );
+
+#undef GlobalAddAtom
+#define GlobalAddAtom GlobalAddAtomX
+#define GlobalAddAtomT GlobalAddAtomA
+
+UINT
+WINAPI
+GlobalGetAtomNameX(
+ ATOM nAtom,
+ LPWSTR lpBuffer,
+ int nSize
+ );
+
+#undef GlobalGetAtomName
+#define GlobalGetAtomName GlobalGetAtomNameX
+#define GlobalGetAtomNameT GlobalGetAtomNameA
+
+DWORD
+WINAPI
+GetModuleFileNameX(
+ HMODULE hModule,
+ LPWSTR lpFilename,
+ DWORD nSize
+ );
+
+#undef GetModuleFileName
+#define GetModuleFileName GetModuleFileNameX
+#define GetModuleFileNameT GetModuleFileNameA
+
+LPWSTR
+WINAPI
+CharPrevX(
+ LPCWSTR lpszStart,
+ LPCWSTR lpszCurrent);
+
+#undef CharPrev
+#define CharPrev CharPrevX
+#define CharPrevT CharPrevA
+
+HFONT WINAPI CreateFontX(int, int, int, int, int, DWORD,
+ DWORD, DWORD, DWORD, DWORD, DWORD,
+ DWORD, DWORD, LPCWSTR);
+#undef CreateFont
+#define CreateFont CreateFontX
+#define CreateFontT CreateFontA
+
+HMODULE
+WINAPI
+LoadLibraryX(
+ LPCWSTR lpLibFileName
+ );
+
+#undef LoadLibrary
+#define LoadLibrary LoadLibraryX
+#define LoadLibraryT LoadLibraryA
+
+HMODULE
+WINAPI
+LoadLibraryExX(
+ LPCWSTR lpLibFileName,
+ HANDLE hFile,
+ DWORD dwFlags
+ );
+
+#undef LoadLibraryEx
+#define LoadLibraryEx LoadLibraryExX
+#define LoadLibraryExT LoadLibraryExA
+
+LONG
+APIENTRY
+RegDeleteKeyX (
+ HKEY hKey,
+ LPCWSTR lpSubKey
+ );
+
+#undef RegDeleteKey
+#define RegDeleteKey RegDeleteKeyX
+#define RegDeleteKeyT RegDeleteKeyA
+
+#undef RpcStringBindingCompose
+#define RpcStringBindingCompose RpcStringBindingComposeW
+
+#undef RpcBindingFromStringBinding
+#define RpcBindingFromStringBinding RpcBindingFromStringBindingW
+
+#undef RpcStringFree
+#define RpcStringFree RpcStringFreeW
+
+BOOL
+WINAPI
+CreateProcessX(
+ LPCWSTR lpApplicationName,
+ LPWSTR lpCommandLine,
+ LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ BOOL bInheritHandles,
+ DWORD dwCreationFlags,
+ LPVOID lpEnvironment,
+ LPCWSTR lpCurrentDirectory,
+ LPSTARTUPINFOW lpStartupInfo,
+ LPPROCESS_INFORMATION lpProcessInformation
+ );
+
+#undef CreateProcess
+#define CreateProcess CreateProcessX
+#define CreateProcessT CreateProcessA
+
+LONG
+APIENTRY
+RegEnumKeyExX (
+ HKEY hKey,
+ DWORD dwIndex,
+ LPWSTR lpName,
+ LPDWORD lpcbName,
+ LPDWORD lpReserved,
+ LPWSTR lpClass,
+ LPDWORD lpcbClass,
+ PFILETIME lpftLastWriteTime
+ );
+
+#undef RegEnumKeyEx
+#define RegEnumKeyEx RegEnumKeyExX
+#define RegEnumKeyExT RegEnumKeyExA
+
+#undef RpcServerUseProtseqEp
+#define RpcServerUseProtseqEp RpcServerUseProtseqEpW
+
+BOOL
+WINAPI
+AppendMenuX(
+ HMENU hMenu,
+ UINT uFlags,
+ UINT uIDNewItem,
+ LPCWSTR lpNewItem
+ );
+
+#undef AppendMenu
+#define AppendMenu AppendMenuX
+#define AppendMenuT AppendMenuA
+
+HANDLE
+WINAPI
+OpenEventX(
+ DWORD dwDesiredAccess,
+ BOOL bInheritHandle,
+ LPCWSTR lpName
+ );
+
+#undef OpenEvent
+#define OpenEvent OpenEventX
+#define OpenEventT OpenEventA
+
+HANDLE
+WINAPI
+CreateEventX(
+ LPSECURITY_ATTRIBUTES lpEventAttributes,
+ BOOL bManualReset,
+ BOOL bInitialState,
+ LPCWSTR lpName
+ );
+
+#undef CreateEvent
+#define CreateEvent CreateEventX
+#define CreateEventT CreateEventA
+
+UINT
+WINAPI
+GetDriveTypeX(
+ LPCWSTR lpRootPathName
+ );
+
+#undef GetDriveType
+#define GetDriveType GetDriveTypeX
+#define GetDriveTypeT GetDriveTypeA
+
+DWORD
+WINAPI
+GetFileAttributesX(
+ LPCWSTR lpFileName
+ );
+
+#undef GetFileAttributes
+#define GetFileAttributes GetFileAttributesX
+#define GetFileAttributesT GetFileAttributesA
+
+LONG
+APIENTRY
+RegEnumKeyX (
+ HKEY hKey,
+ DWORD dwIndex,
+ LPWSTR lpName,
+ DWORD cbName
+ );
+
+#undef RegEnumKey
+#define RegEnumKey RegEnumKeyX
+#define RegEnumKeyT RegEnumKeyA
+
+HANDLE
+WINAPI
+FindFirstFileX(
+ LPCWSTR lpFileName,
+ LPWIN32_FIND_DATAW lpFindFileData
+ );
+
+#undef FindFirstFile
+#define FindFirstFile FindFirstFileX
+#define FindFirstFileT FindFirstFileA
+
+#undef RegisterProtseq
+#define RegisterProtseq RegisterProtseqW
+
+#undef RpcStringBindingParse
+#define RpcStringBindingParse RpcStringBindingParseW
+
+#undef RpcNetworkIsProtseqValid
+#define RpcNetworkIsProtseqValid RpcNetworkIsProtseqValidW
+
+#undef RpcBindingToStringBinding
+#define RpcBindingToStringBinding RpcBindingToStringBindingW
+
+#undef RpcServerUseProtseq
+#define RpcServerUseProtseq RpcServerUseProtseqW
+
+BOOL
+WINAPI
+GetComputerNameX (
+ LPWSTR lpBuffer,
+ LPDWORD nSize
+ );
+
+#undef GetComputerName
+#define GetComputerName GetComputerNameX
+#define GetComputerNameT GetComputerNameA
+
+#undef Foo
+#define Foo FooW
+
+#undef Foo
+#define Foo FooW
+
+#undef Foo
+#define Foo FooW
+
+//The following force Chicago to directly use the ANSI versions
+
+#undef DefWindowProc
+#define DefWindowProc DefWindowProcA
+
+#undef CopyMetaFile // Currently str ptr is always
+#define CopyMetaFile CopyMetaFileA // null, write a wrapper if this
+ // changes
+#undef CreateMetaFile
+#define CreateMetaFile CreateMetaFileA
+
+#undef PostMessage
+#define PostMessage PostMessageA
+
+#undef SendMessage
+#define SendMessage SendMessageA
+
+#undef PeekMessage
+#define PeekMessage PeekMessageA
+
+#undef DispatchMessage
+#define DispatchMessage DispatchMessageA
+
+#undef GetWindowLong
+#define GetWindowLong GetWindowLongA
+
+#undef SetWindowLong
+#define SetWindowLong SetWindowLongA
+
+DWORD
+WINAPI
+GetShortPathNameX(
+ LPCWSTR lpszLongPath,
+ LPWSTR lpszShortPath,
+ DWORD cchBuffer
+ );
+
+#undef GetShortPathName
+#define GetShortPathName GetShortPathNameX
+#define GetShortPathNameT GetShortPathNameA
+
+DWORD
+WINAPI
+GetFullPathNameX(
+ LPCWSTR lpFileName,
+ DWORD nBufferLength,
+ LPWSTR lpBuffer,
+ LPWSTR *lpFilePart
+ );
+
+#undef GetFullPathName
+#define GetFullPathName GetFullPathNameX
+#define GetFullPathNameT GetFullPathNameA
+
+DWORD
+WINAPI
+SearchPathX(
+ LPCWSTR lpPath,
+ LPCWSTR lpFileName,
+ LPCWSTR lpExtension,
+ DWORD nBufferLength,
+ LPWSTR lpBuffer,
+ LPWSTR *lpFilePart
+ );
+
+#undef SearchPath
+#define SearchPath SearchPathX
+#define SearchPathT SearchPathA
+
+ATOM
+WINAPI
+GlobalFindAtomX(
+ LPCWSTR lpString
+ );
+
+#undef GlobalFindAtom
+#define GlobalFindAtom GlobalFindAtomX
+#define GlobalFindAtomT GlobalFindAtomA
+
+int
+WINAPI
+GetClassNameX(
+ HWND hWnd,
+ LPWSTR lpClassName,
+ int nMaxCount);
+
+#undef GetClassName
+#define GetClassName GetClassNameX
+#define GetClassNameT GetClassNameA
+
+LPWSTR
+WINAPI
+CharLowerX(
+ LPWSTR lpsz);
+
+#define CharLowerW CharLowerX
+
+LPWSTR
+WINAPI
+CharUpperX(
+ LPWSTR lpsz);
+
+#define CharUpperW CharUpperX
+
+#define CharLowerBuffW CharLowerBuffW_not_available_on_Win9x
+
+#define CharUpperBuffW CharUpperBuffW_not_available_on_Win9x
+
+BOOL
+WINAPI
+GetStringTypeX(
+ DWORD dwInfoType,
+ LPCWSTR lpSrcStr,
+ int cchSrc,
+ LPWORD lpCharType);
+
+#define GetStringTypeW GetStringTypeX
+
+BOOL
+WINAPI
+IsCharAlphaX(
+ WCHAR ch);
+
+#define IsCharAlphaW IsCharAlphaX
+
+BOOL
+WINAPI
+IsCharAlphaNumericX(
+ WCHAR ch);
+
+#define IsCharAlphaNumericW IsCharAlphaNumericX
+
+#define IsCharLowerW IsCharLowerW_is_not_available_on_Win9x
+
+#define IsCharUpperW IsCharUpperW_is_not_available_on_Win9x
+
+#define LCMapStringW LCMapStringW_is_not_available_on_Win9x
+
+LPWSTR
+WINAPI
+lstrcatX(
+ LPWSTR lpString1,
+ LPCWSTR lpString2
+ );
+
+#define lstrcatW lstrcatX
+
+LPWSTR
+WINAPI
+lstrcpyX(
+ LPWSTR lpString1,
+ LPCWSTR lpString2
+ );
+
+#define lstrcpyW lstrcpyX
+
+LPWSTR
+WINAPI
+lstrcpynX(
+ LPWSTR lpString1,
+ LPCWSTR lpString2,
+ int iMaxLength
+ );
+
+#define lstrcpynW lstrcpynX
+
+int
+WINAPI
+lstrcmpX(
+ LPCWSTR lpString1,
+ LPCWSTR lpString2
+ );
+
+#define lstrcmpW lstrcmpX
+
+int
+WINAPI
+lstrcmpiX(
+ LPCWSTR lpString1,
+ LPCWSTR lpString2
+ );
+
+#define lstrcmpiW lstrcmpiX
+
+HANDLE
+WINAPI
+CreateFileMappingX(
+ HANDLE hFile,
+ LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
+ DWORD flProtect,
+ DWORD dwMaximumSizeHigh,
+ DWORD dwMaximumSizeLow,
+ LPCWSTR lpName
+ );
+
+#undef CreateFileMapping
+#define CreateFileMapping CreateFileMappingX
+#define CreateFileMappingT CreateFileMappingA
+
+HANDLE
+WINAPI
+OpenFileMappingX(
+ DWORD dwDesiredAccess,
+ BOOL bInheritHandle,
+ LPCWSTR lpName
+ );
+
+#undef OpenFileMapping
+#define OpenFileMapping OpenFileMappingX
+#define OpenFileMappingT OpenFileMappingA
+
+#ifdef __cplusplus
+}
+#endif
+
+#else
+//
+// These are the definitions for NT
+//
+#define CreateFileT CreateFileW
+#define DeleteFileT DeleteFileW
+#define RegisterClipboardFormatT RegisterClipboardFormatW
+#define GetClipboardFormatNameT GetClipboardFormatNameW
+#define RegOpenKeyT RegOpenKeyW
+#define RegQueryValueT RegQueryValueW
+#define RegSetValueT RegSetValueW
+#define RegisterWindowMessageT RegisterWindowMessageW
+#define RegOpenKeyExT RegOpenKeyExW
+#define RegQueryValueExT RegQueryValueExW
+#define CreateWindowExT CreateWindowExW
+#define RegisterClassT RegisterClassW
+#define UnregisterClassT UnregisterClassW
+#define wsprintfT wsprintfW
+#define CreateWindowT CreateWindowW
+#define GetPropT GetPropW
+#define SetPropT SetPropW
+#define RemovePropT RemovePropW
+#define GetProfileIntT GetProfileIntW
+#define GlobalAddAtomT GlobalAddAtomW
+#define GlobalGetAtomNameT GlobalGetAtomNameW
+#define GetModuleFileNameT GetModuleFileNameW
+#define CharPrevT CharPrevW
+#define CreateFontT CreateFontW
+#define LoadLibraryT LoadLibraryW
+#define LoadLibraryExT LoadLibraryExW
+#define RegDeleteKeyT RegDeleteKeyW
+#define CreateProcessT CreateProcessW
+#define RegEnumKeyExT RegEnumKeyExW
+#define AppendMenuT AppendMenuW
+#define OpenEventT OpenEventW
+#define CreateEventT CreateEventW
+#define GetDriveTypeT GetDriveTypeW
+#define GetFileAttributesT GetFileAttributesW
+#define RegEnumKeyT RegEnumKeyW
+#define FindFirstFileT FindFirstFileW
+#define GetComputerNameT GetComputerNameW
+#define GetShortPathNameT GetShortPathNameW
+#define GetFullPathNameT GetFullPathNameW
+#define SearchPathT SearchPathW
+#define GlobalFindAtomT GlobalFindAtomW
+#define GetClassNameT GetClassNameW
+#define CreateFileMappingT CreateFileMappingW
+#define OpenFileMappingT OpenFileMappingW
+#define WNDCLASST WNDCLASSW
+
+#endif // _CHICAGO_
+
+#endif // _WIDEWRAP_H_
diff --git a/private/ole32/ih/wx86grpa.hxx b/private/ole32/ih/wx86grpa.hxx
new file mode 100644
index 000000000..469a5ebf3
--- /dev/null
+++ b/private/ole32/ih/wx86grpa.hxx
@@ -0,0 +1,80 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ wx86grpa.h
+
+Abstract:
+
+ Ole interface into Wx86
+
+Author:
+
+ 29-Sep-1995 AlanWar
+
+Revision History:
+
+--*/
+
+#ifdef WX86OLE
+
+typedef HRESULT (*PFNDLLGETCLASSOBJECT)(REFCLSID, REFIID, LPVOID *);
+typedef HRESULT (*PFNDLLCANUNLOADNOW)(void);
+
+
+typedef PFNDLLGETCLASSOBJECT (*WX86PFNGCA)(PVOID);
+typedef PFNDLLCANUNLOADNOW (*WX86PFNCUN)(PVOID);
+typedef void (*WX86GPFNFCB)(PVOID);
+typedef BOOL (*WX86PFNNXPSF)(IUnknown *, REFIID);
+typedef BOOL (*WX86PFNIN2XP)(IUnknown *);
+
+typedef PVOID *(*PFNWX86LOADWHOLE32)(
+ void
+ );
+typedef void (*PFNWX86UNLOADWHOLE32)(
+ void
+);
+
+typedef PVOID (*WHOLEUNMARSHALLEDINSAMEAPT)(PVOID pv, REFIID piid);
+
+typedef void (*WHOLEAGGREGATEPROXY)(IUnknown *, IUnknown *);
+
+#define WholeNeedX86PSFactoryIdx 8
+#define WholeIsN2XProxyIdx 9
+#define WholeThunkDllGetClassObjectIdx 10
+#define WholeThunkDllCanUnloadNowIdx 11
+#define WholeUnmarshalledInSameApt 13
+#define WholeAggregateProxy 14
+
+class CWx86 {
+public:
+ CWx86();
+ ~CWx86();
+
+ PFNDLLGETCLASSOBJECT TranslateDllGetClassObject(PFNDLLGETCLASSOBJECT pv);
+ PFNDLLCANUNLOADNOW TranslateDllCanUnloadNow(PFNDLLCANUNLOADNOW pv);
+ BOOL IsModuleX86(HMODULE hModule);
+ BOOL IsWx86Enabled(void);
+ void SetStubInvokeFlag(UCHAR bFlag);
+ BOOL NeedX86PSFactory(IUnknown *punkObj, REFIID riid);
+ BOOL IsN2XProxy(IUnknown *punk);
+ BOOL SetLoadAsX86(BOOL bFlag);
+ BOOL IsWx86Calling(void);
+ BOOL SetIsWx86Calling(BOOL bFlag);
+ PVOID UnmarshalledInSameApt(PVOID pv, REFIID piid);
+ void AggregateProxy(IUnknown *, IUnknown *);
+ BOOL IsWx86Installed(void);
+
+private:
+ PVOID *_apvWholeFuncs;
+ BOOL _fIsWx86Installed;
+};
+
+inline BOOL CWx86::IsWx86Installed(void)
+{
+ return(_fIsWx86Installed);
+}
+
+#endif
diff --git a/private/ole32/ilib/compob32.def b/private/ole32/ilib/compob32.def
new file mode 100644
index 000000000..09ff69918
--- /dev/null
+++ b/private/ole32/ilib/compob32.def
@@ -0,0 +1,636 @@
+#if 0
+
+ Microsoft Windows
+ Copyright (C) Microsoft Corporation, 1992 - 1992.
+ All rights reserved.
+
+ This .def file is preprocessed by the compiler to create the version for
+ the current build in the appropriate subdir. Basically, whatever you
+ would have used in your code to control what is compiled when can be
+ used in this file for the same purpose. The following defines are in
+ use at the time this file was written:
+
+ FLAT - Used to indicate a NT/DOS7 build
+ i386 - Intel i386/i486 build
+ MIPS - MIPS R3000/R4000 build
+ ALPHA - DEC Alpha build
+ DBG - Used to control Debug/Retail. Set to 1 if Debug,
+ 0 if Retail.
+ WIN31 - Win16 build
+ __OS2__ - OS/2 build (used by CT mostly)
+
+ If none of these are used, it is assumed the entire file can be used
+ for all builds.
+
+#endif
+
+#ifdef FLAT
+
+LIBRARY compob32
+
+DESCRIPTION 'Microsoft (R) Component Object Model DLL 1.00'
+
+EXPORTS
+
+#if defined(i386)
+
+ CoBuildVersion@0 @1
+ CoInitialize@4 @2
+ CoUninitialize@0 @3
+ CoGetMalloc@8 @4
+
+ CoMarshalInterface@24 @5
+ CoUnmarshalInterface@12 @6
+ CoReleaseMarshalData@4 @7
+ CoGetStandardMarshal@24 @8
+ CoGetMarshalSizeMax@24 @23
+ CoMarshalHresult@8 @9
+ CoUnmarshalHresult@8 @10
+
+ CoRegisterClassObject@20 @11
+ CoRevokeClassObject@4 @12
+ CoGetClassObject@20 @13
+ CoCreateInstance@20 @14
+
+; unused @15
+ CoDisconnectObject@8 @16
+ CoLockObjectExternal@12 @17
+
+ CoLoadLibrary@8 @18
+ CoFreeLibrary@4 @19
+ CoFreeAllLibraries@0 @20
+ CoFreeUnusedLibraries@0 @21
+
+ CoRegisterMessageFilter@4 @22
+; CoBlock@0 //23 used by CoGetMarshalSizeMax
+; CoUnblock@4 @24
+ CoFileTimeToDosDateTime@12 @25
+ CoDosDateTimeToFileTime@12 @26
+
+ CoInitializeCriticalSection@4 @27
+ CoEnterCriticalSection@4 @28
+ CoLeaveCriticalSection@4 @29
+ CoDeleteCriticalSection@4 @30
+
+ GetRunningObjectTable@8 @31
+
+ ; unused @32
+ CoOpenClassKey@8 @33
+ CoIsOle1Class@4 @34
+ CoTreatAsClass@8 @35
+ CoGetTreatAsClass@8 @36
+ CoGetCurrentProcess@0 @37
+
+ IsEqualGUID@8 @38
+ StringFromCLSID@8 @39
+ CLSIDFromString@8 @40
+ ProgIDFromCLSID@8 @41
+ CLSIDFromProgID@8 @42
+ StringFromGUID2@12 @43
+
+ IsValidPtrIn@8 @44
+ IsValidPtrOut@8 @45
+ IsValidInterface@4 @46
+ IsValidIid@4 @47
+
+;; ResultFromScode@4 @48
+;; GetScode@4 @49
+
+
+ ;; Temporary entry points used for shared memory allocation.
+
+ SharedMemAlloc@8 @50
+ SharedMemReAlloc@12 @51
+ SharedMemFree@8 @52
+ CoMemctxOf@4 @53
+ ; Removed as this is really obsolete
+ ; CoMemAlloc@12 @54
+ ; CoMemFree@8 @55
+ CoGetPersistentInstance@24 @56
+ CoNewPersistentInstance@32 @57
+
+
+ ;; OLE2.01 functionality
+
+ CoIsHandlerConnected@4 @58
+ ;;CoHasStrongExternalConnections@4 @59
+ CoFileTimeNow@4 @60
+
+ ;; 61-69 unused, reserved for additional 2.01 stuff
+
+ ;; Moniker Functions
+
+ BindMoniker@16 @70
+ MkParseDisplayName@16 @71
+ CreateBindCtx@8 @72
+ CreateItemMoniker@12 @73
+ CreateFileMoniker@8 @74
+ CreateGenericComposite@12 @75
+ CreateAntiMoniker@4 @76
+ CreatePointerMoniker@8 @77
+ MonikerRelativePathTo@16 @78
+#ifdef _CAIRO_
+ CreateFileMonikerEx@12 @79
+#else
+; unused @79
+#endif
+ GetClassFile@8 @80
+ OleSaveToStream@8 @81
+ OleLoadFromStream@12 @82
+ MonikerCommonPrefixWith@12 @83
+
+ ;; internal calls below this point
+
+ ;; The following two entries are probably temporary as
+ ;; they are helpers for drag and drop
+ AssignEndpointProperty@4
+ UnAssignEndpointProperty@4
+ GetInterfaceFromWindowProp@16
+
+ ;; this maybe should be removed
+ FnAssert@16
+
+; StringFromCLSID2@12
+ CoGetClassExt@8
+ Ole1ClassFromCLSID2@12
+; CMemBytesUnMarshal@0
+; CMemStmUnMarshal@0
+ GetOleMutex@0
+ ReleaseOleMutex@0
+ StringFromIID@8
+ IIDFromString@8
+; SzFixNet@20
+ Concatenate@12
+
+ ;; are these still needed?
+ ;;
+ ;;CloneSharedMemStm@4
+ ;;CreateSharedMemStm@8
+ ;;FreeSharedMemStmHandle@4
+ ;;CreateMemLockbytes@8
+ ;;?Create@CMemBytes@@SGPAV1@PAX@Z
+
+ ;; BUGBUG: Temporary name of memory allocators till real
+ ;; memory philosophy defined.
+ ?CoMemAlloc@@YGPAXKKPAX@Z
+ ?CoMemFree@@YGXPAXK@Z
+
+ ?PubMemAlloc@@YGPAXK@Z
+ ?PubMemFree@@YGXPAX@Z
+
+#ifndef _CAIRO_
+ ??2CPrivAlloc@@SGPAXI@Z
+ ??3CPrivAlloc@@SGXPAX@Z
+
+#if DBG==1
+ vdprintf
+#endif
+#endif
+
+ ; Export ability to create remote handler
+ RemCreateRemoteHandler@16
+ CoInitializeEx@8
+ DllDebugObjectRPCHook=DllDebugObjectRPCHook@8
+
+#if DBG==1
+ Dbg_FindRemoteHdlr
+#endif
+
+#ifdef LRPC
+ ;; BUGBUG: The following are old exports from 16 bit having to do
+ ;; with the LRPC part of the system. We are just keeping
+ ;; them here for reference.
+ RemCreateRemoteHandler@40
+ RemAllocOID@4
+ RemFreeOID@4
+ RemConnectToObject@8
+ RemSetHandler@8
+ RemClearHandler@4
+ RemLookupHandler@8
+ RemUninitHandlers@0
+ RemRevokeServer@4
+ RemLookupOrCreateServer@16
+ RemLookupServerUnk@12
+ RemLookupServerOID@12
+ RemLookupSHUnk@12
+ RemUninitServers@0
+ RemCreateRHClassObject@24
+ RemEnsureLocalClassObject@8
+ RemEnsureUniqueHandler@12
+ RemGetInfoForCid@24
+ RemCreateStubManager@16
+
+
+ LrpcCall@12
+ LrpcDispatch@12
+ LrpcRegisterMonitor@4
+ LrpcRevokeMonitor@4
+ LrpcGetConnClient@4
+ LrpcGetConnObject@4
+ LrpcGetObjServer@4
+ LrpcGetMessage@20
+ LrpcTimeout@4
+ LrpcGetThreadWindow@0
+#endif // LRPC
+
+#elif defined(_MIPS_)
+
+ CoBuildVersion @1
+ CoInitialize @2
+ CoUninitialize @3
+ CoGetMalloc @4
+
+ CoMarshalInterface @5
+ CoUnmarshalInterface @6
+ CoReleaseMarshalData @7
+ CoGetStandardMarshal @8
+ CoGetMarshalSizeMax @23
+ CoMarshalHresult @9
+ CoUnmarshalHresult @10
+
+ CoRegisterClassObject @11
+ CoRevokeClassObject @12
+ CoGetClassObject @13
+ CoCreateInstance @14
+
+; unused @15
+ CoDisconnectObject @16
+ CoLockObjectExternal @17
+
+ CoLoadLibrary @18
+ CoFreeLibrary @19
+ CoFreeAllLibraries @20
+ CoFreeUnusedLibraries @21
+ CoRegisterMessageFilter @22
+; CoBlock @23
+; CoUnblock @24
+ CoFileTimeToDosDateTime @25
+ CoDosDateTimeToFileTime @26
+
+ CoInitializeCriticalSection @27
+ CoEnterCriticalSection @28
+ CoLeaveCriticalSection @29
+ CoDeleteCriticalSection @30
+
+ GetRunningObjectTable @31
+
+ ; unused @32
+ CoOpenClassKey @33
+ CoIsOle1Class @34
+ CoTreatAsClass @35
+ CoGetTreatAsClass @36
+ CoGetCurrentProcess @37
+
+ IsEqualGUID @38
+ StringFromCLSID @39
+ CLSIDFromString @40
+ ProgIDFromCLSID @41
+ CLSIDFromProgID @42
+ StringFromGUID2 @43
+
+ IsValidPtrIn @44
+ IsValidPtrOut @45
+ IsValidInterface @46
+ IsValidIid @47
+
+;; ResultFromScode @48
+;; GetScode @49
+
+
+ ;; Temporary entry points used for shared memory allocation.
+
+ SharedMemAlloc @50
+ SharedMemReAlloc @51
+ SharedMemFree @52
+ CoMemctxOf @53
+; Moved to mangled names because these are not documented
+; CoMemAlloc @54
+; CoMemFree @55
+ CoGetPersistentInstance @56
+ CoNewPersistentInstance @57
+
+ ;; OLE2.01 functionality
+
+ CoIsHandlerConnected @58
+ ;;CoHasStrongExternalConnections @59
+ CoFileTimeNow @60
+
+ ;; 61-69 reserved for additional 2.01 functionality
+
+ ;; Moniker Functions
+
+ BindMoniker @70
+ MkParseDisplayName @71
+ CreateBindCtx @72
+ CreateItemMoniker @73
+ CreateFileMoniker @74
+ CreateGenericComposite @75
+ CreateAntiMoniker @76
+ CreatePointerMoniker @77
+ MonikerRelativePathTo @78
+#ifdef _CAIRO_
+ ; CreateFileMonikerEx @79
+#else
+; unused @79
+#endif
+ GetClassFile @80
+ OleSaveToStream @81
+ OleLoadFromStream @82
+ MonikerCommonPrefixWith @83
+
+ ;; internal calls below this point
+
+ ;; The following two entries are probably temporary as
+ ;; they are helpers for drag and drop
+ AssignEndpointProperty
+ UnAssignEndpointProperty
+ GetInterfaceFromWindowProp
+
+ ;; this maybe should be removed
+ FnAssert
+
+; StringFromCLSID2
+ CoGetClassExt
+ Ole1ClassFromCLSID2
+; CMemBytesUnMarshal
+; CMemStmUnMarshal
+ GetOleMutex
+ ReleaseOleMutex
+ StringFromIID
+ IIDFromString
+; SzFixNet
+ Concatenate
+
+ ;; are these still needed?
+ ;;
+ ;;CloneSharedMemStm
+ ;;CreateSharedMemStm
+ ;;FreeSharedMemStmHandle
+ ;;CreateMemLockbytes
+ ;;?Create@CMemBytes@@SGPAV1@PAX@Z
+
+
+ ; Temparary while new CoMemAlloc defined
+ ?CoMemAlloc@@YAPAXKKPAX@Z
+ ?CoMemFree@@YAXPAXK@Z
+
+ ?PubMemAlloc@@YAPAXK@Z
+ ?PubMemFree@@YAXPAX@Z
+
+#ifndef _CAIRO_
+ ??2CPrivAlloc@@SAPAXI@Z
+ ??3CPrivAlloc@@SAXPAX@Z
+
+#if DBG==1
+ vdprintf
+#endif
+#endif
+
+ ; Export ability to create remote handler
+ RemCreateRemoteHandler
+
+#if DBG==1
+ Dbg_FindRemoteHdlr
+#endif
+
+
+ CoInitializeEx
+
+#ifdef LRPC
+ ;; BUGBUG: The following are old exports from 16 bit having to do
+ ;; with the LRPC part of the system. We are just keeping
+ ;; them here for reference.
+ RemAllocOID
+ RemFreeOID
+ RemConnectToObject
+ RemSetHandler
+ RemClearHandler
+ RemLookupHandler
+ RemUninitHandlers
+ RemRevokeServer
+ RemLookupOrCreateServer
+ RemLookupServerUnk
+ RemLookupServerOID
+ RemLookupSHUnk
+ RemUninitServers
+ RemCreateRHClassObject
+ RemEnsureLocalClassObject
+ RemEnsureUniqueHandler
+ RemGetInfoForCid
+ RemCreateStubManager
+
+ LrpcCall
+ LrpcDispatch
+ LrpcRegisterMonitor
+ LrpcRevokeMonitor
+ LrpcGetConnClient
+ LrpcGetConnObject
+ LrpcGetObjServer
+ LrpcGetMessage
+ LrpcTimeout
+ LrpcGetThreadWindow
+
+#endif // LRPC
+
+#elif defined(_PPC_)
+
+ CoBuildVersion @1
+ CoInitialize @2
+ CoUninitialize @3
+ CoGetMalloc @4
+
+ CoMarshalInterface @5
+ CoUnmarshalInterface @6
+ CoReleaseMarshalData @7
+ CoGetStandardMarshal @8
+ CoGetMarshalSizeMax @23
+ CoMarshalHresult @9
+ CoUnmarshalHresult @10
+
+ CoRegisterClassObject @11
+ CoRevokeClassObject @12
+ CoGetClassObject @13
+ CoCreateInstance @14
+
+; unused @15
+ CoDisconnectObject @16
+ CoLockObjectExternal @17
+
+ CoLoadLibrary @18
+ CoFreeLibrary @19
+ CoFreeAllLibraries @20
+ CoFreeUnusedLibraries @21
+ CoRegisterMessageFilter @22
+; CoBlock @23
+; CoUnblock @24
+ CoFileTimeToDosDateTime @25
+ CoDosDateTimeToFileTime @26
+
+ CoInitializeCriticalSection @27
+ CoEnterCriticalSection @28
+ CoLeaveCriticalSection @29
+ CoDeleteCriticalSection @30
+
+ GetRunningObjectTable @31
+
+ ; unused @32
+ CoOpenClassKey @33
+ CoIsOle1Class @34
+ CoTreatAsClass @35
+ CoGetTreatAsClass @36
+ CoGetCurrentProcess @37
+
+ IsEqualGUID @38
+ StringFromCLSID @39
+ CLSIDFromString @40
+ ProgIDFromCLSID @41
+ CLSIDFromProgID @42
+ StringFromGUID2 @43
+
+ IsValidPtrIn @44
+ IsValidPtrOut @45
+ IsValidInterface @46
+ IsValidIid @47
+
+;; ResultFromScode @48
+;; GetScode @49
+
+
+ ;; Temporary entry points used for shared memory allocation.
+
+ SharedMemAlloc @50
+ SharedMemReAlloc @51
+ SharedMemFree @52
+ CoMemctxOf @53
+; Moved to mangled names because these are not documented
+; CoMemAlloc @54
+; CoMemFree @55
+ CoGetPersistentInstance @56
+ CoNewPersistentInstance @57
+
+ ;; OLE2.01 functionality
+
+ CoIsHandlerConnected @58
+ ;;CoHasStrongExternalConnections @59
+ CoFileTimeNow @60
+
+ ;; 61-69 reserved for additional 2.01 functionality
+
+ ;; Moniker Functions
+
+ BindMoniker @70
+ MkParseDisplayName @71
+ CreateBindCtx @72
+ CreateItemMoniker @73
+ CreateFileMoniker @74
+ CreateGenericComposite @75
+ CreateAntiMoniker @76
+ CreatePointerMoniker @77
+ MonikerRelativePathTo @78
+#ifdef _CAIRO_
+ ; CreateFileMonikerEx @79
+#else
+; unused @79
+#endif
+ GetClassFile @80
+ OleSaveToStream @81
+ OleLoadFromStream @82
+ MonikerCommonPrefixWith @83
+
+ ;; internal calls below this point
+
+ ;; The following two entries are probably temporary as
+ ;; they are helpers for drag and drop
+ AssignEndpointProperty
+ UnAssignEndpointProperty
+ GetInterfaceFromWindowProp
+
+ ;; this maybe should be removed
+ FnAssert
+
+; StringFromCLSID2
+ CoGetClassExt
+ Ole1ClassFromCLSID2
+; CMemBytesUnMarshal
+; CMemStmUnMarshal
+ GetOleMutex
+ ReleaseOleMutex
+ StringFromIID
+ IIDFromString
+; SzFixNet
+ Concatenate
+
+ ;; are these still needed?
+ ;;
+ ;;CloneSharedMemStm
+ ;;CreateSharedMemStm
+ ;;FreeSharedMemStmHandle
+ ;;CreateMemLockbytes
+ ;;?Create@CMemBytes@@SGPAV1@PAX@Z
+
+
+ ; Temparary while new CoMemAlloc defined
+ ?CoMemAlloc@@YAPAXKKPAX@Z
+ ?CoMemFree@@YAXPAXK@Z
+
+ ?PubMemAlloc@@YAPAXK@Z
+ ?PubMemFree@@YAXPAX@Z
+
+#ifndef _CAIRO_
+ ??2CPrivAlloc@@SAPAXI@Z
+ ??3CPrivAlloc@@SAXPAX@Z
+
+#if DBG==1
+ vdprintf
+#endif
+#endif
+
+ ; Export ability to create remote handler
+ RemCreateRemoteHandler
+
+#if DBG==1
+ Dbg_FindRemoteHdlr
+#endif
+
+
+ CoInitializeEx
+
+#ifdef LRPC
+ ;; BUGBUG: The following are old exports from 16 bit having to do
+ ;; with the LRPC part of the system. We are just keeping
+ ;; them here for reference.
+ RemAllocOID
+ RemFreeOID
+ RemConnectToObject
+ RemSetHandler
+ RemClearHandler
+ RemLookupHandler
+ RemUninitHandlers
+ RemRevokeServer
+ RemLookupOrCreateServer
+ RemLookupServerUnk
+ RemLookupServerOID
+ RemLookupSHUnk
+ RemUninitServers
+ RemCreateRHClassObject
+ RemEnsureLocalClassObject
+ RemEnsureUniqueHandler
+ RemGetInfoForCid
+ RemCreateStubManager
+
+ LrpcCall
+ LrpcDispatch
+ LrpcRegisterMonitor
+ LrpcRevokeMonitor
+ LrpcGetConnClient
+ LrpcGetConnObject
+ LrpcGetObjServer
+ LrpcGetMessage
+ LrpcTimeout
+ LrpcGetThreadWindow
+
+#endif // LRPC
+
+#endif // i386 / _MIPS_ / _PPC_
+
+#endif // FLAT
diff --git a/private/ole32/ilib/daytona/makefile b/private/ole32/ilib/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/ilib/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/ilib/daytona/makefile.inc b/private/ole32/ilib/daytona/makefile.inc
new file mode 100644
index 000000000..cf8773805
--- /dev/null
+++ b/private/ole32/ilib/daytona/makefile.inc
@@ -0,0 +1,17 @@
+
+#
+# Get the UUIDs from built directory in common
+#
+uuid: proxyb_i.c psfbuf_i.c rchanb_i.c stubb_i.c
+
+proxyb_i.c: ..\..\common\daytona\proxyb_i.c
+ copy ..\..\common\daytona\proxyb_i.c
+
+psfbuf_i.c: ..\..\common\daytona\psfbuf_i.c
+ copy ..\..\common\daytona\psfbuf_i.c
+
+rchanb_i.c: ..\..\common\daytona\rchanb_i.c
+ copy ..\..\common\daytona\rchanb_i.c
+
+stubb_i.c: ..\..\common\daytona\stubb_i.c
+ copy ..\..\common\daytona\stubb_i.c
diff --git a/private/ole32/ilib/daytona/sources b/private/ole32/ilib/daytona/sources
new file mode 100644
index 000000000..0378384a3
--- /dev/null
+++ b/private/ole32/ilib/daytona/sources
@@ -0,0 +1,63 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = uuid
+
+!include ..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= uuid
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..\..\common\daytona;..\..\ih
+
+C_DEFINES= \
+ $(C_DEFINES)
+
+
+SOURCES= \
+ ..\uuidole.cxx
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
diff --git a/private/ole32/ilib/depend.mk b/private/ole32/ilib/depend.mk
new file mode 100644
index 000000000..300d0afdc
--- /dev/null
+++ b/private/ole32/ilib/depend.mk
@@ -0,0 +1,35 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\uuidole.obj $(OBJDIR)\uuidole.lst: .\uuidole.cxx \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h $(CAIROLE)\h\storage.h \
+ $(CAIROLE)\ih\ole1cls.h $(CAIROLE)\ih\privguid.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winmm.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
+$(OBJDIR)\stubb_i.obj $(OBJDIR)\stubb_i.lst: .\stubb_i.c
+
+$(OBJDIR)\rchanb_i.obj $(OBJDIR)\rchanb_i.lst: .\rchanb_i.c
+
+$(OBJDIR)\psfbuf_i.obj $(OBJDIR)\psfbuf_i.lst: .\psfbuf_i.c
+
+$(OBJDIR)\proxyb_i.obj $(OBJDIR)\proxyb_i.lst: .\proxyb_i.c
+
diff --git a/private/ole32/ilib/dirs b/private/ole32/ilib/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/ilib/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/ilib/filelist.mk b/private/ole32/ilib/filelist.mk
new file mode 100644
index 000000000..b8486f2d2
--- /dev/null
+++ b/private/ole32/ilib/filelist.mk
@@ -0,0 +1,59 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = ole232.lib
+
+RELEASE =
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES = .\uuidole.cxx
+
+CFILES = .\proxyb_i.c \
+ .\psfbuf_i.c \
+ .\rchanb_i.c \
+ .\stubb_i.c
+
+
+CINC = $(CINC) -I$(CAIROLE)\h -I$(CAIROLE)\common -I$(CAIROLE)\ih
+
+#
+# Libraries and other object files to link.
+#
+
+
+OBJFILES = $(OBJDIR)\ole232xx.lib
+
+#
+# Precompiled headers.
+#
+
+#
+# Get the UUIDs from built directory in common
+#
+all: proxyb_i.c psfbuf_i.c rchanb_i.c stubb_i.c
+
+proxyb_i.c: $(CAIROLE)\common\proxyb_i.c
+ copy $(CAIROLE)\common\proxyb_i.c
+
+psfbuf_i.c: $(CAIROLE)\common\psfbuf_i.c
+ copy $(CAIROLE)\common\psfbuf_i.c
+
+rchanb_i.c: $(CAIROLE)\common\rchanb_i.c
+ copy $(CAIROLE)\common\rchanb_i.c
+
+stubb_i.c: $(CAIROLE)\common\stubb_i.c
+ copy $(CAIROLE)\common\stubb_i.c
diff --git a/private/ole32/ilib/makefile b/private/ole32/ilib/makefile
new file mode 100644
index 000000000..8418099ab
--- /dev/null
+++ b/private/ole32/ilib/makefile
@@ -0,0 +1,35 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1992.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+default: all
+
+# Pass0.mk generates ole232xx.lib, storag32.lib, compob32.lib
+# FileList.mk combines oledisxx.lib with guids to make ole232.lib
+
+all: makelibs
+
+makelibs:
+ @$(MAKE) -L -$(MAKEFLAGS) -f pass0.mk
+
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/ilib/ole232xx.def b/private/ole32/ilib/ole232xx.def
new file mode 100644
index 000000000..1e90a7598
--- /dev/null
+++ b/private/ole32/ilib/ole232xx.def
@@ -0,0 +1,415 @@
+#if 0
+
+ Microsoft Windows
+ Copyright (C) Microsoft Corporation, 1992 - 1992.
+ All rights reserved.
+
+ This .def file is preprocessed by the compiler to create the version for
+ the current build in the appropriate subdir. Basically, whatever you
+ would have used in your code to control what is compiled when can be
+ used in this file for the same purpose. The following defines are in
+ use at the time this file was written:
+
+ FLAT - Used to indicate a NT/DOS7 build
+ i386 - Intel i386/i486 build
+ MIPS - MIPS R3000/R4000 build
+ ALPHA - DEC Alpha build
+ DBG - Used to control Debug/Retail. Set to 1 if Debug,
+ 0 if Retail.
+ WIN31 - Win16 build
+ __OS2__ - OS/2 build (used by CT mostly)
+
+ If none of these are used, it is assumed the entire file can be used
+ for all builds.
+
+#endif
+
+#ifdef FLAT
+
+LIBRARY ole232
+
+DESCRIPTION 'Microsoft (R) Component OLE 2.0 Base DLL 1.00'
+
+EXPORTS
+
+#if defined (i386)
+
+ OleBuildVersion@0 @1
+ OleInitialize@4 @2
+ OleUninitialize@0 @3
+ DllGetClassObject@12 @4
+ DllGetClassObject=DllGetClassObject@12
+ ;; Unused @5
+ OleQueryLinkFromData@4 @6
+ OleQueryCreateFromData@4 @7
+ OleCreateFromData@28 @8
+ OleCreateLinkFromData@28 @9
+ OleCreate@28 @10
+ OleCreateLink@28 @11
+ OleLoad@16 @12
+ OleSave@12 @13
+ OleRun@4 @14
+ ;; Unused @15
+ OleIsRunning@4 @16
+ OleLockRunning@12 @17
+ ReadClassStg@8 @18
+ WriteClassStg@8 @19
+ ReadClassStm@8 @20
+ WriteClassStm@8 @21
+ ;; BindMoniker@16 in compobj @22
+ ;; MkParseDisplayName@16 in compboj @23
+ ;; OleSaveToStream@8 in compobj @24
+ ;; OleLoadFromStream@24 in compobj @25
+ ;; CreateBindCtx@8 in compobj @26
+ ;; CreateItemMoniker@12 in compobj @27
+ ;; CreateFileMoniker@8 in compobj @28
+ ;; CreateGenericComposite@12 in compobj @29
+ ;; GetRunningObjectTable in compobj @30
+ OleGetMalloc@8 @31
+ ReleaseStgMedium@4 @32
+ ReadStringStream@8 @33
+ WriteStringStream@8 @34
+ RegisterDragDrop@8 @35
+ RevokeDragDrop@4 @36
+ DoDragDrop@16 @37
+ CreateOleAdviseHolder@4 @38
+ CreateDataAdviseHolder@4 @39
+ OleCreateMenuDescriptor@8 @40
+ OleSetMenuDescriptor@20 @41
+ OleDestroyMenuDescriptor@4 @42
+ OpenOrCreateStream@12 @43
+ ;; CreateAntiMoniker@4 in compobj @44
+ IsAccelerator@16 @45
+ ;; CreatePointerMoniker@8 in compobj @45
+ ;; MonikerRelativePathTo@16 in compobj @46
+ ;; CreateFileMonikerEx@12 in compobj @47
+ ;; BUGBUG: CreateMemStm should vanish
+ ;; CreateMemStm@8 is gone @48
+ OleSetClipboard@4 @49
+ OleGetClipboard@4 @50
+ OleDuplicateData@12 @51
+ OleGetIconOfFile@8 @52
+ OleGetIconOfClass@12 @53
+ CreateILockBytesOnHGlobal@12 @54
+ GetHGlobalFromILockBytes@8 @55
+ OleMetafilePictFromIconAndLabel@16 @56
+ ;;GetClassFile@8 in compobj @57
+ OleDraw@16 @58
+ OleCreateDefaultHandler@16 @59
+ OleCreateEmbeddingHelper@24 @60
+ ;; Unused @61
+ ;; Unused @62
+ SetDocumentBitStg@8 @63
+ GetDocumentBitStg@4 @64
+ WriteOleStg@16 @65
+ ReadOleStg@24 @66
+ OleCreateFromFile@32 @67
+ OleCreateLinkToFile@28 @68
+ CreateDataCache@16 @69
+ OleConvertIStorageToOLESTREAM@8 @70
+ OleConvertOLESTREAMToIStorage@12 @71
+ OleConvertIStorageToOLESTREAMEx@28 @72
+ OleConvertOLESTREAMToIStorageEx@28 @73
+ ReadFmtUserTypeStg@12 @74
+ WriteFmtUserTypeStg@12 @75
+ OleFlushClipboard@0 @76
+ OleIsCurrentClipboard@4 @77
+ OleTranslateAccelerator@12 @78
+ OleDoAutoConvert@8 @79
+ OleGetAutoConvert@8 @80
+ OleSetAutoConvert@8 @81
+ GetConvertStg@4 @82
+ SetConvertStg@8 @83
+ CreateStreamOnHGlobal@12 @84
+ GetHGlobalFromStream@8 @85
+ OleSetContainedObject@8 @86
+ OleNoteObjectVisible@8 @87
+ OleCreateStaticFromData@28 @88
+
+ OleRegGetUserType@12 @89
+ OleRegGetMiscStatus@12 @90
+ OleRegEnumFormatEtc@12 @91
+ OleRegEnumVerbs@8 @92
+ OleGetEnumFormatEtc@8 @93 ; used internally
+
+ ;; Multi-thread support
+
+ OleInitializeEx@8 @94
+
+
+ ;; debug routines
+
+ MakeDebugStream@12 @100
+ ;; Unused @101
+ ;; Unused @102
+ ;; Unused @103
+ DbgLogOpen@8 @104
+ DbgLogClose@4 @105
+ DbgLogOutputDebugString@8 @106
+ DbgLogWrite@8 @107
+ DbgLogTimeStamp@8 @108
+ DbgLogWriteBanner@8 @109
+ DbgDumpObject@8 @110
+ DbgIsObjectValid@4 @111
+ DbgDumpExternalObject@8 @112
+ ;; Unused @113
+ DbgDumpClassName@4 @114
+ ;; GetStandardTaskMalloc@4 @116
+
+
+
+//////////////////////////// MIPS ////////////////////////////
+
+#elif defined (_MIPS_)
+
+ OleBuildVersion @1
+ OleInitialize @2
+ OleUninitialize @3
+ DllGetClassObject @4
+
+ ;; Unused @5
+ OleQueryLinkFromData @6
+ OleQueryCreateFromData @7
+ OleCreateFromData @8
+ OleCreateLinkFromData @9
+ OleCreate @10
+ OleCreateLink @11
+ OleLoad @12
+ OleSave @13
+ OleRun @14
+ ;; Unused @15
+ OleIsRunning @16
+ OleLockRunning @17
+ ReadClassStg @18
+ WriteClassStg @19
+ ReadClassStm @20
+ WriteClassStm @21
+ ;; BindMoniker in compobj @22
+ ;; MkParseDisplayName in compobj @23
+ ;; OleSaveToStream in compobj @24
+ ;; OleLoadFromStream in compobj @25
+ ;; CreateBindCtx in compobj @26
+ ;; CreateItemMoniker in compobj @27
+ ;; CreateFileMoniker in compobj @28
+ ;; CreateGenericComposite in compobj @29
+ ;; GetRunningObjectTable in compobj @30
+ OleGetMalloc @31
+ ReleaseStgMedium @32
+ ReadStringStream @33
+ WriteStringStream @34
+ RegisterDragDrop @35
+ RevokeDragDrop @36
+ DoDragDrop @37
+ CreateOleAdviseHolder @38
+ CreateDataAdviseHolder @39
+ OleCreateMenuDescriptor @40
+ OleSetMenuDescriptor @41
+ OleDestroyMenuDescriptor @42
+ OpenOrCreateStream @43
+ IsAccelerator @44
+ ;; CreateAntiMoniker in compobj @44
+ ;; CreatePointerMoniker in compobj @45
+ ;; MonikerRelativePathTo in compobj @46
+ ;; CreateFileMonikerEx in compobj @47
+ ;; BUGBUG: CreateMemStm should vanish
+ ;; CreateMemStm is gone @48
+ OleSetClipboard @49
+ OleGetClipboard @50
+ OleDuplicateData @51
+ OleGetIconOfFile @52
+ OleGetIconOfClass @53
+ CreateILockBytesOnHGlobal @54
+ GetHGlobalFromILockBytes @55
+ OleMetafilePictFromIconAndLabel @56
+ ;;GetClassFile in compobj @57
+ OleDraw @58
+ OleCreateDefaultHandler @59
+ OleCreateEmbeddingHelper @60
+ ;; Unused @61
+ ;; Unused @62
+ SetDocumentBitStg @63
+ GetDocumentBitStg @64
+ WriteOleStg @65
+ ReadOleStg @66
+ OleCreateFromFile @67
+ OleCreateLinkToFile @68
+ CreateDataCache @69
+ OleConvertIStorageToOLESTREAM @70
+ OleConvertOLESTREAMToIStorage @71
+ OleConvertIStorageToOLESTREAMEx @72
+ OleConvertOLESTREAMToIStorageEx @73
+ ReadFmtUserTypeStg @74
+ WriteFmtUserTypeStg @75
+ OleFlushClipboard @76
+ OleIsCurrentClipboard @77
+ OleTranslateAccelerator @78
+ OleDoAutoConvert @79
+ OleGetAutoConvert @80
+ OleSetAutoConvert @81
+ GetConvertStg @82
+ SetConvertStg @83
+ CreateStreamOnHGlobal @84
+ GetHGlobalFromStream @85
+ OleSetContainedObject @86
+ OleNoteObjectVisible @87
+ OleCreateStaticFromData @88
+
+ OleRegGetUserType @89
+ OleRegGetMiscStatus @90
+ OleRegEnumFormatEtc @91
+ OleRegEnumVerbs @92
+ OleGetEnumFormatEtc @93 ; used internally
+
+ ;; Multi-thread support
+
+ OleInitializeEx @94
+
+
+ ;; debug routines
+
+ MakeDebugStream @100
+ ;; Unused @101
+ ;; Unused @102
+ ;; Unused @103
+ DbgLogOpen @104
+ DbgLogClose @105
+ DbgLogOutputDebugString @106
+ DbgLogWrite @107
+ DbgLogTimeStamp @108
+ DbgLogWriteBanner @109
+ DbgDumpObject @110
+ DbgIsObjectValid @111
+ DbgDumpExternalObject @112
+ ;; Unused @113
+ DbgDumpClassName @114
+ ;; GetStandardTaskMalloc @116
+
+//////////////////////////// PPC ////////////////////////////
+
+#elif defined (_PPC_)
+
+ OleBuildVersion @1
+ OleInitialize @2
+ OleUninitialize @3
+ DllGetClassObject @4
+
+ ;; Unused @5
+ OleQueryLinkFromData @6
+ OleQueryCreateFromData @7
+ OleCreateFromData @8
+ OleCreateLinkFromData @9
+ OleCreate @10
+ OleCreateLink @11
+ OleLoad @12
+ OleSave @13
+ OleRun @14
+ ;; Unused @15
+ OleIsRunning @16
+ OleLockRunning @17
+ ReadClassStg @18
+ WriteClassStg @19
+ ReadClassStm @20
+ WriteClassStm @21
+ ;; BindMoniker in compobj @22
+ ;; MkParseDisplayName in compobj @23
+ ;; OleSaveToStream in compobj @24
+ ;; OleLoadFromStream in compobj @25
+ ;; CreateBindCtx in compobj @26
+ ;; CreateItemMoniker in compobj @27
+ ;; CreateFileMoniker in compobj @28
+ ;; CreateGenericComposite in compobj @29
+ ;; GetRunningObjectTable in compobj @30
+ OleGetMalloc @31
+ ReleaseStgMedium @32
+ ReadStringStream @33
+ WriteStringStream @34
+ RegisterDragDrop @35
+ RevokeDragDrop @36
+ DoDragDrop @37
+ CreateOleAdviseHolder @38
+ CreateDataAdviseHolder @39
+ OleCreateMenuDescriptor @40
+ OleSetMenuDescriptor @41
+ OleDestroyMenuDescriptor @42
+ OpenOrCreateStream @43
+ IsAccelerator @44
+ ;; CreateAntiMoniker in compobj @44
+ ;; CreatePointerMoniker in compobj @45
+ ;; MonikerRelativePathTo in compobj @46
+ ;; CreateFileMonikerEx in compobj @47
+ ;; BUGBUG: CreateMemStm should vanish
+ ;; CreateMemStm is gone @48
+ OleSetClipboard @49
+ OleGetClipboard @50
+ OleDuplicateData @51
+ OleGetIconOfFile @52
+ OleGetIconOfClass @53
+ CreateILockBytesOnHGlobal @54
+ GetHGlobalFromILockBytes @55
+ OleMetafilePictFromIconAndLabel @56
+ ;;GetClassFile in compobj @57
+ OleDraw @58
+ OleCreateDefaultHandler @59
+ OleCreateEmbeddingHelper @60
+ ;; Unused @61
+ ;; Unused @62
+ SetDocumentBitStg @63
+ GetDocumentBitStg @64
+ WriteOleStg @65
+ ReadOleStg @66
+ OleCreateFromFile @67
+ OleCreateLinkToFile @68
+ CreateDataCache @69
+ OleConvertIStorageToOLESTREAM @70
+ OleConvertOLESTREAMToIStorage @71
+ OleConvertIStorageToOLESTREAMEx @72
+ OleConvertOLESTREAMToIStorageEx @73
+ ReadFmtUserTypeStg @74
+ WriteFmtUserTypeStg @75
+ OleFlushClipboard @76
+ OleIsCurrentClipboard @77
+ OleTranslateAccelerator @78
+ OleDoAutoConvert @79
+ OleGetAutoConvert @80
+ OleSetAutoConvert @81
+ GetConvertStg @82
+ SetConvertStg @83
+ CreateStreamOnHGlobal @84
+ GetHGlobalFromStream @85
+ OleSetContainedObject @86
+ OleNoteObjectVisible @87
+ OleCreateStaticFromData @88
+
+ OleRegGetUserType @89
+ OleRegGetMiscStatus @90
+ OleRegEnumFormatEtc @91
+ OleRegEnumVerbs @92
+ OleGetEnumFormatEtc @93 ; used internally
+
+ ;; Multi-thread support
+
+ OleInitializeEx @94
+
+
+ ;; debug routines
+
+ MakeDebugStream @100
+ ;; Unused @101
+ ;; Unused @102
+ ;; Unused @103
+ DbgLogOpen @104
+ DbgLogClose @105
+ DbgLogOutputDebugString @106
+ DbgLogWrite @107
+ DbgLogTimeStamp @108
+ DbgLogWriteBanner @109
+ DbgDumpObject @110
+ DbgIsObjectValid @111
+ DbgDumpExternalObject @112
+ ;; Unused @113
+ DbgDumpClassName @114
+ ;; GetStandardTaskMalloc @116
+
+#endif // i386 - MIPS - PPC
+
+#endif // FLAT
diff --git a/private/ole32/ilib/ole2pr32.def b/private/ole32/ilib/ole2pr32.def
new file mode 100644
index 000000000..bf5cf2865
--- /dev/null
+++ b/private/ole32/ilib/ole2pr32.def
@@ -0,0 +1,28 @@
+LIBRARY OLE2PROX
+
+CODE MOVEABLE DISCARDABLE LOADONCALL SHARED
+
+SEGMENTS INIT PRELOAD
+
+DATA MOVEABLE SINGLE
+HEAPSIZE 0
+EXPORTS
+
+#ifdef i386
+
+ WEP@0 @1
+ DllGetClassObject@12 @2
+
+#endif
+#ifdef _MIPS_
+ WEP @1
+ DllGetClassObject @2
+
+#endif
+#ifdef _PPC_
+ WEP @1
+ DllGetClassObject @2
+
+#endif
+;
+; functions statement file (appended by the makefile)
diff --git a/private/ole32/ilib/pass0.mk b/private/ole32/ilib/pass0.mk
new file mode 100644
index 000000000..3e54308b1
--- /dev/null
+++ b/private/ole32/ilib/pass0.mk
@@ -0,0 +1,13 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+default: all
+
+!include $(COMMON)\src\win40.mk
+
+all: $(OBJDIR)\ole232xx.lib $(OBJDIR)\storag32.lib $(OBJDIR)\compob32.lib
diff --git a/private/ole32/ilib/readme.txt b/private/ole32/ilib/readme.txt
new file mode 100644
index 000000000..8b9b5e5be
--- /dev/null
+++ b/private/ole32/ilib/readme.txt
@@ -0,0 +1,6 @@
+The def file ole2w32.def can be found in ole2w32\ole2w32a.def
+
+It is renamed so that win40.mk can merge it with the guids in
+uuid.lib to build the final ole2w32.lib file.
+
+
diff --git a/private/ole32/ilib/storag32.def b/private/ole32/ilib/storag32.def
new file mode 100644
index 000000000..577b232db
--- /dev/null
+++ b/private/ole32/ilib/storag32.def
@@ -0,0 +1,115 @@
+;//+-------------------------------------------------------------------------
+;//
+;// Microsoft Windows
+;// Copyright (C) Microsoft Corporation, 1992 - 1993.
+;//
+;// File: storag32.def
+;//
+;// Contents: storag32.dll module definition file
+;//
+;// History: 23-Sep-92 DrewB Created from multiple def files
+;// 09-Oct-92 AlexT Added HEAPSIZE to 16-bit definitions
+;// 03-Feb-93 DrewB Changed docfile.def to storage.def
+;//
+;// Note: $(OLE)\storage.def is used for 16-bit builds
+;// $(CAIROLE)\ilib\storag32.def is used for non-Cairo 32-bit
+;// $(COMMON)\ilib\storag32.def is used for Cairo 32-bit builds
+;//
+;//--------------------------------------------------------------------------
+
+LIBRARY STORAG32
+DESCRIPTION 'Storage DLL'
+CODE DISCARDABLE LOADONCALL MOVABLE SHARED
+DATA LOADONCALL SINGLE MOVABLE
+
+EXPORTS
+
+#if defined (i386)
+
+ StgCreateDocfile@16 @1
+ StgCreateDocfileOnILockBytes@16 @2
+ StgOpenStorage@24 @3
+ StgOpenStorageOnILockBytes@24 @4
+ StgIsStorageFile@4 @5
+ StgIsStorageILockBytes@4 @6
+ StgSetTimes@16 @7
+#ifdef _CAIRO_
+ StgCreateStorage@20 @43
+ StgCreateStorageOnHandle@16 @44
+ StgOpenStorageOnHandle@12 @45
+ StgIsStorage@8 @46
+
+ FreeVariantArray@8 @50
+#endif
+
+ DfUnMarshalInterface@16 @102
+ DllGetClassObject@12 @103
+ DllGetClassObject=DllGetClassObject@12
+
+#if DBG == 1
+ DfDebug@8 @300
+ DfSetResLimit@8 @310
+ DfGetResLimit@4 @311
+ DfGetMemAlloced@0 @302
+ DfPrintAllocs@0 @303
+#endif
+
+#elif defined (_MIPS_)
+
+ StgCreateDocfile @1
+ StgCreateDocfileOnILockBytes @2
+ StgOpenStorage @3
+ StgOpenStorageOnILockBytes @4
+ StgIsStorageFile @5
+ StgIsStorageILockBytes @6
+ StgSetTimes @7
+#ifdef _CAIRO_
+ StgCreateStorage @43
+ StgCreateStorageOnHandle @44
+ StgOpenStorageOnHandle @45
+ StgIsStorage @46
+
+ FreeVariantArray @50
+#endif
+
+ DfUnMarshalInterface @102
+ DllGetClassObject @103
+
+#if DBG == 1
+ DfDebug @300
+ DfSetResLimit @310
+ DfGetResLimit @311
+ DfGetMemAlloced @302
+ DfPrintAllocs @303
+#endif
+
+#elif defined (_PPC_)
+
+ StgCreateDocfile @1
+ StgCreateDocfileOnILockBytes @2
+ StgOpenStorage @3
+ StgOpenStorageOnILockBytes @4
+ StgIsStorageFile @5
+ StgIsStorageILockBytes @6
+ StgSetTimes @7
+#ifdef _CAIRO_
+ StgCreateStorage @43
+ StgCreateStorageOnHandle @44
+ StgOpenStorageOnHandle @45
+ StgIsStorage @46
+
+ FreeVariantArray @50
+#endif
+
+ DfUnMarshalInterface @102
+ DllGetClassObject @103
+
+#if DBG == 1
+ DfDebug @300
+ DfSetResLimit @310
+ DfGetResLimit @311
+ DfGetMemAlloced @302
+ DfPrintAllocs @303
+#endif
+
+#endif // i386 - MIPS - PPC
diff --git a/private/ole32/ilib/uuidole.cxx b/private/ole32/ilib/uuidole.cxx
new file mode 100644
index 000000000..1dae8ed10
--- /dev/null
+++ b/private/ole32/ilib/uuidole.cxx
@@ -0,0 +1,15 @@
+/*
+ uuid.cpp Include guid's to produce a GUID lib file.
+
+ THIS IS TEMPORARY!!!
+
+*/
+
+#include <windows.h>
+#include <ole2.h>
+#include <initguid.h>
+//this is a pretty bad hack...we need to do something better
+#include <privguid.h>
+#include <ole1cls.h>
+
+
diff --git a/private/ole32/makefile b/private/ole32/makefile
new file mode 100644
index 000000000..ea6157fa4
--- /dev/null
+++ b/private/ole32/makefile
@@ -0,0 +1,28 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+default: all
+
+!include $(CAIROLE)\cairole.mk
+
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/ole232/advise/daholder.cpp b/private/ole32/ole232/advise/daholder.cpp
new file mode 100644
index 000000000..224b8a3bc
--- /dev/null
+++ b/private/ole32/ole232/advise/daholder.cpp
@@ -0,0 +1,1479 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// daholder.cpp
+//
+// Contents:
+// concrete implementation of IDataAdviseHolder, a helper
+// class for OLE server implementors
+//
+// Classes:
+// CDAHolder
+//
+// Functions:
+// CreateDataAdviseHolder
+//
+// History:
+// 01/20/95 - t-ScottH- added Dump methods to CDAHolder and
+// CEnumSTATDATA classes
+// added DumpCDAHolder & DumpCEnumSTATDATA APIs
+// put class definitions in header file daholder.h
+// 03/09/94 - AlexGo - fixed bugs with the enumerator and
+// disconnecting of bad advise sinks
+// 01/24/94 - AlexGo - first pass at conversion to Cairo-style
+// memory allocation
+// 01/11/94 - AlexGo - added VDATEHEAP macros to all functions and
+// methods
+// 12/09/93 - ChrisWe - fix test for error code after CoGetMalloc()
+// in CDAHolder::Advise
+// 11/22/93 - ChrisWe - replace overloaded ==, != with
+// IsEqualIID and IsEqualCLSID
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#include <le2int.h>
+#include "daholder.h"
+
+#ifdef _DEBUG
+#include "dbgdump.h"
+#endif // _DEBUG
+
+#pragma SEG(daholder)
+
+NAME_SEG(DaHolder)
+ASSERTDATA
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// CreateDataAdviseHolder, public
+//
+// Synopsis:
+// Creates an instance of the CDAHolder class
+//
+// Arguments:
+// [ppDAHolder] -- pointer to where to return the created
+// IDataAdviseHolder instance
+//
+// Returns:
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CreateDataAdviseHolder)
+STDAPI CreateDataAdviseHolder(IDataAdviseHolder FAR* FAR* ppDAHolder)
+{
+ VDATEHEAP();
+
+ OLETRACEIN((API_CreateDataAdviseHolder, PARAMFMT("ppDAHolder= %p"), ppDAHolder));
+
+ *ppDAHolder = new FAR CDAHolder(); // task memory; use MEMCTX_TASK below
+
+ CALLHOOKOBJECTCREATE(*ppDAHolder ? NOERROR : E_OUTOFMEMORY,
+ CLSID_NULL,
+ IID_IDataAdviseHolder,
+ (IUnknown **)ppDAHolder);
+
+ HRESULT hr;
+
+ hr = *ppDAHolder ? NOERROR : ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+ OLETRACEOUT((API_CreateDataAdviseHolder, hr));
+
+ return hr;
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDAHolder::CDAHolder, public
+//
+// Synopsis:
+// constructor
+//
+// Effects:
+// returns with reference count set to 1
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDAHolder_ctor)
+CDAHolder::CDAHolder()
+{
+ VDATEHEAP();
+
+ // set reference count
+ SafeAddRef();
+
+ // connections run from [1..infinity)
+ m_dwConnection = 1;
+
+ // there are no STATDATA entries yet
+ m_iSize = 0;
+ m_pSD = NULL;
+
+ GET_A5();
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDAHolder::~CDAHolder, private
+//
+// Synopsis:
+// destructor
+//
+// Effects:
+// frees resources associated with the CDAHolder
+//
+// Notes:
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+CDAHolder::~CDAHolder()
+{
+ VDATEHEAP();
+
+ int iData; // counts array entries as we scan the array
+ STATDATA FAR *pSD; // used to scan the array of STATDATA
+
+ // release the array, if we've allocated it
+
+ // REVIEW: If we want to be really safe, we should release
+ // the stat data's either before or after our destructor.
+ // The release of the advise sinks in the statdata elements
+ // could possible result in us being re-entered (a potential
+ // awkward state for the middle of a class destructor).
+
+ // However, since nobody should be accesssing the advise
+ // holder if we get to the destructor (since the reference
+ // count would have to be zero), we are going to bag on
+ // this modification for Daytona RC1.
+
+ if (m_pSD)
+ {
+ for(pSD = m_pSD, iData = 0; iData < m_iSize; ++pSD, ++iData)
+ UtReleaseStatData(pSD);
+
+ PubMemFree(m_pSD);
+ }
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDAHolder::QueryInterface, public
+//
+// Synopsis:
+// implements IUnknown::QueryInterface
+//
+// Arguments:
+// [iid] -- IID of the desired interface
+// [ppv] -- pointer to a location to return the interface at
+//
+// Returns:
+// E_NOINTERFACE, S_OK
+//
+// Notes:
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDAHolder_QueryInterface)
+STDMETHODIMP CDAHolder::QueryInterface(REFIID iid, LPVOID FAR* ppv)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ if (IsEqualIID(iid, IID_IUnknown) ||
+ IsEqualIID(iid, IID_IDataAdviseHolder))
+ {
+ *ppv = (IDataAdviseHolder FAR *)this;
+ AddRef();
+ return NOERROR;
+ }
+
+ *ppv = NULL;
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDAHolder::AddRef, public
+//
+// Synopsis:
+// implements IUnknown::AddRef
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDAHolder_AddRef)
+STDMETHODIMP_(ULONG) CDAHolder::AddRef()
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ return SafeAddRef();
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDAHolder::Release, public
+//
+// Synopsis:
+// implementa IUnknown::Release
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDAHolder_Release)
+STDMETHODIMP_(ULONG) CDAHolder::Release()
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ return SafeRelease();
+
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDAHolder::Advise, public
+//
+// Synopsis:
+// Add a new advise sink to the list of advise sinks
+// managed by the data advise holder, and which will be notified
+// if a change is indicated using other IDataAdviseHolder
+// methods. A data format is specified, and new data will be
+// sent to the sink in that format, when a change occurs.
+//
+// Arguments:
+// [pDataObject] -- the source data object that presentations
+// should be taken from if an advise is to occur
+// immediately
+// [pFetc] -- The data format the advise sink is interested in
+// [advf] -- control flags
+// [pAdvSink] -- the advise sink being registered
+// [pdwConnection] -- a token that can be used to identify the
+// advise sink later on
+//
+// Returns:
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+// 08/02/94 - AlexGo - stabilized
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDAHolder_Advise)
+STDMETHODIMP CDAHolder::Advise(LPDATAOBJECT pDataObj, FORMATETC FAR* pFetc,
+ DWORD advf, IAdviseSink FAR* pAdvSink,
+ DWORD FAR* pdwConnection)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+ int iSDScan; // index of the scan of SD array entries
+ int iSDFree; // index of first free SD entry, or (-1)
+ STATDATA FAR *pSD; // scans across the array of STATDATA entries
+
+ if( IsZombie() )
+ {
+ return ResultFromScode(CO_E_RELEASED);
+ }
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if (pDataObj)
+ VDATEIFACE(pDataObj);
+
+ VDATEPTRIN(pFetc, FORMATETC);
+ VDATEIFACE(pAdvSink);
+
+ if (!HasValidLINDEX(pFetc))
+ {
+ return(DV_E_LINDEX);
+ }
+
+ // Validate where to return the connection.
+ if (pdwConnection)
+ {
+ VDATEPTRIN(pdwConnection, DWORD);
+
+ // Default to error case
+ *pdwConnection = 0;
+ }
+
+ // scan and remove all unconnected advise sinks
+ for(iSDFree = (-1), pSD = m_pSD, iSDScan = 0; iSDScan < m_iSize;
+ ++pSD, ++iSDScan)
+ {
+ // REVIEW, why do we have to go polling these?
+ if (!pSD->pAdvSink || !IsValidInterface(pSD->pAdvSink))
+ {
+ // not valid, don't try to release
+ pSD->pAdvSink = NULL;
+ goto RemoveBadSD;
+ }
+ else if (!CoIsHandlerConnected(pSD->pAdvSink))
+ {
+ // sink no longer connected, release
+ RemoveBadSD:
+ // release any data. UtReleaseStatData will
+ // zero out the statdata structure.
+ UtReleaseStatData(pSD);
+
+ }
+
+ // if we're still looking for a free entry, note if this one
+ // is free
+ if ((iSDFree == (-1)) && (pSD->dwConnection == 0))
+ iSDFree = iSDScan;
+ }
+
+ // should we send the data immediately?
+ if (advf & ADVF_PRIMEFIRST)
+ {
+ // We are not going to honor ADVF_PRIMEFIRST if pDataObj is
+ // NULL, even when ADVF_NODATA is specfied. We want it to be
+ // this way so that the apps which don't have any data at
+ // startup time, could pass in NULL for pDataObject and
+ // prevent us from sending any OnDataChange() notification.
+ // Later when they have the data avaliable they can call
+ // SendOnDataChange. (SRINIK)
+
+ if (pDataObj)
+ {
+ STGMEDIUM stgmed;
+
+ stgmed.tymed = TYMED_NULL;
+ stgmed.pUnkForRelease = NULL;
+
+ if (advf & ADVF_NODATA)
+ {
+ // don't sent data, send only the notification
+ pAdvSink->OnDataChange(pFetc, &stgmed);
+
+ }
+ else
+ {
+ // get data from object and send it to sink
+ if (pDataObj->GetData(pFetc,
+ &stgmed) == NOERROR)
+ {
+ pAdvSink->OnDataChange(pFetc, &stgmed);
+ ReleaseStgMedium(&stgmed);
+ }
+ }
+
+ // if we only have to advise once, we've done so, and
+ // needn't make an entry in the advise array
+ if (advf & ADVF_ONLYONCE)
+ return NOERROR;
+ }
+ }
+
+ // remove the ADVF_PRIMEFIRST from flags.
+ advf &= (~ADVF_PRIMEFIRST);
+
+ // find a free list entry we can use, if we haven't got one
+ if (iSDFree == (-1))
+ {
+ HRESULT hr;
+
+ // REVIEW, can we share array reallocation code with
+ // oaholder.cpp? Why can't we just use realloc?
+
+ // didn't find any free array entries above; since that
+ // scanned the whole array, have to allocate new entries
+ // here
+
+ pSD = (STATDATA FAR *)PubMemAlloc(sizeof(STATDATA)*(m_iSize+
+ CDAHOLDER_GROWBY));
+
+ if (pSD == NULL)
+ hr = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ else
+ {
+ // copy the old data over, if any, and free it
+ if (m_pSD)
+ {
+ _xmemcpy((void FAR *)pSD, (void FAR *)m_pSD,
+ sizeof(STATDATA)*m_iSize);
+
+ PubMemFree(m_pSD);
+ }
+
+ // initialize newly allocated memory
+
+ _xmemset((void FAR *)(pSD+m_iSize), 0,
+ sizeof(STATDATA)*CDAHOLDER_GROWBY);
+
+ // this is the index of the first free element
+ iSDFree = m_iSize;
+
+ // set up the STATDATA array
+ m_pSD = pSD;
+ m_iSize += CDAHOLDER_GROWBY;
+
+ hr = NOERROR;
+ }
+
+ if (hr != NOERROR)
+ {
+ return(hr);
+ }
+ }
+
+ // if we got here, we can add the new entry, and its index is iSDFree
+
+ // point at the new element
+ pSD = m_pSD+iSDFree;
+
+ // Let the advise get added to the list
+ UtCopyFormatEtc(pFetc, &pSD->formatetc);
+ pSD->advf = advf;
+ pAdvSink->AddRef();
+ pSD->pAdvSink = pAdvSink;
+ pSD->dwConnection = m_dwConnection++;
+
+ // return connection if user requested it
+ if (pdwConnection)
+ *pdwConnection = pSD->dwConnection;
+
+ return NOERROR;
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDAHolder::Unadvise, public
+//
+// Synopsis:
+// removes the advise sink specified from the list of those
+// registered to receive notifications from this data advise
+// holder
+//
+// Arguments:
+// [dwConnection] -- token that identifies which advise sink
+// to remove; this will have come from Advise().
+//
+// Returns:
+// OLE_E_NOCONNECTION, S_OK
+//
+// Notes:
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDAHolder_Unadvise)
+STDMETHODIMP CDAHolder::Unadvise(DWORD dwConnection)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+ int iData; // index into the STATDATA array
+ STATDATA FAR *pSD; // pointer into the STATDATA array
+
+ // protect this against being released via a circular reference
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ for (pSD = m_pSD, iData = 0; iData < m_iSize; ++pSD, ++iData)
+ {
+ // is this the entry we're looking for?
+ if (pSD->dwConnection == dwConnection)
+ {
+ // release resources for the entry. UtReleaseStatData
+ // will zero the statdata.
+
+ UtReleaseStatData(pSD);
+
+ return NOERROR;
+ }
+ }
+
+ // if we found what we were looking for in the loop, we'd return
+ // from there, and never get here. Since we didn't, it must be
+ // that there's no such connection
+ return ReportResult(0, OLE_E_NOCONNECTION, 0, 0);
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDAHolder::SendOnDataChange, public
+//
+// Synopsis:
+// Send an OnDataChange notification to all advise sinks
+// registered with this data advise holder.
+//
+// Arguments:
+// [pDataObject] -- the data object to get data from to send
+// to the advise sinks
+// [dwReserved] --
+// [advf] -- control flags
+//
+// Returns:
+// S_OK
+//
+// Notes:
+// More than one advise sink may be interested in obtaining
+// data in the same format. It may be expensive for the data
+// object to create copies of the data in requested formats.
+// Therefore, when a change is signalled, the data formats
+// are cached. As each advise sink is to be notified, we
+// check to see if the format it is requesting has already been
+// gotten from the data object (with GetData().) If it has,
+// then we simply send that copy again. If not, we get the
+// new format, and add that to the cache.
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDAHolder_SendOnDataChange)
+STDMETHODIMP CDAHolder::SendOnDataChange(IDataObject FAR* pDataObject,
+ DWORD dwReserved, DWORD advf)
+{
+ VDATEHEAP();
+
+ A5_PROLOG(this);
+ HRESULT hresult = NOERROR; // error status so far
+ UINT cFetcTotal; // maximum number of formats we will cache
+ UINT cFetcGotten; // the actual number of formats in the cache
+ UINT cFetc; // the index of the format in the cache under consideration
+ FORMATETC FAR* rgFetc; // a record of the cached presentations
+ STGMEDIUM FAR* rgStgmed; // the cached data presentations
+ UINT cStatData; // a counter for the STATDATA array elements
+ STATDATA FAR *pSD; // a pointer into the array of STATDATA elements
+
+ VDATEIFACE(pDataObject);
+
+ // in the worst case, every advise sink has requested a unique
+ // data format, and we won't get any duplicates. This means that
+ // we will wind up caching all of them.
+ cFetcTotal = m_iSize;
+
+ // if there are no entries, there's nothing to do
+ if (cFetcTotal == 0)
+ return NOERROR;
+
+ // some advise sinks may use these notifications to change their
+ // requested notifications; due to possible circular references,
+ // this could to lead to a release of this holder. Protect against
+ // this here; this is released after most work is done, towards the
+ // end of this function
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ // alloc rgFetc and rgStgmed to accomodate all the cache entries
+ // if either fails to be allocated, we quit
+ rgFetc = (FORMATETC FAR *)PubMemAlloc(cFetcTotal * sizeof(FORMATETC));
+ rgStgmed = (STGMEDIUM FAR *)PubMemAlloc(cFetcTotal * sizeof(STGMEDIUM));
+
+ if (rgFetc == NULL || rgStgmed == NULL)
+ {
+ hresult = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ goto FreeExit;
+ }
+
+ // zero out STDMEDIUM entries
+ _xmemset((void FAR *)rgStgmed, 0, sizeof(STGMEDIUM)*cFetcTotal);
+
+ // ensure we have the right data and send to each advise sink
+ // note the loop is bounded by cFetcTotal, preventing additional
+ // sinks from being notified, if they are registered during these
+ // notifications. cStatData is not used in the loop body, so it
+ // counts down
+
+ for (cFetcGotten = 0, pSD = m_pSD, cStatData = cFetcTotal;
+ cStatData; ++pSD, --cStatData)
+ {
+ // if this slot is not in use, skip it
+ if (!pSD->dwConnection)
+ continue;
+
+ // if the sink is not interested in presentation data,
+ // proceed to notify it immediately, unless this notification
+ // is announcing the termination of the source
+ if ((pSD->advf & ADVF_NODATA) &&
+ !(advf & ADVF_DATAONSTOP))
+ {
+ STGMEDIUM stgmed;
+
+ // don't sent data; use format from collection
+ // and null STGMEDIUM.
+ // REVIEW, should this be done once, up above?
+ stgmed.tymed = TYMED_NULL;
+ stgmed.pUnkForRelease = NULL;
+ pSD->pAdvSink->OnDataChange(&pSD->formatetc, &stgmed);
+
+ // REVIEW, what does this do for NULL?
+ // if nothing, we can share a stdmedNULL, as above
+ ReleaseStgMedium(&stgmed);
+
+ // clean up at end of loop
+ goto DataSent;
+ }
+
+ // if the sink is interested in data at the time of
+ // termination, and the source is not terminating, OR, the
+ // sink is not interested in data at the time of termination,
+ // and we are terminating, skip this sink, and proceed
+ if ((pSD->advf & ADVF_DATAONSTOP) !=
+ (advf & ADVF_DATAONSTOP))
+ continue;
+
+ // check the requested format against the list of formats
+ // for which we've already retrieved the presentation data.
+ // if there is a match, proceed to send that data immediately
+ // from here on in this loop body, cFetc is the index of the
+ // data presentation to send to the current sink
+ // REVIEW PERF: this is an n-squared algorithm;
+ // we check the array of cached presentations for each
+ // advise sink
+ for (cFetc = 0; cFetc < cFetcGotten; ++cFetc)
+ {
+ // if match, continue outer loop
+ if (UtCompareFormatEtc(&rgFetc[cFetc],
+ &pSD->formatetc) == UTCMPFETC_EQ)
+ goto SendThisOne;
+ }
+
+ // if we get here, we have not already fetched presentation
+ // data that matches the requested format
+
+ // init FORMATETC (copy of needed one)
+ // STDMEDIUM was initialized after its allocation to all NULL
+ rgFetc[cFetcGotten] = pSD->formatetc;
+
+ // get the data in the requested format from the data object
+ // REVIEW: assume STGMEDIUM untouched if error
+ // (i.e., still null)
+ hresult = pDataObject->GetData(&rgFetc[cFetcGotten],
+ &rgStgmed[cFetcGotten]);
+
+ // REVIEW, what is this checking?
+ AssertOutStgmedium(hresult, &rgStgmed[cFetcGotten]);
+
+ // the presentation to send is the newly cached one
+ // there is now one more entry in the cache array
+ cFetc = cFetcGotten++;
+
+ SendThisOne:
+ // when we get here, rgFetc[cFetc] is the format to send to the
+ // current advise sink
+
+ // send change notification with requested data
+
+ // The advise sink could have disappeared in the meantime
+ // (if the the GetData call above resulted in an Unadvise,
+ // for example), so we must validate the pAdvSInk first.
+ // pSD will remain a valid regardless, and the advise
+ // flags will have been zero'd, so it is safe to proceed
+ // through the loop without "continue"ing.
+
+ if (pSD->pAdvSink)
+ {
+ pSD->pAdvSink->OnDataChange(&rgFetc[cFetc],
+ &rgStgmed[cFetc]);
+ }
+
+
+ DataSent:
+ // When we get here, something has been sent, possibly
+ // an empty storage medium
+
+ // if the sink requested to only be notified once, we
+ // can free it here
+ if (pSD->advf & ADVF_ONLYONCE)
+ {
+ // free the stat data. UtReleaseStatData will
+ // zero the statdata, thus marking the connection
+ // as invalid.
+
+ UtReleaseStatData(pSD);
+
+ }
+ }
+
+ // free all stgmeds retrieved; FORMATETC.ptd was not allocated
+ for (cFetc = 0; cFetc < cFetcGotten; ++cFetc)
+ ReleaseStgMedium(&rgStgmed[cFetc]);
+
+ hresult = NOERROR;
+
+FreeExit:
+ if (rgFetc != NULL)
+ PubMemFree(rgFetc);
+
+ if (rgStgmed != NULL)
+ PubMemFree(rgStgmed);
+
+ RESTORE_A5();
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDAHolder::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppsz] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 20-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CDAHolder::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszCSafeRefCount;
+ char *pszSTATDATA;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(1000);
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ pszCSafeRefCount = DumpCSafeRefCount( (CSafeRefCount *)this, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CSafeRefCount: " << endl;
+ dstrDump << pszCSafeRefCount;
+ CoTaskMemFree(pszCSafeRefCount);
+
+ dstrDump << pszPrefix << "Next Connection ID = " << m_dwConnection << endl;
+
+ dstrDump << pszPrefix << "No. of STATDATA elements = " << m_iSize << endl;
+
+ for (i = 0; i < m_iSize; i++)
+ {
+ pszSTATDATA = DumpSTATDATA( &m_pSD[i], ulFlag, nIndentLevel + 1) ;
+ dstrDump << pszPrefix << "STATDATA element: " << i << endl;
+ dstrDump << pszSTATDATA;
+ CoTaskMemFree(pszSTATDATA);
+ }
+
+ // clean up and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif //_DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCDAHolder, public (_DEBUG only)
+//
+// Synopsis: calls the CDAHolder::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pIDAH] - pointer to IDAHolder (which we cast to CDAHolder)
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 20-Jan-95 t-ScottH author
+//
+// Notes:
+//
+// This API !!REQUIRES!! that class CDAHolder inherits from IDataAdviseHolder
+// first in order that we can pass in a parameter as a pointer to an
+// IDataAdviseHolder and then cast it to a CDAHolder.
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCDAHolder(IDataAdviseHolder *pIDAH, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pIDAH == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ CDAHolder *pCDAH = (CDAHolder *)pIDAH;
+
+ hresult = pCDAH->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CEnumSTATDATA::CEnumSTATDATA, public
+//
+// Synopsis:
+// constructor
+//
+// Effects:
+// sets reference count to 1
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CEnumSTATDATA_ctor)
+CEnumSTATDATA::CEnumSTATDATA(CDAHolder FAR* pHolder, int iDataStart)
+{
+ VDATEHEAP();
+
+ GET_A5();
+
+ // set reference count
+ m_refs = 1;
+
+ // first element to examine for return
+ m_iDataEnum = iDataStart;
+
+ // initialize pointer to holder, and addref, so it doesn't go
+ // away while enumerator is alive
+ (m_pHolder = pHolder)->AddRef();
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDAHolder::~CDAHolder, private
+//
+// Synopsis:
+// destructor
+//
+// Notes:
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CEnumSTATDATA_dtor)
+CEnumSTATDATA::~CEnumSTATDATA()
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ m_pHolder->Release();
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CEnumSTATDATA::QueryInterface, public
+//
+// Synopsis:
+// implements IUnknown::QueryInterface
+//
+// Arguments:
+// [iid] -- IID of the desired interface
+// [ppv] -- pointer to a location to return the interface at
+//
+// Returns:
+// E_NOINTERFACE, S_OK
+//
+// Notes:
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CEnumSTATDATA_QueryInterface)
+STDMETHODIMP CEnumSTATDATA::QueryInterface(REFIID iid, LPVOID FAR* ppv)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ if (IsEqualIID(iid, IID_IUnknown) ||
+ IsEqualIID(iid, IID_IEnumSTATDATA))
+ {
+ *ppv = (IEnumSTATDATA FAR *)this;
+ AddRef();
+ return NOERROR;
+ }
+
+ *ppv = NULL;
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CEnumSTATDATA::AddRef, public
+//
+// Synopsis:
+// implements IUnknown::AddRef
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CEnumSTATDATA_AddRef)
+STDMETHODIMP_(ULONG) CEnumSTATDATA::AddRef()
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ return ++m_refs;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CEnumSTATDATA::Release, public
+//
+// Synopsis:
+// implementa IUnknown::Release
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CEnumSTATDATA_Release)
+STDMETHODIMP_(ULONG) CEnumSTATDATA::Release()
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ if (--m_refs == 0)
+ {
+ delete this;
+ return 0;
+ }
+
+ return m_refs;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CEnumSTATDATA::Next, public
+//
+// Synopsis:
+// implements IEnumSTATDATA::Next()
+//
+// Effects:
+//
+// Arguments:
+// [celt] -- number of elements requested on this call
+// [rgelt] -- pointer to an array of STATDATAs where copies of
+// the elements can be returned
+// [pceltFectched] -- a pointer to where to return the number of
+// elements actually fetched. May be NULL
+//
+// Returns:
+// S_FALSE, S_OK
+//
+// Notes:
+//
+// History:
+// 03/09/94 - AlexGo - the enumerator no longer enumerates
+// "empty" statdata's in the m_pSD array.
+// 11/01/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CEnumSTATDATA_Next)
+STDMETHODIMP CEnumSTATDATA::Next(ULONG celt, STATDATA FAR *rgelt,
+ ULONG FAR* pceltFetched)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+ UINT ielt; // count of the number of elements fetched so far
+
+ for (ielt = 0; (ielt < celt) && (m_iDataEnum < m_pHolder->m_iSize);
+ m_iDataEnum++)
+ {
+ if( m_pHolder->m_pSD[m_iDataEnum].dwConnection != 0)
+ {
+ ielt++;
+ // copy all bits; AddRef and copy DVTARGETDEVICE
+ // separately
+ UtCopyStatData(&m_pHolder->m_pSD[m_iDataEnum],
+ rgelt++);
+ }
+ }
+
+ // return number of elements fetched, if required
+ if (pceltFetched)
+ *pceltFetched = ielt;
+
+ // no error, if exactly the requested number of elements was fetched
+ return ielt == celt ? NOERROR : ReportResult(0, S_FALSE, 0, 0);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDAHolder::Skip, public
+//
+// Synopsis:
+// implements IEnumSTATDATA::Skip
+//
+// Arguments:
+// [celt] -- the number of elements in the collection to skip
+// over
+//
+// Returns:
+// S_FALSE, S_OK
+//
+// Notes:
+//
+// History:
+// 11/01/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CEnumSTATDATA_Skip)
+STDMETHODIMP CEnumSTATDATA::Skip(ULONG celt)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+ STATDATA FAR *pSD; // scans over the array of STATDATA entries
+
+ // if the enumeration would take us off the end of the array
+ // mark the enumeration as complete
+ if (m_iDataEnum + celt > (ULONG)m_pHolder->m_iSize)
+ {
+ m_iDataEnum = m_pHolder->m_iSize;
+
+ return ReportResult(0, S_FALSE, 0, 0);
+ }
+
+
+ // skip over valid entries in the array, counting down until
+ // we don't have to skip over any more, or until we get to
+ // the end of the array
+ for(pSD = m_pHolder->m_pSD+m_iDataEnum;
+ celt && (m_iDataEnum < m_pHolder->m_iSize);
+ ++m_iDataEnum)
+ {
+ // if the connection is valid, count it as a skipped
+ // enumerated item
+ if (pSD->dwConnection != 0)
+ --celt;
+ }
+
+ // if we could skip them all, indicate by non-error return
+ if (celt == 0)
+ return(NOERROR);
+
+ return(ReportResult(0, S_FALSE, 0, 0));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDAHolder::Reset, public
+//
+// Synopsis:
+// implements IEnumSTATDATA::Reset
+//
+// Arguments:
+// none
+//
+// Returns:
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/01/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CEnumSTATDATA_Reset)
+STDMETHODIMP CEnumSTATDATA::Reset()
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ // move back to the beginning of the STATDATA array
+ m_iDataEnum = 0;
+
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDAHolder::Clone, public
+//
+// Synopsis:
+// implements IEnumSTATDATA::Clone
+//
+// Arguments:
+// none
+//
+// Returns:
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 11/01/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CEnumSTATDATA_Clone)
+STDMETHODIMP CEnumSTATDATA::Clone(LPENUMSTATDATA FAR* ppenum)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ *ppenum = new FAR CEnumSTATDATA(m_pHolder, m_iDataEnum);
+
+ return *ppenum ? NOERROR : ReportResult(0, E_OUTOFMEMORY, 0, 0);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDAHolder::EnumAdvise, public
+//
+// Synopsis:
+// implements IDataAdviseHolder::EnumAdvise
+//
+// Effects:
+// creates an enumerator for the registered advise sinks
+//
+// Arguments:
+// [ppenumAdvise] -- a pointer to where to return the enumerator
+//
+// Returns:
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 11/01/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDAHolder_EnumAdvise)
+STDMETHODIMP CDAHolder::EnumAdvise(IEnumSTATDATA FAR* FAR* ppenumAdvise)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ VDATEPTROUT(ppenumAdvise, IEnumSTATDATA FAR*);
+
+ // REVIEW, memory leak if bad ppenumAdvise pointer
+ *ppenumAdvise = new FAR CEnumSTATDATA(this, 0);
+
+ return *ppenumAdvise ? NOERROR : ReportResult(0, E_OUTOFMEMORY, 0, 0);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumSTATDATA::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppsz] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 20-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CEnumSTATDATA::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszDAH;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(1000);
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "No. of References = " << m_refs << endl;
+
+ dstrDump << pszPrefix << "Index to next element = " << m_iDataEnum << endl;
+
+ if (m_pHolder != NULL)
+ {
+ pszDAH = DumpCDAHolder(m_pHolder, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "Data Advise Holder: " << endl;
+ dstrDump << pszDAH;
+ CoTaskMemFree(pszDAH);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "pCDAHolder = " << m_pHolder << endl;
+ }
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCEnumSTATDATA, public (_DEBUG only)
+//
+// Synopsis: calls the CEnumSTATDATA::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pESD] - pointer to CEnumSTATDATA
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 20-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCEnumSTATDATA(CEnumSTATDATA *pESD, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pESD == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pESD->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
diff --git a/private/ole32/ole232/advise/daytona/makefile b/private/ole32/ole232/advise/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/ole232/advise/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/ole232/advise/daytona/sources b/private/ole32/ole232/advise/daytona/sources
new file mode 100644
index 000000000..83fb75262
--- /dev/null
+++ b/private/ole32/ole232/advise/daytona/sources
@@ -0,0 +1,78 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = ole232
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= advise
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..\..\inc
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+
+SOURCES= \
+ ..\daholder.cpp \
+ ..\oaholder.cpp
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
+!include ..\sources.inc
diff --git a/private/ole32/ole232/advise/depend.mk b/private/ole32/ole232/advise/depend.mk
new file mode 100644
index 000000000..bd426e9e8
--- /dev/null
+++ b/private/ole32/ole232/advise/depend.mk
@@ -0,0 +1,60 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\daholder.obj $(OBJDIR)\daholder.lst: .\daholder.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\oaholder.obj $(OBJDIR)\oaholder.lst: .\oaholder.cpp \
+ $(CAIROLE)\ole232\inc\oaholder.h $(CAIROLE)\common\cobjerr.h \
+ $(CAIROLE)\common\rpcferr.h $(CAIROLE)\h\coguid.h \
+ $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h $(CAIROLE)\h\initguid.h \
+ $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h $(CAIROLE)\h\ole2dbg.h \
+ $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h $(CAIROLE)\h\storage.h \
+ $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h $(CAIROLE)\ih\ole2sp.h \
+ $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\limits.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\malloc.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\wchar.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\widewrap.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winmm.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
diff --git a/private/ole32/ole232/advise/dirs b/private/ole32/ole232/advise/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/ole232/advise/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/ole232/advise/filelist.mk b/private/ole32/ole232/advise/filelist.mk
new file mode 100644
index 000000000..ad996d22a
--- /dev/null
+++ b/private/ole32/ole232/advise/filelist.mk
@@ -0,0 +1,50 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = advise.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CPPFILES = \
+ .\daholder.cpp \
+ .\oaholder.cpp \
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PFILE =
+
+
+!include $(CAIROLE)\ole232\ole.mk
diff --git a/private/ole32/ole232/advise/makefile b/private/ole32/ole232/advise/makefile
new file mode 100644
index 000000000..1725b5e9a
--- /dev/null
+++ b/private/ole32/ole232/advise/makefile
@@ -0,0 +1,26 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1992.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/ole232/advise/oaholder.cpp b/private/ole32/ole232/advise/oaholder.cpp
new file mode 100644
index 000000000..a796e9a6c
--- /dev/null
+++ b/private/ole32/ole232/advise/oaholder.cpp
@@ -0,0 +1,1002 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// oaholder.cpp
+//
+// Contents:
+// COAHolder, a concrete implementation of IOleAdviseHolder,
+// a helper class
+//
+// Classes:
+// COAHolder
+//
+// Functions:
+// CreateOleAdviseHolder
+//
+// History:
+// 31-Jan-95 t-ScottH added _DEBUG only Dump method to the
+// COAHolder class and a DumpCOAHolder
+// API
+// 03/10/94 - RickSa - added call logging and fixed bugs with
+// inserting advises
+// 01/24/94 - AlexGo - first pass at converting to Cairo style
+// memory allocation
+// 01/11/93 - AlexGo - added VDATEHEAP macros to all functions
+// and methods
+// 11/22/93 - ChrisWe - replace overloaded ==, != with
+// IsEqualIID and IsEqualCLSID
+// 10/28/93 - ChrisWe - file cleanup and inspection for Cairo
+//
+//-----------------------------------------------------------------------------
+
+#include <le2int.h>
+#include <oaholder.h>
+#include <limits.h>
+
+#ifdef _DEBUG
+#include <dbgdump.h>
+#endif // _DEBUG
+
+#pragma SEG(oaholder)
+
+NAME_SEG(OaHolder)
+ASSERTDATA
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// CreateDataAdviseHolder, public API
+//
+// Synopsis:
+// Creates an instance of the COAHolder
+//
+// Arguments:
+// [ppOAHolder] -- place to return pointer to newly allocated
+// advise holder
+//
+// Returns:
+// E_INVALIDARG, if ppOAHolder is NULL
+// E_OUTOFMEMORY
+//
+// Notes:
+//
+// History:
+// 10/28/93 - ChrisWe - file cleanup and inspection
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CreateOleAdviseHolder)
+STDAPI CreateOleAdviseHolder(IOleAdviseHolder FAR* FAR* ppOAHolder)
+{
+ OLETRACEIN((API_CreateOleAdviseHolder, PARAMFMT("ppOAHolder= %p"), ppOAHolder));
+
+ VDATEHEAP();
+
+ HRESULT hr;
+
+ VDATEPTROUT_LABEL(ppOAHolder, IOleAdviseHolder FAR* FAR*, errRtn, hr);
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CreateOleAdviseHolder ( %p )"
+ "\n", NULL, ppOAHolder));
+
+
+ *ppOAHolder = new FAR COAHolder(); // task memory; hard coded below
+
+ hr = *ppOAHolder
+ ? NOERROR : ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CreateOleAdviseHolder ( %lx )\n",
+ "[ %p ]\n", NULL, hr, *ppOAHolder));
+
+ CALLHOOKOBJECTCREATE(hr, CLSID_NULL, IID_IOleAdviseHolder,
+ (IUnknown **)ppOAHolder);
+
+errRtn:
+ OLETRACEOUT((API_CreateOleAdviseHolder, hr));
+
+ return hr;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COAHolder::COAHolder, public
+//
+// Synopsis:
+// Initializes COAHolder
+//
+// Effects:
+// Sets reference count to 1
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 10/28/93 - ChrisWe - file cleanup and inspection
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COAHolder_ctor)
+COAHolder::COAHolder()
+{
+ VDATEHEAP();
+
+ // set reference count to 1
+ SafeAddRef();
+
+ // no sink pointers yet
+ m_iSize = 0;
+ m_ppIAS = NULL;
+
+ GET_A5();
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COAHolder::~COAHolder, private
+//
+// Synopsis:
+// destructor, frees managed advise sinks
+//
+// Arguments:
+// none
+//
+// Requires:
+//
+// Notes:
+//
+// History:
+// 10/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COAHolder_dtor)
+COAHolder::~COAHolder()
+{
+ VDATEHEAP();
+
+ int iAdv;
+ IAdviseSink FAR *FAR *ppIAS;
+
+ M_PROLOG(this);
+
+ // free the array, if there is one
+ if (m_ppIAS)
+ {
+ // walk the array of advise sinks, freeing things
+ for (ppIAS = m_ppIAS, iAdv = 0; iAdv < m_iSize; ++ppIAS, ++iAdv)
+ {
+ SafeReleaseAndNULL((IUnknown **)ppIAS);
+ }
+
+ // free the array
+ PubMemFree(m_ppIAS);
+ }
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COAHolder::QueryInterface, public
+//
+// Synopsis:
+// implements IUnknown::QueryInterface
+//
+// Arguments:
+// [iid] -- the interface pointer desired
+// [ppv] -- pointer to where to return the requested interface
+// pointer
+//
+// Returns:
+// E_NOINTERFACE, if requested interface not available
+// S_OK
+//
+// Notes:
+//
+// History:
+// 10/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COAHolder_QueryInterface)
+STDMETHODIMP COAHolder::QueryInterface(REFIID iid, LPVOID FAR* ppv)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ VDATEPTROUT(ppv, LPVOID FAR *);
+
+ LEDebugOut((DEB_ITRACE,
+ "%p _IN COAHolder::QueryInterface ( %p , %p )"
+ "\n", this, iid, ppv));
+
+ HRESULT hr = ReportResult(0, E_NOINTERFACE, 0, 0);
+
+ if (IsEqualIID(iid, IID_IUnknown) ||
+ IsEqualIID(iid, IID_IOleAdviseHolder))
+ {
+ *ppv = (IOleAdviseHolder FAR *)this;
+ AddRef();
+ hr = NOERROR;
+ }
+ else
+ {
+ *ppv = NULL;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT COAHolder::QueryInterface ( %lx )"
+ " [ %p ]\n", this, hr, *ppv));
+
+ return hr;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COAHolder::AddRef, public
+//
+// Synopsis:
+// implements IUnknown::AddRef
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 10/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COAHolder_AddRef)
+STDMETHODIMP_(ULONG) COAHolder::AddRef()
+{
+ ULONG cRefs;
+
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ LEDebugOut((DEB_ITRACE, "%p _IN COAHolder::AddRef ( )\n", this));
+
+ cRefs = SafeAddRef();
+
+ LEDebugOut((DEB_ITRACE, "%p OUT COAHolder::AddRef ( %lu )\n", this,
+ cRefs));
+
+ return cRefs;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COAHolder::Release, public
+//
+// Synopsis:
+// implements IUnknown::Release
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 10/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COAHolder_Release)
+STDMETHODIMP_(ULONG) COAHolder::Release()
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ ULONG cRefs;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN COAHolder::Release ( )\n", this ));
+
+ cRefs = SafeRelease();
+
+ LEDebugOut((DEB_ITRACE, "%p OUT COAHolder::Release ( %lu )\n", this,
+ cRefs));
+
+ return cRefs;
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COAHolder::Advise, public
+//
+// Synopsis:
+// implements IOleAdviseHolder::Advise
+//
+// Effects:
+// Adds the newly specified advise sink the the list of
+// advisees that will be notified when a change is indicated
+// via other IOleAdviseHolder methods on this object
+//
+// Arguments:
+// [pAdvSink] -- the new advise sink to add the the list
+// [pdwConnection] -- pointer to a DWORD where an identifier will
+// be returned that can be used to identify this sink
+// later
+//
+// Returns:
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 10/28/93 - ChrisWe - file inspection and cleanup
+// 03/15/94 - AlexT Zero out new space after a realloc
+// 08/02/94 - AlexGo - stabilized
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COAHolder_Advise)
+STDMETHODIMP COAHolder::Advise(IAdviseSink FAR* pAdvSink,
+ DWORD FAR* pdwConnection)
+{
+ VDATEHEAP();
+
+ int iAdv; // records the first free entry found, or (-1)
+ int iAdvScan; // counts across array entries
+ IAdviseSink FAR *FAR *ppIAS; // points at the array entry being examined
+ IAdviseSink FAR *pIAS; // the actual entry at *ppIAS
+
+ M_PROLOG(this);
+ VDATEIFACE(pAdvSink);
+ HRESULT hr = NOERROR;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN COAHolder::Advise ( %p , %p )"
+ "\n", this, pAdvSink, pdwConnection));
+
+ // Validate where to return the connection.
+ if (pdwConnection)
+ {
+ VDATEPTRIN(pdwConnection, DWORD);
+
+ // Default to error case
+ *pdwConnection = 0;
+ }
+
+ // check our zombie state and stabilize. If we are in a zombie
+ // state, we do not want to be adding new advise sinks.
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( IsZombie() )
+ {
+ hr = ResultFromScode(CO_E_RELEASED);
+ goto errRtn;
+ }
+
+
+ // find an empty slot and clean up disconnected handlers
+ for (iAdv = (-1), ppIAS = m_ppIAS, iAdvScan = 0;
+ iAdvScan < m_iSize; ++ppIAS, ++iAdvScan)
+ {
+ if ((pIAS = *ppIAS) == NULL)
+ {
+ // NULL entries are handled below, to catch
+ // any of the below cases creating new NULL values
+ ;
+ }
+ else if (!IsValidInterface(pIAS))
+ {
+ // not valid; don't try to release
+ *ppIAS = NULL;
+ }
+ else if (!CoIsHandlerConnected(pIAS))
+ {
+ // advise sink not connected to server anymore; release
+ // REVIEW, why do we have to constantly poll these
+ // to see if they are ok?
+ pIAS->Release();
+ *ppIAS = NULL;
+ }
+
+ // if first NULL, save rather than extend array
+ if ((*ppIAS == NULL) && (iAdv == (-1)))
+ iAdv = iAdvScan;
+ }
+
+ // if we didn't find an empty slot, we have to add space
+ if (iAdv == (-1))
+ {
+
+ ppIAS = (IAdviseSink FAR * FAR *)PubMemRealloc(m_ppIAS,
+ sizeof(IAdviseSink FAR *)*(m_iSize + COAHOLDER_GROWBY));
+
+ if (ppIAS != NULL)
+ {
+ // zero out new space
+ _xmemset((void FAR *) (ppIAS + m_iSize), 0,
+ sizeof(IAdviseSink *) * COAHOLDER_GROWBY);
+ // this is the index of the new element to use
+ iAdv = m_iSize;
+
+ // replace the old array
+ m_ppIAS = ppIAS;
+ m_iSize += COAHOLDER_GROWBY;
+ }
+ else
+ {
+ // quit if there was an error
+ hr = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // if we get here, iAdv is the element to use; if the addition
+ // was not possible, function would have returned before now
+ pAdvSink->AddRef();
+ m_ppIAS[iAdv] = pAdvSink;
+
+ // if user wants cookie back, return it
+ if (pdwConnection)
+ {
+ // NOTE: this +1 is balanced by -1 in Unadvise()
+ *pdwConnection = iAdv + 1;
+ }
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT COAHolder::Advise ( %lx )"
+ " [ %p ]\n", this, hr,
+ (pdwConnection)? *pdwConnection : 0));
+
+ return hr;
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COAHolder::Unadvise, public
+//
+// Synopsis:
+// implementat IOleAdviseHolder::Unadvise
+//
+// Effects:
+// removes the specified advise sink from the list of sinks that
+// are notified when other IOleAdviseHolder methods are used on
+// this
+//
+// Arguments:
+// [dwConnection] -- The token that identifies the connection;
+// this would have been obtained previously from a
+// call to Advise()
+//
+// Returns:
+// OLE_E_NOCONNECTION, if the connection token is invalid
+// S_OK
+//
+// Notes: We do not have to stabilize this call since the only
+// outgoing call is the Release at the end
+//
+// History:
+// 10/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COAHolder_Unadvise)
+STDMETHODIMP COAHolder::Unadvise(DWORD dwConnection)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ HRESULT hr = NOERROR;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN COAHolder::Unadvise ( %lu )"
+ "\n", this, dwConnection));
+
+ IAdviseSink FAR* pAdvSink; // the requested advise sink, if there is one
+ int iAdv = (int)dwConnection - 1; // adjust connection index
+
+ // check that the connection token is valid, and if so, check that
+ // there is a connection for it
+ if (((LONG)dwConnection <= 0)
+ || (iAdv >= m_iSize)
+ || ((LONG)dwConnection > INT_MAX)
+ || ((pAdvSink = m_ppIAS[iAdv]) == NULL)
+ || !IsValidInterface(pAdvSink))
+ {
+ hr = ReportResult(0, OLE_E_NOCONNECTION, 0, 0);
+ }
+ else
+ {
+ // remove the advise sink from the array
+ m_ppIAS[iAdv] = NULL;
+
+ // release the advise sink; NB, due to circular references, this
+ // may release this advise holder--[this] may not be valid on
+ // return!
+ pAdvSink->Release();
+ }
+
+ // NB!! If any outgoing calls are added, this function will have
+ // to be stabilized
+
+ LEDebugOut((DEB_ITRACE, "%p OUT COAHolder::Unadvise ( %lx )"
+ " \n", this, hr));
+
+ return hr;
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COAHolder::EnumAdvise, public
+//
+// Synopsis:
+// implements IOleAdviseHolder::EnumAdvise()
+//
+// Effects:
+// returns an enumerator
+//
+// Arguments:
+// [ppenumAdvise] -- pointer to where to return a pointer to
+// an enumerator
+//
+// Returns:
+// E_NOTIMPL
+//
+// Notes:
+// currently not implemented.
+//
+// History:
+// 10/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COAHolder_EnumAdvise)
+STDMETHODIMP COAHolder::EnumAdvise(IEnumSTATDATA FAR* FAR* ppenumAdvise)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ // This is currently not implemented
+ HRESULT hr = ReportResult(0, E_NOTIMPL, 0, 0);
+
+ VDATEPTROUT(ppenumAdvise, IEnumSTATDATA FAR*);
+
+ LEDebugOut((DEB_ITRACE, "%p _IN COAHolder::EnumAdvise ( )"
+ "\n", this));
+
+ *ppenumAdvise = NULL;
+
+ LEDebugOut((DEB_ITRACE, "%p OUT COAHolder::EnumAdvise ( %lx )"
+ "[ %p ]\n", this, hr, *ppenumAdvise));
+
+ return hr;
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COAHolder::SendOnRename(), public
+//
+// Synopsis:
+// Multicast the OnRename OLE compound document notification,
+// to all interested parties
+//
+// Arguments:
+// [pmk] -- the new name of the object
+//
+// Returns:
+// S_OK
+//
+// Notes:
+// This may release the advise holder, since some objects may
+// Unadvise() themselves at the time they receive this
+// notification. To prevent the multicasting code from crashing,
+// the multicast loop is bracketed with AddRef()/Release(). Note
+// that the bracketing Release() may release the advise holder,
+// at which point [this] may no longer be valid.
+//
+// In a similar vein, other parties may add new Advise sinks
+// during these notifications. To avoid getting caught in
+// an infinite loop, we copy the number of advise sinks at the
+// beginning of the function, and do not refer to the current
+// number. If some parties are removed, and re-added, they may
+// be notified more than once, if they happen to be moved to
+// a later spot in the array of advise sinks.
+// REVIEW, copied this comment from previous stuff, and it
+// sounds BOGUS. Since new entries are always put in the first
+// empty slot, the current number always has to settle down,
+// and won't grow without bound, unless some bogus app is
+// continually registering itself when it gets a notification
+//
+// History:
+// 10/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COAHolder_SendOnRename)
+STDMETHODIMP COAHolder::SendOnRename(IMoniker FAR* pmk)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+ VDATEIFACE(pmk);
+
+ HRESULT hr = NOERROR;
+
+ int iAdvLim = m_iSize; // copy the current number of sink entries
+ int iAdv;
+ IAdviseSink FAR *FAR *ppIAS;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN COAHolder::SendOnRename ( %p )"
+ "\n", this, pmk));
+
+ // protect the COAHolder
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ for (ppIAS = m_ppIAS, iAdv = 0; iAdv < iAdvLim; ++ppIAS, ++iAdv)
+ {
+ if (*ppIAS != NULL)
+ (*ppIAS)->OnRename(pmk);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT COAHolder::SendOnRename ( %lx )"
+ " \n", this, hr));
+
+ return hr;
+}
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COAHolder::SendOnSave(), public
+//
+// Synopsis:
+// Multicast the OnSave OLE compound document notification,
+// to all interested parties
+//
+// Arguments:
+// none
+//
+// Returns:
+// S_OK
+//
+// Notes:
+// See notes for COAHolder::SendOnRename().
+//
+// History:
+// 10/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COAHolder_SendOnSave)
+STDMETHODIMP COAHolder::SendOnSave(void)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ HRESULT hr = NOERROR;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN COAHolder::SendOnSave ( )"
+ "\n", this ));
+
+ int iAdvLim = m_iSize; // copy the current number of sink entries
+ int iAdv;
+ IAdviseSink FAR *FAR *ppIAS;
+
+ // protect the COAHolder
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ for (ppIAS = m_ppIAS, iAdv = 0; iAdv < iAdvLim; ++ppIAS, ++iAdv)
+ {
+ if (*ppIAS != NULL)
+ (*ppIAS)->OnSave();
+ }
+
+
+ LEDebugOut((DEB_ITRACE, "%p OUT COAHolder::SendOnSave ( %lx )"
+ " \n", this, hr));
+
+ return hr;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COAHolder::SendOnClose(), public
+//
+// Synopsis:
+// Multicast the OnClose OLE compound document notification,
+// to all interested parties
+//
+// Arguments:
+// none
+//
+// Returns:
+// S_OK
+//
+// Notes:
+// See notes for COAHolder::SendOnRename().
+//
+// History:
+// 10/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COAHolder_SendOnClose)
+STDMETHODIMP COAHolder::SendOnClose(void)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ HRESULT hr = NOERROR;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN COAHolder::SendOnClose ( )"
+ "\n", this));
+
+ int iAdvLim = m_iSize; // copy the current number of sink entries
+ int iAdv;
+ IAdviseSink FAR *FAR *ppIAS;
+
+ // protect the COAHolder
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ for (ppIAS = m_ppIAS, iAdv = 0; iAdv < iAdvLim; ++ppIAS, ++iAdv)
+ {
+ if (*ppIAS != NULL)
+ (*ppIAS)->OnClose();
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT COAHolder::SendOnClose ( %lx )"
+ " \n", this, hr));
+
+ return hr;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COAHolder::SendOnLinkSrcChange, public
+//
+// Synopsis:
+// Multicasts IAdviseSink2::OnLinkSrcChange notification to any
+// advise sinks managed by the COAHolder that provide the
+// IAdviseSink2 interface
+//
+// Arguments:
+// [pmk] -- the new moniker to the link source
+//
+// Returns:
+// S_OK
+//
+// Notes:
+//
+// History:
+// 12/31/93 - ChrisWe - fixed assert
+// 11/01/93 - ChrisWe - made a member of COAHolder
+// 10/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COAHolder_SendOnLinkSrcChange)
+HRESULT COAHolder::SendOnLinkSrcChange(IMoniker FAR* pmk)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ VDATEIFACE(pmk);
+
+ HRESULT hr = NOERROR;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN COAHolder::SendOnLinkSrcChange ( %p )"
+ "\n", this, pmk));
+
+ int iAdvLim = m_iSize; // records the number of entries at start
+ int iAdv; // counts entries
+ IAdviseSink FAR *FAR *ppIAS; // walks over the array of advise sinks
+
+ // protect this from being released through circular references
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ // multicast notification
+ for (ppIAS = m_ppIAS, iAdv = 0; iAdv < iAdvLim; ++ppIAS, ++iAdv)
+ {
+ IAdviseSink FAR* pAdvSink;
+ IAdviseSink2 FAR* pAdvSink2;
+
+ // REVIEW, this seems to require that the number of
+ // advisees can only stay the same, or increase. Why should
+ // we care?
+ Assert(iAdvLim <= m_iSize);
+
+ // get pointer to current advise sink
+ pAdvSink = *ppIAS;
+
+ // if we have an advise sink, and it accepts IAdviseSink2
+ // notifications, send one
+ if ((pAdvSink != NULL) &&
+ pAdvSink->QueryInterface(IID_IAdviseSink2,
+ (LPVOID FAR*)&pAdvSink2) == NOERROR)
+ {
+ pAdvSink2->OnLinkSrcChange(pmk);
+ pAdvSink2->Release();
+ }
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT COAHolder::SendOnLinkSrcChange ( %lx )"
+ " \n", this, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: COAHolder::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppszDump] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 31-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT COAHolder::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszCSafeRefCount;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump;
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ pszCSafeRefCount = DumpCSafeRefCount((CSafeRefCount *)this, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CSafeRefCount:" << endl;
+ dstrDump << pszCSafeRefCount;
+ CoTaskMemFree(pszCSafeRefCount);
+
+ dstrDump << pszPrefix << "No. of Advise Sinks = " << m_iSize << endl;
+ for (i = 0; i < m_iSize; i++)
+ {
+ dstrDump << pszPrefix << "pIAdviseSink [" << i << "] = " << m_ppIAS[i] << endl;
+ }
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCOAHolder, public (_DEBUG only)
+//
+// Synopsis: calls the COAHolder::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pESD] - pointer to COAHolder
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 20-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCOAHolder(COAHolder *pOAH, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pOAH == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pOAH->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
diff --git a/private/ole32/ole232/advise/sources.inc b/private/ole32/ole232/advise/sources.inc
new file mode 100644
index 000000000..d8ec43103
--- /dev/null
+++ b/private/ole32/ole232/advise/sources.inc
@@ -0,0 +1 @@
+SYNCHRONIZE_BLOCK=1
diff --git a/private/ole32/ole232/base/api.cpp b/private/ole32/ole232/base/api.cpp
new file mode 100644
index 000000000..fb6d53bd5
--- /dev/null
+++ b/private/ole32/ole232/base/api.cpp
@@ -0,0 +1,2430 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: api.cpp
+//
+// Contents: OLE2 api definitions.
+//
+// Classes: none
+//
+// Functions: OleRun
+// OleIsRunning
+// OleLockRunning
+// OleSetContainedObject
+// OleNoteObjectVisible
+// OleGetData
+// OleSetData
+// OleSave
+// ReadClassStg
+// WriteClassStg
+// WriteFmtUserTypeStg
+// ReadFmtUserTypeStg
+// ReadM1ClassStm (internal)
+// WriteM1ClassStm (internal)
+// ReadClassStm
+// WriteClassStm
+// ReleaseStgMedium
+// OleDuplicateData
+// ReadOleStg (internal)
+// WriteOleStg (internal)
+// GetDocumentBitStg (internal and unused)
+// GetConvertStg
+// SetConvertStg
+// ReadClipformatStm
+// WriteClipformatStm
+// WriteMonikerStm
+// ReadMonikerStm
+// OleDraw
+// CreateObjectDescriptor (internal (for now))
+//
+// History: dd-mmm-yy Author Comment
+// 20-Feb-95 KentCe Buffer version of Read/WriteM1ClassStm.
+// 04-Jun-94 alexgo added CreateObjectDescriptor and
+// enhanced metafile support
+// 25-Jan-94 alexgo first pass at Cairo-style memory allocation
+// 11-Jan-94 chriswe fixed broken asserts
+// 11-Jan-94 alexgo added VDATEHEAP macros to every function
+// and fixed compile warnings
+// 08-Dec-93 ChrisWe added necessary casts to GlobalLock() calls
+// resulting from removing bogus GlobalLock() macros in
+// le2int.h
+// 21-Oct-93 Alex Gounares (alexgo) 32-bit port, commented
+// and substantial cleanup
+// (curts) 11/01/92 Added OleDuplicateMedium
+// (srinik) 06/22/92 Moved ReadStringStream, WriteStringStream
+// to "utstream.cpp"
+// (barrym) 06/02/92 Moved OleSave, ReadClassStg,
+// WriteClassStg, added
+// OleSaveCompleted, OleIsDirty
+// 28-May-92 Srini Koppolu (srinik) Original Author
+//
+//--------------------------------------------------------------------------
+
+
+// REVIEW FINAL: probably want to change all pstm->Read into StRead(pstm...)
+// except if spec issue 313 is accepted in which case we change StRead into
+// pstm->Read.
+
+#include <le2int.h>
+#pragma SEG(api)
+
+#define COMPOBJSTM_HEADER_SIZE 7
+
+#ifndef _MAC
+FARINTERNAL_(HBITMAP) BmDuplicate(HBITMAP hold, DWORD FAR* lpdwSize,
+ LPBITMAP lpBm);
+#endif
+
+NAME_SEG(Api)
+ASSERTDATA
+
+#define MAX_STR 512
+
+#ifndef WIN32
+// WIN16 uses remove()
+#include <stdio.h>
+#endif
+
+DWORD gdwFirstDword = (DWORD)MAKELONG(COMPOBJ_STREAM_VERSION,
+ BYTE_ORDER_INDICATOR);
+DWORD gdwOleVersion = MAKELONG(OLE_STREAM_VERSION, OLE_PRODUCT_VERSION);
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleRun
+//
+// Synopsis: Calls IRunnableObject->Run on a given object
+//
+// Effects: Usually puts on object in the RunningObjectTable
+//
+// Arguments: [lpUnkown] -- Pointer to the object
+//
+// Requires:
+//
+// Returns: The HRESULT from the Run method.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Oct-93 alexgo ported to 32bit
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleRun)
+STDAPI OleRun(IUnknown FAR* lpUnknown)
+{
+ OLETRACEIN((API_OleRun, PARAMFMT("lpUnknown= %p"), lpUnknown));
+
+ VDATEHEAP();
+
+ HRESULT hresult;
+ IRunnableObject FAR* pRO;
+
+ VDATEIFACE_LABEL(lpUnknown, errRtn, hresult);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&lpUnknown);
+
+ if (lpUnknown->QueryInterface(IID_IRunnableObject, (LPLPVOID)&pRO)
+ != NOERROR)
+ {
+ // if no IRunnableObject, assume already running
+ hresult = NOERROR;
+ goto errRtn;
+ }
+
+ hresult = pRO->Run(NULL);
+ pRO->Release();
+
+errRtn:
+ OLETRACEOUT((API_OleRun, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleIsRunning
+//
+// Synopsis: calls IRunnableObject->IsRunning on the given object
+//
+// Effects: Usually returns whether or not an object is in the
+// Running Object Table.
+//
+// Arguments: [lpOleObj] -- pointer to the object
+//
+// Requires:
+//
+// Returns: TRUE or FALSE (from IRO->IsRunning)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Oct-93 alexgo ported to 32bit
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(OleIsRunning)
+STDAPI_(BOOL) OleIsRunning(IOleObject FAR* lpOleObj)
+{
+ OLETRACEIN((API_OleIsRunning, PARAMFMT("lpOleObj= %p"), lpOleObj));
+
+ VDATEHEAP();
+
+ IRunnableObject FAR* pRO;
+ BOOL bRetval;
+
+ GEN_VDATEIFACE_LABEL(lpOleObj, FALSE, errRtn, bRetval);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IOleObject,(IUnknown **)&lpOleObj);
+
+ if (lpOleObj->QueryInterface(IID_IRunnableObject, (LPLPVOID)&pRO)
+ != NOERROR)
+ {
+ // if no IRunnableObject, assume already running
+ bRetval = TRUE;
+ goto errRtn;
+ }
+
+ bRetval = pRO->IsRunning();
+ pRO->Release();
+
+errRtn:
+ OLETRACEOUTEX((API_OleIsRunning, RETURNFMT("%B"), bRetval));
+
+ return bRetval;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleLockRunning
+//
+// Synopsis: calls IRunnableObject->LockRunning on the given object
+//
+// Effects: The object usually ends up calling CoLockObjectExternal
+// on itself
+//
+// Arguments: [lpUnknown] -- pointer to the object
+// [fLock] -- TRUE == lock running
+// FALSE == unlock running
+// [fLastUnlockCloses] -- if TRUE, IRO->LockRunning
+// is supposed to call IOO->Close
+// if this was the last unlock
+//
+// Requires:
+//
+// Returns: HRESULT from IRunnableObject->LockRunning()
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Oct-93 alexgo 32bit port, changed GEN_VDATEIFACE
+// to VDATEIFACE to fix a bug
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleLockRunning)
+STDAPI OleLockRunning(LPUNKNOWN lpUnknown, BOOL fLock, BOOL fLastUnlockCloses)
+{
+ OLETRACEIN((API_OleLockRunning, PARAMFMT("lpUnknown= %p, fLock= %B, fLastUnlockCloses= %B"),
+ lpUnknown, fLock, fLastUnlockCloses));
+
+ VDATEHEAP();
+
+ IRunnableObject FAR* pRO;
+ HRESULT hresult;
+
+ VDATEIFACE_LABEL(lpUnknown, errRtn, hresult);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&lpUnknown);
+
+ if (lpUnknown->QueryInterface(IID_IRunnableObject, (LPLPVOID)&pRO)
+ != NOERROR)
+ {
+ // if no IRunnableObject, no locks
+ hresult = NOERROR;
+ goto errRtn;
+ }
+
+ hresult = pRO->LockRunning(fLock, fLastUnlockCloses);
+ pRO->Release();
+
+errRtn:
+ OLETRACEOUT((API_OleLockRunning, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleSetContainedObject
+//
+// Synopsis: calls IRunnableObject->SetContainedObject on the given object
+//
+// Effects: Usually has the effect of calling CoLockObjectExternal
+// (lpUnkown, !fContained, FALSE).
+//
+// Arguments: [lpUnknown] -- pointer to the object
+// [fContained] -- if TRUE, the object is an embedding
+//
+// Requires:
+//
+// Returns: HRESULT from the IRO->SetContainedObject call
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Oct-92 alexgo 32bit port, changed GEN_VDATEIFACE to
+// VDATEIFACE to fix a bug
+//
+// Notes: Containers usually call OleSetContainedObject(..,TRUE) after
+// OleLoad or OleCreate. The basic idea is to tell OLE that
+// the object is an embedding. The real effect is to unlock
+// the object (since all objects start out locked) so that
+// other connections may determine it's fate while invisible.
+// OleNoteObjectVisible, for instance, would be called to lock
+// the object when it become visible.
+//
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleSetContainedObject)
+STDAPI OleSetContainedObject(LPUNKNOWN lpUnknown, BOOL fContained)
+{
+ OLETRACEIN((API_OleSetContainedObject, PARAMFMT("lpUnknown= %p, fContained= %B"),
+ lpUnknown, fContained));
+
+ VDATEHEAP();
+
+ IRunnableObject FAR* pRO;
+ HRESULT hresult;
+
+ VDATEIFACE_LABEL(lpUnknown, errRtn, hresult);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&lpUnknown);
+
+ if (lpUnknown->QueryInterface(IID_IRunnableObject, (LPLPVOID)&pRO)
+ != NOERROR)
+ {
+ // if no IRunnableObject, assume container-ness doesn't matter
+ hresult = NOERROR;
+ goto errRtn;
+ }
+
+ hresult = pRO->SetContainedObject(fContained);
+ pRO->Release();
+
+errRtn:
+ OLETRACEOUT((API_OleSetContainedObject, hresult));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleNoteObjectVisible
+//
+// Synopsis: Simple calls CoLockObjectExternal
+//
+// Effects:
+//
+// Arguments: [lpUnknown] -- pointer to the object
+// [fVisible] -- if TRUE, then lock the object,
+// if false, then unlock
+//
+// Requires:
+//
+// Returns: HRESULT from CoLockObjectExternal
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleNoteObjectVisible)
+STDAPI OleNoteObjectVisible(LPUNKNOWN pUnknown, BOOL fVisible)
+{
+ OLETRACEIN((API_OleNoteObjectVisible, PARAMFMT("pUnknown= %p, fVisible= %B"),
+ pUnknown, fVisible));
+
+ VDATEHEAP();
+
+ // NOTE: we as fLastUnlockReleases=TRUE here because there would
+ // otherwise be no other way to fully release the stubmgr. This
+ // means that objects can't use this mechanism to hold invisible
+ // objects alive.
+ HRESULT hr;
+
+ hr = CoLockObjectExternal(pUnknown, fVisible, TRUE);
+
+ OLETRACEOUT((API_OleNoteObjectVisible, hr));
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleSave
+//
+// Synopsis: Writes the CLSID to the storage and calls IPersistStorage->
+// Save()
+//
+// Effects:
+//
+// Arguments: [pPS] -- pointer to the IPersistStorage interface
+// on the object to be saved
+// [pstgSave] -- pointer to the storage to which the object
+// should be saved
+// [fSameAsLoad] -- FALSE indicates a SaveAs operation
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 22-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleSave)
+STDAPI OleSave(
+ IPersistStorage FAR* pPS,
+ IStorage FAR* pstgSave,
+ BOOL fSameAsLoad
+)
+{
+ OLETRACEIN((API_OleSave, PARAMFMT("pPS= %p, pstgSave= %p, fSameAsLoad= %B"),
+ pPS, pstgSave, fSameAsLoad));
+
+ VDATEHEAP();
+
+ HRESULT hresult;
+ CLSID clsid;
+
+ VDATEIFACE_LABEL(pPS, errRtn, hresult);
+ VDATEIFACE_LABEL(pstgSave, errRtn, hresult);
+
+ if (hresult = pPS->GetClassID(&clsid))
+ {
+ goto errRtn;
+ }
+ CALLHOOKOBJECT(S_OK,clsid,IID_IPersistStorage,(IUnknown **)&pPS);
+
+ if (hresult = WriteClassStg(pstgSave, clsid))
+ {
+ goto errRtn;
+ }
+
+ if ((hresult = pPS->Save(pstgSave, fSameAsLoad)) == NOERROR)
+ {
+ hresult = pstgSave->Commit(0);
+ }
+
+errRtn:
+ OLETRACEOUT((API_OleSave, hresult));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReadClassStg
+//
+// Synopsis: Calls IStorage->Stat to get the CLSID from the given storage
+//
+// Effects:
+//
+// Arguments: [pstg] -- pointer to the storage
+// [pclsid] -- place to return the CLSID
+//
+// Requires:
+//
+// Returns: HRESULT from the IS->Stat call
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 22-Oct-93 alexgo 32bit port, fixed bug with invalid
+// [pclsid] and error on IS->Stat
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(ReadClassStg)
+STDAPI ReadClassStg( IStorage FAR * pstg, LPCLSID pclsid)
+{
+ OLETRACEIN((API_ReadClassStg, PARAMFMT("pstg= %p, pclsid= %p"),
+ pstg, pclsid));
+
+ VDATEHEAP();
+
+ HRESULT hresult;
+ STATSTG statstg;
+
+ VDATEIFACE_LABEL(pstg, errRtn, hresult);
+ VDATEPTROUT_LABEL(pclsid, CLSID, errRtn, hresult);
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pstg);
+
+ if ((hresult = pstg->Stat(&statstg, STATFLAG_NONAME)) != NOERROR)
+ {
+ *pclsid = CLSID_NULL;
+ goto errRtn;
+ }
+
+ *pclsid = statstg.clsid;
+
+errRtn:
+ OLETRACEOUT((API_ReadClassStg, hresult));
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: WriteClassStg
+//
+// Synopsis: Calls IStorage->SetClass to store the CLSID in the given
+// storage
+//
+// Effects:
+//
+// Arguments: [pstg] -- pointer to the storage
+// [clsid] -- the CLSID to write into the storage
+//
+// Requires:
+//
+// Returns: HRESULT from the IS->SetClass call
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 22-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(WriteClassStg)
+STDAPI WriteClassStg( IStorage FAR * pstg, REFCLSID clsid)
+{
+ OLETRACEIN((API_WriteClassStg, PARAMFMT("pstg= %p, clsid= %I"),
+ pstg, &clsid));
+
+ VDATEHEAP();
+
+ HRESULT hr;
+
+ VDATEIFACE_LABEL(pstg, errRtn, hr);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pstg);
+
+ // write clsid in storage (what is read above)
+ hr = pstg->SetClass(clsid);
+
+errRtn:
+ OLETRACEOUT((API_WriteClassStg, hr));
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReadM1ClassStm
+//
+// Synopsis: Reads -1L, CLSID from the given stream
+//
+// Effects:
+//
+// Arguments: [pStm] -- pointer to the stream
+// [pclsid] -- where to put the clsid
+//
+// Requires:
+//
+// Returns: HRESULT from the ReadM1ClassStm.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 24-Oct-93 alexgo 32bit port
+// 20-Feb-95 KentCe Convert to buffered stream reads.
+//
+// Notes: Internal API.
+//
+// Reads -1L and CLSID from stream swapping bytes on
+// big-endian machines
+//
+//--------------------------------------------------------------------------
+
+STDAPI ReadM1ClassStm(LPSTREAM pStm, LPCLSID pclsid)
+{
+ VDATEHEAP();
+ CStmBufRead StmRead;
+ HRESULT error;
+
+
+ StmRead.Init(pStm);
+
+ error = ReadM1ClassStmBuf(StmRead, pclsid);
+
+ if (error != NOERROR)
+ *pclsid = CLSID_NULL;
+
+ StmRead.Release();
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: WriteM1ClassStm
+//
+// Synopsis: Writes -1L, CLSID to the given stream
+//
+// Effects:
+//
+// Arguments: [pStm] -- pointer to the stream
+// [clsid] -- CLSID to be written
+//
+// Requires:
+//
+// Returns: HRESULT from the WriteM1ClassStm
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Jan-84 alexgo changed dw from a DWORD to a LONG
+// 24-Oct-93 alexgo 32bit port
+// 20-Feb-95 KentCe Convert to buffered stream writes.
+//
+// Notes: Internal API.
+//
+// Writess -1L and CLSID from stream swapping bytes on
+// big-endian machines
+//
+//--------------------------------------------------------------------------
+
+STDAPI WriteM1ClassStm(LPSTREAM pStm, REFCLSID clsid)
+{
+ VDATEHEAP();
+
+ CStmBufWrite StmWrite;
+ HRESULT error;
+
+ VDATEIFACE( pStm );
+
+
+ StmWrite.Init(pStm);
+
+ error = WriteM1ClassStmBuf(StmWrite, clsid);
+ if (FAILED(error))
+ {
+ goto errRtn;
+ }
+
+ error = StmWrite.Flush();
+
+errRtn:
+ StmWrite.Release();
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReadM1ClassStmBuf
+//
+// Synopsis: Reads -1L and CLSID from the given buffered stream.
+//
+// Arguments: [StmRead] -- Stream Read Object.
+// [pclsid] -- Where to put the clsid
+//
+// Returns: HRESULT from the StmRead.Read's
+//
+//
+// History: dd-mmm-yy Author Comment
+// 20-Feb-95 KentCe Convert to buffered stream reads.
+// 24-Oct-93 alexgo 32bit port
+//
+// Notes: Internal API.
+//
+// Reads -1L and CLSID from stream swapping bytes on
+// big-endian machines
+//
+//--------------------------------------------------------------------------
+
+STDAPI ReadM1ClassStmBuf(CStmBufRead & StmRead, LPCLSID pclsid)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ LONG lValue;
+
+
+ if ((error = StmRead.ReadLong(&lValue)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if (lValue == -1)
+ {
+ // have a GUID
+ error = StmRead.Read((void FAR *)pclsid, sizeof(CLSID));
+ }
+ else
+ {
+ // this is now an error; we don't allow string form
+ // of clsid anymore
+ error = ResultFromScode(E_UNSPEC);
+ }
+
+errRtn:
+ if (error != NOERROR)
+ {
+ *pclsid = CLSID_NULL;
+ }
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: WriteM1ClassStmBuf
+//
+// Synopsis: Writes -1L and CLSID to the given buffered stream.
+//
+// Arguments: [StmRead] -- Stream Write Object.
+// [pclsid] -- Where to read the clsid
+//
+// Returns: HRESULT from the StmWrite.Write's
+//
+//
+// History: dd-mmm-yy Author Comment
+// 20-Feb-95 KentCe Convert to buffered stream reads.
+// 24-Oct-93 alexgo 32bit port
+//
+// Notes: Internal API.
+//
+// Writess -1L and CLSID from stream swapping bytes on
+// big-endian machines
+//
+//--------------------------------------------------------------------------
+
+STDAPI WriteM1ClassStmBuf(CStmBufWrite & StmWrite, REFCLSID clsid)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+
+ // format is -1L followed by GUID
+ if ((error = StmWrite.WriteLong(-1)) != NOERROR)
+ return error;
+
+ return StmWrite.Write((LPVOID)&clsid, sizeof(clsid));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReadClassStm
+//
+// Synopsis: Reads the CLSID from the given stream
+//
+// Effects:
+//
+// Arguments: [pStm] -- pointer to the stream
+// [pclsid] -- where to put the clsid
+//
+// Requires:
+//
+// Returns: HRESULT from the IStream->Read
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 24-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(ReadClassStm)
+// reads CLSID from stream swapping bytes on big-endian machines
+STDAPI ReadClassStm(LPSTREAM pStm, LPCLSID pclsid)
+{
+ OLETRACEIN((API_ReadClassStm, PARAMFMT("pStm= %p, pclsid= %p"), pStm, pclsid));
+
+ VDATEHEAP();
+ HRESULT error;
+
+ VDATEIFACE_LABEL( pStm, errRtn, error );
+ VDATEPTROUT_LABEL(pclsid, CLSID, errRtn, error);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pStm);
+
+ if ((error = StRead(pStm, (void FAR *)pclsid, sizeof(CLSID)))
+ != NOERROR)
+ *pclsid = CLSID_NULL;
+
+errRtn:
+ OLETRACEOUT((API_ReadClassStm, error));
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: WriteClassStm
+//
+// Synopsis: Writes the class ID to the given stream
+//
+// Effects:
+//
+// Arguments: [pStm] -- pointer to the stream
+// [clsid] -- CLSID to write to the stream
+//
+// Requires:
+//
+// Returns: HRESULT from the IStream->Write call
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 24-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(WriteClassStm)
+// writes CLSID to stream swapping bytes on big-endian machines
+STDAPI WriteClassStm(LPSTREAM pStm, REFCLSID clsid)
+{
+ OLETRACEIN((API_WriteClassStm, PARAMFMT("pStm= %p, clsid= %I"), pStm, &clsid));
+
+ VDATEHEAP();
+
+ HRESULT hr;
+
+ VDATEIFACE_LABEL( pStm, errRtn, hr);
+
+ hr = pStm->Write(&clsid, sizeof(clsid), NULL);
+
+errRtn:
+ OLETRACEOUT((API_WriteClassStm, hr));
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pStm);
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReleaseStgMedium
+//
+// Synopsis: Releases any resources held by a storage medium
+//
+// Arguments: [pMedium] -- pointer to the storage medium
+//
+// Returns: nothing
+//
+// History: dd-mmm-yy Author Comment
+// 24-Oct-93 alexgo 32-bit port
+// 15-May-94 DavePl Added EMF support
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(ReleaseStgMedium)
+STDAPI_(void) ReleaseStgMedium( LPSTGMEDIUM pMedium )
+{
+ OLETRACEIN((API_ReleaseStgMedium, PARAMFMT("pMedium= %p"), pMedium));
+
+ VDATEHEAP();
+
+ if (pMedium) {
+
+ BOOL fPunkRel;
+
+ //VDATEPTRIN rejects NULL
+ VOID_VDATEPTRIN_LABEL( pMedium, STGMEDIUM, errRtn);
+ fPunkRel = pMedium->pUnkForRelease != NULL;
+
+ switch (pMedium->tymed) {
+ case TYMED_HGLOBAL:
+ if (pMedium->hGlobal != NULL && !fPunkRel)
+ Verify(GlobalFree(pMedium->hGlobal) == 0);
+ break;
+
+ case TYMED_GDI:
+ if (pMedium->hGlobal != NULL && !fPunkRel)
+ DeleteObject(pMedium->hGlobal);
+ break;
+
+ case TYMED_ENHMF:
+ if (pMedium->hEnhMetaFile != NULL && !fPunkRel)
+ {
+ Verify(DeleteEnhMetaFile(pMedium->hEnhMetaFile));
+ };
+ break;
+
+ case TYMED_MFPICT:
+ if (pMedium->hGlobal != NULL && !fPunkRel) {
+ LPMETAFILEPICT pmfp;
+
+ if ((pmfp = (LPMETAFILEPICT)GlobalLock(pMedium->hGlobal)) == NULL)
+ break;
+
+ DeleteMetaFile(pmfp->hMF);
+ GlobalUnlock(pMedium->hGlobal);
+ Verify(GlobalFree(pMedium->hGlobal) == 0);
+ }
+ break;
+
+ case TYMED_FILE:
+ if (pMedium->lpszFileName != NULL) {
+ if (!IsValidPtrIn(pMedium->lpszFileName, 1))
+ break;
+ if (!fPunkRel) {
+#ifdef WIN32
+ DeleteFile(pMedium->lpszFileName);
+#else
+#ifdef _MAC
+ // the libraries are essentially small model on the MAC
+ Verify(0==remove(pMedium->lpszFileName));
+#else
+ #ifdef OLD_AND_NICE_ASSEMBLER_VERSION
+ // Win 3.1 specific code to call DOS to delete the file
+ // given a far pointer to the file name
+ extern void WINAPI DOS3Call(void);
+ _asm {
+ mov ah,41H
+ push ds
+ lds bx,pMedium
+ lds dx,[bx].lpszFileName
+ call DOS3Call
+ pop ds
+ }
+ #else
+ {
+ OFSTRUCT of;
+ OpenFile(pMedium->lpszFileName, &of, OF_DELETE);
+ }
+ #endif
+#endif
+#endif
+ }
+
+ // WARNING: there was a bug in the 16bit code that the filename
+ // string was not being freed if pUnkForRelease was NULL. the
+ // spec says it should delete the string, so we follow the spec
+ // here.
+
+ PubMemFree(pMedium->lpszFileName);
+ pMedium->lpszFileName = NULL;
+
+ }
+ break;
+
+ case TYMED_ISTREAM:
+ if (pMedium->pstm != NULL &&
+ IsValidInterface(pMedium->pstm))
+ pMedium->pstm->Release();
+ break;
+
+ case TYMED_ISTORAGE:
+ if (pMedium->pstg != NULL &&
+ IsValidInterface(pMedium->pstg))
+ pMedium->pstg->Release();
+ break;
+
+ case TYMED_NULL:
+ break;
+
+ default:
+ AssertSz(FALSE, "Invalid medium in ReleaseStgMedium");
+ }
+
+
+ if (pMedium->pUnkForRelease) {
+ if (IsValidInterface(pMedium->pUnkForRelease))
+ pMedium->pUnkForRelease->Release();
+ pMedium->pUnkForRelease = NULL;
+ }
+
+ // NULL out to prevent unwanted use of just freed data.
+ // Note: this must be done AFTER punkForRelease is called
+ // because our special punkForRelease used in remoting
+ // needs the tymed value.
+
+ pMedium->tymed = TYMED_NULL;
+
+ }
+
+errRtn:
+ OLETRACEOUTEX((API_ReleaseStgMedium, NORETURN));
+
+ return;
+}
+
+#ifdef MAC_REVIEW
+
+ This API must be written for MAC and PICT format.
+#endif
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleDuplicateData
+//
+// Synopsis: Duplicates data from the given handle and clipboard format
+//
+// Effects:
+//
+// Arguments: [hSrc] -- handle to the data to be duplicated
+// [cfFormat] -- format of [hSrc]
+// [uiFlags] -- any flags (such a GMEM_MOVEABLE) for
+// memory allocation
+//
+// Requires:
+//
+// Returns: a HANDLE to the duplicated resource
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-May-94 alexgo added support for enhanced metafiles
+// 24-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleDuplicateData)
+STDAPI_(HANDLE) OleDuplicateData
+ (HANDLE hSrc, CLIPFORMAT cfFormat, UINT uiFlags)
+{
+ HANDLE hDup;
+
+ OLETRACEIN((API_OleDuplicateData, PARAMFMT("hSrc= %h, cfFormat= %d, uiFlags= %x"),
+ hSrc, cfFormat, uiFlags));
+
+ VDATEHEAP();
+
+ if (!hSrc)
+ {
+ hDup = NULL;
+ goto errRtn;
+ }
+
+ switch( cfFormat )
+ {
+ case CF_BITMAP:
+ hDup = (HANDLE) BmDuplicate ((HBITMAP)hSrc, NULL, NULL);
+ break;
+
+ case CF_PALETTE:
+ hDup = (HANDLE) UtDupPalette ((HPALETTE)hSrc);
+ break;
+
+ case CF_ENHMETAFILE:
+ hDup = (HANDLE) CopyEnhMetaFile((HENHMETAFILE)hSrc, NULL);
+ break;
+
+ case CF_METAFILEPICT:
+ if (uiFlags == NULL)
+ {
+ uiFlags = GMEM_MOVEABLE;
+ }
+
+ LPMETAFILEPICT lpmfpSrc;
+ LPMETAFILEPICT lpmfpDst;
+
+ if (!(lpmfpSrc = (LPMETAFILEPICT) GlobalLock (hSrc)))
+ {
+ hDup = NULL;
+ goto errRtn;
+ }
+
+ if (!(hDup = UtDupGlobal (hSrc, uiFlags)))
+ {
+ GlobalUnlock(hSrc);
+ hDup = NULL;
+ goto errRtn;
+ }
+
+ if (!(lpmfpDst = (LPMETAFILEPICT) GlobalLock (hDup)))
+ {
+ GlobalUnlock(hSrc);
+ GlobalFree (hDup);
+ hDup = NULL;
+ goto errRtn;
+ }
+
+ *lpmfpDst = *lpmfpSrc;
+ lpmfpDst->hMF = CopyMetaFile (lpmfpSrc->hMF, NULL);
+ GlobalUnlock (hSrc);
+ GlobalUnlock (hDup);
+ break;
+
+ default:
+ if (uiFlags == NULL)
+ {
+ uiFlags = GMEM_MOVEABLE;
+ }
+
+ hDup = UtDupGlobal (hSrc, uiFlags);
+ }
+
+errRtn:
+ OLETRACEOUTEX((API_OleDuplicateData, RETURNFMT("%h"), hDup));
+
+ return hDup;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: BmDuplicate
+//
+// Synopsis: Duplicates a bitmap
+//
+// Effects:
+//
+// Arguments: [hold] -- the source bitmap
+// [lpdwSize] -- where to put the bitmap size
+// [lpBm] -- where to put the new bitmap
+//
+// Requires:
+//
+// Returns: A handle to the new bitmap
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 25-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(BmDuplicate)
+FARINTERNAL_(HBITMAP) BmDuplicate
+ (HBITMAP hold, DWORD FAR* lpdwSize, LPBITMAP lpBm)
+{
+ VDATEHEAP();
+
+ HBITMAP hnew = NULL;
+ HANDLE hMem;
+ LPVOID lpMem;
+ DWORD dwSize;
+ BITMAP bm;
+ SIZE extents;
+
+ extents.cx = extents.cy = 0;
+
+ // REVIEW (davepl): The bitmap pointer here was being cast to LPOLESTR
+ // for some reason. It's takes a void pointer!
+
+ GetObject (hold, sizeof(BITMAP), &bm);
+ dwSize = ((DWORD) bm.bmHeight) * ((DWORD) bm.bmWidthBytes) *
+ ((DWORD) bm.bmPlanes);
+
+ if (!(hMem = GlobalAlloc (GMEM_MOVEABLE, dwSize)))
+ return NULL;
+
+ if (!(lpMem = GlobalLock (hMem)))
+ goto errRtn;
+
+ GlobalUnlock (hMem);
+
+ // REVIEW(davepl): This should probably use GetDIBits() instead
+
+ GetBitmapBits (hold, dwSize, lpMem);
+ if (hnew = CreateBitmap (bm.bmWidth, bm.bmHeight,
+ bm.bmPlanes, bm.bmBitsPixel, NULL)) {
+ if (!SetBitmapBits (hnew, dwSize, lpMem)) {
+ DeleteObject (hnew);
+ hnew = NULL;
+ goto errRtn;
+ }
+ }
+
+ if (lpdwSize)
+ *lpdwSize = dwSize;
+
+ if (lpBm)
+ *lpBm = bm;
+
+ if (GetBitmapDimensionEx(hold, &extents) && extents.cx && extents.cy)
+ SetBitmapDimensionEx(hnew, extents.cx, extents.cy, NULL);
+
+errRtn:
+ if (hMem)
+ GlobalFree (hMem);
+
+ return hnew;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReadOleStg
+//
+// Synopsis: Internal API to read private OLE information from
+// the OLE_STREAM in the given storage
+//
+// Effects:
+//
+// Arguments: [pstg] -- pointer to the storage
+// [pdwFlags] -- where to put flags stored in the
+// the stream (may be NULL)
+// [pdwOptUpdate] -- where to put the update flags
+// (may be NULL)
+// [pdwReserved] -- where to put the reserved value
+// (may be NULL)
+// [ppmk] -- where to put the moniker
+// (may be NULL)
+// [ppstmOut] -- where to put the OLE_STREAM pointer
+// (may be NULL)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(ReadOleStg)
+STDAPI ReadOleStg
+ (LPSTORAGE pstg, DWORD FAR* pdwFlags, DWORD FAR* pdwOptUpdate,
+ DWORD FAR* pdwReserved, LPMONIKER FAR* ppmk, LPSTREAM FAR* ppstmOut)
+{
+ OLETRACEIN((API_ReadOleStg,
+ PARAMFMT("pdwFlags= %p, pdwOptUpdate= %p, pdwReserved= %p, ppmk= %p, ppstmOut= %p"),
+ pdwFlags, pdwOptUpdate, pdwReserved, ppmk, ppstmOut));
+
+ VDATEHEAP();
+
+ HRESULT error;
+ IStream FAR * pstm;
+ DWORD dwBuf[4];
+ LPMONIKER pmk;
+ LPOLESTR szClassName = OLE_STREAM;
+
+ if (ppmk)
+ {
+ VDATEPTROUT_LABEL( ppmk, LPMONIKER, errNoFreeRtn, error);
+ *ppmk = NULL;
+ }
+
+ if (ppstmOut){
+ VDATEPTROUT_LABEL( ppstmOut, LPSTREAM, errNoFreeRtn, error);
+ *ppstmOut = NULL;
+ }
+ VDATEIFACE_LABEL( pstg, errNoFreeRtn, error);
+
+ if ((error = pstg->OpenStream(szClassName, NULL,
+ (STGM_READ | STGM_SHARE_EXCLUSIVE), 0, &pstm)) != NOERROR) {
+ // This error is OK for some callers (ex: default handler)
+ // of this function. They depend on NOERROR or this error
+ // code. So, don't change the error code.
+ error = ReportResult(0, STG_E_FILENOTFOUND, 0, 0);
+ goto errNoFreeRtn;
+ }
+
+ // read Ole version number, flags, Update options, reserved field
+ if ((error = StRead (pstm, dwBuf, 4*sizeof(DWORD))) != NOERROR)
+ goto errRtn;
+
+ if (dwBuf[0] != gdwOleVersion) {
+ error = ResultFromScode(DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+
+ if (pdwFlags)
+ *pdwFlags = dwBuf[1];
+
+ if (pdwOptUpdate)
+ *pdwOptUpdate = dwBuf[2];
+
+ AssertSz(dwBuf[3] == NULL,"Reserved field in OLE STREAM is not NULL");
+
+ if (dwBuf[3] != NULL) {
+ error = ResultFromScode(DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+
+ if (pdwReserved)
+ *pdwReserved = dwBuf[3];
+
+ if ((error = ReadMonikerStm (pstm, &pmk)) != NOERROR)
+ goto errRtn;
+
+ if (ppmk)
+ *ppmk = pmk;
+ else if (pmk)
+ pmk->Release();
+
+errRtn:
+ if (pstm) {
+ if ((error == NOERROR) && (ppstmOut != NULL))
+ *ppstmOut = pstm;
+ else
+ pstm->Release();
+ }
+
+errNoFreeRtn:
+ OLETRACEOUT((API_ReadOleStg, error));
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: WriteOleStg
+//
+// Synopsis: Writes private OLE info into an OLE_STREAM in the given
+// storage. Internal
+//
+// Effects:
+//
+// Arguments: [pstg] -- pointer to the storage
+// [pOleObj] -- object from which to get info to write
+// (may be NULL)
+// [dwReserved] -- reserved
+// [ppstmOut] -- where to put the private stream
+// (may be NULL)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(WriteOleStg)
+STDAPI WriteOleStg
+ (LPSTORAGE pstg, IOleObject FAR* pOleObj,
+ DWORD dwReserved, LPSTREAM FAR* ppstmOut)
+{
+ OLETRACEIN((API_WriteOleStg, PARAMFMT("pstg= %p, pOleObj= %p, dwReserved= %x, ppstmOut= %p"),
+ pstg, pOleObj, dwReserved, ppstmOut));
+
+ VDATEHEAP();
+
+ IStream FAR * pstm;
+ IOleLink FAR* lpLink;
+ HRESULT error;
+ LPMONIKER pmk = NULL;
+ DWORD dwUpdOpt = NULL;
+ ULONG cbRead;
+ DWORD objflags;
+ ULARGE_INTEGER dwSize;
+ LARGE_INTEGER large_integer;
+
+
+ if (ppstmOut){
+ VDATEPTROUT_LABEL( ppstmOut, LPSTREAM, errNoFreeRtn, error );
+ *ppstmOut = NULL;
+ }
+ VDATEIFACE_LABEL( pstg, errNoFreeRtn, error );
+ if (pOleObj)
+ VDATEIFACE_LABEL( pOleObj, errNoFreeRtn, error );
+
+ if ((error = OpenOrCreateStream(pstg, OLE_STREAM, &pstm)) != NOERROR)
+ {
+ goto errNoFreeRtn;
+ }
+
+ if ((error = pstm->Write(&gdwOleVersion, sizeof(DWORD),
+ NULL)) != NOERROR)
+ goto errRtn;
+
+ // read existing version of flags for doc bit (assume off if missing)
+ if (pstm->Read(&objflags, sizeof(DWORD), &cbRead) != NOERROR ||
+ cbRead != sizeof(DWORD))
+ // nothing there
+ objflags = 0;
+
+ // only preserve docbit
+ objflags &= OBJFLAGS_DOCUMENT;
+
+ if (pOleObj != NULL &&
+ pOleObj->QueryInterface (IID_IOleLink, (LPLPVOID)&lpLink)
+ == NOERROR) {
+ objflags |= OBJFLAGS_LINK;
+ lpLink->GetUpdateOptions (&dwUpdOpt);
+ lpLink->Release();
+ }
+
+ // make sure we are positioned at flag dword field (might not be
+ // because of read above).
+ LISet32( large_integer, sizeof(DWORD) );
+ if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL))
+ != NOERROR)
+ goto errRtn;
+
+ DWORD dwBuf[3];
+
+ dwBuf[0] = objflags;
+ dwBuf[1] = dwUpdOpt;
+ AssertSz(dwReserved == NULL, "Non-NULL passed for reserved field");
+ dwBuf[2] = 0L; // reserved field
+
+ if ((error = pstm->Write(dwBuf, 3*sizeof(DWORD), NULL)) != NOERROR)
+ goto errRtn;
+
+ if (pOleObj != NULL) {
+ error = pOleObj->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
+ OLEWHICHMK_OBJREL, &pmk);
+ AssertOutPtrIface(error, pmk);
+ }
+
+ // else pmk == NULL
+
+ error = WriteMonikerStm (pstm, pmk);
+ if (pmk)
+ pmk->Release();
+
+ // truncate stream to this point to remove any unwanted, stale data
+ LISet32( large_integer, 0);
+ if (pstm->Seek(large_integer, STREAM_SEEK_CUR, &dwSize) == NOERROR)
+ pstm->SetSize(dwSize);
+
+errRtn:
+ if (pstm) {
+ if ((error == NOERROR) && (ppstmOut != NULL))
+ *ppstmOut = pstm;
+ else
+ pstm->Release();
+ }
+
+errNoFreeRtn:
+ OLETRACEOUT((API_WriteOleStg, error));
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SetBitOleStg
+//
+// Synopsis: internal function to write private OLE info into
+// OLE_STREAM on the given storage
+//
+// Effects:
+//
+// Arguments: [pstg] -- pointer to the storage
+// [mask] -- mask for old values
+// [value] -- values to write
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: writes (old_values & mask ) | value into the stream
+//
+// History: dd-mmm-yy Author Comment
+// 27-Oct-93 alexgo 32-bit port, fixed bugs
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(SetBitOleStg)
+
+static INTERNAL SetBitOleStg(LPSTORAGE pstg, DWORD mask, DWORD value)
+{
+ VDATEHEAP();
+
+ IStream FAR * pstm = NULL;
+ HRESULT error;
+ DWORD objflags = 0;
+ LARGE_INTEGER large_integer;
+
+ VDATEIFACE( pstg );
+
+ if (error = pstg->OpenStream(OLE_STREAM, NULL, STGM_SALL, 0, &pstm))
+ {
+ if (STG_E_FILENOTFOUND != GetScode(error))
+ goto errRtn;
+
+ if ((error = pstg->CreateStream(OLE_STREAM, STGM_SALL,
+ 0, 0, &pstm)) != NOERROR)
+ goto errRtn;
+
+ DWORD dwBuf[5];
+
+ dwBuf[0] = gdwOleVersion;
+ dwBuf[1] = objflags;
+ dwBuf[2] = 0L;
+ dwBuf[3] = 0L;
+ dwBuf[4] = 0L;
+
+ if ((error = pstm->Write(dwBuf, 5*sizeof(DWORD), NULL))
+ != NOERROR)
+ goto errRtn;
+ }
+
+ // seek directly to word, read, modify, seek back and write.
+ LISet32( large_integer, sizeof(DWORD) );
+ if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL))
+ != NOERROR)
+ goto errRtn;
+
+ if ((error = StRead(pstm, &objflags, sizeof(objflags))) != NOERROR)
+ goto errRtn;
+
+ objflags = (objflags & mask) | value;
+
+ LISet32( large_integer, sizeof(DWORD) );
+ if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL))
+ != NOERROR)
+ goto errRtn;
+
+ error = pstm->Write(&objflags, sizeof(DWORD), NULL);
+
+errRtn:// close and return error code.
+ if (pstm)
+ pstm->Release();
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetFlagsOleStg
+//
+// Synopsis: Internal function to get the private ole flags from a
+// given storage
+//
+// Effects:
+//
+// Arguments: [pstg] -- pointer to the storage
+// [lpobjflags] -- where to put the flags
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Oct-93 alexgo 32bit port, fixed bugs (error return)
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(GetFlagsOleStg)
+
+static INTERNAL GetFlagsOleStg(LPSTORAGE pstg, LPDWORD lpobjflags)
+{
+ VDATEHEAP();
+
+ IStream FAR * pstm = NULL;
+ HRESULT error;
+ LARGE_INTEGER large_integer;
+
+ VDATEIFACE( pstg );
+
+ if ((error = pstg->OpenStream(OLE_STREAM, NULL,
+ (STGM_READ | STGM_SHARE_EXCLUSIVE),
+ 0, &pstm)) != NOERROR)
+ goto errRtn;
+
+ // seek directly to word, read, modify, seek back and write.
+ LISet32( large_integer, sizeof(DWORD) );
+ if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL))
+ != NOERROR)
+ goto errRtn;
+
+ error = StRead(pstm, lpobjflags, sizeof(*lpobjflags));
+
+errRtn:
+ if (pstm)
+ pstm->Release();
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetDocumentBitStg
+//
+// Synopsis: returns the doc bit from the given storage
+//
+// Effects:
+//
+// Arguments: [pStg] -- pointer to the storage
+//
+// Requires:
+//
+// Returns: NOERROR if the doc bit is set, S_FALSE if not
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Oct-93 alexgo 32bit port
+//
+// Notes:
+// REVIEW32:: Nobody seems to use this function. Nuke it.
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(GetDocumentBitStg)
+// get doc bit; return NOERROR if on; S_FALSE if off
+STDAPI GetDocumentBitStg(LPSTORAGE pStg)
+{
+ OLETRACEIN((API_GetDocumentBitStg, PARAMFMT("pStg= %p"), pStg));
+
+ VDATEHEAP();
+
+ DWORD objflags;
+ HRESULT error;
+
+ if ((error = GetFlagsOleStg(pStg, &objflags)) == NOERROR)
+ {
+ if(!(objflags&OBJFLAGS_DOCUMENT))
+ {
+ error = ResultFromScode(S_FALSE);
+ }
+ }
+
+ OLETRACEOUT((API_GetDocumentBitStg, error));
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SetDocumentBitStg
+//
+// Synopsis: Writes the document bit to the given storage
+//
+// Effects:
+//
+// Arguments: [pStg] -- pointer to the storage
+// [fDocument] -- TRUE, storage is a document, false
+// otherwise
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Oct-93 alexgo 32-bit port
+//
+// Notes:
+// REVIEW32: nobody seems to use this function, nuke it
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(SetDocumentBitStg)
+// set doc bit according to fDocument
+STDAPI SetDocumentBitStg(LPSTORAGE pStg, BOOL fDocument)
+{
+ OLETRACEIN((API_SetDocumentBitStg, PARAMFMT("pStg= %p, fDocument= %B"),
+ pStg, fDocument));
+
+ VDATEHEAP();
+
+ HRESULT hr;
+
+ hr = SetBitOleStg(pStg, fDocument ? -1L : ~OBJFLAGS_DOCUMENT,
+ fDocument ? OBJFLAGS_DOCUMENT : 0);
+
+ OLETRACEOUT((API_SetDocumentBitStg, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetConvertStg
+//
+// Synopsis: Gets the convert bit from the given storage
+//
+// Effects:
+//
+// Arguments: [pStg] -- pointer to the storage
+//
+// Requires:
+//
+// Returns: NOERROR if set, S_FALSE if not
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(GetConvertStg)
+STDAPI GetConvertStg(LPSTORAGE pStg)
+{
+ OLETRACEIN((API_GetConvertStg, PARAMFMT("pStg= %p"), pStg));
+
+ VDATEHEAP();
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pStg);
+
+ DWORD objflags;
+ HRESULT error;
+
+ if ((error = GetFlagsOleStg(pStg, &objflags)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if (objflags&OBJFLAGS_CONVERT)
+ {
+ error = NOERROR;
+ }
+ else
+ {
+ error = ResultFromScode(S_FALSE);
+ }
+
+errRtn:
+ OLETRACEOUT((API_GetConvertStg, error));
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SetConvertStg
+//
+// Synopsis: Sets the convert bit in a storage
+//
+// Effects:
+//
+// Arguments: [pStg] -- pointer to the storage
+// [fConvert] -- convert bit
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(SetConvertStg)
+STDAPI SetConvertStg(LPSTORAGE pStg, BOOL fConvert)
+{
+ OLETRACEIN((API_SetConvertStg, PARAMFMT("pStg= %p, fConvert= %B"),
+ pStg, fConvert));
+
+ VDATEHEAP();
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pStg);
+
+ HRESULT hr;
+
+ hr = SetBitOleStg(pStg, fConvert ? -1L : ~OBJFLAGS_CONVERT,
+ fConvert ? OBJFLAGS_CONVERT : 0);
+
+ OLETRACEOUT((API_SetConvertStg, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReadClipformatStm
+//
+// Synopsis: Reads the clipboard format from the given stream
+//
+// Effects: If the clipboard format is a length followed by a
+// string, then the string is read and registered as a
+// clipboard format (and the new format number is returned).
+//
+// Arguments: [lpstream] -- pointer to the stream
+// [lpdwCf] -- where to put the clipboard format
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: the format of the stream must be one of the following:
+// 0 No clipboard format
+// -1 DWORD predefined windows clipboard format in
+// the second dword.
+// -2 DWORD predefined mac clipboard format in the
+// second dword. This may be obsolete or
+// irrelevant for us. REVIEW32
+// num STRING clipboard format name string (prefaced
+// by length of string).
+//
+// History: dd-mmm-yy Author Comment
+// 27-Oct-93 alexgo 32bit port, fixed ifdef and NULL
+// pointer bugs
+//
+// 17-Mar-94 davepl Revereted to ANSI string reads
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI ReadClipformatStm(LPSTREAM lpstream, DWORD FAR* lpdwCf)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ DWORD dwValue;
+
+ VDATEIFACE(lpstream);
+ VDATEPTROUT(lpdwCf, DWORD);
+
+ if (error = StRead(lpstream, &dwValue, sizeof(DWORD)))
+ {
+ return error;
+ }
+
+ if (dwValue == NULL)
+ {
+ // NULL cf value
+ *lpdwCf = NULL;
+
+ }
+ else if (dwValue == -1L)
+ {
+ // Then this is a NON-NULL predefined windows clipformat.
+ // The clipformat values follows
+
+ if (error = StRead(lpstream, &dwValue, sizeof(DWORD)))
+ return error;
+
+ *lpdwCf = dwValue;
+
+ }
+ else if (dwValue == -2L)
+ {
+ // Then this is a NON-NULL MAC clipboard format.
+ // The clipformat value follows. For MAC the CLIPFORMAT
+ // is 4 bytes
+
+ if (error = StRead(lpstream, &dwValue, sizeof(DWORD)))
+ {
+ return error;
+ }
+ *lpdwCf = dwValue;
+ return ResultFromScode(OLE_S_MAC_CLIPFORMAT);
+ }
+ else
+ {
+ char szACF[MAX_STR];
+
+ if (error = StRead(lpstream, szACF, dwValue))
+ {
+ return error;
+ }
+
+ if (((*lpdwCf = (DWORD) SSRegisterClipboardFormatA(szACF))) == 0)
+ {
+ return ResultFromScode(DV_E_CLIPFORMAT);
+ }
+ }
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: WriteClipformatStm
+//
+// Synopsis: Writes the clipboard format the given stream
+//
+// Arguments: [lpstream] -- pointer to the stream
+// [cf] -- the clipboard format
+//
+// Returns: HRESULT
+//
+// History: dd-mmm-yy Author Comment
+// 11-Jan-94 alexgo cast -1 to a DWORD to remove compile
+// warning
+// 27-Oct-93 alexgo 32bit port
+// 16-Mar-94 davepl Revereted to ANSI string writes
+//
+// Notes: see ReadClipformatStm for a description of the
+// data layout in the stream
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(WriteClipformatStm)
+STDAPI WriteClipformatStm(LPSTREAM lpstream, CLIPFORMAT cf)
+{
+ VDATEHEAP();
+
+#ifdef _MAC
+
+ AssertSz(0,"WriteClipformatStm NYI");
+ return ReportResult(0, E_NOTIMPL, 0, 0);
+
+#else
+
+ HRESULT error;
+
+ VDATEIFACE( lpstream );
+
+ //REVIEW32 where the hell did 0xC000 come from??? Is this
+ //portable to NT && Chicago??? Try to replace with a constant.
+ //(although there don't seem to be any :( )
+
+ if (cf < 0xC000)
+ {
+ DWORD dwBuf[2];
+ DWORD dwSize = sizeof(DWORD);
+
+ if (cf == NULL)
+ {
+ dwBuf[0] = NULL;
+ }
+ else
+ {
+ // write -1L, to indicate NON NULL predefined
+ // clipboard format
+
+ dwBuf[0] = (DWORD)-1L;
+ dwBuf[1] = (DWORD)cf;
+ dwSize += sizeof(DWORD);
+ }
+
+ if (error = StWrite(lpstream, dwBuf, dwSize))
+ {
+ return error;
+ }
+
+ }
+ else
+ {
+ // it is a registerd clipboard format
+
+ char szACF[MAX_STR];
+ ULONG len;
+
+ // Get the name of the clipboard format
+
+ len = SSGetClipboardFormatNameA(cf, szACF, sizeof(szACF));
+ if (0 == len)
+ {
+ return ResultFromScode(E_UNSPEC);
+ }
+
+ ++len; // Account for NULL terminator
+ if (error = StWrite(lpstream, &len, sizeof(len)))
+ {
+ return error;
+ }
+
+ // Write it (plus terminator) to the stream
+ if (error = StWrite(lpstream, szACF, len))
+ {
+ return error;
+ }
+ }
+
+ return NOERROR;
+
+#endif // _MAC
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: WriteMonikerStm
+//
+// Synopsis: Writes the persistent state of the given moniker to the
+// given stream. Internal
+//
+// Effects:
+//
+// Arguments: [pstm] -- pointer to the stream
+// [pmk] -- pointer to the moniker
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(WriteMonikerStm)
+// write size long followed by persistent moniker
+STDAPI WriteMonikerStm (LPSTREAM pstm, LPMONIKER pmk)
+{
+ VDATEHEAP();
+
+ DWORD cb = NULL;
+ ULARGE_INTEGER dwBegin;
+ ULARGE_INTEGER dwEnd;
+ HRESULT error;
+ LARGE_INTEGER large_integer;
+
+ VDATEIFACE( pstm );
+
+ if (pmk == NULL)
+ return pstm->Write(&cb, sizeof(DWORD), NULL);
+ else {
+ VDATEIFACE( pmk );
+ // get the begining position
+ LISet32( large_integer, 0 );
+ if ((error = pstm->Seek (large_integer,
+ STREAM_SEEK_CUR, &dwBegin)) != NOERROR)
+ return error;
+
+ // skip the moniker size DWORD
+ LISet32( large_integer, 4);
+ if ((error = pstm->Seek (large_integer,
+ STREAM_SEEK_CUR, NULL)) != NOERROR)
+ return error;
+
+ if ((error = OleSaveToStream (pmk, pstm)) != NOERROR)
+ return error;
+
+ // get the end position
+ LISet32( large_integer, 0);
+ if ((error = pstm->Seek (large_integer,
+ STREAM_SEEK_CUR, &dwEnd)) != NOERROR)
+ return error;
+
+ // moniker data size
+ cb = dwEnd.LowPart - dwBegin.LowPart;
+
+ // seek to the begining position
+ LISet32( large_integer, dwBegin.LowPart);
+ if ((error = pstm->Seek (large_integer,
+ STREAM_SEEK_SET,NULL)) != NOERROR)
+ return error;
+
+ // write moniker info size
+ if ((error = pstm->Write(&cb, sizeof(DWORD),
+ NULL)) != NOERROR)
+ return error;
+
+ // seek to the end position
+ LISet32( large_integer, dwEnd.LowPart);
+ return pstm->Seek (large_integer, STREAM_SEEK_SET, NULL);
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReadMonikerStm
+//
+// Synopsis: Reads a moniker from the given stream (inverse of
+// WriteMonikerStm)
+//
+// Effects:
+//
+// Arguments: [pstm] -- pointer to the stream
+// [ppmk] -- where to put the moniker
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(ReadMonikerStm)
+// read size long followed by persistent moniker
+STDAPI ReadMonikerStm (LPSTREAM pstm, LPMONIKER FAR* ppmk)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ DWORD cb;
+
+ VDATEPTROUT( ppmk, LPMONIKER );
+ *ppmk = NULL;
+ VDATEIFACE( pstm );
+
+ if ((error = StRead (pstm, &cb, sizeof(DWORD))) != NOERROR)
+ return error;
+
+ if (cb == NULL)
+ return NOERROR;
+
+ return OleLoadFromStream (pstm, IID_IMoniker, (LPLPVOID) ppmk);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleDraw
+//
+// Synopsis: Calls IViewObject->Draw on the given object
+//
+// Effects: Draws something on the screen :)
+//
+// Arguments: [lpUnk] -- pointer to the object
+// [dwAspect] -- aspect to draw (NORMAL, ICON, etc)
+// [hdcDraw] -- the device context to use
+// [lprcBounds] -- the rectangle in which to draw
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Apr-94 alexgo fixed usage of MAKELONG (only
+// for 16bit)
+// 27-Oct-93 alexgo 32bit port
+//
+// Notes:
+// On Win32, RECT and RECTL are identical structures, thus there
+// is no need to convert from RECT to RECTL with MAKELONG.
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleDraw)
+STDAPI OleDraw (LPUNKNOWN lpUnk, DWORD dwAspect, HDC hdcDraw,
+ LPCRECT lprcBounds)
+{
+ HRESULT error;
+ IViewObject FAR* lpView;
+
+#ifndef WIN32
+ RECTL rclBounds;
+#endif //!WIN32
+
+ OLETRACEIN((API_OleDraw, PARAMFMT("lpUnk= %p, dwAspect= %x, hdcDraw= %h, lprcBounds= %tr"),
+ lpUnk, dwAspect, hdcDraw, lprcBounds));
+
+ VDATEHEAP();
+
+
+ VDATEIFACE_LABEL( lpUnk, errRtn, error );
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&lpUnk);
+
+ VDATEPTRIN_LABEL( lprcBounds, RECT, errRtn, error);
+
+#ifndef WIN32
+ rclBounds.left = MAKELONG(lprcBounds->left, 0);
+ rclBounds.right = MAKELONG(lprcBounds->right, 0);
+ rclBounds.top = MAKELONG(lprcBounds->top, 0);
+ rclBounds.bottom = MAKELONG(lprcBounds->bottom, 0);
+
+ lprcBounds = &rclBounds;
+#endif //!WIN32
+
+ if ((error = lpUnk->QueryInterface (IID_IViewObject,
+ (LPLPVOID)&lpView)) != NOERROR)
+ {
+ error = ResultFromScode(DV_E_NOIVIEWOBJECT);
+ goto errRtn;
+ }
+
+ error = lpView->Draw (dwAspect, DEF_LINDEX, 0, 0, 0,
+ hdcDraw, (LPCRECTL)lprcBounds, 0, 0,0);
+ lpView->Release();
+
+errRtn:
+ OLETRACEOUT((API_OleDraw, error));
+
+ return error;
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// CreateObjectDescriptor, static
+//
+// Synopsis:
+// Creates and initializes an OBJECTDESCRIPTOR from the given
+// parameters
+//
+// Arguments:
+// [clsid] -- the class ID of the object being transferred
+// [dwAspect] -- the display aspect drawn by the source of the
+// transfer
+// [psizel] -- pointer to the size of the object
+// [ppointl] -- pointer to the mouse offset in the object that
+// initiated a drag-drop transfer
+// [dwStatus] -- the OLEMISC status flags for the object
+// being transferred
+// [lpszFullUserTypeName] -- the full user type name of the
+// object being transferred
+// [lpszSrcOfCopy] -- a human readable name for the object
+// being transferred
+//
+// Returns:
+// If successful, A handle to the new OBJECTDESCRIPTOR; otherwise
+// NULL.
+//
+// Notes:
+// REVIEW, this seems generally useful for anyone using the
+// clipboard, or drag-drop; perhaps it should be exported.
+//
+// History:
+// 12/07/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CreateObjectDescriptor)
+INTERNAL_(HGLOBAL) CreateObjectDescriptor(CLSID clsid, DWORD dwAspect,
+ const SIZEL FAR *psizel, const POINTL FAR *ppointl,
+ DWORD dwStatus, LPOLESTR lpszFullUserTypeName,
+ LPOLESTR lpszSrcOfCopy)
+{
+ VDATEHEAP();
+
+ DWORD dwFullUserTypeNameBLen; // length of lpszFullUserTypeName in BYTES
+ DWORD dwSrcOfCopyBLen; // length of lpszSrcOfCopy in BYTES
+ HGLOBAL hMem; // handle to the object descriptor
+ LPOBJECTDESCRIPTOR lpOD; // the new object descriptor
+
+ // Get the length of Full User Type Name; Add 1 for the null terminator
+ if (!lpszFullUserTypeName)
+ dwFullUserTypeNameBLen = 0;
+ else
+ dwFullUserTypeNameBLen = (_xstrlen(lpszFullUserTypeName) +
+ 1) * sizeof(OLECHAR);
+
+ // Get the Source of Copy string and it's length; Add 1 for the null
+ // terminator
+ if (lpszSrcOfCopy)
+ dwSrcOfCopyBLen = (_xstrlen(lpszSrcOfCopy) + 1) *
+ sizeof(OLECHAR);
+ else
+ {
+ // No src moniker so use user type name as source string.
+ lpszSrcOfCopy = lpszFullUserTypeName;
+ dwSrcOfCopyBLen = dwFullUserTypeNameBLen;
+ }
+
+ // allocate the memory where we'll put the object descriptor
+ hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
+ sizeof(OBJECTDESCRIPTOR) + dwFullUserTypeNameBLen +
+ dwSrcOfCopyBLen);
+ if (hMem == NULL)
+ goto error;
+
+ lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(hMem);
+ if (lpOD == NULL)
+ goto error;
+
+ // Set the FullUserTypeName offset and copy the string
+ if (!lpszFullUserTypeName)
+ {
+ // zero offset indicates that string is not present
+ lpOD->dwFullUserTypeName = 0;
+ }
+ else
+ {
+ lpOD->dwFullUserTypeName = sizeof(OBJECTDESCRIPTOR);
+ _xmemcpy(((BYTE FAR *)lpOD)+lpOD->dwFullUserTypeName,
+ (const void FAR *)lpszFullUserTypeName,
+ dwFullUserTypeNameBLen);
+ }
+
+ // Set the SrcOfCopy offset and copy the string
+ if (!lpszSrcOfCopy)
+ {
+ // zero offset indicates that string is not present
+ lpOD->dwSrcOfCopy = 0;
+ }
+ else
+ {
+ lpOD->dwSrcOfCopy = sizeof(OBJECTDESCRIPTOR) +
+ dwFullUserTypeNameBLen;
+ _xmemcpy(((BYTE FAR *)lpOD)+lpOD->dwSrcOfCopy,
+ (const void FAR *)lpszSrcOfCopy,
+ dwSrcOfCopyBLen);
+ }
+
+ // Initialize the rest of the OBJECTDESCRIPTOR
+ lpOD->cbSize = sizeof(OBJECTDESCRIPTOR) + dwFullUserTypeNameBLen +
+ dwSrcOfCopyBLen;
+ lpOD->clsid = clsid;
+ lpOD->dwDrawAspect = dwAspect;
+ lpOD->sizel = *psizel;
+ lpOD->pointl = *ppointl;
+ lpOD->dwStatus = dwStatus;
+
+ GlobalUnlock(hMem);
+ return(hMem);
+
+error:
+ if (hMem)
+ {
+ GlobalUnlock(hMem);
+ GlobalFree(hMem);
+ }
+
+ return(NULL);
+}
+
diff --git a/private/ole32/ole232/base/create.cpp b/private/ole32/ole232/base/create.cpp
new file mode 100644
index 000000000..8de0bee6f
--- /dev/null
+++ b/private/ole32/ole232/base/create.cpp
@@ -0,0 +1,4803 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: create.cpp
+//
+// Contents: creation and miscellaneous APIs
+//
+// Classes:
+//
+// Functions: OleCreate
+// OleCreateEx
+// OleCreateFromData
+// OleCreateFromDataEx
+// OleCreateLinkFromData
+// OleCreateLinkFromDataEx
+// OleCreateLink
+// OleCreateLinkEx
+// OleCreateLinkToFile
+// OleCreateLinkToFileEx
+// OleCreateFromFile
+// OleCreateFromFileEx
+// OleDoAutoConvert
+// OleLoad
+// OleCreateStaticFromData
+// OleQueryCreateFromData
+// OleQueryLinkFromData
+// CoIsHashedOle1Class (internal)
+// EnsureCLSIDIsRegistered (internal)
+//
+// History: dd-mmm-yy Author Comment
+// 26-Apr-96 davidwor Moved validation into separate function.
+// 01-Mar-96 davidwor Added extended create functions.
+// 16-Dec-94 alexgo added call tracing
+// 07-Jul-94 KevinRo Changed RegQueryValue to RegOpenKey in
+// strategic places.
+// 10-May-94 KevinRo Reimplemented OLE 1.0 interop
+// 24-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocation
+// 11-Jan-94 alexgo added VDATEHEAP macros to every function
+// 10-Dec-93 AlexT header clean up - include ole1cls.h
+// 08-Dec-93 ChrisWe added necessary casts to GlobalLock() calls
+// resulting from removing bogus GlobalLock() macros in
+// le2int.h
+// 29-Nov-93 ChrisWe changed call to UtIsFormatSupported to
+// take a single DWORD of direction flags
+// 22-Nov-93 ChrisWe replaced overloaded == with IsEqualxID
+// 28-Oct-93 alexgo 32bit port
+// 24-Aug-92 srinik created
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#pragma SEG(create)
+
+#include <create.h>
+#include <ole1cls.h> // Only needed to get CLSID_WordDocument
+
+// HACK ALERT!! This is needed for the MFC OleQueryCreateFromData hack
+#include "..\clipbrd\clipdata.h"
+
+NAME_SEG(Create)
+ASSERTDATA
+
+//used in wCreateObject
+
+#define STG_NONE 0
+#define STG_INITNEW 1
+#define STG_LOAD 2
+
+
+#define QUERY_CREATE_NONE 0
+#define QUERY_CREATE_OLE 1
+#define QUERY_CREATE_STATIC 2
+
+INTERNAL wDoUpdate(IUnknown FAR* lpUnknown);
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wGetEnumFormatEtc
+//
+// Synopsis: retrieves a FormatEtc enumerator
+//
+// Effects:
+//
+// Arguments: [pDataObj] -- the data object
+// [dwDirection] -- direction
+// [ppenum] -- where to put the enumerator
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: asks the data object for the enumerator
+// if it returns OLE_S_USEREG, then get try to get the
+// clsid from IOleObject::GetUserClassID and enumerate
+// the formats from the registry.
+//
+// History: dd-mmm-yy Author Comment
+// 24-Apr-94 alexgo author
+// 13-Mar-95 scottsk Added hack for the Bob Calendar
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT wGetEnumFormatEtc( IDataObject *pDataObj, DWORD dwDirection,
+ IEnumFORMATETC **ppIEnum)
+{
+ HRESULT hresult;
+ IOleObject * pOleObject;
+ CLSID clsid;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN wGetEnumFormatEtc ( %p , %p , %lx )"
+ "\n", NULL, pDataObj, ppIEnum, dwDirection));
+
+ hresult = pDataObj->EnumFormatEtc(dwDirection, ppIEnum);
+
+ if( hresult == ResultFromScode(OLE_S_USEREG) )
+ {
+ hresult = pDataObj->QueryInterface(IID_IOleObject,
+ (void **)&pOleObject);
+
+ if( hresult != NOERROR )
+ {
+ // return E_FAIL vs E_NOINTERFACE
+ hresult = ResultFromScode(E_FAIL);
+ goto errRtn;
+ }
+
+ hresult = pOleObject->GetUserClassID(&clsid);
+
+ if( hresult == NOERROR )
+ {
+ hresult = OleRegEnumFormatEtc(clsid, dwDirection,
+ ppIEnum);
+ }
+
+ pOleObject->Release();
+ }
+ else if (*ppIEnum == NULL && hresult == NOERROR)
+ {
+ // HACK ALERT: NT Bug #8350. MS Bob Calendar returns success from
+ // IDO::EnumFormatEtc and sets *ppIEnum = NULL on the IDO used during
+ // drag-drop. Massage the return value to be failure.
+ hresult = E_FAIL;
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT wGetEnumFormatEtc ( %lx ) [ %p ]\n",
+ NULL, hresult, *ppIEnum));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreate
+//
+// Synopsis: Creates and runs an object of the requested CLSID
+//
+// Effects:
+//
+// Arguments: [rclsid] -- the CLSID of the object to create
+// [iid] -- the interface to request on the object
+// [renderopt] -- render options, such as OLERENDER_DRAW
+// [lpFormatEtc] -- rendering format, if OLERENDER_FORMAT is
+// specified in renderopt.
+// [lpClientSite] -- the client site for the object
+// [lpStg] -- the object's storage
+// [lplpObj] -- where to put the pointer to the created
+// object
+//
+// Requires: HRESULT
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-94 alexgo added call tracing
+// 05-May-94 alexgo fixed error case if cache initialization
+// fails.
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(OleCreate)
+STDAPI OleCreate
+(
+ REFCLSID rclsid,
+ REFIID iid,
+ DWORD renderopt,
+ LPFORMATETC lpFormatEtc,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ DWORD advf = ADVF_PRIMEFIRST;
+
+ return OleCreateEx(rclsid, iid, 0, renderopt,
+ (lpFormatEtc ? 1 : 0), (lpFormatEtc ? &advf : NULL),
+ lpFormatEtc, NULL, NULL, lpClientSite, lpStg, lplpObj);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateEx
+//
+// Synopsis: Creates and runs an object of the requested CLSID
+//
+// Effects:
+//
+// Arguments: [rclsid] -- the CLSID of the object to create
+// [iid] -- the interface to request on the object
+// [dwFlags] -- object creation flags
+// [renderopt] -- render options, such as OLERENDER_DRAW
+// [cFormats] -- the number of elements in rgFormatEtc
+// [rgAdvf] -- array of advise flags, if OLRENDER_FORMAT
+// is specified in renderopt
+// [rgFormatEtc] -- array of rendering formats, if
+// OLERENDER_FORMAT is specified in renderopt
+// [lpAdviseSink] -- the advise sink for the object
+// [rgdwConnection]-- where to put the connection IDs for the
+// advisory connections
+// [lpClientSite] -- the client site for the object
+// [lpStg] -- the object's storage
+// [lplpObj] -- where to put the pointer to the created
+// object
+//
+// Requires: HRESULT
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-94 alexgo added call tracing
+// 05-May-94 alexgo fixed error case if cache initialization
+// fails.
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(OleCreateEx)
+STDAPI OleCreateEx
+(
+ REFCLSID rclsid,
+ REFIID iid,
+ DWORD dwFlags,
+ DWORD renderopt,
+ ULONG cFormats,
+ DWORD FAR* rgAdvf,
+ LPFORMATETC rgFormatEtc,
+ IAdviseSink FAR* lpAdviseSink,
+ DWORD FAR* rgdwConnection,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ OLETRACEIN((API_OleCreateEx,
+ PARAMFMT("rclsid= %I, iid= %I, dwFlags= %x, renderopt= %x, cFormats= %x, rgAdvf= %te, rgFormatEtc= %p, lpAdviseSink= %p, rgdwConnection= %p, lpClientSite= %p, lpStg= %p, lplpObj= %p"),
+ &rclsid, &iid, dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite, lpStg, lplpObj));
+
+ VDATEHEAP();
+
+ HRESULT error;
+ FORMATETC formatEtc;
+ LPFORMATETC lpFormatEtc;
+ BOOL fAlloced = FALSE;
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleCreateEx ( %p , %p , %lx , %lx , %lx ,"
+ "%p , %p , %p , %p , %p , %p , %p )\n", 0, &rclsid, &iid, dwFlags,
+ renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection,
+ lpClientSite, lpStg, lplpObj));
+
+ VDATEPTROUT_LABEL( lplpObj, LPVOID, errRtn, error );
+ *lplpObj = NULL;
+
+ VDATEIID_LABEL( iid, errRtn, error);
+
+ error = wValidateCreateParams(dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite, lpStg);
+ if (error != NOERROR)
+ goto errRtn;
+
+ if ((error = wValidateFormatEtcEx(renderopt, &cFormats, rgFormatEtc,
+ &formatEtc, &lpFormatEtc, &fAlloced)) != NOERROR)
+ goto LExit;
+
+ if ((error = wCreateObject(rclsid, iid, lpClientSite, lpStg,
+ STG_INITNEW, lplpObj)) != NOERROR)
+ goto LExit;
+
+ // No need to Run the object if no caches are requested.
+ if ((renderopt != OLERENDER_NONE) && (renderopt != OLERENDER_ASIS))
+ {
+ if ((error = OleRun((LPUNKNOWN) *lplpObj)) != NOERROR)
+ goto LExit;
+
+ if ((error = wInitializeCacheEx(NULL, rclsid, renderopt,
+ cFormats, rgAdvf, lpFormatEtc, lpAdviseSink, rgdwConnection,
+ *lplpObj))
+ != NOERROR)
+ {
+ // if this fails, we need to call Close
+ // to shut down the embedding (the reverse of Run).
+ // the final release below will be the final
+ // one to nuke the memory image.
+ IOleObject * lpOleObject;
+
+ if( ((IUnknown *)*lplpObj)->QueryInterface(
+ IID_IOleObject, (void **)&lpOleObject) == NOERROR )
+ {
+ Assert(lpOleObject);
+ lpOleObject->Close(OLECLOSE_NOSAVE);
+ lpOleObject->Release();
+ }
+ }
+ }
+
+LExit:
+
+ if (fAlloced)
+ PubMemFree(lpFormatEtc);
+
+ if (error != NOERROR && *lplpObj) {
+ ((IUnknown FAR*) *lplpObj)->Release();
+ *lplpObj = NULL;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleCreateEx ( %lx ) [ %p ]\n", 0,
+ error, *lplpObj));
+
+ error = wReturnCreationError(error);
+
+errRtn:
+ OLETRACEOUT((API_OleCreateEx, error));
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateFromData
+//
+// Synopsis: Creates an embedded object from an IDataObject pointer
+// (such as an data object from the clipboard or from a drag
+// and drop operation)
+//
+// Effects:
+//
+// Arguments: [lpSrcDataObj] -- pointer to the data object from which
+// the object should be created
+// [iid] -- interface ID to request
+// [renderopt] -- rendering options (same as OleCreate)
+// [lpFormatEtc] -- render format options (same as OleCreate)
+// [lpClientSite] -- client site for the object
+// [lpStg] -- storage for the object
+// [lplpObj] -- where to put the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-94 alexgo added call tracing
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(OleCreateFromData)
+STDAPI OleCreateFromData
+(
+ IDataObject FAR* lpSrcDataObj,
+ REFIID iid,
+ DWORD renderopt,
+ LPFORMATETC lpFormatEtc,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ DWORD advf = ADVF_PRIMEFIRST;
+
+ return OleCreateFromDataEx(lpSrcDataObj, iid, 0, renderopt,
+ (lpFormatEtc ? 1 : 0), (lpFormatEtc ? &advf : NULL),
+ lpFormatEtc, NULL, NULL, lpClientSite, lpStg, lplpObj);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateFromDataEx
+//
+// Synopsis: Creates an embedded object from an IDataObject pointer
+// (such as an data object from the clipboard or from a drag
+// and drop operation)
+//
+// Effects:
+//
+// Arguments: [lpSrcDataObj] -- pointer to the data object from which
+// the object should be created
+// [iid] -- interface ID to request
+// [dwFlags] -- object creation flags
+// [renderopt] -- render options, such as OLERENDER_DRAW
+// [cFormats] -- the number of elements in rgFormatEtc
+// [rgAdvf] -- array of advise flags, if OLRENDER_FORMAT
+// is specified in renderopt
+// [rgFormatEtc] -- array of rendering formats, if
+// OLERENDER_FORMAT is specified in renderopt
+// [lpAdviseSink] -- the advise sink for the object
+// [rgdwConnection]-- where to put the connection IDs for the
+// advisory connections
+// [lpClientSite] -- client site for the object
+// [lpStg] -- storage for the object
+// [lplpObj] -- where to put the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-94 alexgo added call tracing
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(OleCreateFromDataEx)
+STDAPI OleCreateFromDataEx
+(
+ IDataObject FAR* lpSrcDataObj,
+ REFIID iid,
+ DWORD dwFlags,
+ DWORD renderopt,
+ ULONG cFormats,
+ DWORD FAR* rgAdvf,
+ LPFORMATETC rgFormatEtc,
+ IAdviseSink FAR* lpAdviseSink,
+ DWORD FAR* rgdwConnection,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ HRESULT hresult;
+ CLIPFORMAT cfFormat;
+ WORD wStatus;
+
+ OLETRACEIN((API_OleCreateFromDataEx,
+ PARAMFMT("lpSrcDataObj= %p, iid= %I, dwFlags= %x, renderopt= %x, cFormats= %x, rgAdvf= %te, rgFormatEtc= %p, lpAdviseSink= %p, rgdwConnection= %p, lpClientSite= %p, lpStg= %p, lplpObj= %p"),
+ lpSrcDataObj, &iid, dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite, lpStg, lplpObj));
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleCreateFromDataEx ( %p , %p , %lx , %lx ,"
+ " %lx , %p , %p , %p , %p , %p , %p , %p )\n", 0, lpSrcDataObj, &iid,
+ dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink,
+ rgdwConnection, lpClientSite, lpStg, lplpObj));
+
+ VDATEPTROUT_LABEL( lplpObj, LPVOID, safeRtn, hresult );
+ *lplpObj = NULL;
+
+ VDATEIFACE_LABEL( lpSrcDataObj, errRtn, hresult );
+ VDATEIID_LABEL( iid, errRtn, hresult );
+
+ hresult = wValidateCreateParams(dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite, lpStg);
+ if (hresult != NOERROR)
+ goto errRtn;
+
+ wStatus = wQueryEmbedFormats(lpSrcDataObj, &cfFormat);
+
+ if (!(wStatus & QUERY_CREATE_OLE))
+ {
+ if (wStatus & QUERY_CREATE_STATIC)
+ {
+ hresult = OLE_E_STATIC;
+ }
+ else
+ {
+ hresult = DV_E_FORMATETC;
+ }
+
+ goto errRtn;
+ }
+
+ // We can create an OLE object.
+
+ // See whether we have to create a package
+
+ //BUGBUG: REVIEW32: wQueryEmbedFormats returns the *first*
+ //format available, not necessarily the one we wanted.
+ //do we necessarily want to create a package, especially if
+ //a "normal" embedding format is available??
+
+ if (cfFormat == g_cfFileName || cfFormat == g_cfFileNameW)
+ {
+ hresult = wCreatePackageEx(lpSrcDataObj, iid, dwFlags, renderopt,
+ cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection,
+ lpClientSite, lpStg, FALSE /*fLink*/, lplpObj);
+ }
+ else
+ {
+ hresult = wCreateFromDataEx(lpSrcDataObj, iid, dwFlags, renderopt,
+ cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection,
+ lpClientSite, lpStg, lplpObj);
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleCreateFromDataEx ( %lx ) [ %p ]\n",
+ 0, hresult, *lplpObj));
+
+safeRtn:
+
+ OLETRACEOUT((API_OleCreateFromDataEx, hresult));
+
+ return hresult;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateLinkFromData
+//
+// Synopsis: Creates a link from a data object (e.g. for Paste->Link)
+//
+// Effects:
+//
+// Arguments: [lpSrcDataObj] -- pointer to the data object
+// [iid] -- requested interface ID
+// [renderopt] -- rendering options
+// [lpFormatEtc] -- format to render (if renderopt ==
+// OLERENDER_FORMAT)
+// [lpClientSite] -- pointer to the client site
+// [lpStg] -- pointer to the storage
+// [lplpObj] -- where to put the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-94 alexgo added call tracing
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(OleCreateLinkFromData)
+STDAPI OleCreateLinkFromData
+(
+ IDataObject FAR* lpSrcDataObj,
+ REFIID iid,
+ DWORD renderopt,
+ LPFORMATETC lpFormatEtc,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ DWORD advf = ADVF_PRIMEFIRST;
+
+ return OleCreateLinkFromDataEx(lpSrcDataObj, iid, 0, renderopt,
+ (lpFormatEtc ? 1 : 0), (lpFormatEtc ? &advf : NULL),
+ lpFormatEtc, NULL, NULL, lpClientSite, lpStg, lplpObj);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateLinkFromDataEx
+//
+// Synopsis: Creates a link from a data object (e.g. for Paste->Link)
+//
+// Effects:
+//
+// Arguments: [lpSrcDataObj] -- pointer to the data object
+// [iid] -- requested interface ID
+// [dwFlags] -- object creation flags
+// [renderopt] -- render options, such as OLERENDER_DRAW
+// [cFormats] -- the number of elements in rgFormatEtc
+// [rgAdvf] -- array of advise flags, if OLRENDER_FORMAT
+// is specified in renderopt
+// [rgFormatEtc] -- array of rendering formats, if
+// OLERENDER_FORMAT is specified in renderopt
+// [lpAdviseSink] -- the advise sink for the object
+// [rgdwConnection]-- where to put the connection IDs for the
+// advisory connections
+// [lpClientSite] -- pointer to the client site
+// [lpStg] -- pointer to the storage
+// [lplpObj] -- where to put the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-94 alexgo added call tracing
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(OleCreateLinkFromDataEx)
+STDAPI OleCreateLinkFromDataEx
+(
+ IDataObject FAR* lpSrcDataObj,
+ REFIID iid,
+ DWORD dwFlags,
+ DWORD renderopt,
+ ULONG cFormats,
+ DWORD FAR* rgAdvf,
+ LPFORMATETC rgFormatEtc,
+ IAdviseSink FAR* lpAdviseSink,
+ DWORD FAR* rgdwConnection,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ OLETRACEIN((API_OleCreateLinkFromDataEx,
+ PARAMFMT("lpSrcDataObj= %p, iid= %I, dwFlags= %x, renderopt= %x, cFormats= %x, rgAdvf= %te, rgFormatEtc= %p, lpAdviseSink= %p, rgdwConnection= %p, lpClientSite= %p, lpStg= %p, lplpObj= %p"),
+ lpSrcDataObj, &iid, dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite, lpStg, lplpObj));
+
+ VDATEHEAP();
+
+ HRESULT error;
+ FORMATETC formatEtc;
+ LPFORMATETC lpFormatEtc;
+ BOOL fAlloced = FALSE;
+ CLIPFORMAT cfFormat;
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleCreateLinkFromDataEx ( %p , %p , %lx,"
+ " %lx, %lx , %p , %p , %p, %p , %p , %p, %p )\n", NULL, lpSrcDataObj,
+ &iid, dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink,
+ rgdwConnection, lpClientSite, lpStg, lplpObj));
+
+ VDATEPTROUT_LABEL( lplpObj, LPVOID, safeRtn, error );
+ *lplpObj = NULL;
+
+ VDATEIFACE_LABEL( lpSrcDataObj, errRtn, error );
+ VDATEIID_LABEL( iid, errRtn, error );
+
+ error = wValidateCreateParams(dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite, lpStg);
+ if (error != NOERROR)
+ goto errRtn;
+
+ cfFormat = wQueryLinkFormats(lpSrcDataObj);
+
+ if (cfFormat == g_cfLinkSource) {
+ CLSID clsidLast;
+ LPMONIKER lpmkSrc;
+ LPDATAOBJECT lpBoundDataObj = NULL;
+
+ // we are going to create a normal link
+ if ((error = wValidateFormatEtcEx(renderopt, &cFormats, rgFormatEtc,
+ &formatEtc, &lpFormatEtc, &fAlloced)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if ((error = wGetMonikerAndClassFromObject(lpSrcDataObj,
+ &lpmkSrc, &clsidLast)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if (wQueryUseCustomLink(clsidLast)) {
+ // the object supports Custom Link Source, so bind
+ // to the object and pass its IDataObject pointer
+ // to wCreateLinkEx()
+
+ if (BindMoniker(lpmkSrc, NULL /*grfOpt*/, IID_IDataObject,
+ (LPLPVOID) &lpBoundDataObj) == NOERROR)
+ {
+ lpSrcDataObj = lpBoundDataObj;
+ }
+ }
+
+ // otherwise continue to use StdOleLink implementation
+ error = wCreateLinkEx(lpmkSrc, clsidLast, lpSrcDataObj, iid,
+ dwFlags, renderopt, cFormats, rgAdvf, lpFormatEtc, lpAdviseSink,
+ rgdwConnection, lpClientSite, lpStg, lplpObj);
+
+ // we don't need the moniker anymore
+ lpmkSrc->Release();
+
+ // we would have bound in the custom link source case,
+ // release the pointer
+ if (lpBoundDataObj)
+ {
+ if (error == NOERROR && (dwFlags & OLECREATE_LEAVERUNNING))
+ OleRun((LPUNKNOWN)*lplpObj);
+
+ lpBoundDataObj->Release();
+ }
+
+ } else if (cfFormat == g_cfFileName || cfFormat == g_cfFileNameW) {
+ // See whether we have to create a packaged link
+
+ error = wCreatePackageEx(lpSrcDataObj, iid, dwFlags, renderopt,
+ cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection,
+ lpClientSite, lpStg, TRUE /*fLink*/, lplpObj);
+ }
+ else
+ {
+ error = DV_E_FORMATETC;
+ }
+
+errRtn:
+
+ if (fAlloced)
+ PubMemFree(lpFormatEtc);
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleCreateLinkFromDataEx ( %lx ) [ %p ]\n",
+ NULL, error, *lplpObj));
+
+safeRtn:
+
+ OLETRACEOUT((API_OleCreateLinkFromDataEx, error));
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateLink
+//
+// Synopsis: Create a link to the object referred to by a moniker
+//
+// Effects:
+//
+// Arguments: [lpmkSrc] -- source of the link
+// [iid] -- interface requested
+// [renderopt] -- rendering options
+// [lpFormatEtc] -- rendering format (if needed)
+// [lpClientSite] -- pointer to the client site for the link
+// [lpStg] -- storage for the link
+// [lplpObj] -- where to put the link object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-94 alexgo added call tracing
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(OleCreateLink)
+STDAPI OleCreateLink
+(
+ IMoniker FAR* lpmkSrc,
+ REFIID iid,
+ DWORD renderopt,
+ LPFORMATETC lpFormatEtc,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ DWORD advf = ADVF_PRIMEFIRST;
+
+ return OleCreateLinkEx(lpmkSrc, iid, 0, renderopt,
+ (lpFormatEtc ? 1 : 0), (lpFormatEtc ? &advf : NULL),
+ lpFormatEtc, NULL, NULL, lpClientSite, lpStg, lplpObj);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateLinkEx
+//
+// Synopsis: Create a link to the object referred to by a moniker
+//
+// Effects:
+//
+// Arguments: [lpmkSrc] -- source of the link
+// [iid] -- interface requested
+// [dwFlags] -- object creation flags
+// [renderopt] -- render options, such as OLERENDER_DRAW
+// [cFormats] -- the number of elements in rgFormatEtc
+// [rgAdvf] -- array of advise flags, if OLRENDER_FORMAT
+// is specified in renderopt
+// [rgFormatEtc] -- array of rendering formats, if
+// OLERENDER_FORMAT is specified in renderopt
+// [lpAdviseSink] -- the advise sink for the object
+// [rgdwConnection]-- where to put the connection IDs for the
+// advisory connections
+// [lpClientSite] -- pointer to the client site for the link
+// [lpStg] -- storage for the link
+// [lplpObj] -- where to put the link object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-94 alexgo added call tracing
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(OleCreateLinkEx)
+STDAPI OleCreateLinkEx
+(
+ IMoniker FAR* lpmkSrc,
+ REFIID iid,
+ DWORD dwFlags,
+ DWORD renderopt,
+ ULONG cFormats,
+ DWORD FAR* rgAdvf,
+ LPFORMATETC rgFormatEtc,
+ IAdviseSink FAR* lpAdviseSink,
+ DWORD FAR* rgdwConnection,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ OLETRACEIN((API_OleCreateLinkEx,
+ PARAMFMT("lpmkSrc= %p, iid= %I, dwFlags= %x, renderopt= %x, cFormats= %x, rgAdvf= %te, rgFormatEtc= %p, lpAdviseSink= %p, rgdwConnection= %p, lpClientSite= %p, lpStg= %p, lplpObj= %p"),
+ lpmkSrc, &iid, dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite, lpStg, lplpObj));
+
+ VDATEHEAP();
+
+ FORMATETC formatEtc;
+ LPFORMATETC lpFormatEtc;
+ BOOL fAlloced = FALSE;
+ HRESULT error;
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleCreateLinkEx ( %p , %p , %lx, %lx,"
+ " %lx , %p , %p , %p, %p , %p , %p , %p )\n", NULL, lpmkSrc, &iid,
+ dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink,
+ rgdwConnection, lpClientSite, lpStg, lplpObj));
+
+ VDATEPTROUT_LABEL( lplpObj, LPVOID, errRtn, error );
+ *lplpObj = NULL;
+
+ VDATEIFACE_LABEL( lpmkSrc, errRtn, error);
+ VDATEIID_LABEL( iid, errRtn, error );
+
+ error = wValidateCreateParams(dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite, lpStg);
+ if (error != NOERROR)
+ goto errRtn;
+
+ if ((error = wValidateFormatEtcEx(renderopt, &cFormats, rgFormatEtc,
+ &formatEtc, &lpFormatEtc, &fAlloced)) == NOERROR)
+ {
+ error = wCreateLinkEx(lpmkSrc, CLSID_NULL, NULL /* lpSrcDataObj */,
+ iid, dwFlags, renderopt, cFormats, rgAdvf, lpFormatEtc,
+ lpAdviseSink, rgdwConnection, lpClientSite, lpStg, lplpObj);
+
+ if (fAlloced)
+ PubMemFree(lpFormatEtc);
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleCreateLinkEx ( %lx ) [ %p ]\n", NULL,
+ error, *lplpObj));
+
+errRtn:
+ OLETRACEOUT((API_OleCreateLinkEx, error));
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateLinkToFile
+//
+// Synopsis: Creates a link object to the file specified in [lpszFileName]
+//
+// Effects:
+//
+// Arguments: [lpszFileName] -- the name of the file
+// [iid] -- interface ID requested
+// [renderopt] -- rendering options
+// [lpFormatEtc] -- format in which to render (if [renderopt]
+// == OLERENDER_FORMAT);
+// [lpClientSite] -- pointer to the client site for the link
+// [lpStg] -- pointer to the storage for the object
+// [lplpObj] -- where to put a pointer to new link object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-94 alexgo added call tracing
+// 28-Oct-93 alexgo 32bit port, fixed memory leak in error
+// case
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleCreateLinkToFile)
+STDAPI OleCreateLinkToFile
+(
+ LPCOLESTR lpszFileName,
+ REFIID iid,
+ DWORD renderopt,
+ LPFORMATETC lpFormatEtc,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ DWORD advf = ADVF_PRIMEFIRST;
+
+ return OleCreateLinkToFileEx(lpszFileName, iid, 0, renderopt,
+ (lpFormatEtc ? 1 : 0), (lpFormatEtc ? &advf : NULL),
+ lpFormatEtc, NULL, NULL, lpClientSite, lpStg, lplpObj);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateLinkToFileEx
+//
+// Synopsis: Creates a link object to the file specified in [lpszFileName]
+//
+// Effects:
+//
+// Arguments: [lpszFileName] -- the name of the file
+// [iid] -- interface ID requested
+// [dwFlags] -- object creation flags
+// [renderopt] -- render options, such as OLERENDER_DRAW
+// [cFormats] -- the number of elements in rgFormatEtc
+// [rgAdvf] -- array of advise flags, if OLRENDER_FORMAT
+// is specified in renderopt
+// [rgFormatEtc] -- array of rendering formats, if
+// OLERENDER_FORMAT is specified in renderopt
+// [lpAdviseSink] -- the advise sink for the object
+// [rgdwConnection]-- where to put the connection IDs for the
+// advisory connections
+// [lpClientSite] -- pointer to the client site for the link
+// [lpStg] -- pointer to the storage for the object
+// [lplpObj] -- where to put a pointer to new link object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-94 alexgo added call tracing
+// 28-Oct-93 alexgo 32bit port, fixed memory leak in error
+// case
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleCreateLinkToFileEx)
+STDAPI OleCreateLinkToFileEx
+(
+ LPCOLESTR lpszFileName,
+ REFIID iid,
+ DWORD dwFlags,
+ DWORD renderopt,
+ ULONG cFormats,
+ DWORD FAR* rgAdvf,
+ LPFORMATETC rgFormatEtc,
+ IAdviseSink FAR* lpAdviseSink,
+ DWORD FAR* rgdwConnection,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ OLETRACEIN((API_OleCreateLinkToFileEx,
+ PARAMFMT("lpszFileName= %ws, iid= %I, dwFlags= %x, renderopt= %x, cFormats= %x, rgAdvf= %te, rgFormatEtc= %p, lpAdviseSink= %p, rgdwConnection= %p, lpClientSite= %p, lpStg= %p, lplpObj= %p"),
+ lpszFileName, &iid, dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite, lpStg, lplpObj));
+
+ VDATEHEAP();
+
+ LPMONIKER lpmkFile = NULL;
+ LPDATAOBJECT lpDataObject = NULL;
+ HRESULT error;
+ BOOL fPackagerMoniker = FALSE;
+ CLSID clsidFile;
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleCreateLinkToFileEx ( \"%s\" , %p , %lx ,"
+ " %lx , %lx , %p , %p , %p, %p , %p , %p , %p )\n", NULL, lpszFileName,
+ &iid, dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink,
+ rgdwConnection, lpClientSite, lpStg, lplpObj));
+
+ VDATEPTROUT_LABEL( lplpObj, LPVOID, safeRtn, error );
+ *lplpObj = NULL;
+
+ VDATEPTRIN_LABEL( (LPVOID)lpszFileName, OLECHAR, logRtn, error );
+ VDATEIID_LABEL( iid, logRtn, error );
+
+ error = wValidateCreateParams(dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite, lpStg);
+ if (error != NOERROR)
+ goto logRtn;
+
+ if (((error = wGetMonikerAndClassFromFile(lpszFileName,
+ TRUE /*fLink*/, &lpmkFile, &fPackagerMoniker, &clsidFile,&lpDataObject))
+ != NOERROR))
+ {
+ goto logRtn;
+ }
+
+ Verify(lpmkFile);
+
+ if (fPackagerMoniker) {
+ // wValidateFormatEtc() will be done in wCreateFromFile()
+
+ Assert(NULL == lpDataObject); // Shouldn't be a BoundDataObject for Packager.
+
+ error = wCreateFromFileEx(lpmkFile,lpDataObject, iid, dwFlags, renderopt,
+ cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection,
+ lpClientSite, lpStg, lplpObj);
+
+ } else {
+ FORMATETC formatEtc;
+ LPFORMATETC lpFormatEtc;
+ BOOL fAlloced = FALSE;
+
+ if ((error = wValidateFormatEtcEx(renderopt, &cFormats, rgFormatEtc,
+ &formatEtc, &lpFormatEtc, &fAlloced)) != NOERROR)
+ {
+ goto ErrRtn;
+ }
+
+ error = wCreateLinkEx(lpmkFile, clsidFile, lpDataObject,
+ iid, dwFlags, renderopt, cFormats, rgAdvf, lpFormatEtc,
+ lpAdviseSink, rgdwConnection, lpClientSite, lpStg, lplpObj);
+
+ if (fAlloced)
+ PubMemFree(lpFormatEtc);
+ }
+
+ErrRtn:
+
+ if (lpmkFile)
+ {
+ lpmkFile->Release();
+ }
+
+ // if the moniker was bound in CreateFromFile, release it now.
+ if (lpDataObject)
+ {
+ lpDataObject->Release();
+ }
+
+ if (error == NOERROR && !lpAdviseSink) {
+ wStuffIconOfFileEx(lpszFileName, TRUE /*fAddLabel*/,
+ renderopt, cFormats, rgFormatEtc, (LPUNKNOWN) *lplpObj);
+ }
+
+logRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleCreateLinkToFileEx ( %lx ) [ %p ]\n",
+ NULL, error, *lplpObj));
+
+safeRtn:
+ OLETRACEOUT((API_OleCreateLinkToFileEx, error));
+
+ return error;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateFromFile
+//
+// Synopsis: Creates an ole object for embedding from a file (for
+// InstertObject->From File type things)
+//
+// Effects:
+//
+// Arguments: [rclsid] -- CLSID to use for creating the object
+// [lpszFileName] -- the filename
+// [iid] -- the requested interface ID
+// [renderopt] -- rendering options
+// [lpFormatEtc] -- rendering format (if needed)
+// [lpClientSite] -- pointer to the object's client site
+// [lpStg] -- pointer to the storage for the object
+// [lplpObj] -- where to put the pointer to the new object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-94 alexgo added call tracing
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(OleCreateFromFile)
+STDAPI OleCreateFromFile
+(
+ REFCLSID rclsid,
+ LPCOLESTR lpszFileName,
+ REFIID iid,
+ DWORD renderopt,
+ LPFORMATETC lpFormatEtc,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ DWORD advf = ADVF_PRIMEFIRST;
+
+ return OleCreateFromFileEx(rclsid, lpszFileName, iid, 0, renderopt,
+ (lpFormatEtc ? 1 : 0), (lpFormatEtc ? &advf : NULL),
+ lpFormatEtc, NULL, NULL, lpClientSite, lpStg, lplpObj);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateFromFileEx
+//
+// Synopsis: Creates an ole object for embedding from a file (for
+// InstertObject->From File type things)
+//
+// Effects:
+//
+// Arguments: [rclsid] -- CLSID to use for creating the object
+// [lpszFileName] -- the filename
+// [iid] -- the requested interface ID
+// [dwFlags] -- object creation flags
+// [renderopt] -- render options, such as OLERENDER_DRAW
+// [cFormats] -- the number of elements in rgFormatEtc
+// [rgAdvf] -- array of advise flags, if OLRENDER_FORMAT
+// is specified in renderopt
+// [rgFormatEtc] -- array of rendering formats, if
+// OLERENDER_FORMAT is specified in renderopt
+// [lpAdviseSink] -- the advise sink for the object
+// [rgdwConnection]-- where to put the connection IDs for the
+// advisory connections
+// [lpClientSite] -- pointer to the object's client site
+// [lpStg] -- pointer to the storage for the object
+// [lplpObj] -- where to put the pointer to the new object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-94 alexgo added call tracing
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(OleCreateFromFileEx)
+STDAPI OleCreateFromFileEx
+(
+ REFCLSID rclsid,
+ LPCOLESTR lpszFileName,
+ REFIID iid,
+ DWORD dwFlags,
+ DWORD renderopt,
+ ULONG cFormats,
+ DWORD FAR* rgAdvf,
+ LPFORMATETC rgFormatEtc,
+ IAdviseSink FAR* lpAdviseSink,
+ DWORD FAR* rgdwConnection,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ OLETRACEIN((API_OleCreateFromFileEx,
+ PARAMFMT("rclsid= %I, lpszFileName= %ws, iid= %I, dwFlags= %x, renderopt= %x, cFormats= %x, rgAdvf= %te, rgFormatEtc= %p, lpAdviseSink= %p, rgdwConnection= %p, lpClientSite= %p, lpStg= %p, lplpObj= %p"),
+ &rclsid, lpszFileName, &iid, dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite, lpStg, lplpObj));
+
+ VDATEHEAP();
+
+ LPMONIKER lpmkFile = NULL;
+ LPDATAOBJECT lpDataObject = NULL;
+ HRESULT error;
+ CLSID clsid;
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleCreateFromFileEx ( %p , \"%s\" , %p ,"
+ " %lx , %lx , %lx , %p , %p , %p , %p , %p , %p , %p )\n", NULL,
+ &rclsid, lpszFileName, &iid, dwFlags, renderopt, cFormats, rgAdvf,
+ rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite, lpStg,
+ lplpObj));
+
+ VDATEPTROUT_LABEL( lplpObj, LPVOID, safeRtn, error );
+ *lplpObj = NULL;
+
+ VDATEPTRIN_LABEL( (LPVOID)lpszFileName, char, errRtn, error );
+ VDATEIID_LABEL( iid, errRtn, error );
+
+ error = wValidateCreateParams(dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite, lpStg);
+ if (error != NOERROR)
+ goto errRtn;
+
+ if (((error = wGetMonikerAndClassFromFile(lpszFileName,
+ FALSE /*fLink*/, &lpmkFile, NULL /*lpfPackagerMoniker*/,
+ &clsid,&lpDataObject)) != NOERROR))
+ {
+ goto errRtn;
+ }
+
+ Verify(lpmkFile);
+
+ // wValidateFormatEtc() will be done in wCreateFromFile()
+ error = wCreateFromFileEx(lpmkFile,lpDataObject, iid, dwFlags, renderopt, cFormats,
+ rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite,
+ lpStg, lplpObj);
+
+ if (lpDataObject)
+ {
+ lpDataObject->Release();
+ }
+
+ if (lpmkFile)
+ {
+ lpmkFile->Release();
+ }
+
+
+ if (error == NOERROR && !lpAdviseSink) {
+ wStuffIconOfFileEx(lpszFileName, FALSE /*fAddLabel*/,
+ renderopt, cFormats, rgFormatEtc, (LPUNKNOWN) *lplpObj);
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleCreateFromFileEx ( %lx ) [ %p ]\n",
+ NULL, error, *lplpObj));
+
+safeRtn:
+
+ OLETRACEOUT((API_OleCreateFromFileEx, error));
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleDoAutoConvert
+//
+// Synopsis: Converts the storage to use the clsid given in
+// [pClsidNew]. Private ole streams are updated with the new
+// info
+//
+// Effects:
+//
+// Arguments: [pStg] -- storage to modify
+// [pClsidNew] -- pointer to the new class ID
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes: REVIEW32: this function should be rewritten to use
+// the new internal API for writing to ole-private streams
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleDoAutoConvert)
+STDAPI OleDoAutoConvert(LPSTORAGE pStg, LPCLSID pClsidNew)
+{
+ OLETRACEIN((API_OleDoAutoConvert, PARAMFMT("pStg= %p, pClsidNew= %I"),
+ pStg, pClsidNew));
+
+ VDATEHEAP();
+
+ HRESULT error;
+ CLSID clsidOld;
+ CLIPFORMAT cfOld;
+ LPOLESTR lpszOld = NULL;
+ LPOLESTR lpszNew = NULL;
+
+ if ((error = ReadClassStg(pStg, &clsidOld)) != NOERROR) {
+ clsidOld = CLSID_NULL;
+ goto errRtn;
+ }
+
+ if ((error = OleGetAutoConvert(clsidOld, pClsidNew)) != NOERROR)
+ goto errRtn;
+
+ // read old fmt/old user type; sets out params to NULL on error
+ error = ReadFmtUserTypeStg(pStg, &cfOld, &lpszOld);
+ Assert(error == NOERROR || (cfOld == NULL && lpszOld == NULL));
+
+ // get new user type name; if error, set to NULL string
+ if ((error = OleRegGetUserType(*pClsidNew, USERCLASSTYPE_FULL,
+ &lpszNew)) != NOERROR)
+ lpszNew = NULL;
+
+ // write class stg
+ if ((error = WriteClassStg(pStg, *pClsidNew)) != NOERROR)
+ goto errRtn;
+
+ // write old fmt/new user type;
+ if ((error = WriteFmtUserTypeStg(pStg, cfOld, lpszNew)) != NOERROR)
+ goto errRewriteInfo;
+
+ // set convert bit
+ if ((error = SetConvertStg(pStg, TRUE)) != NOERROR)
+ goto errRewriteInfo;
+
+ goto okRtn;
+
+errRewriteInfo:
+ (void)WriteClassStg(pStg, clsidOld);
+ (void)WriteFmtUserTypeStg(pStg, cfOld, lpszOld);
+
+errRtn:
+ *pClsidNew = clsidOld;
+
+okRtn:
+ PubMemFree(lpszOld);
+ PubMemFree(lpszNew);
+
+ OLETRACEOUT((API_OleDoAutoConvert, error));
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleLoad
+//
+// Synopsis: Loads an object from the given storage
+//
+// Effects:
+//
+// Arguments: [lpStg] -- the storage to load from
+// [iid] -- the requested interface ID
+// [lpClientSite] -- client site for the object
+// [lplpObj] -- where to put the pointer to the
+// new object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-94 alexgo added call tracing
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(OleLoad)
+STDAPI OleLoad
+(
+ IStorage FAR* lpStg,
+ REFIID iid,
+ IOleClientSite FAR* lpClientSite,
+ void FAR* FAR* lplpObj
+)
+{
+ OLETRACEIN((API_OleLoad, PARAMFMT("lpStg= %p, iid= %I, lpClientSite= %p, lplpObj= %p"),
+ lpStg, &iid, lpClientSite, lplpObj));
+
+ VDATEHEAP();
+
+ HRESULT error;
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleLoad ( %p , %p , %p , %p )\n",
+ NULL, lpStg, &iid, lpClientSite, lplpObj));
+
+ if ((error = OleLoadWithoutBinding(lpStg, iid, lpClientSite, lplpObj))
+ == NOERROR) {
+ // The caller specify that he want a disconnected object by
+ // passing NULL for pClientSite
+ if (lpClientSite != NULL)
+ wBindIfRunning((LPUNKNOWN) *lplpObj);
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleLoad ( %lx ) [ %p ]\n", NULL, error,
+ (error == NOERROR ? *lplpObj : NULL)));
+
+ OLETRACEOUT((API_OleLoad, error));
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleLoadWithoutBinding
+//
+// Synopsis: Internal function to load/create an object from a storage
+// called by OleLoad, etc.
+//
+// Effects:
+//
+// Arguments: [lpStg] -- storage to load from
+// [iid] -- requested interface ID
+// [lpClientSite] -- pointer to the client site
+// [lplpObj] -- where to put the pointer to the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes: REVIEW32: this function is only used in a few, known
+// places. we can maybe get rid of the VDATEPTR's.
+//
+//--------------------------------------------------------------------------
+
+
+INTERNAL OleLoadWithoutBinding
+(
+ IStorage FAR* lpStg,
+ REFIID iid,
+ IOleClientSite FAR* lpClientSite,
+ void FAR* FAR* lplpObj
+)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ CLSID clsid;
+
+ VDATEPTROUT( lplpObj, LPVOID );
+ *lplpObj = NULL;
+ VDATEIID( iid );
+ VDATEIFACE( lpStg );
+
+ if (lpClientSite)
+ VDATEIFACE( lpClientSite );
+
+ error = OleDoAutoConvert(lpStg, &clsid);
+
+ // error only used when clsid could not be read (when CLSID_NULL)
+ if (IsEqualCLSID(clsid, CLSID_NULL))
+ return error;
+
+ return wCreateObject (clsid, iid, lpClientSite, lpStg, STG_LOAD,
+ lplpObj);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateStaticFromData
+//
+// Synopsis: Creates a static ole object from the data in [lpSrcDataObject]
+// If [lpFormatEtcIn] is NULL, then the best possible
+// presentation is extracted.
+//
+// Effects:
+//
+// Arguments: [lpSrcDataObj] -- pointer to the data object
+// [iid] -- requested interface ID for the new object
+// [renderopt] -- redering options
+// [lpClientSite] -- pointer to the client site
+// [lpStg] -- pointer to the storage for the object
+// [lplpObj] -- where to put the pointer to the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-94 alexgo added call tracing
+// 08-Jun-94 davepl Added EMF support
+// 28-Oct-93 alexgo 32bit port
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleCreateStaticFromData)
+STDAPI OleCreateStaticFromData(
+ IDataObject FAR* lpSrcDataObj,
+ REFIID iid,
+ DWORD renderopt,
+ LPFORMATETC lpFormatEtcIn,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ OLETRACEIN((API_OleCreateStaticFromData,
+ PARAMFMT("lpSrcDataObj= %p, iid= %I, renderopt= %x, lpFormatEtcIn= %te, lpClientSite= %p, lpStg= %p, lplpObj= %p"),
+ lpSrcDataObj, &iid, renderopt, lpFormatEtcIn, lpClientSite, lpStg, lplpObj));
+
+ VDATEHEAP();
+
+ IOleObject FAR* lpOleObj = NULL;
+ IOleCache FAR* lpOleCache = NULL;
+ HRESULT error;
+ FORMATETC foretc;
+ FORMATETC foretcCache;
+ STGMEDIUM stgmed;
+ CLSID clsid;
+ BOOL fReleaseStgMed = TRUE;
+ LPOLESTR lpszUserType = NULL;
+
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleCreateStaticFromData ( %p , %p , %lx ,"
+ " %p , %p , %p , %p , %p )\n", NULL, lpSrcDataObj, &iid, renderopt,
+ lpFormatEtcIn, lpClientSite, lpStg, lplpObj));
+
+ VDATEPTROUT_LABEL(lplpObj, LPVOID, safeRtn, error);
+ *lplpObj = NULL;
+ VDATEIFACE_LABEL( lpSrcDataObj, logRtn, error );
+ VDATEIID_LABEL(iid, logRtn, error);
+
+ //VDATEPTRIN rejects NULL
+ if ( lpFormatEtcIn )
+ VDATEPTRIN_LABEL( lpFormatEtcIn, FORMATETC, logRtn, error );
+ VDATEIFACE_LABEL(lpStg, logRtn, error);
+ if (lpClientSite)
+ VDATEIFACE_LABEL(lpClientSite, logRtn, error);
+
+ if (renderopt == OLERENDER_NONE || renderopt == OLERENDER_ASIS)
+ {
+ error = E_INVALIDARG;
+ goto logRtn;
+ }
+
+ if ((error = wValidateFormatEtc (renderopt, lpFormatEtcIn, &foretc))
+ != NOERROR)
+ {
+ goto logRtn;
+ }
+
+ if (renderopt == OLERENDER_DRAW)
+ {
+ if (!UtQueryPictFormat(lpSrcDataObj, &foretc))
+ {
+ error = DV_E_CLIPFORMAT;
+ goto logRtn;
+ }
+ }
+
+ // Set the proper CLSID, or return error if that isn't possible
+
+ if (foretc.cfFormat == CF_METAFILEPICT)
+ {
+ clsid = CLSID_StaticMetafile;
+ }
+ else if (foretc.cfFormat == CF_BITMAP || foretc.cfFormat == CF_DIB)
+ {
+ clsid = CLSID_StaticDib;
+ }
+ else if (foretc.cfFormat == CF_ENHMETAFILE)
+ {
+ clsid = CLSID_Picture_EnhMetafile;
+ }
+ else
+ {
+ error = DV_E_CLIPFORMAT;
+ goto logRtn;
+ }
+
+ error = lpSrcDataObj->GetData(&foretc, &stgmed);
+ if (NOERROR != error)
+ {
+ // We should support the case where the caller wants one of
+ // CF_BITMAP and CF_DIB, and the object supports the other
+ // one those 2 formats. In this case we should do the proper
+ // conversion. Finally the cache that is going to be created
+ // would be a DIB cache.
+
+ AssertOutStgmedium(error, &stgmed);
+
+ if (foretc.cfFormat == CF_DIB)
+ {
+ foretc.cfFormat = CF_BITMAP;
+ foretc.tymed = TYMED_GDI;
+ }
+ else if (foretc.cfFormat == CF_BITMAP)
+ {
+ foretc.cfFormat = CF_DIB;
+ foretc.tymed = TYMED_HGLOBAL;
+ }
+ else
+ {
+ goto logRtn;
+ }
+
+ error = lpSrcDataObj->GetData(&foretc, &stgmed);
+ if (NOERROR != error)
+ {
+ AssertOutStgmedium(error, &stgmed);
+ goto logRtn;
+ }
+ }
+
+ AssertOutStgmedium(error, &stgmed);
+
+ foretcCache = foretc;
+ foretcCache.dwAspect = foretc.dwAspect = DVASPECT_CONTENT;
+ foretcCache.ptd = NULL;
+
+ // Even when the caller asks for bitmap cache we create the DIB cache.
+
+ BITMAP_TO_DIB(foretcCache);
+
+ error = wCreateObject (clsid, IID_IOleObject, lpClientSite,
+ lpStg, STG_INITNEW, (LPLPVOID) &lpOleObj);
+
+ if (NOERROR != error)
+ {
+ goto errRtn;
+ }
+
+ if (lpOleObj->QueryInterface(IID_IOleCache, (LPLPVOID) &lpOleCache)
+ != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ error = lpOleCache->Cache (&foretcCache, ADVF_PRIMEFIRST,
+ NULL /*pdwConnection*/);
+
+ if (FAILED(error))
+ {
+ goto errRtn;
+ }
+
+ //REVIEW32: err, are we sure this is a good idea???
+ //clearing out the error, that is
+
+ error = NOERROR;
+
+ // take ownership of the data
+ foretc.ptd = NULL;
+ if ((error = lpOleCache->SetData (&foretc, &stgmed,
+ TRUE)) != NOERROR)
+ goto errRtn;
+
+ // Write format and user type
+ error = lpOleObj->GetUserType(USERCLASSTYPE_FULL, &lpszUserType);
+ AssertOutPtrParam(error, lpszUserType);
+ WriteFmtUserTypeStg(lpStg, foretcCache.cfFormat, lpszUserType);
+ if (lpszUserType)
+ PubMemFree(lpszUserType);
+
+ fReleaseStgMed = FALSE;
+
+ error = lpOleObj->QueryInterface (iid, lplpObj);
+
+errRtn:
+ if (fReleaseStgMed)
+ ReleaseStgMedium(&stgmed);
+
+ if (lpOleCache)
+ lpOleCache->Release();
+
+ if (error != NOERROR && *lplpObj) {
+ ((IUnknown FAR*) *lplpObj)->Release();
+ *lplpObj = NULL;
+ }
+
+ if (lpOleObj)
+ lpOleObj->Release();
+
+logRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleCreateStaticFromData ( %lx ) [ %p ]\n",
+ NULL, error, *lplpObj));
+
+safeRtn:
+ OLETRACEOUT((API_OleCreateStaticFromData, error));
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleQueryCreateFromData
+//
+// Synopsis: Finds out what we can create from a data object (if anything)
+//
+// Effects:
+//
+// Arguments: [lpSrcDataObj] -- pointer to the data object of interest
+//
+// Requires:
+//
+// Returns: NOERROR -- an OLE object can be created
+// QUERY_CREATE_STATIC -- a static object can be created
+// S_FALSE -- nothing can be created
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(OleQueryCreateFromData)
+STDAPI OleQueryCreateFromData (LPDATAOBJECT lpSrcDataObj)
+{
+ OLETRACEIN((API_OleQueryCreateFromData, PARAMFMT("lpSrcDataObj= %p"), lpSrcDataObj));
+
+ VDATEHEAP();
+ VDATEIFACE( lpSrcDataObj );
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IDataObject,(IUnknown **)&lpSrcDataObj);
+
+ CLIPFORMAT cfFormat;
+ WORD wStatus = wQueryEmbedFormats(lpSrcDataObj, &cfFormat);
+ HRESULT hr;
+
+ if (wStatus & QUERY_CREATE_OLE)
+ // OLE object can be created
+ hr = NOERROR;
+ else if (wStatus & QUERY_CREATE_STATIC)
+ // static object can be created
+ hr = ResultFromScode(OLE_S_STATIC);
+ else // no object can be created
+ hr = ResultFromScode(S_FALSE);
+
+ OLETRACEOUT((API_OleQueryCreateFromData, hr));
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wQueryEmbedFormats
+//
+// Synopsis: Enumerates the formats of the object and looks for
+// ones that let us create either an embeded or static object
+//
+// Effects:
+//
+// Arguments: [lpSrcDataObj] -- pointer to the data object
+// [lpcfFormat] -- place to put the clipboard format
+// of the object
+// Returns: WORD -- bit flag of QUERY_CREATE_NONE, QUERY_CREATE_STATIC
+// and QUERY_CREATE_OLE
+//
+// History: dd-mmm-yy Author Comment
+// 28-Oct-93 alexgo 32bit port
+// 08-Jun-94 davepl Optimized by unwinding while() loop
+// 22-Aug-94 alexgo added MFC hack
+//
+//--------------------------------------------------------------------------
+
+static const unsigned int MAX_ENUM_STEP = 20;
+
+INTERNAL_(WORD) wQueryEmbedFormats
+(
+ LPDATAOBJECT lpSrcDataObj,
+ CLIPFORMAT FAR* lpcfFormat
+)
+{
+ VDATEHEAP();
+
+ // This adjusts the number of formats requested per enumeration
+ // step. If we are running in the WOW box, we should only ask
+ // for one at a time since it is unknown how well old code will
+ // support bulk enumerations.
+
+ ULONG ulEnumSize = IsWOWThread() ? 1 : MAX_ENUM_STEP;
+
+ FORMATETC fetcarray[MAX_ENUM_STEP];
+ IEnumFORMATETC FAR* penm;
+ ULONG ulNumFetched;
+ HRESULT error;
+ WORD wStatus = QUERY_CREATE_NONE;
+ // no object can be created
+ BOOL fDone = FALSE;
+
+ *lpcfFormat = NULL;
+
+ // Grab the enumerator. If this fails, just return
+ // QUERY_CREATE_NONE
+
+ error = wGetEnumFormatEtc(lpSrcDataObj, DATADIR_GET, &penm);
+ if (error != NOERROR)
+ {
+ return QUERY_CREATE_NONE;
+ }
+
+ // Enumerate over the formats available in chunks for ulEnumSize. For
+ // each format we were able to grab, check to see if the clipformat
+ // indicates that we have a creation candidate (static or otherwise),
+ // and set bits in the bitmask as appropriate
+
+ while (!fDone && (SUCCEEDED(penm->Next(ulEnumSize, fetcarray, &ulNumFetched))))
+ {
+ // We will normally get at least one, unless there are 0,
+ // ulEnumSize, 2*ulEnumSize, and so on...
+
+ if (ulNumFetched == 0)
+ break;
+
+ for (ULONG c=0; c<ulNumFetched; c++)
+ {
+ // We care not about the target device
+
+ if (NULL != fetcarray[c].ptd)
+ {
+ PubMemFree(fetcarray[c].ptd);
+ }
+
+ CLIPFORMAT cf = fetcarray[c].cfFormat;
+
+ // In these cases it is an internal
+ // format which is a candidate for
+ // OLE creation directly.
+
+ if (cf == g_cfEmbedSource ||
+ cf == g_cfEmbeddedObject ||
+ cf == g_cfFileName ||
+ cf == g_cfFileNameW)
+ {
+ wStatus |= QUERY_CREATE_OLE;
+ *lpcfFormat = cf;
+ fDone = TRUE;
+ break;
+ }
+ // These formats indicate it is a
+ // candidate for static creation.
+
+ else if (cf == CF_METAFILEPICT ||
+ cf == CF_DIB ||
+ cf == CF_BITMAP ||
+ cf == CF_ENHMETAFILE)
+ {
+ wStatus = QUERY_CREATE_STATIC;
+ *lpcfFormat = cf;
+
+ }
+ } // end for
+
+ if (fDone)
+ {
+ // Starting at the _next_ formatetc, free up
+ // any remaining target devices among the
+ // fetcs we got in the enumeration step.
+
+ for (++c; c<ulNumFetched; c++)
+ {
+ if(fetcarray[c].ptd)
+ {
+ PubMemFree(fetcarray[c].ptd);
+ }
+ }
+ }
+
+ } // end while
+
+
+
+ if (!(wStatus & QUERY_CREATE_OLE))
+ {
+ // MFC HACK ALERT!! MFC3.0 used to re-implement
+ // OleQueryCreateFromData themselves because they did not
+ // want to make the QI RPC below. Since they do a great
+ // many of these calls, making the RPC can be expensive
+ // and destabilising for them (as this hack is being put
+ // in just weeks before final release of Windows NT 3.5).
+ //
+ // Note that this changes the behaviour of clipboard from
+ // 16bit. You will no longer know that you can paste objects
+ // that only support IPersistStorage but offer no data in
+ // in their IDataOjbect implementation.
+
+ CClipDataObject ClipDataObject; // just allocate one of these
+ // on the stack. We won't
+ // do any real work with
+ // this except look at the
+ // vtable.
+ IPersistStorage FAR* lpPS;
+
+
+ // MFC HACK (continued): If we are working with a clipboard
+ // data object, then we do not want to make the QI call
+ // below. We determine if the given data object is a
+ // clipboard data object by comparing vtable addresses.
+
+ // REVIEW: this will potentially break if we make all objects
+ // use the same IUnknown implementation
+
+ if( (*(DWORD *)lpSrcDataObj) !=
+ (*(DWORD *)((IDataObject *)&ClipDataObject)) )
+ {
+
+ if (lpSrcDataObj->QueryInterface(IID_IPersistStorage,
+ (LPLPVOID)&lpPS) == NOERROR)
+ {
+ lpPS->Release();
+ wStatus |= QUERY_CREATE_OLE;
+ // OLE object can be created
+ }
+ }
+ }
+
+ penm->Release();
+ return wStatus;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleQueryLinkFromData
+//
+// Synopsis: Calls wQueryLinkFormats to determine if a link could be
+// created from this data object.
+//
+// Arguments: [lpSrcDataObj] -- the data object
+//
+// Returns: NOERROR, if a link can be created, S_FALSE otherwise
+//
+// History: dd-mmm-yy Author Comment
+// 28-Oct-93 alexgo 32bit port
+//
+//--------------------------------------------------------------------------
+
+STDAPI OleQueryLinkFromData (LPDATAOBJECT lpSrcDataObj)
+{
+ OLETRACEIN((API_OleQueryLinkFromData, PARAMFMT("lpSrcDataObj= %p"),
+ lpSrcDataObj));
+
+ VDATEHEAP();
+ VDATEIFACE( lpSrcDataObj );
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IDataObject,(IUnknown **)&lpSrcDataObj);
+
+ HRESULT hr = NOERROR;
+
+ if(wQueryLinkFormats(lpSrcDataObj) == NULL)
+ {
+ hr = ResultFromScode(S_FALSE);
+ }
+
+ OLETRACEOUT((API_OleQueryLinkFromData, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wQueryLinkFormats
+//
+// Synopsis: Enumerates the formats of a data object to see if
+// a link object could be created from one of them
+//
+// Arguments: [lpSrcDataObj] -- pointer to the data object
+//
+// Returns: CLIPFORMAT of the data in the object that would enable
+// link object creation.
+//
+// History: dd-mmm-yy Author Comment
+// 28-Oct-93 alexgo 32bit port
+// 14-Jun-94 davepl Added bulk enumeration for non-Wow runs
+//
+//--------------------------------------------------------------------------
+
+
+INTERNAL_(CLIPFORMAT) wQueryLinkFormats(LPDATAOBJECT lpSrcDataObj)
+{
+ VDATEHEAP();
+
+ // This adjusts the number of formats requested per enumeration
+ // step. If we are running in the WOW box, we should only ask
+ // for one at a time since it is unknown how well old code will
+ // support bulk enumerations.
+
+ ULONG ulEnumSize = IsWOWThread() ? 1 : MAX_ENUM_STEP;
+
+ FORMATETC fetcarray[MAX_ENUM_STEP];
+ IEnumFORMATETC FAR* penm;
+ ULONG ulNumFetched;
+ HRESULT error;
+ BOOL fDone = FALSE;
+ CLIPFORMAT cf = 0;
+
+
+ // Grab the enumerator. If this fails, just return
+ // QUERY_CREATE_NONE
+
+ error = wGetEnumFormatEtc(lpSrcDataObj, DATADIR_GET, &penm);
+ if (error != NOERROR)
+ {
+ return (CLIPFORMAT) 0;
+ }
+
+ // Enumerate over the formats available in chunks for ulEnumSize. For
+ // each format we were able to grab, check to see if the clipformat
+ // indicates that we have a creation candidate (static or otherwise),
+ // and set bits in the bitmask as appropriate
+
+ while (!fDone && (SUCCEEDED(penm->Next(ulEnumSize, fetcarray, &ulNumFetched))))
+ {
+ // We will normally get at least one, unless there are 0,
+ // ulEnumSize, 2*ulEnumSize, and so on...
+
+ if (ulNumFetched == 0)
+ break;
+
+ for (ULONG c=0; c<ulNumFetched; c++)
+ {
+ // We care not about the target device
+
+ if (NULL != fetcarray[c].ptd)
+ {
+ PubMemFree(fetcarray[c].ptd);
+ }
+
+ CLIPFORMAT cfTemp = fetcarray[c].cfFormat;
+
+ // In these cases it is an internal
+ // format which is a candidate for
+ // OLE creation directly.
+
+ if (cfTemp == g_cfLinkSource ||
+ cfTemp == g_cfFileName ||
+ cfTemp == g_cfFileNameW)
+ {
+ cf = cfTemp;
+ fDone = TRUE;
+ break;
+ }
+
+ } // end for
+
+ if (fDone)
+ {
+ // Starting at the _next_ formatetc, free up
+ // any remaining target devices among the
+ // fetcs we got in the enumeration step.
+
+ for (++c; c<ulNumFetched; c++)
+ {
+ if(fetcarray[c].ptd)
+ {
+ PubMemFree(fetcarray[c].ptd);
+ }
+ }
+ } // end if
+
+ } // end while
+
+
+ penm->Release();
+ return cf;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wClearRelativeMoniker
+//
+// Synopsis: Replaces an old relative moniker with the absolute moniker
+// Internal function
+//
+// Effects:
+//
+// Arguments: [pInitObj] -- the original object
+// [pNewObj] -- the object to which to set the new
+// absolute moniker
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(wClearRelativeMoniker)
+INTERNAL_(void) wClearRelativeMoniker
+ (LPUNKNOWN pInitObj,
+ LPUNKNOWN pNewObj)
+{
+ VDATEHEAP();
+
+ LPOLELINK pOleLink = NULL;
+ LPMONIKER pmkAbsolute = NULL;
+ CLSID clsidLink = CLSID_NULL;
+ LPOLEOBJECT pOleObj=NULL;
+
+ if (NOERROR==pInitObj->QueryInterface (IID_IOleLink,
+ (LPLPVOID) &pOleLink))
+ {
+ // Get absolute moniker ...
+ pOleLink->GetSourceMoniker (&pmkAbsolute);
+ Assert(pmkAbsolute == NULL || IsValidInterface(pmkAbsolute));
+ if (NOERROR==pInitObj->QueryInterface (IID_IOleObject,
+ (LPLPVOID) &pOleObj))
+ {
+ // .. and its class
+ pOleObj->GetUserClassID (&clsidLink);
+ pOleObj->Release();
+ pOleObj = NULL;
+ }
+ pOleLink->Release();
+ pOleLink = NULL;
+ }
+ if (pmkAbsolute &&
+ NOERROR==pNewObj->QueryInterface (IID_IOleLink,
+ (LPLPVOID) &pOleLink))
+ {
+ // Restore the absolute moniker. This will effectively
+ // overwrite the old relative moniker.
+ // This is important because when copying and pasting a link
+ // object between documents, the relative moniker is never
+ // correct. Sometimes, though, it might happen to bind
+ // to a different object, which is confusing to say the least.
+ pOleLink->SetSourceMoniker (pmkAbsolute, clsidLink);
+ }
+ if (pOleLink)
+ pOleLink->Release();
+ if (pOleObj)
+ pOleObj->Release();
+ if (pmkAbsolute)
+ pmkAbsolute->Release();
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCreateFromDataEx
+//
+// Synopsis: This function does the real work of creating from data.
+// Basically, the data is GetData'ed from the data object,
+// copied into a storage, and then loaded
+//
+// Effects:
+//
+// Arguments: [lpSrcDataObj] -- pointer to the data object
+// [iid] -- requested interface
+// [dwFlags] -- object creation flags
+// [renderopt] -- render options, such as OLERENDER_DRAW
+// [cFormats] -- the number of elements in rgFormatEtc
+// [rgAdvf] -- array of advise flags, if OLRENDER_FORMAT
+// is specified in renderopt
+// [rgFormatEtc] -- array of rendering formats, if
+// OLERENDER_FORMAT is specified in renderopt
+// [lpAdviseSink] -- the advise sink for the object
+// [rgdwConnection]-- where to put the connection IDs for the
+// advisory connections
+// [lpClientSite] -- pointer to the client site
+// [lpStg] -- pointer to the storage for the object
+// [lplpObj] -- where to put the pointer to the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 28-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(wCreateFromDataEx)
+INTERNAL wCreateFromDataEx
+(
+ IDataObject FAR* lpSrcDataObj,
+ REFIID iid,
+ DWORD dwFlags,
+ DWORD renderopt,
+ ULONG cFormats,
+ DWORD FAR* rgAdvf,
+ LPFORMATETC rgFormatEtc,
+ IAdviseSink FAR* lpAdviseSink,
+ DWORD FAR* rgdwConnection,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ VDATEHEAP();
+
+ #define OLE_TEMP_STG "\1OleTempStg"
+
+ HRESULT error = NOERROR;
+ IPersistStorage FAR* lpPS = NULL;
+ FORMATETC formatEtc;
+ LPFORMATETC lpFormatEtc;
+ BOOL fAlloced = FALSE;
+ FORMATETC foretcTmp;
+ STGMEDIUM medTmp;
+
+ if ((error = wValidateFormatEtcEx(renderopt, &cFormats, rgFormatEtc,
+ &formatEtc, &lpFormatEtc, &fAlloced)) != NOERROR)
+ {
+ return error;
+ }
+
+ *lplpObj = NULL;
+
+ INIT_FORETC(foretcTmp);
+ medTmp.pUnkForRelease = NULL;
+
+
+ // try to get "EmbeddedObject" data
+
+ LPSTORAGE lpstgSrc = NULL;
+
+ foretcTmp.cfFormat = g_cfEmbeddedObject;
+ foretcTmp.tymed = TYMED_ISTORAGE;
+
+ if (lpSrcDataObj->QueryGetData(&foretcTmp) != NOERROR)
+ goto Next;
+
+ if ((error = StgCreateDocfile (NULL,
+ STGM_SALL|STGM_CREATE|STGM_DELETEONRELEASE,
+ NULL, &lpstgSrc)) != NOERROR)
+ goto errRtn;
+
+ medTmp.tymed = TYMED_ISTORAGE;
+ medTmp.pstg = lpstgSrc;
+
+ if ((error = lpSrcDataObj->GetDataHere(&foretcTmp, &medTmp))
+ == NOERROR)
+ {
+ // lpSrcDataObj passed to this api is a wrapper object
+ // (which offers g_cfEmbeddedObject) for the original
+ // embedded object. Now we got the original embedded object
+ // data into medTmp.pstg.
+
+ // copy the source data into lpStg.
+ if ((error = lpstgSrc->CopyTo (0, NULL, NULL, lpStg))
+ != NOERROR)
+ goto errEmbeddedObject;
+
+ // By doing the following we will be getting a data object
+ // pointer to original embedded object, which we can use to
+ // initialize the cache of the object that we are going to
+ // create. We can not use the lpSrcDataObj passed to this api,
+ // 'cause the presentation data that it may give through the
+ // GetData call may be the one that it generated for the
+ // object. (ex: the container can create an object with
+ // olerender_none an then draw it's own representaion
+ // (icon, etc) for the object.
+
+ LPDATAOBJECT lpInitDataObj = NULL;
+
+ // We pass a NULL client site so we know wClearRelativeMoniker
+ // will be able to get the absolute moniker, not the relative.
+ if ((error = OleLoadWithoutBinding (lpstgSrc, IID_IDataObject,
+ /*lpClientSite*/NULL, (LPLPVOID) &lpInitDataObj))
+ != NOERROR)
+ goto errEmbeddedObject;
+
+ if (renderopt != OLERENDER_ASIS )
+ UtDoStreamOperation(lpStg, /* pstgSrc */
+ NULL, /* pstgDst */
+ OPCODE_REMOVE, /* operation to performed */
+ STREAMTYPE_CACHE);
+ /* stream to be operated upon */
+
+ error = wLoadAndInitObjectEx(lpInitDataObj, iid, renderopt,
+ cFormats, rgAdvf, lpFormatEtc, lpAdviseSink, rgdwConnection,
+ lpClientSite, lpStg, lplpObj);
+
+ if (NOERROR==error)
+ wClearRelativeMoniker (lpInitDataObj,
+ (LPUNKNOWN)*lplpObj);
+
+ if (lpInitDataObj)
+ lpInitDataObj->Release();
+
+ // HACK ALERT!! If wLoadAndInitObject failed, it may have been
+ // because the little trick above with OleLoadWithoutBinding doesn't
+ // work with all objects. Some OLE1 objects (Clipart Gallery in
+ // particular) don't like offer presentions without being edited.
+ //
+ // So if there was an error, we'll just try again with the *real*
+ // data object passed into us. Needless to say, it would be much
+ // nicer to do this in the first place, but that breaks the old
+ // behavior.
+
+ if( error != NOERROR )
+ {
+ error = wLoadAndInitObjectEx( lpSrcDataObj, iid, renderopt,
+ cFormats, rgAdvf, lpFormatEtc, lpAdviseSink, rgdwConnection,
+ lpClientSite, lpStg, lplpObj);
+ }
+
+ }
+
+errEmbeddedObject:
+ if (lpstgSrc)
+ lpstgSrc->Release();
+
+ goto errRtn;
+
+Next:
+
+ // try to get "EmbedSource" data
+
+ foretcTmp.cfFormat = g_cfEmbedSource;
+ foretcTmp.tymed = TYMED_ISTORAGE;
+
+ medTmp.tymed = TYMED_ISTORAGE;
+ medTmp.pstg = lpStg;
+
+ if ((error = lpSrcDataObj->GetDataHere(&foretcTmp, &medTmp))
+ == NOERROR)
+ {
+ error = wLoadAndInitObjectEx(lpSrcDataObj, iid, renderopt,
+ cFormats, rgAdvf, lpFormatEtc, lpAdviseSink, rgdwConnection,
+ lpClientSite, lpStg, lplpObj);
+ goto errRtn;
+ }
+
+ // If we have come here, and if the object doesn't support
+ // IPersistStorage, then we will fail.
+
+ if ((error = wSaveObjectWithoutCommit(lpSrcDataObj, lpStg, FALSE))
+ != NOERROR)
+ goto errRtn;;
+
+ if (renderopt != OLERENDER_ASIS )
+ UtDoStreamOperation(lpStg, /* pstgSrc */
+ NULL, /* pstgDst */
+ OPCODE_REMOVE,
+ /* operation to performed */
+ STREAMTYPE_CACHE);
+ /* stream to be operated upon */
+
+ error = wLoadAndInitObjectEx(lpSrcDataObj, iid, renderopt,
+ cFormats, rgAdvf, lpFormatEtc, lpAdviseSink, rgdwConnection,
+ lpClientSite, lpStg, lplpObj);
+
+errRtn:
+ if (fAlloced)
+ PubMemFree(lpFormatEtc);
+
+ return error;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCreateLinkEx
+//
+// Synopsis: Creates a link by binding the moniker (if necessary),
+// doing a GetData into a storage, and then loading the
+// object from the storage.
+//
+// Effects:
+//
+// Arguments: [lpmkSrc] -- moniker to the link source
+// [rclsid] -- clsid of the link source
+// [lpSrcDataObj] -- pointer to the source data object
+// (may be NULL)
+// [iid] -- requested interface ID
+// [dwFlags] -- object creation flags
+// [renderopt] -- render options, such as OLERENDER_DRAW
+// [cFormats] -- the number of elements in rgFormatEtc
+// [rgAdvf] -- array of advise flags, if OLRENDER_FORMAT
+// is specified in renderopt
+// [rgFormatEtc] -- array of rendering formats, if
+// OLERENDER_FORMAT is specified in renderopt
+// [lpAdviseSink] -- the advise sink for the object
+// [rgdwConnection]-- where to put the connection IDs for the
+// advisory connections
+// [lpClientSite] -- pointer to the client site
+// [lpStg] -- storage for the link object
+// [lplpObj] -- where to put the pointer to the new
+// link object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(wCreateLinkEx)
+INTERNAL wCreateLinkEx
+(
+ IMoniker FAR* lpmkSrc,
+ REFCLSID rclsid,
+ IDataObject FAR* lpSrcDataObj,
+ REFIID iid,
+ DWORD dwFlags,
+ DWORD renderopt,
+ ULONG cFormats,
+ DWORD FAR* rgAdvf,
+ LPFORMATETC rgFormatEtc,
+ IAdviseSink FAR* lpAdviseSink,
+ DWORD FAR* rgdwConnection,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ VDATEHEAP();
+
+ IPersistStorage FAR * lpPS = NULL;
+ IOleLink FAR* lpLink = NULL;
+ IDataObject FAR* lpBoundDataObj = NULL;
+ HRESULT error;
+ CLSID clsidLast = rclsid;
+ BOOL fNeedsUpdate = FALSE;
+
+ if (!lpSrcDataObj && ((renderopt != OLERENDER_NONE)
+ || (IsEqualCLSID(rclsid,CLSID_NULL))
+ || wQueryUseCustomLink(rclsid))) {
+
+ // if renderopt is not OLERENDER_NONE, then we must have
+ // a data obj pointer which will be used to initialize cache.
+
+ // We also bind if we are not able to find from regdb whether
+ // the class has custom link implementation or not
+
+ if ((error = BindMoniker(lpmkSrc, NULL /* grfOpt */,
+ IID_IDataObject, (LPLPVOID) &lpBoundDataObj))
+ != NOERROR) {
+
+ if (OLERENDER_NONE != renderopt)
+ return ResultFromScode(
+ OLE_E_CANT_BINDTOSOURCE);
+
+
+ // else we assume StdOleLink and continue with creation
+ } else {
+ lpSrcDataObj = lpBoundDataObj;
+
+ if (IsEqualCLSID(clsidLast, CLSID_NULL))
+ UtGetClassID((LPUNKNOWN)lpSrcDataObj,
+ &clsidLast);
+ }
+ }
+
+ // Deal with CustomLinkSource
+ // (see notes below)
+ if (lpSrcDataObj) {
+ STGMEDIUM medTmp;
+ FORMATETC foretcTmp;
+
+ INIT_FORETC(foretcTmp);
+ foretcTmp.cfFormat = g_cfCustomLinkSource;
+ foretcTmp.tymed = TYMED_ISTORAGE;
+
+ if (lpSrcDataObj->QueryGetData(&foretcTmp) == NOERROR) {
+ medTmp.tymed = TYMED_ISTORAGE;
+ medTmp.pstg = lpStg;
+ medTmp.pUnkForRelease = NULL;
+
+ if (error = lpSrcDataObj->GetDataHere(&foretcTmp,
+ &medTmp))
+ goto errRtn;
+
+ error = wLoadAndInitObjectEx(lpSrcDataObj, iid,
+ renderopt, cFormats, rgAdvf, rgFormatEtc,
+ lpAdviseSink, rgdwConnection, lpClientSite,
+ lpStg, lplpObj);
+
+ // This is a really strange peice of logic,
+ // spaghetti code at it's finest. Basically,
+ // this says that if there is *NOT* a
+ // custom link source, then we want to do the
+ // logic of wCreateObject, etc. below. If we
+ // got to this line in the code, then we
+ // *did* have a custom link source, so
+ // don't do the stuff below (thus the goto).
+
+ // REVIEW32: If there are any bugs in here,
+ // then rewrite this in a more sensible fashion.
+ // I'm leaving as is for now due to time constraints.
+
+ goto errRtn;
+ }
+ }
+
+ // Otherwise
+ if ((error = wCreateObject (CLSID_StdOleLink, iid, lpClientSite,
+ lpStg, STG_INITNEW, lplpObj)) != NOERROR)
+ goto errRtn;
+
+ if (lpSrcDataObj)
+ {
+ BOOL fCacheNodeCreated = FALSE;
+
+ if ((error = wInitializeCacheEx(lpSrcDataObj, clsidLast,
+ renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink,
+ rgdwConnection, *lplpObj, &fCacheNodeCreated)) != NOERROR)
+ {
+
+ if (error != NOERROR && fCacheNodeCreated)
+ {
+ fNeedsUpdate = TRUE;
+ error = NOERROR;
+ }
+
+ }
+ }
+
+errRtn:
+
+ if (error == NOERROR && *lplpObj)
+ error = ((LPUNKNOWN) *lplpObj)->QueryInterface(IID_IOleLink,
+ (LPLPVOID) &lpLink);
+
+ if (error == NOERROR && lpLink && (dwFlags & OLECREATE_LEAVERUNNING)) {
+ // This will connect to the object if it is already running.
+ lpLink->SetSourceMoniker (lpmkSrc, clsidLast);
+ }
+
+ // We bound to the object to initialize the cache. We don't need
+ // it anymore
+ if (lpBoundDataObj)
+ {
+ if (error == NOERROR && (dwFlags & OLECREATE_LEAVERUNNING))
+ OleRun((LPUNKNOWN)*lplpObj);
+
+ // this will give a chance to the object to go away, if it can
+ wDoLockUnlock(lpBoundDataObj);
+ lpBoundDataObj->Release();
+ }
+
+ // If the source object started running as a result of BindMoniker,
+ // then we would've got rid of it by now.
+
+ if (error == NOERROR && lpLink)
+ {
+ if ( !(dwFlags & OLECREATE_LEAVERUNNING) ) {
+ // This will connect to the object if it is already running.
+ lpLink->SetSourceMoniker (lpmkSrc, clsidLast);
+ }
+
+ if (fNeedsUpdate) {
+ // relevant cache data is not available from the
+ // lpSrcDataObj. So do Update and get the right cache
+ // data.
+ error = wDoUpdate ((LPUNKNOWN) *lplpObj);
+
+ if (GetScode(error) == CACHE_E_NOCACHE_UPDATED)
+ error = ReportResult(0, DV_E_FORMATETC, 0, 0);
+ }
+
+ // Release on lpLink is necessary only if error == NOERROR
+ lpLink->Release();
+
+ }
+
+ if (error != NOERROR && *lplpObj) {
+ ((IUnknown FAR*) *lplpObj)->Release();
+ *lplpObj = NULL;
+ }
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCreateFromFileEx
+//
+// Synopsis: Creates an ole object from a file by binding the given
+// moniker and creating the object from the IDataObject pointer
+//
+// Effects:
+//
+// Arguments: [lpmkFile] -- moniker to the file
+// [iid] -- requested interface ID
+// [dwFlags] -- object creation flags
+// [renderopt] -- render options, such as OLERENDER_DRAW
+// [cFormats] -- the number of elements in rgFormatEtc
+// [rgAdvf] -- array of advise flags, if OLRENDER_FORMAT
+// is specified in renderopt
+// [rgFormatEtc] -- array of rendering formats, if
+// OLERENDER_FORMAT is specified in renderopt
+// [lpAdviseSink] -- the advise sink for the object
+// [rgdwConnection]-- where to put the connection IDs for the
+// advisory connections
+// [lpClientSite] -- pointer to the client site
+// [lpStg] -- pointer to the storage for the new object
+// [lplpObj] -- where to put the pointer to the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(wCreateFromFileEx)
+INTERNAL wCreateFromFileEx
+(
+ LPMONIKER lpmkFile,
+ LPDATAOBJECT lpDataObject,
+ REFIID iid,
+ DWORD dwFlags,
+ DWORD renderopt,
+ ULONG cFormats,
+ DWORD FAR* rgAdvf,
+ LPFORMATETC rgFormatEtc,
+ IAdviseSink FAR* lpAdviseSink,
+ DWORD FAR* rgdwConnection,
+ LPOLECLIENTSITE lpClientSite,
+ LPSTORAGE lpStg,
+ LPLPVOID lplpObj
+)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ LPDATAOBJECT lpLocalDataObj;
+
+
+ if (!lpDataObject)
+ {
+ if ((error = BindMoniker(lpmkFile, NULL, IID_IDataObject,
+ (LPLPVOID) &lpLocalDataObj)) != NOERROR)
+ return error;
+ }
+ else
+ {
+ lpLocalDataObj = lpDataObject;
+ }
+
+ Verify(lpLocalDataObj);
+
+ error = wCreateFromDataEx(lpLocalDataObj, iid, dwFlags, renderopt, cFormats,
+ rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection, lpClientSite,
+ lpStg, lplpObj);
+
+ if (error == NOERROR && (dwFlags & OLECREATE_LEAVERUNNING))
+ OleRun((LPUNKNOWN)*lplpObj);
+
+ // If we bound locally release it now, else it is up to the caller to do the right thing.
+
+ if (!lpDataObject)
+ {
+ wDoLockUnlock(lpLocalDataObj);
+ lpLocalDataObj->Release();
+ }
+
+ return error;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CoIsHashedOle1Class
+//
+// Synopsis: Determines whether or not a CLSID is an OLE1 class
+//
+// Effects:
+//
+// Arguments: [rclsid] -- the class ID in question
+//
+// Requires:
+//
+// Returns: TRUE if ole1.0, FALSE otherwise
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Oct-93 alexgo 32bit port
+//
+// Notes: REVIEW32: This is a strange function..consider nuking
+// it for 32bit, we may not need it (only used in 1 place)
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CoIsHashedOle1Class)
+STDAPI_(BOOL) CoIsHashedOle1Class(REFCLSID rclsid)
+{
+ VDATEHEAP();
+
+ CLSID clsid = rclsid;
+ clsid.Data1 = 0L;
+ WORD wHiWord = HIWORD(rclsid.Data1);
+ return IsEqualGUID(clsid, IID_IUnknown) && wHiWord==4;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: EnsureCLSIDIsRegistered
+//
+// Synopsis: Checks to see if the clsid is in the registration database,
+// if not, puts it there
+//
+// Effects:
+//
+// Arguments: [clsid] -- the clsid in question
+// [pstg] -- storage to get more info about the
+// clsid if we need to register it
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(EnsureCLSIDIsRegistered)
+void EnsureCLSIDIsRegistered
+ (REFCLSID clsid,
+ LPSTORAGE pstg)
+{
+ VDATEHEAP();
+
+ LPOLESTR szProgId = NULL;
+
+ if (NOERROR == ProgIDFromCLSID (clsid, &szProgId))
+ {
+ PubMemFree(szProgId);
+ }
+ else
+ {
+ // This is the case of getting a hashed CLSID from a file from
+ // another machine and the ProgId is not yet in the reg db,
+ // so we must get it from the storage.
+ // This code should rarely be executed.
+ CLIPFORMAT cf = 0;
+ CLSID clsidT;
+ OLECHAR szProgId[256];
+
+ if (ReadFmtUserTypeStg (pstg, &cf, NULL) != NOERROR)
+ return;
+ // Format is the ProgId
+ if (0==GetClipboardFormatName (cf, szProgId, 256))
+ return;
+ // Will force registration of the CLSID if the ProgId (the OLE1
+ // classname) is registered
+ CLSIDFromProgID (szProgId, &clsidT);
+ }
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCreateObject
+//
+// Synopsis: Calls CoCreateInstance to create an object, a defhandler
+// is created if necessary and CLSID info is written to
+// the storage.
+//
+// Effects:
+//
+// Arguments: [clsid] -- the class id of the object to create
+// [iid] -- the requested interface ID
+// [lpClientSite] -- pointer to the client site
+// [lpStg] -- storage for the object
+// [wfStorage] -- flags for the STORAGE, one of
+// STG_NONE, STD_INITNEW, STG_LOAD,
+// defined at the beginning of this file
+// [ppv] -- where to put the pointer to the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-94 alexgo fixed memory leak
+// 29-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(wCreateObject)
+INTERNAL wCreateObject
+(
+ CLSID clsid,
+ REFIID iid,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR * lpStg,
+ WORD wfStorage,
+ void FAR* FAR* ppv
+)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ DWORD dwClsCtx;
+
+ *ppv = NULL;
+
+ CLSID clsidNew;
+ if (wfStorage == STG_INITNEW
+ && SUCCEEDED(OleGetAutoConvert (clsid, &clsidNew)))
+ // Insert an object of the new class
+ clsid = clsidNew;
+
+
+ if (wfStorage == STG_LOAD && CoIsHashedOle1Class (clsid))
+ EnsureCLSIDIsRegistered (clsid, lpStg);
+
+
+ if (IsWOWThread())
+ {
+ // CLSCTX needs to be turned on for possible 16 bit inproc server
+ // such as OLE controls
+ dwClsCtx = CLSCTX_INPROC | CLSCTX_INPROC_SERVER16;
+ }
+ else
+ {
+#ifdef WX86OLE
+ if (gcwx86.IsWx86Enabled())
+ {
+ dwClsCtx = CLSCTX_INPROC | CLSCTX_INPROC_SERVERX86 |
+ CLSCTX_INPROC_HANDLERX86;
+ }
+ else
+ {
+ dwClsCtx = CLSCTX_INPROC;
+ }
+#else
+ dwClsCtx = CLSCTX_INPROC;
+#endif
+ }
+
+ if ((error = CoCreateInstance (clsid, NULL /*pUnkOuter*/,
+ dwClsCtx, iid, ppv)) != NOERROR) {
+
+ // if not OleLoad or error other than class not registered,
+ // exit
+ if (wfStorage != STG_LOAD || GetScode(error)
+ != REGDB_E_CLASSNOTREG)
+ goto errRtn;
+
+ // OleLoad and class not registered: use default handler
+ // directly
+ if ((error = OleCreateDefaultHandler(clsid, NULL, iid, ppv))
+ != NOERROR)
+ goto errRtn;
+ }
+
+ AssertSz(*ppv, "HRESULT is OK, but pointer is NULL");
+
+ if (wfStorage != STG_NONE)
+ {
+ IPersistStorage FAR* lpPS;
+
+ if ((error = ((LPUNKNOWN) *ppv)->QueryInterface(
+ IID_IPersistStorage, (LPLPVOID)&lpPS)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if (wfStorage == STG_INITNEW)
+ {
+ error = WriteClassStg(lpStg, clsid);
+
+ if (SUCCEEDED(error))
+ {
+ error = lpPS->InitNew (lpStg);
+ }
+ }
+ else
+ {
+ error = lpPS->Load (lpStg);
+ }
+
+ lpPS->Release();
+
+ if (FAILED(error))
+ {
+ goto errRtn;
+ }
+
+ }
+
+ if (lpClientSite) {
+ LPOLEOBJECT lpOleObj = NULL;
+
+ if ((error =((LPUNKNOWN) *ppv)->QueryInterface(IID_IOleObject,
+ (LPLPVOID) &lpOleObj)) != NOERROR)
+ goto errRtn;
+
+ error = lpOleObj->SetClientSite (lpClientSite);
+
+ lpOleObj->Release();
+
+ if (FAILED(error))
+ goto errRtn;
+ }
+
+ AssertSz(error == NOERROR, "Invalid code path");
+
+ return NOERROR;
+
+errRtn:
+
+ if (*ppv) {
+ ((LPUNKNOWN) *ppv)->Release();
+ *ppv = NULL;
+ }
+
+ return error;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wLoadAndInitObjectEx
+//
+// Synopsis: Loads and binds an object from the given storage.
+// A cacle is initialized from the data object
+//
+// Effects:
+//
+// Arguments: [lpSrcDataObj] -- pointer to the data object to initialize
+// the cache with
+// [iid] -- requested interface ID
+// [renderopt] -- render options, such as OLERENDER_DRAW
+// [cFormats] -- the number of elements in rgFormatEtc
+// [rgAdvf] -- array of advise flags, if OLRENDER_FORMAT
+// is specified in renderopt
+// [rgFormatEtc] -- array of rendering formats, if
+// OLERENDER_FORMAT is specified in renderopt
+// [lpAdviseSink] -- the advise sink for the object
+// [rgdwConnection]-- where to put the connection IDs for the
+// advisory connections
+// [lpClientSite] -- pointer to the client site.
+// [lpStg] -- storage for the new object
+// [lplpObj] -- where to put the pointer to the new object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(wLoadAndInitObjectEx)
+INTERNAL wLoadAndInitObjectEx
+(
+ IDataObject FAR* lpSrcDataObj,
+ REFIID iid,
+ DWORD renderopt,
+ ULONG cFormats,
+ DWORD FAR* rgAdvf,
+ LPFORMATETC rgFormatEtc,
+ IAdviseSink FAR* lpAdviseSink,
+ DWORD FAR* rgdwConnection,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg,
+ void FAR* FAR* lplpObj
+)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ CLSID clsid;
+
+ if ((error = OleLoadWithoutBinding(lpStg, iid, lpClientSite,
+ lplpObj)) != NOERROR)
+ return error;
+
+ UtGetClassID((LPUNKNOWN) *lplpObj, &clsid);
+
+ error = wInitializeCacheEx(lpSrcDataObj, clsid, renderopt,
+ cFormats, rgAdvf, rgFormatEtc, lpAdviseSink, rgdwConnection,
+ *lplpObj);
+
+ if (error != NOERROR) {
+ // relevant cache data is not available from the lpSrcDataObj.
+ // So do Update and get the right cache data.
+ error = wDoUpdate ((LPUNKNOWN) *lplpObj);
+ }
+
+ if (GetScode(error) == CACHE_E_NOCACHE_UPDATED) {
+ error = ReportResult(0, DV_E_FORMATETC, 0, 0);
+ goto errRtn;
+ }
+
+ if (error == NOERROR)
+ wBindIfRunning((LPUNKNOWN) *lplpObj);
+
+errRtn:
+ if (error != NOERROR && *lplpObj) {
+ ((IUnknown FAR*) *lplpObj)->Release();
+ *lplpObj = NULL;
+ }
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wInitializeCacheEx
+//
+// Synopsis: Query's for IOleCache on the given object and calls IOC->Cache
+// to initialize a cache node.
+//
+// Effects:
+//
+// Arguments: [lpSrcDataObj] -- pointer to data to initialize the cache
+// with
+// [rclsid] -- CLSID to use if an icon is needed
+// [renderopt] -- render options, such as OLERENDER_DRAW
+// [cFormats] -- the number of elements in rgFormatEtc
+// [rgAdvf] -- array of advise flags, if OLRENDER_FORMAT
+// is specified in renderopt
+// [rgFormatEtc] -- array of rendering formats, if
+// OLERENDER_FORMAT is specified in renderopt
+// [lpAdviseSink] -- the advise sink for the object
+// [rgdwConnection]-- where to put the connection IDs for the
+// advisory connections
+// [lpNewObj] -- the object on which the cache should
+// be initialized
+// [pfCacheNodeCreated] -- where to return a flag indicating
+// whether or not a cache node was
+// created
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 31-Oct-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+// This routine modifies lpFormatEtc's fields.
+
+#pragma SEG(wInitializeCacheEx)
+INTERNAL wInitializeCacheEx
+(
+ IDataObject FAR* lpSrcDataObj,
+ REFCLSID rclsid,
+ DWORD renderopt,
+ ULONG cFormats,
+ DWORD FAR* rgAdvf,
+ LPFORMATETC rgFormatEtc,
+ IAdviseSink FAR* lpAdviseSink,
+ DWORD FAR* rgdwConnection,
+ void FAR* lpNewObj,
+ BOOL FAR* pfCacheNodeCreated
+)
+{
+ VDATEHEAP();
+
+ IDataObject FAR* lpNewDataObj = NULL;
+ IOleCache FAR* lpOleCache = NULL;
+ HRESULT error;
+ LPFORMATETC lpFormatEtc;
+ DWORD advf;
+ STGMEDIUM stgmed;
+ DWORD dwConnId = 0;
+ BOOL fIconCase;
+
+ if (pfCacheNodeCreated)
+ *pfCacheNodeCreated = FALSE;
+
+ if (renderopt == OLERENDER_NONE || renderopt == OLERENDER_ASIS)
+ return NOERROR;
+
+ if (lpAdviseSink) {
+ if ((error = ((IUnknown FAR*)lpNewObj)->QueryInterface(IID_IDataObject,
+ (LPLPVOID) &lpNewDataObj)) != NOERROR)
+ return error;
+ }
+ else {
+ if (((IUnknown FAR*)lpNewObj)->QueryInterface(IID_IOleCache,
+ (LPLPVOID) &lpOleCache) != NOERROR)
+ return wQueryFormatSupport(lpNewObj, renderopt, rgFormatEtc);
+ }
+
+ for (ULONG i=0; i<cFormats; i++)
+ {
+ advf = (rgAdvf ? rgAdvf[i] : ADVF_PRIMEFIRST);
+ lpFormatEtc = &rgFormatEtc[i];
+ fIconCase = FALSE;
+
+ if (lpFormatEtc->dwAspect == DVASPECT_ICON) {
+ if (lpFormatEtc->cfFormat == NULL) {
+ lpFormatEtc->cfFormat = CF_METAFILEPICT;
+ lpFormatEtc->tymed = TYMED_MFPICT;
+ }
+ fIconCase = (lpFormatEtc->cfFormat == CF_METAFILEPICT);
+ }
+
+ if (lpAdviseSink)
+ {
+ // if icon case, must use these advise flags or the icon
+ // data won't get passed back correctly
+ if (fIconCase)
+ advf |= (ADVF_PRIMEFIRST | ADVF_ONLYONCE);
+
+ // should we send the data immediately?
+ if ((advf & ADVF_PRIMEFIRST) && lpSrcDataObj)
+ {
+ stgmed.tymed = TYMED_NULL;
+ stgmed.pUnkForRelease = NULL;
+
+ if (advf & ADVF_NODATA)
+ {
+ // don't sent data, send only the notification
+ lpAdviseSink->OnDataChange(lpFormatEtc, &stgmed);
+ }
+ else
+ {
+ if (fIconCase)
+ error = UtGetIconData(lpSrcDataObj, rclsid, lpFormatEtc, &stgmed);
+ else
+ error = lpSrcDataObj->GetData(lpFormatEtc, &stgmed);
+
+ if (error != NOERROR)
+ goto errRtn;
+
+ // send data to sink and release stdmedium
+ lpAdviseSink->OnDataChange(lpFormatEtc, &stgmed);
+ ReleaseStgMedium(&stgmed);
+ }
+
+ if (advf & ADVF_ONLYONCE)
+ continue;
+
+ // remove the ADVF_PRIMEFIRST from flags.
+ advf &= (~ADVF_PRIMEFIRST);
+ }
+
+ // setup advisory connection
+ if ((error = lpNewDataObj->DAdvise(lpFormatEtc, advf,
+ lpAdviseSink, &dwConnId)) != NOERROR)
+ goto errRtn;
+
+ // optionally stuff the id in the array
+ if (rgdwConnection)
+ rgdwConnection[i] = dwConnId;
+ }
+ else
+ {
+ if (fIconCase)
+ advf = ADVF_NODATA;
+
+ // Create a cache of already specified view format.
+ // In case of olerender_draw, lpFormatEtc->cfFormat would have already
+ // been set to NULL.
+
+ error = lpOleCache->Cache(lpFormatEtc, advf, &dwConnId);
+
+ if (FAILED(GetScode(error))) {
+ if (! ((dwConnId != 0) && fIconCase) )
+ goto errRtn;
+
+ // In icon case we can ignore the cache's QueryGetData failure
+ }
+
+ error = NOERROR;
+ if (pfCacheNodeCreated)
+ *pfCacheNodeCreated = TRUE;
+
+ if (fIconCase) {
+ if ((error = UtGetIconData(lpSrcDataObj, rclsid, lpFormatEtc,
+ &stgmed)) == NOERROR) {
+ if ((error = lpOleCache->SetData(lpFormatEtc, &stgmed,
+ TRUE)) != NOERROR)
+ ReleaseStgMedium(&stgmed);
+ }
+ }
+ }
+ }
+
+ if (error == NOERROR && !lpAdviseSink && lpSrcDataObj)
+ error = lpOleCache->InitCache(lpSrcDataObj);
+
+errRtn:
+ if (lpNewDataObj)
+ lpNewDataObj->Release();
+ if (lpOleCache)
+ lpOleCache->Release();
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wReturnCreationError
+//
+// Synopsis: modifies the return code, used internally in creation api's
+//
+// Effects:
+//
+// Arguments: [hresult] -- the original error code
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+INTERNAL wReturnCreationError(HRESULT hresult)
+{
+ VDATEHEAP();
+
+ if (hresult != NOERROR) {
+ SCODE sc = GetScode(hresult);
+
+ if (sc == CACHE_S_FORMATETC_NOTSUPPORTED
+ || sc == CACHE_E_NOCACHE_UPDATED)
+ return ReportResult(0, DV_E_FORMATETC, 0, 0);
+ }
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wGetMonikerAndClassFromFile
+//
+// Synopsis: gets a moniker and class id from the given file
+//
+// Effects:
+//
+// Arguments: [lpszFileName] -- the file
+// [fLink] -- passed onto CreatePackagerMoniker
+// [lplpmkFile] -- where to put the pointer to the file
+// moniker
+// [lpfPackagerMoniker] -- where to put a flag indicating
+// whether or not a packager moniker
+// was created.
+// [lpClsid] -- where to put the class ID
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Nov-93 alexgo 32bit port
+// 10-May-94 KevinRo Reimplemented OLE 1.0 interop
+// 03-Mar-95 ScottSk Added STG_E_FILENOTFOUND
+//
+//
+//--------------------------------------------------------------------------
+
+
+INTERNAL wGetMonikerAndClassFromFile
+(
+ LPCOLESTR lpszFileName,
+ BOOL fLink,
+ LPMONIKER FAR* lplpmkFile,
+ BOOL FAR* lpfPackagerMoniker,
+ CLSID FAR* lpClsid,
+ LPDATAOBJECT * lplpDataObject
+)
+{
+HRESULT hrGetClassFile;
+HRESULT hrFileMoniker;
+HRESULT hresult;
+BOOL fHaveBoundClsid = FALSE;
+LPMONIKER lpFileMoniker;
+
+ VDATEHEAP();
+
+ *lplpDataObject = NULL;
+ *lplpmkFile = NULL;
+
+
+ // Call GetClassFileEx directly (rather than going through GetClassFile).
+ hrGetClassFile = GetClassFileEx ((LPOLESTR)lpszFileName, lpClsid, CLSID_NULL);
+
+ Assert( (NOERROR == hrGetClassFile) || (IsEqualCLSID(*lpClsid, CLSID_NULL)) );
+
+ // To ensure the same error codes are returned as before we don't return immediately if CreateFileMoniker fails.
+ hrFileMoniker = CreateFileMoniker((LPOLESTR)lpszFileName, &lpFileMoniker);
+ Assert( (NOERROR == hrFileMoniker) || (NULL == lpFileMoniker) );
+
+ // If couldn't get the Clsid because an error other than
+ // MK_E_INVALIDEXTENSION occured see if it is already running
+
+ if (FAILED(hrGetClassFile) && (MK_E_INVALIDEXTENSION != hrGetClassFile) && (NOERROR == hrFileMoniker) )
+ {
+ LPBINDCTX pbc;
+
+ if (SUCCEEDED(CreateBindCtx( 0, &pbc )))
+ {
+ if (S_OK == lpFileMoniker->IsRunning(pbc,NULL,NULL))
+ {
+
+ // If the Object is Running Bind and get the CLSID
+ if (NOERROR == lpFileMoniker->BindToObject(pbc, NULL, IID_IDataObject,
+ (LPLPVOID) lplpDataObject))
+ {
+ fHaveBoundClsid = UtGetClassID((LPUNKNOWN)*lplpDataObject,lpClsid);
+ Assert( (TRUE == fHaveBoundClsid) || (IsEqualCLSID(*lpClsid, CLSID_NULL)) );
+ }
+
+ }
+
+ pbc->Release();
+ }
+ }
+
+ // If have a CLSID at this point see if its insertable.
+ if ( (NOERROR == hrGetClassFile) || (TRUE == fHaveBoundClsid) )
+ {
+
+ Assert(!IsEqualCLSID(*lpClsid, CLSID_NULL));
+
+ // Check whether we need package this file, even though it is an
+ // OLE class file.
+ if (!wNeedToPackage(*lpClsid))
+ {
+ if (lpfPackagerMoniker != NULL)
+ {
+ *lpfPackagerMoniker = FALSE;
+ }
+
+ *lplpmkFile = lpFileMoniker;
+ return hrFileMoniker;
+ }
+ }
+
+ //
+ // We didnt' find an OLE insertable object or couldn't get the CLSID. Therefore, create a
+ // packager moniker for it.
+ //
+
+ // If Bound to the DataObject, release it.
+ if (*lplpDataObject)
+ {
+ (*lplpDataObject)->Release();
+ *lplpDataObject = NULL;
+ }
+
+
+ // If GetClassFileEx() failed because the file was not found or could not be openned.
+ // don't try to bind with Packager.
+ if (hrGetClassFile == MK_E_CANTOPENFILE)
+ {
+ if (NOERROR == hrFileMoniker)
+ {
+ lpFileMoniker->Release();
+ }
+
+ return STG_E_FILENOTFOUND;
+ }
+
+ // If we failed to create the file moniker its finally safe to bail without changing the error code.
+ if (NOERROR != hrFileMoniker)
+ {
+ return hrFileMoniker;
+ }
+
+ if (lpfPackagerMoniker != NULL)
+ {
+ *lpfPackagerMoniker = TRUE;
+ }
+
+ hresult = CreatePackagerMonikerEx(lpszFileName,lpFileMoniker,fLink,lplpmkFile);
+ lpFileMoniker->Release();
+
+ return hresult;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCreatePackageEx
+//
+// Synopsis: Internal function, does a IDO->GetData for a filename, and
+// then creates either a link or normal object from that file
+//
+// Effects:
+//
+// Arguments: [lpSrcDataObj] -- the source for the filename
+// [iid] -- the requested interface ID
+// [dwFlags] -- object creation flags
+// [renderopt] -- render options, such as OLERENDER_DRAW
+// [cFormats] -- the number of elements in rgFormatEtc
+// [rgAdvf] -- array of advise flags, if OLRENDER_FORMAT
+// is specified in renderopt
+// [rgFormatEtc] -- array of rendering formats, if
+// OLERENDER_FORMAT is specified in renderopt
+// [lpAdviseSink] -- the advise sink for the object
+// [rgdwConnection]-- where to put the connection IDs for the
+// advisory connections
+// [lpClientSite] -- client site for the object
+// [lpStg] -- storage for the object
+// [fLink] -- if TRUE, create a link
+// [lplpObj] -- where to put the pointer to the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Gets a filename from the data object (converting to Unicode
+// if necessary) and then creates either an embedding or link
+// from that filename.
+//
+// History: dd-mmm-yy Author Comment
+// 24-Apr-94 alexgo rewrote to handle FileNameW
+// 01-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(wCreatePackageEx)
+INTERNAL wCreatePackageEx
+(
+ LPDATAOBJECT lpSrcDataObj,
+ REFIID iid,
+ DWORD dwFlags,
+ DWORD renderopt,
+ ULONG cFormats,
+ DWORD FAR* rgAdvf,
+ LPFORMATETC rgFormatEtc,
+ IAdviseSink FAR* lpAdviseSink,
+ DWORD FAR* rgdwConnection,
+ LPOLECLIENTSITE lpClientSite,
+ LPSTORAGE lpStg,
+ BOOL fLink,
+ LPLPVOID lplpObj
+)
+{
+ VDATEHEAP();
+
+ FORMATETC formatetc;
+ STGMEDIUM medium;
+ HRESULT hresult;
+ CLSID clsid = CLSID_NULL;
+ LPOLESTR pszFileName = NULL;
+ OLECHAR szFileName[MAX_PATH +1]; // in case we
+ // have to
+ // translate
+
+ LEDebugOut((DEB_ITRACE, "%p _IN wCreatePackageEx ( %p , %p , %lx , %lx ,"
+ " %lx , %p , %p , %p , %p , %p , %p , %lu , %p )\n", NULL, lpSrcDataObj,
+ &iid, dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc, lpAdviseSink,
+ rgdwConnection, lpClientSite, lpStg, fLink, lplpObj));
+
+ INIT_FORETC(formatetc);
+ formatetc.cfFormat = g_cfFileNameW;
+ formatetc.tymed = TYMED_HGLOBAL;
+
+ // zero the medium
+ _xmemset(&medium, 0, sizeof(STGMEDIUM));
+
+ // we don't need to do a QueryGetData, because we will have only
+ // gotten here on the advice of a formatetc enumerator from the
+ // data object (and thus, one of the GetData calls should succeed).
+
+
+ hresult = lpSrcDataObj->GetData(&formatetc, &medium);
+
+ // if we couldn't get the Unicode filename for some reason, try
+ // for the ANSI version
+
+ if( hresult != NOERROR )
+ {
+ char * pszAnsiFileName;
+ DWORD cwchSize;
+
+ formatetc.cfFormat = g_cfFileName;
+ // re-NULL the medium, just in case it was messed up by
+ // the first call above
+
+ _xmemset( &medium, 0, sizeof(STGMEDIUM));
+
+ hresult = lpSrcDataObj->GetData(&formatetc, &medium);
+
+ if( hresult == NOERROR )
+ {
+ pszAnsiFileName = (char *)GlobalLock(medium.hGlobal);
+
+ cwchSize = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
+ pszAnsiFileName, -1, szFileName, MAX_PATH);
+
+ if( cwchSize == 0 )
+ {
+ GlobalUnlock(medium.hGlobal);
+ ReleaseStgMedium(&medium);
+ hresult = ResultFromScode(E_FAIL);
+ }
+ else
+ {
+ pszFileName = szFileName;
+ }
+ // we will Unlock at the end of the routine
+ }
+ }
+ else
+ {
+ pszFileName = (LPOLESTR)GlobalLock(medium.hGlobal);
+ }
+
+ if( hresult == NOERROR )
+ {
+ if (fLink)
+ {
+ hresult = OleCreateLinkToFileEx(pszFileName, iid,
+ dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc,
+ lpAdviseSink, rgdwConnection, lpClientSite, lpStg, lplpObj);
+ }
+ else
+ {
+ hresult = OleCreateFromFileEx(clsid, pszFileName, iid,
+ dwFlags, renderopt, cFormats, rgAdvf, rgFormatEtc,
+ lpAdviseSink, rgdwConnection, lpClientSite, lpStg, lplpObj);
+ }
+
+ GlobalUnlock(medium.hGlobal);
+ ReleaseStgMedium(&medium);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT wCreatePackageEx ( %lx ) [ %p ]\n",
+ NULL, hresult, *lplpObj));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wValidateCreateParams
+//
+// Synopsis: Validate the incoming create parameters
+//
+// Effects:
+//
+// Arguments: [cFormats] -- the number of elements in rgAdvf
+// [rgAdvf] -- array of advise flags
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 26-Apr-96 davidwor added function
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(wValidateCreateParams)
+INTERNAL wValidateCreateParams
+(
+ DWORD dwFlags,
+ DWORD renderopt,
+ ULONG cFormats,
+ DWORD FAR* rgAdvf,
+ LPFORMATETC rgFormatEtc,
+ IAdviseSink FAR* lpAdviseSink,
+ DWORD FAR* rgdwConnection,
+ IOleClientSite FAR* lpClientSite,
+ IStorage FAR* lpStg
+)
+{
+ HRESULT hresult = NOERROR;
+
+ VDATEHEAP();
+
+ if (dwFlags != (dwFlags & OLECREATE_LEAVERUNNING)) {
+ VdateAssert(dwFlags, "Invalid creation flags");
+ hresult = ResultFromScode(E_INVALIDARG);
+ goto errRtn;
+ }
+
+ if (renderopt == OLERENDER_DRAW && cFormats > 1) {
+ VdateAssert(cFormats, "Multiple formats not allowed with OLERENDER_DRAW");
+ hresult = ResultFromScode(E_INVALIDARG);
+ goto errRtn;
+ }
+
+ if (renderopt != OLERENDER_FORMAT)
+ VDATEPTRNULL_LABEL( lpAdviseSink, errRtn, hresult );
+
+ if (cFormats == 0) {
+ VDATEPTRNULL_LABEL( rgAdvf, errRtn, hresult );
+ VDATEPTRNULL_LABEL( rgFormatEtc, errRtn, hresult );
+ VDATEPTRNULL_LABEL( rgdwConnection, errRtn, hresult );
+ }
+ else {
+ VDATESIZEREADPTRIN_LABEL( rgAdvf, cFormats * sizeof(DWORD), errRtn, hresult );
+ VDATESIZEREADPTRIN_LABEL( rgFormatEtc, cFormats * sizeof(FORMATETC), errRtn, hresult );
+ if ( rgdwConnection ) {
+ VDATESIZEPTROUT_LABEL( rgdwConnection, cFormats * sizeof(DWORD), errRtn, hresult );
+ _xmemset(rgdwConnection, 0, cFormats * sizeof(DWORD));
+ }
+ }
+
+ if ((hresult = wValidateAdvfEx(cFormats, rgAdvf)) != NOERROR)
+ goto errRtn;
+
+ VDATEIFACE_LABEL( lpStg, errRtn, hresult );
+ if ( lpAdviseSink )
+ VDATEIFACE_LABEL( lpAdviseSink, errRtn, hresult );
+ if ( lpClientSite )
+ VDATEIFACE_LABEL( lpClientSite, errRtn, hresult );
+
+errRtn:
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wValidateAdvfEx
+//
+// Synopsis: Validate the incoming array of ADVF values
+//
+// Effects:
+//
+// Arguments: [cFormats] -- the number of elements in rgAdvf
+// [rgAdvf] -- array of advise flags
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 19-Mar-96 davidwor added function
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(wValidateAdvfEx)
+INTERNAL wValidateAdvfEx
+(
+ ULONG cFormats,
+ DWORD FAR* rgAdvf
+)
+{
+ VDATEHEAP();
+
+ if ((cFormats != 0) != (rgAdvf != NULL))
+ return ResultFromScode(E_INVALIDARG);
+
+ for (ULONG i=0; i<cFormats; i++)
+ {
+ if (rgAdvf[i] != (rgAdvf[i] & MASK_VALID_ADVF))
+ {
+ VdateAssert(rgAdvf, "Invalid ADVF value specified");
+ return ResultFromScode(E_INVALIDARG);
+ }
+ }
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wValidateFormatEtc
+//
+// Synopsis: Validate the incoming formatetc and initialize the
+// out formatetc with the correct info
+//
+// Effects:
+//
+// Arguments: [renderopt] -- rendering option
+// [lpFormatEtc] -- the incoming formatetc
+// [lpMyFormatEtc] -- the out formatetc
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Nov-93 alexgo 32bit port
+//
+// Notes: The original comments,
+//
+// Validate the lpFormatEtc that's been passed to the creation APIs. And then
+// initialize our formateEtc structure with the appropriate info.
+//
+// We allow NULL lpFormatEtc if the render option is olerender_draw
+// We ignore lpFormatEtc if the render option is olerender_none
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(wValidateFormatEtc)
+INTERNAL wValidateFormatEtc
+(
+ DWORD renderopt,
+ LPFORMATETC lpFormatEtc,
+ LPFORMATETC lpMyFormatEtc
+)
+{
+ VDATEHEAP();
+
+ SCODE sc = S_OK;
+
+ if (renderopt == OLERENDER_NONE || renderopt == OLERENDER_ASIS)
+ return NOERROR;
+
+ if (renderopt == OLERENDER_FORMAT) {
+ if (!lpFormatEtc || !lpFormatEtc->cfFormat) {
+ sc = E_INVALIDARG;
+ goto errRtn;
+ }
+
+ if (lpFormatEtc->tymed !=
+ UtFormatToTymed(lpFormatEtc->cfFormat)) {
+ sc = DV_E_TYMED;
+ goto errRtn;
+ }
+
+ } else if (renderopt == OLERENDER_DRAW) {
+ if (lpFormatEtc) {
+ if (lpFormatEtc->cfFormat != NULL) {
+ VdateAssert(lpFormatEtc->cfFormat,"NON-NULL clipformat specified with OLERENDER_DRAW");
+ sc = DV_E_CLIPFORMAT;
+ goto errRtn;
+ }
+
+ if (lpFormatEtc->tymed != TYMED_NULL) {
+ VdateAssert(lpFormatEtc->tymed,"TYMED_NULL is not specified with OLERENDER_DRAW");
+ sc = DV_E_TYMED;
+ goto errRtn;
+ }
+ }
+ } else {
+ VdateAssert(renderopt, "Unexpected value for OLERENDER_ option");
+ sc = E_INVALIDARG;
+ goto errRtn;
+ }
+
+ if (lpFormatEtc) {
+ if (!HasValidLINDEX(lpFormatEtc))
+ {
+ sc = DV_E_LINDEX;
+ goto errRtn;
+ }
+
+ VERIFY_ASPECT_SINGLE(lpFormatEtc->dwAspect)
+
+ *lpMyFormatEtc = *lpFormatEtc;
+
+ } else {
+ INIT_FORETC(*lpMyFormatEtc);
+ lpMyFormatEtc->tymed = TYMED_NULL;
+ lpMyFormatEtc->cfFormat = NULL;
+ }
+
+errRtn:
+ return ReportResult(0, sc, 0, 0);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wValidateFormatEtcEx
+//
+// Synopsis: Validate the incoming formatetc and initialize the
+// out formatetc with the correct info
+//
+// Effects:
+//
+// Arguments: [renderopt] -- rendering option
+// [lpcFormats] -- the number of elements in rgFormatEtc
+// [rgFormatEtc] -- array of rendering formats
+// [lpFormatEtc] -- place to store valid formatetc if only one
+// [lplpFormatEtc] -- the out array of formatetcs
+// [lpfAlloced] -- place to store whether array was allocated
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Nov-93 alexgo 32bit port
+//
+// Notes: The original comments,
+//
+// Validate the lpFormatEtc that's been passed to the creation APIs. And then
+// initialize our formateEtc structure with the appropriate info.
+//
+// We allow NULL lpFormatEtc if the render option is olerender_draw
+// We ignore lpFormatEtc if the render option is olerender_none
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(wValidateFormatEtcEx)
+INTERNAL wValidateFormatEtcEx
+(
+ DWORD renderopt,
+ ULONG FAR* lpcFormats,
+ LPFORMATETC rgFormatEtc,
+ LPFORMATETC lpFormatEtc,
+ LPFORMATETC FAR* lplpFormatEtc,
+ LPBOOL lpfAlloced
+)
+{
+ LPFORMATETC lpfmtetc;
+
+ VDATEHEAP();
+
+ SCODE sc = S_OK;
+
+ *lplpFormatEtc = lpFormatEtc;
+ *lpfAlloced = FALSE;
+
+ if (renderopt == OLERENDER_NONE || renderopt == OLERENDER_ASIS)
+ return NOERROR;
+
+ if (renderopt != OLERENDER_FORMAT && renderopt != OLERENDER_DRAW) {
+ VdateAssert(renderopt, "Unexpected value for OLERENDER_ option");
+ return ResultFromScode(E_INVALIDARG);
+ }
+
+ if ((*lpcFormats != 0) != (rgFormatEtc != NULL))
+ return ResultFromScode(E_INVALIDARG);
+
+ if (*lpcFormats <= 1) {
+ if (*lpcFormats == 0)
+ *lpcFormats = 1;
+ return wValidateFormatEtc(renderopt, rgFormatEtc, lpFormatEtc);
+ }
+
+ *lplpFormatEtc = (LPFORMATETC)PubMemAlloc(*lpcFormats * sizeof(FORMATETC));
+ if (!*lplpFormatEtc)
+ return E_OUTOFMEMORY;
+
+ *lpfAlloced = TRUE;
+
+ for (ULONG i=0; i<*lpcFormats; i++)
+ {
+ lpfmtetc = &rgFormatEtc[i];
+
+ if (renderopt == OLERENDER_FORMAT)
+ {
+ if (!lpfmtetc->cfFormat) {
+ sc = E_INVALIDARG;
+ goto errRtn;
+ }
+
+ if (lpfmtetc->tymed !=
+ UtFormatToTymed(lpfmtetc->cfFormat)) {
+ sc = DV_E_TYMED;
+ goto errRtn;
+ }
+ }
+ else if (renderopt == OLERENDER_DRAW)
+ {
+ if (lpfmtetc->cfFormat != NULL) {
+ VdateAssert(lpfmtetc->cfFormat,"NON-NULL clipformat specified with OLERENDER_DRAW");
+ sc = DV_E_CLIPFORMAT;
+ goto errRtn;
+ }
+
+ if (lpfmtetc->tymed != TYMED_NULL) {
+ VdateAssert(lpfmtetc->tymed,"TYMED_NULL is not specified with OLERENDER_DRAW");
+ sc = DV_E_TYMED;
+ goto errRtn;
+ }
+ }
+
+ if (!HasValidLINDEX(lpfmtetc))
+ {
+ sc = DV_E_LINDEX;
+ goto errRtn;
+ }
+
+ VERIFY_ASPECT_SINGLE(lpfmtetc->dwAspect)
+
+ (*lplpFormatEtc)[i] = *lpfmtetc;
+ }
+
+errRtn:
+ if (sc != S_OK) {
+ PubMemFree(*lplpFormatEtc);
+ *lpfAlloced = FALSE;
+ }
+ return ReportResult(0, sc, 0, 0);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wQueryFormatSupport
+//
+// Synopsis: check to see whether we will be able to Get and SetData of
+// the given format
+//
+// Effects:
+//
+// Arguments: [lpObj] -- pointer to the object
+// [renderopt] -- rendering options
+// [lpFormatEtc] -- the formatetc in question
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Internal function, calls UtIsFormatSupported (which calls
+// EnumFormatEtc and checks all of the formats) if renderopt
+// is OLERENDER_FORMAT
+//
+// History: dd-mmm-yy Author Comment
+// 01-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(wQueryFormatSupport)
+INTERNAL wQueryFormatSupport
+ (LPVOID lpObj, DWORD renderopt, LPFORMATETC lpFormatEtc)
+{
+ VDATEHEAP();
+
+ IDataObject FAR* lpDataObj;
+ HRESULT error = NOERROR;
+
+ if (renderopt == OLERENDER_FORMAT)
+ {
+ if ((error = ((IUnknown FAR*) lpObj)->QueryInterface(
+ IID_IDataObject, (LPLPVOID)&lpDataObj)) == NOERROR)
+ {
+ if (!UtIsFormatSupported(lpDataObj,
+ DATADIR_GET | DATADIR_SET,
+ lpFormatEtc->cfFormat))
+ error = ResultFromScode(DV_E_CLIPFORMAT);
+
+ lpDataObj->Release();
+ }
+ }
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wGetMonikerAndClassFromObject
+//
+// Synopsis: Gets the moniker and class ID from the given object
+//
+// Effects:
+//
+// Arguments: [lpSrcDataObj] -- the data object
+// [lplpmkSrc] -- where to put a pointer to the moniker
+// [lpclsidLast] -- where to put the clsid
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Mar-95 alexgo added a hack for CorelDraw5
+// 01-Nov-93 alexgo 32bit port
+//
+// Notes: see also wGetMonikerAndClassFromFile
+//
+//--------------------------------------------------------------------------
+
+
+
+#pragma SEG(wGetMonikerAndClassFromObject)
+INTERNAL wGetMonikerAndClassFromObject(
+ LPDATAOBJECT lpSrcDataObj,
+ LPMONIKER FAR* lplpmkSrc,
+ CLSID FAR* lpclsidLast
+)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ FORMATETC foretcTmp;
+ STGMEDIUM medium;
+ LPMONIKER lpmkSrc = NULL;
+ LARGE_INTEGER large_integer;
+
+ INIT_FORETC(foretcTmp);
+ foretcTmp.cfFormat = g_cfLinkSource;
+ foretcTmp.tymed = TYMED_ISTREAM;
+
+ // 16bit OLE had a bug where the medium was uninitialized at this
+ // point. Corel5, when doing a paste-link to itself, actually
+ // checked the tymed and compared it with TYMED_NULL. So here
+ // we set the value to something recognizeable.
+ //
+ // NB! In the thunk layer, if we are *NOT* in Corel Draw, this
+ // value will be reset to TYMED_NULL.
+
+ if( IsWOWThread() )
+ {
+ medium.tymed = 0x66666666;
+ }
+ else
+ {
+ medium.tymed = TYMED_NULL;
+ }
+ medium.pstm = NULL;
+ medium.pUnkForRelease = NULL;
+
+ if ((error = lpSrcDataObj->GetData(&foretcTmp, &medium)) != NOERROR)
+ return ReportResult(0, OLE_E_CANT_GETMONIKER, 0, 0);
+
+ LISet32( large_integer, 0 );
+ if ((error = (medium.pstm)->Seek (large_integer, STREAM_SEEK_SET,
+ NULL)) != NOERROR)
+ goto FreeStgMed;
+
+ // get moniker from the stream
+ if ((error = OleLoadFromStream (medium.pstm, IID_IMoniker,
+ (LPLPVOID) lplpmkSrc)) != NOERROR)
+ goto FreeStgMed;
+
+ // read class stm; if error, use CLSID_NULL (for compatibility with
+ // prior times when the clsid was missing).
+ ReadClassStm(medium.pstm, lpclsidLast);
+
+FreeStgMed:
+ ReleaseStgMedium (&medium);
+ if (error != NOERROR)
+ return ReportResult(0, OLE_E_CANT_GETMONIKER, 0, 0);
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wDoLockUnlock
+//
+// Synopsis: tickles an object by locking and unlocking, used to resolve
+// ambiguities with stub manager locks
+//
+// Effects: the object may go away as a result of this call, if the
+// object is invisible and the lock count goes to zero as
+// a result of locking/unlocking.
+//
+// Arguments: [lpUnk] -- pointer to the object to lock/unlock
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(wDoLockUnlock)
+void wDoLockUnlock(IUnknown FAR* lpUnk)
+{
+ VDATEHEAP();
+
+ IRunnableObject FAR* pRO;
+
+ if (lpUnk->QueryInterface(IID_IRunnableObject, (LPLPVOID)&pRO)
+ == NOERROR)
+ { // increase lock count
+ if (pRO->LockRunning(TRUE, FALSE) == NOERROR)
+ // decrease lock count
+ pRO->LockRunning(FALSE, TRUE);
+ pRO->Release();
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wSaveObjectWithoutCommit
+//
+// Synopsis: Saves an object without committing (to preserve the
+// container's undo state)
+//
+// Effects:
+//
+// Arguments: [lpUnk] -- pointer to the object
+// [pstgSave] -- storage in which to save
+// [fSameAsLoad] -- indicates SaveAs operation
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL wSaveObjectWithoutCommit
+ (LPUNKNOWN lpUnk, LPSTORAGE pstgSave, BOOL fSameAsLoad)
+{
+ VDATEHEAP();
+
+ LPPERSISTSTORAGE pPS;
+ HRESULT error;
+ CLSID clsid;
+
+ if (error = lpUnk->QueryInterface(IID_IPersistStorage, (LPLPVOID)&pPS))
+ return error;
+
+ if (error = pPS->GetClassID(&clsid))
+ goto errRtn;
+
+ if (error = WriteClassStg(pstgSave, clsid))
+ goto errRtn;
+
+ if (error = pPS->Save(pstgSave, fSameAsLoad))
+ goto errRtn;
+
+ pPS->SaveCompleted(NULL);
+
+errRtn:
+ pPS->Release();
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wStuffIconOfFileEx
+//
+// Synopsis: Retrieves the icon if file [lpszFile] and stuffs it into
+// [lpUnk]'s cache
+//
+// Effects:
+//
+// Arguments: [lpszFile] -- the file where the icon is stored
+// [fAddLabel] -- if TRUE, adds a label to the icon
+// presentation
+// [renderopt] -- must be OLERENDER_DRAW or
+// OLERENDER_FORMAT for anything to happen
+// [cFormats] -- the number of elements in rgFormatEtc
+// [rgFormatEtc] -- array of rendering formats, aspect must be
+// DVASPECT_ICON and the clipboard format
+// must be NULL or CF_METAFILE for anything
+// to happen
+// [lpUnk] -- pointer to the object in which the icon
+// should be stuffed
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Nov-93 alexgo 32bit port
+//
+// Notes:
+// REVIEW32: maybe we should support enhanced metafiles for NT
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(wStuffIconOfFileEx)
+INTERNAL wStuffIconOfFileEx
+(
+ LPCOLESTR lpszFile,
+ BOOL fAddLabel,
+ DWORD renderopt,
+ ULONG cFormats,
+ LPFORMATETC rgFormatEtc,
+ LPUNKNOWN lpUnk
+)
+{
+ VDATEHEAP();
+
+ IOleCache FAR* lpOleCache;
+ HRESULT error;
+ BOOL fFound = FALSE;
+ FORMATETC foretc;
+ STGMEDIUM stgmed;
+
+ if (renderopt == OLERENDER_NONE || renderopt == OLERENDER_ASIS)
+ return NOERROR;
+
+ if (rgFormatEtc == NULL)
+ return NOERROR; // in this case we default to DVASPECT_CONTENT
+
+ for (ULONG i=0; i<cFormats; i++)
+ {
+ if ((rgFormatEtc[i].dwAspect == DVASPECT_ICON) &&
+ (rgFormatEtc[i].cfFormat == NULL ||
+ rgFormatEtc[i].cfFormat == CF_METAFILEPICT))
+ {
+ foretc = rgFormatEtc[i];
+ fFound = TRUE;
+ }
+ }
+
+ if (!fFound)
+ return NOERROR;
+
+ foretc.cfFormat = CF_METAFILEPICT;
+ foretc.tymed = TYMED_MFPICT;
+
+ if ((error = lpUnk->QueryInterface(IID_IOleCache,
+ (LPLPVOID) &lpOleCache)) != NOERROR)
+ return error;
+
+ stgmed.tymed = TYMED_MFPICT;
+ stgmed.pUnkForRelease = NULL;
+
+ // get icon data of file, from registration database
+ if (!(stgmed.hGlobal = OleGetIconOfFile((LPOLESTR) lpszFile,
+ fAddLabel))) {
+ error = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ // take ownership of the data
+ if ((error = lpOleCache->SetData(&foretc, &stgmed, TRUE)) != NOERROR)
+ ReleaseStgMedium(&stgmed);
+
+errRtn:
+ lpOleCache->Release();
+ return error;
+
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wNeedToPackage
+//
+// Synopsis: Determines whether or not a given CLSID should be
+// packaged.
+//
+// Effects:
+//
+// Arguments: [rclsid] -- the class ID
+//
+// Requires:
+//
+// Returns: BOOL
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Looks for the reg key PackageOnFileDrop, or if it's a
+// Word document, or if it is insertable, or if it's an OLE1
+// class
+//
+// History: dd-mmm-yy Author Comment
+// 02-Nov-93 alexgo 32bit port
+// 03-Jun-94 AlexT Just check for Insertable key (instead
+// of requiring a value)
+//
+// Notes:
+//--------------------------------------------------------------------------
+
+
+
+INTERNAL_(BOOL) wNeedToPackage(REFCLSID rclsid)
+{
+ VDATEHEAP();
+
+ HKEY hkeyClsid;
+ HKEY hkeyTmp;
+ HKEY hkeyTmp2;
+ BOOL fPackage = FALSE;
+ LPOLESTR lpszProgID;
+ DWORD dw;
+ LONG cbValue = sizeof(dw);
+ LONG lRet;
+ CLSID clsidNew;
+
+ if (NOERROR != OleGetAutoConvert (rclsid, &clsidNew))
+ {
+ if (NOERROR != CoGetTreatAsClass (rclsid, &clsidNew))
+ {
+ clsidNew = rclsid;
+ }
+ }
+
+ if (CoOpenClassKey(clsidNew, &hkeyClsid) != NOERROR)
+ return TRUE; // NON-OLE file, package it
+
+ if (ProgIDFromCLSID(clsidNew, &lpszProgID) == NOERROR) {
+ // see whether we can open this key
+
+ dw = (DWORD) RegOpenKey(HKEY_CLASSES_ROOT, lpszProgID,
+ &hkeyTmp);
+
+ PubMemFree(lpszProgID);
+
+ if (dw == ERROR_SUCCESS) {
+ // This is definitely a OLE insertable file.
+ lRet = RegOpenKey(hkeyTmp,
+ OLESTR("PackageOnFileDrop"),
+ &hkeyTmp2);
+ // Check whether we need to package this file
+ if (ERROR_SUCCESS == lRet)
+ {
+ RegCloseKey(hkeyTmp2);
+ fPackage = TRUE;
+ }
+ else if (IsEqualCLSID(clsidNew, CLSID_WordDocument))
+ {
+ // Hack to make sure Word documents are always
+ // Packaged on file drop. We write the key here
+ // so that we can say that a file is Packaged if
+ // and only if its ProgID has the "PackageOnFileDrop"
+ // key.
+ RegSetValue (hkeyTmp,
+ OLESTR("PackageOnFileDrop"),
+ REG_SZ, (LPOLESTR)NULL, 0);
+ fPackage = TRUE;
+ }
+
+ RegCloseKey(hkeyTmp);
+
+ if (fPackage) {
+ RegCloseKey(hkeyClsid);
+ return TRUE;
+ }
+ }
+ }
+
+ // There is no "PackageOnFileDrop" key defined.
+
+ // See whether this is an "Insertable" class by checking for the
+ // existence of the Insertable key - we don't require a value
+
+ lRet = RegOpenKey(hkeyClsid, OLESTR("Insertable"), &hkeyTmp);
+
+ if (ERROR_SUCCESS == lRet)
+ {
+ // Insertable key exists - close it and return
+ RegCloseKey(hkeyTmp);
+ goto errRtn;
+ }
+
+ //
+ // See whether this is a "Ole1Class" class by opening the
+ // registry key Ole1Class. We don't require a value
+ //
+ cbValue = sizeof(dw);
+ lRet = RegOpenKey(hkeyClsid,OLESTR("Ole1Class"),&hkeyTmp);
+ if (ERROR_SUCCESS == lRet)
+ {
+ RegCloseKey(hkeyTmp);
+ goto errRtn;
+ }
+ else
+ {
+ fPackage = TRUE;
+ }
+
+
+
+errRtn:
+ RegCloseKey(hkeyClsid);
+ return fPackage;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wDoUpdate
+//
+// Synopsis: calls IOleObject->Update() on the given object, internal
+// function
+//
+// Effects:
+//
+// Arguments: [lpUnkown] -- the object to update
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(wDoUpdate)
+INTERNAL wDoUpdate(IUnknown FAR* lpUnknown)
+{
+ VDATEHEAP();
+
+ HRESULT error = NOERROR;
+ IOleObject FAR* lpOle;
+
+ if (lpUnknown->QueryInterface (IID_IOleObject, (LPLPVOID)&lpOle)
+ == NOERROR) {
+ error = lpOle->Update();
+ lpOle->Release();
+ }
+
+ return error;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wBindIfRunning
+//
+// Synopsis: calls IOleLink->BindIfRunning() on the given object
+//
+// Effects:
+//
+// Arguments: [lpUnk] -- the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+INTERNAL_(void) wBindIfRunning(LPUNKNOWN lpUnk)
+{
+ VDATEHEAP();
+
+ IOleLink FAR* lpLink;
+
+ if (lpUnk->QueryInterface (IID_IOleLink, (LPLPVOID)&lpLink)
+ == NOERROR)
+ {
+ lpLink->BindIfRunning();
+ lpLink->Release();
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wQueryUseCustomLink
+//
+// Synopsis: look at the registry and see if the class ID has a custom
+// link regisetered
+//
+// Effects:
+//
+// Arguments: [rclsid] -- the class ID in question
+//
+// Requires:
+//
+// Returns: BOOL
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+INTERNAL_(BOOL) wQueryUseCustomLink(REFCLSID rclsid)
+{
+ VDATEHEAP();
+
+ // see whether it has Custom Link implementation
+ HKEY hkeyClsid;
+ HKEY hkeyTmp;
+ BOOL bUseCustomLink = FALSE;
+
+ if (SUCCEEDED(CoOpenClassKey(rclsid, &hkeyClsid)))
+ {
+ DWORD dw;
+ dw = RegOpenKey(hkeyClsid,OLESTR("UseCustomLink"),&hkeyTmp);
+
+ if (ERROR_SUCCESS == dw)
+ {
+ RegCloseKey(hkeyTmp);
+ bUseCustomLink = TRUE;
+ }
+
+ RegCloseKey(hkeyClsid);
+ }
+
+ return bUseCustomLink;
+}
+
diff --git a/private/ole32/ole232/base/daytona/makefile b/private/ole32/ole232/base/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/ole232/base/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/ole232/base/daytona/sources b/private/ole32/ole232/base/daytona/sources
new file mode 100644
index 000000000..9baa96fd7
--- /dev/null
+++ b/private/ole32/ole232/base/daytona/sources
@@ -0,0 +1,82 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = ole232
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= base
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..\..\inc
+INCLUDES= $(INCLUDES);$(BASEDIR)\private\dcomidl\obj
+
+C_DEFINES= \
+ $(C_DEFINES)
+
+
+SOURCES= \
+ ..\privstm.cpp \
+ ..\api.cpp \
+ ..\create.cpp \
+ ..\lockbyte.cpp \
+ ..\memstm.cpp \
+ ..\ole2.cpp
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
diff --git a/private/ole32/ole232/base/depend.mk b/private/ole32/ole232/base/depend.mk
new file mode 100644
index 000000000..4bfa5ade9
--- /dev/null
+++ b/private/ole32/ole232/base/depend.mk
@@ -0,0 +1,165 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\api.obj $(OBJDIR)\api.lst: .\api.cpp $(CAIROLE)\common\cobjerr.h \
+ $(CAIROLE)\common\rpcferr.h $(CAIROLE)\h\coguid.h \
+ $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h $(CAIROLE)\h\initguid.h \
+ $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h $(CAIROLE)\h\ole2dbg.h \
+ $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h $(CAIROLE)\h\storage.h \
+ $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h $(CAIROLE)\ih\ole2sp.h \
+ $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\wchar.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\widewrap.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winmm.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
+$(OBJDIR)\create.obj $(OBJDIR)\create.lst: .\create.cpp \
+ $(CAIROLE)\ih\ole1cls.h $(CAIROLE)\ole232\inc\create.h \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\fetcenum.obj $(OBJDIR)\fetcenum.lst: .\fetcenum.cpp \
+ $(CAIROLE)\ih\olerem.h $(CAIROLE)\ole232\inc\fetcenum.h \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\lockbyte.obj $(OBJDIR)\lockbyte.lst: .\lockbyte.cpp \
+ $(CAIROLE)\ole232\inc\memstm.h $(CAIROLE)\ole232\inc\reterr.h \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\memstm.obj $(OBJDIR)\memstm.lst: .\memstm.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\memstm.h $(CAIROLE)\ole232\inc\ole2int.h \
+ $(CAIROLE)\ole232\inc\reterr.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\ole2.obj $(OBJDIR)\ole2.lst: .\ole2.cpp $(CAIROLE)\h\ole2ver.h \
+ $(CAIROLE)\ole232\inc\clipbrd.h $(CAIROLE)\ole232\inc\taskmap.h \
+ $(CAIROLE)\ole232\inc\trace.h $(CAIROLE)\common\cobjerr.h \
+ $(CAIROLE)\common\rpcferr.h $(CAIROLE)\h\coguid.h \
+ $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h $(CAIROLE)\h\initguid.h \
+ $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h $(CAIROLE)\h\ole2dbg.h \
+ $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h $(CAIROLE)\h\storage.h \
+ $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h $(CAIROLE)\ih\ole2sp.h \
+ $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h $(CAIROLE)\ih\olerem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
diff --git a/private/ole32/ole232/base/dirs b/private/ole32/ole232/base/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/ole232/base/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/ole232/base/filelist.mk b/private/ole32/ole232/base/filelist.mk
new file mode 100644
index 000000000..4cd350f5c
--- /dev/null
+++ b/private/ole32/ole232/base/filelist.mk
@@ -0,0 +1,49 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = base.lib
+
+RELEASE = 1
+
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CPPFILES = .\api.cpp \
+ .\create.cpp \
+ .\fetcenum.cpp \
+ .\lockbyte.cpp \
+ .\memstm.cpp \
+ .\ole2.cpp
+
+CFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+DEFFILE =
+
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PFILE =
+
+!include $(CAIROLE)\ole232\ole.mk
diff --git a/private/ole32/ole232/base/lockbyte.cpp b/private/ole32/ole232/base/lockbyte.cpp
new file mode 100644
index 000000000..5c08f33f4
--- /dev/null
+++ b/private/ole32/ole232/base/lockbyte.cpp
@@ -0,0 +1,259 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: lockbyte.cpp
+//
+// Contents: Apis for working with the standard ILockByte implementation
+// on memory
+//
+// Classes:
+//
+// Functions: CreateILockBytesOnHGlobal
+// GetHGlobalFromILockBytes
+//
+// History: dd-mmm-yy Author Comment
+// 11-Jan-93 alexgo added VDATEHEAP macros to every function
+// fixed compile warnings
+// 16-Dec-93 alexgo fixed bad memory bugs
+// 02-Dec-93 alexgo 32bit port
+// 15-Sep-92 jasonful author
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#pragma SEG(lockbyte)
+
+#include "memstm.h"
+#include <reterr.h>
+
+NAME_SEG(LockBytes)
+ASSERTDATA
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateILockBytesOnHGlobal
+//
+// Synopsis: Creates a CMemBytes on the given HGlobal
+//
+// Effects:
+//
+// Arguments: [hGlobal] -- the memory to use (may be NULL)
+// [fDeleteOnRelease] -- if TRUE, then [hGlobal will
+// be freed when CMemBytes is
+// freed via a Release
+// [pplkbyt] -- where to put the pointer to the CMemByte
+// instance
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Jan-94 alexgo removed initialization of cbSize to -1
+// to fix a compile warning
+// 16-Dec-93 alexgo fixed bogus usage of MAKELONG (turned
+// into a GlobalLock)
+// 02-Dec-93 alexgo 32bit port, fixed memory leak bug
+//
+// Notes: REVIEW32: It's fine to *ask* for shared memory on NT, you
+// just won't get it. We need to make sure that any callers
+// (looks like apps at the moment) don't have the wrong idea :)
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CreateILockBytesOnHGlobal)
+STDAPI CreateILockBytesOnHGlobal
+ (HGLOBAL hGlobal,
+ BOOL fDeleteOnRelease,
+ LPLOCKBYTES FAR* pplkbyt)
+{
+ OLETRACEIN((API_CreateILockBytesOnHGlobal,
+ PARAMFMT("hGlobal= %h, fDeleteOnRelease= %B, pplkbyt= %p"),
+ hGlobal, fDeleteOnRelease, pplkbyt));
+
+ VDATEHEAP();
+
+ HANDLE hMem = NULL;
+ struct MEMSTM FAR* pData = NULL;
+ ILockBytes FAR* pBytes = NULL;
+ DWORD cbSize;
+ BOOL fAllochGlobal = FALSE;
+ HRESULT hresult;
+
+ VDATEPTRIN_LABEL (pplkbyt, LPLOCKBYTES, SafeExit, hresult);
+ *pplkbyt = NULL;
+
+ if (NULL==hGlobal)
+ {
+ hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
+ if (hGlobal == NULL)
+ {
+ goto ErrorExit;
+ }
+ fAllochGlobal = TRUE;
+
+ cbSize = 0;
+ }
+ else
+ {
+ cbSize = GlobalSize (hGlobal);
+ // Is there a way to verify a zero-sized handle?
+ if (cbSize!=0)
+ {
+ // verify validity of passed-in handle
+ if (NULL==GlobalLock(hGlobal))
+ {
+ // bad handle
+ hresult = ResultFromScode (E_INVALIDARG);
+ goto SafeExit;
+ }
+ GlobalUnlock (hGlobal);
+ }
+ }
+
+ hMem = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, sizeof (MEMSTM));
+ if (hMem == NULL)
+ {
+ goto ErrorExit;
+ }
+
+ pData = (MEMSTM FAR *)GlobalLock(hMem);
+
+ if (pData == NULL)
+ {
+ goto FreeMem;
+ }
+
+ pData->cRef = 0;
+ pData->cb = cbSize;
+ pData->fDeleteOnRelease = fDeleteOnRelease;
+ pData->hGlobal = hGlobal;
+
+ pBytes = CMemBytes::Create(hMem); // Create the ILockBytes
+
+ if (pBytes == NULL)
+ {
+ goto FreeMem;
+ }
+
+ *pplkbyt = pBytes;
+ GlobalUnlock(hMem);
+
+ CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_ILockBytes,
+ (IUnknown **)pplkbyt);
+
+ hresult = NOERROR;
+ goto SafeExit;
+
+FreeMem:
+ if (pData)
+ {
+ GlobalUnlock(hMem);
+ }
+ if (hMem)
+ {
+ GlobalFree(hMem);
+ }
+
+ if (fAllochGlobal && hGlobal )
+ {
+ GlobalFree(hGlobal);
+ }
+ErrorExit:
+ Assert (0);
+
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+
+SafeExit:
+ OLETRACEOUT((API_CreateILockBytesOnHGlobal, hresult));
+
+ return hresult;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetHGlobalFromILockBytes
+//
+// Synopsis: Retrieves the hGlobal the ILockBytes was created with
+//
+// Effects:
+//
+// Arguments: [plkbyt] -- pointer to the ILockBytes implementation
+// [phglobal] -- where to put the hglobal
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: hacked--does a pointer cast and checks the signature :( :(
+//
+// History: dd-mmm-yy Author Comment
+// 02-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(GetHGlobalFromILockBytes)
+STDAPI GetHGlobalFromILockBytes
+ (LPLOCKBYTES plkbyt,
+ HGLOBAL FAR* phglobal)
+{
+ OLETRACEIN((API_GetHGlobalFromILockBytes,
+ PARAMFMT("plkbyt= %p, phglobal= %p"),
+ plkbyt, phglobal));
+
+ VDATEHEAP();
+
+ HRESULT hresult;
+ CMemBytes FAR* pCMemByte;
+ MEMSTM FAR* pMem;
+
+ VDATEIFACE_LABEL(plkbyt, errRtn, hresult);
+ VDATEPTRIN_LABEL (phglobal, HANDLE, errRtn, hresult);
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_ILockBytes,(IUnknown **)&plkbyt);
+
+ *phglobal = NULL;
+ pCMemByte = (CMemBytes FAR*)plkbyt;
+
+ if (IsBadReadPtr (&(pCMemByte->m_dwSig), sizeof(ULONG))
+ || pCMemByte->m_dwSig != LOCKBYTE_SIG)
+ {
+ // we were passed someone else's implementation of ILockBytes
+ hresult = ResultFromScode (E_INVALIDARG);
+ goto errRtn;
+ }
+
+ pMem= pCMemByte->m_pData;
+ if (NULL==pMem)
+ {
+ Assert (0);
+ hresult = ResultFromScode (E_OUTOFMEMORY);
+ goto errRtn;
+ }
+ Assert (pMem->cb <= GlobalSize (pMem->hGlobal));
+ Verify (*phglobal = pMem->hGlobal);
+
+ hresult = NOERROR;
+
+errRtn:
+ OLETRACEOUT((API_GetHGlobalFromILockBytes, hresult));
+
+ return hresult;
+}
diff --git a/private/ole32/ole232/base/makefile b/private/ole32/ole232/base/makefile
new file mode 100644
index 000000000..1725b5e9a
--- /dev/null
+++ b/private/ole32/ole232/base/makefile
@@ -0,0 +1,26 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1992.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/ole232/base/memstm.cpp b/private/ole32/ole232/base/memstm.cpp
new file mode 100644
index 000000000..0d51bb817
--- /dev/null
+++ b/private/ole32/ole232/base/memstm.cpp
@@ -0,0 +1,3515 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: memstm.cpp
+//
+// Contents: Implementations of IStream and ILockBytes on memory
+// (versus the file system)
+//
+// Classes: CMemStm
+// CMemBytes
+// CMarshalMemStm
+// CMarshalMemBytes
+//
+// Functions: CreateMemStm
+// CloneMemStm
+// ReleaseMemStm
+// CreateStreamOnHGlobal
+// GetHGlobalFromStream
+// CMemStmUnMarshal
+// CMemBytesUnMarshall
+//
+// History: dd-mmm-yy Author Comment
+// 31-Jan-95 t-ScottH added Dump methods to CMemStm and CMemBytes
+// (_DEBUG only)
+// added DumpCMemStm and CMemBytes APIs
+// 04-Nov-94 ricksa Made CMemStm class multithread safe.
+// 24-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocation
+// 11-Jan-94 alexgo added VDATEHEAP macros to every function &
+// method, fixed compile warnings, removed
+// custom marshalling code. Memory streams
+// and ILockBytes now use standard
+// marshalling.
+// 16-Dec-93 alexgo fixed memory reference bugs (bad pointer)
+// 02-Dec-93 alexgo 32bit port, implement CMemStm::CopyTo
+// 11/22/93 - ChrisWe - replace overloaded ==, != with
+// IsEqualIID and IsEqualCLSID
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#pragma SEG(memstm)
+
+#include "memstm.h"
+#include "sem.hxx"
+#include <reterr.h>
+
+#ifdef _DEBUG
+#include "dbgdump.h"
+#endif // _DEBUG
+
+NAME_SEG(CMemStm)
+ASSERTDATA
+
+
+// Shared memory IStream implementation
+//
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::CMemStm
+//
+// Synopsis: constructor for memory stream
+//
+// Arguments: none
+//
+// History: 20-Dec-94 Rickhi moved from h file
+//
+//--------------------------------------------------------------------------
+CMemStm::CMemStm()
+{
+ // mutex automatically initialized
+ m_hMem = NULL;
+ m_pData = NULL;
+ m_pos = 0;
+ m_refs = 0;
+}
+
+CMemStm::~CMemStm()
+{
+ // empty destructor, mutex automatically cleaned up
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::QueryInterface
+//
+// Synopsis: retrieves the requested interface
+//
+// Effects:
+//
+// Arguments: [iidInterface] -- the requested interface ID
+// [ppvObj] -- where to put the interface pointer
+//
+// Requires:
+//
+// Returns: NOERROR, E_OUTOFMEMORY, E_NOINTERFACE
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IStream
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 04-Nov-94 ricksa Modified for multithreading
+// 11-Jan-94 alexgo removed QI for IMarshal so that
+// the standard marshaller is used.
+// This is fix marshalling across
+// process on 32bit platforms.
+// 02-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_QueryInterface)
+STDMETHODIMP CMemStm::QueryInterface(REFIID iidInterface,
+ void FAR* FAR* ppvObj)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+
+ VDATEPTROUT( ppvObj, LPVOID );
+ *ppvObj = NULL;
+ VDATEIID( iidInterface );
+
+ // Two interfaces supported: IUnknown, IStream
+
+ if (m_pData != NULL && (IsEqualIID(iidInterface, IID_IStream) ||
+ IsEqualIID(iidInterface, IID_IUnknown)))
+ {
+
+ AddRef(); // A pointer to this object is returned
+ *ppvObj = this;
+ error = NOERROR;
+ }
+#ifndef WIN32
+ else if (IsEqualIID(iidInterface, IID_IMarshal))
+ {
+ *ppvObj = (LPVOID) CMarshalMemStm::Create(this);
+
+ if (*ppvObj != NULL)
+ {
+ error = NOERROR;
+ }
+ else
+ {
+ error = ResultFromScode(E_OUTOFMEMORY);
+ }
+ }
+#endif
+ else
+ { // Not accessible or unsupported interface
+ *ppvObj = NULL;
+ error = ResultFromScode(E_NOINTERFACE);
+ }
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::AddRef
+//
+// Synopsis: increments the reference count
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IStream
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Dec-93 alexgo 32bit port
+// 04-Nov-94 ricksa Modified for multithreading
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_AddRef)
+STDMETHODIMP_(ULONG) CMemStm::AddRef(void)
+{
+ VDATEHEAP();
+
+ return InterlockedIncrement((LONG *) &m_refs);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::Release
+//
+// Synopsis: decrements the reference count
+//
+// Effects: deletes the object when ref count == 0
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new ref count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IStream
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 04-Nov-94 ricksa Modified for multithreading
+// 16-Dec-93 alexgo added GlobalUnlock of the MEMSTM handle
+// 02-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_Release)
+STDMETHODIMP_(ULONG) CMemStm::Release(void)
+{
+ VDATEHEAP();
+
+ // The reason for this here is that there is a race when releasing
+ // this object. If two threads are trying to release this object
+ // at the same time, there is a case where the first one dec's
+ // the ref count & then loses the processor to the second thread.
+ // This second thread decrements the reference count to 0 and frees
+ // the memory. The first thread can no longer safely examine the
+ // internal state of the object.
+ ULONG ulResult = InterlockedDecrement((LONG *) &m_refs);
+
+ if (ulResult == 0)
+ {
+ // this MEMSTM handle was GlobalLock'ed in ::Create
+ // we unlock it here, as we no longer need it.
+ GlobalUnlock(m_hMem);
+
+ ReleaseMemStm(&m_hMem);
+
+ delete this;
+ }
+
+ return ulResult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::Read
+//
+// Synopsis: reads [cb] bytes from the stream
+//
+// Effects:
+//
+// Arguments: [pb] -- where to put the data read
+// [cb] -- the number of bytes to read
+// [pcbRead] -- where to put the actual number of bytes
+// read
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IStream
+//
+// Algorithm: uses xmemcpy
+//
+// History: dd-mmm-yy Author Comment
+// 04-Nov-94 ricksa Modified for multithreading
+// 02-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_Read)
+STDMETHODIMP CMemStm::Read(void HUGEP* pb, ULONG cb, ULONG FAR* pcbRead)
+{
+ VDATEHEAP();
+
+ HRESULT error = NOERROR;
+ ULONG cbRead = cb;
+
+ VDATEPTROUT( pb, char);
+
+ // Single thread
+ CLock lck(m_mxs);
+
+ if (pcbRead)
+ {
+ VDATEPTROUT( pcbRead, ULONG );
+ *pcbRead = 0L;
+ }
+
+ if (pcbRead != NULL)
+ {
+ *pcbRead = 0;
+ }
+
+ if (cbRead + m_pos > m_pData->cb)
+ {
+ // Caller is asking for more bytes than we have left
+ cbRead = m_pData->cb - m_pos;
+ }
+
+ if (cbRead > 0)
+ {
+ Assert (m_pData->hGlobal);
+ BYTE HUGEP* pGlobal = (BYTE HUGEP *)GlobalLock(
+ m_pData->hGlobal);
+ if (NULL==pGlobal)
+ {
+ LEERROR(1, "GlobalLock Failed!");
+
+ return ResultFromScode (STG_E_READFAULT);
+ }
+ // overlap is currently considered a bug (see the discussion
+ // on the Write method
+ _xmemcpy(pb, pGlobal + m_pos, cbRead);
+ GlobalUnlock (m_pData->hGlobal);
+ m_pos += cbRead;
+ }
+
+ if (pcbRead != NULL)
+ {
+ *pcbRead = cbRead;
+ }
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::Write
+//
+// Synopsis: Writes [cb] bytes into the stream
+//
+// Effects:
+//
+// Arguments: [pb] -- the bytes to write
+// [cb] -- the number of bytes to write
+// [pcbWritten] -- where to put the number of bytes written
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IStream
+//
+// Algorithm: resizes the internal buffer (if needed), then uses xmemcpy
+//
+// History: dd-mmm-yy Author Comment
+// 04-Nov-94 ricksa Modified for multithreading
+// 02-Dec-93 alexgo 32bit port, fixed bug dealing with
+// 0-byte sized memory
+// 06-Dec-93 alexgo handle overlap case.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_Write)
+STDMETHODIMP CMemStm::Write(void const HUGEP* pb, ULONG cb,
+ ULONG FAR* pcbWritten)
+{
+ VDATEHEAP();
+
+ HRESULT error = NOERROR;
+ ULONG cbWritten = cb;
+ ULARGE_INTEGER ularge_integer;
+ BYTE HUGEP* pGlobal;
+
+ VDATEPTRIN( pb , char );
+
+ // Single thread
+ CLock lck(m_mxs);
+
+ if (pcbWritten != NULL)
+ {
+ *pcbWritten = 0;
+ }
+
+ if (cbWritten + m_pos > m_pData->cb)
+ {
+ ULISet32( ularge_integer, m_pos+cbWritten );
+ error = SetSize(ularge_integer);
+ if (error != NOERROR)
+ {
+ goto Exit;
+ }
+ }
+
+ // we don't write anything if 0 bytes are asked for for two
+ // reasons: 1. optimization, 2. m_pData->hGlobal could be a
+ // handle to a zero-byte memory block, in which case GlobalLock
+ // will fail.
+
+ if( cbWritten > 0 )
+ {
+ pGlobal = (BYTE HUGEP *)GlobalLock (m_pData->hGlobal);
+ if (NULL==pGlobal)
+ {
+ LEERROR(1, "GlobalLock Failed!");
+
+ return ResultFromScode (STG_E_WRITEFAULT);
+ }
+
+ // we use memmove here instead of memcpy to handle the
+ // overlap case. Recall that the app originally gave
+ // use the memory for the memstm. He could (either through
+ // a CopyTo or through really strange code), be giving us
+ // this region to read from, so we have to handle the overlapp
+ // case. The same argument also applies for Read, but for
+ // now, we'll consider overlap on Read a bug.
+ _xmemmove(pGlobal + m_pos, pb, cbWritten);
+ GlobalUnlock (m_pData->hGlobal);
+
+ m_pos += cbWritten;
+ }
+
+ if (pcbWritten != NULL)
+ {
+ *pcbWritten = cbWritten;
+ }
+
+Exit:
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::Seek
+//
+// Synopsis: Moves the internal seek pointer
+//
+// Effects:
+//
+// Arguments: [dlibMoveIN] -- the amount to move by
+// [dwOrigin] -- flags to control whether seeking is
+// relative to the current postion or
+// the begging/end.
+// [plibNewPosition] -- where to put the new position
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IStream
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 04-Nov-94 ricksa Modified for multithreading
+// 02-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_Seek)
+STDMETHODIMP CMemStm::Seek(LARGE_INTEGER dlibMoveIN, DWORD dwOrigin,
+ ULARGE_INTEGER FAR* plibNewPosition)
+{
+ VDATEHEAP();
+
+ HRESULT error = NOERROR;
+ LONG dlibMove = dlibMoveIN.LowPart ;
+ ULONG cbNewPos = dlibMove;
+
+ // Single thread
+ CLock lck(m_mxs);
+
+ if (plibNewPosition != NULL)
+ {
+ VDATEPTROUT( plibNewPosition, ULONG );
+ ULISet32(*plibNewPosition, m_pos);
+ }
+
+ switch(dwOrigin)
+ {
+
+ case STREAM_SEEK_SET:
+ if (dlibMove >= 0)
+ {
+ m_pos = dlibMove;
+ }
+ else
+ {
+ error = ResultFromScode(STG_E_SEEKERROR);
+ }
+
+ break;
+
+ case STREAM_SEEK_CUR:
+ if (!(dlibMove < 0 && ((ULONG) -dlibMove) > m_pos))
+ {
+ m_pos += dlibMove;
+ }
+ else
+ {
+ error = ResultFromScode(STG_E_SEEKERROR);
+ }
+ break;
+
+ case STREAM_SEEK_END:
+ if (!(dlibMove < 0 && ((ULONG) -dlibMove) > m_pData->cb))
+ {
+ m_pos = m_pData->cb + dlibMove;
+ }
+ else
+ {
+ error = ResultFromScode(STG_E_SEEKERROR);
+ }
+ break;
+
+ default:
+ error = ResultFromScode(STG_E_SEEKERROR);
+ }
+
+ if (plibNewPosition != NULL)
+ {
+ ULISet32(*plibNewPosition, m_pos);
+ }
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::SetSize
+//
+// Synopsis: Sets the size of our memory
+//
+// Effects:
+//
+// Arguments: [cb] -- the new size
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IStream
+//
+// Algorithm: calls GlobalRealloc
+//
+// History: dd-mmm-yy Author Comment
+// 04-Nov-94 ricksa Modified for multithreading
+// 02-Dec-93 alexgo 32bit port, added assert
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_SetSize)
+STDMETHODIMP CMemStm::SetSize(ULARGE_INTEGER cb)
+{
+ VDATEHEAP();
+
+ HANDLE hMemNew;
+
+ // Single thread
+ CLock lck(m_mxs);
+
+ // make sure we aren't in overflow conditions.
+
+ AssertSz(cb.HighPart == 0,
+ "MemStream::More than 2^32 bytes asked for");
+
+ if (m_pData->cb == cb.LowPart)
+ {
+ return NOERROR;
+ }
+
+ hMemNew = GlobalReAlloc(m_pData->hGlobal, max (cb.LowPart,1),
+ GMEM_SHARE | GMEM_MOVEABLE);
+
+ if (hMemNew == NULL)
+ {
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+
+ m_pData->hGlobal = hMemNew;
+ m_pData->cb = cb.LowPart;
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::CopyTo
+//
+// Synopsis: Copies data from [this] stream to [pstm]
+//
+// Effects:
+//
+// Arguments: [pstm] -- the stream to copy to
+// [cb] -- the number of bytes to copy
+// [pcbRead] -- where to return the number of bytes read
+// [pcbWritten] -- where to return the number of bytes written
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IStream
+//
+// Algorithm: does an IStream->Write to the given stream
+//
+// History: dd-mmm-yy Author Comment
+// 04-Nov-94 ricksa Modified for multithreading
+// 03-Dec-93 alexgo original implementation
+//
+// Notes: This implementation assumes that the address space
+// is not greater than ULARGE_INTEGER.LowPart (which is
+// for for 32bit operating systems). 64bit NT may need
+// to revisit this code.
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_CopyTo)
+STDMETHODIMP CMemStm::CopyTo(IStream FAR *pstm, ULARGE_INTEGER cb,
+ ULARGE_INTEGER FAR * pcbRead, ULARGE_INTEGER FAR * pcbWritten)
+{
+ VDATEHEAP();
+
+ ULONG cbRead = cb.LowPart;
+ ULONG cbWritten = 0;
+ HRESULT hresult = NOERROR;
+
+ // pstm cannot be NULL
+
+ VDATEPTRIN(pstm, LPSTREAM);
+
+ // Single thread
+ CLock lck(m_mxs);
+
+ // the spec says that if cb is it's maximum value (all bits set,
+ // since it's unsigned), then we will simply read the copy of
+ // this stream
+
+ if ( ~(cb.LowPart) == 0 && ~(cb.HighPart) == 0 )
+ {
+ cbRead = m_pData->cb - m_pos;
+ }
+ else if ( cb.HighPart > 0 )
+ {
+ // we assume that our memory stream cannot
+ // be large enough to accomodate very large (>32bit)
+ // copy to requests. Since this is probably an error
+ // on the caller's part, we assert.
+
+ AssertSz(0, "WARNING: CopyTo request exceeds 32 bits");
+
+ // set the Read value to what's left, so that "Ignore"ing
+ // the assert works properly.
+
+ cbRead = m_pData->cb - m_pos;
+ }
+ else if ( cbRead + m_pos > m_pData->cb )
+ {
+ // more bytes were requested to read than we had left.
+ // cbRead is set to the amount remaining.
+
+ cbRead = m_pData->cb - m_pos;
+ }
+
+ // now write the data to the stream
+
+ if ( cbRead > 0 )
+ {
+ BYTE HUGEP* pGlobal = (BYTE HUGEP *)GlobalLock(
+ m_pData->hGlobal);
+
+ if( pGlobal == NULL )
+ {
+ LEERROR(1, "GlobalLock failed");
+
+ return ResultFromScode(STG_E_INSUFFICIENTMEMORY);
+ }
+
+ hresult = pstm->Write(pGlobal + m_pos, cbRead, &cbWritten);
+
+ // in the error case, the spec says that the return values
+ // may be meaningless, so we do not need to do any special
+ // error handling here
+
+ GlobalUnlock(m_pData->hGlobal);
+ }
+
+ // increment our seek pointer and set the out parameters
+
+ m_pos += cbRead;
+
+ if( pcbRead )
+ {
+ ULISet32(*pcbRead, cbRead);
+ }
+
+ if( pcbWritten )
+ {
+ ULISet32(*pcbWritten, cbWritten);
+ }
+
+ return hresult;
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::Commit
+//
+// Synopsis: Does nothing, no transactions available on memory streams
+//
+// Effects:
+//
+// Arguments: [grfCommitFlags]
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IStream
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 03-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_Commit)
+STDMETHODIMP CMemStm::Commit(DWORD grfCommitFlags)
+{
+ VDATEHEAP();
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::Revert
+//
+// Synopsis: does nothing, as no transactions are supported on memory
+// streams
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IStream
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 03-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_Revert)
+STDMETHODIMP CMemStm::Revert(void)
+{
+ VDATEHEAP();
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::LockRegion
+//
+// Synopsis: not supported in OLE2.01
+//
+// Effects:
+//
+// Arguments: [libOffset]
+// [cb]
+// [dwLockType]
+//
+// Requires:
+//
+// Returns: STG_E_INVALIDFUNCTION
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IStream
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 03-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_LockRegion)
+STDMETHODIMP CMemStm::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ VDATEHEAP();
+
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::UnlockRegion
+//
+// Synopsis: not implemented for OLE2.01
+//
+// Effects:
+//
+// Arguments: [libOffset]
+// [cb]
+// [dwLockType]
+//
+// Requires:
+//
+// Returns: STG_E_INVALIDFUNCTION
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IStream
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 03-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_UnlockRegion)
+STDMETHODIMP CMemStm::UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb, DWORD dwLockType)
+{
+ VDATEHEAP();
+
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::Stat
+//
+// Synopsis: Returns info about this stream
+//
+// Effects:
+//
+// Arguments: [pstatstg] -- the STATSTG to fill with info
+// [statflag] -- status flags, unused
+//
+// Requires:
+//
+// Returns: NOERROR, E_INVALIDARG
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IStream
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 03-Dec-93 alexgo 32bit port
+// 01-Jun-94 AlexT Set type correctly
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_Stat)
+STDMETHODIMP CMemStm::Stat(STATSTG FAR *pstatstg, DWORD statflag)
+{
+ VDATEHEAP();
+
+ VDATEPTROUT( pstatstg, STATSTG );
+
+ memset ( pstatstg, 0, sizeof(STATSTG) );
+
+ pstatstg->type = STGTY_STREAM;
+ pstatstg->cbSize.LowPart = m_pData->cb;
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::Clone
+//
+// Synopsis: creates a new instance of this stream pointing to the
+// same data at the same position (same seek pointer)
+//
+// Effects:
+//
+// Arguments: [ppstm] -- where to put the new CMemStm pointer
+//
+// Requires:
+//
+// Returns: NOERROR, E_OUTOFMEMORY
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IStream
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 03-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_Clone)
+STDMETHODIMP CMemStm::Clone(IStream FAR * FAR *ppstm)
+{
+ VDATEHEAP();
+
+ CMemStm FAR* pCMemStm;
+
+ VDATEPTROUT (ppstm, LPSTREAM);
+
+ *ppstm = pCMemStm = CMemStm::Create(m_hMem);
+
+ if (pCMemStm == NULL)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ pCMemStm->m_pos = m_pos;
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::Create
+//
+// Synopsis: Creates a new CMemStm. [hMem] must be a handle to a MEMSTM
+// block.
+//
+// Effects:
+//
+// Arguments: [hMem] -- handle to a MEMSTM block
+//
+// Requires:
+//
+// Returns: CMemStm *
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Dec-93 alexgo fixed memory access bug
+// 03-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemStm_Create)
+STDSTATICIMP_(CMemStm FAR*) CMemStm::Create(HANDLE hMem)
+{
+ VDATEHEAP();
+
+ CMemStm FAR* pCMemStm = NULL;
+ struct MEMSTM FAR* pData;
+
+ pData = (MEMSTM FAR*) GlobalLock(hMem);
+
+ if (pData != NULL)
+ {
+ pCMemStm = new CMemStm;
+
+ if (pCMemStm != NULL)
+ {
+ // Initialize CMemStm
+ pCMemStm->m_hMem = hMem;
+ (pCMemStm->m_pData = pData)->cRef++; // AddRefMemStm
+ pCMemStm->m_refs = 1;
+ pCMemStm->m_dwSig = STREAM_SIG;
+ }
+ else
+ {
+ // uh-oh, low on memory
+ GlobalUnlock(hMem);
+ }
+ }
+
+ // we do *not* unlock the memory now, the memstm structure should
+ // be locked for the lifetime of any CMemStm's that refer to it.
+ // when the CMemStm is destroyed, we will release our lock on
+ // hMem.
+
+ return pCMemStm;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemStm::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppsz] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 20-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CMemStm::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszMEMSTM;
+ char *pszCMutexSem;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(400);
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "Impl. Signature = " << m_dwSig << endl;
+
+ dstrDump << pszPrefix << "No. of References = " << m_refs << endl;
+
+ dstrDump << pszPrefix << "Seek pointer = " << m_pos << endl;
+
+ dstrDump << pszPrefix << "Memory handle = " << m_hMem << endl;
+
+ if (m_pData != NULL)
+ {
+ pszMEMSTM = DumpMEMSTM(m_pData, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "MEMSTM:" << endl;
+ dstrDump << pszMEMSTM;
+ CoTaskMemFree(pszMEMSTM);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "MEMSTM = " << m_pData << endl;
+ }
+
+ pszCMutexSem = DumpCMutexSem(&m_mxs);
+ dstrDump << pszPrefix << "Mutex = " << pszCMutexSem << endl;
+ CoTaskMemFree(pszCMutexSem);
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCMemStm, public (_DEBUG only)
+//
+// Synopsis: calls the CMemStm::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pMS] - pointer to CMemStm
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 20-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCMemStm(CMemStm *pMS, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pMS == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pMS->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateMemStm
+//
+// Synopsis: Allocates memory and creates a CMemStm for it.
+//
+// Effects:
+//
+// Arguments: [cb] -- the number of bytes to allocate
+// [phMem] -- where to put a handle to the MEMSTM structure
+//
+// Requires:
+//
+// Returns: LPSTREAM to the CMemStream
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 03-Dec-93 alexgo 32bit port
+//
+// Notes: phMem must be free'd with ReleaseMemStm (because of ref
+// counting and the nested handle)
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CreateMemStm)
+STDAPI_(LPSTREAM) CreateMemStm(DWORD cb, LPHANDLE phMem)
+{
+ VDATEHEAP();
+
+ HANDLE h;
+ LPSTREAM pstm = NULL;
+
+ if (phMem)
+ {
+ *phMem = NULL;
+ }
+
+ h = GlobalAlloc (GMEM_SHARE | GMEM_MOVEABLE, cb);
+ if (NULL==h)
+ {
+ return NULL;
+ }
+
+ if (CreateStreamOnHGlobal (h, TRUE, &pstm) != NOERROR)
+ {
+ return NULL;
+ }
+ if (phMem)
+ {
+ // retrieve handle from just-created CMemStm
+ *phMem = ((CMemStm FAR*)pstm)->m_hMem;
+
+ // use pointer to bump ref count
+ Assert(((CMemStm FAR*)pstm)->m_pData != NULL);
+ ((CMemStm FAR*)pstm)->m_pData->cRef++; // AddRefMemStm
+ }
+ return pstm;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CloneMemStm
+//
+// Synopsis: Clones a memory stream
+//
+// Effects:
+//
+// Arguments: [hMem] -- a handle to the MEMSTM block
+//
+// Requires:
+//
+// Returns: LPSTREAM
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+#pragma SEG(CloneMemStm)
+
+STDAPI_(LPSTREAM) CloneMemStm(HANDLE hMem)
+{
+ VDATEHEAP();
+
+ return CMemStm::Create(hMem); // Create the stream
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReleaseMemStm
+//
+// Synopsis: Releases the memory used by a MEMSTM structure (including
+// the nested handle)
+//
+// Effects:
+//
+// Arguments: [phMem] -- pointer the MEMSTM handle
+// [fInternalOnly] -- if TRUE, then only the actual memory
+// that MEMSTM refers to is freed
+// (not the MEMSTM structure itself)
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies: sets *phMem to NULL on success
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port and fixed bad memory access
+// bug
+//
+// Notes: REVIEW32: look at taking out the second argument
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(ReleaseMemStm)
+STDAPI_(void) ReleaseMemStm (LPHANDLE phMem, BOOL fInternalOnly)
+{
+ VDATEHEAP();
+
+ struct MEMSTM FAR* pData;
+
+ pData = (MEMSTM FAR*) GlobalLock(*phMem);
+
+ // check for NULL pointer in case handle got freed already
+ // decrement ref count and free if no refs left
+ if (pData != NULL && --pData->cRef == 0)
+ {
+ if (pData->fDeleteOnRelease)
+ {
+ Verify (0==GlobalFree (pData->hGlobal));
+ }
+
+ if (!fInternalOnly)
+ {
+ GlobalUnlock(*phMem);
+ Verify (0==GlobalFree(*phMem));
+ goto End;
+ }
+ }
+
+ GlobalUnlock(*phMem);
+End:
+ *phMem = NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateStreamOnHGlobal
+//
+// Synopsis: Creates a CMemStm from the given hGlobal (if [hGlobal] is
+// NULL, we allocate a zero byte one)
+//
+// Effects:
+//
+// Arguments: [hGlobal] -- the memory
+// [fDeleteOnRelease] -- whether the memory should be
+// release on delete
+// [ppstm] -- where to put the stream
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Jan-93 alexgo removed initialization of cbSize to -1
+// to fix compile warning
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CreateStreamOnHGlobal)
+STDAPI CreateStreamOnHGlobal(HANDLE hGlobal, BOOL fDeleteOnRelease,
+ LPSTREAM FAR* ppstm)
+{
+ OLETRACEIN((API_CreateStreamOnHGlobal, PARAMFMT("hGlobal= %h, fDeleteOnRelease= %B, ppstm= %p"),
+ hGlobal, fDeleteOnRelease, ppstm));
+
+ VDATEHEAP();
+
+ HANDLE hMem = NULL;
+ struct MEMSTM FAR* pData = NULL;
+ LPSTREAM pstm = NULL;
+ DWORD cbSize;
+ HRESULT hresult;
+
+ VDATEPTRIN_LABEL (ppstm, LPSTREAM, SafeExit, hresult);
+
+ *ppstm = NULL;
+ if (NULL==hGlobal)
+ {
+ hGlobal = GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, 0);
+ if (hGlobal == NULL)
+ {
+ goto ErrorExit;
+ }
+ cbSize = 0;
+ }
+ else
+ {
+ cbSize = GlobalSize (hGlobal);
+ // Is there a way to verify a zero-sized handle?
+ // we currently do no verification for them
+ if (cbSize!=0)
+ {
+ // verify validity of passed-in handle
+ if (NULL==GlobalLock(hGlobal))
+ {
+ // bad handle
+ hresult = ResultFromScode (E_INVALIDARG);
+ goto SafeExit;
+ }
+ GlobalUnlock (hGlobal);
+ }
+ }
+
+ hMem = GlobalAlloc (GMEM_SHARE | GMEM_MOVEABLE, sizeof (MEMSTM));
+ if (hMem == NULL)
+ {
+ goto ErrorExit;
+ }
+
+ pData = (MEMSTM FAR*) GlobalLock(hMem);
+
+ if (pData == NULL)
+ {
+ GlobalUnlock(hMem);
+ goto FreeMem;
+ }
+
+ pData->cRef = 0;
+ pData->cb = cbSize;
+ pData->fDeleteOnRelease = fDeleteOnRelease;
+ pData->hGlobal = hGlobal;
+ GlobalUnlock(hMem);
+
+ pstm = CMemStm::Create(hMem);
+
+ if (pstm == NULL)
+ {
+ goto FreeMem;
+ }
+
+ *ppstm = pstm;
+
+ CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)ppstm);
+ hresult = NOERROR;
+ goto SafeExit;
+
+FreeMem:
+ if (hMem)
+ {
+ Verify(0==GlobalFree(hMem));
+ }
+ErrorExit:
+
+ LEERROR(1, "Out of memory!");
+
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+
+SafeExit:
+
+ OLETRACEOUT((API_CreateStreamOnHGlobal, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetHGlobalFromStream
+//
+// Synopsis: Retrieves the HGLOBAL to the memory from the given stream
+// pointer (must be a pointer to a CMemByte structure)
+//
+// Effects:
+//
+// Arguments: [pstm] -- pointer to the CMemByte
+// [phglobal] -- where to put the hglobal
+//
+// Requires:
+//
+// Returns: HRESULT (E_INVALIDARG, E_OUTOFMEMORY, NOERROR)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(GetHGlobalFromStream)
+STDAPI GetHGlobalFromStream(LPSTREAM pstm, HGLOBAL FAR* phglobal)
+{
+ OLETRACEIN((API_GetHGlobalFromStream, PARAMFMT("pstm= %p, phglobal= %p"),
+ pstm, phglobal));
+
+ VDATEHEAP();
+
+ HRESULT hresult;
+ CMemStm FAR* pCMemStm;
+ MEMSTM FAR* pMem;
+
+ VDATEIFACE_LABEL (pstm, errRtn, hresult);
+ VDATEPTRIN_LABEL (phglobal, HANDLE, errRtn, hresult);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pstm);
+
+ pCMemStm = (CMemStm FAR*) pstm;
+
+ if (IsBadReadPtr (&(pCMemStm->m_dwSig), sizeof(ULONG))
+ || pCMemStm->m_dwSig != STREAM_SIG)
+ {
+ // we were passed someone else's implementation of ILockBytes
+ hresult = ResultFromScode (E_INVALIDARG);
+ goto errRtn;
+ }
+
+ pMem= pCMemStm->m_pData;
+ if (NULL==pMem)
+ {
+ LEERROR(1, "Out of memory!");
+
+ hresult = ResultFromScode (E_OUTOFMEMORY);
+ goto errRtn;
+ }
+ Assert (pMem->cb <= GlobalSize (pMem->hGlobal));
+ Verify (*phglobal = pMem->hGlobal);
+
+ hresult = NOERROR;
+
+errRtn:
+ OLETRACEOUT((API_GetHGlobalFromStream, hresult));
+
+ return hresult;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Shared memory ILockBytes implementation
+//
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemBytes::QueryInterface
+//
+// Synopsis: returns the requested interface pointer
+//
+// Effects: a CMarshalMemBytes will be created if IID_IMarshal is
+// requested
+//
+// Arguments: [iidInterface] -- the requested interface ID
+// [ppvObj] -- where to put the interface pointer
+//
+// Requires:
+//
+// Returns: NOERROR, E_OUTOFMEMORY, E_NOINTERFACE
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: ILockBytes
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Jan-94 alexgo removed QI for IMarshal so that
+// the standard marshaller will be used.
+// This is to enable correct operation on
+// 32bit platforms.
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemBytes_QueryInterface)
+STDMETHODIMP CMemBytes::QueryInterface(REFIID iidInterface,
+ void FAR* FAR* ppvObj)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+
+ VDATEPTROUT( ppvObj, LPVOID );
+ *ppvObj = NULL;
+ VDATEIID( iidInterface );
+
+ if (m_pData != NULL && (IsEqualIID(iidInterface, IID_ILockBytes) ||
+ IsEqualIID(iidInterface, IID_IUnknown)))
+ {
+ m_refs++; // A pointer to this object is returned
+ *ppvObj = this;
+ error = NOERROR;
+ }
+
+ // this is not an else if because m_pData can be NULL and we
+ // allow creating a CMarshalMemBytes. REVIEW32: We may want
+ // to remove this behavior.
+
+#ifndef WIN32
+ if (IsEqualIID(iidInterface, IID_IMarshal))
+ {
+ *ppvObj = (LPVOID) CMarshalMemBytes::Create(this);
+ if (*ppvObj != NULL)
+ {
+ error = NOERROR;
+ }
+ else
+ {
+ error = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ }
+#endif
+ else
+ {
+ *ppvObj = NULL;
+ error = ResultFromScode(E_NOINTERFACE);
+ }
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemBytes::AddRef
+//
+// Synopsis: Incrememts the reference count
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: ILockBytes
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CMemBytes::AddRef(void)
+{
+ VDATEHEAP();
+
+ return ++m_refs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemBytes::Release
+//
+// Synopsis: decrements the reference count
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: ILockBytes
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-93 alexgo added GlobalUnlock to match the Global
+// Lock in Create
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CMemBytes::Release(void)
+{
+ VDATEHEAP();
+
+ if (--m_refs != 0)
+ {
+ return m_refs;
+ }
+
+ // GlobalUnlock the m_hMem that we GlobalLocke'd in Create
+ GlobalUnlock(m_hMem);
+
+ ReleaseMemStm(&m_hMem);
+
+ delete this;
+ return 0;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemBytes::ReadAt
+//
+// Synopsis: reads [cb] bytes from starting position [ulOffset]
+//
+// Effects:
+//
+// Arguments: [ulOffset] -- the offset to start reading from
+// [pb] -- where to put the data
+// [cb] -- the number of bytes to read
+// [pcbRead] -- where to put the number of bytes actually
+// read
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: ILockBytes
+//
+// Algorithm: just calls xmemcpy
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemBytes_ReadAt)
+STDMETHODIMP CMemBytes::ReadAt(ULARGE_INTEGER ulOffset, void HUGEP* pb,
+ ULONG cb, ULONG FAR* pcbRead)
+{
+ VDATEHEAP();
+
+ HRESULT error = NOERROR;
+ ULONG cbRead = cb;
+
+ VDATEPTROUT( pb, char );
+
+ // make sure we don't offset out of the address space!
+ AssertSz(ulOffset.HighPart == 0,
+ "CMemBytes: offset greater than 2^32");
+
+ if (pcbRead)
+ {
+ *pcbRead = 0L;
+ }
+
+ if (cbRead + ulOffset.LowPart > m_pData->cb)
+ {
+
+ if (ulOffset.LowPart > m_pData->cb)
+ {
+ // the offset overruns the size of the memory
+ cbRead = 0;
+ }
+ else
+ {
+ // just read what's left
+ cbRead = m_pData->cb - ulOffset.LowPart;
+ }
+ }
+
+ if (cbRead > 0)
+ {
+ BYTE HUGEP* pGlobal = (BYTE HUGEP *)GlobalLock(
+ m_pData->hGlobal);
+ if (NULL==pGlobal)
+ {
+ LEERROR(1, "GlobalLock failed!");
+
+ return ResultFromScode (STG_E_READFAULT);
+ }
+ _xmemcpy(pb, pGlobal + ulOffset.LowPart, cbRead);
+ GlobalUnlock (m_pData->hGlobal);
+ }
+
+ if (pcbRead != NULL)
+ {
+ *pcbRead = cbRead;
+ }
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemBytes::WriteAt
+//
+// Synopsis: writes [cb] bytes at [ulOffset] in the stream
+//
+// Effects:
+//
+// Arguments: [ulOffset] -- the offset at which to start writing
+// [pb] -- the buffer to read from
+// [cb] -- the number of bytes to write
+// [pcbWritten] -- where to put the number of bytes written
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: ILockBytes
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemBytes_WriteAt)
+STDMETHODIMP CMemBytes::WriteAt(ULARGE_INTEGER ulOffset, void const HUGEP* pb,
+ ULONG cb, ULONG FAR* pcbWritten)
+{
+ VDATEHEAP();
+
+ HRESULT error = NOERROR;
+ ULONG cbWritten = cb;
+ BYTE HUGEP* pGlobal;
+
+ VDATEPTRIN( pb, char );
+
+ // make sure the offset doesn't go beyond our address space!
+
+ AssertSz(ulOffset.HighPart == 0, "WriteAt, offset greater than 2^32");
+
+ if (pcbWritten)
+ {
+ *pcbWritten = 0;
+ }
+
+ if (cbWritten + ulOffset.LowPart > m_pData->cb)
+ {
+ ULARGE_INTEGER ularge_integer;
+ ULISet32( ularge_integer, ulOffset.LowPart + cbWritten);
+ error = SetSize( ularge_integer );
+ if (error != NOERROR)
+ {
+ goto Exit;
+ }
+ }
+
+ // CMemBytes does not allow zero-sized memory handles
+
+ pGlobal = (BYTE HUGEP *)GlobalLock (m_pData->hGlobal);
+
+ if (NULL==pGlobal)
+ {
+ LEERROR(1, "GlobalLock failed!");
+
+ return ResultFromScode (STG_E_WRITEFAULT);
+ }
+
+ _xmemcpy(pGlobal + ulOffset.LowPart, pb, cbWritten);
+ GlobalUnlock (m_pData->hGlobal);
+
+
+ if (pcbWritten != NULL)
+ {
+ *pcbWritten = cbWritten;
+ }
+
+Exit:
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemBytes::Flush
+//
+// Synopsis: Flushes internal state to disk
+// Not needed for memory ILockBytes
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: ILockBytes
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemBytes_Flush)
+STDMETHODIMP CMemBytes::Flush(void)
+{
+ VDATEHEAP();
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemBytes::SetSize
+//
+// Synopsis: Sets the size of the memory buffer
+//
+// Effects:
+//
+// Arguments: [cb] -- the new size
+//
+// Requires:
+//
+// Returns: NOERROR, E_OUTOFMEMORY
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: ILockBytes
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemBytes_SetSize)
+STDMETHODIMP CMemBytes::SetSize(ULARGE_INTEGER cb)
+{
+ VDATEHEAP();
+
+ HANDLE hMemNew;
+
+ AssertSz(cb.HighPart == 0,
+ "SetSize: trying to set to more than 2^32 bytes");
+
+ if (m_pData->cb == cb.LowPart)
+ {
+ return NOERROR;
+ }
+
+ hMemNew = GlobalReAlloc(m_pData->hGlobal, max (cb.LowPart, 1),
+ GMEM_SHARE | GMEM_MOVEABLE);
+
+ if (hMemNew == NULL)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ m_pData->hGlobal = hMemNew;
+ m_pData->cb = cb.LowPart;
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemBytes::LockRegion
+//
+// Synopsis: Locks a region. Since only we have access to the memory,
+// nothing needs to be done (note that the *app* also may
+// access, but there's not much we can do about that)
+//
+// Effects:
+//
+// Arguments: [libOffset] -- offset to start with
+// [cb] -- the number of bytes in the locked region
+// [dwLockType] -- the type of lock to use
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: ILockBytes
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemBytes_LockRegion)
+STDMETHODIMP CMemBytes::LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb, DWORD dwLockType)
+{
+ VDATEHEAP();
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemBytes::UnlockRegion
+//
+// Synopsis: Unlocks a region; since only we have access to the memory,
+// nothing needs to be done.
+//
+// Effects:
+//
+// Arguments: [libOffset] -- the offset to start with
+// [cb] -- the number of bytes in the region
+// [dwLockType] -- the lock type
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: ILockBytes
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemBytes_UnlockRegion)
+STDMETHODIMP CMemBytes::UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb, DWORD dwLockType)
+{
+ VDATEHEAP();
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemBytes::Stat
+//
+// Synopsis: returns status information
+//
+// Effects:
+//
+// Arguments: [pstatstg] -- where to put the status info
+// [statflag] -- status flags (ignored)
+//
+// Requires:
+//
+// Returns: NOERROR, E_INVALIDARG
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: ILockBytes
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+// 01-Jun-94 AlexT Set type correctly
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemBytes_Stat)
+STDMETHODIMP CMemBytes::Stat(STATSTG FAR *pstatstg, DWORD statflag)
+{
+ VDATEHEAP();
+
+ VDATEPTROUT( pstatstg, STATSTG );
+
+ memset ( pstatstg, 0, sizeof(STATSTG) );
+
+ pstatstg->type = STGTY_LOCKBYTES;
+ pstatstg->cbSize.LowPart = m_pData->cb;
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemBytes::Create
+//
+// Synopsis: Creates an instance of CMemBytes
+//
+// Effects:
+//
+// Arguments: [hMem] -- handle to the memory (must be a MEMSTM block)
+//
+// Requires:
+//
+// Returns: CMemBytes *
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Dec-93 alexgo fixed bad pointer bug (took out
+// GlobalUnlock)
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMemBytes_Create)
+STDSTATICIMP_(CMemBytes FAR*) CMemBytes::Create(HANDLE hMem)
+{
+ VDATEHEAP();
+
+ CMemBytes FAR* pCMemBytes = NULL;
+ struct MEMSTM FAR* pData;
+
+ pData = (MEMSTM FAR*) GlobalLock(hMem);
+
+ if (pData != NULL)
+ {
+ Assert (pData->hGlobal);
+
+ pCMemBytes = new CMemBytes;
+
+ if (pCMemBytes != NULL)
+ {
+ // Initialize CMemBytes
+ pCMemBytes->m_dwSig = LOCKBYTE_SIG;
+ pCMemBytes->m_hMem = hMem;
+ (pCMemBytes->m_pData = pData)->cRef++; // AddRefMemStm
+ pCMemBytes->m_refs = 1;
+ CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_ILockBytes,
+ (IUnknown **)&pCMemBytes);
+ }
+ else
+ {
+ // uh-oh, low on memory
+ GlobalUnlock(hMem);
+ }
+ }
+
+ // we don't GlobalUnlock(hMem) until we destory this CMemBytes
+ return pCMemBytes;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMemBytes::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppsz] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 20-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CMemBytes::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszMEMSTM;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(400);
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "Impl. Signature = " << m_dwSig << endl;
+
+ dstrDump << pszPrefix << "No. of References = " << m_refs << endl;
+
+ dstrDump << pszPrefix << "Memory handle = " << m_hMem << endl;
+
+ if (m_pData != NULL)
+ {
+ pszMEMSTM = DumpMEMSTM(m_pData, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "MEMSTM:" << endl;
+ dstrDump << pszMEMSTM;
+ CoTaskMemFree(pszMEMSTM);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "MEMSTM = " << m_pData << endl;
+ }
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCMemBytes, public (_DEBUG only)
+//
+// Synopsis: calls the CMemBytes::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pMB] - pointer to CMemBytes
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 20-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCMemBytes(CMemBytes *pMB, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pMB == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pMB->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+// --------------------------------------------------------------------
+// EVERYTHING BELOW HERE HAS BEEN REMOVED FROM WIN32 VERSIONS.
+
+#ifndef WIN32
+
+// CMemStm object's IMarshal implementation
+//
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshalMemStm::QueryInterface
+//
+// Synopsis: returns the requested interface ID
+//
+// Effects:
+//
+// Arguments: [iidInterface] -- the requested interface
+// [ppvObj] -- where to put the interface pointer
+//
+// Requires:
+//
+// Returns: NOERROR, E_NOINTERFACE
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IMarshal
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMarshalMemStm_QueryInterface)
+STDMETHODIMP CMarshalMemStm::QueryInterface(REFIID iidInterface,
+ void FAR* FAR* ppvObj)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+
+ VDATEPTROUT( ppvObj, LPVOID );
+ *ppvObj = NULL;
+ VDATEIID( iidInterface );
+
+ // Two interfaces supported: IUnknown, IMarshal
+
+ if (IsEqualIID(iidInterface, IID_IMarshal) ||
+ IsEqualIID(iidInterface, IID_IUnknown))
+ {
+ m_refs++; // A pointer to this object is returned
+ *ppvObj = this;
+ error = NOERROR;
+ }
+ else
+ {
+ // Not accessible or unsupported interface
+ *ppvObj = NULL;
+ error = ResultFromScode (E_NOINTERFACE);
+ }
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshalMemstm::AddRef
+//
+// Synopsis: increments the reference count
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IMarshal
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMarshalMemStm_AddRef)
+STDMETHODIMP_(ULONG) CMarshalMemStm::AddRef(void)
+{
+ VDATEHEAP();
+
+ return ++m_refs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshalMemStm::Release
+//
+// Synopsis: decrements the reference count
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IMarshal
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMarshalMemStm_Release)
+STDMETHODIMP_(ULONG) CMarshalMemStm::Release(void)
+{
+ VDATEHEAP();
+
+ if (--m_refs != 0)
+ {
+ return m_refs;
+ }
+
+ if (m_pMemStm != NULL)
+ {
+ m_pMemStm->Release();
+ }
+
+ delete this; // Free storage
+ return 0;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshalMemStm::GetUnmarshalClass
+//
+// Synopsis: returns the object class that should be used to create
+// the proxy in the unmarshalling process (CLSID_StdMemStm)
+//
+// Effects:
+//
+// Arguments: [riid] -- the interface ID of the object to be
+// marshalled
+// [pv] -- pointer to the object
+// [dwDestContext] -- marshalling context (such a no shared mem)
+// [pvDestContext] -- reserved
+// [mshlfags] -- marshalling flags (e.g. NORMAL)
+// [pCid] -- where to put the class ID
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IMarshal
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMarshalMemStm_GetUnmarshalClass)
+STDMETHODIMP CMarshalMemStm::GetUnmarshalClass(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags,
+ CLSID FAR* pCid)
+{
+ VDATEHEAP();
+
+ VDATEPTROUT( pCid, CLSID);
+
+ *pCid = CLSID_StdMemStm;
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshalMemStm::GetUnmarshalSizeMax
+//
+// Synopsis: returns the amount of memory needed to marshal the data
+// (in this case, the hglobal)
+//
+// Effects:
+//
+// Arguments: [riid] -- the interface of the object
+// [pv] -- pointer to the object
+// [dwDestContext] -- marshalling context (such a no shared mem)
+// [pvDestContext] -- reserved
+// [mshlfags] -- marshalling flags (e.g. NORMAL)
+// [pSize] -- where to put the size
+//
+// Requires:
+//
+// Returns: NOERROR, E_INVALIDARG
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IMarshal
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMarshalMemStm_GetMarshalSizeMax)
+STDMETHODIMP CMarshalMemStm::GetMarshalSizeMax(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags,
+ DWORD FAR* pSize)
+{
+ VDATEHEAP();
+
+ VDATEPTROUT(pSize, DWORD);
+
+ *pSize = sizeof(m_pMemStm->m_hMem);
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshalMemStm::MarshalInterface
+//
+// Synopsis: marshals a reference of the objects interface into [pStm]
+//
+// Effects:
+//
+// Arguments: [pStm] -- the stream into which the object should
+// be marshalled
+// [riid] -- the interface ID of the object to be
+// marshalled
+// [pv] -- points to the interface
+// [dwDestContext] -- the marshalling context
+// [pvDestContext] -- unused
+// [mshlflags] -- marshalling flags
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IMarshal
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMarshalMemStm_MarshalInterface)
+STDMETHODIMP CMarshalMemStm::MarshalInterface(IStream FAR* pStm,
+ REFIID riid, void FAR* pv, DWORD dwDestContext,
+ LPVOID pvDestContext, DWORD mshlflags)
+{
+ VDATEHEAP();
+
+ VDATEPTRIN( pStm, IStream );
+ VDATEIID( riid );
+ VDATEIFACE( pv );
+
+ if (m_pMemStm == NULL)
+ {
+ return ResultFromScode(E_UNSPEC);
+ }
+
+ if ((!IsEqualIID(riid, IID_IStream) &&
+ !IsEqualIID(riid, IID_IUnknown)) || pv != m_pMemStm)
+ {
+ return ReportResult(0, E_INVALIDARG, 0, 0);
+ }
+
+ // increase ref count on hglobal (ReleaseMarshalData has -- to match)
+ HRESULT error;
+ if ((error = pStm->Write(&m_pMemStm->m_hMem,
+ sizeof(m_pMemStm->m_hMem), NULL)) == NOERROR)
+ {
+ m_pMemStm->m_pData->cRef++; // AddRefMemStm
+ }
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshalMemStm::UnmarshalInterface
+//
+// Synopsis: Unmarshals an the object from the given stream
+//
+// Effects:
+//
+// Arguments: [pStm] -- the stream to read data from
+// [riid] -- the interface the caller wants from the
+// object
+// [ppvObj] -- where to put a pointer to the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IMarshal
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CMarshalMemStm_UnmarshalInterface)
+STDMETHODIMP CMarshalMemStm::UnmarshalInterface(IStream FAR* pStm,
+ REFIID riid, void FAR* FAR* ppv)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ HANDLE hMem;
+
+ VDATEPTROUT( ppv, LPVOID );
+ *ppv = NULL;
+ VDATEPTRIN( pStm, IStream );
+ VDATEIID( riid );
+
+ if (!IsEqualIID(riid, IID_IStream) && !IsEqualIID(riid, IID_IUnknown))
+ {
+ return ResultFromScode(E_INVALIDARG);
+ }
+
+ error = pStm->Read(&hMem,sizeof(hMem),NULL);
+ if (error != NOERROR)
+ {
+ return error;
+ }
+
+ if (m_pMemStm != NULL)
+ {
+ if (hMem != m_pMemStm->m_hMem)
+ {
+ return ResultFromScode(E_UNSPEC);
+ }
+ }
+ else
+ {
+ m_pMemStm = (CMemStm FAR*) CloneMemStm(hMem);
+ if (m_pMemStm == NULL)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+ }
+
+ m_pMemStm->AddRef();
+ *ppv = (LPVOID) m_pMemStm;
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMarshalMemStm::ReleaseMarshalData
+//
+// Synopsis: releases the marshalling data (takes away ref count on
+// hglobal)
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CMarshalMemStm_ReleaseMarshalData)
+STDMETHODIMP CMarshalMemStm::ReleaseMarshalData(IStream FAR* pStm)
+{
+ VDATEHEAP();
+
+ // reduce ref count on hglobal (matches that done in MarshalInterface)
+ HRESULT error;
+ HANDLE hMem;
+
+ VDATEIFACE( pStm );
+
+ error = pStm->Read(&hMem,sizeof(hMem),NULL);
+ if (error == NOERROR)
+ ReleaseMemStm(&hMem);
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member:
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CMarshalMemStm_DisconnectObject)
+STDMETHODIMP CMarshalMemStm::DisconnectObject(DWORD dwReserved)
+{
+ VDATEHEAP();
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member:
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CMarshalMemStm_Create)
+STDSTATICIMP_(CMarshalMemStm FAR*) CMarshalMemStm::Create(CMemStm FAR* pMemStm)
+{
+ VDATEHEAP();
+
+ CMarshalMemStm FAR* pMMS;
+
+ //VDATEPTRIN rejects NULL
+ if( pMemStm )
+ GEN_VDATEPTRIN( pMemStm, CMemStm, (CMarshalMemStm FAR *) NULL );
+
+ pMMS = new(MEMCTX_TASK, NULL) CMarshalMemStm;
+
+ if (pMMS == NULL)
+ return NULL;
+
+ if (pMemStm != NULL) {
+ pMMS->m_pMemStm = pMemStm;
+ pMMS->m_pMemStm->AddRef();
+ }
+
+ pMMS->m_refs = 1;
+
+ return pMMS;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function:
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CMemStmUnMarshal)
+STDAPI_(IUnknown FAR*) CMemStmUnMarshal(void)
+{
+ VDATEHEAP();
+
+ return CMarshalMemStm::Create(NULL);
+}
+
+
+
+// CMemBytes object's IMarshal implementation
+//
+
+//+-------------------------------------------------------------------------
+//
+// Member:
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CMarshalMemBytes_QueryInterface)
+STDMETHODIMP CMarshalMemBytes::QueryInterface(REFIID iidInterface,
+ void FAR* FAR* ppvObj)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+
+ VDATEIID( iidInterface );
+ VDATEPTROUT( ppvObj, LPVOID );
+ *ppvObj = NULL;
+
+ // Two interfaces supported: IUnknown, IMarshal
+
+ if (IsEqualIID(iidInterface, IID_IMarshal)
+ || IsEqualIID(iidInterface, IID_IUnknown))
+ {
+ m_refs++; // A pointer to this object is returned
+ *ppvObj = this;
+ error = NOERROR;
+ }
+ else
+ { // Not accessible or unsupported interface
+ *ppvObj = NULL;
+ error = ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member:
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+// Called when CMarshalMemBytes is referenced by an additional pointer.
+//
+
+#pragma SEG(CMarshalMemBytes_AddRef)
+STDMETHODIMP_(ULONG) CMarshalMemBytes::AddRef(void)
+{
+ VDATEHEAP();
+
+ return ++m_refs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member:
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CMarshalMemBytes_Release)
+// Called when a pointer to this CMarshalMemBytes is discarded
+//
+STDMETHODIMP_(ULONG) CMarshalMemBytes::Release(void)
+{
+ VDATEHEAP();
+
+ if (--m_refs != 0) // Still used by others
+ return m_refs;
+
+ if (m_pMemBytes != NULL)
+ m_pMemBytes->Release();
+
+ delete this; // Free storage
+ return 0;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member:
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CMarshalMemBytes_GetUnmarshalClass)
+// Returns the clsid of the object that created this CMarshalMemBytes.
+//
+STDMETHODIMP CMarshalMemBytes::GetUnmarshalClass(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, CLSID FAR* pCid)
+{
+ VDATEHEAP();
+
+ VDATEIID( riid );
+ VDATEIFACE( pv );
+
+ *pCid = CLSID_StdMemBytes;
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member:
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CMarshalMemBytes_GetMarshalSizeMax)
+STDMETHODIMP CMarshalMemBytes::GetMarshalSizeMax(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, DWORD FAR* pSize)
+{
+ VDATEHEAP();
+
+ VDATEPTROUT( pSize, DWORD );
+ VDATEIID( riid );
+ VDATEIFACE( pv );
+
+ *pSize = sizeof(m_pMemBytes->m_hMem);
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member:
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CMarshalMemBytes_MarshalInterface)
+STDMETHODIMP CMarshalMemBytes::MarshalInterface(IStream FAR* pStm,
+ REFIID riid, void FAR* pv, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags)
+{
+ VDATEHEAP();
+
+ VDATEPTRIN(pStm, IStream );
+ VDATEIID( riid );
+ if ( pv )
+ VDATEPTRIN( pv , char );
+
+ if (m_pMemBytes == NULL)
+ return ReportResult(0, E_UNSPEC, 0, 0);
+
+ if ((!IsEqualIID(riid, IID_ILockBytes) &&
+ !IsEqualIID(riid, IID_IUnknown)) || pv != m_pMemBytes)
+ return ReportResult(0, E_INVALIDARG, 0, 0);
+
+ // increase ref count on hglobal (ReleaseMarshalData has -- to match)
+ HRESULT error;
+
+ if ((error = pStm->Write(&m_pMemBytes->m_hMem,
+ sizeof(m_pMemBytes->m_hMem), NULL)) == NOERROR)
+ m_pMemBytes->m_pData->cRef++; // AddRefMemStm
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member:
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CMarshalMemBytes_UnmarshalInterface)
+STDMETHODIMP CMarshalMemBytes::UnmarshalInterface(IStream FAR* pStm,
+ REFIID riid, void FAR* FAR* ppv)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ HANDLE hMem;
+
+ VDATEPTROUT( ppv , LPVOID );
+ *ppv = NULL;
+ VDATEIFACE( pStm );
+ VDATEIID( riid );
+
+
+ if (!IsEqualIID(riid, IID_ILockBytes) &&
+ !IsEqualIID(riid, IID_IUnknown))
+ return ReportResult(0, E_INVALIDARG, 0, 0);
+
+ error = pStm->Read(&hMem,sizeof(hMem),NULL);
+ if (error != NOERROR)
+ return error;
+
+ if (m_pMemBytes != NULL)
+ {
+ if (hMem != m_pMemBytes->m_hMem)
+ return ReportResult(0, E_UNSPEC, 0, 0);
+ }
+ else
+ {
+ m_pMemBytes = CMemBytes::Create(hMem); // Create the lockbytes
+
+ if (m_pMemBytes == NULL)
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ m_pMemBytes->AddRef();
+ *ppv = (LPVOID) m_pMemBytes;
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member:
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+
+STDMETHODIMP CMarshalMemBytes::ReleaseMarshalData(IStream FAR* pStm)
+{
+ VDATEHEAP();
+
+ // reduce ref count on hglobal (matches that done in MarshalInterface)
+ HRESULT error;
+ HANDLE hMem;
+
+ VDATEIFACE( pStm );
+
+ error = pStm->Read(&hMem,sizeof(hMem),NULL);
+ if (error == NOERROR)
+ ReleaseMemStm(&hMem);
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member:
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CMarshalMemBytes_DisconnectObject)
+STDMETHODIMP CMarshalMemBytes::DisconnectObject(DWORD dwReserved)
+{
+ VDATEHEAP();
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member:
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CMarshalMemBytes_Create)
+STDSTATICIMP_(CMarshalMemBytes FAR*) CMarshalMemBytes::Create(
+ CMemBytes FAR* pMemBytes)
+{
+ VDATEHEAP();
+
+ CMarshalMemBytes FAR* pMMB;
+
+ //VDATEPTRIN rejects NULL
+ if( pMemBytes )
+ GEN_VDATEPTRIN( pMemBytes, CMemBytes,
+ (CMarshalMemBytes FAR *)NULL);
+
+ pMMB = new(MEMCTX_TASK, NULL) CMarshalMemBytes;
+
+ if (pMMB == NULL)
+ return NULL;
+
+ if (pMemBytes != NULL)
+ {
+ pMMB->m_pMemBytes = pMemBytes;
+ pMMB->m_pMemBytes->AddRef();
+ }
+
+ pMMB->m_refs = 1;
+
+ return pMMB;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member:
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+
+#pragma SEG(CMemBytesUnMarshal)
+STDAPI_(IUnknown FAR*) CMemBytesUnMarshal(void)
+{
+ VDATEHEAP();
+
+ return CMarshalMemBytes::Create(NULL);
+}
+
+#endif // !WIN32 -- win32 builds use standard marshalling for
+ // streams and lockbytes.
diff --git a/private/ole32/ole232/base/ole2.cpp b/private/ole32/ole232/base/ole2.cpp
new file mode 100644
index 000000000..9efcc70f6
--- /dev/null
+++ b/private/ole32/ole232/base/ole2.cpp
@@ -0,0 +1,577 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ole2.cpp
+//
+// Contents: LibMain and initialization routines
+//
+// Classes:
+//
+// Functions: LibMain
+// OleInitialize
+// OleInitializeWOW
+// OleInitializeEx
+// OleUnitialize
+// OleBuildVersion - !WIN32
+//
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 AlexT alias OleBuildVersion, remove OleGetMalloc
+// remove DisableThreadLibaryCalls
+// 11-Jan-94 alexgo added VDATEHEAP macros to every function
+// 10-Dec-93 alexgo added support for LEDebugOut
+// 06-Dec-93 ChrisWe remove declaration of ClipboardInitialize()
+// and ClipboardUninitialize(), which are declared in
+// clipbrd.h; include that instead
+// 15-Mar-94 KevinRo Added OleInitializeWOW();
+//
+//--------------------------------------------------------------------------
+
+
+#include <le2int.h>
+#include <clipbrd.h>
+#include <dragopt.h>
+#include <drag.h>
+
+#pragma SEG(ole)
+
+#include <olerem.h>
+#include <ole2ver.h>
+#include <thunkapi.hxx>
+#include <ddesrvr.h>
+#include <perfmnce.hxx>
+#include <olesem.hxx>
+
+//
+// DECLARE_INFOLEVEL is a macro used with cairo-style debugging output.
+// it creates a global variable LEInfoLevel which contains bits flags
+// of the various debugging output that should be sent to the debugger.
+//
+// Note that info level may be set within the debugger once ole232.dll
+// has loaded.
+//
+// Currently LEInfoLevel defaults to DEB_WARN | DEB_ERROR
+//
+DECLARE_INFOLEVEL(LE);
+DECLARE_INFOLEVEL(Ref);
+DECLARE_INFOLEVEL(DD);
+DECLARE_INFOLEVEL(VDATE);
+
+NAME_SEG(Ole2Main)
+// these are globals
+
+HMODULE g_hmodOLE2 = NULL;
+HINSTANCE g_hinst = NULL;
+ULONG g_cOleProcessInits = 0;
+
+CLIPFORMAT g_cfObjectLink = NULL;
+CLIPFORMAT g_cfOwnerLink = NULL;
+CLIPFORMAT g_cfNative = NULL;
+CLIPFORMAT g_cfLink = NULL;
+CLIPFORMAT g_cfBinary = NULL;
+CLIPFORMAT g_cfFileName = NULL;
+CLIPFORMAT g_cfFileNameW = NULL;
+CLIPFORMAT g_cfNetworkName = NULL;
+CLIPFORMAT g_cfDataObject = NULL;
+CLIPFORMAT g_cfEmbeddedObject = NULL;
+CLIPFORMAT g_cfEmbedSource = NULL;
+CLIPFORMAT g_cfCustomLinkSource = NULL;
+CLIPFORMAT g_cfLinkSource = NULL;
+CLIPFORMAT g_cfLinkSrcDescriptor = NULL;
+CLIPFORMAT g_cfObjectDescriptor = NULL;
+CLIPFORMAT g_cfOleDraw = NULL;
+CLIPFORMAT g_cfPBrush = NULL;
+CLIPFORMAT g_cfMSDraw = NULL;
+CLIPFORMAT g_cfOlePrivateData = NULL;
+CLIPFORMAT g_cfScreenPicture = NULL;
+
+ATOM g_aDropTarget = NULL;
+
+ASSERTDATA
+
+ASSERTOUTDATA
+
+// more globals
+
+extern UINT uOmPostWmCommand;
+extern UINT uOleMessage;
+extern COleStaticMutexSem g_mxsSingleThreadOle;
+
+
+// this dummy function is used to avoid a copy of the environment variables.
+// NOTE: the moniker and dde code still use the windows heap.
+
+extern "C" void _setenvp(void) {
+ VDATEHEAP();
+ }
+
+
+#ifdef _CHICAGO_
+// Private Chicago Defines
+//
+// The Chicago Shell will dynamically load the OLE32.DLL to improve
+// bootup start time. When an application calls CoInitialize, post
+// a message to the shell to inform it to load OLE32.DLL if it hasn't
+// already. The Shell will never unload OLE32.DLL.
+//
+// We are using an undocumented Shell interface.
+//
+BOOL gfShellInitialized = FALSE;
+
+#define WM_SHELLNOTIFY 0x0034
+#define SHELLNOTIFY_OLELOADED 0x0002
+
+extern "C" HWND WINAPI GetShellWindow(void);
+#endif // _CHICAGO_
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleInitializeWOW
+// Synopsis: Entry point to initialize the 16-bit WOW thunk layer.
+//
+// Effects: This routine is called when OLE32 is loaded by a VDM.
+// It serves two functions: It lets OLE know that it is
+// running in a VDM, and it passes in the address to a set
+// of functions that are called by the thunk layer. This
+// allows normal 32-bit processes to avoid loading the WOW
+// DLL since the thunk layer references it.
+//
+// Arguments: [vlpmalloc] -- 16:16 pointer to the 16 bit allocator.
+// [lpthk] -- Flat pointer to the OleThunkWOW virtual
+// interface. This is NOT an OLE/IUnknown style
+// interface.
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 3-15-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleInitializeWOW( LPMALLOC vlpmalloc, LPOLETHUNKWOW lpthk )
+{
+ OLETRACEIN((API_OleInitializeWOW, PARAMFMT("vlpmalloc= %x, lpthk= %p"),
+ vlpmalloc, lpthk));
+
+ SetOleThunkWowPtr(lpthk);
+
+ HRESULT hr;
+
+ hr = OleInitializeEx( NULL, COINIT_APARTMENTTHREADED );
+
+ OLETRACEOUT((API_OleInitializeWOW, hr));
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleInitialize
+//
+// Synopsis: Initializes OLE in single threaded mode
+//
+// Effects:
+//
+// Arguments: [pMalloc] -- the memory allocator to use
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 06-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI OleInitialize(void * pMalloc)
+{
+ OLETRACEIN((API_OleInitialize, PARAMFMT("pMalloc= %p"), pMalloc));
+
+ VDATEHEAP();
+
+ HRESULT hr;
+
+ hr = OleInitializeEx( pMalloc, COINIT_APARTMENTTHREADED );
+
+ OLETRACEOUT((API_OleInitialize, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleInitializeEx
+//
+// Synopsis: Initializes ole
+//
+// Effects:
+//
+// Arguments: [pMalloc] -- the task memory allocator to use
+// [flags] -- single or multi-threaded
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 06-Dec-93 alexgo 32bit port
+// 24-May-94 AlexT Propagate CoInitializeEx's return code
+// 21-Jul-94 AlexT Allow nested OleInit/Uninit calls
+// 24-Aug-94 AlexT Return S_OK for first success and S_FALSE
+// thereafter (unless an allocator was
+// passed in)
+//
+// Notes: This routine may be called multiple times per apartment
+//
+//--------------------------------------------------------------------------
+#pragma SEG(OleInitialize)
+STDAPI OleInitializeEx(LPVOID pMalloc, ULONG ulFlags)
+{
+ OLETRACEIN((API_OleInitialize, PARAMFMT("pMalloc= %p, ulFlags= %x"), pMalloc, ulFlags));
+ VDATEHEAP();
+
+ HRESULT hr;
+#if DBG==1
+ HRESULT hrCoInit = S_OK;
+#endif
+ DWORD cThreadOleInits;
+
+ StartPerfCounter(CoInitialize);
+ hr = CoInitializeEx(pMalloc, ulFlags);
+ EndPerfCounter(CoInitialize);
+
+ if (SUCCEEDED(hr))
+ {
+ Assert (g_hmodOLE2);
+#if DBG==1
+ hrCoInit = hr;
+#endif
+
+ COleTls tls;
+ cThreadOleInits = ++ tls->cOleInits;
+
+ do
+ {
+ // We only want to do the below initialization once per apartment
+ if (cThreadOleInits > 1)
+ {
+ // We've already been this way before, just return
+ Assert(SUCCEEDED(hr) && "Bad OleInitializeEx logic");
+ break;
+ }
+
+ // single thread registration of DDE and clipboard formats.
+ // Only do this once per process.
+
+ COleStaticLock lck(g_mxsSingleThreadOle);
+
+ if (++g_cOleProcessInits != 1)
+ {
+ // already done the per-process initialization
+ break;
+ }
+
+ if (FALSE==DDELibMain (g_hmodOLE2, (WORD)0, (WORD)0, NULL))
+ {
+ Assert (!"DDELibMain failed()");
+
+ hr = E_OUTOFMEMORY;
+ break;
+ }
+
+ // Only need to do the initialization once so check the global
+ // that gets assigned last.
+
+ if( !g_aDropTarget )
+ {
+#ifndef _CHICAGO_
+ // on NT3.51, clipboard formats are pre-registered for us by user32.
+ // We know they are going to be sequential. This gives us a
+ // good performance improvement (since the clipboard formats never
+ // change.
+
+ // BUGBUG(alexgo); Chicago needs to get this behaviour too
+
+ g_cfObjectLink = RegisterClipboardFormat(OLESTR("ObjectLink"));
+
+ g_cfOwnerLink = g_cfObjectLink + 1;
+ Assert(g_cfOwnerLink == RegisterClipboardFormat(OLESTR("OwnerLink")));
+
+ g_cfNative = g_cfObjectLink + 2;
+ Assert(g_cfNative == RegisterClipboardFormat(OLESTR("Native")));
+
+ g_cfBinary = g_cfObjectLink + 3;
+ Assert(g_cfBinary == RegisterClipboardFormat(OLESTR("Binary")));
+
+ g_cfFileName = g_cfObjectLink + 4;
+ Assert(g_cfFileName == RegisterClipboardFormat(OLESTR("FileName")));
+
+ g_cfFileNameW = g_cfObjectLink + 5;
+ Assert(g_cfFileNameW ==
+ RegisterClipboardFormat(OLESTR("FileNameW")));
+
+ g_cfNetworkName = g_cfObjectLink + 6;
+ Assert(g_cfNetworkName ==
+ RegisterClipboardFormat(OLESTR("NetworkName")));
+
+ g_cfDataObject = g_cfObjectLink + 7;
+ Assert(g_cfDataObject ==
+ RegisterClipboardFormat(OLESTR("DataObject")));
+
+ g_cfEmbeddedObject = g_cfObjectLink + 8;
+ Assert(g_cfEmbeddedObject ==
+ RegisterClipboardFormat(OLESTR("Embedded Object")));
+
+ g_cfEmbedSource = g_cfObjectLink + 9;
+ Assert(g_cfEmbedSource ==
+ RegisterClipboardFormat(OLESTR("Embed Source")));
+
+ g_cfCustomLinkSource = g_cfObjectLink + 10;
+ Assert(g_cfCustomLinkSource ==
+ RegisterClipboardFormat(OLESTR("Custom Link Source")));
+
+ g_cfLinkSource = g_cfObjectLink + 11;
+ Assert(g_cfLinkSource ==
+ RegisterClipboardFormat(OLESTR("Link Source")));
+
+ g_cfObjectDescriptor = g_cfObjectLink + 12;
+ Assert(g_cfObjectDescriptor ==
+ RegisterClipboardFormat(OLESTR("Object Descriptor")));
+
+ g_cfLinkSrcDescriptor = g_cfObjectLink + 13;
+ Assert(g_cfLinkSrcDescriptor ==
+ RegisterClipboardFormat(OLESTR("Link Source Descriptor")));
+
+ g_cfOleDraw = g_cfObjectLink + 14;
+ Assert(g_cfOleDraw == RegisterClipboardFormat(OLESTR("OleDraw")));
+
+ g_cfPBrush = g_cfObjectLink + 15;
+ Assert(g_cfPBrush == RegisterClipboardFormat(OLESTR("PBrush")));
+
+ g_cfMSDraw = g_cfObjectLink + 16;
+ Assert(g_cfMSDraw == RegisterClipboardFormat(OLESTR("MSDraw")));
+
+ g_cfOlePrivateData = g_cfObjectLink + 17;
+ Assert(g_cfOlePrivateData ==
+ RegisterClipboardFormat(OLESTR("Ole Private Data")));
+
+ g_cfScreenPicture = g_cfObjectLink + 18;
+ Assert(g_cfScreenPicture ==
+ RegisterClipboardFormat(OLESTR("Screen Picture")));
+
+ g_aDropTarget = GlobalAddAtom(OLE_DROP_TARGET_PROP);
+ AssertSz(g_aDropTarget, "Couldn't add drop target atom\n");
+ }
+
+ // Used in Inplace editing
+ uOmPostWmCommand = RegisterWindowMessage(OLESTR("OM_POST_WM_COMMAND"));
+ uOleMessage = RegisterWindowMessage(OLESTR("OLE_MESSAHE"));
+
+#else // !_CHICAGO_
+
+ g_cfObjectLink = SSRegisterClipboardFormatA("ObjectLink");
+ g_cfOwnerLink = SSRegisterClipboardFormatA("OwnerLink");
+ g_cfNative = SSRegisterClipboardFormatA("Native");
+ g_cfBinary = SSRegisterClipboardFormatA("Binary");
+ g_cfFileName = SSRegisterClipboardFormatA("FileName");
+ g_cfFileNameW = SSRegisterClipboardFormatA("FileNameW");
+ g_cfNetworkName = SSRegisterClipboardFormatA("NetworkName");
+ g_cfDataObject = SSRegisterClipboardFormatA("DataObject");
+ g_cfEmbeddedObject = SSRegisterClipboardFormatA("Embedded Object");
+ g_cfEmbedSource = SSRegisterClipboardFormatA("Embed Source");
+ g_cfCustomLinkSource = SSRegisterClipboardFormatA("Custom Link Source");
+ g_cfLinkSource = SSRegisterClipboardFormatA("Link Source");
+ g_cfObjectDescriptor = SSRegisterClipboardFormatA("Object Descriptor");
+ g_cfLinkSrcDescriptor = SSRegisterClipboardFormatA("Link Source Descriptor");
+ g_cfOleDraw = SSRegisterClipboardFormatA("OleDraw");
+ g_cfPBrush = SSRegisterClipboardFormatA("PBrush");
+ g_cfMSDraw = SSRegisterClipboardFormatA("MSDraw");
+ g_cfOlePrivateData = SSRegisterClipboardFormatA("Ole Private Data");
+ g_cfScreenPicture = SSRegisterClipboardFormatA("Screen Picture");
+ g_aDropTarget = GlobalAddAtomA(OLE_DROP_TARGET_PROPA);
+ AssertSz(g_aDropTarget, "Couldn't add drop target atom\n");
+ }
+
+ // Used in Inplace editing
+ uOmPostWmCommand = RegisterWindowMessageA("OM_POST_WM_COMMAND");
+ uOleMessage = RegisterWindowMessageA("OLE_MESSAHE");
+
+#endif // !_CHICAGO_
+
+ } while (FALSE); // end of do
+
+
+ if (FAILED(hr))
+ {
+ // clean up and break out
+ DDEWEP (WEP_FREE_DLL);
+
+ tls->cOleInits--;
+ CoUninitialize();
+ }
+ else
+ {
+#if defined(_CHICAGO_)
+ if (!gfShellInitialized && CoGetCurrentProcess() == 1)
+ {
+ // The Chicago Shell will dynamically load the OLE32.DLL to improve
+ // bootup start time. When an application calls CoInitialize, post
+ // a message to the shell to inform it to load OLE32.DLL if it hasn't
+ // already. The Shell will never unload OLE32.DLL.
+ //
+ // We are using an undocumented Shell interface.
+ //
+ // We do this last so that we dont take a task switch while in
+ // CoInitialize.
+#if DBG==1
+ if (RegQueryValueEx(HKEY_CURRENT_USER,
+ L"Software\\Microsoft\\OLE2\\NoShellNotify",
+ NULL, // reserved
+ NULL, // lpdwType
+ NULL, // lpbData
+ NULL) != ERROR_SUCCESS) // lpcbData
+#endif
+ {
+ HWND hwndShell = GetShellWindow();
+ if (hwndShell)
+ {
+ PostMessage(hwndShell,WM_SHELLNOTIFY,
+ SHELLNOTIFY_OLELOADED,0L);
+ }
+ }
+
+ }
+
+ gfShellInitialized = TRUE;
+#endif // _CHICAGO_
+
+ Assert(SUCCEEDED(hr) && "Bad OleInitializeEx logic");
+
+ // If we're overriding the allocator, we return whatever
+ // CoInitializeEx returned
+
+ if (NULL != pMalloc)
+ {
+ Assert(hr == hrCoInit && "Bad OleInit logic");
+ }
+ else if (1 == cThreadOleInits)
+ {
+ // First successful call to OleInitializeEx - S_OK
+ hr = S_OK;
+ }
+ else
+ {
+ // Second or greater succesful call to OleInitializeEx - S_FALSE
+ hr = S_FALSE;
+ }
+ }
+ }
+
+ OLETRACEOUT((API_OleInitialize, hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleUnitialize
+//
+// Synopsis: Unitializes OLE, releasing any grabbed resources
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 06-Dec-93 alexgo 32bit port
+// 21-Jul-94 AlexT Allow nested OleInit/Uninit calls
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+#pragma SEG(OleUninitialize)
+STDAPI_(void) OleUninitialize(void)
+{
+ OLETRACEIN((API_OleUninitialize, NOPARAM));
+
+ VDATEHEAP();
+
+ COleTls tls(TRUE);
+
+ if (tls.IsNULL() || 0 == tls->cOleInits)
+ {
+ LEDebugOut((DEB_ERROR,
+ "(0 == thread inits) Unbalanced call to OleUninitialize\n"));
+ goto errRtn;
+ }
+
+ if (0 == -- tls->cOleInits)
+ {
+ // This thread has called OleUninitialize for the last time. Check if
+ // we need to do per process uninit now.
+
+ ClipboardUninitialize(); // Must be first thing
+ DestroyCommonDdeWindow();
+
+ COleStaticLock lck(g_mxsSingleThreadOle);
+
+ if (--g_cOleProcessInits == 0)
+ {
+
+ DragDropProcessUninitialize();
+
+ // after this point, the uninit should not fail (because we don't
+ // have code to redo the init).
+ DDEWEP (WEP_FREE_DLL);
+
+#if DBG==1
+ // check for unreleased globals
+ UtGlobalFlushTracking();
+#endif
+ }
+ }
+
+ // We call CoInitialize each time we call OleInitialize, so here we
+ // balance that call
+ CoUninitialize();
+
+errRtn:
+ OLETRACEOUTEX((API_OleUninitialize, NORETURN));
+
+ return;
+}
diff --git a/private/ole32/ole232/base/privstm.cpp b/private/ole32/ole232/base/privstm.cpp
new file mode 100644
index 000000000..6f10053f5
--- /dev/null
+++ b/private/ole32/ole232/base/privstm.cpp
@@ -0,0 +1,1476 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: privstm.cpp
+//
+// Contents: Handles all reading/writing of the \1CompObj stream
+//
+// Functions: Implements:
+//
+// INTERNAL ReadCompObjStm
+// INTERNAL WriteCompObjStm
+// INTERNAL ClipfmtToStm
+// INTERNAL StmToClipfmt
+// INTERNAL GetUNICODEUserType
+// INTERNAL GetUNICODEProgID
+// INTERNAL GetUNICODEClipFormat
+// INTERNAL PutUNICODEUserType
+// INTERNAL PutUNICODEProgID
+// INTERNAL PutUNICODEClipFormat
+// INTERNAL UtGetUNICODEData
+// INTERNAL ANSIStrToStm
+// INTERNAL ANSIStmToStr
+//
+// STDAPI WriteFmtUserTypeStg
+// STDAPI ReadFmtUserTypeStg
+// STDAPI ReadFmtProgIdStg
+//
+// History: dd-mmm-yy Author Comment
+// 08-Feb-94 davepl Created
+//
+//
+// Notes: The CompObj stream (in 16-bit OLE) contained fields for
+// the ClassID, UserType, Clipboard format, and (in later
+// versions only) ProgID. These were always written in ANSI
+// format.
+//
+// The file format has been extended such that ANSI data is
+// written to the stream in much the same way as before. The
+// key difference is that in the event the internal UNICODE
+// versions of this data cannot be losslessly converted to
+// ANSI, the ANSI version is written as a NULL string, and
+// the UNICODE version follows at the end of the stream. This
+// way, 16-bit apps see as much of what they expect as possible,
+// and 32-bit apps can write UNICODE transparently in a
+// backwards-compatible way.
+//
+// The file format of the stream is:
+//
+// (A) WORD Byte Order
+// WORD Format Version
+// DWORD Original OS ver Always Windows 3.1
+// DWORD -1
+// CLSID Class ID
+// ULONG Length of UserType
+// <var> User Type string ANSI
+// <var> Clipformat ANSI (when using string tag)
+// ----------------------------
+// (B) ULONG Length of Prog ID
+// <var> Prog ID ANSI (not always present)
+// ----------------------------
+// (C) ULONG Magic Number Signified UNICODE data present
+// ULONG Length of UserType
+// ULONG User Type string UNICODE
+// <var> Clipformat UNICODE (when tag is string)
+// ULONG Length of Prog ID
+// <var> Prog ID UNICODE
+//
+// Section (A) is always present. Section (B) is present when
+// stream has been written by a later 16-bit app or by a
+// 32-bit app. Section (C) is present when written by a
+// 32-bit app.
+//
+// If a string is present in UNICODE, the ANSI version will be
+// NULL (a zero for length and _no_ <var> data). When the
+// UNICODE section is present, strings that were not needed
+// because the ANSI conversion was successful are written
+// as NULL (again, zero len and no <var> data).
+//
+// A NULL clipboard format is written as a 0 tag.
+//
+// In order to read any field, the entire string is read into
+// an internal object, and the fields are extracted individually.
+// In order to write an fields, the stream is read into the
+// object (if possible), the fields updated, and then rewritten
+// as an atomic object.
+//
+//--------------------------------------------------------------------------
+
+
+#include <le2int.h>
+
+static const ULONG COMP_OBJ_MAGIC_NUMBER = 0x71B239F4;
+
+#define MAX_CFNAME 400 // Maximum size of a clipformat name
+ // (my choice, none documented)
+
+const DWORD gdwFirstDword = (DWORD)MAKELONG(COMPOBJ_STREAM_VERSION,
+ BYTE_ORDER_INDICATOR);
+
+enum TXTTYPE
+{
+ TT_UNICODE = 0, TT_ANSI = 1
+};
+
+// This is the data object into which the stream is read prior to
+// extracting fields.
+
+struct CompObjHdr // The leading data in the CompObj stream
+{
+ DWORD m_dwFirstDword; // First DWORD, byte order and format ver
+ DWORD m_dwOSVer; // Originating OS Ver (eg: Win31)
+ DWORD m_unused; // Always a -1L in the stream
+ CLSID m_clsClass; // Class ID of this object
+};
+
+class CompObjStmData : public CPrivAlloc
+{
+public:
+
+ CompObjHdr m_hdr;
+ ULONG m_cchUserType; // Number of CHARACTERS in UserType
+ ULONG m_cchProgID; // Number of CHARACTERS in ProgID
+ DWORD m_dwFormatTag; // Clipformat type (none, string, clip, etc)
+ ULONG m_ulFormatID; // If tag is std clipformat, what type?
+
+ LPOLESTR m_pszOUserType; // Pointer to OLESTR UserType
+ LPOLESTR m_pszOProgID; // Pointer to OLESTR ProgID
+
+ LPSTR m_pszAUserType; // Pointer to ANSI UserType
+ LPSTR m_pszAProgID; // Pointer to ANSI ProgID
+
+ TXTTYPE ttClipString; // Format needed for the clipformat string
+
+ CompObjStmData(void)
+ {
+ memset(this, 0, sizeof(CompObjStmData));
+ ttClipString = TT_ANSI; // By default, use ANSI Clipformat
+ };
+
+ ~CompObjStmData(void)
+ {
+ PubMemFree(m_pszOUserType);
+ PubMemFree(m_pszOProgID);
+ PubMemFree(m_pszAUserType);
+ PubMemFree(m_pszAProgID);
+ };
+};
+
+// Prototypes for fns declared in this file
+
+INTERNAL ReadCompObjStm (IStorage *, CompObjStmData *);
+INTERNAL WriteCompObjStm (IStorage *, CompObjStmData *);
+INTERNAL ClipfmtToStm (CStmBufWrite &, ULONG, ULONG, TXTTYPE);
+INTERNAL StmToClipfmt (CStmBufRead &, DWORD *, DWORD *, TXTTYPE);
+INTERNAL GetUNICODEUserType (CompObjStmData *, LPOLESTR *);
+INTERNAL GetUNICODEProgID (CompObjStmData *, LPOLESTR *);
+INTERNAL GetClipFormat (CompObjStmData *, DWORD *, DWORD *);
+INTERNAL PutUNICODEUserType (CompObjStmData *, LPOLESTR);
+INTERNAL PutUNICODEProgID (CompObjStmData *, LPOLESTR);
+INTERNAL PutClipFormat (CompObjStmData *, DWORD, DWORD);
+INTERNAL ANSIStrToStm (CStmBufWrite &, LPCSTR);
+INTERNAL ANSIStmToStr (CStmBufRead & StmRead, LPSTR * pstr, ULONG *);
+
+STDAPI WriteFmtUserTypeStg (IStorage *, CLIPFORMAT, LPOLESTR);
+STDAPI ReadFmtUserTypeStg (IStorage *, CLIPFORMAT *, LPOLESTR *);
+STDAPI ReadFmtProgIdStg (IStorage *, LPOLESTR *);
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReadCompObjStm, PRIVATE INTERNAL
+//
+// Synopsis: Reads the \1CompObj stream into an internal data structure
+// that will contain the best-case representation of that
+// stream (ie: ANSI where possible, UNICODE where needed).
+//
+// Effects: Reads ANSI data where available. At end of standard ANSI
+// data, looks for ANSI ProgID field. If found, looks for
+// MagicNumber indicating UNICODE data is to follow. If this
+// matches, UNICODE strings are pulled from the stream. They
+// should only be found where the ANSI version was NULL
+// (because it could not be converted from UNICODE).
+//
+// Capable of reading 3 stream formats seamlessly:
+// - Original ANSI sans ProgID field
+// - Extended OLE 2.01 version with ProgID
+// - Extended OLE 2/32 version with ProgID and UNICODE extensions
+//
+// Arguments: [pstg] -- ptr to IStorage to read from
+// [pcod] -- ptr to already-allocated CompObjData object
+//
+// Returns: NOERROR on success
+// INVALIDARG on missing pcod
+// Various I/O on stream missing, read errors, etc
+// E_OUTOFMEMORY on any allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+// Notes: Any memory allocated herein will be allocated on
+// pointers in the pcod object, which will be freed by its
+// destructor when it exits scope or is deleted explicitly.
+//
+//--------------------------------------------------------------------------
+
+INTERNAL ReadCompObjStm(IStorage * pstg, CompObjStmData * pcod)
+{
+ VDATEHEAP();
+
+ HRESULT hr; // Result code
+ const ULONG RESERVED = 0; // For reserved parameters
+ ULONG ulSize = 0; // Holder for length of ProgID string
+ BOOL fExtStm = 1; // Could this be ext with UNICODE?
+ CStmBufRead StmRead;
+
+
+ Win4Assert(pcod);
+
+ // Validate the pstg interface
+ VDATEIFACE(pstg);
+
+ // Open the CompObj stream
+ if (FAILED(hr = StmRead.OpenStream(pstg, COMPOBJ_STREAM))) // L"\1CompObj"
+ {
+ goto errRtn;
+ }
+
+ // Read the header from the CompObj stream:
+ //
+ // WORD Byte Order Indicator 02 bytes
+ // WORD Format version 02 bytes
+ // DWORD Originating OS version 04 bytes
+ // DWORD -1 04 bytes
+ // CLSID Class ID 16 bytes
+ // --------
+ // 28 bytes == sizeof(dwBuf)
+
+ Win4Assert(sizeof(CompObjHdr) == 28 &&
+ "Warning: possible packing error in CompObjHdr struct");
+
+ hr = StmRead.Read(&pcod->m_hdr, sizeof(CompObjHdr));
+ if (FAILED(hr))
+ {
+ goto errRtn;
+ }
+
+ // NB: There used to be a check against the OS version here,
+ // but since the version number has been forced to always
+ // be written as Win3.1, checking it would be redundant.
+
+ // Win4Assert(pcod->m_hdr.m_dwOSVer == 0x00000a03);
+#if DBG==1
+ if (pcod->m_hdr.m_dwOSVer != 0x00000a03)
+ {
+ LEDebugOut((DEB_WARN, "ReadCompObjStm found unexpected OSVer %lx",
+ pcod->m_hdr.m_dwOSVer));
+ }
+#endif
+
+ // Get the User type string from the stream (ANSI FORMAT!)
+ if (FAILED(hr = ANSIStmToStr(StmRead, &pcod->m_pszAUserType,
+ &pcod->m_cchUserType)))
+ {
+ goto errRtn;
+ }
+
+ // Get the clipboard format data from the stream
+ if (FAILED(hr = StmToClipfmt(StmRead, // Stream to read from
+ &pcod->m_dwFormatTag, // DWORD clip format
+ &pcod->m_ulFormatID, // DWORD clip type
+ TT_ANSI))) // Use ANSI
+ {
+ goto errRtn;
+ }
+
+ // We have to special-case the ProgID field, because it may not
+ // be present in objects written by early (pre-2.01) versions
+ // of OLE. We only continue when ProgID can be found, but
+ // its absence is not an error, so return what we have so far.
+
+ hr = StmRead.Read(&ulSize, sizeof(ULONG));
+
+ if (FAILED(hr))
+ {
+ // We were unable to read the size field; make sure ulSize is 0
+ ulSize = 0;
+ }
+
+ // The ProgID can be no longer than 39 chars plus a NULL. Other
+ // numbers likely indicate garbage.
+
+ if (ulSize > 40 || 0 == ulSize)
+ {
+#if DBG==1
+ if (ulSize > 40)
+ {
+ LEDebugOut((DEB_WARN,"ReadCompObjStm: ulSize > 40 for ProgID\n"));
+ }
+#endif
+ fExtStm = 0; // No ProgID implies no UNICODE to follow
+ }
+
+ // If it looks like we have a hope of findind the ProgID and maybe
+ // even UNICODE, try to fetch the ProdID
+
+ if (fExtStm)
+ {
+ // Allocate memory for string on our ProgID pointer
+ pcod->m_pszAProgID = (char *) PubMemAlloc(ulSize);
+ if (NULL == pcod->m_pszAProgID)
+ {
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+ if (FAILED(hr = StmRead.Read(pcod->m_pszAProgID, ulSize)))
+ {
+ // OK, we give up on ProgID and the UNICODE, but that's
+ // _not_ reason to fail, since ProgID could just be missing
+
+ pcod->m_cchProgID = 0;
+ PubMemFree(pcod->m_pszAProgID);
+ pcod->m_pszAProgID = NULL;
+ fExtStm = 0;
+ }
+ else
+ {
+ // We managed to get ProgID from the stream, so set the
+ // length in pcod and go looking for the UNICODE...
+ pcod->m_cchProgID = ulSize;
+ }
+ }
+
+ // See if we can find the Magic number
+
+ DWORD dwMagic;
+ if (fExtStm)
+ {
+ if (FAILED(StmRead.Read(&dwMagic, sizeof(dwMagic))))
+ {
+ fExtStm = 0;
+ }
+ }
+
+ if (fExtStm && dwMagic != COMP_OBJ_MAGIC_NUMBER)
+ {
+ fExtStm = 0;
+ }
+
+ // If fExtStm is still TRUE, we go ahead and read the UNICODE
+
+ if (fExtStm)
+ {
+ // Get the UNICODE version of the user type
+ if (FAILED(hr = ReadStringStream(StmRead, &pcod->m_pszOUserType)))
+ {
+ goto errRtn;
+ }
+
+ // Get the clipboard format (UNICODE)
+
+ DWORD dwFormatTag;
+ ULONG ulFormatID;
+ if (FAILED(hr = StmToClipfmt(StmRead, // Stream to read from
+ &dwFormatTag, // DWORD clip format
+ &ulFormatID, // DWORD clip type
+ TT_UNICODE))) // Use UNICODE
+ {
+ goto errRtn;
+ }
+
+ // If we found some form of clipboard format, that implies the ANSI
+ // was missing, so set up all of the fields based on this data.
+
+ if (dwFormatTag)
+ {
+ pcod->m_dwFormatTag = dwFormatTag;
+ pcod->m_ulFormatID = ulFormatID;
+ }
+
+ // Get the UNICODE version of the ProgID. If there was any UNICODE at
+ // all, we know for sure there is a UNICODE ProgID, so no special casing
+ // as was needed for the ANSI version
+
+ if (FAILED(hr = ReadStringStream(StmRead, &pcod->m_pszOProgID)))
+ {
+ goto errRtn;
+ }
+ if (pcod->m_pszOProgID)
+ {
+ pcod->m_cchProgID = _xstrlen(pcod->m_pszOProgID) + 1;
+ }
+ }
+
+ // We successfully read the CompObj stream
+ hr = NOERROR;
+
+errRtn:
+
+ StmRead.Release();
+
+ return(hr);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: StmToClipfmt, PRIVATE INTERNAL
+//
+// Synopsis: Reads the clipboard format from the given stream. Caller
+// specifies whether or not the string format description,
+// if present, should be expected in ANSI or UNICODE format.
+//
+// Effects: If the clipboard format is a length followed by a
+// string, then the string is read and registered as a
+// clipboard format (and the new format number is returned).
+//
+// Arguments: [lpstream] -- pointer to the stream
+// [lpdwCf] -- where to put the clipboard format
+// [lpdTag] -- format type (string, clip, etc)
+// [ttType] -- text type TT_ANSI or TT_UNICODE
+//
+// Returns: hr
+//
+// Algorithm: the format of the stream must be one of the following:
+//
+// 0 No clipboard format
+// -1 DWORD predefined windows clipboard format in
+// the second dword.
+// -2 DWORD predefined mac clipboard format in the
+// second dword. This may be obsolete or
+// irrelevant for us. REVIEW32
+// num STRING clipboard format name string (prefaced
+// by length of string).
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+//--------------------------------------------------------------------------
+
+INTERNAL StmToClipfmt
+ (CStmBufRead & StmRead,
+ DWORD * lpdTag,
+ DWORD * lpdwCf,
+ TXTTYPE ttText)
+{
+ VDATEHEAP();
+
+ HRESULT hr;
+ DWORD dwValue;
+
+ VDATEPTROUT(lpdwCf, DWORD);
+
+ Win4Assert (lpdwCf); // These ptrs are always required
+ Win4Assert (lpdTag);
+
+ // Read the format type tag from the stream
+
+ if (FAILED(hr = StmRead.Read(&dwValue, sizeof(DWORD))))
+ {
+ return hr;
+ }
+
+ *lpdTag = dwValue;
+
+ // If the tag is zero, there is no clipboard format info
+
+ if (dwValue == 0)
+ {
+ *lpdwCf = 0; // NULL cf value
+ }
+
+ // If it is -1, then it is a standard Windows clipboard format
+
+ else if (dwValue == -1L)
+ {
+ // Then this is a NON-NULL predefined windows clipformat.
+ // The clipformat values follows
+
+ if (FAILED(hr = StmRead.Read(&dwValue, sizeof(DWORD))))
+ {
+ return hr;
+ }
+ *lpdwCf = dwValue;
+ }
+
+ // If it is -2, it is a MAC format
+
+ else if (dwValue == -2L)
+ {
+ // Then this is a NON-NULL MAC clipboard format.
+ // The clipformat value follows. For MAC the CLIPFORMAT
+ // is 4 bytes
+
+ if (FAILED(hr = StmRead.Read(&dwValue, sizeof(DWORD))))
+ {
+ return hr;
+ }
+ *lpdwCf = dwValue;
+ return ResultFromScode(OLE_S_MAC_CLIPFORMAT);
+ }
+
+ // Anything but a 0, -1, or -2 indicates a string is to follow, and the
+ // DWORD we already read is the length of the that string
+
+ else
+ {
+ // Allocate enough memory for whatever type of string it is
+ // we expect to find, and read the string
+
+ if (dwValue > MAX_CFNAME)
+ {
+ return ResultFromScode(DV_E_CLIPFORMAT);
+ }
+
+ if (TT_ANSI == ttText) // READ ANSI
+ {
+ char szCf[MAX_CFNAME];
+
+ if (FAILED(hr = StmRead.Read(szCf, dwValue)))
+ {
+ return hr;
+ }
+
+ // Try to register the clipboard format and return the result
+ // (Note: must explicitly call ANSI version)
+
+ if (((*lpdwCf = (DWORD) SSRegisterClipboardFormatA(szCf))) == 0)
+ {
+ return ResultFromScode(DV_E_CLIPFORMAT);
+ }
+ }
+ else // READ UNICODE
+ {
+ OLECHAR wszCf[MAX_CFNAME];
+
+ Win4Assert(dwValue < MAX_CFNAME);
+ if (FAILED(hr=StmRead.Read(wszCf, dwValue * sizeof(OLECHAR))))
+ {
+ return hr;
+ }
+
+ // Try to register the clipboard format and return the result
+
+ if (((*lpdwCf = (DWORD) RegisterClipboardFormat(wszCf))) == 0)
+ {
+ return ResultFromScode(DV_E_CLIPFORMAT);
+ }
+ }
+ }
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetUNICODEUserType, PRIVATE INTERNAL
+//
+// Synopsis: Given a CompObjStmData object, returns the User Type
+// in UNICODE format, converting the ANSI rep as required.
+//
+// Effects: Allocates memory on the caller's ptr to hold the string
+//
+// Arguments: [pcod] -- The CompObjStmData object
+// [pstr] -- Pointer to allocate resultant string on
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+//--------------------------------------------------------------------------
+
+INTERNAL GetUNICODEUserType
+ ( CompObjStmData * pcod,
+ LPOLESTR * pstr )
+{
+ VDATEHEAP();
+ HRESULT hr = NOERROR;
+
+ // Validate and NULL the OUT parameter, or return if none given
+ if (pstr)
+ {
+ VDATEPTROUT(pstr, LPOLESTR);
+ *pstr = NULL;
+ }
+ else
+ {
+ return(NOERROR);
+ }
+
+ // Either get the UNICODE string, or convert the ANSI version and
+ // get it as UNICODE.
+
+ if (pcod->m_cchUserType)
+ {
+ hr = UtGetUNICODEData( pcod->m_cchUserType,
+ pcod->m_pszAUserType,
+ pcod->m_pszOUserType,
+ pstr );
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetUNICODEProgID, PRIVATE INTERNAL
+//
+// Synopsis: Given a CompObjStmData object, returns the ProgID string
+// in UNICODE format, converting the ANSI rep as required.
+//
+// Effects: Allocates memory on the caller's ptr to hold the string
+//
+// Arguments: [pcod] -- The CompObjStmData object
+// [pstr] -- Pointer to allocate resultant string on
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+//--------------------------------------------------------------------------
+
+INTERNAL GetUNICODEProgID
+ ( CompObjStmData * pcod,
+ LPOLESTR * pstr )
+{
+ VDATEHEAP();
+ HRESULT hr = NOERROR;
+
+ // Validate and NULL the OUT parameter, or return if none given
+ if (pstr)
+ {
+ VDATEPTROUT(pstr, LPOLESTR);
+ *pstr = NULL;
+ }
+ else
+ {
+ return(NOERROR);
+ }
+
+ // Either get the UNICODE string, or convert the ANSI version and
+ // get it as UNICODE.
+
+ if (pcod->m_cchProgID)
+ {
+ hr = UtGetUNICODEData( pcod->m_cchProgID,
+ pcod->m_pszAProgID,
+ pcod->m_pszOProgID,
+ pstr );
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetClipFormat, PRIVATE INTERNAL
+//
+// Synopsis: Given a CompObjStmData object, extracts the clipboard format
+// type (none, standard, string).
+//
+// Effects: If string type, memory is allocated on the caller's ptr
+//
+// Arguments: [pcod] -- The CompObjStmData object to extract from
+// [pdwFormatID] -- Tag type OUT parameter
+// [pdwFormatTag] -- Tag OUT parameter
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failures
+// OLE_S_MAC_CLIPFORMAT as a warning that a MAC fmt is returned
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+//--------------------------------------------------------------------------
+
+INTERNAL GetClipFormat
+ ( CompObjStmData * pcod,
+ DWORD * pdwFormatID,
+ DWORD * pdwFormatTag )
+{
+ VDATEHEAP();
+ *pdwFormatTag = (DWORD) pcod->m_dwFormatTag;
+ *pdwFormatID = pcod->m_ulFormatID;
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: PutUNICODEUserType, PRIVATE INTERNAL
+//
+// Synopsis: Given a UNICODE string, stores it in the CompObjDataStm
+// object in ANSI if possible. If the UNICODE -> ANSI
+// conversion is not possible, it is stored in the object
+// in UNICODE.
+//
+// Notes: Input string is duplicated, so it adds no references
+// to the string passed in.
+//
+// Arguments: [pcod] -- The CompObjDataStm object
+// [szUser] -- The UNICODE UserType string
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+//--------------------------------------------------------------------------
+
+INTERNAL PutUNICODEUserType(CompObjStmData * pcod, LPOLESTR szUser)
+{
+ VDATEHEAP();
+
+ HRESULT hr;
+
+ // If no string supplied, clear UserType fields, otherwise
+ // if it can be converted to ANSI, store it an ANSI. Last
+ // resort, store it as UNICODE.
+
+ if (NULL == szUser)
+ {
+ pcod->m_cchUserType = 0;
+
+ PubMemFree(pcod->m_pszAUserType);
+ PubMemFree(pcod->m_pszOUserType);
+ pcod->m_pszAUserType = NULL;
+ pcod->m_pszOUserType = NULL;
+ }
+ else
+ {
+ if (FAILED(hr = UtPutUNICODEData( _xstrlen(szUser)+1,
+ szUser,
+ &pcod->m_pszAUserType,
+ &pcod->m_pszOUserType,
+ &pcod->m_cchUserType )))
+ {
+ return(hr);
+ }
+
+ }
+ return(NOERROR);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: PutUNICODEProgID, PRIVATE INTERNAL
+//
+// Synopsis: Given a UNICODE string, stores it in the CompObjDataStm
+// object in ANSI if possible. If the UNICODE -> ANSI
+// conversion is not possible, it is stored in the object
+// in UNICODE.
+//
+// Notes: Input string is duplicated, so it adds no references
+// to the string passed in.
+//
+// Arguments: [pcod] -- The CompObjDataStm object
+// [szProg] -- The UNICODE ProgID string
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+//--------------------------------------------------------------------------
+
+
+INTERNAL PutUNICODEProgID(CompObjStmData * pcod, LPOLESTR szProg)
+{
+ VDATEHEAP();
+
+ HRESULT hr;
+
+ // If no string supplied, clear ProgID fields, otherwise
+ // if it can be converted to ANSI, store it an ANSI. Last
+ // resort, store it as UNICODE.
+
+ if (NULL == szProg)
+ {
+ pcod->m_cchProgID = 0;
+ PubMemFree(pcod->m_pszAProgID);
+ PubMemFree(pcod->m_pszOProgID);
+ pcod->m_pszAProgID = NULL;
+ pcod->m_pszOProgID = NULL;
+ }
+ else
+ {
+ if (FAILED(hr = UtPutUNICODEData( _xstrlen(szProg)+1,
+ szProg,
+ &pcod->m_pszAProgID,
+ &pcod->m_pszOProgID,
+ &pcod->m_cchProgID )))
+ {
+ return(hr);
+ }
+
+ }
+ return(NOERROR);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: PutClipFormat
+//
+// Synopsis: Stores the clipformat in the internal data structure
+//
+// Effects: Input string is duplicated as required, so no references are
+// kept by this function.
+//
+// Arguments: [pcod] -- The CompObjStmData object
+// [dwFormatTag] -- Format tag (string, clipboard, none)
+// [ulFormatID] -- If format tag is clipboard, what format
+//
+// Returns: NOERROR on success
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+//--------------------------------------------------------------------------
+
+INTERNAL PutClipFormat
+ ( CompObjStmData * pcod,
+ DWORD dwFormatTag,
+ ULONG ulFormatID
+ )
+{
+ VDATEHEAP();
+ pcod->m_dwFormatTag = (ULONG) dwFormatTag;
+ pcod->m_ulFormatID = ulFormatID;
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: WriteCompObjStm, PRIVATE INTERNAL
+//
+// Synopsis: Writes CompObjStmData object to the CompObj stream in
+// the IStorage provided.
+//
+// First the ANSI fields are written (including the ProgID),
+// followed by a MagicNumber, followed by whatever OLESTR
+// versions were required because ANSI fields could not be
+// converted.
+//
+// Destroys any existing CompObj stream!
+//
+// Arguments: [pstg] -- The IStorage to write the stream to
+// [pcod] -- The CompObjStmData object to write out
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failure
+// Various I/O on stream failures
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+//--------------------------------------------------------------------------
+
+INTERNAL WriteCompObjStm(IStorage * pstg, CompObjStmData * pcod)
+{
+ VDATEHEAP();
+
+ HRESULT hr = NOERROR;
+ const ULONG RESERVED = 0;
+ const ULONG ulMagic = COMP_OBJ_MAGIC_NUMBER;
+ CStmBufWrite StmWrite;
+
+
+ // The CompObjStmData parameter must be supplied
+ if (NULL == pcod)
+ {
+ return ResultFromScode(E_INVALIDARG);
+ }
+
+ VDATEIFACE(pstg);
+
+ // Open the CompObj stm for writing (and overwrite it if
+ // if already exists, which is why we _don't_ specify the
+ // STGM_FAILIFTHERE flag)
+
+ if (FAILED(hr = StmWrite.CreateStream(pstg, COMPOBJ_STREAM)))
+ {
+ goto errRtn;
+ }
+
+ // Set up the header
+
+ pcod->m_hdr.m_dwFirstDword = gdwFirstDword;
+
+ // The OSVer _must_ be Win 3.10 (0a03), since the old DLL will bail if
+ // it finds anything else.
+
+ pcod->m_hdr.m_dwOSVer = 0x00000a03; // gdwOrgOSVersion;
+ pcod->m_hdr.m_unused = (DWORD) -1;
+
+ if (ReadClassStg(pstg, &pcod->m_hdr.m_clsClass) != NOERROR)
+ {
+ pcod->m_hdr.m_clsClass = CLSID_NULL;
+ }
+
+ // Write the CompObj stream header
+
+ Win4Assert(sizeof(CompObjHdr) == 28 &&
+ "Warning: possible packing error in CompObjHdr struct");
+
+ if (FAILED(hr = StmWrite.Write(pcod, sizeof(CompObjHdr))))
+ {
+ goto errRtn;
+ }
+
+ // Write the ANSI UserType
+
+ if (FAILED(hr = ANSIStrToStm(StmWrite, pcod->m_pszAUserType)))
+ {
+ goto errRtn;
+ }
+
+ if (TT_ANSI == pcod->ttClipString)
+ {
+ if (FAILED(hr = ClipfmtToStm(StmWrite, // the stream
+ pcod->m_dwFormatTag, // format tag
+ pcod->m_ulFormatID, // format ID
+ TT_ANSI)))// TRUE==use ANSI
+ {
+ goto errRtn;
+ }
+ }
+ else
+ {
+ const ULONG ulDummy = 0;
+ if (FAILED(hr = StmWrite.Write(&ulDummy, sizeof(ULONG))))
+ {
+ goto errRtn;
+ }
+ }
+
+ // Write the ANSI ProgID
+
+ if (FAILED(hr = ANSIStrToStm(StmWrite, pcod->m_pszAProgID)))
+ {
+ goto errRtn;
+ }
+
+ // Write the Magic Number
+
+ if (FAILED(hr = StmWrite.Write(&ulMagic, sizeof(ULONG))))
+ {
+ goto errRtn;
+ }
+
+ // Write the OLESTR version of UserType
+
+ if (FAILED(hr = WriteStringStream(StmWrite, pcod->m_pszOUserType)))
+ {
+ goto errRtn;
+ }
+
+ // If we have to write a UNICODE clipformat string, do it now. If
+ // ANSI was sufficient, just write a 0 to the stream here.
+
+ if (TT_UNICODE == pcod->ttClipString)
+ {
+ if (FAILED(hr = ClipfmtToStm(StmWrite, // the stream
+ pcod->m_dwFormatTag, // format tag
+ pcod->m_ulFormatID, // format ID
+ TT_UNICODE))) // FALSE==use UNICODE
+ {
+ goto errRtn;
+ }
+ }
+ else
+ {
+ const ULONG ulDummy = 0;
+ if (FAILED(hr = StmWrite.Write(&ulDummy, sizeof(ULONG))))
+ {
+ goto errRtn;
+ }
+ }
+
+ // Write the OLESTR version of ProgID
+
+ if (FAILED(hr = WriteStringStream(StmWrite, pcod->m_pszOProgID)))
+ {
+ goto errRtn;
+ }
+
+ hr = StmWrite.Flush();
+
+ // That's it.. clean up and exit
+
+errRtn:
+
+ StmWrite.Release();
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ClipFtmToStm, PRIVATE INTERNAL
+//
+// Synopsis: Writes out the clipboard format information at the
+// current point in the stream. A flag is available
+// to specify whether or not the string format desc
+// (if present) is in ANSI or UNICODE format.
+//
+// Arguments: [pstm] -- the stream to write to
+// [dwFormatTag] -- format tag (string, clipfmt, etc)
+// [ulFormatID] -- if clipfmt, which one
+// [szClipFormat] -- if string format, the string itself
+// [ttText] -- text type: TT_ANSI or TT_UNICODE
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+//--------------------------------------------------------------------------
+
+INTERNAL ClipfmtToStm
+ ( CStmBufWrite & StmWrite,
+ DWORD dwFormatTag,
+ ULONG ulFormatID,
+ TXTTYPE ttText )
+
+{
+ VDATEHEAP();
+
+ HRESULT hr;
+
+ const ULONG ulDummy = 0;
+ switch((DWORD)dwFormatTag)
+ {
+
+ // If the tag is 0, there is no clipboard format info.
+
+ case 0:
+
+ if (FAILED(hr = StmWrite.Write(&ulDummy, sizeof(ULONG))))
+ {
+ return(hr);
+ }
+
+ return(NOERROR);
+
+ // In the -1 and -2 cases (yes, I wish there were constants too) all we
+ // need to write is the format ID
+
+ case -1:
+ case -2:
+
+ // Write the format tag to the stream
+ if (FAILED(hr = StmWrite.Write(&dwFormatTag, sizeof(dwFormatTag))))
+ {
+ return hr;
+ }
+ return(StmWrite.Write(&ulFormatID, sizeof(ulFormatID)));
+
+
+ // In all other cases, we need to write the string raw with termination
+ // (ie: the format tag we've already written was the length).
+
+ default:
+
+
+ if (TT_ANSI == ttText)
+ {
+ char szClipName[MAX_CFNAME];
+ int cbLen = SSGetClipboardFormatNameA(ulFormatID, szClipName, MAX_CFNAME);
+ if (cbLen == 0)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+ cbLen++; // Account for NULL terminator
+ szClipName[cbLen] = '\0';
+ // Write the format tag to the stream
+ if (FAILED(hr = StmWrite.Write(&cbLen, sizeof(cbLen))))
+ {
+ return hr;
+ }
+
+ return (StmWrite.Write(szClipName, cbLen));
+
+ }
+ else
+ {
+ OLECHAR wszClipName[MAX_CFNAME];
+ int ccLen = GetClipboardFormatName(ulFormatID, wszClipName, MAX_CFNAME);
+ if (ccLen == 0)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+ ccLen++; // Account for NULL terminator
+ wszClipName[ccLen] = OLESTR('\0');
+
+ // Write the format tag to the stream
+ if (FAILED(hr = StmWrite.Write(&ccLen, sizeof(ccLen))))
+ {
+ return hr;
+ }
+
+ return (StmWrite.Write(wszClipName, ccLen*sizeof(OLECHAR)));
+ }
+
+ } // end switch()
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ANSIStrToStm, PRIVATE INTERNAL
+//
+// Synopsis: Writes an ANSI string out to a stream, preceded by a ULONG
+// indicating its length (INCLUDING TERMINATOR). If the
+// string is 0-length, or a NULL ptr is passed in, just
+// the length (0) is written, and no blank string is stored
+// in the stream.
+//
+// Arguments: [pstm] -- the stream to write to
+// [str] -- the string to write
+//
+//
+//
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+//--------------------------------------------------------------------------
+
+INTERNAL ANSIStrToStm(CStmBufWrite & StmWrite, LPCSTR str)
+{
+ VDATEHEAP();
+
+ HRESULT hr;
+ ULONG ulDummy = 0;
+ ULONG ulLen;
+
+ // If the pointer is NULL or if it is valid but points to
+ // a 0-length string, _just_ write the 0-length, but no
+ // string.
+
+ if (NULL == str || (ulLen = strlen(str) + 1) == 1)
+ {
+ return(StmWrite.Write(&ulDummy, sizeof(ulDummy)));
+ }
+
+ if (FAILED(hr = StmWrite.Write(&ulLen, sizeof(ulLen))))
+ {
+ return(hr);
+ }
+
+ return StmWrite.Write(str, ulLen);
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ANSIStmToStr, PRIVATE INTERNAL
+//
+// Synopsis: Reads a string from a stream, which is preceded by a ULONG
+// giving its length. If the string OUT parameter is NULL,
+// the string is read but not returned. If the parameter is
+// a valid pointer, memory is allocated on it to hold the str.
+//
+// Arguments: [pstm] -- the stream to write to
+// [pstr] -- the caller's string pointer
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+//--------------------------------------------------------------------------
+
+INTERNAL ANSIStmToStr(CStmBufRead & StmRead, LPSTR * pstr, ULONG * pulLen)
+{
+ VDATEHEAP();
+ LPSTR szTmp = NULL;
+ ULONG ulTmp;
+ HRESULT hr;
+
+ if (pstr)
+ {
+ VDATEPTROUT(pstr, LPSTR);
+ *pstr = NULL;
+ }
+
+ if (pulLen)
+ {
+ VDATEPTROUT(pulLen, ULONG *);
+ *pulLen = 0;
+ }
+
+ // Find out how many bytes are to follow as a string
+
+ if (FAILED(hr = StmRead.Read(&ulTmp, sizeof(ulTmp))))
+ {
+ return(hr);
+ }
+
+ // If none, we can just return now
+
+ if (0 == ulTmp)
+ {
+ return(NOERROR);
+ }
+
+ if (pulLen)
+ {
+ *pulLen = ulTmp;
+ }
+
+ // Allocate a buffer to read the string into
+
+ szTmp = (LPSTR) PubMemAlloc(ulTmp);
+ if (NULL == szTmp)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ if (FAILED(hr = StmRead.Read(szTmp, ulTmp)))
+ {
+ PubMemFree(szTmp);
+ return(hr);
+ }
+
+ // If the caller wanted the string, assign it over, otherwise
+ // just free it now.
+
+ if (pstr)
+ {
+ *pstr = szTmp;
+ }
+ else
+ {
+ PubMemFree(szTmp);
+ }
+
+ return(NOERROR);
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReadFmtUserTypeStg
+//
+// Synopsis: Read ClipFormat, UserType from CompObj stream
+//
+// Arguments: [pstg] -- storage containing CompObj stream
+// [pcf] -- place holder for clip format, may be NULL
+// [ppszUserType] -- place holder for User Type, may be NULL
+//
+// Returns: If NOERROR, *pcf is clip format and *ppszUserType is User Type
+// If ERROR, *pcf is 0 and *ppszUserType is NULL
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: ??-???-?? ? Ported
+// 15-Jul-94 AlexT Make sure *pcf & *pszUserType are clear
+// on error
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI ReadFmtUserTypeStg
+ ( IStorage * pstg,
+ CLIPFORMAT * pcf,
+ LPOLESTR * ppszUserType )
+{
+ OLETRACEOUTEX((API_ReadFmtUserTypeStg,
+ PARAMFMT("pstg= %p, pcf= %p, ppszUserType= %p"),
+ pstg, pcf, ppszUserType));
+
+ VDATEHEAP();
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pstg);
+
+ HRESULT hr;
+ CompObjStmData cod;
+
+ do
+ {
+ // Read the CompObj stream
+ hr = ReadCompObjStm(pstg, &cod);
+ if (FAILED(hr))
+ {
+ // clean up and return
+ break;
+ }
+
+ // Extract the clipboard format
+ if (NULL != pcf)
+ {
+ ULONG ulFormatID = 0;
+ DWORD dwFormatTag = 0;
+
+ if (FAILED(hr = GetClipFormat(&cod, &ulFormatID, &dwFormatTag))
+ && GetScode(hr) != OLE_S_MAC_CLIPFORMAT)
+ {
+ // clean up and return
+ break;
+ }
+
+ *pcf = (CLIPFORMAT) ulFormatID;
+ }
+
+ // Extract the User Type
+ if (NULL != ppszUserType)
+ {
+ if (FAILED(hr = GetUNICODEUserType(&cod, ppszUserType)))
+ {
+ // clean up and return
+ break;
+ }
+ }
+
+ hr = S_OK;
+ } while (FALSE);
+
+ if (FAILED(hr))
+ {
+ // Make sure the out parameters are zeroed out in the failure case
+
+ if (NULL != pcf)
+ {
+ *pcf = 0;
+ }
+
+ if (NULL != ppszUserType)
+ {
+ *ppszUserType = NULL;
+ }
+ }
+
+ OLETRACEOUT((API_ReadFmtUserTypeStg, hr));
+
+ return(hr);
+}
+
+STDAPI ReadFmtProgIdStg
+ ( IStorage * pstg,
+ LPOLESTR * pszProgID )
+{
+ VDATEHEAP();
+
+ HRESULT hr;
+ CompObjStmData cod;
+
+ // Read the CompObj stream
+ if (FAILED(hr = ReadCompObjStm(pstg, &cod)))
+ {
+ return(hr);
+
+ }
+
+ // Extract the User Type
+ if (pszProgID)
+ {
+ if (FAILED(hr = GetUNICODEProgID(&cod, pszProgID)))
+ {
+ return(hr);
+ }
+ }
+ return(NOERROR);
+}
+
+
+
+STDAPI WriteFmtUserTypeStg
+ ( LPSTORAGE pstg,
+ CLIPFORMAT cf,
+ LPOLESTR szUserType)
+{
+ OLETRACEIN((API_WriteFmtUserTypeStg, PARAMFMT("pstg= %p, cf= %x, szUserType= %ws"),
+ pstg, cf, szUserType));
+
+ VDATEHEAP();
+ HRESULT hr;
+ CompObjStmData cod;
+ CLSID clsid;
+ LPOLESTR szProgID = NULL;
+
+ VDATEIFACE_LABEL(pstg, errRtn, hr);
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pstg);
+
+
+ // Read the CompObj stream. If it's not there, we don't care,
+ // we'll build a new one. Some errors, such as E_OUTOFMEMORY, cannot
+ // be overlooked, so we must return them.
+
+ if (FAILED(hr = ReadCompObjStm(pstg, &cod)))
+ {
+ if (hr == ResultFromScode(E_OUTOFMEMORY))
+ {
+ goto errRtn;
+ }
+ }
+
+ // Set the User Type in the Object.
+
+ if (szUserType)
+ {
+ if (FAILED(hr = PutUNICODEUserType(&cod, szUserType)))
+ {
+ goto errRtn;
+ }
+ }
+
+ // Set the ProgID field
+
+ if (ReadClassStg(pstg, &clsid) != NOERROR)
+ {
+ clsid = CLSID_NULL;
+ }
+
+ if (SUCCEEDED(ProgIDFromCLSID (clsid, &szProgID)))
+ {
+ PutUNICODEProgID(&cod, szProgID);
+ }
+
+ if (szProgID)
+ {
+ PubMemFree(szProgID);
+ }
+
+ // Set the clipboard format. 0xC000 is a magical constant which
+ // bounds the standard clipboard format type IDs
+
+ if (cf < 0xC000)
+ {
+ if (0 == cf)
+ {
+ PutClipFormat(&cod, 0, 0); // NULL format
+ }
+ else
+ {
+ PutClipFormat(&cod, (DWORD)-1, cf); // Standard format
+ }
+ }
+ else
+ {
+ PutClipFormat(&cod, MAX_CFNAME, cf); // Custom format
+
+ }
+
+ // Now we have all the info in the CompObjData object.
+ // Now we can write it out to the stream as a big atomic object.
+
+ if (FAILED(hr = WriteCompObjStm(pstg, &cod)))
+ {
+ if (hr == ResultFromScode(E_OUTOFMEMORY))
+ {
+ goto errRtn;
+ }
+ }
+
+ hr = NOERROR;
+
+errRtn:
+ OLETRACEOUT((API_WriteFmtUserTypeStg, hr));
+
+ return hr;
+}
diff --git a/private/ole32/ole232/cache/cachenod.cpp b/private/ole32/ole232/cache/cachenod.cpp
new file mode 100644
index 000000000..81a125c50
--- /dev/null
+++ b/private/ole32/ole232/cache/cachenod.cpp
@@ -0,0 +1,2444 @@
+//+----------------------------------------------------------------------------
+//
+// File:
+// cachenod.cpp
+//
+// Contents:
+//
+// Classes:
+// CCacheNode
+//
+// Functions:
+//
+// History:
+// 31-Jan-95 t-ScottH added Dump method for CCacheNode
+// added DumpCCacheNode API
+// initialize m_dwPresBitsPos in CCacheNode
+// ::Initialize(...)
+// added m_dwPresFlag private data member to
+// keep track of type of IOlePresObj
+// (CGenObject|CMfObject|CEMfObject)
+// 23-Feb-94 alexgo added call tracing
+// 24-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocation
+// 01/11/94 - AlexGo - added VDATEHEAP macros to every function
+// and method
+// 12/07/93 - ChrisWe - make default params to StSetSize explicit
+// 11/22/93 - ChrisWe - replace overloaded ==, != with
+// IsEqualIID and IsEqualCLSID
+// 11/05/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#include <le2int.h>
+
+#pragma SEG(cachenod)
+
+#include <olepres.h>
+#include <olecache.h>
+#include <cachenod.h>
+
+#include <mf.h>
+#include <emf.h>
+#include <gen.h>
+
+#ifdef _DEBUG
+#include <dbgdump.h>
+#endif // _DEBUG
+
+NAME_SEG(Cachenod)
+ASSERTDATA
+
+// declare local function
+#pragma SEG(wGetData)
+INTERNAL wGetData(LPDATAOBJECT lpSrcDataObj, LPFORMATETC lpforetc,
+ LPSTGMEDIUM lpmedium);
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::Initialize, private
+//
+// Synopsis:
+// Routine used by the CCacheNode constructors to do common
+// initialization.
+//
+// Arguments:
+// [advf] -- ADVF flag
+// [pOleCache] -- COleCache this cache node belongs to
+//
+// Notes:
+// [pOleCache] is not reference counted; the cache node is
+// considered to be a part of the implementation of COleCache,
+// and is owned by COleCache.
+//
+// History:
+// 13-Feb-95 t-ScottH initialize m_dwPresBitsPos and new
+// data member m_dwPresFlag
+// 11/05/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_Initialize)
+INTERNAL_(void) CCacheNode::Initialize(DWORD advf, COleCache FAR* pOleCache)
+{
+ VDATEHEAP();
+
+ m_refs = 1; // there is one reference to this
+
+ // initialize other values
+ m_advf = advf;
+ m_usFlag = CCACHENODEF_DIRTY;
+ m_iStreamNum = OLE_INVALID_STREAMNUM;
+ m_dwPresBitsPos = 0;
+ m_dwAdvConnId = NULL;
+ m_pOleCache = pOleCache;
+ m_pDataObj = NULL;
+ m_pPresObj = NULL;
+ m_pPresObjAfterFreeze = NULL;
+ #ifdef _DEBUG
+ m_dwPresFlag = 0;
+ #endif // _DEBUG
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::Uninitialize, private
+//
+// Synopsis:
+// Frees all resources associated with the cache node. Dissociates
+// the cache node from its owning m_pOleCache, in preparation for
+// destruction.
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 11/05/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+INTERNAL_(void) CCacheNode::Uninitialize()
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::Uninitialize ( )\n",
+ this ));
+
+ // This will tear down any advisory connections
+ OnStop();
+
+ // Destroy the presentation object if we have one
+ if (m_pPresObj)
+ {
+ m_pPresObj->Release();
+ m_pPresObj = NULL;
+ }
+
+ // Destroy the presentation object that we had created after freeze,
+ // if there is one
+ if (m_pPresObjAfterFreeze)
+ {
+ m_pPresObjAfterFreeze->Release();
+ m_pPresObjAfterFreeze = NULL;
+ }
+
+ // delete the ptd if it is non-null
+ if (m_foretc.ptd)
+ {
+ PubMemFree(m_foretc.ptd);
+ m_foretc.ptd = NULL;
+ }
+
+ // Make a note that we are not owned by COleCache.
+ m_pOleCache = NULL; // NOTE: no ref count
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::Uninitialize ( )\n",
+ this));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::CCacheNode, public
+//
+// Synopsis:
+// constructor - use this constructor when the cache node is
+// to be loaded later
+//
+// Arguments:
+// [pOleCache] -- pointer to the COleCache that owns this node
+//
+// Notes:
+//
+// History:
+// 11/05/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_ctor)
+CCacheNode::CCacheNode(COleCache FAR* pOleCache)
+{
+ VDATEHEAP();
+
+ m_foretc.cfFormat = NULL;
+ m_foretc.ptd = NULL;
+ m_foretc.dwAspect = NULL;
+ m_foretc.lindex = DEF_LINDEX;
+ m_foretc.tymed = TYMED_HGLOBAL;
+
+ Initialize((DWORD)0, pOleCache);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::CCacheNode, public
+//
+// Synopsis:
+// constructor - use this constructor when all the data to
+// initialize the cache node is available now
+//
+// Arguments:
+// [lpFormatetc] - the format for the presentation that this
+// cache node will hold
+// [advf] - the advise control flags, from ADVF_*
+// [pOleCache] -- pointer to the COleCache that owns this node
+//
+// Notes:
+//
+// History:
+// 11/05/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+CCacheNode::CCacheNode(LPFORMATETC lpFormatetc, DWORD advf,
+ COleCache FAR* pOleCache)
+{
+ VDATEHEAP();
+
+ UtCopyFormatEtc(lpFormatetc, &m_foretc);
+ Initialize(advf, pOleCache);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::~CCacheNode, private
+//
+// Synopsis:
+// destructor
+//
+// Notes:
+//
+// History:
+// 11/05/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+CCacheNode::~CCacheNode()
+{
+ VDATEHEAP();
+
+ // if this is still associated with a COleCache, free all resources
+ if (m_pOleCache != NULL)
+ Uninitialize();
+}
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::GetPresObj, public
+//
+// Synopsis:
+// get a pointer to the existing presentation object, if there
+// is one.
+//
+// Arguments:
+// none
+//
+// Returns:
+// pointer to the current presentation object, if there is one,
+// or NULL
+//
+// Notes:
+//
+// History:
+// 11/05/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_GetPresObj)
+INTERNAL_(LPOLEPRESOBJECT) CCacheNode::GetPresObj(void)
+{
+ VDATEHEAP();
+
+ return m_pPresObj; // NON ref counted pointer
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::GetFormatEtc, public
+//
+// Synopsis:
+// Returns a pointer to the format description for the cache node.
+// The pointed to FORMATETC cannot be changed.
+//
+// Arguments:
+// none
+//
+// Returns:
+// A pointer to the constant FORMATETC for this cache node.
+//
+// Notes:
+//
+// History:
+// 11/05/93 - ChrisWe - file inspection and cleanup
+// changed to return const pointer to avoid struct copy
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_GetFormatEtc)
+INTERNAL_(const FORMATETC FAR *) CCacheNode::GetFormatEtc(void)
+{
+ VDATEHEAP();
+
+ // no copy of ptd is made; the caller can copy if necessary
+ return((const FORMATETC FAR *)&m_foretc);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::CopyStatData, public
+//
+// Synopsis:
+// Copies the stat data for this cache node, but does not include
+// the advise sink
+//
+// Arguments:
+// [lpStatData] -- pointer to where to copy the stat data to
+//
+// Returns:
+//
+// Notes:
+//
+// History:
+// 11/05/93 - ChrisWe - file inspection and cleanup
+// renamed from GetStatData to indicate copying function
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_CopyStatData)
+INTERNAL_(void) CCacheNode::CopyStatData(STATDATA FAR* lpStatData)
+{
+ VDATEHEAP();
+
+ // Here the ptd gets copied.
+ UtCopyFormatEtc(&m_foretc, &(lpStatData->formatetc));
+ // REVIEW, shouldn't we echo the UtCopy... return code as a return here?
+
+ lpStatData->advf = m_advf;
+ lpStatData->pAdvSink = NULL;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::GetAdvf, public
+//
+// Synopsis:
+// return the advise control flag for the cache node
+//
+// Arguments:
+// none
+//
+// Returns:
+// the advf flags for the cache node in a DWORD
+//
+// Notes:
+//
+// History:
+// 11/05/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_GetAdvf)
+INTERNAL_(DWORD) CCacheNode::GetAdvf(void)
+{
+ VDATEHEAP();
+
+ return m_advf;
+}
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::SaveCompleted, public
+//
+// Synopsis:
+// Notify the cache node that the save of this cache node is
+// complete. If the presentation data is not being used for
+// drawing, it can be discarded.
+//
+// Arguments:
+// [iStreamNum] -- the stream number that the presentation was
+// saved to
+// [fDrawCache] -- used to indicate whether or not the cached
+// presentation is to be used for drawing
+//
+// Notes:
+//
+// History:
+// 11/05/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+INTERNAL_(void) CCacheNode::SaveCompleted(int iStreamNum, BOOL fDrawCache)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::SaveCompleted ( %d , "
+ "%lu )\n", this, iStreamNum, fDrawCache ));
+
+ // All the changes have been flushed to the disk.
+ // the cache node data is no longer dirty
+ m_usFlag &= ~CCACHENODEF_DIRTY;
+
+ // this identifies the stream that the node was written to on disk
+ m_iStreamNum = iStreamNum;
+
+ // If this cache node is not being used in drawing, then discard the
+ // presentation data handle. If we need it again later, we can
+ // reload it from the stream.
+ if (!fDrawCache)
+ {
+ if (m_usFlag & CCACHENODEF_FROZEN)
+ {
+ if (m_pPresObjAfterFreeze)
+ m_pPresObjAfterFreeze->DiscardHPRES();
+
+ }
+ else
+ {
+ // REVIEW, shouldn't this be unconditional?
+ // <-- shouldn't be under an "else"?
+ // that is, isn't there an unfrozen presentation,
+ // whether or not the cache node is frozen?
+
+ if (m_pPresObj)
+ {
+ m_pPresObj->DiscardHPRES();
+ }
+
+
+ }
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::SaveCompleted ( )\n",
+ this));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::SetAdvf, public
+//
+// Synopsis:
+// Set new ADVF_ control flags for the advisory connection to
+// this cache node.
+//
+// Effects:
+// Saves the new setting persistently, if a stream has already
+// been associated with this cache node.
+//
+// Arguments:
+// [advf] -- the new advise control flags
+//
+// Returns:
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/05/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_SetAdvf)
+INTERNAL CCacheNode::SetAdvf(DWORD dwAdvf)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::SetAdvf ( %lx )\n",
+ this, dwAdvf));
+
+ LPSTREAM pstm; // stream used to store this cache node, if there is one
+
+ TearDownAdviseConnection();
+ m_advf = dwAdvf; // record the new advise control flags
+ SetupAdviseConnection();
+
+ // get the stream for this cache node, if possible
+ if (pstm = GetStm(FALSE /*fSeekToPresBits*/, STGM_READWRITE))
+ {
+ // save the advise flags if this cache node has a valid stream
+ // assigned. Then we don't have to set the dirty bit.
+ if (FAILED(UtWriteOlePresStmHeader(pstm, &m_foretc, m_advf)))
+ {
+ // if the write failed, set the dirty bit
+ m_usFlag |= CCACHENODEF_DIRTY;
+ }
+
+ pstm->Release();
+
+ }
+ else
+ {
+ // if no stream yet, we have to mark this as dirty
+ m_usFlag |= CCACHENODEF_DIRTY;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::SetAdvf ( %lx )\n",
+ this, NOERROR));
+
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::Delete, public
+//
+// Synopsis:
+// Called to delete a CCacheNode when it is no longer needed by
+// the cache. COleCache uses this to indicate that it is through
+// with this cache node. Once this is called, no method calls
+// against the CCacheNode by the owning cache are valid.
+//
+// Arguments:
+// none
+//
+// Notes:
+// Note that this may not actually destroy the cache node.
+// While it is no longer used, other objects may still be holding
+// on to its IAdviseSink interface. That must be released for
+// the last time to destroy this.
+//
+// History:
+// 11/05/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_Delete)
+INTERNAL_(void) CCacheNode::Delete(void)
+{
+ VDATEHEAP();
+
+#ifdef _DEBUG
+ CCacheNode *pTemp = this;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::Delete ( )\n", this));
+#endif //DEBUG
+
+ Uninitialize();
+
+ // Release our advise sink
+ // As result of this, if the ref count maintained by advise sink becomes
+ // zero (which implies that there are no external references to advise
+ // sink), then the destructor of CCacheNode will be called.
+ Release();
+
+#ifdef _DEBUG
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::Delete ( )\n", pTemp));
+#endif
+
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::Load, public
+//
+// Synopsis:
+// Load a cache node from a stream; only loads the presentation
+// header. (REVIEW, need to see presentation object::Load)
+//
+// Arguments:
+// [lpstream] -- the stream to load the presentation out of
+// [iStreamNum] -- the stream number
+//
+// Returns:
+// REVIEW
+// DV_E_LINDEX, for invalid lindex in stream
+// S_OK
+//
+// Notes:
+// As part of the loading, the presentation object gets created,
+// and loaded from the stream.
+//
+// History:
+// 11/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_Load)
+INTERNAL CCacheNode::Load(LPSTREAM lpstream, int iStreamNum)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::Load ( %lx , %d )\n",
+ this, lpstream, iStreamNum));
+
+ HRESULT error;
+ BOOL fConvert = FALSE; // REVIEW, what's this mean?
+
+ // read the presentation stream header
+ if (error = UtReadOlePresStmHeader(lpstream, &m_foretc, &m_advf,
+ &fConvert))
+ goto errRtn;
+
+ // validate the lindex
+ if (!HasValidLINDEX(&m_foretc))
+ {
+ LEDebugOut((DEB_ERROR, "Invalid lindex found in the stream"));
+ error = ResultFromScode(DV_E_LINDEX);
+ goto errRtn;
+ }
+
+ // Create the appropriate presentation object
+ if (error = CreatePresObject(NULL /*pDataObject*/, fConvert))
+ goto errRtn;
+
+ // if there's no clipboard format, exit
+ if (m_foretc.cfFormat == NULL)
+ {
+ error = NOERROR;
+ goto errRtn;
+ }
+
+ // remember the starting poistion of presentation bits
+ SetPresBitsPos(lpstream);
+
+ // presentation object reads rest of the stream
+ error = m_pPresObj->Load(lpstream, TRUE /*fReadHeaderOnly*/);
+
+errRtn:
+ // in case of error clear the state that got generated in this Load call
+ if (error != NOERROR)
+ {
+ // Destroy the presentation object if we have any
+ if (m_pPresObj)
+ {
+ m_pPresObj->Release();
+ m_pPresObj = NULL;
+ }
+
+ m_foretc.cfFormat = NULL;
+
+ // delete the ptd if it is non-null
+ if (m_foretc.ptd)
+ PubMemFree(m_foretc.ptd);
+
+ }
+ else
+ {
+ m_usFlag &= ~CCACHENODEF_DIRTY;
+ m_iStreamNum = iStreamNum;
+ }
+
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::Load ( %lx )\n",
+ this, error));
+
+ return error;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::Save, public
+//
+// Synopsis:
+// Saves a cache node, including its presentation object,
+// to a stream.
+//
+// Arguments:
+// [pstgSave] -- the storage that will contain the stream
+// [fSameAsLoad] -- is this storage the same one we loaded from
+// [iStreamNum] -- the stream number to save to
+// [fDrawCache] -- used to indicate whether or not the cached
+// presentation is to be used for drawing; if false,
+// the presentation is discarded after saving
+// [fSaveIfSavedBefore] -- instructs the method to save this
+// cache node, even if it's been saved before
+// [lpCntCachesNotSaved] -- a running count of the number of
+// caches that have not been saved
+//
+// Returns:
+// REVIEW
+// S_OK
+//
+// Notes:
+//
+// History:
+// 03/10/94 - AlexT - Don't call SaveCompleted if we don't save!
+// (see logRtn, below)
+// 01/11/94 - AlexGo - fixed compile error (signed/unsigned
+// mismatch)
+// 11/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+
+// Save the CacheNode and its presentation object to the stream
+
+#pragma SEG(CCacheNode_Save)
+INTERNAL CCacheNode::Save(LPSTORAGE pstgSave, BOOL fSameAsLoad,
+ int iStreamNum, BOOL fDrawCache, BOOL fSaveIfSavedBefore,
+ int FAR* lpCntCachesNotSaved)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::Save ( %p , %lu ,"
+ "%d , %lu , %lu , %p )\n", this, pstgSave, fSameAsLoad,
+ iStreamNum, fDrawCache, fSaveIfSavedBefore,
+ lpCntCachesNotSaved));
+
+ HRESULT error = NOERROR; // error status so far
+ LPSTREAM lpstream = NULL; // the stream to save to
+ LPSTORAGE lpStg; // storage the cache is presently stored in
+ OLECHAR szNewName[sizeof(OLE_PRESENTATION_STREAM)/sizeof(OLECHAR)];
+ // the new stream name, if we need one
+ LPOLEPRESOBJECT pPresObj; // the presentation object to write out
+
+ // are we meant to save it to the same stream that it was loaded from?
+ if (fSameAsLoad)
+ {
+ // if we're to save this if it was saved before, but there's
+ // no stream number, OR, we're not to save this again if it was
+ // saved before, and there is a stream number, don't save
+ // this node, and add to the count of caches that have not
+ // been saved
+ if ((fSaveIfSavedBefore && (m_iStreamNum == OLE_INVALID_STREAMNUM))
+ || (!fSaveIfSavedBefore &&
+ (m_iStreamNum != OLE_INVALID_STREAMNUM)))
+ {
+ if (lpCntCachesNotSaved)
+ ++*lpCntCachesNotSaved;
+
+ AssertSz(NOERROR == error, "Error set incorrectly");
+ goto logRtn;
+ }
+
+ // if it's not dirty, and we were to save to the same place,
+ // there's no need to save it again
+ if (!(m_usFlag & CCACHENODEF_DIRTY) &&
+ (m_iStreamNum == iStreamNum))
+ {
+ goto errRtn;
+ }
+ }
+
+ // start with the standard stream name
+ _xstrcpy(szNewName, OLE_PRESENTATION_STREAM);
+
+ // if we want a stream other than '0', change the numeric suffix
+ if (iStreamNum != 0)
+ UtGetPresStreamName(szNewName, iStreamNum);
+
+ if (fSameAsLoad && !(m_usFlag & CCACHENODEF_DIRTY) &&
+ (m_iStreamNum != OLE_INVALID_STREAMNUM))
+ {
+ OLECHAR szOldName[
+ sizeof(OLE_PRESENTATION_STREAM)/sizeof(OLECHAR)];
+ // the old name of the presentation's stream
+
+ // We are being asked to save in to a different stream. Since
+ // we are not dirty we can rename the old stream to a new name.
+
+ // get the storage the cache is presently stored in
+ lpStg = m_pOleCache->GetStg();
+ Assert(lpStg != NULL);
+
+ // create the old presentation stream name
+ _xstrcpy(szOldName, OLE_PRESENTATION_STREAM);
+ if (m_iStreamNum != 0)
+ UtGetPresStreamName(szOldName, m_iStreamNum);
+
+ // delete the stream with the new name, if there is one
+ lpStg->DestroyElement(szNewName);
+
+ // rename the old stream
+ error = lpStg->RenameElement(szOldName, szNewName);
+
+ // if all is well, get out
+ if (error == NOERROR)
+ goto errRtn;
+
+ error = ResultFromScode(STG_E_WRITEFAULT);
+
+ goto errRtn;
+ }
+
+ // We are either dirty or being asked to save into a different storage
+
+ // Create or open (an existing) stream.
+ if (error = OpenOrCreateStream(pstgSave, szNewName, &lpstream))
+ {
+ RESTORE_A5();
+
+ goto errRtn;
+ }
+
+ // if it is not same as load and not dirty we can do stream copy
+ if (!(fSameAsLoad || (m_usFlag & CCACHENODEF_DIRTY)))
+ {
+ LPSTREAM pstmSrc; // stream the presentation was loaded from
+
+ // get source stream
+ if (pstmSrc = GetStm(FALSE /*fSeekToPresBits*/, STGM_READ))
+ {
+ ULARGE_INTEGER ularge_int; // amount of stream to copy
+
+ // initialize to copy all of stream
+ ULISet32(ularge_int, (DWORD)-1L); // REVIEW, need
+ // hi part?
+
+ error = pstmSrc->CopyTo(lpstream, ularge_int, NULL,
+ NULL);
+
+ // release the srouce stream */
+ pstmSrc->Release();
+
+ if (error == NOERROR)
+ {
+ StSetSize(lpstream, 0, TRUE);
+ goto errRtn;
+ }
+ }
+
+ // we might get here if the stream copy failed, or we couldn't
+ // get the source stream; we fall through and follow the
+ // regular procedure
+ }
+
+ // write the presentation stream header
+ if (error = UtWriteOlePresStmHeader(lpstream, &m_foretc, m_advf))
+ goto errRtn;
+
+ // if there is nothing more to write, return success
+ if (m_foretc.cfFormat == NULL)
+ {
+ StSetSize(lpstream, 0, TRUE);
+ goto errRtn;
+ }
+
+ // we want to save the updated presentation that we got after we
+ // froze the aspect.
+ if (m_pPresObjAfterFreeze && !m_pPresObjAfterFreeze->IsBlank())
+ pPresObj = m_pPresObjAfterFreeze;
+ else
+ pPresObj = m_pPresObj;
+
+ // if there's no presentation object, quit
+ if (!pPresObj)
+ {
+ AssertSz(FALSE, "No presentation object");
+ error = ResultFromScode(OLE_E_BLANK);
+ goto errRtn;
+ }
+
+ // remember the starting position of presentation bits
+ SetPresBitsPos(lpstream);
+
+ // ask the presentation object to save itself
+ error = pPresObj->Save(lpstream);
+
+errRtn:
+ // release the stream, if there is one
+ if (lpstream)
+ {
+ lpstream->Release();
+ }
+
+ if ((error == NOERROR) && fSameAsLoad)
+ {
+ SaveCompleted(iStreamNum, fDrawCache);
+ }
+
+logRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::Save ( %lx ) [ %d ]\n",
+ this, error,
+ (lpCntCachesNotSaved)? *lpCntCachesNotSaved : 0));
+
+ return error;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::SetPresBitsPos, private
+//
+// Synopsis:
+// Sets CCacheNode::m_dwPresBitsPos to the point where the
+// presentation begins in the stream associated with this cache
+// node.
+//
+// Arguments:
+// [lpStream] -- the stream the cache node is being saved to
+//
+// Notes:
+//
+// History:
+// 11/06/93 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_SetPresBitsPos)
+INTERNAL_(void) CCacheNode::SetPresBitsPos(LPSTREAM lpStream)
+{
+ VDATEHEAP();
+
+ LARGE_INTEGER large_int; // fed into IStream::Seek to get current pos
+ ULARGE_INTEGER ularge_int; // retrieves the position of the presentation
+
+ LISet32(large_int, 0);
+ lpStream->Seek(large_int, STREAM_SEEK_CUR, &ularge_int);
+ m_dwPresBitsPos = ularge_int.LowPart;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::OnRun, public
+//
+// Synopsis:
+// Inform the cache node that the server is now running; the
+// cache node will set up advisory connections to the data
+// object to be informed of changes to the presentation. If
+// this is called and a data object is already registered in
+// this node, the call is ignored.
+//
+// Arguments:
+// [lpDataObj] -- the data object presented by the newly
+// activated server NB, this is not reference counted
+//
+// Returns:
+// the FORMATETC dwAspect for this cache node
+//
+// Notes:
+//
+// History:
+// 11/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_OnRun)
+INTERNAL_(DWORD) CCacheNode::OnRun(LPDATAOBJECT lpDataObj)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::OnRun ( %p )\n",
+ this, lpDataObj));
+
+ if ((m_pDataObj == NULL) && (lpDataObj != NULL))
+ {
+ m_pDataObj = lpDataObj; // NOTE: no ref count
+ SetupAdviseConnection();
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::OnRun ( %lu )\n",
+ this, m_foretc.dwAspect));
+
+ return(m_foretc.dwAspect);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::OnStop, public
+//
+// Synopsis:
+// Informs the cache node that the server is being deactivated.
+// The cache node tears down any advisory connections it has
+// establised to the data object exposed by the server, and
+// forgets about the data object. If this is called when no
+// live data object is registered with the cache node, the call
+// is ignored.
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 11/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_OnStop)
+INTERNAL_(void) CCacheNode::OnStop()
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::OnStop ( )\n",
+ this ));
+
+ TearDownAdviseConnection();
+
+ // forget the data object
+ m_pDataObj = NULL; // NOTE; no ref count
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::OnStop ( )\n",
+ this));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::CreatePresObject, public
+//
+// Synopsis:
+// Create the presentation object for the cache node. If there
+// is no clipboard format (cfFormat), then query the source data
+// object for one of our preferred formats. If there is no
+// source data object, no error is returned, but no presentation
+// is created
+//
+// Arguments:
+// [lpSrcDataObj] -- data object to use as the basis for the
+// new presentation
+// [fConvert] -- REVIEW, what's this for?
+//
+// Returns:
+//
+// Notes:
+//
+// History:
+// 11/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+// Try to create appropriate presentation object. If cfFormat is NULL, then
+// try to query lpSrcDataObj to see whether it supports one of our standard
+// formats
+#pragma SEG(CCacheNode_CreatePresObject)
+INTERNAL CCacheNode::CreatePresObject(LPDATAOBJECT lpSrcDataObj, BOOL fConvert)
+{
+ VDATEHEAP();
+
+ BOOL fFormatSupported; // is the format we want supported?
+ HRESULT error; // error status so far
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::CreatePresObject ( %lx , "
+ "%lu )\n", this, lpSrcDataObj, fConvert));
+
+ if (lpSrcDataObj)
+ {
+ // check whether object supports the cachenode's format. If the
+ // cachenode format field is NULL, the query will be made for
+ // our standard formats.
+ fFormatSupported = QueryFormatSupport(lpSrcDataObj);
+
+ }
+ else
+ {
+ if (m_foretc.cfFormat == NULL)
+ {
+ // Since data object pointer is NULL, at this moment
+ // we won't be able to say whether the object supports
+ // any of our standard formats. So, we return without
+ // creating presentation object.
+ error = NOERROR;
+ goto errRtn;
+ }
+
+ // assume the format we want is supported
+ fFormatSupported = TRUE;
+ }
+
+ // massage format, if necessary
+ BITMAP_TO_DIB(m_foretc);
+
+ if ((error = CreateOlePresObject(&m_pPresObj, fConvert)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if (fFormatSupported)
+ {
+ error = NOERROR;
+ goto errRtn;
+ }
+
+ error = ResultFromScode(CACHE_S_FORMATETC_NOTSUPPORTED);
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::CreatePresObj ( %lx )\n",
+ this ));
+
+ return error;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::CreateOlePresObject, private
+//
+// Synopsis:
+// Creates a presentation object, according to the clipboard
+// format m_foretc.cfFormat
+//
+// Arguments:
+// [ppPresObject] -- pointer to where to return the pointer to
+// the newly created presentation object
+// [fConvert] -- REVIEW, what's this for?
+//
+// Returns:
+// DV_E_CLIPFORMAT, if object doesn't support one of the standard
+// formats
+// E_OUTOFMEMORY, if we can't allocate the presentation object
+// S_OK
+//
+// Notes:
+//
+// History:
+// 13-Feb-95 t-ScottH added m_dwPresFlag to track type of
+// IOlePresObject
+// 11/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+INTERNAL CCacheNode::CreateOlePresObject(LPOLEPRESOBJECT FAR* ppPresObj,
+ BOOL fConvert)
+{
+ HRESULT error = NOERROR;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::CreateOlePresObject "
+ "( %lx , %lu )\n", this, ppPresObj, fConvert));
+
+ switch(m_foretc.cfFormat)
+ {
+ case NULL:
+ // lpSrcDataObj must be NON-NULL,(ie) object doesn't support
+ // one of our standard formats.
+ *ppPresObj = NULL;
+ return ResultFromScode(DV_E_CLIPFORMAT);
+
+ case CF_METAFILEPICT:
+ *ppPresObj = new FAR CMfObject(this, m_foretc.dwAspect,
+ fConvert);
+ #ifdef _DEBUG
+ // for use with debugger extensions and dump method
+ m_dwPresFlag = CN_PRESOBJ_MF;
+ #endif // _DEBUG
+ break;
+
+ case CF_ENHMETAFILE:
+ *ppPresObj = new FAR CEMfObject(this, m_foretc.dwAspect);
+ #ifdef _DEBUG
+ // for use with debugger extensions and dump method
+ m_dwPresFlag = CN_PRESOBJ_EMF;
+ #endif // _DEBUG
+ break;
+
+
+ default:
+ *ppPresObj = new FAR CGenObject(this, m_foretc.cfFormat,
+ m_foretc.dwAspect);
+ #ifdef _DEBUG
+ // for use with debugger extensions and dump method
+ m_dwPresFlag = CN_PRESOBJ_GEN;
+ #endif // _DEBUG
+ }
+
+ if (!*ppPresObj)
+ {
+ error = ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::CreateOlePresObject "
+ "( %lx ) [ %p ]\n", this, error, *ppPresObj));
+
+ return error;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::GetStm, public
+//
+// Synopsis:
+// Get the stream the presentation is stored in. Optionally
+// position the stream at the point where the presentation
+// data begins
+//
+// Arguments:
+// [fSeekToPresBits] -- position the stream so that the
+// presentation bits would be the next read/written
+// [dwStgAccess] -- the access mode (STGM_*) to open the stream
+// with
+//
+// Returns:
+// NULL, if there is no stream, or the stream cannot be opened
+//
+// Notes:
+//
+// History:
+// 11/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+INTERNAL_(LPSTREAM) CCacheNode::GetStm(BOOL fSeekToPresBits, DWORD dwStgAccess)
+{
+ VDATEHEAP();
+
+ LPSTREAM pstm; // the stream we'll return
+ LPSTORAGE pstg; // the storage to create/open the stream in
+ OLECHAR szName[sizeof(OLE_PRESENTATION_STREAM)/sizeof(OLECHAR)];
+ // the name of the stream
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::GetStm ( %lu , %lx )\n",
+ this, fSeekToPresBits, dwStgAccess));
+
+ // if there's no stream assigned, we can't get it
+ if (m_iStreamNum == OLE_INVALID_STREAMNUM)
+ {
+ pstm = NULL;
+ goto errRtn;
+ }
+
+ // if the cache doesn't own storage, we can't get a stream
+ if ((pstg = m_pOleCache->GetStg()) == NULL)
+ {
+ pstm = NULL;
+ goto errRtn;
+ }
+
+ // begin by copying the default stream name
+ _xstrcpy(szName, OLE_PRESENTATION_STREAM);
+
+ // if we want a stream other than '0', adjust the name
+ if (m_iStreamNum)
+ UtGetPresStreamName(szName, m_iStreamNum);
+
+ // attempt to open the stream
+ if (pstg->OpenStream(szName, NULL,
+ (dwStgAccess | STGM_SHARE_EXCLUSIVE),
+ NULL, &pstm) == NOERROR)
+ {
+ // if we're to position the stream at the presentation, do so
+ if (fSeekToPresBits)
+ {
+ LARGE_INTEGER large_int;
+
+ LISet32(large_int, m_dwPresBitsPos);
+ if (pstm->Seek(large_int, STREAM_SEEK_SET, NULL) !=
+ NOERROR)
+ {
+ // If we can't position, release the stream,
+ // and don't return it.
+ pstm->Release();
+ pstm = NULL;
+ }
+ }
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::GetStm ( %p )\n", this,
+ pstm));
+
+ // return the stream
+ return(pstm);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::Update, public
+//
+// Synopsis:
+// Updates the presentation object in this cache node from
+// the given data object. The update is only done if the
+// [grfUpdf] flags match m_advf specifications, and if
+// there is actually a presentation to update.
+//
+// Arguments:
+// [lpDataObj] -- the data object to use as a source of data
+// [grfUpdf] -- the update control flags
+//
+// Returns:
+// S_FALSE
+// S_OK
+//
+// Notes: BUGBUG::this is a spaghetti function--rewrite
+//
+// History:
+// 11/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+// Update our presentation object from the given data object.
+
+#pragma SEG(CCacheNode_Update)
+INTERNAL CCacheNode::Update(LPDATAOBJECT lpDataObj, DWORD grfUpdf)
+{
+ VDATEHEAP();
+
+ STGMEDIUM medium; // the medium of the presentation
+ FORMATETC foretc; // the format of the presentation
+
+ HRESULT error = NOERROR;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::Update ( %p , %lx )\n",
+ this, lpDataObj, grfUpdf));
+
+ // if no data object is passed in, we can't do the update
+ if (!lpDataObj)
+ {
+ error = ResultFromScode(S_FALSE);
+ goto errRtn;
+ }
+
+ // if the presentation object hasn't been created yet (most probably
+ // because the cfFormat field is NULL), try to create it now.
+ if (!m_pPresObj)
+ CreatePresObject(lpDataObj, FALSE /*fConvert*/);
+
+ // if the presentation object hasn't been created even after we have a
+ // source data object, then it implies that the source data object
+ // doesn't support our standard formats; we can't update
+ if (!m_pPresObj)
+ {
+ error = ResultFromScode(S_FALSE);
+ goto errRtn;
+ }
+
+ // if we're only supposed to update if the presentation object is
+ // blank, and it's not blank, there's nothing to do
+ if ((grfUpdf & UPDFCACHE_ONLYIFBLANK) && (!m_pPresObj->IsBlank()))
+ {
+ error = NOERROR;
+ goto errRtn;
+ }
+
+ // update if this cachenode is created with ADVFCACHE_ONSAVE
+ if ((grfUpdf & UPDFCACHE_ONSAVECACHE) && (m_advf & ADVFCACHE_ONSAVE))
+ goto update;
+
+ // Normally cachenodes created with ADVF_NODATA will not get updated
+ // unless update flag is UPDFCACHE_NODATACACHE. But if cache advise
+ // flags has ADVFCACHE_ONSAVE then we allow it to get updated.
+ // (see bug # 464 in ole2issues database)
+ if (m_advf & ADVF_NODATA)
+ {
+ if (grfUpdf & UPDFCACHE_NODATACACHE)
+ goto update;
+
+ error = NOERROR;
+ goto errRtn;
+ }
+
+ // update if this cachenode is created with ADVF_DATAONSTOP
+ if ((grfUpdf & UPDFCACHE_ONSTOPCACHE) && (m_advf & ADVF_DATAONSTOP))
+ goto update;
+
+ // Update if this is a normal cache node
+ // (i.e. the cache node that gets live updates)
+ if ((grfUpdf & UPDFCACHE_NORMALCACHE)
+ && !(m_advf & (ADVFCACHE_ONSAVE | ADVF_DATAONSTOP)))
+ {
+ // Note: ADVF_NODATA is already covered above. We won't come
+ // here if the cache advise flags has ADVF_NODATA
+ goto update;
+ }
+
+ // Update if this cache node is blank
+ if ((grfUpdf & UPDFCACHE_IFBLANK) && m_pPresObj->IsBlank())
+ goto update;
+
+ goto errRtn;
+
+update:
+ // initialize the medium
+ medium.tymed = TYMED_NULL;
+ medium.hGlobal = NULL;
+ medium.pUnkForRelease = NULL;
+
+ // make a copy of the desired format; this may mutate below
+ foretc = m_foretc;
+
+ // let the object create the medium.
+ if (wGetData(lpDataObj, &foretc, &medium) != NOERROR)
+ {
+ error = ResultFromScode(S_FALSE);
+ goto errRtn;
+ }
+
+ // take the ownership of the data.
+
+ if (SetDataWDO(&foretc, &medium, TRUE /*fRelease*/, lpDataObj) != NOERROR)
+ {
+ error = ResultFromScode(S_FALSE);
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::Update ( %lx )\n",
+ this, error));
+
+ return error;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::SetDataWDO, public
+//
+// Synopsis:
+// Data is set into the presentation object, if this cache node
+// is not frozen. If the cache node is frozen, then the
+// new presentation data is stashed into the m_pPresObjAfterFreeze
+// presentation object, which is created, if there isn't already
+// one. If data is successfully set in the presentation object,
+// and the node is not frozen, the cache is notified that this
+// is dirty.
+//
+// Arguments:
+// [lpForetc] -- the format of the new data
+// [lpStgmed] -- the storage medium the new data is one
+// [fRelease] -- passed on to the presentation object; indicates
+// whether or not to release the storage medium
+// [pDataObj] -- pointer to the revelant source data object
+//
+// Returns:
+// E_FAIL
+// REVIEW, result from presentationObject::SetData
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+INTERNAL CCacheNode::SetDataWDO(LPFORMATETC lpForetc, LPSTGMEDIUM lpStgmed,
+ BOOL fRelease, IDataObject * pDataObj)
+{
+ VDATEHEAP();
+
+ HRESULT hresult; // error status so far
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::SetDataWDO ( %p , %p , %lu )"
+ "\n", this, lpForetc, lpStgmed, fRelease));
+
+ // if the cache is frozen, stash the data in the m_pPresObjAfterFreeze
+ // presentation for later
+ if (m_usFlag & CCACHENODEF_FROZEN)
+ {
+ // if there's no presentation, create one now
+ if (!m_pPresObjAfterFreeze)
+ {
+ if (CreateOlePresObject(&m_pPresObjAfterFreeze,
+ FALSE) != NOERROR)
+ {
+ hresult = ResultFromScode(E_FAIL);
+ goto errRtn;
+ }
+ }
+
+ hresult = m_pPresObjAfterFreeze->SetDataWDO(lpForetc, lpStgmed, fRelease, pDataObj);
+ }
+ else
+ {
+ // the cache is not frozen, set data in regular presentation
+ // object
+ // REVIEW, why is it that we don't create m_pPresObj if it
+ // doesn't already exist?
+ if (m_pPresObj)
+ hresult = m_pPresObj->SetDataWDO(lpForetc, lpStgmed,
+ fRelease, pDataObj);
+ else
+ hresult = ReportResult(0, E_FAIL, 0, 0);
+ }
+
+ // NotifyOleCache so that it can generate view notifcation as well as
+ // set the dirty flag
+ if (hresult == NOERROR)
+ {
+ m_usFlag |= CCACHENODEF_DIRTY;
+ NotifyOleCache(TRUE /*fDirty*/);
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::SetDataWDO ( %lx )\n", this,
+ hresult));
+
+ return hresult;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::Freeze, public
+//
+// Synopsis:
+// Freeze the cachenode. From here on, OnDataChange() is ignored
+// until this node is unfrozen (Unfreeze().) This is not
+// persistent across Save/Load. (If we receive OnDataChange(),
+// the new data is stashed away in m_pPresAfterFreeze, but is
+// not exported to the outside of the cache node.)
+//
+// Arguments:
+// none
+//
+// Returns:
+// VIEW_S_ALREADY_FROZEN
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_Freeze)
+INTERNAL CCacheNode::Freeze()
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::Freeze ( )\n",
+ this));
+
+ // if already frozen, return error
+ if (m_usFlag & CCACHENODEF_FROZEN)
+ {
+ hresult = ResultFromScode(VIEW_S_ALREADY_FROZEN);
+ }
+ else
+ {
+ m_usFlag |= CCACHENODEF_FROZEN;
+ hresult = NOERROR;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::Freeze ( %lx )\n",
+ this, hresult));
+
+ return hresult;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::Unfreeze, public
+//
+// Synopsis:
+// Unfreeze the cachenode. If there have been changes to
+// the presentation data since the node was frozen, the node
+// is updated to reflect those changes. From this point on,
+// OnDataChange() notifications are no longer ignored.
+//
+// Arguments:
+// none
+//
+// Returns:
+// OLE_E_NOCONNECTION, if the node was not frozen (REVIEW scode)
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_Unfreeze)
+INTERNAL CCacheNode::Unfreeze()
+{
+ VDATEHEAP();
+ HRESULT hresult;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::UnFreeze ( )\n", this ));
+
+ // if not frozen, return error
+ if (!(m_usFlag & CCACHENODEF_FROZEN))
+ {
+ hresult = ResultFromScode(OLE_E_NOCONNECTION);
+ goto errRtn;
+ }
+
+ // node is no longer frozen
+ m_usFlag &= ~CCACHENODEF_FROZEN;
+
+ // If we have a non-NULL m_pPresObjAfterFreeze, and it is not blank,
+ // then make that current.
+ if (m_pPresObjAfterFreeze)
+ {
+ if (m_pPresObjAfterFreeze->IsBlank())
+ {
+ // It's no good. Get rid of it.
+ m_pPresObjAfterFreeze->Release();
+ }
+ else
+ {
+ // Destroy the frozen presentation object
+ if (m_pPresObj)
+ m_pPresObj->Release();
+
+ // make m_pPresObjAfterFreeze the current one
+ m_pPresObj = m_pPresObjAfterFreeze;
+
+ // notify the olecache that the data has changed
+ NotifyOleCache(TRUE /*fDirty*/);
+ }
+
+ // we no longer have an "after-freeze" presentation object
+ m_pPresObjAfterFreeze = NULL;
+ }
+
+ hresult = NOERROR;
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::UnFreeze ( %lx )\n", this,
+ hresult));
+
+ return hresult;
+
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::QueryFormatSupport, private
+//
+// Synopsis:
+// Check to see if the data object supports the presentation
+// format specified for this cache node. If no format is
+// specified, check for any of our preferred formats. If
+// the format is CF_DIB, and that is not available, check for
+// CF_BITMAP.
+//
+// Arguments:
+// [lpDataObj] -- the data object
+//
+// Returns:
+// TRUE if the format is supported, FALSE otherwise
+//
+// Notes:
+//
+// History:
+// 11/09/93 - ChrisWe - no longer necessary to reset format
+// after UtQueryPictFormat, since that leaves descriptor
+// untouched now
+// 11/09/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_QueryFormatSupport)
+INTERNAL_(BOOL) CCacheNode::QueryFormatSupport(LPDATAOBJECT lpDataObj)
+{
+ VDATEHEAP();
+ BOOL fRet = FALSE;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::QueryFormatSupport ( %p )\n",
+ this, lpDataObj));
+
+ if (!lpDataObj)
+ {
+ fRet = FALSE;
+ goto errRtn;
+ }
+
+ // is there no format specified?
+ if (m_foretc.cfFormat == NULL)
+ {
+ // check for our preferred format
+ if (UtQueryPictFormat(lpDataObj, &m_foretc))
+ {
+ fRet = TRUE;
+ goto errRtn;
+ }
+ }
+ else
+ {
+ // check to see if the specified format is supported
+ if (lpDataObj->QueryGetData(&m_foretc) == NOERROR)
+ {
+ fRet = TRUE;
+ goto errRtn;
+ }
+
+ // if the format was DIB, and that was not supported,
+ // check to see if BITMAP is supported instead
+ if (m_foretc.cfFormat == CF_DIB)
+ {
+ FORMATETC foretc = m_foretc;
+
+ foretc.cfFormat = CF_BITMAP;
+ foretc.tymed = TYMED_GDI;
+ if (lpDataObj->QueryGetData(&foretc) == NOERROR)
+ {
+ fRet = TRUE;
+ }
+ }
+ }
+
+ errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::QueryFormatSupport"
+ " ( %lu )\n", this, fRet));
+
+ return fRet;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::SetupAdviseConnection, private
+//
+// Synopsis:
+// Set up data advise sourced by the server object, and sunk
+// by this cache node, if there is a valid data object.
+//
+// Arguments:
+// none
+//
+// Returns:
+// OLE_E_BLANK, if no presentation object exists or can be
+// created
+// DATA_E_FORMATETC
+// OLE_E_ADVISENOTSUPPORTED
+// S_OK, indicates successful advise, or no data object
+//
+// Notes:
+//
+// History:
+// 11/09/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_SetupAdviseConnection)
+INTERNAL CCacheNode::SetupAdviseConnection(void)
+{
+ VDATEHEAP();
+
+ DWORD grfAdvf; // local copy of advise control flags
+ HRESULT hresult; // error status
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::SetupAdviseConnection"
+ " ( )\n", this ));
+
+ // if there's no data object, there's nothing to do
+ if (m_pDataObj == NULL)
+ {
+ hresult = NOERROR;
+ goto errRtn;
+ }
+
+ // if don't have a presentation object try to create one.
+ if (!m_pPresObj)
+ CreatePresObject(m_pDataObj, FALSE /*fConvert*/);
+
+ // if we couldn't create one then return error.
+ if (!m_pPresObj)
+ {
+ hresult = ResultFromScode(OLE_E_BLANK);
+ goto errRtn;
+ }
+
+ // if cache advise flags have ADVF_NODATA then don't setup
+ // any advise connection
+ if (m_advf & ADVF_NODATA)
+ {
+ hresult = NOERROR;
+ goto errRtn;
+ }
+
+ // copy base advise control flags
+ grfAdvf = m_advf;
+
+ // only the DDE layer looks for these 2 bits
+ grfAdvf |= (ADVFDDE_ONSAVE | ADVFDDE_ONCLOSE);
+
+ // if we were to get data when it is saved, get it instead when
+ // the object is stopped; this prevents us having to reload the
+ // object here to get this, if the server is saved after we've
+ // terminated, or the local handler is no longer running
+ if (grfAdvf & ADVFCACHE_ONSAVE)
+ {
+ grfAdvf &= (~ADVFCACHE_ONSAVE);
+ grfAdvf |= ADVF_DATAONSTOP;
+ }
+
+ // These two flags are not meaningful to the cache
+ // REVIEW, why not?
+ grfAdvf &= (~(ADVFCACHE_NOHANDLER | ADVFCACHE_FORCEBUILTIN));
+
+ // if we already have data, then remove the ADVF_PRIMEFIRST
+ if (!m_pPresObj->IsBlank())
+ grfAdvf &= (~ADVF_PRIMEFIRST);
+
+ // set up the advise with the data object, using massaged flags
+ if ((hresult = m_pDataObj->DAdvise(&m_foretc, grfAdvf,
+ (IAdviseSink FAR *)this, &m_dwAdvConnId)) != NOERROR)
+ {
+ // The advise failed. If the requested format was CF_DIB,
+ // try for CF_BITMAP instead.
+ if (m_foretc.cfFormat == CF_DIB)
+ {
+ FORMATETC foretc; // new format descriptor
+
+ // create new format descriptor
+ foretc = m_foretc;
+ foretc.cfFormat = CF_BITMAP;
+ foretc.tymed = TYMED_GDI;
+
+ // request advise
+ hresult = m_pDataObj->DAdvise(&foretc, grfAdvf,
+ (IAdviseSink FAR *)this,
+ &m_dwAdvConnId);
+ }
+ }
+
+errRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::SetupAdviseConnection "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::TearDownAdviseConnection, private
+//
+// Synopsis:
+// Remove advise connection from data object to this sink. Returns
+// immediately if there is no advise connection.
+//
+// Arguments:
+// none
+//
+// Returns:
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/09/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_TearDownAdviseConnection)
+INTERNAL CCacheNode::TearDownAdviseConnection()
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::TearDownAdviseConnection"
+ " ( )\n", this ));
+
+ // if there's no advise connection, nothing to do
+
+ if (m_dwAdvConnId != 0 && m_pDataObj)
+ {
+ // if there is a data object, unadvise from it
+
+ // ignore error on the Unadvise since it not reported
+ // reliably and may be can't-call-out-in-async.
+ m_pDataObj->DUnadvise(m_dwAdvConnId);
+ CoDisconnectObject((IUnknown FAR *)this, NULL);
+ }
+
+ // there's no longer an advise connection
+ m_dwAdvConnId = 0;
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::TearDownAdviseConnection"
+ " ( %lx )\n", this, NOERROR));
+
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::NotifyOleCache, private
+//
+// Synopsis:
+// Notify the cache this cache node belongs to that the
+// content of this cache node is dirty. This cache node is
+// identified by its aspect and lindex. No notification is
+// delivered if the cache is frozen.
+//
+// Arguments:
+// [fDirty] -- indicates that the cache is dirty
+//
+// Notes:
+//
+// History:
+// 11/09/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+inline INTERNAL_(void) CCacheNode::NotifyOleCache(BOOL fDirty)
+{
+ VDATEHEAP();
+
+ if (!(m_usFlag & CCACHENODEF_FROZEN))
+ {
+ m_pOleCache->OnChange(m_foretc.dwAspect, m_foretc.lindex,
+ fDirty);
+ }
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::QueryInterface, public
+//
+// Synopsis:
+// implementation of IUnknown::QueryInterface
+//
+// Arguments:
+// [iid] -- IID of the desired interface
+// [ppvObj] -- pointer to where to return the requested interface
+//
+// Returns:
+// E_NOINTERFACE
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/09/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_QueryInterface)
+STDMETHODIMP CCacheNode::QueryInterface(REFIID iid, LPVOID FAR* ppvObj)
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+
+ VDATEPTROUT(ppvObj, LPVOID);
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::QueryInterface ( %p , %p )"
+ "\n", this, iid, ppvObj));
+
+ if (IsEqualIID(iid, IID_IUnknown) ||
+ IsEqualIID(iid, IID_IAdviseSink))
+ {
+ *ppvObj = (IAdviseSink FAR *)this;
+ AddRef();
+ hresult = NOERROR;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ hresult = ResultFromScode(E_NOINTERFACE);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::QueryInterface ( %lx )"
+ " [ %p ]\n", this, hresult, *ppvObj));
+
+ return hresult;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::AddRef, public
+//
+// Synopsis:
+// implements IUnknown::AddRef
+//
+// Arguments:
+// none
+//
+// Returns:
+// the reference count of this object
+//
+// Notes:
+//
+// History:
+// 11/09/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_AddRef)
+STDMETHODIMP_(ULONG) CCacheNode::AddRef(void)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::AddRef ( )\n", this));
+
+ m_refs++;
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::Release ( %lu )\n", this,
+ m_refs));
+
+ return m_refs;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::Release, public
+//
+// Synopsis:
+// implements IUnknown::Release
+//
+// Arguments:
+// none
+//
+// Returns:
+// the reference count of the object
+//
+// Notes:
+//
+// History:
+// 11/09/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_Release)
+STDMETHODIMP_(ULONG) CCacheNode::Release(void)
+{
+ VDATEHEAP();
+
+ ULONG cRefs;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::Release ( )\n", this ));
+
+ if ( (cRefs = --m_refs) == 0)
+ {
+ LEDebugOut((DEB_ITRACE, "%p DELETED CCacheNode\n", this));
+ delete this;
+ }
+
+ // the this pointer may be invalid here, but all we want is it's
+ // value.
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::Release ( %lu )\n", this,
+ cRefs));
+
+ return cRefs;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheNode::OnDataChange, public
+//
+// Synopsis:
+// The cache node is notified that the data it is interested in
+// has changed. The cache node records the new version of the
+// data, and notifies the cache that it belongs to that data
+// has changed
+//
+// Arguments:
+// [lpForetc] -- the format of the new data
+// [lpStgmed] -- the storage medium of the new data
+//
+// Notes:
+//
+// History:
+// 11/09/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheNode_OnDataChange)
+STDMETHODIMP_(void) CCacheNode::OnDataChange(FORMATETC FAR* lpForetc,
+ STGMEDIUM FAR* lpStgmed)
+{
+ VDATEHEAP();
+
+ VOID_VDATEPTRIN(lpForetc, FORMATETC);
+ VOID_VDATEPTRIN(lpStgmed, STGMEDIUM);
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CCacheNode::OnDataChange "
+ "( %p , %p )\n", this, lpForetc, lpStgmed));
+
+ // It is possible for this to be called after the cache node
+ // has been disassociated from its owning cache. If that has
+ // happened, do nothing
+ if (m_pOleCache == NULL)
+ {
+ goto errRtn;
+ }
+
+ // if there's no storage medium, there's no data to copy
+ if (lpStgmed->tymed == TYMED_NULL)
+ NotifyOleCache(FALSE /*fDirty*/);
+ else
+ {
+ // the cache node shouldn't exist with this setting
+ Assert(!(m_advf & ADVF_NODATA));
+
+ // make a copy of the data
+ SetData(lpForetc, lpStgmed, FALSE /*fRelease*/);
+ }
+
+errRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT CCacheNode::OnDataChange ( )\n",
+ this ));
+
+ return;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCacheNode::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppsz] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 31-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CCacheNode::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszFORMATETC;
+ char *pszADVF;
+ char *pszPresObj;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(1500);
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "No. of References = ";
+ dstrDump << m_refs << endl;
+
+ pszFORMATETC = DumpFORMATETC(&m_foretc, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "FORMATETC: " << endl;
+ dstrDump << pszFORMATETC;
+ CoTaskMemFree(pszFORMATETC);
+
+ pszADVF = DumpADVFFlags(m_advf);
+ dstrDump << pszPrefix << "Advise Flags = ";
+ dstrDump << pszADVF << endl;
+ CoTaskMemFree(pszADVF);
+
+ dstrDump << pszPrefix << "Cache Node Flag = ";
+ if (m_usFlag & CCACHENODEF_FROZEN)
+ {
+ dstrDump << "CCACHENODEF_FROZEN ";
+ }
+ else if (m_usFlag & CCACHENODEF_DIRTY)
+ {
+ dstrDump << "CCACHENODEF_DIRTY ";
+ }
+ else
+ {
+ dstrDump << "No FLAG is set! ";
+ }
+ dstrDump << "(" << (void *)m_usFlag << ")" << endl;
+
+ dstrDump << pszPrefix << "Advise Connection ID = ";
+ dstrDump << m_dwAdvConnId << endl;
+
+ dstrDump << pszPrefix << "Byte offset to Pres. bits = ";
+ dstrDump << m_dwPresBitsPos << endl;
+
+ dstrDump << pszPrefix << "Stream No. with Pres. = ";
+ dstrDump << m_iStreamNum << endl;
+
+ // possible recursion if we call COleCache::Dump
+ dstrDump << pszPrefix << "pCOleCache = ";
+ dstrDump << m_pOleCache << endl;
+
+ dstrDump << pszPrefix << "pIDataObject = ";
+ dstrDump << m_pDataObj << endl;
+
+ dstrDump << pszPrefix << "IOlePresObj implementation= ";
+ switch (m_dwPresFlag)
+ {
+ case CN_PRESOBJ_GEN:
+ dstrDump << "CGenObject" << endl;
+ break;
+ case CN_PRESOBJ_MF:
+ dstrDump << "CMfObject" << endl;
+ break;
+ case CN_PRESOBJ_EMF:
+ dstrDump << "CEMfObject" << endl;
+ break;
+ default:
+ dstrDump << "Cannot resolve" << endl;
+ }
+
+ if (m_pPresObj != NULL)
+ {
+ pszPresObj = DumpIOlePresObj(m_pPresObj, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "IOlePresObj:" << endl;
+ dstrDump << pszPresObj;
+ CoTaskMemFree(pszPresObj);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "pIOlePresObj = ";
+ dstrDump << m_pPresObj << endl;
+ }
+
+ if (m_pPresObjAfterFreeze != NULL)
+ {
+ pszPresObj = DumpIOlePresObj(m_pPresObjAfterFreeze, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "IOlePresObj (after freeze):" << endl;
+ dstrDump << pszPresObj;
+ CoTaskMemFree(pszPresObj);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "pIOlePresObjAfterFreeze = ";
+ dstrDump << m_pPresObjAfterFreeze << endl;
+ }
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCCacheNode, public (_DEBUG only)
+//
+// Synopsis: calls the CCacheNode::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pCN] - pointer to CCacheNode
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 31-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCCacheNode(CCacheNode *pCN, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pCN == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pCN->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// wGetData, internal
+//
+// Synopsis:
+// Fetch the data from the data object in the requested format.
+// If the fetch fails, and the requested format was CF_DIB,
+// try CF_BITMAP as an alternative.
+//
+// Arguments:
+// [lpSrcDataObj] -- source data object
+// [lpforetc] -- desired data format
+// [lpmedium] -- if successful, the storage medium containing
+// the requested data
+//
+// Returns:
+// DATA_E_FORMATETC
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/09/93 - ChrisWe - modified to not alter the requested
+// format unless the subsequent CF_BITMAP request succeeds.
+// 11/09/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(wGetData)
+INTERNAL wGetData(LPDATAOBJECT lpSrcDataObj, LPFORMATETC lpforetc,
+ LPSTGMEDIUM lpmedium)
+{
+ VDATEHEAP();
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN wGetData ( %p , %p , %p )\n",
+ NULL, lpSrcDataObj, lpforetc, lpmedium));
+
+ // get the data in the requested format
+ if ((hresult = lpSrcDataObj->GetData(lpforetc, lpmedium)) != NOERROR)
+ {
+ // GetData failed. If the requested format was CF_DIB,
+ // then try CF_BITMAP instead.
+ if (lpforetc->cfFormat == CF_DIB)
+ {
+ FORMATETC foretc; // copy of requested format
+
+ // copy the base format descriptor; try CF_BITMAP
+ foretc = *lpforetc;
+ foretc.cfFormat = CF_BITMAP;
+ foretc.tymed = TYMED_GDI;
+
+ hresult = lpSrcDataObj->GetData(&foretc, lpmedium);
+ if (hresult == NOERROR)
+ {
+ lpforetc->cfFormat = CF_BITMAP;
+ lpforetc->tymed = TYMED_GDI;
+ }
+ }
+
+ // GetData failed. If the requested format was CF_ENHMETAFILE,
+ // silently retry for standard metafile instread.
+
+ if (lpforetc->cfFormat == CF_ENHMETAFILE)
+ {
+ FORMATETC foretc; // copy of requested format
+
+ foretc = *lpforetc;
+ foretc.cfFormat = CF_METAFILEPICT;
+ foretc.tymed = TYMED_MFPICT;
+
+ hresult = lpSrcDataObj->GetData(&foretc, lpmedium);
+ if (hresult == NOERROR)
+ {
+ lpforetc->cfFormat = CF_METAFILEPICT;
+ lpforetc->tymed = TYMED_MFPICT;
+ }
+ }
+ }
+
+ AssertOutStgmedium(hresult, lpmedium);
+
+ LEDebugOut((DEB_ITRACE, "%p OUT wGetData ( %lx )\n", NULL, hresult));
+
+ return hresult;
+}
+
+
+
+
diff --git a/private/ole32/ole232/cache/dacache.cpp b/private/ole32/ole232/cache/dacache.cpp
new file mode 100644
index 000000000..f90e5f30c
--- /dev/null
+++ b/private/ole32/ole232/cache/dacache.cpp
@@ -0,0 +1,645 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// dacache.cpp
+//
+// Contents:
+// implementation of the data advise cache - CDataAdviseCache
+//
+// Classes:
+// CDataAdviseCache
+//
+// Functions:
+//
+// History:
+// 31-Jan-95 t-ScottH add Dump method to CDataAdviseCache and
+// DumpCDataAdviseCache API
+// 24-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocation
+// 01/11/94 - AlexGo - added VDATEHEAP macros to every function
+// and method
+// 11/02/93 - ChrisWe - file inspection and cleanup
+// 12/15/92 - JasonFul - Created
+//
+//-----------------------------------------------------------------------------
+
+#include <le2int.h>
+
+#pragma SEG(dacache)
+
+#include <dacache.h>
+#include <reterr.h>
+
+#ifdef _DEBUG
+#include <dbgdump.h>
+#include <daholder.h>
+#endif // _DEBUG
+
+ASSERTDATA
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDataAdviseCache::CreateDataAdviseCache, static public
+//
+// Synopsis:
+// Creates an instance of the CDataAdviseCache
+//
+// Arguments:
+// [pp] -- pointer to a location to where to return the
+// newly created CDataAdviseCache
+//
+// Returns:
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 11/02/93 - ChrisWe - file cleanup and inspection
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CreateDataAdviseCache)
+FARINTERNAL CDataAdviseCache::CreateDataAdviseCache(LPDATAADVCACHE FAR* pp)
+{
+ VDATEHEAP();
+
+ VDATEPTRIN(pp, LPDATAADVCACHE);
+
+ // try to allocate the CDataAdviseCache
+ if(NULL == (*pp = new DATAADVCACHE))
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+ // initialize the DataAdviseHolder member
+ if(CreateDataAdviseHolder(&((*pp)->m_pDAH)) != NOERROR)
+ {
+ // free the DataAdviseCache
+ delete *pp;
+ *pp = NULL;
+
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ return(NOERROR);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDataAdviseCache::CDataAdviseCache, private
+//
+// Synopsis:
+// constructor
+//
+// Arguments:
+// none
+//
+// Notes:
+// This is private because it does not create a fully
+// formed CDataAdviseCache. m_pDAH must be allocated before
+// this can be used. That is done by the static member
+// CreateDataAdviseCache, which first calls this
+//
+// History:
+// 11/02/93 - ChrisWe - file cleanup and inspection
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDataAdviseCache_ctor)
+CDataAdviseCache::CDataAdviseCache():
+ m_mapClientToDelegate(MEMCTX_TASK)
+{
+ VDATEHEAP();
+
+ //now allocated with system allocator
+ //Assert(CoMemctxOf(this) == MEMCTX_TASK);
+
+ // no data advise holder allocated yet
+ m_pDAH = NULL;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDataAdviseCache::~CDataAdviseCache, public
+//
+// Synopsis:
+// destructor
+//
+// Arguments:
+// none
+//
+// Requires:
+// successful call to CreateDataAdviseCache
+//
+// Notes:
+//
+// History:
+// 11/02/93 - ChrisWe - file cleanup and inspection
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDataAdviseCache_dtor)
+CDataAdviseCache::~CDataAdviseCache()
+{
+ VDATEHEAP();
+
+ // release the data advise holder
+ if( m_pDAH )
+ {
+ m_pDAH->Release();
+ }
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDataAdviseCache::Advise, public
+//
+// Synopsis:
+// Records an advise sink for later use. The sink will be
+// registered with the data object, if there is one, and
+// will be remembered for later registration with the data object,
+// in case it should go away, and return later.
+//
+// Effects:
+//
+// Arguments:
+// [pDataObject] -- the data object that the advise sink is
+// interested in changes to; may be null if the
+// data object isn't running
+// [pFetc] -- the format the advise sink would like to recieve
+// new data in
+// [advf] -- advise control flags ADVF_*
+// [pAdvise] -- the advise sink
+// [pdwClient] -- a token identifying the connection
+//
+// Returns:
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 11/02/93 - ChrisWe - file cleanup and inspection
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDataAdviseCache_Advise)
+HRESULT CDataAdviseCache::Advise(LPDATAOBJECT pDataObject,
+ FORMATETC FAR* pFetc, DWORD advf, LPADVISESINK pAdvise,
+ DWORD FAR* pdwClient)
+ // first 4 parms are as in DataObject::Advise
+{
+ VDATEHEAP();
+
+ DWORD dwDelegate = 0; // the delegate connection number
+ HRESULT hr;
+
+ // if there is a data object, ask to be advised of changes
+ if(pDataObject != NULL)
+ RetErr(pDataObject->DAdvise(pFetc, advf, pAdvise, &dwDelegate));
+
+ // if there is no data object, (i.e. the object is not active,
+ // dwDelegate is zero
+
+ // Here we are using the data advise holder only to hold advise
+ // connections. We are not going to use it to send OnDataChange to
+ // sinks.
+
+ // REVIEW, handling of ADVF_ONLYONCE seems broken...
+ // it's clear that we can't cope with this flag properly; we have
+ // no way of knowing when the notification takes place, and therefore
+ // we can't remove the entry from m_pDAH. The notification may have
+ // taken place above, and it may not have. If the data object wasn't
+ // around, then the advise request here is lost, and the sink will
+ // never be notified. Or, if the request isn't PRIMEFIRST, and the
+ // data object is deactivated, then the data object loses the request,
+ // and on subsequent activation, we won't readvise it on EnumAndAdvise.
+ // So, what good are we for ONLYONCE sinks? What does this break?
+ if(advf & ADVF_ONLYONCE)
+ return NOERROR;
+
+ // keep a local copy of the advise
+ hr = m_pDAH->Advise(NULL, pFetc, advf, pAdvise, pdwClient);
+
+ // if we failed to keep a local reference to the advise sink,
+ // we won't be able to maintain this mapping, so remove the
+ // advise on the data object, if there is one
+ if (hr != NOERROR)
+ {
+ Exit1:
+ if (pDataObject != NULL)
+ pDataObject->DUnadvise(dwDelegate);
+
+ return(hr);
+ }
+
+ // create a map entry from *pdwClient -> dwDelegate
+
+ // if the map entry creation failed, undo all work
+ if (m_mapClientToDelegate.SetAt(*pdwClient, dwDelegate) != TRUE)
+ {
+ // map failed to allocate memory, undo advise since we won't
+ // be able to find this one again
+ m_pDAH->Unadvise(*pdwClient);
+
+ // map entry creation must have failed from lack of allocation
+ hr = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+ // undo the advise on the data object
+ goto Exit1;
+ }
+
+ return(NOERROR);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDataAdviseCache::Unadvise, public
+//
+// Synopsis:
+// Remove an advise sink from the list of sinks the advise cache
+// maintains; the sink is also removed from the list of items
+// registered with the data object, if the data object is provided
+//
+// Effects:
+//
+// Arguments:
+// [pDataObject] -- the data object, if it is running, or NULL
+// [dwClient] -- the token that identifies this connection
+//
+// Returns:
+// OLE_E_NOCONNECTION, for a bad dwClient
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/02/93 - ChrisWe - file cleanup and inspection
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDataAdviseCache_Unadvise)
+HRESULT CDataAdviseCache::Unadvise(IDataObject FAR* pDataObject, DWORD dwClient)
+{
+ VDATEHEAP();
+
+ DWORD dwDelegate;
+
+ // retrieve dwDelegate before removing from map
+ if(pDataObject != NULL)
+ RetErr(ClientToDelegate(dwClient, &dwDelegate));
+
+ // do these first so error from remote unadvise is last(which might
+ // be sync call during async dispatch
+
+ RetErr(m_pDAH->Unadvise(dwClient));
+
+ // If the above line succeeded, Remove Key must succeed.
+ Verify(TRUE == m_mapClientToDelegate.RemoveKey(dwClient));
+
+ // Delegate connection could be 0 if it did not accept the Advise
+ if(pDataObject != NULL && dwDelegate != 0)
+ {
+ // Unadvise is asynchronous, don't worry about return value
+ pDataObject->DUnadvise(dwDelegate);
+ }
+
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDataAdviseCache::EnumAdvise, public
+//
+// Synopsis:
+// returns an enumerator over the advisory connections
+//
+// Arguments:
+// [ppenumAdvise] -- pointer to where to return the enumerator
+//
+// Returns:
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 11/02/93 - ChrisWe - file cleanup and inspection
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDataAdviseCache_EnumAdvise)
+HRESULT CDataAdviseCache::EnumAdvise(LPENUMSTATDATA FAR* ppenumAdvise)
+{
+ VDATEHEAP();
+
+ return m_pDAH->EnumAdvise(ppenumAdvise);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDataAdviseCache::ClientToDelegate, private
+//
+// Synopsis:
+// returns the delegate connection id for a given client
+// connection id
+//
+// Arguments:
+// [dwClient] -- the client connection identifier
+// [pdwDelegate] -- pointer to where to return the delegate
+// connection identifier
+//
+// Returns:
+// OLE_E_NOCONNECTION, for a bad dwClient
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/02/93 - ChrisWe - file cleanup and inspection
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDataAdviseCache_ClientToDelegate)
+HRESULT CDataAdviseCache::ClientToDelegate(DWORD dwClient,
+ DWORD FAR* pdwDelegate)
+{
+ VDATEHEAP();
+
+ VDATEPTRIN(pdwDelegate, DWORD);
+ DWORD dwDelegate = *pdwDelegate = 0;
+
+ if (FALSE == m_mapClientToDelegate.Lookup(dwClient, dwDelegate))
+ return(ReportResult(0, OLE_E_NOCONNECTION, 0, 0));
+
+ *pdwDelegate = dwDelegate;
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CDataAdviseCache::EnumAndAdvise, public
+//
+// Synopsis:
+// Enumerate all the advise sinks registered in the data advise
+// cache. For each one, either register it with the
+// given data object, or deregister it, depending on [fAdvise].
+// Does not change what sinks are known to the data advise cache.
+//
+// Effects:
+//
+// Arguments:
+// [pDataDelegate] -- a data object that the advise sinks
+// are interested in
+// [fAdvise] -- if TRUE, register the advise sinks with
+// pDataDelegate object (with IDataObject::DAdvise();) if
+// FALSE, the deregister the advise sinks
+// (with DUnadvise().)
+//
+// Returns:
+// OLE_E_NOCONNECTION, if the mapping is corrupt (REVIEW!)
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/04/93 - ChrisWe - file cleanup and inspection
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CDataAdviseCache_EnumAndAdvise)
+HRESULT CDataAdviseCache::EnumAndAdvise(LPDATAOBJECT pDataDelegate,
+ BOOL fAdvise)
+{
+ VDATEHEAP();
+
+ VDATEIFACE(pDataDelegate);
+ LPENUMSTATDATA penumAdvise; // enumerator for the data advise holder
+ DWORD dwDelegate; // delegate connection id for the current connection
+ STATDATA statdata; // filled in by the penumAdvise enumerator
+ HRESULT hresult = NOERROR; // current error status
+
+ // get an enumerator from the data advise holder
+ RetErr(m_pDAH->EnumAdvise(&penumAdvise));
+
+ // repeat for each advise sink in the data advise holder...
+ while(NOERROR == penumAdvise->Next(1, &statdata, NULL))
+ {
+ if(fAdvise)
+ {
+ // It is possible that the delegate's Advise will fail
+ // even though we allowed the advise on the loaded
+ // object to succeed(because the delegate is "pickier".)
+ if(NOERROR==pDataDelegate->DAdvise(&statdata.formatetc,
+ statdata.advf, statdata.pAdvSink,
+ &dwDelegate))
+ {
+ // we know the key is present; this SetAt
+ // should not fail
+ Verify(m_mapClientToDelegate.SetAt(
+ statdata.dwConnection,
+ dwDelegate));
+ }
+ }
+ else // unadvise
+ {
+ if((hresult=ClientToDelegate(statdata.dwConnection,
+ &dwDelegate)) != NOERROR)
+ {
+ AssertSz(0, "Corrupt mapping");
+ UtReleaseStatData(&statdata);
+ goto errRtn;
+ }
+
+ if(dwDelegate != 0)
+ {
+ if(NOERROR==pDataDelegate->DUnadvise(
+ dwDelegate))
+ {
+ // we know the key is present; this
+ // SetAt should not fail
+ Verify(m_mapClientToDelegate.SetAt(
+ statdata.dwConnection,
+ 0));
+ }
+ else
+ {
+ LEDebugOut((DEB_IWARN,
+ "WARNING: Delegate rejected unadvise\n"));
+ ;
+ }
+ }
+ }
+ UtReleaseStatData(&statdata);
+ }
+
+ errRtn:
+
+ // release the enumerator
+ penumAdvise->Release();
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDataAdviseCache::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppsz] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 31-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CDataAdviseCache::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszDAH;
+ char *pszCMapDD;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(1000);
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ if (m_pDAH != NULL)
+ {
+ pszDAH = DumpCDAHolder((CDAHolder *)m_pDAH, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CDAHolder: " << endl;
+ dstrDump << pszDAH;
+ CoTaskMemFree(pszDAH);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "pIDataAdviseHolder = " << m_pDAH << endl;
+ }
+
+ pszCMapDD = DumpCMapDwordDword(&m_mapClientToDelegate, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "Map of Clients to Delegate:" << endl;
+ dstrDump << pszCMapDD;
+ CoTaskMemFree(pszCMapDD);
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCDataAdviseCache, public (_DEBUG only)
+//
+// Synopsis: calls the CDataAdviseCache::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pDAC] - pointer to CDataAdviseCache
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 31-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCDataAdviseCache(CDataAdviseCache *pDAC, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pDAC == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pDAC->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
diff --git a/private/ole32/ole232/cache/daytona/makefile b/private/ole32/ole232/cache/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/ole232/cache/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/ole232/cache/daytona/sources b/private/ole32/ole232/cache/daytona/sources
new file mode 100644
index 000000000..cef9057af
--- /dev/null
+++ b/private/ole32/ole232/cache/daytona/sources
@@ -0,0 +1,78 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = ole232
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= cache
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..\..\inc
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+
+SOURCES= \
+ ..\cachenod.cpp \
+ ..\dacache.cpp \
+ ..\olecache.cpp
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
diff --git a/private/ole32/ole232/cache/depend.mk b/private/ole32/ole232/cache/depend.mk
new file mode 100644
index 000000000..fe8aa9a74
--- /dev/null
+++ b/private/ole32/ole232/cache/depend.mk
@@ -0,0 +1,91 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\cachenod.obj $(OBJDIR)\cachenod.lst: .\cachenod.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\cachenod.h $(CAIROLE)\ole232\inc\gen.h \
+ $(CAIROLE)\ole232\inc\mf.h $(CAIROLE)\ole232\inc\ole2int.h \
+ $(CAIROLE)\ole232\inc\olecache.h $(CAIROLE)\ole232\inc\olepres.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\malloc.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\wchar.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\widewrap.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winmm.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
+$(OBJDIR)\dacache.obj $(OBJDIR)\dacache.lst: .\dacache.cpp \
+ $(CAIROLE)\ole232\inc\dacache.h $(CAIROLE)\ole232\inc\map_dwdw.h \
+ $(CAIROLE)\ole232\inc\reterr.h $(CAIROLE)\common\cobjerr.h \
+ $(CAIROLE)\common\rpcferr.h $(CAIROLE)\h\coguid.h \
+ $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h $(CAIROLE)\h\initguid.h \
+ $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h $(CAIROLE)\h\ole2dbg.h \
+ $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h $(CAIROLE)\h\storage.h \
+ $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h $(CAIROLE)\ih\ole2sp.h \
+ $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\olecache.obj $(OBJDIR)\olecache.lst: .\olecache.cpp \
+ $(CAIROLE)\ih\ole1cls.h $(CAIROLE)\ole232\inc\cachenod.h \
+ $(CAIROLE)\ole232\inc\olecache.h $(CAIROLE)\ole232\inc\olepres.h \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\limits.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\malloc.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\wchar.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\widewrap.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winmm.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
diff --git a/private/ole32/ole232/cache/dirs b/private/ole32/ole232/cache/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/ole232/cache/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/ole232/cache/filelist.mk b/private/ole32/ole232/cache/filelist.mk
new file mode 100644
index 000000000..048221e66
--- /dev/null
+++ b/private/ole32/ole232/cache/filelist.mk
@@ -0,0 +1,51 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = cache.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CPPFILES = \
+ .\cachenod.cpp \
+ .\dacache.cpp \
+ .\olecache.cpp \
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PFILE =
+
+
+!include $(CAIROLE)\ole232\ole.mk
diff --git a/private/ole32/ole232/cache/makefile b/private/ole32/ole232/cache/makefile
new file mode 100644
index 000000000..1725b5e9a
--- /dev/null
+++ b/private/ole32/ole232/cache/makefile
@@ -0,0 +1,26 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1992.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/ole232/cache/olecache.cpp b/private/ole32/ole232/cache/olecache.cpp
new file mode 100644
index 000000000..3d1a6e648
--- /dev/null
+++ b/private/ole32/ole232/cache/olecache.cpp
@@ -0,0 +1,6339 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// olecache.cpp
+//
+// Contents:
+// Ole default presentation cache implementation
+//
+// Classes:
+// COleCache - ole multiple presentation cache
+// CCacheEnum - enumerator for COleCache
+//
+// Functions:
+// CreateDataCache
+//
+// History:
+// 31-Jan-95 t-ScottH add Dump methods to COleCache
+// CCacheEnum
+// CCacheEnumFormatEtc
+// add the following APIs: DumpCOleCache
+// DumpCCacheEnum
+// DumpCCacheEnumFormatEtc
+// moved CCacheEnumFormatEtc def'n to header file
+// added flag to COLECACHEFLAGS to indicate aggregation
+// (_DEBUG only)
+// 01/09/95 - t-ScottH - change VDATETHREAD to accept a this
+// pointer, and added VDATETHREAD to IViewObject:: methods
+// (COleCache::CCacheViewImpl:: )
+// 03/01/94 - AlexGo - Added call tracing to AddRef/Release
+// implementations
+// 02/08/94 - ChrisWe - 7297: need implementation of
+// FORMATETC enumerator
+// 01/24/94 alexgo first pass at converting to Cairo-style
+// memory allocation
+// 01/11/94 - AlexGo - added VDATEHEAP macros to every function
+// and method.
+// 12/10/93 - AlexT - header file clean up, include ole1cls.h
+// 12/09/93 - ChrisWe - incremented pointer in COleCache::GetNext()
+// 11/30/93 - alexgo - fixed bugs with GETPPARENT usage
+// 11/23/93 - ChrisWe - introduce use of CACHEID_NATIVE,
+// CACHEID_GETNEXT_GETALL, CACHEID_GETNEXT_GETALLBUTNATIVE
+// for documentary purposes
+// 11/22/93 - ChrisWe - replace overloaded ==, != with
+// IsEqualIID and IsEqualCLSID
+// 07/04/93 - SriniK - Added the support for reading PBrush,
+// MSDraw native objects, hence avoid creating
+// presentation cache/stream. Also started writing static
+// object data into "OLE_CONTENTS" stream in placeable
+// metafile format for static metafile and DIB File
+// format for static dibs. This enabled me to provide
+// support for converting static objects. Also added code
+// to support converting static metafile to MSDraw object
+// and static DIB to PBrush object.
+// 06/04/93 - SriniK - Added the support for demand loading and
+// discarding the caches.
+// 11/12/92 - SriniK - created
+//
+//-----------------------------------------------------------------------------
+
+//
+// A Brief Story about Cache IDs:
+//
+// Although I'm sure the true intent was to only to confuse mere mortals
+// by randomly applying a modulus value to the cache id value, I think it
+// works like this:
+//
+// When a node has never occupied this slot, its ID is simply its index
+// into the array of present nodes. When a node is detached from the cache,
+// the cache node pointer is cleared (signifying an emtpy slot), but its ID is
+// left in the slot. When a new node is placed in this slot, it assumes
+// the ID of the old node, plus MAX_CACHELIST_ITEMS. Thus if this constant
+// is 100 (which it was last I looked), when node 5 is detached, and a new
+// node is later added at this slot, it receives ID 105.
+//
+// I believe the intention was that this prevented apps from accidentally
+// using ID 5 and getting the data from ID 105 by mistake (ie: referencing
+// a stale connection).
+#include <le2int.h>
+
+#pragma SEG(olecache)
+
+#include <olepres.h>
+#include <olecache.h>
+#include <cachenod.h>
+#include <ole1cls.h>
+
+#ifdef _DEBUG
+#include <dbgdump.h>
+#endif // _DEBUG
+
+NAME_SEG(OleCache)
+ASSERTDATA
+
+#ifndef WIN32
+#ifndef _MAC
+const LONG lMaxSmallInt = 32767;
+const LONG lMinSmallInt = -32768;
+#else
+
+#ifdef MAC_REVIEW
+Review IS_SMALL_INT.
+#endif
+#include <limits.h>
+
+#define lMaxSmallInt SHRT_MAX
+#define lMinSmallInt SHRT_MIN
+#endif
+
+#define IS_SMALL_INT(lVal) \
+((HIWORD(lVal) && ((lVal > lMaxSmallInt) || (lVal < lMinSmallInt))) \
+ ? FALSE : TRUE)
+
+#endif // WIN32
+
+#define FREEZE_CONSTANT 143 // Used by Freeze() and Unfreeze()
+
+// predefined CACHEIDs
+#define CACHEID_INVALID ((DWORD)(-1))
+#define CACHEID_NATIVE 0
+
+// The CACHEID_GETNEXT_* values can be used when beginning an enumeration
+// with the GetNext() functions to begin the enumeration at a particular
+// place.
+#define CACHEID_GETNEXT_GETALL ((DWORD)(-1))
+#define CACHEID_GETNEXT_GETALLBUTNATIVE 0
+
+
+// This was the original code...
+
+/*
+#define VERIFY_TYMED_SINGLE_VALID_FOR_CLIPFORMAT(pfetc) {\
+ if ((pfetc->cfFormat==CF_METAFILEPICT && pfetc->tymed!=TYMED_MFPICT)\
+ || ( (pfetc->cfFormat==CF_BITMAP || \
+ pfetc->cfFormat == CF_DIB ) \
+ && pfetc->tymed!=TYMED_GDI)\
+ || (pfetc->cfFormat!=CF_METAFILEPICT && \
+ pfetc->cfFormat!=CF_BITMAP && \
+ pfetc->cfFormat!=CF_DIB && \
+ pfetc->tymed!=TYMED_HGLOBAL)) \
+ return ResultFromScode(DV_E_TYMED); \
+}
+*/
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// CheckTymedCFCombination (Internal)
+//
+// Synopsis:
+// Verifies that the combination of clipformat and tymed is
+// valid to the cache.
+//
+// Arguments:
+// [pfetc] -- The candidate FORMATETC
+//
+// Returns:
+// S_OK For a valid combination
+// CACHE_S_FORMATETC_NOTSUPPORTED For a combination which can be
+// cached, but not drawn by the cache
+// DV_E_TYMED For all other combinations
+//
+// Rules:
+//
+// 1> (CMF && TMF) || (CEM && TEM) || (CB && TG) || (CD && TH) => S_OK
+// (TH && ~CD) => CACHE_S_FORMATETC_NOTSUPPORTED
+//
+// 2> (~S_OK && ~CACHE_S_FORMATETC_NOTSUPPORTED) => DV_E_TYMED
+//
+// Where: CMF == CF_METAFILEPICT
+// CEM == CF_ENHMETAFILE
+// CB == CF_BITMAP
+// CD == CF_FIB
+// TMF == TYMED_MFPICT
+// TEM == TYMED_ENHMETAFILE
+// TG == TYMED_GDI
+// TH == TYMED_HGLOBAL
+//
+// Notes:
+// Since CACHE_S_FORMATETC_NOTSUPPORTED was never implemented in
+// 16-bit, we return S_OK in its place if we are in the WOW.
+//
+// History:
+// 01/07/94 DavePl Created
+//
+//-----------------------------------------------------------------------------
+
+INTERNAL_(HRESULT) CheckTymedCFCombination(LPFORMATETC pfetc)
+{
+
+ HRESULT hr;
+
+ // CF_METAFILEPICT on TYMED_MFPICT is a valid combination
+
+ if (pfetc->cfFormat == CF_METAFILEPICT && pfetc->tymed == TYMED_MFPICT)
+ {
+ hr = S_OK;
+ }
+
+ // CF_ENHMETAFILE on TYMED_ENHMF is a valid combination
+
+ else if (pfetc->cfFormat == CF_ENHMETAFILE && pfetc->tymed == TYMED_ENHMF)
+ {
+ hr = S_OK;
+ }
+
+ // CF_BITMAP on TYMED_GDI is a valid combination
+
+ else if (pfetc->cfFormat == CF_BITMAP && pfetc->tymed == TYMED_GDI)
+ {
+ hr = S_OK;
+ }
+
+ // CF_DIB on TYMED_HGLOBAL is a valid combination
+
+ else if (pfetc->cfFormat == CF_DIB && pfetc->tymed == TYMED_HGLOBAL)
+ {
+ hr = S_OK;
+ }
+
+ // Anything else on TYMED_HGLOBAL is valid, but we cannot draw it
+
+ else if (pfetc->tymed == TYMED_HGLOBAL)
+ {
+ hr = IsWOWThread() ? S_OK : CACHE_S_FORMATETC_NOTSUPPORTED;
+ }
+
+ // Any other combination is invalid
+
+ else
+ {
+ hr = DV_E_TYMED;
+ }
+
+ return hr;
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// IsSameAsObjectFormatEtc, internal
+//
+// Synopsis:
+// REVIEW, checks to see if [lpforetc] is compatible with
+// [cfFormat]. If [lpforetc] doesn't have a format set,
+// sets it to cfFormat, which is then assumed to be
+// one of CF_METAFILEPICT, or CF_DIB.
+//
+// Arguments:
+// [lpforetc] -- a pointer to a FORMATETC
+// [cfFormat] -- a clipboard format
+//
+// Returns:
+// DV_E_ASPECT, if the aspect isn't DVASPECT_CONTENT
+// DV_E_LINDEX, DV_E_CLIPFORMAT if the lindex or clipboard
+// formats don't match
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+INTERNAL IsSameAsObjectFormatEtc(LPFORMATETC lpforetc, CLIPFORMAT cfFormat);
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// CreateDataCache, public
+//
+// Synopsis:
+// Creates an instance of COleCache, the default presentation
+// cache used by Ole.
+//
+// Arguments:
+// [pUnkOuter] -- pointer to outer unknown, if this is being
+// aggregated
+// [rclsid] -- the class that the cache should assume for itself
+// [iid] -- the interface the user would like returned
+// [ppv] -- pointer to where to return the requested interface
+//
+// Returns:
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 11/15/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CreateDataCache)
+STDAPI CreateDataCache(IUnknown FAR* pUnkOuter, REFCLSID rclsid, REFIID iid,
+ LPVOID FAR* ppv)
+{
+ OLETRACEIN((API_CreateDataCache, PARAMFMT("pUnkOuter= %p, rclsid= %I, iid= %I, ppv= %p"),
+ pUnkOuter, &rclsid, &iid, ppv));
+
+ VDATEHEAP();
+
+ HRESULT error;
+ COleCache FAR* lpCOleCache; // the newly allocated cache
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&pUnkOuter);
+
+ // NULL for pUnkOuter is OK
+ if (pUnkOuter)
+ {
+ VDATEIFACE_LABEL(pUnkOuter, errRtn, error);
+ if (!IsEqualIID(iid, IID_IUnknown))
+ {
+ // being aggregated but they did not request IUnknown
+ error = E_INVALIDARG;
+ goto errRtn;
+ }
+ }
+
+ // allocate new cache
+ lpCOleCache = (COleCache FAR*) new FAR COleCache(pUnkOuter, rclsid);
+
+ // if insufficient memory, return
+ if (!lpCOleCache)
+ {
+ *ppv = NULL;
+
+ error = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ // if we're being aggregated, return private IUnknown
+ if (pUnkOuter)
+ {
+ *ppv = (void FAR *)(IUnknown FAR *)&lpCOleCache->m_UnkPrivate;
+ error = NOERROR;
+ }
+ else
+ {
+ // get requested interface on cache
+ error = lpCOleCache->QueryInterface(iid, ppv);
+
+ // release local pointer to cache and return
+ lpCOleCache->Release();
+ }
+
+ CALLHOOKOBJECTCREATE(error, rclsid, iid, (IUnknown **)ppv);
+
+errRtn:
+ OLETRACEOUT((API_CreateDataCache, error));
+
+ return error;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::COleCache, public
+//
+// Synopsis:
+// constructor
+//
+// Arguments:
+// [pUnkOuter] -- outer unknown, if being aggregated
+// [rclsid] -- the class id the cache should assume for itself
+//
+// Notes:
+// The IUnknown returned is not the private unknown. The private
+// unknown is pOleCache->m_UnkPrivate
+//
+// History:
+// 11/15/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_ctor)
+COleCache::COleCache(IUnknown FAR* pUnkOuter, REFCLSID rclsid)
+{
+ VDATEHEAP();
+
+ GET_A5();
+
+ // set reference count for return from constructor
+ m_refs = 1;
+
+ // initialize flags
+ m_uFlag = 0;
+
+ // aggregate, or use our own IUnknown for outer IUnknown
+
+ if (NULL == pUnkOuter)
+ {
+ m_pUnkOuter = &m_UnkPrivate;
+ }
+ else
+ {
+ m_pUnkOuter = pUnkOuter;
+
+ // this is for the debugger extensions
+ // (since we can not compare m_pUnkOuter to m_pUnkPrivate with copied mem)
+ // it is only used in the ::Dump method
+ #ifdef _DEBUG
+ m_uFlag |= COLECACHEF_AGGREGATED;
+ #endif // _DEBUG
+ }
+
+ // no storage yet
+ m_pStg = NULL;
+
+ // initialize cache list
+ m_uCacheNodeCnt = 0;
+ m_uCacheNodeMax = 0;
+ m_pCacheList = NULL;
+ LEVERIFY( GrowCacheList() ); // REVIEW(davepl) Need error case here?
+
+ m_pCacheEnum = NULL; // pointer to cache enumerator list
+
+ // no advise sink connected for the view object
+ m_pViewAdvSink = NULL;
+ m_advfView = 0;
+ m_aspectsView = 0;
+
+ // id of cache node which was used in the previous Draw call
+ m_dwDrawCacheId = CACHEID_INVALID;
+
+ // no frozen aspects
+ m_dwFrozenAspects = NULL;
+
+ // no data object yet
+ m_pDataObject = NULL; // non-NULL if running; no ref count
+
+ m_clsid = rclsid;
+
+ // set flags for the format, based on the clsid
+
+ if (IsEqualCLSID(m_clsid, CLSID_StaticMetafile))
+ {
+ m_cfFormat = CF_METAFILEPICT;
+ m_uFlag |= COLECACHEF_STATIC | COLECACHEF_FORMATKNOWN;
+
+ }
+ else if (IsEqualCLSID(m_clsid, CLSID_StaticDib))
+ {
+ m_cfFormat = CF_DIB;
+ m_uFlag |= COLECACHEF_STATIC | COLECACHEF_FORMATKNOWN;
+
+ }
+ else if (IsEqualCLSID(m_clsid, CLSID_PBrush))
+ {
+ m_cfFormat = CF_DIB;
+ m_uFlag |= COLECACHEF_PBRUSHORMSDRAW | COLECACHEF_FORMATKNOWN;
+
+ }
+ else if (IsEqualCLSID(m_clsid, CLSID_MSDraw))
+ {
+ m_cfFormat = CF_METAFILEPICT;
+ m_uFlag |= COLECACHEF_PBRUSHORMSDRAW | COLECACHEF_FORMATKNOWN;
+
+ }
+ else if (IsEqualCLSID(m_clsid, CLSID_Picture_EnhMetafile))
+ {
+ m_cfFormat = CF_ENHMETAFILE;
+ m_uFlag |= COLECACHEF_STATIC | COLECACHEF_FORMATKNOWN;
+ }
+ else
+ {
+ m_cfFormat = NULL;
+ }
+
+ // If we know the object format then add a cachenode for it. This node
+ // will be put in the 0th entry of the cachelist. This node never gets
+ // saved. It's get used in drawing, for finding out the extents, and by
+ // the enumerator, etc...
+
+ if (m_cfFormat)
+ {
+ LEVERIFY( AddCacheNodeForNative() );
+ }
+
+ m_fUsedToBePBrush = FALSE;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::~COleCache, public //REVIEW
+//
+// Synopsis:
+// destructor
+//
+// Notes:
+// Enumerators for the cache no not reference count it, with the
+// view that the cache can go away at any time, invalidating
+// the enumerators. This walks the list of enumerators, alerting
+// them to the fact that the cache is being destroyed.
+//
+// History:
+// 11/15/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_dtor)
+COleCache::~COleCache(void)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ // Notify all cache enumerators that we are getting deleted
+ while(m_pCacheEnum)
+ {
+ m_pCacheEnum->OnOleCacheDelete();
+ m_pCacheEnum = m_pCacheEnum->m_pNextCacheEnum;
+ }
+
+ // Clear the cache list - delete all the cache nodes
+ DeleteAll();
+
+ // delete the list of cache node pointers
+ PubMemFree(m_pCacheList);
+
+ // if we're holding storage, release it
+ if (m_pStg)
+ {
+ m_pStg->Release();
+ m_pStg = NULL;
+ }
+
+ // if we're holding an advise sink, release it
+ if (m_pViewAdvSink)
+ {
+ m_pViewAdvSink->Release();
+ m_pViewAdvSink = NULL;
+ }
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::QueryInterface, public
+//
+// Synopsis:
+// implements IUnknown::QueryInterface
+//
+// Arguments:
+// [iid] -- IID of the desired interface
+// [ppv] -- pointer to where to return the requested interface
+//
+// Returns:
+// E_NOINTERFACE, if the requested interface is not available
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/15/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_QueryInterface)
+STDMETHODIMP COleCache::QueryInterface(REFIID iid, LPVOID FAR* ppv)
+{
+ VDATEHEAP();
+
+ return(m_pUnkOuter->QueryInterface(iid, ppv));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::AddRef, public
+//
+// Synopsis:
+// implements IUnknown::AddRef
+//
+// Arguments:
+// none
+//
+// Returns:
+// the object's reference count
+//
+// Notes:
+//
+// History:
+// 11/15/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_AddRef)
+STDMETHODIMP_(ULONG) COleCache::AddRef(void)
+{
+ VDATEHEAP();
+
+ return(m_pUnkOuter->AddRef());
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::Release, public
+//
+// Synopsis:
+// implements IUnknown::Release
+//
+// Arguments:
+// none
+//
+// Returns:
+// the object's reference count
+//
+// Notes:
+//
+// History:
+// 11/15/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_Release)
+STDMETHODIMP_(ULONG) COleCache::Release(void)
+{
+ VDATEHEAP();
+
+ return(m_pUnkOuter->Release());
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::GetExtent, public
+//
+// Synopsis:
+// Gets the size of the cached presentation for [dwAspect]. If
+// there are several, because of varied advise control flags,
+// such as ADVF_NODATA, ADVF_ONSTOP, ADVF_ONSAVE, etc, gets the
+// most up to date one, up to frozen cached values
+//
+// Arguments:
+// [dwAspect] -- the aspect for which we'd like the extent
+// [lpsizel] -- pointer to where to return the width and height
+//
+// Returns:
+// OLE_E_BLANK
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/16/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_GetExtent)
+INTERNAL COleCache::GetExtent(DWORD dwAspect, LPSIZEL lpsizel)
+{
+ VDATEHEAP();
+
+ DWORD dwCacheId; // cache id of node currently being examined
+ LPCACHENODE lpCacheNode; // pointer to node being examined
+ int iCacheType; // cache type [from below] of node being examined
+ int iCacheTypeSoFar; // best cache type so far
+// these values are defined in order of least to best preferred, so that
+// numeric comparisons are valid; DO NOT REORDER
+#define CACHETYPE_NODATA 1
+#define CACHETYPE_ONSTOP 2
+#define CACHETYPE_ONSAVE 3
+#define CACHETYPE_NORMAL 4
+ const FORMATETC FAR *lpforetc; // format information for current node
+ DWORD grfAdvf; // advise flags for current node
+
+ // if there are no cache nodes, there's nothing we can return
+ if (!m_uCacheNodeCnt)
+ {
+ lpsizel->cx = 0;
+ lpsizel->cy = 0;
+ return ResultFromScode(OLE_E_BLANK);
+ }
+
+ // Here we want to return the extents of the cache node that has NORMAL
+ // advise flags. If we don't find such a node then we will take the next
+ // best available.
+
+ // REVIEW(davepl) Clean up this loop, I get ill just looking at it
+
+ for(iCacheTypeSoFar = 0, dwCacheId = CACHEID_GETNEXT_GETALL;
+ lpCacheNode = GetNext(dwAspect, DEF_LINDEX,
+ &dwCacheId);)
+ {
+ // get a pointer to the FORMATETC for this node
+ lpforetc = lpCacheNode->GetFormatEtc();
+
+ // make sure the cfFormat is either CF_METAFILEPICT or CF_DIB
+ if ((lpforetc->cfFormat == CF_METAFILEPICT) ||
+ (lpforetc->cfFormat == CF_DIB) ||
+ (lpforetc->cfFormat == CF_ENHMETAFILE))
+ {
+ grfAdvf = lpCacheNode->GetAdvf();
+
+ if (!(grfAdvf & (ADVFCACHE_ONSAVE |
+ ADVF_DATAONSTOP | ADVF_NODATA)))
+ iCacheType = CACHETYPE_NORMAL;
+ else
+ {
+ if (grfAdvf & ADVFCACHE_ONSAVE)
+ iCacheType = CACHETYPE_ONSAVE;
+ else if (grfAdvf & ADVF_NODATA)
+ iCacheType = CACHETYPE_NODATA;
+ else
+ iCacheType = CACHETYPE_ONSTOP;
+ }
+
+ if (iCacheType > iCacheTypeSoFar)
+ {
+ SIZEL sizelTmp;
+
+ // Get the extents from the presentation object
+ if ((lpCacheNode->GetPresObj())->GetExtent(
+ dwAspect, &sizelTmp) != NOERROR)
+ continue;
+
+ if (sizelTmp.cx == 0 || sizelTmp.cy == 0)
+ continue;
+
+ // We got proper extent, update state.
+ // If the cache is a
+ // NORMAL cache then we are done.
+ *lpsizel = sizelTmp;
+ if ((iCacheTypeSoFar = iCacheType) ==
+ CACHETYPE_NORMAL)
+ return NOERROR;
+ }
+ }
+ }
+
+ if (lpsizel->cx == 0 || lpsizel->cy == 0)
+ return ResultFromScode(OLE_E_BLANK);
+
+ return NOERROR;
+
+// don't need these anymore
+#undef CACHETYPE_NODATA
+#undef CACHETYPE_ONSTOP
+#undef CACHETYPE_ONSAVE
+#undef CACHETYPE_NORMAL
+}
+
+
+// Private methods of COleCache - called by its friends CCacheNode, CCacheEnum
+// and all nested classes of COleCache
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::OnChange, private
+//
+// Synopsis:
+// Used by cache nodes to alert the cache that their content has
+// changed. The advise sink held by the cache is alerted to
+// the change if it affects an aspect that the advise sink is
+// interested in.
+//
+// Arguments:
+// [dwAspect] -- the aspect that changed
+// [lindex] -- the lindex for the aspect that changed
+// [fDirty] -- indicates that the change has made the cache dirty
+//
+// Notes:
+//
+// History:
+// 11/16/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+// Each one of the cache nodes call this method when their data changes. We
+// in turn send the view notification only if the aspect and lindex of the
+// cache node (that called us) matches with the aspect and lindex for which
+// view advise is set up.
+
+#pragma SEG(COleCache_OnChange)
+INTERNAL_(void) COleCache::OnChange(DWORD dwAspect, LONG lindex, BOOL fDirty)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ // mark the cache as dirty
+ if (fDirty)
+ m_uFlag |= COLECACHEF_DIRTY;
+
+ // if there's no view advise sink, there's nothing to do
+ if (m_pViewAdvSink == NULL)
+ return;
+
+ // if the aspect that changed is not one that the view advise sink
+ // client is interested in, there's nothing more to do
+ if (!(m_aspectsView & dwAspect))
+ return;
+
+ // advise the view advise sink client of the change
+ m_pViewAdvSink->OnViewChange(dwAspect, lindex);
+
+ // if client only wanted notification once, free the advise sink
+ if (m_advfView & ADVF_ONLYONCE)
+ {
+ m_pViewAdvSink->Release();
+ m_pViewAdvSink = NULL;
+ }
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::GetStg, private
+//
+// Synopsis:
+// returns the storage the cache has been given to use
+//
+// Arguments:
+// none
+//
+// Returns:
+// pointer to the IStorage instance
+//
+// History:
+// 11/16/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+INTERNAL_(LPSTORAGE) COleCache::GetStg(void)
+{
+ VDATEHEAP();
+
+ return m_pStg;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::DetachCacheEnum, private
+//
+// Synopsis:
+// This removes an instance of CCacheEnum from the list of
+// enumerators maintained by COleCache.
+//
+// Arguments:
+// [pCacheEnum] -- the cache enumerator to remove
+//
+// Notes:
+//
+// History:
+// 11/16/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+// CCacheEnum calls this routine to remove its pointer to the enumerators list
+
+#pragma SEG(COleCache_DetachCacheEnum)
+INTERNAL_(void) COleCache::DetachCacheEnum(CCacheEnum FAR* pCacheEnum)
+{
+ VDATEHEAP();
+
+ CCacheEnum FAR *FAR *ppCE; // pointer to the pointer to the list item
+ CCacheEnum FAR *pCE; // pointer to the item
+
+ // NOTE: no ref count
+
+ // search the list for [pCacheEnum]
+ for(ppCE = &m_pCacheEnum; pCE = *ppCE; ppCE = &pCE->m_pNextCacheEnum)
+ {
+ // if we find [pCacheEnum], splice it out of the list
+ if (pCE == pCacheEnum)
+ {
+ *ppCE = pCE->m_pNextCacheEnum;
+ pCE->m_pNextCacheEnum = NULL;
+ break;
+ }
+ }
+}
+
+
+// Following are the COleCache cache list manipulation methods
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::GrowCacheList, private
+//
+// Synopsis:
+// Grows the size of the cachenode list. Use this when all
+// available nodes are used up. Grows the list by
+// NUM_CACHELIST_ITEMS
+//
+// Arguments:
+// none
+//
+// Returns:
+// TRUE if the list is successfully grown, FALSE otherwise
+//
+// Modifies:
+// m_pCacheList
+//
+// Notes:
+//
+// History:
+// 11/16/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_GrowCacheList)
+INTERNAL_(BOOL) COleCache::GrowCacheList(void)
+{
+ VDATEHEAP();
+
+ ULONG ulNewMax; // the number of cache nodes we'll have after growing
+ ULONG ulSize; // the amount of memory required
+ LPCACHELIST pCacheList; // pointer to the (re)allocated memory
+ ULONG ulCnt; // used to count off the new items for initialization
+
+
+ ulNewMax = NUM_CACHELIST_ITEMS + m_uCacheNodeMax;
+
+ // The current architecture of the cache prevents the cachenode
+ // array from having more entries that MAX_CACHELIST_ITEMS, so
+ // we must fail any attempt to grow the cache beyond this point.
+
+ if (ulNewMax > MAX_CACHELIST_ITEMS)
+ {
+ return NULL;
+ }
+
+ ulSize = ulNewMax * sizeof(CACHELIST_ITEM);
+
+ // (re)allocate the memory for the cachelist array
+ if (m_pCacheList == NULL)
+ pCacheList = (LPCACHELIST)PubMemAlloc(ulSize);
+ else
+ pCacheList = (LPCACHELIST)PubMemRealloc(m_pCacheList,
+ ulSize);
+
+ // if allocation failed, nothing more we can do
+ if (pCacheList == NULL)
+ return FALSE;
+ // REVIEW, if a reallocation, if m_pCacheList still valid on failure
+
+ // assign the new memory
+ m_pCacheList = pCacheList;
+
+ // initialize the newly allocated items with 0
+ for (pCacheList += m_uCacheNodeMax, ulCnt = NUM_CACHELIST_ITEMS;
+ ulCnt; ++pCacheList, --ulCnt)
+ {
+ pCacheList->dwCacheId = 0;
+ pCacheList->lpCacheNode = 0;
+ }
+
+ // record new array length
+ m_uCacheNodeMax = ulNewMax;
+ return TRUE;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::DeleteAll, private
+//
+// Synopsis:
+// Delete all cache nodes in the cache list array
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 11/16/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+// clear the cache list
+
+#pragma SEG(COleCache_DeleteAll)
+INTERNAL_(void) COleCache::DeleteAll(void)
+{
+ VDATEHEAP();
+
+ DWORD dwCacheId = CACHEID_GETNEXT_GETALL;
+ LPCACHENODE lpCacheNode;
+
+ // if no nodes are in use, nothing to do
+ if (!m_uCacheNodeCnt)
+ return;
+
+ // get each node that is in use, and free it
+ while(m_uCacheNodeCnt && GetNext(&dwCacheId))
+ {
+ // Remove the CacheNode from the list and then delete it.
+ if (lpCacheNode = Detach(dwCacheId))
+ lpCacheNode->Delete();
+ }
+
+ Assert(!m_uCacheNodeCnt);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::Attach, private
+//
+// Synopsis:
+// adds a new cache node to the cache node list
+//
+// Arguments:
+// [lpCacheNode] -- pointer to new cache node to add to the list
+//
+// Returns:
+// The cache id of the newly added node, or CACHEID_INVALID,
+// if it cannot be attached.
+//
+// Modifies:
+// m_pCacheList
+//
+// Notes:
+//
+// History:
+// 11/16/93 - ChrisWe - file inspection and cleanup; return
+// CACHEID_INVALID on failure, instead of zero, which
+// is a legitimate (internal) cache node id
+//
+//-----------------------------------------------------------------------------
+
+// Find an empty entry and add the CacheNode to the list. Note that
+// lpCacheNode is not ref counted.
+
+#pragma SEG(COleCache_Attach)
+INTERNAL_(DWORD) COleCache::Attach(LPCACHENODE lpCacheNode)
+{
+ VDATEHEAP();
+
+ CACHELIST_ITEM FAR *pCI; // pointer to current cachelist item
+ ULONG c; // counter
+
+ // The dwCacheID is nothing but the index into the array plus
+ // N*MAX_CACHELIST_ITEMS. Since 0 cannot be a valid connection ID, we
+ // should not use the 0th entry of the array.
+ // REVIEW, and yet we do, for the CACHEID_NATIVE!!!
+
+ // look for an empty slot
+ for(pCI = m_pCacheList + (c = CACHEID_NATIVE+1); c < m_uCacheNodeMax;
+ ++pCI, ++c)
+ {
+ if (pCI->lpCacheNode == NULL)
+ goto foundEmpty;
+ }
+
+ // if we get here, all slots are in use, so grow the array of slots
+ // if we can't grow it, get out
+ if (!GrowCacheList())
+ return(CACHEID_INVALID);
+
+ // the first free slot is at the end of the (newly allocated) array
+ pCI = m_pCacheList+c;
+
+foundEmpty:
+ // We found an empty slot. Now assign the cache ID such that we
+ // will be able to catch error cases.
+ if (pCI->dwCacheId == 0)
+ pCI->dwCacheId = c;
+ else
+ pCI->dwCacheId += MAX_CACHELIST_ITEMS;
+
+ pCI->lpCacheNode = lpCacheNode;
+
+ // Keep track of the number of caches
+ m_uCacheNodeCnt++;
+ return pCI->dwCacheId;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::Detach, private
+//
+// Synopsis:
+// Remove the indicated cache node from the list of cache nodes
+// maintained. The cache node is not deleted, but is returned.
+//
+// Arguments:
+// [dwCacheId] -- the id of the cache node
+//
+// Returns:
+// pointer to the detached cache node, if it is found, or NULL.
+//
+// Notes:
+//
+// History:
+// 11/17/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_Detach)
+INTERNAL_(LPCACHENODE) COleCache::Detach(DWORD dwCacheId)
+{
+ VDATEHEAP();
+
+ ULONG index = dwCacheId % MAX_CACHELIST_ITEMS;
+ LPCACHENODE lpCacheNode = NULL; // return value; the node being detached
+ CACHELIST_ITEM FAR *pCI; // the cachelist item affected
+
+ if (index >= m_uCacheNodeMax)
+ return NULL;
+
+ pCI = m_pCacheList+index;
+ if ((pCI->dwCacheId == dwCacheId) && (pCI->lpCacheNode != NULL))
+ {
+ // record the cache node pointer for return
+ lpCacheNode = pCI->lpCacheNode;
+
+ // mark this cache node item as unused
+ pCI->lpCacheNode = NULL;
+
+ Assert(m_uCacheNodeCnt != 0);
+ // Keep trck of the number of caches
+ m_uCacheNodeCnt--;
+ }
+
+ return lpCacheNode;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::GetNext, private
+//
+// Synopsis:
+// Fetch the next cache node after the one identified by
+// *[lpdwCacheId]. Update *[lpdwCacheID] to that node.
+//
+// Arguments:
+// [lpdwCacheId] -- pointer to a cache id.
+//
+// Returns:
+// pointer to the cache node, if there is one, or NULL
+//
+// Notes:
+//
+// History:
+// 11/17/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+// Upon entry *lpdwCacheId will be set to the cur cache id. On exit it will be
+// set to the next valid cache id.
+
+#pragma SEG(COleCache_GetNext)
+INTERNAL_(LPCACHENODE) COleCache::GetNext(LPDWORD lpdwCacheId)
+{
+ VDATEHEAP();
+
+ CACHELIST_ITEM FAR *pCI; // used to walk the array of cachelist items
+ ULONG index; // the index of the current cachelist item
+
+ // Start from the entry next to the current one. If starting at the
+ // "next" element pushes us past the last possible cache node index,
+ // there's no way we can actually find anything, so return NULL.
+
+ if (*lpdwCacheId % MAX_CACHELIST_ITEMS == MAX_CACHELIST_ITEMS - 1)
+ {
+ return NULL;
+ }
+
+ index = (*lpdwCacheId+1) % MAX_CACHELIST_ITEMS;
+
+ for(pCI = m_pCacheList + index; index < m_uCacheNodeMax; ++pCI, ++index)
+ {
+ if (pCI->lpCacheNode)
+ {
+ *lpdwCacheId = pCI->dwCacheId;
+ return pCI->lpCacheNode;
+ }
+ }
+
+ // if we got here, we went off the end of the array
+ // REVIEW, should we set *lpdwCacheId so we don't iterate again
+ // if the last N entries were all empty?
+ return NULL;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::GetAt, private
+//
+// Synopsis:
+// Fetch the cache node identified by [dwCacheId]
+//
+// Arguments:
+// [dwCacheId] -- the id of the cache node to fetch
+//
+// Returns:
+// the pointer to the cache node, if it is valid, or NULL
+//
+// Notes:
+//
+// History:
+// 11/17/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_GetAt)
+INTERNAL_(LPCACHENODE) COleCache::GetAt(DWORD dwCacheId)
+{
+ VDATEHEAP();
+
+ ULONG index = dwCacheId % MAX_CACHELIST_ITEMS;
+ CACHELIST_ITEM FAR *pCI;
+
+ if (index >= m_uCacheNodeMax)
+ return NULL;
+
+ pCI = m_pCacheList+index;
+ if (pCI->dwCacheId == dwCacheId)
+ return(pCI->lpCacheNode); // could be NULL
+
+ return NULL;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::GetAt, private
+//
+// Synopsis:
+// Fetch the cache node with the given [dwAspect], [lindex],
+// [cfFormat], and for device described by [ptd]
+//
+// Arguments:
+// [dwAspect] -- the aspect to look for
+// [lindex] -- the lindex to look for
+// [cfFormat] -- the clipboard format to look for
+// [ptd] -- the target device for the cache node
+// [lpdwCacheId] -- a pointer to where to return the cache node
+// id, if a match is found
+//
+// Returns:
+// pointer to a cache node that matches the requested attributes,
+// if there is one, or NULL
+//
+// Notes:
+// the m_dwDrawCacheId node is checked first, if there is one
+//
+// History:
+// 11/17/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_GetAt)
+INTERNAL_(LPCACHENODE) COleCache::GetAt(DWORD dwAspect, LONG lindex,
+ CLIPFORMAT cfFormat, DVTARGETDEVICE FAR* ptd, DWORD FAR* lpdwCacheId)
+{
+ VDATEHEAP();
+
+ DWORD dwCacheId = CACHEID_GETNEXT_GETALL;
+ LPCACHENODE lpCacheNode = NULL;
+ const FORMATETC FAR *lpforetc;
+
+ // Check to see whether the cache currently being used for drawing is
+ // the one that we are looking for.
+ if (m_dwDrawCacheId != CACHEID_INVALID)
+ {
+ if (!(lpCacheNode = GetAt(m_dwDrawCacheId)))
+ {
+ // the draw cache id has become invalid, so clear it.
+ m_dwDrawCacheId = CACHEID_INVALID;
+ }
+ else
+ {
+ // The draw cache id is valid, get the formatetc of
+ // the cache
+ lpforetc = lpCacheNode->GetFormatEtc();
+
+ // look for a match
+ if ((lpforetc->cfFormat == cfFormat) &&
+ (lpforetc->dwAspect == dwAspect) &&
+ (lpforetc->lindex == lindex) &&
+ UtCompareTargetDevice(ptd,
+ lpforetc->ptd))
+ {
+ dwCacheId = m_dwDrawCacheId;
+ goto errRtn;
+ }
+ }
+ }
+
+ // What we are looking for does not match with the current draw cache.
+ // So, scan the list for a match.
+ while(lpCacheNode = GetNext(&dwCacheId))
+ {
+ if (dwCacheId == m_dwDrawCacheId)
+ continue; // we have checked the draw cache, so skip it
+
+ lpforetc = lpCacheNode->GetFormatEtc();
+ if ((lpforetc->cfFormat == cfFormat) &&
+ (lpforetc->dwAspect == dwAspect) &&
+ (lpforetc->lindex == lindex) &&
+ UtCompareTargetDevice(ptd, lpforetc->ptd))
+ break; // we found a match, so break out of the loop
+ }
+
+ // if we don't find a match, then lpCacheNode will be NULL.
+errRtn:
+ if (lpdwCacheId)
+ *lpdwCacheId = dwCacheId;
+
+ return lpCacheNode;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::GetNext, public
+//
+// Synopsis:
+// Fetch the next cache node after the one identified by
+// *[lpdwCacheId] that matches the given [dwAspect] and [lindex]
+//
+// Arguments:
+// [dwAspect] -- the aspect to look for
+// [lindex] -- the lindex to look for
+// [lpdwCacheId] -- pointer to a cache id of the node after which
+// to start the search. The cache id of the node that
+// is found to match [dwAspect] and [lindex] will be
+// returned in the same place.
+//
+// Returns:
+// pointer to the cache node that matches the requested
+// attributes, if one is found, or NULL
+//
+// Notes:
+//
+// History:
+// 11/17/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_GetNext)
+INTERNAL_(LPCACHENODE) COleCache::GetNext(DWORD dwAspect, LONG lindex,
+ DWORD FAR* lpdwCacheId)
+{
+ VDATEHEAP();
+
+ DWORD dwCacheId = *lpdwCacheId;
+ LPCACHENODE lpCacheNode = NULL;
+ const FORMATETC FAR *lpforetc;
+
+ while(lpCacheNode = GetNext(&dwCacheId))
+ {
+ lpforetc = lpCacheNode->GetFormatEtc();
+ if ((lpforetc->dwAspect == dwAspect) &&
+ (lpforetc->lindex == lindex))
+ break; // we found a match, so break out of the loop
+ }
+
+ // if we don't find a match, then lpCacheNode will be NULL.
+ // REVIEW, so why don't we advance *lpdwCacheId in that case?
+ if (lpCacheNode)
+ *lpdwCacheId = dwCacheId;
+
+ return lpCacheNode;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::GetAt, private
+//
+// Synopsis:
+// Fetch a pointer to the cache node with the given FORMATETC,
+// if there is one. if [lpforetc]->cfFormat is NULL, we check
+// for CF_ENHMETAFILE, CF_METAFILE, and CF_DIB, in that order.
+//
+// Arguments:
+// [lpforetc] -- pointer to the FORMATETC to check for
+//
+// Returns:
+// Pointer to the cache node with a matching FORMATETC, if there
+// is one, or NULL.
+//
+// Notes:
+//
+// History:
+// 11/17/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_GetAt)
+INTERNAL_(LPCACHENODE) COleCache::GetAt(LPFORMATETC lpforetc,
+ DWORD FAR* lpdwCacheId)
+{
+ VDATEHEAP();
+
+ LPCACHENODE lpCacheNode;
+
+ if (lpforetc->cfFormat == 0)
+ {
+ // See whether we already cached an EMF, metafile or a DIB
+
+ if (lpCacheNode = GetAt(lpforetc->dwAspect, lpforetc->lindex,
+ CF_METAFILEPICT, lpforetc->ptd, lpdwCacheId))
+ goto Exit;
+
+
+ if (lpCacheNode = GetAt(lpforetc->dwAspect, lpforetc->lindex,
+ CF_DIB, lpforetc->ptd, lpdwCacheId))
+ goto Exit;
+
+ if (lpCacheNode = GetAt(lpforetc->dwAspect, lpforetc->lindex,
+ CF_ENHMETAFILE, lpforetc->ptd, lpdwCacheId))
+ goto Exit;
+
+ // If we have a NULL node, and we are _looking_ for a NULL
+ // node, we must satisfy the request so that the advise flags
+ // can be updated for multiple caches of NULL nodes.
+
+ if (lpCacheNode = GetAt(lpforetc->dwAspect, lpforetc->lindex,
+ 0, lpforetc->ptd, lpdwCacheId))
+ goto Exit;
+
+
+ }
+ else
+ {
+ // NON-NULL cfFormat
+ // see whether this format is already cached.
+
+ if (lpCacheNode = GetAt(lpforetc->dwAspect, lpforetc->lindex,
+ lpforetc->cfFormat, lpforetc->ptd, lpdwCacheId))
+ goto Exit;
+ }
+
+Exit:
+ return lpCacheNode;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::GetPresObjForDrawing, private
+//
+// Synopsis:
+// Fetch a presentation object matching the given parameters,
+// if there is one. We try to get CF_ENHMETAFILE,
+// CF_METAFILEPICT, and CF_DIB formats, in that order.
+//
+// Arguments:
+// [dwAspect] -- the aspect we'd like
+// [lindex] -- the lindex we'd like
+// [ptd] -- description of the target device the presentation
+// should be suitable for
+//
+// Returns:
+// pointer to the presentation object, if a suitable one is
+// found, or NULL
+//
+// Modifies:
+// m_dwDrawCacheId is set to the newly found cache id, if one
+// is found
+//
+// Notes:
+//
+// History:
+// 11/17/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_GetPresObjForDrawing)
+INTERNAL_(LPOLEPRESOBJECT) COleCache::GetPresObjForDrawing(DWORD dwAspect,
+ LONG lindex, DVTARGETDEVICE FAR* ptd)
+{
+ VDATEHEAP();
+
+ LPOLEPRESOBJECT lpPresObj; // the found presentation object
+ DWORD dwCacheId; // the cache id of the presentation object
+
+ // Try for Enhanced Metafile
+ if ((lpPresObj = GetPresObj(dwAspect, lindex, CF_ENHMETAFILE, ptd,
+ &dwCacheId)) && !lpPresObj->IsBlank())
+ goto success;
+
+ // Try for Metafile
+ if ((lpPresObj = GetPresObj(dwAspect, lindex, CF_METAFILEPICT, ptd,
+ &dwCacheId)) && !lpPresObj->IsBlank())
+ goto success;
+
+
+ // Try for Dib
+ if ((lpPresObj = GetPresObj(dwAspect, lindex, CF_DIB, ptd,
+ &dwCacheId)) && !lpPresObj->IsBlank())
+ goto success;
+
+
+ return NULL;
+
+success:
+ // COleCache try to get the CacheNode for a given dwAspect, lindex, ptd,
+ // etc.., they will first try the cachenode with this cache id, and if
+ // they don't find the match they will start scanning the list.
+ //
+ // This caching is necessary 'cause even when the containers create
+ // mutiple caches most of the time they deal with only one (view)
+ // aspect.
+
+ m_dwDrawCacheId = dwCacheId;
+ return lpPresObj;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::GetPresObj, private
+//
+// Synopsis:
+// Get the presentation object of the cache node which matches
+// the requested attributes.
+//
+// Arguments:
+// [dwAspect] -- the aspect
+// [lindex] -- the lindex
+// [cfFormat] -- the clipboard format
+// [ptd] -- points to the description of the target device
+// [pdwCacheId] -- pointer to a location where the cache id
+// can be returned for the presentation object
+//
+// Returns:
+// pointer to the presentation object, is one is found that
+// matches the requested parameters, or NULL
+//
+// Notes:
+// If a request is made for CF_BITMAP ([cfFormat]), then
+// GetPresObj() checks for CF_DIB.
+//
+// History:
+// 11/17/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_GetPresObj)
+INTERNAL_(LPOLEPRESOBJECT) COleCache::GetPresObj(DWORD dwAspect, LONG lindex,
+ CLIPFORMAT cfFormatIn, DVTARGETDEVICE FAR* ptd,
+ DWORD FAR* pdwCacheId)
+{
+ VDATEHEAP();
+
+ LPCACHENODE lpCacheNode;
+#ifndef _MAC
+ CLIPFORMAT cfFormat = ((cfFormatIn == CF_BITMAP) ? CF_DIB :
+ cfFormatIn);
+#endif
+
+ if (lpCacheNode = GetAt(dwAspect, lindex, cfFormat, ptd, pdwCacheId))
+ return lpCacheNode->GetPresObj();
+
+ return NULL;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::AddCacheNodeForNative, private
+//
+// Synopsis:
+// Create the Native format cache node, and add it to the list
+// of cache nodes, if it doesn't already exist.
+//
+// Arguments:
+// none
+//
+// Returns:
+// pointer to the found, or newly created cache node. Can
+// return NULL if out of memory
+//
+// Notes:
+// This assumes that m_cfFormat is set.
+//
+// History:
+// 11/17/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+INTERNAL_(LPCACHENODE)COleCache::AddCacheNodeForNative(void)
+{
+ VDATEHEAP();
+
+ CACHELIST_ITEM FAR *pCI; // points to CACHEID_NATIVE cache node
+ LPCACHENODE lpCacheNode; // points to the cache node in the cache list
+ FORMATETC foretc; // the format we'll initialize the new node with
+
+ // point at the CACHEID_NATIVE node
+ pCI = &m_pCacheList[CACHEID_NATIVE];
+
+ // if we already have a native format, return it
+ if (pCI->lpCacheNode)
+ return(pCI->lpCacheNode);
+
+ Assert(m_cfFormat);
+
+ INIT_FORETC(foretc);
+
+ foretc.cfFormat = m_cfFormat;
+
+ if (foretc.cfFormat == CF_METAFILEPICT)
+ {
+ foretc.tymed = TYMED_MFPICT;
+ }
+ else if (foretc.cfFormat == CF_ENHMETAFILE)
+ {
+ foretc.tymed = TYMED_ENHMF;
+ }
+ else
+ {
+ foretc.tymed = TYMED_HGLOBAL; // REVIEW, need to use union
+ }
+
+ // create cache node
+ if (lpCacheNode = new FAR CCacheNode(&foretc,
+ (((m_uFlag & COLECACHEF_PBRUSHORMSDRAW) && !m_fUsedToBePBrush) ?
+ ADVF_NODATA : 0), this))
+ {
+ if (lpCacheNode->CreatePresObject(NULL /*lpDataObj*/,
+ FALSE /*fConvert*/) != NOERROR)
+ {
+ // if we can't create presentation object,
+ // delete the cache node, and drop out
+ lpCacheNode->Delete();
+ }
+ else
+ {
+ // there's one more cache node in use
+ ++m_uCacheNodeCnt;
+
+ // set this as the CACHEID_NATIVE cache node
+ pCI->lpCacheNode = lpCacheNode;
+ }
+ }
+
+ // if creation failed, this will return NULL
+ return pCI->lpCacheNode;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::DeleteCacheNodeForNative, private
+//
+// Synopsis:
+// Delete the native format cache node
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 11/17/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+inline INTERNAL_(void) COleCache::DeleteCacheNodeForNative(void)
+{
+ VDATEHEAP();
+
+ CACHELIST_ITEM FAR *pCI = &m_pCacheList[CACHEID_NATIVE];
+
+ // if there is no native cache node, there's nothing to do
+ if (!pCI->lpCacheNode)
+ return;
+
+ // delete the native cache node
+ pCI->lpCacheNode->Delete();
+ pCI->lpCacheNode = NULL;
+ --m_uCacheNodeCnt;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::MoveCacheNodeForNative, private
+//
+// Synopsis:
+// Moves whatever cache node is under CACHEID_NATIVE to
+// another position and another cache id, leaving the
+// native cachenode unused.
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 11/17/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+inline INTERNAL_(void) COleCache::MoveCacheNodeForNative(void)
+{
+ VDATEHEAP();
+
+ if (m_pCacheList[CACHEID_NATIVE].lpCacheNode)
+ Attach(Detach(CACHEID_NATIVE));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::UpdateCacheNodeForNative, private
+//
+// Synopsis:
+// Update the native data cache node from the storage currently
+// associated with the cache
+//
+// Arguments:
+// none
+//
+// Returns:
+// a pointer to the native cache node
+//
+// Notes:
+//
+// History:
+// 11/23/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+INTERNAL_(LPCACHENODE) COleCache::UpdateCacheNodeForNative()
+{
+ VDATEHEAP();
+
+ CACHELIST_ITEM FAR *pCI = &m_pCacheList[CACHEID_NATIVE];
+ FORMATETC foretc;
+ STGMEDIUM stgmed;
+
+ // if there is no native cache node, add one
+ if (!pCI->lpCacheNode)
+ {
+ AddCacheNodeForNative();
+
+ // if there still isn't a native cache node, get out
+ if (!pCI->lpCacheNode)
+ return NULL;
+ }
+
+ Assert(m_pStg);
+ if (!m_pStg)
+ goto errRtn;
+
+ // initialize a FORMATETC for native data
+ INIT_FORETC(foretc);
+ foretc.cfFormat = m_cfFormat;
+
+ if (foretc.cfFormat == CF_METAFILEPICT)
+ {
+ foretc.tymed = TYMED_MFPICT;
+ }
+ else if (foretc.cfFormat == CF_ENHMETAFILE)
+ {
+ foretc.tymed = TYMED_ENHMF;
+ }
+ else
+ {
+ foretc.tymed = TYMED_HGLOBAL; // REVIEW, need to use union
+ }
+
+ // retrieve a global with the native data
+ stgmed.pUnkForRelease = NULL;
+ stgmed.tymed = foretc.tymed;
+ stgmed.hGlobal = UtGetHPRESFromNative(m_pStg, foretc.cfFormat,
+ (m_uFlag & COLECACHEF_PBRUSHORMSDRAW) ? TRUE : FALSE);
+
+ // set the data
+ if (stgmed.hGlobal)
+ pCI->lpCacheNode->SetData(&foretc, &stgmed, TRUE);
+
+errRtn:
+ return pCI->lpCacheNode;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleObject::FindObjectFormat, private
+//
+// Synopsis:
+// Determines what the object's clipboard format is. If
+// it is CF_ENHMETAFILE, CF_METAFILEPICT, or CF_DIB, the format
+// is marked as COLECACHE_FORMATKNOWN, and installed in
+// CACHEID_NATIVE. If anything else, the format is unknown, and
+// the native cache node is made empty. There is no effect, if the
+// presentation is COLECACHE_STATIC.
+//
+// Arguments:
+// [pstg] -- pointer to storage where the object can be found
+//
+// Notes:
+//
+// History:
+//
+//-----------------------------------------------------------------------------
+
+INTERNAL_(void) COleCache::FindObjectFormat(LPSTORAGE pstg)
+{
+ VDATEHEAP();
+
+ CLIPFORMAT cf;
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pstg);
+
+ if (m_uFlag & COLECACHEF_STATIC)
+ return;
+
+ if (IsEqualCLSID(m_clsid, CLSID_PBrush) || m_fUsedToBePBrush)
+ cf = CF_DIB;
+ else if (IsEqualCLSID(m_clsid, CLSID_MSDraw))
+ cf = CF_METAFILEPICT;
+ else
+ {
+ if (!pstg)
+ return;
+
+ if (FAILED(ReadFmtUserTypeStg(pstg, &cf, NULL)))
+ cf = 0;
+ }
+
+ if (m_cfFormat == cf)
+ return;
+
+ if (cf == CF_METAFILEPICT || cf == CF_DIB || cf == CF_ENHMETAFILE)
+ {
+ DeleteCacheNodeForNative();
+ m_cfFormat = cf;
+ AddCacheNodeForNative();
+ m_uFlag |= COLECACHEF_FORMATKNOWN;
+
+ }
+ else
+ {
+ MoveCacheNodeForNative();
+ m_uFlag &= ~COLECACHEF_FORMATKNOWN;
+ }
+}
+
+
+// IOleCacheControl implementation
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::OnRun, public
+//
+// Synopsis:
+// implements IOleCacheControl::OnRun
+//
+// Notify the cache that the object is running; the cache will
+// set up advisory connections with interested presentation nodes.
+// No effect if the cache has already been notified that the object
+// is running.
+//
+// Arguments:
+// [pDataObj] -- an IDataObject interface on the running object
+//
+// Returns:
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/23/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_OnRun)
+STDMETHODIMP COleCache::OnRun(IDataObject FAR* pDataObj)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ DWORD dwCacheId; // used to loop through the cache nodes
+ LPCACHENODE lpCacheNode; // points to the current cache node
+
+ M_PROLOG(this);
+
+ VDATEIFACE(pDataObj);
+
+ // if we already have the data object, nothing more to do
+ if (m_pDataObject)
+ return NOERROR;
+
+ m_pDataObject = pDataObj; // NOTE: no ref count
+
+ // Notify all the cache nodes that the object is RUN, so that they can
+ // set up the advise connections with it.
+ for(dwCacheId = CACHEID_GETNEXT_GETALL;
+ lpCacheNode = GetNext(&dwCacheId);)
+ lpCacheNode->OnRun(pDataObj);
+
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::OnStop, public
+//
+// Synopsis:
+// implements IOleCacheControl::OnStop
+//
+// Informs the cache that the object (whose IDataObject is
+// in m_pDataObject) has stopped. Advisory connections to the
+// object are torn down. No effect if the cache has already
+// been notified that the object has stopped.
+//
+// Arguments:
+// none
+//
+// Returns:
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/23/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_OnStop)
+STDMETHODIMP COleCache::OnStop(void)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ DWORD dwCacheId; // used to loop through the cache nodes
+ LPCACHENODE lpCacheNode; // points to the current cache node
+
+ M_PROLOG(this);
+
+ // if there's no data object, there's nothing to do
+ if (!m_pDataObject)
+ return(NOERROR);
+
+ for(dwCacheId = CACHEID_GETNEXT_GETALL;
+ lpCacheNode = GetNext(&dwCacheId);)
+ lpCacheNode->OnStop();
+
+ m_pDataObject = NULL; // NOTE: no ref count
+
+ return NOERROR;
+}
+
+
+
+// IOleCache implementation
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::Cache, public
+//
+// Synopsis:
+// implementation of IOleCache::Cache
+//
+// Instructs that cache to cache a rendering of this object.
+//
+// Arguments:
+// [lpforetcIn] -- the presentation format to cache
+// [advf] -- the advise control flags, from ADVF_*
+// [lpdwCacheId] -- pointer to where to return the id of the
+// cache node for this format
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 11/24/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_Cache)
+STDMETHODIMP COleCache::Cache(LPFORMATETC lpforetcIn, DWORD advf,
+ LPDWORD lpdwCacheId)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT error;
+ FORMATETC foretc;
+ LPCACHENODE lpCacheNode = NULL;
+ DWORD dwDummyCacheId; // point lpdwCacheId at this to avoid testing
+
+ M_PROLOG(this);
+
+ // initialize *lpdwCacheId in case of error return, OR,
+ // initialize lpdwCacheId so that we needn't test it before assigning
+ // *lpdwCacheId in future
+ if (lpdwCacheId)
+ *lpdwCacheId = CACHEID_NATIVE; // REVIEW, not CACHEID_INVALID?
+ else
+ lpdwCacheId = &dwDummyCacheId;
+
+ // validate parameters
+ if (!HasValidLINDEX(lpforetcIn))
+ {
+ return(DV_E_LINDEX);
+ }
+
+ if (FAILED(error = VerifyAspectSingle(lpforetcIn->dwAspect)))
+ {
+ return error;
+ }
+
+ if (lpforetcIn->cfFormat)
+ {
+ if (FAILED(error = CheckTymedCFCombination(lpforetcIn)))
+ {
+ return error;
+ }
+ }
+
+ if (lpforetcIn->ptd)
+ {
+ VDATEPTRIN(lpforetcIn->ptd, sizeof(DVTARGETDEVICE));
+ }
+
+ AssertSz(m_pStg,
+ "Cache IStorage ptr has not been initialized by handler\n");
+
+ // copy the FORMATETC, so that we can alter it if we wish
+ foretc = *lpforetcIn;
+
+ if (foretc.dwAspect != DVASPECT_ICON)
+ {
+ BITMAP_TO_DIB(foretc);
+
+ if (m_uFlag & COLECACHEF_FORMATKNOWN)
+ {
+ // check to see if the new format is the same as the
+ // current native format
+ if ((error = IsSameAsObjectFormatEtc(&foretc,
+ m_cfFormat)) == NOERROR)
+ {
+
+ // if ptd is NULL then we know how to draw
+ // this format. Return success code, but return
+ // CACHEID_NATIVE for dwCacheId.
+ if (foretc.ptd == NULL)
+ {
+ // Locate the cache node and update the
+ // advise flags, if they are different
+
+ if (lpCacheNode = GetAt(&foretc, lpdwCacheId))
+ {
+ if (lpCacheNode->GetAdvf() != advf)
+ {
+ // If we are setting new advise flags,
+ // mark the cache as dirty
+
+ lpCacheNode->SetAdvf(advf);
+ m_uFlag |= COLECACHEF_DIRTY;
+ }
+ }
+
+ // We assume that we _must_ already have
+ // cached this format, so we must have
+ // found it
+
+ Assert(lpCacheNode);
+
+ return ResultFromScode(CACHE_S_SAMECACHE);
+ }
+ else if (m_uFlag & COLECACHEF_STATIC)
+ {
+ // NON-NULL ptd doesn't make any sense
+ // for static objects
+ return ResultFromScode(
+ DV_E_DVTARGETDEVICE);
+ }
+
+ }
+ else if (m_uFlag & COLECACHEF_STATIC)
+ return error;
+
+ // otherwise, if formatetc is a non-standard formatetc
+ // (OR) ptd is NON NULL, then we don't have choice but
+ // to cache it.
+ }
+
+ }
+
+ // check to see if we've already got this format cached
+ if (lpCacheNode = GetAt(&foretc, lpdwCacheId))
+ {
+ // are the advise control flags different?
+ if (lpCacheNode->GetAdvf() != advf)
+ {
+ // change the advise control flags; mark cache dirty
+ lpCacheNode->SetAdvf(advf);
+ m_uFlag |= COLECACHEF_DIRTY;
+ }
+
+ // get out, indicating this is already cached
+ return ResultFromScode(CACHE_S_SAMECACHE);
+ }
+
+ // if aspect is DVASPECT_ICON, then format has to be CF_METAFILEPICT
+ if (foretc.dwAspect == DVASPECT_ICON)
+ {
+ // if the format is not set, set it
+ if (foretc.cfFormat == NULL)
+ {
+ foretc.cfFormat = CF_METAFILEPICT;
+ foretc.tymed = TYMED_MFPICT;
+ }
+ else if (foretc.cfFormat != CF_METAFILEPICT)
+ return ResultFromScode(DV_E_FORMATETC);
+ }
+
+ // if this aspect is frozen, don't allow creation of the cache
+ if (m_dwFrozenAspects & lpforetcIn->dwAspect)
+ return ResultFromScode(E_FAIL);
+
+ // Create cache node for this formatetc
+ if (!(lpCacheNode = new FAR CCacheNode(&foretc, advf, this)))
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+ // Add it to the cache list
+ if (!(*lpdwCacheId = Attach(lpCacheNode)))
+ {
+ // if we fail to attach it, delete it and return error
+ lpCacheNode->Delete();
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ // the new cache node has successfully been added, mark cache dirty
+ m_uFlag |= COLECACHEF_DIRTY;
+
+ // try to create the presentation object
+ if ((error = lpCacheNode->CreatePresObject(m_pDataObject,
+ FALSE /*fConvert*/)) == NOERROR)
+ {
+ // presentation object is created, let the cachenode setup
+ // advise connections with the server object.
+ lpCacheNode->OnRun(m_pDataObject);
+ }
+
+ // CreatePresObject can fail to create the presentation object because
+ // of one of the following reasons.
+ // 1. The server object doesn't support the format
+ // 2. The object is not running and the lpformatetc->cfFormat == NULL.
+ //
+ // If the object is running and cfFormat is NULL, then the method
+ // CreatePresObject queries the object to check whether it supports
+ // one of CF_ENHMETAFILE, CF_METAFILEPICT, CF_DIB and CF_BITMAP in that
+ // order. And only if the obejct supports one of those formats does it
+ // create the presentation object, othewise it will be case 1.
+ //
+ // Whether the presentation object is created or not, the cachenode will
+ // not be removed. It is the responsibility of the caller to do Uncache
+ // if the presentation object is not created (which would be conveyed
+ // through a special error code.)
+
+ // Do the special handling for icon here. If the object is not able to
+ // render ICON with CF_METAFILEPICT format, then we will go ahead and
+ // render it ourselves, by getting the ICON from registration data base.
+
+ if (foretc.dwAspect == DVASPECT_ICON &&
+ !IsEqualCLSID(m_clsid, CLSID_NULL))
+ {
+ LPOLEPRESOBJECT lpPresObj; // presentation obj, if there is one
+ STGMEDIUM stgmed;
+
+ // if we failed to create the presentation object, as above,
+ // error code is already set
+ if (!(lpPresObj = lpCacheNode->GetPresObj()))
+ goto errRtn;
+
+ // Don't bother if it has already been rendered
+ if (!lpPresObj->IsBlank())
+ return NOERROR;
+
+ // lookup the icon
+ if (UtGetIconData(NULL/*lpSrcDataObj*/, m_clsid,
+ &foretc, &stgmed) == NOERROR)
+ {
+ if (lpCacheNode->SetData(&foretc, &stgmed, TRUE) !=
+ NOERROR)
+ ReleaseStgMedium(&stgmed);
+ }
+ }
+
+ // If we don't already have an error condition, check to see if this
+ // a format we cannot draw.
+
+ if (S_OK == error && lpforetcIn->cfFormat)
+ {
+ error = CheckTymedCFCombination(&foretc);
+ }
+
+
+errRtn:
+
+ return(error);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::Uncache, public
+//
+// Synopsis:
+// implements IOleCache::Uncache
+//
+// instructs the cache that the indicated cache node is no longer
+// needed and should be deleted
+//
+// Arguments:
+// [dwCacheId] -- the id of the cache node to delete
+//
+// Returns:
+// OLE_E_NOCONNECTION, if [dwCacheId] is invalid
+// S_OK
+//
+// Notes:
+// Internally, CACHEID_NATIVE is valid for COLECACHEF_FORMATKNOWN,
+// but this cache id is never passed outside. This cache node
+// is maintained automatically without any user knowledge of it.
+// Outside the cache, CACHEID_NATIVE is invalid. If this value
+// is passed in, we have to check to see if we have such a node,
+// and if we do, ignore it.
+// REVIEW, why don't we return OLE_E_NOCONNECTION here?
+//
+// History:
+// 11/24/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_Uncache)
+STDMETHODIMP COleCache::Uncache(DWORD dwCacheId)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LPCACHENODE lpCacheNode; // the cache node dwCacheId identifies
+
+ M_PROLOG(this);
+
+ // if the cache id is for the native format node, then this node is
+ // not known about externally, and this is merely an invalid cache node
+ // id that was handed back from Cache().
+ if (dwCacheId == CACHEID_NATIVE)
+ {
+ if (m_uFlag & COLECACHEF_FORMATKNOWN)
+ return NOERROR;
+ }
+ else
+ {
+ // remove cachenode from the cache list and then call its
+ // delete method
+ if (lpCacheNode = Detach(dwCacheId))
+ {
+ lpCacheNode->Delete();
+ m_uFlag |= COLECACHEF_DIRTY;
+ return NOERROR;
+ }
+ }
+
+ // if we got here, [dwCachdId] was invalid
+ return ResultFromScode(OLE_E_NOCONNECTION);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::EnumCache, public
+//
+// Synopsis:
+// implements IOleCache::EnumCache
+//
+// returns an enumerator that can be used to tell what is in the
+// cache
+//
+// Arguments:
+// [ppenum] -- a pointer to where to return the pointer to the
+// enumerator
+//
+// Returns:
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 11/24/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_EnumCache)
+STDMETHODIMP COleCache::EnumCache(LPENUMSTATDATA FAR* ppenum)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ M_PROLOG(this);
+
+ if (!(*ppenum = (LPENUMSTATDATA) new CCacheEnum(this, (DWORD) DEF_LINDEX,
+ FALSE)))
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::InitCache, public
+//
+// Synopsis:
+// implements IOleCache::InitCache
+//
+// initializes all cache nodes with the given data object
+//
+// Arguments:
+// [lpSrcDataObj] -- pointer to the source data object
+//
+// Returns:
+// E_INVALIDARG, if [lpSrcDataObj] is NULL
+// same as IOleCache2::UpdateCache
+//
+// Notes:
+//
+// History:
+// 11/24/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_InitCache)
+STDMETHODIMP COleCache::InitCache(LPDATAOBJECT lpSrcDataObj)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ M_PROLOG(this);
+
+ // make sure there's a data object
+ if (!lpSrcDataObj)
+ return ResultFromScode(E_INVALIDARG);
+
+ // scan the cache list and update all the cache nodes. It is possible
+ // that for some cache nodes the presentation objects get created as
+ // part of the update process. As explained in IOleCache
+ return UpdateCache(lpSrcDataObj, UPDFCACHE_ALLBUTNODATACACHE,
+ NULL /* reserved */);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::SetData, public
+//
+// Synopsis:
+// implements IOleCache::SetData
+//
+// puts data into the cache node which matches the given
+// FORMATETC
+//
+// Arguments:
+// [pformatetc] -- the format the data is in
+// [pmedium] -- the storage medium for the new data
+// [fRelease] -- indicates whether to release the storage
+// after the data is examined
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// If the data is for a static object, it is written out to
+// disk to the contents stream.
+//
+// History:
+// 11/24/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_SetData)
+STDMETHODIMP COleCache::SetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium,
+ BOOL fRelease)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LPCACHENODE lpCacheNode; // pointer to the matching cache node
+ CLIPFORMAT cfFormat; // local copy of (transmuted) format
+
+ M_PROLOG(this);
+
+ VERIFY_TYMED_SINGLE_VALID_FOR_CLIPFORMAT(pformatetc)
+
+ // if the object, is static, and we don't already have it,
+ // write it out to the contents stream
+ if (m_uFlag & COLECACHEF_STATIC)
+ {
+ HRESULT error;
+ FORMATETC foretc;
+ STGMEDIUM stgmed;
+
+ if (pformatetc->dwAspect == DVASPECT_ICON)
+ goto LOther;
+
+ foretc = *pformatetc;
+
+ if (error = IsSameAsObjectFormatEtc(&foretc, m_cfFormat))
+ return error;
+
+ if (foretc.ptd)
+ return ResultFromScode(DV_E_DVTARGETDEVICE);
+
+ if (!(lpCacheNode = AddCacheNodeForNative()))
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ if (error = lpCacheNode->SetData(pformatetc, pmedium, fRelease))
+ return error;
+
+ // write data into "CONTENTS" stream
+ if (error = OpenOrCreateStream(m_pStg,
+ OLE_CONTENTS_STREAM, &stgmed.pstm))
+ return error;
+
+ stgmed.pUnkForRelease = NULL;
+ stgmed.tymed = TYMED_ISTREAM;
+ foretc.tymed = TYMED_ISTREAM;
+
+ error = (lpCacheNode->GetPresObj())->GetDataHere(&foretc,
+ &stgmed);
+ stgmed.pstm->Release();
+ return error;
+ }
+
+LOther:
+ // if its CF_BITMAP, keep CF_DIB instead
+ cfFormat = ((pformatetc->cfFormat == CF_BITMAP) ?
+ CF_DIB : pformatetc->cfFormat);
+
+ // find the cache node for the requested data, if there is one
+ if (!(lpCacheNode = GetAt(pformatetc->dwAspect,
+ pformatetc->lindex, cfFormat, pformatetc->ptd,
+ NULL /*lpdwCacheId*/)))
+ return ResultFromScode(OLE_E_BLANK);
+
+ // set the data in that cache node
+ return lpCacheNode->SetData(pformatetc, pmedium, fRelease);
+}
+
+
+// IOleCache2 implementation
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::UpdateCache, public
+//
+// Synopsis:
+// implements IOleCache2::UpdateCache
+//
+// Updates all cache entries with the data object passed in, if
+// it is not NULL. If NULL, uses the already-known about data
+// object that is kept inside if the object is running.
+//
+// Arguments:
+// [pDataObjIn] -- The data object to get data from, or NULL
+// [grfUpdf] -- update control flags
+// [pReserved] -- must be NULL
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// The native cache node is updated on disk, only if its
+// COLECACHEF_PBRUSHORMSDRAW
+// REVIEW, what about other native format objects?
+//
+// History:
+// 11/24/93 - ChrisWe - file cleanup and inspection
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_UpdateCache)
+STDMETHODIMP COleCache::UpdateCache(LPDATAOBJECT pDataObjIn, DWORD grfUpdf,
+ LPVOID pReserved)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LPDATAOBJECT pDataObject; // the data object to use for the update
+ DWORD dwCacheId; // cache id of current node being examined
+ ULONG cntUpdatedNodes; // count of nodes that were updated without error
+ ULONG cntTotalNodes;
+ LPCACHENODE lpCacheNode; // the cache node currently being updated
+
+ M_PROLOG(this);
+
+ if (pReserved != NULL)
+ AssertSz(FALSE, "Non-NULL reserved parameter passed to OleCache::UpdateCache");
+
+ // validate the data object, if one is passed in; if there isn't one,
+ // use the current one for the cache, if there is one
+ if (pDataObjIn)
+ {
+ VDATEIFACE(pDataObjIn);
+ pDataObject = pDataObjIn;
+
+ }
+ else if (!(pDataObject = m_pDataObject))
+ {
+ return ResultFromScode(OLE_E_NOTRUNNING);
+ }
+
+ // if no caches, then there is nothing to update.
+ if (m_uCacheNodeCnt == 0)
+ return NOERROR;
+
+ // Do special handling for PaintBrush or MSDraw objects.
+ if (m_uFlag & COLECACHEF_PBRUSHORMSDRAW)
+ UpdateCacheNodeForNative();
+
+ // Ask the cache nodes to update themselves from this data object
+ // pointer.
+ for(cntUpdatedNodes = 0, dwCacheId = CACHEID_GETNEXT_GETALLBUTNATIVE,
+ cntTotalNodes = 0;
+ lpCacheNode = GetNext(&dwCacheId);)
+ {
+ cntTotalNodes++;
+ if (lpCacheNode->Update(pDataObject, grfUpdf) == NOERROR)
+ {
+ cntUpdatedNodes++;
+ }
+ }
+
+ // it's OK to have zero nodes and zero updates (PBrush will
+ // have this in particular
+
+ if( cntUpdatedNodes == cntTotalNodes )
+ {
+ return NOERROR;
+ }
+
+ if (cntUpdatedNodes == 0)
+ return ReportResult(0, CACHE_E_NOCACHE_UPDATED, 0, 0);
+
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::DiscardCache, public
+//
+// Synopsis:
+// implements IOleCache2::DiscardCache
+//
+// Instructs the cache that its contents should be discarded;
+// the contents are optionally saved to disk before discarding.
+//
+// Arguments:
+// [dwDiscardOpt] -- discard option from DISCARDCACHE_*
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// This maintains the dirty state of the cache, even if it is
+// saved.
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+STDMETHODIMP COleCache::DiscardCache(DWORD dwDiscardOpt)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT error; // error state so far
+ COLECACHEFLAG uDirty = m_uFlag & COLECACHEF_DIRTY;
+ // remember state of the dirty flag
+
+ if (dwDiscardOpt == DISCARDCACHE_SAVEIFDIRTY)
+ {
+ // if the contents are dirty, try to save to disk
+ if (uDirty)
+ {
+ if (m_pStg == NULL)
+ return ResultFromScode(OLE_E_NOSTORAGE);
+
+ if (FAILED(error = Save(m_pStg,
+ TRUE /* fSameAsLoad */)))
+ return error;
+ }
+
+ // continue and do SaveCompleted which will discard the cached
+ // presentations from memory
+
+ goto LNoSave;
+ }
+
+ // if any option other than NOSAVE was specified, we shouldn't have
+ // gotten here
+ AssertSz(dwDiscardOpt == DISCARDCACHE_NOSAVE,
+ "Invalid DiscardCache option");
+ if (dwDiscardOpt != DISCARDCACHE_NOSAVE)
+ return ResultFromScode(E_INVALIDARG);
+
+LNoSave:
+ m_uFlag |= COLECACHEF_NOSCRIBBLEMODE | COLECACHEF_SAMEASLOAD;
+ wSaveCompleted(NULL, TRUE /*fDiscardDrawCacheAlso*/);
+
+ // restore the dirty state, since Save() will have cleared it
+ // REVIEW, why, since it's not dirty anymore?
+ m_uFlag |= uDirty;
+
+ return NOERROR;
+}
+
+
+// private IUnknown implementation
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheUnkImpl::QueryInterface, public
+//
+// Synopsis:
+// implements IUnknown::QueryInterface
+//
+// This provides the private IUnknown implementation when
+// COleCache is aggregated
+//
+// Arguments:
+// [iid] -- IID of the desired interface
+// [ppv] -- pointer to where to return the requested interface
+//
+// Returns:
+// E_NOINTERFACE, if the requested interface is not available
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheUnkImpl_QueryInterface)
+STDMETHODIMP NC(COleCache, CCacheUnkImpl)::QueryInterface(REFIID iid,
+ LPVOID FAR* ppv)
+{
+ VDATEHEAP();
+
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_UnkPrivate);
+
+ M_PROLOG(pOleCache);
+ VDATEPTROUT(ppv, LPVOID);
+
+ if (IsEqualIID(iid, IID_IUnknown) ||
+ IsEqualIID(iid, IID_IOleCache) ||
+ IsEqualIID(iid, IID_IOleCache2))
+ *ppv = (void FAR *)(IOleCache2 FAR *)pOleCache;
+ else if (IsEqualIID(iid, IID_IDataObject))
+ *ppv = (void FAR *)(IDataObject FAR *)&pOleCache->m_Data;
+ else if (IsEqualIID(iid, IID_IViewObject) ||
+ IsEqualIID(iid, IID_IViewObject2))
+ *ppv = (void FAR *)(IViewObject2 FAR *)&pOleCache->m_View;
+ else if (IsEqualIID(iid, IID_IPersist) ||
+ IsEqualIID(iid, IID_IPersistStorage))
+ *ppv = (void FAR *)(IPersistStorage FAR *)pOleCache;
+ else if (IsEqualIID(iid, IID_IOleCacheControl))
+ *ppv = (void FAR *)(IOleCacheControl FAR *)pOleCache;
+ else
+ {
+ *ppv = NULL;
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+
+ pOleCache->m_pUnkOuter->AddRef();
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheUnkImpl::AddRef, public
+//
+// Synopsis:
+// implements IUnknown::AddRef
+//
+// This is part of the private IUnknown implementation of
+// COleCache used when COleCache is aggregated
+//
+// Arguments:
+// none
+//
+// Returns:
+// the object's reference count
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheUnkImpl_AddRef)
+STDMETHODIMP_(ULONG) NC(COleCache, CCacheUnkImpl)::AddRef(void)
+{
+ VDATEHEAP();
+
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_UnkPrivate);
+
+ LEDebugOut((DEB_TRACE, "%p _IN COleCache::CCacheUnkImpl::AddRef "
+ "( )\n", this ));
+
+ M_PROLOG(pOleCache);
+
+ ++pOleCache->m_refs;
+
+ LEDebugOut((DEB_TRACE, "%p OUT COleCache::CCacheUnkImpl::AddRef "
+ "( %lu )\n", this, pOleCache->m_refs));
+
+ return pOleCache->m_refs;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheUnkImpl::Release, public
+//
+// Synopsis:
+// implements IUnknown::Release
+//
+// This is part of the private IUnknown implementation of
+// COleCache used when COleCache is aggregated
+//
+// Arguments:
+// none
+//
+// Returns:
+// the object's reference count
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheUnkImpl_Release)
+STDMETHODIMP_(ULONG) NC(COleCache, CCacheUnkImpl)::Release(void)
+{
+ VDATEHEAP();
+
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_UnkPrivate);
+ ULONG uRefs; // the reference count after decrementing
+
+ M_PROLOG(pOleCache);
+
+ LEDebugOut((DEB_TRACE, "%p _IN COleCache::CCacheUnkImpl::Release "
+ "( )\n", this ));
+
+ if ((uRefs = --pOleCache->m_refs) == 0)
+ {
+ delete pOleCache;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT COleCache::CCacheUnkImpl::Release "
+ "( %lu )\n", this, uRefs));
+
+ return uRefs; // m_refs reference is no longer valid if it was zero
+}
+
+// IDataObject implementation
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheDataImpl::QueryInterface, public
+//
+// Synopsis:
+// implements IUnknown::QueryInterface
+//
+// Arguments:
+// [iid] -- IID of the desired interface
+// [ppv] -- pointer to where to return the requested interface
+//
+// Returns:
+// E_NOINTERFACE, if the requested interface is not available
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheDataImpl_QueryInterface)
+STDMETHODIMP NC(COleCache,CCacheDataImpl)::QueryInterface(REFIID riid,
+ LPVOID FAR* ppvObj)
+{
+ VDATEHEAP();
+
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_Data);
+
+ return pOleCache->m_pUnkOuter->QueryInterface(riid, ppvObj);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheDataImpl::AddRef, public
+//
+// Synopsis:
+// implements IUnknown::AddRef
+//
+// Arguments:
+// none
+//
+// Returns:
+// the object's reference count
+//
+// Notes:
+//
+// History:
+// 11/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheDataImpl_AddRef)
+STDMETHODIMP_(ULONG) NC(COleCache,CCacheDataImpl)::AddRef (void)
+{
+ VDATEHEAP();
+
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_Data);
+
+ return pOleCache->m_pUnkOuter->AddRef();
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheDataImpl::Release, public
+//
+// Synopsis:
+// implements IUnknown::Release
+//
+// Arguments:
+// none
+//
+// Returns:
+// the object's reference count
+//
+// Notes:
+//
+// History:
+// 11/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheDataImpl_Release)
+STDMETHODIMP_(ULONG) NC(COleCache,CCacheDataImpl)::Release (void)
+{
+ VDATEHEAP();
+
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_Data);
+
+ return pOleCache->m_pUnkOuter->Release();
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheDataImpl::GetData, public
+//
+// Synopsis:
+// implements IDataObject::GetData
+//
+// Arguments:
+// [pforetcIn] -- the format the requestor would like the data in
+// [pmedium] -- where to return the storage medium to the caller
+//
+// Returns:
+// OLE_E_BLANK, if the cache is empty
+// REVIEW, anything COleCache::GetPresObj returns
+// REVIEW, anything returned by presObj->GetData
+//
+// Notes:
+//
+// History:
+// 11/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheDataImpl_GetData)
+STDMETHODIMP NC(COleCache,CCacheDataImpl)::GetData(LPFORMATETC pforetcIn,
+ LPSTGMEDIUM pmedium)
+{
+ VDATEHEAP();
+
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_Data);
+ LPOLEPRESOBJECT lpPresObj; // the presentation object with
+ // the requested data in it
+
+ M_PROLOG(pOleCache);
+
+ // if the cache is empty, return with nothing
+ if (!pOleCache->m_uCacheNodeCnt)
+ return ResultFromScode(OLE_E_BLANK);
+
+ Verify(pmedium);
+ Verify(pforetcIn);
+
+ // null out in case of error
+ pmedium->tymed = TYMED_NULL;
+ pmedium->pUnkForRelease = NULL;
+
+ VERIFY_ASPECT_SINGLE(pforetcIn->dwAspect);
+
+ // if no presentation object in the cache that matches the requested
+ // format, return blank
+ if (!(lpPresObj = pOleCache->GetPresObj(pforetcIn->dwAspect,
+ pforetcIn->lindex, pforetcIn->cfFormat,
+ pforetcIn->ptd, NULL)))
+ return(ResultFromScode(OLE_E_BLANK));
+
+ // if we got here, we have a presentation object that matches the
+ // requested format; return data from it
+ return(lpPresObj->GetData(pforetcIn, pmedium));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheDataImpl::GetDataHere, public
+//
+// Synopsis:
+// implements IDataObject::GetDataHere
+//
+// Arguments:
+// [pforetcIn] -- the format the requestor would like the data in
+// [pmedium] -- where to return the storage medium to the caller
+//
+// Returns:
+// OLE_E_BLANK, if the cache is empty
+// REVIEW, anything COleCache::GetPresObj returns
+// REVIEW, anything returned by presObj->GetData
+//
+// Notes:
+//
+// History:
+// 11/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheDataImpl_GetDataHere)
+STDMETHODIMP NC(COleCache,CCacheDataImpl)::GetDataHere(LPFORMATETC pforetcIn,
+ LPSTGMEDIUM pmedium)
+{
+ VDATEHEAP();
+
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_Data);
+ LPOLEPRESOBJECT lpPresObj; // the presentation object with the
+ // requested data in it
+
+ M_PROLOG(pOleCache);
+
+ // if the cache is empty, return with nothing
+ if (!pOleCache->m_uCacheNodeCnt);
+ return ResultFromScode(OLE_E_BLANK);
+
+ VERIFY_TYMED_SINGLE(pforetcIn->tymed);
+ VERIFY_ASPECT_SINGLE(pforetcIn->dwAspect);
+
+ // TYMED_MFPICT, TYMED_GDI will not be allowed
+ if ((pforetcIn->tymed == TYMED_MFPICT)
+ || (pforetcIn->tymed == TYMED_GDI)
+ || (pmedium->tymed != pforetcIn->tymed))
+ return ReportResult(0, DV_E_TYMED, 0, 0);
+
+ // Get data from cache node, if one exists
+ if (!(lpPresObj = pOleCache->GetPresObj(pforetcIn->dwAspect,
+ pforetcIn->lindex, pforetcIn->cfFormat,
+ pforetcIn->ptd, NULL)))
+ return ResultFromScode(OLE_E_BLANK);
+
+ // ask the presentation object for the data
+ return lpPresObj->GetDataHere(pforetcIn, pmedium);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheDataImpl::QueryGetData, public
+//
+// Synopsis:
+// implements IDataObject::QueryGetData
+//
+// Arguments:
+// [pforetcIn] -- the format to check for
+//
+// Returns:
+// S_FALSE, if data is not available in the requested format
+// S_OK otherwise
+//
+// Notes:
+// We will say that the formatetc is supported only if there is
+// a cache and a presentation data in that cache for that
+// formatetc.
+//
+// History:
+// 11/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheDataImpl_QueryGetData)
+STDMETHODIMP NC(COleCache,CCacheDataImpl)::QueryGetData(LPFORMATETC pforetcIn)
+{
+ VDATEHEAP();
+
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_Data);
+ LPOLEPRESOBJECT lpPresObj; // the presentation object with the
+ // requested data in it
+
+ M_PROLOG(pOleCache);
+
+ // if the cache is empty, return with nothing
+ if (!pOleCache->m_uCacheNodeCnt)
+ {
+ return ResultFromScode(S_FALSE);
+ }
+
+ VERIFY_TYMED_VALID_FOR_CLIPFORMAT(pforetcIn);
+
+ // if the cachenode for this formatetc and the presentation object for
+ // the cachenode exists then query will succeed
+ if (lpPresObj = pOleCache->GetPresObj(pforetcIn->dwAspect,
+ pforetcIn->lindex, pforetcIn->cfFormat,
+ pforetcIn->ptd, NULL))
+ {
+ return NOERROR;
+ }
+
+ return ResultFromScode(S_FALSE);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheDataImpl::GetCanonicalFormatEtc, public
+//
+// Synopsis:
+// implements IDataObject::GetCanonicalFormatEtc
+//
+// Arguments:
+// [pformatetc] --
+// [pformatetcOut] --
+//
+// Returns:
+//
+// Notes:
+//
+// History:
+// 11/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheDataImpl_GetCanonicalFormatEtc)
+STDMETHODIMP NC(COleCache,CCacheDataImpl)::GetCanonicalFormatEtc(
+ LPFORMATETC pformatetc, LPFORMATETC pformatetcOut)
+{
+ VDATEHEAP();
+
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_Data);
+
+ M_PROLOG(pOleCache);
+
+ // REVIEW: code need to be added
+ return ReportResult(0, E_NOTIMPL, 0, 0); // just not implemented
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheDataImpl::SetData, public
+//
+// Synopsis:
+// implements IDataObject::SetData
+//
+// Arguments:
+// [pformatetc] -- the format the data is in
+// [pmedium] -- the storage medium the data is on
+// [fRelease] -- release storage medium after data is copied
+//
+// Returns:
+// REVIEW, anything IOleCache::SetData can return
+//
+// Notes:
+// Does the same thing as IOleCache::SetData
+//
+// History:
+// 11/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheDataImpl_SetData)
+STDMETHODIMP NC(COleCache,CCacheDataImpl)::SetData(LPFORMATETC pformatetc,
+ LPSTGMEDIUM pmedium, BOOL fRelease)
+{
+ VDATEHEAP();
+
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_Data);
+
+ VERIFY_TYMED_SINGLE_VALID_FOR_CLIPFORMAT(pformatetc);
+
+ return pOleCache->SetData(pformatetc, pmedium, fRelease);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheDataImpl::EnumFormatEtc, public
+//
+// Synopsis:
+// implements IDataObject::EnumFormatEtc
+//
+// Arguments:
+// [dwDirection] -- which way to run the enumerator
+// [ppenumFormatEtc] -- pointer to where to put the enumerator
+//
+// Returns:
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 02/10/94 - ChrisWe - added implementation
+// 11/10/93 - ChrisWe - set returned pointer to NULL
+// 11/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheDataImpl_EnumFormatEtc)
+STDMETHODIMP NC(COleCache,CCacheDataImpl)::EnumFormatEtc(DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenumFormatEtc)
+{
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_Data);
+ IEnumSTATDATA FAR *pIES;
+ HRESULT hr;
+
+ VDATEHEAP();
+ VDATEPTROUT(ppenumFormatEtc, LPENUMFORMATETC);
+
+ // initialize for error return
+ *ppenumFormatEtc = NULL;
+
+ // check that only an enumeration for retrieval is required
+ if ((dwDirection | DATADIR_GET) != DATADIR_GET)
+ return(ReportResult(0, E_NOTIMPL, 0, 0));
+
+ hr = pOleCache->EnumCache(&pIES);
+ if (!SUCCEEDED(hr))
+ return(hr);
+
+ *ppenumFormatEtc = (IEnumFORMATETC FAR *)new CCacheEnumFormatEtc(pIES);
+ pIES->Release();
+
+ if (!*ppenumFormatEtc)
+ return(ReportResult(0, E_OUTOFMEMORY, 0, 0));
+
+ return(S_OK);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheDataImpl::DAdvise, public
+//
+// Synopsis:
+// implements IDataObject::DAdvise
+//
+// Arguments:
+// [pforetc] -- the data format the advise sink is interested in
+// [advf] -- advise control flags from ADVF_*
+// [pAdvSink] -- the advise sink
+// [pdwConnection] -- pointer to where to return the connection id
+//
+// Returns:
+// OLE_E_ADVISENOTSUPPORTED
+//
+// Notes:
+// Defhndlr and deflink never call the following three methods. Even for App
+// handlers which make use our cache implementation this is not necessary. So,
+// I am making it return error.
+//
+// History:
+// 11/10/93 - ChrisWe - set returned connection id to 0
+// 11/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheDataImpl_DAdvise)
+STDMETHODIMP NC(COleCache,CCacheDataImpl)::DAdvise(LPFORMATETC pforetc,
+ DWORD advf, IAdviseSink FAR* pAdvSink, DWORD FAR* pdwConnection)
+{
+ VDATEHEAP();
+
+ *pdwConnection = 0;
+ return(ReportResult(0, OLE_E_ADVISENOTSUPPORTED, 0, 0));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheDataImpl::DUnadvise, public
+//
+// Synopsis:
+// implements IDataObject::DUnadvise
+//
+// Arguments:
+// [dwConnection] -- the connection id
+//
+// Returns:
+// OLE_E_NOCONNECTION
+//
+// Notes:
+// See COleCache::CCacheDataImpl::DAdvise
+//
+// History:
+// 11/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(COleCache_CCacheDataImpl_DUnadvise)
+STDMETHODIMP NC(COleCache,CCacheDataImpl)::DUnadvise(DWORD dwConnection)
+{
+ VDATEHEAP();
+
+ return(ReportResult(0, OLE_E_NOCONNECTION, 0, 0));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheDataImpl::EnumDAdvise, public
+//
+// Synopsis:
+// implements IDataObject::EnumDAdvise
+//
+// Arguments:
+// [ppenumDAdvise] -- pointer to where to return the enumerator
+//
+// Returns:
+// OLE_E_ADVISENOTSUPPORTED
+//
+// Notes:
+// See COleCache::CCacheDataImpl::DAdvise
+//
+// History:
+// 11/10/93 - ChrisWe - set returned enumerator pointer to 0
+// 11/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheDataImpl_EnumDAdvise)
+STDMETHODIMP NC(COleCache,CCacheDataImpl)::EnumDAdvise(
+ LPENUMSTATDATA FAR* ppenumDAdvise)
+{
+ VDATEHEAP();
+
+ *ppenumDAdvise = NULL;
+ return(ReportResult(0, OLE_E_ADVISENOTSUPPORTED, 0, 0));
+}
+
+
+// IViewObject implementation
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheViewImpl::QueryInterface, public
+//
+// Synopsis:
+// implements IUnknown::QueryInterface
+//
+// Arguments:
+// [iid] -- IID of the desired interface
+// [ppv] -- pointer to where to return the requested interface
+//
+// Returns:
+// E_NOINTERFACE, if the requested interface is not available
+// S_OK
+//
+// Notes:
+//
+// History:
+// 01/12/95 - t-ScottH- added VDATETHREAD( GETPPARENT...)
+// 11/10/93 - ChrisWe - file inspection and cleanup
+// 11/30/93 - alexgo - fixed bug with GETPPARENT usage
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheViewImpl_QueryInterface)
+STDMETHODIMP NC(COleCache,CCacheViewImpl)::QueryInterface(REFIID riid,
+ LPVOID FAR* ppvObj)
+{
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_View);
+
+ VDATEHEAP();
+ VDATETHREAD(pOleCache);
+
+ return pOleCache->m_pUnkOuter->QueryInterface(riid, ppvObj);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheViewImpl::AddRef, public
+//
+// Synopsis:
+// implements IUnknown::AddRef
+//
+// Arguments:
+// none
+//
+// Returns:
+// the object's reference count
+//
+// Notes:
+//
+// History:
+// 01/12/95 - t-ScottH- added VDATETHREAD( GETPPARENT...)
+// 11/10/93 - ChrisWe - file inspection and cleanup
+// 11/30/93 - alexgo - fixed bug with GETPPARENT usage
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheViewImpl_AddRef)
+STDMETHODIMP_(ULONG) NC(COleCache,CCacheViewImpl)::AddRef(void)
+{
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_View);
+
+ VDATEHEAP();
+
+ //
+ // VDATETHREAD contains a 'return HRESULT' but this procedure expects to
+ // return a ULONG. Avoid the warning.
+#if ( _MSC_VER >= 800 )
+#pragma warning( disable : 4245 )
+#endif
+ VDATETHREAD(pOleCache);
+#if ( _MSC_VER >= 800 )
+#pragma warning( default: 4245 )
+#endif
+
+ return pOleCache->m_pUnkOuter->AddRef();
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheViewImpl::Release, public
+//
+// Synopsis:
+// implements IUnknown::Release
+//
+// Arguments:
+// none
+//
+// Returns:
+// the object's reference count
+//
+// Notes:
+//
+// History:
+// 01/12/95 - t-ScottH- added VDATETHREAD( GETPPARENT...)
+// 11/10/93 - ChrisWe - file inspection and cleanup
+// 11/30/93 - alexgo - fixed bug with GETPPARENT usage
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheViewImpl_Release)
+STDMETHODIMP_(ULONG) NC(COleCache,CCacheViewImpl)::Release(void)
+{
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_View);
+
+ VDATEHEAP();
+
+ //
+ // VDATETHREAD contains a 'return HRESULT' but this procedure expects to
+ // return a ULONG. Avoid the warning.
+#if ( _MSC_VER >= 800 )
+#pragma warning( disable : 4245 )
+#endif
+ VDATETHREAD(pOleCache);
+#if ( _MSC_VER >= 800 )
+#pragma warning( default : 4245 )
+#endif
+
+ return pOleCache->m_pUnkOuter->Release();
+}
+
+
+#ifdef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Method: static COleCache::DrawStackSwitch
+//
+// Synopsis: needed for stack switching
+//
+// Arguments: [pCV] --
+// [dwDrawAspect] --
+// [lindex] --
+// [pvAspect] --
+// [ptd] --
+// [hicTargetDev] --
+// [hdcDraw] --
+// [lprcBounds] --
+// [lprcWBounds] --
+// [pfnContinue] --
+// [DWORD] --
+// [DWORD] --
+// [dwContinue] --
+//
+// Returns:
+//
+// History: 5-25-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+INTERNAL COleCache::DrawStackSwitch(
+ LPVOID *pCV,
+ DWORD dwDrawAspect,
+ LONG lindex, void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev, HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ BOOL (CALLBACK * pfnContinue)(DWORD),
+ DWORD dwContinue)
+{
+ HRESULT hres = NOERROR;
+ StackDebugOut((DEB_STCKSWTCH, "COleCache::DrawStackSwitch 32->16 : pCV(%x)n", pCV));
+ hres = ((CCacheViewImpl *)pCV)->SSDraw(dwDrawAspect, lindex, pvAspect, ptd, hicTargetDev, hdcDraw,
+ lprcBounds, lprcWBounds, pfnContinue, dwContinue);
+ StackDebugOut((DEB_STCKSWTCH, "COleCache::DrawStackSwitch 32<-16 back; hres:%ld\n", hres));
+ return hres;
+}
+#endif // _CHICAGO_
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheViewImpl::Draw, public
+//
+// Synopsis:
+// implements IViewObject::Draw
+//
+// Arguments:
+// [dwDrawAspect] -- a value from the DVASPECT_* enumeration
+// [lindex] -- indicates what piece of the object is of
+// interest; legal values vary with dwDrawAspect
+// [pvAspect] -- currently NULL
+// [ptd] -- the target device
+// [hicTargetDev] -- in information context for [ptd]
+// [hdcDraw] -- device context on which drawing is to be done
+// [lprcBounds] -- boundaries of drawing on [hdcDraw]
+// [lprcWBounds] -- if hdcDraw is a meta-file, it's boundaries
+// [pfnContinue] --a callback function that the drawer should call
+// periodically to see if rendering should be aborted.
+// [dwContinue] -- passed on into [pfnContinue]
+//
+// Returns:
+// OLE_E_BLANK, if no presentation object can be found
+// REVIEW, anything from IOlePresObj::Draw
+//
+// Notes:
+// This finds the presentation object in the cache for
+// the requested format, if there is one, and then passes
+// on the call to its Draw method.
+//
+// The use of a callback function as a parameter means that
+// this interface cannot be remoted, unless some custom
+// proxy is built, allowing the function to be called back in its
+// original context; the interface is defined as
+// [local] in common\types
+//
+// History:
+// 01/12/95 - t-ScottH- added VDATETHREAD( GETPPARENT...)
+// 11/11/93 - ChrisWe - file inspection and cleanup
+// 11/30/93 - alexgo - fixed bug with GETPPARENT usage
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheViewImpl_Draw)
+STDMETHODIMP NC(COleCache,CCacheViewImpl)::Draw(
+ DWORD dwDrawAspect,
+ LONG lindex, void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev, HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ BOOL (CALLBACK * pfnContinue)(DWORD),
+ DWORD dwContinue)
+#ifdef _CHICAGO_
+{
+ HRESULT hres;
+ // Note: Switch to the 16 bit stack under WIN95.
+ if (SSONBIGSTACK())
+ {
+ LEDebugOut((DEB_TRACE, "COleCache::DrawStackSwitch 32->16; this(%x)n", this));
+ hres = SSCall(44, SSF_SmallStack, (LPVOID)DrawStackSwitch, (DWORD) this,
+ (DWORD)dwDrawAspect, (DWORD)lindex,(DWORD) pvAspect, (DWORD)ptd, (DWORD)hicTargetDev,
+ (DWORD)hdcDraw, (DWORD)lprcBounds, (DWORD)lprcWBounds, (DWORD)pfnContinue, (DWORD)dwContinue);
+ }
+ else
+ hres = SSDraw(dwDrawAspect, lindex, pvAspect, ptd, hicTargetDev, hdcDraw,
+ lprcBounds, lprcWBounds, pfnContinue, dwContinue);
+
+ return hres;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSDraw
+//
+// Synopsis: Called by Draw after switching to 16 bit stack
+//
+// Arguments: [dwDrawAspect] --
+// [lindex] --
+// [pvAspect] --
+// [ptd] --
+// [hicTargetDev] --
+// [hdcDraw] --
+// [lprcBounds] --
+// [lprcWBounds] --
+// [pfnContinue] --
+// [DWORD] --
+// [DWORD] --
+// [dwContinue] --
+//
+// Returns:
+//
+// History: 5-25-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+#pragma SEG(COleCache_CCacheViewImpl_SSDraw)
+STDMETHODIMP NC(COleCache,CCacheViewImpl)::SSDraw(
+ DWORD dwDrawAspect,
+ LONG lindex, void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev, HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ BOOL (CALLBACK * pfnContinue)(DWORD),
+ DWORD dwContinue)
+#endif // _CHICAGO_
+{
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_View);
+
+ VDATEHEAP();
+ VDATETHREAD(pOleCache);
+
+ BOOL bMetaDC; // is [hdcDraw] for a metafile?
+ LPOLEPRESOBJECT lpPresObj; // the presentation object for the
+ // requested format, if there is one
+
+ M_PROLOG(pOleCache);
+
+ // validate parameters
+// if (pvAspect)
+// VDATEPTRIN(pvAspect, ?????);
+ if (ptd)
+ VDATEPTRIN(ptd, DVTARGETDEVICE);
+ if (lprcWBounds)
+ VDATEPTRIN(lprcWBounds, RECTL);
+
+ if( !lprcBounds )
+ {
+ return E_INVALIDARG;
+ }
+ else
+ {
+ VDATEPTRIN(lprcBounds, RECTL);
+ }
+
+ // we can't draw into a NULL-DC.
+ if( hdcDraw == NULL )
+ {
+ return E_INVALIDARG;
+ }
+
+ if (!IsValidLINDEX(dwDrawAspect, lindex))
+ {
+ return(DV_E_LINDEX);
+ }
+
+ // Get presentation object for this aspect, lindex, ptd, if there is one
+ if (!(lpPresObj = pOleCache->GetPresObjForDrawing(dwDrawAspect,
+ lindex, ptd)))
+ return ReportResult(0, OLE_E_BLANK, 0, 0);
+
+ // if the DC is a metafile DC then valid window bounds must be passed in
+ if ((bMetaDC = OleIsDcMeta(hdcDraw)) && (lprcWBounds == NULL))
+ return ReportResult(0, E_INVALIDARG, 0, 0);
+
+#ifdef MAC_REVIEW
+
+A RECT value on the MAC contains members which are 'short's'. A RECTL
+uses longs, and in the code below an assumption is explicitely made
+that long member values is directly comp[atible on the MAC. Naturally, this is not
+the case, and the compiler will barf on this.
+
+#endif
+
+#ifndef WIN32 // no need to do this on WIN 32 also
+
+ // On Win 16 make sure that the coordinates are valid 16bit quantities.
+ RECT rcBounds;
+ RECT rcWBounds;
+
+ if (!(IS_SMALL_INT(lprcBounds->left) &&
+ IS_SMALL_INT(lprcBounds->right) &&
+ IS_SMALL_INT(lprcBounds->top) &&
+ IS_SMALL_INT(lprcBounds->bottom)))
+ {
+ AssertSz(FALSE, "Rect coordinate is not a small int");
+ return ReportResult(0, OLE_E_INVALIDRECT, 0, 0);
+
+ }
+ else
+ {
+ rcBounds.left = (int) lprcBounds->left;
+ rcBounds.right = (int) lprcBounds->right;
+ rcBounds.top = (int) lprcBounds->top;
+ rcBounds.bottom = (int) lprcBounds->bottom;
+ }
+
+
+ if (bMetaDC)
+ {
+ if (!(IS_SMALL_INT(lprcWBounds->left) &&
+ IS_SMALL_INT(lprcWBounds->right) &&
+ IS_SMALL_INT(lprcWBounds->top) &&
+ IS_SMALL_INT(lprcWBounds->bottom)))
+ {
+ AssertSz(FALSE, "Rect coordinate is not a small int");
+ return ReportResult(0, OLE_E_INVALIDRECT, 0, 0);
+ }
+ else
+ {
+ rcWBounds.left = (int) lprcWBounds->left;
+ rcWBounds.right = (int) lprcWBounds->right;
+ rcWBounds.top = (int) lprcWBounds->top;
+ rcWBounds.bottom = (int) lprcWBounds->bottom;
+ }
+ }
+
+ return(lpPresObj->Draw(pvAspect, hicTargetDev, hdcDraw,
+ &rcBounds, &rcWBounds, pfnContinue, dwContinue));
+#else
+ // on MAC as well as win 32 we can use the same pointer as it is,
+ // 'cause rect fields are 32 bit quantities
+ return(lpPresObj->Draw(pvAspect, hicTargetDev, hdcDraw,
+ lprcBounds, lprcWBounds, pfnContinue, dwContinue));
+#endif
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheViewImpl::GetColorSet, public
+//
+// Synopsis:
+// implements IViewObject::GetColorSet
+//
+// Arguments:
+// [dwDrawAspect] -- a value from the DVASPECT_* enumeration
+// [lindex] -- indicates what piece of the object is of
+// interest; legal values vary with dwDrawAspect
+// [pvAspect] -- currently NULL
+// [ptd] -- the target device
+// [hicTargetDev] -- in information context for [ptd]
+// [ppColorSet] -- the color set required for the requested
+// rendering
+//
+// Returns:
+// OLE_E_BLANK, if no presentation object can be found
+// REVIEW, anything from IOlePresObj::Draw
+//
+// Notes:
+// Finds a presentation object in the cache that matches the
+// requested rendering, if there is one, and asks the
+// presentation object for the color set.
+//
+// History:
+// 01/12/95 - t-ScottH- added VDATETHREAD( GETPPARENT...)
+// 11/11/93 - ChrisWe - file inspection and cleanup
+// 11/30/93 - alexgo - fixed bug with GETPPARENT usage
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheViewImpl_GetColorSet)
+STDMETHODIMP NC(COleCache, CCacheViewImpl)::GetColorSet(DWORD dwDrawAspect,
+ LONG lindex, void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev, LPLOGPALETTE FAR* ppColorSet)
+{
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_View);
+
+ VDATEHEAP();
+ VDATETHREAD(pOleCache);
+
+ LPOLEPRESOBJECT lpPresObj;
+
+ M_PROLOG(pOleCache);
+
+ *ppColorSet = NULL;
+
+ if (!IsValidLINDEX(dwDrawAspect, lindex))
+ {
+ return(DV_E_LINDEX);
+ }
+
+ // Get presentation object for this aspect, lindex, ptd
+ if (!(lpPresObj = pOleCache->GetPresObjForDrawing(dwDrawAspect,
+ lindex, ptd)))
+ return ResultFromScode(OLE_E_BLANK);
+
+ return(lpPresObj->GetColorSet(pvAspect, hicTargetDev, ppColorSet));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheViewImpl, public
+//
+// Synopsis:
+// implements IViewObject::Freeze
+//
+// Arguments:
+// [dwDrawAspect] -- a value from the DVASPECT_* enumeration
+// [lindex] -- indicates what piece of the object is of
+// interest; legal values vary with dwDrawAspect
+// [pvAspect] -- currently NULL
+// [pdwFreeze] -- a token that can later be used to unfreeze
+// this aspects cached presentations
+//
+// Returns:
+// OLE_E_BLANK, if no presentation is found that matches the
+// requested characteristics
+//
+// Notes:
+// The current implementation returns the ASPECT+FREEZE_CONSTANT
+// as the FreezeID. At Unfreeze time we get the ASPECT by doing
+// FreezeID-FREEZE_CONSTANT.
+//
+// REVIEW: In future where we allow lindexes other than DEF_LINDEX,
+// we will have to use some other scheme for generating the
+// FreezeID.
+//
+// History:
+// 01/12/95 - t-ScottH- added VDATETHREAD( GETPPARENT...)
+// 11/11/93 - ChrisWe - file inspection and cleanup
+// 11/30/93 - alexgo - fixed bug with GETPPARENT
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheViewImpl_Freeze)
+STDMETHODIMP NC(COleCache,CCacheViewImpl)::Freeze(DWORD dwAspect,
+ LONG lindex, LPVOID pvAspect, DWORD FAR* pdwFreeze)
+{
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_View);
+
+ VDATEHEAP();
+ VDATETHREAD(pOleCache);
+
+ DWORD dwDummyFreeze; // point at this if !pdwFreeze to avoid retesting
+ LPCACHENODE lpCacheNode; // pointer to cache node being examined
+ DWORD dwCacheId; // id of cache node being examined
+ int iCnt; // counts number of cache nodes frozen
+
+ M_PROLOG(pOleCache);
+
+ // We need to initialize this first for error returns
+ if (!pdwFreeze)
+ {
+ // point at a dummy, so we don't always have to pre-test
+ // assignments of *pdwFreeze with "if (pdwFreeze) ..."
+ pdwFreeze = &dwDummyFreeze;
+ }
+ else
+ {
+ // initialize for error returns
+ VDATEPTROUT(pdwFreeze, DWORD);
+ *pdwFreeze = 0;
+ }
+
+ // validate parameters
+ VERIFY_ASPECT_SINGLE(dwAspect);
+
+ if (!IsValidLINDEX(dwAspect, lindex))
+ {
+ return(DV_E_LINDEX);
+ }
+
+// if (pvAspect)
+// VDATEPTRIN(pvAspect , ??????)
+
+ // nothing to do if the aspect we're interested in is already frozen
+ if (pOleCache->m_dwFrozenAspects & dwAspect)
+ {
+ *pdwFreeze = dwAspect + FREEZE_CONSTANT;
+
+ return(ResultFromScode(VIEW_S_ALREADY_FROZEN));
+ }
+
+ // start searching cache at beginning
+ dwCacheId = CACHEID_GETNEXT_GETALL;
+
+ // no cache nodes have been frozen yet
+ iCnt = 0;
+
+ // freeze each cache node that matches the aspect and lindex
+ while(lpCacheNode = pOleCache->GetNext(dwAspect, lindex, &dwCacheId))
+ {
+ lpCacheNode->Freeze(); // REVIEW, do we have to check for error
+ iCnt++;
+ }
+
+ // if we froze any cache nodes
+ if (iCnt)
+ {
+ // Add this aspect to the frozen aspects list.
+ pOleCache->m_dwFrozenAspects |= dwAspect;
+
+ // return the freeze id
+ *pdwFreeze = dwAspect + FREEZE_CONSTANT;
+
+ return(NOERROR);
+ }
+
+ // if we got here, nothing matched the requested characteristics
+ return(ResultFromScode(OLE_E_BLANK));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheViewImpl::Unfreeze, public
+//
+// Synopsis:
+// implements IViewObject::Unfreeze
+//
+// Arguments:
+// [dwFreezeId] -- the id returned by Freeze() when some aspect
+// was frozen earlier
+//
+// Returns:
+// OLE_E_NOCONNECTION, if dwFreezeId is invalid
+// S_OK
+//
+// Notes:
+// See notes for Freeze().
+//
+// History:
+// 01/12/95 - t-ScottH- added VDATETHREAD( GETPPARENT...)
+// 11/11/93 - ChrisWe - file inspection and cleanup
+// 11/30/93 - alexgo - fixed bug with GETPPARENT usage
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheViewImpl_Unfreeze)
+STDMETHODIMP NC(COleCache,CCacheViewImpl)::Unfreeze(DWORD dwFreezeId)
+{
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_View);
+
+ VDATEHEAP();
+ VDATETHREAD(pOleCache);
+
+ DWORD dwAspect; // the aspect, after recovered from the dwFreezeId
+ LPCACHENODE lpCacheNode; // pointer to cache node being examined
+ DWORD dwCacheId; // id of cache node being examined
+ LONG lindex; // the lindex for the frozen item
+
+ HRESULT error = ResultFromScode(OLE_E_NOCONNECTION);
+
+ M_PROLOG(pOleCache);
+
+ // Get Aspect and lindex from dwFreezeId
+ dwAspect = dwFreezeId - FREEZE_CONSTANT;
+ lindex = DEF_LINDEX;
+
+ // Make sure that only one bit is set and it is <= DVASPECT_DOCPRINT
+ // REVIEW, we didn't check for DVASPECT_DOCPRINT when we froze!
+ // REVIEW, does this really check for one bit?
+ // REVIEW, why not use VERIFY_ASPECT_SINGLE?
+ // REVIEW, shouldn't error be E_INVALIDARG?
+ if (!(!(dwAspect & (dwAspect-1)) && (dwAspect <= DVASPECT_DOCPRINT)))
+ return error;
+
+ // Make sure that this aspect is frozen
+ // REVIEW, shouldn't we have a better error code?
+ if (!(pOleCache->m_dwFrozenAspects & dwAspect))
+ return error;
+
+ // Need to start search from the beginning
+ dwCacheId = CACHEID_GETNEXT_GETALL;
+
+ // unfreeze all the cache nodes that match (aspect, lindex)
+ while (lpCacheNode = pOleCache->GetNext(dwAspect, lindex, &dwCacheId))
+ if (lpCacheNode->Unfreeze() == NOERROR) // REVIEW, have to check for error?
+ pOleCache->m_dwFrozenAspects &= ~dwAspect; // Remove this aspect from the
+ // frozen aspects list only if
+ // the object is unfrozen
+
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheViewImpl::SetAdvise, public
+//
+// Synopsis:
+// implements IViewObject::SetAdvise
+//
+// Arguments:
+// [aspects] -- the aspects the sink would like to be advised of
+// changes to
+// [advf] -- advise control flags from ADVF_*
+// [pAdvSink] -- the advise sink
+//
+// Returns:
+// E_INVALIDARG
+// S_OK
+//
+// Notes:
+// Only one advise sink is allowed at a time. If a second one
+// is registered, the first one is released.
+//
+// When cache nodes notify the cache that they have changed,
+// if their (aspect, lindex) match those specified here,
+// OnViewChange notification is sent to the sink.
+//
+// History:
+// 01/12/95 - t-ScottH- added VDATETHREAD( GETPPARENT...)
+// 11/11/93 - ChrisWe - file inspection and cleanup
+// 11/30/93 - alexgo - fixed bug with GETPPARENT usage
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheViewImpl_SetAdvise)
+STDMETHODIMP NC(COleCache,CCacheViewImpl)::SetAdvise(DWORD aspects,
+ DWORD advf, IAdviseSink FAR* pAdvSink)
+{
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_View);
+
+ VDATEHEAP();
+ VDATETHREAD(pOleCache);
+
+ M_PROLOG(pOleCache);
+
+ // if an advise sink is given, check it
+ if (pAdvSink != NULL)
+ VDATEIFACE(pAdvSink);
+
+ if (advf & ADVF_NODATA) // ?????
+ return ReportResult(0, E_INVALIDARG, 0, 0);
+
+ // REVIEW: should probably check agains ADVCACHE*
+
+ // We allow only one view advise at any given time, so Release the
+ // old sink.
+ if (pOleCache->m_pViewAdvSink != NULL)
+ pOleCache->m_pViewAdvSink->Release();
+
+ // Remember the new sink.
+ if ((pOleCache->m_pViewAdvSink = pAdvSink) != NULL) {
+ pAdvSink->AddRef();
+
+ // remember the control flags and requested aspect
+ pOleCache->m_advfView = advf;
+ pOleCache->m_aspectsView = aspects;
+
+ // send OnViewChange immediately if ADVF_PRIMEFIRST is done.
+ if (advf & ADVF_PRIMEFIRST)
+ pOleCache->OnChange(aspects, DEF_LINDEX,
+ FALSE /*fDirty*/);
+ }
+
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheViewImpl::GetAdvise, public
+//
+// Synopsis:
+// implement IViewObject::GetAdvise
+//
+// Arguments:
+// [pAspects] -- a pointer to where to return the aspects the
+// current advise sink is interested in
+// [pAdvf] -- a pointer to where to return the advise control
+// flags for the current advise sink
+// [ppAdvSink] -- a pointer to where to return a reference to
+// the current advise sink
+//
+// Returns:
+// S_OK
+//
+// Notes:
+//
+// History:
+// 01/12/95 - t-ScottH- added VDATETHREAD( GETPPARENT...)
+// 11/11/93 - ChrisWe - file inspection and cleanup
+// 11/30/93 - alexgo - fixed bug with GETPPARENT usage
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheViewImpl_GetAdvise)
+STDMETHODIMP NC(COleCache,CCacheViewImpl)::GetAdvise(DWORD FAR* pAspects,
+ DWORD FAR* pAdvf, IAdviseSink FAR* FAR* ppAdvSink)
+{
+ COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_View);
+
+ VDATEHEAP();
+ VDATETHREAD(pOleCache);
+
+ M_PROLOG(pOleCache);
+
+ // validate the parameters
+ if (ppAdvSink)
+ {
+ VDATEPTROUT(ppAdvSink, IAdviseSink FAR *);
+ // initialize this for error returns
+ *ppAdvSink = NULL;
+ }
+ if (pAspects)
+ VDATEPTROUT(pAspects, DWORD);
+ if (pAdvf)
+ VDATEPTROUT(pAdvf, DWORD);
+
+ if (pOleCache->m_pViewAdvSink == NULL)
+ {
+ // no view advise sink registered
+ if (pAspects)
+ *pAspects = 0;
+
+ if (pAdvf)
+ *pAdvf = 0;
+
+ // *ppAdvSink has already been initialized above
+ }
+ else
+ {
+ if (pAspects)
+ *pAspects = pOleCache->m_aspectsView;
+
+ if (pAdvf)
+ *pAdvf = pOleCache->m_advfView;
+
+ if (ppAdvSink)
+ (*ppAdvSink = pOleCache->m_pViewAdvSink)->AddRef();
+
+ }
+
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::CCacheViewImpl::GetExtent, public
+//
+// Synopsis:
+// implements IViewObject::GetExtent
+//
+// Arguments:
+// [dwDrawAspect] -- the aspect for which we'd like the extent
+// [lindex] -- the lindex for which we'd like the extent
+// [ptd] -- pointer to the target device descriptor
+// [lpsizel] -- pointer to where to return the extent
+//
+// Returns:
+// OLE_E_BLANK, if no presentation can be found that matches
+// (dwDrawAspect, lindex)
+// REVIEW, anything from IOlePresObj::GetExtent
+//
+// Notes:
+//
+// History:
+// 01/12/95 - t-ScottH- added VDATETHREAD( GETPPARENT...)
+// 11/11/93 - ChrisWe - file inspection and cleanup
+// 11/30/93 - alexgo - fixed bug with GETPPARENT usage
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_CCacheViewImpl_GetExtent)
+STDMETHODIMP NC(COleCache,CCacheViewImpl)::GetExtent(DWORD dwDrawAspect,
+ LONG lindex, DVTARGETDEVICE FAR* ptd, LPSIZEL lpsizel)
+{
+COleCache FAR *pOleCache = GETPPARENT(this, COleCache, m_View);
+HRESULT hr;
+
+ VDATEHEAP();
+ VDATETHREAD(pOleCache);
+ VDATEPTROUT(lpsizel, SIZEL);
+
+ LPOLEPRESOBJECT lpPresObj;
+
+ M_PROLOG(pOleCache);
+
+ // validate parameters
+ if (!IsValidLINDEX(dwDrawAspect, lindex))
+ {
+ return(DV_E_LINDEX);
+ }
+
+ if (ptd)
+ VDATEPTRIN(ptd, DVTARGETDEVICE);
+
+ // Get presentation object for this aspect, lindex, ptd, if there is one
+ if (!(lpPresObj = pOleCache->GetPresObjForDrawing(dwDrawAspect,
+ lindex, ptd)))
+ return ResultFromScode(OLE_E_BLANK);
+
+ hr = lpPresObj->GetExtent(dwDrawAspect, lpsizel);
+
+ // make sure Extents are positive
+ lpsizel->cx = LONG_ABS(lpsizel->cx);
+ lpsizel->cy = LONG_ABS(lpsizel->cy);
+
+ return hr;
+}
+
+
+// IPersistStorage implementation
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::GetClassID, public
+//
+// Synopsis:
+// implements IPersist::GetClassID
+//
+// Arguments:
+// [pClassID] -- pointer to where to return class id
+//
+// Returns:
+// E_NOTIMPL
+//
+// Notes:
+//
+// History:
+// 11/11/93 - ChrisWe - file inspection and cleanup;
+// set result to CLSID_NULL
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_GetClassID)
+STDMETHODIMP COleCache::GetClassID(LPCLSID pClassID)
+{
+ VDATEHEAP();
+
+ VDATEPTROUT(pClassID, LPCLSID);
+ *pClassID = m_clsid;
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::IsDirty, public
+//
+// Synopsis:
+// implements IPersistStorage::IsDirty
+//
+// Arguments:
+// none
+//
+// Returns:
+// S_FALSE, if the object does not need saving
+// S_OK otherwise
+//
+// Notes:
+//
+// History:
+// 11/11/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_IsDirty)
+STDMETHODIMP COleCache::IsDirty(void)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ return((m_uFlag & COLECACHEF_DIRTY) ?
+ NOERROR : ResultFromScode(S_FALSE));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::InitNew, public
+//
+// Synopsis:
+// implements IPersistStorage::InitNew
+//
+// Arguments:
+// [pstg] -- the temp storage the object can use until saved
+//
+// Returns:
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/11/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_InitNew)
+STDMETHODIMP COleCache::InitNew(LPSTORAGE pstg)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+ VDATEIFACE(pstg);
+
+ if (m_pStg)
+ return ResultFromScode(CO_E_ALREADYINITIALIZED);
+
+ m_uFlag |= COLECACHEF_DIRTY;
+
+ (m_pStg = pstg)->AddRef();
+
+ // initialize native cachenode, if that's meaningful
+ FindObjectFormat(pstg);
+
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::Load, public
+//
+// Synopsis:
+// implements IPersistStorage::Load
+//
+// Arguments:
+// [pstg] -- the storage to load from
+//
+// Returns:
+// REVIEW, various Storage errors
+// S_OK
+//
+// Notes:
+// Presentations are loaded from sequentially numbered
+// streams, stopping at the first one that cannot be found.
+//
+// History:
+// 11/11/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_Load)
+STDMETHODIMP COleCache::Load(LPSTORAGE pstg)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ A5_PROLOG(this);
+ HRESULT error; // error status so far
+ LPSTREAM lpstream; // stream we're loading a presentation from
+ LPCACHENODE lpCacheNode; // cache node we're loading
+ int iPresStreamNum; // counts through the presentation streams
+ OLECHAR szName[
+ sizeof(OLE_PRESENTATION_STREAM)/sizeof(OLECHAR)];
+ // used to construct the names of presentation streams
+
+ VDATEIFACE(pstg);
+
+ // REVIEW(davepl) Does this error code really make any sense here?
+
+ if (m_pStg)
+ return ResultFromScode(CO_E_ALREADYINITIALIZED);
+
+ // remember the storage; we'll AddRef this later, if load is successful
+ m_pStg = pstg;
+
+ CLSID clsid;
+
+ error = ReadClassStg(pstg, &clsid);
+
+ if ( SUCCEEDED(error) &&
+ IsEqualCLSID(clsid, CLSID_PBrush))
+ {
+ m_uFlag |= COLECACHEF_PBRUSHORMSDRAW | COLECACHEF_FORMATKNOWN;
+ m_fUsedToBePBrush = TRUE;
+ }
+
+
+ // initialize native cachenode, if that's meaningful
+ FindObjectFormat(pstg);
+
+ if (m_uFlag & COLECACHEF_STATIC)
+ {
+ UINT uiStatus;
+
+ // if static object is in old format (i.e. data was written
+ // into the OLE_PRESENTATION_STREAM rather than the CONTENTS
+ // stream), then convert it to new format.
+ error = UtOlePresStmToContentsStm(pstg,
+ OLE_PRESENTATION_STREAM, TRUE, &uiStatus);
+
+ if (error != NOERROR)
+ {
+
+ // if CONTENTS stream doesn't exist or we are not able
+ // to create it, then we have a problem.
+
+ if (uiStatus & CONVERT_NODESTINATION)
+ goto errRtn;
+
+ // By now we know that CONTENTS stream exists.
+ // REVIEW, seems to me there could be other errors!
+ error = NOERROR;
+ }
+
+ // We know that the data is in the CONTENTS stream. Now let's
+ // make sure that it is in the proper format.
+ lpCacheNode = UpdateCacheNodeForNative();
+ if (lpCacheNode == NULL)
+ {
+ error = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+
+ }
+ else if ((lpCacheNode->GetPresObj())->IsBlank())
+ {
+ // Even though CONTENTS stream existed, we are not
+ // able to read data from it. The stream format is
+ // invalid.
+ AssertSz(FALSE, "Format of CONTENTS stream is invalid");
+ error = ResultFromScode(DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+
+ }
+ else if (m_uFlag & COLECACHEF_FORMATKNOWN)
+ {
+ UpdateCacheNodeForNative();
+ }
+
+ // prepare to construct presentation stream names in szName
+ _xstrcpy(szName, OLE_PRESENTATION_STREAM);
+
+ // Enumerate the presentation streams and load them one after another.
+ // The enumeration stops the first time the attempt to open
+ // stream fails.
+ for(iPresStreamNum = 0; iPresStreamNum < OLE_MAX_PRES_STREAMS;)
+ {
+
+ if (error = pstg->OpenStream(szName, NULL,
+ (STGM_READ | STGM_SHARE_EXCLUSIVE), 0,
+ &lpstream))
+ {
+ // Translate stream does not exist into ok. This
+ // means that we don't have any more streams to read.
+ if (GetScode(error) == STG_E_FILENOTFOUND)
+ error = NOERROR;
+
+ goto errRtn;
+ }
+
+ // We've opened the stream. Now create a cachenode, so that
+ // we can ask it to load itself from the stream.
+ if (!(lpCacheNode = new FAR CCacheNode(this)))
+ {
+ error = ReportResult (0, E_OUTOFMEMORY, 0, 0);
+ goto errLoad;
+ }
+
+ // ask the cachenode to load itself from the stream
+ if (error = lpCacheNode->Load(lpstream, iPresStreamNum))
+ goto errLoad;
+
+ // add the cache node to the cache list
+ if (!Attach(lpCacheNode))
+ {
+ error = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ goto errLoad;
+ }
+
+ // release the stream
+ lpstream->Release();
+ lpstream = NULL;
+
+ // if the server object is runinng, ask the loaded cached
+ // node to connect to the server object
+ if (m_pDataObject)
+ lpCacheNode->OnRun(m_pDataObject);
+
+ // Get the next presentation stream name.
+
+ UtGetPresStreamName(szName, ++iPresStreamNum);
+ continue;
+
+ errLoad:
+ // something went wrong while loading the current stream
+ if (lpstream)
+ lpstream->Release();
+ if (lpCacheNode)
+ lpCacheNode->Delete();
+ break;
+ }
+
+
+errRtn:
+ if (error != NOERROR)
+ {
+ // delete all the cache nodes that we loaded so far.
+ DeleteAll();
+ m_pStg = NULL;
+ }
+ else
+ {
+ // cache is not dirty
+ m_uFlag &= ~COLECACHEF_DIRTY;
+
+ // remember storage we loaded from
+ m_pStg->AddRef();
+
+ // if static object remove all the caches (if there
+ // are any) except the ICON cache.
+ if (m_uFlag & COLECACHEF_STATIC)
+ {
+ DWORD dwCacheId = CACHEID_GETNEXT_GETALLBUTNATIVE;
+ // REVIEW -- GETNEXT_GETALL
+ // REVIEW, if COLECACHEF_STATIC, there doesn't
+ // appear to be a native cache node, but I
+ // don't understand why
+ const FORMATETC FAR *lpforetc;
+
+ while (lpCacheNode = GetNext(&dwCacheId))
+ {
+ lpforetc = lpCacheNode->GetFormatEtc();
+ if (lpforetc->dwAspect != DVASPECT_ICON)
+ Uncache(dwCacheId);
+ }
+ }
+ }
+
+ RESTORE_A5();
+ return error;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::Save, public
+//
+// Synopsis:
+// implements IPersistStorage::Save
+//
+// Arguments:
+// [pstgSave] -- the storage to use to save this
+// [fSameAsLoad] -- is this the same storage we loaded from?
+//
+// Returns:
+//
+// Notes:
+// All the caches are saved to streams with sequential numeric
+// names. Load takes advantage of this to load until it
+// can't find the next file.
+//
+// History:
+// 11/11/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+// $$$
+// Save all the caches to presentation streams numbered sequentially
+
+#pragma SEG(COleCache_Save)
+STDMETHODIMP COleCache::Save(LPSTORAGE pstgSave, BOOL fSameAsLoad)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ A5_PROLOG(this);
+ HRESULT error = NOERROR; // error status so far
+ int iPresStreamNum; // the stream number to use to save
+ LPCACHENODE lpCacheNode; // the cache node being saved
+ DWORD dwCacheId; // cache id of the cache being saved
+ int cntCachesNotSaved;
+
+ // validate parameters
+ VDATEIFACE(pstgSave);
+
+ // if we're saving to the same place this was loaded from, and
+ // the cache isn't dirty, there's no need to rewrite everything out
+ if (fSameAsLoad && !(m_uFlag & COLECACHEF_DIRTY))
+ {
+ error = NOERROR;
+ goto errRtn;
+ }
+
+ // Enumerate the cache nodes and ask them to save themselves into
+ // presentation streams.
+ // REVIEW, what is this extra pass before hand about? It just
+ // seems to count the items to save, and do nothing more. I asked
+ // SriniK, and he couldn't give me an answer after looking at it.
+ // He's promised to add some more comments to the code after he's
+ // looked at it some more.
+ dwCacheId = CACHEID_GETNEXT_GETALLBUTNATIVE; // REVIEW GETNEXT_GETALL???
+ iPresStreamNum = 0;
+ cntCachesNotSaved = 0;
+ while (lpCacheNode = GetNext(&dwCacheId))
+ {
+ // Ask the cache node to save itself into this stream
+ error = lpCacheNode->Save(pstgSave, fSameAsLoad,
+ iPresStreamNum, (dwCacheId == m_dwDrawCacheId),
+ TRUE /* save if you have saved before */,
+ &cntCachesNotSaved);
+
+ if ((error != NOERROR) ||
+ (++iPresStreamNum >= OLE_MAX_PRES_STREAMS))
+ break;
+ }
+
+ if (fSameAsLoad && (cntCachesNotSaved != 0) && (error == NOERROR))
+ {
+ dwCacheId = CACHEID_GETNEXT_GETALLBUTNATIVE;
+ iPresStreamNum = 0;
+
+ while (lpCacheNode = GetNext(&dwCacheId))
+ {
+ // Ask the cache node to save itself into this stream
+ error = lpCacheNode->Save(pstgSave, fSameAsLoad,
+ iPresStreamNum,
+ (dwCacheId == m_dwDrawCacheId),
+ FALSE /* save if haven't before */,
+ NULL);
+
+ if ((error != NOERROR) ||
+ (++iPresStreamNum >=
+ OLE_MAX_PRES_STREAMS))
+ break;
+ }
+ }
+
+ // remove additional presentation streams if any exist
+ UtRemoveExtraOlePresStreams(pstgSave, iPresStreamNum);
+
+errRtn:
+ if (error == NOERROR)
+ {
+ m_uFlag |= COLECACHEF_NOSCRIBBLEMODE;
+ if (fSameAsLoad)
+ m_uFlag |= COLECACHEF_SAMEASLOAD;
+ else
+ m_uFlag &= ~COLECACHEF_SAMEASLOAD;
+ }
+
+ RESTORE_A5();
+ return error;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::SaveCompleted, public
+//
+// Synopsis:
+// implements IPersistStorage::SaveCompleted
+//
+// Arguments:
+// [pstgNew] -- NULL, or a pointer to the storage that the current
+// storage operations are being done to, when this is
+// not the same as the storage this object was loaded
+// from (pointer to a "Save as..." destination.)
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_SaveCompleted)
+STDMETHODIMP COleCache::SaveCompleted(LPSTORAGE pstgNew)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ M_PROLOG(this);
+ return wSaveCompleted(pstgNew, FALSE /*fDiscardDrawCacheAlso*/);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::wSaveCompleted, private
+//
+// Synopsis:
+// Does work of IPersistStorage::wSaveCompleted, making a new
+// storage the current one, and clearing the dirty flags on
+// the cache nodes and cache if a save was done to the original
+// storage the cache was loaded from.
+//
+// Arguments:
+// [pstgNew] -- pointer to storage saving was done to, if it
+// wasn't done to the original source location.
+//
+// Returns:
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+INTERNAL COleCache::wSaveCompleted(LPSTORAGE pstgNew,
+ BOOL fDiscardDrawCacheAlso)
+{
+ VDATEHEAP();
+
+ if ((m_uFlag & COLECACHEF_SAMEASLOAD) || pstgNew)
+ {
+ m_uFlag &= ~COLECACHEF_SAMEASLOAD;
+
+ // if new storage, make this the current storage
+ // REVIEW, this means that DiscardCache() would save to this
+ // storage, rather than the original
+ if (pstgNew)
+ {
+ if (m_pStg)
+ m_pStg->Release();
+
+ (m_pStg = pstgNew)->AddRef();
+ }
+
+ if (m_uFlag & COLECACHEF_NOSCRIBBLEMODE)
+ {
+ DWORD dwCacheId;
+ LPCACHENODE lpCacheNode;
+ int iStreamNum;
+
+ // Do special handling for PaintBrush or MSDraw objects.
+ if (m_uFlag & COLECACHEF_PBRUSHORMSDRAW)
+ UpdateCacheNodeForNative();
+
+ // clear the dirty flags of all the cache nodes
+ for(iStreamNum = 0, dwCacheId =
+ CACHEID_GETNEXT_GETALLBUTNATIVE;
+ lpCacheNode = GetNext(&dwCacheId);
+ ++iStreamNum)
+ {
+ lpCacheNode->SaveCompleted(iStreamNum,
+ (!fDiscardDrawCacheAlso &&
+ (dwCacheId ==
+ m_dwDrawCacheId)));
+ }
+
+ m_uFlag &= ~COLECACHEF_DIRTY;
+ }
+ }
+
+ m_uFlag &= ~COLECACHEF_NOSCRIBBLEMODE;
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::HandsOffStorage, public
+//
+// Synopsis:
+// implements IPersistStorage::HandsOffStorage
+//
+// Arguments:
+// none
+//
+// Returns:
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(COleCache_HandsOffStorage)
+STDMETHODIMP COleCache::HandsOffStorage(void)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ M_PROLOG(this);
+
+ // if we're holding onto storage, release it
+ if (m_pStg)
+ {
+ m_pStg->Release();
+ m_pStg = NULL;
+ }
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: COleCache::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppsz] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 31-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT COleCache::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ unsigned int ui;
+ char *pszPrefix;
+ char *pszCThreadCheck;
+ char *pszCacheListItem;
+ char *pszCCacheEnum;
+ char *pszADVF;
+ char *pszDVASPECT;
+ char *pszCLSID;
+ char *pszClipFormat;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(3900);
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ pszCThreadCheck = DumpCThreadCheck((CThreadCheck *)this, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CThreadCheck:" << endl;
+ dstrDump << pszCThreadCheck;
+ CoTaskMemFree(pszCThreadCheck);
+
+ // these are not included since they are just vtables (also, we would
+ // not get the correct values in the debugger extension for the addresses)
+ // dstrDump << pszPrefix << "&IUnknown = " << &m_UnkPrivate << endl;
+ // dstrDump << pszPrefix << "&IDataObject = " << &m_Data << endl;
+ // dstrDump << pszPrefix << "&IViewObject2 = " << &m_View << endl;
+
+ dstrDump << pszPrefix << "No. of References = " << m_refs << endl;
+
+ dstrDump << pszPrefix << "pIUnknown, pUnkOuter = ";
+ if (m_uFlag & COLECACHEF_AGGREGATED)
+ {
+ dstrDump << "AGGREGATED (" << m_pUnkOuter << ")" << endl;
+ }
+ else
+ {
+ dstrDump << "NO AGGREGATION (" << m_pUnkOuter << ")" << endl;
+ }
+
+ dstrDump << pszPrefix << "pIStorage = " << m_pStg << endl;
+
+ dstrDump << pszPrefix << "COleCache Flags = ";
+ if (m_uFlag & COLECACHEF_DIRTY)
+ {
+ dstrDump << "COLECACHEF_DIRTY ";
+ }
+ if (m_uFlag & COLECACHEF_NOSCRIBBLEMODE)
+ {
+ dstrDump << "COLECACHEF_NOSCRIBBLEMODE ";
+ }
+ if (m_uFlag & COLECACHEF_SAMEASLOAD)
+ {
+ dstrDump << "COLECACHEF_SAMEASLOAD ";
+ }
+ if (m_uFlag & COLECACHEF_PBRUSHORMSDRAW)
+ {
+ dstrDump << "COLECACHEF_PBRUSHORMSDRAW ";
+ }
+ if (m_uFlag & COLECACHEF_STATIC)
+ {
+ dstrDump << "COLECACHEF_STATIC ";
+ }
+ if (m_uFlag & COLECACHEF_FORMATKNOWN)
+ {
+ dstrDump << "COLECACHEF_FORMATKNOWN ";
+ }
+ if (m_uFlag & COLECACHEF_AGGREGATED)
+ {
+ dstrDump << "COLECACHEF_AGGREGATED ";
+ }
+ // if none of the flags are set!
+ if ( !( (m_uFlag & COLECACHEF_DIRTY) |
+ (m_uFlag & COLECACHEF_NOSCRIBBLEMODE) |
+ (m_uFlag & COLECACHEF_SAMEASLOAD) |
+ (m_uFlag & COLECACHEF_PBRUSHORMSDRAW) |
+ (m_uFlag & COLECACHEF_STATIC) |
+ (m_uFlag & COLECACHEF_FORMATKNOWN) |
+ (m_uFlag & COLECACHEF_AGGREGATED)))
+ {
+ dstrDump << "No FLAGS SET! ";
+ }
+ dstrDump << "(" << (void *)m_uFlag << ")" << endl;
+
+ dstrDump << pszPrefix << "Size of CacheList(max) = " << m_uCacheNodeMax << endl;
+
+ dstrDump << pszPrefix << "No. of elements in CacheList = " << m_uCacheNodeCnt << endl;
+
+ // the array could be sparse
+ if (m_uCacheNodeCnt != 0)
+ {
+ for (ui = 0; ui < m_uCacheNodeMax; ui++)
+ {
+ pszCacheListItem = DumpCACHELIST_ITEM(&m_pCacheList[ui], ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CacheList Item [" << ui << "]:" << endl;
+ dstrDump << pszCacheListItem;
+ CoTaskMemFree(pszCacheListItem);
+ }
+ }
+
+ if (m_pCacheEnum != NULL)
+ {
+ dstrDump << pszPrefix << "CCacheEnum:" << endl;
+ pszCCacheEnum = DumpCCacheEnum(m_pCacheEnum, ulFlag, nIndentLevel + 1);
+ dstrDump << pszCCacheEnum;
+ CoTaskMemFree(pszCCacheEnum);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "CCacheEnum: = " << m_pCacheEnum << endl;
+ }
+
+ dstrDump << pszPrefix << "pIAdviseSink (View advise) = " << m_pViewAdvSink << endl;
+
+ pszADVF = DumpADVFFlags(m_advfView);
+ dstrDump << pszPrefix << "View Advise Flags = " << pszADVF << endl;
+ CoTaskMemFree(pszADVF);
+
+ pszDVASPECT = DumpDVASPECTFlags(m_aspectsView);
+ dstrDump << pszPrefix << "Aspect Flags = " << pszDVASPECT << endl;
+ CoTaskMemFree(pszDVASPECT);
+
+ dstrDump << pszPrefix << "Drawing Cache ID = " << m_dwDrawCacheId << endl;
+
+ dstrDump << pszPrefix << "Count of Frozen Aspects = " << m_dwFrozenAspects<< endl;
+
+ dstrDump << pszPrefix << "pIDataObject = " << m_pDataObject << endl;
+
+ pszCLSID = DumpCLSID(m_clsid);
+ dstrDump << pszPrefix << "CLSID = " << pszCLSID << endl;
+ CoTaskMemFree(pszCLSID);
+
+ pszClipFormat = DumpCLIPFORMAT(m_cfFormat);
+ dstrDump << pszPrefix << "Clipboard Format = " << pszClipFormat << endl;
+ CoTaskMemFree(pszClipFormat);
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCOleCache, public (_DEBUG only)
+//
+// Synopsis: calls the COleCache::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pOC] - pointer to COleCache
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 31-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCOleCache(COleCache *pOC, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pOC == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pOC->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+// CCacheEnumFormatEtc implementation
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnumFormatEtc::CCacheEnumFormatEtc, public
+//
+// Synopsis:
+// constructor
+//
+// sets reference count to 1
+//
+// Arguments:
+// [pIES] -- IEnumSTATDATA enumerator that this IEnumFORMATETC
+// enumerator will be based on; may be NULL
+//
+// Notes:
+// We allow the underlying IEnumSTATDATA enumerator to be null
+// for the case where an IEnumSTATDATA enumerator refuses to
+// be cloned, and yet we want to clone this IEnumFORMATETC.
+// When the underlying enumerator is NULL, we always return
+// OLE_E_BLANK, and treat this enumerator as empty; taking the
+// cache's IEnumSTATDATA as an example worthy of copying.
+//
+// History:
+// 02/08/94 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CCacheEnumFormatEtc_ctor)
+CCacheEnumFormatEtc::CCacheEnumFormatEtc(IEnumSTATDATA FAR *pIES)
+{
+ VDATEHEAP();
+
+ m_refs = 1;
+ if (m_pIES = pIES)
+ pIES->AddRef();
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnumFormatEtc::~CCacheEnumFormatEtc, private
+//
+// Synopsis:
+// destructor
+//
+// dissociates this enumerator from the cache, if it still exists
+//
+// Notes:
+//
+// History:
+// 02/08/94 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+CCacheEnumFormatEtc::~CCacheEnumFormatEtc()
+{
+ VDATEHEAP();
+
+ if (m_pIES)
+ m_pIES->Release();
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnumFormatEtc::QueryInterface, public
+//
+// Synopsis:
+// implements IUnknown::QueryInterface
+//
+// Arguments:
+// [iid] -- IID of the desired interface
+// [ppv] -- pointer to where to return the requested interface
+//
+// Returns:
+// E_NOINTERFACE, if the requested interface is not available
+// S_OK
+//
+// Notes:
+//
+// History:
+// 02/08/94 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CCacheEnumFormatEtc_QueryInterface)
+STDMETHODIMP CCacheEnumFormatEtc::QueryInterface(REFIID riid, LPVOID FAR* ppv)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ if (IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IEnumFORMATETC))
+ *ppv = (void FAR *)(IEnumFORMATETC FAR *)this;
+ else
+ {
+ *ppv = NULL;
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+
+ AddRef();
+ return(NOERROR);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnumFormatEtc::AddRef, public
+//
+// Synopsis:
+// implements IUnknown::AddRef
+//
+// Arguments:
+// none
+//
+// Returns:
+// the object's reference count
+//
+// Notes:
+//
+// History:
+// 02/08/94 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CCacheEnumFormatEtc_AddRef)
+STDMETHODIMP_(ULONG) CCacheEnumFormatEtc::AddRef(void)
+{
+ VDATEHEAP();
+
+ return m_refs++;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnumFormatEtc::Release, public
+//
+// Synopsis:
+// implements IUnknown::Release
+//
+// Arguments:
+// none
+//
+// Returns:
+// the object's reference count
+//
+// Notes:
+//
+// History:
+// 02/08/94 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CCacheEnumFormatEtc_Release)
+STDMETHODIMP_(ULONG) CCacheEnumFormatEtc::Release(void)
+{
+ VDATEHEAP();
+
+ if (--m_refs == 0)
+ {
+ delete this;
+ return(0);
+ }
+
+ return m_refs;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnumFormatEtc::Next, public
+//
+// Synopsis:
+// implements IEnumFORMATETC::Next
+//
+// Arguments:
+// [celt] -- the number of items the caller would like returned
+// [rgelt] -- a pointer to where the items may be returned as
+// an array
+// [pceltFetched] -- a pointer to where to place the count of
+// the actual number of items returned. May be NULL
+// if the caller is not interested in this number
+//
+// Returns:
+// S_OK, if exactly the number of items requested is being
+// returned
+// S_FALSE, if fewer items than the number requested are being
+// returned
+// OLE_E_BLANK, if the ole cache associated with this
+// enumerator has been destroyed
+//
+// Notes:
+//
+// History:
+// 02/08/94 - ChrisWe - created
+// 08/23/94 - Davepl - enforced enumerator count OUT param
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CCacheEnumFormatEtc_Next)
+STDMETHODIMP CCacheEnumFormatEtc::Next(ULONG celt, FORMATETC FAR* rgelt,
+ ULONG FAR* pceltFetched)
+{
+ STATDATA sd; // used as intermediary for other enumerator
+ ULONG cnt; // count of number of elements fetched so far
+ ULONG fc; // FetchCount
+ HRESULT hr;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+ VDATEPTROUT(rgelt, FORMATETC);
+
+ // Enumerators require that when more than one element is being fetched,
+ // a valid OUT ulong is provided to indicate the count of elts returned
+ // 16-bit didn't enforce this, so we InWow-special-case it.
+
+ if (!IsWOWThread())
+ {
+ if ( celt > 1 && NULL == pceltFetched)
+ {
+ return E_INVALIDARG;
+ }
+ }
+
+ // if no other enumerator, can't comply
+ if (!m_pIES)
+ return(ReportResult(0, OLE_E_BLANK, 0, 0)); // REVIEW, scode
+
+ // iterate until we've fetched as many items as requested
+ for(cnt = 0; cnt < celt; ++rgelt, ++cnt)
+ {
+ hr = m_pIES->Next(1, &sd, &fc);
+
+ if (fc != 1)
+ break;
+
+ // copy the relevant information
+ *rgelt = sd.formatetc;
+ Assert(rgelt->ptd == NULL);
+
+ // release the advise sink in the STATDATA
+ if (sd.pAdvSink)
+ sd.pAdvSink->Release();
+ // REVIEW, as this is done here, we are using the IEnumSTATDATA
+ // enumerator to implement this one. The IES enumerator does
+ // more work than this one, namely this AddRef'ing of the
+ // advise sink, which might actually be remoted. We're doing
+ // this this way because that one already exists, and we're
+ // trying to disturb the code as little as possible. A
+ // performance optimization that can be done later on is to
+ // switch the code between the two enumerators, (or to factor
+ // out the guts of the IES one,) so that we don't do the
+ // extra work for this one, but only for the IES one when it
+ // is necessary.
+ }
+
+ // if a count of returned elements was requested, copy it
+ if (pceltFetched)
+ *pceltFetched = cnt;
+
+ // if we fetched as many items as requested, return
+ if (cnt == celt)
+ return NOERROR;
+
+ // zero out the unused array elements
+ for(; cnt < celt; ++rgelt, ++cnt)
+ {
+ rgelt->cfFormat = 0;
+ }
+
+ return(ReportResult(0, S_FALSE, 0, 0));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::Skip, public
+//
+// Synopsis:
+// implements IEnumFORMATETC::Skip
+//
+// Arguments:
+// [celt] -- count of the number of items in the enumeration to
+// skip over
+//
+// Returns:
+// OLE_E_BLANK, if the associated ole cache has been destroyed
+// S_FALSE, if there were fewer items left in the enumeration
+// than we were to skip
+// S_OK
+//
+// Notes:
+//
+// History:
+// 02/08/94 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CCacheEnumFormatEtc_Skip)
+STDMETHODIMP CCacheEnumFormatEtc::Skip(ULONG celt)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ // if no other enumerator, can't comply
+ if (!m_pIES)
+ return(ReportResult(0, OLE_E_BLANK, 0, 0)); // REVIEW, scode
+
+ return(m_pIES->Skip(celt));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnumFormatEtc::Reset, public
+//
+// Synopsis:
+// implements IEnumFORMATETC::Reset
+//
+// Arguments:
+// none
+//
+// Returns:
+// OLE_E_BLANK, if the associated ole cache has been destroyed
+// S_OK
+//
+// Notes:
+//
+// History:
+// 02/08/94 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CCacheEnumFormatEtc_Reset)
+STDMETHODIMP CCacheEnumFormatEtc::Reset(void)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ // if no other enumerator, can't comply
+ if (!m_pIES)
+ return(ReportResult(0, OLE_E_BLANK, 0, 0)); // REVIEW, scode
+
+ return(m_pIES->Reset());
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnumFormatEtc::Clone, public
+//
+// Synopsis:
+// implements IEnumFORMATETC::Clone
+//
+// Arguments:
+// [ppenum] -- pointer to where to return the created enumerator
+//
+// Returns:
+// OLE_E_BLANK, if the associated cache has been destroyed;
+// no enumerator is created in this case
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 02/08/94 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CCacheEnumFormatEtc_Clone)
+STDMETHODIMP CCacheEnumFormatEtc::Clone(LPENUMFORMATETC FAR* ppenum)
+{
+ IEnumSTATDATA FAR *pIES; // the IEnumSTATDATA to base the clone on
+ HRESULT hr;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ // obtain an IEnumSTATDATA to base the cloned IEnumFORMATETC on
+ if (!m_pIES)
+ pIES = NULL;
+ else
+ hr = m_pIES->Clone(&pIES);
+
+ // create the new IEnumFORMATETC
+ *ppenum = new CCacheEnumFormatEtc(pIES);
+
+ // release the IEnumSTATDATA, if we've got one
+ if (pIES)
+ pIES->Release();
+
+ // if no new enumerator, we ran out of memory
+ if (!*ppenum)
+ return(ReportResult(0, E_OUTOFMEMORY, 0, 0));
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCacheEnumFormatEtc::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppsz] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 31-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CCacheEnumFormatEtc::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszCThreadCheck;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump;
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ pszCThreadCheck = DumpCThreadCheck((CThreadCheck *)this, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CThreadCheck:" << endl;
+ dstrDump << pszCThreadCheck;
+ CoTaskMemFree(pszCThreadCheck);
+
+ dstrDump << pszPrefix << "No. of References = " << m_refs << endl;
+
+ dstrDump << pszPrefix << "pIEnumSTATDATA = " << m_pIES << endl;
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCCacheEnumFormatEtc, public (_DEBUG only)
+//
+// Synopsis: calls the CCacheEnumFormatEtc::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pCEFE] - pointer to CCacheEnumFormatEtc
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 31-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCCacheEnumFormatEtc(CCacheEnumFormatEtc *pCEFE, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pCEFE == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pCEFE->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+// CCacheEnum implementation
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnum::CCacheEnum, public
+//
+// Synopsis:
+// constructor
+//
+// sets reference count to 1
+//
+// Arguments:
+// [pOleCache] -- the instance of COleCache this is an
+// enumerator for; may be NULL
+// [dwCurrent] -- id of the item in the cache that the enumerator
+// is on
+// [fDib] -- act as if the last item seen is a CF_DIB cache item
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheEnum_ctor)
+CCacheEnum::CCacheEnum(COleCache FAR* pOleCache, ULONG ulCurrent, BOOL fDib)
+{
+ VDATEHEAP();
+
+ m_ulCurCacheId = ulCurrent;
+ m_refs = 1;
+ m_pOleCache = pOleCache; // remember the COleCache object pointer
+ // NOTE: no ref count
+ m_pNextCacheEnum = NULL;
+ m_fDib = fDib;
+
+ // if there's a cache, add this enumerator to the head of the
+ // enumerator list
+ if (pOleCache)
+ {
+ m_pNextCacheEnum = pOleCache->m_pCacheEnum;
+ pOleCache->m_pCacheEnum = this;
+ }
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnum::~CCacheEnum, private
+//
+// Synopsis:
+// destructor
+//
+// dissociates this enumerator from the cache, if it still exists
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+CCacheEnum::~CCacheEnum()
+{
+ VDATEHEAP();
+
+ // If there's a cache, ask it to remove us from its enumerator list
+ if (m_pOleCache)
+ m_pOleCache->DetachCacheEnum(this);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnum::OnOleCacheDelete, private
+//
+// Synopsis:
+// Indicates that the cache the enumerator was associated
+// with has been destroyed. The enumerator no longer returns
+// anything but error values.
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheEnum_OnOleCacheDelete)
+// COleCache calls this when it is getting deleted
+INTERNAL_(void) CCacheEnum::OnOleCacheDelete(void)
+{
+ VDATEHEAP();
+
+ m_pOleCache = NULL; // NOTE: no ref count
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnum::QueryInterface, public
+//
+// Synopsis:
+// implements IUnknown::QueryInterface
+//
+// Arguments:
+// [iid] -- IID of the desired interface
+// [ppv] -- pointer to where to return the requested interface
+//
+// Returns:
+// E_NOINTERFACE, if the requested interface is not available
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheEnum_QueryInterface)
+STDMETHODIMP CCacheEnum::QueryInterface(REFIID riid, LPVOID FAR* ppv)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ if (IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IEnumSTATDATA))
+ *ppv = (void FAR *)(IEnumSTATDATA FAR *)this;
+ else
+ {
+ *ppv = NULL;
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+
+ AddRef();
+ return(NOERROR);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnum::AddRef, public
+//
+// Synopsis:
+// implements IUnknown::AddRef
+//
+// Arguments:
+// none
+//
+// Returns:
+// the object's reference count
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheEnum_AddRef)
+STDMETHODIMP_(ULONG) CCacheEnum::AddRef()
+{
+ VDATEHEAP();
+
+ return m_refs++;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnum::Release, public
+//
+// Synopsis:
+// implements IUnknown::Release
+//
+// Arguments:
+// none
+//
+// Returns:
+// the object's reference count
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheEnum_Release)
+STDMETHODIMP_(ULONG) CCacheEnum::Release()
+{
+ VDATEHEAP();
+
+ if (--m_refs == 0)
+ {
+ delete this;
+ return(0);
+ }
+
+ return m_refs;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnum::Next, public
+//
+// Synopsis:
+// implements IEnumSTATDATA::Next
+//
+// Arguments:
+// [celt] -- the number of items the caller would like returned
+// [rgelt] -- a pointer to where the items may be returned as
+// an array
+// [pceltFetched] -- a pointer to where to place the count of
+// the actual number of items returned. May be NULL
+// if the caller is not interested in this number
+//
+// Returns:
+// S_OK, if exactly the number of items requested is being
+// returned
+// S_FALSE, if fewer items than the number requested are being
+// returned
+// OLE_E_BLANK, if the ole cache associated with this
+// enumerator has been destroyed
+//
+// Notes:
+// Immediately after any CF_DIB item is returned, a CF_BITMAP
+// item is synthesized for the same cache item, and returned next.
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup; use pointer
+// aritmetic to speed array accesses
+// 08/08/94 AlexT Handle case where cache node is uncached
+// during enumeration
+// 08/23/94 - Davepl - enforced enumerator count OUT param
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheEnum_Next)
+STDMETHODIMP CCacheEnum::Next(ULONG celt, STATDATA FAR* rgelt,
+ ULONG FAR* pceltFetched)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ // Enumerators require that when more than one element is being fetched,
+ // a valid OUT ulong is provided to indicate the count of elts returned
+ // 16-bit didn't enforce this, so we InWow-special-case it.
+
+ if (celt > 1 && NULL == pceltFetched && !IsWOWThread())
+ {
+ return E_INVALIDARG;
+ }
+
+ ULONG cnt; // count of number of elements fetched so far
+ LPCACHENODE lpCacheNode; // pointer to the current cache node
+
+ // if no cache, can't run enumerator
+ if (!m_pOleCache)
+ return ReportResult (0, OLE_E_BLANK, 0, 0); // REVIEW, scode
+
+ // iterate until we've fetched as many items as requested
+ cnt = 0;
+ while (cnt < celt)
+ {
+ if (!m_fDib)
+ {
+ // If we're here, the last returned item was NOT
+ // CF_DIB
+
+ // Get next valid cache node from cache node list
+ lpCacheNode = m_pOleCache->GetNext(&m_ulCurCacheId);
+ if (NULL == lpCacheNode)
+ {
+ // No more nodes to process
+ break;
+ }
+
+ // Ask the CacheNode itself for the statdata.
+ lpCacheNode->CopyStatData(rgelt);
+
+ // if this item is of format CF_DIB, then on the
+ // next iteration, return a synthesized CF_BITMAP for
+ // the same item
+ if (CF_DIB == rgelt->formatetc.cfFormat)
+ {
+ m_fDib = TRUE;
+ }
+ }
+ else
+ {
+ // The last item returned was a CF_DIB
+ // now we synthesize a CF_BITMAP item for the same
+ // cache item
+
+ m_fDib = FALSE;
+
+ // get the *current* cache node
+ lpCacheNode = m_pOleCache->GetAt(m_ulCurCacheId);
+
+ if (NULL == lpCacheNode ||
+ CF_DIB != lpCacheNode->GetFormatEtc()->cfFormat)
+ {
+ // The node no longer exists (or is the wrong
+ // type) - caller probably called Uncache, so
+ // we'll just get the next node
+ continue;
+ }
+
+ // Ask the CacheNode for the statdata.
+ lpCacheNode->CopyStatData(rgelt);
+ rgelt->formatetc.cfFormat = CF_BITMAP;
+ rgelt->formatetc.tymed = TYMED_GDI;
+ }
+
+ // return the connection id
+ rgelt->dwConnection = m_ulCurCacheId;
+
+ cnt++;
+ rgelt++;
+ }
+
+ // if a count of returned elements was requested, copy it
+ if (pceltFetched)
+ *pceltFetched = cnt;
+
+ // if we fetched as many items as requested, return
+ if (cnt == celt)
+ return NOERROR;
+
+ // zero out the unused array elements
+ for(; cnt < celt; ++rgelt, ++cnt)
+ {
+ rgelt->dwConnection = 0;
+ rgelt->pAdvSink = NULL;
+ }
+
+ return ReportResult(0, S_FALSE, 0, 0);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// COleCache::Skip, public
+//
+// Synopsis:
+// implements IEnumSTATDATA::Skip
+//
+// Arguments:
+// [celt] -- count of the number of items in the enumeration to
+// skip over
+//
+// Returns:
+// OLE_E_BLANK, if the associated ole cache has been destroyed
+// S_FALSE, if there were fewer items left in the enumeration
+// than we were to skip
+// S_OK
+//
+// Notes:
+// REVIEW, Skipped would-have-been-synthesized CF_BITMAP items
+// are not counted towards the skip count
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup;
+// fixed error return for case where there are fewer items
+// in the enumeration than we are to skip
+// 08/08/94 AlexT Synchronize with ::Next implementation
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheEnum_Skip)
+STDMETHODIMP CCacheEnum::Skip(ULONG celt)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LPCACHENODE lpCacheNode; // pointer to the current cache node
+
+ // if there's no cache, there's nothing we can do
+ if (!m_pOleCache)
+ return ReportResult (0, OLE_E_BLANK, 0, 0);
+
+ for (NULL; celt > 0; celt--)
+ {
+ if (m_fDib)
+ {
+ // The last node enumerated (or skipped) was CF_DIB;
+ // if that node still exists, we'll "skip" the fake
+ // CF_BITMAP node we would have generated.
+
+ m_fDib = FALSE;
+
+ // get the *current* cache node
+ lpCacheNode = m_pOleCache->GetAt(m_ulCurCacheId);
+
+ if (NULL != lpCacheNode &&
+ CF_DIB == lpCacheNode->GetFormatEtc()->cfFormat)
+ {
+ // The current cache node exists and it is of type
+ // CF_DIB, which means we've "found" a node to
+ // skip (in this case it's our fake CF_BITMAP that
+ // we would have generated from CF_DIB). The
+ // continue statement will execute the celt--
+ // in the for loop above
+
+ continue;
+ }
+
+ // if there was no cache node at m_ulCurCacheId, or
+ // the format was not CF_DIB that means the original
+ // node disappeared while we were enumerating
+ // (the caller may have called Uncache); we just
+ // fall through and pick up the next node
+ }
+
+ // If we're here, the last returned item was NOT
+ // CF_DIB
+
+ // Get next valid cache node from cache node list
+ lpCacheNode = m_pOleCache->GetNext(&m_ulCurCacheId);
+ if (NULL == lpCacheNode)
+ {
+ return ReportResult (0, S_FALSE, 0, 0);
+ }
+
+ // if this item is of format CF_DIB, then on the
+ // next iteration, return a synthesized CF_BITMAP for
+ // the same item
+ if (CF_DIB == lpCacheNode->GetFormatEtc()->cfFormat)
+ {
+ m_fDib = TRUE;
+ }
+ }
+
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnum::Reset, public
+//
+// Synopsis:
+// implements IEnumSTATDATA::Reset
+//
+// Arguments:
+// none
+//
+// Returns:
+// OLE_E_BLANK, if the associated ole cache has been destroyed
+// S_OK
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheEnum_Reset)
+STDMETHODIMP CCacheEnum::Reset(void)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ // if there's no cache, there's nothing to do
+ if (!m_pOleCache)
+ return ReportResult (0, OLE_E_BLANK, 0, 0);
+ // REVIEW, shouldn't there be a better error code for this?
+
+ // don't need to return a synthesized CF_BITMAP next
+ if (m_fDib)
+ m_fDib = FALSE;
+
+ // begin scanning the cache from the beginning again
+ m_ulCurCacheId = CACHEID_GETNEXT_GETALL;
+ return NOERROR;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CCacheEnum::Clone, public
+//
+// Synopsis:
+// implements IEnumSTATDATA::Clone
+//
+// Arguments:
+// [ppenum] -- pointer to where to return the created enumerator
+//
+// Returns:
+// OLE_E_BLANK, if the associated cache has been destroyed;
+// no enumerator is created in this case
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 11/28/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#pragma SEG(CCacheEnum_Clone)
+STDMETHODIMP CCacheEnum::Clone(LPENUMSTATDATA FAR* ppenum)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ // if there's no cache, don't create enumerator
+ if (!m_pOleCache)
+ {
+ *ppenum = NULL;
+ return ReportResult (0, OLE_E_BLANK, 0, 0);
+ }
+
+ // pass our state (pointer to COleCache and current item id) to the
+ // constuctor to get a clone.
+ if (!(*ppenum = (LPENUMSTATDATA) new CCacheEnum(m_pOleCache,
+ m_ulCurCacheId, m_fDib)))
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+ return NOERROR;
+}
+
+
+INTERNAL IsSameAsObjectFormatEtc(LPFORMATETC lpforetc, CLIPFORMAT cfFormat)
+{
+ VDATEHEAP();
+
+ // this function only checks for DVASPECT_CONTENT
+ if (lpforetc->dwAspect != DVASPECT_CONTENT)
+ return ResultFromScode(DV_E_DVASPECT);
+
+ // is the lindex right?
+ if (lpforetc->lindex != DEF_LINDEX)
+ return ResultFromScode(DV_E_LINDEX);
+
+ // if there's no format, set it to CF_METAFILEPICT or CF_DIB
+ if (lpforetc->cfFormat == NULL)
+ {
+ lpforetc->cfFormat = cfFormat;
+
+ if (lpforetc->cfFormat == CF_METAFILEPICT)
+ {
+ lpforetc->tymed = TYMED_MFPICT;
+ }
+#ifdef FULL_EMF_SUPPORT
+ else if (lpforetc->cfFormat == CF_ENHMETAFILE)
+ {
+ lpforetc->tymed = TYMED_ENHMF;
+ }
+#endif
+ else
+ {
+ lpforetc->tymed = TYMED_HGLOBAL;
+ }
+ }
+ else
+ {
+ // if it's CF_BITMAP, change it to CF_DIB
+ BITMAP_TO_DIB((*lpforetc));
+
+ // compare the two formats
+ if (lpforetc->cfFormat != cfFormat)
+ return ResultFromScode(DV_E_CLIPFORMAT);
+ }
+
+ // if we got here, the two formats are [interchangeable?]
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CCacheEnum::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppsz] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 31-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CCacheEnum::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszCThreadCheck;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump;
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ pszCThreadCheck = DumpCThreadCheck((CThreadCheck *)this, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CThreadCheck:" << endl;
+ dstrDump << pszCThreadCheck;
+ CoTaskMemFree(pszCThreadCheck);
+
+ dstrDump << pszPrefix << "No. of References = " << m_refs << endl;
+
+ dstrDump << pszPrefix << "Last returned item CF_DIB?= ";
+ if (m_fDib == TRUE)
+ {
+ dstrDump << "TRUE" << endl;
+ }
+ else
+ {
+ dstrDump << "FALSE" << endl;
+ }
+
+ dstrDump << pszPrefix << "Current cache ID enum = " << m_ulCurCacheId << endl;
+
+ // we don't want to dump the COleCache due to recursion
+ dstrDump << pszPrefix << "pCOleCache = " << m_pOleCache << endl;
+
+ dstrDump << pszPrefix << "pNext CCacheEnum = " << m_pNextCacheEnum << endl;
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCCacheEnum, public (_DEBUG only)
+//
+// Synopsis: calls the CCacheEnum::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pCE] - pointer to CCacheEnum
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 31-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCCacheEnum(CCacheEnum *pCE, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pCE == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pCE->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
diff --git a/private/ole32/ole232/clipbrd/clipapi.cpp b/private/ole32/ole232/clipbrd/clipapi.cpp
new file mode 100644
index 000000000..283495e75
--- /dev/null
+++ b/private/ole32/ole232/clipbrd/clipapi.cpp
@@ -0,0 +1,3722 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: clipapi.cpp
+//
+// Contents: Clipboard related OLE API's
+//
+// Classes:
+//
+// Functions:
+// OleFlushClipboard
+// OleGetClipboard
+// OleIsCurrentClipboard
+// OleSetClipboard
+//
+// History: dd-mmm-yy Author Comment
+// 12-Aug-94 alexgo added support for transfering
+// DVASPECT_ICON, etc.
+// 08-Aug-94 BruceMa Memory sift fix
+// 10-Jun-94 alexgo added support for OLE1 Containers
+// 17-May-94 alexgo created OleOpenClipboard and enhanced
+// code to mimize the times when the
+// clipboard is kept open.
+// 25-Apr-94 alexgo made thread-safe for the apartment model
+// 16-Mar-94 alexgo author
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#include <getif.hxx>
+#include <clipbrd.h>
+#include <olesem.hxx>
+#include <ostm2stg.h> // for wProgIDFromCLSID
+#include "clipdata.h"
+
+//
+// types local to this file
+//
+
+typedef enum tagCLIPWNDFLAGS
+{
+ CLIPWND_REMOVEFROMCLIPBOARD = 1,
+ CLIPWND_IGNORECLIPBOARD = 2,
+ CLIPWND_DONTCALLAPP = 4
+} CLIPWNDFLAGS;
+
+typedef enum tagGETCLSIDFLAGS
+{
+ USE_NORMAL_CLSID = 1,
+ USE_STANDARD_LINK = 2,
+} GETCLSIDFLAGS;
+
+
+//
+// functions local to this file. They are not "static" so the symbols
+// show up in ntsd debug builds.
+//
+extern "C" LRESULT ClipboardWndProc( HWND, UINT, WPARAM, LPARAM );
+HRESULT GetDataFromDescriptor(IDataObject *pDataObj, LPCLSID pclsid,
+ UINT cf, GETCLSIDFLAGS fFlags,
+ LPOLESTR *ppszSrcOfCopy,
+ DWORD *pdwStatus);
+HRESULT GetDataFromStorage(IDataObject *pDataObj, UINT cf,
+ STGMEDIUM *pmedium, IStorage **ppstg);
+HRESULT GetDataFromStream(IDataObject *pDataObj, UINT cf,
+ STGMEDIUM *pmedium, IStream **ppstm);
+HRESULT GetNative(IDataObject *pDataObj, STGMEDIUM *pmedium);
+HRESULT GetObjectLink(IDataObject *pDataObj, STGMEDIUM *pmedium);
+HRESULT GetOwnerLink(IDataObject *pDataObj, STGMEDIUM *pmedium);
+HRESULT HandleFromHandle(IDataObject *pDataObj, FORMATETC *pformatetc,
+ STGMEDIUM *pmedium);
+HRESULT MapCFToFormatetc( UINT cf, FORMATETC *pformatetc );
+HRESULT RemoveClipboardDataObject( HWND hClipWnd, DWORD fFlags );
+HRESULT RenderFormat( HWND hClipWnd, UINT cf, IDataObject *pDataObj );
+HRESULT SetClipboardDataObject( HWND hClipWnd, IDataObject *pDataObj );
+HRESULT SetClipboardFormats( HWND hClipWnd, IDataObject *pDataObj );
+HWND VerifyCallerIsClipboardOwner( void );
+
+//
+//static variables
+//
+
+// vcClipboardInit is used to keep track of the number of times Clipboard
+// Initialize is called (right now, only from OleInitialize), so that we
+// only create a private clipboard window class once per dll (even though
+// the many threads may need their own instance of the window class in the
+// apartment model).
+
+static ULONG vcClipboardInit;
+
+// vszClipboardWndClass is the name of the window class used by OLE to
+// create private clipboard windows for copy/paste and other clipboard
+// data transfers.
+
+#ifdef _CHICAGO_
+// Note: we have to create a unique string so that get
+// register a unique class for each 16 bit app.
+// The class space is global on chicago.
+//
+
+char g_vszClipboardWndClass[] = "CLIPBRDWNDCLASS 0x######## ";
+#define vszClipboardWndClass g_vszClipboardWndClass
+#define ClpWNDCLASS WNDCLASSA
+#define ClpRegisterClass RegisterClassA
+#define ClpUnregisterClass UnregisterClassA
+#define ClpCreateWindowEx SSCreateWindowExA
+
+#else
+static const OLECHAR vszClipboardWndClass[] = OLESTR("CLIPBRDWNDCLASS");
+#define ClpWNDCLASS WNDCLASS
+#define ClpRegisterClass RegisterClass
+#define ClpUnregisterClass UnregisterClass
+#define ClpCreateWindowEx CreateWindowEx
+
+#endif
+
+
+// Mutex used to synchronize clipboard initialization / cleanup
+
+extern COleStaticMutexSem g_mxsSingleThreadOle;
+
+
+// Property we put on the window that is used to keep a duplicate of
+// OlePrivateData (so we don't have to go the clipboard to fetch it)
+WCHAR *pwszClipPrivateData = L"ClipPrivData";
+
+//
+// functions (in alphabetical order)
+//
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ClipboardInitialize (private)
+//
+// Synopsis: Creates the private clipboard window class (if necessary)
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires: hmodOLE2 must be initialized
+//
+// Returns: TRUE upon success, false otherwise
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Register the clipboard class only once per dll instance
+// (or more specifically, every time vcClipboardInit == 0,
+// which may happen multiple times in a WOW box).
+//
+// History: dd-mmm-yy Author Comment
+// 23-Oct-94 alexgo fixed up Chicago WOW hacks (see comments)
+// 25-Apr-94 alexgo updated to the apartment model
+// 16-Mar-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+BOOL ClipboardInitialize( void )
+{
+ ClpWNDCLASS wc;
+ BOOL fRet = TRUE;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN ClipboardInitialize ( )\n", NULL));
+
+ // serialize access to this function
+ // we'll unlock the mutex automatically in "lck"'s destructor
+ // (called at function exit)
+
+ COleStaticLock lck(g_mxsSingleThreadOle);
+
+ // One time initializtaion (when loaded for the first time)
+
+ if (vcClipboardInit == 0)
+ {
+#ifdef _CHICAGO_
+ if (IsWOWThread())
+ {
+ wsprintfA(vszClipboardWndClass,"CLIPBRDWNDCLASS %08X",
+ CoGetCurrentProcess());
+ }
+#endif // _CHICAGO_
+
+
+ // Register Clipboard window class
+ wc.style = 0;
+ wc.lpfnWndProc = ClipboardWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = sizeof(void *);
+
+ AssertSz(g_hmodOLE2, "Dll instance variable not set");
+
+ wc.hInstance = g_hmodOLE2; //global vairable set in
+ //ole2.cpp
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = vszClipboardWndClass;
+
+ // register this window class, returning if we fail
+ if (!ClpRegisterClass(&wc))
+ {
+ LEWARN(FALSE, "ClipboardInitialize RegisterClass failed!");
+
+ // it is possible that our dll got unloaded without us
+ // having called unregister, so we call it here and try
+ // again.
+ ClpUnregisterClass( vszClipboardWndClass, g_hmodOLE2 );
+ if (!ClpRegisterClass(&wc))
+ {
+ LEWARN(FALSE, "ClipboardInitialize RegisterClass failed again!");
+ LEDebugOut((DEB_WARN,
+ "WARNING: RegisterClass failed\n"));
+ fRet = FALSE;
+ goto errRtn;
+ }
+ }
+
+ vcClipboardInit++;
+ }
+
+errRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT ClipboardIntialize ( %lu )\n",
+ NULL, fRet));
+
+ return fRet;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ClipboardUnitialize (internal)
+//
+// Synopsis: Uninitializes the clipboard for the current thread.
+//
+// Effects:
+//
+// Arguments: void
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Oct-94 alexgo fixed up Chicago WOW hacks (see comments)
+// 25-Apr-94 alexgo made thread-safe
+// 16-Mar-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+void ClipboardUninitialize(void)
+{
+ VDATEHEAP();
+
+ //
+ // BUGBUG - This cleanup is done during OleUninitialize, but not
+ // if somebody does FreeLibrary(OLE32.DLL). This is bad. It causes
+ // us to leak the class register and any clipboard window. We have
+ // gotten around the class re-register problem above in the
+ // ClipboardInitialize function, but we still leak a window.
+ //
+
+ LEDebugOut((DEB_ITRACE, "%p _IN ClipboardUninitialize ( )\n", NULL));
+
+ COleTls tls;
+ if(tls->hwndClip)
+ {
+ // destroy the window and NULL out the hwnd in the thread
+ // storage
+ Verify(SSDestroyWindow(tls->hwndClip));
+ tls->hwndClip = NULL;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ClipboardProcessUnitialize (internal)
+//
+// Synopsis: Uninitializes the clipboard. If this the last such time,
+// then the private clipboard window class is unregistered.
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires: hmodOLE2 must be initialized before calling this function
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Oct-94 alexgo fixed up Chicago WOW hacks (see comments)
+// 25-Apr-94 alexgo made thread-safe
+// 16-Mar-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+void ClipboardProcessUninitialize(void)
+{
+ // serialize access for the apartment model
+
+ COleStaticLock lck(g_mxsSingleThreadOle);
+
+ if(vcClipboardInit == 1)
+ {
+ vcClipboardInit--;
+
+ BOOL fRet = ClpUnregisterClass(vszClipboardWndClass,
+ g_hmodOLE2);
+
+ LEWARN(!fRet, "UnRegisterClass failed!");
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT ClipboardUninitialize ( )\n", NULL));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ClipboardWndProc
+//
+// Synopsis: Window message procedure for the private clipboard window
+//
+// Effects:
+//
+// Arguments: [hWnd] -- handle to private clipboard window
+// [msg] -- the Window message
+// [wParam] -- parameter 1
+// [lParam] -- parameter 2
+//
+// Requires:
+//
+// Returns: LRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: processes messages sent to the private clipboard window:
+// WM_DESTROYCLIPBOARD: somebody else is taking ownership
+// of the clipboard, so release the data object
+// (if any)
+// WM_RENDERFORMAT: a request has been made for data of the
+// specified format--actually put it on the clipboard
+// WM_RENDERALLFORMATS: the app is going away, so empty the
+// clipboard! The app is supposed to call
+// OleFlushClipboard before exiting, if it hasn't, then
+// we can only assume that the app is terminating
+// "abnormally". We currently do nothing for this call
+//
+// History: dd-mmm-yy Author Comment
+// 23-Oct-94 alexgo added support for eating WM_CANCELMODE
+// messages
+// 20-Mar-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+extern "C" LRESULT ClipboardWndProc( HWND hWnd, UINT msg, WPARAM wParam,
+ LPARAM lParam )
+{
+ LRESULT lresult = 0;
+ IDataObject * pDataObj = NULL;
+ UINT cf;
+ HRESULT hresult;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN ClipboardWndProc ( %lx , %u , %lu ,"
+ " %ld )\n", NULL, hWnd, msg, wParam, lParam));
+
+ AssertSz((GetCurrentThreadId()
+ == GetWindowThreadProcessId(hWnd, NULL)),
+ "Clip window not on current thread");
+
+ switch( msg )
+ {
+ // note that the clipboard should *NOT* be opened for these messages
+
+ case WM_RENDERALLFORMATS:
+ // this message is sent to us if this window (the private
+ // clipboard window) is about to be destroyed.
+
+ // We don't currently do anything for this message.
+ // REVIEW: in the future, we may want to render all the
+ // remaining formats. However, the app is *supposed* to
+ // call OleFlushClipboard to accomplish this task.
+
+ Assert(lresult == 0);
+ break;
+
+ case WM_DESTROYCLIPBOARD:
+ // we get this message when somebody else takes ownership
+ // of the clipboard. Since our app may have an AddRef'ed
+ // data object already there, we need to remove it.
+
+ // there is no need to open the clipboard (since we specify
+ // the IGNORECLIPBOARD flag)
+
+ RemoveClipboardDataObject(hWnd, CLIPWND_IGNORECLIPBOARD);
+
+ Assert(lresult == 0);
+
+ break;
+
+ case WM_RENDERFORMAT:
+
+ cf = (UINT)wParam;
+
+ pDataObj = (IDataObject *)GetProp( hWnd,
+ CLIPBOARD_DATA_OBJECT_PROP);
+
+ if( !pDataObj )
+ {
+ LEDebugOut((DEB_ERROR, "ERROR!: No data object "
+ "on the private window\n"));
+ break;
+ }
+
+ // now render the data onto the clipboard
+ hresult = RenderFormat( hWnd, cf, pDataObj);
+
+#if DBG == 1
+ if( hresult != NOERROR )
+ {
+ char szBuf[256];
+ char *pszBuf;
+
+ // we have to do predefined formats by hand
+ if( cf > 0xC000 )
+ {
+ SSGetClipboardFormatNameA(cf, szBuf, 256);
+ pszBuf = szBuf;
+ }
+ else
+ {
+ switch( cf )
+ {
+ case CF_METAFILEPICT:
+ pszBuf = "CF_METAFILEPICT";
+ break;
+ case CF_BITMAP:
+ pszBuf = "CF_BITMAP";
+ break;
+ case CF_DIB:
+ pszBuf = "CF_DIB";
+ break;
+ case CF_PALETTE:
+ pszBuf = "CF_PALETTE";
+ break;
+ case CF_TEXT:
+ pszBuf = "CF_TEXT";
+ break;
+ case CF_UNICODETEXT:
+ pszBuf = "CF_UNICODETEXT";
+ break;
+ case CF_ENHMETAFILE:
+ pszBuf = "CF_ENHMETAFILE";
+ break;
+ default:
+ pszBuf = "UNKNOWN Default Format";
+ break;
+ }
+ }
+ LEDebugOut((DEB_WARN, "WARNING: Unable to render "
+ "format '%s' (%x)\n", pszBuf, cf));
+ }
+#endif // DBG == 1
+
+ Assert(lresult == 0);
+
+ break;
+
+ case WM_CANCELMODE:
+ // we want to swallow the WM_CANCELMODE message. This
+ // allows us to start drag drop, alt-tab to another app
+ // (which causes a WM_CANCELMODE message) and continue
+ // dragging.
+
+ Assert(lresult == 0);
+
+ break;
+
+ case WM_DESTROY:
+ // apps are supposed to call OleSetClipboard(NULL) or
+ // OleFlushClipboard() before terminating a thread. However,
+ // not all apps do what they're supposed to, so just
+ // remove as much state as we can safely do
+
+ // Potentially, we could use CLIPWND_REMOVEFROMCLIPBOARD
+ // here. However, getting in this situation should be
+ // somewhat unusual, so we don't want to do any more work
+ // than absolutely necessary. Even though we'll leave a
+ // hwnd on the clipboard in g_cfDataObject, that hwnd
+ // will soon be invalid (because it's the one getting this
+ // WM_DESTROY message).
+
+#if DBG == 1
+ // do some debug checking first though
+
+ if( GetProp( hWnd, pwszClipPrivateData) != 0 )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: App did not cleanup the "
+ "clipboard properly, OleSetClipboard(NULL) or "
+ "OleFlushClipboard not called"));
+ }
+
+#endif // DBG == 1
+
+ RemoveClipboardDataObject(hWnd, (CLIPWND_DONTCALLAPP |
+ CLIPWND_IGNORECLIPBOARD));
+
+ Assert(lresult == 0);
+
+ break;
+
+ default:
+ lresult = SSDefWindowProc( hWnd, msg, wParam, lParam);
+ break;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT ClipboardWndProc ( %ld )\n", NULL,
+ lresult));
+
+ return lresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ClipSetCaptureForDrag
+//
+// Synopsis: Sets mouse capture mode for a drag operation
+//
+// Arguments: [pdrgop] - pointer to object that handles drag operation
+//
+// Returns: S_OK -- it worked
+// E_FAIL -- unexpected failure occurred.
+//
+// Algorithm: Get the clipboard window for the thread. Record the drag
+// drag operation pointer on the window for use by capture
+// mode. then turn on capture mode.
+//
+// History: dd-mmm-yy Author Comment
+// 21-Apr-94 ricksa created
+//
+// Notes: The purpose of this function is to hide where the drag
+// pointer is stored for the window.
+//
+//--------------------------------------------------------------------------
+HRESULT ClipSetCaptureForDrag(CDragOperation *pdrgop)
+{
+ // Default to failure
+ HRESULT hr = ResultFromScode(E_FAIL);
+
+ // We will use the clipboard window to capture the mouse but we
+ // must have a clipboard window so we make sure it is created
+ // if it is not already there.
+ HWND hWndClip = GetPrivateClipboardWindow(CLIP_CREATEIFNOTTHERE);
+
+ if (hWndClip != NULL)
+ {
+ AssertSz((GetCurrentThreadId()
+ == GetWindowThreadProcessId(hWndClip, NULL)),
+ "Clip window not on current thread");
+
+ // Capture the mouse
+ SetCapture(hWndClip);
+
+ // Teller the caller that we worked.
+ hr = NOERROR;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ClipReleaseCaptureForDrag
+//
+// Synopsis: Clean up drag mouse capture
+//
+// Algorithm: Get the clipboard window for the thread. Turn the drag
+// operation pointer into null. Then release the capture.
+//
+// History: dd-mmm-yy Author Comment
+// 21-Apr-94 ricksa created
+//
+// Notes: It is assumed that the clip board window and the thread
+// doing drag and drop are on the same thread. Therefore,
+// there should be no race between clean up here and
+// the use of the pointer in the clipboard window proc.
+//
+//--------------------------------------------------------------------------
+void ClipReleaseCaptureForDrag(void)
+{
+#if 0
+ // this code turned off by ericoe on 4/19/95
+ // left here for reference "just in case"
+ // the whole block turned off because we no longer need to do the RemoveProp
+
+ // Tell the window that the drag operation is over
+ HWND hWndClip = GetPrivateClipboardWindow(CLIP_QUERY);
+
+ AssertSz((hWndClip != NULL), "Release capture but no window");
+
+ if (hWndClip)
+ {
+ AssertSz((GetCurrentThreadId()
+ == GetWindowThreadProcessId(hWndClip, NULL)),
+ "Clip window not on current thread");
+
+ // We are done so remove the property
+ Verify(RemoveProp(hWndClip, pwszClipDragProp));
+ }
+#endif
+
+ // Stop the mouse capture
+ ReleaseCapture();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetDataFromDescriptor
+//
+// Synopsis: Retrieves object descriptor data from the specified
+// clipboard format and fetches the clsid, SrcOfCopy
+// string, and status flags
+//
+// Effects:
+//
+// Arguments: [pDataObj] -- the source data object
+// [pclsid] -- where to put the clsid
+// [cf] -- the clipboard format to retrieve
+// [fFlags] -- clsid conversion flags
+// [ppszSrcOfCopy] -- where to put an ALLOCATED (public
+// allocator) copy of the SrcOfCopy
+// string.
+// [pdwStatus] -- where to put the status bits
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: see synopsis
+//
+// History: dd-mmm-yy Author Comment
+// 18-Aug-94 alexgo added support for fetching dwStatus
+// 10-Jun-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+HRESULT GetDataFromDescriptor(IDataObject *pDataObj, LPCLSID pclsid,
+ UINT cf, GETCLSIDFLAGS fFlags,
+ LPOLESTR *ppszSrcOfCopy,
+ DWORD *pdwStatus)
+{
+ HRESULT hresult;
+ FORMATETC formatetc;
+ STGMEDIUM medium;
+ LPOBJECTDESCRIPTOR pObjDesc;
+
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN GetDataFromDescriptor ( %p , "
+ "%p , %d , %lx , %p, %p )\n", NULL, pDataObj, pclsid, cf,
+ fFlags, ppszSrcOfCopy, pdwStatus));
+
+ // we don't bother with extensive attempts to fetch the
+ // OLE2 data since we're only using it to construct OLE1. If
+ // the data is offered in a non-standard way, the the worse
+ // that will happen is that you can't paste an *object* to
+ // an OLE1 container. 16bit was even more strict in that
+ // you *always* had to offer OLE2 formats on standard mediums.
+
+ INIT_FORETC(formatetc);
+ formatetc.cfFormat = cf;
+ formatetc.tymed = TYMED_HGLOBAL;
+ medium.tymed = TYMED_HGLOBAL;
+
+ hresult = pDataObj->GetData(&formatetc, &medium);
+
+ if( hresult != NOERROR )
+ {
+ goto logRtn;
+ }
+
+ pObjDesc = (LPOBJECTDESCRIPTOR)GlobalLock(medium.hGlobal);
+
+ if( !pObjDesc )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ if( pclsid )
+ {
+ // if we want to use the standard link AND the object really
+ // is a link object (potentially a custom link), then
+ // just set the clsid to the be the standard link object
+ if( (fFlags & USE_STANDARD_LINK) &&
+ (pObjDesc->dwStatus & OLEMISC_ISLINKOBJECT) )
+ {
+ *pclsid = CLSID_StdOleLink;
+ }
+ else
+ {
+ *pclsid = pObjDesc->clsid;
+ }
+ }
+
+ if( ppszSrcOfCopy )
+ {
+ if( pObjDesc->dwSrcOfCopy )
+ {
+ *ppszSrcOfCopy = UtDupString(
+ (LPOLESTR)(((BYTE *)pObjDesc)+pObjDesc->dwSrcOfCopy));
+
+ }
+ else
+ {
+ *ppszSrcOfCopy = UtDupString(OLESTR(""));
+ }
+
+ if( !*ppszSrcOfCopy )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ }
+
+ if( pdwStatus )
+ {
+ *pdwStatus = pObjDesc->dwStatus;
+ }
+
+ GlobalUnlock(medium.hGlobal);
+
+errRtn:
+
+ ReleaseStgMedium(&medium);
+
+logRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT GetDataFromDescriptor ( %lx ) "
+ "[ %p ]\n", NULL, hresult,
+ (ppszSrcOfCopy) ? *ppszSrcOfCopy : 0 ));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetDataFromStorage
+//
+// Synopsis: Calls GetData[Here] for TYMED_ISTORAGE and returns the
+// results on either an HGLOBAL or memory-based storage
+//
+// Effects:
+//
+// Arguments: [pDataObj] -- the source data object
+// [pformatetc] -- formatetc to retrieve
+// [pmedium] -- where to put the resulting HGlobal, may
+// be NULL
+// [ppstg] -- where to save the real IStorage
+// (may be NULL)
+//
+// Requires: if pmedium is specified, then pmedium->tymed must be
+// TYMED_HGLOBAL
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: we create a storage on memory
+// first try to GetDataHere to that storage, if that fails, then
+// do a GetData and CopyTo the returned storage to our memory
+// storage.
+//
+// History: dd-mmm-yy Author Comment
+// 11-Apr-94 alexgo author
+//
+// Notes: NB!!: The caller takes ownership of the data--if an hglobal
+// is requested, then it must be explicitly GlobalFree'd.
+// Similarly, the returned storage must be released and both
+// release mechanisms must be called if both data items are
+// returned.
+//
+//--------------------------------------------------------------------------
+
+HRESULT GetDataFromStorage(IDataObject *pDataObj, FORMATETC *pformatetc,
+ STGMEDIUM *pmedium, IStorage **ppstg)
+{
+ HRESULT hresult;
+ STGMEDIUM memmedium; // for the memory-based IStorage
+ ILockBytes * pLockBytes;
+ BOOL fDeleteOnRelease = FALSE;
+ FORMATETC fetctemp;
+
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN GetDataFromStorage ( %p , %p , %p"
+ " )\n", NULL, pDataObj, pformatetc, pmedium));
+
+#if DBG ==1
+ if( pmedium )
+ {
+ Assert(pmedium->tymed == TYMED_HGLOBAL);
+ }
+#endif // DBG ==1
+
+ Assert(pformatetc->tymed & TYMED_ISTORAGE);
+
+ // don't stomp on the in-parameter
+ fetctemp = *pformatetc;
+ fetctemp.tymed = TYMED_ISTORAGE;
+
+
+ _xmemset(&memmedium, 0, sizeof(STGMEDIUM));
+ memmedium.tymed = TYMED_ISTORAGE;
+
+ // the only time we want the hglobal that the storage will be
+ // constructed from to be automatically deleted is if the caller
+ // only requested a storage to be returned.
+
+ if( ppstg && !pmedium )
+ {
+ fDeleteOnRelease = TRUE;
+ }
+
+ hresult = UtCreateStorageOnHGlobal( NULL,
+ fDeleteOnRelease,
+ &(memmedium.pstg), &pLockBytes);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // first try to do a GetDataHere call
+
+ hresult = pDataObj->GetDataHere( &fetctemp, &memmedium );
+
+ if( hresult != NOERROR )
+ {
+ STGMEDIUM appmedium; // a medium that is filled
+ // in by the app
+
+ _xmemset(&appmedium, 0, sizeof(STGMEDIUM));
+
+ // hmmm, that didn't work, try for a plain GetData call
+ hresult = pDataObj->GetData(&fetctemp, &appmedium);
+
+ if( hresult == NOERROR )
+ {
+ // now do the CopyTo
+
+ hresult = appmedium.pstg->CopyTo(0, NULL, NULL,
+ memmedium.pstg);
+
+ // we are now done with the app supplied medium
+ ReleaseStgMedium(&appmedium);
+ }
+ }
+
+ // release the storage unless there's no error and the
+ // caller requested a copy
+
+ if( ppstg && hresult == NOERROR )
+ {
+ *ppstg = memmedium.pstg;
+ // we need to do a Commit here to flush cached data to
+ // disk (in this case, to the hglobal). The release
+ // below in the alternate code path will automatically
+ // cause a Commit
+ memmedium.pstg->Commit(STGC_DEFAULT);
+ }
+ else
+ {
+ memmedium.pstg->Release();
+ }
+
+ // now retrieve the HGLOBAL from the storage. NB! It is very
+ // important to do this *after* the release; the final release
+ // on the storage causes a Commit. (Alternately, we can simply
+ // call Commit--see above).
+
+ if( hresult == NOERROR && pmedium )
+ {
+ hresult = GetHGlobalFromILockBytes(pLockBytes,
+ &(pmedium->hGlobal));
+ }
+
+ pLockBytes->Release();
+
+errRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT GetDataFromStorage ( %lx )\n",
+ NULL, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetDataFromStream
+//
+// Synopsis: Calls GetData[Here] for TYMED_ISTREAM and returns the
+// results on an HGLOBAL
+//
+// Effects:
+//
+// Arguments: [pDataObj] -- the source data object
+// [pformatetc] -- the formatetc to retrieve
+// [pmedium] -- where to put the resulting HGlobal.
+// (may be NULL)
+// [ppstm] -- where to put the stream ( may be NULL )
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: we create a stream on memory
+// first try to GetDataHere to that stream, if that fails, then
+// do a GetData and CopyTo the returned stream to our memory
+// stream.
+//
+// History: dd-mmm-yy Author Comment
+// 11-Apr-94 alexgo author
+//
+// Notes: NB!!: The caller takes ownership fo the data returned, either
+// GlobalFree or Release (or both) must be called.
+//
+//--------------------------------------------------------------------------
+
+HRESULT GetDataFromStream(IDataObject *pDataObj, FORMATETC *pformatetc,
+ STGMEDIUM *pmedium, IStream **ppstm)
+{
+ HRESULT hresult;
+ STGMEDIUM memmedium; // for the memory-based IStream
+ HGLOBAL hglobal = NULL;
+ BOOL fDeleteOnRelease = FALSE;
+ FORMATETC fetctemp;
+
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN GetDataFromStream ( %p , %p , %p )\n",
+ NULL, pDataObj, pformatetc, pmedium));
+
+ // the only time we want the underlying hglobal for the stream to
+ // be automatically deleted is if the caller only wanted the
+ // stream returned.
+
+ if( ppstm && !pmedium )
+ {
+ fDeleteOnRelease = TRUE;
+ }
+
+ Assert( pformatetc->tymed & TYMED_ISTREAM );
+
+ // don't stomp on the in-parameter
+ fetctemp = *pformatetc;
+ fetctemp.tymed = TYMED_ISTREAM;
+
+
+ _xmemset(&memmedium, 0, sizeof(STGMEDIUM));
+ memmedium.tymed = TYMED_ISTREAM;
+
+ hresult = CreateStreamOnHGlobal( NULL,
+ fDeleteOnRelease,
+ &(memmedium.pstm));
+
+ if( hresult != NOERROR )
+ {
+ goto logRtn;
+ }
+
+
+ // first try to do a GetDataHere call
+
+ hresult = pDataObj->GetDataHere( &fetctemp, &memmedium );
+
+ if( hresult != NOERROR )
+ {
+ if (hresult == E_OUTOFMEMORY)
+ {
+ goto errRtn;
+ }
+
+ STGMEDIUM appmedium; // a medium that is filled
+ // in by the app
+ LARGE_INTEGER li;
+ ULARGE_INTEGER uli;
+ ULARGE_INTEGER uliWritten;
+#if DBG == 1
+ ULARGE_INTEGER uliEnd;
+#endif
+
+ _xmemset(&appmedium, 0, sizeof(STGMEDIUM));
+
+ // hmmm, that didn't work, try for a plain GetData call
+ hresult = pDataObj->GetData( &fetctemp, &appmedium );
+
+ if( hresult != NOERROR )
+ {
+ // oh well, we tried. Cleanup and away we go
+ goto errRtn;
+ }
+
+ // now do the CopyTo. In order to do this, we need
+ // to get the size of the returned stream, reset its
+ // seek pointer to the beginning and then do a stream
+ // CopyTo.
+
+ LISet32(li, 0);
+
+ hresult = appmedium.pstm->Seek(li, STREAM_SEEK_CUR, &uli);
+
+ if( hresult != NOERROR )
+ {
+ ReleaseStgMedium(&appmedium);
+ goto errRtn;
+ }
+
+#if DBG == 1
+
+ // According to the spec, the end of the data should be
+ // positioned at the current seek pointer (which is
+ // not necessarily the end of the stream). Here we will
+ // see if the current seek pointer is at the *end* of the
+ // stream. If the current seek is NOT equal to the end,
+ // then there is a good chance of a bug somewhere in the
+ // system (so we'll print a warning)
+
+ hresult = appmedium.pstm->Seek(li, STREAM_SEEK_END, &uliEnd);
+
+ // we don't return on error for debug builds so retail
+ // and debug have exactly the same behaviour
+
+ if( hresult == NOERROR )
+ {
+ // compare the two seek pointers. The high parts
+ // *must* be zero (or we're hosed, since all of
+ // this is taking place in memory
+
+ Assert(uliEnd.HighPart == 0);
+
+ LEWARN(uliEnd.LowPart != uli.LowPart,
+ "Stream seek pointer "
+ "not at end, possible error");
+ }
+ else
+ {
+ LEDebugOut((DEB_ERROR, "ERROR!: IStream->Seek failed!"
+ "\n"));
+ // FALL-THROUGH!! This is deliberate--even
+ // though we're in an error case, we want
+ // debug && retail to have the same behaviour
+ // (besides, we'll most likely fail in the
+ // Seek call below).
+ }
+
+#endif // DBG == 1
+
+
+ // now backup to the beginning
+
+ hresult = appmedium.pstm->Seek(li, STREAM_SEEK_SET, NULL);
+
+ if( hresult != NOERROR )
+ {
+ ReleaseStgMedium(&appmedium);
+ goto errRtn;
+ }
+
+ // now that we know how many bytes to copy, actually do so.
+
+ hresult = appmedium.pstm->CopyTo(memmedium.pstm, uli,
+ NULL, &uliWritten);
+
+ if( hresult == NOERROR )
+ {
+ // make sure we got enough data
+ if( uli.LowPart != uliWritten.LowPart )
+ {
+ // we probably ran out of memory
+ // trying to resize the memory stream
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ }
+ }
+
+ // we are now done with the app supplied medium
+ ReleaseStgMedium(&appmedium);
+ }
+
+ // now fetch the hglobal from the [resized] memory stream
+
+ if( hresult == NOERROR )
+ {
+ hresult = GetHGlobalFromStream(memmedium.pstm, &hglobal);
+ }
+
+errRtn:
+
+ // if the caller wanted the stream, then give it to him
+ // (only if there was no error)
+ // otherwise, release it
+
+ if( hresult == NOERROR && ppstm )
+ {
+ *ppstm = memmedium.pstm;
+ // we do not need to call Commit in this case; our
+ // implementation of memory streams guarantees that
+ // the underlying hglobal always contains flushed
+ // information.
+ }
+ else
+ {
+ memmedium.pstm->Release();
+ }
+
+ // if there was an error, then would have never allocated the
+ // hglobal
+
+ if( hresult == NOERROR && pmedium)
+ {
+ pmedium->hGlobal = hglobal;
+ }
+
+logRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT GetDataFromStream ( %lx )\n",
+ NULL, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetNative
+//
+// Synopsis: Retrieves or syntesizes OLE1 Native data format
+//
+// Effects:
+//
+// Arguments: [pDataObj] -- the source data object
+// [pmedium] -- where to put the data
+//
+// Requires: pmedium->tymed must be TYMED_HGLOBAL
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+// cfNative is an OLE1 format consisting of an aribtrary
+// hGlobal. It is up to the source app to interpret any
+// data therein; OLE1 containers merely store and forward it.
+//
+// first fetch either EmbedSource or EmbeddedObject
+// then check to see if that NATIVE_STREAM exists. If so,
+// then this was an object created from an OLE1 server and
+// we should just offer it's native data.
+// Otherwise, the object is an OLE2 object, and we should
+// offer it's storage as the native data.
+//
+// History: dd-mmm-yy Author Comment
+// 10-Jun-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT GetNative( IDataObject *pDataObj, STGMEDIUM *pmedium)
+{
+ HRESULT hresult;
+ IStorage * pstg = NULL;
+ IStream * pstm = NULL;
+ UINT cf;
+ HGLOBAL hNative = NULL;
+ DWORD dwSize = 0;
+ LPVOID pv;
+ FORMATETC formatetc;
+
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN GetNative ( %p , %p )\n", NULL,
+ pDataObj, pmedium));
+
+ Assert(pmedium->tymed == TYMED_HGLOBAL);
+
+ if( SSIsClipboardFormatAvailable(g_cfEmbeddedObject) )
+ {
+ cf = g_cfEmbeddedObject;
+ }
+ else if( SSIsClipboardFormatAvailable(g_cfEmbedSource) )
+ {
+ cf = g_cfEmbedSource;
+ }
+ else
+ {
+ hresult = ResultFromScode(E_UNEXPECTED);
+ LEDebugOut((DEB_ERROR, "ERROR!: Native data should not "
+ "be on clipboard!!\n"));
+ goto errRtn;
+ }
+
+ INIT_FORETC(formatetc);
+ formatetc.cfFormat = cf;
+ formatetc.tymed = TYMED_ISTORAGE;
+
+ hresult = GetDataFromStorage(pDataObj, &formatetc, pmedium, &pstg);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ hresult = pstg->OpenStream(OLE10_NATIVE_STREAM, NULL, STGM_SALL, 0,
+ &pstm);
+
+ if( hresult == NOERROR )
+ {
+ // we had ole1 data originally, just use it.
+
+ hresult = StRead(pstm, &dwSize, sizeof(DWORD));
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ hNative = GlobalAlloc((GMEM_SHARE | GMEM_MOVEABLE), dwSize);
+
+ if( !hNative )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: GlobalAlloc failed!"
+ "\n"));
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ pv = GlobalLock(hNative);
+
+ if( !pv )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: GlobalLock failed!"
+ "\n"));
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ // now copy the data from the stream into the hglobal
+
+ hresult = StRead(pstm, pv, dwSize);
+
+ GlobalUnlock(hNative);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // this is bit is counter-intuitive. The hglobal
+ // we have in pmedium->hGlobal still has a storage on
+ // top of it, so we must release our stream, then
+ // the storage, and finally free the hglobal so we
+ // don't leak memory. We've already allocated another
+ // hglobal in this routine to return the Native data.
+
+ pstm->Release();
+ pstg->Release();
+ GlobalFree(pmedium->hGlobal);
+
+ // now we assign pmedium->hGlobal to the hglobal we
+ // just created so we can pass it out
+
+ pmedium->hGlobal = hNative;
+
+ // don't release the streams again
+ goto logRtn;
+
+ }
+ else
+ {
+ // storage for an OLE2 object. pmedium->hGlobal
+ // should already contain the data we need to put
+ // on the clipboard (from the GetDataFromStorage call)
+
+ Assert(pmedium->hGlobal);
+ hresult = NOERROR;
+ }
+
+errRtn:
+ if( pstm )
+ {
+ pstm->Release();
+ }
+
+ if( pstg )
+ {
+ pstg->Release();
+ }
+
+ if( hresult != NOERROR )
+ {
+ GlobalFree(pmedium->hGlobal);
+ }
+
+logRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT GetNative ( %lx ) [ %lx ]\n",
+ NULL, hresult, pmedium->hGlobal));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetObjectLink
+//
+// Synopsis: Synthesizes OLE1 ObjectLink format from LinkSource data
+//
+// Effects:
+//
+// Arguments: [pDataObj] -- the source data object
+// [pmedium] -- where to put the data
+//
+// Requires: pmedium->tymed must be TYMED_HGLOBAL
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Get the LinkSource data, which contains a serialized
+// moniker. Load the moniker from the stream and parse it
+// to retrieve the file name and item name (if available).
+// Get the class ID of the link source from either the
+// LinkSource stream or from LinkSrcDescriptor.
+// Once these strings are converted to ANSI, we can build
+// the ObjectLink format, which looks like:
+//
+// classname\0filename\0itemname\0\0
+//
+// History: dd-mmm-yy Author Comment
+// 10-Jun-94 alexgo author
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT GetObjectLink( IDataObject *pDataObj, STGMEDIUM *pmedium)
+{
+ HRESULT hresult;
+ IStream * pstm = NULL;
+ IMoniker * pmk = NULL;
+ CLSID clsid;
+ LPOLESTR pszFile = NULL,
+ pszClass = NULL,
+ pszItem = NULL;
+ LPSTR pszFileA = NULL,
+ pszClassA = NULL,
+ pszItemA = NULL,
+ pszObjectLink;
+ DWORD cbszFileA = 0,
+ cbszClassA = 0,
+ cbszItemA = 0;
+ LARGE_INTEGER li;
+ FORMATETC formatetc;
+
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN GetObjectLink ( %p , %p )\n", NULL,
+ pDataObj, pmedium));
+
+ Assert(pmedium->tymed == TYMED_HGLOBAL);
+
+ // fetch LinkSource data
+
+ INIT_FORETC(formatetc);
+ formatetc.cfFormat = g_cfLinkSource;
+ formatetc.tymed = TYMED_ISTREAM;
+
+ hresult = GetDataFromStream(pDataObj, &formatetc, NULL, &pstm);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // reset the stream seek pointer to the beginning
+
+ LISet32(li, 0);
+ hresult = pstm->Seek(li, STREAM_SEEK_SET, NULL);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // load the moniker from the stream, so we can parse out
+ // it's underlying file and item name
+
+ hresult = OleLoadFromStream(pstm, IID_IMoniker, (LPLPVOID)&pmk);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ hresult = Ole10_ParseMoniker(pmk, &pszFile, &pszItem);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // BUGBUG! we should call szFixNet here to turn a potential UNC
+ // filename into a drive letter combo. Some old OLE1 containers
+ // don't understand UNC filenames
+
+ // now fetch the class ID so we can construct the ClassName
+
+ hresult = ReadClassStm(pstm, &clsid);
+
+ if( hresult != NOERROR )
+ {
+ // it is possible that the stream does not contain
+ // the clsid of the link source. In this case, we should
+ // fetch it from the LinkSourceDescriptor
+
+ hresult = GetDataFromDescriptor(pDataObj, &clsid,
+ g_cfLinkSrcDescriptor,
+ USE_NORMAL_CLSID, NULL, NULL);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+ }
+
+ hresult = ProgIDFromCLSID(clsid, &pszClass);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // by this point, we should have all of our strings. Convert
+ // them to ANSI and stuff them in an hglobal.
+
+
+ hresult = UtPutUNICODEData(_xstrlen(pszClass)+1, pszClass, &pszClassA,
+ NULL, &cbszClassA);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+ else if( pszClassA == NULL )
+ {
+ hresult = ResultFromScode(E_FAIL);
+ goto errRtn;
+ }
+
+ hresult = UtPutUNICODEData(_xstrlen(pszFile)+1, pszFile, &pszFileA,
+ NULL, &cbszFileA);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // we are allowed to have a NULL item name
+
+ if( pszItem )
+ {
+ hresult = UtPutUNICODEData(_xstrlen(pszItem)+1, pszItem,
+ &pszItemA, NULL, &cbszItemA);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+ }
+
+ // we allocate 2 extra bytes for terminating '\0''s. (if the
+ // item name is NULL, we should be safe and terminate it with a
+ // zero as well, so we'll end up with 3 \0's at the end.
+ pmedium->hGlobal = GlobalAlloc((GMEM_MOVEABLE | GMEM_SHARE ),
+ cbszClassA + cbszFileA + cbszItemA + 2);
+
+ if( !pmedium->hGlobal )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ pszObjectLink = (LPSTR)GlobalLock(pmedium->hGlobal);
+
+ if( !pszObjectLink )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ _xmemcpy(pszObjectLink, pszClassA, cbszClassA);
+ pszObjectLink += cbszClassA;
+ _xmemcpy(pszObjectLink, pszFileA, cbszFileA);
+ pszObjectLink += cbszFileA;
+ if( pszItemA )
+ {
+ _xmemcpy(pszObjectLink, pszItemA, cbszItemA);
+ pszObjectLink += cbszItemA;
+ }
+ else
+ {
+ *pszObjectLink = '\0';
+ pszObjectLink++;
+ }
+
+ *pszObjectLink = '\0';
+
+ GlobalUnlock(pmedium->hGlobal);
+
+errRtn:
+ if( pmk )
+ {
+ pmk->Release();
+ }
+
+ if( pszClass )
+ {
+ PubMemFree(pszClass);
+ }
+
+ if( pszFile )
+ {
+ PubMemFree(pszFile);
+ }
+
+ if( pszItem )
+ {
+ PubMemFree(pszItem);
+ }
+
+ if( pszClassA )
+ {
+ PubMemFree(pszClassA);
+ }
+
+ if( pszFileA )
+ {
+ PubMemFree(pszFileA);
+ }
+
+ if( pszItemA )
+ {
+ PubMemFree(pszItemA);
+ }
+
+ if( pstm )
+ {
+ pstm->Release();
+ }
+
+ if( hresult != NOERROR )
+ {
+ if( pmedium->hGlobal )
+ {
+ GlobalFree(pmedium->hGlobal);
+ pmedium->hGlobal = NULL;
+ }
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT GetObjectLink ( %lx ) [ %lx ]\n",
+ NULL, hresult, pmedium->hGlobal));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetOwnerLink
+//
+// Synopsis: Synthesizes OLE1 OwnerLink format from ObjectDescriptor data
+//
+// Effects:
+//
+// Arguments: [pDataObj] -- the source data object
+// [pmedium] -- where to put the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: fetch the clsid and SrcOfCopy string from data offered
+// in cfObjectDescriptor. Then turn the class ID into
+// the prog ID and then turn all strings into ANSI. From
+// this, we can build the OwnerLink format data, which looks
+// like:
+// szClass\0SrcOfCopy\0\0\0
+//
+// History: dd-mmm-yy Author Comment
+// 10-Jun-94 alexgo author
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT GetOwnerLink( IDataObject *pDataObj, STGMEDIUM *pmedium)
+{
+ HRESULT hresult;
+ LPOLESTR pszSrcOfCopy = NULL,
+ pszClass = NULL;
+ LPSTR pszSrcOfCopyA = NULL,
+ pszClassA = NULL,
+ pszOwnerLink;
+ DWORD cbszClassA = 0,
+ cbszSrcOfCopyA;
+ CLSID clsid;
+
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN GetOwnerLink ( %p , %p )\n", NULL,
+ pDataObj, pmedium));
+
+ hresult = GetDataFromDescriptor(pDataObj, &clsid,
+ g_cfObjectDescriptor, USE_STANDARD_LINK,
+ &pszSrcOfCopy, NULL);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // 16bit code called wProgIDFromCLSID, but in when
+ // constructing ObjectLink, simply called ProgIDFromCLSID
+ // directly. The w version of the function special-cases
+ // the prog-id string for a Link object (specifically, "OLE2Link")
+
+ // we need to do it here to handle the case of copying an OLE2
+ // link object to an ole1 container, and then copying the object
+ // from the ole1 container back to an ole2 container.
+
+ hresult = wProgIDFromCLSID(clsid, &pszClass);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // now convert all our data to ANSI
+
+ hresult = UtPutUNICODEData(_xstrlen(pszClass)+1, pszClass,
+ &pszClassA, NULL, &cbszClassA);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ hresult = UtPutUNICODEData(_xstrlen(pszSrcOfCopy)+1, pszSrcOfCopy,
+ &pszSrcOfCopyA, NULL, &cbszSrcOfCopyA);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // now allocate an HGLOBAL for OwnerLink and stuff the
+ // string data in there. We alloc 2 extra bytes for
+ // the terminating NULL characters.
+
+ pmedium->hGlobal = GlobalAlloc((GMEM_MOVEABLE | GMEM_SHARE |
+ GMEM_ZEROINIT),
+ cbszClassA + cbszSrcOfCopyA + 2);
+
+ if( !pmedium->hGlobal )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ pszOwnerLink = (LPSTR)GlobalLock(pmedium->hGlobal);
+
+ if( !pszOwnerLink )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ _xmemcpy(pszOwnerLink, pszClassA, cbszClassA);
+ pszOwnerLink += cbszClassA;
+ _xmemcpy(pszOwnerLink, pszSrcOfCopyA, cbszSrcOfCopyA);
+ pszOwnerLink += cbszSrcOfCopyA;
+
+ *pszOwnerLink = '\0';
+ pszOwnerLink++;
+ *pszOwnerLink = '\0';
+
+ GlobalUnlock(pmedium->hGlobal);
+
+errRtn:
+
+ if( pszClass )
+ {
+ PubMemFree(pszClass);
+ }
+
+ if( pszSrcOfCopy )
+ {
+ PubMemFree(pszSrcOfCopy);
+ }
+
+
+ if( pszClassA )
+ {
+ PubMemFree(pszClassA);
+ }
+
+ if( pszSrcOfCopyA )
+ {
+ PubMemFree(pszSrcOfCopyA);
+ }
+
+ if( hresult != NOERROR )
+ {
+ if( pmedium->hGlobal )
+ {
+ GlobalFree(pmedium->hGlobal);
+ pmedium->hGlobal = NULL;
+ }
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT GetOwnerLink ( %lx ) [ %lx ]\n",
+ NULL, hresult, pmedium->hGlobal));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetPrivateClipboardWindow (internal)
+//
+// Synopsis: Finds the private ole-clipboard window associated with
+// the current appartment (creating one if necessary).
+//
+// Effects:
+//
+// Arguments: [fFlags] -- if CLIP_CREATEIFNOTTHERE, then a window
+// will be created if none already exists
+// if CLIP_QUERY, the current clipboard
+// window (if any) will be returned.
+//
+// Requires:
+//
+// Returns: HWND (NULL on failure)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Mar-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HWND GetPrivateClipboardWindow( CLIPWINDOWFLAGS fFlags )
+{
+ HWND hClipWnd = 0;
+ HRESULT hr;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN GetPrivateClipboardWindow ( %lx )\n",
+ NULL, fFlags));
+
+ COleTls tls(hr);
+ if (SUCCEEDED(hr))
+ {
+ hClipWnd = tls->hwndClip;
+
+ if( !hClipWnd && (fFlags & CLIP_CREATEIFNOTTHERE) )
+ {
+ // NOTE: do not need to Stack Switch since the
+ // the windows is in ole itself.
+
+ if (ClipboardInitialize())
+ {
+ hClipWnd = ClpCreateWindowEx(NULL,vszClipboardWndClass, NULL,
+ WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, NULL, NULL, g_hmodOLE2, NULL);
+
+ // if we can't create the window, print an error
+ LEERROR(!hClipWnd, "Unable to create private clipboard win");
+
+ // now set the hwnd into our thread-local storage
+ tls->hwndClip = hClipWnd;
+ }
+ }
+ }
+ LEDebugOut((DEB_ITRACE, "%p OUT GetPrivateClipboardWindow ( %lx )\n",
+ NULL, hClipWnd));
+
+
+ // hClipWnd should always be a valid window
+
+#if DBG ==1
+ if( hClipWnd )
+ {
+ Assert(IsWindow(hClipWnd));
+ }
+#endif // DBG == 1
+
+ return hClipWnd;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HandleFromHandle
+//
+// Synopsis: Calls IDataObject->GetData for the given format and returns
+// the resulting handle (duplicated if necessary).
+//
+// Effects:
+//
+// Arguments: [pDataObj] -- the source data object
+// [pformatetc] -- the formatetc
+// [pmedium] -- the tymed to use for GetData and where
+// to return the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: if data object sets pUnkForRelease after the GetData call,
+// we'll duplicate the returned data. Otherwise, we just pass
+// out the results of GetData
+//
+// History: dd-mmm-yy Author Comment
+// 11-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT HandleFromHandle(IDataObject *pDataObj, FORMATETC *pformatetc,
+ STGMEDIUM *pmedium)
+{
+ HRESULT hresult;
+ STGMEDIUM tempmedium;
+
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN HandleFromHandle ( %p , %p , %p )\n",
+ NULL, pDataObj, pformatetc, pmedium));
+
+ _xmemset(&tempmedium, 0, sizeof(STGMEDIUM));
+
+ hresult = pDataObj->GetData(pformatetc, &tempmedium);
+
+ if( hresult == NOERROR )
+ {
+ if( tempmedium.pUnkForRelease )
+ {
+ pmedium->hGlobal = OleDuplicateData(
+ tempmedium.hGlobal, pformatetc->cfFormat,
+ GMEM_MOVEABLE | GMEM_DDESHARE );
+
+ if( !pmedium->hGlobal )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ // fall through so we release the original
+ // data
+ }
+ // now release the original data
+ ReleaseStgMedium(&tempmedium);
+ }
+ else
+ {
+ pmedium->hGlobal = tempmedium.hGlobal;
+ }
+ }
+
+ // we don't ever try a GetDataHere for handles
+
+ LEDebugOut((DEB_ITRACE, "%p OUT HandleFromHandle ( %lx )\n",
+ hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: MapCFToFormatetc
+//
+// Synopsis: Given a clipboard format, find the corresponding formatetc
+// in our private data
+//
+// Effects:
+//
+// Arguments: [hClipWnd] -- the hwnd of our private clipboard window
+// [cf] -- the clipboard format in question
+// [pformatec] -- the formatetc to fill in
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 12-Aug-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT MapCFToFormatetc( HWND hClipWnd, UINT cf, FORMATETC *pformatetc )
+{
+FORMATETC * prgfetc;
+HRESULT hresult = S_FALSE;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN MapCFToFormatetc ( %x , %p )\n",
+ NULL, cf, pformatetc));
+
+ prgfetc = (FORMATETC *)GetProp( hClipWnd, pwszClipPrivateData );
+
+ LEERROR(!prgfetc, "No private clipboard data!!");
+
+ if( prgfetc )
+ {
+ for( ; prgfetc->cfFormat != 0; prgfetc++ )
+ {
+ if( prgfetc->cfFormat == cf )
+ {
+ *pformatetc = *prgfetc;
+
+ // Bug#8207 - Corel Draw puts an Aspect and lindex of 0 for the Formatetc.
+ // if we encounter an Aspect of zero make it DVASPECT_CONTENT.
+ if (0 == pformatetc->dwAspect)
+ {
+ pformatetc->dwAspect = DVASPECT_CONTENT;
+ pformatetc->lindex = -1;
+ }
+
+ hresult = S_OK;
+ break;
+ }
+ }
+ }
+
+ if( S_FALSE == hresult )
+ {
+ // The only time this should fail is if the caller asked for one of our synthesized OLE 1.0 formats.
+ AssertSz( (cf == g_cfObjectLink) || (cf == g_cfOwnerLink) || (cf == g_cfNative),"Unknown Format");
+
+ INIT_FORETC(*pformatetc);
+ pformatetc->cfFormat = cf;
+ pformatetc->tymed = TYMED_HGLOBAL;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT MapCFToFormatec ( )\n", NULL ));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+// Function: OleFlushClipboard
+//
+// Synopsis: Removes the data object from the clipboard (as the app is
+// going away). The formats it supports will be rendered on
+// the clipboard so that the data may still be 'pasted' by
+// other apps.
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires: the caller must be the owner of the clipboard
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: 1. Make sure the caller is the clipboard window owner
+// 2. flush format data onto the clipboard
+// 3. remove the clipboard data object
+//
+// History: dd-mmm-yy Author Comment
+// 16-Mar-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI OleFlushClipboard( void )
+{
+ OLETRACEIN((API_OleFlushClipboard, NOPARAM));
+
+ HRESULT hresult;
+ HWND hClipWnd;
+ UINT cf = NULL;
+ HANDLE handle;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleFlushClipboard ( )\n", NULL));
+
+
+ if( (hClipWnd = VerifyCallerIsClipboardOwner()) == NULL)
+ {
+ //caller is not the clipboard owner, so return with an
+ //error
+ hresult = ResultFromScode(E_FAIL);
+ goto errRtn;
+ }
+
+
+ //
+ //
+ // BEGIN: OPENCLIPBOARD
+ //
+ //
+
+ // now open the clipboard so we can add and remove data
+
+ hresult = OleOpenClipboard(hClipWnd, NULL);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // now go through all of the formats on the clipboard and render
+ // each one. Doing a GetClipboardData will force rendering for
+ // any as yet unrendered formats
+
+ while( (cf = SSEnumClipboardFormats(cf)) != NULL )
+ {
+ // we ignore the return of GetClipboardData. Even if
+ // fails, we ought to flush as many as we can and then
+ // remove our data object.
+
+ handle = SSGetClipboardData(cf);
+
+ LEWARN( !handle, "GetClipboardData failed!");
+ }
+ // now get rid of the data object on the clipboard && local
+ // clipboard window
+
+ hresult = RemoveClipboardDataObject(hClipWnd,
+ CLIPWND_REMOVEFROMCLIPBOARD);
+
+ // now close the clipboard
+ if( !SSCloseClipboard() )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: Can't close clipboard!\n"));
+ // if hresult != NOERROR, then RemoveClipboardDataObject
+ // failed--as it would be the first failure, we do not want
+ // to mask that error code with CLIPBRD_E_CANT_CLOSE.
+ if( hresult == NOERROR )
+ {
+ hresult = ResultFromScode(CLIPBRD_E_CANT_CLOSE);
+ }
+ }
+
+ //
+ //
+ // END: CLOSECLIPBOARD
+ //
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleFlushClipboard ( %lx )\n", NULL,
+ hresult));
+
+ OLETRACEOUT((API_OleFlushClipboard, hresult));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleGetClipboard
+//
+// Synopsis: Retrieves an IDataObject * from the clipboard.
+//
+// Effects:
+//
+// Arguments: [ppDataObj] -- where to put the data object pointer
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+// Excepting a hack for 16bit, we open the clipboard and
+// prefetch any private clipboard formats we may have
+// put there (currently g_cfDataObject and g_cfOlePrivateData).
+//
+// We then always create a fake data object to return to the
+// caller. The QueryInterface on this data object is tweaked
+// in such a way to preserve identity (see CClipDataObject::
+// QueryInterface). This fake data object always tries to
+// satisfy requests (such as QueryGetData) locally by using
+// information stored internally (from g_cfOlePrivateData) or
+// by looking on the clipboard. This has a significant
+// speed advantage. If there is a real data object on the
+// clipboard, then we will fetch the interface only when
+// needed. See clipdata.cpp for more details.
+//
+// To retrieve the marshalled IDataObject pointer, we first
+// look for g_cfDataObject on the clipboard and retrieve the
+// hGlobal associated with that format. The hGlobal contains
+// the window handle of the private clipboard window of the
+// process that called OleSetClipboard. We use this window
+// handle to RPC over to the server process and get the
+// IDataObject data transfer object. This is exactly the same
+// mechanism used by Drag'n'Drop. As mentioned above, we do
+// this only when necessary as an optimization.
+//
+// History: dd-mmm-yy Author Comment
+// 30-Jun-94 alexgo added a hack for hosehead 16bit apps
+// 16-May-94 alexgo reduced the amount of work done between
+// Open and CloseClipboard
+// 16-Mar-94 alexgo author
+//
+// Notes: We must only hold the clipboard open for a small amount of
+// time because apps are calling OleGetClipboard to poll the
+// clipboard state during idle time. If the clipboard is held
+// open for a long period of time, this leads to frequent
+// collisions between multiple apps running simultaneously.
+// In particular, we should not make any rpc's during the time
+// in which we hold the clipboard open.
+//
+// If we are in WOW and the caller of OleGetClipboard is
+// the clipboard owner, then we will simply return the data
+// object straight from our private clipboard window. We
+// need to do this because some 16bit apps (such as Project)
+// have broken reference counting. See comments below in
+// the code.
+//
+//--------------------------------------------------------------------------
+
+STDAPI OleGetClipboard( IDataObject **ppDataObj )
+{
+ HRESULT hresult;
+ HWND hClipWnd = NULL; // clipboard owner
+ HGLOBAL hOlePrivateData = NULL;
+ FORMATETC * prgFormats = NULL; // array of formats.
+ DWORD cFormats = 0; // count of formats in
+ // prgFormats
+
+ VDATEHEAP();
+
+ OLETRACEIN((API_OleGetClipboard, PARAMFMT("ppDataObj= %p"), ppDataObj));
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleGetClipboard ( %p )\n", NULL,
+ ppDataObj));
+
+ VDATEPTROUT_LABEL(ppDataObj, IDataObject *, errNoChkRtn, hresult);
+
+ *ppDataObj = NULL;
+
+ //
+ // HACK ALERT!!!!
+ //
+
+ // 16bit Project has a cute reference counting scheme; if they
+ // own the clipboard, they just call Release on the data object
+ // they put on the clipboard instead of the data object we
+ // return from OleGetClipboard (thanks guys).
+ //
+ // to work around this, if we are in wow and the caller owns
+ // the clipboard, we simply AddRef the data object given to us
+ // in OleSetClipboard and return it.
+ //
+ // We do NOT do this for 32bit OLE for several reasons:
+ // 1. Even though the caller owns the clipboard, he
+ // does not necessarily control the data object given to
+ // OleSetClipboard (for example, he can get a data object
+ // from IOO::GetClipboardData). Thus, it is important
+ // that we wrap the data object on the clipboard
+ // (see comments above in the algorithm section)
+ // 2. Hopefully, the new algorithm makes it harder for
+ // apps to get away with doing stupid stuff
+
+ if( IsWOWThread() )
+ {
+ hClipWnd = VerifyCallerIsClipboardOwner();
+
+ if( hClipWnd != NULL )
+ {
+ // the caller does own the clipboard, just
+ // return the data object put there
+
+ *ppDataObj = (IDataObject *)GetProp( hClipWnd,
+ CLIPBOARD_DATA_OBJECT_PROP);
+
+ if( *ppDataObj )
+ {
+ (*ppDataObj)->AddRef();
+ hresult = NOERROR;
+ // leave the OleGetClipboard
+ goto errRtn;
+
+ }
+
+ // else FALL-THROUGH!!
+ // This is the case where the clipboard has
+ // been flushed but the calling app is still the
+ // 'owner'. We need to construct a fake data
+ // object in this case.
+ }
+ }
+
+ //
+ //
+ // BEGIN: OPENCLIPBOARD
+ //
+ //
+
+ hresult = OleOpenClipboard(NULL, NULL);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // Try to fetch the formatetc data. Note that we may
+ // not need to use this data if we can successfully rpc
+ // over to the clipboard data source process to get the original
+ // data object.
+
+ // again, we don't worry about capturing errors here; if something
+ // fails, then prgFormats will remain NULL
+
+ if( SSIsClipboardFormatAvailable(g_cfOlePrivateData) )
+ {
+ HGLOBAL hOlePrivateData;
+ FORMATETC * pClipFormatetc;
+ FORMATETC * ptemp;
+
+ hOlePrivateData = SSGetClipboardData(g_cfOlePrivateData);
+
+ if( hOlePrivateData )
+ {
+
+ // hOlePrivateData is an hglobal with a
+ // zero terminated array of formatetcs in it.
+ //
+ // we count them up and copy into an
+ // *allocated* peice of memory, which may get passed
+ // to our fake clipboard data object.
+
+ pClipFormatetc =
+ (FORMATETC *)GlobalLock(hOlePrivateData);
+
+ LEERROR(pClipFormatetc == NULL, "GlobalLock failed!");
+
+ if( pClipFormatetc )
+ {
+ for( cFormats = 0, ptemp = pClipFormatetc;
+ ptemp->cfFormat != 0;
+ ptemp++ )
+ {
+ cFormats++;
+ }
+
+ if( cFormats > 0 )
+ {
+ prgFormats = (FORMATETC *)
+ PrivMemAlloc( cFormats *
+ sizeof(FORMATETC));
+
+ if( prgFormats )
+ {
+ _xmemcpy(prgFormats,
+ pClipFormatetc,
+ cFormats *
+ sizeof(FORMATETC));
+ }
+ }
+
+ GlobalUnlock(hOlePrivateData);
+ }
+ }
+ }
+
+ if( !SSCloseClipboard() )
+ {
+ LEDebugOut((DEB_ERROR, "ERROR: CloseClipboard failed!\n"));
+ ; // no-op to keep the compiler happy.
+ }
+
+
+ //
+ //
+ // END: CLOSECLIPBOARD
+ //
+ //
+
+ // Create our own clipboard data object. We always return
+ // our own data object to the caller
+
+ hresult = CClipDataObject::Create(ppDataObj,
+ prgFormats, cFormats);
+
+ // if the Create call succeeds, the fake data object
+ // will take ownership of the formatetc array. If it
+ // failed, we should free it.
+
+ if( hresult != NOERROR && prgFormats )
+ {
+ PrivMemFree(prgFormats);
+ }
+
+errRtn:
+
+#if DBG == 1
+ // make the data object is non-NULL on success and NULL on failure
+ if( hresult != NOERROR )
+ {
+ Assert(*ppDataObj == NULL);
+ }
+ else
+ {
+ Assert(*ppDataObj != NULL);
+ }
+#endif // DBG == 1
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleGetClipboard ( %lx ) [ %p ]\n",
+ NULL, hresult, *ppDataObj));
+
+ // register the new IDataObject interface for HookOle
+ CALLHOOKOBJECTCREATE(hresult,CLSID_NULL,IID_IDataObject,
+ (IUnknown **)ppDataObj);
+
+errNoChkRtn:
+
+ OLETRACEOUT((API_OleGetClipboard, hresult));
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleIsCurrentClipboard
+//
+// Synopsis: returns NOERROR if the given data object is still on the
+// clipboard, false otherwise.
+//
+// Effects:
+//
+// Arguments: [pDataObj] -- the data object to check against
+//
+// Requires: g_cfDataObject must be registered
+//
+// Returns: S_OK, S_FALSE
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: 1. Verify caller is the clipboard owner
+// 2. Compare the data object pointer on our private clipboard
+// window against the data object pointer given by the caller
+//
+// History: dd-mmm-yy Author Comment
+// 12-Aug-94 alexgo optimized
+// 16-Mar-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI OleIsCurrentClipboard( IDataObject *pDataObj )
+{
+ OLETRACEIN((API_OleIsCurrentClipboard, PARAMFMT("pDataObj= %p"), pDataObj));
+
+ HRESULT hresult = ResultFromScode(S_FALSE);
+ HWND hClipWnd;
+ IDataObject * pClipDataObject = NULL;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleIsCurrentClipboard ( %p )\n",
+ NULL, pDataObj));
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IDataObject,(IUnknown **)&pDataObj);
+
+ if( pDataObj == NULL )
+ {
+ Assert(hresult == ResultFromScode(S_FALSE));
+ goto errRtn;
+ }
+
+ // the caller must be the current clipboard owner
+
+ if( (hClipWnd = VerifyCallerIsClipboardOwner()) == NULL )
+ {
+ LEDebugOut((DEB_WARN,
+ "WARNING: Caller not clipboard owner\n"));
+ Assert(hresult == ResultFromScode(S_FALSE));
+ goto errRtn;
+ }
+
+
+ // In order for the data object to *really* be on the clipboard,
+ // the g_cfDataObject must have the HWND of the private clipboard
+ // window (even if we still have the DataObject pointer stuck
+ // on the private clipboard window)
+
+ // HOWEVER, the data on the clipboard may change at any point
+ // in time that we don't hold it open. In order to check this data,
+ // we'd have to open the clipboard (a shared resource). Since
+ // we don't get any useful information from this check, we don't
+ // bother doing it.
+
+
+ // now get the pointer property from the window
+
+ pClipDataObject = (IDataObject *)GetProp(hClipWnd,
+ CLIPBOARD_DATA_OBJECT_PROP);
+
+ // since we are in the same process, we can directly compare
+ // these pointers.
+ if( pClipDataObject == pDataObj)
+ {
+ hresult = NOERROR;
+ }
+ else
+ {
+ hresult = ResultFromScode(S_FALSE);
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleIsCurrentClipboard ( %lx )\n",
+ NULL, hresult));
+
+ OLETRACEOUT((API_OleIsCurrentClipboard, hresult));
+
+ return hresult;
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleOpenClipboard (internal)
+//
+// Synopsis: Opens the clipboard
+//
+// Effects:
+//
+// Arguments: [hClipWnd] -- open the clipboard with this window
+// may be NULL.
+// [phClipWnd] -- where to put the clipboard owner
+// may be NULL
+//
+// Requires:
+//
+// Returns: NOERROR: the clipboard was opened successfully
+// CLIPBRD_E_CANT_OPEN: could not open the clipboard
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: If we can't open the clipboard, we sleep for a bit and then
+// try again (in case we collided with another app). This
+// algorithm may need to be improved.
+//
+// History: dd-mmm-yy Author Comment
+// 17-May-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT OleOpenClipboard( HWND hClipWnd, HWND *phClipWnd )
+{
+ HRESULT hresult = NOERROR;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN OleOpenClipboard ( %p )\n", NULL,
+ phClipWnd ));
+
+ if( hClipWnd == NULL )
+ {
+ // go ahead and create a clipboard window if we don't already
+ // have one
+ hClipWnd = GetPrivateClipboardWindow(CLIP_CREATEIFNOTTHERE);
+ }
+
+ if( !hClipWnd )
+ {
+ hresult = ResultFromScode(E_FAIL);
+ }
+ else if( !SSOpenClipboard(hClipWnd) )
+ {
+ // OpenClipboard will fail if another window (i.e. another
+ // process or thread) has it open
+
+ // sleep for a bit and then try again
+
+ LEDebugOut((DEB_WARN, "WARNING: First try to open clipboard "
+ "failed!, sleeping 1 second\n"));
+
+ Sleep(0); // give up our time quanta and allow somebody
+ // else to get scheduled in.
+
+ if( !SSOpenClipboard(hClipWnd) )
+ {
+ LEDebugOut((DEB_WARN,
+ "WARNING: Unable to open clipboard on "
+ "second try\n"));
+ hresult = ResultFromScode(CLIPBRD_E_CANT_OPEN);
+ }
+ }
+
+ if( phClipWnd )
+ {
+ *phClipWnd = hClipWnd;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT OleOpenClipboard ( %lx ) "
+ "[ %p ]\n", NULL, hresult, (phClipWnd)? *phClipWnd : 0));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleSetClipboard
+//
+// Synopsis: puts the given IDataObject on the clipboard
+//
+// Effects:
+//
+// Arguments: [pDataObj] -- the data object to put on the clipboard
+// if NULL, the clipboard is cleared
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: 1. clear the clipboard of any data object and other data
+// that may be there.
+// 2. Set [pDataOjbect] as the new clipboard data object
+// 3. Set any downlevel formats on the clipboard for delayed
+// rendering.
+//
+// History: dd-mmm-yy Author Comment
+// 11-Apr-94 alexgo added support for downlevel formats
+// 24-Mar-94 alexgo allow NULL for pDataObject
+// 16-Mar-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI OleSetClipboard( IDataObject *pDataObject )
+{
+ OLETRACEIN((API_OleSetClipboard, PARAMFMT("pDataObject= %p"), pDataObject));
+
+ HRESULT hresult = NOERROR;
+ HWND hClipWnd;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleSetClipboard ( %p )\n", NULL,
+ pDataObject));
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IDataObject,(IUnknown **)&pDataObject);
+
+ //
+ //
+ // BEGIN: OPENCLIPBOARD
+ //
+ //
+
+ hresult = OleOpenClipboard(NULL, &hClipWnd);
+
+ if( hresult != NOERROR )
+ {
+ goto logRtn;
+ }
+
+ // now clear the data and take ownership of the clipboard with
+ // an EmptyClipboard call. Note that EmptyClipboard will call
+ // back to our private clipboard window proc (ClipboardWndProc)
+ // with a WM_DESTROYCLIPBOARD message. ClipboardWndProc will
+ // remove any existing data objects (and do the IDO->Release).
+
+ if( !SSEmptyClipboard() )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: Unable to empty clipboard\n"));
+ hresult = ResultFromScode(CLIPBRD_E_CANT_EMPTY);
+ goto errRtn;
+ }
+
+ // NULL is a legal value for pDataObject. Basically, it says
+ // "clear the clipboard" (which was done above in the EmptyClipboard
+ // call).
+
+ if( pDataObject )
+ {
+ // now we set the data object onto the clipboard
+
+ hresult = SetClipboardDataObject(hClipWnd, pDataObject);
+
+ if( hresult == NOERROR )
+ {
+ // now set all of our downlevel formats on the
+ // clipboard
+
+ hresult = SetClipboardFormats(hClipWnd, pDataObject);
+ }
+ }
+
+errRtn:
+ // now close the clipboard.
+
+ if( !SSCloseClipboard() )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: Unable to close clipboard\n"));
+
+ // don't overwrite an earlier error code!
+ if( hresult == NOERROR )
+ {
+ hresult = ResultFromScode(CLIPBRD_E_CANT_CLOSE);
+ }
+ }
+
+ //
+ //
+ // END: CLOSECLIPBOARD
+ //
+ //
+
+logRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleSetClipboard ( %p ) \n", NULL,
+ hresult));
+
+ OLETRACEOUT((API_OleSetClipboard, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: RemoveClipboardDataObject (internal)
+//
+// Synopsis: removes the g_cfDataObject format from the clipboard
+// along with the associated information on the private
+// clipboard window
+//
+// Effects: the DataObject pointer will be released.
+//
+// Arguments: [hClipWnd] -- handle to the private clipboard window
+// [fFlags] -- if CLIPWND_REMOVEFROMCLIPBOARD, then we
+// will remove g_cfDataObject from the clipboard
+//
+// Requires: the clipboard must be open
+// g_cfDataObject must be set
+//
+// Returns: HRESULT
+//
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: we first remove the g_cfDataObject format from the clipboard
+// if fFlags == CLIPWND_REMOVEFROMCLIPBOARD (see comments
+// regarding this in Notes) and then remove the properties on our
+// local private clipboard window, and finally release the data
+// object pointer
+//
+// History: dd-mmm-yy Author Comment
+// 16-Mar-94 alexgo author
+//
+// Notes: This function succeeds if there is no clipboard data object.
+//
+// OleSetClipboard also calls this function to remove any data
+// object that may be present from a previous OleSetClipboard
+// call. (Note that the call is indirect; OleSetClipboard will
+// call EmptyClipboard, which will get to our clipboard window
+// proc with a WM_DESTROYCLIPBOARD message). OleFlushClipboard
+// will also call this function.
+//
+// CLIPWND_REMOVEFROMCLIPBOARD (and CLIPWND_IGNORECLIPBOARD)
+// are used to handle the two different cases in which we
+// need to remove the clipboard data object:
+// 1. Somebody has called EmptyClipboard(). We will
+// get a WM_DESTROYCLIPBOARD message in our private
+// clipboard window proc. If we have an AddRef'ed
+// pointer on the clipboard (well, really on our
+// private clipboard window), it is imperative that
+// we do the corresponding Release. However, since
+// we are doing this as a result of EmptyClipboard,
+// there is no need to futz with data on the clipboard
+// (as it's all being deleted anyway).
+//
+// 2. We are in an OleFlushClipboard call. Here we
+// *want* the rest of the clipboard to remain (except
+// for our data object pointer), so we just need to
+// disable the g_cfDataObject information.
+// BUGBUG!! this is currently implemented by
+// EmptyClipboard, which will change once the data object
+// is implemented.
+//
+//--------------------------------------------------------------------------
+
+HRESULT RemoveClipboardDataObject( HWND hClipWnd, DWORD fFlags )
+{
+ HRESULT hresult = NOERROR;
+ IDataObject * pDataObj;
+ FORMATETC * prgformats = NULL;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN RemoveClipboardDataObject ( %lx , "
+ "%lx )\n", NULL, hClipWnd, fFlags ));
+
+ Assert(g_cfDataObject);
+
+ // get && remove the data object pointer. We rely on
+ // RemoveProp to correctly handle the race condition (somebody
+ // else doing a GetProp simultaneously with our call).
+
+ //
+ // We must not delete the property since some 16-bit applications
+ // rely on OleIsCurrentClipboard() during the IDataObject->Release().
+ //
+ pDataObj = (IDataObject *)GetProp(hClipWnd, CLIPBOARD_DATA_OBJECT_PROP);
+
+ // now get && remove && free our private clipboard data
+
+ if( GetProp( hClipWnd, pwszClipPrivateData) != 0 )
+ {
+ prgformats = (FORMATETC *)RemoveProp( hClipWnd, pwszClipPrivateData);
+ }
+
+ if( prgformats )
+ {
+ PrivMemFree(prgformats);
+ }
+
+ // if there is no data object, then we may have already
+ // removed it (from a previous call here).
+
+ if( pDataObj )
+ {
+ DWORD dwAssignAptID;
+
+ // pDataObj was AddRef'ed in SetClipboardDataObject
+ if( !(fFlags & CLIPWND_DONTCALLAPP) )
+ {
+ pDataObj->Release();
+ }
+
+
+ // now get rid of our endpoint property. If pDataObj is
+ // NULL, then there is no need to do this (which is why the
+ // call is in this if block!)
+
+ hresult = UnAssignEndpointProperty(hClipWnd,&dwAssignAptID);
+
+ //
+ // Now we can remove the property after the IDataObject->Release().
+ //
+ RemoveProp(hClipWnd, CLIPBOARD_DATA_OBJECT_PROP);
+ }
+ // else HRESULT == NOERROR from initialization
+
+ if( (fFlags & CLIPWND_REMOVEFROMCLIPBOARD) &&
+ SSIsClipboardFormatAvailable(g_cfDataObject) )
+ {
+ HGLOBAL hMem;
+ HWND * phMem;
+
+ // since we can't simply remove g_cfDataObject from the clipboard
+ // (and keep all the other formats), we'll simply replace
+ // the value (the HWND of our private clipboard window) with a
+ // NULL. Note that we only do this if g_cfDataObject really
+ // exists on the clipboard (see the conditional test above)
+
+ hMem = GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE,
+ sizeof(HWND));
+
+ if( !hMem )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: GlobalAlloc failed!!"
+ "\n"));
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ // keep trying to remove the rest of our state
+ goto errRtn;
+ }
+
+ phMem = (HWND *)GlobalLock(hMem);
+
+ if( !phMem )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: GlobalLock failed!!"
+ "\n"));
+ GlobalFree(hMem);
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ // keep trying to remove the rest of our state
+ goto errRtn;
+ }
+
+ *phMem = NULL;
+
+ GlobalUnlock(hMem);
+
+ if( !SSSetClipboardData(g_cfDataObject, hMem) )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: Can't RESET clipboard"
+ " data with SetClipboardData\n"));
+ GlobalFree(hMem);
+
+ // FALL THROUGH!! This is deliberate. Even if
+ // we can't NULL out the data on the clipboard, we
+ // ought to at least try to remove the rpc endpoints
+ // and so forth on our private clipboard window.
+ }
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT RemoveClipboardDataObject ( %lx )\n",
+ NULL, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: RenderFormat, private
+//
+// Synopsis: Grab the content data for the given clipboard format and
+// put it on the clipboard
+//
+// Effects:
+//
+// Arguments: [hClipWnd] -- the clipboard window
+/// [pDataObj] -- the data object from which to get the
+// data
+// [cf] -- the clipboard format to put on the
+// clipboard
+//
+// Requires: the clipboard must be open for this function to work
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: if format ==
+// g_cfNative:
+// copy either OLE10_NATIVE_STREAM (if available) into
+// an hglobal or put the entire storage from EmbedSource
+// or EmbeddedObject on top an hglobal
+// g_cfOwnerLink:
+// synthesize from g_cfObjectDescriptor
+// g_cfObjectLink:
+// synthesize from g_cfLinkSource if not offered
+// directly by the app
+// all others:
+// find the formatetc corresponding to the clipboard
+// format and ask for data directly using that
+// formatetc. In the case of multiple TYMED's, we
+// prefer TYMED_ISTORAGE, then TYMED_ISTREAM, then
+// handle based mediums. TYMED_FILE is not supported.
+//
+// History: dd-mmm-yy Author Comment
+// 11-Aug-94 alexgo optimized; now use the object's original
+// formatetc for GetData calls.
+// 10-Jun-94 alexgo added OLE1 support
+// 11-Apr-94 alexgo author
+//
+// Notes: In the ideal world, we simply ask for TYMED_HGLOBAL and
+// DVASPECT_CONTENT and then stuff the resulting hglobal onto
+// the clipboard. However, this would require apps honoring
+// the contractual obligations of an interface, which, of course,
+// doesn't happen.
+//
+// The 16bit code effectively special cased certain formats,
+// notably cfEmbeddedOjbect, g_cfLinkSource, and g_cfEmbedSource.
+// The algorithm above implements behaviour similar to the
+// 16bit sources. Note that new apps can take advantage of
+// this functionality for app-defined formats and simplify
+// their data transfer IDataObject implementations.
+//
+//--------------------------------------------------------------------------
+
+HRESULT RenderFormat( HWND hClipWnd, UINT cf, IDataObject *pDataObj )
+{
+HRESULT hresult = E_FAIL;
+STGMEDIUM medium;
+FORMATETC formatetc;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN RenderFormat ( %u , %p )\n", NULL,
+ cf, pDataObj));
+
+
+ _xmemset(&medium, 0, sizeof(STGMEDIUM));
+ medium.tymed = TYMED_HGLOBAL;
+
+ if( cf == g_cfNative )
+ {
+ // OLE1 format: synthesize from OLE2 data
+ hresult = GetNative(pDataObj, &medium);
+ }
+ else if( cf == g_cfOwnerLink )
+ {
+ // OLE1 format: synthesize from OLE2 data
+ hresult = GetOwnerLink(pDataObj, &medium);
+ }
+ else if( cf == g_cfObjectLink )
+ {
+ // ObjectLink is a special OLE1 format. The 16bit OLE
+ // allowed apps to pass their own ObjectLink data, so
+ // we preserve that behaviour here. First check to see
+ // if we can fetch it directly; if not, then we synthesize
+ // it.
+
+ Assert(NOERROR != hresult);
+
+ if(S_OK == MapCFToFormatetc(hClipWnd, cf, &formatetc))
+ {
+ hresult = HandleFromHandle(pDataObj, &formatetc, &medium);
+ }
+
+ if(NOERROR != hresult)
+ {
+ hresult = GetObjectLink(pDataObj, &medium);
+ }
+ }
+ else if( cf == g_cfScreenPicture && IsWOWThread() )
+ {
+ //
+ // HACK ALERT!!!
+ //
+
+ // this is a really evil hack. XL 16bit puts a data format
+ // "Screen Picture" on the clipboard (which is really nothing
+ // more than a metafile). However, since neither OLE nor
+ // Windows knows anything about this metafile (it's just a
+ // 4byte number to us), the metafile is invalid after XL shuts
+ // down.
+ //
+ // The cute part is that Word 6 uses Screen Picture data
+ // first (even if it' is invalid). As a result, without
+ // this hack, you can't paste any objects from XL into Word after
+ // XL has shut down.
+ //
+ // The hack is to never allow "Screen Picture" data to ever be
+ // realized onto the clipboard. Word 6 then defaults to its
+ // "normal" OLE2 processing.
+
+ hresult = E_FAIL;
+ }
+ else
+ {
+ // find the original formatetc given to us by the data
+ // object and use that to fetch the data
+
+ Assert(NOERROR != hresult);
+
+ if (S_OK == MapCFToFormatetc(hClipWnd, cf, &formatetc))
+ {
+ // get the data according to the medium specified in formatetc
+
+ if( (formatetc.tymed & TYMED_ISTORAGE) )
+ {
+ hresult = GetDataFromStorage(pDataObj, &formatetc,
+ &medium, NULL);
+ }
+ else if( (formatetc.tymed & TYMED_ISTREAM) )
+ {
+ hresult = GetDataFromStream(pDataObj, &formatetc,
+ &medium, NULL);
+ }
+ else
+ {
+ // we don't support TYMED_FILE
+ formatetc.tymed &= ~(TYMED_FILE);
+
+ // we don't need to do any more checking on the
+ // formatetc. Even if we have a 'bogus' formatetc,
+ // it's what the app told us it could support.
+
+ hresult = HandleFromHandle(pDataObj, &formatetc,
+ &medium);
+ }
+ }
+
+ }
+
+ // if hresult is NOERROR, then we have successfully retrieved
+ // an HGLOBAL that can simply be stuffed onto the clipboard.
+
+ if(NOERROR == hresult)
+ {
+
+ Assert(NULL != medium.hGlobal);
+
+ if( !SSSetClipboardData(cf, medium.hGlobal ) )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: SetClipboardData "
+ "failed!\n"));
+
+ // Dump any memory we're hanging onto
+ if (GMEM_INVALID_HANDLE != GlobalFlags(medium.hGlobal))
+ {
+ ReleaseStgMedium(&medium);
+ }
+
+ hresult = ResultFromScode(CLIPBRD_E_CANT_SET);
+ }
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT RenderFormat ( %lx )\n", NULL,
+ hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SetClipboardDataObject (internal)
+//
+// Synopsis: Puts an IDataObject on the private clipboard window
+// and a handle to the clipboard window on the clipboard
+//
+// Effects: pDataObject will get AddRef'ed
+//
+// Arguments: [hClipWnd] -- handle to the private clipboard window
+// [pDataObject] -- the data object
+//
+// Requires: the clipboard must be open
+// g_cfDataObject must already be registered
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: We take the private clipboard window (passed as an
+// argument) and put the data object pointer on it
+// it as a private property. We also attach an rpc endpoint
+// to this window as a public property and then put the
+// window handle on the clipboard. OleGetClipboard will
+// retrieve this window handle, get the rpc endpoint, and
+// rpc over here (the set clipboard process) to get the
+// IDataObject pointer (marshalled, of course ;-)
+//
+// History: dd-mmm-yy Author Comment
+// 16-Mar-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT SetClipboardDataObject( HWND hClipWnd ,
+ IDataObject *pDataObject )
+{
+HRESULT hresult;
+HWND * phMem;
+HANDLE hMem;
+DWORD dwAssignAptID;
+
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN SetClipboardDataObject ( %lx ,%p )\n",
+ NULL, hClipWnd, pDataObject ));
+
+ AssertSz(pDataObject, "Invalid data object");
+ Assert(g_cfDataObject);
+
+ // try to assign an endpoint property to the window
+
+ if( (hresult = AssignEndpointProperty(hClipWnd)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ // put the data object pointer on the window
+
+ if( !SetProp(hClipWnd, CLIPBOARD_DATA_OBJECT_PROP, pDataObject) )
+ {
+
+ // uh-oh, try to back out, but don't worry if we fail
+ // from now on.
+ LEDebugOut((DEB_WARN, "WARNING: Unable to SetProp for the "
+ "data object pointer\n"));
+ UnAssignEndpointProperty(hClipWnd,&dwAssignAptID);
+ hresult = ResultFromScode(E_FAIL);
+ goto errRtn;
+ }
+
+ // now allocate memory for the HWND of the private clipboard
+ // window and put that on the clipboard
+
+ hMem = GlobalAlloc( GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(HWND));
+
+ if( !hMem )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: GlobalAlloc failed!!\n"));
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto cleanup;
+ }
+
+ phMem = (HWND *)GlobalLock(hMem);
+
+ if( !phMem )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: GlobalLock failed!!\n"));
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto cleanup;
+ }
+
+ *phMem = hClipWnd;
+
+ GlobalUnlock(hMem);
+
+ if( !SSSetClipboardData( g_cfDataObject, hMem ) )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: SetClipboardData for "
+ "g_cfDataObject failed (%lx) !!\n", GetLastError()));
+ hresult = ResultFromScode(CLIPBRD_E_CANT_SET);
+ goto cleanup;
+ }
+
+ pDataObject->AddRef();
+
+ hresult = NOERROR;
+
+ goto errRtn;
+
+cleanup:
+
+ UnAssignEndpointProperty(hClipWnd,&dwAssignAptID);
+
+ RemoveProp(hClipWnd, CLIPBOARD_DATA_OBJECT_PROP);
+ if( hMem )
+ {
+ GlobalFree(hMem);
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT SetClipboardDataObject ( %lx )\n",
+ NULL, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SetClipboardFormats
+//
+// Synopsis: enumerates the formats available from the data object and
+// sets up the clipboard to delay-render those formats.
+//
+// Effects:
+//
+// Arguments: [hClipWnd] -- the clipboard window
+// [pDataObj] -- the data object
+//
+// Requires: the clipboard must be open
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Simply enumerate all of the formats available on the object
+// and set each up for delayed rendereing (via
+// SetClipboardData(cf, NULL)). We also keep track of the
+// "real" formatetc for each clipboard format that we'll render.
+// These formatetc's are placed in an array and put on the
+// clipboard as g_cfOlePrivateData.
+//
+// See Notes below for more discussion on this.
+//
+// OLE1 support: In order to allow OLE1 containers to
+// paste OLE2 objects, we have to offer OLE1 formats in addition
+// to OLE2 data. We'll offer OLE1 formats as follows:
+//
+// g_cfNative: if either EmbedSource or EmbeddedObject
+// is available AND we can offer OwnerLink
+// g_cfOwnerLink: if ObjectDescriptor is available AND
+// we can offer Native
+// g_cfObjectLink: if LinkSource is available
+//
+// We will offer the formats in in the order above.
+//
+// History: dd-mmm-yy Author Comment
+// 4/13/95 rogerg Bug#10731 Graph 5.0 does not Include
+// its ObjectDescriptor in its enumerator
+// 22-Feb-95 alexgo restored broken 16bit behavior to
+// make Lotus Freelance work
+// 11-Apr-94 alexgo author
+//
+// Notes: For every clipboard format, we could do a QueryGetData
+// to see if RenderFormat would actually succeed. However,
+// this relies on the QueryGetData from the app to be both
+// fast and accurate (definitely an unwarranted assumption).
+//
+// Of course, by *not* doing a QueryGetData, we are assuming
+// that the formats enumerated by the data object are all
+// "legal" for clipboard transmission.
+//
+// The "real" purpose of g_cfOlePrivateData is to allow us to
+// determine whether private clipboard formats where originally
+// IStorage based. This is especially important for
+// OleFlushClipboard and copy/pasting mutiple objects. Transfer
+// of multiple objects relies on private clipboard formats, which,
+// in some apps, are only available on IStorage.
+//
+// These same apps rely on the Formatetc enumerator (or
+// QueryGetData) to tell them that the private format is available
+// on a storage (since it wasn't always in 16bit OLE). Since we
+// *can* offer it to them on a storage (see clipdata.cpp), it
+// is important that we preserve the fact that the data originally
+// came from a storage.
+//
+// Instead of always *testing* the data at enumerator or Query
+// time, we simply save the formatetc now (with [potentially]
+// modified fields such as ptd).
+//
+// Also note that RenderFormat uses the information in
+// OlePrivateData when trying to render clipboard formats.
+//
+//--------------------------------------------------------------------------
+
+HRESULT SetClipboardFormats( HWND hClipWnd, IDataObject *pDataObj )
+{
+ IEnumFORMATETC * pIEnum;
+ HRESULT hresult;
+ FORMATETC formatetc;
+ HGLOBAL hglobal, hcopy;
+ FORMATETC * prgFormats;
+ FORMATETC * prgFormatsCopy;
+ DWORD cFormats = 0;
+ DWORD cFormatsCopy = 0;
+ BOOL fOfferNative = FALSE,
+ fOfferedNative = FALSE,
+ fOfferObjectLink = FALSE;
+ CLSID clsid;
+ DWORD dwStatus;
+ BOOL fHaveObjectDescriptor=FALSE;
+
+ VDATEHEAP();
+
+
+ LEDebugOut((DEB_ITRACE, "%p _IN SetClipboardFormats ( %p )\n",
+ NULL, pDataObj));
+
+
+
+ // get the formatetc enumerator
+
+ hresult = pDataObj->EnumFormatEtc(DATADIR_GET, &pIEnum);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // count up the available formats
+
+ while( (hresult = pIEnum->Next(1, &formatetc, NULL)) == NOERROR )
+ {
+ if( formatetc.ptd )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: Non-NULL ptd!\n"));
+ PubMemFree(formatetc.ptd);
+ }
+ cFormats++;
+
+ if (g_cfObjectDescriptor == formatetc.cfFormat)
+ fHaveObjectDescriptor = TRUE;
+
+ }
+
+ pIEnum->Reset();
+
+ // Bug#10731 - If no ObjectDescriptor in Enumertor increment cFormats in case we have to add it
+ // when we add the EmbedSource
+ if (!fHaveObjectDescriptor)
+ cFormats++;
+
+ // for our locally cached copy of the formats
+ prgFormatsCopy = (FORMATETC *)PrivMemAlloc(
+ (cFormats + 1)*sizeof(FORMATETC));
+
+ if( prgFormatsCopy == NULL )
+ {
+ hresult = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ cFormatsCopy = cFormats;
+
+ // since some of these may be duplicated clipboard formats, we
+ // are potentially allocating more memory than we need, but that's
+ // OK.
+
+ hglobal = GlobalAlloc((GMEM_MOVEABLE | GMEM_DDESHARE),
+ (cFormats +1)*sizeof(FORMATETC));
+
+ prgFormats = (FORMATETC *)GlobalLock(hglobal);
+
+
+
+ if( prgFormats == NULL )
+ {
+ GlobalFree(hglobal);
+ pIEnum->Release();
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ _xmemset(prgFormats, 0, (cFormats + 1)*sizeof(FORMATETC));
+
+ cFormats = 0;
+
+ while( (hresult = pIEnum->Next(1, &formatetc, NULL)) ==
+ NOERROR )
+ {
+ // Excel5, 16bit, would offer data in it's enumerator
+ // that you couldn't actually fetch. Since this causes
+ // Paste Special behaviour to be broken, we have to fix it
+ // here.
+
+ if( IsWOWThread() )
+ {
+ hresult = pDataObj->QueryGetData(&formatetc);
+
+ if( hresult != NOERROR )
+ {
+ // free the target device (if there
+ // is one)
+
+ if( formatetc.ptd )
+ {
+ LEDebugOut((DEB_WARN,
+ "WARNING: Non-NULL ptd!\n"));
+ PubMemFree(formatetc.ptd);
+ }
+
+ continue;
+ }
+ }
+
+ if( formatetc.ptd )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: Non-NULL ptd!\n"));
+ PubMemFree(formatetc.ptd);
+ formatetc.ptd = NULL;
+ }
+
+ // we first need to check to see if the clipboard format is a
+ // user-defined GDI format. We do not know how to duplicate
+ // these, so we can't satisfy the GetData request.
+
+ if( formatetc.cfFormat >= CF_GDIOBJFIRST &&
+ formatetc.cfFormat <= CF_GDIOBJLAST )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: caller attempted to "
+ "use a special GDI format (%lx)\n",
+ formatetc.cfFormat));
+
+ // keep going though and get the rest of the clipboard
+ // formats
+ continue;
+ }
+
+ // HACK ALERT!!!
+ if( IsWOWThread() )
+ {
+ // Word6 offers CF_BITMAP on HGLOBAL in it's enumerator
+ // but only succeeds the GetData call if TYMED_GDI is
+ // specified. So patch up the formatetc to reflect
+ // something more accurate.
+
+ if( (formatetc.cfFormat == CF_BITMAP ||
+ formatetc.cfFormat == CF_PALETTE ) &&
+ formatetc.tymed == TYMED_HGLOBAL )
+ {
+ formatetc.tymed = TYMED_GDI;
+ }
+ }
+
+ // determine if we should offer any OLE1 formats as well
+
+ if( formatetc.cfFormat == g_cfEmbeddedObject ||
+ formatetc.cfFormat == g_cfEmbedSource )
+ {
+ fOfferNative = TRUE;
+ }
+ else if( formatetc.cfFormat == g_cfLinkSource )
+ {
+ fOfferObjectLink = TRUE;
+ // if the app offers ObjectLink itself, then we'll
+ // consider a private clipboard format and set
+ // it up for delayed rendering as any other format.
+ // We'll check for this down below.
+ }
+
+ // if we haven't already setup this clipboard format, do
+ // so now.
+ if( !SSIsClipboardFormatAvailable(formatetc.cfFormat) )
+ {
+
+ // Bug#10731 If we are adding the EmbedSource but there was no Object Descriptor in
+ // the Enumerator, see if we can add the Object Descriptor now.
+
+ if ( (formatetc.cfFormat == g_cfEmbedSource) && !fHaveObjectDescriptor)
+ {
+ FORMATETC fetcObjDescriptor;
+
+ fetcObjDescriptor.cfFormat = g_cfObjectDescriptor;
+ fetcObjDescriptor.ptd = NULL;
+ fetcObjDescriptor.dwAspect = DVASPECT_CONTENT;
+ fetcObjDescriptor.lindex = -1;
+ fetcObjDescriptor.tymed = TYMED_HGLOBAL ;
+
+ if ( SUCCEEDED(pDataObj->QueryGetData(&fetcObjDescriptor)) )
+ {
+ SSSetClipboardData(g_cfObjectDescriptor, NULL);
+ prgFormats[cFormats] = fetcObjDescriptor;
+ cFormats++;
+ }
+
+ }
+
+ // Bug#18669 - if dwAspect was set to NULL the 16 bit dlls would
+ // set it to content.
+ if ( (NULL == formatetc.dwAspect) && IsWOWThread() )
+ {
+ formatetc.dwAspect = DVASPECT_CONTENT;
+ formatetc.lindex = -1; // CorelDraw also has a lindex of 0.
+ }
+
+ // no way to catch any errors
+ SSSetClipboardData(formatetc.cfFormat, NULL);
+ prgFormats[cFormats] = formatetc;
+ cFormats++;
+ }
+
+ // HACK ALERT!!!! Lotus Freelance 2.1 depends on getting
+ // cfNative *before* presentation formats (like CF_METAFILEPICT).
+ // Therefore, we emulate OLE16 behaviour and offer cfNative
+ // and cfOwnerLink immediately *after* cfEmbeddedObject or
+ // cfEmbedSource.
+ //
+ // NB! This hack destroys the exact ordering of formats
+ // offered by the data object given in OleSetClipboard
+
+ if( fOfferNative && !fOfferedNative )
+ {
+ // even if the calls below fail, don't put OLE1 formats
+ // the clipboard again.
+
+ fOfferedNative = TRUE;
+ // this call will fail if CF_OBJECTDESCRIPTOR is not
+ // available
+
+ hresult = GetDataFromDescriptor(pDataObj, &clsid,
+ g_cfObjectDescriptor,
+ USE_NORMAL_CLSID, NULL, NULL);
+
+ // we do not want static objects like metafiles and
+ // dib's to be treated as embeddings by OLE1 containers.
+ // They will be able to better handle the data as just
+ // a plain metafile
+
+ if( hresult == NOERROR &&
+ !IsEqualCLSID(clsid, CLSID_StaticMetafile) &&
+ !IsEqualCLSID(clsid, CLSID_StaticDib) &&
+ !IsEqualCLSID(clsid, CLSID_Picture_EnhMetafile))
+ {
+ SSSetClipboardData(g_cfNative, NULL);
+ SSSetClipboardData(g_cfOwnerLink, NULL);
+ }
+ }
+
+ }
+
+ // we don't need to do this now because we'll reset hresult
+ // to NOERROR below. Note that this does mean that we'll
+ // ignore any failure from the enumerator. We do this for two
+ // reasons:
+ // 1. The enumerator really should *not* fail on anything;
+ // all it should do is memcmp some stuff into the formatetc
+ // that we pass in. If it decides to fail at some point,
+ // then we'll just put on the clipboard whatever was
+ // enumerated 'til that point.
+ // 2. It is too late (88/28/94) to change for NT3.5 This
+ // behaviour (ingnoring failure) has been around for a while
+ // (see reason #1). It is possible that some apps are
+ // returning failure instead of S_FALSE to terminate.
+ // If we checked for failure and returned, we'd break those
+ // apps.
+ //
+ //if( hresult == ResultFromScode(S_FALSE) )
+ //{
+ // this is OK, means the enumerator terminated successfully
+ // hresult = NOERROR;
+ //}
+
+ pIEnum->Release();
+
+ // now keep a copy of the formats locally
+
+ _xmemcpy(prgFormatsCopy, prgFormats, (cFormatsCopy + 1)*sizeof(FORMATETC));
+
+ GlobalUnlock(hglobal);
+
+ // now set up any OLE1 formats we might need to offer.
+
+
+ // if the app offers ObjectLink itself, then we will have already
+ // set it up for delayed rendering in the enumerator loop above
+
+ if( fOfferObjectLink && !SSIsClipboardFormatAvailable(g_cfObjectLink) )
+ {
+ hresult = GetDataFromDescriptor(pDataObj, NULL,
+ g_cfLinkSrcDescriptor,
+ USE_NORMAL_CLSID, NULL, &dwStatus);
+
+ // there are some kinds of links that can't be linked to
+ // by OLE1 containers. Non-filename links (e.g. a progid
+ // moniker) and links to embeddings are common examples.
+
+ // Clipboard source providers indicate this state by
+ // setting the OLEMISC_CANLINKBYOLE1 bit in the status
+ // field of LinkSourceDescriptor
+
+ if( hresult == NOERROR && (dwStatus & OLEMISC_CANLINKBYOLE1) )
+ {
+ SSSetClipboardData(g_cfObjectLink, NULL);
+ }
+ }
+
+ // even if the calls to GetDataFromDescriptor failed above, it only
+ // means that we can't render OLE1 formats. This is OK.
+
+ hresult = NOERROR;
+
+ // now stuff the formatetc's on the clipboard and our private
+ // clipboard window (for use by RenderFormat).
+
+
+ if( !SetProp(hClipWnd, pwszClipPrivateData, (HANDLE)prgFormatsCopy) )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: SetProp to clipboard "
+ "window failed!\n"));
+ GlobalFree(hglobal);
+ PrivMemFree(prgFormatsCopy);
+ hresult = ResultFromScode(E_FAIL);
+ goto errRtn;
+ }
+
+ if( !SSSetClipboardData(g_cfOlePrivateData, hglobal) )
+ {
+ GlobalFree(hglobal); // on success, the clipboard will
+ // take ownership of our hglobal.
+
+ LEDebugOut((DEB_WARN, "WARNING: Unable to set clipboard "
+ "formats!\n"));
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT SetClipboardFormats ( %lx )\n", NULL,
+ hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: VerifyCallerIsClipboardOwner (internal)
+//
+// Synopsis: Checks to make sure the caller is the clipboard owner
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HWND to the private clipboard window (the owner of the
+// clipboard) upon success
+// NULL on failure.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 16-Mar-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HWND VerifyCallerIsClipboardOwner( void )
+{
+ HWND hClipWnd,
+ hWndClipOwner;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN VerifyCallerIsClipboardOwner ( )\n",
+ NULL ));
+
+ // don't create a window if none exists
+ hClipWnd = GetPrivateClipboardWindow( CLIP_QUERY );
+
+ if( hClipWnd )
+ {
+
+ hWndClipOwner = SSGetClipboardOwner();
+
+ if( hClipWnd != hWndClipOwner )
+ {
+ // caller is not owner, return NULL
+ hClipWnd = NULL;
+ }
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT VerifyCallerIsClipboardOwner "
+ "( %lx )\n", NULL, hClipWnd));
+
+ return hClipWnd;
+}
diff --git a/private/ole32/ole232/clipbrd/clipbrd.cpp b/private/ole32/ole232/clipbrd/clipbrd.cpp
new file mode 100644
index 000000000..3b53198df
--- /dev/null
+++ b/private/ole32/ole232/clipbrd/clipbrd.cpp
@@ -0,0 +1,3815 @@
+
+#define STATIC
+//+----------------------------------------------------------------------------
+//
+// File:
+// clipbrd.cpp
+//
+// Contents:
+// OLE2 clipboard handling
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 24-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocation
+// 01/11/94 - alexgo - added VDATEHEAP macro to every function
+// 12/31/93 - ChrisWe - fixed string argument to Warn(); did some
+// additional cleanup and formatting
+// 12/08/93 - ChrisWe - added necessary casts to GlobalLock() calls
+// resulting from removing bogus GlobalLock() macros in
+// le2int.h
+// 12/08/93 - continuing cleanup
+// 12/07/93 - ChrisWe - format some functions, free handle on
+// error condition (GlobalLock() failure) in MakeObjectLink
+// 12/06/93 - ChrisWe - begin file cleanup; use new map_uhw.h to
+// avoid bogus unions in Clipboard functions
+// 11/28/93 - ChrisWe - make default parameter explicit on
+// UtDupGlobal call
+// 11/22/93 - ChrisWe - replace overloaded ==, != with
+// IsEqualIID and IsEqualCLSID
+//
+//-----------------------------------------------------------------------------
+
+#include <le2int.h>
+#pragma SEG(clipbrd)
+
+#include <map_uhw.h>
+#include <create.h>
+#include <clipbrd.h>
+#include <scode.h>
+#include <objerror.h>
+#include <reterr.h>
+#include <ole1cls.h>
+#include <ostm2stg.h>
+// REVIEW #include "cmonimp.h" // for CreateOle1FileMoniker()
+
+#ifdef _MAC
+# include <string.h>
+# pragma segment ClipBrd
+
+// On the Macintosh, the clipboard is always open. We define a macro for
+// OpenClipboard that returns TRUE. When this is used for error checking,
+// the compiler should optimize away any code that depends on testing this,
+// since it is a constant.
+# define OpenClipboard(x) TRUE
+
+// On the Macintosh, the clipboard is not closed. To make all code behave
+// as if everything is OK, we define a macro for CloseClipboard that returns
+// TRUE. When this is used for error checking, the compiler should optimize
+// away any code that depends on testing this, since it is a constant.
+# define CloseClipboard() TRUE
+
+#endif // _MAC
+
+ASSERTDATA
+
+#ifdef MAC_REVIEW
+ All code is commented out for MAC currently. It is very Windows
+ specific, and has to written for MAC.
+#endif
+
+// declarations of local functions
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// wNativeStreamToHandle, static
+//
+// Synopsis:
+// Reads the contents of a length prefixed stream into a piece
+// of HGLOBAL memory.
+//
+// Arguments:
+// [pstm] -- pointer to the IStream instance to read material
+// from; the stream should be positioned just before
+// the length prefix
+// [ph] -- pointer to where to return the handle to the allocated
+// HGLOBAL.
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// REVIEW, this looks like something that should be a Ut function
+//
+// History:
+// 12/13/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+STATIC INTERNAL wNativeStreamToHandle(LPSTREAM pstm, LPHANDLE ph);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// wStorageToHandle, static
+//
+// Synopsis:
+// Copy an IStorage instance to a (new) handle.
+//
+// The contents of the IStorage instance are duplicated in
+// a new HGLOBAL based IStorage instance, less any
+// STREAMTYPE_CACHE streams.
+//
+// Arguments:
+// [pstg] -- pointer to the IStorage instance to copy
+// [ph] -- pointer to where to return the new handle.
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// REVIEW, this looks like something that should be a Ut function
+//
+// History:
+// 12/13/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+STATIC INTERNAL wStorageToHandle(LPSTORAGE pstg, LPHANDLE ph);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// wProgIDFromCLSID, static
+//
+// Synopsis:
+// Maps a CLSID to a string program/object name
+//
+// Maps CLSID_StdOleLink, which is not listed in the registry.
+//
+// Arguments:
+// [clsid] -- the class id to get the program id for
+// [psz] -- pointer to where to return the pointer to the newly
+// allocated string
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 12/13/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+FARINTERNAL wProgIDFromCLSID(REFCLSID clsid, LPOLESTR FAR* psz);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// CreateObjectDescriptor, static
+//
+// Synopsis:
+// Creates and initializes an OBJECTDESCRIPTOR from the given
+// parameters
+//
+// Arguments:
+// [clsid] -- the class ID of the object being transferred
+// [dwAspect] -- the display aspect drawn by the source of the
+// transfer
+// [psizel] -- pointer to the size of the object
+// [ppointl] -- pointer to the mouse offset in the object that
+// initiated a drag-drop transfer
+// [dwStatus] -- the OLEMISC status flags for the object
+// being transferred
+// [lpszFullUserTypeName] -- the full user type name of the
+// object being transferred
+// [lpszSrcOfCopy] -- a human readable name for the object
+// being transferred
+//
+// Returns:
+// If successful, A handle to the new OBJECTDESCRIPTOR; otherwise
+// NULL.
+//
+// Notes:
+// REVIEW, this seems generally useful for anyone using the
+// clipboard, or drag-drop; perhaps it should be exported.
+//
+// History:
+// 12/07/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+STATIC INTERNAL_(HGLOBAL) CreateObjectDescriptor(CLSID clsid, DWORD dwAspect,
+ const SIZEL FAR *psizel, const POINTL FAR *ppointl,
+ DWORD dwStatus, LPOLESTR lpszFullUserTypeName,
+ LPOLESTR lpszSrcOfCopy);
+
+// $$$
+STATIC INTERNAL_(void) RemoveClipDataObject(void);
+// REVIEW, is this local, redeclaration, or what?
+
+// Worker routine for CClipDataObject::GetData() below
+// NOTE: may be called with pmedium of NULL (even though this is not legal).
+// NOTE: also may be called with
+//
+// $$$
+STATIC HRESULT GetOle2Format(LPFORMATETC pforetc, LPSTGMEDIUM pmedium);
+
+// $$$
+STATIC INTERNAL ObjectLinkToMonikerStream(LPOLESTR grszFileItem, DWORD cbFile,
+ REFCLSID clsid, LPSTREAM pstm);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// IsNetDDEObjectLink, static
+//
+// Synopsis:
+// Determines if the cfObjectLink object on the clipboard
+// refers to a network file (one prefixed with \\server\share...)
+//
+// Effects:
+//
+// Arguments:
+// [fMustOpen] -- Indicates that the clipboard must be opened
+// before retrieving the cfObjectLink data format. If
+// the clipboard is already open, it is left that way.
+//
+// Returns:
+// TRUE, if the cfObjectLink data item is a network file,
+// FALSE otherwise
+//
+// Notes:
+// REVIEW, what is this about: This returns TRUE if it can't
+// open the clipboard, with a comment to the effect that this
+// will cause a failure.
+//
+// History:
+// 01/04/94 - ChrisWe - formatting
+//
+//-----------------------------------------------------------------------------
+STATIC FARINTERNAL_(BOOL) IsNetDDEObjectLink(BOOL fMustOpen);
+
+
+// $$$
+STATIC INTERNAL_(BOOL) OrderingIs(const CLIPFORMAT cf1, const CLIPFORMAT cf2);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// wOwnerLinkClassIsStdOleLink, static
+//
+// Synopsis:
+// Checks to see that the clipboard format registered as
+// cfOwnerLink is actually the standard Ole Link.
+//
+// Arguments:
+// [fOpenClipbrd] -- If true, signifies that the clipboard
+// is must be opened--it isn't already open. If it is
+// already open, it is left open.
+//
+// Returns:
+// TRUE if cfOwnerLink is actually the standard OLE link,
+// FALSE otherwise.
+//
+// Notes:
+//
+// History:
+// 01/04/93 - ChrisWe - formatted
+//
+//-----------------------------------------------------------------------------
+STATIC INTERNAL_(BOOL) wOwnerLinkClassIsStdOleLink(BOOL fOpenClipbrd);
+
+
+STATIC INTERNAL_(BOOL) wEmptyClipboard(void);
+
+STATIC const OLECHAR szStdOleLink[] = OLESTR("OLE2Link");
+
+STATIC const OLECHAR szClipboardWndClass[] = OLESTR("CLIPBOARDWNDCLASS");
+
+// DataObject 'posted' on clipboard
+//
+// pClipDataObj assumed to be valid in the context of the
+// process that owns the clipboard.
+//
+// pClipDataObj == NULL => GetClipboardData(cfDataObject) == NULL
+// => hClipDataObj == NULL
+//
+// To enable delayed marshalling of ClipDataObj must keep the pointer
+// in a global variable: initially SetClipboardData(cfDataObject, NULL);
+// marshal ClipDataObj only when GetClipboardData(cfDataObject) is called
+//
+STATIC LPDATAOBJECT pClipDataObj = NULL; // Pointer to the object
+
+// This always corresponds to what is on the clipboard as cfDataObject format
+// May be NULL, indicating either that cfDataObject is on clipboard but not
+// rendered. or cfDataObject is not on clipboard.
+STATIC HANDLE hClipDataObj = NULL;
+
+
+STATIC INTERNAL MakeObjectLink(LPDATAOBJECT pDataObj, LPSTREAM pStream,
+ LPHANDLE ph, BOOL fOwnerLink/*= FALSE*/);
+
+STATIC INTERNAL GetClassFromDescriptor(LPDATAOBJECT pDataObj, LPCLSID pclsid,
+ BOOL fLink, BOOL fUser, LPOLESTR FAR* pszSrcOfCopy);
+
+
+//+----------------------------------------------------------------------------
+//
+// Class:
+// CClipEnumFormatEtc
+//
+// Purpose:
+// Provides an enumerator for the data object CClipDataObject
+//
+// Interface:
+// IEnumFORMATETC
+// CClipEnumFormatEtc
+// constructor - this creates an instance that is
+// nearly ready to use; the created instance must still
+// be Init()ed before use, or have it's internal members
+// (except for the reference count) copied from an
+// existing enumerator, as in a clone operation.
+// Init
+// Initializes the enumerator to be at the beginning in
+// its scan state.
+//
+// Notes:
+//
+// History:
+// 12/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+class FAR CClipEnumFormatEtc : public IEnumFORMATETC, public CPrivAlloc
+{
+public:
+ // IUnknown methods
+ STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPLPVOID ppvObj);
+ STDMETHOD_(ULONG,AddRef)(THIS);
+ STDMETHOD_(ULONG,Release)(THIS);
+
+ // IEnumFORMATETC methods
+ STDMETHOD(Next)(THIS_ ULONG celt, FORMATETC FAR * rgelt,
+ ULONG FAR* pceltFetched);
+ STDMETHOD(Skip)(THIS_ ULONG celt);
+ STDMETHOD(Reset)(THIS);
+ STDMETHOD(Clone)(THIS_ IEnumFORMATETC FAR* FAR* ppenum);
+
+ // constructor
+ CClipEnumFormatEtc();
+
+ // initializer
+ void Init(void);
+
+private:
+ INTERNAL NextOne(FORMATETC FAR* pforetc);
+
+ ULONG m_refs; // reference count
+
+ CLIPFORMAT m_cfCurrent; // the last returned format on the clipboard
+ CLIPFORMAT m_cfForceNext; // if non-0, the next format to be enumerated
+ unsigned m_uFlag;
+#define CLIPENUMF_LINKSOURCEAVAILABLE 0x0001
+ /* is cfObjectLink somewhere on the clipboard? */
+#define CLIPENUMF_DONE 0x0002 /* forces enumerator to stop */
+
+ SET_A5;
+};
+
+
+
+// $$$
+#pragma SEG(OleSetClipboard)
+STDAPI OleSetClipboard(LPDATAOBJECT pDataObj)
+{
+ VDATEHEAP();
+
+ if (pDataObj)
+ VDATEIFACE(pDataObj);
+
+ // REVIEW - Server must be running through the whole time
+ // its object is on the clipboard.
+ //
+ // BUGBUG - should fail if pDataObj points to fake data object obtained
+ // by a call to OleGetClipboard
+ // REVIEW, why? Is it because once we've taken it off the clipboard
+ // it no longer exists?
+ if (!OpenClipboard(GetClipboardWindow()))
+ return(ReportResult(0, CLIPBRD_E_CANT_OPEN, 0, 0));
+
+#ifndef _MAC
+ if (!wEmptyClipboard())
+ {
+ // Also will clear pClipDaObj
+ Verify(CloseClipboard());
+ return(ReportResult(0, CLIPBRD_E_CANT_EMPTY, 0, 0));
+ }
+#endif // _MAC
+
+ // Save both pointer to the object
+ pClipDataObj = pDataObj;
+
+ if (pDataObj != NULL)
+ {
+ pClipDataObj->AddRef();
+
+ // Post required clipboard formats
+ //
+ // "..., which makes the passed IDataObject accessible
+ // from the clipboard"
+ //
+ // Delay marshalling until needed by passing NULL handle
+ SetClipboardData(cfDataObject, NULL);
+
+ // REVIEW, what if this wasn't NULL before? Did we just
+ // drop a handle on the floor?
+ hClipDataObj = NULL;
+
+ SetOle1ClipboardFormats(pDataObj);
+ }
+
+ return(CloseClipboard() ? NOERROR :
+ ResultFromScode(CLIPBRD_E_CANT_CLOSE));
+}
+
+
+#pragma SEG(OleGetClipboard)
+STDAPI OleGetClipboard(LPDATAOBJECT FAR* ppDataObj)
+{
+ VDATEHEAP();
+
+ HRESULT hresult;
+ HANDLE hMem;
+ BOOL fOpen;
+ IStream FAR* pStm;
+
+ // validate the output parameter
+ VDATEPTROUT(ppDataObj, LPDATAOBJECT);
+
+ // initialize this for error returns
+ *ppDataObj = NULL;
+
+ if (!(fOpen = OpenClipboard(GetClipboardWindow())))
+ {
+ // REVIEW - clipboard opened by caller
+ // If clipboard opended by this task (thread)
+ // it won't change during this call
+ if (GetWindowThreadProcessId(GetOpenClipboardWindow(),NULL) !=
+ GetCurrentThreadId())
+ {
+ // spec says return S_FALSE if someone else owns
+ // clipboard
+ return(ReportResult(0, S_FALSE, 0, 0));
+ }
+ }
+
+ if (pClipDataObj == NULL)
+ hresult = CreateClipboardDataObject(ppDataObj);
+ else // not the fake data object
+ {
+ // try to get a data object off the clipboard
+ hMem = GetClipboardData(cfDataObject);
+ if (hMem == NULL)
+ {
+ hresult = ReportResult(0, CLIPBRD_E_BAD_DATA, 0, 0);
+ goto Exit;
+ }
+
+ // "..., which makes the passed IDataObject accessible
+ // from the clipboard"
+ //
+ // Create shared memory stream on top of clipboard data.
+ // UnMarshal object's interface
+ pStm = CloneMemStm(hMem);
+ if (pStm == NULL)
+ {
+ hresult = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ goto Exit;
+ }
+
+ hresult = CoUnmarshalInterface(pStm, IID_IDataObject,
+ (LPLPVOID)ppDataObj);
+ pStm->Release();
+
+ if (GetScode(hresult) == RPC_E_CANTPOST_INSENDCALL)
+ {
+ // This happens when inplace object gets WM_INITMENU,
+ // and it is trying to Get the clipboard object, to
+ // decide whether to enable Paste and PasteLink menus.
+ // For this case we can create the fake data object
+ // and return the pointer to it.
+ hresult = CreateClipboardDataObject(ppDataObj);
+ }
+ }
+
+ if (hresult != NOERROR)
+ *ppDataObj = NULL;
+
+Exit:
+#ifdef MAC_REVIEW
+ Does mac have to trash the hMem handle, ericoe
+#endif
+
+ if (fOpen && !CloseClipboard())
+ hresult = ResultFromScode(CLIPBRD_E_CANT_CLOSE);
+
+ return(hresult);
+}
+
+
+// OleFlushClipboard
+//
+// Remove the DataObject from the clipboard, but leave hGlobal-based formats
+// including OLE1 formats on the clipboard (for use after the server app
+// exits).
+//
+#pragma SEG(OleFlushClipboard)
+STDAPI OleFlushClipboard(void)
+{
+ VDATEHEAP();
+
+ HWND hwnd;
+ BOOL fOpen;
+ CLIPFORMAT cf = 0;
+ HRESULT hresult = NOERROR;
+
+ hwnd = GetClipboardWindow();
+
+ if (hwnd == GetClipboardOwner()) // Caller owns the clipboard
+ {
+ fOpen = OpenClipboard(hwnd);
+ ErrZS(fOpen, CLIPBRD_E_CANT_OPEN);
+
+ // Make sure all formats are rendered
+ while (cf = EnumClipboardFormats(cf)) // not ==
+ {
+ if (cf != cfDataObject)
+ GetClipboardData(cf); // ignore return value
+ }
+
+ // this does OleSetClipboard(cfDataObject, NULL)
+ RemoveClipDataObject();
+
+ errRtn:
+ if (fOpen && !CloseClipboard())
+ hresult = ResultFromScode(CLIPBRD_E_CANT_CLOSE);
+ }
+
+ return(hresult);
+}
+
+#pragma SEG(OleIsCurrentClipboard)
+STDAPI OleIsCurrentClipboard(LPDATAOBJECT pDataObj)
+{
+ VDATEHEAP();
+
+ HWND hwnd;
+
+ // validate parameters
+ VDATEIFACE(pDataObj);
+
+ hwnd = GetClipboardWindow();
+
+ if (hwnd == GetClipboardOwner())
+ {
+ // Caller owns the clipboard, pClipDataObj valid in caller's
+ // address space
+ return(ReportResult(0, ((pClipDataObj == pDataObj) ? S_OK :
+ S_FALSE), 0, 0));
+ }
+
+ // someone else owns the clipboard
+ return(ResultFromScode(S_FALSE));
+}
+
+
+// Implementation of fake clipboard data object
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipDataObject::QueryInterface, public
+//
+// Synopsis:
+// implements IUnknown::QueryInterface
+//
+// Arguments:
+// [riid] -- the IID of the desired interface
+// [ppv] -- pointer to where to return the requested interface
+// pointer
+//
+// Returns:
+// E_NOINTERFACE, S_OK
+//
+// History:
+// 12/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipDataObject_QueryInterface)
+STDMETHODIMP CClipDataObject::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
+{
+ VDATEHEAP();
+
+ HRESULT hresult;
+
+ M_PROLOG(this);
+
+ // initialize this for error return
+ *ppvObj = NULL;
+
+ // validate parameters
+ VDATEPTROUT(ppvObj, LPVOID);
+ VDATEIID(riid);
+
+ if (IsEqualIID(riid, IID_IDataObject) ||
+ IsEqualIID(riid, IID_IUnknown))
+ {
+
+ AddRef(); // A pointer to this object is returned
+ *ppvObj = (void FAR *)(IDataObject FAR *)this;
+ hresult = NOERROR;
+ }
+ else
+ {
+ // Not accessible or unsupported interface
+ hresult = ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+
+ return hresult;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipDataObject::AddRef, public
+//
+// Synopsis:
+// implements IUnknown::AddRef
+//
+// Arguments:
+// none
+//
+// Returns:
+// The new reference count of the object
+//
+// History:
+// 12/06/93 - ChrisWe - file inspection
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipDataObject_AddRef)
+STDMETHODIMP_(ULONG) CClipDataObject::AddRef(void)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ return(++m_refs);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipDataObject::Release, internal
+//
+// Synopsis:
+// Decrements the reference count of the object, freeing it
+// if the last reference has gone away
+//
+// Arguments:
+// none
+//
+// Returns:
+// The new reference count of the object.
+//
+// History:
+// 12/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipDataObject_Release)
+STDMETHODIMP_(ULONG) CClipDataObject::Release(void)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ if (--m_refs != 0) // Still used by others
+ return(m_refs);
+
+ delete this; // Free storage
+ return(0);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipDataObject::GetData, public
+//
+// Synopsis:
+// implements IDataObject::GetData
+//
+// Retrieves data from the system clipboard, if data is available
+// in the requested format
+//
+// Arguments:
+// [pformatetcIn] -- the desired format to retrieve the data in
+// [pmedium] -- the medium the data will be retrieved in
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 12/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipDataObject_GetData)
+STDMETHODIMP CClipDataObject::GetData(LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ // validate parameters
+ VDATEPTRIN(pformatetcIn, FORMATETC);
+ VDATEPTROUT(pmedium, STGMEDIUM);
+
+ pmedium->tymed = TYMED_NULL;
+ pmedium->pUnkForRelease = NULL;
+
+ // REVIEW, what result does this have?
+ return(GetDataHere(pformatetcIn, pmedium));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// CClipDataObject::GetDataHere, internal
+//
+// Synopsis:
+// implements IDataObject::GetDataHere
+//
+// Retrieves the requested data from the clipboard, if possible.
+//
+// Arguments:
+// [pformatetcIn] -- the format the requestor would like
+// [pmedium] -- the medium the requestor would like the
+// data returned on
+// REVIEW, this doesn't seem to be used in the expected
+// way here.
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// This is written to accept a NULL [pmedium] so that it can be
+// used to do the work for QueryGetData(). In that case
+// it just asks the clipboard with IsClipboardFormatAvailable().
+//
+// History:
+// 12/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipDataObject_GetDataHere)
+STDMETHODIMP CClipDataObject::GetDataHere(LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium)
+{
+ VDATEHEAP();
+
+ HANDLE hData;
+ CLIPFORMAT cf;
+ DWORD tymed;
+
+ M_PROLOG(this);
+
+ // validate parameters
+ if (pmedium)
+ VDATEPTROUT(pmedium, STGMEDIUM);
+ VDATEPTRIN(pformatetcIn, FORMATETC);
+ VERIFY_LINDEX(pformatetcIn->lindex);
+
+ if (pformatetcIn->ptd != NULL)
+ return(ReportResult(0, DV_E_DVTARGETDEVICE, 0, 0));
+
+ if (pformatetcIn->dwAspect
+ && !(pformatetcIn->dwAspect & DVASPECT_CONTENT))
+ return(ReportResult(0, DV_E_DVASPECT, 0, 0));
+
+ cf = pformatetcIn->cfFormat;
+ tymed = pformatetcIn->tymed;
+
+ if (cf == cfEmbeddedObject || cf == cfEmbedSource ||
+ cf == cfLinkSource || (cf == cfLinkSrcDescriptor &&
+ !IsClipboardFormatAvailable(cfLinkSrcDescriptor))
+ || (cf == cfObjectDescriptor &&
+ !IsClipboardFormatAvailable(cfObjectDescriptor)))
+ {
+ return(GetOle2Format(pformatetcIn, pmedium));
+ }
+
+ //
+ // REVIEW: probably should be able to return data in any of flat
+ // mediums. For now only return hglobal.
+ //
+
+ if (((cf == CF_BITMAP) || (cf == CF_PALETTE)) && (tymed & TYMED_GDI))
+ tymed = TYMED_GDI;
+ else if ((cf == CF_METAFILEPICT) && (tymed & TYMED_MFPICT))
+ tymed = TYMED_MFPICT;
+ else if (tymed & TYMED_HGLOBAL)
+ tymed = TYMED_HGLOBAL;
+ else
+ return(ReportResult(0, DV_E_TYMED, 0, 0));
+
+ if (pmedium == NULL)
+ return(IsClipboardFormatAvailable(cf) ? NOERROR :
+ ReportResult(0, DV_E_CLIPFORMAT, 0, 0));
+
+ // initialize for error return case
+ pmedium->pUnkForRelease = NULL;
+ pmedium->hGlobal = NULL;
+
+ // We just want to take the clipboard data and pass it on. We don't
+ // want to get into the business of copying the data
+ if (pmedium->tymed != TYMED_NULL)
+ return(ReportResult(0, E_NOTIMPL, 0, 0));
+
+ if (!OpenClipboard(GetClipboardWindow()))
+ return(ReportResult(0, CLIPBRD_E_CANT_OPEN, 0, 0));
+
+ hData = GetClipboardData(cf);
+ if (hData == NULL)
+ {
+ Verify(CloseClipboard());
+ return(ReportResult(0, DV_E_CLIPFORMAT, 0, 0));
+ }
+
+ pmedium->tymed = tymed;
+ pmedium->hGlobal = OleDuplicateData(hData, cf, GMEM_MOVEABLE);
+ return(CloseClipboard() ? NOERROR :
+ ResultFromScode(CLIPBRD_E_CANT_CLOSE));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipDataObject::QueryGetData, internal
+//
+// Synopsis:
+// implements IDataObject::QueryGetData
+//
+// determines if the requested data can be fetched
+//
+// Arguments:
+// [pformatetcIn] -- checks to see if this format is available
+//
+// Returns:
+//
+// Notes:
+//
+// History:
+// 12/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipDataObject_QueryGetData)
+STDMETHODIMP CClipDataObject::QueryGetData(LPFORMATETC pformatetcIn)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ return(NOERROR == GetDataHere(pformatetcIn, NULL) ? NOERROR :
+ ResultFromScode(S_FALSE));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipDataObject::GetCanonicalFormatEtc, public
+//
+// Synopsis:
+// implements IDataObject::GetCanonicalFormatEtc
+//
+// Arguments:
+// [pformatetc] -- the format for which we'd like a base
+// equivalence class
+// [pformatetcOut] -- the equivalence class
+//
+// Returns:
+// S_OK
+//
+// Notes:
+//
+// History:
+// 12/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipDataObject_GetCanonicalFormatEtc)
+STDMETHODIMP CClipDataObject::GetCanonicalFormatEtc(LPFORMATETC pformatetc,
+ LPFORMATETC pformatetcOut)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ // validate parameters
+ VDATEPTRIN(pformatetc, FORMATETC);
+ VDATEPTROUT(pformatetcOut, FORMATETC);
+ VERIFY_LINDEX(pformatetc->lindex);
+
+ // set return values
+ INIT_FORETC(*pformatetcOut);
+ pformatetcOut->cfFormat = pformatetc->cfFormat;
+
+ // BUGBUG - Handle cfEmbeddedObject, cfEmbedSource, cfLinkSource
+ // REVIEW, this must be a reference to the fact that UtFormatToTymed
+ // only currently (12/06/93) returns anything explicit for
+ // CF_METAFILEPICT, CF_PALETTE, and CF_BITMAP. For anything else
+ // it returns TYMED_HGLOBAL. I don't know what the correct
+ // values should be for the above mentioned items....
+ pformatetcOut->tymed = UtFormatToTymed(pformatetc->cfFormat);
+
+ return(NOERROR);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipDataObject::SetData, public
+//
+// Synopsis:
+// implements IDataObject::SetData
+//
+// Arguments:
+// [pformatetc] -- the format the data is in
+// [pmedium] -- the storage medium the data is in
+// [fRelease] -- indicates that the callee should release
+// the storage medium when it is done with it
+//
+// Returns:
+// E_NOTIMPL
+//
+// Notes:
+// It is not allowed to set things on the clipboard
+// with this. Technically, it would be possible to do. Would
+// it be useful to implement this so that it worked? Would we
+// be able to release the storage medium correctly?
+// REVIEW, if we're not going to allow it, shouldn't we have
+// a better error message than E_NOTIMPL? That seems to indicate
+// brokenness, rather than planned decision....
+//
+// History:
+// 12/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipDataObject_SetData)
+STDMETHODIMP CClipDataObject::SetData(LPFORMATETC pformatetc,
+ STGMEDIUM FAR* pmedium, BOOL fRelease)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ return(ReportResult(0, E_NOTIMPL, 0, 0));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipDataObject::EnumFormatEtc, public
+//
+// Synopsis:
+// implements IDataObject::EnumFormatEtc
+//
+// Arguments:
+// [dwDirection] -- flags from DATADIR_*
+// [ppenumFormatEtc] -- pointer to where to return the enumerator
+//
+// Returns:
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 12/08/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipDataObject_EnumFormatEtc)
+STDMETHODIMP CClipDataObject::EnumFormatEtc(DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenumFormatEtc)
+{
+ VDATEHEAP();
+
+ HRESULT hresult = NOERROR;
+ CClipEnumFormatEtc *pCCEFE; // the newly created enumerator
+
+ A5_PROLOG(this);
+
+ // validate parameters
+ VDATEPTROUT(ppenumFormatEtc, LPENUMFORMATETC);
+
+ // initialize this for error returns
+ *ppenumFormatEtc = NULL;
+
+ // REVIEW, a user could potentially be very confused by this,
+ // since DATADIR_SET is a valid argument. Perhaps it would be
+ // better to return an empty enumerator, OR, create a new error
+ // code for this condition?
+ if (dwDirection != DATADIR_GET)
+ return(ResultFromScode(E_INVALIDARG));
+
+ // open the clipboard, so we can enumerate the available formats
+ // REVIEW, I believe the enumerator repeatedly does this, so
+ // why Open and Close the clipboard here?
+ if (!OpenClipboard(GetClipboardWindow()))
+ {
+ AssertSz(0,"EnumFormatEtc cannont OpenClipboard");
+ return(ReportResult(0, CLIPBRD_E_CANT_OPEN, 0, 0));
+ }
+
+ // allocate the enumerator
+ pCCEFE = new CClipEnumFormatEtc;
+ if (pCCEFE == NULL)
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+
+ // initialize the enumerator, and prepare to return it
+ pCCEFE->Init();
+ *ppenumFormatEtc = (IEnumFORMATETC FAR *)pCCEFE;
+
+ if (!CloseClipboard())
+ hresult = ResultFromScode(CLIPBRD_E_CANT_CLOSE);
+
+ RESTORE_A5();
+ return(hresult);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipDataObject::DAdvise, public
+//
+// Synopsis:
+// implements IDataObject::DAdvise
+//
+// Arguments:
+// [pFormatetc] -- the format we are interested in being
+// advised of changes to
+// [advf] -- the advise control flags, from ADVF_*
+// [pAdvSink] -- pointer to the advise sink to use for
+// notifications
+// [pdwConnection] -- pointer to a DWORD where DAdvise() can
+// return a token that identifies this advise connection
+//
+// Returns:
+// E_NOTIMPL
+//
+// Notes:
+//
+// History:
+// 12/08/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipDataObject_DAdvise)
+STDMETHODIMP CClipDataObject::DAdvise(FORMATETC FAR* pFormatetc, DWORD advf,
+ IAdviseSink FAR* pAdvSink, DWORD FAR* pdwConnection)
+
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ VDATEPTROUT(pdwConnection, DWORD);
+ *pdwConnection = 0;
+ return(ReportResult(0, E_NOTIMPL, 0, 0));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipDataObject::DUnadvise, public
+//
+// Synopsis:
+// implements IDataObject::Dunadvise
+//
+// Arguments:
+// [dwConnection] -- a connection identification token, as
+// returned by DAdvise()
+//
+// Returns:
+// E_NOTIMPL
+//
+// Notes:
+//
+// History:
+// 12/08/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipDataObject_DUnadvise)
+STDMETHODIMP CClipDataObject::DUnadvise(DWORD dwConnection)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ return(ReportResult(0, E_NOTIMPL, 0, 0));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipDataObject::EnumDAdvise, public
+//
+// Synopsis:
+// implements IDataObject::EnumDAdvise
+//
+// Arguments:
+// [ppenumAdvise] -- pointer to where to return the enumerator
+//
+// Returns:
+// E_NOTIMPL
+//
+// Notes:
+//
+// History:
+// 12/08/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipDataObject_EnumDAdvise)
+STDMETHODIMP CClipDataObject::EnumDAdvise(LPENUMSTATDATA FAR* ppenumAdvise)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ VDATEPTROUT(ppenumAdvise, LPENUMSTATDATA FAR*);
+ *ppenumAdvise = NULL;
+ return(ReportResult(0, E_NOTIMPL, 0, 0));
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipDataObject::CClipDataObject, public
+//
+// Synopsis:
+// constructor
+//
+// Arguments:
+// none
+//
+// Notes:
+// returns with reference count set to 1
+//
+// History:
+// 12/08/93 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+CClipDataObject::CClipDataObject()
+{
+ VDATEHEAP();
+
+ m_refs = 1;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// CreateClipboardDataObject, internal
+//
+// Synopsis:
+// Creates an instance of CClipDataObject, manifested as
+// an IDataObject.
+//
+// Arguments:
+// [ppDataObj] -- pointer to where to return the IDataObject
+// instance
+//
+// Returns:
+// OLE_E_BLANK, if there are no registered clipboard formats
+// (and *ppDataObj will be NULL)
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 12/08/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CreateClipboardDataObject)
+INTERNAL CreateClipboardDataObject(LPDATAOBJECT FAR* ppDataObj)
+{
+ VDATEHEAP();
+
+ // initialize this for error returns
+ *ppDataObj = NULL;
+
+ if (CountClipboardFormats() == 0)
+ return(ReportResult(0, OLE_E_BLANK, 0, 0));
+
+ *ppDataObj = new CClipDataObject;
+ if (*ppDataObj == NULL)
+ return(ReportResult(0, E_OUTOFMEMORY, 0, 0));
+
+ return NOERROR;
+}
+
+
+// Implemetation of FORMATETC enumerator for the above fake clipboard data
+// object
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipEnumFormatEtc::QueryInterface, public
+//
+// Synopsis:
+// implements IUnknown::QueryInterface
+//
+// Arguments:
+// [riid] -- the IID of the desired interface
+// [ppv] -- pointer to where to return the requested interface
+// pointer
+//
+// Returns:
+// E_NOINTERFACE, S_OK
+//
+// History:
+// 12/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipEnumFormatEtc_QueryInterface)
+STDMETHODIMP CClipEnumFormatEtc::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
+{
+ VDATEHEAP();
+
+ HRESULT hresult;
+
+ M_PROLOG(this);
+
+ // Two interfaces supported: IUnknown, IEnumFORMATETC
+ if (IsEqualIID(riid, IID_IEnumFORMATETC) ||
+ IsEqualIID(riid, IID_IUnknown))
+ {
+ AddRef(); // A pointer to this object is returned
+ *ppvObj = (void FAR *)(IEnumFORMATETC FAR *)this;
+ hresult = NOERROR;
+ }
+ else
+ {
+ // Not accessible or unsupported interface
+ *ppvObj = NULL;
+ hresult = ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+
+ return hresult;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipEnumFormatEtc::AddRef, public
+//
+// Synopsis:
+// implements IUnknown::AddRef
+//
+// Arguments:
+// none
+//
+// Returns:
+// The new reference count of the object
+//
+// History:
+// 12/06/93 - ChrisWe - file inspection
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipEnumFormatEtc_AddRef)
+STDMETHODIMP_(ULONG) CClipEnumFormatEtc::AddRef(void)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ return(++m_refs);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipEnumFormatEtc::Release, internal
+//
+// Synopsis:
+// Decrements the reference count of the object, freeing it
+// if the last reference has gone away
+//
+// Arguments:
+// none
+//
+// Returns:
+// The new reference count of the object.
+//
+// History:
+// 12/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipEnumFormatEtc_Release)
+STDMETHODIMP_(ULONG) CClipEnumFormatEtc::Release(void)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ if (--m_refs != 0) // Still used by others
+ return(m_refs);
+
+ delete this; // Free storage
+ return(0);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipEnumFormatEtc::Next, public
+//
+// Synopsis:
+// implements IEnumFORMATETC::Next
+//
+// Arguments:
+// [celt] -- the number of elements the caller would like
+// returned
+// [rgelt] -- a pointer to space where the elements may be
+// returned
+// [pceltFetched] -- a pointer to where to return a count of
+// the number of elements fetched; May be NULL.
+//
+// Returns:
+// S_OK if the requested number of items is retrieved, or
+// S_FALSE, if fewer than the requested number is retrieved
+//
+// Notes:
+//
+// History:
+// 12/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipEnumFormatEtc_Next)
+STDMETHODIMP CClipEnumFormatEtc::Next(ULONG celt, FORMATETC FAR * rgelt,
+ ULONG FAR* pceltFetched)
+{
+ VDATEHEAP();
+
+ ULONG celtSoFar; // count of elements fetched so far
+ ULONG celtDummy; // used to avoid retesting pceltFetched
+
+ // did the caller ask for the number of elements fetched?
+ if (pceltFetched != NULL)
+ {
+ // validate the pointer
+ VDATEPTROUT(pceltFetched, ULONG);
+
+ // initialize for error return
+ *pceltFetched = 0;
+ }
+ else
+ {
+ // point at the dummy so we can assign *pceltFetched w/o test
+ pceltFetched = &celtDummy;
+
+ // if pceltFetched == NULL, can only ask for 1 element
+ if (celt != 1)
+ return(ResultFromScode(E_INVALIDARG));
+ }
+
+ // validate parameters
+ VDATEPTROUT(rgelt, FORMATETC);
+ if (celt != 0)
+ VDATEPTROUT(rgelt + celt - 1, FORMATETC);
+
+ // fetch the items
+ for(celtSoFar = 0; celtSoFar < celt; ++rgelt, ++celtSoFar)
+ {
+ if (NextOne(rgelt) != NOERROR)
+ break;
+ }
+
+ *pceltFetched = celtSoFar;
+
+ return(celtSoFar < celt ? ResultFromScode(S_FALSE) : NOERROR);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipEnumFormatEtc::NextOne, private
+//
+// Synopsis:
+// Workhorse function for CClipEnumFormatEtc::Next(); iterates
+// over the available formats on the clipboard using the
+// appropriate win32s APIs.
+//
+// Arguments:
+// [pforetc] -- pointer to a FORMATETC to fill in with the
+// next format
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// This skips over cfDataObject, cfObjectLink, and cfOwnerLink.
+// cfObjectLink and cfOwnerLink are returned after all other
+// formats; cfDataObject is not returned at all.
+//
+// History:
+// 01/04/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipEnumFormatEtc_NextOne)
+INTERNAL CClipEnumFormatEtc::NextOne(FORMATETC FAR* pforetc)
+{
+ VDATEHEAP();
+
+ CLIPFORMAT cfNext;
+ HRESULT hresult;
+
+ M_PROLOG(this);
+
+ // Initialize the FORMATETC we're going to fetch into
+ INIT_FORETC(*pforetc);
+
+ // is there a CLIPFORMAT that we want to force to be next?
+ if (m_cfForceNext != 0)
+ {
+ // return the format we're forcing to be next
+ pforetc->cfFormat = m_cfForceNext;
+ pforetc->tymed = UtFormatToTymed(m_cfForceNext);
+
+ // there's no more format to force to be next
+ m_cfForceNext = 0;
+ return(NOERROR);
+ }
+
+ // if the enumerator is done, get out
+ if (m_uFlag & CLIPENUMF_DONE)
+ return(ResultFromScode(S_FALSE));
+
+ // if we can't open the clipboard, we can't enumerate the formats on it
+ if (!OpenClipboard(GetClipboardWindow()))
+ {
+ AssertSz(0, "CClipEnumFormatEtc::Next cannot OpenClipboard");
+ return(ReportResult(0, CLIPBRD_E_CANT_OPEN, 0, 0));
+ }
+
+ // error state so far
+ hresult = NOERROR;
+
+ // get the next format to be returned by the enumerator
+ cfNext = EnumClipboardFormats(m_cfCurrent);
+
+TryAgain:
+ // skip cfDataObject
+ if (cfNext == cfDataObject)
+ cfNext = EnumClipboardFormats(cfNext);
+
+ if (cfNext == cfObjectLink)
+ {
+ if (!IsNetDDEObjectLink(FALSE))
+ {
+ // Hack to make sure CF_LINKSOURCE is last.
+ m_uFlag |= CLIPENUMF_LINKSOURCEAVAILABLE;
+ }
+
+ // skip cfObjectlink for now
+ cfNext = EnumClipboardFormats(cfNext);
+ goto TryAgain;
+ }
+
+ if (cfNext == cfOwnerLink)
+ {
+ if (!IsClipboardFormatAvailable(cfNative)
+ || OrderingIs(cfOwnerLink, cfNative))
+ {
+ // This is the case of copying a link object from a
+ // 1.0 container EmbeddedObject will need to be
+ // generated on request in GetData.
+ pforetc->cfFormat = cfEmbeddedObject;
+ pforetc->tymed = TYMED_ISTORAGE;
+ goto errRtn;
+ }
+ else
+ {
+ // skip cfOwnerlink
+ cfNext = EnumClipboardFormats(cfNext);
+ goto TryAgain;
+ }
+ }
+
+ // is there nothing more on the clipboard?
+ if (cfNext == 0)
+ {
+ // mark the enumeration as done
+ m_uFlag |= CLIPENUMF_DONE;
+
+ if (m_uFlag & CLIPENUMF_LINKSOURCEAVAILABLE)
+ {
+ // Prevent infinite loop. Return S_FALSE next time.
+ cfNext = cfObjectLink;
+ }
+ else
+ {
+ hresult = ResultFromScode(S_FALSE);
+ goto errRtn;
+ }
+ }
+
+ if (cfNext == cfNative)
+ {
+ if (IsClipboardFormatAvailable(cfOwnerLink) &&
+ OrderingIs(cfNative, cfOwnerLink))
+ {
+ pforetc->cfFormat = wOwnerLinkClassIsStdOleLink(FALSE) ?
+ cfEmbeddedObject : cfEmbedSource;
+ pforetc->tymed = TYMED_ISTORAGE;
+
+ if (!IsClipboardFormatAvailable(cfObjectDescriptor))
+ {
+ // cfObjectDescriptor may be directly on the
+ // clipboard if it was flushed.
+ m_cfForceNext = cfObjectDescriptor;
+ }
+ }
+ else
+ {
+ // Native without ownerlink is useless
+ cfNext = EnumClipboardFormats(cfNext);
+ goto TryAgain;
+ }
+ }
+ else if (cfNext == cfObjectLink)
+ {
+ pforetc->cfFormat = cfLinkSource;
+ pforetc->tymed = TYMED_ISTREAM;
+
+ if (!IsClipboardFormatAvailable(cfLinkSrcDescriptor))
+ {
+ // cfLinkSrcDescriptor may be directly on the clipboard
+ // if it was flushed.
+ m_cfForceNext = cfLinkSrcDescriptor;
+ }
+ }
+ else
+ {
+ pforetc->cfFormat = cfNext;
+ pforetc->tymed = UtFormatToTymed(cfNext);
+ }
+
+errRtn:
+ m_cfCurrent = cfNext;
+
+ if (!CloseClipboard())
+ hresult = ResultFromScode(CLIPBRD_E_CANT_CLOSE);
+
+ return(hresult);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipEnumFormatEtc::Skip, public
+//
+// Synopsis:
+// Implements IEnumFORMATETC::Skip
+//
+// Arguments:
+// [celt] -- the number of elements to skip in the enumeration
+//
+// Returns:
+// S_FALSE, if fewer elements were available than [celt]
+// S_TRUE, otherwise
+//
+// Notes:
+//
+// History:
+// 12/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipEnumFormatEtc_Skip)
+STDMETHODIMP CClipEnumFormatEtc::Skip(ULONG celt)
+{
+ VDATEHEAP();
+
+ ULONG celtSoFar; // a count of the elements we've skipped so far
+ FORMATETC formatetc; // a dummy FORMATETC to fetch formats into
+
+ M_PROLOG(this);
+
+ // skip over as many formats as requested
+ for(celtSoFar = 0; (celtSoFar < celt) &&
+ (NextOne(&formatetc) == NOERROR); ++celtSoFar)
+ ;
+
+ return((celtSoFar < celt) ? ResultFromScode(S_FALSE) : NOERROR);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipEnumFormatEtc::Reset, public
+//
+// Synopsis:
+// implements IEnumFORMATETC::Reset
+//
+// Arguments:
+// none
+//
+// Returns:
+// S_OK
+//
+// Notes:
+//
+// History:
+// 12/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipEnumFormatEtc_Reset)
+STDMETHODIMP CClipEnumFormatEtc::Reset(void)
+{
+ VDATEHEAP();
+
+ Init();
+
+ return(NOERROR);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipEnumFormatEtc::Clone, public
+//
+// Synopsis:
+// implements IEnumFORMATETC::Clone
+//
+// Arguments:
+// [ppenum] -- pointer to where to return the new enumerator
+//
+// Returns:
+// E_OUTOFMEMORY, S_OK
+//
+// Notes:
+//
+// History:
+// 12/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(CClipEnumFormatEtc_Clone)
+STDMETHODIMP CClipEnumFormatEtc::Clone(IEnumFORMATETC FAR* FAR* ppenum)
+{
+ VDATEHEAP();
+
+ CClipEnumFormatEtc FAR* pECB; // pointer to the new enumerator
+
+ M_PROLOG(this);
+
+ // validate parameters
+ VDATEPTROUT(ppenum, LPENUMFORMATETC);
+
+ // allocate the new enumerator
+ *ppenum = pECB = new CClipEnumFormatEtc;
+ if (pECB == NULL)
+ return(ResultFromScode(E_OUTOFMEMORY));
+
+ // set the clone enumerator to be in the same state as this one
+ pECB->m_cfCurrent = m_cfCurrent;
+ pECB->m_uFlag = m_uFlag;
+ pECB->m_cfForceNext = m_cfForceNext;
+
+ return(NOERROR);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipEnumFormatEtc::CClipEnumFormatEtc, public
+//
+// Synopsis:
+// constructor
+//
+// Arguments:
+// none
+//
+// Notes:
+// returns with reference count set to 1
+//
+// History:
+// 12/10/93 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+CClipEnumFormatEtc::CClipEnumFormatEtc()
+{
+ VDATEHEAP();
+
+ m_refs = 1;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Member:
+// CClipEnumFormatEtc::Init, public
+//
+// Synopsis:
+// Initializes enumerator, preparing it for use.
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 12/10/93 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+void CClipEnumFormatEtc::Init(void)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+
+ // initialize enumerator to be at beginning of scan state
+ m_cfCurrent = 0;
+ m_uFlag = 0;
+ m_cfForceNext = 0;
+}
+
+
+// $$$
+// ObjectLinkToMonikerStream
+//
+// grszFileItem == szFileName\0szItemName\0\0
+// i.e. the tail end of an ObjectLink
+// cbFile == strlen(szFileName)
+//
+// Create a moniker from the ObjectLink and serialize it to pstm
+//
+
+#pragma SEG(ObjectLinkToMonikerStream)
+STATIC INTERNAL ObjectLinkToMonikerStream(LPOLESTR grszFileItem, DWORD cbFile,
+ REFCLSID clsid, LPSTREAM pstm)
+{
+ VDATEHEAP();
+
+ HRESULT hr = NOERROR;
+ LPMONIKER pmk = NULL;
+ LPMONIKER pmkFile = NULL;
+ LPMONIKER pmkItem = NULL;
+ LPPERSISTSTREAM ppersiststm = NULL;
+
+#ifdef WIN32 // REVIEW, no 16 bit interop
+ return(ReportResult(0, E_NOTIMPL, 0, 0));
+// REVIEW, this seems to be used by GetOle2Format().
+#else
+ Assert(grszFileItem);
+ Assert(cbFile == (DWORD)_xstrlen(grszFileItem) + 1);
+
+ if (NOERROR != (hr = CreateOle1FileMoniker(grszFileItem, clsid,
+ &pmkFile)))
+ {
+ AssertSz (0, "Cannot create file moniker");
+ goto errRtn;
+ }
+
+ grszFileItem += cbFile;
+ if (*grszFileItem)
+ {
+ if (NOERROR != (hr = CreateItemMoniker(OLESTR("!"),
+ grszFileItem, &pmkItem)))
+ {
+ AssertSz(0, "Cannot create file moniker");
+ goto errRtn;
+ }
+
+ if (NOERROR != (hr = CreateGenericComposite(pmkFile,
+ pmkItem, &pmk)))
+ {
+ AssertSz(0, "Cannot create composite moniker");
+ goto errRtn;
+ }
+ }
+ else
+ {
+ // No item
+ pmk = pmkFile;
+ pmk->AddRef();
+ }
+
+ if (NOERROR != (hr = pmk->QueryInterface(IID_IPersistStream,
+ (LPLPVOID)&ppersiststm)))
+ {
+ AssertSz(0, "Cannot get IPersistStream from moniker");
+ goto errRtn;
+ }
+
+ if (NOERROR != (hr = OleSaveToStream(ppersiststm, pstm)))
+ {
+ AssertSz(0, "Cannot save to Persist Stream");
+ goto errRtn;
+ }
+
+ errRtn:
+ if (pmk)
+ pmk->Release();
+ if (pmkFile)
+ pmkFile->Release();
+ if (pmkItem)
+ pmkItem->Release();
+ if (ppersiststm)
+ ppersiststm->Release();
+ return hr;
+#endif // WIN32
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// wHandleToStorage, static
+//
+// Synopsis:
+// Copies the contents of a handle to a native clipboard
+// format to an IStorage instance.
+//
+// Arguments:
+// [pstg] -- the IStorage instance to copy the handle contents to
+// [hNative] -- a handle to a native clipboard format
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+// REVIEW, this seems to assume that the handle was already
+// an IStorage instance disguised as an OLE1.0 object for the
+// sake of a containing OLE1.0 object, and creates a copy of
+// the underlying OLE2.0 stuff in the target storage.
+//
+// The Cache streams are removed from the handle based storage
+// before copying to the target.
+// REVIEW, it's not clear if the caller would like this. Perhaps
+// they should just not be copied....
+//
+// History:
+// 12/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+#pragma SEG(wHandleToStorage)
+STATIC INTERNAL wHandleToStorage(LPSTORAGE pstg, HANDLE hNative)
+{
+ VDATEHEAP();
+
+ LPLOCKBYTES plkbyt = NULL;
+ LPSTORAGE pstgNative = NULL;
+ HRESULT hresult;
+
+ RetErr(CreateILockBytesOnHGlobal(hNative, FALSE, &plkbyt));
+ if (NOERROR != (hresult = StgIsStorageILockBytes(plkbyt)))
+ {
+ AssertSz(0, "Native data is not an IStorage");
+ goto errRtn;
+ }
+
+ // This is really a 2.0 object disguised as a 1.0 object
+ // for the sake of its 1.0 container, so reconstitute
+ // the original IStorage from the native data.
+ if (NOERROR != (hresult = StgOpenStorageOnILockBytes(plkbyt, NULL,
+ STGM_DFRALL, NULL, 0, &pstgNative)))
+ {
+ AssertSz(0, "Couldn't open storage on native data");
+ goto errRtn;
+ }
+
+ ErrRtnH(UtDoStreamOperation(pstgNative, NULL, OPCODE_REMOVE,
+ STREAMTYPE_CACHE));
+
+ if (NOERROR != (hresult = pstgNative->CopyTo(0, NULL, NULL, pstg)))
+ {
+ AssertSz(0, "Couldn't copy storage");
+ goto errRtn;
+ }
+
+ errRtn:
+ if (pstgNative)
+ pstgNative->Release();
+ if (plkbyt)
+ plkbyt->Release();
+
+ return(hresult);
+}
+
+
+#ifndef WIN32 // REVIEW, can't find GetMetaFileBits() in win32
+ // REVIEW, seems to be OLE1
+
+#pragma SEG(MfToPres)
+INTERNAL MfToPres(HANDLE hMfPict, PPRES ppres)
+{
+ VDATEHEAP();
+
+ LPMETAFILEPICT pMfPict;
+
+ Assert(ppres);
+ pMfPict = (LPMETAFILEPICT)GlobalLock(hMfPict);
+ RetZS(pMfPict, CLIPBRD_E_BAD_DATA);
+ ppres->m_format.m_ftag = ftagClipFormat;
+ ppres->m_format.m_cf = CF_METAFILEPICT;
+ ppres->m_ulHeight = pMfPict->yExt;
+ ppres->m_ulWidth = pMfPict->xExt;
+
+ // GetMetaFileBits() invalidates its parameter, therefore we must copy
+ ppres->m_data.m_h = GetMetaFileBits(CopyMetaFile(pMfPict->hMF, NULL));
+ ppres->m_data.m_cbSize = GlobalSize(ppres->m_data.m_h);
+ ppres->m_data.m_pv = GlobalLock(ppres->m_data.m_h);
+ GlobalUnlock(hMfPict);
+ return(NOERROR);
+}
+
+#pragma SEG(DibToPres)
+INTERNAL DibToPres(HANDLE hDib, PPRES ppres)
+{
+ VDATEHEAP();
+
+ BITMAPINFOHEADER FAR* pbminfohdr;
+
+ Assert(ppres);
+
+ pbminfohdr = (BITMAPINFOHEADER FAR*)GlobalLock(hDib);
+ RetZS(pbminfohdr, CLIPBRD_E_BAD_DATA);
+
+ ppres->m_format.m_ftag = ftagClipFormat;
+ ppres->m_format.m_cf = CF_DIB;
+ ppres->m_ulHeight = pbminfohdr->biHeight;
+ ppres->m_ulWidth = pbminfohdr->biWidth;
+ ppres->m_data.m_h = hDib;
+ ppres->m_data.m_pv = pbminfohdr;
+ ppres->m_data.m_cbSize = GlobalSize (hDib);
+
+ // Don't free the hDib because it is on the clipboard.
+ ppres->m_data.m_fNoFree = TRUE;
+
+ // Do not unlock hDib
+ return(NOERROR);
+}
+
+
+#pragma SEG(BmToPres)
+INTERNAL BmToPres(HBITMAP hBM, PPRES ppres)
+{
+ VDATEHEAP();
+
+ HANDLE hDib;
+
+ if (hDib = UtConvertBitmapToDib(hBM))
+ {
+ // this routine keeps hDib, it doesn't make a copy of it
+ return DibToPres(hDib, ppres);
+ }
+
+ return(ResultFromScode(E_OUTOFMEMORY));
+}
+
+#endif // WIN32
+
+//$$$
+// OrderingIs
+//
+// Return whether the relative ordering of cf1 and cf2 on the clipboard
+// is "cf1 then cf2". Will return FALSE if cf1 is not on the clipboard,
+// so OrderingIs (cf1, cf2) => IsClipboardFormatAvailable (cf1)
+// Clipboard must be open.
+//
+INTERNAL_(BOOL) OrderingIs(const CLIPFORMAT cf1, const CLIPFORMAT cf2)
+{
+ VDATEHEAP();
+
+ CLIPFORMAT cf = 0;
+
+ while (cf = EnumClipboardFormats(cf))
+ {
+ if (cf == cf1)
+ return(TRUE);
+ if (cf == cf2)
+ return(FALSE);
+ }
+
+ return(FALSE); // didn't find either format
+}
+
+
+// wMakeEmbedObjForLink
+//
+// Generate a storage (cfEmbedSource) for a link copied from a 1.0 container.
+//
+
+#pragma SEG(wMakeEmbedObjForLink)
+INTERNAL wMakeEmbedObjForLink(LPSTORAGE pstg)
+{
+ VDATEHEAP();
+
+#ifdef WIN32 // REVIEW, seems to be OLE1
+ return(ReportResult(0, OLE_E_NOOLE1, 0, 0));
+#else
+ GENOBJ genobj;
+ HANDLE hOwnerLink;
+ LPOLESTR pch;
+ HRESULT hresult;
+
+ genobj.m_class.Set(CLSID_StdOleLink);
+ genobj.m_ppres = new PRES;
+ RetZS(genobj.m_ppres, E_OUTOFMEMORY);
+ genobj.m_fLink = TRUE;
+ genobj.m_lnkupdopt = UPDATE_ALWAYS;
+
+ if (IsClipboardFormatAvailable(CF_METAFILEPICT))
+ {
+ RetErr(MfToPres(GetClipboardData(CF_METAFILEPICT),
+ genobj.m_ppres));
+ }
+ else if (IsClipboardFormatAvailable(CF_DIB))
+ {
+ RetErr(DibToPres(GetClipboardData(CF_DIB),
+ genobj.m_ppres));
+ }
+ else if (IsClipboardFormatAvailable(CF_BITMAP))
+ {
+ RetErr(BmToPres((HBITMAP)GetClipboardData(CF_BITMAP),
+ genobj.m_ppres));
+ }
+ else
+ {
+ delete genobj.m_ppres;
+ genobj.m_ppres = NULL;
+ genobj.m_fNoBlankPres = TRUE;
+ }
+
+ if (NULL == (hOwnerLink = GetClipboardData(cfOwnerLink)))
+ {
+ Assert(0);
+ return(ResultFromScode (DV_E_CLIPFORMAT));
+ }
+
+ if (NULL == (pch = GlobalLock(hOwnerLink)))
+ return(ResultFromScode(CLIPBRD_E_BAD_DATA));
+
+
+ genobj.m_classLast.Set(UtDupString(pch));
+ pch += _xstrlen(pch)+1;
+ genobj.m_szTopic = *pch ? UtDupString (pch) : NULL;
+ pch += _xstrlen(pch)+1;
+ genobj.m_szItem = *pch ? UtDupString (pch) : NULL;
+
+ GlobalUnlock(hOwnerLink);
+ hresult = GenericObjectToIStorage(genobj, pstg, NULL);
+ if (SUCCEEDED(hresult))
+ hresult = NOERROR;
+
+ if (!OrderingIs(cfNative, cfOwnerLink))
+ return(hresult);
+ else
+ {
+ // Case of copying an OLE 2 link from a 1.0 container.
+ // The first part of this function created a presentation
+ // stream from the presentation on the clipboard. The
+ // presentation is NOT already inside the Native data (i.e.,
+ // the cfEmbeddedObject) because we removed it to conserve
+ // space.
+ HGLOBAL h = GetClipboardData(cfNative);
+ RetZS(h, CLIPBRD_E_BAD_DATA);
+ return(wHandleToStorage(pstg, h));
+ }
+#endif // WIN32
+}
+
+
+#pragma SEG(CreateObjectDescriptor)
+STATIC INTERNAL_(HGLOBAL) CreateObjectDescriptor(CLSID clsid, DWORD dwAspect,
+ const SIZEL FAR *psizel, const POINTL FAR *ppointl,
+ DWORD dwStatus, LPOLESTR lpszFullUserTypeName,
+ LPOLESTR lpszSrcOfCopy)
+{
+ VDATEHEAP();
+
+ DWORD dwFullUserTypeNameBLen; // length of lpszFullUserTypeName in BYTES
+ DWORD dwSrcOfCopyBLen; // length of lpszSrcOfCopy in BYTES
+ HGLOBAL hMem; // handle to the object descriptor
+ LPOBJECTDESCRIPTOR lpOD; // the new object descriptor
+
+ // Get the length of Full User Type Name; Add 1 for the null terminator
+ if (!lpszFullUserTypeName)
+ dwFullUserTypeNameBLen = 0;
+ else
+ dwFullUserTypeNameBLen = (_xstrlen(lpszFullUserTypeName) +
+ 1) * sizeof(OLECHAR);
+
+ // Get the Source of Copy string and it's length; Add 1 for the null
+ // terminator
+ if (lpszSrcOfCopy)
+ dwSrcOfCopyBLen = (_xstrlen(lpszSrcOfCopy) + 1) *
+ sizeof(OLECHAR);
+ else
+ {
+ // No src moniker so use user type name as source string.
+ lpszSrcOfCopy = lpszFullUserTypeName;
+ dwSrcOfCopyBLen = dwFullUserTypeNameBLen;
+ }
+
+ // allocate the memory where we'll put the object descriptor
+ hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
+ sizeof(OBJECTDESCRIPTOR) + dwFullUserTypeNameBLen +
+ dwSrcOfCopyBLen);
+ if (hMem == NULL)
+ goto error;
+
+ lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(hMem);
+ if (lpOD == NULL)
+ goto error;
+
+ // Set the FullUserTypeName offset and copy the string
+ if (!lpszFullUserTypeName)
+ {
+ // zero offset indicates that string is not present
+ lpOD->dwFullUserTypeName = 0;
+ }
+ else
+ {
+ lpOD->dwFullUserTypeName = sizeof(OBJECTDESCRIPTOR);
+ _xmemcpy(((BYTE FAR *)lpOD)+lpOD->dwFullUserTypeName,
+ (const void FAR *)lpszFullUserTypeName,
+ dwFullUserTypeNameBLen);
+ }
+
+ // Set the SrcOfCopy offset and copy the string
+ if (!lpszSrcOfCopy)
+ {
+ // zero offset indicates that string is not present
+ lpOD->dwSrcOfCopy = 0;
+ }
+ else
+ {
+ lpOD->dwSrcOfCopy = sizeof(OBJECTDESCRIPTOR) +
+ dwFullUserTypeNameBLen;
+ _xmemcpy(((BYTE FAR *)lpOD)+lpOD->dwSrcOfCopy,
+ (const void FAR *)lpszSrcOfCopy,
+ dwSrcOfCopyBLen);
+ }
+
+ // Initialize the rest of the OBJECTDESCRIPTOR
+ lpOD->cbSize = sizeof(OBJECTDESCRIPTOR) + dwFullUserTypeNameBLen +
+ dwSrcOfCopyBLen;
+ lpOD->clsid = clsid;
+ lpOD->dwDrawAspect = dwAspect;
+ lpOD->sizel = *psizel;
+ lpOD->pointl = *ppointl;
+ lpOD->dwStatus = dwStatus;
+
+ GlobalUnlock(hMem);
+ return(hMem);
+
+error:
+ if (hMem)
+ {
+ GlobalUnlock(hMem);
+ GlobalFree(hMem);
+ }
+
+ return(NULL);
+}
+
+
+#pragma SEG(wOwnerLinkClassIsStdOleLink)
+STATIC INTERNAL_(BOOL) wOwnerLinkClassIsStdOleLink(BOOL fOpenClipbrd)
+{
+ VDATEHEAP();
+
+ BOOL f = FALSE;
+ LPOLESTR sz = NULL;
+ HANDLE h; // handle for clipboard data
+
+ if (fOpenClipbrd && !OpenClipboard(GetClipboardWindow()))
+ return(FALSE);
+
+ h = GetClipboardData(cfOwnerLink);
+ ErrZ(h);
+ sz = (LPOLESTR)GlobalLock(h);
+ ErrZ(sz);
+
+ f = (0 == _xstrcmp(szStdOleLink, sz));
+errRtn:
+ if (sz)
+ GlobalUnlock(h);
+ if (fOpenClipbrd)
+ Verify(CloseClipboard());
+
+ return(f);
+}
+
+
+#pragma SEG(IsNetDDEObjectLink)
+STATIC FARINTERNAL_(BOOL) IsNetDDEObjectLink(BOOL fMustOpen)
+{
+ VDATEHEAP();
+
+ BOOL fAnswer;
+ HANDLE hObjLink;
+ LPOLESTR pObjLink;
+
+ if (fMustOpen)
+ {
+ if (!OpenClipboard(GetClipboardWindow()))
+ return(TRUE); // cause a failure
+ }
+
+ hObjLink = GetClipboardData(cfObjectLink);
+ pObjLink = (LPOLESTR)GlobalLock(hObjLink);
+ if (NULL==pObjLink)
+ {
+ fAnswer = TRUE;// cause a failure
+ goto errRtn;
+ }
+
+ // Net DDE :"classnames" are of the form:
+ // \\machinename\NDDE$\0$pagename.ole
+
+ fAnswer = (OLESTR('\\')==pObjLink[0] && OLESTR('\\')==pObjLink[1]);
+ GlobalUnlock(hObjLink);
+
+errRtn:
+ if (fMustOpen)
+ CloseClipboard();
+
+ return(fAnswer);
+}
+
+
+
+// $$$ Continue
+// Handle cfEmbeddedObject, cfEmbedSource, cfLinkSource, cfObjectDescriptor,
+// cfLinkDesciptor
+//
+#pragma SEG(GetOle2Format)
+HRESULT GetOle2Format(LPFORMATETC pforetc, LPSTGMEDIUM pmedium)
+{
+ VDATEHEAP();
+
+ CLIPFORMAT cf; // local copy of pforetc->cfFormat
+ HRESULT hresult; // error state so far
+ DWORD cbDoc, cbClass, cbItemName;
+ HANDLE hOle1;
+ HANDLE hNative;
+ STGMEDIUM stgm;
+ CLSID clsid;
+ LPOLESTR szDoc;
+
+ // the following variables are used in error cleanup situations, and
+ // need to be initialized to NULL so the cleanup code does not try
+ // to free things that haven't been used
+ LPOLESTR szClass = NULL;
+ LPOLESTR szItemName = NULL;
+ IStream FAR* pstm = NULL;
+ IStorage FAR* pstg = NULL;
+
+ // validate parameters
+ VERIFY_LINDEX(pforetc->lindex);
+
+ cf = pforetc->cfFormat;
+
+ Assert ((cf == cfEmbeddedObject) || (cf == cfEmbedSource)
+ || (cf == cfLinkSource) || (cf == cfLinkSrcDescriptor)
+ || (cf == cfObjectDescriptor));
+
+ // Verify availability of format
+ if ((cf == cfEmbedSource) && (!IsClipboardFormatAvailable(cfNative) ||
+ !IsClipboardFormatAvailable(cfOwnerLink)))
+ {
+ return(ResultFromScode(DV_E_CLIPFORMAT));
+ }
+
+ if ((cf == cfObjectDescriptor) &&
+ !IsClipboardFormatAvailable(cfOwnerLink))
+ {
+ return(ResultFromScode(DV_E_CLIPFORMAT));
+ }
+
+ if (((cf == cfLinkSource) || (cf == cfLinkSrcDescriptor)) &&
+ (!IsClipboardFormatAvailable(cfObjectLink) ||
+ IsNetDDEObjectLink(TRUE)))
+ {
+ return(ResultFromScode(DV_E_CLIPFORMAT));
+ }
+
+ if (!OpenClipboard(GetClipboardWindow()))
+ return(ReportResult(0, CLIPBRD_E_CANT_OPEN, 0, 0));
+
+ // After this point, don't just return in case of error any more
+ // as the clipboard is open. From here on, either goto OK_Exit,
+ // or errRtn, depending on the reason for quitting.
+
+ if (cf == cfEmbeddedObject)
+ {
+ if (!IsClipboardFormatAvailable(cfOwnerLink) ||
+ (OrderingIs(cfNative, cfOwnerLink) &&
+ !wOwnerLinkClassIsStdOleLink(FALSE)))
+#ifdef NEVER
+/*
+REVIEW
+ChrisWe, 1/6/94. I'm not at all sure about this. The original code for the
+condition above is as below, with the unary negation. But it seems that
+If we want embedded source we want to fail if the cfOwnerLink is for a link,
+not if it isn't a link. The below code seems to agree with that.
+
+This agrees with what OleSetClipboard does when you try to put
+cfEmbeddedObject on the clipboard. All of the above are true, and everything
+is alright. I don't see how this negation can work on win16 unless there's
+a compiler bug or something weird is going on.
+*/
+ //!wOwnerLinkClassIsStdOleLink(FALSE)))
+#endif // NEVER
+ {
+ hresult = ResultFromScode (DV_E_CLIPFORMAT);
+ goto OK_Exit; // Close clipboard and exit
+ }
+ }
+
+ // Is it just a query?
+ if (pmedium == NULL)
+ {
+ hresult = NOERROR;
+ goto OK_Exit; // Close clipboard and exit
+ }
+
+ // Get all the data we need out of the OLE1 formats
+ hOle1 = GetClipboardData(((cf == cfEmbedSource) ||
+ (cf == cfEmbeddedObject) ||
+ (cf == cfObjectDescriptor)) ?
+ cfOwnerLink : cfObjectLink);
+ if (hOle1 == NULL)
+ {
+ hresult = ReportResult(0, DV_E_CLIPFORMAT, 0, 0);
+ goto errRtn;
+ }
+
+ szClass = (LPOLESTR)GlobalLock(hOle1);
+ if (szClass == NULL)
+ {
+ hresult = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ goto errRtn;
+ }
+
+ if ((hresult = wCLSIDFromProgID(szClass, &clsid,
+ /*fForceAssign*/ TRUE)) != NOERROR)
+ goto errRtn;
+
+ cbClass = _xstrlen(szClass) + 1;
+ szDoc = szClass + cbClass;
+ cbDoc = _xstrlen(szDoc) + 1;
+ szItemName = szDoc + cbDoc;
+ cbItemName = _xstrlen(szItemName) + 1;
+
+ if (cf == cfEmbedSource)
+ {
+ if (NULL == (hNative = GetClipboardData(cfNative)))
+ {
+ hresult = ReportResult(0, DV_E_CLIPFORMAT, 0, 0);
+ goto errRtn;
+ }
+ }
+
+ stgm = *pmedium; // just an alias mechanism
+ // REVIEW, NO, this makes a copy!!!
+
+ // Choose and allocate medium
+ if (pmedium->tymed == TYMED_NULL)
+ {
+ // none of our media need this
+ stgm.pUnkForRelease = NULL;
+
+ // GetData: Callee chooses medium
+ if (((cf == cfEmbedSource) || (cf == cfEmbeddedObject)) &&
+ (pforetc->tymed & TYMED_ISTORAGE))
+ {
+ // Choose Storage (Per spec)
+ stgm.tymed = TYMED_ISTORAGE;
+ hresult = StgCreateDocfile(NULL, STGM_CREATE |
+ STGM_SALL | STGM_DELETEONRELEASE,
+ 0, &pstg);
+ if (hresult != NOERROR)
+ goto errRtn;
+ stgm.pstg = pstg;
+ }
+ else if ((cf == cfLinkSource) &&
+ (pforetc->tymed & TYMED_ISTREAM))
+ {
+ // Choose Stream (Per spec)
+ stgm.tymed = TYMED_ISTREAM;
+ pstm = CreateMemStm((cbClass + cbDoc)*sizeof(OLECHAR),
+ NULL);
+ if (pstm == NULL)
+ {
+ hresult = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ goto errRtn;
+ }
+ stgm.pstm = pstm;
+ }
+ else if (((cf == cfLinkSrcDescriptor) ||
+ (cf == cfObjectDescriptor)) &&
+ (pforetc->tymed & TYMED_HGLOBAL))
+ {
+ // Do not need to allocate handle now,
+ // will be allocated below.
+ stgm.tymed = TYMED_HGLOBAL;
+ }
+ else
+ {
+ // don't understand any other media types
+ hresult = ResultFromScode(DV_E_TYMED);
+ goto errRtn;
+ }
+ }
+ else // GetDataHere
+ {
+ if ((((cf == cfEmbedSource) || (cf == cfEmbeddedObject)) &&
+ !(pmedium->tymed &= TYMED_ISTORAGE)) ||
+ (cf==cfLinkSource &&
+ !(pmedium->tymed &= TYMED_ISTREAM)) ||
+ (cf == cfObjectDescriptor) ||
+ (cf == cfLinkSrcDescriptor))
+ {
+ hresult = ResultFromScode(DV_E_TYMED);
+ goto errRtn;
+ }
+ }
+
+
+ // Write the data to the medium
+ switch (stgm.tymed)
+ {
+ case TYMED_ISTORAGE:
+ if (cf == cfEmbedSource)
+ {
+ if (!CoIsOle1Class(clsid))
+ {
+ hresult = wHandleToStorage(stgm.pstg, hNative);
+ if (hresult != NOERROR)
+ {
+ hresult = ResultFromScode(
+ DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+ }
+ else
+ {
+#ifdef WIN32 // REVIEW, no OLE1-2 interop
+ return(ReportResult(0, OLE_E_NOOLE1, 0, 0));
+#else
+ // Create a storage for a 1.0 object
+ ErrRtnH(WriteClassStg(stgm.pstg,clsid));
+
+ // If we ever decide to write a Format and
+ // User Type for link objects, we'll need to
+ // remove this check
+ if (clsid != CLSID_StdOleLink)
+ {
+ if (wWriteFmtUserType(stgm.pstg,clsid)
+ != NOERROR)
+ {
+ // This happens when the class
+ // is not registered. Use class
+ // name as user Type
+ WriteFmtUserTypeStg(stgm.pstg,
+ RegisterClipboardFormat(szClass),
+ szClass);
+ }
+ }
+ hresult = StSave10NativeData(stgm.pstg,
+ hNative, FALSE);
+ if (hresult != NOERROR)
+ {
+ hresult = ResultFromScode(
+ DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+ if (!IsBadReadPtr(szItemName, 1)
+ && (szItemName[0] != '\0'))
+ {
+ StSave10ItemName(stgm.pstg, szItemName);
+ }
+#endif // WIN32
+ }
+ }
+ else if (cf == cfEmbeddedObject)
+ {
+ hresult = wMakeEmbedObjForLink(stgm.pstg);
+ if (hresult != NOERROR)
+ {
+ hresult = ResultFromScode(DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+ }
+ else
+ {
+ Assert(0);
+ hresult = ResultFromScode(DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+ break;
+
+ case TYMED_ISTREAM:
+
+ if (NOERROR != (hresult = ObjectLinkToMonikerStream(szDoc,
+ cbDoc, clsid, stgm.pstm)))
+ {
+ AssertSz(0, "Cannot make Serialized moniker");
+ goto errRtn;
+ }
+
+ hresult = WriteClassStm(stgm.pstm, clsid);
+ break;
+
+ case TYMED_HGLOBAL:
+ {
+ LPOLESTR szSrcOfCopy;
+ STATIC const SIZEL sizel = {0, 0};
+ STATIC const POINTL pointl = {0, 0};
+ LONG cb; // holds the sizeof(szFullName), and the query
+ // return length
+ OLECHAR szFullName[256];
+
+ Assert((cf == cfObjectDescriptor) ||
+ (cf == cfLinkSrcDescriptor));
+ Assert(clsid != CLSID_NULL);
+
+ // allocate a string to hold the source name. Note that when
+ // this is composed below, we don't need to add an extra
+ // character for the '\\'; cbDob and cbItemName both already
+ // include the terminating NULL for the string, so the
+ // backslash simply occupies one of those
+ szSrcOfCopy = (LPOLESTR)PubMemAlloc((size_t)(cbDoc +
+ cbItemName)*sizeof(OLECHAR));
+ ErrZS(szSrcOfCopy, E_OUTOFMEMORY);
+
+ // construct the copy source name
+ _xstrcpy(szSrcOfCopy, szDoc);
+ _xstrcat(szSrcOfCopy, OLESTR("\\"));
+ _xstrcat(szSrcOfCopy, szItemName);
+
+ // NULL terminate the string in case it is left untouched
+ szFullName[0] = OLECHAR('\0');
+
+ // set the result buffer size, and query the registry
+ cb = sizeof(szFullName);
+ RegQueryValue(HKEY_CLASSES_ROOT, szClass, szFullName, &cb);
+
+ // check to see that the buffer was big enough for the name
+ // REVIEW, if asserts aren't in the retail code, then we should
+ // test for this, and possibly allocate a buffer big enough
+ Assert(cb <= sizeof(szFullName));
+
+ stgm.hGlobal = CreateObjectDescriptor(clsid, DVASPECT_CONTENT,
+ &sizel, &pointl,
+ OLEMISC_CANTLINKINSIDE | OLEMISC_CANLINKBYOLE1,
+ szFullName, szSrcOfCopy);
+
+ PubMemFree(szSrcOfCopy);
+ break;
+ }
+ default:
+ // catch any cases we missed
+ Assert(0);
+ }
+
+ // copy back the results
+ *pmedium = stgm;
+ goto OK_Exit;
+
+errRtn:
+ // free storage if we used it
+ if (pstg != NULL)
+ pstg->Release();
+
+ // free stream if we used it
+ if (pstm != NULL)
+ pstm->Release();
+
+OK_Exit:
+ if (szClass != NULL)
+ GlobalUnlock(hOle1);
+
+ if (!CloseClipboard())
+ hresult = ResultFromScode(CLIPBRD_E_CANT_CLOSE);
+
+ return(hresult);
+}
+
+
+#pragma SEG(Is10CompatibleLinkSource)
+STATIC INTERNAL Is10CompatibleLinkSource(LPDATAOBJECT pDataObj)
+{
+ VDATEHEAP();
+
+ FORMATETC formatetc;
+ STGMEDIUM medium;
+ LPLINKSRCDESCRIPTOR pLinkDescriptor;
+ BOOL fCompatible;
+
+ INIT_FORETC(formatetc);
+ formatetc.cfFormat = cfLinkSrcDescriptor;
+ formatetc.tymed = TYMED_HGLOBAL;
+
+ RetErr(pDataObj->GetData(&formatetc, &medium));
+ pLinkDescriptor = (LPLINKSRCDESCRIPTOR)GlobalLock(medium.hGlobal);
+ RetZS(pLinkDescriptor, E_HANDLE);
+ fCompatible = (pLinkDescriptor->dwStatus & OLEMISC_CANLINKBYOLE1) != 0;
+ GlobalUnlock(medium.hGlobal);
+ ReleaseStgMedium(&medium);
+
+ return(fCompatible ? NOERROR : ResultFromScode(S_FALSE));
+}
+
+
+// returns clsid based on [LinkSrc,Object]Desciptor; for persist class from
+// ObjectDescriptor which is a link, returns CLSID_StdOleLink;
+// NOTE: the OLEMISC_ISLINKOBJECT bit is ignored in the link src descriptor.
+#pragma SEG(GetClassFromDescriptor)
+STATIC INTERNAL GetClassFromDescriptor(LPDATAOBJECT pDataObj, LPCLSID pclsid,
+ BOOL fLink, BOOL fUser, LPOLESTR FAR* pszSrcOfCopy)
+{
+ VDATEHEAP();
+
+ FORMATETC formatetc;
+ STGMEDIUM medium;
+ LPOBJECTDESCRIPTOR pObjDescriptor;
+ HRESULT hresult;
+
+ INIT_FORETC(formatetc);
+ formatetc.cfFormat = fLink ? cfLinkSrcDescriptor : cfObjectDescriptor;
+ formatetc.tymed = TYMED_HGLOBAL;
+ medium.tymed = TYMED_NULL;
+
+ hresult = pDataObj->GetData(&formatetc, &medium);
+ AssertOutStgmedium(hresult, &medium);
+ if (hresult != NOERROR)
+ return(hresult);
+
+ pObjDescriptor = (LPOBJECTDESCRIPTOR)GlobalLock(medium.hGlobal);
+ RetZS(pObjDescriptor, E_HANDLE);
+ *pclsid = (!fLink && !fUser &&
+ (pObjDescriptor->dwStatus & OLEMISC_ISLINKOBJECT)) ?
+ CLSID_StdOleLink : pObjDescriptor->clsid;
+ if (pszSrcOfCopy)
+ {
+ *pszSrcOfCopy = UtDupString((LPOLESTR)
+ (((BYTE FAR *)pObjDescriptor) +
+ pObjDescriptor->dwSrcOfCopy));
+ }
+ GlobalUnlock(medium.hGlobal);
+ ReleaseStgMedium(&medium);
+
+ return(NOERROR);
+}
+
+
+#pragma SEG(SetOle1ClipboardFormats)
+FARINTERNAL SetOle1ClipboardFormats(LPDATAOBJECT pDataObj)
+{
+ VDATEHEAP();
+
+ HRESULT hresult; // error state so far
+ LPENUMFORMATETC penumFormatEtc; // the data object's FORMATETC enum
+ FORMATETC foretc; // used to hold the results of the enumerator Next()
+ BOOL fLinkSourceAvail = FALSE;
+ BOOL fLinkSrcDescAvail = FALSE;
+ BOOL fEmbedObjAvail = FALSE;
+ CLSID clsid;
+
+ // Enumerate all formats offered by data object, set clipboard
+ // with formats retrievable onhGbal.
+ hresult = pDataObj->EnumFormatEtc(DATADIR_GET, &penumFormatEtc);
+ if (hresult != NOERROR)
+ return(hresult);
+
+ while((hresult = penumFormatEtc->Next(1, &foretc, NULL)) == NOERROR)
+ {
+ if ((foretc.cfFormat == cfEmbedSource) ||
+ (foretc.cfFormat == cfEmbeddedObject))
+ {
+ if (foretc.cfFormat == cfEmbeddedObject)
+ fEmbedObjAvail = TRUE;
+
+ // get the clsid of the object; user .vs. persist
+ // clsid ignored since we only test against the
+ // clsids below.
+ if (NOERROR == GetClassFromDescriptor(pDataObj, &clsid,
+ FALSE, FALSE, NULL) &&
+ !IsEqualCLSID(clsid,
+ CLSID_StaticMetafile) &&
+ !IsEqualCLSID(clsid, CLSID_StaticDib))
+ {
+ SetClipboardData(cfNative, NULL);
+ SetClipboardData(cfOwnerLink, NULL);
+ }
+ }
+ else if (foretc.cfFormat == cfLinkSource)
+ {
+ fLinkSourceAvail = TRUE;
+ }
+ else if (foretc.cfFormat == cfLinkSrcDescriptor)
+ {
+ fLinkSrcDescAvail = TRUE;
+ }
+ else
+ {
+ // use only those TYMEDs OLE1 supported
+ // make sure it is available
+ // use first (highest fidelity) one enumerated
+ if ((NULL == foretc.ptd) &&
+ (foretc.tymed & (TYMED_HGLOBAL |
+ TYMED_GDI | TYMED_MFPICT)) &&
+ (NOERROR == pDataObj->QueryGetData(
+ &foretc)) &&
+ !IsClipboardFormatAvailable(
+ foretc.cfFormat))
+ {
+ SetClipboardData(foretc.cfFormat, NULL);
+ }
+ }
+
+ PubMemFree(foretc.ptd);
+ }
+
+ // Do not allow 1.0 link to 2.0 embedded object.
+ if (fLinkSourceAvail && !fEmbedObjAvail &&
+ (NOERROR == Is10CompatibleLinkSource(pDataObj)))
+ {
+ // ObjectLink should be after any presentation formats
+ SetClipboardData(cfObjectLink, NULL);
+ if (fLinkSrcDescAvail)
+ {
+ // Only offer LinkSrcDesc if offering a link, ie,
+ // ObjectLink. If clipboard is flushed, we don't want
+ // to offer LinkSrcDesc thru the DataObj if we are not
+ // offering LinkSrc.
+ SetClipboardData(cfLinkSrcDescriptor, NULL);
+ }
+ }
+
+ // Were they all enumerated successfully?
+ if (GetScode(hresult) == S_FALSE)
+ hresult = NOERROR;
+
+ // release the enumerator
+ penumFormatEtc->Release();
+
+ return(hresult);
+}
+
+
+// RemoveClipDataObject
+//
+// Called from: WM_RENDERALLFORMATS, WM_DESTROYCLIPBOARD therefore
+// clipboard is already open.
+// We use hClipDataObj instead of calling GetClipboardData(cfDataObj)
+// because GetClipboardData returns NULL (without asking us to render
+// cfDataObject)--Windows bug?
+//
+
+#pragma SEG(RemoveClipDataObject)
+STATIC INTERNAL_(void) RemoveClipDataObject(void)
+{
+ VDATEHEAP();
+
+ IStream FAR* pStm;
+
+ if (pClipDataObj == NULL)
+ {
+ Assert(NULL == hClipDataObj);
+ return;
+ }
+
+ if (hClipDataObj != NULL)
+ {
+ pStm = CloneMemStm(hClipDataObj);
+ Assert(pStm != NULL);
+ CoReleaseMarshalData(pStm);
+ pStm->Release();
+
+ ReleaseMemStm(&hClipDataObj, /*fInternalOnly*/TRUE);
+ hClipDataObj = NULL;
+ SetClipboardData(cfDataObject, NULL);
+ // hClipDataObj freed by call !!
+ }
+ else
+ {
+ // The Clipboard Data Object was never rendered.
+ }
+
+ CoDisconnectObject(pClipDataObj, 0);
+ pClipDataObj->Release();
+ pClipDataObj = NULL;
+}
+
+
+// $$$
+// Windows specifics
+//
+
+// Worker routines for ClipboardWndProc()
+//
+
+STATIC LRESULT RenderDataObject(void);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// RenderOle1Format, static
+//
+// Synopsis:
+// Ask object for data in the clip format that corresponds to the
+// requested Ole1 clip format, which is one of cfOwnerLink,
+// cfObjectLink, or cfNative.
+//
+// REVIEW, what does this mean? Is this an internal comment?
+// Note that pDataObj should never point to a fake data object
+// because it is either pClipDataObj or pointer to a proxy to an
+// object pointed by pClipDataObj.
+//
+// Arguments:
+// [cf] -- the desired clipboard format
+// [pDataObj] -- pointer to the IDataObject instance to get the
+// required rendition from
+//
+// Returns:
+// A handle to memory containing the format. This memory handle
+// is allocated appropriately for being placed on the clipboard.
+// If the call is unsuccessful, the handle is NULL.
+//
+// Notes:
+//
+// History:
+// 12/13/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+STATIC HANDLE RenderOle1Format(CLIPFORMAT cf, LPDATAOBJECT pDataObj);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// RenderFormat, static
+//
+// Synopsis:
+//REVIEW
+// Ask object for data in the requested clip format.
+// Ole1, Ole2 clip formats are not (and shouldn't be) handled.
+// This is for private clipformats.
+//
+// Arguments:
+// [cf] -- the requested clipboard format
+// [pDataObj] -- the data object to get the rendition from
+//
+// Requires:
+//
+// Returns:
+//
+// Notes:
+//
+// History:
+// 12/13/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+STATIC HANDLE RenderFormat(CLIPFORMAT cf, LPDATAOBJECT pDataObj);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// RenderFormatAndAspect, static
+//
+// Synopsis:
+// Allocate a new handle and render the requested data aspect
+// in the requested format into it.
+//
+// Arguments:
+// [cf] -- the desired clipboard format
+// [pDataObj] -- the IDataObject to get the data from
+// [dwAspect] -- the desired aspect
+//
+// Returns:
+// the newly allocated handle, or NULL.
+//
+// Notes:
+//
+// History:
+// 12/13/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+STATIC HANDLE RenderFormatAndAspect(CLIPFORMAT cf, LPDATAOBJECT pDataObj,
+ DWORD dwAspect);
+
+
+#ifndef _MAC
+
+STATIC HWND hwndClipboard = NULL; // Window used for Ole clipboard handling
+
+
+// Process delayed rendering messages.
+
+#pragma SEG(ClipboardWndProc)
+extern "C" LRESULT CALLBACK __loadds ClipboardWndProc(HWND hwnd,
+ UINT message, WPARAM wparam, LPARAM lparam)
+{
+ VDATEHEAP();
+
+ HANDLE hMem;
+ CLIPFORMAT cf;
+
+ switch(message)
+ {
+ case WM_RENDERFORMAT:
+
+ cf = wparam;
+
+ if (cf == cfDataObject)
+ return(RenderDataObject());
+
+ // An app had opened the clipboard and tried to get
+ // a format with a NULL handle. Ask object to provide data.
+ //
+ // Note that that while the above if() is executed in the
+ // context of the process owning the clipboard (that is
+ // pClipDataObj is valid) the code below may or may not
+ // that of the clipboard owner.
+ if (pClipDataObj == NULL)
+ return(0);
+
+ if ((cf == cfOwnerLink) || (cf == cfObjectLink) ||
+ (cf == cfNative))
+ hMem = RenderOle1Format(cf, pClipDataObj);
+ else
+ hMem = RenderFormat(cf, pClipDataObj);
+
+ if (hMem != NULL)
+ {
+ SetClipboardData(cf, hMem);
+ }
+
+
+ return(0);
+
+ case WM_RENDERALLFORMATS:
+
+ // Server app is going away.
+ // Open the clipboard and render all intresting formats.
+ if (!OpenClipboard(GetClipboardWindow()))
+ return(0);
+
+ if (pClipDataObj)
+ {
+ RemoveClipDataObject();
+ wEmptyClipboard();
+ }
+
+ // else clipboard was flushed, so we don't want to empty it
+ Verify(CloseClipboard());
+
+ return(0);
+
+ case WM_DESTROYCLIPBOARD:
+ // Another app is empting the clipboard; remove
+ // DataObject (if any).
+ // Note that that app had opened the clipboard
+
+ RemoveClipDataObject();
+
+ return(0);
+ }
+
+ return(DefWindowProc(hwnd, message, wparam, lparam));
+}
+#endif // _MAC
+
+
+// An app tries to get access to object on clipboard
+// Marshall its interface. Note that while that app
+// may or may not be the process that owns the clipboard
+// the code below is always executed by the clipboard owner.
+//
+// "..., which makes the passed IDataObject accessible
+// from the clipboard"
+//
+#pragma SEG(RenderDataObject)
+STATIC LRESULT RenderDataObject(void)
+{
+ VDATEHEAP();
+
+ HRESULT hresult;
+ HANDLE hMem;
+ IStream FAR* pStm;
+
+ if (pClipDataObj == NULL)
+ return(0);
+
+ // Create shared memory stream to Marshal object's interface
+ pStm = CreateMemStm(MARSHALINTERFACE_MIN, &hMem);
+ if (pStm == NULL)
+ return(0);
+
+ // REVIEW - If data object's server is not running
+ // MarshalInterface will fail. It is possible (per spec)
+ // for an app to set the clipboard with a pointer to
+ // an object whose server is a different process (i.e.
+ // with a pointer to defhdnlr).
+ hresult = CoMarshalInterface(pStm, IID_IDataObject,
+ pClipDataObj, 0, NULL, MSHLFLAGS_TABLESTRONG);
+ pStm->Release();
+ if (hresult != NOERROR)
+ {
+ GlobalFree(hMem);
+ return(0);
+ }
+
+ SetClipboardData(cfDataObject, hMem);
+ hClipDataObj = hMem;
+ OleSetEnumFormatEtc(pClipDataObj, TRUE /*fClip*/);
+ return(0);
+}
+
+
+INTERNAL wSzFixNet(LPOLESTR FAR* pszIn)
+{
+ VDATEHEAP();
+
+#ifdef REVIEW32
+//this doesn't seem to link well...look at it later
+
+ LPBC pbc = NULL;
+ UINT dummy = 0xFFFF;
+ LPOLESTR szOut = NULL;
+ HRESULT hresult= NOERROR;
+
+ RetErr(CreateBindCtx(0, &pbc));
+ ErrRtnH(SzFixNet(pbc, *pszIn, &szOut, &dummy));
+ if (szOut)
+ {
+ delete *pszIn;
+ *pszIn = szOut;
+ }
+
+ // else leave *pszIn unchanged
+errRtn:
+ if (pbc)
+ pbc->Release();
+ return(hresult);
+
+#endif //REVIEW32
+ return(E_NOTIMPL);
+}
+
+
+// MakeObjectLink
+//
+// Take the stream returned by GetData(CF_LINKSOURCE), which should be
+// positioned just before the moniker,
+// and create a clipboard handle for format ObjectLink or OwnerLink.
+// (They look the same.)
+//
+// On entry:
+// *ph is an un-alloc'd (probably NULL) handle
+//
+// On exit:
+// If successful:
+// *ph is the Owner/ObjectLink
+// return NOERROR
+// If cannot make ObjectLink: (because there are > 1 ItemMonikers)
+// *ph = NULL
+// return S_FALSE
+//
+//
+// Stream ::= FileMoniker [:: ItemMoniker]
+// ObjectLink ::= szClsid\0szFile\0szItem\0\0
+//
+#pragma SEG(MakeObjectLink)
+INTERNAL MakeObjectLink(LPDATAOBJECT pDataObj, LPSTREAM pStream,
+ LPHANDLE ph, BOOL fOwnerLink)
+{
+ VDATEHEAP();
+
+ HRESULT hr;
+ LPMONIKER pmk = NULL; // the moniker reconstituted from the stream
+ LPOLESTR szFile = NULL;
+ size_t cbFile; // length of szFile, if not NULL
+ LPOLESTR szItem = NULL;
+ size_t cbItem; // length of szItem, if not NULL
+ CLSID clsid;
+ LPOLESTR pszCid = NULL;
+ size_t cbCid; // length of pszCid, if not NULL
+#ifdef MAYBE_LATER
+ LPMONIKER pmkReduced= NULL;
+ LPBC pbc = NULL;
+#endif // MAYBE_LATER
+ UINT cb; // length of string to allocate for object link
+ LPOLESTR pch; // used to rove over the object link and fill it in
+ LARGE_INTEGER large_integer; // sets the seek position in the stream
+
+ // validate ph
+ VDATEPTROUT(ph, HANDLE);
+
+ // initialize this in case of error returns
+ *ph = NULL;
+
+ // validate remaining parameters
+ VDATEIFACE(pDataObj);
+ VDATEIFACE(pStream);
+
+ // move to the beginning of the stream
+ LISet32(large_integer, 0);
+ if (NOERROR != (hr = pStream->Seek(large_integer, STREAM_SEEK_SET,
+ NULL)))
+ {
+ AssertSz (0, "Cannot seek to beginning of stream\r\n");
+ goto errRtn;
+ }
+
+ // get the link moniker in active form
+ if (NOERROR != (hr = OleLoadFromStream(pStream, IID_IMoniker,
+ (LPLPVOID)&pmk)))
+ {
+ AssertSz (0, "Cannot get moniker from stream");
+ goto errRtn;
+ }
+
+#ifdef MAYBE_LATER
+ // Reduction
+ if (NOERROR != (hr = CreateBindCtx(&pbc)))
+ {
+ AssertSz(0, "Cannot create bind ctx");
+ goto errRtn;
+ }
+
+ if (NOERROR != (hr = pmk->Reduce(pbc, MKRREDUCE_ALL, NULL,
+ &pmkReduced)))
+ {
+ AssertSz(0, "Cannot reduce moniker");
+ goto errRtn;
+ }
+
+ if (pmkReduced != NULL)
+ {
+ pmk->Release();
+ pmk = pmkReduced;
+ pmkReduced = NULL; // for ref counting reasons
+ }
+ else
+ {
+ Assert (hr == MK_REDUCED_TO_SELF);
+ }
+#endif // MAYBE_LATER
+
+ // We now have the moniker, pmk.
+//REVIEW32 Ole10_ParseMoniker has been temporarily removed
+
+ if (!fOwnerLink /* && (NOERROR != Ole10_ParseMoniker(pmk,
+ &szFile, &szItem)) */)
+ {
+ // Not a File or File::Item moniker
+ hr = ReportResult(0, S_FALSE, 0, 0);
+ goto errRtn;
+ }
+
+ wSzFixNet(&szFile);
+
+ // Determine class to put in first piece of ObjectLink
+ if (NOERROR != ReadClassStm(pStream, &clsid))
+ {
+ // get the clsid if the link source for use in ObjectLink
+ if (NOERROR != (hr = GetClassFromDescriptor(pDataObj, &clsid,
+ TRUE, TRUE, NULL)))
+ {
+ AssertSz (0, "Cannot determine clsid for file");
+ goto errRtn;
+ }
+ }
+
+ if ((hr = ProgIDFromCLSID(clsid, &pszCid)) != NOERROR)
+ goto errRtn;
+
+ // Allocate the ObjectLink handle.
+ cb = (cbCid = _xstrlen(pszCid)) + (cbFile = _xstrlen(szFile)) +
+ (szItem ? (cbItem = _xstrlen(szItem)) : 0) +
+ 4; // for the \0's
+ *ph = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cb*sizeof(OLECHAR));
+ if (NULL == *ph)
+ {
+ hr= ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ goto errRtn;
+ }
+
+ pch = (LPOLESTR)GlobalLock(*ph);
+ if (NULL == pch)
+ {
+ hr = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ GlobalFree(*ph);
+ *ph = NULL;
+ goto errRtn;
+ }
+
+ // Fill in the ObjectLink handle.
+ _xstrcpy(pch, pszCid);
+ pch += cbCid + 1; // skip over string and its null terminator
+
+ // add the filename, and skip over its null terminator
+ if ((NULL == szFile) || fOwnerLink)
+ *pch++ = '\0';
+ else
+ {
+ _xstrcpy(pch, szFile);
+ pch += cbFile + 1;
+ }
+
+ // embedded 2.0 objs should have no item
+ if ((NULL == szItem) || fOwnerLink)
+ *pch++ = '\0';
+ else
+ {
+ _xstrcpy(pch, szItem);
+ pch += cbItem + 1;
+ }
+
+ // add final null terminator
+ *pch++ = '\0';
+
+ GlobalUnlock(*ph);
+
+errRtn:
+ if (pmk)
+ pmk->Release();
+#ifdef MAYBE_LATER
+ if (pbc)
+ pbc->Release();
+#endif // MAYBE_LATER
+ if (pszCid)
+ PubMemFree(pszCid);
+ if (szFile)
+ PubMemFree(szFile);
+ if (szItem)
+ PubMemFree(szItem);
+
+ return(hr);
+}
+
+
+#pragma SEG(wNativeStreamToHandle)
+STATIC INTERNAL wNativeStreamToHandle(LPSTREAM pstm, LPHANDLE ph)
+{
+ VDATEHEAP();
+
+ HRESULT hresult = NOERROR;
+ DWORD dwSize; // the size of the stream content, stored in the stream
+ LPVOID pv;
+
+ ErrRtnH(StRead(pstm, &dwSize, sizeof(DWORD)));
+
+ ErrZS(*ph = GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, dwSize),
+ E_OUTOFMEMORY);
+ ErrZS(pv = GlobalLock(*ph), E_OUTOFMEMORY);
+ ErrRtnH(StRead(pstm, pv, dwSize));
+
+errRtn:
+ if (pv)
+ GlobalUnlock(*ph);
+
+ return(hresult);
+}
+
+
+#pragma SEG(wStorageToHandle)
+STATIC INTERNAL wStorageToHandle(LPSTORAGE pstg, LPHANDLE ph)
+{
+ VDATEHEAP();
+
+ CLSID clsid;
+ HRESULT hresult = NOERROR; // error state so far
+ LPLOCKBYTES plbData = NULL; // lock bytes on HGlobal instance
+ LPSTORAGE pstgLB = NULL; // IStorage on ILockBytes on HGlobal
+
+ // validate parameters
+ VDATEPTROUT(ph, HANDLE);
+
+ RetErr(CreateILockBytesOnHGlobal(NULL, /*fDeleteOnRelease*/ FALSE,
+ &plbData));
+
+ ErrRtnH(StgCreateDocfileOnILockBytes(plbData, STGM_CREATE | STGM_SALL,
+ 0, &pstgLB));
+
+ // We remove the cache streams first, then copy, for three reasons:
+ // 1. We are free to modify pstg; it was the result of a GetData.
+ // 2. The CopyTo will have less work.
+ // 3. Presumably the ultimate docfile on memory will be less sparse
+ // (since we are not removing anything from it).
+
+ // read the class id
+ // REVIEW, why? This is not ever used anywhere!!! Can we remove it?
+ ErrRtnH(ReadClassStg(pstg, &clsid));
+
+ // remove the cache streams
+ ErrRtnH(UtDoStreamOperation(pstg, NULL, OPCODE_REMOVE,
+ STREAMTYPE_CACHE));
+
+ // Copy what was given to us into a storage we can convert to a handle
+ ErrRtnH(pstg->CopyTo(0, NULL, NULL, pstgLB));
+
+ ErrRtnH(GetHGlobalFromILockBytes(plbData, ph));
+
+errRtn:
+ if (plbData)
+ plbData->Release();
+ if (pstgLB)
+ pstgLB->Release();
+
+ return(hresult);
+}
+
+
+#pragma SEG(wProgIDFromCLSID)
+FARINTERNAL wProgIDFromCLSID(REFCLSID clsid, LPOLESTR FAR* psz)
+{
+ VDATEHEAP();
+
+ HRESULT hresult;
+
+ if (NOERROR == (hresult = ProgIDFromCLSID(clsid, psz)))
+ return(NOERROR);
+
+ if (IsEqualCLSID(clsid, CLSID_StdOleLink))
+ {
+ *psz = UtDupString(szStdOleLink);
+ return(NOERROR);
+ }
+
+ return(hresult);
+}
+
+
+#pragma SEG(wCLSIDFromProgID)
+FARINTERNAL wCLSIDFromProgID(LPOLESTR szClass, LPCLSID pclsid,
+ BOOL fForceAssign)
+{
+ VDATEHEAP();
+
+ size_t len;
+ LONG cbValue;
+ OLECHAR sz[400];
+
+ if (0 == _xstrcmp(szClass, szStdOleLink))
+ {
+ *pclsid = CLSID_StdOleLink;
+ return NOERROR;
+ }
+
+#ifdef NEVER
+//REVIEW32: taken out for the moment
+ return(ResultFromScode(E_NOTIMPL));
+#endif // NEVER
+ // return(CLSIDFromOle1Class(szClass, pclsid, fForceAssign));
+//REVIEW
+ // This code is taken directly from the original 16 bit ole2 release
+ // implementation of CLSIDFromOle1Class. The Ole1 compatibility lookup
+ // is omitted. That implementation was in base\compapi.cpp
+ len = _xstrlen(szClass);
+ _xmemcpy((void *)sz, szClass, len*sizeof(OLECHAR));
+ sz[len] = OLESTR('\\');
+ _xstrcpy(sz+len+1, OLESTR("Clsid"));
+ if (RegQueryValue(HKEY_CLASSES_ROOT, sz, sz, &cbValue) == 0)
+ return(CLSIDFromString(sz, pclsid));
+
+ return(ResultFromScode(REGDB_E_KEYMISSING));
+}
+
+#pragma SEG(wGetEmbeddedObjectOrSource)
+FARINTERNAL wGetEmbeddedObjectOrSource (LPDATAOBJECT pDataObj,
+ LPSTGMEDIUM pmedium)
+{
+ VDATEHEAP();
+
+ HRESULT hresult;
+ FORMATETC foretc;
+
+ // Prepare formatetc
+ INIT_FORETC(foretc);
+ foretc.tymed = TYMED_ISTORAGE;
+
+ // Prepare medium for GetDataHere calls
+ pmedium->pUnkForRelease = NULL;
+ pmedium->tymed = TYMED_ISTORAGE;
+ RetErr(StgCreateDocfile(NULL,
+ STGM_CREATE | STGM_SALL | STGM_DELETEONRELEASE,
+ 0, &(pmedium->pstg)));
+
+ // Try cfEmbeddedObject Here
+ foretc.cfFormat = cfEmbeddedObject;
+ hresult = pDataObj->GetDataHere(&foretc,pmedium);
+ if (NOERROR == hresult)
+ return NOERROR;
+
+ // Try cfEmbedSource Here
+ foretc.cfFormat = cfEmbedSource;
+ hresult = pDataObj->GetDataHere(&foretc,pmedium);
+ if (NOERROR == hresult)
+ return NOERROR;
+
+ // Prepare medium for GetData calls, free temp stg
+ ReleaseStgMedium(pmedium);
+
+ // Try cfEmbeddedObject
+ foretc.cfFormat = cfEmbeddedObject;
+ hresult = pDataObj->GetData(&foretc,pmedium);
+ AssertOutStgmedium(hresult, pmedium);
+ if (NOERROR == hresult)
+ return NOERROR;
+
+ // Try cfEmbedSource
+ foretc.cfFormat = cfEmbedSource;
+ hresult = pDataObj->GetData(&foretc,pmedium);
+ AssertOutStgmedium(hresult, pmedium);
+ if (NOERROR == hresult)
+ return NOERROR;
+
+ // Failure
+ return(ResultFromScode(DV_E_FORMATETC));
+}
+
+
+#pragma SEG(RenderOle1Format)
+STATIC HANDLE RenderOle1Format(CLIPFORMAT cf, LPDATAOBJECT pDataObj)
+{
+ VDATEHEAP();
+
+ HRESULT hresult; // errors state so far
+ STGMEDIUM stgm; // dummy storage medium where returned handle may
+ // be created
+
+ // following variables are initialized so they can be used in error
+ // condition cleanup at the end of the function
+ LPSTREAM pstmNative = NULL; // native format stream that some formats
+ // may use
+ LPOLESTR pszCid = NULL; // a string that is the object class name
+ HANDLE hMem = NULL; // return value
+
+ // initialize the storage medium
+ stgm.tymed = TYMED_NULL;
+ stgm.pstg = NULL;
+ stgm.pUnkForRelease = NULL;
+
+ if (cf == cfOwnerLink)
+ {
+ LPOLESTR szSrcOfCopy; // text name of object being transferred
+ LPOLESTR pMem; // access to locked hMem
+ size_t uCidLen; // length of pszCid
+ size_t uSrcOfCopyLen; // length of szSrcOfCopy
+ CLSID clsid; // class id of the object being transferred
+
+ // get the clsid from the object; we care about getting the link
+ // clsid if the object is indeed a link.
+ ErrRtnH(GetClassFromDescriptor(pDataObj, &clsid, FALSE,
+ FALSE, &szSrcOfCopy));
+
+ // cfObjectDescriptor -> OwnerLink szClassname\0\0\0\0
+
+ // converts the link clsid specially
+ ErrRtnH(wProgIDFromCLSID(clsid, &pszCid));
+
+ uCidLen = _xstrlen(pszCid);
+ uSrcOfCopyLen = szSrcOfCopy ? _xstrlen(szSrcOfCopy) : 0;
+ hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE,
+ (uCidLen + uSrcOfCopyLen + 4)* sizeof(OLECHAR));
+ ErrZS(hMem, E_OUTOFMEMORY);
+
+ pMem = (LPOLESTR)GlobalLock(hMem);
+ ErrZS(pMem, E_OUTOFMEMORY);
+
+ // create the owner link format
+ _xmemcpy((void FAR *)pMem, (const void FAR *)pszCid,
+ uCidLen*sizeof(OLECHAR));
+ pMem += uCidLen;
+ *pMem = OLESTR('\0');
+ _xmemcpy((void FAR *)++pMem, (const void FAR *)szSrcOfCopy,
+ uSrcOfCopyLen*sizeof(OLECHAR));
+ pMem += uSrcOfCopyLen;
+ *pMem = OLESTR('\0');
+ *++pMem = OLESTR('\0');
+
+ PubMemFree(szSrcOfCopy);
+ GlobalUnlock(hMem);
+ }
+ else if (cf == cfObjectLink)
+ {
+ FORMATETC foretc; // format descriptor for rendition request
+
+ INIT_FORETC(foretc);
+
+ // First check if cfObjectLink is offered by the DataObject
+ // directly. Servers do this when they want OLE1 containers
+ // to link to something different from what OLE2 containers
+ // link to. For instance, they may provide a wrapper object
+ // of their own class so OLE1 conatiners can link to the
+ // outside of an embedded object.
+ foretc.tymed = TYMED_HGLOBAL;
+ foretc.cfFormat = cfObjectLink;
+ hresult = pDataObj->GetData(&foretc, &stgm);
+ AssertOutStgmedium(hresult, &stgm);
+ if (NOERROR == hresult)
+ hMem = UtDupGlobal(stgm.hGlobal, GMEM_MOVEABLE);
+ else
+ {
+ // Otherwise generate the ObjectLink from cfLinkSource
+ foretc.tymed = TYMED_ISTREAM;
+ foretc.cfFormat = cfLinkSource;
+
+ hresult = pDataObj->GetData(&foretc,&stgm);
+ AssertOutStgmedium(hresult, &stgm);
+ if (hresult != NOERROR)
+ {
+ Warn("Could not GetData(cfLinkSource, TYMED_ISTREAM)");
+ return(NULL);
+ }
+
+ // cfLinkSource -> ObjectLink ==
+ // szClassName\0szFile\0szItem\0\0
+ ErrRtnH(MakeObjectLink(pDataObj, stgm.pstm, &hMem,
+ FALSE));
+ }
+ }
+ else if (cf == cfNative)
+ {
+ ErrRtnH(wGetEmbeddedObjectOrSource(pDataObj, &stgm));
+
+ if (NOERROR == stgm.pstg->OpenStream(OLE10_NATIVE_STREAM, NULL,
+ STGM_SALL, 0, &pstmNative))
+ {
+ ErrRtnH(wNativeStreamToHandle(pstmNative, &hMem));
+ }
+ else
+ {
+ ErrRtnH(wStorageToHandle(stgm.pstg, &hMem));
+ }
+ Assert(hMem);
+ }
+ else
+ {
+ // unknown format
+ return(NULL);
+ }
+
+errRtn:
+ ReleaseStgMedium(&stgm);
+ if (pstmNative)
+ pstmNative->Release();
+ if ((hresult != NOERROR) && (hMem != NULL))
+ {
+ GlobalFree(hMem);
+ hMem = NULL;
+ }
+ PubMemFree(pszCid);
+ return(hMem);
+}
+
+
+#pragma SEG(RenderFormatAndAspect)
+STATIC HANDLE RenderFormatAndAspect(CLIPFORMAT cf, LPDATAOBJECT pDataObj,
+ DWORD dwAspect)
+{
+ VDATEHEAP();
+
+ HRESULT hresult;
+ HANDLE hMem; // the return value
+ FORMATETC foretc; // the format descriptor for data requests based on cf
+ STGMEDIUM stgm; // the storage medium for data requests
+
+ // REVIEW: if object can't return hglobal probably should try all
+ // possible mediums, convert to hglobal. For now only try hglobal.
+
+ // initialize format descriptor
+ INIT_FORETC(foretc);
+ foretc.cfFormat = cf;
+ foretc.tymed = UtFormatToTymed(cf);
+ foretc.dwAspect = dwAspect;
+
+ // initialize medium for fetching
+ stgm.tymed = TYMED_NULL;
+ stgm.hGlobal = NULL;
+
+ hresult = pDataObj->GetData(&foretc, &stgm);
+ AssertOutStgmedium(hresult, &stgm);
+ if (hresult != NOERROR)
+ goto ErrorExit;
+
+ if (stgm.pUnkForRelease == NULL)
+ hMem = stgm.hGlobal;
+ else
+ {
+ hMem = OleDuplicateData(stgm.hGlobal, foretc.cfFormat,
+ GMEM_DDESHARE | GMEM_MOVEABLE);
+
+ ReleaseStgMedium(&stgm);
+ }
+
+ return(hMem);
+
+ErrorExit:
+ return(NULL);
+}
+
+
+#pragma SEG(RenderFormat)
+STATIC HANDLE RenderFormat(CLIPFORMAT cf, LPDATAOBJECT pDataObj)
+{
+ VDATEHEAP();
+
+ HANDLE h;
+
+ if (h = RenderFormatAndAspect(cf, pDataObj, DVASPECT_CONTENT))
+ return(h);
+
+ if (h = RenderFormatAndAspect(cf, pDataObj, DVASPECT_DOCPRINT))
+ return(h);
+
+ if (h = RenderFormatAndAspect(cf, pDataObj, DVASPECT_THUMBNAIL))
+ return(h);
+
+ return(RenderFormatAndAspect(cf, pDataObj, DVASPECT_ICON));
+}
+
+
+
+// Mapping of thread ID to a clipboard window handle.
+// WIN32 : Only looks for thread IDs of the current process; resides in
+// instance data.
+// REVIEW, if the OLE compound document model is single-threaded, do we need
+// this? There should only be one thread ID => one window handle
+STATIC CMapUintHwnd FAR * pTaskToClip = NULL;
+
+#ifndef _MAC
+// Get clipboard window handle of the current process.
+//
+
+#pragma SEG(GetClipboardWindow)
+HWND GetClipboardWindow(void)
+{
+ VDATEHEAP();
+
+ HWND hwnd;
+
+ if ((NULL == pTaskToClip) &&
+ (pTaskToClip = new CMapUintHwnd()) == NULL)
+ return NULL;
+
+ if (!pTaskToClip->Lookup(GetCurrentThreadId(), hwnd))
+ {
+ // Create an invisible window which will handle all of this
+ // app's delay rendering messages. Even though hInstance is
+ // specified as being the DLL's rather than the app's, the
+ // thread whose stack this function is called with is the one
+ // whose msg queue will be associated with this window.
+ hwnd = CreateWindow(szClipboardWndClass, OLESTR(""), WS_POPUP,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, NULL, NULL, hmodOLE2,
+ NULL);
+
+ if (hwnd != NULL)
+ Verify(pTaskToClip->SetAt(GetCurrentThreadId(), hwnd));
+ }
+
+ return(hwnd);
+}
+#endif // _MAC
+
+
+// this keeps track of the number of times the clipboard has been
+// initialized; it is incremented for each initialization, and decremented
+// for each uninitialization
+// REVIEW, does this variable have to be per-thread, or per-process for the DLL?
+STATIC ULONG cClipboardInit = 0;
+
+#pragma SEG(ClipboardInitialize)
+FARINTERNAL_(BOOL) ClipboardInitialize(void)
+{
+ VDATEHEAP();
+
+#ifndef _MAC
+ WNDCLASS wc;
+
+ // One time initializtaion (when loaded for the first time)
+ if (cClipboardInit++ == 0)
+ {
+ // The first process to load this DLL
+
+ // Register Clipboard window class
+ wc.style = 0;
+ wc.lpfnWndProc = ClipboardWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 4; // REVIEW, what's this the sizeof()?
+ wc.hInstance = hmodOLE2;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = szClipboardWndClass;
+
+ // register this window class, returning if we fail
+ if (!RegisterClass(&wc))
+ {
+ cClipboardInit--;
+ return(FALSE);
+ }
+ }
+
+ // Remove the current htask from the map; the only reason this
+ // htask would be in the map is that it got reused
+ // REVIEW, if CD model is single threaded, do we need this?
+ if (pTaskToClip != NULL)
+ pTaskToClip->RemoveKey(GetCurrentThreadId());
+
+#endif // _MAC
+ return(TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ClipboardUninitialize
+//
+// Synopsis:
+//
+// Effects:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 15-Feb-94 AlexT Added delete call (and this comment block)
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(ClipboardUninitialize)
+FARINTERNAL_(void) ClipboardUninitialize(void)
+{
+ VDATEHEAP();
+
+#ifndef _MAC
+ HWND hwnd;
+
+ // REVIEW, do we need this pTaskToClip stuff?
+ if (pTaskToClip != NULL &&
+ pTaskToClip->Lookup(GetCurrentThreadId(), hwnd))
+ {
+ DestroyWindow(hwnd);
+
+ pTaskToClip->RemoveKey(GetCurrentThreadId());
+ }
+
+ // Last process using this DLL?
+ if (--cClipboardInit == 0)
+ {
+ // NULL out in case dll is not actually unloaded
+
+ delete pTaskToClip;
+ pTaskToClip = NULL;
+
+ // since the last reference has gone away, unregister wnd class
+ UnregisterClass(szClipboardWndClass, hmodOLE2);
+ }
+#endif // _MAC
+}
+
+
+STATIC INTERNAL_(BOOL) wEmptyClipboard(void)
+{
+ VDATEHEAP();
+
+ OleRemoveEnumFormatEtc(TRUE /*fClip*/);
+ return(EmptyClipboard());
+}
diff --git a/private/ole32/ole232/clipbrd/clipdata.cpp b/private/ole32/ole232/clipbrd/clipdata.cpp
new file mode 100644
index 000000000..a3c3860f1
--- /dev/null
+++ b/private/ole32/ole232/clipbrd/clipdata.cpp
@@ -0,0 +1,5544 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: clipdata.cpp
+//
+// Contents: implementation of CClipDataObject
+//
+// Classes:
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH added Dump method to CClipDataObject,
+// CClipEnumFormatEtc and added APIs
+// DumpCClipDataObject, DumpCClipEnumFormatEtc
+// 09-Jan-95 t-scotth changed VDATETHREAD to accept a pointer, and
+// ensured VDATETHREAD is before VDATEPTRIN and
+// VDATEPTROUT
+// 21-Nov-94 alexgo added thread validation
+// 11-Aug-94 alexgo added support for EmbeddedObject from
+// OLE1 formats.
+// 04-Jun-94 alexgo now converts OLE1 formats into OLE2
+// 30-May-94 alexgo now supports enhanced metafiles
+// 17-May-94 alexgo now use OleOpenClipboard instead of
+// OpenClipboard.
+// 11-May-94 alexgo eliminated allocations for 0
+// bytes from the enumerator.
+// 02-Apr-94 alexgo author
+//
+// Notes:
+// This file is laid out as follows:
+// ClipboardDataObject private methods
+// ClipboardDataObject IDataObject methods
+// OLE1 support functions (in alphabetical order)
+// Formatetc Enumerator methods
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#include <getif.hxx>
+#include "clipdata.h"
+#include "clipbrd.h"
+#include <ostm2stg.h> //for wCLSIDFromProgID and GenericObjectToIStorage
+
+#ifdef _DEBUG
+#include <dbgdump.h>
+#endif // _DEBUG
+
+// helper function used by the data object and formatetc enumerator
+HRESULT BmToPres(HANDLE hBM, PPRES ppres);
+BOOL CanRetrieveOle2FromOle1( UINT cf);
+HRESULT DibToPres(HANDLE hDib, PPRES ppres);
+BOOL IsOwnerLinkStdOleLink( void );
+HRESULT MfToPres( HANDLE hMFPict, PPRES ppres);
+HRESULT NativeToStorage(IStorage *pstg, HANDLE hNative);
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::CClipDataObject
+//
+// Synopsis: constructor
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: initializes reference count to 1
+
+//
+// History: dd-mmm-yy Author Comment
+// 02-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CClipDataObject::CClipDataObject( )
+{
+ m_refs = 1;
+ m_rgFormats = NULL;
+ m_cFormats = 0;
+
+ // OLE1 support stuff
+
+ m_hOle1 = NULL;
+ m_pUnkOle1 = NULL;
+
+ // Data object to use to get the data.
+ m_pDataObject = NULL;
+
+ m_fTriedToGetDataObject = FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::~CClipDataObject
+//
+// Synopsis: destructor
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: frees the formatetc array (if one exists)
+//
+// History: dd-mmm-yy Author Comment
+// 19-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CClipDataObject::~CClipDataObject( )
+{
+ PrivMemFree(m_rgFormats); // will accept NULL
+
+ if (m_pDataObject != NULL)
+ {
+ // Release our reference to the data object.
+ m_pDataObject->Release();
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::GetDataObjectForClip (private)
+//
+// Synopsis: Get clip board data object from the clipboard
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: If we've tried this before, then return; otherwise:
+// Open the clipboard. Get the data object from the clipboard
+// if it is there. Close the clipboard and update our private
+// member.
+//
+// History: dd-mmm-yy Author Comment
+// 12-Aug-94 alexgo handle identity better
+// 17-Jun-94 alexgo optimized
+// 13-Jun-94 Ricksa author
+//
+// Notes: We must only try to get the real data object once in order
+// to preserve OLE identity. Recall that we call this function
+// if somebody does a QI for IUnknown. Now suppose that
+// GetInterfaceFromWindowProp fails for a 'benign' reason
+// (like we're in the middle of processing a send message).
+// Our QueryInterface will then return *our* IUnknown, thus
+// establishing the identity of this object to be CClipDataObject.
+//
+// Now suppose another call to QI for IUnknown is made. If
+// we simply noticed that m_pDataObject was NULL and called
+// GetInterfaceFromWindowProp again, it could succeed and we
+// would return a *different* IUnknown (thus violating OLE
+// object identity).
+//
+// For this reason, we only allow one call to
+// GetInterfaceFromWindowProp.
+//
+// Note that it is not strictly necessary to disable multiple
+// calls to GetInterfaceFromWindowProp for GetData and
+// GetDataHere methods. Neither of these methods affect
+// object identity. However, for the sake of consistency and
+// simplicity (!), we treat GetData and QI the same.
+//
+//--------------------------------------------------------------------------
+
+void CClipDataObject::GetDataObjectForClip( )
+{
+ HGLOBAL hDataObject;
+ HWND * phClipWnd;
+ HWND hClipWnd = NULL;
+ HRESULT hresult;
+
+#if DBG == 1
+ BOOL fCloseClipSucceeded;
+#endif // DBG
+
+ LEDebugOut((DEB_ITRACE,
+ "%p _IN CClipDataObject::GetDataObjectForClip ( )\n", this));
+
+
+ // if we already have a data object, or we've already tried and failed
+ // to get one, then we don't need to do any work here.
+
+ if( m_pDataObject || m_fTriedToGetDataObject == TRUE )
+ {
+ goto logRtn;
+ }
+
+ // if cfDataObject is not on the clipboard, don't bother opening it;
+ // we know that we can't get a data object.
+
+ if( !SSIsClipboardFormatAvailable(g_cfDataObject) )
+ {
+ goto errRtn;
+ }
+
+ //
+ //
+ // BEGIN: OPEN CLIPBOARD
+ //
+ //
+
+ // Open the clipboard in preparation for the get
+ hresult = OleOpenClipboard(NULL, NULL);
+
+ if( hresult != NOERROR )
+ {
+ LEDebugOut((DEB_ERROR, "ERROR: OleOpenClipboard failed!\n"));
+ goto errRtn;
+ }
+
+ hDataObject = SSGetClipboardData(g_cfDataObject);
+
+ if( hDataObject )
+ {
+ phClipWnd = (HWND *)GlobalLock(hDataObject);
+
+ LEERROR(phClipWnd == NULL, "GlobalLock failed!");
+
+ if( phClipWnd )
+ {
+ hClipWnd = *phClipWnd;
+ GlobalUnlock(hDataObject);
+ }
+ }
+
+
+#if DBG == 1
+ fCloseClipSucceeded =
+
+#endif // DBG
+
+ SSCloseClipboard();
+
+#if DBG == 1
+ // We only report this error in debug
+ if (!fCloseClipSucceeded)
+ {
+ LEDebugOut((DEB_ERROR, "ERROR: CloseClipboard failed!\n"));
+ }
+
+#endif // DBG
+
+ //
+ //
+ // END: CLOSE CLIPBOARD
+ //
+ //
+
+ if( hClipWnd )
+ {
+ // See if we can get a data object
+ hresult = GetInterfaceFromWindowProp( hClipWnd,
+ IID_IDataObject,
+ (IUnknown **) &m_pDataObject,
+ CLIPBOARD_DATA_OBJECT_PROP );
+
+
+#if DBG ==1
+ if( hresult != NOERROR )
+ {
+ Assert(m_pDataObject == NULL);
+ }
+ else
+ {
+ Assert(m_pDataObject != NULL);
+ }
+#endif // DBG == 1
+
+ }
+
+errRtn:
+ // if we didn't get a data object, then set a flag so we
+ // don't try to do this again.
+
+ if( m_pDataObject == NULL )
+ {
+ m_fTriedToGetDataObject = TRUE;
+ }
+
+logRtn:
+
+ LEDebugOut((DEB_ITRACE,
+ "%p OUT CClipDataObject::GetDataObjectForClip ( ) "
+ "[ %p ]\n", this, m_pDataObject));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::MatchFormatetc
+//
+// Synopsis: checks the given formatetc against the array of formatetc's
+// the clipdata data source supports
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- the formatetc to check
+// [ptymed] -- where to stuff the tymed of the *original*
+// formatetc (may be NULL)
+//
+// Requires:
+//
+// Returns: FormatMatchFlag --
+// FORMAT_NOTFOUND
+// FORMAT_BADMATCH
+// FORMAT_GOODMATCH
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 18-Aug-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+FormatMatchFlag CClipDataObject::MatchFormatetc( FORMATETC *pformatetc,
+ TYMED *ptymed )
+{
+ ULONG i;
+ FormatMatchFlag fFlag = FORMAT_NOTFOUND;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::MatchFormatetc ("
+ " %p , %p)\n", this, pformatetc, ptymed));
+
+ if( ptymed )
+ {
+ *ptymed = TYMED_NULL;
+ }
+ if( m_rgFormats )
+ {
+ for( i = 0; i < m_cFormats; i++ )
+ {
+ // if the clipboard format matchs AND
+ // the aspect matches AND
+ // the tymed matches
+ // then, return success
+
+ if( m_rgFormats[i].cfFormat ==
+ pformatetc->cfFormat)
+ {
+ // we don't need to check TYMED because
+ // this clipboard data object can satisfy
+ // almost all valid TYMED's, and specfically,
+ // more than will be contained in the
+ // formatetc tymed field.
+
+
+ // Bug#9384 - Visio16 (3.0) or's together what aspects it
+ // supports so have to and out Aspect we are interested in.
+ //
+ // If the current format aspect is 0, then good match.
+ //
+ if( ( (m_rgFormats[i].dwAspect & pformatetc->dwAspect) == pformatetc->dwAspect) ||
+ m_rgFormats[i].dwAspect == 0)
+ {
+ fFlag = FORMAT_GOODMATCH;
+
+ // keep track of the tymed
+ if( ptymed )
+ {
+ // this cast is a cute one;
+ // formatetc.tymed is
+ // actually declared to be
+ // a DWORD, since compiler
+ // type-checking is a bad
+ // thing in OLE16.
+ *ptymed = (TYMED)
+ m_rgFormats[i].tymed;
+ }
+ }
+ else
+ {
+ fFlag = FORMAT_BADMATCH;
+ }
+ }
+ }
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::MatchFormatetc ("
+ "%lx )\n", this, fFlag));
+
+ return fFlag;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::Create (static)
+//
+// Synopsis: Creates a new Clipboard data object
+//
+// Effects:
+//
+// Arguments: [ppDataObj] -- where to put the data object
+// [cFormats] -- the count of formatetcs
+// [prgFormats] -- the array of formatetcs (may be NULL)
+//
+// Requires: the clipboard must be open
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: Creates a new data object, initializing an internal
+// formatetc array if g_cfOlePrivateData is available.
+//
+// History: dd-mmm-yy Author Comment
+// 19-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT CClipDataObject::Create( IDataObject **ppDataObj,
+ FORMATETC *prgFormats, DWORD cFormats )
+{
+ HRESULT hresult = NOERROR;
+ CClipDataObject * pClipData;
+
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::Create ( %p )\n",
+ NULL, ppDataObj));
+
+ pClipData = new CClipDataObject();
+
+ if( pClipData )
+ {
+ pClipData->m_cFormats = cFormats;
+ pClipData->m_rgFormats = prgFormats;
+
+ *ppDataObj = pClipData;
+ }
+ else
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::Create ( %lx ) "
+ "[ %lx ]\n", NULL, hresult, *ppDataObj));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::QueryInterface
+//
+// Synopsis: returns requested interfaces
+//
+// Effects:
+//
+// Arguments: [riid] -- the requested interface
+// [ppvObj] -- where to put the interface pointer
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: Since we always create one of these data objects for
+// OleGetClipboard, we need to be careful about how we
+// handle QueryInterface since apps are free to QI for IFoo
+//
+// Identity laws: for each object with identity, QI for
+// IUnknown should always return the same
+// IUnknown. However, IFoo-->IUnknown-->IFoo
+// does NOT have to give you back the same
+// IFoo. We take advantage of this loophole.
+//
+// QI for:
+// IDataObject: always return a pointer to us (the fake
+// data object)
+// IFoo: if we can get a pointer back to the
+// original data object, delegate to it.
+// Note that a QI back to IDataObject will
+// not get back to this fake data object
+// IUnknown: as above, delegate to the real data object
+// if available. If we're in the remote case,
+// we'll end up getting the standard identity
+// object's IUnknown (unless the data object
+// was custom-marshalled).
+//
+// History: dd-mmm-yy Author Comment
+// 02-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipDataObject::QueryInterface( REFIID riid, LPVOID *ppvObj )
+{
+ HRESULT hresult = NOERROR;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::QueryInterface "
+ "( %p , %p )\n", this, riid, ppvObj));
+
+ // We always return our data object if IDataObject is requested.
+ if( IsEqualIID(riid, IID_IDataObject) )
+ {
+ *ppvObj = this;
+ AddRef();
+ goto logRtn;
+ }
+
+ // try to get the remote data object;
+ // GetDataObjectForClip will set m_pDataObject.
+ GetDataObjectForClip();
+
+ if (m_pDataObject != NULL)
+ {
+ // If we have a real data object, the we use that to give us
+ // the new interface since they probably want something strange
+ hresult = m_pDataObject->QueryInterface(riid, ppvObj);
+ }
+ else if( IsEqualIID(riid, IID_IUnknown) )
+ {
+ *ppvObj = this;
+ AddRef();
+ }
+ else
+ {
+ *ppvObj = NULL;
+ hresult = ResultFromScode(E_NOINTERFACE);
+ }
+
+logRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::QueryInterface "
+ "( %lx ) [ %p ]\n", this, hresult, *ppvObj ));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::AddRef
+//
+// Synopsis: increments the reference count
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG-- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CClipDataObject::AddRef( )
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::AddRef ( )\n", this));
+
+ ++m_refs;
+
+ LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::AddRef ( %lu )\n",
+ this, m_refs));
+
+ return m_refs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::Release
+//
+// Synopsis: decrements the reference count on the object
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CClipDataObject::Release( )
+{
+ ULONG cRefs;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::Release ( )\n", this));
+
+ if( (cRefs = --m_refs ) == 0 )
+ {
+ LEDebugOut((DEB_TRACE, "%p DELETED CClipDataObject\n", this));
+ delete this;
+ }
+
+ // using "this" below is OK, since we only want its value
+ LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::Release ( %lu )\n",
+ this, cRefs));
+
+ return cRefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::GetData
+//
+// Synopsis: retrieves data of the specified format
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- the requested format
+// [pmedium] -- where to put the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: General algorithm: we *always* duplicate data from the
+// clipboard and offer it back to the caller in the desired
+// format.
+//
+// GDI objects (BITMAPs, metafiles): these are duplicated
+// via OleDuplicateData and offered back only if
+// the requested tymed is correct (i.e. either
+// TYMED_GDI or TYMED_MFPICT). We do not attempt
+// to extract the bits and write them into a file,
+// for example. Note that DIBs are really memory
+// objects.
+//
+// for all other formats (which are flat):
+//
+// if asked for TYMED_FILE: create a temporary file and call
+// GetDataHere.
+// if asked for TYMED_ISTREAM: create a stream on an hglobal
+// and call GetDataHere.
+// if asked for TYMED_HGLOBAL: simply duplicate the data and
+// return.
+// if asked for TYMED_ISTORAGE, we will create a storage on
+// an hglobal and call GetDataHere. GetDataHere
+// will call StgIsStorageILockBytes to verify that
+// the data in the HGlobal is really a flattened
+// storage. This allows apps to pass app-defined
+// formats as storages.
+//
+// Note that we do no checking on whether it is sensible
+// for data in a particular flat format to be passed on
+// a storage. StgIsStorageILockBytes will detect that
+// we can't construct a storage on the flat data, so we
+// will catch all illegal attempts to get storage data.
+//
+// Medium preferences:
+// GDI objects: only one allowed (depends on format)
+// Others: ISTORAGE, then HGLOBAL, then ISTREAM,
+// then FILE. If we know the 'prefered' medium
+// of the data (from the original formatetc),
+// then we use the ordering above to find the
+// first match between what the caller wants
+// and the 'preferred' mediums of the data.
+// Otherwise, we use the first medium from the
+// above list that matches what the caller wants.
+//
+//
+// OLE1 Compatibility:
+// The basic problem: Ole1 objects only offer cfNative,
+// cfOwnerLink, and/or cfObjectLink on the clipboard.
+// We need to translate these into cfEmbedSource,
+// cfLinkSource, etc.
+// Basic Algorithm:
+// First check to see if we can satisfy an OLE2 data
+// request directly, without medium translation. If so,
+// then we simply return the data to the user.
+// Otherwise, we create the Ole2 data and then copy it
+// into whatever medium the caller desired. Note that
+// this potentially means an extra allocation, but apps
+// are not likely to ask for ObjectDescriptor on a
+// memory stream ;-)
+//
+//
+// History: dd-mmm-yy Author Comment
+// 04-Jun-94 alexgo added OLE1 support
+// 02-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipDataObject::GetData( LPFORMATETC pformatetc, LPSTGMEDIUM
+ pmedium)
+{
+ HRESULT hresult = NOERROR;
+ HANDLE handle;
+ TYMED tymedOriginal = TYMED_NULL;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ VDATEPTRIN(pformatetc, FORMATETC);
+ VDATEPTROUT(pmedium, STGMEDIUM);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::GetData ( %p , %p )\n",
+ this, pformatetc, pmedium));
+
+
+ // zero the pmedium structure.
+
+ _xmemset(pmedium, 0, sizeof(STGMEDIUM));
+
+ // try to get the remote data object
+ // GetDataObjectForClip will set m_pDataObject.
+ GetDataObjectForClip();
+
+
+ if (m_pDataObject != NULL)
+ {
+ // We have a data object, so just forward that call to the
+ // real data object and then exit the routine since it did
+ // all the work.
+ hresult = m_pDataObject->GetData(pformatetc, pmedium);
+
+ // WOW HACK alert! Some Win16 apps, like Word6 and XL,
+ // won't work if we continue and offer data in the requested
+ // format anyway. By failing here, we more closely mimic
+ // 16bit OLE behaviour
+
+ if (hresult == NOERROR || IsWOWThread() )
+ {
+ goto errRtn;
+ }
+
+ // If this GetData failed, we just fall through since the
+ // generic code may be able to handle the request
+ }
+
+ // first, we are going through and verify that we can satisfy
+ // the format and medium request. We will fetch the data in
+ // the subsequent switch statement.
+
+ // we first need to check to see if the clipboard format is a
+ // user-defined GDI format. We do not know how to duplicate
+ // these, so we can't satisfy the GetData request.
+
+ if( pformatetc->cfFormat >= CF_GDIOBJFIRST &&
+ pformatetc->cfFormat <= CF_GDIOBJLAST )
+ {
+ hresult = ResultFromScode(DV_E_FORMATETC);
+ goto errRtn;
+ }
+
+ // WOW HACK alert! 16bit OLE code only allowed CONTENT and NULL
+ // aspect GetData calls. Unfortunately, this means that if an app put
+ // an ICON metafile on the clipboard, you could only retrieve it
+ // after shutdown as CONTENT (very weird). We preserve 16bit
+ // behaviour here but fix it for 32bit.
+
+ if( IsWOWThread() )
+ {
+ if( pformatetc->dwAspect != DVASPECT_CONTENT &&
+ pformatetc->dwAspect != NULL )
+ {
+ hresult = ResultFromScode(DV_E_FORMATETC);
+ goto errRtn;
+ }
+ }
+ else
+ {
+ // the only time we want to fail is if the caller
+ // requested something like metafile w/ aspect CONTENT
+ // and all we had was a metafile w/ aspect ICON.
+ //
+ // if the format wasn't found in our list, we may
+ // still be able to retrieve it because it may be
+ // a format synthesized by the win32 clipboard (like
+ // OEM_TEXT, etc).
+
+ // We also want to get the tymed of the original formatetc
+ // we'll use it below to better determine which tymed
+ // to user passes in tymed == -1 (like MFC does).
+
+ if( MatchFormatetc(pformatetc, &tymedOriginal) ==
+ FORMAT_BADMATCH )
+ {
+ hresult = ResultFromScode(DV_E_FORMATETC);
+ goto errRtn;
+ }
+ }
+
+
+ // now check for "standard" formats
+
+ switch( pformatetc->cfFormat )
+ {
+ case CF_BITMAP:
+ case CF_PALETTE:
+ // TYMED_GDI is the only medium we support.
+ if( (pformatetc->tymed & TYMED_GDI) )
+ {
+ pmedium->tymed = TYMED_GDI;
+ }
+ else
+ {
+ hresult = ResultFromScode(DV_E_TYMED);
+ goto errRtn;
+ }
+ break;
+
+ case CF_METAFILEPICT:
+ // TYMED_MFPICT is the only medium we support
+ if( (pformatetc->tymed & TYMED_MFPICT) )
+ {
+ pmedium->tymed = TYMED_MFPICT;
+ }
+ else
+ {
+ hresult = ResultFromScode(DV_E_TYMED);
+ goto errRtn;
+ }
+ break;
+
+ case CF_ENHMETAFILE:
+ // TYMED_ENHMF is the only medium we support
+
+ if( (pformatetc->tymed & TYMED_ENHMF) )
+ {
+ pmedium->tymed = TYMED_ENHMF;
+ }
+ else
+ {
+ hresult = ResultFromScode(DV_E_TYMED);
+ goto errRtn;
+ }
+ break;
+
+
+ // all other formats
+ default:
+ // we prefer TYMED_ISTORAGE, then TYMED_HGLOBAL, then
+ // TYMED_ISTREAM
+
+ // first check for matches with the 'preferred'
+ // mediums of the data
+
+ if( tymedOriginal != TYMED_NULL )
+ {
+ if( ((pformatetc->tymed & TYMED_ISTORAGE)
+ & tymedOriginal) )
+ {
+ pmedium->tymed = TYMED_ISTORAGE;
+ break;
+ }
+ else if( ((pformatetc->tymed & TYMED_HGLOBAL)
+ & tymedOriginal))
+ {
+ pmedium->tymed = TYMED_HGLOBAL;
+ break;
+ }
+ else if( ((pformatetc->tymed & TYMED_ISTREAM)
+ & tymedOriginal))
+ {
+ pmedium->tymed = TYMED_ISTREAM;
+ break;
+ }
+ }
+
+ // if we didn't match above or if we don't know
+ // the preferred formats, then make a best guess
+ // and keep going.
+
+ if( (pformatetc->tymed & TYMED_ISTORAGE) )
+ {
+ pmedium->tymed = TYMED_ISTORAGE;
+ }
+ else if( (pformatetc->tymed & TYMED_HGLOBAL) )
+ {
+ pmedium->tymed = TYMED_HGLOBAL;
+ }
+ else if( (pformatetc->tymed & TYMED_ISTREAM) )
+ {
+ pmedium->tymed = TYMED_ISTREAM;
+ }
+ else
+ {
+ hresult = ResultFromScode(DV_E_TYMED);
+ goto errRtn;
+ }
+ break;
+ }
+
+ // if we get this far, we've successfully picked the medium
+ // on which we want to get our data. For each medium, grab
+ // the data.
+
+ // If we need to construct OLE2 formats from OLE1 data,
+ // then go ahead and try to fetch the data here. If we can
+ // fetch the data in the desired medium, then go ahead and return.
+ // This optimization saves 1 extra allocation and copy when
+ // retrieving OLE1 data.
+
+ if( CanRetrieveOle2FromOle1(pformatetc->cfFormat) )
+ {
+ //
+ //
+ // BEGIN: OPENCLIPBOARD
+ //
+ //
+
+ hresult = OleOpenClipboard(NULL, NULL);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // now fetch the data. Since we're passing in the caller's
+ // pmedium, this call *may* fail (since GetOle2FromOle1
+ // *only* retrieves HGLOBAL or the native TYMED). If so,
+ // we'll fetch HGLOBAL from the OleGetClipboardData call
+ // below and then do the appropriate conversion.
+
+ hresult = GetOle2FromOle1(pformatetc->cfFormat, pmedium);
+
+ // no matter what the result, we want to close the
+ // clipboard
+
+ if( !SSCloseClipboard() )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: CloseClipboard "
+ "failed!\n"));
+ ; // no-op
+ }
+
+ //
+ //
+ // END: CLOSECLIPBOARD
+ //
+ //
+
+ if( hresult == NOERROR )
+ {
+ // we successfully retrieved the Ole2 data the
+ // caller wanted. First reset our state
+ // (*without* freeing the data we're returning
+ // to the caller) and then go ahead and
+ // return.
+
+ FreeResources(JUST_RESET);
+ goto errRtn;
+ }
+
+ // FALL-THROUGH. If we weren't able
+ // to retrieve data in the desired format, it probably
+ // means the caller was asking for data on non-primary
+ // medium. The default processing below should take care of
+ // this.
+
+ // Recall that this code block is an optimization to
+ // avoid multiple allocations and copies in the "normal"
+ // case.
+
+ }
+
+ switch( pmedium->tymed )
+ {
+ case TYMED_HGLOBAL:
+ case TYMED_MFPICT:
+ case TYMED_ENHMF:
+ case TYMED_GDI:
+ // Mini-algorithm: Open the clipboard, fetch and
+ // duplicate the data, then close the clipboard.
+
+ // we only open the clipboard here because the
+ // GetDataHere call will open the clipboard for
+ // the other cases. (Recall that OpenClipboard and
+ // CloseClipboard are not balanced; only one CloseClipboard
+ // is necessary to actually close the clipboard).
+
+ //
+ //
+ // BEGIN: OPENCLIPBOARD
+ //
+ //
+
+ hresult = OleOpenClipboard(NULL, NULL);
+
+ if( hresult != NOERROR )
+ {
+ break;
+ }
+
+ hresult = OleGetClipboardData(pformatetc->cfFormat, &handle);
+
+ if( hresult == NOERROR )
+ {
+ // since hGlobal is in a union, we don't need to
+ // explicity assign for each medium type.
+
+ pmedium->hGlobal = OleDuplicateData(handle,
+ pformatetc->cfFormat, NULL);
+ if( !pmedium->hGlobal )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ // FALL-THROUGH!!: this is deliberate; we want
+ // to close the clipboard and get out (which is
+ // what the code below does)
+ }
+ }
+
+ if( !SSCloseClipboard() )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: CloseClipboard failed!"
+ "\n"));
+
+ // don't overwrite the original error code
+ if( hresult == NOERROR )
+ {
+ hresult =
+ ResultFromScode(CLIPBRD_E_CANT_CLOSE);
+ }
+ // FALL-THROUGH!! to the break below;
+ }
+
+ //
+ //
+ // END: CLOSECLIPBOARD
+ //
+ //
+
+ break;
+
+ case TYMED_ISTREAM:
+ // create a memory stream.
+ hresult = CreateStreamOnHGlobal(NULL,
+ TRUE /*fDeleteOnRelease*/, &(pmedium->pstm));
+
+ if( hresult != NOERROR )
+ {
+ break;
+ }
+
+ hresult = GetDataHere( pformatetc, pmedium );
+
+ break;
+
+ case TYMED_ISTORAGE:
+ // create a memory storage (ILockBytes on top of a
+ // a docfile).
+
+ hresult = UtCreateStorageOnHGlobal(NULL,
+ TRUE /*fDeleteOnRelease*/, &(pmedium->pstg),
+ NULL);
+
+ if( hresult != NOERROR )
+ {
+ break;
+ }
+
+ hresult = GetDataHere( pformatetc, pmedium );
+
+ break;
+
+ case TYMED_FILE:
+ // create a temporary file
+ pmedium->lpszFileName = (LPOLESTR)PubMemAlloc( MAX_PATH +1 );
+
+ if( !pmedium->lpszFileName )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ break;
+ }
+
+ hresult = UtGetTempFileName( OLESTR("~OLE"),
+ pmedium->lpszFileName);
+
+ if( hresult == NOERROR )
+ {
+ hresult = GetDataHere( pformatetc, pmedium );
+ }
+ break;
+
+ default:
+ // should never get here
+ AssertSz(0, "Unknown TYMED for get Data");
+ hresult = ResultFromScode(E_UNEXPECTED);
+ break;
+ }
+
+ // NB!!! Do not put any extra processing here without modifying the
+ // error paths in the above switch (they just break, instead of
+ // doing a goto errRtn. This was done to avoid some duplicated
+ // code.
+
+ if( hresult != NOERROR )
+ {
+ // ReleaseStgMedium will correctly cleanup NULL and
+ // partially NULL mediums, so we can rely on it for
+ // general-purpose cleanup
+ ReleaseStgMedium(pmedium);
+ }
+
+ // no matter what the error code, we should reset our state and
+ // free any resources the OLE1 compatibility code may have allocated
+
+ FreeResources(RESET_AND_FREE);
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::GetData ( %lx )\n",
+ this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::GetDataHere
+//
+// Synopsis: retrieves data of the specified format
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- the requested format
+// [pmedium] -- where to put the data, if NULL, then
+// the call is treated as a Query.
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: General algorithm: we *always* duplicate data from the
+// clipboard and offer it back to the caller in the desired
+// medium. Since this is GetDataHere, we attempt to copy the
+// data into the medium provided by the caller.
+//
+// GDI objects (BITMAPs, metafiles): *cannot* be retrieved
+// by GetDataHere, since we do not translate GDI
+// objects into byte arrays and we cannot copy a
+// metafile into a metafile (for example).
+//
+// for all other formats (which are flat):
+//
+// if asked for TYMED_FILE: open the file for create/append and
+// write the data into it.
+// if asked for TYMED_ISTREAM: write the data into the stream
+// if asked for TYMED_HGLOBAL: verify first that the given
+// hglobal is big enough; if so, then copy the clipboard
+// data into it.
+//
+// if asked for TYMED_ISTORAGE: call StgIsStorageILockBytes
+// to verify that the data in the HGlobal is really
+// a flattened storage. This allows apps to pass
+// app-defined formats as storages.
+//
+// OLE1 Compatibility:
+// OleGetClipboardData will manufacture OLE2 formats from
+// OLE1 data as necessary. We simply take this handle and
+// copy it into the caller's medium (as with any other handle).
+//
+// History: dd-mmm-yy Author Comment
+// 04-Jun-94 alexgo added OLE1 support
+// 02-Apr-94 alexgo author
+//
+// Notes: The spec does not say that a NULL pmedium should be treated
+// as a Query; however the 16bit code did that and it was fairly
+// easy for us to duplicate that behaviour.
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipDataObject::GetDataHere( LPFORMATETC pformatetc, LPSTGMEDIUM
+ pmedium)
+{
+ HRESULT hresult = NOERROR;
+ HANDLE handle;
+ DWORD cbClipData;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ VDATEPTRIN(pformatetc, FORMATETC);
+
+ if( pmedium )
+ {
+ VDATEPTRIN(pmedium, STGMEDIUM);
+ }
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::GetDataHere ( %p , %p"
+ " )\n", this, pformatetc, pmedium));
+
+ // try to get the remote data object
+ // GetDataObjectForClip will set m_pDataObject.
+ GetDataObjectForClip();
+
+ if (m_pDataObject != NULL)
+ {
+ // We have a data object, so just forward that call to the
+ // real data object and then exit the routine since it did
+ // all the work.
+ hresult = m_pDataObject->GetDataHere(pformatetc, pmedium);
+
+ // If this this failed, we just fall through since the
+ // generic code may be able to handle the request
+
+ // WOW HACK alert! Some Win16 apps, like Word6 and XL,
+ // won't work if we continue and offer data in the requested
+ // format anyway. By failing here, we more closely mimic
+ // 16bit OLE behaviour
+
+ if (hresult == NOERROR || IsWOWThread() )
+ {
+ goto logRtn;
+ }
+
+ // If this GetDataHere failed, we just fall through since the
+ // generic code may be able to handle the request
+ }
+
+ // eliminate the GDI case immediately
+
+ // we do not satisfy requests to GetDataHere for a GDI object
+ // note that DIB's are really memory objects.
+
+ if( (pformatetc->cfFormat == CF_BITMAP) ||
+ (pformatetc->cfFormat == CF_PALETTE) ||
+ (pformatetc->cfFormat == CF_METAFILEPICT) ||
+ (pformatetc->cfFormat == CF_ENHMETAFILE) ||
+ (pformatetc->cfFormat >= CF_GDIOBJFIRST &&
+ pformatetc->cfFormat <= CF_GDIOBJLAST ))
+ {
+ hresult = ResultFromScode(DV_E_FORMATETC);
+ goto logRtn;
+ }
+
+ // WOW HACK alert! 16bit OLE code only allowed CONTENT and NULL
+ // aspect GetData calls. Unfortunately, this means that if an app put
+ // an ICON metafile on the clipboard, you could only retrieve it
+ // after shutdown as CONTENT (very weird). We preserve 16bit
+ // behaviour here but fix it for 32bit.
+
+ if( IsWOWThread() )
+ {
+ if( pformatetc->dwAspect != DVASPECT_CONTENT &&
+ pformatetc->dwAspect != NULL )
+ {
+ hresult = ResultFromScode(DV_E_FORMATETC);
+ goto logRtn;
+ }
+ }
+ else
+ {
+ // the only time we want to fail is if the caller
+ // requested something like metafile w/ aspect CONTENT
+ // and all we had was a metafile w/ aspect ICON.
+ //
+ // if the format wasn't found in our list, we may
+ // still be able to retrieve it because it may be
+ // a format synthesized by the win32 clipboard (like
+ // OEM_TEXT, etc).
+
+ if( MatchFormatetc(pformatetc, NULL) == FORMAT_BADMATCH )
+ {
+ hresult = ResultFromScode(DV_E_FORMATETC);
+ goto logRtn;
+ }
+ }
+
+ // If pmedium == NULL, then we will just
+ // query and leave. As noted above, this behavior is for 16bit
+ // compatibility.
+
+ if( !pmedium )
+ {
+ if( OleIsClipboardFormatAvailable(pformatetc->cfFormat) )
+ {
+ hresult = NOERROR;
+ }
+ else
+ {
+ hresult = ResultFromScode(DV_E_CLIPFORMAT);
+ }
+
+ goto logRtn;
+ }
+
+ //
+ //
+ // BEGIN: OPENCLIPBOARD
+ //
+ //
+
+ // open the clipboard and retrieve the data. Once we have it,
+ // we'll do a switch and stuff it into the right spot.
+
+ hresult = OleOpenClipboard(NULL, NULL);
+
+ if( hresult != NOERROR )
+ {
+ goto logRtn;
+ }
+
+ // now actually get the data
+
+ Assert(pmedium);
+
+ hresult = OleGetClipboardData(pformatetc->cfFormat, &handle);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // now copy the data into the given medium
+
+ // for everything but storages, we need to know the size of the
+ // data coming off the clipboard.
+
+ // note that we have a general problem with comparing sizes--
+ // GlobalSize returns the size of the *allocated* block, which
+ // is not the same as the size of the real data (which, in
+ // general, we have no way of determining).
+
+ // When transfering from HGLOBAL to HGBOBAL, we therefore have
+ // a boundary case where we actually have enough room to copy
+ // the *real* data from the clipboard, but the global block
+ // from the clipboard is bigger (causing a failure)
+
+ // If an app really cares, GetData should be called instead.
+
+ if( pmedium->tymed != TYMED_ISTORAGE )
+ {
+ cbClipData = GlobalSize(handle);
+
+ if( cbClipData == 0 )
+ {
+ // got bad data from the clipboard
+ hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
+ goto errRtn;
+ }
+ }
+
+ switch( pmedium->tymed )
+ {
+ case TYMED_HGLOBAL:
+ // if there is enough room to stuff the data in the given
+ // hglobal, then do so.
+
+ hresult = UtHGLOBALtoHGLOBAL( handle, cbClipData,
+ pmedium->hGlobal);
+ break;
+
+ case TYMED_ISTREAM:
+ // copy the data into the medium's stream
+
+ hresult = UtHGLOBALtoStm( handle, cbClipData, pmedium->pstm);
+ break;
+
+ case TYMED_ISTORAGE:
+ // create a storage on top of the HGLOBAL and CopyTo to the
+ // medium's storage. Note that this will only work if
+ // the HGLOBAL originally had a storage dumped on it
+
+ hresult = UtHGLOBALtoStorage( handle, pmedium->pstg);
+ break;
+
+ case TYMED_FILE:
+ // append the data into the file
+
+ hresult = UtHGLOBALtoFile( handle, cbClipData,
+ pmedium->lpszFileName);
+ break;
+
+ default:
+ // we can't GetDataHere into GDI objects!!! (etc).
+
+ hresult = ResultFromScode(DV_E_TYMED);
+ break;
+ }
+
+ // NB!!: Be careful about adding extra code here; the above
+ // switch does nothing special for error cases.
+
+errRtn:
+
+ if( !SSCloseClipboard() )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: CloseClipboard failed!\n"));
+ if( hresult == NOERROR )
+ {
+ hresult = ResultFromScode(CLIPBRD_E_CANT_CLOSE);
+ }
+ }
+
+ //
+ //
+ // END: CLOSECLIPBOARD
+ //
+ //
+
+ // now free any resources we may have used for OLE1 compatibility
+
+ FreeResources(RESET_AND_FREE);
+
+logRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::GetDataHere ( %lx )\n",
+ this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::QueryGetData
+//
+// Synopsis: queries whether a GetData call would succeed
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- the requested format
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: we simply see if the requested clipboard format is on the
+// clipboard.
+//
+// If we have an array of formatetcs (m_rgFormats from the
+// g_cfOlePrivateData clipboard data), then we use that info
+// to check. Otherwise, we will do as much checking as we can
+// without actually fetching the data.
+//
+// Note that this is not 100% accurate (because
+// we may not be able to get the data in the requested medium
+// (such as TYMED_ISTORAGE)). Without actually doing a GetData
+// call, however, this is the best we can do.
+//
+// History: dd-mmm-yy Author Comment
+// 04-Jun-94 alexgo added OLE1 support
+// 17-May-94 alexgo removed call to OpenClipboard
+// 02-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipDataObject::QueryGetData( LPFORMATETC pformatetc )
+{
+ HRESULT hresult = NOERROR;
+ FormatMatchFlag fFlag;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ VDATEPTRIN(pformatetc, FORMATETC);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::QueryGetData ( %p )\n",
+ this, pformatetc));
+
+
+ // we check if the clipboard format is available *before*
+ // checking the formatetc list as an optimization. If a previous
+ // attempt to render data had failed, then NT will remove that
+ // clipboard format from the clipboard.
+
+ if( OleIsClipboardFormatAvailable(pformatetc->cfFormat) )
+ {
+ fFlag = MatchFormatetc(pformatetc, NULL);
+
+ if( fFlag == FORMAT_GOODMATCH )
+ {
+ hresult = NOERROR;
+ goto errRtn;
+ }
+ else if( fFlag == FORMAT_BADMATCH )
+ {
+ hresult = ResultFromScode(DV_E_FORMATETC);
+ goto errRtn;
+ }
+
+ // even if we didn't match in the formatetc list,
+ // continue to check below. We can satisfy
+ // many more GetData requests than the app may
+ // have orginally.
+
+ // do all the verification we can without actually
+ // fetching the data
+
+
+ switch( pformatetc->cfFormat )
+ {
+ case CF_BITMAP:
+ case CF_PALETTE:
+ // GDI objects must be requested on TYMED_GDI
+ if( pformatetc->tymed != TYMED_GDI )
+ {
+ hresult = ResultFromScode(DV_E_TYMED);
+ }
+ break;
+
+ case CF_METAFILEPICT:
+ // metafiles must be on TYMED_MFPICT
+ if( pformatetc->tymed != TYMED_MFPICT )
+ {
+ hresult = ResultFromScode(DV_E_TYMED);
+ }
+ break;
+
+ case CF_ENHMETAFILE:
+ // enhanced metafiles must be on TYMED_ENHMF;
+ if( pformatetc->tymed != TYMED_ENHMF )
+ {
+ hresult = ResultFromScode(DV_E_TYMED);
+ }
+ break;
+
+ default:
+ // we cannot deal with special GDI objects
+ if( pformatetc->cfFormat >= CF_GDIOBJFIRST &&
+ pformatetc->cfFormat <= CF_GDIOBJLAST )
+ {
+ hresult = ResultFromScode(DV_E_FORMATETC);
+ break;
+ }
+
+ // we cannot put other formats onto metafiles
+ // or GDI objects
+
+ // failure case: if somebody requests
+ // TYMED_ISTORAGE but the actually hglobal on the
+ // clipboard does not contain storage-formated data
+
+ if( pformatetc->tymed == TYMED_GDI ||
+ pformatetc->tymed == TYMED_MFPICT ||
+ pformatetc->tymed == TYMED_ENHMF )
+ {
+ hresult = ResultFromScode(DV_E_TYMED);
+ }
+ break;
+ }
+ }
+ else
+ {
+ hresult = ResultFromScode(DV_E_CLIPFORMAT);
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::QueryGetData "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::GetCanonicalFormatEtc
+//
+// Synopsis: retrieve the canonical format
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- the requested format
+// [pformatetcOut] -- the canonical format
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: Since we always return the same data for each clipboard
+// format, this function is very simple (basically returns
+// the input formatetc, with a NULL target device).
+//
+// History: dd-mmm-yy Author Comment
+// 02-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipDataObject::GetCanonicalFormatEtc( LPFORMATETC pformatetc,
+ LPFORMATETC pformatetcOut)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ VDATEPTRIN(pformatetc, FORMATETC);
+ VDATEPTROUT(pformatetcOut, FORMATETC);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::GetCanonicalFormatEtc"
+ " ( %p , %p )\n", this, pformatetc, pformatetcOut));
+
+ // initialize the out param
+ INIT_FORETC(*pformatetcOut);
+
+ pformatetcOut->cfFormat = pformatetc->cfFormat;
+ pformatetcOut->tymed = pformatetc->tymed;
+
+ LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::GetCanonicalFormatEtc"
+ " ( %lx )\n", this, NOERROR ));
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::SetData
+//
+// Synopsis: sets data of the specified format
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- the format of the data
+// [pmedium] -- the data
+//
+// Requires:
+//
+// Returns: E_NOTIMPL
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipDataObject::SetData( LPFORMATETC pformatetc, LPSTGMEDIUM
+ pmedium, BOOL fRelease)
+{
+HRESULT hr;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ VDATEREADPTRIN(pformatetc, FORMATETC);
+ VDATEREADPTRIN(pmedium, STGMEDIUM);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::SetData ( %p , %p )\n",
+ this, pformatetc, pmedium));
+
+
+ // try to get the remote data object
+ // GetDataObjectForClip will set m_pDataObject.
+ GetDataObjectForClip();
+
+ if (NULL != m_pDataObject)
+ {
+ hr = m_pDataObject->SetData(pformatetc,pmedium,fRelease);
+ }
+ else
+ {
+ hr = E_FAIL;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::SetData ( %lx )\n",
+ this, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::EnumFormatEtc
+//
+// Synopsis: return an enumerator for the available data formats
+//
+// Effects:
+//
+// Arguments: [dwDirection] -- the direction (GET or SET)
+// [ppenum] -- where to put the enumerator
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: create a clipboard formatetc enumerator. Upon creation,
+// we'll grab everything off clipboard we need (so that simple
+// enumeration doesn't block access to the clipboard).
+//
+// History: dd-mmm-yy Author Comment
+// 02-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipDataObject::EnumFormatEtc( DWORD dwDirection,
+ LPENUMFORMATETC * ppenum )
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ VDATEPTROUT(ppenum, LPENUMFORMATETC);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipDataObject::EnumFormatEtc ( %lx "
+ ", %p )\n", this, dwDirection, ppenum));
+
+ // we can only enumerate in the GET direction
+
+ if( dwDirection != DATADIR_GET )
+ {
+ hresult = ResultFromScode(E_INVALIDARG);
+ goto errRtn;
+ }
+
+
+ hresult = CClipEnumFormatEtc::Create(ppenum, m_rgFormats, m_cFormats);
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CClipDataObject::EnumFormatEtc ( %lx )"
+ "\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::DAdvise
+//
+// Synopsis: register a data advise
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- the requested format
+// [dwAdvf] -- advise flags
+// [pAdvSink] -- the advise sink
+// [pdwConnection] -- where to put the connection ID
+//
+// Requires:
+//
+// Returns: OLE_E_ADVISENOTSUPPORTED
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipDataObject::DAdvise( LPFORMATETC pformatetc, DWORD dwAdvf,
+ IAdviseSink * pAdvSink, DWORD *pdwConnection )
+{
+ (void)pformatetc;
+ (void)dwAdvf;
+ (void)pAdvSink;
+ (void)pdwConnection;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_WARN, "WARNING: DAdvise on the clipboard data"
+ "object is not supported!\n"));
+
+ return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::DUnadvise
+//
+// Synopsis: unadvises an advise connection
+//
+// Effects:
+//
+// Arguments: [dwConnection] -- the connection to remove
+//
+// Requires:
+//
+// Returns: OLE_E_ADVISENOTSUPPORTED
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipDataObject::DUnadvise(DWORD dwConnection)
+{
+ (void)dwConnection;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_WARN, "WARNING: DUnadvise on the clipboard data"
+ "object is not supported!\n"));
+
+ return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::EnumDAdvise
+//
+// Synopsis: enumerates data advises
+//
+// Effects:
+//
+// Arguments: [ppenum] -- where to put the enumerator
+//
+// Requires:
+//
+// Returns: OLE_E_ADVISENOTSUPPORTED
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipDataObject::EnumDAdvise( LPENUMSTATDATA *ppenum)
+{
+ (void)ppenum;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_WARN, "WARNING: EnumDAdvise on the clipboard data"
+ "object is not supported!\n"));
+
+ return ResultFromScode(OLE_E_ADVISENOTSUPPORTED);
+}
+
+//
+// Private methods on CClipDataObject
+//
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::FreeResources (private)
+//
+// Synopsis: frees any resources allocated by OLE1 compatibility
+// code and resets state
+//
+// Effects:
+//
+// Arguments: [fFlags] -- either JUST_RESET or RESET_AND_FREE
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 04-Jun-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+void CClipDataObject::FreeResources( FreeResourcesFlags fFlags )
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::FreeResources "
+ "( %lx )\n", this, fFlags));
+
+ if( (fFlags & RESET_AND_FREE) )
+ {
+ if( m_hOle1 )
+ {
+ GlobalFree(m_hOle1);
+ }
+
+ if( m_pUnkOle1 )
+ {
+ m_pUnkOle1->Release();
+ }
+ }
+
+ m_hOle1 = NULL;
+ m_pUnkOle1 = NULL;
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::FreeResources "
+ "( )\n", this ));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::GetAndTranslateOle1 (private)
+//
+// Synopsis: Retrieves either cfOwnerLink or cfObjectLink from the
+// clipboard, reads the strings and converts to Unicode
+//
+// Effects: all strings will be allocated with the public allocator
+//
+// Arguments: [cf] -- the clipboard format to retrieve
+// must be either cfOwnerLink or cfObjectLink
+// [ppszClass] -- where to put the class name (may be NULL)
+// [ppszFile] -- where to put the file name (may be NULL)
+// [ppszItem] -- where to put the item name (may be NULL)
+// [ppszItemA] -- where to put the ANSI item name
+// (may be NULL)
+//
+// Requires: the clipboard must be open
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: cfOwnerLink and cfObjectLink are laid out as follows
+// classname\0filename\0\itemname\0\0
+// These strings are ANSI, so we must convert to unicode.
+//
+// History: dd-mmm-yy Author Comment
+// 04-Jun-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT CClipDataObject::GetAndTranslateOle1( UINT cf, LPOLESTR *ppszClass,
+ LPOLESTR *ppszFile, LPOLESTR *ppszItem, LPSTR *ppszItemA )
+{
+ LPSTR pszClassA = NULL,
+ pszFileA = NULL,
+ pszItemA = NULL;
+ HGLOBAL hOle1;
+ HRESULT hresult = NOERROR;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::GetAndTranslate"
+ "Ole1 ( %d , %p , %p , %p )\n", this, cf, ppszClass, ppszFile,
+ ppszItem));
+
+ Assert( cf == g_cfOwnerLink || cf == g_cfObjectLink );
+
+ // NULL out-params
+ if( ppszClass )
+ {
+ *ppszClass = NULL;
+ }
+ if( ppszFile )
+ {
+ *ppszFile = NULL;
+ }
+ if( ppszItem )
+ {
+ *ppszItem = NULL;
+ }
+
+ hOle1 = SSGetClipboardData(cf);
+
+ if( hOle1 == NULL )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: GetClipboardData Failed!\n"));
+ hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
+ goto logRtn;
+ }
+
+ pszClassA = (LPSTR)GlobalLock(hOle1);
+
+ if( pszClassA == NULL )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: GlobalLock failed!\n"));
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto logRtn;
+ }
+
+ if( ppszClass )
+ {
+ hresult = UtGetUNICODEData(strlen(pszClassA) + 1, pszClassA,
+ NULL, ppszClass);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+ }
+
+ pszFileA = pszClassA + strlen(pszClassA) + 1;
+
+ if( ppszFile )
+ {
+ hresult = UtGetUNICODEData(strlen(pszFileA) + 1, pszFileA,
+ NULL, ppszFile );
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+ }
+
+ pszItemA = pszFileA + strlen(pszFileA) +1;
+
+ if( ppszItem )
+ {
+ hresult = UtGetUNICODEData(strlen(pszItemA) + 1, pszItemA,
+ NULL, ppszItem);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+ }
+
+ if( ppszItemA )
+ {
+ *ppszItemA = UtDupStringA(pszItemA);
+
+ if( !*ppszItemA )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ // FALL-THROUGH! no need to goto the error
+ // handling code right below us
+ }
+ }
+
+errRtn:
+
+ GlobalUnlock(hOle1);
+
+ if( hresult != NOERROR )
+ {
+ if( ppszClass && *ppszClass )
+ {
+ PubMemFree(*ppszClass);
+ *ppszClass = NULL;
+ }
+
+ if( ppszFile && *ppszFile )
+ {
+ PubMemFree(*ppszFile);
+ *ppszFile = NULL;
+ }
+
+ if( ppszItem && *ppszItem )
+ {
+ PubMemFree(*ppszItem);
+ *ppszItem = NULL;
+ }
+
+#if DBG == 1
+ // if this assert goes off, then we added more code
+ // without modifying the error paths for ansi item strings
+
+ if( ppszItemA )
+ {
+ Assert(*ppszItem == NULL );
+ }
+#endif // DBG ==1
+
+ }
+
+logRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::GetAndTranslate"
+ "Ole1 ( %lx ) [ %p , %p , %p ]\n", this, hresult,
+ (ppszClass)? *ppszClass : 0,
+ (ppszFile) ? *ppszFile : 0,
+ (ppszItem) ? *ppszItem : 0 ));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::GetEmbeddedObjectFromOle1
+//
+// Synopsis: synthesizes cfEmbeddedObject from available OLE1
+// data.
+//
+// Effects:
+//
+// Arguments: [pmedium] -- where to put the requested data
+//
+// Requires: The clipboard must be OPEN
+// we must have verified that the correct formats are
+// available before calling
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: create a memory-based stroage and stuff the following
+// infomation in it:
+// clsid StdOleLink
+// an available presentation
+// the class from OwnerLink data as the user type
+// link information
+//
+// Much of this work is done by the helper function
+// GenericObjectToIStorage
+//
+// History: dd-mmm-yy Author Comment
+// 11-Aug-94 alexgo author
+//
+// Notes: This code is largely based from 16bit OLE sources
+// REVIEW: we may want to rework portions of this code,
+// particularly if we rewrite the GENOBJ code (in
+// ostm2stg.cpp).
+//
+//--------------------------------------------------------------------------
+
+HRESULT CClipDataObject::GetEmbeddedObjectFromOle1( STGMEDIUM *pmedium )
+{
+ HRESULT hresult;
+ IStorage * pstg = NULL;
+ LPOLESTR pszClass = NULL;
+ ILockBytes * plockbytes = NULL;
+ BOOL fDeleteOnRelease = TRUE;
+ GENOBJ genobj;
+ HGLOBAL hglobal;
+
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::GetEmbeddedObject"
+ "FromOle1 ( %p )\n", this, pmedium));
+
+
+ // if we are asking for EmbeddedObject on an hglobal, then we
+ // don't want to delete the hglobal when we release the storage
+
+ if( pmedium->tymed == TYMED_HGLOBAL )
+ {
+ fDeleteOnRelease = FALSE;
+ }
+
+ genobj.m_class.Set(CLSID_StdOleLink, NULL);
+
+ // the destructor for the generic object will free the
+ // presentation.
+ genobj.m_ppres = new PRES;
+
+ if( genobj.m_ppres == NULL )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ genobj.m_fLink = TRUE;
+ genobj.m_lnkupdopt = UPDATE_ALWAYS;
+
+ if( SSIsClipboardFormatAvailable(CF_METAFILEPICT))
+ {
+ hglobal = SSGetClipboardData(CF_METAFILEPICT);
+
+ if( hglobal )
+ {
+ if( (hresult = MfToPres(hglobal, genobj.m_ppres))
+ != NOERROR)
+ {
+ goto errRtn;
+ }
+ }
+ else
+ {
+ LEDebugOut((DEB_WARN, "WARNING: Unable to "
+ "retrieve CF_METAFILEPICT\n"));
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ }
+ else if( SSIsClipboardFormatAvailable(CF_DIB) )
+ {
+ hglobal = SSGetClipboardData(CF_DIB);
+
+ if( hglobal )
+ {
+ // DibToPres will take ownership of the
+ // hglobal
+ HGLOBAL hTemp;
+
+ hTemp = UtDupGlobal(hglobal, GMEM_DDESHARE |
+ GMEM_MOVEABLE);
+
+ if( !hTemp )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ if( (hresult = DibToPres(hTemp, genobj.m_ppres))
+ != NOERROR )
+ {
+ GlobalFree(hTemp);
+ goto errRtn;
+ }
+ }
+ else
+ {
+ LEDebugOut((DEB_WARN, "WARNING: Unable to "
+ "retrieve CF_DIB\n"));
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+ }
+ else if (SSIsClipboardFormatAvailable(CF_BITMAP))
+ {
+ hglobal = SSGetClipboardData(CF_BITMAP);
+
+ if( hglobal )
+ {
+ if( (hresult = BmToPres(hglobal, genobj.m_ppres))
+ != NOERROR )
+ {
+ goto errRtn;
+ }
+ }
+ else
+ {
+ LEDebugOut((DEB_WARN, "WARNING: Unable to "
+ "retrieve CF_BITMAP\n"));
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+ }
+ else
+ {
+ delete genobj.m_ppres;
+ genobj.m_ppres = NULL;
+ genobj.m_fNoBlankPres = TRUE;
+ }
+
+
+ hresult = GetAndTranslateOle1(g_cfOwnerLink, &pszClass,
+ &genobj.m_szTopic, &genobj.m_szItem, NULL);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ genobj.m_classLast.SetSz(pszClass);
+
+ // now we need to create a storage to stuff the generic object
+ // into.
+
+ hresult = UtCreateStorageOnHGlobal(NULL, fDeleteOnRelease,
+ &pstg, &plockbytes);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ hresult = GenericObjectToIStorage(genobj, pstg, NULL);
+
+ if (SUCCEEDED(hresult))
+ {
+ hresult = NOERROR;
+ }
+
+ if( IsOwnerLinkStdOleLink() &&
+ SSIsClipboardFormatAvailable( g_cfNative) )
+ {
+ // Case of copying an OLE 2 link from a 1.0 container.
+ // The first part of this function created a presentation
+ // stream from the presentation on the clipboard. The
+ // presentation is NOT already inside the Native data (i.e.,
+ // the cfEmbeddedObject) because we removed it to conserve
+ // space.
+ hglobal = SSGetClipboardData(g_cfNative);
+
+ if( hglobal == NULL )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: GetClipboardData for "
+ "cfNative failed!\n"));
+ hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
+
+ goto errRtn;
+ }
+
+ // now stuff the native data into the storage, first
+ // removing any presentation streams that may have
+ // previously existed.
+
+ hresult = NativeToStorage(pstg, hglobal);
+ }
+
+ // finished!! now fill out the pmedium argument and return
+
+ if( pmedium->tymed == TYMED_ISTORAGE )
+ {
+ // hang onto the storage, in case we need to release
+ // it later
+
+ m_pUnkOle1 = (IUnknown *)pstg;
+
+ pmedium->pstg = pstg;
+ // NO AddRef
+ }
+ else
+ {
+ Assert(pmedium->tymed == TYMED_HGLOBAL);
+
+ hresult = GetHGlobalFromILockBytes(plockbytes,
+ &pmedium->hGlobal);
+
+ // GetHGLOBAL should never fail here because we
+ // just created the ILockBytes!!
+ Assert( hresult == NOERROR );
+
+ // in this case, we want to release the storage
+ // and save the hglobal for later delete
+
+ m_hOle1 = pmedium->hGlobal;
+
+ pstg->Release();
+ pstg = NULL;
+ }
+errRtn:
+
+ // if there was an error, we need to blow away any storage
+ // that we may have created
+
+ if( hresult != NOERROR )
+ {
+ if( pszClass )
+ {
+ PubMemFree(pszClass);
+ }
+
+ if( pstg )
+ {
+ pstg->Release();
+ Assert(m_pUnkOle1 == NULL);
+ }
+ }
+
+ // no matter what, we need to release our lockbytes
+
+ if( plockbytes )
+ {
+ // in case of failure we need to make sure the HGLOBAL
+ // used by plockbytes also gets freed - fDeleteOnRelease
+ // tells if plockbytes->Release will do that work for us
+
+ if (FAILED(hresult) && !fDeleteOnRelease)
+ {
+ HRESULT hrCheck; // Preserve hresult
+
+ // GetHGlobal should never fail here because we just
+ // created the ILockBytes
+ hrCheck = GetHGlobalFromILockBytes(plockbytes,
+ &hglobal);
+ Assert(NOERROR == hrCheck);
+
+ // GlobalFree returns NULL on success
+ hglobal = GlobalFree(hglobal);
+ Assert(hglobal == NULL);
+ }
+
+ plockbytes->Release();
+ }
+
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::GetEmbeddedObject"
+ "FromOle1 ( %lx ) \n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::GetEmbedSourceFromOle1 (private)
+//
+// Synopsis: synthesizes cfEmbedSource from available OLE1 data
+//
+// Effects:
+//
+// Arguments: [pmedium] -- where to put the resulting data
+//
+// Requires: The clipboard must be OPEN
+// we must have verified that the correct formats are
+// available before calling and *while* the clipboard
+// is open (to avoid a race condition)
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: create a memory-based storage and stuff the following
+// information in it:
+// the clsid of the embedding
+// the class name as the user type
+// the native data in the OLE10_NATIVE_STREAM
+// the item name in the OLE10_ITEMNAME_STREAM
+//
+// History: dd-mmm-yy Author Comment
+// 17-Aug-94 alexgo fix the check for OLE2 data to handle
+// OLE2 treat as from OLE1
+// 03-Aug-94 AlexT Check for OLE 2 data
+// 04-Jun-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT CClipDataObject::GetEmbedSourceFromOle1( STGMEDIUM *pmedium )
+{
+ HRESULT hresult;
+ IStorage * pstg = NULL;
+ HGLOBAL hNative;
+ HGLOBAL hCopy = NULL;
+ LPOLESTR pszClass = NULL;
+ LPSTR pszItemA = NULL;
+ CLSID clsid;
+ ILockBytes * plockbytes = NULL;
+ BOOL fDeleteOnRelease = TRUE;
+ BOOL fIsOle1 = TRUE;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::GetEmbedSourceFrom"
+ "Ole1 ( %p )\n", this, pmedium));
+
+ Assert(SSIsClipboardFormatAvailable(g_cfOwnerLink));
+ Assert(SSIsClipboardFormatAvailable(g_cfNative));
+
+ // first fetch the class name of the object
+
+ hresult = GetAndTranslateOle1( g_cfOwnerLink, &pszClass, NULL, NULL,
+ &pszItemA );
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // now fetch the clsid for the embedding
+
+ hresult = wCLSIDFromProgID(pszClass, &clsid, TRUE);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // if we are asking for EmbedSource on an hglobal, then we
+ // don't want to delete the hglobal when we release the storage
+
+ if( pmedium->tymed == TYMED_HGLOBAL )
+ {
+ fDeleteOnRelease = FALSE;
+ }
+
+ // now fetch the native data
+
+ hNative = SSGetClipboardData(g_cfNative);
+
+ if( hNative == NULL )
+ {
+ hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
+ goto errRtn;
+ }
+
+ if (!CoIsOle1Class(clsid))
+ {
+ // Just because the clsid is OLE2 does not mean that the
+ // underlying data is OLE2. For example, suppose a container
+ // copies an old OLE1 object to the clipboard, but the OLE2
+ // version of that object has been installed on the system.
+ // CLSIDFromProgID will return the *OLE2* class ID in this case.
+ // If we're in this case, then we should fall through and treat
+ // the data as normal OLE1 (StgOpenStorageOnILockBytes would
+ // fail in any event).
+
+ hresult = CreateILockBytesOnHGlobal(hNative, FALSE,
+ &plockbytes);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ hresult = StgIsStorageILockBytes(plockbytes);
+
+ plockbytes->Release();
+ plockbytes = NULL;
+
+ if( hresult == NOERROR )
+ {
+ // the hNative data really contains a serialized
+ // IStorage.
+ //
+ // This will arise in two cases:
+ // 1. Publisher 2.0, 16bit put data on the
+ // clipboard. They do not call OLE api's but
+ // instead synthesize the same data that 16bit
+ // OleSetClipboard would.
+ //
+ // 2. An OLE1.0 container copies an OLE2 embedding
+ // to the clipboard.
+
+ fIsOle1 = FALSE;
+
+ hCopy = UtDupGlobal(hNative,
+ GMEM_DDESHARE | GMEM_MOVEABLE);
+
+ if( NULL == hCopy )
+ {
+ hresult = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ // create plockbytes
+ hresult = CreateILockBytesOnHGlobal(hCopy,
+ fDeleteOnRelease,
+ &plockbytes);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // the HGLOBAL in plockbytes can change, so we
+ // can't do anything with hCopy; we NULL it out
+ // to make sure we don't try to free it
+
+ hCopy = NULL;
+
+ hresult = StgOpenStorageOnILockBytes(plockbytes, NULL,
+ STGM_SALL,
+ NULL, 0, &pstg);
+ if (FAILED(hresult))
+ {
+ goto errRtn;
+ }
+
+ // We explicitly ignore any error returned by the
+ // following
+ UtDoStreamOperation(pstg, NULL, OPCODE_REMOVE,
+ STREAMTYPE_CACHE);
+ }
+ // else the data is really OLE1 and is just being emulated by
+ // an OLE2 object
+ // Just fall through to the code below which will
+ // stuff hNative into the OLE10_NATIVE_STREAM
+
+ }
+
+ // this will be TRUE if the clsid is OLE1 or if the clsid is OLE2
+ // but the data in hNative is OLE1 anyway (see comments above)
+
+ if( fIsOle1 == TRUE )
+ {
+ hresult = UtCreateStorageOnHGlobal( NULL, fDeleteOnRelease,
+ &pstg, &plockbytes);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // we need to stuff the class id of the embedding into the
+ // storage
+
+ // REVIEW: this clsid may be an OLE2 class id. This could
+ // cause us trouble in treat as scenarios.
+
+ hresult = pstg->SetClass(clsid);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // store the user type information, etc in our private data
+ // streams if RegisterClipboardFormat fails, it will return 0,
+ // which is OK for us.
+
+ hresult = WriteFmtUserTypeStg(pstg,
+ RegisterClipboardFormat(pszClass),
+ pszClass);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // now stuff the native data into the OLE10_NATIVE_STREAM
+
+ // this is a little worker function found in utstream.cpp
+ // which will stuff the hglobal to the OLE1 data into the
+ // right stream.
+ // the OLE1 DDE stuff also uses this function.
+
+ // REVIEW:
+ // the FALSE flag is confusing here, it's supposed to be
+ // fIsOle1Interop. 16bit clipboard sources passed FALSE when doing
+ // their 1.0 interop stuff, so we'll do that here. When we
+ // overhaul the main 1.0 interop stuff, we should change this flag
+ // to be something more intuitive.
+
+ hresult = StSave10NativeData(pstg, hNative, FALSE);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // If we have an item name, then stuff that into
+ // OLE10_ITEMNAME_STREAM
+
+ if( pszItemA && pszItemA[0] != '\0' )
+ {
+ hresult = StSave10ItemName(pstg, pszItemA);
+ }
+ }
+
+ // this Commit call in non-intuitive. Basically, we may
+ // try to get the underlying hglobal (see below) *before*
+ // we release the storage. The commit guarantees that all
+ // the important state information gets flushed to the
+ // hglobal (which is not otherwise guaranteed).
+
+ hresult = pstg->Commit(STGC_DEFAULT);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // FINIS!!
+ // now fill out all of the arguments
+
+ if( pmedium->tymed == TYMED_ISTORAGE )
+ {
+ // hang onto the storage, in case we need to release
+ // it later
+
+ m_pUnkOle1 = (IUnknown *)pstg;
+
+ pmedium->pstg = pstg;
+ // NO AddRef
+ }
+ else
+ {
+ Assert(pmedium->tymed == TYMED_HGLOBAL);
+
+ hresult = GetHGlobalFromILockBytes(plockbytes,
+ &pmedium->hGlobal);
+
+ // GetHGLOBAL should never fail here because we
+ // just created the ILockBytes!!
+ Assert( hresult == NOERROR );
+
+ // in this case, we want to release the storage
+ // and save the hglobal for later delete
+
+ m_hOle1 = pmedium->hGlobal;
+
+ pstg->Release();
+ pstg = NULL;
+ }
+
+errRtn:
+
+ // we are done with our strings
+
+ if( pszClass )
+ {
+ PubMemFree(pszClass);
+ }
+
+ if( pszItemA )
+ {
+ PubMemFree(pszItemA);
+ }
+
+ // if there was an error, we need to blow away any storage
+ // that we may have created
+
+ if( hresult != NOERROR )
+ {
+ if( pstg )
+ {
+ pstg->Release();
+ m_pUnkOle1 = NULL;
+ }
+ }
+
+ // no matter what, we need to release our lockbytes.
+
+ if( plockbytes )
+ {
+ // in case of failure we need to make sure the HGLOBAL
+ // used by plockbytes also gets freed - fDeleteOnRelease
+ // tells if plockbytes->Release will do that work for us
+
+ if (FAILED(hresult) && !fDeleteOnRelease)
+ {
+ HRESULT hrCheck; // Preserve hresult
+
+ // GetHGlobal should never fail here because we just
+ // created the ILockBytes
+ hrCheck = GetHGlobalFromILockBytes(plockbytes, &hCopy);
+ Assert(NOERROR == hrCheck);
+
+ // hCopy will be freed below
+ }
+
+ plockbytes->Release();
+ }
+
+ if (NULL != hCopy)
+ {
+ // GlobalFree returns NULL on success
+ hCopy = GlobalFree(hCopy);
+ Assert(NULL == hCopy);
+ }
+
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::GetEmbedSource"
+ "FromOle1 ( %lx ) \n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::GetLinkSourceFromOle1 (private)
+//
+// Synopsis: Synthesizes cfLinkSource format from OLE1 data
+//
+// Effects:
+//
+// Arguments: [pmedium] -- where to put the data
+//
+// Requires: the clipboard must be open
+// we must have verified that the correct formats are
+// available before calling and *while* the clipboard
+// is open (to avoid a race condition)
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: Gets the clsid, filename, and item name for the OLE1 object
+// and creates an OLE1 file moniker. This moniker is then
+// saved into a memory stream
+//
+// History: dd-mmm-yy Author Comment
+// 04-Jun-94 alexgo author
+// 05-Aug-94 AlexT Link Source also needs class id
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT CClipDataObject::GetLinkSourceFromOle1( STGMEDIUM *pmedium )
+{
+ HRESULT hresult;
+ IStream * pstm = NULL;
+ LPMONIKER pmkFile = NULL,
+ pmkFinal = NULL,
+ pmkItem = NULL;
+ IPersistStream *pPersistStream = NULL;
+ LPOLESTR pszClass = NULL,
+ pszFile = NULL,
+ pszItem = NULL;
+ CLSID clsid;
+ UINT cf;
+ BOOL fDeleteOnRelease = TRUE;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::GetLinkSourceFrom"
+ "Ole1 ( %p , %p )\n", this, pmedium ));
+
+
+ // fetch the info we need from cfOwnerLink or cfObjectLink
+ // If this function is called, we should have already determined
+ // that the formats were available in the correct order
+ // for creating links.
+
+
+ if( SSIsClipboardFormatAvailable(g_cfObjectLink) )
+ {
+ cf = g_cfObjectLink;
+ }
+ else
+ {
+ cf = g_cfOwnerLink;
+ Assert(SSIsClipboardFormatAvailable(g_cfOwnerLink));
+ }
+
+ hresult = GetAndTranslateOle1(cf, &pszClass, &pszFile,
+ &pszItem, NULL);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // now fetch the clsid for the OLE1 server
+
+ hresult = wCLSIDFromProgID(pszClass, &clsid, TRUE);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // now build up our moniker
+
+ hresult = CreateOle1FileMoniker(pszFile, clsid, &pmkFile);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ if( pszItem && pszItem[0] != OLESTR('\0') )
+ {
+ hresult = CreateItemMoniker(OLESTR("!"), pszItem,
+ &pmkItem);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+
+ hresult = CreateGenericComposite(pmkFile, pmkItem,
+ &pmkFinal);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+ }
+ else
+ {
+ pmkFinal = pmkFile;
+
+ // this addref is done so we can release all of our
+ // monikers at once (i.e., the variables pmkFinal
+ // and pmkFile will both be released)
+ pmkFinal->AddRef();
+ }
+
+ // pmkFinal now contains the moniker we need. Create a
+ // memory stream and save the moniker into it.
+
+ // if we are asking for LinkSource on an hglobal, then we
+ // don't want to delete the hglobal when we release the stream
+
+ if( pmedium->tymed == TYMED_HGLOBAL )
+ {
+ fDeleteOnRelease = FALSE;
+ }
+
+ hresult = CreateStreamOnHGlobal(NULL, fDeleteOnRelease, &pstm);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ hresult = pmkFinal->QueryInterface(IID_IPersistStream,
+ (LPLPVOID)&pPersistStream);
+
+ // we implemented this file moniker, it should support
+ // IPersistStream
+
+ Assert(hresult == NOERROR);
+
+ hresult = OleSaveToStream(pPersistStream, pstm);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ hresult = WriteClassStm(pstm, clsid);
+
+ if (hresult != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ // no matter what, we should save the stream so we can clean
+ // up and release our resources if needed
+
+
+
+ if( pmedium->tymed == TYMED_ISTREAM )
+ {
+ // save the stream, in case we need to release it later
+ m_pUnkOle1 = (IUnknown *)pstm;
+
+ pmedium->pstm = pstm;
+ }
+ else
+ {
+ Assert(pmedium->tymed == TYMED_HGLOBAL);
+ hresult = GetHGlobalFromStream(pstm, &(pmedium->hGlobal));
+
+ // since we created the memory stream, the GetHGlobal
+ // should never fail
+ Assert(hresult == NOERROR);
+
+ // in this case, we want to release the stream and hang
+ // onto the hglobal
+
+ m_hOle1 = pmedium->hGlobal;
+
+ pstm->Release();
+ pstm = NULL;
+ }
+
+errRtn:
+
+ if( pPersistStream )
+ {
+ pPersistStream->Release();
+ }
+
+ if( pmkFile )
+ {
+ pmkFile->Release();
+ }
+
+ if( pmkItem )
+ {
+ pmkItem->Release();
+ }
+
+ if( pmkFinal )
+ {
+ pmkFinal->Release();
+ }
+
+ if( pszClass )
+ {
+ PubMemFree(pszClass);
+ }
+
+ if( pszFile )
+ {
+ PubMemFree(pszFile);
+ }
+
+ if( pszItem )
+ {
+ PubMemFree(pszItem);
+ }
+
+ if( hresult != NOERROR )
+ {
+ if( pstm )
+ {
+ HRESULT hrCheck;
+
+ if (!fDeleteOnRelease)
+ {
+ // pstm->Release will not free the underlying
+ // HGLOBAL, so we need to do so ourselves
+
+ HGLOBAL hgFree;
+
+ hrCheck = GetHGlobalFromStream(pstm, &hgFree);
+
+ // since we created the memory stream, the GetHGlobal
+ // should never fail
+ Assert(hrCheck == NOERROR);
+
+ // GlobalFree returns NULL on success
+ hgFree = GlobalFree(hgFree);
+ Assert(NULL == hgFree);
+ }
+
+ pstm->Release();
+ m_pUnkOle1 = NULL;
+ }
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::GetLinkSourceFrom"
+ "Ole1 ( %lx ) [ %p , %p ]\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::GetObjectDescriptorFromOle1 (private)
+//
+// Synopsis: retrieves a UNICODE object descriptor from OLE1 data
+//
+// Effects:
+//
+// Arguments: [cf] -- the OLE1 clipboard format to use
+// [pmedium] -- where to put the hglobal
+//
+// Requires: the clipboard must be open
+// cf must be eith OwnerLink or ObjectLink
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: Calls CreateObjectDesciptor
+//
+// History: dd-mmm-yy Author Comment
+// 04-Jun-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT CClipDataObject::GetObjectDescriptorFromOle1( UINT cf,
+ STGMEDIUM *pmedium )
+{
+ HRESULT hresult;
+ HGLOBAL hglobal;
+ LPOLESTR pszClass = NULL,
+ pszFile = NULL,
+ pszItem = NULL,
+ pszSrcOfCopy = NULL;
+ CLSID clsid;
+ const SIZEL sizel = {0, 0};
+ const POINTL pointl = {0, 0};
+ OLECHAR szFullName[256];
+ LONG cb = sizeof(szFullName); // RegQueryValue takes
+ // bytes!!
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::GetObjectDescriptor"
+ "FromOle1 ( %d , %p )\n", this, cf, pmedium));
+
+ Assert(cf == g_cfOwnerLink || cf == g_cfObjectLink);
+
+ // fetch the data we need
+
+ hresult = GetAndTranslateOle1( cf, &pszClass, &pszFile, &pszItem,
+ NULL);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ hresult = wCLSIDFromProgID(pszClass, &clsid, TRUE);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // now fetch the full user name of the object. This info
+ // is found in the registry.
+
+ if( RegQueryValue(HKEY_CLASSES_ROOT, pszClass, szFullName, &cb) != 0 )
+ {
+ // uh-oh, it failed for some reason. The class name
+ // (potentially OLE2Link) was probably not registered, so
+ // just use the class name.
+ //
+ // NB!! 16bit did no error checking for this case, so
+ // szFullName in their equivalent code would be left as
+ // a NULL string. This had the effect of making a
+ // blank entry in most paste-special dialogs.
+
+ _xstrcpy(szFullName, pszClass);
+ }
+
+ // build up the SourceOfCopy string. It will be a concatenation
+ // of the Filename and Item name that we retrieved from the
+ // Owner/ObjectLink OLE1 structures
+
+ pszSrcOfCopy = (LPOLESTR)PrivMemAlloc( (_xstrlen(pszFile) +
+ _xstrlen(pszItem) + 2) * sizeof(OLECHAR));
+
+ if( pszSrcOfCopy == NULL )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ _xstrcpy(pszSrcOfCopy, pszFile);
+
+ if( pszItem && *pszItem != OLESTR('\0') )
+ {
+ _xstrcat(pszSrcOfCopy, OLESTR("\\"));
+ _xstrcat(pszSrcOfCopy, pszItem);
+ }
+
+ // create an object descriptor
+
+ hglobal = CreateObjectDescriptor(clsid, DVASPECT_CONTENT, &sizel,
+ &pointl,
+ (OLEMISC_CANTLINKINSIDE | OLEMISC_CANLINKBYOLE1),
+ szFullName, pszSrcOfCopy);
+
+ if( hglobal == NULL )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ // now fill in out params
+
+ Assert(pmedium->tymed == TYMED_HGLOBAL);
+
+ pmedium->hGlobal = hglobal;
+
+ // we need to save the hglobal so we can free it later if need
+ // be
+
+ m_hOle1 = hglobal;
+
+errRtn:
+
+ if( pszClass )
+ {
+ PubMemFree(pszClass);
+ }
+
+ if( pszFile )
+ {
+ PubMemFree(pszFile);
+ }
+
+ if( pszItem )
+ {
+ PubMemFree(pszItem);
+ }
+
+ if( pszSrcOfCopy )
+ {
+ // NB!! This was allocated with *private* memory
+ PrivMemFree(pszSrcOfCopy);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::GetObjectDescriptor"
+ "FromOle1 ( %lx )\n", this, hresult ));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::GetOle2FromOle1 (private)
+//
+// Synopsis: synthesize the given ole2 format from available ole1 data
+//
+// Effects:
+//
+// Arguments: [cf] -- the clipboard format to synthesize
+// [pmedium] -- where to put the data
+//
+// Requires: the clipboard must be open
+// CanRetrieveOle2FromOle1 should have succeeded before calling
+// this function
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 04-Jun-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT CClipDataObject::GetOle2FromOle1( UINT cf, STGMEDIUM *pmedium )
+{
+ HRESULT hresult = ResultFromScode(DV_E_TYMED);
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::GetOle2FromOle1 "
+ "( %d , %p )\n", this, cf, pmedium));
+
+ if( cf == g_cfEmbedSource )
+ {
+ // we can only fetch EmbedSource on an hglobal or storage
+
+ if( pmedium->tymed == TYMED_HGLOBAL ||
+ pmedium->tymed == TYMED_ISTORAGE )
+ {
+ hresult = GetEmbedSourceFromOle1(pmedium);
+ }
+ }
+ else if( cf == g_cfEmbeddedObject )
+ {
+ // we can only fetch EmbeddedObject on an hglobal or storage
+
+ if( pmedium->tymed == TYMED_HGLOBAL ||
+ pmedium->tymed == TYMED_ISTORAGE )
+ {
+ hresult = GetEmbeddedObjectFromOle1(pmedium);
+ }
+ }
+ else if( cf == g_cfLinkSource )
+ {
+ // we can only fetch LinkSource on an hglobal or stream
+
+ if( pmedium->tymed == TYMED_HGLOBAL ||
+ pmedium->tymed == TYMED_ISTREAM )
+ {
+ hresult = GetLinkSourceFromOle1(pmedium);
+ }
+ }
+ else if( cf == g_cfObjectDescriptor )
+ {
+ // we can only fetch this on an hglobal
+
+ if( pmedium->tymed == TYMED_HGLOBAL )
+ {
+ hresult = GetObjectDescriptorFromOle1(g_cfOwnerLink,
+ pmedium);
+ }
+ }
+ else if( cf == g_cfLinkSrcDescriptor )
+ {
+ // we can only fetch this on an hglobal. Note that
+ // a link source descriptor is really an object descriptor
+
+ // also, we can use either ObjectLink or OwnerLink as the
+ // the data source, but the only time it is valid to use
+ // OwnerLink is if ObjectLink is not available
+
+ if( pmedium->tymed == TYMED_HGLOBAL )
+ {
+ UINT cfOle1;
+
+ if( SSIsClipboardFormatAvailable(g_cfObjectLink) )
+ {
+ cfOle1 = g_cfObjectLink;
+ }
+ else
+ {
+ cfOle1 = g_cfOwnerLink;
+ }
+
+ hresult = GetObjectDescriptorFromOle1(cfOle1,
+ pmedium);
+ }
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::GetOle2FromOle1 "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::OleGetClipboardData (private)
+//
+// Synopsis: private replacement for GetClipboardData that synthesizes
+// OLE2 formats from OLE1 data if necessary
+//
+// Effects:
+//
+// Arguments: [cf] -- the clipboard format to use
+// [phglobal] -- where to put the fetched data
+//
+// Requires: the clipboard must be open
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: Try to fetch the request format; if that fails then
+// try to synthesize the data from OLE1
+//
+// History: dd-mmm-yy Author Comment
+// 04-Jun-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT CClipDataObject::OleGetClipboardData( UINT cf, HGLOBAL *phglobal )
+{
+ HRESULT hresult = NOERROR;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::OleGetClipboard"
+ "Data ( %x , %p )\n", this, cf, phglobal ));
+
+ Assert(phglobal);
+
+ *phglobal = NULL;
+
+ // fetch the real data, if available
+ if( SSIsClipboardFormatAvailable(cf) )
+ {
+ *phglobal = SSGetClipboardData(cf);
+ }
+ else if( CanRetrieveOle2FromOle1(cf) )
+ {
+ STGMEDIUM medium;
+
+ medium.tymed = TYMED_HGLOBAL;
+
+ hresult = GetOle2FromOle1(cf, &medium);
+
+ if( hresult == NOERROR )
+ {
+ *phglobal = medium.hGlobal;
+ }
+ }
+ else
+ {
+ hresult = ResultFromScode(DV_E_FORMATETC);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::OleGetClipboardData"
+ " ( %lx ) [ %lx ]\n", this, hresult, *phglobal));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::OleIsClipboardFormatAvailable (private)
+//
+// Synopsis: determines whether a clipboard format is available or
+// can be synthesized from available formats
+//
+// Effects:
+//
+// Arguments: [cf] -- the clipboard format to check for
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 04-Jun-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+BOOL CClipDataObject::OleIsClipboardFormatAvailable( UINT cf )
+{
+ BOOL fRet;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CClipDataObject::OleIsClipboard"
+ "FormatAvailable ( %d )\n", this, cf));
+
+ if( !SSIsClipboardFormatAvailable(cf) )
+ {
+ // if the clipboard format is not normally available, see
+ // if we can make it from available formats
+ fRet = CanRetrieveOle2FromOle1(cf);
+ }
+ else
+ {
+ fRet = TRUE;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CClipDataObject::OleIsClipboard"
+ "FormatAvailable ( %lu )\n", this, fRet ));
+
+ return fRet;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipDataObject::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppszDump] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CClipDataObject::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ unsigned int ui;
+ char *pszPrefix;
+ char *pszCThreadCheck;
+ char *pszFORMATETC;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(500);
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ pszCThreadCheck = DumpCThreadCheck((CThreadCheck *)this, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CThreadCheck:" << endl;
+ dstrDump << pszCThreadCheck;
+ CoTaskMemFree(pszCThreadCheck);
+
+ dstrDump << pszPrefix << "No. of References = " << m_refs << endl;
+
+ dstrDump << pszPrefix << "Handle OLE2 -> OLE1 data = " << m_hOle1 << endl;
+
+ dstrDump << pszPrefix << "pIUnknown to OLE1 data = " << m_pUnkOle1 << endl;
+
+ dstrDump << pszPrefix << "No. in FORMATETC array = " << m_cFormats << endl;
+
+ for (ui = 0; ui < m_cFormats; ui++)
+ {
+ pszFORMATETC = DumpFORMATETC(&m_rgFormats[ui], ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "FORMATETC [" << ui << "]:" << endl;
+ dstrDump << pszFORMATETC;
+ CoTaskMemFree(pszFORMATETC);
+ }
+
+ dstrDump << pszPrefix << "pIDataObject = " << m_pDataObject << endl;
+
+ dstrDump << pszPrefix << "TriedToGetDataObject? = ";
+ if (m_fTriedToGetDataObject == TRUE)
+ {
+ dstrDump << "TRUE" << endl;
+ }
+ else
+ {
+ dstrDump << "FALSE" << endl;
+ }
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCClipDataObject, public (_DEBUG only)
+//
+// Synopsis: calls the CClipDataObject::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pCDO] - pointer to CClipDataObject
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCClipDataObject(CClipDataObject *pCDO, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pCDO == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pCDO->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//
+// OLE1 support methods
+//
+
+//+-------------------------------------------------------------------------
+//
+// Function: BmToPres
+//
+// Synopsis: copies a bitmap into a presentation object
+//
+// Effects:
+//
+// Arguments: [hBM] -- handle to the bitmap
+// [ppres] -- the presentation object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: converts the bitmap to a DIB and then calls DibToPres
+//
+// History: dd-mmm-yy Author Comment
+// 11-Aug-94 alexgo port from 16bit
+//
+// Notes: This code is largely based from 16bit OLE sources
+// REVIEW: we may want to rework portions of this code,
+// particularly if we rewrite the PPRES/GENOBJ code (in
+// ostm2stg.cpp).
+//
+//--------------------------------------------------------------------------
+
+HRESULT BmToPres(HANDLE hBM, PPRES ppres)
+{
+ HANDLE hDib;
+ HRESULT hresult;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN BmToPres ( %lx , %p )\n", NULL,
+ hBM, ppres));
+
+ if( (hDib = UtConvertBitmapToDib((HBITMAP)hBM, NULL)) )
+ {
+ // this routine keeps hDib, it doesn't make a copy of it
+ hresult = DibToPres(hDib, ppres);
+ }
+ else
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT BmToPres ( %lx )\n", NULL, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CanRetrieveOle2FromOle1 (private)
+//
+// Synopsis: Determines whether we can synthesize the asked for
+// ole2 format from the formats available on the clipboard.
+// Also checks to see if the *real* OLE2 format is available.
+//
+// Effects: does not need to open the clipboard
+//
+// Arguments: [cf] -- the clipboard format to check for
+//
+// Requires:
+//
+// Returns: TRUE if we can synthesize the requested format AND the
+// real format is NOT available
+// FALSE otherwise
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: for cfEmbedSource:
+// cfNative and cfOwnerLink must be present and
+// cfNative must precede cfOwnerLink and cfOwnerLink
+// must not represent a StdOleLink
+//
+// for cfEmbeddedObject:
+// cfOwnerLink must be present and cfNative
+// must not be not present OR
+//
+// cfNative must come after cfOwnerLink OR
+//
+// cfNative precedes cfOwnerLink and
+// cfOwnerLink represents a StdOleLink
+//
+// for cfLinkSource:
+// cfObjectLink must be present OR
+//
+// both cfNative and cfOwnerLink must be present
+// and cfOwnerLink must precede cfNative
+//
+// for cfObjectDescriptor or cfLinkSrcDescriptor
+// either cfObjectLink or cfOwnerLink must be
+// available
+//
+// History: dd-mmm-yy Author Comment
+// 11-Aug-94 alexgo added support for EmbeddedObject
+// retrieval ala 16bit OLE
+// 04-Jun-94 alexgo author
+//
+// Notes: We don't want to synthesize OLE2 formats from OLE1
+// if the real OLE2 formats are available because the OLE2
+// formats probably contain more information.
+//
+// We sometimes need to open the clipboard to accurately
+// fetch enough information to satisfy a query on
+// EmbedSource, EmbeddedObject or LinkSource.
+// Since the clipboard is a global resource, we
+// must only open it for brief periods of time.
+//
+//--------------------------------------------------------------------------
+
+BOOL CanRetrieveOle2FromOle1( UINT cf )
+{
+ BOOL fRet = FALSE,
+ fOwnerLink = FALSE,
+ fNative = FALSE,
+ fOpenedClipboard = FALSE;
+ UINT cfFirst = 0, // the first format available
+ cfTemp;
+ HRESULT hresult;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CanRetrieveOle2From"
+ "Ole1 ( %d )\n", NULL, cf ));
+
+
+ if( SSIsClipboardFormatAvailable(g_cfOlePrivateData) )
+ {
+ // if we put the data on the clipboard, assume only OLE2
+ // data transfers
+
+ goto errRtn;
+ }
+
+ // first check for LinkSourceDescriptor or ObjectDescriptor, as
+ // we do not need to open the clipboard for these.
+
+ if( cf == g_cfObjectDescriptor )
+ {
+ // we must have either OwnerLink or ObjectLink
+ if( !SSIsClipboardFormatAvailable(g_cfObjectDescriptor) &&
+ (SSIsClipboardFormatAvailable(g_cfObjectLink) ||
+ SSIsClipboardFormatAvailable(g_cfOwnerLink) ) )
+ {
+ fRet = TRUE;
+ }
+
+ goto errRtn;
+ }
+
+ if( cf == g_cfLinkSrcDescriptor )
+ {
+ // we must have either OwnerLink or ObjectLink
+ if( !SSIsClipboardFormatAvailable(g_cfLinkSrcDescriptor) &&
+ (SSIsClipboardFormatAvailable(g_cfObjectLink) ||
+ SSIsClipboardFormatAvailable(g_cfOwnerLink) ) )
+ {
+ fRet = TRUE;
+ }
+
+ goto errRtn;
+ }
+
+
+ // now check for the remaining OLE2 formats EmbedSource,
+ // EmbeddedObject, and LinkSource.
+
+
+ if( (cf == g_cfEmbedSource) || (cf == g_cfEmbeddedObject) ||
+ (cf == g_cfLinkSource) )
+ {
+ // we need to open the clipboard so our calls to
+ // EnumClipboardFormats and GetClipboardData will work.
+
+ // however, the caller of this function may have already
+ // opened the clipboard, so we need to check for this.
+
+ //
+ //
+ // BEGIN: OPENCLIPBOARD
+ //
+ //
+
+ if( GetOpenClipboardWindow() !=
+ GetPrivateClipboardWindow(CLIP_QUERY) )
+ {
+ hresult = OleOpenClipboard(NULL, NULL);
+
+ if( hresult != NOERROR )
+ {
+ // if we can't open the clipboard,
+ // then we can't accurately determine
+ // if we can fetch the requested
+ // data. Assume that we can't
+ // and return.
+ fRet = FALSE;
+ goto errRtn;
+
+ }
+
+ fOpenedClipboard = TRUE;
+ }
+
+ // we now need to determine the ordering of the clipboard
+ // formats Native and OwnerLink. OLE1 specifies different
+ // behaviour based on the order in which these formats
+ // appear (see the Algorithm section for details)
+
+ fNative = SSIsClipboardFormatAvailable(g_cfNative);
+ fOwnerLink = SSIsClipboardFormatAvailable(g_cfOwnerLink);
+
+
+ if( fNative && fOwnerLink )
+ {
+ cfTemp = 0;
+ while( (cfTemp = SSEnumClipboardFormats(cfTemp)) != 0 )
+ {
+ if( cfTemp == g_cfNative )
+ {
+ cfFirst = g_cfNative;
+ break;
+ }
+ else if( cfTemp == g_cfOwnerLink )
+ {
+ cfFirst = g_cfOwnerLink;
+ break;
+ }
+ }
+ }
+
+
+ if( cf == g_cfEmbeddedObject )
+ {
+ // cfOwnerLink must be present and cfNative
+ // must not be not present OR
+ // cfNative must come after cfOwnerLink OR
+ // cfNative comes before cfOwnerLink and
+ // cfOwnerLink represents a StdOleLink
+
+ if( fOwnerLink && !fNative )
+ {
+ fRet = TRUE;
+ }
+ else if ( cfFirst == g_cfOwnerLink &&
+ fNative )
+ {
+ fRet = TRUE;
+ }
+ else if( cfFirst == g_cfNative && fOwnerLink &&
+ IsOwnerLinkStdOleLink() )
+ {
+ fRet = TRUE;
+ }
+ }
+ else if( cf == g_cfEmbedSource )
+ {
+ // cfNative and cfOwnerLink must be present
+ // cfNative must precede cfOwnerLink and
+ // OwnerLink must not represent a StdOleLink
+
+ if( cfFirst == g_cfNative && fOwnerLink &&
+ !IsOwnerLinkStdOleLink())
+ {
+ fRet = TRUE;
+ }
+ }
+ else
+ {
+ Assert(cf == g_cfLinkSource);
+
+ // cfObjectLink must be present OR
+ // both cfNative and cfOwnerLink must be present
+ // and cfOwnerLink must precede cfNative
+
+ if( SSIsClipboardFormatAvailable(g_cfObjectLink) )
+ {
+ fRet = TRUE;
+ }
+ else if( cfFirst == g_cfOwnerLink )
+ {
+ fRet = TRUE;
+ }
+
+ }
+
+ if( fOpenedClipboard )
+ {
+ if( !SSCloseClipboard() )
+ {
+ LEDebugOut((DEB_ERROR, "ERROR!: "
+ "CloseClipboard failed in "
+ "CanRetrieveOle2FromOle1!\n"));
+
+ // just keep going and hope for the best.
+ }
+ }
+
+ //
+ //
+ // END: CLOSECLIPBOARD
+ //
+ //
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CanRetrieveOle2From"
+ "Ole1 ( %d )\n", NULL, fRet));
+
+ return fRet;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DibToPres
+//
+// Synopsis: stuffs a DIB into a presentation object
+//
+// Effects: takes ownership of hDib.
+//
+// Arguments: [hDib] -- the DIB
+// [ppres] -- the presentation object
+//
+// Requires: hDib *must* be a copy; this function will take ownership
+// of the hglobal.
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: sets various fields in the presentation object
+//
+// History: dd-mmm-yy Author Comment
+// 11-Aug-94 alexgo port from 16bit
+//
+// Notes: This code is largely based from 16bit OLE sources
+// REVIEW: we may want to rework portions of this code,
+// particularly if we rewrite the PPRES/GENOBJ code (in
+// ostm2stg.cpp).
+//
+// We take ownership of hDib because this function is
+// called by BmToPres, which allocates a DIB calls us.
+//
+//--------------------------------------------------------------------------
+
+HRESULT DibToPres( HANDLE hDib, PPRES ppres)
+{
+ BITMAPINFOHEADER * pbminfohdr;
+ HRESULT hresult = NOERROR;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN DibToPres ( %lx , %p )\n", NULL,
+ hDib, ppres));
+
+ Assert (ppres);
+
+ pbminfohdr = (BITMAPINFOHEADER FAR*) GlobalLock (hDib);
+
+ if( pbminfohdr == NULL )
+ {
+ hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
+ goto errRtn;
+ }
+
+ // ftagClipFormat is defined in ostm2stg.h
+
+ ppres->m_format.m_ftag = ftagClipFormat;
+ ppres->m_format.m_cf = CF_DIB;
+ ppres->m_ulHeight = pbminfohdr->biHeight;
+ ppres->m_ulWidth = pbminfohdr->biWidth;
+
+ // the destructor for m_data (in ostm2stg.cpp) will GlobalUnlock
+ // m_pv and free m_h. Cute, ehh??
+ ppres->m_data.m_h = hDib;
+ ppres->m_data.m_pv = pbminfohdr;
+ ppres->m_data.m_cbSize = GlobalSize (hDib);
+
+ // we must free hDib
+ ppres->m_data.m_fNoFree = FALSE;
+
+ // Do not unlock hDib (done by ~CData in ostm2stg.cpp)
+
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT DibToPres ( %lx )\n", NULL, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsOwnerLinkStdOleLink
+//
+// Synopsis: checks to see if the OwnerLink data on the clipboard
+// really represents a StdOleLink.
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires: The clipboard *must* be open.
+// cfOwnerLink must be on the clipboard.
+//
+// Returns: TRUE/FALSE
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: checks the class name in the OwnerLink data to see if it
+// matches 'OLE2Link'.
+//
+// History: dd-mmm-yy Author Comment
+// 11-Aug-94 alexgo author
+//
+// Notes: OwnerLink data is laid out as follows
+// szClass\0szFile\0szItem\0\0
+//
+// where sz* are ANSI strings.
+//
+//--------------------------------------------------------------------------
+
+BOOL IsOwnerLinkStdOleLink( void )
+{
+ HGLOBAL hOwnerLink;
+ LPSTR pszClass;
+ BOOL fRet = FALSE;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN IsOwnerLinkStdOleLink ( )\n", NULL));
+
+ Assert(SSIsClipboardFormatAvailable(g_cfOwnerLink));
+ Assert(GetOpenClipboardWindow() ==
+ GetPrivateClipboardWindow(CLIP_QUERY));
+
+ hOwnerLink = SSGetClipboardData(g_cfOwnerLink);
+
+ if( hOwnerLink )
+ {
+ pszClass = (LPSTR)GlobalLock(hOwnerLink);
+
+ if( pszClass )
+ {
+ // NB!! These are intentionally ANSI strings.
+ // OLE1 apps only understand ANSI
+
+ if( _xmemcmp(pszClass, "OLE2Link",
+ sizeof("OLE2Link")) == 0 )
+ {
+ fRet = TRUE;
+ }
+
+ GlobalUnlock(hOwnerLink);
+ }
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT IsOwnerLinkStdOleLink ( %lu )\n",
+ NULL, fRet));
+
+ return fRet;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: MfToPres
+//
+// Synopsis: copies the given metafile into the presentation object
+//
+// Effects:
+//
+// Arguments: [hMfPict] -- the metafilepict handle
+// [ppres] -- the presentation object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: copies the metafile and fills out relevant fields in
+// the presentation object
+//
+// History: dd-mmm-yy Author Comment
+// 11-Aug-94 alexgo port from 16bit
+//
+// Notes: This code is largely based from 16bit OLE sources
+// REVIEW: we may want to rework portions of this code,
+// particularly if we rewrite the PPRES/GENOBJ code (in
+// ostm2stg.cpp).
+//
+//--------------------------------------------------------------------------
+
+HRESULT MfToPres( HANDLE hMfPict, PPRES ppres )
+{
+ HRESULT hresult;
+ LPMETAFILEPICT pMfPict = NULL;
+ HANDLE hglobal = NULL;
+ DWORD cbSize;
+ LPVOID pv = NULL;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN MfToPres ( %lx , %p )\n", NULL,
+ hMfPict, ppres));
+
+ Assert (ppres);
+
+ pMfPict = (LPMETAFILEPICT) GlobalLock (hMfPict);
+
+
+ if( !pMfPict )
+ {
+ hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
+ goto errRtn;
+ }
+
+ ppres->m_format.m_ftag = ftagClipFormat;
+ ppres->m_format.m_cf = CF_METAFILEPICT;
+ ppres->m_ulHeight = pMfPict->yExt;
+ ppres->m_ulWidth = pMfPict->xExt;
+
+ // in order for the presentation object stuff to work right,
+ // we need to get the metafile bits in an HGLOBAL
+
+ cbSize = GetMetaFileBitsEx(pMfPict->hMF, 0, NULL);
+
+ if( cbSize == 0 )
+ {
+ hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
+ goto errRtn;
+ }
+
+ hglobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cbSize);
+
+ if( hglobal == NULL )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ pv = GlobalLock(hglobal);
+
+ if( pv == NULL )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ // now fetch the real bits
+
+ if( GetMetaFileBitsEx(pMfPict->hMF, cbSize, pv) == 0 )
+ {
+ hresult = ResultFromScode(CLIPBRD_E_BAD_DATA);
+ goto errRtn;
+ }
+
+
+ ppres->m_data.m_h = hglobal;
+ ppres->m_data.m_cbSize = cbSize;
+ ppres->m_data.m_pv = pv;
+
+ hresult = NOERROR;
+
+errRtn:
+
+ if( pMfPict )
+ {
+ GlobalUnlock(hMfPict);
+ }
+
+ if( hresult != NOERROR )
+ {
+ if( pv )
+ {
+ GlobalUnlock(hglobal);
+ }
+
+ if( hglobal )
+ {
+ GlobalFree(hglobal);
+ }
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT MftoPres ( %lx )\n", NULL, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: NativeToStorage
+//
+// Synopsis: takes the hglobal from cfNative and stuffs the data
+// onto the given storage.
+//
+// Effects:
+//
+// Arguments: [pstg] -- the storage
+// [hNative] -- the hglobal
+//
+// Requires: hNative must really have an IStorage in it
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: layers a storage on top of the HGLOBAL, removes any
+// presentation streams, and then copies into the given
+// storage.
+//
+// History: dd-mmm-yy Author Comment
+// 11-Aug-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT NativeToStorage( LPSTORAGE pstg, HANDLE hNative )
+{
+ LPLOCKBYTES plockbyte = NULL;
+ LPSTORAGE pstgNative= NULL;
+ HRESULT hresult;
+ HGLOBAL hCopy = NULL;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN NativeToStorage ( %p , %lx )\n",
+ NULL, pstg, hNative));
+
+ hCopy = UtDupGlobal(hNative, GMEM_DDESHARE | GMEM_MOVEABLE);
+
+ if( hCopy == NULL )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ hresult = CreateILockBytesOnHGlobal( hCopy, TRUE /*fDeleteOnRelease*/,
+ &plockbyte);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // This is really a 2.0 object disguised as a 1.0 object
+ // for the sake of its 1.0 container, so reconstitute
+ // the original IStorage from the native data.
+
+ hresult = StgIsStorageILockBytes(plockbyte);
+
+ if( hresult != NOERROR )
+ {
+ LEDebugOut((DEB_ERROR, "ERROR!: Native data is not based on an"
+ " IStorage!\n"));
+
+ goto errRtn;
+ }
+
+ hresult = StgOpenStorageOnILockBytes(plockbyte, NULL, STGM_DFRALL,
+ NULL, 0, &pstgNative);
+
+ if( hresult != NOERROR )
+ {
+ LEDebugOut((DEB_ERROR, "ERROR!: OpenStorage on Native data"
+ "failed!!\n"));
+ goto errRtn;
+ }
+
+ // now remove the any presentation streams from the native IStorage.
+ // we do this because the OLE1 container will just hang on to the
+ // hglobal although it may change (i.e. resize) the presenation.
+ // Any cached presentation streams may therefore be invalid.
+
+ // the caller of this function should reconstruct new presentation
+ // streams from data available on the clipboard.
+
+ hresult = UtDoStreamOperation(pstgNative,/* pstgSrc */
+ NULL, /* pstgDst */
+ OPCODE_REMOVE, /* operation to performed */
+ STREAMTYPE_CACHE); /* streams to be operated upon */
+
+ if( hresult != NOERROR )
+ {
+ LEDebugOut((DEB_ERROR, "ERROR!: Cache stream removal "
+ "failed for Native data-based IStorage!\n"));
+ goto errRtn;
+ }
+
+ hresult = pstgNative->CopyTo(0, NULL, NULL, pstg);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+errRtn:
+ if( pstgNative )
+ {
+ pstgNative->Release();
+ }
+ if( plockbyte )
+ {
+ plockbyte->Release();
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT NativeToStorage ( %lx )\n", NULL,
+ hresult));
+
+ return hresult;
+}
+
+
+//
+// Clipboard Data object Formatetc Enumerator
+//
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipEnumFormatEtc::QueryInterface
+//
+// Synopsis: returns requested interfaces
+//
+// Effects:
+//
+// Arguments: [riid] -- the requested interface
+// [ppvObj] -- where to put the interface pointer
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipEnumFormatEtc::QueryInterface( REFIID riid, LPVOID *ppvObj )
+{
+ HRESULT hresult = NOERROR;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipEnumFormatEtc::QueryInterface "
+ "( %p , %p )\n", this, riid, ppvObj));
+
+ if( IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IEnumFORMATETC) )
+ {
+ *ppvObj = this;
+ AddRef();
+ }
+ else
+ {
+ *ppvObj = NULL;
+ hresult = ResultFromScode(E_NOINTERFACE);
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CClipEnumFormatEtc::QueryInterface "
+ "( %lx ) [ %p ]\n", this, *ppvObj ));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipEnumFormatEtc::AddRef
+//
+// Synopsis: increments the reference count
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG-- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CClipEnumFormatEtc::AddRef( )
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipEnumFormatEtc::AddRef ( )\n",
+ this));
+
+ ++m_refs;
+
+ LEDebugOut((DEB_TRACE, "%p OUT CClipEnumFormatEtc::AddRef ( %lu )\n",
+ this, m_refs));
+
+ return m_refs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipEnumFormatEtc::Release
+//
+// Synopsis: decrements the reference count on the object
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CClipEnumFormatEtc::Release( )
+{
+ ULONG cRefs;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipEnumFormatEtc::Release ( )\n",
+ this));
+
+ if( (cRefs = --m_refs ) == 0 )
+ {
+ LEDebugOut((DEB_TRACE, "%p DELETED CClipEnumFormatEtc\n",
+ this));
+ delete this;
+ }
+
+ // using "this" below is OK, since we only want its value
+ LEDebugOut((DEB_TRACE, "%p OUT CClipEnumFormatEtc::Release ( %lu )\n",
+ this, cRefs));
+
+ return cRefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipEnumFormatEtc::Next
+//
+// Synopsis: gets the next [celt] formats
+//
+// Effects:
+//
+// Arguments: [celt] -- the number of elements to fetch
+// [rgelt] -- where to put them
+// [pceltFetched] -- the number of formats actually fetched
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipEnumFormatEtc::Next( ULONG celt, FORMATETC *rgelt,
+ ULONG *pceltFetched)
+{
+ HRESULT hresult = NOERROR;
+ ULONG cFetched;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ VDATEPTROUT(rgelt, FORMATETC);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipEnumFormatEtc::Next ( %lu , %p "
+ ", %p )\n", this, celt, rgelt, pceltFetched));
+
+
+ if( pceltFetched )
+ {
+ VDATEPTROUT(pceltFetched, ULONG);
+ }
+ else if ( celt != 1 )
+ {
+ // the spec says that if pceltFetched == NULL, then
+ // the count of elements to fetch must be 1
+ hresult = ResultFromScode(E_INVALIDARG);
+ goto errRtn;
+ }
+
+ // we can only grab as many elements as there are left
+
+ if( celt > m_cTotal - m_iCurrent )
+ {
+ cFetched = m_cTotal - m_iCurrent;
+ hresult = S_FALSE;
+ }
+ else
+ {
+ cFetched = celt;
+ }
+
+ // don't do the copy if we don't have any elements to copy
+
+ if( cFetched > 0 )
+ {
+#if DBG == 1
+ // if we have no elements, then the array should be NULL
+ if( m_cTotal == 0 )
+ {
+ Assert(m_rgFormats == NULL);
+ }
+ else
+ {
+ Assert(m_rgFormats);
+ }
+#endif // DBG == 1
+
+ _xmemcpy( rgelt, m_rgFormats + m_iCurrent,
+ cFetched * sizeof(FORMATETC) );
+ }
+
+ m_iCurrent += cFetched;
+
+ if( pceltFetched )
+ {
+ *pceltFetched = cFetched;
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CClipEnumFormatEtc::Next ( %lx ) "
+ "[ %lu ]\n", this, hresult,
+ (pceltFetched) ? *pceltFetched : 0));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipEnumFormatEtc::Skip
+//
+// Synopsis: skips the next [celt] formats
+//
+// Effects:
+//
+// Arguments: [celt] -- the number of elements to skip
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipEnumFormatEtc::Skip( ULONG celt )
+{
+ HRESULT hresult = NOERROR;
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipEnumFormatEtc::Skip ( %lu )\n",
+ this, celt));
+
+ m_iCurrent += celt;
+
+ if( m_iCurrent > m_cTotal )
+ {
+ // whoops, skipped to far ahead. Set us to the max limit.
+ m_iCurrent = m_cTotal;
+ hresult = ResultFromScode(S_FALSE);
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CClipEnumFormatEtc::Skip ( %lx )\n",
+ this, hresult ));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipEnumFormatEtc::Reset
+//
+// Synopsis: resets the seek pointer to zero
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipEnumFormatEtc::Reset( void )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipEnumFormatEtc::Reset ( )\n",
+ this));
+
+ m_iCurrent = 0;
+
+ LEDebugOut((DEB_TRACE, "%p OUT CClipEnumFormatEtc::Reset ( %lx )\n",
+ this, NOERROR ));
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipEnumFormatEtc::Clone
+//
+// Synopsis: clones the enumerator
+//
+// Effects:
+//
+// Arguments: [ppIEnum] -- where to put the cloned enumerator
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CClipEnumFormatEtc::Clone( IEnumFORMATETC **ppIEnum )
+{
+ HRESULT hresult = ResultFromScode(E_OUTOFMEMORY);
+ CClipEnumFormatEtc * pClipEnum;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ VDATEPTROUT(ppIEnum, IEnumFORMATETC *);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CClipEnumFormatEtc::Clone ( %p )\n",
+ this, ppIEnum));
+
+ *ppIEnum = NULL;
+
+ pClipEnum = new CClipEnumFormatEtc();
+
+ // ref count will be 1 and m_iCurrent will be zero.
+
+ if( pClipEnum )
+ {
+ pClipEnum->m_cTotal = m_cTotal;
+ pClipEnum->m_iCurrent = m_iCurrent;
+
+ // only bother to copy the formatetc array if we actually
+ // have elements in it.
+
+ if( m_cTotal > 0 )
+ {
+ Assert(m_rgFormats == NULL);
+
+ pClipEnum->m_rgFormats = (FORMATETC *)PrivMemAlloc(
+ m_cTotal * sizeof(FORMATETC));
+
+ if( pClipEnum->m_rgFormats )
+ {
+ // copy our formatetc's into the cloned
+ // enumerator's array
+ _xmemcpy(pClipEnum->m_rgFormats, m_rgFormats,
+ m_cTotal * sizeof(FORMATETC) );
+
+ *ppIEnum = pClipEnum;
+
+ hresult = NOERROR;
+ }
+ else
+ {
+ delete pClipEnum;
+ }
+ }
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CClipEnumFormatEtc::Clone ( %p )\n",
+ this, *ppIEnum));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipEnumFormatEtc::CClipEnumFormatEtc, private
+//
+// Synopsis: constructor
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CClipEnumFormatEtc::CClipEnumFormatEtc( void )
+{
+ m_refs = 1; // give the intial reference
+ m_rgFormats = NULL;
+ m_iCurrent = 0;
+ m_cTotal = 0;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipEnumFormatEtc::~CClipEnumFormatEtc, private
+//
+// Synopsis: destructor
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CClipEnumFormatEtc::~CClipEnumFormatEtc( void )
+{
+ if( m_rgFormats )
+ {
+ PrivMemFree(m_rgFormats);
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipEnumFormatEtc::Create, static, public
+//
+// Synopsis: Creates a clipboard formatetc enumerator
+//
+// Effects:
+//
+// Arguments: [ppIEnum] -- where to put the enumerator
+// [prgFormats] -- the initial list of formats to use
+// (may be NULL)
+// [cFormats] -- the count of formats in that list
+//
+// Requires: the clipboard must be open
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+// If we are given a list of formats to use, then simply
+// copy formats that are still valid (i.e. still on the
+// clipboard) into the enumerator. A clipboard format
+// could dissappear from the clipboard if we were unable
+// to render its data.
+//
+// Otherwise, numerate all of the clipboard formats and create an
+// array of formatetc's from them.
+//
+// for each clipboard format, we will check to see if it
+// is something we know about (BITMAPs, EmbedSource, etc).
+// and correctly construct a formatetc that would successfully
+// fetch the data if passed to GetData.
+//
+// Note that user-defined formats will always get a flat medium
+// even if the data could be retrieved onto a storage. Without
+// actually fetching the data (which could be expensive), or
+// without knowing the original formatetc, we cannot do any
+// better.
+//
+// "Private" formats, such as g_cfDataObject, which are only used
+// internally by OLE are not included in the enumeration, even
+// though they are technically available on the clipboard
+//
+// If only OLE1 formats are present, then we will synthesize
+// the list of OLE2 formats that we could support.
+//
+// History: dd-mmm-yy Author Comment
+// 04-Jun-94 alexgo added OLE1 support
+// 11-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT CClipEnumFormatEtc::Create( IEnumFORMATETC **ppIEnum,
+ FORMATETC *prgFormats, DWORD cFormats )
+{
+ HRESULT hresult = ResultFromScode(E_OUTOFMEMORY);
+ CClipEnumFormatEtc * pClipEnum;
+ UINT cfFormat = NULL;
+ ULONG i;
+ ULONG cExtraFormats;
+ DWORD flatmediums,
+ structuredmediums;
+
+#define MAX_OLE2FORMATS 4 // we can at most construct 4 OLE2
+ // formats from OLE1 data
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CClipEnumFormatEtc::Create ( %p )\n",
+ NULL, ppIEnum));
+
+ *ppIEnum = NULL;
+
+ // Lame-oid 16bit apps do binary comparisons on the tymed instead
+ // of bit-masking. This is a hack to make them work.
+ if( IsWOWThread() )
+ {
+ flatmediums = TYMED_HGLOBAL;
+ structuredmediums = TYMED_ISTORAGE;
+ }
+ else
+ {
+ flatmediums = (TYMED_HGLOBAL | TYMED_ISTREAM);
+ structuredmediums = (TYMED_ISTORAGE | TYMED_ISTREAM |
+ TYMED_HGLOBAL);
+ }
+
+ pClipEnum = new CClipEnumFormatEtc();
+
+ if( !pClipEnum )
+ {
+ goto errRtn;
+ }
+
+ // if we were given an array of formats to begin with, use it
+
+ if( prgFormats != NULL )
+ {
+ // this may be bigger than we need, but that's OK
+
+ // if the number of formats is 0, then don't bother
+ // allocating
+
+ if( cFormats > 0 )
+ {
+ pClipEnum->m_rgFormats = (FORMATETC *)PrivMemAlloc(
+ cFormats * sizeof(FORMATETC));
+
+ if( !pClipEnum->m_rgFormats )
+ {
+ delete pClipEnum;
+ goto errRtn;
+ }
+
+ }
+
+
+ // check to see if the format is still there
+ for( i=0; i< cFormats; i++ )
+ {
+ if( SSIsClipboardFormatAvailable(
+ prgFormats[i].cfFormat) )
+ {
+ // structure copy
+ pClipEnum->m_rgFormats[pClipEnum->m_cTotal] =
+ prgFormats[i];
+ pClipEnum->m_cTotal++;
+ }
+ }
+
+ // if we get this far, then everything is OK
+
+ *ppIEnum = pClipEnum;
+ hresult = NOERROR;
+
+ goto errRtn;
+ }
+
+ Assert(prgFormats == NULL);
+
+ // if we were NOT given an array of formats to start from, then
+ // build up a list from scratch.
+
+ // Since we'll be calling EnumClipboardFormats, we must open
+ // the clipboard
+
+ //
+ //
+ // BEGIN: OPENCLIPBOARD
+ //
+ //
+
+ hresult = OleOpenClipboard(NULL, NULL);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // first count the number of formats on the clipboard
+
+ pClipEnum->m_cTotal = CountClipboardFormats();
+
+ // don't include OLE's private clipboard formats in the count
+ if (SSIsClipboardFormatAvailable(g_cfDataObject))
+ pClipEnum->m_cTotal--;
+ if (SSIsClipboardFormatAvailable(g_cfOlePrivateData))
+ pClipEnum->m_cTotal--;
+
+ // now allocate memory for the array
+ // if there are zero formats, then don't bother allocating
+ // the memory
+
+ if( pClipEnum->m_cTotal > 0 )
+ {
+
+ // here we will allocate enough memory for the formats
+ // we know about plus enough to cover any OLE2 formats
+ // that we might be able to synthesize from OLE1 formats
+
+ pClipEnum->m_rgFormats = (FORMATETC *)PrivMemAlloc(
+ (pClipEnum->m_cTotal +
+ MAX_OLE2FORMATS) *
+ sizeof(FORMATETC));
+
+ if( !pClipEnum->m_rgFormats )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ if( !SSCloseClipboard() )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: "
+ "CloseClipboard failed!\n"));
+ ; // no-op to keep the compiler happy
+ }
+
+ //
+ // END: CLOSECLIPBOARD
+ //
+
+ delete pClipEnum;
+ goto errRtn;
+ }
+ }
+
+ // first check to see if we can synthesize any OLE2 formats
+ // from OLE1 data.
+
+ cExtraFormats = 0;
+
+ // check for EmbedSource first
+ if( CanRetrieveOle2FromOle1(g_cfEmbedSource) )
+ {
+ // set up a formatetc entry for EmbedSource
+
+ INIT_FORETC(pClipEnum->m_rgFormats[cExtraFormats]);
+ pClipEnum->m_rgFormats[cExtraFormats].cfFormat =
+ g_cfEmbedSource;
+ pClipEnum->m_rgFormats[cExtraFormats].tymed =
+ structuredmediums;
+
+ cExtraFormats++;
+
+ // we only want to support cfObjectDescriptor if we
+ // can offer EmbedSource (which is why we're in this
+ // if block)
+
+ if( CanRetrieveOle2FromOle1(g_cfObjectDescriptor) )
+ {
+ INIT_FORETC(pClipEnum->m_rgFormats[cExtraFormats]);
+ pClipEnum->m_rgFormats[cExtraFormats].cfFormat =
+ g_cfObjectDescriptor;
+ pClipEnum->m_rgFormats[cExtraFormats].tymed =
+ flatmediums;
+
+ cExtraFormats++;
+ }
+ }
+
+
+ // check for EmbeddedObject
+ if( CanRetrieveOle2FromOle1(g_cfEmbeddedObject) )
+ {
+ // set up a formatetc entry for EmbedSource
+
+ INIT_FORETC(pClipEnum->m_rgFormats[cExtraFormats]);
+ pClipEnum->m_rgFormats[cExtraFormats].cfFormat =
+ g_cfEmbeddedObject;
+ pClipEnum->m_rgFormats[cExtraFormats].tymed =
+ structuredmediums;
+
+ cExtraFormats++;
+
+ // we only want to support cfObjectDescriptor if we
+ // can offer EmbedEmbedded (which is why we're in this
+ // if block)
+
+ if( CanRetrieveOle2FromOle1(g_cfObjectDescriptor) )
+ {
+ INIT_FORETC(pClipEnum->m_rgFormats[cExtraFormats]);
+ pClipEnum->m_rgFormats[cExtraFormats].cfFormat =
+ g_cfObjectDescriptor;
+ pClipEnum->m_rgFormats[cExtraFormats].tymed =
+ flatmediums;
+
+ cExtraFormats++;
+ }
+ }
+ // check for LinkSource
+
+ if( CanRetrieveOle2FromOle1(g_cfLinkSource) )
+ {
+ INIT_FORETC(pClipEnum->m_rgFormats[cExtraFormats]);
+ pClipEnum->m_rgFormats[cExtraFormats].cfFormat =
+ g_cfLinkSource;
+
+ // for LinkSource in WOW, we want to explicitly offer
+ // only ISTREAM tymed because that's what 16bit code
+ // did.
+ if( IsWOWThread() )
+ {
+ pClipEnum->m_rgFormats[cExtraFormats].tymed =
+ TYMED_ISTREAM;
+ }
+ else
+ {
+ pClipEnum->m_rgFormats[cExtraFormats].tymed =
+ flatmediums;
+ }
+
+ cExtraFormats++;
+
+ // we only want to support cfLinkSrcDescriptor if we
+ // can offer LinkSource
+
+ if( CanRetrieveOle2FromOle1(g_cfLinkSrcDescriptor) )
+ {
+ INIT_FORETC(pClipEnum->m_rgFormats[cExtraFormats]);
+ pClipEnum->m_rgFormats[cExtraFormats].cfFormat =
+ g_cfLinkSrcDescriptor;
+ pClipEnum->m_rgFormats[cExtraFormats].tymed =
+ flatmediums;
+
+ cExtraFormats++;
+ }
+ }
+
+ pClipEnum->m_cTotal += cExtraFormats;
+
+ // now we need to go through and initialize each formatetc array
+ // for the remaining formats available directly on the clipboard
+ // NB: this includes any ole1 formats from which constructed OLE2
+ // formats above. This will make it easier for apps, the interop
+ // layer, and our api's to special case behaviour for backwards
+ // compatibility with old apps.
+
+ cfFormat = NULL;
+ // we increment the loop counter at the bottom (so we can skip
+ // private clipboard formats)
+
+ for( i = cExtraFormats; i < pClipEnum->m_cTotal; i++ )
+ {
+ // lindex == DEF_LINDEX
+ // aspect == DVASPECT_CONTENT
+ // ptd == NULL
+
+ INIT_FORETC(pClipEnum->m_rgFormats[i]);
+
+ cfFormat = SSEnumClipboardFormats(cfFormat);
+
+ Assert(cfFormat); // if it's NULL, something
+ // really weird is happening.
+
+ pClipEnum->m_rgFormats[i].cfFormat = cfFormat;
+
+ // try to make some reasonable guesses as to what's
+ // there.
+
+ switch( cfFormat )
+ {
+ case CF_BITMAP:
+ case CF_PALETTE:
+ pClipEnum->m_rgFormats[i].tymed = TYMED_GDI;
+ break;
+
+ case CF_METAFILEPICT:
+ pClipEnum->m_rgFormats[i].tymed = TYMED_MFPICT;
+ break;
+
+ case CF_ENHMETAFILE:
+ pClipEnum->m_rgFormats[i].tymed = TYMED_ENHMF;
+ break;
+
+ default:
+ // check for Storage-based OLE2 formats.
+ if( cfFormat == g_cfEmbedSource ||
+ cfFormat == g_cfEmbeddedObject )
+ {
+ // we can get these on any structured and flat
+ // mediums
+ pClipEnum->m_rgFormats[i].tymed =
+ structuredmediums;
+
+ // In order to get here, the app must have
+ // manually set these formats on the clipboard
+ // (i.e. by not using OleSetClipboard()).
+
+ // This is OK, but print out a warning.
+
+ LEDebugOut((DEB_WARN, "WARNING: Ole2 formats "
+ "unexpected on clipboard\n"));
+ }
+ else
+ {
+ // we don't know, so be safe and just answer
+ // with flat mediums
+ pClipEnum->m_rgFormats[i].tymed =
+ flatmediums;
+ }
+ break;
+ }
+ }
+
+ if( !SSCloseClipboard() )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: CloseClipboard failed!\n"));
+ ; // no-op to keep the compiler happy
+ }
+
+ //
+ //
+ // END: CLOSECLIPBOARD
+ //
+ //
+
+ // if we get this far, then everything is OK
+
+ *ppIEnum = pClipEnum;
+
+ hresult = NOERROR;
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CClipEnumFormatEtc::Create ( %lx )"
+ " [ %p ]\n", NULL, hresult, *ppIEnum));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClipEnumFormatEtc::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppszDump] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CClipEnumFormatEtc::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ unsigned int ui;
+ char *pszPrefix;
+ char *pszCThreadCheck;
+ char *pszFORMATETC;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(500);
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ pszCThreadCheck = DumpCThreadCheck((CThreadCheck *)this, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CThreadCheck:" << endl;
+ dstrDump << pszCThreadCheck;
+ CoTaskMemFree(pszCThreadCheck);
+
+ dstrDump << pszPrefix << "No. of References = " << m_refs << endl;
+
+ dstrDump << pszPrefix << "Index to current FORMATETC = " << m_iCurrent << endl;
+
+ dstrDump << pszPrefix << "No. in FORMATETC array = " << m_cTotal << endl;
+
+ for (ui = 0; ui < m_cTotal; ui++)
+ {
+ pszFORMATETC = DumpFORMATETC(&m_rgFormats[ui], ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "FORMATETC [" << ui << "]:" << endl;
+ dstrDump << pszFORMATETC;
+ CoTaskMemFree(pszFORMATETC);
+ }
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCClipEnumFormatEtc, public (_DEBUG only)
+//
+// Synopsis: calls the CClipEnumFormatEtc::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pCEFE] - pointer to CClipEnumFormatEtc
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCClipEnumFormatEtc(CClipEnumFormatEtc *pCEFE, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pCEFE == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pCEFE->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
diff --git a/private/ole32/ole232/clipbrd/clipdata.h b/private/ole32/ole232/clipbrd/clipdata.h
new file mode 100644
index 000000000..6a0501905
--- /dev/null
+++ b/private/ole32/ole232/clipbrd/clipdata.h
@@ -0,0 +1,207 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: clipdata.h
+//
+// Contents: Declaration of the clipboard data object.
+//
+// Classes: CClipDataObject
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH added Dump methods to CClipDataObject
+// and CClipEnumFormatEtc
+// 31-Mar-94 alexgo author
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+#include <dbgexts.h>
+#endif // _DEBUG
+
+#ifndef _CLIPDATA_H
+#define _CLIPDATA_H
+
+
+typedef enum
+{
+ RESET_AND_FREE = 1,
+ JUST_RESET = 2
+} FreeResourcesFlags;
+
+typedef enum
+{
+ FORMAT_NOTFOUND = 1,
+ FORMAT_BADMATCH = 2,
+ FORMAT_GOODMATCH = 4
+} FormatMatchFlag;
+
+//+-------------------------------------------------------------------------
+//
+// Class: CClipDataObject
+//
+// Purpose: clipboard data object
+//
+// Interface: IDataObject
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH added Dump method (_DEBUG only)
+// 04-Jun-94 alexgo added OLE1 support
+// 31-Mar-94 alexgo author
+//
+// Notes: See clipdata.cpp for a description of OLE1 support
+//
+//--------------------------------------------------------------------------
+
+class CClipDataObject : public IDataObject, public CPrivAlloc,
+ public CThreadCheck
+{
+public:
+ // IUnknown methods
+ STDMETHOD(QueryInterface) (REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ // IDataObject methods
+ STDMETHOD(GetData) (LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium);
+ STDMETHOD(GetDataHere) (LPFORMATETC pformatetc,
+ LPSTGMEDIUM pmedium);
+ STDMETHOD(QueryGetData) (LPFORMATETC pformatetc);
+ STDMETHOD(GetCanonicalFormatEtc) (LPFORMATETC pformatetc,
+ LPFORMATETC pformatetcOut);
+ STDMETHOD(SetData) (LPFORMATETC pformatetc,
+ STGMEDIUM FAR* pmedium, BOOL fRelease);
+ STDMETHOD(EnumFormatEtc) (DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenumFormatEtc);
+ STDMETHOD(DAdvise) (FORMATETC FAR* pFormatetc, DWORD advf,
+ IAdviseSink FAR* pAdvSink, DWORD FAR* pdwConnection);
+ STDMETHOD(DUnadvise) (DWORD dwConnection);
+ STDMETHOD(EnumDAdvise) (LPENUMSTATDATA FAR* ppenumAdvise);
+
+ static HRESULT CClipDataObject::Create(IDataObject **ppDataObj,
+ FORMATETC *prgFormats, DWORD cFormats);
+
+#ifdef _DEBUG
+
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+
+ // need to be able to access CClipDataObject private data members in the
+ // following debugger extension APIs
+ // this allows the debugger extension APIs to copy memory from the
+ // debuggee process memory to the debugger's process memory
+ // this is required since the Dump method follows pointers to other
+ // structures and classes
+ friend DEBUG_EXTENSION_API(dump_clipdataobject);
+
+#endif // _DEBUG
+
+ // HACK ALERT!!! The constructor and destructor for the clipboard
+ // data object should really be private. However, MFC was being
+ // slimy, so we have to special case testing against clipboard data
+ // objects in OleQueryCreateFromData. See create.cpp,
+ // wQueryEmbedFormats for more details.
+
+ CClipDataObject(); // constructor
+ ~CClipDataObject(); // destructor
+
+private:
+ void GetDataObjectForClip(); // Get real data object for clipboard
+ FormatMatchFlag MatchFormatetc( FORMATETC *pformatetc, TYMED *ptymed );
+ // checks the given formatetc against
+ // the formatetc we know about.
+
+ // the following methods and data items are used for OLE1
+ // support
+ void FreeResources( FreeResourcesFlags fFlags );
+ HRESULT GetAndTranslateOle1( UINT cf, LPOLESTR *ppszClass,
+ LPOLESTR *ppszFile, LPOLESTR *ppszItem,
+ LPSTR *ppszItemA );
+ HRESULT GetEmbeddedObjectFromOle1( STGMEDIUM *pmedium );
+ HRESULT GetEmbedSourceFromOle1( STGMEDIUM *pmedium );
+ HRESULT GetLinkSourceFromOle1( STGMEDIUM *pmedium );
+ HRESULT GetObjectDescriptorFromOle1( UINT cf,
+ STGMEDIUM *pmedium );
+ HRESULT GetOle2FromOle1( UINT cf, STGMEDIUM *pmedium );
+ HRESULT OleGetClipboardData( UINT cf, HANDLE *pHandle );
+ BOOL OleIsClipboardFormatAvailable( UINT cf );
+
+ HGLOBAL m_hOle1; // hGlobal to OLE2 data constructed
+ // from OLE1 data
+ IUnknown * m_pUnkOle1; // IUnknown to either a storage or
+ // a stream of OLE1 data
+
+ // end of OLE1 support
+
+ ULONG m_refs; // reference count
+ FORMATETC * m_rgFormats;// array of formatetcs (if available)
+ DWORD m_cFormats; // count of the formats
+ IDataObject * m_pDataObject; // Actual data object for data.
+ BOOL m_fTriedToGetDataObject;
+ // indicates whether or not we've
+ // tried to get the real IDataObject
+ // from the clipboard source
+ // (see GetDataObjectForClip)
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CClipEnumFormatEtc
+//
+// Purpose: Enumerator for the formats available on the clipboard
+//
+// Interface: IEnumFORMATETC
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH added Dump method (_DEBUG only)
+// 05-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CClipEnumFormatEtc :public IEnumFORMATETC, public CPrivAlloc,
+ public CThreadCheck
+{
+public:
+ STDMETHOD(QueryInterface)(REFIID riid, LPLPVOID ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ STDMETHOD(Next) (ULONG celt, FORMATETC *rgelt,
+ ULONG *pceltFetched);
+ STDMETHOD(Skip) (ULONG celt);
+ STDMETHOD(Reset) (void);
+ STDMETHOD(Clone) (IEnumFORMATETC **ppenum);
+
+ static HRESULT Create(IEnumFORMATETC **ppIEnum, FORMATETC *prgFormats,
+ DWORD cFormats);
+
+#ifdef _DEBUG
+
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+
+ // need to be able to access CClipEnumFormatEtc private data members in the
+ // following debugger extension APIs
+ // this allows the debugger extension APIs to copy memory from the
+ // debuggee process memory to the debugger's process memory
+ // this is required since the Dump method follows pointers to other
+ // structures and classes
+ friend DEBUG_EXTENSION_API(dump_clipenumformatetc);
+
+#endif // _DEBUG
+
+private:
+ CClipEnumFormatEtc(); // constructor
+ ~CClipEnumFormatEtc(); // destructor
+
+ ULONG m_refs; // reference count
+ ULONG m_iCurrent; // current clipboard format
+ ULONG m_cTotal; // total number of formats
+ FORMATETC * m_rgFormats; // array of available formats
+};
+
+#endif // !_CLIPDATA_H
diff --git a/private/ole32/ole232/clipbrd/daytona/makefile b/private/ole32/ole232/clipbrd/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/ole232/clipbrd/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/ole232/clipbrd/daytona/sources b/private/ole32/ole232/clipbrd/daytona/sources
new file mode 100644
index 000000000..994edb9f4
--- /dev/null
+++ b/private/ole32/ole232/clipbrd/daytona/sources
@@ -0,0 +1,77 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = ole232
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= clipbrd
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..\..\inc
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+
+SOURCES= \
+ ..\clipapi.cpp \
+ ..\clipdata.cpp
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
diff --git a/private/ole32/ole232/clipbrd/depend.mk b/private/ole32/ole232/clipbrd/depend.mk
new file mode 100644
index 000000000..a4da51dd2
--- /dev/null
+++ b/private/ole32/ole232/clipbrd/depend.mk
@@ -0,0 +1,36 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\clipbrd.obj $(OBJDIR)\clipbrd.lst: .\clipbrd.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole1cls.h $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h \
+ $(CAIROLE)\ih\olemem.h $(CAIROLE)\ih\olerem.h $(CAIROLE)\ih\privguid.h \
+ $(CAIROLE)\ih\utils.h $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\clipbrd.h $(CAIROLE)\ole232\inc\create.h \
+ $(CAIROLE)\ole232\inc\fetcenum.h $(CAIROLE)\ole232\inc\map_uhw.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(CAIROLE)\ole232\inc\ostm2stg.h \
+ $(CAIROLE)\ole232\inc\reterr.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
diff --git a/private/ole32/ole232/clipbrd/dirs b/private/ole32/ole232/clipbrd/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/ole232/clipbrd/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/ole232/clipbrd/filelist.mk b/private/ole32/ole232/clipbrd/filelist.mk
new file mode 100644
index 000000000..ab99d0a9a
--- /dev/null
+++ b/private/ole32/ole232/clipbrd/filelist.mk
@@ -0,0 +1,48 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = clipbrd.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CPPFILES = \
+ .\clipbrd.cpp \
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PFILE =
+
+!include $(CAIROLE)\ole232\ole.mk
diff --git a/private/ole32/ole232/clipbrd/makefile b/private/ole32/ole232/clipbrd/makefile
new file mode 100644
index 000000000..1725b5e9a
--- /dev/null
+++ b/private/ole32/ole232/clipbrd/makefile
@@ -0,0 +1,26 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1992.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/ole232/debug/cdebug.cpp b/private/ole32/ole232/debug/cdebug.cpp
new file mode 100644
index 000000000..d909a41a5
--- /dev/null
+++ b/private/ole32/ole232/debug/cdebug.cpp
@@ -0,0 +1,1226 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// cdebug.cpp
+//
+// Contents:
+// Ole2 internal debugging support; implementation of debugstream
+// and IDebug for interface/class
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 24-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocation
+// 12/31/93 - ChrisWe - defined DbgWarn for use by reterr.h
+// 12/31/93 - ChrisWe - make compile with _DEBUG defined
+// 03-Jan-95 BruceMa Use olewcstombs, etc.
+//
+//-----------------------------------------------------------------------------
+
+#include <le2int.h>
+
+//REVIEW32: RemLookupSHUnk not supported in cairo compobj
+#ifndef WIN32
+#include <olerem.h> //for RemLookupSHUnk
+#endif
+
+#pragma SEG(cdebug)
+
+#pragma SEG(cdebug)
+
+#include <string.h>
+#ifdef _MAC
+#define Yield()
+#endif
+
+//
+// Redefine UNICODE functions to ANSI for Chicago support.
+//
+#if !defined(UNICODE)
+#define swprintf wsprintfA
+#undef _xstrcpy
+#undef _xstrlen
+#define _xstrcpy strcpy
+#define _xstrlen strlen
+#endif
+
+#ifdef _DEBUG
+FARINTERNAL_(void) DbgWarn(LPSTR psz, LPSTR pszFileName, ULONG uLineno)
+{
+ static const char msg[] = "Unexpected result: ";
+ const char *pszmsg;
+ TCHAR buf[250];
+
+ // pick a message
+ pszmsg = psz ? psz : msg;
+
+ // write this out to the debugger
+#ifdef UNICODE
+ MultiByteToWideChar(CP_ACP, 0, pszmsg, strlen(pszmsg)+1,
+ buf, sizeof(buf));
+ OutputDebugString(buf);
+ MultiByteToWideChar(CP_ACP, 0, pszFileName, strlen(pszFileName)+1,
+ buf, sizeof(buf));
+ OutputDebugString(buf);
+ wsprintf(buf, TEXT(", line %lu\n"), uLineno);
+#else // !UNICODE
+ OutputDebugString(pszmsg);
+ OutputDebugString(pszFileName);
+ wsprintfA(buf, TEXT(", line %lu\n"), uLineno);
+#endif // UNICODE
+
+ OutputDebugString(buf);
+}
+#endif // _DEBUG
+
+
+//some constants used only in this file
+#define DBGMARGIN 45
+#define DBGTABSIZE 4
+#define HEADER 1
+#define NOHEADER 0
+
+// mattp!!!! NYI for MAC
+
+
+#ifdef _MAC
+TCHAR vDebugStr[300];
+
+
+#pragma SEG(DbgReplyFilter)
+pascal BOOL DbgReplyFilter (
+ long lParam,
+ HighLevelEventMsgPtr lpmsg,
+ TargetIDPtr lptargetid)
+{
+ //#pragma unused (lptargetid)
+ TargetID sender;
+ unsigned long msgRefcon;
+ unsigned long cb;
+
+ long msgClass = (long)(lpmsg->theMsgEvent.message);
+ long msgType = *(long *)&(lpmsg->theMsgEvent.where);
+
+ if ((msgType != 'Sync') || (msgClass != 'Dbg2')) { // i
+ return false;
+ }
+
+ AcceptHighLevelEvent(&sender, &msgRefcon, NULL, &cb); // here we dispose of the auto reply
+
+ return true;
+}
+
+void OutputDebugString(const TCHAR *s)
+{
+ //*vDebugStr = sprintf(vDebugStr+1, "%s", s);
+ //DebugStr((Str255) vDebugStr);
+
+ if (SendHighLevelEvent('LSpy', 'Dbg2', 'TEXT', 'Eric',(TCHAR*) s, _xstrlen(s))) {
+ long timeout = TickCount() + 60; //timeout in 1 second
+ OSErr err;
+
+#if 0
+ while (timeout > TickCount()) {
+ EventRecord evt;
+
+ if (GetSpecificHighLevelEvent(
+ (GetSpecificFilterProcPtr) DbgReplyFilter, NULL, &err)) {
+ // DebugStr("\pgot dbg2 return reciept");
+ break;
+ }
+
+ WaitNextEvent(NULL, &evt, 3, NULL);
+ }
+#else
+ SystemTask();
+#endif
+ }
+ else
+ ;//DebugStr("\pBad send hl");
+}
+#endif // _MAC
+
+
+ASSERTDATA
+
+#define DBGLOGFILENAME TEXT("debug.log")
+static void GetCurDateTime(LPTSTR lpsz);
+
+
+#pragma SEG(DbgLogOpen)
+STDAPI_(HFILE) DbgLogOpen(LPCTSTR lpszFile, LPCTSTR lpszMode)
+{
+#ifdef _DEBUG
+#ifndef _MAC
+ HFILE fh;
+ LPSTR lpsz;
+#ifdef _UNICODE
+ char buf[2 * MAX_PATH];
+#endif
+
+ AssertSz( lpszFile && lpszMode, "Invalid arguments to DbgLogOpen");
+
+ switch (lpszMode[0]) {
+ case TEXT('w'):
+#ifdef _UNICODE
+ WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, lpszFile, -1, buf, MAX_PATH, NULL, NULL);
+ lpsz = buf;
+#else
+ lpsz = (LPSTR)lpszFile;
+#endif
+ // Open for writing (overwrite if exists)
+ fh = _lcreat(lpsz, 0);
+ break;
+
+ case TEXT('r'):
+ // Open for reading
+#ifdef _UNICODE
+ WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, lpszFile, -1, buf, MAX_PATH, NULL, NULL);
+ lpsz = buf;
+#else
+ lpsz = (LPSTR)lpszFile;
+#endif
+ fh = _lopen(lpsz, OF_READ);
+ break;
+
+ case TEXT('a'):
+#ifdef _UNICODE
+ WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, lpszFile, -1, buf, MAX_PATH, NULL, NULL);
+ lpsz = buf;
+#else
+ lpsz = (LPSTR)lpszFile;
+#endif
+ // Open for appending
+ // to append to log file seek to end before writing
+ if ((fh = _lopen(lpsz, OF_READWRITE)) != -1) {
+#ifdef WIN32
+ _llseek(fh, 0L, FILE_END);
+#else
+ _llseek(fh, 0L, SEEK_END);
+#endif // WIN32
+ } else {
+ // file does not exist, create a new one.
+ fh = _lcreat(lpsz, 0);
+ }
+ break;
+ }
+ return fh;
+#endif //_MAC
+#else
+ (void) lpszFile;
+ (void) lpszMode;
+ return -1;
+#endif //_DEBUG
+}
+
+
+#pragma SEG(DbgLogClose)
+STDAPI_(void) DbgLogClose(HFILE fh)
+{
+#ifdef _DEBUG
+#ifndef _MAC
+ if (fh != -1)
+ _lclose(fh);
+#endif
+#else
+ (void) fh;
+#endif
+}
+
+
+#pragma SEG(DbgLogWrite)
+STDAPI_(void) DbgLogWrite(HFILE fh, LPCTSTR lpszStr)
+{
+#ifdef _DEBUG
+ LPSTR lpsz;
+#ifdef _UNICODE
+ char buf[2 * MAX_PATH];
+#endif
+#ifndef _MAC
+ if (fh != -1 && lpszStr)
+ {
+#ifdef _UNICODE
+ WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK, lpszStr, -1, buf, MAX_PATH, NULL, NULL);
+ lpsz = buf;
+#else
+ lpsz = (LPSTR)lpszStr;
+#endif // _UNICODE
+ _lwrite(fh, lpsz, strlen(lpsz)); // NOTE NOT UNICODE
+ }
+#endif // _MAC
+#else
+ (void) fh;
+ (void) lpszStr;
+#endif
+}
+
+
+#pragma SEG(DbgLogTimeStamp)
+STDAPI_(void) DbgLogTimeStamp(HFILE fh, LPCTSTR lpsz)
+{
+#ifdef _DEBUG
+ TCHAR buffer[80];
+
+ GetCurDateTime(buffer);
+
+ DbgLogOutputDebugString(fh, TEXT("\n***************************************\n"));
+ if (lpsz) DbgLogOutputDebugString(fh, lpsz);
+ DbgLogOutputDebugString(fh, TEXT(": "));
+ DbgLogOutputDebugString(fh, buffer);
+ DbgLogOutputDebugString(fh, TEXT("\n"));
+ DbgLogOutputDebugString(fh, TEXT(".......................................\n\n"));
+#else
+ (void) fh;
+ (void) lpsz;
+#endif
+}
+
+
+#pragma SEG(DbgLogWriteBanner)
+STDAPI_(void) DbgLogWriteBanner(HFILE fh, LPCTSTR lpsz)
+{
+#ifdef _DEBUG
+ DbgLogOutputDebugString(fh, TEXT("\n***************************************\n"));
+ if (lpsz) DbgLogOutputDebugString(fh, lpsz);
+ DbgLogOutputDebugString(fh, TEXT("\n"));
+ DbgLogOutputDebugString(fh, TEXT(".......................................\n\n"));
+#else
+ (void) fh;
+ (void) lpsz;
+#endif
+}
+
+
+#pragma SEG(DbgLogOutputDebugString)
+STDAPI_(void) DbgLogOutputDebugString(HFILE fh, LPCTSTR lpsz)
+{
+#ifdef _DEBUG
+#ifndef _MAC
+ if (fh != -1)
+ DbgLogWrite(fh, lpsz);
+ OutputDebugString(lpsz);
+#endif
+#else
+ (void)fh;
+ (void)lpsz;
+#endif
+}
+
+
+#ifdef _DEBUG
+
+#pragma SEG(GetCurDateTime)
+static void GetCurDateTime(LPTSTR lpsz)
+{
+ unsigned year, month, day, dayOfweek, hours, min, sec;
+ static const TCHAR FAR* const dayNames[7] =
+ { TEXT("Sun"), TEXT("Mon"), TEXT("Tue"), TEXT("Wed"),
+ TEXT("Thu"), TEXT("Fri"), TEXT("Sat") };
+ static const TCHAR FAR* const monthNames[12] =
+ { TEXT("Jan"), TEXT("Feb"), TEXT("Mar"), TEXT("Apr"), TEXT("May"),
+ TEXT("Jun"), TEXT("Jul"), TEXT("Aug"),
+ TEXT("Sep"), TEXT("Oct"), TEXT("Nov"), TEXT("Dec") };
+
+#ifndef _MAC
+#ifdef WIN32
+ SYSTEMTIME st;
+ GetLocalTime(&st);
+ year = st.wYear;
+ month = st.wMonth - 1;
+ dayOfweek = st.wDayOfWeek;
+ day = st.wDay;
+ hours = st.wHour;
+ min = st.wMinute;
+ sec = st.wSecond;
+#else
+ _asm {
+ // Call GetDate
+ mov ah, 0x2a
+ int 0x21
+ mov year, cx
+ mov month, dx
+ mov day, dx
+ mov dayOfweek, ax
+
+ // Call GetTime
+ mov ah, 0x2c
+ int 0x21
+ mov hours, cx
+ mov min, cx
+ mov sec, dx
+ }
+
+ month >>= 8;
+ month -= 1;
+ day &= 0xFF;
+ dayOfweek &= 0xFF;
+ hours >>= 8;
+ min &= 0xFF;
+ sec >>= 8;
+#endif //_WIN32
+#else // defined(_MAC)
+
+ // REVIEW MAC -- need function here to get current date & time
+ day = 9;
+ month = 1;
+ year = 1960;
+ hours = 12;
+ min = 30;
+ sec = 17;
+
+#endif //_MAC
+
+ // Format time as: Wed Jan 02 02:03:55 1990
+ // Format time as: Wed 05/02/1992 02:03:55
+
+#if defined(UNICODE)
+ wsprintf(lpsz, TEXT("%ws %ws %02d %02d:%02d:%02d %d"),
+ dayNames[dayOfweek],monthNames[month], day, hours, min, sec, year);
+#else
+ wsprintfA(lpsz, "%s %s %02d %02d:%02d:%02d %d",
+ dayNames[dayOfweek],monthNames[month], day, hours, min, sec, year);
+#endif
+}
+
+
+class FAR CDebugLog
+{
+private:
+ HFILE m_fhLog;
+
+public:
+ CDebugLog( ) { m_fhLog = -1; }
+ CDebugLog( LPCTSTR lpszFileName );
+ ~CDebugLog() { DbgLogClose(m_fhLog); }
+ HFILE Open(LPCTSTR lpszFileName, LPCTSTR lpszMode)
+ { return (m_fhLog = DbgLogOpen(lpszFileName, lpszMode)); }
+ void Close(void) { DbgLogClose(m_fhLog); m_fhLog = -1; }
+ void OutputDebugString(LPCTSTR lpsz) { DbgLogOutputDebugString(m_fhLog, lpsz); }
+ void TimeStamp(LPCTSTR lpsz) { DbgLogTimeStamp(m_fhLog, lpsz); }
+ void WriteBanner(LPCTSTR lpsz) { DbgLogWriteBanner(m_fhLog, lpsz); }
+
+};
+
+
+//-------------------------------------------------------------------------
+// Thought for the decade:
+// All these methods and all these functions and crud, for what?
+// So we can avoid calling the shared, system-provided, *printf?
+// Was it worth it? Is Barney a genius? He sure knows how to lead
+// everyone down the garden path...
+//-------------------------------------------------------------------------
+
+class FAR CDebugStream : public CPrivAlloc
+{
+
+public:
+ STDSTATIC_(IDebugStream FAR *) Create( // no aggregation
+ int margin, int tabsize, BOOL fHeader);
+
+private:
+ CDebugStream( int margin, int tabsize, BOOL fHeader );
+ ~CDebugStream();
+ void OutputDebugString( LPCTSTR lpsz ) {m_DbgLog.OutputDebugString(lpsz);}
+
+
+implementations:
+ implement CDSImpl : IDebugStream
+ {
+
+ public:
+ CDSImpl( CDebugStream FAR * pDebugStream )
+ { m_pDebugStream = pDebugStream; }
+ ~CDSImpl( void ) ; //{ if (m_pDebugStream->m_pendingReturn) ForceReturn(); }
+ void PrintString( LPTSTR );
+ void ForceReturn( void );
+ void ReturnIfPending( void );
+ STDMETHOD(QueryInterface)(REFIID iid, LPVOID FAR* ppvObj );
+ STDMETHOD_(ULONG,AddRef)( void );
+ STDMETHOD_(ULONG,Release)( void );
+
+ STDMETHOD_(IDebugStream&, operator << ) ( IUnknown FAR * pDebug );
+ STDMETHOD_(IDebugStream&, operator << ) ( REFCLSID rclsid );
+ STDMETHOD_(IDebugStream&, operator << ) ( int n );
+ STDMETHOD_(IDebugStream&, operator << ) ( long l );
+ STDMETHOD_(IDebugStream&, operator << ) ( ULONG l );
+ STDMETHOD_(IDebugStream&, operator << ) ( LPCTSTR sz );
+ STDMETHOD_(IDebugStream&, operator << ) ( TCHAR ch );
+ STDMETHOD_(IDebugStream&, operator << ) ( void FAR * pv );
+ STDMETHOD_(IDebugStream&, operator << ) ( CBool b );
+ STDMETHOD_(IDebugStream&, operator << ) ( CAtom atom );
+ STDMETHOD_(IDebugStream&, operator << ) ( CHwnd hwnd );
+ STDMETHOD_(IDebugStream&, Tab) ( void );
+ STDMETHOD_(IDebugStream&, Indent) ( void );
+ STDMETHOD_(IDebugStream&, UnIndent) ( void );
+ STDMETHOD_(IDebugStream&, Return) ( void );
+ STDMETHOD_(IDebugStream&, LF) ( void );
+ CDebugStream FAR * m_pDebugStream;
+ };
+ DECLARE_NC(CDebugStream,CDSImpl)
+
+ CDSImpl m_DebugStream;
+
+shared_state:
+ ULONG m_refs;
+ int m_indent;
+ int m_position;
+ int m_margin;
+ int m_tabsize;
+ BOOL m_pendingReturn;
+ CDebugLog m_DbgLog;
+};
+
+#endif // _DEBUG
+
+
+
+/*
+ * The member variable m_pendingReturn is a hack to allow
+ * the sequence of operations Return, UnIndent put the character
+ * at the *beginning of the unindented line* The debugwindow does
+ * not seem to support going to the beginning of the line or
+ * backspacing, so we do not actually do a Return until we know
+ * that the next operation is not UnIndent.
+ *
+ */
+
+
+
+/*
+ * Implementation of per process list heads
+ */
+
+#ifdef NEVER // per-proces debug lists not used
+
+static IDebug FAR * GetIDHead()
+{
+ if this gets enabled, the map should be in the etask
+}
+
+static void SetIDHead(IDebug FAR* pIDHead)
+{
+ if this gets enabled, the map should be in the etask
+}
+
+#endif // NEVER
+
+
+/*
+ * Implementation of IDebug constructor and destructor
+ */
+
+
+#ifdef NEVER
+__export IDebug::IDebug( void )
+{
+ SETPVTBL(IDebug);
+//#ifdef _DEBUG
+ BOOL fIsShared = (SHARED == PlacementOf(this));
+ IDebug FAR* pIDHead = (fIsShared ? pIDHeadShared : GetIDHead());
+
+ pIDPrev = NULL;
+ if (pIDHead)
+ pIDHead->pIDPrev = this;
+ pIDNext = pIDHead;
+ if (fIsShared) pIDHeadShared = this;
+ else SetIDHead(this);
+}
+#endif //NEVER
+
+
+#ifdef NEVER
+__export IDebug::~IDebug( void )
+{
+//#ifdef _DEBUG
+ BOOL fIsShared = (SHARED == PlacementOf(this));
+ if (pIDPrev)
+ pIDPrev->pIDNext = pIDNext;
+ else
+ if (fIsShared) pIDHeadShared = pIDNext;
+ else
+ SetIDHead(pIDNext);
+ if (pIDNext)
+ pIDNext->pIDPrev = pIDPrev;
+}
+#endif //NEVER
+
+//REVIEW: maybe we should expose this later
+STDAPI OleGetClassID( LPUNKNOWN pUnk, LPCLSID lpclsid )
+{
+ LPRUNNABLEOBJECT lpRunnableObject = NULL;
+ LPPERSIST lpPersist = NULL;
+ HRESULT hresult = NOERROR;
+
+ VDATEIFACE(pUnk);
+ VDATEPTROUT(lpclsid, LPCLSID);
+
+ *lpclsid = CLSID_NULL;
+
+ pUnk->QueryInterface(IID_IRunnableObject, (LPLPVOID)&lpRunnableObject);
+ if( lpRunnableObject ){
+ hresult = lpRunnableObject->GetRunningClass(lpclsid);
+ lpRunnableObject->Release();
+ } else {
+ pUnk->QueryInterface(IID_IPersist, (LPLPVOID)&lpPersist);
+ if( lpPersist ){
+ hresult = lpPersist->GetClassID( lpclsid );
+ lpPersist->Release();
+ }
+ }
+ return hresult;
+}
+
+#ifdef _DEBUG
+
+CDebugStream::CDebugStream( int margin, int tabsize, BOOL fHeader) : m_DebugStream(this)
+{
+#ifndef _MAC
+ static BOOL fAppendFile = FALSE;
+
+ // Create the debug log file. Overwrite the existing file if it exists.
+ m_DbgLog.Open(DBGLOGFILENAME, (fAppendFile ? TEXT("a") : TEXT("w")));
+
+ if( fHeader )
+ // only add creation timestamp to top of file.
+ if (! fAppendFile) {
+ m_DbgLog.TimeStamp(TEXT("Created"));
+ fAppendFile = TRUE;
+ } else {
+ m_DbgLog.WriteBanner(NULL);
+ }
+#endif
+ m_indent = 0;
+ m_position = m_indent;
+ m_margin = margin;
+ m_tabsize = tabsize;
+ m_refs = 1;
+ m_pendingReturn = FALSE;
+}
+
+
+CDebugStream::~CDebugStream()
+{
+ m_DbgLog.Close();
+}
+
+
+NC(CDebugStream,CDSImpl)::~CDSImpl(void)
+{
+ if (m_pDebugStream->m_pendingReturn) ForceReturn();
+}
+
+
+STDMETHODIMP NC(CDebugStream,CDSImpl)::QueryInterface(REFIID iidInterface,
+ void FAR* FAR* ppvObj )
+{
+ VDATEPTROUT(ppvObj, LPLPVOID);
+
+ if (IsEqualGUID(iidInterface, IID_IUnknown) ||
+ IsEqualGUID(iidInterface, IID_IDebugStream))
+ {
+ *ppvObj = (void FAR *)this;
+ return NOERROR;
+ } else
+ {
+ *ppvObj = NULL;
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+}
+
+
+STDMETHODIMP_(ULONG) NC(CDebugStream,CDSImpl)::AddRef( void )
+{
+ return ++m_pDebugStream->m_refs;
+}
+
+
+STDMETHODIMP_(ULONG) NC(CDebugStream,CDSImpl)::Release( void )
+{
+ if (--m_pDebugStream->m_refs == 0) {
+ delete m_pDebugStream;
+ return 0;
+ }
+
+ return m_pDebugStream->m_refs;
+}
+
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (int n)
+{
+ TCHAR buffer[12];
+ ReturnIfPending();
+ buffer[swprintf(buffer, TEXT("%d"), n)] = TEXT('\0');
+ PrintString(buffer);
+ return *this;
+}
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (long l)
+{
+ TCHAR buffer[16];
+ ReturnIfPending();
+ buffer[swprintf(buffer, TEXT("%ld"), l)] = TEXT('\0');
+ PrintString(buffer);
+ return *this;
+}
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (ULONG l)
+{
+ TCHAR buffer[16];
+ ReturnIfPending();
+ buffer[swprintf(buffer, TEXT("%lu"), l)] = TEXT('\0');
+ PrintString(buffer);
+ return *this;
+}
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (CAtom atom)
+{
+ TCHAR buffer[128];
+ ReturnIfPending();
+
+ if( (ATOM)atom ){
+ if( !GetAtomName((ATOM)atom, buffer, sizeof(buffer)) )
+ buffer[swprintf(buffer, TEXT("Invalid atom"))] = TEXT('\0');
+ }else
+ buffer[swprintf(buffer, TEXT("NULL atom"))] = TEXT('\0');
+
+ PrintString(buffer);
+ return *this;
+}
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (CHwnd hwnd)
+{
+ TCHAR szBuf[128];
+
+ ReturnIfPending();
+
+ if( (HWND)hwnd )
+ szBuf[swprintf(szBuf, TEXT("window handle: %x"), (HWND)hwnd)] = TEXT('\0');
+ else
+ szBuf[swprintf(szBuf, TEXT("NULL window handle"))] = TEXT('\0');
+
+ PrintString(szBuf);
+ return *this;
+}
+
+LPTSTR FindBreak( LPTSTR sz, int currentPosition, int margin )
+{
+ LPTSTR szBreak = sz;
+ LPTSTR szPtr = sz;
+
+ if( !sz )
+ return NULL;
+
+ while (*szPtr)
+ {
+ while (*(szPtr) && *(szPtr++) <= TEXT(' '));
+ while (*(szPtr) && *(szPtr++) > TEXT(' '));
+ if (currentPosition+(szPtr-sz) < margin)
+ {
+ szBreak = szPtr;
+ }
+ else return szBreak;
+ }
+ return szPtr;
+}
+
+/*
+ * PrintString is an internal utility routine that can assume that
+ * everything in the string (other than the null at the end) is >=
+ * ' '. Thus it knows that when it prints a single character, the
+ * position on the debug terminal advances a single columm. This
+ * would not be the case if the string could contain tabs,
+ * returns, etc.
+ */
+
+void NC(CDebugStream,CDSImpl)::PrintString(LPTSTR sz)
+{
+ // assert sz != NULL
+ LPTSTR szUnprinted = sz;
+ LPTSTR szPtr = sz;
+ TCHAR chSave;
+
+ #ifdef _MAC
+ Puts(sz);
+ return;
+ #endif
+
+ if( !sz )
+ return;
+
+ while (*szUnprinted)
+ {
+ szPtr = FindBreak( szUnprinted, m_pDebugStream->m_position, m_pDebugStream->m_margin );
+ if (szPtr == szUnprinted && m_pDebugStream->m_position > m_pDebugStream->m_indent)
+ {
+ Return();
+ szPtr = FindBreak( szUnprinted, m_pDebugStream->m_position, m_pDebugStream->m_margin );
+ if (szPtr == szUnprinted) // text won't fit even after word wrapping
+ {
+ m_pDebugStream->OutputDebugString(szUnprinted);
+ m_pDebugStream->m_position += _xstrlen(szUnprinted);
+ return;
+ }
+ }
+ chSave = *szPtr;
+ *szPtr = TEXT('\0');
+ if (m_pDebugStream->m_position == m_pDebugStream->m_indent) // no text on line, skip blanks
+ {
+ while (*szUnprinted == TEXT(' ')) szUnprinted++;
+ }
+ m_pDebugStream->OutputDebugString(szUnprinted);
+ *szPtr = chSave;
+ m_pDebugStream->m_position += (szPtr - szUnprinted);
+ szUnprinted = szPtr;
+ }
+}
+
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (TCHAR ch)
+{
+ TCHAR buffer[2] = TEXT("a");
+
+ if (ch==TEXT('\n')) Return();
+ else if (ch==TEXT('\t')) Tab();
+ else if (ch >= TEXT(' '))
+ {
+ ReturnIfPending();
+ if (m_pDebugStream->m_position >= m_pDebugStream->m_margin) Return();
+ *buffer = ch;
+ m_pDebugStream->OutputDebugString(buffer);
+ m_pDebugStream->m_position++;
+ }
+ return *this;
+}
+
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (LPCTSTR sz)
+{
+ LPTSTR szCopy;
+ TCHAR chSave;
+ LPTSTR szPtr;
+ LPTSTR szPtrSave;
+
+ ReturnIfPending();
+
+ if (!sz)
+ return *this;
+
+ szCopy = (LPTSTR)PubMemAlloc(sizeof(TCHAR)*(2+_xstrlen(sz)));
+ if (!szCopy)
+ {
+ Return();
+ *this << TEXT("Memory allocation error in DebugStream");
+ Return();
+ return *this;
+ }
+
+ _xstrcpy( szCopy, sz );
+ for (szPtr = szCopy, szPtrSave = szCopy; *szPtr; szPtr++)
+ {
+ if ( *szPtr < TEXT(' '))// we hit a control character or the end
+ {
+ chSave = *szPtr;
+ *szPtr = TEXT('\0');
+ PrintString( szPtrSave );
+ if (chSave != TEXT('\0'))
+ *szPtr = chSave;
+ szPtrSave = szPtr+1;
+ switch (chSave)
+ {
+ case TEXT('\t'): Tab();
+ break;
+ case TEXT('\n'): Return();
+ break;
+ case TEXT('\r'): m_pDebugStream->OutputDebugString(TEXT("\r"));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ PrintString( szPtrSave );
+
+ PubMemFree(szCopy);
+
+ return *this;
+}
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (CBool b)
+{
+ ReturnIfPending();
+ if (b) *this << TEXT("TRUE");
+ else *this << TEXT("FALSE");
+ return *this;
+}
+
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << ( void FAR * pv )
+{
+ TCHAR buffer[12];
+
+ ReturnIfPending();
+ if (pv == NULL)
+ *this << TEXT("NULL");
+ else
+ {
+ buffer[swprintf(buffer, TEXT("%lX"), pv)] = TEXT('\0');
+ PrintString(buffer);
+ }
+
+ return *this;
+}
+
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator <<
+ ( REFCLSID rclsid )
+{
+ TCHAR sz[256];
+
+ // REVIEW: do lookup in reg.dat for user type name
+
+ //
+ // BUGBUG - Hack just to get things rolling along.
+ //
+#if !defined(_CHICAGO_)
+ if (IsEqualGUID(rclsid, CLSID_NULL))
+ _xstrcpy(sz, TEXT("NULL CLSID"));
+ else if (StringFromCLSID2(rclsid, sz, sizeof(sz)) == 0)
+ _xstrcpy(sz, TEXT("Unknown CLSID"));
+
+ *this << sz;
+#endif
+
+ return *this;
+}
+
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator <<
+ ( IUnknown FAR * pUnk )
+{
+ IDebug FAR * pDebug = NULL;
+ CLSID clsid = CLSID_NULL;
+
+ ReturnIfPending();
+
+ if( IsValidInterface(pUnk) ){
+ pUnk->QueryInterface(IID_IDebug, (void FAR* FAR*)&pDebug);
+ if (pDebug) {
+ pDebug->Dump( this );
+ if ( !pDebug->IsValid( 0 ) )
+ *this << TEXT("Object is not valid") << TEXT('\n');
+ /*
+ * NB: Debug interfaces are *not* ref counted (so as not to skew the
+ * counts of the objects they are debugging! :)
+ */
+ } else {
+ OleGetClassID(pUnk, (LPCLSID)&clsid);
+ *this << clsid << TEXT(" @ ")<<(VOID FAR *)pUnk << TEXT(" doesn't support debug dumping");
+ }
+ } else if (!pUnk)
+ *this << TEXT("NULL interface");
+ else
+ *this << TEXT("Invalid interface @ ") << (VOID FAR *)pUnk;
+
+ return *this;
+}
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::Tab( void )
+{
+ ReturnIfPending();
+ int advance = m_pDebugStream->m_tabsize * ( 1 + m_pDebugStream->m_position/m_pDebugStream->m_tabsize) - m_pDebugStream->m_position;
+
+ if (m_pDebugStream->m_position + advance < m_pDebugStream->m_margin)
+ {
+ for (int i = 0; i < advance; i++)
+ m_pDebugStream->OutputDebugString(TEXT(" "));
+ m_pDebugStream->m_position += advance;
+ }
+ return *this;
+}
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::Indent( void )
+{
+ if (m_pDebugStream->m_indent + m_pDebugStream->m_tabsize < m_pDebugStream->m_margin)
+ m_pDebugStream->m_indent += m_pDebugStream->m_tabsize;
+ if (!m_pDebugStream->m_pendingReturn)
+ while (m_pDebugStream->m_position < m_pDebugStream->m_indent)
+ operator<<(TEXT(' '));
+
+ return *this;
+}
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::UnIndent( void )
+{
+ if (m_pDebugStream->m_indent > 0) m_pDebugStream->m_indent -= m_pDebugStream->m_tabsize;
+ return *this;
+}
+
+
+void NC(CDebugStream,CDSImpl)::ForceReturn( void )
+{
+ m_pDebugStream->OutputDebugString(TEXT("\n"));
+ for (int i = 0; i<m_pDebugStream->m_indent; i++)
+ m_pDebugStream->OutputDebugString(TEXT(" "));
+ m_pDebugStream->m_position = m_pDebugStream->m_indent;
+ m_pDebugStream->m_pendingReturn = FALSE;
+}
+
+void NC(CDebugStream,CDSImpl)::ReturnIfPending( void )
+{
+ if (m_pDebugStream->m_pendingReturn) ForceReturn();
+}
+
+
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::Return( void )
+{
+ ReturnIfPending();
+ m_pDebugStream->m_pendingReturn = TRUE;
+ Yield(); // let dbwin get control
+ return *this;
+}
+
+STDMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::LF( void )
+{
+ return Return();
+}
+
+STDSTATICIMP_(IDebugStream FAR *) CDebugStream::Create( // no aggregation
+ int margin, int tabsize, BOOL fHeader )
+{
+ CDebugStream FAR * pcds = new CDebugStream( margin, tabsize, fHeader );
+ if( !pcds ){
+ AssertSz( pcds, "Out of Memory");
+ return NULL;
+ }
+ return &(pcds->m_DebugStream);
+}
+#endif // _DEBUG
+
+
+STDAPI_(IDebugStream FAR *) MakeDebugStream( short margin, short tabsize, BOOL fHeader)
+{
+#ifdef _DEBUG
+ return CDebugStream::Create( margin, tabsize, fHeader );
+#else
+ (void) margin;
+ (void) tabsize;
+ (void) fHeader;
+ return NULL;
+#endif // _DEBUG
+}
+
+
+
+//
+// IDebug helpers
+//
+
+STDAPI_(void) DbgDumpObject( IUnknown FAR * pUnk, DWORD dwReserved )
+{
+#ifdef _DEBUG
+ IDebugStream FAR * pcds = MakeDebugStream( DBGMARGIN, DBGTABSIZE, NOHEADER );
+ (void)dwReserved;
+
+ if( pcds ) {
+ *pcds << pUnk;
+ pcds->Return();
+ pcds->Release();
+ }
+#else
+ (void) pUnk;
+ (void) dwReserved;
+#endif
+}
+
+STDAPI_(void) DbgDumpExternalObject( IUnknown FAR * pUnk, DWORD dwReserved )
+{
+//REVIEW32: Compobj does not support RemLookupSHUnk yet (alexgo 11/8/93)
+
+#ifdef WIN32
+ (void)dwReserved;
+ (void)pUnk;
+
+#elif _DEBUG
+ SHREG shreg;
+
+ (void) dwReserved;
+
+ if( IsValidInterface(pUnk) ){
+ if( RemLookupSHUnk(pUnk, NULL, &shreg) == NOERROR ){
+ DbgDumpObject(shreg.m_pSM, 0);
+ shreg.m_pSM->Release();
+ }
+ }
+
+#else
+ (void) dwReserved;
+ (void) pUnk;
+#endif
+}
+
+STDAPI_(BOOL) DbgIsObjectValid( IUnknown FAR * pUnk )
+{
+#ifdef _DEBUG
+ BOOL fReturn = TRUE; // default value for objects that don't
+ // support IDebug
+ IDebug FAR * pDebug = NULL;
+
+ if( IsValidInterface(pUnk) ){
+ pUnk->QueryInterface( IID_IDebug, (void FAR* FAR*)&pDebug);
+ if (pDebug)
+ fReturn = pDebug->IsValid();
+ //IDebug is not addref'd
+ return fReturn;
+ }
+ return FALSE;
+#else
+ (void) pUnk;
+ return TRUE;
+#endif
+}
+
+
+STDAPI_(void) DbgDumpClassName( IUnknown FAR * pUnk )
+{
+#ifdef _DEBUG
+ CLSID clsid;
+
+ IDebugStream FAR * pcds = MakeDebugStream( DBGMARGIN, DBGTABSIZE, NOHEADER );
+
+ if( pcds ) {
+ if( IsValidInterface(pUnk) ){
+ OleGetClassID( pUnk, (LPCLSID)&clsid);
+ *pcds << clsid << TEXT(" @ ") << (void FAR* )pUnk << TEXT('\n');
+ }else if (!pUnk)
+ *pcds << TEXT("NULL interface") << TEXT('\n');
+ else
+ *pcds << (void FAR *)pUnk << TEXT(" is not a valid interface") << TEXT('\n');
+ pcds->Release();
+ }
+#else
+ (void)pUnk;
+#endif
+}
+
+STDAPI_(void) DumpAllObjects( void )
+{
+//#ifdef _DEBUG
+#ifdef NEVER
+ IDebug FAR * pID = GetIDHead();
+ IDebugStream FAR * pcds = MakeDebugStream( DBGMARGIN, DBGTABSIZE, NOHEADER );
+
+ *pcds << TEXT("----TASK OBJECTS-------\n");
+ while (pID)
+ {
+ pID->Dump( pcds );
+ pID = pID->pIDNext;
+ }
+ *pcds << TEXT("----SHARED OBJECTS-------\n");
+ pID = pIDHeadShared;
+ while (pID)
+ {
+ pID->Dump( pcds );
+ pID = pID->pIDNext;
+ }
+
+ pcds->Release();
+#endif
+}
+
+
+STDAPI_(BOOL) ValidateAllObjects( BOOL fSuspicious )
+{
+//#ifdef _DEBUG
+#ifdef NEVER
+ IDebug FAR * pID = GetIDHead();
+ int pass = 0;
+ IDebugStream FAR * pcds = MakeDebugStream( DBGMARGIN, DBGTABSIZE, NOHEADER);
+ BOOL fReturn = TRUE;
+
+ while (pID)
+ {
+ if (!(pID->IsValid(fSuspicious)))
+ {
+ fReturn = FALSE;
+ if (pass == 0)
+ *pcds <<
+ TEXT("\n****INVALID OBJECT*****\n");
+ else
+ *pcds << TEXT("\n****INVALID SHARED MEMORY OBJECT*****\n");
+ pID->Dump( pcds );
+ pcds->Return();
+ }
+ pID = pID->pIDNext;
+ if ((pID == NULL) && (pass++ == 0))
+ pID = pIDHeadShared;
+ }
+ pcds->Release();
+ return fReturn;
+#endif //NEVER
+ (void) fSuspicious;
+ return TRUE;
+}
+
+
+#ifdef _DEBUG
+
+
+extern "C"
+BOOL CALLBACK __loadds DebCallBack(WORD wID, DWORD dwData)
+{
+// TCHAR rgchBuf[50];
+//// BOOL fTraceStack = FALSE;
+//// STACKTRACEENTRY ste;
+//// WORD wSS, wCS, wIP, wBP;
+// NFYLOADSEG FAR* pNFY = (NFYLOADSEG FAR *)dwData;
+//
+// if (wID == NFY_LOADSEG)
+// {
+// if (0 == _xstrcmp(pNFY->lpstrModuleName, TEXT("OLE2")))
+// {
+// swprintf(rgchBuf, TEXT("Load seg %02x(%#04x), module %s"), pNFY->wSegNum,
+// pNFY->wSelector, pNFY->lpstrModuleName);
+// OutputDebugString(rgchBuf);
+// _asm int 3
+//// if (fTraceStack)
+//// {
+//// _asm mov wSS, SS
+//// _asm mov wCS, CS
+//// _asm mov wIP, IP
+//// _asm mov wBP, BP
+//// ste.dwSize = sizeof(STACKTRACEENTRY);
+//// if (StackTraceCSIPFirst(&ste, wSS, wCS, wIP, wBP))
+//// {
+//// while (fTraceStack && StackTraceNext(&ste));
+//// }
+////
+//// }
+// }
+// }
+// else if (wID == NFY_FREESEG)
+// {
+// }
+ (void) wID;
+ (void) dwData;
+ return FALSE;
+}
+
+BOOL InstallHooks(void)
+{
+// return NotifyRegister(NULL, (LPFNNOTIFYCALLBACK)DebCallBack, NF_NORMAL);
+return TRUE;
+}
+
+BOOL UnInstallHooks()
+{
+// return NotifyUnRegister(NULL);
+return TRUE;
+}
+
+
+#endif
diff --git a/private/ole32/ole232/debug/daytona/makefile b/private/ole32/ole232/debug/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/ole232/debug/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/ole232/debug/daytona/sources b/private/ole32/ole232/debug/daytona/sources
new file mode 100644
index 000000000..d0c2d74a3
--- /dev/null
+++ b/private/ole32/ole232/debug/daytona/sources
@@ -0,0 +1,79 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = ole232
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= debug
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..\..\inc
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+
+SOURCES= \
+ ..\cdebug.cpp \
+ ..\debapi.cxx \
+ ..\dstream.cpp \
+ ..\dbgdump.cpp
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
diff --git a/private/ole32/ole232/debug/dbgdump.cpp b/private/ole32/ole232/debug/dbgdump.cpp
new file mode 100644
index 000000000..be99d27f2
--- /dev/null
+++ b/private/ole32/ole232/debug/dbgdump.cpp
@@ -0,0 +1,1310 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: dbgdump.cpp
+//
+// Contents: contains APIs to dump structures (return a formatted string
+// of structure dumps in a coherent fashion)
+//
+// Classes:
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Jan-95 t-ScottH author
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#include <memstm.h>
+#include <dbgdump.h>
+
+#ifdef _DEBUG
+ const char szDumpErrorMessage[] = "Dump Error - Out of Memory \n\0";
+ const char szDumpBadPtr[] = "Dump Error - NULL pointer \n\0";
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpADVFFlags, public (_DEBUG only)
+//
+// Synopsis: returns a char array with the set flags and hex value
+//
+// Effects:
+//
+// Arguments: [dwADVF] - flags
+//
+// Requires:
+//
+// Returns: character arry of string value of flags
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpADVFFlags(DWORD dwAdvf)
+{
+ char *pszDump;
+ dbgstream dstrDump(100);
+
+ if (dwAdvf & ADVF_NODATA)
+ {
+ dstrDump << "ADVF_NODATA ";
+ }
+ if (dwAdvf & ADVF_PRIMEFIRST)
+ {
+ dstrDump << "ADVF_PRIMEFIRST ";
+ }
+ if (dwAdvf & ADVF_ONLYONCE)
+ {
+ dstrDump << "ADVF_ONLYONCE ";
+ }
+ if (dwAdvf & ADVF_DATAONSTOP)
+ {
+ dstrDump << "ADVF_DATAONSTOP ";
+ }
+ if (dwAdvf & ADVFCACHE_NOHANDLER)
+ {
+ dstrDump << "ADVFCACHE_NOHANDLER ";
+ }
+ if (dwAdvf & ADVFCACHE_FORCEBUILTIN)
+ {
+ dstrDump << "ADVFCACHE_FORCEBUILTIN ";
+ }
+ if (dwAdvf & ADVFCACHE_ONSAVE)
+ {
+ dstrDump << "ADVFCACHE_ONSAVE ";
+ }
+ // see if there are any flags set
+ if ( ! (( dwAdvf & ADVF_NODATA ) |
+ ( dwAdvf & ADVF_PRIMEFIRST ) |
+ ( dwAdvf & ADVF_ONLYONCE ) |
+ ( dwAdvf & ADVF_DATAONSTOP ) |
+ ( dwAdvf & ADVFCACHE_NOHANDLER ) |
+ ( dwAdvf & ADVFCACHE_FORCEBUILTIN ) |
+ ( dwAdvf & ADVFCACHE_ONSAVE )))
+ {
+ dstrDump << "No FLAGS SET! ";
+ }
+ // cast as void * for formatting (0x????????)
+ dstrDump << "(" << (void *)dwAdvf << ")";
+
+ pszDump = dstrDump.str();
+
+ if (pszDump == NULL)
+ {
+ return UtDupStringA(szDumpErrorMessage);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpATOM, public (_DEBUG only)
+//
+// Synopsis: returns the ATOM name using GetAtomName
+//
+// Effects:
+//
+// Arguments: [atm] - the ATOM to get name of
+//
+// Requires: GetAtomNameA API
+//
+// Returns: a pointer to character array containing
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+#ifdef _DEBUG
+
+#define MAX_ATOMNAME 256
+
+char *DumpATOM(ATOM atm)
+{
+ UINT nResult;
+ char *pszAtom = (char *)CoTaskMemAlloc(MAX_ATOMNAME);
+
+ nResult = GetAtomNameA( atm, pszAtom, MAX_ATOMNAME);
+
+ if (nResult == 0) // GetAtomName failed
+ {
+ // try get GlobalAtomNameA
+ nResult = GlobalGetAtomNameA(atm, pszAtom, MAX_ATOMNAME);
+
+ if (nResult == 0)
+ {
+ CoTaskMemFree(pszAtom);
+
+ return DumpWIN32Error(GetLastError());
+ }
+ }
+
+ return pszAtom;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCLIPFORMAT, public (_DEBUG only)
+//
+// Synopsis: returns the CLIPFORMAT name using GetClipboardFormatName
+//
+// Effects:
+//
+// Arguments: [clipformat] - the CLIPFORMAT to get name of
+//
+// Requires: GetClipboardFormatName API
+//
+// Returns: a pointer to character array containing
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+#ifdef _DEBUG
+
+#define MAX_FORMATNAME 256
+
+char *DumpCLIPFORMAT(CLIPFORMAT clipformat)
+{
+ int nResult;
+ char *pszClipFormat;
+
+ // we have to do predefined formats by name
+ if ( clipformat > 0xC000 )
+ {
+ pszClipFormat = (char *)CoTaskMemAlloc(MAX_FORMATNAME);
+
+ nResult = SSGetClipboardFormatNameA( clipformat, pszClipFormat, MAX_FORMATNAME);
+
+ if (nResult == 0) // GetClipboardFormatName failed
+ {
+ CoTaskMemFree(pszClipFormat);
+
+ return DumpWIN32Error(GetLastError());
+ }
+ }
+ else
+ {
+ switch (clipformat)
+ {
+ case CF_METAFILEPICT:
+ pszClipFormat = UtDupStringA("CF_METAFILEPICT\0");
+ break;
+ case CF_BITMAP:
+ pszClipFormat = UtDupStringA("CF_BITMAP\0");
+ break;
+ case CF_DIB:
+ pszClipFormat = UtDupStringA("CF_DIB\0");
+ break;
+ case CF_PALETTE:
+ pszClipFormat = UtDupStringA("CF_PALETTE\0");
+ break;
+ case CF_TEXT:
+ pszClipFormat = UtDupStringA("CF_TEXT\0");
+ break;
+ case CF_UNICODETEXT:
+ pszClipFormat = UtDupStringA("CF_UNICODETEXT\0");
+ break;
+ case CF_ENHMETAFILE:
+ pszClipFormat = UtDupStringA("CF_ENHMETAFILE\0");
+ break;
+ default:
+ pszClipFormat = UtDupStringA("UNKNOWN Default Format\0");
+ break;
+ }
+ }
+
+ return pszClipFormat;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCMutexSem, public (_DEBUG only)
+//
+// Synopsis: not implemented
+//
+// Effects:
+//
+// Arguments: [pMS] - pointer to a CMutexSem
+//
+// Requires:
+//
+// Returns: character array
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCMutexSem(CMutexSem *pMS)
+{
+ return UtDupStringA("Dump CMutexSem not implemented\0");
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCLSID, public (_DEBUG only)
+//
+// Synopsis: dump a CLSID into a string using StringFromCLSID and
+// ProgIDFromCLSID
+//
+// Effects:
+//
+// Arguments: [clsid] - pointer to a CLSID
+//
+// Requires: StringFromCLSID and ProgIDFromCLSID APIs
+//
+// Returns: character array of string (allocated by OLE)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCLSID(REFCLSID clsid)
+{
+ int i;
+ HRESULT hresult;
+ LPOLESTR pszClsidString;
+ LPOLESTR pszClsidID;
+ char *pszDump;
+
+ hresult = StringFromCLSID(clsid, &pszClsidString);
+
+ if (hresult != S_OK)
+ {
+ CoTaskMemFree(pszClsidString);
+
+ return DumpHRESULT(hresult);
+ }
+
+ hresult = ProgIDFromCLSID(clsid, &pszClsidID);
+
+ if ((hresult != S_OK)&&(hresult != REGDB_E_CLASSNOTREG))
+ {
+ CoTaskMemFree(pszClsidString);
+ CoTaskMemFree(pszClsidID);
+
+ return DumpHRESULT(hresult);
+ }
+
+ pszDump = (char *)CoTaskMemAlloc(512);
+
+ if (hresult != REGDB_E_CLASSNOTREG)
+ {
+ i = wsprintfA(pszDump, "%ls %ls\0", pszClsidString, pszClsidID);
+ }
+ else
+ {
+ i = wsprintfA(pszDump, "%ls (CLSID not in registry)\0", pszClsidString);
+ }
+
+ if (i == 0)
+ {
+ pszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszClsidString);
+ CoTaskMemFree(pszClsidID);
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpDVAPECTFlags, public (_DEBUG only)
+//
+// Synopsis: returns a char array with the set flags and hex value
+//
+// Effects:
+//
+// Arguments: [dwAspect] - flags
+//
+// Requires:
+//
+// Returns: character arry of string value of flags
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpDVASPECTFlags(DWORD dwAspect)
+{
+ char *pszDump;
+ dbgstream dstrDump(100);
+
+ if (dwAspect & DVASPECT_CONTENT)
+ {
+ dstrDump << "DVASPECT_CONTENT ";
+ }
+ if (dwAspect & DVASPECT_THUMBNAIL)
+ {
+ dstrDump << "DVASPECT_THUMBNAIL ";
+ }
+ if (dwAspect & DVASPECT_ICON)
+ {
+ dstrDump << "DVASPECT_ICON ";
+ }
+ if (dwAspect & DVASPECT_DOCPRINT)
+ {
+ dstrDump << "DVASPECT_DOCPRINT ";
+ }
+ if ( ! ((dwAspect & DVASPECT_CONTENT) |
+ (dwAspect & DVASPECT_THUMBNAIL) |
+ (dwAspect & DVASPECT_ICON) |
+ (dwAspect & DVASPECT_DOCPRINT)))
+ {
+ dstrDump << "No FLAGS SET! ";
+ }
+ dstrDump << "(" << (void *)dwAspect << ")";
+
+ pszDump = dstrDump.str();
+
+ if (pszDump == NULL)
+ {
+ return UtDupStringA(szDumpErrorMessage);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpFILETIME, public (_DEBUG only)
+//
+// Synopsis: Dumps a filetime structure
+//
+// Effects:
+//
+// Arguments: [pFT] - pointer to a FILETIME structure
+//
+// Requires:
+//
+// Returns: character array of structure dump
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpFILETIME(FILETIME *pFT)
+{
+ char *pszDump;
+ dbgstream dstrDump(100);
+
+ if (pFT == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);;
+ }
+
+ dstrDump << "Low: " << pFT->dwLowDateTime;
+ dstrDump << "\tHigh: " << pFT->dwHighDateTime;
+
+ pszDump = dstrDump.str();
+
+ if (pszDump == NULL)
+ {
+ return UtDupStringA(szDumpErrorMessage);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpHRESULT
+//
+// Synopsis: Takes an HRESULT and builds a character array with a
+// string version of the error and a hex version
+//
+// Effects:
+//
+// Arguments: [hresult] - the error which we are looking up
+//
+// Requires:
+//
+// Returns: character array
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpHRESULT(HRESULT hresult)
+{
+ dbgstream dstrDump(100);
+ char *pszDump;
+ char *pszMessage = NULL;
+ int cMsgLen;
+
+ cMsgLen = FormatMessageA(
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ 0,
+ hresult,
+ MAKELANGID(0, SUBLANG_ENGLISH_US),
+ (char *)pszMessage,
+ 512,
+ 0);
+
+ if (cMsgLen == 0) // FormatMessage failed
+ {
+ delete[] pszMessage;
+ return UtDupStringA(szDumpErrorMessage);
+ }
+
+ dstrDump << "Error Code: " << pszMessage;
+ dstrDump << "(" << hresult << ")";
+
+ pszDump = dstrDump.str();
+
+ if (pszDump == NULL)
+ {
+ pszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ delete[] pszMessage;
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpMonikerDisplayName
+//
+// Synopsis: dumps a meaningful moniker name
+//
+// Effects:
+//
+// Arguments: [pMoniker] - pointer to IMoniker interface
+//
+// Requires:
+//
+// Returns: character array of display name (ANSI)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 09-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpMonikerDisplayName(IMoniker *pMoniker)
+{
+ int i;
+ HRESULT hresult;
+ LPOLESTR pszMoniker;
+ char *pszDump;
+ LPBC pBC;
+
+ if (pMoniker == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = CreateBindCtx(0, &pBC);
+ if (hresult != S_OK)
+ {
+ return DumpHRESULT(hresult);
+ }
+
+ hresult = pMoniker->GetDisplayName(pBC, NULL, &pszMoniker);
+
+ if (hresult != S_OK)
+ {
+ CoTaskMemFree(pszMoniker);
+
+ return DumpHRESULT(hresult);
+ }
+
+ pszDump = (char *)CoTaskMemAlloc(512);
+
+ i = wsprintfA(pszDump, "%ls \0", pszMoniker);
+
+ if (i == 0)
+ {
+ pszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszMoniker);
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpWIN32Error
+//
+// Synopsis: Takes an WIN32 error and builds a character array with a
+// string version of the error and a hex version
+//
+// Effects:
+//
+// Arguments: [dwError] - the error which we are looking up
+//
+// Requires:
+//
+// Returns: character array
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpWIN32Error(DWORD dwError)
+{
+ HRESULT hresult;
+
+ hresult = HRESULT_FROM_WIN32(dwError);
+
+ return DumpHRESULT(hresult);
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCACHELIST_ITEM, public (_DEBUG only)
+//
+// Synopsis: returns a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [pCLI] - a pointer to a CACHELIST_ITEM object
+// [ulFlag] - a flag determining the prefix of all newlines of
+// the out character array(default is 0 -no prefix)
+// [nIndentLevel] - will add an indent prefix after the other prefix
+// for all newlines(include those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCACHELIST_ITEM(CACHELIST_ITEM *pCLI, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszDump;
+ char *pszCCacheNode;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(1500);
+
+ if (pCLI == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ // determine prefix
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << pCLI << " _VB ";
+ }
+
+ // determine indentation prefix
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "Cache Node ID = " << pCLI->dwCacheId << endl;
+
+ if (pCLI->lpCacheNode != NULL)
+ {
+ pszCCacheNode = DumpCCacheNode(pCLI->lpCacheNode, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "Cache Node:" << endl;
+ dstrDump << pszCCacheNode;
+ CoTaskMemFree(pszCCacheNode);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "lpCacheNode = " << pCLI->lpCacheNode << endl;
+ }
+
+ // cleanup and provide pointer to character array
+ pszDump = dstrDump.str();
+
+ if (pszDump == NULL)
+ {
+ pszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCMapDwordDword, public (_DEBUG only)
+//
+// Synopsis: not implemented
+//
+// Effects:
+//
+// Arguments: [pMDD] - pointer to a CMapDwordDword
+//
+// Requires:
+//
+// Returns: character array
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCMapDwordDword(CMapDwordDword *pMDD, ULONG ulFlag, int nIndentLevel)
+{
+ return UtDupStringA(" DumpCMapDwordDword is not implemented\n");
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpFORMATETC, public (_DEBUG only)
+//
+// Synopsis: returns a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [pFE] - a pointer to a FORMATETC object
+// [ulFlag] - a flag determining the prefix of all newlines of
+// the out character array(default is 0 -no prefix)
+// [nIndentLevel] - will add an indent prefix after the other prefix
+// for all newlines(include those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpFORMATETC(FORMATETC *pFE, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszDump;
+ char *pszClipFormat;
+ char *pszDVASPECT;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump;
+
+ if (pFE == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ // determine prefix
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << pFE << " _VB ";
+ }
+
+ // determine indentation prefix
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ pszClipFormat = DumpCLIPFORMAT(pFE->cfFormat);
+ dstrDump << pszPrefix << "CLIPFORMAT = " << pszClipFormat << endl;
+ CoTaskMemFree(pszClipFormat);
+
+ dstrDump << pszPrefix << "pDVTARGETDEVICE = " << pFE->ptd << endl;
+
+ pszDVASPECT = DumpDVASPECTFlags(pFE->dwAspect);
+ dstrDump << pszPrefix << "Aspect Flags = " << pszDVASPECT << endl;
+ CoTaskMemFree(pszDVASPECT);
+
+ dstrDump << pszPrefix << "Tymed Flags = ";
+ if (pFE->tymed & TYMED_HGLOBAL)
+ {
+ dstrDump << "TYMED_HGLOBAL ";
+ }
+ if (pFE->tymed & TYMED_FILE)
+ {
+ dstrDump << "TYMED_FILE ";
+ }
+ if (pFE->tymed & TYMED_ISTREAM)
+ {
+ dstrDump << "TYMED_ISTREAM ";
+ }
+ if (pFE->tymed & TYMED_ISTORAGE)
+ {
+ dstrDump << "TYMED_ISTORAGE ";
+ }
+ if (pFE->tymed & TYMED_GDI)
+ {
+ dstrDump << "TYMED_GDI ";
+ }
+ if (pFE->tymed & TYMED_MFPICT)
+ {
+ dstrDump << "TYMED_MFPICT ";
+ }
+ if (pFE->tymed & TYMED_ENHMF)
+ {
+ dstrDump << "TYMED_ENHMF ";
+ }
+ if (pFE->tymed == TYMED_NULL)
+ {
+ dstrDump << "TYMED_NULL ";
+ }
+ // if none of the flags are set there is an error
+ if ( !( (pFE->tymed & TYMED_HGLOBAL ) |
+ (pFE->tymed & TYMED_FILE ) |
+ (pFE->tymed & TYMED_ISTREAM ) |
+ (pFE->tymed & TYMED_ISTORAGE ) |
+ (pFE->tymed & TYMED_GDI ) |
+ (pFE->tymed & TYMED_MFPICT ) |
+ (pFE->tymed & TYMED_ENHMF ) |
+ (pFE->tymed == TYMED_NULL )))
+ {
+ dstrDump << "Error in FLAG!!!! ";
+ }
+ dstrDump << "(" << (void *)pFE->tymed << ")" << endl;
+
+ // cleanup and provide pointer to character array
+ pszDump = dstrDump.str();
+
+ if (pszDump == NULL)
+ {
+ pszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpIOlePresObj, public (_DEBUG only)
+//
+// Synopsis: calls the IOlePresObj::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pOPO] - pointer to IOlePresObj
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 31-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpIOlePresObj(IOlePresObj *pOPO, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pOPO == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ // defers to CMfObject, CEMfObject, CGenObject
+ hresult = pOPO->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpMEMSTM, public (_DEBUG only)
+//
+// Synopsis: returns a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [pMS] - a pointer to a MEMSTM object
+// [ulFlag] - a flag determining the prefix of all newlines of
+// the out character array(default is 0 -no prefix)
+// [nIndentLevel] - will add an indent prefix after the other prefix
+// for all newlines(include those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpMEMSTM(MEMSTM *pMS, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszDump;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump;
+
+ if (pMS == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ // determine prefix
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << pMS << " _VB ";
+ }
+
+ // determine indentation prefix
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "Size of Global Memory = " << pMS->cb << endl;
+ dstrDump << pszPrefix << "References = " << pMS->cRef << endl;
+ dstrDump << pszPrefix << "hGlobal = " << pMS->hGlobal << endl;
+ dstrDump << pszPrefix << "DeleteOnRelease? = ";
+ if (pMS->fDeleteOnRelease == TRUE)
+ {
+ dstrDump << "TRUE" << endl;
+ }
+ else
+ {
+ dstrDump << "FALSE" << endl;
+ }
+
+ // cleanup and provide pointer to character array
+ pszDump = dstrDump.str();
+
+ if (pszDump == NULL)
+ {
+ pszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpSTATDATA, public (_DEBUG only)
+//
+// Synopsis: returns a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [pSD] - a pointer to a STATDATA object
+// [ulFlag] - a flag determining the prefix of all newlines of
+// the out character array(default is 0 -no prefix)
+// [nIndentLevel] - will add an indent prefix after the other prefix
+// for all newlines(include those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpSTATDATA(STATDATA *pSD, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszDump;
+ char *pszFORMATETC;
+ char *pszADVF;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(500);
+
+ if (pSD == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ // determine prefix
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << pSD << " _VB ";
+ }
+
+ // determine indentation prefix
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ pszFORMATETC = DumpFORMATETC( &(pSD->formatetc), ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "FORMATETC:" << endl;
+ dstrDump << pszFORMATETC;
+ CoTaskMemFree(pszFORMATETC);
+
+ pszADVF = DumpADVFFlags( pSD->advf );
+ dstrDump << pszPrefix << "Advise flag = " << pszADVF << endl;
+ CoTaskMemFree(pszADVF);
+
+ dstrDump << pszPrefix << "pIAdviseSink = " << pSD->pAdvSink << endl;
+
+ dstrDump << pszPrefix << "Connection ID = " << pSD->dwConnection << endl;
+
+ // cleanup and provide pointer to character array
+ pszDump = dstrDump.str();
+
+ if (pszDump == NULL)
+ {
+ pszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpSTGMEDIUM, public (_DEBUG only)
+//
+// Synopsis: returns a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [pFE] - a pointer to a STGMEDIUM object
+// [ulFlag] - a flag determining the prefix of all newlines of
+// the out character array(default is 0 -no prefix)
+// [nIndentLevel] - will add an indent prefix after the other prefix
+// for all newlines(include those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpSTGMEDIUM(STGMEDIUM *pSM, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszDump;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump;
+
+ if (pSM == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ // determine prefix
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << pSM << " _VB ";
+ }
+
+ // determine indentation prefix
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "Tymed Flags = ";
+ if (pSM->tymed & TYMED_HGLOBAL)
+ {
+ dstrDump << "TYMED_HGLOBAL ";
+ }
+ if (pSM->tymed & TYMED_FILE)
+ {
+ dstrDump << "TYMED_FILE ";
+ }
+ if (pSM->tymed & TYMED_ISTREAM)
+ {
+ dstrDump << "TYMED_ISTREAM ";
+ }
+ if (pSM->tymed & TYMED_ISTORAGE)
+ {
+ dstrDump << "TYMED_ISTORAGE ";
+ }
+ if (pSM->tymed & TYMED_GDI)
+ {
+ dstrDump << "TYMED_GDI ";
+ }
+ if (pSM->tymed & TYMED_MFPICT)
+ {
+ dstrDump << "TYMED_MFPICT ";
+ }
+ if (pSM->tymed & TYMED_ENHMF)
+ {
+ dstrDump << "TYMED_ENHMF ";
+ }
+ if (pSM->tymed == TYMED_NULL)
+ {
+ dstrDump << "TYMED_NULL ";
+ }
+ // if none of the flags are set there is an error
+ if ( !( (pSM->tymed & TYMED_HGLOBAL ) |
+ (pSM->tymed & TYMED_FILE ) |
+ (pSM->tymed & TYMED_ISTREAM ) |
+ (pSM->tymed & TYMED_ISTORAGE ) |
+ (pSM->tymed & TYMED_GDI ) |
+ (pSM->tymed & TYMED_MFPICT ) |
+ (pSM->tymed & TYMED_ENHMF ) |
+ (pSM->tymed == TYMED_NULL )))
+ {
+ dstrDump << "Error in FLAG!!!! ";
+ }
+ dstrDump << "(" << (void *)pSM->tymed << ")" << endl;
+
+ dstrDump << pszPrefix << "Union (handle or pointer) = " << pSM->hBitmap << endl;
+
+ dstrDump << pszPrefix << "pIUnknown for Release = " << pSM->pUnkForRelease << endl;
+
+ // cleanup and provide pointer to character array
+ pszDump = dstrDump.str();
+
+ if (pszDump == NULL)
+ {
+ pszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
diff --git a/private/ole32/ole232/debug/debapi.cxx b/private/ole32/ole232/debug/debapi.cxx
new file mode 100644
index 000000000..314cd0fbc
--- /dev/null
+++ b/private/ole32/ole232/debug/debapi.cxx
@@ -0,0 +1,26 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: DebAPI.CXX
+//
+// Contents: Debugging API's
+//
+// Classes:
+//
+// Functions:
+//
+// History: 29-Nov-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+
+#if DBG==1
+
+#include <debnot.h>
+
+DECLARE_INFOLEVEL(LE)
+
+#endif // DBG==1
diff --git a/private/ole32/ole232/debug/depend.mk b/private/ole32/ole232/debug/depend.mk
new file mode 100644
index 000000000..28d84c74c
--- /dev/null
+++ b/private/ole32/ole232/debug/depend.mk
@@ -0,0 +1,39 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\debapi.obj $(OBJDIR)\debapi.lst: .\debapi.cxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\ctype.h $(CRTINC)\string.h $(OSINC)\windef.h \
+ $(OSINC)\winnt.h
+
+$(OBJDIR)\cdebug.obj $(OBJDIR)\cdebug.lst: .\cdebug.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\olerem.h $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(CAIROLE)\ole232\inc\toolhelp.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\wchar.h \
+ $(CRTINC)\ctype.h $(CRTINC)\string.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\widewrap.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h $(OSINC)\windef.h \
+ $(OSINC)\winnt.h
+
diff --git a/private/ole32/ole232/debug/dirs b/private/ole32/ole232/debug/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/ole232/debug/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/ole232/debug/dstream.cpp b/private/ole32/ole232/debug/dstream.cpp
new file mode 100644
index 000000000..df3a48699
--- /dev/null
+++ b/private/ole32/ole232/debug/dstream.cpp
@@ -0,0 +1,758 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dstream.cpp
+//
+// Contents: internal debugging support (debug stream which builds a string)
+//
+// Classes: dbgstream implementation
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 09-Feb-95 t-ScottH author
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#include <stdio.h>
+#include "dstream.h"
+
+//+-------------------------------------------------------------------------
+//
+// Member: dbgstream, public (_DEBUG only)
+//
+// Synopsis: constructor
+//
+// Effects: initializes and allocates buffer
+//
+// Arguments: [dwSize] - size of initial buffer to allocate
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+dbgstream::dbgstream(DWORD dwSize)
+{
+ init();
+ allocate(dwSize);
+ if (m_dwBufSize)
+ {
+ m_pszBuf[0] = '\0';
+ }
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: dbgstream, public (_DEBUG only)
+//
+// Synopsis: constructor
+//
+// Effects: initializes and allocates buffer
+//
+// Arguments:
+//
+// Requires: DEFAULT_INITAL_ALLOC
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+// allocate the buffer with the default initial size
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+dbgstream::dbgstream()
+{
+ init();
+ allocate(DEFAULT_INITIAL_ALLOC);
+ if (m_dwBufSize)
+ {
+ m_pszBuf[0] = '\0';
+ }
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: ~dbgstream, public (_DEBUG only)
+//
+// Synopsis: destructor
+//
+// Effects: frees the string if m_fFrozen == FALSE
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies: frees the character array
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+// we only want to free the string if it has not been passed off externally
+// using the str() method
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+dbgstream::~dbgstream()
+{
+ if (m_fFrozen == FALSE)
+ {
+ free();
+ }
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: init, private (_DEBUG only)
+//
+// Synopsis: initializes the data members
+//
+// Effects: initializes radix to DEFAULT_RADIX,
+// precision to DEFAULT_PRECISION decimal places
+//
+// Arguments:
+//
+// Requires: DEFAULT_RADIX, DEFAULT_PRECISION
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+void dbgstream::init()
+{
+ m_dwIndex = 0;
+ m_dwBufSize = 0;
+ m_fFrozen = FALSE;
+ m_radix = DEFAULT_RADIX;
+ m_precision = DEFAULT_PRECISION;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: allocate, private (_DEBUG only)
+//
+// Synopsis: allocate the buffer
+//
+// Effects: if allocates fail, freeze the buffer
+//
+// Arguments: [dwSize] - size of buffer to allocate (in bytes)
+//
+// Requires: CoTaskMemRealloc
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+void dbgstream::allocate(DWORD dwSize)
+{
+ m_pszBuf = (char *)CoTaskMemAlloc(dwSize);
+
+ if (m_pszBuf == NULL)
+ {
+ m_fFrozen = TRUE;
+ }
+ else
+ {
+ m_dwBufSize = dwSize;
+ }
+
+ return;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: free, private (_DEBUG only)
+//
+// Synopsis: frees the buffer (resets index and max size)
+//
+// Effects:
+//
+// Arguments: none
+//
+// Requires: CoTaskMemFree
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+void dbgstream::free()
+{
+ CoTaskMemFree(m_pszBuf);
+ m_dwIndex = 0;
+ m_dwBufSize = 0;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: reallocate, private (_DEBUG only)
+//
+// Synopsis: reallocates the buffer (keeps data intact), depending on
+// current size this method will choose a growby size
+//
+// Effects:
+//
+// Arguments: none
+//
+// Requires: CoTaskMemRealloc, DEFAULT_GROWBY, DEFAULT_INITIAL_ALLOC
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+// tried to make reallocation more efficient based upon current size
+// (I don't know any of the mathematical theory :-)
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+void dbgstream::reallocate()
+{
+ if (m_dwBufSize < (DEFAULT_INITIAL_ALLOC * 2))
+ {
+ reallocate(DEFAULT_GROWBY);
+ }
+ else
+ {
+ reallocate(m_dwBufSize/2);
+ }
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: reallocate, private (_DEBUG only)
+//
+// Synopsis: reallocate the buffer (keep data intact)
+//
+// Effects: if reallocation fails, freeze the buffer
+//
+// Arguments: [dwSize] - amount to grow buffer by
+//
+// Requires: CoTaskMemRealloc
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+// new buffer size = m_dwBufSize + dwSize
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+void dbgstream::reallocate(DWORD dwSize)
+{
+ char *pszBuf;
+
+ Assert(dwSize > 0);
+
+ pszBuf = (char *)CoTaskMemRealloc(m_pszBuf, m_dwBufSize + dwSize);
+
+ if (pszBuf != NULL)
+ {
+ m_pszBuf = pszBuf;
+ m_dwBufSize += dwSize;
+ }
+ else
+ {
+ m_fFrozen = TRUE;
+ }
+
+ return;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: freeze, public (_DEBUG only)
+//
+// Synopsis: freeze the buffer by throwing the flag
+//
+// Effects:
+//
+// Arguments: none
+//
+// Requires:
+//
+// Returns: BOOL - whether buffer was frozen (we are alway successful)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+BOOL dbgstream::freeze()
+{
+ m_fFrozen = TRUE;
+ return TRUE;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: unfreeze, public (_DEBUG only)
+//
+// Synopsis: unfreeze the buffer
+//
+// Effects: if buffer size = 0, allocate the buffer
+//
+// Arguments: none
+//
+// Requires:
+//
+// Returns: BOOL - whether successful
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+// buffer may be frozen if no memory, so try to allocate buffer if NULL
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+BOOL dbgstream::unfreeze()
+{
+ if (m_pszBuf == NULL)
+ {
+ allocate(DEFAULT_INITIAL_ALLOC);
+ if (m_pszBuf == NULL)
+ {
+ return FALSE;
+ }
+ }
+ m_fFrozen = FALSE;
+
+ return TRUE;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: str, public (_DEBUG only)
+//
+// Synopsis: passes the string externally
+//
+// Effects: freezes buffer until unfreeze method is called
+//
+// Arguments: none
+//
+// Requires:
+//
+// Returns: char * - buffer
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char * dbgstream::str()
+{
+ m_fFrozen = TRUE;
+ return m_pszBuf;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: overloaded operator<<(int), public (_DEBUG only)
+//
+// Synopsis: put int into stream (store in character buffer)
+//
+// Effects:
+//
+// Arguments: [i] - integer to put in stream
+//
+// Requires: _itoa
+//
+// Returns: reference to dbgstream (current object)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+dbgstream& dbgstream::operator<<(int i)
+{
+ // _itoa - fills up to 17 bytes
+ char szBuffer[20];
+
+ if (m_fFrozen == FALSE)
+ {
+ _itoa(i, szBuffer, m_radix);
+ return (operator<<(szBuffer));
+ }
+ return *this;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: overloaded operator<<(long), public (_DEBUG only)
+//
+// Synopsis: put long into stream (store in character buffer)
+//
+// Effects:
+//
+// Arguments: [l] - long to put in stream
+//
+// Requires: _ltoa
+//
+// Returns: reference to dbgstream (current object)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+dbgstream& dbgstream::operator<<(long l)
+{
+ // _ltoa - up to 33 bytes
+ char szBuffer[35];
+
+ if (m_fFrozen == FALSE)
+ {
+ _ltoa(l, szBuffer, m_radix);
+ return (operator<<(szBuffer));
+ }
+ return *this;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: overloaded operator<<(unsigned long), public (_DEBUG only)
+//
+// Synopsis: put unsigned long into stream (store in character buffer)
+//
+// Effects:
+//
+// Arguments: [ul] - long to put in stream
+//
+// Requires: _ultoa
+//
+// Returns: reference to dbgstream (current object)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+dbgstream& dbgstream::operator<<(unsigned long ul)
+{
+ // _ltoa - up to 33 bytes
+ char szBuffer[35];
+
+ if (m_fFrozen == FALSE)
+ {
+ _ultoa(ul, szBuffer, m_radix);
+ return (operator<<(szBuffer));
+ }
+ return *this;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: overloaded operator<<(const void *), public (_DEBUG only)
+//
+// Synopsis: put const void* into stream (store in character buffer)
+//
+// Effects: all pointers are inherently void*
+//
+// Arguments: [p] - void * to put in stream
+//
+// Requires: wsprintf
+//
+// Returns: reference to dbgstream (current object)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+// wsprintf not most efficient, but easy for formatting
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+dbgstream& dbgstream::operator<<(const void *p)
+{
+ char szBuffer[15];
+ int i;
+
+ if (m_fFrozen == FALSE)
+ {
+ wsprintfA(szBuffer, "0x%08x", p);
+ return (operator<<(szBuffer));
+ }
+ return *this;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: overloaded operator<<(const char *), public (_DEBUG only)
+//
+// Synopsis: put const char* into stream (store in character buffer)
+//
+// Effects:
+//
+// Arguments: [psz] - const char * to put in stream
+//
+// Requires:
+//
+// Returns: reference to dbgstream (current object)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+dbgstream& dbgstream::operator<<(const char *psz)
+{
+ int i;
+
+ // only if string is not frozen
+ if (m_fFrozen == FALSE)
+ {
+ for (i = 0; psz[i] != '\0'; i++)
+ {
+ if ((m_dwIndex + i) >= (m_dwBufSize - 2))
+ {
+ // if reallocate fails m_fFrozen is TRUE
+ reallocate();
+ if (m_fFrozen == TRUE)
+ {
+ return *this;
+ }
+ }
+ m_pszBuf[m_dwIndex + i] = psz[i];
+ }
+ // ensure that always null terminated string
+ m_pszBuf[m_dwIndex + i] = '\0';
+ m_dwIndex += i;
+ }
+ return *this;
+}
+
+#endif // _DEBUG
diff --git a/private/ole32/ole232/debug/filelist.mk b/private/ole32/ole232/debug/filelist.mk
new file mode 100644
index 000000000..7b8870a46
--- /dev/null
+++ b/private/ole32/ole232/debug/filelist.mk
@@ -0,0 +1,53 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = debug.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CPPFILES = .\cdebug.cpp
+
+CXXFILES = \
+!if "$(BUILDTYPE)" == "DEBUG"
+ .\debapi.cxx
+!endif
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PFILE =
+
+
+!include $(CAIROLE)\ole232\ole.mk
diff --git a/private/ole32/ole232/debug/makefile b/private/ole32/ole232/debug/makefile
new file mode 100644
index 000000000..1725b5e9a
--- /dev/null
+++ b/private/ole32/ole232/debug/makefile
@@ -0,0 +1,26 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1992.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/ole232/dirs b/private/ole32/ole232/dirs
new file mode 100644
index 000000000..c92327129
--- /dev/null
+++ b/private/ole32/ole232/dirs
@@ -0,0 +1,46 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS= \
+ inc \
+ advise \
+ base \
+ cache \
+ clipbrd \
+ debug \
+ drag \
+ inplace \
+ stdimpl \
+ ole1 \
+ util
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS=
diff --git a/private/ole32/ole232/doc/autolink.txt b/private/ole32/ole232/doc/autolink.txt
new file mode 100644
index 000000000..33a77f02d
--- /dev/null
+++ b/private/ole32/ole232/doc/autolink.txt
@@ -0,0 +1,154 @@
+From: Douglas Hodges
+To: Alexander Gounares
+Subject: possible change for next OLE version.
+Date: Tuesday, November 02, 1993 12:16PM
+
+a suggestion for consideration.
+
+doug
+----------
+From: Rao Remala
+To: Bob Atkinson; Craig Wittenberg; Tony Williams
+Cc: Douglas Hodges
+Subject: RE: Autoconversion of links
+Date: Thursday, September 23, 1993 3:08PM
+
+Thanks for the info and help! No changes now and Publisher is out of luck
+--rao
+
+----------
+|From: Bob Atkinson
+|To: Craig Wittenberg; Rao Remala; Tony Williams
+|Cc: Douglas Hodges
+|Subject: RE: Autoconversion of links
+|Date: Thursday, September 23, 1993 10:36AM
+|
+|I agree with Doug.
+|
+|If the class is different, then we cannot *automatically* go
+|ahead, in any of our (present) APIs, as we have no idea as to
+|what action the action the caller took based in the erroneous
+|information we gave him. We must give the opportunity to the
+|piece of code that took action on the erroneous info the
+|opportunity to do something different based on the new
+|information, as only it knows what it did.
+|
+|Doug's suggestion makes it easy for an app to write a simple
+|helper function that ignores certain changes while deals with
+|others. Hopefully it would be easy for us; it seems so.
+|
+|One might ask whether we should put such a new helper function
+|in our libraries. I believe I am against that: 1) it's a new
+|OLE api, and 2) I really want applications to be conscious of
+|the fact that this change can happen.
+|
+| Bob
+|----------
+|| From: Douglas Hodges
+|| To: Bob Atkinson; Craig Wittenberg; Rao Remala; Tony Williams
+|| Subject: RE: Autoconversion of links
+|| Date: Thursday, September 23, 1993 10:08AM
+|| Priority: High
+||
+|| unfortunately i don't think it is correct to do this. i don't
+|| think there is anything we can do for shipping apps (or soon
+|| to be shipped apps) that don't do this correctly.
+||
+|| we need to have apps handle the OLE_E_CLASSDIFF situation
+|| correctly. but our problem is that we don't really have our
+|| whole story straight as to how this is to be handled.
+|| currently we recommend that if the OLE_E_CLASSDIFF error comes
+|| then the app should simply call IOleLink::BindLinkSource with
+|| the flag OLELINK_EVENIFCLASSDIFF. this is correct ONLY if both
+|| the old class and the new class use OLE's DefLink. if either
+|| class uses a custom link, then in fact the link must be
+|| recreated.
+||
+|| we need to give a different error code from OleRun when in
+|| fact it is required to re-create the link (ie. re-binding with
+|| OLELINK_EVENIFCLASSDIFF is not good enough).
+||
+|| suggestion: OLE_E_CLASSDIFFMUSTRECREATELINK
+|| this scode should be returned instead of OLE_E_CLASSDIFF if
+|| either the old or new class uses a custom link handler (there
+|| is REGDB info that tells us if a class uses a custom link).
+||
+|| currently the OUTLINE sample apps handle the OLE_E_CLASSDIFF
+|| error by re-creating the link in all situations because this
+|| always works. it is a lot of overhead and is a lot more
+|| complicated than simply re-binding with the
+|| OLELINK_EVENIFCLASSDIFF flag. if we had the two error codes
+|| then, the OUTLINE sample code code be easily modified to
+|| handle both cases. i can imagine that if we add the new error
+|| code, that some apps could choose to handle the
+|| OLE_E_CLASSDIFF case and simply fail to ever bind a link that
+|| is in the OLE_E_CLASSDIFFMUSTRECREATE case.
+||
+|| doug
+|| ----------
+|| |From: Rao Remala
+|| |To: Douglas Hodges
+|| |Subject: FW: Autoconversion of links
+|| |Date: Wednesday, September 22, 1993 5:20PM
+|| |Priority: High
+|| |
+|| |
+|| |----------
+|| |From: B. Ashok
+|| |To: Rao Remala; Srini Koppolu
+|| |Cc: Paul Klemond
+|| |Subject: FW: Autoconversion of links
+|| |Date: Wednesday, September 22, 1993 5:06PM
+|| |Priority: High
+|| |
+|| |
+|| |I tried changing the bindflags to OLELINK_EVENIFCLASSDIFF under
+|| |the debugger and autoconversion of links works just fine. I'm
+|| |convinced that this should be the default behavior when OleRun
+|| |is called. Otherwise, there seems to be no way to autoconvert
+|| |a link correctly without breaking some containers.
+|| |
+|| |-- Bash
+|| |
+|| |----------
+|| |From: bash
+|| |To: natbro; paulkle; phaniv; raor; seanch; srinik; vikramn
+|| |Cc: bash
+|| |Subject: Autoconversion of links
+|| |Date: Wednesday, September 22, 1993 4:40PM
+|| |Priority: High
+|| |
+|| |
+|| |I ran across the following problem while debugging
+|| |autoconversion of works 2.0 objects and it seems like a fairly
+|| |serious one from the user's point of view.
+|| |We do autoconversion of works 2.0 objects to works 3.0 and
+|| |everything works fine from a 1.0 container. However we have
+|| |the following problem with Publisher 2.0 (and with other ole
+|| |2.0 containers that call OleRun to activate links):
+|| |
+|| |Let's say Pub 2.0 had a linked works 2.0 object in it. When we
+|| |try to activate this, Pub 2.0 calls OleRun, which ends up
+|| |returning OLE_E_CLASSDIFF since the clsids are indeed
+|| |different. The only workaround that I know of at present is to
+|| |have the container call BindToSource with
+|| |OLELINK_EVENIFCLASSDIFF which of course it is too late to do
+|| |since there exist shipped apps like Pub 2.0 out there which
+|| |call OleRun to activate links... (FYI, the Works WP and DB do
+|| |the same thing too). My question is this: is it possible to
+|| |make OLELINK_EVENIFCLASSDIFF as the default behavior when
+|| |OleRun is called ? Or is there anything at all we can do on
+|| |the server side (reg.dat or any other hack) to get
+|| |autoconversion of links to work ?
+|| |
+|| |Thanks for any info.
+|| |
+|| |-- Bash
+|| |
+|| |
+|| |
+||
+||
+|
+
+
diff --git a/private/ole32/ole232/doc/olesize.txt b/private/ole32/ole232/doc/olesize.txt
new file mode 100644
index 000000000..e7d6d73d7
--- /dev/null
+++ b/private/ole32/ole232/doc/olesize.txt
@@ -0,0 +1,94 @@
+Size of the ole dll (Intel)
+
+
+10/31. Original build
+
+ Summary 1C000 (text+bss+data) == 114,688
+
+ .text 1A800
+ .bss 600
+ .rdata A00
+ .edata C00
+ .data 1200
+ .rsrc 1600
+ .idata 1600
+ .CRT 200
+ .reloc C00
+ .debug 12D76B
+
+11/2/93 Removed some MFC stuff in the advises
+
+
+ Summary 1CE00 == 118,272
+
+ .text 1B200
+ .bss 600
+ .rdata A00
+ .edata C00
+ .data 1600
+ .rsrc 1600
+ .idata 1600
+ .CRT 200
+ .reloc E00
+ .debug 13D8D0
+
+11/11/93 Cache nodes improved, first working dll
+
+ Summary 1C400 == 115,712
+
+ .text 1A800
+ .bss 600
+ .rdata A00
+ .edata C00
+ .data 1600
+ .rsrc 1600
+ .idata 1600
+ .reloc E00
+ .debug 138C63
+
+11/29/93 Cache nodes finished, minor improvements to the default
+ class factory implementation. Lots of bug fixes.
+
+
+
+ Summary 1C600 == 116,224
+
+ .text 1A800
+ .bss 600
+ .rdata A00
+ .edata C00
+ .data 1800
+ .rsrc 1600
+ .idata 1600
+ .reloc E00
+ .debug 139EB5
+
+12/7/93 Inplace inlining removed, MemStm::CopyTo added
+
+
+ Summary 1C000 == 114,688
+
+ .text 1A800
+ .bss 200
+ .rdata A00
+ .edata C00
+ .data 1600
+ .rsrc 1600
+ .idata 1600
+ .reloc E00
+ .debug 13905B
+
+01/12/94 RPC drag drop, clipboard, and linking functional
+
+
+ Summary 1A800 == 108,544
+
+ .text 19A00
+ .bss 200
+ .rdata 1600
+ .edata C00
+ .data C00
+ .rsrc 1600
+ .idata 1600
+ .reloc E00
+ .debug 13751A
diff --git a/private/ole32/ole232/doc/preraid.txt b/private/ole32/ole232/doc/preraid.txt
new file mode 100644
index 000000000..8eb30d3e2
--- /dev/null
+++ b/private/ole32/ole232/doc/preraid.txt
@@ -0,0 +1,87 @@
+preraid.txt
+
+This file contains general notes for the ole2w32.dll project. These items
+should all be entered into our raid database once that is established.
+
+
+1. alexgo -- api.cpp contains a lot of seemingly redundant api's, such
+ as OleNoteObjectVisible and OleSetContainedObject, which do nothing
+ but call CoLockObjectExternal. We ought to think about replacing these
+ with #define's.
+
+2. alexgo -- there are *16* api's in api.cpp which all do basically the
+ same thing, reading and writing private OLE info into a special stream
+ in a storage. There is a lot of duplicate code between these functions;
+ with a little bit of thought, we can clean this up significantly.
+
+ Some of these (such as GetDocumentBitStg) don't even seem to be used
+ by anyone.
+
+3. alexgo -- fix writing ANSI strings to streams to write an ansi version
+ to the 16bit named private stream (OLE_STREAM, COMPOBJ_STREAM) and
+ write a duplicate unicode string to a 32bit private stream. Be sure
+ to maintain consistent state across the two stream/strings
+
+4. alexgo -- fix autoconversion of links. We need to return a new
+ error code OLE_E_CLASSDIFFMUSTRECREATELINK to handle the case of
+ custom links and modify the sample code to deal with this appropriately.
+ See the file autolink.txt for a more thorough discussion of this issue.
+
+5. alexgo -- fix the drawing of icons and labels. The code (icon.cpp)
+ currently assumes English language with an ANSI character set.
+
+6. DONE: alexgo -- the OleReg functions (in olereg.cpp and elsewhere) need to
+ be updated to the new 32bit standard. The following note from ShannonC
+ gives more details.
+
+
+From: Shannon Chan
+To: Object Oriented Interfaces,Methods&API's
+Subject: FINAL: Registry conflicts between 16 bit OLE2 and 32 bit OLE2
+Date: Friday, December 03, 1993 11:19AM
+
+Last month, I sent out a proposal on how to resolve the registry
+conflicts between 16 bit OLE 2 and 32
+bit OLE 2. There were no objections. This message describes the
+final resolution of this issue.
+
+Conflicting registry entries currently prevent the installation of 16
+bit OLE 2 and 32 bit OLE 2 applications on the same machine. The 16
+bit applications require 16 bit DLLs. The 32 bit applications
+require 32 bit DLLs. The problem is that the same registry entries
+are used to register both 16 bit DLLs and 32 bit DLLs. The solution
+to this problem is to define new registry entries for 32 bit OLE 2.
+
+16 bit OLE 2 will continue to use the existing registry keys:
+InProcServer - Registers a 16 bit in-process server DLL.
+InProcHandler - Registers a 16 bit handler DLL.
+ProxyStubClsid - Maps an IID to a CLSID in a 16 bit proxy DLL.
+
+32 bit OLE 2 will use new registry keys:
+InProcServer32 - Registers a 32 bit in-process server DLL.
+InProcHandler32 - Registers a 32 bit handler DLL.
+ProxyStubClsid32 - Maps an IID to a CLSID in a 32 bit proxy DLL.
+
+Some people asked why we need ProxyStubClsid32. We need
+ProxyStubClsid32 because the IID to CLSID mapping may be different
+for 16 bit interfaces and 32 bit interfaces. The IID to CLSID
+mapping depends on how we package the interface proxies into a set of
+proxy DLLs.
+
+ShannonC
+
+
+7. alexgo -- need to replace all memory allocations with the debug versions
+ for resource tracking. See alext's mail.
+
+8. DONE (partially) alexgo -- need to put in call tracing stuff (LEDebugOut).
+
+9. alexgo -- optimization. The defhandler makes many many calls to IsRunning.
+ We may be able to make IsRunning faster or perhaps analyze our code paths
+ and reduce the number of calls to it.
+
+10. alexgo -- the OleConvert api's in the ole1 directory need to be
+ implemented (currently, they are just stubbed).
+
+11. alexgo -- the test harness should ensure that structures (such as
+ FORMATETC) are packed ala MS C style /Zp8 packing.
diff --git a/private/ole32/ole232/doc/tracegrm.txt b/private/ole32/ole232/doc/tracegrm.txt
new file mode 100644
index 000000000..a1fbace5d
--- /dev/null
+++ b/private/ole32/ole232/doc/tracegrm.txt
@@ -0,0 +1,137 @@
+ Linking and Embedding Call Tracing
+
+Alex Gounares (alexgo), 12/15/93
+
+
+------------------------------
+
+NB: All call tracing added to the L&E layers of OLE *must*
+conform to this spec; post processing tools may break otherwise.
+
+Syntax of this grammar:
+ non-terminals are bracketed with underscores (e.g. _foo_)
+ Other tokens are literally or as described
+
+General:
+
+ Call logging should be done via the LEDebugOut macro, which
+ takes the following parameters:
+
+ LEDebugOut(( _type_ , _formatstring_ , _arguments));
+
+ _type_ : DEB_TRACE
+ | DEB_ITRACE
+ ;
+
+ DEB_TRACE should be used for any API or method *directly*
+ reachable by an OLE app.
+
+ DEB_ITRACE should be used for all internal APIs and
+ methods.
+
+ In some circumstances (an important internal function),
+ it is permissible to use DEB_TRACE for internal functions
+ and methods, but this is discouraged.
+
+ _arguments_ : whatever is needed by _formatstring_
+
+ There are three _formatstring_ formats currently supported,
+ one for function entrance, another for function exit, and
+ a third for object deletion. More formats may be added
+ as needed, so tools must be prepared to ignore
+ non-conforming strings (as it may be a new format for a new
+ tool).
+
+ _formatstring_ : _in_
+ | _out_
+ | _delete_
+ ;
+
+Function entrance: // _IN is literal
+
+ _in_ : "_this_ _IN _name_ _args_ _extra_ \n"
+ ;
+
+ _this_ : %p
+ //should be passed the pointer
+ //to the *top* level object in
+ //the class (if the this pointer
+ //points to a nested class)
+ //If a function, then 0 should be
+ //passed.
+ ;
+
+ _name_ : // the complete name of the function
+ // or method (i.e. CFoo::CBar::Blah)
+
+ _args_ : ( )
+ | ( _arglist_ )
+ ;
+
+ _arglist_ : _arglist_ , _arg_
+ | _arg_
+ ;
+
+ _arg_ : _string_
+ | _integral_
+ ;
+
+ _string_ : \"%s\"
+ | \"%ws\"
+ ;
+
+ _integral_ : any printf conversion string
+ other than strings (see NOTES)
+
+ _extra_ : an arbitrary number of bytes
+ with no newline character
+
+Function exit:
+
+ _out_ : "_this_ OUT _name_ _return_ _outparams_ _extra_ \n"
+ ;
+
+ _return_ : ( _arg_ )
+ ;
+
+ _outparams_ : [ _arglist_ ] // used to put the
+ | // values of the
+ ; // out parameters
+
+
+Object Deletion:
+
+ _delete_ : "_this_ DELETED _extra_ \n"
+ ;
+
+
+
+NOTES:
+
+ 1. The newline does not need to be preceeded by a space.
+ Other spaces in the grammar are intentional (the
+ space character is the token delimiter)
+
+ 2. Tools should ignore any extra bytes after the known
+ fields to be compatible with future revs of the
+ logging.
+
+ 3. In general, the following conversion codes are used
+ for the following data types. These are not binding,
+ however, individual functions/methods may do
+ something different as appropriate.
+
+ HRESULT %lx
+ pointer %p
+ DWORD %lu
+ DWORD(bitflags) %lx
+ ULONG %lu
+ LONG %ld
+ REFGUID %p
+
+ 4. For in/out params, in may be awkward to print
+ the out value (since it may be a long piece of
+ memory). In this case, just printing the pointer
+ value (although the same as the argument) is
+ sufficient.
+
diff --git a/private/ole32/ole232/drag/daytona/makefile b/private/ole32/ole232/drag/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/ole232/drag/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/ole232/drag/daytona/sources b/private/ole32/ole232/drag/daytona/sources
new file mode 100644
index 000000000..c6cab2321
--- /dev/null
+++ b/private/ole32/ole232/drag/daytona/sources
@@ -0,0 +1,77 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = ole232
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= drag
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES= ..;..\..\..\common\daytona;..\..\..\ih;..\..\inc
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+
+SOURCES= \
+ ..\ido.cpp \
+ ..\drag.cpp
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
diff --git a/private/ole32/ole232/drag/depend.mk b/private/ole32/ole232/drag/depend.mk
new file mode 100644
index 000000000..bdfaaa6fe
--- /dev/null
+++ b/private/ole32/ole232/drag/depend.mk
@@ -0,0 +1,35 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\drag.obj $(OBJDIR)\drag.lst: .\drag.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\olerem.h $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\clipbrd.h $(CAIROLE)\ole232\inc\enumgen.h \
+ $(CAIROLE)\ole232\inc\fetcenum.h $(CAIROLE)\ole232\inc\memstm.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
diff --git a/private/ole32/ole232/drag/dirs b/private/ole32/ole232/drag/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/ole232/drag/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/ole232/drag/dmsgfltr.h b/private/ole32/ole232/drag/dmsgfltr.h
new file mode 100644
index 000000000..0d277813b
--- /dev/null
+++ b/private/ole32/ole232/drag/dmsgfltr.h
@@ -0,0 +1,88 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dmsgfltr.cpp
+//
+// Contents: This tiny message filter implementation exists to prevent
+// the eating of mouse messages by applications during drag and
+// drop. The default behavior of the call control is to eat these
+// messages. And application can specify whatever behavior they
+// want with messages.
+//
+// Classes: CDragMessageFilter
+//
+// History: dd-mmm-yy Author Comment
+// 03-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+#ifndef _DMSGFLTR_H_
+#define _DMSGFLTR_H_
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDragMessageFilter
+//
+// Purpose: Handles special message filter processing req'd by Drag
+// and Drop.
+//
+// Interface: QueryInterface - get new interface
+// AddRef - bump reference count
+// Release - dec reference count
+// HandleInComingCall - handle new RPC
+// RetryRejectedCall - whether to retry rejected
+// MessagePending - handle message during RPC
+//
+// History: dd-mmm-yy Author Comment
+// 03-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CDragMessageFilter : public CPrivAlloc, public IMessageFilter
+{
+public:
+
+ CDragMessageFilter(void);
+
+ ~CDragMessageFilter(void);
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
+
+ ULONG STDMETHODCALLTYPE AddRef(void);
+
+ ULONG STDMETHODCALLTYPE Release(void);
+
+ DWORD STDMETHODCALLTYPE HandleInComingCall(
+ DWORD dwCallType,
+ HTASK htaskCaller,
+ DWORD dwTickCount,
+ LPINTERFACEINFO lpInterfaceInfo);
+
+ DWORD STDMETHODCALLTYPE RetryRejectedCall(
+ HTASK htaskCallee,
+ DWORD dwTickCount,
+ DWORD dwRejectType);
+
+ DWORD STDMETHODCALLTYPE MessagePending(
+ HTASK htaskCallee,
+ DWORD dwTickCount,
+ DWORD dwPendingType);
+
+ static HRESULT Create(IMessageFilter **pMF);
+
+private:
+
+ // Previous message filter
+ LPMESSAGEFILTER _lpMessageFilterPrev;
+
+ // Reference count on our object
+ LONG _crefs;
+};
+
+
+
+
+#endif // _DMSGFLTR_H_
diff --git a/private/ole32/ole232/drag/drag.cpp b/private/ole32/ole232/drag/drag.cpp
new file mode 100644
index 000000000..ac367bed5
--- /dev/null
+++ b/private/ole32/ole232/drag/drag.cpp
@@ -0,0 +1,2514 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: drag.cpp
+//
+// Contents: Api's for doing drag'n'drop
+//
+// Classes: CPoint
+// CDragOperation
+// CDropTarget
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-94 alexgo converted to PrivDragDrop rpc
+// for Drag Drop protocol
+// 20-Oct-94 alexgo added Win3.1 style drag drop
+// for Chicago/NT shell
+// 30-Sep-94 ricksa Drag/Drop optimization.
+// 18-Jul-94 ricksa made cursors work in shared WOW
+// 21-Apr-94 ricksa made drag/drop handle WM_CANCELMODE
+// 04-Apr-94 ricksa rewrote DoDragDrop loop
+// 11-Jan-94 alexgo added VDATEHEAP to every function
+// 29-Dec-93 alexgo converted to RPC alogirithm for
+// getting IDropTarget, etc.
+// 06-Dec-93 alexgo commented, formatted
+// 93/94 Johann Posch (JohannP) created Drag/Drop for Ole 16 bit
+//
+// Notes:
+//
+// RPC Drag Drop algorithm:
+//
+// During a drag drop operation, the user is moving the mouse around
+// the screen, passing over many windows. For each window the mouse
+// is over, we need to determine if the window is a drop target.
+// If it is, then we remote the IDropTarget interface to the DropSource
+// so that the correct visual feedbacks can be given.
+//
+// To accomplish this, RegisterDragDrop adds two properties to the
+// drop target window: a public property, EndPoint ID (provided to
+// us by compobj), and a private property (available only to the calling
+// process), the IDropTarget pointer.
+//
+// During the DoDragDrop loop, we ask compobj to test each window for
+// the EndpointID property. If it is there, compobj (via
+// GetInterfaceFromWindowProp), then we will rpc to the drop target
+// process, get the IDropTarget pointer and marshal it back to the
+// drop source process. We also install a custom message filter to
+// ensure that messages (particularly mouse move messages) are handled
+// correctly.
+//
+// RevokeDragDrop simply removes the above mentioned properties from
+// the window handle.
+//
+// Because in Win32, you can always switch windows and mouse capture
+// depends on having the mouse button down, drag/drop processing
+// is changed slightly. Whenever, the user does an operation that
+// would switch windows, the clipboard window that we use for capture
+// will get a WM_CANCELMODE. It will notify the drag operation and
+// the drag operation will proceed as if the user aborted the operation.
+//
+//
+// Win 3.1 DragDrop algorithm:
+//
+// Win3.1 apps can register a window as a drop target via DragAcceptFiles.
+// This API sets the WS_EX_ACCEPTFILES bit in the window style.
+//
+// In Win3.1, these apps would get a WM_DROPFILES message when
+// files where dropped on them. An hglobal with the filenames is
+// sent in the wparam of WM_DROPFILES.
+//
+// In Chicago and NT3.5, CF_HDROP is a new clipboard format that is
+// identical to the data sent in WM_DROPFILES. If we see this format
+// available in a data object passed to DoDragDrop, then we enter
+// into our Win31 compatibility mode (which affects finding a drop
+// target).
+//
+// When finding a drop target for a given window, we check to
+// see if a window in the hierarchy is registered as a Win31 drop
+// target. If so, then we create a wrapper drop target. This wrapper
+// drop target will forward calls to the real drop target (if available).
+//
+// With Win3.1 drag drop, we can do a COPY. If the OLE target indicates
+// that no OLE drop can be performed (by returning DROPEFFECT_NONE),
+// then we substitute in DROPEFFECT_COPY.
+//
+// On Drop, if the OLE target chooses not to accept the drop, then
+// we will post the window a WM_DROPFILES message with the hglobal
+// obtained from IDataObject::GetData(CF_HDROP).
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+// Note: Enable including native user APIs
+// for stack switching
+#include <userapis.h>
+#pragma SEG(drag)
+
+#include <getif.hxx>
+#include <dragopt.h>
+#include <resource.h>
+#include "enumgen.h"
+#include "clipbrd.h"
+#include "drag.h"
+
+
+NAME_SEG(Drag)
+ASSERTDATA
+
+ATOM g_aEndpointHack;
+
+// DROPFILES is the structure of data contained in the CF_HDROP format.
+// However, this is private to the shell, so it is not declared in any
+// header files.
+
+typedef struct _DROPFILES {
+ DWORD pFiles; // offset of file list
+ POINTL pt; // drop point (client coords)
+ DWORD fNC; // is it on NonClient area
+ // and pt is in screen coords
+ DWORD fWide; // WIDE character switch
+} DROPFILES, FAR * LPDROPFILES;
+
+
+#define WM_NCMOUSEFIRST 0x00A0
+#define WM_NCMOUSELAST 0x00A9
+
+
+// From ido.cpp to create shared memory formats
+HANDLE CreateSharedDragFormats(IDataObject *pIDataObject);
+
+
+#define VK_ALT VK_MENU
+
+static const struct {
+ int keyCode;
+ WPARAM keyFlag;
+ } vKeyMap [] = {
+ { VK_LBUTTON, MK_LBUTTON },
+ { VK_RBUTTON, MK_RBUTTON },
+ { VK_MBUTTON, MK_MBUTTON },
+ { VK_ALT , MK_ALT },
+ { VK_SHIFT , MK_SHIFT },
+ { VK_CONTROL, MK_CONTROL }
+ };
+
+// This is the default cursor object for 32 bit apps. Only one such object
+// is needed for 32 bit apps. 16 bit apps need one per shared WOW application
+// that is running.
+CDragDefaultCursors *cddcDefault32 = NULL;
+
+extern ATOM g_aDropTarget;
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: DragDropProcessUninitialize
+//
+// Synopsis: Does any Unitialization necessary at OleUninitialize time.
+// for the last Unitialize for the Process
+//
+// Returns: none
+//
+// Algorithm:
+
+// History: dd-mmm-yy Author Comment
+// 18-Jul-94 rogerg Created
+//
+// Note: We need a per thread default cursor object in WOW because
+// of the clean up that WOW does. For 32 bit apps, we just use
+// one for the entire process.
+//
+//--------------------------------------------------------------------------
+
+
+void DragDropProcessUninitialize(void)
+{
+
+ if (NULL != cddcDefault32)
+ {
+ delete cddcDefault32;
+ cddcDefault32 = NULL;
+ }
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDefaultCursors::GetDefaultCursorObject, static
+//
+// Synopsis: Get appropriate pointer to default cursor object
+//
+// Returns: NULL - error occurred
+// ~NULL - pointer to appropriate default cursor table
+//
+// Algorithm: If we are in a 32 bit app, just get a pointer to the
+// single cursor table. In 16 bit, get the per thread cursor
+// table. If there is none, then allocate and initialize it.
+//
+// History: dd-mmm-yy Author Comment
+// 18-Jul-94 Ricksa Created
+//
+// Note: We need a per thread default cursor object in WOW because
+// of the clean up that WOW does. For 32 bit apps, we just use
+// one for the entire process.
+//
+//--------------------------------------------------------------------------
+CDragDefaultCursors *CDragDefaultCursors::GetDefaultCursorObject(void)
+{
+ if (!IsWOWThread())
+ {
+ // If we aren't in WOW, we can use the single common default cursor
+ // object. We make sure that it is initialized before we use it.
+
+ if (NULL == cddcDefault32)
+ {
+ cddcDefault32 = new CDragDefaultCursors;
+ if (cddcDefault32)
+ {
+ if (!cddcDefault32->Init())
+ {
+ delete cddcDefault32;
+ cddcDefault32 = NULL;
+ }
+
+ }
+ }
+
+ return cddcDefault32;
+ }
+
+ COleTls tls;
+
+ // We are in WOW. Get the cursor object if it has already been allocated
+ CDragDefaultCursors *pccdc16 = (CDragDefaultCursors *) tls->pDragCursors;
+
+ if (pccdc16 == NULL)
+ {
+ // No cursor table so allocate it -- Please note that we take advantage
+ // of the fact that this object has only the default constructor by
+ // simply allocating it rather than "newing" it. The point is that
+ // we need to free the memory at thread release time and this happens
+ // in code that doesn't know about the the object.
+ pccdc16 = (CDragDefaultCursors *)
+ PrivMemAlloc(sizeof(CDragDefaultCursors));
+
+ if (pccdc16 != NULL)
+ {
+ // Successfully allocated so initialize it
+ if (!pccdc16->Init())
+ {
+ PrivMemFree(pccdc16);
+ return NULL;
+ }
+
+ tls->pDragCursors = pccdc16;
+ }
+ }
+
+ return pccdc16;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CDragDefaultCursors::Init
+//
+// Synopsis: Initialize object by loading all the default cursors.
+//
+// History: dd-mmm-yy Author Comment
+// 19-Apr-94 Ricksa Created
+//
+// Note: We continue the Win16 practice of ignoring possible failure
+// cases when loading the cursors although we do put in a
+// debug verification that they all loaded.
+//
+//--------------------------------------------------------------------------
+BOOL CDragDefaultCursors::Init(void)
+{
+ // Make sure table is set to NULLs.
+ memset(&ahcursorDefaults[0][0], 0, sizeof(ahcursorDefaults));
+
+ // Load cursors for operation
+ if ( !(ahcursorDefaults[NO_SCROLL] [NO_DROP]
+ = LoadCursor (g_hmodOLE2, MAKEINTRESOURCE(CURNONE))) )
+ return FALSE;
+
+ if (!(ahcursorDefaults[NO_SCROLL] [MOVE_DROP] =
+ LoadCursor (g_hmodOLE2, MAKEINTRESOURCE(CURMOVE))) )
+ return FALSE;
+
+ if (!(ahcursorDefaults[NO_SCROLL] [COPY_DROP] =
+ LoadCursor (g_hmodOLE2, MAKEINTRESOURCE(CURCOPY))) )
+ return FALSE;
+
+ if (!(ahcursorDefaults[NO_SCROLL] [LINK_DROP] =
+ LoadCursor(g_hmodOLE2, MAKEINTRESOURCE(CURLINK))) )
+ return FALSE;
+
+
+ // Load cursors for operation
+ ahcursorDefaults[SCROLL] [NO_DROP] =
+ ahcursorDefaults[NO_SCROLL] [NO_DROP];
+
+ ahcursorDefaults[SCROLL] [MOVE_DROP] =
+ ahcursorDefaults[NO_SCROLL] [MOVE_DROP];
+
+ ahcursorDefaults[SCROLL] [COPY_DROP] =
+ ahcursorDefaults[NO_SCROLL] [COPY_DROP];
+
+ ahcursorDefaults[SCROLL] [LINK_DROP] =
+ ahcursorDefaults[NO_SCROLL] [LINK_DROP];
+
+
+#if DBG == 1
+ // For debug, verify that cursors were loaded correctly
+ for (int i = 0; i < 2; i++)
+ {
+ for (int j = 0; j < 4; j++)
+ {
+ AssertSz((ahcursorDefaults[i] [j] != NULL),
+ "Drag/Drop cursor initialization failed!");
+ }
+ }
+#endif // DBG == 1
+
+ return TRUE;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CDragDefaultCursors::SetCursor
+//
+// Synopsis: Set cursor to appropriate value
+//
+// Algorithm: We use the input effect to calculate the appropriate offset
+// into the table for the cursor to use.
+//
+// History: dd-mmm-yy Author Comment
+// 19-Apr-94 Ricksa Created
+//
+// Note: We use the table approach so we to make consistent behavior
+// between scroll and non-scroll cursors.
+//
+//--------------------------------------------------------------------------
+void CDragDefaultCursors::SetCursor(DWORD dwEffect)
+{
+ // Get Scroll index
+ int iScroll = (dwEffect & DROPEFFECT_SCROLL) ? SCROLL : NO_SCROLL;
+
+ int iCursorType = NO_DROP;
+
+ if (dwEffect & DROPEFFECT_LINK)
+ {
+ iCursorType = LINK_DROP;
+ }
+ else if (dwEffect & DROPEFFECT_COPY)
+ {
+ iCursorType = COPY_DROP;
+ }
+ else if (dwEffect & DROPEFFECT_MOVE)
+ {
+ iCursorType = MOVE_DROP;
+ }
+
+ ::SetCursor(ahcursorDefaults[iScroll] [iCursorType]);
+}
+
+
+
+//
+// Drag/Drop Operation Statics
+//
+LONG CDragOperation::s_wScrollInt = -1;
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetControlKeysState
+//
+// Synopsis: queries the current status of the control keys
+//
+// Arguments: [fAll] -- if true, the just query the keys, not mouse
+// buttons too
+//
+// Returns: the MK flags for each key pressed
+//
+// Algorithm: Get key state either for all keys and mouse buttons in
+// the vKeyMap table or simply for the key portion of the table
+// and translate it to the WPARAM form as returned in mouse
+// messages.
+//
+// History: dd-mmm-yy Author Comment
+// 06-Dec-93 alexgo 32bit port
+//
+//--------------------------------------------------------------------------
+
+WORD GetControlKeysState(BOOL fAll)
+{
+ WORD grfKeyState = 0;
+
+ int i = (fAll) ? 0 : 3;
+
+ for (; i < sizeof(vKeyMap) / sizeof(vKeyMap[0]); i++)
+ {
+ if (GetKeyState(vKeyMap[i].keyCode) < 0) // Key down
+ {
+ grfKeyState |= vKeyMap[i].keyFlag;
+ }
+ }
+
+ return grfKeyState;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetControlKeysStateOfParam
+//
+// Synopsis: gets the key/button state of wparam (used with mouse messages)
+//
+// Arguments: [wParam] -- the wParam to parse apart
+//
+// Returns: the key's set in wParam
+//
+// Algorithm: First determine if keys we are interested in are set
+// in the wParam message. Then go check the state of the
+// ALT key and record that in the key state. We then return
+// that to the caller.
+//
+// History: dd-mmm-yy Author Comment
+// 06-Dec-93 alexgo 32bit port
+//
+//--------------------------------------------------------------------------
+
+WORD GetControlKeysStateOfParam(WPARAM wParam)
+{
+ // Check all the buttons we are interested in at once.
+ WORD grfKeyState = wParam
+ & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON | MK_SHIFT | MK_CONTROL);
+
+ // get the alt key
+ if (GetKeyState(VK_ALT) < 0) // Key down
+ {
+ grfKeyState |= MK_ALT;
+ }
+
+ return grfKeyState;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsWin31DropTarget
+//
+// Synopsis: determines whether the given hwnd is a valid drop target
+// for Win31 style drag drop
+//
+// Effects:
+//
+// Arguments: [hwnd] -- the window to check
+//
+// Requires:
+//
+// Returns: TRUE/FALSE
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: checks the WS_EX_ACCEPTFILES style bit. If this bit is
+// set and the window is not disabled, then it is a valid
+// Win3.1 drop target.
+//
+// History: dd-mmm-yy Author Comment
+// 25-Jan-95 alexgo added check for WS_DISABLED
+// 20-Oct-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+BOOL IsWin31DropTarget( HWND hwnd )
+{
+ LONG exstyle;
+
+ exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+
+
+ if( (exstyle & WS_EX_ACCEPTFILES) )
+ {
+ LONG style;
+ style = GetWindowLong(hwnd, GWL_STYLE);
+
+ if( !(style & WS_DISABLED) )
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UseWin31DragDrop
+//
+// Synopsis: tests the given data object to see if enough data is offered
+// to perform Win3.1 style drag drop
+//
+// Effects:
+//
+// Arguments: [pDataObject] -- pointer to the data object
+//
+// Requires: pdataobj must not be NULL
+//
+// Returns: TRUE/FALSE
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: does an IDataObject::QueryGetData for CF_HDROP
+//
+// History: dd-mmm-yy Author Comment
+// 30-Oct-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+BOOL UseWin31DragDrop(IDataObject *pDataObject)
+{
+ FORMATETC formatetc;
+
+ INIT_FORETC(formatetc);
+ formatetc.cfFormat = CF_HDROP;
+ formatetc.tymed = TYMED_HGLOBAL;
+
+ if( pDataObject->QueryGetData(&formatetc) == NOERROR )
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsNCDrop
+//
+// Synopsis: are we dropping into the non-client area of the window or
+// on an iconic window?
+//
+// Effects: *DOES A SEND MESSAGE*!!!
+//
+// Arguments: [hwnd] -- the window to ask
+// [pt] -- the point in screen coords
+//
+// Requires:
+//
+// Returns: TRUE/FALSE (TRUE if in non-client area)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 25-Jan-95 alexgo borrowed from Win95 shell sources
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+BOOL IsNCDrop(HWND hwnd, POINT pt)
+{
+ return (!IsIconic(hwnd) &&
+ HTCLIENT!=SendMessage(hwnd, WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y)));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: GetDropTarget
+//
+// Synopsis: Gets the IDropTarget * from the closest window in the
+// hierachy up from the given window (if available, of
+// course ;-)
+//
+// Arguments: [hwndCur] -- the window to the cursor is currently over
+// [hwndDropTarget] -- the window that contains a valid DropTarget
+//
+// Returns: Result of drag enter operation at Target
+//
+// Algorithm: Loop calling PrivDragDrop until we get a drop target or
+// we run out of windows that are parent to the window that
+// the mouse is currently on.
+//
+// If a window in the hierarchy has registered itself for
+// Win3.1 drag drop, then we create a drop target wrapper
+// (CDropTarget) to handle the Win3.1 protocol. Note
+// that a window hierarchy may be both OLE *and* Win3.1
+// targets.
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-94 alexgo converted to use PrivDragDrop
+// 20-Oct-94 alexgo added Win31 drop target support
+// 30-Sep-94 ricksa Drag/Drop optimization.
+// 21-Jul-94 alexgo removed GetDropTargetFromWindow
+// optimization and put that functionality
+// in GetInterfaceFromWindowProp (to
+// help make clipboard faster).
+// 06-Apr-94 Ricksa Modified to call GetDropTargetFromWindow
+// to optimize local calls
+// 11-Jan-94 alexgo changed name from GetTopStm to
+// GetDropTarget, converted to the RPC-style
+// drag drop, added a VDATEHEAP macro
+// 06-Dec-93 alexgo commented
+//
+//--------------------------------------------------------------------------
+
+HRESULT CDragOperation::GetDropTarget(HWND hwnd31,HWND hwndDropTarget)
+{
+IDropTarget *ptarget = NULL;
+DDInfo hDDInfo = NULL;
+
+ VDATEHEAP();
+
+ DDDebugOut((DEB_ITRACE, "%p _IN GetDropTarget ( %x,%x)\n", this, hwnd31,hwndDropTarget));
+
+ _pDropTarget = NULL;
+
+ HRESULT hr = E_FAIL;
+
+
+ if (hwndDropTarget)
+ {
+
+ Assert(GetProp(hwndDropTarget, (LPCWSTR)g_aDropTarget));
+
+ hr = PrivDragDrop(hwndDropTarget,
+ DRAGOP_ENTER,
+ _DOBuffer,
+ _pDataObject,
+ _grfKeyState,
+ _cpt.GetPOINTL(),
+ _pdwEffect,
+ NULL,
+ &hDDInfo);
+
+ if (hr != NOERROR)
+ {
+ hwndDropTarget = NULL;
+ }
+
+ }
+
+ Assert( (NULL == hwnd31) || IsWin31DropTarget(hwnd31));
+
+ if( hwndDropTarget || hwnd31 )
+ {
+ ptarget = new CDropTarget(hwnd31, hwndDropTarget, *_pdwEffect, this, hDDInfo);
+
+ if( ptarget == NULL )
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ {
+ hr = NOERROR;
+ }
+
+ // if we have a Win31 drop target AND the OLE drop target returned
+ // DROPEFFECT_NONE, then we should return DROPEFFECT_COPY
+
+ if( hr == NOERROR && *_pdwEffect == DROPEFFECT_NONE && hwnd31 )
+ {
+ *_pdwEffect = DROPEFFECT_COPY;
+ }
+
+ _pDropTarget = ptarget;
+
+ }
+
+ DDDebugOut((DEB_ITRACE, "%p OUT GetDropTarget ( %lx ) [ %p ]\n",
+ this, hr, _pDropTarget));
+
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CDragOperation::CDragOperation
+//
+// Synopsis: Initialize the object to start the operation
+//
+// Arguments: [pDataObject] - pointer to data object to drop
+// [pDropSource] - pointer to source for drop operation
+// [dwOKEffects] - effects allowed in drag operation
+// [pdwEffect] - how operation affected source data
+// [hr] - whether constructor succeeded
+//
+// Algorithm: Initialize data in object. Make sure that static data
+// is initialized. Wait for first mouse message to begin.
+//
+// History: dd-mmm-yy Author Comment
+// 20-Oct-94 alexgo added support for Win31 drag drop
+// 04-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CDragOperation::CDragOperation(
+ LPDATAOBJECT pDataObject,
+ LPDROPSOURCE pDropSource,
+ DWORD dwOKEffects,
+ DWORD FAR *pdwEffect,
+ HRESULT& hr)
+ :
+ _pDataObject(pDataObject),
+ _pDropSource(pDropSource),
+ _dwOKEffects(dwOKEffects),
+ _pdwEffect(pdwEffect),
+ _hwndLast((HWND) -1),
+ _pDropTarget(NULL),
+ _pRealDropTarget(NULL),
+ _fEscapePressed(FALSE),
+ _hrDragResult(S_OK),
+ _curOld(GetCursor()),
+ _hFormats(NULL),
+ _fReleasedCapture(FALSE)
+{
+ VDATEHEAP();
+
+ // Set the default scroll interval
+ if (s_wScrollInt < 0)
+ {
+ InitScrollInt();
+ }
+
+ hr = GetMarshalledInterfaceBuffer(IID_IDataObject, pDataObject,
+ &_DOBuffer);
+
+ if( hr != NOERROR )
+ {
+ Assert(NULL == _DOBuffer);
+ return;
+ }
+
+ // Get appropriate default cursor table object
+ if ((_pcddcDefault = CDragDefaultCursors::GetDefaultCursorObject()) == NULL)
+ {
+ // Some error occurred while we were trying to initialize the
+ // so return an error. This should be highly unusual.
+ DDDebugOut((DEB_ERROR,
+ "CDragDefaultCursors::GetDefaultCursorObject Failed!\n"));
+ hr = E_FAIL;
+ return;
+ }
+
+ // We will use the clipboard window to capture the mouse but we
+ // must have a clipboard window so we make sure it is created
+ // if it is not already there.
+ hr = ClipSetCaptureForDrag(this);
+
+ if (FAILED(hr))
+ {
+ return;
+ }
+
+ _hFormats = CreateSharedDragFormats(pDataObject);
+
+ // it's OK for _hFormats to be NULL (indicates an empty or non-existant
+ // formatetc enumertor
+
+ // For following peek
+ MSG msg;
+
+ // Busy wait until a mouse or escape message is in the queue
+ while (!PeekMessage(&msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE))
+ {
+ // Note: all keyboard messages except escape are tossed. This is
+ // fairly reasonable since the user has to be holding the left
+ // mouse button down at this point. They can't really be doing
+ // too much data input one handed.
+ if ((PeekMessage(&msg, 0, WM_KEYDOWN, WM_KEYDOWN, PM_REMOVE)
+ || PeekMessage(&msg, 0, WM_SYSKEYDOWN, WM_SYSKEYDOWN, PM_REMOVE))
+ && msg.wParam == VK_ESCAPE)
+ {
+ _fEscapePressed = TRUE;
+ break;
+ }
+ }
+
+ // get mouse pos and key state
+ if (!_fEscapePressed)
+ {
+ _cpt.Set(msg.pt.x, msg.pt.y);
+ _grfKeyState = GetControlKeysStateOfParam(msg.wParam);
+ }
+ else
+ {
+ // We ask the cursor for its position since we didn't get a
+ // position from the mouse.
+ GetCursorPos(_cpt.GetAddressOfPOINT());
+ _grfKeyState = GetControlKeysState(TRUE);
+ }
+
+ // Check to see if we need to do Win3.1 style drag drop.
+ // If we do, then set a flag so we can construct a fake drop target as
+ // needed
+
+ if( UseWin31DragDrop(pDataObject) )
+ {
+ _fUseWin31 = TRUE;
+ }
+ else
+ {
+ _fUseWin31 = FALSE;
+ }
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ~CDragOperation
+//
+// Synopsis: Clean up object
+//
+// Algorithm: Release mouse capture. Restore ole cursor. Remove enum
+// formats.
+//
+// History: dd-mmm-yy Author Comment
+// 04-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CDragOperation::~CDragOperation(void)
+{
+ VDATEHEAP();
+
+ AssertSz((_pDropTarget == NULL), "CDragOperation::~CDragOperation");
+
+ // Stop the mouse capture
+ ReleaseCapture();
+
+ // Restore the cursor if it got changed
+ SetCursor(_curOld);
+
+ // Close the handle to the shared memory
+ if (_hFormats)
+ {
+ CloseHandle(_hFormats);
+ _hFormats = NULL;
+ }
+
+ if( _DOBuffer )
+ {
+ ReleaseMarshalledInterfaceBuffer(_DOBuffer);
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CDragOperation::InitScrollInt
+//
+// Synopsis: Initialize the scroll interval
+//
+// Algorithm: Look in profile for defined interval. If none set, then
+// default to zero.
+//
+// History: dd-mmm-yy Author Comment
+// 04-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+void CDragOperation::InitScrollInt(void)
+{
+ DWORD dw;
+ OLECHAR szBuffer[20];
+
+ s_wScrollInt = DD_DEFSCROLLDELAY;
+
+ dw = sizeof(szBuffer);
+ if (ERROR_SUCCESS == RegQueryValueEx(HKEY_CURRENT_USER,
+ OLESTR("Control Panel\\Mouse\\DragScrollDelay"),
+ NULL,
+ NULL,
+ (LPBYTE)szBuffer,
+ &dw))
+ {
+ s_wScrollInt = wcstol(szBuffer, NULL, 0);
+ }
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CDragOperation::UpdateTarget
+//
+// Synopsis: Update the target window based on mouse location
+//
+// Returns: TRUE - continue drag operation
+// FALSE - error or time to drop
+//
+// Algorithm: First, we query the source to see if it wants to continue
+// with the drop. If so, we get current window for mouse. If
+// it is different than the previous window check to see whether
+// the targets are different. If they are different, then notify
+// the current target that we are leaving and then notify the
+// new target that we have arrived.
+//
+// History: dd-mmm-yy Author Comment
+// 04-Apr-94 Ricksa Created
+// 10-Jul-94 AlexT Allow same IDropTarget on different HWNDs
+//
+//--------------------------------------------------------------------------
+BOOL CDragOperation::UpdateTarget(void)
+{
+ VDATEHEAP();
+
+ DDDebugOut((DEB_ITRACE, "%p _IN CDragOperation::UpdateTarget ( )\n", this));
+
+ // Assume this operation will continue the drag drop
+ BOOL fResult = TRUE;
+ HRESULT hr;
+ LPDROPTARGET lpCurDropTarget = NULL,
+ lpOldDropTarget = NULL;
+ HWND hWndTemp = NULL;
+
+ HWND hwndCur = WindowFromPoint(_cpt.GetPOINT());
+
+ // Query continue can return telling us one of four things:
+ // (1) Keep going (S_OK), (2) Drop operation should occur
+ // (DRAGDROP_S_DROP), (3) Drop operation is canceled
+ // (DRAGDROP_S_CANCEL) or (4) An unexpected error has occurred.
+
+ HRESULT hrQuery = _pDropSource->QueryContinueDrag(_fEscapePressed,
+ _grfKeyState);
+
+ if (FAILED(hrQuery) || (hrQuery == ResultFromScode(DRAGDROP_S_CANCEL)))
+ {
+ // Unexpected error or the operation has been cancelled so give up.
+ _hrDragResult = hrQuery;
+ fResult = FALSE;
+ goto UpdateTarget_exit;
+ }
+
+ // walk up the window list to find the actual pointer values for the current
+ // and old IDropTarget interfaces
+ if (hwndCur != _hwndLast)
+ {
+ hWndTemp = _hwndLast;
+
+ BOOL fChangedWin31 = FALSE;
+
+ HWND hWndOldDrop = NULL;
+ HWND hWndNewDrop = NULL;
+ HWND hWndWin31Drop = NULL;
+
+ LPDROPTARGET lpRealDropTarget = NULL;
+ HANDLE hTemp = NULL;
+
+ DWORD dwCurrentProcessId = 0;
+
+ if (hWndTemp != (HWND)-1)
+ GetWindowThreadProcessId(hWndTemp, &dwCurrentProcessId);
+
+ DWORD dwTempProcessID = dwCurrentProcessId;
+
+ while (hWndTemp && !lpRealDropTarget && hWndTemp != (HWND)-1 && dwTempProcessID == dwCurrentProcessId)
+ {
+ if (lpRealDropTarget = (IDropTarget *)GetProp(hWndTemp, (LPCWSTR)g_aDropTarget))
+ {
+ hWndOldDrop = hWndTemp;
+ }
+
+ hWndTemp = GetParent(hWndTemp);
+
+ if (hWndTemp)
+ {
+ GetWindowThreadProcessId(hWndTemp, &dwTempProcessID);
+ }
+ }
+
+ hWndTemp = hwndCur;
+
+ if (hWndTemp != (HWND)-1)
+ GetWindowThreadProcessId(hWndTemp, &dwCurrentProcessId);
+
+ dwTempProcessID = dwCurrentProcessId;
+
+ while (hWndTemp && dwTempProcessID == dwCurrentProcessId)
+ {
+ // If we haven't found the DropTarget yet, check this window.
+ if (!lpCurDropTarget)
+ {
+ if (lpCurDropTarget = (IDropTarget *)GetProp(hWndTemp, (LPCWSTR)g_aDropTarget))
+ {
+ hWndNewDrop = hWndTemp;
+ }
+ }
+
+ // if the current window is a win31 drop target, update the win31 window
+ // handle in our DropTarget Class. NOTE: Beware, this code relies on the
+ // fact that we can party on the CDropTarget Class directly, knowing that
+ // the class is reconstructed below as a result of the GetDropTarget()
+ // when the real IDropTarget ptrs change.
+
+ if (!fChangedWin31 &&
+ IsWin31DropTarget(hWndTemp) &&
+ _fUseWin31)
+ {
+ fChangedWin31 = TRUE;
+
+ hWndWin31Drop = hWndTemp;
+
+ if (_pDropTarget)
+ {
+ ((CDropTarget*)_pDropTarget)->_hwnd31 = hWndTemp;
+ }
+ }
+
+
+ // if have a droptarget, and handle Win31 break.
+ if (lpCurDropTarget && (!_fUseWin31 || fChangedWin31))
+ {
+ break;
+ }
+
+ hWndTemp = GetParent(hWndTemp);
+
+ if (hWndTemp)
+ {
+ GetWindowThreadProcessId(hWndTemp, &dwTempProcessID);
+ }
+ }
+
+ // only update the drop target if the target has actually changed.
+
+ // HACK ALERT: We must explicitly check _hwndLast for -1 because Excel does not
+ // use OLE drag drop internally. When the cursor is moved outside the Overlapped
+ // Excel window, DoDragDrop is called. At this point _pRealDropTarget == NULL
+ // and lpCurDropTarget == NULL, and the no-smoking cursor does not appear.
+
+ // the _pRealDropTarget==NULL relies on the fact that lpCurDropTarget==NULL. This
+ // is true because the first case would short-circuit the rest of the condition
+ // otherwise
+ if ( (lpCurDropTarget != _pRealDropTarget) ||
+ (_hwndLast == (HWND)-1) ||
+ (hWndNewDrop != hWndOldDrop) ||
+ (_pRealDropTarget == NULL))
+ {
+ DDDebugOut((DEB_ITRACE, "%p lpCurDropTarget != lpOldDropTarget\n", this));
+
+ // The window that we are working on has changed
+ _hwndLast = hwndCur;
+ _pRealDropTarget = lpCurDropTarget;
+
+ // Assume that neither current or previous window are drop aware
+ BOOL fCurAndLastNotDropAware = TRUE;
+
+ if (_pDropTarget != NULL)
+ {
+ // There was a previous drop target
+
+ // Last window was drag/drop aware
+ fCurAndLastNotDropAware = FALSE;
+
+ // Tell the drop target we are leaving & release it
+ _pDropTarget->DragLeave();
+ _pDropTarget->Release();
+ _pDropTarget = NULL;
+ }
+
+ // Set up effects for query of target
+ *_pdwEffect = _dwOKEffects;
+
+ hr = GetDropTarget(hWndWin31Drop,hWndNewDrop);
+
+ if (_pDropTarget != NULL)
+ {
+ // This window is drop awarre
+ fCurAndLastNotDropAware = FALSE;
+
+ // Errors from this call are ignored. We interpret them
+ // as the drop being disallowed. Since we don't really
+ // use this information here but in the DragOver call
+ // we make shortly, we just use this call to notify
+ // the application that we are beginning a drag operation.
+
+ if (!HandleFeedBack(hr))
+ {
+ goto UpdateTarget_exit;
+ }
+ }
+ else
+ {
+ // Tell the source that nothing happened
+
+ // only use DROPEFFECT_NONE if there is no new drop target.
+ hr = _pDropSource->GiveFeedback(*_pdwEffect = DROPEFFECT_NONE);
+
+ if (hr != NOERROR)
+ {
+ if (DRAGDROP_S_USEDEFAULTCURSORS == GetScode(hr))
+ {
+ _pcddcDefault->SetCursorNone();
+ }
+ else
+ {
+ // Unexpected error -- we will give up drag/drop.
+ DDDebugOut((DEB_ERROR,
+ "CDragOperation::UpdateTarget 1st GiveFeedback FAILED %x\n",
+ hr));
+ _hrDragResult = hr;
+ fResult = FALSE;
+ goto UpdateTarget_exit;
+ }
+ }
+ }
+
+ if (fCurAndLastNotDropAware)
+ {
+ // Neither new or old window know about drag/drop so set
+ // cursor accordingly.
+ _pcddcDefault->SetCursorNone();
+ }
+ }
+ else
+ {
+ // The window that we are working on has changed
+ _hwndLast = hwndCur;
+ }
+ }
+
+
+ if (hrQuery != NOERROR)
+ {
+ // Query asked for a drop
+ fResult = FALSE;
+ _hrDragResult = hrQuery;
+ }
+
+UpdateTarget_exit:
+
+ DDDebugOut((DEB_ITRACE, "%p OUT CDragOperation::UpdateTarget ( %lx )\n",
+ this, fResult));
+
+ return fResult;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CDragOperation::HandleFeedBack
+//
+// Synopsis: Handle feedback and update of cursor
+//
+// Arguments: [hr] - hresult from previous operation on drop target.
+//
+// Returns: TRUE - continue drag operation
+// FALSE - error
+//
+// Algorithm: If previous operation on the target failed, map this to a
+// disallowed drop. Then ask the source for feedback. If it
+// so requests, then update the cursor. If an unexpected
+// error occurs, let caller know that loop should break.
+//
+// History: dd-mmm-yy Author Comment
+// 19-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CDragOperation::HandleFeedBack(HRESULT hr)
+{
+ VDATEHEAP();
+
+ DDDebugOut((DEB_ITRACE, "%p _IN CDragOperation::HandleFeedBack ( %x )\n",
+ this, hr));
+
+ BOOL fResult = TRUE;
+
+ if (hr != NOERROR)
+ {
+
+ // target not responding for some reason; treat
+ // as if drop not possible, but don't preserve
+ // the reason why.
+ *_pdwEffect = DROPEFFECT_NONE;
+ }
+
+ // If bogus return from drag over, then make sure results are appropriate.
+ // However, if we are in a WOW we need to do things a little differently
+ // to maintain complete compatability with Win 3.1. In 16-bit OLE 2.0,
+ // the *_pdwEffect value is not changed when displaying feedback (i.e.,
+ // the result of the & is not stored back into *_pdwEffect in Win 3.1...
+ // in straight NT we do). Not storing the results back into *_pdwEffect
+ // when InWow() is a hack specifically for Visio, and even more
+ // specifically, for dragging from Visio's palette of "items" to an
+ // Excel spreadsheet.
+
+ if (IsWOWThread())
+ {
+ hr = _pDropSource->GiveFeedback( *_pdwEffect & (_dwOKEffects | DROPEFFECT_SCROLL));
+ }
+ else
+ {
+ *_pdwEffect &= (_dwOKEffects | DROPEFFECT_SCROLL);
+
+ hr = _pDropSource->GiveFeedback(*_pdwEffect);
+ }
+
+ if(hr != NOERROR)
+ {
+ // Either we want to change the cursor or some unexpected
+ // error has occurred.
+
+ if (DRAGDROP_S_USEDEFAULTCURSORS == GetScode(hr))
+ {
+ _pcddcDefault->SetCursor(*_pdwEffect);
+ }
+ else
+ {
+ DDDebugOut((DEB_ERROR,
+ "CDragOperation::HandleFeedBack Feedback FAILED %x\n", hr));
+
+ fResult = FALSE;
+
+ _hrDragResult = hr;
+ }
+ }
+
+ DDDebugOut((DEB_ITRACE, "%p OUT CDragOperation::HandleFeedBack ( %lx )\n",
+ this, fResult));
+
+ return fResult;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CDragOperation::DragOver
+//
+// Synopsis: Tell the target we are dragging over and process the result
+//
+// Returns: TRUE - continue drag operation
+// FALSE - error or time to drop
+//
+// Algorithm: Call the target's drag over if there is one and then
+// get the sources feedback to update the cursor accordingly.
+//
+// History: dd-mmm-yy Author Comment
+// 04-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CDragOperation::DragOver(void)
+{
+ VDATEHEAP();
+
+ DDDebugOut((DEB_ITRACE, "%p _IN CDragOperation::DragOver ( )\n", this));
+
+ // Default the result of the function to continue the loop for
+ // drag and drop.
+ BOOL fResult = TRUE;
+
+ // Local holder for errors.
+ HRESULT hr;
+
+ if (_pDropTarget != NULL)
+ {
+ // Keep effect in a local variable to save indirections
+ // in this routine.
+ *_pdwEffect = _dwOKEffects;
+
+ hr = _pDropTarget->DragOver(_grfKeyState, _cpt.GetPOINTL(), _pdwEffect);
+
+ // Get feedback from source & update cursor if necessary
+ fResult = HandleFeedBack(hr);
+ }
+
+ DDDebugOut((DEB_ITRACE, "%p OUT CDragOperation::DragOver ( %lx )\n",
+ this, fResult));
+
+ return fResult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CDragOperation::HandleMessages
+//
+// Synopsis: Handle windows messages
+//
+// Returns: TRUE - continue drag operation
+// FALSE - error or time to drop
+//
+// Algorithm: Check for any windows message. If the message is a mouse
+// message then record the new position of the mouse. If it
+// is a key message, the record whether escape has been pushed.
+// If this is any other message, then dispatch it. Repeat this
+// process until the scroll interval has been exceeded.
+//
+// History: dd-mmm-yy Author Comment
+// 04-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+BOOL CDragOperation::HandleMessages(void)
+{
+ VDATEHEAP();
+
+ DDDebugOut((DEB_ITRACE, "%p _IN CDragOperation::HandleMessages ( )\n",
+ this));
+
+
+ // Message buffer
+ MSG msg;
+
+ // Default result of function to continue
+ BOOL fResult = TRUE;
+
+ // Capture all messages (i.e. modal loop).
+ // Process all input messages, dispatch other messages
+ //
+ // Note:we must NOT loop here until a hardware message comes in
+ // scrolling will not work.
+ // * yielding is important since other apps need to run
+ // * look for mouse messages first since these are the most
+ // impotant
+
+ // Flag for whether we peeked a message
+ BOOL fMsg;
+
+ UINT uTimer = SetTimer(NULL, 0, s_wScrollInt, NULL);
+
+ do
+ {
+ fMsg = FALSE;
+
+ // Note: the order of peek is important - further messages can show up
+ // in the last peek
+
+ // If we looked for mouse messages first, we might never pick up
+ // WM_QUIT or keyboard messages (because by the time we finished
+ // processing the mouse message another might be on the queue).
+ // So, we check for WM_QUIT and keyboard messages first.
+
+ if (PeekMessage(&msg, 0, WM_QUIT, WM_QUIT, PM_REMOVE | PM_NOYIELD) ||
+ PeekMessage(&msg, 0, WM_KEYFIRST, WM_KEYLAST,
+ PM_REMOVE | PM_NOYIELD) ||
+ PeekMessage(&msg, 0, WM_SYSKEYDOWN, WM_SYSKEYUP,
+ PM_REMOVE | PM_NOYIELD) ||
+ PeekMessage(&msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) ||
+ PeekMessage(&msg, 0, WM_NCMOUSEFIRST, WM_NCMOUSELAST,
+ PM_REMOVE | PM_NOYIELD) ||
+ PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD))
+ {
+ fMsg = TRUE;
+
+
+
+ if (msg.message == WM_QUIT)
+ {
+ // Quit message so we are done.
+ PostQuitMessage(msg.wParam);
+
+ // We are going exiting so the error doesn't matter too much
+ _hrDragResult = ResultFromScode(E_UNSPEC);
+
+ // Make sure we break out of the loop
+ fResult = FALSE;
+ }
+ else if ((msg.message >= WM_KEYFIRST &&
+ msg.message <= WM_KEYLAST) ||
+ (msg.message >= WM_SYSKEYDOWN &&
+ msg.message <= WM_SYSKEYUP))
+ {
+ // Pull all keyboard messages from the queue - this keeps
+ // the keyboard state in sync with the user's actions
+
+ // We use a do/while so that we process the message we've
+ // already peeked.
+
+ do
+ {
+ // We only really pay attention to the escape key and dump
+ // any other key board messages.
+ if ((msg.message == WM_KEYDOWN
+ || msg.message == WM_SYSKEYDOWN)
+ && msg.wParam == VK_ESCAPE)
+ {
+ // Esc pressed: Cancel
+ _fEscapePressed = TRUE;
+ }
+ }
+ while (PeekMessage(&msg, 0, WM_KEYFIRST, WM_KEYLAST,
+ PM_REMOVE | PM_NOYIELD) ||
+ PeekMessage(&msg, 0, WM_SYSKEYDOWN, WM_SYSKEYUP,
+ PM_REMOVE | PM_NOYIELD));
+
+ DWORD grfKeyState; // temp variable for key state
+
+ // get the key state don't change the button states!!
+ grfKeyState = GetControlKeysState(FALSE) |
+ (_grfKeyState &
+ (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON));
+
+ // if the keyboard state is unchanged, then don't exit
+ // this loop (as that will result in DragOver being called).
+ // If we call DragOver for each keyboard message, then
+ // performance is unacceptably slow.
+
+ if ((grfKeyState == _grfKeyState) && !_fEscapePressed)
+ {
+ fMsg = FALSE;
+ }
+ else
+ {
+ DDDebugOut((DEB_ITRACE, "Updating key state\n"));
+ _grfKeyState = grfKeyState;
+ }
+ }
+ else if (msg.message >= WM_MOUSEFIRST &&
+ msg.message <= WM_MOUSELAST)
+ {
+ // we may not have the focus (e.g. if we are the Chicago
+ // shell). Therefore, we won't ever get any WM_KEYDOWN
+ // messages. Double check the esc key status here
+
+ if( GetKeyState(VK_ESCAPE) < 0 )
+ {
+ _fEscapePressed = TRUE;
+ }
+
+ // We got a mouse move message - we skip all the mouse messages
+ // till we get to the last one. The point here is that
+ // because of the length of DragOver calls, we can get behind
+ // in processing messages which causes odd things to happen
+ // on the screen.
+ if (WM_MOUSEMOVE == msg.message)
+ {
+ MSG msg2;
+
+ // Keep processing mouse move messages till there
+ // aren't any more.
+ // if PeekMessage returns true update the original msg.
+ while(PeekMessage(&msg2, 0, WM_MOUSEMOVE, WM_MOUSEMOVE,
+ PM_REMOVE))
+ {
+ msg = msg2;
+ }
+
+ }
+
+
+ // Record position of the mouse
+ _cpt.Set(msg.pt.x, msg.pt.y);
+
+ // set mouse button state here
+ _grfKeyState = GetControlKeysStateOfParam(msg.wParam);
+
+ }
+ else if (msg.message >= WM_NCMOUSEFIRST &&
+ msg.message <= WM_NCMOUSELAST)
+ {
+ // Nothing we need to do for these NC mouse actions
+ NULL;
+ }
+ else if ( (msg.message == WM_TIMER) && (msg.wParam == uTimer) )
+ {
+ // Our timer was triggered. We need to recheck the keyboard
+ // state just in case it has changed. This is important for
+ // the Chicago shell--if it doesn't have focus, then we won't
+ // get any WM_KEYDOWN message (just mouse moves).
+
+ _grfKeyState = GetControlKeysState(FALSE) | (_grfKeyState &
+ (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON));
+
+ if( GetKeyState(VK_ESCAPE) < 0 )
+ {
+ _fEscapePressed = TRUE;
+ }
+
+ // go ahead and fall out of the loop so we call DragOver
+ // (our timeout expired).
+ }
+ else
+ {
+ // Dispatch all other messages
+ DispatchMessage(&msg);
+ fMsg = FALSE;
+ }
+ }
+ else
+ {
+ WaitMessage();
+ }
+
+ // we have to leave the loop periodicially since apps
+ // might rely on on it the DragOver is called freqeuntly.
+ } while (!fMsg);
+
+ // Get rid of the timer we created for the loop
+ KillTimer(NULL, uTimer);
+
+ DDDebugOut((DEB_ITRACE, "%p OUT CDragOperation::HandleMessages ( %lx )\n",
+ this, fResult));
+
+
+ return fResult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CDragOperation::CompleteDrop
+//
+// Synopsis: Complete the drag/drop operation
+//
+// Returns: Result of operation
+//
+// Algorithm: If there is a target and we have decided to drop, then
+// drop. Otherwise, release the target and return whatever
+// the other result of the operation was.
+//
+// History: dd-mmm-yy Author Comment
+// 04-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HRESULT CDragOperation::CompleteDrop(void)
+{
+ VDATEHEAP();
+
+ DDDebugOut((DEB_ITRACE, "%p _IN CDragOperation::CompleteDrop ( )\n",
+ this));
+
+ // Stop the mouse capture in case a dialog box is thrown up.
+ ReleaseCapture();
+
+ if (_pDropTarget != NULL)
+ {
+ // Caller is Drag/Drop aware
+ // and indicated it might accept drop
+
+ // The drop source replies DRAG_S_DROP if the user has
+ // released the left mouse button. However, we may be over
+ // a drop target which has refused a drop (via the feedback
+ // DROPEFFECT_NONE). Thus, both the drop source and drop
+ // target need to agree before we commit the drop.
+
+ if ((DRAGDROP_S_DROP == GetScode(_hrDragResult))
+ && (*_pdwEffect != DROPEFFECT_NONE))
+ {
+ // We are going to try to drop
+ *_pdwEffect = _dwOKEffects;
+
+ HRESULT hr = _pDropTarget->Drop(_pDataObject, _grfKeyState,
+ _cpt.GetPOINTL(), _pdwEffect);
+
+ if (FAILED(hr))
+ {
+ // If drop actually failed in the last stage, let the
+ // caller know that this happened.
+ _hrDragResult = hr;
+ }
+
+
+ }
+ else
+ {
+ *_pdwEffect = DROPEFFECT_NONE;
+ _pDropTarget->DragLeave();
+
+ }
+
+ _pDropTarget->Release();
+ _pDropTarget = NULL;
+ }
+ else
+ {
+ *_pdwEffect = DROPEFFECT_NONE;
+ }
+
+ DDDebugOut((DEB_ITRACE, "%p OUT CDragOperation::CompleteDrop ( %lx )\n",
+ this, _hrDragResult));
+
+ return _hrDragResult;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: RegisterDragDrop
+//
+// Synopsis: Registers a drop target
+//
+// Arguments: [hwnd] -- a handle to the drop target window
+// [pDropTarget] -- the IDropTarget interface for the window
+//
+// Returns: HRESULT
+//
+// Algorithm: We ask compobj (via AssignEndpoinProperty) to put an
+// endpoint ID publicly available on the window handle. Then
+// we put the IDropTarget pointer on the window as a private
+// property (see the notes at the beginning of this file).
+//
+// History: dd-mmm-yy Author Comment
+// 06-Apr-94 ricksa Added tracing
+// 16-Jan-94 alexgo pDropTarget is now AddRef'ed
+// 11-Jan-94 alexgo added VDATEHEAP, converted to RPC-style
+// drag drop.
+// 06-Dec-93 alexgo commented
+//
+// Notes: By AddRef'ing the pDropTarget pointer, we are changing
+// the semantics of the 16bit code (which did not do an
+// AddRef).
+//
+//--------------------------------------------------------------------------
+#pragma SEG(RegisterDragDrop)
+STDAPI RegisterDragDrop(HWND hwnd, LPDROPTARGET pDropTarget)
+{
+
+ VDATEHEAP();
+
+ HRESULT hresult = NOERROR;
+
+#ifndef _MAC
+ OLETRACEIN((API_RegisterDragDrop, PARAMFMT("hwnd= %h, pDropTarget= %p"),
+ hwnd, pDropTarget));
+
+ DDDebugOut((DEB_ITRACE, "%p _IN RegisterDragDrop ( %lx %p )\n",
+ NULL, hwnd, pDropTarget));
+
+
+ if (!IsValidInterface(pDropTarget))
+ {
+ hresult = ResultFromScode(E_INVALIDARG);
+ goto RegisterDragDrop_exit;
+ }
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IDropTarget,(IUnknown **)&pDropTarget);
+
+ if (!IsWindow(hwnd))
+ {
+ hresult = ResultFromScode(DRAGDROP_E_INVALIDHWND);
+ goto RegisterDragDrop_exit;
+ }
+
+ // HACK: We need to add this atom every time RegisterDragDrop
+ // is called because 16-bit Word does not call RevokeDragDrop
+ // and user will automatically clean-up this atom if Word is the
+ // first app run, and then exited before another app calls
+ // RegisterDragDrop.
+ g_aEndpointHack = GlobalAddAtom(ENDPOINT_PROP_NAME);
+
+ if (GetProp(hwnd, (LPCWSTR)g_aDropTarget))
+ {
+ hresult = ResultFromScode(DRAGDROP_E_ALREADYREGISTERED);
+ goto RegisterDragDrop_exit;
+ }
+
+ // first assign an RPC endpoint to the window
+ if( (hresult = AssignEndpointProperty(hwnd)) != NOERROR )
+ {
+ goto RegisterDragDrop_exit;
+ }
+
+ if (!SetProp(hwnd, (LPCWSTR)g_aDropTarget, (HANDLE)pDropTarget))
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // Add a reference to the object since we are holding on to it.
+ pDropTarget->AddRef();
+
+RegisterDragDrop_exit:
+
+ DDDebugOut((DEB_ITRACE, "%p OUT RegisterDragDrop ( %lx )\n",
+ NULL, hresult));
+
+ OLETRACEOUT((API_RegisterDragDrop, hresult));
+
+#endif // !_MAC
+ return hresult;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: RevokeDragDrop
+//
+// Synopsis: Unregisters a window as a drop target
+//
+// Arguments: [hwnd] -- the window to unregister
+//
+// Returns: HRESULT
+//
+// Algorithm: Removes the two window properties set by
+// RegisterDragDrop
+//
+// History: dd-mmm-yy Author Comment
+// 06-Apr-94 ricksa added tracing
+// 16-Jan-94 alexgo added a Release to the drag drop
+// pointer to match the AddRef in
+// RegisterDragDrop.
+// 11-Jan-94 alexgo converted to RPC-style drag drop,
+// added VDATEHEAP macro
+// 06-Dec-93 alexgo commented
+//
+// Notes: the DropTarget->Release call changes the semantics of
+// this function from the 16bit version (see Notes: for
+// RegisterDragDrop).
+//
+//--------------------------------------------------------------------------
+#pragma SEG(RevokeDragDrop)
+STDAPI RevokeDragDrop(HWND hwnd)
+{
+HRESULT hr = NOERROR;
+DWORD dwAssignAptID;
+
+ VDATEHEAP();
+
+
+#ifndef _MAC
+ OLETRACEIN((API_RevokeDragDrop, PARAMFMT("hwnd= %h"), hwnd));
+
+ DDDebugOut((DEB_ITRACE, "%p _IN RevokeDragDrop ( %lx )\n", NULL, hwnd));
+
+ LPDROPTARGET pDropTarget;
+
+ if (!IsWindow(hwnd))
+ {
+ hr = ResultFromScode(DRAGDROP_E_INVALIDHWND);
+ goto RevokeDragDrop_exit;
+ }
+
+ if ((pDropTarget = (LPDROPTARGET)RemoveProp(hwnd, (LPCWSTR)g_aDropTarget))
+ == NULL)
+ {
+ hr = ResultFromScode(DRAGDROP_E_NOTREGISTERED);
+ goto RevokeDragDrop_exit;
+ }
+
+ // Ask compobj to remove the endpoint ID it placed on the window.
+ if (SUCCEEDED(UnAssignEndpointProperty(hwnd,&dwAssignAptID)))
+ {
+
+ // Release our reference to the object since we are no longer using it.
+ // NOTE: AddRef came from RegisterDragDrop
+
+ // Warning: Only call Release if we are in the same thread that Registered the DropTarget
+ // Or we are FreeThreading.
+ // Note: AptID == ThreadID if not FreeThreading
+
+ if( (dwAssignAptID == GetCurrentThreadId()) || (!IsApartmentInitialized()) )
+ {
+ pDropTarget->Release();
+ }
+ else
+ {
+ AssertSz(0,"RevokeDragDrop called on wrong thread");
+ hr = RPC_E_WRONG_THREAD;
+ }
+
+ }
+#ifdef _DEBUG
+ else
+ {
+ AssertSz(0,"Failed to Remove EndPoint");
+ }
+#endif // _DEBUG
+
+ // This mirrors the atom added in RegisterDragDrop
+ GlobalDeleteAtom(g_aEndpointHack);
+
+RevokeDragDrop_exit:
+
+ DDDebugOut((DEB_ITRACE, "%p OUT RegisterDragDrop ( %lx )\n", NULL, hr));
+
+ OLETRACEOUT((API_RevokeDragDrop, hr));
+
+#endif // !_MAC
+
+ return hr;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DoDragDrop
+//
+// Synopsis: The main drag'n'drop loop
+//
+// Effects:
+//
+// Arguments: [pDataObject] -- the object to drag
+// [pDropSource] -- the drop source
+// [dwOKEffects] -- effects flags (stuff to draw)
+// [pdwEffect] -- what actually happened in
+// the drag drop attempt
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: See the notes at the beginning of the file
+//
+// History: dd-mmm-yy Author Comment
+// 05-Dec-94 JohannP added stack switching for WIN95
+// 11-Jan-94 alexgo added VDATEHEAP macro, converted to
+// the RPC-style drag drop.
+// 31-Dec-93 erikgav chicago port
+// 06-Dec-93 alexgo formatted
+//
+// Notes: Under Win95 SSAPI(DoDragDrop) gets expanded to SSDoDragDrop.
+// This function is called by DoDragDrop (in stkswtch.cxx)
+// which switches to the 16 bit stack first.
+// IMPORTANT: this function has to be executed on the 16 bit
+// since call back via USER might occur.
+//--------------------------------------------------------------------------
+#pragma SEG(DoDragDrop)
+STDAPI SSAPI(DoDragDrop)(
+ LPDATAOBJECT pDataObject,
+ LPDROPSOURCE pDropSource,
+ DWORD dwOKEffects,
+ DWORD FAR *pdwEffect)
+{
+
+ VDATEHEAP();
+
+ HRESULT hr = NOERROR;
+
+
+
+#ifndef _MAC
+
+ OLETRACEIN((API_DoDragDrop,PARAMFMT("pDataObject= %p, pDropSource= %p, dwOKEffects= %x, pdwEffect= %p"),
+ pDataObject, pDropSource, dwOKEffects, pdwEffect));
+
+ DDDebugOut((DEB_ITRACE,
+ "%p _IN DoDragDrop ( %p %p %lx %p )\n", NULL, pDataObject,
+ pDropSource, dwOKEffects, pdwEffect));
+
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IDataObject,(IUnknown **)&pDataObject);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IDropSource,(IUnknown **)&pDropSource);
+
+ if (IsValidPtrOut(pdwEffect, sizeof(DWORD))
+ && IsValidInterface(pDropSource)
+ && IsValidInterface(pDataObject))
+ {
+
+
+ // Create the object that does all the work.
+ CDragOperation drgop(pDataObject, pDropSource, dwOKEffects, pdwEffect,
+ hr);
+
+
+ // Did the constructor succeeded?
+ if (SUCCEEDED(hr))
+ {
+ // Loop till worker object tells us to stop
+ for (;;)
+ {
+
+ // Update target based on new window position
+ if (!drgop.UpdateTarget())
+ {
+ // Error so we are done
+ break;
+ }
+
+
+ // Notify
+ if (!drgop.DragOver())
+ {
+ break;
+ }
+ // Handle any messages we get in the mean time
+ if (!drgop.HandleMessages())
+ {
+ break;
+ }
+
+ } // end for loop
+
+ hr = drgop.CompleteDrop();
+ }
+
+ }
+ else
+ {
+ // Invalid argument
+ hr = ResultFromScode(E_INVALIDARG);
+ }
+
+ DDDebugOut((DEB_ITRACE, "%p OUT DoDragDrop ( %lx )\n", NULL, hr));
+
+ OLETRACEOUT((API_DoDragDrop, hr));
+
+#endif // !_MAC
+
+
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDropTarget::CDropTarget
+//
+// Synopsis: constructor for the CDropTarget class
+//
+// Effects:
+//
+// Arguments: [hwnd31] -- the hwnd of the Win3.1 drop target
+// may be NULL
+// [hwndOLE] -- the hwnd of the OLE drop target
+// [dwEffectLast] -- the last effect given the the current
+// drop target that we are to emulate
+// [pdo] -- a pointer to the main drag drop class
+// [hDDInfo] -- handle to cached drag drag info
+//
+//
+// Requires: hwnd31 *must* be a handle to a valid Win3.1 drop source
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: initializes variables
+//
+// History: dd-mmm-yy Author Comment
+// 20-Oct-94 alexgo author
+// 08-Jan-95
+//
+// Notes: there are two ways of determining if a given hwnd is
+// a valid Win3.1 drop target:
+// 1. send a WM_QUERYDROPOBJECT message for a TRUE/FALSE
+// reply
+// 2. check the extended style bits for WS_EX_ACCEPTFILES
+//
+// if ptarget is non-NULL, then the specific window to which
+// it belongs is *not* guaranteed to be the same window as
+// hwndtarget. hwndtarget is the window that is registered as
+// a Win3.1 target. All that is guaranteed is that the ole
+// target and hwndtarget are in the same window hierarchy.
+//
+//--------------------------------------------------------------------------
+
+CDropTarget::CDropTarget( HWND hwnd31, HWND hwndOLE, DWORD dwEffectLast,
+ CDragOperation *pdo, DDInfo hDDInfo )
+{
+ _crefs = 1;
+
+ _hwndOLE = hwndOLE;
+ _hwnd31 = hwnd31;
+ _hDDInfo = hDDInfo;
+
+ _dwEffectLast = dwEffectLast;
+
+ _pdo = pdo; // pointer to the current drag operation class
+
+#if DBG ==1
+
+ // now do some checking (see Notes above)
+
+ if( hwnd31 )
+ {
+ LONG exstyle;
+
+ exstyle = GetWindowLong(hwnd31, GWL_EXSTYLE);
+
+ // strictly speaking, an app could process the WM_QUERYDROPOBJECT
+ // message itself (and thus, not set the extended style bits).
+ // However, this should be considered an application bug; the
+ // documentation states that apps should call DragAcceptFiles,
+ // which will set the WS_EX_ACCEPTFILES bit
+
+ Assert( (exstyle & WS_EX_ACCEPTFILES) );
+ }
+
+#endif // DBG ==1
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDropTarget::~CDropTarget
+//
+// Synopsis: frees the cached drag drop info handle
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 08-Jan-95 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CDropTarget::~CDropTarget()
+{
+ if( _hDDInfo )
+ {
+ FreeDragDropInfo(_hDDInfo);
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDropTarget::QueryInterface
+//
+// Synopsis: returns available interfaces on this object
+//
+// Effects:
+//
+// Arguments: [riid] -- the requested interface
+// [ppv] -- where to put the interface
+//
+// Requires:
+//
+// Returns: E_UNEXPECTED
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDropTarget
+//
+// Algorithm: CDropTarget is only used internally by OLE's drag drop code.
+// It should never do a QI.
+//
+// History: dd-mmm-yy Author Comment
+// 20-Oct-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDropTarget::QueryInterface( REFIID riid, LPVOID * ppv )
+{
+ (void)riid; // unused;
+ (void)ppv; // unused;
+
+ AssertSz(0, "Unexpected QI to CDropTarget");
+
+ return E_UNEXPECTED;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDropTarget::AddRef
+//
+// Synopsis: increments the reference count
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG, the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDropTarget
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 20-Oct-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDropTarget::AddRef( void )
+{
+ VDATEHEAP();
+
+ DDDebugOut((DEB_ITRACE, "%p _IN CDropTarget::AddRef ( )\n", this));
+
+ _crefs++;
+
+ DDDebugOut((DEB_ITRACE, "%p OUT CDropTarget::AddRef ( %ld )\n", this,
+ _crefs));
+
+ return _crefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDropTarget::Release
+//
+// Synopsis: decrements the reference count
+//
+// Effects: may delete 'this' object
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG, the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDropTarget
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 20-Oct-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDropTarget::Release( void )
+{
+ ULONG crefs;
+
+ VDATEHEAP();
+
+ DDDebugOut((DEB_ITRACE, "%p _IN CDropTarget::Release ( )\n", this));
+
+ crefs = --_crefs;
+
+ if( crefs == 0)
+ {
+ DDDebugOut((DEB_ITRACE, "DELETING CDropTarget %p\n", this));
+ delete this;
+ }
+
+ DDDebugOut((DEB_ITRACE, "%p OUT CDropTarget::Release ( %ld )\n",
+ this, crefs));
+
+ return crefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDropTarget::DragEnter
+//
+// Synopsis: sets the window up for drag drop
+//
+// Effects:
+//
+// Arguments: [pDataObject] -- the data object to drop
+// [grfKeyState] -- the current keyboard state
+// [pt] -- the cursor point
+// [pdwEffect] -- where to return the drag drop effect
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDropTarget
+//
+// Algorithm: should never be called. DragEnter is always called
+// via GetDropTarget
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo eliminated
+// 20-Oct-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDropTarget::DragEnter( IDataObject * pDataObject,
+ DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect )
+{
+ AssertSz(0, "DragEnter unexpectedly called!");
+
+ return E_UNEXPECTED;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDropTarget::DragOver
+//
+// Synopsis: called while the mouse is over a given window
+//
+// Effects:
+//
+// Arguments: [grfKeyState] -- the state of the keyboard
+// [ptl] -- the position of the cursor
+// [pdwEffect] -- the drag drop effect
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDropTarget
+//
+// Algorithm: If an OLE target is available, then we forward the call.
+// If the target says DROPEFFECT_NONE, then we go ahead
+// and return DROPEFFECT_COPY if a Win31 target window is
+// available.
+//
+// If there is no OLE target and we have a Win3.1 target,
+// then we go ahead and return DROPEFFECT_COPY.
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-94 alexgo converted to PrivDragDrop protocol
+// 20-Oct-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDropTarget::DragOver( DWORD grfKeyState, POINTL ptl,
+ DWORD *pdwEffect)
+{
+ HRESULT hresult = NOERROR;
+
+ VDATEHEAP();
+
+
+ DDDebugOut((DEB_ITRACE, "%p _IN CDropTarget::DragOver ( %lx , %lx "
+ ", %lx )\n", this, grfKeyState, &ptl, *pdwEffect));
+
+ if( _hwndOLE )
+ {
+ hresult = PrivDragDrop(_hwndOLE, DRAGOP_OVER, NULL, NULL, grfKeyState,
+ ptl, pdwEffect, NULL, &_hDDInfo);
+
+ _dwEffectLast = *pdwEffect;
+
+ if( _hwnd31 )
+ {
+ // we only want to stomp on the effect if the DragOver call
+ // succeeded. If the call failed, then just assume that a
+ // Win3.1 drop would fail as well.
+
+ if( hresult == NOERROR && *pdwEffect == DROPEFFECT_NONE )
+ {
+ *pdwEffect = DROPEFFECT_COPY;
+ }
+ }
+ }
+ else if ( _hwnd31 )
+ {
+ *pdwEffect = DROPEFFECT_COPY;
+ }
+
+
+ DDDebugOut((DEB_ITRACE, "%p OUT CDropTarget::DragOver ( %lx ) [ "
+ "%lx ]\n", this, hresult, *pdwEffect));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDropTarget::DragLeave
+//
+// Synopsis: called when the cursor leaves the current target window
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDropTarget
+//
+// Algorithm: Forwards the DragLeave call to the OLE-drop target
+// (if it exists).
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-94 alexgo converted to PrivDragDrop protocol
+// 20-Oct-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDropTarget::DragLeave()
+{
+ HRESULT hresult = NOERROR;
+ static POINTL ptl = {0, 0};
+
+ VDATEHEAP();
+
+ DDDebugOut((DEB_ITRACE, "%p _IN CDropTarget::DragLeave ( )\n",
+ this));
+
+ if( _hwndOLE )
+ {
+ hresult = PrivDragDrop(_hwndOLE, DRAGOP_LEAVE, NULL, NULL, NULL,
+ ptl, NULL, NULL, &_hDDInfo);
+ }
+
+ DDDebugOut((DEB_ITRACE, "%p OUT CDropTarget::DragLeave ( %lx )\n",
+ this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDropTarget::Drop
+//
+// Synopsis: called if the user lets go of the mouse button while
+// over a drop target
+//
+// Effects:
+//
+// Arguments: [pDataObject] -- the data object to use
+// [grfKeyState] -- the keyboard state
+// [ptl] -- the current mouse position
+// [pdwEffect] -- where to return cursor effect feedback
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDropTarget
+//
+// Algorithm: If there is an OLE-target available, then we first forward
+// the drop request to it. If the call fails
+// (or DROPEFFECT_NONE is returned), then we try the Win31
+// drop by posting a WM_DROPFILES message to the Win31 target
+// window (ifit exists).
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-94 alexgo converted to PrivDragDrop protocol
+// 20-Oct-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDropTarget::Drop( IDataObject *pDataObject,
+ DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect )
+{
+ STGMEDIUM medium;
+ FORMATETC formatetc;
+ HRESULT hresult = E_FAIL;
+ IFBuffer DOBuffer = _pdo->GetDOBuffer();
+
+
+ VDATEHEAP();
+
+ DDDebugOut((DEB_ITRACE, "%p _IN CDropTarget::Drop ( %p , %lx , ",
+ "%p , %lx )\n", this, pDataObject, grfKeyState, &ptl, *pdwEffect));
+
+
+ // we don't forward Drop calls to the target if the last effect
+ // is DROPEFFECT_NONE. It is important that we check for this because
+ // to DoDragDrop 'normally' would not call Drop if the last effect
+ // was DROPEFFECT_NONE. However, this target wrapper will stomp
+ // pdwEffect and return DROPEFFECT_COPY instead of DROPEFFECT_NONE.
+
+ if( _hwndOLE && _dwEffectLast != DROPEFFECT_NONE )
+ {
+ hresult = PrivDragDrop(_hwndOLE, DRAGOP_DROP, DOBuffer, pDataObject,
+ grfKeyState, ptl, pdwEffect,
+ GetPrivateClipboardWindow(CLIP_QUERY), &_hDDInfo);
+ }
+ else if( _hwndOLE )
+ {
+ // if the 'real' drop effect is NONE, then we need to call
+ // DragLeave here before going on to post the WM_DROPFILES
+ // message. Otherwise, the app that is both an OLE and Win31
+ // and has been returning DROPEFFECT_NONE will never get a
+ // Drop or DragLeave call (which is necessary to terminate
+ // the OLE2 drag protocol). Capone in particular is sensitive
+ // to this.
+
+ *pdwEffect = DROPEFFECT_NONE;
+ hresult = DragLeave();
+ }
+
+
+ if( (hresult != NOERROR || *pdwEffect == DROPEFFECT_NONE) &&
+ (hresult != S_FALSE) &&
+ (_hwnd31) )
+ {
+ medium.tymed = TYMED_NULL;
+ INIT_FORETC(formatetc);
+ formatetc.cfFormat = CF_HDROP;
+ formatetc.tymed = TYMED_HGLOBAL;
+
+ hresult = pDataObject->GetData(&formatetc, &medium);
+
+ if( hresult == NOERROR )
+ {
+ // we need to fixup the mouse point coordinates in the CF_HDROP
+ // data. The point point should be in client coordinates
+ // (whereas IDropTarget::Drop takes screen coordinates)
+
+ DROPFILES *pdf = (DROPFILES *)GlobalLock(medium.hGlobal);
+ POINT pt;
+
+ pt.x = ptl.x;
+ pt.y = ptl.y;
+
+ if( pdf )
+ {
+
+ // we also need to set the non-client (NC) flag of the
+ // dropfile data. This lets the app do different behaviour
+ // depending on whether the drop point is in the client or
+ // non-client area (Word6, for example, opens the file if on
+ // non-client area, otherwise makes a package object).
+
+ pdf->fNC = IsNCDrop(_hwnd31, pt);
+
+ if( ScreenToClient(_hwnd31, &pt) )
+ {
+ pdf->pt.x = pt.x;
+ pdf->pt.y = pt.y;
+ }
+ else
+ {
+ LEDebugOut((DEB_WARN, "WARNING: CF_HDROP pt coords"
+ "not updated!!\n"));
+ ; // don't do anything
+ }
+
+
+ GlobalUnlock(medium.hGlobal);
+ }
+ else
+ {
+ LEDebugOut((DEB_WARN, "WARNING: OUT OF MEMORY!\n"));
+ ; // don't do anything
+ }
+
+
+ if( PostMessage(_hwnd31, WM_DROPFILES,
+ (WPARAM)medium.hGlobal, 0) )
+ {
+ *pdwEffect = DROPEFFECT_COPY;
+ }
+ else
+ {
+ // PostMessage failed, so free the data
+ ReleaseStgMedium(&medium);
+ *pdwEffect = DROPEFFECT_NONE;
+ }
+ }
+ }
+
+ DDDebugOut((DEB_ITRACE, "%p OUT CDropTarget::Drop ( %lx ) [ %lx ]\n",
+ this, hresult, *pdwEffect));
+
+ return hresult;
+}
diff --git a/private/ole32/ole232/drag/filelist.mk b/private/ole32/ole232/drag/filelist.mk
new file mode 100644
index 000000000..a461fa741
--- /dev/null
+++ b/private/ole32/ole232/drag/filelist.mk
@@ -0,0 +1,49 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = drag.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CPPFILES = \
+ .\drag.cpp \
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PFILE =
+
+
+!include $(CAIROLE)\ole232\ole.mk
diff --git a/private/ole32/ole232/drag/ido.cpp b/private/ole32/ole232/drag/ido.cpp
new file mode 100644
index 000000000..92e34a776
--- /dev/null
+++ b/private/ole32/ole232/drag/ido.cpp
@@ -0,0 +1,1501 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: ido.cpp
+//
+// Contents: Special data object implementation to optimize drag/drop
+//
+// Classes: SSharedFormats
+// CDragDataObject
+// CDragEnum
+//
+// Functions: CreateDragDataObject
+// CreateDragDataObject
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 ricksa Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#include <utils.h>
+#include <dragopt.h>
+
+// Format for name of shared memory
+OLECHAR szSharedMemoryTemplate[] = OLESTR("DragDrop%lx");
+
+// Maximum size of string for name of shared memory. This is the size of the
+// template plus the maximum number of hex digits in a long.
+const int DRAG_SM_NAME_MAX = sizeof(szSharedMemoryTemplate)
+ + sizeof(DWORD) * 2;
+
+// Useful function for getting an enumerator
+HRESULT wGetEnumFormatEtc(
+ IDataObject *pDataObj,
+ DWORD dwDirection,
+ IEnumFORMATETC **ppIEnum);
+
+//+-------------------------------------------------------------------------
+//
+// Struct: SSharedFormats
+//
+// Purpose: Is used for accessing formats in shared memory
+//
+// History: dd-mmm-yy Author Comment
+// 26-Sep-94 ricksa Created
+//
+//--------------------------------------------------------------------------
+struct SSharedFormats
+{
+ DWORD _cFormats;
+ FORMATETC _FormatEtc[1];
+};
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDragDataObject
+//
+// Purpose: Server side data object for drag that creates enumerator
+// for shared formats.
+//
+// Interface: QueryInterface
+// AddRef
+// Release
+// GetData
+// GetDataHere
+// QueryGetData
+// GetCanonicalFormatEtc
+// SetData
+// EnumFormatEtc
+// DAdvise
+// DUnadvise
+// EnumDAdvise
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Notes: This class only exists for return the enumerator. For
+// all other operations it will simply pass the operation on
+// to the real data object.
+//
+//--------------------------------------------------------------------------
+class CDragDataObject : public IDataObject, public CPrivAlloc
+{
+public:
+ CDragDataObject(
+ void *pvMarshaledDataObject,
+ DWORD dwSmId);
+
+ ~CDragDataObject(void);
+
+ //
+ // IUnknown
+ //
+ STDMETHODIMP QueryInterface(
+ REFIID riid,
+ void **ppvObject);
+
+ STDMETHODIMP_(ULONG) AddRef(void);
+
+ STDMETHODIMP_(ULONG) Release(void);
+
+ //
+ // IDataObject
+ //
+ STDMETHODIMP GetData(
+ FORMATETC *pformatetcIn,
+ STGMEDIUM *pmedium);
+
+ STDMETHODIMP GetDataHere(
+ FORMATETC *pformatetc,
+ STGMEDIUM *pmedium);
+
+ STDMETHODIMP QueryGetData(
+ FORMATETC *pformatetc);
+
+ STDMETHODIMP GetCanonicalFormatEtc(
+ FORMATETC *pformatectIn,
+ FORMATETC *pformatetcOut);
+
+ STDMETHODIMP SetData(
+ FORMATETC *pformatetc,
+ STGMEDIUM *pmedium,
+ BOOL fRelease);
+
+ STDMETHODIMP EnumFormatEtc(
+ DWORD dwDirection,
+ IEnumFORMATETC **ppenumFormatEtc);
+
+ STDMETHODIMP DAdvise(
+ FORMATETC *pformatetc,
+ DWORD advf,
+ IAdviseSink *pAdvSink,
+ DWORD *pdwConnection);
+
+ STDMETHODIMP DUnadvise(DWORD dwConnection);
+
+ STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise);
+
+private:
+
+ IDataObject * GetRealDataObjPtr(void);
+
+ ULONG _cRefs;
+
+ void * _pvMarshaledDataObject;
+
+ IDataObject * _pIDataObject;
+
+ DWORD _dwSmId;
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDragEnum
+//
+// Purpose: Enumerator created above to enumerate shared formats.
+//
+// Interface: QueryInterface
+// AddRef
+// Release
+// Next
+// Skip
+// Reset
+// Clone
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Notes: This class only enumerates things from shared memory
+// when the drag/drop operation was started.
+//
+//--------------------------------------------------------------------------
+class CDragEnum : public IEnumFORMATETC, public CPrivAlloc
+{
+public:
+
+ //
+ // IUnknown
+ //
+ STDMETHODIMP QueryInterface(
+ REFIID riid,
+ void **ppvObject);
+
+ STDMETHODIMP_(ULONG) AddRef(void);
+
+ STDMETHODIMP_(ULONG) Release(void);
+
+ //
+ // IEnumFORMATETC
+ //
+ STDMETHODIMP Next(
+ ULONG celt,
+ FORMATETC *rgelt,
+ ULONG *pceltFetched);
+
+ STDMETHODIMP Skip(ULONG celt);
+
+ STDMETHODIMP Reset(void);
+
+ STDMETHODIMP Clone(IEnumFORMATETC **ppenum);
+
+private:
+
+ friend CDragDataObject;
+
+ // Used when unmarshaling
+ CDragEnum(DWORD dwSharedMemoryId, HRESULT& rhr);
+
+ // Used by Clone operation
+ CDragEnum(
+ HANDLE hSharedMemory,
+ DWORD _cOffset,
+ HRESULT& rhr);
+
+ ~CDragEnum(void);
+
+ HRESULT MapSharedReadMemory(void);
+
+ DWORD _cRefs;
+
+ DWORD _cOffset;
+
+ SSharedFormats * _pSharedFormats;
+
+ DWORD _dwSharedMemoryId;
+
+ HANDLE _hSharedMemory;
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::CDragDataObject
+//
+// Synopsis: Create server side object for drag
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CDragDataObject::CDragDataObject(void *pvMarshaledDataObject, DWORD dwSmId)
+ : _cRefs(1), _pvMarshaledDataObject(pvMarshaledDataObject), _dwSmId(dwSmId),
+ _pIDataObject(NULL)
+{
+ // Header does all the work
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::~CDragDataObject
+//
+// Synopsis: Free any resources connected with this object
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note:
+//
+//--------------------------------------------------------------------------
+CDragDataObject::~CDragDataObject(void)
+{
+ // Release held pointer since we no longer need it.
+ if (_pIDataObject)
+ {
+ _pIDataObject->Release();
+ }
+
+ // this memory was allocated in RemPrivDragDrop, getif.cxx
+ if( _pvMarshaledDataObject )
+ {
+ PrivMemFree(_pvMarshaledDataObject);
+ }
+
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::GetRealDataObjPtr
+//
+// Synopsis: Get the pointer to the real data object from the client
+//
+// Returns: NULL - could not unmarshal drag source's data object
+// ~NULL - pointer to drag source's data object
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+IDataObject *CDragDataObject::GetRealDataObjPtr(void)
+{
+ if (_pIDataObject == NULL)
+ {
+ _pIDataObject = UnmarshalDragDataObject(_pvMarshaledDataObject);
+
+ LEERROR(!_pIDataObject, "Unable to unmarshal dnd data object");
+ }
+
+ return _pIDataObject;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::QueryInterface
+//
+// Synopsis: Get new interface
+//
+// Arguments: [riid] - interface id of requested interface
+// [ppvObject] - where to put the new interface pointer
+//
+// Returns: NOERROR - interface was instantiated
+// E_FAIL - could not unmarshal source's data object
+// other - some error occurred.
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note:
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragDataObject::QueryInterface(
+ REFIID riid,
+ void **ppvObject)
+{
+ if(IsEqualIID(riid, IID_IDataObject))
+ {
+ *ppvObject = this;
+ AddRef();
+ return NOERROR;
+ }
+
+ return (GetRealDataObjPtr() != NULL)
+ ? _pIDataObject->QueryInterface(riid, ppvObject)
+ : E_FAIL;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::AddRef
+//
+// Synopsis: Create server side object for drag
+//
+// Returns: Current reference count
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CDragDataObject::AddRef(void)
+{
+ DDDebugOut((DEB_ITRACE, "ADDREF == %d\n", _cRefs + 1));
+ return ++_cRefs;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::Release
+//
+// Synopsis: Decrement reference count to the object
+//
+// Returns: Current reference count to the object
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CDragDataObject::Release(void)
+{
+ ULONG cRefs = --_cRefs;
+
+ DDDebugOut((DEB_ITRACE, "RELEASE == %d\n", cRefs));
+
+ if (cRefs == 0)
+ {
+ delete this;
+ }
+
+ return cRefs;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::GetData
+//
+// Synopsis: Create server side object for drag
+//
+// Arguments: [pformatetcIn] - format for requested data
+// [pmedium] - storage medium
+//
+// Returns: NOERROR - operation was successful
+// Other - operation failed
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note: This just forwards the operation to the source data object
+// if possible.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragDataObject::GetData(
+ FORMATETC *pformatetcIn,
+ STGMEDIUM *pmedium)
+{
+ return (GetRealDataObjPtr() != NULL)
+ ? _pIDataObject->GetData(pformatetcIn, pmedium)
+ : E_FAIL;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::GetDataHere
+//
+// Synopsis: Create server side object for drag
+//
+// Arguments: [pformatetc] - format for requested data
+// [pmedium] - storage medium
+//
+// Returns: NOERROR - operation was successful
+// Other - operation failed
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note: This just forwards the operation to the source data object
+// if possible.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragDataObject::GetDataHere(
+ FORMATETC *pformatetc,
+ STGMEDIUM *pmedium)
+{
+ return (GetRealDataObjPtr() != NULL)
+ ? _pIDataObject->GetDataHere(pformatetc, pmedium)
+ : E_FAIL;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::QueryGetData
+//
+// Synopsis: Create server side object for drag
+//
+// Arguments: [pformatetc] - format to verify
+//
+// Returns: NOERROR - operation was successful
+// Other - operation failed
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note: This just forwards the operation to the source data object
+// if possible.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragDataObject::QueryGetData(FORMATETC *pformatetc)
+{
+ return (GetRealDataObjPtr() != NULL)
+ ? _pIDataObject->QueryGetData(pformatetc)
+ : E_FAIL;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::GetCanonicalFormatEtc
+//
+// Synopsis: Create server side object for drag
+//
+// Arguments: [pformatetcIn] - input format
+// [pformatetcOut] - output format
+//
+// Returns: NOERROR - operation was successful
+// Other - operation failed
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note: This just forwards the operation to the source data object
+// if possible.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragDataObject::GetCanonicalFormatEtc(
+ FORMATETC *pformatetcIn,
+ FORMATETC *pformatetcOut)
+{
+ return (GetRealDataObjPtr() != NULL)
+ ? _pIDataObject->GetCanonicalFormatEtc(pformatetcIn, pformatetcOut)
+ : E_FAIL;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::SetData
+//
+// Synopsis: Create server side object for drag
+//
+// Arguments: [pformatetc] - format for set
+// [pmedium] - medium to use
+// [fRelease] - who releases
+//
+// Returns: NOERROR - operation was successful
+// Other - operation failed
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note: This just forwards the operation to the source data object
+// if possible.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragDataObject::SetData(
+ FORMATETC *pformatetc,
+ STGMEDIUM *pmedium,
+ BOOL fRelease)
+{
+ return (GetRealDataObjPtr() != NULL)
+ ? _pIDataObject->SetData(pformatetc, pmedium, fRelease)
+ : E_FAIL;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::EnumFormatEtc
+//
+// Synopsis: Create server side object for drag
+//
+// Arguments: [dwDirection] - direction of formats either set or get
+// [ppenumFormatEtc] - where to put enumerator
+//
+// Returns: NOERROR - operation succeeded.
+//
+// Algorithm: If format enumerator requested is for a data get, the
+// create our private enumerator object otherwise pass
+// the request to the real data object.
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note: For the data set direction, we just use the data object of
+// the drop source.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragDataObject::EnumFormatEtc(
+ DWORD dwDirection,
+ IEnumFORMATETC **ppenumFormatEtc)
+{
+ HRESULT hr;
+
+ // Create our enumerator
+ if (dwDirection == DATADIR_GET)
+ {
+ // In the data get case we use our overridden enumerator.
+ // This s/b the typical case with Drag and Drop.
+ hr = E_OUTOFMEMORY;
+
+ CDragEnum *pDragEnum = new CDragEnum(_dwSmId, hr);
+
+ if (hr == NOERROR)
+ {
+ *ppenumFormatEtc = pDragEnum;
+ }
+ else
+ {
+ delete pDragEnum;
+ }
+ }
+ else
+ {
+ // Call through to the real data object because this is the
+ // set case. In general, this won't happen during Drag and Drop.
+ hr = (GetRealDataObjPtr() != NULL)
+ ? _pIDataObject->EnumFormatEtc(dwDirection, ppenumFormatEtc)
+ : E_FAIL;
+ }
+
+ return hr;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::DAdvise
+//
+// Synopsis: Create server side object for drag
+//
+// Arguments: [pformatetc] - format to be advised on
+// [advf] - type of advise
+// [pAdvSink] - advise to notify
+// [pdwConnection] - connection id for advise
+//
+// Returns: NOERROR - operation was successful
+// Other - operation failed
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note: This just forwards the operation to the source data object
+// if possible.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragDataObject::DAdvise(
+ FORMATETC *pformatetc,
+ DWORD advf,
+ IAdviseSink *pAdvSink,
+ DWORD *pdwConnection)
+{
+ return (GetRealDataObjPtr() != NULL)
+ ? _pIDataObject->DAdvise(pformatetc, advf, pAdvSink, pdwConnection)
+ : E_FAIL;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::DUnadvise
+//
+// Synopsis: Create server side object for drag
+//
+// Arguments: [dwConnection] - connection id for advise
+//
+// Returns: NOERROR - operation was successful
+// Other - operation failed
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note: This just forwards the operation to the source data object
+// if possible.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragDataObject::DUnadvise(DWORD dwConnection)
+{
+ return (GetRealDataObjPtr() != NULL)
+ ? _pIDataObject->DUnadvise(dwConnection)
+ : E_FAIL;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragDataObject::EnumDAdvise
+//
+// Synopsis: Create server side object for drag
+//
+// Arguments: [ppenumAdvise] - where to put the enumerator
+//
+// Returns: NOERROR - operation was successful
+// Other - operation failed
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note: This just forwards the operation to the source data object
+// if possible.
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
+{
+ return (GetRealDataObjPtr() != NULL)
+ ? _pIDataObject->EnumDAdvise(ppenumAdvise)
+ : E_FAIL;
+}
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragEnum::CDragEnum
+//
+// Synopsis: Create enumerator object from server data object
+//
+// Arguments: [dwSharedMemoryId] - shared memory id
+// [rhr] - error result
+//
+// Algorithm: Initalize the object and then open the shared memory
+// segment and then pass the rest of the work on to
+// MapSharedMemory to get the memory mapped in.
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+CDragEnum::CDragEnum(DWORD dwSharedMemoryId, HRESULT& rhr)
+ : _cRefs(1), _cOffset(0), _dwSharedMemoryId(dwSharedMemoryId),
+ _hSharedMemory(NULL), _pSharedFormats(NULL)
+{
+ // Open the shared memory
+ OLECHAR szSharedMemoryName[DRAG_SM_NAME_MAX];
+
+ wsprintf(szSharedMemoryName, szSharedMemoryTemplate, dwSharedMemoryId);
+
+ // Create the shared memory object
+ _hSharedMemory = OpenFileMapping(FILE_MAP_READ, FALSE, szSharedMemoryName);
+
+ rhr = MapSharedReadMemory();
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragEnum::CDragEnum
+//
+// Synopsis: Create enumerator for Clone operation
+//
+// Arguments: [hSharedMemory] - handle to shared memory for formats
+// [cOffset] - current offset in the enumeration
+// [rhr] - error result if any
+//
+// Algorithm: Initialize the object and then dupicate the input handle.
+// Then pass the rest of the work on to MapSharedReadMemory
+// to get the memory mapped in.
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note:
+//
+//--------------------------------------------------------------------------
+CDragEnum::CDragEnum(HANDLE hSharedMemory, DWORD cOffset, HRESULT& rhr)
+ : _cRefs(1), _cOffset(cOffset), _dwSharedMemoryId(0), _hSharedMemory(NULL),
+ _pSharedFormats(NULL)
+{
+
+ // Duplicate the handle
+ DuplicateHandle(GetCurrentProcess(), hSharedMemory,
+ GetCurrentProcess(), &_hSharedMemory, 0, FALSE, DUPLICATE_SAME_ACCESS);
+
+ rhr = MapSharedReadMemory();
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragEnum::~CDragEnum
+//
+// Synopsis: Free reference to memory for formats
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note:
+//
+//--------------------------------------------------------------------------
+CDragEnum::~CDragEnum(void)
+{
+ // Free mapped memory if it got mapped.
+ if (_pSharedFormats != NULL)
+ {
+ UnmapViewOfFile(_pSharedFormats);
+ }
+
+ // Close file mapping if it got created.
+ if (_hSharedMemory != NULL)
+ {
+ CloseHandle(_hSharedMemory);
+ }
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragEnum::MapSharedReadMemory
+//
+// Synopsis: Map in the shared memory containing the formats
+//
+// Returns: NOERROR - could map in memory or no formats available
+//
+// Algorithm: If we have a handle to the shared memory, then map the
+// memory in.
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note:
+//
+//--------------------------------------------------------------------------
+HRESULT CDragEnum::MapSharedReadMemory(void)
+{
+ if (_hSharedMemory != NULL)
+ {
+ // Map in the shared memory
+ _pSharedFormats = (SSharedFormats *) MapViewOfFile(_hSharedMemory,
+ FILE_MAP_READ, 0, 0, 0);
+ }
+
+ // It's OK to have a null shared memory handle (indicates that no
+ // formats were available. Not that if we're out of memory, returning
+ // NOERROR here is going to mask that condition. However, we'll
+ // fail soon enough anyway.
+
+ return NOERROR;
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragEnum::QueryInterface
+//
+// Synopsis: Return requested interface
+//
+// Arguments: [riid] - interface id for output interface
+// [ppvObject] - where to put output interface pointer
+//
+// Returns: NOERROR - could return the interface requested
+// E_NOINTERFACE - could not instantiate requested interface.
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note:
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragEnum::QueryInterface(
+ REFIID riid,
+ void **ppvObject)
+{
+ // Assume error to avoid the implicit goto of an else clause.
+ HRESULT hr = E_NOINTERFACE;
+
+ // Our enumerator only knows about two interfaces.
+ if(IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IEnumFORMATETC))
+ {
+ *ppvObject = this;
+ AddRef();
+ hr = NOERROR;
+ }
+
+ return hr;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragEnum::AddRef
+//
+// Synopsis: Add a reference to the interface
+//
+// Returns: Current count of references
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CDragEnum::AddRef(void)
+{
+ return ++_cRefs;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragEnum::Release
+//
+// Synopsis: Release a reference to the enumerator
+//
+// Returns: The current reference count
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CDragEnum::Release(void)
+{
+ // Remember to copy reference count out because memory might go
+ // away on the release.
+ ULONG cRefs = --_cRefs;
+
+ if (cRefs == 0)
+ {
+ delete this;
+ }
+
+ return cRefs;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragEnum::Next
+//
+// Synopsis: Return an array of formats requested
+//
+// Arguments: [celt] - number requested to return
+// [rgelt] - array to hold returned items
+// [pceltFetched] - actual number returned.
+//
+// Returns: NOERROR - number requested returned
+// S_FALSE - less than requested returned
+// E_OUTOFMEMORY - could not allocate memory to hold data
+//
+// Algorithm: Validate the input parameters. Then calculate the number
+// to return by taking the minimum of the items left to
+// enumerate and the number of items requested. Then copy
+// all the formatetc's from shared memory to the output
+// buffer. Then for each formatetc that contains a pointer
+// to a DVDEVICETARGET, allocate a new target buffer and
+// then copy the DVDEVICETARGET from shared memory. There
+// is a trick here where in the formatetc in shared memory
+// the ptd field is really an offset from the beginning of
+// shared memory rather than an actual pointer. This is so
+// we don't have to depend on the base of the shared memory.
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note:
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragEnum::Next(
+ ULONG celt,
+ FORMATETC *rgelt,
+ ULONG *pceltFetched)
+{
+ if (celt == 0)
+ {
+ LEDebugOut((DEB_ERROR,
+ "CDragEnum::Next requested entries returned is invalid\n"));
+ return E_INVALIDARG;
+ }
+
+ if (!IsValidPtrOut(rgelt, sizeof(FORMATETC) * celt))
+ {
+ LEDebugOut((DEB_ERROR,
+ "CDragEnum::Next array to return entries invalid\n"));
+ return E_INVALIDARG;
+ }
+
+ if (pceltFetched)
+ {
+ if (!IsValidPtrOut(pceltFetched, sizeof(*pceltFetched)))
+ {
+ LEDebugOut((DEB_ERROR,
+ "CDragEnum::Next count to return invalid\n"));
+ return E_INVALIDARG;
+ }
+ }
+ else if (celt != 1)
+ {
+ LEDebugOut((DEB_ERROR,
+ "CDragEnum::count requested != 1 & count fetched is NULL\n"));
+ return E_INVALIDARG;
+
+ }
+
+ // handle the case where we have no data
+ if( _pSharedFormats == NULL )
+ {
+ if( pceltFetched )
+ {
+ *pceltFetched = 0;
+ }
+ return S_FALSE;
+ }
+
+
+ // Calculate the maximum number that we can return
+ ULONG cToReturn = (_cOffset < _pSharedFormats->_cFormats)
+ ? _pSharedFormats->_cFormats - _cOffset
+ : 0;
+
+ // Are we going to return any?
+ if (cToReturn != 0)
+ {
+ // If the number requested is less that the maximum number
+ // we can return, the we will return all requested/
+ if (celt < cToReturn)
+ {
+ cToReturn = celt;
+ }
+
+ // Copy the FormatEtcs
+ memcpy(&rgelt[0], &_pSharedFormats->_FormatEtc[_cOffset],
+ sizeof(FORMATETC) * cToReturn);
+
+ // Allocate and copy the DVTARGETDEVICE - a side effect of this
+ // loop is that our offset pointer gets updated to its value at
+ // the completion of the routine.
+ for (DWORD i = 0; i < cToReturn; i++, _cOffset++)
+ {
+ if (_pSharedFormats->_FormatEtc[_cOffset].ptd != NULL)
+ {
+ // Create a pointer to the device target - Remember when
+ // we created the shared memory block we overroad the ptd
+ // field of the FORMATETC so that it is now the offset
+ // from the beginning of the shared memory. We reverse
+ // that here so we can copy the data for the consumer.
+ DVTARGETDEVICE *pdvtarget = (DVTARGETDEVICE *)
+ ((BYTE *) _pSharedFormats
+ + (DWORD) _pSharedFormats->_FormatEtc[_cOffset].ptd);
+
+ // Allocate a new DVTARGETDEVICE
+ DVTARGETDEVICE *pdvtargetNew = (DVTARGETDEVICE *)
+ CoTaskMemAlloc(pdvtarget->tdSize);
+
+ // Did the memory allocation succeed?
+ if (pdvtargetNew == NULL)
+ {
+ // NO! - so clean up. First we free any device targets
+ // that we might have allocated.
+ for (DWORD j = 0; j < i; j++)
+ {
+ if (rgelt[j].ptd != NULL)
+ {
+ CoTaskMemFree(rgelt[j].ptd);
+ }
+ }
+
+ // Then we restore the offset to its initial state
+ _cOffset -= i;
+
+ return E_OUTOFMEMORY;
+ }
+
+ // Copy the old targetDevice to the new one
+ memcpy(pdvtargetNew, pdvtarget, pdvtarget->tdSize);
+
+ // Update output FORMATETC pointer
+ rgelt[i].ptd = pdvtargetNew;
+ }
+ }
+ }
+
+ if (pceltFetched)
+ {
+ *pceltFetched = cToReturn;
+ }
+
+ return (cToReturn == celt) ? NOERROR : S_FALSE;
+
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragEnum::Skip
+//
+// Synopsis: Skip the input number of entries in the list
+//
+// Arguments: [celt] - count of entries to skip
+//
+// Returns: NOERROR - number could be skipped
+// S_FALSE - skip greater than the end of the list
+//
+// Algorithm: Bump offset by count input. If this is greater than or
+// equal to the number of formats, return S_FALSE otherwise
+// return NOERROR.
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragEnum::Skip(ULONG celt)
+{
+ HRESULT hr = NOERROR;
+
+ _cOffset += celt;
+
+ if( _pSharedFormats == NULL )
+ {
+ _cOffset = 0;
+ hr = S_FALSE;
+ }
+ else if (_cOffset >= _pSharedFormats->_cFormats)
+ {
+ _cOffset = _pSharedFormats->_cFormats;
+ hr = S_FALSE;
+ }
+
+ return hr;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragEnum::Reset
+//
+// Synopsis: Reset enumeration index to the beginning
+//
+// Returns: NOERROR
+//
+// Algorithm: Just set our offset back to 0.
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragEnum::Reset(void)
+{
+ _cOffset = 0;
+ return NOERROR;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragEnum::Clone
+//
+// Synopsis: Create a duplicate copy of this enumeration.
+//
+// Arguments: [ppenum] - where to return the enumerator
+//
+// Returns: S_OK - could create the enumerator copy
+// E_OUTOFMEMORY - could not create the copy
+//
+// Algorithm: Call constructor for enumerator that dups the handle to the
+// shared memory.
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDragEnum::Clone(IEnumFORMATETC **ppenum)
+{
+ HRESULT hr = E_OUTOFMEMORY;
+
+ CDragEnum *pDragEnum = new CDragEnum(_hSharedMemory, _cOffset, hr);
+
+ return hr;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CreateDragDataObject
+//
+// Synopsis: Create the server side data object for format enumeration
+//
+// Arguments: [pvMarshaledDataObject] - marshaled real data object buffer
+// [dwSmId] - id for the shared memory
+// [ppIDataObject] - output data object.
+//
+// Returns: NOERROR - could create the object
+// E_OUTOFMEMORY - could not create the object
+//
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+// Note:
+//
+//--------------------------------------------------------------------------
+HRESULT CreateDragDataObject(
+ void *pvMarshaledDataObject,
+ DWORD dwSmId,
+ IDataObject **ppIDataObject)
+{
+ CDragDataObject *pDragDataObject =
+ new CDragDataObject(pvMarshaledDataObject, dwSmId);
+
+ if (pDragDataObject != NULL)
+ {
+ *ppIDataObject = pDragDataObject;
+ }
+
+ // The only thing that can fail here is the memory allocation of
+ // CDragDataObject thus there are only two error returns.
+ return (pDragDataObject != NULL) ? NOERROR : E_OUTOFMEMORY;
+}
+
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CreateDragDataObject
+//
+// Synopsis: Put the data formats for the data object in shared memory.
+//
+// Arguments: [pIDataObject] - data object to use for formats.
+//
+// Returns: NULL - could not create enumerator
+// ~NULL - handle to shared memory
+//
+// Algorithm: First calculate the size of the required memory by enumerating
+// the formats. Then allocate the memory and map it into the
+// process. Then enumerate the formats again placing them in
+// the shared memory. Finally, map the memory out of the
+// process and return the handle the file mapping to the
+// caller.
+//
+// History: dd-mmm-yy Author Comment
+// 30-Sep-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+HANDLE CreateSharedDragFormats(IDataObject *pIDataObject)
+{
+
+ // Handle to the shared memory for formats
+ HANDLE hSharedMemory = NULL;
+
+ // Pointer to share memory
+ SSharedFormats *pSharedFormats = NULL;
+
+ // Size required for the shared memory
+ DWORD dwSize = 0;
+
+ // Count of FORMATETCs contained in the enumerator
+ DWORD cFormatEtc = 0;
+
+ // Buffer for name of shared memory for enumerator
+ OLECHAR szSharedMemoryName[DRAG_SM_NAME_MAX];
+
+ // Work pointer to shared memory for storing FORMATETCs from the enumerator.
+ FORMATETC *pFormatEtc;
+
+ // Work ptr to shared memory for storing DVTARGETDEVICEs from enumerator.
+ BYTE *pbDvTarget = NULL;
+
+ //
+ // Calculate the size of the formats
+ //
+
+ // Get the format enumerator
+ IEnumFORMATETC *penum = NULL;
+ HRESULT hr = wGetEnumFormatEtc(pIDataObject, DATADIR_GET, &penum);
+ FORMATETC FormatEtc;
+
+ if( hr != NOERROR )
+ {
+ // not all apps support enumerators (yahoo). Also, we may
+ // have run out of memory or encountered some other error.
+
+ DDDebugOut((DEB_WARN, "WARNING: Failed to get formatetc enumerator"
+ ", error code (%lx)", hr));
+ goto exitRtn;
+ }
+
+ // Enumerate the data one at a time because this is a local operation
+ // and it make the code simpler.
+ while ((hr = penum->Next(1, &FormatEtc, NULL)) == S_OK)
+ {
+ // Bump the entry count
+ cFormatEtc++;
+
+ // Bump the size by the size of another FORMATETC.
+ dwSize += sizeof(FORMATETC);
+
+ // Is there a device target associated with the FORMATETC?
+ if (FormatEtc.ptd != NULL)
+ {
+ // Bump the size required by the size of the target device
+ dwSize += FormatEtc.ptd->tdSize;
+
+ // Free the target device
+ CoTaskMemFree(FormatEtc.ptd);
+ }
+ }
+
+ // HRESULT s/b S_FALSE at the end of the enumeration.
+ if (hr != S_FALSE)
+ {
+ goto errRtn;
+ }
+
+ // the enumerator may have been empty
+
+ if( dwSize == 0 )
+ {
+ DDDebugOut((DEB_WARN, "WARNING: Empty formatetc enumerator"));
+ goto exitRtn;
+ }
+
+
+ dwSize += sizeof(SSharedFormats); // add space for _cFormats and one exter FORMATETC for FALSE in enumerator.
+
+ //
+ // Create shared memory for the type enumeration
+ //
+
+ // Build name of shared memory - make it unique by using the thread id.
+ wsprintf(szSharedMemoryName, szSharedMemoryTemplate, GetCurrentThreadId());
+
+ // Create the shared memory object
+ hSharedMemory = CreateFileMapping((HANDLE) 0xFFFFFFFF, NULL,
+ PAGE_READWRITE, 0, dwSize, szSharedMemoryName);
+
+ // Did the file mapping get created?
+ if (hSharedMemory == NULL)
+ {
+ goto errRtn;
+ }
+
+ // Map in the memory
+ pSharedFormats = (SSharedFormats *) MapViewOfFile(
+ hSharedMemory,
+ FILE_MAP_WRITE,
+ 0, // High-order 32 bits of file offset
+ 0, // Low-order 32 bits of file offset
+ 0); // Number of bytes to map; 0 means all.
+
+ // Could we map the memory?
+ if (pSharedFormats == NULL)
+ {
+ goto errRtn;
+ }
+
+ // We can initialize the size of the array now.
+ pSharedFormats->_cFormats = cFormatEtc;
+
+ //
+ // Copy the formats into the shared memory
+ //
+
+ // Get back to the start of the enumeration
+ penum->Reset();
+
+ // This is the pointer to where we will copy the data from the
+ // enumeration.
+ pFormatEtc = &pSharedFormats->_FormatEtc[0];
+
+ // put DvTarget past last valid FormatEtc + 1 to handle S_FALSE enumerator case.
+
+ pbDvTarget = (BYTE *) (&pSharedFormats->_FormatEtc[cFormatEtc + 1]);
+
+ // Loop loading the formats into the shared memory.
+ while (penum->Next(1, pFormatEtc, NULL) != S_FALSE)
+ {
+ // Is there a DVTARGETDEVICE?
+ if (pFormatEtc->ptd != NULL)
+ {
+
+ // Copy the device target data
+ memcpy(pbDvTarget,pFormatEtc->ptd,(pFormatEtc->ptd)->tdSize);
+
+ // Free the target device data
+ CoTaskMemFree(pFormatEtc->ptd);
+
+ // NOTE: For this shared memory structure, we override the
+ // FORMATETC field so that it is that offset to the DVTARGETDEVICE
+ // from the beginning of the shared memory rather than a direct
+ // pointer to the structure. This is because we can't guarantee
+ // the base of shared memory in different processes.
+
+ pFormatEtc->ptd = (DVTARGETDEVICE *)
+ (pbDvTarget - (BYTE *) pSharedFormats);
+
+ // Bump pointer of where to copy target to next available
+ // byte for copy.
+ pbDvTarget += ((DVTARGETDEVICE *) pbDvTarget)->tdSize;
+
+ Assert(dwSize >= (DWORD) (pbDvTarget - (BYTE *) pSharedFormats));
+
+ }
+
+ // Bug#18669 - if dwAspect was set to NULL the 16 bit dlls would
+ // set it to content.
+ if ( (NULL == pFormatEtc->dwAspect) && IsWOWThread() )
+ {
+ pFormatEtc->dwAspect = DVASPECT_CONTENT;
+ pFormatEtc->lindex = -1; // CorelDraw also puts up a lindex of 0
+ }
+
+ // Bump the pointer in the table of FORMATETCs to the next slot
+ pFormatEtc++;
+ }
+
+ Assert( dwSize >= (DWORD) ( (BYTE *) pFormatEtc - (BYTE *) pSharedFormats));
+ Assert( dwSize >= (DWORD) ( (BYTE *) pbDvTarget - (BYTE *) pSharedFormats));
+
+
+ // Successful enumeration always ends with S_FALSE.
+ if (hr == S_FALSE)
+ {
+ goto exitRtn;
+ }
+
+errRtn:
+
+ if (hSharedMemory != NULL)
+ {
+ CloseHandle(hSharedMemory);
+ hSharedMemory = NULL;
+ }
+
+exitRtn:
+
+ if( penum )
+ {
+ // HACK ALERT: Do not release the enumerator if the calling application
+ // was Interleaf 6.0, otherwise they will fault in the release call.
+ if (!IsTaskName(L"ILEAF6.EXE"))
+ {
+ penum->Release();
+ }
+ }
+
+ if (pSharedFormats != NULL)
+ {
+ // Only remote clients will use this memory so we unmap it
+ // out of our address space.
+ UnmapViewOfFile(pSharedFormats);
+ }
+
+ return hSharedMemory;
+}
diff --git a/private/ole32/ole232/drag/makefile b/private/ole32/ole232/drag/makefile
new file mode 100644
index 000000000..1725b5e9a
--- /dev/null
+++ b/private/ole32/ole232/drag/makefile
@@ -0,0 +1,26 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1992.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/ole232/filelist.mk b/private/ole32/ole232/filelist.mk
new file mode 100644
index 000000000..8ffea3b3d
--- /dev/null
+++ b/private/ole32/ole232/filelist.mk
@@ -0,0 +1,88 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = ole232.dll
+
+TARGET_DESCRIPTION = "$(PLATFORM) $(BUILDTYPE) Compound Doc DLL"
+
+RELEASE = 0
+
+COFFBASE = ole232
+
+SUBDIRS = \
+ advise \
+ base \
+ cache \
+ clipbrd \
+ debug \
+ drag \
+ inplace \
+ stdimpl \
+ ole1 \
+ util
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CPPFILES =
+
+CFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+# BE SURE TO CHANGE THIS ONCE MERGED INTO COMMON
+DEFFILE = $(CAIROLE)\ilib\ole232xx.def
+
+LIBS = \
+ $(CAIROLE)\ilib\$(OBJDIR)\compob32.lib \
+ $(CAIROLE)\ilib\$(OBJDIR)\storag32.lib \
+ $(CAIROLE)\ilib\$(OBJDIR)\ole232.lib \
+!if "$(OPSYS)" == "NT1X"
+ $(IMPORT)\nt1x\lib\$(OBJDIR)\shell32.lib
+!elseif "$(OPSYS)" == "NT"
+ $(IMPORT)\nt475\lib\$(OBJDIR)\shell32.lib
+!elseif "$(OPSYS)" == "DOS" && "$(PLATFORM)" == "i386"
+ $(IMPORT)\chicago\lib\shell32.lib \
+ $(IMPORT)\chicago\lib\mpr.lib \
+ $(COMMON)\src\chicago\$(OBJDIR)\chicago.lib
+!endif
+
+!if "$(OPSYS)" == "NT"
+LIBS = $(LIBS) $(CAIROLIB)
+!endif
+
+OBJFILES = \
+!if "$(OPSYS)" == "NT1X"
+ ..\common\$(OBJDIR)\dllentr2.obj \
+!elseif "$(OPSYS)" == "DOS" && "$(PLATFORM)" == "i386"
+ ..\common\$(OBJDIR)\dllentr2.obj \
+!endif
+ .\advise\$(OBJDIR)\advise.lib \
+ .\base\$(OBJDIR)\base.lib \
+ .\cache\$(OBJDIR)\cache.lib \
+ .\clipbrd\$(OBJDIR)\clipbrd.lib \
+ .\debug\$(OBJDIR)\debug.lib \
+ .\drag\$(OBJDIR)\drag.lib \
+ .\inplace\$(OBJDIR)\inplace.lib \
+ .\stdimpl\$(OBJDIR)\stdimpl.lib \
+ .\ole1\$(OBJDIR)\ole1.lib \
+ .\util\$(OBJDIR)\util.lib
+
+
+RCFILES = .\res\ole2w32.rc
+
+RCFLAGS = /i .\res
diff --git a/private/ole32/ole232/inc/cachenod.h b/private/ole32/ole232/inc/cachenod.h
new file mode 100644
index 000000000..292be2a7f
--- /dev/null
+++ b/private/ole32/ole232/inc/cachenod.h
@@ -0,0 +1,229 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// cachenod.h
+//
+// Contents:
+//
+// Classes:
+// CCacheNode
+//
+// Functions:
+//
+// History:
+// 31-Jan-95 t-ScottH add Dump method to CCacheNode (_DEBUG only)
+// add private data member (m_dwPresFlag) to keep
+// track of type of IOlePresObj (_DEBUG only)
+// (CMfObject|CEMfObject|CGenObject)
+// 24-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocation
+// 11/05/93 - ChrisWe - file inspection and cleanup
+// 06/04/93 - SriniK - added support for demand loading and
+// discarding of cachenodes
+// 11/12/92 - SriniK - created
+//
+//-----------------------------------------------------------------------------
+
+#ifndef _CACHENOD_H_
+#define _CACHENOD_H_
+
+//+----------------------------------------------------------------------------
+//
+// Class:
+// CCacheNode
+//
+// Purpose:
+// A cache node encapsulates a presentation object for a single
+// FORMATETC. The implementation includes the advise sink for
+// the presentation object. COleCache maintains a list of these
+// nodes for all the presentations it is caching.
+//
+// Interface:
+// IAdviseSink
+// all notifications are ignored except for OnDataChange
+//
+// CCacheNode -- constructor -- there are two forms, one permits
+// deferred initialization and requires fewer parameters.
+//
+// GetPresObj -- returns a pointer to the presentation object
+// in the cache node, if there is one
+//
+// GetFormatEtc -- returns a constant pointer to the format
+// descriptor for this cache node
+//
+// CopyStatData -- returns a copy of the STATDATA for this node
+//
+// SetAdvf -- sets the advise control flags for this node
+//
+// GetAdvf -- gets the advise control flags for this node
+//
+// SaveCompleted -- alerts the node that the saving of its data
+// is complete that the drawing information might be
+// discarded because it is no longer needed.
+//
+// Delete -- delete this cache node from it's owning cache
+// note there is no public destructor, and this is the
+// only means to eliminate a cache node from its owner
+//
+// Load -- load the cache node from the indicated stream
+//
+// Save -- save the cache node to the indicated stream
+//
+// OnRun -- alert the cache node that the server is running, and
+// that a data object is available
+//
+// OnStop -- alert the cache node that the server has stopped
+//
+// CreatePresObject -- ask the node to create a presentation object
+//
+// Update -- ask the node to update its presentation object
+// from the given data object
+//
+// SetData -- assign a presentation to the cache node
+//
+// Freeze -- freeze the cache node against changes
+//
+// Unfreeze -- unfreeze the cache node against changes
+//
+// GetStm -- get the stream the presentation data is stored in
+//
+// Notes:
+// The standard formats on windows in order of preference
+// are CF_METAFILEPICT, CF_DIB, and CF_BITMAP. On Macintosh,
+// the only standard format is PICT, and it is defined to
+// CF_METAFILEPICT.
+//
+// When a cache node is set up for CF_DIB format, the code
+// considers CF_BITMAP an acceptable substibute if a request
+// to the data object for CF_DIB fails.
+// REVIEW, the presentation object apparently handles the
+// conversion
+//
+// The advise sink here is only used for data advises.
+//
+// REVIEW, this is not thread safe
+//
+// History:
+// 31-Jan-95 t-ScottH add Dump method (_DEBUG only)
+// 11/05/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+class FAR CCacheNode : public IAdviseSink, public CPrivAlloc
+{
+public:
+ // IUnknown methods
+ STDMETHOD(QueryInterface)(REFIID iid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // IAdviseSink methods
+ STDMETHOD_(void,OnDataChange)(FORMATETC FAR* pFormatetc,
+ STGMEDIUM FAR* pStgmed);
+
+ // We won't setup Ole advises, so we will never get these notifications
+ STDMETHOD_(void,OnViewChange)(DWORD aspects, LONG lindex) {}
+ STDMETHOD_(void,OnRename)(IMoniker FAR* pmk) {}
+ STDMETHOD_(void,OnSave)(void) {}
+ STDMETHOD_(void,OnClose)(void) {}
+
+ CCacheNode(COleCache FAR* pOleCache);
+ CCacheNode(LPFORMATETC lpFormatetc, DWORD advf,
+ COleCache FAR* pOleCache);
+
+ INTERNAL_(LPOLEPRESOBJECT) GetPresObj(void);
+ INTERNAL_(void) CopyStatData (STATDATA FAR* lpStatData);
+ INTERNAL_(const FORMATETC FAR *) GetFormatEtc(void);
+ INTERNAL SetAdvf(DWORD dwAdvf);
+ INTERNAL_(DWORD) GetAdvf(void);
+ INTERNAL_(void) SaveCompleted(int iStreamNum, BOOL fDrawCache);
+
+ INTERNAL_(void) Delete(void);
+ INTERNAL Load(LPSTREAM lpstream, int iStreamNum);
+ INTERNAL Save(LPSTORAGE pstgSave, BOOL fSameAsLoad, int iStreamNum,
+ BOOL fDrawCache, BOOL fSaveIfSavedBefore,
+ int FAR* lpCntCachesNotSaved);
+ // REVIEW, fSaveIfSavedBefore, lpCntCachesNotSaved seem totally bogus
+ INTERNAL_(DWORD) OnRun(LPDATAOBJECT lpDataObj);
+ INTERNAL_(void) OnStop(void);
+ INTERNAL CreatePresObject(LPDATAOBJECT lpDataObj, BOOL fConvert);
+ INTERNAL Update(LPDATAOBJECT pDataObj, DWORD grfUpdf);
+
+ INTERNAL SetDataWDO(LPFORMATETC lpForetc, LPSTGMEDIUM lpStgmed,
+ BOOL fRelease, IDataObject * pdo);
+
+ // Most cases of SetData do not need the IDataObject pointer, so as an
+ // alternative to using default parameters, this function wraps
+ // SetDataWDO and passes a NULL along as the data object.
+
+ INTERNAL SetData(LPFORMATETC lpForetc, LPSTGMEDIUM lpStgmed,
+ BOOL fRelease)
+ {
+ return SetDataWDO(lpForetc, lpStgmed, fRelease, NULL);
+ }
+
+ INTERNAL Freeze (void);
+ INTERNAL Unfreeze (void);
+ INTERNAL_(LPSTREAM) GetStm(BOOL fSeekToPresBits, DWORD dwStgAccess);
+
+ #ifdef _DEBUG
+
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+
+ // need to be able to access CCacheNode private data members in the
+ // following debugger extension APIs
+ // this allows the debugger extension APIs to copy memory from the
+ // debuggee process memory to the debugger's process memory
+ // this is required since the Dump method follows pointers to other
+ // structures and classes
+ friend DEBUG_EXTENSION_API(dump_cachenode);
+ friend DEBUG_EXTENSION_API(dump_cachelist_item);
+ friend DEBUG_EXTENSION_API(dump_olecache);
+ friend DEBUG_EXTENSION_API(dump_defobject);
+ friend DEBUG_EXTENSION_API(dump_deflink);
+
+ #endif // _DEBUG
+
+private:
+ ~CCacheNode();
+ INTERNAL_(void) Initialize(DWORD dwAdvf, COleCache FAR* pOleCache);
+ INTERNAL_(void) Uninitialize(void);
+ INTERNAL_(BOOL) QueryFormatSupport(LPDATAOBJECT lpDataObj);
+ INTERNAL SetupAdviseConnection(void);
+ INTERNAL TearDownAdviseConnection(void);
+ inline INTERNAL_(void) NotifyOleCache(BOOL fDirty);
+ INTERNAL CreateOlePresObject(LPOLEPRESOBJECT FAR* ppPresObj,
+ BOOL fMacPict);
+ INTERNAL_(void) SetPresBitsPos(LPSTREAM lpStream);
+
+ ULONG m_refs; // reference count
+
+ FORMATETC m_foretc; // the data format for this cache node
+ DWORD m_advf; // the advise control flags requested for this cache node
+ unsigned short m_usFlag; // flags for the cache node
+# define CCACHENODEF_FROZEN 0x01 /* this cache node is frozen */
+# define CCACHENODEF_DIRTY 0x02 /* this cache node is dirty */
+ DWORD m_dwAdvConnId; // the advise connection ID
+ DWORD m_dwPresBitsPos; // byte offset to presentation bits in stream
+ int m_iStreamNum; // number of the stream with the presentation in it
+ COleCache FAR* m_pOleCache; // owning cache; not ref counted
+ LPDATAOBJECT m_pDataObj; // server object pointer, not ref counted
+ LPOLEPRESOBJECT m_pPresObj; // presentation object
+ LPOLEPRESOBJECT m_pPresObjAfterFreeze;
+ // to hold the data changes that take place after Freeze
+
+ #ifdef _DEBUG
+ // keep track of type of IOlePresObj for use with debugger extensions
+ // only (so we know how much memory to copy)
+ DWORD m_dwPresFlag;
+
+ #define CN_PRESOBJ_GEN 0x00000001
+ #define CN_PRESOBJ_EMF 0x00000010
+ #define CN_PRESOBJ_MF 0x00000100
+
+ #endif // _DEBUG
+};
+
+#endif //_CACHENOD_H_
+
diff --git a/private/ole32/ole232/inc/clipbrd.h b/private/ole32/ole232/inc/clipbrd.h
new file mode 100644
index 000000000..3cd016d4f
--- /dev/null
+++ b/private/ole32/ole232/inc/clipbrd.h
@@ -0,0 +1,185 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// clipbrd.h
+//
+// Contents:
+//
+// Classes:
+// CClipDataObject
+//
+// Functions:
+//
+// History:
+// 17/05/94 - AlexGo - added OleOpenClipboard
+// 16/03/94 - AlexGo - modified for the rewritten clipboard code.
+// 12/08/93 - ChrisWe - continue with file cleanup
+// 12/06/93 - ChrisWe - began file cleanup
+//
+//-----------------------------------------------------------------------------
+
+#ifndef _CLIPBRD_H_
+#define _CLIPBRD_H_
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// ClipboardInitialize, internal
+//
+// Synopsis:
+// Initialize the use of the clipboard.
+//
+// Effects:
+// Registers a window class CLIPBRDWNDCLASS.
+//
+// Arguments:
+// none
+//
+// Returns:
+// TRUE for success; FALSE other wise
+//
+// Notes:
+//
+// History:
+// 12/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+BOOL ClipboardInitialize(void);
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// ClipboardUninitialize, internal
+//
+// Synopsis:
+// Terminates use of the clipboard by OLE, freeing associated
+// resources.
+//
+// Effects:
+// If this is the last reference, unregisters the clipboard
+// window class.
+//
+// Arguments:
+// none
+//
+// Notes:
+//
+// History:
+// 12/06/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+void ClipboardUninitialize(void);
+
+
+// flags used for GetPrivateClipboardWindow
+
+typedef enum tagCLIPWINDOWFLAGS
+{
+ CLIP_QUERY = 0,
+ CLIP_CREATEIFNOTTHERE = 1
+} CLIPWINDOWFLAGS;
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetPrivateClipboardWindow
+//
+// Synopsis: Retrieves (creates if necessary) the private clipboard
+// window associated with the current apartment (thread)
+//
+// Effects:
+//
+// Arguments: fCreate -- if TRUE and no window currently exists,
+// create one
+//
+// Requires:
+//
+// Returns: HWND
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: see description in the code (clipapi.cpp)
+//
+// History: dd-mmm-yy Author Comment
+// 16-Mar-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HWND GetPrivateClipboardWindow( CLIPWINDOWFLAGS fFlags );
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleOpenClipboard (internal)
+//
+// Synopsis: Opens the clipboard
+//
+// Effects:
+//
+// Arguments: [hClipWnd] -- open the clipboard with this window
+// may be NULL.
+// [phClipWnd] -- where to put the clipboard owner
+// may be NULL
+//
+// Requires:
+//
+// Returns: NOERROR: the clipboard was opened successfully
+// CLIPBRD_E_CANT_OPEN: could not open the clipboard
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 17-May-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT OleOpenClipboard( HWND hClipWnd, HWND *phClipWnd );
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ClipSetCaptureForDrag
+//
+// Synopsis: Sets mouse capture mode for a drag operation
+//
+// Arguments: [pdrgop] - pointer to object that handles drag operation
+//
+// Returns: S_OK -- it worked
+// E_FAIL -- unexpected failure occurred.
+//
+// Algorithm: see description in the code (clipapi.cpp)
+//
+// History: dd-mmm-yy Author Comment
+// 21-Apr-94 ricksa created
+//
+//--------------------------------------------------------------------------
+class CDragOperation; // Forward declaration for circular dependencies
+HRESULT ClipSetCaptureForDrag(CDragOperation *pdrgop);
+
+//+-------------------------------------------------------------------------
+//
+// Function: ClipReleaseCaptureForDrag
+//
+// Synopsis: Clean up drag mouse capture
+//
+// Algorithm: see description in the code (clipapi.cpp)
+//
+// History: dd-mmm-yy Author Comment
+// 21-Apr-94 ricksa created
+//
+//--------------------------------------------------------------------------
+void ClipReleaseCaptureForDrag(void);
+
+#endif // _CLIPBRD_H_
+
diff --git a/private/ole32/ole232/inc/create.h b/private/ole32/ole232/inc/create.h
new file mode 100644
index 000000000..ba9cbd3c8
--- /dev/null
+++ b/private/ole32/ole232/inc/create.h
@@ -0,0 +1,76 @@
+#if !defined( _CREATE_H_ )
+#define _CREATE_H_
+
+
+INTERNAL wCreateFromData(IDataObject FAR* lpSrcDataObj, REFIID iid, DWORD renderopt, LPFORMATETC lpFormatEtc, IOleClientSite FAR* lpClientSite, IStorage FAR* lpStg, void FAR* FAR* lplpObj);
+
+INTERNAL wCreateFromDataEx(IDataObject FAR* lpSrcDataObj, REFIID iid, DWORD dwFlags, DWORD renderopt, ULONG cFormats, DWORD FAR* rgAdvf, LPFORMATETC rgFormatEtc, IAdviseSink FAR* lpAdviseSink, DWORD FAR* rgdwConnection, IOleClientSite FAR* lpClientSite, IStorage FAR* lpStg, void FAR* FAR* lplpObj);
+
+INTERNAL wCreateLink(IMoniker FAR* lpmkSrc, REFCLSID clsidLast, IDataObject FAR* lpSrcDataObj, REFIID iid, DWORD renderopt, LPFORMATETC lpFormatEtc, IOleClientSite FAR* lpClientSite, IStorage FAR* lpStg, void FAR* FAR* lplpObj);
+
+INTERNAL wCreateLinkEx(IMoniker FAR* lpmkSrc, REFCLSID clsidLast, IDataObject FAR* lpSrcDataObj, REFIID iid, DWORD dwFlags, DWORD renderopt, ULONG cFormats, DWORD FAR* rgAdvf, LPFORMATETC rgFormatEtc, IAdviseSink FAR* lpAdviseSink, DWORD FAR* rgdwConnection, IOleClientSite FAR* lpClientSite, IStorage FAR* lpStg, void FAR* FAR* lplpObj);
+
+INTERNAL wCreateObject(CLSID rclsid, REFIID iid, IOleClientSite FAR* lpClientSite, IStorage FAR* lpstg, WORD wfStorage, void FAR* FAR* ppv);
+
+INTERNAL wCreateFromFile(LPMONIKER lpmkFile, REFIID iid, DWORD renderopt, LPFORMATETC lpFormatEtc, LPOLECLIENTSITE lpClientSite, LPSTORAGE lpStg, LPLPVOID lplpObj);
+
+INTERNAL wCreateFromFileEx(LPMONIKER lpmkFile,LPDATAOBJECT lpDataObject, REFIID iid, DWORD dwFlags, DWORD renderopt, ULONG cFormats, DWORD FAR* rgAdvf, LPFORMATETC rgFormatEtc, IAdviseSink FAR* lpAdviseSink, DWORD FAR* rgdwConnection, LPOLECLIENTSITE lpClientSite, LPSTORAGE lpStg, LPLPVOID lplpObj);
+
+
+INTERNAL wInitializeCache(IDataObject FAR* lpSrcDataObj, REFCLSID rclsId, DWORD renderopt, LPFORMATETC lpFormatEtc, void FAR* lpNewObj, BOOL FAR* pfCacheNodeCreated = NULL);
+
+INTERNAL wInitializeCacheEx(IDataObject FAR* lpSrcDataObj, REFCLSID rclsid, DWORD renderopt, ULONG cFormats, DWORD FAR* rgAdvf, LPFORMATETC rgFormatEtc, IAdviseSink FAR* lpAdviseSink, DWORD FAR* rgdwConnection, void FAR* lpNewObj, BOOL FAR* pfCacheNodeCreated = NULL);
+
+INTERNAL wGetMonikerAndClassFromFile(LPCOLESTR lpszFileName, BOOL fLink, LPMONIKER FAR* lplpMoniker, BOOL FAR* lpfPackagerMoniker, CLSID FAR* lpClsid,LPDATAOBJECT* lplpDataObject);
+
+INTERNAL wCreatePackage(LPDATAOBJECT lpSrcDataObj, REFIID iid, DWORD renderopt, LPFORMATETC lpFormatEtc, LPOLECLIENTSITE lpClientSite, LPSTORAGE lpStg, BOOL fLink, LPLPVOID lplpObj);
+
+INTERNAL wCreatePackageEx(LPDATAOBJECT lpSrcDataObj, REFIID iid, DWORD dwFlags, DWORD renderopt, ULONG cFormats, DWORD FAR* rgAdvf, LPFORMATETC rgFormatEtc, IAdviseSink FAR* lpAdviseSink, DWORD FAR* rgdwConnection, LPOLECLIENTSITE lpClientSite, LPSTORAGE lpStg, BOOL fLink, LPLPVOID lplpObj);
+
+
+INTERNAL wValidateCreateParams(DWORD dwFlags, DWORD renderopt, ULONG cFormats, DWORD FAR* rgAdvf, LPFORMATETC rgFormatEtc, IAdviseSink FAR* lpAdviseSink, DWORD FAR* rgdwConnection, IOleClientSite FAR* lpClientSite, IStorage FAR* lpStg);
+
+INTERNAL wValidateAdvfEx(ULONG cFormats, DWORD FAR* rgAdvf);
+
+INTERNAL wValidateFormatEtc(DWORD renderopt, LPFORMATETC lpFormatEtc, LPFORMATETC lpMyFormatEtc);
+
+INTERNAL wValidateFormatEtcEx(DWORD renderopt, ULONG FAR* lpcFormats, LPFORMATETC rgFormatEtc, LPFORMATETC lpFormatEtc, LPFORMATETC FAR* lplpFormatEtc, LPBOOL lpfAlloced);
+
+INTERNAL wQueryFormatSupport(LPVOID lpObj, DWORD optrender, LPFORMATETC lpFormatEtc);
+
+INTERNAL wLoadAndInitObject(IDataObject FAR* lpSrcDataObj, REFIID iid, DWORD renderopt, LPFORMATETC lpFormatEtc, IOleClientSite FAR* lpClientSite, IStorage FAR* lpStg, void FAR* FAR* lplpObj);
+
+INTERNAL wLoadAndInitObjectEx(IDataObject FAR* lpSrcDataObj, REFIID iid, DWORD renderopt, ULONG cFormats, DWORD FAR* rgAdvf, LPFORMATETC rgFormatEtc, IAdviseSink FAR* lpAdviseSink, DWORD FAR* rgdwConnection, IOleClientSite FAR* lpClientSite, IStorage FAR* lpStg, void FAR* FAR* lplpObj);
+
+INTERNAL wGetMonikerAndClassFromObject(LPDATAOBJECT lpSrcDataObj, LPMONIKER FAR* lplpmkSrc, CLSID FAR* lpclsid);
+
+INTERNAL wGetEmbeddedDataObject(LPDATAOBJECT FAR* lplpSrcDataObj, BOOL FAR* lpfRelease, DWORD renderopt, LPSTORAGE lpstgDst);
+
+INTERNAL wSaveObjectWithoutCommit(LPUNKNOWN lpUnk, LPSTORAGE lpStg, BOOL fSameAsLoad);
+
+INTERNAL wStuffIconOfFile(LPCOLESTR lpszFile, BOOL fAddLabel, DWORD renderopt, LPFORMATETC lpforetc, LPUNKNOWN lpUnk);
+
+INTERNAL wStuffIconOfFileEx(LPCOLESTR lpszFile, BOOL fAddLabel, DWORD renderopt, ULONG cFormats, LPFORMATETC rgFormatEtc, LPUNKNOWN lpUnk);
+
+
+void wDoLockUnlock(IUnknown FAR* lpUnknown);
+
+STDAPI CreatePackagerMoniker (LPCOLESTR lpszPathName, LPMONIKER FAR* ppmk,BOOL fLink);
+STDAPI CreatePackagerMonikerEx (LPCOLESTR lpszPathName,LPMONIKER lpFileMoniker,BOOL fLink,LPMONIKER FAR* ppmk);
+
+INTERNAL wReturnCreationError(HRESULT hresult);
+INTERNAL_(BOOL) wNeedToPackage(REFCLSID rclsid);
+INTERNAL_(WORD) wQueryEmbedFormats(LPDATAOBJECT lpSrcDataObj,
+ CLIPFORMAT FAR* lpcfFormat);
+INTERNAL_(CLIPFORMAT) wQueryLinkFormats(LPDATAOBJECT lpSrcDataObj);
+
+INTERNAL_(void) wBindIfRunning(LPUNKNOWN lpUnk);
+INTERNAL OleLoadWithoutBinding(LPSTORAGE lpStg, REFIID iid, LPOLECLIENTSITE lpClientSite, LPLPVOID lplpObj);
+
+
+INTERNAL_(BOOL) wQueryUseCustomLink(REFCLSID clsid);
+
+WINOLEAPI CoCreateErrorInfo(ICreateErrorInfo **ppCreateErrorInfo);
+
+#endif // _CREATE_H
+
diff --git a/private/ole32/ole232/inc/dacache.h b/private/ole32/ole232/inc/dacache.h
new file mode 100644
index 000000000..a9d622919
--- /dev/null
+++ b/private/ole32/ole232/inc/dacache.h
@@ -0,0 +1,135 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// dacache.h
+//
+// Classes:
+// CDataAdviseCache
+//
+// Functions:
+//
+// History:
+// 31-Jan-95 t-ScottH add Dump method to CDataAdviseCache class
+// 24-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocation
+// 11/02/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#ifndef _DACACHE_H_
+#define _DACACHE_H_
+
+#ifdef _DEBUG
+#include <dbgexts.h>
+#endif // _DEBUG
+
+#include <map_dwdw.h>
+
+//+----------------------------------------------------------------------------
+//
+// Class:
+// CDataAdviseCache
+//
+// Purpose:
+// A CDataAdviseCache is used to remember data advises across
+// loaded<-->running transitions. The data advise cache holds
+// on to advise sinks that are interested in data, even if there
+// is no data object, because the server is not activated.
+// These advise sinks can be registered with a running data object
+// later on, when it is activated, or they can be Unadvised()
+// if the object is to go inactive.
+//
+// Interface:
+// Advise - add a new advise sink for the indicated data object,
+// if there is one; if no data object, record the
+// advise sink for future use
+//
+// Unadvise - remove an advise sink from the advise sink cache,
+// and from the data object, if there is one
+//
+// EnumAdvise - enumerate all the registered advise sinks
+//
+// ClientToDelegate - Maps a client connection number to a
+// delegate connection number. Client connection numbers
+// are those returned by Advise(), while the delegate
+// connection numbers are those used by the data object
+// itself.
+//
+// EnumAndAdvise - A data object has become newly active (or
+// has just been deactivated.) This will enumerate all
+// the registered advise sinks, and call Advise() (or
+// Unadvise()) on the data object.
+//
+// CreateDataAdviseCache - creates an instance of the
+// CDataAdviseCache; there is no public constructor,
+// because internal data structures must be allocated,
+// and these allocations could fail. There is no way
+// to indicate such a failure when using "new," so
+// clients are required to use this function instead.
+//
+// ~CDataAdviseCache
+//
+// Notes:
+// This is an internal helper class, and does not support any
+// interfaces.
+//
+// Because a connection number must be returned even in the loaded
+// state, there must be two sets of connection numbers: client
+// numbers are "fake" connection numbers returned to the caller;
+// delegate numbers are those returned by the "real" running
+// object. We maintain a map from client numbers to delegate
+// numbers. If not running, our client numbers map to zero.
+// Client numbers also map to zero if the delegate refused the
+// Advise when it began to run. We use a DWORD->DWORD map.
+//
+// History:
+// 31-Jan-95 t-ScottH add Dump method (_DEBUG only)
+// 11/02/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+class FAR CDataAdviseCache : public CPrivAlloc
+{
+public:
+ HRESULT Advise(LPDATAOBJECT pDataObject, FORMATETC FAR* pFetc,
+ DWORD advf, LPADVISESINK pAdvise,
+ DWORD FAR* pdwClient);
+ // first 4 parms are as in DataObject::Advise
+ HRESULT Unadvise(IDataObject FAR* pDataObject, DWORD dwClient);
+ HRESULT EnumAdvise(LPENUMSTATDATA FAR* ppenumAdvise);
+ HRESULT EnumAndAdvise(LPDATAOBJECT pDataObject, BOOL fAdvise);
+ // Advise or Unadvise
+
+ static FARINTERNAL CreateDataAdviseCache(
+ class CDataAdviseCache FAR* FAR* ppDataAdvCache);
+ ~CDataAdviseCache();
+
+ #ifdef _DEBUG
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+
+ // need to be able to access CDataAdviseCache private data members
+ // in the following debugger extension APIs
+ // this allows the debugger extension APIs to copy memory from the
+ // debuggee process memory to the debugger's process memory
+ // this is required since the Dump method follows pointers to other
+ // structures and classes
+ friend DEBUG_EXTENSION_API(dump_defobject);
+ friend DEBUG_EXTENSION_API(dump_deflink);
+ friend DEBUG_EXTENSION_API(dump_dataadvisecache);
+ #endif // _DEBUG
+
+private:
+ CDataAdviseCache();
+ HRESULT ClientToDelegate(DWORD dwClient, DWORD FAR* pdwDelegate);
+
+ LPDATAADVISEHOLDER m_pDAH; // a data advise holder
+ CMapDwordDword m_mapClientToDelegate; // the map of clients to delegates
+
+};
+
+typedef class CDataAdviseCache DATAADVCACHE;
+typedef DATAADVCACHE FAR* LPDATAADVCACHE;
+
+#endif // _DACACHE_H_
+
diff --git a/private/ole32/ole232/inc/daholder.h b/private/ole32/ole232/inc/daholder.h
new file mode 100644
index 000000000..2d5be8981
--- /dev/null
+++ b/private/ole32/ole232/inc/daholder.h
@@ -0,0 +1,179 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: daholder.h
+//
+// Contents: CDAHolder, concrete version of IDataAdviseHolder
+//
+// Classes: CDAHolder
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 06-Feb-95 t-ScottH created - split class definition from
+// cpp file (for debug purposes)
+// - added Dump method to CDAHolder
+//
+//--------------------------------------------------------------------------
+
+#ifndef _DAHOLDER_H_
+#define _DAHOLDER_H_
+
+#ifdef _DEBUG
+#include <dbgexts.h>
+#endif // _DEBUG
+
+//+----------------------------------------------------------------------------
+//
+// Class:
+// CDAHolder
+//
+// Purpose:
+// provides concrete implementation of IDataAdviseHolder
+//
+// Interface:
+// IDataAdviseHolder
+//
+// Notes:
+// REVIEW, not thread safe, under assumption that docs cant be MT
+//
+// Connections are numbered from [1..infinity). We don't use
+// zero to avoid getting caught on someone else's zero init'ed
+// memory. Zero is checked for as a connection number on entry
+// to routines, and rejected. This allows us to use zero as
+// a way to mark unused STATDATA entries in our array.
+//
+// History:
+// 06-Feb-95 t-Scotth added Dump method (_DEBUG only)
+// 01/24/94 - AlexGo - now inherit from CPrivAlloc
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+// NOTE: CDAHolder MUST inherit from IDataAdviseHolder first in order for the
+// DumpCDAHolder function to work since we cast the IDataAdviseHolder as a
+// CDAHolder (if it inherits from IDataAdviseHolder first, then the pointers
+// are the same)
+
+class FAR CDAHolder : public IDataAdviseHolder, public CSafeRefCount
+{
+public:
+ CDAHolder();
+
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (REFIID riid, LPVOID FAR* ppv);
+ STDMETHOD_(ULONG,AddRef) () ;
+ STDMETHOD_(ULONG,Release) ();
+
+ // *** IDataAdviseHolder methods ***
+ STDMETHOD(Advise)(LPDATAOBJECT pDataObj, FORMATETC FAR* pFetc,
+ DWORD advf, IAdviseSink FAR* pAdvSink,
+ DWORD FAR* pdwConnection);
+ STDMETHOD(Unadvise)(DWORD dwConnection);
+ STDMETHOD(EnumAdvise)(IEnumSTATDATA FAR* FAR* ppenumAdvise);
+
+ STDMETHOD(SendOnDataChange)(IDataObject FAR* pDataObject,
+ DWORD dwReserved, DWORD advf);
+
+ // *** debug and dump methods ***
+ #ifdef _DEBUG
+
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+
+ // need to be able to access CDAHolder private data members in the
+ // following debugger extension APIs
+ // this allows the debugger extension APIs to copy memory from the
+ // debuggee process memory to the debugger's process memory
+ // this is required since the Dump method follows pointers to other
+ // structures and classes
+ friend DEBUG_EXTENSION_API(dump_daholder);
+ friend DEBUG_EXTENSION_API(dump_enumstatdata);
+ friend DEBUG_EXTENSION_API(dump_dataadvisecache);
+ friend DEBUG_EXTENSION_API(dump_defobject);
+ friend DEBUG_EXTENSION_API(dump_deflink);
+
+ #endif // _DEBUG
+
+private:
+ ~CDAHolder();
+
+
+ DWORD m_dwConnection; // next connection number to use
+ int m_iSize; // number of stat data elements in array
+ STATDATA FAR *m_pSD; // array of STATDATA elements
+#define CDAHOLDER_GROWBY 5 /* number of entries to grow array by each time */
+
+ SET_A5;
+
+ // the enumerator returned by the EnumAdvise method
+ friend class CEnumSTATDATA;
+};
+
+//+----------------------------------------------------------------------------
+//
+// Class:
+// CEnumSTATDATA
+//
+// Purpose:
+// is the enumerator returned by CDAHolder::Enum
+//
+// Interface:
+// IEnumSTATDATA
+//
+// Notes:
+// Keeps the underlying CDAHolder alive for the lifetime of
+// the enumerator.
+//
+// History:
+// 10/29/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+class CEnumSTATDATA : public IEnumSTATDATA, public CPrivAlloc
+{
+public:
+ CEnumSTATDATA(CDAHolder FAR* pHolder, int iDataStart);
+
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR* ppv);
+ STDMETHOD_(ULONG,AddRef)() ;
+ STDMETHOD_(ULONG,Release)();
+
+ // *** IEnumSTATDATA methods ***
+ STDMETHOD(Next)(ULONG celt, STATDATA FAR * rgelt,
+ ULONG FAR* pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)();
+ STDMETHOD(Clone)(LPENUMSTATDATA FAR* ppenum);
+
+ #ifdef _DEBUG
+
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+
+
+ // need to be able to access CEnumSTATDATA private data members in the
+ // following debugger extension APIs
+ // this allows the debugger extension APIs to copy memory from the
+ // debuggee process memory to the debugger's process memory
+ // this is required since the Dump method follows pointers to other
+ // structures and classes
+ friend DEBUG_EXTENSION_API(dump_enumstatdata);
+
+ #endif // _DEBUG
+
+private:
+ ~CEnumSTATDATA();
+
+ ULONG m_refs; // reference count
+ int m_iDataEnum; // index of the next element to return
+
+ CDAHolder FAR* m_pHolder; // pointer to holder; is ref counted
+
+ SET_A5;
+};
+
+
+
+#endif // _DAHOLDER_H_
diff --git a/private/ole32/ole232/inc/daytona/makefile b/private/ole32/ole232/inc/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/ole232/inc/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/ole232/inc/daytona/sources b/private/ole32/ole232/inc/daytona/sources
new file mode 100644
index 000000000..362fab343
--- /dev/null
+++ b/private/ole32/ole232/inc/daytona/sources
@@ -0,0 +1,65 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = ole232
+
+TARGETNAME= empty
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..\..\inc
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+SOURCES = ..\empty.cxx
+
+!include ..\..\precomp2.inc
+!include ..\sources.inc
diff --git a/private/ole32/ole232/inc/dbgdump.h b/private/ole32/ole232/inc/dbgdump.h
new file mode 100644
index 000000000..87b9ea386
--- /dev/null
+++ b/private/ole32/ole232/inc/dbgdump.h
@@ -0,0 +1,136 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File:
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+//
+//--------------------------------------------------------------------------
+
+#ifndef _DBGDUMP_H
+#define _DBGDUMP_H
+
+#include <le2int.h>
+#include <olecache.h>
+#include <olepres.h>
+#include <oaholder.h>
+#include <dacache.h>
+#include <memstm.h>
+#include <dstream.h>
+
+#define DEB_VERBOSE 0x10000000
+#define NO_PREFIX 0x00000000
+
+#define DUMPTAB " "
+
+
+extern const char szDumpErrorMessage[];
+extern const char szDumpBadPtr[];
+
+class CEnumSTATDATA;
+class CCacheEnumFormatEtc;
+class CClipDataObject;
+class CClipEnumFormatEtc;
+class CDefClassFactory;
+class CDefObject;
+class CDefLink;
+class CEMfObject;
+class CMfObject;
+class CGenObject;
+class CEnumFmt;
+class CEnumFmt10;
+class CEnumVerb;
+
+// Dump structures which fit on one line and prefix not required
+// NOTE: there is no newline character a the end of these char arrays
+extern char *DumpADVFFlags(DWORD dwAdvf);
+
+extern char *DumpATOM(ATOM atom);
+
+extern char *DumpCLSID(REFCLSID clsid);
+
+extern char *DumpCLIPFORMAT(CLIPFORMAT clipformat);
+
+extern char *DumpCMutexSem(CMutexSem *pCMS);
+
+extern char *DumpDVASPECTFlags(DWORD dwAspect);
+
+extern char *DumpFILETIME(FILETIME *pFT);
+
+extern char *DumpHRESULT(HRESULT hresult);
+
+extern char *DumpMonikerDisplayName(IMoniker *pMoniker);
+
+extern char *DumpWIN32Error(DWORD dwError);
+
+// Dump structures which may be multiple lines - take care of prefixes
+// NOTE: the following dumps have newline characters throughout and at the end
+extern char *DumpCACHELIST_ITEM(CACHELIST_ITEM *pCLI, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCCacheEnum(CCacheEnum *pCE, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCCacheEnumFormatEtc(CCacheEnumFormatEtc *pCEFE, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCCacheNode(CCacheNode *pCN, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCClipDataObject(CClipDataObject *pCDO, ULONG ulFLag, int nIndentLevel);
+
+extern char *DumpCClipEnumFormatEtc(CClipEnumFormatEtc *pCEFE, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCDAHolder(IDataAdviseHolder *pIDAH, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCDataAdviseCache(CDataAdviseCache *pDAC, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCDefClassFactory(CDefClassFactory *pDCF, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCDefLink(CDefLink *pDL, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCDefObject(CDefObject *pDO, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCEMfObject(CEMfObject *pEMFO, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCEnumFmt(CEnumFmt *pEF, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCEnumFmt10(CEnumFmt10 *pEF, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCEnumSTATDATA(CEnumSTATDATA *pESD, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCEnumVerb(CEnumVerb *pEV, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCGenObject(CGenObject *pGO, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCMapDwordDword(CMapDwordDword *pMDD, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCMemBytes(CMemBytes *pMB, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCMemStm(CMemStm *pMS, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCMfObject(CMfObject *pMFO, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCOAHolder(COAHolder *pOAH, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCOleCache(COleCache *pOC, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCSafeRefCount(CSafeRefCount *pSRC, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpCThreadCheck(CThreadCheck *pTC, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpFORMATETC(FORMATETC *pFE, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpIOlePresObj(IOlePresObj *pIPO, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpMEMSTM(MEMSTM *pMS, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpSTATDATA(STATDATA *pSD, ULONG ulFlag, int nIndentLevel);
+
+extern char *DumpSTGMEDIUM(STGMEDIUM *pSM, ULONG ulFlag, int nIndentLevel);
+
+#endif // _DBGDUMP_H
diff --git a/private/ole32/ole232/inc/dbgexts.h b/private/ole32/ole232/inc/dbgexts.h
new file mode 100644
index 000000000..cc20db3ea
--- /dev/null
+++ b/private/ole32/ole232/inc/dbgexts.h
@@ -0,0 +1,35 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dbgexts.h
+//
+// Contents: macro for declaration of debugger extensions for friend
+// to each class
+//
+// Classes:
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 03-Feb-95 t-ScottH author
+//
+//--------------------------------------------------------------------------
+
+#ifndef _DBGEXTS_H_
+#define _DBGEXTS_H_
+
+#include <ntsdexts.h>
+
+#define DEBUG_EXTENSION_API(s) \
+ void \
+ s( \
+ HANDLE hCurrentProcess, \
+ HANDLE hCurrentThread, \
+ DWORD dwCurrentPc, \
+ PNTSD_EXTENSION_APIS lpExtensionApis, \
+ LPSTR args \
+ )
+
+#endif // _DBGEXTS_H_
diff --git a/private/ole32/ole232/inc/dirs b/private/ole32/ole232/inc/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/ole232/inc/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/ole232/inc/drag.h b/private/ole32/ole232/inc/drag.h
new file mode 100644
index 000000000..efb06ed6a
--- /dev/null
+++ b/private/ole32/ole232/inc/drag.h
@@ -0,0 +1,433 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: drag.h
+//
+// Contents: Classes used in drag operation
+//
+// Classes: CPoint
+// CDragDefaultCursors
+// CDragOperation
+// CWin31DropTarget
+//
+// History: dd-mmm-yy Author Comment
+// 20-Oct-94 alexgo added CWin31DropTarget to handle Win3.1
+// style drag drop
+// 21-Apr-94 ricksa split out from drag.cpp
+//
+// Notes: This exists as a separate file to facilitate the special
+// processing required for WM_CANCELMODE during drag/drop.
+//
+//--------------------------------------------------------------------------
+
+#ifndef _DRAG_H
+#define _DRAG_H
+
+void DragDropProcessUninitialize(void);
+
+//+-------------------------------------------------------------------------
+//
+// Class: CPoint
+//
+// Purpose: Handles strangness of the POINTL & POINT structures.
+//
+// Interface: Set - set value of data
+// GetPOINT - return a reference to a POINT structure
+// GetPOINTL - return a reference to a POINTL structure
+// GetAddressOfPOINT - return address of point structure
+//
+// History: dd-mmm-yy Author Comment
+// 04-Apr-94 Ricksa Created
+//
+// Notes: This class is created because we have two structures
+// that are exactly the same in Win32 but have different
+// types. This class will have to be modified for use
+// in Win16 if we ever do that again.
+//
+//--------------------------------------------------------------------------
+class CPoint
+{
+public:
+
+ CPoint(void);
+
+ void Set(LONG x, LONG y);
+
+ POINT& GetPOINT(void);
+
+ POINTL& GetPOINTL(void);
+
+ POINT * GetAddressOfPOINT(void);
+
+private:
+
+ POINT _pt;
+
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CPoint::CPoint
+//
+// Synopsis: Initialize object to zero
+//
+// History: dd-mmm-yy Author Comment
+// 04-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CPoint::CPoint(void)
+{
+ _pt.x = 0;
+ _pt.y = 0;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CPoint::Set
+//
+// Synopsis: Set value of structure
+//
+// History: dd-mmm-yy Author Comment
+// 04-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CPoint::Set(LONG x, LONG y)
+{
+ _pt.x = x;
+ _pt.y = y;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CPoint::GetPOINT
+//
+// Synopsis: Return a reference to a POINT type for function calls
+//
+// History: dd-mmm-yy Author Comment
+// 04-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline POINT& CPoint::GetPOINT(void)
+{
+ return _pt;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CPoint::GetPOINTL
+//
+// Synopsis: Return a reference to a POINTL type for function calls
+//
+// History: dd-mmm-yy Author Comment
+// 04-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline POINTL& CPoint::GetPOINTL(void)
+{
+ return *((POINTL *) &_pt);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CPoint::GetAddressOfPOINT
+//
+// Synopsis: Return address of POINT type for function calls
+//
+// History: dd-mmm-yy Author Comment
+// 04-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline POINT *CPoint::GetAddressOfPOINT(void)
+{
+ return &_pt;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDragDefaultCursors
+//
+// Purpose: Handles init/setting default drag cursors
+//
+// Interface: NeedInit - whether object needs to be initialized
+// Init - does initialization
+// SetCursor - sets cursor to appropriate default
+//
+// History: dd-mmm-yy Author Comment
+// 19-Apr-94 Ricksa Created
+//
+// Notes: This class specifically avoids a constructor and depends
+// on the behavior of of static data being initialized to
+// NULL. The reason for this is two fold: (1) it makes start
+// up faster by avoiding a page fault when the constructor
+// would be called and (2) it allows this ole32 to be loaded
+// at boot time before cursors exist.
+//
+//--------------------------------------------------------------------------
+class CDragDefaultCursors : public CPrivAlloc
+{
+public:
+
+ BOOL Init(void);
+
+ void SetCursor(DWORD dwEffect);
+
+ void SetCursorNone(void);
+
+ static CDragDefaultCursors *GetDefaultCursorObject(void);
+
+private:
+
+ enum SCROLL_TYPE {NO_SCROLL, SCROLL};
+
+ enum CURSOR_ID {NO_DROP, MOVE_DROP, COPY_DROP, LINK_DROP};
+
+ HCURSOR ahcursorDefaults[2][4];
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CDragDefaultCursors::SetCursorNone
+//
+// Synopsis: Set the cursor to none
+//
+// History: dd-mmm-yy Author Comment
+// 19-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CDragDefaultCursors::SetCursorNone(void)
+{
+ ::SetCursor(ahcursorDefaults[NO_SCROLL][NO_DROP]);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDragOperation
+//
+// Purpose: Handles breaking down drag operation into managable pieces
+//
+// Interface: UpdateTarget - update where we are trying to drop
+// HandleFeedBack - handle cursor feedback
+// DragOver - handle dragging object over target
+// HandleMessages - Handle windows messages
+// CompleteDrop - Do drop or clean up
+// CancelDrag - notify operation that drag is canceled.
+// ReleaseCapture - release capture on the mouse
+// GetDropTarget - get target for drop
+//
+// History: dd-mmm-yy Author Comment
+// 04-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+class CDragOperation
+{
+public:
+ CDragOperation(
+ LPDATAOBJECT pDataObject,
+ LPDROPSOURCE pDropSource,
+ DWORD dwOKEffects,
+ DWORD FAR *pdwEffect,
+ HRESULT& hr);
+
+ ~CDragOperation(void);
+
+ BOOL UpdateTarget(void);
+
+ BOOL HandleFeedBack(HRESULT hr);
+
+ BOOL DragOver(void);
+
+ BOOL HandleMessages(void);
+
+ HRESULT CompleteDrop(void);
+
+ void CancelDrag(void);
+
+ void ReleaseCapture(void);
+
+ IFBuffer GetDOBuffer(void);
+
+private:
+
+ void InitCursors(void);
+
+ void InitScrollInt(void);
+
+ HRESULT GetDropTarget(HWND hwnd31,HWND hwndDropTarget);
+
+ LPDATAOBJECT _pDataObject;
+
+ IFBuffer _DOBuffer; // a buffer for the marshalled
+ // data object
+
+ LPDROPSOURCE _pDropSource;
+
+ LPDROPTARGET _pDropTarget;
+
+ LPDROPTARGET _pRealDropTarget;
+
+ HANDLE _hFormats;
+
+ CPoint _cpt;
+
+ DWORD _dwOKEffects;
+
+ DWORD FAR * _pdwEffect;
+
+ BOOL _fEscapePressed;
+
+ HCURSOR _curOld;
+
+ HWND _hwndLast;
+
+ DWORD _grfKeyState;
+
+ HRESULT _hrDragResult;
+
+ BOOL _fReleasedCapture;
+
+ CDragDefaultCursors* _pcddcDefault;
+
+ BOOL _fUseWin31;
+
+ static LONG s_wScrollInt;
+
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CDragOperation::ReleaseCapture
+//
+// Synopsis: Tell clipboard window to turn off mouse capture if we haven't
+// already done so.
+//
+// History: dd-mmm-yy Author Comment
+// 07-Jul-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CDragOperation::ReleaseCapture(void)
+{
+ if (!_fReleasedCapture)
+ {
+ _fReleasedCapture = TRUE;
+ ClipReleaseCaptureForDrag();
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDragOperation::GetDOBuffer
+//
+// Synopsis: returns the interface buffer for the marshalled
+// data object interface
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns: IFBuffer *
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Dec-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline IFBuffer CDragOperation::GetDOBuffer(void)
+{
+ return _DOBuffer;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDropTarget
+//
+// Purpose: Implements IDropTarget for the DoDragLoop. This class
+// will either delegate to a real drop target (registered
+// with RegisterDragDrop) or translate IDropTarget methods
+// into the Win3.1 drag drop protocol.
+//
+// Interface: IDropTarget
+//
+// History: dd-mmm-yy Author Comment
+// 20-Oct-94 alexgo author
+//
+// Notes: This class is NOT thread safe, nor is it safe to pass
+// outside of the CDragOperation class (which is why
+// QueryInterface is not implemented). As long as
+// DoDropDrag works by a modal loop on the calling thread,
+// this should not have to change.
+//
+//--------------------------------------------------------------------------
+
+class CDropTarget : public IDropTarget, public CPrivAlloc
+{
+public:
+ STDMETHOD(QueryInterface) (REFIID riid, LPVOID *ppv);
+ STDMETHOD_(ULONG, AddRef) (void);
+ STDMETHOD_(ULONG, Release) (void);
+ STDMETHOD(DragEnter) (IDataObject *pDataObject, DWORD grfKeyState,
+ POINTL ptl, DWORD *pdwEffect);
+ STDMETHOD(DragOver) (DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect);
+ STDMETHOD(DragLeave) (void);
+ STDMETHOD(Drop) (IDataObject *pDataObject, DWORD grfKeyState, POINTL pt,
+ DWORD *pdwEffect);
+
+private:
+
+ CDropTarget(HWND hwnd31, HWND hwndOLE, DWORD _dwEffectLast,
+ CDragOperation *pdo, DDInfo hDDInfo);
+
+ ~CDropTarget();
+
+ HWND _hwndOLE;
+ HWND _hwnd31;
+ DWORD _dwEffectLast;
+ ULONG _crefs;
+ CDragOperation * _pdo;
+ DDInfo _hDDInfo;
+
+ // make CDragOperation a friend so it can create an instance of our
+ // class (the constructor is private)
+
+ friend class CDragOperation;
+
+};
+
+
+// BUGBUG!! Fix this once Chicago && NT header files are merged
+
+#define CF_HDROP 15
+
+#endif // _DRAG_H
diff --git a/private/ole32/ole232/inc/dstream.h b/private/ole32/ole232/inc/dstream.h
new file mode 100644
index 000000000..f198e2fc6
--- /dev/null
+++ b/private/ole32/ole232/inc/dstream.h
@@ -0,0 +1,162 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dstream.h
+//
+// Contents: internal debugging support (debug stream which builds a string)
+//
+// Classes: dbgstream
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 09-Feb-95 t-ScottH author
+//
+//--------------------------------------------------------------------------
+
+#ifndef _STREAM_H_
+#define _STREAM_H_
+
+//+-------------------------------------------------------------------------
+//
+// Class: dbgstream (_DEBUG only)
+//
+// Purpose: a stream which builds a string for debugging purposes
+// (used to build a string in Dump methods of LE objects such
+// that the character array can be passed off in debugger extensions
+// or used by call tracing)
+//
+// Interface: private:
+// allocate(DWORD)
+// free()
+// reallocate()
+// reallocate(DWORD)
+// init()
+// public:
+// dbgstream(DWORD)
+// dbgstream()
+// ~dbgstream()
+// hex()
+// oct()
+// dec()
+// precision()
+// freeze()
+// unfreeze()
+// str()
+// operator<<(const void *)
+// operator<<(const char *)
+// operator<<(const unsigned char *)
+// operator<<(const signed char *)
+// operator<<(int)
+// operator<<(unsigned int)
+// operator<<(long)
+// operator<<(unsigned long)
+// operator<<(float)
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-95 t-ScottH author
+//
+// Notes:
+// This is simple, efficient implementation of the CRT ostrstream. The
+// ostrstream was found to have too much overhead and thus performance
+// was terrible (in the debugger extensions almost a 5-10x slower) than
+// this implementation
+//
+// this implementation differs from the ostrstream class
+// - no need to append a null character to the string (the string ALWAYS
+// maintains a null character at the end of the string)
+// - implementation uses CoTaskMem[Alloc, Free, Realloc] for memory
+// management. Therefore, all strings passes out externally must also
+// use CoTaskMem[Alloc, Free, Realloc] for memory management
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+#define DEFAULT_INITIAL_ALLOC 300
+#define DEFAULT_GROWBY 100
+
+#define DEFAULT_RADIX 10
+#define DEFAULT_PRECISION 6
+
+#define endl "\n"
+#define ends "\0"
+
+class dbgstream
+{
+ private:
+ // *** data members ***
+
+ // pointer to last character in buffer
+ DWORD m_dwIndex;
+
+ // maximum size of current buffer
+ DWORD m_dwBufSize;
+
+ // if TRUE -> cannot change buffer
+ BOOL m_fFrozen;
+
+ // buffer
+ char *m_pszBuf;
+
+ // hex, dec, or oct for storing ints or longs
+ int m_radix;
+
+ // precision for doubles and floats
+ int m_precision;
+
+
+ // *** private methods ***
+ void allocate(DWORD dwSize);
+ void reallocate(DWORD dwSize);
+ void reallocate();
+ void free();
+
+ void init();
+
+ public:
+ // *** constructors and destructor ***
+ dbgstream(DWORD dwSize);
+ dbgstream();
+
+ ~dbgstream();
+
+ // *** public interface ***
+ char *str();
+
+ BOOL freeze();
+ BOOL unfreeze();
+
+ void hex() {m_radix = 16;}
+ void dec() {m_radix = 10;}
+ void oct() {m_radix = 8; }
+
+ void precision(int p) {m_precision = p;}
+
+ dbgstream& dbgstream::operator<<(int i);
+ dbgstream& dbgstream::operator<<(unsigned int ui)
+ {
+ return (operator<<((unsigned long)ui));
+ }
+ dbgstream& dbgstream::operator<<(long l);
+ dbgstream& dbgstream::operator<<(unsigned long ul);
+
+ dbgstream& dbgstream::operator<<(const void *p);
+
+ dbgstream& dbgstream::operator<<(const char *psz);
+ dbgstream& dbgstream::operator<<(const unsigned char *psz)
+ {
+ return (operator<<((const char *)psz));
+ }
+ dbgstream& dbgstream::operator<<(const signed char *psz)
+ {
+ return (operator<<((const char *)psz));
+ }
+
+};
+
+#endif // _DEBUG
+
+#endif // _STREAM_H_
diff --git a/private/ole32/ole232/inc/emf.h b/private/ole32/ole232/inc/emf.h
new file mode 100644
index 000000000..5e96d5eee
--- /dev/null
+++ b/private/ole32/ole232/inc/emf.h
@@ -0,0 +1,166 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: emf.h
+//
+// Contents: Declaration of CEMfObject
+//
+// Classes: CEMfObject
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH add Dump method to CEMfObject
+// 12-May-94 DavePl created
+//
+//--------------------------------------------------------------------------
+
+#include "olepres.h"
+#include "olecache.h"
+#include "cachenod.h"
+
+// The following number adjusts the count of records processed by
+// our EMF enumeration function before the user's callback function
+// is run.
+
+#define EMF_RECORD_COUNT 20
+
+// Enumeration to indicate which format a hEMF is to be serialized as.
+// Values are not indicative of anything, just non-zero and non-one to
+// make it easier to catch bogus values while debugging
+
+typedef enum tagEMFWRITETYPE
+{
+ WRITE_AS_WMF = 13,
+ WRITE_AS_EMF = 17
+} EMFWRITETYPE;
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CEMfObject
+//
+// Purpose: Enhanced Metafile presentation object
+//
+// Interface: IOlePresObj
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH add Dump method (_DEBUG only) (this method
+// is also a method in IOlePresObj
+// 12-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+class FAR CEMfObject : public IOlePresObj, public CPrivAlloc
+{
+public:
+ CEMfObject(LPCACHENODE pCacheNode, DWORD dwAspect);
+ ~CEMfObject();
+
+ STDMETHOD (QueryInterface) (THIS_ REFIID riid,
+ void ** ppvObj);
+
+ STDMETHOD_(ULONG,AddRef) (THIS);
+
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ STDMETHOD (GetData) (THIS_ LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium );
+
+ STDMETHOD (GetDataHere) (THIS_ LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium );
+
+ STDMETHOD (SetDataWDO) (THIS_ LPFORMATETC pformatetc,
+ STGMEDIUM FAR * pmedium,
+ BOOL fRelease, IDataObject * pdo);
+
+ STDMETHOD (Draw) (THIS_ void * pvAspect,
+ HDC hicTargetDev,
+ HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ int (CALLBACK * pfnContinue)(DWORD),
+ DWORD dwContinue);
+
+
+ STDMETHOD (Load) (THIS_ LPSTREAM pstm,
+ BOOL fReadHeaderOnly);
+
+ STDMETHOD (Save) (THIS_ LPSTREAM pstm);
+
+ STDMETHOD (GetExtent) (THIS_ DWORD dwAspect,
+ LPSIZEL lpsizel);
+
+ STDMETHOD (GetColorSet) (void * pvAspect,
+ HDC hicTargetDev,
+ LPLOGPALETTE * ppColorSet);
+
+ STDMETHOD_(BOOL, IsBlank) (void);
+
+ STDMETHOD_(void, DiscardHPRES) (void);
+
+ int CALLBACK CallbackFuncForDraw (HDC hdc,
+ HANDLETABLE * lpHTable,
+ const ENHMETARECORD * lpEMFR,
+ int nObj,
+ LPARAM lpobj);
+
+ #ifdef _DEBUG
+ STDMETHOD(Dump) (THIS_ char **ppszDump, ULONG ulFlag, int nIndentLevel);
+ #endif // _DEBUG
+
+private:
+
+ INTERNAL ChangeData (HENHMETAFILE hEMfp, BOOL fDelete);
+ INTERNAL_(HENHMETAFILE) LoadHPRES (void);
+ INTERNAL_(HENHMETAFILE) GetCopyOfHPRES (void);
+ inline HENHMETAFILE M_HPRES(void);
+
+ ULONG m_ulRefs;
+ HENHMETAFILE m_hPres;
+
+ BOOL m_fMetaDC;
+ int m_nRecord;
+ HRESULT m_error;
+ LPLOGPALETTE m_pColorSet;
+
+
+ int (CALLBACK * m_pfnContinue)(DWORD);
+
+ DWORD m_dwContinue;
+ DWORD m_dwAspect;
+ DWORD m_dwSize;
+ LONG m_lWidth;
+ LONG m_lHeight;
+ LPCACHENODE m_pCacheNode;
+};
+
+// This is the prototype for the callback function which
+// will enumerate over the enhanced metafile records.
+
+int CALLBACK EMfCallbackFuncForDraw (HDC hdc,
+ HANDLETABLE * pHTable,
+ const ENHMETARECORD * pMFR,
+ int nObj,
+ LPARAM lpobj);
+
+// Utility function to de-serialize an enhanced metafile from
+// a stream, and create a usable handle to it
+
+FARINTERNAL UtGetHEMFFromEMFStm(LPSTREAM lpstream,
+ DWORD * dwSize,
+ HENHMETAFILE * lphPres);
+
+// Utility function which takes a handle to an enhanced metafile
+// and serializes the associated metafile to a stream
+
+FARINTERNAL UtHEMFToEMFStm(HENHMETAFILE hEMF,
+ DWORD dwSize,
+ LPSTREAM lpstream,
+ EMFWRITETYPE type);
+
+// A utility function to check whether or not a DC in question
+// is a standard DC or a metafile DC.
+
+STDAPI_(BOOL) OleIsDcMeta (HDC hdc);
diff --git a/private/ole32/ole232/inc/empty.cxx b/private/ole32/ole232/inc/empty.cxx
new file mode 100644
index 000000000..7702a07bf
--- /dev/null
+++ b/private/ole32/ole232/inc/empty.cxx
@@ -0,0 +1,26 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: empty.cxx
+//
+// Contents: This file is used as a target for building the precompiled
+// header. It is not linked into the product.
+// Classes:
+//
+// Functions:
+//
+// History: 6-22-94 kevinro Created
+//
+//----------------------------------------------------------------------------
+
+#include <le2int.h>
+
+#pragma hdrstop
+
+void VoidFunc()
+{
+
+}
+
diff --git a/private/ole32/ole232/inc/enumgen.h b/private/ole32/ole232/inc/enumgen.h
new file mode 100644
index 000000000..824b151e9
--- /dev/null
+++ b/private/ole32/ole232/inc/enumgen.h
@@ -0,0 +1,180 @@
+/****************************** Module Header ******************************\
+* Module Name: ENUMGEN.H
+*
+* This module contains structure definitions for the enumerator class.
+*
+* Created: 8-July-1992
+*
+* Copyright (c) 1985 - 1992 Microsoft Corporation
+*
+* History:
+* Created by TonyKit
+*
+\***************************************************************************/
+
+#ifndef __ENUMGEN_H__
+#define __ENUMGEN_H__
+
+
+/****** Generic Enumerator Interface ****************************************/
+
+#define LPENUMGENERIC IEnumGeneric FAR*
+
+#undef INTERFACE
+#define INTERFACE IEnumGeneric
+
+DECLARE_INTERFACE_(IEnumGeneric, IUnknown)
+{
+ //*** IUnknown methods ***/
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ //*** IEnumerator methods ***/
+ STDMETHOD(Next) (THIS_ ULONG celt,
+ LPVOID pArrayObjs,
+ ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ LPENUMGENERIC FAR* ppenm) PURE;
+
+ //*** helper methods ***/
+ STDMETHOD(UpdateEnumerator)(THIS_ REFIID riid, DWORD dwCurrent,
+ DWORD dwNew) PURE;
+ STDMETHOD(SetCurrent) (THIS_ DWORD dwCurrent) PURE;
+ STDMETHOD(SetNext) (THIS_ LPENUMGENERIC pEnumGenNext) PURE;
+ STDMETHOD(GetNext) (THIS_ LPENUMGENERIC FAR* ppEnumGenNext) PURE;
+ STDMETHOD(SetPrev) (THIS_ LPENUMGENERIC pEnumGenPrev) PURE;
+ STDMETHOD(GetPrev) (THIS_ LPENUMGENERIC FAR* ppEnumGenPrev) PURE;
+};
+
+
+/****** Generic Enumerator Callback Interface *****************************/
+
+#define LPENUMCALLBACK IEnumCallback FAR*
+
+#undef INTERFACE
+#define INTERFACE IEnumCallback
+
+DECLARE_INTERFACE_(IEnumCallback, IUnknown)
+{
+ //*** IUnknown methods ***/
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ //*** IEnumCallback methods ***/
+ STDMETHOD(Next) (THIS_ DWORD FAR* pdwCurrent,DWORD dwInfo,
+ LPVOID FAR* ppNext) PURE;
+ STDMETHOD(Skip) (THIS_ DWORD FAR* pdwCurrent,DWORD dwInfo) PURE;
+ STDMETHOD(Reset) (THIS_ DWORD FAR* pdwCurrent) PURE;
+ STDMETHOD(Clone) (THIS_ DWORD FAR* pdwCurrent) PURE;
+ STDMETHOD(Destroy) (THIS_ DWORD dwCurrent) PURE;
+};
+
+
+/****** Generic Enumerator Holder Interface ******************************/
+
+#define LPENUMHOLDER IEnumHolder FAR*
+
+#undef INTERFACE
+#define INTERFACE IEnumHolder
+
+DECLARE_INTERFACE_(IEnumHolder, IUnknown)
+{
+ //*** IUnknown methods ***/
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ //*** IEnumHolder methods ***/
+
+ STDMETHOD(CreateEnumerator)(THIS_ REFIID riid, DWORD dwInfo,
+ LPENUMCALLBACK pEnumCallback,
+ LPVOID FAR* ppGenericEnumerator) PURE;
+ STDMETHOD(UpdateEnumerators)(THIS_ REFIID riid, DWORD dwCurrent,
+ DWORD dwNew) PURE;
+ STDMETHOD(RemoveEnumerator)(THIS_ LPENUMGENERIC pEnumGeneric) PURE;
+ STDMETHOD(EnumeratorCount)(THIS_ WORD FAR* pwCount) PURE;
+};
+
+
+STDAPI CreateEnumHolder(LPENUMHOLDER FAR* ppEnumHolder);
+
+
+/****** CEnumList class *************************************/
+
+class FAR CEnumHolder : public IEnumHolder, public CPrivAlloc {
+public:
+ //*** IUnknown methods ***/
+ STDMETHOD(QueryInterface) (REFIID riid, LPLPVOID ppvObj);
+ STDMETHOD_(ULONG,AddRef) ();
+ STDMETHOD_(ULONG,Release) ();
+
+ //*** IEnumHolder methods ***/
+ STDMETHOD(CreateEnumerator)(REFIID riid, DWORD dwInfo,
+ LPENUMCALLBACK pEnumCallback,
+ LPLPVOID ppGenericEnumerator);
+ STDMETHOD(UpdateEnumerators)(REFIID riid, DWORD dwCurrent,
+ DWORD dwNew);
+ STDMETHOD(RemoveEnumerator)(LPENUMGENERIC pEnumGeneric);
+ STDMETHOD(EnumeratorCount)(WORD FAR* pwCount);
+
+ STDSTATIC_(CEnumHolder FAR*) Create(void);
+
+ctor_dtor:
+ CEnumHolder() { GET_A5(); m_nCount = 0; m_refs = 0; m_pFirst = NULL; m_pLast = NULL; }
+ ~CEnumHolder() {}
+
+private:
+ ULONG m_refs;
+ WORD m_nCount;
+ LPENUMGENERIC m_pFirst;
+ LPENUMGENERIC m_pLast;
+ SET_A5;
+};
+
+
+/****** CEnumGeneric class *************************************/
+
+class FAR CEnumGeneric : public IEnumGeneric {
+public:
+ //*** IUnknown methods ***/
+ STDMETHOD(QueryInterface) (REFIID riid, LPLPVOID ppvObj);
+ STDMETHOD_(ULONG,AddRef) ();
+ STDMETHOD_(ULONG,Release) ();
+
+ //*** IEnumGeneric methods ***/
+ STDMETHOD(Next) (ULONG celt, LPVOID pArrayObjs, ULONG FAR* pceltFetched);
+ STDMETHOD(Skip) (ULONG celt);
+ STDMETHOD(Reset) ();
+ STDMETHOD(Clone) (LPENUMGENERIC FAR* ppenm);
+
+ //*** helper methods ***/
+ STDMETHOD(UpdateEnumerator)(REFIID riid, DWORD dwCurrent, DWORD dwNew);
+ STDMETHOD(SetCurrent) (DWORD dwCurrent);
+ STDMETHOD(SetNext)(LPENUMGENERIC pNext);
+ STDMETHOD(GetNext)(LPENUMGENERIC FAR* ppNext);
+ STDMETHOD(SetPrev)(LPENUMGENERIC pPrev);
+ STDMETHOD(GetPrev)(LPENUMGENERIC FAR* ppPrev);
+
+ STDSTATIC_(CEnumGeneric FAR*) Create(LPENUMHOLDER pEnumHolder, REFIID riid,
+ DWORD dwInfo, LPENUMCALLBACK pEnumCallback);
+ctor_dtor:
+ CEnumGeneric() { GET_A5(); m_refs = 0; m_dwCurrent = 0; m_pNext = m_pPrev = NULL; }
+ ~CEnumGeneric() {}
+
+private:
+ IID m_iid;
+ ULONG m_refs; // referance count, when 0 this object goes away
+ DWORD m_dwCurrent;
+ DWORD m_dwDirection; // extra information for enumerator
+ LPENUMCALLBACK m_pEnumCallback; // callback proc to get the next element
+ LPENUMHOLDER m_pParent; // pointer to the list which owns this object
+ LPENUMGENERIC m_pNext; // pointer to the next guy in the list
+ LPENUMGENERIC m_pPrev; // pointer to the prev guy in the list
+ SET_A5;
+};
+
+
+#endif // __ENUMGEN_H__
diff --git a/private/ole32/ole232/inc/fetcenum.h b/private/ole32/ole232/inc/fetcenum.h
new file mode 100644
index 000000000..eda64e02c
--- /dev/null
+++ b/private/ole32/ole232/inc/fetcenum.h
@@ -0,0 +1,9 @@
+#if !defined( _FETCENUM_H_ )
+#define _FETCENUM_H_
+
+#include <olerem.h>
+STDAPI OleSetEnumFormatEtc(LPDATAOBJECT pDataObj, BOOL fClip);
+STDAPI OleGetEnumFormatEtc(OID oid, LPENUMFORMATETC FAR* ppenumfortec);
+STDAPI OleRemoveEnumFormatEtc(BOOL fClip);
+
+#endif // _FETCENUM_H
diff --git a/private/ole32/ole232/inc/gen.h b/private/ole32/ole232/inc/gen.h
new file mode 100644
index 000000000..f8f7ca501
--- /dev/null
+++ b/private/ole32/ole232/inc/gen.h
@@ -0,0 +1,104 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: gen.h
+//
+// Contents: Declaration of CGenObject
+//
+// Classes: CGenObject
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH add Dump method to CGenObject
+// 24-Jan-94 alexgo first pass converting to Cairo style
+// memory allocation
+// 23-Nov-93 alexgo 32bit port
+// 23-Nov-93 alexgo removed internal function declarations
+// (only used in gen.cpp, so put them there)
+//
+//--------------------------------------------------------------------------
+
+
+#include "olepres.h"
+#include "olecache.h"
+#include "cachenod.h"
+
+//+-------------------------------------------------------------------------
+//
+// Class: CGenObject::IOlePresObj
+//
+// Purpose: Implementation of IOlePresObj for device independent bitmaps
+//
+// Interface: IOlePresObj (internal OLE interface)
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH add Dump method (_DEBUG only) (this method
+// is also a method in IOlePresObj
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class FAR CGenObject : public IOlePresObj, public CPrivAlloc
+{
+public:
+ CGenObject (LPCACHENODE pCacheNode, CLIPFORMAT cfFormat,
+ DWORD dwAspect);
+ ~CGenObject( void );
+
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS) ;
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ STDMETHOD(GetData) (THIS_ LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium );
+ STDMETHOD(GetDataHere) (THIS_ LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium );
+
+ STDMETHOD(SetDataWDO) (THIS_ LPFORMATETC pformatetc, LPSTGMEDIUM pmedium,
+ BOOL fRelease, IDataObject * pdo);
+
+ STDMETHOD(Draw) (THIS_ void FAR* pvAspect, HDC hicTargetDev,
+ HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds,
+ BOOL (CALLBACK * pfnContinue)(DWORD),
+ DWORD dwContinue);
+ STDMETHOD(GetExtent) (THIS_ DWORD dwAspect, LPSIZEL lpsizel);
+ STDMETHOD(Load) (THIS_ LPSTREAM pstm, BOOL fReadHeaderOnly = FALSE);
+ STDMETHOD(Save) (THIS_ LPSTREAM pstm);
+ STDMETHOD(GetColorSet) (void FAR* pvAspect, HDC hicTargetDev,
+ LPLOGPALETTE FAR* ppColorSet);
+ STDMETHOD_(BOOL, IsBlank) (THIS);
+ STDMETHOD_(void, DiscardHPRES)(THIS);
+
+ #ifdef _DEBUG
+ STDMETHOD(Dump) (THIS_ char **ppszDump, ULONG ulFlag, int nIndentLevel);
+ #endif // _DEBUG
+
+private:
+
+#ifndef _MAC
+ INTERNAL GetBitmapData(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium);
+
+ INTERNAL SetBitmapData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium,
+ BOOL fRelease, IDataObject *pDataObject);
+#endif
+
+ INTERNAL ChangeData(HANDLE hData, BOOL fDelete);
+ INTERNAL_(HANDLE) LoadHPRES(void);
+ INTERNAL_(HANDLE) GetCopyOfHPRES(void);
+
+shared_state:
+ ULONG m_ulRefs;
+ DWORD m_dwAspect;
+ DWORD m_dwSize;
+ LONG m_lWidth;
+ LONG m_lHeight;
+ HANDLE m_hPres;
+ CLIPFORMAT m_cfFormat;
+ LPCACHENODE m_pCacheNode;
+};
+
diff --git a/private/ole32/ole232/inc/le2int.h b/private/ole32/ole232/inc/le2int.h
new file mode 100644
index 000000000..e20b1f2d8
--- /dev/null
+++ b/private/ole32/ole232/inc/le2int.h
@@ -0,0 +1,664 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// ole2int.h
+//
+// Contents:
+// This is the internal compound document header file that all
+// implementations in the linking and embedding code include.
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 20-Jan-95 t-ScottH add CThreadCheck::Dump method (_DEBUG only)
+// 09-Jan-95 t-scotth changed macro VDATETHREAD to accept a
+// pointer
+// 19-Apr-94 alexgo renamed global clipboard formats to
+// Cairo conventions
+// 24-Jan-94 alexgo first pass converting to Cairo style
+// memory allocation
+// 01/13/93 - alexgo - temporarily disabled _DEBUG for Chicago
+// 12/30/93 - ChrisWe - define _DEBUG #if DBG==1 so that asserts
+// are included; got rid of some previously #ifdef NEVER
+// code; added proper file prolog
+// 12/27/93 - ErikGav - changed lstr* to wcs* on Win32
+// 12/17/93 - ChrisWe - added first pass at GlobalAlloc debugging
+// macros
+// 12/08/93 - ChrisWe - made error assert message strings constant;
+// formatting changes
+// 12/07/93 - ChrisWe - removed obsolete names for memory arenas;
+// did some minor formatting; removed obsolete DBCS stuff
+//
+//-----------------------------------------------------------------------------
+
+/*
+ * This is the internal ole2 header, which means it contains those
+ * interfaces which might eventually be exposed to the outside
+ * and which will be exposed to our implementations. We don't want
+ * to expose these now, so I have put them in a separate file.
+ */
+
+#ifndef _LE2INT_H_
+#define _LE2INT_H_
+
+//
+// Prevent lego errors under Chicago.
+//
+#if defined(_CHICAGO_)
+#define _CTYPE_DISABLE_MACROS
+#endif
+
+#ifndef _CHICAGO_
+// For TLS on Nt, we use a reserved DWORD in the TEB directly. We need to
+// include these files in order to get the macro NtCurrentTeb. These must
+// be included before windows.h
+extern "C"
+{
+#include <nt.h> // NT_PRODUCT_TYPE
+#include <ntdef.h> // NT_PRODUCT_TYPE
+#include <ntrtl.h> // NT_PRODUCT_TYPE
+#include <nturtl.h> // NT_PRODUCT_TYPE
+#include <windef.h> // NT_PRODUCT_TYPE
+#include <winbase.h> // NT_PRODUCT_TYPE
+}
+#endif // _CHICAGO_
+
+
+// ------------------------------------
+// system includes
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+#ifdef WIN32
+# include <wchar.h>
+#else
+# include <ctype.h>
+#endif
+
+// we need to turn on the validation code in the ole library for
+// Cairo/Daytona/Chicago debug builds, which was keyed off _DEBUG
+// in the win16 code. It appears we need this before any other files
+// are included so that debug only declarations in ole2.h/compobj.h
+// get processed.
+#if DBG==1
+# ifndef _DEBUG
+# define _DEBUG
+# endif
+#endif
+
+#ifndef _MAC
+# include <windows.h>
+# include <malloc.h>
+# include <shellapi.h>
+#else
+//#include <mac.h>
+#endif // _MAC
+
+//
+// Debug support
+//
+
+# include <debnot.h>
+
+DECLARE_DEBUG(LE)
+DECLARE_DEBUG(Ref)
+DECLARE_DEBUG(DD)
+
+#if DBG==1
+
+#define LEDebugOut(x) LEInlineDebugOut x
+#define RefDebugOut(x) RefInlineDebugOut x
+#define DDDebugOut(x) DDInlineDebugOut x
+
+#else
+
+#define LEDebugOut(x) NULL
+#define RefDebugOut(x) NULL
+#define DDDebugOut(x) NULL
+
+#endif // DBG
+
+#include <tls.h>
+
+//+-------------------------------------------------------------------------
+//
+// Function: LEERROR (macro)
+//
+// Synopsis: prints out an error message if [cond] is TRUE, along with
+// the file and line information
+//
+// Effects:
+//
+// Arguments: [cond] -- condition to test against
+// [szError] -- string to print out
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 18-Apr-94 alexgo author
+//
+// Notes: Only present in DEBUG builds
+//
+//--------------------------------------------------------------------------
+#if DBG==1
+
+#define LEERROR( cond, szError ) if( cond ) {\
+ LEDebugOut((DEB_ERROR, "ERROR!: %s (%s %d)\n", szError, __FILE__, \
+ __LINE__)); }
+
+#else
+
+#define LEERROR( cond, szError )
+
+#endif //!DBG
+
+//+-------------------------------------------------------------------------
+//
+// Function: LEWARN (macro)
+//
+// Synopsis: prints out a warning message if [cond] is TRUE, along with
+// the file and line information
+//
+// Effects:
+//
+// Arguments: [cond] -- condition to test against
+// [szWarn] -- string to print out
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 18-Apr-94 alexgo author
+//
+// Notes: Only present in DEBUG builds
+//
+//--------------------------------------------------------------------------
+#if DBG==1
+
+#define LEWARN( cond, szWarn ) if( cond ) {\
+ LEDebugOut((DEB_WARN, "WARNING!: %s (%s %d)\n", szWarn, __FILE__, \
+ __LINE__)); }
+
+#else
+
+#define LEWARN( cond, szWarn )
+
+#endif //!DBG
+
+//+-------------------------------------------------------------------------
+//
+// Function: LEVERIFY (macro)
+//
+// Synopsis: prints out a warning message if [cond] is FALSE, along with
+// the file and line information. In non-debug builds, the
+// condition IS still evaluated/executed.
+//
+// Effects:
+//
+// Arguments: [cond] -- condition to test for (intended to be true)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Aug-94 davepl author
+//
+// Notes: Warns only in DEBUG builds, executes in all builds
+//
+//--------------------------------------------------------------------------
+
+#if DBG==1
+
+#define LEVERIFY( cond ) ( (cond) ? \
+ (void) NULL : \
+ LEDebugOut((DEB_WARN, "VERIFY FAILED: %s (%s %d)\n", #cond, __FILE__, __LINE__)) \
+ )
+
+#else
+
+#define LEVERIFY( cond ) (void) (cond)
+
+#endif //!DBG
+
+
+#ifdef WIN32
+
+# define __loadds // Not used
+# define UnlockData(ds) // Not used
+
+# define _fmalloc malloc
+# define _frealloc realloc
+# define _ffree free
+
+#endif // WIN32
+
+#ifdef WIN32
+
+# define _xmemset memset
+# define _xmemcpy memcpy
+# define _xmemcmp memcmp
+# define _xmemmove memmove
+
+#else
+
+# define _xmemset _fmemset
+# define _xmemcpy _fmemcpy
+# define _xmemcmp _fmemcmp
+# define _xmemmove _fmemmove
+
+#endif // WIN32
+
+
+#ifdef WIN32
+
+# define EXPORT
+
+#else
+
+# define EXPORT __export
+
+#endif
+
+
+// ------------------------------------
+// public includes
+#include <ole2.h>
+#include <ole2sp.h>
+#include <ole2com.h>
+// ------------------------------------
+// internal includes
+#include <utils.h>
+#include <olecoll.h>
+#include <valid.h>
+#include <map_kv.h>
+#include <privguid.h>
+#include <memapi.hxx>
+
+/* Exported CLSIDs.. */
+// REVIEW, why not just change these to be correct?
+#define CLSID_StaticMetafile CLSID_Picture_Metafile
+#define CLSID_StaticDib CLSID_Picture_Dib
+
+
+
+#ifdef _MAC
+#define BITMAP_TO_DIB(foretc)
+#else
+#define BITMAP_TO_DIB(foretc) \
+ if (foretc.cfFormat == CF_BITMAP) {\
+ foretc.cfFormat = CF_DIB;\
+ foretc.tymed = TYMED_HGLOBAL;\
+ }
+#endif // _MAC
+
+
+// NOTE!!!
+//
+// If a member is added to the aspect, tymed, or advf enumerations,
+// these values MUST be updated accordingly!!
+
+#define MAX_VALID_ASPECT DVASPECT_DOCPRINT
+#define MAX_VALID_TYMED TYMED_ENHMF
+#define MAX_VALID_ADVF ADVF_DATAONSTOP
+
+// This creates a mask of the valid ADVF bits:
+#define MASK_VALID_ADVF ((MAX_VALID_ADVF << 1) - 1)
+
+// #include "pres.h"
+
+#define VERIFY_ASPECT_SINGLE(dwAsp) {\
+ if (!(dwAsp && !(dwAsp & (dwAsp-1)) && (dwAsp <= MAX_VALID_ASPECT))) {\
+ AssertSz(FALSE, "More than 1 aspect is specified");\
+ return ResultFromScode(DV_E_DVASPECT);\
+ }\
+}
+
+
+#define VERIFY_TYMED_SINGLE(tymed) {\
+ if (!(tymed && !(tymed & (tymed-1)) && (tymed <= MAX_VALID_TYMED))) \
+ return ResultFromScode(DV_E_TYMED); \
+}
+
+// Legal formats for clipformat (and thus, cache nodes)
+// CF_METAFILEPICT && TYMED_MFPICT
+// CF_BITMAP && TYMED_GDI
+// CF_DIB && TYMED_HGLOBAL
+// CF_other && TYMED_HGLOBAL
+
+#define VERIFY_TYMED_VALID_FOR_CLIPFORMAT(pfetc) {\
+ if ((pfetc->cfFormat==CF_METAFILEPICT && !(pfetc->tymed & TYMED_MFPICT))\
+ || (pfetc->cfFormat==CF_ENHMETAFILE && !(pfetc->tymed & TYMED_ENHMF))\
+ || (pfetc->cfFormat==CF_BITMAP && !(pfetc->tymed & TYMED_GDI))\
+ || (pfetc->cfFormat==CF_DIB && !(pfetc->tymed & TYMED_HGLOBAL))\
+ || (pfetc->cfFormat!=CF_METAFILEPICT && \
+ pfetc->cfFormat!=CF_BITMAP && \
+ pfetc->cfFormat!=CF_DIB && \
+ pfetc->cfFormat!=CF_ENHMETAFILE && \
+ !(pfetc->tymed & TYMED_HGLOBAL)))\
+ return ResultFromScode(DV_E_TYMED); \
+}
+
+#define VERIFY_TYMED_SINGLE_VALID_FOR_CLIPFORMAT(pfetc) \
+{ \
+ if (pfetc->cfFormat==CF_METAFILEPICT && pfetc->tymed != TYMED_MFPICT) \
+ return ResultFromScode(DV_E_TYMED); \
+ \
+ if (pfetc->cfFormat==CF_ENHMETAFILE && pfetc->tymed != TYMED_ENHMF) \
+ return ResultFromScode(DV_E_TYMED); \
+ \
+ if (pfetc->cfFormat==CF_BITMAP && pfetc->tymed != TYMED_GDI) \
+ return ResultFromScode(DV_E_TYMED); \
+ \
+ if (pfetc->cfFormat==CF_DIB && pfetc->tymed != TYMED_HGLOBAL) \
+ return ResultFromScode(DV_E_TYMED); \
+ \
+ if (pfetc->cfFormat != CF_METAFILEPICT) \
+ if (pfetc->cfFormat != CF_BITMAP) \
+ if (pfetc->cfFormat != CF_DIB) \
+ if (pfetc->cfFormat != CF_ENHMETAFILE) \
+ if (pfetc->tymed != TYMED_HGLOBAL) \
+ return ResultFromScode(DV_E_TYMED); \
+}
+
+// This was the original code...
+
+/*
+#define VERIFY_TYMED_SINGLE_VALID_FOR_CLIPFORMAT(pfetc) {\
+ if ((pfetc->cfFormat==CF_METAFILEPICT && pfetc->tymed!=TYMED_MFPICT)\
+ || ( (pfetc->cfFormat==CF_BITMAP || \
+ pfetc->cfFormat == CF_DIB ) \
+ && pfetc->tymed!=TYMED_GDI)\
+ || (pfetc->cfFormat!=CF_METAFILEPICT && \
+ pfetc->cfFormat!=CF_BITMAP && \
+ pfetc->cfFormat!=CF_DIB && \
+ pfetc->tymed!=TYMED_HGLOBAL)) \
+ return ResultFromScode(DV_E_TYMED); \
+}
+*/
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// CreateObjectDescriptor, static
+//
+// Synopsis:
+// Creates and initializes an OBJECTDESCRIPTOR from the given
+// parameters
+//
+// Arguments:
+// [clsid] -- the class ID of the object being transferred
+// [dwAspect] -- the display aspect drawn by the source of the
+// transfer
+// [psizel] -- pointer to the size of the object
+// [ppointl] -- pointer to the mouse offset in the object that
+// initiated a drag-drop transfer
+// [dwStatus] -- the OLEMISC status flags for the object
+// being transferred
+// [lpszFullUserTypeName] -- the full user type name of the
+// object being transferred
+// [lpszSrcOfCopy] -- a human readable name for the object
+// being transferred
+//
+// Returns:
+// If successful, A handle to the new OBJECTDESCRIPTOR; otherwise
+// NULL.
+//
+// Notes:
+// REVIEW, this seems generally useful for anyone using the
+// clipboard, or drag-drop; perhaps it should be exported.
+//
+// History:
+// 12/07/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+INTERNAL_(HGLOBAL) CreateObjectDescriptor(CLSID clsid, DWORD dwAspect,
+ const SIZEL FAR *psizel, const POINTL FAR *ppointl,
+ DWORD dwStatus, LPOLESTR lpszFullUserTypeName,
+ LPOLESTR lpszSrcOfCopy);
+
+
+INTERNAL_(HRESULT) CheckTymedCFCombination(LPFORMATETC pfetc);
+
+/*
+#define VERIFY_ASPECT_SINGLE(dwAsp) {\
+ if (!(dwAsp && !(dwAsp & (dwAsp-1)) && (dwAsp <= MAX_VALID_ASPECT))) {\
+ AssertSz(FALSE, "More than 1 aspect is specified");\
+ return ResultFromScode(DV_E_DVASPECT);\
+ }\
+}
+*/
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// VerifyAspectSingle (Internal Inline)
+//
+// Synopsis:
+// Verifies that exactly one bit is set in the aspect, and that
+// it is one of the known aspect bits.
+//
+// Returns:
+// S_OK For a valid aspect
+// DV_E_ASPECT For an invalid aspect
+//
+// Notes:
+// The (0 == (dwAsp & (dwAsp - 1))) test is an efficient means
+// for testing that exactly at most bit is set in dwAsp, once it
+// is known that dwAsp is nonzero.
+//
+// History:
+// 01/07/94 DavePl Created
+//
+//-----------------------------------------------------------------------------
+
+inline HRESULT VerifyAspectSingle(DWORD dwAsp)
+{
+ // Ensure at least one bit is set
+
+ if (dwAsp)
+ {
+ // Ensure at most one bit is set
+
+ if (0 == (dwAsp & (dwAsp-1)))
+ {
+ // Ensure that one bit is valid
+
+ if (MAX_VALID_ASPECT >= dwAsp)
+ {
+ return S_OK;
+ }
+ }
+ }
+
+ LEDebugOut((DEB_WARN,"WARNING: Invalid Aspect DWORD -> %0X\n", dwAsp));
+
+ return DV_E_DVASPECT;
+}
+
+
+/*
+#define VERIFY_TYMED_SINGLE(tymed) {\
+ if (!(tymed && !(tymed & (tymed-1)) && (tymed <= MAX_VALID_TYMED))) \
+ return ResultFromScode(DV_E_TYMED); \
+}
+*/
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// VerifyTymedSingle (Internal Inline)
+//
+// Synopsis:
+// Verifies that exactly one bit is set in the tymed, and that
+// it is one of the known tymed bits.
+//
+// Returns:
+// S_OK For a valid aspect
+// DV_E_ASPECT For an invalid aspect
+//
+// Notes:
+// The (0 == (dwAsp & (dwAsp - 1))) test is an efficient means
+// for testing that exactly at most bit is set in dwTymed, once it
+// is known that dwTymed is nonzero.
+//
+// History:
+// 01/07/94 DavePl Created
+//
+//-----------------------------------------------------------------------------
+
+inline HRESULT VerifyTymedSingle(DWORD dwTymed)
+{
+ // Ensure that at least one bit is set
+
+ if (dwTymed)
+ {
+ // Ensure that at most one bit is set
+
+ if (0 == (dwTymed & (dwTymed - 1)))
+ {
+ // Ensure that the one set bit is a valid one
+
+ if (MAX_VALID_TYMED >= dwTymed)
+ {
+ return S_OK;
+ }
+ }
+ }
+
+ LEDebugOut((DEB_WARN,"WARNING: Invalid Tymed DWORD -> %0X\n", dwTymed));
+
+ return DV_E_TYMED;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CThreadCheck
+//
+// Purpose: ensures that an object is called on the correct thread
+//
+// Interface:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Jan-95 t-ScottH add Dump method to CThreadCheck class
+// (_DEBUG only)
+// 21-Nov-94 alexgo author
+//
+// Notes: To use this class, an object should simply publicly
+// inherit CThreadCheck. The VDATETHREAD macro can then be
+// used to check the thread id at each entry point.
+//
+//--------------------------------------------------------------------------
+
+class CThreadCheck
+{
+public:
+ inline CThreadCheck();
+ BOOL VerifyThreadId(); // in utils.cpp
+ #ifdef _DEBUG
+ HRESULT Dump(char **ppszDumpOA, ULONG ulFlag, int nIndentLevel); // utils.cpp
+ #endif //_DEBUG
+
+private:
+ DWORD m_tid;
+};
+
+//+-------------------------------------------------------------------------
+//
+// Member: CThreadCheck::CThreadCheck
+//
+// Synopsis: stores the current thread id
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline CThreadCheck::CThreadCheck( void )
+{
+ m_tid = GetCurrentThreadId();
+
+ LEWARN(!m_tid, "GetCurrentThreadId failed!!");
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: VDATETHREAD (macro)
+//
+// Synopsis: makes sure the correct thread is called
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires: the calling class must inherit from CThreadCheck
+//
+// Returns: RPC_E_WRONG_THREAD if called on the wrong thread
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 09-Jan-95 t-ScottH give VDATETHREAD an argument
+// 21-Nov-94 alexgo author
+//
+// Notes: THIS MACRO FUNCTIONS IN RETAIL BUILDS TOO!!!
+//
+//--------------------------------------------------------------------------
+
+
+#define VDATETHREAD(pObject) if( !( pObject->VerifyThreadId() ) ) { return RPC_E_WRONG_THREAD; }
+
+// utility macros.
+
+#define LONG_ABS(x) ((x) < 0 ? -(x) : (x))
+
+
+#endif // _LE2INT_H_
+
diff --git a/private/ole32/ole232/inc/map_dwdw.h b/private/ole32/ole232/inc/map_dwdw.h
new file mode 100644
index 000000000..f78b61fc3
--- /dev/null
+++ b/private/ole32/ole232/inc/map_dwdw.h
@@ -0,0 +1,69 @@
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+
+class FAR CMapDwordDword : public CPrivAlloc
+{
+public:
+ // Construction
+ CMapDwordDword(UINT nBlockSize=10)
+ : m_mkv(sizeof(DWORD), sizeof(DWORD), nBlockSize) { }
+ CMapDwordDword(UINT nBlockSize, UINT nHashTableSize)
+ : m_mkv(sizeof(DWORD), sizeof(DWORD), nBlockSize,
+ &MKVDefaultHashKey, nHashTableSize) { }
+
+ // Attributes
+ // number of elements
+ int GetCount() const
+ { return m_mkv.GetCount(); }
+ BOOL IsEmpty() const
+ { return GetCount() == 0; }
+
+ // Lookup
+ BOOL Lookup(DWORD key, DWORD FAR& value) const
+ { return m_mkv.Lookup((LPVOID)&key, sizeof(DWORD), (LPVOID)&value); }
+
+ BOOL LookupHKey(HMAPKEY hKey, DWORD FAR& value) const
+ { return m_mkv.LookupHKey(hKey, (LPVOID)&value); }
+
+ BOOL LookupAdd(DWORD key, DWORD FAR& value) const
+ { return m_mkv.LookupAdd((LPVOID)&key, sizeof(DWORD), (LPVOID)&value); }
+
+ // Add/Delete
+ // add a new (key, value) pair
+ BOOL SetAt(DWORD key, DWORD value)
+ { return m_mkv.SetAt((LPVOID)&key, sizeof(DWORD), (LPVOID)&value); }
+ BOOL SetAtHKey(HMAPKEY hKey, DWORD value)
+ { return m_mkv.SetAtHKey(hKey, (LPVOID)&value); }
+
+ // removing existing (key, ?) pair
+ BOOL RemoveKey(DWORD key)
+ { return m_mkv.RemoveKey((LPVOID)&key, sizeof(DWORD)); }
+
+ BOOL RemoveHKey(HMAPKEY hKey)
+ { return m_mkv.RemoveHKey(hKey); }
+
+ void RemoveAll()
+ { m_mkv.RemoveAll(); }
+
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return m_mkv.GetStartPosition(); }
+
+ void GetNextAssoc(POSITION FAR& rNextPosition, DWORD FAR& rKey, DWORD FAR& rValue) const
+ { m_mkv.GetNextAssoc(&rNextPosition, (LPVOID)&rKey, NULL, (LPVOID)&rValue); }
+
+ HMAPKEY GetHKey(DWORD key) const
+ { return m_mkv.GetHKey((LPVOID)&key, sizeof(DWORD)); }
+
+#ifdef _DEBUG
+ void AssertValid() const
+ { m_mkv.AssertValid(); }
+#endif
+
+private:
+ CMapKeyToValue m_mkv;
+};
diff --git a/private/ole32/ole232/inc/map_lp.h b/private/ole32/ole232/inc/map_lp.h
new file mode 100644
index 000000000..d18c37d81
--- /dev/null
+++ b/private/ole32/ole232/inc/map_lp.h
@@ -0,0 +1,69 @@
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+
+class FAR CMapLongPtr : public CPrivAlloc
+{
+public:
+ // Construction
+ CMapLongPtr(DWORD memctx, UINT nBlockSize=10)
+ : m_mkv(memctx, sizeof(void FAR*), sizeof(LONG), nBlockSize) { }
+ CMapLongPtr(DWORD memctx, UINT nBlockSize, UINT nHashTableSize)
+ : m_mkv(memctx, sizeof(void FAR*), sizeof(LONG), nBlockSize,
+ &MKVDefaultHashKey, nHashTableSize) { }
+
+ // Attributes
+ // number of elements
+ int GetCount() const
+ { return m_mkv.GetCount(); }
+ BOOL IsEmpty() const
+ { return GetCount() == 0; }
+
+ // Lookup
+ BOOL Lookup(LONG key, void FAR* FAR& value) const
+ { return m_mkv.Lookup((LPVOID)&key, sizeof(LONG), (LPVOID)&value); }
+
+ BOOL LookupHKey(HMAPKEY hKey, void FAR* FAR& value) const
+ { return m_mkv.LookupHKey(hKey, (LPVOID)&value); }
+
+ BOOL LookupAdd(LONG key, void FAR* FAR& value) const
+ { return m_mkv.LookupAdd((LPVOID)&key, sizeof(LONG), (LPVOID)&value); }
+
+ // Add/Delete
+ // add a new (key, value) pair
+ BOOL SetAt(LONG key, void FAR* value)
+ { return m_mkv.SetAt((LPVOID)&key, sizeof(LONG), (LPVOID)&value); }
+ BOOL SetAtHKey(HMAPKEY hKey, void FAR* value)
+ { return m_mkv.SetAtHKey(hKey, (LPVOID)&value); }
+
+ // removing existing (key, ?) pair
+ BOOL RemoveKey(LONG key)
+ { return m_mkv.RemoveKey((LPVOID)&key, sizeof(LONG)); }
+
+ BOOL RemoveHKey(HMAPKEY hKey)
+ { return m_mkv.RemoveHKey(hKey); }
+
+ void RemoveAll()
+ { m_mkv.RemoveAll(); }
+
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return m_mkv.GetStartPosition(); }
+
+ void GetNextAssoc(POSITION FAR& rNextPosition, LONG FAR& rKey, void FAR* FAR& rValue) const
+ { m_mkv.GetNextAssoc(&rNextPosition, (LPVOID)&rKey, NULL, (LPVOID)&rValue); }
+
+ HMAPKEY GetHKey(LONG key) const
+ { return m_mkv.GetHKey((LPVOID)&key, sizeof(LONG)); }
+
+#ifdef _DEBUG
+ void AssertValid() const
+ { m_mkv.AssertValid(); }
+#endif
+
+private:
+ CMapKeyToValue m_mkv;
+};
diff --git a/private/ole32/ole232/inc/map_uhw.h b/private/ole32/ole232/inc/map_uhw.h
new file mode 100644
index 000000000..066a8c340
--- /dev/null
+++ b/private/ole32/ole232/inc/map_uhw.h
@@ -0,0 +1,69 @@
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+
+class FAR CMapUintHwnd : public CPrivAlloc
+{
+public:
+ // Construction
+ CMapUintHwnd(UINT nBlockSize=10)
+ : m_mkv(sizeof(HWND), sizeof(UINT), nBlockSize) { }
+ CMapUintHwnd(UINT nBlockSize, UINT nHashTableSize)
+ : m_mkv(sizeof(HWND), sizeof(UINT), nBlockSize,
+ &MKVDefaultHashKey, nHashTableSize) { }
+
+ // Attributes
+ // number of elements
+ int GetCount() const
+ { return m_mkv.GetCount(); }
+ BOOL IsEmpty() const
+ { return GetCount() == 0; }
+
+ // Lookup
+ BOOL Lookup(UINT key, HWND FAR& value) const
+ { return m_mkv.Lookup((LPVOID)&key, sizeof(UINT), (LPVOID)&value); }
+
+ BOOL LookupHKey(HMAPKEY hKey, HWND FAR& value) const
+ { return m_mkv.LookupHKey(hKey, (LPVOID)&value); }
+
+ BOOL LookupAdd(UINT key, HWND FAR& value) const
+ { return m_mkv.LookupAdd((LPVOID)&key, sizeof(UINT), (LPVOID)&value); }
+
+ // Add/Delete
+ // add a new (key, value) pair
+ BOOL SetAt(UINT key, HWND value)
+ { return m_mkv.SetAt((LPVOID)&key, sizeof(UINT), (LPVOID)&value); }
+ BOOL SetAtHKey(HMAPKEY hKey, HWND value)
+ { return m_mkv.SetAtHKey(hKey, (LPVOID)&value); }
+
+ // removing existing (key, ?) pair
+ BOOL RemoveKey(UINT key)
+ { return m_mkv.RemoveKey((LPVOID)&key, sizeof(UINT)); }
+
+ BOOL RemoveHKey(HMAPKEY hKey)
+ { return m_mkv.RemoveHKey(hKey); }
+
+ void RemoveAll()
+ { m_mkv.RemoveAll(); }
+
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return m_mkv.GetStartPosition(); }
+
+ void GetNextAssoc(POSITION FAR& rNextPosition, UINT FAR& rKey, HWND FAR& rValue) const
+ { m_mkv.GetNextAssoc(&rNextPosition, (LPVOID)&rKey, NULL, (LPVOID)&rValue); }
+
+ HMAPKEY GetHKey(UINT key) const
+ { return m_mkv.GetHKey((LPVOID)&key, sizeof(UINT)); }
+
+#ifdef _DEBUG
+ void AssertValid() const
+ { m_mkv.AssertValid(); }
+#endif
+
+private:
+ CMapKeyToValue m_mkv;
+};
diff --git a/private/ole32/ole232/inc/memstm.h b/private/ole32/ole232/inc/memstm.h
new file mode 100644
index 000000000..0b4483c41
--- /dev/null
+++ b/private/ole32/ole232/inc/memstm.h
@@ -0,0 +1,390 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: memstm.h
+//
+// Contents: class declarations and API's for memory streams
+//
+// Classes: MEMSTM (struct)
+// CMemStm
+// CMemBytes
+// CMarshalMemStm
+// CMarshalMemBytes
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 31-Jan-95 t-ScottH added Dump methods to CMemStm and CMemBytes
+// (_DEBUG only)
+// 24-Jan-94 alexgo first pass converting to Cairo style
+// memory allocation
+// 09-Nov-93 alexgo 32bit port, added API declarations
+// 02-Dec-93 alexgo finished commenting and converting
+// to cairo standards
+//--------------------------------------------------------------------------
+#if !defined( _MEMSTM_H_ )
+#define _MEMSTM_H_
+
+#include <sem.hxx> // CMutexSem
+
+#ifdef _DEBUG
+#include "dbgexts.h"
+#endif // _DEBUG
+
+/*
+ * MemStm APIs
+ */
+
+STDAPI_(LPSTREAM) CreateMemStm(DWORD cb, LPHANDLE phMem);
+STDAPI_(LPSTREAM) CloneMemStm(HANDLE hMem);
+STDAPI_(void) ReleaseMemStm(LPHANDLE phMem, BOOL fInternalOnly);
+STDAPI CreateStreamOnHGlobal(HANDLE hGlobal,
+ BOOL fDeleteOnRelease, LPSTREAM FAR * ppstm);
+STDAPI GetHGlobalFromStream(LPSTREAM pstm,
+ HGLOBAL FAR *phglobal);
+STDAPI_(IUnknown FAR*) CMemStmUnMarshal(void);
+STDAPI_(IUnknown FAR*) CMemBytesUnMarshal(void);
+
+class FAR CMarshalMemStm;
+class FAR CMarshalMemBytes;
+
+//+-------------------------------------------------------------------------
+//
+// Class: MEMSTM
+//
+// Purpose: A structure to describe the global memroy
+//
+// Interface:
+//
+// History: dd-mmm-yy Author Comment
+// 09-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+// cRef counts all CMemStm pointers to this MEMSTM plus the number of times
+// a hMem handle to MEMSTM had been returned
+//
+//--------------------------------------------------------------------------
+
+struct MEMSTM
+{ // Data in shared memory
+ DWORD cb; // Size of hGlobal
+ DWORD cRef; // See below
+#ifdef NOTSHARED
+ HANDLE hGlobal; // The data
+#else
+ BYTE * m_pBuf;
+ HANDLE hGlobal;
+#endif
+
+ BOOL fDeleteOnRelease;
+};
+
+#define STREAM_SIG (0x4d525453L)
+
+//+-------------------------------------------------------------------------
+//
+// Class: CMemStm
+//
+// Purpose: IStream on memory (shared mem for win16)
+//
+// Interface: IStream
+//
+// History: dd-mmm-yy Author Comment
+// 02-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+// CMemStm is a stream implementation on top of global shared memory MEMSTM
+//
+// CMemStm
+// +---------+
+// + pvtf + Shared memory
+// +---------+ +--------------+
+// + m_pMem +-->|cb |
+// +---------+ |cRef |
+// |hGlobal |--->+--------------+
+// +--------------+ | Actual Data |
+// CMemStm MEMSTM +--------------+
+//--------------------------------------------------------------------------
+class FAR CMemStm : public IStream, public CPrivAlloc
+{
+public:
+ STDMETHOD(QueryInterface) (REFIID iidInterface, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+ STDMETHOD(Read) (VOID HUGEP* pv, ULONG cb, ULONG FAR* pcbRead);
+ STDMETHOD(Write) (VOID const HUGEP* pv, ULONG cb, ULONG *pcbWritten);
+ STDMETHOD(Seek) (LARGE_INTEGER dlibMove, DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition);
+ STDMETHOD(SetSize) (ULARGE_INTEGER cb);
+ STDMETHOD(CopyTo) (IStream *pstm, ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten);
+ STDMETHOD(Commit) (DWORD grfCommitFlags);
+ STDMETHOD(Revert) (void);
+ STDMETHOD(LockRegion) (ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion) (ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat) (STATSTG *pstatstg, DWORD statflag);
+ STDMETHOD(Clone)(IStream **ppstm);
+
+ STDSTATIC_(CMemStm FAR*) Create(HANDLE hMem);
+
+ #ifdef _DEBUG
+
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+
+ friend DEBUG_EXTENSION_API(dump_cmemstm);
+
+ #endif // _DEBUG
+
+ CMemStm();
+ ~CMemStm();
+
+private:
+ DWORD m_dwSig; // Signature indicating this is our
+ // implementation of
+ // IStream: STREAM_SIG
+ ULONG m_refs; // Number of references to this CmemStm
+ ULONG m_pos; // Seek pointer for Read/Write
+ HANDLE m_hMem; // Memory Handle passed on creation
+ MEMSTM FAR* m_pData; // Pointer to that memroy
+ CMutexSem m_mxs; // mutex for MultiThread protection
+
+ friend HRESULT STDAPICALLTYPE GetHGlobalFromStream(LPSTREAM, HGLOBAL *);
+ friend LPSTREAM STDAPICALLTYPE CreateMemStm(DWORD, LPHANDLE);
+ friend class CMarshalMemStm;
+};
+
+#define LOCKBYTE_SIG (0x0046574A)
+
+//+-------------------------------------------------------------------------
+//
+// Class: CMemBytes
+//
+// Purpose: an ILockBytes implementation atop (global shared in win16)
+// memory MEMSTM
+//
+// Interface: ILockBytes
+//
+// History: dd-mmm-yy Author Comment
+// 02-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+// CMemBytes
+// +---------+
+// + pvtf + Shared memory
+// +---------+ +--------------+
+// + m_pData +-->| cb |
+// +---------+ | cRef |
+// | hGlobal |--->+-------------+
+// +--------------+ | Actual data |
+// CMemBytes MEMSTM +-------------+
+//
+// cRef counts all CMemBytes pointers to this MEMSTM.
+// It and fDeleteOnRelease control the GlobalFree'ing of the hGlobal.
+//
+//--------------------------------------------------------------------------
+
+class FAR CMemBytes : public ILockBytes, public CPrivAlloc
+{
+public:
+ STDMETHOD(QueryInterface) (REFIID iidInterface,
+ void FAR* FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+ STDMETHOD(ReadAt) (ULARGE_INTEGER ulOffset, VOID HUGEP *pv, ULONG cb,
+ ULONG FAR *pcbRead);
+ STDMETHOD(WriteAt) (ULARGE_INTEGER ulOffset, VOID const HUGEP *pv,
+ ULONG cb, ULONG FAR *pcbWritten);
+ STDMETHOD(Flush) (void);
+ STDMETHOD(SetSize) (ULARGE_INTEGER cb);
+ STDMETHOD(LockRegion) (ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion) (ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD statflag);
+
+ STDSTATIC_(CMemBytes FAR*) Create(HANDLE hMem);
+
+ #ifdef _DEBUG
+
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+
+ friend DEBUG_EXTENSION_API(dump_membytes);
+
+ #endif // _DEBUG
+
+ctor_dtor:
+ CMemBytes()
+ {
+ GET_A5();
+ m_hMem = NULL;
+ m_pData = NULL;
+ m_refs = 0;
+ }
+ ~CMemBytes()
+ {
+ // empty body
+ }
+
+private:
+ DWORD m_dwSig; // Signature indicating this
+ // is our implementation of
+ // ILockBytes: LOCKBYTE_SIG
+ ULONG m_refs; // Normal reference count
+ HANDLE m_hMem; // Handle for bookeeping info
+ // (MEMSTM)
+ MEMSTM FAR* m_pData; // Pointer to that memory
+
+ friend HRESULT STDAPICALLTYPE GetHGlobalFromILockBytes(LPLOCKBYTES,
+ HGLOBAL FAR*);
+ friend class CMarshalMemBytes;
+ SET_A5;
+};
+
+#ifndef WIN32
+//
+// THE MARSHALLING CLASSES BELOW ARE ONLY IN 16BIT OLE!!!!
+//
+
+//+-------------------------------------------------------------------------
+//
+// Class: CMarshalMemStm
+//
+// Purpose: provides marshalling for CMemStm's
+//
+// Interface: IMarshal
+//
+// History: dd-mmm-yy Author Comment
+// 02-Dec-93 alexgo 32bit port
+// 05-Dec-93 alexgo removed m_clsid
+//
+// Notes:
+//
+// CMarshalMemStm can Marshal, Unmarshal CMemStm. It is impletented as
+// a seperate object accessible from CMemStm, CMemBytes: QueryIntreface of
+// IMarshal on CMemStm's IStream will return an IMarshal pointer to
+// CMarshalMemStm, but QueryInterface of IStream on that IMarshal will
+// fail.
+// Also QueryInterface of IUnknown on IMarshal will not return the same value
+// As QueryInterface of IUnkown on the original IStream.
+//
+//--------------------------------------------------------------------------
+
+class FAR CMarshalMemStm : public IMarshal
+{
+public:
+ STDMETHOD(QueryInterface) (REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ STDMETHOD(GetUnmarshalClass)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(THIS_ IStream FAR* pStm, REFIID riid,
+ LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(THIS_ IStream FAR* pStm, REFIID riid,
+ LPVOID FAR* ppv);
+ STDMETHOD(ReleaseMarshalData)(THIS_ IStream FAR* pStm);
+ STDMETHOD(DisconnectObject)(THIS_ DWORD dwReserved);
+
+ STDSTATIC_(CMarshalMemStm FAR*) Create(CMemStm FAR* pMemStm);
+
+ctor_dtor:
+ CMarshalMemStm()
+ {
+ GET_A5();
+ m_pMemStm = NULL;
+ m_refs = 0;
+ }
+ ~CMarshalMemStm()
+ {
+ // empty body
+ }
+
+private:
+ ULONG m_refs; // Number of references to this CmemStm
+ CMemStm FAR* m_pMemStm; // Pointer to object [Un]Marshalled
+ SET_A5;
+};
+
+//+-------------------------------------------------------------------------
+//
+// Class: CMarshalMemBytes
+//
+// Purpose: provides marshalling for CMemBytes
+//
+// Interface: IMarshal
+//
+// History: dd-mmm-yy Author Comment
+// 02-Dec-93 alexgo 32bit port
+// 05-Dec-93 alexgo removed m_clsid
+//
+// Notes:
+//
+// CMarshalMemBytes can Marshal, Unmarshal CMemBytes. It is impletented as
+// a seperate object accessible from CMemBytes, CMemBytes: QueryIntreface of
+// IMarshal on CMemBytes's ILocBytes will return an IMarshal pointer to
+// CMarshalMemBytes, but QueryInterface of ILockBytes on that IMarshal will
+// fail.
+// Also QueryInterface of IUnknown on IMarshal will not return the same value
+// As QueryInterface of IUnkown on the original ILockBytes.
+//
+//--------------------------------------------------------------------------
+
+class FAR CMarshalMemBytes : public IMarshal
+{
+public:
+ STDMETHOD(QueryInterface) (REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ STDMETHOD(GetUnmarshalClass)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(THIS_ IStream FAR* pStm, REFIID riid,
+ LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(THIS_ IStream FAR* pStm, REFIID riid,
+ LPVOID FAR* ppv);
+ STDMETHOD(ReleaseMarshalData)(THIS_ IStream FAR* pStm);
+ STDMETHOD(DisconnectObject)(THIS_ DWORD dwReserved);
+
+ STDSTATIC_(CMarshalMemBytes FAR*) Create(CMemBytes FAR* pMemBytes);
+
+ctor_dtor:
+ CMarshalMemBytes()
+ {
+ GET_A5();
+ m_pMemBytes = NULL;
+ m_refs = 0;
+ }
+ ~CMarshalMemBytes()
+ {
+ // empty body
+ }
+
+private:
+ ULONG m_refs; // Number of references to
+ // this CMemBytes
+ CMemBytes FAR* m_pMemBytes; // Pointer to object
+ // [Un]Marshalled
+ SET_A5;
+};
+
+#endif // !WIN32
+
+#endif // _MemBytes_H
diff --git a/private/ole32/ole232/inc/mf.h b/private/ole32/ole232/inc/mf.h
new file mode 100644
index 000000000..c3e1e7e33
--- /dev/null
+++ b/private/ole32/ole232/inc/mf.h
@@ -0,0 +1,177 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: mf.h
+//
+// Contents: Declaration of CMfObject (metafile presentation object)
+//
+// Classes: CMfObject
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH add Dump method to CMfObject
+// 24-Jan-94 alexgo first pass converting to Cairo style
+// memory allocation
+// 29-Nov-93 alexgo 32bit port
+//
+//--------------------------------------------------------------------------
+
+#include "olepres.h"
+#include "olecache.h"
+#include "cachenod.h"
+
+#define RECORD_COUNT 16
+
+#ifndef _MAC
+
+typedef struct _METADC
+{
+ int xMwo;
+ int yMwo;
+ int xMwe;
+ int yMwe;
+ int xre;
+ int yre;
+ struct _METADC FAR* pNext;
+} METADC, *PMETADC, FAR* LPMETADC;
+
+typedef struct _METAINFO
+{
+ METADC headDc;
+ int xwo;
+ int ywo;
+ int xwe;
+ int ywe;
+ int xro;
+ int yro;
+} METAINFO, *PMETAINFO, FAR* LPMETAINFO;
+
+#endif
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CMfObject
+//
+// Purpose: Metafile presentation object
+//
+// Interface: IOlePresObj
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH add Dump method (_DEBUG only) (this method
+// is also a method in IOlePresObj
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class FAR CMfObject : public IOlePresObj, public CPrivAlloc
+{
+public:
+ CMfObject(LPCACHENODE pCacheNode, DWORD dwAspect,
+ BOOL fConvert = FALSE);
+ ~CMfObject(void);
+
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS) ;
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ STDMETHOD(GetData) (THIS_ LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium );
+ STDMETHOD(GetDataHere) (THIS_ LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium );
+
+ STDMETHOD(SetDataWDO) (THIS_ LPFORMATETC pformatetc,
+ STGMEDIUM FAR * pmedium,
+ BOOL fRelease, IDataObject * pdo);
+
+ STDMETHOD(Draw) (THIS_ void FAR* pvAspect, HDC hicTargetDev,
+ HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ BOOL (CALLBACK * pfnContinue)(DWORD),
+ DWORD dwContinue);
+ STDMETHOD(GetExtent) (THIS_ DWORD dwAspect, LPSIZEL lpsizel);
+ STDMETHOD(Load) (THIS_ LPSTREAM pstm, BOOL fReadHeaderOnly = FALSE);
+ STDMETHOD(Save) (THIS_ LPSTREAM pstm);
+ STDMETHOD(GetColorSet) (void FAR* pvAspect, HDC hicTargetDev,
+ LPLOGPALETTE FAR* ppColorSet);
+ STDMETHOD_(BOOL, IsBlank) (THIS);
+ STDMETHOD_(void, DiscardHPRES)(THIS);
+
+#ifndef _MAC
+ inline int CallbackFuncForDraw(HDC hdc, LPHANDLETABLE lpHTable,
+ LPMETARECORD lpMFR, int nObj);
+
+ inline int CallbackFuncForGetColorSet(HDC hdc, LPHANDLETABLE lpHTable,
+ LPMETARECORD lpMFR, int nObj);
+#endif
+
+ #ifdef _DEBUG
+ STDMETHOD(Dump) (THIS_ char **ppszDump, ULONG ulFlag, int nIndentLevel);
+ #endif // _DEBUG
+
+private:
+
+#ifndef _MAC
+ INTERNAL_(HANDLE) GetHmfp (void);
+ INTERNAL_(BOOL) PopDc (void);
+ INTERNAL_(BOOL) PushDc (void);
+ INTERNAL_(void) CleanStack(void);
+#endif
+
+ INTERNAL ChangeData (HANDLE hMfp, BOOL fDelete);
+ INTERNAL_(HANDLE) LoadHPRES(void);
+ INTERNAL_(HANDLE) GetCopyOfHPRES(void);
+
+ INTERNAL_(void) SetPictOrg (HDC, int, int, BOOL);
+ INTERNAL_(void) SetPictExt (HDC, int, int);
+ INTERNAL_(void) ScalePictExt (HDC, int, int, int, int);
+ INTERNAL_(void) ScaleRectExt (HDC, int, int, int, int);
+
+shared_state:
+ ULONG m_ulRefs;
+#ifdef _MAC
+ PicHandle m_hPres;
+#else
+ HMETAFILE m_hPres;
+
+ // these are used only during draw
+ LPMETAINFO m_pMetaInfo;
+ LPMETADC m_pCurMdc;
+ BOOL m_fMetaDC;
+ int m_nRecord;
+ HRESULT m_error;
+ LPLOGPALETTE m_pColorSet;
+ BOOL m_fConvert;
+#endif
+ BOOL (CALLBACK * m_pfnContinue)(DWORD);
+ DWORD m_dwContinue;
+ DWORD m_dwAspect;
+ DWORD m_dwSize;
+ LONG m_lWidth;
+ LONG m_lHeight;
+ LPCACHENODE m_pCacheNode;
+ HPALETTE m_hPalDCOriginal;
+ HPALETTE m_hPalLast;
+
+};
+
+
+INTERNAL_(DWORD) MfGetSize (LPHANDLE lphmf);
+
+#ifndef _MAC
+FARINTERNAL_(HMETAFILE) QD2GDI(HANDLE);
+
+int CALLBACK __loadds MfCallbackFuncForDraw(HDC hdc, HANDLETABLE FAR* lpHTable,
+ METARECORD FAR* lpMFR, int nObj, LPARAM lpobj);
+
+int CALLBACK __loadds MfCallbackFuncForGetColorSet(HDC hdc,
+ HANDLETABLE FAR* lpHTable,
+ METARECORD FAR* lpMFR, int nObj, LPARAM lpobj);
+#endif
diff --git a/private/ole32/ole232/inc/oaholder.h b/private/ole32/ole232/inc/oaholder.h
new file mode 100644
index 000000000..419e10c98
--- /dev/null
+++ b/private/ole32/ole232/inc/oaholder.h
@@ -0,0 +1,116 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// oaholder.h
+//
+// Contents:
+// concrete IOleAdviseHolder declaration
+//
+// Classes:
+// COAHolder, concrete version of IOleAdviseHolder
+//
+// Functions:
+//
+// History:
+// 31-Jan-95 t-ScottH added Dump method to COAHolder class
+// 24-Jan-94 alexgo first pass converting to Cairo style
+// memory allocation
+// 11/01/93 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+
+#ifndef _OAHOLDER_H_
+#define _OAHOLDER_H_
+
+#ifdef _DEBUG
+#include <dbgexts.h>
+#endif // _DEBUG
+
+//+----------------------------------------------------------------------------
+//
+// Class:
+// COAHolder
+//
+// Purpose:
+// Provides concrete implementation of IOleAdviseHolder; a helper
+// class that OLE implementors can use
+//
+// Interface:
+// IOleAdviseHolder
+// SendOnLinkSrcChange() - multicasts the OnLinkSrcChange
+// notification to any registered advise sinks that support
+// IAdviseSink2
+//
+// Notes:
+// Is hard coded to always be allocated from Task memory
+// (MEMCTX_TASK).
+//
+// Connection numbers run from [1..n], and while the implementation
+// uses an array, indexed from [0..n-1], the returned value is
+// one more than the array index of the sink; Advise() and
+// Unadvise() do the adjustment arithmetic; all of this means
+// that elements can't be shifted around, or they won't be found
+// again.
+//
+// REVIEW -- IS NOT THREAD SAFE under assumption that documents
+// will always be single threaded
+//
+//
+// History:
+// 31-Jan-95 t-ScottH added _DEBUG only Dump method
+// 11/01/93 - ChrisWe - moved declaration to oaholder.h
+// 10/28/93 - ChrisWe - removed use of CPtrArray
+// 10/28/93 - ChrisWe - file cleanup and inspection for Cairo
+//
+//-----------------------------------------------------------------------------
+
+class FAR COAHolder : public IOleAdviseHolder, public CSafeRefCount
+{
+public:
+ COAHolder();
+
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (REFIID riid, LPVOID FAR* ppv);
+ STDMETHOD_(ULONG,AddRef) () ;
+ STDMETHOD_(ULONG,Release) ();
+
+ // *** IOleAdviseHolder methods ***
+ STDMETHOD(Advise)(IAdviseSink FAR* pAdvSink, DWORD FAR* pdwConnection);
+ STDMETHOD(Unadvise)(DWORD dwConnection);
+ STDMETHOD(EnumAdvise)(IEnumSTATDATA FAR* FAR* ppenumAdvise);
+
+ STDMETHOD(SendOnRename)(IMoniker FAR* pMk);
+ STDMETHOD(SendOnSave)();
+ STDMETHOD(SendOnClose)();
+
+ // non-interface methods
+ HRESULT SendOnLinkSrcChange(IMoniker FAR* pmk);
+
+ #ifdef _DEBUG
+
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+
+ // need to be able to access COAHolder private data members in the
+ // following debugger extension APIs
+ // this allows the debugger extension APIs to copy memory from the
+ // debuggee process memory to the debugger's process memory
+ // this is required since the Dump method follows pointers to other
+ // structures and classes
+ friend DEBUG_EXTENSION_API(dump_oaholder);
+ friend DEBUG_EXTENSION_API(dump_deflink);
+ friend DEBUG_EXTENSION_API(dump_defobject);
+
+ #endif // _DEBUG
+
+private:
+ ~COAHolder();
+
+#define COAHOLDER_GROWBY 5 /* number of array elements to add each realloc */
+ IAdviseSink FAR *FAR *m_ppIAS; // array of advise sinks
+ int m_iSize; // size of array of advise sinks
+ SET_A5;
+};
+
+#endif // _OAHOLDER_H_
+
diff --git a/private/ole32/ole232/inc/olecache.h b/private/ole32/ole232/inc/olecache.h
new file mode 100644
index 000000000..adc5bdc56
--- /dev/null
+++ b/private/ole32/ole232/inc/olecache.h
@@ -0,0 +1,554 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// olecache.h
+//
+// Contents:
+// Ole presentation cache default implementation specification
+//
+// Classes:
+// COleCache - ole multiple presentation cache
+// CCacheEnum - enumerator for COleCache
+//
+// Functions:
+//
+// History:
+// 31-Jan-95 t-ScottH add Dump method to: COleCache
+// CCacheEnum
+// CCacheEnumFormatEtc
+// moved CCacheEnumFormatEtc class def'n
+// from cpp to this header file
+// add a flag to COLECACHEFLAGs to indicate
+// aggregation in _DEBUG builds
+// 24-Jan-94 alexgo first pass converting to Cairo style
+// memory allocation
+// 11/15/93 - ChrisWe - file inspection and cleanup;
+// remove use of nested classes in COleCache, where
+// possible; remove declaration of CreateDataCache,
+// since it is declared in dvobj.h
+//
+//-----------------------------------------------------------------------------
+
+#include <olepres.h>
+
+#ifdef _DEBUG
+#include <dbgexts.h>
+#endif // _DEBUG
+
+#ifndef _OLECACHE_H_
+#define _OLECACHE_H_
+
+//+----------------------------------------------------------------------------
+//
+// Class:
+// COleCache
+//
+// Purpose:
+// Ole presentation cache; this maintains the presentations for
+// one embedding.
+//
+// For every unique FORMATETC, a cache node is created; cache
+// nodes encapsulate a presentation object and advise sink.
+//
+// COleCache handles persistence of cache nodes, saving (loading)
+// their presentation objects, format descriptions, and advise
+// options.
+//
+// Interface:
+// IUnknown (public IUnknown for aggregation purposes)
+// IOleCacheControl
+// IOleCache2
+// IPersistStorage
+// IViewObject2
+// IDataObject
+// m_UnkPrivate
+// the private IUnknown for aggregation purposes
+//
+// INTERNAL GetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel);
+// returns the size of the aspect indicated
+//
+// Private Interface used by friend classes:
+// INTERNAL_(void) OnChange(DWORD dwAspect, LONG lindex,
+// BOOL fDirty);
+// CCacheNode instances use this to alert the cache to
+// changes to themselves so that the cache can be
+// marked dirty, if that is necessary
+// INTERNAL_(LPSTORAGE) GetStg(void);
+// CCacheNode uses this to obtain storage when cache
+// nodes are being saved
+//
+// INTERNAL_(void) DetachCacheEnum(CCacheEnum FAR* pCacheEnum);
+// When about to be destroyed, CCacheEnum instances
+// use this to request to be taken off
+// the list of cache enumerators that COleCache
+// maintains.
+//
+// Notes:
+// The constructor returns a pointer to the public IUnknown
+// of the object. The private one is available at m_UnkPrivate.
+//
+// The cache maintains its contents in an array. Ids of the
+// cache nodes, such as those returned from Cache(), start out
+// being the index of the node in the array. To detect
+// reuse of an array element, each id is incremented by the maximum
+// size of the array each time it is reused. To find an element by
+// id simply take (id % max_array_size). (id / max_array_size)
+// gives the number of times the array element has been used to
+// cache data. (We do not allocate all the array members at once,
+// but instead grow the array on demand, up to the maximum
+// compile-time array size, MAX_CACHELIST_ITEMS.)
+// If id's do not match
+// exactly, before taking the modulo value, we know that a
+// request has been made for an earlier generation of data that
+// no longer exists.
+//
+// The cache automatically maintains a "native format" node.
+// This node cannot be deleted by the user, and is always kept
+// up to date on disk. This node attempts to keep either a
+// CF_METAFILEPICT, or CF_DIB rendering, with preference in
+// this order.
+// REVIEW, it's not clear how this node ever gets loaded.
+//
+// History:
+// 31-Jan-95 t-ScottH add Dump method (_DEBUG only)
+// 11/15/93 - ChrisWe - file inspection and cleanup;
+// removed use of nested classes where possible;
+// got rid of obsolete declaration of GetOlePresStream;
+// moved presentation stream limits to ole2int.h;
+// coalesced many BOOL flags into a single unsigned
+// quantity
+//
+//-----------------------------------------------------------------------------
+
+// declare the array of cache node pointers
+// COleCache will maintain an array of these
+class FAR CCacheNode; // see cachenod.h for its definition
+typedef CCacheNode FAR* LPCACHENODE;
+
+typedef struct _CACHELIST_ITEM
+{
+ DWORD dwCacheId; // the id assigned to this cache node
+ LPCACHENODE lpCacheNode; // pointer to the cache node
+} CACHELIST_ITEM, FAR* LPCACHELIST;
+
+// forward declare the cache enumerator
+class FAR CCacheEnum;
+
+class FAR COleCache : public IOleCacheControl, public IOleCache2,
+ public IPersistStorage, public CPrivAlloc, public CThreadCheck
+{
+public:
+ COleCache(IUnknown FAR* pUnkOuter, REFCLSID rclsid);
+ ~COleCache();
+
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void) ;
+ STDMETHOD_(ULONG,Release)(void);
+
+ // *** IOleCacheControl methods ***
+ STDMETHOD(OnRun)(THIS_ LPDATAOBJECT pDataObject);
+ STDMETHOD(OnStop)(void);
+
+ // *** IOleCache methods ***
+ STDMETHOD(Cache)(THIS_ LPFORMATETC lpFormatetc, DWORD advf,
+ LPDWORD lpdwCacheId);
+ STDMETHOD(Uncache)(THIS_ DWORD dwCacheId);
+ STDMETHOD(EnumCache)(THIS_ LPENUMSTATDATA FAR* ppenumStatData);
+ STDMETHOD(InitCache)(THIS_ LPDATAOBJECT pDataObject);
+ STDMETHOD(SetData)(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium,
+ BOOL fRelease);
+
+ // *** IOleCache2 methods ***
+ STDMETHOD(UpdateCache)(LPDATAOBJECT pDataObject, DWORD grfUpdf,
+ LPVOID pReserved);
+ STDMETHOD(DiscardCache)(DWORD dwDiscardOptions);
+
+
+ // IPersist methods
+ STDMETHOD(GetClassID)(LPCLSID pClassID);
+
+ // IPersistStorage methods
+ STDMETHOD(IsDirty)(void);
+ STDMETHOD(InitNew)(LPSTORAGE pstg);
+ STDMETHOD(Load)(LPSTORAGE pstg);
+ STDMETHOD(Save)(LPSTORAGE pstgSave, BOOL fSameAsLoad);
+ STDMETHOD(SaveCompleted)(LPSTORAGE pstgNew);
+ STDMETHOD(HandsOffStorage)(void);
+
+
+ // Other public methods, called by defhndlr and deflink
+ INTERNAL GetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel);
+
+#ifdef _CHICAGO_
+ static INTERNAL DrawStackSwitch(
+ LPVOID *pCV,
+ DWORD dwDrawAspect,
+ LONG lindex, void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev, HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ BOOL (CALLBACK * pfnContinue)(DWORD),
+ DWORD dwContinue);
+#endif
+
+
+
+ // used as the private IUnknown for aggregation
+ // this is implemented as a nested class because of the member
+ // name collisions with the other IUnknown
+ // m_UnkPrivate is a public member so that other OLE internal
+ // classes that aggregate this can reach it, since use
+ // of "new COleCache" will return the public IUnknown
+ class CCacheUnkImpl : public IUnknown
+ {
+ public:
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void) ;
+ STDMETHOD_(ULONG,Release)(void);
+ };
+ DECLARE_NC(COleCache, CCacheUnkImpl)
+ CCacheUnkImpl m_UnkPrivate; // vtable for private IUnknown
+
+ // used to get cache contents and to get advises when cache changes
+ // this has to be implemented as a nested class because
+ // IDataObject::SetData collides with IOleCache::SetData
+ class CCacheDataImpl : public IDataObject
+ {
+ public:
+ // IUnknown methods
+ STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // IDataObject methods
+ STDMETHOD(GetData)(LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium );
+ STDMETHOD(GetDataHere)(THIS_ LPFORMATETC pformatetc,
+ LPSTGMEDIUM pmedium );
+ STDMETHOD(QueryGetData)(THIS_ LPFORMATETC pformatetc );
+ STDMETHOD(GetCanonicalFormatEtc)(LPFORMATETC pformatetc,
+ LPFORMATETC pformatetcOut);
+ STDMETHOD(SetData)(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium,
+ BOOL fRelease);
+ STDMETHOD(EnumFormatEtc)(DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenumFormatEtc);
+ STDMETHOD(DAdvise)(FORMATETC FAR* pFormatetc, DWORD advf,
+ IAdviseSink FAR* pAdvSink,
+ DWORD FAR* pdwConnection);
+ STDMETHOD(DUnadvise)(DWORD dwConnection);
+ STDMETHOD(EnumDAdvise)(LPENUMSTATDATA FAR* ppenumAdvise);
+ };
+
+ friend class CCacheDataImpl;
+
+ CCacheDataImpl m_Data; // vtable for IDataObject
+
+#ifdef _DEBUG
+
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+
+ // need to be able to access COleCache private data members in the
+ // following debugger extension APIs
+ // this allows the debugger extension APIs to copy memory from the
+ // debuggee process memory to the debugger's process memory
+ // this is required since the Dump method follows pointers to other
+ // structures and classes
+ friend DEBUG_EXTENSION_API(dump_olecache);
+ friend DEBUG_EXTENSION_API(dump_defobject);
+ friend DEBUG_EXTENSION_API(dump_deflink);
+
+#endif // _DEBUG
+
+
+
+private:
+ // Called by CCacheNode
+ INTERNAL_(void) OnChange(DWORD dwAspect, LONG lindex, BOOL fDirty);
+ INTERNAL_(LPSTORAGE) GetStg(void);
+
+ // Cache Enumerator list maintainance routines
+ INTERNAL_(void) DetachCacheEnum(CCacheEnum FAR* pCacheEnum);
+
+ // Cachenode list manipulation routines. Purely internal, called only
+ // by COleCache and its nested classes
+ INTERNAL_(BOOL) GrowCacheList(void);
+ INTERNAL_(void) DeleteAll(void);
+ INTERNAL_(DWORD) Attach(LPCACHENODE lpCacheNode);
+ INTERNAL_(LPCACHENODE) Detach(DWORD dwCacheId);
+
+ INTERNAL_(LPCACHENODE) GetNext(LPDWORD lpdwCacheId);
+ INTERNAL_(LPCACHENODE) GetAt(DWORD dwCacheId);
+ INTERNAL_(LPCACHENODE) GetAt(DWORD dwAspect, LONG lindex,
+ CLIPFORMAT cfFormat, DVTARGETDEVICE FAR* ptd,
+ DWORD FAR* lpdwCacheId);
+ INTERNAL_(LPCACHENODE) GetNext(DWORD dwAspect, LONG lindex,
+ DWORD FAR* dwCacheId);
+ INTERNAL_(LPCACHENODE) GetAt(LPFORMATETC lpforetc, LPDWORD lpdwCacheId);
+
+
+ INTERNAL_(LPOLEPRESOBJECT) GetPresObjForDrawing(DWORD dwAspect,
+ LONG lindex, DVTARGETDEVICE FAR* ptd);
+ INTERNAL_(LPOLEPRESOBJECT) GetPresObj(DWORD dwAspect, LONG lindex,
+ CLIPFORMAT cfFormat, DVTARGETDEVICE FAR* ptd,
+ DWORD FAR* pdwCacheId);
+
+ INTERNAL_(LPCACHENODE) AddCacheNodeForNative(void);
+ inline INTERNAL_(void) DeleteCacheNodeForNative(void);
+ inline INTERNAL_(void) MoveCacheNodeForNative(void);
+ INTERNAL_(LPCACHENODE) UpdateCacheNodeForNative(void);
+ INTERNAL_(void) FindObjectFormat(LPSTORAGE pstg);
+ INTERNAL wSaveCompleted(LPSTORAGE pstgNew, BOOL fDiscardDrawCacheAlso);
+
+ // used to set up view advises and draw the object
+ // this has to be implemented as a nested class because GetExtent
+ // collides with another methods on COleCache
+ class CCacheViewImpl : public IViewObject2
+ {
+ public:
+ // IUnknown methods
+ STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // IViewObject methods
+ STDMETHOD(Draw)(DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev, HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ BOOL(CALLBACK * pfnContinue)(DWORD),
+ DWORD dwContinue);
+
+ STDMETHOD(GetColorSet)(DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev,
+ LPLOGPALETTE FAR* ppColorSet);
+
+ STDMETHOD(Freeze)(DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DWORD FAR* pdwFreeze);
+ STDMETHOD(Unfreeze)(DWORD dwFreeze);
+ STDMETHOD(SetAdvise)(DWORD aspects, DWORD advf,
+ LPADVISESINK pAdvSink);
+ STDMETHOD(GetAdvise)(DWORD FAR* pAspects, DWORD FAR* pAdvf,
+ LPADVISESINK FAR* ppAdvSink);
+
+ // IViewObject2 methods
+ STDMETHOD(GetExtent)(DWORD dwDrawAspect, LONG lindex,
+ DVTARGETDEVICE FAR * ptd, LPSIZEL lpsizel);
+
+#ifdef _CHICAGO_
+ // private Draw method
+ STDMETHOD(SSDraw)(DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev, HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ BOOL(CALLBACK * pfnContinue)(DWORD),
+ DWORD dwContinue);
+#endif
+
+ };
+
+
+ DECLARE_NC(COleCache, CCacheViewImpl)
+ CCacheViewImpl m_View; // vtable for IViewObject2
+
+ friend CCacheNode; // REVIEW, is this necessary?
+ friend CCacheEnum;
+
+ ULONG m_refs; // reference count
+ IUnknown FAR* m_pUnkOuter; // aggregating IUnknown
+
+ LPSTORAGE m_pStg; // the storage used to store this on disk
+
+ typedef unsigned COLECACHEFLAG; // flag type; used in implementation
+ COLECACHEFLAG m_uFlag;
+#define COLECACHEF_DIRTY 0x0001 /* cache not on disk */
+#define COLECACHEF_NOSCRIBBLEMODE 0x0002
+#define COLECACHEF_SAMEASLOAD 0x0004
+#define COLECACHEF_PBRUSHORMSDRAW 0x0008
+#define COLECACHEF_STATIC 0x0010
+ /* CLSID_StaticMetafile or CLSID_StaticDib */
+#define COLECACHEF_FORMATKNOWN 0x0020
+
+// this is for clearing out the format flags, use &= and ~
+#define COLECACHEF_NOTNORMAL (COLECACHEF_STATIC | COLECACHEF_FORMATKNOWN)
+
+#ifdef _DEBUG
+ // in debug builds keep track of if we are aggregated
+ #define COLECACHEF_AGGREGATED 0x1000
+#endif // _DEBUG
+
+ LPCACHELIST m_pCacheList; // cache node list array
+ ULONG m_uCacheNodeMax; // size of m_pCacheList
+ ULONG m_uCacheNodeCnt; // number of items in m_pCacheList in use
+#define MAX_CACHELIST_ITEMS 99 /* maximum number of items in m_pCacheList */
+#define NUM_CACHELIST_ITEMS 5 /* number of items to start with, and grow by */
+
+ CCacheEnum FAR* m_pCacheEnum; // pointer to the cache enumerators' list
+
+ // single view advise back to consumer of the cache
+ IAdviseSink FAR* m_pViewAdvSink;
+ DWORD m_advfView; // the advise control flags for the view's advise sink
+ DWORD m_aspectsView;
+
+ // for caching the dwCacheId that's currently used for drawing
+ DWORD m_dwDrawCacheId;
+
+ // (bit) list of frozen Aspects, used by Freeze() and Unfreeze()
+ DWORD m_dwFrozenAspects;
+
+ IDataObject FAR* m_pDataObject; // non-NULL if running; no ref count
+
+ CLSID m_clsid;
+ CLIPFORMAT m_cfFormat; // format of the object
+ BOOL m_fUsedToBePBrush;
+};
+
+
+//+----------------------------------------------------------------------------
+//
+// Class:
+// CCacheEnum
+//
+// Purpose:
+// provides an implementation of an enumerator over COleCache
+//
+// Interface:
+// IEnumSTATDATA
+// a standard enumeration interface
+// CCacheEnum
+// constructor; has arguments to allow its use for
+// cloning the enumerator
+//
+// Notes:
+// Whenever the enumerator encounters an item that is of
+// format CF_DIB, it will return a synthesized CF_BITMAP item for
+// the same element immediately afterwards.
+//
+// The enumerator keeps the id of the element last returned
+// as its state.
+//
+// When the enumerator is to be destroyed, the cache must
+// be notified with DetachCacheEnum(), which removes the enumerator
+// from the list of enumerators maintained by the cache.
+//
+// When the cache is to be destroyed, the enumerator must be
+// notified with OnOleCacheDelete(), so that it knows that it's
+// pointer to the cache is no longer valid
+//
+// REVIEW, not multi-thread safe
+//
+// History:
+// 31-Jan-95 t-ScottH added Dump method (_DEBUG only)
+// 11/15/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+class FAR CCacheEnum : public IEnumSTATDATA, public CPrivAlloc,
+ public CThreadCheck
+{
+public:
+ CCacheEnum(COleCache FAR* pOleCache, DWORD dwCurrent, BOOL fDib);
+
+ // IUnknown methods
+ STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR* ppv);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+ // IEnumSTATDATA methods
+ STDMETHOD(Next)(ULONG celt, STATDATA FAR * rgelt,
+ ULONG FAR* pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(LPENUMSTATDATA FAR* ppenum);
+
+#ifdef _DEBUG
+ HRESULT Dump(char **ppszDumpOA, ULONG ulFlag, int nIndentLevel);
+#endif // _DEBUG
+
+ friend COleCache;
+
+private:
+ ~CCacheEnum();
+
+ // called by COleCache, when it is released
+ INTERNAL_(void) OnOleCacheDelete(void);
+
+ ULONG m_refs; // reference count
+ BOOL m_fDib; // last item returned was a CF_DIB
+ ULONG m_ulCurCacheId; // current cache id enumerator is on
+ COleCache FAR* m_pOleCache; // pointer to the cache
+ CCacheEnum FAR* m_pNextCacheEnum; // next cache enumerator that exists
+};
+typedef CCacheEnum FAR* LPCACHEENUM;
+
+
+//+----------------------------------------------------------------------------
+//
+// Class:
+// CCacheEnumFormatEtc
+//
+// Purpose:
+// provides an implemenation of IEnumFORMATETC over COleCache;
+// This enumerator is returned by the cache's implementation of
+// IDataObject, when asked for EnumFormatEtc()
+//
+// Interface:
+// IEnumFORMATETC
+// a standard enumeration interface
+// CCacheEnumFormatEtc
+// constructor; has arguments to allow its use for
+// cloning the enumerator
+//
+// Notes:
+// COleCache already has one enumerator providing IEnumSTATDATA.
+// Note that a FORMATETC is a member of the STATDATA structure.
+// Therefore, to provide this (as a convenience for putting
+// cached items on the clipboard, which requires IDataObject to
+// return IEnumFORMATETC,) we build it on top of the existing
+// IEnumSTATDATA enumerator, discarding the unneeded elements.
+//
+// REVIEW, not multi-thread safe
+//
+// History:
+// 31-Jan-95 t-ScottH add Dump method (_DEBUG only)
+// 02/08/94 - ChrisWe - created
+//
+//-----------------------------------------------------------------------------
+class FAR CCacheEnumFormatEtc : public IEnumFORMATETC, public CPrivAlloc,
+ public CThreadCheck
+{
+public:
+ CCacheEnumFormatEtc(IEnumSTATDATA FAR *pIES);
+
+ // IUnknown methods
+ STDMETHOD(QueryInterface)(REFIID riid, LPVOID FAR* ppv);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+ // IEnumFORMATETC methods
+ STDMETHOD(Next)(ULONG celt, FORMATETC FAR * rgelt,
+ ULONG FAR* pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(LPENUMFORMATETC FAR* ppenum);
+
+#ifdef _DEBUG
+ HRESULT Dump(char **ppszDumpOA, ULONG ulFlag, int nIndentLevel);
+#endif // _DEBUG
+
+private:
+ ~CCacheEnumFormatEtc();
+
+ ULONG m_refs; // reference count
+ IEnumSTATDATA FAR *m_pIES; // enumerator used as basis for this one
+};
+
+
+
+#endif //_OLECACHE_H_
+
diff --git a/private/ole32/ole232/inc/olepres.h b/private/ole32/ole232/inc/olepres.h
new file mode 100644
index 000000000..ba2ac44b7
--- /dev/null
+++ b/private/ole32/ole232/inc/olepres.h
@@ -0,0 +1,73 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// olepres.h
+//
+// Contents:
+// IOlePresObj declaration
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 01-Jan-95 t-ScottH add Dump method to the interface (_DEBUG only)
+// 11/11/93 - ChrisWe - fix type qualifier problems on
+// IOlePresObj::Draw; replace define of LPOLEPRESOBJECT
+// with a typedef
+// 11/10/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+#ifndef _OLEPRES_H_
+#define _OLEPRES_H_
+
+
+#undef INTERFACE
+#define INTERFACE IOlePresObj
+
+#ifdef MAC_REVIEW
+Does this need to be made A5 aware?
+#endif
+
+DECLARE_INTERFACE_(IOlePresObj, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOlePresObj methods ***
+ // NOTE: these methods match similarly named methods in IDataObject,
+ // IViewObject and IOleObject
+ STDMETHOD(GetData)(THIS_ LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium ) PURE;
+ STDMETHOD(GetDataHere)(THIS_ LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium ) PURE;
+ STDMETHOD(SetDataWDO)(THIS_ LPFORMATETC pformatetc,
+ STGMEDIUM FAR * pmedium, BOOL fRelease, IDataObject * pdo) PURE;
+ STDMETHOD(Draw)(THIS_ void FAR* pvAspect, HDC hicTargetDev,
+ HDC hdcDraw, LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ BOOL (CALLBACK * pfnContinue)(DWORD),
+ DWORD dwContinue) PURE;
+ STDMETHOD(GetExtent)(THIS_ DWORD dwAspect, LPSIZEL lpsizel) PURE;
+
+ STDMETHOD(Load)(THIS_ LPSTREAM pstm, BOOL fReadHeaderOnly) PURE;
+ STDMETHOD(Save)(THIS_ LPSTREAM pstm) PURE;
+ STDMETHOD(GetColorSet)(THIS_ void FAR* pvAspect,
+ HDC hicTargetDev,
+ LPLOGPALETTE FAR* ppColorSet) PURE;
+ STDMETHOD_(BOOL, IsBlank)(THIS) PURE;
+ STDMETHOD_(void, DiscardHPRES)(THIS) PURE;
+
+ #ifdef _DEBUG
+ STDMETHOD(Dump)(THIS_ char **ppszDumpOA, ULONG ulFlag, int nIndentLevel) PURE;
+ #endif // _DEBUG
+};
+
+typedef IOlePresObj FAR *LPOLEPRESOBJECT;
+
+#endif //_OLEPRES_H_
+
diff --git a/private/ole32/ole232/inc/ostm2stg.h b/private/ole32/ole232/inc/ostm2stg.h
new file mode 100644
index 000000000..3e564011e
--- /dev/null
+++ b/private/ole32/ole232/inc/ostm2stg.h
@@ -0,0 +1,374 @@
+/* ostm2stg.h
+
+ Used by ostm2stg.cpp only
+
+ Defines a generic object structure which stores all the data necessary
+ to construct either a 2.0 IStorage or a 1.0 OLESTREAM
+*/
+
+
+
+#define OLE_PRESENTATION_STREAM_1 OLESTR("\2OlePres001")
+
+// We will need to do conversions to and from WIN16 and WIN32 bitmaps, so
+// define what a BITMAP used to be under WIN16 (Same for METAFILEPICT).
+
+#pragma pack(1) // Ensure the structure is not expanded
+ // for alignment reasons
+typedef struct tagWIN16BITMAP
+{
+ short bmType;
+ short bmWidth;
+ short bmHeight;
+ short bmWidthBytes;
+ BYTE bmPlanes;
+ BYTE bmBitsPixel;
+ void FAR* bmBits;
+} WIN16BITMAP, * LPWIN16BITMAP;
+
+typedef struct tagWIN16METAFILEPICT
+{
+ short mm;
+ short xExt;
+ short yExt;
+ WORD hMF;
+} WIN16METAFILEPICT, * LPWIN16METAFILEPICT;
+
+
+#pragma pack() // Resume normal packing
+
+// Version number written to stream, From OLE 1.0 ole.h
+const DWORD dwVerToFile = 0x0501;
+
+typedef enum { ctagNone, ctagCLSID, ctagString } CLASSTAG;
+typedef enum { ftagNone, ftagClipFormat, ftagString } FORMATTAG;
+
+class CClass : public CPrivAlloc
+{
+public:
+ CLSID m_clsid; // These two should always represent
+ LPOLESTR m_szClsid; // the same CLSID
+
+ INTERNAL Set (REFCLSID clsid, LPSTORAGE pstg);
+ INTERNAL SetSz (LPOLESTR pcsz);
+ INTERNAL Reset (REFCLSID clsid);
+ CClass (void);
+ ~CClass (void);
+
+};
+typedef CClass CLASS;
+
+
+class CData : public CPrivAlloc
+{
+public:
+ ULONG m_cbSize;
+ LPVOID m_pv; // the same memory
+ HANDLE m_h;
+ BOOL m_fNoFree; // Free memory in destructor?
+
+ CData (void);
+ ~CData (void);
+};
+typedef CData DATA;
+typedef CData *PDATA;
+
+
+class CFormat : public CPrivAlloc
+{
+public:
+ FORMATTAG m_ftag;
+ struct
+ {
+ CLIPFORMAT m_cf;
+ DATA m_dataFormatString;
+ };
+
+ CFormat (void);
+ inline BOOL operator== (const CFormat FAR&)
+ {
+ Win4Assert(0 && "Format == Used");
+ return FALSE;
+ };
+};
+typedef CFormat FORMAT;
+typedef CFormat *PFORMAT;
+
+
+class CPres : public CPrivAlloc
+{
+public:
+ FORMAT m_format;
+ ULONG m_ulHeight;
+ ULONG m_ulWidth;
+ DATA m_data;
+
+ CPres (void);
+};
+typedef CPres PRES;
+typedef CPres *PPRES;
+
+
+// OLE 1.0 values. Used in m_lnkupdopt
+#define UPDATE_ALWAYS 0L
+#define UPDATE_ONSAVE 1L
+#define UPDATE_ONCALL 2L
+#define UPDATE_ONCLOSE 3L
+
+// OLE 1.0 format id's
+// These never change.
+#define FMTID_LINK 1L
+#define FMTID_EMBED 2L
+#define FMTID_STATIC 3L
+#define FMTID_PRES 5L
+
+class CGenericObject : CPrivAlloc
+{
+public:
+ CLASS m_class;
+ CLASS m_classLast;
+ PPRES m_ppres;
+ DATA m_dataNative;
+ BOOL m_fLink;
+ BOOL m_fStatic;
+ BOOL m_fNoBlankPres;
+ LPOLESTR m_szTopic;
+ LPOLESTR m_szItem;
+ ULONG m_lnkupdopt;
+
+ CGenericObject (void);
+ ~CGenericObject (void);
+};
+typedef CGenericObject GENOBJ;
+typedef CGenericObject FAR* PGENOBJ;
+typedef const GENOBJ FAR * PCGENOBJ;
+
+
+
+static INTERNAL OLESTREAMToGenericObject
+ (LPOLESTREAM pos,
+ PGENOBJ pgenobj)
+;
+
+static INTERNAL GetStaticObject
+ (LPOLESTREAM pos,
+ PGENOBJ pgenobj)
+;
+
+static INTERNAL GetPresentationObject
+ (LPOLESTREAM pos,
+ PGENOBJ pgenobj,
+ BOOL fStatic = FALSE)
+;
+
+static INTERNAL GetStandardPresentation
+ (LPOLESTREAM pos,
+ PGENOBJ pgenobj,
+ CLIPFORMAT cf)
+;
+
+static INTERNAL GetGenericPresentation
+ (LPOLESTREAM pos,
+ PGENOBJ pgenobj)
+;
+
+static INTERNAL GetSizedDataOLE1Stm
+ (LPOLESTREAM pos,
+ PDATA pdata)
+;
+
+static INTERNAL OLE1StreamToUL
+ (LPOLESTREAM pos,
+ ULONG FAR* pul)
+;
+
+static INTERNAL GenericObjectToOLESTREAM
+ (const GENOBJ FAR& genobj,
+ LPOLESTREAM pos)
+;
+
+static INTERNAL OLE1StmToString
+ (LPOLESTREAM pos,
+ LPOLESTR FAR* psz)
+;
+
+static INTERNAL PutPresentationObject
+ (LPOLESTREAM pos,
+ const PRES FAR* pres,
+ const CLASS FAR& cls,
+ BOOL fStatic = FALSE)
+;
+
+static INTERNAL PutStandardPresentation
+ (LPOLESTREAM pos,
+ const PRES FAR* pres)
+;
+
+static INTERNAL PutGenericPresentation
+ (LPOLESTREAM pos,
+ const PRES FAR* pres,
+ LPCOLESTR szClass)
+;
+
+
+static INTERNAL StringToOLE1Stm
+ (LPOLESTREAM pos,
+ LPCOLESTR sz)
+;
+
+static INTERNAL SizedDataToOLE1Stm
+ (LPOLESTREAM pos,
+ const DATA FAR& data)
+;
+
+static INTERNAL PutNetworkInfo
+ (LPOLESTREAM pos,
+ LPOLESTR szTopic)
+;
+
+static INTERNAL Read20OleStream
+ (LPSTORAGE pstg,
+ PGENOBJ pgenobj)
+;
+
+static INTERNAL Read20PresStream
+ (LPSTORAGE pstg,
+ PGENOBJ pgenobj,
+ BOOL fObjFmtKnown)
+;
+
+static INTERNAL StorageToGenericObject
+ (LPSTORAGE pstg,
+ PGENOBJ pgenobj)
+;
+
+static INTERNAL MonikerIntoGenObj
+ (PGENOBJ pgenobj,
+ REFCLSID clsidLast,
+ LPMONIKER pmk)
+;
+
+static INTERNAL OLE2StmToSizedData
+ (LPSTREAM pstm,
+ PDATA pdata,
+ ULONG cbSizeDelta=0,
+ ULONG cbSizeKnown=0)
+;
+
+static INTERNAL Read20NativeStreams
+ (LPSTORAGE pstg,
+ PDATA pdata)
+;
+
+static INTERNAL GenObjToOLE2Stm
+ (LPSTORAGE pstg,
+ const GENOBJ FAR& genobj)
+;
+
+FARINTERNAL GenericObjectToIStorage
+ (const GENOBJ FAR& genobj,
+ LPSTORAGE pstg,
+ const DVTARGETDEVICE FAR* ptd)
+;
+
+static INTERNAL PresToNewOLE2Stm
+ (LPSTORAGE pstg,
+ BOOL fLink,
+ const PRES FAR& pres,
+ const DVTARGETDEVICE FAR* ptd,
+ LPOLESTR szStream,
+ BOOL fPBrushNative = FALSE);
+;
+
+static INTERNAL PresToIStorage
+ (LPSTORAGE pstg,
+ const GENOBJ FAR& genobj,
+ const DVTARGETDEVICE FAR* ptd)
+;
+
+static INTERNAL Write20NativeStreams
+ (LPSTORAGE pstg,
+ const GENOBJ FAR& genobj)
+;
+
+static INTERNAL WriteFormat
+ (LPSTREAM pstm,
+ const FORMAT FAR& format)
+;
+
+static INTERNAL ReadFormat
+ (LPSTREAM pstm,
+ PFORMAT pformat)
+;
+
+static INTERNAL DataObjToOLE2Stm
+ (LPSTREAM pstm,
+ const DATA FAR& data)
+;
+
+
+static INTERNAL OLE2StmToUL
+ (LPSTREAM pstm,
+ ULONG FAR* pul)
+;
+
+
+inline static INTERNAL ULToOLE2Stm
+ (LPSTREAM pstm,
+ ULONG ul)
+;
+
+inline static INTERNAL FTToOle2Stm (LPSTREAM pstm);
+
+static INTERNAL FindPresStream
+ (LPSTORAGE pstg,
+ LPSTREAM FAR* ppstm,
+ BOOL fObjFmtKnown)
+;
+
+static INTERNAL MonikerToOLE2Stm
+ (LPSTREAM pstm,
+ LPOLESTR szFile,
+ LPOLESTR szItem,
+ CLSID clsid)
+;
+
+static INTERNAL OLE2StmToMoniker
+ (LPSTREAM pstm,
+ LPMONIKER FAR* ppmk)
+;
+
+static INTERNAL ReadRealClassStg
+ (LPSTORAGE pstg,
+ LPCLSID pclsid)
+;
+
+
+INTERNAL wCLSIDFromProgID(LPOLESTR szClass, LPCLSID pclsid,
+ BOOL fForceAssign);
+
+INTERNAL wProgIDFromCLSID
+ (REFCLSID clsid,
+ LPOLESTR FAR* pszClass)
+;
+
+INTERNAL wWriteFmtUserType
+ (LPSTORAGE,
+ REFCLSID)
+;
+
+INTERNAL_(BOOL) wIsValidHandle
+ (HANDLE h,
+ CLIPFORMAT cf)
+;
+
+inline INTERNAL_(VOID) ConvertBM32to16(LPBITMAP lpsrc, LPWIN16BITMAP lpdest);
+inline INTERNAL_(VOID) ConvertBM16to32(LPWIN16BITMAP lpsrc, LPBITMAP lpdest);
+inline INTERNAL_(VOID) ConvertMF16to32(
+ LPWIN16METAFILEPICT lpsrc,
+ LPMETAFILEPICT lpdest );
+inline INTERNAL_(VOID) ConvertMF32to16(
+ LPMETAFILEPICT lpsrc,
+ LPWIN16METAFILEPICT lpdest );
+
+
diff --git a/private/ole32/ole232/inc/qd2gdi.h b/private/ole32/ole232/inc/qd2gdi.h
new file mode 100644
index 000000000..b07f9c7a1
--- /dev/null
+++ b/private/ole32/ole232/inc/qd2gdi.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+
+ QuickDraw PICT Import Filter
+
+*****************************************************************************
+
+ This file contains the interface for the QuickDraw import filter
+ that reads Mac pictures from disk and/or memory. In addition to the
+ Aldus filter interface, it also supports a parameterized interface
+ for Microsoft applications to control some conversion results.
+
+****************************************************************************/
+
+/*--- Possible Aldus-defined error code returns ---*/
+
+#define NOERR 0 // Conversion succeeded
+
+#define IE_NOT_MY_FILE 5301 // Invalid version (not version 1 or 2 PICT)
+ // Invalid QD2GDI structure version (greater than 2)
+ // Ill-formed PICT header record sequence
+
+#define IE_TOO_BIG 5302 // Image extents exceed 32K
+
+#define IE_BAD_FILE_DATA 5309 // Image bounding box is empty
+ // Attempt to read past end of picture
+ // Corrupted input file
+ // Zero-length record
+
+#define IE_IMPORT_ABORT 5310 // Opening of source image failed
+ // Read failure (network failure, floppy popped)
+ // Most I/O errors
+
+#define IE_MEM_FULL 5311 // CreateMetaFile() failure
+ // CloseMetaFile() failure
+ // Unable to allocate memory (out of memory)
+
+#define IE_MEM_FAIL 5315 // Handle lock failure
+
+#define IE_NOPICTURES 5317 // Empty bounding rectangle or nothing drawn
+
+#define IE_UNSUPP_VERSION 5342 // User-defined abort performed
+
+
+/*--- Aldus-defined file access block ---*/
+
+typedef DWORD FILETYPE;
+
+typedef struct
+{
+ unsigned slippery : 1; /* TRUE if file may disappear. */
+ unsigned write : 1; /* TRUE if open for write. */
+ unsigned unnamed : 1; /* TRUE if unnamed. */
+ unsigned linked : 1; /* Linked to an FS FCB. */
+ unsigned mark : 1; /* Generic mark bit. */
+ FILETYPE fType; /* The file type. */
+#define IBMFNSIZE 124
+ short handle; /* MS-DOS open file handle. */
+ char fullName[IBMFNSIZE]; /* Device, path, file names. */
+ DWORD filePos; /* Our current file posn. */
+} FILESPEC, FAR *LPFILESPEC;
+
+
+/*--- Preferences memory block ---*/
+
+typedef struct // "old" version 1 USERPREFS
+{
+ char signature[6];
+ WORD version;
+ LPSTR sourceFilename;
+ HANDLE sourceHandle;
+ LPSTR destinationFilename;
+ BYTE penPatternAction;
+ BYTE nonSquarePenAction;
+ BYTE penModeAction;
+ BYTE textModeAction;
+ BYTE charLock;
+ BYTE nonRectRegionAction;
+ BOOL PICTinComment;
+ BOOL optimizePP;
+ WORD lineClipWidthThreshold;
+ WORD reserved[6];
+} USERPREFS_V1, FAR *LPUSERPREFS_V1;
+
+
+typedef struct // current version 2 USERPREFS
+{
+ char signature[6];
+ WORD version;
+ WORD size;
+ LPSTR sourceFilename;
+ HANDLE sourceHandle;
+ LPSTR destinationFilename;
+ BYTE penPatternAction;
+ BYTE nonSquarePenAction;
+ BYTE penModeAction;
+ BYTE textModeAction;
+ BYTE nonRectRegionAction;
+ BOOL optimizePP;
+ WORD reserved[6];
+
+} USERPREFS, FAR * LPUSERPREFS;
+
+typedef struct {
+ HANDLE hmf; //handle to resulting
+ RECT bbox; //bounding box
+ WORD inch; //metafile units/inch (for image size)
+}PICTINFO;
+
+
+/*********************** Exported Function Definitions **********************/
+
+int FAR PASCAL GetFilterInfo( short PM_Version, LPSTR lpIni,
+ HANDLE FAR * lphPrefMem,
+ HANDLE FAR * lphFileTypes );
+/* Returns information about this filter.
+ Input parameters are PM_Version which is the filter interface version#
+ and lpIni which is a copy of the win.ini entry
+ Output parameters are lphPrefMem which is a handle to moveable global
+ memory which will be allocated and initialized.
+ lphFileTypes is a structure that contains the file types
+ that this filter can import. (For MAC only)
+ This routine should be called once, just before the filter is to be used
+ the first time. */
+
+
+void FAR PASCAL GetFilterPref( HANDLE hInst, HANDLE hWnd, HANDLE hPrefMem, WORD wFlags );
+/* Input parameters are hInst (in order to access resources), hWnd (to
+ allow the DLL to display a dialog box), and hPrefMem (memory allocated
+ in the GetFilterInfo() entry point). WFlags is currently unused, but
+ should be set to 1 for Aldus' compatability */
+
+
+short FAR PASCAL ImportGR( HDC hdcPrint, LPFILESPEC lpFileSpec,
+ PICTINFO FAR * lpPict, HANDLE hPrefMem );
+/* Import the metafile in the file indicated by the lpFileSpec. The
+ metafile generated will be returned in lpPict. */
+
+
+short FAR PASCAL ImportEmbeddedGr( HDC hdcPrint, LPFILESPEC lpFileSpec,
+ PICTINFO FAR * lpPict, HANDLE hPrefMem,
+ DWORD dwSize, LPSTR lpMetafileName );
+/* Import the metafile in using the previously opened file handle in
+ the structure field lpFileSpec->handle. Reading begins at offset
+ lpFileSpect->filePos, and the convertor will NOT expect to find the
+ 512 byte PICT header. The metafile generated will be returned in
+ lpPict and can be specified via lpMetafileName (NIL = memory metafile,
+ otherwise, fully qualified filename. */
+
+short FAR PASCAL QD2GDI( LPUSERPREFS lpPrefMem, PICTINFO FAR * lpPict );
+/* Import the metafile as specified using the parameters supplied in the
+ lpPrefMem. The metafile will be returned in lpPict. */
+
diff --git a/private/ole32/ole232/inc/reterr.h b/private/ole32/ole232/inc/reterr.h
new file mode 100644
index 000000000..f7746c485
--- /dev/null
+++ b/private/ole32/ole232/inc/reterr.h
@@ -0,0 +1,67 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// reterr.h
+//
+// Contents:
+// Macros that perform an (argument) operation, and on failure,
+// give a warning, and branch to error returns
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 12/30/93 - ChrisWe - redefined Warn macro; added DbgWarn
+//
+//-----------------------------------------------------------------------------
+
+/* Jason's error handling macros */
+
+#ifndef RETERR_H
+#define RETERR_H
+
+#ifdef _DEBUG
+#ifdef NEVER
+FARINTERNAL_(void) wWarn(LPOLESTR sz, LPOLESTR szFile, int iLine);
+#define Warn(sz) wWarn(sz, __FILE__, __LINE__)
+#endif // NEVER
+FARINTERNAL_(void) DbgWarn(LPSTR psz, LPSTR pszFileName, ULONG uLineno);
+#define Warn(sz) DbgWarn(sz, __FILE__, __LINE__)
+#else
+#define Warn(sz)
+#endif // _DEBUG
+
+// Call x. If hresult is not NOERROR, goto errRtn.
+#define ErrRtn(x) do {if (NOERROR != (x)) {Warn(NULL); goto errRtn;}} while(0)
+
+// Call x. If hresult is not NOERROR, store it in hresult and goto errRtn.
+#define ErrRtnH(x) do {if (NOERROR != (hresult=(x))) {Warn(NULL); goto errRtn;}} while (0)
+
+// If x, goto errRtn.
+#define ErrNz(x) do {if (x) {Warn(NULL); goto errRtn;}} while (0)
+
+// If x==0, goto errRtn.
+#define ErrZ(x) do {if (!(x)) {Warn(NULL); goto errRtn;}} while (0)
+
+// If x==0, goto errRtn with a specific scode
+#define ErrZS(x, scode) do {if (!(x)) {Warn(NULL); hresult=ResultFromScode(scode); goto errRtn;}} while (0)
+
+// Call x. If hresult is not NOERROR, return that hresult.
+#define RetErr(x) do {HRESULT hresult; if (NOERROR != (hresult=(x))) {Warn(NULL); return hresult;}} while (0)
+
+// Return unexpected error if x is non-zero
+#define RetNz(x) do {if (x) {Warn(NULL); return ReportResult(0, E_UNEXPECTED, 0, 0);}} while (0)
+
+// Return specific scode if x is non-zero
+#define RetNzS(x, scode) do {if (x) {Warn(NULL); return ResultFromScode (scode);}} while (0)
+
+// Return unexpected error if x is zero
+#define RetZ(x) do {if (!(x)) {Warn(NULL); return ReportResult(0, E_UNEXPECTED, 0, 0);}} while (0)
+
+// Return specific scode if x is zero
+#define RetZS(x, scode) do {if (!(x)) {Warn(NULL); return ResultFromScode (scode);}} while (0)
+
+#endif // RETERR_H
+
diff --git a/private/ole32/ole232/inc/sources.inc b/private/ole32/ole232/inc/sources.inc
new file mode 100644
index 000000000..ef716da8c
--- /dev/null
+++ b/private/ole32/ole232/inc/sources.inc
@@ -0,0 +1,2 @@
+SYNCHRONIZE_BLOCK=1
+SYNCHRONIZE_DRAIN=1
diff --git a/private/ole32/ole232/inplace/daytona/makefile b/private/ole32/ole232/inplace/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/ole232/inplace/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/ole232/inplace/daytona/sources b/private/ole32/ole232/inplace/daytona/sources
new file mode 100644
index 000000000..67f81b8b1
--- /dev/null
+++ b/private/ole32/ole232/inplace/daytona/sources
@@ -0,0 +1,76 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = ole232
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= inplace
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..\..\inc
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+
+SOURCES= \
+ ..\inplace.cpp
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
diff --git a/private/ole32/ole232/inplace/depend.mk b/private/ole32/ole232/inplace/depend.mk
new file mode 100644
index 000000000..04dbde84a
--- /dev/null
+++ b/private/ole32/ole232/inplace/depend.mk
@@ -0,0 +1,33 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\inplace.obj $(OBJDIR)\inplace.lst: .\inplace.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\inplace.h
+
diff --git a/private/ole32/ole232/inplace/dirs b/private/ole32/ole232/inplace/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/ole232/inplace/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/ole232/inplace/filelist.mk b/private/ole32/ole232/inplace/filelist.mk
new file mode 100644
index 000000000..fd6286455
--- /dev/null
+++ b/private/ole32/ole232/inplace/filelist.mk
@@ -0,0 +1,49 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = inplace.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CPPFILES = \
+ .\inplace.cpp \
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PFILE =
+
+
+!include $(CAIROLE)\ole232\ole.mk
diff --git a/private/ole32/ole232/inplace/inplace.cpp b/private/ole32/ole232/inplace/inplace.cpp
new file mode 100644
index 000000000..754d8e40a
--- /dev/null
+++ b/private/ole32/ole232/inplace/inplace.cpp
@@ -0,0 +1,2875 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: inplace.cpp
+//
+// Contents: Implementation of OLE inplace editing API's
+//
+// Classes: CFrame implementation, used to store per-window info
+//
+// Functions: OleCreateMenuDescriptor
+// OleSetMenuDescriptor
+// OleDestroyMenuDescriptor
+// OleTranslateAccelerator
+// IsAccelerator
+// FrameWndFilterProc
+// MessageFilterProc
+//
+//
+// History: dd-mmm-yy Author Comment
+// 31-Mar-94 ricksa Fixed menu merge bug & added some comments
+// 23-Feb-94 alexgo added call tracing
+// 11-Jan-94 alexgo added VDATEHEAP macros to every function
+// 31-Dec-93 ChrisWe fixed casts in OutputDebugStrings
+// 07-Dec-93 alexgo merged changes with shipped 16bit 2.01a
+// (RC9). Also removed lots of bad inlining.
+// 01-Dec-93 alexgo 32bit port, made globals static
+// 07-Dec-92 srinik Converted frame filter implementatio
+// into a C++ class implementation.
+// So, most of the code is rewritten.
+// 09-Jul-92 srinik author
+//
+// Notes: REVIEW32: we need to do something about the new
+// focus management policy for NT (re TonyWi's mail)
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#pragma SEG(inplace)
+
+#include "inplace.h"
+
+NAME_SEG(InPlace)
+ASSERTDATA
+
+// to keep the code bases common
+// REVIEW32: we may want to clean this up a bit
+#ifdef WIN32
+#define FARPROC WNDPROC
+#endif
+
+
+#ifdef WIN32
+// we'd be faster if we used an atom instead of a string!
+static const OLECHAR szPropFrameFilter[] = OLESTR("pFrameFilter");
+#else
+static const OLECHAR szPropFrameFilterH[] = OLESTR("pFrameFilterH");
+static const OLECHAR szPropFrameFilterL[] = OLESTR("pFrameFilterL");
+#endif //WIN32
+
+static WORD wSignature; // = (WORD) { 'S', 'K' }
+
+static HHOOK hMsgHook = NULL;
+static PCFRAMEFILTER pFrameFilter = NULL;
+
+// the values for these globals are set in ole2.cpp
+UINT uOmPostWmCommand;
+UINT uOleMessage;
+
+#define OM_CLEAR_MENU_STATE 0 // lParam is NULL
+#define OM_COMMAND_ID 1 // LOWORD(lParam) contains
+ // the command ID
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsHmenuEqual
+//
+// Synopsis: Test whether two menu handles are equal taking into
+// account whether one might be a Win16 handle.
+//
+// History: dd-mmm-yy Author Comment
+// 31-May-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL IsHmenuEqual(HMENU hmenu1, HMENU hmenu2)
+{
+
+ if (HIWORD(hmenu1) == 0 || HIWORD(hmenu2) == 0)
+ {
+
+ return LOWORD(hmenu1) == LOWORD(hmenu2);
+ }
+ else
+ {
+
+ return hmenu1 == hmenu2;
+ }
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CPaccel
+//
+// Purpose: Handles enumeration of ACCEL table for IsAccelerator
+//
+// Interface: InitLPACCEL - Initialize object
+// operator-> Get pointer to current ACCEL in enumeration
+// Next - bump current pointer
+//
+// History: dd-mmm-yy Author Comment
+// 14-Apr-94 Ricksa Created
+//
+// Notes: This class also guarantees clean up of the
+// allocated accelerator table & to localize the differences
+// between Win16 & Win32 within this class.
+//
+//--------------------------------------------------------------------------
+class CPaccelEnum : public CPrivAlloc
+{
+public:
+ CPaccelEnum(void);
+
+ inline ~CPaccelEnum(void);
+
+ BOOL InitLPACCEL(HACCEL haccel, int cAccel);
+
+ LPACCEL operator->(void);
+
+ void Next(void);
+
+private:
+
+ LPACCEL _lpaccel;
+
+#ifdef WIN32
+
+ LPACCEL _lpaccelBase;
+
+#else // !WIN32
+
+ HACCEL _haccel;
+
+#endif // WIN32
+};
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CPaccelEnum::CPaccelEnum
+//
+// Synopsis: Initialize object to zero
+//
+// History: dd-mmm-yy Author Comment
+// 14-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CPaccelEnum::CPaccelEnum(void) : _lpaccel(NULL)
+{
+#ifdef WIN32
+
+ // In Win32, we allocate the memory so we need to keep track of the
+ // base of the memory that we allocated.
+ _lpaccelBase = NULL;
+
+#else // !WIN32
+
+ // In Win16, we release by unlock resource so we need to keep track of
+ // the accelerator handle.
+ _haccel = NULL;
+
+#endif // WIN32
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CPaccelEnum::~CPaccelEnum
+//
+// Synopsis: Free resources connected with resource table
+//
+// History: dd-mmm-yy Author Comment
+// 14-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline CPaccelEnum::~CPaccelEnum(void)
+{
+#ifdef WIN32
+
+ PrivMemFree(_lpaccelBase);
+
+#else // !WIN32
+
+ UnlockResource(hAccel);
+
+#endif // WIN32
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CPaccelEnum::InitLPACCEL
+//
+// Synopsis: Initialize Accelerator table pointer
+//
+// Arguments: [haccel] - handle to accelerator table
+// [cAccel] - count of entries in the table
+//
+// Returns: TRUE - table was allocated successfully
+// FALSE - table could not be allocated
+//
+// History: dd-mmm-yy Author Comment
+// 14-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline BOOL CPaccelEnum::InitLPACCEL(HACCEL haccel, int cAccel)
+{
+#ifdef WIN32
+
+ // Allocate the memory for the table. If that succeeds, then copy
+ // the accelerator table. Note that if _lpaccelBase gets allocated,
+ // but CopyAcceleratorTable fails, the memory will be cleaned up
+ // in the destructor.
+ if (((_lpaccelBase
+ = (LPACCEL) PrivMemAlloc(cAccel * sizeof(ACCEL))) != NULL)
+ && (CopyAcceleratorTable(haccel, _lpaccelBase, cAccel) == cAccel))
+ {
+ _lpaccel = _lpaccelBase;
+ return TRUE;
+ }
+
+ return FALSE;
+
+#else // !WIN32
+
+ // Just lock the resource
+ return ((_lpaccel = LockResource(haccel)) != NULL);
+
+#endif // WIN32
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CPaccelEnum::operator->
+//
+// Synopsis: Return pointer to accelerator table
+//
+// History: dd-mmm-yy Author Comment
+// 14-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline LPACCEL CPaccelEnum::operator->(void)
+{
+ AssertSz((_lpaccel != NULL), "CPaccelEnum::operator-> _lpaccel NULL!");
+ return _lpaccel;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CPaccelEnum::Next
+//
+// Synopsis: Bump enumeration pointer
+//
+// History: dd-mmm-yy Author Comment
+// 14-Apr-94 Ricksa Created
+//
+//--------------------------------------------------------------------------
+inline void CPaccelEnum::Next(void)
+{
+ AssertSz((_lpaccel != NULL), "CPaccelEnum::Next _lpaccel NULL!");
+ _lpaccel++;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateMenuDescriptor
+//
+// Synopsis: creates a descriptor from a combined menu (for use in
+// dispatching menu messages)
+//
+// Effects:
+//
+// Arguments: [hmenuCombined] -- handle the combined menu
+// [lpMenuWidths] -- an array of 6 longs with the
+// the number of menus in each
+// group
+//
+// Requires:
+//
+// Returns: handle to an OLEMENU
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Allocates space for enough ole menu items (total of all the
+// combined menues) and then fills in each ole menu item from
+// the combined menu
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes: if hmenuCombined is NULL, we still allocate the ole menu
+// descriptor handle
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleCreateMenuDescriptor)
+STDAPI_(HOLEMENU) OleCreateMenuDescriptor (HMENU hmenuCombined,
+ LPOLEMENUGROUPWIDTHS lplMenuWidths)
+{
+ OLETRACEIN((API_OleCreateMenuDescriptor, PARAMFMT("hmenuCombined= %h, lplMenuWidths= %tw"),
+ hmenuCombined, lplMenuWidths));
+ VDATEHEAP();
+
+ int iGroupCnt, n;
+ int iMenuCnt;
+ HGLOBAL hOleMenu;
+ LPOLEMENU lpOleMenu;
+ LPOLEMENUITEM lpMenuList;
+ DWORD dwOleMenuItemsSize = 0;
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleCreateMenuDescriptor ( %lx , "
+ "%p )\n", NULL, hmenuCombined, lplMenuWidths));
+
+ if (hmenuCombined)
+ {
+ GEN_VDATEPTRIN_LABEL( lplMenuWidths, OLEMENUGROUPWIDTHS,
+ (HOLEMENU)NULL, errRtn, hOleMenu );
+
+ iMenuCnt = 0;
+ for (iGroupCnt = 0; iGroupCnt < 6; iGroupCnt++)
+ {
+ iMenuCnt += (int) lplMenuWidths->width[iGroupCnt];
+ }
+
+ if (iMenuCnt == 0)
+ {
+ hOleMenu = NULL;
+ goto errRtn;
+ }
+
+ dwOleMenuItemsSize = (iMenuCnt-1) * sizeof(OLEMENUITEM);
+ }
+
+ hOleMenu = GlobalAlloc(GMEM_SHARE | GMEM_ZEROINIT,
+ sizeof(OLEMENU) + dwOleMenuItemsSize);
+
+ if (!hOleMenu)
+ {
+ goto errRtn;
+ }
+
+ if (! (lpOleMenu = (LPOLEMENU) GlobalLock(hOleMenu)))
+ {
+ GlobalFree(hOleMenu);
+ hOleMenu = NULL;
+ goto errRtn;
+ }
+
+ lpOleMenu->wSignature = wSignature;
+ lpOleMenu->hmenuCombined = hmenuCombined;
+ lpOleMenu->lMenuCnt = (LONG) iMenuCnt;
+
+ if (! hmenuCombined)
+ {
+ goto Exit;
+ }
+
+ lpMenuList = lpOleMenu->menuitem;
+
+ for (iMenuCnt = 0, iGroupCnt = 0; iGroupCnt < 6; iGroupCnt++)
+ {
+ lpOleMenu->MenuWidths.width[iGroupCnt] =
+ lplMenuWidths->width[iGroupCnt];
+ for (n = 0; n < lplMenuWidths->width[iGroupCnt]; n++)
+ {
+ lpMenuList->fObjectMenu = (iGroupCnt % 2);
+ if (GetSubMenu(hmenuCombined, iMenuCnt) != NULL)
+ {
+ lpMenuList->fwPopup = MF_POPUP;
+ lpMenuList->item = (UINT) GetSubMenu(
+ hmenuCombined, iMenuCnt);
+ }
+ else
+ {
+ lpMenuList->fwPopup = NULL;
+ lpMenuList->item = GetMenuItemID (
+ hmenuCombined, iMenuCnt);
+ }
+
+ lpMenuList++;
+ iMenuCnt++;
+ }
+ }
+
+
+Exit:
+ GlobalUnlock(hOleMenu);
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleCreateMenuDescriptor ( %lx )\n",
+ NULL, hOleMenu));
+
+ OLETRACEOUTEX((API_OleCreateMenuDescriptor, RETURNFMT("%h"), hOleMenu));
+
+ return (HOLEMENU) hOleMenu;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleSetMenuDescriptor
+//
+// Synopsis: Called by the SetMenu method on the IOleInPlace frame
+// interface. This API adds(removes) the FrameWndFilterProc
+// to the Frame window of the container. And then sets and
+// removes the main(frame) menu bar
+//
+// Effects:
+//
+// Arguments: [holemenu] -- a handle to the composite menu descriptor
+// [hwndFrame] -- a handle to the container's frame window
+// [hwndActiveObject] -- a handle to the object's in-place
+// window
+// [lpFrame] -- pointer to the container's
+// IOleInPlaceFrame implementation
+// [lpActiveObj] -- pointer to in-place object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: check arguments, then create a new frame filter object
+// and attach it to the frame (replacing any that might
+// already be there).
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleSetMenuDescriptor)
+STDAPI OleSetMenuDescriptor
+(
+ HOLEMENU holemenu,
+ HWND hwndFrame,
+ HWND hwndObject,
+ LPOLEINPLACEFRAME lpFrame,
+ LPOLEINPLACEACTIVEOBJECT lpObject
+)
+{
+ OLETRACEIN((API_OleSetMenuDescriptor,
+ PARAMFMT("holemenu= %h, hwndFrame= %h, hwndObject= %h, lpFrame= %p, lpObject= %p"),
+ holemenu, hwndFrame, hwndObject, lpFrame, lpObject));
+
+ VDATEHEAP();
+
+ PCFRAMEFILTER pFrameFilter;
+ LPOLEMENU lpOleMenu = NULL;
+ LPOLEMENU lpOleMenuCopy = NULL;
+ HRESULT error = NOERROR;
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleSetMenuDescriptor ( %lx , %lx ,"
+ "%lx , %p , %p )\n", NULL, holemenu, hwndFrame, hwndObject,
+ lpFrame, lpObject));
+
+ // The Frame window parameter always needs to be valid since
+ // we use it for both hook and unhook of menus
+ if (hwndFrame == NULL || !IsWindow(hwndFrame))
+ {
+ LEDebugOut((DEB_ERROR,
+ "ERROR in OleSetMenuDesciptor: bad hwndFrame\n"));
+ error = ResultFromScode(OLE_E_INVALIDHWND);
+ goto errRtn;
+ }
+
+ if (holemenu != NULL)
+ {
+ if (hwndObject == NULL || !IsWindow(hwndObject))
+ {
+ LEDebugOut((DEB_ERROR,
+ "ERROR in OleSetMenuDesciptor: bad hwndFrame\n"));
+ error = ResultFromScode(OLE_E_INVALIDHWND);
+ goto errRtn;
+ }
+
+ if (lpFrame && lpObject)
+ {
+ // the caller wants us to provide the support for
+ // context sensitive help, let's validat the pointers
+ VDATEIFACE_LABEL(lpFrame, errRtn, error);
+ VDATEIFACE_LABEL(lpObject, errRtn, error);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IOleInPlaceFrame,
+ (IUnknown **)&lpFrame);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IOleInPlaceActiveObject,
+ (IUnknown **)&lpObject);
+ }
+
+ if (!(lpOleMenu = wGetOleMenuPtr(holemenu)))
+ {
+ error = ResultFromScode(E_HANDLE);
+ goto errRtn;
+ }
+
+ // OleMenuPtr gets released down below by wReleaseOleMenuPtr
+
+ // Allocate memory for the copy
+ DWORD dwSize = GlobalSize(holemenu);
+
+ lpOleMenuCopy = (LPOLEMENU) PrivMemAlloc(dwSize);
+
+ if (lpOleMenuCopy == NULL)
+ {
+ wReleaseOleMenuPtr(holemenu);
+ error = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ memcpy(lpOleMenuCopy, lpOleMenu, dwSize);
+ }
+
+ // if there is a frame filter get rid off it.
+ if (pFrameFilter = (PCFRAMEFILTER) wGetFrameFilterPtr(hwndFrame))
+ {
+ // be sure to remove our window proc hook
+
+ pFrameFilter->RemoveWndProc();
+
+ pFrameFilter->SafeRelease();
+ }
+
+ // Add a new frame filter
+ if (holemenu)
+ {
+ error = CFrameFilter::Create (lpOleMenuCopy,
+ lpOleMenu->hmenuCombined,
+ hwndFrame, hwndObject, lpFrame,
+ lpObject);
+
+ if (FAILED(error))
+ {
+ PrivMemFree(lpOleMenuCopy);
+ }
+
+ wReleaseOleMenuPtr(holemenu);
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleSetMenuDescriptor ( %lx )\n",
+ NULL, error ));
+
+ OLETRACEOUT((API_OleSetMenuDescriptor, error));
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleDestroyMenuDescriptor
+//
+// Synopsis: Releases the menu descriptor allocated by
+// OleCreateMenuDescriptor
+//
+// Effects:
+//
+// Arguments: [holemenu] -- the menu descriptor
+//
+// Requires:
+//
+// Returns: NOERROR, E_HANDLE
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: does a global lock and verifies that holemenu is
+// really a menu descriptor handle (via wGetOleMenuPtr),
+// then unlock's and free's.
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleDestroyMenuDescriptor)
+STDAPI OleDestroyMenuDescriptor (HOLEMENU holemenu)
+{
+ OLETRACEIN((API_OleDestroyMenuDescriptor, PARAMFMT("holemenu= %h"), holemenu));
+
+ VDATEHEAP();
+
+ LPOLEMENU lpOleMenu;
+ HRESULT error;
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleDestroyMenuDescriptor ( %lx )\n",
+ NULL, holemenu));
+
+ // make sure that it is a valid handle
+ if (! (lpOleMenu = wGetOleMenuPtr(holemenu)))
+ {
+ error = ResultFromScode(E_HANDLE);
+ }
+ else
+ {
+ wReleaseOleMenuPtr(holemenu);
+ GlobalFree((HGLOBAL) holemenu);
+ error = NOERROR;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleDestroyMenuDescriptor ( %lx )\n",
+ NULL, error));
+
+ OLETRACEOUT((API_OleDestroyMenuDescriptor, error));
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wSysKeyToKey (internal)
+//
+// Synopsis: Converts a message from a WM_SYSKEY to a WM_KEY message
+// if the alt key was not held down
+//
+// Effects:
+//
+// Arguments: [lpMsg] -- the message to convert
+//
+// Requires:
+//
+// Returns: UINT -- the new message
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+// 07-Dec-93 alexgo removed inlining
+//
+// Notes: original notes:
+//
+// if the ALT key is down when a key is pressed, then the 29th bit of the
+// LPARAM will be set
+//
+// If the message was not made with the ALT key down, convert the message
+// from a WM_SYSKEY* to a WM_KEY* message.
+//
+//--------------------------------------------------------------------------
+
+static UINT wSysKeyToKey(LPMSG lpMsg)
+{
+ VDATEHEAP();
+
+ UINT message = lpMsg->message;
+
+ if (!(HIWORD(lpMsg->lParam) & 0x2000)
+ && (message >= WM_SYSKEYDOWN && message <= WM_SYSDEADCHAR))
+ {
+ message -= (WM_SYSKEYDOWN - WM_KEYDOWN);
+ }
+
+ return message;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleTranslateAccelerator
+//
+// Synopsis: Called by an inplace object to allow a container to attempt
+// to handle an accelerator
+//
+// Effects:
+//
+// Arguments: [lpFrame] -- pointer to IOleInPlaceFrame where the
+// keystroke might be sent
+// [lpFrameInfo] -- pointer to and OLEINPLACEFRAMEINFO
+// from the container with it's accelerator
+// table
+// [lpmsg] -- the keystroke
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: We call SendMessage to store the accelerator cmd
+// (to handle degenerate lookups on the container) and
+// then ask the container to handle
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleTranslateAccelerator)
+STDAPI OleTranslateAccelerator(LPOLEINPLACEFRAME lpFrame,
+ LPOLEINPLACEFRAMEINFO lpFrameInfo, LPMSG lpMsg)
+{
+ OLETRACEIN((API_OleTranslateAccelerator,
+ PARAMFMT("lpFrame= %p, lpFrameInfo= %to, lpMsg= %tm"),
+ lpFrame, lpFrameInfo, lpMsg));
+
+ VDATEHEAP();
+
+ WORD cmd;
+ BOOL fFound;
+ HRESULT error;
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleTranslateAccelerator ( %p , %p "
+ ", %p )\n", NULL, lpFrame, lpFrameInfo, lpMsg));
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IOleInPlaceFrame,
+ (IUnknown **)&lpFrame);
+
+ // Validate parameters -- the best that we can!
+ // Note: the macro's VDATEPTR* were not used because they return
+ // immediately & break the tracing semantics
+ if (!IsValidInterface(lpFrame)
+ || !IsValidPtrIn(lpFrameInfo, sizeof(OLEINPLACEFRAMEINFO))
+ || !IsValidPtrIn(lpMsg, sizeof(MSG)))
+ {
+ error = ResultFromScode(E_INVALIDARG);
+ goto exitRtn;
+ }
+
+
+ // Search the (container) frame's table of accelerators. Remember that
+ // the container may be (actually most likely) is in a separate
+ // process.
+ fFound = IsAccelerator(lpFrameInfo->haccel,
+ lpFrameInfo->cAccelEntries, lpMsg, &cmd);
+
+ if (!fFound && lpFrameInfo->fMDIApp)
+ {
+ // If no accelerator was found and the app is a MDI app,
+ // then we see if there is a mdi accelerator found.
+ fFound = IsMDIAccelerator(lpMsg, &cmd);
+ }
+
+ if (fFound)
+ {
+ // Found some kind of for the container accelerator.
+
+ // uOleMessage is set in ole2.cpp -- it is a private message
+ // between OLE applications.
+
+ // This SendMessage tells the message filter that is on the
+ // frame window what the command translated to. This will
+ // be used in menu collision processing.
+ SSSendMessage(lpFrameInfo->hwndFrame, uOleMessage,
+ OM_COMMAND_ID, MAKELONG(cmd, 0));
+
+ // Send the command and the message to the container. The
+ // result tells the caller whether the container really
+ // used the command.
+
+ error = lpFrame->TranslateAccelerator(lpMsg, cmd);
+
+ }
+ else if (wSysKeyToKey(lpMsg) == WM_SYSCHAR)
+ {
+ // Eat the message if it is "Alt -". This is supposed
+ // to bring the MDI system menu down. But we can not
+ // support it. And we also don't want the message to
+ // be Translated by the object application either.
+ // So, we return as if it has been accepted by the
+ // container as an accelerator.
+
+ // If the container wants to support this it can
+ // have an accelerator for this. This is not an
+ // issue for SDI apps, because it will be thrown
+ // away by USER anyway.
+
+ // This is the original support as it appeared in
+ // the 16-bit version of OLE and the first 32-bit
+ // release. To fix the problem, remove the comment
+ // tags from the else case below and comment the
+ // code out in the _DEBUG #ifdef below. This new
+ // code will walk back up through the objects
+ // parent windows until a window is found that
+ // contains a system menu, at which point the
+ // message is sent.
+
+ if (lpMsg->wParam != OLESTR('-'))
+ {
+ SSSendMessage(lpFrameInfo->hwndFrame,
+ lpMsg->message,
+ lpMsg->wParam, lpMsg->lParam);
+ }
+// else
+// {
+// HWND hWndCurrent = lpMsg->hwnd;
+//
+// while ( hWndCurrent &&
+// !(GetWindowLong(hWndCurrent, GWL_STYLE) & WS_SYSMENU))
+// {
+// hWndCurrent = GetParent(hWndCurrent);
+// }
+//
+// if (hWndCurrent)
+// {
+// SSSendMessage(hWndCurrent,
+// lpMsg->message,
+// lpMsg->wParam, lpMsg->lParam);
+// }
+// }
+
+#ifdef _DEBUG
+ else
+ {
+ OutputDebugString(
+ TEXT("OleTranslateAccelerator: Alt+ - key is discarded\r\n"));
+ }
+#endif
+ error = NOERROR;
+ }
+ else
+ {
+ error = ResultFromScode(S_FALSE);
+ }
+
+exitRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleTranslateAccelerator ( %lx )\n",
+ NULL, error));
+
+ OLETRACEOUT((API_OleTranslateAccelerator, error));
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsAccelerator
+//
+// Synopsis: determines whether [lpMsg] is an accelerator in the [hAccel]
+//
+// Effects:
+//
+// Arguments: [hAccel] -- the accelerator table
+// [cAccelEntries] -- the number of entries in the accelerator
+// table
+// [lpMsg] -- the keystroke message that we should
+// see if it's an accelerator
+// [lpCmd] -- where to return the corresponding command
+// ID if an accelerator is found (may be NULL)
+//
+// Requires:
+//
+// Returns: TRUE if accelerator is found, FALSE otherwise or on error
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(BOOL) IsAccelerator
+ (HACCEL hAccel, int cAccelEntries, LPMSG lpMsg, WORD FAR* lpwCmd)
+{
+ OLETRACEIN((API_IsAccelerator,
+ PARAMFMT("hAccel= %h, cAccelEntries= %d, lpMsg= %tm, lpwCmd= %p"),
+ hAccel, cAccelEntries, lpMsg, lpwCmd));
+
+ VDATEHEAP();
+
+ WORD cmd = NULL;
+ WORD flags;
+ BOOL fFound = FALSE;
+ BOOL fVirt;
+ UINT message;
+
+ // Safe place for pointer to accelerator table
+ CPaccelEnum cpaccelenum;
+
+ LEDebugOut((DEB_TRACE, "%p _IN IsAccelerator ( %lx , %d , %p , %p )\n",
+ NULL, hAccel, cAccelEntries, lpMsg, lpwCmd));
+
+ if (! cAccelEntries)
+ {
+ // no accelerators so we can stop here.
+ goto errRtn;
+ }
+
+ // Change message type from WM_SYS type to WM_KEY type if the ALT
+ // key is not pressed.
+ message = wSysKeyToKey(lpMsg);
+
+ // Figure out whether this message is one that can possibly contain
+ // an accelerator.
+ switch (message)
+ {
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ // wParam in this message is virtual key code
+ fVirt = TRUE;
+ break;
+
+ case WM_CHAR:
+ case WM_SYSCHAR:
+ // wParam is the character
+ fVirt = FALSE;
+ break;
+
+ default:
+ goto errRtn;
+ }
+
+ // Get a pointer to the accerator table
+ if ((hAccel == NULL)
+ || !cpaccelenum.InitLPACCEL(hAccel, cAccelEntries))
+ {
+ // Handle is NULL or we could not lock the resource so exit.
+ goto errRtn;
+ }
+
+ do
+ {
+ // Get the flags from the accelerator table entry to save
+ // a pointer dereference.
+ flags = cpaccelenum->fVirt;
+
+ // if the key in the message and the table aren't the same,
+ // or if the key is virtual and the accel table entry is not or
+ // vice versa (if key is not virtual & accel table entry is
+ // not), we can skip checking the accel entry immediately.
+ if ((cpaccelenum->key != (WORD) lpMsg->wParam) ||
+ ((fVirt != 0) != ((flags & FVIRTKEY) != 0)))
+ {
+ goto Next;
+ }
+
+ if (fVirt)
+ {
+ // If shift down & shift not requested in accelerator
+ // table or if shift not down and shift not set,
+ // we skip this table entry.
+ if ((GetKeyState(VK_SHIFT) < 0) != ((flags & FSHIFT)
+ != 0))
+ {
+ goto Next;
+ }
+
+ // Likewise if control key down & control key not
+ // set in accelerator table or if control not down
+ // and it was set in the accelerator table, we skip
+ // skip this entry in the table.
+ if ((GetKeyState(VK_CONTROL) < 0) !=
+ ((flags & FCONTROL) != 0))
+ {
+ goto Next;
+ }
+ }
+
+ // If the ALT key is down and the accel table flags do not
+ // request the ALT flags or if the alt key is not down and
+ // the ALT is requested, this item does not match.
+ if ((GetKeyState(VK_MENU) < 0) != ((flags & FALT) != 0))
+ {
+ goto Next;
+ }
+
+ // We have gotten a match in the table. If there is a command,
+ // we get it out of the table and record that we found
+ // something.
+ if (cmd = cpaccelenum->cmd)
+ {
+ fFound = TRUE;
+ }
+
+ goto errRtn;
+
+Next:
+ cpaccelenum.Next();
+
+ } while (--cAccelEntries);
+
+
+errRtn:
+ // Common exit
+
+ if (lpwCmd)
+ {
+ // If caller wants to get back the command that they
+ // requested, we assign it at this point.
+ *lpwCmd = cmd;
+ }
+
+
+ LEDebugOut((DEB_TRACE, "%p OUT IsAccelerator ( %lu )\n", NULL,
+ fFound));
+
+ OLETRACEOUTEX((API_IsAccelerator, RETURNFMT("%B"), fFound));
+
+ // Return the result of the search.
+ return fFound;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsMDIAccelerator
+//
+// Synopsis: determines wither [lpMsg] is an accelerator for MDI window
+// commands
+//
+// Effects:
+//
+// Arguments: [lpMsg] -- the keystroke to look at
+// [lpCmd] -- where to put the command ID
+//
+// Requires:
+//
+// Returns: BOOL
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Make sure message is a key down message. Then make sure
+// that the control key is up or toggled and the ALT key is
+// down. Then if F4 is pressed set the system command to
+// close or if the F6 or tab keys are pressed send the
+// appropriate window switch message.
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port, fixed fall-through bug
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(IsMDIAccelerator)
+BOOL IsMDIAccelerator(LPMSG lpMsg, WORD FAR* lpCmd)
+{
+ VDATEHEAP();
+
+ BOOL fResult = FALSE;
+
+ LEDebugOut((DEB_TRACE, "%p _IN IsMDIAccelerator ( %p , %p )\n",
+ NULL, lpMsg, lpCmd));
+
+ // This can be an accelerator only if this is some kind of key down.
+ if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
+ {
+ goto IsMDIAccelerator_exit;
+ }
+
+ if (GetKeyState(VK_CONTROL) >= 0)
+ {
+ // All MIDI accelerators have the control key up (or toggled),
+ // so we can exit here if it isn't down.
+ goto IsMDIAccelerator_exit;
+ }
+
+ switch ((WORD)lpMsg->wParam)
+ {
+ case VK_F4:
+ *lpCmd = SC_CLOSE;
+ fResult = TRUE;
+ break; // this break was not in the 16bit code, but
+ // it looks like it must be there (otherwise
+ // this info is lost)
+ case VK_F6:
+ case VK_TAB:
+ fResult = TRUE;
+
+ *lpCmd = (GetKeyState(VK_SHIFT) < 0)
+ ? SC_PREVWINDOW : SC_NEXTWINDOW;
+
+ break;
+ }
+
+IsMDIAccelerator_exit:
+
+ LEDebugOut((DEB_TRACE, "%p OUT IsMDIAccelerator ( %lu ) [ %lu ] \n",
+ NULL, fResult, *lpCmd));
+
+ return fResult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: FrameWndFilterProc
+//
+// Synopsis: The callback proc for the container's frame window
+//
+// Effects:
+//
+// Arguments: [hwnd] -- the window handle
+// [msg] -- the msg causing the notification
+// [uParam] -- first param
+// [lParam] -- second param
+//
+// Requires:
+//
+// Returns: LRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Gets the CFrame object (if available) and asks it
+// to deal with the window message
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(FrameWndFilterProc)
+STDAPI_(LRESULT) FrameWndFilterProc(HWND hwnd, UINT msg, UINT uParam, LONG lParam)
+{
+ VDATEHEAP();
+
+ PCFRAMEFILTER pFrameFilter;
+ LRESULT lresult;
+
+
+ LEDebugOut((DEB_TRACE, "%p _IN FrameWndFilterProc ( %lx , %u ,"
+ " %u , %ld )\n", NULL, hwnd, msg, uParam, lParam));
+
+ if (!(pFrameFilter = (PCFRAMEFILTER) wGetFrameFilterPtr(hwnd)))
+ {
+ lresult = SSDefWindowProc(hwnd, msg, uParam, lParam);
+ }
+ else
+ {
+ // stabilize the frame filter
+ CStabilize FFstabilize((CSafeRefCount *)pFrameFilter);
+
+ if (msg == WM_SYSCOMMAND)
+ {
+ lresult = pFrameFilter->OnSysCommand(uParam,
+ lParam);
+ }
+ else
+ {
+ lresult = pFrameFilter->OnMessage(msg, uParam,
+ lParam);
+ }
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT FrameWndFilterProc ( %lu )\n",
+ NULL, lresult));
+
+ return lresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CFrameFilter::Create
+//
+// Synopsis: Allocates and initializes a CFrame object (which handles
+// all of the real processing work for event callbacks)
+//
+// Effects:
+//
+// Arguments: [lpOleMenu] -- pointer to the ole menu descriptor
+// [hmenuCombined] -- the combined menu handle
+// [hwndFrame] -- handle to the container's frame
+// (where the CFrame should be installed)
+// [hwndActiveObj] -- handle to the in-place object's window
+// [lpFrame] -- pointer to the container's
+// IOleInPlaceFrame implementation
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Allocates the object and installs a pointer to it as
+// a property on the window
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CFrameFilter_Create)
+HRESULT CFrameFilter::Create(LPOLEMENU lpOleMenu, HMENU hmenuCombined,
+ HWND hwndFrame, HWND hwndActiveObj,
+ LPOLEINPLACEFRAME lpFrame, LPOLEINPLACEACTIVEOBJECT lpActiveObj)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::Create ( %lx , %p ,"
+ " %lx , %lx , %p , %p )\n", NULL, lpOleMenu,
+ hmenuCombined, hwndFrame, hwndActiveObj,
+ lpFrame, lpActiveObj));
+
+ CFrameFilter * pFF = new CFrameFilter(hwndFrame, hwndActiveObj);
+
+ if (!pFF)
+ {
+ goto errRtn;
+ }
+
+ pFF->SafeAddRef();
+
+ pFF->m_lpOleMenu = lpOleMenu;
+ pFF->m_hmenuCombined = hmenuCombined;
+
+ // If the following pointers are NON-NULL, it means that the container
+ // wants us to use our message filter to deal with the F1 key. So,
+ // remember the pointers.
+
+ if (lpFrame && lpActiveObj)
+ {
+ // these addref's should not be outgoing calls, so
+ // no need to stabilize around them. (unless, of
+ // course, the container made an outgoing call for
+ // frame->AddRef, but that would be really weird).
+
+ (pFF->m_lpFrame = lpFrame)->AddRef();
+ (pFF->m_lpObject = lpActiveObj)->AddRef();
+ }
+
+ // Hook the frame wnd proc
+ if (!(pFF->m_lpfnPrevWndProc = (WNDPROC) SetWindowLong (hwndFrame,
+ GWL_WNDPROC, (LONG) FrameWndFilterProc)))
+ {
+ goto errRtn;
+ }
+
+#ifdef WIN32
+ if (!SetProp (hwndFrame, szPropFrameFilter, (HANDLE) pFF))
+ {
+ goto errRtn;
+ }
+#else
+ if (!SetProp (hwndFrame, szPropFrameFilterH, HIWORD(pFF)))
+ {
+ goto errRtn;
+ }
+
+ if (!SetProp (hwndFrame, szPropFrameFilterL, LOWORD(pFF)))
+ {
+ goto errRtn;
+ }
+#endif
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::Create ( %lx )\n",
+ NULL, NOERROR ));
+ return NOERROR;
+
+errRtn:
+ if (pFF)
+ {
+ pFF->SafeRelease();
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::Create ( %lx )\n",
+ NULL, ResultFromScode(E_OUTOFMEMORY)));
+
+ return ResultFromScode(E_OUTOFMEMORY);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFrameFilter::CFrameFilter
+//
+// Synopsis: Constructor for the frame filter object
+//
+// Effects:
+//
+// Arguments: [hwndFrame] -- the container's frame
+// [hwndActiveObj] -- the inplace object's window
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CFrameFilter_ctor)
+CFrameFilter::CFrameFilter (HWND hwndFrame, HWND hwndActiveObj)
+{
+ VDATEHEAP();
+
+ m_hwndFrame = hwndFrame;
+ m_hwndObject = hwndActiveObj;
+ m_lpFrame = NULL;
+ m_lpObject = NULL;
+ m_lpfnPrevWndProc = NULL;
+ m_fObjectMenu = FALSE;
+ m_fCurItemPopup = FALSE;
+ m_fInMenuMode = FALSE;
+ m_fGotMenuCloseEvent = FALSE;
+ m_uCurItemID = NULL;
+ m_cAltTab = NULL;
+ m_hwndFocusOnEnter = NULL;
+ m_fDiscardWmCommand = FALSE;
+ m_cmdId = NULL;
+ m_fRemovedWndProc = FALSE;
+#ifdef _CHICAGO_
+ m_fInNCACTIVATE = FALSE;
+#endif
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFrameFileter::~CFrameFilter
+//
+// Synopsis: destroys the object
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CFrameFilter_dtor)
+CFrameFilter::~CFrameFilter(void)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::~CFrameFilter ( )\n",
+ this));
+
+ PrivMemFree(m_lpOleMenu);
+
+ // remove the FrameWndFilterProc hook. We do this *before*
+ // the Releases since those releases may make outgoing calls
+ // (we'd like to be in a 'safe' state).
+
+ // REVIEW32: We may want to check to see if we're the current
+ // window proc before blowing it away. Some apps (like Word)
+ // go ahead and blow away the wndproc by theselves without calling
+ // OleSetMenuDescriptor(NULL);
+
+ RemoveWndProc();
+
+ if (m_lpFrame != NULL)
+ {
+ // OleUnInitialize could have been called.
+ // In such case we do not want to call releas
+ // on OLeObject.
+ COleTls tls;
+ if(tls->cOleInits > 0)
+ {
+ SafeReleaseAndNULL((IUnknown **)&m_lpFrame);
+ SafeReleaseAndNULL((IUnknown **)&m_lpObject);
+ }
+ else
+ {
+ m_lpObject = NULL;
+ m_lpFrame = NULL;
+ }
+ }
+
+
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::~CFrameFilter ( )\n",
+ this));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFrameFilter::RemoveWndProc
+//
+// Synopsis: un-installs our window proc for inplace-processing
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires: none
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 04-Aug-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+void CFrameFilter::RemoveWndProc()
+{
+ LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::RemoveWndProc ( )\n",
+ this));
+
+ if( m_fRemovedWndProc == FALSE)
+ {
+ m_fRemovedWndProc = TRUE;
+
+ if (m_lpfnPrevWndProc)
+ {
+ // If the sub-classing has already been removed, then
+ // don't bother to remove it again. This only happens
+ // to be the case with Word 6 and inplace embeddings.
+ // At some future date, we might want to make this for
+ // non-wow things to (just to be safe). Also note, that
+ // if somebody comes along later (after us) and
+ // sub-classes the window, we won't be able to remove
+ // ourselves so we just avoid it. Maybe this function
+ // should return a BOOL indicating this failure
+ // condition?
+
+ if (!IsWOWThread() ||
+ GetWindowLong(m_hwndFrame, GWL_WNDPROC) ==
+ (LONG)FrameWndFilterProc)
+ {
+ SetWindowLong (m_hwndFrame, GWL_WNDPROC,
+ (LONG) m_lpfnPrevWndProc);
+
+ }
+
+ // We remove the window property at the
+ // same time as the sub-classing since
+ // the window property is the flag as to
+ // whether we are doing sub-classing. The
+ // problem this solves is that what if
+ // OleSetMenuDescriptor is called while we
+ // have the menu subclassed? We won't remove
+ // this property until the outer most sub
+ // classing is exited which if we are setting
+ // a new sub-class will remove the new
+ // sub-class' window property. Therefore, it
+ // will look like the window is not sub-classed
+ // at all.
+#ifdef WIN32
+ RemoveProp (m_hwndFrame, szPropFrameFilter);
+#else
+ RemoveProp (m_hwndFrame, szPropFrameFilterH);
+ RemoveProp (m_hwndFrame, szPropFrameFilterL);
+#endif
+ }
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::RemoveWndProc ( )\n",
+ this));
+
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFrameFilter::OnSysCommand
+//
+// Synopsis: Process system messages
+//
+// Effects:
+//
+// Arguments: [uParam] -- the first message argument
+// [lParam] -- the second message argument
+//
+// Requires: the 'this' pointer must have been stabilized before
+// calling this function.
+//
+// Returns: LRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: big switch to deal with the different types of messages
+// see comments below
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+// 07-Dec-93 alexgo removed inlining
+//
+// Notes: FrameWndFilterProc currently does the work of stabilizing
+// the framefilter's 'this' pointer.
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CFrameFilter_OnSysCommand)
+LRESULT CFrameFilter::OnSysCommand(UINT uParam, LONG lParam)
+{
+ VDATEHEAP();
+
+ UINT uParamTmp = (uParam & 0xFFF0);
+ LRESULT lresult;
+
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnSysCommand ( %lu ,"
+ " %ld )\n", this, uParam, lParam));
+
+ // this lets the sending app continue processing
+ if (InSendMessage())
+ {
+
+ SSReplyMessage(NULL);
+ }
+
+ switch (uParamTmp)
+ {
+ case SC_KEYMENU:
+ case SC_MOUSEMENU:
+ OnEnterMenuMode();
+ SSCallWindowProc((WNDPROC) m_lpfnPrevWndProc, m_hwndFrame,
+ WM_SYSCOMMAND, uParam, lParam);
+
+ // By this time menu processing would've been completed.
+
+ if (! m_fGotMenuCloseEvent)
+ {
+ // Can happen if user cancelled menu mode when MDI
+ // window's system menu is down. Hence generate
+ // the message here
+
+ SSSendMessage(m_hwndFrame, WM_MENUSELECT, 0,
+ MAKELONG(-1,0));
+ }
+
+ // We can not set m_fObjectMenu to FALSE yet, 'cause we
+ // could be recieving the WM_COMMAND (if a menu item is
+ // selected), which gets posted by the windows' menu
+ // processing code.
+ // We will clear the flag when we get OM_CLEAR_MENU_STATE
+ // message. Even if WM_COMMAND got generated, this message
+ // will come after that
+ PostMessage (m_hwndFrame, uOleMessage, OM_CLEAR_MENU_STATE,
+ 0L);
+ OnExitMenuMode();
+ lresult = 0L;
+ goto errRtn;
+
+ case SC_NEXTWINDOW:
+ case SC_PREVWINDOW:
+
+ OnEnterAltTabMode();
+ lresult = SSCallWindowProc((WNDPROC)m_lpfnPrevWndProc,
+ m_hwndFrame, WM_SYSCOMMAND, uParam, lParam);
+ OnExitAltTabMode();
+
+ goto errRtn;
+
+ default:
+ break;
+ }
+
+ lresult = SSCallWindowProc((WNDPROC)m_lpfnPrevWndProc, m_hwndFrame,
+ WM_SYSCOMMAND, uParam, lParam);
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnSysCommand ( %lx )\n",
+ this, lresult));
+
+ return lresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFrameFilter::OnEnterMenuMode
+//
+// Synopsis: called by the SysCommand processing, puts us into in
+// InMenuMode, sets the focus and installs our message filter
+// hook.
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Feb-94 alexgo restored OLE32 in GetModuleHandle
+// 31-Dec-93 erikgav removed hardcoded "OLE2" in GetModuleHandle
+// 07-Dec-93 alexgo removed inlining
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes: REVIEW32: We may need to update this to reflect new
+// focus management policies.
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CFrameFilter_OnEnterMenuMode)
+void CFrameFilter::OnEnterMenuMode()
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnEnterMenuMode ( )\n",
+ this ));
+
+ if (m_fInMenuMode)
+ {
+ goto errRtn;
+ }
+
+ m_fInMenuMode = TRUE;
+ m_fGotMenuCloseEvent = FALSE;
+ m_hwndFocusOnEnter = SetFocus(m_hwndFrame);
+
+ if (!m_lpFrame)
+ {
+ goto errRtn;
+ }
+
+ // REVIEW32: hMsgHook is a static (formerly global) variable for
+ // the whole dll. This may cause problems on NT (with threads, etc)
+ // (what happens if we haven't yet unhooked a previous call and
+ // we get here again????)
+
+ // BUGBUG: GetModuleHandle("OLE2") below -- DLL's are
+ // named differently across platforms
+
+ if (hMsgHook = (HHOOK) SetWindowsHookEx (WH_MSGFILTER,
+ (HOOKPROC) MessageFilterProc,
+ //GetModuleHandle(NULL),
+ GetModuleHandle(TEXT("OLE32")),
+ GetCurrentThreadId()))
+ {
+ pFrameFilter = this;
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnEnterMenuMode ( )\n",
+ this ));
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFrameFilter::OnExitMenuMode
+//
+// Synopsis: takes us out of InMenuMode
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: Resets the focus and unhooks our callback function
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+// 07-Dec-93 alexgo removed inlining
+//
+// Notes: REVIEW32:: see OnEnterMenuMode
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CFrameFilter_OnExitMenuMode)
+void CFrameFilter::OnExitMenuMode()
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnExitMenuMode ( )\n",
+ this));
+
+ if (m_fInMenuMode)
+ {
+
+ m_fInMenuMode = FALSE;
+ m_fGotMenuCloseEvent = TRUE;
+ m_uCurItemID = NULL;
+
+ if (hMsgHook)
+ {
+ UnhookWindowsHookEx(hMsgHook);
+ hMsgHook = NULL;
+ pFrameFilter = NULL;
+ }
+
+ SetFocus(m_hwndFocusOnEnter);
+ m_hwndFocusOnEnter = NULL;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnExitMenuMode ( )\n",
+ this));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFrameFileter::OnEnterAltTabMode
+//
+// Synopsis: enters AltTab mode and sets the focus
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+// 07-Dec-93 alexgo removed inlining
+//
+// Notes: REVIEW32: we may need to modify to implement new
+// focus management policy
+//
+//--------------------------------------------------------------------------
+
+void CFrameFilter::OnEnterAltTabMode(void)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnEnterAltTabMode ( )\n",
+ this ));
+
+ if (m_cAltTab == NULL)
+ {
+
+ m_fInMenuMode = TRUE;
+ // this will prevent SetFocus from getting
+ // delegated to the object
+ m_hwndFocusOnEnter = SetFocus(m_hwndFrame);
+ m_fInMenuMode = FALSE;
+ }
+
+ m_cAltTab++;
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnEnterAltTabMode ( )\n",
+ this ));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFrameFilter::OnExitAltTabMode
+//
+// Synopsis: exits alt-tab mode and sets the focus
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+// 07-Dec-93 alexgo removed inlining
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+void CFrameFilter::OnExitAltTabMode()
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnExitAltTabMode ( )\n",
+ this ));
+
+ Assert(m_cAltTab != NULL);
+
+ if (--m_cAltTab == 0)
+ {
+ // The m_hwndFocusOnEnter would've been set to NULL if we are
+ // going to ALT-TAB out into some other process. In that case
+ // we would have got WM_ACTIVATEAPP and/or WM_KILLFOCUS.
+ if (m_hwndFocusOnEnter)
+ {
+ SetFocus(m_hwndFocusOnEnter);
+ m_hwndFocusOnEnter = NULL;
+ }
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnExitAltTabMode ( )\n",
+ this ));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFrameFilter::OnMessage
+//
+// Synopsis: Handles window message processing
+//
+// Effects:
+//
+// Arguments: [msg] -- the window message
+// [uParam] -- the first argument
+// [lParam] -- the second argument
+//
+// Requires:
+//
+// Returns: LRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: a big switch to deal with the different commands
+// see comments below
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+// 07-Dec-93 alexgo removed inlining
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CFrameFilter_OnMessage)
+LRESULT CFrameFilter::OnMessage(UINT msg, UINT uParam, LONG lParam)
+{
+ VDATEHEAP();
+ LRESULT lresult;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::OnMessage ( %u , %u ,"
+ " %ld )\n", this, msg, uParam, lParam));
+
+ // We come to this routine only if the message is not WM_SYSCOMMAND
+
+ switch (msg)
+ {
+ case WM_SETFOCUS:
+ if (m_fInMenuMode)
+ {
+ lresult = SSDefWindowProc (m_hwndFrame, msg, uParam, lParam);
+ goto errRtn;
+ }
+ break;
+
+ case WM_MENUSELECT:
+ if (m_fInMenuMode)
+ {
+#ifdef WIN32
+ HMENU hmenu = (HMENU) lParam;
+ UINT fwMenu = HIWORD(uParam);
+ UINT uItem = 0;
+
+ // There is a subtle difference in the message between
+ // Win16 & Win32 here. In Win16, the item is either
+ // an item id or a menu handle for a pop up menu.
+ // In Win32, the item is an item id or an offset
+ // in a menu if it is a popup menu handle. To minimize
+ // changes, we map this field as was appropriate for
+ // Win16.
+
+ if ( (fwMenu & MF_POPUP) &&
+ (hmenu != 0) )
+ {
+ uItem = (UINT) GetSubMenu(hmenu, (int) LOWORD(uParam));
+ }
+ else {
+ uItem = LOWORD(uParam);
+ }
+
+#ifdef _CHICAGO_
+ if (!uItem) {
+ uItem = LOWORD(uParam);
+ }
+#endif // _CHICAGO_
+
+#else // !WIN32
+ HMENU hmenu = (HMENU)HIWORD(lParam);
+ UINT fwMenu = LOWORD(lParam);
+ UINT uItem = uParam;
+#endif // else !WIN32
+
+
+ m_uCurItemID = uItem;
+ m_fCurItemPopup = fwMenu & MF_POPUP;
+
+ if (hmenu == 0 && fwMenu == 0xFFFF)
+ {
+ // end of menu processing
+
+ // We can not set m_fObjectMenu to FALSE yet,
+ // because we could be recieving the
+ // WM_COMMAND (if a menu item is selected),
+ // which is posted by the windows' menu
+ // processing code, and will be recieved at
+ // a later time.
+
+ // There is no way to figure whether the user
+ // has selected a menu (which implies that
+ // WM_COMMAND is posted), or ESCaped out of
+ // menu selection.
+
+ // This problem is handled by posting a
+ // message to ourselves to clear the flag.
+ // See CFrameFilter::OnSysCommand() for
+ // more details...
+
+ m_fGotMenuCloseEvent = TRUE;
+ SSSendMessage(m_hwndObject, msg, uParam, lParam);
+ }
+ else
+ {
+ if (fwMenu & MF_SYSMENU)
+ {
+ m_fObjectMenu = FALSE;
+ // if it is top level menu, see whose
+ // menu it is
+ }
+ else if (IsHmenuEqual(hmenu, m_hmenuCombined))
+ {
+ // set m_fObjectMenu
+ IsObjectMenu (uItem, fwMenu);
+
+ // this flag must not be modified
+ // when nested menus are selected.
+ }
+
+ if (m_fObjectMenu)
+ {
+ lresult = SSSendMessage(m_hwndObject, msg, uParam, lParam);
+ goto errRtn;
+ }
+ } // else
+ } // if (m_fInMenuMode)
+ break; // WM_MENUSELECT
+
+ case WM_MEASUREITEM:
+ case WM_DRAWITEM:
+ if (m_fInMenuMode && m_fObjectMenu)
+ {
+ lresult = SSSendMessage(m_hwndObject, msg, uParam, lParam);
+ goto errRtn;
+ }
+ break;
+
+ case WM_ENTERIDLE:
+ {
+ WCHAR wstr[10];
+
+ // We need to post this message if the server is
+ // SnapGraphics. See bug #18576.
+ GetClassName(m_hwndObject, wstr, 10);
+ if (0 == lstrcmpW(OLESTR("MGX:SNAP2"), wstr))
+ {
+ PostMessage(m_hwndObject, msg, uParam, lParam);
+ }
+ else
+ {
+ SSSendMessage(m_hwndObject, msg, uParam, lParam);
+ }
+ }
+ break;
+
+ case WM_INITMENU:
+ m_fObjectMenu = FALSE;
+ if (m_fInMenuMode && IsHmenuEqual(m_hmenuCombined, (HMENU)uParam))
+ {
+ SSSendMessage(m_hwndObject, msg, uParam, lParam);
+ }
+ break;
+
+ case WM_INITMENUPOPUP:
+ if (!m_fInMenuMode)
+ {
+ // Accelarator translation....
+
+ if (! ((BOOL) HIWORD(lParam)))
+ {
+ // if not a system menu, see whether windows
+ // generated WM_INITMENUPOPUP for object's
+ // menu because of menu collision. If so
+ // fix it and route it to container
+
+ // menu collisions can occur with combined
+ // menus (from object and container)
+ if (IsMenuCollision(uParam, lParam))
+ {
+ lresult = 0L;
+ goto errRtn;
+ }
+ }
+ }
+
+ if (m_fObjectMenu)
+ {
+ lresult = SSSendMessage(m_hwndObject, msg, uParam, lParam);
+ goto errRtn;
+ }
+ break;
+
+ case WM_SYSCHAR:
+ if (InSendMessage())
+ {
+ SSReplyMessage(NULL);
+ }
+ break;
+
+#ifdef _CHICAGO_
+ case WM_NCACTIVATE:
+ //Note: On chicago with new rpc WM_NCACTIVATE gets dispatched
+ // recursively until stack overflow.
+ // Needs to be reviewed. (OS problem)
+ // See bug 25313, 25490, 25549
+
+ if (m_fInNCACTIVATE)
+ {
+ goto errRtn;
+ }
+ m_fInNCACTIVATE = TRUE;
+ break;
+#endif // _CHICAGO_
+
+ case WM_COMMAND:
+ // End of menu processing or accelartor translation.
+ // Check whether we should give the message to the object
+ // or not.
+
+ // If the LOWORD of lParam is NON-NULL, then the message
+ // must be from a control, and the control must belong to
+ // the container app.
+
+ // REVIEW32: what about app-specific commands with NULL
+ // lParams???
+
+ if (LOWORD(lParam) == 0)
+ {
+ m_cmdId = 0;
+
+ if (m_fDiscardWmCommand)
+ {
+ m_fDiscardWmCommand = FALSE;
+ lresult = 0L;
+ goto errRtn;
+ }
+
+ if (m_fObjectMenu)
+ {
+ m_fObjectMenu = FALSE;
+ lresult = PostMessage(m_hwndObject, msg, uParam,lParam);
+ goto errRtn;
+ }
+ }
+ break;
+
+ case WM_ACTIVATEAPP:
+ case WM_KILLFOCUS:
+ // If in ALT-TAB mode, we get these messages only if we are
+ // going to ALT-TAB out in to some other task. In this case,
+ // on exit from ALT-TAB mode we wouldn't want to set
+ // focus back to the window that had the focus on
+ // entering the ALT-TAB mode.
+
+ if (m_cAltTab)
+ {
+ m_hwndFocusOnEnter = NULL;
+ }
+ break;
+
+ default:
+ if (msg == uOleMessage)
+ {
+ switch(uParam)
+ {
+ case OM_CLEAR_MENU_STATE:
+ m_fObjectMenu = FALSE;
+ break;
+
+ case OM_COMMAND_ID:
+ // this message is sent by
+ // OleTranslateAccelerator, before it actually
+ // calls the lpFrame->TranslateAccelerator
+ // method.
+ // We remember the command id here, later it
+ // gets used if the container's calling of
+ // TranslateAccelerator results in a
+ // WM_INITMENUPOPUP for the object because
+ // of command id collision. In that case we
+ // scan the menu list to see whether there is
+ // any container menu which has the same
+ // command id, if so we generate
+ // WM_INITMENUPOPUP for that menu.
+ m_cmdId = LOWORD(lParam);
+ break;
+
+ default:
+ AssertSz(FALSE, "Unexpected OLE private message");
+ break;
+ } // switch
+
+ lresult = 0L;
+ goto errRtn;
+ } // if (msg == uOleMessage)
+ else if (m_fInMenuMode && (msg == uOmPostWmCommand))
+ {
+ // if the current selection is a popup menu then
+ // return its menu handle else post the command
+ // and return NULL.
+
+ if (m_fCurItemPopup)
+ {
+ lresult = m_uCurItemID;
+ goto errRtn;
+ }
+
+ HWND hwnd;
+
+ hwnd = m_hwndFrame;
+ if (m_fObjectMenu)
+ {
+ hwnd = m_hwndObject;
+ }
+ PostMessage (hwnd, WM_COMMAND, m_uCurItemID, 0L);
+
+ m_fObjectMenu = FALSE;
+ lresult = 0L;
+ goto errRtn;
+ } // else if
+
+ break; // default
+
+ } // switch
+
+ lresult = SSCallWindowProc ((WNDPROC) m_lpfnPrevWndProc, m_hwndFrame,
+ msg, uParam, lParam);
+
+errRtn:
+#ifdef _CHICAGO_
+ m_fInNCACTIVATE = FALSE;
+#endif
+ LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::OnMessage ( %lu )\n",
+ this, lresult));
+
+ return lresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFrameFilter::IsObjectMenu
+//
+// Synopsis: This gets called when WM_MENUSELECT is sent for a
+// top level (either POPUP or normal) menu item. Figures
+// out whether [uMenuItem] really belongs to the in-place object
+//
+// Effects:
+//
+// Arguments: [uMenuItem] -- the menu in question
+// [fwMenu] -- the menu type
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: Searchs through our ole menu descriptor to find a match
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+// 07-Dec-93 alexgo removed inlining
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CFrameFilter_IsObjectMenu)
+void CFrameFilter::IsObjectMenu(UINT uMenuItem, UINT fwMenu)
+{
+ VDATEHEAP();
+ int i,
+ iMenuCnt;
+ LPOLEMENUITEM lpMenuList;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::IsObjectMenu ( %u , "
+ "%u )\n", this, uMenuItem, fwMenu));
+
+ if (m_hmenuCombined == NULL)
+ {
+ goto errRtn;
+ }
+
+
+ m_fObjectMenu = FALSE;
+
+ lpMenuList = m_lpOleMenu->menuitem;
+ iMenuCnt = (int) m_lpOleMenu->lMenuCnt;
+
+ for (i = 0; i < iMenuCnt; i++)
+ {
+ // Are the types of the menus the same?
+ if ((fwMenu & MF_POPUP) == lpMenuList[i].fwPopup)
+ {
+ // Are we dealing with a menu handle?
+ if (fwMenu & MF_POPUP)
+ {
+ // See if windows handles are equal
+ if (IsHmenuEqual((HMENU) uMenuItem,
+ (HMENU)lpMenuList[i].item))
+ {
+ m_fObjectMenu = lpMenuList[i].fObjectMenu;
+ break;
+ }
+ }
+ // Are item handles equal?
+ else if (uMenuItem == lpMenuList[i].item)
+ {
+ m_fObjectMenu = lpMenuList[i].fObjectMenu;
+
+ // If the menu isn't hilited, another menu with a duplicate
+ // menu ID must have been selected. The duplicate menu was
+ // probably created by the other application.
+ if (!(GetMenuState(m_hmenuCombined, uMenuItem, MF_BYCOMMAND)
+ & MF_HILITE))
+ {
+ m_fObjectMenu = !m_fObjectMenu;
+ }
+ break;
+ }
+ }
+ }
+
+errRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::IsObjectMenu ( )\n",
+ this ));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFrameFilter::IsMenuCollision
+//
+// Synopsis: Determines if we've had a menu collission. This gets called
+// as a result of WM_INITMENUPOPUP during accelerator translation
+//
+// Effects:
+//
+// Arguments: [uParam] -- the first window message argument
+// [lParam] -- the second argument
+//
+// Requires:
+//
+// Returns: BOOL
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+// 07-Dec-93 alexgo changed Assert(hmenuPopup) to an if
+// in merging with 16bit RC9 sources
+// 07-Dec-93 alexgo removed inlining
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+BOOL CFrameFilter::IsMenuCollision(UINT uParam, LONG lParam)
+{
+ BOOL fRet;
+ int iCntrMenu,
+ iObjMenu,
+ iMenuCnt;
+ BOOL fGenerateWmCommand;
+ HMENU hmenuPopup;
+ LPOLEMENUITEM lpMenuList;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::IsMenuCollision ( %u ,"
+ " %ld )\n", this, uParam, lParam ));
+
+ if (m_hmenuCombined == NULL)
+ {
+ fRet = FALSE;
+ goto errRtn;
+ }
+
+ if (m_lpOleMenu == NULL)
+ {
+ fRet = FALSE;
+ goto errRtn;
+ }
+
+ hmenuPopup = (HMENU) uParam;
+ iObjMenu = (int) LOWORD(lParam);
+
+ lpMenuList = m_lpOleMenu->menuitem;
+ iMenuCnt = (int) m_lpOleMenu->lMenuCnt;
+
+ if (iObjMenu >= iMenuCnt)
+ {
+ fRet = FALSE;
+ goto errRtn;
+ }
+
+ if( hmenuPopup != (HMENU)lpMenuList[iObjMenu].item )
+ {
+ // this could be the container's popmenu, not associated
+ // with the frame
+ fRet = FALSE;
+ goto errRtn;
+ }
+
+ Assert(lpMenuList[iObjMenu].fwPopup);
+
+ if (! lpMenuList[iObjMenu].fObjectMenu)
+ {
+ fRet = FALSE; // container's pop-up menu
+ goto errRtn;
+ }
+
+ // Otherwise the popup menu belongs to the object. This can only
+ // happen because of id collision. Start scanning the menus starting
+ // from the next top level menu item to look for a match in
+ // container's menus (while scanning skip object's menus)
+
+
+ // It is possible that the colliding command id may not be associated
+ // with any of the container's menus. In that case we must send
+ // WM_COMMAND to the container.
+
+ fGenerateWmCommand = TRUE;
+ m_fDiscardWmCommand = FALSE;
+ iCntrMenu = iObjMenu + 1;
+
+
+ while (iCntrMenu < iMenuCnt)
+ {
+ if (! lpMenuList[iCntrMenu].fObjectMenu)
+ {
+
+ if (lpMenuList[iCntrMenu].fwPopup & MF_POPUP)
+ {
+ if (GetMenuState(
+ (HMENU)lpMenuList[iCntrMenu].item,
+ m_cmdId, MF_BYCOMMAND) != -1)
+ {
+ // We found match in the container's
+ // menu list Generate WM_INITMENUPOPUP
+ // for the corresponding popup
+ SSCallWindowProc ((WNDPROC)
+ m_lpfnPrevWndProc,
+ m_hwndFrame, WM_INITMENUPOPUP,
+ lpMenuList[iCntrMenu].item
+ /*uParam*/,
+ MAKELONG(iCntrMenu,
+ HIWORD(lParam)));
+
+ // We have sent WM_INITMENUPOPUP to
+ // the container.
+ // Now rechek the menu state. If
+ // disabled or grayed then
+ // don't generate WM_COMMAND
+
+ if (GetMenuState((HMENU)
+ lpMenuList[iCntrMenu].item,
+ m_cmdId, MF_BYCOMMAND) &
+ (MF_DISABLED | MF_GRAYED))
+ {
+ fGenerateWmCommand = FALSE;
+ }
+
+ break;
+ }
+
+ }
+ else
+ {
+ // top-level, non-popup container menu
+ if (GetMenuItemID(m_lpOleMenu->hmenuCombined,
+ iCntrMenu) == m_cmdId)
+ {
+ // No need to generate
+ // WM_INITMENUPOPUP
+
+ // Chek the menu state. If disabled or
+ // grayed then don't generate
+ // WM_COMMAND
+ if (GetMenuState(
+ m_lpOleMenu->hmenuCombined,
+ m_cmdId, MF_BYCOMMAND) &
+ (MF_DISABLED | MF_GRAYED))
+ {
+ fGenerateWmCommand = FALSE;
+ }
+
+ break;
+ }
+ }
+ }
+
+ iCntrMenu++;
+ }
+
+ // Check the object's colliding menu's status
+ if (GetMenuState((HMENU)lpMenuList[iObjMenu].item, m_cmdId,
+ MF_BYCOMMAND) & (MF_DISABLED | MF_GRAYED))
+ {
+ // Then windows is not going to genearte WM_COMMAND for the
+ // object's menu, so we will generate
+ // the command and send it to the container
+
+ if (fGenerateWmCommand)
+ {
+ SSCallWindowProc ((WNDPROC) m_lpfnPrevWndProc,
+ m_hwndFrame, WM_COMMAND, m_cmdId,
+ MAKELONG(0, 1)); /* not from control */
+ // & and as result of
+ // accelerator
+ m_cmdId = NULL;
+ }
+ }
+ else
+ {
+
+ // Wait for WM_COMMAND generated by windows to come to our
+ // frame filter wndproc which would have been sent to the
+ // container anyway because we have not set the m_fObjectMenu
+ // flag.
+ //
+ // But we need to throw it away if the container's menu
+ // associated with the command is disabled or grayed
+
+ if (! fGenerateWmCommand)
+ {
+ m_fDiscardWmCommand = TRUE;
+ }
+ }
+
+ fRet = TRUE;
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::IsMenuCollision "
+ "( %lu )\n", this, fRet));
+
+ return fRet;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFrameFilter::DoContextSensitiveHelp
+//
+// Synopsis: Calls IOIPF->ContextSensitive help on both the container
+// and the object.
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: FALSE if we're in popup menu mode, TRUE otherwise
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+// 07-Dec-93 alexgo removed inlining
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CFrameFilter_DoContextSensitiveHelp)
+BOOL CFrameFilter::DoContextSensitiveHelp(void)
+{
+ VDATEHEAP();
+ BOOL fRet;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::DoContextSensitiveHelp"
+ " ( )\n", this ));
+
+ if (m_fCurItemPopup)
+ {
+ fRet = FALSE;
+ }
+ else
+ {
+ m_lpFrame->ContextSensitiveHelp(TRUE);
+ m_lpObject->ContextSensitiveHelp (TRUE);
+
+ PostMessage (m_hwndFrame, WM_COMMAND, m_uCurItemID, 0L);
+ fRet = TRUE;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::DoContextSensitiveHelp"
+ " ( %lu )\n", this, fRet));
+
+ return fRet;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFrameFilter::GetActiveObject
+//
+// Synopsis: Returns the IOleInplaceActiveObject interface pointer
+//
+// Effects:
+//
+// Arguments: lplpOIAO
+//
+// Requires:
+//
+// Returns: NOERROR or E_INVALIDARG
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 28-Jul-94 bobday created for WinWord hack
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CFrameFilter_GetActiveObject)
+STDMETHODIMP CFrameFilter::GetActiveObject( LPOLEINPLACEACTIVEOBJECT *lplpOIAO)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CFrameFilter::GetActiveObject"
+ " ( %p )\n", this, lplpOIAO ));
+
+ VDATEPTROUT( lplpOIAO, LPOLEINPLACEACTIVEOBJECT);
+
+ *lplpOIAO = m_lpObject;
+
+ if ( m_lpObject )
+ {
+ m_lpObject->AddRef();
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CFrameFilter::GetActiveObject"
+ " ( %lx ) [ %p ]\n", this, NOERROR , *lplpOIAO ));
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wGetFrameFilterPtr
+//
+// Synopsis: Gets the CFrame object from the window
+//
+// Effects:
+//
+// Arguments: [hwndFrame] -- the window to get the CFrame object from
+//
+// Requires:
+//
+// Returns: pointer to the frame filter
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+inline PCFRAMEFILTER wGetFrameFilterPtr(HWND hwndFrame)
+{
+ VDATEHEAP();
+
+#ifdef WIN32
+
+ return (PCFRAMEFILTER) GetProp (hwndFrame, szPropFrameFilter);
+#else
+ WORD hiword;
+ WORD loword;
+
+ if (!(hiword = GetProp (hwndFrame, szPropFrameFilterH)))
+ {
+ return NULL;
+ }
+
+ loword = GetProp (hwndFrame, szPropFrameFilterL);
+
+ return (PCFRAMEFILTER) (MAKELONG(loword, hiword));
+#endif
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wGetOleMenuPtr
+//
+// Synopsis: Locks a handle to an ole menu and returns the pointer
+// (after some error checking)
+//
+// Effects:
+//
+// Arguments: [holemenu]
+//
+// Requires:
+//
+// Returns: pointer to the ole menu
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+LPOLEMENU wGetOleMenuPtr(HOLEMENU holemenu)
+{
+ VDATEHEAP();
+
+ LPOLEMENU lpOleMenu;
+
+ if (! (holemenu &&
+ (lpOleMenu = (LPOLEMENU) GlobalLock((HGLOBAL) holemenu))))
+ {
+ return NULL;
+ }
+
+ if (lpOleMenu->wSignature != wSignature)
+ {
+ AssertSz(FALSE, "Error - handle is not a HOLEMENU");
+ GlobalUnlock((HGLOBAL) holemenu);
+ return NULL;
+ }
+
+ return lpOleMenu;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wReleaseOleMenuPtr
+//
+// Synopsis: calls GlobalUnlock
+//
+// Effects:
+//
+// Arguments: [holemenu] -- handle to the ole menu
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline void wReleaseOleMenuPtr(HOLEMENU holemenu)
+{
+ VDATEHEAP();
+
+ GlobalUnlock((HGLOBAL) holemenu);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: MessageFilterProc
+//
+// Synopsis: The message filter installed when entering menu mode;
+// handles context sensitive help
+//
+// Effects:
+//
+// Arguments: [nCode] -- hook code
+// [wParam] -- first arg
+// [lParam] -- second arg
+//
+// Requires:
+//
+// Returns: LRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(MessageFilterProc)
+STDAPI_(LRESULT) MessageFilterProc(int nCode, WPARAM wParam, LPARAM lParam)
+{
+ VDATEHEAP();
+ LRESULT lresult;
+ LPMSG lpMsg = (LPMSG) lParam;
+
+
+ LEDebugOut((DEB_TRACE, "%p _IN MessageFilterProc ( %d , %ld , %lu )\n",
+ NULL, nCode, (LONG)wParam, lParam));
+
+ // If it is not the F1 key then let the message (wihtout modification)
+ // go to the next proc in the hook/filter chain.
+
+ if (lpMsg && lpMsg->message == WM_KEYDOWN
+ && lpMsg->wParam == VK_F1 && pFrameFilter)
+ {
+ if (pFrameFilter->DoContextSensitiveHelp())
+ {
+ // Change message value to be WM_CANCELMODE and then
+ // call the next hook. When the windows USER.EXE's
+ // menu processing code sees this message it will
+ // bring down menu state and come out of its
+ // menu processing loop.
+
+ lpMsg->message = WM_CANCELMODE;
+ lpMsg->wParam = NULL;
+ lpMsg->lParam = NULL;
+ }
+ else
+ {
+ lresult = TRUE; // otherwise throw away this message.
+ goto errRtn;
+ }
+ }
+
+ lresult = CallNextHookEx (hMsgHook, nCode, wParam, lParam);
+
+errRtn:
+ LEDebugOut((DEB_TRACE, "%p OUT MessageFilterProc ( %ld )\n", NULL,
+ lresult));
+
+ return lresult;
+}
diff --git a/private/ole32/ole232/inplace/inplace.h b/private/ole32/ole232/inplace/inplace.h
new file mode 100644
index 000000000..73931a1af
--- /dev/null
+++ b/private/ole32/ole232/inplace/inplace.h
@@ -0,0 +1,151 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: inplace.h
+//
+// Contents: Private API's and classes for the inplace OLE API's
+//
+// Classes: CFrameFilter
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 24-Jan-94 alexgo first pass converting to Cairo style
+// memory allocation
+// 07-Dec-93 alexgo removed inlining
+// 01-Dec-93 alexgo 32bit port
+//
+//--------------------------------------------------------------------------
+
+#if !defined( _INPLACE_H_ )
+#define _INPLACE_H_
+
+// This ACCEL structure and the related constants definitions come with WIN32.
+// Win31 also uses the same stuff internally but it's not exposed in the
+// header files.
+
+#ifndef FVIRTKEY
+
+#define FVIRTKEY TRUE // Assumed to be == TRUE
+#define FLASTKEY 0x80 // Indicates last key in the table
+#define FNOINVERT 0x02
+#define FSHIFT 0x04
+#define FCONTROL 0x08
+#define FALT 0x10
+
+#pragma pack(1)
+typedef struct tagACCEL { // Accelerator Table structure
+ BYTE fVirt;
+ WORD key;
+ WORD cmd;
+} ACCEL, FAR* LPACCEL;
+#pragma pack()
+
+#endif // FVIRTKEY
+
+// private structures
+
+typedef struct tagOLEMENUITEM
+{
+ UINT item;
+ WORD fwPopup;
+ BOOL fObjectMenu;
+} OLEMENUITEM;
+typedef OLEMENUITEM FAR* LPOLEMENUITEM;
+
+typedef struct tagOLEMENU
+{
+ WORD wSignature;
+ HWND hwndFrame;
+ HMENU hmenuCombined;
+ OLEMENUGROUPWIDTHS MenuWidths;
+ LONG lMenuCnt;
+ OLEMENUITEM menuitem[1];
+} OLEMENU;
+typedef OLEMENU FAR* LPOLEMENU;
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CFrameFilter
+//
+// Purpose: Gets attached to an apps window so we can store various
+// bits of relevant info
+//
+// Interface:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes: CSafeRefCount inherits CPrivAlloc
+//
+//--------------------------------------------------------------------------
+
+class FAR CFrameFilter : public CSafeRefCount
+{
+public:
+ static HRESULT Create(LPOLEMENU lpOleMenu, HMENU hmenuCombined,
+ HWND hwndFrame, HWND hwndActiveObj,
+ LPOLEINPLACEFRAME lpFrame,
+ LPOLEINPLACEACTIVEOBJECT lpActiveObj);
+
+ CFrameFilter (HWND hwndFrame, HWND hwndActiveObj);
+ ~CFrameFilter(void);
+
+ LRESULT OnSysCommand(UINT uParam, LONG lParam);
+ void OnEnterMenuMode(void);
+ void OnExitMenuMode(void);
+ void OnEnterAltTabMode(void);
+ void OnExitAltTabMode(void);
+ LRESULT OnMessage(UINT msg, UINT uParam, LONG lParam);
+ void IsObjectMenu (UINT uMenuItem, UINT fwMenu);
+ BOOL IsMenuCollision(UINT uParam, LONG lParam);
+ BOOL DoContextSensitiveHelp();
+ STDMETHOD(GetActiveObject) (
+ LPOLEINPLACEACTIVEOBJECT *lplpActiveObj);
+
+ void RemoveWndProc();
+
+private:
+ HWND m_hwndObject;
+ HWND m_hwndFrame;
+ LPOLEINPLACEFRAME m_lpFrame;
+ LPOLEINPLACEACTIVEOBJECT m_lpObject;
+ WNDPROC m_lpfnPrevWndProc;
+ BOOL m_fObjectMenu;
+ BOOL m_fCurItemPopup;
+ BOOL m_fInMenuMode;
+ BOOL m_fDiscardWmCommand;
+ BOOL m_fGotMenuCloseEvent;
+ BOOL m_fRemovedWndProc;
+ UINT m_cmdId;
+ UINT m_uCurItemID;
+ LPOLEMENU m_lpOleMenu;
+ HMENU m_hmenuCombined;
+ HWND m_hwndFocusOnEnter;
+ int m_cAltTab;
+#ifdef _CHICAGO_
+ BOOL m_fInNCACTIVATE;
+#endif
+};
+
+typedef CFrameFilter FAR* PCFRAMEFILTER;
+
+
+STDAPI_(LRESULT) FrameWndFilterProc (HWND hwnd, UINT msg, UINT uParam,
+ LONG lParam);
+STDAPI_(LRESULT) MessageFilterProc(int nCode, WPARAM wParam,
+ LPARAM lParam);
+
+BOOL IsMDIAccelerator(LPMSG lpMsg, WORD FAR* cmd);
+
+inline PCFRAMEFILTER wGetFrameFilterPtr(HWND hwndFrame);
+
+LPOLEMENU wGetOleMenuPtr(HOLEMENU holemenu);
+inline void wReleaseOleMenuPtr(HOLEMENU holemenu);
+
+#endif // _INPLACE_H
+
diff --git a/private/ole32/ole232/inplace/makefile b/private/ole32/ole232/inplace/makefile
new file mode 100644
index 000000000..1725b5e9a
--- /dev/null
+++ b/private/ole32/ole232/inplace/makefile
@@ -0,0 +1,26 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1992.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/ole232/makefile b/private/ole32/ole232/makefile
new file mode 100644
index 000000000..84abf21b9
--- /dev/null
+++ b/private/ole32/ole232/makefile
@@ -0,0 +1,25 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1992.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all:
+ echo $(BUILDMSG)
+
+clean: all
+
+!else # NTMAKEENV
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/ole232/ole.mk b/private/ole32/ole232/ole.mk
new file mode 100644
index 000000000..19953c3a9
--- /dev/null
+++ b/private/ole32/ole232/ole.mk
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+CINC = $(CINC) -I$(CAIROLE)\h -I$(CAIROLE)\common -I$(CAIROLE)\ih \
+ -I$(CAIROLE)\ole232\inc
diff --git a/private/ole32/ole232/ole1/daytona/makefile b/private/ole32/ole232/ole1/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/ole232/ole1/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/ole232/ole1/daytona/sources b/private/ole32/ole232/ole1/daytona/sources
new file mode 100644
index 000000000..05a99a551
--- /dev/null
+++ b/private/ole32/ole232/ole1/daytona/sources
@@ -0,0 +1,78 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = ole232
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= ole1
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..\..\inc
+INCLUDES= $(INCLUDES);$(BASEDIR)\private\dcomidl\obj
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+
+SOURCES= \
+ ..\ddecnvrt.cpp \
+ ..\ostm2stg.cpp
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
diff --git a/private/ole32/ole232/ole1/ddecnvrt.cpp b/private/ole32/ole232/ole1/ddecnvrt.cpp
new file mode 100644
index 000000000..4fe6090b3
--- /dev/null
+++ b/private/ole32/ole232/ole1/ddecnvrt.cpp
@@ -0,0 +1,351 @@
+
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ ddecnvrt.cpp
+
+Abstract:
+
+ This module contains the code to read/write PBrush, MSDraw native data
+ formats. This module also contains PBrush native format <->DIbFile stream,
+ and MSDraw native format <-> placeable metafile stream conversion routines.
+
+Author:
+
+ Srini Koppolu (srinik) 06/29/1993
+
+Revision History:
+
+--*/
+
+#include <le2int.h>
+#include <ole1cls.h>
+#ifndef _MAC
+
+
+
+
+/************************ FILE FORMATS **********************************
+
+
+Normal Metafile (memory or disk based):
+
+ ------------ ---------------
+ | METAHEADER | Metafile bits |
+ ------------ ---------------
+
+Placeable Metafile:
+
+ --------------------- -----------------
+ | PLACEABLEMETAHEADER | Normal metafile |
+ --------------------- -----------------
+
+Memory Based DIB:
+
+ ------------------ --------------- ----------
+ | BITMAPINFOHEADER | RGBQUAD array | DIB bits |
+ ------------------ --------------- ----------
+
+DIB file format:
+
+ ------------------ ------------------
+ | BITMAPFILEHEADER | Memory based DIB |
+ ------------------ ------------------
+
+Ole10NativeStream Format:
+
+ -------- ----------------------
+ | dwSize | Object's Native data |
+ -------- ----------------------
+
+PBrush Native data format:
+
+ -----------------
+ | Dib File format |
+ -----------------
+
+MSDraw Native data format:
+
+ --------------------- ------------- ------------- -----------------
+ | mapping mode (WORD) | xExt (WORD) | yExt (WORD) | Normal metafile |
+ --------------------- ------------- ------------- -----------------
+
+
+*****************************************************************************/
+
+
+
+
+FARINTERNAL UtGetHMFPICTFromMSDrawNativeStm
+ (LPSTREAM pstm, DWORD dwSize, HANDLE FAR* lphdata)
+{
+ HRESULT error;
+ WORD mfp[3]; // mm, xExt, yExt
+ HMETAFILE hMF = NULL;
+
+ *lphdata = NULL;
+
+ if (error = pstm->Read(mfp, sizeof(mfp), NULL))
+ return error;
+
+ dwSize -= sizeof(mfp);
+
+ if (error = UtGetHMFFromMFStm(pstm, dwSize, FALSE, (void **)&hMF))
+ return error;
+
+ AssertSz(mfp[0] == MM_ANISOTROPIC, "invalid map mode in MsDraw native data");
+
+ if (*lphdata = UtGetHMFPICT(hMF, TRUE, (int) mfp[1], (int) mfp[2]))
+ return NOERROR;
+
+ return ResultFromScode(E_OUTOFMEMORY);
+}
+
+
+FARINTERNAL UtPlaceableMFStmToMSDrawNativeStm
+ (LPSTREAM pstmPMF, LPSTREAM pstmMSDraw)
+{
+ DWORD dwSize; // size of metafile bits excluding the placeable MF header
+ LONG xExt;
+ LONG yExt;
+ WORD wBuf[5]; // dwSize(DWORD), mm(int), xExt(int), yExt(int)
+ HRESULT error;
+
+ if (error = UtGetSizeAndExtentsFromPlaceableMFStm(pstmPMF, &dwSize,
+ &xExt, &yExt))
+ return error;
+
+ *((DWORD FAR*) wBuf) = dwSize + 3*sizeof(WORD);
+ wBuf[2] = MM_ANISOTROPIC;
+ wBuf[3] = (int) xExt;
+ wBuf[4] = (int) yExt;
+
+ if (error = pstmMSDraw->Write(wBuf, sizeof(wBuf), 0))
+ return error;
+
+ ULARGE_INTEGER ularge_int;
+ ULISet32(ularge_int, dwSize);
+ if ((error = pstmPMF->CopyTo(pstmMSDraw, ularge_int,
+ NULL, NULL)) == NOERROR)
+ StSetSize(pstmMSDraw, 0, TRUE);
+
+ return error;
+
+}
+
+
+FARINTERNAL UtDIBFileStmToPBrushNativeStm
+ (LPSTREAM pstmDIBFile, LPSTREAM pstmPBrush)
+{
+ BITMAPFILEHEADER bfh;
+ HRESULT error;
+
+ if (error = pstmDIBFile->Read(&bfh, sizeof(bfh), 0))
+ return error;
+
+ // seek to the begining of the stream
+ LARGE_INTEGER large_int;
+ LISet32( large_int, 0);
+ if (error = pstmDIBFile->Seek(large_int, STREAM_SEEK_SET, 0))
+ return error;
+
+ if (error = pstmPBrush->Write(&(bfh.bfSize), sizeof(DWORD), 0))
+ return error;
+
+ ULARGE_INTEGER ularge_int;
+ ULISet32(ularge_int, bfh.bfSize);
+
+ if ((error = pstmDIBFile->CopyTo(pstmPBrush, ularge_int,
+ NULL, NULL)) == NOERROR)
+ StSetSize(pstmPBrush, 0, TRUE);
+
+ return error;
+}
+
+
+
+FARINTERNAL UtContentsStmTo10NativeStm
+ (LPSTORAGE pstg, REFCLSID rclsid, BOOL fDeleteSrcStm, UINT FAR* puiStatus)
+{
+ CLIPFORMAT cf;
+ LPOLESTR lpszUserType = NULL;
+ HRESULT error;
+ LPSTREAM pstmSrc = NULL;
+ LPSTREAM pstmDst = NULL;
+
+ *puiStatus = NULL;
+
+ if (error = ReadFmtUserTypeStg(pstg, &cf, &lpszUserType))
+ return error;
+
+
+ if (! ((cf == CF_DIB && rclsid == CLSID_PBrush)
+ || (cf == CF_METAFILEPICT && rclsid == CLSID_MSDraw))) {
+ error = ResultFromScode(DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+
+ if (error = pstg->OpenStream(OLE_CONTENTS_STREAM, NULL,
+ (STGM_READ|STGM_SHARE_EXCLUSIVE),
+ 0, &pstmSrc)) {
+ *puiStatus |= CONVERT_NOSOURCE;
+
+ // check whether OLE10_NATIVE_STREAM exists
+ if (pstg->OpenStream(OLE10_NATIVE_STREAM, NULL,
+ (STGM_READ|STGM_SHARE_EXCLUSIVE), 0, &pstmDst))
+ *puiStatus |= CONVERT_NODESTINATION;
+ else {
+ pstmDst->Release();
+ pstmDst = NULL;
+ }
+
+ goto errRtn;
+ }
+
+ if (error = OpenOrCreateStream(pstg, OLE10_NATIVE_STREAM, &pstmDst)) {
+ *puiStatus |= CONVERT_NODESTINATION;
+ goto errRtn;
+ }
+
+ if (cf == CF_METAFILEPICT)
+ error = UtPlaceableMFStmToMSDrawNativeStm(pstmSrc, pstmDst);
+ else
+ error = UtDIBFileStmToPBrushNativeStm(pstmSrc, pstmDst);
+
+errRtn:
+ if (pstmDst)
+ pstmDst->Release();
+
+ if (pstmSrc)
+ pstmSrc->Release();
+
+ if (error == NOERROR) {
+ LPOLESTR lpszProgId = NULL;
+ ProgIDFromCLSID(rclsid, &lpszProgId);
+
+ error = WriteFmtUserTypeStg(pstg,
+ RegisterClipboardFormat(lpszProgId),
+ lpszUserType);
+
+ if (lpszProgId)
+ delete lpszProgId;
+ }
+
+ if (error == NOERROR) {
+ if (fDeleteSrcStm)
+ pstg->DestroyElement(OLE_CONTENTS_STREAM);
+ } else {
+ pstg->DestroyElement(OLE10_NATIVE_STREAM);
+ }
+
+ if (lpszUserType)
+ delete lpszUserType;
+
+ return error;
+}
+
+
+
+FARINTERNAL Ut10NativeStmToContentsStm
+ (LPSTORAGE pstg, REFCLSID rclsid, BOOL fDeleteSrcStm)
+{
+
+ CLIPFORMAT cfOld;
+ CLIPFORMAT cfNew;
+ LPOLESTR lpszUserType = NULL;
+ HRESULT error;
+ LPSTREAM pstmSrc = NULL;
+ LPSTREAM pstmDst = NULL;
+
+
+ if (error = ReadFmtUserTypeStg(pstg, &cfOld, &lpszUserType))
+ return error;
+
+ if (rclsid == CLSID_StaticDib)
+ cfNew = CF_DIB;
+ else if (rclsid == CLSID_StaticMetafile)
+ cfNew = CF_METAFILEPICT;
+ else {
+ AssertSz(FALSE, "Internal Error: this routine shouldn't have been called for this class");
+ return ResultFromScode(E_FAIL);
+ }
+
+ if (cfOld == g_cfPBrush) {
+ if (cfNew != CF_DIB) {
+ error = ResultFromScode(DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+ } else if (cfOld == g_cfMSDraw) {
+ if (cfNew != CF_METAFILEPICT) {
+ error = ResultFromScode(DV_E_CLIPFORMAT);
+ goto errRtn;
+ }
+ } else {
+ // Converted to static object from some class other than PBrush or
+ // MSDraw. The data must be in a proper format in the CONTENTS
+ // stream.
+ return NOERROR;
+ }
+
+ if (error = pstg->OpenStream(OLE10_NATIVE_STREAM, NULL,
+ (STGM_READ|STGM_SHARE_EXCLUSIVE),
+ 0, &pstmSrc))
+ goto errRtn;
+
+ if (error = OpenOrCreateStream(pstg, OLE_CONTENTS_STREAM, &pstmDst))
+ goto errRtn;
+
+ DWORD dwSize;
+ if (error = pstmSrc->Read(&dwSize, sizeof(DWORD), NULL))
+ goto errRtn;
+
+ if (cfOld == g_cfMSDraw) {
+ WORD mfp[3]; // mm, xExt, yExt
+
+ if (error = pstmSrc->Read(mfp, sizeof(mfp), NULL))
+ goto errRtn;
+
+ dwSize -= sizeof(mfp);
+
+ error = UtMFStmToPlaceableMFStm(pstmSrc, dwSize,
+ (LONG) mfp[1], (LONG) mfp[2], pstmDst);
+
+ } else {
+ // The PBrush native data format is DIB File format. So all we got to
+ // do is CopyTo.
+
+ ULARGE_INTEGER ularge_int;
+ ULISet32(ularge_int, dwSize);
+ if ((error = pstmSrc->CopyTo(pstmDst, ularge_int, NULL,
+ NULL)) == NOERROR)
+ StSetSize(pstmDst, 0, TRUE);
+ }
+
+errRtn:
+ if (pstmDst)
+ pstmDst->Release();
+
+ if (pstmSrc)
+ pstmSrc->Release();
+
+ if (error == NOERROR) {
+ error = WriteFmtUserTypeStg(pstg, cfNew, lpszUserType);
+
+ if (fDeleteSrcStm)
+ pstg->DestroyElement(OLE10_NATIVE_STREAM);
+
+ } else {
+ pstg->DestroyElement(OLE_CONTENTS_STREAM);
+ }
+
+ if (lpszUserType)
+ PubMemFree(lpszUserType);
+
+ return error;
+}
+
+#endif
+
diff --git a/private/ole32/ole232/ole1/depend.mk b/private/ole32/ole232/ole1/depend.mk
new file mode 100644
index 000000000..5851368c6
--- /dev/null
+++ b/private/ole32/ole232/ole1/depend.mk
@@ -0,0 +1,34 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\ostm2stg.obj $(OBJDIR)\ostm2stg.lst: .\ostm2stg.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(CAIROLE)\ole232\inc\ostm2stg.h \
+ $(CAIROLE)\ole232\inc\reterr.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ddedebug.h
+
diff --git a/private/ole32/ole232/ole1/dirs b/private/ole32/ole232/ole1/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/ole232/ole1/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/ole232/ole1/filelist.mk b/private/ole32/ole232/ole1/filelist.mk
new file mode 100644
index 000000000..81346a9a7
--- /dev/null
+++ b/private/ole32/ole232/ole1/filelist.mk
@@ -0,0 +1,49 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = ole1.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CPPFILES = \
+ .\ostm2stg.cpp \
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PFILE =
+
+
+!include $(CAIROLE)\ole232\ole.mk
diff --git a/private/ole32/ole232/ole1/makefile b/private/ole32/ole232/ole1/makefile
new file mode 100644
index 000000000..1725b5e9a
--- /dev/null
+++ b/private/ole32/ole232/ole1/makefile
@@ -0,0 +1,26 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1992.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/ole232/ole1/ostm2stg.cpp b/private/ole32/ole232/ole1/ostm2stg.cpp
new file mode 100644
index 000000000..ef20e1e06
--- /dev/null
+++ b/private/ole32/ole232/ole1/ostm2stg.cpp
@@ -0,0 +1,5818 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ostm2stg.cpp
+//
+// Contents: OLE 1 - OLE 2 Stream/IStorage Interoperatbility
+//
+// Functions: Implements API functions:
+// OleConvertOLESTREAMToIStorage
+// OleConvertIStorageToOLESTREAM
+// OleConvertOLESTREAMToIStorageEx
+// OleConvertIStorageToOLESTREAMEx
+//
+//
+// History: dd-mmm-yy Author Comment
+// 03-Feb-92 jasonful original version
+// 08-Aug-93 srinik added Ex functions
+// 12-Feb-94 davepl 32-bit port
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#include "ostm2stg.h"
+#include <ctype.h>
+#include <limits.h>
+#include <string.h>
+#include <ole1cls.h>
+
+ASSERTDATA
+
+// We need a ptr value which will indicate that the associated handle
+// is a metafile handle, and therefore cannot be cleaned up as if
+// it were a normal global memory handle
+
+#define METADATAPTR ((void *) -1)
+
+// This fn is not prototyped in any include file, since it was static
+// to its file. Need to add the prototype to a common include file.
+
+HRESULT STDAPICALLTYPE CreateOle1FileMoniker(LPWSTR,REFCLSID,LPMONIKER FAR*);
+
+// This is defined in the new privstm.cpp; must be added to an include file.
+
+STDAPI ReadFmtProgIdStg ( IStorage * pstg, LPOLESTR * pszProgID );
+FARINTERNAL wWriteFmtUserType (LPSTORAGE, REFCLSID);
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenericObject::CGenericObject
+//
+// Synopsis: Constructor for CGenericObject class
+//
+// Effects: Initializes all child pointers to NULL and sets
+// flags to FALSE
+//
+// History: dd-mmm-yy Author Comment
+// 14-Feb-94 davepl Cleanup and document
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+CGenericObject::CGenericObject(void)
+{
+ m_ppres = NULL; // Presentation data
+ m_fLink = FALSE; // Flag: Linked (T) or Embedded (F)
+ m_fStatic = FALSE; // Flag: Static object
+ m_fNoBlankPres = FALSE; // Flag: do not want a blank presentation
+ m_szTopic = NULL; // Topic string for this object
+ m_szItem = NULL; // Item (file) string for this object
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenericObject::~CGenericObject
+//
+// Synopsis: Desctuctor for CGenericObject class
+//
+// Effects: Removes children then self
+//
+// History: dd-mmm-yy Author Comment
+// 12-Aug-94 alexgo check for NULL before delete
+// 14-Feb-94 davepl Cleanup and document
+//
+// Notes: As much as I hated to do it, some of these strings
+// have to be freed with PubMemFree because they are
+// allocated by UtDupString, which allocates public memory.
+//
+//--------------------------------------------------------------------------
+
+CGenericObject::~CGenericObject (void)
+{
+ if( m_ppres )
+ {
+ delete m_ppres; // Presentation data
+ }
+
+ if( m_szTopic )
+ {
+ PubMemFree(m_szTopic); // Topic string
+ }
+
+ if( m_szItem )
+ {
+ PubMemFree(m_szItem); // Item string
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CData::CData
+//
+// Synopsis: Constructor for a simple class which holds a piece of
+// memory.
+//
+// Effects: Clears size, flags, and pointer
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes: 14-Feb-94 davepl Cleanup and document
+//
+//--------------------------------------------------------------------------
+
+CData::CData (void)
+{
+ m_cbSize = 0; // Count, in bytes, of data size
+ m_h = NULL; // Memory handke
+ m_pv= NULL; // Memory pointer
+ m_fNoFree = FALSE; // Flag: Should memory be freed in destructor
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CData::~CData
+//
+// Synopsis: Destructor for simple data class
+//
+// Effects: Unlocks and frees memory if m_fNoFree is not set
+//
+// History: dd-mmm-yy Author Comment
+// 14-Feb-94 davepl Cleanup and document
+//
+// Notes: If a metafile handle is stored in the handle, the
+// pointer will be marked with a special value, indicating
+// that we must DeleteMetafile, not GlobalFree the handle.
+//
+//--------------------------------------------------------------------------
+
+CData::~CData (void)
+{
+ if (m_h) // Do we have a handle?
+ {
+ if (m_pv == METADATAPTR)
+ {
+ LEVERIFY(DeleteMetaFile((HMETAFILE) m_h));
+ }
+ else
+ {
+ GlobalUnlock (m_h); // Dec lock count
+ if (!m_fNoFree) // Free this memory if we
+ { // have been flagged to do so
+ LEVERIFY(0==GlobalFree (m_h));
+ }
+ }
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFormat::CFormat
+//
+// Synopsis: CFormat class constructor
+//
+// Effects: Initializes format tag and clipboard format
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes: 14-Feb-94 davepl Cleanup and document
+//
+//--------------------------------------------------------------------------
+
+CFormat::CFormat (void)
+{
+ m_ftag = ftagNone; // Format tag (string, clipformat, or none)
+ m_cf = 0; // Clipboard format
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClass::CClass
+//
+// Synopsis: CClass constructor
+//
+// Effects: sets class ID and class ID string to NULL
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CClass::CClass (void)
+{
+ m_szClsid = NULL;
+ m_clsid = CLSID_NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPres::CPres
+//
+// Synopsis: CPres constructor
+//
+// Effects: Initializes height & width of presentation data to zero.
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+CPres::CPres (void)
+{
+ m_ulHeight = 0L;
+ m_ulWidth = 0L;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClass::Set, INTERNAL
+//
+// Synopsis: Sets the m_szClsid based on clsid
+//
+// Effects: Sets m_szClsid in the following order of preference:
+// - ProgID obtained from ProgIDFromCLSID()
+// - If it is a static type, m_szClsid is left blank
+// - Tries to read it from [pstg]
+// - Tries to obtain it from registry based on CLSID
+//
+//
+// Arguments: [clsid] - class id object is to be set to
+// [pstg] - storage which may contain info on the
+// clipboard format as a last resort
+//
+// Returns: NOERROR on success
+// REGDB_E_CLASSNOTREG unknown class
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 davepl Cleaned up and documented
+//
+// Notes: Hard-coded maximum of 256 character clip format name.
+// On failure, m_clsid has still been set to clsid.
+//
+//--------------------------------------------------------------------------
+
+INTERNAL CClass::Set (REFCLSID clsid, LPSTORAGE pstg)
+{
+ CLIPFORMAT cf;
+ unsigned short const ccBufSize = 256;
+ LPOLESTR szProgId = NULL;
+
+ Assert (m_clsid == CLSID_NULL && m_szClsid == NULL);
+
+ // set the m_clsid member in the object
+ m_clsid = clsid;
+
+ // If we can get it using ProgIDFromCLSID, that's the simplest case
+ if (NOERROR == wProgIDFromCLSID (clsid, &m_szClsid))
+ {
+ return NOERROR;
+ }
+
+ // If not, maybe the object is static, in which case we leave the
+ // class string NULL
+
+ if (IsEqualCLSID(CLSID_StaticMetafile, clsid) ||
+ IsEqualCLSID(CLSID_StaticDib, clsid))
+ {
+ return NOERROR;
+ }
+
+ // If still no luck, try to read the clipboard format from the storage
+ // and then look that up.
+
+ if (pstg &&
+ SUCCEEDED(ReadFmtUserTypeStg(pstg, &cf, NULL)) &&
+ SUCCEEDED(ReadFmtProgIdStg (pstg, &szProgId)))
+ {
+ // Last-ditch effort. If the class is an unregistered OLE1 class,
+ // the ProgID should still be obtainable from the format tag.
+ // If the class is an unregistered OLE2 class, the ProgId should be
+ // at the end of the CompObj stream.
+
+ if (CoIsOle1Class(clsid))
+ {
+ Verify (GetClipboardFormatName (cf, szProgId, ccBufSize));
+ }
+ else
+ {
+ // If its an OLE 2 object and we couldn't get the program ID from
+ // the storage, we're out of luck
+
+ if (szProgId == NULL || szProgId[0] == L'\0')
+ {
+ if (szProgId)
+ {
+ PubMemFree(szProgId);
+ }
+ return ResultFromScode (REGDB_E_CLASSNOTREG);
+ }
+ }
+
+ // At this point we know we have a program ID and that this is an
+ // OLE 2 object, so we use the program ID as the class name.
+
+ m_szClsid = szProgId;
+ return NOERROR;
+ }
+ else
+ {
+ // If we hit this path, we couldn't read from the storage
+
+ return ResultFromScode (REGDB_E_CLASSNOTREG);
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClass:SetSz, INTERNAL
+//
+// Synopsis: Sets CGenericObject's CLASS member ID based on the class
+// name passed in.
+//
+// History: dd-mmm-yy Author Comment
+// 15-Feb-94 davepl Cleaned up and documented
+//
+//--------------------------------------------------------------------------
+
+
+INTERNAL CClass::SetSz (LPOLESTR sz)
+{
+ HRESULT hr;
+
+ // The class info should be completely unset at this point
+ Assert (m_clsid==CLSID_NULL && m_szClsid==NULL);
+
+ m_szClsid = sz;
+
+ if (FAILED(hr = wCLSIDFromProgID (sz, &m_clsid, TRUE)))
+ {
+ return hr;
+ }
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClass::Reset
+//
+// Synopsis: Frees the Class ID string for CClass and resets the pointer,
+// then sets the class ID and string bassed on the CLSID
+// passed in.
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 davepl Cleaned up and documented
+//
+// Notes: Class ID must already be set before calling RESET
+//
+//--------------------------------------------------------------------------
+
+INTERNAL CClass::Reset (REFCLSID clsid)
+{
+ m_clsid = clsid;
+
+ // We should already have a class ID string if we are _re_setting it
+ Assert(m_szClsid);
+
+ PubMemFree(m_szClsid);
+
+ HRESULT hr;
+ m_szClsid = NULL;
+
+ if (FAILED(hr = wProgIDFromCLSID (clsid, &m_szClsid)))
+ {
+ return hr;
+ }
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CClass::~CClass
+//
+// Synopsis: CClass destructor
+//
+// History: dd-mmm-yy Author Comment
+// 12-Aug-94 alexgo check for NULL before free'ing memory
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CClass::~CClass (void)
+{
+ // The string is created by UtDupString, so its public memory
+
+ if( m_szClsid )
+ {
+ PubMemFree(m_szClsid);
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wConvertOLESTREAMToIStorage, INTERNAL
+//
+// Synopsis: Worker function. Ensures the OLESTREAM is correctly
+// set up then calls OLESTREAMToGenericObject.
+//
+// History: dd-mmm-yy Author Comment
+// 15-Feb-94 davepl Cleaned up and documented
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+INTERNAL wConvertOLESTREAMToIStorage(
+ LPOLESTREAM polestream,
+ LPSTORAGE pstg,
+ PGENOBJ pgenobj)
+{
+ VDATEIFACE (pstg);
+
+#if DBG==1
+ if (IsBadReadPtr (polestream, sizeof(OLESTREAM)) ||
+ IsBadReadPtr (polestream->lpstbl, sizeof(OLESTREAMVTBL)) ||
+ IsBadCodePtr ((FARPROC)polestream->lpstbl->Get))
+ {
+ AssertSz (0, "Bad OLESTREAM");
+ return ResultFromScode (E_INVALIDARG);
+ }
+#endif
+
+ return OLESTREAMToGenericObject (polestream, pgenobj);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleConvertOLESTREAMToIStorage, STDAPI
+//
+// Synopsis: Given an OLE 1 stream and an OLE 2 storage, reads an object
+// from the OLE 1 stream into a CGenericObject. Once read in,
+// the object is written from generic format back into the OLE 2
+// storage object.
+//
+// Arguments: [polestream] -- OLE 1 stream to read object from
+// [pstg] -- OLE 2 storage to write object to
+// [ptd] -- Target device
+//
+// Requires: Streams should be set up, and OLE 1 stream should be
+// positioned at the beginning of the next OLE 1 object
+// to be read.
+//
+// Returns: [DV_E_DVTARGETDEVICE] Invalid write ptr to target device
+// CONVERT10_E_OLESTREAM_FMT On unknown OLE 1 format
+// CONVERT10_E_OLESTREAM_GET On stream read failue
+// E_OUTOFMEMORY On stream I/O memory failure
+//
+// History: dd-mmm-yy Author Comment
+// 14-Feb-94 davepl Cleanup and documentation
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI OleConvertOLESTREAMToIStorage(
+ LPOLESTREAM polestream,
+ LPSTORAGE pstg,
+ const DVTARGETDEVICE FAR* ptd)
+{
+
+ OLETRACEIN((API_OleConvertOLESTREAMToIStorage,
+ PARAMFMT("polestream= %p, pstg= %p, ptd= %td"),
+ polestream, pstg, ptd));
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleConvertOLESTREAMToIStorage ("
+ " %p , %p , %p)\n", 0 /*function*/,
+ polestream, pstg, ptd
+ ));
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pstg);
+
+ HRESULT hresult;
+
+ // This is the generic object we will use as intermediate storage to
+ // hold the contents of the OLESTREAM
+
+ CGenericObject genobj;
+
+ if (ptd)
+ {
+ // The side of the td is the first DWORD. Ensure that much is
+ // valid and then we can use it to check the whole structure.
+ if (IsBadReadPtr (ptd, sizeof(DWORD)))
+ {
+ hresult = ResultFromScode (DV_E_DVTARGETDEVICE);
+ goto errRtn;
+ }
+ if (IsBadReadPtr (ptd, (UINT) ptd->tdSize))
+ {
+ hresult = ResultFromScode (DV_E_DVTARGETDEVICE_SIZE);
+ goto errRtn;
+ }
+ }
+
+ if (FAILED(hresult=wConvertOLESTREAMToIStorage(polestream,pstg,&genobj)))
+ {
+ goto errRtn;
+ }
+
+ // If we were able to read the object out of the stream, we can now try
+ // to write it back out to the storage
+
+ hresult = GenericObjectToIStorage (genobj, pstg, ptd);
+
+errRtn:
+ LEDebugOut((DEB_TRACE, "%p OUT OleConvertOLESTREAMToIStorage ( %lx ) "
+ "\n", 0 /*function*/, hresult));
+
+ OLETRACEOUT((API_OleConvertOLESTREAMToIStorage, hresult));
+ return hresult;
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: PrependUNCName
+//
+// Synopsis: Convert *pszFile to use szUNC=="\\server\share" instead
+// of drive letter
+//
+// Effects: Deletes the UNC name and returns *ppszFile as a NEW string
+// with the full UNC filename. The string originally held at
+// *ppszFile is deleted by this function.
+//
+// Arguments: [ppszFile] Pointer to incoming filename string pointer
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 davepl Cleanup, documentation, allocation fixes
+//
+// Notes: This function does some frightening things by changing the
+// caller's pointer and deleting various reference parameters.
+// Be sure you know what's going on before turning this function
+// loose on one of your own pointers.
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL PrependUNCName (LPOLESTR FAR* ppszFile, LPOLESTR szUNC)
+{
+ HRESULT hresult = NOERROR;
+ LPOLESTR szNew;
+
+ // No place to put result, so nothing to do...
+ if (NULL==szUNC)
+ {
+ return hresult;
+ }
+
+ // Ensure the caller's pointer is valid
+ if (NULL == *ppszFile)
+ {
+ return ResultFromScode(CONVERT10_E_OLESTREAM_FMT);
+ }
+
+ // Ensure the second letter of path is a colon (ie; X:\file)
+ if((*ppszFile)[1] != L':')
+ {
+ return ResultFromScode(CONVERT10_E_OLESTREAM_FMT);
+ }
+
+ // Allocate enough space for new filename (we will be
+ // omitting the X: portion of the filename, so this calculation
+ // is _not_ short by 2 as it may appear)
+
+ szNew = (LPOLESTR)
+ PubMemAlloc((_xstrlen(*ppszFile)+_xstrlen (szUNC)) * sizeof(OLECHAR));
+
+ if (NULL == szNew)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // Copy over the UNC name
+ _xstrcpy (szNew, szUNC);
+
+ // Add the original name, except for the X:
+ _xstrcat (szNew, (*ppszFile) + 2);
+
+ // Free the original name
+ PubMemFree(*ppszFile);
+ *ppszFile = szNew;
+
+ // Delete the UNC name
+ PubMemFree(szUNC);
+ return hresult;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OLESTREAMToGenericObject, INTERNAL
+//
+// Synopsis: Reads and OLE 1.0 version of an object from an OLE 1 stream
+// and stores it internally, including presentation and native
+// data, in a GenericObject.
+//
+// Effects: Creates a GenericObject that can be written back in OLE 1
+// or OLE 2 format
+//
+// Arguments: [pos] -- pointer to OLE 1 stream to read object from
+// [pgenobj] -- pointer to generic object to read into
+//
+// Requires: Input stream setup and GenObj created
+//
+// Returns: NOERROR On success
+// CONVERT10_E_OLESTREAM_FMT On unknown OLE 1 format
+// CONVERT10_E_OLESTREAM_GET On stream read failue
+// E_OUTOFMEMORY On stream I/O memory failure
+//
+// Signals: (none)
+//
+// Modifies: Stream position, GenObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 14-Feb-94 davepl Added Trace code
+// davepl Cleaned up and documented
+// davepl Rerouted errors through central return
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(OLESTREAMToGenericObject)
+static INTERNAL OLESTREAMToGenericObject
+(
+ LPOLESTREAM pos,
+ PGENOBJ pgenobj
+)
+{
+ HRESULT error = NOERROR;
+ ULONG ulFmtId;
+ LPOLESTR szClass = NULL;
+
+ // Read OLE Version # from the stream and discard it
+ if (FAILED(error = OLE1StreamToUL(pos, NULL)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to read OLE ver# from stream at line %d in %s\n",
+ __LINE__, __FILE__));
+ goto errRtn;
+ }
+
+ // Get Format ID from the stream
+ if (FAILED(error = OLE1StreamToUL(pos, &ulFmtId)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to read format ID from stream at line %d in %s\n",
+ __LINE__, __FILE__));
+ goto errRtn;
+ }
+
+ // If this is a static object, read it into the generic object and return
+ if (ulFmtId == FMTID_STATIC)
+ {
+ if (FAILED(error = GetStaticObject (pos, pgenobj)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to read static object at line %d in %s\n",
+ __LINE__, __FILE__));
+ }
+ goto errRtn;
+ }
+
+ // If this is neither a linked nor an embedded object, something
+ // is wrong
+ if (ulFmtId != FMTID_LINK && ulFmtId != FMTID_EMBED)
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Object is neither linked nor embedded at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ error = ResultFromScode(CONVERT10_E_OLESTREAM_FMT);
+ goto errRtn;
+ }
+
+ // If this is a linked object, set our flag in GenericObject
+ if (FMTID_LINK == ulFmtId)
+ {
+ pgenobj->m_fLink = TRUE;
+ }
+
+ // Read the class name from the stream
+
+ if (FAILED(error = OLE1StmToString(pos, &szClass)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to read the class name from stream at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ goto errRtn;
+ }
+ if (NULL == szClass)
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Class name was returned NULL at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ error = CONVERT10_E_OLESTREAM_FMT;
+ goto errRtn;
+ }
+
+ // If this is an embedded object, set the class ID and class string
+ // If it is a linked object, set the class name but set the class ID
+ // to CLSID_StdOleLink
+
+ if (FMTID_EMBED == ulFmtId)
+ {
+ pgenobj->m_class.SetSz (szClass);
+ }
+ else
+ {
+ Assert (ulFmtId == FMTID_LINK);
+ pgenobj->m_classLast.SetSz (szClass);
+ pgenobj->m_class.Set (CLSID_StdOleLink, NULL);
+ }
+
+ // Read the Topic string from the stream
+ if (FAILED(error = OLE1StmToString(pos, &(pgenobj->m_szTopic))))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to read topic string from stream at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ goto errRtn;
+ }
+
+ // Read the Item string from the stream
+ if (FAILED(error = OLE1StmToString(pos, &(pgenobj->m_szItem))))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to get item string from stream at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ goto errRtn;
+ }
+
+ // If this is a linked object, set up the filename etc.
+ if (FMTID_LINK == ulFmtId)
+ {
+ LPOLESTR szUNCName = NULL;
+
+ // Read the network name from the stream
+
+ if (FAILED(error = OLE1StmToString(pos, &szUNCName)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to get network name from stream at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ goto errRtn;
+ }
+
+ // Convert a drive-letter based name to \\srv\share name
+ if (FAILED(error = PrependUNCName (&(pgenobj->m_szTopic), szUNCName)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to convert drv ltr to UNC name at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ goto errRtn;
+ }
+
+ // Read network type and network driver version # from stream
+ // (They are both shorts and we discarding them, so read a LONG)
+ if (FAILED(error = OLE1StreamToUL (pos, NULL)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to get net type/ver from stream at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ goto errRtn;
+ }
+
+ // Read the link-updating options from the stream. This field
+ // use OLE 1.0 enumeration values for the link update options
+ if (FAILED(error = OLE1StreamToUL(pos, &(pgenobj->m_lnkupdopt))))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to read link update opts at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ goto errRtn;
+ }
+
+ // OLE 1.0 duplicates the link update options in the highword
+ // of the LONG, and we don't want that, so clear the highword.
+
+ pgenobj->m_lnkupdopt &= 0x0000FFFF;
+ }
+ else // This path is taken to read in embedded objects
+ {
+ Assert (ulFmtId == FMTID_EMBED);
+
+ // Read and store the native data from the stream
+ if (FAILED(error = GetSizedDataOLE1Stm (pos, &(pgenobj->m_dataNative))))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to get native data from stream at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ goto errRtn;
+ }
+ }
+
+ // For both linked and embedded objects, we need to read in any
+ // presentation data that may be present. Note that certain formats
+ // such as MS-Paint will not provide presentation data; this is OK
+ // since they can be rendered by native data alone (space saving measure)
+
+ if (FAILED(error = GetPresentationObject (pos, pgenobj)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to get presentation data from stream at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ goto errRtn;
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT OLESTREAMToGenericObject ( %lx ) \n",
+ NULL /*function*/, error));
+
+ return error;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetStaticObject, INTERNAL
+//
+// Synopsis: Reads the presentation data for a static object into the
+// PPRES member of GenericObject, and sets format and class
+// flags accordingly
+//
+// Effects:
+//
+// Arguments: [pos] -- stream we are reading OLE 1 object from
+// [pgenobj] -- GenericObject we are reading into
+// Requires:
+//
+// Returns: NOERROR On success
+// CONVERT10_E_OLESTREAM_FMT On unknown OLE 1 format
+// CONVERT10_E_OLESTREAM_GET On stream read failue
+// E_OUTOFMEMORY On stream I/O memory failure
+//
+// Signals: (none)
+//
+// Modifies: Stream position, GenericObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 14-Feb-94 davepl Cleanup and documentation
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL GetStaticObject (LPOLESTREAM pos, PGENOBJ pgenobj)
+{
+ HRESULT error;
+
+ // Read the presentation data, standard or generic, into the
+ // PPRES member of the GenericObject
+ if (FAILED(error = GetPresentationObject(pos, pgenobj, TRUE)))
+ {
+ return ResultFromScode(error);
+ }
+
+ // Ensure that the format tag is a clipboard format
+ if (ftagClipFormat != pgenobj->m_ppres->m_format.m_ftag)
+ {
+ return ResultFromScode(CONVERT10_E_OLESTREAM_FMT);
+ }
+
+ // If the clipboard format is a METAFILEPIC, set the CLASS
+ // member of GenericObject to CLSID_StaticMetafile
+ if (CF_METAFILEPICT == pgenobj->m_ppres->m_format.m_cf)
+ {
+ pgenobj->m_class.Set (CLSID_StaticMetafile, NULL);
+ }
+
+ // Otherwise, check to see if it is a DIB, and set the CLASS
+ // member accordingly
+
+ else if (CF_DIB == pgenobj->m_ppres->m_format.m_cf)
+ {
+ pgenobj->m_class.Set (CLSID_StaticDib, NULL);
+ }
+
+ // If it is neither a METAFILEPIC nor a DIB, we have a problem
+
+ else
+ {
+ AssertSz (0, "1.0 static object not in one of 3 standard formats");
+ return ResultFromScode (CONVERT10_E_OLESTREAM_FMT);
+ }
+
+ // Flag the GenericObject as Static
+ pgenobj->m_fStatic = TRUE;
+ return NOERROR;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateBlankPres, INTERNAL
+//
+// Synopsis: Sets up the format in the PPRES struct as ClipFormat 0
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 davepl Cleaned up
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL CreateBlankPres(PPRES ppres)
+{
+ Assert (ppres);
+ ppres->m_format.m_ftag = ftagClipFormat;
+ ppres->m_format.m_cf = 0;
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetPresentationObject, INTERNAL
+//
+// Synopsis: Reads the presentation data into the CGenericObject object
+//
+// Arguments: [pos] -- OLE 1 stream we are reading from
+// [pgenobj] -- Generic object we are reading to
+// [fStatic] -- Flag: getting a static pres object?
+//
+// Requires: stream open, object allocated
+//
+// Returns: CONVERT10_E_OLESTREAM_FMT unknown format id in stream
+//
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 davepl Cleaned up and documented
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL GetPresentationObject(
+ LPOLESTREAM pos,
+ PGENOBJ pgenobj,
+ BOOL fStatic)
+{
+ LPOLESTR szClass = NULL;
+ HRESULT hresult = NOERROR;
+
+ Assert (pgenobj->m_ppres==NULL);
+
+ if (TRUE != fStatic) //FALSE!
+ {
+ // Pull the OLE version number out of the stream, we don't want it
+
+ if (FAILED(hresult = OLE1StreamToUL(pos, NULL)))
+ {
+ return hresult;
+ }
+
+ // Pull the OLE 1 format identifier out of the stream
+
+ ULONG ulFmtId;
+ if (FAILED(hresult = OLE1StreamToUL (pos, &ulFmtId)))
+ {
+ return hresult;
+ }
+
+ // If the format identifier is not FMTID_PRES, we've got a
+ // problem... unless it's 0 in which case it simply means
+ // that there _is no_ presentation data, ie: PBrush, Excel
+
+ if (ulFmtId != FMTID_PRES)
+ {
+ if (0==ulFmtId)
+ {
+ return NOERROR;
+ }
+ else
+ {
+ return ResultFromScode(CONVERT10_E_OLESTREAM_FMT);
+ }
+ }
+ }
+
+ // Pull in the type name for the OLE1 data
+
+ if (FAILED(hresult = OLE1StmToString (pos, &szClass)))
+ {
+ return hresult;
+ }
+
+ if (0==_xstrcmp (szClass, OLESTR("METAFILEPICT")))
+ {
+ hresult = GetStandardPresentation (pos, pgenobj, CF_METAFILEPICT);
+ }
+ else if (0==_xstrcmp (szClass, OLESTR("BITMAP")))
+ {
+ hresult = GetStandardPresentation (pos, pgenobj, CF_BITMAP);
+ }
+ else if (0==_xstrcmp (szClass, OLESTR("DIB")))
+ {
+ hresult = GetStandardPresentation (pos, pgenobj, CF_DIB);
+ }
+ else if (0==_xstrcmp (szClass, OLESTR("ENHMETAFILE")))
+ {
+ Assert (0 && "Encountered an unsupported format: ENHMETAFILE");
+ }
+ else
+ {
+ // This is a Generic Presentation stream
+
+#if DBG==1
+ Assert (!fStatic);
+ if (_xstrcmp (pgenobj->m_fLink
+ ? pgenobj->m_classLast.m_szClsid
+ : pgenobj->m_class.m_szClsid, szClass))
+ {
+ Assert (0 && "Class name in embedded object stream does\n"
+ "not match class name in pres object stream");
+ }
+#endif
+ hresult = GetGenericPresentation (pos, pgenobj);
+ }
+
+ if (szClass)
+ {
+ PubMemFree(szClass);
+ }
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetBitmapAsDib, INTERNAL
+//
+// Synopsis: Reads a bitmap from the OLE1 stream, converts it to a DIB,
+// and stores it in the DATA member of CGenericObject
+//
+// Arguments: [pos] -- The OLE 1 stream to read from
+// [pdata] -- The DATA object to read into
+//
+// Requires:
+//
+// Returns: NOERROR success
+// CONVERT10_E_OLESTREAM_GET I/O error
+// CONVERT10_E_OLESTREAM_BITMAP_TO_DIB conversion error
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 davepl Cleaned up and documented
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL GetBitmapAsDib(LPOLESTREAM pos, PDATA pdata)
+{
+ HRESULT hresult= NOERROR;
+ HGLOBAL hBits = NULL;
+ HGLOBAL hDib = NULL;
+ LPVOID pBits = NULL;
+ WIN16BITMAP bm;
+ HBITMAP hBitmap;
+ ULONG cbBits;
+ ULONG ul;
+
+
+ Assert (pdata->m_h==NULL && pdata->m_pv==NULL && pdata->m_cbSize==0);
+
+ // Get size of all bitmap data, including the bitmap header struct
+
+ if (FAILED(hresult = OLE1StreamToUL(pos, &ul)))
+ {
+ return hresult;
+ }
+
+ // Read the bitmap header structure. Since this was stored as Win16
+ // BITMAP, we have to pull a structure of that size from the stream
+ // (A Win32 BITMAP uses LONGs and hence is larger).
+
+ if (pos->lpstbl->Get (pos, &bm, sizeof(WIN16BITMAP)) < sizeof(WIN16BITMAP))
+ {
+ return ResultFromScode (CONVERT10_E_OLESTREAM_GET);
+ }
+
+ // The bitmap data is total size - header size
+ // Allocate enough memory to hold the bitmap data
+
+ cbBits = ul - sizeof(WIN16BITMAP);
+ hBits = GlobalAlloc (GMEM_MOVEABLE, cbBits);
+ if (NULL == hBits)
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ pBits = (void FAR*) GlobalLock (hBits);
+ if (pBits == NULL)
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ // Read the header data into our allocated buffer
+ if (pos->lpstbl->Get (pos, pBits, cbBits) < cbBits)
+ {
+ hresult = ResultFromScode (CONVERT10_E_OLESTREAM_GET);
+ goto errRtn;
+ }
+
+ // Turn that raw data into a bitmap
+ hBitmap = CreateBitmap (bm.bmWidth, bm.bmHeight, bm.bmPlanes,
+ bm.bmBitsPixel, pBits);
+
+ if (NULL == hBitmap)
+ {
+ hresult = ResultFromScode(CONVERT10_E_OLESTREAM_BITMAP_TO_DIB);
+ goto errRtn;
+ }
+
+ // NOTE: The following call gave only the first parameter in the
+ // (davepl) original source; The second is the palette handle, which
+ // I've passed as NULL to indicate the default stock palette.
+
+ hDib = UtConvertBitmapToDib (hBitmap, NULL);
+ if (NULL == hDib)
+ {
+ hresult = ResultFromScode(CONVERT10_E_OLESTREAM_BITMAP_TO_DIB);
+ goto errRtn;
+ }
+
+ // Set the presentation data pointers to point to this new DIB
+
+ pdata->m_pv = GlobalLock (hDib);
+ if (NULL == pdata->m_pv)
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ pdata->m_cbSize = GlobalSize (hDib);
+ pdata->m_h = hDib;
+
+ // Free up allocations and resources, return result
+
+errRtn:
+
+ if (pBits)
+ {
+ Verify (0==GlobalUnlock (hBits));
+ }
+ if (hBits)
+ {
+ Verify (0==GlobalFree (hBits));
+ }
+ if (hBitmap)
+ {
+ Verify (DeleteObject (hBitmap));
+ }
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetMfBits, INTERNAL
+//
+// Synopsis: Strips the METAFILE header from the stream and then reads
+// the metafile bits into an allocated memory area; the
+// presentation data member of [pos] is then set to point
+// to this memory.
+//
+// Arguments: [pos] -- the OLE 1 stream to read from
+// [pdata] -- the presentation data member of generic object
+//
+// Returns: NOERROR success
+// CONVERT10_E_OLESTREAM_GET stream error
+// E_OUTOFMEMORY allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 davepl Cleaned up and documented
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL GetMfBits(LPOLESTREAM pos, PDATA pdata)
+{
+ ULONG cbSize;
+ WIN16METAFILEPICT mfpictDummy;
+ HRESULT hresult = NOERROR;
+
+ Assert (0==pdata->m_cbSize && pdata->m_h==NULL && NULL==pdata->m_pv);
+
+ // Read the data size from the stream
+
+ if (FAILED(hresult = (OLE1StreamToUL (pos, &cbSize))))
+ {
+ return hresult;
+ }
+
+ // Now read the actual data
+
+ if (cbSize <= sizeof(WIN16METAFILEPICT))
+ {
+ return ResultFromScode(CONVERT10_E_OLESTREAM_FMT);
+ }
+
+ // An OLESTREAM contains a METAFILEPICT structure (with a meaningless
+ // handle) followed by the metafile bits. So consume the METAFILEPICT.
+
+ if (pos->lpstbl->Get (pos, &mfpictDummy, sizeof(WIN16METAFILEPICT))
+ < sizeof(WIN16METAFILEPICT))
+ {
+ return ResultFromScode(CONVERT10_E_OLESTREAM_GET);
+ }
+
+ // Deduct from our count of bytes to read the size of the header which
+ // we just consumed. Set the presentation data size to be this new size.
+
+ cbSize -= sizeof(WIN16METAFILEPICT);
+ pdata->m_cbSize = cbSize;
+
+ // Grad some memory to store the metafile bits
+
+ pdata->m_h = GlobalAlloc (GMEM_MOVEABLE, cbSize);
+ if (NULL==pdata->m_h)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ pdata->m_pv = GlobalLock (pdata->m_h);
+ if (NULL==pdata->m_pv)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+ // Get the actual metafile bits
+
+ if (pos->lpstbl->Get (pos, pdata->m_pv, cbSize) < cbSize)
+ {
+ return ResultFromScode(CONVERT10_E_OLESTREAM_GET);
+ }
+
+ return hresult;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetStandardPresentation, INTERNAL
+//
+// Synopsis: Allocates a PRES member for generic object, then reads
+// whatever presentation may be found in the stream into
+// that PRES.
+//
+// Arguments: [pos] -- the OLE 1 stream to read from
+// [pgenobj] -- the generic object we are going to set
+// up with the presentation data
+// [cf] -- the clipboad format we are to read
+//
+// Returns: NOERROR success
+// E_OUTOFMEMORY allocation failure
+//
+// Modifies: [pgenobj] - sets up the m_ppres member
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 davepl Cleaned up and documented
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL GetStandardPresentation(
+ LPOLESTREAM pos,
+ PGENOBJ pgenobj,
+ CLIPFORMAT cf)
+{
+ HRESULT hresult = NOERROR;
+
+ // Allocate enough memory for the PRES object
+ pgenobj->m_ppres = new PRES;
+ if (NULL == pgenobj->m_ppres)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // Set up the format tag and clipboard format
+ pgenobj->m_ppres->m_format.m_ftag = ftagClipFormat;
+ pgenobj->m_ppres->m_format.m_cf = cf;
+
+ // Get the width of the data from the stream
+ if (FAILED(hresult = OLE1StreamToUL(pos, &(pgenobj->m_ppres->m_ulWidth))))
+ {
+ return hresult;
+ }
+ // Get the height of the data from the stream
+ if (FAILED(hresult=OLE1StreamToUL(pos, &(pgenobj->m_ppres->m_ulHeight))))
+ {
+ return hresult;
+ }
+
+ // The height saved by OLE 1.0 objects into the stream is always a
+ // negative value (Y-increase in pixel is negative upward?) so we
+ // have to correct that value.
+
+ pgenobj->m_ppres->m_ulHeight
+ = (ULONG) -((LONG) pgenobj->m_ppres->m_ulHeight);
+
+ // Read the appropriate presentation data based on the clipboard
+ // format ID
+
+ switch(cf)
+ {
+ case CF_METAFILEPICT:
+ {
+ hresult = GetMfBits (pos, &(pgenobj->m_ppres->m_data));
+ break;
+ }
+
+ case CF_BITMAP:
+ {
+ // When reading a bitmap, we will convert from Bitmap to
+ // DIB in the process, so update the PRES clipboard format ID
+
+ pgenobj->m_ppres->m_format.m_cf = CF_DIB;
+ hresult = GetBitmapAsDib (pos, &(pgenobj->m_ppres->m_data));
+ break;
+ }
+
+ case CF_DIB:
+ {
+ Assert (CF_DIB==cf);
+ hresult = GetSizedDataOLE1Stm (pos, &(pgenobj->m_ppres->m_data));
+ break;
+ }
+
+ default:
+ {
+ Assert(0 && "Unexpected clipboard format reading PRES");
+ }
+ }
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetGenericPresentation, INTERNAL
+//
+// Synopsis: Allocated the PRES member of the generic object and reads
+// the generic presentation data into it.
+//
+// Effects: If the format is a known clipboard format, we set the
+// format tag to indicate this, and set the format type
+// to indicate the clipboard format type. If it is unknown,
+// we set the format tag to string and read the description
+// of the format.
+//
+// Arguments: [pos] -- the OLE 1 stream we are reading from
+// [pgenobj] -- the generic object we are reading to
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 davepl Code cleanup and document
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL GetGenericPresentation(
+ LPOLESTREAM pos,
+ PGENOBJ pgenobj)
+{
+ ULONG ulClipFormat;
+ HRESULT hresult = NOERROR;
+
+ // The PRES member should not exist at this point
+ Assert (NULL==pgenobj->m_ppres);
+
+ // Allocate the PRES member of the generic object
+
+ pgenobj->m_ppres = new PRES;
+ if (NULL == pgenobj->m_ppres)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // Read the clipboard format ID
+
+ if (FAILED(hresult = OLE1StreamToUL (pos, &ulClipFormat)))
+ {
+ delete (pgenobj->m_ppres);
+ return hresult;
+ }
+
+ // If the clipboard format is not 0, we have a known clipboard
+ // format and we should set the tag type and ID accordingly
+
+ if (ulClipFormat)
+ {
+ pgenobj->m_ppres->m_format.m_ftag = ftagClipFormat;
+ pgenobj->m_ppres->m_format.m_cf = (CLIPFORMAT) ulClipFormat;
+ }
+ else
+ {
+ // Otherwise, we have a custom format so we need to set the
+ // tag type to string and read in the data format string
+
+ pgenobj->m_ppres->m_format.m_ftag = ftagString;
+ if (FAILED(hresult = (GetSizedDataOLE1Stm
+ (pos, &(pgenobj->m_ppres->m_format.m_dataFormatString)))))
+ {
+ delete (pgenobj->m_ppres);
+ return hresult;
+ }
+ }
+
+ // We don't know the size, so reset to 0
+
+ pgenobj->m_ppres->m_ulHeight = 0;
+ pgenobj->m_ppres->m_ulWidth = 0;
+
+ // Read the raw generic presentation data into the PRES member
+
+ if (FAILED(hresult=GetSizedDataOLE1Stm(pos,&(pgenobj->m_ppres->m_data))))
+ {
+ delete (pgenobj->m_ppres);
+ return hresult;
+ }
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetSizedDataOLE1Stm, INTERNAL
+//
+// Synopsis: Reads bytes from an OLE 1 stream into a CData object.
+// Obtains the number of bytes to read from the first
+// ULONG in the stream
+//
+// Arguments: [pos] -- the stream to read from
+// [pdata] -- the CData object to read to
+//
+// Requires:
+//
+// Returns: NOERROR on success
+// CONVERT10_E_OLESTREAM_GET on stream read problem
+// E_OUTOFMEMORY on allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 davepl Cleaned up and documented
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL GetSizedDataOLE1Stm(LPOLESTREAM pos, PDATA pdata)
+{
+ ULONG cbSize;
+ HRESULT hr;
+ Assert (0==pdata->m_cbSize && pdata->m_h==NULL && NULL==pdata->m_pv);
+
+ // Read size of data
+ if (FAILED(hr = OLE1StreamToUL(pos, &cbSize)))
+ {
+ return hr;
+ }
+
+ if (cbSize==0)
+ {
+ return NOERROR;
+ }
+
+ // Allocate memory for data
+ pdata->m_cbSize = cbSize;
+
+ pdata->m_h = GlobalAlloc (GMEM_MOVEABLE, cbSize);
+ if (NULL==pdata->m_h)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+ pdata->m_pv = GlobalLock (pdata->m_h);
+
+ if (NULL==pdata->m_pv)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // Read data into allocated buffer
+
+ if (pos->lpstbl->Get (pos, pdata->m_pv, cbSize) < cbSize)
+ {
+ return ResultFromScode(CONVERT10_E_OLESTREAM_GET);
+ }
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OLE1StreamToUL, INTERNAL
+//
+// Synopsis: Reads a ULONG from an OLE1 stream
+//
+// Arguments: [pos] -- the OLE 1 stream to read from
+// [pul] -- the ULONG to read into
+//
+// Returns: NOERROR on success
+// CONVERT10_E_OLESTREAM_GET on stream read failure
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 davepl Cleaned up and documented
+//
+// Notes: on failure [pul] is preserved
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL OLE1StreamToUL(LPOLESTREAM pos, ULONG FAR* pul)
+{
+ ULONG ul;
+
+ // Read the data from the stream into the local ULONG
+
+ if (pos->lpstbl->Get (pos, &ul, sizeof(ULONG)) < sizeof(ULONG))
+ {
+ return ResultFromScode(CONVERT10_E_OLESTREAM_GET);
+ }
+
+ // If all went well, store the data into [pul]
+
+ if (pul != NULL)
+ {
+ Assert (!IsBadWritePtr (pul, sizeof(ULONG)));
+ *pul = ul;
+ }
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DataToOLE1Stm, INTERNAL INLINE
+//
+// Synopsis: Writes raw data out to an OLE 1 stream
+//
+// Arguments: [pos] -- the stream to write to
+// [pvBuf] -- the buffer to write from
+// [ulSize] -- the number of bytes to write
+//
+// Returns: NOERROR on success
+// CONVERT10_E_OLESTREAM_PUT on stream write failure
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 davepl Cleaned up and documented
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline static INTERNAL DataToOLE1Stm(LPOLESTREAM pos, LPVOID pvBuf, ULONG ulSize)
+{
+ // Write the data out to the stream
+
+ if (pos->lpstbl->Put(pos, pvBuf, ulSize) < ulSize)
+ {
+ return ResultFromScode(CONVERT10_E_OLESTREAM_PUT);
+ }
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ULToOLE1Stream, INTERNAL INLINE
+//
+// Synopsis: Write a ULONG to the specified OLESTREAM via the Put()
+// member of the stream's VTBL
+//
+// Effects: Advances stream position by sizeof(ULONG) on success.
+//
+// Arguments: [pos] -- The stream into which the ULONG is written
+// [ul] -- The ULONG, passed by value
+//
+// Requires:
+//
+// Returns: NOERROR on success
+// CONVERT10_E_OLESTREAM_PUT on failure
+//
+// Signals: (none)
+//
+// Modifies: Stream position
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Jan-93 davepl Cleaned up and documented
+//
+// Notes: On failure 0-3 bytes may have been written
+//
+//--------------------------------------------------------------------------
+
+inline static INTERNAL ULToOLE1Stream(LPOLESTREAM pos, ULONG ul)
+{
+ if (pos->lpstbl->Put (pos, &ul, sizeof(ULONG)) < sizeof(ULONG))
+ {
+ return ResultFromScode(CONVERT10_E_OLESTREAM_PUT);
+ }
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: StringToOLE1Stm, INTERNAL
+//
+// Synopsis: Converts the input OLESTR to ANSI and writes it to an
+// OLE 1 stream, preceded by a ULONG indicating the number
+// of bytes in the ANSI representation (terminator included).
+//
+// Arguments: [pos] -- The stream into which the ULONG is written
+// [szOleStr] -- The STR to be written
+//
+// Returns: NOERROR on success
+// CONVERT10_E_OLESTREAM_PUT on stream write failure
+// E_NOMEMORY on allocation failure
+//
+// Modifies: Stream position
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-94 davepl Cleaned up and documented
+// 15-Feb-94 davepl Re-write for ANSI/WCHAR handling
+// 17-Feb-94 davepl Restructured error handling
+//
+// Notes: On failure, 0 to (cbSize-1) bytes may have been written
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL StringToOLE1Stm(LPOLESTREAM pos, LPCOLESTR pszOleStr)
+{
+ HRESULT hr = NOERROR;
+ LPSTR pszAnsi = NULL; // Ansi version of OLE input string
+
+ if (pszOleStr)
+ {
+ // This handy function will calculate the size of the buffer we
+ // need to represent the OLESTR in ANSI format for us.
+
+ ULONG cbSize = WideCharToMultiByte(CP_ACP, // Code Page ANSI
+ 0, // No flags
+ pszOleStr, // Input OLESTR
+ -1, // Input len (auto detect)
+ NULL, // Output buffer
+ 0, // Output len (check only)
+ NULL, // Default char
+ NULL);// Flag: Default char used
+
+ if (cbSize == FALSE)
+ {
+ return ResultFromScode(E_UNSPEC);
+ }
+
+ // Now that we know the actual needed length, allocate a buffer
+
+ pszAnsi = (LPSTR) PrivMemAlloc(cbSize);
+ if (NULL == pszAnsi)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // We've got out buffer and our length, so do the conversion now
+ // We don't need to check for cbSize == FALSE since that was
+ // already done during the length test, but we need to check
+ // for substitution. Iff this call sets the fDefChar even when
+ // only doing a length check, these two tests could be merged,
+ // but I don't believe this is the case.
+
+ BOOL fDefUsed = 0;
+ cbSize = WideCharToMultiByte(CP_ACP, // Code Page ANSI
+ 0, // No flags
+ pszOleStr, // Input OLESTR
+ -1, // Input len (auto detect)
+ pszAnsi, // Output buffer
+ cbSize, // Output len
+ NULL, // Default char (use system's)
+ &fDefUsed); // Flag: Default char used
+
+ // If number of bytes converted was 0, we failed
+
+ if (fDefUsed)
+ {
+ hr = ResultFromScode(E_UNSPEC);
+ }
+
+ // Write the size of the string (including null terminator) to stream
+
+ else if (FAILED(hr = ULToOLE1Stream(pos, cbSize)))
+ {
+ NULL;
+ }
+
+ // Write the Ansi version of the string into the stream
+
+ else if (pos->lpstbl->Put(pos, pszAnsi, cbSize) < cbSize)
+ {
+ hr = ResultFromScode(CONVERT10_E_OLESTREAM_PUT);
+ }
+
+ if (pszAnsi)
+ {
+ PrivMemFree(pszAnsi);
+ }
+ }
+
+ // If the pointer is not valid, we write a length of zero into
+ // the stream
+
+ else
+ {
+ hr = ULToOLE1Stream(pos, 0);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OLE2StmToUL, INTERNAL
+//
+// Synopsis: Reads a ULONG from the specified ISTREAM and stores it at
+// the ULONG deferenced by pul
+//
+// Effects: Writes the value read into memory at pul
+//
+// Arguments: [pstm] -- The stream from which the ULONG is read
+// [pul] -- ULONG to hold the value read
+//
+// Requires:
+//
+// Returns: NOERROR on success
+// CONVERT10_E_OLESTREAM_PUT on failure
+//
+// Signals: (none)
+//
+// Modifies: Stream position
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 11-Feb-93 davepl Cleaned up and documented
+//
+// Notes: On failure, *pul is not disturbed regardless of how
+// many bytes were actually read from the stream
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL OLE2StmToUL(LPSTREAM pstm, ULONG FAR* pul)
+{
+ ULONG ul;
+ ULONG cbRead;
+ HRESULT hr = NOERROR;
+
+ // Attempt to read 4 bytes from the stream to form a ULONG.
+
+ if (FAILED(hr = pstm->Read (&ul, sizeof(ULONG), &cbRead)))
+ {
+ return hr;
+ }
+
+ if (cbRead != sizeof(ULONG))
+ {
+ hr = STG_E_READFAULT;
+ }
+ // Ensure that the [pul] pointer is valid and that we have write
+ // access to all 4 bytes (assertion only). If OK, transfer the
+ // ULONG to [*pul]
+ else if (pul != NULL)
+ {
+ Assert (FALSE == IsBadWritePtr(pul, sizeof(ULONG)));
+ *pul = ul;
+ }
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OLE1StmToString, INTERNAL
+//
+// Synopsis: Reads a cstr from the specified STREAM and stores it in
+// a dynamically allocated buffer as an OLESTR; sets the
+// user's pointer to point to this new buffer.
+//
+// Effects: Allocates memory on the input pointer, advances stream pos'n
+//
+// Arguments: [pos ] -- The stream from which the STR is read
+// [ppsz] -- OLESTR ** which allows this fn to modify the
+// caller's pointer to point to memory allocated
+// by this fn to hold the OLESTR
+//
+// Requires: Stream must be set up. Caller's responsibilty to free memory.
+//
+// Returns: NOERROR on success
+// CONVERT10_E_OLESTREAM_GET on failure
+// E_OUTOFMEMORY if buffers couldn't be allocated
+//
+// Signals: (none)
+//
+// Modifies: Stream position, caller's string pointer
+//
+// Algorithm: if ppsz == NULL, string is read from stream and discarded
+// if ppsz != NULL, string is read and converted into a
+// dynamically allocated buffer. *ppsz is set
+// to point to this buffer, which must be later
+// freed by the caller
+//
+// History: dd-mmm-yy Author Comment
+// 12-Jan-93 davepl Cleaned up and documented
+// 14-Jan-93 davepl Changed to return LPOLESTR
+//
+// Notes: [ppsz] may be NULL on entry; string is read and discarded
+// with no cleanup required by the caller
+//
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL OLE1StmToString(LPOLESTREAM pos, LPOLESTR FAR* ppsz)
+{
+ ULONG cbSize; // Size in bytes of cstr
+ LPOLESTR pszOleStr = NULL;
+ LPSTR pszAnsiStr = NULL;
+ HRESULT error = NOERROR;
+
+ // if ppsz is valid, NULL out *ppsz as default out parameter
+
+ if (NULL != ppsz)
+ {
+ *ppsz = NULL;
+ }
+
+ // Retrieve the incoming string size from the stream
+
+ if (FAILED(error = OLE1StreamToUL (pos, &cbSize)))
+ {
+ goto errRtn;
+ }
+
+ // If there are chars to be read, allocate memory for the
+ // ANSI and OLESTR versions. Read the string into the
+ // ANSI version and convert it to OLESTR
+
+ if (0 < cbSize)
+ {
+ // Allocate the ANSI buffer
+ pszAnsiStr = (LPSTR) PrivMemAlloc((size_t)cbSize);
+ if (NULL == pszAnsiStr)
+ {
+ error = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ // Read the string into the ANSI buffer
+ if (pos->lpstbl->Get (pos, pszAnsiStr, cbSize) < cbSize)
+ {
+ error = ResultFromScode(CONVERT10_E_OLESTREAM_GET);
+ goto errRtn;
+ }
+
+ // We only need to perform the ANSI->OLESTR conversion in those
+ // cases where the caller needs an out parameter
+
+ if (NULL != ppsz)
+ {
+ // Allocate the OLESTR buffer
+ pszOleStr = (LPOLESTR) PubMemAlloc((size_t)cbSize * 2);
+ if (NULL == pszOleStr)
+ {
+ error = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ // Convert from ANSI buffer to OLESTR buffer
+ if (FALSE==MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszAnsiStr,
+ cbSize, pszOleStr, cbSize *2))
+ {
+ error = HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION);
+ PubMemFree(pszOleStr);
+ goto errRtn;
+ }
+ *ppsz = pszOleStr;
+ }
+ }
+
+errRtn:
+
+ if (pszAnsiStr)
+ {
+ PrivMemFree(pszAnsiStr);
+ }
+
+ return error;
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GenericObjectToIStorage
+//
+// Synopsis: Write the generic object in memory out to an OLE 2 IStorage
+// This invovles writing the class, native data, and
+// presentation data out where applicable.
+//
+// Arguments: [genobj] -- the generic object holding the info
+// [pstg] -- the IStorage object to write to
+// [ptd] -- target device
+//
+// Returns: NOERROR on success
+// CONVERT10_S_NO_PRESENTATION in cases where the object did
+// not have needed presentation data
+//
+// History: dd-mmm-yy Author Comment
+// 17-Feb-94 davepl Cleanup and document
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+FARINTERNAL GenericObjectToIStorage(
+ const GENOBJ FAR& genobj,
+ LPSTORAGE pstg,
+ const DVTARGETDEVICE FAR* ptd)
+{
+ HRESULT hr = NOERROR;
+
+ // Assert (genobj.m_class.m_clsid != CLSID_NULL);
+
+ // Write the class ID out to the storage
+ if (FAILED(hr = WriteClassStg (pstg, genobj.m_class.m_clsid)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to WriteClassStg at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ return hr;
+ }
+
+ if (!genobj.m_fLink)
+ {
+ if (genobj.m_fStatic)
+ {
+ // If we are a static embedded object, get the format name from
+ // the registration database and write it out to the IStorage
+
+ LPOLESTR pszUserType = NULL;
+
+ OleRegGetUserType(genobj.m_class.m_clsid, USERCLASSTYPE_FULL,
+ &pszUserType);
+
+ WriteFmtUserTypeStg (pstg, genobj.m_ppres->m_format.m_cf,
+ pszUserType);
+
+ if (pszUserType)
+ {
+ PubMemFree(pszUserType);
+ }
+ }
+ else if (wWriteFmtUserType (pstg, genobj.m_class.m_clsid) != NOERROR)
+ {
+ // This happens when the class is not registered.
+ // Use ProgId as UserType.
+
+ WriteFmtUserTypeStg (pstg,
+ RegisterClipboardFormat (genobj.m_class.m_szClsid),
+ genobj.m_class.m_szClsid);
+ }
+ }
+
+ if (FAILED(hr = GenObjToOLE2Stm (pstg, genobj)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to write gen obj to stream at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ return hr;
+ }
+
+ // If it's not a link and not a static object, dump its native
+ // data out to the storage
+
+ if (!genobj.m_fLink && !genobj.m_fStatic)
+ {
+ if (FAILED(hr=Write20NativeStreams (pstg, genobj)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to write native stream at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ return hr;
+ }
+ }
+
+ if (! genobj.m_fLink)
+ {
+ if (genobj.m_class.m_clsid == CLSID_PBrush)
+ {
+ if (! genobj.m_ppres || (genobj.m_ppres->m_format.m_cf == CF_DIB))
+ {
+ // If the object is not a link, and it is a PBrush object with
+ // either a DIB presentation or no presentation at all, we
+ // don't need to do anything.
+
+ return NOERROR;
+ }
+ }
+
+ if (genobj.m_class.m_clsid == CLSID_MSDraw)
+ {
+ if (! genobj.m_ppres ||
+ (genobj.m_ppres->m_format.m_cf == CF_METAFILEPICT))
+ {
+ // Similarly, if it is not a link, and it is an MSDraw object
+ // with no presentation or a METAFILEPICT presentation, we
+ // don't need to do anything.
+
+ return NOERROR;
+ }
+ }
+ }
+
+ // In all other cases, we have to dump the presenation data out to
+ // the storage.
+
+ if (FAILED(hr = PresToIStorage (pstg, genobj, ptd)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to write pres to IStorage at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ return hr;
+ }
+
+ // If we are a static object, copy the contents of the presentation
+ // stream over to the contents stream.
+
+ if (genobj.m_fStatic)
+ {
+ UINT uiStatus;
+ return UtOlePresStmToContentsStm(pstg, OLE_PRESENTATION_STREAM,
+ TRUE, &uiStatus);
+ }
+
+ // If we don't have a presentation (but weren't one of the special
+ // cases handled above), we have a problem
+
+ //
+ // We don't care if genobj.m_pres is NULL if a blank presentation is
+ // permited as the routine PresToIStorage will generate a blank pres.
+ //
+ if ((NULL == genobj.m_ppres) && genobj.m_fNoBlankPres)
+ {
+ LEDebugOut(( DEB_ERROR,
+ "We have no presentation at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ return ResultFromScode(CONVERT10_S_NO_PRESENTATION);
+ }
+
+ return NOERROR;
+
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GenObjToOLE2Stm, INTERNAL
+//
+// Synopsis: Write the generic object out to the OLE 2 stream
+//
+// Effects: Write the whole object, including presentation data, etc.
+//
+// Arguments: [pstg] -- the IStorage to write to
+// [genobj] -- the generic object to write
+//
+// Returns: NOERROR on success
+// This is an upper level function, so there are numerous
+// error that could be propagated up through it
+//
+// History: dd-mmm-yy Author Comment
+// 14-Feb-94 davepl Code cleanup and document
+//
+// Notes: The code is enclosed in a do{}while(FALSE) block so that
+// we can break out of it on any error and fall through to
+// the cleanup and error return code.
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL GenObjToOLE2Stm(LPSTORAGE pstg, const GENOBJ FAR& genobj)
+{
+ HRESULT hr = NOERROR;
+ LPSTREAM pstm=NULL;
+
+ do { // The do{}while(FALSE) allows us to break out on error
+
+ // Create a stream in the current IStorage
+ if (FAILED(hr = OpenOrCreateStream (pstg, OLE_STREAM, &pstm)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Can't create streamat line %d in %s\n",
+ __LINE__, __FILE__));
+
+ break;
+ }
+
+ // Write the Ole version out to that new stream
+ if (FAILED(hr = ULToOLE2Stm (pstm, gdwOleVersion)))
+ {
+ break;
+ }
+
+ // Write the object flags (for links only, otherwise 0) to the stream
+ if (FAILED(hr = ULToOLE2Stm
+ (pstm, genobj.m_fLink ? OBJFLAGS_LINK : 0L)))
+ {
+ break;
+ }
+
+ // Write the update options out to the stream
+ if (genobj.m_fLink || genobj.m_class.m_clsid == CLSID_StdOleLink)
+ {
+ // If our object's link update options are UPDATE_ONCALL, we
+ // write out the corresponding OLE 2 flags, otherwise, we
+ // write out OLEUPDATE_ALWAYS
+
+ if (genobj.m_lnkupdopt==UPDATE_ONCALL)
+ {
+ if (FAILED(hr = ULToOLE2Stm (pstm, OLEUPDATE_ONCALL)))
+ {
+ break;
+ }
+ }
+ else
+ {
+ if (FAILED(hr = ULToOLE2Stm (pstm, OLEUPDATE_ALWAYS)))
+ {
+ break;
+ }
+ }
+
+ }
+ else
+ {
+ // We are neither a link nor a StdOleLink, so we have no
+ // update options.. just write out a 0.
+ if (FAILED(hr = ULToOLE2Stm (pstm, 0L)))
+ {
+ break;
+ }
+ }
+
+ // This is a reserved filed (was View Format), just write a 0
+ if (FAILED(hr = ULToOLE2Stm (pstm, 0L)))
+ {
+ break;
+ }
+
+ // We have no relative moniker, write out NULL
+ if (FAILED(hr = WriteMonikerStm (pstm, (LPMONIKER)NULL)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to write moniker to stream at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ break;
+ }
+
+ // If we are a link, we have to write out all of that information...
+
+ if (genobj.m_fLink || genobj.m_class.m_clsid == CLSID_StdOleLink)
+ {
+ // relative source moniker
+ if (FAILED(hr = WriteMonikerStm (pstm, (LPMONIKER)NULL)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to write moniker to stream at line %d in %s\n",
+ __LINE__, __FILE__));
+ break;
+ }
+
+ // absolute source moniker
+ if (FAILED(hr = MonikerToOLE2Stm (pstm, genobj.m_szTopic,
+ genobj.m_szItem, genobj.m_classLast.m_clsid)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to write moniker to stream at line %d in %s\n",
+ __LINE__, __FILE__));
+ break;
+ }
+
+ // write the classLast field to the stream
+
+ CLSID clsid;
+
+ // If we have the classLast already, use that clsid
+ if (genobj.m_classLast.m_szClsid)
+ {
+ clsid = genobj.m_classLast.m_clsid;
+ }
+ else
+ {
+ // Otherwise, if it's a StdOleLink, class id is NULL
+ if (genobj.m_class.m_clsid == CLSID_StdOleLink)
+ {
+ clsid = CLSID_NULL;
+ }
+ else
+ {
+ // If we don't have last class and not a link, use the
+ // class id of the generic object
+ clsid = genobj.m_class.m_clsid;
+ }
+ }
+
+ if (FAILED(hr = WriteM1ClassStm(pstm, clsid)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to write M1 to stream at line %d in %s\n",
+ __LINE__, __FILE__));
+ break;
+ }
+
+ // last display == NULL string
+ if (FAILED(hr = ULToOLE2Stm (pstm, 0L)))
+ {
+ break;
+ }
+
+ // Last Change time
+ if (FAILED(hr = FTToOle2Stm (pstm)))
+ {
+ break;
+ }
+
+ // Last known up to date
+ if (FAILED(hr = FTToOle2Stm (pstm)))
+ {
+ break;
+ }
+
+ // rtUpdate
+ if (FAILED(hr = FTToOle2Stm (pstm)))
+ {
+ break;
+ }
+
+ // end marker
+ if (FAILED(hr = ULToOLE2Stm(pstm, (ULONG) -1L)))
+ {
+ break;
+ }
+ }
+
+ } while (FALSE); // This do{}while(FALSE) is a once-through "loop"
+ // that we can break out of on error and fall
+ // through to the return.
+
+ if (pstm)
+ {
+ pstm->Release();
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: MonikerToOLE2Stm, INTERNAL
+//
+// Synopsis: Write the file and item moniker as a composite to the stream
+//
+// Effects: Builds a composite of the file and item monikers, and then
+// writes them out. If there is no file, a NULL moniker is
+// written in its place
+//
+// Arguments: [pstm] -- The OLE2 storage we are writing to
+// [pszFile] -- The file associated with the object
+// [spzItem] -- The item
+// [clsid] -- The class ID of the object
+//
+// Returns: NOERROR on success
+//
+// History: dd-mmm-yy Author Comment
+// 18-Feb-94 davepl Reworked, cleaned up and documented
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+
+#pragma SEG(MonikerToOLE2Stm)
+static INTERNAL MonikerToOLE2Stm(
+ LPSTREAM pstm,
+ LPOLESTR szFile,
+ LPOLESTR szItem,
+ CLSID clsid) // CLSID of the link source file, szFile
+
+{
+ HRESULT hr = NOERROR;
+ LPMONIKER pmkFile = NULL; // File moniker
+ LPMONIKER pmkItem = NULL; // Item moniker
+ LPMONIKER pmkComp = NULL; // Composite of file + item monikers
+
+
+ // If we don't have a file, write a NULL moniker
+ if (NULL == szFile)
+ {
+ if (FAILED(hr = WriteMonikerStm (pstm, NULL)))
+ {
+ goto errRtn;
+ }
+ }
+ else
+ {
+ // Otherwise, create a file moniker (OLE1 or OLE2 as appplicable)
+
+ if (CoIsOle1Class (clsid))
+ {
+ if (FAILED(hr = CreateOle1FileMoniker (szFile, clsid, &pmkFile)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Can't create OLE 1 moniker at line %d in %s\n",
+ __LINE__, __FILE__));
+ goto errRtn;
+ }
+ }
+ else
+ {
+ if (FAILED(hr = CreateFileMoniker (szFile, &pmkFile)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Can't create file moniker at line %d in %s\n",
+ __LINE__, __FILE__));
+ goto errRtn;
+ }
+ }
+
+ // If we don't have an Item, write just the file moniker
+
+ if (NULL==szItem)
+ {
+ if (FAILED(hr = WriteMonikerStm (pstm, pmkFile)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to write moniker to stream at line %d in %s\n",
+ __LINE__, __FILE__));
+ goto errRtn;
+ }
+
+ }
+
+ // Otherwise, create a composite of the file + item monikers
+ // and write it out
+
+ else
+ {
+ if (FAILED(hr=CreateItemMoniker(OLESTR("!"), szItem, &pmkItem)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to create item moniker at line %d in %s\n",
+ __LINE__, __FILE__));
+ goto errRtn;
+ }
+
+ if (FAILED(hr=CreateGenericComposite(pmkFile, pmkItem, &pmkComp)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to create generic pres at line %d in %s\n",
+ __LINE__, __FILE__));
+ goto errRtn;
+ }
+
+ if (FAILED(hr = WriteMonikerStm (pstm, pmkComp)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to write moniker to stream at line %d in %s\n",
+ __LINE__, __FILE__));
+ goto errRtn;
+ }
+ }
+ }
+
+
+ errRtn:
+ if (pmkFile)
+ {
+ pmkFile->Release();
+ }
+ if (pmkItem)
+ {
+ pmkItem->Release();
+ }
+ if (pmkComp)
+ {
+ pmkComp->Release();
+ }
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsStandardFormat, INTERNAL
+//
+// Synopsis: Returns TRUE if object is in clipboard format and is one
+// one of the three standard formats (METAFILE, DIB, BITMAP)
+//
+// Arguments: [format] -- the format object which contains the
+// format tag and clipboard format type
+//
+// Returns: TRUE if METAFILE, DIB, or BITMAP
+// FALSE if other format or not clipboard format at all
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 davepl documented and chaged from big
+// conditional to a switch()
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL_(BOOL) IsStandardFormat(const FORMAT FAR& format)
+{
+ // First we must ensure that the format tag indicates that this
+ // object is in clipboard format at all...
+
+ if (format.m_ftag == ftagClipFormat)
+ {
+ // If so, there is a limited set of clipboard formats which
+ // we consider "standard". If it is not among these,
+ // we return FALSE.
+
+ switch(format.m_cf)
+ {
+ case CF_METAFILEPICT:
+ case CF_BITMAP:
+ case CF_DIB:
+
+ return TRUE;
+
+
+ default:
+
+ return FALSE;
+
+ }
+ }
+ return FALSE;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: PresToIStorage, INTERNAL
+//
+// Synopsis: Given an generic object and an IStorage, write genobj's
+// presentation data out to the storage
+//
+// Effects: Will call PresToNewOLE2Stm to create a stream in this
+// storage to hold the presentation data
+//
+// Arguments: [pstg] -- the storage to save to
+// [genobj] -- the generic object holding the presenation
+// [ptd] -- the target device for the presentation
+//
+// Returns: NOERROR on success
+// Various other errors may propagate back up from I/O funcs
+//
+// History: dd-mmm-yy Author Comment
+// 18-Feb-94 davepl ARRGR! Cleanup and document
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL PresToIStorage(
+ LPSTORAGE pstg,
+ const GENOBJ FAR& genobj,
+ const DVTARGETDEVICE FAR* ptd)
+{
+ HRESULT hr = NOERROR;
+
+ if (genobj.m_fNoBlankPres)
+ {
+ return NOERROR;
+ }
+
+ PRES pres;
+
+ if (NULL==genobj.m_ppres)
+ {
+ // If we're not a link, and we don't have a presentation, we will
+ // create a blank presentation and write it out. If we are a link,
+ // we will do nothing, and just fall through to the return.
+
+ if (!genobj.m_fLink)
+ {
+ if (FAILED(hr = CreateBlankPres (&pres)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to create blank pres at line %d in %s\n",
+ __LINE__, __FILE__));
+ return hr;
+ }
+
+ if (FAILED(hr = PresToNewOLE2Stm
+ (pstg, genobj.m_fLink, pres, ptd, OLE_PRESENTATION_STREAM)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to write pres to new stream at line %d in %s\n",
+ __LINE__, __FILE__));
+ return hr;
+ }
+ }
+ }
+ else
+ {
+ // If the object did indeed have a presentation, we write it
+ // out to a new stream
+
+ if (IsStandardFormat (genobj.m_ppres->m_format))
+ {
+ // If the presentation is a standard clipboard
+ // format, we can write it out with no other work
+
+ if (FAILED(hr = PresToNewOLE2Stm ( pstg,
+ genobj.m_fLink,
+ *(genobj.m_ppres),
+ ptd,
+ OLE_PRESENTATION_STREAM)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to write pres to new stream at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ return hr;
+ }
+
+ }
+ else
+ {
+ // If the presentation is not a standard format,
+ // it may be a PBrush object (handled below), or if
+ // not, we write it as a generic presentation stream
+
+ if (genobj.m_classLast.m_clsid != CLSID_PBrush)
+ {
+ if(FAILED(hr = PresToNewOLE2Stm ( pstg,
+ genobj.m_fLink,
+ *(genobj.m_ppres),
+ ptd,
+ OLE_PRESENTATION_STREAM)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to write pres to new stream at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ return hr;
+ }
+ }
+ else // PBrush
+ {
+ BOOL fPBrushNative = FALSE;
+
+ // We know this is a PBrush object. If the
+ // format tag is a format string, check to see
+ // if that string is "Native", in which case
+ // we set the flag to indicate that this is
+ // native pbrush data.
+
+ if (genobj.m_ppres->m_format.m_ftag == ftagString)
+ {
+ if (!strcmp( (LPCSTR) genobj.m_ppres->
+ m_format.m_dataFormatString.m_pv,
+ "Native"
+ )
+ )
+ {
+ fPBrushNative = TRUE;
+ }
+ }
+
+ if (FAILED(hr = PresToNewOLE2Stm( pstg,
+ genobj.m_fLink,
+ *(genobj.m_ppres),
+ ptd,
+ OLE_PRESENTATION_STREAM,
+ fPBrushNative)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to write pres to new stream at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ return hr;
+ }
+
+
+ }
+
+ }
+ }
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: PresToNewOLE2Stm, INTERNAL
+//
+// Synopsis: Creates a new stream within a storage and writes the
+// generic object's presentation data out to it.
+//
+// Arguments: [pstg] -- the storage in which to create the stream
+// [fLink] -- flag: is this object a link?
+// [pres] -- the presentation data to be saved
+// [ptd] -- the target render device
+// [szStream] -- the name of the new stream
+// [fPBrushNative] -- flag: is this native PBrush pres data?
+//
+// Returns: NOERROR on success
+// STG_E_WRITEFAULT on stream write failure
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleanup and documentation
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL PresToNewOLE2Stm(
+ LPSTORAGE pstg,
+ BOOL fLink,
+ const PRES FAR& pres,
+ const DVTARGETDEVICE FAR* ptd,
+ LPOLESTR szStream,
+ BOOL fPBrushNative
+)
+{
+HRESULT hr = NOERROR;
+LPSTREAM pstm=NULL;
+FORMATETC foretc;
+
+
+
+ // Create the new stream to hold the presentation data
+ if (FAILED(hr = OpenOrCreateStream (pstg, szStream, &pstm)))
+ {
+ goto errRtn;
+ }
+
+ // Fill in the FormatEtc structure
+ if (fPBrushNative)
+ {
+ foretc.cfFormat = CF_DIB;
+ }
+ else
+ {
+ switch( pres.m_format.m_ftag)
+ {
+ case ftagClipFormat:
+ foretc.cfFormat = pres.m_format.m_cf;
+ break;
+ case ftagString:
+ // m_dataFormatString is an ASCII string.
+ foretc.cfFormat = SSRegisterClipboardFormatA( (LPCSTR) pres.m_format.m_dataFormatString.m_pv);
+ Assert(0 != foretc.cfFormat);
+ break;
+ default:
+ AssertSz(0,"Error in Format");
+ hr = E_UNEXPECTED;
+ goto errRtn;
+ break;
+ }
+ }
+
+
+ foretc.ptd = (DVTARGETDEVICE *) ptd;
+ foretc.dwAspect = DVASPECT_CONTENT;
+ foretc.lindex = -1;
+ foretc.tymed = TYMED_NULL; // tymed field is ignored by utWriteOlePresStmHeader.
+
+ if (FAILED(hr = UtWriteOlePresStmHeader(pstm,&foretc,(fLink) ? (ADVF_PRIMEFIRST) : (0L))))
+ {
+ goto errRtn;
+ }
+
+ if (fPBrushNative)
+ {
+ if (FAILED(hr = UtHDIBFileToOlePresStm(pres.m_data.m_h, pstm)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Unable to write DIB to stream at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ goto errRtn;
+ }
+ }
+ else
+ {
+ // Compression
+ if (FAILED(hr = ULToOLE2Stm (pstm, 0L)))
+ {
+ goto errRtn;
+ }
+
+ // Width / Height
+ if (FAILED(hr = ULToOLE2Stm (pstm, pres.m_ulWidth)))
+ {
+ goto errRtn;
+ }
+ if (FAILED(hr = ULToOLE2Stm (pstm, pres.m_ulHeight)))
+ {
+ goto errRtn;
+ }
+
+ // Presentation data
+ if (FAILED(hr = DataObjToOLE2Stm (pstm, pres.m_data)))
+ {
+ goto errRtn;
+ }
+ }
+
+ errRtn:
+ if (pstm)
+ {
+ pstm->Release();
+ }
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ULToOLE2Stm, INTERNAL
+//
+// Synopsis: Writes a ULONG out to an OLE2 stream
+//
+// Arguments: [pstm] -- the stream to write to
+// [ul] -- the ULONG to write to that stream
+//
+// Returns: NOERROR on success
+// STG_E_WRITEFAULT on write failure
+//
+// History: dd-mmm-yy Author Comment
+// 18-Feb-94 davepl Cleaned up and documented
+//
+//--------------------------------------------------------------------------
+
+inline static INTERNAL ULToOLE2Stm(LPSTREAM pstm, ULONG ul)
+{
+ // Write the ULONG out
+ return pstm->Write (&ul, sizeof(ULONG), NULL);
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: FTToOLE2Stm, INTERNAL
+//
+// Synopsis: Writes a dummy filetime out to an OLE2 stream
+//
+// Arguments: [pstm] -- the stream to write to
+//
+// Returns: NOERROR on success
+// STG_E_WRITEFAULT on write failure
+//
+// History: dd-mmm-yy Author Comment
+// 31-Mar-95 scottsk Created
+//
+//--------------------------------------------------------------------------
+
+inline static INTERNAL FTToOle2Stm(LPSTREAM pstm)
+{
+ FILETIME ft = { 0, 0 };
+
+ return pstm->Write (&ft, sizeof(FILETIME), NULL);
+
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DataObjToOLE2Stm
+//
+// Synopsis: Writes a fixed-size data buffer to an OLE2 stream preceded
+// by a ULONG indicating the number of bytes to follow.
+//
+// Returns: NOERROR on success
+// STG_E_WRITEFAULT on write failure
+//
+// History: dd-mmm-yy Author Comment
+// 18-Feb-94 davepl Code cleanup
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL DataObjToOLE2Stm(LPSTREAM pstm, const DATA FAR& data)
+{
+ HRESULT hr;
+
+
+ // Write a ULONG indicating the number of bytes to follow
+ if (FAILED(hr = ULToOLE2Stm (pstm, data.m_cbSize)))
+ {
+ return hr;
+ }
+
+ // If there are any bytes to follow...
+ if (data.m_cbSize)
+ {
+ if (FAILED(hr = pstm->Write (data.m_pv, data.m_cbSize, NULL)))
+ {
+ return hr;
+ }
+ }
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: SizedDataToOLE1Stm
+//
+// Synopsis: Writes a fixed-size data buffer to an OLE1 stream preceded
+// by a ULONG indicating the number of bytes to follow.
+//
+// Parameters: [pos] -- The stream to write to
+// [data] -- The data object to write out
+//
+// Returns: NOERROR on success
+// STG_E_WRITEFAULT on write failure
+//
+// History: dd-mmm-yy Author Comment
+// 18-Feb-94 davepl Code cleanup
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL SizedDataToOLE1Stm(LPOLESTREAM pos, const DATA FAR& data)
+{
+ HRESULT hr = NOERROR;
+
+ // Ensure the memory we are going to write out is valid
+ Assert (data.m_pv);
+
+ // Write the ULONG representing the byte count of the sized data
+
+ if (FAILED(hr = ULToOLE1Stream (pos, data.m_cbSize)))
+ {
+ Assert (0 && "Can't write UL to ole1 stream");
+ return hr;
+ }
+
+ if (pos->lpstbl->Put (pos, data.m_pv, data.m_cbSize) < data.m_cbSize)
+ {
+ Assert (0 && "Cant write sized data to ole1 stream");
+ return ResultFromScode(CONVERT10_E_OLESTREAM_PUT);
+ }
+ return NOERROR;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: Write20NativeStreams, INTERNAL
+//
+// Synopsis: Writes the generic object's native data out to an OLE 2 stream
+//
+// Effects: Creates an ILockBytes on the handle to the native data, and
+// then attempts to create a storage on it. If it can, it uses
+// the CopyTo interface to write that storage into our OLE 2
+// stream. Otherwise, it manually creates a stream in the OLE 2
+// storage and dumps the native data into it.
+//
+// Arguments: [pstg] -- the OLE 2 storage we are saving genobj to
+// [genobj] -- the generic object we are writing
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failure
+// STG_E_WRITEFAULT on storage write failure
+//
+// History: dd-mmm-yy Author Comment
+// 18-Feb-94 davepl Removed 14 goto's (for better or worse)
+// See "Notes" for new control flow
+// 24-Mar-94 alext Fix OLE 1 native case (there was an
+// extra stream open)
+//
+// Notes: There are two possible major codepaths based on the creation
+// of the Stg on ILockBytes. The outcome is handled by a
+// switch statement, and both the TRUE and FALSE cases are
+// loaded with break statements that will bail out to the
+// bottom of the function on any failure. This gives us a
+// single entry and exit point, without all the gotos
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL Write20NativeStreams(LPSTORAGE pstg, const GENOBJ FAR& genobj)
+{
+ LPLOCKBYTES plkbyt = NULL;
+ LPSTORAGE pstgNative = NULL;
+ LPSTREAM pstmNative = NULL;
+ HRESULT hr = NOERROR;
+
+ // Create an ILockBytes instance on our generic object's native data
+
+ if (SUCCEEDED(hr = CreateILockBytesOnHGlobal
+ (genobj.m_dataNative.m_h, FALSE, &plkbyt)))
+ {
+ // If the ILockBytes appears to contain an IStorage, then this was
+ // an OLE 2 object "hiding" within the OLE 1 stream as native data
+
+ switch ((DWORD)(S_OK == StgIsStorageILockBytes (plkbyt)))
+ {
+ case (TRUE):
+
+ // Open the IStorage contained in the ILockBytes
+
+ if (FAILED(hr = StgOpenStorageOnILockBytes (plkbyt,
+ (LPSTORAGE)NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT,
+ (SNB)NULL,
+ 0,
+ &pstgNative)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Can't open storage on ILBytes at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ break; // on failure fall through to error return
+ }
+
+ // Remove the stream from the native data
+
+ if (FAILED(hr = UtDoStreamOperation(pstgNative,
+ NULL, // pstgDst
+ OPCODE_REMOVE, // operation
+ STREAMTYPE_CACHE))) // stream
+ {
+ LEDebugOut(( DEB_ERROR,
+ "OPCODE REMOVE stream op failed at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ break; // on failure fall through to error return
+ }
+
+ // Copy the "hidden" IStorage to our destination storage
+
+ if (FAILED(hr = pstgNative->CopyTo (0, NULL,(SNB)NULL, pstg)))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "CopyTo member fn failed at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ break; // on failure fall through to error return
+ }
+
+ break; // end case TRUE
+
+
+ case FALSE:
+
+ // This is the typical case, where the OLE 1 stream had just
+ // plain old native data, so write it to a stream inside our
+ // output IStorage and call it OLE10_NATIVE_STREAM
+
+ ULONG cb;
+ LPVOID pv = genobj.m_dataNative.m_pv;
+
+ if (NULL == pv)
+ {
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ break;
+ }
+
+ // Create the new stream to hold the native data
+
+ if (FAILED(hr = OpenOrCreateStream
+ (pstg, OLE10_NATIVE_STREAM, &pstmNative)))
+ {
+ break; // on failure fall through to error return
+ }
+
+ // Write the length of the native data to the stream
+
+ if (FAILED(hr = pstmNative->Write
+ (&genobj.m_dataNative.m_cbSize, sizeof(ULONG), &cb)))
+ {
+ break; // on failure fall through to error return
+ }
+
+ // Now write the actual native data
+
+ if (FAILED(hr = pstmNative->Write
+ (pv, genobj.m_dataNative.m_cbSize, &cb)))
+ {
+ break; // on failure fall through to error return
+ }
+
+ // Write out the item name
+
+ if (genobj.m_szItem)
+ {
+ ULONG cchItem;
+ LPSTR pszAnsiItem;
+ int cbWritten;
+
+ // We need to convert m_szItem from Wide to Ansi
+
+ // The ANSI string is bounded by the byte length of the
+ // Unicode string (one Unicode character maximally translates
+ // to one double-byte char, so we just use that length
+ cchItem = lstrlenW(genobj.m_szItem) + 1;
+
+ pszAnsiItem = (LPSTR) PrivMemAlloc(cchItem * sizeof(OLECHAR));
+ if (NULL == pszAnsiItem)
+ {
+ hr = E_OUTOFMEMORY;
+ break;
+ }
+
+ // We've got out buffer and our length, so do the conversion now
+ // We don't need to check for cbSize == FALSE since that was
+ // already done during the length test, but we need to check
+ // for substitution. Iff this call sets the fDefChar even when
+ // only doing a length check, these two tests could be merged,
+ // but I don't believe this is the case.
+
+ BOOL fDefUsed = 0;
+ cbWritten = WideCharToMultiByte(CP_ACP, // Code Page ANSI
+ 0, // No flags
+ genobj.m_szItem, // Input OLESTR
+ cchItem, // Input len (auto detect)
+ pszAnsiItem, // Output buffer
+ cchItem * sizeof(OLECHAR), // Output len
+ NULL, // Default char (use system's)
+ &fDefUsed); // Flag: Default char used
+
+ // If number of bytes converted was 0, we failed
+
+ if ((FALSE == cbWritten) || fDefUsed)
+ {
+ hr = ResultFromScode(E_UNSPEC);
+ }
+ else
+ {
+ // Write the size of the string (including null terminator) to stream
+ hr = StSave10ItemName(pstg, pszAnsiItem);
+ }
+
+ PrivMemFree(pszAnsiItem);
+
+ if (FAILED(hr))
+ {
+ break; // on failure fall through to error return
+ }
+ }
+ break;
+
+ } // end switch
+ } // end if
+
+ // Free up any resources that may have been allocated in any of the
+ // code paths above
+
+ if (NULL != plkbyt)
+ {
+ plkbyt->Release();
+ }
+
+ if (NULL != pstgNative)
+ {
+ pstgNative->Release();
+ }
+
+ if (NULL != pstmNative)
+ {
+ pstmNative->Release();
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wConvertIStorageToOLESTREAM, INTERNAL
+//
+// Synopsis: Worker function; brings object from the IStorage into
+// the internal generic object representation
+//
+// Arguments: [pstg] -- the IStorage the object resides in
+// [polestream]-- the OLE 1 stream it will be going to
+// [pgenobj] -- the generic object to hold the internal rep
+//
+// Returns: NOERROR on success
+// STG_E_FILENOTFOUND bad IStorage
+// CONVERT10_E_STG_NO_STD_STREAM the IStorage was missing one
+// of the required standard streams
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleanup and documentation
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+INTERNAL wConvertIStorageToOLESTREAM (
+ LPSTORAGE pstg,
+ LPOLESTREAM polestream,
+ PGENOBJ pgenobj
+)
+{
+ SCODE scode = S_OK;
+
+ VDATEIFACE (pstg);
+
+ // Ensure that all of the pointers are valid
+
+#if DBG==1
+ if (IsBadReadPtr (polestream, sizeof(OLESTREAM)) ||
+ IsBadReadPtr (polestream->lpstbl, sizeof(OLESTREAMVTBL)) ||
+ IsBadCodePtr ((FARPROC)polestream->lpstbl->Put))
+ {
+ LEDebugOut(( DEB_ERROR,
+ "Bad OLESTREAM at line %d in %s\n",
+ __LINE__, __FILE__));
+
+ return ResultFromScode (E_INVALIDARG);
+ }
+#endif
+
+ scode = GetScode (StorageToGenericObject (pstg, pgenobj));
+
+ // If the storage was not there, modify the return code to
+ // make it specific to the conversion process, otherwise just
+ // return whatever error code came back.
+
+ if (scode != S_OK)
+ {
+ if (scode == STG_E_FILENOTFOUND)
+ {
+ return ResultFromScode(CONVERT10_E_STG_NO_STD_STREAM);
+ }
+ else
+ {
+ return ResultFromScode(scode);
+ }
+ }
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleConvertIStorageToOLESTREAM, STDAPI
+//
+// Synopsis: Reads an object from an IStorage into a generic internal
+// representation, then writes it back out to an OLE 1 stream
+//
+// Arguments: [pstg] -- the IStorage to read from
+// [polestream] -- the OLESTREAM to write to
+//
+// Returns: NOERROR on success
+// CONVERT10_E_STG_NO_STD_STREAM when one of the needed streams
+// inside the IStorage was not
+// present
+// E_INVALIDARG bad input argument
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Cleanup and documentation
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI OleConvertIStorageToOLESTREAM(LPSTORAGE pstg, LPOLESTREAM polestream)
+{
+ OLETRACEIN((API_OleConvertIStorageToOLESTREAM,
+ PARAMFMT("pstg= %p, polestream= %p"), pstg, polestream));
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleConvertIStorageToOLESTREAM ("
+ " %p , %p )\n", 0 /*function*/,
+ pstg, polestream
+ ));
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pstg);
+
+ HRESULT hr;
+ CGenericObject genobj;
+
+ // Read from the IStorage into the generic object
+ hr = wConvertIStorageToOLESTREAM(pstg, polestream, &genobj);
+ if (FAILED(hr))
+ {
+ goto errRtn;
+ }
+
+ // Write from the generic object out to the OLE 1 stream
+ hr = GenericObjectToOLESTREAM (genobj, polestream);
+
+errRtn:
+ LEDebugOut((DEB_TRACE,"%p OUT OleConvertIStorageToOLESTREAM ( %lx ) "
+ "\n", 0 /*function*/, hr));
+
+ OLETRACEOUT((API_OleConvertIStorageToOLESTREAM, hr));
+
+ return hr;
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wFillPpres, INTERNAL
+//
+// Synopsis: Fills in the generic object's presentation data by
+// building a presentation out of the native data
+//
+// Arguments: [pstg] -- the IStorage we are reading from
+// [pgenobj] -- the generic object
+// [cfFormat] -- what clipboard format is being used
+// [fOle10Native] -- flag: is this OLE 1 native data?
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY can't allocate mem for PRES member
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleanup, documentation
+// 19-Jul-94 davepl Fixed HMETAFILE cases
+//
+// Notes: Since most of this code treats HMETAFILE handles and
+// HGLOBALS indentically, we need to special case the
+// the HMETAFILE case by marking the pointer with a
+// special value
+//
+//--------------------------------------------------------------------------
+
+
+static INTERNAL wFillPpres(
+ LPSTORAGE pstg,
+ PGENOBJ pgenobj,
+ CLIPFORMAT cfFormat,
+ BOOL fOle10Native)
+{
+ pgenobj->m_ppres = new PRES;
+
+ if (pgenobj->m_ppres == NULL)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // Set the format tag and clipboard format in the PRES member
+ pgenobj->m_ppres->m_format.m_cf = cfFormat;
+ pgenobj->m_ppres->m_format.m_ftag = ftagClipFormat;
+
+ // Build the presentation based on the object's native data
+ HANDLE hpres = UtGetHPRESFromNative(pstg, pgenobj->m_ppres->m_format.m_cf,
+ fOle10Native);
+
+ void * lppres = NULL;
+
+ if (hpres == NULL)
+ {
+ return NOERROR;
+ }
+
+ // Lock the DIB or the METAFILEPICT structure
+
+ lppres = GlobalLock(hpres);
+ if (NULL == lppres)
+ {
+ goto errRtn;
+ }
+
+ if (cfFormat == CF_DIB)
+ {
+ // If it's a DIB, fill in the extents
+ LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) lppres;
+ UtGetDibExtents(lpbmi, (LPLONG) &(pgenobj->m_ppres->m_ulWidth),
+ (LPLONG) &(pgenobj->m_ppres->m_ulHeight));
+
+ GlobalUnlock(hpres);
+ pgenobj->m_ppres->m_data.m_h = hpres;
+
+ pgenobj->m_ppres->m_data.m_cbSize
+ = GlobalSize(pgenobj->m_ppres->m_data.m_h);
+ pgenobj->m_ppres->m_data.m_pv
+ = GlobalLock(pgenobj->m_ppres->m_data.m_h);
+
+
+ }
+ else if (cfFormat == CF_METAFILEPICT)
+ {
+ LPMETAFILEPICT lpmfp = (LPMETAFILEPICT) lppres;
+
+ // If it's a METAFILE, fill in the width, height
+ pgenobj->m_ppres->m_ulWidth = (ULONG) lpmfp->xExt;
+ pgenobj->m_ppres->m_ulHeight = (ULONG) lpmfp->yExt;
+ pgenobj->m_ppres->m_data.m_h = lpmfp->hMF;
+ GlobalFree(hpres);
+ hpres = NULL;
+
+ // We place a special known value in the pointer field
+ // to indicate that the associated handle is a metafile
+ // handle (as opposed to a global memory handle), which
+ // signals us to special case its cleanup.
+
+ pgenobj->m_ppres->m_data.m_pv = METADATAPTR;
+
+ // We cannot merely GlobalSize() the HMETAFILE, so we
+ // ask the GDI how many bytes we will need to store the
+ // data.
+
+ pgenobj->m_ppres->m_data.m_cbSize =
+ GetMetaFileBitsEx((HMETAFILE) pgenobj->m_ppres->m_data.m_h, 0, NULL);
+
+ if (0 == pgenobj->m_ppres->m_data.m_cbSize)
+ {
+ pgenobj->m_ppres->m_data.m_h = NULL;
+ goto errRtn;
+ }
+ }
+ else
+ {
+ goto errRtn;
+ }
+
+ return NOERROR;
+
+
+errRtn:
+ if (hpres)
+ {
+ Verify(GlobalUnlock(hpres));
+ GlobalFree(hpres);
+ }
+
+ delete pgenobj->m_ppres;
+ pgenobj->m_ppres = NULL;
+ return ResultFromScode(E_OUTOFMEMORY);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: StorageToGenericObject, INTERNAL
+//
+// Synopsis: Read an object from an IStorage into the generic object,
+// and set up the format type, native and pres data.
+//
+// Arguments: [pstg] -- the IStorage we are reading from
+// [pgenobj] -- the generic object we are reading into
+//
+// Returns: NOERROR on success
+// various possible errors from lower-level fns
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleanup and documentation
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL StorageToGenericObject(LPSTORAGE pstg, PGENOBJ pgenobj)
+{
+ CLSID clsid;
+ CLIPFORMAT cf = NULL;
+ BOOL fObjFmtKnown = FALSE;
+ HRESULT hr;
+
+ // Get the class ID from the IStorage
+ if (FAILED(hr = ReadRealClassStg (pstg, &clsid)))
+ {
+ return hr;
+ }
+
+ // Set the class ID in our generic object
+ if (CLSID_StaticMetafile == clsid || CLSID_StaticDib == clsid)
+ {
+ if (CLSID_StaticMetafile == clsid)
+ {
+ cf = CF_METAFILEPICT;
+ }
+ else
+ {
+ cf = CF_DIB;
+ }
+ fObjFmtKnown = TRUE;
+
+ pgenobj->m_class.Set(clsid, NULL);
+ pgenobj->m_fStatic = TRUE;
+ }
+ else
+ {
+ if (FAILED(hr = pgenobj->m_class.Set (clsid, pstg)))
+ {
+ return hr;
+ }
+ }
+
+ // Get the OLE version, flags, update opts, and moniker
+
+ SCODE sc = GetScode (Read20OleStream (pstg, pgenobj));
+
+ // It is okay for the Ole Stream to be missing.
+ if (sc != S_OK)
+ {
+ if (sc != STG_E_FILENOTFOUND)
+ {
+ return ResultFromScode (sc);
+ }
+ }
+
+ // Read the native data into the generic object
+ if (FAILED(hr = Read20NativeStreams (pstg, &(pgenobj->m_dataNative))))
+ {
+ return hr;
+ }
+
+ // Try to ascertain the clipboard format
+ if (cf == 0)
+ {
+ if (clsid == CLSID_PBrush)
+ {
+ cf = CF_DIB;
+ }
+ else if (clsid == CLSID_MSDraw)
+ {
+ cf = CF_METAFILEPICT;
+ }
+ else
+ {
+ ReadFmtUserTypeStg (pstg, &cf, NULL);
+ }
+
+ fObjFmtKnown = (cf == CF_METAFILEPICT || cf == CF_DIB);
+ }
+
+ // Read the presentation data if possible
+ if (FAILED(hr = Read20PresStream (pstg, pgenobj, fObjFmtKnown)))
+ {
+ return hr;
+ }
+
+ // If we don't have a presentation, it might be a PBrush object,
+ // which is OK because OLE 1 DLLs know how to draw them based on
+ // the native data. Otherwise, we will try and create a presentation
+ // based on the native data.
+
+ if (pgenobj->m_ppres == NULL)
+ {
+ if (clsid == CLSID_PBrush)
+ {
+ return NOERROR;
+ }
+ if (cf == CF_METAFILEPICT || cf == CF_DIB)
+ {
+ if (FAILED(hr=wFillPpres(pstg,pgenobj,cf,clsid == CLSID_MSDraw)))
+ {
+ return hr;
+ }
+ }
+ }
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: GenericObjectToOLESTREAM, INTERNAL
+//
+// Synopsis: Writes the interal object representation out to an OLE1
+// stream.
+//
+// Arguments: [genobj] -- the object to write out
+// [pos] -- the OLE 1 stream to write to
+//
+// Returns: NOERROR on success
+//
+// History: dd-mmm-yy Author Comment
+// 22-Feb-94 davepl 32-bit port
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL GenericObjectToOLESTREAM(
+ const GENOBJ FAR& genobj,
+ LPOLESTREAM pos)
+{
+ HRESULT hr;
+
+ if (genobj.m_fStatic)
+ {
+ return PutPresentationObject (pos, genobj.m_ppres, genobj.m_class,
+ TRUE /* fStatic*/ );
+ }
+
+ // OLE version
+ if (FAILED(hr = ULToOLE1Stream (pos, dwVerToFile)))
+ {
+ return hr;
+ }
+
+ // Format ID for embedded or linked object
+ if (FAILED(hr = ULToOLE1Stream
+ (pos, genobj.m_fLink ? FMTID_LINK : FMTID_EMBED)))
+ {
+ return hr;
+ }
+
+ // We must have the class id string by this point
+ Assert (genobj.m_class.m_szClsid);
+
+ // Write out the class ID string
+ if (FAILED(hr = StringToOLE1Stm (pos, genobj.m_class.m_szClsid)))
+ {
+ return hr;
+ }
+
+ // Write out the topic string
+ if (FAILED(hr = StringToOLE1Stm (pos, genobj.m_szTopic)))
+ {
+ return hr;
+ }
+
+ // Write out the item string
+ if (FAILED(hr = StringToOLE1Stm (pos, genobj.m_szItem)))
+ {
+ return hr;
+ }
+
+ // Write out the update options, network info for a link,
+ // or the native data for an embedded object
+ if (genobj.m_fLink)
+ {
+ // Network information
+ if (FAILED(hr = PutNetworkInfo (pos, genobj.m_szTopic)))
+ {
+ return hr;
+ }
+ // Link update options
+ if (FAILED(hr = ULToOLE1Stream (pos, genobj.m_lnkupdopt)))
+ {
+ return hr;
+ }
+ }
+ else
+ {
+ if (FAILED(hr = SizedDataToOLE1Stm (pos, genobj.m_dataNative)))
+ {
+ return hr;
+ }
+ }
+
+ // Write out the presentation data
+ return PutPresentationObject (pos, genobj.m_ppres, genobj.m_class);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: PutNetworkInfo, INTERNAL
+//
+// Synopsis: If needed, converts a DOS-style path to a proper network
+// path. In any case, writes network path to OLE 1 stream
+//
+// Arguments: [pos] -- the OLE 1 stream we are writing to
+// [szTopic] -- the topic string for this object
+//
+// Returns: NOERROR on success
+// Various possible I/O errors on write
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleanup and documentation
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL PutNetworkInfo(LPOLESTREAM pos, LPOLESTR szTopic)
+{
+ LPOLESTR szNetName = NULL;
+ HRESULT hr = NOERROR;
+
+ // If we have an X:\ style path, we want to convert that
+ // to a proper network name
+
+ if (szTopic && IsCharAlphaW(szTopic[0]) && szTopic[1]==':')
+ {
+ OLECHAR szBuf[80];
+ DWORD u;
+ OLECHAR szDrive[3];
+
+ szDrive[0] = (OLECHAR)CharUpperW((LPWSTR)szTopic[0]);
+ szDrive[1] = ':' ;
+ szDrive[2] = '\0';
+
+ if (GetDriveType (szDrive) == DRIVE_REMOTE
+ && OleWNetGetConnection (szDrive, szBuf, &u) == WN_SUCCESS)
+ {
+ szNetName =szBuf;
+ }
+ }
+
+ // We now have the network name, so write it out to OLE 1 stream
+ if (FAILED(hr = StringToOLE1Stm (pos, szNetName)))
+ {
+ return hr;
+ }
+
+ // Network type, driver version number, but we have to pad for
+ // the space anyway
+
+ if (FAILED(hr = ULToOLE1Stream (pos, 0L)))
+ {
+ return hr;
+ }
+
+ Assert (hr == NOERROR);
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OpenStream, INTERNAL
+//
+// Synopsis: Opens a stream in SHARE_EXCLUSIVE, READ mode
+//
+// Arguments: [pstg] -- the storage the stream resides in
+// [szName] -- the name of the stream
+// [ppstm] -- out parameter for stream
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleanup and document
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static inline INTERNAL OpenStream(
+ LPSTORAGE pstg,
+ LPOLESTR szName,
+ LPSTREAM FAR* ppstm)
+{
+ return pstg->OpenStream
+ (szName, NULL, STGM_SHARE_EXCLUSIVE| STGM_READ, 0, ppstm);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReadRealClassStg, INTERNAL
+//
+// Synopsis: Reads the _real_ class of the object. ie: if the class is
+// StdOleLink, we need to find out the class of the object
+// to which this is linked
+//
+// Arguments: pstg -- the storage to read from
+// pclsid -- caller's CLSID holder
+//
+// Returns: NOERROR on success
+//
+// History: dd-mmm-yy Author Comment
+// 04-Mar-04 davepl 32-bit port
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL ReadRealClassStg(LPSTORAGE pstg, LPCLSID pclsid)
+{
+ LPSTREAM pstm = NULL;
+ HRESULT hr = NOERROR;
+
+ // Get the class ID from the IStorage
+ if (FAILED(hr = ReadClassStg (pstg, pclsid)))
+ {
+ return hr;
+ }
+
+ // If it's a link, we have to figure out what class its a link _to_
+ if (CLSID_StdOleLink == *pclsid)
+ {
+ LPMONIKER pmk = NULL;
+
+ if (FAILED(hr = ReadOleStg (pstg, NULL, NULL, NULL, NULL, &pstm)))
+ {
+ return hr;
+ }
+
+ if (FAILED(hr = ReadMonikerStm (pstm, &pmk)))
+ {
+ goto errRtn;
+ }
+
+ if (pmk)
+ {
+ pmk->Release();
+ }
+
+ if (FAILED(hr = ReadMonikerStm (pstm, &pmk)))
+ {
+ goto errRtn;
+ }
+
+ if (pmk)
+ {
+ pmk->Release();
+ }
+
+ // Read "last class"
+ if (FAILED(hr = ReadM1ClassStm (pstm, pclsid)))
+ {
+ goto errRtn;
+ }
+ }
+
+ errRtn:
+
+ if (pstm)
+ {
+ pstm->Release();
+ }
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: Read20OleStream, INTERNAL
+//
+// Synopsis: Reads the update options and absolute source class from
+// an OLE 2 object
+//
+// Arguments: pstg -- the IStorage to read from
+// pgenobj -- the genobj we are reading into
+//
+// Returns: NOERROR on success
+//
+// History: dd-mmm-yy Author Comment
+// 06-Mar-94 davepl 32-bit port
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL Read20OleStream(LPSTORAGE pstg, PGENOBJ pgenobj)
+{
+ LPMONIKER pmk = NULL;
+ HRESULT hr = NOERROR;
+ LPSTREAM pstm = NULL;
+ ULONG ul = (ULONG) -1L;
+ CLSID clsidLast;
+
+ if (SUCCEEDED(hr = OpenStream (pstg, OLE_STREAM, &pstm)))
+ {
+ // OLE version
+ if (SUCCEEDED(hr = OLE2StmToUL (pstm, NULL)))
+ {
+ // Object flags
+ if (SUCCEEDED(hr = OLE2StmToUL (pstm, &ul)))
+ {
+ if (ul & OBJFLAGS_LINK)
+ {
+ pgenobj->m_fLink = TRUE;
+ }
+
+ // Update options
+ hr = OLE2StmToUL (pstm, &ul);
+ }
+ }
+ }
+
+ // If no errors so far...
+
+ // If this is a link, get the update options
+
+ if (SUCCEEDED(hr) && pgenobj->m_fLink)
+ {
+ switch (ul)
+ {
+ case OLEUPDATE_ALWAYS:
+ pgenobj->m_lnkupdopt = UPDATE_ALWAYS;
+ break;
+
+ case OLEUPDATE_ONCALL:
+ pgenobj->m_lnkupdopt = UPDATE_ONCALL;
+ break;
+
+ default:
+ AssertSz (0, "Warning: Invalid update options in Storage");
+ hr = ResultFromScode(CONVERT10_E_STG_FMT);
+ }
+ }
+
+ if (SUCCEEDED(hr)) // Only continue if no failures so far
+ {
+ // Reserved (was view format)
+ if (SUCCEEDED(hr = OLE2StmToUL (pstm, NULL)))
+ {
+ if (pgenobj->m_fLink)
+ {
+
+ // All 4 of these calls must succeed or we simply fall
+ // through to the cleanup code
+
+ // ignore relative moniker
+ if (SUCCEEDED(hr = OLE2StmToMoniker (pstm, NULL)) &&
+ // ignore relative source moniker
+ SUCCEEDED(hr = OLE2StmToMoniker (pstm, NULL)) &&
+ // get absolute source moniker
+ SUCCEEDED(hr = OLE2StmToMoniker (pstm, &pmk)) &&
+ // get class from abs moniker
+ SUCCEEDED(hr = ReadM1ClassStm (pstm, &clsidLast)) )
+ {
+ hr = MonikerIntoGenObj (pgenobj, clsidLast, pmk);
+ }
+ }
+ }
+ }
+
+ // Clean up any resources and return status to caller
+
+ if (pstm)
+ {
+ pstm->Release();
+ }
+ if (pmk)
+ {
+ pmk->Release();
+ }
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OLE2StmToMoniker, INTERNAL
+//
+// Synopsis: Calls ReadMonikerStm to get a moniker from a stream,
+// and if the ppmk parameter was NULL, it does a Release()
+// on the moniker object immediately, otherwise sets the
+// caller's pointer to point to the moniker that was read.
+//
+// Arguments: [pstm] -- the stream to read the moniker from
+// [ppmk] -- points to caller's moniker ptr
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleanup and documentation
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL OLE2StmToMoniker(LPSTREAM pstm, LPMONIKER FAR* ppmk)
+{
+ LPMONIKER pmk = NULL;
+ HRESULT hr = NOERROR;
+
+ if (FAILED(hr = ReadMonikerStm (pstm, &pmk)))
+ {
+ return hr;
+ }
+
+ if (ppmk) // If the callers wanted a result, return the
+ { // moniker as an out parameter
+ *ppmk = pmk;
+ }
+ else // Otherwise, release it immediately and
+ { // return to caller
+ if (pmk)
+ {
+ pmk->Release();
+ }
+ }
+
+ return NOERROR;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReadFormat, INTERNAL
+//
+// Synopsis: Reads the format ID type from the stream, and based on that,
+// reads the format ID from the stream.
+//
+// Arguments: [pstm] -- the stream to read from
+// [pformat] -- caller's format member object
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleanup and documentation
+//
+// Notes: The first ULONG indicates the type (standard clipboard,
+// Mac, NULL, or string) of the identifier
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL ReadFormat(LPSTREAM pstm, PFORMAT pformat)
+{
+ ULONG ul;
+ HRESULT hr = NOERROR;
+
+ // Get the format ID type indicator
+
+ if (FAILED(hr = OLE2StmToUL (pstm, &ul)))
+ {
+ return hr;
+ }
+
+ // The first ULONG indicates what kind of format ID will
+ // found in the stream:
+ //
+ // -1 => A standard clipboard format ID
+ // -2 => A Macintosh format
+ // 0 => NULL format
+ // >0 => The number of bytes of the text string
+ // identifier to follow
+
+ switch ((signed long)ul)
+ {
+ case -1L: // Standard clipboard format
+
+ ULONG ulClipFormat;
+ pformat->m_ftag = ftagClipFormat;
+ if (FAILED(hr = OLE2StmToUL (pstm, &ulClipFormat)))
+ {
+ return hr;
+ }
+ pformat->m_cf = (CLIPFORMAT) ulClipFormat;
+ break;
+
+
+ case -2L: // Macintosh format
+
+ return ResultFromScode(CONVERT10_E_STG_FMT);
+
+
+ case 0: // NULL format
+
+ pformat->m_ftag = ftagNone;
+ pformat->m_cf = 0;
+ return NOERROR;
+
+
+ default: // ul == size of string (format name)
+
+
+ pformat->m_ftag = ftagString;
+ if (FAILED(hr = OLE2StmToSizedData
+ (pstm, &(pformat->m_dataFormatString), 0, ul)))
+ {
+ return hr;
+ }
+ break;
+
+ }
+ return NOERROR;
+}
+
+
+#ifdef _OBSOLETE
+
+//+-------------------------------------------------------------------------
+//
+// Function: WriteFormat, INTERNAL
+//
+// Synopsis: Depending on what kind of format (standard cf, string, etc)
+// the format object holds, this fn writes out the appropriate
+// information to the stream
+//
+// Arguments: [pstm] -- the stream to write to
+// [format] -- the format object to get info from
+//
+// Returns: NOERROR on success
+// E_UNEXPECTED for a NULL format tag
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleanup and documentation
+// Notes:
+//--------------------------------------------------------------------------
+
+static INTERNAL WriteFormat(LPSTREAM pstm, const FORMAT FAR& format)
+{
+ HRESULT hr;
+
+ switch (format.m_ftag)
+ {
+ case ftagNone:
+ Assert (0 && "Cant write a NULL format tag");
+ return ResultFromScode (E_UNEXPECTED);
+
+ case ftagClipFormat:
+ if (FAILED(hr = ULToOLE2Stm (pstm, (ULONG) -1L)))
+ {
+ return hr;
+ }
+ if (FAILED(hr = ULToOLE2Stm (pstm, format.m_cf)))
+ {
+ return hr;
+ }
+ break;
+
+ case ftagString:
+ if (FAILED(hr=DataObjToOLE2Stm(pstm,format.m_dataFormatString)))
+ {
+ return hr;
+ }
+ break;
+
+ default:
+ AssertSz (0, "invalid m_ftag value");
+ return ResultFromScode (E_UNEXPECTED);
+ }
+ return NOERROR;
+}
+
+#endif // _OBSOLETE
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ReadDibAsBitmap, INTERNAL
+//
+// Synopsis: Reads a DIB from an OLE 2 stream and stores it as a
+// Bitmap in a DATA structure
+//
+// Arguments: [pstm] -- the OLE 2 stream to read from
+// [pdata] -- the data object to hold the bitmap
+//
+// Returns: NOERROR on success
+// CONVERT10_E_STG_DIB_TO_BITMAP conversion failure
+// E_OUTOFMEMORY allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleanup and documentation
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL ReadDibAsBitmap(LPSTREAM pstm, PDATA pdata)
+{
+ DATA dataDib;
+ ULONG cb;
+ ULONG cbBits;
+ ULONG cbBitsFake;
+ BITMAP bm;
+
+ HBITMAP hBitmap = NULL;
+ HRESULT hr = NOERROR;
+ HGLOBAL hBits = NULL;
+ LPBYTE pBits = NULL;
+
+ Assert (pdata&&pdata->m_cbSize==0&&pdata->m_h==NULL&&pdata->m_pv==NULL);
+
+ // Read the DIB into our local DATA object
+ if (FAILED(hr = OLE2StmToSizedData (pstm, &dataDib)))
+ {
+ return hr;
+ }
+
+ // Convert the DIB to a Bitmap
+ hBitmap = UtConvertDibToBitmap (dataDib.m_h);
+ if (NULL == hBitmap )
+ {
+ return ResultFromScode(CONVERT10_E_STG_DIB_TO_BITMAP);
+ }
+
+ if (0 == GetObject (hBitmap, sizeof(BITMAP), &bm))
+ {
+ return ResultFromScode(CONVERT10_E_STG_DIB_TO_BITMAP);
+ }
+
+ cbBits = (DWORD) bm.bmHeight * (DWORD) bm.bmWidthBytes
+ * (DWORD) bm.bmPlanes;
+
+ // There was a bug in OLE 1.0. It calculated the size of a bitmap
+ // as Height * WidthBytes * Planes * BitsPixel.
+ // So we need to put that many bytes here even if most of the end of that
+ // data block is garbage. Otherwise OLE 1.0 will try to read too many
+ // bytes of the OLESTREAM as bitmap bits.
+
+ cbBitsFake = cbBits * (DWORD) bm.bmBitsPixel;
+
+ // Allocate enough memory for our resultant BITMAP & header
+ hBits = GlobalAlloc (GMEM_MOVEABLE, cbBitsFake + sizeof (BITMAP));
+ if (NULL == hBits)
+ {
+ if (hBitmap)
+ {
+ Verify (DeleteObject (hBitmap));
+ }
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // Get a pointer to the memory
+ pBits = (LPBYTE) GlobalLock (hBits);
+ if (NULL == pBits)
+ {
+ if (hBitmap)
+ {
+ Verify (DeleteObject (hBitmap));
+ }
+ GlobalFree(hBits);
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // Copy the raw bitmap data
+ cb = GetBitmapBits (hBitmap, cbBits, pBits + sizeof(BITMAP));
+ if (cb != cbBits)
+ {
+ if (hBitmap)
+ {
+ Verify (DeleteObject (hBitmap));
+ }
+ GlobalFree(hBits);
+ return ResultFromScode(CONVERT10_E_STG_DIB_TO_BITMAP);
+ }
+
+ // Set the caller's pointer to point to the bitmap
+
+ *((BITMAP FAR*)pBits) = bm;
+
+ pdata->m_h = hBits;
+ pdata->m_pv = pBits;
+ pdata->m_cbSize = cbBitsFake + sizeof(BITMAP);
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: Read20PresStream, INTERNAL
+//
+// Synopsis: Reads presentation data from an IStorage into a
+// generic object
+//
+// Arguments: [pstg] -- the IStorage holding the pres stream
+// [pgenobj] -- the generic object to read to
+// [fObjFmtKnown] -- flag: Do we know the object format?
+//
+// Returns: NOEROR on success
+// E_OUTOFMEMORY on allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 22-Feb-94 davepl Code cleanup and documentation
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL Read20PresStream(
+ LPSTORAGE pstg,
+ PGENOBJ pgenobj,
+ BOOL fObjFmtKnown)
+{
+ HRESULT hr = NOERROR;
+ LPSTREAM pstm = NULL;
+
+ // Find the best presentation stream in this IStorage
+
+ if (FAILED(hr = FindPresStream (pstg, &pstm, fObjFmtKnown)))
+ {
+ return hr;
+ }
+
+ if (pstm)
+ {
+ // Allocate a generic presentation object
+ Assert (NULL==pgenobj->m_ppres);
+ pgenobj->m_ppres = new PRES;
+ if (NULL == pgenobj->m_ppres)
+ {
+ pstm->Release();
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+ }
+ else
+ {
+ // No presentation stream
+ Assert (NULL == pgenobj->m_ppres);
+ return NOERROR;
+ }
+
+ // read the format
+ if (FAILED(hr = ReadFormat (pstm, &(pgenobj->m_ppres->m_format))))
+ {
+ pstm->Release();
+ return hr;
+ }
+
+ // This is the fix for Bug 4020, highly requested by Access
+ if (pgenobj->m_ppres->m_format.m_ftag == ftagNone)
+ {
+ // NULL format
+ delete pgenobj->m_ppres;
+ pgenobj->m_ppres = NULL;
+ Assert (hr == NOERROR);
+ pstm->Release();
+ return hr;
+ }
+
+ // Each of the following calls must succeed in order for the following
+ // one to be executed; if any fails, the if( .. && ..) will be false
+ // and hr will be set to the error that caused the failure
+
+ // target device
+ if (SUCCEEDED(hr = OLE2StmToSizedData (pstm, NULL, 4)) &&
+ // aspect
+ SUCCEEDED(hr = OLE2StmToUL (pstm, NULL)) &&
+ // lIndex
+ SUCCEEDED(hr = OLE2StmToUL (pstm, NULL)) &&
+ // cache flags
+ SUCCEEDED(hr = OLE2StmToUL (pstm, NULL)) &&
+ // compression
+ SUCCEEDED(hr = OLE2StmToUL (pstm, NULL)) &&
+ // width
+ SUCCEEDED(hr = OLE2StmToUL (pstm, &(pgenobj->m_ppres->m_ulWidth))))
+ { // height
+ hr = OLE2StmToUL (pstm, &(pgenobj->m_ppres->m_ulHeight));
+ }
+
+ // We only proceed if everything so far has suceeded
+
+ if (SUCCEEDED(hr))
+ {
+ if (pgenobj->m_ppres->m_format.m_ftag == ftagClipFormat &&
+ pgenobj->m_ppres->m_format.m_cf == CF_DIB &&
+ !pgenobj->m_fStatic)
+ {
+ pgenobj->m_ppres->m_format.m_cf = CF_BITMAP;
+ hr = ReadDibAsBitmap (pstm, &(pgenobj->m_ppres->m_data));
+ }
+ else
+ {
+ // In most cases, we look for a sized block of data in the
+ // stream.
+
+ hr = OLE2StmToSizedData (pstm, &(pgenobj->m_ppres->m_data));
+ }
+ }
+
+ // Free up the stream and return status to caller
+
+ if (pstm)
+ {
+ pstm->Release();
+ }
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OLE2StmToSizedData, INTERNAL
+//
+// Synopsis: Reads a set amount of data from an OLE 2 stream into a
+// DATA structure. If the number of bytes are not known
+// ahead of time, the data length is pulled as the first
+// ULONG at the current stream position.
+//
+// Arguments: [pstm] -- the stream to read from
+// [pdata] -- the DATA structure to read to
+// [cbSizeDelta] -- amount to be subtracted from
+// length; used to read target devices
+// where the length of data includes
+// prefixed length
+// [cbSizeKnown] -- number of bytes to read if known
+// ahead of time
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleanup and documentation
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL OLE2StmToSizedData(
+ LPSTREAM pstm,
+ PDATA pdata,
+ ULONG cbSizeDelta, // default 0
+ ULONG cbSizeKnown) // default 0
+{
+ ULONG cbSize;
+ ULONG cbRead;
+ LARGE_INTEGER large_integer;
+ HRESULT hr = NOERROR;
+
+ // If we don't know the data size ahead of time, read it from the stream;
+ // it will be the first ULONG at the current position
+
+ if (cbSizeKnown)
+ {
+ cbSize = cbSizeKnown;
+ }
+ else
+ {
+ if (FAILED(hr = (OLE2StmToUL (pstm, &cbSize))))
+ {
+ return hr;
+ }
+ }
+
+ cbSize -= cbSizeDelta;
+
+ // If pdata is set, it means we actually do want to read the
+ // data to a buffer, rather than just skip over it (the NULL case)
+
+ if (pdata)
+ {
+ Assert (pdata->m_cbSize==0 && pdata->m_h==NULL && pdata->m_pv==NULL);
+
+ // Set the number of bytes in the DATA structure
+
+ pdata->m_cbSize = cbSize;
+
+ // If there are any, allocate a buffer and read them.
+
+ if (cbSize)
+ {
+ // Allocate memory on the DATA handle
+ pdata->m_h = GlobalAlloc (GMEM_MOVEABLE, cbSize);
+ if (NULL == pdata->m_h)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // Lock memory in for the read
+ pdata->m_pv = GlobalLock (pdata->m_h);
+ if (NULL == pdata->m_pv)
+ {
+ GlobalFree(pdata->m_h);
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // Read the data to the buffer
+ if (FAILED(hr = pstm->Read (pdata->m_pv, cbSize, &cbRead)))
+ {
+ GlobalUnlock(pdata->m_h);
+ GlobalFree(pdata->m_h);
+ return hr;
+ }
+
+ // If we didn't get enough bytes, bail now
+ if (cbRead != cbSize)
+ {
+ GlobalUnlock(pdata->m_h);
+ GlobalFree(pdata->m_h);
+ return ResultFromScode(STG_E_READFAULT);
+ }
+ }
+ else
+ {
+ // We have 0 bytes to read, so mark the
+ // memory handle and ptr as NULL
+ pdata->m_h = NULL;
+ pdata->m_pv = NULL;
+ }
+ }
+ else
+ {
+ // we don't care what the data is, so just skip it
+ LISet32( large_integer, cbSize );
+ if (FAILED(hr = pstm->Seek (large_integer, STREAM_SEEK_CUR, NULL)))
+ {
+ return hr;
+ }
+ }
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: RankOfPres, INTERNAL
+//
+// Synopsis: Returns a ULONG indicating the relative "goodness" of a
+// presentation. The preference is, in descending order:
+//
+// Type Rank
+// ---------- ----------
+// METAFILE x30000
+// DIB x20000
+// none x10000
+//
+// Add x200 for fScreenTargDev being set
+// Add x4 for Content aspect
+// Add x3 for Thumbnail aspect
+// Add x2 for Icon aspect
+// Add x1 for Docprint aspect
+//
+// Eg: Metafile in Content aspect, with ScreenTargDev: 30204
+//
+// The whole point of this is that there may be many
+// presentation streams available in the IStorage. This fn
+// is used to select the best one.
+//
+// Arguments: [format] -- the format tag & type structure
+// [fScreenTargDev]-- do we have a handle to the target dev
+// [dwAspect] -- the aspect type
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleanup and documentation
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL_(ULONG) RankOfPres(
+ const FORMAT FAR& format,
+ const BOOL fScreenTargDev,
+ const DWORD dwAspect)
+{
+ ULONG ul = 0L;
+
+ if (format.m_cf==CF_METAFILEPICT)
+ {
+ ul += 0x030000;
+ }
+ else if (format.m_cf==CF_DIB)
+ {
+ ul += 0x020000;
+ }
+ else if (format.m_ftag != ftagNone)
+ {
+ ul += 0x010000;
+ }
+
+ ul += (fScreenTargDev + 1) * 0x0100;
+
+ switch (dwAspect)
+ {
+ case DVASPECT_CONTENT:
+ ul += 0x04;
+ break;
+
+ case DVASPECT_THUMBNAIL:
+ ul += 0x03;
+ break;
+
+ case DVASPECT_ICON:
+ ul += 0x02;
+ break;
+
+ case DVASPECT_DOCPRINT:
+ ul += 0x01;
+ break;
+ }
+
+ return ul;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsBetter, INTERNAL INLINE
+//
+// Synopsis: Calls RankOfPres to determine if one presentation is
+// better than another
+//
+// Effects:
+//
+// Arguments: [format] -- the format tag and type
+// [fScreenTargDev]-- do we have a handle to target device
+// [dwAspect] -- the aspect of the presentation
+// [formatBest] -- the best format seen so far
+// [fScreenTargDevBest] -- flag for best format seen so far
+// [dwAspectBest] -- the aspect of best format seen so far
+//
+// History: dd-mmm-yy Author Comment
+/// 21-Feb-94 davepl Code cleanup and documentation
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline static INTERNAL_(BOOL) IsBetter(
+ const FORMAT FAR& format,
+ const BOOL fScreenTargDev,
+ const DWORD dwAspect,
+ const FORMAT FAR& formatBest,
+ const BOOL fScreenTargDevBest,
+ const DWORD dwAspectBest)
+{
+ return RankOfPres (format, fScreenTargDev, dwAspect) >
+ RankOfPres (formatBest, fScreenTargDevBest, dwAspectBest);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: FindPresStream, INTERNAL
+//
+// Synopsis: Enumerates over the streams in an IStorage, looking for
+// presentation streams. Selects the best stream among
+// these based on the comparison fn, IsBetter(), which uses
+// for comparison the criteria established in RankOfPres().
+//
+// Arguments: [pstg] -- the IStorage to look in
+// [ppstmBest] -- out param for best pres stream
+// [fObjFmtKnown] is the object format known
+//
+// Returns: NOERROR on success
+// If no presentation is found, it is not an error but
+// *ppstm is set to NULL.
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleanup and documentation
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL FindPresStream(
+ LPSTORAGE pstg,
+ LPSTREAM FAR* ppstmBest,
+ BOOL fObjFmtKnown)
+{
+ HRESULT hr = NOERROR;
+ LPSTREAM pstm = NULL;
+ IEnumSTATSTG FAR* penumStg = NULL;
+ DWORD dwAspectBest = 0;
+ BOOL fTargDevBest = -1;
+ STATSTG statstg;
+ FORMAT formatBest;
+
+ Assert (ppstmBest);
+
+ *ppstmBest = NULL;
+
+ // Set up the enumeration on the available IStreams in the storage
+ if (FAILED(hr = pstg->EnumElements (NULL, NULL, NULL, &penumStg)))
+ {
+ return hr;
+ }
+
+ // Enumerate through them and search for the best among all
+ // presentation streams
+
+ while (penumStg->Next (1, &statstg, NULL) == NOERROR)
+ {
+ // Check to see if this a presentation stream
+
+ if (lstrlenW(statstg.pwcsName) >= 8 &&
+ 0==memcmp(statstg.pwcsName, OLESTR("\2OlePres"), 8*sizeof(WCHAR)))
+ {
+ FORMAT format;
+ DATA dataTargDev;
+ DWORD dwAspect;
+
+ // Open the presentation stream
+ if (FAILED(hr = OpenStream (pstg, statstg.pwcsName, &pstm)))
+ {
+ goto errRtn;
+ }
+
+ // Read the format from the pres stream
+ if (FAILED(hr = ReadFormat (pstm, &format)))
+ {
+ goto errRtn;
+ }
+
+ // Read the target device from the pres stream
+ if (FAILED(hr = OLE2StmToSizedData (pstm, &dataTargDev, 4)))
+ {
+ goto errRtn;
+ }
+
+ // Get the aspect from the pres stream
+ if (FAILED(hr = OLE2StmToUL (pstm, &dwAspect)))
+ {
+ goto errRtn;
+ }
+
+ // Check to see if this presentation stream is better
+ // than the best seen so far
+
+ if (IsBetter (format, dataTargDev.m_h==NULL, dwAspect,
+ formatBest, fTargDevBest, dwAspectBest))
+ {
+ // If it is, we can release the "best"
+ if (*ppstmBest)
+ {
+ (*ppstmBest)->Release();
+ }
+
+ // The king is dead, long live the king
+ *ppstmBest = pstm;
+ pstm->AddRef();
+
+ formatBest = format;
+ fTargDevBest = (dataTargDev.m_h==NULL);
+ dwAspectBest = dwAspect;
+ }
+ pstm->Release();
+ pstm = NULL;
+ }
+ PubMemFree(statstg.pwcsName);
+ statstg.pwcsName = NULL;
+ }
+
+ // On Windows For Workgroups machines, statstg.pwcsName!=NULL when
+ // Next() returns S_FALSE. Bug 3370.
+ statstg.pwcsName = NULL;
+
+ errRtn:
+
+ if (statstg.pwcsName)
+ {
+ PubMemFree(statstg.pwcsName);
+ }
+
+ if (*ppstmBest)
+ {
+ if (dwAspectBest != DVASPECT_CONTENT && fObjFmtKnown)
+ {
+ // then don't use this stream, we will get the presentaion
+ // from the CONTENTS stream
+ (*ppstmBest)->Release();
+ *ppstmBest = NULL;
+ }
+ else
+ {
+ LARGE_INTEGER large_integer;
+ LISet32( large_integer, 0);
+ hr = (*ppstmBest)->Seek(large_integer, STREAM_SEEK_SET,NULL);
+ }
+ }
+
+ if (penumStg)
+ {
+ penumStg->Release();
+ }
+ if (pstm)
+ {
+ pstm->Release();
+ }
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: Reads native data from an OLE 2 stream
+//
+// Synopsis: If the fn can find OLE 1 native data in the stream, it is
+// read out; otherwise, it attempts to create an IStorage
+// in memory on the data in the stream, and then uses the
+// CopyTo interface to extract the data.
+//
+// Arguments: [pstg] -- The OLE 2 IStorage to look in
+// [pdata] -- The DATA object to read native data to
+//
+// Returns: NOERROR on success
+// STG_E_READFAULT on read failure
+// E_OUTOFMEMORY on allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 21-feb-94 davepl Cleaned up and documented code
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL Read20NativeStreams(LPSTORAGE pstg, PDATA pdata)
+{
+ LPSTREAM pstm = NULL;
+ LPLOCKBYTES plkbyt = NULL;
+ LPSTORAGE pstgNative= NULL;
+
+ HRESULT hr = NOERROR;
+
+ // There are two possible codepaths based on the success of
+ // OpenStream. If it is true, it is because we were able to
+ // open the OLE 1 presentation stream in the OLE 2 object.
+ // Thus, it must have been an OLE 1 object "hidden" in
+ // an OLE 2 IStream.
+ //
+ // If that fails, we create an in-memory IStorage based on
+ // the native data and use the CopyTo member to extract the
+ // natice data.
+ //
+ // If we experience a failure at any point, a "break" statement
+ // bails us out past everything to the error cleanup and return
+ // code following the closure of the switch() statement.
+
+ switch ((DWORD)(NOERROR==OpenStream (pstg, OLE10_NATIVE_STREAM, &pstm)))
+ {
+ case TRUE:
+ {
+ // This was a 1.0 object "hidden" inside a 2.0 IStorage
+ ULONG cbRead;
+
+ Assert (pdata->m_cbSize==0 && NULL==pdata->m_h && NULL==pdata->m_pv);
+
+ // read size
+ if (FAILED(hr = pstm->Read(&(pdata->m_cbSize),sizeof(DWORD),&cbRead)))
+ {
+ break;
+ }
+
+ if (sizeof(DWORD) != cbRead)
+ {
+ hr = ResultFromScode (STG_E_READFAULT);
+ break;
+ }
+
+ // allocate memory to store copy of stream
+ pdata->m_h = GlobalAlloc (GMEM_MOVEABLE, pdata->m_cbSize);
+ if (NULL == pdata->m_h)
+ {
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ break;
+ }
+
+ pdata->m_pv = GlobalLock (pdata->m_h);
+ if (NULL == pdata->m_pv)
+ {
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ break;
+ }
+
+ // read stream
+ if (FAILED(hr = pstm->Read(pdata->m_pv,pdata->m_cbSize,&cbRead)))
+ {
+ break;
+ }
+
+ if (pdata->m_cbSize != cbRead)
+ {
+ hr= ResultFromScode (STG_E_READFAULT);
+ break;
+ }
+ break;
+ }
+
+ case FALSE:
+ {
+ const DWORD grfCreateStg = STGM_READWRITE | STGM_SHARE_EXCLUSIVE
+ | STGM_DIRECT | STGM_CREATE ;
+
+ // Copy pstg into pstgNative, thereby removing slack and
+ // giving us access to the bits via an ILockBytes
+ if (FAILED(hr = CreateILockBytesOnHGlobal (NULL, FALSE, &plkbyt)))
+ {
+ break;
+ }
+ if (FAILED(hr = StgCreateDocfileOnILockBytes
+ (plkbyt, grfCreateStg, 0, &pstgNative)))
+ {
+ break;
+ }
+ if (FAILED(hr = pstg->CopyTo (0, NULL, 0, pstgNative)))
+ {
+ break;
+ }
+
+
+ // Set pdata->m_cbSize
+ STATSTG statstg;
+ if (FAILED(hr = plkbyt->Stat (&statstg, 0)))
+ {
+ break;
+ }
+ pdata->m_cbSize = statstg.cbSize.LowPart;
+
+ // Set pdata->m_h
+ if (FAILED(hr = GetHGlobalFromILockBytes (plkbyt, &(pdata->m_h))))
+ {
+ break;
+ }
+ Assert (GlobalSize (pdata->m_h) >= pdata->m_cbSize);
+
+ // Set pdata->m_pv
+ pdata->m_pv = GlobalLock (pdata->m_h);
+ if (NULL == pdata->m_pv)
+ {
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ break;
+ }
+ } // end case
+ } // end switch
+
+ // Cleanup and return status to caller
+ if (pstm)
+ {
+ pstm->Release();
+ }
+ if (plkbyt)
+ {
+ plkbyt->Release();
+ }
+ if (pstgNative)
+ {
+ pstgNative->Release();
+ }
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: PutPresentationObject, INTERNAL
+//
+// Synopsis: Writes a presentation to an OLE 1 stream.
+//
+// Arguments: [pos] -- the OLE 1 stream to write to
+// [ppres] -- the presentation object
+// [cls] -- the class object
+// [fStatic] -- flag: is this a static object
+//
+// Returns: NOERROR on success
+// various possible I/O errors on failure
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleaned up and documented
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL PutPresentationObject(
+ LPOLESTREAM pos,
+ const PRES FAR* ppres,
+ const CLASS FAR& cls,
+ BOOL fStatic) // optional
+{
+ HRESULT hr;
+
+ // Is there a real presentation?
+
+ BOOL fIsPres = FALSE;
+ if (ppres)
+ {
+ if (ppres->m_format.m_ftag != ftagClipFormat ||
+ ppres->m_format.m_cf != 0 )
+ {
+ fIsPres = TRUE;
+ }
+ }
+
+ // write the OLE version to the stream
+ if (FAILED(hr = ULToOLE1Stream (pos, dwVerToFile)))
+ {
+ return hr;
+ }
+
+ // Calc format ID for presentation object, use 0 for no presentation
+
+ ULONG id = 0L;
+
+ if (fIsPres)
+ {
+ if (fStatic)
+ {
+ id = FMTID_STATIC;
+ }
+ else
+ {
+ id = FMTID_PRES;
+ }
+ }
+ if (FAILED(hr = ULToOLE1Stream(pos, id)))
+ {
+ return hr;
+ }
+
+ if (!fIsPres)
+ {
+ // No presentation
+ return NOERROR;
+ }
+
+ if (IsStandardFormat (ppres->m_format))
+ {
+ return PutStandardPresentation (pos, ppres);
+ }
+ else
+ {
+ Assert (!fStatic);
+ return PutGenericPresentation (pos, ppres, cls.m_szClsid);
+ }
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: PutStandardPresentation, INTERNAL
+//
+// Synopsis: Writes a standard presentation (META, DIB, or BITMAP) out
+// to an OLE 1 stream. Creates the METAFILEPICT header
+// as required.
+//
+// Arguments: [pos] -- the OLE 1 stream to write to
+// [ppres] -- the presentation to write
+//
+// Returns: NOERROR on success
+// Various other errors are possible from I/O routines
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Cleaned up and documented
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL PutStandardPresentation(
+ LPOLESTREAM pos,
+ const PRES FAR* ppres)
+{
+ HRESULT hr = NOERROR;
+
+ Assert (ppres->m_format.m_ftag == ftagClipFormat);
+
+ // Write the clipboard format string to the OLE 1 stream
+ // (Will be written in ANSI, not OLESTR format)
+
+ switch (ppres->m_format.m_cf)
+ {
+ case CF_METAFILEPICT:
+ if (FAILED(hr = StringToOLE1Stm (pos, OLESTR("METAFILEPICT"))))
+ {
+ return hr;
+ }
+ break;
+
+ case CF_DIB:
+ if (FAILED(hr = StringToOLE1Stm (pos, OLESTR("DIB"))))
+ {
+ return hr;
+ }
+ break;
+
+ case CF_BITMAP:
+ if (FAILED(hr = StringToOLE1Stm (pos, OLESTR("BITMAP"))))
+ {
+ return hr;
+ }
+ break;
+
+ default:
+ Assert (0 && "Don't know how to write pres format");
+ }
+
+ // Write width
+
+ if (FAILED(hr = ULToOLE1Stream(pos, ppres->m_ulWidth)))
+ {
+ return hr;
+ }
+ // OLE 1.0 file format expects height to be saved as a negative value
+ if (FAILED(hr = ULToOLE1Stream(pos, - ((LONG)ppres->m_ulHeight))))
+ {
+ return hr;
+ }
+
+ // Do special handling for CF_METAFILEPICT
+ if (ppres->m_format.m_cf == CF_METAFILEPICT)
+ {
+ // Need a header to write, crete one here
+
+ WIN16METAFILEPICT mfpict =
+ {
+ MM_ANISOTROPIC,
+ (int)(long) ppres->m_ulWidth,
+ (int)(long) ppres->m_ulHeight,
+ 0
+ };
+
+ // put size ater adjusting it for metafilepict
+
+ if (FAILED(hr = ULToOLE1Stream
+ (pos, (ppres->m_data.m_cbSize + sizeof(WIN16METAFILEPICT)))))
+ {
+ return hr;
+ }
+
+ // put metafilepict
+
+ if (FAILED(hr = DataToOLE1Stm(pos, &mfpict, sizeof(mfpict))))
+ {
+ return hr;
+ }
+
+ // put metafile bits
+
+ // There are two possible means by which we got these metafile
+ // bits: either we have an in-memory metafile, or raw bits
+ // which we read from disk. If it is an in-memory metafile,
+ // the m_pv ptr will have been set to METADATAPTR, and we need
+ // to extract the bits to our own buffer before saving them.
+ // If they came from disk, we can just re-write the buffer
+ // into which we read them.
+
+ if (METADATAPTR == ppres->m_data.m_pv)
+ {
+ BYTE *pb = (BYTE *) PrivMemAlloc(ppres->m_data.m_cbSize);
+ if (NULL == pb)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ if (0 == GetMetaFileBitsEx((HMETAFILE) ppres->m_data.m_h,
+ ppres->m_data.m_cbSize, pb))
+ {
+ PrivMemFree(pb);
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ if (FAILED(hr = DataToOLE1Stm(pos, pb, ppres->m_data.m_cbSize)))
+ {
+ PrivMemFree(pb);
+ return hr;
+ }
+ PrivMemFree(pb);
+ }
+ else // Bits were originally read into our buffer from disk
+ {
+ if (FAILED(hr = DataToOLE1Stm(pos, ppres->m_data.m_pv,
+ ppres->m_data.m_cbSize)))
+ {
+ return hr;
+ }
+ }
+ }
+ else
+ {
+ // Not a METAFILE, just write the data
+
+ if (FAILED(hr = SizedDataToOLE1Stm (pos, ppres->m_data)))
+ {
+ return hr;
+ }
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: PutGenericPresentation, INTERNAL
+//
+// Synopsis: Writes a generic presentation to the stream based on
+// the clipboard format. (Dumps raw pres data to stm)
+//
+// Arguments: [pos] -- the stream to write to
+// [ppres] -- the presentation
+// [szClass] -- class name
+//
+// History: dd-mmm-yy Author Comment
+// 16-Feb-94 davepl 32-bit port'n'doc
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL PutGenericPresentation(
+ LPOLESTREAM pos,
+ const PRES FAR* ppres,
+ LPCOLESTR szClass)
+{
+ Assert (szClass);
+ HRESULT hr = NOERROR;
+
+ // Write the format class name out to the stream
+
+ if (FAILED(hr = StringToOLE1Stm(pos, szClass)))
+ {
+ return hr;
+ }
+
+ // This semi-mythical 0xC000 occurs in
+ // other code I've seen in this project also; if there's
+ // a constant defined, someone ought to fix this
+
+ if (ppres->m_format.m_ftag == ftagClipFormat)
+ {
+ if (ppres->m_format.m_cf < 0xc000)
+ {
+ if (FAILED(hr = ULToOLE1Stream (pos, ppres->m_format.m_cf)))
+ {
+ return hr;
+ }
+ }
+ else
+ {
+ if (FAILED(hr = ULToOLE1Stream (pos, 0L)))
+ {
+ return hr;
+ }
+
+ OLECHAR buf[256];
+
+ if (!GetClipboardFormatName(ppres->m_format.m_cf, buf,
+ sizeof(buf)))
+ {
+ return ResultFromScode(DV_E_CLIPFORMAT);
+ }
+
+ if (FAILED(hr = StringToOLE1Stm (pos, buf)))
+ {
+ return hr;
+ }
+ }
+ }
+ else if (ppres->m_format.m_ftag == ftagString)
+ {
+ // Write the format string to the stream
+
+ if (FAILED(hr = ULToOLE1Stream (pos, 0L)))
+ {
+ return hr;
+ }
+ if (FAILED(hr = SizedDataToOLE1Stm
+ (pos, ppres->m_format.m_dataFormatString)))
+ {
+ return hr;
+ }
+
+ }
+ else
+ {
+ AssertSz (0, "Bad format");
+ }
+
+ Assert (ppres->m_data.m_cbSize && ppres->m_data.m_h);
+
+ // Write the raw presentation data out
+
+ if (FAILED(hr = SizedDataToOLE1Stm (pos, ppres->m_data)))
+ {
+ return hr;
+ }
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wClassesMatchW, INTERNAL INLINE
+//
+// Synopsis: Worker function to compare classes. Special case for
+// handling when the class of the file cannot be determined
+// because it is not a real file; this returns NOERROR
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Cleaned up and documented
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline INTERNAL wClassesMatchW(REFCLSID clsidIn, LPOLESTR szFile)
+{
+ CLSID clsid;
+
+ // If we can get the CLSID for the code that works with this file,
+ // compare it to the CLSID passed in, and return the result of
+ // that comparison
+
+ if (NOERROR==GetClassFile (szFile, &clsid))
+ {
+ if (IsEqualCLSID(clsid, clsidIn))
+ {
+ return NOERROR;
+ }
+ else
+ {
+ return ResultFromScode(S_FALSE);
+ }
+ }
+ else
+ {
+ // If we can't determine the class of the file (because it's
+ // not a real file) then OK.
+ // Bug 3937.
+
+ return NOERROR;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: MonikerIntoGenObj, INTERNAL
+//
+// Synopsis: Merges an OLE 2.0 moniker into a generic object
+//
+// Effects: Sets ths Topic, Item, and class members
+//
+// Arguments: [pgenobj] -- the generic object to receive moniker
+// [clsidLast] -- if a link, what its a link to
+// [pmk] -- the moniker to merge in
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Code cleanup
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL MonikerIntoGenObj(
+ PGENOBJ pgenobj,
+ REFCLSID clsidLast,
+ LPMONIKER pmk )
+{
+ LPOLESTR szFile=NULL;
+ LPOLESTR szItem=NULL;
+ BOOL fClassesMatch = FALSE;
+
+ // If the classes match, that implies this is a link to a pseudo-object
+ // not to an embedded object. If GetClassFile fails because the file
+ // does not exist or is unsaved then we give the link the benefit
+ // of the doubt and let it stay a link. Only if we know the
+ // classes do NOT match do we change the link into an Ole2Link
+ // embedded object.
+
+ // Ole10_PareMoniker returns S_FALSE in the FileMoniker - ItemMoniker - ItemMoniker... case
+ // so check for NOERROR explicitly.
+ if (NOERROR == Ole10_ParseMoniker (pmk, &szFile, &szItem))
+ {
+ SCODE sc = GetScode(wClassesMatchW(clsidLast, szFile));
+ if (sc == S_OK || sc == MK_E_CANTOPENFILE)
+ {
+ pgenobj->m_szTopic = szFile;
+ pgenobj->m_szItem = szItem;
+ fClassesMatch = TRUE;
+ }
+ }
+
+ if (FALSE == fClassesMatch)
+ {
+ // This moniker is either not a File or File::Item moniker,
+ // or is a link to an embedded object, so the only
+ // way we can convert it to OLE 1.0 is to make it an opaque Ole2Link
+
+ pgenobj->m_fLink = FALSE;
+ pgenobj->m_class.Reset (CLSID_StdOleLink);
+ }
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleConvertIStorageToOLESTREAMEx, STDAPI
+//
+// Synopsis: Similar to OleConvertIStorageToOLESTREAM, except that the
+// presentation data that needs to be written into OLESTREAM
+// is passed in. pmedium->tymed can only be TYMED_HGLOBAL
+// or TYMED_ISTREAM and the medium will not be released by the
+// api. cfFormat can be NULL, If it is NULL then the other
+// parameters (lWidth, lHeight, dwSize, pmedium) will be ignored.
+//
+// Arguments: [pstg] -- the storage object to convert from
+// [cfFormat] -- clipboard format
+// [lWidth] -- width
+// [lHeight] -- height
+// [dwSize] -- size in bytes
+// [pmedium] -- serialized bytes
+// [polestm] -- the OLE 1 stream to write to
+//
+// Returns: NOERROR on success
+// DV_E_TYMED invalid clipboard format
+// E_INVALIDARG invalid arg, normally stg or stm
+// DV_E_STGMEDIUM bad medium ptr
+// E_OUTOFMEMORY allocation failure
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Cleaned up and documented
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+STDAPI OleConvertIStorageToOLESTREAMEx
+(
+ LPSTORAGE pstg,
+ CLIPFORMAT cfFormat,
+ LONG lWidth,
+ LONG lHeight,
+ DWORD dwSize,
+ LPSTGMEDIUM pmedium,
+ LPOLESTREAM polestm
+)
+{
+
+ OLETRACEIN((API_OleConvertIStorageToOLESTREAMEx,
+ PARAMFMT("pstg= %p, cfFormat= %x, lWidth= %d, lHeight= %d, dwSize= %ud, pmedium= %ts, polestm= %p"),
+ pstg, cfFormat, lWidth, lHeight, dwSize, pmedium, polestm));
+
+ LEDebugOut((DEB_ITRACE, "%p _IN OleConvertIStorageToOLESTREAMEx ("
+ " %p, %x , %lx , %lx , %x , %p , %p )\n", 0 /*function*/,
+ pstg, cfFormat, lWidth, lHeight, dwSize, pmedium, polestm
+ ));
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pstg);
+
+ HGLOBAL hGlobal = NULL;
+ HRESULT hr = NOERROR;
+ BOOL fFree = FALSE;
+ CGenericObject genobj;
+
+ // If we are given a clipboard format...
+
+ if (cfFormat) {
+
+ VDATEPTRIN_LABEL(pmedium, STGMEDIUM, errRtn, hr);
+
+ // Check that the medium ptr is valid
+ if (pmedium->hGlobal == NULL)
+ {
+ hr = ResultFromScode(DV_E_STGMEDIUM);
+ goto errRtn;
+ }
+
+ // Cannot have a 0 sized clipboard representation
+ if (dwSize == 0)
+ {
+ hr = ResultFromScode(E_INVALIDARG);
+ goto errRtn;
+ }
+
+ switch (pmedium->tymed)
+ {
+ case TYMED_HGLOBAL:
+ hGlobal = pmedium->hGlobal;
+ break;
+
+ case TYMED_ISTREAM:
+ VDATEIFACE_LABEL(pmedium->pstm, errRtn, hr);
+ if ((hr = UtGetHGLOBALFromStm(pmedium->pstm, dwSize,
+ &hGlobal)) != NOERROR)
+ {
+ goto errRtn;
+ }
+ fFree = TRUE;
+ break;
+
+ default:
+ hr = ResultFromScode(DV_E_TYMED);
+ goto errRtn;
+ }
+ }
+
+ if (FAILED(hr = wConvertIStorageToOLESTREAM(pstg, polestm, &genobj)))
+ {
+ goto errRtn;
+ }
+
+ // Clean m_ppres
+ if (genobj.m_ppres)
+ {
+ delete genobj.m_ppres;
+ genobj.m_ppres = NULL;
+ }
+
+ if (cfFormat)
+ {
+ // fill genobj.m_ppres
+
+ PPRES ppres;
+
+ if ((genobj.m_ppres = ppres = new PRES) == NULL)
+ {
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ ppres->m_ulWidth = (ULONG) lWidth;
+ ppres->m_ulHeight = (ULONG) lHeight;
+ ppres->m_data.m_cbSize = dwSize;
+ ppres->m_data.m_fNoFree = !fFree;
+ ppres->m_data.m_h = hGlobal;
+ ppres->m_data.m_pv = GlobalLock(hGlobal);
+ ppres->m_format.m_ftag = ftagClipFormat;
+ ppres->m_format.m_cf = cfFormat;
+
+ }
+ else
+ {
+ genobj.m_fNoBlankPres = TRUE;
+ }
+
+ // REVIEW: We may not want to allow NULL cfFormat with static object
+
+ hr = GenericObjectToOLESTREAM (genobj, polestm);
+
+ LEDebugOut((DEB_ITRACE, "%p OUT OleConvertIStorageToOLESTREAMEx ( %lx ) "
+ "\n", 0 /*function*/, hr));
+
+ OLETRACEOUT((API_OleConvertIStorageToOLESTREAMEx, hr));
+
+ return hr;
+
+errRtn:
+
+ if (fFree && hGlobal != NULL)
+ {
+ GlobalFree(hGlobal);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT OleConvertIStorageToOLESTREAMEx ( %lx ) "
+ "\n", 0 /*function*/, hr));
+
+ OLETRACEOUT((API_OleConvertIStorageToOLESTREAMEx, hr));
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleConvertOLESTREAMToIStorageEx, STDAPI
+//
+// Synopsis: Similar to OleConvertOLESTREAMToIStorage, except that the
+// presentation data that is read from OLESTREAM is passed out.
+// And no presentation stream will written in to the storage.
+// pmedium->tymed can be TYMED_ISTREAM ot TYMED_NULL. If
+// TYMED_NULL, then the bits will be returned in a global
+// handle through pmedium->hGlobal. Otherwise data will be
+// written into pmedium->pstm. NULL will be returned through
+// *pcfFormat, if there is no presentation in the OLESTREAM.
+//
+// Arguments: [pstg] -- the storage object to convert to
+// [cfFormat] -- clipboard format
+// [lWidth] -- width
+// [lHeight] -- height
+// [dwSize] -- size in bytes
+// [pmedium] -- serialized bytes
+// [polestm] -- the OLE 1 stream to write from
+//
+// Returns: DV_E_TYMED invalid clipboard format
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Cleaned up and documented
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+STDAPI OleConvertOLESTREAMToIStorageEx
+(
+ LPOLESTREAM polestm,
+ LPSTORAGE pstg,
+ CLIPFORMAT FAR* pcfFormat,
+ LONG FAR* plWidth,
+ LONG FAR* plHeight,
+ DWORD FAR* pdwSize,
+ LPSTGMEDIUM pmedium
+)
+{
+ OLETRACEIN((API_OleConvertOLESTREAMToIStorageEx,
+ PARAMFMT("polestm= %p, pstg= %p, pcfFormat= %p, plWidth= %p, plHeight= %p, pdwSize= %p, pmedium= %p"),
+ polestm, pstg, pcfFormat, plWidth, plHeight, pdwSize, pmedium));
+
+ LEDebugOut((DEB_ITRACE, "%p _IN OleConvertOLESTREAMToIStorageEx ("
+ " %p , %p , %p , %p , %p , %p , %p )\n", 0 /*function*/,
+ polestm, pstg, pcfFormat,plWidth,plHeight,pdwSize,pmedium
+ ));
+
+ HRESULT hr;
+ PPRES ppres = NULL;
+ GENOBJ genobj;
+
+ VDATEPTROUT_LABEL(pcfFormat, CLIPFORMAT, errRtn, hr);
+ VDATEPTROUT_LABEL(plWidth, LONG, errRtn, hr);
+ VDATEPTROUT_LABEL(plHeight, LONG, errRtn, hr);
+ VDATEPTROUT_LABEL(pdwSize, DWORD, errRtn, hr);
+ VDATEPTROUT_LABEL(pmedium, STGMEDIUM, errRtn, hr);
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pstg);
+
+ if (pmedium->tymed == TYMED_ISTREAM)
+ {
+ VDATEIFACE_LABEL(pmedium->pstm, errRtn, hr);
+ }
+ else if (pmedium->tymed != TYMED_NULL)
+ {
+ hr = ResultFromScode(DV_E_TYMED);
+ goto errRtn;
+ }
+
+ // Bring the object into genobj
+
+ if (FAILED((hr = wConvertOLESTREAMToIStorage(polestm, pstg, &genobj))))
+ {
+ goto errRtn;
+ }
+
+ ppres = genobj.m_ppres;
+ genobj.m_ppres = NULL;
+
+ if (FAILED(hr = GenericObjectToIStorage (genobj, pstg, NULL)))
+ {
+ goto errRtn;
+ }
+
+ // If no presentation is available, clear our all the pres
+ // dimensions and format
+
+ if (ppres == NULL)
+ {
+ *pcfFormat = 0;
+ *plWidth = 0L;
+ *plHeight = 0L;
+ *pdwSize = 0L;
+
+ // Don't worry about the pmedium, it is already in the proper state
+
+ hr = NOERROR;
+ goto errRtn;
+ }
+
+ // If we reach here, we have a presentation, so set the OUT
+ // parameters accordingly
+
+ *plWidth = (LONG) ppres->m_ulWidth;
+ *plHeight = (LONG) ppres->m_ulHeight;
+ *pdwSize = ppres->m_data.m_cbSize;
+
+ Assert(ppres->m_format.m_ftag != ftagNone);
+
+ // If we have a clipboard format ID, return that in the OUT paramter,
+ // otherwise return whatever we get back from an attempt to register
+ // the format string
+
+ if (ppres->m_format.m_ftag == ftagClipFormat)
+ {
+ *pcfFormat = ppres->m_format.m_cf;
+ }
+ else
+ {
+ // m_dataFormatString is an ASCII string.
+ *pcfFormat = SSRegisterClipboardFormatA( (LPCSTR) ppres->m_format.m_dataFormatString.m_pv);
+ Assert(0 != *pcfFormat);
+ }
+
+ if (pmedium->tymed == TYMED_NULL)
+ {
+ if (ppres->m_data.m_h)
+ {
+ Assert(ppres->m_data.m_pv != NULL);
+ GlobalUnlock(ppres->m_data.m_h);
+ }
+
+ // transfer the ownership
+ pmedium->tymed = TYMED_HGLOBAL;
+ pmedium->hGlobal = ppres->m_data.m_h;
+
+ // Null out the handle and pointer so that destructor of PRES will not
+ // free it.
+ ppres->m_data.m_h = NULL;
+ ppres->m_data.m_pv = NULL;
+
+ }
+ else
+ {
+ hr = pmedium->pstm->Write(ppres->m_data.m_pv, *pdwSize, NULL);
+ }
+
+errRtn:
+
+ if (ppres)
+ {
+ delete ppres;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT OleConvertOLESTREAMToIStorageEx ( %lx ) "
+ "\n", 0 /*function*/, hr));
+
+ OLETRACEOUT((API_OleConvertOLESTREAMToIStorageEx, hr));
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: wWriteFmtUserType, INTERNAL
+//
+// Synopsis: Gets the user type for a class ID and writes it to
+// an IStorage
+//
+//
+// Arguments: [pstg] -- the storage to write to
+// [clsid] -- the class ID
+//
+//
+// Returns: NOERROR on success
+//
+// History: dd-mmm-yy Author Comment
+// 21-Feb-94 davepl Cleaned up and documented
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+FARINTERNAL wWriteFmtUserType(LPSTORAGE pstg, REFCLSID clsid)
+{
+ HRESULT hr = NOERROR;
+ LPOLESTR szProgID = NULL;
+ LPOLESTR szUserType = NULL;
+
+ // Get the program ID
+ if (FAILED(hr = ProgIDFromCLSID (clsid, &szProgID)))
+ {
+ goto errRtn;
+ }
+
+ // Get the user type
+ if (FAILED(hr = OleRegGetUserType(clsid,USERCLASSTYPE_FULL,&szUserType)))
+ {
+ goto errRtn;
+ }
+
+ // Write the user type out to the storage
+ if (FAILED(hr = WriteFmtUserTypeStg
+ (pstg, RegisterClipboardFormat (szProgID), szUserType)))
+ {
+ goto errRtn;
+ }
+
+ // Clean up and return status
+
+ errRtn:
+
+ if (szProgID)
+ {
+ PubMemFree(szProgID);
+ }
+ if (szUserType)
+ {
+ PubMemFree(szUserType);
+ }
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wCLSIDFromProgID
+//
+// Synopsis: Looks for the key HKEY_CLASSES_ROOT\{ProgID}\Clsid\ to get
+// the string version of the class ID, then returns the CLSID
+// value of whatever it found.
+//
+// History: dd-mmm-yy Author Comment
+// 25-Jun-94 alexgo fixed Ole1 CLSID creation
+// 15-Apr-94 davepl Rewrite
+//
+// Notes: Used to be in clipboard code, but used in this file
+//
+//--------------------------------------------------------------------------
+
+INTERNAL wCLSIDFromProgID(LPOLESTR szProgID, LPCLSID pclsid, BOOL fForceAssign)
+{
+ VDATEHEAP();
+
+ // Apparently some optimization. If the class name is "OLE2Link", we can
+ // return CLSID_StdOleLInk without even bothering to check the registry.
+
+ if (0 == _xstrcmp(szProgID, OLESTR("OLE2Link")))
+ {
+ *pclsid = CLSID_StdOleLink;
+ return NOERROR;
+ }
+ else
+ {
+ // this function will look for a CLSID under the ProgID entry in
+ // the registry or manufacture one if none present.
+
+ return CLSIDFromOle1Class(szProgID, pclsid, fForceAssign);
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wProgIDFromCLSID
+//
+// Synopsis: A wrapper for ProgIDFromCLSID. The only change in
+// functionality is to check and see if this is a
+// CLSID_StdOleLink, and if so, return a prog ID of
+// "OLE2Link" rather than failing.
+//
+//
+// History: dd-mmm-yy Author Comment
+// 15-Feb-94 davepl Rewrite
+//
+//--------------------------------------------------------------------------
+
+FARINTERNAL wProgIDFromCLSID(REFCLSID clsid, LPOLESTR FAR* psz)
+{
+ VDATEHEAP();
+
+ HRESULT hresult;
+
+ // If we can get the ProgID by conventional methods, great, just
+ // return it.
+
+ if (NOERROR == (hresult = ProgIDFromCLSID(clsid, psz)))
+ {
+ return hresult;
+ }
+
+ // If we failed, it might be because this is a standard OLE link, which
+ // will not have a ProgID entry in the registry, so we fake it out by
+ // returning the ProgID manually.
+
+ if (IsEqualCLSID(clsid, CLSID_StdOleLink))
+ {
+ *psz = UtDupString(OLESTR("OLE2Link"));
+ return(NOERROR);
+ }
+
+ // Must not have been able to resolve for ProgID, so return the error.
+ return(hresult);
+}
+
+
+#if 0
+
+
+// We don't need these conversion fns yet, but we likely will soon.
+
+inline INTERNAL_(VOID) ConvertBM32to16(LPBITMAP lpsrc, LPWIN16BITMAP lpdest)
+{
+ lpdest->bmType = (short)lpsrc->bmType;
+ lpdest->bmWidth = (short)lpsrc->bmWidth;
+ lpdest->bmHeight = (short)lpsrc->bmHeight;
+ lpdest->bmWidthBytes = (short)lpsrc->bmWidthBytes;
+ lpdest->bmPlanes = (BYTE)lpsrc->bmPlanes;
+ lpdest->bmBitsPixel = (BYTE)lpsrc->bmBitsPixel;
+}
+
+inline INTERNAL_(VOID) ConvertBM16to32(LPWIN16BITMAP lpsrc, LPBITMAP lpdest)
+{
+ lpdest->bmType = MAKELONG(lpsrc->bmType,NULL_WORD);
+ lpdest->bmWidth = MAKELONG(lpsrc->bmWidth,NULL_WORD);
+ lpdest->bmHeight = MAKELONG(lpsrc->bmHeight,NULL_WORD);
+ lpdest->bmWidthBytes = MAKELONG(lpsrc->bmWidthBytes,NULL_WORD);
+ lpdest->bmPlanes = (WORD)lpsrc->bmPlanes;
+ lpdest->bmBitsPixel = (WORD)lpsrc->bmBitsPixel;
+}
+
+inline INTERNAL_(VOID) ConvertMF16to32(
+ LPWIN16METAFILEPICT lpsrc,
+ LPMETAFILEPICT lpdest )
+{
+ lpdest->mm = (DWORD)lpsrc->mm;
+ lpdest->xExt = (DWORD)MAKELONG(lpsrc->xExt,NULL_WORD);
+ lpdest->yExt = (DWORD)MAKELONG(lpsrc->yExt,NULL_WORD);
+}
+
+inline INTERNAL_(VOID) ConvertMF32to16(
+ LPMETAFILEPICT lpsrc,
+ LPWIN16METAFILEPICT lpdest )
+{
+ lpdest->mm = (short)lpsrc->mm;
+ lpdest->xExt = (short)lpsrc->xExt;
+ lpdest->yExt = (short)lpsrc->yExt;
+}
+
+#endif
diff --git a/private/ole32/ole232/precomp2.inc b/private/ole32/ole232/precomp2.inc
new file mode 100644
index 000000000..89d95e297
--- /dev/null
+++ b/private/ole32/ole232/precomp2.inc
@@ -0,0 +1,21 @@
+#//+---------------------------------------------------------------
+#//
+#// File: precom2.inc
+#//
+#// Contents: directives for global precompiled include file when the
+#// sources file is two directories below ole232 (or wherever
+#// this file is located. We could easily have precomp3 and
+#// precomp4 for other areas. The ole2int.obj\* files should not
+#// otherwise be mentioned in the sources files.
+#//
+#// History: 18-May-94 CraigWi Created
+#// 23-May-94 BillMo Cairo fixed.
+#//----------------------------------------------------------------
+
+PRECOMPILED_CXX=1
+PRECOMPILED_INCLUDE=..\..\inc\le2int.h
+PRECOMPILED_TARGET=..\..\inc\$(GPCH_BUILD)\obj\*\le2int.pch
+PRECOMPILED_OPTION=/Yule2int.h /Fp..\..\inc\$(GPCH_BUILD)\obj\*\le2int.pch
+PRECOMPILED_OBJ=..\..\inc\$(GPCH_BUILD)\obj\*\le2int.obj
+
+
diff --git a/private/ole32/ole232/stdimpl/clthndlr.cpp b/private/ole32/ole232/stdimpl/clthndlr.cpp
new file mode 100644
index 000000000..0a1847897
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/clthndlr.cpp
@@ -0,0 +1,1157 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: clnthndlr.cpp
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 10-10-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+
+#include <le2int.h>
+
+#ifdef SERVER_HANDLER
+
+#include "handler.hxx"
+
+ASSERTDATA
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateClientSiteHandler
+//
+// Synopsis:
+//
+// Arguments: [pOCS] --
+// [ppClntHdlr] --
+//
+// Returns:
+//
+// History: 11-10-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CreateClientSiteHandler(IOleClientSite *pOCS, CClientSiteHandler **ppClntHdlr)
+{
+ HdlDebugOut((DEB_SERVERHANDLER, "IN CreateClientSiteHandler(pOCS:%p)\n",pOCS));
+ HRESULT hres = NOERROR;
+
+ *ppClntHdlr = new CClientSiteHandler(pOCS);
+
+ if (*ppClntHdlr == NULL)
+ {
+ hres = E_OUTOFMEMORY;
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER, "OUT CreateClientSiteHandler(ppSrvHdlr:%p) return %lx\n",*ppClntHdlr,hres));
+ return hres;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::CClientSiteHandler
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: 9-22-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CClientSiteHandler::CClientSiteHandler(IOleClientSite *pOCS)
+{
+ _cRefs = 1;
+ _pOCont = NULL;
+ _pOIPS = NULL;
+ _pOCSActive = NULL;
+
+ _pOCS = pOCS;
+ if (_pOCS)
+ {
+ _pOCS->AddRef();
+ }
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::~CClientSiteHandler
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: 9-22-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CClientSiteHandler::~CClientSiteHandler()
+{
+ HdlAssert((_pOCont == NULL));
+ HdlAssert((_pOIPS == NULL));
+ HdlAssert((_pOCSActive == NULL));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::GetClientSiteDelegate
+//
+// Synopsis: returns the delegate for the IOleClientSite
+//
+// Arguments: [dwID] -- normal OleClientSite or
+// active OleClientSite (passed on DoVerb)
+//
+// Returns:
+//
+// History: 11-20-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+inline IOleClientSite *CClientSiteHandler::GetClientSiteDelegate(DWORD dwID)
+{
+ HdlAssert(( dwID > 0 && dwID <= ID_ClientSiteActive));
+ return (dwID == ID_ClientSite) ? _pOCS : _pOCSActive;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::GetPUnkClientSiteDelegate
+//
+// Synopsis: returns a delegate PUnk of all possible delegates
+//
+// Arguments: [dwID] -- id of delegate
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+IUnknown *CClientSiteHandler::GetPUnkClientSiteDelegate(DWORD dwID)
+{
+ HdlAssert(( dwID > 0 && dwID <= ID_Container));
+ switch (dwID)
+ {
+ case ID_ClientSite:
+ return _pOCS;
+ case ID_ClientSiteActive:
+ return _pOCSActive;
+ case ID_InPlaceSite:
+ return _pOIPS;
+ case ID_Container:
+ return _pOCont;
+ default:
+ HdlAssert((FALSE && "Invalid ID for delegate"));
+ }
+ return NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::SetClientSiteDelegate
+//
+// Synopsis:
+//
+// Arguments: [dwId] --
+// [pUnk] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void CClientSiteHandler::SetClientSiteDelegate(DWORD dwId, IUnknown *pUnk)
+{
+ HdlDebugOut((DEB_CLIENTHANDLER_UNKNOWN, "%p _IN CClientSiteHandler::SetClientSiteDelegate\n", this));
+ HdlAssert(( dwId > 0 && dwId <= ID_Container));
+
+ if (( dwId > 0 && dwId <= ID_Container))
+ {
+ IUnknown *pUnkOld = GetPUnkClientSiteDelegate(dwId);
+ if (pUnk)
+ {
+ pUnk->AddRef();
+ }
+ if (pUnkOld)
+ {
+ pUnkOld->Release();
+ }
+ }
+
+ switch (dwId)
+ {
+ case ID_ClientSite:
+ _pOCS = (IOleClientSite *) pUnk;
+ break;
+ case ID_ClientSiteActive:
+ _pOCSActive = (IOleClientSite *) pUnk;
+ break;
+ case ID_InPlaceSite:
+ _pOIPS = (IOleInPlaceSite *) pUnk;
+ break;
+ case ID_Container:
+ _pOCont = (IOleContainer *) pUnk;
+ break;
+ default:
+ HdlAssert((FALSE && "Invalid ID for delegate"));
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::QueryInterface
+//
+// Synopsis:
+//
+// Arguments: [riid] --
+// [ppv] --
+//
+// Returns:
+//
+// History: 8-18-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::QueryInterface( REFIID riid, void **ppv )
+{
+ HRESULT hresult = NOERROR;
+ VDATEHEAP();
+
+ HdlDebugOut((DEB_CLIENTHANDLER_UNKNOWN, "%p _IN CClientSiteHandler::QueryInterface (%lx, %p)\n", this, riid, ppv));
+
+ if ( IsEqualIID(riid, IID_IUnknown)
+ || IsEqualIID(riid, IID_IClientSiteHandler) )
+ {
+ *ppv = (void FAR *)(IClientSiteHandler *)this;
+ InterlockedIncrement((long *)&_cRefs);
+ }
+ else
+ {
+ *ppv = NULL;
+ hresult = E_NOINTERFACE;
+ }
+
+ HdlDebugOut((DEB_CLIENTHANDLER_UNKNOWN, "%p OUT CClientSiteHandler::QueryInterface (%lx)[%p]\n", this, hresult, *ppv));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::AddRef
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 8-18-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CClientSiteHandler::AddRef( void )
+{
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER_UNKNOWN, "%p _IN CClientSiteHandler::AddRef\n", this));
+
+ InterlockedIncrement((long *)&_cRefs);
+
+ HdlDebugOut((DEB_CLIENTHANDLER_UNKNOWN, "%p OUT CClientSiteHandler::AddRef (%ld)\n", this, _cRefs));
+ return _cRefs;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::Release
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 8-18-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CClientSiteHandler::Release( void )
+{
+ ULONG cRefs = 0;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER_UNKNOWN, "%p _IN CClientSiteHandler::Release\n", this));
+
+ InterlockedDecrement((long *)&_cRefs);
+ cRefs = _cRefs;
+ if (_cRefs == 0)
+ {
+ if (_pOCS)
+ {
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::Release OleClientSite\n", _pOCS));
+ _pOCS->Release();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::Release OleClientSite\n", _pOCS));
+ }
+ if (_pOCSActive)
+ {
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::Release OleClientSiteActive\n", _pOCSActive));
+ // release the active OleClientSite
+ _pOCSActive->Release();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::Release OleClientSiteActive\n", _pOCSActive));
+ }
+
+ if (_pOCont)
+ {
+ _pOCont->Release();
+ }
+
+ if (_pOIPS)
+ {
+ _pOIPS->Release();
+ }
+
+ delete this;
+ }
+
+ HdlDebugOut((DEB_CLIENTHANDLER_UNKNOWN, "%p OUT CClientSiteHandler::Release (%ld)\n", this, cRefs));
+ return cRefs;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::PrivQueryInterface
+//
+// Synopsis:
+//
+// Arguments: [dwId] --
+// [riidResult] --
+// [ppvResult] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::PrivQueryInterface(
+ /* [in] */ DWORD dwId,
+ /* [in] */ REFIID riidResult,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvResult)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::PrivQueryInterface (dwId:%ld)\n", this,dwId));
+ HdlAssert((GetPUnkClientSiteDelegate(dwId) != NULL && "ClientSiteHandler invalid OleClientSite pointer!"));
+
+ hresult = GetPUnkClientSiteDelegate(dwId)->QueryInterface(riidResult, ppvResult);
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::PrivQueryInterface hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::PrivAddRef
+//
+// Synopsis:
+//
+// Arguments: [dwId] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::PrivAddRef(
+ /* [in] */ DWORD dwId)
+{
+ HRESULT hresult = NOERROR;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::PrivAddRef (dwId:%ld)\n", this,dwId));
+
+ GetPUnkClientSiteDelegate(dwId)->AddRef();
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::PrivAddRef hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::PrivRelease
+//
+// Synopsis: called by the serverhandler; releases a delegate object of clientsitehandler
+//
+// Arguments: [dwId] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::PrivRelease(
+ /* [in] */ DWORD dwId)
+{
+ HRESULT hresult = NOERROR;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::PrivRelease (dwId:%ld)\n", this,dwId));
+
+ // Release the object - the connection will remain
+ HdlAssert((dwId > ID_NONE && dwId <= ID_Container));
+
+ SetClientSiteDelegate(dwId, NULL);
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::PrivRelease hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::GetContainer
+//
+// Synopsis: delegates call on to appropriate OleClientSite
+//
+// Arguments: [dwId] -- id of the OleClientSite the call should be delegate too
+// [ppContainer] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::GetContainer(DWORD dwId, IOleContainer * *ppContainer)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::GetContainer\n", this));
+
+ HdlAssert((GetClientSiteDelegate(dwId) != NULL && "ClientSiteHandler invalid OleClientSite pointer!"));
+ hresult = GetClientSiteDelegate(dwId)->GetContainer(ppContainer);
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::GetContainer hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::OnShowWindow
+//
+// Synopsis: delegates call on to appropriate OleClientSite
+//
+// Arguments: [dwId] -- id of the OleClientSite the call should be delegate too
+// [fShow] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::OnShowWindow(DWORD dwId, BOOL fShow)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::OnShowWindow\n", this));
+
+ HdlAssert((GetClientSiteDelegate(dwId) != NULL && "ClientSiteHandler invalid OleClientSite pointer!"));
+ hresult = GetClientSiteDelegate(dwId)->OnShowWindow(fShow);
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::OnShowWindow hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::RequestNewObjectLayout
+//
+// Synopsis: delegates call on to appropriate OleClientSite
+//
+// Arguments: [dwId] -- id of the OleClientSite the call should be delegate too
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::RequestNewObjectLayout(DWORD dwId)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::RequestNewObjectLayout\n", this));
+
+ HdlAssert((GetClientSiteDelegate(dwId) != NULL && "ClientSiteHandler invalid OleClientSite pointer!"));
+ hresult = GetClientSiteDelegate(dwId)->RequestNewObjectLayout();
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::RequestNewObjectLayout hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::GetMoniker
+//
+// Synopsis: delegates call on to appropriate OleClientSite
+//
+// Arguments: [dwId] -- id of the OleClientSite the call should be delegate too
+// [DWORD] --
+// [IMoniker] --
+// [ppmk] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::GetMoniker(DWORD dwId, DWORD dwAssign,DWORD dwWhichMoniker,IMoniker * *ppmk)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::GetMoniker\n", this));
+
+ HdlAssert((GetClientSiteDelegate(dwId) != NULL && "ClientSiteHandler invalid OleClientSite pointer!"));
+ hresult = GetClientSiteDelegate(dwId)->GetMoniker(dwAssign, dwWhichMoniker,ppmk);
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::GetMoniker hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::SaveObject
+//
+// Synopsis: delegates call on to appropriate OleClientSite
+//
+// Arguments: [dwId] -- id of the OleClientSite the call should be delegate too
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::SaveObject(DWORD dwId )
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::SaveObject\n", this));
+
+ HdlAssert((GetClientSiteDelegate(dwId) != NULL && "ClientSiteHandler invalid OleClientSite pointer!"));
+ hresult = GetClientSiteDelegate(dwId)->SaveObject();
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::SaveObject hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::ShowObject
+//
+// Synopsis: delegates call on to appropriate OleClientSite
+//
+// Arguments: [dwId] -- id of the OleClientSite the call should be delegate too
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::ShowObject(DWORD dwId)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::ShowObject\n", this));
+
+ HdlAssert((GetClientSiteDelegate(dwId) != NULL && "ClientSiteHandler invalid OleClientSite pointer!"));
+ hresult = GetClientSiteDelegate(dwId)->ShowObject();
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::ShowObject hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+
+//
+// IOleInPlaceSite methods
+//
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::GetWindow
+//
+// Synopsis: delegates call on to OleInPlaceSite
+//
+// Arguments: [phwnd] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::GetWindow( HWND *phwnd)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::GetWindow\n", this));
+
+ HdlAssert((_pOIPS != NULL && "ClientSiteHandler invalid OleInPlaceSite pointer!"));
+ hresult = _pOIPS->GetWindow(phwnd);
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::GetWindow hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::ContextSensitiveHelp
+//
+// Synopsis: delegates call on to OleInPlaceSite
+//
+// Arguments: [fEnterMode] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::ContextSensitiveHelp(BOOL fEnterMode)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::ContextSensitiveHelp\n", this));
+
+ HdlAssert((_pOIPS != NULL && "ClientSiteHandler invalid OleInPlaceSite pointer!"));
+ hresult = _pOIPS->ContextSensitiveHelp(fEnterMode);
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::ContextSensitiveHelp hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::CanInPlaceActivate
+//
+// Synopsis: delegates call on to OleInPlaceSite
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::CanInPlaceActivate( void)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::CanInPlaceActivate\n", this));
+
+ HdlAssert((_pOIPS != NULL && "ClientSiteHandler invalid OleInPlaceSite pointer!"));
+ hresult = _pOIPS->CanInPlaceActivate();
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::CanInPlaceActivate hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::OnInPlaceActivate
+//
+// Synopsis: delegates call on to OleInPlaceSite
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::OnInPlaceActivate( void)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::OnInPlaceActivate\n", this));
+
+ HdlAssert((_pOIPS != NULL && "ClientSiteHandler invalid OleInPlaceSite pointer!"));
+ hresult = _pOIPS->OnInPlaceActivate();
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::OnInPlaceActivate hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::OnUIActivate
+//
+// Synopsis: delegates call on to OleInPlaceSite
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::OnUIActivate( void)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::OnUIActivate\n", this));
+
+ HdlAssert((_pOIPS != NULL && "ClientSiteHandler invalid OleInPlaceSite pointer!"));
+ hresult = _pOIPS->OnUIActivate();
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::OnUIActivate hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::GetWindowContext
+//
+// Synopsis: delegates call on to OleInPlaceSite
+//
+// Arguments: [ppFrame] --
+// [ppDoc] --
+// [lprcPosRect] --
+// [lprcClipRect] --
+// [lpFrameInfo] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::GetWindowContext(
+ /* [out] */ IOleInPlaceFrame * *ppFrame,
+ /* [out] */ IOleInPlaceUIWindow * *ppDoc,
+ /* [out] */ LPRECT lprcPosRect,
+ /* [out] */ LPRECT lprcClipRect,
+ /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::GetWindowContext\n", this));
+
+ HdlAssert((_pOIPS != NULL && "ClientSiteHandler invalid OleInPlaceSite pointer!"));
+ hresult = _pOIPS->GetWindowContext(ppFrame, ppDoc, lprcPosRect, lprcClipRect, lpFrameInfo);
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::GetWindowContext hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::Scroll
+//
+// Synopsis: delegates call on to OleInPlaceSite
+//
+// Arguments: [scrollExtant] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::Scroll(
+ /* [in] */ SIZE scrollExtant)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::Scroll\n", this));
+
+ HdlAssert((_pOIPS != NULL && "ClientSiteHandler invalid OleInPlaceSite pointer!"));
+ hresult = _pOIPS->Scroll(scrollExtant);
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::Scroll hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::OnUIDeactivate
+//
+// Synopsis: delegates call on to OleInPlaceSite
+//
+// Arguments: [fUndoable] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::OnUIDeactivate(
+ /* [in] */ BOOL fUndoable)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::OnUIDeactivate\n", this));
+
+ HdlAssert((_pOIPS != NULL && "ClientSiteHandler invalid OleInPlaceSite pointer!"));
+ hresult = _pOIPS->OnUIDeactivate(fUndoable);
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::OnUIDeactivate hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::OnInPlaceDeactivate
+//
+// Synopsis: delegates call on to OleInPlaceSite
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::OnInPlaceDeactivate( void)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::OnInPlaceDeactivate\n", this));
+
+ HdlAssert((_pOIPS != NULL && "ClientSiteHandler invalid OleInPlaceSite pointer!"));
+ hresult = _pOIPS->OnInPlaceDeactivate();
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::OnInPlaceDeactivate hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::DiscardUndoState
+//
+// Synopsis: delegates call on to OleInPlaceSite
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::DiscardUndoState( void)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::DiscardUndoState\n", this));
+
+ HdlAssert((_pOIPS != NULL && "ClientSiteHandler invalid OleInPlaceSite pointer!"));
+ hresult = _pOIPS->DiscardUndoState();
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::DiscardUndoState hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::DeactivateAndUndo
+//
+// Synopsis: delegates call on to OleInPlaceSite
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::DeactivateAndUndo( void)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::DeactivateAndUndo\n", this));
+
+ HdlAssert((_pOIPS != NULL && "ClientSiteHandler invalid OleInPlaceSite pointer!"));
+ hresult = _pOIPS->DeactivateAndUndo();
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::DeactivateAndUndo hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::OnPosRectChange
+//
+// Synopsis: delegates call on to OleInPlaceSite
+//
+// Arguments: [lprcPosRect] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::OnPosRectChange(
+ /* [in] */ LPCRECT lprcPosRect)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::OnPosRectChange\n", this));
+
+ HdlAssert((_pOIPS != NULL && "ClientSiteHandler invalid OleInPlaceSite pointer!"));
+ hresult = _pOIPS->OnPosRectChange(lprcPosRect);
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::OnPosRectChange hr=%lx\n", this, hresult));
+ return hresult;
+}
+
+//
+// ClientSiteHandler methods
+//
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::GoInPlaceActivate
+//
+// Synopsis: called by the serverhandler when going inplace
+//
+// Arguments: [pInSrvInPlace] --
+// [ppOutSrvInPlace] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::GoInPlaceActivate(
+ /* [in] */ INSRVINPLACE *pInSrvInPlace,
+ /* [out] */ OUTSRVINPLACE * *ppOutSrvInPlace)
+{
+ HRESULT hresult = NOERROR;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::GoInPlaceActivate\n", this));
+ HdlAssert((_pOIPS != NULL && "OleInPlaceSite invalid"));
+
+ DWORD dwId = pInSrvInPlace->dwDelegateID;
+
+ COutSrvInPlace *pOutSrvInPlace;
+
+
+ if ( (pOutSrvInPlace = new COutSrvInPlace) == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ // 1. OnInPlaceActivate
+ if (pInSrvInPlace->dwOperation & OP_OnInPlaceActivate)
+ {
+ hresult = _pOIPS->OnInPlaceActivate();
+ if (SUCCEEDED(hresult))
+ {
+ pOutSrvInPlace->dwOperation |= OP_OnInPlaceActivate;
+ }
+ else
+ {
+ HdlDebugOut((DEB_WARN,"OnInPlaceActivate failed hr:%x\n", hresult));
+ }
+ }
+
+ // 2. Get the window
+ if (pInSrvInPlace->dwOperation & OP_GetWindow)
+ {
+ HWND hwnd;
+
+ hresult =_pOIPS->GetWindow(&hwnd);
+ if (SUCCEEDED(hresult))
+ {
+ pOutSrvInPlace->hwnd = hwnd;
+ pOutSrvInPlace->dwOperation |= OP_GetWindow;
+ }
+ else
+ {
+ HdlDebugOut((DEB_WARN,"GetWindow failed hr:%x\n", hresult));
+ }
+ }
+
+ // 2. Get the window context
+ if (pInSrvInPlace->dwOperation & OP_GetWindowContext)
+ {
+ IOleInPlaceFrame *pFrame = 0;
+ IOleInPlaceUIWindow *pDoc = 0;
+
+ // BUGBUG: check for allocation failures or move these parameters
+ // into pOutSrvInPlace structure.
+
+ LPRECT lprcPosRect = (LPRECT) PubMemAlloc(sizeof(RECT));
+ LPRECT lprcClipRect = (LPRECT) PubMemAlloc(sizeof(RECT));
+ LPOLEINPLACEFRAMEINFO lpFrameInfo =
+ (LPOLEINPLACEFRAMEINFO) PubMemAlloc(sizeof(OLEINPLACEFRAMEINFO));
+
+ lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
+
+ hresult = _pOIPS->GetWindowContext(&pFrame, &pDoc, lprcPosRect, lprcClipRect, lpFrameInfo);
+ if (SUCCEEDED(hresult))
+ {
+ pOutSrvInPlace->dwOperation |= OP_GetWindowContext;
+ pOutSrvInPlace->pOIPFrame = pFrame;
+ pOutSrvInPlace->pOIPUIWnd = pDoc;
+ pOutSrvInPlace->lprcPosRect = lprcPosRect;
+ pOutSrvInPlace->lprcClipRect = lprcClipRect;
+ pOutSrvInPlace->lpFrameInfo = lpFrameInfo;
+ }
+ else
+ {
+ HdlDebugOut((DEB_WARN,"GetWindowContext failed hr:%x\n", hresult));
+ PubMemFree(lprcPosRect);
+ PubMemFree(lprcClipRect);
+ PubMemFree(lpFrameInfo);
+ }
+ }
+
+ // 3. OleClientSite::ShowObject
+ if (pInSrvInPlace->dwOperation & OP_OnShowWindow)
+ {
+ hresult = GetClientSiteDelegate(dwId)->ShowObject();
+ if (SUCCEEDED(hresult))
+ {
+ pOutSrvInPlace->dwOperation |= OP_OnShowWindow;
+ }
+ else
+ {
+ HdlDebugOut((DEB_WARN,"GetClientSiteDelegate failed hr:%x\n", hresult));
+ }
+ }
+
+ // 4. OleInPlaceFrame::InsertMenus
+
+ *ppOutSrvInPlace = pOutSrvInPlace;
+
+ pOutSrvInPlace->Dump();
+
+errRtn:
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::GoInPlaceActivate\n", this));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::GoInPlace
+//
+// Synopsis:
+//
+// Arguments: [pInSrvInPlace] --
+// [pOutSrvInPlace] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes: Not implemented yet.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::GoInPlace(
+ /* [in] */ INSRVINPLACE *pInSrvInPlace,
+ /* [out] */ OUTSRVINPLACE * *pOutSrvInPlace)
+{
+ HRESULT hresult = NOERROR;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::GoInPlace\n", this));
+
+ //
+ // This method is not implemented yet!
+ //
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::GoInPlace\n", this));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CClientSiteHandler::UndoPlace
+//
+// Synopsis:
+//
+// Arguments: [pInSrvInPlace] --
+// [pOutSrvInPlace] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes: Not implemented yet.
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CClientSiteHandler::UndoPlace(
+ /* [in] */ INSRVINPLACE *pInSrvInPlace,
+ /* [out] */ OUTSRVINPLACE * *pOutSrvInPlace)
+{
+ HRESULT hresult = NOERROR;
+ VDATEHEAP();
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::UndoInplace\n", this));
+
+ //
+ // This method is not implemented yet!
+ //
+
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p OUT CClientSiteHandler::UndoInplace\n", this));
+ return hresult;
+}
+
+
+#endif // SERVER_HANDLER
diff --git a/private/ole32/ole232/stdimpl/clthndlr.h b/private/ole32/ole232/stdimpl/clthndlr.h
new file mode 100644
index 000000000..5fb1b8176
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/clthndlr.h
@@ -0,0 +1,198 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: clnthndlr.h
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 10-10-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef SERVER_HANDLER
+
+#ifndef _CLTHNDLR_H_DEFINED_
+#define _CLTHNDLR_H_DEFINED_
+
+#include "srvhdl.h"
+
+//+---------------------------------------------------------------------------
+//
+// Class: CClientSiteHandler ()
+//
+// Purpose:
+//
+// Interface:
+// CClientSiteHandler --
+// ~CClientSiteHandler --
+// QueryInterface --
+// AddRef --
+// Release --
+// PrivQueryInterface --
+// PrivAddRef --
+// PrivRelease --
+// GetContainer --
+// OnShowWindow --
+// GetMoniker --
+// RequestNewObjectLayout --
+// SaveObject --
+// ShowObject --
+// GetWindow --
+// ContextSensitiveHelp --
+// CanInPlaceActivate --
+// OnInPlaceActivate --
+// OnUIActivate --
+// GetWindowContext --
+// Scroll --
+// OnUIDeactivate --
+// OnInPlaceDeactivate --
+// DiscardUndoState --
+// DeactivateAndUndo --
+// OnPosRectChange --
+// GoInPlaceActivate --
+// GoInPlace --
+// UndoPlace --
+// GetClientSiteDelegate --
+// GetPUnkClientSiteDelegate --
+// SetClientSiteDelegate --
+// _pOCS --
+// _pOCSActive --
+// _pOCont --
+// _pOIPS --
+// _cRefs --
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+class CClientSiteHandler : public IClientSiteHandler
+{
+public:
+
+ CClientSiteHandler(IOleClientSite *pOCS);
+ ~CClientSiteHandler();
+
+ STDMETHOD(QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ // PrivUnknown methods
+ STDMETHOD(PrivQueryInterface)(
+ /* [in] */ DWORD dwId,
+ /* [in] */ REFIID riidResult,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvResult);
+
+ STDMETHOD(PrivAddRef)(
+ /* [in] */ DWORD dwId);
+
+ STDMETHOD(PrivRelease)(
+ /* [in] */ DWORD dwId);
+
+
+ // IOleClientSite methods
+
+ STDMETHOD (GetContainer )(
+ /* [in] */ DWORD dwId,
+ /* [out] */ IOleContainer * *ppContainer);
+
+ STDMETHOD (OnShowWindow )(
+ /* [in] */ DWORD dwId,
+ /* [in] */ BOOL fShow);
+
+ STDMETHOD (GetMoniker )(
+ /* [in] */ DWORD dwId,
+ /* [in] */ DWORD dwAssign,
+ /* [in] */ DWORD dwWhichMoniker,
+ /* [out] */ IMoniker * *ppmk);
+
+ STDMETHOD (RequestNewObjectLayout )(
+ /* [in] */ DWORD dwId
+ );
+
+ STDMETHOD (SaveObject )(
+ /* [in] */ DWORD dwId
+ );
+
+ STDMETHOD (ShowObject )(
+ /* [in] */ DWORD dwId
+ );
+
+
+ // IOleWindow methods
+ STDMETHOD (GetWindow) (
+ /* [out] */ HWND __RPC_FAR *phwnd);
+
+ STDMETHOD (ContextSensitiveHelp) (
+ /* [in] */ BOOL fEnterMode);
+
+ // IOleInPlaceSite methods
+ STDMETHOD (CanInPlaceActivate)( void);
+
+ STDMETHOD (OnInPlaceActivate)( void);
+
+ STDMETHOD (OnUIActivate)( void);
+
+ STDMETHOD (GetWindowContext)(
+ /* [out] */ IOleInPlaceFrame * *ppFrame,
+ /* [out] */ IOleInPlaceUIWindow * *ppDoc,
+ /* [out] */ LPRECT lprcPosRect,
+ /* [out] */ LPRECT lprcClipRect,
+ /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo);
+
+ STDMETHOD (Scroll)(
+ /* [in] */ SIZE scrollExtant);
+
+ STDMETHOD (OnUIDeactivate)(
+ /* [in] */ BOOL fUndoable);
+
+ STDMETHOD (OnInPlaceDeactivate)( void);
+
+ STDMETHOD (DiscardUndoState)( void);
+
+ STDMETHOD (DeactivateAndUndo)( void);
+
+ STDMETHOD (OnPosRectChange)(
+ /* [in] */ LPCRECT lprcPosRect);
+
+ // IClientSiteHandler methods
+
+ STDMETHOD (GoInPlaceActivate)(
+ /* [in] */ INSRVINPLACE *pInSrvInPlace,
+ /* [out] */ OUTSRVINPLACE * *pOutSrvInPlace);
+
+ STDMETHOD (GoInPlace)(
+ /* [in] */ INSRVINPLACE *pInSrvInPlace,
+ /* [out] */ OUTSRVINPLACE * *pOutSrvInPlace);
+
+ STDMETHOD (UndoPlace)(
+ /* [in] */ INSRVINPLACE *pInSrvInPlace,
+ /* [out] */ OUTSRVINPLACE * *pOutSrvInPlace);
+
+public:
+ IOleClientSite *GetClientSiteDelegate(DWORD dwID);
+ IUnknown *GetPUnkClientSiteDelegate(DWORD dwID);
+ void SetClientSiteDelegate(DWORD dwID, IUnknown *pOCS);
+
+public:
+ IOleClientSite *_pOCS;
+ IOleClientSite *_pOCSActive;
+ IOleContainer *_pOCont;
+ IOleInPlaceSite *_pOIPS;
+
+private:
+ ULONG _cRefs;
+
+};
+
+HRESULT CreateClientSiteHandler(IOleClientSite *pOCS, CClientSiteHandler **ppClntHdlr);
+
+#endif // _CLTHNDLR_H_DEFINED
+
+#endif // SERVER_HANDLER
diff --git a/private/ole32/ole232/stdimpl/daytona/makefile b/private/ole32/ole232/stdimpl/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/ole232/stdimpl/daytona/sources b/private/ole32/ole232/stdimpl/daytona/sources
new file mode 100644
index 000000000..10f961a09
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/daytona/sources
@@ -0,0 +1,82 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = ole232
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= stdimpl
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..\..\inc
+INCLUDES= $(INCLUDES);$(BASEDIR)\private\cinc;$(BASEDIR)\private\dcomidl\obj
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -D_TRACKLINK_=1
+
+SOURCES= \
+ ..\Handler.cpp \
+ ..\DefSrv.cpp \
+ ..\Clthndlr.cpp \
+ ..\srvhndlr.cpp \
+ ..\defcf.cpp \
+ ..\defhndlr.cpp \
+ ..\deflink.cpp \
+ ..\defutil.cpp \
+ ..\gen.cpp \
+ ..\icon.cpp \
+ ..\mf.cpp \
+ ..\emf.cpp \
+ ..\olereg.cpp \
+ ..\oregfmt.cpp \
+ ..\oregverb.cpp
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
+
+
diff --git a/private/ole32/ole232/stdimpl/defcf.cpp b/private/ole32/ole232/stdimpl/defcf.cpp
new file mode 100644
index 000000000..02e8b467f
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/defcf.cpp
@@ -0,0 +1,582 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: defcf.cpp
+//
+// Contents: The class factory implementations for the default handler
+// and default link
+//
+// Classes: CDefClassFactory
+//
+// Functions: DllGetClassObject
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH added Dump method to CDefClassFactory
+// and DumpCDefClassFactory API
+// 24-Jan-94 alexgo first pass converting to Cairo style
+// memory allocation
+// 11-Jan-94 alexgo made custom memory stream unmarshalling
+// for 16bit only.
+// 11-Jan-94 alexgo added VDATEHEAP macro to every function
+// and method
+// 22-Nov-93 alexgo removed overload GUID ==
+// 09-Nov-93 alexgo 32bit port
+// 04-Mar-92 SriniK author
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#pragma SEG(deflink)
+
+#include <olerem.h>
+#include <memstm.h>
+#include <create.h>
+
+#include "defcf.h"
+
+#ifdef _DEBUG
+#include <dbgdump.h>
+#endif // _DEBUG
+
+NAME_SEG(DefLink)
+ASSERTDATA
+
+#ifdef _MAC
+// These global class decl's are necessary for CFront because both
+// defhndlr.h and deflink.h have nested class's of the same name.
+// These decl's allow this.
+
+class CDataObjectImpl {
+ VDATEHEAP();
+};
+class COleObjectImpl {};
+class CManagerImpl {};
+class CAdvSinkImpl {};
+class CPersistStgImpl {};
+
+#endif
+
+#include "defhndlr.h"
+#include "deflink.h"
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllGetClassObject
+//
+// Synopsis: Returns a pointer to the class factory
+//
+// Effects:
+//
+// Arguments: [clsid] -- the class id desired
+// [iid] -- the requested interface
+// [ppv] -- where to put the pointer to the new object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 09-Nov-93 alexgo 32bit port
+// 22-Nov-93 alexgo removed overloaded GUID ==
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(DllGetClassObject)
+#ifdef WIN32
+HRESULT Ole232DllGetClassObject(REFCLSID clsid, REFIID iid, void FAR* FAR* ppv)
+#else
+STDAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void FAR* FAR* ppv)
+#endif // WIN32
+{
+ VDATEHEAP();
+
+ VDATEPTROUT(ppv, LPVOID);
+ *ppv = NULL;
+ VDATEIID( iid );
+
+ if ( !IsEqualIID(iid,IID_IUnknown) && !IsEqualIID(iid,
+ IID_IClassFactory))
+ {
+ return ResultFromScode(E_NOINTERFACE);
+ }
+
+ if ((*ppv = new CDefClassFactory (clsid)) == NULL)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ return NOERROR;
+}
+
+/*
+ * IMPLEMENTATION of CDefClassFactory
+ *
+ */
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefClassFactory::CDefClassFactory
+//
+// Synopsis: constructor for the class factory
+//
+// Effects:
+//
+// Arguments: [clsidClass] -- the class id for the the factory
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 09-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CDefClassFactory_ctor)
+CDefClassFactory::CDefClassFactory (REFCLSID clsidClass)
+{
+ VDATEHEAP();
+
+ m_clsid = clsidClass;
+ m_refs = 1;
+ GET_A5();
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefClassFactory::QueryInterface
+//
+// Synopsis: Only IUnkown and IClassFactory are supported
+//
+// Arguments: [iid] -- the requested interface
+// [ppvObj] -- where to put the interface pointer
+//
+// Returns: HRESULT
+//
+// Notes: Bad parameters will raise an exception. The exception
+// handler catches exceptions and returns E_INVALIDARG.
+//
+//-------------------------------------------------------------------------
+#pragma SEG(CDefClassFactory_QueryInterface)
+STDMETHODIMP CDefClassFactory::QueryInterface (REFIID iid, LPVOID FAR* ppvObj)
+{
+ HRESULT hr;
+ __try
+ {
+ //validate parameters.
+ *ppvObj = 0;
+
+ if(IsEqualIID(iid, IID_IUnknown) ||
+ IsEqualIID(iid,IID_IClassFactory))
+ {
+ AddRef();
+ *ppvObj = (IClassFactory *) this;
+ hr = S_OK;
+ }
+ else
+ {
+ hr = E_NOINTERFACE;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //An exception occurred, probably because of a bad parameter.
+ hr = E_INVALIDARG;
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefClassFactory::AddRef
+//
+// Synopsis: increments the reference count
+//
+// Returns: ULONG -- the new reference count
+//
+// Notes: Use InterlockedIncrement to make it multi-thread safe.
+//
+//--------------------------------------------------------------------------
+#pragma SEG(CDefClassFactory_AddRef)
+STDMETHODIMP_(ULONG) CDefClassFactory::AddRef(void)
+{
+ InterlockedIncrement((long *) &m_refs);
+ return m_refs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefClassFactory::Release
+//
+// Synopsis: decrements the reference count
+//
+// Effects: deletes the object when count == 0
+//
+// Returns: ULONG -- the remaining reference count
+//
+// Notes: Use InterlockedDecrement to make it multi-thread safe.
+// We use the count local variable so that we don't access
+// a data member after decrementing the reference count.
+//
+//--------------------------------------------------------------------------
+#pragma SEG(CDefClassFactory_Release)
+STDMETHODIMP_(ULONG) CDefClassFactory::Release(void)
+{
+ ULONG count = m_refs - 1;
+
+ if(InterlockedDecrement((long *) &m_refs) == 0)
+ {
+ delete this;
+ count = 0;
+ }
+ return count;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefClassFactory::CreateInstance
+//
+// Synopsis: Creates an instance of the class that the class factory
+// was created for (by DllGetClassObject)
+//
+// Effects:
+//
+// Arguments: [pUnkOuter] -- the controlling unknown (for aggregation)
+// [iid] -- the requested interface ID
+// [ppv] -- where to put the pointer to the new object
+//
+// Requires:
+//
+// Returns: HRESULT. E_INVALIDARG is returned if an non-null pUnkOuter
+// is passed when asked to create a moniker.
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IClassFactory
+//
+// Algorithm: Tests the classid against a number of predefined ones, doing
+// appropriate tests and actions for each (see comments below).
+//
+// History: dd-mmm-yy Author Comment
+// 11-Jan-94 alexgo ifdef'ed out code to deal with
+// custom marshalling of memory streams
+// and lockbytes (it's 16bit only)
+// 12-Nov-93 alexgo removed IID check's for monikers
+// (see notes below)
+// 12-Nov-93 alexgo removed a goto and more redundant code
+// changed overloaded == to IsEqualCLSID
+// 11-Nov-93 alexgo 32bit port
+//
+// Notes:
+// 11/12/93: All of the conditional blocks for monikers
+// used to have code that tested iid == IMarshal ||
+// IMoniker (and then we'd do the QueryInterface).
+// I removed that code, relying on the moniker to tell
+// us what iid's it will accept. Now OleCreate(moniker,
+// iid) will behave the same way as CreateFileMoniker,
+// moniker->QueryInterface(iid).
+//
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CDefClassFactory_CreateInstance)
+STDMETHODIMP CDefClassFactory::CreateInstance
+ (IUnknown FAR* pUnkOuter, REFIID iid, void FAR* FAR* ppv)
+{
+ VDATEHEAP();
+
+ HRESULT hresult = NOERROR;
+ LPMONIKER pmk = NULL;
+ IUnknown FAR* pUnk = NULL;
+
+ M_PROLOG(this);
+ VDATEPTROUT( ppv, LPVOID );
+ *ppv = NULL;
+ VDATEIID( iid );
+
+ if ( pUnkOuter )
+ VDATEIFACE( pUnkOuter );
+
+
+ *ppv = NULL;
+
+ // WIN32 uses standard marshalling for memory streams
+ // and lockbytes.
+#ifndef WIN32
+ if (IsEqualCLSID(m_clsid, CLSID_StdMemStm))
+ {
+ if (pUnkOuter != NULL || !IsEqualIID(iid,IID_IMarshal))
+ {
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+
+ return (*ppv = CMemStmUnMarshal()) != NULL ? NOERROR :
+ ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ else if (IsEqualCLSID(m_clsid, CLSID_StdMemBytes))
+ {
+ if (pUnkOuter != NULL || !IsEqualIID(iid,IID_IMarshal))
+ {
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+
+ return (*ppv = CMemBytesUnMarshal()) != NULL ? NOERROR :
+ ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+#endif // !WIN32
+
+ if (IsEqualCLSID(m_clsid, CLSID_ItemMoniker))
+ {
+ hresult = CreateItemMoniker(OLESTR(""), OLESTR(""), &pmk);
+ }
+ else if (IsEqualCLSID(m_clsid, CLSID_CompositeMoniker))
+ {
+ hresult = Concatenate(NULL, NULL, &pmk);
+ }
+ else if (IsEqualCLSID(m_clsid, CLSID_PackagerMoniker))
+ {
+ hresult = CreatePackagerMoniker (OLESTR(""), &pmk, FALSE);
+ }
+ else if (IsEqualCLSID(m_clsid, CLSID_AntiMoniker))
+ {
+ hresult = CreateAntiMoniker(&pmk);
+ }
+ else if (IsEqualCLSID(m_clsid, CLSID_PointerMoniker))
+ {
+ hresult = CreatePointerMoniker(NULL, &pmk);
+ }
+ else if (IsEqualCLSID(m_clsid, CLSID_StdOleLink))
+ {
+ pUnk = CDefLink::Create(pUnkOuter);
+ }
+ else if (IsEqualCLSID(m_clsid, CLSID_ErrorObject))
+ {
+ if(pUnkOuter != NULL)
+ {
+ return CLASS_E_NOAGGREGATION;
+ }
+ hresult = CoCreateErrorInfo((ICreateErrorInfo **)&pUnk);
+ }
+ else
+ {
+ pUnk = CDefObject::Create(pUnkOuter, m_clsid,
+ EMBDHLP_INPROC_HANDLER | EMBDHLP_CREATENOW, NULL);
+ }
+
+ //we have two cases at this point, we created a moniker
+ //(pmk != NULL && hresult == NOERROR), or we created a link
+ //or handler (pUnk != NULL).
+
+ //Here we handle the appropriate error conditions
+ if (pmk != NULL && hresult == NOERROR)
+ {
+ //Moniker case. The built-in monikers cannot
+ //be aggregated.
+
+ AssertSz(pUnk == NULL, "Internal error, shouldn't get here");
+
+ if( pUnkOuter != NULL )
+ {
+ pmk->Release(); //we created it, but shouldn't have
+ return ResultFromScode(E_INVALIDARG);
+ }
+
+ //CAST WARNING!!
+ //This case is safe, since IMoniker inherits from IUnkown
+ //and we will only use IUnkown interfaces from here on out.
+ //
+ //This eliminates a redundant QueryInterface
+ pUnk = (LPUNKNOWN)pmk;
+ }
+ else if ( pUnk == NULL )
+ {
+ //Link or embedding case. Could not create the
+ //correct handler
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+ else if ( hresult != NOERROR )
+ {
+ //something went wrong creating a moniker. Return
+ //the error code
+ return hresult;
+ }
+
+ //if we get this far, then everything is OK; we have successfully
+ //created either a moniker or default handler or default link
+ //now QueryInterface and return
+
+ hresult = pUnk->QueryInterface(iid, ppv);
+ //The QI will add a ref, plus the ref from Create, so
+ //we need to release one.
+ pUnk->Release();
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefClassFactory::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppszDump] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CDefClassFactory::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszCLSID;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump;
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "No. of References = " << m_refs << endl;
+
+ pszCLSID = DumpCLSID(m_clsid);
+ dstrDump << pszPrefix << "CLSID = " << pszCLSID << endl;
+ CoTaskMemFree(pszCLSID);
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCDefClassFactory, public (_DEBUG only)
+//
+// Synopsis: calls the CDefClassFactory::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pCDF] - pointer to CDefClassFactory
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCDefClassFactory(CDefClassFactory *pCDF, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pCDF == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pCDF->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
diff --git a/private/ole32/ole232/stdimpl/defcf.h b/private/ole32/ole232/stdimpl/defcf.h
new file mode 100644
index 000000000..3b938dc8d
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/defcf.h
@@ -0,0 +1,67 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: defcf.h
+//
+// Contents: class factory for def handler and def link
+//
+// Classes: CDefClassFactory
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 06-Feb-95 t-ScottH created - transfer CDefClassFactory
+// definition into header file from cpp file
+//
+//--------------------------------------------------------------------------
+
+#ifndef _DEFCF_H_
+#define _DEFCF_H_
+
+#ifdef _DEBUG
+#include <dbgexts.h>
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDefClassFactory
+//
+// Purpose: The class factory for the default handler and default link
+//
+// Interface: IClassFactory
+//
+// History: dd-mmm-yy Author Comment
+// 09-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+class FAR CDefClassFactory : public IClassFactory, public CPrivAlloc
+{
+public:
+ CDefClassFactory (REFCLSID clsidClass);
+ STDMETHOD(QueryInterface) (REFIID iid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+ STDMETHOD(CreateInstance) (LPUNKNOWN pUnkOuter, REFIID iid,
+ LPVOID FAR* ppv);
+ STDMETHODIMP CDefClassFactory::LockServer ( BOOL fLock )
+ { return NOERROR; }
+
+ #ifdef _DEBUG
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+ #endif // _DEBUG
+
+private:
+ CLSID m_clsid;
+ ULONG m_refs;
+
+ SET_A5;
+};
+
+
+#endif // _DEFCF_H_
diff --git a/private/ole32/ole232/stdimpl/defhndlr.cpp b/private/ole32/ole232/stdimpl/defhndlr.cpp
new file mode 100644
index 000000000..1455678f2
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/defhndlr.cpp
@@ -0,0 +1,6112 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: defhndlr.cpp
+//
+// Contents: Implementation of the default handler
+//
+// Classes: CDefObject (see defhndlr.h)
+//
+// Functions: OleCreateDefaultHandler
+// OleCreateEmbeddingHelper
+//
+//
+// History: dd-mmm-yy Author Comment
+//
+// 11-17-95 JohannP (Johann Posch) Architectural change:
+// Default handler will talk to a handler object
+// on the server site (ServerHandler). The serverhandler
+// communicates with the default handler via the
+// clientsitehandler. See document: "The Ole Server Handler".
+//
+// 06-Sep-95 davidwor modified SetHostNames to avoid atoms
+// 01-Feb-95 t-ScottH add Dump method to CDefObject
+// add DumpCDefObject API
+// add DHFlag to indicate aggregation
+// initialize m_cConnections in constructor
+// 09-Jan-95 t-scotth changed VDATETHREAD to accept a pointer
+// 15-Nov-94 alexgo optimized, removed excess BOOLS and
+// now use multiple inheritance
+// 01-Aug-94 alexgo added object stabilization
+// 16-Jan-94 alexgo fixed bug in control flow for
+// advises
+// 11-Jan-94 alexgo added VDATEHEAP macro to every function
+// and method.
+// 10-Dec-93 alexgo added call tracing, ran through
+// tab filter program to eliminate
+// whitespace
+// 30-Nov-93 alexgo fixed bug with cache aggregation
+// 22-Nov-93 alexgo removed overloaded == for GUIDs
+// 09-Nov-93 ChrisWe changed COleCache::Update to
+// COleCache::UpdateCache, and COleCache::Discard to
+// COleCache::DiscardCache, which do the same as the
+// originals, but without the indirect function call
+// 02-Nov-93 alexgo 32bit port
+// srinik 09/15/92 Removed code for giving cfOwnerLink data through
+// GetData() method
+// srinik 09/11/92 Removed IOleCache implementation, as a result of
+// removing voncache.cpp, and moving IViewObject
+// implementation into olecache.cpp.
+// SriniK 06/04/92 Fixed problems in IPersistStorage methods
+// 04-Mar-92 srinik created
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+
+#include <scode.h>
+#include <objerror.h>
+
+#include <olerem.h>
+
+#include "handler.hxx"
+#include "defhndlr.h"
+#include "defutil.h"
+#include "ole1cls.h"
+
+#ifdef _DEBUG
+#include <dbgdump.h>
+#endif // _DEBUG
+
+
+ASSERTDATA
+
+/*
+* IMPLEMENTATION of CDefObject
+*
+*/
+
+
+FARINTERNAL_(LPUNKNOWN) CreateDdeProxy(IUnknown FAR* pUnkOuter,
+ REFCLSID rclsid);
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateRemoteHandler
+//
+// Synopsis: Calls CreateIdentityHandler (or CreateDdeProxy for 1.0-2.0
+// interop). Internal function
+//
+// Effects:
+//
+// Arguments: [rclsid] -- clsid that the remote handler is for
+// [pUnkOuter] -- the controlling unkown
+// [iid] -- requested interface ID
+// [ppv] -- where to put the pointer to the
+// remote handler
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Dec-93 alexgo added call tracing info
+// 02-Nov-93 alexgo 32bit port, disabled CreateDdeProxy
+//
+// Notes: REVIEW32: 1.0-2.0 interop not yet fully decided. For the
+// moment, CreateDdeProxy has been disabled.
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL CreateRemoteHandler (REFCLSID rclsid,
+ IUnknown FAR* pUnkOuter, REFIID iid, void FAR* FAR* ppv)
+{
+ VDATEHEAP();
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CreateRemoteHandler ("
+ " %p , %p , %p , %p )\n", 0 /*function*/, rclsid, pUnkOuter,
+ iid, ppv));
+
+
+ if (CoIsOle1Class(rclsid))
+ {
+ IUnknown FAR * pUnk;
+
+ COleTls Tls;
+ if( Tls->dwFlags & OLETLS_DISABLE_OLE1DDE )
+ {
+ // If this app doesn't want or can tolerate having a DDE
+ // window then currently it can't use OLE1 classes because
+ // they are implemented using DDE windows.
+ //
+ hresult = CO_E_OLE1DDE_DISABLED;
+ goto errRtn;
+ }
+
+ LEDebugOut((DEB_ITRACE,
+ "%p CreateRemoteHandler calling CreateDdeProxy ("
+ " %p , %p )\n",
+ 0 /*function*/, pUnkOuter, rclsid));
+
+ pUnk = CreateDdeProxy (pUnkOuter, rclsid);
+
+ if (pUnk == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ hresult = pUnk->QueryInterface(iid, ppv);
+ pUnk->Release();
+ goto errRtn;
+
+ }
+
+#ifdef DCOM
+ // Create LRPC handler. Dont know the OID yet so pass NULL.
+ hresult = CreateIdentityHandler(pUnkOuter, 0, iid, ppv);
+#else
+ // Create LRPC handler
+ hresult = CreateIdentityHandler(pUnkOuter, PSTDMARSHAL, iid, ppv);
+#endif
+
+errRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT CreateRemoteHandler ( %lx ) "
+ "[ %p ]\n", 0 /*function*/, hresult, (ppv) ? *ppv : 0));
+
+ CALLHOOKOBJECTCREATE(hresult, rclsid, iid, (IUnknown **)ppv);
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateDefaultHandler
+//
+// Synopsis: API to create the default handler. Simply calls
+// OleCreateEmbeddingHelper with more arguments
+//
+// Effects:
+//
+// Arguments: [clsid] -- the clsid of the remote exe
+// [pUnkOuter] -- the controlling unknown (so we can
+// be aggregated)
+// [iid] -- the requested interface
+// [ppv] -- where to put a pointer to the default
+// handler
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Dec-93 alexgo added call tracing
+// 02-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleCreateDefaultHandler)
+STDAPI OleCreateDefaultHandler(REFCLSID clsid, IUnknown FAR* pUnkOuter,
+ REFIID iid, LPVOID FAR* ppv)
+{
+ OLETRACEIN((API_OleCreateDefaultHandler,
+ PARAMFMT("clsid= %I, pUnkOuter= %p, iid= %I, ppv= %p"),
+ &clsid, pUnkOuter, &iid, ppv));
+
+ VDATEHEAP();
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleCreateDefaultHandler "
+ "( %p , %p , %p , %p )\n", 0 /*function*/,
+ clsid, pUnkOuter, iid, ppv));
+
+ hresult = OleCreateEmbeddingHelper(clsid, pUnkOuter,
+ EMBDHLP_INPROC_HANDLER | EMBDHLP_CREATENOW, NULL, iid, ppv);
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleCreateDefaultHandler "
+ "( %lx ) [ %p ]\n", 0 /*function*/, hresult,
+ (ppv)? *ppv : 0 ));
+
+ OLETRACEOUT((API_OleCreateDefaultHandler, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleCreateEmbeddingHelper
+//
+// Synopsis: Creates an instance of CDefObject (the default handler).
+// Called by OleCreateDefaultHandler
+//
+// Effects:
+//
+// Arguments: [clsid] -- class id of the server
+// [pUnkOuter] -- the controlling unkown for aggregation
+// [flags] -- whether to create an inproc handler or
+// helper for an inproc server. The inproc
+// server case is useful for embedding an
+// object inside an object, etc.
+// [pCF] -- a pointer to the server's class factory
+// may be NULL.
+// [iid] -- the requested interface
+// [ppv] -- where to put the pointer to the
+// embedding helper
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleCreateEmbeddingHelper)
+STDAPI OleCreateEmbeddingHelper(REFCLSID clsid, IUnknown FAR* pUnkOuter,
+ DWORD flags, IClassFactory FAR* pCF, REFIID iid, LPVOID FAR* ppv)
+{
+ OLETRACEIN((API_OleCreateEmbeddingHelper,
+ PARAMFMT("clsid= %I, pUnkOuter= %p, flags= %x, pCF= %p, iid= %I, ppv= %p"),
+ &clsid, pUnkOuter, flags, pCF, &iid, ppv));
+
+ VDATEHEAP();
+
+ HRESULT hresult = E_INVALIDARG;
+ IUnknown FAR * pUnk;
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleCreateEmbeddingHelper "
+ "( %p , %p , %lu , %p , %p , %p )\n", 0 /*function*/,
+ clsid, pUnkOuter, flags, pCF, iid, ppv));
+
+ VDATEPTROUT_LABEL(ppv, LPVOID, safeRtn, hresult);
+ *ppv = NULL;
+
+ if (pUnkOuter)
+ {
+ VDATEIFACE_LABEL(pUnkOuter, safeRtn, hresult);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IUnknown,(IUnknown **)&pUnkOuter);
+ }
+
+ if (LOWORD(flags) > EMBDHLP_INPROC_SERVER)
+ {
+ Assert(hresult == E_INVALIDARG);
+ goto errRtn;
+ }
+
+ // Caller must get out IUnknown if we are being
+ // aggregated (because IUnknown is the only *private*
+ // interface currently supported by the default handler
+ if( (pUnkOuter != NULL) && (iid != IID_IUnknown) )
+ {
+ Assert(hresult == E_INVALIDARG);
+ goto errRtn;
+ }
+
+ if (pCF)
+ {
+ VDATEIFACE_LABEL(pCF, safeRtn, hresult);
+ }
+ else if (LOWORD(flags) == EMBDHLP_INPROC_SERVER)
+ {
+ // can't have NULL pCF for server case
+ Assert(hresult == E_INVALIDARG);
+ goto errRtn;
+ }
+
+ // if we allowed delay create of handler, we might possibly treat
+ // the handler as a server-type object
+ if (LOWORD(flags) == EMBDHLP_INPROC_HANDLER &&
+ flags&EMBDHLP_DELAYCREATE)
+ {
+ Assert(hresult == E_INVALIDARG);
+ goto errRtn;
+ }
+
+ pUnk = CDefObject::Create(pUnkOuter, clsid, flags, pCF);
+
+ if (pUnk == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ hresult = pUnk->QueryInterface(iid, ppv);
+ pUnk->Release();
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT OleCreateEmbeddingHelper "
+ "( %lx ) [ %p ]\n", 0 /*function*/, hresult, (ppv)? *ppv :0));
+
+ CALLHOOKOBJECTCREATE(hresult, clsid, iid, (IUnknown **)ppv);
+
+safeRtn:
+ OLETRACEOUT((API_OleCreateEmbeddingHelper, hresult));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::Create, static
+//
+// Synopsis: Creates an instance of CDefObject
+//
+// Effects:
+//
+// Arguments: [pUnkOuter] -- the controlling unkown
+// [clsid] -- the clsid of the server
+// [flags] -- creation flags
+// [pCF] -- pointer to the server's class factory
+// may be NULL.
+//
+// Requires:
+//
+// Returns: pointer to the CDefObject's IUnkown implementation
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: none
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Nov-93 alexgo 32bit port
+//
+// Notes: OleCreateDefaultHandler or OleCreateEmbeddingHelper
+// are the preferred ways to create a handler.
+//
+//--------------------------------------------------------------------------
+
+IUnknown *CDefObject::Create( IUnknown *pUnkOuter, REFCLSID clsid,
+ DWORD flags, IClassFactory *pCF)
+{
+ VDATEHEAP();
+
+ CDefObject FAR* pDefObj;
+
+ if ((pDefObj = new CDefObject(pUnkOuter)) == NULL)
+ {
+ return NULL;
+ }
+
+ // set our ref count to 1
+ pDefObj->m_Unknown.AddRef();
+
+ pDefObj->m_clsidServer = clsid;
+ pDefObj->m_clsidBits = CLSID_NULL;
+ pDefObj->m_clsidUser = CLSID_NULL;
+
+ if( (LOWORD(flags) == EMBDHLP_INPROC_HANDLER) )
+ {
+ pDefObj->m_flags |= DH_INPROC_HANDLER;
+ }
+
+ if( IsEqualCLSID(clsid, CLSID_StaticMetafile) ||
+ IsEqualCLSID(clsid, CLSID_StaticDib) ||
+ IsEqualCLSID(clsid, CLSID_Picture_EnhMetafile))
+ {
+ pDefObj->m_flags |= DH_STATIC;
+ }
+
+ if (pCF != NULL)
+ {
+ pDefObj->m_pCFDelegate = pCF;
+ pCF->AddRef();
+ }
+
+ if(flags & EMBDHLP_DELAYCREATE) {
+ // delay creation of delegate until later
+ Assert(pCF != NULL);
+
+ // if we allowed delay create of handler, we might possibly
+ // treat the handler as a server-type object
+ Assert(LOWORD(flags) == EMBDHLP_INPROC_SERVER);
+
+ Assert(pDefObj->m_pUnkDelegate == NULL);
+ Assert(pDefObj->m_pProxyMgr == NULL);
+
+ pDefObj->m_flags |= DH_DELAY_CREATE;
+ } else {
+ // EMBDHLP_CREATENOW
+
+ if (pDefObj->CreateDelegate() != NOERROR)
+ {
+ goto errRtn;
+ }
+ }
+
+ // create cache and get commonly used pointers into it
+ if ((pDefObj->m_pCOleCache = new COleCache(pDefObj->m_pUnkOuter,
+ clsid)) == NULL)
+ goto errRtn;
+
+ if (CDataAdviseCache::CreateDataAdviseCache(&pDefObj->m_pDataAdvCache)
+ != NOERROR)
+ goto errRtn;
+
+ return &pDefObj->m_Unknown;
+
+errRtn:
+ pDefObj->m_Unknown.Release();
+ return NULL;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::CDefObject
+//
+// Synopsis: constructor, sets member variables to NULL
+//
+// Effects:
+//
+// Arguments: [pUnkOuter] -- the controlling unkown
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: none
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CDefObject::CDefObject (IUnknown *pUnkOuter)
+{
+ VDATEHEAP();
+
+ if (!pUnkOuter)
+ {
+ pUnkOuter = &m_Unknown;
+ }
+
+ m_fIsMaybeRunning = FALSE;
+
+ //m_clsidServer
+ //m_clsidBits are set in ::Create
+
+ m_cRefsOnHandler = 0;
+ m_cConnections = 0;
+ m_pCFDelegate = NULL;
+ m_pUnkDelegate = NULL;
+ m_pUnkOuter = pUnkOuter;
+ m_pProxyMgr = NULL;
+
+ m_pCOleCache = NULL;
+ m_pOAHolder = NULL;
+ m_dwConnOle = 0L;
+
+ m_pAppClientSite = NULL;
+ m_pStg = NULL;
+
+ m_pDataAdvCache = NULL;
+ m_flags = DH_INIT_NEW;
+
+ m_pHostNames = NULL;
+ m_ibCntrObj = 0;
+ m_pOleDelegate = NULL;
+ m_pDataDelegate = NULL;
+ m_pPSDelegate = NULL;
+
+#ifdef SERVER_HANDLER
+ _pSrvHndlr = NULL;
+ _pClientSiteHandler = NULL;
+
+ // We used to read options from the registry but it was too slow.
+ _dwHandlerOptions = HO_Default;
+ _dwServerHandler = _dwHandlerOptions & HO_ServerHandler;
+ _dwClientSiteHandler= _dwHandlerOptions & HO_ClientSiteHandler;
+
+#endif // SERVER_HANDLER
+
+#ifdef _DEBUG
+ if (pUnkOuter != &m_Unknown)
+ {
+ m_flags |= DH_AGGREGATED;
+ }
+#endif // _DEBUG
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::CleanupForDelete
+//
+// Synopsis: Releases all pointers, etc so that [this] may be safely
+// deleted
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires: the server must have been STOP'ed.
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 02-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+void CDefObject::CleanupForDelete(void)
+{
+ VDATEHEAP();
+
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefObject::CleanupForDelete ( )\n",
+ this));
+
+ // release our cached pointers will cause AddRef's back to us
+ // because of the May '94 rules of aggregation.
+
+ m_cRefsOnHandler++;
+
+
+ // REVIEW Craigwi/Srini: this is temporary; should really set up
+ // IsRunning so that it calls OnClose when we discover that the server
+ // has stopped running when we think it had been running.
+ if (m_pCOleCache)
+ {
+ m_pCOleCache->OnStop();
+ }
+
+ // release all the pointers that we remeber
+
+ // NOTE: we must release cached interface pointers. However,
+ // since we already did a release on the outer unknown in Create,
+ // we need to do the corresponding AddRef here.
+
+ if( m_pProxyMgr )
+ {
+ m_pUnkOuter->AddRef();
+ SafeReleaseAndNULL((IUnknown **)&m_pProxyMgr);
+ }
+
+ // release cached pointers in the nested classes
+
+ if( m_pDataDelegate )
+ {
+ m_pUnkOuter->AddRef();
+ SafeReleaseAndNULL((IUnknown **)&m_pDataDelegate);
+ }
+
+ if( m_pOleDelegate )
+ {
+ m_pUnkOuter->AddRef();
+ SafeReleaseAndNULL((IUnknown **)&m_pOleDelegate);
+ }
+
+ if( m_pPSDelegate )
+ {
+ m_pUnkOuter->AddRef();
+ SafeReleaseAndNULL((IUnknown **)&m_pPSDelegate);
+ }
+
+ if (m_pUnkDelegate)
+ {
+ SafeReleaseAndNULL((IUnknown **)&m_pUnkDelegate);
+ }
+
+ if (m_pCFDelegate)
+ {
+ SafeReleaseAndNULL((IUnknown **)&m_pCFDelegate);
+ }
+
+#ifdef SERVER_HANDLER
+ if (_pSrvHndlr)
+ {
+ SafeReleaseAndNULL((IUnknown **)&_pSrvHndlr);
+ }
+
+ if (_pClientSiteHandler)
+ {
+ SafeReleaseAndNULL((IUnknown **)&_pClientSiteHandler);
+ }
+#endif // SERVER_HANDLER
+
+ if (m_pCOleCache)
+ {
+ COleCache *pcache = m_pCOleCache;
+ m_pCOleCache = NULL;
+ pcache->m_UnkPrivate.Release();
+ }
+
+
+ if (m_pAppClientSite)
+ {
+ SafeReleaseAndNULL((IUnknown **)&m_pAppClientSite);
+ }
+
+ if (m_pStg)
+ {
+ SafeReleaseAndNULL((IUnknown **)&m_pStg);
+ }
+
+ if (m_pHostNames)
+ {
+ PrivMemFree(m_pHostNames);
+ m_pHostNames = NULL;
+ }
+
+ if (m_pOAHolder)
+ {
+ SafeReleaseAndNULL((IUnknown **)&m_pOAHolder);
+ }
+ if (m_pDataAdvCache)
+ {
+ LPDATAADVCACHE pcacheTemp = m_pDataAdvCache;
+ m_pDataAdvCache = NULL;
+ delete pcacheTemp;
+ }
+
+ // undo the addref above
+
+ m_cRefsOnHandler--;
+
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefObject::CleanupForDelete ( )\n",
+ this));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::~CDefObject
+//
+// Synopsis: Destructor for the the default handler
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: calls CleanupForDelete to release all of our pointers, etc.
+//
+// History: dd-mmm-yy Author Comment
+// 03-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CDefObject_dtor)
+CDefObject::~CDefObject(void)
+{
+ VDATEHEAP();
+
+ CleanupForDelete();
+
+ Assert(m_pUnkDelegate == NULL);
+ Assert(m_pCFDelegate == NULL);
+ Assert(m_pProxyMgr == NULL);
+ Assert(m_pCOleCache == NULL);
+ Assert(m_pOAHolder == NULL);
+ Assert(m_pAppClientSite == NULL);
+ Assert(m_pHostNames == NULL);
+ Assert(m_pStg == NULL);
+ Assert(m_pDataAdvCache == NULL);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::CreateDelegate
+//
+// Synopsis: Creates either a remote handler or a user supplied delegate
+// (passed into the creation of the remote handler in the
+// [pCF] field).
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires: The remote handler must support IProxyManager
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 03-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+INTERNAL CDefObject::CreateDelegate(void)
+{
+ VDATEHEAP();
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CreateDelegate "
+ "( )\n", this));
+
+ if (m_pUnkDelegate != NULL)
+ {
+ hresult = NOERROR;
+ goto errRtn;
+ }
+
+ if (m_pCFDelegate == NULL)
+ {
+ // create standard lrpc or dde remoting piece
+ hresult = CreateRemoteHandler (m_clsidServer, m_pUnkOuter,
+ IID_IUnknown, (LPLPVOID)&m_pUnkDelegate);
+ }
+ else
+ {
+ // create user supplied piece; m_pCFDelegate must encode the
+ // clsid.
+ // REVIEW: could later assert that the handler clsid is same
+ hresult = m_pCFDelegate->CreateInstance(m_pUnkOuter,
+ IID_IUnknown, (LPLPVOID)&m_pUnkDelegate);
+ }
+
+ AssertOutPtrIface(hresult, m_pUnkDelegate);
+
+ if (hresult != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ // release after successful create
+ if (m_pCFDelegate != NULL)
+ {
+ m_pCFDelegate->Release();
+ m_pCFDelegate = NULL;
+ }
+
+ // NOTE: the remote handler is created initially locked; this is
+ // reflected in the m_fContainedObject = FALSE in the ctor
+
+ // allow the handler to not expose proxymgr
+ if (m_pUnkDelegate->QueryInterface (IID_IProxyManager,
+ (LPLPVOID) &m_pProxyMgr) == NOERROR)
+ {
+ // rule is: release the outer unknown for cached pointers
+ // of the aggregatee
+ m_pUnkOuter->Release();
+ }
+ else
+ {
+ m_pProxyMgr = NULL;
+ }
+
+ // can't have an inproc server with a proxymgr or a handler without one
+ Assert((m_pProxyMgr != NULL) == !!(m_flags & DH_INPROC_HANDLER));
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CreateDelegate "
+ "( %lx )\n", this , hresult));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::CPrivUnknown::AddRef
+//
+// Synopsis: Increments the reference count.
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG (the new reference count)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IUnkown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 03-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDefObject::CPrivUnknown::AddRef( void )
+{
+ CDefObject *pDefObject = GETPPARENT(this, CDefObject, m_Unknown);
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CPrivUnknown::AddRef "
+ "( )\n", pDefObject));
+
+
+ // we need to keep track of the hander's reference count separately
+ // from the handler/advise sink combination in order to handle
+ // our running/stopped state transitions.
+
+ pDefObject->m_cRefsOnHandler++;
+ pDefObject->SafeAddRef();
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CPrivUnknown::AddRef "
+ "( %lu )\n", pDefObject, pDefObject->m_cRefsOnHandler));
+
+ return pDefObject->m_cRefsOnHandler;
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::CPrivUnknown::Release
+//
+// Synopsis: Decrements the ref count, cleaning up and deleting the
+// object if necessary
+//
+// Effects: May delete the object (and potentially objects to which the
+// handler has pointer)
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG--the new ref count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 03-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDefObject::CPrivUnknown::Release( void )
+{
+ CDefObject *pDefObject = GETPPARENT(this, CDefObject, m_Unknown);
+
+ VDATEHEAP();
+
+ ULONG refcount;
+
+
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CPrivUnknown::Release "
+ "( )\n", pDefObject));
+
+ if( pDefObject->m_cRefsOnHandler == 1)
+ {
+ pDefObject->Stop();
+ }
+
+ refcount = --pDefObject->m_cRefsOnHandler;
+ pDefObject->SafeRelease();
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CPrivUnknown::Release "
+ "( %lu )\n", pDefObject, refcount));
+
+ return refcount;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::CPrivUnknown::QueryInterface
+//
+// Synopsis: Returns a pointer to one of the supported interfaces.
+//
+// Effects:
+//
+// Arguments: [iid] -- the requested interface ID
+// [ppv] -- where to put the iface pointer
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 03-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::CPrivUnknown::QueryInterface(REFIID iid,
+ LPLPVOID ppv)
+{
+ CDefObject * pDefObject = GETPPARENT(this, CDefObject, m_Unknown);
+ HRESULT hresult;
+
+ VDATEHEAP();
+
+
+ LEDebugOut((DEB_TRACE,
+ "%p _IN CDefObject::CUnknownImpl::QueryInterface "
+ "( %p , %p )\n", pDefObject, iid, ppv));
+
+ CStabilize stabilize((CSafeRefCount*)pDefObject);
+
+ if (IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppv = (void FAR *)this;
+ }
+ else if (IsEqualIID(iid, IID_IOleObject))
+ {
+ *ppv = (void FAR *)(IOleObject *)pDefObject;
+ }
+ else if (IsEqualIID(iid, IID_IDataObject))
+ {
+ *ppv = (void FAR *)(IDataObject *)pDefObject;
+ }
+ else if (IsEqualIID(iid, IID_IRunnableObject))
+ {
+ *ppv = (void FAR *)(IRunnableObject *)pDefObject;
+ }
+ else if (IsEqualIID(iid, IID_IPersist) ||
+ IsEqualIID(iid, IID_IPersistStorage))
+ {
+ *ppv = (void FAR *)(IPersistStorage *)pDefObject;
+ }
+ else if( IsEqualIID(iid, IID_IViewObject) ||
+ IsEqualIID(iid, IID_IViewObject2) ||
+ IsEqualIID(iid, IID_IOleCache) ||
+ IsEqualIID(iid, IID_IOleCache2) )
+ {
+ // m_pCOleCache is a pointer to the *public* IUnknown
+ // (we want the private one)
+ hresult =
+ pDefObject->m_pCOleCache->m_UnkPrivate.QueryInterface(
+ iid, ppv);
+
+ LEDebugOut((DEB_TRACE,
+ "%p OUT CDefObject::CUnknownImpl::QueryInterface "
+ "( %lx ) [ %p ]\n", pDefObject, hresult,
+ (ppv) ? *ppv : 0 ));
+
+ return hresult;
+ }
+ else if( !(pDefObject->m_flags & DH_INPROC_HANDLER) &&
+ IsEqualIID(iid, IID_IExternalConnection) )
+ {
+ // only allow IExternalConnection if inproc server. We
+ // know we are an inproc server if we are *not* an inproc
+ // handler (cute, huh? ;-)
+
+ *ppv = (void FAR *)(IExternalConnection *)pDefObject;
+ }
+ else if( IsEqualIID(iid, IID_IOleLink) )
+ {
+ // this prevents a remote call for
+ // a query which will almost always fail; the remote call
+ // interfered with server notification messages.
+ *ppv = NULL;
+
+ LEDebugOut((DEB_TRACE,
+ "%p OUT CDefObject::CUnknownImpl::QueryInterface "
+ "( %lx ) [ %p ]\n", pDefObject, E_NOINTERFACE, 0));
+
+ return E_NOINTERFACE;
+ }
+ else if( IsEqualIID(iid, IID_IInternalUnknown) )
+ {
+ // this interface is private between the handler and the
+ // remoting layer and is never exposed by handlers.
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+ else if( pDefObject->CreateDelegate() == NOERROR)
+ {
+
+ hresult = pDefObject->m_pUnkDelegate->QueryInterface( iid,
+ ppv);
+
+ LEDebugOut((DEB_TRACE,
+ "%p OUT CDefObject::CUnknownImpl::QueryInterface "
+ "( %lx ) [ %p ]\n", pDefObject, hresult,
+ (ppv) ? *ppv : 0 ));
+
+ return hresult;
+ }
+ else
+ {
+ // no delegate and couldn't create one
+ *ppv = NULL;
+
+ LEDebugOut((DEB_TRACE,
+ "%p OUT CDefObject::CUnkownImpl::QueryInterface "
+ "( %lx ) [ %p ]\n", pDefObject, CO_E_OBJNOTCONNECTED,
+ 0 ));
+
+ return CO_E_OBJNOTCONNECTED;
+ }
+
+ // this indirection is important since there are different
+ // implementationsof AddRef (this unk and the others).
+ ((IUnknown FAR*) *ppv)->AddRef();
+
+ LEDebugOut((DEB_TRACE,
+ "%p OUT CDefObject::CUnknownImpl::QueryInterface "
+ "( %lx ) [ %p ]\n", pDefObject, NOERROR, *ppv));
+
+ return NOERROR;
+}
+
+/*
+ * IMPLEMENTATION of IUnknown methods
+ */
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::QueryInterface
+//
+// Synopsis: QI's to the controlling IUnknown
+//
+// Effects:
+//
+// Arguments: [riid] -- the interface ID
+// [ppv] -- where to put it
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IUnknown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Nov-94 alexgo author
+//
+// Notes: We do *not* need to stabilize this method as only
+// one outgoing call is made and we do not use the
+// 'this' pointer afterwards
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::QueryInterface( REFIID riid, void **ppv )
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::QueryInterface ( %lx , "
+ "%p )\n", this, riid, ppv));
+
+ Assert(m_pUnkOuter);
+
+ hresult = m_pUnkOuter->QueryInterface(riid, ppv);
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::QueryInterface ( %lx ) "
+ "[ %p ]\n", this, hresult, *ppv));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::AddRef
+//
+// Synopsis: delegates AddRef to the controlling IUnknown
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IUnknown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Nov-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDefObject::AddRef( void )
+{
+ ULONG crefs;;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::AddRef ( )\n", this));
+
+ Assert(m_pUnkOuter);
+
+ crefs = m_pUnkOuter->AddRef();
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::AddRef ( %ld ) ", this,
+ crefs));
+
+ return crefs;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::Release
+//
+// Synopsis: delegates Release to the controlling IUnknown
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IUnknown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Nov-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDefObject::Release( void )
+{
+ ULONG crefs;;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Release ( )\n", this));
+
+ Assert(m_pUnkOuter);
+
+ crefs = m_pUnkOuter->Release();
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Release ( %ld ) ", this,
+ crefs));
+
+ return crefs;
+}
+
+/*
+ * IMPLEMENTATION of CDataObjectImpl methods
+ */
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::GetDataDelegate
+//
+// Synopsis: Calls DuCacheDelegate (a glorified QueryInterface)
+// for the IDataObject interface on the def handler's
+// delegate
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: IDataObject *
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 04-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(IDataObject FAR*) CDefObject::GetDataDelegate(void)
+{
+ VDATEHEAP();
+
+ if( IsZombie() )
+ {
+ return NULL;
+ }
+
+ if (m_pDataDelegate) {
+ return m_pDataDelegate;
+ }
+
+ return (IDataObject FAR*)DuCacheDelegate( &m_pUnkDelegate,
+ IID_IDataObject, (LPLPVOID) &m_pDataDelegate,
+ m_pUnkOuter);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::GetData
+//
+// Synopsis: calls IDO->GetData on the cache, if that fails, then the
+// call is delegated
+//
+// Effects: Space for the data is allocated; caller is responsible for
+// freeing.
+//
+// Arguments: [pformatetcIn] -- format of the data to get
+// [pmedium] -- the medium to transmit the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::GetData( LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetData ( %p , %p )\n",
+ this, pformatetcIn, pmedium));
+
+ VDATEPTROUT( pmedium, STGMEDIUM );
+ VDATEREADPTRIN( pformatetcIn, FORMATETC );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+
+ if (!HasValidLINDEX(pformatetcIn))
+ {
+ return DV_E_LINDEX;
+ }
+
+ pmedium->tymed = TYMED_NULL;
+ pmedium->pUnkForRelease = NULL;
+
+ Assert(m_pCOleCache != NULL);
+
+ hresult = m_pCOleCache->m_Data.GetData(pformatetcIn, pmedium);
+
+ if( hresult != NOERROR )
+ {
+ if( IsRunning() && GetDataDelegate() )
+ {
+ hresult = m_pDataDelegate->GetData(pformatetcIn,
+ pmedium);
+ AssertOutStgmedium(hresult, pmedium);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetData ( %lx )\n",
+ this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::GetDataHere
+//
+// Synopsis: Gets data and puts it into the medium specified in pmedium
+//
+// Effects:
+//
+// Arguments: [pformatetcIn] -- the format of the data
+// [pmedium] -- the medium to put the data in
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: Tries the cache first, if that fails, calls GetDataHere
+// on the delegate.
+//
+// History: dd-mmm-yy Author Comment
+// 05-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::GetDataHere( LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE,
+ "%p _IN CDefObject::GetDataHere "
+ "( %p , %p )\n", this, pformatetcIn, pmedium));
+
+ VDATEREADPTRIN( pformatetcIn, FORMATETC );
+ VDATEREADPTRIN( pmedium, STGMEDIUM );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if (!HasValidLINDEX(pformatetcIn))
+ {
+ return DV_E_LINDEX;
+ }
+
+ Assert((m_pCOleCache) != NULL);
+
+ hresult = m_pCOleCache->m_Data.GetDataHere(pformatetcIn,
+ pmedium);
+
+ if( hresult != NOERROR)
+ {
+ if( IsRunning() && GetDataDelegate() )
+ {
+ hresult = m_pDataDelegate->GetDataHere(pformatetcIn,
+ pmedium);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetDataHere "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::QueryGetData
+//
+// Synopsis: Determines whether or not a GetData call with [pformatetcIn]
+// would succeed.
+//
+// Effects:
+//
+// Arguments: [pformatetcIn] -- the format of the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: Tries the cache first, then the delegate.
+//
+// History: dd-mmm-yy Author Comment
+// 05-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::QueryGetData( LPFORMATETC pformatetcIn )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::QueryGetData "
+ "( %p )\n", this, pformatetcIn));
+
+ VDATEREADPTRIN( pformatetcIn, FORMATETC );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if (!HasValidLINDEX(pformatetcIn))
+ {
+ return DV_E_LINDEX;
+ }
+
+ Assert((m_pCOleCache) != NULL);
+
+ hresult = m_pCOleCache->m_Data.QueryGetData(pformatetcIn);
+
+ if( hresult != NOERROR )
+ {
+ if( IsRunning() && GetDataDelegate() )
+ {
+ hresult = m_pDataDelegate->QueryGetData(pformatetcIn);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::QueryGetData "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::GetCanonicalFormatEtc
+//
+// Synopsis: Calls IDO->GetCanonicalFormatEtc on the delegate
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- the reqested format
+// [pformatetcOut] -- the canonical format
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::GetCanonicalFormatEtc( LPFORMATETC pformatetc,
+ LPFORMATETC pformatetcOut)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE,
+ "%p _IN CDefObject::GetCanonicalFormatEtc "
+ "( %p , %p )\n", this, pformatetc, pformatetcOut));
+
+
+ VDATEPTROUT( pformatetcOut, FORMATETC );
+ VDATEREADPTRIN( pformatetc, FORMATETC );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ pformatetcOut->ptd = NULL;
+ pformatetcOut->tymed = TYMED_NULL;
+
+ if (!HasValidLINDEX(pformatetc))
+ {
+ return DV_E_LINDEX;
+ }
+
+ if( IsRunning() && GetDataDelegate() )
+ {
+ hresult = m_pDataDelegate->GetCanonicalFormatEtc( pformatetc,
+ pformatetcOut);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetCanonicalFormatEtc "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::SetData
+//
+// Synopsis: Calls IDO->SetData on the handler's delegate
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- the format of the data
+// [pmedium] -- the data's transmision medium
+// [fRelease] -- if the delegate should release
+// the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::SetData( LPFORMATETC pformatetc,
+ LPSTGMEDIUM pmedium, BOOL fRelease)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SetData "
+ "( %p , %p , %ld )\n", this, pformatetc, pmedium,
+ fRelease));
+
+ VDATEREADPTRIN( pformatetc, FORMATETC );
+ VDATEREADPTRIN( pmedium, STGMEDIUM );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if (!HasValidLINDEX(pformatetc))
+ {
+ return DV_E_LINDEX;
+ }
+
+ if( IsRunning() && GetDataDelegate() )
+ {
+ hresult = m_pDataDelegate->SetData(pformatetc, pmedium,
+ fRelease);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::SetData "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::EnumFormatEtc
+//
+// Synopsis: Enumerates the formats available from an object
+//
+// Effects:
+//
+// Arguments: [dwDirection] -- indicates which set of formats are
+// desired (i.e. those that can be set or
+// those that can be retrieved via GetData)
+// [ppenumFormatEtc] -- where to put the pointer to the
+// enumerator
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: Tries the delegate (if available). If the delegate is
+// is not currently connected (or if it returns OLE_E_USEREG),
+// then we attempt to build the enumerator from the reg database
+//
+// History: dd-mmm-yy Author Comment
+// 05-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::EnumFormatEtc( DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenumFormatEtc)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE,
+ "%p _IN CDefObject::EnumFormatEtc ( %lu , %p )\n", this,
+ dwDirection, ppenumFormatEtc));
+
+ VDATEPTROUT(ppenumFormatEtc, LPVOID);
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ *ppenumFormatEtc = NULL;
+
+ if( IsRunning() && GetDataDelegate() )
+ {
+ hresult = m_pDataDelegate->EnumFormatEtc (dwDirection,
+ ppenumFormatEtc);
+
+ if (!GET_FROM_REGDB(hresult))
+ {
+ LEDebugOut((DEB_TRACE,
+ "%p OUT CDefObject::CDataObject::EnumFormatEtc "
+ "( %lx ) [ %p ]\n", this,
+ hresult, ppenumFormatEtc));
+
+ return hresult;
+ }
+ }
+ // Not running, or object wants to use reg db anyway
+ hresult = OleRegEnumFormatEtc (m_clsidServer, dwDirection,
+ ppenumFormatEtc);
+
+ LEDebugOut((DEB_TRACE,
+ "%p OUT CDefObject::EnumFormatEtc "
+ "( %lx ) [ %p ]\n", this, hresult, ppenumFormatEtc));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::DAdvise
+//
+// Synopsis: Sets up a data advise connection
+//
+// Effects:
+//
+// Arguments: [pFormatetc] -- format to be advise'd on
+// [advf] -- advise flags
+// [pAdvSink] -- advise sink (whom to notify)
+// [pdwConnection] -- where to put the connection ID
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: calls Advise on the DataAdvise cache
+//
+// History: dd-mmm-yy Author Comment
+// 05-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::DAdvise(FORMATETC *pFormatetc, DWORD advf,
+ IAdviseSink * pAdvSink, DWORD * pdwConnection)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::DAdvise "
+ "( %p , %lu , %p , %p )\n", this, pFormatetc, advf,
+ pAdvSink, pdwConnection));
+
+ VDATEREADPTRIN( pFormatetc, FORMATETC );
+ VDATEIFACE( pAdvSink );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ IDataObject * pDataDelegate = NULL;
+
+ if( pdwConnection )
+ {
+ VDATEPTROUT( pdwConnection, DWORD );
+ *pdwConnection = NULL;
+ }
+
+ if( !HasValidLINDEX(pFormatetc) )
+ {
+ return DV_E_LINDEX;
+ }
+
+ if( IsRunning() )
+ {
+ pDataDelegate = GetDataDelegate();
+ }
+
+ // setting up advises' changes state. Don't do this if we
+ // are in a zombie state
+
+ if( IsZombie() == FALSE )
+ {
+ hresult = m_pDataAdvCache->Advise(pDataDelegate, pFormatetc, advf,
+ pAdvSink, pdwConnection);
+ }
+ else
+ {
+ hresult = CO_E_RELEASED;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::DAdvise "
+ "( %lx ) [ %lu ]\n", this, hresult,
+ (pdwConnection) ? *pdwConnection : 0));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::DUnadvise
+//
+// Synopsis: Tears down a data advise connection
+//
+// Effects:
+//
+// Arguments: [dwConnection] -- the advise connection to remove
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: delegates to the DataAdvise cache
+//
+// History: dd-mmm-yy Author Comment
+// 05-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::DUnadvise(DWORD dwConnection)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE,
+ "%p _IN CDefObject::DUnadvise ( %lu )\n", this, dwConnection));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ IDataObject * pDataDelegate = NULL;
+
+ if( IsRunning() )
+ {
+ pDataDelegate = GetDataDelegate();
+ }
+
+ hresult = m_pDataAdvCache->Unadvise(pDataDelegate, dwConnection);
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::DUnadvise "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::EnumDAdvise
+//
+// Synopsis: Enumerates advise connection (delegates to data advise cache)
+//
+// Effects:
+//
+// Arguments: [ppenumAdvise] -- where to put a pointer to the enumerator
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Nov-93 alexgo 32bit port
+//
+// Notes: We do NOT need to stabilize this method, as we make
+// no outgoing calls (EnumAdvise on the data advise cache
+// just allocates an advise enumerator which we implement)
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::EnumDAdvise( LPENUMSTATDATA * ppenumAdvise )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::EnumDAdvise "
+ "( %p )\n", this, ppenumAdvise));
+
+ VDATEPTROUT( ppenumAdvise, LPENUMSTATDATA );
+ *ppenumAdvise = NULL;
+
+ hresult = m_pDataAdvCache->EnumAdvise (ppenumAdvise);
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::EnumDAdvise "
+ "( %lx ) [ %p ]\n", this, hresult, *ppenumAdvise));
+
+ return hresult;
+}
+
+/*
+* IMPLEMENTATION of COleObjectImpl methods
+*
+*/
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::COleObjectImpl::GetOleDelegate
+//
+// Synopsis: Gets the IID_IOleObject interface from the delegate
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: IOleObject *
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(IOleObject FAR*) CDefObject::GetOleDelegate(void)
+{
+ VDATEHEAP();
+
+ if( IsZombie() )
+ {
+ return NULL;
+ }
+
+ return (IOleObject FAR*)DuCacheDelegate(&m_pUnkDelegate,
+ IID_IOleObject, (LPLPVOID) &m_pOleDelegate, m_pUnkOuter);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::COleObjectImpl::SetClientSite
+//
+// Synopsis: Sets the client site for the object
+//
+// Effects:
+//
+// Arguments: [pClientSite] -- pointer to the client site
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: If running, set the client site in the server, if not
+// running (or successfully set the server client site),
+// save it in the handler as well
+//
+// History: dd-mmm-yy Author Comment
+// 05-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::SetClientSite(IOleClientSite * pClientSite)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+ HRESULT hresult;
+ IOleObject * pOleDelegate;
+ BOOL fIsRunning;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SetClientSite "
+ "( %p )\n", this, pClientSite));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ fIsRunning=IsRunning();
+
+ if( (fIsRunning) && (pOleDelegate = GetOleDelegate()) != NULL)
+ {
+
+ #ifdef SERVER_HANDLER
+ // Do not set the client site if serverhandler
+ // and clientsitehandler are available
+ if (CanUseServerHandler() && _pClientSiteHandler)
+ {
+ hresult = NOERROR;
+ }
+ else
+ #endif // SERVER_HANDLER
+ {
+ hresult = pOleDelegate->SetClientSite(pClientSite);
+ }
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+ }
+
+ // we shouldn't set the client site if we are in a zombie state;
+ // it's possible that we're zombied and have already gotten
+ // to the point in our destructor where we release the client
+ // site. Resetting it here would cause an unbalanced addref.
+
+ if( IsZombie() == FALSE )
+ {
+ BOOL fLockedContainer = m_flags & DH_LOCKED_CONTAINER;
+
+ fIsRunning=IsRunning(); // I am chicken, maybe running state has changed!
+
+ hresult = DuSetClientSite(fIsRunning, pClientSite,
+ &m_pAppClientSite, &fLockedContainer);
+
+ if( fLockedContainer )
+ {
+ m_flags |= DH_LOCKED_CONTAINER;
+ }
+ else
+ {
+ m_flags &= ~DH_LOCKED_CONTAINER;
+ }
+
+ #ifdef SERVER_HANDLER
+ if (CanUseServerHandler() && _pClientSiteHandler)
+ {
+ HdlDebugOut((DEB_CLIENTHANDLER, "%p _IN CClientSiteHandler::SetClientSiteDelegate\n", this, m_pAppClientSite));
+ _pClientSiteHandler->SetClientSiteDelegate(ID_ClientSite, m_pAppClientSite);
+ }
+ #endif // SERVER_HANDLER
+
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::SetClientSite "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::GetClientSite
+//
+// Synopsis: returns the client site of the object
+//
+// Effects:
+//
+// Arguments: [ppClientSite] -- where to put the client site pointer
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Nov-93 alexgo 32bit port
+//
+// Notes: We do NOT need to stabilize this call. The client
+// site addref should simply addref the client site on this
+// thread.
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::GetClientSite( IOleClientSite ** ppClientSite)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetClientSite "
+ "( %p )\n", this, ppClientSite));
+
+ VDATEPTROUT(ppClientSite, IOleClientSite *);
+
+ *ppClientSite = m_pAppClientSite;
+ if( *ppClientSite )
+ {
+ (*ppClientSite)->AddRef();
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetClientSite "
+ "( %lx ) [ %p ]\n", this, NOERROR, *ppClientSite));
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::SetHostNames
+//
+// Synopsis: Sets the name that may appear in an object's window
+//
+// Effects: Turns the strings into atoms
+//
+// Arguments: [szContainerApp] -- name of the container
+// [szContainerObj] -- name of the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: turns the strings into atoms, calls IOO->SetHostNames
+// on the delegate
+//
+// History: dd-mmm-yy Author Comment
+// 05-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::SetHostNames( LPCOLESTR szContainerApp,
+ LPCOLESTR szContainerObj)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+
+ HRESULT hresult = NOERROR;
+ OLECHAR szNull[] = OLESTR("");
+ DWORD cbApp, cbObj;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SetHostNames "
+ "( \"%ws\" , \"%ws\" )\n", this, szContainerApp,
+ szContainerObj));
+
+ VDATEPTRIN( (LPVOID)szContainerApp, char );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( (m_flags & DH_STATIC) )
+ {
+ hresult = OLE_E_STATIC;
+ goto errRtn;
+ }
+
+ // Make sure both arguments point to a valid string; this
+ // simplifies the code that follows.
+ if (!szContainerApp)
+ {
+ szContainerApp = szNull;
+ }
+ if (!szContainerObj)
+ {
+ szContainerObj = szNull;
+ }
+
+ cbApp = (_xstrlen(szContainerApp) + 1) * sizeof(OLECHAR);
+ cbObj = (_xstrlen(szContainerObj) + 1) * sizeof(OLECHAR);
+ m_ibCntrObj = cbApp;
+
+ if (m_pHostNames)
+ {
+ PrivMemFree(m_pHostNames);
+ }
+
+ m_pHostNames = (char *)PrivMemAlloc(cbApp+cbObj);
+
+ // Store the two strings in the m_pHostNames pointer.
+ if (m_pHostNames)
+ {
+ memcpy(m_pHostNames, szContainerApp, cbApp);
+ memcpy(m_pHostNames + cbApp, szContainerObj, cbObj);
+ }
+
+ if( IsRunning() && GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->SetHostNames(szContainerApp,
+ szContainerObj);
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::SetHostNames "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::Close
+//
+// Synopsis: calls IOO->Close on the delegate and does misc. cleanup
+// in the handler
+//
+// Effects:
+//
+// Arguments: [dwFlags] -- closing flags
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::Close( DWORD dwFlags )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult = NOERROR;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Close "
+ "( %lu )\n", this, dwFlags));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ // NOTE: if server died, ISRUNNING cleans up (a bit) and returns FALSE.
+
+ if(IsRunning() )
+ {
+
+ // We need an AddRef/Release bracket because calling Close on
+ // the delegate can cause the DefHandler (used an an
+ // Emdedding helper) to be released and go away. This would
+ // cause us to crash when we reference m_pDefObject when we
+ // call STOP. Bug 3819.
+ m_pUnkOuter->AddRef();
+ if( GetOleDelegate() )
+ {
+ #ifdef SERVER_HANDLER
+ if (CanUseServerHandler())
+ {
+ if ((hresult = SrvCloseAndRelease(dwFlags)) != NOERROR)
+ {
+ m_pUnkOuter->Release();
+ goto errRtn;
+ }
+
+ }
+ else
+ #endif // SERVER_HANDLER
+ if (FAILED(hresult = m_pOleDelegate->Close(dwFlags)))
+ {
+ m_pUnkOuter->Release();
+ goto errRtn;
+ }
+ }
+
+ if (dwFlags == OLECLOSE_NOSAVE) {
+ // Discard in memory data of the presentation caches.
+ // Next time when they are needed, they will loaded
+ // from storage.
+ m_pCOleCache->DiscardCache(DISCARDCACHE_NOSAVE);
+ }
+
+ // always do stop here; prevents problems if server doesn't
+ // send OnClose (later OnClose will detect (!IsRunning())
+ // and do nothing).
+ Stop();
+
+ m_pUnkOuter->Release();
+ }
+ else
+ {
+ BOOL fLockedContainer;
+
+ if (dwFlags != OLECLOSE_NOSAVE)
+ {
+ AssertSz(dwFlags == OLECLOSE_SAVEIFDIRTY,
+ "OLECLOSE_PROMPTSAVE is inappropriate\n");
+ if( IsDirty() == NOERROR )
+ {
+ if( m_pAppClientSite )
+ {
+ hresult = m_pAppClientSite->SaveObject();
+ if (hresult != NOERROR)
+ {
+ goto errRtn;
+ }
+ }
+ }
+ }
+
+ // server is not running; if container still locked, unlock
+ // now. ISRUNNING normally does much simpler cleanup;
+ // if ISRUNNING unlocks the container, this should be removed.
+
+ fLockedContainer = m_flags & DH_LOCKED_CONTAINER;
+ m_flags &= ~DH_LOCKED_CONTAINER;
+
+ DuLockContainer(m_pAppClientSite, FALSE, &fLockedContainer);
+
+ // this is not an error since the app is closed
+ // hresult is == NOERROR;
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Close "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::SetMoniker
+//
+// Synopsis: Gives a moniker to the embedding (usually called by the
+// container)
+//
+// Effects:
+//
+// Arguments: [dwWhichMoniker] -- flags to indicate the type of
+// moniker
+// [pmk] -- the moniker
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: delegates to the server object
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::SetMoniker( DWORD dwWhichMoniker, LPMONIKER pmk )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult = NOERROR;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SetMoniker "
+ "( %lu , %p )\n", this, dwWhichMoniker, pmk));
+
+ VDATEIFACE( pmk );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+
+ if( IsRunning() && GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->SetMoniker(dwWhichMoniker, pmk);
+ }
+ // else case: return NOERROR
+ // this is not an error since we will call SetMoniker in Run().
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::COleObjectImpl::SetMoniker "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::COleObjectImpl::GetMoniker
+//
+// Synopsis: Calls the client site to get the object's moniker
+//
+// Effects:
+//
+// Arguments: [dwAssign] -- controls whether a moniker should be
+// assigned if not already present
+// [dwWhichMoniker] -- the moniker type to get
+// [ppmk] -- where to put a pointer to the moniker
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::GetMoniker( DWORD dwAssign, DWORD dwWhichMoniker,
+ LPMONIKER FAR* ppmk)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetMoniker "
+ "( %lu , %lu , %p )\n", this, dwAssign,
+ dwWhichMoniker, ppmk));
+
+ VDATEPTROUT( ppmk, LPMONIKER );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ *ppmk = NULL;
+
+ // the moniker is always accessible via the client site
+ if( m_pAppClientSite)
+ {
+ hresult = m_pAppClientSite->GetMoniker(dwAssign,
+ dwWhichMoniker, ppmk);
+ }
+ else
+ {
+ // not running and no client site
+ hresult = E_UNSPEC;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetMoniker "
+ "( %lx ) [ %p ]\n", this, hresult, *ppmk));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::InitFromData
+//
+// Synopsis: Initializes the object from the data in [pDataObject]
+//
+// Effects:
+//
+// Arguments: [pDataObject] -- the data
+// [fCreation] -- TRUE on creation, FALSE for data transfer
+// [dwReserved] -- unused
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: delegates to the server
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::InitFromData(LPDATAOBJECT pDataObject,
+ BOOL fCreation, DWORD dwReserved)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::InitFromData "
+ "( %p , %ld , %lu )\n", this, pDataObject,
+ fCreation, dwReserved ));
+
+ if( pDataObject )
+ {
+ VDATEIFACE(pDataObject);
+ }
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( IsRunning() && GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->InitFromData(pDataObject,
+ fCreation, dwReserved);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::InitFromData "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::GetClipboardData
+//
+// Synopsis: Retrieves a data object that could be passed to the clipboard
+//
+// Effects:
+//
+// Arguments: [dwReserverd] -- unused
+// [ppDataObject] -- where to put the pointer to the data object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: delegates to the server
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::GetClipboardData( DWORD dwReserved,
+ LPDATAOBJECT * ppDataObject)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE,
+ "%p _IN CDefObject::GetClipboardData "
+ "( %lu , %p )\n", this, dwReserved, ppDataObject));
+
+ VDATEPTROUT( ppDataObject, LPDATAOBJECT );
+
+ CStabilize stabilize((CSafeRefCount*)this);
+
+ *ppDataObject = NULL;
+
+ if( IsRunning() && GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->GetClipboardData (dwReserved,
+ ppDataObject);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetClipboardData "
+ "( %lx ) [ %p ]\n", this, hresult, *ppDataObject));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::DoVerb
+//
+// Synopsis: Calls a verb on the object (such as Edit)
+//
+// Effects: The object may launch its app, go in place, etc
+//
+// Arguments: [iVerb] -- the verb number
+// [lpmsg] -- the windows message that caused the verb
+// to be invoked
+// [pActiveSite] -- the client site in which the verb was
+// invoked
+// [lindex] -- reserved
+// [hwndParent] -- the document window (containing the object)
+// [lprcPosRect] -- the object's bounding rectangle
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: delegates to the server (launching it if necessary)
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::DoVerb( LONG iVerb, LPMSG lpmsg,
+ LPOLECLIENTSITE pActiveSite, LONG lindex,
+ HWND hwndParent, const RECT * lprcPosRect)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ BOOL bStartedNow = FALSE;
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::DoVerb "
+ "( %ld , %p , %p , %ld , %lx , %p )\n", this,
+ iVerb, lpmsg, pActiveSite, lindex, hwndParent, lprcPosRect));
+
+
+ if( lpmsg )
+ {
+ VDATEPTRIN( lpmsg, MSG );
+ }
+
+ if (pActiveSite)
+ {
+ VDATEIFACE( pActiveSite );
+ }
+
+ if( lprcPosRect )
+ {
+ VDATEPTRIN(lprcPosRect, RECT);
+ }
+
+ CStabilize stabilize((CSafeRefCount*)this);
+
+ if (lindex != 0 && lindex != -1)
+ {
+ hresult = DV_E_LINDEX;
+ goto errRtn;
+ }
+
+ if (!IsRunning())
+ {
+ if( FAILED(hresult = Run(NULL)) )
+ {
+ goto errRtn;
+ }
+ bStartedNow = TRUE;
+ }
+
+#ifdef SERVER_HANDLER
+ if (CanUseServerHandler())
+ {
+ hresult = SrvDoVerb(iVerb, lpmsg, pActiveSite, lindex, hwndParent, lprcPosRect);
+ }
+ else
+#endif
+ {
+ if( !GetOleDelegate() )
+ {
+ hresult = E_NOINTERFACE;
+ }
+ else
+ {
+ hresult = m_pOleDelegate->DoVerb(iVerb, lpmsg, pActiveSite,
+ lindex, hwndParent, lprcPosRect);
+ }
+ }
+
+ if (FAILED(hresult) && bStartedNow)
+ {
+ Close(OLECLOSE_NOSAVE);
+ }
+
+errRtn:
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::DoVerb "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::EnumVerbs
+//
+// Synopsis: Enumerates the verbs that an object supports
+//
+// Effects:
+//
+// Arguments: [ppenumOleVerb] -- where to put the verb enumerator
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: delegates to the cache (if running), otherwise looks it up
+// in the registration database
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::EnumVerbs( IEnumOLEVERB ** ppenumOleVerb)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::EnumVerbs "
+ "( %p )\n", this, ppenumOleVerb));
+
+ VDATEPTROUT( ppenumOleVerb, IEnumOLEVERB FAR );
+
+ CStabilize stabilize((CSafeRefCount*)this);
+
+ *ppenumOleVerb = NULL;
+
+ if( IsRunning() && GetOleDelegate() )
+ {
+
+ hresult = m_pOleDelegate->EnumVerbs (ppenumOleVerb);
+
+ if (!GET_FROM_REGDB(hresult))
+ {
+ goto errRtn;
+ }
+ }
+ // Not running, or object deferred to us, so interrogate reg db
+ hresult = OleRegEnumVerbs( m_clsidServer, ppenumOleVerb);
+
+errRtn:
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::EnumVerbs "
+ "( %lx ) [ %p ]\n", this, hresult, *ppenumOleVerb));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::Update
+//
+// Synopsis: Brings any caches or views up-to-date
+//
+// Effects: may launch the server (if not already running)
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: delegates to the server, launching it if it is not
+// already running
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::Update( void )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ BOOL bStartedNow = FALSE;
+ HRESULT hresult = NOERROR;
+ HRESULT hrLock;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Update ( )\n", this ));
+
+ CStabilize stabilize((CSafeRefCount*)this);
+
+ if( (m_flags & DH_STATIC) )
+ {
+ hresult = OLE_E_STATIC;
+ goto errRtn;
+ }
+
+ if (!IsRunning())
+ {
+ if( FAILED(hresult = Run(NULL)))
+ {
+ goto errRtn;
+ }
+ bStartedNow = TRUE;
+ }
+
+ // as a convenience to the server, we make the connection strong
+ // for the duration of the update; thus, if lock container (of
+ // embedings of this server) is done with co lock obj external,
+ // nothing special need be done.
+ hrLock = LockRunning(TRUE, FALSE);
+
+ if( GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->Update();
+ }
+
+ if (hresult == NOERROR)
+ {
+ m_flags &= ~DH_INIT_NEW;
+
+ if (bStartedNow)
+ {
+ hresult = m_pCOleCache->UpdateCache(
+ GetDataDelegate(),
+ UPDFCACHE_ALLBUTNODATACACHE,
+ NULL);
+ }
+ else
+ {
+ // already running...
+ // normal caches would have got updated as a result
+ // of SendOnDataChange of the object.
+ hresult = m_pCOleCache->UpdateCache(
+ GetDataDelegate(),
+ UPDFCACHE_IFBLANKORONSAVECACHE,
+ NULL);
+ }
+ }
+
+ // balance lock above; do not release on last unlock; i.e., siliently
+ // restore to the state before this routine was called.
+ if( hrLock == NOERROR )
+ {
+ LockRunning(FALSE, FALSE);
+ }
+
+ if( bStartedNow )
+ {
+ Close(OLECLOSE_SAVEIFDIRTY);
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Update "
+ "( %lx )\n", this, hresult ));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::IsUpToDate
+//
+// Synopsis: returns whether or not the embedding is up-to-date
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HRESULT (NOERROR == is up to date)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: delegates to the server if it is running
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::IsUpToDate(void)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::IsUpToDate ( )\n", this));
+
+ CStabilize stabilize((CSafeRefCount*)this);
+
+ if( (m_flags & DH_STATIC) )
+ {
+ hresult = NOERROR;
+ }
+ else if( IsRunning() && GetOleDelegate() )
+ {
+ // if running currently, propogate call; else fail
+ hresult = m_pOleDelegate->IsUpToDate();
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::IsUpToDate "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::SetExtent
+//
+// Synopsis: Set's the size boundaries on an object
+//
+// Effects:
+//
+// Arguments: [dwDrawAspect] -- the drawing aspect (such as ICON, etc)
+// [lpsizel] -- the new size (in HIMETRIC)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: delegates to the server if running
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::SetExtent( DWORD dwDrawAspect, LPSIZEL lpsizel )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SetExtent "
+ "( %lu , %p )\n", this, dwDrawAspect, lpsizel));
+
+ VDATEPTRIN( lpsizel, SIZEL );
+
+ CStabilize stabilize((CSafeRefCount*)this);
+
+
+ if( (m_flags & DH_STATIC) )
+ {
+ hresult = OLE_E_STATIC;
+ }
+ else if( IsRunning() && GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->SetExtent(dwDrawAspect, lpsizel);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::SetExtent "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::GetExtent
+//
+// Synopsis: Retrieve the size of the object
+//
+// Effects:
+//
+// Arguments: [dwDrawAspect] -- the drawing aspect (such as icon)
+// [lpsizel] -- where to put the size
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Tries the server first, the the cache if that fails
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes: Hacks for bogus WordArt2.0 app.
+// REVIEW32: We may want to take them out for 32bit
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::GetExtent( DWORD dwDrawAspect, LPSIZEL lpsizel )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ VDATEPTROUT(lpsizel, SIZEL);
+
+ HRESULT hresult = NOERROR;
+ BOOL fNoDelegate = TRUE;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetExtent "
+ "( %lu , %p )\n", this, dwDrawAspect, lpsizel));
+
+ CStabilize stabilize((CSafeRefCount*)this);
+
+ lpsizel->cx = 0;
+ lpsizel->cy = 0;
+
+ // if server is running try to get extents from the server
+ if( IsRunning() && GetOleDelegate() )
+ {
+ fNoDelegate = FALSE;
+ hresult = m_pOleDelegate->GetExtent(dwDrawAspect, lpsizel);
+ }
+
+ // if there is error or object is not running or WordArt2 returns zero
+ // extents, then get extents from Cache
+ if (hresult != NOERROR || fNoDelegate || (0==lpsizel->cx &&
+ 0==lpsizel->cy))
+ {
+ // Otherwise try to get extents from cache
+ Assert(m_pCOleCache != NULL);
+ hresult = m_pCOleCache->GetExtent(dwDrawAspect,
+ lpsizel);
+ }
+
+ // WordArt2.0 is giving negative extents!!
+ if (SUCCEEDED(hresult)) {
+ lpsizel->cx = LONG_ABS(lpsizel->cx);
+ lpsizel->cy = LONG_ABS(lpsizel->cy);
+ }
+
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetExtent "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::Advise
+//
+// Synopsis: Sets up an advise connection for things like close, save,
+// rename, etc.
+//
+// Effects: Creates an OleAdviseHolder
+//
+// Arguments: [pAdvSink] -- whom to advise
+// [pdwConnection] -- where to put the connection ID
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: delegates to the server and creates a an OleAdviseHolder
+// if one doesn't already exist
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::Advise(IAdviseSink *pAdvSink, DWORD *pdwConnection)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Advise "
+ "( %p , %p )\n", this, pAdvSink, pdwConnection));
+
+ VDATEIFACE( pAdvSink );
+ VDATEPTROUT( pdwConnection, DWORD );
+
+ CStabilize stabilize((CSafeRefCount*)this);
+
+ *pdwConnection = NULL;
+
+ if( (m_flags & DH_STATIC) )
+ {
+ hresult = OLE_E_STATIC;
+ goto errRtn;
+ }
+
+
+ // if defhndlr got running without going through run, setup advise.
+ // The call to run (via ProxyMgr::Connect) always comes before any
+ // other method call in the default handler. Thus it is safe to
+ // assume that there is no earlier point by which this advise (or any
+ // other of the calls) should have been done.
+ if( IsRunning() && m_dwConnOle == 0L && GetOleDelegate() )
+ {
+ if( IsZombie() )
+ {
+ hresult = CO_E_RELEASED;
+ goto errRtn;
+ }
+
+ // delegate to the server
+ hresult = m_pOleDelegate->Advise((IAdviseSink *)&m_AdviseSink,
+ &m_dwConnOle);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+ }
+
+ // if we are in a zombie state, we shouldn't go allocate more
+ // memory.
+
+ if( IsZombie() )
+ {
+ hresult = CO_E_RELEASED;
+ }
+
+ if( m_pOAHolder == NULL )
+ {
+ hresult = CreateOleAdviseHolder((IOleAdviseHolder **)&m_pOAHolder);
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+ }
+
+ // stuff the advise notification in our advise holder
+ hresult = m_pOAHolder->Advise(pAdvSink, pdwConnection);
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Advise "
+ "( %lx ) [ %lu ]\n", this, hresult,
+ (pdwConnection)? *pdwConnection : 0));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::COleObjectImpl::Unadvise
+//
+// Synopsis: Tears down an advise connection
+//
+// Effects:
+//
+// Arguments: [dwConnection] -- the connection to destroy
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::Unadvise(DWORD dwConnection)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Unadvise "
+ "( %lu )\n", this, dwConnection));
+
+ CStabilize stabilize((CSafeRefCount*)this);
+
+ if( m_pOAHolder == NULL )
+ {
+ // no one registered
+ hresult = OLE_E_NOCONNECTION;
+ }
+ else
+ {
+ hresult = m_pOAHolder->Unadvise(dwConnection);
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Unadvise "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::EnumAdvise
+//
+// Synopsis: Enumerate the advises currently established
+//
+// Effects:
+//
+// Arguments: [ppenumAdvise] -- where to put the advise enumerator
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes: We do NOT need to stabilize because EnumAdvise only
+// allocates some memory for an enumerator and returns.
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::EnumAdvise( LPENUMSTATDATA *ppenumAdvise )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::EnumAdvise "
+ "( *p )\n", this, ppenumAdvise));
+
+ VDATEPTROUT( ppenumAdvise, LPENUMSTATDATA );
+ *ppenumAdvise = NULL;
+
+ if( m_pOAHolder == NULL )
+ {
+ // no one registered
+ hresult = E_UNSPEC;
+ }
+ else
+ {
+ hresult = m_pOAHolder->EnumAdvise(ppenumAdvise);
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::EnumAdvise "
+ "( %lx ) [ %p ]\n", this, hresult, *ppenumAdvise));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::GetMiscStatus
+//
+// Synopsis: Get misc status bits, such as OLEMISC_ONLYICONIC
+//
+// Effects:
+//
+// Arguments: [dwAspect] -- the drawing aspect we're concerned about
+// [pdwStatus] -- where to put the status bits
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Delegates to the server. If not there, or if it returns
+// OLE_E_USEREG, then lookup in the registration database
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::GetMiscStatus( DWORD dwAspect, DWORD *pdwStatus)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetMiscStatus "
+ "( %lu , %p )\n", this, dwAspect, pdwStatus));
+
+ VDATEPTROUT(pdwStatus, DWORD);
+
+ CStabilize stabilize((CSafeRefCount*)this);
+
+
+ if( IsRunning() && GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->GetMiscStatus(dwAspect, pdwStatus);
+
+ if (!GET_FROM_REGDB(hresult))
+ {
+ goto errRtn;
+ }
+ }
+
+ // Not running or object wants us to use reg db.
+ hresult = OleRegGetMiscStatus (m_clsidServer, dwAspect, pdwStatus);
+
+ if (hresult == NOERROR)
+ {
+ if( (m_flags & DH_STATIC) )
+ {
+ (*pdwStatus) |= (OLEMISC_STATIC |
+ OLEMISC_CANTLINKINSIDE);
+ }
+ else if( CoIsOle1Class(m_clsidServer) )
+ {
+ (*pdwStatus) |= OLEMISC_CANTLINKINSIDE;
+ }
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetMiscStatus "
+ "( %lx ) [ %lx ]\n", this, hresult, *pdwStatus));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::SetColorScheme
+//
+// Synopsis: Sets the palette for an object
+//
+// Effects:
+//
+// Arguments: [lpLogpal] -- the palette
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Delegates to the server
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::SetColorScheme( LPLOGPALETTE lpLogpal )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SetColorScheme "
+ "( %p )\n", this, lpLogpal));
+
+ CStabilize stabilize((CSafeRefCount*)this);
+
+ if( (m_flags & DH_STATIC) )
+ {
+ hresult = OLE_E_STATIC;
+ }
+ else if( lpLogpal == NULL || lpLogpal->palNumEntries == NULL)
+ {
+ hresult = E_INVALIDARG;
+ }
+ else if( IsRunning() && GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->SetColorScheme (lpLogpal);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::SetColorScheme "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::GetUserClassID
+//
+// Synopsis: Retrieves the class ID for the object
+//
+// Effects:
+//
+// Arguments: [pClassID] -- where to put the class ID
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Delegates to the server, or if not running (or if it
+// fails the delegated call), then we attempt
+// to get the class id from the storage.
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::GetUserClassID( CLSID *pClassID )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetUserClassID "
+ "( %p )\n", this, pClassID));
+
+ VDATEPTROUT(pClassID, CLSID);
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+
+ if( IsRunning() )
+ {
+#ifdef SERVER_HANDLER
+ if ( CanUseServerHandler() )
+ {
+ // the userclassid was obtained on the RunAndInitialize call
+ *pClassID = m_clsidUser;
+ hresult = NOERROR;
+ goto errRtn;
+
+ }
+ else
+#endif // SERVER_HANDLER
+ if ( GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->GetUserClassID(pClassID);
+ // success! We don't have to figure it out ourselves, so
+ // skip to the end and exit
+ if (hresult == NOERROR )
+ {
+ goto errRtn;
+ }
+ }
+ }
+
+ if( !IsEqualCLSID(m_clsidServer, CLSID_NULL) )
+ {
+ *pClassID = m_clsidServer;
+ hresult = NOERROR;
+ }
+ else
+ {
+ hresult = GetClassBits(pClassID);
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetUserClassID "
+ "( %lx ) [ %p ]\n", this, hresult, pClassID));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::GetUserType
+//
+// Synopsis: Gets a descriptive string about the object for the user
+//
+// Effects:
+//
+// Arguments: [dwFromOfType] -- whether to get a short/long/etc version
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Delegates to the server, failing that, trys the registration
+// database, failing that, tries to read from the storage
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::GetUserType( DWORD dwFormOfType,
+ LPOLESTR *ppszUserType)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetUserType "
+ "( %lu , %p )\n", this, dwFormOfType, ppszUserType));
+
+ VDATEPTROUT(ppszUserType, LPOLESTR);
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ *ppszUserType = NULL;
+
+ if( IsRunning() && GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->GetUserType (dwFormOfType,
+ ppszUserType);
+
+ if (!GET_FROM_REGDB(hresult))
+ {
+ goto errRtn;
+ }
+ }
+
+ if( (hresult = OleRegGetUserType( m_clsidServer, dwFormOfType,
+ ppszUserType)) == NOERROR)
+ {
+ goto errRtn;
+ }
+
+
+ // Try reading from storage
+ // This really ugly bit of 16bit code tries to read the user type
+ // from the storage. If that fails, then we look in the registry
+
+ if( NULL == m_pStg ||
+ NOERROR != (hresult = ReadFmtUserTypeStg(m_pStg, NULL, ppszUserType)) ||
+ NULL == *ppszUserType )
+ {
+ OLECHAR sz[256];
+ long cb = sizeof(sz);// ReqQueryValue expects
+ // a *byte* count
+ *ppszUserType = UtDupString (
+ (ERROR_SUCCESS ==
+ RegQueryValue (HKEY_CLASSES_ROOT,
+ OLESTR("Software\\Microsoft\\OLE2\\UnknownUserType"),
+ sz, &cb))
+ ? (LPCOLESTR)sz : OLESTR("Unknown"));
+
+ if (NULL != *ppszUserType)
+ {
+ hresult = NOERROR;
+ }
+ else
+ {
+ hresult = E_OUTOFMEMORY;
+ }
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetUserType "
+ "( %lx ) [ %p ]\n", this, hresult, *ppszUserType));
+
+
+ return hresult;
+}
+
+/*
+* IMPLEMENTATION of CROImpl methods
+*
+* BUGBUG: REVIEW32: We never delegate to the server (if it implements
+* IRunnableObject). Perhaps we should do this (so they could
+* do some special behavior?)
+*/
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::GetRunningClass
+//
+// Synopsis: Get the class id of the server
+//
+// Effects:
+//
+// Arguments: [lpClsid] -- where to put the class id
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IRunnableObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes: We do not need to stabilize this call as no outgoing
+// calls are made.
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::GetRunningClass(LPCLSID lpClsid)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetRunningClass "
+ "( %p )\n", this, lpClsid));
+
+ VDATEPTROUT(lpClsid, CLSID);
+
+ *lpClsid = m_clsidServer;
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetRunningClass "
+ "( %lx ) [ %p ]\n", this, NOERROR, lpClsid));
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::Run
+//
+// Synopsis: Sets the object running (if it isn't already)
+//
+// Effects: may launch the server
+//
+// Arguments: [pbc] -- the bind context (unused)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IRunnableObject
+//
+// Algorithm: If already running, return. Otherwise, get the proxy
+// manager to create the server. Initialize the storage
+// and caches, and set the host name for the server's window.
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+STDMETHODIMP CDefObject::Run(LPBINDCTX pbc)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+ IDataObject FAR* pDataDelegate;
+ IOleObject FAR* pOleDelegate;
+ IPersistStorage FAR* pPStgDelegate;
+ IMoniker FAR* pmk = NULL;
+ BOOL fLockedContainer;
+
+ // NOTE: ignore pbc for now
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Run ( %p )\n", this, pbc));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+
+ m_fIsMaybeRunning = TRUE; // let's set this to be safe
+ if( IsRunning() )
+ {
+ hresult = S_OK;
+ // just return the error code
+ goto errRtn2;
+ }
+ m_fIsMaybeRunning = TRUE; // by end of this fcn, we might be running
+
+
+ if( (m_flags & DH_STATIC) )
+ {
+ hresult = OLE_E_STATIC;
+ goto errRtn2;
+ }
+
+
+ if( IsZombie() )
+ {
+ hresult = CO_E_RELEASED;
+ goto errRtn2;
+ }
+
+ if( FAILED(hresult = CreateDelegate()) )
+ {
+ // just return the error code
+ goto errRtn2;
+ }
+
+ if (m_pProxyMgr != NULL)
+ {
+ #ifdef SERVER_HANDLER
+ if (CanUseServerHandler())
+ {
+ // create object talking to the server hander
+ if( SUCCEEDED(hresult = SrvInitialize()) )
+ {
+ if( SUCCEEDED(hresult = SrvRun()) )
+ {
+ // done - nothing more to do here
+ goto errRtn2;
+ }
+ // SrvRun failed - release the serverhandler
+ // and try to execute the run steps the usual way
+ if (NULL != _pSrvHndlr)
+ {
+ HdlDebugOut((DEB_SERVERHANDLER, "Failed to Create Server Handler\n"));
+ SafeReleaseAndNULL((IUnknown **)&_pSrvHndlr);
+ }
+ _dwServerHandler = _dwClientSiteHandler = 0;
+ }
+ }
+ #endif // SERVER_HANDLER
+
+ if ( FAILED(hresult = m_pProxyMgr->CreateServer(m_clsidServer,
+ CLSCTX_LOCAL_SERVER,
+ NULL)))
+ {
+ // just return the error code
+ goto errRtn2;
+ }
+ }
+
+
+ // NOTE: the lock state of the proxy mgr is not changed; it remembers
+ // the state and sets up the connection correctly.
+
+ // server is running; normally this coincides with locking the
+ // container, but we keep a separate flag since locking the container
+ // may fail.
+
+ m_flags |= DH_FORCED_RUNNING;
+
+
+ // Lock the container
+
+ fLockedContainer = m_flags & DH_LOCKED_CONTAINER;
+
+ DuLockContainer(m_pAppClientSite, TRUE, &fLockedContainer );
+
+ if( fLockedContainer )
+ {
+ m_flags |= DH_LOCKED_CONTAINER;
+ }
+ else
+ {
+ m_flags &= ~DH_LOCKED_CONTAINER;
+ }
+
+
+ if( pPStgDelegate = GetPSDelegate() )
+ {
+ if( m_pStg)
+ {
+ if( (m_flags & DH_INIT_NEW) )
+ {
+ hresult = pPStgDelegate->InitNew(m_pStg);
+ }
+ else
+ {
+ hresult = pPStgDelegate->Load(m_pStg);
+ }
+ if (hresult != NOERROR)
+ {
+ // this will cause us to stop the
+ // the server we just launced
+ goto errRtn;
+ }
+ }
+ }
+
+ if( pDataDelegate = GetDataDelegate() )
+ {
+ // inform cache that we are running
+ Assert(m_pCOleCache != NULL);
+
+ m_pCOleCache->OnRun(pDataDelegate);
+
+ // Enumerate all the advises we stored while we were either not
+ // running or running the previous time, and send them to the
+ // now-running object.
+ m_pDataAdvCache->EnumAndAdvise(pDataDelegate, TRUE);
+ }
+
+ if( pOleDelegate = GetOleDelegate() )
+ {
+ // REVIEW MM1: what are we supposed to do in case of failure
+ if( m_pAppClientSite )
+ {
+ pOleDelegate->SetClientSite(m_pAppClientSite);
+ }
+
+ if (m_pHostNames)
+ {
+ if (hresult = pOleDelegate->SetHostNames((LPOLESTR)m_pHostNames,
+ (LPOLESTR)(m_pHostNames + m_ibCntrObj))
+ != NOERROR)
+ {
+ goto errRtn;
+ }
+ }
+
+ // set single ole advise (we multiplex)
+ Assert(m_dwConnOle == 0L);
+
+ if ((hresult = pOleDelegate->Advise((IAdviseSink *)&m_AdviseSink,
+ &m_dwConnOle)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if( m_pAppClientSite != NULL &&
+ m_pAppClientSite->GetMoniker
+ (OLEGETMONIKER_ONLYIFTHERE,
+ OLEWHICHMK_OBJREL, &pmk) == NOERROR)
+ {
+ AssertOutPtrIface(NOERROR, pmk);
+ pOleDelegate->SetMoniker(OLEWHICHMK_OBJREL, pmk);
+ pmk->Release();
+ }
+ }
+
+errRtn:
+ if (hresult != NOERROR)
+ {
+ Stop();
+
+ // if for some reason we did not unlock the container by now,
+ // do it (e.g., app crashed or failed during InitNew).
+
+ fLockedContainer = (m_flags & DH_LOCKED_CONTAINER);
+ m_flags &= ~DH_LOCKED_CONTAINER;
+
+ DuLockContainer(m_pAppClientSite, FALSE, &fLockedContainer );
+
+ }
+
+errRtn2:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Run "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::Stop
+//
+// Synopsis: Undoes some of Run() (stops the server)...internal function
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: unadvise connections (if any), stop the cache, disconnect
+// from the proxy manager and unlock the container
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+// undo effects of Run(); some of this work is done also in IsRunning
+// when we detect we are not running (in case the server crashed).
+//--------------------------------------------------------------------------
+
+INTERNAL CDefObject::Stop (void)
+{
+ BOOL fLockedContainer;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefObject::CROImpl::Stop "
+ "( )\n", this));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ m_fIsMaybeRunning = TRUE; // set this just to be safe
+ if( !IsRunning() )
+ {
+ // NOTE: ISRUNNING below does some of this cleanup
+ goto errRtn; // return NOERROR
+ }
+
+ // NOTE: we cleanup connections which point directly back to us;
+ // connections which point back to the app (e.g, the clientsite and
+ // data advise) are left alone; an app must know how to use
+ // CoDisconnectObject if deterministic shutdown is desired.
+ if( m_dwConnOle != 0L && GetOleDelegate() )
+ {
+ m_pOleDelegate->Unadvise(m_dwConnOle);
+ m_dwConnOle = 0L;
+ }
+
+ if( m_pDataDelegate )
+ {
+ m_pDataAdvCache->EnumAndAdvise(m_pDataDelegate, FALSE);
+ }
+
+ // inform cache that we are not running (Undoes advise)
+ Assert(m_pCOleCache != NULL);
+ m_pCOleCache->OnStop();
+
+ // if no proxymgr, no need to disconnect
+ if( m_pProxyMgr != NULL )
+ {
+ m_pProxyMgr->Disconnect();
+ }
+
+ // make sure unlocked if we locked it
+ // guard against disappearance
+ m_pUnkOuter->AddRef();
+
+ fLockedContainer = (m_flags & DH_LOCKED_CONTAINER);
+ m_flags &= ~DH_LOCKED_CONTAINER;
+
+ DuLockContainer(m_pAppClientSite, FALSE, &fLockedContainer);
+
+ // known not running
+ m_flags &= ~ DH_FORCED_RUNNING;
+
+
+ m_pUnkOuter->Release();
+
+errRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefObject::Stop "
+ "( %lx )\n", this, NOERROR ));
+
+ m_fIsMaybeRunning = FALSE;
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::IsRunning
+//
+// Synopsis: Returns TRUE if the server is running (False otherwise)
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: BOOL
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IRunnableObject
+//
+// Algorithm: checks flags in the handler or queries the proxy manager
+//
+// History: dd-mmm-yy Author Comment
+// 07-Nov-93 alexgo 32bit port
+//
+// Notes: original notes:
+//
+// returns TRUE if running (m_fForcedRunning *may* be true); returns FALSE if
+// not running or was and the app crashed (m_fForcedRunning *will* be FALSE).
+//
+// REVIEW32: This function is a good candidate for optimization;
+// it is called many times.
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(BOOL) CDefObject::IsRunning(void)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ BOOL fReturn;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::IsRunning "
+ "( )\n", this));
+
+#if 0
+ if (!m_fIsMaybeRunning) { // if never run, it can't be running
+ fReturn = FALSE;
+ goto errRtn;
+ }
+#endif
+
+ {
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ // no delgate -> not running
+ if( m_pUnkDelegate == NULL)
+ {
+ Assert( (m_flags & DH_DELAY_CREATE) && m_pCFDelegate != NULL);
+ Assert(!(m_flags & DH_LOCKED_CONTAINER));
+ Assert(!(m_flags & DH_FORCED_RUNNING));
+ fReturn = FALSE;
+ goto errRtn;
+ }
+
+ // can't have an inproc server with a proxymgr or a handler without
+ // one
+ Assert((m_pProxyMgr != NULL) == !!(m_flags & DH_INPROC_HANDLER));
+
+ if( m_pProxyMgr == NULL)
+ {
+ // Embeddings are explicitly run (forced running), while
+ // file-level link sources can be implicitly run.
+ if (!(m_flags & DH_EMBEDDING) ||
+ (m_flags & DH_FORCED_RUNNING) )
+ {
+ fReturn = TRUE;
+ goto errRtn;
+ }
+
+ // clean up below; could do more to cleanup (e.g., unadvise)
+ }
+ else {
+ if( m_pProxyMgr->IsConnected() )
+ {
+ // have proxymgr; must be inproc handler; handler keeps flag
+ fReturn = TRUE;
+ goto errRtn;
+ }
+ }
+
+ // we know that we must not be running
+ fReturn = FALSE;
+
+ m_flags &= ~DH_FORCED_RUNNING;
+
+
+ // cleanup advise connection
+ m_dwConnOle = 0L;
+
+ // inform cache that we are not running (Undoes advise)
+ if( m_pCOleCache )
+ {
+ m_pCOleCache->OnStop();
+ }
+
+ // REVIEW: do we unlock container? It would seem like a problem
+ // since just about any call might cause the container to
+ // be unlocked and shutdown.
+
+ // NOTE: we currently do the unlock in DoVerb and Update since
+ // normally might shutdown the server and thus the app might receive
+ // an unlock.
+
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::IsRunning "
+ "( %lu )\n", this, fReturn));
+
+ if (fReturn)
+ m_fIsMaybeRunning = TRUE;
+ return fReturn;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::SetContainedObject
+//
+// Synopsis: sets the embedding status of an object
+//
+// Effects:
+//
+// Arguments: [fContained] -- TRUE indicates we are an embedding/
+// FALSE otherwise
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IRunnableObject
+//
+// Algorithm: Sets flags, if we are an improc handler, we will call
+// IRunnableObject->LockRunning(FALSE) to unlock ourselves
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+// note that this is a contained object; this unlocks
+// connection to the server
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::SetContainedObject(BOOL fContained)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult = NOERROR;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SetContainedObject "
+ "( %lu )\n", this, fContained));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( !!(m_flags & DH_CONTAINED_OBJECT) != !!fContained)
+ {
+ // not contained in the same way as desired;
+ // for inproc handler, [un]lock connection
+ // for inproc server, just remember flag
+
+ if( (m_flags & DH_INPROC_HANDLER) )
+ {
+ hresult = LockRunning(!fContained, FALSE);
+ }
+
+ if (hresult == NOERROR)
+ {
+ // the !! ensure exactly 0 or 1 will be stored in
+ // m_fContainedObject
+
+ if( fContained )
+ {
+ m_flags |= DH_CONTAINED_OBJECT;
+ }
+ else
+ {
+ m_flags &= ~DH_CONTAINED_OBJECT;
+ }
+ }
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::SetContainedObject "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::LockRunning
+//
+// Synopsis: Locks or unlocks the object
+//
+// Effects:
+//
+// Arguments: [fLock] -- TRUE, then lock, unlock if FALSE
+// [fLastUnlockCloses] -- shut down if unlocking the last
+// lock
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IRunnableObject
+//
+// Algorithm: If we are an improc server, call CoLockObjectExternal,
+// otherwise have the proxy manager lock us down.
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::LockRunning(BOOL fLock, BOOL fLastUnlockCloses)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::LockRunning "
+ "( %lu , %lu )\n", this, fLock, fLastUnlockCloses ));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ // else map to lock connection
+ if( !(m_flags & DH_INPROC_HANDLER) )
+ {
+ // inproc server: use CoLockObjExternal; will close down
+ // if invisible via new IExternalConnection interface.
+
+ Assert(m_pProxyMgr == NULL);
+ hresult = CoLockObjectExternal((IUnknown *)(IOleObject *)this, fLock,
+ fLastUnlockCloses); }
+ else if( m_pUnkDelegate == NULL )
+ {
+ // NOTE: this really shouldn't happen at present
+ // since we currently disallow delay create with
+ // inproc handler. In fact, the LockConnection below
+ // is one of the reasons why we must have the
+ // proxymgr upfront. In the future we could force
+ // the creation of the delegate here.
+ Assert( (m_flags & DH_DELAY_CREATE) && m_pCFDelegate != NULL);
+ hresult = NOERROR;
+ }
+ else
+ {
+ Assert(m_pProxyMgr != NULL);
+
+ hresult = m_pProxyMgr->LockConnection(fLock, fLastUnlockCloses);
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::LockRunning "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+
+/*
+* IMPLEMENTATION of CECImpl methods
+*
+*/
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::AddConnection
+//
+// Synopsis: Adds an external connection
+//
+// Effects:
+//
+// Arguments: [extconn] -- the type of connection (such as
+// EXTCONN_STRONG)
+// [reserved] -- unused
+//
+// Requires:
+//
+// Returns: DWORD -- the number of strong connections
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IExternalConnection
+//
+// Algorithm: keeps track of strong connections
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(DWORD) CDefObject::AddConnection(DWORD extconn, DWORD reserved)
+{
+ VDATEHEAP();
+
+ //
+ // VDATETHREAD contains a 'return HRESULT' but this procedure expects to
+ // return a DWORD. Avoid the warning.
+#if ( _MSC_VER >= 800 )
+#pragma warning( disable : 4245 )
+#endif
+ VDATETHREAD(this);
+#if ( _MSC_VER >= 800 )
+#pragma warning( default : 4245 )
+#endif
+
+ DWORD dwConn;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::AddConnection "
+ "( %lu , %lu )\n", this, extconn, reserved));
+
+ Assert( !(m_flags & DH_INPROC_HANDLER) );
+
+ dwConn = extconn&EXTCONN_STRONG ? ++m_cConnections : 0;
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::AddConnection "
+ "( %lu )\n", this, dwConn));
+
+ return dwConn;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::ReleaseConnection
+//
+// Synopsis: Releases external connection, potentially calling IOO->Close
+//
+// Effects:
+//
+// Arguments: [extconn] -- the type of connection
+// [reserved] -- unused
+// [fLastReleaseCloses] -- call IOO->Close if its the last
+// release
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(DWORD) CDefObject::ReleaseConnection(DWORD extconn,
+ DWORD reserved, BOOL fLastReleaseCloses)
+{
+ VDATEHEAP();
+
+ //
+ // VDATETHREAD contains a 'return HRESULT' but this procedure expects to
+ // return a DWORD. Avoid the warning.
+#if ( _MSC_VER >= 800 )
+#pragma warning( disable : 4245 )
+#endif
+ VDATETHREAD(this);
+#if ( _MSC_VER >= 800 )
+#pragma warning( default : 4245 )
+#endif
+
+ DWORD dwConn;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::ReleaseConnection "
+ "( %lu , %lu , %lu )\n", this, extconn, reserved,
+ fLastReleaseCloses));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ // must be an embedding helper
+
+ Assert( !(m_flags & DH_INPROC_HANDLER) );
+
+ if( (extconn & EXTCONN_STRONG) && --m_cConnections == 0 &&
+ fLastReleaseCloses)
+ {
+ // REVIEW: might want this to be close save if dirty.
+ Close(OLECLOSE_NOSAVE);
+ }
+
+ dwConn = (extconn & EXTCONN_STRONG) ? m_cConnections : 0;
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::ReleaseConnection "
+ "( %lu )\n", this, dwConn));
+
+ return dwConn;
+}
+
+
+/*
+* IMPLEMENTATION of CAdvSinkImpl methods
+*
+*/
+
+// NOTE: since the advise sink side of the object can stay alive longer than
+// the ole object side, we must not do anything if the ole object has been
+// released.
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::CAdvSinkImpl::QueryInterface
+//
+// Synopsis: Only supports IUnkown and IAdviseSink, we do not delegate
+// to the rest of the handler (since it might not be alive
+// when we are)
+//
+// Effects:
+//
+// Arguments: [iid] -- the requested interface
+// [ppvObj] -- where to put a pointer to the interface
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink, IUnkown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Dec-93 alexgo added call tracing
+// 22-Nov-93 alexgo removed overloaded ==
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::CAdvSinkImpl::QueryInterface(REFIID iid,
+ LPVOID *ppvObj)
+{
+ VDATEHEAP();
+
+ HRESULT hresult;
+ CDefObject * pDefObject = GETPPARENT(this, CDefObject, m_AdviseSink);
+
+ LEDebugOut((DEB_TRACE,
+ "%p _IN CDefObject::CAdvSinkImpl::QueryInterface "
+ "( %p , %p )\n", pDefObject, iid, ppvObj));
+
+ VDATEPTROUT( ppvObj, LPVOID );
+ *ppvObj = NULL;
+
+ if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IAdviseSink))
+ {
+ *ppvObj = this;
+ AddRef();
+ hresult = NOERROR;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ hresult = E_NOINTERFACE;
+ }
+
+ LEDebugOut((DEB_TRACE,
+ "%p OUT CDefObject::CAdvSinkImpl::QueryInterface "
+ "( %lx ) [ %p ]\n", pDefObject, hresult, *ppvObj));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::CAdvSinkImpl::AddRef
+//
+// Synopsis: increments the reference count
+//
+// Effects:
+//
+// Arguments: none
+//
+// Requires:
+//
+// Returns: ULONG; the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Aug-94 alexgo author
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDefObject::CAdvSinkImpl::AddRef( void )
+{
+ ULONG cRefs;
+
+
+ CDefObject * pDefObject = GETPPARENT(this, CDefObject, m_AdviseSink);
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CAdvSinkImpl::AddRef "
+ "( )\n", this));
+
+ cRefs = pDefObject->SafeAddRef();
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CAdvSinkImpl::AddRef "
+ "( %lu )\n", this, cRefs));
+
+ return cRefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::CAdvSinkImpl::Release
+//
+// Synopsis: Releases a reference
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG (number of remaining references)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink, IUnkown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Dec-93 alexgo added call tracing
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDefObject::CAdvSinkImpl::Release ( void )
+{
+ VDATEHEAP();
+
+ CDefObject * pDefObject = GETPPARENT(this, CDefObject, m_AdviseSink);
+
+ ULONG refcount;
+
+ LEDebugOut((DEB_TRACE,
+ "%p _IN CDefObject::CAdvSinkImpl::Release "
+ "( )\n", pDefObject ));
+
+ refcount = pDefObject->SafeRelease();
+
+ LEDebugOut((DEB_TRACE,
+ "%p OUT CDefObject::CAdvSinkImpl::Release "
+ "( %lu )\n", pDefObject, refcount));
+
+ return refcount;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::CAdvSinkImpl::OnDataChange
+//
+// Synopsis: Function to notify on data change
+//
+// Effects: Never called
+//
+// Arguments: [pFormatetc] -- format of the data
+// [pStgmed] -- data medium
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CDefObject::CAdvSinkImpl::OnDataChange(
+ FORMATETC *pFormatetc, STGMEDIUM *pStgmed)
+{
+ VDATEHEAP();
+
+ VOID_VDATEPTRIN( pFormatetc, FORMATETC );
+ VOID_VDATEPTRIN( pStgmed, STGMEDIUM );
+
+ Assert(FALSE); // never received
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::CAdvSinkImpl::OnViewChange
+//
+// Synopsis: notification of view changes
+//
+// Effects: never called
+//
+// Arguments: [aspects]
+// [lindex]
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CDefObject::CAdvSinkImpl::OnViewChange
+ (DWORD aspects, LONG lindex)
+{
+ VDATEHEAP();
+
+ Assert(FALSE); // never received
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::CAdvSinkImpl::OnRename
+//
+// Synopsis: Notification of name changes
+//
+// Effects:
+//
+// Arguments: [pmk] -- the new name (moniker)
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink
+//
+// Algorithm: notifies the advise holder (if one exists)
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CDefObject::CAdvSinkImpl::OnRename(IMoniker *pmk)
+{
+ VDATEHEAP();
+
+ CDefObject * pDefObject = GETPPARENT(this, CDefObject, m_AdviseSink);
+
+ LEDebugOut((DEB_TRACE,
+ "%p _IN CDefObject::CAdvSinkImpl::OnRename "
+ "( %p )\n", pDefObject, pmk));
+
+ VOID_VDATEIFACE( pmk );
+
+ CStabilize stabilize((CSafeRefCount *)pDefObject);
+
+ if (pDefObject->m_pOAHolder != NULL)
+ {
+ pDefObject->m_pOAHolder->SendOnRename(pmk);
+ }
+
+ LEDebugOut((DEB_TRACE,
+ "%p OUT CDefObject::CAdvSinkImpl::OnRename "
+ "( )\n", pDefObject));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::CAdvSinkImpl::OnSave
+//
+// Synopsis: Notification of save's
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink
+//
+// Algorithm: notifies the advise holder
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CDefObject::CAdvSinkImpl::OnSave( void )
+{
+ VDATEHEAP();
+
+ CDefObject * pDefObject = GETPPARENT(this, CDefObject, m_AdviseSink);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CAdvSinkImpl::OnSave "
+ "( )\n", pDefObject));
+
+ CStabilize stabilize((CSafeRefCount *)pDefObject);
+
+ if (pDefObject->m_pOAHolder != NULL)
+ {
+ pDefObject->m_pOAHolder->SendOnSave();
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CAdvSinkImpl::OnSave "
+ "( )\n", pDefObject));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::CAdvSinkImpl::OnClose
+//
+// Synopsis: notification of the object closing
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink
+//
+// Algorithm: notifies the advise holder and stops the server
+//
+// History: dd-mmm-yy Author Comment
+// 01-Aug-94 alexgo stabilized
+// 15-Dec-93 alexgo added call tracing
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CDefObject::CAdvSinkImpl::OnClose( void )
+{
+ VDATEHEAP();
+
+ CDefObject * pDefObject = GETPPARENT(this, CDefObject, m_AdviseSink);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CAdvSinkImpl::OnClose "
+ "( )\n", pDefObject));
+
+ CStabilize stabilize((CSafeRefCount *)pDefObject);
+
+ BOOL fAlive = pDefObject->m_cRefsOnHandler != 0;
+ // m_refs == 0 when released
+
+ if (pDefObject->m_pOAHolder != NULL)
+ {
+ // In general, OnClose can delete this defhndlr; thus
+ // we addref the aggregate so that we can tell if we
+ // should go away
+ pDefObject->m_pUnkOuter->AddRef();
+ pDefObject->m_pOAHolder->SendOnClose();
+ fAlive = pDefObject->m_pUnkOuter->Release() != 0;
+
+ // make sure that if we are alive, the ole object has
+ // non-zero refs. (the test apps violated this once)
+ Assert(!fAlive || pDefObject->m_cRefsOnHandler != 0);
+ }
+
+ if (fAlive)
+ {
+ pDefObject->Stop();
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CAdvSinkImpl::OnClose "
+ "( )\n", pDefObject));
+}
+
+
+/*
+* IMPLEMENTATION of CPersistStgImpl methods
+*
+*/
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::GetPSDelegate
+//
+// Synopsis: retrieves the IPersistStorage interface from the delegate
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: IPersistStorage *
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(IPersistStorage *) CDefObject::GetPSDelegate(void)
+{
+ VDATEHEAP();
+
+ if( IsZombie() )
+ {
+ return NULL;
+ }
+
+ return (IPersistStorage FAR*)DuCacheDelegate(
+ &m_pUnkDelegate,
+ IID_IPersistStorage,
+ (LPLPVOID) &m_pPSDelegate,
+ m_pUnkOuter);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::GetClassID
+//
+// Synopsis: Retrieves the class ID of the object
+//
+// Effects:
+//
+// Arguments: [pClassID] -- where to put the class ID
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IPersistStorage
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::GetClassID (CLSID *pClassID)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetClassID "
+ "( %p )\n", this, pClassID));
+
+ VDATEPTROUT(pClassID, CLSID );
+
+ hresult = GetClassBits(pClassID);
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetClassID "
+ "( %lx ) [ %p ]\n", this, hresult, pClassID));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::IsDirty
+//
+// Synopsis: Returns whether or not the object needs to be saved
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HRESULT -- NOERROR means the object *is* dirty
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IPersistStorage
+//
+// Algorithm: if the server is running, delegate. If the server is
+// clean (or not present), ask the cache
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::IsDirty( void )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::IsDirty ( )\n", this));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ // if server is running, it holds definitive dirty flag
+ if( IsRunning() && GetPSDelegate() )
+ {
+ if ( (hresult = m_pPSDelegate->IsDirty()) == NOERROR)
+ {
+ goto errRtn;
+ }
+ }
+
+ Assert(m_pCOleCache != NULL);
+ hresult = m_pCOleCache->IsDirty();
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::IsDirty "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::InitNew
+//
+// Synopsis: Create a new object with the given storage
+//
+// Effects:
+//
+// Arguments: [pstg] -- the storage for the new object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IPersistStorage
+//
+// Algorithm: Delegates to the server and to the cache. Writes
+// Ole private data to the storage.
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::InitNew( IStorage *pstg )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ VDATEIFACE( pstg );
+
+ HRESULT hresult;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::InitNew ( %p )\n",
+ this, pstg));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( m_pStg )
+ {
+ hresult = CO_E_ALREADYINITIALIZED;
+ goto errRtn;
+ }
+
+ m_flags |= DH_EMBEDDING;
+
+
+ if( IsRunning() && GetPSDelegate()
+ && (hresult = m_pPSDelegate->InitNew(pstg)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ m_flags |= DH_INIT_NEW;
+
+
+ // if we're in a zombie state, don't change the storage!
+
+ if( IsZombie() )
+ {
+ hresult = CO_E_RELEASED;
+ goto errRtn;
+ }
+
+ Assert(m_pCOleCache != NULL);
+ if ((hresult = m_pCOleCache->InitNew(pstg)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ // remember the storage pointer
+ (m_pStg = pstg)->AddRef();
+
+ // go ahead and write the Ole stream now
+ WriteOleStg(pstg, (IOleObject *)this, NULL, NULL);
+
+errRtn:
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::InitNew "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::Load
+//
+// Synopsis: Loads object data from the given storage
+//
+// Effects:
+//
+// Arguments: [pstg] -- the storage for the object's data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IPeristStorage
+//
+// Algorithm: Reads ole-private data (or creates if not there), delegates
+// to the server and the cache.
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::Load (IStorage *pstg)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult;
+ DWORD dwFlags;
+ DWORD dwOptUpdate;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Load ( %p )\n",
+ this, pstg));
+
+ VDATEIFACE( pstg );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+
+ if( m_pStg )
+ {
+ hresult = CO_E_ALREADYINITIALIZED;
+ goto errRtn;
+ }
+
+ m_flags |= DH_EMBEDDING;
+
+
+ // NOTE: we can get the moniker from container, so no need to get
+ // it here
+
+ hresult = ReadOleStg (pstg, &dwFlags, &dwOptUpdate, NULL, NULL, NULL);
+
+ if (hresult == NOERROR)
+ {
+ if (dwFlags & OBJFLAGS_CONVERT)
+ {
+ if( DoConversionIfSpecialClass(pstg) != NOERROR )
+ {
+ hresult = OLE_E_CANTCONVERT;
+ goto errRtn;
+ }
+ }
+
+ Assert (dwOptUpdate == NULL);
+
+ }
+ else if (hresult == STG_E_FILENOTFOUND)
+ {
+ // it is OK if the Ole stream doesn't exist.
+ hresult = NOERROR;
+
+ // go ahead and write the Ole stream now
+ WriteOleStg(pstg, (IOleObject *)this, NULL, NULL);
+ }
+ else
+ {
+ goto errRtn;
+ }
+
+
+ // if running, tell server to load from pstg
+ if( IsRunning() && GetPSDelegate()
+ && (hresult = m_pPSDelegate->Load(pstg)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ // if we're in a zombie state, don't addref' the storage!
+
+ if( IsZombie() )
+ {
+ hresult = CO_E_RELEASED;
+ goto errRtn;
+ }
+
+ // now load cache from pstg
+ Assert(m_pCOleCache != NULL);
+
+ if ((hresult = m_pCOleCache->Load(pstg)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ m_flags &= ~DH_INIT_NEW; // clear init new flag
+
+ // remember the storage pointer
+ (m_pStg = pstg)->AddRef();
+
+errRtn:
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Load "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::Save
+//
+// Synopsis: Saves the object to the given storage
+//
+// Effects:
+//
+// Arguments: [pstgSave] -- storage in which to save
+// [fSameAsLoad] -- FALSE indicates a SaveAs operation
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IPersistStorage
+//
+// Algorithm: Saves ole-private data, delegates to the server and then
+// to the cache
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::Save( IStorage *pstgSave, BOOL fSameAsLoad)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult = NOERROR;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Save "
+ "( %p , %lu )\n", this, pstgSave, fSameAsLoad ));
+
+ VDATEIFACE( pstgSave );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ Assert(m_pCOleCache != NULL);
+
+ if( IsRunning() && GetPSDelegate() )
+ {
+
+ DWORD grfUpdf = UPDFCACHE_IFBLANK;
+
+#ifdef NEVER
+ // We would have liked to have done this check as an
+ // optimization, but WordArt2 does not give the right answer
+ // (bug 3504) so we can't.
+ if (m_pPStgDelegate->IsDirty() == NOERROR)
+#endif
+ grfUpdf |= UPDFCACHE_ONSAVECACHE;
+
+ // Write the Ole stream
+ WriteOleStg(pstgSave, (IOleObject *)this, NULL, NULL);
+
+ // next save server data
+ if (hresult = m_pPSDelegate->Save(pstgSave, fSameAsLoad))
+ {
+ goto errRtn;
+ }
+
+ m_pCOleCache->UpdateCache(GetDataDelegate(), grfUpdf, NULL);
+
+ hresult = m_pCOleCache->Save(pstgSave,
+ fSameAsLoad);
+
+ }
+ else
+ {
+ // This above line will take care of the case where new
+ // caches got added but the object hasn't been Run yet, and
+ // other cases like that.
+
+ if ((hresult = m_pCOleCache->Save(m_pStg,TRUE))
+ != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ // By now we are sure that object's current state has got
+ // saved into its storage.
+
+ AssertSz(m_pStg, "Object doesn't have storage");
+
+ if (!fSameAsLoad)
+ {
+ hresult = m_pStg->CopyTo(NULL, NULL, NULL, pstgSave);
+ }
+ }
+
+errRtn:
+ if (hresult == NOERROR)
+ {
+ if( fSameAsLoad )
+ {
+ m_flags |= DH_SAME_AS_LOAD;
+ // gets used in SaveCompleted
+ m_flags &= ~DH_INIT_NEW;
+ }
+ else
+ {
+ m_flags &= ~DH_SAME_AS_LOAD;
+ }
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Save "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::SaveCompleted
+//
+// Synopsis: called when the save is completed
+//
+// Effects:
+//
+// Arguments: [pstgNew] -- the new storage for the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IPersistStorage
+//
+// Algorithm: delegates to the server and the cache.
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::SaveCompleted( IStorage *pstgNew )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult = NOERROR;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SaveCompleted "
+ "( %p )\n", this, pstgNew));
+
+
+ if( pstgNew )
+ {
+ VDATEIFACE(pstgNew);
+ }
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( IsRunning() && GetPSDelegate() )
+ {
+ hresult = m_pPSDelegate->SaveCompleted(pstgNew);
+ }
+
+ // we don't save the new storage if we're in a zombie state!
+
+ if( hresult == NOERROR && pstgNew && !IsZombie() )
+ {
+ if( m_pStg )
+ {
+ m_pStg->Release();
+ }
+
+ m_pStg = pstgNew;
+ pstgNew->AddRef();
+ }
+
+ // let the cache know that the save is completed, so that it can
+ // clear its dirty flag in Save or SaveAs situation, as well as
+ // remember the new storage pointer if a new one is given
+
+ Assert(m_pCOleCache != NULL);
+
+ if( (m_flags & DH_SAME_AS_LOAD) || pstgNew)
+ {
+ // clear init-new and same-as-load flags
+ m_flags &= ~(DH_SAME_AS_LOAD | DH_INIT_NEW);
+ }
+
+ m_pCOleCache->SaveCompleted(pstgNew);
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::SaveCompleted ( %lx )\n",
+ this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::HandsOffStorage
+//
+// Synopsis: Forces the server to release a storage (for low-mem reasons,
+// etc).
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IPersistStorage
+//
+// Algorithm: Delegates to the server and the cache
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefObject::HandsOffStorage(void)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ HRESULT hresult = NOERROR;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefObject::HandsOffStorage ( )\n",
+ this));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( IsRunning() && GetPSDelegate() )
+ {
+ hresult = m_pPSDelegate->HandsOffStorage();
+ }
+
+ if (hresult == NOERROR)
+ {
+ if( m_pStg )
+ {
+ m_pStg->Release();
+ m_pStg = NULL;
+ }
+
+ Assert(m_pCOleCache != NULL);
+ m_pCOleCache->HandsOffStorage();
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::HandsOffStorage ( %lx )\n",
+ this, hresult));
+
+ return hresult;
+}
+
+/*
+ * Default handler private functions
+ */
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::GetClassBits
+//
+// Synopsis: Gets a class id for the object
+//
+// Effects:
+//
+// Arguments: [pClsidBits] -- where to put the class id
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: Tries the server, then the storage, and finally the
+// clsid we were created with
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+// always gets a clsid and returns NOERROR; the clsid may be m_clsidServer
+// under certain conditions (e.g., no compobj stream).
+//
+//--------------------------------------------------------------------------
+
+INTERNAL CDefObject::GetClassBits(CLSID FAR* pClsidBits)
+{
+ VDATEHEAP();
+
+ // alway try server first; this allows the server to respond
+ if( IsRunning() && GetPSDelegate() )
+ {
+ if( m_pPSDelegate->GetClassID(pClsidBits) == NOERROR )
+ {
+ m_clsidBits = *pClsidBits;
+ return NOERROR;
+ }
+ }
+
+ // not running, no ps or error: use previously cached value
+ if( !IsEqualCLSID(m_clsidBits, CLSID_NULL) )
+ {
+ *pClsidBits = m_clsidBits;
+ return NOERROR;
+ }
+
+ // not running, no ps or error and no clsidBits yet: read from stg
+ // if not static object.
+ if( !(m_flags & DH_STATIC) )
+ {
+ if (m_pStg && ReadClassStg(m_pStg, pClsidBits) == NOERROR)
+ {
+ m_clsidBits = *pClsidBits;
+ return NOERROR;
+ }
+ }
+
+ // no contact with server and can't get from storage; don't set
+ // m_clsidBits so if we get a storage or the serve becomes running,
+ // we get the right one
+
+ *pClsidBits = m_clsidServer;
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::DoConversionIfSpecialClass
+//
+// Synopsis: Convert old data formats.
+//
+// Effects:
+//
+// Arguments: [pstg] -- the storage with the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: see notes...
+//
+// History: dd-mmm-yy Author Comment
+// 08-Nov-93 alexgo 32bit port
+//
+// Notes: this is not yet functional for 32bit OLE
+//
+// If the class is CLSID_StaticDib/CLSID_StaticMetafile and the old
+// format is "PBrush"/"MSDraw" the data must be in the OLE10_NATIVESTREAM.
+// Move the data into the CONTENTS stream
+//
+// If the class is CLSID_PBrush/CLSID_MSDraw and the old format is
+// metafile/DIB then data must be in the CONTENTS stream. Move the data
+// from the CONTENTS stream to the OLE10_NATIVESTREAM"
+//
+//--------------------------------------------------------------------------
+
+INTERNAL CDefObject::DoConversionIfSpecialClass(LPSTORAGE pstg)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefObject::DoConversionIfSpecialClass ("
+ " %p )\n", this, pstg));
+
+ HRESULT hresult;
+ UINT uiStatus;
+
+ /*** Handle the static object case ***/
+
+ if( (m_flags & DH_STATIC) ) {
+ if ((hresult = Ut10NativeStmToContentsStm(pstg, m_clsidServer,
+ TRUE /* fDeleteContentStm*/)) == NOERROR)
+#ifdef OLD
+ UtRemoveExtraOlePresStreams(pstg, 0 /*iStart*/);
+#endif
+ goto errRtn;
+
+ }
+
+
+ /*** Handle the PBrush & MSDraw case ***/
+
+ // Conversion is not a frequent operation. So, it is better to do the
+ // CLSID comparison here when it is necessary than doing comparison
+ // upfront and remember a flag
+
+ // if the class is not one of the following two then the object server
+ // will do the necessary conversion.
+
+ CLSID clsid = CLSID_NULL;
+
+ // Get the real CLSID from the storage. This is necessary because we
+ // may be a PBrush object being "treated as".
+ ReadClassStg(pstg, &clsid);
+
+ // if the real CLSID is not PaintBrush or the known CLSID is not MSDRAW
+ // head out.
+ if( clsid != CLSID_PBrush && m_clsidServer != CLSID_MSDraw )
+ {
+ hresult = NOERROR;
+ goto exitRtn;
+ }
+
+ // if the real CLSID is not paintbrush, then set clsid to the clsid to
+ // the known clsid.
+ if (clsid != CLSID_PBrush)
+ {
+ clsid = m_clsidServer;
+ }
+
+ //
+ hresult = UtContentsStmTo10NativeStm(pstg, clsid,
+ TRUE /* fDeleteContentStm*/,
+ &uiStatus);
+
+ // if OLE10_NATIVE_STREAM exists then assume success
+ if (!(uiStatus & CONVERT_NODESTINATION))
+ hresult = NOERROR;
+
+ if (hresult != NOERROR) {
+ // May be the static object data is in OlePres stream. If so,
+ // first convert that to contents stream and then try again
+ // In OLE2.0 first release static object were written to
+ // OlePres000 stream.
+ hresult = UtOlePresStmToContentsStm(pstg,
+ OLE_PRESENTATION_STREAM,
+ TRUE /*fDeletePresStm*/, &uiStatus);
+
+ if (hresult == NOERROR)
+ hresult = UtContentsStmTo10NativeStm(pstg,
+ m_clsidServer,
+ TRUE /* fDeleteContentStm*/,
+ &uiStatus);
+ }
+
+errRtn:
+ if (hresult == NOERROR)
+ // conversion is successful, turn the bit off
+ SetConvertStg(pstg, FALSE);
+
+exitRtn:
+ LEDebugOut((DEB_TRACE, "%p OUT CDefObject::DoConversionIfSpecialClass "
+ "( %lx ) \n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefObject::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppszDump] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CDefObject::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszCSafeRefCount;
+ char *pszCThreadCheck;
+ char *pszOAHolder;
+ char *pszCLSID;
+ char *pszCOleCache;
+ char *pszDAC;
+ LPOLESTR pszName;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(5000);
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ pszCSafeRefCount = DumpCSafeRefCount((CSafeRefCount *)this, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CSafeRefCount:" << endl;
+ dstrDump << pszCSafeRefCount;
+ CoTaskMemFree(pszCSafeRefCount);
+
+ pszCThreadCheck = DumpCThreadCheck((CThreadCheck *)this, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CThreadCheck:" << endl;
+ dstrDump << pszCThreadCheck;
+ CoTaskMemFree(pszCThreadCheck);
+
+ // only vtable pointers (plus we don't get the right address in debugger extensions)
+ // dstrDump << pszPrefix << "&IUnknown = " << &m_Unknown << endl;
+ // dstrDump << pszPrefix << "&IAdviseSink = " << &m_AdviseSink << endl;
+
+ dstrDump << pszPrefix << "pIOleObject Delegate = " << m_pOleDelegate << endl;
+
+ dstrDump << pszPrefix << "pIDataObject Delegate = " << m_pDataDelegate << endl;
+
+ dstrDump << pszPrefix << "pIPersistStorage Delegate = " << m_pPSDelegate << endl;
+
+ dstrDump << pszPrefix << "Count of Strong Connection= " << m_cConnections << endl;
+
+ dstrDump << pszPrefix << "No. of Refs. on Handler = " << m_cRefsOnHandler << endl;
+
+ dstrDump << pszPrefix << "pIUnknown pUnkOuter = ";
+ if (m_flags & DH_AGGREGATED)
+ {
+ dstrDump << "AGGREGATED (" << m_pUnkOuter << ")" << endl;
+ }
+ else
+ {
+ dstrDump << "NO AGGREGATION (" << m_pUnkOuter << ")" << endl;
+ }
+
+ pszCLSID = DumpCLSID(m_clsidServer);
+ dstrDump << pszPrefix << "Server CLSID = " << pszCLSID << endl;
+ CoTaskMemFree(pszCLSID);
+
+ pszCLSID = DumpCLSID(m_clsidBits);
+ dstrDump << pszPrefix << "Persistent CLSID = " << pszCLSID << endl;
+ CoTaskMemFree(pszCLSID);
+
+ dstrDump << pszPrefix << "Handler flags = ";
+ if (m_flags & DH_SAME_AS_LOAD)
+ {
+ dstrDump << "DH_SAME_AS_LOAD ";
+ }
+ if (m_flags & DH_CONTAINED_OBJECT)
+ {
+ dstrDump << "DH_CONTAINED_OBJECT ";
+ }
+ if (m_flags & DH_LOCKED_CONTAINER)
+ {
+ dstrDump << "DH_LOCKED_CONTAINER ";
+ }
+ if (m_flags & DH_FORCED_RUNNING)
+ {
+ dstrDump << "DH_FORCED_RUNNING ";
+ }
+ if (m_flags & DH_EMBEDDING)
+ {
+ dstrDump << "DH_EMBEDDING ";
+ }
+ if (m_flags & DH_INIT_NEW)
+ {
+ dstrDump << "DH_INIT_NEW ";
+ }
+ if (m_flags & DH_STATIC)
+ {
+ dstrDump << "DH_STATIC ";
+ }
+ if (m_flags & DH_INPROC_HANDLER)
+ {
+ dstrDump << "DH_INPROC_HANDLER ";
+ }
+ if (m_flags & DH_DELAY_CREATE)
+ {
+ dstrDump << "DH_DELAY_CREATE ";
+ }
+ if (m_flags & DH_AGGREGATED)
+ {
+ dstrDump << "DH_AGGREGATED ";
+ }
+ // if none of the flags are set...
+ if ( !( (m_flags & DH_SAME_AS_LOAD) |
+ (m_flags & DH_CONTAINED_OBJECT) |
+ (m_flags & DH_LOCKED_CONTAINER) |
+ (m_flags & DH_FORCED_RUNNING) |
+ (m_flags & DH_EMBEDDING) |
+ (m_flags & DH_INIT_NEW) |
+ (m_flags & DH_STATIC) |
+ (m_flags & DH_INPROC_HANDLER) |
+ (m_flags & DH_DELAY_CREATE) |
+ (m_flags & DH_AGGREGATED)))
+ {
+ dstrDump << "No FLAGS SET!";
+ }
+ dstrDump << "(" << (void *)m_flags << ")" << endl;
+
+ dstrDump << pszPrefix << "pIClassFactory Delegate = " << m_pCFDelegate << endl;
+
+ dstrDump << pszPrefix << "pIUnknown Delegate = " << m_pUnkDelegate << endl;
+
+ dstrDump << pszPrefix << "pIProxyManager = " << m_pProxyMgr << endl;
+
+ if (m_pCOleCache != NULL)
+ {
+ pszCOleCache = DumpCOleCache(m_pCOleCache, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "COleCache: " << endl;
+ dstrDump << pszCOleCache;
+ CoTaskMemFree(pszCOleCache);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "pCOleCache = " << m_pCOleCache << endl;
+ }
+
+ if (m_pOAHolder != NULL)
+ {
+ pszOAHolder = DumpCOAHolder(m_pOAHolder, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "COAHolder: " << endl;
+ dstrDump << pszOAHolder;
+ CoTaskMemFree(pszOAHolder);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "pIOleAdviseHolder = " << m_pOAHolder << endl;
+ }
+
+ dstrDump << pszPrefix << "OLE Connection Advise ID = " << m_dwConnOle << endl;
+
+ dstrDump << pszPrefix << "pIOleClientSite = " << m_pAppClientSite << endl;
+
+ dstrDump << pszPrefix << "pIStorage = " << m_pStg << endl;
+
+ pszName = (LPOLESTR)m_pHostNames;
+ dstrDump << pszPrefix << "Application Name = " << pszName << endl;
+
+ pszName = (LPOLESTR)(m_pHostNames + m_ibCntrObj);
+ dstrDump << pszPrefix << "Document Name = " << pszName << endl;
+
+ if (m_pDataAdvCache != NULL)
+ {
+ pszDAC = DumpCDataAdviseCache(m_pDataAdvCache, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CDataAdviseCache: " << endl;
+ dstrDump << pszDAC;
+ CoTaskMemFree(pszDAC);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "pCDataAdviseCache = " << m_pDataAdvCache << endl;
+ }
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCDefObject, public (_DEBUG only)
+//
+// Synopsis: calls the CDefObject::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pDO] - pointer to CDefObject
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCDefObject(CDefObject *pDO, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pDO == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pDO->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+
+
+
diff --git a/private/ole32/ole232/stdimpl/defhndlr.h b/private/ole32/ole232/stdimpl/defhndlr.h
new file mode 100644
index 000000000..9f3098740
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/defhndlr.h
@@ -0,0 +1,338 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: defhndlr.h
+//
+// Contents: class declaration for the default handler
+//
+// Classes: CDefObject
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+//
+// 11-17-95 JohannP (Johann Posch) Architectural change:
+// Default handler will talk to a handler object
+// on the server site (ServerHandler). The serverhandler
+// communicates with the default handler via the
+// clientsitehandler. See document: "The Ole Server Handler".
+//
+// 06-Sep-95 davidwor removed SetHostNames atoms and replaced with
+// m_pHostNames and m_ibCntrObj members
+// 01-Feb-95 t-ScottH added Dump method to CDefObject
+// added DHFlag to indicate aggregation
+// (_DEBUG only)
+// changed private member from IOleAdviseHolder *
+// to COAHolder * (it is what we instantiate)
+// 15-Nov-94 alexgo optimized, removed 16bit burfiness
+// (nested classes and multiple BOOLs)
+// 25-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocations.
+// 02-Nov-93 alexgo 32bit port
+//
+//--------------------------------------------------------------------------
+
+#include <utils.h>
+#include "olepres.h"
+#include "olecache.h"
+#include "dacache.h"
+#include "oaholder.h"
+
+#ifdef SERVER_HANDLER
+#include "handler.hxx"
+#endif // SERVER_HANDLER
+
+
+// default handler flags
+
+typedef enum tagDHFlags
+{
+#ifdef _DEBUG
+ DH_AGGREGATED = 512,
+#endif // _DEBUG
+ DH_SAME_AS_LOAD = 1,
+ DH_CONTAINED_OBJECT = 2, // indicates an embedding
+ DH_LOCKED_CONTAINER = 4,
+ DH_FORCED_RUNNING = 8,
+ DH_EMBEDDING = 16, // link or an embedding?
+ DH_INIT_NEW = 32,
+ DH_STATIC = 64,
+ DH_INPROC_HANDLER = 128,
+ DH_DELAY_CREATE = 256
+} DHFlags;
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDefObject
+//
+// Purpose: The default handler class. The object acts as a surrogate,
+// or handler for an out-of-process server exe.
+//
+// Interface: The default handler implements
+// IDataObject
+// IOleObject
+// IPersistStorage
+// IRunnableObject
+// IExternalConnection
+// IAdviseSink
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH added Dump method (_DEBUG only)
+// 15-Nov-94 alexgo memory optimization
+// 02-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+class CDefObject : public CSafeRefCount, public IDataObject,
+ public IOleObject, public IPersistStorage, public IRunnableObject,
+ public IExternalConnection, public CThreadCheck
+{
+public:
+
+ static IUnknown *Create (IUnknown *pUnkOuter,
+ REFCLSID clsidClass, DWORD flags, IClassFactory *pCF);
+
+ class CPrivUnknown : public IUnknown
+ {
+ public:
+ STDMETHOD(QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+ };
+
+ friend class CPrivUnknown;
+
+ CPrivUnknown m_Unknown;
+
+ // IUnknown methods
+
+ STDMETHOD(QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ // IDataObject methods
+
+ INTERNAL_(IDataObject *) GetDataDelegate(void);
+
+ STDMETHOD(GetData) ( LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium );
+ STDMETHOD(GetDataHere) ( LPFORMATETC pformatetc,
+ LPSTGMEDIUM pmedium );
+ STDMETHOD(QueryGetData) ( LPFORMATETC pformatetc );
+ STDMETHOD(GetCanonicalFormatEtc) ( LPFORMATETC pformatetc,
+ LPFORMATETC pformatetcOut);
+ STDMETHOD(SetData) ( LPFORMATETC pformatetc,
+ LPSTGMEDIUM pmedium, BOOL fRelease);
+ STDMETHOD(EnumFormatEtc) ( DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenumFormatEtc);
+ STDMETHOD(DAdvise) ( FORMATETC FAR* pFormatetc, DWORD advf,
+ IAdviseSink FAR* pAdvSink,
+ DWORD FAR* pdwConnection);
+ STDMETHOD(DUnadvise) ( DWORD dwConnection);
+ STDMETHOD(EnumDAdvise) ( LPENUMSTATDATA FAR* ppenumAdvise);
+
+ // IOleObject methods
+
+ INTERNAL_(IOleObject *)GetOleDelegate();
+
+ STDMETHOD(SetClientSite) ( LPOLECLIENTSITE pClientSite);
+ STDMETHOD(GetClientSite) ( LPOLECLIENTSITE FAR* ppClientSite);
+ STDMETHOD(SetHostNames) ( LPCOLESTR szContainerApp,
+ LPCOLESTR szContainerObj);
+ STDMETHOD(Close) ( DWORD reserved);
+ STDMETHOD(SetMoniker) ( DWORD dwWhichMoniker, LPMONIKER pmk);
+ STDMETHOD(GetMoniker) ( DWORD dwAssign, DWORD dwWhichMoniker,
+ LPMONIKER FAR* ppmk);
+ STDMETHOD(InitFromData) ( LPDATAOBJECT pDataObject,
+ BOOL fCreation,
+ DWORD dwReserved);
+ STDMETHOD(GetClipboardData) ( DWORD dwReserved,
+ LPDATAOBJECT FAR* ppDataObject);
+ STDMETHOD(DoVerb) ( LONG iVerb,
+ LPMSG lpmsg,
+ LPOLECLIENTSITE pActiveSite,
+ LONG lindex,
+ HWND hwndParent,
+ const RECT FAR* lprcPosRect);
+ STDMETHOD(EnumVerbs) ( IEnumOLEVERB FAR* FAR* ppenumOleVerb);
+ STDMETHOD(Update) (void);
+ STDMETHOD(IsUpToDate) (void);
+ STDMETHOD(GetUserClassID) ( CLSID FAR* pClsid);
+ STDMETHOD(GetUserType) ( DWORD dwFormOfType,
+ LPOLESTR FAR* pszUserType);
+ STDMETHOD(SetExtent) ( DWORD dwDrawAspect, LPSIZEL lpsizel);
+ STDMETHOD(GetExtent) ( DWORD dwDrawAspect, LPSIZEL lpsizel);
+ STDMETHOD(Advise)(IAdviseSink FAR* pAdvSink,
+ DWORD FAR* pdwConnection);
+ STDMETHOD(Unadvise)( DWORD dwConnection);
+ STDMETHOD(EnumAdvise) ( LPENUMSTATDATA FAR* ppenumAdvise);
+ STDMETHOD(GetMiscStatus) ( DWORD dwAspect,
+ DWORD FAR* pdwStatus);
+ STDMETHOD(SetColorScheme) ( LPLOGPALETTE lpLogpal);
+
+ // IPeristStorage methods
+
+ INTERNAL_(IPersistStorage *) GetPSDelegate(void);
+
+ STDMETHOD(GetClassID) ( LPCLSID pClassID);
+ STDMETHOD(IsDirty) (void);
+ STDMETHOD(InitNew) ( LPSTORAGE pstg);
+ STDMETHOD(Load) ( LPSTORAGE pstg);
+ STDMETHOD(Save) ( LPSTORAGE pstgSave, BOOL fSameAsLoad);
+ STDMETHOD(SaveCompleted) ( LPSTORAGE pstgNew);
+ STDMETHOD(HandsOffStorage) ( void);
+
+ // IRunnable Object methods
+
+ STDMETHOD(GetRunningClass) (LPCLSID lpClsid);
+ STDMETHOD(Run) (LPBINDCTX pbc);
+ STDMETHOD_(BOOL, IsRunning) (void);
+ STDMETHOD(LockRunning)(BOOL fLock, BOOL fLastUnlockCloses);
+ STDMETHOD(SetContainedObject)(BOOL fContained);
+
+ INTERNAL Stop(void);
+
+ // IExternalConnection methods
+
+ STDMETHOD_(DWORD, AddConnection) (THIS_ DWORD extconn,
+ DWORD reserved);
+ STDMETHOD_(DWORD, ReleaseConnection) (THIS_ DWORD extconn,
+ DWORD reserved, BOOL fLastReleaseCloses);
+
+
+ // NOTE: the advise sink has a separate controlling unknown from the
+ // other interfaces; the lifetime of the memory for this implementation
+ // is still the same as the default handler. The ramifications of
+ // this are that when the default handler goes away it must make sure
+ // that all pointers back to the sink are released; see the special
+ // code in the dtor of the default handler.
+ class CAdvSinkImpl : public IAdviseSink
+ {
+ public:
+ STDMETHOD(QueryInterface) ( REFIID iid, LPVOID FAR* ppvObj);
+
+ STDMETHOD_(ULONG,AddRef) (void);
+
+ STDMETHOD_(ULONG,Release) (void);
+
+ // *** IAdviseSink methods ***
+ STDMETHOD_(void,OnDataChange)( FORMATETC FAR* pFormatetc,
+ STGMEDIUM FAR* pStgmed);
+ STDMETHOD_(void,OnViewChange)( DWORD aspects, LONG lindex);
+ STDMETHOD_(void,OnRename)( IMoniker FAR* pmk);
+ STDMETHOD_(void,OnSave)(void);
+ STDMETHOD_(void,OnClose)(void);
+ };
+
+ friend class CAdvSinkImpl;
+
+ CAdvSinkImpl m_AdviseSink;
+
+#ifdef _DEBUG
+
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+
+ // need to be able to access CDefObject private data members in the
+ // following debugger extension APIs
+ // this allows the debugger extension APIs to copy memory from the
+ // debuggee process memory to the debugger's process memory
+ // this is required since the Dump method follows pointers to other
+ // structures and classes
+ friend DEBUG_EXTENSION_API(dump_defobject);
+
+#endif // _DEBUG
+
+private:
+
+ CDefObject (IUnknown *pUnkOuter);
+ virtual ~CDefObject (void);
+ INTERNAL_(void) CleanupForDelete(void);
+ INTERNAL_(ULONG) CheckDelete(ULONG ulRet);
+ INTERNAL GetClassBits(CLSID FAR* pClsidBits);
+ INTERNAL CreateDelegate(void);
+ INTERNAL DoConversionIfSpecialClass(LPSTORAGE pstg);
+
+#ifdef SERVER_HANDLER
+ INTERNAL SrvInitialize();
+ INTERNAL SrvRun();
+ INTERNAL SrvDoVerb( LONG iVerb, LPMSG lpmsg,
+ LPOLECLIENTSITE pActiveSite, LONG lindex,
+ HWND hwndParent, const RECT * lprcPosRect);
+
+ INTERNAL SrvRunAndDoVerb( LONG iVerb, LPMSG lpmsg,
+ LPOLECLIENTSITE pActiveSite, LONG lindex,
+ HWND hwndParent, const RECT * lprcPosRect);
+
+
+ INTERNAL_(DWORD) SrvRelease();
+ INTERNAL SrvCloseAndRelease(DWORD dwFlag);
+
+ INTERNAL_(void) InitializeServerHandlerOptions(REFCLSID clsidSrv);
+
+ BOOL CanUseServerHandler()
+ {
+ return ( (m_pCFDelegate == NULL) && (m_pProxyMgr != NULL)
+ && (_dwServerHandler & HO_UseServerHandler));
+ }
+ BOOL CanUseClientSiteHandler()
+ {
+ return (_dwClientSiteHandler & HO_UseClientSiteHandler);
+ }
+
+ IServerHandler * _pSrvHndlr; // pointer to remote serverhandler interface
+ CClientSiteHandler * _pClientSiteHandler; // pointer to local ClientSiteHandler
+ DWORD _dwServerHandler; // options from registery + local state
+ DWORD _dwClientSiteHandler; // options from registery + local state
+ DWORD _dwHandlerOptions; // handler options from registery
+#endif // SERVER_HANDLER
+
+
+ IOleObject * m_pOleDelegate;
+ IDataObject * m_pDataDelegate;
+ IPersistStorage * m_pPSDelegate;
+
+ DWORD m_fIsMaybeRunning; // ericoe test for running
+
+ DWORD m_cConnections;
+ ULONG m_cRefsOnHandler;
+ IUnknown * m_pUnkOuter;
+ CLSID m_clsidServer; // clsid of app we will run
+ CLSID m_clsidBits; // clsid of bits on disk;
+ // NULL init
+ CLSID m_clsidUser; // clsid returned be GetUserClassID
+
+
+ DWORD m_flags; // handler flags
+ IClassFactory * m_pCFDelegate; // only set if delayed create
+ IUnknown * m_pUnkDelegate;
+ IProxyManager * m_pProxyMgr;
+
+ // m_fForcedRunning indicates that the container forced the object
+ // running via ::Run or DoVerb. Handlers (EMBDHLP_INPROC_HANDLER) can
+ // can go running implicitly via marshaling (usually via moniker bind)
+ // and thus we actually use pProxyMgr->IsConnected to answer IsRunning.
+
+ // Distinguishes between embeddings and links. We cannot use
+ // m_pStg because it gets set to NULL in HandsOffStorage.
+
+ // data cache
+ COleCache * m_pCOleCache; // pointer to COleCache
+
+ // ole advise info
+ COAHolder * m_pOAHolder;
+ DWORD m_dwConnOle; // if not 0L, ole advise conn.
+
+ // info passed to server on run
+ IOleClientSite * m_pAppClientSite;
+ IStorage * m_pStg; // may be NULL
+ char * m_pHostNames; // store both host name strings
+ DWORD m_ibCntrObj; // offset into m_pHostNames
+ LPDATAADVCACHE m_pDataAdvCache;
+};
+
diff --git a/private/ole32/ole232/stdimpl/deflink.cpp b/private/ole32/ole232/stdimpl/deflink.cpp
new file mode 100644
index 000000000..0e211c9c2
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/deflink.cpp
@@ -0,0 +1,7776 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: deflink.h
+//
+// Contents: Implementation of the standard link object
+//
+// Classes: CDefLink
+//
+// Functions:
+//
+// Author:
+// Craig Wittenberg (craigwi) 8/12/92
+//
+// History: dd-mmm-yy Author Comment
+// 20-Feb-95 KentCe Buffered stream i/o.
+// 01-Feb-95 t-ScottH added Dump method to CDefLink
+// added DumpCDefLink API
+// added DLFlag to indicate if aggregated
+// (_DEBUG only)
+// 09-Jan-95 t-scotth changed VDATETHREAD to accept a pointer
+// 09-Jan-95 alexgo fixed a ton of link tracking bugs from
+// 16bit OLE.
+// 21-Nov-94 alexgo memory optimization
+// 28-Aug-94 alexgo added IsReallyRunning
+// 02-Aug-94 alexgo added object stabilization
+// 30-Jun-94 alexgo handles re-entrant shutdowns better
+// 31-May-94 alexgo now recovers from crashed servers
+// 06-May-94 alexgo made IsRunning work properly
+// 07-Mar-94 alexgo added call tracing
+// 03-Feb-94 alexgo fixed errors with SendOnLinkSrcChange
+// 11-Jan-94 alexgo added VDATEHEAP macros to every function
+// and method. Also fixed an aggregation bug,
+// allowing linking to work.
+// 22-Nov-93 alexgo removed overloaded GUID ==
+// 15-Nov-93 alexgo 32bit port
+//
+// ChrisWe 11/09/93 Changed COleCache::Update to COleCache::UpdateCache,
+// which does the same thing without an indirect fuction call
+// srinik 09/11/92 Removed IOleCache implementation, as a result of
+// removing voncache.cpp, and moving IViewObject
+// implementation into olecache.cpp.
+//
+// SriniK 06/04/92 Fixed problems in IPersistStorage methods
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+
+
+#include <scode.h>
+#include <objerror.h>
+
+#include "deflink.h"
+#include "defutil.h"
+
+#ifdef _DEBUG
+#include <dbgdump.h>
+#endif // _DEBUG
+
+#ifdef _TRACKLINK_
+#include <itrkmnk.hxx>
+#endif
+
+ASSERTDATA
+
+
+/*
+* IMPLEMENTATION of CDefLink
+*/
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::Create
+//
+// Synopsis: public function to create an instance of a link object
+//
+// Effects: allocates a new object
+//
+// Arguments: [pUnkOuter] -- pointer to the controlling unknown
+// (for aggregation)
+//
+// Requires:
+//
+// Returns: IUnkown FAR * to the link object
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 31-May-94 alexgo use new aggregation rules (release
+// through outer).
+// 15-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+IUnknown *CDefLink::Create(IUnknown FAR* pUnkOuter)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::Create ( %p )\n",
+ NULL /*we are a static function*/, pUnkOuter));
+
+ CDefLink FAR* pDefObj;
+
+ if ((pDefObj = new CDefLink(pUnkOuter)) == NULL)
+ {
+ goto errRtn;
+ }
+
+ pDefObj->m_cRefsOnLink = 1;
+ pDefObj->SafeAddRef();
+
+
+ if (CDataAdviseCache::CreateDataAdviseCache(&pDefObj->m_pDataAdvCache)
+ != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ // create cache and get commonly used pointers into it
+ if ((pDefObj->m_pCOleCache = new FAR COleCache(pDefObj->m_pUnkOuter,
+ CLSID_NULL)) == NULL)
+ {
+ // m_pDataAdvCache will be deleted in the destructor
+ goto errRtn;
+ }
+
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::Create ( %p )\n",
+ NULL, &pDefObj->m_Unknown));
+
+ return &pDefObj->m_Unknown;
+
+errRtn:
+ if(pDefObj)
+ {
+ LEDebugOut((DEB_TRACE, "DELETING link object %p\n",
+ pDefObj));
+ delete pDefObj;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::Create ( %p )\n",
+ NULL, NULL ));
+
+ return NULL;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::CDefLink
+//
+// Synopsis: Constructor for the default link object
+//
+// Effects:
+//
+// Arguments: [pUnkOuter] -- pointer to the controlling unknown
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 15-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CDefLink::CDefLink (IUnknown *pUnkOuter)
+{
+ VDATEHEAP();
+
+ static FILETIME z; //to zero out member variables
+
+ if (!pUnkOuter)
+ {
+ pUnkOuter = &m_Unknown;
+ }
+
+ m_pUnkOuter = pUnkOuter;
+
+ m_pDataDelegate = NULL;
+ m_pOleDelegate = NULL;
+ m_pRODelegate = NULL;
+ m_pOleItemContainerDelegate = NULL;
+
+ m_pMonikerAbs = NULL;
+ m_pMonikerRel = NULL;
+ m_pUnkDelegate = NULL;
+ m_dwUpdateOpt = OLEUPDATE_ALWAYS;
+ m_clsid = CLSID_NULL;
+
+ m_pStg = NULL;
+ m_flags = 0;
+
+ m_pCOleCache = NULL;
+
+ m_pCOAHolder = NULL;
+ m_dwConnOle = 0;
+ m_pAppClientSite = NULL;
+ m_pDataAdvCache = NULL;
+ m_dwConnTime = 0;
+
+ m_ltChangeOfUpdate = z;
+ m_ltKnownUpToDate = z;
+ m_rtUpdate = z;
+
+#ifdef _DEBUG
+ if (pUnkOuter != &m_Unknown)
+ {
+ m_flags |= DL_AGGREGATED;
+ }
+#endif // _DEBUG
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink:CleaupForDelete
+//
+// Synopsis: Releases pointers that have been addref'ed and otherwise
+// frees resources used by the deflink object
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 12-Jan-94 ChrisWe fixed cache release
+// 15-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CDefLink::CleanupForDelete(void)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::CleanupForDelete ( )\n",
+ this ));
+
+ if (m_pMonikerAbs)
+ {
+ m_pMonikerAbs->Release();
+ m_pMonikerAbs = NULL;
+ }
+
+ if (m_pMonikerRel)
+ {
+ m_pMonikerRel->Release();
+ m_pMonikerRel = NULL;
+ }
+
+ if (m_pCOleCache)
+ {
+ m_pCOleCache->m_UnkPrivate.Release();
+ m_pCOleCache = NULL;
+ }
+
+
+ if (m_pAppClientSite)
+ {
+ m_pAppClientSite->Release();
+ m_pAppClientSite = NULL;
+ }
+ Assert(!(m_flags & DL_LOCKED_CONTAINER));
+
+ if (m_pStg)
+ {
+ m_pStg->Release();
+ m_pStg = NULL;
+ }
+
+ m_flags &= ~(DL_DIRTY_LINK);
+
+ if (m_pCOAHolder)
+ {
+ Verify(m_pCOAHolder->Release() == 0);
+ m_pCOAHolder = NULL;
+ }
+
+ if (m_pDataAdvCache)
+ {
+ delete m_pDataAdvCache;
+ m_pDataAdvCache = NULL;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::CleanupForDelete ( )\n",
+ this ));
+
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpSzTime
+//
+// Synopsis: Prints the time in the FILETIME strucutre
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes: NYI for 32bit
+//
+//--------------------------------------------------------------------------
+
+#ifdef LINK_DEBUG
+INTERNAL_(void) DumpSzTime( LPOLESTR szMsg, FILETIME ft )
+{
+ VDATEHEAP();
+
+ WORD wDate, wTime;
+ XCHAR szBuffer[24];
+
+ CoFileTimeToDosDateTime(&ft, &wDate, &wTime);
+
+ int Day = ( wDate & 0x001F);
+ int Month = ( (wDate>>5) & 0x000F);
+ int Year = 1980 + ((wDate>>9) & 0x007F);
+
+ int Sec = ( wTime & 0x001F);
+ int Min = ( (wTime>>5) & 0x003F);
+ int Hour = ( (wTime>>11) & 0x001F);
+
+ wsprintf((LPOLESTR)szBuffer, " %02d:%02d:%02d on %02d/%02d/%04d\n",
+ Hour, Min, Sec, Month, Day, Year);
+ OutputDebugString(szMsg);
+ OutputDebugString(szBuffer);
+}
+#else
+#define DumpSzTime(a,b)
+#endif
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::SetUpdateTimes
+//
+// Synopsis: Internal function to save local and remote times for
+// link->IsUpToDate calculations
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: See notes below
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+// The basic problem in calculating link IsUpToDate is that
+// the local clock may be different than the remote clock.
+// The solution is to keep track of both times on *both*
+// clocks (i.e. time now and time of change on both the local
+// and remote clocks). IsUpToDate is calculated by comparing
+// the differences between the times on the two clocks. This,
+// of course, assumes that both clocks equivalently measure
+// a second.
+//
+//--------------------------------------------------------------------------
+
+INTERNAL CDefLink::SetUpdateTimes( void )
+{
+ VDATEHEAP();
+
+ FILETIME rtNewUpdate;
+ LPMONIKER pmkAbs = NULL;
+ HRESULT hresult;
+ LPBINDCTX pbc = NULL;
+
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::SetUpdateTimes ( )\n",
+ this ));
+
+ //use the relative moniker if it exists and if the container has a
+ //moniker
+ if (NOERROR != GetAbsMkFromRel(&pmkAbs, NULL))
+ {
+ //otherwise use the absolute moniker
+ pmkAbs = m_pMonikerAbs;
+ if (pmkAbs)
+ {
+ pmkAbs->AddRef();
+ }
+ }
+ if (pmkAbs == NULL)
+ {
+ hresult = E_UNSPEC;
+ goto errRet;
+ }
+
+ hresult = CreateBindCtx( 0, &pbc );
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+
+ //debugging aids
+ DumpSzTime("SetUpdateTimes (going in): rtUpdate = ",m_rtUpdate);
+ DumpSzTime("SetUpdateTimes (going in): ltKnownUpToDate = ",
+ m_ltKnownUpToDate);
+ DumpSzTime("SetUpdateTimes (going in): ltChangeOfUpdate = ",
+ m_ltChangeOfUpdate);
+
+ //get the current local time.
+ CoFileTimeNow(&m_ltKnownUpToDate);
+
+ //debugging aids
+ DumpSzTime("SetUpdateTimes: time now is ",m_ltKnownUpToDate);
+
+ //get the time of last change on the remote machine
+ hresult = pmkAbs->GetTimeOfLastChange(pbc, NULL, &rtNewUpdate);
+ if (hresult == NOERROR)
+ {
+ //if the remote time of last change is different than
+ //what we previously stored as the remote time of last change,
+ //then we update the remote time of last change and update
+ //our local time of last change.
+ //Since the IsUpToDate algorithm relies on taking the
+ //differences between times on the same clock and comparing
+ //those differences between machines, it is important that
+ //the two times (local and remote) are *set* simulataneously.
+
+ if ((rtNewUpdate.dwLowDateTime != m_rtUpdate.dwLowDateTime)||
+ (rtNewUpdate.dwHighDateTime !=
+ m_rtUpdate.dwHighDateTime))
+
+ {
+ // rtUpdate value is changing
+ m_rtUpdate = rtNewUpdate;
+
+ //debugging aid
+ DumpSzTime("rtUpdate changing to ", m_rtUpdate);
+ m_ltChangeOfUpdate = m_ltKnownUpToDate;
+
+ //debugging aid
+ DumpSzTime("ltChangeOfUpdate changing to ",
+ m_ltChangeOfUpdate);
+ m_flags |= DL_DIRTY_LINK;
+ }
+ }
+errRet:
+ //debugging aids
+ DumpSzTime("SetUpdateTimes (going out): rtUpdate = ",m_rtUpdate);
+ DumpSzTime("SetUpdateTimes (going out): ltKnownUpToDate = ",
+ m_ltKnownUpToDate);
+ DumpSzTime("SetUpdateTimes (going out): ltChangeOfUpdate = ",
+ m_ltChangeOfUpdate);
+
+ if (pmkAbs)
+ {
+ pmkAbs->Release();
+ }
+
+ if (pbc)
+ {
+ pbc->Release();
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::SetUpdateTimes ( %lx )\n",
+ this, hresult));
+
+ return(hresult);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::UpdateUserClassID
+//
+// Synopsis: Grabs the class ID from the remote server (our delegate)
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+// update clsid from server if running; necessary because link source in
+// treatas case may decide to change the clsid (e.g., if features are used
+// which aren't supported by the old clsid).
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CDefLink::UpdateUserClassID(void)
+{
+ VDATEHEAP();
+
+ CLSID clsid;
+ IOleObject *pOleDelegate;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::UpdateUserClass ( )\n",
+ this));
+
+ if( (pOleDelegate = GetOleDelegate()) != NULL &&
+ pOleDelegate->GetUserClassID(&clsid) == NOERROR)
+ {
+ m_clsid = clsid;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::UpdateUserClass ( )\n",
+ this ));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::~CDefLink
+//
+// Synopsis: The destructor.
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes: Should only be called after CleanupForDelete
+// and both ref counts are zero
+//
+//--------------------------------------------------------------------------
+
+CDefLink::~CDefLink (void)
+{
+ VDATEHEAP();
+
+ CleanupForDelete();
+
+ Assert(m_pMonikerAbs == NULL);
+ Assert(m_pMonikerRel == NULL);
+ Assert(m_pUnkDelegate == NULL);
+ Assert(m_pStg == NULL);
+ Assert(!(m_flags & DL_DIRTY_LINK));
+ Assert(m_pCOleCache == NULL);
+ Assert(m_pCOAHolder == NULL);
+ Assert(m_pAppClientSite == NULL);
+ Assert(!(m_flags & DL_LOCKED_CONTAINER) );
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::CPrivUnkown::AddRef
+//
+// Synopsis: increments the reference count
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG (the new reference count)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IUnknown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDefLink::CPrivUnknown::AddRef( void )
+{
+ VDATEHEAP();
+
+ CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_Unknown);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CUnknownImpl::AddRef ( )\n",
+ pDefLink));
+
+ ++pDefLink->m_cRefsOnLink;
+ pDefLink->SafeAddRef();
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CUnknownImpl::AddRef "
+ "( %lu )\n", pDefLink, pDefLink->m_cRefsOnLink));
+
+ return pDefLink->m_cRefsOnLink;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::CPrivUnknown::Release
+//
+// Synopsis: Decrements the reference count, deleting the object if
+// count == zero
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IUnknown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDefLink::CPrivUnknown::Release( void )
+{
+ VDATEHEAP();
+ ULONG cRefs;
+
+ CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_Unknown);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CUnknownImpl::Release ( )\n",
+ pDefLink ));
+
+ if( pDefLink->m_cRefsOnLink == 1 )
+ {
+ pDefLink->SafeAddRef(); // Guard
+ pDefLink->UnbindSource();
+ pDefLink->SafeRelease();
+ }
+
+ cRefs = --pDefLink->m_cRefsOnLink;
+ pDefLink->SafeRelease();
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CUnknownImpl::Release "
+ "( %lu )\n", pDefLink, cRefs));
+
+ return cRefs;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::CPrivUnknown::QueryInterface
+//
+// Synopsis: The link's private QI implementation
+//
+// Effects:
+//
+// Arguments: [iid] -- the requested interface ID
+// [ppv] -- where to put the pointer to the interface
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IUnknown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 11-Jan-94 alexgo QI to the cache now queries to the cache's
+// private IUnknown implementation
+// 22-Nov-93 alexgo removed overloaded GUID ==
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::CPrivUnknown::QueryInterface(REFIID iid,
+ LPLPVOID ppv)
+{
+ HRESULT hresult = NOERROR;
+ CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_Unknown);
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CPrivUnknown::QueryInterface"
+ " ( %p , %p )\n", pDefLink, iid, ppv));
+
+ if (IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppv = (void FAR *)&pDefLink->m_Unknown;
+ //AddRef this object (not the aggregate)
+ AddRef();
+ // hresult already set to NOERROR;
+ goto errRtn;
+ }
+ else if (IsEqualIID(iid, IID_IOleObject))
+ {
+ *ppv = (void FAR *) (IOleObject *)pDefLink;
+ }
+ else if (IsEqualIID(iid, IID_IDataObject))
+ {
+ *ppv = (void FAR *) (IDataObject *)pDefLink;
+ }
+ else if (IsEqualIID(iid, IID_IOleLink))
+ {
+ *ppv = (void FAR *) (IOleLink *)pDefLink;
+ }
+ else if (IsEqualIID(iid, IID_IRunnableObject))
+ {
+ *ppv = (void FAR *) (IRunnableObject *)pDefLink;
+ }
+ else if (IsEqualIID(iid, IID_IViewObject) ||
+ IsEqualIID(iid, IID_IOleCache) ||
+ IsEqualIID(iid, IID_IViewObject2) ||
+ IsEqualIID(iid, IID_IOleCache2) )
+ {
+ hresult =
+ pDefLink->m_pCOleCache->m_UnkPrivate.QueryInterface(iid,ppv);
+ goto errRtn;
+ }
+ else if (IsEqualIID(iid, IID_IPersistStorage) ||
+ IsEqualIID(iid, IID_IPersist))
+ {
+ *ppv = (void FAR *) (IPersistStorage *)pDefLink;
+ }
+ else
+ {
+ *ppv = NULL;
+ hresult = E_NOINTERFACE;
+ goto errRtn;
+ }
+
+ pDefLink->m_pUnkOuter->AddRef();
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CPrivUnknown::QueryInterface"
+ " ( %lx ) [ %p ]\n", pDefLink, hresult, *ppv));
+
+ return(hresult);
+}
+
+
+/*
+ * IMPLEMENTATION of IUnknown methods
+ */
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::QueryInterface
+//
+// Synopsis: QI's to the controlling IUnknown
+//
+// Effects:
+//
+// Arguments: [riid] -- the interface ID
+// [ppv] -- where to put it
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IUnknown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Nov-94 alexgo author
+//
+// Notes: We do *not* need to stabilize this method as only
+// one outgoing call is made and we do not use the
+// 'this' pointer afterwards
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::QueryInterface( REFIID riid, void **ppv )
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::QueryInterface ( %lx , "
+ "%p )\n", this, riid, ppv));
+
+ Assert(m_pUnkOuter);
+
+ hresult = m_pUnkOuter->QueryInterface(riid, ppv);
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::QueryInterface ( %lx ) "
+ "[ %p ]\n", this, hresult, *ppv));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::AddRef
+//
+// Synopsis: delegates AddRef to the controlling IUnknown
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IUnknown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Nov-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDefLink::AddRef( void )
+{
+ ULONG crefs;;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::AddRef ( )\n", this));
+
+ Assert(m_pUnkOuter);
+
+ crefs = m_pUnkOuter->AddRef();
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::AddRef ( %ld ) ", this,
+ crefs));
+
+ return crefs;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::Release
+//
+// Synopsis: delegates Release to the controlling IUnknown
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IUnknown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Nov-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDefLink::Release( void )
+{
+ ULONG crefs;;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Release ( )\n", this));
+
+ Assert(m_pUnkOuter);
+
+ crefs = m_pUnkOuter->Release();
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Release ( %ld )\n", this,
+ crefs));
+
+ return crefs;
+}
+
+/*
+ * IMPLEMENTATION of CDataObjectImpl methods
+ */
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetDataDelegate
+//
+// Synopsis: Private method to get the IDataObject interface on
+// the server delegate for the link
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: IDataObject *
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+// This function may return misleading information if the
+// server has died (i.e., you'll return a pointer to a cached
+// interface proxy). It is the responsibility of the caller
+// to handler server crashes.
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(IDataObject *) CDefLink::GetDataDelegate(void)
+{
+ VDATEHEAP();
+
+ IDataObject *pDataDelegate;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::GetDataDelegate ( )\n",
+ this ));
+
+ if( !IsZombie() )
+ {
+ DuCacheDelegate(&m_pUnkDelegate,
+ IID_IDataObject, (LPLPVOID)&m_pDataDelegate, NULL);
+ pDataDelegate = m_pDataDelegate;
+#if DBG == 1
+ if( m_pDataDelegate )
+ {
+ Assert(m_pUnkDelegate);
+ }
+#endif // DBG == 1
+
+ }
+ else
+ {
+ pDataDelegate = NULL;
+ }
+
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::GetData"
+ "Delegate ( %p )\n", this, pDataDelegate));
+
+ return pDataDelegate;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::ReleaseDataDelegate
+//
+// Synopsis: Private method to release the IDataObject pointer on the
+// server to which we are linked
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CDefLink::ReleaseDataDelegate(void)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::ReleaseDataDelegate ( )\n",
+ this));
+
+ if (m_pDataDelegate)
+ {
+ SafeReleaseAndNULL((IUnknown **)&m_pDataDelegate);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::ReleaseData"
+ "Delegate ( )\n", this ));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetData
+//
+// Synopsis: Gets data from the server
+//
+// Effects:
+//
+// Arguments: [pfromatetcIn] -- the requested data format
+// [pmedium] -- where to put the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: Tries the cache first, then asks the server
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium )
+{
+ HRESULT hresult = NOERROR;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetData"
+ " ( %p , %p )\n", this, pformatetcIn, pmedium));
+
+ VDATEPTROUT( pmedium, STGMEDIUM );
+ VDATEREADPTRIN( pformatetcIn, FORMATETC );
+
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( !HasValidLINDEX(pformatetcIn) )
+ {
+ return DV_E_LINDEX;
+ }
+
+ pmedium->tymed = TYMED_NULL;
+ pmedium->pUnkForRelease = NULL;
+
+
+ Assert(m_pCOleCache != NULL);
+ if( m_pCOleCache->m_Data.GetData(pformatetcIn, pmedium) != NOERROR)
+ {
+ if( GetDataDelegate() )
+ {
+ hresult = m_pDataDelegate->GetData(pformatetcIn,
+ pmedium);
+ AssertOutStgmedium(hresult, pmedium);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetData"
+ " ( %lx )\n", this, hresult));
+
+ return(hresult);
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetDataHere
+//
+// Synopsis: Retrieves data into the specified pmedium
+//
+// Effects:
+//
+// Arguments: [pformatetcIn] -- the requested format
+// [pmedium] -- where to put the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: Asks the cache first, then the server delegate
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetDataHere( LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium )
+{
+ HRESULT hresult = NOERROR;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetDataHere"
+ " ( %p , %p )\n", this, pformatetcIn, pmedium));
+
+ VDATEREADPTRIN( pformatetcIn, FORMATETC );
+ VDATEREADPTRIN( pmedium, STGMEDIUM );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( !HasValidLINDEX(pformatetcIn) )
+ {
+ return DV_E_LINDEX;
+ }
+
+ Assert(m_pCOleCache != NULL);
+ if( m_pCOleCache->m_Data.GetDataHere(pformatetcIn, pmedium) != NOERROR )
+ {
+ if ( GetDataDelegate() )
+ {
+ hresult = m_pDataDelegate->GetDataHere(pformatetcIn,
+ pmedium);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetDataHere"
+ " ( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::QueryGetData
+//
+// Synopsis: Returns whether or not a GetData call for the requested
+// format would succeed.
+//
+// Effects:
+//
+// Arguments: [pformatetcIn] -- the requested data format
+//
+// Requires:
+//
+// Returns: HRESULT (NOERROR == GetData would succeed)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: Asks the cache first, then the server delegate (if the
+// cache call fails)
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::QueryGetData(LPFORMATETC pformatetcIn )
+{
+ HRESULT hresult = NOERROR;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::QueryGetData"
+ " ( %p )\n", this, pformatetcIn));
+
+ VDATEREADPTRIN( pformatetcIn, FORMATETC );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( !HasValidLINDEX(pformatetcIn) )
+ {
+ hresult = DV_E_LINDEX;
+ goto errRtn;
+ }
+
+ Assert(m_pCOleCache != NULL);
+ if( m_pCOleCache->m_Data.QueryGetData(pformatetcIn) != NOERROR )
+ {
+ if ( GetDataDelegate() )
+ {
+ hresult = m_pDataDelegate->QueryGetData(pformatetcIn);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::QueryGetData"
+ " ( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetCanonicalFormatEtc
+//
+// Synopsis: Gets the cannonical (or preferred) data format for the
+// object (choosing from the given formats)
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- the requested formats
+// [pformatetcOut] -- where to to put the canonical format
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: Delegates to the server (if running)
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetCanonicalFormatEtc( LPFORMATETC pformatetc,
+ LPFORMATETC pformatetcOut)
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Get"
+ "CanonicalFormatetc ( %p , %p )\n", this, pformatetc,
+ pformatetcOut));
+
+ VDATEPTROUT( pformatetcOut, FORMATETC );
+ VDATEREADPTRIN( pformatetc, FORMATETC );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ pformatetcOut->ptd = NULL;
+ pformatetcOut->tymed = TYMED_NULL;
+
+ if (!HasValidLINDEX(pformatetc))
+ {
+ return DV_E_LINDEX;
+ }
+
+ if( GetDataDelegate() )
+ {
+ hresult = m_pDataDelegate->GetCanonicalFormatEtc(pformatetc,
+ pformatetcOut);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Get"
+ "CanonicalFormatetc ( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::SetData
+//
+// Synopsis: Stuffs data into an object (such as an icon)
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- the format of the data
+// [pmedium] -- the data
+// [fRelease] -- if TRUE, then the data should be free'd
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: Delegates to the server
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes: The cache gets updated via a OnDataChange advise
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::SetData( LPFORMATETC pformatetc,
+ LPSTGMEDIUM pmedium, BOOL fRelease)
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetData"
+ " ( %p , %p , %lu )\n", this, pformatetc, pmedium,
+ fRelease));
+
+ VDATEREADPTRIN( pformatetc, FORMATETC );
+ VDATEREADPTRIN( pmedium, STGMEDIUM );
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( !HasValidLINDEX(pformatetc) )
+ {
+ hresult = DV_E_LINDEX;
+ goto errRtn;
+
+ }
+
+ if( GetDataDelegate() )
+ {
+ hresult = m_pDataDelegate->SetData(pformatetc, pmedium,
+ fRelease);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetData "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::EnumFormatEtc
+//
+// Synopsis: Enumerates the formats accepted for either GetData or SetData
+//
+// Effects:
+//
+// Arguments: [dwDirection] -- which formats (1 == GetData or
+// 2 == SetData)
+// [ppenumFormatEtc] -- where to put the enumerator
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: Delegates to the server, if not available or the server
+// returns OLE_E_USEREG
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 30-May-94 alexgo now handles crashed servers
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::EnumFormatEtc( DWORD dwDirection,
+ LPENUMFORMATETC *ppenumFormatEtc)
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ VDATEPTROUT(ppenumFormatEtc, LPENUMFORMATETC);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::EnumFormat"
+ "Etc ( %lu , %p )\n", this, dwDirection,
+ ppenumFormatEtc));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( GetDataDelegate() )
+ {
+ hresult=m_pDataDelegate->EnumFormatEtc (dwDirection,
+ ppenumFormatEtc);
+
+ if( !GET_FROM_REGDB(hresult) )
+ {
+ if( SUCCEEDED(hresult) || IsReallyRunning() )
+ {
+ // if we failed, but the server is still
+ // running, then go ahead and propogate the
+ // error to the caller.
+ // Note that IsReallyRunning will clean up our
+ // state if the server had crashed.
+ goto errRtn;
+ }
+
+ // FALL-THROUGH!! This is deliberate. If
+ // the call failed and the server is no longer
+ // running, then we assume the server has crashed.
+ // We want to go ahead and fetch the information
+ // from the registry.
+ }
+ }
+
+ // Not running or object wants to use reg db anyway
+ hresult = OleRegEnumFormatEtc(m_clsid, dwDirection,
+ ppenumFormatEtc);
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::EnumFormat"
+ "Etc ( %lx ) [ %p ]\n", this, hresult,
+ *ppenumFormatEtc));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::DAdvise
+//
+// Synopsis: Sets up a data advise connection
+//
+// Effects:
+//
+// Arguments: [pFormatetc] -- the data format to advise on
+// [advf] -- advise flags
+// [pAdvSink] -- whom to notify
+// [pdwConnection] -- where to put the advise connection ID
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: Delegates to the advise cache
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::DAdvise(FORMATETC *pFormatetc, DWORD advf,
+ IAdviseSink *pAdvSink, DWORD *pdwConnection)
+{
+ HRESULT hresult;
+ IDataObject * pDataDelegate;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::DAdvise "
+ "( %p , %lu , %p , %p )\n", this, pFormatetc, advf,
+ pAdvSink, pdwConnection ));
+
+ VDATEREADPTRIN( pFormatetc, FORMATETC );
+ VDATEIFACE( pAdvSink );
+
+ if (pdwConnection)
+ {
+ VDATEPTROUT( pdwConnection, DWORD );
+ *pdwConnection = NULL;
+ }
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if (!HasValidLINDEX(pFormatetc))
+ {
+ hresult = DV_E_LINDEX;
+ goto errRtn;
+ }
+
+ pDataDelegate = GetDataDelegate(); // NULL if not running
+
+ hresult = m_pDataAdvCache->Advise(pDataDelegate,
+ pFormatetc, advf, pAdvSink, pdwConnection);
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::DAdvise "
+ "( %lx ) [ %p ]\n", this, hresult, (pdwConnection) ?
+ *pdwConnection : 0 ));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::DUnadvise
+//
+// Synopsis: Destroys a data advise connection
+//
+// Effects:
+//
+// Arguments: [dwConnection] -- the connection to dismantle
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: delegates to the data advise cache
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::DUnadvise(DWORD dwConnection)
+{
+ HRESULT hresult;
+ IDataObject FAR* pDataDelegate;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::DUnadvise"
+ " ( %lu )\n", this, dwConnection ));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ pDataDelegate = GetDataDelegate();// NULL if not running
+
+ hresult = m_pDataAdvCache->Unadvise(pDataDelegate, dwConnection);
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::DUnadvise ( %lx )\n",
+ this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::EnumDAdvise
+//
+// Synopsis: Enumerates the data advise connections to the object
+//
+// Effects:
+//
+// Arguments: [ppenumAdvise] -- where to put the enumerator
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IDataObject
+//
+// Algorithm: delegates to the data advise cache
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes: This method does NOT have to be stabilized as we are
+// only going to be allocating memory for the enumerator
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::EnumDAdvise( LPENUMSTATDATA *ppenumAdvise )
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::EnumDAdvise"
+ " ( %p )\n", this, ppenumAdvise));
+
+ hresult = m_pDataAdvCache->EnumAdvise (ppenumAdvise);
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::EnumDAdvise"
+ " ( %lx ) [ %p ]\n", this, hresult, *ppenumAdvise));
+
+ return hresult;
+}
+
+
+
+/*
+* IMPLEMENTATION of COleObjectImpl methods
+*
+*/
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetOleDelegate
+//
+// Synopsis: Gets the IOleObject interface from the server, private method
+//
+// Effects:
+//
+// Arguments: [void]
+//
+// Requires:
+//
+// Returns: IOleObject *
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized and handled the zombie state
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+// This function may return misleading information if the
+// server has died (i.e., you'll return a pointer to a cached
+// interface proxy). It is the responsibility of the caller
+// to handler server crashes.
+//
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(IOleObject *) CDefLink::GetOleDelegate(void)
+{
+ IOleObject *pOleDelegate;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::GetOle"
+ "Delegate ( )\n", this ));
+
+ if( !IsZombie() )
+ {
+ DuCacheDelegate(&m_pUnkDelegate,
+ IID_IOleObject, (LPLPVOID)&m_pOleDelegate, NULL);
+
+ pOleDelegate = m_pOleDelegate;
+
+#if DBG == 1
+ if( m_pOleDelegate )
+ {
+ Assert(m_pUnkDelegate);
+ }
+#endif // DBG == 1
+ }
+ else
+ {
+ pOleDelegate = NULL;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::GetOle"
+ "Delegate ( %p )\n", this, pOleDelegate));
+
+ return pOleDelegate;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::ReleaseOleDelegate (private)
+//
+// Synopsis: Releases the IOleObject pointer from the server
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CDefLink::ReleaseOleDelegate(void)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::ReleaseOle"
+ "Delegate ( )\n", this ));
+
+ if (m_pOleDelegate)
+ {
+ SafeReleaseAndNULL((IUnknown **)&m_pOleDelegate);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::ReleaseOle"
+ "Delegate ( )\n", this ));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::SetClientSite
+//
+// Synopsis: Sets the client site for the object
+//
+// Effects:
+//
+// Arguments: [pClientSite] -- the client site
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Stores the pointer; if the link is running, then
+// the LockContainer is called via the client site by
+// the DuSetClientSite helper function
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized and handled zombie state
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::SetClientSite( IOleClientSite *pClientSite )
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetClientSite"
+ " ( %p )\n", this, pClientSite));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( IsZombie() )
+ {
+ // we don't want to change our state (i.e. reset the
+ // the client site) if we're zombied, because it's possible
+ // that we'd never be able to release the client site again
+ // resulting in memory leaks or faults.
+
+ hresult = CO_E_RELEASED;
+ }
+ else
+ {
+ BOOL fLockedContainer = (m_flags & DL_LOCKED_CONTAINER);
+
+ // here we use whether or not we've been bound to the server
+ // as the test for whether or not we're running (even though
+ // the server may have crashed since we last bound). We do
+ // this because DuSetClientSite will Unlock the old container
+ // and lock the new if we're running. Thus, if we've ever been
+ // running, we need to unlock the old container (even though
+ // we may not currently be running).
+
+ hresult = DuSetClientSite(
+ m_pUnkDelegate ? TRUE : FALSE,
+ pClientSite,
+ &m_pAppClientSite,
+ &fLockedContainer);
+
+ if(fLockedContainer)
+ {
+ m_flags |= DL_LOCKED_CONTAINER;
+ }
+ else
+ {
+ m_flags &= ~(DL_LOCKED_CONTAINER);
+ }
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetClientSite"
+ " ( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetClientSite
+//
+// Synopsis: Retrieves the stored client site pointer
+//
+// Effects:
+//
+// Arguments: [ppClientSite] -- where to put the client site pointer
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 22-Nov-93 alexgo inlined DuGetClientSite
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetClientSite( IOleClientSite **ppClientSite )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetClientSite ( %p )\n",
+ this, ppClientSite));
+
+ VDATEPTROUT(ppClientSite, IOleClientSite *);
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ *ppClientSite = m_pAppClientSite;
+
+ if( *ppClientSite )
+ {
+ (*ppClientSite)->AddRef();
+ }
+
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetClientSite"
+ " ( %lx ) [ %p ] \n", this, NOERROR, *ppClientSite));
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::SetHostNames
+//
+// Synopsis: In principal, should set the names to be drawn for
+// the server object. Not relevant for links (link servers
+// are not a part of the document being edited).
+//
+// Effects:
+//
+// Arguments: [szContainerApp] -- the name of the container
+// [szContainerObj] -- the container's name for the object
+//
+// Requires:
+//
+// Returns: HRESULT (NOERROR currently)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::SetHostNames
+ (LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetHostNames"
+ " ( %p , %p )\n", this, szContainerApp, szContainerObj));
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetHostNames"
+ " ( %lx )\n", this, NOERROR));
+
+ return NOERROR; // makes the embedded/link case more the same
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::Close
+//
+// Synopsis: Closes the object (in this case, just saves and unbinds the
+// link)
+//
+// Effects:
+//
+// Arguments: [dwFlags] -- clising flags (such as SAVEIFDIRTY)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+STDMETHODIMP CDefLink::Close( DWORD dwFlags )
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Close "
+ "( %lu )\n", this, dwFlags));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if (dwFlags != OLECLOSE_NOSAVE)
+ {
+ AssertSz(dwFlags == OLECLOSE_SAVEIFDIRTY,
+ "OLECLOSE_PROMPTSAVE is inappropriate\n");
+ if( IsDirty() == NOERROR )
+ {
+ if( m_pAppClientSite )
+ {
+ m_pAppClientSite->SaveObject();
+ }
+ }
+
+ }
+
+ // just unbind.
+ UnbindSource();
+
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Close "
+ "( %lx )\n", this, NOERROR));
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::SetMoniker
+//
+// Synopsis: Sets the moniker to the link object
+//
+// Effects:
+//
+// Arguments: [dwWhichMoniker] -- which moniker
+// [pmk] -- the new moniker
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: calls utility method UpdateRelMkFromAbsMk
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+// The moniker of the container is changing.
+// The next time we bind, we will try using the container moniker
+// composed with the relative moniker, and then, if that fails,
+// the absolute moniker, so there is no real need for us to
+// change these monikers.
+//
+// However, there are two cases when we know the absolute moniker
+// is the correct one, and we can take this opportunity to
+// recompute the relative moniker (which is changing because
+// the container moniker is changing). The advantage of this is
+// that GetDisplayName can return a better result in the interim
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::SetMoniker( DWORD dwWhichMoniker, LPMONIKER pmk )
+{
+ HRESULT hresult = NOERROR;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetMoniker "
+ "( %lx , %p )\n", this, dwWhichMoniker, pmk));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( IsZombie() )
+ {
+ hresult = CO_E_RELEASED;
+ }
+ else if (dwWhichMoniker == OLEWHICHMK_CONTAINER
+ || dwWhichMoniker == OLEWHICHMK_OBJFULL)
+ {
+ if( m_pMonikerRel == NULL || m_pUnkDelegate)
+ {
+ UpdateRelMkFromAbsMk(pmk);
+ }
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetMoniker"
+ " ( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetMoniker
+//
+// Synopsis: Retrieves the moniker for the object
+//
+// Effects:
+//
+// Arguments: [dwAssign] -- flags (such as wether a moniker should
+// be assigned to the object if none currently
+// exits)
+// [dwWhichMoniker]-- which moniker to get (relative/absolute/etc)
+// [ppmk] -- where to put a pointer to the moniker
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: asks the client site for the moniker
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetMoniker( DWORD dwAssign, DWORD dwWhichMoniker,
+ LPMONIKER *ppmk)
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetMoniker "
+ "( %lx , %lx , %p )\n", this, dwAssign, dwWhichMoniker,
+ ppmk));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( m_pAppClientSite )
+ {
+ hresult = m_pAppClientSite->GetMoniker(dwAssign, dwWhichMoniker,
+ ppmk);
+ }
+ else
+ {
+ // no client site
+ *ppmk = NULL;
+ hresult = E_UNSPEC;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetMoniker "
+ "( %lx ) [ %p ]\n", this, hresult, *ppmk ));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::InitFromData
+//
+// Synopsis: Initializes the object from the given data
+//
+// Effects:
+//
+// Arguments: [pDataObject] -- the data object to initialize from
+// [fCreation] -- TRUE indicates the object is being
+// created, FALSE a data transfer
+// [dwReserved] -- unused
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Delegates to the server
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::InitFromData( LPDATAOBJECT pDataObject, BOOL fCreation,
+ DWORD dwReserved)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::InitFromData "
+ "( %p , %lu , %lx )\n", this, pDataObject, fCreation,
+ dwReserved));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->InitFromData(pDataObject,
+ fCreation, dwReserved);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::InitFromData "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetClipboardData
+//
+// Synopsis: Retrieves a data object that could be put on the clipboard
+//
+// Effects:
+//
+// Arguments: [dwReserved] -- unused
+// [ppDataObject] -- where to put the pointer to the data
+// object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Delegates to the server object
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetClipboardData( DWORD dwReserved,
+ LPDATAOBJECT *ppDataObject)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetClipboard"
+ "Data ( %lx , %p )\n", this, dwReserved, ppDataObject));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if ( GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->GetClipboardData (dwReserved,
+ ppDataObject);
+ }
+ else
+ {
+ hresult = OLE_E_NOTRUNNING;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetClipboard"
+ "Data ( %lx ) [ %p ]\n", this, hresult, *ppDataObject));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::DoVerb
+//
+// Synopsis: Sends a verb to the object (such as Open)
+//
+// Effects:
+//
+// Arguments: [iVerb] -- the verb
+// [lpmsg] -- the window's message that caused the verb
+// [pActiveSite] -- the site where the object was activated
+// [lindex] -- unused currently
+// [hwndParent] -- the parent window of the container
+// [lprcPosRect] -- the rectange bounding the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Binds to the server and then delegates the DoVerb call
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes: If we had bound to the server and it crashed, we pretend it
+// was still running anyway for DoVerb (our call to BindToSource
+// will re-run it). Essentially, this algorithm "fixes" the
+// crash and restores the link's state.
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::DoVerb
+ (LONG iVerb, LPMSG lpmsg, LPOLECLIENTSITE pActiveSite, LONG lindex,
+ HWND hwndParent, LPCRECT lprcPosRect)
+{
+ HRESULT hresult;
+ BOOL bStartedNow = !m_pUnkDelegate;
+
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::DoVerb "
+ "( %ld , %ld , %p , %ld , %lx , %p )\n", this, iVerb,
+ lpmsg, pActiveSite, lindex, hwndParent, lprcPosRect));
+
+ if( lpmsg )
+ {
+ VDATEPTRIN( lpmsg, MSG );
+ }
+
+ if( pActiveSite )
+ {
+ VDATEIFACE( pActiveSite );
+ }
+
+
+ if( lprcPosRect )
+ {
+ VDATEPTRIN(lprcPosRect, RECT);
+ }
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( lindex != 0 && lindex != -1 )
+ {
+ hresult = DV_E_LINDEX;
+ goto errRtn;
+ }
+
+ // if we had crashed, BindToSource will reconnect us
+
+ if ( FAILED(hresult = BindToSource(0, NULL)) )
+ {
+ goto errRtn;
+ }
+
+ // we don't propogate hide to server; this (and other behavior)
+ // favors the link object as serving an OLE container rather than
+ // a general programmability client. This leave the link running,
+ // possibly invisible.
+
+ if (iVerb == OLEIVERB_HIDE)
+ {
+ hresult = NOERROR;
+ goto errRtn;
+ }
+
+ if( GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->DoVerb(iVerb, lpmsg, pActiveSite,
+ lindex, hwndParent, lprcPosRect);
+ }
+ else
+ {
+ hresult = E_NOINTERFACE;
+ }
+
+ if (bStartedNow && FAILED(hresult))
+ {
+ UnbindSource();
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::DoVerb "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::EnumVerbs
+//
+// Synopsis: Enumerate the verbs accepted by this object
+//
+// Effects:
+//
+// Arguments: [ppenumOleVerb] -- where to put the pointer to the enumerator
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: askes the server delegate. If not there or it returns
+// OLE_E_USEREG, then we get the info from the registration
+// database
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 30-May-94 alexgo now handles crashed servers
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::EnumVerbs( IEnumOLEVERB **ppenumOleVerb )
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::EnumVerbs "
+ "( %p )\n", this, ppenumOleVerb));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->EnumVerbs(ppenumOleVerb);
+
+ if( !GET_FROM_REGDB(hresult) )
+ {
+ if( SUCCEEDED(hresult) || IsReallyRunning() )
+ {
+ // if we failed, but the server is still
+ // running, then go ahead and propogate the
+ // error to the caller.
+ // Note that IsReallyRunning will clean up our
+ // state if the server had crashed.
+ goto errRtn;
+ }
+ // FALL-THROUGH!! This is deliberate. If
+ // the call failed and the server is no longer
+ // running, then we assume the server has crashed.
+ // We want to go ahead and fetch the information
+ // from the registry.
+ }
+ }
+
+ // Not running or object wants to use reg db anyway
+ hresult = OleRegEnumVerbs(m_clsid, ppenumOleVerb);
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::EnumVerbs "
+ "( %lx ) [ %p ]\n", this, hresult, *ppenumOleVerb));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetUserClassID
+//
+// Synopsis: Retrieves the class id of the linked object
+//
+// Effects:
+//
+// Arguments: [pClassID] -- where to put the class ID
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes: No need to stabilize as we make no outgoing calls
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetUserClassID(CLSID *pClassID)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetUserClass"
+ "ID ( %p )\n", this, pClassID));
+
+ VDATEPTROUT(pClassID, CLSID);
+
+ *pClassID = m_clsid;
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetUserClass"
+ "ID ( %lx )\n", this, NOERROR ));
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetUserType
+//
+// Synopsis: Retrieves a descriptive string about the server type
+//
+// Effects:
+//
+// Arguments: [dwFormOfType] -- indicates whether a short or long string
+// description is desired
+// [pszUserType] -- where to put the string
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Asks the server delegate, if that fails or the server
+// returns OLE_E_USEREG, then get the info from the registration
+// database
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 30-May-94 alexgo now handles crashed servers
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetUserType(DWORD dwFormOfType,
+ LPOLESTR *ppszUserType)
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetUserType "
+ "( %lu , %p )\n", this, dwFormOfType, ppszUserType));
+
+ VDATEPTROUT(ppszUserType, LPOLESTR);
+ *ppszUserType = NULL;
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+
+ if( GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->GetUserType (dwFormOfType,
+ ppszUserType);
+
+ if( !GET_FROM_REGDB(hresult) )
+ {
+ if( SUCCEEDED(hresult) || IsReallyRunning() )
+ {
+ // if we failed, but the server is still
+ // running, then go ahead and propogate the
+ // error to the caller.
+ // Note that IsReallyRunning will clean up our
+ // state if the server had crashed.
+ goto errRtn;
+ }
+ // FALL-THROUGH!! This is deliberate. If
+ // the call failed and the server is no longer
+ // running, then we assume the server has crashed.
+ // We want to go ahead and fetch the information
+ // from the registry.
+
+ }
+ }
+
+ // Not running, or object wants to use reg db anyway
+
+ // Consult reg db
+ hresult = OleRegGetUserType(m_clsid, dwFormOfType,
+ ppszUserType);
+
+ // it is not appropriate to read from the stg since the storage is
+ // owned by the link, not the link source (thus, the link source
+ // never has the opportunity to call WriteFmtUserTypeStg on the
+ // link object's storage).
+
+ // We also do not need to bother storing the last known user
+ // type because if we can get it for one particular clsid, we
+ // should always be able to get it. If we can't get the user type,
+ // then either we have never gotten a user type (and thus don't
+ // have a "last known") or we've changed clsid's (in which case,
+ // the last known user type would be wrong).
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetUserType "
+ "( %lx ) [ %p ]\n", this, hresult, *ppszUserType));
+
+ return hresult;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::Update
+//
+// Synopsis: Updates the link (by calling IOleLink->Update)
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 18-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::Update(void)
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Update ( )\n",
+ this ));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ hresult = Update(NULL);
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Update ( "
+ "%lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//fudge value
+#define TwoSeconds 0x01312D00
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::IsUpToDate
+//
+// Synopsis: Determines whether or not a link is up-to-date
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HRESULT -- NOERROR == IsUpToDate, S_FALSE == out of date
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: The current time is compared with the last time known
+// up-to-date on *both* machines (the process of the container
+// and the process of the link). These time differences are
+// compared to determine whether the link is out-of-date.
+// See the UpdateTimes method.
+//
+// History: dd-mmm-yy Author Comment
+// 09-Jan-95 alexgo correctly answer IsUpToDate now; also
+// fixup monikers if needed.
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes: The arithmetic calculations in this method assume
+// two's complement arithmetic and a high order sign bit
+// (true for most current machines)
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::IsUpToDate(void)
+{
+ FILETIME rtTimeOfLastChange;
+ LPMONIKER pmkAbs = NULL;
+ IMoniker * pmkContainer = NULL;
+ HRESULT hresult = NOERROR;
+ LPBINDCTX pbc = NULL;
+ FILETIME rtDiff;
+ FILETIME ltDiff;
+ FILETIME ftTemp;
+ FILETIME ftNow;
+ BOOL fHighBitSet;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::IsUpToDate "
+ "( )\n", this ));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if (m_dwUpdateOpt == OLEUPDATE_ALWAYS &&
+ IsRunning())
+ {
+ // hresult == NOERROR from default initializer
+ goto errRet;
+ }
+
+
+ // use the relative moniker if it exists and if the container
+ // has a moniker
+ if (NOERROR != GetAbsMkFromRel(&pmkAbs, &pmkContainer))
+ {
+ // otherwise use the absolute moniker
+ if (pmkAbs = m_pMonikerAbs)
+ {
+ pmkAbs->AddRef();
+ }
+ }
+
+ if (pmkAbs == NULL)
+ {
+ hresult = MK_E_UNAVAILABLE;
+ goto errRet;
+ }
+
+ hresult = CreateBindCtx( 0, &pbc );
+ if (hresult != NOERROR)
+ {
+ goto errRet;
+ }
+
+ //get the remote time of last change
+ hresult = pmkAbs->GetTimeOfLastChange(pbc, NULL, &rtTimeOfLastChange);
+ if (hresult != NOERROR)
+ {
+ // if GetTimeOfLastChange failed, it's possible that the moniker
+ // we constructed is bogus. Try again using the *real* absolute
+ // moniker. We do this to mimic bind behaviour. The moniker
+ // we use above is constructed from the relative moniker. In binding,
+ // if the relative moniker fails, then we fall back to the last
+ // known real absolute moniker.
+ BOOL fSuccess = FALSE;
+
+ if( m_pMonikerAbs )
+ {
+ if (pmkAbs != m_pMonikerAbs)
+ {
+ // do this if we did the bind on the relative one.above
+ hresult = m_pMonikerAbs->GetTimeOfLastChange(pbc, NULL,
+ &rtTimeOfLastChange);
+
+ if( hresult == NOERROR )
+ {
+ fSuccess = TRUE;
+ // hang onto the better absolute moniker
+ pmkAbs->Release(); // releases the one we contructed
+ // in GetAbsMkFromRel
+ pmkAbs = m_pMonikerAbs;
+ pmkAbs->AddRef(); // so the Release() down below
+ } // doesn't hose us.
+ }
+
+#ifdef _TRACKLINK_
+ if (!fSuccess)
+ {
+ // at this point we have tried either: relative then absolute OR
+ // just absolute. We now should try the reduced absolute one.
+
+ IMoniker *pmkReduced;
+ EnableTracking(m_pMonikerAbs, OT_ENABLEREDUCE);
+ hresult = m_pMonikerAbs->Reduce(pbc, MKRREDUCE_ALL, NULL, &pmkReduced);
+ EnableTracking(m_pMonikerAbs, OT_DISABLEREDUCE);
+ if (hresult == NOERROR)
+ {
+ hresult = pmkReduced->GetTimeOfLastChange(pbc, NULL,
+ &rtTimeOfLastChange);
+ if (hresult != NOERROR)
+ {
+ pmkReduced->Release();
+ }
+ else
+ {
+ fSuccess = TRUE;
+ pmkAbs->Release();
+ pmkAbs = pmkReduced;
+ }
+ }
+ }
+#endif
+ }
+
+ if (!fSuccess)
+ {
+ hresult = MK_E_UNAVAILABLE;
+ goto errRet;
+ }
+ }
+
+ // once we get this far, we know that either 1. the relative moniker
+ // is good, or 2. the absolute moniker is good. In any event, pmkAbs
+ // now points to a (semi)-reasonable spot. (I say 'semi', because
+ // even though GetTimeOfLastChange succeeded, we aren't guaranteed that
+ // a Bind would be successful.
+ //
+ // check to see if we need to update the relative moniker (if we don't
+ // already have one, don't bother.) It is also possible that the
+ // absolute moniker is now bad. Use the known 'good' one and update
+ // both monikers
+
+ // we ignore the return code here; if this call fails, it is not
+ // serious.
+
+ // pmkContainer may be NULL if our container doesn't offer us one.
+ if( pmkContainer )
+ {
+ UpdateMksFromAbs(pmkContainer, pmkAbs);
+
+ pmkContainer->Release();
+ }
+
+ // compute rtDiff = max(0, rtTimeOfLastChange - rtUpdate)
+ // possibly optimize with _fmemcopy
+
+ // debugging aid
+ DumpSzTime("IsUpToDate: rtTimeOfLastChange = ", rtTimeOfLastChange);
+
+ // start rtDiff calculation
+ rtDiff = rtTimeOfLastChange;
+
+ // debugging aid
+ DumpSzTime("IsUpToDate: rtUpdate = ", m_rtUpdate);
+
+ // the following subtractions rely on two's complement
+ if (m_rtUpdate.dwLowDateTime > rtDiff.dwLowDateTime)
+ {
+ //handle the carry
+ rtDiff.dwHighDateTime =
+ (DWORD)((LONG)rtDiff.dwHighDateTime - 1);
+ }
+
+ rtDiff.dwLowDateTime = (DWORD)((LONG)rtDiff.dwLowDateTime -
+ (LONG)m_rtUpdate.dwLowDateTime);
+ rtDiff.dwHighDateTime = (DWORD)((LONG)rtDiff.dwHighDateTime -
+ (LONG)m_rtUpdate.dwHighDateTime);
+
+
+ // if rtDiff < 0, say we are out of date.
+ if ((LONG)rtDiff.dwHighDateTime < 0)
+ {
+ hresult = S_FALSE;
+ goto errRet;
+ }
+
+ if (rtDiff.dwHighDateTime == 0 && rtDiff.dwLowDateTime == 0)
+ {
+ // no time difference. could be due to large clock ticks,
+ // so we say we are up to date only if several seconds have
+ // elapsed since last known update time.
+
+ CoFileTimeNow( &ftNow );
+ ftTemp = m_ltKnownUpToDate;
+
+ // This bit of logic may seem strange. All we want is
+ // is to test the high bit in a portable fashion
+ // between 32/64bit machines (so a constant isn't good)
+ // As long as the sign bit is the high order bit, then
+ // this trick will do
+
+ fHighBitSet = ((LONG)ftTemp.dwLowDateTime < 0);
+
+ ftTemp.dwLowDateTime += TwoSeconds;
+
+ // if the high bit was set, and now it's zero, then we
+ // had a carry
+
+ if (fHighBitSet && ((LONG)ftTemp.dwLowDateTime >= 0))
+ {
+ ftTemp.dwHighDateTime++; // handle the carry.
+ }
+
+ // compare times
+ if ((ftNow.dwHighDateTime > ftTemp.dwHighDateTime) ||
+ ((ftNow.dwHighDateTime == ftTemp.dwHighDateTime) &&
+ (ftNow.dwLowDateTime > ftTemp.dwLowDateTime)))
+ {
+ hresult = NOERROR;
+ }
+ else
+ {
+ hresult = S_FALSE;
+ }
+ }
+ else
+ {
+ // there was a time difference
+
+ // compute ltDiff = max(0, m_ltKnownUpToDate -
+ // m_ltChangeOfUpdate);
+ // Actually, by this time we know rtDiff >= 0, so we can
+ // simply compare ltDiff with rtDiff -- no need to compute
+ // the max.
+
+ ltDiff = m_ltKnownUpToDate;
+
+ // debugging aid
+ DumpSzTime("IsUpToDate: ltKnownUpToDate = ",ltDiff);
+ DumpSzTime("IsUpToDate: ltChangeOfUpdate = ",
+ m_ltChangeOfUpdate);
+
+ // these calc's rely on two's complement.
+
+ if (m_ltChangeOfUpdate.dwLowDateTime >
+ ltDiff.dwLowDateTime)
+ {
+ // handle carry
+ ltDiff.dwHighDateTime =
+ (DWORD)((LONG)ltDiff.dwHighDateTime - 1);
+ }
+
+ ltDiff.dwLowDateTime = (DWORD)((LONG)ltDiff.dwLowDateTime -
+ (LONG)m_ltChangeOfUpdate.dwLowDateTime);
+ ltDiff.dwHighDateTime = (DWORD)((LONG)ltDiff.dwHighDateTime -
+ (LONG)m_ltChangeOfUpdate.dwHighDateTime);
+
+ // Now determine if rtDiff < ltDiff
+ if (ltDiff.dwHighDateTime > rtDiff.dwHighDateTime)
+ {
+ hresult = NOERROR;
+ }
+ else if (ltDiff.dwHighDateTime == rtDiff.dwHighDateTime)
+ {
+ if (ltDiff.dwLowDateTime > rtDiff.dwLowDateTime)
+ {
+ hresult = NOERROR;
+ }
+ else
+ {
+ hresult = S_FALSE;
+ }
+ }
+ else
+ {
+ hresult = S_FALSE;
+ }
+ }
+
+ // all cases should have been handled by this point. Release
+ // any resources grabbed.
+
+errRet:
+ if (pmkAbs)
+ {
+ pmkAbs->Release();
+ }
+ if (pbc)
+ {
+ pbc->Release();
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::IsUpToDate "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::SetExtent
+//
+// Synopsis: Sets the drawing extents, not allowed for links
+//
+// Effects:
+//
+// Arguments: [dwDrawAspect] -- the drawing aspect
+// [lpsizel] -- the new extents
+//
+// Requires:
+//
+// Returns: E_UNSPEC (not allowed)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 19-Nov-93 alexgo 32 bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::SetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetExtent "
+ "( %lx , %p )\n", this, dwDrawAspect, lpsizel));
+
+ LEDebugOut((DEB_WARN, "Set Extent called for links, E_UNSPEC \n"));
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetExtent "
+ "( %lx )\n", this, E_UNSPEC));
+
+ return E_UNSPEC; // can't call this for a link
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetExtent
+//
+// Synopsis: Get's the size (extents) of the object
+//
+// Effects:
+//
+// Arguments: [dwDrawAspect] -- the drawing aspect
+// [lpsizel] -- where to put the extents
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Asks the server first, if not running or an error
+// then delegate to the cache
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetExtent( DWORD dwDrawAspect, LPSIZEL lpsizel)
+{
+ HRESULT error = E_FAIL;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetExtent "
+ "( %lx , %p )\n", this, dwDrawAspect, lpsizel));
+
+ VDATEPTROUT(lpsizel, SIZEL);
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ lpsizel->cx = 0;
+ lpsizel->cy = 0;
+
+ // if server is running try to get extents from the server
+ if( GetOleDelegate() )
+ {
+ error = m_pOleDelegate->GetExtent(dwDrawAspect, lpsizel);
+ }
+
+ // if there is error or object is not running get extents from Cache
+ if( error != NOERROR )
+ {
+ Assert(m_pCOleCache != NULL);
+ error = m_pCOleCache->GetExtent(dwDrawAspect,
+ lpsizel);
+ }
+
+ // WordArt2.0 is giving negative extents!!
+ if (SUCCEEDED(error))
+ {
+ lpsizel->cx = LONG_ABS(lpsizel->cx);
+ lpsizel->cy = LONG_ABS(lpsizel->cy);
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetExtent "
+ "( %lx )\n", this, error ));
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::Advise
+//
+// Synopsis: Sets up an advise connection to the object for things like
+// Close, Save, etc.
+//
+// Effects:
+//
+// Arguments: [pAdvSink] -- whom to notify
+// [pdwConnection] -- where to put the connection ID
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Creates an OleAdvise holder (if one not already present
+// and then delegates to it)
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized and handle zombie case
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::Advise(IAdviseSink *pAdvSink,
+ DWORD *pdwConnection)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Advise "
+ "( %p , %p )\n", this, pAdvSink, pdwConnection));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( IsZombie() )
+ {
+ hresult = CO_E_RELEASED;
+ goto errRtn;
+ }
+
+ // if we haven't got an advise holder yet, allocate one
+ if (m_pCOAHolder == NULL)
+ {
+ // allocate the advise holder
+ m_pCOAHolder = new FAR COAHolder;
+
+ // check to make sure we got one
+ if (m_pCOAHolder == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+ }
+
+ // delegate the call to the advise holder
+ hresult = m_pCOAHolder->Advise(pAdvSink, pdwConnection);
+
+errRtn:
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Advise "
+ "( %lx ) [ %lu ]\n", this, hresult,
+ (pdwConnection) ? *pdwConnection : 0 ));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::Unadvise
+//
+// Synopsis: Removes an advise connection to the object
+//
+// Effects:
+//
+// Arguments: [dwConnection] -- the connection ID to remove
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Delegates to the OleAdvise holder (which was created
+// during the Advise--if it wasn't, then we are in a strange
+// state).
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::Unadvise(DWORD dwConnection)
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Unadvise "
+ "( %lu )\n", this, dwConnection ));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if (m_pCOAHolder == NULL)
+ {
+ // no one registered
+ hresult = E_UNEXPECTED;
+ }
+ else
+ {
+ hresult = m_pCOAHolder->Unadvise(dwConnection);
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Unadvise "
+ "( %lx )\n", this, hresult ));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::EnumAdvise
+//
+// Synopsis: Enumerates the advise connections on the object
+//
+// Effects:
+//
+// Arguments: [ppenumAdvise] -- where to put the pointer to the advise
+// enumerator
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Delegates to the advise holder
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes: We do not need to stabilize this method as we only allocate
+// memory for hte advise enumerator
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::EnumAdvise( LPENUMSTATDATA *ppenumAdvise )
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::EnumAdvise "
+ "( %p )\n", this, ppenumAdvise ));
+
+ if (m_pCOAHolder == NULL)
+ {
+ // no one registered
+ hresult = E_UNSPEC;
+ }
+ else
+ {
+ hresult = m_pCOAHolder->EnumAdvise(ppenumAdvise);
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::EnumAdvise "
+ "( %lx ) [ %p ]\n", this, hresult, *ppenumAdvise ));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetMiscStatus
+//
+// Synopsis: Gets the miscellaneous status bits (such as
+// OLEMISC_ONLYICONIC)
+//
+// Effects:
+//
+// Arguments: [dwAspect] -- the drawing aspect
+// [pdwStatus] -- where to put the status bits
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm: Asks the server first, if not running or if it returns
+// OLE_E_USEREG, then get the info from the registration
+// database. We always add link-specific bits regardless
+// of error conditions or what the server or regdb says.
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 30-May-94 alexgo now handles crashed servers
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetMiscStatus( DWORD dwAspect, DWORD *pdwStatus)
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetMiscStatus"
+ " ( %lx , %p )\n", this, dwAspect, pdwStatus ));
+
+ VDATEPTROUT(pdwStatus, DWORD);
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( GetOleDelegate() )
+ {
+ hresult = m_pOleDelegate->GetMiscStatus (dwAspect, pdwStatus);
+
+ if( !GET_FROM_REGDB(hresult) )
+ {
+ if(SUCCEEDED(hresult) || IsReallyRunning() )
+ {
+ // if we failed, but the server is still
+ // running, then go ahead and propogate the
+ // error to the caller.
+ // Note that IsReallyRunning will clean up our
+ // state if the server had crashed.
+ goto errRtn;
+ }
+ // FALL-THROUGH!! This is deliberate. If
+ // the call failed and the server is no longer
+ // running, then we assume the server has crashed.
+ // We want to go ahead and fetch the information
+ // from the registry.
+ }
+ }
+
+ // Not running or object wants us to use reg db.
+ hresult = OleRegGetMiscStatus(m_clsid, dwAspect,
+ pdwStatus);
+
+errRtn:
+ // add link-specific bits (even if error) and return.
+ // we add them even if an error because in order to get here, we
+ // have to have instantiated this link object; thus, it is always
+ // valid to say OLEMISC_ISLINKOBJECT, etc.
+
+ (*pdwStatus) |= OLEMISC_CANTLINKINSIDE | OLEMISC_ISLINKOBJECT;
+
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetMiscStatus"
+ " ( %lx ) [ %lx ]\n", this, hresult, *pdwStatus ));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::SetColorScheme
+//
+// Synopsis: Sets the palette for the object; unused for links
+//
+// Effects:
+//
+// Arguments: [lpLogpal] -- the palette
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::SetColorScheme(LPLOGPALETTE lpLogpal)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+ // we ignore this always
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetColor"
+ "Scheme ( %p )\n", this, lpLogpal));
+
+ LEDebugOut((DEB_WARN, "Link IOO:SetColorScheme called on a link\n"));
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetColor"
+ "Scheme ( %lx )\n", this, NOERROR));
+
+ return NOERROR;
+}
+
+
+/*
+* IMPLEMENTATION of CLinkImpl methods
+*
+*/
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::BeginUpdates
+//
+// Synopsis: Private method to update the caches and then set the update
+// times
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CDefLink::BeginUpdates(void)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::BeginUpdates ( )\n", this));
+
+ IDataObject FAR* pDataDelegate;
+
+ if( pDataDelegate = GetDataDelegate() )
+ {
+ // inform cache that we are running
+ Assert(m_pCOleCache != NULL);
+ m_pCOleCache->OnRun(pDataDelegate);
+
+ // update only the automatic local caches from the newly
+ // running src
+ m_pCOleCache->UpdateCache(pDataDelegate, UPDFCACHE_NORMALCACHE,
+ NULL);
+
+ // we are an automatic link which is now up to date
+ SetUpdateTimes();
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::BeginUpdates ( )\n", this ));
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::EndUpdates
+//
+// Synopsis: Calls OnStop on the cache
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CDefLink::EndUpdates(void)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::EndUpdates ( )\n", this));
+
+ Assert(m_pCOleCache != NULL);
+ m_pCOleCache->OnStop();
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::EndUpdates ( )\n", this));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::UpdateAutoOnSave
+//
+// Synopsis: Updates caches that have been set with ADVFCACHE_ONSAVE
+// and sets the update times. Private method
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CDefLink::UpdateAutoOnSave(void)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::UpdateAutoOnSave ( )\n",
+ this));
+
+ // if m_pUnkDelegate is non-NULL, assume we are running
+ // (we only want to take the hit of the rpc-call IsRunning
+ // on external entry points.
+
+ if (m_pUnkDelegate && m_dwUpdateOpt == OLEUPDATE_ALWAYS)
+ {
+ // update any cache which has ADVFCACHE_ONSAVE
+ Assert(m_pCOleCache != NULL);
+
+ //REVIEW32: I think SetUpdateTimes ought to be called
+ //*after* the cache has been updated (that's what
+ //BeginUpdates does as well)
+ SetUpdateTimes();
+ m_pCOleCache->UpdateCache(GetDataDelegate(),
+ UPDFCACHE_IFBLANKORONSAVECACHE, NULL);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::UpdateAutoOnSaves ( )\n",
+ this));
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::UpdateRelMkFromAbsMk (private)
+//
+// Synopsis: Creates a new relative moniker from the absolute moniker
+//
+// Effects:
+//
+// Arguments: [pmkContainer] -- the moniker to the container (may be NULL)
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Feb-94 alexgo check for NULL before SendOnLinkSrcChange
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+// update relative moniker from abs; always release relative moniker;
+// may leave relative moniker NULL; doesn't return an error (because
+// no caller wanted it); dirties the link when we get rid of an
+// existing relative moniker or get a new one.
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CDefLink::UpdateRelMkFromAbsMk(IMoniker *pmkContainer)
+{
+ LPMONIKER pmkTemp = NULL;
+ BOOL fNeedToAdvise = FALSE;
+ HRESULT hresult;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::UpdateRelMkFromAbsMk ( %p )\n",
+ this, pmkContainer ));
+
+ if (m_pMonikerRel)
+ {
+ m_pMonikerRel->Release();
+ m_pMonikerRel = NULL;
+
+ m_flags |= DL_DIRTY_LINK; // got rid on an existing moniker, now dirty
+ fNeedToAdvise = TRUE;
+ }
+
+ // NOTE: m_pMonikerRel is now NULL and only set when if we get a
+ // new one
+
+ if (m_pMonikerAbs == NULL)
+ {
+ // no abs mk thus no relative one
+ goto errRtn;
+ }
+
+ if (pmkContainer)
+ {
+ pmkTemp = pmkContainer;
+ }
+ else
+ {
+ hresult = GetMoniker( OLEGETMONIKER_ONLYIFTHERE, // it will be
+ OLEWHICHMK_CONTAINER, &pmkTemp );
+
+ AssertOutPtrIface(hresult, pmkTemp);
+ if (hresult != NOERROR)
+ {
+ // no container moniker, thus no relative one to it
+ goto errRtn;
+ }
+
+ Assert(pmkTemp != NULL);
+ }
+
+ hresult = pmkTemp->RelativePathTo(m_pMonikerAbs, &m_pMonikerRel);
+ AssertOutPtrIface(hresult, m_pMonikerRel);
+
+ if (hresult != NOERROR)
+ {
+ // no relationship between container and absolute, thus no
+ // relative
+ if (m_pMonikerRel)
+ {
+ m_pMonikerRel->Release();
+ m_pMonikerRel = NULL;
+ }
+ }
+
+ if (pmkContainer == NULL)
+ {
+ // new moniker was allocated and needs to be released
+ pmkTemp->Release();
+ }
+
+ if (m_pMonikerRel != NULL)
+ {
+ m_flags |= DL_DIRTY_LINK; // have new relative moniker; dirty
+ fNeedToAdvise = TRUE;
+ }
+
+ // if there's an advise holder and we need to advise, send out
+ // the change notification.
+ if (fNeedToAdvise && m_pCOAHolder)
+ {
+ m_pCOAHolder->SendOnLinkSrcChange(m_pMonikerAbs);
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::UpdateRelMkFromAbsMk ( %p )\n",
+ this, pmkContainer ));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::UpdateMksFromAbs
+//
+// Synopsis: make a reasonable attempt to get valid rel && absolute
+// monikers
+//
+// Effects:
+//
+// Arguments: [pmkContainer] -- the moniker to the container
+// [pmkAbs] -- 'good' absolute moniker
+//
+// Requires:
+//
+// Returns: S_OK
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 09-Jan-95 alexgo author
+//
+// Notes: This function should only be used when we aren't 100% sure
+// of the validity of the moniker (i.e. after an IMoniker::
+// TimeOfLastChange call). We do not do any error
+// recovery. Basically, the idea is 'try' to put us in a
+// more consistent state, but it that fails, it's OK (because
+// we'd basically have OLE 16bit behaviour).
+//
+//--------------------------------------------------------------------------
+
+INTERNAL CDefLink::UpdateMksFromAbs( IMoniker *pmkContainer, IMoniker *pmkAbs )
+{
+ HRESULT hresult;
+ IMoniker *pmktempRel;
+ BOOL fNeedToUpdate = FALSE;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::UpdateMksFromAbs ( %p , %p )\n",
+ this, pmkContainer, pmkAbs));
+
+ // try updating the relative moniker (if one exists). Basically, we
+ // see if the relative moniker between pmkContainer and pmkAbs is
+ // any different than the moniker we currently have.
+
+ if( m_pMonikerRel )
+ {
+ hresult = pmkContainer->RelativePathTo(pmkAbs, &pmktempRel);
+
+ if( hresult == NOERROR )
+ {
+ if( pmktempRel->IsEqual(m_pMonikerRel) == S_FALSE )
+ {
+ // need to update the relative moniker.
+
+ m_pMonikerRel->Release();
+ m_pMonikerRel = pmktempRel;
+ m_pMonikerRel->AddRef();
+
+ // updated relative moniker, now dirty
+ m_flags |= DL_DIRTY_LINK;
+ fNeedToUpdate = TRUE;
+ }
+ }
+ }
+
+ // it is also possible that the absolute moniker is now bad. Use the
+ // known 'good' one.
+
+ if( m_pMonikerAbs && m_pMonikerAbs->IsEqual(pmkAbs) == S_FALSE )
+ {
+ m_pMonikerAbs->Release();
+ m_pMonikerAbs = pmkAbs;
+ m_pMonikerAbs->AddRef();
+
+#ifdef _TRACKLINK_
+ EnableTracking(m_pMonikerAbs, OT_READTRACKINGINFO);
+#endif
+
+ m_flags |= DL_DIRTY_LINK;
+
+ fNeedToUpdate = TRUE;
+ }
+
+ // send out an advise to any interested parties if we changed our
+ // monikers. Note that we do this even if just the relative moniker
+ // changed because the moniker we give apps via GetSourceMoniker is
+ // computed from the relative.
+
+ if( fNeedToUpdate && m_pCOAHolder )
+ {
+ m_pCOAHolder->SendOnLinkSrcChange(m_pMonikerAbs);
+ }
+
+ hresult = NOERROR;
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::UpdateMksFromAbs ( %lx )\n",
+ this, hresult));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetAbsMkFromRel (private)
+//
+// Synopsis: Gets the absolute moniker from the relative moniker
+// stored in the link
+//
+// Effects:
+//
+// Arguments: [ppmkAbs] -- where to put the pointer to the moniker
+// [ppmkCont] -- where to put the container moniker
+// (may be NULL)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: calls IMoniker->ComposeWith on the moniker to the container
+//
+// History: dd-mmm-yy Author Comment
+// 09-Jan-95 alexgo added ppmkCont parameter
+// 21-Nov-94 alexgo memory optimization
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL CDefLink::GetAbsMkFromRel(IMoniker **ppmkAbs, IMoniker **ppmkCont )
+{
+ LPMONIKER pmkContainer = NULL;
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::GetAbsMkFromRel ( %p , %p )\n",
+ this, ppmkAbs, ppmkCont));
+
+ *ppmkAbs = NULL;
+ if (m_pMonikerRel == NULL)
+ {
+ hresult = E_FAIL;
+ goto errRtn;
+ }
+
+ hresult = GetMoniker( OLEGETMONIKER_ONLYIFTHERE,
+ OLEWHICHMK_CONTAINER, &pmkContainer );
+ AssertOutPtrIface(hresult, pmkContainer);
+ if (hresult != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ Assert(pmkContainer != NULL);
+
+ hresult = pmkContainer->ComposeWith( m_pMonikerRel, FALSE, ppmkAbs );
+
+ if (pmkContainer)
+ {
+ if( ppmkCont )
+ {
+ *ppmkCont = pmkContainer; // no need to AddRef, just implicitly
+ // transfer ownership from pmkContainer
+ }
+ else
+ {
+ pmkContainer->Release();
+ }
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::GetAbsMkFromRel ( %lx ) "
+ "[ %p ]\n", this, hresult, *ppmkAbs));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::SetUpdateOptions
+//
+// Synopsis: Sets the update options for the link (such as always or
+// manual)
+//
+// Effects:
+//
+// Arguments: [dwUpdateOpt] -- update options
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleLink
+//
+// Algorithm: If UPDATE_ALWAYS, then update the caches, otherwise
+// call OnStop (via EndUpdates)
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized and handle zombie case
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::SetUpdateOptions(DWORD dwUpdateOpt)
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetUpdateOptions "
+ "( %lx )\n", this, dwUpdateOpt));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( IsZombie() )
+ {
+ hresult = CO_E_RELEASED;
+ goto errRtn;
+ }
+
+ switch (dwUpdateOpt)
+ {
+ case OLEUPDATE_ALWAYS:
+ // make sure we are connected if running
+ BindIfRunning();
+
+ // if we've already are in UPDATE_ALWAYS mode,
+ // we don't need to reenter
+ if (m_pUnkDelegate &&
+ m_dwUpdateOpt != OLEUPDATE_ALWAYS)
+ {
+ BeginUpdates();
+ }
+ break;
+
+ case OLEUPDATE_ONCALL:
+ // if we aren't already in UPDATE_ONCALL mode, then
+ // enter it.
+ if (m_dwUpdateOpt != OLEUPDATE_ONCALL)
+ {
+ // inform cache that we are not running
+ // (even if not running)
+ EndUpdates();
+ }
+ break;
+ default:
+ hresult = E_INVALIDARG;
+ goto errRtn;
+ }
+
+ m_dwUpdateOpt = dwUpdateOpt;
+
+ m_flags |= DL_DIRTY_LINK;
+
+ hresult = NOERROR;
+
+errRtn:
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetUpdateOptions "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetUpdateOptions
+//
+// Synopsis: Retrieves the current update mode for the link
+//
+// Effects:
+//
+// Arguments: [pdwUpdateOpt] -- wehre to put the update options
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleLink
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetUpdateOptions(LPDWORD pdwUpdateOpt)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetUpdateOptions "
+ "( %p )\n", this, pdwUpdateOpt));
+
+ *pdwUpdateOpt = m_dwUpdateOpt;
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetUpdateOptions "
+ "( %lx ) [ %lx ]\n", this, NOERROR, *pdwUpdateOpt));
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::SetSourceMoniker
+//
+// Synopsis: Sets the link source moniker
+//
+// Effects:
+//
+// Arguments: [pmk] -- moniker to the new source (NULL used
+// for CancelLink operations)
+// [rclsid] -- the clsid of the source
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleLink
+//
+// Algorithm: Stores the new absolute moniker and creates a new relative
+// moniker from the absolute moniker
+//
+// History: dd-mmm-yy Author Comment
+// 09-Jan-95 alexgo added call to SetUpdateTimes to keep
+// internal state consistent
+// 21-Nov-94 alexgo memory optimization
+/// 03-Aug-94 alexgo stabilized and handle zombie case
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::SetSourceMoniker( LPMONIKER pmk, REFCLSID clsid )
+{
+ HRESULT hresult = NOERROR;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetSourceMoniker "
+ "( %p , %p )\n", this, pmk, clsid));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( IsZombie() )
+ {
+ hresult = CO_E_RELEASED;
+ goto errRtn;
+ }
+
+ if (pmk)
+ {
+ VDATEIFACE(pmk);
+ }
+
+
+ UnbindSource();
+
+ // REVIEW: the following code appears in several places and should
+ // be put in a separate routine:
+ // SetBothMk(pmkSrcAbs, <calculated from abs>,
+ // TRUE/*fBind*/);
+
+ if (m_pMonikerAbs)
+ {
+ m_pMonikerAbs->Release();
+ }
+
+ if ((m_pMonikerAbs = pmk) != NULL)
+ {
+ pmk->AddRef();
+
+ //
+ // TRACKLINK
+ //
+ // -- use ITrackingMoniker to convert file moniker to
+ // be tracking.
+ //
+#ifdef _TRACKLINK_
+ EnableTracking(pmk, OT_READTRACKINGINFO);
+#endif
+ }
+
+ UpdateRelMkFromAbsMk(NULL);
+
+ // to prevent error in BindToSource when clsid is different; i.e., we
+ // shouldn't fail to connect (or require OLELINKBIND_EVENIFCLASSDIFF)
+ // when the moniker is changed; i.e., we expect the class to change
+ // so don't bother the programmer.
+ m_clsid = CLSID_NULL;
+
+ if (BindIfRunning() != NOERROR)
+ {
+ // server not running -> use clsid given (even if CLSID_NULL
+ // and even
+ // if no moniker)
+ m_clsid = clsid;
+ }
+
+errRtn:
+
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetSourceMoniker "
+ "( %lx )\n", this, hresult ));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetSourceMoniker
+//
+// Synopsis: Gets the moniker to the source
+//
+// Effects:
+//
+// Arguments: [ppmk] -- where to put the moniker
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleLink
+//
+// Algorithm: We first try to build a new absolute moniker from the
+// relative one, if that fails then we return the currently
+// stored absolute moniker.
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetSourceMoniker(LPMONIKER *ppmk)
+{
+ LPMONIKER pmkAbs = NULL;
+ // the absolute moniker constructed from the rel
+ HRESULT hresult = NOERROR;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetSourceMoniker "
+ "( %p )\n", this, ppmk));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ GetAbsMkFromRel(&pmkAbs, NULL);
+ if (pmkAbs)
+ {
+ *ppmk = pmkAbs; // no addref
+ }
+ else if (*ppmk = m_pMonikerAbs)
+ {
+ // we've been asked to give the pointer so we should AddRef()
+ m_pMonikerAbs->AddRef();
+ }
+ else
+ {
+ hresult = MK_E_UNAVAILABLE;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetSourceMoniker "
+ "( %lx ) [ %p ]\n", this, hresult, *ppmk));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::SetSourceDisplayName
+//
+// Synopsis: Creates a moniker from the display name and calls
+// SetSourceMoniker, thus setting the moniker to the source
+//
+// Effects:
+//
+// Arguments: [lpszStatusText] -- the display name
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleLink
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized and handle the zombie case
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::SetSourceDisplayName(
+ LPCOLESTR lpszStatusText)
+{
+ HRESULT error;
+ IBindCtx FAR* pbc;
+ ULONG cchEaten;
+ IMoniker FAR* pmk;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::SetSourceDisplay"
+ "Name ( %p )\n", this, lpszStatusText));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( IsZombie() )
+ {
+ error = CO_E_RELEASED;
+ goto errRtn;
+ }
+
+ if (error = CreateBindCtx(0,&pbc))
+ {
+ goto errRtn;
+ }
+
+ error = MkParseDisplayName(pbc, (LPOLESTR)lpszStatusText, &cchEaten,
+ &pmk);
+
+
+ // In Daytona, we release the hidden server
+ // must release this now so the (possibly) hidden server goes away.
+ Verify(pbc->Release() == 0);
+
+ if (error != NOERROR)
+ {
+ goto errRtn;
+ }
+
+
+ error = SetSourceMoniker(pmk, CLSID_NULL);
+
+ pmk->Release();
+
+ // NOTE: we don't bind to the link source now since that would leave
+ // the server running, but hidden. If the caller want to not start
+ // the server twice it should parse the moniker itself, call
+ // SetSourceMoniker and then BindToSource with the bind context of
+ // the parse.
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::SetSourceDisplay"
+ "Name ( %lx )\n", this, error ));
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetSourceDisplayName
+//
+// Synopsis: Retrieves the source display name (such as that set with
+// SetSourceDisplayName)
+//
+// Effects:
+//
+// Arguments: [lplpszDisplayName] -- where to put a pointer to the
+// display name
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleLink
+//
+// Algorithm: Gets the absolute moniker and asks it for the display name
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetSourceDisplayName( LPOLESTR *lplpszDisplayName )
+{
+ HRESULT hresult;
+ IBindCtx FAR* pbc;
+ LPMONIKER pmk = NULL;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetSourceDisplay"
+ "Name ( %p )\n", this, lplpszDisplayName));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ *lplpszDisplayName = NULL;
+
+ GetSourceMoniker(&pmk);
+
+ if (pmk == NULL)
+ {
+ hresult = E_FAIL;
+ goto errRtn;
+ }
+
+ if (hresult = CreateBindCtx(0,&pbc))
+ {
+ goto errRtn;
+ }
+
+ hresult = pmk->GetDisplayName(pbc, NULL,lplpszDisplayName);
+ AssertOutPtrParam(hresult, *lplpszDisplayName);
+
+ Verify(pbc->Release() == 0);
+errRtn:
+ if (pmk)
+ {
+ pmk->Release();
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetSourceDisplay"
+ "Name ( %lx ) [ %p ]\n", this, hresult,
+ *lplpszDisplayName));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::BindToSource
+//
+// Synopsis: Binds to the link source
+//
+// Effects:
+//
+// Arguments: [bindflags] -- controls the binding (such as binding
+// even if the class ID is different)
+// [pbc] -- the bind context
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleLink
+//
+// Algorithm: First try binding with the relative moniker, failing that
+// then try the absolute moniker. Once bound, we set up
+// the advises and cache.
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilize and check for zombie case
+// 03-Feb-94 alexgo check for NULL before SendOnLinkSrcChange
+// 11-Jan-94 alexgo cast -1's to DWORD to fix compile
+// warning
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::BindToSource(DWORD bindflags, LPBINDCTX pbc)
+{
+ HRESULT error;
+ IOleObject FAR* pOleDelegate;
+ IDataObject FAR* pDataDelegate;
+ IBindCtx FAR* pBcUse;
+ CLSID clsid;
+ LPMONIKER pmkAbs = NULL;
+ LPMONIKER pmkHold = NULL;
+ LPRUNNABLEOBJECT pRODelegate;
+ LPOLEITEMCONTAINER pOleCont;
+ BOOL fLockedContainer;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::BindToSource "
+ "( %lx , %p )\n", this, bindflags, pbc));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ // if we're zombied (e.g. in the middle of our destructor), we
+ // don't really want to bind the source again ;-)
+
+ if( IsZombie() )
+ {
+ error = CO_E_RELEASED;
+ goto logRtn;
+ }
+
+ // if we're running, then we're already bound
+ if (IsReallyRunning())
+ {
+ error = NOERROR;
+ goto logRtn;
+ }
+
+ // nobody to bind to
+ if (m_pMonikerAbs == NULL)
+ {
+ error = E_UNSPEC;
+ goto logRtn;
+ }
+
+ if ((pBcUse = pbc) == NULL && (error = CreateBindCtx(0,&pBcUse))
+ != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ {
+ //
+ // Rewritten BillMo 30 Jan 1995.
+ //
+ // Enumeration which is used to keep track of what stage of resolution
+ // we were successful in.
+ //
+ enum
+ {
+ None, Relative, Ids, Absolute
+ } ResolveSuccess = { None };
+
+ if (m_pMonikerRel != NULL)
+ {
+ error = GetAbsMkFromRel(&pmkAbs, NULL);
+ if (error == NOERROR)
+ {
+ error = pmkAbs->BindToObject(pBcUse,
+ NULL,
+ IID_IUnknown,
+ (LPVOID FAR *) &m_pUnkDelegate);
+ if (error == NOERROR)
+ {
+ ResolveSuccess = Relative;
+ }
+ else
+ {
+ pmkAbs->Release();
+ pmkAbs = NULL;
+ }
+ }
+ }
+
+ if (ResolveSuccess == None && error != RPC_E_CALL_REJECTED)
+ {
+ error = m_pMonikerAbs->BindToObject(pBcUse,
+ NULL,
+ IID_IUnknown,
+ (LPVOID FAR *)&m_pUnkDelegate);
+ if (error == NOERROR)
+ {
+ ResolveSuccess = Absolute;
+ (pmkAbs = m_pMonikerAbs)->AddRef();
+ }
+ }
+
+#ifdef _TRACKLINK_
+ if (ResolveSuccess == None && error != RPC_E_CALL_REJECTED)
+ {
+ HRESULT error2;
+ Assert(pmkAbs == NULL);
+ EnableTracking(m_pMonikerAbs, OT_ENABLEREDUCE);
+ error2 = m_pMonikerAbs->Reduce(pBcUse,
+ MKRREDUCE_ALL,
+ NULL,
+ &pmkAbs);
+ EnableTracking(m_pMonikerAbs, OT_DISABLEREDUCE);
+ if (error2 == NOERROR)
+ {
+ if (pmkAbs != NULL)
+ {
+ error2 = pmkAbs->BindToObject(pBcUse,
+ NULL,
+ IID_IUnknown,
+ (LPVOID FAR *)&m_pUnkDelegate);
+ if (error2 == NOERROR)
+ {
+ ResolveSuccess = Ids;
+ error = NOERROR;
+ }
+ else
+ {
+ pmkAbs->Release();
+ pmkAbs=NULL;
+ }
+ }
+ // else error contains error from m_pMonikerAbs->BindToObject
+ }
+ else
+ if (error2 == MK_S_REDUCED_TO_SELF)
+ {
+ if (pmkAbs != NULL)
+ {
+ pmkAbs->Release();
+ pmkAbs=NULL;
+ }
+ }
+ // else error contains error from m_pMonikerAbs->BindToObject
+ }
+#endif
+ //
+ // Update the link state
+ //
+
+ if (ResolveSuccess == None)
+ goto errRtn;
+
+ // Update the absolute moniker and send OnLinkSrcChange
+ // (may update relative if this was an Ids resolve)
+ if (ResolveSuccess == Relative || ResolveSuccess == Ids)
+ {
+ // binding succeeded with relative moniker or ids
+ // Update the absolute one.
+
+ // hold on to old absolute one
+ pmkHold = m_pMonikerAbs;
+ if (pmkHold)
+ {
+ pmkHold->AddRef();
+ }
+
+ if (m_pMonikerAbs)
+ {
+ m_pMonikerAbs->Release();
+ m_pMonikerAbs = NULL;
+ }
+
+ if (ResolveSuccess == Relative)
+ {
+ GetAbsMkFromRel(&m_pMonikerAbs, NULL);
+ }
+ else
+ {
+ // Ids
+ m_pMonikerAbs = pmkAbs;
+ pmkAbs = NULL;
+ UpdateRelMkFromAbsMk(NULL);
+ }
+
+ //
+ // test to see if we had no abs moniker before OR the
+ // one we had is different to the new one.
+ //
+
+ if (pmkHold == NULL ||
+ pmkHold->IsEqual(m_pMonikerAbs)
+ != NOERROR )
+ {
+ m_flags |= DL_DIRTY_LINK;
+
+ // send change notification if the advise
+ // holder present.
+ if( m_pCOAHolder)
+ {
+ m_pCOAHolder->SendOnLinkSrcChange(
+ m_pMonikerAbs);
+ }
+ }
+
+ // have new absolute moniker; dirty
+ if (pmkHold)
+ {
+ pmkHold->Release();
+ }
+ }
+
+ // Update the relative
+ if (ResolveSuccess == Absolute)
+ {
+ UpdateRelMkFromAbsMk(NULL);
+ }
+ }
+
+#ifdef _TRACKLINK_
+ EnableTracking(m_pMonikerAbs, OT_READTRACKINGINFO);
+
+ if (m_pMonikerAbs->IsDirty())
+ m_flags |= DL_DIRTY_LINK;
+#endif
+
+ // NOTE: don't need to update the relative moniker when there isn't
+ // one because we will do that at save time.
+
+ // Successfully bound, Lock the Object.
+ if ((pRODelegate = GetRODelegate()) != NULL)
+ {
+ // lock so invisible link source does not goes away.
+
+ Assert(0 == (m_flags & DL_LOCKED_RUNNABLEOBJECT));
+
+ if (NOERROR == pRODelegate->LockRunning(TRUE, FALSE))
+ {
+ m_flags |= DL_LOCKED_RUNNABLEOBJECT;
+ }
+ }
+ else if( (pOleCont = GetOleItemContainerDelegate()) != NULL)
+ {
+
+ // have container in same process or handler which doesn't
+ // support IRunnableObject.
+
+ Assert(0 == (m_flags & DL_LOCKED_OLEITEMCONTAINER));
+
+ if (NOERROR == pOleCont->LockContainer(TRUE))
+ {
+ m_flags |= DL_LOCKED_OLEITEMCONTAINER;
+ }
+
+ }
+
+
+ // Lock the container
+ fLockedContainer = m_flags & DL_LOCKED_CONTAINER;
+
+ DuLockContainer(m_pAppClientSite, TRUE, &fLockedContainer );
+
+ if(fLockedContainer)
+ {
+ m_flags |= DL_LOCKED_CONTAINER;
+ }
+ else
+ {
+ m_flags &= ~DL_LOCKED_CONTAINER;
+ }
+
+ // By this point, we have successfully bound to the server. Now
+ // we take care of misc administrative tasks.
+
+ Assert(m_pUnkDelegate != NULL &&
+ "CDefLink::BindToSource expected valid m_pUnkDelegate");
+
+ // get class of link source; use NULL if it doesn't support IOleObject
+ // or IOleObject::GetUserClassID returns an error.
+ if ((pOleDelegate = GetOleDelegate()) == NULL ||
+ pOleDelegate->GetUserClassID(&clsid) != NOERROR)
+ {
+ clsid = CLSID_NULL;
+ }
+
+ // if different and no flag, release and return error.
+ if ( IsEqualCLSID(m_clsid,CLSID_NULL))
+ {
+ // m_clsid now NULL; link becomes dirty
+ m_flags |= DL_DIRTY_LINK;
+ }
+ else if ( !IsEqualCLSID(clsid, m_clsid) )
+ {
+ if ((bindflags & OLELINKBIND_EVENIFCLASSDIFF) == 0)
+ {
+ error = OLE_E_CLASSDIFF;
+ goto errRtn;
+ }
+
+ // clsid's do no match; link becomes dirty
+ m_flags |= DL_DIRTY_LINK;
+ }
+
+ // use new class (even if null); dirty flag set above
+ m_clsid = clsid;
+
+ // it is possible that a re-entrant call unbound our source
+ // thus making pOleDelegate invalid (since it's a local on
+ // the stack
+
+ LEWARN(pOleDelegate != m_pOleDelegate,
+ "Unbind during IOL::BindToSource");
+
+ // we fetched m_pOleDelegate in the call to GetOleDelegate above.
+ if( m_pOleDelegate != NULL)
+ {
+ // set single ole advise (we multiplex)
+ if ((error = m_pOleDelegate->Advise(
+ &m_AdviseSink,
+ &m_dwConnOle)) != NOERROR)
+ {
+ goto errRtn;
+ }
+ }
+
+ // Set up advise connections for data changes
+ if( pDataDelegate = GetDataDelegate() )
+ {
+ // setup wild card advise to get time change
+ FORMATETC fetc;
+
+ fetc.cfFormat = NULL;
+ fetc.ptd = NULL;
+ fetc.dwAspect = (DWORD)-1L;
+ fetc.lindex = -1;
+ fetc.tymed = (DWORD)-1L;
+
+ if ((error = pDataDelegate->DAdvise(&fetc, ADVF_NODATA,
+ &m_AdviseSink,
+ &m_dwConnTime)) != NOERROR)
+ {
+ LEDebugOut((DEB_WARN, "WARNING: server does not "
+ "support wild card advises\n"));
+ goto errRtn;
+ }
+
+
+ // it is possible that a re-entrant call unbound our
+ // link server, so we need to fetch the data object
+ // pointer again
+
+ LEWARN(pDataDelegate != m_pDataDelegate,
+ "Unbind during IOL::BindToSource");
+
+ // this will set up data advise connections with
+ // everybody in our data advise holder
+ // (see dacache.cpp)
+
+ error = m_pDataAdvCache->EnumAndAdvise(
+ m_pDataDelegate, TRUE);
+
+ if( error != NOERROR )
+ {
+ goto errRtn;
+ }
+ }
+
+ if (m_dwUpdateOpt == OLEUPDATE_ALWAYS)
+ {
+ // we inform the cache that we are running only if auto
+ // update; otherwise, we are a manual link and will call
+ // Update directly (which doesn't require OnRun to be called).
+
+ BeginUpdates();
+ }
+
+ // Our m_pUnkDelegate may have been released by an
+ // OnClose advise that came in while we were setting up Advise
+ // sinks.
+
+ if (NULL == m_pUnkDelegate)
+ {
+ LEDebugOut((DEB_WARN,
+ "CDefLink::BindToSource - "
+ "m_pUnkDelegate was released "
+ "(probably due to OnClose)"));
+
+ error = MK_E_NOOBJECT;
+ }
+
+errRtn:
+ // free used resources
+ if (pmkAbs)
+ {
+ pmkAbs->Release();
+ }
+ if (error != NOERROR)
+ {
+ UnbindSource(); // ClientSite will be unlocked in UnBindSource
+ }
+
+ if (pbc == NULL && pBcUse != NULL)
+ {
+ // created bind ctx locally
+ Verify(pBcUse->Release() == 0);
+ }
+
+#if DBG == 1
+ if( m_pUnkDelegate )
+ {
+ Assert(error == NOERROR );
+ }
+ else
+ {
+ Assert(error != NOERROR );
+ }
+#endif
+ AssertOutPtrIface(error, m_pUnkDelegate);
+
+logRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::BindToSource "
+ "( %lx )\n", this, error ));
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::BindIfRunning
+//
+// Synopsis: Binds to the source server only if it is currently running
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HRESULT (NOERROR if connected)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleLink
+//
+// Algorithm: Gets a good moniker to the source (first tries relative,
+// then tries absolute), ask it if the server is running, if
+// yes, then bind to it.
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilize and handle the zombie case
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes: We may return NOERROR (connected) even if the server has
+// crashed unexpectedly
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::BindIfRunning(void)
+{
+ HRESULT error;
+ LPBC pbc;
+ LPMONIKER pmkAbs = NULL;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::BindIfRunning "
+ "( )\n", this ));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ // if we're zombied (e.g. in our destructor), then we don't want
+ // to bind to the server!
+
+
+ if( IsZombie() )
+ {
+ error = CO_E_RELEASED;
+ goto errRtn;
+ }
+
+ if (IsReallyRunning())
+ {
+ error = NOERROR;
+ goto errRtn;
+ }
+
+ // try getting an absolute moniker from the relative moniker first
+ if (GetAbsMkFromRel(&pmkAbs, NULL) != NOERROR)
+ {
+ // can't get relative moniker; use abs if available
+ if ((pmkAbs = m_pMonikerAbs) == NULL)
+ {
+ error = E_FAIL;
+ goto errRtn;
+ }
+
+ pmkAbs->AddRef();
+ }
+
+ // NOTE: we used to try both monikers, but this caused problems if
+ // both would bind and the absolute one was running: we would bind
+ // to the wrong one or force the relative one to be running. Now,
+ // if we have a relative moniker, we try that one only; if we only
+ // have an absolute moniker, we try that one; otherwise we fail.
+
+ error = CreateBindCtx( 0, &pbc );
+ if (error != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if ((error = pmkAbs->IsRunning(pbc, NULL, NULL)) == NOERROR)
+ {
+ // abs is running, but rel is not; force BindToSource to use
+ // the absolute moniker
+ error = BindToSource(0, pbc);
+ }
+
+ // else return last error (from pmkAbs->IsRunning)
+
+ pbc->Release();
+
+errRtn:
+ if (pmkAbs)
+ {
+ pmkAbs->Release();
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::BindIfRunning "
+ "( %lx )\n", this, error ));
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetBoundSource
+//
+// Synopsis: Returns a pointer to the server delegate
+//
+// Effects:
+//
+// Arguments: [ppUnk] -- where to put the pointer to the server
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleLink
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetBoundSource(LPUNKNOWN *ppUnk)
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetBoundSource "
+ "( %p )\n", this, ppUnk));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if (!IsReallyRunning())
+ {
+ *ppUnk = NULL;
+ hresult = E_FAIL;
+ }
+ else
+ {
+ (*ppUnk = m_pUnkDelegate)->AddRef();
+ hresult = NOERROR;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetBoundSource "
+ "( %lx ) [ %p ]\n", this, hresult, *ppUnk));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::UnbindSource
+//
+// Synopsis: Unbinds the connection to the link source server
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleLink
+//
+// Algorithm: First unadvise all advise connections and then tickle
+// the container by lock/unlocking (to handle the silent
+// update case). Finally, we release all pointers to the
+// server. If we were the only folks connected, the server
+// will go away
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::UnbindSource(void)
+{
+ LPDATAOBJECT pDataDelegate;
+ LPOLEOBJECT pOleDelegate;
+ LPRUNNABLEOBJECT pRODelegate;
+ LPOLEITEMCONTAINER pOleCont;
+ HRESULT hresult = NOERROR;
+ IUnknown * pUnkDelegate;
+ BOOL fLockedContainer;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::UnbindSource "
+ "( )\n", this ));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if (!m_pUnkDelegate)
+ {
+ // hresult == NOERROR
+ goto errRtn;
+ }
+
+ // unadvise so if delegate stays around, we get the correct results
+ if ((pOleDelegate = GetOleDelegate()) != NULL &&
+ m_dwConnOle != 0)
+ {
+ pOleDelegate->Unadvise(m_dwConnOle);
+ m_dwConnOle = 0;
+ }
+
+ if( pDataDelegate = GetDataDelegate() )
+ {
+ if (m_dwConnTime)
+ {
+ pDataDelegate->DUnadvise(m_dwConnTime);
+ m_dwConnTime = 0;
+ }
+
+ // we can actually be re-entered here, so refetch the
+ // IDO pointer from the server (if it's still around)
+
+ LEWARN(pDataDelegate != m_pDataDelegate,
+ "Unbind called within IOL::UnbindSource!");
+
+ // pDataDelegate should still be good, since we still have
+ // an AddRef on it. Go through and do the unadvises again
+ // anyway.
+
+ // this will unadvise everybody registered in the data
+ // advise holder
+ m_pDataAdvCache->EnumAndAdvise(
+ pDataDelegate, FALSE);
+ }
+
+ // inform cache that we are not running (even if OnRun was not called)
+ EndUpdates();
+
+
+ if ( (m_flags & DL_LOCKED_RUNNABLEOBJECT) &&
+ ((pRODelegate = GetRODelegate()) != NULL) )
+ {
+ // unlock so invisible link source goes away.
+ // do it just before release delegates so above unadvises go
+
+ m_flags &= ~DL_LOCKED_RUNNABLEOBJECT;
+ pRODelegate->LockRunning(FALSE, TRUE);
+ }
+
+
+ if( (m_flags & DL_LOCKED_OLEITEMCONTAINER) &&
+ ((pOleCont = GetOleItemContainerDelegate()) != NULL) )
+ {
+ // have container in same process or handler
+ // Unlock to shutdown.
+
+ m_flags &= ~DL_LOCKED_OLEITEMCONTAINER;
+ pOleCont->LockContainer(FALSE);
+ }
+
+ Assert(0 == (m_flags & (DL_LOCKED_OLEITEMCONTAINER | DL_LOCKED_RUNNABLEOBJECT)));
+
+ // release all of our pointers.
+
+ ReleaseOleDelegate();
+ ReleaseDataDelegate();
+ ReleaseRODelegate();
+ ReleaseOleItemContainerDelegate();
+
+ // if we are the only consumer of this data, the following will stop
+ // the server; set member to NULL first since release may cause this
+ // object to be accessed again.
+
+ pUnkDelegate = m_pUnkDelegate;
+
+ LEWARN(pUnkDelegate == NULL, "Unbind called within IOL::UnbindSource");
+
+ m_pUnkDelegate = NULL;
+
+ if( pUnkDelegate )
+ {
+ pUnkDelegate->Release();
+ }
+
+ // make sure unlocked if we locked it
+ // guard against disappearance
+ m_pUnkOuter->AddRef();
+
+ fLockedContainer = m_flags & DL_LOCKED_CONTAINER;
+ m_flags &= ~DL_LOCKED_CONTAINER;
+
+ DuLockContainer(m_pAppClientSite, FALSE, &fLockedContainer);
+
+ m_pUnkOuter->Release();
+
+
+ AssertSz( hresult == NOERROR, "Bogus code modification, check error "
+ "paths");
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::UnbindSource "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::Update
+//
+// Synopsis: Updates the link (fills cache, etc).
+//
+// Effects:
+//
+// Arguments: [pbc] -- the bind context
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOleLink
+//
+// Algorithm: Bind to the server, then update the caches
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+// As in IOO::DoVerb, we try to "fix" crashed servers by
+// staying bound to them if we rebind due to a crash. See
+// the Notes in IOO::DoVerb for more info.
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::Update(LPBINDCTX pbc)
+{
+ HRESULT error = NOERROR;
+ BOOL bStartedNow = !m_pUnkDelegate;
+ LPBINDCTX pBcUse;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Update ( %p )\n",
+ this, pbc));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if (pbc)
+ {
+ pBcUse = pbc;
+ }
+ else
+ {
+ if (FAILED(error = CreateBindCtx( 0, &pBcUse )))
+ goto errBndCtx;
+ }
+
+
+ if (FAILED(error = BindToSource(0,pBcUse)))
+ {
+ goto errRtn;
+ }
+
+ // store the pUnk there to allow for
+ // better optimization (if we didn't, file based link sources would
+ // be launched multiple times since the moniker code does not put
+ // them in the bind ctx (and probably shouldn't)).
+ pBcUse->RegisterObjectBound(m_pUnkDelegate);
+
+ SetUpdateTimes(); // ignore error.
+
+ if (bStartedNow && (m_dwUpdateOpt == OLEUPDATE_ALWAYS))
+ {
+ // if this is an auto-link and we ran it now, then all the
+ // automatic caches would have been updated during the
+ // running process. So, here we have to update only the
+ // ADVFCACHE_ONSAVE caches.
+ error= m_pCOleCache->UpdateCache(
+ GetDataDelegate(),
+ UPDFCACHE_IFBLANKORONSAVECACHE, NULL);
+ }
+ else
+ {
+ // This is a manual-link or it is an auto-link then it is
+ // already running. In all these cases, all the caches need
+ // to be updated.
+ // (See bug 1616, to find out why we also have to update
+ // the autmatic caches of auto-links).
+
+ error= m_pCOleCache->UpdateCache(
+ GetDataDelegate(),
+ UPDFCACHE_ALLBUTNODATACACHE, NULL);
+ }
+
+ if (bStartedNow)
+ {
+ UnbindSource();
+ }
+
+
+
+errRtn:
+
+ // if we created a bind context release it.
+ if ( (NULL == pbc) && pBcUse)
+ {
+ pBcUse->Release();
+ }
+
+errBndCtx:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Update ( %lx )\n",
+ this, error ));
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::EnableTracking
+//
+// Synopsis: Calls ITrackingMoniker::EnableTracking on the passed moniker.
+//
+// Arguments: [pmk] -- moniker
+//
+// [ulFlags]
+// OT_READTRACKINGINFO -- read tracking info from source
+// OT_ENABLESAVE -- enable save of tracking info
+// OT_DISABLESAVE -- disable save of tracking info
+//
+// Algorithm: QI to ITrackingMoniker and call EnableTracking
+//
+//
+//--------------------------------------------------------------------------
+#ifdef _TRACKLINK_
+INTERNAL CDefLink::EnableTracking(IMoniker *pmk, ULONG ulFlags)
+{
+ ITrackingMoniker *ptm = NULL;
+ HRESULT hr = E_FAIL;
+
+ if (pmk != NULL)
+ {
+ hr = pmk->QueryInterface(IID_ITrackingMoniker, (void**)&ptm);
+ if (hr == S_OK)
+ {
+ hr = ptm->EnableTracking(NULL, ulFlags);
+ LEDebugOut((DEB_TRACK,
+ "CDefLink(%08X)::EnableTracking -- ptm->EnableTracking() = %08X\n",
+ this, hr));
+ ptm->Release();
+ }
+ else
+ {
+ LEDebugOut((DEB_TRACK,
+ "CDefLink(%08X)::EnableTracking -- pmk->QI failed (%08X)\n",
+ this, hr));
+ }
+ }
+ else
+ {
+ LEDebugOut((DEB_TRACK,
+ "CDefLink(%08X)::EnableTracking -- pmk is NULL\n",
+ this));
+ }
+ return(hr);
+}
+#endif
+
+
+/*
+ * IMPLEMENTATION of CROImpl methods
+ */
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetRODelegate (private)
+//
+// Synopsis: gets the IRunnableObject from the interface
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: IRunnableObject *
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized and handle the zombie case
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+// This function may return misleading information if the
+// server has died (i.e., you'll return a pointer to a cached
+// interface proxy). It is the responsibility of the caller
+// to handler server crashes.
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(IRunnableObject *) CDefLink::GetRODelegate(void)
+{
+ IRunnableObject *pRODelegate;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::GetRODelegate "
+ "( )\n", this ));
+
+ // if we're zombied, then we don't want to QI for a new interface!!
+
+ if( !IsZombie() )
+ {
+ DuCacheDelegate(&(m_pUnkDelegate),
+ IID_IRunnableObject, (LPLPVOID)&m_pRODelegate, NULL);
+
+ pRODelegate = m_pRODelegate;
+
+#if DBG == 1
+ if( m_pRODelegate )
+ {
+ Assert(m_pUnkDelegate);
+ }
+#endif // DBG == 1
+ }
+ else
+ {
+ pRODelegate = NULL;
+ }
+
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::GetRODelegate "
+ "( %p )\n", this, pRODelegate));
+
+ return pRODelegate;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::ReleaseRODelegate (private)
+//
+// Synopsis: Releases the IRO pointer to the server
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CDefLink::ReleaseRODelegate(void)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::ReleaseRODelegate "
+ "( )\n", this ));
+
+ if (m_pRODelegate)
+ {
+ SafeReleaseAndNULL((IUnknown **)&m_pRODelegate);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::ReleaseRODelegate "
+ "( )\n", this ));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetRunningClass
+//
+// Synopsis: retrieves the class of the the default link
+//
+// Effects:
+//
+// Arguments: [lpClsid] -- where to put the class id
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IRunnableObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetRunningClass(LPCLSID lpClsid)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::GetRunningClass "
+ "( %p )\n", this, lpClsid));
+
+ VDATEPTROUT(lpClsid, CLSID);
+
+ *lpClsid = CLSID_StdOleLink;
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::GetRunningClass "
+ "( %lx )\n", this, NOERROR));
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::Run
+//
+// Synopsis: Runs the object (binds to the server)
+//
+// Effects:
+//
+// Arguments: [pbc] -- the bind context
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IRunnableObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::Run (LPBINDCTX pbc)
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Run ( %p )\n",
+ this, pbc ));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ hresult = BindToSource(0, pbc);
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Run ( %lx )\n",
+ this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::IsRunning
+//
+// Synopsis: returns whether or not we've bound to the link server
+//
+// Effects:
+//
+// Arguments: none
+//
+// Requires:
+//
+// Returns: TRUE/FALSE
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IRunnableObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 27-Aug-94 alexgo author
+//
+// Notes: 16bit OLE only ever implemented this function. We
+// implement IsReallyRunning to allow links to recover
+// from a crashed server.
+// Unfortunately, we can't just move the IsReallyRunning
+// implementation into IsRunning. Many apps (like Project)
+// sit and spin calling OleIsRunning. IsReallyRunning also
+// will sometimes make outgoing RPC calls; with Project,
+// this causes a really cool infinite feedback loop. (the
+// outgoing call resets some state in Project and they decide
+// to call OleIsRunning again ;-)
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(BOOL) CDefLink::IsRunning (void)
+{
+ BOOL fRet;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::IsRunning ( )\n",
+ this ));
+
+ if( m_pUnkDelegate )
+ {
+ fRet = TRUE;
+ }
+ else
+ {
+ fRet = FALSE;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::IsRunning ( %d )\n",
+ this, fRet));
+
+ return fRet;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::IsReallyRunning
+//
+// Synopsis: Returns whether or not the link server is running
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: BOOL -- TRUE == is running
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: If we have not yet bound to the link server, then we
+// are not running. If we have, we would like to verify
+// that the server is still running (i.e. it hasn't crashed).
+// Thus, we ask the absolute moniker if we are still running.
+// (it will ping the rot, which will ping the server).
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 06-May-94 alexgo now calls IMoniker::IsRunning
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(BOOL) CDefLink::IsReallyRunning (void)
+{
+ BOOL fRet = FALSE;
+ LPBC pbc;
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::IsReallyRunning "
+ "( )\n", this));
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( m_pUnkDelegate != NULL )
+ {
+ if( CreateBindCtx( 0, &pbc ) != NOERROR )
+ {
+ // this is a bit counter-intuitive. Basically,
+ // the only error we'll get is OutOfMemory, but
+ // we have no way of returning that error.
+
+ // In order to mimimize the amount of work we need
+ // to do (since we are in a low-mem state), just
+ // return the current Running state (in this,
+ // TRUE, since m_pUnkDelegate is not NULL
+
+ fRet = TRUE;
+ goto errRtn;
+ }
+
+ if( m_pMonikerAbs )
+ {
+ hresult = m_pMonikerAbs->IsRunning(pbc,
+ NULL, NULL);
+
+ if( hresult != NOERROR )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: link server "
+ "crashed or exited inappropriately "
+ "( %lx ). Recovering...\n", hresult));
+
+ // wowsers, the server has crashed or gone
+ // away even though we were bound to it.
+ // let's go ahead and unbind.
+
+ // don't worry about errors here; we're
+ // just trying to cleanup as best we can
+
+ UnbindSource();
+ }
+ if( hresult == NOERROR )
+ {
+ fRet = TRUE;
+ }
+#if DBG == 1
+ else
+ {
+ Assert(fRet == FALSE);
+ }
+#endif // DBG == 1
+
+ }
+
+#if DBG == 1
+ else
+ {
+ // we cannot have a pointer to the link server
+ // if we don't have a moniker to it. If we get
+ // to this state, something is hosed.
+
+ AssertSz(0,
+ "Pointer to link server without a moniker");
+ }
+#endif // DBG == 1
+
+ pbc->Release();
+ }
+
+errRtn:
+
+ // do some checking here. If we say we're running, then
+ // we should have a valid pUnkDelegate. Otherwise, it should
+ // be NULL. Note, however, that is *is* possible for us
+ // to unbind during this call even if we think we're running
+ //
+ // This occurs if during the call to IMoniker::IsRunning, we
+ // get another call in which does an UnbindSource; thus
+ // we'll think we're really running (from IMoniker::IsRunning),
+ // but we've really unbound.
+ //
+ // We'll check for that condition here
+
+
+ if( fRet == TRUE )
+ {
+ if( m_pUnkDelegate == NULL )
+ {
+ fRet = FALSE;
+ LEDebugOut((DEB_WARN, "WARNING: Re-entrant Unbind"
+ " during IsReallyRunning, should be OK\n"));
+ }
+ }
+#if DBG == 1
+ if( fRet == TRUE )
+ {
+ Assert(m_pUnkDelegate != NULL);
+ }
+ else
+ {
+ Assert(m_pUnkDelegate == NULL);
+ }
+#endif // DBG == 1
+
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::IsReallyRunning"
+ "( %lu )\n", this, fRet));
+
+ return fRet;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::SetContainedObject
+//
+// Synopsis: Sets the object as an embedding, not relevant for links
+//
+// Effects:
+//
+// Arguments: [fContained] -- flag to toggle embedding status
+//
+// Requires:
+//
+// Returns: HRESULT (NOERROR)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IRunnableObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+// note contained object; links don't care at present
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::SetContainedObject(BOOL fContained)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::LockRunning
+//
+// Synopsis: Lock/Unlock the connection to the server. Does nothing
+// for links.
+//
+// Effects:
+//
+// Arguments: [fLock] -- flag to lock/unlock
+// [fLastUnlockCloses] -- close if its the last unlock
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IRunnableObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+// Links have different liveness characteristics than embeddings.
+// We do not need to do anything for LockRunning for links.
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::LockRunning(BOOL fLock, BOOL fLastUnlockCloses)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ return NOERROR;
+}
+
+/*
+ * IMPLEMENTATION of CPersistStgImpl methods
+ */
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetClassID
+//
+// Synopsis: Retrieves the class id of the default link
+//
+// Effects:
+//
+// Arguments: [pClassID] -- where to put the class ID
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IPersistStorage
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::GetClassID (CLSID *pClassID)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ *pClassID = CLSID_StdOleLink;
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::IsDirty
+//
+// Synopsis: Returns TRUE if the linked object has changed
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: NOERROR if dirty
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IPersistStorage
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::IsDirty(void)
+{
+ HRESULT hresult;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::IsDirty"
+ " ( )\n", this));
+
+ if( (m_flags & DL_DIRTY_LINK) )
+ {
+ hresult = NOERROR;
+ }
+ else
+ {
+ Assert(m_pCOleCache != NULL);
+ hresult = m_pCOleCache->IsDirty();
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::IsDirty "
+ "( %lx )\n", this, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::InitNew
+//
+// Synopsis: Initialize a new link object from the given storage
+//
+// Effects:
+//
+// Arguments: [pstg] -- the new storage for the link
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IPersistStorage
+//
+// Algorithm: Delegates to the cache
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized and handle the zombie case
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::InitNew( IStorage *pstg)
+{
+ HRESULT error;
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::InitNew "
+ "( %p )\n", this, pstg));
+
+ VDATEIFACE(pstg);
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ if( IsZombie() )
+ {
+ error = CO_E_RELEASED;
+ }
+ else if (m_pStg == NULL)
+ {
+ Assert(m_pCOleCache != NULL);
+ if ((error = m_pCOleCache->InitNew(pstg)) == NOERROR)
+ {
+ m_flags |= DL_DIRTY_LINK;
+ (m_pStg = pstg)->AddRef();
+ }
+ }
+ else
+ {
+ error = CO_E_ALREADYINITIALIZED;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::InitNew "
+ "( %lx )\n", this, error ));
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::Load
+//
+// Synopsis: Initializes a link from data stored in the storage
+//
+// Effects:
+//
+// Arguments: [pstg] -- the storage with link data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IPersistStorage
+//
+// Algorithm: Read ole private data and set internal link information.
+// Then delegate to the cache to load presentation data, etc.
+//
+// History: dd-mmm-yy Author Comment
+// 20-Feb-94 KentCe Buffer internal stream i/o.
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized and handle zombie case
+// 19-Nov-93 alexgo 32bit port
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::Load(IStorage *pstg)
+{
+ HRESULT error;
+ LPMONIKER pmk = NULL;
+ LPMONIKER pmkSrcAbs = NULL;
+ LPMONIKER pmkSrcRel = NULL;
+ CLSID clsid;
+ DWORD dwFlags;
+ DWORD dwOptUpdate;
+ LPSTREAM pstm = NULL;
+ DWORD dummy;
+ ULONG cbRead;
+ CStmBufRead StmRead;
+
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CPeristStgImpl::Load "
+ "( %p )\n", this, pstg ));
+
+ VDATEIFACE(pstg);
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ // if we're in a zombie state, we don't want to be reloading
+ // our object!!
+
+ if( IsZombie() )
+ {
+ error = CO_E_RELEASED;
+ goto logRtn;
+ }
+
+ if (m_pStg)
+ {
+ error = CO_E_ALREADYINITIALIZED;
+ goto logRtn;
+ }
+
+ //read link data from the storage
+ error = ReadOleStg (pstg, &dwFlags, &dwOptUpdate, NULL, &pmk, &pstm);
+
+ if (error == NOERROR)
+ {
+ // set the update options.
+ SetUpdateOptions (dwOptUpdate);
+
+ // we can get the moniker from container, so no need to
+ // remeber this
+ if (pmk)
+ {
+ pmk->Release();
+ }
+
+ Assert (pstm != NULL);
+
+ // Read relative source moniker. Write NULL for the time being
+ if ((error = ReadMonikerStm (pstm, &pmkSrcRel)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ // Read absolute source moniker; stored in link below
+ if ((error = ReadMonikerStm (pstm, &pmkSrcAbs)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ //
+ // Buffer the read i/o from the stream.
+ //
+ StmRead.Init(pstm);
+
+
+ // Read -1 followed by the last class name
+ if ((error = ReadM1ClassStmBuf(StmRead, &clsid)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ // Read the last display name
+
+ // Right now, this is always an empty string
+ LPOLESTR pstr = NULL;
+ if ((error = ReadStringStream (StmRead, &pstr)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if (pstr)
+ {
+ LEDebugOut((DEB_ERROR, "ERROR!: Link user type "
+ "string found, unexpected\n"));
+ PubMemFree(pstr);
+ }
+
+ if ((error = StmRead.Read(&dummy, sizeof(DWORD)))
+ != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if ((error = StmRead.Read(&(m_ltChangeOfUpdate),
+ sizeof(FILETIME))) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if ((error = StmRead.Read(&(m_ltKnownUpToDate),
+ sizeof(FILETIME))) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if ((error = StmRead.Read(&(m_rtUpdate),
+ sizeof(FILETIME))) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ //
+ // TRACKLINK
+ //
+ // - tell the absolute moniker to convert itself
+ // into a tracking moniker using ITrackingMoniker::
+ // EnableTracking. (The composite
+ // moniker should pass this on to each of
+ // its contained monikers.)
+ // - if the moniker is already a tracking file moniker
+ // ignore the request.
+ //
+#ifdef _TRACKLINK_
+ EnableTracking(pmkSrcAbs, OT_READTRACKINGINFO);
+#endif
+
+ m_pMonikerRel = pmkSrcRel;
+ if (pmkSrcRel)
+ {
+ pmkSrcRel->AddRef();
+ }
+
+ m_pMonikerAbs = pmkSrcAbs;
+ if (pmkSrcAbs)
+ {
+ pmkSrcAbs->AddRef();
+ }
+
+ m_clsid = clsid;
+ // just loaded; thus not dirty
+
+ m_flags &= ~(DL_DIRTY_LINK);
+
+ }
+ else if( error == STG_E_FILENOTFOUND)
+ {
+ // It's OK if the Ole stream doesn't exist.
+ error = NOERROR;
+
+ }
+ else
+ {
+ return error;
+ }
+
+ // now load cache from pstg
+ Assert(m_pCOleCache != NULL);
+
+ if (error = m_pCOleCache->Load(pstg))
+ {
+ goto errRtn;
+ }
+
+ (m_pStg = pstg)->AddRef();
+
+errRtn:
+ StmRead.Release();
+
+ if (pmkSrcAbs)
+ {
+ pmkSrcAbs->Release();
+ }
+
+ if (pmkSrcRel)
+ {
+ pmkSrcRel->Release();
+ }
+
+ if (pstm)
+ {
+ pstm->Release();
+ }
+
+#ifdef REVIEW
+ if (error == NOERROR && m_pAppClientSite)
+ {
+ BindIfRunning();
+ }
+#endif
+
+logRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Load "
+ "( %lx )\n", this, error ));
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::Save
+//
+// Synopsis: Saves the link the given storage
+//
+// Effects:
+//
+// Arguments: [pstgSave] -- the storage to save into
+// [fSameAsLoad] -- FALSE indicates SaveAs operation
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IPersistStorage
+//
+// Algorithm: Writes private ole data (such as the clsid, monikers,
+// and update times) and the presentations stored in the
+// cache to the given storage
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 19-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::Save( IStorage *pstgSave, BOOL fSameAsLoad)
+{
+ HRESULT error = NOERROR;
+ LPSTREAM pstm = NULL;
+ DWORD cbWritten;
+ CStmBufWrite StmWrite;
+
+
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CPeristStgImpl::Save "
+ "( %p , %lu )\n", this, pstgSave, fSameAsLoad ));
+
+ VDATEIFACE(pstgSave);
+
+ CStabilize stabilize((CSafeRefCount *)this);
+
+ // update any cache which has ADVFCACHE_ONSAVE
+ UpdateAutoOnSave();
+
+ if( fSameAsLoad && !(m_flags & DL_DIRTY_LINK))
+ {
+ // The storage is not a new one (so we don't need to
+ // initialize our private data) and the link is not
+ // dirty, so we just need to delegate to the cache
+ goto LSaveCache;
+ }
+
+ // assign object moniker (used by WriteOleStg); we don't save this
+ // moniker since WriteOleStg gets it again; we also don't care if
+ // this failes as we don't want a failure here to prevent the link
+ // from being saved; the assignment might fail if some container has
+ // yet to be saved to a file. REIVEW PERF: we could pass this mk to
+ // WriteOleStg. We don't get the moniker for !fSameAsLoad since the
+ // relative moniker is not correct for the new stg and it causes the
+ // container to do work in a case for which it might not be prepared.
+
+ IMoniker * pMkObjRel;
+
+ if (fSameAsLoad && GetMoniker(
+ OLEGETMONIKER_FORCEASSIGN,
+ OLEWHICHMK_OBJREL, &pMkObjRel) == NOERROR)
+ {
+ pMkObjRel->Release();
+ }
+
+ if ((error = WriteOleStg(pstgSave,(IOleObject *)this, NULL,
+ &pstm)) != NOERROR)
+ {
+ goto logRtn;
+ }
+
+ Assert(pstm != NULL);
+
+ // Write relative source moniker.
+ // if it is NULL, try to compute it now. We may be saving a file for
+ // the first time, so the container now has a moniker for the first
+ // time.
+
+ if (m_pMonikerRel == NULL || m_pUnkDelegate)
+ {
+ // if the link is connected, we know that the absolute
+ // moniker is correct -- it was updated at bind time if
+ // necessary. If the link container moniker has changed
+ // (file/saveas) then we can exploit this opportunity to
+ // straighten things out and improve our link tracking
+ // since we know which of the two monikers is correct.
+ UpdateRelMkFromAbsMk(NULL);
+ }
+
+ if ((error = WriteMonikerStm (pstm, m_pMonikerRel))
+ != NOERROR)
+ {
+ goto errRtn;
+ }
+
+#ifdef _TRACKLINK_
+ EnableTracking(m_pMonikerAbs, OT_ENABLESAVE);
+#endif
+
+ // Write absolute source moniker.
+ error = WriteMonikerStm (pstm, m_pMonikerAbs);
+
+#ifdef _TRACKLINK_
+ EnableTracking(m_pMonikerAbs, OT_DISABLESAVE);
+#endif
+
+ if (error != NOERROR)
+ goto errRtn;
+ //
+ //
+ //
+ StmWrite.Init(pstm);
+
+
+ // write last class name
+ UpdateUserClassID();
+ if ((error = WriteM1ClassStmBuf(StmWrite, m_clsid)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+
+ // write last display name, should be NULL if the moniker's are
+ // non-NULL. For the time being this is always NULL.
+ if ((error = StmWrite.WriteLong(0))
+ != NOERROR)
+ {
+ goto errRtn;
+ }
+
+
+ // write -1 as the end marker, so that if we want to extend
+ // the file formats (ex: adding network name) it will be easier.
+ if ((error = StmWrite.WriteLong(-1))
+ != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if ((error = StmWrite.Write(&(m_ltChangeOfUpdate),
+ sizeof(FILETIME))) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if ((error = StmWrite.Write(&(m_ltKnownUpToDate),
+ sizeof(FILETIME))) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if ((error = StmWrite.Write(&(m_rtUpdate),
+ sizeof(FILETIME))) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if ((error = StmWrite.Flush()) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if (!fSameAsLoad)
+ {
+ // Copy link tracking info
+ static const LPOLESTR lpszLinkTracker = OLESTR("\1OleLink");
+
+ pstgSave->DestroyElement(lpszLinkTracker);
+
+ if (m_pStg)
+ {
+ // copy link tracking info, if one existed,
+ // ignore error
+ m_pStg->MoveElementTo(lpszLinkTracker,
+ pstgSave, lpszLinkTracker,
+ STGMOVE_COPY);
+ }
+ }
+
+LSaveCache:
+ // last, save cache
+ Assert(m_pCOleCache != NULL);
+ error = m_pCOleCache->Save(pstgSave, fSameAsLoad);
+
+errRtn:
+ StmWrite.Release();
+
+ if (pstm)
+ {
+ pstm->Release();
+ }
+
+ if (error == NOERROR)
+ {
+ m_flags |= DL_NO_SCRIBBLE_MODE;
+ if( fSameAsLoad )
+ {
+ m_flags |= DL_SAME_AS_LOAD;
+ }
+ else
+ {
+ m_flags &= ~(DL_SAME_AS_LOAD);
+ }
+ }
+
+logRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Save "
+ "( %lx )\n", this, error ));
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::SaveCompleted
+//
+// Synopsis: Called once the save is completed (for all objects in the
+// container). Clear the dirty flag and update the storage
+// that we hand onto.
+//
+// Effects:
+//
+// Arguments: [pstgNew] -- the new default storage for the object
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IPersistStorage
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized and handle zombie case
+// 20-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::SaveCompleted( IStorage *pstgNew)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::Save"
+ "Completed ( %p )\n", this, pstgNew ));
+
+ if (pstgNew)
+ {
+ VDATEIFACE(pstgNew);
+ }
+
+ // don't hang on to the new storage if we're in a zombie state!
+
+ if (pstgNew && !IsZombie() )
+ {
+ if (m_pStg)
+ {
+ m_pStg->Release();
+ }
+
+ m_pStg = pstgNew;
+ pstgNew->AddRef();
+ }
+
+ // REVIEW: do we send on save???
+
+ if( (m_flags & DL_SAME_AS_LOAD) || pstgNew)
+ {
+ if( (m_flags & DL_NO_SCRIBBLE_MODE) )
+ {
+ m_flags &= ~(DL_DIRTY_LINK);
+ }
+
+ m_flags &= ~(DL_SAME_AS_LOAD);
+ }
+
+ // let the cache know that the save is completed, so that it can clear
+ // its dirty flag in Save or SaveAs situation, as well as remember the
+ // new storage pointer if a new one is given
+
+ Assert(m_pCOleCache != NULL);
+ m_pCOleCache->SaveCompleted(pstgNew);
+
+ m_flags &= ~(DL_NO_SCRIBBLE_MODE);
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::Save"
+ "Completed ( %lx )\n", this, NOERROR ));
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::HandsOffStorage
+//
+// Synopsis: Releases all pointers to the storage (useful for low-mem
+// situations)
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HRESULT (NOERROR)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IPersistStorage
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 20-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::HandsOffStorage(void)
+{
+ VDATEHEAP();
+ VDATETHREAD(this);
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::HandsOff"
+ "Storage ( )\n", this ));
+
+ if (m_pStg)
+ {
+ m_pStg->Release();
+ m_pStg = NULL;
+ }
+
+ Assert(m_pCOleCache != NULL);
+ m_pCOleCache->HandsOffStorage();
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::HandsOff"
+ "Storage ( %lx )\n", this, NOERROR));
+
+ return NOERROR;
+}
+
+
+/*
+* IMPLEMENTATION of CAdvSinkImpl methods
+*
+*/
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::CAdvSinkImpl::QueryInterface
+//
+// Synopsis: Returns an interface pointer
+//
+// Effects:
+//
+// Arguments: [iid] -- the requested interface ID
+// [ppvObj] -- where to put a pointer to the interface
+//
+// Requires:
+//
+// Returns: HRESULT (NOERROR or E_NOINTERFACE)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 20-Nov-93 alexgo 32bit port
+// 22-Nov-93 alexgo removed overloaded GUID ==
+//
+// Notes: The advise sink has a different memory lifetime than
+// the default link object as a whole; thus we cannot give
+// out pointers to it (they may be invalid)
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CDefLink::CAdvSinkImpl::QueryInterface( REFIID iid,
+ LPVOID *ppvObj)
+{
+ HRESULT hresult;
+ CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_AdviseSink);
+
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CAdvSinkImpl::QueryInterface"
+ " ( %p , %p )\n", pDefLink, ppvObj));
+
+ if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IAdviseSink))
+ {
+ *ppvObj = this;
+ AddRef();
+ hresult = NOERROR;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ hresult = E_NOINTERFACE;
+ }
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CAdvSinkImpl::QueryInterface"
+ " ( %lx ) [ %p ]\n", pDefLink, hresult, ppvObj));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink:CAdvSinkImpl::AddRef
+//
+// Synopsis: Increments the reference count
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 13-Mar-94 alexgo moved from header file to provide for
+// better tracking of reference counts
+// (via call-tracing)
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDefLink::CAdvSinkImpl::AddRef ()
+{
+ CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_AdviseSink);
+
+ VDATEHEAP();
+ ULONG cRefs;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CAdvSinkImpl::AddRef ( )\n",
+ pDefLink ));
+
+ cRefs = pDefLink->SafeAddRef();
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CAdvSinkImpl::AddRef ( %lu "
+ ")\n", pDefLink, cRefs ));
+
+ return cRefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink:CAdvSinkImpl::Release
+//
+// Synopsis: Release a reference count
+//
+// Effects: Will delete the object once # of refs == 0
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 20-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDefLink::CAdvSinkImpl::Release ()
+{
+ CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_AdviseSink);
+
+ VDATEHEAP();
+ ULONG cRefs;
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CAdvSinkImpl::Release ( )\n",
+ pDefLink ));
+
+ cRefs = pDefLink->SafeRelease();
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CAdvSinkImpl::Release "
+ "( %lu )\n", pDefLink, cRefs));
+
+ return cRefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::CAdvSinkImpl::OnDataChange
+//
+// Synopsis: Called when the advise source modifies its data
+//
+// Effects:
+//
+// Arguments: [pFormatetc] -- format of the data
+// [pStgmed] -- the new data
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink
+//
+// Algorithm: If we automatically update, then set our update times.
+// (if the cache needs to get new data, it will set up its
+// own advise)
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 20-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CDefLink::CAdvSinkImpl::OnDataChange(
+ FORMATETC *pFormatetc, STGMEDIUM *pStgmed)
+{
+ CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_AdviseSink);
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CAdvSinkImpl::OnDataChange "
+ "( %p , %p )\n", pDefLink, pFormatetc, pStgmed));
+
+ CStabilize stabilize((CSafeRefCount *)pDefLink);
+
+ // must be wild card advise that prompted this
+ Assert(pFormatetc->cfFormat == NULL && pFormatetc->ptd == NULL &&
+ pFormatetc->dwAspect == -1 && pFormatetc->tymed == -1);
+
+ Assert(pStgmed->tymed == TYMED_NULL);
+
+ // only received to get time change for automatic links
+ if( pDefLink->m_dwUpdateOpt == OLEUPDATE_ALWAYS)
+ {
+ pDefLink->SetUpdateTimes();
+ }
+ // else ignore
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CAdvSinkImpl::OnDataChange "
+ "( )\n", pDefLink));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::CAdvSinkImpl::OnViewChange
+//
+// Synopsis: Called when the view changes; should never be called for
+// links
+//
+// Effects:
+//
+// Arguments: [aspects] -- drawing aspect
+// [lindex] -- unused
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 20-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CDefLink::CAdvSinkImpl::OnViewChange
+ (DWORD aspects, LONG lindex)
+{
+ VDATEHEAP();
+
+ Assert(FALSE); // never received
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::CAdvSinkImpl::OnRename
+//
+// Synopsis: Called when the soure object gets renamed
+//
+// Effects:
+//
+// Arguments: [pmk] -- the new name
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink
+//
+// Algorithm: resets the internal monikers to the source object
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized and handle zombie case
+// 03-Feb-94 alexgo SendOnLInkSrcChange now checks for NULL
+// first.
+// 20-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CDefLink::CAdvSinkImpl::OnRename(IMoniker *pmk)
+{
+ CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_AdviseSink);
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CAdvSinkImpl::OnRename "
+ "( %p )\n", pDefLink, pmk));
+
+ CStabilize stabilize((CSafeRefCount *)pDefLink);
+
+ // if we're in a zombie state, don't change our monikers.
+
+ if( pDefLink->IsZombie() )
+ {
+ goto errRtn;
+ }
+ // note new moniker; propogate to IAdviseSink2::OnLinkSrcChange
+
+ // REVIEW: the following code appears in several places and should
+ // be put in a separate routine:
+ // SetBothMk(pmkSrcAbs, <calc from abs>, FALSE/*fBind*/);
+
+ if( pDefLink->m_pMonikerAbs )
+ {
+ pDefLink->m_pMonikerAbs->Release();
+ }
+
+ if( (pDefLink->m_pMonikerAbs = pmk) != NULL)
+ {
+ pmk->AddRef();
+
+ //
+ // TRACKLINK --
+ // - enable tracking on the moniker passed in.
+ // (this will get a new shellink if neccessary.)
+ //
+#ifdef _TRACKLINK_
+ pDefLink->EnableTracking(pmk, OT_READTRACKINGINFO);
+#endif
+ }
+
+ pDefLink->UpdateRelMkFromAbsMk(NULL);
+
+ // the name of the link source changed; this has no bearing on the
+ // name of the link object itself.
+
+ if( pDefLink->m_pCOAHolder )
+ {
+ pDefLink->m_pCOAHolder->SendOnLinkSrcChange(pmk);
+ }
+
+errRtn:
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CAdvSinkImpl::OnRename "
+ "( )\n", pDefLink ));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::CAdvSinkImpl::OnSave
+//
+// Synopsis: Called when the source object gets saved
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink
+//
+// Algorithm: updates caches with ADVFCACHE_ONSAVE
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 20-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CDefLink::CAdvSinkImpl::OnSave()
+{
+ CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_AdviseSink);
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CAdvSinkImpl::OnSave "
+ "( )\n", pDefLink ));
+
+ CStabilize stabilize((CSafeRefCount *)pDefLink);
+
+ if( pDefLink->m_pCOAHolder != NULL)
+ {
+ pDefLink->m_pCOAHolder->SendOnSave();
+ }
+
+ // update any cache which has ADVFCACHE_ONSAVE
+ pDefLink->UpdateAutoOnSave();
+
+ // update notion of clsid
+ pDefLink->UpdateUserClassID();
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CAdvSinkImpl::OnSave "
+ "( )\n", pDefLink ));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::CAdvSinkImpl::OnClose
+//
+// Synopsis: Notification that the server is closing
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IAdviseSink
+//
+// Algorithm: Sends OnClose to all interested parties (in the advise
+// holder) and the unbinds the source
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo memory optimization
+// 03-Aug-94 alexgo stabilized
+// 30-Jun-94 alexgo unbind the source before doing the
+// send on close
+// 20-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CDefLink::CAdvSinkImpl::OnClose(void)
+{
+ CDefLink *pDefLink = GETPPARENT(this, CDefLink, m_AdviseSink);
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN CDefLink::CAdvSinkImpl::OnClose ( )\n",
+ pDefLink ));
+
+ CStabilize stabilize((CSafeRefCount *)pDefLink);
+
+ if( pDefLink->m_dwUpdateOpt == OLEUPDATE_ALWAYS )
+ {
+ // IGNORE return value! (we need to do as much of the close
+ // process as we can
+ pDefLink->SetUpdateTimes();
+ }
+
+ if( pDefLink->m_pCOAHolder != NULL )
+ {
+ // In general, OnClose can delete this defhndlr; thus we
+ // addref the aggregate so that we can tell if we should
+ // go away
+ pDefLink->m_pUnkOuter->AddRef();
+ pDefLink->m_pCOAHolder->SendOnClose();
+
+ // unbind our source, in case we didnt' already
+
+ pDefLink->UnbindSource();
+ // since we may get deleted by the release, don't use
+ // any member variables afterward
+ pDefLink->m_pUnkOuter->Release();
+ }
+ else
+ {
+ pDefLink->UnbindSource();
+ }
+
+
+ LEDebugOut((DEB_TRACE, "%p OUT CDefLink::CAdvSinkImpl ( )\n",
+ pDefLink ));
+}
+
+
+/*
+ * IMPLEMENTATION of OleItemContainer methods
+ */
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::GetOleItemContainerDelegate (private)
+//
+// Synopsis: gets the IOleItemContainer from the interface
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: IOleItemContainer *
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+// This function may return misleading information if the
+// server has died (i.e., you'll return a pointer to a cached
+// interface proxy). It is the responsibility of the caller
+// to handler server crashes.
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(IOleItemContainer *) CDefLink::GetOleItemContainerDelegate(void)
+{
+ IOleItemContainer *pOleItemContainerDelegate;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::GetOleItemContainerDelegate "
+ "( )\n", this ));
+
+ // if we're zombied, then we don't want to QI for a new interface!!
+
+ if( !IsZombie() )
+ {
+ DuCacheDelegate(&(m_pUnkDelegate),
+ IID_IOleItemContainer, (LPLPVOID)&m_pOleItemContainerDelegate, NULL);
+
+ pOleItemContainerDelegate = m_pOleItemContainerDelegate;
+
+#if DBG == 1
+ if( m_pOleItemContainerDelegate )
+ {
+ Assert(m_pUnkDelegate);
+ }
+#endif // DBG == 1
+ }
+ else
+ {
+ m_pOleItemContainerDelegate = NULL;
+ }
+
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::GetOleItemContainerDelegate "
+ "( %p )\n", this, pOleItemContainerDelegate));
+
+ return m_pOleItemContainerDelegate;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::ReleaseOleItemContainerDelegate (private)
+//
+// Synopsis: Releases the OleItemContainer pointer to the server
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CDefLink::ReleaseOleItemContainerDelegate(void)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN CDefLink::ReleaseOleItemContainerDelegate "
+ "( )\n", this ));
+
+ if (m_pOleItemContainerDelegate)
+ {
+ SafeReleaseAndNULL((IUnknown **)&m_pOleItemContainerDelegate);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT CDefLink::ReleaseOleItemContainerDelegate "
+ "( )\n", this ));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDefLink::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppszDump] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CDefLink::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszCSafeRefCount;
+ char *pszCThreadCheck;
+ char *pszCLSID;
+ char *pszCOleCache;
+ char *pszCOAHolder;
+ char *pszDAC;
+ char *pszFILETIME;
+ char *pszMonikerDisplayName;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(5000);
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ pszCSafeRefCount = DumpCSafeRefCount((CSafeRefCount *)this, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CSafeRefCount:" << endl;
+ dstrDump << pszCSafeRefCount;
+ CoTaskMemFree(pszCSafeRefCount);
+
+ pszCThreadCheck = DumpCThreadCheck((CThreadCheck *)this, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CThreadCheck:" << endl;
+ dstrDump << pszCThreadCheck;
+ CoTaskMemFree(pszCThreadCheck);
+
+ // only vtable pointers (plus we don't get the right address in debugger extensions)
+ // dstrDump << pszPrefix << "&IUnknown = " << &m_Unknown << endl;
+ // dstrDump << pszPrefix << "&IAdviseSink = " << &m_AdviseSink << endl;
+
+ dstrDump << pszPrefix << "Link flags = ";
+ if (m_flags & DL_SAME_AS_LOAD)
+ {
+ dstrDump << "DL_SAME_AS_LOAD ";
+ }
+ if (m_flags & DL_NO_SCRIBBLE_MODE)
+ {
+ dstrDump << "DL_NO_SCRIBBLE_MODE ";
+ }
+ if (m_flags & DL_DIRTY_LINK)
+ {
+ dstrDump << "DL_DIRTY_LINK ";
+ }
+ if (m_flags & DL_LOCKED_CONTAINER)
+ {
+ dstrDump << "DL_LOCKED_CONTAINER ";
+ }
+ // if none of the flags are set...
+ if ( !( (m_flags & DL_SAME_AS_LOAD) |
+ (m_flags & DL_LOCKED_CONTAINER) |
+ (m_flags & DL_NO_SCRIBBLE_MODE) |
+ (m_flags & DL_DIRTY_LINK)))
+ {
+ dstrDump << "No FLAGS SET!";
+ }
+ dstrDump << "(" << (void *)m_flags << ")" << endl;
+
+ dstrDump << pszPrefix << "pIOleObject Delegate = " << m_pOleDelegate << endl;
+
+ dstrDump << pszPrefix << "pIDataObject Delegate = " << m_pDataDelegate << endl;
+
+ dstrDump << pszPrefix << "pIRunnableObject Delegate = " << m_pRODelegate << endl;
+
+ dstrDump << pszPrefix << "No. of Refs. on Link = " << m_cRefsOnLink << endl;
+
+ dstrDump << pszPrefix << "pIUnknown pUnkOuter = ";
+ if (m_flags & DL_AGGREGATED)
+ {
+ dstrDump << "AGGREGATED (" << m_pUnkOuter << ")" << endl;
+ }
+ else
+ {
+ dstrDump << "NO AGGREGATION (" << m_pUnkOuter << ")" << endl;
+ }
+
+ dstrDump << pszPrefix << "pIMoniker Absolute = " << m_pMonikerAbs << endl;
+
+ if (m_pMonikerAbs != NULL)
+ {
+ pszMonikerDisplayName = DumpMonikerDisplayName(m_pMonikerAbs);
+ dstrDump << pszPrefix << "pIMoniker Absolute = ";
+ dstrDump << pszMonikerDisplayName;
+ dstrDump << "( " << m_pMonikerAbs << " )" << endl;
+ CoTaskMemFree(pszMonikerDisplayName);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "pIMoniker Absolute = NULL or unable to resolve" << endl;
+ }
+
+ if (m_pMonikerRel != NULL)
+ {
+ pszMonikerDisplayName = DumpMonikerDisplayName(m_pMonikerRel);
+ dstrDump << pszPrefix << "pIMoniker Relative = ";
+ dstrDump << pszMonikerDisplayName;
+ dstrDump << "( " << m_pMonikerRel << " )" << endl;
+ CoTaskMemFree(pszMonikerDisplayName);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "pIMoniker Absolute = NULL or unable to resolve" << endl;
+ }
+
+ dstrDump << pszPrefix << "pIUnknown Delegate = " << m_pUnkDelegate << endl;
+
+ dstrDump << pszPrefix << "OLEUPDATE flags = ";
+ if (m_dwUpdateOpt & OLEUPDATE_ALWAYS)
+ {
+ dstrDump << "OLEUPDATE_ALWAYS ";
+ }
+ else if (m_dwUpdateOpt & OLEUPDATE_ONCALL)
+ {
+ dstrDump << "OLEUPDATE_ONCALL ";
+ }
+ else
+ {
+ dstrDump << "No FLAGS SET!";
+ }
+ dstrDump << "(" << (void *)m_flags << ")" << endl;
+
+ pszCLSID = DumpCLSID(m_clsid);
+ dstrDump << pszPrefix << "Last known CLSID of link = " << pszCLSID << endl;
+ CoTaskMemFree(pszCLSID);
+
+ dstrDump << pszPrefix << "pIStorage = " << m_pStg << endl;
+
+ if (m_pCOleCache != NULL)
+ {
+ pszCOleCache = DumpCOleCache(m_pCOleCache, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "COleCache: " << endl;
+ dstrDump << pszCOleCache;
+ CoTaskMemFree(pszCOleCache);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "pCOleCache = " << m_pCOleCache << endl;
+ }
+
+ if (m_pCOAHolder != NULL)
+ {
+ pszCOAHolder = DumpCOAHolder(m_pCOAHolder, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "COAHolder: " << endl;
+ dstrDump << pszCOAHolder;
+ CoTaskMemFree(pszCOAHolder);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "pCOAHolder = " << m_pCOAHolder << endl;
+ }
+
+ dstrDump << pszPrefix << "OLE Connection Advise ID = " << m_dwConnOle << endl;
+
+ if (m_pDataAdvCache != NULL)
+ {
+ pszDAC = DumpCDataAdviseCache(m_pDataAdvCache, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CDataAdviseCache: " << endl;
+ dstrDump << pszDAC;
+ CoTaskMemFree(pszDAC);
+ }
+ else
+ {
+ dstrDump << pszPrefix << "pCDataAdviseCache = " << m_pDataAdvCache << endl;
+ }
+
+ dstrDump << pszPrefix << "pIOleClientSite = " << m_pAppClientSite << endl;
+
+ dstrDump << pszPrefix << "Connection for time = " << m_dwConnTime << endl;
+
+ pszFILETIME = DumpFILETIME(&m_ltChangeOfUpdate);
+ dstrDump << pszPrefix << "Change of update filetime = " << pszFILETIME << endl;
+ CoTaskMemFree(pszFILETIME);
+
+ pszFILETIME = DumpFILETIME(&m_ltKnownUpToDate);
+ dstrDump << pszPrefix << "Known up to date filetime = " << pszFILETIME << endl;
+ CoTaskMemFree(pszFILETIME);
+
+ pszFILETIME = DumpFILETIME(&m_rtUpdate);
+ dstrDump << pszPrefix << "Update filetime = " << pszFILETIME << endl;
+ CoTaskMemFree(pszFILETIME);
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCDefLink, public (_DEBUG only)
+//
+// Synopsis: calls the CDefLink::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pDL] - pointer to CDefLink
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCDefLink(CDefLink *pDL, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pDL == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pDL->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+
diff --git a/private/ole32/ole232/stdimpl/deflink.h b/private/ole32/ole232/stdimpl/deflink.h
new file mode 100644
index 000000000..ab0b14595
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/deflink.h
@@ -0,0 +1,302 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: deflink.h
+//
+// Contents: Declares the default link object
+//
+// Classes: CDefLink
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH added Dump method to CDefLink
+// added DLFlag to indicate if aggregated
+// (in _DEBUG only)
+// 21-Nov-94 alexgo memory optimization
+// 25-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocations.
+// 13-Nov-93 alexgo 32bit port
+//
+//--------------------------------------------------------------------------
+
+#include "olepres.h"
+#include "olecache.h"
+#include "dacache.h"
+#include <oaholder.h>
+
+typedef enum tagDLFlags
+{
+#ifdef _DEBUG
+ // keep track of if aggregated or not in debug build
+ DL_AGGREGATED = 256,
+#endif // _DEBUG
+ DL_SAME_AS_LOAD = 1,
+ DL_NO_SCRIBBLE_MODE = 2,
+ DL_DIRTY_LINK = 4,
+ DL_LOCKED_CONTAINER = 8,
+ DL_LOCKED_RUNNABLEOBJECT = 16,
+ DL_LOCKED_OLEITEMCONTAINER = 32
+} DLFlags;
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDefLink
+//
+// Purpose: The "embedding" for a link; the default object that implements
+// a link connection
+//
+// Interface: IUnknown
+// IDataObject
+// IOleObject
+// IOleLink
+// IRunnableObject
+// IAdviseSink
+// IPersistStorage
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH add Dump method (_DEBUG only)
+// 21-Nov-94 alexgo memory optimization
+// 13-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class FAR CDefLink : public CSafeRefCount, public IDataObject,
+ public IOleObject, public IOleLink, public IRunnableObject,
+ public IPersistStorage, public CThreadCheck
+{
+public:
+
+ static IUnknown FAR* Create(IUnknown FAR* pUnkOuter);
+
+ class CPrivUnknown : public IUnknown
+ {
+ STDMETHOD(QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+ };
+
+ friend class CPrivUnknown;
+ CPrivUnknown m_Unknown;
+
+ // IUnknown methods
+
+ STDMETHOD(QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ // IDataObject methods
+
+ INTERNAL_(IDataObject *) GetDataDelegate(void);
+ INTERNAL_(void) ReleaseDataDelegate(void);
+
+ STDMETHOD(GetData) ( LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium );
+ STDMETHOD(GetDataHere) ( LPFORMATETC pformatetc,
+ LPSTGMEDIUM pmedium );
+ STDMETHOD(QueryGetData) ( LPFORMATETC pformatetc );
+ STDMETHOD(GetCanonicalFormatEtc) ( LPFORMATETC pformatetc,
+ LPFORMATETC pformatetcOut);
+ STDMETHOD(SetData) ( LPFORMATETC pformatetc,
+ LPSTGMEDIUM pmedium,
+ BOOL fRelease);
+ STDMETHOD(EnumFormatEtc) ( DWORD dwDirection,
+ LPENUMFORMATETC *ppenumFormatEtc);
+ STDMETHOD(DAdvise) ( FORMATETC *pFormatetc, DWORD advf,
+ IAdviseSink *pAdvSink,
+ DWORD *pdwConnection);
+ STDMETHOD(DUnadvise) ( DWORD dwConnection);
+ STDMETHOD(EnumDAdvise) ( LPENUMSTATDATA *ppenumAdvise);
+
+ // IOleObject methods
+
+ INTERNAL_(IOleObject FAR*) GetOleDelegate(void);
+ INTERNAL_(void) ReleaseOleDelegate(void);
+
+ // *** IOleObject methods ***
+ STDMETHOD(SetClientSite)(LPOLECLIENTSITE pClientSite);
+ STDMETHOD(GetClientSite)(LPOLECLIENTSITE *ppClientSite);
+ STDMETHOD(SetHostNames)(LPCOLESTR szContainerApp,
+ LPCOLESTR szContainerObj);
+ STDMETHOD(Close) ( DWORD reserved);
+ STDMETHOD(SetMoniker) ( DWORD dwWhichMoniker, LPMONIKER pmk);
+ STDMETHOD(GetMoniker) ( DWORD dwAssign, DWORD dwWhichMoniker,
+ LPMONIKER *ppmk);
+ STDMETHOD(InitFromData) ( LPDATAOBJECT pDataObject,
+ BOOL fCreation,
+ DWORD dwReserved);
+ STDMETHOD(GetClipboardData) ( DWORD dwReserved,
+ LPDATAOBJECT *ppDataObject);
+ STDMETHOD(DoVerb) ( LONG iVerb,
+ LPMSG lpmsg,
+ LPOLECLIENTSITE pActiveSite,
+ LONG lindex,
+ HWND hwndParent,
+ const RECT *lprcPosRect);
+ STDMETHOD(EnumVerbs) ( IEnumOLEVERB **ppenumOleVerb);
+ STDMETHOD(Update) (void);
+ STDMETHOD(IsUpToDate) (void);
+ STDMETHOD(GetUserClassID) ( CLSID *pClsid);
+ STDMETHOD(GetUserType) ( DWORD dwFormOfType,
+ LPOLESTR *pszUserType);
+ STDMETHOD(SetExtent) ( DWORD dwDrawAspect, LPSIZEL lpsizel);
+ STDMETHOD(GetExtent) ( DWORD dwDrawAspect, LPSIZEL lpsizel);
+ STDMETHOD(Advise)(IAdviseSink FAR* pAdvSink,
+ DWORD *pdwConnection);
+ STDMETHOD(Unadvise)( DWORD dwConnection);
+ STDMETHOD(EnumAdvise) ( LPENUMSTATDATA *ppenumAdvise);
+ STDMETHOD(GetMiscStatus) ( DWORD dwAspect,
+ DWORD *pdwStatus);
+ STDMETHOD(SetColorScheme) ( LPLOGPALETTE lpLogpal);
+
+ // IOleLink methods
+
+ STDMETHOD(SetUpdateOptions) ( DWORD dwUpdateOpt);
+ STDMETHOD(GetUpdateOptions) ( LPDWORD pdwUpdateOpt);
+ STDMETHOD(SetSourceMoniker) ( LPMONIKER pmk, REFCLSID rclsid);
+ STDMETHOD(GetSourceMoniker) ( LPMONIKER *ppmk);
+ STDMETHOD(SetSourceDisplayName) ( LPCOLESTR lpszStatusText);
+ STDMETHOD(GetSourceDisplayName) (
+ LPOLESTR *lplpszDisplayName);
+ STDMETHOD(BindToSource) ( DWORD bindflags, LPBINDCTX pbc);
+ STDMETHOD(BindIfRunning) (void);
+ STDMETHOD(GetBoundSource) ( LPUNKNOWN *pUnk);
+ STDMETHOD(UnbindSource) (void);
+ STDMETHOD(Update) ( LPBINDCTX pbc);
+
+ // IRunnableObject methods
+
+ INTERNAL_(IRunnableObject FAR*) GetRODelegate(void);
+ INTERNAL_(void) ReleaseRODelegate(void);
+
+ STDMETHOD(GetRunningClass) (LPCLSID lpClsid);
+ STDMETHOD(Run) (LPBINDCTX pbc);
+ STDMETHOD_(BOOL,IsRunning) (void);
+ STDMETHOD(LockRunning)(BOOL fLock, BOOL fLastUnlockCloses);
+ STDMETHOD(SetContainedObject)(BOOL fContained);
+
+ // IPersistStorage methods
+
+ STDMETHOD(GetClassID) ( LPCLSID pClassID);
+ STDMETHOD(IsDirty) (void);
+ STDMETHOD(InitNew) ( LPSTORAGE pstg);
+ STDMETHOD(Load) ( LPSTORAGE pstg);
+ STDMETHOD(Save) ( LPSTORAGE pstgSave, BOOL fSameAsLoad);
+ STDMETHOD(SaveCompleted) ( LPSTORAGE pstgNew);
+ STDMETHOD(HandsOffStorage) ( void);
+
+ // will really check to see if the server is still
+ // running and do appropriate cleanups if we have
+ // crashed
+
+ STDMETHOD_(BOOL, IsReallyRunning)(void);
+
+
+ // NOTE: the advise sink has a separate controlling unknown from the
+ // other interfaces; the lifetime of the memory for this implementation
+ // is still the same as the default handler. The ramifications of
+ // this are that when the default handler goes away it must make sure
+ // that all pointers back to the sink are released; see the special
+ // code in the dtor of the default handler.
+ class CAdvSinkImpl : public IAdviseSink
+ {
+ public:
+
+ STDMETHOD(QueryInterface) ( REFIID iid, LPVOID *ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ // *** IAdviseSink methods ***
+ STDMETHOD_(void,OnDataChange)( FORMATETC *pFormatetc,
+ STGMEDIUM *pStgmed);
+ STDMETHOD_(void,OnViewChange)( DWORD aspects, LONG lindex);
+ STDMETHOD_(void,OnRename)( IMoniker *pmk);
+ STDMETHOD_(void,OnSave)(void);
+ STDMETHOD_(void,OnClose)(void);
+ };
+
+ friend class CAdvSinkImpl;
+ CAdvSinkImpl m_AdviseSink;
+
+#ifdef _DEBUG
+
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+
+ // need to be able to access CDefLink private data members in the
+ // following debugger extension APIs
+ // this allows the debugger extension APIs to copy memory from the
+ // debuggee process memory to the debugger's process memory
+ // this is required since the Dump method follows pointers to other
+ // structures and classes
+ friend DEBUG_EXTENSION_API(dump_deflink);
+
+#endif // _DEBUG
+
+private:
+
+ CDefLink( IUnknown *pUnkOuter);
+ INTERNAL_(void) CleanupForDelete(void);
+ ~CDefLink (void);
+
+ INTERNAL_(void) UpdateUserClassID();
+ INTERNAL_(void) BeginUpdates(void);
+ INTERNAL_(void) EndUpdates(void);
+ INTERNAL_(void) UpdateAutoOnSave(void);
+ INTERNAL_(void) UpdateRelMkFromAbsMk(IMoniker *pmkContainer);
+ INTERNAL UpdateMksFromAbs(IMoniker *pmkContainer, IMoniker *pmkAbs);
+ INTERNAL GetAbsMkFromRel(LPMONIKER *ppmkAbs, IMoniker **ppmkContainer );
+ INTERNAL SetUpdateTimes( void );
+#ifdef _TRACKLINK_
+ INTERNAL EnableTracking( IMoniker * pmk, ULONG ulFlags );
+#endif
+
+ INTERNAL_(IOleItemContainer FAR*) GetOleItemContainerDelegate(void);
+ INTERNAL_(void) ReleaseOleItemContainerDelegate(void);
+
+ INTERNAL_(void) CheckDelete(void);
+
+ DWORD m_flags; // DLFlags enumeration
+ IDataObject * m_pDataDelegate;
+ IOleObject * m_pOleDelegate;
+ IRunnableObject * m_pRODelegate;
+ IOleItemContainer * m_pOleItemContainerDelegate;
+
+ ULONG m_cRefsOnLink;
+ IUnknown * m_pUnkOuter;
+ IMoniker * m_pMonikerAbs; // THE absolute moniker
+ // of the link source
+ IMoniker * m_pMonikerRel; // THE relative moniker
+ // of the link source
+ IUnknown * m_pUnkDelegate; // from mk bind; non-null
+ // if running
+ DWORD m_dwUpdateOpt;
+ CLSID m_clsid; // last known clsid of
+ // link source;
+ // NOTE: may be NULL
+ IStorage * m_pStg;
+
+ // data cache
+ COleCache * m_pCOleCache; // cache (always non-NULL)
+
+ // ole advise info
+ COAHolder * m_pCOAHolder; // OleAdviseHolder
+
+ DWORD m_dwConnOle; // if running, ole advise conn.
+
+ LPDATAADVCACHE m_pDataAdvCache;// data advise cache
+
+ IOleClientSite * m_pAppClientSite;// not passed to server!
+
+ DWORD m_dwConnTime; // dwConnection for time
+ // changes
+ FILETIME m_ltChangeOfUpdate;
+ FILETIME m_ltKnownUpToDate;
+ FILETIME m_rtUpdate;
+};
+
+
diff --git a/private/ole32/ole232/stdimpl/defsrv.cpp b/private/ole32/ole232/stdimpl/defsrv.cpp
new file mode 100644
index 000000000..8ba2fe9c0
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/defsrv.cpp
@@ -0,0 +1,585 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: defsrv.cpp
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 10-19-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+
+#include <le2int.h>
+
+#ifdef SERVER_HANDLER
+
+#include <scode.h>
+#include <objerror.h>
+
+#include <olerem.h>
+
+#include "defhndlr.h"
+#include "defutil.h"
+#include "ole1cls.h"
+
+#ifdef _DEBUG
+#include <dbgdump.h>
+#endif // _DEBUG
+
+
+ASSERTDATA
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDefObject::SrvInitialize
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 10-19-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CDefObject::SrvInitialize(void)
+{
+ HRESULT hresult = NOERROR;
+ VDATEHEAP();
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CDefObject::Initialize\n", this));
+
+ CLSID clsidsrv = CLSID_ServerHandler;
+ Assert (( CanUseServerHandler() ));
+ Assert((m_pProxyMgr != NULL));
+
+ if (CanUseClientSiteHandler())
+ {
+ hresult = CreateClientSiteHandler(m_pAppClientSite, &_pClientSiteHandler);
+ if (FAILED(hresult))
+ {
+ _pClientSiteHandler = NULL;
+ }
+ Assert((_pClientSiteHandler != NULL));
+
+ }
+
+ hresult = m_pProxyMgr->CreateServerWithHandler(m_clsidServer,
+ CLSCTX_LOCAL_SERVER, NULL,clsidsrv,
+ IID_IServerHandler, (void **) &_pSrvHndlr,
+ IID_IClientSiteHandler, _pClientSiteHandler);
+
+ if (SUCCEEDED(hresult))
+ {
+ // set up the server handler and call InitializeAndRun on it
+ Assert((_pSrvHndlr != NULL));
+ }
+ else
+ {
+ // try to get server without server handler object
+
+ _dwClientSiteHandler = 0;
+ _dwServerHandler = 0;
+
+ // release the client handler
+ if (_pClientSiteHandler)
+ {
+ _pClientSiteHandler->Release();
+ _pClientSiteHandler = NULL;
+ }
+ // Note: do not try to launch the server without handler here
+ // this will be done by the default handler
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CDefObject::SrvInitialize\n", this));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDefObject::SrvRun
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 10-19-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CDefObject::SrvRun(void)
+{
+ HRESULT hresult = NOERROR;
+ VDATEHEAP();
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CDefObject::SrvRun\n", this));
+ INSRVRUN InSrvRun;
+ OUTSRVRUN *pOutSrvRun = NULL;
+ BOOL fLockedContainer;
+ IMoniker *pmk;
+
+ memset((void*)&InSrvRun, 0, sizeof(InSrvRun));
+ Assert((_pSrvHndlr));
+
+ // get the Container and lock it
+
+ // NOTE: the lock state of the proxy mgr is not changed; it remembers
+ // the state and sets up the connection correctly.
+
+ // server is running; normally this coincides with locking the
+ // container, but we keep a separate flag since locking the container
+ // may fail.
+
+ m_flags |= DH_FORCED_RUNNING;
+ // Lock the container
+ fLockedContainer = m_flags & DH_LOCKED_CONTAINER;
+ DuLockContainer(m_pAppClientSite, TRUE, &fLockedContainer );
+ if( fLockedContainer )
+ {
+ m_flags |= DH_LOCKED_CONTAINER;
+ }
+ else
+ {
+ m_flags &= ~DH_LOCKED_CONTAINER;
+ }
+
+ // PStgDelegate Load or InitNew
+ InSrvRun.dwInFlags = m_flags;
+ InSrvRun.pStg = m_pStg;
+
+ if (NULL == m_pPSDelegate)
+ {
+ InSrvRun.dwOperation |= OP_NeedPersistStorage;
+ }
+ if (NULL == m_pDataDelegate)
+ {
+ InSrvRun.dwOperation |= OP_NeedDataObject;
+ }
+ if (NULL == m_pOleDelegate)
+ {
+ InSrvRun.dwOperation |= OP_NeedOleObject;
+ InSrvRun.dwOperation |= OP_NeedUserClassID;
+ }
+
+ // Set the clientsite
+ if (m_pAppClientSite)
+ {
+ InSrvRun.dwOperation |= OP_GotClientSite;
+ }
+
+ // set the hostname
+ InSrvRun.pszContainerApp = (LPOLESTR)m_pHostNames;
+ InSrvRun.pszContainerObj = (LPOLESTR)(m_pHostNames + m_ibCntrObj);
+
+
+ // adivse sink
+ Assert((m_dwConnOle == 0L));
+ InSrvRun.pAS = (IAdviseSink *) &m_AdviseSink;
+ InSrvRun.dwConnOle = m_dwConnOle;
+
+ // Get the Moniker and call
+ if(m_pAppClientSite != NULL)
+ {
+ if (m_pAppClientSite->GetMoniker
+ (OLEGETMONIKER_ONLYIFTHERE,OLEWHICHMK_OBJREL, &pmk) == NOERROR)
+ {
+ AssertOutPtrIface(NOERROR, pmk);
+ InSrvRun.pMnk = pmk;
+ }
+ else
+ {
+ InSrvRun.pMnk = NULL;
+ }
+
+ // QI for IMsoDocumentSite
+ IUnknown *pMsoDS = NULL;
+
+ hresult = m_pAppClientSite->QueryInterface(
+ IID_IMsoDocumentSite,
+ (void **)&pMsoDS);
+ if (hresult == NOERROR)
+ {
+ // indicate we have MsoDocumentSite
+ InSrvRun.dwOperation |= OP_HaveMsoDocumentSite;
+ pMsoDS->Release();
+ }
+ }
+
+
+ // MAKE CALL TO SERVERHANDLER
+ hresult = _pSrvHndlr->RunAndInitialize(&InSrvRun, &pOutSrvRun);
+
+ if (SUCCEEDED(hresult))
+ {
+ if (InSrvRun.dwOperation & OP_NeedPersistStorage)
+ {
+ Assert(NULL != pOutSrvRun->pPStg);
+ m_pPSDelegate = pOutSrvRun->pPStg;
+ }
+ if (InSrvRun.dwOperation & OP_NeedDataObject)
+ {
+ Assert(NULL != pOutSrvRun->pDO);
+ m_pDataDelegate = pOutSrvRun->pDO;
+
+ // inform cache that we are running
+ Assert(NULL != m_pCOleCache);
+ m_pCOleCache->OnRun(m_pDataDelegate);
+
+ // Enumerate all the advises we stored while we were either not
+ // running or running the previous time, and send them to the
+ // now-running object.
+ Assert(NULL != m_pDataAdvCache);
+ m_pDataAdvCache->EnumAndAdvise(m_pDataDelegate, TRUE);
+ }
+ if (InSrvRun.dwOperation & OP_NeedOleObject)
+ {
+ Assert(NULL != pOutSrvRun->pOO);
+ m_pOleDelegate = pOutSrvRun->pOO;
+ }
+ if (InSrvRun.dwOperation & OP_NeedUserClassID)
+ {
+ Assert(NULL != pOutSrvRun->pUserClassID);
+ m_clsidUser = *(pOutSrvRun->pUserClassID);
+ }
+
+ m_dwConnOle = pOutSrvRun->dwOutFlag;
+
+ if (InSrvRun.pMnk != NULL)
+ {
+ InSrvRun.pMnk->Release();
+ }
+
+ // release the pUnkOuter for all marshald pointers
+ if (m_pPSDelegate && m_pUnkOuter)
+ {
+ m_pUnkOuter->Release();
+ }
+ if (m_pOleDelegate && m_pUnkOuter)
+ {
+ m_pUnkOuter->Release();
+ }
+ if (m_pDataDelegate && m_pUnkOuter)
+ {
+ m_pUnkOuter->Release();
+ }
+ }
+ else // Server Handler RunAndInitialize has failed... now clean up.
+ {
+ Stop();
+
+ // if for some reason we did not unlock the container by now,
+ // do it (e.g., app crashed or failed during InitNew).
+
+ fLockedContainer = (m_flags & DH_LOCKED_CONTAINER);
+
+ DuLockContainer(m_pAppClientSite, FALSE, &fLockedContainer );
+
+ if( fLockedContainer )
+ {
+ m_flags |= DH_LOCKED_CONTAINER;
+ }
+ else
+ {
+ m_flags &= ~DH_LOCKED_CONTAINER;
+ }
+
+ if (InSrvRun.pMnk != NULL)
+ {
+ InSrvRun.pMnk->Release();
+ }
+ }
+
+ if (pOutSrvRun != NULL)
+ {
+ PubMemFree(pOutSrvRun->pUserClassID); // OK to free NULL;
+ PubMemFree(pOutSrvRun);
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CDefObject::SrvRun( %lx )\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDefObject::SrvRunAndDoVerb
+//
+// Synopsis:
+//
+// Arguments: [iVerb] --
+// [lpmsg] --
+// [pActiveSite] --
+// [lindex] --
+// [hwndParent] --
+// [lprcPosRect] --
+//
+// Returns:
+//
+// History: 10-19-95 JohannP (Johann Posch) Created
+//
+// Notes: This is not implemented yet.
+//
+//----------------------------------------------------------------------------
+HRESULT CDefObject::SrvRunAndDoVerb( LONG iVerb, LPMSG lpmsg,
+ LPOLECLIENTSITE pActiveSite, LONG lindex,
+ HWND hwndParent, const RECT * lprcPosRect)
+{
+ HRESULT hresult = NOERROR;
+ VDATEHEAP();
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CDefObject::SrvRunAndDoVerb\n", this));
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CDefObject::SrvRunAndDoVerb\n", this));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDefObject::SrvDoVerb
+//
+// Synopsis: 1. gathers information on the client site
+// 2. calls the serverhandler with SrvDoverb with collected information
+// 3. serverhandler sets up connections and calls
+// OleObject::DoVerb on reall object
+// 4. release objects which did not get used
+//
+// Arguments: [iVerb] -- OleObject DoVerb parameter
+// [lpmsg] -- detto
+// [pActiveSite] -- detto
+// [lindex] -- detto
+// [hwndParent] -- detto
+// [lprcPosRect] -- detto
+//
+// Returns:
+//
+// History: 10-19-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CDefObject::SrvDoVerb( LONG iVerb, LPMSG lpmsg,
+ LPOLECLIENTSITE pActiveSite, LONG lindex,
+ HWND hwndParent, const RECT * lprcPosRect)
+{
+ HRESULT hresult = NOERROR;
+ VDATEHEAP();
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CDefObject::SrvDoVerb\n", this));
+ CInSrvRun InSrvRun;
+ OUTSRVRUN *pOutSrvRun = NULL;
+ IOleContainer *pOCont = NULL;
+ IOleObject *pOOCont = NULL;
+ IOleClientSite *pOContCS;
+ IOleInPlaceSite *pOIPS;
+
+ // set up the DoVerb parametes
+ InSrvRun.dwOperation = 0;
+ InSrvRun.iVerb = iVerb;
+ InSrvRun.lpmsg = lpmsg;
+ InSrvRun.lindex = lindex;
+ InSrvRun.hwndParent = hwndParent;
+ InSrvRun.lprcPosRect = (RECT *)lprcPosRect;
+
+ // Step 1: set up OleClientSiteActive
+ if (pActiveSite)
+ {
+ // Currently this Assert goes off with LE test = deflink-1854 (bchapman Mar'96)
+ Assert(NULL != _pClientSiteHandler);
+
+ _pClientSiteHandler->SetClientSiteDelegate(ID_ClientSiteActive, pActiveSite);
+ InSrvRun.dwOperation |= OP_GotClientSiteActive;
+ }
+
+ // Step 2: IOleClientSite::GetContainer
+ // Note: this call might cause a GetUserClassID call
+ // to the server
+ hresult = m_pAppClientSite->GetContainer(&pOCont);
+ if (hresult == NOERROR)
+ {
+ HdlAssert((_pClientSiteHandler->_pOCont == NULL));
+
+ _pClientSiteHandler->_pOCont = pOCont;
+ InSrvRun.dwOperation |= OP_GotContainer;
+
+ // Step 3: QI on OleContainer for the OleObject
+ hresult = pOCont->QueryInterface(IID_IOleObject, (void **)&pOOCont);
+ if (hresult == NOERROR)
+ {
+ InSrvRun.dwOperation |= OP_GotOleObjectOfContainer;
+
+ // release OleObject of container
+ pOOCont->Release();
+ }
+ }
+
+ // Step 6: OI for IOleInPlaceSite
+ hresult = m_pAppClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&pOIPS);
+ if (hresult == NOERROR)
+ {
+ // set up OleInPlaceSite on the clientsitehandler
+ HdlAssert((_pClientSiteHandler != NULL));
+
+ // release the old OleInPlaceSite
+ if (_pClientSiteHandler->_pOIPS)
+ {
+ _pClientSiteHandler->_pOIPS->Release();
+ }
+
+ _pClientSiteHandler->_pOIPS = pOIPS;
+
+ // Step 7: IOleInPlaceSite::CanInPlaceActivate
+ InSrvRun.dwInPlace = pOIPS->CanInPlaceActivate();
+
+ // indicate we have OleInPlaceSite
+ InSrvRun.dwOperation |= OP_GotInPlaceSite;
+ }
+
+
+ // call the ServerHandler
+ HdlDebugOut((DEB_SERVERHANDLER, "%p In CDefObject::SrvDoVerb calling DoVerb on ServerHandler!\n",this));
+ hresult = _pSrvHndlr->DoVerb(&InSrvRun, &pOutSrvRun);
+ HdlDebugOut((DEB_SERVERHANDLER, "%p In CDefObject::SrvDoVerb return from DoVerb on ServerHandler!\n",this));
+
+ Assert(NULL != _pClientSiteHandler);
+
+ if (FAILED(hresult))
+ {
+ HdlDebugOut((DEB_ERROR, "OO::DoVerb failed !"));
+ goto errRtn;
+ }
+ // Release the active OleClientSite if not used by server
+ if ( (InSrvRun.dwOperation & OP_GotClientSiteActive)
+ && !(pOutSrvRun->dwOperation & OP_GotClientSiteActive) )
+ {
+ // release the active clientsite if not used by the server app.
+ Assert(NULL != _pClientSiteHandler);
+
+ _pClientSiteHandler->SetClientSiteDelegate(ID_ClientSiteActive, NULL);
+ }
+
+ // Release OleInPlaceSite if not used by server
+ if ( (InSrvRun.dwOperation & OP_GotInPlaceSite)
+ && !(pOutSrvRun->dwOperation & OP_GotInPlaceSite) )
+ {
+ _pClientSiteHandler->SetClientSiteDelegate(ID_InPlaceSite,NULL);
+ }
+
+ // Release the container if not used by server
+ if ( (InSrvRun.dwOperation & OP_GotContainer)
+ && !(pOutSrvRun->dwOperation & OP_GotContainer) )
+ {
+ _pClientSiteHandler->SetClientSiteDelegate(ID_Container,NULL);
+ }
+
+errRtn:
+
+ // delete the out parameter
+ if (pOutSrvRun)
+ {
+ PubMemFree(pOutSrvRun);
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CDefObject::SrvDoVerb\n",this));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDefObject::SrvRelease
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 10-19-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD CDefObject::SrvRelease(void)
+{
+ VDATEHEAP();
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CDefObject::SrvRelease\n", this));
+ Assert((_pSrvHndlr != NULL));
+
+ DWORD dwRet = _pSrvHndlr->Release();
+#if DBG==1
+ if (dwRet)
+ {
+ HdlDebugOut((DEB_ERROR, "Last IServerHandler::Release() return %ld\n", dwRet));
+ }
+#endif
+
+ _pSrvHndlr = NULL;
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CDefObject::SrvRelease\n", this));
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDefObject::SrvCloseAndRelease
+//
+// Synopsis:
+//
+// Arguments: [dwFlag] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CDefObject::SrvCloseAndRelease(DWORD dwFlag)
+{
+ HRESULT hresult;
+ VDATEHEAP();
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CDefObject::SrvCloseAndRelease\n", this));
+ HdlAssert((_pSrvHndlr != NULL));
+
+ hresult = _pSrvHndlr->CloseAndRelease(dwFlag);
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CDefObject::SrvSrvCloseAndRelease hr:%lx\n",this,hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CDefObject::InitializeServerHandlerOptions
+//
+// Synopsis:
+//
+// Arguments: [clsidSrv] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes: determines server application specifics which can be used
+// to make serverhandler operations more efficient
+// Review: (JohannP) we would need a flag in the registery or so
+//
+//----------------------------------------------------------------------------
+void CDefObject::InitializeServerHandlerOptions(REFCLSID clsidSrv)
+{
+ VDATEHEAP();
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CDefObject::InitializeServerHandlerOptions\n",this));
+
+ //
+ // this method should retrieve server application specific informantion
+ //
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CDefObject::InitializeServerHandlerOptions\n",this));
+}
+
+#endif // SERVER_HANDLER
diff --git a/private/ole32/ole232/stdimpl/defutil.cpp b/private/ole32/ole232/stdimpl/defutil.cpp
new file mode 100644
index 000000000..147ca54c1
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/defutil.cpp
@@ -0,0 +1,317 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: defutil.cpp
+//
+// Contents: Implementations of utility functions for the default
+// handler and default link objects
+//
+// Classes: none
+//
+// Functions: DuLockContainer
+// DuSetClientSite
+// DuGetClientSite
+// DuCacheDelegate
+//
+// History: dd-mmm-yy Author Comment
+// 11-Jan-94 alexgo added VDATEHEAP macros to every function
+// 20-Nov-93 alexgo 32bit port
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#pragma SEG(defutil)
+
+#include <olerem.h>
+#include <ole2dbg.h>
+
+ASSERTDATA
+NAME_SEG(defutil)
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DuLockContainer
+//
+// Synopsis: Calls IOleContainer->LockContainer from the given client site
+//
+// Effects: Unlocking the container may release the calling object.
+//
+// Arguments: [pCS] -- the client site from which to get
+// the IOleContainer pointer
+// [fLockNew] -- TRUE == lock, FALSE == unlock
+// [pfLockCur] -- pointer to a flag with the current lock
+// state
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 20-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(DuLockContainer)
+INTERNAL_(void) DuLockContainer(IOleClientSite FAR* pCS, BOOL fLockNew,
+ BOOL FAR*pfLockCur)
+{
+ VDATEHEAP();
+
+#ifdef _DEBUG
+ BOOL fLocked = FALSE; // used only for debugging so don't waste
+ // the code space in the retail version
+#endif // _DEBUG
+
+ IOleContainer FAR* pContainer;
+
+ //the double bang turns each into a true boolean
+ if (!!fLockNew == !!*pfLockCur)
+ {
+ // already locked as needed
+ return;
+ }
+
+ // set flag to false first since unlocking container may release obj;
+ // we can just set to false since it is either already false or going
+ // to become false (don't set to true until we know the lock completed).
+ *pfLockCur = FALSE;
+
+ if (pCS == NULL)
+ {
+ pContainer = NULL;
+ }
+ else
+ {
+ HRESULT hresult = pCS->GetContainer(&pContainer);
+
+ // Excel 5 can return S_FALSE, pContainer == NULL
+ // so we can't use AssertOutPtrIface here since it
+ // expects all successful returns to provide a
+ // valid interface
+
+ if (hresult != NOERROR)
+ {
+ pContainer = NULL; // just in case
+ }
+ }
+ if (pContainer != NULL)
+ {
+ // we assume that LockContainer will succeed first and
+ // and set the locked flag that was passed into us. This
+ // way, if LockContainer succeeeds, we won't access memory
+ // that could have potentially been blown away.
+ // If it *fails*, then we handle reset the flag (as our
+ // memory would not have been free'd)
+
+ BOOL fLockOld = *pfLockCur;
+ *pfLockCur = fLockNew;
+
+ if( pContainer->LockContainer(fLockNew) != NOERROR )
+ {
+ //failure case, we were not deleted
+ *pfLockCur = fLockOld;
+ //fLocked is FALSE
+ }
+#ifdef _DEBUG
+ else
+ {
+ fLocked = TRUE;
+ }
+#endif // _DEBUG
+
+ pContainer->Release();
+ }
+
+#ifdef _DEBUG
+ if (!fLocked)
+ {
+ Puts("WARNING: couldn't lock/unlock container for clientsite:\n");
+ DbgDumpObject(pCS,0);
+ }
+#endif // _DEBUG
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DuSetClientSite
+//
+// Synopsis: Called by the default handler and deflink SetClientSite
+// implemenations; Releases the old client site (and unlocks
+// its container), stores the client site (locking its
+// container).
+//
+// Effects:
+//
+// Arguments: [fRunning] -- whether or not the delegate is running
+// [pCSNew] -- the new client site
+// [ppCSCur] -- a pointer to the original client site
+// pointer. [*ppCSCur] will be reset
+// to the new client site pointer.
+// [pfLockCur] -- pointer to the fLocked flag, used by
+// DuLockContainer.
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 22-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(DuSetClientSite)
+INTERNAL DuSetClientSite(BOOL fRunning, IOleClientSite FAR* pCSNew,
+ IOleClientSite FAR* FAR* ppCSCur, BOOL FAR*pfLockCur)
+{
+ VDATEHEAP();
+
+ if (pCSNew)
+ {
+ VDATEIFACE( pCSNew );
+ }
+
+ IOleClientSite FAR* pCSCur = *ppCSCur;
+
+ if (pCSCur != NULL)
+ {
+ // Unlock the old container
+ if (fRunning)
+ {
+ DuLockContainer(pCSCur, FALSE, pfLockCur);
+ }
+
+ pCSCur->Release();
+ }
+
+ // we've decided to keep the pointer that's been passed to us. So we
+ // must AddRef()
+ if ((pCSCur = pCSNew) != NULL)
+ {
+ pCSNew->AddRef();
+
+ // Lock the newcontainer
+ if (fRunning)
+ {
+ DuLockContainer(pCSNew, TRUE, pfLockCur);
+ }
+ }
+
+ *ppCSCur = pCSCur;
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DuCacheDelegate
+//
+// Synopsis: Retrieves the requested interface from [pUnk]. If [fAgg] is
+// true, we release the pointer (so ref counts to not get
+// obfuscated ;-)
+//
+// Effects:
+//
+// Arguments: [ppUnk] -- the object to QueryInterface on
+// [iid] -- the requested interface
+// [ppv] -- where to put the pointer to the interface
+// [pUnkOuter] -- controlling unknown, if non-NULL indicates
+// aggregation and release is called on it
+//
+//
+//
+// Requires:
+//
+// Returns: void *, the requested interface pointer
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Jun-94 alexgo better handle re-entrancy
+// 20-Jun-94 alexgo updated to May '94 aggregation rules
+// 22-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(DuCacheDelegate)
+INTERNAL_(void FAR*) DuCacheDelegate(IUnknown FAR** ppUnk,
+ REFIID iid, LPVOID FAR* ppv, IUnknown *pUnkOuter)
+{
+ VDATEHEAP();
+
+ if (*ppUnk != NULL && *ppv == NULL)
+ {
+ if ((*ppUnk)->QueryInterface (iid, ppv) == NOERROR)
+ {
+ // the QI may actually be an outgoing call so it
+ // is possible that ppUnk was released and set to
+ // NULL during our call. To make the default link
+ // and handler simpler, we check for that case and
+ // release any pointer we may have obtained
+ // from the QI
+
+ if( *ppUnk == NULL )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: Delegate "
+ "released during QI, should be OK\n"));
+ if( *ppv )
+ {
+ // this should never be a final
+ // release on the default handler
+ // since we are calling it from
+ // within a method in the default
+ // link object. Therefore,
+ // we do not need to guard this
+ // release
+ //
+ // in the case of the link object,
+ // this may be the final release
+ // on the proxies, but since they are
+ // not aggregated into the link
+ // object, that's OK.
+
+ (*(IUnknown **)ppv)->Release();
+ *ppv = NULL;
+ }
+ }
+ if( pUnkOuter && *ppv)
+ {
+ // we will keep the pointer but we don't want
+ // to bump the ref count of the aggregate,
+ // so we gotta do Release() on the controlling
+ // unknown.
+ pUnkOuter->Release();
+ }
+ }
+ }
+
+ return *ppv;
+}
+
+
diff --git a/private/ole32/ole232/stdimpl/defutil.h b/private/ole32/ole232/stdimpl/defutil.h
new file mode 100644
index 000000000..a7b66edf0
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/defutil.h
@@ -0,0 +1,46 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: defutil.h
+//
+// Contents: Declarations for utility functions used in the default
+// handler and default link
+//
+// Classes:
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 20-Nov-93 alexgo 32bit port
+//
+//--------------------------------------------------------------------------
+
+#if !defined( _DEFUTIL_H_ )
+#define _DEFUTIL_H_
+
+INTERNAL_(void) DuLockContainer(IOleClientSite FAR* pCS,
+ BOOL fLockNew,
+ BOOL FAR*pfLockCur);
+INTERNAL DuSetClientSite(BOOL fRunning,
+ IOleClientSite FAR* pCSNew,
+ IOleClientSite FAR* FAR* ppCSCur,
+ BOOL FAR*pfLockCur);
+INTERNAL_(void FAR*) DuCacheDelegate(IUnknown FAR** ppUnk,
+ REFIID iid,
+ LPVOID FAR* ppv,
+ IUnknown *pUnkOuter);
+
+
+#define GET_FROM_REGDB(scode) \
+ (((scode == OLE_S_USEREG) || (scode == RPC_E_CANTPOST_INSENDCALL) || \
+ (scode == RPC_E_CANTCALLOUT_INASYNCCALL) || \
+ (scode == RPC_E_CANTCALLOUT_INEXTERNALCALL) || \
+ (scode == RPC_E_CANTCALLOUT_ININPUTSYNCCALL) || \
+ (scode == RPC_E_CALL_CANCELED) || (scode == RPC_E_CALL_REJECTED)) \
+ ? TRUE : FALSE)
+
+
+#endif // _DEFUTIL_H
diff --git a/private/ole32/ole232/stdimpl/depend.mk b/private/ole32/ole232/stdimpl/depend.mk
new file mode 100644
index 000000000..7cf7c038e
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/depend.mk
@@ -0,0 +1,279 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\defcf.obj $(OBJDIR)\defcf.lst: .\defcf.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\olerem.h $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\dacache.h $(CAIROLE)\ole232\inc\map_dwdw.h \
+ $(CAIROLE)\ole232\inc\memstm.h $(CAIROLE)\ole232\inc\oaholder.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(CAIROLE)\ole232\inc\olecache.h \
+ $(CAIROLE)\ole232\inc\olepres.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\defhndlr.h \
+ .\deflink.h
+
+$(OBJDIR)\defhndlr.obj $(OBJDIR)\defhndlr.lst: .\defhndlr.cpp \
+ $(CAIROLE)\ole232\inc\olepres.h $(CAIROLE)\common\cobjerr.h \
+ $(CAIROLE)\common\rpcferr.h $(CAIROLE)\h\coguid.h \
+ $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h $(CAIROLE)\h\initguid.h \
+ $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h $(CAIROLE)\h\ole2dbg.h \
+ $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h $(CAIROLE)\h\storage.h \
+ $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h $(CAIROLE)\ih\ole2sp.h \
+ $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h $(CAIROLE)\ih\olerem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\dacache.h $(CAIROLE)\ole232\inc\map_dwdw.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(CAIROLE)\ole232\inc\olecache.h \
+ $(CAIROLE)\ole232\inc\olepres.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\defutil.h \
+ .\defhndlr.h
+
+$(OBJDIR)\deflink.obj $(OBJDIR)\deflink.lst: .\deflink.cpp \
+ $(CAIROLE)\ole232\inc\olepres.h $(CAIROLE)\common\cobjerr.h \
+ $(CAIROLE)\common\rpcferr.h $(CAIROLE)\h\coguid.h \
+ $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h $(CAIROLE)\h\initguid.h \
+ $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h $(CAIROLE)\h\ole2dbg.h \
+ $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h $(CAIROLE)\h\storage.h \
+ $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h $(CAIROLE)\ih\ole2sp.h \
+ $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\dacache.h $(CAIROLE)\ole232\inc\map_dwdw.h \
+ $(CAIROLE)\ole232\inc\oaholder.h $(CAIROLE)\ole232\inc\ole2int.h \
+ $(CAIROLE)\ole232\inc\olecache.h $(CAIROLE)\ole232\inc\olepres.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\malloc.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\wchar.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\widewrap.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winmm.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\deflink.h .\defutil.h
+
+$(OBJDIR)\defutil.obj $(OBJDIR)\defutil.lst: .\defutil.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\olerem.h $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\gen.obj $(OBJDIR)\gen.lst: .\gen.cpp \
+ $(CAIROLE)\ole232\inc\cachenod.h $(CAIROLE)\ole232\inc\gen.h \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(CAIROLE)\ole232\inc\olecache.h \
+ $(CAIROLE)\ole232\inc\olepres.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\icon.obj $(OBJDIR)\icon.lst: .\icon.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\memory.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\malloc.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\wchar.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\widewrap.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winmm.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\icon.h
+
+$(OBJDIR)\mf.obj $(OBJDIR)\mf.lst: .\mf.cpp $(CAIROLE)\ole232\inc\mf.h \
+ $(CAIROLE)\ole232\inc\qd2gdi.h $(CAIROLE)\common\cobjerr.h \
+ $(CAIROLE)\common\rpcferr.h $(CAIROLE)\h\coguid.h \
+ $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h $(CAIROLE)\h\initguid.h \
+ $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h $(CAIROLE)\h\ole2dbg.h \
+ $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h $(CAIROLE)\h\storage.h \
+ $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h $(CAIROLE)\ih\ole2sp.h \
+ $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\cachenod.h $(CAIROLE)\ole232\inc\ole2int.h \
+ $(CAIROLE)\ole232\inc\olecache.h $(CAIROLE)\ole232\inc\olepres.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(CRTINC)\wchar.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\widewrap.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winmm.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\olereg.obj $(OBJDIR)\olereg.lst: .\olereg.cpp \
+ $(CAIROLE)\ole232\inc\reterr.h $(CAIROLE)\common\cobjerr.h \
+ $(CAIROLE)\common\rpcferr.h $(CAIROLE)\h\coguid.h \
+ $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h $(CAIROLE)\h\initguid.h \
+ $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h $(CAIROLE)\h\ole2dbg.h \
+ $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h $(CAIROLE)\h\storage.h \
+ $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h $(CAIROLE)\ih\ole2sp.h \
+ $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\oleregpv.h
+
+$(OBJDIR)\oregfmt.obj $(OBJDIR)\oregfmt.lst: .\oregfmt.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(CAIROLE)\ole232\inc\reterr.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\malloc.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\wchar.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\widewrap.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winmm.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\oleregpv.h
+
+$(OBJDIR)\oregverb.obj $(OBJDIR)\oregverb.lst: .\oregverb.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(CAIROLE)\ole232\inc\reterr.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\malloc.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\wchar.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\widewrap.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winmm.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\oleregpv.h
+
diff --git a/private/ole32/ole232/stdimpl/dirs b/private/ole32/ole232/stdimpl/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/ole232/stdimpl/emf.cpp b/private/ole32/ole232/stdimpl/emf.cpp
new file mode 100644
index 000000000..bcda41935
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/emf.cpp
@@ -0,0 +1,1729 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: emf.cpp
+//
+// Contents: Implentation of the enhanced metafile picture object
+//
+// Classes: CEMfObject
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH added Dump method to EMfObject
+// added DumpEMfObject API
+// initialize m_pfnContinue in constructor
+// 12-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#include <limits.h>
+#include "emf.h"
+
+#ifdef _DEBUG
+#include <dbgdump.h>
+#endif // _DEBUG
+
+ASSERTDATA
+
+//+-------------------------------------------------------------------------
+//
+// Function: CEMfObject::M_HPRES
+//
+// Synopsis: Returns handle to EMF, possibly after demand-loading it
+//
+// History: dd-mmm-yy Author Comment
+// 12-May-94 DavePl Created
+//
+// Notes:
+// The following macro allows for demand loading of the
+// presentation bits for enhanced metafiles. If the handle to
+// the EMF (m_hPres) is already set, it is returned. If it is
+// not, LoadHPRES() is called which loads the presentation and
+// returns the handle to it.
+//
+//--------------------------------------------------------------------------
+
+inline HENHMETAFILE CEMfObject::M_HPRES(void)
+{
+ return (m_hPres ? m_hPres : LoadHPRES());
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::CEMfObject
+//
+// Synopsis: constructor for the enhanced metafile object
+//
+// Effects:
+//
+// Arguments: [pCacheNode] -- pointer to the cache node for this object
+// [dwAspect] -- drawing aspect for the object
+//
+// History: dd-mmm-yy Author Comment
+// 13-Feb-95 t-ScottH initialize m_pfnContinue
+// 12-May-94 DavePl Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CEMfObject::CEMfObject(LPCACHENODE pCacheNode, DWORD dwAspect)
+{
+ VDATEHEAP();
+
+ m_ulRefs = 1;
+ m_hPres = NULL;
+ m_dwSize = 0;
+ m_dwAspect = dwAspect;
+ m_pCacheNode = pCacheNode;
+ m_dwContinue = 0;
+ m_pfnContinue = NULL;
+ m_lWidth = 0;
+ m_lHeight = 0;
+ m_fMetaDC = FALSE;
+ m_nRecord = 0;
+ m_error = NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::~CEMfObject
+//
+// Synopsis: Destroys an enahnced metafile presentation object
+//
+// History: dd-mmm-yy Author Comment
+// 12-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+CEMfObject::~CEMfObject (void)
+{
+ VDATEHEAP();
+
+ CEMfObject::DiscardHPRES();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::QueryInterface
+//
+// Synopsis: returns supported interfaces
+//
+// Arguments: [iid] -- the requested interface ID
+// [ppvObj] -- where to put the interface pointer
+//
+// Requires:
+//
+// Returns: NOERROR, E_NOINTERFACE
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 12-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CEMfObject::QueryInterface (REFIID iid, void ** ppvObj)
+{
+ VDATEHEAP();
+
+ if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IOlePresObj))
+ {
+ *ppvObj = this;
+ AddRef();
+ return NOERROR;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::AddRef
+//
+// Synopsis: Increments the reference count
+//
+// Returns: ULONG -- the new reference count
+//
+// Derivation: IOlePresObj
+//
+// History: dd-mmm-yy Author Comment
+// 12-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CEMfObject::AddRef(void)
+{
+ VDATEHEAP();
+
+ return (ULONG) InterlockedIncrement((LONG *) &m_ulRefs);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::Release
+//
+// Synopsis: decrements the reference count
+//
+// Effects: deletes the object once the ref count goes to zero
+//
+// Returns: ULONG -- the new reference count
+//
+// Derivation: IOlePresObj
+//
+// History: dd-mmm-yy Author Comment
+// 12-May-94 DavePl Created
+//
+// Notes: Not multi-threaded safe
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CEMfObject::Release(void)
+{
+ VDATEHEAP();
+
+ ULONG cTmp = (ULONG) InterlockedDecrement((LONG *) &m_ulRefs);
+ if (0 == cTmp)
+ {
+ delete this;
+ }
+
+ return cTmp;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::GetData
+//
+// Synopsis: Retrieves data in the specified format from the object
+//
+// Arguments: [pformatetcIn] -- the requested data format
+// [pmedium] -- where to put the data
+//
+// Returns: HRESULT
+//
+// Derivation: IOlePresObject
+//
+// History: dd-mmm-yy Author Comment
+// 12-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CEMfObject::GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
+{
+ VDATEHEAP();
+
+ HRESULT hr = NOERROR;
+ pmedium->tymed = (DWORD) TYMED_NULL;
+ pmedium->pUnkForRelease = NULL;
+
+ // We can only support enhanced metafile TYMED
+ if (!(pformatetcIn->tymed & (DWORD) TYMED_ENHMF))
+ {
+ hr = DV_E_TYMED;
+ }
+ // We can only support enhanced metafile clipformat
+ else if (pformatetcIn->cfFormat != CF_ENHMETAFILE)
+ {
+ hr = DV_E_CLIPFORMAT;
+ }
+
+ // Check to ensure we are not blank
+ else if (IsBlank())
+ {
+ hr = OLE_E_BLANK;
+ }
+
+ // Go ahead and try to get the data
+
+ else
+ {
+ HENHMETAFILE hEMF = M_HPRES();
+ if (NULL == hEMF)
+ {
+ hr = OLE_E_BLANK;
+ }
+
+ else if (NULL == (pmedium->hEnhMetaFile = CopyEnhMetaFile(hEMF, NULL)))
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ else
+ {
+ pmedium->tymed = (DWORD) TYMED_ENHMF;
+ }
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::GetDataHere
+//
+// Synopsis: Retrieves data of the specified format into the specified
+// medium
+//
+// Arguments: [pformatetcIn] -- the requested data format
+// [pmedium] -- where to put the data
+//
+// Derivation: IOlePresObj
+//
+// Algorithm: Does error checking and then copies the EMF into a
+// stream.
+//
+// History: dd-mmm-yy Author Comment
+// 14-May-94 DavePl Created
+//
+// Notes: Although I'm only handling TYMED_ISTREAM here, since that's
+// all standard metafiles provide, there's no compelling reason
+// we couldn't support other formats. In fact, supporting
+// raw bits on TYMED_HGLOBAL might be a nice addition, and
+// TYMED_MFPICT would make for an easy way to do enhanced to
+// standard conversions. NTIssue #2802.
+//
+//
+// _______
+// | DWORD | One DWORD indicating the size of the header
+// |-------|
+// | |
+// | HDR | The ENHMETAHEADER structure
+// | |
+// |-------|
+// | |
+// | DATA | Raw EMF bits
+// |_______|
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CEMfObject::GetDataHere
+ (LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
+{
+ VDATEHEAP();
+
+ HRESULT hr = NOERROR;
+
+ // We can only handle EMF format
+ if (pformatetcIn->cfFormat != CF_ENHMETAFILE)
+ {
+ hr = DV_E_CLIPFORMAT;
+ }
+ // We can only support returns to ISTREAM
+ else if (pmedium->tymed != (DWORD) TYMED_ISTREAM)
+ {
+ hr = DV_E_TYMED;
+ }
+ // The stream ptr must be valid
+ else if (pmedium->pstm == NULL)
+ {
+ hr = E_INVALIDARG;
+ }
+ // The presentation must not be blank
+ else if (IsBlank())
+ {
+ hr = OLE_E_BLANK;
+ }
+ else
+ {
+ // Get the metaheader size
+
+ HENHMETAFILE hEMF = M_HPRES();
+ DWORD dwMetaHdrSize = GetEnhMetaFileHeader(hEMF, 0, NULL);
+ if (dwMetaHdrSize == 0)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ // Allocate the meta header
+
+ void * pvHeader = PrivMemAlloc(dwMetaHdrSize);
+ if (NULL == pvHeader)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // Retrieve the ENHMETAHEADER
+
+ if (0 == GetEnhMetaFileHeader(hEMF, dwMetaHdrSize, (ENHMETAHEADER *) pvHeader))
+ {
+ PrivMemFree(pvHeader);
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ // Write the byte count to disk.
+
+ hr = StWrite(pmedium->pstm, &dwMetaHdrSize, sizeof(DWORD));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // Write the enhmetaheader to disk
+
+ hr = StWrite(pmedium->pstm, pvHeader, dwMetaHdrSize);
+
+ PrivMemFree(pvHeader);
+
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ DWORD dwSize = GetEnhMetaFileBits(hEMF, 0, NULL);
+ if (0 == dwSize)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ // Write the EMF bits to the stream
+
+ hr = UtHEMFToEMFStm(hEMF,
+ m_dwSize,
+ pmedium->pstm,
+ WRITE_AS_EMF);
+
+ }
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::SetDataWDO
+//
+// Synopsis: Stores an ehanced metafile in this object
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- format of the data coming in
+// [pmedium] -- the new metafile (data)
+// [fRelease] -- if true, then we'll release the [pmedium]
+// [IDataObject] -- unused for EMF objects
+//
+// Derivation: IOlePresObj
+//
+// History: dd-mmm-yy Author Comment
+// 14-May-94 Davepl Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CEMfObject::SetDataWDO
+ (LPFORMATETC pformatetc, STGMEDIUM * pmedium, BOOL fRelease, IDataObject * )
+{
+ VDATEHEAP();
+
+ HRESULT hr;
+ BOOL fTakeData = FALSE;
+
+ // If someone is trying to SetData on our EMF object with a standard
+ // metafile, we must convert it to EMF format
+
+ if (pformatetc->cfFormat == CF_METAFILEPICT)
+ {
+ // If its a standard metafile, it must be TYMED_MFPICT
+ if (pmedium->tymed != (DWORD) TYMED_MFPICT)
+ {
+ return DV_E_TYMED;
+ }
+
+ // We need to know the size of the metafile in bytes,
+ // so we have to lock the structure and grab the handle
+ // for a call to GetMetaFileBitsEx
+
+ METAFILEPICT * pMF = (METAFILEPICT *) GlobalLock(pmedium->hMetaFilePict);
+ if (NULL == pMF)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // Determine the no. of bytes needed to hold the
+ // metafile
+
+ DWORD dwSize = GetMetaFileBitsEx(pMF->hMF, NULL, 0);
+ if (0 == dwSize)
+ {
+ GlobalUnlock(pmedium->hMetaFilePict);
+ return E_FAIL;
+ }
+
+ // Allocate space for the metafile bits
+
+ void *pvBuffer = PrivMemAlloc(dwSize);
+ if (NULL == pvBuffer)
+ {
+ GlobalUnlock(pmedium->hMetaFilePict);
+ return E_OUTOFMEMORY;
+ }
+
+ // Retrieve the bits to our buffer
+
+ if (0 == GetMetaFileBitsEx(pMF->hMF, dwSize, pvBuffer))
+ {
+ GlobalUnlock(pmedium->hMetaFilePict);
+ PrivMemFree(pvBuffer);
+ return E_FAIL;
+ }
+
+ HENHMETAFILE hEMF = SetWinMetaFileBits(dwSize,
+ (const BYTE *) pvBuffer, NULL, pMF);
+ if (NULL == hEMF)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ GlobalUnlock(pmedium->hMetaFilePict);
+ PrivMemFree(pvBuffer);
+ return hr;
+ }
+
+ GlobalUnlock(pmedium->hMetaFilePict);
+ PrivMemFree(pvBuffer);
+
+ // Update the cache node. To avoid a copy operation, let the cache
+ // node keep our EMF. It will take the data even in the event of
+ // an error
+
+ hr = ChangeData (hEMF, TRUE /* fTakeData */ );
+
+ if (fRelease)
+ {
+ ReleaseStgMedium(pmedium);
+ }
+
+ return hr;
+ }
+
+
+
+ // Other than standard metafile ,we can only accept enhanced metafile format
+
+ if (pformatetc->cfFormat != CF_ENHMETAFILE)
+ {
+ return DV_E_CLIPFORMAT;
+ }
+
+ // The medium must be enhanced metafile
+ if (pmedium->tymed != (DWORD) TYMED_ENHMF)
+ {
+ return DV_E_TYMED;
+ }
+
+ // If no controlling unkown, and the release flag is set,
+ // it is up to us to take control of the data
+
+ if ((pmedium->pUnkForRelease == NULL) && fRelease)
+ {
+ fTakeData = TRUE;
+ }
+
+ // ChangeData will keep the data if fRelease is TRUE, else it copies
+
+ hr = ChangeData (pmedium->hEnhMetaFile, fTakeData);
+
+ // If we've taken the data, clear the TYMED
+ if (fTakeData)
+ {
+ pmedium->tymed = (DWORD) TYMED_NULL;
+ pmedium->hEnhMetaFile = NULL;
+ }
+
+ // If we are supposed to release the data, do it now
+
+ else if (fRelease)
+ {
+ ReleaseStgMedium(pmedium);
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::ChangeData (internal)
+//
+// Synopsis: Swaps the stored enhanced metafile presentation into the
+// cache node
+//
+// Arguments: [hEMF] -- the new enhanced metafile
+// [fTakeData] -- if TRUE, then delete [hEMF]
+//
+// History: dd-mmm-yy Author Comment
+// 14-May-94 DavePl Created
+//
+// Notes: If the routine fails then the object will be left with it's
+// old data. We are supposed to delete the incoming EMF when
+// fTakeData is set, even in the event of an error.
+//
+//--------------------------------------------------------------------------
+
+INTERNAL CEMfObject::ChangeData (HENHMETAFILE hEMF, BOOL fTakeData)
+{
+ VDATEHEAP();
+
+ HENHMETAFILE hNewEMF;
+ DWORD dwSize;
+ HRESULT hr = NOERROR;
+
+ // If we're not supposed to delete the metafile when we're
+ // done, we need to make a copy. Otherwise, we can just
+ // use the handle that came in.
+
+ if (!fTakeData)
+ {
+ hNewEMF = CopyEnhMetaFile(hEMF, NULL);
+ if (NULL == hNewEMF)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+
+ }
+ }
+ else
+ {
+ hNewEMF = hEMF;
+ }
+
+ // We get the size of the EMF by calling GetEnhMetaFileBits with
+ // a NULL buffer
+
+ dwSize = GetEnhMetaFileBits(hNewEMF, 0, NULL);
+ if (0 == dwSize)
+ {
+ hr = OLE_E_BLANK;
+ }
+ else
+ {
+ // We need the dimensions of the metafile, so
+ // we have to get the header.
+
+ ENHMETAHEADER emfHeader;
+ UINT result = GetEnhMetaFileHeader(hNewEMF,
+ sizeof(emfHeader),
+ &emfHeader);
+ if (0 == result)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ else
+ {
+ // If there already is an EMF presentation, kill it
+ // so we can replace it
+
+ DiscardHPRES();
+
+ // Set up our new EMF as the presentation
+
+ m_hPres = hNewEMF;
+ m_dwSize = dwSize;
+
+ m_lWidth = emfHeader.rclFrame.right -
+ emfHeader.rclFrame.left;
+ m_lHeight = emfHeader.rclFrame.bottom -
+ emfHeader.rclFrame.top;
+
+ // EMF extents are returned in physical himets,
+ // but all of the other formats are in logical
+ // himets, so we need to convert.
+
+ LONG HorzSize,
+ HorzRes,
+ VertSize,
+ VertRes,
+ LogXPels,
+ LogYPels;
+
+ HDC hdcTmp = GetDC(NULL);
+ if (hdcTmp)
+ {
+ const LONG HIMET_PER_MM = 100;
+ const LONG HIMET_PER_LINCH = 2540;
+
+ HorzSize = GetDeviceCaps(hdcTmp, HORZSIZE);
+ HorzRes = GetDeviceCaps(hdcTmp, HORZRES);
+ VertSize = GetDeviceCaps(hdcTmp, VERTSIZE);
+ VertRes = GetDeviceCaps(hdcTmp, VERTRES);
+ LogXPels = GetDeviceCaps(hdcTmp, LOGPIXELSX);
+ LogYPels = GetDeviceCaps(hdcTmp, LOGPIXELSY);
+
+ LEVERIFY( ReleaseDC(NULL, hdcTmp) );
+
+ // The GDI cannot fail the above calls, but
+ // it's a possibility that some broken driver
+ // returns a zero. Unlikely, but a division
+ // by zero is severe, so check for it...
+
+ if ( !HorzSize || !HorzRes || !VertSize ||
+ !VertRes || !LogXPels || !LogYPels)
+ {
+ Assert(0 && " A Devicecap is zero! ");
+ hr = E_FAIL;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // Convert physical himetrics to pixels
+
+ m_lWidth = MulDiv(m_lWidth, HorzRes, HorzSize);
+ m_lHeight = MulDiv(m_lHeight, VertRes, VertSize);
+ m_lWidth = m_lWidth / HIMET_PER_MM;
+ m_lHeight = m_lHeight / HIMET_PER_MM;
+
+ // Convert pixels to logical himetrics
+
+ m_lWidth =
+ MulDiv(m_lWidth, HIMET_PER_LINCH, LogXPels);
+ m_lHeight =
+ MulDiv(m_lHeight, HIMET_PER_LINCH, LogYPels);
+ }
+
+ }
+ else
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ }
+ }
+
+ if (FAILED(hr))
+ {
+ LEVERIFY( DeleteEnhMetaFile(hNewEMF) );
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::Draw
+//
+// Synopsis: Draws the stored presentation
+//
+// Arguments: [pvAspect] -- (UNUSED) the drawing aspect
+// [hicTargetDev] -- (UNUSED) the target device
+// [hdcDraw] -- hdc to draw into
+// [lprcBounds] -- bounding rectangle to draw into
+// [lprcWBounds] -- (UNUSED) bounding rectangle for the metafile
+// [pfnContinue] -- function to call while drawing
+// [dwContinue] -- parameter to [pfnContinue]
+//
+// Returns: HRESULT
+//
+// Derivation: IOlePresObj
+//
+// Algorithm: Sets the viewport and metafile boundaries, then plays
+// the metafile
+//
+// History: dd-mmm-yy Author Comment
+// 14-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CEMfObject::Draw(THIS_ void * /* UNUSED pvAspect */,
+ HDC /* UNUSED hicTargetDev */,
+ HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL /* UNUSED lprcWBounds */,
+ int (CALLBACK * pfnContinue)(DWORD),
+ DWORD dwContinue)
+{
+ VDATEHEAP();
+
+ m_error = NOERROR;
+
+ int iOldDc;
+ RECT rlBounds;
+
+ // We receive a RECTL, and must pass in a RECT. 16-bit used to
+ // manually copy the fields over, but we know that in Win32 they
+ // really are the same structure. Assert to be sure.
+
+ Assert(sizeof(RECT) == sizeof(RECTL));
+
+ Assert(lprcBounds);
+
+ // We must have an EMF handle before we can even begin
+
+ if (!M_HPRES())
+ {
+ return OLE_E_BLANK;
+ }
+
+ // Make a copy of the incoming bounding rectangle
+ memcpy(&rlBounds, lprcBounds, sizeof(RECT));
+
+ m_nRecord = EMF_RECORD_COUNT;
+
+ // Determine whether or not we are drawing into another
+ // metafile
+
+ m_fMetaDC = OleIsDcMeta (hdcDraw);
+
+ // Save the current state of the DC
+
+ if (0 == (iOldDc = SaveDC (hdcDraw)))
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ m_pfnContinue = pfnContinue;
+ m_dwContinue = dwContinue;
+
+ LEVERIFY( EnumEnhMetaFile(hdcDraw, m_hPres, EMfCallbackFuncForDraw, this, (RECT *) lprcBounds) );
+
+ LEVERIFY( RestoreDC (hdcDraw, iOldDc) );
+ return m_error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: EMfCallBackFuncForDraw
+//
+// Synopsis: callback function for drawing metafiles -- call's the caller's
+// draw method (via a passed in this pointer)
+//
+// Effects:
+//
+// Arguments: [hdc] -- the device context
+// [lpHTable] -- pointer to the MF handle table
+// [lpEMFR] -- pointer to metafile record
+// [nObj] -- number of objects
+//
+// Requires:
+//
+// Returns: non-zero to continue, zero stops the drawing
+//
+// History: dd-mmm-yy Author Comment
+// 12-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+
+int CALLBACK EMfCallbackFuncForDraw(HDC hdc,
+ HANDLETABLE FAR* lpHTable,
+ const ENHMETARECORD FAR* lpEMFR,
+ int nObj,
+ LPARAM lpobj)
+{
+ VDATEHEAP();
+
+ // Warning: this casts an LPARAM (a long) to a pointer, but
+ // it's the "approved" way of doing this...
+
+ return ((CEMfObject *) lpobj)->CallbackFuncForDraw(hdc,
+ lpHTable,
+ lpEMFR,
+ nObj,
+ lpobj);
+}
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::CallbackFuncForDraw
+//
+// Synopsis: Draws the metafile
+//
+// Effects:
+//
+// Arguments: [hdc] -- the device context
+// [lpHTable] -- pointer to the MF handle table
+// [lpEMFR] -- pointer to metafile record
+// [nObj] -- number of objects
+//
+// Requires:
+//
+// Returns: non-zero to continue, zero stops the drawing
+//
+// History: dd-mmm-yy Author Comment
+// 12-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+int CALLBACK CEMfObject::CallbackFuncForDraw(HDC hdc,
+ LPHANDLETABLE lpHTable,
+ const ENHMETARECORD * lpEMFR,
+ int nObj,
+ LPARAM /* UNUSED lpobj*/)
+{
+ // Count down the record count. When the count reaches zero,
+ // it is time to call the "continue" function
+
+ if (0 == --m_nRecord)
+ {
+ m_nRecord = EMF_RECORD_COUNT;
+
+ if (m_pfnContinue && !((*(m_pfnContinue))(m_dwContinue)))
+ {
+ m_error = E_ABORT;
+ return FALSE;
+ }
+ }
+
+ LEVERIFY( PlayEnhMetaFileRecord (hdc, lpHTable, lpEMFR, (unsigned) nObj) );
+ return TRUE;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::Load
+//
+// Synopsis: Loads an enhanced metafile object from the given stream
+//
+// Arguments: [lpstream] -- the stream from which to load
+// [fReadHeaderOnly] -- if TRUE, then only the header is
+// read
+// Returns: HRESULT
+//
+// Derivation: IOlePresObj
+//
+// History: dd-mmm-yy Author Comment
+// 12-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CEMfObject::Load(LPSTREAM lpstream, BOOL fReadHeaderOnly)
+{
+ VDATEHEAP();
+
+ DWORD dwBuf[4];
+ HRESULT hr;
+
+ /* read dwCompression, width, height, size of data */
+ hr = StRead(lpstream, dwBuf, 4*sizeof(DWORD));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ m_lWidth = (LONG) dwBuf[1];
+ m_lHeight = (LONG) dwBuf[2];
+ m_dwSize = dwBuf[3];
+
+ if (!m_dwSize || fReadHeaderOnly)
+ {
+ return NOERROR;
+ }
+
+ // Read the EMF from the stream and create a handle to it. Note
+ // that the size will be adjusted to reflect the size of the
+ // in-memory EMF, which may well differ from the the persistent
+ // form (which is a MF with an EMF embedded as a comment).
+
+ return UtGetHEMFFromEMFStm(lpstream, &m_dwSize, &m_hPres);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObjectn
+//
+// Synopsis: Saves the metafile to the given stream
+//
+// Arguments: [lpstream] -- the stream to save to
+//
+// Returns: HRESULT
+//
+// Derivation: IOlePresObj
+//
+// History: dd-mmm-yy Author Comment
+// 12-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CEMfObject::Save(LPSTREAM lpstream)
+{
+ VDATEHEAP();
+
+ HRESULT hr;
+ DWORD dwBuf[4];
+
+ DWORD dwPersistSize;
+
+ // The EMF could have been provided during this session, which would imply
+ // that the resultant size of the converted EMF has no bearing on the size
+ // of the original EMF we have been using. Thus, we must update the size
+ // for the persistent form.
+
+ // If we are a blank presentation, there's no need to calculate
+ // anything: our size is just 0
+
+ if (IsBlank() || m_hPres == NULL)
+ {
+ dwPersistSize = 0;
+ }
+ else
+ {
+ HDC hdcTemp = CreateCompatibleDC(NULL);
+ if (NULL == hdcTemp)
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ dwPersistSize = GetWinMetaFileBits(m_hPres, 0, NULL, MM_ANISOTROPIC, hdcTemp);
+ if (0 == dwPersistSize)
+ {
+ LEVERIFY( DeleteDC(hdcTemp) );
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+ Verify(DeleteDC(hdcTemp));
+ }
+
+ /* write dwCompression, width, height, size of data */
+
+ dwBuf[0] = 0L;
+ dwBuf[1] = (DWORD) m_lWidth;
+ dwBuf[2] = (DWORD) m_lHeight;
+ dwBuf[3] = dwPersistSize;
+
+ hr = StWrite(lpstream, dwBuf, sizeof(dwBuf));
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // if blank object, don't write any more; no error.
+ if (IsBlank() || m_hPres == NULL)
+ {
+ StSetSize(lpstream, 0, TRUE);
+ return NOERROR;
+ }
+
+ return UtHEMFToEMFStm(m_hPres,
+ dwPersistSize,
+ lpstream,
+ WRITE_AS_WMF);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::IsBlank
+//
+// Synopsis: Returns whether or not the enhanced metafile is blank
+//
+// Arguments: void
+//
+// Returns: TRUE/FALSE
+//
+// Derivation: IOlePresObj
+//
+// History: dd-mmm-yy Author Comment
+// 12-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+BOOL CEMfObject::IsBlank(void)
+{
+ VDATEHEAP();
+
+ return (m_dwSize ? FALSE : TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::LoadHPRES (private)
+//
+// Synopsis: Loads the presentation from the cache's stream and returns
+// a handle to it
+//
+// Returns: HANDLE to the metafile
+//
+// History: dd-mmm-yy Author Comment
+// 12-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(HENHMETAFILE) CEMfObject::LoadHPRES(void)
+{
+ VDATEHEAP();
+
+ LPSTREAM pstm = m_pCacheNode->GetStm(TRUE /*fSeekToPresBits*/,
+ STGM_READ);
+
+ if (pstm)
+ {
+ // In case ::Load() fails, NULL the handle first
+
+ m_hPres = NULL;
+ LEVERIFY( SUCCEEDED(Load(pstm, FALSE /* fHeaderOnly*/)) );
+ pstm->Release();
+ }
+
+ return m_hPres;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::DiscardHPRES
+//
+// Synopsis: deletes the stored metafile
+//
+// Derivation: IOlePresObj
+//
+// History: dd-mmm-yy Author Comment
+// 12-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+void CEMfObject::DiscardHPRES(void)
+{
+ VDATEHEAP();
+
+ if (m_hPres)
+ {
+ LEVERIFY( DeleteEnhMetaFile(m_hPres) );
+ m_hPres = NULL;
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::GetCopyOfHPRES (private)
+//
+// Synopsis: makes a copy of the enhanced metafile (if one is present),
+// otherwise just loads it from the stream (but doesn't store
+// it in [this] object)
+//
+// Arguments: void
+//
+// Returns: HENHMETAFILE to the enhanced metafile
+//
+// History: dd-mmm-yy Author Comment
+// 12-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(HENHMETAFILE) CEMfObject::GetCopyOfHPRES(void)
+{
+ VDATEHEAP();
+
+ HENHMETAFILE hPres;
+
+ // Make a copy if the presentation data is already loaded
+ if (m_hPres)
+ {
+ return CopyEnhMetaFile(m_hPres, NULL);
+ }
+
+ // Load the presentation data now and return the same handle.
+ // No need to copy the data. If the caller wants the m_hPres to be
+ // set s/he would call LoadHPRES() directly.
+
+ LEVERIFY( LoadHPRES() );
+ hPres = m_hPres; // Grab the handle from the member var
+ m_hPres = NULL; // (re-) Clear out the member var
+ return hPres;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::GetColorSet
+//
+// Synopsis: Retrieves the logical palette associated with the EMF
+//
+// Effects:
+//
+// Arguments: [pvAspect] -- the drawing aspect
+// [hicTargetDev] -- target device
+// [ppColorSet] -- where to put the logical palette pointer
+//
+// Returns: HRESULT
+//
+// Derivation: IOlePresObj
+//
+// History: dd-mmm-yy Author Comment
+// 18-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CEMfObject::GetColorSet(LPVOID /* UNUSED pvAspect */,
+ HDC /* UNUSED hicTargetDev */,
+ LPLOGPALETTE * ppColorSet)
+{
+ VDATEHEAP();
+ VDATEPTROUT(ppColorSet, LPLOGPALETTE);
+
+ m_pColorSet = *ppColorSet = NULL;
+
+ if (IsBlank() || !M_HPRES())
+ {
+ return OLE_E_BLANK;
+ }
+
+ HENHMETAFILE hEMF = M_HPRES();
+
+ // Get the count of palette entries
+
+ UINT cColors = GetEnhMetaFilePaletteEntries(hEMF, 0, NULL);
+
+ // If no palette entries, return a NULL LOGPALETTE
+
+ if (0 == cColors)
+ {
+ return S_FALSE;
+ }
+
+ // REVIEW (davepl) A quick fix until we figure out what happens, or if
+ // it is possible, for a EMF to have more than 32767 colors
+
+ LEWARN( cColors > USHRT_MAX, "EMF has more colors than LOGPALETTE allows" );
+
+ if (cColors > USHRT_MAX)
+ {
+ cColors = USHRT_MAX;
+ }
+
+ // Calculate the size of the variably-sized LOGPALLETE structure
+
+ UINT uPalSize = cColors * sizeof(PALETTEENTRY) + 2 * sizeof(WORD);
+
+ // Allocate the LOGPALETTE structure
+
+ m_pColorSet = (LPLOGPALETTE) PubMemAlloc(uPalSize);
+
+ if( NULL == m_pColorSet)
+ {
+ m_error = E_OUTOFMEMORY;
+ return FALSE;
+ }
+
+ // Get the actual color entries
+
+ m_pColorSet->palVersion = 0x300;
+ m_pColorSet->palNumEntries = (WORD) cColors;
+ UINT result = GetEnhMetaFilePaletteEntries(
+ hEMF,
+ cColors,
+ &(m_pColorSet->palPalEntry[0]));
+
+ // If it failed, clean up and bail
+
+ if (cColors != result)
+ {
+ PubMemFree(m_pColorSet);
+ m_pColorSet = NULL;
+ return HRESULT_FROM_WIN32(GDI_ERROR);
+ }
+
+ // We succeeded, so set the OUT ptr and return
+
+ *ppColorSet = m_pColorSet;
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::GetExtent
+//
+// Synopsis: Retrieves the extents of the enhanced metafile
+//
+// Arguments: [dwDrawAspect] -- the drawing aspect we're interested in
+// [lpsizel] -- where to put the extent info
+//
+// Returns: NOERROR, DV_E_DVASPECT, OLE_E_BLANK
+//
+// Derivation: IOlePresObj
+//
+// History: dd-mmm-yy Author Comment
+// 18-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CEMfObject::GetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel)
+{
+ VDATEHEAP();
+
+ if (!(dwDrawAspect & m_dwAspect))
+ {
+ return DV_E_DVASPECT;
+ }
+
+ if (IsBlank())
+ {
+ return OLE_E_BLANK;
+ }
+
+ lpsizel->cx = m_lWidth;
+ lpsizel->cy = m_lHeight;
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEMfObject::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppszDump] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CEMfObject::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszHRESULT;
+ char *pszDVASPECT;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(500);
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "No. of References = " << m_ulRefs << endl;
+
+ dstrDump << pszPrefix << "Handle Enhanced Metafile = " << m_hPres << endl;
+
+ dstrDump << pszPrefix << "IsMetaDeviceContext? = ";
+ if (m_fMetaDC == TRUE)
+ {
+ dstrDump << "TRUE" << endl;
+ }
+ else
+ {
+ dstrDump << "FALSE" << endl;
+ }
+
+ dstrDump << pszPrefix << "No. of Records in Metafile = " << m_nRecord << endl;
+
+ pszHRESULT = DumpHRESULT(m_error);
+ dstrDump << pszPrefix << "Error code = " << pszHRESULT << endl;
+ CoTaskMemFree(pszHRESULT);
+
+ dstrDump << pszPrefix << "pLOGPALETTE (Color set palette) = " << m_pColorSet << endl;
+
+ dstrDump << pszPrefix << "Continue = " << m_dwContinue << endl;
+
+ dstrDump << pszPrefix << "fp Continue = " << m_pfnContinue<< endl;
+
+ pszDVASPECT = DumpDVASPECTFlags(m_dwAspect);
+ dstrDump << pszPrefix << "Aspect flags = " << pszDVASPECT << endl;
+ CoTaskMemFree(pszDVASPECT);
+
+ dstrDump << pszPrefix << "Size = " << m_dwSize << endl;
+
+ dstrDump << pszPrefix << "Width = " << m_lWidth << endl;
+
+ dstrDump << pszPrefix << "Height = " << m_lHeight << endl;
+
+ dstrDump << pszPrefix << "pCacheNode = " << m_pCacheNode << endl;
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCEMfObject, public (_DEBUG only)
+//
+// Synopsis: calls the CEMfObject::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pEMFO] - pointer to CEMfObject
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCEMfObject(CEMfObject *pEMFO, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pEMFO == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pEMFO->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtGetHEMFFromEMFStm
+//
+// Synopsis: Reads an enhanced metafile from a stream into memory,
+// creates the enhanced metafile from the raw data, and
+// returns a handle to it.
+//
+// Arguments: [lpstream] -- stream containing the EMF
+// [dwSize] -- data size within stream
+// [fConvert] -- FALSE for metafile, TRUE for PICT
+//
+// Requires: lpstream positioned at start of data
+//
+// Returns: HRESULT
+//
+// History: 15-May-94 DavePl Created
+//
+//--------------------------------------------------------------------------
+
+FARINTERNAL UtGetHEMFFromEMFStm(LPSTREAM lpstream,
+ DWORD * pdwSize,
+ HENHMETAFILE * lphPres)
+{
+ VDATEHEAP();
+
+ BYTE *pbEMFData = NULL;
+ HRESULT hr = NOERROR;
+
+ // initialize this in case of error return
+
+ *lphPres = NULL;
+
+ // allocate a global handle for the data
+
+ pbEMFData = (BYTE *) GlobalAlloc(GMEM_FIXED, *pdwSize);
+ if (NULL == pbEMFData)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // read the stream into the bit storage
+
+ hr = StRead(lpstream, pbEMFData, *pdwSize);
+
+ if (FAILED(hr))
+ {
+ LEVERIFY( NULL == GlobalFree((HGLOBAL) pbEMFData) );
+ return hr;
+ }
+
+ // Create an in-memory EMF based on the raw bits
+
+ HDC hdcTemp = CreateCompatibleDC(NULL);
+ if (NULL == hdcTemp)
+ {
+ LEVERIFY( NULL == GlobalFree((HGLOBAL) pbEMFData) );
+ return E_FAIL;
+ }
+
+ *lphPres = SetWinMetaFileBits(*pdwSize, pbEMFData, hdcTemp, NULL);
+
+ LEVERIFY( DeleteDC(hdcTemp) );
+
+ // In any case, we can free the bit buffer
+
+ LEVERIFY( NULL == GlobalFree((HGLOBAL) pbEMFData) );
+
+ // If the SetEnhM... failed, set the error code
+
+ if (*lphPres == NULL)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ // We need to update the size of the in-memory EMF, as it
+ // could differ from out persistent MF form.
+
+ *pdwSize = GetEnhMetaFileBits(*lphPres, NULL, NULL);
+ if (0 == *pdwSize)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtHEMFToEMFStm
+//
+// Synopsis: Takes a handle to an enhanced metafile and serializes it
+// to the supplied stream. It can be serialized as either
+// a standard or enhanced metafile.
+//
+// Arguments: [lphEMF] -- ptr to the EMF handle
+// [dwSize] -- size of the EMF bits
+// [lpstream] -- the stream to write to
+// [fWriteAsWMF] -- write as WMF, not EMF
+//
+// Returns: HRESULT
+//
+// History: 15-May-94 DavePl Created
+//
+// Notes: This fn is used to serialize EMFs as MFs in the cache node
+// save case, which will allow 16-bit DLLs to read them back.
+// A EMF converted to MF contains the original EMF as an
+// embedded comment record, so no loss is taken in the
+// EMF -> MF -> EMF conversion case.
+//
+// The incoming dwSize must be large enough to accomodate the
+// WMF (w/embedded EMF) in the standard metafile save case.
+//
+//--------------------------------------------------------------------------
+
+
+FARINTERNAL UtHEMFToEMFStm(HENHMETAFILE hEMF,
+ DWORD dwSize,
+ LPSTREAM lpstream,
+ EMFWRITETYPE emfwType
+ )
+{
+ VDATEHEAP();
+
+ HRESULT hr;
+
+ Assert(emfwType == WRITE_AS_EMF || emfwType == WRITE_AS_WMF);
+
+ // If we don't have a handle, there's nothing to do.
+
+ if (hEMF == NULL)
+ {
+ return OLE_E_BLANK;
+ }
+
+ void *lpBits;
+
+ lpBits = PrivMemAlloc(dwSize);
+ if (NULL == lpBits)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ if (emfwType == WRITE_AS_WMF)
+ {
+ // WMF WRITE CASE
+
+ // Get the raw bits of the metafile that we are going to
+ // write out
+
+ HDC hdcTemp = CreateCompatibleDC(NULL);
+ if (NULL == hdcTemp)
+ {
+ hr = E_FAIL;
+ goto errRtn;
+ }
+
+ if (0 == GetWinMetaFileBits(hEMF, dwSize, (BYTE *) lpBits, MM_ANISOTROPIC, hdcTemp))
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ LEVERIFY( DeleteDC(hdcTemp) );
+ goto errRtn;
+ }
+ LEVERIFY( DeleteDC(hdcTemp) );
+
+ // write the metafile bits out to the stream
+
+ }
+ else
+ {
+ // EMF WRITE CASE
+
+ if (0 == GetEnhMetaFileBits(hEMF, dwSize, (BYTE *) lpBits))
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto errRtn;
+ }
+ }
+
+ hr = StWrite(lpstream, lpBits, dwSize);
+
+errRtn:
+
+ // free the metafile bits
+
+ PrivMemFree(lpBits);
+
+ // set the stream size
+ if (SUCCEEDED(hr))
+ {
+ hr = StSetSize(lpstream, 0, TRUE);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtGetHEMFFromContentsStm
+//
+// Synopsis: Pulls EMF data from a stream and creates a handle to
+// the resultant in-memory EMF
+//
+// Arguments: [pstm] -- the stream to read from
+// [phdata] -- the handle to create on
+//
+// Returns: (void)
+//
+// History: 10-Jul-94 DavePl Created
+//
+//
+//--------------------------------------------------------------------------
+
+void UtGetHEMFFromContentsStm(LPSTREAM pstm, HANDLE * phdata)
+{
+ *phdata = NULL;
+
+ DWORD dwSize;
+ ENHMETAHEADER * pHdr;
+
+ // Pull the size of the metafile header from the stream
+
+ if (FAILED(StRead(pstm, &dwSize, sizeof(DWORD))))
+ {
+ return;
+ }
+
+ // The header must be at least as large as the byte
+ // offset to the nBytes member of the ENHMETAHEADER struct.
+
+ if (dwSize < offsetof(ENHMETAHEADER, nBytes))
+ {
+ return;
+ }
+
+ // Allocate enough memory for the header struct
+
+ pHdr = (ENHMETAHEADER *) PrivMemAlloc(dwSize);
+ if (NULL == pHdr)
+ {
+ return;
+ }
+
+ // Read the header structure into our buffer
+
+ if (FAILED(StRead(pstm, pHdr, dwSize)))
+ {
+ PrivMemFree(pHdr);
+ return;
+ }
+
+ // All we care about in the header is the size of the
+ // metafile bits, so cache that and free the header buffer
+
+ dwSize = pHdr->nBytes;
+ PrivMemFree(pHdr);
+
+ // Allocate memory to read the raw EMF bits into
+
+ BYTE * lpBytes = (BYTE *) PrivMemAlloc(dwSize);
+ if (NULL == lpBytes)
+ {
+ return;
+ }
+
+ // Read the raw bits into the buffer...
+
+ if (FAILED(StRead(pstm, lpBytes, dwSize)))
+ {
+ PrivMemFree(lpBytes);
+ return;
+ }
+
+ // Create an in-memory EMF based on those bits
+
+ HENHMETAFILE hEmf = SetEnhMetaFileBits(dwSize, lpBytes);
+ PrivMemFree(lpBytes);
+
+ if (NULL == hEmf)
+ {
+ return;
+ }
+
+ *phdata = hEmf;
+
+ return;
+}
+
+
+
+
+
+
+
diff --git a/private/ole32/ole232/stdimpl/filelist.mk b/private/ole32/ole232/stdimpl/filelist.mk
new file mode 100644
index 000000000..d5ebe5895
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/filelist.mk
@@ -0,0 +1,57 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = stdimpl.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CPPFILES = .\defcf.cpp \
+ .\defhndlr.cpp \
+ .\deflink.cpp \
+ .\defutil.cpp \
+ .\gen.cpp \
+ .\icon.cpp \
+ .\mf.cpp \
+ .\olereg.cpp \
+ .\oregfmt.cpp \
+ .\oregverb.cpp
+
+CFILES =
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PFILE =
+
+
+!include $(CAIROLE)\ole232\ole.mk
diff --git a/private/ole32/ole232/stdimpl/gen.cpp b/private/ole32/ole232/stdimpl/gen.cpp
new file mode 100644
index 000000000..82546c92d
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/gen.cpp
@@ -0,0 +1,1908 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: gen.cpp
+//
+// Contents: Implementation of the generic picture object (CGenObject)
+// and dib routines.
+//
+// Classes: CGenObject implementation
+//
+// Functions: DibDraw (internal)
+// DibMakeLogPalette (internal)
+// DibFillPaletteEntries (internal)
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH add Dump method and DumpCGenObject API
+// 25-Jan-94 alexog first pass at converting to Cairo-style
+// memory allocations.
+// 11-Jan-94 alexgo added VDATEHEAP macros to every function
+// and method
+// 07-Dec-93 ChrisWe make default params to StSetSize explicit
+// 07-Dec-93 alexgo merged 16bit RC9 changes
+// 29-Nov-93 ChrisWe make default arguments to UtDupGlobal,
+// UtConvertBitmapToDib explicit
+// 23-Nov-93 alexgo 32bit port
+// srinik 06/04/93 Added the support for demand loading and
+// discarding the caches.
+// SriniK 03/19/1993 Deleted dib.cpp and moved DIB drawing routines
+// into this file.
+// SriniK 01/07/1993 Merged dib.cpp into gen.cpp
+//
+//--------------------------------------------------------------------------
+
+/*
+REVIEW32::: WARNING WARNING
+There are many potentially bogus pointer to Palette, etc handle conversions
+put in to make the code compile. :(
+(Gee, thanks for marking them as you went)
+*/
+
+#include <le2int.h>
+#pragma SEG(gen)
+
+#include "gen.h"
+
+#ifdef _DEBUG
+#include <dbgdump.h>
+#endif // _DEBUG
+
+ASSERTDATA
+
+#define M_HPRES() (m_hPres ? m_hPres : LoadHPRES())
+
+//local functions
+INTERNAL DibDraw(HANDLE hDib, HDC hdc, LPCRECTL lprc);
+INTERNAL_(HANDLE) DibMakeLogPalette (BYTE FAR *lpColorData,
+ WORD wDataSize,
+ LPLOGPALETTE FAR* lplpLogPalette);
+INTERNAL_(void) DibFillPaletteEntries(BYTE FAR *lpColorData,
+ WORD wDataSize, LPLOGPALETTE lpLogPalette);
+
+
+
+/*
+ * IMPLEMENTATION of CGenObject
+ *
+ */
+
+NAME_SEG(Gen)
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::CGenObject
+//
+// Synopsis: Constructor
+//
+// Effects:
+//
+// Arguments: [pCacheNode] -- cache for the object
+// [cfFormat] -- clipboard format of the object
+// [dwAspect] -- drawing aspect of the object
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: just initializes member variables
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CGenObject_ctor)
+CGenObject::CGenObject(LPCACHENODE pCacheNode, CLIPFORMAT cfFormat,
+ DWORD dwAspect)
+{
+ VDATEHEAP();
+
+ m_ulRefs = 1;
+ m_dwSize = NULL;
+ m_lWidth = NULL;
+ m_lHeight = NULL;
+ m_hPres = NULL;
+ m_cfFormat = cfFormat;
+ m_dwAspect = dwAspect;
+ m_pCacheNode = pCacheNode;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::~CGenObject
+//
+// Synopsis: Destructor
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CGenObject_dtor)
+CGenObject::~CGenObject(void)
+{
+ VDATEHEAP();
+
+ if (m_hPres)
+ {
+ LEVERIFY( NULL == GlobalFree (m_hPres));
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::QueryInterface
+//
+// Synopsis: returns interfaces on the generic picture object
+//
+// Effects:
+//
+// Arguments: [iid] -- the requested interface ID
+// [ppvObj] -- where to put the interface pointer
+//
+// Requires:
+//
+// Returns: NOERROR, E_NOINTERFACE
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IUnkown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CGenObject_QueryInterface)
+STDMETHODIMP CGenObject::QueryInterface (REFIID iid, void FAR* FAR* ppvObj)
+{
+ VDATEHEAP();
+
+ if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IOlePresObj))
+ {
+ *ppvObj = this;
+ AddRef();
+ return NOERROR;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ return ResultFromScode(E_NOINTERFACE);
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::AddRef
+//
+// Synopsis: increments the reference count
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IUnknown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CGenObject_AddRef)
+STDMETHODIMP_(ULONG) CGenObject::AddRef(void)
+{
+ VDATEHEAP();
+
+ return ++m_ulRefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::Release
+//
+// Synopsis: Decrements the reference count
+//
+// Effects: may delete [this] object
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IUnknown
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CGenObject_Release)
+STDMETHODIMP_(ULONG) CGenObject::Release(void)
+{
+ VDATEHEAP();
+
+ if (--m_ulRefs == 0)
+ {
+ delete this;
+ return 0;
+ }
+
+ return m_ulRefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::GetData
+//
+// Synopsis: retrieves data of the specified format
+//
+// Effects:
+//
+// Arguments: [pformatetcIn] -- the requested data format
+// [pmedium] -- where to put the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObject
+//
+// Algorithm: If available, copies the presentation to pmedium
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CGenObject_GetData)
+STDMETHODIMP CGenObject::GetData
+ (LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
+{
+ VDATEHEAP();
+
+ SCODE sc;
+
+ if (IsBlank())
+ {
+ sc = OLE_E_BLANK;
+ }
+ else if (pformatetcIn->cfFormat != m_cfFormat)
+ {
+
+ if (m_cfFormat == CF_DIB &&
+ pformatetcIn->cfFormat == CF_BITMAP)
+ {
+ return GetBitmapData(pformatetcIn, pmedium);
+ }
+ else
+ {
+ sc = DV_E_CLIPFORMAT;
+ }
+ }
+ else if (0 == (pformatetcIn->tymed & TYMED_HGLOBAL))
+ {
+ sc = DV_E_TYMED;
+ }
+ else
+ {
+ if (NULL == (pmedium->hGlobal = GetCopyOfHPRES()))
+ {
+ sc = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ pmedium->tymed = TYMED_HGLOBAL;
+ return NOERROR;
+ }
+
+errRtn:
+ // null out in case of error
+ pmedium->tymed = TYMED_NULL;
+ pmedium->pUnkForRelease = NULL;
+ return ResultFromScode(sc);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::GetDataHere
+//
+// Synopsis: retrieves presentation data into the given pmedium
+//
+// Effects:
+//
+// Arguments: [pformatetcIn] -- the requested data format
+// [pmedium] -- where to put the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm: copies presentation data into the given storage medium
+// after error checking on the arguments
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CGenObject_GetDataHere)
+STDMETHODIMP CGenObject::GetDataHere
+ (LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
+{
+ VDATEHEAP();
+
+ SCODE scode = S_OK;
+
+ if (pformatetcIn->cfFormat != m_cfFormat)
+ {
+ scode = DV_E_CLIPFORMAT;
+ }
+ else if (pmedium->tymed != TYMED_HGLOBAL
+ && pmedium->tymed != TYMED_ISTREAM)
+ {
+ scode = DV_E_TYMED;
+ }
+ else if (pmedium->hGlobal == NULL)
+ {
+ scode = E_INVALIDARG;
+ }
+ else if (IsBlank())
+ {
+ scode = OLE_E_BLANK;
+ }
+ else // actually get the data now
+ {
+ if (pmedium->tymed == TYMED_HGLOBAL)
+ {
+ // check the size of the given pmedium and then
+ // copy the data into it
+ LPVOID lpsrc = NULL;
+ LPVOID lpdst = NULL;
+ DWORD dwSizeDst;
+
+ scode = E_OUTOFMEMORY;
+
+ if (0 == (dwSizeDst = GlobalSize(pmedium->hGlobal)))
+ {
+ goto errRtn;
+ }
+
+ // not enough room to copy
+ if (dwSizeDst < m_dwSize)
+ {
+ goto errRtn;
+ }
+
+ if (NULL == (lpdst = (LPVOID) GlobalLock(pmedium->hGlobal)))
+ {
+ goto errRtn;
+ }
+
+ if (NULL == (lpsrc = (LPVOID) GlobalLock(M_HPRES())))
+ {
+ goto errMem;
+ }
+
+ _xmemcpy(lpdst, lpsrc, m_dwSize);
+ scode = S_OK;
+
+ errMem:
+ if (lpdst)
+ {
+ GlobalUnlock(pmedium->hGlobal);
+ }
+ if (lpsrc)
+ {
+ GlobalUnlock(m_hPres);
+ }
+
+ }
+ else
+ {
+ Assert(pmedium->tymed == TYMED_ISTREAM);
+ if (m_cfFormat == CF_DIB)
+ {
+ return UtHDIBToDIBFileStm(M_HPRES(),
+ m_dwSize,pmedium->pstm);
+ }
+ else
+ {
+ return UtHGLOBALtoStm(M_HPRES(),
+ m_dwSize, pmedium->pstm);
+ }
+ }
+ }
+
+errRtn:
+ return ResultFromScode(scode);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::SetDataWDO
+//
+// Synopsis: Takes the given presentation data and stores it
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- the format of the data
+// [pmedium] -- the new presentation data
+// [fRelease] -- if TRUE, then we keep the data, else
+// we keep a copy
+// [pDataObj] -- pointer to the IDataObject, may be NULL
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CGenObject::SetDataWDO
+ (LPFORMATETC pformatetc, LPSTGMEDIUM pmedium, BOOL fRelease, IDataObject * pDataObj)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ BOOL fTakeData = FALSE;
+
+ if (pformatetc->cfFormat != m_cfFormat)
+ {
+ if (m_cfFormat == CF_DIB && pformatetc->cfFormat == CF_BITMAP)
+ {
+ return SetBitmapData(pformatetc, pmedium, fRelease, pDataObj);
+ }
+ else
+ {
+ return ResultFromScode(DV_E_CLIPFORMAT);
+ }
+ }
+
+
+ if (pmedium->tymed != TYMED_HGLOBAL)
+ {
+ return ResultFromScode(DV_E_TYMED);
+ }
+
+ if ((pmedium->pUnkForRelease == NULL) && fRelease)
+ {
+ // we can take the ownership of the data
+ fTakeData = TRUE;
+ }
+
+ // ChangeData will keep the data if fRelease is TRUE, else it copies
+ error = ChangeData (pmedium->hGlobal, fTakeData);
+
+ if (fTakeData)
+ {
+ pmedium->tymed = TYMED_NULL;
+ }
+ else if (fRelease)
+ {
+ ReleaseStgMedium(pmedium);
+ }
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::ChangeData (private)
+//
+// Synopsis: Replaces the stored presentation
+//
+// Effects:
+//
+// Arguments: [hNewData] -- the new presentation
+// [fDelete] -- if TRUE, then free hNewData
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+// Notes:
+//
+// If the routine fails then the object will be left with it's old data.
+// In case of failure if fDelete is TRUE, then hNewData will be freed.
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CGenObject_ChangeData)
+INTERNAL CGenObject::ChangeData (HANDLE hNewData, BOOL fDelete)
+{
+ VDATEHEAP();
+
+ HRESULT hresult = ResultFromScode(E_OUTOFMEMORY);
+
+ if (!hNewData)
+ {
+ return ResultFromScode(OLE_E_BLANK);
+ }
+
+ if (!fDelete)
+ {
+ if (NULL == (hNewData = UtDupGlobal(hNewData, GMEM_MOVEABLE)))
+ {
+ return hresult;
+ }
+ }
+ else
+ {
+ HANDLE hTmp;
+
+ // change the ownership to yourself
+
+ hTmp = GlobalReAlloc (hNewData, 0L, GMEM_MODIFY|GMEM_SHARE);
+ if (NULL == hTmp)
+ {
+ if (NULL == (hTmp = UtDupGlobal(hNewData, GMEM_MOVEABLE)))
+ {
+ goto errRtn;
+ }
+
+ // Realloc failed but copying succeeded. Since this is fDelete
+ // case, free the source global handle.
+ LEVERIFY( NULL == GlobalFree(hNewData));
+ }
+
+ hNewData = hTmp;
+ }
+
+#ifndef _MAC
+
+ // CF_DIB format specific code. Get the it's extents
+ if (m_cfFormat == CF_DIB)
+ {
+ LPBITMAPINFOHEADER lpBi;
+
+ if (NULL == (lpBi = (LPBITMAPINFOHEADER) GlobalLock (hNewData)))
+ {
+ goto errRtn;
+ }
+
+ UtGetDibExtents (lpBi, &m_lWidth, &m_lHeight);
+ GlobalUnlock (hNewData);
+ }
+
+#endif
+
+ // free the old presentation
+ if (m_hPres)
+ {
+ LEVERIFY( NULL == GlobalFree (m_hPres));
+ }
+
+ // store the new presentation in m_hPres
+ m_dwSize = GlobalSize (m_hPres = hNewData);
+
+ return NOERROR;
+
+errRtn:
+ if (hNewData && fDelete)
+ {
+ LEVERIFY( NULL == GlobalFree (hNewData));
+ }
+
+ return hresult;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::Draw
+//
+// Synopsis: Calls DibDraw to draw the stored bitmap presentation
+//
+// Effects:
+//
+// Arguments: [pvAspect] -- drawing aspect
+// [hicTargetDev] -- the target device
+// [hdcDraw] -- the device context
+// [lprcBounds] -- drawing boundary
+// [lprcWBounds] -- boundary rectangle for metafiles
+// [pfnContinue] -- callback function to periodically call
+// for long drawing operations
+// [dwContinue] -- argument to be passed to pfnContinue
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CGenObject_Draw)
+STDMETHODIMP CGenObject::Draw(void * /* UNUSED pvAspect */,
+ HDC /* UNUSED hicTargetDev */,
+ HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL /* UNUSED lprcWBounds */,
+ BOOL (CALLBACK * /*UNUSED pfcCont*/)(DWORD),
+ DWORD /* UNUSED dwContinue */)
+{
+ VDATEHEAP();
+
+#ifndef _MAC
+ if (m_cfFormat == CF_DIB)
+ {
+ return DibDraw (M_HPRES(), hdcDraw,lprcBounds);
+ }
+#endif
+
+ return ResultFromScode(E_NOTIMPL);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::Load
+//
+// Synopsis: Loads a stored presentation object from the given stream
+//
+// Effects:
+//
+// Arguments: [lpstream] -- the stream from which to load
+// [fReadHeaderOnly] -- if TRUE, only get header info
+// (such as size, width, height, etc)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CGenObject::Load(LPSTREAM lpstream, BOOL fReadHeaderOnly)
+{
+ VDATEHEAP();
+
+ DWORD dwBuf[4];
+ HRESULT error;
+
+ /* read dwCompression, width, height, size of data */
+ error = StRead(lpstream, dwBuf, 4 * sizeof(DWORD));
+ if (error)
+ {
+ return error;
+ }
+
+ // we don't allow for compression yet
+ AssertSz (dwBuf[0] == 0, "Picture compression factor is non-zero");
+
+ m_lWidth = (LONG) dwBuf[1];
+ m_lHeight = (LONG) dwBuf[2];
+ m_dwSize = dwBuf[3];
+
+
+ if (!m_dwSize || fReadHeaderOnly)
+ {
+ return NOERROR;
+ }
+
+ return UtGetHGLOBALFromStm(lpstream, m_dwSize, &m_hPres);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::Save
+//
+// Synopsis: Stores presentation data to the given stream
+//
+// Effects:
+//
+// Arguments: [lpstream] -- where to store the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CGenObject::Save(LPSTREAM lpstream)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ DWORD dwBuf[4];
+
+ /* write dwCompression, width, height, size of data */
+
+ dwBuf[0] = 0L;
+ dwBuf[1] = (DWORD) m_lWidth;
+ dwBuf[2] = (DWORD) m_lHeight;
+ dwBuf[3] = m_dwSize;
+
+ error = StWrite(lpstream, dwBuf, 4*sizeof(DWORD));
+ if (error)
+ {
+ return error;
+ }
+
+ // if we're blank or don't have any presentation data, then
+ // nothing to else to save.
+ if (IsBlank() || m_hPres == NULL)
+ {
+ StSetSize(lpstream, 0, TRUE);
+ return NOERROR;
+ }
+
+ return UtHGLOBALtoStm(m_hPres, m_dwSize, lpstream);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::GetExtent
+//
+// Synopsis: retrieves the size (width/height) of the presentation bitmap
+//
+// Effects:
+//
+// Arguments: [dwDrawAspect] -- the drawing aspect the caller is
+// interested in
+// [lpsizel] -- where to put the size extents
+//
+// Requires:
+//
+// Returns: HRESULT (NOERROR, DV_E_DVASPECT, OLE_E_BLANK)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm: retrieves the stored dimensions
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CGenObject_GetExtent)
+STDMETHODIMP CGenObject::GetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel)
+{
+ VDATEHEAP();
+
+ // aspects must match
+ if (!(dwDrawAspect & m_dwAspect))
+ {
+ return ResultFromScode(DV_E_DVASPECT);
+ }
+
+ if (IsBlank())
+ {
+ return ResultFromScode(OLE_E_BLANK);
+ }
+
+ lpsizel->cx = m_lWidth;
+ lpsizel->cy = m_lHeight;
+
+ if (lpsizel->cx || lpsizel->cy)
+ {
+ return NOERROR;
+ }
+ else
+ {
+ return ResultFromScode(OLE_E_BLANK);
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::GetColorSet
+//
+// Synopsis: Retrieves the pallette associated with the bitmap
+//
+// Effects:
+//
+// Arguments: [pvAspect] -- the drawing aspect (unused)
+// [hicTargetDev] -- the target device (unused)
+// [ppColorSet] -- where to put the new palette
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm: Allocates a new pallette and copies the bitmap
+// palette into it.
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port, fixed bad memory bugs
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CGenObject::GetColorSet(LPVOID /* UNUSED pvAspect */,
+ HDC /* UNUSED hicTargetDev */,
+ LPLOGPALETTE * ppColorSet)
+{
+ VDATEHEAP();
+
+ HRESULT hresult = ResultFromScode(S_FALSE);
+
+ if (m_cfFormat == CF_DIB)
+ {
+ if (IsBlank())
+ {
+ return ResultFromScode(OLE_E_BLANK);
+ }
+
+ LPBITMAPINFOHEADER lpbmih;
+ LPLOGPALETTE lpLogpal;
+ WORD wPalSize;
+
+ if (NULL == (lpbmih = (LPBITMAPINFOHEADER) GlobalLock (M_HPRES())))
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // A bitmap with more than 8 bpp cannot have a palette at all,
+ // so we just return S_FALSE
+
+ if (lpbmih->biBitCount > 8)
+ {
+ goto errRtn;
+ }
+
+ // Note: the return from UtPaletteSize can overflow the WORD
+ // wPalSize, but utPaletteSize asserts against this
+
+ if (0 == (wPalSize = (WORD) UtPaletteSize(lpbmih)))
+ {
+ goto errRtn;
+ }
+
+ lpLogpal = (LPLOGPALETTE)PubMemAlloc(wPalSize +
+ 2*sizeof(WORD));
+ if (lpLogpal == NULL)
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ DibFillPaletteEntries((BYTE FAR *)++lpbmih, wPalSize, lpLogpal);
+ *ppColorSet = lpLogpal;
+ hresult = NOERROR;
+
+ errRtn:
+ GlobalUnlock(m_hPres);
+ return hresult;
+ }
+
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::IsBlank
+//
+// Synopsis: returns TRUE if the presentation is blank
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: TRUE/FALSE
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObject
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CGenObject_IsBlank)
+STDMETHODIMP_(BOOL) CGenObject::IsBlank(void)
+{
+ VDATEHEAP();
+
+ return (m_dwSize ? FALSE : TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::LoadHPRES (private)
+//
+// Synopsis: Loads the presentation from the internal cache's stream
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HANDLE (to the presentation)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(HANDLE) CGenObject::LoadHPRES()
+{
+ VDATEHEAP();
+
+ LPSTREAM pstm;
+
+ pstm = m_pCacheNode->GetStm(TRUE /*fSeekToPresBits*/, STGM_READ);
+ if (pstm)
+ {
+ LEVERIFY( SUCCEEDED(Load(pstm)));
+ pstm->Release();
+ }
+
+ return m_hPres;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::DiscardHPRES
+//
+// Synopsis: Deletes the object's presentation
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CGenObject::DiscardHPRES(void)
+{
+ VDATEHEAP();
+
+ if (m_hPres)
+ {
+ LEVERIFY( NULL == GlobalFree(m_hPres));
+ m_hPres = NULL;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::GetCopyOfHPRES (private)
+//
+// Synopsis: Returns a handle to a copy of the presentation data
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HANDLE
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: makes a copy of m_hPres if not NULL, otherwise loads it
+// from the stream (without setting m_hPres)
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(HANDLE) CGenObject::GetCopyOfHPRES()
+{
+ VDATEHEAP();
+
+ HANDLE hPres;
+
+ // Make a copy if the presentation data is already loaded
+ if (m_hPres)
+ {
+ return(UtDupGlobal(m_hPres, GMEM_MOVEABLE));
+ }
+
+ // Load the presentation data now and return the same handle.
+ // No need to copy the data. If the caller wants the m_hPres to be
+ // set he would call LoadHPRES() directly.
+
+ hPres = LoadHPRES();
+ m_hPres = NULL;
+ return hPres;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::GetBitmapData (private)
+//
+// Synopsis: Gets bitmap data from a dib
+//
+// Effects:
+//
+// Arguments: [pformatetcIn] -- the requested format
+// [pmedium] -- where to put the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: checks the parameters, then calls UtConvertDibtoBitmap
+// to get raw bitmap data from the device-independent bitmap
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+#ifndef _MAC
+
+#pragma SEG(CGenObject_GetBitmapData)
+INTERNAL CGenObject::GetBitmapData
+ (LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
+{
+ VDATEHEAP();
+
+ SCODE sc = E_OUTOFMEMORY;
+
+ if (0 == (pformatetcIn->tymed & TYMED_GDI))
+ {
+ sc = DV_E_TYMED;
+ }
+
+ pmedium->pUnkForRelease = NULL;
+
+ pmedium->hGlobal = UtConvertDibToBitmap(M_HPRES());
+
+ // if pmedium->hGlobal is not NULL, then UtConvertDibToBitmap succeeded
+ // so the tymed needs to be set appropriately, and the return value
+ // changed to S_OK.
+ if (NULL != pmedium->hGlobal)
+ {
+ pmedium->tymed = TYMED_GDI;
+ sc = S_OK;
+ }
+ else
+ {
+ pmedium->tymed = TYMED_NULL;
+ }
+
+ return ResultFromScode(sc);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::SetBitmapData (private)
+//
+// Synopsis: Converts bitmap data to a dib and stores it in [this]
+// presenatation object
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- the format of the data
+// [pmedium] -- the data
+// [fRelease] -- if TRUE, then pmedium will be free'd
+//
+// Returns: HRESULT
+//
+// Algorithm: calls UtConvertBitmapToDib and stores the result
+//
+// History: dd-mmm-yy Author Comment
+// 07-Jul-94 DavePl Added CF_PALETTE support
+//
+// Notes: if [fRelease] == TRUE, then [pmedium] is released, even
+// if a dib could not be built
+//
+//--------------------------------------------------------------------------
+
+INTERNAL CGenObject::SetBitmapData(LPFORMATETC pformatetc,
+ STGMEDIUM * pmedium,
+ BOOL fRelease,
+ IDataObject * pDataObject)
+{
+ VDATEHEAP();
+
+ HGLOBAL hDib;
+
+ if (pmedium->tymed != TYMED_GDI)
+ {
+ return ResultFromScode(DV_E_TYMED);
+ }
+
+ // If we have a data object and if we can get the palette from it,
+ // use that to do the bitmap -> dib conversion. Otherwise, just
+ // pass a NULL palette along and the default one will be used
+
+ STGMEDIUM stgmPalette;
+ FORMATETC fetcPalette = {
+ CF_PALETTE,
+ NULL,
+ pformatetc->dwAspect,
+ DEF_LINDEX,
+ TYMED_GDI
+ };
+
+
+ if (pDataObject && SUCCEEDED(pDataObject->GetData(&fetcPalette, &stgmPalette)))
+ {
+ hDib = UtConvertBitmapToDib((HBITMAP)pmedium->hGlobal,
+ (HPALETTE) stgmPalette.hGlobal);
+ ReleaseStgMedium(&stgmPalette);
+ }
+ else
+ {
+ hDib = UtConvertBitmapToDib((HBITMAP)pmedium->hGlobal, NULL);
+ }
+
+ if (fRelease)
+ {
+ ReleaseStgMedium(pmedium);
+ }
+
+ if (!hDib)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ FORMATETC foretcTmp = *pformatetc;
+ STGMEDIUM pmedTmp = *pmedium;
+
+ foretcTmp.cfFormat = CF_DIB;
+ foretcTmp.tymed = TYMED_HGLOBAL;
+
+ pmedTmp.pUnkForRelease = NULL;
+ pmedTmp.tymed = TYMED_HGLOBAL;
+ pmedTmp.hGlobal = hDib;
+
+ // Now that we have converted the bitmap data to DIB,
+ // SetData _back_ on ourselves again with the DIB info
+
+ return SetDataWDO(&foretcTmp, &pmedTmp, TRUE, NULL);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGenObject::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppszDump] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CGenObject::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszDVASPECT;
+ char *pszCLIPFORMAT;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(500);
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "No. of References = " << m_ulRefs << endl;
+
+ pszDVASPECT = DumpDVASPECTFlags(m_dwAspect);
+ dstrDump << pszPrefix << "Aspect flags = " << pszDVASPECT << endl;
+ CoTaskMemFree(pszDVASPECT);
+
+ dstrDump << pszPrefix << "Size = " << m_dwSize << endl;
+
+ dstrDump << pszPrefix << "Width = " << m_lWidth << endl;
+
+ dstrDump << pszPrefix << "Height = " << m_lHeight << endl;
+
+ dstrDump << pszPrefix << "Presentation Handle = " << m_hPres << endl;
+
+ pszCLIPFORMAT = DumpCLIPFORMAT(m_cfFormat);
+ dstrDump << pszPrefix << "Clip Format = " << pszCLIPFORMAT << endl;
+ CoTaskMemFree(pszCLIPFORMAT);
+
+ dstrDump << pszPrefix << "pCacheNode = " << m_pCacheNode << endl;
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCGenObject, public (_DEBUG only)
+//
+// Synopsis: calls the CGenObject::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pGO] - pointer to CGenObject
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCGenObject(CGenObject *pGO, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pGO == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pGO->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DibDraw
+//
+// Synopsis: Draws a device independent bitmap
+//
+// Effects:
+//
+// Arguments: [hDib] -- the bitmap
+// [hdc] -- the device context
+// [lprc] -- the bounding rectangle
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Sets the palette to the palette in the dib, sizes and draws
+// the dib to the bounding rectangle. The original palette
+// is then restored
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+// 07-Dec-93 alexgo merged RC9 16bit changes. The
+// error-handling code used to reset the
+// old palette and then RealizePalette.
+// The call to RealizePalette was removed
+// 11-May-94 davepl Added support for BITMAPCOREINFO dibs
+// 17-Jul-94 davepl Added 12, 32 bpp support
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL DibDraw (HANDLE hDib, HDC hdc, LPCRECTL lprc)
+{
+ VDATEHEAP();
+
+ HRESULT error = ResultFromScode(E_DRAW);
+ BYTE FAR * lpDib;
+ HANDLE hPalette = NULL;
+ HPALETTE hLogPalette = NULL,
+ hOldPalette = NULL;
+ LPLOGPALETTE lpLogPalette;
+ WORD wPalSize;
+ DWORD cbHeaderSize;
+ BOOL fNeedPalette = FALSE;
+ WORD iHeight;
+ WORD iWidth;
+ int iOffBits;
+ BITMAPINFO * pbi = NULL;
+ BOOL fWeAllocd = FALSE;
+
+ if (NULL == hDib)
+ {
+ return ResultFromScode(OLE_E_BLANK);
+ }
+
+ Assert(lprc);
+
+ if (NULL == (lpDib = (BYTE FAR *) GlobalLock (hDib)))
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // The bitmap header could be BITMAPINFOHEADER or
+ // BITMAPCOREHEADER. Set our cbHeaderSize flag
+ // based on the header type. We can then calculate the
+ // palette size and the offset to the raw data bits. If
+ // we don't recognize either one of the structures here,
+ // we bail; the data is likely corrupt.
+
+ // Just a thought here: could be dangerous if the struct
+ // is not LONG aligned and this is run on an Alpha. As far
+ // as I've been able to find out, they always are long
+ // aligned
+
+ cbHeaderSize = *((ULONG *) lpDib);
+ LEWARN( cbHeaderSize > 500, "Struct size > 500, likely invalid!");
+
+ if (cbHeaderSize == sizeof(BITMAPINFOHEADER))
+ {
+ // Note: this assignment can overflow the WORD wPalSize,
+ // but the UtPaletteSize function asserts against this
+
+ wPalSize = (WORD) UtPaletteSize((LPBITMAPINFOHEADER)lpDib);
+
+ iWidth = (WORD) ((LPBITMAPINFOHEADER)lpDib)->biWidth;
+ iHeight = (WORD) ((LPBITMAPINFOHEADER)lpDib)->biHeight;
+ pbi = (LPBITMAPINFO) lpDib;
+ iOffBits = wPalSize + sizeof(BITMAPINFOHEADER);
+ }
+ else if (cbHeaderSize == sizeof(BITMAPCOREHEADER))
+ {
+
+// Since the clipboard itself does not support COREINFO
+// bitmaps, we will not support them in the presentation
+// cache. When (if) windows adds complete support for
+// these, the code is here and ready.
+
+#ifndef CACHE_SUPPORT_COREINFO
+ error = DV_E_TYMED;
+ goto errRtn;
+#else
+
+ // BUGBUG Special case 32 bpp bitmaps
+
+ // If we have a palette, we need to calculate its size and
+ // allocate enough memory for the palette entries (remember
+ // we get one entry for free with the BITMAPINFO struct, so
+ // less one). If we don't have a palette, we only need to
+ // allocate enough for the BITMAPINFO struct itself.
+
+ // Bitmaps with more than 64K colors lack a palette; they
+ // use direct RGB entries in the pixels
+
+ if ((((LPBITMAPCOREHEADER)lpDib)->bcBitCount) > 16)
+ {
+ wPalSize = 0;
+ pbi = (BITMAPINFO *) PrivMemAlloc(sizeof(BITMAPINFO));
+ }
+ else
+ {
+ wPalSize = sizeof(RGBQUAD) *
+ (1 << (((LPBITMAPCOREHEADER)lpDib)->bcBitCount));
+ pbi = (BITMAPINFO *) PrivMemAlloc(sizeof(BITMAPINFO)
+ + wPalSize - sizeof(RGBQUAD));
+ }
+
+ if (NULL == pbi)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+ else
+ {
+ fWeAllocd = TRUE;
+ }
+
+
+ // Grab the width and height
+ iWidth = ((LPBITMAPCOREHEADER)lpDib)->bcWidth;
+ iHeight = ((LPBITMAPCOREHEADER)lpDib)->bcHeight;
+
+ // Clear all the fields. Don't worry about color table, as if
+ // it exists we will set the entries explicitly.
+
+ memset(pbi, 0, sizeof(BITMAPINFOHEADER));
+
+ // Transfer what fields we do have from the COREINFO
+
+ pbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbi->bmiHeader.biWidth = iWidth;
+ pbi->bmiHeader.biHeight = iHeight;
+ pbi->bmiHeader.biPlanes = 1;
+ pbi->bmiHeader.biBitCount = ((LPBITMAPCOREHEADER)lpDib)->bcBitCount;
+
+ // Set up the color palette, if required.
+ // Note that we must translate from RGBTRIPLE entries to
+ // RGBQUAD.
+
+ for (WORD c = 0; c < wPalSize / sizeof(RGBQUAD); c++)
+ {
+ pbi->bmiColors[c].rgbRed = ((BITMAPCOREINFO *)lpDib)->bmciColors[c].rgbtRed;
+ pbi->bmiColors[c].rgbBlue = ((BITMAPCOREINFO *)lpDib)->bmciColors[c].rgbtBlue;
+ pbi->bmiColors[c].rgbGreen = ((BITMAPCOREINFO *)lpDib)->bmciColors[c].rgbtGreen;
+ pbi->bmiColors[c].rgbReserved = 0;
+ }
+
+ iOffBits = wPalSize + sizeof(BITMAPCOREHEADER);
+#endif
+ }
+ else
+ {
+ error = E_FAIL;
+ goto errRtn;
+ }
+
+ // if color info exists, create a palette from the data and select it
+ // images with < 16 bpp do not have a palette from which we can create
+ // a logical palette
+
+ fNeedPalette = ((LPBITMAPINFOHEADER)lpDib)->biBitCount < 16;
+ if (wPalSize && fNeedPalette)
+ {
+ hLogPalette = (HPALETTE)DibMakeLogPalette(lpDib + cbHeaderSize,
+ wPalSize,
+ &lpLogPalette);
+ if (NULL == hLogPalette)
+ {
+ error = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+
+ if (NULL == (hPalette = CreatePalette (lpLogPalette)))
+ {
+ goto errRtn;
+ }
+
+ // we're done with lpLogPalette now, so unlock it
+ // (DibMakeLogPalette got the pointer via a GlobalLock)
+
+ GlobalUnlock(hLogPalette);
+
+ // select as a background palette
+ hOldPalette = SelectPalette (hdc, (HPALETTE)hPalette, TRUE);
+ if (NULL == hOldPalette)
+ {
+ goto errRtn;
+ }
+
+ LEVERIFY( 0 < RealizePalette(hdc) );
+ }
+
+
+ // size the dib to fit our drawing rectangle and draw it
+
+ if (!StretchDIBits( hdc, // HDC
+ lprc->left, // XDest
+ lprc->top, // YDest
+ lprc->right - lprc->left, // nDestWidth
+ lprc->bottom - lprc->top, // nDestHeight
+ 0, // XSrc
+ 0, // YSrc
+ iWidth, // nSrcWidth
+ iHeight, // nSrcHeight
+ lpDib + iOffBits, // lpBits
+ pbi, // lpBitsInfo
+ DIB_RGB_COLORS, // iUsage
+ SRCCOPY // dwRop
+ )
+ )
+ {
+ error = ResultFromScode(E_DRAW);
+ }
+ else
+ {
+ error = NOERROR;
+ }
+
+errRtn:
+
+ // We only want to free the header if it is was one which we allocated,
+ // which can only happen when we were give a core header type in the
+ // first place
+
+ if (fWeAllocd)
+ {
+ PrivMemFree(pbi);
+ }
+
+ if (lpDib)
+ {
+ GlobalUnlock (hDib);
+ }
+
+ // if color palette exists do the following
+ if (fNeedPalette)
+ {
+ hOldPalette = (HPALETTE)(OleIsDcMeta (hdc) ?
+ GetStockObject(DEFAULT_PALETTE)
+ : (HPALETTE)hOldPalette);
+
+ if (hOldPalette)
+ {
+ LEVERIFY( SelectPalette (hdc, hOldPalette, TRUE) );
+ // BUGBUG: Do we need to realize the palette?
+ }
+
+ if (hPalette)
+ {
+ LEVERIFY( DeleteObject (hPalette) );
+ }
+
+ if (hLogPalette)
+ {
+ LEVERIFY( NULL == GlobalFree (hLogPalette) );
+ }
+ }
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DibMakeLogPalette
+//
+// Synopsis: Makes a logical palette from a byte array of color info
+//
+// Effects:
+//
+// Arguments: [lpColorData] -- the color data
+// [wDataSize] -- size of the data
+// [lplpLogPalette] -- where to put a pointer to the
+//
+// Requires:
+//
+// Returns: HANDLE to the logical palette (must be global unlock'ed
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes: GlobalUnlock *must* be called on the returned handle to
+// avoid a memory leak (*lplpLogPalette is the result
+// of a global lock on the handle)
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(DibMakeLogPalette)
+INTERNAL_(HANDLE) DibMakeLogPalette(
+ BYTE FAR * lpColorData, WORD wDataSize,
+ LPLOGPALETTE FAR *lplpLogPalette)
+{
+ VDATEHEAP();
+
+ HANDLE hLogPalette=NULL;
+ LPLOGPALETTE lpLogPalette;
+ DWORD dwLogPalSize = wDataSize + 2 * sizeof(WORD);
+
+ if (NULL == (hLogPalette = GlobalAlloc(GMEM_MOVEABLE, dwLogPalSize)))
+ {
+ return NULL;
+ }
+
+ if (NULL == (lpLogPalette = (LPLOGPALETTE) GlobalLock (hLogPalette)))
+ {
+ LEVERIFY( NULL == GlobalFree (hLogPalette));
+ return NULL;
+ }
+
+ // BUGBUG What kind of garbage is this?
+ // We unlock the handle and return the pointer?
+
+ GlobalUnlock (hLogPalette);
+ *lplpLogPalette = lpLogPalette;
+ DibFillPaletteEntries(lpColorData, wDataSize, lpLogPalette);
+ return hLogPalette;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DibFillPaletteEntries
+//
+// Synopsis: Fills the logical palette with the color info in [lpColorData]
+//
+// Effects:
+//
+// Arguments: [lpColorData] -- the color info
+// [wDataSize] -- the size of the color info
+// [lpLogPalette] -- the logical palette
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) DibFillPaletteEntries(
+ BYTE FAR * lpColorData, WORD wDataSize, LPLOGPALETTE lpLogPalette)
+{
+ VDATEHEAP();
+
+ LPPALETTEENTRY lpPE;
+ RGBQUAD FAR * lpQuad;
+
+ lpLogPalette->palVersion = 0x300;
+ lpLogPalette->palNumEntries = wDataSize / sizeof(PALETTEENTRY);
+
+ /* now convert RGBQUAD to PALETTEENTRY as we copy color info */
+ for (lpQuad = (RGBQUAD far *)lpColorData,
+ lpPE = (LPPALETTEENTRY)lpLogPalette->palPalEntry,
+ wDataSize /= sizeof(RGBQUAD);
+ wDataSize--;
+ ++lpQuad,++lpPE)
+ {
+ lpPE->peFlags = NULL;
+ lpPE->peRed = lpQuad->rgbRed;
+ lpPE->peBlue = lpQuad->rgbBlue;
+ lpPE->peGreen = lpQuad->rgbGreen;
+ }
+}
+
+#endif
+
diff --git a/private/ole32/ole232/stdimpl/handler.cpp b/private/ole32/ole232/stdimpl/handler.cpp
new file mode 100644
index 000000000..48a9d9156
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/handler.cpp
@@ -0,0 +1,197 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: handler.cpp
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 11-14-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+
+#include <le2int.h>
+
+#include <scode.h>
+#include <objerror.h>
+#include <olerem.h>
+#include "defhndlr.h"
+#include "defutil.h"
+
+
+#ifdef SERVER_HANDLER
+
+// Note: The DocObject interfaces will be published with Win96.
+// Remove the definition below once this interface is in
+// the public uuid file.
+// Office application are using them already.
+const GUID IID_IMsoDocumentSite = { 0xb722bcc7L, 0x4e68, 0x101b, 0xa2, 0xbc, 0x00, 0xaa, 0x00 ,0x40 ,0x47 ,0x70 };
+
+
+CInSrvRun::~CInSrvRun()
+{
+}
+
+CInSrvRun::CInSrvRun()
+{
+ dwOperation = 0;
+
+ pMnk = NULL;
+ pOCont = NULL;
+ pStg = NULL;
+ dwInPlace = NULL;
+ dwInFlags = NULL;
+ dwOperation = NULL;
+ dwInOptions = NULL;
+ pszContainerApp = NULL;
+ pszContainerObj = NULL;
+ pAS = NULL;
+
+ iVerb = NULL;
+ lpmsg = NULL;
+ lindex = NULL;
+ hwndParent = NULL;
+ lprcPosRect = NULL;
+ pContClassID = NULL;
+
+}
+
+CInSrvRun::DumpRun()
+{
+ HdlDebugOut((DEB_DUMP_INRUN, "CServerHandler::DumpRun (INSRVRUN) (%p)\n", this));
+ HdlDebugOut((DEB_DUMP_INRUN, "dwInOptions (%lx)\n", dwInOptions));
+ HdlDebugOut((DEB_DUMP_INRUN, "IStream (%p)\n", pStg));
+ HdlDebugOut((DEB_DUMP_INRUN, "IAdviseSink (%p)\n", pAS));
+ HdlDebugOut((DEB_DUMP_INRUN, "IMoniker (%p)\n", pMnk));
+ HdlDebugOut((DEB_DUMP_INRUN, "IOleContainer (%p)\n", pOCont));
+ HdlDebugOut((DEB_DUMP_INRUN, "pszContainerApp (%p)\n", pszContainerApp));
+ HdlDebugOut((DEB_DUMP_INRUN, "pszContainerObj (%p)\n", pszContainerObj));
+
+ return NOERROR;
+}
+
+CInSrvRun::DumpDoVerb()
+{
+ HdlDebugOut((DEB_DUMP_INRUN, "CServerHandler::DumpDoVerb this:(%p)\n", this));
+
+ HdlDebugOut((DEB_DUMP_INRUN, "iVerb (%ld)\n", iVerb ));
+ HdlDebugOut((DEB_DUMP_INRUN, "lpmsg (%p)\n", lpmsg ));
+ HdlDebugOut((DEB_DUMP_INRUN, "lindex (%ld)\n", lindex ));
+ HdlDebugOut((DEB_DUMP_INRUN, "hwndParent (%ld)\n", hwndParent ));
+ HdlDebugOut((DEB_DUMP_INRUN, "lprcPosRect (%p)\n", lprcPosRect ));
+ return NOERROR;
+}
+
+COutSrvRun::~COutSrvRun()
+{
+}
+
+COutSrvRun::COutSrvRun()
+{
+ dwOperation = 0;
+
+ pOO = 0;
+ pDO = 0;
+ pPStg = 0;
+ hrSetHostNames = 0;
+ hrPStg = 0;
+ hrAdvise = 0;
+ pUserClassID = 0;
+ dwOutFlag = 0;
+ dwOutOptions = 0;
+
+}
+
+COutSrvRun::DumpRun()
+{
+ HdlDebugOut((DEB_SERVERHANDLER, "CServerHandler::Dump (OUTSRVRUN) (%p)\n", this));
+
+ return NOERROR;
+}
+COutSrvRun::DumpDoVerb()
+{
+ HdlDebugOut((DEB_DUMP_OUTRUN, "CServerHandler::DumpDoVerb (OUTSRVRUN) (%p)\n", this));
+ HdlDebugOut((DEB_DUMP_OUTRUN, "pOO = 0; (%p)\n", pOO ));
+ HdlDebugOut((DEB_DUMP_OUTRUN, "pDO = 0; (%p)\n", pDO ));
+ HdlDebugOut((DEB_DUMP_OUTRUN, "pPStg = 0; (%p)\n", pPStg ));
+ HdlDebugOut((DEB_DUMP_OUTRUN, "hrSetHostNames = 0; (%x)\n", hrSetHostNames ));
+ HdlDebugOut((DEB_DUMP_OUTRUN, "hrPStg = 0; (%x)\n", hrPStg ));
+ HdlDebugOut((DEB_DUMP_OUTRUN, "hrAdvise = 0; (%x)\n", hrAdvise ));
+ HdlDebugOut((DEB_DUMP_OUTRUN, "pUserClassID = 0; (%p)\n", pUserClassID ));
+ HdlDebugOut((DEB_DUMP_OUTRUN, "dwOutFlag = 0; (%ld)\n", dwOutFlag ));
+ HdlDebugOut((DEB_DUMP_OUTRUN, "dwOutOptions = 0; (%ld)\n", dwOutOptions ));
+
+ return NOERROR;
+}
+CInSrvInPlace::CInSrvInPlace()
+{
+ dwOperation = 0;
+
+ dwInFlags = 0;
+ dwInOptions = 0;
+ dwDrawAspect = 0;
+ pOIPObj = NULL;
+
+}
+CInSrvInPlace::~CInSrvInPlace()
+{
+}
+CInSrvInPlace::Dump()
+{
+ HdlDebugOut((DEB_DUMP_ININPLACE, "CServerHandler::Dump (OUTSRVINPLACE) (%p)\n", this));
+ HdlDebugOut((DEB_DUMP_ININPLACE, "dwOperation, (%ld)\n",dwOperation));
+ HdlDebugOut((DEB_DUMP_ININPLACE, "dwInFlags, (%ld)\n",dwInFlags));
+ HdlDebugOut((DEB_DUMP_ININPLACE, "dwInOptions, (%ld \n",dwInOptions));
+ HdlDebugOut((DEB_DUMP_ININPLACE, "dwDrawAspect, (%ld)\n",dwDrawAspect));
+ HdlDebugOut((DEB_DUMP_ININPLACE, "sizel, (%p) \n",sizel));
+
+ return NOERROR;
+
+}
+
+COutSrvInPlace::COutSrvInPlace()
+{
+ dwOperation = 0;
+ dwOutFlags = 0;
+ dwOutOptions = 0;
+ hwnd = 0;
+ pOIPFrame = 0;
+ pOIPUIWnd = 0;
+ lprcPosRect = 0;
+ lprcClipRect = 0;
+ lpFrameInfo = 0;
+ hmenuShared = 0;
+ pszStatusText = 0;
+ dwDrawAspect = 0;
+}
+COutSrvInPlace::~COutSrvInPlace()
+{
+}
+COutSrvInPlace::Dump()
+{
+ HdlDebugOut((DEB_DUMP_OUTINPLACE, "CServerHandler::Dump (OUTSRVINPLACE) (%p)\n", this));
+ HdlDebugOut((DEB_DUMP_OUTINPLACE, "dwOutFlags, (%ld)\n",dwOutFlags));
+ HdlDebugOut((DEB_DUMP_OUTINPLACE, "dwOutOptions, (%ld \n",dwOutOptions));
+ HdlDebugOut((DEB_DUMP_OUTINPLACE, "hwnd, (%x) \n",hwnd));
+ HdlDebugOut((DEB_DUMP_OUTINPLACE, "pOIPFrame, (%p) \n",pOIPFrame));
+ HdlDebugOut((DEB_DUMP_OUTINPLACE, "pOIPUIWnd, (%p) \n",pOIPUIWnd));
+ HdlDebugOut((DEB_DUMP_OUTINPLACE, "lprcPosRect, (%p) \n",lprcPosRect));
+ HdlDebugOut((DEB_DUMP_OUTINPLACE, "lprcClipRect, (%p) \n",lprcClipRect));
+ HdlDebugOut((DEB_DUMP_OUTINPLACE, "lpFrameInfo, (%p) \n",lpFrameInfo));
+ HdlDebugOut((DEB_DUMP_OUTINPLACE, "hmenuShared, (%p) \n",hmenuShared));
+ HdlDebugOut((DEB_DUMP_OUTINPLACE, "MenuWidths, (%ld)\n",MenuWidths));
+ HdlDebugOut((DEB_DUMP_OUTINPLACE, "pszStatusText, (%p) \n",pszStatusText));
+ HdlDebugOut((DEB_DUMP_OUTINPLACE, "dwDrawAspect, (%ld)\n",dwDrawAspect));
+ HdlDebugOut((DEB_DUMP_OUTINPLACE, "sizel, (%p) \n",sizel));
+
+ return NOERROR;
+}
+
+
+#endif // SERVER_HANDLER
diff --git a/private/ole32/ole232/stdimpl/handler.hxx b/private/ole32/ole232/stdimpl/handler.hxx
new file mode 100644
index 000000000..7331a3ee6
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/handler.hxx
@@ -0,0 +1,126 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: handler.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 10-20-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef SERVER_HANDLER
+
+#ifndef _SRV_CLT_HANDLR_H_DEFINED_
+#define _SRV_CLT_HANDLR_H_DEFINED_
+
+#include <utils.h>
+#include "srvhdl.h"
+
+DECLARE_DEBUG(Hdl)
+
+#if DBG==1
+
+extern "C" unsigned long HdlInfoLevel; // ServerHandle and ClientSiteHandler
+
+#define HdlAssert(e) Win4Assert(e)
+#define HdlVerify(e) Win4Assert(e)
+#define HdlDebugOut(x) HdlInlineDebugOut x
+
+#define DEB_DEFHANDLER DEB_USER1
+#define DEB_LINKHANDLER DEB_USER2
+#define DEB_SERVERHANDLER DEB_USER3
+#define DEB_CLIENTHANDLER DEB_USER4
+#define DEB_SERVERHANDLER_UNKNOWN DEB_USER5
+#define DEB_CLIENTHANDLER_UNKNOWN DEB_USER6
+
+#define DEB_DUMP_INRUN DEB_USER7
+#define DEB_DUMP_OUTRUN DEB_USER8
+#define DEB_DUMP_ININPLACE DEB_USER9
+#define DEB_DUMP_OUTINPLACE DEB_USER10
+
+
+#else
+
+#define HdlDebugOut(x) NULL
+#define HdlAssert(e) Win4Assert(e)
+#define HdlVerify(e) Win4Assert(e)
+
+#endif // DBG
+
+
+class CInSrvRun : public INSRVRUN
+{
+public:
+ CInSrvRun();
+ ~CInSrvRun();
+ DumpRun();
+ DumpDoVerb();
+
+};
+
+
+class COutSrvRun : public OUTSRVRUN
+{
+public:
+ COutSrvRun();
+ ~COutSrvRun();
+ DumpRun();
+ DumpDoVerb();
+
+};
+class COutSrvInPlace : public OUTSRVINPLACE
+{
+public:
+ COutSrvInPlace();
+ ~COutSrvInPlace();
+ Dump();
+};
+
+class CInSrvInPlace : public INSRVINPLACE
+{
+public:
+ CInSrvInPlace();
+ ~CInSrvInPlace();
+ Dump();
+};
+
+typedef enum
+{
+ // options for the server handler
+ HO_ServerHandler = 0x0000ffff
+ ,HO_UseServerHandler = 0x00000001
+ ,HO_ServerCanInPlaceActivate = 0x00000002
+
+ // options for the client site handler
+ ,HO_ClientSiteHandler = 0xffff0000
+ ,HO_UseClientSiteHandler = 0x00010000
+ ,HO_ClientCanInPlaceActivate = 0x00020000
+
+ // Turn the server handler off again.
+ //,HO_Default = 0x000f000f
+ ,HO_Default = 0
+ ,HO_All = 0xffffffff
+
+} HandlerOptions;
+
+
+// Note: The DocObject interfaces will be published with Win96.
+// Remove the definition below once this interface is in
+// the public header files
+// Office application are using them already.
+//
+DEFINE_GUID(IID_IMsoDocumentSite, 0xb722bcc7L, 0x4e68, 0x101b, 0xa2, 0xbc, 0x00, 0xaa, 0x00 ,0x40 ,0x47 ,0x70 );
+
+#include "srvhndlr.h"
+#include "clthndlr.h"
+
+#endif // _SRV_CLT_HANDLR_H_DEFINED_
+
+#endif // SERVER_HANDLER
diff --git a/private/ole32/ole232/stdimpl/icon.cpp b/private/ole32/ole232/stdimpl/icon.cpp
new file mode 100644
index 000000000..406923881
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/icon.cpp
@@ -0,0 +1,2302 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: icon.cpp
+//
+// Contents: Functions to create DVASPECT_ICON metafile from a filename
+// or class ID
+//
+// Classes:
+//
+// Functions:
+// OleGetIconOfFile
+// OleGetIconOfClass
+// OleMetafilePictFromIconAndLabel
+//
+// HIconAndSourceFromClass: Extracts the first icon in a class's
+// server path and returns the path and icon index to
+// caller.
+// FIconFileFromClass: Retrieves the path to the exe/dll
+// containing the default icon, and the index of the icon.
+// IconLabelTextOut
+// XformWidthInPixelsToHimetric
+// Converts an int width into HiMetric units
+// XformWidthInHimetricToPixels
+// Converts an int width from HiMetric units
+// XformHeightInPixelsToHimetric
+// Converts an int height into HiMetric units
+// XformHeightInHimetricToPixels
+// Converts an int height from HiMetric units
+//
+// History: dd-mmm-yy Author Comment
+// 24-Nov-93 alexgo 32bit port
+// 15-Dec-93 alexgo fixed some bad UNICODE string handling
+// 11-Jan-94 alexgo added VDATEHEAP macros to every function
+// 25-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocations.
+// 26-Apr-94 AlexT Add tracing, fix bugs, etc
+// 27-Dec-94 alexgo fixed multithreading problems, added
+// support for quoted icon names
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+#include <le2int.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <commdlg.h>
+#include <memory.h>
+#include <cderr.h>
+#include <resource.h>
+
+#include "icon.h"
+
+#define OLEUI_CCHKEYMAX 256
+#define OLEUI_CCHPATHMAX 256
+#define OLEUI_CCHLABELMAX 42
+
+#define ICONINDEX 0
+
+#define AUXUSERTYPE_SHORTNAME USERCLASSTYPE_SHORT // short name
+#define HIMETRIC_PER_INCH 2540 // number HIMETRIC units per inch
+#define PTS_PER_INCH 72 // number points (font size) per inch
+
+#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
+#define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH)
+
+static OLECHAR const gszDefIconLabelKey[] =
+ OLESTR( "Software\\Microsoft\\OLE2\\DefaultIconLabel");
+
+#define IS_SEPARATOR(c) ( (c) == OLESTR(' ') || (c) == OLESTR('\\') || (c) == OLESTR('/') || (c) == OLESTR('\t') || (c) == OLESTR('!') || (c) == OLESTR(':') )
+
+//REVIEW: what about the \\ case for UNC filenames, could it be considered a delimter also?
+
+#define IS_FILENAME_DELIM(c) ( (c) == OLESTR('\\') || (c) == OLESTR('/') || (c) == OLESTR(':') )
+
+
+#ifdef WIN32
+#define LSTRCPYN(lpdst, lpsrc, cch) \
+(\
+ lpdst[cch-1] = OLESTR('\0'), \
+ lstrcpynW(lpdst, lpsrc, cch-1)\
+)
+#else
+#define LSTRCPYN(lpdst, lpsrc, cch) \
+(\
+ lpdst[cch-1] = OLESTR('\0'), \
+ lstrncpy(lpdst, lpsrc, cch-1)\
+)
+#endif
+
+void IconLabelTextOut(HDC hDC, HFONT hFont, int nXStart, int nYStart,
+ UINT fuOptions, RECT FAR * lpRect, LPCSTR lpszString,
+ UINT cchString);
+
+/*******
+ *
+ * ICON METAFILE FORMAT:
+ *
+ * The metafile generated with OleMetafilePictFromIconAndLabel contains
+ * the following records which are used by the functions in DRAWICON.C
+ * to draw the icon with and without the label and to extract the icon,
+ * label, and icon source/index.
+ *
+ * SetWindowOrg
+ * SetWindowExt
+ * DrawIcon:
+ * Inserts records of DIBBITBLT or DIBSTRETCHBLT, once for the
+ * AND mask, one for the image bits.
+ * Escape with the comment "IconOnly"
+ * This indicates where to stop record enumeration to draw only
+ * the icon.
+ * SetTextColor
+ * SetBkColor
+ * CreateFont
+ * SelectObject on the font.
+ * ExtTextOut
+ * One or more ExtTextOuts occur if the label is wrapped. The
+ * text in these records is used to extract the label.
+ * SelectObject on the old font.
+ * DeleteObject on the font.
+ * Escape with a comment that contains the path to the icon source (ANSI).
+ * Escape with a comment that is the string of the icon index (ANSI).
+ *
+ * Additional optional fields (new for 32-bit OLE, and only present if icon
+ * source or label was not translatable):
+ *
+ * Escape with a comment that contains the string
+ * "OLE: Icon label next (Unicode)" (ANSI string)
+ * Escape with a comment that contains the Unicode label
+ *
+ * Escape with a comment that contains the string
+ * "OLE: Icon source next (Unicode)" (ANSI string)
+ * Escape with a comment that contains the path to the icon source (UNICODE)
+ *
+ *******/
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleGetIconOfFile (public)
+//
+// Synopsis: Returns a hMetaPict containing an icon and label (filename)
+// for the specified filename
+//
+// Effects:
+//
+// Arguments: [lpszPath] -- LPOLESTR path including filename to use
+// [fUseAsLabel] -- if TRUE, use the filename as the icon's
+// label; no label if FALSE
+//
+// Requires: lpszPath != NULL
+//
+// Returns: HGLOBAL to the hMetaPict
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: tries to get the icon from the class ID or from the
+// exe associated with the file extension.
+//
+// History: dd-mmm-yy Author Comment
+// 27-Nov-93 alexgo first 32bit port (minor cleanup)
+// 15-Dec-93 alexgo changed lstrlen to _xstrlen
+// 27-Dec-93 erikgav chicago port
+// 28-Dec-94 alexgo fixed multithreading problems
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(HGLOBAL) OleGetIconOfFile(LPOLESTR lpszPath, BOOL fUseFileAsLabel)
+{
+ OLETRACEIN((API_OleGetIconOfFile, PARAMFMT("lpszPath= %ws, fUseFileAsLabel= %B"),
+ lpszPath, fUseFileAsLabel));
+
+ VDATEHEAP();
+
+ HGLOBAL hMetaPict = NULL;
+ BOOL fUseGenericDocIcon = FALSE;
+ BOOL bRet;
+
+ OLECHAR szIconFile[OLEUI_CCHPATHMAX];
+ OLECHAR szLabel[OLEUI_CCHLABELMAX];
+ OLECHAR szDocument[OLEUI_CCHLABELMAX];
+ CLSID clsid;
+ HICON hDefIcon = NULL;
+ UINT IconIndex = 0;
+ UINT cchPath;
+ BOOL fGotLabel = FALSE;
+
+ HRESULT hResult = E_FAIL;
+ UINT uFlags;
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleGetIconOfFile (%p, %d)\n",
+ NULL, lpszPath, fUseFileAsLabel));
+
+
+ *szIconFile = OLESTR('\0');
+ *szDocument = OLESTR('\0');
+
+ if (NULL == lpszPath)
+ {
+ // The spec allows a NULL lpszPath...
+ hMetaPict = NULL;
+ goto ErrRtn;
+ }
+
+ SHFILEINFO shfi;
+ uFlags = (SHGFI_ICON | SHGFI_LARGEICON | SHGFI_DISPLAYNAME |
+ SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES);
+
+ _xmemset(&shfi, 0, sizeof(shfi));
+
+ if (fUseFileAsLabel)
+ uFlags |= SHGFI_LINKOVERLAY;
+
+ if (OleSHGetFileInfo( lpszPath, FILE_ATTRIBUTE_NORMAL, &shfi, sizeof(shfi), uFlags))
+ {
+ if (shfi.iIcon == 0)
+ {
+ // Destroy the returned icon
+ DestroyIcon(shfi.hIcon);
+
+ // REVIEW: if non-NULL path str, do we want parameter validation?
+ hResult = GetClassFile(lpszPath, &clsid);
+
+ // use the clsid we got to get to the icon
+ if( NOERROR == hResult )
+ {
+ hDefIcon = HIconAndSourceFromClass(clsid, szIconFile, &IconIndex);
+ }
+ }
+ else
+ {
+ hDefIcon = shfi.hIcon;
+
+ hResult = NOERROR;
+
+ OLECHAR szUnicodeLabel[OLEUI_CCHLABELMAX];
+
+ #ifdef _CHICAGO_
+ LPTSTR lpszDisplayName;
+
+ if (fUseFileAsLabel)
+ lpszDisplayName = shfi.szDisplayName;
+ else
+ lpszDisplayName = shfi.szTypeName;
+
+ if(MultiByteToWideChar(AreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, lpszDisplayName,
+ -1, szUnicodeLabel, OLEUI_CCHLABELMAX) )
+ {
+ LSTRCPYN(szLabel, szUnicodeLabel,
+ sizeof(szLabel)/sizeof(OLECHAR) );
+ }
+
+ #else
+ if (fUseFileAsLabel)
+ LSTRCPYN(szLabel, shfi.szDisplayName, sizeof(szLabel)/sizeof(OLECHAR));
+ else
+ LSTRCPYN(szLabel, shfi.szTypeName, sizeof(szLabel)/sizeof(OLECHAR));
+ #endif
+
+ fGotLabel = TRUE;
+
+ // need to fill out szIconFile, which is the path to the file in which the icon
+ // was extracted. Unfortunately, the shell can't return this value to us, so we
+ // must get the file that OLE would have used in the fallback case. This could
+ // be inconsistant with the shell if the application has installed a custom icon
+ // handler.
+ hResult = GetClassFile(lpszPath, &clsid);
+
+ if( NOERROR == hResult )
+ {
+ FIconFileFromClass(clsid, szIconFile, OLEUI_CCHPATHMAX, &IconIndex);
+ }
+
+ }
+
+ }
+
+ cchPath = _xstrlen(lpszPath);
+
+ if ((NOERROR != hResult) || (NULL == hDefIcon))
+ {
+ WORD index = 0;
+ // we need to copy into a large buffer because the second
+ // parameter of ExtractAssociatedIcon (the path name) is an
+ // in/out
+ _xstrcpy(szIconFile, lpszPath);
+ hDefIcon = OleExtractAssociatedIcon(g_hmodOLE2, szIconFile, &index);
+ IconIndex = index;
+ }
+
+ if (fUseGenericDocIcon || hDefIcon <= (HICON)1)
+ {
+ DWORD dwLen;
+
+ dwLen = GetModuleFileName(g_hmodOLE2,
+ szIconFile,
+ sizeof(szIconFile) / sizeof(OLECHAR));
+ if (0 == dwLen)
+ {
+ LEDebugOut((DEB_WARN,
+ "OleGetIconOfFile: GetModuleFileName failed - %ld",
+ GetLastError()));
+ goto ErrRtn;
+ }
+
+ IconIndex = ICONINDEX;
+ hDefIcon = LoadIcon(g_hmodOLE2, MAKEINTRESOURCE(DEFICON));
+ }
+
+ // Now let's get the label we want to use.
+ if (fGotLabel)
+ {
+ // Do nothing
+ }
+ else if (fUseFileAsLabel)
+ {
+ // This assumes the path uses only '\', '/', and '.' as separators
+ // strip off path, so we just have the filename.
+ LPOLESTR lpszBeginFile;
+
+ // set pointer to END of path, so we can walk backwards
+ // through it.
+ lpszBeginFile = lpszPath + cchPath - 1;
+
+ while ((lpszBeginFile >= lpszPath) &&
+ (!IS_FILENAME_DELIM(*lpszBeginFile)))
+ {
+#ifdef WIN32
+ lpszBeginFile--;
+#else
+ lpszBeginFile = CharPrev(lpszPath, lpszBeginFile);
+#endif
+ }
+
+ lpszBeginFile++; // step back over the delimiter
+ // LSTRCPYN takes count of characters!
+ LSTRCPYN(szLabel, lpszBeginFile, sizeof(szLabel) / sizeof(OLECHAR));
+ }
+
+ // use the short user type (AuxUserType2) for the label
+ else if (0 == OleStdGetAuxUserType(clsid, AUXUSERTYPE_SHORTNAME,
+ szLabel, OLEUI_CCHLABELMAX, NULL))
+ {
+ if (OLESTR('\0')==szDocument[0]) // review, this is always true
+ {
+ LONG lRet;
+ LONG lcb;
+
+ lcb = sizeof (szDocument);
+ lRet = RegQueryValue(HKEY_CLASSES_ROOT, gszDefIconLabelKey,
+ szDocument, &lcb);
+
+#if DBG==1
+ if (ERROR_SUCCESS != lRet)
+ {
+ LEDebugOut((DEB_WARN,
+ "RegQueryValue for default icon label failed - %d\n",
+ GetLastError()));
+
+ }
+
+#endif
+
+ // NULL out last byte of string so don't rely on Reg behavior if buffer isn't big enough
+ szDocument[OLEUI_CCHLABELMAX -1] = OLESTR('\0');
+ }
+
+ _xstrcpy(szLabel, szDocument);
+ }
+
+ hMetaPict = OleMetafilePictFromIconAndLabel(hDefIcon, szLabel,
+ szIconFile, IconIndex);
+
+ bRet = DestroyIcon(hDefIcon);
+ Win4Assert(bRet && "DestroyIcon failed");
+
+ErrRtn:
+ LEDebugOut((DEB_TRACE, "%p OUT OleGetIconOfFile( %lx )\n",
+ hMetaPict ));
+
+ OLETRACEOUTEX((API_OleGetIconOfFile, RETURNFMT("%h"), hMetaPict));
+
+ return hMetaPict;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: GetAssociatedExectutable
+//
+// Synopsis: Finds the executables associated with the provided extension
+//
+// Effects:
+//
+// Arguments: [lpszExtension] -- pointer to the extension
+// [lpszExecutable] -- where to put the executable name
+// (assumes OLEUIPATHMAX OLECHAR buffer
+// from calling function)
+//
+// Requires: lpszExecutable must be large enough to hold the path
+//
+// Returns: TRUE if exe found, FALSE otherwise
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Queries reg database
+//
+// History: dd-mmm-yy Author Comment
+// 27-Nov-93 alexgo 32bit port
+// 15-Dec-93 alexgo fixed bug calculating size of strings
+// 26-Apr-94 AlexT Tracing, bug fixes
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+BOOL FAR PASCAL GetAssociatedExecutable(LPOLESTR lpszExtension,
+ LPOLESTR lpszExecutable)
+{
+ VDATEHEAP();
+
+ BOOL bRet;
+ HKEY hKey;
+ LONG dw;
+ LRESULT lRet;
+ OLECHAR szValue[OLEUI_CCHKEYMAX];
+ OLECHAR szKey[OLEUI_CCHKEYMAX];
+ LPOLESTR lpszTemp, lpszExe;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN GetAssociatedExecutable (%p, %p)\n",
+ NULL, lpszExtension, lpszExecutable));
+
+ // REVIEW: actually returns a LONG, which is indeed an LRESULT, not
+ // sure why the distinction here
+
+ lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ bRet = FALSE;
+ goto ErrRtn;
+ }
+
+ dw = sizeof(szValue);
+
+ lRet = RegQueryValue(hKey, lpszExtension, szValue, &dw);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ RegCloseKey(hKey);
+ bRet = FALSE;
+ goto ErrRtn;
+ }
+
+ // szValue now has ProgID
+ _xstrcpy(szKey, szValue);
+ _xstrcat(szKey, OLESTR("\\Shell\\Open\\Command"));
+
+ // RegQueryValue wants *bytes*, not characters
+ dw = sizeof(szValue);
+
+ lRet = RegQueryValue(hKey, szKey, szValue, &dw);
+
+ RegCloseKey(hKey);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ bRet = FALSE;
+ goto ErrRtn;
+ }
+
+ // szValue now has an executable name in it. Let's null-terminate
+ // at the first post-executable space (so we don't have cmd line
+ // args.
+
+ lpszTemp = szValue;
+ PUSHORT pCharTypes;
+
+ pCharTypes = (PUSHORT)_alloca (sizeof (USHORT) * (lstrlenW(lpszTemp) + 1));
+ if (pCharTypes == NULL)
+ {
+ goto ErrRtn;
+ }
+
+ GetStringTypeW (CT_CTYPE1, lpszTemp, -1, pCharTypes);
+
+ while ((OLESTR('\0') != *lpszTemp) && (pCharTypes[lpszTemp - szValue] & C1_SPACE))
+ {
+ lpszTemp++; // Strip off leading spaces
+ }
+
+ lpszExe = lpszTemp;
+
+ while ((OLESTR('\0') != *lpszTemp) && ((pCharTypes[lpszTemp - szValue] & C1_SPACE) == 0))
+ {
+ lpszTemp++; // Set through exe name
+ }
+
+ // null terminate at first space (or at end).
+ *lpszTemp = OLESTR('\0');
+
+ Win4Assert(_xstrlen(lpszExe) < OLEUI_CCHPATHMAX &&
+ "GetAssociatedFile too long");
+ _xstrcpy(lpszExecutable, lpszExe);
+
+ bRet = TRUE;
+
+ErrRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT GetAssociatedExecutable( %d )\n",
+ bRet ));
+
+ return bRet;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleGetIconOfClass (public)
+//
+// Synopsis: returns a hMetaPict containing an icon and label for the
+// specified class ID
+//
+// Effects:
+//
+// Arguments: [rclsid] -- the class ID to use
+// [lpszLabel] -- the label for the icon
+// [fUseTypeAsLabel] -- if TRUE, use the clsid's user type
+// as the label
+//
+// Requires:
+//
+// Returns: HGLOBAL
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Dec-93 alexgo fixed small bugs with Unicode strings
+// 27-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(HGLOBAL) OleGetIconOfClass(REFCLSID rclsid, LPOLESTR lpszLabel,
+ BOOL fUseTypeAsLabel)
+{
+ OLETRACEIN((API_OleGetIconOfClass,
+ PARAMFMT("rclisd= %I, lpszLabel= %p, fUseTypeAsLabel= %B"),
+ &rclsid, lpszLabel, fUseTypeAsLabel));
+
+ VDATEHEAP();
+
+ BOOL bRet;
+ OLECHAR szLabel[OLEUI_CCHLABELMAX];
+ OLECHAR szIconFile[OLEUI_CCHPATHMAX];
+ OLECHAR szDocument[OLEUI_CCHLABELMAX];
+ HICON hDefIcon;
+ UINT IconIndex;
+ HGLOBAL hMetaPict = NULL;
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleGetIconOfClass (%p, %p, %d)\n",
+ NULL, &rclsid, lpszLabel, fUseTypeAsLabel));
+
+
+ *szDocument = OLESTR('\0');
+
+#if DBG==1
+ if (fUseTypeAsLabel && (NULL != lpszLabel))
+ {
+ LEDebugOut((DEB_WARN,
+ "Ignoring non-NULL lpszLabel passed to OleGetIconOfClass\n"));
+ }
+#endif
+
+ if (!fUseTypeAsLabel) // Use string passed in as label
+ {
+ if (NULL != lpszLabel)
+ {
+ // LSTRCPYN takes count of characters!
+ LSTRCPYN(szLabel, lpszLabel, sizeof(szLabel) / sizeof(OLECHAR));
+ }
+ else
+ {
+ *szLabel = OLESTR('\0');
+ }
+ }
+ // Use AuxUserType2 (short name) as label
+ else if (0 == OleStdGetAuxUserType(rclsid, AUXUSERTYPE_SHORTNAME,
+ szLabel,
+ sizeof(szLabel) / sizeof(OLECHAR),
+ NULL))
+ {
+ // If we can't get the AuxUserType2, then try the long name
+ if (0 == OleStdGetUserTypeOfClass(rclsid,
+ szLabel,
+ sizeof(szLabel) / sizeof(OLECHAR),
+ NULL))
+ {
+ if (OLESTR('\0') == szDocument[0])
+ {
+ // RegQueryValue expects number of *bytes*
+ LONG lRet;
+ LONG lcb;
+
+ lcb = sizeof(szDocument);
+
+ lRet = RegQueryValue(HKEY_CLASSES_ROOT, gszDefIconLabelKey,
+ szDocument, &lcb);
+
+#if DBG==1
+ if (ERROR_SUCCESS != lRet)
+ {
+ LEDebugOut((DEB_WARN,
+ "RegQueryValue for default icon label failed - %d\n",
+ GetLastError()));
+ }
+#endif
+ // NULL out last byte of string so don't rely on Reg behavior if buffer isn't big enough
+ szDocument[OLEUI_CCHLABELMAX -1] = OLESTR('\0');
+ }
+
+ _xstrcpy(szLabel, szDocument); // last resort
+ }
+ }
+
+ // Get the icon, icon index, and path to icon file
+ hDefIcon = HIconAndSourceFromClass(rclsid, szIconFile, &IconIndex);
+
+ if (NULL == hDefIcon) // Use Vanilla Document
+ {
+ DWORD dwLen;
+
+ dwLen = GetModuleFileName(g_hmodOLE2,
+ szIconFile,
+ sizeof(szIconFile) / sizeof(OLECHAR));
+ if (0 == dwLen)
+ {
+ LEDebugOut((DEB_WARN,
+ "OleGetIconOfClass: GetModuleFileName failed - %ld",
+ GetLastError()));
+ goto ErrRtn;
+ }
+
+ IconIndex = ICONINDEX;
+ hDefIcon = LoadIcon(g_hmodOLE2, MAKEINTRESOURCE(DEFICON));
+ }
+
+ // Create the metafile
+ hMetaPict = OleMetafilePictFromIconAndLabel(hDefIcon, szLabel,
+ szIconFile, IconIndex);
+
+ bRet = DestroyIcon(hDefIcon);
+ Win4Assert(bRet && "DestroyIcon failed");
+
+
+ErrRtn:
+ LEDebugOut((DEB_TRACE, "%p OUT OleGetIconOfClass( %p )\n",
+ NULL, hMetaPict ));
+
+ OLETRACEOUTEX((API_OleGetIconOfClass, RETURNFMT("%h"), hMetaPict));
+
+ return hMetaPict;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HIconAndSourceFromClass
+//
+// Synopsis:
+// Given an object class name, finds an associated executable in the
+// registration database and extracts the first icon from that
+// executable. If none is available or the class has no associated
+// executable, this function returns NULL.
+//
+// Effects:
+//
+// Arguments: [rclsid] -- pointer the class id
+// [pszSource] -- where to put the source of the icon
+// [puIcon] -- where to store the index of the icon
+// -- in [pszSource]
+//
+// Requires:
+//
+// Returns: HICON -- handle to the extracted icon
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+HICON FAR PASCAL HIconAndSourceFromClass(REFCLSID rclsid, LPOLESTR pszSource,
+ UINT FAR *puIcon)
+{
+ VDATEHEAP();
+
+ HICON hIcon = NULL;
+ UINT IconIndex;
+
+ LEDebugOut((DEB_ITRACE, "%p _IN HIconAndSourceFromClass (%p, %p, %p)\n",
+ NULL, &rclsid, pszSource, puIcon));
+
+ if (IsEqualCLSID(CLSID_NULL, rclsid) || NULL==pszSource)
+ {
+ goto ErrRtn;
+ }
+
+ if (!FIconFileFromClass(rclsid, pszSource, OLEUI_CCHPATHMAX, &IconIndex))
+ {
+ goto ErrRtn;
+ }
+
+ hIcon = OleExtractIcon(g_hmodOLE2, pszSource, IconIndex);
+
+ // REVIEW: What's special about icon handles > 32 ?
+
+ if ((HICON)32 > hIcon)
+ {
+ // REVIEW: any cleanup or releasing of handle needed before we lose
+ // the ptr?
+
+ hIcon=NULL;
+ }
+ else
+ {
+ *puIcon= IconIndex;
+ }
+
+ErrRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT HIconAndSourceFromClass( %lx ) [ %d ]\n",
+ NULL, hIcon, *puIcon));
+
+ return hIcon;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ExtractNameAndIndex
+//
+// Synopsis: from the given string, extract the file name and icon index
+//
+// Effects:
+//
+// Arguments: [pszInfo] -- the starting string
+// [pszEXE] -- where to put the name (already allocated)
+// [cchEXE] -- sizeof pszEXE
+// [pIndex] -- where to put the icon index
+//
+// Requires: pszInfo != NULL
+// pszEXE != NULL
+// cchEXE != 0
+// pIndex != NULL
+//
+// Returns: BOOL -- TRUE on success, FALSE on error
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: takes strings of the form '"name",index' or 'name,index'
+// from the DefaultIcon registry entry
+//
+// parsing is very simple: if the name is enclosed in quotes,
+// take that as the exe name. If any other characters exist,
+// they must be a comma followed by digits (for the icon index)
+//
+// if the name is not enclosed by quotes, assume the name is
+// the entire string up until the last comma (if it exists).
+//
+// History: dd-mmm-yy Author Comment
+// 27-Dec-94 alexgo author
+//
+// Notes: legal filenames in NT and Win95 can include commas, but not
+// quotation marks.
+//
+//--------------------------------------------------------------------------
+
+BOOL ExtractNameAndIndex( LPOLESTR pszInfo, LPOLESTR pszEXE, UINT cchEXE,
+ UINT *pIndex)
+{
+ BOOL fRet = FALSE;
+ LPOLESTR pszStart = pszInfo;
+ LPOLESTR pszIndex = NULL;
+ LPOLESTR pszDest = pszEXE;
+ UINT cchName = 0;
+ DWORD i = 0;
+
+ Assert(pszInfo);
+ Assert(pszEXE);
+ Assert(cchEXE != 0);
+ Assert(pIndex);
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN ExtractNameAndIndex ( \"%ws\" , \"%ws\" ,"
+ " %d , %p )\n", NULL, pszInfo, pszEXE, cchEXE, pIndex));
+
+ *pIndex = 0;
+
+ if( *pszStart == OLESTR('\"') )
+ {
+ // name enclosed by quotes; just zoom down til the very last quote
+
+ pszStart++;
+
+ while( *pszStart != OLESTR('\0') && *pszStart != OLESTR('\"') &&
+ pszDest < (pszEXE + cchEXE))
+ {
+ *pszDest = *pszStart;
+ pszDest++;
+ pszStart++;
+ }
+
+ *pszDest = OLESTR('\0');
+
+ if( *pszStart == OLESTR('\"') )
+ {
+ pszIndex = pszStart + 1;
+ }
+ else
+ {
+ pszIndex = pszStart;
+ }
+
+ fRet = TRUE;
+ }
+ else
+ {
+ // find the last comma (if available)
+
+ pszIndex = pszStart + _xstrlen(pszStart);
+
+ while( *pszIndex != OLESTR(',') && pszIndex > pszStart )
+ {
+ pszIndex--;
+ }
+
+ // if no comma was found, just reset the index pointer to the end
+ if( pszIndex == pszStart )
+ {
+ pszIndex = pszStart + _xstrlen(pszStart);
+ }
+
+ cchName = (pszIndex - pszStart)/sizeof(OLECHAR);
+
+ if( cchEXE > cchName )
+ {
+ while( pszStart < pszIndex )
+ {
+ *pszDest = *pszStart;
+ pszDest++;
+ pszStart++;
+ }
+ *pszDest = OLESTR('\0');
+
+ fRet = TRUE;
+ }
+ }
+
+ // now fetch the index value
+
+ if( *pszIndex == OLESTR(',') )
+ {
+ pszIndex++;
+ }
+
+ *pIndex = wcstol(pszIndex, NULL, 10);
+
+ LEDebugOut((DEB_ITRACE, "%p OUT ExtractNameAndIndex ( %d ) [ \"%ws\" , "
+ " %d ]\n", NULL, fRet, pszEXE, *pIndex));
+
+ return fRet;
+}
+
+#if DBG == 1
+
+//+-------------------------------------------------------------------------
+//
+// Function: VerifyExtractNameAndIndex
+//
+// Synopsis: verifies the functioning of ExtractNameAndIndex (DEBUG only)
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Dec-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+void VerifyExtractNameAndIndex( void )
+{
+ OLECHAR szName[256];
+ UINT index = 0;
+ BOOL fRet = FALSE;
+
+ VDATEHEAP();
+
+ fRet = ExtractNameAndIndex( OLESTR("\"foo,8\",8"), szName, 256, &index);
+
+ Assert(fRet);
+ Assert(_xstrcmp(szName, OLESTR("foo,8")) == 0);
+ Assert(index == 8);
+
+ fRet = ExtractNameAndIndex( OLESTR("foo,8,8,89"), szName, 256, &index);
+
+ Assert(fRet);
+ Assert(_xstrcmp(szName, OLESTR("foo,8,8")) == 0);
+ Assert(index == 89);
+
+ fRet = ExtractNameAndIndex( OLESTR("progman.exe"), szName, 256, &index);
+
+ Assert(fRet);
+ Assert(_xstrcmp(szName, OLESTR("progman.exe")) == 0);
+ Assert(index == 0);
+
+ fRet = ExtractNameAndIndex( OLESTR("\"progman.exe\""), szName, 256,
+ &index);
+
+ Assert(fRet);
+ Assert(_xstrcmp(szName, OLESTR("progman.exe")) == 0);
+ Assert(index == 0);
+
+ VDATEHEAP();
+}
+
+#endif // DBG == 1
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: FIconFileFromClass, private
+//
+// Synopsis: Looks up the path to the exectuble that contains the class
+// default icon
+//
+// Effects:
+//
+// Arguments: [rclsid] -- the class ID to lookup
+// [pszEXE] -- where to put the server name
+// [cch] -- UINT size of [pszEXE]
+// [lpIndex] -- where to put the index of the icon
+// in the executable
+//
+// Requires: pszEXE != NULL
+// cch != 0
+//
+// Returns: TRUE if one or more characters where found for [pszEXE],
+// FALSE otherwise
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Nov-93 alexgo 32bit port
+// 15-Dec-93 alexgo fixed memory allocation bug and
+// some UNICODE string manip stuff
+// 27-Apr-94 AlexT Tracing, clean up memory allocation
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#define MAX_PATH_AND_INDEX 136 // room for 128 OLECHAR path and icon's index
+
+BOOL FAR PASCAL FIconFileFromClass(REFCLSID rclsid, LPOLESTR pszEXE,
+ UINT cch, UINT FAR *lpIndex)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN FIconFileFromClass (%p, %p, %d, %p)\n",
+ NULL, &rclsid, pszEXE, cch, lpIndex));
+
+ Win4Assert(NULL != pszEXE && "Bad argument to FIconFileFromClass");
+ Win4Assert(cch != 0 && "Bad argument to FIconFileFromClass");
+
+ BOOL bRet;
+ OLECHAR lpBuffer[MAX_PATH_AND_INDEX];
+
+ LONG dw;
+ LONG lRet;
+ HKEY hKey;
+ LPOLESTR lpIndexString;
+
+ if (IsEqualCLSID(CLSID_NULL, rclsid))
+ {
+ bRet = FALSE;
+ goto ErrRtn;
+ }
+
+ //Here, we alloc a buffer (maxpathlen + 8) to
+ //pass to RegQueryValue. Then, we copy the exe to pszEXE and the
+ //index to *lpIndex.
+
+ if (CoIsOle1Class(rclsid))
+ {
+ LPOLESTR lpszProgID;
+
+ // we've got an ole 1.0 class on our hands, so we look at
+ // progID\protocol\stdfileedting\server to get the
+ // name of the executable.
+
+ // REVIEW: could this possibly fail and leave you with an
+ // invalid ptr passed into regopenkey?
+
+ ProgIDFromCLSID(rclsid, &lpszProgID);
+
+ //Open up the class key
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, lpszProgID, &hKey);
+ PubMemFree(lpszProgID);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ bRet = FALSE;
+ goto ErrRtn;
+ }
+
+ // RegQueryValue expects number of *bytes*
+ dw= sizeof(lpBuffer);
+ lRet = RegQueryValue(hKey,
+ OLESTR("Protocol\\StdFileEditing\\Server"),
+ lpBuffer, &dw);
+
+ RegCloseKey(hKey);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ bRet = FALSE;
+ goto ErrRtn;
+ }
+
+ // Use server and 0 as the icon index
+ // LSTRCPYN takes count of characters!
+ LSTRCPYN(pszEXE, lpBuffer, cch);
+
+ // REVIEW: is this internally trusted? No validation...
+ // (same for rest of writes to it this fn)
+
+ *lpIndex = 0;
+
+ bRet = TRUE;
+ goto ErrRtn;
+ }
+
+ /*
+ * We have to go walking in the registration database under the
+ * classname, so we first open the classname key and then check
+ * under "\\DefaultIcon" to get the file that contains the icon.
+ */
+
+ {
+ LPOLESTR pszClass;
+ OLECHAR szKey[64];
+
+ StringFromCLSID(rclsid, &pszClass);
+
+ _xstrcpy(szKey, OLESTR("CLSID\\"));
+ _xstrcat(szKey, pszClass);
+ PubMemFree(pszClass);
+
+ //Open up the class key
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, szKey, &hKey);
+ }
+
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ bRet = FALSE;
+ goto ErrRtn;
+ }
+
+ //Get the executable path and icon index.
+
+ // RegQueryValue expects number of bytes
+ dw = sizeof(lpBuffer);
+ lRet=RegQueryValue(hKey, OLESTR("DefaultIcon"), lpBuffer, &dw);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ // no DefaultIcon key...try LocalServer
+
+ // RegQueryValue expects number of bytes
+ dw= sizeof(lpBuffer);
+ lRet=RegQueryValue(hKey, OLESTR("LocalServer32"), lpBuffer,
+ &dw);
+ }
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ // RegQueryValue expects number of bytes
+ dw= sizeof(lpBuffer);
+ lRet=RegQueryValue(hKey, OLESTR("LocalServer"), lpBuffer,
+ &dw);
+ }
+
+ RegCloseKey(hKey);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ // no LocalServer entry either...they're outta luck.
+ bRet = FALSE;
+ goto ErrRtn;
+ }
+
+ // lpBuffer contains a string that looks like
+ // "<pathtoexe>,<iconindex>",
+ // so we need to separate the path and the icon index.
+
+ bRet = ExtractNameAndIndex(lpBuffer, pszEXE, cch, lpIndex);
+
+#if DBG == 1
+ // do some quick checking while we're at it.
+ VerifyExtractNameAndIndex();
+#endif // DBG == 1
+
+ErrRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT FIconFileFromClass ( %d ) [%d]\n",
+ NULL, bRet, *lpIndex));
+
+ return bRet;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleMetafilePictFromIconAndLabel (public)
+//
+// Synopsis:
+// Creates a METAFILEPICT structure that container a metafile in which
+// the icon and label are drawn. A comment record is inserted between
+// the icon and the label code so our special draw function can stop
+// playing before the label.
+//
+// Effects:
+//
+// Arguments: [hIcon] -- icon to draw into the metafile
+// [pszLabel] -- the label string
+// [pszSourceFile] -- local pathname of the icon
+// [iIcon] -- index into [pszSourceFile] for the icon
+//
+// Requires:
+//
+// Returns: HGLOBAL to a METAFILEPICT structure (using MM_ANISOTROPIC
+// mapping mode)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 27-Nov-93 alexgo first 32bit port
+// 15-Dec-93 alexgo fixed bugs with UNICODE strings
+// 09-Mar-94 AlexT Make this backwards compatible
+//
+// Notes: REVIEW32:: need to fix font grabbing etc, to be international
+// friendly, see comments below
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(HGLOBAL) OleMetafilePictFromIconAndLabel(HICON hIcon,
+ LPOLESTR pwcsLabel, LPOLESTR pwcsSourceFile, UINT iIcon)
+{
+ OLETRACEIN((API_OleMetafilePictFromIconAndLabel,
+ PARAMFMT("hIcon= %h, pwcsLabel= %ws, pwcsSourceFile= %ws, iIcon= %d"),
+ hIcon, pwcsLabel, pwcsSourceFile, iIcon));
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_TRACE, "%p _IN OleMetafilePictFromIconAndLabel (%p, %p, %p, %d)\n",
+ NULL, hIcon, pwcsLabel, pwcsSourceFile, iIcon));
+
+ //Where to stop to exclude label (explicitly ANSI)
+ static char szIconOnly[] = "IconOnly";
+ static char szIconLabelNext[] = "OLE: Icon label next (Unicode)";
+ static char szIconSourceNext[] = "OLE: Icon source next (Unicode)";
+ static char szDefaultChar[] = "?";
+
+ // REVIEW: Mein Got! This is a huge fn, could it be broken up?
+
+ HGLOBAL hMem = NULL;
+ HDC hDC, hDCScreen;
+ HMETAFILE hMF;
+ LPMETAFILEPICT pMF;
+ OLECHAR wszIconLabel[OLEUI_CCHLABELMAX + 1];
+ char szIconLabel[OLEUI_CCHLABELMAX + 1];
+ UINT cchLabelW;
+ UINT cchLabelA;
+ UINT cchIndex;
+ BOOL bUsedDefaultChar;
+ TEXTMETRICA textMetric;
+ UINT cxIcon, cyIcon;
+ UINT cxText, cyText;
+ UINT cx, cy;
+ HFONT hFont, hSysFont, hFontT;
+ int cyFont;
+ char szIndex[10];
+ RECT TextRect;
+ char * pszSourceFile;
+ UINT cchSourceFile;
+ int iRet;
+ BOOL bWriteUnicodeLabel;
+ BOOL bWriteUnicodeSource;
+ LOGFONT logfont;
+
+ if (NULL == hIcon) // null icon is valid
+ {
+ goto ErrRtn;
+ }
+
+ // REVIEW: ptr validation on IN params?
+
+ bWriteUnicodeSource = FALSE;
+ pszSourceFile = NULL;
+ if (NULL != pwcsSourceFile)
+ {
+ // Prepare source file string
+ cchSourceFile = _xstrlen(pwcsSourceFile) + 1;
+ pszSourceFile = (char *) PrivMemAlloc(cchSourceFile);
+ if (NULL == pszSourceFile)
+ {
+ LEDebugOut((DEB_WARN, "PrivMemAlloc(%d) failed\n",
+ cchSourceFile));
+ goto ErrRtn;
+ }
+
+ iRet = WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP, 0,
+ pwcsSourceFile, cchSourceFile,
+ pszSourceFile, cchSourceFile,
+ szDefaultChar, &bUsedDefaultChar);
+
+ bWriteUnicodeSource = bUsedDefaultChar;
+
+ if (0 == iRet)
+ {
+ // Unexpected failure, since at worst we should have
+ // just filled in pszSourceFile with default characters.
+ LEDebugOut((DEB_WARN, "WideCharToMultiByte failed - %lx\n",
+ GetLastError()));
+ }
+ }
+
+ // Create a memory metafile. We explicitly make it an ANSI metafile for
+ // backwards compatibility.
+#ifdef WIN32
+ hDC = CreateMetaFileA(NULL);
+#else
+ hDC = CreateMetaFile(NULL);
+#endif
+
+ if (NULL == hDC)
+ {
+ LEDebugOut((DEB_WARN, "CreateMetaFile failed - %lx\n",
+ GetLastError()));
+
+ PrivMemFree(pszSourceFile);
+ goto ErrRtn;
+ }
+
+ //Allocate the metafilepict
+ hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(METAFILEPICT));
+
+ if (NULL == hMem)
+ {
+ LEDebugOut((DEB_WARN, "GlobalAlloc failed - %lx\n",
+ GetLastError()));
+
+ hMF = CloseMetaFile(hDC);
+ DeleteMetaFile(hMF);
+ PrivMemFree(pszSourceFile);
+ goto ErrRtn;
+ }
+
+ // Prepare ANSI label
+ szIconLabel[0] = '\0';
+ cchLabelW = 0;
+ cchLabelA = 0;
+
+ // REVIEW: don't follow the logic here: you conditionally set it above
+ // and explicity clear it here?
+
+ bWriteUnicodeLabel = FALSE;
+ if (NULL != pwcsLabel)
+ {
+ cchLabelW = _xstrlen(pwcsLabel) + 1;
+ if (OLEUI_CCHLABELMAX < cchLabelW)
+ {
+ //REVIEW: would it be worth warning of the truncation in debug builds?
+ // or is this a common case?
+
+ LSTRCPYN(wszIconLabel, pwcsLabel, OLEUI_CCHLABELMAX);
+ wszIconLabel[OLEUI_CCHLABELMAX] = L'\0';
+ pwcsLabel = wszIconLabel;
+ cchLabelW = OLEUI_CCHLABELMAX;
+ }
+
+ cchLabelA = cchLabelW;
+
+ // We have a label - translate it to ANSI for the TextOut's...
+ iRet = WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP, 0,
+ pwcsLabel, cchLabelW,
+ szIconLabel, sizeof(szIconLabel),
+ szDefaultChar, &bUsedDefaultChar);
+
+ if (0 == iRet)
+ {
+ // Unexpected failure, since at worst we should have
+ // just filled in pszSourceFile with default characters.
+ LEDebugOut((DEB_WARN, "WideCharToMultiByte failed - %lx\n",
+ GetLastError()));
+ }
+
+ bWriteUnicodeLabel = bUsedDefaultChar;
+ }
+
+ //Need to use the screen DC for these operations
+ hDCScreen = GetDC(NULL);
+
+ LOGFONT lf;
+ SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), &lf, FALSE);
+ hFont = CreateFontIndirect(&lf);
+
+ hFontT= (HFONT) SelectObject(hDCScreen, hFont);
+
+ GetTextMetricsA(hDCScreen, &textMetric);
+
+ cxText = textMetric.tmMaxCharWidth * 10; // Why 10?
+ // We use double the height to provide some margin space
+ cyText = textMetric.tmHeight * 2;
+
+ SelectObject(hDCScreen, hFontT);
+
+ cxIcon = GetSystemMetrics(SM_CXICON);
+ cyIcon = GetSystemMetrics(SM_CYICON);
+
+ // If we have no label, then we want the metafile to be the width of
+ // the icon (plus margin), not the width of the fattest string.
+ if ('\0' == szIconLabel[0])
+ {
+ cx = cxIcon + cxIcon / 4;
+ }
+ else
+ {
+ cx = max(cxText, cxIcon);
+ }
+
+ cy = cyIcon + cyText + 4; // Why 4?
+
+ //Set the metafile size to fit the icon and label
+ SetMapMode(hDC, MM_ANISOTROPIC);
+ SetWindowOrgEx(hDC, 0, 0, NULL);
+ SetWindowExtEx(hDC, cx, cy, NULL);
+
+ //Set up rectangle to pass to IconLabelTextOut
+ SetRectEmpty(&TextRect);
+
+ TextRect.right = cx;
+ TextRect.bottom = cy;
+
+ //Draw the icon and the text, centered with respect to each other.
+ DrawIcon(hDC, (cx - cxIcon) / 2, 0, hIcon);
+
+ //String that indicates where to stop if we're only doing icons
+
+ Escape(hDC, MFCOMMENT, sizeof(szIconOnly), szIconOnly, NULL);
+
+ SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
+ SetBkMode(hDC, TRANSPARENT);
+
+ IconLabelTextOut(hDC, hFont, 0, cy - cyText, ETO_CLIPPED,
+ &TextRect, szIconLabel, cchLabelA);
+
+ // Write comments containing the icon source file and index.
+
+ if (NULL != pwcsSourceFile)
+ {
+ AssertSz(pszSourceFile != NULL, "Unicode source existed");
+
+ //Escape wants number of *bytes*
+ Escape(hDC, MFCOMMENT,
+ cchSourceFile, pszSourceFile, NULL);
+
+ cchIndex = wsprintfA(szIndex, "%u", iIcon);
+
+ // Escape wants number of *bytes*
+ Escape(hDC, MFCOMMENT, cchIndex + 1, szIndex, NULL);
+ }
+ else if (bWriteUnicodeLabel || bWriteUnicodeSource)
+ {
+ // We're going to write out comment records for the Unicode
+ // strings, so we need to emit dummy ANSI source comments.
+
+ //Escape wants number of *bytes*
+ Escape(hDC, MFCOMMENT, sizeof(""), "", NULL);
+
+ // Escape wants number of *bytes*
+ Escape(hDC, MFCOMMENT, sizeof("0"), "0", NULL);
+ }
+
+ if (bWriteUnicodeLabel)
+ {
+ // Now write out the UNICODE label
+ Escape(hDC, MFCOMMENT,
+ sizeof(szIconLabelNext), szIconLabelNext, NULL);
+
+ Escape(hDC, MFCOMMENT,
+ cchLabelW * sizeof(OLECHAR), (LPSTR) pwcsLabel,
+ NULL);
+ }
+
+ if (bWriteUnicodeSource)
+ {
+ // Now write out the UNICODE label
+ Escape(hDC, MFCOMMENT,
+ sizeof(szIconSourceNext), szIconSourceNext, NULL);
+
+ Escape(hDC, MFCOMMENT,
+ cchSourceFile * sizeof(OLECHAR), (LPSTR) pwcsSourceFile,
+ NULL);
+ }
+
+ //All done with the metafile, now stuff it all into a METAFILEPICT.
+ hMF = CloseMetaFile(hDC);
+
+ if (NULL==hMF)
+ {
+ GlobalFree(hMem);
+ hMem = NULL;
+
+ ReleaseDC(NULL, hDCScreen);
+ goto ErrRtn;
+ }
+
+ pMF=(LPMETAFILEPICT)GlobalLock(hMem);
+
+ //Transform to HIMETRICS
+ cx=XformWidthInPixelsToHimetric(hDCScreen, cx);
+ cy=XformHeightInPixelsToHimetric(hDCScreen, cy);
+ ReleaseDC(NULL, hDCScreen);
+
+ pMF->mm=MM_ANISOTROPIC;
+ pMF->xExt=cx;
+ pMF->yExt=cy;
+ pMF->hMF=hMF;
+
+ GlobalUnlock(hMem);
+
+ DeleteObject(hFont);
+ PrivMemFree(pszSourceFile);
+
+ // REVIEW: any need to release the font resource?
+ErrRtn:
+ LEDebugOut((DEB_TRACE, "%p OUT OleMetafilePictFromIconAndLabel ( %p )\n",
+ NULL, hMem));
+
+ OLETRACEOUTEX((API_OleMetafilePictFromIconAndLabel,
+ RETURNFMT("%h"), hMem));
+ return hMem;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IconLabelTextOut (internal)
+//
+// Synopsis:
+// Replacement for DrawText to be used in the "Display as Icon" metafile.
+// Uses ExtTextOutA to output a string center on (at most) two lines.
+// Uses a very simple word wrap algorithm to split the lines.
+//
+// Effects:
+//
+// Arguments: [hDC] -- device context (cannot be NULL)
+// [hFont] -- font to use
+// [nXStart] -- x-coordinate of starting position
+// [nYStart] -- y-coordinate of starting position
+// [fuOptions] -- rectangle type
+// [lpRect] -- rect far * containing rectangle to draw
+// text in.
+// [lpszString] -- string to draw
+// [cchString] -- length of string (truncated if over
+// OLEUI_CCHLABELMAX), including terminating
+// NULL
+//
+// Requires:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 28-Nov-93 alexgo initial 32bit port
+// 09-Mar-94 AlexT Use ANSI strings
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+// POSTPPC: The parameter 'cchString' is superfluous since lpszString
+// is guaranteed to be null terminated
+void IconLabelTextOut(HDC hDC, HFONT hFont, int nXStart, int nYStart,
+ UINT fuOptions, RECT FAR * lpRect, LPCSTR lpszString,
+ UINT cchString)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN IconLabelTextOut (%lx, %lx, %d, %d, %d, %p, %p, %d)\n",
+ NULL, hDC, hFont,
+ nXStart, nYStart, fuOptions, lpRect, lpszString, cchString));
+
+ AssertSz(hDC != NULL, "Bad arg to IconLabelTextOut");
+ AssertSz(lpszString != NULL, "Bad arg to IconLabelTextOut");
+ AssertSz(strlen(lpszString) < OLEUI_CCHLABELMAX,
+ "Bad arg to IconLabelTextOut");
+
+ // REVIEW: does our compiler have to initialize static function scoped
+ // data? I know old versions did...
+
+ static char szSeparators[] = " \t\\/!:";
+ static char szTempBuff[OLEUI_CCHLABELMAX];
+
+ HDC hDCScreen;
+ int cxString, cyString, cxMaxString;
+ int cxFirstLine, cyFirstLine, cxSecondLine;
+ int index;
+ char chKeep;
+ LPSTR lpszSecondLine;
+ LPSTR lpstrLast;
+ HFONT hFontT;
+ SIZE size;
+ int cch = strlen(lpszString);
+ UINT uiAlign = GDI_ERROR;
+
+ // Initialization stuff...
+
+ strcpy(szTempBuff, lpszString);
+
+ // set maximum width
+
+ cxMaxString = lpRect->right - lpRect->left;
+
+ // get screen DC to do text size calculations
+ hDCScreen = GetDC(NULL);
+
+ hFontT= (HFONT)SelectObject(hDCScreen, hFont);
+
+ // get the extent of our label
+ GetTextExtentPointA(hDCScreen, szTempBuff, cch, &size);
+
+ cxString = size.cx;
+ cyString = size.cy;
+
+ // Select in the font we want to use
+ SelectObject(hDC, hFont);
+
+ // Center the string
+ uiAlign = SetTextAlign(hDC, TA_CENTER);
+
+ // String is smaller than max string - just center, ETO, and return.
+ if (cxString <= cxMaxString)
+ {
+ ExtTextOutA(hDC,
+ nXStart + lpRect->right / 2,
+ nYStart,
+ fuOptions,
+ lpRect,
+ szTempBuff,
+ cch,
+ NULL);
+
+ goto CleanupAndLeave;
+ }
+
+ // BUGBUG - NtIssue #2730 All code below here needs to be
+ // carefully verified - it looks suspicious...
+
+ // String is too long...we've got to word-wrap it.
+ // Are there any spaces, slashes, tabs, or bangs in string?
+
+
+ if (strlen(szTempBuff) != strcspn(szTempBuff, szSeparators))
+ {
+ // Yep, we've got spaces, so we'll try to find the largest
+ // space-terminated string that will fit on the first line.
+
+ index = cch;
+
+ while (index >= 0)
+ {
+ // scan the string backwards for spaces, slashes,
+ // tabs, or bangs
+
+ // REVIEW: scary. Could this result in a negative
+ // index, or is it guarnateed to hit a separator
+ // before that?
+
+ while (!IS_SEPARATOR(szTempBuff[index]) )
+ {
+ index--;
+ }
+
+ if (index <= 0)
+ {
+ break;
+ }
+
+ // remember what char was there
+ chKeep = szTempBuff[index];
+
+ szTempBuff[index] = '\0'; // just for now
+
+ GetTextExtentPointA(hDCScreen, szTempBuff,
+ index,&size);
+
+ cxFirstLine = size.cx;
+ cyFirstLine = size.cy;
+
+ // REVIEW: but chKeep is NOT an OLECHAR
+
+ // put the right OLECHAR back
+ szTempBuff[index] = chKeep;
+
+ if (cxFirstLine <= cxMaxString)
+ {
+ ExtTextOutA(hDC,
+ nXStart + lpRect->right / 2,
+ nYStart,
+ fuOptions,
+ lpRect,
+ szTempBuff,
+ index + 1, // BUGBUG - NtIssue #2730
+ NULL);
+
+ lpszSecondLine = szTempBuff;
+ lpszSecondLine += index + 1;
+
+ GetTextExtentPointA(hDCScreen,
+ lpszSecondLine,
+ strlen(lpszSecondLine),
+ &size);
+
+ // If the second line is wider than the
+ // rectangle, we just want to clip the text.
+ cxSecondLine = min(size.cx, cxMaxString);
+
+ ExtTextOutA(hDC,
+ nXStart + lpRect->right / 2,
+ nYStart + cyFirstLine,
+ fuOptions,
+ lpRect,
+ lpszSecondLine,
+ strlen(lpszSecondLine),
+ NULL);
+
+ goto CleanupAndLeave;
+ } // end if
+
+ index--;
+ } // end while
+ } // end if
+
+ // Here, there are either no spaces in the string
+ // (strchr(szTempBuff, ' ') returned NULL), or there spaces in the
+ // string, but they are positioned so that the first space
+ // terminated string is still longer than one line.
+ // So, we walk backwards from the end of the string until we
+ // find the largest string that will fit on the first
+ // line , and then we just clip the second line.
+
+ // We allow 40 characters in the label, but the metafile is
+ // only as wide as 10 W's (for aesthetics - 20 W's wide looked
+ // dumb. This means that if we split a long string in half (in
+ // terms of characters), then we could still be wider than the
+ // metafile. So, if this is the case, we just step backwards
+ // from the halfway point until we get something that will fit.
+ // Since we just let ETO clip the second line
+
+ cch = strlen(szTempBuff);
+ lpstrLast = &szTempBuff[cch];
+ chKeep = *lpstrLast;
+ *lpstrLast = '\0';
+
+ GetTextExtentPointA(hDCScreen, szTempBuff, cch, &size);
+
+ cxFirstLine = size.cx;
+ cyFirstLine = size.cy;
+
+ while (cxFirstLine > cxMaxString)
+ {
+ *lpstrLast = chKeep;
+
+ // The string is always ansi, so always use CharPrevA.
+ lpstrLast = CharPrevA(szTempBuff, lpstrLast);
+
+ if (szTempBuff == lpstrLast)
+ {
+ goto CleanupAndLeave;
+ }
+
+ chKeep = *lpstrLast;
+ *lpstrLast = '\0';
+
+ // need to calculate the new length of the string
+ cch = strlen(szTempBuff);
+
+ GetTextExtentPointA(hDCScreen, szTempBuff,
+ cch, &size);
+ cxFirstLine = size.cx;
+ }
+
+ ExtTextOutA(hDC,
+ nXStart + lpRect->right / 2,
+ nYStart,
+ fuOptions,
+ lpRect,
+ szTempBuff,
+ strlen(szTempBuff),
+ NULL);
+
+ szTempBuff[cch] = chKeep;
+ lpszSecondLine = szTempBuff;
+ lpszSecondLine += cch;
+
+ GetTextExtentPointA(hDCScreen, lpszSecondLine,
+ strlen(lpszSecondLine), &size);
+
+ // If the second line is wider than the rectangle, we
+ // just want to clip the text.
+ cxSecondLine = min(size.cx, cxMaxString);
+
+ ExtTextOutA(hDC,
+ nXStart + lpRect->right / 2,
+ nYStart + cyFirstLine,
+ fuOptions,
+ lpRect,
+ lpszSecondLine,
+ strlen(lpszSecondLine),
+ NULL);
+
+CleanupAndLeave:
+ // If we changed the alignment we restore it here
+ if (uiAlign != GDI_ERROR)
+ {
+ SetTextAlign(hDC, uiAlign);
+ }
+
+ SelectObject(hDCScreen, hFontT);
+ ReleaseDC(NULL, hDCScreen);
+
+ LEDebugOut((DEB_ITRACE, "%p OUT IconLabelTextOut ()\n"));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleStdGetUserTypeOfClass, private
+//
+// Synopsis: Returns the user type info of the specified class
+//
+// Effects:
+//
+// Arguments: [rclsid] -- the class ID in question
+// [lpszUserType] -- where to put the user type string
+// [cch] -- the length of [lpszUserType] (in
+// *characters*, not bytes)
+// [hKey] -- handle to the reg db (may be NULL)
+//
+// Requires:
+//
+// Returns: UINT -- the number of characters put into the return string
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(UINT) OleStdGetUserTypeOfClass(REFCLSID rclsid, LPOLESTR lpszUserType, UINT cch, HKEY hKey)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN OleStdGetUserTypeOfClass (%p, %p, %d, %lx)\n",
+ NULL, &rclsid, lpszUserType, cch, hKey));
+
+ LONG dw = 0;
+ LONG lRet;
+
+ // REVIEW: would make more sense to set this when the reg is opened
+
+ BOOL bCloseRegDB = FALSE;
+
+ if (hKey == NULL)
+ {
+ //Open up the root key.
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ {
+ goto ErrRtn;
+ }
+
+ bCloseRegDB = TRUE;
+ }
+
+
+ // Get a string containing the class name
+ {
+ LPOLESTR lpszCLSID;
+ OLECHAR szKey[128];
+
+ StringFromCLSID(rclsid, &lpszCLSID);
+
+ _xstrcpy(szKey, OLESTR("CLSID\\"));
+ _xstrcat(szKey, lpszCLSID);
+ PubMemFree((LPVOID)lpszCLSID);
+
+ dw = cch * sizeof(OLECHAR);
+ lRet = RegQueryValue(hKey, szKey, lpszUserType, &dw);
+ dw = dw / sizeof(OLECHAR);
+ }
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ {
+ dw = 0;
+ }
+
+ if ( ((LONG)ERROR_SUCCESS!=lRet) && (CoIsOle1Class(rclsid)) )
+ {
+ LPOLESTR lpszProgID;
+
+ // We've got an OLE 1.0 class, so let's try to get the user
+ // type name from the ProgID entry.
+
+ ProgIDFromCLSID(rclsid, &lpszProgID);
+
+ // REVIEW: will progidfromclsid always set your ptr for you?
+
+ dw = cch * sizeof(OLECHAR);
+ lRet = RegQueryValue(hKey, lpszProgID, lpszUserType, &dw);
+ dw = dw / sizeof(OLECHAR);
+
+ PubMemFree((LPVOID)lpszProgID);
+
+ if ((LONG)ERROR_SUCCESS != lRet)
+ {
+ dw = 0;
+ }
+ }
+
+
+ if (bCloseRegDB)
+ {
+ RegCloseKey(hKey);
+ }
+
+ErrRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT OleStdGetUserTypeOfClass ( %d )\n",
+ NULL, dw));
+
+ return (UINT)dw;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleStdGetAuxUserType, private
+//
+// Synopsis: Returns the specified AuxUserType from the reg db
+//
+// Effects:
+//
+// Arguments: [rclsid] -- the class ID in question
+// [hKey] -- handle to the reg db root (may be NULL)
+// [wAuxUserType] -- which field to look for (name, exe, etc)
+// [lpszUserType] -- where to put the returned string
+// [cch] -- size of [lpszUserType] in *characters*
+//
+// Requires:
+//
+// Returns: UINT -- number of characters in returned string.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+// 27-Apr-94 AlexT Tracing, clean up
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(UINT) OleStdGetAuxUserType(REFCLSID rclsid,
+ WORD wAuxUserType,
+ LPOLESTR lpszAuxUserType,
+ int cch,
+ HKEY hKey)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN OleStdGetAuxUserType (%p, %hu, %p, %d, %lx)\n",
+ NULL, &rclsid, wAuxUserType, lpszAuxUserType, cch, hKey));
+
+ LONG dw = 0;
+ HKEY hThisKey;
+ BOOL bCloseRegDB = FALSE;
+ LRESULT lRet;
+ LPOLESTR lpszCLSID;
+ OLECHAR szKey[OLEUI_CCHKEYMAX];
+ OLECHAR szTemp[32];
+
+ lpszAuxUserType[0] = OLESTR('\0');
+
+ if (NULL == hKey)
+ {
+ lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hThisKey);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ goto ErrRtn;
+ }
+
+ bCloseRegDB = TRUE;
+ }
+ else
+ {
+ hThisKey = hKey;
+ }
+
+ StringFromCLSID(rclsid, &lpszCLSID);
+
+ _xstrcpy(szKey, OLESTR("CLSID\\"));
+ _xstrcat(szKey, lpszCLSID);
+ wsprintf(szTemp, OLESTR("\\AuxUserType\\%d"), wAuxUserType);
+ _xstrcat(szKey, szTemp);
+ PubMemFree(lpszCLSID);
+
+ dw = cch * sizeof(OLECHAR);
+
+ lRet = RegQueryValue(hThisKey, szKey, lpszAuxUserType, &dw);
+
+ // Convert dw from byte count to OLECHAR count
+ dw = dw / sizeof(OLECHAR);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ dw = 0;
+ lpszAuxUserType[0] = '\0';
+ }
+
+ if (bCloseRegDB)
+ {
+ RegCloseKey(hThisKey);
+ }
+
+ErrRtn:
+ // dw is
+
+ LEDebugOut((DEB_ITRACE, "%p OUT OleStdGetAuxUserType ( %d )\n",
+ NULL, dw));
+
+ return (UINT)dw;
+}
+
+//REVIEW: these seem redundant, could the fns be mereged creatively?
+
+//+-------------------------------------------------------------------------
+//
+// Function:
+// XformWidthInPixelsToHimetric
+// XformWidthInHimetricToPixels
+// XformHeightInPixelsToHimetric
+// XformHeightInHimetricToPixels
+//
+// Synopsis:
+// Functions to convert an int between a device coordinate system and
+// logical HiMetric units.
+//
+// Effects:
+//
+// Arguments:
+//
+// [hDC] HDC providing reference to the pixel mapping. If
+// NULL, a screen DC is used.
+//
+// Size Functions:
+// [lpSizeSrc] LPSIZEL providing the structure to convert. This
+// contains pixels in XformSizeInPixelsToHimetric and
+// logical HiMetric units in the complement function.
+// [lpSizeDst] LPSIZEL providing the structure to receive converted
+// units. This contains pixels in
+// XformSizeInPixelsToHimetric and logical HiMetric
+// units in the complement function.
+//
+// Width Functions:
+// [iWidth] int containing the value to convert.
+//
+// Requires:
+//
+// Returns:
+// Size Functions: None
+// Width Functions: Converted value of the input parameters.
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port (initial)
+//
+// Notes:
+//
+// When displaying on the screen, Window apps display everything enlarged
+// from its actual size so that it is easier to read. For example, if an
+// app wants to display a 1in. horizontal line, that when printed is
+// actually a 1in. line on the printed page, then it will display the line
+// on the screen physically larger than 1in. This is described as a line
+// that is "logically" 1in. along the display width. Windows maintains as
+// part of the device-specific information about a given display device:
+// LOGPIXELSX -- no. of pixels per logical in along the display width
+// LOGPIXELSY -- no. of pixels per logical in along the display height
+//
+// The following formula converts a distance in pixels into its equivalent
+// logical HIMETRIC units:
+//
+// DistInHiMetric = (HIMETRIC_PER_INCH * DistInPix)
+// -------------------------------
+// PIXELS_PER_LOGICAL_IN
+//
+//
+// REVIEW32:: merge all these functions into one, as they all do
+// basically the same thing
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(int) XformWidthInPixelsToHimetric(HDC hDC, int iWidthInPix)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN XformWidthInPixelsToHimetric (%lx, %d)\n",
+ NULL, hDC, iWidthInPix));
+
+ int iXppli; // Pixels per logical inch along width
+ int iWidthInHiMetric;
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
+
+ // We got pixel units, convert them to logical HIMETRIC along
+ // the display
+ iWidthInHiMetric = MAP_PIX_TO_LOGHIM(iWidthInPix, iXppli);
+
+ if (fSystemDC)
+ {
+ ReleaseDC(NULL, hDC);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT XformWidthInPixelsToHimetric (%d)\n",
+ NULL, iWidthInHiMetric));
+
+ return iWidthInHiMetric;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: XformWidthInHimetricToPixels
+//
+// Synopsis: see XformWidthInPixelsToHimetric
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(int) XformWidthInHimetricToPixels(HDC hDC, int iWidthInHiMetric)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN XformWidthInHimetricToPixels (%lx, %d)\n",
+ NULL, hDC, iWidthInHiMetric));
+
+ int iXppli; //Pixels per logical inch along width
+ int iWidthInPix;
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
+
+ // We got logical HIMETRIC along the display, convert them to
+ // pixel units
+
+ iWidthInPix = MAP_LOGHIM_TO_PIX(iWidthInHiMetric, iXppli);
+
+ if (fSystemDC)
+ {
+ ReleaseDC(NULL, hDC);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT XformWidthInHimetricToPixels (%d)\n",
+ NULL, iWidthInPix));
+
+ return iWidthInPix;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: XformHeightInPixelsToHimetric
+//
+// Synopsis: see XformWidthInPixelsToHimetric
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(int) XformHeightInPixelsToHimetric(HDC hDC, int iHeightInPix)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN XformHeightInPixelsToHimetric (%lx, %d)\n",
+ NULL, hDC, iHeightInPix));
+
+ int iYppli; //Pixels per logical inch along height
+ int iHeightInHiMetric;
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iYppli = GetDeviceCaps (hDC, LOGPIXELSY);
+
+ // We got pixel units, convert them to logical HIMETRIC along the
+ // display
+ iHeightInHiMetric = MAP_PIX_TO_LOGHIM(iHeightInPix, iYppli);
+
+ if (fSystemDC)
+ {
+ ReleaseDC(NULL, hDC);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT XformHeightInPixelsToHimetric (%d)\n",
+ NULL, hDC, iHeightInHiMetric));
+
+ return iHeightInHiMetric;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: XformHeightInHimetricToPixels
+//
+// Synopsis: see XformWidthInPixelsToHimetric
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(int) XformHeightInHimetricToPixels(HDC hDC, int iHeightInHiMetric)
+{
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN XformHeightInHimetricToPixels (%lx, %d)\n",
+ NULL, hDC, iHeightInHiMetric));
+
+ int iYppli; //Pixels per logical inch along height
+ int iHeightInPix;
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iYppli = GetDeviceCaps (hDC, LOGPIXELSY);
+
+ // We got logical HIMETRIC along the display, convert them to pixel
+ // units
+ iHeightInPix = MAP_LOGHIM_TO_PIX(iHeightInHiMetric, iYppli);
+
+ if (fSystemDC)
+ {
+ ReleaseDC(NULL, hDC);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT XformHeightInHimetricToPixels (%d)\n",
+ NULL, hDC, iHeightInPix));
+
+ return iHeightInPix;
+}
diff --git a/private/ole32/ole232/stdimpl/icon.h b/private/ole32/ole232/stdimpl/icon.h
new file mode 100644
index 000000000..d8488d995
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/icon.h
@@ -0,0 +1,63 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: icon.h
+//
+// Contents: function declarations for manipulating icons (see icon.cpp)
+//
+// Classes:
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 24-Nov-93 alexgo 32bit port
+//
+//--------------------------------------------------------------------------
+
+#if !defined( _ICON_H )
+#define _ICON_H_
+
+#if !defined( IDS_DEFICONLABEL )
+#define IDS_DEFICONLABEL 310
+#endif
+
+STDAPI_(int) XformWidthInHimetricToPixels(HDC, int);
+STDAPI_(int) XformWidthInPixelsToHimetric(HDC, int);
+STDAPI_(int) XformHeightInHimetricToPixels(HDC, int);
+STDAPI_(int) XformHeightInPixelsToHimetric(HDC, int);
+
+HICON FAR PASCAL HIconAndSourceFromClass(REFCLSID, LPOLESTR,
+ UINT FAR *);
+
+BOOL FAR PASCAL FIconFileFromClass(REFCLSID, LPOLESTR, UINT,
+ UINT FAR *);
+
+LPOLESTR FAR PASCAL PointerToNthField(LPOLESTR, int, OLECHAR);
+
+BOOL FAR PASCAL GetAssociatedExecutable(LPOLESTR, LPOLESTR);
+
+STDAPI_(UINT) OleStdGetAuxUserType(REFCLSID rclsid,
+ WORD wAuxUserType,
+ LPOLESTR lpszAuxUserType,
+ int cch,
+ HKEY hKey);
+
+STDAPI_(UINT) OleStdGetUserTypeOfClass(REFCLSID rclsid,
+ LPOLESTR lpszUserType,
+ UINT cch,
+ HKEY hKey);
+
+STDAPI_(UINT) OleStdIconLabelTextOut(HDC hDC,
+ HFONT hFont,
+ int nXStart,
+ int nYStart,
+ UINT fuOptions,
+ RECT FAR * lpRect,
+ LPOLESTR lpszString,
+ UINT cchString,
+ int FAR * lpDX);
+
+#endif // _ICON_H
diff --git a/private/ole32/ole232/stdimpl/makefile b/private/ole32/ole232/stdimpl/makefile
new file mode 100644
index 000000000..1725b5e9a
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/makefile
@@ -0,0 +1,26 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1992.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/ole232/stdimpl/mf.cpp b/private/ole32/ole232/stdimpl/mf.cpp
new file mode 100644
index 000000000..d9b4b330f
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/mf.cpp
@@ -0,0 +1,2304 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: mf.cpp
+//
+// Contents: Implentation of hte metafile picture object
+//
+// Classes: CMfObject
+//
+// Functions: OleIsDcMeta
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH added Dump method to CMfObject
+// added DumpCMfObject API
+// initialize m_pfnContinue in constructor
+// 25-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocations.
+// 11-Jan-93 alexgo added VDATEHEAP macros to every
+// function and method
+// 31-Dec-93 ErikGav chicago port
+// 17-Dec-93 ChrisWe fixed second argument to SelectPalette calls
+// in CallbackFuncForDraw
+// 07-Dec-93 ChrisWe made default params to StSetSize explicit
+// 07-Dec-93 alexgo merged 16bit RC9 changes
+// 29-Nov-93 alexgo 32bit port
+// 04-Jun-93 srinik support for demand loading and discarding
+// of caches
+// 13-Mar-92 srinik created
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#include <qd2gdi.h>
+#include "mf.h"
+
+#ifdef _DEBUG
+#include <dbgdump.h>
+#endif // _DEBUG
+
+#define M_HPRES() (m_hPres ? m_hPres : LoadHPRES())
+
+/*
+ * IMPLEMENTATION of CMfObject
+ *
+ */
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::CMfObject
+//
+// Synopsis: constructor for the metafile object
+//
+// Effects:
+//
+// Arguments: [pCacheNode] -- pointer to the cache node for this object
+// [dwAspect] -- drawing aspect for the object
+// [fConvert] -- specifies whether to convert from Mac
+// QuickDraw format
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 13-Feb-95 t-ScottH initialize m_pfnContinue
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CMfObject::CMfObject(LPCACHENODE pCacheNode, DWORD dwAspect, BOOL fConvert)
+{
+ VDATEHEAP();
+
+ m_ulRefs = 1;
+ m_hPres = NULL;
+ m_dwSize = 0;
+ m_dwAspect = dwAspect;
+ m_pCacheNode = pCacheNode;
+ m_dwContinue = 0;
+ m_pfnContinue = NULL;
+ m_lWidth = 0;
+ m_lHeight = 0;
+
+ m_fConvert = fConvert;
+ m_pMetaInfo = NULL;
+ m_pCurMdc = NULL;
+ m_fMetaDC = FALSE;
+ m_nRecord = 0;
+ m_error = NOERROR;
+ m_pColorSet = NULL;
+
+ m_hPalDCOriginal = NULL;
+ m_hPalLast = NULL;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::~CMfObject
+//
+// Synopsis: Destroys a metafile presentation object
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CMfObject::~CMfObject (void)
+{
+ VDATEHEAP();
+
+ CMfObject::DiscardHPRES();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::QueryInterface
+//
+// Synopsis: returns supported interfaces
+//
+// Effects:
+//
+// Arguments: [iid] -- the requested interface ID
+// [ppvObj] -- where to put the interface pointer
+//
+// Requires:
+//
+// Returns: NOERROR, E_NOINTERFACE
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMfObject::QueryInterface (REFIID iid, void FAR* FAR* ppvObj)
+{
+ VDATEHEAP();
+
+ if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IOlePresObj))
+ {
+ *ppvObj = this;
+ AddRef();
+ return NOERROR;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::AddRef
+//
+// Synopsis: Increments the reference count
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CMfObject::AddRef(void)
+{
+ VDATEHEAP();
+
+ return ++m_ulRefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::Release
+//
+// Synopsis: decrements the reference count
+//
+// Effects: deletes the object once the ref count goes to zero
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CMfObject::Release(void)
+{
+ VDATEHEAP();
+
+ if (--m_ulRefs == 0) {
+ delete this;
+ return 0;
+ }
+
+ return m_ulRefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::GetData
+//
+// Synopsis: Retrieves data in the specified format from the object
+//
+// Effects:
+//
+// Arguments: [pformatetcIn] -- the requested data format
+// [pmedium] -- where to put the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObject
+//
+// Algorithm: Does error checking and then gets a copy of the metafilepict
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMfObject::GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
+{
+ VDATEHEAP();
+
+ SCODE sc;
+
+ // null out in case of error
+ pmedium->tymed = (DWORD) TYMED_NULL;
+ pmedium->pUnkForRelease = NULL;
+
+ if (!(pformatetcIn->tymed & (DWORD) TYMED_MFPICT))
+ {
+ sc = DV_E_TYMED;
+ }
+ else if (pformatetcIn->cfFormat != CF_METAFILEPICT)
+ {
+ sc = DV_E_CLIPFORMAT;
+ }
+ else if (IsBlank())
+ {
+ sc = OLE_E_BLANK;
+ }
+ // here we actually try to get the data
+ else if (NULL == (pmedium->hGlobal = GetHmfp()))
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else {
+ pmedium->tymed = (DWORD) TYMED_MFPICT;
+ return NOERROR;
+ }
+
+ return ResultFromScode(sc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::GetDataHere
+//
+// Synopsis: Retrieves data of the specified format into the specified
+// medium
+//
+// Effects:
+//
+// Arguments: [pformatetcIn] -- the requested data format
+// [pmedium] -- where to put the data
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm: Does error checking and then copies the metafile into a
+// stream.
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMfObject::GetDataHere
+ (LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
+{
+ VDATEHEAP();
+
+ SCODE sc;
+
+ if (pformatetcIn->cfFormat != CF_METAFILEPICT)
+ {
+ sc = DV_E_CLIPFORMAT;
+ }
+ else if (pmedium->tymed != (DWORD) TYMED_ISTREAM)
+ {
+ sc = DV_E_TYMED;
+ }
+ else if (pmedium->pstm == NULL)
+ {
+ sc = E_INVALIDARG;
+ }
+ else if (IsBlank())
+ {
+ sc = OLE_E_BLANK;
+ }
+ else
+ {
+ HANDLE hpres = M_HPRES();
+ return UtHMFToPlaceableMFStm(&hpres, m_dwSize, m_lWidth,
+ m_lHeight, pmedium->pstm);
+ }
+
+ return ResultFromScode(sc);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::SetDataWDO
+//
+// Synopsis: Stores a metafile in this object
+//
+// Effects:
+//
+// Arguments: [pformatetc] -- format of the data coming in
+// [pmedium] -- the new metafile (data)
+// [fRelease] -- if true, then we'll release the [pmedium]
+// [pDataObj] -- unused for MF objects
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm: does error checking and then stores the new data.
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMfObject::SetDataWDO (LPFORMATETC pformatetc,
+ STGMEDIUM * pmedium,
+ BOOL fRelease,
+ IDataObject * /* UNUSED */)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ BOOL fTakeData = FALSE;
+
+ if (pformatetc->cfFormat != CF_METAFILEPICT)
+ {
+ return ResultFromScode(DV_E_CLIPFORMAT);
+ }
+
+ if (pmedium->tymed != (DWORD) TYMED_MFPICT)
+ {
+ return ResultFromScode(DV_E_TYMED);
+ }
+
+ if ((pmedium->pUnkForRelease == NULL) && fRelease)
+ {
+ // we can take the ownership of the data
+ fTakeData = TRUE;
+ }
+
+ // ChangeData will keep the data if fRelease is TRUE, else it copies
+ error = ChangeData (pmedium->hGlobal, fTakeData);
+
+ if (fTakeData)
+ {
+ pmedium->tymed = (DWORD) TYMED_NULL;
+ }
+ else if (fRelease)
+ {
+ ReleaseStgMedium(pmedium);
+ }
+
+ return error;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::GetHmfp (internal)
+//
+// Synopsis: Gets a copy of the stored metafile presentation
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HANDLE
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(HANDLE) CMfObject::GetHmfp (void)
+{
+ VDATEHEAP();
+
+ return UtGetHMFPICT((HMETAFILE)GetCopyOfHPRES(), TRUE, m_lWidth,
+ m_lHeight);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::ChangeData (internal)
+//
+// Synopsis: Swaps the stored metafile presentation
+//
+// Effects:
+//
+// Arguments: [hMfp] -- the new metafile
+// [fDelete] -- if TRUE, then delete [hMfp]
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port, fixed GlobalUnlock bug
+// Notes:
+//
+// If the routine fails then the object will be left with it's old data.
+// If fDelete is TRUE, then hMeta, and the hMF it contains will be deleted
+// whether the routine is successful or not.
+//
+//--------------------------------------------------------------------------
+
+INTERNAL CMfObject::ChangeData (HANDLE hMfp, BOOL fDelete)
+{
+ VDATEHEAP();
+
+
+ HANDLE hNewMF;
+ LPMETAFILEPICT lpMetaPict;
+ DWORD dwSize;
+ HRESULT error = NOERROR;
+
+ if ((lpMetaPict = (LPMETAFILEPICT) GlobalLock (hMfp)) == NULL)
+ {
+ if (fDelete)
+ {
+ LEVERIFY( NULL == GlobalFree (hMfp) );
+ }
+ return E_OUTOFMEMORY;
+ }
+
+ if (!fDelete) {
+ if (NULL == (hNewMF = CopyMetaFile (lpMetaPict->hMF, NULL)))
+ {
+ return E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ hNewMF = lpMetaPict->hMF;
+ }
+
+
+ if (lpMetaPict->mm != MM_ANISOTROPIC)
+ {
+ error = ResultFromScode(E_UNSPEC);
+ LEWARN( error, "Mapping mode is not anisotropic" );
+
+ }
+ else if (0 == (dwSize = MfGetSize (&hNewMF)))
+ {
+ error = ResultFromScode(OLE_E_BLANK);
+ }
+ else
+ {
+ if (m_hPres)
+ {
+ LEVERIFY( DeleteMetaFile (m_hPres) );
+ }
+ m_hPres = (HMETAFILE)hNewMF;
+ m_dwSize = dwSize;
+ m_lWidth = lpMetaPict->xExt;
+ m_lHeight = lpMetaPict->yExt;
+ }
+
+ GlobalUnlock (hMfp);
+
+ if (error != NOERROR)
+ {
+ LEVERIFY( DeleteMetaFile ((HMETAFILE)hNewMF) );
+ }
+
+ if (fDelete)
+ {
+ LEVERIFY( NULL == GlobalFree (hMfp) );
+ }
+
+ return error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::Draw
+//
+// Synopsis: Draws the stored presentation
+//
+// Effects:
+//
+// Arguments: [pvAspect] -- the drawing aspect
+// [hicTargetDev] -- the target device
+// [hdcDraw] -- hdc to draw into
+// [lprcBounds] -- bounding rectangle to draw into
+// [lprcWBounds] -- bounding rectangle for the metafile
+// [pfnContinue] -- function to call while drawing
+// [dwContinue] -- parameter to [pfnContinue]
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm: Sets the viewport and metafile boundaries, then plays
+// the metafile
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMfObject::Draw (void * /* UNUSED pvAspect */,
+ HDC /* UNUSED hicTargetDev */,
+ HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ BOOL (CALLBACK * pfnContinue)(DWORD),
+ DWORD dwContinue)
+{
+ VDATEHEAP();
+
+ m_error = NOERROR;
+
+ int iRgn;
+ int iOldDc;
+ RECT rect;
+ LPRECT lpRrc = (LPRECT) &rect;
+
+ Assert(lprcBounds);
+
+ if (!M_HPRES())
+ {
+ return ResultFromScode(OLE_E_BLANK);
+ }
+
+ rect.left = lprcBounds->left;
+ rect.right = lprcBounds->right;
+ rect.top = lprcBounds->top;
+ rect.bottom = lprcBounds->bottom;
+
+ iOldDc = SaveDC (hdcDraw);
+ if (0 == iOldDc)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ m_nRecord = RECORD_COUNT;
+ m_fMetaDC = OleIsDcMeta (hdcDraw);
+
+ if (!m_fMetaDC) {
+ iRgn = IntersectClipRect (hdcDraw, lpRrc->left, lpRrc->top,
+ lpRrc->right, lpRrc->bottom);
+ Assert( ERROR != iRgn );
+
+ if (iRgn == NULLREGION) {
+ goto errRtn;
+ }
+ if (iRgn == ERROR) {
+ m_error = ResultFromScode(E_UNSPEC);
+ goto errRtn;
+ }
+
+
+ // Because the LPToDP conversion takes the current world
+ // transform into consideration, we must check to see
+ // if we are in a GM_ADVANCED device context. If so,
+ // save its state and reset to GM_COMPATIBLE while we
+ // convert LP to DP (then restore the DC).
+
+ if (GM_ADVANCED == GetGraphicsMode(hdcDraw))
+ {
+ HDC screendc = GetDC(NULL);
+ RECT rect = {0, 0, 1000, 1000};
+ HDC emfdc = CreateEnhMetaFile(screendc, NULL, &rect, NULL);
+ PlayMetaFile( emfdc, m_hPres);
+ HENHMETAFILE hemf = CloseEnhMetaFile(emfdc);
+ PlayEnhMetaFile( hdcDraw, hemf, lpRrc);
+ DeleteEnhMetaFile( hemf );
+
+ goto errRtn;
+ }
+ else
+ {
+ LEVERIFY( LPtoDP (hdcDraw, (LPPOINT) lpRrc, 2) );
+ }
+
+ LEVERIFY( 0 != SetMapMode (hdcDraw, MM_ANISOTROPIC) );
+ LEVERIFY( SetViewportOrg (hdcDraw, lpRrc->left, lpRrc->top) );
+ LEVERIFY( SetViewportExt (hdcDraw, lpRrc->right - lpRrc->left,
+ lpRrc->bottom - lpRrc->top) );
+
+ }
+ else
+ {
+ iOldDc = -1;
+
+ if (!lprcWBounds)
+ {
+ return ResultFromScode(E_DRAW);
+ }
+
+ m_pMetaInfo = (LPMETAINFO)PrivMemAlloc(sizeof(METAINFO));
+ if( !m_pMetaInfo )
+ {
+ AssertSz(m_pMetaInfo, "Memory allocation failed");
+ m_error = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ m_pCurMdc = (LPMETADC) (m_pMetaInfo);
+
+ m_pMetaInfo->xwo = lprcWBounds->left;
+ m_pMetaInfo->ywo = lprcWBounds->top;
+ m_pMetaInfo->xwe = lprcWBounds->right;
+ m_pMetaInfo->ywe = lprcWBounds->bottom;
+
+ m_pMetaInfo->xro = lpRrc->left - lprcWBounds->left;
+ m_pMetaInfo->yro = lpRrc->top - lprcWBounds->top;
+
+ m_pCurMdc->xre = lpRrc->right - lpRrc->left;
+ m_pCurMdc->yre = lpRrc->bottom - lpRrc->top;
+ m_pCurMdc->xMwo = 0;
+ m_pCurMdc->yMwo = 0;
+ m_pCurMdc->xMwe = 0;
+ m_pCurMdc->yMwe = 0;
+ m_pCurMdc->pNext = NULL;
+ }
+
+ m_pfnContinue = pfnContinue;
+ m_dwContinue = dwContinue;
+
+ // m_hPalDCOriginal and m_hPalLast are used to clean up any
+ // palettes that are selected into a DC during the metafile
+ // enumeration.
+ m_hPalDCOriginal = NULL;
+ m_hPalLast = NULL;
+
+ LEVERIFY( EnumMetaFile(hdcDraw, m_hPres, MfCallbackFuncForDraw,
+ (LPARAM) this) );
+
+ if (m_fMetaDC)
+ {
+ CleanStack();
+
+ }
+
+ // if m_hPalLast exists at this point, we have duped a palette
+ // and it needs to be freed.
+ if (m_hPalLast)
+ {
+ HPALETTE hPalTemp;
+
+ // when calling SelectPalette on a Metafile DC, the old
+ // palette is not returned. We need to select another
+ // palette into the metafile DC so DeleteObject can be
+ // called. To do this, we will use the stock palette.
+ if (m_fMetaDC)
+ {
+ hPalTemp = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
+ }
+ else
+ {
+ // Get the original palette selected in the DC.
+ hPalTemp = m_hPalDCOriginal;
+ }
+
+ // hPalTemp could be NULL...
+
+ if (hPalTemp)
+ {
+ // BUGBUG: Should this palette be selected in the
+ // foreground?
+ SelectPalette(hdcDraw, hPalTemp, TRUE);
+ }
+
+ DeleteObject(m_hPalLast);
+ }
+
+ m_fMetaDC = FALSE;
+
+errRtn:
+
+ LEVERIFY( RestoreDC (hdcDraw, iOldDc) );
+ return m_error;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::GetColorSet
+//
+// Synopsis: Retrieves the logical palette associated with the metafile
+//
+// Effects:
+//
+// Arguments: [pvAspect] -- the drawing aspect
+// [hicTargetDev] -- target device
+// [ppColorSet] -- where to put the logical palette pointer
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm: Plays the metafile into a new metafile. The play callback
+// function stores the metafile palette which is then returned.
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+STDMETHODIMP CMfObject::GetColorSet (LPVOID /* UNUSED pvAspect */,
+ HDC /* UNUSED hicTargetDev */,
+ LPLOGPALETTE * ppColorSet)
+{
+ VDATEHEAP();
+
+ if (IsBlank() || !M_HPRES())
+ {
+ return ResultFromScode(OLE_E_BLANK);
+ }
+
+ m_pColorSet = NULL;
+
+ HDC hdcMeta = CreateMetaFile(NULL);
+ if (NULL == hdcMeta)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ m_error = NOERROR;
+
+
+ LEVERIFY( EnumMetaFile(hdcMeta, m_hPres, MfCallbackFuncForGetColorSet,
+ (LPARAM) this) );
+
+ LEVERIFY( CloseMetaFile(hdcMeta) );
+
+ if( m_error != NOERROR )
+ {
+ return m_error;
+ }
+
+ if ((*ppColorSet = m_pColorSet) == NULL)
+ {
+ return ResultFromScode(S_FALSE);
+ }
+
+ return NOERROR;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: MfCallBackFunForDraw
+//
+// Synopsis: callback function for drawing metafiles -- call's the caller's
+// draw method (via a passed in this pointer)
+//
+// Effects:
+//
+// Arguments: [hdc] -- the device context
+// [lpHTable] -- pointer to the MF handle table
+// [lpMFR] -- pointer to metafile record
+// [nObj] -- number of objects
+//
+// Requires:
+//
+// Returns: non-zero to continue, zero stops the drawing
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+int CALLBACK __loadds MfCallbackFuncForDraw
+ (HDC hdc, HANDLETABLE FAR* lpHTable, METARECORD FAR* lpMFR, int nObj,
+ LPARAM lpobj)
+{
+ VDATEHEAP();
+
+ return ((CMfObject FAR*) lpobj)->CallbackFuncForDraw(hdc, lpHTable,
+ lpMFR, nObj);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: MfCallbackFuncForGetColorSet
+//
+// Synopsis: callback function for grabbing the palette from a metafile
+//
+// Effects:
+//
+// Arguments: [hdc] -- the device context
+// [lpHTable] -- pointer to the MF handle table
+// [lpMFR] -- pointer to metafile record
+// [nObj] -- number of objects
+//
+// Requires:
+//
+// Returns: non-zero to continue, zero stops the drawing
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+int CALLBACK __loadds MfCallbackFuncForGetColorSet
+ (HDC hdc, HANDLETABLE FAR* lpHTable, METARECORD FAR* lpMFR, int nObj,
+ LPARAM lpobj)
+{
+ VDATEHEAP();
+
+ return ((CMfObject FAR*) lpobj)->CallbackFuncForGetColorSet(hdc, lpHTable,
+ lpMFR, nObj);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::CallbackFuncForGetColorSet
+//
+// Synopsis: Merges all the color palettes in the metafile into
+// one palette (called when GetColorSet enumerates the metafile)
+//
+// Effects:
+//
+// Arguments: [hdc] -- the device context
+// [lpHTable] -- pointer to the MF handle table
+// [lpMFR] -- pointer to metafile record
+// [nObj] -- number of objects
+//
+// Requires:
+//
+// Returns: non-zero to continue, zero stops the drawing
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+int CMfObject::CallbackFuncForGetColorSet(HDC /* UNUSED hdc */,
+ LPHANDLETABLE /* UNUSED lpHTable */,
+ LPMETARECORD lpMFR,
+ int /* UNUSED nObj */)
+{
+ VDATEHEAP();
+
+ if (lpMFR->rdFunction == META_CREATEPALETTE)
+ {
+ LPLOGPALETTE lplogpal = (LPLOGPALETTE) &(lpMFR->rdParm[0]);
+ UINT uPalSize = (lplogpal->palNumEntries) *
+ sizeof(PALETTEENTRY)
+ + 2 * sizeof(WORD);
+
+ if (m_pColorSet == NULL)
+ {
+ // This is the first CreatePalette record.
+
+ m_pColorSet = (LPLOGPALETTE)PubMemAlloc(uPalSize);
+ if(NULL == m_pColorSet)
+ {
+ m_error = ResultFromScode(E_OUTOFMEMORY);
+ return FALSE;
+ }
+ _xmemcpy(m_pColorSet, lplogpal, (size_t) uPalSize);
+ }
+
+ // if we hit more than one CreatePalette record then, we need to
+ // merge those palette records.
+
+ // REVIEW32::BUGBUG:: err, we don't ever seem to do this
+ // mergeing referred to above :(
+ }
+
+ return TRUE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::CallbackFuncForDraw
+//
+// Synopsis: Draws the metafile
+//
+// Effects:
+//
+// Arguments: [hdc] -- the device context
+// [lpHTable] -- pointer to the MF handle table
+// [lpMFR] -- pointer to metafile record
+// [nObj] -- number of objects
+//
+// Requires:
+//
+// Returns: non-zero to continue, zero stops the drawing
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 17-Dec-93 ChrisWe fixed second argument to SelectPalette calls
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+int CMfObject::CallbackFuncForDraw
+ (HDC hdc, LPHANDLETABLE lpHTable, LPMETARECORD lpMFR, int nObj)
+{
+ VDATEHEAP();
+
+
+ if (!--m_nRecord)
+ {
+ m_nRecord = RECORD_COUNT;
+
+ if (m_pfnContinue && !((*(m_pfnContinue))(m_dwContinue)))
+ {
+ m_error = ResultFromScode(E_ABORT);
+ return FALSE;
+ }
+ }
+
+ if (m_fMetaDC)
+ {
+ switch (lpMFR->rdFunction)
+ {
+ case META_SETWINDOWORG:
+ SetPictOrg (hdc, (SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0],
+ FALSE);
+ return TRUE;
+
+ case META_OFFSETWINDOWORG:
+ SetPictOrg (hdc, (SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0],
+ TRUE);
+ return TRUE;
+
+ case META_SETWINDOWEXT:
+ SetPictExt (hdc, (SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0]);
+ return TRUE;
+
+ case META_SCALEWINDOWEXT:
+ ScalePictExt (hdc, (SHORT)lpMFR->rdParm[3], (SHORT)lpMFR->rdParm[2],
+ (SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0]);
+ return TRUE;
+
+ case META_SCALEVIEWPORTEXT:
+ ScaleRectExt (hdc, (SHORT)lpMFR->rdParm[3], (SHORT)lpMFR->rdParm[2],
+ (SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0]);
+ return TRUE;
+
+ case META_SAVEDC:
+ {
+ BOOL fSucceeded = PushDc();
+ LEVERIFY( fSucceeded );
+ if (!fSucceeded)
+ return FALSE;
+ break;
+ }
+
+ case META_RESTOREDC:
+ LEVERIFY( PopDc() );
+ break;
+
+ case META_SELECTPALETTE:
+ {
+ // All selectpalette records are recorded such that the
+ // palette is rendered in foreground mode. Rather than
+ // allowing the record to play out in this fashion, we
+ // grab the handle and select it ourselves, forcing it
+ // to background (using colors already mapped in the DC)
+
+ // Dupe the palette.
+ HPALETTE hPal = UtDupPalette((HPALETTE) lpHTable->objectHandle[lpMFR->rdParm[0]]);
+
+ // Select the dupe into the DC. EnumMetaFile calls DeleteObject
+ // on the palette handle in the metafile handle table. If that
+ // palette is currently selected into a DC, we rip and leak the
+ // resource.
+ LEVERIFY( NULL != SelectPalette(hdc, hPal, TRUE) );
+
+ // if we had previously saved a palette, we need to delete
+ // it (for the case of multiple SelectPalette calls in a
+ // MetaFile).
+ if (m_hPalLast)
+ {
+ DeleteObject(m_hPalLast);
+ }
+
+ // remember our duped palette so that it can be properly destroyed
+ // later.
+ m_hPalLast = hPal;
+
+ return TRUE;
+ }
+
+ case META_OFFSETVIEWPORTORG:
+ AssertSz(0, "OffsetViewportOrg() in metafile");
+ return TRUE;
+
+ case META_SETVIEWPORTORG:
+ AssertSz(0, "SetViewportOrg() in metafile");
+ return TRUE;
+
+ case META_SETVIEWPORTEXT:
+ AssertSz(0, "SetViewportExt() in metafile");
+ return TRUE;
+
+ case META_SETMAPMODE:
+ AssertSz(lpMFR->rdParm[0] == MM_ANISOTROPIC,
+ "SetmapMode() in metafile with invalid mapping mode");
+ return TRUE;
+
+ default:
+ break;
+ }
+ }
+ else
+ { // non-metafile DC. (ScreenDC or other DC...)
+
+ if (lpMFR->rdFunction == META_SELECTPALETTE)
+ {
+ // All selectpalette records are recorded such that the
+ // palette is rendered in foreground mode. Rather than
+ // allowing the record to play out in this fashion, we
+ // grab the handle and select it ourselves, forcing it
+ // to background (using colors already mapped in the DC)
+
+
+ HPALETTE hPal = UtDupPalette((HPALETTE) lpHTable->objectHandle[lpMFR->rdParm[0]]);
+
+ HPALETTE hPalOld = SelectPalette(hdc, hPal, TRUE);
+
+ if (!m_hPalDCOriginal)
+ {
+ m_hPalDCOriginal = hPalOld;
+ }
+ else
+ {
+ // This case gets hit if we have already stored
+ // the original palette from the DC. This means
+ // that hPalOld is a palette we have created using
+ // UtDupPal above. This means we need to delete
+ // the old palette and remember the new one.
+ DeleteObject(hPalOld);
+ }
+
+ m_hPalLast = hPal;
+
+ return TRUE;
+ }
+ }
+
+ LEVERIFY( PlayMetaFileRecord (hdc, lpHTable, lpMFR, (unsigned) nObj) );
+ return TRUE;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::SetPictOrg (private)
+//
+// Synopsis: Sets the hdc's origin via SetWindowOrg
+//
+// Effects:
+//
+// Arguments: [hdc] -- the device context
+// [xOrg] -- the x origin
+// [yOrg] -- the y origin
+// [fOffset] -- if TRUE, [xOrg] and [yOrg] are offsets
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 alexgo 32bit port
+//
+// Notes: used by the metafile interpreter
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CMfObject::SetPictOrg
+ (HDC hdc, int xOrg, int yOrg, BOOL fOffset)
+{
+ VDATEHEAP();
+
+ if (fOffset)
+ {
+
+ m_pCurMdc->xMwo += xOrg;
+ m_pCurMdc->yMwo += yOrg;
+ }
+ else
+ {
+ m_pCurMdc->xMwo = xOrg;
+ m_pCurMdc->yMwo = yOrg;
+ }
+
+ if (m_pCurMdc->xMwe && m_pCurMdc->yMwe)
+ {
+ LEVERIFY ( SetWindowOrg (hdc, // Review (davepl) MEIN GOT!
+ (m_pCurMdc->xMwo -
+ MulDiv (m_pMetaInfo->xro, m_pCurMdc->xMwe,
+ m_pCurMdc->xre)),
+ (m_pCurMdc->yMwo -
+ MulDiv (m_pMetaInfo->yro, m_pCurMdc->yMwe,
+ m_pCurMdc->yre))) );
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::SetPictExt
+//
+// Synopsis: Sets teh metafile's extents
+//
+// Effects:
+//
+// Arguments: [hdc] -- the device context
+// [xExt] -- the X-extent
+// [yExt] -- the Y-extent
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes: used by the metafile interpreter
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CMfObject::SetPictExt (HDC hdc, int xExt, int yExt)
+{
+ VDATEHEAP();
+
+ m_pCurMdc->xMwe = xExt;
+ m_pCurMdc->yMwe = yExt;
+
+ Assert( m_pCurMdc->xre && m_pCurMdc->yre );
+
+ int xNewExt = MulDiv (m_pMetaInfo->xwe, xExt, m_pCurMdc->xre);
+ int yNewExt = MulDiv (m_pMetaInfo->ywe, yExt, m_pCurMdc->yre);
+
+ int xNewOrg = m_pCurMdc->xMwo
+ - MulDiv (m_pMetaInfo->xro, xExt, m_pCurMdc->xre);
+ int yNewOrg = m_pCurMdc->yMwo
+ - MulDiv (m_pMetaInfo->yro, yExt, m_pCurMdc->yre);
+
+ LEVERIFY( SetWindowExt (hdc, xNewExt, yNewExt) );
+ LEVERIFY( SetWindowOrg (hdc, xNewOrg, yNewOrg) );
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::ScalePictExt
+//
+// Synopsis: Scales the metafile
+//
+// Effects:
+//
+// Arguments: [hdc] -- the device context
+// [xNum] -- the x numerator
+// [xDenom] -- the x demominator
+// [yNum] -- the y numberator
+// [yDenom] -- the y demoninator
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes: used by the metafile interpreter
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CMfObject::ScalePictExt (HDC hdc,
+ int xNum,
+ int xDenom,
+ int yNum,
+ int yDenom)
+{
+ VDATEHEAP();
+
+ Assert( xDenom && yDenom );
+
+ int xNewExt = MulDiv (m_pCurMdc->xMwe, xNum, xDenom);
+ int yNewExt = MulDiv (m_pCurMdc->yMwe, yNum, yDenom);
+
+ SetPictExt(hdc, xNewExt, yNewExt);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::ScaleRectExt
+//
+// Synopsis: scales the viewport
+//
+// Effects:
+//
+// Arguments: [hdc] -- the device context
+// [xNum] -- the x numerator
+// [xDenom] -- the x demominator
+// [yNum] -- the y numberator
+// [yDenom] -- the y demoninator
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes: Used by the metafile interpreter
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CMfObject::ScaleRectExt(HDC hdc,
+ int xNum,
+ int xDenom,
+ int yNum,
+ int yDenom)
+{
+ VDATEHEAP();
+
+ AssertSz( xDenom, "Denominator is 0 for x-rect scaling");
+ AssertSz( yDenom, "Denominator is 0 for y-rect scaling");
+
+ m_pCurMdc->xre = MulDiv (m_pCurMdc->xre, xNum, xDenom);
+ m_pCurMdc->yre = MulDiv (m_pCurMdc->yre, yNum, yDenom);
+
+ SetPictExt (hdc, m_pCurMdc->xMwe, m_pCurMdc->yMwe);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::PushDC
+//
+// Synopsis: pushes metafile info onto a stack
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: BOOL -- TRUE if successful, FALSE otherwise
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes: Used by the metafile interpreter engine.
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(BOOL) CMfObject::PushDc (void)
+{
+ VDATEHEAP();
+
+ LPMETADC pNode = NULL;
+
+ pNode = (LPMETADC) PrivMemAlloc(sizeof(METADC));
+
+ if (pNode)
+ {
+ *pNode = *m_pCurMdc;
+ m_pCurMdc->pNext = pNode;
+ pNode->pNext = NULL;
+ m_pCurMdc = pNode;
+ return TRUE;
+ }
+
+ m_error = ResultFromScode(E_OUTOFMEMORY);
+ return FALSE;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::PopDC
+//
+// Synopsis: pops metafile info from the metafile info stack
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: BOOL -- TRUE if successful, FALSE otherwise (more pops
+// than pushes)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes: used in the metafile interpreter
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(BOOL) CMfObject::PopDc (void)
+{
+ VDATEHEAP();
+
+ LPMETADC pPrev = (LPMETADC) (m_pMetaInfo);
+ LPMETADC pCur = ((LPMETADC) (m_pMetaInfo))->pNext;
+
+ if (NULL == pCur)
+ {
+ LEWARN( NULL == pCur, "More pops than pushes from DC stack" );
+ return FALSE;
+ }
+
+ while (pCur->pNext)
+ {
+ pPrev = pCur;
+ pCur = pCur->pNext;
+ }
+
+ if (pCur)
+ {
+ PrivMemFree(pCur);
+ }
+
+ pPrev->pNext = NULL;
+ m_pCurMdc = pPrev;
+
+ return TRUE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::CleanStack
+//
+// Synopsis: Deletes the stack of metafile info
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes: used in the metafile interpreter
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(void) CMfObject::CleanStack (void)
+{
+ VDATEHEAP();
+
+ LPMETADC pCur;
+
+ while (NULL != (pCur = ((LPMETADC) (m_pMetaInfo))->pNext))
+ {
+ ((LPMETADC) (m_pMetaInfo))->pNext = pCur->pNext;
+ PrivMemFree(pCur);
+ }
+
+ PrivMemFree(m_pMetaInfo);
+
+ m_pCurMdc = NULL;
+ m_pMetaInfo = NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: QD2GDI
+//
+// Synopsis: Converts macintosh pictures to Win32 GDI metafiles
+//
+// Effects:
+//
+// Arguments: [hBits] -- handle to the mac picture bits
+//
+// Requires:
+//
+// Returns: HMETAFILE
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Loads ole2conv.dll and calls QD2GDI in that dll
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+FARINTERNAL_(HMETAFILE) QD2GDI (HANDLE hBits)
+{
+ VDATEHEAP();
+
+ USERPREFS userPrefs =
+ {
+ {'Q','D','2','G','D','I'}, //signature
+ 2, //structure version number
+ sizeof(USERPREFS), //structure size
+ NULL, //source filename
+ NULL, //or source handle
+ NULL, //returned memory-based
+ //metafile
+ 3, //simulated pattern lines
+ 5, //use max dimension
+ //non-squarer pen
+ 1, //arithmetic transfer
+ 1, //create opaque text
+ 1, //simulate non-rectangular
+ //regions
+ 0, //don't optimize for PowerPoint
+ {0,0,0,0,0,0} //reserved
+ };
+
+
+
+ HINSTANCE hinstFilter;
+ void (FAR PASCAL *qd2gdiPtr)( USERPREFS FAR *, PICTINFO FAR *);
+ PICTINFO pictinfo;
+
+ hinstFilter = LoadLibrary(OLESTR("OLECNV32.DLL"));
+
+#if 0
+ //REVIEW:CHICAGO
+
+ //HINSTANCE_ERROR not defined in chicago
+
+ if (hinstFilter < (HINSTANCE)HINSTANCE_ERROR)
+ {
+ return NULL;
+ }
+#endif
+
+ if (hinstFilter == NULL)
+ {
+ return NULL;
+ }
+
+ *((FARPROC*)&qd2gdiPtr) = GetProcAddress(hinstFilter, "QD2GDI");
+
+ userPrefs.sourceFilename = NULL;
+ userPrefs.sourceHandle = hBits;
+ pictinfo.hmf = NULL;
+
+ if (qd2gdiPtr == NULL)
+ {
+ goto errRtn;
+ }
+
+ (*qd2gdiPtr)( (USERPREFS FAR *)&userPrefs, (PICTINFO FAR *)&pictinfo);
+
+errRtn:
+ LEVERIFY( FreeLibrary(hinstFilter) );
+ return (HMETAFILE)pictinfo.hmf;
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: MfGetSize
+//
+// Synopsis: Returns the size of a metafile
+//
+// Effects:
+//
+// Arguments: [lphmf] -- pointer to the metafile handle
+//
+// Requires:
+//
+// Returns: DWORD -- the size of the metafile
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(DWORD) MfGetSize (LPHANDLE lphmf)
+{
+ VDATEHEAP();
+
+ return GetMetaFileBitsEx((HMETAFILE)*lphmf,0,NULL);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleIsDcMeta
+//
+// Synopsis: Returns whether a device context is really a metafile
+//
+// Effects:
+//
+// Arguments: [hdc] -- the device context
+//
+// Requires:
+//
+// Returns: BOOL (TRUE if a metafile)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(BOOL) OleIsDcMeta (HDC hdc)
+{
+ VDATEHEAP();
+
+ return (GetDeviceCaps (hdc, TECHNOLOGY) == DT_METAFILE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::Load
+//
+// Synopsis: Loads an metafile object from the given stream
+//
+// Effects:
+//
+// Arguments: [lpstream] -- the stream from which to load
+// [fReadHeaderOnly] -- if TRUE, then only the header is
+// read
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMfObject::Load(LPSTREAM lpstream, BOOL fReadHeaderOnly)
+{
+ VDATEHEAP();
+
+ DWORD dwBuf[4];
+ HRESULT error;
+
+ /* read dwCompression, width, height, size of data */
+ error = StRead(lpstream, dwBuf, 4*sizeof(DWORD));
+ if (error)
+ {
+ return error;
+ }
+
+ AssertSz (dwBuf[0] == 0, "Picture compression factor is non-zero");
+
+ m_lWidth = (LONG) dwBuf[1];
+ m_lHeight = (LONG) dwBuf[2];
+ m_dwSize = dwBuf[3];
+
+ if (!m_dwSize || fReadHeaderOnly)
+ {
+ return NOERROR;
+ }
+
+ return UtGetHMFFromMFStm(lpstream, m_dwSize, m_fConvert,
+ (LPLPVOID) &m_hPres);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::Save
+//
+// Synopsis: Saves the metafile to the given stream
+//
+// Effects:
+//
+// Arguments: [lpstream] -- the stream to save to
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMfObject::Save(LPSTREAM lpstream)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ DWORD dwBuf[4];
+
+ /* write dwCompression, width, height, size of data */
+
+ dwBuf[0] = 0L;
+ dwBuf[1] = (DWORD) m_lWidth;
+ dwBuf[2] = (DWORD) m_lHeight;
+ dwBuf[3] = m_dwSize;
+
+ error = StWrite(lpstream, dwBuf, sizeof(dwBuf));
+ if (error)
+ {
+ return error;
+ }
+
+
+ // if blank object, don't write any more; no error.
+ if (IsBlank() || m_hPres == NULL)
+ {
+ StSetSize(lpstream, 0, TRUE);
+ return NOERROR;
+ }
+
+ return UtHMFToMFStm((LPLPVOID)&m_hPres, m_dwSize, lpstream);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::GetExtent
+//
+// Synopsis: Retrieves the extents of the metafile
+//
+// Effects:
+//
+// Arguments: [dwDrawAspect] -- the drawing aspect we're interested in
+// (must match the aspect of the current
+// metafile)
+// [lpsizel] -- where to put the extent info
+//
+// Requires:
+//
+// Returns: NOERROR, DV_E_DVASPECT, OLE_E_BLANK
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMfObject::GetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel)
+{
+ VDATEHEAP();
+
+ if (0 == (dwDrawAspect & m_dwAspect))
+ {
+ return ResultFromScode(DV_E_DVASPECT);
+ }
+
+ if (IsBlank())
+ {
+ return ResultFromScode(OLE_E_BLANK);
+ }
+
+ lpsizel->cx = m_lWidth;
+ lpsizel->cy = m_lHeight;
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::IsBlank
+//
+// Synopsis: Returns whether or not the metafile is blank
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: TRUE/FALSE
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(BOOL) CMfObject::IsBlank(void)
+{
+ VDATEHEAP();
+
+ return (m_dwSize ? FALSE : TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::LoadHPRES (private)
+//
+// Synopsis: Loads the presentation from the cache's stream and returns
+// a handle to it
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HANDLE to the metafile
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+INTERNAL_(HANDLE) CMfObject::LoadHPRES(void)
+{
+ VDATEHEAP();
+
+ LPSTREAM pstm;
+
+ pstm = m_pCacheNode->GetStm(TRUE /*fSeekToPresBits*/, STGM_READ);
+ if (pstm)
+ {
+ LEVERIFY( SUCCEEDED(Load(pstm)));
+ pstm->Release();
+ }
+
+ return m_hPres;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::DiscardHPRES
+//
+// Synopsis: deletes the stored metafile
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IOlePresObj
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CMfObject::DiscardHPRES(void)
+{
+ VDATEHEAP();
+
+ if (m_hPres)
+ {
+ LEVERIFY( DeleteMetaFile (m_hPres) );
+ m_hPres = NULL;
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::GetCopyOfHPRES (private)
+//
+// Synopsis: makes a copy of the metafile (if one is present), otherwise
+// just load it from the stream (but don't store it in [this]
+// object)
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HANDLE to the metafile
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+INTERNAL_(HANDLE) CMfObject::GetCopyOfHPRES(void)
+{
+ VDATEHEAP();
+
+ HANDLE hPres;
+
+ // Make a copy if the presentation data is already loaded
+ if (m_hPres)
+ {
+ return CopyMetaFile(m_hPres, NULL);
+ }
+
+ // Load the presentation data now and return the same handle.
+ // No need to copy the data. If the caller wants the m_hPres to be
+ // set he would call LoadHPRES() directly.
+
+ hPres = LoadHPRES();
+ m_hPres = NULL; // NULL this, LoadHPRES set it.
+ return hPres;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMfObject::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppszDump] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CMfObject::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszHRESULT;
+ char *pszDVASPECT;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump(500);
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "No. of References = " << m_ulRefs << endl;
+
+ dstrDump << pszPrefix << "pMETAINFO (Metafile information) = " << m_pMetaInfo << endl;
+
+ dstrDump << pszPrefix << "pMETADC (current device context) = " << m_pCurMdc << endl;
+
+ dstrDump << pszPrefix << "IsMetaDeviceContext? = ";
+ if (m_fMetaDC == TRUE)
+ {
+ dstrDump << "TRUE" << endl;
+ }
+ else
+ {
+ dstrDump << "FALSE" << endl;
+ }
+
+ dstrDump << pszPrefix << "No. of Records in Metafile = " << m_nRecord << endl;
+
+ pszHRESULT = DumpHRESULT(m_error);
+ dstrDump << pszPrefix << "Error code = " << pszHRESULT << endl;
+ CoTaskMemFree(pszHRESULT);
+
+ dstrDump << pszPrefix << "pLOGPALETTE (Color set palette) = " << m_pColorSet << endl;
+
+ dstrDump << pszPrefix << "ConvertFromMac? = ";
+ if (m_fConvert == TRUE)
+ {
+ dstrDump << "TRUE" << endl;
+ }
+ else
+ {
+ dstrDump << "FALSE" << endl;
+ }
+
+ dstrDump << pszPrefix << "Continue = " << m_dwContinue << endl;
+
+ dstrDump << pszPrefix << "fp Continue = " << m_pfnContinue<< endl;
+
+ pszDVASPECT = DumpDVASPECTFlags(m_dwAspect);
+ dstrDump << pszPrefix << "Aspect flags = " << pszDVASPECT << endl;
+ CoTaskMemFree(pszDVASPECT);
+
+ dstrDump << pszPrefix << "Size = " << m_dwSize << endl;
+
+ dstrDump << pszPrefix << "Width = " << m_lWidth << endl;
+
+ dstrDump << pszPrefix << "Height = " << m_lHeight << endl;
+
+ dstrDump << pszPrefix << "pCacheNode = " << m_pCacheNode << endl;
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCMfObject, public (_DEBUG only)
+//
+// Synopsis: calls the CMfObject::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pMFO] - pointer to CMfObject
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCMfObject(CMfObject *pMFO, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pMFO == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pMFO->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
diff --git a/private/ole32/ole232/stdimpl/olereg.cpp b/private/ole32/ole232/stdimpl/olereg.cpp
new file mode 100644
index 000000000..1555cd1f2
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/olereg.cpp
@@ -0,0 +1,667 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: olereg.cpp
+//
+// Contents: Helper routines to interrogate the reg database
+//
+// Classes:
+//
+// Functions: OleRegGetUserType
+// OleRegGetMiscStatus
+// OleGetAutoConvert
+// OleSetAutoConvert
+//
+// History: dd-mmm-yy Author Comment
+// 11-Jan-94 alexgo added VDATEHEAP macros to every function
+// 30-Nov-93 alexgo 32bit port
+// 11-Nov-92 jasonful author
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#pragma SEG(olereg)
+
+#include <reterr.h>
+#include "oleregpv.h"
+#include <ctype.h>
+
+ASSERTDATA
+#define MAX_STR 512
+
+// Reg Db Keys
+static const OLECHAR szAuxUserTypeKey[] = OLESTR("AuxUserType");
+static const OLECHAR szMiscStatusKey[] = OLESTR("MiscStatus") ;
+static const OLECHAR szProgIDKey[] = OLESTR("ProgID");
+static const OLECHAR szClsidKey[] = OLESTR("Clsid");
+static const OLECHAR szAutoConverTo[] = OLESTR("AutoConvertTo");
+
+// this is really a global variable
+const OLECHAR szClsidRoot[] = OLESTR("CLSID\\");
+
+
+static INTERNAL OleRegGetDword
+ (HKEY hkey,
+ LPCOLESTR szKey,
+ DWORD FAR* pdw);
+
+static INTERNAL OleRegGetDword
+ (HKEY hkey,
+ DWORD dwKey,
+ DWORD FAR* pdw);
+
+static INTERNAL OleRegGetString
+ (HKEY hkey,
+ LPCOLESTR szKey,
+ LPOLESTR FAR* pszValue);
+
+
+static INTERNAL OleRegGetString
+ (HKEY hkey,
+ DWORD dwKey,
+ LPOLESTR FAR* pszValue);
+
+//+-------------------------------------------------------------------------
+//
+// Function: Atol (static)
+//
+// Synopsis: Converts string to integer
+//
+// Effects:
+//
+// Arguments: [sz] -- the string
+//
+// Requires:
+//
+// Returns: LONG
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes: 32bit OLE just uses wcstol as a #define
+//
+// original 16bit comment:
+//
+// Replacement for stdlib atol,
+// which didn't work and doesn't take far pointers.
+// Must be tolerant of leading spaces.
+//
+//--------------------------------------------------------------------------
+#ifndef WIN32
+#pragma SEG(Atol)
+FARINTERNAL_(LONG) Atol
+ (LPOLESTR sz)
+{
+ VDATEHEAP();
+
+ signed int sign = +1;
+ UINT base = 10;
+ LONG l = 0;
+
+ if (NULL==sz)
+ {
+ Assert (0);
+ return 0;
+ }
+ while (isspace(*sz))
+ {
+ sz++;
+ }
+
+ if (*sz== OLESTR('-'))
+ {
+ sz++;
+ sign = -1;
+ }
+ if (sz[0]==OLESTR('0') && sz[1]==OLESTR('x'))
+ {
+ base = 16;
+ sz+=2;
+ }
+
+ if (base==10)
+ {
+ while (isdigit(*sz))
+ {
+ l = l * base + *sz - OLESTR('0');
+ sz++;
+ }
+ }
+ else
+ {
+ Assert (base==16);
+ while (isxdigit(*sz))
+ {
+ l = l * base + isdigit(*sz) ? *sz - OLESTR('0') :
+ toupper(*sz) - OLESTR('A') + 10;
+ sz++;
+ }
+ }
+ return l * sign;
+}
+#endif //!WIN32
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleRegGetDword
+//
+// Synopsis: returns the value of subkey "szKey" as a DWORD
+//
+// Effects:
+//
+// Arguments: [hkey] -- handle to a key in the regdb
+// [szKey] -- the subkey to look for
+// [pdw] -- where to put the dword
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleRegGetDword)
+static INTERNAL OleRegGetDword
+ (HKEY hkey,
+ LPCOLESTR szKey,
+ DWORD FAR* pdw)
+{
+ VDATEHEAP();
+
+ VDATEPTRIN (pdw, DWORD);
+
+ LPOLESTR szLong = NULL;
+
+ HRESULT hresult = OleRegGetString (hkey, szKey, &szLong);
+ if (hresult != NOERROR)
+ {
+ return hresult;
+ }
+ *pdw = Atol (szLong);
+ PubMemFree(szLong);
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleRegGetDword (overloaded)
+//
+// Synopsis: Gets a dword from a sub-key given as a dword
+//
+// Effects:
+//
+// Arguments: [hkey] -- handle to a key in the regdb
+// [dwKey] -- number to convert to a string key to lookup in
+// the regdb
+// [pdw] -- where to put the dword
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 30-Nov-93 alexgo 32bit port
+//
+// Notes: REVIEW32: This deep layering is kinda strange, as each
+// overloaded function is used exactly once. It might be
+// better just to inline the stuff and be done with it.
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleRegGetDword)
+static INTERNAL OleRegGetDword
+ (HKEY hkey,
+ DWORD dwKey,
+ DWORD FAR* pdw)
+{
+ VDATEHEAP();
+
+ OLECHAR szBuf[MAX_STR];
+ wsprintf(szBuf, OLESTR("%ld"), dwKey);
+
+ return OleRegGetDword (hkey, szBuf, pdw);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleRegGetString
+//
+// Synopsis: Return the value of subkey [szKey] of key [hkey] as a string
+//
+// Effects:
+//
+// Arguments: [hkey] -- a handle to a key in the reg db
+// [szKey] -- the subkey to get the value of
+// [ppszValue] -- where to put the value string
+//
+// Requires:
+//
+// Returns: HRESULT (NOERROR, E_OUTOFMEMORY, REGDB_E_KEYMISSING)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+// 15-Dec-93 ChrisWe cb is supposed to be the size of the
+// buffer in bytes; changed to use sizeof()
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleRegGetString)
+static INTERNAL OleRegGetString
+ (HKEY hkey,
+ LPCOLESTR szKey,
+ LPOLESTR FAR* ppszValue)
+{
+ VDATEHEAP();
+
+ OLECHAR szBuf [MAX_STR];
+ LONG cb = sizeof(szBuf);
+
+ *ppszValue = NULL;
+
+ if (ERROR_SUCCESS == RegQueryValue (hkey, (LPOLESTR) szKey,
+ szBuf, &cb))
+ {
+ *ppszValue = UtDupString (szBuf);
+ return *ppszValue ? NOERROR : ResultFromScode (E_OUTOFMEMORY);
+ }
+ return ReportResult(0, REGDB_E_KEYMISSING, 0, 0);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleRegGetString (overloaded)
+//
+// Synopsis: Gets the string value of the DWORD subkey
+//
+// Effects:
+//
+// Arguments: [hkey] -- handle to a key in the regdb
+// [dwKey] -- the subkey value
+// [ppszValue] -- where to put the return value
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+static INTERNAL OleRegGetString
+ (HKEY hkey,
+ DWORD dwKey,
+ LPOLESTR FAR* ppszValue)
+{
+ VDATEHEAP();
+
+ OLECHAR szBuf[MAX_STR];
+ wsprintf(szBuf, OLESTR("%ld"), dwKey);
+
+ return OleRegGetString (hkey, szBuf, ppszValue);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleRegGetUserType
+//
+// Synopsis: Returns the user type name for the class id.
+//
+// Effects:
+//
+// Arguments: [clsid] -- the class ID to look up
+// [dwFormOfType] -- flag indicating whether the fullname,
+// shortname, or app name is desired
+// [ppszUserType] -- where to put the type string
+//
+// Requires: returned string must be deleted
+//
+// Returns: HRESULT (NOERROR, OLE_E_CLSID)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Nov-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleRegGetUserType)
+STDAPI OleRegGetUserType
+ (REFCLSID clsid,
+ DWORD dwFormOfType, // as in IOleObject::GetUserType
+ LPOLESTR FAR* ppszUserType) // out parm
+{
+ OLETRACEIN((API_OleRegGetUserType, PARAMFMT("clsid= %I, dwFormOfType= %x, ppszUserType= %p"),
+ &clsid, dwFormOfType, ppszUserType));
+
+ VDATEHEAP();
+
+ LPOLESTR pszTemp;
+ HKEY hkeyClsid = NULL;
+ HKEY hkeyAux = NULL;
+ HRESULT hresult = NOERROR;
+
+ VDATEPTROUT_LABEL (ppszUserType, LPOLESTR, safeRtn, hresult);
+ *ppszUserType = NULL;
+
+ ErrRtnH(CoOpenClassKey(clsid, &hkeyClsid));
+
+ if (dwFormOfType == USERCLASSTYPE_FULL ||
+ ERROR_SUCCESS != RegOpenKey (hkeyClsid, szAuxUserTypeKey,
+ &hkeyAux))
+ {
+ // use Main User Type Name (value of key CLSID(...))
+ hresult = OleRegGetString(hkeyClsid, (LPOLESTR)NULL,
+ &pszTemp);
+ if (SUCCEEDED(hresult))
+ {
+ // If no user type string is registered under the class key,
+ // OleRegGetString returns NOERROR and returns an empty string.
+ // We need to check for this and return the appropriate error.
+ if ( !pszTemp[0] )
+ {
+ PubMemFree(pszTemp);
+ hresult = ResultFromScode(REGDB_E_INVALIDVALUE);
+ goto errRtn;
+ }
+ *ppszUserType = pszTemp;
+ }
+ }
+ else
+ {
+ // look under key AuxUserType
+ if (NOERROR !=
+ OleRegGetString (hkeyAux, dwFormOfType, ppszUserType)
+ || NULL==*ppszUserType
+ || '\0'==(*ppszUserType)[0])
+ {
+ // Couldn't find the particular FormOfType requested,
+ // so use Full User Type Name (value of main
+ // CLSID key), as per spec
+ ErrRtnH (OleRegGetString (hkeyClsid, (LPOLESTR)NULL,
+ ppszUserType));
+ }
+ }
+
+ errRtn:
+
+ CLOSE (hkeyClsid);
+ CLOSE (hkeyAux);
+
+ safeRtn:
+ OLETRACEOUT((API_OleRegGetUserType, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleRegGetMiscStatus
+//
+// Synopsis: Retrieves misc status bits from the reg db
+//
+// Effects:
+//
+// Arguments: [clsid] -- the class ID
+// [dwAspect] -- specify the aspect (used in querrying
+// the reg db)
+// [pdwStatus] -- return to return the status bits
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes: Uses default (0) is the MiscStatus key is missing
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleRegGetMiscStatus)
+STDAPI OleRegGetMiscStatus
+ (REFCLSID clsid,
+ DWORD dwAspect,
+ DWORD FAR* pdwStatus)
+{
+ OLETRACEIN((API_OleRegGetMiscStatus, PARAMFMT("clsid= %I, dwAspect= %x, pdwStatus= %p"),
+ &clsid, dwAspect, pdwStatus));
+
+ VDATEHEAP();
+
+ HKEY hkeyClsid = NULL;
+ HKEY hkeyMisc = NULL;
+ HRESULT hresult = NOERROR;
+
+ VDATEPTROUT_LABEL(pdwStatus, DWORD, safeRtn, hresult);
+ *pdwStatus = 0;
+
+ ErrRtnH(CoOpenClassKey(clsid, &hkeyClsid));
+
+ // Open MiscStatus key
+ if (ERROR_SUCCESS != RegOpenKey (hkeyClsid, szMiscStatusKey,
+ &hkeyMisc))
+ {
+ // MiscStatus key not there, so use default.
+ hresult = NOERROR;
+ goto errRtn;
+ }
+ if (OleRegGetDword (hkeyMisc, dwAspect, pdwStatus) != NOERROR)
+ {
+ // Get default value from main Misc key
+ ErrRtnH (OleRegGetDword (hkeyMisc,
+ (LPOLESTR)NULL, pdwStatus));
+ // Got default value
+ }
+ // Got value for dwAspect
+
+ errRtn:
+ CLOSE (hkeyMisc);
+ CLOSE (hkeyClsid);
+
+ safeRtn:
+ OLETRACEOUT((API_OleRegGetMiscStatus, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleGetAutoConvert
+//
+// Synopsis: Retrieves the class ID that [clsidOld] should be converted
+// to via auto convert
+//
+// Effects:
+//
+// Arguments: [clsidOld] -- the original class ID
+// [pClsidNew] -- where to put the new convert-to class ID
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 05-Apr-94 kevinro removed bogus assert, restructured
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleGetAutoConvert)
+STDAPI OleGetAutoConvert(REFCLSID clsidOld, LPCLSID pClsidNew)
+{
+ OLETRACEIN((API_OleGetAutoConvert, PARAMFMT("clsidOld= %I, pClsidNew= %p"),
+ &clsidOld, pClsidNew));
+
+ VDATEHEAP();
+
+ HRESULT hresult;
+ HKEY hkeyClsid = NULL;
+ LPOLESTR lpszClsid = NULL;
+ VDATEPTROUT_LABEL (pClsidNew, CLSID, errRtn, hresult);
+ *pClsidNew = CLSID_NULL;
+
+ hresult = CoOpenClassKey(clsidOld, &hkeyClsid);
+ if (FAILED(hresult))
+ {
+ goto errRtn;
+ }
+
+ hresult = OleRegGetString(hkeyClsid, szAutoConverTo, &lpszClsid);
+
+ if (SUCCEEDED(hresult))
+ {
+ // Its Possible there is an AutoConvert Key under the CLSID but it has not value
+
+ if (OLESTR('\0') == lpszClsid[0])
+ {
+ hresult = REGDB_E_KEYMISSING;
+ }
+ else
+ {
+ // convert string into CLSID
+ hresult = CLSIDFromString(lpszClsid, pClsidNew);
+ }
+ }
+
+ CLOSE(hkeyClsid);
+ PubMemFree(lpszClsid);
+
+errRtn:
+ OLETRACEOUT((API_OleGetAutoConvert, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleSetAutoConvert
+//
+// Synopsis: Sets the autoconvert information in the regdb
+//
+// Effects:
+//
+// Arguments: [clsidOld] -- the original class id
+// [clsidNew] -- that class id that [clsidOld] should be
+// auto-converted to
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleSetAutoConvert)
+STDAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew)
+{
+ OLETRACEIN((API_OleSetAutoConvert, PARAMFMT("clsidOld= %I, clsidNew= %I"),
+ &clsidOld, &clsidNew));
+
+ VDATEHEAP();
+
+ HRESULT hresult;
+ HKEY hkeyClsid = NULL;
+
+ ErrRtnH(CoOpenClassKey(clsidOld, &hkeyClsid));
+
+ if (IsEqualCLSID(clsidNew, CLSID_NULL))
+ {
+ // ignore error since there may not be a value at present
+ (void)RegDeleteKey(hkeyClsid, szAutoConverTo);
+ }
+ else
+ {
+ OLECHAR szClsid[MAX_STR];
+ Verify(StringFromCLSID2(clsidNew, szClsid, sizeof(szClsid))
+ != 0);
+
+ if (RegSetValue(hkeyClsid, szAutoConverTo, REG_SZ, szClsid,
+ _xstrlen(szClsid)) != ERROR_SUCCESS)
+ {
+ hresult = ResultFromScode(REGDB_E_WRITEREGDB);
+ }
+ }
+
+errRtn:
+ CLOSE(hkeyClsid);
+
+ OLETRACEOUT((API_OleSetAutoConvert, hresult));
+
+ return hresult;
+}
+
+
diff --git a/private/ole32/ole232/stdimpl/oleregpv.h b/private/ole32/ole232/stdimpl/oleregpv.h
new file mode 100644
index 000000000..65b866c8b
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/oleregpv.h
@@ -0,0 +1,38 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: oleregpv.h
+//
+// Contents: Private header for the reg db api's
+//
+// Classes:
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 08-Sep-95 davidwor added size to szClsidRoot to allow
+// sizeof{szClsidRoot) for efficiency
+// 01-Dec-93 alexgo 32bit port
+//
+//--------------------------------------------------------------------------
+
+#ifndef fOleRegPv_h
+#define fOleRegPv_h
+
+#define CLOSE(hkey) do { if (hkey) {Verify(ERROR_SUCCESS== \
+ RegCloseKey(hkey)); hkey=NULL;}} while (0)
+
+#define DELIM OLESTR(",")
+
+#ifdef WIN32
+#define Atol(sz) wcstol((sz), NULL, 10)
+#else //WIN16
+FARINTERNAL_(LONG) Atol(LPOLESTR sz);
+#endif //WIN32
+
+extern const OLECHAR szClsidRoot[7];
+
+#endif //fOleRegPv_h
diff --git a/private/ole32/ole232/stdimpl/oregfmt.cpp b/private/ole32/ole232/stdimpl/oregfmt.cpp
new file mode 100644
index 000000000..7a003c827
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/oregfmt.cpp
@@ -0,0 +1,2001 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: oregfmt.cpp
+//
+// Contents: Enumerator implementation for the regdb formatetc's
+//
+// Classes: CEnumFmt
+// CEnumFmt10
+//
+// Functions: OleRegEnumFormatEtc
+//
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH add Dump methods to CEnumFmt, CEnumFmt10
+// and add APIs DumpCEnumFmt, DumpCEnumFmt10
+// DumpFMT, DumpFMTCache
+// 25-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocations.
+// 11-Jan-94 alexgo added VDATEHEAP macros to every function
+// 31-Dec-93 erikgav chicago port
+// 01-Dec-93 alexgo 32bit port
+// 12-Nov-92 jasonful author
+//
+//--------------------------------------------------------------------------
+
+#include <le2int.h>
+#pragma SEG(oregfmt)
+
+#include <reterr.h>
+#include "oleregpv.h"
+#include <ctype.h>
+#include <string.h>
+
+#ifdef _DEBUG
+#include <dbgdump.h>
+#endif // _DEBUG
+
+ASSERTDATA
+
+#define MAX_STR 256
+
+#define UtRemoveRightmostBit(x) ((x)&((x)-1))
+#define UtRightmostBit(x) ((x)^UtRemoveRightmostBit(x))
+#define UtIsSingleBit(x) ((x) && (0==UtRemoveRightmostBit(x)))
+
+// reg db key
+static const LPCOLESTR DATA_FORMATS = OLESTR("DataFormats\\GetSet");
+
+static INTERNAL CreateEnumFormatEtc10
+ (REFCLSID clsid,
+ DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenum);
+
+
+typedef struct FARSTRUCT
+{
+ FORMATETC fmt;
+ DWORD dwAspects; // aspects not yet returned
+ BOOL fUseMe; // is the cache valid?
+} FMTCACHE;
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CEnumFmt
+//
+// Purpose: FORMATETC enumerator for regdb formats
+//
+// Interface: IEnumFORMATETC
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class FAR CEnumFmt : public IEnumFORMATETC, public CPrivAlloc
+{
+public:
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ // *** IEnumFORMATETC methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, FORMATETC FAR * rgelt,
+ ULONG FAR* pceltFetched) ;
+ STDMETHOD(Skip) (THIS_ ULONG celt) ;
+ STDMETHOD(Reset) (THIS) ;
+ STDMETHOD(Clone) (THIS_ LPENUMFORMATETC FAR* ppenum) ;
+
+ CEnumFmt (LPOLESTR szClsid, DWORD dwDirection, DWORD iKey=0);
+ STDMETHOD(OpenHKey) (HKEY FAR*);
+
+ #ifdef _DEBUG
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+ #endif // _DEBUG
+
+ ULONG m_cRef;
+ LPOLESTR m_szClsid;
+ DWORD m_dwDirection;
+ DWORD m_iKey ; // index of current key in reg db
+
+ // We cannot keep an hkey open because Clone (or trying to use any 2
+ // independent enumerators) would fail.
+ FMTCACHE m_cache;
+};
+
+// For OLE 1.0
+typedef struct
+{
+ CLIPFORMAT cf;
+ DWORD dw; // DATADIR_GET/SET
+} FMT;
+
+#ifdef _DEBUG
+// for use in CEnumFmt[10] Dump methods
+char *DumpFMT(FMT *pFMT, ULONG ulFlag, int nIndentLevel);
+char *DumpFMTCACHE(FMTCACHE *pFMTC, ULONG ulFlag, int nIndentLevel);
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Class: CEnumFmt10 : CEnumFmt
+//
+// Purpose: Enumerates OLE1.0 formats
+//
+// Interface: IEnumFORMATETC
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class FAR CEnumFmt10 : public CEnumFmt
+{
+public:
+ STDMETHOD(Next) (THIS_ ULONG celt, FORMATETC FAR * rgelt,
+ ULONG FAR* pceltFetched) ;
+ STDMETHOD(Skip) (THIS_ ULONG celt) ;
+ STDMETHOD(Clone) (THIS_ LPENUMFORMATETC FAR* ppenum) ;
+ STDMETHOD_(ULONG,Release) (THIS) ;
+ CEnumFmt10 (LPOLESTR szClsid, DWORD dwDirection, DWORD iKey=0);
+
+ STDMETHOD(InitFromRegDb) (HKEY);
+ STDMETHOD(InitFromScratch) (void);
+
+ #ifdef _DEBUG
+ HRESULT Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel);
+ #endif // _DEBUG
+
+ FMT FAR* m_rgFmt;
+ size_t m_cFmt; // number of Fmts in m_rgFmt
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt::CEnumFmt
+//
+// Synopsis: Constructor for the formatetc enumerator
+//
+// Effects:
+//
+// Arguments: [szClsid] -- the class id to look for
+// [dwDirection] -- (either SET or GET)
+// [iKey] -- index into the regdb (which formatetc)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt_ctor)
+CEnumFmt::CEnumFmt
+ (LPOLESTR szClsid,
+ DWORD dwDirection,
+ DWORD iKey)
+{
+ VDATEHEAP();
+
+ m_cRef = 1;
+ m_szClsid = szClsid;
+ m_iKey = iKey;
+ m_dwDirection = dwDirection;
+ m_cache.fUseMe = FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt10::CEnumFmt10
+//
+// Synopsis: Constructor for the 1.0 formatetc enumerator
+//
+// Effects:
+//
+// Arguments: [szClsid] -- the class id to look for
+// [dwDirection] -- (either SET or GET)
+// [iKey] -- index into the regdb (which formatetc)
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt10_ctor)
+CEnumFmt10::CEnumFmt10
+ (LPOLESTR szClsid,
+ DWORD dwDirection,
+ DWORD iKey)
+ : CEnumFmt (szClsid, dwDirection, iKey)
+{
+ VDATEHEAP();
+
+ m_rgFmt = NULL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateEnumFormatEtc (static)
+//
+// Synopsis: Creates a 2.0 formatetc enumerator object
+//
+// Effects:
+//
+// Arguments: [clsid] -- the class ID to look for
+// [dwDirection] -- the formatetc direction (SET or GET)
+// [ppenum] -- where to put the enumerator
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Checks to make sure that the data exists in the reg db
+// and then allocates an enumerator object
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CreateEnumFormatEtc)
+static INTERNAL CreateEnumFormatEtc
+ (REFCLSID clsid,
+ DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenum)
+{
+ VDATEHEAP();
+
+ OLECHAR szKey[MAX_STR];
+ LPOLESTR szClsid = NULL;
+ HKEY hkey = NULL;
+ HKEY hkeyFmts = NULL;
+
+ RetErr (StringFromCLSID (clsid, &szClsid));
+ _xstrcpy (szKey, szClsidRoot);
+ _xstrcat (szKey, szClsid);
+ if (ERROR_SUCCESS != RegOpenKey (HKEY_CLASSES_ROOT, szKey, &hkey))
+ {
+ PubMemFree(szClsid);
+ return ReportResult(0, REGDB_E_CLASSNOTREG, 0, 0);
+ }
+ if (ERROR_SUCCESS != RegOpenKey (hkey, (LPOLESTR) DATA_FORMATS,
+ &hkeyFmts))
+ {
+ CLOSE (hkey);
+ PubMemFree(szClsid);
+ return ReportResult(0, REGDB_E_KEYMISSING, 0, 0);
+ }
+ CLOSE (hkeyFmts);
+ CLOSE (hkey);
+ *ppenum = new FAR CEnumFmt (szClsid, dwDirection);
+ // hook the new interface
+ CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_IEnumFORMATETC,
+ (IUnknown **)ppenum);
+ // do not delete szClsid. Will be deleted on Release
+ return *ppenum ? NOERROR : ResultFromScode (E_OUTOFMEMORY);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleRegEnumFormatEtc
+//
+// Synopsis: Creates a reg db formatetc enumerator
+//
+// Effects:
+//
+// Arguments: [clsid] -- the class ID we're interested in
+// [dwDirection] -- either GET or SET (for the formatetc and
+// IDataObject->[Get|Set]Data)
+// [ppenum] -- where to put the enumerator
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Creates either an OLE2 enumerator or an OLE1 enumerator
+//
+// History: dd-mmm-yy Author Comment
+// 29-Nov-93 ChrisWe allow more than one DATADIR_* flag at a
+// time
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleRegEnumFormatEtc)
+STDAPI OleRegEnumFormatEtc
+ (REFCLSID clsid,
+ DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenum)
+{
+ OLETRACEIN((API_OleRegEnumFormatEtc, PARAMFMT("clsid= %I, dwDirection= %x, ppenum= %p"),
+ &clsid, dwDirection, ppenum));
+
+ VDATEHEAP();
+
+ HRESULT hr;
+
+ VDATEPTROUT_LABEL(ppenum, LPENUMFORMATETC, errRtn, hr);
+ *ppenum = NULL;
+
+ // check that dwDirection only has valid values
+ if (dwDirection & ~(DATADIR_GET | DATADIR_SET))
+ {
+ hr = ResultFromScode(E_INVALIDARG);
+ goto errRtn;
+ }
+
+ if (CoIsOle1Class (clsid))
+ {
+ hr = CreateEnumFormatEtc10 (clsid, dwDirection, ppenum);
+ }
+ else
+ {
+ hr = CreateEnumFormatEtc (clsid, dwDirection, ppenum);
+ }
+
+errRtn:
+ OLETRACEOUT((API_OleRegEnumFormatEtc, hr));
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt::OpenHKey
+//
+// Synopsis: Opens a the regdb and returns a handle to the formatetc's
+//
+// Effects:
+//
+// Arguments: [phkey] -- where to put the regdb handle
+//
+// Requires:
+//
+// Returns: NOERROR, REGDB_E_KEYMISSING
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt_OpenHKey)
+STDMETHODIMP CEnumFmt::OpenHKey
+ (HKEY FAR* phkey)
+{
+ VDATEHEAP();
+
+ VDATEPTRIN (phkey, HKEY);
+ OLECHAR szBuf [MAX_STR];
+
+ _xstrcpy (szBuf, szClsidRoot);
+ _xstrcat (szBuf, m_szClsid);
+ _xstrcat (szBuf, OLESTR("\\"));
+ _xstrcat (szBuf, DATA_FORMATS);
+ return ERROR_SUCCESS==RegOpenKey (HKEY_CLASSES_ROOT, szBuf, phkey)
+ ? NOERROR
+ : ResultFromScode(REGDB_E_KEYMISSING);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt::Reset
+//
+// Synopsis: Resets the enumerator
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFormatEtc
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt_Reset)
+STDMETHODIMP CEnumFmt::Reset (void)
+{
+ VDATEHEAP();
+
+ m_iKey = 0;
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt::Skip
+//
+// Synopsis: Skips the next [c] formatetc's
+//
+// Effects:
+//
+// Arguments: [c] -- number of formatetc's to skip
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFormatEtc
+//
+// Algorithm: just calls Next [c] times :)
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt_Skip)
+STDMETHODIMP CEnumFmt::Skip
+ (ULONG c)
+{
+ VDATEHEAP();
+
+ ULONG i=0;
+ FORMATETC formatetc;
+ HRESULT hresult = NOERROR;
+
+ while (i++ < c)
+ {
+ // There will not be a target device to free
+ ErrRtnH (Next (1, &formatetc, NULL));
+ }
+
+ errRtn:
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt::Next
+//
+// Synopsis: Gets the next formatetc from teh regdb
+//
+// Effects:
+//
+// Arguments: [cfmt] -- the number of formatetc's to return
+// [rgfmt] -- where to put the formatetc's
+// [pcfmtFetched] -- where to put how many formatetc's were
+// actually fetched
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm: In the reg db, apps may compactly specify that a formatetc
+// applies to multiple aspects by simply using the numeric
+// value of the aspects or'ed together. Since our enumerator
+// should give one formatetc *per* aspect, if multiple aspects
+// are specified, then we cache the formatetc and use it the
+// next time a formatetc is requested (via next or [cfmt] > 1)
+// That's what the m_cache stuff is all about.
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt_Next)
+STDMETHODIMP CEnumFmt::Next
+ (ULONG cfmt,
+ FORMATETC FAR * rgfmt,
+ ULONG FAR* pcfmtFetched)
+{
+ VDATEHEAP();
+
+ OLECHAR szBuf [MAX_STR];
+ OLECHAR szKey [80];
+ DWORD dwAspects;
+ LPOLESTR psz;
+ LONG cb = 0;
+ HKEY hkey = NULL;
+ ULONG ifmt = 0; // number successfully fetched so far
+ LPOLESTR szFmt = NULL;
+ LPOLESTR szAspects = NULL;
+ LPOLESTR szMedia = NULL;
+ LPOLESTR szDirection = NULL;
+ HRESULT hresult = NOERROR;
+
+ RetErr (OpenHKey (&hkey));
+
+ while (ifmt < cfmt)
+ {
+ // use the cached value (multiple aspects specified for the
+ // formatetc.
+ if (m_cache.fUseMe)
+ {
+ rgfmt[ifmt] = m_cache.fmt;
+ rgfmt[ifmt].dwAspect = UtRightmostBit (
+ m_cache.dwAspects);
+ m_cache.dwAspects = UtRemoveRightmostBit (
+ m_cache.dwAspects);
+ if (0==m_cache.dwAspects)
+ m_cache.fUseMe = FALSE;
+ ifmt++;
+ }
+ else
+ {
+ wsprintf (szKey, OLESTR("%d"), m_iKey++);
+ cb = MAX_STR;
+ if (ERROR_SUCCESS == RegQueryValue (hkey, szKey,
+ szBuf, &cb))
+ {
+ rgfmt[ifmt].ptd = NULL;
+ rgfmt[ifmt].lindex = DEF_LINDEX;
+
+ psz = szBuf;
+ ErrZS(*psz, REGDB_E_INVALIDVALUE);
+
+ szFmt = psz;
+
+ while (*psz && *psz != DELIM[0])
+ psz++;
+ ErrZS(*psz, REGDB_E_INVALIDVALUE);
+ *psz++ = OLESTR('\0');
+
+ szAspects = psz;
+
+ while (*psz && *psz != DELIM[0])
+ psz++;
+ ErrZS(*psz, REGDB_E_INVALIDVALUE);
+ *psz++ = OLESTR('\0');
+
+ szMedia = psz;
+
+ while (*psz && *psz != DELIM[0])
+ psz++;
+ ErrZS(*psz, REGDB_E_INVALIDVALUE);
+ *psz++ = OLESTR('\0');
+
+ szDirection = psz;
+
+ // Format
+ rgfmt [ifmt].cfFormat = _xisdigit (szFmt[0])
+ ? (CLIPFORMAT) Atol (szFmt)
+ : RegisterClipboardFormat (szFmt);
+
+ // Aspect
+ dwAspects = Atol (szAspects);
+ ErrZS (dwAspects, REGDB_E_INVALIDVALUE);
+ if (UtIsSingleBit (dwAspects))
+ {
+ rgfmt[ifmt].dwAspect = Atol(szAspects);
+ }
+ else
+ {
+ rgfmt[ifmt].dwAspect =
+ UtRightmostBit(dwAspects);
+ m_cache.fmt = rgfmt[ifmt];
+ m_cache.dwAspects =
+ UtRemoveRightmostBit(
+ dwAspects) & 0xf;
+ if (m_cache.dwAspects != 0)
+ {
+ m_cache.fUseMe = TRUE;
+ }
+ }
+
+ // Media
+ rgfmt[ifmt].tymed = Atol (szMedia);
+ if (m_cache.fUseMe)
+ {
+ m_cache.fmt.tymed = rgfmt[ifmt].tymed;
+ }
+
+ // Direction
+ if ( (Atol (szDirection) & m_dwDirection) ==
+ m_dwDirection)
+ {
+ // This format supports the direction
+ // we are interested in
+ ifmt++;
+ }
+ else
+ {
+ m_cache.fUseMe = FALSE;
+ }
+ }
+ else
+ {
+ break; // no more entries
+ }
+ }// else
+ }// while
+
+ if (pcfmtFetched)
+ {
+ *pcfmtFetched = ifmt;
+ }
+
+ errRtn:
+ CLOSE (hkey);
+
+ if (NOERROR==hresult)
+ {
+ return ifmt==cfmt ? NOERROR : ResultFromScode (S_FALSE);
+ }
+ else
+ {
+ if (pcfmtFetched)
+ {
+ *pcfmtFetched = 0;
+ }
+
+ m_cache.fUseMe = FALSE;
+ return hresult;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt::Clone
+//
+// Synopsis: clones the enumerator
+//
+// Effects:
+//
+// Arguments: [ppenum] -- where to put the cloned enumerator
+//
+// Requires:
+//
+// Returns: NOERROR, E_OUTOFMEMORY
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt_Clone)
+STDMETHODIMP CEnumFmt::Clone
+ (LPENUMFORMATETC FAR* ppenum)
+{
+ VDATEHEAP();
+
+ VDATEPTRIN (ppenum, LPENUMFORMATETC);
+ *ppenum = new FAR CEnumFmt (UtDupString(m_szClsid), m_dwDirection,
+ m_iKey);
+ return *ppenum ? NOERROR : ResultFromScode (E_OUTOFMEMORY);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt::QueryInterface
+//
+// Synopsis: returns supported interfaces
+//
+// Effects:
+//
+// Arguments: [iid] -- the requested interface ID
+// [ppv] -- where to put the interface pointer
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFormatEtc
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt_QueryInterface)
+STDMETHODIMP CEnumFmt::QueryInterface(REFIID iid, LPVOID FAR* ppv)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+ if (IsEqualIID(iid, IID_IUnknown) ||
+ IsEqualIID(iid, IID_IEnumFORMATETC))
+ {
+ *ppv = this;
+ AddRef();
+ return NOERROR;
+ }
+ else
+ {
+ *ppv = NULL;
+ return ResultFromScode (E_NOINTERFACE);
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt::AddRef
+//
+// Synopsis: Increments the reference count
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt_AddRef)
+STDMETHODIMP_(ULONG) CEnumFmt::AddRef(void)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+ return ++m_cRef;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt::Release
+//
+// Synopsis: decrements the reference count
+//
+// Effects: may delete this object
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt_Release)
+STDMETHODIMP_(ULONG) CEnumFmt::Release(void)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+ if (--m_cRef == 0)
+ {
+ PubMemFree(m_szClsid);
+ delete this;
+ return 0;
+ }
+ return m_cRef;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppszDump] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CEnumFmt::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszFMTCACHE;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump;
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "No. of References = " << m_cRef << endl;
+
+ dstrDump << pszPrefix << "CLSID string = " << m_szClsid << endl;
+
+ dstrDump << pszPrefix << "Direction = " << m_dwDirection<< endl;
+
+ dstrDump << pszPrefix << "Current Key Index = " << m_iKey << endl;
+
+ pszFMTCACHE = DumpFMTCACHE(&m_cache, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "FMTCACHE: " << endl;
+ dstrDump << pszFMTCACHE;
+ CoTaskMemFree(pszFMTCACHE);
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCEnumFmt, public (_DEBUG only)
+//
+// Synopsis: calls the CEnumFmt::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pEF] - pointer to CEnumFmt
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCEnumFmt(CEnumFmt *pEF, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pEF == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pEF->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+/////////////////////////////////////////
+// OLE 1.0 stuff
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateEnumFormatEtc10
+//
+// Synopsis: Creates a 1.0 format enumerator
+//
+// Effects:
+//
+// Arguments: [clsid] -- the class id we're interested in
+// [dwDirection] -- either GET or SET
+// [ppenum] -- where to put the enumerator
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: checks to see if the info's in the reg db, then creates
+// and initializes a 1.0 enumerator object. (note that there
+// does not *have* to be any info in the regdb, we can
+// InitFromScratch)
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CreateEnumFormatEtc10)
+static INTERNAL CreateEnumFormatEtc10
+ (REFCLSID clsid,
+ DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenum)
+{
+ VDATEHEAP();
+
+ LPOLESTR szClsid = NULL;
+ HKEY hkey = NULL;
+ HKEY hkeyFmts = NULL;
+ HRESULT hresult = NOERROR;
+ BOOL fInReg;
+ CEnumFmt10 FAR* penum;
+
+ VDATEPTROUT (ppenum, LPENUMFORMATETC);
+ *ppenum = NULL;
+
+ RetErr (ProgIDFromCLSID (clsid, &szClsid));
+ if (ERROR_SUCCESS != RegOpenKey (HKEY_CLASSES_ROOT, szClsid, &hkey))
+ {
+ PubMemFree(szClsid);
+ return ReportResult(0, REGDB_E_CLASSNOTREG, 0, 0);
+ }
+
+ // Does this server have "Request/SetDataFormats" keys?
+ fInReg = (ERROR_SUCCESS == RegOpenKey (hkey,
+ OLESTR("Protocol\\StdFileEditing\\RequestDataFormats"),
+ &hkeyFmts));
+ CLOSE(hkeyFmts);
+
+ penum = new FAR CEnumFmt10 (szClsid, dwDirection);
+ if (NULL==penum)
+ {
+ ErrRtnH (ResultFromScode (E_OUTOFMEMORY));
+ }
+
+ if (fInReg)
+ {
+ penum->InitFromRegDb (hkey);
+ }
+ else
+ {
+ penum->InitFromScratch ();
+ }
+
+
+ errRtn:
+ CLOSE (hkey);
+ if (hresult == NOERROR)
+ {
+ *ppenum = penum;
+ CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_IEnumFORMATETC,
+ (IUnknown **)ppenum);
+ }
+ else
+ {
+ PubMemFree(szClsid);
+ // If no error, szClsid will be deleted on Release
+ }
+ return hresult;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt10::Next
+//
+// Synopsis: Gets the next 1.0 format
+//
+// Effects:
+//
+// Arguments: [cfmt] -- the number of formatetc's to get
+// [rgfmt] -- where to put the formatetc's
+// [pcfmtFetched] -- where to put the num of formatetc's fetched
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm: Ole1.0 formats are retrieved when the enumerator object
+// is created, so we just return ones from our internal array
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt10_Next)
+STDMETHODIMP CEnumFmt10::Next
+ (ULONG cfmt,
+ FORMATETC FAR * rgfmt,
+ ULONG FAR* pcfmtFetched)
+{
+ VDATEHEAP();
+
+ ULONG ifmt = 0; // number successfully fetched so far
+
+ while (ifmt < cfmt
+ && m_rgFmt != NULL
+ && m_rgFmt[m_iKey].cf != 0)
+ {
+ if ( (m_rgFmt[m_iKey].dw & m_dwDirection) == m_dwDirection)
+ {
+ // This format supports the direction we are
+ // interested in
+ rgfmt [ifmt].cfFormat = m_rgFmt[m_iKey].cf;
+ rgfmt [ifmt].ptd = NULL;
+ rgfmt [ifmt].lindex = DEF_LINDEX;
+ rgfmt [ifmt].tymed =
+ UtFormatToTymed(m_rgFmt[m_iKey].cf);
+ rgfmt [ifmt].dwAspect = DVASPECT_CONTENT;
+ ifmt++;
+ }
+ m_iKey++;
+ }
+
+ if (pcfmtFetched)
+ *pcfmtFetched = ifmt;
+
+ return ifmt==cfmt ? NOERROR : ResultFromScode (S_FALSE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: Index (static)
+//
+// Synopsis: finds the index of the given clipformat in the format
+// array
+//
+// Effects:
+//
+// Arguments: [rgFmt] -- the clipformat array
+// [cf] -- the clipformat to look for
+// [iMax] -- size of the array
+// [pi] -- where to put the index
+//
+// Requires:
+//
+// Returns: TRUE if found, FALSE otherwise
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(Index)
+static INTERNAL_(BOOL) Index
+ (FMT FAR * rgFmt,
+ CLIPFORMAT cf, // format to search for
+ size_t iMax, // size of array
+ size_t FAR* pi) // out parm, index of found format
+{
+ VDATEHEAP();
+
+ for (size_t i=0; i< iMax; i++)
+ {
+ if (rgFmt[i].cf==cf)
+ {
+ *pi = i;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: String2Clipformat (static)
+//
+// Synopsis: Converts a string to a clipboard format number (and then
+// registers the format)
+//
+// Effects:
+//
+// Arguments: [sz] -- the string to convert
+//
+// Requires:
+//
+// Returns: CLIPFORMAT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(String2Clipformat)
+static INTERNAL_(CLIPFORMAT) String2Clipformat
+ (LPOLESTR sz)
+{
+ VDATEHEAP();
+
+ if (_xstrlen(sz) >= 3 &&
+ 0==memcmp (sz, OLESTR("CF_"), 3*sizeof(sz[0])))
+ {
+ #define macro(cf) if (0==_xstricmp (sz, OLESTR(#cf))) return cf
+ macro (CF_TEXT);
+ macro (CF_BITMAP);
+ macro (CF_METAFILEPICT);
+ macro (CF_SYLK);
+ macro (CF_DIF);
+ macro (CF_TIFF);
+ macro (CF_OEMTEXT);
+ macro (CF_DIB);
+ macro (CF_PALETTE);
+ macro (CF_PENDATA);
+ macro (CF_RIFF);
+ macro (CF_WAVE);
+ macro (CF_OWNERDISPLAY);
+ macro (CF_DSPTEXT);
+ macro (CF_DSPBITMAP);
+ macro (CF_DSPMETAFILEPICT);
+ #undef macro
+ }
+ return RegisterClipboardFormat (sz);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt10::InitFromRegDb (internal)
+//
+// Synopsis: Initializes the 1.0 enumerator from the reg db (loads
+// all the available formats)
+//
+// Effects:
+//
+// Arguments: [hkey] -- handle to the regdb
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+// Original comment:
+//
+// Fill m_rgFmt with FMTs which map clipformats to Get/Set flags
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt10_InitFromRegDb)
+STDMETHODIMP CEnumFmt10::InitFromRegDb
+ (HKEY hkey) // CLSID key
+{
+ VDATEHEAP();
+
+ LPOLESTR pch;
+ LPOLESTR szReq = (LPOLESTR)PubMemAlloc(512 * sizeof(OLECHAR));
+ LPOLESTR szSet = (LPOLESTR)PubMemAlloc(512 * sizeof(OLECHAR));
+ LPOLESTR szFmt;
+ BOOL bMore;
+ size_t cFmts = 0;
+ size_t iFmt = 0;
+ size_t iFmtPrev;
+ CLIPFORMAT cf;
+ LONG cb;
+ HRESULT hresult = NOERROR;
+
+ if( !szReq )
+ {
+ // assumes delete 0 works (if szSet == 0)
+ PubMemFree(szSet);
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+ if( !szSet )
+ {
+ PubMemFree(szReq);
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+
+ cb = 512;
+ if (ERROR_SUCCESS == RegQueryValue (hkey,
+ OLESTR("Protocol\\StdFileEditing\\RequestDataFormats"),
+ szReq, &cb))
+ {
+ cFmts = 1; // no commas means one format
+ for (pch = szReq; *pch; pch++)
+ {
+ if (*pch==OLESTR(','))
+ cFmts++;
+ }
+ }
+
+ // the size of szSet
+ cb = 512;
+ if (ERROR_SUCCESS == RegQueryValue (hkey,
+ OLESTR("Protocol\\StdFileEditing\\SetDataFormats"),
+ szSet, &cb))
+ {
+ cFmts++; // no commas means one format
+ for (pch = szSet; *pch; pch++)
+ {
+ if (*pch==OLESTR(','))
+ cFmts++;
+ }
+ }
+
+ if (cFmts==0)
+ {
+ Assert(0);
+ ErrRtnH (ReportResult(0, REGDB_E_KEYMISSING, 0, 0));
+ }
+
+ m_rgFmt = (FMT FAR *)PrivMemAlloc(sizeof(FMT)*(cFmts+1));
+ if (m_rgFmt==NULL)
+ {
+ ErrRtnH (ResultFromScode (E_OUTOFMEMORY));
+ }
+
+ pch = szReq;
+ bMore = (*pch != 0);
+ while (bMore)
+ {
+ while (*pch == OLESTR(' '))
+ pch++;
+ szFmt = pch;
+ while (*pch && *pch != DELIM[0])
+ pch++;
+ if (*pch == 0)
+ bMore = FALSE;
+ *pch++ = OLESTR('\0');
+ m_rgFmt[iFmt].cf = String2Clipformat(szFmt);
+ m_rgFmt[iFmt++].dw = DATADIR_GET;
+ }
+
+ pch = szSet;
+ bMore = (*pch != 0);
+ while (bMore)
+ {
+ while (*pch == OLESTR(' '))
+ pch++;
+ szFmt = pch;
+ while (*pch && *pch != DELIM[0])
+ pch++;
+ if (*pch == 0)
+ bMore = FALSE;
+ *pch++ = OLESTR('\0');
+ cf = String2Clipformat(szFmt);
+ if (Index (m_rgFmt, cf, iFmt, &iFmtPrev))
+ {
+ // This format can also be gotten
+ m_rgFmt[iFmtPrev].dw |= DATADIR_SET;
+ }
+ else
+ {
+ m_rgFmt[iFmt].cf = cf;
+ m_rgFmt[iFmt++].dw = DATADIR_SET;
+ }
+ }
+
+ // Terminator
+ m_rgFmt[iFmt].cf = 0;
+ m_cFmt = iFmt;
+
+ errRtn:
+ PubMemFree(szReq);
+ PubMemFree(szSet);
+ return hresult;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt10::InitFromScratch
+//
+// Synopsis: Initialize the enumerated formats for a 1.0 server that
+// does not specify any Request/SetData formats.
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: HRESULT (NOERROR, E_OUTOFMEMORY)
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: sets up Metafiles and "Native" formats
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+// The spec says that what EnumFormatEtc returns is not a
+// guarantee of support.
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt10_InitFromScratch)
+
+STDMETHODIMP CEnumFmt10::InitFromScratch
+ (void)
+{
+ VDATEHEAP();
+
+ m_rgFmt = (FMT FAR *)PrivMemAlloc(10 * sizeof(FMT));
+ if( !m_rgFmt )
+ {
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+ m_rgFmt[0].cf = CF_METAFILEPICT;
+ m_rgFmt[0].dw = DATADIR_GET;
+ m_rgFmt[1].cf = RegisterClipboardFormat (OLESTR("Native"));
+ m_rgFmt[1].dw = DATADIR_GET | DATADIR_SET;
+ m_rgFmt[2].cf = 0; // Terminator
+ m_cFmt = 2;
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt10::Skip
+//
+// Synopsis: skips to over [c] formats
+//
+// Effects:
+//
+// Arguments: [c] -- the number of formats to skip
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes: This is re-implemented so we get the right implementation
+// of Next (because C++ is evil OOP).
+// REVIEW32: we can probably get rid of this by clever use
+// of virtual (but must make sure the vtables don't get hosed).
+//
+//--------------------------------------------------------------------------
+
+
+#pragma SEG(CEnumFmt10_Skip)
+STDMETHODIMP CEnumFmt10::Skip
+ (ULONG c)
+{
+ VDATEHEAP();
+
+ ULONG i=0;
+ FORMATETC formatetc;
+ HRESULT hresult = NOERROR;
+
+ while (i++ < c)
+ {
+ // There will not be a target device to free
+ ErrRtnH (Next (1, &formatetc, NULL));
+ }
+
+ errRtn:
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt10::Clone
+//
+// Synopsis: duplicates the 1.0 format enumerator
+//
+// Effects:
+//
+// Arguments: [ppenum] -- where to put the cloned enumerator
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port, fixed memory leak
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt10_Clone)
+STDMETHODIMP CEnumFmt10::Clone
+ (LPENUMFORMATETC FAR* ppenum)
+{
+ VDATEHEAP();
+
+ VDATEPTROUT (ppenum, LPENUMFORMATETC);
+ CEnumFmt10 FAR* penum;
+ penum = new FAR CEnumFmt10 (UtDupString(m_szClsid), m_dwDirection,
+ m_iKey);
+ if (NULL==penum)
+ {
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+ penum->m_cFmt = m_cFmt;
+ penum->m_rgFmt = (FMT FAR *)PrivMemAlloc((m_cFmt+1) * sizeof(FMT));
+ if (NULL==penum->m_rgFmt)
+ {
+ PubMemFree(penum);
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+ _xmemcpy (penum->m_rgFmt, m_rgFmt, (m_cFmt+1)*sizeof(FMT));
+ Assert (penum->m_rgFmt[penum->m_cFmt].cf==0);
+ *ppenum = penum;
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt10::Release
+//
+// Synopsis: decrements the reference count
+//
+// Effects: may delete the object
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumFORMATETC
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumFmt10_Release)
+STDMETHODIMP_(ULONG) CEnumFmt10::Release(void)
+{
+ VDATEHEAP();
+
+ M_PROLOG(this);
+ if (--m_cRef == 0)
+ {
+ PubMemFree(m_szClsid);
+ PrivMemFree(m_rgFmt);
+ delete this;
+ return 0;
+ }
+ return m_cRef;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumFmt10::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppszDump] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CEnumFmt10::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ unsigned int ui;
+ char *pszPrefix;
+ char *pszCEnumFmt;
+ char *pszFMT;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump;
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ pszCEnumFmt = DumpCEnumFmt((CEnumFmt *)this, ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "CEnumFmt: " << endl;
+ dstrDump << pszCEnumFmt;
+ CoTaskMemFree(pszCEnumFmt);
+
+ dstrDump << pszPrefix << "No. in FMT array = " << m_cFmt << endl;
+
+ for (ui = 0; ui < m_cFmt; ui++)
+ {
+ pszFMT = DumpFMT(&m_rgFmt[ui], ulFlag, nIndentLevel + 1);
+ dstrDump << pszPrefix << "FMT [" << ui << "]: " << endl;
+ dstrDump << pszFMT;
+ CoTaskMemFree(pszFMT);
+ }
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCEnumFmt10, public (_DEBUG only)
+//
+// Synopsis: calls the CEnunFmt10::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pEF] - pointer to CEnumFmt10
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCEnumFmt10(CEnumFmt10 *pEF, ULONG ulFlag, int nIndentLevel)
+{
+ HRESULT hresult;
+ char *pszDump;
+
+ if (pEF == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pEF->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpFMT, public (_DEBUG only)
+//
+// Synopsis: returns a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [pFMT] - a pointer to a FMT object
+// [ulFlag] - a flag determining the prefix of all newlines of
+// the out character array(default is 0 -no prefix)
+// [nIndentLevel] - will add an indent prefix after the other prefix
+// for all newlines(include those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpFMT(FMT *pFMT, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszDump;
+ char *pszCLIPFORMAT;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump;
+
+ if (pFMT == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ // determine prefix
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << pFMT << " _VB ";
+ }
+
+ // determine indentation prefix
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ pszCLIPFORMAT = DumpCLIPFORMAT(pFMT->cf);
+ dstrDump << pszPrefix << "Clip format = " << pszCLIPFORMAT << endl;
+ CoTaskMemFree(pszCLIPFORMAT);
+
+ dstrDump << pszPrefix << "Dword = " << pFMT->dw << endl;
+
+ // cleanup and provide pointer to character array
+ pszDump = dstrDump.str();
+
+ if (pszDump == NULL)
+ {
+ pszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpFMTCACHE, public (_DEBUG only)
+//
+// Synopsis: returns a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [pFMT] - a pointer to a FMTCACHE object
+// [ulFlag] - a flag determining the prefix of all newlines of
+// the out character array(default is 0 -no prefix)
+// [nIndentLevel] - will add an indent prefix after the other prefix
+// for all newlines(include those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 23-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpFMTCACHE(FMTCACHE *pFMT, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ char *pszDump;
+ char *pszFORMATETC;
+ char *pszDVASPECT;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump;
+
+ if (pFMT == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ // determine prefix
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << pFMT << " _VB ";
+ }
+
+ // determine indentation prefix
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ pszFORMATETC = DumpFORMATETC(&pFMT->fmt, ulFlag, nIndentLevel);
+ dstrDump << pszPrefix << "FORMATETC: " << endl;
+ dstrDump << pszFORMATETC;
+ CoTaskMemFree(pszFORMATETC);
+
+ pszDVASPECT = DumpDVASPECTFlags(pFMT->dwAspects);
+ dstrDump << pszPrefix << "Aspect flags: = " << pszDVASPECT << endl;
+ CoTaskMemFree(pszDVASPECT);
+
+ dstrDump << pszPrefix << "IsCacheValid? = ";
+ if (pFMT->fUseMe == TRUE)
+ {
+ dstrDump << "TRUE" << endl;
+ }
+ else
+ {
+ dstrDump << "FALSE" << endl;
+ }
+
+ // cleanup and provide pointer to character array
+ pszDump = dstrDump.str();
+
+ if (pszDump == NULL)
+ {
+ pszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
diff --git a/private/ole32/ole232/stdimpl/oregverb.cpp b/private/ole32/ole232/stdimpl/oregverb.cpp
new file mode 100644
index 000000000..0aa77ee66
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/oregverb.cpp
@@ -0,0 +1,1254 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: oregverb.cpp
+//
+// Contents: Implementation of the enumerator for regdb verbs
+//
+// Classes: CEnumVerb
+//
+// Functions: OleRegEnumVerbs
+//
+// History: dd-mmm-yy Author Comment
+// 12-Sep-95 davidwor made cache thread-safe
+// 08-Sep-95 davidwor optimized caching code
+// 12-Jul-95 t-gabes cache verbs and enumerator
+// 01-Feb-95 t-ScottH add Dump method to CEnumVerb and API
+// DumpCEnumVerb
+// 25-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocations.
+// 11-Jan-94 alexgo added VDATEHEAP macros to every function
+// 31-Dec-93 erikgav chicago port
+// 01-Dec-93 alexgo 32bit port
+// 12-Nov-93 jasonful author
+//
+//--------------------------------------------------------------------------
+
+
+#include <le2int.h>
+#pragma SEG(oregverb)
+
+#include <reterr.h>
+#include "oleregpv.h"
+
+#ifdef _DEBUG
+#include <dbgdump.h>
+#endif // _DEBUG
+
+ASSERTDATA
+
+#define MAX_STR 256
+#define MAX_VERB 33
+#define OLEIVERB_LOWEST OLEIVERB_HIDE
+
+// reg db key
+static const OLECHAR VERB[] = OLESTR("\\Verb");
+
+// stdfileediting key
+static const OLECHAR STDFILE[] = OLESTR("\\Protocol\\StdFileEditing");
+
+// default verbs
+static const OLECHAR DEFVERB[] =
+ OLESTR("Software\\Microsoft\\OLE1\\UnregisteredVerb");
+
+// default verb
+static const OLECHAR EDIT[] = OLESTR("Edit");
+
+//+-------------------------------------------------------------------------
+//
+// Struct: VerbList
+//
+// Purpose: to hold the enumerator's list of verbs
+//
+// History: dd-mmm-yy Author Comment
+// 12-Jul-95 t-gabes author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+typedef struct VerbList
+{
+ ULONG cRef; // reference count
+ CLSID clsid; // CLSID of the cached verbs
+ ULONG cVerbs; // count of verbs in oleverb array
+ OLEVERB oleverb[1]; // variable-size list of verbs
+} VERBLIST, *LPVERBLIST;
+
+STDAPI MakeVerbList(HKEY hkey, REFCLSID rclsid, LPVERBLIST *ppVerbList);
+STDAPI OleReleaseEnumVerbCache(void);
+
+//+-------------------------------------------------------------------------
+//
+// Class: CEnumVerb
+//
+// Purpose: enumerates the verbs listed in the reg db for a given class
+//
+// Interface: IEnumOLEVERB
+//
+// History: dd-mmm-yy Author Comment
+// 02-Aug-95 t-gabes rewrote to use cache
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class FAR CEnumVerb : public IEnumOLEVERB, public CPrivAlloc
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ // *** IEnumOLEVERB methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, LPOLEVERB reelt,
+ ULONG FAR* pceltFetched);
+ STDMETHOD(Skip) (THIS_ ULONG celt);
+ STDMETHOD(Reset) (THIS);
+ STDMETHOD(Clone) (THIS_ LPENUMOLEVERB FAR* ppenm);
+
+ ULONG GetRefCount (void);
+
+#ifdef _DEBUG
+ HRESULT Dump (char **ppszDump, ULONG ulFlag, int nIndentLevel);
+ friend char *DumpCEnumVerb (CEnumVerb *pEV, ULONG ulFlag, int nIndentLevel);
+#endif // _DEBUG
+
+private:
+ CEnumVerb (LPVERBLIST pVerbs, LONG iVerb=0);
+
+ ULONG m_cRef; // reference count
+ LONG m_iVerb; // current verb number (0 is the first)
+ LPVERBLIST m_VerbList; // all the verbs for this class
+
+ friend HRESULT STDAPICALLTYPE OleRegEnumVerbs (REFCLSID, LPENUMOLEVERB FAR*);
+ friend HRESULT STDAPICALLTYPE OleReleaseEnumVerbCache(void);
+};
+
+//+-------------------------------------------------------------------------
+//
+// Struct: EnumVerbCache
+//
+// Purpose: to cache the enumerator for the last enumerated class
+//
+// History: dd-mmm-yy Author Comment
+// 12-Jul-95 t-gabes author
+//
+//
+//--------------------------------------------------------------------------
+
+typedef struct
+{
+ CEnumVerb* pEnum; // pointer to the cached enumerator
+#ifdef _DEBUG
+ LONG iCalls; // total calls counter
+ LONG iHits; // cache hit counter
+#endif // _DEBUG
+} EnumVerbCache;
+
+// Last enumerator used
+EnumVerbCache g_EnumCache = { NULL };
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleRegEnumVerbs
+//
+// Synopsis: Creates an enumerator to go through the verbs in the reg db
+// for the given class ID
+//
+// Effects:
+//
+// Arguments: [clsid] -- the class ID we're interested in
+// [ppenum] -- where to put the enumerator pointer
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Makes sure that the info is in the database and then
+// creates the enumerator
+//
+// History: dd-mmm-yy Author Comment
+// 12-Sep-95 davidwor modified to make thread-safe
+// 08-Sep-95 davidwor optimized caching code
+// 12-Jul-95 t-gabes rewrote to use cache
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleRegEnumVerbs)
+STDAPI OleRegEnumVerbs
+ (REFCLSID clsid,
+ LPENUMOLEVERB FAR* ppenum)
+{
+ OLETRACEIN((API_OleRegEnumVerbs, PARAMFMT("clsid= %I, ppenum= %p"),
+ &clsid, ppenum));
+ VDATEHEAP();
+
+ CEnumVerb* pEnum;
+ LPVERBLIST pVerbList;
+ BOOL fOle1Class;
+ OLECHAR szKey[MAX_STR];
+ int cchBase;
+ HKEY hkey;
+ HRESULT hresult;
+
+ VDATEPTROUT_LABEL (ppenum, LPENUMOLEVERB, errSafeRtn, hresult);
+ *ppenum = NULL;
+
+#ifdef _DEBUG
+ // Increment total calls counter
+ InterlockedIncrement(&g_EnumCache.iCalls);
+#endif // _DEBUG
+ // Grab the global enumerator and put a NULL in its place. If another
+ // thread calls into OleRegEnumVerbs during this operation they won't
+ // be able to screw with the enumerator we're working with.
+ pEnum = (CEnumVerb *)InterlockedExchange((long *)&g_EnumCache.pEnum, 0);
+ if (pEnum != NULL)
+ {
+ if (IsEqualCLSID(clsid, pEnum->m_VerbList->clsid))
+ {
+#ifdef _DEBUG
+ // Increment cache hits counter
+ InterlockedIncrement(&g_EnumCache.iHits);
+#endif
+
+ if (1 == pEnum->GetRefCount())
+ {
+ // No other references -> AddRef and return this copy
+ *ppenum = pEnum;
+ pEnum->AddRef();
+ pEnum->Reset();
+ LEDebugOut((DEB_TRACE, "VERB Enumerator cache handed out\n"));
+ }
+ else
+ {
+ // Has additional references -> return a Cloned copy
+ if (NOERROR == pEnum->Clone(ppenum))
+ {
+ (*ppenum)->Reset();
+ LEDebugOut((DEB_TRACE, "VERB Enumerator cache cloned\n"));
+ }
+ }
+
+ // Swap our enumerator with the current contents of the global. If
+ // another thread called OleRegEnumVerbs during this operation and
+ // stored an enumerator in the global, we need to Release it.
+ pEnum = (CEnumVerb *)InterlockedExchange((long *)&g_EnumCache.pEnum, (long)pEnum);
+ if (pEnum != NULL)
+ {
+ pEnum->Release();
+ LEDebugOut((DEB_TRACE, "VERB Enumerator cache released (replacing global)\n"));
+ }
+
+ goto errRtn;
+ }
+ else
+ {
+ // Our clsid didn't match the clsid of the cache so we'll release the
+ // cached enumerator and proceed with creating a new enumerator to
+ // store in the global cache.
+ pEnum->Release();
+ LEDebugOut((DEB_TRACE, "VERB Enumerator cache released (different CLSID)\n"));
+ }
+ }
+
+ fOle1Class = CoIsOle1Class(clsid);
+
+ if (fOle1Class)
+ {
+ // Fills out szKey and cchBase as follows:
+ // szKey - "<ProgID>\Protocol\StdFileEditing"
+ // cchBase - length of "<ProgID>" portion
+
+ LPOLESTR psz;
+
+ RetErr(ProgIDFromCLSID(clsid, &psz));
+
+ cchBase = _xstrlen(psz);
+
+ memcpy(szKey, psz, cchBase * sizeof(OLECHAR));
+ memcpy(&szKey[cchBase], STDFILE, sizeof(STDFILE));
+
+ PubMemFree(psz);
+ }
+ else
+ {
+ // Fills out szKey and cchBase as follows:
+ // szKey - "CLSID\{clsid}"
+ // cchBase - length of full szKey string
+
+ memcpy(szKey, szClsidRoot, sizeof(szClsidRoot));
+
+ if (0 == StringFromCLSID2(clsid, &szKey[sizeof(szClsidRoot) / sizeof(OLECHAR) - 1], sizeof(szKey)))
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ cchBase = _xstrlen(szKey);
+ }
+
+ // append "\Verb" to the end
+ _xstrcat(szKey, VERB);
+
+ if (ERROR_SUCCESS != RegOpenKeyEx(
+ HKEY_CLASSES_ROOT,
+ szKey,
+ NULL,
+ KEY_READ,
+ &hkey))
+ {
+ // verb key doesn't exist, so figure out why
+
+ szKey[cchBase] = OLESTR('\0');
+ // szKey now contains one of the following:
+ // OLE1 - "<ProgID>"
+ // OLE2 - "CLSID\{clsid}"
+
+ if (ERROR_SUCCESS != RegOpenKeyEx(
+ HKEY_CLASSES_ROOT,
+ szKey,
+ NULL,
+ KEY_READ,
+ &hkey))
+ {
+ // the class isn't registered
+ return ReportResult(0, REGDB_E_CLASSNOTREG, 0, 0);
+ }
+
+ CLOSE(hkey);
+
+ // The class has no verbs. This is fine for OLE1 but not OLE2
+ if (!fOle1Class)
+ return ResultFromScode(OLEOBJ_E_NOVERBS);
+
+ // if hkey is NULL, MakeVerbList will use the default verb
+ hkey = NULL;
+ }
+
+ // make the verb list
+ RetErr(MakeVerbList(hkey, clsid, &pVerbList));
+ Assert(pVerbList != NULL);
+
+ // create a CEnumVerb object (this calls AddRef on pVerbList)
+ pEnum = new FAR CEnumVerb(pVerbList);
+ if (NULL == pEnum)
+ {
+ PrivMemFree(pVerbList);
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errSafeRtn;
+ }
+
+ // set the out parameter and AddRef on behalf of the caller
+ *ppenum = pEnum;
+ pEnum->AddRef();
+
+ LEDebugOut((DEB_TRACE, "VERB Enumerator cache created\n"));
+
+ // Swap our enumerator with the current contents of the global. If
+ // another thread called OleRegEnumVerbs during this operation and
+ // stored an enumerator in the global, we need to Release it.
+ pEnum = (CEnumVerb *)InterlockedExchange((long *)&g_EnumCache.pEnum, (long)pEnum);
+ if (pEnum != NULL)
+ {
+ pEnum->Release();
+ LEDebugOut((DEB_TRACE, "VERB Enumerator cache released (replacing global)\n"));
+ }
+
+errRtn:
+ hresult = *ppenum ? NOERROR : ResultFromScode (E_OUTOFMEMORY);
+
+ // hook the new interface
+ CALLHOOKOBJECTCREATE(S_OK, CLSID_NULL, IID_IEnumOLEVERB, (IUnknown **)ppenum);
+
+errSafeRtn:
+ LEDebugOut((DEB_TRACE, "VERB Enumerator cache hits/calls: (%d/%d)\n", g_EnumCache.iHits, g_EnumCache.iCalls));
+ OLETRACEOUT((API_OleRegEnumVerbs, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: MakeVerbList
+//
+// Synopsis: gets the list of verbs from the reg db
+//
+// Effects:
+//
+// Arguments: [hkey] -- handle to reg key to get verbs from
+// NULL for default verb
+// [rclsid] -- CLSID to store with verb list
+// [ppVerbList] -- OUT paramater for where to put result
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: none
+//
+// Algorithm: Calls RegEnumKey to loop through the reg keys and create a
+// list of verbs, which are then collected into one
+// larger list. Also, flags and attribs are parsed out.
+//
+// History: dd-mmm-yy Author Comment
+// 12-Sep-95 davidwor modified to make thread-safe
+// 08-Sep-95 davidwor optimized caching code
+// 14-Jul-95 t-gabes Author
+//
+// Notes:
+// OLEVERB flags are given default values if they are not in
+// reg db. This works well for OLE 1.0
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumVerb_MakeVerbList)
+STDAPI MakeVerbList
+ (HKEY hkey,
+ REFCLSID rclsid,
+ LPVERBLIST *ppVerbList)
+{
+ VDATEHEAP();
+
+ LONG cbValue;
+ LPVERBLIST pVerbList;
+ OLECHAR szBuf[MAX_VERB]; // regdb buffer
+ OLEVERB * rgVerbs = NULL; // verb info array
+ OLECHAR * pszNames = NULL; // list of NULL-delimited verb names
+ DWORD cchSpace = 0; // space left for verb names (in bytes)
+ DWORD cchName; // size of one name (in bytes)
+ DWORD cVerbs; // number of verbs
+ DWORD iVerbs; // verb array index
+ LONG maxVerbIdx = 0;
+ LONG maxVerbNum = OLEIVERB_LOWEST;
+ LONG minVerbNum = OLEIVERB_LOWEST - 1;
+ HRESULT hresult = NOERROR;
+
+ VDATEPTROUT(ppVerbList, LPVERBLIST);
+ *ppVerbList = NULL;
+
+ if (NULL == hkey)
+ {
+ /*
+ * No verbs registered
+ */
+
+ cbValue = sizeof(szBuf);
+
+ // read the default verb name from the reg db
+ if (ERROR_SUCCESS != RegQueryValue(
+ HKEY_CLASSES_ROOT,
+ DEFVERB,
+ szBuf,
+ &cbValue))
+ {
+ // when all else fails, use the string "Edit"
+ _xstrcpy(szBuf, EDIT);
+ cbValue = sizeof(EDIT);
+ }
+
+ pVerbList = (LPVERBLIST)PrivMemAlloc(sizeof(VERBLIST) + cbValue);
+ if (NULL == pVerbList)
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ // fill out a single verb with the defaults
+ pVerbList->cRef = 0;
+ pVerbList->clsid = rclsid;
+ pVerbList->cVerbs = 1;
+ pVerbList->oleverb[0].lVerb = 0;
+ pVerbList->oleverb[0].fuFlags = MF_STRING | MF_UNCHECKED | MF_ENABLED;
+ pVerbList->oleverb[0].grfAttribs = OLEVERBATTRIB_ONCONTAINERMENU;
+ pVerbList->oleverb[0].lpszVerbName = (LPOLESTR)&pVerbList->oleverb[1];
+ memcpy(pVerbList->oleverb[0].lpszVerbName, szBuf, cbValue);
+
+ *ppVerbList = pVerbList;
+ return NOERROR;
+ }
+
+ /*
+ * Have registered verbs
+ */
+
+ // determine number of subkeys
+ hresult = RegQueryInfoKey(
+ hkey, NULL, NULL, NULL, &cVerbs,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ if (ERROR_SUCCESS != hresult || !cVerbs)
+ {
+ // they have a "Verb" key but no verb subkeys
+ hresult = ResultFromScode(OLEOBJ_E_NOVERBS);
+ goto errRtn;
+ }
+
+ // preallocate this much space for verb names (in bytes)
+ cchSpace = sizeof(OLECHAR) * cVerbs * 32;
+
+ // allocate the VerbList with space for each OLEVERB
+ // and space for 32 characters for each verb name
+ pVerbList = (LPVERBLIST)PrivMemAlloc(
+ sizeof(VERBLIST) +
+ sizeof(OLEVERB) * (cVerbs - 1) +
+ cchSpace);
+
+ if (NULL == pVerbList)
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ pVerbList->cRef = 0;
+ pVerbList->clsid = rclsid;
+ pVerbList->cVerbs = cVerbs;
+
+ // Allocate temporary storage for the verbs. Later we'll move the verbs
+ // from this list into the final VerbList in sorted order.
+ rgVerbs = (OLEVERB *)PrivMemAlloc(sizeof(OLEVERB) * cVerbs);
+
+ if (NULL == rgVerbs)
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ // point pszNames at the first verb name
+ pszNames = (OLECHAR *)&pVerbList->oleverb[cVerbs];
+
+ for (iVerbs = 0; iVerbs < cVerbs; iVerbs++)
+ {
+ LPOLESTR psz = pszNames;
+
+ // read a verb number
+ hresult = RegEnumKey(hkey, iVerbs, szBuf, MAX_VERB);
+ if (NOERROR != hresult)
+ goto errRtn;
+
+ // this is how much space remains
+ cbValue = cchSpace;
+
+ // read a verb name on the verb number
+ hresult = RegQueryValue(hkey, szBuf, pszNames, &cbValue);
+ if (NOERROR != hresult)
+ goto errRtn;
+
+ // for safety, make sure verb name isn't too long
+ if (cbValue > (MAX_VERB + 8) * sizeof(OLECHAR))
+ {
+ cbValue = (MAX_VERB + 8) * sizeof(OLECHAR);
+ pszNames[MAX_VERB + 8 - 1] = OLESTR('\0');
+ }
+
+ rgVerbs[iVerbs].lVerb = Atol(szBuf);
+
+ if (rgVerbs[iVerbs].lVerb > maxVerbNum)
+ {
+ maxVerbNum = rgVerbs[iVerbs].lVerb;
+ maxVerbIdx = iVerbs;
+ }
+
+ rgVerbs[iVerbs].fuFlags = MF_STRING | MF_UNCHECKED | MF_ENABLED;
+ rgVerbs[iVerbs].grfAttribs = OLEVERBATTRIB_ONCONTAINERMENU;
+
+ // see if the verb name is followed by a delimiter
+ while (*psz && *psz != DELIM[0])
+ psz++;
+
+ // determine size of verb name (in characters)
+ cchName = psz - pszNames + 1;
+
+ if (*psz == DELIM[0])
+ {
+ // Parse the menu flags and attributes by finding each delimiter
+ // and stuffing a 0 over it. This breaks the string into three
+ // parts which can be handled separately.
+ LPOLESTR pszFlags;
+
+ *psz++ = OLESTR('\0'); // replace delimiter with 0
+ pszFlags = psz; // remember start of flags
+
+ while (*psz && *psz != DELIM[0])
+ psz++;
+
+ if (*psz == DELIM[0])
+ {
+ *psz++ = OLESTR('\0'); // replace delimiter with 0
+ if (*psz != 0)
+ rgVerbs[iVerbs].grfAttribs = Atol(psz);
+ }
+
+ // now that the flags portion ends with a 0 we can parse it
+ if (*pszFlags != 0)
+ rgVerbs[iVerbs].fuFlags = Atol(pszFlags);
+ }
+
+ rgVerbs[iVerbs].lpszVerbName = pszNames;
+
+ pszNames += cchName; // move pointer to next verb name position
+ cchSpace -= cchName; // calculate how much space is left
+ }
+
+ // sort the verbs while putting them in the final verb list
+ for (iVerbs = 0; iVerbs < cVerbs; iVerbs++)
+ {
+ LONG minCurNum = maxVerbNum,
+ minCurIdx = maxVerbIdx;
+ LONG idx, num;
+
+ // find next verb
+ for (idx = 0; idx < (LONG)cVerbs; idx++)
+ {
+ num = rgVerbs[idx].lVerb;
+ if (num < minCurNum && num > minVerbNum)
+ {
+ minCurNum = num;
+ minCurIdx = idx;
+ }
+ }
+
+ pVerbList->oleverb[iVerbs].lVerb = rgVerbs[minCurIdx].lVerb;
+ pVerbList->oleverb[iVerbs].fuFlags = rgVerbs[minCurIdx].fuFlags;
+ pVerbList->oleverb[iVerbs].grfAttribs = rgVerbs[minCurIdx].grfAttribs;
+ pVerbList->oleverb[iVerbs].lpszVerbName = rgVerbs[minCurIdx].lpszVerbName;
+
+ minVerbNum = minCurNum;
+ }
+
+ *ppVerbList = pVerbList;
+
+errRtn:
+ if (rgVerbs)
+ PrivMemFree(rgVerbs);
+ if (hkey)
+ CLOSE(hkey);
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: OleReleaseEnumVerbCache
+//
+// Synopsis: Releases the cache if necessary
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: Just call Release method
+//
+// History: dd-mmm-yy Author Comment
+// 12-Sep-95 davidwor modified to make thread-safe
+// 18-Jul-95 t-gabes Author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(OleReleaseEnumVerbCache)
+STDAPI OleReleaseEnumVerbCache(void)
+{
+ CEnumVerb* pEnum;
+
+ pEnum = (CEnumVerb *)InterlockedExchange((long *)&g_EnumCache.pEnum, 0);
+
+ if (NULL != pEnum)
+ {
+ pEnum->Release();
+ LEDebugOut((DEB_TRACE, "VERB Enumerator cache released\n"));
+ }
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumVerb::CEnumVerb
+//
+// Synopsis: Constructor for the verb enumerator
+//
+// Effects:
+//
+// Arguments:
+// [pVerbs] -- ptr to the verb list
+// [iVerb] -- the index of the verb we're on
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 12-Sep-95 davidwor modified to make thread-safe
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumVerb_ctor)
+CEnumVerb::CEnumVerb
+ (LPVERBLIST pVerbs,
+ LONG iVerb)
+{
+ VDATEHEAP();
+
+ m_cRef = 1;
+ m_iVerb = iVerb;
+ m_VerbList = pVerbs;
+
+ // AddRef the VerbList since we now have a reference to it
+ InterlockedIncrement((long *)&m_VerbList->cRef);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumVerb::QueryInterface
+//
+// Synopsis: returns the interface implementation
+//
+// Effects:
+//
+// Arguments: [iid] -- the requested interface id
+// [ppv] -- where to put a pointer to the interface
+//
+// Requires:
+//
+// Returns: NOERROR, E_NOINTERFACE
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumOLEVERB
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumVerb_QueryInterface)
+STDMETHODIMP CEnumVerb::QueryInterface(REFIID iid, LPVOID FAR* ppv)
+{
+ VDATEHEAP();
+
+ VDATEPTROUT(ppv, LPVOID);
+
+ if (IsEqualIID(iid, IID_IUnknown) ||
+ IsEqualIID(iid, IID_IEnumOLEVERB))
+ {
+ *ppv = this;
+ AddRef();
+ return NOERROR;
+ }
+
+ *ppv = NULL;
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumVerb::AddRef
+//
+// Synopsis: increments the reference count
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new reference count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumOLEVERB
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 12-Sep-95 davidwor modified to make thread-safe
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumVerb_AddRef)
+STDMETHODIMP_(ULONG) CEnumVerb::AddRef(void)
+{
+ VDATEHEAP();
+
+ return InterlockedIncrement((long *)&m_cRef);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumVerb::Release
+//
+// Synopsis: decrements the reference count
+//
+// Effects: will delete the object when ref count goes to zero
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: ULONG -- the new ref count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumOLEVERB
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 12-Sep-95 davidwor modified to make thread-safe
+// 18-Jul-95 t-gabes release verb cache when finished
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumVerb_Release)
+STDMETHODIMP_(ULONG) CEnumVerb::Release(void)
+{
+ VDATEHEAP();
+
+ ULONG cRef;
+
+ cRef = InterlockedDecrement((long *)&m_cRef);
+ if (0 == cRef)
+ {
+ if (0 == InterlockedDecrement((long *)&m_VerbList->cRef))
+ {
+ // no more references to m_VerbList so free it
+ PrivMemFree(m_VerbList);
+ LEDebugOut((DEB_TRACE, "VERB Enumerator verb list released\n"));
+ }
+
+ delete this;
+ return 0;
+ }
+
+ return cRef;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumVerb::Next
+//
+// Synopsis: gets the next [cverb] verbs from the verb list
+//
+// Effects:
+//
+// Arguments: [cverb] -- the number of verbs to get
+// [rgverb] -- where to put the verbs
+// [pcverbFetched] -- where to put the num of verbs retrieved
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumOLEVERB
+//
+// Algorithm: loops through [cverb] times and grabs the info from the
+// reg db
+//
+// History: dd-mmm-yy Author Comment
+// 17-Jul-95 t-gabes rewrote to use cache
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumVerb_Next)
+STDMETHODIMP CEnumVerb::Next
+ (ULONG cverb,
+ LPOLEVERB rgverb,
+ ULONG FAR* pcverbFetched)
+{
+ VDATEHEAP();
+
+ ULONG iVerb; // number successfully fetched
+ HRESULT hresult = NOERROR;
+
+ if (!rgverb)
+ {
+ if (pcverbFetched)
+ *pcverbFetched = 0;
+ VDATEPTROUT(rgverb, OLEVERB);
+ }
+
+ if (pcverbFetched)
+ {
+ VDATEPTROUT(pcverbFetched, ULONG);
+ }
+ else if (cverb != 1)
+ {
+ // the spec says that if pcverbFetched == NULL, then
+ // the count of elements to fetch must be 1
+ return ResultFromScode(E_INVALIDARG);
+ }
+
+ for (iVerb = 0; iVerb < cverb; iVerb++)
+ {
+ if (m_iVerb >= (LONG)m_VerbList->cVerbs)
+ {
+ // no more
+ hresult = ResultFromScode(S_FALSE);
+ goto errRtn;
+ }
+
+ OLEVERB *lpov = &m_VerbList->oleverb[m_iVerb++];
+
+ rgverb[iVerb].lVerb = lpov->lVerb;
+ rgverb[iVerb].fuFlags = lpov->fuFlags;
+ rgverb[iVerb].grfAttribs = lpov->grfAttribs;
+ rgverb[iVerb].lpszVerbName = UtDupString(lpov->lpszVerbName);
+ }
+
+errRtn:
+ if (pcverbFetched)
+ {
+ *pcverbFetched = iVerb;
+ }
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumVerb::Skip
+//
+// Synopsis: skips [c] verbs in the enumeration
+//
+// Effects:
+//
+// Arguments: [c] -- the number of verbs to skip
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumOLEVERB
+//
+// Algorithm: adds [c] to the verb index
+//
+// History: dd-mmm-yy Author Comment
+// 17-Jul-95 t-gabes rewrote to use cache
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumVerb_Skip)
+STDMETHODIMP CEnumVerb::Skip(ULONG c)
+{
+ VDATEHEAP();
+
+ m_iVerb += c;
+ if (m_iVerb > (LONG)m_VerbList->cVerbs)
+ {
+ // skipping too many
+ m_iVerb = m_VerbList->cVerbs;
+ return ResultFromScode(S_FALSE);
+ }
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumVerb::Reset
+//
+// Synopsis: resets the verb enumeration to the beginning
+//
+// Effects:
+//
+// Arguments: void
+//
+// Requires:
+//
+// Returns: NOERROR
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumOLEVERB
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 17-Jul-95 t-gabes rewrote to use cache
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumVerb_Reset)
+STDMETHODIMP CEnumVerb::Reset(void)
+{
+ VDATEHEAP();
+
+ m_iVerb = 0;
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumVerb::Clone
+//
+// Synopsis: creates a copy of the enumerator
+//
+// Effects:
+//
+// Arguments: [ppenum] -- where to put a pointer to the new clone
+//
+// Requires:
+//
+// Returns: NOERROR, E_OUTOFMEMORY
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation: IEnumOLEVERB
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Dec-93 alexgo 32bit port
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumVerb_Clone)
+STDMETHODIMP CEnumVerb::Clone(LPENUMOLEVERB FAR* ppenum)
+{
+ VDATEHEAP();
+
+ VDATEPTROUT(ppenum, LPENUMOLEVERB);
+
+ *ppenum = new FAR CEnumVerb(m_VerbList, m_iVerb);
+ if (!*ppenum)
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumVerb::GetRefCount
+//
+// Synopsis: Gets the reference count for the class
+//
+// Effects:
+//
+// Arguments: none
+//
+// Requires:
+//
+// Returns: ref count
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 12-Jul-95 t-gabes Author
+//
+// Notes: This is needed so OleRegEnumVerbs knows when to dup the cache
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(CEnumVerb_GetRefCount)
+ULONG CEnumVerb::GetRefCount (void)
+{
+ VDATEHEAP();
+
+ return m_cRef;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CEnumVerb::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppszDump] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+HRESULT CEnumVerb::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump;
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "No. of References = " << m_cRef << endl;
+
+ dstrDump << pszPrefix << "Address of verb list = " << m_VerbList << endl;
+
+ dstrDump << pszPrefix << "Current Verb Number = " << m_iVerb << endl;
+
+ // cleanup and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCEnumVerb, public (_DEBUG only)
+//
+// Synopsis: calls the CEnumVerb::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pEV] - pointer to CEnumVerb
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Feb-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCEnumVerb(CEnumVerb *pEV, ULONG ulFlag, int nIndentLevel)
+{
+ char *pszDump;
+
+ if (NULL == pEV)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ pEV->Dump(&pszDump, ulFlag, nIndentLevel);
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
diff --git a/private/ole32/ole232/stdimpl/srvhndlr.cpp b/private/ole32/ole232/stdimpl/srvhndlr.cpp
new file mode 100644
index 000000000..4b937e269
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/srvhndlr.cpp
@@ -0,0 +1,1671 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: srvhndlr.cpp
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 9-18-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+
+#include <le2int.h>
+
+#ifdef SERVER_HANDLER
+
+#include "handler.hxx"
+
+ASSERTDATA
+
+#define DH_INIT_NEW 32
+
+DECLARE_INFOLEVEL(Hdl);
+#if DBG==1
+#endif
+
+// Note: the following variable should be per appartment
+// global variable
+unsigned long gdwServerHandlerOptions;
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateServerHandler
+//
+// Synopsis:
+//
+// Arguments: [pClsID] --
+// [punk] --
+// [pClntHndlr] --
+// [ppSrvHdlr] --
+//
+// Returns:
+//
+// History: 10-20-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CreateServerHandler(const CLSID *pClsID, IUnknown *punk, IClientSiteHandler *pClntHndlr, IServerHandler **ppSrvHdlr)
+{
+ HdlDebugOut((DEB_SERVERHANDLER, "IN CreateServerHandler(pUnk:%p)(pClntHndlr:%p)\n",punk, pClntHndlr));
+ Assert((punk != NULL && "CreateServerHandler: invalid punk"));
+ HRESULT hres = NOERROR;
+
+ // verify the class id for the default serverhandler
+
+ if (IsEqualCLSID(*pClsID, CLSID_ServerHandler))
+ {
+ *ppSrvHdlr = new CServerHandler(punk);
+
+ if (*ppSrvHdlr == NULL)
+ {
+ hres = E_OUTOFMEMORY;
+ }
+ else if (pClntHndlr)
+ {
+ ((CServerHandler *) *ppSrvHdlr)->SetClientSiteHandler(pClntHndlr);
+ }
+ }
+ else
+ {
+ HdlDebugOut((DEB_ERROR, "CreateServerHandler: invalid CLSID\n"));
+ *ppSrvHdlr = NULL;
+ hres = E_NOINTERFACE;
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER, "OUT CreateServerHandler(ppSrvHdlr:%p) return %lx\n",*ppSrvHdlr,hres));
+ return hres;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::CServerHandler
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: 8-22-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CServerHandler::CServerHandler(IUnknown *pUnk)
+{
+ _cRefs = 1; // this is the first addref for the serverhandler interface
+ _cTotalRefs = 1; // same
+
+ _dwId = ID_ServerHandler;
+ _pUnkObj = pUnk;
+ _pOO = NULL;
+
+ _pCSH= NULL;
+ _OpState = OpState_NoOp;
+
+ _OleContainer._cRefs = 0;
+ _OleContainer._dwId = ID_Container;
+ _OleContainer._pSrvHndlr = this;
+ _OleContainer._pOContDelegate = NULL;
+
+ _OleInPlaceSite._cRefs = 0;
+ _OleInPlaceSite._dwId = ID_InPlaceSite;
+ _OleInPlaceSite._pSrvHndlr = this;
+ _OleInPlaceSite._pOIPSDelegate = NULL;
+
+ _OleClientSite._cRefs = 0;
+ _OleClientSite._dwId = ID_ClientSite;
+ _OleClientSite._pSrvHndlr = this;
+ _OleClientSite._pCSDelegate = NULL;
+
+ _OleClientSiteActive._cRefs = 0;
+ _OleClientSiteActive._dwId = ID_ClientSiteActive;
+ _OleClientSiteActive._pSrvHndlr = this;
+ _OleClientSiteActive._pCSDelegate = NULL;
+
+ _pUnkObj->AddRef();
+
+ pOutSrvInPlace = NULL;
+ _hrCanInPlaceActivate = S_FALSE;
+
+ return;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::~CServerHandler
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: 8-22-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CServerHandler::~CServerHandler()
+{
+ if (pOutSrvInPlace)
+ {
+ delete pOutSrvInPlace;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::GetContainerDelegate
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(IOleContainer *) CServerHandler::GetContainerDelegate(void)
+{
+ IOleContainer *pOCont = NULL;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::GetContainerDelegate\n", this));
+
+ if (_OleContainer._pOContDelegate == NULL)
+ {
+ if (_pCSH->PrivQueryInterface(ID_ClientSite, IID_IOleContainer, (void **)&pOCont) == NOERROR)
+ {
+ _OleContainer._pOContDelegate = pOCont;
+ }
+ HdlAssert((_OleContainer._pOContDelegate != NULL));
+ }
+ else
+ {
+ pOCont = _OleContainer._pOContDelegate;
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::GetContainerDelegate\n", this));
+ return pOCont;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::ReleaseObject
+//
+// Synopsis:
+//
+// Arguments: (none)
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(void) CServerHandler::ReleaseObject()
+{
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::ReleaseObject\n", this));
+
+ if (_pOO)
+ {
+ HdlDebugOut((DEB_SERVERHANDLER, "%p ___ CServerHandler::ReleaseObject OO(%p)\n", this, _pOO));
+ _pOO->Release();
+ _pOO = NULL;
+ }
+
+ if (_pUnkObj)
+ {
+ HdlDebugOut((DEB_SERVERHANDLER, "%p ___ CServerHandler::ReleaseObject pUnkObj(%p)\n", this, _pUnkObj));
+ _pUnkObj->Release();
+ _pUnkObj = NULL;
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::ReleaseObject\n", this));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::QueryInterface
+//
+// Synopsis:
+//
+// Arguments: [riid] --
+// [ppv] --
+//
+// Returns:
+//
+// History: 9-18-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::QueryInterface( REFIID riid, void **ppv )
+{
+ HRESULT hresult = NOERROR;
+ VDATEHEAP();
+
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p _IN CServerHandler::QueryInterface (%lx, %p)\n", this, riid, ppv));
+
+ if ( IsEqualIID(riid, IID_IUnknown)
+ || IsEqualIID(riid, IID_IServerHandler) )
+ {
+ *ppv = (void FAR *)this;
+ AddRef();
+ }
+ else
+ {
+ hresult = E_NOINTERFACE;
+ *ppv = NULL;
+ }
+
+
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p OUT CServerHandler::QueryInterface (%lx)[%p]\n", this, hresult, *ppv));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::AddRef
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 9-18-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CServerHandler::AddRef( void )
+{
+ VDATEHEAP();
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p _IN CServerHandler::AddRef\n", this));
+
+ InterlockedIncrement((long *)&_cRefs);
+ PrivAddRef(_dwId);
+
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p OUT CServerHandler::AddRef (%ld)\n", this, _cRefs));
+ return _cRefs;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::Release
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 9-18-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CServerHandler::Release( void )
+{
+ ULONG cRefs;
+ ULONG cRefsUnk;
+ VDATEHEAP();
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p _IN CServerHandler::Release\n", this));
+
+ cRefs = _cRefs - 1;
+ HdlAssert((cRefs >= 0 ));
+
+ cRefsUnk = PrivRelease(_dwId, cRefs);
+ HdlAssert(( cRefsUnk >= cRefs));
+
+ // release all objects if refcount on the serverhandler becomes zero
+ if (0 == InterlockedDecrement( (long*) &_cRefs) )
+ {
+ ReleaseObject();
+ return 0;
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p OUT CServerHandler::Release (%ld)\n", this, cRefs));
+ return cRefs;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::RunAndInitialize
+//
+// Synopsis:
+//
+// Arguments: [pRunInit] --
+//
+// Returns:
+//
+// History: 9-18-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::RunAndInitialize (INSRVRUN *pInSrvRun, OUTSRVRUN **ppOutSrvRun)
+{
+ HRESULT hresult = NOERROR;
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::RunAndInitialize(%p)\n", this,pInSrvRun));
+ IPersistStorage *pPStg = NULL;
+ IDataObject *pDO = NULL;
+ IOleObject *pOO = NULL;
+ COutSrvRun *pOutSrvRun;
+
+ CInSrvRun *pISR = (CInSrvRun *)pInSrvRun;
+
+ OperationState os = GetOpState();
+ os = SetOpState(OpState_RunAndInitialize);
+ _dwOperation = pInSrvRun->dwOperation;
+
+ Assert((ppOutSrvRun != NULL));
+
+ pISR->DumpRun();
+
+ if ( (pOutSrvRun = new COutSrvRun) == NULL)
+ {
+ hresult = E_OUTOFMEMORY;
+ goto errRtn;
+ }
+
+ *ppOutSrvRun = (OUTSRVRUN *)pOutSrvRun;
+
+ Assert((_pUnkObj != NULL));
+
+
+ // QI for the IPersitStorage
+ if (pInSrvRun->dwOperation & OP_NeedPersistStorage)
+ {
+ hresult = _pUnkObj->QueryInterface(IID_IPersistStorage, (void**) &pPStg);
+ if (FAILED(hresult))
+ {
+ goto errRtn;
+ }
+ pOutSrvRun->pPStg = pPStg;
+
+ if (NULL != pInSrvRun->pStg)
+ {
+ if( (pInSrvRun->dwInFlags & DH_INIT_NEW) )
+ {
+ hresult = pPStg->InitNew(pInSrvRun->pStg);
+ }
+ else
+ {
+ hresult = pPStg->Load(pInSrvRun->pStg);
+ }
+
+ pOutSrvRun->hrPStg = hresult;
+
+ if (FAILED(hresult))
+ {
+ goto errRtn;
+ }
+ }
+ }
+
+
+ // QI for the IDataObject
+ if (pInSrvRun->dwOperation & OP_NeedDataObject)
+ {
+ hresult = _pUnkObj->QueryInterface(IID_IDataObject, (void**) &pDO);
+ if (FAILED(hresult))
+ {
+ goto errRtn;
+ }
+ pOutSrvRun->pDO = pDO;
+ }
+
+
+ // QI for the OleObject
+ if (pInSrvRun->dwOperation & OP_NeedOleObject)
+ {
+ hresult = _pUnkObj->QueryInterface(IID_IOleObject, (void**) &pOO);
+ if (FAILED(hresult))
+ {
+ goto errRtn;
+ }
+
+ HdlAssert((_pOO == NULL));
+ _pOO = pOO;
+ _pOO->AddRef(); // Hold an extra reference here in the SvrHndlr.
+
+ pOutSrvRun->pOO = pOO;
+ }
+
+ if (_pOO)
+ {
+ // set clientsite and hostname
+ if (pInSrvRun->dwOperation & OP_GotClientSite)
+ {
+ _OleClientSite._pCSDelegate = _pCSH;
+ _OleClientSite._dwId = ID_ClientSite;
+
+ // Set up the ClientSite from the ClientSiteHandler
+ _pOO->SetClientSite((IOleClientSite *)&_OleClientSite);
+ }
+ if (pInSrvRun->pszContainerObj)
+ {
+ hresult = _pOO->SetHostNames (pInSrvRun->pszContainerApp,
+ pInSrvRun->pszContainerObj);
+ if (FAILED(hresult))
+ {
+ pOutSrvRun->hrSetHostNames = hresult;
+ goto errRtn;
+ }
+ }
+
+ hresult = _pOO->Advise ((IAdviseSink *)pInSrvRun->pAS,
+ &(pOutSrvRun->dwOutFlag));
+ if(FAILED(hresult))
+ {
+ pOutSrvRun->hrAdvise = hresult;
+ goto errRtn;
+ }
+
+ // set the moniker if available
+ if (pInSrvRun->pMnk)
+ {
+ _pOO->SetMoniker(OLEWHICHMK_OBJREL, pInSrvRun->pMnk);
+ }
+
+ // get the UserClassID
+ if (pInSrvRun->dwOperation & OP_NeedUserClassID)
+ {
+ // Note: UserClassID should be a variable of OutSrvRun
+ pOutSrvRun->pUserClassID = new CLSID;
+ if (pOutSrvRun->pUserClassID)
+ {
+ _pOO->GetUserClassID(pOutSrvRun->pUserClassID);
+ }
+ }
+ }
+
+ pOutSrvRun->DumpRun();
+
+errRtn:
+ if(FAILED(hresult))
+ {
+ // Stop the server we just launced
+ SafeReleaseAndNULL( (IUnknown**) &(pOutSrvRun->pOO) );
+ SafeReleaseAndNULL( (IUnknown**) &(pOutSrvRun->pDO) );
+ SafeReleaseAndNULL( (IUnknown**) &(pOutSrvRun->pPStg) );
+ }
+
+ _dwOperation = 0;
+ SetOpState(os);
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::RunAndInitialize return %lx\n", this, hresult));
+
+ return hresult;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::RunAndDoVerb
+//
+// Synopsis:
+//
+// Arguments: [pRunDoVerb] --
+//
+// Returns:
+//
+// History: 9-18-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::RunAndDoVerb (INSRVRUN *pInSrvRun, OUTSRVRUN **ppOutSrvRun)
+{
+ HRESULT hresult = NOERROR;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::RunAndDoVerb(%p)\n", this,pInSrvRun));
+
+ HdlAssert((FALSE && "Method not implemented"));
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::RunAndDoVerb return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::DoVerb
+//
+// Synopsis:
+//
+// Arguments: [pDoVerb] --
+//
+// Returns:
+//
+// History: 9-18-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::DoVerb (INSRVRUN *pInSrvRun, OUTSRVRUN **ppOutSrvRun)
+{
+ HRESULT hresult = E_FAIL;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::DoVerb(%p)\n", this,pInSrvRun));
+
+ IOleClientSite *pOCSActive = NULL;
+ CInSrvRun *pISR = (CInSrvRun *)pInSrvRun;
+ COutSrvRun *pOutSrvRun;
+
+ Assert(( ppOutSrvRun != NULL));
+ pISR->DumpDoVerb();
+
+
+ if ( (pOutSrvRun = new COutSrvRun) == NULL)
+ {
+ goto errRtn;
+ }
+
+ *ppOutSrvRun = (OUTSRVRUN *)pOutSrvRun;
+ if (_pOO)
+ {
+ _dwOperation = pInSrvRun->dwOperation;
+ OperationState os = GetOpState();
+ os = SetOpState(OpState_DoVerb);
+
+ if (pInSrvRun->dwOperation & OP_GotClientSiteActive)
+ {
+ // Set up our OleClientSiteActive
+ _OleClientSiteActive._pCSDelegate = _pCSH;
+ _OleClientSiteActive._dwId = ID_ClientSiteActive;
+ pOCSActive = (IOleClientSite *)&_OleClientSiteActive;
+ }
+
+ if (pInSrvRun->dwOperation & OP_GotInPlaceSite)
+ {
+ _hrCanInPlaceActivate = pInSrvRun->dwInPlace;
+ _OleInPlaceSite._pOIPSDelegate = _pCSH;
+
+ }
+
+ hresult = _pOO->DoVerb(pInSrvRun->iVerb, pInSrvRun->lpmsg, pOCSActive,
+ pInSrvRun->lindex, pInSrvRun->hwndParent, pInSrvRun->lprcPosRect);
+
+ // pass back flag if OleInPlaceSite is used or not
+ if (pInSrvRun->dwOperation & OP_GotClientSiteActive)
+ {
+ if (_OleClientSiteActive._cRefs != 0)
+ {
+ pOutSrvRun->dwOperation |= OP_GotClientSiteActive;
+ }
+ else
+ {
+ _OleClientSiteActive._pCSDelegate = NULL;
+ }
+
+ }
+
+ // pass back if OleInPlaceSite is used
+ if (pInSrvRun->dwOperation & OP_GotInPlaceSite)
+ {
+ if (_OleInPlaceSite._cRefs != 0)
+ {
+ pOutSrvRun->dwOperation |= OP_GotInPlaceSite;
+ }
+ else
+ {
+ _OleInPlaceSite._pOIPSDelegate = NULL;
+ }
+ }
+
+ // pass back if OleContainer is used
+ if (pInSrvRun->dwOperation & OP_GotContainer)
+ {
+ if (_OleContainer._cRefs != 0)
+ {
+ pOutSrvRun->dwOperation |= OP_GotContainer;
+ }
+ else
+ {
+ _OleContainer._pOContDelegate = NULL;
+ }
+ }
+
+
+ SetOpState(os);
+ }
+
+errRtn:
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::DoVerb return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::CloseAndRelease
+//
+// Synopsis:
+//
+// Arguments: [dwClose] --
+//
+// Returns:
+//
+// History: 9-18-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::CloseAndRelease(DWORD dwClose)
+{
+ HRESULT hresult = NOERROR;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::CloseAndRelease(%ld)\n", this, dwClose));
+
+ // CODEWORK: maybe just assert that these interface ptrs are non-NULL
+
+ if (_pUnkObj)
+ {
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::Release pUnkObj(%p) release\n", this, _pUnkObj));
+ _pUnkObj->Release();
+ _pUnkObj = NULL;
+ }
+
+ if (_pOO)
+ {
+ _pOO->Close(dwClose);
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::Release OO(%p) release\n", this, _pOO));
+ _pOO->Release();
+ _pOO = NULL;
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::CloseAndRelease return %lx\n", this, hresult));
+ return hresult;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::SetClientSiteHandler
+//
+// Synopsis:
+//
+// Arguments: [pCSH] --
+//
+// Returns:
+//
+// History: 10-10-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::SetClientSiteHandler(IClientSiteHandler *pCSH)
+{
+ HRESULT hresult = NOERROR;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::SetClientSiteHandler(%p)\n", this, pCSH));
+ if (pCSH)
+ {
+ _pCSH = pCSH;
+ }
+ else
+ {
+ hresult = E_INVALIDARG;
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::SetClientSiteHandler return %lx\n", this, hresult));
+ return hresult;
+}
+
+
+
+// IOleWindow Methods
+
+STDMETHODIMP CServerHandler::COleInPlaceSiteImpl::GetWindow(
+ /* [out] */ HWND __RPC_FAR *phwnd)
+{
+ HRESULT hresult = NOERROR;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleInPlaceSiteImpl::GetWindow\n", this));
+ if ( (_pSrvHndlr->GetOpState() == OpState_DoVerb)
+ && (_pSrvHndlr->pOutSrvInPlace->dwOperation & OP_GetWindow) )
+ {
+ HdlAssert(( _pSrvHndlr->pOutSrvInPlace ));
+ HdlAssert(( _pSrvHndlr->pOutSrvInPlace->hwnd ));
+ *phwnd = _pSrvHndlr->pOutSrvInPlace->hwnd;
+ }
+ else
+ {
+ HdlAssert(( _pOIPSDelegate != NULL && "CServerHandler::OleInPlaceSite invalid OleInPlace object!\n"));
+ hresult = _pOIPSDelegate->GetWindow(phwnd);
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleCInPlaceSiteImpl::GetWindow return %lx\n", this, hresult));
+ return hresult;
+}
+
+//
+// IOleInPlaceSite Methods
+//
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleInPlaceSiteImpl::ContextSensitiveHelp
+//
+// Synopsis:
+//
+// Arguments: [fEnterMode] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleInPlaceSiteImpl::ContextSensitiveHelp(
+ /* [in] */ BOOL fEnterMode)
+{
+ HRESULT hresult = NOERROR;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleCInPlaceSiteImpl::ContextSensitiveHelp\n", this));
+
+ HdlAssert(( _pOIPSDelegate != NULL && "CServerHandler::OleInPlaceSite invalid OleInPlace object!\n"));
+ hresult = _pOIPSDelegate->ContextSensitiveHelp(fEnterMode);
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleCInPlaceSiteImpl::ContextSensitiveHelp return %lx\n", this, hresult));
+ return hresult;
+}
+
+
+
+STDMETHODIMP CServerHandler::COleInPlaceSiteImpl::CanInPlaceActivate( void)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleInPlaceSiteImpl::CanInPlaceActivate\n", this));
+
+ if (_pSrvHndlr->GetOpState() == OpState_DoVerb)
+ {
+ hresult = _pSrvHndlr->_hrCanInPlaceActivate;
+ }
+ else
+ {
+ // call back to client site
+ HdlAssert(( _pOIPSDelegate != NULL && "CServerHandler::OleInPlaceSite invalid OleInPlace object!\n"));
+ hresult = _pOIPSDelegate->CanInPlaceActivate();
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleInPlaceSiteImpl::CanInPlaceActivate return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleInPlaceSiteImpl::OnInPlaceActivate
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleInPlaceSiteImpl::OnInPlaceActivate( void)
+{
+ HRESULT hresult = NOERROR;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleInPlaceSiteImpl::OnInPlaceActivate\n", this));
+
+ if (_pSrvHndlr->GetOpState() == OpState_DoVerb)
+ {
+ CInSrvInPlace InSrvInPlace;
+ InSrvInPlace.dwInFlags = 0;
+ InSrvInPlace.dwOperation = 0;
+
+ // Note: we do not knwo on which OleClientSite
+ // ShowWindow will be called
+ InSrvInPlace.dwDelegateID = ID_ClientSite;
+
+ // set operation for this call
+ InSrvInPlace.dwOperation |= OP_OnInPlaceActivate;
+ InSrvInPlace.dwOperation |= OP_GetWindow ;
+
+ // Note: the following operations do not work with some applications!
+ // it would save two more rpc calls!
+ //InSrvInPlace.dwOperation |= OP_GetWindowContext ;
+ //InSrvInPlace.dwOperation |= OP_OnShowWindow ;
+
+
+ // delete the old OutSrvRun data
+ if (_pSrvHndlr->pOutSrvInPlace)
+ {
+ delete _pSrvHndlr->pOutSrvInPlace;
+ _pSrvHndlr->pOutSrvInPlace = NULL;
+ }
+
+ // call back to client site
+ hresult = _pSrvHndlr->_pCSH->GoInPlaceActivate(&InSrvInPlace, (OUTSRVINPLACE **)&(_pSrvHndlr->pOutSrvInPlace));
+ HdlAssert((hresult == NOERROR));
+ HdlAssert((_pSrvHndlr->pOutSrvInPlace != NULL));
+
+ _pSrvHndlr->pOutSrvInPlace->Dump();
+ }
+ else
+ {
+ HdlAssert(( _pOIPSDelegate != NULL && "CServerHandler::OleInPlaceSite invalid OleInPlace object!\n"));
+ hresult = _pOIPSDelegate->OnInPlaceActivate();
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleInPlaceSiteImpl::OnInPlaceActivate return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleInPlaceSiteImpl::OnUIActivate
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleInPlaceSiteImpl::OnUIActivate( void)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleInPlaceSiteImpl::OnUIActivate\n", this));
+
+ HdlAssert(( _pOIPSDelegate != NULL && "CServerHandler::OleInPlaceSite invalid OleInPlace object!\n"));
+ hresult = _pOIPSDelegate->OnUIActivate();
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleInPlaceSiteImpl::OnUIActivate return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleInPlaceSiteImpl::GetWindowContext
+//
+// Synopsis:
+//
+// Arguments: [ppFrame] --
+// [ppDoc] --
+// [lprcPosRect] --
+// [lprcClipRect] --
+// [lpFrameInfo] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleInPlaceSiteImpl::GetWindowContext(
+ /* [out] */ IOleInPlaceFrame __RPC_FAR *__RPC_FAR *ppFrame,
+ /* [out] */ IOleInPlaceUIWindow __RPC_FAR *__RPC_FAR *ppDoc,
+ /* [out] */ LPRECT lprcPosRect,
+ /* [out] */ LPRECT lprcClipRect,
+ /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo)
+{
+ HRESULT hresult = NOERROR;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleInPlaceSiteImpl::GetWindowContext\n", this));
+
+ if ( (_pSrvHndlr->GetOpState() == OpState_DoVerb)
+ && (_pSrvHndlr->pOutSrvInPlace->dwOperation & OP_GetWindowContext) )
+
+ {
+ COutSrvInPlace *pOutSrvInPlace = _pSrvHndlr->pOutSrvInPlace;
+ *ppFrame = pOutSrvInPlace->pOIPFrame;
+ *ppDoc = pOutSrvInPlace->pOIPUIWnd;
+ lprcPosRect = pOutSrvInPlace->lprcPosRect;
+ lprcClipRect = pOutSrvInPlace->lprcClipRect;
+ lpFrameInfo = pOutSrvInPlace->lpFrameInfo;
+
+ }
+ else
+ {
+ HdlAssert(( _pOIPSDelegate != NULL && "CServerHandler::OleInPlaceSite invalid OleInPlace object!\n"));
+ hresult = _pOIPSDelegate->GetWindowContext(ppFrame, ppDoc,lprcPosRect, lprcClipRect, lpFrameInfo);
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleInPlaceSiteImpl::GetWindowContext return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleInPlaceSiteImpl::Scroll
+//
+// Synopsis:
+//
+// Arguments: [scrollExtant] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleInPlaceSiteImpl::Scroll(
+ /* [in] */ SIZE scrollExtant)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleInPlaceSiteImpl::Scroll\n", this));
+
+ HdlAssert(( _pOIPSDelegate != NULL && "CServerHandler::OleInPlaceSite invalid OleInPlace object!\n"));
+ hresult = _pOIPSDelegate->Scroll(scrollExtant);
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleInPlaceSiteImpl::Scroll return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleInPlaceSiteImpl::OnUIDeactivate
+//
+// Synopsis:
+//
+// Arguments: [fUndoable] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleInPlaceSiteImpl::OnUIDeactivate(
+ /* [in] */ BOOL fUndoable)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleInPlaceSiteImpl::OnUIDeactivate\n", this));
+
+ HdlAssert(( _pOIPSDelegate != NULL && "CServerHandler::OleInPlaceSite invalid OleInPlace object!\n"));
+ hresult = _pOIPSDelegate->OnUIDeactivate(fUndoable);
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleInPlaceSiteImpl::OnUIDeactivate return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleInPlaceSiteImpl::OnInPlaceDeactivate
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleInPlaceSiteImpl::OnInPlaceDeactivate( void)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleInPlaceSiteImpl::OnInPlaceDeactivate\n", this));
+
+ HdlAssert(( _pOIPSDelegate != NULL && "CServerHandler::OleInPlaceSite invalid OleInPlace object!\n"));
+ hresult = _pOIPSDelegate->OnInPlaceDeactivate();
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleInPlaceSiteImpl::OnInPlaceDeactivate return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleInPlaceSiteImpl::DiscardUndoState
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleInPlaceSiteImpl::DiscardUndoState( void)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleInPlaceSiteImpl::DiscardUndoState\n", this));
+
+ HdlAssert(( _pOIPSDelegate != NULL && "CServerHandler::OleInPlaceSite invalid OleInPlace object!\n"));
+ hresult = _pOIPSDelegate->DiscardUndoState();
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleInPlaceSiteImpl::DiscardUndoState return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleInPlaceSiteImpl::DeactivateAndUndo
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleInPlaceSiteImpl::DeactivateAndUndo( void)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleInPlaceSiteImpl::DeactivateAndUndo\n", this));
+
+ HdlAssert(( _pOIPSDelegate != NULL && "CServerHandler::OleInPlaceSite invalid OleInPlace object!\n"));
+ hresult = _pOIPSDelegate->DeactivateAndUndo();
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleInPlaceSiteImpl::DeactivateAndUndo return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleInPlaceSiteImpl::OnPosRectChange
+//
+// Synopsis:
+//
+// Arguments: [lprcPosRect] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleInPlaceSiteImpl::OnPosRectChange(
+ /* [in] */ LPCRECT lprcPosRect)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleInPlaceSiteImpl::OnPosRectChange\n", this));
+
+ HdlAssert(( _pOIPSDelegate != NULL && "CServerHandler::OleInPlaceSite invalid OleInPlace object!\n"));
+ hresult = _pOIPSDelegate->OnPosRectChange(lprcPosRect);
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleInPlaceSiteImpl::OnPosRectChange return %lx\n", this, hresult));
+ return hresult;
+}
+
+//
+// IOleClientSite
+//
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleClientSiteImpl::GetContainer
+//
+// Synopsis:
+//
+// Arguments: [ppContainer] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleClientSiteImpl::GetContainer(
+ /* [out] */ IOleContainer __RPC_FAR *__RPC_FAR *ppContainer)
+{
+ HRESULT hresult = NOERROR;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleClientSiteImpl::GetContainer\n", this));
+
+ if ( (_pSrvHndlr->GetOpState() == OpState_DoVerb)
+ && (_pSrvHndlr->_dwOperation & OP_GotContainer) )
+ {
+ // give out our local OleContainer object
+ *ppContainer = (IOleContainer *)&_pSrvHndlr->_OleContainer;
+ _pSrvHndlr->_OleContainer.AddRef();
+ }
+ else
+ {
+ HdlAssert(( _pCSDelegate != NULL && "CServerHandler::OleClient invalid OleClientSite object!\n"));
+ hresult = _pCSDelegate->GetContainer(_dwId, ppContainer);
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleClientSiteImpl::GetContainer return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleClientSiteImpl::ShowObject
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleClientSiteImpl::ShowObject( void)
+{
+ HRESULT hresult = S_OK;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleClientSiteImpl::ShowObject\n", this));
+
+ if ( (_pSrvHndlr->GetOpState() == OpState_DoVerb)
+ && (_pSrvHndlr->pOutSrvInPlace)
+ && (_pSrvHndlr->pOutSrvInPlace->dwOperation & OP_OnShowWindow) )
+ {
+ // done on GoInPlaceActive
+ }
+ else
+ {
+ HdlAssert(( _pCSDelegate != NULL && "CServerHandler::OleClient invalid OleClientSite object!\n"));
+ hresult = _pCSDelegate->ShowObject(_dwId);
+ }
+
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleClientSiteImpl::ShowObject return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleClientSiteImpl::OnShowWindow
+//
+// Synopsis:
+//
+// Arguments: [fShow] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleClientSiteImpl::OnShowWindow(
+ /* [in] */ BOOL fShow)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleClientSiteImpl::OnShowWindow\n", this));
+
+ HdlAssert(( _pCSDelegate != NULL && "CServerHandler::OleClient invalid OleClientSite object!\n"));
+ hresult = _pCSDelegate->OnShowWindow(_dwId, fShow);
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleClientSiteImpl::OnShowWindow return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleClientSiteImpl::RequestNewObjectLayout
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleClientSiteImpl::RequestNewObjectLayout( void)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleClientSiteImpl::RequestNewObjectLayout\n", this));
+
+ HdlAssert(( _pCSDelegate != NULL && "CServerHandler::OleClient invalid OleClientSite object!\n"));
+ hresult = _pCSDelegate->RequestNewObjectLayout(_dwId);
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleClientSiteImpl::RequestNewObjectLayout return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleClientSiteImpl::SaveObject
+//
+// Synopsis:
+//
+// Arguments: [void] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleClientSiteImpl::SaveObject( void)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleClientSiteImpl::SaveObject\n", this));
+
+ HdlAssert(( _pCSDelegate != NULL && "CServerHandler::OleClient invalid OleClientSite object!\n"));
+ hresult = _pCSDelegate->SaveObject(_dwId);
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleClientSiteImpl::SaveObject return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleClientSiteImpl::GetMoniker
+//
+// Synopsis:
+//
+// Arguments: [dwAssign] --
+// [dwWhichMoniker] --
+// [ppmk] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleClientSiteImpl::GetMoniker(
+ /* [in] */ DWORD dwAssign,
+ /* [in] */ DWORD dwWhichMoniker,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleClientSiteImpl::GetMoniker\n", this));
+
+ HdlAssert(( _pCSDelegate != NULL && "CServerHandler::OleClient invalid OleClientSite object!\n"));
+ hresult = _pCSDelegate->GetMoniker(_dwId, dwAssign, dwWhichMoniker, ppmk);
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleClientSiteImpl::GetMoniker return %lx\n", this, hresult));
+ return hresult;
+}
+
+//
+// IOleContainer methods
+//
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleContainerImpl::ParseDisplayName
+//
+// Synopsis:
+//
+// Arguments: [pbc] --
+// [pszDisplayName] --
+// [pchEaten] --
+// [ppmkOut] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleContainerImpl::ParseDisplayName(
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ LPOLESTR pszDisplayName,
+ /* [out] */ ULONG __RPC_FAR *pchEaten,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleContainerImpl::ParseDisplayName\n", this));
+
+ HdlAssert(( _pOContDelegate != NULL && "CServerHandler::OleClient invalid OleContainer object!\n"));
+ hresult = _pOContDelegate->ParseDisplayName(pbc, pszDisplayName, pchEaten, ppmkOut);
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleContainerImpl::ParseDisplayName return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleContainerImpl::EnumObjects
+//
+// Synopsis:
+//
+// Arguments: [grfFlags] --
+// [ppenum] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleContainerImpl::EnumObjects(
+ /* [in] */ DWORD grfFlags,
+ /* [out] */ IEnumUnknown __RPC_FAR *__RPC_FAR *ppenum)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleContainerImpl::EnumObjects\n", this));
+
+ HdlAssert(( _pOContDelegate != NULL && "CServerHandler::OleClient invalid OleContainer object!\n"));
+ hresult = _pOContDelegate->EnumObjects(grfFlags, ppenum);
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleContainerImpl::EnumObjects return %lx\n", this, hresult));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::COleContainerImpl::LockContainer
+//
+// Synopsis:
+//
+// Arguments: [fLock] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::COleContainerImpl::LockContainer(
+ /* [in] */ BOOL fLock)
+{
+ HRESULT hresult;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::COleContainerImpl::LockContainer\n", this));
+
+ HdlAssert(( _pOContDelegate != NULL && "CServerHandler::OleClient invalid OleContainer object!\n"));
+ hresult = _pOContDelegate->LockContainer(fLock);
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::COleContainerImpl::LockContainer return %lx\n", this, hresult));
+ return hresult;
+}
+
+//
+// Unknown for OleClientSite
+//
+
+//+---------------------------------------------------------------------------
+//
+// Macro: UNKNOWNIMP
+//
+// Synopsis: Macro for IUnknown implementation of nested classes of
+// serverhandler object.
+//
+// Arguments: [CClassName] -- the class name
+// [VarName] -- the variable of the nested class
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+#define UNKNOWNIMP(CClassName,VarName) \
+STDMETHODIMP CServerHandler::CClassName::QueryInterface( REFIID riid, void **ppv ) \
+{ \
+ HRESULT hresult = NOERROR; \
+ VDATEHEAP(); \
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p _IN CServerHandler::"#CClassName"::QueryInterface (%lx, %p)\n", this, riid, ppv)); \
+ if (IsEqualIID(riid, IID_IUnknown)) \
+ { \
+ *ppv = this; \
+ InterlockedIncrement((long *)&_cRefs); \
+ hresult = _pSrvHndlr->PrivAddRef(_dwId); \
+ } \
+ else \
+ { \
+ hresult = _pSrvHndlr->PrivQueryInterface(_dwId, riid, ppv); \
+ } \
+ \
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p OUT CServerHandler::"#CClassName"::QueryInterface (%lx)[%p]\n", this, hresult, *ppv)); \
+ return hresult; \
+} \
+STDMETHODIMP_(ULONG) CServerHandler::CClassName::AddRef( void ) \
+{ \
+ VDATEHEAP(); \
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p _IN CServerHandler::"#CClassName"::AddRef\n", this)); \
+ InterlockedIncrement((long *)&_cRefs); \
+ _pSrvHndlr->PrivAddRef(_dwId); \
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p OUT CServerHandler::"#CClassName"::AddRef (%ld)\n", this, _cRefs)); \
+ return _cRefs; \
+} \
+STDMETHODIMP_(ULONG) CServerHandler::CClassName::Release( void ) \
+{ \
+ ULONG cRefs = 0; \
+ VDATEHEAP(); \
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p _IN CServerHandler::"#CClassName"::Release\n", this)); \
+ InterlockedDecrement((long *)&_cRefs); \
+ cRefs = _cRefs; \
+ _pSrvHndlr->PrivRelease(_dwId, cRefs); \
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p OUT CServerHandler::"#CClassName"::Release (%ld)\n", this, cRefs)); \
+ return cRefs; \
+}
+
+UNKNOWNIMP(COleClientSiteImpl,_OleClientSite)
+UNKNOWNIMP(COleInPlaceSiteImpl, _OleInPlaceSite)
+UNKNOWNIMP(COleContainerImpl, _OleContainer)
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: CServerHandler::PrivQueryInterface
+//
+// Synopsis:
+//
+// Arguments: [dwId] --
+// [riid] --
+// [ppv] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CServerHandler::PrivQueryInterface( DWORD dwId, REFIID riid, void **ppv )
+{
+ HRESULT hresult = NOERROR;
+ VDATEHEAP();
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p _IN CServerHandler::PrivQueryInterface (%lx, %p)\n", this, riid, ppv));
+
+ if (IsEqualIID(riid, IID_IOleClientSite))
+ {
+ *ppv = (void FAR *)(IOleClientSite *)&_OleClientSite;
+ _OleClientSite.AddRef();
+ }
+ else if ( (_dwOperation & OP_GotInPlaceSite)
+ && ( IsEqualIID(riid, IID_IOleInPlaceSite)
+ || IsEqualIID(riid, IID_IOleWindow)) )
+ {
+ *ppv = (void FAR *)(IOleInPlaceSite *)&_OleInPlaceSite;
+ _OleInPlaceSite.AddRef();
+ }
+ else if (IsEqualIID(riid, IID_IOleContainer))
+ {
+ // Note: serverhandler should know if client supports OleContainer
+ if ( GetContainerDelegate() )
+ {
+ *ppv = (void FAR *)(IOleContainer *)&_OleContainer;
+ _OleContainer.AddRef();
+ }
+ else
+ {
+ *ppv = NULL;
+ hresult = E_NOINTERFACE;
+ }
+
+ }
+ else if ( (GetOpState() == OpState_DoVerb)
+ && (IsEqualIID(riid, IID_IOleObject)) )
+ {
+ if (!(_dwOperation & OP_GotOleObjectOfContainer))
+ {
+ *ppv = NULL;
+ hresult = E_NOINTERFACE;
+ }
+ else
+ {
+ // call back and get the interface
+ hresult = _pCSH->PrivQueryInterface(dwId, riid, ppv);
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::PrivQueryInterface on pUnkObj (%lx)[%p]\n", this, hresult, *ppv));
+ }
+ }
+ else if ( ( (GetOpState() == OpState_DoVerb)
+ ||(GetOpState() == OpState_RunAndInitialize))
+ && (IsEqualIID(riid, IID_IMsoDocumentSite)) )
+ {
+ if (!(_dwOperation & OP_HaveMsoDocumentSite))
+ {
+ *ppv = NULL;
+ hresult = E_NOINTERFACE;
+ }
+ else
+ {
+ // call back and get the interface
+ hresult = _pCSH->PrivQueryInterface(dwId, riid, ppv);
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::PrivQueryInterface on pUnkObj (%lx)[%p]\n", this, hresult, *ppv));
+ }
+ }
+ else
+ {
+ hresult = _pCSH->PrivQueryInterface(dwId, riid, ppv);
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::PrivQueryInterface on pUnkObj (%lx)[%p]\n", this, hresult, *ppv));
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p OUT CServerHandler::PrivQueryInterface (%lx)[%p]\n", this, hresult, *ppv));
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: PrivAddRef
+//
+// Synopsis:
+//
+// Arguments: [dwId] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CServerHandler::PrivAddRef( DWORD dwId)
+{
+ VDATEHEAP();
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p _IN CServerHandler::PrivAddRef\n", this));
+
+ //_cTotalRefs++;
+ InterlockedIncrement((long *)&_cTotalRefs);
+
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p OUT CServerHandler::PrivAddRef (%ld)\n", this, _cTotalRefs));
+ return _cTotalRefs;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: PrivRelease
+//
+// Synopsis:
+//
+// Arguments: [dwId] --
+// [cLRefs] --
+//
+// Returns:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CServerHandler::PrivRelease( DWORD dwId, ULONG cLRefs )
+{
+ ULONG cTotalRefs = 0;
+ VDATEHEAP();
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p _IN CServerHandler::PrivRelease\n", this));
+
+ //_cTotalRefs--;
+ InterlockedDecrement((long *)&_cTotalRefs);
+ cTotalRefs = _cTotalRefs;
+
+ HdlAssert(( cLRefs <= cTotalRefs));
+
+ HdlAssert(( dwId > ID_NONE && dwId <= ID_ServerHandler));
+
+ if (cLRefs == 0)
+ {
+ switch(dwId)
+ {
+ case ID_ServerHandler:
+ // nothing to do
+ break;
+ case ID_Container:
+ if (_OleContainer._pOContDelegate)
+ {
+ // Note: the application used the OleContainer object on other methods
+ // then IUnknown - see GetContainerDelegate
+ // Release the OleContainer delegate
+
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::Releasing pOCont\n", this));
+ _OleContainer._pOContDelegate->Release();
+ _OleContainer._pOContDelegate = NULL;
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::Releasing pOCont\n", this));
+ }
+ break;
+
+ default:
+ if (_pCSH)
+ {
+ // release the ClientSiteHandler interface - calls back to the container
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::Releasing object on CSH\n", this));
+ _pCSH->PrivRelease(dwId);
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::Releasing object on CSH\n", this));
+ }
+ break;
+ }
+
+ }
+
+ if (cTotalRefs == 0)
+ {
+ // release the ClientSiteHandler interface - calls back to the container
+ if (_pCSH)
+ {
+ HdlDebugOut((DEB_SERVERHANDLER, "%p _IN CServerHandler::Releasing ClientSiteHandler\n", this));
+ _pCSH->Release();
+ HdlDebugOut((DEB_SERVERHANDLER, "%p OUT CServerHandler::Releasing ClientSiteHandler\n", this));
+ }
+
+ HdlAssert((_pOO == NULL));
+
+ delete this;
+ }
+
+ HdlDebugOut((DEB_SERVERHANDLER_UNKNOWN, "%p OUT CServerHandler::PrivRelease(clRefs:%ld) (cTotalRefs:%ld)\n", this, cLRefs, cTotalRefs));
+ return cTotalRefs;
+}
+
+#endif // SERVER_HANDLER
diff --git a/private/ole32/ole232/stdimpl/srvhndlr.h b/private/ole32/ole232/stdimpl/srvhndlr.h
new file mode 100644
index 000000000..53093fe30
--- /dev/null
+++ b/private/ole32/ole232/stdimpl/srvhndlr.h
@@ -0,0 +1,370 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: srvhndlr.h
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef SERVER_HANDLER
+
+#ifndef _SRVHNDLR_H_DEFINED_
+#define _SRVHNDLR_H_DEFINED_
+
+typedef enum
+{
+ OpState_NoOp = 0,
+ OpState_RunAndInitialize = 1,
+ OpState_RunAndDoVerb = 2,
+ OpState_DoVerb = 3,
+} OperationState;
+
+enum ClientSiteID
+{
+ ID_NONE = 0
+ ,ID_ClientSite = 1
+ ,ID_ClientSiteActive = 2
+ ,ID_InPlaceSite = 3
+ ,ID_Container = 4
+
+ ,ID_ServerHandler = 5
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Enum: Operation
+//
+// Synopsis: Used to specify an operation requested by the clientsitehander
+// or by the serverhandler
+// E.g. OP_NeedPersistStorage means the clientsitehandler needs
+// IPersistStorage interface
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+typedef enum
+{
+ // used on Run
+ OP_NeedPersistStorage = 0x00000001
+ ,OP_NeedOleObject = 0x00000002
+ ,OP_NeedDataObject = 0x00000004
+ ,OP_NeedUserClassID = 0x00000008
+
+ ,OP_GotClientSite = 0x00000010
+ ,OP_HaveMsoDocumentSite = 0x00000020
+
+ // used for inplace
+ ,OP_GotInPlaceSite = 0x00010000
+ ,OP_GotClientSiteActive = 0x00020000
+ ,OP_GotContainer = 0x00040000
+ ,OP_GotOleObjectOfContainer= 0x00080000
+
+ ,OP_OnInPlaceActivate = 0x00100000
+ ,OP_GetWindow = 0x00200000
+ ,OP_GetWindowContext = 0x00400000
+ ,OP_OnShowWindow = 0x00800000
+
+} Operation;
+
+//+---------------------------------------------------------------------------
+//
+// Class: CServerHandler ()
+//
+// Purpose:
+//
+// Interface: CServerHandler --
+// ~CServerHandler --
+// Create --
+// QueryInterface --
+// AddRef --
+// Release --
+// RunAndInitialize --
+// RunAndDoVerb --
+// DoVerb --
+// CloseAndRelease --
+// PrivQueryInterface --
+// PrivAddRef --
+// PrivRelease --
+// QueryInterface --
+// AddRef --
+// Release --
+// SaveObject --
+// GetMoniker --
+// GetContainer --
+// ShowObject --
+// OnShowWindow --
+// RequestNewObjectLayout --
+// _cRefs --
+// _dwId --
+// _pSrvHndlr --
+// _pCSDelegate --
+// _pCSDelegate --
+// COleClientSiteImpl --
+// _OleClientSite --
+// _OleClientSiteActive --
+// QueryInterface --
+// AddRef --
+// Release --
+// GetWindow --
+// ContextSensitiveHelp --
+// CanInPlaceActivate --
+// OnInPlaceActivate --
+// OnUIActivate --
+// GetWindowContext --
+// Scroll --
+// OnUIDeactivate --
+// OnInPlaceDeactivate --
+// DiscardUndoState --
+// DeactivateAndUndo --
+// OnPosRectChange --
+// _cRefs --
+// _dwId --
+// _pSrvHndlr --
+// _pOIPSDelegate --
+// _pOIPSDelegate --
+// COleInPlaceSiteImpl --
+// _OleInPlaceSite --
+// QueryInterface --
+// AddRef --
+// Release --
+// ParseDisplayName --
+// EnumObjects --
+// LockContainer --
+// _cRefs --
+// _dwId --
+// _pSrvHndlr --
+// _pOContDelegate --
+// _pOContDelegate --
+// COleContainerImpl --
+// _OleContainer --
+// GetContainerDelegate --
+// SetClientSiteHandler --
+// ReleaseObject --
+// os --
+// _OpState --
+// os --
+// _OpState --
+// _cRefs --
+// _cTotalRefs --
+// _dwId --
+// _OpState --
+// _dwOperation --
+// pOutSrvInPlace --
+// _hrCanInPlaceActivate --
+// _pUnkObj --
+// _pOO --
+// _pCSH --
+//
+// History: 11-17-95 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+class CServerHandler : public IServerHandler
+{
+public:
+
+ CServerHandler(IUnknown *pUnk);
+ ~CServerHandler();
+
+ // IUnknown methods
+
+ STDMETHOD(QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ // IServerHandler
+ STDMETHOD(RunAndInitialize) (INSRVRUN *pInSrvRun, OUTSRVRUN **ppOutSrvRun);
+ STDMETHOD(RunAndDoVerb) (INSRVRUN *pInSrvRun, OUTSRVRUN **ppOutSrvRun);
+ STDMETHOD(DoVerb) (INSRVRUN *pInSrvRun, OUTSRVRUN **ppOutSrvRun);
+ STDMETHOD(CloseAndRelease) (DWORD dwClose);
+
+
+ STDMETHOD(PrivQueryInterface) (DWORD dwId, REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,PrivAddRef) (DWORD dwId);
+ STDMETHOD_(ULONG,PrivRelease) (DWORD dwId, ULONG cLRefs);
+
+ class COleClientSiteImpl : public IOleClientSite
+ {
+ public:
+ STDMETHOD(QueryInterface) ( REFIID iid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+ // IOleClientSiteMethods
+ STDMETHOD (SaveObject)( void);
+
+ STDMETHOD (GetMoniker)(
+ /* [in] */ DWORD dwAssign,
+ /* [in] */ DWORD dwWhichMoniker,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk);
+
+ STDMETHOD (GetContainer)(
+ /* [out] */ IOleContainer __RPC_FAR *__RPC_FAR *ppContainer);
+
+ STDMETHOD (ShowObject)( void);
+
+ STDMETHOD (OnShowWindow)(
+ /* [in] */ BOOL fShow);
+
+ STDMETHOD (RequestNewObjectLayout)( void);
+
+ //private:
+ ULONG _cRefs; //
+ DWORD _dwId; // id of clientsite
+ CServerHandler *_pSrvHndlr;
+ IClientSiteHandler *_pCSDelegate;
+
+ };
+
+ friend class COleClientSiteImpl;
+
+ COleClientSiteImpl _OleClientSite;
+
+ // Active OleClientSite on DoVerb
+ COleClientSiteImpl _OleClientSiteActive;
+
+
+ class COleInPlaceSiteImpl : public IOleInPlaceSite
+ {
+ public:
+ STDMETHOD(QueryInterface) ( REFIID iid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+ // IOleInPlaceSite Methods
+
+ /* [input_sync] */
+ STDMETHOD (GetWindow)(
+ /* [out] */ HWND __RPC_FAR *phwnd);
+
+ STDMETHOD (ContextSensitiveHelp)(
+ /* [in] */ BOOL fEnterMode);
+
+
+ STDMETHOD (CanInPlaceActivate)( void);
+
+ STDMETHOD (OnInPlaceActivate)( void);
+
+ STDMETHOD (OnUIActivate)( void);
+
+ STDMETHOD (GetWindowContext)(
+ /* [out] */ IOleInPlaceFrame __RPC_FAR *__RPC_FAR *ppFrame,
+ /* [out] */ IOleInPlaceUIWindow __RPC_FAR *__RPC_FAR *ppDoc,
+ /* [out] */ LPRECT lprcPosRect,
+ /* [out] */ LPRECT lprcClipRect,
+ /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo);
+
+ STDMETHOD (Scroll)(
+ /* [in] */ SIZE scrollExtant);
+
+ STDMETHOD (OnUIDeactivate)(
+ /* [in] */ BOOL fUndoable);
+
+ STDMETHOD (OnInPlaceDeactivate)( void);
+
+ STDMETHOD (DiscardUndoState)( void);
+
+ STDMETHOD (DeactivateAndUndo)( void);
+
+ STDMETHOD (OnPosRectChange)(
+ /* [in] */ LPCRECT lprcPosRect);
+
+ //private:
+ ULONG _cRefs; //
+ DWORD _dwId; //
+ CServerHandler *_pSrvHndlr;
+ IClientSiteHandler *_pOIPSDelegate;
+ };
+
+ friend class COleInPlaceSiteImpl;
+ COleInPlaceSiteImpl _OleInPlaceSite;
+
+ class COleContainerImpl : public IOleContainer
+ {
+ public:
+ STDMETHOD(QueryInterface) ( REFIID iid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+ // IOleContainer methods
+
+ STDMETHOD (ParseDisplayName)(
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ LPOLESTR pszDisplayName,
+ /* [out] */ ULONG __RPC_FAR *pchEaten,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut);
+
+
+ STDMETHOD (EnumObjects)(
+ /* [in] */ DWORD grfFlags,
+ /* [out] */ IEnumUnknown __RPC_FAR *__RPC_FAR *ppenum);
+
+ STDMETHOD (LockContainer)(
+ /* [in] */ BOOL fLock);
+
+ //private:
+ ULONG _cRefs; //
+ DWORD _dwId; //
+ CServerHandler *_pSrvHndlr;
+ IOleContainer * _pOContDelegate;
+ };
+
+ friend class COleContainerImpl;
+ COleContainerImpl _OleContainer;
+
+
+ // private methods
+ STDMETHOD_(IOleContainer *, GetContainerDelegate)(void);
+
+ STDMETHOD(SetClientSiteHandler)(IClientSiteHandler *pCSH);
+ STDMETHOD_(void, ReleaseObject)();
+
+ INTERNAL_(OperationState) SetOpState (OperationState opstate)
+ {
+ OperationState os = _OpState;
+ _OpState = opstate;
+ return os;
+ }
+
+ INTERNAL_(OperationState) GetOpState()
+ {
+ return _OpState;
+ }
+
+private:
+ ULONG _cRefs; // refcount on IServerHandler
+ ULONG _cTotalRefs; // total refcount on all objects
+
+ DWORD _dwId; // id of Serverhandler
+ OperationState _OpState; // internal operation state
+
+ DWORD _dwOperation; // operation option passed in on DoVerb
+ COutSrvInPlace *pOutSrvInPlace;
+ HRESULT _hrCanInPlaceActivate;
+
+ // pointer to the object at server site
+ IUnknown *_pUnkObj; // the object unknown
+ IOleObject *_pOO; // the oleobject
+
+
+ // pointer to object at client site
+ IClientSiteHandler *_pCSH;
+};
+
+HRESULT CreateServerHandler(const CLSID *pClsID, IUnknown *punk,
+ IClientSiteHandler *pClntHndlr,
+ IServerHandler **ppSrvHdlr);
+
+#endif // _SRVHNDLR_H_DEFINED
+
+#endif // SERVER_HANDLER
diff --git a/private/ole32/ole232/util/convert.cpp b/private/ole32/ole232/util/convert.cpp
new file mode 100644
index 000000000..cb79c8279
--- /dev/null
+++ b/private/ole32/ole232/util/convert.cpp
@@ -0,0 +1,1209 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// convert.cpp
+//
+// Contents:
+// This module contains the code to read/write DIB, metafile,
+// placeable metafiles, olepres stream, etc... This module also
+// contains routines for converting from one format to other.
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 15-Feb-94 alexgo fixed a bug in loading placeable metafiles
+// from a storage (incorrect size calculation).
+// 25-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocations.
+// 01/11/93 - alexgo - added VDATEHEAP macros to every function
+// 12/08/93 - ChrisWe - fixed wPrepareBitmapHeader not to use
+// (LPOLESTR) cast
+// 12/07/93 - ChrisWe - make default params to StSetSize explicit
+// 12/02/93 - ChrisWe - more formatting; fixed UtHMFToMFStm,
+// 32 bit version, which was doing questionable things
+// with the hBits handle; got rid of the OLESTR
+// uses in favor of (void *) or (BYTE *) as appropriate
+// 11/29/93 - ChrisWe - move CONVERT_SOURCEISICON, returned
+// by UtOlePresStmToContentsStm(), to utils.h
+// 11/28/93 - ChrisWe - begin file inspection and cleanup
+// 06/28/93 - SriniK - created
+//
+//-----------------------------------------------------------------------------
+
+#include <le2int.h>
+
+#pragma SEG(ole2)
+
+NAME_SEG(convert)
+ASSERTDATA
+
+#ifndef _MAC
+FARINTERNAL_(HMETAFILE) QD2GDI(HANDLE hBits);
+#endif
+
+void UtGetHEMFFromContentsStm(LPSTREAM lpstm, HANDLE * phdata);
+
+
+/************************ FILE FORMATS **********************************
+
+Normal Metafile (memory or disk based):
+
+ ------------ ---------------
+ | METAHEADER | Metafile bits |
+ ------------ ---------------
+
+Placeable Metafile:
+
+ --------------------- -----------------
+ | PLACEABLEMETAHEADER | Normal metafile |
+ --------------------- -----------------
+
+Memory Based DIB:
+
+ ------------------ --------------- ----------
+ | BITMAPINFOHEADER | RGBQUAD array | DIB bits |
+ ------------------ --------------- ----------
+
+DIB file format:
+
+ ------------------ ------------------
+ | BITMAPFILEHEADER | Memory based DIB |
+ ------------------ ------------------
+
+Ole10NativeStream Format:
+
+ -------- ----------------------
+ | dwSize | Object's Native data |
+ -------- ----------------------
+
+PBrush Native data format:
+
+ -----------------
+ | Dib File format |
+ -----------------
+
+MSDraw Native data format:
+
+ --------------------- ------------- ------------- -----------------
+ | mapping mode (WORD) | xExt (WORD) | yExt (WORD) | Normal metafile |
+ --------------------- ------------- ------------- -----------------
+
+*****************************************************************************/
+
+
+FARINTERNAL UtGetHGLOBALFromStm(LPSTREAM lpstream, DWORD dwSize,
+ HANDLE FAR* lphPres)
+{
+ VDATEHEAP();
+
+ HANDLE hBits = NULL;
+ void FAR *lpBits = NULL;
+ HRESULT error;
+
+ // initialize this for error return cases
+ *lphPres = NULL;
+
+ // allocate a new handle
+ if (!(hBits = GlobalAlloc(GMEM_MOVEABLE, dwSize))
+ || !(lpBits = (BYTE *)GlobalLock(hBits)))
+ {
+ error = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ // read the stream into the allocated memory
+ if (error = StRead(lpstream, lpBits, dwSize))
+ goto errRtn;
+
+ // if we got this far, return new handle
+ *lphPres = hBits;
+
+errRtn:
+ // unlock the handle, if it was successfully locked
+ if (lpBits)
+ GlobalUnlock(hBits);
+
+ // free the handle if there was an error
+ if ((error != NOERROR) && hBits)
+ GlobalFree(hBits);
+
+ return(error);
+}
+
+
+#ifndef _MAC
+
+FARINTERNAL UtGetHDIBFromDIBFileStm(LPSTREAM pstm, HANDLE FAR* lphdata)
+{
+ VDATEHEAP();
+
+ BITMAPFILEHEADER bfh;
+ DWORD dwSize; // the size of the data to read
+ HRESULT error;
+
+ // read the bitmap file header
+ if (error = pstm->Read(&bfh, sizeof(BITMAPFILEHEADER), NULL))
+ {
+ *lphdata = NULL;
+ return(error);
+ }
+
+ // calculate the size of the DIB to read
+ dwSize = bfh.bfSize - sizeof(BITMAPFILEHEADER);
+
+ // read the DIB
+ return(UtGetHGLOBALFromStm(pstm, dwSize, lphdata));
+}
+
+
+FARINTERNAL_(HANDLE) UtGetHMFPICT(HMETAFILE hMF, BOOL fDeleteOnError,
+ DWORD xExt, DWORD yExt)
+{
+ VDATEHEAP();
+
+ HANDLE hmfp; // handle to the new METAFILEPICT
+ LPMETAFILEPICT lpmfp; // pointer to the new METAFILEPICT
+
+ // if no METAFILE, nothing to do
+ if (hMF == NULL)
+ return(NULL);
+
+ // allocate a new handle
+ if (!(hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT))))
+ goto errRtn;
+
+ // lock the handle
+ if (!(lpmfp = (LPMETAFILEPICT)GlobalLock(hmfp)))
+ goto errRtn;
+
+ // make the METAFILEPICT
+ lpmfp->hMF = hMF;
+ lpmfp->xExt = (int)xExt;
+ lpmfp->yExt = (int)yExt;
+ lpmfp->mm = MM_ANISOTROPIC;
+
+ GlobalUnlock(hmfp);
+ return(hmfp);
+
+errRtn:
+ if (hmfp)
+ GlobalFree(hmfp);
+
+ if (fDeleteOnError)
+ DeleteMetaFile(hMF);
+
+ return(NULL);
+}
+
+#endif // _MAC
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtGetHMFFromMFStm
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [lpstream] -- stream containing metafile or PICT
+// [dwSize] -- data size within stream
+// [fConvert] -- FALSE for metafile, TRUE for PICT
+// [lphPres] -- placeholder for output metafile
+//
+// Requires: lpstream positioned at start of data
+//
+// Returns: HRESULT
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 29-Apr-94 AlexT Add comment block, enabled Mac conversion
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+FARINTERNAL UtGetHMFFromMFStm(LPSTREAM lpstream, DWORD dwSize,
+ BOOL fConvert, HANDLE FAR* lphPres)
+{
+#ifdef WIN32
+ LEDebugOut((DEB_ITRACE, "%p _IN UtGetHMFFromMFStm (%p, %d, %d, %p)\n",
+ NULL, lpstream, dwSize, fConvert, lphPres));
+
+ VDATEHEAP();
+
+ BYTE *pbMFData = NULL;
+ HRESULT hrError;
+
+ // initialize this in case of error return
+ *lphPres = NULL;
+
+ // allocate a global handle for the data (since QD2GDI needs a
+ // handle)
+
+ pbMFData = (BYTE *) GlobalAlloc(GMEM_FIXED, dwSize);
+ if (NULL == pbMFData)
+ {
+ hrError = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ // read the stream into the bit storage
+
+ ULONG cbRead;
+ hrError = lpstream->Read(pbMFData, dwSize, &cbRead);
+ if (FAILED(hrError))
+ {
+ return(hrError);
+ }
+ // hrError = StRead(lpstream, pbMFData, dwSize);
+
+ if (hrError != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if (fConvert)
+ {
+ // It's a Mac PICT
+ *lphPres = QD2GDI((HGLOBAL) pbMFData);
+ }
+ else
+ {
+ // It's a Windows metafile
+ *lphPres = SetMetaFileBitsEx(dwSize, pbMFData);
+ }
+
+ if (*lphPres == NULL)
+ hrError = ResultFromScode(E_OUTOFMEMORY);
+
+errRtn:
+ if (NULL != pbMFData)
+ {
+ GlobalFree(pbMFData);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT UtGetHMFFromMFStm ( %lx ) [ %p ]\n",
+ NULL, hrError, *lphPres));
+
+ return(hrError);
+#else
+ HANDLE hBits; // handle to the new METAFILE
+ void FAR* lpBits = NULL;
+ HRESULT error;
+
+ // initialize this in case of error return
+ *lphPres = NULL;
+
+ // allocate a new handle, and lock the bits
+ if (!(hBits = GlobalAlloc(GMEM_MOVEABLE, dwSize))
+ || !(lpBits = GlobalLock(hBits)))
+ {
+ error = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ // read the stream into the bit storage
+ error = StRead(lpstream, lpBits, dwSize);
+ GlobalUnlock(hBits);
+
+ if (error)
+ goto errRtn;
+
+ if (!fConvert)
+ *lphPres = SetMetaFileBits(hBits);
+ else
+ {
+ if (*lphPres = QD2GDI(hBits))
+ {
+ // Need to free this handle upon success
+ GlobalFree(hBits);
+ hBits = NULL;
+ }
+
+ }
+
+ if (!*lphPres)
+ error = ResultFromScode(E_OUTOFMEMORY);
+
+errRtn:
+ if (error && hBits)
+ GlobalFree(hBits);
+ return(error);
+#endif // WIN32
+}
+
+
+FARINTERNAL UtGetSizeAndExtentsFromPlaceableMFStm(LPSTREAM pstm,
+ DWORD FAR* pdwSize, LONG FAR* plWidth, LONG FAR* plHeight)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ LARGE_INTEGER large_int; // used to set the seek pointer
+ ULARGE_INTEGER ularge_int; // retrieves the new seek position
+ LONG xExt; // the x extent of the metafile
+ LONG yExt; // the y extent of the metafile
+ METAHEADER mfh;
+ PLACEABLEMETAHEADER plac_mfh;
+
+ // read the placeable metafile header
+ if (error = pstm->Read(&plac_mfh, sizeof(plac_mfh), NULL))
+ return(error);
+
+ // check the magic number in the header
+ if (plac_mfh.key != PMF_KEY)
+ return ResultFromScode(E_FAIL);
+
+ // remember the seek pointer
+ LISet32(large_int, 0);
+ if (error = pstm->Seek(large_int, STREAM_SEEK_CUR, &ularge_int))
+ return(error);
+
+ // read metafile header
+ if (error = pstm->Read(&mfh, sizeof(mfh), NULL))
+ return(error);
+
+ // seek back to the begining of metafile header
+ LISet32(large_int, ularge_int.LowPart);
+ if (error = pstm->Seek(large_int, STREAM_SEEK_SET, NULL))
+ return(error);
+
+ // calculate the extents of the metafile
+ xExt = (plac_mfh.bbox.right - plac_mfh.bbox.left);// metafile units
+ yExt = (plac_mfh.bbox.bottom - plac_mfh.bbox.top);// metafile units
+
+ // REVIEW, why aren't there constants for this?
+ xExt = (xExt * 2540) / plac_mfh.inch; // HIMETRIC units
+ yExt = (yExt * 2540) / plac_mfh.inch; // HIMETRIC units
+
+ if (pdwSize)
+ {
+#ifdef WIN16
+ //this code seems to work OK on Win16
+ *pdwSize = 2 * (mfh.mtSize + mfh.mtHeaderSize);
+ // REVIEW NT: review METAHEADER
+#else //WIN32
+ //mt.Size is the size in words of the metafile.
+ //this fixes bug 6739 (static objects can't be copied
+ //or loaded from a file).
+ *pdwSize = sizeof(WORD) * mfh.mtSize;
+#endif //WIN16
+ }
+
+ if (plWidth)
+ *plWidth = xExt;
+
+ if (plHeight)
+ *plHeight = yExt;
+
+ return NOERROR;
+}
+
+
+FARINTERNAL UtGetHMFPICTFromPlaceableMFStm(LPSTREAM pstm, HANDLE FAR* lphdata)
+{
+ VDATEHEAP();
+
+ HRESULT error; // error state so far
+ DWORD dwSize; // size of the METAFILE we have to read from the stream
+ LONG xExt; // x extent of the METAFILE we have to read from the stream
+ LONG yExt; // y extent of the METAFILE we have to read from the stream
+ HMETAFILE hMF; // handle to the METAFILE read from the stream
+
+ if (lphdata == NULL)
+ return ResultFromScode(E_INVALIDARG);
+
+ // initialize this in case of error return
+ *lphdata = NULL;
+
+ // get the size of the METAFILE
+ if (error = UtGetSizeAndExtentsFromPlaceableMFStm(pstm, &dwSize,
+ &xExt, &yExt))
+ return(error);
+
+ // fetch the METAFILE
+ if (error = UtGetHMFFromMFStm(pstm, dwSize, FALSE /*fConvert*/,
+ (HANDLE FAR *)&hMF))
+ return(error);
+
+ // convert to a METAFILEPICT
+ if (!(*lphdata = UtGetHMFPICT(hMF, TRUE /*fDeleteOnError*/, xExt,
+ yExt)))
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ return NOERROR;
+}
+
+
+
+/****************************************************************************/
+/***************** Write routines *********************/
+/****************************************************************************/
+
+#ifndef _MAC
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// wPrepareBitmapHeader, static
+//
+// Synopsis:
+// Initializes the content of a BITMAPFILEHEADER
+//
+// Arguments:
+// [lpbfh] -- pointer to the BITMAPFILEHEADER to initialize
+// [dwSize] -- the size of the file; obtained by dividing
+// the size of the file by 4 (see win32 documentation.)
+//
+// History:
+// 12/08/93 - ChrisWe - made static
+//
+//-----------------------------------------------------------------------------
+static INTERNAL_(void) wPrepareBitmapFileHeader(LPBITMAPFILEHEADER lpbfh,
+ DWORD dwSize)
+{
+ VDATEHEAP();
+
+ // NOTE THESE ARE NOT SUPPOSED TO BE UNICODE
+ // see win32s documentation
+ ((char *)(&lpbfh->bfType))[0] = 'B';
+ ((char *)(&lpbfh->bfType))[1] = 'M';
+
+ lpbfh->bfSize = dwSize + sizeof(BITMAPFILEHEADER);
+ lpbfh->bfReserved1 = 0;
+ lpbfh->bfReserved2 = 0;
+ lpbfh->bfOffBits = 0;
+}
+
+
+FARINTERNAL UtHDIBToDIBFileStm(HANDLE hdata, DWORD dwSize, LPSTREAM pstm)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ BITMAPFILEHEADER bfh;
+
+ wPrepareBitmapFileHeader(&bfh, dwSize);
+
+ if (error = pstm->Write(&bfh, sizeof(bfh), NULL))
+ return(error);
+
+ return UtHGLOBALtoStm(hdata, dwSize, pstm);
+}
+
+
+FARINTERNAL UtDIBStmToDIBFileStm(LPSTREAM pstmDIB, DWORD dwSize,
+ LPSTREAM pstmDIBFile)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ BITMAPFILEHEADER bfh;
+ ULARGE_INTEGER ularge_int; // indicates how much to copy
+
+ wPrepareBitmapFileHeader(&bfh, dwSize);
+
+ if (error = pstmDIBFile->Write(&bfh, sizeof(bfh), NULL))
+ return(error);
+
+ ULISet32(ularge_int, dwSize);
+ if ((error = pstmDIB->CopyTo(pstmDIBFile, ularge_int, NULL,
+ NULL)) == NOERROR)
+ StSetSize(pstmDIBFile, 0, TRUE);
+
+ return(error);
+}
+
+
+// REVIEW, move these to utils.h so that gen.cpp and mf.cpp can use them for
+// the same purposes
+// REVIEW, add some more comments; is HDIBFILEHDR a windows structure?
+struct tagHDIBFILEHDR
+{
+ DWORD dwCompression;
+ DWORD dwWidth;
+ DWORD dwHeight;
+ DWORD dwSize;
+};
+typedef struct tagHDIBFILEHDR HDIBFILEHDR;
+
+struct tagOLEPRESSTMHDR
+{
+ DWORD dwAspect;
+ DWORD dwLindex;
+ DWORD dwAdvf;
+};
+typedef struct tagOLEPRESSTMHDR OLEPRESSTMHDR;
+
+FARINTERNAL UtHDIBFileToOlePresStm(HANDLE hdata, LPSTREAM pstm)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ HDIBFILEHDR hdfh;
+ LPBITMAPFILEHEADER lpbfh;
+ LPBITMAPINFOHEADER lpbmi;
+
+ if (!(lpbfh = (LPBITMAPFILEHEADER)GlobalLock(hdata)))
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ lpbmi = (LPBITMAPINFOHEADER)(((BYTE *)lpbfh) +
+ sizeof(BITMAPFILEHEADER));
+
+ hdfh.dwCompression = 0;
+ // REVIEW, these casts are hosed
+ UtGetDibExtents(lpbmi, (LPLONG)&hdfh.dwWidth, (LPLONG)&hdfh.dwHeight);
+
+ hdfh.dwSize = lpbfh->bfSize - sizeof(BITMAPFILEHEADER);
+
+ // write compesssion, Width, Height, size
+ if (error = pstm->Write(&hdfh, sizeof(hdfh), 0))
+ goto errRtn;
+
+ // write the BITMAPINFOHEADER
+ // REVIEW, does this size include the data?
+ if ((error = pstm->Write(lpbmi, hdfh.dwSize, NULL)) == NOERROR)
+ StSetSize(pstm, 0, TRUE);
+
+errRtn:
+ GlobalUnlock(hdata);
+ return(error);
+}
+
+#endif // _MAC
+
+
+
+FARINTERNAL UtHMFToMFStm(HANDLE FAR* lphMF, DWORD dwSize, LPSTREAM lpstream)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+
+ // if there's no handle, there's nothing to do
+ if (*lphMF == 0)
+ return ResultFromScode(OLE_E_BLANK);
+
+#ifdef _MAC
+
+ AssertSz(GetHandleSize((Handle)*lphMF) == dwSize,
+ "pic hdl size not correct");
+ HLock( (HANDLE)*lphMF );
+
+ error = StWrite(lpstream, * (*lphMF), dwSize);
+
+ // Eric: We should be unlocking, right?
+ HUnlock((HANDLE)(*lphMF));
+
+ if (error != NOERROR)
+ AssertSz(0, "StWrite failure" );
+
+#else
+
+ HANDLE hBits = NULL;
+ void *lpBits;
+
+#ifdef WIN32
+
+ // allocate memory to hold the METAFILE bits
+ // Bug 18346 - OLE16 use to get the Handle size of the Metafile which was a METAHEADER bigger than the
+ // actual Metafile. Need to write out this much more worth of data so 16 bit dlls can read the Picture.
+
+ dwSize += sizeof(METAHEADER);
+
+ hBits = GlobalAlloc(GPTR, dwSize);
+ if (hBits == NULL)
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ if (!(lpBits = GlobalLock(hBits)))
+ goto errRtn;
+
+ // REVIEW, shouldn't we check the returned size?
+ // REVIEW, what should we do about enhanced metafiles? If we
+ // convert and write those out (which have more features that 32 bit
+ // apps might use,) then you can't read the same document on a win16
+ // machine....
+ GetMetaFileBitsEx((HMETAFILE)*lphMF, dwSize, lpBits);
+
+ // write the metafile bits out to the stream
+ error = StWrite(lpstream, lpBits, dwSize);
+
+ GlobalUnlock(hBits);
+
+errRtn:
+ // free the metafile bits
+ GlobalFree(hBits);
+
+#else
+ if (!(hBits = GetMetaFileBits(*lphMF)))
+ {
+ error = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ if (lpBits = GlobalLock(hBits))
+ {
+ error = StWrite(lpstream, lpBits, dwSize);
+ GlobalUnlock(hBits);
+ }
+ else
+ error = ResultFromScode(E_OUTOFMEMORY);
+
+ if (hBits)
+ *lphMF = SetMetaFileBits(hBits);
+errRtn:
+
+#endif // WIN32
+#endif // _MAC
+
+ // set the stream size
+ if (error == NOERROR)
+ StSetSize(lpstream, 0, TRUE);
+
+ return(error);
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// wPreparePlaceableMFHeader, static
+//
+// Synopsis:
+// Initializes a PLACEABLEMETAHEADER.
+//
+// Arguments:
+// [lpplac_mfh] -- pointer to the PLACEABLEMETAHEADER to initialize
+// [lWidth] -- Width of the metafile
+// REVIEW, in what units?
+// REVIEW, why is this not unsigned?
+// [lHeight] -- Height of the metafile
+// REVIEW, in what units?
+// REVIEW, why is this not unsigned?
+//
+// Notes:
+//
+// History:
+// 12/08/93 - ChrisWe - made static
+//
+//-----------------------------------------------------------------------------
+static INTERNAL_(void) wPreparePlaceableMFHeader(
+ PLACEABLEMETAHEADER FAR* lpplac_mfh, LONG lWidth, LONG lHeight)
+{
+ VDATEHEAP();
+
+ WORD FAR* lpw; // roves over the words included in the checksum
+
+ lpplac_mfh->key = PMF_KEY;
+ lpplac_mfh->hmf = 0;
+ lpplac_mfh->inch = 576; // REVIEW, where's this magic number from?
+ lpplac_mfh->bbox.left = 0;
+ lpplac_mfh->bbox.top = 0;
+ lpplac_mfh->bbox.right = (int) ((lWidth * lpplac_mfh->inch) / 2540);
+ // REVIEW, more magic
+ lpplac_mfh->bbox.bottom = (int) ((lHeight * lpplac_mfh->inch) / 2540);
+ // REVIEW, more magic
+ lpplac_mfh->reserved = NULL;
+
+ // Compute the checksum of the 10 words that precede the checksum field.
+ // It is calculated by XORing zero with those 10 words.
+ for(lpplac_mfh->checksum = 0, lpw = (WORD FAR*)lpplac_mfh;
+ lpw < (WORD FAR*)&lpplac_mfh->checksum; ++lpw)
+ lpplac_mfh->checksum ^= *lpw;
+}
+
+
+FARINTERNAL UtHMFToPlaceableMFStm(HANDLE FAR* lphMF, DWORD dwSize,
+ LONG lWidth, LONG lHeight, LPSTREAM pstm)
+{
+ VDATEHEAP();
+
+ PLACEABLEMETAHEADER plac_mfh;
+ HRESULT error;
+
+ wPreparePlaceableMFHeader(&plac_mfh, lWidth, lHeight);
+
+ // write the placeable header to the stream
+ if (error = pstm->Write(&plac_mfh, sizeof(plac_mfh), NULL))
+ return(error);
+
+ // write the rest of the METAFILE to the stream
+ return UtHMFToMFStm(lphMF, dwSize, pstm);
+}
+
+
+FARINTERNAL UtMFStmToPlaceableMFStm(LPSTREAM pstmMF, DWORD dwSize,
+ LONG lWidth, LONG lHeight, LPSTREAM pstmPMF)
+{
+ VDATEHEAP();
+
+ PLACEABLEMETAHEADER plac_mfh;
+ HRESULT error;
+ ULARGE_INTEGER ularge_int; // indicates how much data to copy
+
+ wPreparePlaceableMFHeader(&plac_mfh, lWidth, lHeight);
+
+ // write the placeable header to the stream
+ if (error = pstmPMF->Write(&plac_mfh, sizeof(plac_mfh), NULL))
+ return(error);
+
+ // copy the METAFILE data from one stream to the other
+ ULISet32(ularge_int, dwSize);
+ if ((error = pstmMF->CopyTo(pstmPMF, ularge_int, NULL, NULL)) ==
+ NOERROR)
+ StSetSize(pstmPMF, 0, TRUE);
+
+ return(error);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtWriteOlePresStmHeader, private
+//
+// Synopsis: Write the presentation stream header
+//
+// Effects:
+//
+// Arguments: [lpstream] -- destination stream
+// [pforetc] -- FORMATETC for this presentation
+// [dwAdvf] -- advise flags for the presentation
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 11-May-94 AlexT Added function header, translate to
+// ANSI before saving ptd
+//
+// Notes: This function can fail in low memory for presentations with
+// non-NULL ptds (since we allocate memory to do the conversion
+// to the persistent format). NtIssue #2789
+//
+//--------------------------------------------------------------------------
+
+FARINTERNAL UtWriteOlePresStmHeader(LPSTREAM lpstream, LPFORMATETC pforetc,
+ DWORD dwAdvf)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ OLEPRESSTMHDR opsh;
+
+ // write clip format
+ // REVIEW, change name of this function?
+ if (error = WriteClipformatStm(lpstream, pforetc->cfFormat))
+ return(error);
+
+ // write target device info
+ if (pforetc->ptd)
+ {
+ DVTDINFO dvtdInfo;
+ DVTARGETDEVICE *ptdA;
+
+ error = UtGetDvtd32Info(pforetc->ptd, &dvtdInfo);
+ if (FAILED(error))
+ {
+ return(error);
+ }
+
+ ptdA = (DVTARGETDEVICE *) PrivMemAlloc(dvtdInfo.cbConvertSize);
+ if (NULL == ptdA)
+ {
+ return(E_OUTOFMEMORY);
+ }
+
+ error = UtConvertDvtd32toDvtd16(pforetc->ptd, &dvtdInfo, ptdA);
+
+ if (SUCCEEDED(error))
+ {
+ error = StWrite(lpstream, ptdA, ptdA->tdSize);
+ }
+
+ PrivMemFree(ptdA);
+
+ if (FAILED(error))
+ {
+ return(error);
+ }
+ }
+ else
+ {
+ // if ptd is null then write 4 as size.
+ // REVIEW, what is that the sizeof()?
+ DWORD dwNullPtdLength = 4;
+
+ if (error = StWrite(lpstream, &dwNullPtdLength, sizeof(DWORD)))
+ return(error);
+ }
+
+ opsh.dwAspect = pforetc->dwAspect;
+ opsh.dwLindex = pforetc->lindex;
+ opsh.dwAdvf = dwAdvf;
+
+ // write DVASPECT, lindex, advise flags
+ return StWrite(lpstream, &opsh, sizeof(opsh));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtReadOlePresStmHeader
+//
+// Synopsis: Reads in a presentation stream header
+//
+// Arguments: [pstm] -- source stream
+// [pforetc] -- FORMATETC to be filled in
+// [pdwAdvf] -- advise flags to be filled in
+// [pfConvert] -- Mac conversion required, to be filled in
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 11-May-94 AlexT Added function header, translate ptd
+// from ANSI when loading
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+FARINTERNAL UtReadOlePresStmHeader(LPSTREAM pstm, LPFORMATETC pforetc,
+ DWORD FAR* pdwAdvf, BOOL FAR* pfConvert)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ DWORD dwRead;
+ OLEPRESSTMHDR opsh;
+
+ // initialize this for error return cases
+ // Check for NULL ptr, as caller may not need this information
+
+ if (pfConvert)
+ {
+ *pfConvert = FALSE;
+ }
+
+ // there's no target device information yet
+ pforetc->ptd = NULL;
+
+ // REVIEW, rename this function to indicate its origin?
+ error = ReadClipformatStm(pstm, &dwRead);
+
+ if (error == NOERROR)
+ pforetc->cfFormat = (CLIPFORMAT)dwRead;
+ else
+ {
+#ifndef _MAC
+ if (GetScode(error) == OLE_S_MAC_CLIPFORMAT)
+ {
+ // check whether the clipformat is "pict"
+ // REVIEW, what's this cuteness?
+ if (dwRead != *((DWORD *)"TCIP"))
+ return(error);
+
+ if (pfConvert)
+ *pfConvert = TRUE;
+ else
+ return ResultFromScode(DV_E_CLIPFORMAT);
+
+ pforetc->cfFormat = CF_METAFILEPICT;
+ }
+ else
+#endif
+ return(error);
+ }
+
+ // set the proper tymed
+ if (pforetc->cfFormat == CF_METAFILEPICT)
+ {
+ pforetc->tymed = TYMED_MFPICT;
+ }
+ else if (pforetc->cfFormat == CF_ENHMETAFILE)
+ {
+ pforetc->tymed = TYMED_ENHMF;
+ }
+ else if (pforetc->cfFormat == CF_BITMAP)
+ {
+ AssertSz(0, "We don't read/save CF_BITMAP anymore");
+ return ResultFromScode(DV_E_CLIPFORMAT);
+ }
+ else if (pforetc->cfFormat == NULL)
+ {
+ pforetc->tymed = TYMED_NULL;
+ }
+ else
+ {
+ pforetc->tymed = TYMED_HGLOBAL;
+ }
+
+ // Read targetdevice info.
+ if (error = StRead(pstm, &dwRead, sizeof(dwRead)))
+ return(error);
+
+ // if the tdSize of ptd is non-null and is > 4, then go ahead read the
+ // remaining data of the target device info
+ if (dwRead > 4)
+ {
+ DVTARGETDEVICE *ptdA;
+ DVTDINFO dvtdInfo;
+
+ ptdA = (DVTARGETDEVICE *) PrivMemAlloc(dwRead);
+ if (NULL == ptdA)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ ptdA->tdSize = dwRead;
+ error = StRead(pstm, ((BYTE*)ptdA) + sizeof(dwRead),
+ dwRead - sizeof(dwRead));
+
+ if (SUCCEEDED(error))
+ {
+ error = UtGetDvtd16Info(ptdA, &dvtdInfo);
+ if (SUCCEEDED(error))
+ {
+ pforetc->ptd = (DVTARGETDEVICE *) PubMemAlloc(dvtdInfo.cbConvertSize);
+ if (NULL == pforetc->ptd)
+ {
+ error = E_OUTOFMEMORY;
+ }
+ else
+ {
+ error = UtConvertDvtd16toDvtd32(ptdA, &dvtdInfo, pforetc->ptd);
+ }
+ }
+ }
+
+ PrivMemFree(ptdA);
+
+ if (FAILED(error))
+ {
+ goto errRtn;
+ }
+ }
+ else
+ pforetc->ptd = NULL;
+
+ // Read DVASPECT, lindex, advise flags
+ if ((error = StRead(pstm, &opsh, sizeof(opsh))) != NOERROR)
+ goto errRtn;
+
+ pforetc->dwAspect = opsh.dwAspect;
+ pforetc->lindex = opsh.dwLindex;
+ if (pdwAdvf)
+ *pdwAdvf = opsh.dwAdvf;
+
+ return NOERROR;
+
+errRtn:
+ if (pforetc->ptd)
+ {
+ PubMemFree(pforetc->ptd);
+ pforetc->ptd = NULL;
+ }
+
+ return(error);
+}
+
+
+FARINTERNAL UtOlePresStmToContentsStm(LPSTORAGE pstg, LPOLESTR lpszPresStm,
+ BOOL fDeletePresStm, UINT FAR* puiStatus)
+{
+ VDATEHEAP();
+
+ LPSTREAM pstmOlePres;
+ LPSTREAM pstmContents = NULL;
+ HRESULT error;
+ FORMATETC foretc;
+ HDIBFILEHDR hdfh;
+
+ // there's no status yet
+ *puiStatus = 0;
+
+ // POSTPPC:
+ //
+ // This function needs to be rewritten to correctly handle the case described in
+ // the comments below (rather than just skipping out of the function if the contents
+ // stream already exists). The best course of action will probably be to convert
+ // DIBs->Metafiles and Metafiles->DIBs in the needed cases.
+
+ // The code inside the #ifdef below is used to determine if the contents
+ // stream has already been created (which is the case for an object that has
+ // been converted to a bitmap) because in the case of an object that has been
+ // converted to a static DIB and the object has a METAFILE presentation stream
+ // we already have a cachenode created as a DIB and we will read the contents
+ // stream after this call to get the DIB data. However, this function sees
+ // the metafile presentation, and converts it into the contents stream (which
+ // when then try to load as a DIB) and bad things happen (it doesn't work). If
+ // the stream already exists, then we bail out of this function.
+ if (pstg->CreateStream(OLE_CONTENTS_STREAM,(STGM_READWRITE | STGM_SHARE_EXCLUSIVE), NULL,
+ 0, &pstmContents) != NOERROR)
+ {
+ return NOERROR;
+ }
+
+ // created stream, it must not have existed
+ pstmContents->Release();
+ pstg->DestroyElement(OLE_CONTENTS_STREAM);
+
+ if ((error = pstg->OpenStream(lpszPresStm, NULL,
+ (STGM_READ | STGM_SHARE_EXCLUSIVE), 0, &pstmOlePres)) !=
+ NOERROR)
+ {
+ // we can't open the source stream
+ *puiStatus |= CONVERT_NOSOURCE;
+
+ // check whether "CONTENTS" stream exits
+ if (pstg->OpenStream(OLE_CONTENTS_STREAM, NULL,
+ (STGM_READ | STGM_SHARE_EXCLUSIVE), 0,
+ &pstmContents) != NOERROR)
+ {
+ // we can't open the destination stream either
+ // REVIEW, since we can't open the source, who cares?
+ // REVIEW, is there a cheaper way to test existence
+ // other than opening?
+ *puiStatus |= CONVERT_NODESTINATION;
+ }
+ else
+ pstmContents->Release();
+
+ return(error);
+ }
+
+ foretc.ptd = NULL;
+ if (error = UtReadOlePresStmHeader(pstmOlePres, &foretc, NULL, NULL))
+ goto errRtn;
+
+ if (error = pstmOlePres->Read(&hdfh, sizeof(hdfh), 0))
+ goto errRtn;
+
+ AssertSz(hdfh.dwCompression == 0,
+ "Non-zero compression not supported");
+
+ if (error = OpenOrCreateStream(pstg, OLE_CONTENTS_STREAM,
+ &pstmContents))
+ {
+ *puiStatus |= CONVERT_NODESTINATION;
+ goto errRtn;
+ }
+
+ if (foretc.dwAspect == DVASPECT_ICON)
+ {
+ *puiStatus |= CONVERT_SOURCEISICON;
+ fDeletePresStm = FALSE;
+ error = NOERROR;
+ goto errRtn;
+ }
+
+ if (foretc.cfFormat == CF_DIB)
+ error = UtDIBStmToDIBFileStm(pstmOlePres, hdfh.dwSize,
+ pstmContents);
+ else if (foretc.cfFormat == CF_METAFILEPICT)
+ error = UtMFStmToPlaceableMFStm(pstmOlePres,
+ hdfh.dwSize, hdfh.dwWidth, hdfh.dwHeight,
+ pstmContents);
+ else
+ error = ResultFromScode(DV_E_CLIPFORMAT);
+
+errRtn:
+ if (pstmOlePres)
+ pstmOlePres->Release();
+
+ if (pstmContents)
+ pstmContents->Release();
+
+ if (foretc.ptd)
+ PubMemFree(foretc.ptd);
+
+ if (error == NOERROR)
+ {
+ if (fDeletePresStm && lpszPresStm)
+ pstg->DestroyElement(lpszPresStm);
+ }
+ else
+ {
+ pstg->DestroyElement(OLE_CONTENTS_STREAM);
+ }
+
+ return(error);
+}
+
+
+FARINTERNAL_(HANDLE) UtGetHPRESFromNative(LPSTORAGE pstg, CLIPFORMAT cfFormat,
+ BOOL fOle10Native)
+{
+ VDATEHEAP();
+
+ LPSTREAM pstm;
+ HGLOBAL hdata = NULL;
+
+ if ((cfFormat != CF_METAFILEPICT) &&
+ (cfFormat != CF_DIB) &&
+ (cfFormat != CF_ENHMETAFILE))
+ {
+ return(NULL);
+ }
+
+ if (fOle10Native)
+ {
+ DWORD dwSize;
+
+ if (pstg->OpenStream(OLE10_NATIVE_STREAM, NULL,
+ (STGM_READ | STGM_SHARE_EXCLUSIVE), 0,
+ &pstm) != NOERROR)
+ return(NULL);
+
+ if (pstm->Read(&dwSize, sizeof(DWORD), NULL) == NOERROR)
+ {
+ // is it PBrush native data?
+ if (cfFormat == CF_DIB)
+ UtGetHDIBFromDIBFileStm(pstm, &hdata);
+ else
+ {
+ // MSDraw native data or PaintBrush
+ //
+ UtGetHMFPICTFromMSDrawNativeStm(pstm, dwSize,
+ &hdata);
+ }
+ }
+ }
+ else
+ {
+ if (pstg->OpenStream(OLE_CONTENTS_STREAM, NULL,
+ (STGM_READ | STGM_SHARE_EXCLUSIVE), 0,
+ &pstm) != NOERROR)
+ return(NULL);
+
+ if (cfFormat == CF_DIB)
+ {
+ UtGetHDIBFromDIBFileStm(pstm, &hdata);
+ }
+ else if (cfFormat == CF_METAFILEPICT)
+ {
+ UtGetHMFPICTFromPlaceableMFStm(pstm, &hdata);
+ }
+ else
+ {
+ UtGetHEMFFromContentsStm(pstm, &hdata);
+ }
+ }
+
+ pstm->Release();
+ return(hdata);
+}
+
+
diff --git a/private/ole32/ole232/util/daytona/makefile b/private/ole32/ole232/util/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/ole232/util/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/ole232/util/daytona/sources b/private/ole32/ole232/util/daytona/sources
new file mode 100644
index 000000000..ecc4ad7c6
--- /dev/null
+++ b/private/ole32/ole232/util/daytona/sources
@@ -0,0 +1,83 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = ole232
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= util
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES= ..\..\..\common\daytona;..\..\..\ih;..\..\inc
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+
+SOURCES= \
+ ..\convert.cpp \
+ ..\global.cpp \
+ ..\info.cpp \
+ ..\map_kv.cpp \
+ ..\ole2util.cpp \
+ ..\plex.cpp \
+ ..\utils.cpp \
+ ..\utstream.cpp
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+!include ..\..\precomp2.inc
diff --git a/private/ole32/ole232/util/depend.mk b/private/ole32/ole232/util/depend.mk
new file mode 100644
index 000000000..6dc58d8fa
--- /dev/null
+++ b/private/ole32/ole232/util/depend.mk
@@ -0,0 +1,237 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\convert.obj $(OBJDIR)\convert.lst: .\convert.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\global.obj $(OBJDIR)\global.lst: .\global.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\info.obj $(OBJDIR)\info.lst: .\info.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\map_kv.obj $(OBJDIR)\map_kv.lst: .\map_kv.cpp \
+ $(CAIROLE)\ih\map_kv.h $(CAIROLE)\ih\plex.h \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\ole2util.obj $(OBJDIR)\ole2util.lst: .\ole2util.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\olenew.obj $(OBJDIR)\olenew.lst: .\olenew.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\plex.obj $(OBJDIR)\plex.lst: .\plex.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\plex.h $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\wchar.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\widewrap.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\utils.obj $(OBJDIR)\utils.lst: .\utils.cpp \
+ $(CAIROLE)\common\cobjerr.h $(CAIROLE)\common\rpcferr.h \
+ $(CAIROLE)\h\coguid.h $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h \
+ $(CAIROLE)\h\initguid.h $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h \
+ $(CAIROLE)\h\ole2dbg.h $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h \
+ $(CAIROLE)\h\storage.h $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h \
+ $(CAIROLE)\ih\ole2sp.h $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\memory.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\malloc.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\wchar.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\widewrap.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winmm.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
+$(OBJDIR)\utstream.obj $(OBJDIR)\utstream.lst: .\utstream.cpp \
+ $(CAIROLE)\ole232\inc\reterr.h $(CAIROLE)\common\cobjerr.h \
+ $(CAIROLE)\common\rpcferr.h $(CAIROLE)\h\coguid.h \
+ $(CAIROLE)\h\compobj.h $(CAIROLE)\h\dvobj.h $(CAIROLE)\h\initguid.h \
+ $(CAIROLE)\h\moniker.h $(CAIROLE)\h\ole2.h $(CAIROLE)\h\ole2dbg.h \
+ $(CAIROLE)\h\oleguid.h $(CAIROLE)\h\scode.h $(CAIROLE)\h\storage.h \
+ $(CAIROLE)\ih\debug.h $(CAIROLE)\ih\map_kv.h $(CAIROLE)\ih\ole2sp.h \
+ $(CAIROLE)\ih\olecoll.h $(CAIROLE)\ih\olemem.h \
+ $(CAIROLE)\ih\privguid.h $(CAIROLE)\ih\utils.h \
+ $(CAIROLE)\ih\utstream.h $(CAIROLE)\ih\valid.h \
+ $(CAIROLE)\ole232\inc\ole2int.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\limits.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\malloc.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\wchar.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\widewrap.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winmm.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
diff --git a/private/ole32/ole232/util/dirs b/private/ole32/ole232/util/dirs
new file mode 100644
index 000000000..1d0b9edbb
--- /dev/null
+++ b/private/ole32/ole232/util/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/ole232/util/filelist.mk b/private/ole32/ole232/util/filelist.mk
new file mode 100644
index 000000000..53af21763
--- /dev/null
+++ b/private/ole32/ole232/util/filelist.mk
@@ -0,0 +1,54 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = util.lib
+
+RELEASE =
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CPPFILES = \
+ .\convert.cpp \
+ .\global.cpp \
+ .\info.cpp \
+ .\map_kv.cpp \
+ .\ole2util.cpp \
+ .\olenew.cpp \
+ .\plex.cpp \
+ .\utils.cpp \
+ .\utstream.cpp \
+
+RCFILES =
+
+
+#
+# Libraries and other object files to link.
+#
+
+DEFFILE =
+
+LIBS =
+
+OBJFILES =
+
+#
+# Precompiled headers.
+#
+
+PFILE =
+
+!include $(CAIROLE)\ole232\ole.mk
diff --git a/private/ole32/ole232/util/global.cpp b/private/ole32/ole232/util/global.cpp
new file mode 100644
index 000000000..25c95487f
--- /dev/null
+++ b/private/ole32/ole232/util/global.cpp
@@ -0,0 +1,821 @@
+//+----------------------------------------------------------------------------
+//
+// File:
+// global.cpp
+//
+// Contents:
+// Ut functions that deal with HGlobals for debugging;
+// see le2int.h
+//
+// Classes:
+//
+// Functions:
+// UtGlobalAlloc
+// UtGlobalReAlloc
+// UtGlobalLock
+// UtGlobalUnlock
+// UtGlobalFree
+// UtGlobalFlush
+// UtSetClipboardData
+//
+// History:
+// 12/20/93 - ChrisWe - created
+// 01/11/94 - alexgo - added VDATEHEAP macros to every function
+// 02/25/94 AlexT Add some generic integrity checking
+// 03/30/94 AlexT Add UtSetClipboardData
+//
+// Notes:
+//
+// These routines are designed to catch bugs that corrupt GlobalAlloc memory.
+// We cannot guarantee that all global memory will be manipulated with these
+// routines (e.g. OLE might allocate a handle and the client application
+// might free it), so we can't require that these routines be used in pairs.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <le2int.h>
+
+#if DBG==1 && defined(WIN32)
+#include <olesem.hxx>
+
+ASSERTDATA
+
+// undefine these, so we don't call ourselves recursively
+// if this module is used, these are defined in le2int.h to replace
+// the existing allocator with the functions here
+#undef GlobalAlloc
+#undef GlobalReAlloc
+#undef GlobalLock
+#undef GlobalUnlock
+#undef GlobalFree
+#undef SetClipboardData
+
+// Same ones as in memapi.cxx
+#define OLEMEM_ALLOCBYTE 0xde
+#define OLEMEM_FREEBYTE 0xed
+
+typedef struct s_GlobalAllocInfo
+{
+ HGLOBAL hGlobal; // A GlobalAlloc'd HGLOBAL
+ ULONG cbGlobalSize; // GlobalSize(hGlobal)
+ ULONG cbUser; // size requested by caller
+ ULONG ulIndex; // allocation index (1st, 2nd...)
+ struct s_GlobalAllocInfo *pNext;
+} SGLOBALALLOCINFO, *PSGLOBALALLOCINFO;
+
+//+-------------------------------------------------------------------------
+//
+// Class: CGlobalTrack
+//
+// Purpose: GlobalAlloc memory tracking
+//
+// History: 25-Feb-94 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CGlobalTrack
+{
+ public:
+
+ //
+ // We only have a constructor for debug builds, to ensure this object
+ // is statically allocated. Statically allocated objects are initialized
+ // to all zeroes, which is what we need.
+ //
+
+ CGlobalTrack();
+
+ HGLOBAL cgtGlobalAlloc(UINT uiFlag, DWORD cbUser);
+ HGLOBAL cgtGlobalReAlloc(HGLOBAL hGlobal, DWORD cbUser, UINT uiFlag);
+ HGLOBAL cgtGlobalFree(HGLOBAL hGlobal);
+ LPVOID cgtGlobalLock(HGLOBAL hGlobal);
+ BOOL cgtGlobalUnlock(HGLOBAL hGlobal);
+
+ void cgtVerifyAll(void);
+ void cgtFlushTracking(void);
+ BOOL cgtStopTracking(HGLOBAL hGlobal);
+
+ private:
+ ULONG CalculateAllocSize(ULONG cbUser);
+ void InitializeRegion(HGLOBAL hGlobal, ULONG cbStart, ULONG cbEnd);
+ void Track(HGLOBAL hGlobal, ULONG cbUser);
+ void Retrack(HGLOBAL hOld, HGLOBAL hNew);
+ void VerifyHandle(HGLOBAL hGlobal);
+
+ ULONG _ulIndex;
+ PSGLOBALALLOCINFO _pRoot;
+ static COleStaticMutexSem _mxsGlobalMemory;
+};
+
+COleStaticMutexSem CGlobalTrack::_mxsGlobalMemory;
+
+CGlobalTrack gGlobalTrack;
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGlobalTrack::CGlobalTrack, public
+//
+// Synopsis: constructor
+//
+// History: 28-Feb-94 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+CGlobalTrack::CGlobalTrack()
+{
+ Win4Assert (g_fDllState == DLL_STATE_STATIC_CONSTRUCTING);
+ Win4Assert (_pRoot == NULL && _ulIndex == 0);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGlobalTrack::cgtGlobalAlloc, public
+//
+// Synopsis: Debugging version of GlobalAlloc
+//
+// Arguments: [uiFlag] -- allocation flags
+// [cbUser] -- requested allocation size
+//
+// Requires: We must return a "real" GlobalAlloc'd pointer, because
+// we may not necessarily be the ones to free it.
+//
+// Returns: HGLOBAL
+//
+// Algorithm: We allocate an extra amount to form a tail and initialize it
+// to a known value.
+//
+// History: 25-Feb-94 AlexT Added this prologue
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HGLOBAL CGlobalTrack::cgtGlobalAlloc(UINT uiFlag, DWORD cbUser)
+{
+ VDATEHEAP();
+
+ ULONG cbAlloc;
+ HGLOBAL hGlobal;
+
+ cbAlloc = CalculateAllocSize(cbUser);
+ hGlobal = GlobalAlloc(uiFlag, cbAlloc);
+ if (NULL == hGlobal)
+ {
+ LEDebugOut((DEB_WARN, "GlobalAlloc(%ld) failed - %lx\n", cbAlloc,
+ GetLastError()));
+ }
+ else
+ {
+ if (uiFlag & GMEM_ZEROINIT)
+ {
+ // Caller asked for zeroinit, so we only initialize the tail
+ InitializeRegion(hGlobal, cbUser, cbAlloc);
+ }
+ else
+ {
+ // Caller did not ask for zeroinit, so we initialize the whole
+ // region
+ InitializeRegion(hGlobal, 0, cbAlloc);
+ }
+
+ Track(hGlobal, cbUser);
+ }
+
+ return(hGlobal);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGlobalTrack::cgtGlobalReAlloc, public
+//
+// Synopsis: Debugging version of GlobalReAlloc
+//
+// Arguments: [hGlobal] -- handle to reallocate
+// [cbUser] -- requested allocation size
+// [uiFlag] -- allocation flags
+//
+// Returns: reallocated handle
+//
+// Algorithm:
+//
+// if (modify only)
+// reallocate
+// else
+// reallocate with tail
+// initialize tail
+//
+// update tracking information
+//
+// History: 25-Feb-94 AlexT Added this prologue
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HGLOBAL CGlobalTrack::cgtGlobalReAlloc(HGLOBAL hGlobal, DWORD cbUser, UINT uiFlag)
+{
+ VDATEHEAP();
+
+ HGLOBAL hNew;
+ ULONG cbAlloc;
+
+ VerifyHandle(hGlobal);
+
+ if (uiFlag & GMEM_MODIFY)
+ {
+ // We're not changing sizes, so there's no work for us to do
+
+ LEDebugOut((DEB_WARN, "UtGlobalReAlloc modifying global handle\n"));
+ hNew = GlobalReAlloc(hGlobal, cbUser, uiFlag);
+ }
+ else
+ {
+ cbAlloc = CalculateAllocSize(cbUser);
+ hNew = GlobalReAlloc(hGlobal, cbAlloc, uiFlag);
+ if (NULL == hNew)
+ {
+ LEDebugOut((DEB_WARN, "GlobalReAlloc failed - %lx\n",
+ GetLastError()));
+ }
+ else
+ {
+ InitializeRegion(hNew, cbUser, cbAlloc);
+ }
+ }
+
+ if (NULL != hNew)
+ {
+ if (uiFlag & GMEM_MODIFY)
+ {
+ // Retrack will only track hNew if we were tracking hGlobal
+ Retrack(hGlobal, hNew);
+ }
+ else
+ {
+ // We've allocated a new block, so we always want to track the
+ // new one
+ cgtStopTracking(hGlobal);
+ Track(hNew, cbUser);
+ }
+ }
+
+ return(hNew);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGlobalTrack::cgtGlobalFree, public
+//
+// Synopsis: Debugging version of GlobalReAlloc
+//
+// Arguments: [hGlobal] -- global handle to free
+//
+// Returns: Same as GlobalFree
+//
+// Algorithm:
+//
+// History: 25-Feb-94 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HGLOBAL CGlobalTrack::cgtGlobalFree(HGLOBAL hGlobal)
+{
+ VDATEHEAP();
+
+ HGLOBAL hReturn;
+
+ VerifyHandle(hGlobal);
+
+ hReturn = GlobalFree(hGlobal);
+
+ if (NULL == hReturn)
+ {
+ cgtStopTracking(hGlobal);
+ }
+ else
+ {
+ LEDebugOut((DEB_WARN, "GlobalFree did not free %lx\n", hGlobal));
+ }
+
+ return(hReturn);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGlobalTrack::cgtGlobalLock, public
+//
+// Synopsis: Debugging version of GlobalLock
+//
+// Arguments: [hGlobal] -- global memory handle
+//
+// Returns: Same as GlobalLock
+//
+// History: 25-Feb-94 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+LPVOID CGlobalTrack::cgtGlobalLock(HGLOBAL hGlobal)
+{
+ VDATEHEAP();
+
+ VerifyHandle(hGlobal);
+ return(GlobalLock(hGlobal));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGlobalTrack::cgtGlobalUnlock, public
+//
+// Synopsis: Debugging version of GlobalUnlock
+//
+// Arguments: [hGlobal] -- global memory handle
+//
+// Returns: Same as GlobalUnlock
+//
+// History: 25-Feb-94 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+BOOL CGlobalTrack::cgtGlobalUnlock(HGLOBAL hGlobal)
+{
+ VDATEHEAP();
+
+ VerifyHandle(hGlobal);
+ return(GlobalUnlock(hGlobal));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGlobalTrack::cgtVerifyAll, public
+//
+// Synopsis: Verify all tracked handles
+//
+// History: 28-Feb-94 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+void CGlobalTrack::cgtVerifyAll(void)
+{
+ VerifyHandle(NULL);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGlobalTrack::cgtFlushTracking
+//
+// Synopsis: Stops all tracking
+//
+// Effects: Frees all internal memory
+//
+// History: 28-Feb-94 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+void CGlobalTrack::cgtFlushTracking(void)
+{
+ COleStaticLock lck(_mxsGlobalMemory);
+ BOOL bResult;
+
+ while (NULL != _pRoot)
+ {
+ bResult = cgtStopTracking(_pRoot->hGlobal);
+ Assert(bResult && "CGT::cgtFlushTracking problem");
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGlobalTrack::CalculateAllocSize, private
+//
+// Synopsis: calculate total allocation size (inluding tail)
+//
+// Arguments: [cbUser] -- requested size
+//
+// Returns: total count of bytes to allocate
+//
+// Algorithm: calculate bytes needed to have at least one guard page at the
+// end
+//
+// History: 28-Feb-94 AlexT Created
+//
+// Notes: By keeping this calculation in one location we make it
+// easier to maintain.
+//
+//--------------------------------------------------------------------------
+
+ULONG CGlobalTrack::CalculateAllocSize(ULONG cbUser)
+{
+ SYSTEM_INFO si;
+ ULONG cbAlloc;
+
+#ifdef _CHICAGO_
+ // BUGBUG Chicago: GetSystemInfo not yet implemented
+ si.dwPageSize = 0x1000;
+#else
+ GetSystemInfo(&si);
+#endif
+
+ // Calculate how many pages are need to cover cbUser
+ cbAlloc = ((cbUser + si.dwPageSize - 1) / si.dwPageSize) * si.dwPageSize;
+
+ // Add an extra page so that the tail is at least one page long
+ cbAlloc += si.dwPageSize;
+
+ return(cbAlloc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGlobalTrack::InitializeRegion, private
+//
+// Synopsis: initialize region to bad value
+//
+// Effects: fills in memory region
+//
+// Arguments: [hGlobal] -- global memory handle
+// [cbStart] -- count of bytes to skip
+// [cbEnd] -- end offset (exclusive)
+//
+// Requires: cbEnd > cbStart
+//
+// Algorithm: fill in hGlobal from cbStart (inclusive) to cbEnd (exclusive)
+//
+// History: 28-Feb-94 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+void CGlobalTrack::InitializeRegion(HGLOBAL hGlobal, ULONG cbStart, ULONG cbEnd)
+{
+ BYTE *pbStart;
+ BYTE *pb;
+
+ Assert(cbStart < cbEnd && "illogical parameters");
+ Assert(cbEnd <= GlobalSize(hGlobal) && "global memory too small");
+
+ // GlobalLock on GMEM_FIXED memory is a nop, so this is a safe call
+ pbStart = (BYTE *) GlobalLock(hGlobal);
+
+ if (NULL == pbStart)
+ {
+ // Shouldn't have failed - (we allocated > 0 bytes)
+
+ LEDebugOut((DEB_WARN, "GlobalLock failed - %lx\n", GetLastError()));
+ return;
+ }
+
+ // Initialize the tail portion of the memory
+ for (pb = pbStart + cbStart; pb < pbStart + cbEnd; pb++)
+ {
+ *pb = OLEMEM_ALLOCBYTE;
+ }
+
+ GlobalUnlock(hGlobal);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGlobalTrack::Track, private
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [hGlobal] -- global memory handle
+// [cbUser] -- user allocation size
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: 28-Feb-94 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+void CGlobalTrack::Track(HGLOBAL hGlobal, ULONG cbUser)
+{
+ COleStaticLock lck(_mxsGlobalMemory);
+ PSGLOBALALLOCINFO pgi;
+
+ if (cgtStopTracking(hGlobal))
+ {
+ // If it's already in our list, it's possible that someone else
+ // freed the HGLOBAL without telling us - remove our stale one
+ LEDebugOut((DEB_WARN, "CGT::Track - %lx was already in list!\n",
+ hGlobal));
+ }
+
+ pgi = (PSGLOBALALLOCINFO) PrivMemAlloc(sizeof(SGLOBALALLOCINFO));
+ if (NULL == pgi)
+ {
+ LEDebugOut((DEB_WARN, "CGT::Insert - PrivMemAlloc failed\n"));
+
+ // Okay fine - we just won't track this one
+
+ return;
+ }
+
+ pgi->hGlobal = hGlobal;
+ pgi->cbGlobalSize = GlobalSize(hGlobal);
+ Assert((0 == cbUser || pgi->cbGlobalSize > 0) && "GlobalSize failed - bad handle?");
+ pgi->cbUser = cbUser;
+ pgi->ulIndex = ++_ulIndex;
+ pgi->pNext = _pRoot;
+ _pRoot = pgi;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGlobalTrack::Retrack, private
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [hOld] -- previous handle
+// [hNew] -- new handle
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 28-Feb-94 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+void CGlobalTrack::Retrack(HGLOBAL hOld, HGLOBAL hNew)
+{
+ COleStaticLock lck(_mxsGlobalMemory);
+ PSGLOBALALLOCINFO pgi;
+
+ if (hOld != hNew && cgtStopTracking(hNew))
+ {
+ // If hNew was already in the list, it's possible that someone else
+ // freed the HGLOBAL without telling us so we removed the stale one
+ LEDebugOut((DEB_WARN, "CGT::Retrack - %lx was already in list!\n", hNew));
+ }
+
+ for (pgi = _pRoot; NULL != pgi; pgi = pgi->pNext)
+ {
+ if (pgi->hGlobal == hOld)
+ {
+ pgi->hGlobal = hNew;
+ break;
+ }
+ }
+
+ if (NULL == pgi)
+ {
+ // We didn't find hOld
+ LEDebugOut((DEB_WARN, "CGT::Retrack - hOld (%lx) not found\n", hOld));
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGlobalTrack::cgtStopTracking, public
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [hGlobal] -- global handle
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 28-Feb-94 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+BOOL CGlobalTrack::cgtStopTracking(HGLOBAL hGlobal)
+{
+ COleStaticLock lck(_mxsGlobalMemory);
+ PSGLOBALALLOCINFO *ppgi = &_pRoot;
+ PSGLOBALALLOCINFO pgi;
+
+ while (*ppgi != NULL && (*ppgi)->hGlobal != hGlobal)
+ {
+ ppgi = &((*ppgi)->pNext);
+ }
+
+ if (NULL == *ppgi)
+ {
+ return(FALSE);
+ }
+
+ pgi = *ppgi;
+ Assert(pgi->hGlobal == hGlobal && "CGT::cgtStopTracking search problem");
+
+ *ppgi = pgi->pNext;
+
+ PrivMemFree(pgi);
+ return(TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CGlobalTrack::VerifyHandle, private
+//
+// Synopsis: Verify global handle
+//
+// Arguments: [hGlobal] -- global memory handle
+//
+// Signals: Asserts if bad
+//
+// Algorithm:
+//
+// History: 28-Feb-94 AlexT Created
+// 22-Jun-94 AlexT Allow for handle to have been freed and
+// reallocated under us
+//
+//--------------------------------------------------------------------------
+
+void CGlobalTrack::VerifyHandle(HGLOBAL hGlobal)
+{
+ COleStaticLock lck(_mxsGlobalMemory);
+ PSGLOBALALLOCINFO pgi, pgiNext;
+ ULONG cbAlloc;
+ BYTE *pbStart;
+ BYTE *pb;
+
+ // Note that we use a while loop (recording pgiNext up front) instead
+ // of a for loop because pgi will get removed from the list if we call
+ // cgtStopTracking on it
+
+ pgi = _pRoot;
+ while (NULL != pgi)
+ {
+ pgiNext = pgi->pNext;
+
+ if (NULL == hGlobal || pgi->hGlobal == hGlobal)
+ {
+ if (pgi->cbGlobalSize != GlobalSize(pgi->hGlobal))
+ {
+ // pgi->hGlobal's size has changed since we started tracking
+ // it; it must have been freed or reallocated by someone
+ // else. Stop tracking it.
+
+ // This call will remove pgi from the list (so we NULL it to
+ // make sure we don't try reusing it)!
+
+ cgtStopTracking(pgi->hGlobal);
+ pgi = NULL;
+ }
+ else
+ {
+ cbAlloc = CalculateAllocSize(pgi->cbUser);
+
+ pbStart = (BYTE *) GlobalLock(pgi->hGlobal);
+
+ // it is legitimate to have a zero length (NULL memory) handle
+ if (NULL == pbStart)
+ {
+ LEDebugOut((DEB_WARN, "GlobalLock failed - %lx\n",
+ GetLastError()));
+ }
+ else
+ {
+ for (pb = pbStart + pgi->cbUser;
+ pb < pbStart + cbAlloc;
+ pb++)
+ {
+ if (*pb != OLEMEM_ALLOCBYTE)
+ break;
+ }
+
+ if (pb < pbStart + cbAlloc)
+ {
+ // In general an application may have freed and reallocated
+ // any HGLOBAL, so we can only warn about corruption.
+
+ LEDebugOut((DEB_WARN, "HGLOBAL #%ld may be corrupt\n",
+ pgi->ulIndex));
+#ifdef GLOBALDBG
+ // If GLOBALDBG is true, then all allocations should be
+ // coming through these routines. In this case we assert
+ // if we've found corruption.
+ Assert(0 && "CGlobalTrack::VerifyHandle - HGLOBAL corrupt");
+#endif
+ }
+
+ GlobalUnlock(pgi->hGlobal);
+ }
+ }
+ }
+
+ pgi = pgiNext;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtGlobalAlloc, ReAlloc, Free, Lock, Unlock
+//
+// Synopsis: Debug versions of Global memory routines
+//
+// Arguments: Same as Windows APIs
+//
+// History: 28-Feb-94 AlexT Created
+//
+// Notes: These entry points just call the worker routines
+//
+//--------------------------------------------------------------------------
+
+extern "C" HGLOBAL WINAPI UtGlobalAlloc(UINT uiFlag, DWORD cbUser)
+{
+ return gGlobalTrack.cgtGlobalAlloc(uiFlag, cbUser);
+}
+
+extern "C" HGLOBAL WINAPI UtGlobalReAlloc(HGLOBAL hGlobal, DWORD cbUser, UINT uiFlag)
+{
+ return gGlobalTrack.cgtGlobalReAlloc(hGlobal, cbUser, uiFlag);
+}
+
+extern "C" LPVOID WINAPI UtGlobalLock(HGLOBAL hGlobal)
+{
+ return gGlobalTrack.cgtGlobalLock(hGlobal);
+}
+
+extern "C" BOOL WINAPI UtGlobalUnlock(HGLOBAL hGlobal)
+{
+ return gGlobalTrack.cgtGlobalUnlock(hGlobal);
+}
+
+extern "C" HGLOBAL WINAPI UtGlobalFree(HGLOBAL hGlobal)
+{
+ return gGlobalTrack.cgtGlobalFree(hGlobal);
+}
+
+extern "C" void UtGlobalFlushTracking(void)
+{
+ gGlobalTrack.cgtFlushTracking();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtSetClipboardData
+//
+// Synopsis: Calls Windows SetClipboardData and stops tracking the handle
+//
+// Arguments: [uFormat] -- clipboard format
+// [hMem] -- data handle
+//
+// Returns: Same as SetClipboard
+//
+// Algorithm: If SetClipboardData succeeds, stop tracking the handle
+//
+// History: 30-Mar-94 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+extern "C" HANDLE WINAPI UtSetClipboardData(UINT uFormat, HANDLE hMem)
+{
+ HANDLE hRet;
+
+ hRet = SetClipboardData(uFormat, hMem);
+
+ if (NULL != hRet)
+ {
+ gGlobalTrack.cgtStopTracking(hMem);
+ }
+
+ return(hRet);
+}
+
+#endif // DBG==1 && defined(WIN32)
diff --git a/private/ole32/ole232/util/info.cpp b/private/ole32/ole232/util/info.cpp
new file mode 100644
index 000000000..5e2d7abd5
--- /dev/null
+++ b/private/ole32/ole232/util/info.cpp
@@ -0,0 +1,65 @@
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: info.cpp
+//
+// Contents: RegisterWithCommnot and other hacks to build in
+// the cairo environment
+//
+// Classes:
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 26-Oct-93 alexgo snagged and hacked from RickSa's stuff
+//
+// Notes:
+// This stuff is OBSOLETE!! Remove it whenever BryanT
+// removes the calls from the dll loaders...
+//
+//--------------------------------------------------------------------------
+
+
+#include <le2int.h>
+
+// BUGBUG: Temporary definitions of functions these probably can be removed
+// as they are probably obsolete.
+
+
+//+-------------------------------------------------------------------
+//
+// Function: RegisterWithCommnot
+//
+// Synopsis: Used by Cairo to work around DLL unloading problems
+//
+// Arguments: <none>
+//
+// History: 06-Oct-92 BryanT Created
+//
+//--------------------------------------------------------------------
+STDAPI_(void) RegisterWithCommnot( void )
+{
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: DeRegisterWithCommnot
+//
+// Synopsis: Used by Cairo to work around DLL unloading problems
+//
+// Arguments: <none>
+//
+// History: 06-Oct-92 BryanT Created
+//
+// Notes: BUGBUG: Keep in touch with BryanT to see if this is
+// obsolete.
+//
+//--------------------------------------------------------------------
+
+STDAPI_(void) DeRegisterWithCommnot( void )
+{
+}
+
diff --git a/private/ole32/ole232/util/makefile b/private/ole32/ole232/util/makefile
new file mode 100644
index 000000000..1725b5e9a
--- /dev/null
+++ b/private/ole32/ole232/util/makefile
@@ -0,0 +1,26 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1992.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+# We need to do the following so that build will stop reading from the
+# pipe.
+
+all :
+ echo $(BUILDMSG)
+
+clean : all
+
+!else # NTMAKEENV
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/ole232/util/map_kv.cpp b/private/ole32/ole232/util/map_kv.cpp
new file mode 100644
index 000000000..7ba103fb0
--- /dev/null
+++ b/private/ole32/ole232/util/map_kv.cpp
@@ -0,0 +1,666 @@
+/////////////////////////////////////////////////////////////////////////////
+// class CMapKeyToValue - a mapping from 'KEY's to 'VALUE's, passed in as
+// pv/cb pairs. The keys can be variable length, although we optmizize the
+// case when they are all the same.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include <le2int.h>
+#pragma SEG(map_kv)
+
+#include "map_kv.h"
+
+#include "plex.h"
+ASSERTDATA
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+#pragma SEG(CMapKeyToValue_ctor)
+CMapKeyToValue::CMapKeyToValue(UINT cbValue, UINT cbKey,
+ int nBlockSize, LPFNHASHKEY lpfnHashKey, UINT nHashSize)
+{
+ VDATEHEAP();
+
+ Assert(nBlockSize > 0);
+
+ m_cbValue = cbValue;
+ m_cbKey = cbKey;
+ m_cbKeyInAssoc = cbKey == 0 ? sizeof(CKeyWrap) : cbKey;
+
+ m_pHashTable = NULL;
+ m_nHashTableSize = nHashSize;
+ m_lpfnHashKey = lpfnHashKey;
+
+ m_nCount = 0;
+ m_pFreeList = NULL;
+ m_pBlocks = NULL;
+ m_nBlockSize = nBlockSize;
+}
+
+#pragma SEG(CMapKeyToValue_dtor)
+CMapKeyToValue::~CMapKeyToValue()
+{
+ VDATEHEAP();
+
+ ASSERT_VALID(this);
+ RemoveAll();
+ Assert(m_nCount == 0);
+}
+
+#define LOCKTHIS
+#define UNLOCKTHIS
+
+#ifdef NEVER
+void CMapKeyToValue::LockThis(void)
+{
+ VDATEHEAP();
+
+ LOCKTHIS;
+}
+
+void CMapKeyToValue::UnlockThis(void)
+{
+ VDATEHEAP();
+
+ UNLOCKTHIS;
+}
+
+#endif //NEVER
+
+#pragma SEG(MKVDefaultHashKey)
+// simple, default hash function
+// REVIEW: need to check the value in this for GUIDs and strings
+STDAPI_(UINT) MKVDefaultHashKey(LPVOID pKey, UINT cbKey)
+{
+ VDATEHEAP();
+
+ UINT hash = 0;
+ BYTE FAR* lpb = (BYTE FAR*)pKey;
+
+ while (cbKey-- != 0)
+ hash = 257 * hash + *lpb++;
+
+ return hash;
+}
+
+
+#pragma SEG(CMapKeyToValue_InitHashTable)
+BOOL CMapKeyToValue::InitHashTable()
+{
+ VDATEHEAP();
+
+ ASSERT_VALID(this);
+ Assert(m_nHashTableSize > 0);
+
+ if (m_pHashTable != NULL)
+ return TRUE;
+
+ Assert(m_nCount == 0);
+
+ if ((m_pHashTable = (CAssoc FAR* FAR*)PrivMemAlloc(m_nHashTableSize *
+ sizeof(CAssoc FAR*))) == NULL)
+ return FALSE;
+
+ _xmemset(m_pHashTable, 0, sizeof(CAssoc FAR*) * m_nHashTableSize);
+
+ ASSERT_VALID(this);
+
+ return TRUE;
+}
+
+
+#pragma SEG(CMapKeyToValue_RemoveAll)
+void CMapKeyToValue::RemoveAll()
+{
+ VDATEHEAP();
+
+ LOCKTHIS;
+
+ ASSERT_VALID(this);
+
+ // free all key values and then hash table
+ if (m_pHashTable != NULL)
+ {
+ // destroy assocs
+ for (UINT nHash = 0; nHash < m_nHashTableSize; nHash++)
+ {
+ register CAssoc FAR* pAssoc;
+ for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL;
+ pAssoc = pAssoc->pNext)
+ // assoc itself is freed by FreeDataChain below
+ FreeAssocKey(pAssoc);
+ }
+
+ // free hash table
+ PrivMemFree(m_pHashTable);
+ m_pHashTable = NULL;
+ }
+
+ m_nCount = 0;
+ m_pFreeList = NULL;
+ m_pBlocks->FreeDataChain();
+ m_pBlocks = NULL;
+
+ ASSERT_VALID(this);
+ UNLOCKTHIS;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Assoc helpers
+// CAssoc's are singly linked all the time
+
+#pragma SEG(CMapKeyToValue_NewAssoc)
+CMapKeyToValue::CAssoc FAR*
+ CMapKeyToValue::NewAssoc(UINT hash, LPVOID pKey, UINT cbKey, LPVOID pValue)
+{
+ VDATEHEAP();
+
+ if (m_pFreeList == NULL)
+ {
+ // add another block
+ CPlex FAR* newBlock = CPlex::Create(m_pBlocks, m_nBlockSize, SizeAssoc());
+
+ if (newBlock == NULL)
+ return NULL;
+
+ // chain them into free list
+ register BYTE FAR* pbAssoc = (BYTE FAR*) newBlock->data();
+ // free in reverse order to make it easier to debug
+ pbAssoc += (m_nBlockSize - 1) * SizeAssoc();
+ for (int i = m_nBlockSize-1; i >= 0; i--, pbAssoc -= SizeAssoc())
+ {
+ ((CAssoc FAR*)pbAssoc)->pNext = m_pFreeList;
+ m_pFreeList = (CAssoc FAR*)pbAssoc;
+ }
+ }
+ Assert(m_pFreeList != NULL); // we must have something
+
+ CMapKeyToValue::CAssoc FAR* pAssoc = m_pFreeList;
+
+ // init all fields except pNext while still on free list
+ pAssoc->nHashValue = hash;
+ if (!SetAssocKey(pAssoc, pKey, cbKey))
+ return NULL;
+
+ SetAssocValue(pAssoc, pValue);
+
+ // remove from free list after successfully initializing it (except pNext)
+ m_pFreeList = m_pFreeList->pNext;
+ m_nCount++;
+ Assert(m_nCount > 0); // make sure we don't overflow
+
+ return pAssoc;
+}
+
+
+#pragma SEG(CMapKeyToValue_FreeAssoc)
+// free individual assoc by freeing key and putting on free list
+void CMapKeyToValue::FreeAssoc(CMapKeyToValue::CAssoc FAR* pAssoc)
+{
+ VDATEHEAP();
+
+ pAssoc->pNext = m_pFreeList;
+ m_pFreeList = pAssoc;
+ m_nCount--;
+ Assert(m_nCount >= 0); // make sure we don't underflow
+
+ FreeAssocKey(pAssoc);
+}
+
+
+#pragma SEG(CMapKeyToValue_GetAssocAt)
+// find association (or return NULL)
+CMapKeyToValue::CAssoc FAR*
+CMapKeyToValue::GetAssocAt(LPVOID pKey, UINT cbKey, UINT FAR& nHash) const
+{
+ VDATEHEAP();
+
+ if (m_lpfnHashKey)
+ nHash = (*m_lpfnHashKey)(pKey, cbKey) % m_nHashTableSize;
+ else
+ nHash = MKVDefaultHashKey(pKey, cbKey) % m_nHashTableSize;
+
+ if (m_pHashTable == NULL)
+ return NULL;
+
+ // see if it exists
+ register CAssoc FAR* pAssoc;
+ for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext)
+ {
+ if (CompareAssocKey(pAssoc, pKey, cbKey))
+ return pAssoc;
+ }
+ return NULL;
+}
+
+
+#pragma SEG(CMapKeyToValue_CompareAssocKey)
+BOOL CMapKeyToValue::CompareAssocKey(CAssoc FAR* pAssoc, LPVOID pKey2, UINT cbKey2) const
+{
+ VDATEHEAP();
+
+ LPVOID pKey1;
+ UINT cbKey1;
+
+ GetAssocKeyPtr(pAssoc, &pKey1, &cbKey1);
+ return cbKey1 == cbKey2 && _xmemcmp(pKey1, pKey2, cbKey1) == 0;
+}
+
+
+#pragma SEG(CMapKeyToValue_SetAssocKey)
+BOOL CMapKeyToValue::SetAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const
+{
+ VDATEHEAP();
+
+ Assert(cbKey == m_cbKey || m_cbKey == 0);
+
+ if (m_cbKey == 0)
+ {
+ Assert(m_cbKeyInAssoc == sizeof(CKeyWrap));
+
+ // alloc, set size and pointer
+ if ((pAssoc->key.pKey = PrivMemAlloc(cbKey)) == NULL)
+ return FALSE;
+
+ pAssoc->key.cbKey = cbKey;
+ }
+
+ LPVOID pKeyTo;
+
+ GetAssocKeyPtr(pAssoc, &pKeyTo, &cbKey);
+
+ _xmemcpy(pKeyTo, pKey, cbKey);
+
+ return TRUE;
+}
+
+
+#pragma SEG(CMapKeyToValue_GetAssocKeyPtr)
+// gets pointer to key and its length
+void CMapKeyToValue::GetAssocKeyPtr(CAssoc FAR* pAssoc, LPVOID FAR* ppKey,UINT FAR* pcbKey) const
+{
+ VDATEHEAP();
+
+ if (m_cbKey == 0)
+ {
+ // variable length key; go indirect
+ *ppKey = pAssoc->key.pKey;
+ *pcbKey = pAssoc->key.cbKey;
+ }
+ else
+ {
+ // fixed length key; key in assoc
+ *ppKey = (LPVOID)&pAssoc->key;
+ *pcbKey = m_cbKey;
+ }
+}
+
+
+#pragma SEG(CMapKeyToValue_FreeAssocKey)
+void CMapKeyToValue::FreeAssocKey(CAssoc FAR* pAssoc) const
+{
+ VDATEHEAP();
+
+ if (m_cbKey == 0)
+ PrivMemFree(pAssoc->key.pKey);
+}
+
+
+#pragma SEG(CMapKeyToValue_GetAssocValuePtr)
+void CMapKeyToValue::GetAssocValuePtr(CAssoc FAR* pAssoc, LPVOID FAR* ppValue) const
+{
+ VDATEHEAP();
+
+ *ppValue = (char FAR*)&pAssoc->key + m_cbKeyInAssoc;
+}
+
+
+#pragma SEG(CMapKeyToValue_GetAssocValue)
+void CMapKeyToValue::GetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const
+{
+ VDATEHEAP();
+
+ LPVOID pValueFrom;
+ GetAssocValuePtr(pAssoc, &pValueFrom);
+ Assert(pValue != NULL);
+ _xmemcpy(pValue, pValueFrom, m_cbValue);
+}
+
+
+#pragma SEG(CMapKeyToValue_SetAssocValue)
+void CMapKeyToValue::SetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const
+{
+ VDATEHEAP();
+
+ LPVOID pValueTo;
+ GetAssocValuePtr(pAssoc, &pValueTo);
+ if (pValue == NULL)
+ _xmemset(pValueTo, 0, m_cbValue);
+ else
+ _xmemcpy(pValueTo, pValue, m_cbValue);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma SEG(CMapKeyToValue_Lookup)
+// lookup value given key; return FALSE if key not found; in that
+// case, the value is set to all zeros
+BOOL CMapKeyToValue::Lookup(LPVOID pKey, UINT cbKey, LPVOID pValue) const
+{
+ VDATEHEAP();
+
+ UINT nHash;
+ BOOL fFound;
+
+ LOCKTHIS;
+ fFound = LookupHKey((HMAPKEY)GetAssocAt(pKey, cbKey, nHash), pValue);
+ UNLOCKTHIS;
+ return fFound;
+}
+
+
+#pragma SEG(CMapKeyToValue_LookupHKey)
+// lookup value given key; return FALSE if NULL (or bad) key; in that
+// case, the value is set to all zeros
+BOOL CMapKeyToValue::LookupHKey(HMAPKEY hKey, LPVOID pValue) const
+{
+ VDATEHEAP();
+
+ BOOL fFound = FALSE;
+
+ LOCKTHIS;
+
+ // REVIEW: would like some way to verify that hKey is valid
+ register CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+ if (pAssoc == NULL)
+ {
+ _xmemset(pValue, 0, m_cbValue);
+ goto Exit; // not in map
+ }
+
+ ASSERT_VALID(this);
+
+ GetAssocValue(pAssoc, pValue);
+ fFound = TRUE;
+Exit:
+ UNLOCKTHIS;
+ return fFound;
+}
+
+
+#pragma SEG(CMapKeyToValue_LookupAdd)
+// lookup and if not found add; returns FALSE only if OOM; if added,
+// value added and pointer passed are set to zeros.
+BOOL CMapKeyToValue::LookupAdd(LPVOID pKey, UINT cbKey, LPVOID pValue) const
+{
+ VDATEHEAP();
+
+ BOOL fFound;
+
+ LOCKTHIS;
+
+ fFound = Lookup(pKey, cbKey, pValue);
+ if (!fFound) // value set to zeros since lookup failed
+ fFound = ((CMapKeyToValue FAR*)this)->SetAt(pKey, cbKey, NULL);
+
+ UNLOCKTHIS;
+ return fFound;
+}
+
+
+#pragma SEG(CMapKeyToValue_SetAt)
+// the only place new assocs are created; return FALSE if OOM;
+// never returns FALSE if keys already exists
+BOOL CMapKeyToValue::SetAt(LPVOID pKey, UINT cbKey, LPVOID pValue)
+{
+ VDATEHEAP();
+
+ UINT nHash;
+ register CAssoc FAR* pAssoc;
+ BOOL fFound = FALSE;
+
+ LOCKTHIS;
+
+ ASSERT_VALID(this);
+
+ if ((pAssoc = GetAssocAt(pKey, cbKey, nHash)) == NULL)
+ {
+ if (!InitHashTable())
+ // out of memory
+ goto Exit;
+
+ // it doesn't exist, add a new Association
+ if ((pAssoc = NewAssoc(nHash, pKey, cbKey, pValue)) == NULL)
+ goto Exit;
+
+ // put into hash table
+ pAssoc->pNext = m_pHashTable[nHash];
+ m_pHashTable[nHash] = pAssoc;
+
+ ASSERT_VALID(this);
+ }
+ else
+ SetAssocValue(pAssoc, pValue);
+
+ fFound = TRUE;
+Exit:
+ UNLOCKTHIS;
+ return fFound;
+}
+
+
+#pragma SEG(CMapKeyToValue_SetAtHKey)
+// set existing hkey to value; return FALSE if NULL or bad key
+BOOL CMapKeyToValue::SetAtHKey(HMAPKEY hKey, LPVOID pValue)
+{
+ VDATEHEAP();
+
+ BOOL fDone = FALSE;
+ LOCKTHIS;
+ // REVIEW: would like some way to verify that hKey is valid
+ register CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+ if (pAssoc == NULL)
+ goto Exit; // not in map
+
+ ASSERT_VALID(this);
+
+ SetAssocValue(pAssoc, pValue);
+ fDone = TRUE;
+Exit:
+ UNLOCKTHIS;
+ return fDone;
+}
+
+
+#pragma SEG(CMapKeyToValue_RemoveKey)
+// remove key - return TRUE if removed
+BOOL CMapKeyToValue::RemoveKey(LPVOID pKey, UINT cbKey)
+{
+ VDATEHEAP();
+
+ BOOL fFound = FALSE;
+ UINT i;
+
+ LOCKTHIS;
+ ASSERT_VALID(this);
+
+ if (m_pHashTable == NULL)
+ goto Exit; // nothing in the table
+
+ register CAssoc FAR* FAR* ppAssocPrev;
+ if (m_lpfnHashKey)
+ i = (*m_lpfnHashKey)(pKey, cbKey) % m_nHashTableSize;
+ else
+ i = MKVDefaultHashKey(pKey, cbKey) % m_nHashTableSize;
+
+ ppAssocPrev = &m_pHashTable[i];
+
+ CAssoc FAR* pAssoc;
+ for (pAssoc = *ppAssocPrev; pAssoc != NULL; pAssoc = pAssoc->pNext)
+ {
+ if (CompareAssocKey(pAssoc, pKey, cbKey))
+ {
+ // remove it
+ *ppAssocPrev = pAssoc->pNext; // remove from list
+ FreeAssoc(pAssoc);
+ ASSERT_VALID(this);
+ fFound = TRUE;
+ break;
+ }
+ ppAssocPrev = &pAssoc->pNext;
+ }
+Exit:
+ UNLOCKTHIS;
+ return fFound;
+}
+
+
+#pragma SEG(CMapKeyToValue_RemoveHKey)
+// remove key based on pAssoc (HMAPKEY)
+BOOL CMapKeyToValue::RemoveHKey(HMAPKEY hKey)
+{
+ VDATEHEAP();
+
+ BOOL fFound = FALSE;
+
+ // REVIEW: would like some way to verify that hKey is valid
+ CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+
+ LOCKTHIS;
+ ASSERT_VALID(this);
+
+ if (m_pHashTable == NULL)
+ goto Exit; // nothing in the table
+
+ if (pAssoc == NULL || pAssoc->nHashValue >= m_nHashTableSize)
+ goto Exit; // null hkey or bad hash value
+
+ register CAssoc FAR* FAR* ppAssocPrev;
+ ppAssocPrev = &m_pHashTable[pAssoc->nHashValue];
+
+ while (*ppAssocPrev != NULL)
+ {
+ if (*ppAssocPrev == pAssoc)
+ {
+ // remove it
+ *ppAssocPrev = pAssoc->pNext; // remove from list
+ FreeAssoc(pAssoc);
+ ASSERT_VALID(this);
+ fFound = TRUE;
+ break;
+ }
+ ppAssocPrev = &(*ppAssocPrev)->pNext;
+ }
+
+Exit:
+ UNLOCKTHIS;
+ return fFound;
+}
+
+
+#pragma SEG(CMapKeyToValue_GetHKey)
+HMAPKEY CMapKeyToValue::GetHKey(LPVOID pKey, UINT cbKey) const
+{
+ VDATEHEAP();
+
+ UINT nHash;
+ HMAPKEY hKey;
+
+ LOCKTHIS;
+ ASSERT_VALID(this);
+
+ hKey = (HMAPKEY)GetAssocAt(pKey, cbKey, nHash);
+ UNLOCKTHIS;
+ return hKey;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Iterating
+
+// for fixed length keys, copies key to pKey; pcbKey can be NULL;
+// for variable length keys, copies pointer to key to pKey; sets pcbKey.
+
+#pragma SEG(CMapKeyToValue_GetNextAssoc)
+void CMapKeyToValue::GetNextAssoc(POSITION FAR* pNextPosition,
+ LPVOID pKey, UINT FAR* pcbKey, LPVOID pValue) const
+{
+ VDATEHEAP();
+
+ ASSERT_VALID(this);
+
+ Assert(m_pHashTable != NULL); // never call on empty map
+
+ register CAssoc FAR* pAssocRet = (CAssoc FAR*)*pNextPosition;
+ Assert(pAssocRet != NULL);
+
+ if (pAssocRet == (CAssoc FAR*) BEFORE_START_POSITION)
+ {
+ // find the first association
+ for (UINT nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
+ if ((pAssocRet = m_pHashTable[nBucket]) != NULL)
+ break;
+ Assert(pAssocRet != NULL); // must find something
+ }
+
+ // find next association
+ CAssoc FAR* pAssocNext;
+ if ((pAssocNext = pAssocRet->pNext) == NULL)
+ {
+ // go to next bucket
+ for (UINT nBucket = pAssocRet->nHashValue + 1;
+ nBucket < m_nHashTableSize; nBucket++)
+ if ((pAssocNext = m_pHashTable[nBucket]) != NULL)
+ break;
+ }
+
+ // fill in return data
+ *pNextPosition = (POSITION) pAssocNext;
+
+ // fill in key/pointer to key
+ LPVOID pKeyFrom;
+ UINT cbKey;
+ GetAssocKeyPtr(pAssocRet, &pKeyFrom, &cbKey);
+ if (m_cbKey == 0)
+ // variable length key; just return pointer to key itself
+ *(void FAR* FAR*)pKey = pKeyFrom;
+ else
+ _xmemcpy(pKey, pKeyFrom, cbKey);
+
+ if (pcbKey != NULL)
+ *pcbKey = cbKey;
+
+ // get value
+ GetAssocValue(pAssocRet, pValue);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+#pragma SEG(CMapKeyToValue_AssertValid)
+void CMapKeyToValue::AssertValid() const
+{
+ VDATEHEAP();
+
+#ifdef _DEBUG
+ Assert(m_cbKeyInAssoc == (m_cbKey == 0 ? sizeof(CKeyWrap) : m_cbKey));
+
+ Assert(m_nHashTableSize > 0);
+ Assert(m_nCount == 0 || m_pHashTable != NULL);
+
+ if (m_pHashTable != NULL)
+ Assert(!IsBadReadPtr(m_pHashTable, m_nHashTableSize * sizeof(CAssoc FAR*)));
+
+ if (m_lpfnHashKey)
+ Assert(!IsBadCodePtr((FARPROC)m_lpfnHashKey));
+
+ if (m_pFreeList != NULL)
+ Assert(!IsBadReadPtr(m_pFreeList, SizeAssoc()));
+
+ if (m_pBlocks != NULL)
+ Assert(!IsBadReadPtr(m_pBlocks, SizeAssoc() * m_nBlockSize));
+
+#endif //_DEBUG
+}
diff --git a/private/ole32/ole232/util/ole2util.cpp b/private/ole32/ole232/util/ole2util.cpp
new file mode 100644
index 000000000..51e0ed81a
--- /dev/null
+++ b/private/ole32/ole232/util/ole2util.cpp
@@ -0,0 +1,1105 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// ole2util.cpp
+//
+// Contents:
+// Ole internal utility routines
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 06/01/94 - AlexGo - UtQueryPictFormat now supports
+// enhanced metafiles
+// 03/18/94 - AlexGo - fixed UtGetPresStreamName (incorrect
+// string processing)
+// 01/11/94 - ChrisWe - don't reference unlocked handle in
+// UtConvertBitmapToDib
+// 01/11/94 - alexgo - added VDATEHEAP macro to every function
+// 12/07/93 - ChrisWe - removed incorrect uses of (LPOLESTR);
+// removed duplicate GetClassFromDataObj function, which
+// is the same as UtGetClassID
+// 11/30/93 - ChrisWe - continue file cleanup; don't open
+// streams in UtRemoveExtraOlePresStreams()
+// 11/28/93 - ChrisWe - file cleanup and inspection;
+// reformatted many functions
+// 11/22/93 - ChrisWe - replace overloaded ==, != with
+// IsEqualIID and IsEqualCLSID
+// 06/28/93 - SriniK - added UtGetDibExtents
+// 11/16/92 - JasonFul - created; moved contents here from util.cpp
+//
+//-----------------------------------------------------------------------------
+
+#include <le2int.h>
+#pragma SEG(ole2util)
+
+NAME_SEG(Ole2Utils)
+ASSERTDATA
+
+#define WIDTHBYTES(i) ((i+31)/32*4)
+
+#define PALETTESIZE 256 /* Number of entries in the system palette */
+
+// REVIEW, according to the spec, IDataObject::EnumFormatEtc() is only
+// required to service one dwDirection DATADIR_ value at a time. This
+// function has been asking it to do more than one at a time, and expecting
+// return of FORMATETCs that match all the requested directions. Code
+// seen in OleRegEnumFormatEtc() checks on creation, and fails if any
+// value other than plain DATADIR_GET or plain DATADIR_SET is specified
+// so this has clearly never worked for OLE1, or registration database lookups
+// since the only caller of UtIsFormatSupported has always asked for both
+// at the same time.
+#pragma SEG(UtIsFormatSupported)
+FARINTERNAL_(BOOL) UtIsFormatSupported(IDataObject FAR* lpDataObj,
+ DWORD dwDirection, CLIPFORMAT cfFormat)
+{
+ VDATEHEAP();
+
+ FORMATETC formatetc; // a place to fetch formats from the enumerator
+ IEnumFORMATETC FAR* penm; // enumerates the formats of [lpDataObj]
+ ULONG ulNumFetched; // a count of the number of formats fetched
+ HRESULT error; // the error state so far
+
+ // try to get the enumerator from the data object
+ error = lpDataObj->EnumFormatEtc(dwDirection, &penm);
+
+ if (error != NOERROR)
+ {
+ if (FAILED(error))
+ return FALSE;
+ else
+ {
+ CLSID clsid;
+
+ // Use reg db; this case is primarily for the OLE1
+ // compatibility code since it may talk to a data
+ // object from a server in the same process as
+ // the server.
+ if (UtGetClassID(lpDataObj, &clsid) != TRUE)
+ return(FALSE);
+
+ // synthesize an enumerator
+ // REVIEW, if the data object is synthesized for
+ // the OLE1 object, why doesn't that implementation
+ // go ahead and synthesize this? Why does it have
+ // to be done like this? What if it's on the clipboard
+ // and someone wants to use it?
+ if (OleRegEnumFormatEtc(clsid, dwDirection, &penm)
+ != NOERROR)
+ return FALSE;
+ Assert(penm);
+ }
+ }
+
+ // check for the format we're looking for
+ while(NOERROR == (error = penm->Next(1, &formatetc, &ulNumFetched)))
+ {
+ if ((ulNumFetched == 1) && (formatetc.cfFormat == cfFormat))
+ break;
+ }
+
+ // release the enumerator
+ penm->Release();
+
+ // if error isn't S_FALSE, we fetched an item, and broke out of the
+ // while loop above --> the format was found. Return TRUE indicating
+ // that the format is supported
+ return(error == NOERROR ? TRUE : FALSE);
+}
+
+
+#pragma SEG(UtDupPalette)
+FARINTERNAL_(HPALETTE) UtDupPalette(HPALETTE hpalette)
+{
+ VDATEHEAP();
+
+ WORD cEntries; // holds the number of entries in the palette
+ HANDLE hLogPal; // ia a handle to a new logical palette
+ LPLOGPALETTE pLogPal; // is a pointer to the new logical palette
+ HPALETTE hpaletteNew = NULL; // the new palette we will return
+
+ if (0 == GetObject(hpalette, sizeof(cEntries), &cEntries))
+ return(NULL);
+
+ if (NULL == (hLogPal = GlobalAlloc(GMEM_MOVEABLE,
+ sizeof (LOGPALETTE) +
+ cEntries * sizeof (PALETTEENTRY))))
+ return(NULL);
+
+ if (NULL == (pLogPal = (LPLOGPALETTE)GlobalLock(hLogPal)))
+ goto errRtn;
+
+ if (0 == GetPaletteEntries(hpalette, 0, cEntries,
+ pLogPal->palPalEntry))
+ goto errRtn;
+
+ pLogPal->palVersion = 0x300;
+ pLogPal->palNumEntries = cEntries;
+
+ if (NULL == (hpaletteNew = CreatePalette(pLogPal)))
+ goto errRtn;
+
+errRtn:
+ if (pLogPal)
+ GlobalUnlock(hLogPal);
+
+ if (hLogPal)
+ GlobalFree(hLogPal);
+
+ AssertSz(hpaletteNew, "Warning: UtDupPalette Failed");
+ return(hpaletteNew);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtFormatToTymed
+//
+// Synopsis: gets the right TYMED for the given rendering format
+//
+// Effects:
+//
+// Arguments: [cf] -- the clipboard format
+//
+// Requires:
+//
+// Returns: one of the TYMED enumeration
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 07-Jul-94 alexgo added EMF's
+//
+// Notes: This should only be called for formats that we can
+// render
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(UtFormatToTymed)
+FARINTERNAL_(DWORD) UtFormatToTymed(CLIPFORMAT cf)
+{
+ VDATEHEAP();
+
+ if( cf == CF_METAFILEPICT )
+ {
+ return TYMED_MFPICT;
+ }
+ else if( cf == CF_BITMAP )
+ {
+ return TYMED_GDI;
+ }
+ else if( cf == CF_DIB )
+ {
+ return TYMED_HGLOBAL;
+ }
+ else if( cf == CF_ENHMETAFILE )
+ {
+ return TYMED_ENHMF;
+ }
+ else if( cf == CF_PALETTE )
+ {
+ LEWARN(1,"Trying to render CF_PALETTE");
+ return TYMED_GDI;
+ }
+
+ LEDebugOut((DEB_WARN, "WARNING: trying to render clipformat (%lx)\n",
+ cf));
+
+ return TYMED_HGLOBAL;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtQueryPictFormat
+//
+// Synopsis: finds our "preferred" drawing formatetc from the given
+// data object
+//
+// Effects:
+//
+// Arguments: [lpSrcDataObj] -- the source data object
+// [lpforetc] -- where to stuff the preferred format
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 01-Jun-94 alexgo rewrite/now supports Enhanced Metafiles
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(UtQueryPictFormat)
+FARINTERNAL_(BOOL) UtQueryPictFormat(LPDATAOBJECT lpSrcDataObj,
+ LPFORMATETC lpforetc)
+{
+ FORMATETC foretctemp; // local copy of current values of format desc
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN UtQueryPictFormat ( %p , %p )\n",
+ NULL, lpSrcDataObj, lpforetc));
+
+ // copy format descriptor
+ foretctemp = *lpforetc;
+
+ // set values and query for our preferred formats in order of
+ // preference
+
+
+ foretctemp.cfFormat = CF_METAFILEPICT;
+ foretctemp.tymed = TYMED_MFPICT;
+ if (lpSrcDataObj->QueryGetData(&foretctemp) == NOERROR)
+ {
+ goto QuerySuccess;
+ }
+
+ foretctemp.cfFormat = CF_ENHMETAFILE;
+ foretctemp.tymed = TYMED_ENHMF;
+ if( lpSrcDataObj->QueryGetData(&foretctemp) == NOERROR )
+ {
+ goto QuerySuccess;
+ }
+ foretctemp.cfFormat = CF_DIB;
+ foretctemp.tymed = TYMED_HGLOBAL;
+ if (lpSrcDataObj->QueryGetData(&foretctemp) == NOERROR)
+ {
+ goto QuerySuccess;
+ }
+
+ foretctemp.cfFormat = CF_BITMAP;
+ foretctemp.tymed = TYMED_GDI;
+ if (lpSrcDataObj->QueryGetData(&foretctemp) == NOERROR)
+ {
+ goto QuerySuccess;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT UtQueryPictFormat ( %lu )\n",
+ NULL, FALSE));
+
+ return FALSE;
+
+QuerySuccess:
+ // data object supports this format; change passed in
+ // format to match
+
+ lpforetc->cfFormat = foretctemp.cfFormat;
+ lpforetc->tymed = foretctemp.tymed;
+
+ // return success
+
+ LEDebugOut((DEB_ITRACE, "%p OUT UtQueryPictFormat ( %lu )\n",
+ NULL, TRUE));
+
+ return(TRUE);
+}
+
+
+#pragma SEG(UtConvertDibToBitmap)
+FARINTERNAL_(HBITMAP) UtConvertDibToBitmap(HANDLE hDib)
+{
+ VDATEHEAP();
+
+ LPBITMAPINFOHEADER lpbmih;
+ HDC hdc; // the device context to create the bitmap for
+ size_t uBitsOffset; // the offset to where the image begins in the DIB
+ HBITMAP hBitmap; // the bitmap we'll return
+
+ if (!(lpbmih = (LPBITMAPINFOHEADER)GlobalLock(hDib)))
+ return(NULL);
+
+ if (!(hdc = GetDC(NULL))) // Get screen DC.
+ {
+ // REVIEW: we may have to use the target device of this
+ // cache node.
+ return(NULL);
+ }
+
+ uBitsOffset = sizeof(BITMAPINFOHEADER) +
+ (lpbmih->biClrUsed ? lpbmih->biClrUsed :
+ UtPaletteSize(lpbmih));
+
+ hBitmap = CreateDIBitmap(hdc, lpbmih, CBM_INIT,
+ ((BYTE *)lpbmih)+uBitsOffset,
+ (LPBITMAPINFO) lpbmih, DIB_RGB_COLORS);
+
+ // release the DC
+ ReleaseDC(NULL, hdc);
+
+ return hBitmap;
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtConvertBitmapToDib, internal
+//
+// Synopsis:
+// Creates a Device Independent Bitmap capturing the content of
+// the argument bitmap.
+//
+// Arguments:
+// [hBitmap] -- Handle to the bitmap to convert
+// [hpal] -- color palette for the bitmap; may be null for
+// default stock palette
+//
+// Returns:
+// Handle to the DIB. May be null if any part of the conversion
+// failed.
+//
+// Notes:
+//
+// History:
+// 11/29/93 - ChrisWe - file inspection and cleanup
+// 07/18/94 - DavePl - fixed for 16, 32, bpp bitmaps
+//
+//-----------------------------------------------------------------------------
+
+FARINTERNAL_(HANDLE) UtConvertBitmapToDib(HBITMAP hBitmap, HPALETTE hpal)
+{
+ VDATEHEAP();
+
+ HDC hScreenDC;
+ BITMAP bm; // bitmap for hBitmap
+ UINT uBits; // number of color bits for bitmap
+ size_t uBmiSize; // size of bitmap info for the DIB
+ size_t biSizeImage; // temp to hold value in the handle memory
+ HANDLE hBmi; // handle for the new DIB bitmap we'll create
+ LPBITMAPINFOHEADER lpBmi; // pointer to the actual data area for DIB
+ HANDLE hDib = NULL; // the DIB we'll return
+ BOOL fSuccess = FALSE;
+ DWORD dwCompression;
+ BOOL fDeletePalette = FALSE;
+
+ if (NULL == hBitmap)
+ {
+ return(NULL);
+ }
+
+ // if no palette provided, use the default
+
+ if (NULL == hpal)
+ {
+ // This block fixes NTBUG #13029. The problem is that on a palette
+ // device (ie a 256 color video driver), we don't get passed the palette
+ // that is used by the DDB. So, we build the palette based on what
+ // is currently selected into the system palette.
+
+ // POSTPPC:
+ //
+ // We should change the clipboard code that calls this to ask for
+ // CF_PALETTE from the IDataObject that the DDB was obtained from, that
+ // way we know we get the colors that the calling app really intended
+ HDC hDCGlobal = GetDC(NULL);
+ int iRasterCaps = GetDeviceCaps(hDCGlobal, RASTERCAPS);
+
+ ReleaseDC(NULL, hDCGlobal);
+
+ if ((iRasterCaps & RC_PALETTE))
+ {
+ // Based the following code from the win sdk MYPAL example program.
+ // this creates a palette out of the currently active palette.
+ HANDLE hLogPal = GlobalAlloc (GHND,
+ (sizeof (LOGPALETTE) +
+ (sizeof (PALETTEENTRY) * (PALETTESIZE))));
+
+ // if we are OOM, return failure now, because we aren't going
+ // to make it through the allocations later on.
+
+ if (!hLogPal)
+ return NULL;
+
+ LPLOGPALETTE pLogPal = (LPLOGPALETTE)GlobalLock (hLogPal);
+
+ // 0x300 is a magic number required by GDI
+ pLogPal->palVersion = 0x300;
+ pLogPal->palNumEntries = PALETTESIZE;
+
+ // fill in intensities for all palette entry colors
+ for (int iLoop = 0; iLoop < PALETTESIZE; iLoop++)
+ {
+ *((WORD *) (&pLogPal->palPalEntry[iLoop].peRed)) = (WORD)iLoop;
+ pLogPal->palPalEntry[iLoop].peBlue = 0;
+ pLogPal->palPalEntry[iLoop].peFlags = PC_EXPLICIT;
+ }
+
+ // create a logical color palette according the information
+ // in the LOGPALETTE structure.
+ hpal = CreatePalette ((LPLOGPALETTE) pLogPal) ;
+
+ GlobalUnlock(hLogPal);
+ GlobalFree(hLogPal);
+
+ if (!hpal)
+ return NULL;
+
+ fDeletePalette = TRUE;
+ }
+ else
+ {
+ hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
+ }
+ }
+
+ if (NULL == GetObject(hBitmap, sizeof(bm), (LPVOID)&bm))
+ {
+ return(NULL);
+ }
+
+
+ uBits = bm.bmPlanes * bm.bmBitsPixel;
+
+ // Based on the number of bits per pixel, set up the size
+ // of the color table, and the compression type as per the
+ // the following table:
+ //
+ //
+ // BPP Palette Size Compression
+ // ~~~ ~~~~~~~~~~~~ ~~~~~~~~~~~
+ // 1,2,4,8 2^BPP * sizeof(RGBQUAD) None
+ // 16, 32 3 * sizeof(DWORD) masks BI_BITFIELDS
+ // 24 0 None
+
+
+ if (16 == bm.bmBitsPixel || 32 == bm.bmBitsPixel)
+ {
+ uBmiSize = sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD);
+ dwCompression = BI_BITFIELDS;
+ }
+ else if (24 == bm.bmBitsPixel)
+ {
+ uBmiSize = sizeof(BITMAPINFOHEADER);
+ dwCompression = BI_RGB;
+ }
+ else
+ {
+ Assert( bm.bmBitsPixel == 1 ||
+ bm.bmBitsPixel == 2 ||
+ bm.bmBitsPixel == 4 ||
+ bm.bmBitsPixel == 8 );
+
+
+ // VGA and EGA are planar devices on Chicago, so uBits needs
+ // to be used when determining the size of the bitmap info +
+ // the size of the color table.
+ uBmiSize = sizeof(BITMAPINFOHEADER) +
+ (1 << uBits) * sizeof(RGBQUAD);
+ dwCompression = BI_RGB;
+ }
+
+ // Allocate enough memory to hold the BITMAPINFOHEADER
+
+ hBmi = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, (DWORD)uBmiSize);
+ if (NULL == hBmi)
+ {
+ return NULL;
+ }
+
+ lpBmi = (LPBITMAPINFOHEADER) GlobalLock(hBmi);
+ if (NULL == lpBmi)
+ {
+ GlobalFree(hBmi);
+ return NULL;
+ }
+
+ // Set up any interesting non-zero fields
+
+ lpBmi->biSize = (LONG)sizeof(BITMAPINFOHEADER);
+ lpBmi->biWidth = (LONG) bm.bmWidth;
+ lpBmi->biHeight = (LONG) bm.bmHeight;
+ lpBmi->biPlanes = 1;
+ lpBmi->biBitCount = uBits;
+ lpBmi->biCompression = dwCompression;
+
+ // Grab the screen DC and set out palette into it
+
+ hScreenDC = GetDC(NULL);
+ if (NULL == hScreenDC)
+ {
+ GlobalUnlock(hBmi);
+ goto errRtn;
+ }
+
+
+ // Call GetDIBits with a NULL lpBits parm, so that it will calculate
+ // the biSizeImage field for us
+
+ GetDIBits(hScreenDC, // DC
+ hBitmap, // Bitmap handle
+ 0, // First scan line
+ bm.bmHeight, // Number of scan lines
+ NULL, // Buffer
+ (LPBITMAPINFO)lpBmi, // BITMAPINFO
+ DIB_RGB_COLORS);
+
+ // If the driver did not fill in the biSizeImage field, make one up
+
+ if (0 == lpBmi->biSizeImage)
+ {
+ LEDebugOut((DEB_WARN, "WARNING: biSizeImage was not computed for us\n"));
+
+ lpBmi->biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * uBits) * bm.bmHeight;
+ }
+
+ // Realloc the buffer to provide space for the bits. Use a new handle so
+ // that in the failure case we do not lose the exiting handle, which we
+ // would need to clean up properly.
+
+ biSizeImage = lpBmi->biSizeImage;
+ GlobalUnlock(hBmi);
+
+ hDib = GlobalReAlloc(hBmi, (uBmiSize + biSizeImage), GMEM_MOVEABLE);
+ if (NULL == hDib)
+ {
+ goto errRtn;
+ }
+
+ // If the realloc succeeded, we can get rid of the old handle
+
+ hBmi = NULL;
+
+ // re-acquire the pointer to the handle
+
+ lpBmi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
+ if (NULL == lpBmi)
+ {
+ goto errRtn;
+ }
+
+ hpal = SelectPalette(hScreenDC, hpal, FALSE);
+ RealizePalette(hScreenDC);
+
+ // Call GetDIBits with a NON-NULL lpBits parm, and get the actual bits
+
+ if (GetDIBits(hScreenDC, // DC
+ hBitmap, // HBITMAP
+ 0, // First scan line
+ (WORD)lpBmi->biHeight, // Count of scan lines
+ ((BYTE FAR *)lpBmi)+uBmiSize, // Bitmap bits
+ (LPBITMAPINFO)lpBmi, // BITMAPINFOHEADER
+ DIB_RGB_COLORS) // Palette style
+ )
+ {
+ fSuccess = TRUE;
+ }
+
+ GlobalUnlock(hDib);
+
+errRtn:
+
+ if (hScreenDC)
+ {
+ // Select back the old palette into the screen DC
+
+ SelectPalette(hScreenDC, hpal, FALSE);
+ ReleaseDC(NULL, hScreenDC);
+ }
+
+ if (fDeletePalette)
+ {
+ DeleteObject(hpal);
+ }
+
+ // If we failed, we need to free up the header and the DIB
+ // memory
+
+ if (FALSE == fSuccess)
+ {
+ if (hBmi)
+ {
+ GlobalFree(hBmi);
+ }
+
+ if (hDib)
+ {
+ GlobalFree(hDib);
+ hDib = NULL;
+ }
+ }
+
+ return(hDib);
+}
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtPaletteSize, internal
+//
+// Synopsis:
+// Returns the size of a color table for a palette given the
+// number of bits of color desired.
+//
+// Basically, the number of color table entries is:
+//
+// 1BPP
+// 1<<1 = 2
+//
+// 4BPP
+// if pbmi->biClrUsed is not zero and is less than 16, then use pbmi->biClrUsed,
+// otherwise use 1 << 4 = 16
+//
+// 8BPP
+// if pbmi->biClrUsed is not zero and is less than 256, then use pbmi->biClrUsed,
+// otherwise use 1 << 8 = 256
+//
+// 16BPP
+// if pbmi->biCompression is BITFIELDS then there are three color entries,
+// otherwise no color entries.
+//
+// 24BPP
+// pbmi->biCompression must be BI_RGB, there is no color table.
+//
+// 32BPP
+// if pbmi->biCompression is BITFIELDS then there are three color entries,
+// otherwise no color entries.
+//
+//
+// There is never a case with a color table larger than 256 colors.
+//
+// Arguments:
+// [lpHeader] -- ptr to BITMAPINFOHEADER structure
+//
+// Returns:
+// Size in bytes of color information
+//
+// Notes:
+//
+// History:
+// 11/29/93 - ChrisWe - change bit count argument to unsigned,
+// and return value to size_t
+//
+// 07/18/94 - DavePl - Fixed for 16, 24, 32bpp DIBs
+//
+//-----------------------------------------------------------------------------
+
+
+FARINTERNAL_(size_t) UtPaletteSize(BITMAPINFOHEADER * pbmi)
+{
+DWORD dwSize;
+WORD biBitCount = pbmi->biBitCount;
+
+
+ VDATEHEAP();
+
+ // Compute size of color table information in a DIB.
+
+ if (8 >= biBitCount)
+ {
+ if (pbmi->biClrUsed && (pbmi->biClrUsed < (DWORD) (1 << biBitCount)) )
+ {
+ dwSize = pbmi->biClrUsed * sizeof(RGBQUAD);
+ }
+ else
+ {
+ Assert(0 == pbmi->biClrUsed);
+
+ dwSize = (1 << biBitCount) * sizeof(RGBQUAD);
+ }
+ }
+ else if (BI_BITFIELDS == pbmi->biCompression)
+ {
+ Assert(24 != biBitCount); // BI_BITFIELDS should never be set for 24 bit.
+ dwSize = 3 * sizeof(RGBQUAD);
+ }
+ else
+ {
+ dwSize = 0;
+ }
+
+ Assert( (dwSize < 65536) && "Palette size overflows WORD");
+
+ return dwSize;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtGetDibExtents
+//
+// Synopsis: Returns the size of the DIB in HIMETRIC units
+//
+// Effects:
+//
+// Arguments: [lpbmi] -- the BITMAPINFOHEADER for the DIB
+// [plWidth] -- OUT param for width
+// [plHeight] -- OUT param for height
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 04-Aug-94 Davepl Corrected logic
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+FARINTERNAL_(void) UtGetDibExtents(LPBITMAPINFOHEADER lpbmi,
+ LONG FAR* plWidth, LONG FAR* plHeight)
+{
+ VDATEHEAP();
+
+ #define HIMET_PER_METER 100000L // number of HIMETRIC units / meter
+
+ if (!(lpbmi->biXPelsPerMeter && lpbmi->biYPelsPerMeter))
+ {
+ HDC hdc;
+ hdc = GetDC(NULL);
+ lpbmi->biXPelsPerMeter = MulDiv(GetDeviceCaps(hdc, LOGPIXELSX),
+ 10000, 254);
+ lpbmi->biYPelsPerMeter = MulDiv(GetDeviceCaps(hdc, LOGPIXELSY),
+ 10000, 254);
+
+ ReleaseDC(NULL, hdc);
+ }
+
+ *plWidth = (lpbmi->biWidth * HIMET_PER_METER / lpbmi->biXPelsPerMeter);
+ *plHeight= (lpbmi->biHeight * HIMET_PER_METER / lpbmi->biYPelsPerMeter);
+
+ // no longer need this
+ #undef HIMET_PER_METER
+
+}
+
+
+#pragma SEG(UtGetClassID)
+FARINTERNAL_(BOOL) UtGetClassID(LPUNKNOWN lpUnk, CLSID FAR* lpClsid)
+{
+ VDATEHEAP();
+
+ LPOLEOBJECT lpOleObj; // IOleObject pointer
+ LPPERSIST lpPersist; // IPersist pointer
+
+ // try to ask it as an object
+ if (lpUnk->QueryInterface(IID_IOleObject,
+ (LPLPVOID)&lpOleObj) == NOERROR)
+ {
+ lpOleObj->GetUserClassID(lpClsid);
+ lpOleObj->Release();
+ return(TRUE);
+ }
+
+ // try to ask it as a persistent object
+ if (lpUnk->QueryInterface(IID_IPersist,
+ (LPLPVOID)&lpPersist) == NOERROR)
+ {
+ lpPersist->GetClassID(lpClsid);
+ lpPersist->Release();
+ return(TRUE);
+ }
+
+ *lpClsid = CLSID_NULL;
+ return(FALSE);
+}
+
+
+#pragma SEG(UtGetIconData)
+FARINTERNAL UtGetIconData(LPDATAOBJECT lpSrcDataObj, REFCLSID rclsid,
+ LPFORMATETC lpforetc, LPSTGMEDIUM lpstgmed)
+{
+ VDATEHEAP();
+
+ CLSID clsid = rclsid;
+
+ lpstgmed->tymed = TYMED_NULL;
+ lpstgmed->pUnkForRelease = NULL;
+ lpstgmed->hGlobal = NULL;
+
+ if (lpSrcDataObj)
+ {
+ if (lpSrcDataObj->GetData(lpforetc, lpstgmed) == NOERROR)
+ return NOERROR;
+
+ if (IsEqualCLSID(clsid, CLSID_NULL))
+ UtGetClassID(lpSrcDataObj, &clsid);
+ }
+
+ // get data from registration database
+ lpstgmed->hGlobal = OleGetIconOfClass(clsid, NULL, TRUE);
+
+ if (lpstgmed->hGlobal == NULL)
+ return ResultFromScode(E_OUTOFMEMORY);
+ else
+ lpstgmed->tymed = TYMED_MFPICT;
+
+ return NOERROR;
+}
+
+
+
+// Performs operation like COPY, MOVE, REMOVE etc.. on src, dst storages. The
+// caller can specifiy which streams to be operated upon through
+// grfAllowedStreams parameter.
+
+STDAPI UtDoStreamOperation(LPSTORAGE pstgSrc, LPSTORAGE pstgDst, int iOpCode,
+ DWORD grfAllowedStmTypes)
+{
+ VDATEHEAP();
+
+ HRESULT error; // error status so far
+ IEnumSTATSTG FAR* penumStg; // used to enumerate the storage elements
+ ULONG celtFetched; // how many storage elements were fetched
+ STATSTG statstg;
+
+ // get an enumerator over the source storage
+ if (error = pstgSrc->EnumElements(NULL, NULL, NULL, &penumStg))
+ return error;
+
+ // repeat for every storage
+ while(penumStg->Next(1, &statstg, &celtFetched) == NOERROR)
+ {
+
+ // operate on streams that we're interested in
+ if (statstg.type == STGTY_STREAM)
+ {
+ DWORD stmType;
+
+ // find the type of the stream
+ // REVIEW, we must have constants for these name
+ // prefixes!!!
+ switch (statstg.pwcsName[0])
+ {
+ case '\1':
+ stmType = STREAMTYPE_CONTROL;
+ break;
+
+ case '\2':
+ stmType = STREAMTYPE_CACHE;
+ break;
+
+ case '\3':
+ stmType = STREAMTYPE_CONTAINER;
+ break;
+
+ default:
+ stmType = (DWORD)STREAMTYPE_OTHER;
+ }
+
+
+ // check whether it should be operated upon
+ if (stmType & grfAllowedStmTypes)
+ {
+ switch(iOpCode)
+ {
+#ifdef LATER
+ case OPCODE_COPY:
+ pstgDst->DestroyElement(
+ statstg.pwcsName);
+ error = pstgSrc->MoveElementTo(
+ statstg.pwcsName,
+ pstgDst,
+ statstg.pwcsName,
+ STGMOVE_COPY);
+ break;
+
+ case OPCODE_MOVE:
+ pstgDst->DestroyElement(
+ statstg.pwcsName);
+ error = pstgSrc->MoveElementTo(
+ statstg.pwcsName,
+ pstgDst,
+ statstg.pwcsName,
+ STGMOVE_MOVE);
+ break;
+
+ case OPCODE_EXCLUDEFROMCOPY:
+ AssertSz(FALSE, "Not yet implemented");
+ break;
+
+#endif // LATER
+ case OPCODE_REMOVE:
+ error = pstgSrc->DestroyElement(
+ statstg.pwcsName);
+ break;
+
+ default:
+ AssertSz(FALSE, "Invalid opcode");
+ break;
+ }
+ }
+ }
+
+ // if the enumerator allocated a new name string, get rid of it
+ if (statstg.pwcsName)
+ PubMemFree(statstg.pwcsName);
+
+ // quit the enumeration loop if we've hit an error
+ if (error != NOERROR)
+ break;
+ }
+
+ // release the enumerator
+ penumStg->Release();
+
+ // return the error state
+ return error;
+}
+
+
+FARINTERNAL_(void) UtGetPresStreamName(LPOLESTR lpszName, int iStreamNum)
+{
+ VDATEHEAP();
+ int i; // counts down the digits of iStreamNum
+
+ // count down the last three '0' characters of OLE_PRESENTATION_STREAM
+ // the -2 backs us up to the last character (remember the NULL
+ // terminator!)
+ for(lpszName += sizeof(OLE_PRESENTATION_STREAM)/sizeof(OLECHAR) - 2,
+ i = 3; i; --lpszName, --i)
+ {
+ *lpszName = OLESTR("0123456789")[iStreamNum % 10];
+ if( iStreamNum > 0 )
+ {
+ iStreamNum /= 10;
+ }
+ }
+}
+
+
+FARINTERNAL_(void) UtRemoveExtraOlePresStreams(LPSTORAGE pstg, int iStart)
+{
+ VDATEHEAP();
+
+ HRESULT hr; // error code from stream deletion
+ OLECHAR szName[sizeof(OLE_PRESENTATION_STREAM)/sizeof(OLECHAR)];
+ // space for the stream names
+
+ // if the stream number is invalid, do nothing
+ if ((iStart < 0) || (iStart >= OLE_MAX_PRES_STREAMS))
+ return;
+
+ // create presentation stream name
+ _xstrcpy(szName, OLE_PRESENTATION_STREAM);
+ UtGetPresStreamName(szName, iStart);
+
+ // for each of these streams that exists, get rid of it
+ while((hr = pstg->DestroyElement(szName)) == NOERROR)
+ {
+ // if we've gotten to the end of the possible streams, quit
+ if (++iStart >= OLE_MAX_PRES_STREAMS)
+ break;
+
+ // Get the next presentation stream name
+ UtGetPresStreamName(szName, iStart);
+ }
+
+ // since the only reason these streams should be open, the first
+ // failure had better be that the file was not found, and not
+ // anything else (such as STG_E_ACCESSDENIED)
+ AssertSz(hr == STG_E_FILENOTFOUND,
+ "UtRemoveExtraOlePresStreams failure");
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ConvertPixelsToHIMETRIC
+//
+// Synopsis: Converts a pixel dimension to HIMETRIC units
+//
+// Effects:
+//
+// Arguments: [hdcRef] -- the reference DC
+// [ulPels] -- dimension in pixel measurement
+// [pulHIMETRIC] -- OUT param of converted HIMETRIC result
+// [tDimension] -- indicates XDIMENSION or YDIMENSION of input
+//
+// Returns: S_OK, E_FAIL
+//
+// Algorithm: screen_mm * input_pels HIMETRICS/
+// ---------------------- * / == HIMETRICS
+// screen_pels /mm
+//
+// History: dd-mmm-yy Author Comment
+// 04-Aug-94 Davepl Created
+//
+// Notes: We need to know whether the input size is in the X or
+// Y dimension, since the aspect ratio could vary
+//
+//--------------------------------------------------------------------------
+
+FARINTERNAL ConvertPixelsToHIMETRIC (HDC hdcRef,
+ ULONG lPels,
+ ULONG * pulHIMETRIC,
+ DIMENSION tDimension)
+{
+ VDATEHEAP();
+ VDATEPTROUT(pulHIMETRIC, ULONG *);
+
+ // Clear OUT parameter in case of error
+
+ *pulHIMETRIC = 0;
+
+ ULONG scrmm = 0;
+ ULONG scrpel = 0;
+
+ const ULONG HIMETRIC_PER_MM = 100;
+
+ // If we weren't given a reference DC, use the screen as a default
+
+ BOOL fLocalDC = FALSE;
+ if (NULL == hdcRef)
+ {
+ hdcRef = GetDC(NULL);
+ if (hdcRef)
+ {
+ fLocalDC = TRUE;
+ }
+ }
+
+ if (hdcRef)
+ {
+ Assert(tDimension == XDIMENSION || tDimension == YDIMENSION);
+
+ // Get the count of pixels and millimeters for the screen
+
+ if (tDimension == XDIMENSION)
+ {
+ scrmm = GetDeviceCaps(hdcRef, HORZSIZE);
+ scrpel = GetDeviceCaps(hdcRef, HORZRES);
+ }
+ else
+ {
+ scrmm = GetDeviceCaps(hdcRef, VERTSIZE);
+ scrpel = GetDeviceCaps(hdcRef, VERTRES);
+ }
+
+ // If we had to create a temporary DC, it can be released now
+
+ if (TRUE == fLocalDC)
+ {
+ ReleaseDC(NULL, hdcRef);
+ }
+ }
+
+ // If we successfully obtained the DC's size and resolution,
+ // we can compute the HIMETRIC value.
+
+ if (scrmm && scrpel)
+ {
+ *pulHIMETRIC = (scrmm * lPels * HIMETRIC_PER_MM) / scrpel;
+
+ return S_OK;
+ }
+
+ return E_FAIL;
+
+}
diff --git a/private/ole32/ole232/util/plex.cpp b/private/ole32/ole232/util/plex.cpp
new file mode 100644
index 000000000..bbdb33821
--- /dev/null
+++ b/private/ole32/ole232/util/plex.cpp
@@ -0,0 +1,53 @@
+// This is a part of the Microsoft Foundation Classes C++ library.
+// Copyright (C) 1992 Microsoft Corporation
+// All rights reserved.
+//
+// This source code is only intended as a supplement to the
+// Microsoft Foundation Classes Reference and Microsoft
+// QuickHelp documentation provided with the library.
+// See these sources for detailed information regarding the
+// Microsoft Foundation Classes product.
+
+#include <le2int.h>
+#pragma SEG(plex)
+
+#include "plex.h"
+ASSERTDATA
+
+// Collection support
+#ifdef OLE_COLL_SEG
+#pragma code_seg(OLE_COLL_SEG)
+#endif
+
+
+#pragma SEG(CPlex_Create)
+CPlex FAR* CPlex::Create(CPlex FAR* FAR& pHead, UINT nMax, UINT cbElement)
+{
+ VDATEHEAP();
+
+ Assert(nMax > 0 && cbElement > 0);
+ CPlex FAR* p = (CPlex FAR*)PrivMemAlloc(sizeof(CPlex) + nMax * cbElement);
+ if (p == NULL)
+ return NULL;
+
+ p->nMax = nMax;
+ p->nCur = 0;
+ p->pNext = pHead;
+ pHead = p; // change head (adds in reverse order for simplicity)
+ return p;
+}
+
+#pragma SEG(CPlex_FreeDataChain)
+void CPlex::FreeDataChain() // free this one and links
+{
+ VDATEHEAP();
+
+ CPlex FAR* pThis;
+ CPlex FAR* pNext;
+
+ for (pThis = this; pThis != NULL; pThis = pNext) {
+ pNext = pThis->pNext;
+ pThis->pNext = NULL; // So compiler won't do nasty optimizations
+ PrivMemFree(pThis);
+ }
+}
diff --git a/private/ole32/ole232/util/utils.cpp b/private/ole32/ole232/util/utils.cpp
new file mode 100644
index 000000000..46c7fe0ed
--- /dev/null
+++ b/private/ole32/ole232/util/utils.cpp
@@ -0,0 +1,2726 @@
+//+----------------------------------------------------------------------------
+//
+// File:
+// utils.cpp
+//
+// Contents:
+// general OLE internal utility routines
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 23-Jan-95 t-ScottH -added Dump method to CSafeRefCount and
+// CThreadCheck class
+// -added DumpCSafeRefCount API
+// 28-Jul-94 alexgo added object stabilization classes
+// 06-May-94 AlexT Add DVTARGET conversion routines
+// 25-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocations.
+// 01/11/94 - alexgo - added VDATEHEAP macros to every function
+// 12/15/93 - ChrisWe - UtDupString has to scale length by
+// sizeof(OLECHAR)
+// 12/08/93 - ChrisWe - added necessary casts to GlobalLock() calls
+// resulting from removing bogus GlobalLock() macros in
+// le2int.h
+// 11/28/93 - ChrisWe - removed unreferenced define for MAX_STR,
+// formatted UtDupGlobal, UtDupString
+// 03/02/92 - SriniK - created
+//
+//-----------------------------------------------------------------------------
+
+#include <le2int.h>
+#pragma SEG(utils)
+
+#include <memory.h>
+
+#ifdef _DEBUG
+#include "dbgdump.h"
+#endif // _DEBUG
+
+NAME_SEG(Utils)
+ASSERTDATA
+
+
+#pragma SEG(UtDupGlobal)
+FARINTERNAL_(HANDLE) UtDupGlobal(HANDLE hsrc, UINT uiFlags)
+{
+ VDATEHEAP();
+
+ HANDLE hdst = NULL; // the newly create Handle DeSTination
+ DWORD dwSize; // the size of the global
+#ifndef _MAC
+ void FAR *lpsrc; // a pointer to the source memory
+ void FAR *lpdst; // a pointer to the destination memory
+#endif
+
+ // if no source, nothing to duplicate
+ if (!hsrc)
+ return(NULL);
+
+#ifdef _MAC
+ if (!(hdst = NewHandle(dwSize = GetHandleSize(hsrc))))
+ return(NULL);
+ BlockMove(*hsrc, *hdst, dwSize);
+ return(hdst);
+#else
+ // if there's no content, do nothing
+ if (!(lpsrc = GlobalLock(hsrc)))
+ goto errRtn;
+
+ // allocate a new global
+ hdst = GlobalAlloc(uiFlags, (dwSize = GlobalSize(hsrc)));
+
+ // if the allocation failed, get out
+ if ((hdst == NULL) || ((lpdst = GlobalLock(hdst)) == NULL))
+ goto errRtn;
+
+ // copy the content
+ _xmemcpy(lpdst, lpsrc, dwSize);
+
+ // unlock the handles
+ GlobalUnlock(hsrc);
+ GlobalUnlock(hdst);
+ return(hdst);
+
+errRtn:
+ // unlock the source handle
+ GlobalUnlock(hsrc);
+
+ // if we allocated a destination handle, free it
+ if (hdst)
+ GlobalFree(hdst);
+
+ return(NULL);
+#endif // _MAC
+}
+
+
+#pragma SEG(UtDupString)
+
+// copies string using the TASK allocator; returns NULL on out of memory
+
+// often when calling UtDupString, the caller knows the string length.
+// a good speed boost would be to call UtDupPtr instead
+
+// lpvIn must be non null
+// note: we do an alloc even if dw == 0
+FARINTERNAL_(LPVOID) UtDupPtr(LPVOID lpvIn, DWORD dw)
+{
+ VDATEHEAP();
+ LPVOID lpvOut; // the newly allocated ptr
+
+ Assert(lpvIn); // internal fcn, lpvIn must be non-null
+ if ((lpvOut = PubMemAlloc(dw)) != NULL) {
+ memcpy(lpvOut, lpvIn, dw);
+ }
+
+ return lpvOut;
+}
+
+FARINTERNAL_(LPOLESTR) UtDupString(LPCOLESTR lpszIn)
+{
+ return (LPOLESTR) UtDupPtr( (LPVOID) lpszIn,
+ (_xstrlen(lpszIn)+1) * sizeof(OLECHAR) );
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtDupStringA
+//
+// Synopsis: Duplicates an ANSI string using the TASK allocator
+//
+// Effects:
+//
+// Arguments: [pszAnsi] -- the string to duplicate
+//
+// Requires:
+//
+// Returns: the newly allocated string duplicate or NULL
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 04-Jun-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+LPSTR UtDupStringA( LPCSTR pszAnsi )
+{
+ return (LPSTR) UtDupPtr( (LPVOID) pszAnsi,
+ strlen(pszAnsi) + 1 );
+}
+
+
+
+#pragma SEG(UtCopyTargetDevice)
+FARINTERNAL_(DVTARGETDEVICE FAR*) UtCopyTargetDevice(DVTARGETDEVICE FAR* ptd)
+{
+ // if nothing to copy, return
+ if (ptd == NULL)
+ return(NULL);
+
+ return (DVTARGETDEVICE FAR*) UtDupPtr((LPVOID) ptd, ptd->tdSize);
+}
+
+
+#pragma SEG(UtCopyFormatEtc)
+FARINTERNAL_(BOOL) UtCopyFormatEtc(FORMATETC FAR* pFetcIn,
+ FORMATETC FAR* pFetcCopy)
+{
+ VDATEHEAP();
+
+ // copy structures
+ *pFetcCopy = *pFetcIn;
+
+ if (pFetcIn->ptd == NULL) {
+ // all done, return true because the copy succeeded
+ return TRUE;
+ }
+
+ // create a copy of the td descriptor, which is allocated
+ pFetcCopy->ptd = UtCopyTargetDevice(pFetcIn->ptd);
+
+ // return TRUE if we copied the data if we were supposed to
+ return(pFetcCopy->ptd != NULL);
+}
+
+
+#pragma SEG(UtCompareFormatEtc)
+FARINTERNAL_(int) UtCompareFormatEtc(FORMATETC FAR* pFetcLeft,
+ FORMATETC FAR* pFetcRight)
+{
+ VDATEHEAP();
+
+ int iResult; // indicates whether the match is exact or partial
+
+ // if the clipboard formats are different, there is no match
+ if (pFetcLeft->cfFormat != pFetcRight->cfFormat)
+ return(UTCMPFETC_NEQ);
+
+ // if the target devices don't match, there is no match
+ if (!UtCompareTargetDevice(pFetcLeft->ptd, pFetcRight->ptd))
+ return(UTCMPFETC_NEQ);
+
+ // compare the aspects for the two formats
+ if (pFetcLeft->dwAspect == pFetcRight->dwAspect)
+ {
+ // the match is exact
+ iResult = UTCMPFETC_EQ;
+ }
+ else if ((pFetcLeft->dwAspect & ~pFetcRight->dwAspect) != 0)
+ {
+ // left not subset of aspects of right; not equal
+ return(UTCMPFETC_NEQ);
+ }
+ else
+ {
+ // left aspects are a subset of the right aspects
+ iResult = UTCMPFETC_PARTIAL;
+ }
+
+ // if we get here, iResult is set to one of UPCMPFETC_EQ or _PARTIAL
+
+ // compare the media for the two formats
+ if (pFetcLeft->tymed == pFetcRight->tymed)
+ {
+ // same medium flags; do not change value of iResult
+ ;
+ }
+ else if ((pFetcLeft->tymed & ~pFetcRight->tymed) != 0)
+ {
+ // left not subset of medium flags of right; not equal
+ return(UTCMPFETC_NEQ);
+ }
+ else
+ {
+ // left subset of right
+ iResult = UTCMPFETC_PARTIAL;
+ }
+
+ return(iResult);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtCompareTargetDevice
+//
+// Synopsis: Compare two DVTARGETDEVICEs
+//
+// Arguments: [ptdLeft] -- comparand
+// [ptdRight] -- comparee
+//
+// Returns: TRUE iff the two target devices are equivalent
+//
+// Algorithm:
+//
+// History: 09-May-94 AlexT Rewrote to do more than just a binary
+// compare
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#define UT_DM_COMPARISON_FIELDS (DM_ORIENTATION | \
+ DM_PAPERSIZE | \
+ DM_PAPERLENGTH | \
+ DM_PAPERWIDTH | \
+ DM_SCALE | \
+ DM_PRINTQUALITY | \
+ DM_COLOR)
+
+#pragma SEG(UtCompareTargetDevice)
+FARINTERNAL_(BOOL) UtCompareTargetDevice(DVTARGETDEVICE FAR* ptdLeft,
+ DVTARGETDEVICE FAR* ptdRight)
+{
+ LEDebugOut((DEB_ITRACE, "%p _IN UtCompareTargetDevice (%p, %p)\n",
+ NULL, ptdLeft, ptdRight));
+
+ VDATEHEAP();
+
+ BOOL bRet = FALSE; // More often than not we return FALSE
+
+ // We use a do-while(FALSE) loop so that we can break out to common
+ // return code at the end (the joys of tracing)
+ do
+ {
+ // if the addresses of the two target device descriptors are the same,
+ // then they must be the same. Note this handles the two NULL case.
+ if (ptdLeft == ptdRight)
+ {
+ bRet = TRUE;
+ break;
+ }
+
+ // if either td is NULL, can't compare them
+ if ((ptdRight == NULL) || (ptdLeft == NULL))
+ {
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+
+ // we ignore device name (My Printer vs. Your Printer doesn't matter)
+
+ // check driver name
+ if (ptdLeft->tdDriverNameOffset != 0)
+ {
+ if (ptdRight->tdDriverNameOffset == 0)
+ {
+ // Left driver exists, but no right driver
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+
+ // Both drivers exist
+ if (_xstrcmp((LPOLESTR)((BYTE*)ptdLeft +
+ ptdLeft->tdDriverNameOffset),
+ (LPOLESTR)((BYTE*)ptdRight +
+ ptdRight->tdDriverNameOffset)) != 0)
+ {
+ // Driver names don't match
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+ }
+ else if (ptdRight->tdDriverNameOffset != 0)
+ {
+ // Left driver doesn't exist, but right driver does
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+
+ // we ignore port name
+
+ if (0 == ptdLeft->tdExtDevmodeOffset)
+ {
+ if (0 == ptdRight->tdExtDevmodeOffset)
+ {
+ // Nothing left to compare
+ bRet = TRUE;
+ break;
+ }
+ else
+ {
+ // Only one Devmode
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+ }
+ else if (0 == ptdRight->tdExtDevmodeOffset)
+ {
+ // Only one Devmode exists
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+
+ // Both TDs have Devmodes
+ DEVMODEW *pdmLeft, *pdmRight;
+
+ pdmLeft = (DEVMODEW *)((BYTE*)ptdLeft +
+ ptdLeft->tdExtDevmodeOffset);
+ pdmRight = (DEVMODEW *)((BYTE*)ptdRight +
+ ptdRight->tdExtDevmodeOffset);
+
+ // Check driver version
+ if (pdmLeft->dmDriverVersion != pdmRight->dmDriverVersion)
+ {
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+
+ // For a successful match, both device mode must specify the same
+ // values for each of the following:
+ // DM_ORIENTATION, DM_PAPERSIZE, DM_PAPERLENGTH.
+ // DM_PAPERWIDTH, DM_SCALE, DM_PRINTQUALITY, DM_COLOR
+
+ if ((pdmLeft->dmFields & UT_DM_COMPARISON_FIELDS) ^
+ (pdmRight->dmFields & UT_DM_COMPARISON_FIELDS))
+ {
+ // Only one of pdmLeft and pdmRight specify at least one
+ // of the comparison fields
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+
+ if ((pdmLeft->dmFields & DM_ORIENTATION) &&
+ pdmLeft->dmOrientation != pdmRight->dmOrientation)
+ {
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+
+ if ((pdmLeft->dmFields & DM_PAPERSIZE) &&
+ pdmLeft->dmPaperSize != pdmRight->dmPaperSize)
+ {
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+
+ if ((pdmLeft->dmFields & DM_PAPERLENGTH) &&
+ pdmLeft->dmPaperLength != pdmRight->dmPaperLength)
+ {
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+
+ if ((pdmLeft->dmFields & DM_PAPERWIDTH) &&
+ pdmLeft->dmPaperWidth != pdmRight->dmPaperWidth)
+ {
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+
+ if ((pdmLeft->dmFields & DM_SCALE) &&
+ pdmLeft->dmScale != pdmRight->dmScale)
+ {
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+
+ if ((pdmLeft->dmFields & DM_PRINTQUALITY) &&
+ pdmLeft->dmPrintQuality != pdmRight->dmPrintQuality)
+ {
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+
+ if ((pdmLeft->dmFields & DM_COLOR) &&
+ pdmLeft->dmColor != pdmRight->dmColor)
+ {
+ AssertSz(bRet == FALSE, "bRet not set correctly");
+ break;
+ }
+
+ bRet = TRUE;
+ } while (FALSE);
+
+ LEDebugOut((DEB_ITRACE, "%p OUT UtCompareTargetDevice (%d)\n",
+ NULL, bRet));
+
+ return(bRet);
+}
+
+#pragma SEG(UtCopyStatData)
+FARINTERNAL_(BOOL) UtCopyStatData(STATDATA FAR* pSDIn, STATDATA FAR* pSDCopy)
+{
+ VDATEHEAP();
+
+ // copy structures
+ *pSDCopy = *pSDIn;
+
+ // create copy of target device description (which is allocated)
+ pSDCopy->formatetc.ptd = UtCopyTargetDevice(pSDIn->formatetc.ptd);
+
+ // if there is an advise sink, account for the copy/reference
+ if (pSDCopy->pAdvSink != NULL)
+ pSDCopy->pAdvSink->AddRef();
+
+ // return TRUE if the copy was done if it was required
+ return((pSDCopy->formatetc.ptd != NULL) ==
+ (pSDIn->formatetc.ptd != NULL));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtReleaseStatData
+//
+// Synopsis: nulls && releases members of the given stat data structure
+//
+// Effects:
+//
+// Arguments: pStatData
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: We copy the data first and NULL out the stat data
+// because the Release on the Advise sink could cause us
+// to be re-entered.
+//
+// History: dd-mmm-yy Author Comment
+// 20-Jul-94 alexgo made safe for OLE sytle re-entrancy
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+FARINTERNAL_(void) UtReleaseStatData(STATDATA FAR* pStatData)
+{
+ STATDATA sd;
+
+ VDATEHEAP();
+
+ sd = *pStatData;
+
+ // zero out the original before doing any work
+
+ _xmemset(pStatData, 0, sizeof(STATDATA));
+
+ // if there's a target device description, free it
+ if (sd.formatetc.ptd != NULL)
+ {
+ PubMemFree(sd.formatetc.ptd);
+ }
+
+ if( sd.pAdvSink )
+ {
+ sd.pAdvSink->Release();
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtCreateStorageOnHGlobal
+//
+// Synopsis: creates a storage on top of an HGlobal
+//
+// Effects:
+//
+// Arguments: [hGlobal] -- the memory on which to create the
+// storage
+// [fDeleteOnRelease] -- if TRUE, then delete the hglobal
+// once the storage is released.
+// [ppStg] -- where to put the storage interface
+// [ppILockBytes] -- where to put the underlying ILockBytes,
+// maybe NULL. The ILB must be released.
+
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: create an ILockBytes on HGLOBAL and then create the docfile
+// on top of the ILockBytes
+//
+// History: dd-mmm-yy Author Comment
+// 07-Apr-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT UtCreateStorageOnHGlobal( HGLOBAL hGlobal, BOOL fDeleteOnRelease,
+ IStorage **ppStg, ILockBytes **ppILockBytes )
+{
+ HRESULT hresult;
+ ILockBytes * pLockBytes;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN UtCreateStorageOnHGlobal ( %lx , %p )"
+ "\n", NULL, hGlobal, ppStg));
+
+ hresult = CreateILockBytesOnHGlobal(hGlobal, fDeleteOnRelease,
+ &pLockBytes);
+
+ if( hresult == NOERROR )
+ {
+ hresult = StgCreateDocfileOnILockBytes( pLockBytes,
+ STGM_CREATE | STGM_SALL, 0, ppStg);
+
+ // no matter what the result of StgCreate is, we want
+ // to release the LockBytes. If hresult == NOERROR, then
+ // the final release to the LockBytes will come when the
+ // created storage is released.
+ }
+
+ if( ppILockBytes )
+ {
+ *ppILockBytes = pLockBytes;
+ }
+ else if (pLockBytes)
+ {
+ // we release here so the final release of the storage
+ // will be the final release of the lockbytes
+ pLockBytes->Release();
+ }
+
+
+ LEDebugOut((DEB_ITRACE, "%p OUT UtCreateStorageOnHGlobal ( %lx ) "
+ "[ %p ]\n", NULL, hresult, *ppStg));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtGetTempFileName
+//
+// Synopsis: retrieves a temporary filename (for use in GetData, TYMED_FILE
+// and temporary docfiles)
+//
+// Effects:
+//
+// Arguments: [pszPrefix] -- prefix of the temp filename
+// [pszTempName] -- buffer that will receive the temp path.
+// must be MAX_PATH or greater.
+//
+// Requires:
+//
+// Returns: HRESULT;
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm: tries to get a file in the temp directory, failing that, in
+// the windows directory
+//
+// History: dd-mmm-yy Author Comment
+// 07-Apr-94 alexgo author
+//
+// Notes: OPTIMIZATION: The storage code has a similar peice of code
+// for generating temporary docfiles. We may want to use this
+// routine there as well.
+//
+//--------------------------------------------------------------------------
+
+HRESULT UtGetTempFileName( LPOLESTR pszPrefix, LPOLESTR pszTempName )
+{
+ HRESULT hresult = NOERROR;
+ //OLECHAR szPath[MAX_PATH + 1];
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN UtGetTempFilename ( \"%ws\" , "
+ "\"%ws\")\n", NULL, pszPrefix, pszTempName));
+
+//BUGBUG!! This doesn't compile on Chicago; fix it soon
+#ifdef LATER
+ if( !GetTempPath(MAX_PATH, szPath) )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: GetTempPath failed!\n"));
+ if( !GetWindowsDirectory(szPath, MAX_PATH) )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: GetWindowsDirectory"
+ " failed!!\n"));
+ hresult = ResultFromScode(E_FAIL);
+ goto errRtn;
+ }
+ }
+
+ if( !GetTempFileName( szPath, pszPrefix, 0, pszTempName ) )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: GetTempFileName failed!!\n"));
+ hresult = ResultFromScode(E_FAIL);
+ }
+#endif //LATER
+
+ // BUGBUG! This is just a hack for now
+ LEDebugOut((DEB_ERROR, "ERROR!: Filename support not complete!!\n"));
+ _xstrcpy(pszTempName, OLESTR("foo.bar"));
+
+//errRtn:
+
+ LEDebugOut((DEB_ITRACE, "%p OUT UtGetTempFilename ( %lx ) "
+ "[ \"%ws\" ]\n", NULL, hresult, pszTempName));
+
+ return hresult;
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Function:
+// UtHGLOBALtoStm, internal
+//
+// Synopsis:
+// Write the contents of an HGLOBAL to a stream
+//
+// Arguments:
+// [hdata] -- handle to the data to write out
+// [dwSize] -- size of the data to write out
+// [pstm] -- stream to write the data out to; on exit, the
+// stream is positioned after the written data
+//
+// Returns:
+// HRESULT
+//
+// Notes:
+//
+// History:
+// 04/10/94 - AlexGo - added call tracing, moved from convert.cpp
+// to utils.cpp, misc improvements.
+// 11/30/93 - ChrisWe - file inspection and cleanup
+//
+//-----------------------------------------------------------------------------
+
+HRESULT UtHGLOBALtoStm(HGLOBAL hGlobalSrc, DWORD dwSize, LPSTREAM pstm)
+{
+ HRESULT hresult = NOERROR;
+ void * lpdata;
+ ULONG cbWritten;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN UtHGLOBALtoStm ( %lx , %lu , %p )\n",
+ NULL, hGlobalSrc, dwSize, pstm));
+
+ lpdata = GlobalLock(hGlobalSrc);
+
+ if (lpdata)
+ {
+ hresult = pstm->Write(lpdata, dwSize, &cbWritten);
+
+ // if we didn't write enough data, then it's an error
+ // condition for us.
+
+ if( hresult == NOERROR && cbWritten != dwSize )
+ {
+ hresult = ResultFromScode(E_FAIL);
+ }
+
+ if( hresult == NOERROR )
+ {
+ // this call isn't strictly necessary, but may
+ // be useful for compacting the size of presentations
+ // stored on disk (when called by the presentation
+ // code)
+ hresult = StSetSize(pstm, 0, TRUE);
+ }
+
+ GlobalUnlock(hGlobalSrc);
+ }
+
+
+ LEDebugOut((DEB_ITRACE, "%p OUT UtHGLOBALtoStm ( %lx )\n", NULL,
+ hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtHGLOBALtoHGLOBAL, internal
+//
+// Synopsis: Copies the source HGLOBAL into the target HGLOBAL
+//
+// Effects:
+//
+// Arguments: [hGlobalSrc] -- the source HGLOBAL
+// [dwSize] -- the number of bytes to copy
+// [hGlobalTgt] -- the target HGLOBAL
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes: this function will fail if the target hglobal is not large
+// enough
+//
+//--------------------------------------------------------------------------
+
+HRESULT UtHGLOBALtoHGLOBAL( HGLOBAL hGlobalSrc, DWORD dwSize,
+ HGLOBAL hGlobalTgt)
+{
+ DWORD cbTarget;
+ void * pvSrc;
+ void * pvTgt;
+ HRESULT hresult = ResultFromScode(E_OUTOFMEMORY);
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN UtHGLOBALtoHGLOBAL ( %lx , %lu , "
+ "%lx )\n", NULL, hGlobalSrc, dwSize, hGlobalTgt));
+
+ cbTarget = GlobalSize(hGlobalTgt);
+
+ if( cbTarget == 0 || cbTarget < dwSize )
+ {
+ hresult = ResultFromScode(E_FAIL);
+ goto errRtn;
+ }
+
+ pvSrc = GlobalLock(hGlobalSrc);
+
+ if( pvSrc )
+ {
+ pvTgt = GlobalLock(hGlobalTgt);
+
+ if( pvTgt )
+ {
+ _xmemcpy( pvTgt, pvSrc, dwSize);
+
+ GlobalUnlock(hGlobalTgt);
+ hresult = NOERROR;
+ }
+
+ GlobalUnlock(hGlobalSrc);
+ }
+
+errRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT UtHGLOBALtoHGLOBAL ( %lx )\n",
+ NULL, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtHGLOBALtoStorage, internal
+//
+// Synopsis: Copies the source HGLOBAL into the target storage
+//
+// Effects:
+//
+// Arguments: [hGlobalSrc] -- the source HGLOBAL
+// [pStgTgt] -- the target storage
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes: this function will fail if the source HGLOBAL did not
+// originally have a storage layered on top of it.
+//
+//--------------------------------------------------------------------------
+
+HRESULT UtHGLOBALtoStorage( HGLOBAL hGlobalSrc, IStorage *pStgTgt)
+{
+ HRESULT hresult;
+ ILockBytes * pLockBytes = NULL;
+ IStorage * pStgSrc;
+ ULONG cRefs;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN UtHGLOBALtoStroage ( %lx , %p )"
+ "\n", NULL, hGlobalSrc, pStgTgt));
+
+ hresult = CreateILockBytesOnHGlobal(hGlobalSrc,
+ FALSE /*fDeleteOnRelease*/, &pLockBytes);
+
+ if( hresult != NOERROR )
+ {
+ goto errRtn;
+ }
+
+ // now we make sure that the hglobal really has a storage
+ // in it
+
+ if( StgIsStorageILockBytes(pLockBytes) != NOERROR )
+ {
+ hresult = ResultFromScode(E_FAIL);
+ goto errRtn;
+ }
+
+ hresult = StgOpenStorageOnILockBytes( pLockBytes, NULL,
+ STGM_SALL, NULL, 0, &pStgSrc);
+
+ if( hresult == NOERROR )
+ {
+ hresult = pStgSrc->CopyTo( 0, NULL, NULL, pStgTgt);
+
+ // no matter what the result, we want to free the
+ // source storage
+
+ pStgSrc->Release();
+ }
+
+errRtn:
+
+ if( pLockBytes )
+ {
+ cRefs = pLockBytes->Release();
+ Assert(cRefs == 0);
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT UtHGLOBALtoStorage ( %lx ) "
+ "[ %p ]\n", NULL, hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtHGLOBALtoFile, internal
+//
+// Synopsis: Copies the source HGLOBAL into the target file
+//
+// Effects:
+//
+// Arguments: [hGlobalSrc] -- the source HGLOBAL
+// [dwSize] -- the number of bytes to copy
+// [pszFileName] -- the target file
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 10-Apr-94 alexgo author
+//
+// Notes: if the file already exists, we simply append to it
+//
+//--------------------------------------------------------------------------
+
+HRESULT UtHGLOBALtoFile( HGLOBAL hGlobalSrc, DWORD dwSize,
+ LPCOLESTR pszFileName)
+{
+ HRESULT hresult;
+ HANDLE hFile;
+ void * pvSrc;
+ DWORD cbWritten;
+
+ VDATEHEAP();
+
+ LEDebugOut((DEB_ITRACE, "%p _IN UtHGLOBALtoFile ( %lx , %lu , "
+ "\"%ws\" )\n", NULL, hGlobalSrc, dwSize, pszFileName));
+
+
+ hresult = ResultFromScode(E_NOTIMPL);
+ (void)hFile;
+ (void)pvSrc;
+ (void)cbWritten;
+
+
+// this doesn't compile for chicago, BUGBUG, fix soon
+#ifdef LATER
+ pvSrc = GlobalLock(hGlobalSrc);
+
+ if( !pvSrc )
+ {
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ // open the file for append, creating if it doesn't already exist.
+
+ hFile = CreateFile( pszFileName, GENERIC_WRITE, 0, NULL,
+ OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
+
+ if( hFile )
+ {
+ if( !WriteFile( hFile, pvSrc, dwSize, &cbWritten, NULL) )
+ {
+ LEDebugOut((DEB_WARN, "WARNING: WriteFile failed!\n"));
+ hresult = HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ if( cbWritten != dwSize && hresult == NOERROR )
+ {
+ // still an error if we didn't write all the bytes
+ // we wanted
+ hresult = ResultFromScode(E_FAIL);
+ }
+
+ if( !CloseHandle(hFile) )
+ {
+ AssertSz(0, "CloseFile failed! Should not happen!");
+
+ // if there's no error yet, set the error
+ if( hresult == NOERROR )
+ {
+ hresult = HRESULT_FROM_WIN32(GetLastError());
+ }
+ }
+ }
+ else
+ {
+ LEDebugOut((DEB_WARN, "WARNING: CreateFile failed!!\n"));
+ hresult = HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ GlobalUnlock(hGlobalSrc);
+
+errRtn:
+
+#endif // LATER
+
+
+ LEDebugOut((DEB_ITRACE, "%p OUT UtHGLOBALtoFile ( %lx )\n", NULL,
+ hresult));
+
+ return hresult;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtGetDvtd16Info
+//
+// Synopsis: Fills in pdvdtInfo
+//
+// Arguments: [pdvtd16] -- pointer to ANSI DVTARGETDEVICE
+// [pdvtdInfo] -- pointer to DVDT_INFO block
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Modifies: pdvtdInfo
+//
+// Algorithm:
+//
+// History: 06-May-94 AlexT Created from DrewB's original functions
+// 10-Jul-94 AlexT Make sure DEVMODE ends up DWORD aligned
+//
+// Notes: Do we need to do any error checking on the strings?
+//
+//--------------------------------------------------------------------------
+
+// We can't use sizeof(DV_TARGETDEVICE) because MIDL keeps flipping back
+// and forth over whether to make the embedded array size 0 or size 1
+
+#define UT_DVTARGETDEVICE_SIZE (sizeof(DWORD) + sizeof(WORD) * 4)
+
+// tdSize td...Offset's
+#define DVTD_MINSIZE (sizeof(DWORD) + 4 * sizeof(WORD))
+
+extern "C" HRESULT UtGetDvtd16Info(DVTARGETDEVICE const UNALIGNED *pdvtd16,
+ PDVTDINFO pdvtdInfo)
+{
+ LEDebugOut((DEB_ITRACE, "%p _IN UtGetDvtd16Info (%p, %p)\n",
+ NULL, pdvtd16, pdvtdInfo));
+
+ DEVMODEA UNALIGNED *pdm16;
+
+ // Let's do some sanity checking on the incoming DVTARGETDEVICE
+ if (pdvtd16->tdSize < DVTD_MINSIZE)
+ {
+ LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdSize\n"));
+ return(E_INVALIDARG);
+ }
+
+ // We need at least a DVTARGETDEVICE
+ pdvtdInfo->cbConvertSize = UT_DVTARGETDEVICE_SIZE;
+
+ // Compute required size for Drv, Device, Port names
+ if (pdvtd16->tdDriverNameOffset != 0)
+ {
+ if (pdvtd16->tdDriverNameOffset > pdvtd16->tdSize ||
+ pdvtd16->tdDriverNameOffset < DVTD_MINSIZE)
+ {
+ // Offset can't be larger than size or fall within base
+ // structure
+ LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdDriverNameOffset\n"));
+ return(E_INVALIDARG);
+ }
+
+ pdvtdInfo->cchDrvName = strlen((char *)pdvtd16 +
+ pdvtd16->tdDriverNameOffset) + 1;
+
+ pdvtdInfo->cbConvertSize += pdvtdInfo->cchDrvName * sizeof(WCHAR);
+ }
+ else
+ {
+ pdvtdInfo->cchDrvName = 0;
+ }
+
+ if (pdvtd16->tdDeviceNameOffset != 0)
+ {
+ if (pdvtd16->tdDeviceNameOffset > pdvtd16->tdSize ||
+ pdvtd16->tdDeviceNameOffset < DVTD_MINSIZE)
+ {
+ // Offset can't be larger than size or fall within base
+ // structure
+ LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdDeviceNameOffset\n"));
+ return(E_INVALIDARG);
+ }
+
+ pdvtdInfo->cchDevName = strlen((char *)pdvtd16 +
+ pdvtd16->tdDeviceNameOffset) + 1;
+
+ pdvtdInfo->cbConvertSize += pdvtdInfo->cchDevName * sizeof(WCHAR);
+ }
+ else
+ {
+ pdvtdInfo->cchDevName = 0;
+ }
+
+ if (pdvtd16->tdPortNameOffset != 0)
+ {
+ if (pdvtd16->tdPortNameOffset > pdvtd16->tdSize ||
+ pdvtd16->tdPortNameOffset < DVTD_MINSIZE)
+ {
+ // Offset can't be larger than size or fall within base
+ // structure
+ LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdPortNameOffset\n"));
+ return(E_INVALIDARG);
+ }
+
+
+ pdvtdInfo->cchPortName = strlen((char *)pdvtd16 +
+ pdvtd16->tdPortNameOffset) + 1;
+
+ pdvtdInfo->cbConvertSize += pdvtdInfo->cchPortName * sizeof(WCHAR);
+ }
+ else
+ {
+ pdvtdInfo->cchPortName = 0;
+ }
+
+ if (pdvtd16->tdExtDevmodeOffset != 0)
+ {
+ if (pdvtd16->tdExtDevmodeOffset > pdvtd16->tdSize ||
+ pdvtd16->tdExtDevmodeOffset < DVTD_MINSIZE)
+ {
+ // Offset can't be larger than size or fall within base
+ // structure
+ LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdExtDevmodeOffset\n"));
+ return(E_INVALIDARG);
+ }
+
+ // The DEVMODEW structure needs to be DWORD aligned, so here we make
+ // sure cbConvertSize (which will be the beginning of DEVMODEW) is
+ // DWORD aligned
+ pdvtdInfo->cbConvertSize += (sizeof(DWORD) - 1);
+ pdvtdInfo->cbConvertSize &= ~(sizeof(DWORD) - 1);
+
+ // Now compute the space needed for the DEVMODE
+ pdm16 = (DEVMODEA *)((BYTE *)pdvtd16 + pdvtd16->tdExtDevmodeOffset);
+
+ // We start with a basic DEVMODEW
+ pdvtdInfo->cbConvertSize += sizeof(DEVMODEW);
+
+ if (pdm16->dmSize > sizeof(DEVMODEA))
+ {
+ // The input DEVMODEA is larger than a standard DEVMODEA, so
+ // add space for the extra amount
+ pdvtdInfo->cbConvertSize += pdm16->dmSize - sizeof(DEVMODEA);
+ }
+
+ // Finally we account for the extra driver data
+ pdvtdInfo->cbConvertSize += pdm16->dmDriverExtra;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT UtGetDvtd16Info (%lx) [%ld]\n",
+ NULL, S_OK, pdvtdInfo->cbConvertSize));
+
+ return(S_OK);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtConvertDvtd16toDvtd32
+//
+// Synopsis: Fills in a 32-bit DVTARGETDEVICE based on a 16-bit
+// DVTARGETDEVICE
+//
+// Arguments: [pdvtd16] -- pointer to ANSI DVTARGETDEVICE
+// [pdvtdInfo] -- pointer to DVDT_INFO block
+// [pdvtd32] -- pointer to UNICODE DVTARGETDEVICE
+//
+// Requires: pdvtdInfo must have been filled in by a previous call to
+// UtGetDvtd16Info
+//
+// pdvtd32 must be at least pdvtdInfo->cbConvertSize bytes long
+//
+// Returns: HRESULT
+//
+// Modifies: pdvtd32
+//
+// Algorithm:
+//
+// History: 06-May-94 AlexT Created from DrewB's original functions
+// 10-Jul-94 AlexT Make sure DEVMODEW is DWORD aligned
+//
+// Notes: Do we need to do any error checking on the strings?
+//
+//--------------------------------------------------------------------------
+
+extern "C" HRESULT UtConvertDvtd16toDvtd32(DVTARGETDEVICE const UNALIGNED *pdvtd16,
+ DVTDINFO const *pdvtdInfo,
+ DVTARGETDEVICE *pdvtd32)
+{
+ LEDebugOut((DEB_ITRACE, "%p _IN UtConvertDvtd16toDvtd32 (%p, %p, %p)\n",
+ NULL, pdvtd16, pdvtdInfo, pdvtd32));
+
+#if DBG==1
+ {
+ // Verify the passed in pdvtdInfo is what we expect
+ DVTDINFO dbgDvtdInfo;
+ Assert(UtGetDvtd16Info(pdvtd16, &dbgDvtdInfo) == S_OK);
+ Assert(0 == memcmp(&dbgDvtdInfo, pdvtdInfo, sizeof(DVTDINFO)));
+ }
+#endif
+
+ HRESULT hr = S_OK;
+ USHORT cbOffset;
+ int cchWritten;
+ DEVMODEA UNALIGNED *pdm16;
+ DEVMODEW *pdm32;
+ UINT nCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ memset(pdvtd32, 0, pdvtdInfo->cbConvertSize);
+
+ cbOffset = UT_DVTARGETDEVICE_SIZE;
+
+ if (pdvtdInfo->cchDrvName != 0)
+ {
+ pdvtd32->tdDriverNameOffset = cbOffset;
+ cchWritten = MultiByteToWideChar(
+ CP_ACP, 0,
+ (char *)pdvtd16+pdvtd16->tdDriverNameOffset,
+ pdvtdInfo->cchDrvName,
+ (LPOLESTR)((BYTE *)pdvtd32 +
+ pdvtd32->tdDriverNameOffset),
+ pdvtdInfo->cchDrvName);
+ if (0 == cchWritten)
+ {
+ hr = E_UNEXPECTED;
+ goto ErrRtn;
+ }
+ cbOffset += cchWritten * sizeof(WCHAR);
+ }
+
+ if (pdvtdInfo->cchDevName != 0)
+ {
+ pdvtd32->tdDeviceNameOffset = cbOffset;
+ cchWritten = MultiByteToWideChar(
+ nCodePage, 0,
+ (char *)pdvtd16 + pdvtd16->tdDeviceNameOffset,
+ pdvtdInfo->cchDevName,
+ (LPOLESTR)((BYTE *)pdvtd32 +
+ pdvtd32->tdDeviceNameOffset),
+ pdvtdInfo->cchDevName);
+
+ if (0 == cchWritten)
+ {
+ hr = E_UNEXPECTED;
+ goto ErrRtn;
+ }
+ cbOffset += cchWritten * sizeof(WCHAR);
+ }
+
+ if (pdvtdInfo->cchPortName != 0)
+ {
+ pdvtd32->tdPortNameOffset = cbOffset;
+ cchWritten = MultiByteToWideChar(
+ nCodePage, 0,
+ (char *)pdvtd16 + pdvtd16->tdPortNameOffset,
+ pdvtdInfo->cchPortName,
+ (LPOLESTR)((BYTE *)pdvtd32 +
+ pdvtd32->tdPortNameOffset),
+ pdvtdInfo->cchPortName);
+ if (0 == cchWritten)
+ {
+ hr = E_UNEXPECTED;
+ goto ErrRtn;
+ }
+
+ cbOffset += cchWritten * sizeof(WCHAR);
+ }
+
+ if (pdvtd16->tdExtDevmodeOffset != 0)
+ {
+ // Make sure DEVMODEW will be DWORD aligned
+ cbOffset += (sizeof(DWORD) - 1);
+ cbOffset &= ~(sizeof(DWORD) - 1);
+
+ pdvtd32->tdExtDevmodeOffset = cbOffset;
+ pdm32 = (DEVMODEW *)((BYTE *)pdvtd32+pdvtd32->tdExtDevmodeOffset);
+
+ pdm16 = (DEVMODEA *)((BYTE *)pdvtd16+pdvtd16->tdExtDevmodeOffset);
+
+ // The incoming DEVMODEA can have one of the following two forms:
+ //
+ // 1) 32 chars for dmDeviceName
+ // m bytes worth of fixed size data (where m <= 38)
+ // n bytes of dmDriverExtra data
+ //
+ // and dmSize will be 32+m
+ //
+ // 2) 32 chars for dmDeviceName
+ // 38 bytes worth of fixed size data
+ // 32 chars for dmFormName
+ // m additional bytes of fixed size data
+ // n bytes of dmDriverExtra data
+ //
+ // and dmSize will be 32 + 38 + 32 + m
+ //
+ // We have to be careful to translate the dmFormName string, if it
+ // exists
+
+ // First, translate the dmDeviceName
+ if (MultiByteToWideChar(nCodePage, 0, (char *)pdm16->dmDeviceName,
+ CCHDEVICENAME,
+ pdm32->dmDeviceName, CCHDEVICENAME) == 0)
+ {
+ hr = E_UNEXPECTED;
+ goto ErrRtn;
+ }
+
+
+ // Now check to see if we have a dmFormName to translate
+ if (pdm16->dmSize <= FIELD_OFFSET(DEVMODEA, dmFormName))
+ {
+ // No dmFormName, just copy the remaining m bytes
+ memcpy(&pdm32->dmSpecVersion, &pdm16->dmSpecVersion,
+ pdm16->dmSize - CCHDEVICENAME);
+ }
+ else
+ {
+ // There is a dmFormName; copy the bytes between the names first
+ memcpy(&pdm32->dmSpecVersion, &pdm16->dmSpecVersion,
+ FIELD_OFFSET(DEVMODEA, dmFormName) -
+ FIELD_OFFSET(DEVMODEA, dmSpecVersion));
+
+ // Now translate the dmFormName
+ if (MultiByteToWideChar(CP_ACP, 0, (char *)pdm16->dmFormName,
+ CCHFORMNAME,
+ pdm32->dmFormName, CCHFORMNAME) == 0)
+ {
+ hr = E_UNEXPECTED;
+ goto ErrRtn;
+ }
+
+ // Now copy the remaining m bytes
+
+ if (pdm16->dmSize > FIELD_OFFSET(DEVMODEA, dmLogPixels))
+ {
+ memcpy(&pdm32->dmLogPixels, &pdm16->dmLogPixels,
+ pdm16->dmSize - FIELD_OFFSET(DEVMODEA, dmLogPixels));
+ }
+ }
+
+ pdm32->dmSize = sizeof(DEVMODEW);
+ if (pdm16->dmSize > sizeof(DEVMODEA))
+ {
+ pdm32->dmSize += pdm16->dmSize - sizeof(DEVMODEA);
+ }
+
+ // Copy the extra driver bytes
+ memcpy(((BYTE*)pdm32) + pdm32->dmSize, ((BYTE*)pdm16) + pdm16->dmSize,
+ pdm16->dmDriverExtra);
+
+ cbOffset += pdm32->dmSize + pdm32->dmDriverExtra;
+ }
+
+ // Finally, set pdvtd32's size
+ pdvtd32->tdSize = cbOffset;
+
+
+ErrRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT UtConvertDvtd16toDvtd32 (%lx)\n",
+ NULL, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtGetDvtd32Info
+//
+// Synopsis: Fills in pdvdtInfo
+//
+// Arguments: [pdvtd32] -- pointer to ANSI DVTARGETDEVICE
+// [pdvtdInfo] -- pointer to DVDT_INFO block
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Modifies: pdvtdInfo
+//
+// Algorithm:
+//
+// History: 06-May-94 AlexT Created from DrewB's original functions
+//
+// Notes: Do we need to do any error checking on the strings?
+//
+//--------------------------------------------------------------------------
+
+extern "C" HRESULT UtGetDvtd32Info(DVTARGETDEVICE const *pdvtd32, PDVTDINFO pdvtdInfo)
+{
+ LEDebugOut((DEB_ITRACE, "%p _IN UtGetDvtd32Info (%p, %p)\n",
+ NULL, pdvtd32, pdvtdInfo));
+
+ DEVMODEW *pdm32;
+
+ // Let's do some sanity checking on the incoming DVTARGETDEVICE
+ if (pdvtd32->tdSize < DVTD_MINSIZE)
+ {
+ LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdSize\n"));
+ return(E_INVALIDARG);
+ }
+
+ pdvtdInfo->cbConvertSize = UT_DVTARGETDEVICE_SIZE;
+
+ // Compute required size for Drv, Device, Port names
+ if (pdvtd32->tdDriverNameOffset != 0)
+ {
+ if (pdvtd32->tdDriverNameOffset > pdvtd32->tdSize ||
+ pdvtd32->tdDriverNameOffset < DVTD_MINSIZE)
+ {
+ // Offset can't be larger than size or fall within base
+ // structure
+ LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdDriverNameOffset\n"));
+ return(E_INVALIDARG);
+ }
+
+ pdvtdInfo->cchDrvName = lstrlenW((WCHAR *)((BYTE *)pdvtd32 +
+ pdvtd32->tdDriverNameOffset)) + 1;
+
+ pdvtdInfo->cbConvertSize += pdvtdInfo->cchDrvName * sizeof(WCHAR);
+ }
+ else
+ {
+ pdvtdInfo->cchDrvName = 0;
+ }
+
+ if (pdvtd32->tdDeviceNameOffset != 0)
+ {
+ if (pdvtd32->tdDeviceNameOffset > pdvtd32->tdSize ||
+ pdvtd32->tdDeviceNameOffset < DVTD_MINSIZE)
+ {
+ // Offset can't be larger than size or fall within base
+ // structure
+ LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdDeviceNameOffset\n"));
+ return(E_INVALIDARG);
+ }
+
+ pdvtdInfo->cchDevName = lstrlenW((WCHAR *)((BYTE *)pdvtd32 +
+ pdvtd32->tdDeviceNameOffset)) + 1;
+
+ pdvtdInfo->cbConvertSize += pdvtdInfo->cchDevName * sizeof(WCHAR);
+ }
+ else
+ {
+ pdvtdInfo->cchDevName = 0;
+ }
+
+ if (pdvtd32->tdPortNameOffset != 0)
+ {
+ if (pdvtd32->tdPortNameOffset > pdvtd32->tdSize ||
+ pdvtd32->tdPortNameOffset < DVTD_MINSIZE)
+ {
+ // Offset can't be larger than size or fall within base
+ // structure
+ LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdPortNameOffset\n"));
+ return(E_INVALIDARG);
+ }
+
+ pdvtdInfo->cchPortName = lstrlenW((WCHAR *)((BYTE *)pdvtd32 +
+ pdvtd32->tdPortNameOffset)) + 1;
+
+ pdvtdInfo->cbConvertSize += pdvtdInfo->cchPortName * sizeof(WCHAR);
+ }
+ else
+ {
+ pdvtdInfo->cchPortName = 0;
+ }
+
+ // Now compute the space needed for the DEVMODE
+ if (pdvtd32->tdExtDevmodeOffset != 0)
+ {
+ if (pdvtd32->tdExtDevmodeOffset > pdvtd32->tdSize ||
+ pdvtd32->tdExtDevmodeOffset < DVTD_MINSIZE)
+ {
+ // Offset can't be larger than size or fall within base
+ // structure
+ LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdExtDevmodeOffset\n"));
+ return(E_INVALIDARG);
+ }
+
+ // The DEVMODEA structure needs to be DWORD aligned, so here we make
+ // sure cbConvertSize (which will be the beginning of DEVMODEA) is
+ // DWORD aligned
+ pdvtdInfo->cbConvertSize += (sizeof(DWORD) - 1);
+ pdvtdInfo->cbConvertSize &= ~(sizeof(DWORD) - 1);
+
+ pdm32 = (DEVMODEW *)((BYTE *)pdvtd32+pdvtd32->tdExtDevmodeOffset);
+
+ // We start with a basic DEVMODEA
+ pdvtdInfo->cbConvertSize += sizeof(DEVMODEA);
+
+ if (pdm32->dmSize > sizeof(DEVMODEW))
+ {
+ // The input DEVMODEW is larger than a standard DEVMODEW, so
+ // add space for the extra amount
+ pdvtdInfo->cbConvertSize += pdm32->dmSize - sizeof(DEVMODEW);
+ }
+
+ // Finally we account for the extra driver data
+ pdvtdInfo->cbConvertSize += pdm32->dmDriverExtra;
+ }
+
+ LEDebugOut((DEB_ITRACE, "%p OUT UtGetDvtd32Info (%lx) [%ld]\n",
+ NULL, S_OK, pdvtdInfo->cbConvertSize));
+
+ return(S_OK);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtConvertDvtd32toDvtd16
+//
+// Synopsis: Fills in a 32-bit DVTARGETDEVICE based on a 16-bit
+// DVTARGETDEVICE
+//
+// Arguments: [pdvtd32] -- pointer to ANSI DVTARGETDEVICE
+// [pdvtdInfo] -- pointer to DVDT_INFO block
+// [pdvtd16] -- pointer to UNICODE DVTARGETDEVICE
+//
+// Requires: pdvtdInfo must have been filled in by a previous call to
+// UtGetDvtd32Info
+//
+// pdvtd16 must be at least pdvtdInfo->cbSizeConvert bytes long
+//
+// Returns: HRESULT
+//
+// Modifies: pdvtd16
+//
+// Algorithm:
+//
+// History: 06-May-94 AlexT Created from DrewB's original functions
+//
+// Notes: Do we need to do any error checking on the strings?
+//
+// On Chicago we'll have to provide helper code to do this
+// translation
+//
+//--------------------------------------------------------------------------
+
+extern "C" HRESULT UtConvertDvtd32toDvtd16(DVTARGETDEVICE const *pdvtd32,
+ DVTDINFO const *pdvtdInfo,
+ DVTARGETDEVICE UNALIGNED *pdvtd16)
+{
+ LEDebugOut((DEB_ITRACE, "%p _IN UtConvertDvtd32toDvtd16 (%p, %p, %p)\n",
+ NULL, pdvtd32, pdvtdInfo, pdvtd16));
+
+#if DBG==1
+ {
+ // Verify the passed in pdvtdInfo is what we expect
+ DVTDINFO dbgDvtdInfo;
+ Assert(UtGetDvtd32Info(pdvtd32, &dbgDvtdInfo) == S_OK);
+ Assert(0 == memcmp(&dbgDvtdInfo, pdvtdInfo, sizeof(DVTDINFO)));
+ }
+#endif
+
+ HRESULT hr = S_OK;
+ USHORT cbOffset;
+ int cbWritten;
+ DEVMODEA UNALIGNED *pdm16;
+ DEVMODEW *pdm32;
+ UINT nCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ memset(pdvtd16, 0, pdvtdInfo->cbConvertSize);
+
+ cbOffset = UT_DVTARGETDEVICE_SIZE;
+
+ if (pdvtdInfo->cchDrvName != 0)
+ {
+ pdvtd16->tdDriverNameOffset = cbOffset;
+ cbWritten = WideCharToMultiByte(CP_ACP, 0,
+ (WCHAR *)((BYTE *)pdvtd32 +
+ pdvtd32->tdDriverNameOffset),
+ pdvtdInfo->cchDrvName,
+ (char *)pdvtd16 + pdvtd16->tdDriverNameOffset,
+ pdvtdInfo->cchDrvName * sizeof(WCHAR),
+ NULL, NULL);
+
+ if (0 == cbWritten)
+ {
+ hr = E_UNEXPECTED;
+ goto ErrRtn;
+ }
+ cbOffset += cbWritten;
+ }
+
+ if (pdvtdInfo->cchDevName != 0)
+ {
+ pdvtd16->tdDeviceNameOffset = cbOffset;
+ cbWritten = WideCharToMultiByte(
+ nCodePage, 0,
+ (WCHAR *)((BYTE *)pdvtd32 +
+ pdvtd32->tdDeviceNameOffset),
+ pdvtdInfo->cchDevName,
+ (char *)pdvtd16 + pdvtd16->tdDeviceNameOffset,
+ pdvtdInfo->cchDevName * sizeof(WCHAR),
+ NULL, NULL);
+
+ if (0 == cbWritten)
+ {
+ hr = E_UNEXPECTED;
+ goto ErrRtn;
+ }
+ cbOffset += cbWritten;
+ }
+
+ if (pdvtdInfo->cchPortName != 0)
+ {
+ pdvtd16->tdPortNameOffset = cbOffset;
+ cbWritten = WideCharToMultiByte(nCodePage, 0,
+ (WCHAR *)((BYTE *)pdvtd32 +
+ pdvtd32->tdPortNameOffset),
+ pdvtdInfo->cchPortName,
+ (char *)pdvtd16 + pdvtd16->tdPortNameOffset,
+ pdvtdInfo->cchPortName * sizeof(WCHAR),
+ NULL, NULL);
+ if (0 == cbWritten)
+ {
+ hr = E_UNEXPECTED;
+ goto ErrRtn;
+ }
+ cbOffset += cbWritten;
+ }
+
+ if (pdvtd32->tdExtDevmodeOffset != 0)
+ {
+ // Make sure DEVMODEA will be DWORD aligned
+ cbOffset += (sizeof(DWORD) - 1);
+ cbOffset &= ~(sizeof(DWORD) - 1);
+
+ pdvtd16->tdExtDevmodeOffset = cbOffset;
+ pdm16 = (DEVMODEA *)((BYTE *)pdvtd16+pdvtd16->tdExtDevmodeOffset);
+
+ pdm32 = (DEVMODEW *)((BYTE *)pdvtd32+pdvtd32->tdExtDevmodeOffset);
+
+ // The incoming DEVMODEW can have one of the following two forms:
+ //
+ // 1) 32 WCHARs for dmDeviceName
+ // m bytes worth of fixed size data (where m <= 38)
+ // n bytes of dmDriverExtra data
+ //
+ // and dmSize will be 64+m
+ //
+ // 2) 32 WCHARs for dmDeviceName
+ // 38 bytes worth of fixed size data
+ // 32 WCHARs for dmFormName
+ // m additional bytes of fixed size data
+ // n bytes of dmDriverExtra data
+ //
+ // and dmSize will be 64 + 38 + 64 + m
+ //
+ // We have to be careful to translate the dmFormName string, if it
+ // exists
+
+
+ // Need to attempt to copy the entire buffer since old UI lib does a memcmp to verify if ptd's are equal
+
+ if (WideCharToMultiByte(nCodePage, 0, pdm32->dmDeviceName,CCHDEVICENAME,
+ (char *)pdm16->dmDeviceName, CCHDEVICENAME,
+ NULL, NULL) == 0)
+ {
+
+ // in DBCS case we can run out of pdm16->dmDeviceName buffer space
+ // Current Implementation of WideCharToMultiByte copies in what fit before error
+ // but in case this behavior changes copy again up to NULL char if error out above
+
+ if (WideCharToMultiByte(nCodePage, 0, pdm32->dmDeviceName,-1,
+ (char *)pdm16->dmDeviceName, CCHDEVICENAME,
+ NULL, NULL) == 0)
+ {
+ hr = E_UNEXPECTED;
+ goto ErrRtn;
+ }
+ }
+
+ // Now check to see if we have a dmFormName to translate
+ if (pdm32->dmSize <= FIELD_OFFSET(DEVMODEW, dmFormName))
+ {
+ // No dmFormName, just copy the remaining m bytes
+ memcpy(&pdm16->dmSpecVersion, &pdm32->dmSpecVersion,
+ pdm32->dmSize - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
+ }
+ else
+ {
+ // There is a dmFormName; copy the bytes between the names first
+ memcpy(&pdm16->dmSpecVersion, &pdm32->dmSpecVersion,
+ FIELD_OFFSET(DEVMODEW, dmFormName) -
+ FIELD_OFFSET(DEVMODEW, dmSpecVersion));
+
+ // Now translate the dmFormName
+ if (WideCharToMultiByte(CP_ACP, 0,
+ pdm32->dmFormName, CCHFORMNAME,
+ (char *) pdm16->dmFormName, CCHFORMNAME,
+ NULL, NULL) == 0)
+ {
+
+ if (WideCharToMultiByte(CP_ACP, 0,
+ pdm32->dmFormName, -1,
+ (char *) pdm16->dmFormName, CCHFORMNAME,
+ NULL, NULL) == 0)
+ {
+ hr = E_UNEXPECTED;
+ goto ErrRtn;
+ }
+ }
+
+ // Now copy the remaining m bytes
+
+ if (pdm32->dmSize > FIELD_OFFSET(DEVMODEW, dmLogPixels))
+ {
+ memcpy(&pdm16->dmLogPixels, &pdm32->dmLogPixels,
+ pdm32->dmSize - FIELD_OFFSET(DEVMODEW, dmLogPixels));
+ }
+ }
+
+ pdm16->dmSize = sizeof(DEVMODEA);
+ if (pdm32->dmSize > sizeof(DEVMODEW))
+ {
+ pdm16->dmSize += pdm32->dmSize - sizeof(DEVMODEW);
+ }
+
+ // Copy the extra driver bytes
+ memcpy(((BYTE*)pdm16) + pdm16->dmSize, ((BYTE*)pdm32) + pdm32->dmSize,
+ pdm32->dmDriverExtra);
+
+ cbOffset += pdm16->dmSize + pdm16->dmDriverExtra;
+ }
+
+ // Finally, set pdvtd16's size
+ pdvtd16->tdSize = cbOffset;
+
+ErrRtn:
+ LEDebugOut((DEB_ITRACE, "%p OUT UtConvertDvtd32toDvtd16 (%lx)\n",
+ NULL, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtGetUNICODEData, PRIVATE INTERNAL
+//
+// Synopsis: Given a string length, and two pointers (one ANSI, one
+// OLESTR), returns the UNICODE version of whichever string
+// is valid.
+//
+// Effects: Memory is allocated on the caller's pointer for new OLESTR
+//
+// Arguments: [ulLength] -- length of string in CHARACTERS (not bytes)
+// (including terminator)
+// [szANSI] -- candidate ANSI string
+// [szOLESTR] -- candidate OLESTR string
+// [pstr] -- OLESTR OUT parameter
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failure
+// E_ANSITOUNICODE if ANSI cannot be converted to UNICODE
+//
+// Algorithm: If szOLESTR is available, a simple copy is performed
+// If szOLESTR is not available, szANSI is converted to UNICODE
+// and the result is copied.
+//
+// History: dd-mmm-yy Author Comment
+// 08-Mar-94 davepl Created
+//
+// Notes: Only one of the two input strings (ANSI or UNICODE) should
+// be set on entry.
+//
+//--------------------------------------------------------------------------
+
+INTERNAL UtGetUNICODEData
+ ( ULONG ulLength,
+ LPSTR szANSI,
+ LPOLESTR szOLESTR,
+ LPOLESTR * pstr )
+{
+ VDATEHEAP();
+
+ // This fn is only called when one of the input strings
+ // has valid data... assert the impossible.
+
+ Win4Assert(pstr); // must have an out string
+ Win4Assert(ulLength); // must have a non-zero length
+ Win4Assert(szANSI || szOLESTR); // must have at least one source string
+
+ // If neither the ANSI nor the OLESTR version has data,
+ // there is nothing to return.
+
+#if 0
+// This is no better than what was there!!!
+ *pstr = NULL;
+ if (szOLESTR) {
+ *pstr = (LPOLESTR) UtDupPtr(szOLESTR, ulLength * sizeof(OLECHAR));
+ }
+ else if (szANSI) {
+ if (FALSE == MultiByteToWideChar(CP_ACP, // Code page ANSI
+ 0, // Flags (none)
+ szANSI, // Source ANSI str
+ ulLength, // length of string
+ *pstr, // Dest UNICODE buffer
+ ulLength * sizeof(OLECHAR) )) // size of UNICODE buffer
+ {
+ PubMemFree(*pstr);
+ *pstr = NULL;
+ return ResultFromScode(E_UNSPEC);
+ }
+
+ }
+
+ if (NULL == *pstr)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+#else
+
+ if (!(szANSI || szOLESTR))
+ {
+ *pstr = NULL;
+ }
+
+ // Allocate memory for the UNICODE return string
+
+ *pstr = (LPOLESTR) PubMemAlloc(ulLength * sizeof(OLECHAR));
+ if (NULL == *pstr)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // Trivial case: we already have UNICODE, just copy it
+ if (szOLESTR)
+ {
+ _xstrcpy(*pstr, szOLESTR);
+ return(NOERROR);
+ }
+
+ // Otherwise, we have to convert the ANSI string to UNICODE
+ // and return that.
+
+ else
+ {
+ if (FALSE == MultiByteToWideChar(CP_ACP, // Code page ANSI
+ 0, // Flags (none)
+ szANSI, // Source ANSI str
+ ulLength, // length of string
+ *pstr, // Dest UNICODE buffer
+ ulLength * sizeof(OLECHAR) )) // size of UNICODE buffer
+ {
+ PubMemFree(*pstr);
+ *pstr = NULL;
+ return ResultFromScode(E_UNSPEC);
+ }
+ }
+ return NOERROR;
+#endif
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: UtPutUNICODEData, PRIVATE INTERNAL
+//
+// Synopsis: Given an OLESTR and two possible buffer pointer, one ANSI
+// and the other OLESTR, this fn tries to convert the string
+// down to ANSI. If it succeeds, it allocates memory on the
+// ANSI ptr for the result. If it fails, it allocates memory
+// on the UNICODE ptr and copies the input string over. The
+// length of the final result (ANSI or UNICODE) is returned
+// in dwResultLen.
+//
+// Arguments: [ulLength] -- input length of OLESTR str
+// NB!!!! this value must include the
+// null terminator character.
+// [str] -- the OLESTR to store
+// [pszANSI] -- candidate ANSI str ptr
+// [pszOLESTR] -- candidate OLESTR str ptr. May be NULL,
+// in which case no copy is made of the
+// original string if the ANSI conversion
+// fails.
+// [pdwResultLen] -- where to store the length of result. This
+// length includes the terminating NULL.
+// Length is in CHARACTERS.
+//
+// Returns: NOERROR on success
+// E_OUTOFMEMORY on allocation failure
+// E_FAIL can't convert ANSI string and no
+// pszOLESTR is NULL
+//
+// History: dd-mmm-yy Author Comment
+// 10-Jun-94 alexgo allow pszOLESTR to be NULL
+// 08-Mar-94 davepl Created
+//
+//--------------------------------------------------------------------------
+
+// this function is poorly coded. But, it looks like it only gets called when a 1.0
+// clip format is needed. That is not very often!
+
+INTERNAL UtPutUNICODEData
+ ( ULONG ulLength,
+ LPOLESTR str,
+ LPSTR * pszANSI,
+ LPOLESTR * pszOLESTR,
+ DWORD * pdwResultLen )
+{
+ VDATEHEAP();
+
+ Win4Assert(pszANSI);
+ Win4Assert(str);
+ Win4Assert(pdwResultLen);
+ Win4Assert(ulLength);
+
+ // Free any strings currently attached to these pointers; if we wind
+ // up setting one here, we can't leave the other valid.
+
+ if (*pszANSI)
+ {
+ PubMemFree(*pszANSI);
+ *pszANSI = NULL;
+ }
+ if (pszOLESTR && *pszOLESTR)
+ {
+ PubMemFree(*pszOLESTR);
+ *pszOLESTR = NULL;
+ }
+
+ // Create a working buffer for UNICODE->ANSI conversion
+ LPSTR szANSITEMP = (LPSTR) PubMemAlloc((ulLength+1) * 2);
+ if (NULL == szANSITEMP)
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // Try to convert the UNICODE down to ANSI. If it succeeds,
+ // we just copy the result to the ANSI dest. If it fails,
+ // we copy the UNICODE version direct to the UNICODE dest.
+
+ LPCSTR pDefault = "?";
+ BOOL fUseDef = 0;
+
+ if (FALSE == WideCharToMultiByte (CP_ACP,
+ 0,
+ str,
+ ulLength,
+ szANSITEMP,
+ (ulLength + 1) * 2,
+ pDefault,
+ &fUseDef) || fUseDef )
+ {
+ // UNICODE->ANSI failed!
+
+ // Won't be needing the ANSI buffer anymore...
+ PubMemFree(szANSITEMP);
+
+ if( pszOLESTR )
+ {
+ *pszANSI = NULL;
+ *pszOLESTR = (LPOLESTR) PubMemAlloc((ulLength + 1) * sizeof(OLECHAR));
+ if (NULL == *pszOLESTR)
+ {
+ *pdwResultLen = 0;
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+ // Move the UNICODE source to UNICODE dest
+ _xstrcpy(*pszOLESTR, str);
+ *pdwResultLen = _xstrlen(str) + 1;
+
+ // That's it... return success
+ return(NOERROR);
+ }
+ else
+ {
+ return ResultFromScode(E_FAIL);
+ }
+ }
+
+ // This code path is taken when the conversion to ANSI was
+ // successful. We copy the ANSI result to the ANSI dest.
+
+ if( pszOLESTR )
+ {
+ *pszOLESTR = NULL;
+ }
+
+ *pdwResultLen = strlen(szANSITEMP) + 1;
+ *pszANSI = (LPSTR) PubMemAlloc(*pdwResultLen);
+ if (NULL == *pszANSI)
+ {
+ *pdwResultLen = 0;
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+ strcpy(*pszANSI, szANSITEMP);
+
+ PubMemFree(szANSITEMP);
+
+ return(NOERROR);
+}
+
+//
+// Object Stabilization classes
+//
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeRefCount::CSafeRefCount
+//
+// Synopsis: constructor for the safe ref count class
+//
+// Effects:
+//
+// Arguments: none
+//
+// Requires:
+//
+// Returns: none
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 28-Jul-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CSafeRefCount::CSafeRefCount()
+{
+ RefDebugOut((DEB_TRACE, "%p _IN CSafeRefCount::CSafeRefCount ( )\n",
+ this));
+
+ m_cRefs = 0;
+ m_cNest = 0;
+ m_fInDelete = FALSE;
+
+ RefDebugOut((DEB_TRACE, "%p OUT CSafeRefCount::CSafeRefcount ( )\n",
+ this));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeRefCount::~CSafeRefCount (virtual)
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 28-Jul-94 alexgo author
+//
+// Notes: this fcn MUST be in retail build even though it does nothing
+// it is needed to trigger derived class's virtual destructors
+//
+//--------------------------------------------------------------------------
+
+//#ifdef _DEBUG
+CSafeRefCount::~CSafeRefCount()
+{
+ Assert(m_cRefs == 0 && m_cNest == 0 && m_fInDelete == TRUE);
+}
+//#endif
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeRefCount::SafeAddRef
+//
+// Synopsis: increments the reference count on the object
+//
+// Effects:
+//
+// Arguments: none
+//
+// Requires:
+//
+// Returns: ULONG -- the reference count after the increment
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: increments the reference count.
+//
+// History: dd-mmm-yy Author Comment
+// 28-Jul-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+ULONG CSafeRefCount::SafeAddRef()
+{
+ RefDebugOut((DEB_TRACE, "%p _IN CSafeRefCount::SafeAddRef ( )\n",
+ this));
+
+ m_cRefs++;
+
+ //AssertSz(m_fInDelete == FALSE, "AddRef called on deleted object!");
+
+ // this *could* be really bad. If we are deleting the object,
+ // it means that during the destructor, somebody made an outgoing
+ // call eventually ended up with another addref to ourselves
+ // (even though all pointers to us had been 'Released').
+ //
+ // this is usually caused by code like the following:
+ // m_pFoo->Release();
+ // m_pFoo = NULL;
+ //
+ // If the the Release may cause Foo to be deleted, which may cause
+ // the object to get re-entered during Foo's destructor. However,
+ // 'this' object has not yet set m_pFoo to NULL, so it may
+ // try to continue to use m_pFoo.
+ //
+ // However, the May '94 aggregation rules REQUIRE this behaviour
+ // In your destructor, you have to addref the outer unknown before
+ // releasing cached interface pointers on your aggregatee. We
+ // can't put an assert here because we do this all the time now.
+ //
+ // REVIEW32: we may want to try to figure out a way to distinguish
+ // 'safe' uses of AddRef-after-zero (like the aggregation case)
+ // as opposed to dangerous cases (noted above).
+
+ RefDebugOut((DEB_TRACE, "%p OUT CSafeRefCount::SafeAddRef ( %lu )\n",
+ this, m_cRefs));
+
+ return m_cRefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeRefCount::SafeRelease
+//
+// Synopsis: decrements the reference count on the object
+//
+// Effects: May delete the object!
+//
+// Arguments:
+//
+// Requires:
+//
+// Returns: ULONG -- the reference count after decrement
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: decrements the reference count. If the reference count
+// is zero AND the nest count is zero AND we are not currently
+// trying to delete our object, then it is safe to delete.
+//
+// History: dd-mmm-yy Author Comment
+// 28-Jul-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+ULONG CSafeRefCount::SafeRelease()
+{
+ ULONG cRefs;
+
+ RefDebugOut((DEB_TRACE, "%p _IN CSafeRefCount::SafeRelease ( )\n",
+ this));
+
+ if( m_cRefs > 0 )
+ {
+ cRefs = --m_cRefs;
+
+ if( m_cRefs == 0 && m_cNest == 0 && m_fInDelete == FALSE )
+ {
+ RefDebugOut((DEB_TRACE,
+ "DELETING CSafeRefCount %p\n", this));
+
+ m_fInDelete = TRUE;
+ delete this;
+ }
+ }
+ else
+ {
+ // somebody is releasing a non-addrefed pointer!!
+ AssertSz(0, "Release called on a non-addref'ed pointer!\n");
+
+ cRefs = 0;
+ }
+
+ RefDebugOut((DEB_TRACE, "%p OUT CSafeRefCount::SafeRelease ( %lu )\n",
+ this, cRefs));
+
+ return cRefs;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeRefCount::IncrementNestCount
+//
+// Synopsis: increments the nesting count of the object
+//
+// Effects:
+//
+// Arguments: none
+//
+// Requires:
+//
+// Returns: ULONG; the nesting count after increment
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 28-Jul-94 alexgo author
+//
+// Notes: The nesting count is the count of how many times an
+// an object has been re-entered. For example, suppose
+// somebody calls pFoo->Bar1(), which makes some calls that
+// eventually call pFoo->Bar2();. On entrace to Bar2, the
+// nest count of the object should be 2 (since the invocation
+// of Bar1 is still on the stack above us).
+//
+// It is important to keep track of the nest count so we do
+// not accidentally delete ourselves during a nested invocation.
+// If we did, then when the stack unwinds to the original
+// top level call, it could try to access a non-existent member
+// variable and crash.
+//
+//--------------------------------------------------------------------------
+
+ULONG CSafeRefCount::IncrementNestCount()
+{
+ RefDebugOut((DEB_TRACE, "%p _IN CSafeRefCount::IncrementNestCount "
+ "( )\n", this));
+
+#if DBG == 1
+ if( m_fInDelete )
+ {
+ RefDebugOut((DEB_IWARN, "WARNING: CSafeRefCount, object %p "
+ "re-entered during delete!\n", this));
+ }
+#endif
+
+ m_cNest++;
+
+ RefDebugOut((DEB_TRACE, "%p OUT CSafeRefCount::IncrementNestCount "
+ "( %lu )\n", this, m_cNest));
+
+ return m_cNest;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeRefCount::DecrementNestCount
+//
+// Synopsis: decrements the nesting count and deletes the object
+// (if necessary)
+//
+// Effects: may delete 'this' object!
+//
+// Arguments: none
+//
+// Requires:
+//
+// Returns: ULONG, the nesting count after decrement
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: decrements the nesting count. If the nesting count is zero
+// AND the reference count is zero AND we are not currently
+// trying to delete ourselves, then delete 'this' object
+//
+// History: dd-mmm-yy Author Comment
+// 28-Jul-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+ULONG CSafeRefCount::DecrementNestCount()
+{
+ ULONG cNest;
+
+ RefDebugOut((DEB_TRACE, "%p _IN CSafeRefCount::DecrementNestCount "
+ "( )\n", this));
+
+ if( m_cNest > 0 )
+ {
+ cNest = --m_cNest;
+
+ if( m_cRefs == 0 && m_cNest == 0 && m_fInDelete == FALSE )
+ {
+ RefDebugOut((DEB_TRACE,
+ "DELETING CSafeRefCount %p\n", this));
+
+ m_fInDelete = TRUE;
+ delete this;
+ }
+ }
+ else
+ {
+ // somebody forget to increment the nest count!!
+ AssertSz(0, "Unbalanced nest count!!");
+
+ cNest = 0;
+ }
+
+ RefDebugOut((DEB_TRACE, "%p OUT CSafeRefCount::DecrementNestCount "
+ "( %lu )\n", this, cNest));
+
+ return cNest;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeRefCount::IsZombie
+//
+// Synopsis: determines whether or not the object is in a zombie state
+// (i.e. all references gone, but we are still on the stack
+// somewhere).
+//
+// Effects:
+//
+// Arguments: none
+//
+// Requires:
+//
+// Returns: TRUE if in a zombie state
+// FALSE otherwise
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm: If we are in the middle of a delete, or if the ref count
+// is zero and the nest count is greater than zero, then we
+// are a zombie
+//
+// History: dd-mmm-yy Author Comment
+// 28-Jul-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+BOOL CSafeRefCount::IsZombie()
+{
+ BOOL fIsZombie;
+
+ RefDebugOut((DEB_TRACE, "%p _IN CSafeRefCount::IsZombie ( )\n",
+ this));
+
+ if( (m_cRefs == 0 && m_cNest > 0) || m_fInDelete == TRUE )
+ {
+ fIsZombie = TRUE;
+ }
+ else
+ {
+ fIsZombie = FALSE;
+ }
+
+ RefDebugOut((DEB_TRACE, "%p OUT CSafeRefCount::IsZombie ( %d )\n",
+ this, fIsZombie));
+
+ return fIsZombie;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CSafeRefCount::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppsz] - argument
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 20-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+#ifdef _DEBUG
+
+HRESULT CSafeRefCount::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump;
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "References = " << m_cRefs << endl;
+ dstrDump << pszPrefix << "Nesting level = " << m_cNest << endl;
+ dstrDump << pszPrefix << "InDelete = ";
+ if (m_fInDelete == TRUE)
+ {
+ dstrDump << "TRUE" << endl;
+ }
+ else
+ {
+ dstrDump << "FALSE" << endl;
+ }
+
+ // clean up and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif //_DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCSafeRefCount, public (_DEBUG only)
+//
+// Synopsis: calls the CSafeRefCount::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pSRC] - pointer to CSafeRefCount
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 20-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCSafeRefCount(CSafeRefCount *pSRC, ULONG ulFlag, int nIndentLevel)
+{
+ char *pszDump;
+ HRESULT hresult;
+
+ if (pSRC == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pSRC->Dump( &pszDump, ulFlag, nIndentLevel);
+
+ if (hresult!=NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Member: CThreadCheck::VerifyThreadId
+//
+// Synopsis: makes sure that the calling thread is the same as the thread
+// the object was created on if the threading model is *not*
+// free threading.
+//
+// Effects:
+//
+// Arguments: none
+//
+// Requires:
+//
+// Returns: TRUE/FALSE
+//
+// Signals:
+//
+// Modifies:
+//
+// Derivation:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 21-Nov-94 alexgo author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+BOOL CThreadCheck::VerifyThreadId( void )
+{
+ if( m_tid == GetCurrentThreadId() )
+ {
+ return TRUE;
+ }
+ else
+ {
+ LEDebugOut((DEB_ERROR, "ERROR!: Called on thread %lx, should be"
+ " %lx \n", GetCurrentThreadId(), m_tid));
+ return FALSE;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CThreadCheck::Dump, public (_DEBUG only)
+//
+// Synopsis: return a string containing the contents of the data members
+//
+// Effects:
+//
+// Arguments: [ppszDump] - an out pointer to a null terminated character array
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: HRESULT
+//
+// Signals:
+//
+// Modifies: [ppszDump] - argument
+//
+// Derivation:
+//
+// Algorithm: use dbgstream to create a string containing information on the
+// content of data structures
+//
+// History: dd-mmm-yy Author Comment
+// 20-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+#ifdef _DEBUG
+
+HRESULT CThreadCheck::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
+{
+ int i;
+ char *pszPrefix;
+ dbgstream dstrPrefix;
+ dbgstream dstrDump;
+
+ // determine prefix of newlines
+ if ( ulFlag & DEB_VERBOSE )
+ {
+ dstrPrefix << this << " _VB ";
+ }
+
+ // determine indentation prefix for all newlines
+ for (i = 0; i < nIndentLevel; i++)
+ {
+ dstrPrefix << DUMPTAB;
+ }
+
+ pszPrefix = dstrPrefix.str();
+
+ // put data members in stream
+ dstrDump << pszPrefix << "Thread ID = " << m_tid << endl;
+
+ // clean up and provide pointer to character array
+ *ppszDump = dstrDump.str();
+
+ if (*ppszDump == NULL)
+ {
+ *ppszDump = UtDupStringA(szDumpErrorMessage);
+ }
+
+ CoTaskMemFree(pszPrefix);
+
+ return NOERROR;
+}
+
+#endif //_DEBUG
+
+//+-------------------------------------------------------------------------
+//
+// Function: DumpCThreadCheck, public (_DEBUG only)
+//
+// Synopsis: calls the CThreadCheck::Dump method, takes care of errors and
+// returns the zero terminated string
+//
+// Effects:
+//
+// Arguments: [pTC] - pointer to CThreadCheck
+// [ulFlag] - flag determining prefix of all newlines of the
+// out character array (default is 0 - no prefix)
+// [nIndentLevel] - will add a indent prefix after the other prefix
+// for ALL newlines (including those with no prefix)
+//
+// Requires:
+//
+// Returns: character array of structure dump or error (null terminated)
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 20-Jan-95 t-ScottH author
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef _DEBUG
+
+char *DumpCThreadCheck(CThreadCheck *pTC, ULONG ulFlag, int nIndentLevel)
+{
+ char *pszDump;
+ HRESULT hresult;
+
+ if (pTC == NULL)
+ {
+ return UtDupStringA(szDumpBadPtr);
+ }
+
+ hresult = pTC->Dump( &pszDump, ulFlag, nIndentLevel);
+
+ if (hresult != NOERROR)
+ {
+ CoTaskMemFree(pszDump);
+
+ return DumpHRESULT(hresult);
+ }
+
+ return pszDump;
+}
+
+#endif // _DEBUG
diff --git a/private/ole32/ole232/util/utstream.cpp b/private/ole32/ole232/util/utstream.cpp
new file mode 100644
index 000000000..155278c89
--- /dev/null
+++ b/private/ole32/ole232/util/utstream.cpp
@@ -0,0 +1,986 @@
+
+//+----------------------------------------------------------------------------
+//
+// File:
+// utstream.cpp
+//
+// Contents:
+// Ole stream utilities
+//
+// Classes:
+//
+// Functions:
+//
+// History:
+// 10-May-94 KevinRo Added ansi versions of StringStream stuff
+// 25-Jan-94 alexgo first pass at converting to Cairo-style
+// memory allocations.
+// 01/11/94 - alexgo - added VDATEHEAP macros to every function
+// 12/07/93 - ChrisWe - file inspection and cleanup; fixed
+// String reading and writing to cope with OLESTR, and
+// with differing alignment requirements
+// 06/23/93 - SriniK - moved ReadStringStream(),
+// WriteStringStream(), and OpenOrCreateStream() here
+// from api.cpp and ole2.cpp
+// 03/14/92 - SriniK - created
+//
+//-----------------------------------------------------------------------------
+
+#include <le2int.h>
+#pragma SEG(utstream)
+
+#include <reterr.h>
+#include <limits.h>
+
+NAME_SEG(UtStream)
+ASSERTDATA
+
+// this constant is used to size string buffers when we attempt to write out
+// a string and its length in one write call
+#define UTSTRINGBUF_SIZE 100
+
+// REVIEW, I thought that OpenStream already had an option to do this. If
+// so, this function shouldn't be used in our code. But we can't remove it
+// because it is exported to the outside.
+// this is exported to the outside
+#pragma SEG(OpenOrCreateStream)
+STDAPI OpenOrCreateStream(IStorage FAR * pstg, LPCOLESTR pwcsName,
+ IStream FAR* FAR* ppstm)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+
+ error = pstg->CreateStream(pwcsName, STGM_SALL | STGM_FAILIFTHERE,
+ 0, 0, ppstm);
+ if (GetScode(error) == STG_E_FILEALREADYEXISTS)
+ error = pstg->OpenStream(pwcsName, NULL, STGM_SALL, 0, ppstm);
+
+ return(error);
+}
+
+// returns S_OK when string read and allocated (even if zero length)
+STDAPI ReadStringStream(CStmBufRead & StmRead, LPOLESTR FAR * ppsz)
+{
+ VDATEHEAP();
+
+ ULONG cb; // the length of the string in *bytes* (NOT CHARACTERS)
+ HRESULT hresult;
+
+ // initialize the the string pointer for error returns
+ *ppsz = NULL;
+
+ if ((hresult = StmRead.Read((void FAR *)&cb, sizeof(ULONG))) != NOERROR)
+ return hresult;
+
+ // is string empty?
+ if (cb == 0)
+ return(NOERROR);
+
+ // allocate memory to hold the string
+ if (!(*ppsz = (LPOLESTR)PubMemAlloc(cb)))
+ return(ReportResult(0, E_OUTOFMEMORY, 0, 0));
+
+ // read the string; this includes a trailing NULL
+ if ((hresult = StmRead.Read((void FAR *)(*ppsz), cb)) != NOERROR)
+ goto errRtn;
+
+ return(NOERROR);
+
+errRtn:
+ // delete the string, and return without one
+ PubMemFree(*ppsz);
+ *ppsz = NULL;
+ return(hresult);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReadStringStreamA
+//
+// Synopsis: Read a ANSI stream from the stream
+//
+// Effects:
+//
+// Arguments: [pstm] -- Stream to read from
+// [ppsz] -- Output pointer
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+// 2-20-95 KentCe Converted to buffer stream reads.
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI ReadStringStreamA(CStmBufRead & StmRead, LPSTR FAR * ppsz)
+{
+ VDATEHEAP();
+
+ ULONG cb; // the length of the string in *bytes* (NOT CHARACTERS)
+ HRESULT hresult;
+
+ // initialize the the string pointer for error returns
+ *ppsz = NULL;
+
+ if ((hresult = StmRead.Read((void FAR *)&cb, sizeof(ULONG))) != NOERROR)
+ return hresult;
+
+ // is string empty?
+ if (cb == 0)
+ return(NOERROR);
+
+ // allocate memory to hold the string
+ if (!(*ppsz = (LPSTR)PubMemAlloc(cb)))
+ return(ReportResult(0, E_OUTOFMEMORY, 0, 0));
+
+ // read the string; this includes a trailing NULL
+ if ((hresult = StmRead.Read((void FAR *)(*ppsz), cb)) != NOERROR)
+ goto errRtn;
+
+ return(NOERROR);
+
+errRtn:
+ // delete the string, and return without one
+ PubMemFree(*ppsz);
+ *ppsz = NULL;
+ return(hresult);
+}
+
+
+// this is exported to the outside
+STDAPI WriteStringStream(CStmBufWrite & StmWrite, LPCOLESTR psz)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ ULONG cb; // the count of bytes (NOT CHARACTERS) to write to the stream
+
+ // if the string pointer is NULL, use zero length
+ if (!psz)
+ cb = 0;
+ else
+ {
+ // count is length of string, plus terminating null
+ cb = (1 + _xstrlen(psz))*sizeof(OLECHAR);
+
+ // if possible, do a single write instead of two
+
+ if (cb <= UTSTRINGBUF_SIZE)
+ {
+ BYTE bBuf[sizeof(ULONG)+
+ UTSTRINGBUF_SIZE*sizeof(OLECHAR)];
+ // buffer for count and string
+
+ // we have to use _xmemcpy to copy the length into
+ // the buffer to avoid potential boundary faults,
+ // since bBuf might not be aligned strictly enough
+ // to do *((ULONG FAR *)bBuf) = cb;
+ _xmemcpy((void FAR *)bBuf, (const void FAR *)&cb,
+ sizeof(cb));
+ _xmemcpy((void FAR *)(bBuf+sizeof(cb)),
+ (const void FAR *)psz, cb);
+
+ // write contents of buffer all at once
+ return( StmWrite.Write((VOID FAR *)bBuf,
+ cb+sizeof(ULONG)));
+ }
+ }
+
+ // if we got here, our buffer isn't large enough, so we do two writes
+ // first, write the length
+ if (error = StmWrite.Write((VOID FAR *)&cb, sizeof(ULONG)))
+ return error;
+
+ // are we are done writing the string?
+ if (psz == NULL)
+ return NOERROR;
+
+ // write the string
+ return(StmWrite.Write((VOID FAR *)psz, cb));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteStringStreamA
+//
+// Synopsis: Writes an ANSI string to a stream in a length prefixed format.
+//
+// Effects:
+//
+// Arguments: [pstm] -- Stream
+// [psz] -- Ansi string to write
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-12-94 kevinro Created
+// 2-20-95 KentCe Converted to buffer stream writes.
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+FARINTERNAL_(HRESULT) WriteStringStreamA(CStmBufWrite & StmWrite, LPCSTR psz)
+{
+ VDATEHEAP();
+
+ HRESULT error;
+ ULONG cb; // the count of bytes (NOT CHARACTERS) to write to the stream
+
+ // if the string pointer is NULL, use zero length
+ if (!psz)
+ cb = 0;
+ else
+ {
+ // count is length of string, plus terminating null
+ cb = (1 + strlen(psz));
+
+ // if possible, do a single write instead of two
+
+ if (cb <= UTSTRINGBUF_SIZE)
+ {
+ BYTE bBuf[sizeof(ULONG)+
+ UTSTRINGBUF_SIZE];
+ // buffer for count and string
+
+ // we have to use _xmemcpy to copy the length into
+ // the buffer to avoid potential boundary faults,
+ // since bBuf might not be aligned strictly enough
+ // to do *((ULONG FAR *)bBuf) = cb;
+ _xmemcpy((void FAR *)bBuf, (const void FAR *)&cb,
+ sizeof(cb));
+ _xmemcpy((void FAR *)(bBuf+sizeof(cb)),
+ (const void FAR *)psz, cb);
+
+ // write contents of buffer all at once
+ return(StmWrite.Write((VOID FAR *)bBuf,
+ cb+sizeof(ULONG)));
+ }
+ }
+
+ // if we got here, our buffer isn't large enough, so we do two writes
+ // first, write the length
+ if (error = StmWrite.Write((VOID FAR *)&cb, sizeof(ULONG)))
+ return error;
+
+ // are we are done writing the string?
+ if (psz == NULL)
+ return NOERROR;
+
+ // write the string
+ return(StmWrite.Write((VOID FAR *)psz, cb));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: StRead
+//
+// Synopsis: Stream read that only succeeds if all requested bytes read
+//
+// Arguments: [pStm] -- source stream
+// [pvBuffer] -- destination buffer
+// [ulcb] -- bytes to read
+//
+// Returns: S_OK if successful, else error code
+//
+// Algorithm:
+//
+// History: 18-May-94 AlexT Added header block, fixed S_FALSE case
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#pragma SEG(StRead)
+FARINTERNAL_(HRESULT) StRead(IStream FAR * pStm, LPVOID pvBuffer, ULONG ulcb)
+{
+ VDATEHEAP();
+
+ HRESULT hr;
+ ULONG cbRead;
+
+ hr = pStm->Read(pvBuffer, ulcb, &cbRead);
+ if (FAILED(hr))
+ {
+ return(hr);
+ }
+
+ if (ulcb == cbRead)
+ {
+ return(S_OK);
+ }
+
+ // We got a success code but not enough bytes - turn it into an error
+
+ return(STG_E_READFAULT);
+}
+
+
+// if fRelative is FALSE then dwSize is the size of the stream
+// if it is TRUE then find the current seek position and add dwSize to that
+// and then set it as the stream size.
+FARINTERNAL StSetSize(LPSTREAM pstm, DWORD dwSize, BOOL fRelative)
+{
+ VDATEHEAP();
+
+ LARGE_INTEGER large_int; // indicates where to seek to
+ ULARGE_INTEGER ularge_int; // indicates absolute position
+ ULARGE_INTEGER ularge_integer; // the size we will set for the stream
+ HRESULT error;
+
+ LISet32(large_int, 0);
+ ULISet32(ularge_integer, dwSize);
+
+ if (fRelative)
+ {
+ if (error = pstm->Seek(large_int, STREAM_SEEK_CUR, &ularge_int))
+ return(error);
+
+ // REVIEW: is there a routine to do 64 bit addition ???
+ ularge_integer.LowPart += ularge_int.LowPart;
+ }
+
+ return(pstm->SetSize(ularge_integer));
+}
+
+
+// REVIEW, is this actually used?
+#pragma SEG(StSave10NativeData)
+FARINTERNAL_(HRESULT) StSave10NativeData(IStorage FAR* pstgSave,
+ HANDLE hNative, BOOL fIsOle1Interop)
+{
+ VDATEHEAP();
+
+ DWORD dwSize;
+ HRESULT error;
+
+ if (!hNative)
+ return ReportResult(0, E_UNSPEC, 0, 0);
+
+ if (!(dwSize = GlobalSize (hNative)))
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+#ifdef OLE1INTEROP
+ if ( fIsOle1Interop )
+ {
+ LPLOCKBYTES plkbyt;
+ LPSTORAGE pstgNative= NULL;
+ const DWORD grfStg = STGM_READWRITE | STGM_SHARE_EXCLUSIVE
+ | STGM_DIRECT ;
+
+ if ((error = CreateILockBytesOnHGlobal (hNative, FALSE, &plkbyt))!=NOERROR)
+ goto errRtn;
+
+ if ((error = StgOpenStorageOnILockBytes (plkbyt, (LPSTORAGE)NULL, grfStg,
+ (SNB)NULL, 0, &pstgNative)) != NOERROR){
+ error = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ plkbyt->Release();
+ goto errRtn;
+ }
+
+ pstgNative->CopyTo (0, NULL, 0, pstgSave);
+ plkbyt->Release();
+ pstgNative->Release();
+ }
+ else
+#endif
+ {
+ LPSTREAM lpstream = NULL;
+
+ if (error = OpenOrCreateStream(pstgSave, OLE10_NATIVE_STREAM, &lpstream))
+ goto errRtn;
+
+ if (error = StWrite(lpstream, &dwSize, sizeof(DWORD))) {
+ lpstream->Release();
+ goto errRtn;
+ }
+
+ error = UtHGLOBALtoStm(hNative, dwSize, lpstream);
+
+ lpstream->Release();
+ }
+
+errRtn:
+ return error;
+}
+
+
+
+#pragma SEG(StSave10ItemName)
+FARINTERNAL StSave10ItemName
+ (IStorage FAR* pstg,
+ LPCSTR szItemNameAnsi)
+{
+ VDATEHEAP();
+
+ CStmBufWrite StmWrite;
+ HRESULT hresult;
+
+
+ if ((hresult = StmWrite.OpenOrCreateStream(pstg, OLE10_ITEMNAME_STREAM))
+ != NOERROR)
+ {
+ return hresult;
+ }
+
+ hresult = WriteStringStreamA(StmWrite, szItemNameAnsi);
+ if (FAILED(hresult))
+ {
+ goto errRtn;
+ }
+
+ hresult = StmWrite.Flush();
+
+errRtn:
+ StmWrite.Release();
+
+ return hresult;
+}
+
+
+#pragma SEG(StRead10NativeData)
+FARINTERNAL StRead10NativeData
+ (IStorage FAR* pstg,
+ HANDLE FAR* phNative)
+{
+ VDATEHEAP();
+
+ DWORD dwSize;
+ LPSTREAM pstream = NULL;
+ HRESULT hresult;
+
+ *phNative = NULL;
+
+ RetErr (pstg->OpenStream (OLE10_NATIVE_STREAM, NULL, STGM_SALL, 0, &pstream));
+ ErrRtnH (StRead (pstream, &dwSize, sizeof (DWORD)));
+
+ ErrRtnH (UtGetHGLOBALFromStm(pstream, dwSize, phNative));
+
+errRtn:
+ if (pstream)
+ pstream->Release();
+ return hresult;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBuf::CStmBuf, public
+//
+// Synopsis: Constructor.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CStmBuf::CStmBuf(void)
+{
+ m_pStm = NULL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBuf::~CStmBuf, public
+//
+// Synopsis: Destructor.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CStmBuf::~CStmBuf(void)
+{
+ //
+ // Verify that the programmer released the stream interface.
+ //
+ Assert(m_pStm == NULL);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::Init, public
+//
+// Synopsis: Define the stream interface to read from.
+//
+// Arguments: [pstm] -- Pointer to stream to read.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes: Release method must be called.
+//
+//----------------------------------------------------------------------------
+void CStmBufRead::Init(IStream * pstm)
+{
+ Assert(m_pStm == NULL);
+
+ m_pStm = pstm;
+
+ m_pStm->AddRef();
+
+ Reset();
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::OpenStream, public
+//
+// Synopsis: Open a stream for reading.
+//
+// Arguments: [pstg] -- Pointer to storage that contains stream to open.
+// [pwcsName] -- Name of stream to open.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes: Release method must be called.
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufRead::OpenStream(IStorage * pstg, const OLECHAR * pwcsName)
+{
+ VDATEHEAP();
+ HRESULT hr;
+
+
+ Assert(m_pStm == NULL);
+
+ hr = pstg->OpenStream(pwcsName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0,
+ &m_pStm);
+
+ Reset();
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::Read, public
+//
+// Synopsis: Read data from the stream.
+//
+// Arguments: [pBuf] - Address to store read bytes in.
+// [cBuf] - Maximum number of bytes to read.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufRead::Read(PVOID pBuf, ULONG cBuf)
+{
+ ULONG cnt;
+ HRESULT hr;
+
+
+ //
+ // While more bytes to read.
+ //
+ while (cBuf)
+ {
+ //
+ // If our buffer is empty, read more data.
+ //
+ if (m_cBuffer == 0)
+ {
+ hr = m_pStm->Read(m_aBuffer, sizeof(m_aBuffer), &m_cBuffer);
+ if (FAILED(hr))
+ return hr;
+
+ if (m_cBuffer == 0)
+ return STG_E_READFAULT;
+
+ m_pBuffer = m_aBuffer;
+ }
+
+ //
+ // Determine number of bytes to read.
+ //
+ cnt = min(m_cBuffer, cBuf);
+
+ //
+ // Copy the input from the input buffer, update variables.
+ //
+ memcpy(pBuf, m_pBuffer, cnt);
+ pBuf = (PBYTE)pBuf + cnt;
+ cBuf -= cnt;
+ m_pBuffer += cnt;
+ m_cBuffer -= cnt;
+ }
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::ReadLong, public
+//
+// Synopsis: Read a long value from the stream.
+//
+// Arguments: [plValue] - Address of long to fill.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufRead::ReadLong(LONG * plValue)
+{
+ return Read(plValue, sizeof(LONG));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::Reset
+//
+// Synopsis: Reset buffer variables.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void CStmBufRead::Reset(void)
+{
+ m_pBuffer = m_aBuffer;
+ m_cBuffer = 0;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::Release, public
+//
+// Synopsis: Release read stream interface.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void CStmBufRead::Release()
+{
+ if (m_pStm)
+ {
+ m_pStm->Release();
+ m_pStm = NULL;
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufWrite::Init, public
+//
+// Synopsis: Define the stream interface to write to.
+//
+// Arguments: [pstm] -- Pointer to stream to write.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes: Release method must be called.
+//
+//----------------------------------------------------------------------------
+void CStmBufWrite::Init(IStream * pstm)
+{
+ Assert(m_pStm == NULL);
+
+ m_pStm = pstm;
+
+ m_pStm->AddRef();
+
+ Reset();
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::OpenOrCreateStream, public
+//
+// Synopsis: Open/Create a stream for writing.
+//
+// Arguments: [pstg] -- Pointer to storage that contains stream to open.
+// [pwcsName] -- Name of stream to open.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes: Release method must be called.
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufWrite::OpenOrCreateStream(IStorage * pstg,
+ const OLECHAR * pwcsName)
+{
+ VDATEHEAP();
+ HRESULT hr;
+
+
+ hr = pstg->CreateStream(pwcsName, STGM_SALL | STGM_FAILIFTHERE, 0, 0,
+ &m_pStm);
+
+ if (hr == STG_E_FILEALREADYEXISTS)
+ {
+ hr = pstg->OpenStream(pwcsName, NULL, STGM_SALL, 0, &m_pStm);
+ }
+
+ Reset();
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufRead::CreateStream, public
+//
+// Synopsis: Create a stream for writing.
+//
+// Arguments: [pstg] -- Pointer storage that contains stream to create.
+// [pwcsName] -- Name of stream to create.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes: Release method must be called.
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufWrite::CreateStream(IStorage * pstg, const OLECHAR * pwcsName)
+{
+ VDATEHEAP();
+
+ HRESULT hr;
+
+
+ hr = pstg->CreateStream(pwcsName, STGM_CREATE | STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE, 0, 0, &m_pStm);
+
+ Reset();
+
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufWrite::Write, public
+//
+// Synopsis: Write data to the stream.
+//
+// Arguments: [pBuf] - Address to store write bytes to.
+// [cBuf] - Maximum number of bytes to write.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufWrite::Write(void const * pBuf, ULONG cBuf)
+{
+ ULONG cnt;
+ HRESULT hr;
+
+
+ //
+ // Keep writing until the caller's buffer is empty.
+ //
+ while (cBuf)
+ {
+ //
+ // Compute the number of bytes to copy.
+ //
+ cnt = min(m_cBuffer, cBuf);
+
+ //
+ // Copy to the internal write buffer and update variables.
+ //
+ memcpy(m_pBuffer, pBuf, cnt);
+ pBuf = (PBYTE)pBuf + cnt;
+ cBuf -= cnt;
+ m_pBuffer += cnt;
+ m_cBuffer -= cnt;
+
+ //
+ // On full internal buffer, flush.
+ //
+ if (m_cBuffer == 0)
+ {
+ LEDebugOut((DEB_WARN, "WARNING: Multiple buffer flushes.\n"));
+
+ hr = Flush();
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufWrite::WriteLong, public
+//
+// Synopsis: Write long value to the stream.
+//
+// Arguments: [lValue] - Long value to write.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufWrite::WriteLong(LONG lValue)
+{
+ return Write(&lValue, sizeof(LONG));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufWrite::Flush, public
+//
+// Synopsis: Flush write buffer to the system.
+//
+// Arguments: None.
+//
+// Returns: HRESULT.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes: Performs a write of the stream buffer to the system, does not
+// force a flush to disk.
+//
+//----------------------------------------------------------------------------
+HRESULT CStmBufWrite::Flush(void)
+{
+ ULONG cnt;
+ HRESULT hr;
+
+
+ //
+ // This might be an overactive assert, but shouldn't happen.
+ //
+ Assert(m_cBuffer != sizeof(m_aBuffer));
+
+ hr = m_pStm->Write(m_aBuffer, sizeof(m_aBuffer) - m_cBuffer, &cnt);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ if (cnt != sizeof(m_aBuffer) - m_cBuffer)
+ {
+ return STG_E_MEDIUMFULL;
+ }
+
+ Reset();
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufWrite::Reset, public
+//
+// Synopsis: Reset buffer variables.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void CStmBufWrite::Reset(void)
+{
+ m_pBuffer = m_aBuffer;
+ m_cBuffer = sizeof(m_aBuffer);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStmBufWrite::Release, public
+//
+// Synopsis: Release write stream interface.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// History: 20-Feb-95 KentCe Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void CStmBufWrite::Release()
+{
+ if (m_pStm)
+ {
+ //
+ // Verify that flush was called.
+ //
+ Assert(m_cBuffer == sizeof(m_aBuffer));
+
+ m_pStm->Release();
+ m_pStm = NULL;
+ }
+}
diff --git a/private/ole32/olecnfg/clshive.c b/private/ole32/olecnfg/clshive.c
new file mode 100644
index 000000000..08a134d8f
--- /dev/null
+++ b/private/ole32/olecnfg/clshive.c
@@ -0,0 +1,310 @@
+//*************************************************************
+//
+// Personal Classes Profile management routines
+//
+// Microsoft Confidential
+// Copyright (c) Microsoft Corporation 1995
+// All rights reserved
+//
+//*************************************************************
+
+#include "uenv.h"
+
+LPTSTR GetSidString(HANDLE UserToken);
+VOID DeleteSidString(LPTSTR SidString);
+PSID GetUserSid (HANDLE UserToken);
+VOID DeleteUserSid(PSID Sid);
+
+BOOL
+MergeUserClasses(
+ HKEY UserClassStore,
+ HKEY CommonClassStore,
+ HKEY MergedClassStore,
+ BOOL ForceNew);
+
+BOOL
+CloneRegistryTree(
+ HKEY hkSourceTree,
+ HKEY hkDestinationTree,
+ LPTSTR lpDestTreeName );
+
+BOOL
+AddSharedValuesToSubkeys( HKEY hkShared, LPTSTR pszSubtree );
+
+BOOL
+AddSharedValues( HKEY hkShared );
+void CreateMachineClassHive( )
+{
+ HKEY hkUser;
+ HKEY hkMachine;
+ LONG result;
+ DWORD dwDisp;
+
+ result =
+ RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ TEXT("Software\\Classes"),
+ 0,
+ KEY_READ,
+ &hkUser);
+ result =
+ RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+ TEXT("Software\\MachineClasses"),
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL,
+ &hkMachine,
+ &dwDisp );
+
+ CloneRegistryTree(hkUser, hkMachine, NULL);
+
+ AddSharedValues( hkMachine );
+
+ RegCloseKey( hkUser );
+ RegCloseKey( hkMachine );
+}
+
+
+LPTSTR
+GetUserMergedHivePath(
+ LPTSTR SidString )
+{
+ // open HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ProfileList
+ // open ...\SidString
+ // get value for ProfileImagePath, and if it is reg_expand_sz, expand it
+ // append Classes as the last component of the hive file name
+ long result;
+ HKEY hkProfileListKey;
+ HKEY hkProfileKey;
+ TCHAR ProfilePath[256];
+ TCHAR ExpandedProfilePath[256];
+ LPTSTR pszProfileDirectory = NULL;
+ LPTSTR pszReturnedHivePath = NULL;
+ DWORD dwType;
+ DWORD dwSize = sizeof( ProfilePath );
+
+
+ result = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList",
+ 0,
+ KEY_READ,
+ &hkProfileListKey );
+
+ // TBD: errors?
+
+ result = RegOpenKeyEx( hkProfileListKey,
+ SidString,
+ 0,
+ KEY_READ,
+ &hkProfileKey );
+
+ result = RegQueryValueEx( hkProfileKey,
+ L"ProfileImagePath",
+ NULL,
+ &dwType,
+ (BYTE*)&ProfilePath,
+ &dwSize );
+
+ if ( dwType == REG_EXPAND_SZ )
+ {
+ ExpandEnvironmentStrings( ProfilePath,
+ ExpandedProfilePath,
+ sizeof(ExpandedProfilePath)/sizeof(TCHAR) );
+ pszProfileDirectory = ExpandedProfilePath;
+ }
+ else
+ {
+ pszProfileDirectory = ProfilePath;
+ }
+
+ pszReturnedHivePath = (LPTSTR) LocalAlloc( LPTR,
+ (lstrlenW( pszProfileDirectory )+1) * sizeof(TCHAR) +
+ sizeof( L"\\ClsRoot" ) );
+ // make up the returned string as the profile directory with \ClsRoot on the end
+ lstrcpyW( pszReturnedHivePath, pszProfileDirectory );
+ lstrcatW( pszReturnedHivePath, L"\\ClsRoot" );
+
+ return pszReturnedHivePath;
+}
+
+void
+FreeUserMergedHivePath( LPTSTR hivepath )
+{
+ LocalFree( hivepath );
+}
+
+// see if the desired hive file already exists. If so, load it and return
+// otherwise, create a hive containing a single key, load it and return
+BOOL
+CreateUserMergedClasses(
+ LPTSTR SidString,
+ LPTSTR MergedClassesString,
+ HKEY * phkMerged )
+{
+ LPTSTR HivePath;
+ long result;
+ HKEY DummyKey;
+ DWORD dwDisp;
+ NTSTATUS Status;
+ BOOLEAN WasEnabled;
+
+ if (!NT_SUCCESS(Status)) {
+ // TBD: report error
+ }
+
+ HivePath = GetUserMergedHivePath( SidString );
+
+ // see if the desired hive file already exists. If so, load it and return
+ if ( 0xFFFFFFFF == GetFileAttributes( HivePath ) )
+ {
+ // create a hive containing a single key, load it and return
+ result = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
+ L"Software\\Microsoft\\DummyKey",
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL,
+ &DummyKey,
+ &dwDisp );
+
+ //
+ // Enable the backup privilege
+ //
+
+ Status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, TRUE, FALSE, &WasEnabled);
+
+ // do this by doing a RegSaveKey of a small subtree
+ result = RegSaveKey( DummyKey,
+ HivePath,
+ NULL );
+
+ result = RegCloseKey( DummyKey );
+ //
+ // Restore the privilege to its previous state
+ //
+
+ Status = RtlAdjustPrivilege(SE_BACKUP_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
+ }
+
+ //
+ // Enable the restore privilege
+ //
+
+ Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &WasEnabled);
+
+
+ result = RegLoadKey( HKEY_USERS,
+ MergedClassesString,
+ HivePath );
+
+ // if result is OK, then open the subkey and return it
+ result = RegOpenKeyEx( HKEY_USERS,
+ MergedClassesString,
+ 0,
+ KEY_ALL_ACCESS,
+ phkMerged );
+
+ FreeUserMergedHivePath( HivePath );
+ // close keys?
+
+ //
+ // Restore the privilege to its previous state
+ //
+
+ Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
+
+ return TRUE;
+}
+
+
+
+
+void MergeUserClassHives( HANDLE Token )
+{
+ HKEY hkUser;
+ HKEY hkMachine;
+ HKEY hkMerged;
+ LONG result;
+ LPTSTR SidString;
+ LPTSTR MergedClassesString;
+ DWORD dwDisp;
+ BOOL ForceNew = FALSE;
+
+ result =
+ RegCreateKeyEx(HKEY_CURRENT_USER,
+ TEXT("Software\\Classes"),
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ,
+ NULL,
+ &hkUser,
+ &dwDisp);
+
+ result =
+ RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ TEXT("Software\\MachineClasses"),
+ 0,
+ KEY_READ,
+ &hkMachine);
+
+ if ( result == ERROR_FILE_NOT_FOUND )
+ {
+ CreateMachineClassHive();
+ result =
+ RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ TEXT("Software\\MachineClasses"),
+ 0,
+ KEY_READ,
+ &hkMachine);
+
+ }
+
+ SidString = GetSidString( Token );
+
+ MergedClassesString = (LPTSTR) LocalAlloc( LPTR,
+ (lstrlenW( SidString ) + 1) * sizeof(WCHAR) +
+ sizeof(L"_MergedClasses" ) );
+ // TBD: check for NULL
+
+ lstrcpyW( MergedClassesString, SidString );
+ lstrcatW( MergedClassesString, L"_MergedClasses" );
+
+ result = RegOpenKeyEx( HKEY_USERS,
+ MergedClassesString,
+ 0,
+ KEY_ALL_ACCESS,
+ &hkMerged );
+
+ if ( result == ERROR_FILE_NOT_FOUND )
+ {
+ CreateUserMergedClasses(SidString, MergedClassesString, &hkMerged );
+ ForceNew = TRUE;
+ }
+
+ MergeUserClasses(hkUser, hkMachine, hkMerged, ForceNew );
+
+ RegCloseKey( hkUser );
+ RegCloseKey( hkMachine );
+ RegCloseKey( hkMerged );
+
+ LocalFree( MergedClassesString );
+
+ DeleteSidString( SidString );
+}
+
+void MergeHives( )
+{
+ HANDLE Token;
+ NTSTATUS Status;
+
+ Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_QUERY, &Token );
+
+ MergeUserClassHives( Token );
+
+ NtClose( Token );
+
+}
+
diff --git a/private/ole32/olecnfg/main.c b/private/ole32/olecnfg/main.c
new file mode 100644
index 000000000..45507397b
--- /dev/null
+++ b/private/ole32/olecnfg/main.c
@@ -0,0 +1,374 @@
+//
+//
+//
+
+#include "olecnfg.h"
+
+const char * GlobalKeyNames[] =
+ {
+ 0,
+ "EnableDCOM",
+ "DefaultLaunchPermission",
+ "DefaultAccessPermission",
+ "LegacyAuthenticationLevel"
+ };
+
+const char * ClsidKeyNames[] =
+ {
+ 0,
+ "InprocHandler32",
+ "InprocServer32",
+ "LocalServer32",
+ "LocalService",
+ "RemoteServerName",
+ "RunAs",
+ "ActivateAtStorage",
+ "LaunchPermission",
+ "AccessPermission"
+ };
+
+int ArgsLeft;
+char ** Args;
+
+HKEY hRegOle = 0;
+HKEY hRegClsid = 0;
+
+#define IsDigit(c) (IsCharAlphaNumeric(c) && !IsCharAlpha(c))
+
+void __cdecl main(int argc, char **argv)
+{
+ int GlobalKeys[GLOBAL_KEYS+1];
+ int Key;
+ int n;
+ DWORD Disposition;
+ long RegStatus;
+
+ memset( GlobalKeys, 0, sizeof(GlobalKeys) );
+
+ ArgsLeft = argc - 1;
+ Args = argv + 1;
+
+ if ( (argc > 1) &&
+ ((strcmp( "/?", argv[1] ) == 0) || (strcmp( "-?", argv[1] ) == 0)) )
+ {
+ DisplayHelp();
+ return;
+ }
+
+ //
+ // With no arguments, display the global registry activation values.
+ //
+ if ( ArgsLeft == 0 )
+ {
+ DisplayGlobalSettings();
+ return;
+ }
+
+ //
+ // Look for specified global registry keys and operations
+ //
+ for ( ; ArgsLeft > 0; )
+ {
+ if ( _stricmp( *Args, "EnableDCOM" ) == 0 )
+ Key = ENABLE_NETWORK_OLE;
+ else if ( _stricmp( *Args, "DefaultLaunchPermission" ) == 0 )
+ Key = DEFAULT_LAUNCH_PERMISSION;
+ else if ( _stricmp( *Args, "DefaultAccessPermission" ) == 0 )
+ Key = DEFAULT_ACCESS_PERMISSION;
+ else if ( _stricmp( *Args, "LegacyAuthenticationLevel" ) == 0 )
+ Key = LEGACY_AUTHENTICATION_LEVEL;
+ else
+ break;
+
+ EAT_ARG();
+
+ if ( Key >= 100 )
+ {
+ if ( Key == MERGE )
+ {
+ MergeHives( );
+ }
+ else if ( Key == SAVE_USER )
+ {
+ SaveChangesToUser( );
+ }
+ else if ( Key == SAVE_COMMON )
+ {
+ SaveChangesToCommon( );
+ }
+ continue;
+ }
+
+ if ( Key == DEFAULT_ACCESS_PERMISSION )
+ {
+ GlobalKeys[Key] = YES;
+ continue;
+ }
+
+ if ( Key == LEGACY_AUTHENTICATION_LEVEL )
+ {
+ if ( ! IsDigit(**Args) || (**Args < '1') || (**Args > '6') )
+ {
+ printf( "LegacyAuthenticationLevel must be followed by a 1 to 6.\n" );
+ return;
+ }
+
+ GlobalKeys[Key] = **Args;
+ }
+ else if ( (GlobalKeys[Key] = ReadYesOrNo()) == INVALID )
+ {
+ printf( "%s must be followed by 'y' or 'n'\n", Args[-1] );
+ return;
+ }
+
+ EAT_ARG();
+ }
+
+ //
+ // Set global keys on or off.
+ //
+ for ( Key = 1; Key < sizeof(GlobalKeys)/sizeof(int); Key++ )
+ {
+ if ( (Key == LEGACY_AUTHENTICATION_LEVEL) && (GlobalKeys[Key] != 0) )
+ {
+ if ( ! SetGlobalKey( Key, GlobalKeys[Key] - '0' ) )
+ return;
+ continue;
+ }
+
+ if ( (GlobalKeys[Key] == YES) || (GlobalKeys[Key] == NO) )
+ if ( ! SetGlobalKey( Key, GlobalKeys[Key] ) )
+ return;
+ }
+
+ //
+ // Process any CLSID/ProgID specification.
+ //
+ ParseClsidProgId();
+
+ if ( hRegOle )
+ RegCloseKey( hRegOle );
+ if ( hRegClsid )
+ RegCloseKey( hRegClsid );
+}
+
+void ParseClsidProgId()
+{
+ CLSID_INFO ClsidInfo;
+ BOOL NoKeys;
+ int ClsidKey;
+
+ if ( ArgsLeft == 0 )
+ return;
+
+ memset( &ClsidInfo, 0, sizeof(CLSID_INFO) );
+
+ NoKeys = TRUE;
+
+ if ( (ArgsLeft > 0) && (**Args != '{') )
+ {
+ ClsidInfo.ProgId = *Args;
+ EAT_ARG();
+
+ if ( (ArgsLeft > 0) &&
+ (**Args != '{') &&
+ (NextClsidKey() == UNKNOWN) )
+ {
+ ClsidInfo.ProgIdDescription = *Args;
+ EAT_ARG();
+ }
+ }
+
+ if ( (ArgsLeft > 0) && (**Args == '{') )
+ {
+ ClsidInfo.Clsid = *Args;
+ EAT_ARG();
+
+ if ( (ArgsLeft > 0) &&
+ (NextClsidKey() == UNKNOWN) )
+ {
+ ClsidInfo.ClsidDescription = *Args;
+ EAT_ARG();
+ }
+ }
+
+ for (; ArgsLeft > 0;)
+ {
+ ClsidKey = NextClsidKey();
+ if ( (1 <= ClsidKey) && (ClsidKey <= CLSID_KEYS) )
+ NoKeys = FALSE;
+
+ EAT_ARG();
+
+ switch ( ClsidKey )
+ {
+ case LAUNCH_PERMISSION :
+ if ( (ClsidInfo.LaunchPermission = ReadYesOrNo()) == INVALID )
+ {
+ printf( "%s must be followed by 'y' or 'n'\n",
+ ClsidKeyNames[LAUNCH_PERMISSION] );
+ goto ErrorReturn;
+ }
+ EAT_ARG();
+ break;
+
+ case ACCESS_PERMISSION :
+ ClsidInfo.AccessPermission = YES;
+ break;
+
+ case ACTIVATE_AT_STORAGE :
+ if ( (ClsidInfo.ActivateAtStorage = ReadYesOrNo()) == INVALID )
+ {
+ printf( "%s must be followed by 'y' or 'n'\n",
+ ClsidKeyNames[ACTIVATE_AT_STORAGE] );
+ goto ErrorReturn;
+ }
+ EAT_ARG();
+ break;
+
+ case INPROC_HANDLER32 :
+ case INPROC_SERVER32 :
+ case LOCAL_SERVER32 :
+ case LOCAL_SERVICE :
+ if ( NextClsidKey() == UNKNOWN )
+ {
+ ClsidInfo.ServerPaths[ClsidKey] = *Args;
+ EAT_ARG();
+ }
+ else
+ {
+ ClsidInfo.ServerPaths[ClsidKey] = "";
+ }
+ break;
+
+ case REMOTE_SERVER_NAME :
+ if ( NextClsidKey() == UNKNOWN )
+ {
+ ClsidInfo.RemoteServerName = *Args;
+ EAT_ARG();
+ }
+ else
+ {
+ ClsidInfo.RemoteServerName = "";
+ }
+ break;
+
+ case RUN_AS :
+ if ( NextClsidKey() == UNKNOWN )
+ {
+ ClsidInfo.RunAsUserName = *Args;
+ EAT_ARG();
+
+ if ( _stricmp(ClsidInfo.RunAsUserName,"Interactive User") == 0 )
+ break;
+
+ if ( _stricmp(ClsidInfo.RunAsUserName,"Interactive") == 0 )
+ {
+ if ( (ArgsLeft > 0) && (_stricmp(*Args,"User") == 0) )
+ {
+ EAT_ARG();
+ ClsidInfo.RunAsUserName = "Interactive User";
+ break;
+ }
+ }
+
+ if ( NextClsidKey() != UNKNOWN )
+ {
+ printf( "RunAs password or '*' must follow the user name.\n" );
+ goto ErrorReturn;
+ }
+
+ ClsidInfo.RunAsPassword = *Args;
+ EAT_ARG();
+ }
+ else
+ {
+ ClsidInfo.RunAsUserName = "";
+ }
+ break;
+
+ default :
+ printf( "Invalid CLSID/ProgID specification given (%s)\n", Args[-1] );
+ goto ErrorReturn;
+ break;
+ } // switch
+ } // for
+
+ //
+ // Display current CLSID/ProgID settings if no keys were specified and
+ // only a CLSID or ProgID (but not both) was given.
+ //
+ if ( NoKeys &&
+ (ClsidInfo.ProgIdDescription == 0) &&
+ (ClsidInfo.ClsidDescription == 0) &&
+ ((ClsidInfo.Clsid == 0) || (ClsidInfo.ProgId == 0)) )
+ DisplayClsidKeys( &ClsidInfo );
+ else
+ UpdateClsidKeys( &ClsidInfo );
+
+ return;
+
+ErrorReturn:
+ printf( "No CLSID/ProgID entries were modified\n" );
+}
+
+int NextClsidKey()
+{
+ if ( ArgsLeft == 0 )
+ return END_OF_ARGS;
+
+ if ( _stricmp( *Args, "InprocHandler32" ) == 0 )
+ return INPROC_HANDLER32;
+ if ( _stricmp( *Args, "InprocServer32" ) == 0 )
+ return INPROC_SERVER32;
+ if ( _stricmp( *Args, "LocalServer32" ) == 0 )
+ return LOCAL_SERVER32;
+ if ( _stricmp( *Args, "LocalService" ) == 0 )
+ return LOCAL_SERVICE;
+ if ( _stricmp( *Args, "RemoteServerName" ) == 0 )
+ return REMOTE_SERVER_NAME;
+ if ( _stricmp( *Args, "RunAs" ) == 0 )
+ return RUN_AS;
+ if ( _stricmp( *Args, "ActivateAtStorage" ) == 0 )
+ return ACTIVATE_AT_STORAGE;
+ if ( _stricmp( *Args, "LaunchPermission" ) == 0 )
+ return LAUNCH_PERMISSION;
+ if ( _stricmp( *Args, "AccessPermission" ) == 0 )
+ return ACCESS_PERMISSION;
+
+ return UNKNOWN;
+}
+
+int ReadYesOrNo()
+{
+ if ( ArgsLeft == 0 )
+ return INVALID;
+
+ if ( (char)CharUpperA((LPSTR)**Args) == 'Y' )
+ return YES;
+ if ( (char)CharUpperA((LPSTR)**Args) == 'N' )
+ return NO;
+
+ return INVALID;
+}
+
+
+void DisplayHelp()
+{
+ puts( "\nolecnfg\n"
+ "\t[EnableDCOM <y,n>]\n"
+ "\t[DefaultLaunchPermission <y,n>]\n"
+ "\t[DefaultAccessPermission]\n"
+ "\t[LegacyAuthenticationLevel <1,2,3,4,5,6>]\n" );
+ puts( "\t[[ProgID [Description]] [CLSID [Description]]\n"
+ "\t\t[InprocHandler32 [Path]]\n"
+ "\t\t[InprocServer32 [Path]]\n"
+ "\t\t[LocalServer32 [Path]]\n"
+ "\t\t[LocalService [Path]]\n"
+ "\t\t[RemoteServerName [MachineName]]\n"
+ "\t\t[RunAs [UserName Password]] ]\n"
+ "\t\t[ActivateAtStorage <y,n>]\n"
+ "\t\t[LaunchPermission <y,n>]\n"
+ "\t\t[AccessPermission]\n"
+ "\t]\n" );
+}
diff --git a/private/ole32/olecnfg/makefile b/private/ole32/olecnfg/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ole32/olecnfg/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/olecnfg/olecnfg.c b/private/ole32/olecnfg/olecnfg.c
new file mode 100644
index 000000000..b34c85a99
--- /dev/null
+++ b/private/ole32/olecnfg/olecnfg.c
@@ -0,0 +1,996 @@
+//
+//
+//
+
+#include "olecnfg.h"
+
+BOOL SetGlobalKey( int Key, int Value )
+{
+ DWORD RegStatus;
+ HKEY hReg;
+ DWORD Disposition;
+ char * ValueName;
+
+ if ( hRegOle == 0 )
+ {
+ RegStatus = RegCreateKeyEx(
+ HKEY_LOCAL_MACHINE,
+ "SOFTWARE\\Microsoft\\OLE",
+ 0,
+ "REG_SZ",
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hRegOle,
+ &Disposition );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Could not open HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\OLE for writing\n" );
+ return FALSE;
+ }
+ }
+
+ // BUGBUG : Extra stuff to do for PersonalClasses and InstallCommon.
+
+ if ( (Key == DEFAULT_LAUNCH_PERMISSION) ||
+ (Key == DEFAULT_ACCESS_PERMISSION) )
+ {
+ RegStatus = RegCreateKeyEx(
+ hRegOle,
+ GlobalKeyNames[Key],
+ 0,
+ "REG_SZ",
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hReg,
+ &Disposition );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Unable to open or add global key %s (status %d)\n",
+ GlobalKeyNames[Key],
+ RegStatus );
+ return FALSE;
+ }
+
+ ValueName = NULL;
+ }
+ else
+ {
+ hReg = hRegOle;
+ ValueName = (char *)GlobalKeyNames[Key];
+ }
+
+ if ( Key == LEGACY_AUTHENTICATION_LEVEL )
+ {
+ RegStatus = RegSetValueEx(
+ hReg,
+ ValueName,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&Value,
+ sizeof(DWORD) );
+ }
+ else if ( Key != DEFAULT_ACCESS_PERMISSION )
+ {
+ RegStatus = RegSetValueEx(
+ hReg,
+ ValueName,
+ 0,
+ REG_SZ,
+ (LPBYTE)(Value == YES ? "Y" : "N"),
+ 2 * sizeof(char) );
+ }
+ else
+ RegStatus = ERROR_SUCCESS;
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Unable to set value for %s (status %d)\n",
+ GlobalKeyNames[Key],
+ RegStatus );
+ return FALSE;
+ }
+
+ if ( Key == LEGACY_AUTHENTICATION_LEVEL )
+ {
+ printf( "Global setting %s set to %d.\n",
+ GlobalKeyNames[Key],
+ Value );
+ }
+ else if ( Key == DEFAULT_ACCESS_PERMISSION )
+ {
+ printf( "Global setting %s set to on.\n",
+ GlobalKeyNames[Key] );
+ }
+ else
+ {
+ printf( "Global setting %s set to %c.\n",
+ GlobalKeyNames[Key],
+ Value == YES ? 'Y' : 'N' );
+ }
+
+ return TRUE;
+}
+
+void DisplayGlobalSettings()
+{
+ HKEY hReg;
+ DWORD RegStatus;
+ int Key;
+ DWORD Type;
+ DWORD Value;
+ DWORD BufSize;
+ char * ValueName;
+
+ RegStatus = RegOpenKeyEx(
+ HKEY_LOCAL_MACHINE,
+ "SOFTWARE\\Microsoft\\OLE",
+ 0,
+ KEY_READ,
+ &hRegOle );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Could not open HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\OLE\n" );
+ return;
+ }
+
+ printf( "\nGlobal OLE registry settings :\n" );
+
+ for ( Key = 1; Key <= GLOBAL_KEYS; Key++ )
+ {
+ if ( (Key == DEFAULT_LAUNCH_PERMISSION) ||
+ (Key == DEFAULT_ACCESS_PERMISSION) )
+ {
+ RegStatus = RegOpenKeyEx(
+ hRegOle,
+ GlobalKeyNames[Key],
+ 0,
+ KEY_READ,
+ &hReg );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( " %-28sN (key does not exist or could not be opened)\n",
+ GlobalKeyNames[Key] );
+ continue;
+ }
+
+ ValueName = NULL;
+ }
+ else
+ {
+ hReg = hRegOle;
+ ValueName = (char *)GlobalKeyNames[Key];
+ }
+
+ if ( Key != DEFAULT_ACCESS_PERMISSION )
+ {
+ BufSize = sizeof(DWORD);
+
+ RegStatus = RegQueryValueEx(
+ hReg,
+ ValueName,
+ 0,
+ &Type,
+ (LPBYTE) &Value,
+ &BufSize );
+ }
+ else
+ RegStatus = ERROR_SUCCESS;
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ if ( Key == DEFAULT_LAUNCH_PERMISSION )
+ printf( " %-28sN (key value could not be read)\n",
+ GlobalKeyNames[Key] );
+ else
+ printf( " %-28s%c (value not present)\n",
+ GlobalKeyNames[Key],
+ (Key == LEGACY_AUTHENTICATION_LEVEL) ? '2' : 'N' );
+ continue;
+ }
+
+ if ( Key == LEGACY_AUTHENTICATION_LEVEL )
+ {
+ printf( " %-28s%d\n",
+ GlobalKeyNames[Key],
+ Value );
+ }
+ else if ( Key == DEFAULT_ACCESS_PERMISSION )
+ {
+ printf( " %-28son\n",
+ GlobalKeyNames[Key] );
+ }
+ else
+ {
+ printf( " %-28s%c\n",
+ GlobalKeyNames[Key],
+ (char)CharUpper((LPSTR)((char *)&Value)[0]) );
+ }
+ }
+}
+
+void DisplayClsidKeys(
+ CLSID_INFO * ClsidInfo )
+{
+ HKEY hProgId;
+ HKEY hClsid;
+ HKEY hProgIdClsid;
+ HKEY hKey;
+ DWORD RegStatus;
+ DWORD RegType;
+ DWORD BufSize;
+ char ProgIdClsid[64];
+ char Value[128];
+ int Key;
+ BOOL HasRunAs;
+ char Password[64];
+ LSA_HANDLE hPolicy;
+ LSA_OBJECT_ATTRIBUTES ObjAttributes;
+ LSA_UNICODE_STRING LsaKey;
+ LSA_UNICODE_STRING * LsaData;
+ WCHAR wszKey[64];
+ WCHAR wszPassword[64];
+ NTSTATUS NtStatus;
+
+ RegStatus = RegOpenKeyEx(
+ HKEY_CLASSES_ROOT,
+ "CLSID",
+ 0,
+ KEY_READ,
+ &hRegClsid );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Could not open HKEY_CLASSES_ROOT\\CLSID for reading.\n" );
+ return;
+ }
+
+ if ( ClsidInfo->ProgId )
+ {
+ RegStatus = RegOpenKeyEx(
+ HKEY_CLASSES_ROOT,
+ ClsidInfo->ProgId,
+ 0,
+ KEY_READ,
+ &hProgId );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Couldn't open ProgID %s\n", ClsidInfo->ProgId );
+ return;
+ }
+
+ RegStatus = RegOpenKeyEx(
+ hProgId,
+ "CLSID",
+ 0,
+ KEY_READ,
+ &hProgIdClsid );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Couldn't open CLSID key for ProgID %s\n", ClsidInfo->ProgId );
+ return;
+ }
+
+ BufSize = sizeof(ProgIdClsid);
+
+ RegStatus = RegQueryValueEx(
+ hProgIdClsid,
+ NULL,
+ 0,
+ &RegType,
+ (LPBYTE) ProgIdClsid,
+ &BufSize );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Couldn't open CLSID value for ProgID %s\n", ClsidInfo->ProgId );
+ return;
+ }
+
+ if ( ClsidInfo->Clsid &&
+ (_stricmp( ClsidInfo->Clsid, ProgIdClsid ) != 0) )
+ {
+ printf( "ProgID %s CLSID key value %s differs from given CLSID %s.\n",
+ ClsidInfo->ProgId,
+ ProgIdClsid,
+ ClsidInfo->Clsid );
+ return;
+ }
+ else
+ ClsidInfo->Clsid = ProgIdClsid;
+ }
+
+
+ if ( ! ClsidInfo->Clsid )
+ {
+ printf( "Could not determine CLSID.\n" );
+ return;
+ }
+
+ RegStatus = RegOpenKeyEx(
+ hRegClsid,
+ ClsidInfo->Clsid,
+ 0,
+ KEY_READ,
+ &hClsid );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Could not open CLSID %s\n", ClsidInfo->Clsid );
+ return;
+ }
+
+ putchar( '\n' );
+ if ( ClsidInfo->ProgId )
+ printf( "Server settings for ProgID %s, ", ClsidInfo->ProgId );
+ else
+ printf( "Server settings for " );
+
+ printf( "CLSID %s\n", ClsidInfo->Clsid );
+
+ HasRunAs = FALSE;
+
+ for ( Key = 1; Key <= CLSID_KEYS; Key++ )
+ {
+ RegStatus = RegOpenKeyEx(
+ hClsid,
+ ClsidKeyNames[Key],
+ 0,
+ KEY_READ,
+ &hKey );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ continue;
+
+ BufSize = sizeof(Value);
+
+ if ( Key != ACCESS_PERMISSION )
+ {
+ RegStatus = RegQueryValueEx(
+ hKey,
+ NULL,
+ 0,
+ &RegType,
+ (LPBYTE) Value,
+ &BufSize );
+ }
+ else
+ RegStatus = ERROR_SUCCESS;
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( " %-28s(key exists, but value could not be read)\n",
+ ClsidKeyNames[Key] );
+ continue;
+ }
+
+ printf( " %-28s%s\n",
+ ClsidKeyNames[Key],
+ (Key == ACCESS_PERMISSION) ? "on" : Value );
+
+ if ( (Key == RUN_AS) && (_stricmp(Value,"Interactive User") != 0) )
+ HasRunAs = TRUE;
+ }
+
+ if ( ! HasRunAs )
+ return;
+
+ //
+ // Give the option of verifying the RunAs password.
+ //
+
+ printf( "\nCLSID configured with RunAs. Would you like to verify the password? " );
+
+ if ( (char)CharUpper((LPSTR)getchar()) != 'Y' )
+ return;
+
+ while ( getchar() != '\n' )
+ ;
+
+ putchar( '\n' );
+
+ lstrcpyW( wszKey, L"SCM:" );
+ MultiByteToWideChar( CP_ACP,
+ MB_PRECOMPOSED,
+ ClsidInfo->Clsid,
+ -1,
+ &wszKey[lstrlenW(wszKey)],
+ sizeof(wszKey)/2 - lstrlenW(wszKey) );
+
+ LsaKey.Length = (lstrlenW(wszKey) + 1) * sizeof(WCHAR);
+ LsaKey.MaximumLength = sizeof(wszKey);
+ LsaKey.Buffer = wszKey;
+
+ InitializeObjectAttributes( &ObjAttributes, NULL, 0L, NULL, NULL );
+
+ // Open the local security policy
+ NtStatus = LsaOpenPolicy( NULL,
+ &ObjAttributes,
+ POLICY_CREATE_SECRET,
+ &hPolicy );
+
+ if ( ! NT_SUCCESS( NtStatus ) )
+ {
+ printf( "Could not open RunAs password (0x%x)\n", NtStatus );
+ return;
+ }
+
+ // Retrive private data
+ NtStatus = LsaRetrievePrivateData( hPolicy, &LsaKey, &LsaData );
+
+ if ( ! NT_SUCCESS(NtStatus) )
+ {
+ printf( "Could not open RunAs password (0x%x)\n", NtStatus );
+ return;
+ }
+
+ LsaClose(hPolicy);
+
+ for (;;)
+ {
+ printf( "Password : " );
+ ReadPassword( Password );
+
+ if ( strcmp( Password, "dcom4ever" ) == 0 )
+ {
+ printf( "\nThe RunAs password is %ws\n", LsaData->Buffer );
+ return;
+ }
+
+ MultiByteToWideChar( CP_ACP,
+ MB_PRECOMPOSED,
+ Password,
+ -1,
+ wszPassword,
+ sizeof(wszPassword) );
+
+ if ( lstrcmpW( wszPassword, LsaData->Buffer ) != 0 )
+ {
+ printf( "\nPassword does not match RunAs password.\n" );
+ printf( "Enter another password or hit Control-C to exit.\n\n" );
+ }
+ else
+ {
+ printf( "\nPasswords match.\n" );
+ return;
+ }
+ }
+}
+
+void UpdateClsidKeys( CLSID_INFO * ClsidInfo )
+{
+ HKEY hProgId;
+ HKEY hClsid;
+ HKEY hProgIdClsid;
+ HKEY hKey;
+ DWORD RegStatus;
+ DWORD Disposition;
+ DWORD RegType;
+ char ProgIdClsid[64];
+ char Response[64];
+ DWORD BufSize;
+ int n;
+
+ RegStatus = RegOpenKeyEx(
+ HKEY_CLASSES_ROOT,
+ "CLSID",
+ 0,
+ KEY_READ | KEY_WRITE,
+ &hRegClsid );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Could not open HKEY_CLASSES_ROOT\\CLSID for writing\n" );
+ return;
+ }
+
+ hProgId = 0;
+ hClsid = 0;
+
+ if ( ClsidInfo->ProgId )
+ {
+ RegStatus = RegCreateKeyEx(
+ HKEY_CLASSES_ROOT,
+ ClsidInfo->ProgId,
+ 0,
+ "REG_SZ",
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hProgId,
+ &Disposition );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Could not open or create ProgID key %s.\n",
+ ClsidInfo->ProgId);
+ return;
+ }
+
+ if ( Disposition == REG_CREATED_NEW_KEY )
+ printf( "ProgId key %s created.\n", ClsidInfo->ProgId );
+
+ if ( ClsidInfo->ProgIdDescription )
+ {
+ RegStatus = RegSetValueEx(
+ hProgId,
+ NULL,
+ 0,
+ REG_SZ,
+ (LPBYTE) ClsidInfo->ProgIdDescription,
+ strlen(ClsidInfo->ProgIdDescription) + sizeof(char) );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Could not set description value for ProgID %s.\n", ClsidInfo->ProgId );
+ return;
+ }
+
+ printf( "Setting description value %s for ProgID %s.\n",
+ ClsidInfo->ProgIdDescription,
+ ClsidInfo->ProgId );
+ }
+
+ RegStatus = RegCreateKeyEx(
+ hProgId,
+ "CLSID",
+ 0,
+ "REG_SZ",
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hProgIdClsid,
+ &Disposition );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Could not open or create CLSID key for ProgID %s.\n",
+ ClsidInfo->ProgId );
+ return;
+ }
+
+ //
+ // Check if a CLSID key value already exists for this ProgID. If so,
+ // and a CLSID was specified to us then check if they differ.
+ //
+
+ BufSize = sizeof(ProgIdClsid);
+
+ RegStatus = RegQueryValueEx(
+ hProgIdClsid,
+ NULL,
+ 0,
+ &RegType,
+ (LPBYTE) ProgIdClsid,
+ &BufSize );
+
+ if ( RegStatus == ERROR_SUCCESS )
+ {
+ if ( ClsidInfo->Clsid &&
+ (_stricmp(ClsidInfo->Clsid, ProgIdClsid) != 0) )
+ {
+ printf( "ProgID %s has existing CLSID key value %s\n",
+ ClsidInfo->ProgId,
+ ProgIdClsid );
+ printf( "which differs from given CLSID %s.\n",
+ ClsidInfo->Clsid );
+ printf( "Would you like to replace the existing CLSID value with the new CLSID value? " );
+ gets( Response );
+ if ( (char)CharUpper((LPSTR)Response[0]) != 'Y' )
+ ClsidInfo->Clsid = ProgIdClsid;
+ }
+ else
+ ClsidInfo->Clsid = ProgIdClsid;
+ }
+
+ if ( ! ClsidInfo->Clsid )
+ {
+ printf( "CLSID for ProgID %s not specified.\n",
+ ClsidInfo->ProgId );
+ return;
+ }
+
+ if ( ClsidInfo->Clsid != ProgIdClsid )
+ {
+ RegStatus = RegSetValueEx(
+ hProgIdClsid,
+ NULL,
+ 0,
+ REG_SZ,
+ (LPBYTE) ClsidInfo->Clsid,
+ strlen(ClsidInfo->Clsid) + sizeof(char) );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Could not set CLSID value for ProgID %s.\n", ClsidInfo->ProgId );
+ return;
+ }
+
+ printf( "Setting CLSID value %s for ProgID %s.\n",
+ ClsidInfo->Clsid,
+ ClsidInfo->ProgId );
+ }
+ }
+
+ RegStatus = RegCreateKeyEx(
+ hRegClsid,
+ ClsidInfo->Clsid,
+ 0,
+ "REG_SZ",
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hClsid,
+ &Disposition );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Could not open or create CLSID key %s.\n", ClsidInfo->Clsid );
+ return;
+ }
+
+ if ( Disposition == REG_CREATED_NEW_KEY )
+ printf( "CLSID key %s created.\n", ClsidInfo->Clsid );
+
+ if ( ClsidInfo->ClsidDescription )
+ {
+ RegStatus = RegSetValueEx(
+ hClsid,
+ NULL,
+ 0,
+ REG_SZ,
+ (LPBYTE) ClsidInfo->ClsidDescription,
+ strlen(ClsidInfo->ClsidDescription) + sizeof(char) );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Could not set description value for CLSID %s.\n", ClsidInfo->Clsid );
+ return;
+ }
+
+ printf( "Setting description value %s for CLSID %s.\n",
+ ClsidInfo->ClsidDescription,
+ ClsidInfo->Clsid );
+ }
+
+ //
+ // Now add and delete individual keys on this CLSID.
+ //
+
+ if ( (ClsidInfo->LaunchPermission == YES) ||
+ (ClsidInfo->LaunchPermission == NO) )
+ {
+ SetClsidKey( hClsid,
+ ClsidInfo->Clsid,
+ ClsidKeyNames[LAUNCH_PERMISSION],
+ (ClsidInfo->LaunchPermission == YES) ? "Y" : "N" );
+ }
+
+ if ( ClsidInfo->AccessPermission == YES )
+ {
+ SetClsidKey( hClsid,
+ ClsidInfo->Clsid,
+ ClsidKeyNames[ACCESS_PERMISSION],
+ NULL );
+ }
+
+ if ( (ClsidInfo->ActivateAtStorage == YES) ||
+ (ClsidInfo->ActivateAtStorage == NO) )
+ {
+ SetClsidKey( hClsid,
+ ClsidInfo->Clsid,
+ ClsidKeyNames[ACTIVATE_AT_STORAGE],
+ (ClsidInfo->ActivateAtStorage == YES) ? "Y" : "N" );
+ }
+
+ for ( n = 1; n <= CLSID_PATH_KEYS; n++ )
+ {
+ if ( ! ClsidInfo->ServerPaths[n] )
+ continue;
+ if ( ClsidInfo->ServerPaths[n][0] == '\0' )
+ DeleteClsidKey( hClsid,
+ ClsidInfo->Clsid,
+ ClsidKeyNames[n] );
+ else
+ SetClsidKey( hClsid,
+ ClsidInfo->Clsid,
+ ClsidKeyNames[n],
+ ClsidInfo->ServerPaths[n] );
+ }
+
+ if ( ClsidInfo->RemoteServerName )
+ {
+ if ( ClsidInfo->RemoteServerName[0] == '\0' )
+ DeleteClsidKey( hClsid,
+ ClsidInfo->Clsid,
+ ClsidKeyNames[REMOTE_SERVER_NAME] );
+ else
+ SetClsidKey( hClsid,
+ ClsidInfo->Clsid,
+ ClsidKeyNames[REMOTE_SERVER_NAME],
+ ClsidInfo->RemoteServerName );
+ }
+
+ if ( ClsidInfo->RunAsUserName )
+ {
+ DWORD CharRead;
+ char Password1[64];
+ char Password2[64];
+ LSA_HANDLE hPolicy;
+ LSA_OBJECT_ATTRIBUTES ObjAttributes;
+ LSA_UNICODE_STRING LsaKey;
+ LSA_UNICODE_STRING LsaData;
+ WCHAR wszKey[64];
+ WCHAR wszPassword[64];
+ NTSTATUS NtStatus;
+ BOOL Status;
+ BOOL RunAsInteractiveUser;
+
+ RunAsInteractiveUser = (_stricmp(ClsidInfo->RunAsUserName,"Interactive User") == 0);
+
+ if ( ! RunAsInteractiveUser )
+ {
+ InitializeObjectAttributes( &ObjAttributes, NULL, 0L, NULL, NULL );
+
+ // Open the local security policy
+ NtStatus = LsaOpenPolicy( NULL,
+ &ObjAttributes,
+ POLICY_CREATE_SECRET,
+ &hPolicy );
+
+ if ( ! NT_SUCCESS( NtStatus ) )
+ {
+ printf( "Could not setup RunAs (0x%x)\n", NtStatus );
+ return;
+ }
+
+ lstrcpyW( wszKey, L"SCM:" );
+ MultiByteToWideChar( CP_ACP,
+ MB_PRECOMPOSED,
+ ClsidInfo->Clsid,
+ -1,
+ &wszKey[lstrlenW(wszKey)],
+ sizeof(wszKey)/2 - lstrlenW(wszKey) );
+
+ LsaKey.Length = (lstrlenW(wszKey) + 1) * sizeof(WCHAR);
+ LsaKey.MaximumLength = sizeof(wszKey);
+ LsaKey.Buffer = wszKey;
+ }
+
+ if ( ClsidInfo->RunAsUserName[0] == '\0' )
+ {
+ DeleteClsidKey( hClsid,
+ ClsidInfo->Clsid,
+ ClsidKeyNames[RUN_AS] );
+
+ LsaStorePrivateData( hPolicy, &LsaKey, NULL );
+ }
+ else
+ {
+ Status = SetClsidKey( hClsid,
+ ClsidInfo->Clsid,
+ ClsidKeyNames[RUN_AS],
+ ClsidInfo->RunAsUserName );
+
+ if ( ! Status )
+ return;
+
+ if ( ! RunAsInteractiveUser && (ClsidInfo->RunAsPassword[0] == '*') )
+ {
+ for (;;)
+ {
+ printf( "Enter RunAs password for %s : ", ClsidInfo->RunAsUserName );
+ ReadPassword( Password1 );
+
+ printf( "Confirm password : " );
+ ReadPassword( Password2 );
+
+ if ( strcmp( Password1, Password2 ) != 0 )
+ {
+ printf( "Passwords differ, try again or hit Control-C to exit.\n" );
+ continue;
+ }
+
+ if ( Password1[0] == '\0' )
+ {
+ printf( "Do you really want a blank password? " );
+ gets( Response );
+ if ( (char)CharUpper((LPSTR)Response[0]) != 'Y' )
+ continue;
+ }
+
+ break;
+ }
+
+ ClsidInfo->RunAsPassword = Password1;
+ } // if password == "*"
+
+ // Got a good one!
+
+ if ( ! RunAsInteractiveUser )
+ {
+ MultiByteToWideChar( CP_ACP,
+ MB_PRECOMPOSED,
+ ClsidInfo->RunAsPassword,
+ -1,
+ wszPassword,
+ sizeof(wszPassword)/2 );
+
+ LsaData.Length = (lstrlenW(wszPassword) + 1) * sizeof(WCHAR);
+ LsaData.MaximumLength = sizeof(wszPassword);
+ LsaData.Buffer = wszPassword;
+
+ // Store private data
+ NtStatus = LsaStorePrivateData( hPolicy, &LsaKey, &LsaData );
+
+ if ( ! NT_SUCCESS(NtStatus) )
+ {
+ printf( "Could not store password securely (0x%x)\n", NtStatus );
+ return;
+ }
+
+ LsaClose(hPolicy);
+ }
+ }
+ }
+
+ printf( "CLSID keys updated successfully.\n" );
+}
+
+BOOL SetClsidKey(
+ HKEY hClsid,
+ char * Clsid,
+ const char * Key,
+ char * Value )
+{
+ HKEY hKey;
+ DWORD RegStatus;
+ DWORD Disposition;
+ DWORD ValueType;
+ DWORD ValueSize;
+ char OldValue[256];
+ BOOL HasOldValue;
+
+ HasOldValue = FALSE;
+
+ RegStatus = RegCreateKeyEx(
+ hClsid,
+ Key,
+ 0,
+ "REG_SZ",
+ REG_OPTION_NON_VOLATILE,
+ KEY_READ | KEY_WRITE,
+ NULL,
+ &hKey,
+ &Disposition );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Could not create key %s for CLSID %s\n", Key, Clsid );
+ return FALSE;
+ }
+
+ if ( Disposition == REG_CREATED_NEW_KEY )
+ {
+ printf( "Added key %s for CLSID %s\n", Key, Clsid );
+ }
+ else
+ {
+ ValueSize = sizeof(OldValue);
+
+ RegStatus = RegQueryValueEx(
+ hKey,
+ NULL,
+ 0,
+ &ValueType,
+ OldValue,
+ &ValueSize );
+
+ HasOldValue = (RegStatus == ERROR_SUCCESS);
+ }
+
+ if ( ! Value )
+ return TRUE;
+
+ RegStatus = RegSetValueEx(
+ hKey,
+ NULL,
+ 0,
+ REG_SZ,
+ (LPBYTE) Value,
+ strlen(Value) + sizeof(char) );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Could not set value %s for key %s\n", Value, Key );
+ return FALSE;
+ }
+
+ if ( HasOldValue )
+ printf( "Changed value from %s to %s for key %s\n", OldValue, Value, Key );
+ else
+ printf( "Added value %s for key %s\n", Value, Key );
+
+ return TRUE;
+}
+
+BOOL DeleteClsidKey(
+ HKEY hClsid,
+ char * Clsid,
+ const char * Key )
+{
+ DWORD RegStatus;
+
+ RegStatus = RegDeleteKey( hClsid, Key );
+
+ if ( RegStatus != ERROR_SUCCESS )
+ {
+ printf( "Could not delete key %s for CLSID %s\n", Key, Clsid );
+ return FALSE;
+ }
+
+ printf( "Deleted key %s for CLSID %s\n", Key, Clsid );
+ return TRUE;
+}
+
+void ReadPassword( char * Password )
+{
+ int c, n;
+
+ n = 0;
+
+ for (;;)
+ {
+ c = _getch();
+
+ // ^C
+ if ( c == 0x3 )
+ {
+ putchar( '\n' );
+ ExitProcess( 0 );
+ }
+
+ // Backspace
+ if ( c == 0x8 )
+ {
+ if ( n )
+ {
+ n--;
+ _putch( 0x8 );
+ _putch( ' ' );
+ _putch( 0x8 );
+ }
+ continue;
+ }
+
+ // Return
+ if ( c == '\r' )
+ break;
+
+ Password[n++] = c;
+ _putch( '*' );
+ }
+
+ Password[n] = 0;
+ putchar( '\n' );
+}
+
+BOOL ControlCConsoleHandler( DWORD ControlType )
+{
+ if ( (ControlType == CTRL_C_EVENT) || (ControlType == CTRL_BREAK_EVENT) )
+ {
+ printf( "RunAs password unchanged\n" );
+ ExitProcess( 0 );
+ }
+
+ return FALSE;
+}
+
+
diff --git a/private/ole32/olecnfg/olecnfg.h b/private/ole32/olecnfg/olecnfg.h
new file mode 100644
index 000000000..e7ff03f34
--- /dev/null
+++ b/private/ole32/olecnfg/olecnfg.h
@@ -0,0 +1,121 @@
+//
+//
+//
+
+#ifndef _OLECONFIG_
+#define _OLECONFIG_
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntlsa.h>
+#include <windows.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <conio.h>
+
+#define ENABLE_NETWORK_OLE 1
+#define DEFAULT_LAUNCH_PERMISSION 2
+#define DEFAULT_ACCESS_PERMISSION 3
+#define LEGACY_AUTHENTICATION_LEVEL 4
+
+#define GLOBAL_KEYS 4
+
+#define MERGE 101
+#define SAVE_USER 102
+#define SAVE_COMMON 103
+
+#define GLOBAL_OPERATIONS 103
+
+#define INPROC_HANDLER32 1
+#define INPROC_SERVER32 2
+#define LOCAL_SERVER32 3
+#define LOCAL_SERVICE 4
+#define REMOTE_SERVER_NAME 5
+#define RUN_AS 6
+#define ACTIVATE_AT_STORAGE 7
+#define LAUNCH_PERMISSION 8
+#define ACCESS_PERMISSION 9
+
+#define CLSID_KEYS 9
+#define CLSID_PATH_KEYS 4
+
+#define UNKNOWN 0
+#define END_OF_ARGS -1
+
+#define INVALID -1
+#define NO 1
+#define YES 2
+
+#define EAT_ARG() Args++; ArgsLeft--;
+
+typedef struct
+ {
+ char * Clsid;
+ char * ClsidDescription;
+ char * ProgId;
+ char * ProgIdDescription;
+
+ int LaunchPermission;
+ int AccessPermission;
+ int ActivateAtStorage;
+
+ char * ServerPaths[CLSID_PATH_KEYS+1];
+ char * RemoteServerName;
+ char * RunAsUserName;
+ char * RunAsPassword;
+ } CLSID_INFO;
+
+extern const char * GlobalKeyNames[];
+extern const char * ClsidKeyNames[];
+
+extern int ArgsLeft;
+extern char ** Args;
+extern char * ProgramName;
+
+extern HKEY hRegOle;
+extern HKEY hRegClsid;
+
+// main.c
+void ParseClsidProgId();
+int NextClsidKey();
+int ReadYesOrNo();
+void DisplayHelp();
+
+// oleconfig.c
+BOOL SetGlobalKey(
+ int Key,
+ int Value );
+
+void DisplayGlobalSettings();
+
+void DisplayClsidKeys(
+ CLSID_INFO * ClsidInfo );
+
+void UpdateClsidKeys(
+ CLSID_INFO * ClsidInfo );
+
+BOOL SetClsidKey(
+ HKEY hClsid,
+ char * Clsid,
+ const char * Key,
+ char * Value );
+
+BOOL DeleteClsidKey(
+ HKEY hClsid,
+ char * Clsid,
+ const char * Key );
+
+void ReadPassword(
+ char * Password );
+
+BOOL ControlCConsoleHandler(
+ DWORD ControlType );
+
+void MergeHives( );
+
+void SaveChangesToUser( );
+
+void SaveChangesToCommon( );
+
+#endif
diff --git a/private/ole32/olecnfg/olecnfg.rc b/private/ole32/olecnfg/olecnfg.rc
new file mode 100644
index 000000000..5dbcc8a3a
--- /dev/null
+++ b/private/ole32/olecnfg/olecnfg.rc
@@ -0,0 +1,50 @@
+#include <windows.h>
+#include <winver.h>
+
+#define VER_FILEVERSION_STR "4.0\0"
+#define VER_FILEVERSION 4,0000,0001,0001
+
+#define VER_PRODUCTNAME_STR "Microsoft OLE 4.0 for Windows NT(TM) Operating System\0"
+#define VER_COMPANYNAME_STR "Microsoft Corporation\0"
+#define VER_LEGALTRADEMARKS_STR "Microsoft(TM) is a registered trademark of Microsoft Corporation. Windows NT(TM) is a trademark of Microsoft Corporation\0"
+#define VER_LEGALCOPYRIGHT_STR "Copyright (C) Microsoft Corp. 1992 - 1996\0"
+#define VER_PRODUCTVERSION_STR "4.0\0"
+#define VER_PRODUCTVERSION 4,0000,001,0001
+#define VER_COMMENT_STR "Microsoft OLE 4.0 for Windows NT(TM) Operating System\0"
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE 0
+#define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#define VER_FILEFLAGS 0L
+#define VER_FILEOS VOS_NT_WINDOWS32
+#define VER_FILEDESCRIPTION_STR "Microsoft OLE 4.0 for Windows NT(TM) Operating System\0"
+
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION VER_FILEVERSION
+PRODUCTVERSION VER_PRODUCTVERSION
+FILEFLAGSMASK VER_FILEFLAGSMASK
+FILEFLAGS VER_FILEFLAGS
+FILEOS VER_FILEOS
+FILETYPE VFT_APP
+FILESUBTYPE VER_FILESUBTYPE
+{
+ BLOCK "StringFileInfo"
+ {
+ BLOCK "040904E4"
+ {
+ VALUE "CompanyName", VER_COMPANYNAME_STR
+ VALUE "FileDescription", VER_FILEDESCRIPTION_STR
+ VALUE "FileVersion", VER_FILEVERSION_STR
+ VALUE "InternalName", "OLECNFG.EXE\0"
+ VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
+ VALUE "LegalTrademarks", VER_LEGALTRADEMARKS_STR
+ VALUE "ProductName", VER_PRODUCTNAME_STR
+ VALUE "ProductVersion", VER_PRODUCTVERSION_STR
+ VALUE "Comments", VER_COMMENT_STR
+ }
+ }
+ BLOCK "VarFileInfo"
+ {
+ VALUE "Translation", 0x409, 1252
+ }
+}
diff --git a/private/ole32/olecnfg/sid.c b/private/ole32/olecnfg/sid.c
new file mode 100644
index 000000000..435df4654
--- /dev/null
+++ b/private/ole32/olecnfg/sid.c
@@ -0,0 +1,255 @@
+//*************************************************************
+//
+// SID management functions.
+//
+// THESE FUNCTIONS ARE WINDOWS NT SPECIFIC!!!!!
+//
+// Microsoft Confidential
+// Copyright (c) Microsoft Corporation 1995
+// All rights reserved
+//
+//*************************************************************
+
+#include "uenv.h"
+
+LPTSTR GetSidString(HANDLE UserToken);
+VOID DeleteSidString(LPTSTR SidString);
+PSID GetUserSid (HANDLE UserToken);
+VOID DeleteUserSid(PSID Sid);
+
+#define DebugMsg(x)
+
+/***************************************************************************\
+* GetSidString
+*
+* Allocates and returns a string representing the sid of the current user
+* The returned pointer should be freed using DeleteSidString().
+*
+* Returns a pointer to the string or NULL on failure.
+*
+* History:
+* 26-Aug-92 Davidc Created
+*
+\***************************************************************************/
+LPTSTR GetSidString(HANDLE UserToken)
+{
+ NTSTATUS NtStatus;
+ PSID UserSid;
+ UNICODE_STRING UnicodeString;
+#ifndef UNICODE
+ STRING String;
+#endif
+
+ //
+ // Get the user sid
+ //
+
+ UserSid = GetUserSid(UserToken);
+ if (UserSid == NULL) {
+ DebugMsg((DM_WARNING, TEXT("GetSidString: GetUserSid returned NULL")));
+ return NULL;
+ }
+
+ //
+ // Convert user SID to a string.
+ //
+
+ NtStatus = RtlConvertSidToUnicodeString(
+ &UnicodeString,
+ UserSid,
+ (BOOLEAN)TRUE // Allocate
+ );
+ //
+ // We're finished with the user sid
+ //
+
+ DeleteUserSid(UserSid);
+
+ //
+ // See if the conversion to a string worked
+ //
+
+ if (!NT_SUCCESS(NtStatus)) {
+ DebugMsg((DM_WARNING, TEXT("GetSidString: RtlConvertSidToUnicodeString failed, status = 0x%x"),
+ NtStatus));
+ return NULL;
+ }
+
+#ifdef UNICODE
+
+
+ return(UnicodeString.Buffer);
+
+#else
+
+ //
+ // Convert the string to ansi
+ //
+
+ NtStatus = RtlUnicodeStringToAnsiString(&String, &UnicodeString, TRUE);
+ RtlFreeUnicodeString(&UnicodeString);
+ if (!NT_SUCCESS(NtStatus)) {
+ DebugMsg((DM_WARNING, TEXT("GetSidString: RtlUnicodeStringToAnsiString failed, status = 0x%x"),
+ status));
+ return NULL;
+ }
+
+
+ return(String.Buffer);
+
+#endif
+
+}
+
+
+/***************************************************************************\
+* DeleteSidString
+*
+* Frees up a sid string previously returned by GetSidString()
+*
+* Returns nothing.
+*
+* History:
+* 26-Aug-92 Davidc Created
+*
+\***************************************************************************/
+VOID DeleteSidString(LPTSTR SidString)
+{
+
+#ifdef UNICODE
+ UNICODE_STRING String;
+
+ RtlInitUnicodeString(&String, SidString);
+
+ RtlFreeUnicodeString(&String);
+#else
+ ANSI_STRING String;
+
+ RtlInitAnsiString(&String, SidString);
+
+ RtlFreeAnsiString(&String);
+#endif
+
+}
+
+
+
+/***************************************************************************\
+* GetUserSid
+*
+* Allocs space for the user sid, fills it in and returns a pointer. Caller
+* The sid should be freed by calling DeleteUserSid.
+*
+* Note the sid returned is the user's real sid, not the per-logon sid.
+*
+* Returns pointer to sid or NULL on failure.
+*
+* History:
+* 26-Aug-92 Davidc Created.
+\***************************************************************************/
+PSID GetUserSid (HANDLE UserToken)
+{
+ PTOKEN_USER pUser;
+ PSID pSid;
+ DWORD BytesRequired = 200;
+ NTSTATUS status;
+
+
+ //
+ // Allocate space for the user info
+ //
+
+ pUser = (PTOKEN_USER)LocalAlloc(LMEM_FIXED, BytesRequired);
+
+
+ if (pUser == NULL) {
+ DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to allocate %d bytes"),
+ BytesRequired));
+ return NULL;
+ }
+
+
+ //
+ // Read in the UserInfo
+ //
+
+ status = NtQueryInformationToken(
+ UserToken, // Handle
+ TokenUser, // TokenInformationClass
+ pUser, // TokenInformation
+ BytesRequired, // TokenInformationLength
+ &BytesRequired // ReturnLength
+ );
+
+ if (status == STATUS_BUFFER_TOO_SMALL) {
+
+ //
+ // Allocate a bigger buffer and try again.
+ //
+
+ pUser = LocalReAlloc(pUser, BytesRequired, LMEM_MOVEABLE);
+ if (pUser == NULL) {
+ DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to allocate %d bytes"),
+ BytesRequired));
+ return NULL;
+ }
+
+ status = NtQueryInformationToken(
+ UserToken, // Handle
+ TokenUser, // TokenInformationClass
+ pUser, // TokenInformation
+ BytesRequired, // TokenInformationLength
+ &BytesRequired // ReturnLength
+ );
+
+ }
+
+ if (!NT_SUCCESS(status)) {
+ DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to query user info from user token, status = 0x%x"),
+ status));
+ LocalFree(pUser);
+ return NULL;
+ }
+
+
+ BytesRequired = RtlLengthSid(pUser->User.Sid);
+ pSid = LocalAlloc(LMEM_FIXED, BytesRequired);
+ if (pSid == NULL) {
+ DebugMsg((DM_WARNING, TEXT("GetUserSid: Failed to allocate %d bytes"),
+ BytesRequired));
+ LocalFree(pUser);
+ return NULL;
+ }
+
+
+ status = RtlCopySid(BytesRequired, pSid, pUser->User.Sid);
+
+ LocalFree(pUser);
+
+ if (!NT_SUCCESS(status)) {
+ DebugMsg((DM_WARNING, TEXT("GetUserSid: RtlCopySid Failed. status = %d"),
+ status));
+ LocalFree(pSid);
+ pSid = NULL;
+ }
+
+
+ return pSid;
+}
+
+
+/***************************************************************************\
+* DeleteUserSid
+*
+* Deletes a user sid previously returned by GetUserSid()
+*
+* Returns nothing.
+*
+* History:
+* 26-Aug-92 Davidc Created
+*
+\***************************************************************************/
+VOID DeleteUserSid(PSID Sid)
+{
+ LocalFree(Sid);
+}
diff --git a/private/ole32/olecnfg/sources b/private/ole32/olecnfg/sources
new file mode 100644
index 000000000..2a1675c5b
--- /dev/null
+++ b/private/ole32/olecnfg/sources
@@ -0,0 +1,74 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1989
+
+
+Revision History:
+
+!ENDIF
+
+#
+# The TARGETNAME variable is defined by the developer. It is the name of
+# the target (component) that is being built by this makefile. It
+# should NOT include any path or file extension information.
+#
+
+TARGETNAME=olecnfg
+
+#
+# The TARGETPATH and TARGETTYPE varialbes are defined by the developer.
+# The first specifies where the target is to be build. The second specifies
+# the type of target (either PROGRAM, DYNLINK or LIBRARY)
+#
+
+TARGETPATH=.
+TARGETTYPE=PROGRAM
+
+#
+# The INCLUDES variable specifies any include paths that are specific to
+# this source directory. Separate multiple directory paths with single
+# semicolons. Relative path specifications are okay.
+#
+
+INCLUDES=.
+
+#
+# The SOURCES variable is defined by the developer. It is a list of all the
+# source files for this component. Each source file should be on a separate
+# line using the line continuation character. This will minimize merge
+# conflicts if two developers adding source files to the same component.
+#
+
+SOURCES=\
+ main.c \
+ treemgmt.c \
+ clshive.c \
+ sid.c \
+ olecnfg.c \
+ olecnfg.rc
+
+# C_DEFINES=
+
+LINKLIBS=\
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib
+
+UMTYPE=console
diff --git a/private/ole32/olecnfg/treemgmt.c b/private/ole32/olecnfg/treemgmt.c
new file mode 100644
index 000000000..761c293b0
--- /dev/null
+++ b/private/ole32/olecnfg/treemgmt.c
@@ -0,0 +1,882 @@
+//*************************************************************
+//
+// Personal Classes Profile management routines
+//
+// Microsoft Confidential
+// Copyright (c) Microsoft Corporation 1995
+// All rights reserved
+//
+//*************************************************************
+
+#include "uenv.h"
+#include "windows.h"
+
+// Local Data Structures
+
+LPTSTR SpecialSubtrees[] =
+ {
+ TEXT("CLSID"),
+ TEXT("Interface"),
+ TEXT("TypeLib"),
+ TEXT("Licenses"),
+ TEXT("FileType")
+ };
+
+#define MAX_SPECIAL_SUBTREE (sizeof(SpecialSubtrees)/sizeof(LPTSTR))
+//
+// Local function proto-types
+//
+typedef struct _RegKeyInfo {
+ DWORD SubKeyCount;
+ DWORD MaxSubKeyLen;
+ DWORD ValueCount;
+ DWORD MaxValueNameLen;
+ DWORD MaxValueLen;
+ DWORD SDLen;
+ LPTSTR pSubKeyName;
+ LPTSTR pValueName;
+ LPTSTR pValue;
+ } REGKEYINFO, *PREGKEYINFO;
+
+//*************************************************************
+//
+// PrepForEnumRegistryTree()
+//
+// Purpose: prepare to duplicate a source bunch of keys into the destination.
+//
+// Parameters: hkSourceTree - source registry tree
+// pRegKeyInfo - info block for use doing enumeration
+//
+// Return: TRUE if successful
+// FALSE if an error occurs
+//
+// History: Date Author Comment
+// 1/30/96 GregJen Created
+//
+//*************************************************************
+BOOL
+PrepForEnumRegistryTree(
+ HKEY hkSourceTree,
+ PREGKEYINFO pRegKeyInfo
+ )
+{
+ LPTSTR pStringsBuffer;
+ LONG result;
+
+ result = RegQueryInfoKey(hkSourceTree,
+ NULL,
+ NULL,
+ 0,
+ &pRegKeyInfo->SubKeyCount,
+ &pRegKeyInfo->MaxSubKeyLen,
+ NULL,
+ &pRegKeyInfo->ValueCount,
+ &pRegKeyInfo->MaxValueNameLen,
+ &pRegKeyInfo->MaxValueLen,
+ &pRegKeyInfo->SDLen,
+ NULL);
+
+ if ( result != ERROR_SUCCESS )
+ return FALSE;
+
+ // allocate a block of memory to use for enumerating subkeys and values
+ pStringsBuffer = (LPTSTR) LocalAlloc( LPTR,
+ (pRegKeyInfo->MaxSubKeyLen +
+ pRegKeyInfo->MaxValueNameLen +
+ pRegKeyInfo->MaxValueLen + 3)
+ * sizeof( TCHAR ) );
+ if ( !pStringsBuffer )
+ return FALSE;
+
+ pRegKeyInfo->pSubKeyName = pStringsBuffer;
+ pRegKeyInfo->pValueName = pStringsBuffer + pRegKeyInfo->MaxSubKeyLen + 1;
+ pRegKeyInfo->pValue = pRegKeyInfo->pValueName +
+ pRegKeyInfo->MaxValueNameLen + 1;
+
+}
+
+//*************************************************************
+//
+// CleanupAfterEnumRegistryTree()
+//
+// Purpose: duplicate a source bunch of keys into the destination.
+//
+// Parameters: hkSourceTree - source registry tree
+// pRegKeyInfo - info block for use doing enumeration
+//
+// Return: TRUE if successful
+// FALSE if an error occurs
+//
+// History: Date Author Comment
+// 1/30/96 GregJen Created
+//
+//*************************************************************
+void
+CleanupAfterEnumRegistryTree(
+ HKEY hkSourceTree,
+ PREGKEYINFO pRegKeyInfo)
+{
+ LocalFree( pRegKeyInfo->pSubKeyName );
+}
+BOOL
+DeleteRegistrySubtree (
+ HKEY hkTree )
+{
+ HKEY hkCurrentSourceKey;
+ DWORD idx;
+ DWORD NameLen;
+ LONG result = ERROR_SUCCESS;
+ REGKEYINFO RegKeyInfo;
+ BOOL Success = FALSE;
+
+ if ( !PrepForEnumRegistryTree( hkTree, &RegKeyInfo ) )
+ return FALSE; // nothing to clean up here yet
+
+ // enumerate all the source subkeys
+ // for each: if dest subkey is older than source, delete it
+ // if dest subkey does not exist (or was deleted) clone the subkey
+ //
+ // Clone all the subkeys
+ //
+ for ( idx = 0;
+ (result == ERROR_SUCCESS) &&
+ ( result != ERROR_MORE_DATA ) &&
+ ( idx < RegKeyInfo.SubKeyCount );
+ idx++ ) {
+ NameLen = RegKeyInfo.MaxSubKeyLen + sizeof( TCHAR );
+ result = RegEnumKeyEx( hkTree,
+ idx,
+ RegKeyInfo.pSubKeyName,
+ &NameLen,
+ NULL,
+ NULL,
+ NULL,
+ NULL );
+
+ if ( ( result != ERROR_SUCCESS ) && ( result != ERROR_MORE_DATA ) )
+ goto cleanup;
+
+ // TBD: open the subkey in the source tree AS CurrentSourceKey
+ result = RegOpenKeyEx(hkTree,
+ RegKeyInfo.pSubKeyName,
+ 0,
+ KEY_ALL_ACCESS,
+ &hkCurrentSourceKey);
+
+ DeleteRegistrySubtree( hkCurrentSourceKey );
+
+ RegCloseKey( hkCurrentSourceKey );
+
+ RegDeleteKey( hkTree, RegKeyInfo.pSubKeyName );
+
+ result = ERROR_SUCCESS;
+ }
+
+cleanup:
+ CleanupAfterEnumRegistryTree( hkTree, &RegKeyInfo );
+
+ return TRUE;
+}
+
+//*************************************************************
+//
+// CloneRegistryValues()
+//
+// Purpose: copy the values from under the source key to the dest key
+//
+// Parameters: SourceTree - source registry tree
+// DestinationTree - destintation registry tree
+// RegKeyInfo - handy information from the RegEnumKeyEx call.
+//
+// Return: TRUE if successful
+// FALSE if an error occurs
+//
+// History: Date Author Comment
+// 1/14/96 GregJen Created
+//
+//*************************************************************
+BOOL
+CloneRegistryValues(
+ HKEY hkSourceTree,
+ HKEY hkDestinationTree,
+ REGKEYINFO RegKeyInfo )
+{
+ LONG result = ERROR_SUCCESS;
+ DWORD idx;
+ DWORD ValueLen;
+ DWORD ValueType;
+ DWORD DataLen;
+
+ for ( idx = 0;
+ (result == ERROR_SUCCESS) &&
+ ( result != ERROR_MORE_DATA ) &&
+ ( idx < RegKeyInfo.ValueCount );
+ idx++ )
+ {
+ DataLen = RegKeyInfo.MaxValueLen + sizeof( TCHAR );
+ ValueLen = RegKeyInfo.MaxValueNameLen + sizeof( TCHAR );
+
+ result = RegEnumValue( hkSourceTree,
+ idx,
+ RegKeyInfo.pValueName,
+ &ValueLen,
+ NULL,
+ &ValueType,
+ (BYTE*) RegKeyInfo.pValue,
+ &DataLen);
+
+ // TBD: check errors
+
+ // now add the value to the destination key
+
+ result = RegSetValueEx( hkDestinationTree,
+ RegKeyInfo.pValueName,
+ 0,
+ ValueType,
+ (BYTE*) RegKeyInfo.pValue,
+ DataLen );
+ // TBD: check errors
+ }
+ return TRUE;
+}
+//*************************************************************
+//
+// CloneRegistryTree()
+//
+// Purpose: duplicate a source bunch of keys into the destination.
+//
+// Parameters: SourceTree - source registry tree
+// DestinationTree - destintation registry tree
+// lpSubKeyName - if present this is a subkey name that
+// corresponds to the SourceTree HKEY.
+//
+// Return: TRUE if successful
+// FALSE if an error occurs
+//
+// History: Date Author Comment
+// 1/14/96 GregJen Created
+//
+//*************************************************************
+BOOL
+CloneRegistryTree(
+ HKEY hkSourceTree,
+ HKEY hkDestinationTree,
+ LPTSTR lpDestTreeName )
+{
+ HKEY hkCurrentSourceKey;
+ DWORD idx;
+ DWORD NameLen;
+ LONG result = ERROR_SUCCESS;
+ REGKEYINFO RegKeyInfo;
+ BOOL Success = FALSE;
+
+ if ( !PrepForEnumRegistryTree( hkSourceTree, &RegKeyInfo ) )
+ return FALSE; // nothing to clean up here yet
+
+ if ( lpDestTreeName ) {
+ HKEY hkNewKey;
+ DWORD dwSDLen = RegKeyInfo.SDLen;
+ DWORD dwDisp;
+ SECURITY_INFORMATION SI = DACL_SECURITY_INFORMATION; // for now...
+ PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR)
+ LocalAlloc( LPTR, dwSDLen );
+ // TBD: check for NULL;
+
+ // Get the registry security information from the old key
+ result = RegGetKeySecurity( hkSourceTree,
+ SI,
+ pSD,
+ &dwSDLen);
+ // TBD: check for errors, free pSD
+ // create a key with the given name, and registry info
+ result = RegCreateKeyEx( hkDestinationTree,
+ lpDestTreeName,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ pSD,
+ &hkNewKey,
+ &dwDisp );
+ // TBD: check for errors, free pSD
+
+ // TBD: and update the hkDestinationTree variable to point to it
+
+ hkDestinationTree = hkNewKey;
+ LocalFree( pSD );
+ }
+
+ //
+ // clone the values
+ //
+
+ if ( ! CloneRegistryValues( hkSourceTree, hkDestinationTree, RegKeyInfo ) )
+ goto cleanup;
+
+ //
+ // Clone all the subkeys
+ //
+ for ( idx = 0;
+ (result == ERROR_SUCCESS) &&
+ ( result != ERROR_MORE_DATA ) &&
+ ( idx < RegKeyInfo.SubKeyCount );
+ idx++ ) {
+ NameLen = RegKeyInfo.MaxSubKeyLen + sizeof( TCHAR );
+ result = RegEnumKeyEx( hkSourceTree,
+ idx,
+ RegKeyInfo.pSubKeyName,
+ &NameLen,
+ NULL,
+ NULL,
+ NULL,
+ NULL );
+
+ if ( ( result != ERROR_SUCCESS ) && ( result != ERROR_MORE_DATA ) )
+ goto cleanup;
+
+ // TBD: open the subkey in the source tree AS CurrentSourceKey
+ result = RegOpenKeyEx(hkSourceTree,
+ RegKeyInfo.pSubKeyName,
+ 0,
+ KEY_READ,
+ &hkCurrentSourceKey);
+
+ //
+ // recurse passing the subkey name
+ //
+ CloneRegistryTree( hkCurrentSourceKey,
+ hkDestinationTree,
+ RegKeyInfo.pSubKeyName );
+
+ //
+ // close our open key
+ //
+
+ RegCloseKey( hkCurrentSourceKey );
+ }
+
+ Success = TRUE;
+
+cleanup:
+ if ( lpDestTreeName )
+ {
+ RegCloseKey( hkDestinationTree );
+ }
+
+ CleanupAfterEnumRegistryTree( hkSourceTree, &RegKeyInfo );
+
+ return Success;
+}
+
+// TBD: dummy prototypes for now
+// dummy testing code
+void TestCloneHive( )
+{
+ // for testing
+ HKEY hkSource;
+ HKEY hkDestination;
+ LONG result;
+
+ result =
+ RegOpenKeyEx(HKEY_CLASSES_ROOT,
+ TEXT(".pps"),
+ 0,
+ KEY_READ,
+ &hkSource);
+ result =
+ RegOpenKeyEx(HKEY_CLASSES_ROOT,
+ TEXT(".paa"),
+ 0,
+ KEY_ALL_ACCESS,
+ &hkDestination);
+ CloneRegistryTree(hkSource, hkDestination, NULL);
+}
+
+void SaveChangesToUser( )
+{
+}
+
+void SaveChangesToCommon( )
+{
+}
+
+BOOL
+AddSharedValuesToSubkeys( HKEY hkShared, LPTSTR pszSubtree )
+{
+ HKEY hkSourceKey;
+ HKEY hkCurrentSourceKey;
+ DWORD idx;
+ DWORD NameLen;
+ LONG result = ERROR_SUCCESS;
+ REGKEYINFO RegKeyInfo;
+ BOOL Success = FALSE;
+
+
+ // for every subkey, set "Shared" value
+ result = RegOpenKeyEx( hkShared,
+ pszSubtree,
+ 0,
+ KEY_READ,
+ &hkSourceKey );
+
+ // TBD: if no subtree in source, skip ahead to next special subtree
+ if ( result == ERROR_FILE_NOT_FOUND )
+ return TRUE;
+
+ if ( !PrepForEnumRegistryTree( hkSourceKey, &RegKeyInfo ) )
+ goto cleanup2;
+
+ // enumerate all the source subkeys
+ // for each: if dest subkey is older than source, delete it
+ // if dest subkey does not exist (or was deleted) clone the subkey
+ //
+ // Clone all the subkeys
+ //
+ for ( idx = 0;
+ (result == ERROR_SUCCESS) &&
+ ( result != ERROR_MORE_DATA ) &&
+ ( idx < RegKeyInfo.SubKeyCount );
+ idx++ )
+ {
+ NameLen = RegKeyInfo.MaxSubKeyLen + sizeof( TCHAR );
+ result = RegEnumKeyEx( hkSourceKey,
+ idx,
+ RegKeyInfo.pSubKeyName,
+ &NameLen,
+ NULL,
+ NULL,
+ NULL,
+ NULL );
+
+ if ( ( result != ERROR_SUCCESS ) && ( result != ERROR_MORE_DATA ) )
+ goto cleanup;
+
+ result = RegOpenKeyEx( hkSourceKey,
+ RegKeyInfo.pSubKeyName,
+ 0,
+ KEY_ALL_ACCESS,
+ &hkCurrentSourceKey );
+
+ // check for errors
+
+ result = RegSetValueEx( hkCurrentSourceKey,
+ L"Shared",
+ 0,
+ REG_SZ,
+ (LPBYTE) L"Y",
+ sizeof( L"Y" ) );
+
+ RegCloseKey( hkCurrentSourceKey );
+
+ }
+
+ Success = TRUE;
+
+cleanup:
+ CleanupAfterEnumRegistryTree( hkSourceKey, &RegKeyInfo );
+
+cleanup2:
+ RegCloseKey( hkSourceKey );
+
+ return Success;
+
+}
+
+BOOL
+AddSharedValues( HKEY hkShared )
+{
+ // for each of the special subtrees, add "Shared" values
+ int idx;
+
+ // now, for each of the special top-level keys, process the level below them
+ // these keys are: CLSID, Interface, TypeLib, Licenses, FileType
+
+ for ( idx = 0; idx < MAX_SPECIAL_SUBTREE; idx++ )
+ {
+ AddSharedValuesToSubkeys( hkShared, SpecialSubtrees[idx] );
+ }
+
+ // now do all the top level keys (file extensions and progids)
+ AddSharedValuesToSubkeys( hkShared, NULL );
+
+ return TRUE;
+}
+
+
+//*************************************************************
+//
+// MergeUserClasses()
+//
+// Purpose: Merges the user's class information with the
+// common class information.
+//
+// Parameters: UserClassStore - Per-user class information
+// CommonClassStore - Machine-wide class information
+// MergedClassStore - Destination for merged information.
+//
+// Return: TRUE if successful
+// FALSE if an error occurs
+//
+// Comments: UserClassStore may be a null HKEY, implying
+// just copy the information from the common
+// portion into the merged portion
+//
+// History: Date Author Comment
+// 1/14/96 GregJen Created
+//
+//*************************************************************
+BOOL
+MergeRegistrySubKeys (
+ HKEY hkSourceTree,
+ HKEY hkDestTree )
+{
+ HKEY hkCurrentSourceKey;
+ HKEY hkCurrentDestKey;
+ DWORD idx;
+ DWORD NameLen;
+ LONG result = ERROR_SUCCESS;
+ REGKEYINFO RegKeyInfo;
+ BOOL Success = FALSE;
+ FILETIME SourceFileTime;
+ FILETIME DestFileTime;
+ LONG cmp;
+
+ if ( !PrepForEnumRegistryTree( hkSourceTree, &RegKeyInfo ) )
+ return FALSE; // nothing to clean up here yet
+
+ // enumerate all the source subkeys
+ // for each: if dest subkey is older than source, delete it
+ // if dest subkey does not exist (or was deleted) clone the subkey
+ //
+ // Clone all the subkeys
+ //
+ for ( idx = 0;
+ (result == ERROR_SUCCESS) &&
+ ( result != ERROR_MORE_DATA ) &&
+ ( idx < RegKeyInfo.SubKeyCount );
+ idx++ ) {
+ NameLen = RegKeyInfo.MaxSubKeyLen + sizeof( TCHAR );
+ result = RegEnumKeyEx( hkSourceTree,
+ idx,
+ RegKeyInfo.pSubKeyName,
+ &NameLen,
+ NULL,
+ NULL,
+ NULL,
+ &SourceFileTime );
+
+ if ( ( result != ERROR_SUCCESS ) && ( result != ERROR_MORE_DATA ) )
+ goto cleanup;
+
+ // TBD: open the subkey in the source tree AS CurrentSourceKey
+ result = RegOpenKeyEx(hkSourceTree,
+ RegKeyInfo.pSubKeyName,
+ 0,
+ KEY_READ,
+ &hkCurrentSourceKey);
+
+
+ result = RegOpenKeyEx(hkDestTree,
+ RegKeyInfo.pSubKeyName,
+ 0,
+ KEY_READ,
+ &hkCurrentDestKey);
+
+ // if current dest key does not exist,
+ if ( result == ERROR_FILE_NOT_FOUND )
+ {
+ //
+ // recurse passing the subkey name
+ //
+ CloneRegistryTree( hkCurrentSourceKey,
+ hkDestTree,
+ RegKeyInfo.pSubKeyName );
+ }
+ // if current dest key is older than current source key, delete dest
+ // then recreate new
+ else
+ {
+ RegQueryInfoKey( hkCurrentDestKey,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &DestFileTime );
+
+
+ cmp = CompareFileTime( &SourceFileTime, &DestFileTime );
+ if ( cmp > 0 )
+ {
+ // delete dest
+ //
+ DeleteRegistrySubtree( hkCurrentDestKey );
+
+ //
+ // recurse passing the subkey name
+ //
+ CloneRegistryTree( hkCurrentSourceKey,
+ hkDestTree,
+ RegKeyInfo.pSubKeyName );
+ }
+ }
+
+ //
+ // close our open key
+ //
+
+ RegCloseKey( hkCurrentSourceKey );
+
+ result = ERROR_SUCCESS;
+ }
+
+cleanup:
+ CleanupAfterEnumRegistryTree( hkSourceTree, &RegKeyInfo );
+
+ return TRUE;
+}
+
+
+
+
+//*************************************************************
+//
+// MergeUserClasses()
+//
+// Purpose: Merges the user's class information with the
+// common class information.
+//
+// Parameters: UserClassStore - Per-user class information
+// CommonClassStore - Machine-wide class information
+// MergedClassStore - Destination for merged information.
+//
+// Return: TRUE if successful
+// FALSE if an error occurs
+//
+// Comments: UserClassStore may be a null HKEY, implying
+// just copy the information from the common
+// portion into the merged portion
+//
+// History: Date Author Comment
+// 1/14/96 GregJen Created
+//
+//*************************************************************
+BOOL
+MergeRegistrySubtree (
+ HKEY hkSourceParent,
+ HKEY hkDestParent,
+ LPTSTR pszSubtree )
+{
+ HKEY hkCurrentSourceKey;
+ HKEY hkCurrentDestKey;
+ LONG result;
+ DWORD dummy = 0;
+
+ // open the special subtree in the source tree
+ result = RegOpenKeyEx( hkSourceParent,
+ pszSubtree,
+ 0,
+ KEY_READ,
+ &hkCurrentSourceKey );
+
+ // TBD: if no subtree in source, skip ahead to next special subtree
+ if ( result == ERROR_FILE_NOT_FOUND )
+ return TRUE;
+
+ result = RegOpenKeyEx( hkDestParent,
+ pszSubtree,
+ 0,
+ KEY_ALL_ACCESS,
+ &hkCurrentDestKey );
+ // TBD: if no such subtree in dest, do CloneRegistry etc
+ if ( result == ERROR_FILE_NOT_FOUND )
+ {
+ //
+ // recurse passing the subkey name
+ //
+ CloneRegistryTree( hkCurrentSourceKey,
+ hkDestParent,
+ pszSubtree );
+ }
+ // TBD:if timestamp on source is newer than timestamp on dest,
+ // delete dest and recreate??
+
+ MergeRegistrySubKeys( hkCurrentSourceKey,
+ hkCurrentDestKey );
+
+ // make sure the timestamp on the special trees is updated
+ result = RegSetValueEx( hkCurrentDestKey,
+ TEXT("Updated"),
+ 0,
+ REG_DWORD,
+ (BYTE*) &dummy,
+ sizeof( DWORD ) );
+
+
+ // close special subtrees
+ RegCloseKey( hkCurrentSourceKey );
+ RegCloseKey( hkCurrentDestKey );
+
+ return TRUE;
+}
+
+long
+CompareRegistryTimes(
+ HKEY hkLHS,
+ HKEY hkRHS )
+{
+ FILETIME LHSTime;
+ FILETIME RHSTime;
+
+ RegQueryInfoKey( hkLHS,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &LHSTime );
+
+ RegQueryInfoKey( hkRHS,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &RHSTime );
+
+ return CompareFileTime( &LHSTime, &RHSTime );
+}
+
+//*************************************************************
+//
+// MergeUserClasses()
+//
+// Purpose: Merges the user's class information with the
+// common class information.
+//
+// Parameters: UserClassStore - Per-user class information
+// CommonClassStore - Machine-wide class information
+// MergedClassStore - Destination for merged information.
+//
+// Return: TRUE if successful
+// FALSE if an error occurs
+//
+// Comments: UserClassStore may be a null HKEY, implying
+// just copy the information from the common
+// portion into the merged portion
+//
+// History: Date Author Comment
+// 1/14/96 GregJen Created
+//
+//*************************************************************
+BOOL
+MergeUserClasses(
+ HKEY UserClassStore,
+ HKEY CommonClassStore,
+ HKEY MergedClassStore,
+ BOOL ForceNew )
+{
+ BOOL fNotCorrectUser = FALSE;
+ HKEY hkOverridingSubtree = CommonClassStore;
+ HKEY hkMergingSubtree = UserClassStore;
+ int idx;
+
+ //TBD: check time stamps on source and destination
+ // if same user, and timestamps are in sync, do nothing
+
+ // if destination does not belong to the current user, then
+ // delete everything under it
+
+ if ( fNotCorrectUser ) {
+ DeleteRegistrySubtree( MergedClassStore );
+ }
+
+
+ if ( !ForceNew &&
+ ( CompareRegistryTimes( MergedClassStore, CommonClassStore ) > 0 ) &&
+ ( CompareRegistryTimes( MergedClassStore, UserClassStore ) > 0 ) )
+ {
+ return TRUE;
+ }
+
+ // TBD: copy everything from the overriding store into the
+ // destination store
+ // At this moment, the common store overrides the user store;
+ // this will eventually reverse.
+
+ CloneRegistryTree( hkOverridingSubtree, MergedClassStore, NULL );
+
+ // now, for each of the special top-level keys, process the level below them
+ // these keys are: CLSID, Interface, TypeLib, Licenses, FileType
+
+ for ( idx = 0; idx < MAX_SPECIAL_SUBTREE; idx++ )
+ {
+ MergeRegistrySubtree( hkMergingSubtree,
+ MergedClassStore,
+ SpecialSubtrees[idx] );
+ }
+
+ // now do all the top level keys (file extensions and progids)
+ // TBD: MergeRegistrySubtree( UserClassStore, MergedClassStore );
+ MergeRegistrySubtree( hkMergingSubtree,
+ MergedClassStore,
+ NULL );
+
+return TRUE;
+}
+// dummy testing code
+void TestMergeHives( )
+{
+ // for testing
+ HKEY hkUser;
+ HKEY hkMachine;
+ HKEY hkMerged;
+ LONG result;
+ DWORD dwCreated;
+
+ result =
+ RegOpenKeyEx(HKEY_CLASSES_ROOT,
+ TEXT(".111111\\PerUser"),
+ 0,
+ KEY_READ,
+ &hkUser);
+ result =
+ RegOpenKeyEx(HKEY_CLASSES_ROOT,
+ TEXT(".111111\\MachineClasses"),
+ 0,
+ KEY_READ,
+ &hkMachine);
+ // note: eventually, this would be created with the
+ // same security as the per-user part.
+
+ // if the per-user part is missing, just copy the machine to per-user
+ //
+ result =
+ RegCreateKeyEx(HKEY_CLASSES_ROOT,
+ TEXT(".111111\\MergedClasses"),
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL,
+ &hkMerged,
+ &dwCreated);
+ MergeUserClasses(hkUser, hkMachine, hkMerged, TRUE);
+}
+
+
diff --git a/private/ole32/olecnfg/uenv.h b/private/ole32/olecnfg/uenv.h
new file mode 100644
index 000000000..f950563ca
--- /dev/null
+++ b/private/ole32/olecnfg/uenv.h
@@ -0,0 +1,26 @@
+//*************************************************************
+//
+// Personal Classes Profile management routines
+//
+// Microsoft Confidential
+// Copyright (c) Microsoft Corporation 1995
+// All rights reserved
+//
+//*************************************************************
+
+#define UNICODE 1
+
+#include "nt.h"
+#include "ntrtl.h"
+#include "nturtl.h"
+#include "windows.h"
+#include "userenv.h"
+
+LPTSTR GetSidString(HANDLE UserToken);
+VOID DeleteSidString(LPTSTR SidString);
+PSID GetUserSid (HANDLE UserToken);
+VOID DeleteUserSid(PSID Sid);
+
+
+
+
diff --git a/private/ole32/olecnv32/api.c b/private/ole32/olecnv32/api.c
new file mode 100644
index 000000000..27b63ea0b
--- /dev/null
+++ b/private/ole32/olecnv32/api.c
@@ -0,0 +1,499 @@
+
+/****************************************************************************
+ QuickDraw Import Filter; Implementation
+*****************************************************************************
+
+ This file contains the source for a dynamically loaded graphics
+ import filters that read QuickDraw PICT images. The entry points
+ support both Aldus version 1 style interface, embedded extensions,
+ and a parameterized input control.
+
+****************************************************************************/
+
+#include <headers.c>
+#pragma hdrstop
+
+#include "api.h" /* Own interface */
+
+/*********************** Exported Data **************************************/
+
+
+/*********************** Private Data ***************************************/
+
+#define GraphicsImport 2
+#define PICTHeaderOffset 512
+
+#define USEDIALOG TRUE
+#define NODIALOG FALSE
+
+private USERPREFS upgradePrefs;
+private USERPREFS defaultPrefs =
+{
+ { 'Q','D','2','G','D','I' }, // signature
+ 2, // version = 2
+ sizeof( USERPREFS ), // size of structure
+ NULL, // no sourceFilename, yet
+ NULL, // no sourceHandle, yet
+ NULL, // no destinationFilename, yet
+ 3, // penPatternAction = blend fore and background
+ 5, // nonSquarePenAction = use max dimension
+ 1, // penModeAction = use srcCopy
+ 1, // textModeAction = use srcCopy
+ 1, // nonRectRegionAction = create masks
+ 0, // optimize PowerPoint = false
+ 0, // noRLE = false
+ 0, // reservedByte
+ { 0, 0, 0, 0, 0 } // reserved initialized
+};
+
+private Handle instanceHandle;
+
+
+/*********************** Private Function Definitions ***********************/
+
+LPUSERPREFS VerifyPrefBlock( LPUSERPREFS lpPrefs );
+/* Perform cursory verification of the parameter block header */
+
+private void ConvertPICT( LPUSERPREFS lpPrefs, PICTINFO far * lpPict,
+ Boolean doDialog );
+/* perform conversion and return results once environment is set up */
+
+/*********************** Function Implementation ****************************/
+#ifdef WIN32
+int WINAPI GetFilterInfo( short PM_Version, LPSTR lpIni,
+ HANDLE FAR * lphPrefMem,
+ HANDLE FAR * lphFileTypes )
+/*=====================*/
+#else
+int FAR PASCAL GetFilterInfo( short PM_Version, LPSTR lpIni,
+ HANDLE FAR * lphPrefMem,
+ HANDLE FAR * lphFileTypes )
+/*=========================*/
+#endif
+/* Returns information about this filter.
+ Input parameters are PM_Version which is the filter interface version#
+ and lpIni which is a copy of the win.ini entry
+ Output parameters are lphPrefMem which is a handle to moveable global
+ memory which will be allocated and initialized.
+ lphFileTypes is a structure that contains the file types
+ that this filter can import. (For MAC only)
+ This routine should be called once, just before the filter is to be used
+ the first time. */
+{
+ LPUSERPREFS lpPrefs;
+
+ /* allocate the global memory block */
+ *lphPrefMem = GlobalAlloc( GHND, Sizeof( USERPREFS ) );
+
+ /* if allocation is unsuccessful, set global error */
+ if (*lphPrefMem == NULL)
+ {
+ ErSetGlobalError( ErMemoryFull );
+ }
+ else
+ {
+ /* lock down the memory and assign the default values */
+ lpPrefs = (LPUSERPREFS)GlobalLock( *lphPrefMem );
+ *lpPrefs = defaultPrefs;
+
+ /* unlock the memory */
+ GlobalUnlock( *lphPrefMem );
+ }
+
+ /* Indicate handles graphics import */
+ return( GraphicsImport );
+
+ UnReferenced( PM_Version );
+ UnReferenced( lpIni );
+ UnReferenced( lphFileTypes );
+
+} /* GetFilterInfo */
+
+
+#ifdef WIN32
+void WINAPI GetFilterPref( HANDLE hInst, HANDLE hWnd,
+ HANDLE hPrefMem, WORD wFlags )
+/*======================*/
+#else
+void FAR PASCAL GetFilterPref( HANDLE hInst, HANDLE hWnd,
+ HANDLE hPrefMem, WORD wFlags )
+/*==========================*/
+#endif
+/* Input parameters are hInst (in order to access resources), hWnd (to
+ allow the DLL to display a dialog box), and hPrefMem (memory allocated
+ in the GetFilterInfo() entry point). WFlags is currently unused, but
+ should be set to 1 for Aldus' compatability */
+{
+ return;
+
+ UnReferenced( hInst );
+ UnReferenced( hWnd );
+ UnReferenced( hPrefMem );
+ UnReferenced( wFlags );
+
+} /* GetFilterPref */
+
+
+#ifndef _OLECNV32_
+
+#ifdef WIN32
+short WINAPI ImportGr( HDC hdcPrint, LPFILESPEC lpFileSpec,
+ PICTINFO FAR * lpPict, HANDLE hPrefMem )
+/*==================*/
+#else
+short FAR PASCAL ImportGr( HDC hdcPrint, LPFILESPEC lpFileSpec,
+ PICTINFO FAR * lpPict, HANDLE hPrefMem )
+/*======================*/
+#endif
+/* Import the metafile in the file indicated by the lpFileSpec. The
+ metafile generated will be returned in lpPict. */
+{
+ LPUSERPREFS lpPrefs;
+
+ /* Check for any errors from GetFilterInfo() or GetFilterPref() */
+ if (ErGetGlobalError() != NOERR)
+ {
+ return ErInternalErrorToAldus();
+ }
+
+ /* Lock the preference memory and verify correct header */
+ lpPrefs = (LPUSERPREFS)GlobalLock( hPrefMem );
+ lpPrefs = VerifyPrefBlock( lpPrefs );
+
+ /* if there is no error from the header verification, proceed */
+ if (ErGetGlobalError() == NOERR)
+ {
+ /* provide IO module with source file name and read begin offset */
+ IOSetFileName( (StringLPtr) lpFileSpec->fullName );
+ IOSetReadOffset( PICTHeaderOffset );
+
+ /* save the source filename for the status dialog box */
+ lpPrefs->sourceFilename = lpFileSpec->fullName;
+
+ /* Tell Gdi module to create a memory-based metafile */
+ lpPrefs->destinationFilename = NULL;
+
+ /* convert the image, provide status update */
+ ConvertPICT( lpPrefs, lpPict, USEDIALOG );
+ }
+
+ /* Unlock preference memory */
+ GlobalUnlock( hPrefMem );
+
+ /* return the translated error code (if any problems encoutered) */
+ return ErInternalErrorToAldus();
+
+ UnReferenced( hdcPrint );
+ UnReferenced( hPrefMem );
+
+} /* ImportGR */
+
+#ifdef WIN32
+short WINAPI ImportEmbeddedGr( HDC hdcPrint, LPFILESPEC lpFileSpec,
+ PICTINFO FAR * lpPict, HANDLE hPrefMem,
+ DWORD dwSize, LPSTR lpMetafileName )
+/*==========================*/
+#else
+short FAR PASCAL ImportEmbeddedGr( HDC hdcPrint, LPFILESPEC lpFileSpec,
+ PICTINFO FAR * lpPict, HANDLE hPrefMem,
+ DWORD dwSize, LPSTR lpMetafileName )
+/*==============================*/
+#endif
+/* Import the metafile in using the previously opened file handle in
+ the structure field lpFileSpec->handle. Reading begins at offset
+ lpFileSpect->filePos, and the convertor will NOT expect to find the
+ 512 byte PICT header. The metafile generated will be returned in
+ lpPict and can be specified via lpMetafileName (NIL = memory metafile,
+ otherwise, fully qualified filename. */
+{
+ LPUSERPREFS lpPrefs;
+
+ /* Check for any errors from GetFilterInfo() or GetFilterPref() */
+ if (ErGetGlobalError() != NOERR)
+ {
+ return ErInternalErrorToAldus();
+ }
+
+ /* Lock the preference memory and verify correct header */
+ lpPrefs = (LPUSERPREFS)GlobalLock( hPrefMem );
+ lpPrefs = VerifyPrefBlock( lpPrefs );
+
+ /* if there is no error from the header verification, proceed */
+ if (ErGetGlobalError() == NOERR)
+ {
+ /* provide IO module with source file handle and read begin offset */
+ IOSetFileHandleAndSize( lpFileSpec->handle, dwSize );
+ IOSetReadOffset( lpFileSpec->filePos );
+
+ /* save the source filename for the status dialog box */
+ lpPrefs->sourceFilename = lpFileSpec->fullName;
+
+ /* Tell Gdi module to create metafile passed as parameter */
+ lpPrefs->destinationFilename = lpMetafileName;
+
+ /* convert the image, provide status update */
+ ConvertPICT( lpPrefs, lpPict, USEDIALOG );
+ }
+
+ /* Unlock preference memory */
+ GlobalUnlock( hPrefMem );
+
+ /* return the translated error code (if any problems encoutered) */
+ return ErInternalErrorToAldus();
+
+ UnReferenced( hdcPrint );
+ UnReferenced( hPrefMem );
+
+} /* ImportEmbeddedGr */
+
+#endif // !_OLECNV32_
+
+
+#ifdef WIN32
+short WINAPI QD2GDI( LPUSERPREFS lpPrefMem, PICTINFO FAR * lpPict )
+/*================*/
+#else
+short FAR PASCAL QD2GDI( LPUSERPREFS lpPrefMem, PICTINFO FAR * lpPict )
+/*====================*/
+#endif
+/* Import the metafile as specified using the parameters supplied in the
+ lpPrefMem. The metafile will be returned in lpPict. */
+{
+ /* verify correct header, and return if something is wrong */
+ lpPrefMem = VerifyPrefBlock( lpPrefMem );
+
+ /* if there is no error from the header verification, proceed */
+ if (ErGetGlobalError() == NOERR)
+ {
+#ifndef _OLECNV32_
+ /* Determine if there is a fully-qualified source file name */
+ if (lpPrefMem->sourceFilename != NIL)
+ {
+ /* Set the filename and read offset */
+ IOSetFileName( (StringLPtr) lpPrefMem->sourceFilename );
+ IOSetReadOffset( 0 );
+
+ }
+ /* otherwise, we are performing memory read from a global memory block */
+ else
+#endif // !_OLECNV32_
+ if (lpPrefMem->sourceHandle != NIL)
+ {
+ /* Set the memory handle and read offset */
+ IOSetMemoryHandle( (Integer) lpPrefMem->sourceHandle );
+ IOSetReadOffset( 0 );
+ }
+ else
+ {
+ /* Problem with input parameter block */
+ ErSetGlobalError( ErNoSourceFormat );
+#ifdef _OLECNV32_
+ return(ErGetGlobalError());
+#else
+ return ErInternalErrorToAldus();
+#endif
+ }
+
+ /* convert the image - no status updates */
+ ConvertPICT( lpPrefMem, lpPict, NODIALOG );
+ }
+
+ /* return the translated error code (if any problems encoutered) */
+#ifdef _OLECNV32_
+ return(ErGetGlobalError());
+#else
+ return ErInternalErrorToAldus();
+#endif
+
+} /* QD2GDI */
+
+
+#ifdef WIN32
+BOOL LibMain( HINSTANCE hInst, DWORD fdwReason, LPVOID lpReserved)
+/*=========*/
+#else
+int FAR PASCAL LibMain( HANDLE hInst, WORD wDataSeg, WORD cbHeap,
+ LPSTR lpszCmdline )
+/*===================*/
+#endif
+/* Needed to get an instance handle */
+{
+ instanceHandle = hInst;
+
+ /* default return value */
+ return( 1 );
+
+#ifndef WIN32
+ UnReferenced( wDataSeg );
+ UnReferenced( cbHeap );
+ UnReferenced( lpszCmdline );
+#endif
+
+} /* LibMain */
+
+#ifdef WIN32
+int WINAPI WEP( int nParameter )
+/*===========*/
+#else
+int FAR PASCAL WEP( int nParameter )
+/*===============*/
+#endif
+{
+ /* default return value */
+ return( 1 );
+
+ UnReferenced( nParameter );
+
+} /* WEP */
+
+
+
+/******************************* Private Routines ***************************/
+
+
+LPUSERPREFS VerifyPrefBlock( LPUSERPREFS lpPrefs )
+/*-------------------------*/
+/* Perform cursory verification of the parameter block header */
+{
+ Byte i;
+ Byte far * prefs = (Byte far *)lpPrefs;
+ Byte far * check = (Byte far *)&defaultPrefs;
+
+ /* loop through chars of signature verifying it */
+ for (i = 0; i < sizeof( lpPrefs->signature); i++)
+ {
+ /* if any of the byte miscompare ... */
+ if (*prefs++ != *check++)
+ {
+ /* ... set a global flag and return */
+ ErSetGlobalError( ErInvalidPrefsHeader );
+ }
+ }
+
+ /* check if this is a version 1 structure */
+ if (lpPrefs->version == 1)
+ {
+ USERPREFS_V1 v1Prefs = *((LPUSERPREFS_V1)lpPrefs);
+
+ /* convert the version 1 fields to version 2 fields */
+ upgradePrefs = defaultPrefs;
+ upgradePrefs.sourceFilename = v1Prefs.sourceFilename;
+ upgradePrefs.sourceHandle = v1Prefs.sourceHandle;
+ upgradePrefs.destinationFilename = v1Prefs.destinationFilename;
+ upgradePrefs.nonSquarePenAction = v1Prefs.nonSquarePenAction;
+ upgradePrefs.penModeAction = v1Prefs.penModeAction;
+ upgradePrefs.textModeAction = v1Prefs.textModeAction;
+ upgradePrefs.optimizePP = v1Prefs.optimizePP;
+
+ /* since new functionality was added to the patterned pens and region
+ records, upgrade to highest image fidelity setting if they didn't
+ request omit or import abort actions. */
+ upgradePrefs.penPatternAction = (v1Prefs.penPatternAction == 1) ?
+ (Byte)3 :
+ v1Prefs.penPatternAction;
+ upgradePrefs.nonRectRegionAction = (v1Prefs.nonRectRegionAction == 0) ?
+ (Byte)1 :
+ v1Prefs.nonRectRegionAction;
+
+ /* return address of the converted fields data structure */
+ return &upgradePrefs;
+ }
+ else if( lpPrefs->version <= 3 )
+ {
+ if( lpPrefs->version==2 )
+ { /* noRLE wasn't supported in version 2, so zero it */
+ lpPrefs->noRLE = 0;
+ }
+
+ /* return address that was passed in */
+ return lpPrefs;
+ }
+ else /* version > 3 is an error */
+ ErSetGlobalError( ErInvalidPrefsHeader );
+}
+
+
+private void ConvertPICT( LPUSERPREFS lpPrefs, PICTINFO far * lpPict,
+ Boolean doDialog )
+/*----------------------*/
+/* perform conversion and return results once environment is set up */
+{
+#ifndef _OLECNV32_
+ FARPROC dialogBoxProcedure;
+ StatusParam statusParams;
+#endif
+
+ /* Set conversion preferences */
+ /* This is somewhat bogus in that it passes ptr to middle of USERPREFS
+ to a function that wants a ptr to ConvPrefs (a trailing subset) */
+ GdiSetConversionPrefs( (ConvPrefsLPtr)&lpPrefs->destinationFilename );
+
+#ifndef _OLECNV32_
+ if (doDialog)
+ {
+ /* save data in structure to be passed to dialog window */
+ statusParams.sourceFilename = lpPrefs->sourceFilename;
+ statusParams.instance = instanceHandle;
+
+ /* make a callable address for status dialog */
+ dialogBoxProcedure = MakeProcInstance( StatusProc, instanceHandle );
+
+ /* make sure that the procedure address was obtained */
+ if (dialogBoxProcedure == NULL)
+ {
+ /* set error if unable to proceed */
+ ErSetGlobalError( ErNoDialogBox );
+ return;
+ }
+ else
+ {
+ /* AR: GetActiveWindow() may be bad, since the ability to update
+ !!! links may be performed in the background, shutting out
+ any process which then becomes the active window */
+
+ /* dialog module calls quickdraw entry point to convert image */
+ DialogBoxParam( instanceHandle, MAKEINTRESOURCE( RS_STATUS ),
+ GetActiveWindow(), dialogBoxProcedure,
+ (DWORD)((StatusParamLPtr)&statusParams) );
+
+ /* release the procedure instance */
+ FreeProcInstance( dialogBoxProcedure );
+ }
+ }
+ else
+#endif // !_OLECNV32_
+ {
+ /* convert image, NULL parameter means no status updates */
+ QDConvertPicture( NULL );
+ }
+
+ /* Get conversion results in parameter block */
+ GdiGetConversionResults( lpPict );
+
+#ifdef DEBUG
+ if (ErGetGlobalError() == ErNoError)
+ {
+ HANDLE hPICT;
+ LPMETAFILEPICT lpPICT;
+
+ OpenClipboard( GetActiveWindow() );
+
+ hPICT = GlobalAlloc( GHND, sizeof( METAFILEPICT ) );
+
+ if (hPICT)
+ {
+ lpPICT = (LPMETAFILEPICT)GlobalLock( hPICT );
+ lpPICT->mm = MM_ANISOTROPIC;
+ lpPICT->xExt = Width( lpPict->bbox );
+ lpPICT->yExt = Height( lpPict->bbox );
+ lpPICT->hMF = CopyMetaFile( lpPict->hmf, NULL );
+ GlobalUnlock( hPICT );
+
+ SetClipboardData( CF_METAFILEPICT, hPICT );
+ CloseClipboard();
+ }
+ }
+#endif
+
+} /* ConvertPICT */
+
diff --git a/private/ole32/olecnv32/api.h b/private/ole32/olecnv32/api.h
new file mode 100644
index 000000000..416794326
--- /dev/null
+++ b/private/ole32/olecnv32/api.h
@@ -0,0 +1,155 @@
+
+/****************************************************************************
+ Metafile Import Filter; Interface
+*****************************************************************************
+
+ This file contains the interface for the QuickDraw import filter
+ that reads Mac pictures from disk and/or memory. In addition to the
+ Aldus filter interface, it also supports a parameterized interface
+ for Microsoft applications to control some conversion results.
+
+****************************************************************************/
+
+/*--- Aldus-defined file access block ---*/
+
+typedef DWORD FILETYPE;
+
+typedef struct
+{
+ unsigned slippery : 1; /* TRUE if file may disappear. */
+ unsigned write : 1; /* TRUE if open for write. */
+ unsigned unnamed : 1; /* TRUE if unnamed. */
+ unsigned linked : 1; /* Linked to an FS FCB. */
+ unsigned mark : 1; /* Generic mark bit. */
+ FILETYPE fType; /* The file type. */
+#define IBMFNSIZE 124
+ short handle; /* MS-DOS open file handle. */
+ char fullName[IBMFNSIZE]; /* Device, path, file names. */
+ DWORD filePos; /* Our current file posn. */
+} FILESPEC, FAR *LPFILESPEC;
+
+
+/*--- Preferences memory block ---*/
+
+typedef struct // "old" version 1 USERPREFS
+{
+ char signature[6];
+ WORD version;
+ LPSTR sourceFilename;
+ HANDLE sourceHandle;
+ LPSTR destinationFilename;
+ BYTE penPatternAction;
+ BYTE nonSquarePenAction;
+ BYTE penModeAction;
+ BYTE textModeAction;
+ BYTE charLock;
+ BYTE nonRectRegionAction;
+ BOOL PICTinComment;
+ BOOL optimizePP;
+ WORD lineClipWidthThreshold;
+ WORD reserved[6];
+} USERPREFS_V1, FAR *LPUSERPREFS_V1;
+
+
+typedef struct // current version 3 USERPREFS
+{
+ char signature[6];
+ WORD version;
+ WORD size;
+ LPSTR sourceFilename;
+ HANDLE sourceHandle;
+ LPSTR destinationFilename;
+ BYTE penPatternAction;
+ BYTE nonSquarePenAction;
+ BYTE penModeAction;
+ BYTE textModeAction;
+ BYTE nonRectRegionAction;
+ BOOL optimizePP;
+ BYTE noRLE; // new (split out from reserved[0] of version 2)
+ BYTE reservedByte; // rest of first reserved word
+ WORD reserved[5];
+
+} USERPREFS, FAR * LPUSERPREFS;
+
+
+/*********************** Exported Function Definitions **********************/
+
+#ifdef WIN32
+int WINAPI GetFilterInfo( short PM_Version, LPSTR lpIni,
+ HANDLE FAR * lphPrefMem,
+ HANDLE FAR * lphFileTypes );
+#else
+int FAR PASCAL GetFilterInfo( short PM_Version, LPSTR lpIni,
+ HANDLE FAR * lphPrefMem,
+ HANDLE FAR * lphFileTypes );
+#endif
+/* Returns information about this filter.
+ Input parameters are PM_Version which is the filter interface version#
+ and lpIni which is a copy of the win.ini entry
+ Output parameters are lphPrefMem which is a handle to moveable global
+ memory which will be allocated and initialized.
+ lphFileTypes is a structure that contains the file types
+ that this filter can import. (For MAC only)
+ This routine should be called once, just before the filter is to be used
+ the first time. */
+
+
+#ifdef WIN32
+void WINAPI GetFilterPref( HANDLE hInst, HANDLE hWnd, HANDLE hPrefMem, WORD wFlags );
+#else
+void FAR PASCAL GetFilterPref( HANDLE hInst, HANDLE hWnd, HANDLE hPrefMem, WORD wFlags );
+#endif
+/* Input parameters are hInst (in order to access resources), hWnd (to
+ allow the DLL to display a dialog box), and hPrefMem (memory allocated
+ in the GetFilterInfo() entry point). WFlags is currently unused, but
+ should be set to 1 for Aldus' compatability */
+
+
+#ifdef WIN32
+short WINAPI ImportGR( HDC hdcPrint, LPFILESPEC lpFileSpec,
+ PICTINFO FAR * lpPict, HANDLE hPrefMem );
+#else
+short FAR PASCAL ImportGR( HDC hdcPrint, LPFILESPEC lpFileSpec,
+ PICTINFO FAR * lpPict, HANDLE hPrefMem );
+#endif
+/* Import the metafile in the file indicated by the lpFileSpec. The
+ metafile generated will be returned in lpPict. */
+
+
+#ifdef WIN32
+short WINAPI ImportEmbeddedGr( HDC hdcPrint, LPFILESPEC lpFileSpec,
+ PICTINFO FAR * lpPict, HANDLE hPrefMem,
+ DWORD dwSize, LPSTR lpMetafileName );
+#else
+short FAR PASCAL ImportEmbeddedGr( HDC hdcPrint, LPFILESPEC lpFileSpec,
+ PICTINFO FAR * lpPict, HANDLE hPrefMem,
+ DWORD dwSize, LPSTR lpMetafileName );
+#endif
+/* Import the metafile in using the previously opened file handle in
+ the structure field lpFileSpec->handle. Reading begins at offset
+ lpFileSpect->filePos, and the convertor will NOT expect to find the
+ 512 byte PICT header. The metafile generated will be returned in
+ lpPict and can be specified via lpMetafileName (NIL = memory metafile,
+ otherwise, fully qualified filename. */
+
+#ifdef WIN32
+short WINAPI QD2GDI( LPUSERPREFS lpPrefMem, PICTINFO FAR * lpPict );
+#else
+short FAR PASCAL QD2GDI( LPUSERPREFS lpPrefMem, PICTINFO FAR * lpPict );
+#endif
+/* Import the metafile as specified using the parameters supplied in the
+ lpPrefMem. The metafile will be returned in lpPict. */
+
+#ifdef WIN32
+BOOL LibMain( HINSTANCE hInst, DWORD fdwReason, LPVOID lpvReserved);
+#else
+int FAR PASCAL LibMain( HANDLE hInst, WORD wDataSeg, WORD cbHeap,
+ LPSTR lpszCmdline );
+#endif
+/* Needed to get an instance handle */
+
+#ifdef WIN32
+int WINAPI WEP( int nParameter );
+#else
+int FAR PASCAL WEP( int nParameter );
+#endif
diff --git a/private/ole32/olecnv32/bufio.c b/private/ole32/olecnv32/bufio.c
new file mode 100644
index 000000000..178c78c21
--- /dev/null
+++ b/private/ole32/olecnv32/bufio.c
@@ -0,0 +1,394 @@
+/****************************************************************************
+ Unit Bufio; Implementation
+*****************************************************************************
+
+ Bufio implements the structured reading of the imput stream. As such, it
+ will handle the necessary byte-swapping that must occur when reading a
+ native Macintosh file.
+
+ This interface will also shield the calling application from knowledge of
+ the source format (file vs. memory).
+
+ Module Prefix: IO
+
+****************************************************************************/
+
+#include "headers.c"
+#pragma hdrstop
+
+#include "filesys.h"
+
+#ifndef _OLECNV32_
+//#include "status.h"
+#endif // _OLECNV32_
+
+/*********************** Exported Data **************************************/
+
+
+/*********************** Private Data ***************************************/
+
+#define UNKNOWN 0
+#define FILE 1
+#define MEMORY 2
+#define RTF 3
+
+#define BUFFERSIZE 1024
+
+private LongInt numBytesRead;
+private LongInt pictureSize;
+private LongInt beginOffset;
+
+private LongInt bufferCount;
+private Byte buffer[BUFFERSIZE];
+private Byte * nextCharPtr;
+private Byte huge * nextCharHPtr;
+
+private Byte sourceType = UNKNOWN;
+private Integer fileHandle = ( Integer ) NULL;
+private Str255 fileName;
+private Boolean openFile;
+
+private Byte huge * memoryHPtr;
+private Handle memoryHandle;
+
+private Handle dialogHandle;
+
+/*********************** Private Function Definitions ***********************/
+
+private void ReadNextBuffer( void );
+/* Replenish the i/o buffer with the next set of characters */
+
+/* Memory operations - check return values on usage */
+#define MDisposHandle( h ) ((void) GlobalFree( h ))
+#define MLock( h ) ((LPtr) GlobalLock( h ))
+#define MUnlock( h ) ((void) GlobalUnlock( h ))
+#define MDR( h ) ((LPtr) GlobalLock( h ))
+#define MUR( h ) ((void) GlobalUnlock( h ))
+#define MNewHandle( s ) GlobalAlloc( GMEM_MOVEABLE, s )
+
+/*********************** Function Implementation ****************************/
+
+void IOGetByte( Byte far * byteLPtr )
+/*============*/
+/* Read a byte from the input stream. If the buffer is empty, then
+ it is replenished. */
+{
+ /* Make sure that no global error code has been set before read */
+ if (ErGetGlobalError() != NOERR )
+ {
+ *byteLPtr = 0;
+ return;
+ }
+
+ /* Check for an attempt to read past the EOF or memory block. This
+ would indicate that the opcode parsing was thrown off somewhere. */
+ if (numBytesRead >= pictureSize)
+ {
+ ErSetGlobalError( ErReadPastEOF );
+ *byteLPtr = 0;
+ return;
+ }
+
+ /* Check to see if we need to replenish the read buffer */
+ if (bufferCount <= 0)
+ {
+ ReadNextBuffer();
+ }
+
+ /* Decrement the count of characters in the buffer, increment the total
+ number of bytes read from the file, and return the next character. */
+ bufferCount--;
+ numBytesRead++;
+
+ /* determine where to read the next byte from - use short or huge ptrs */
+ *byteLPtr = (sourceType == FILE) ? *nextCharPtr++ : *nextCharHPtr++;
+
+} /* IOGetByte */
+
+
+
+void IOSkipBytes( LongInt byteCount )
+/*==============*/
+/* Skip the designated number of bytes */
+{
+ /* make sure we are skipping a valid number of bytes */
+ if (byteCount <= 0)
+ {
+ return;
+ }
+
+ /* Check for an attempt to read past the EOF or memory block. This
+ would indicate that the opcode parsing was thrown off somewhere. */
+ if (numBytesRead + byteCount >= pictureSize)
+ {
+ ErSetGlobalError( ErReadPastEOF );
+ }
+ else
+ {
+ /* determine if there are sufficient bytes remaining in the buffer */
+ if (bufferCount >= byteCount)
+ {
+ /* decrement # bytes remaining, increment # bytes read and pointer */
+ bufferCount -= byteCount;
+ numBytesRead += byteCount;
+
+ /* increment the appropriate pointer based on media type */
+ if (sourceType == FILE)
+ {
+ /* increment near pointer to data segment buffer */
+ nextCharPtr += byteCount;
+ }
+ else
+ {
+ /* increment huge pointer to global memory block */
+ nextCharHPtr += byteCount;
+ }
+ }
+ else /* sourceType == FILE and buffer needs to be replenished */
+ {
+ Byte unusedByte;
+
+ /* continue calling IOGetByte() until desired number are skipped */
+ while (byteCount--)
+ {
+ /* call IOGetByte to make sure the cache is replenished */
+ IOGetByte( &unusedByte );
+ }
+ }
+ }
+
+} /* IOSkipBytes */
+
+
+
+void IOAlignToWordOffset( void )
+/*======================*/
+/* Align next memory read to Word boundary. */
+{
+ /* check to see if we have read an odd number of bytes so far. Skip
+ the ensuing byte if necessary to align. */
+ if (numBytesRead & 0x0001)
+ {
+ IOSkipBytes( 1 );
+ }
+
+} /* IOAlignToWordOffset */
+
+
+#ifndef _OLECNV32_
+void IOSetFileName( StringLPtr pictFileName )
+/*================*/
+/* Interface routine to set the source filename */
+{
+ lstrcpy( fileName, pictFileName );
+ sourceType = FILE;
+ openFile = TRUE;
+
+} /* IOSetFileName */
+
+void IOSetFileHandleAndSize( Integer pictFileHandle, LongInt pictFileSize )
+/*=========================*/
+/* Interface routine to set the source file Handle */
+{
+ fileHandle = pictFileHandle;
+ pictureSize = pictFileSize;
+ sourceType = FILE;
+ openFile = FALSE;
+
+} /* IOSetFIleHandle */
+#endif // !_OLECNV32_
+
+
+
+void IOSetMemoryHandle( Integer pictMemoryHandle )
+/*==================*/
+/* Interface routine to set the source file Handle */
+{
+ memoryHandle = ( Handle ) pictMemoryHandle;
+ sourceType = MEMORY;
+
+} /* IOSetMemoryHandle */
+
+
+
+void IOSetReadOffset( LongInt readOffset )
+/*==================*/
+/* Set the beginning offset to seek to when the file is opened */
+{
+ beginOffset = readOffset;
+}
+
+
+
+void IOOpenPicture( Handle dialog )
+/*================*/
+/* Open the input stream depending on the source type set by a previous
+ IOSet___ interface routine. Determine the size of the picture image. */
+{
+#ifndef _OLECNV32_
+ OSErr openError;
+#endif // !_OLECNV32_
+
+ /* if the type isn't set, return error */
+ if (sourceType == UNKNOWN)
+ {
+ ErSetGlobalError( ErNoSourceFormat );
+ return;
+ }
+
+ /* initialize the various reader variables */
+ numBytesRead = 0;
+ bufferCount = 0;
+
+ /* determine how to open the soure data stream */
+#ifndef _OLECNV32_
+ if (sourceType == FILE)
+ {
+ /* if we are openning and converting an entire file */
+ if (openFile)
+ {
+ /* open the file */
+ openError = FSOpen( (StringLPtr)fileName, OF_READ | OF_SHARE_DENY_WRITE, &fileHandle );
+ if (openError)
+ {
+ ErSetGlobalError( ErOpenFail);
+ }
+ else
+ {
+ /* and determine the file length */
+ FSSetFPos( fileHandle, FSFROMLEOF, 0L );
+ FSGetFPos( fileHandle, &pictureSize );
+ }
+ }
+
+ /* set position to the designated start position */
+ FSSetFPos( fileHandle, FSFROMSTART, beginOffset );
+ numBytesRead = beginOffset;
+ }
+ else /* if (sourceType == MEMORY) */
+#endif // !_OLECNV32_
+ {
+ /* lock the memory block */
+ memoryHPtr = (Byte huge *) MLock( memoryHandle );
+ if (memoryHPtr == NULL)
+ {
+ ErSetGlobalError( ErMemoryFail );
+ return;
+ }
+ else
+ {
+ /* and determine the overall memory block size */
+ pictureSize = GlobalSize( memoryHandle );
+ }
+
+ /* set the huge character read pointer, bytes read, and buffer count */
+ nextCharHPtr = memoryHPtr + beginOffset;
+ bufferCount = pictureSize - beginOffset;
+ numBytesRead = beginOffset;
+ }
+
+#ifndef _OLECNV32_
+ /* make sure that a dialog handle was supplied for update */
+ if (dialog)
+ {
+ /* save off the dialog box handle */
+ dialogHandle = dialog;
+
+ /* calculate the interval to update the status dialog */
+ SendMessage( dialogHandle, SM_SETRANGE, 0, pictureSize );
+ }
+#endif // !OLECNV32
+
+} /* IOOpenPicture */
+
+
+
+void IOClosePicture( void )
+/*=================*/
+/* Close the source input stream */
+{
+ /* if this is a file-based metafile */
+#ifndef _OLECNV32_
+ if (sourceType == FILE)
+ {
+ /* make sure this isn't the ImportEmbeddedGr() entry point */
+ if (openFile)
+ {
+ /* close the file if necessary */
+ FSCloseFile( fileHandle );
+ fileHandle = ( Integer ) NULL;
+ }
+ }
+ else
+#endif // !_OLECNV32_
+ {
+ /* unlock the global memory block */
+ MUnlock( memoryHandle );
+ memoryHandle = NULL;
+ }
+
+ /* de-initialize the module variables */
+ sourceType = UNKNOWN;
+ dialogHandle = NULL;
+
+} /* IOClosePicture */
+
+
+
+void IOUpdateStatus( void )
+/*=================*/
+/* Update the status bar dialog to reflect current progress */
+{
+#ifndef _OLECNV32_
+ /* update only if a dialog box was created */
+ if (dialogHandle)
+ {
+ /* calculate the interval to update the status dialog */
+ SendMessage( dialogHandle, SM_SETPOSITION, 0, numBytesRead );
+ }
+#endif // !_OLECNV32_
+
+} /* IOUpdateStatus */
+
+
+
+/******************************* Private Routines ***************************/
+
+
+private void ReadNextBuffer( void )
+/*-------------------------*/
+/* Replenish the i/o buffer with the next set of characters. This should
+ only be called if performing buffered I/O - not with MEMORY-based file */
+{
+#ifndef _OLECNV32_
+ OSErr fileError;
+
+ /* Read the required number of bytes from the file. Check the error
+ code return and set the global status error if the read failed. */
+
+ if (sourceType == FILE)
+ {
+ /* Calculate the number of bytes that should be read into the buffer.
+ This needs to be done, since this may be a memory source picture,
+ in which an invalid read could produce a GP violation */
+ if (numBytesRead + BUFFERSIZE > pictureSize)
+ bufferCount = pictureSize - numBytesRead;
+ else
+ bufferCount = BUFFERSIZE;
+
+ /* read the bytes from the file */
+ fileError = FSRead( fileHandle, &bufferCount, &buffer);
+
+ /* if there is any error, notify the error module */
+ if (fileError != 0)
+ {
+ ErSetGlobalError( ErReadFail );
+ return;
+ }
+
+ /* reset the character read pointer to the beginning of the buffer */
+ nextCharPtr = buffer;
+ }
+#endif // _OLECNV32_
+
+} /* ReadNextBuffer */
diff --git a/private/ole32/olecnv32/bufio.h b/private/ole32/olecnv32/bufio.h
new file mode 100644
index 000000000..1ecac1ff2
--- /dev/null
+++ b/private/ole32/olecnv32/bufio.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+ Unit Bufio; Interface
+*****************************************************************************
+
+ Bufio implements the structured reading of the imput stream. As such, it
+ will handle the necessary byte-swapping that must occur when reading a
+ native Macintosh file.
+
+ This interface will also shield the calling application from knowledge of
+ the source format (file vs. memory).
+
+ Module Prefix: IO
+
+*****************************************************************************/
+
+
+/*********************** Exported Function Definitions **********************/
+
+void IOGetByte( Byte far * );
+/* Retrieves an 8-bit unsigned char from the input stream */
+
+void IOSkipBytes( LongInt byteCount );
+/* Skip the designated number of bytes */
+
+void IOAlignToWordOffset( void );
+/* Align next memory read to Word boundary. */
+
+void IOSetFileName( StringLPtr pictFileName );
+/* Interface routine to set the source filename */
+
+void IOSetFileHandleAndSize( Integer pictFileHandle, LongInt pictFileSize );
+/* Interface routine to set the source file Handle */
+
+void IOSetMemoryHandle( Integer pictMemoryHandle );
+/* Interface routine to set the source file Handle */
+
+void IOSetReadOffset( LongInt readOffset );
+/* Set the beginning offset to seek to when the file is opened */
+
+void IOOpenPicture( Handle dialog );
+/* Open the input stream set by a previous IOSet___ interface routine. */
+
+void IOClosePicture( void );
+/* Close the source input stream */
+
+void IOUpdateStatus( void );
+/* Update the status bar dialog to reflect current progress */
+
+
diff --git a/private/ole32/olecnv32/cache.c b/private/ole32/olecnv32/cache.c
new file mode 100644
index 000000000..95a569ab0
--- /dev/null
+++ b/private/ole32/olecnv32/cache.c
@@ -0,0 +1,1161 @@
+
+
+/****************************************************************************
+ Unit Cache; Implementation
+*****************************************************************************
+
+ Module Prefix: Ca
+
+****************************************************************************/
+
+#include "headers.c"
+#pragma hdrstop
+
+#include "cache.h" /* own interface */
+
+/*********************** Exported Data **************************************/
+
+
+/*********************** Private Data ***************************************/
+
+/*--- Gdi cache ---*/
+
+typedef struct
+{
+ HPEN handle;
+ LOGPEN logPen;
+ Boolean stockObject;
+
+} Pen, far * PenLPtr;
+
+
+typedef struct
+{
+ HBRUSH handle;
+ LOGBRUSH logBrush;
+ Boolean stockObject;
+
+} Brush, far * BrushLPtr;
+
+
+typedef struct
+{
+ Handle metafile; // metafile handle
+
+ Rect prevClipRect; // last cliprect before SaveDC()
+ Rect curClipRect; // last clipping rectangle
+ Boolean forceNewClipRect; // always emit new clipping rectangle?
+
+ HPEN nulPen; // frequently used pens
+ HPEN whitePen;
+ HPEN blackPen;
+
+ HBRUSH nulBrush; // frequently used brushes
+ HBRUSH whiteBrush;
+ HBRUSH blackBrush;
+
+ Boolean stockFont; // current font selection
+ HFONT curFont;
+ LOGFONT curLogFont;
+
+ Brush curBrush; // current pen and brush selections
+ Pen curPen;
+ Pen nextPen; // cached frame(pen)
+
+ CaPrimitive nextPrim; // cached primitive
+ Boolean samePrim;
+ Handle polyHandle;
+ Integer numPoints;
+ Integer maxPoints;
+ Point far * pointList;
+
+ Word iniROP2; // initial value for ROP2 mode
+ Word iniTextAlign; // initial value for text alignment
+ Word iniBkMode;
+ RGBColor iniTxColor;
+ RGBColor iniBkColor;
+
+ Word curROP2; // current ROP codes setting
+ Word curBkMode; // current background mode
+ RGBColor curBkColor; // current background color
+ Word curStretchMode; // current stretchblt mode
+
+ RGBColor curTextColor; // last text color
+ Word curTextAlign; // last text alignment value
+ short curCharExtra; // last char extra value
+ Fixed spExtra; // last space extra value
+ Point txNumer; // last text scaling
+ Point txDenom; // factors
+
+ Boolean restorePen; // do any attribs need to be re-issued
+ Boolean restoreBrush; // after RestoreDC() call?
+ Boolean restoreFont;
+ Boolean restoreCharExtra;
+ Boolean restoreStretchMode;
+
+} GdiCache;
+
+private GdiCache gdiCache;
+
+/*********************** Private Function Definitions ***********************/
+
+#define /* void */ NewPolygon( /* void */ ) \
+/* start a new polygon definition */ \
+gdiCache.numPoints = 0
+
+
+private void AddPolyPt( Point pt );
+/* Add a point to the polygon buffer */
+
+
+private void SelectCachedPen( void );
+/* select the currently cached Pen into the metafile */
+
+
+/*********************** Function Implementation ****************************/
+
+
+void CaInit( Handle metafile )
+/*=========*/
+/* initialize the gdi cache module */
+{
+ /* save off the metafile handle into global structure */
+ gdiCache.metafile = metafile;
+
+ /* make sure that text and background colors will be set */
+ gdiCache.curTextColor =
+ gdiCache.curBkColor = RGB( 12, 34, 56 );
+
+ /* get handles to some stock pen objects */
+ gdiCache.nulPen = GetStockObject( NULL_PEN );
+ gdiCache.whitePen = CreatePen( PS_INSIDEFRAME, 1, RGB( 255, 255, 255 ) );
+ gdiCache.blackPen = CreatePen( PS_INSIDEFRAME, 1, RGB( 0, 0, 0 ) );
+
+ /* get handles to some stock brush objects */
+ gdiCache.nulBrush = GetStockObject( NULL_BRUSH );
+ gdiCache.whiteBrush = GetStockObject( WHITE_BRUSH );
+ gdiCache.blackBrush = GetStockObject( BLACK_BRUSH );
+
+ /* allocate space for the polygon buffer */
+ gdiCache.numPoints = 0;
+ gdiCache.maxPoints = 16;
+ gdiCache.polyHandle = GlobalAlloc( GHND, gdiCache.maxPoints * sizeof( Point ) );
+ if (gdiCache.polyHandle == NULL)
+ {
+ ErSetGlobalError( ErMemoryFull);
+ }
+ else
+ {
+ /* get a pointer address for the memory block */
+ gdiCache.pointList = (Point far *)GlobalLock( gdiCache.polyHandle );
+ }
+
+ /* mark the primitive cache as empty */
+ gdiCache.nextPrim.type = CaEmpty;
+
+ /* the current primitive isn't being repeated */
+ gdiCache.samePrim = FALSE;
+
+ /* turn off forcing of a new clipping rectangle */
+ gdiCache.forceNewClipRect = FALSE;
+
+} /* CaInit */
+
+
+
+void CaFini( void )
+/*=========*/
+/* close down the cache module */
+{
+ /* delete the current font selection if non-NULL and non-stock */
+ if ((gdiCache.curFont != NULL) && !gdiCache.stockFont)
+ {
+ /* free the font object */
+ DeleteObject( gdiCache.curFont );
+ }
+
+ /* remove the current brush selection if non-NULL and not a stock brush */
+ if ((gdiCache.curBrush.handle != NULL) && !gdiCache.curBrush.stockObject)
+ {
+ /* see if the current brush has a DIB - if so, delete it */
+ if (gdiCache.curBrush.logBrush.lbStyle == BS_DIBPATTERN)
+ {
+ /* free the DIB memory used for brush */
+ GlobalFree( (HANDLE) gdiCache.curBrush.logBrush.lbHatch );
+ }
+
+ /* delte the brush object */
+ DeleteObject( gdiCache.curBrush.handle );
+ }
+
+ /* remove the current pen selection if non-NULL and not a stock pen */
+ if ((gdiCache.curPen.handle != NULL) && !gdiCache.curPen.stockObject)
+ {
+ DeleteObject( gdiCache.curPen.handle );
+ }
+
+ /* Remove other pens created at initialization time */
+ DeleteObject( gdiCache.whitePen );
+ DeleteObject( gdiCache.blackPen );
+
+ /* deallocate the polygon buffer */
+ GlobalUnlock( gdiCache.polyHandle );
+ GlobalFree( gdiCache.polyHandle );
+
+} /* CaFini */
+
+
+
+void CaSetMetafileDefaults( void )
+/*========================*/
+/* Set up any defaults that will be used throughout the metafile context */
+{
+ /* set up some metafile defaults */
+ gdiCache.iniTextAlign = TA_LEFT | TA_BASELINE | TA_NOUPDATECP;
+ gdiCache.iniROP2 = R2_COPYPEN;
+ gdiCache.iniBkMode = TRANSPARENT;
+ gdiCache.iniTxColor = RGB( 0, 0, 0 );
+ gdiCache.iniBkColor = RGB( 255, 255, 255 );
+
+ /* Put the records into the metafile */
+ CaSetROP2( gdiCache.iniROP2 );
+ CaSetTextAlign( gdiCache.iniTextAlign );
+ CaSetBkMode( gdiCache.iniBkMode );
+ CaSetTextColor( gdiCache.iniTxColor );
+ CaSetBkColor( gdiCache.iniBkColor );
+
+} /* CaSetMetafileDefaults */
+
+
+
+void CaSamePrimitive( Boolean same )
+/*==================*/
+/* indicate whether next primitive is the same or new */
+{
+ gdiCache.samePrim = same;
+
+} /* CaSamePrimitive */
+
+
+
+void CaMergePen( Word verb )
+/*=============*/
+/* indicate that next pen should be merged with previous logical pen */
+{
+ if (gdiCache.nextPen.handle != NULL)
+ {
+ /* check to see if this is a NULL pen - the merge can happen */
+ if (gdiCache.samePrim && verb == GdiFrame &&
+ gdiCache.nextPen.handle == gdiCache.nulPen)
+ {
+ /* remove the cached pen - don't delte the pen object */
+ gdiCache.nextPen.handle = NULL;
+ }
+ else
+ {
+ /* if not removing a null pen, then flush the cache. This will most
+ often result in a line segment being flushed. */
+ CaFlushCache();
+ }
+ }
+
+} /* CaMergePen */
+
+
+
+Word CaGetCachedPrimitive( void )
+/*=======================*/
+/* return the current cached primitive type */
+{
+ return gdiCache.nextPrim.type;
+
+} /* CaGetCachedPrimitive */
+
+
+
+void CaCachePrimitive( CaPrimitiveLPtr primLPtr )
+/*===================*/
+/* Cache the primitive passed down. This includes the current pen and brush. */
+{
+ /* not another line segment and/or not continuous - flush cache */
+ CaFlushCache();
+
+ /* save off the new primitive */
+ gdiCache.nextPrim = *primLPtr;
+
+ /* check if we need to copy over the polygon list, also */
+ if ((gdiCache.nextPrim.type == CaPolygon) ||
+ (gdiCache.nextPrim.type == CaPolyLine))
+ {
+ /* create new polygon */
+ NewPolygon();
+
+ /* add the polygon to the polygon buffer */
+ while (gdiCache.nextPrim.a.poly.numPoints--)
+ {
+ AddPolyPt( *gdiCache.nextPrim.a.poly.pointList++);
+ }
+ }
+
+} /* CaCachePrimitive */
+
+
+
+void CaFlushCache( void )
+/*===============*/
+/* Flush the current primitive stored in the cache */
+{
+ /* if the cache is empty, then just return - nothing to do */
+ if (gdiCache.nextPrim.type == CaEmpty)
+ {
+ return;
+ }
+
+ /* select all cached attributes */
+ CaFlushAttributes();
+
+ /* emit any cached primitive, if necessary */
+ switch (gdiCache.nextPrim.type)
+ {
+ case CaLine:
+ {
+ Rect clip;
+ Point delta;
+ Point offset;
+
+ /* determine the length in both directions */
+ delta.x = gdiCache.nextPrim.a.line.end.x - gdiCache.nextPrim.a.line.start.x;
+ delta.y = gdiCache.nextPrim.a.line.end.y - gdiCache.nextPrim.a.line.start.y;
+
+ /* set clipRect extents based upon current point position */
+ clip.left = min( gdiCache.nextPrim.a.line.start.x, gdiCache.nextPrim.a.line.end.x );
+ clip.top = min( gdiCache.nextPrim.a.line.start.y, gdiCache.nextPrim.a.line.end.y );
+ clip.right = max( gdiCache.nextPrim.a.line.start.x, gdiCache.nextPrim.a.line.end.x );
+ clip.bottom = max( gdiCache.nextPrim.a.line.start.y, gdiCache.nextPrim.a.line.end.y );
+
+ /* extend clip rectangle for down-right pen stylus hang */
+ clip.right += gdiCache.nextPrim.a.line.pnSize.x;
+ clip.bottom += gdiCache.nextPrim.a.line.pnSize.y;
+
+ /* determine the new starting and ending points */
+ gdiCache.nextPrim.a.line.start.x -= delta.x;
+ gdiCache.nextPrim.a.line.start.y -= delta.y;
+ gdiCache.nextPrim.a.line.end.x += delta.x;
+ gdiCache.nextPrim.a.line.end.y += delta.y;
+
+ /* ajust the clipping rect for vertical line penSize roundoff? */
+ if (delta.x == 0)
+ {
+ /* vertical line - expand clip in x dimension */
+ clip.left--;
+ }
+ /* are we are adjusting pen by 1/2 metafile unit - roundoff error? */
+ else if (gdiCache.nextPrim.a.line.pnSize.x & 0x01)
+ {
+ /* adjust clipping rectangle to clip the rounding error */
+ clip.right--;
+ }
+
+ /* ajust the clipping rect for horizontal line penSize roundoff? */
+ if (delta.y == 0)
+ {
+ /* horizontal line - extend clip in y dimension */
+ clip.top--;
+ }
+ /* are we are adjusting pen by 1/2 metafile unit - roundoff error? */
+ else if (gdiCache.nextPrim.a.line.pnSize.y & 0x01)
+ {
+ /* adjust clipping rectangle to clip the rounding error */
+ clip.bottom--;
+ }
+
+ /* cut the size of the pen dimensions in half for offsets */
+ offset.x = gdiCache.nextPrim.a.line.pnSize.x / 2;
+ offset.y = gdiCache.nextPrim.a.line.pnSize.y / 2;
+
+ /* set the new clipping rectangle */
+ SaveDC( gdiCache.metafile );
+ IntersectClipRect( gdiCache.metafile,
+ clip.left, clip.top, clip.right, clip.bottom );
+
+ /* move to the first point and draw to second (with padding) */
+
+// MoveTo is replaced by MoveToEx in win32
+#ifdef WIN32
+ MoveToEx( gdiCache.metafile,
+ gdiCache.nextPrim.a.line.start.x + offset.x,
+ gdiCache.nextPrim.a.line.start.y + offset.y, NULL );
+#else
+ MoveTo( gdiCache.metafile,
+ gdiCache.nextPrim.a.line.start.x + offset.x,
+ gdiCache.nextPrim.a.line.start.y + offset.y );
+#endif
+
+ LineTo( gdiCache.metafile,
+ gdiCache.nextPrim.a.line.end.x + offset.x,
+ gdiCache.nextPrim.a.line.end.y + offset.y );
+
+ /* restore the previous clipping rectangle */
+ RestoreDC( gdiCache.metafile, -1 );
+ break;
+ }
+
+ case CaRectangle:
+ {
+ if (gdiCache.curPen.handle == gdiCache.nulPen)
+ {
+ Point poly[5];
+
+ /* set up the bounding coodinates */
+ poly[0].x = poly[3].x = gdiCache.nextPrim.a.rect.bbox.left;
+ poly[0].y = poly[1].y = gdiCache.nextPrim.a.rect.bbox.top;
+ poly[1].x = poly[2].x = gdiCache.nextPrim.a.rect.bbox.right;
+ poly[2].y = poly[3].y = gdiCache.nextPrim.a.rect.bbox.bottom;
+ poly[4] = poly[0];
+
+ /* perform call to render rectangle */
+ Polygon( gdiCache.metafile, poly, 5 );
+ }
+ else
+ {
+ Rectangle( gdiCache.metafile,
+ gdiCache.nextPrim.a.rect.bbox.left, gdiCache.nextPrim.a.rect.bbox.top,
+ gdiCache.nextPrim.a.rect.bbox.right, gdiCache.nextPrim.a.rect.bbox.bottom );
+ }
+ break;
+ }
+
+ case CaRoundRect:
+ {
+ RoundRect( gdiCache.metafile,
+ gdiCache.nextPrim.a.rect.bbox.left, gdiCache.nextPrim.a.rect.bbox.top,
+ gdiCache.nextPrim.a.rect.bbox.right, gdiCache.nextPrim.a.rect.bbox.bottom,
+ gdiCache.nextPrim.a.rect.oval.x, gdiCache.nextPrim.a.rect.oval.y );
+ break;
+ }
+
+ case CaEllipse:
+ {
+ Ellipse( gdiCache.metafile,
+ gdiCache.nextPrim.a.rect.bbox.left, gdiCache.nextPrim.a.rect.bbox.top,
+ gdiCache.nextPrim.a.rect.bbox.right, gdiCache.nextPrim.a.rect.bbox.bottom );
+ break;
+ }
+
+ case CaArc:
+ {
+ Arc( gdiCache.metafile,
+ gdiCache.nextPrim.a.arc.bbox.left, gdiCache.nextPrim.a.arc.bbox.top,
+ gdiCache.nextPrim.a.arc.bbox.right, gdiCache.nextPrim.a.arc.bbox.bottom,
+ gdiCache.nextPrim.a.arc.start.x, gdiCache.nextPrim.a.arc.start.y,
+ gdiCache.nextPrim.a.arc.end.x, gdiCache.nextPrim.a.arc.end.y );
+ break;
+ }
+
+ case CaPie:
+ {
+ Pie( gdiCache.metafile,
+ gdiCache.nextPrim.a.arc.bbox.left, gdiCache.nextPrim.a.arc.bbox.top,
+ gdiCache.nextPrim.a.arc.bbox.right, gdiCache.nextPrim.a.arc.bbox.bottom,
+ gdiCache.nextPrim.a.arc.start.x, gdiCache.nextPrim.a.arc.start.y,
+ gdiCache.nextPrim.a.arc.end.x, gdiCache.nextPrim.a.arc.end.y );
+ break;
+ }
+
+ case CaPolygon:
+ case CaPolyLine:
+ {
+ Point offset;
+ Integer i;
+
+ /* see if centering of the pen is required */
+ if (gdiCache.curPen.handle == gdiCache.nulPen)
+ {
+ /* no - just filling the object without frame */
+ offset.x = offset.y = 0;
+ }
+ else
+ {
+ /* transform all points to correct for down-right pen
+ rendering in QuickDraw and make for a GDI centered pen */
+ offset.x = gdiCache.nextPrim.a.poly.pnSize.x / 2;
+ offset.y = gdiCache.nextPrim.a.poly.pnSize.y / 2;
+ }
+
+ /* transform end point for all points in the polygon */
+ for (i = 0; i < gdiCache.numPoints; i++)
+ {
+ /* increment each coordinate pair off half of the pen size */
+ gdiCache.pointList[i].x += offset.x;
+ gdiCache.pointList[i].y += offset.y;
+ }
+
+ /* call the appropriate GDI routine based upon the type */
+ if (gdiCache.nextPrim.type == CaPolygon)
+ {
+ Polygon( gdiCache.metafile,
+ gdiCache.pointList,
+ gdiCache.numPoints );
+ }
+ else
+ {
+ Polyline( gdiCache.metafile,
+ gdiCache.pointList,
+ gdiCache.numPoints );
+ }
+ break;
+ }
+ }
+
+ /* mark the primitive cache as empty */
+ gdiCache.nextPrim.type = CaEmpty;
+
+} /* CaFlushCache */
+
+
+
+void CaFlushAttributes( void )
+/*====================*/
+/* flush any pending attribute elements */
+{
+ /* select the cached pen - the routine will determine if one exits */
+ SelectCachedPen();
+
+} /* CaFlushAttributes */
+
+
+
+void CaCreatePenIndirect( LOGPEN far * newLogPen )
+/*======================*/
+/* create a new pen */
+{
+ PenLPtr compare;
+ Boolean different;
+
+ /* determine which pen to compare against */
+ compare = (gdiCache.nextPen.handle != NULL) ? &gdiCache.nextPen :
+ &gdiCache.curPen;
+
+ /* compare the two pens */
+ different = ((newLogPen->lopnStyle != compare->logPen.lopnStyle) ||
+ (newLogPen->lopnColor != compare->logPen.lopnColor) ||
+ (newLogPen->lopnWidth.x != compare->logPen.lopnWidth.x));
+
+ /* if the pens are different ... */
+ if (different)
+ {
+ /* if there is a cached pen ... */
+ if (gdiCache.nextPen.handle != NULL)
+ {
+ /* flush the cached primitive - there is a change of pens */
+ CaFlushCache();
+
+ /* check to see if the new pen is changed by next selection */
+ different = ((newLogPen->lopnStyle != gdiCache.curPen.logPen.lopnStyle) ||
+ (newLogPen->lopnColor != gdiCache.curPen.logPen.lopnColor) ||
+ (newLogPen->lopnWidth.x != gdiCache.curPen.logPen.lopnWidth.x));
+ }
+ }
+
+ /* if the pen has changed from the current setting, cache the next pen */
+ if (different || gdiCache.curPen.handle == NULL)
+ {
+ /* if there is a pending line or polyline, the flush the cache */
+ if (gdiCache.nextPrim.type == CaLine || gdiCache.nextPrim.type == CaPolyLine)
+ {
+ CaFlushCache();
+ }
+
+ /* assign the new pen attributes */
+ gdiCache.nextPen.logPen = *newLogPen;
+
+ /* currently not using a stock pen object */
+ gdiCache.nextPen.stockObject = FALSE;
+
+ /* check for any pre-defined pen objects */
+ if (gdiCache.nextPen.logPen.lopnStyle == PS_NULL)
+ {
+ /* and use them if possible */
+ gdiCache.nextPen.handle = gdiCache.nulPen;
+ gdiCache.nextPen.stockObject = TRUE;
+ }
+ else if (gdiCache.nextPen.logPen.lopnWidth.x == 1)
+ {
+ if (newLogPen->lopnColor == RGB( 0, 0, 0 ))
+ {
+ gdiCache.nextPen.handle = gdiCache.blackPen;
+ gdiCache.nextPen.stockObject = TRUE;
+ }
+ else if (gdiCache.nextPen.logPen.lopnColor == RGB( 255, 255, 255 ))
+ {
+ gdiCache.nextPen.handle = gdiCache.whitePen;
+ gdiCache.nextPen.stockObject = TRUE;
+ }
+ }
+
+ if (!gdiCache.nextPen.stockObject)
+ {
+ /* otherwise, create a new pen */
+ gdiCache.nextPen.handle = CreatePenIndirect( &gdiCache.nextPen.logPen );
+ }
+ }
+ else
+ {
+ /* copy the current setting back into the next pen setting */
+ gdiCache.nextPen = gdiCache.curPen;
+ }
+
+ /* check if cache was invalidated */
+ if (gdiCache.restorePen && (gdiCache.curPen.handle != NULL))
+ {
+ /* if pen was invalidated by RestoreDC(), reselect it */
+ SelectObject( gdiCache.metafile, gdiCache.curPen.handle );
+ }
+
+ /* all is ok with cache now */
+ gdiCache.restorePen = FALSE;
+
+} /* CaCreatePenIndirect */
+
+
+
+void CaCreateBrushIndirect( LOGBRUSH far * newLogBrush )
+/*========================*/
+/* Create a new logical brush using structure passed in */
+{
+ /* assume that the DIB patterns are different */
+ Boolean differentDIB = TRUE;
+
+ /* check if we are comparing two DIB patterned brushes */
+ if ((newLogBrush->lbStyle == BS_DIBPATTERN) &&
+ (gdiCache.curBrush.logBrush.lbStyle == BS_DIBPATTERN))
+ {
+ Word nextSize = (Word)GlobalSize( (HANDLE) newLogBrush->lbHatch ) / 2;
+ Word currSize = (Word)GlobalSize( (HANDLE) gdiCache.curBrush.logBrush.lbHatch ) / 2;
+
+ /* make sure that the sizes are the same */
+ if (nextSize == currSize)
+ {
+ Word far * nextDIBPattern = (Word far *)GlobalLock( (HANDLE) newLogBrush->lbHatch );
+ Word far * currDIBPattern = (Word far *)GlobalLock( (HANDLE) gdiCache.curBrush.logBrush.lbHatch );
+
+ /* assume that the DIBs are the same so far */
+ differentDIB = FALSE;
+
+ /* compare all the bytes in the two brush patterns */
+ while (currSize--)
+ {
+ /* are they the same ? */
+ if (*nextDIBPattern++ != *currDIBPattern++)
+ {
+ /* if not, flag the difference and break from the loop */
+ differentDIB = TRUE;
+ break;
+ }
+ }
+
+ /* Unlock the data blocks */
+ GlobalUnlock( (HANDLE) newLogBrush->lbHatch );
+ GlobalUnlock( (HANDLE) gdiCache.curBrush.logBrush.lbHatch );
+
+ /* see if these did compare exactly */
+ if (!differentDIB)
+ {
+ /* if so, free the new DIB brush - it's no longer needed */
+ GlobalFree( (HANDLE) newLogBrush->lbHatch );
+ }
+ }
+ }
+
+ /* see if we are requesting a new brush */
+ if (differentDIB &&
+ (newLogBrush->lbStyle != gdiCache.curBrush.logBrush.lbStyle ||
+ newLogBrush->lbColor != gdiCache.curBrush.logBrush.lbColor ||
+ newLogBrush->lbHatch != gdiCache.curBrush.logBrush.lbHatch ||
+ gdiCache.curBrush.handle == NULL))
+ {
+ HBRUSH brushHandle;
+ Boolean stockBrush;
+
+ /* flush the primitive cache if changing brush selection */
+ CaFlushCache();
+
+ /* if current brush has a DIB, make sure to free memory */
+ if (gdiCache.curBrush.logBrush.lbStyle == BS_DIBPATTERN)
+ {
+ /* free the memory */
+ GlobalFree( (HANDLE) gdiCache.curBrush.logBrush.lbHatch );
+ }
+
+ /* copy over the new structure */
+ gdiCache.curBrush.logBrush = *newLogBrush;
+
+ /* We currently aren't using a stock brush */
+ stockBrush = FALSE;
+
+ /* use stock objects if possible */
+ if (gdiCache.curBrush.logBrush.lbStyle == BS_HOLLOW)
+ {
+ /* use null (hollow) brush */
+ brushHandle = gdiCache.nulBrush;
+ stockBrush = TRUE;
+ }
+ /* check for some standard solid colored brushes */
+ else if (gdiCache.curBrush.logBrush.lbStyle == BS_SOLID)
+ {
+ if (gdiCache.curBrush.logBrush.lbColor == RGB( 0, 0, 0) )
+ {
+ /* use solid black brush */
+ brushHandle = gdiCache.blackBrush;
+ stockBrush = TRUE;
+ }
+ else if (gdiCache.curBrush.logBrush.lbColor == RGB( 255, 255, 255 ))
+ {
+ /* use solid white brush */
+ brushHandle = gdiCache.whiteBrush;
+ stockBrush = TRUE;
+ }
+ }
+
+ /* if unable to find a stock brush, then create a new one */
+ if (!stockBrush)
+ {
+ /* otherwise, create new brush using logbrush structure */
+ brushHandle = CreateBrushIndirect( &gdiCache.curBrush.logBrush );
+ }
+
+ /* select the new brush */
+ SelectObject( gdiCache.metafile, brushHandle );
+
+ /* if this isn't the first brush selection and not a stock brush */
+ if (gdiCache.curBrush.handle != NULL && !gdiCache.curBrush.stockObject)
+ {
+ /* delete the previous brush object */
+ DeleteObject( gdiCache.curBrush.handle );
+ }
+
+ /* save brush handle in current cache variable */
+ gdiCache.curBrush.handle = brushHandle;
+ gdiCache.curBrush.stockObject = stockBrush;
+ }
+ else if (gdiCache.restoreBrush)
+ {
+ /* if brush was invalidated by RestoreDC(), reselect it */
+ SelectObject( gdiCache.metafile, gdiCache.curBrush.handle );
+ }
+
+ /* all is ok with cache now */
+ gdiCache.restoreBrush = FALSE;
+
+} /* CaCreateBrushIndirect */
+
+
+
+void CaCreateFontIndirect( LOGFONT far * newLogFont )
+/*=======================*/
+/* create the logical font passed as paramter */
+{
+ /* make sure we are requesting a new font */
+ if (newLogFont->lfHeight != gdiCache.curLogFont.lfHeight ||
+ newLogFont->lfWeight != gdiCache.curLogFont.lfWeight ||
+ newLogFont->lfEscapement != gdiCache.curLogFont.lfEscapement ||
+ newLogFont->lfOrientation != gdiCache.curLogFont.lfOrientation ||
+ newLogFont->lfItalic != gdiCache.curLogFont.lfItalic ||
+ newLogFont->lfUnderline != gdiCache.curLogFont.lfUnderline ||
+ newLogFont->lfPitchAndFamily != gdiCache.curLogFont.lfPitchAndFamily ||
+ lstrcmp( newLogFont->lfFaceName, gdiCache.curLogFont.lfFaceName ) != 0 ||
+ gdiCache.curFont == NULL)
+ {
+ HFONT fontHandle;
+ Boolean stockFont;
+
+ /* flush the primitive cache if changing font attributes */
+ CaFlushCache();
+
+ /* assign the new pen attributes */
+ gdiCache.curLogFont = *newLogFont;
+
+ /* currently not using a stock font object */
+ stockFont = FALSE;
+
+ /* check for any pre-defined pen objects */
+ if (newLogFont->lfFaceName == NULL)
+ {
+ fontHandle = GetStockObject( SYSTEM_FONT );
+ stockFont = TRUE;
+ }
+ else
+ {
+ /* otherwise, create a new pen */
+ fontHandle = CreateFontIndirect( &gdiCache.curLogFont );
+ }
+
+ /* select the new font */
+ SelectObject( gdiCache.metafile, fontHandle );
+
+ /* if this isn't the first font selection and not a stock font */
+ if (gdiCache.curFont != NULL && !gdiCache.stockFont)
+ {
+ /* delete the previous font object */
+ DeleteObject( gdiCache.curFont );
+ }
+
+ /* save font handle in current cache variable */
+ gdiCache.curFont = fontHandle;
+ gdiCache.stockFont = stockFont;
+ }
+ else if (gdiCache.restoreFont)
+ {
+ /* if pen was invalidated by RestoreDC(), reselect it */
+ SelectObject( gdiCache.metafile, gdiCache.curFont );
+ }
+
+ /* all is ok with cache now */
+ gdiCache.restoreFont = FALSE;
+
+} /* CaCreateFontIndirect */
+
+
+
+void CaSetBkMode( Word mode )
+/*==============*/
+/* set the backgound transfer mode */
+{
+ if (gdiCache.curBkMode != mode)
+ {
+ /* flush the primitive cache if changing mode */
+ CaFlushCache();
+
+ /* set the background mode and save in global cache */
+ SetBkMode( gdiCache.metafile, mode );
+ gdiCache.curBkMode = mode;
+ }
+
+ /* no need to worry about restoring BkMode, since this is set
+ before the initial SaveDC() is issued and is restored after each
+ RestoreDC() call back to the metafile default. */
+
+} /* CaSetBkMode */
+
+
+
+void CaSetROP2( Word ROP2Code )
+/*============*/
+/* set the transfer ROP mode according to ROP2Code */
+{
+ /* check for change in ROP code */
+ if (gdiCache.curROP2 != ROP2Code)
+ {
+ /* flush the primitive cache if changing ROP mode */
+ CaFlushCache();
+
+ /* set the ROP code and save in global cache variable */
+ SetROP2( gdiCache.metafile, ROP2Code );
+ gdiCache.curROP2 = ROP2Code;
+ }
+
+ /* no need to worry about restoring ROP code, since this is set
+ before the initial SaveDC() is issued and is restored after each
+ RestoreDC() call back to the metafile default. */
+
+} /* CaSetROP2 */
+
+
+
+void CaSetStretchBltMode( Word mode )
+/*======================*/
+/* stretch blt mode - how to preserve scanlines using StretchDIBits() */
+{
+ if (gdiCache.curStretchMode != mode)
+ {
+ /* flush the primitive cache if changing mode */
+ CaFlushCache();
+
+ /* set the stretch blt mode and save in global cache variable */
+ SetStretchBltMode( gdiCache.metafile, mode );
+ gdiCache.curStretchMode = mode;
+ }
+ else if (gdiCache.restoreStretchMode)
+ {
+ /* if stretch blt mode was invalidated by RestoreDC(), re-issue */
+ SetStretchBltMode( gdiCache.metafile, gdiCache.curStretchMode );
+ }
+
+ /* all is ok with cache now */
+ gdiCache.restoreStretchMode = FALSE;
+
+} /* CaSetStretchBltMode */
+
+
+
+void CaSetTextAlign( Word txtAlign )
+/*=================*/
+/* set text alignment according to parameter */
+{
+ if (gdiCache.curTextAlign != txtAlign)
+ {
+ /* flush the primitive cache if changing text alignment */
+ CaFlushCache();
+
+ /* Set the text color and save in cache */
+ SetTextAlign( gdiCache.metafile, txtAlign );
+ gdiCache.curTextAlign = txtAlign;
+ }
+
+ /* no need to worry about restoring text align, since this is set
+ before the initial SaveDC() is issued and is restored after each
+ RestoreDC() call back to the metafile default. */
+
+} /* CaSetTextAlign */
+
+
+void CaSetTextColor( RGBColor txtColor )
+/*=================*/
+/* set the text color if different from current setting */
+{
+ if (gdiCache.curTextColor != txtColor)
+ {
+ /* flush the primitive cache if changing text color */
+ CaFlushCache();
+
+ /* Set the text color and save in cache */
+ SetTextColor( gdiCache.metafile, txtColor );
+ gdiCache.curTextColor = txtColor;
+ }
+
+ /* no need to worry about restoring text color, since this is set
+ before the initial SaveDC() is issued and is restored after each
+ RestoreDC() call back to the metafile default. */
+
+} /* CaSetTextColor */
+
+
+void CaSetTextCharacterExtra( Integer chExtra )
+/*==========================*/
+/* set the character extra spacing */
+{
+ if (gdiCache.curCharExtra != chExtra)
+ {
+ /* flush the primitive cache if changing text char extra */
+ CaFlushCache();
+
+ /* set the char extra and same state in the cache */
+ SetTextCharacterExtra( gdiCache.metafile, chExtra );
+ gdiCache.curCharExtra = chExtra;
+
+ }
+ else if (gdiCache.restoreCharExtra)
+ {
+ /* if text char extra was invalidated by RestoreDC(), re-issue */
+ SetTextCharacterExtra( gdiCache.metafile, gdiCache.curCharExtra );
+ }
+
+ /* all is ok with cache now */
+ gdiCache.restoreCharExtra = FALSE;
+
+} /* CaSetTextCharacterExtra */
+
+
+void CaSetBkColor( RGBColor bkColor )
+/*===============*/
+/* set background color if different from current setting */
+{
+ if (gdiCache.curBkColor != bkColor)
+ {
+ /* flush the primitive cache if changing background color */
+ CaFlushCache();
+
+ /* Set the background color and save in cache */
+ SetBkColor( gdiCache.metafile, bkColor );
+ gdiCache.curBkColor = bkColor;
+ }
+
+ /* no need to worry about restoring background color, since this is set
+ before the initial SaveDC() is issued and is restored after each
+ RestoreDC() call back to the metafile default. */
+
+} /* CaSetBkColor */
+
+
+Boolean CaIntersectClipRect( Rect rect )
+/*=========================*/
+/* Create new clipping rectangle - return FALSE if drawing is disabled */
+{
+ Rect combinedRect;
+
+ /* See if the clipping rectangle is empty, indicating that no drawing
+ should occur into the metafile */
+ if (Height( rect ) == 0 || Width( rect ) == 0)
+ {
+ /* indicate that drawing is disabled */
+ return FALSE;
+ }
+
+ /* don't do anything if rectangle hasn't changed */
+ if (!EqualRect( &rect, &gdiCache.curClipRect ) || gdiCache.forceNewClipRect)
+ {
+ /* flush the primitive cache if changing clip region */
+ CaFlushCache();
+
+ /* is new clip rect is completely enclosed by current cliprect? */
+ IntersectRect( &combinedRect, &rect, &gdiCache.curClipRect );
+
+ /* check for equality of intersection and new cliprect */
+ if (!EqualRect( &combinedRect, &rect ) || gdiCache.forceNewClipRect)
+ {
+ /* must be called just to be able to change clipping rectangle */
+ CaRestoreDC();
+ CaSaveDC();
+ }
+
+ /* set the new clipping rectangle */
+ IntersectClipRect( gdiCache.metafile,
+ rect.left, rect.top, rect.right, rect.bottom );
+
+ /* save the current clip rectangle, since it has changed */
+ gdiCache.curClipRect = rect;
+
+ /* turn off forcing of the clipping rectangle */
+ gdiCache.forceNewClipRect = FALSE;
+ }
+
+ /* return TRUE - drawing is enabled */
+ return TRUE;
+
+} /* GdiIntersectClipRect */
+
+
+void CaSetClipRect( Rect rect )
+/*================*/
+/* set the current cliprectangle to be equal to rect */
+{
+ gdiCache.curClipRect = rect;
+
+} /* CaSetClipRect */
+
+
+Rect far * CaGetClipRect( void )
+/*=====================*/
+/* get the current cliprectangle */
+{
+ return &gdiCache.curClipRect;
+
+} /* CaGetClipRect */
+
+
+void CaNonRectangularClip( void )
+/*=======================*/
+/* notify cache that a non-rectangular clipping region was set */
+{
+ gdiCache.forceNewClipRect = TRUE;
+
+} /* CaNonRectangularClip */
+
+
+void CaSaveDC( void )
+/*===========*/
+/* save the current device context - used to set up clipping rects */
+{
+ /* the previous clipping rectangle is saved off */
+ gdiCache.prevClipRect = gdiCache.curClipRect;
+
+ /* issue call to GDI */
+ SaveDC( gdiCache.metafile );
+}
+
+
+void CaRestoreDC( void )
+/*==============*/
+/* restore the device context and invalidate cached attributes */
+{
+ /* restore previous clipping rectangle */
+ gdiCache.curClipRect = gdiCache.prevClipRect;
+
+ /* invalidate all of the cached attributes and objects */
+ gdiCache.restorePen =
+ gdiCache.restoreBrush =
+ gdiCache.restoreFont =
+ gdiCache.restoreCharExtra = TRUE;
+
+ /* reset metafile defaults */
+ gdiCache.curROP2 = gdiCache.iniROP2;
+ gdiCache.curTextAlign = gdiCache.iniTextAlign;
+ gdiCache.curBkMode = gdiCache.iniBkMode;
+ gdiCache.curTextColor = gdiCache.iniTxColor;
+ gdiCache.curBkColor = gdiCache.iniBkColor;
+
+ /* issue call to GDI */
+ RestoreDC( gdiCache.metafile, -1 );
+}
+
+/******************************* Private Routines ***************************/
+
+
+private void AddPolyPt( Point pt )
+/*--------------------*/
+/* Add a point to the polygon buffer */
+{
+ /* make sure that we haven't reached maximum size */
+ if ((gdiCache.numPoints + 1) >= gdiCache.maxPoints)
+ {
+ /* expand the number of points that can be cached by 10 */
+ gdiCache.maxPoints += 16;
+
+ /* unlock to prepare for re-allocation */
+ GlobalUnlock( gdiCache.polyHandle);
+
+ /* re-allocate the memory handle by the given amount */
+ gdiCache.polyHandle = GlobalReAlloc(
+ gdiCache.polyHandle,
+ gdiCache.maxPoints * sizeof( Point ),
+ GMEM_MOVEABLE);
+
+ /* make sure that the re-allocation succeeded */
+ if (gdiCache.polyHandle == NULL)
+ {
+ /* if not, flag global error and exit from here */
+ ErSetGlobalError( ErMemoryFull );
+ return;
+ }
+
+ /* lock the memory handle to get a pointer address */
+ gdiCache.pointList = (Point far *)GlobalLock( gdiCache.polyHandle );
+ }
+
+ /* insert the new point and increment the number of points in the buffer */
+ gdiCache.pointList[gdiCache.numPoints++] = pt;
+
+} /* AddPolyPt */
+
+
+
+private void SelectCachedPen( void )
+/*--------------------------*/
+/* select the currently cached Pen into the metafile */
+{
+ /* make sure that there is some new pen to select */
+ if (gdiCache.nextPen.handle != NULL)
+ {
+ /* make sure that the pens are different */
+ if (gdiCache.nextPen.handle != gdiCache.curPen.handle)
+ {
+ /* select the new pen */
+ SelectObject( gdiCache.metafile, gdiCache.nextPen.handle);
+
+ /* if this isn't the first pen selection and not a stock pen */
+ if (gdiCache.curPen.handle != NULL && !gdiCache.curPen.stockObject)
+ {
+ /* delete the previous pen selection */
+ DeleteObject( gdiCache.curPen.handle );
+ }
+
+ /* save pen handle in current cache variable */
+ gdiCache.curPen = gdiCache.nextPen;
+ }
+
+ /* reset the cache pen to indicate no pre-existing cached pen */
+ gdiCache.nextPen.handle = NULL;
+ }
+
+} /* SelectCachedPen */
+
diff --git a/private/ole32/olecnv32/cache.h b/private/ole32/olecnv32/cache.h
new file mode 100644
index 000000000..3ca67846f
--- /dev/null
+++ b/private/ole32/olecnv32/cache.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+ Unit Cache; Interface
+*****************************************************************************
+
+ Module Prefix: Ca
+
+*****************************************************************************/
+
+
+#define CaEmpty 0
+#define CaLine 1
+#define CaRectangle 2
+#define CaRoundRect 3
+#define CaEllipse 4
+#define CaArc 5
+#define CaPie 6
+#define CaPolygon 7
+#define CaPolyLine 8
+
+typedef struct
+{
+ Word type;
+ Word verb;
+ union
+ {
+ struct
+ {
+ Point start;
+ Point end;
+ Point pnSize;
+ } line;
+
+ struct
+ {
+ Rect bbox;
+ Point oval;
+ } rect;
+
+ struct
+ {
+ Rect bbox;
+ Point start;
+ Point end;
+ } arc;
+
+ struct
+ {
+ Integer numPoints;
+ Point far * pointList;
+ Point pnSize;
+ } poly;
+
+ } a;
+
+} CaPrimitive, far * CaPrimitiveLPtr;
+
+
+/*********************** Exported Function Definitions **********************/
+
+void CaInit( Handle metafile );
+/* initialize the gdi cache module */
+
+
+void CaFini( void );
+/* close down the cache module */
+
+
+void CaSetMetafileDefaults( void );
+/* Set up any defaults that will be used throughout the metafile context */
+
+
+Word CaGetCachedPrimitive( void );
+/* return the current cached primitive type */
+
+
+void CaSamePrimitive( Boolean same );
+/* indicate whether next primitive is the same or new */
+
+
+void CaMergePen( Word verb );
+/* indicate that next pen should be merged with previous logical pen */
+
+
+void CaCachePrimitive( CaPrimitiveLPtr primLPtr );
+/* Cache the primitive passed down. This includes the current pen and brush. */
+
+
+void CaFlushCache( void );
+/* Flush the current primitive stored in the cache */
+
+
+void CaFlushAttributes( void );
+/* flush any pending attribute elements */
+
+
+void CaCreatePenIndirect( LOGPEN far * newLogPen );
+/* create a new pen */
+
+
+void CaCreateBrushIndirect( LOGBRUSH far * newLogBrush );
+/* Create a new logical brush using structure passed in */
+
+
+void CaCreateFontIndirect( LOGFONT far * newLogFont );
+/* create the logical font passed as paramter */
+
+
+void CaSetBkMode( Word mode );
+/* set the backgound transfer mode */
+
+
+void CaSetROP2( Word ROP2Code );
+/* set the transfer ROP mode according to ROP2Code */
+
+
+void CaSetStretchBltMode( Word mode );
+/* stretch blt mode - how to preserve scanlines using StretchDIBits() */
+
+
+void CaSetTextAlign( Word txtAlign );
+/* set text alignment according to parameter */
+
+
+void CaSetTextColor( RGBColor txtColor );
+/* set the text color if different from current setting */
+
+
+void CaSetTextCharacterExtra( Integer chExtra );
+/* set the character extra spacing */
+
+
+void CaSetBkColor( RGBColor bkColor );
+/* set background color if different from current setting */
+
+
+Boolean CaIntersectClipRect( Rect rect );
+/* Create new clipping rectangle - return FALSE if drawing is disabled */
+
+
+void CaSetClipRect( Rect rect );
+/* set the current cliprectangle to be equal to rect */
+
+Rect far * CaGetClipRect( void );
+/* return the current cached clip rectangle */
+
+void CaNonRectangularClip( void );
+/* notify cache that a non-rectangular clipping region was set */
+
+void CaSaveDC( void );
+/* save the current device context - used to set up clipping rects */
+
+
+void CaRestoreDC( void );
+/* restore the device context and invalidate cached attributes */
diff --git a/private/ole32/olecnv32/daytona/makefile b/private/ole32/olecnv32/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/olecnv32/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/olecnv32/daytona/makefile.inc b/private/ole32/olecnv32/daytona/makefile.inc
new file mode 100644
index 000000000..254aa09c2
--- /dev/null
+++ b/private/ole32/olecnv32/daytona/makefile.inc
@@ -0,0 +1 @@
+obj\$(TARGET_DIRECTORY)\olecnv32.def: olecnv32.src
diff --git a/private/ole32/olecnv32/daytona/olecnv32.src b/private/ole32/olecnv32/daytona/olecnv32.src
new file mode 100644
index 000000000..4b68c80e4
--- /dev/null
+++ b/private/ole32/olecnv32/daytona/olecnv32.src
@@ -0,0 +1,35 @@
+#if 0
+
+ Microsoft Windows
+ Copyright (C) Microsoft Corporation, 1992 - 1992.
+ All rights reserved.
+
+ This .def file is preprocessed by the compiler to create the version for
+ the current build in the appropriate subdir. Basically, whatever you
+ would have used in your code to control what is compiled when can be
+ used in this file for the same purpose. The following defines are in
+ use at the time this file was written:
+
+ i386 - Intel i386/i486 build
+ MIPS - MIPS R3000/R4000 build
+ ALPHA - DEC Alpha build
+ DBG - Used to control Debug/Retail. Set to 1 if Debug,
+ 0 if Retail.
+ WIN31 - Win16 build
+ __OS2__ - OS/2 build (used by CT mostly)
+
+ If none of these are used, it is assumed the entire file can be used
+ for all builds.
+
+#endif
+
+#ifdef WIN32
+
+LIBRARY OLECNV32
+
+DESCRIPTION 'QuickDraw to GDI Conversion DLL for 32-bit OLE'
+
+EXPORTS
+ QD2GDI PRIVATE
+
+#endif // WIN32
diff --git a/private/ole32/olecnv32/daytona/sources b/private/ole32/olecnv32/daytona/sources
new file mode 100644
index 000000000..bb942c64b
--- /dev/null
+++ b/private/ole32/olecnv32/daytona/sources
@@ -0,0 +1,83 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = olecnv32
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= olecnv32
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= DYNLINK
+
+DLLDEF= obj\$(TARGET_DIRECTORY)\olecnv32.def
+
+DLLBASE=@$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,usermode
+
+!include ..\..\daytona.inc
+
+INCLUDES= ..;..\..\ih
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -D_OLECNV32_
+
+SOURCES= \
+ ..\api.c \
+ ..\bufio.c \
+ ..\cache.c \
+ ..\error.c \
+ ..\gdiprim.c \
+ ..\getdata.c \
+ ..\quickdrw.c \
+ ..\olecnv32.rc
+
+DLLENTRY=LibMain
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+LINKER_FLAGS=-verbose
+LINKLIBS= $(WIN32_LIBS) \
+ $(GUI32_LIBS)
+
+USE_CRTDLL=1
+
+PRECOMPILED_INCLUDE= ..\headers.c
+
+NTTARGETFILE0=$(DLLDEF)
diff --git a/private/ole32/olecnv32/dirs b/private/ole32/olecnv32/dirs
new file mode 100644
index 000000000..d3eda5293
--- /dev/null
+++ b/private/ole32/olecnv32/dirs
@@ -0,0 +1,40 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+#
+# Note that is currently omitted because there is no difference
+# from the daytona binary.
+OPTIONAL_DIRS= \
+ \
+ daytona
diff --git a/private/ole32/olecnv32/error.c b/private/ole32/olecnv32/error.c
new file mode 100644
index 000000000..3f0685957
--- /dev/null
+++ b/private/ole32/olecnv32/error.c
@@ -0,0 +1,74 @@
+/****************************************************************************
+ Unit Bufio; Implementation
+*****************************************************************************
+
+ Error handles all the interpretation, metafile creation, or read failures
+ that may occur during the course of the translation.
+
+ Currently it only supports saving a single error into a global variable.
+
+ Module Prefix: Er
+
+****************************************************************************/
+
+#include "headers.c"
+#pragma hdrstop
+
+#ifndef _OLECNV32_
+#define IMPDEFS
+#include "errdefs.h" /* Aldus error return codes */
+#endif
+
+/*********************** Exported Data **************************************/
+
+
+/*********************** Private Data ***************************************/
+
+OSErr globalError; /* not declared private for macro calls */
+
+/*********************** Private Function Definitions ***********************/
+
+
+/*********************** Function Implementation ****************************/
+
+#ifndef _OLECNV32_
+
+OSErr ErInternalErrorToAldus( void )
+/*==========================*/
+/* returns the appropriate Aldus error code given the current global error */
+{
+ switch (globalError)
+ {
+ case ErNoError : return NOERR;
+
+ case ErInvalidVersion :
+ case ErInvalidVersionID :
+ case ErBadHeaderSequence : return IE_NOT_MY_FILE;
+
+ case ErCreateMetafileFail :
+ case ErCloseMetafileFail :
+ case ErMemoryFull : return IE_MEM_FULL;
+
+ case ErMemoryFail : return IE_MEM_FAIL;
+
+ case ErNullBoundingRect :
+ case ErReadPastEOF : return IE_BAD_FILE_DATA;
+
+ case ErEmptyPicture : return IE_NOPICTURES;
+
+ case Er32KBoundingRect : return IE_TOO_BIG;
+
+ case ErNoDialogBox :
+ case ErOpenFail :
+ case ErReadFail : return IE_IMPORT_ABORT;
+
+ case ErNoSourceFormat :
+ case ErNonSquarePen :
+ case ErInvalidXferMode :
+ case ErNonRectRegion : return IE_UNSUPP_VERSION;
+
+ default : return IE_IMPORT_ABORT;
+ }
+}
+
+#endif
diff --git a/private/ole32/olecnv32/error.h b/private/ole32/olecnv32/error.h
new file mode 100644
index 000000000..789cecb6e
--- /dev/null
+++ b/private/ole32/olecnv32/error.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+ Unit Error; Interface
+*****************************************************************************
+
+ Error handles all the interpretation, metafile creation, or read failures
+ that may occur during the course of the translation.
+
+ Module Prefix: Er
+
+*****************************************************************************/
+
+
+/********************* Exported Data ***************************************/
+
+#define ErNoError NOERR
+#define ErInvalidVersion 1 /* file is not version 1 or 2 */
+#define ErInvalidVersionID 2 /* PICT 2 version ID invalid */
+#define ErBadHeaderSequence 3 /* PICT 2 HeaderOp not found */
+#define ErInvalidPrefsHeader 4 /* Preferences header invalid */
+#define ErNoSourceFormat 5 /* no source filename/handle given */
+
+#define ErMemoryFull 10 /* GlobalAlloc() fail */
+#define ErMemoryFail 11 /* GlobalLock() fail */
+#define ErCreateMetafileFail 12 /* CreateMetafile() fail */
+#define ErCloseMetafileFail 13 /* CloseMetafile() fail */
+
+#define ErEmptyPicture 20 /* no primitives found in file */
+
+#define ErNullBoundingRect 30 /* BBox defines NULL area */
+#define Er32KBoundingRect 31 /* BBox extents exceed 32K */
+
+#define ErReadPastEOF 40 /* Attempt to read past end of file */
+#define ErOpenFail 41 /* OpenFile() failed */
+#define ErReadFail 42 /* read from disk failed */
+
+#define ErNonSquarePen 50 /* non-square pen & user pref abort */
+#define ErPatternedPen 51 /* patterned pen & user pref abort */
+#define ErInvalidXferMode 52 /* invalid transfer mode & abort */
+#define ErNonRectRegion 53 /* non-rectangular region abort */
+
+#define ErNoDialogBox 60 /* unable to run status dialog box */
+
+extern OSErr globalError;
+
+/*********************** Exported Function Definitions **********************/
+
+#define ErSetGlobalError( /* OSErr */ error ) \
+/* callback function that allows any routine to set a global error state */ \
+globalError = error
+
+#define ErGetGlobalError( /* void */ ) \
+/* callback function that allows any routine to get global error state */ \
+globalError
+
+OSErr ErInternalErrorToAldus( void );
+/* returns the appropriate Aldus error code given the current global error */
diff --git a/private/ole32/olecnv32/filesys.h b/private/ole32/olecnv32/filesys.h
new file mode 100644
index 000000000..b048c17f5
--- /dev/null
+++ b/private/ole32/olecnv32/filesys.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+ Unit FileSys; Interface
+*****************************************************************************
+
+ FileSys implements the DOS file system calls used by the Presenter and BFile.
+ The interface is preserved to be mostly the same as the MAC OS interface.
+ All filenames and directories passed as arguments are assumned to be in Ansi,
+ and all filenames and directories returned will be in Ansi.
+
+ Module prefix: FS
+
+****************************************************************************/
+
+
+/********************* Exported Data ***************************************/
+
+#define FSFROMSTART 0 /* From Start of file */
+#define FSFROMMARK 1 /* From current file marker */
+#define FSFROMLEOF 2 /* From End of File */
+
+/* File System errors */
+
+#define FSERROR -1 /* failure flage for file I/O */
+#define FUNCERR 1 /* invalid function */
+#define FNFERR 2 /* DOS file not found */
+#define DIRNFERR 3 /* Path not found */
+#define DUPFNERR 4 /* DOS too many files opened */
+#define TMFOERR 4
+#define OPWRERR 5 /* DOS Access denied error */
+#define FNOPNERR 6 /* DOS invalid handle */
+#define MEMFULLERR 8 /* Insufficient memory */
+#define IOERR 13 /* DOS invalid data */
+#define VOLOFFLINERR 15 /* DOS Drive not ready */
+#define WPRERR 19 /* DOS disk write-protected */
+#define POSERR 25 /* Invalid Seek */
+#define PERMERR 32 /* DOS sharing violation */
+#define VLCKDERR 33 /* DOS lock violation */
+#define WRPERMERR 65 /* Network Write Permission Error: access denied */
+#define DIRFULERR 82 /* DOS cannot make directory entry */
+#define ABORTERR 83 /* Fail DOS int24 critical handler */
+
+#define DSKFULERR -34 /* MAC Disk full error */
+#define EOFERR -39 /* MAC end-of-file error */
+#define FBSYERR -47 /* MAC file busy error */
+#define FLCKDERR -49 /* MAC file is locked error */
+
+/* Scrap Manager errors */
+#define NOSCRAPERR -100 /* MAC Desk scrap isn't initialized */
+#define NOFORMATERR -101 /* MAC No data of the requested format */
+#define SPOPENERR -102 /* PP Couldn't open the scrap */
+#define SPDATAERR -103 /* PP the scrap had invalid data */
+
+#define MAXBLERR - 2 /* Block too large error */
+
+/* File attribute constants */
+#define FS_NORMAL 0x00 /* Normal file - No read/write restrictions */
+#define FS_RDONLY 0x01 /* Read only file */
+#define FS_HIDDEN 0x02 /* Hidden file */
+#define FS_SYSTEM 0x04 /* System file */
+#define FS_VOLID 0x08 /* Volume ID file */
+#define FS_SUBDIR 0x10 /* Subdirectory */
+#define FS_ARCH 0x20 /* Archive file */
+
+
+/********************* Exported Operations *********************************/
+
+OSErr FSRead( Integer fileRef, LongInt far * lbytes, LPtr des);
+/* Read lbytes long from file fileRef to buffer des. 'Lbytes' is updated to
+ indicate the number of bytes actually read. Error is returned by function
+ if !FALSE. */
+
+OSErr FSGetFPos( Integer fileRef, LongInt far * markPos );
+/* Get the current mark position in fileRef. Return that position
+ in markPos. Function returns error code if !NOERR. */
+
+OSErr FSSetFPos(Integer fileRef, Word postype, LongInt Offset);
+/* Move the fileRef file pointer to the new position Offset */
+
+OSErr FSOpen( StringLPtr filename, Word mode, Integer far* fileRef);
+/* Open filename with DOS OPEN 'mode' and return a valid 'fileRef' if NOERR.
+ Create an entry in the internal file table and initialize it. The DOS
+ handle is left opened (for performance reasons) until
+ FSTempClose(fileRef) is called. Return the appropriate error
+ if failed. */
+
+OSErr FSCloseFile(Integer fileRef);
+/* Close the file given its 'fileRef'. Also remove its file table entry. */
+
+
diff --git a/private/ole32/olecnv32/gdiprim.c b/private/ole32/olecnv32/gdiprim.c
new file mode 100644
index 000000000..f94b16cac
--- /dev/null
+++ b/private/ole32/olecnv32/gdiprim.c
@@ -0,0 +1,4080 @@
+
+/****************************************************************************
+ Unit GdiPrim; Implementation
+*****************************************************************************
+
+ The Gdi module is called directly by the QuickDraw (QD) module in order
+ to emit metafile primitives. It is responsible for accessing the current
+ CGrafPort structure in order to access the individual attribute settings.
+
+ It also supports the caching and redundant elimination of duplicate
+ elements when writing to the metafile.
+
+ Module Prefix: Gdi
+
+****************************************************************************/
+
+#include "headers.c"
+#pragma hdrstop
+
+#include "math.h" /* for floating-point (sin, cos) calculations */
+#include "qdcoment.i" /* for interpretation of picture comments */
+#include "cache.h" /* for all drawing to metafile context */
+
+/*********************** Exported Data **************************************/
+
+/*********************** Private Data ***************************************/
+
+/*--- mixture of grey values ---*/
+
+#define NOMIX FALSE
+#define MIXGREY TRUE
+
+/*--- Gdi environment ---*/
+
+typedef struct{
+ Handle metafile; // metafile handle
+
+ LOGBRUSH newLogBrush;
+ LOGFONT newLogFont;
+ LOGPEN newLogPen;
+
+ Rect clipRect; // current clip rectangle
+
+ Boolean drawingEnabled; // is drawing currently enabled?
+ Boolean sameObject; // same primitive being drawn?
+ Boolean useGdiFont; // override font search w/Gdi name?
+
+ Integer hatchIndex; // hatch pattern for fills
+
+ Pattern lastPattern; // patterns used for the current
+ Integer lastPatType; // brush selection
+ RGBColor lastFgColor; // fore- and background colors
+ RGBColor lastBkColor; // used to create selected brush
+
+ HDC infoContext; // information context for fonts
+ FONTENUMPROC fontFunction; // used to access font information
+
+ Byte state[GdiNumAttrib]; // have various attributes changed
+
+} GdiEnv;
+
+private GdiEnv gdiEnv;
+private ConvPrefsLPtr gdiPrefsLPtr;
+private PICTINFO gdiPict;
+
+
+/*--- Font face translation ---*/
+
+#define FntSystemFont 0
+#define FntApplFont 1
+#define FntNewYork 2
+#define FntGeneva 3
+#define FntMonaco 4
+#define FntVenice 5
+#define FntLondon 6
+#define FntAthens 7
+#define FntSanFran 8
+#define FntToronto 9
+#define FntCairo 11
+#define FntLosAngeles 12
+#define FntZapfDingbats 13
+#define FntBookman 14
+#define FntHelvNarrow 15
+#define FntPalatino 16
+#define FntZapfChancery 18
+#define FntTimes 20
+#define FntHelvetica 21
+#define FntCourier 22
+#define FntSymbol 23
+#define FntMobile 24
+#define FntAvantGarde 33
+#define FntNewCentury 34
+#define FntMTExtra 2515
+#define FntUnknown -1
+
+#define MaxFntName LF_FACESIZE
+#define NumFntEntries 27
+#define NumTTSubs 12
+#define TTSubStart 11
+#define FntFromGdi (NumFntEntries - 1)
+#define FntNoMatch (NumFntEntries - 2)
+#define FntDefault 2
+
+#define MTEXTRA_CHARSET 160
+#define FENCES_CHARSET 161
+
+typedef struct
+{
+ Integer fontNum;
+ Byte macName[MaxFntName];
+ Byte gdiName[MaxFntName];
+ Byte family;
+ Byte charset;
+} FontEntry, far * FontEntryLPtr;
+
+private FontEntry fontTable[NumFntEntries] =
+{
+ { FntSystemFont, "Chicago", "Chicago", FF_ROMAN, ANSI_CHARSET },
+ { FntNewYork, "New York", "New York", FF_ROMAN, ANSI_CHARSET },
+ { FntGeneva, "Geneva", "Geneva", FF_SWISS, ANSI_CHARSET },
+ { FntMonaco, "Monaco", "Monaco", FF_MODERN, ANSI_CHARSET },
+ { FntVenice, "Venice", "Venice", FF_ROMAN, ANSI_CHARSET },
+ { FntLondon, "London", "London", FF_ROMAN, ANSI_CHARSET },
+ { FntAthens, "Athens", "Athens", FF_ROMAN, ANSI_CHARSET },
+ { FntSanFran, "San Francisco", "San Francisco", FF_SWISS, ANSI_CHARSET },
+ { FntToronto, "Toronto", "Toronto", FF_SWISS, ANSI_CHARSET },
+ { FntCairo, "Cairo", "Cairo", FF_DECORATIVE, SYMBOL_CHARSET },
+ { FntLosAngeles, "Los Angeles", "Los Angeles", FF_SWISS, ANSI_CHARSET },
+ { FntZapfDingbats, "Zapf Dingbats", "ZapfDingbats", FF_DECORATIVE, SYMBOL_CHARSET },
+ { FntBookman, "Bookman", "Bookman", FF_ROMAN, ANSI_CHARSET },
+ { FntHelvNarrow, "N Helvetica Narrow", "Helvetica-Narrow", FF_SWISS, ANSI_CHARSET },
+ { FntPalatino, "Palatino", "Palatino", FF_ROMAN, ANSI_CHARSET },
+ { FntZapfChancery, "Zapf Chancery", "ZapfChancery", FF_ROMAN, ANSI_CHARSET },
+ { FntTimes, "Times", "Times", FF_ROMAN, ANSI_CHARSET },
+ { FntHelvetica, "Helvetica", "Helvetica", FF_SWISS, ANSI_CHARSET },
+ { FntCourier, "Courier", "Courier", FF_MODERN, ANSI_CHARSET },
+ { FntSymbol, "Symbol", "Symbol", FF_DECORATIVE, SYMBOL_CHARSET },
+ { FntMobile, "Mobile", "Mobile", FF_DECORATIVE, SYMBOL_CHARSET },
+ { FntAvantGarde, "Avant Garde", "AvantGarde", FF_SWISS, ANSI_CHARSET },
+ { FntNewCentury, "New Century Schlbk", "NewCenturySchlbk", FF_ROMAN, ANSI_CHARSET },
+ { FntMTExtra, "MT Extra", "MT Extra", FF_DECORATIVE, MTEXTRA_CHARSET },
+ { FntUnknown, "Fences", "Fences", FF_DECORATIVE, FENCES_CHARSET },
+ { FntUnknown, "", "", FF_ROMAN, ANSI_CHARSET },
+ { FntUnknown, "", "", FF_ROMAN, ANSI_CHARSET }
+};
+
+private Byte trueTypeSub[NumTTSubs][MaxFntName] =
+{
+ "Monotype Sorts",
+ "Bookman Old Style",
+ "Arial Narrow",
+ "Book Antiqua",
+ "Monotype Corsiva",
+ "Times New Roman",
+ "Arial",
+ "Courier New",
+ "Symbol",
+ "Mobile",
+ "Century Gothic",
+ "Century Schoolbook"
+};
+
+private Byte MacToAnsiTable[128] =
+{
+ 0xC4, /* 80 -- upper case A with diaeresis or umlaut mark */
+ 0xC5, /* 81 -- upper case A with ring */
+ 0xC7, /* 82 -- upper case C with cedilla */
+ 0xC9, /* 83 -- upper case E with accute accent */
+ 0xD1, /* 84 -- upper case N with tilde */
+ 0xD6, /* 85 -- upper case O with diaeresis or umlaut mark */
+ 0xDC, /* 86 -- upper case U with diaeresis or umlaut mark */
+ 0xE1, /* 87 -- lower case a with accute accent */
+ 0xE0, /* 88 -- lower case a with grave accent */
+ 0xE2, /* 89 -- lower case a with circumflex accent */
+ 0xE4, /* 8A -- lower case a with diaeresis or umlaut mark */
+ 0xE3, /* 8B -- lower case a with tilde */
+ 0xE5, /* 8C -- lower case a with ring */
+ 0xE7, /* 8D -- lower case c with cedilla */
+ 0xE9, /* 8E -- lower case e with accute accent */
+ 0xE8, /* 8F -- lower case e with grave accent */
+ 0xEA, /* 90 -- lower case e with circumflex accent */
+ 0xEB, /* 91 -- lower case e with diaeresis or umlaut mark */
+ 0xED, /* 92 -- lower case i with accute accent */
+ 0xEC, /* 93 -- lower case i with grave accent */
+ 0xEE, /* 94 -- lower case i with circumflex accent */
+ 0xEF, /* 95 -- lower case i with diaeresis or umlaut mark */
+ 0xF1, /* 96 -- lower case n with tilde */
+ 0xF3, /* 97 -- lower case o with accute accent */
+ 0xF2, /* 98 -- lower case o with grave accent */
+ 0xF4, /* 99 -- lower case o with circumflex accent */
+ 0xF6, /* 9A -- lower case o with diaeresis or umlaut mark */
+ 0xF5, /* 9B -- lower case o with tilde */
+ 0xFA, /* 9C -- lower case u with accute accent */
+ 0xF9, /* 9D -- lower case u with grave accent */
+ 0xFB, /* 9E -- lower case u with circumflex accent */
+ 0xFC, /* 9F -- lower case u with diaeresis or umlaut mark */
+ 0x86, /* A0 -- UNS - MAC A0 <new> */
+ 0xB0, /* A1 -- degrees */
+ 0xA2, /* A2 -- cent currency symbol */
+ 0xA3, /* A3 -- pound currency */
+ 0xA7, /* A4 -- section separator */
+ 0x95, /* A5 -- bullet <changed from B7> */
+ 0xB6, /* A6 -- paragraph (cp > 0x80) */
+ 0xDF, /* A7 -- beta */
+ 0xAE, /* A8 -- registered */
+ 0xA9, /* A9 -- copyright */
+ 0x99, /* AA -- trade mark <new> */
+ 0xB4, /* AB -- apostrophe */
+ 0xA8, /* AC -- space with diaeresis or umlaut mark */
+ 0xB0, /* AD -- not equal <unused1> */
+ 0xC6, /* AE -- UPPER CASE AE */
+ 0xD8, /* AF -- UNS - ANSI D8 */
+ 0x81, /* B0 -- infinity <unused2> */
+ 0xB1, /* B1 -- plus minus */
+ 0x8A, /* B2 -- <= <unused3> */
+ 0x8D, /* B3 -- >= <unused4> */
+ 0xA5, /* B4 -- yen currency symbol */
+ 0xB5, /* B5 -- UNS - ANSI B5 */
+ 0x8E, /* B6 -- lower case Delta <unused5> */
+ 0x8F, /* B7 -- Sigma <unused6> */
+ 0x90, /* B8 -- upper case Pi <unused7> */
+ 0x9A, /* B9 -- lower case pi <unused8> */
+ 0x9D, /* BA -- upper integral <unused9> */
+ 0xAA, /* BB -- super script a w/underscore */
+ 0xBA, /* BC -- UNS - ANSI BA */
+ 0x9E, /* BD -- Omega <unused10> */
+ 0xE6, /* BE -- lower case ae */
+ 0xF8, /* BF -- UNS - ANSI F8 */
+ 0xBF, /* C0 -- upside down ? */
+ 0xA1, /* C1 -- upside down < */
+ 0xAC, /* C2 -- UNS - ANSI AC */
+ 0xA6, /* C3 -- square root <unused11> */
+ 0x83, /* C4 -- function (f) <new> */
+ 0xAD, /* C5 -- UNS - 437 F7 <unused12> */
+ 0xB2, /* C6 -- upper case delta <unused13> */
+ 0xAB, /* C7 -- << */
+ 0xBB, /* C8 -- >> */
+ 0x85, /* C9 -- elipsis <new> */
+ 0xA0, /* CA -- non breaking space <new> */
+ 0xC0, /* CB -- upper case A with grave accent */
+ 0xC3, /* CC -- upper case A with tilde */
+ 0xD5, /* CD -- upper case O with tilde */
+ 0x8C, /* CE -- upper case CE <new> */
+ 0x9C, /* CF -- lower case CE <new> */
+ 0x96, /* D0 -- dash <changed from AD> */
+ 0x97, /* D1 -- m dash <changed from 96> */
+ 0x93, /* D2 -- double open quote */
+ 0x94, /* D3 -- double close quote */
+ 0x91, /* D4 -- single open quote */
+ 0x92, /* D5 -- single close quote */
+ 0xF7, /* D6 -- divide <new> */
+ 0xB3, /* D7 -- open diamond <unused14> */
+ 0xFF, /* D8 -- lower case y with diaeresis or umlaut mark */
+ 0x9F, /* D9 -- Undefined <new upper case y with diaeresis or umlaut mark> */
+ 0xB9, /* DA -- Undefined <new forward slash> */
+ 0xA4, /* DB -- UNS - ANSI A4. */
+ 0x8B, /* DC -- Undefined <new less than sign> */
+ 0x9B, /* DD -- Undefined <new greater than sign> */
+ 0xBC, /* DE -- Undefined <unused15 connected fi> */
+ 0xBD, /* DF -- Undefined <unused16 connected fl> */
+ 0x87, /* E0 -- Undefined <new double cross> */
+ 0xB7, /* E1 -- Undefined <new bullet character> */
+ 0x82, /* E2 -- Undefined <new single lower smart quote> */
+ 0x84, /* E3 -- Undefined <new double lower smart quote> */
+ 0x89, /* E4 -- Undefined <new weird percent sign> */
+ 0xC2, /* E5 -- upper case A with circumflex accent. */
+ 0xCA, /* E6 -- upper case E with circumflex accent. */
+ 0xC1, /* E7 -- upper case A with accute accent. */
+ 0xCB, /* E8 -- upper case E with diaeresis or umlaut mark. */
+ 0xC8, /* E9 -- upper case E with grave accent. */
+ 0xCD, /* EA -- upper case I with accute accent. */
+ 0xCE, /* EB -- upper case I with circumflex accent. */
+ 0xCF, /* EC -- upper case I with diaeresis or umlaut mark. */
+ 0xCC, /* ED -- upper case I with grave accent. */
+ 0xD3, /* EE -- upper case O with accute accent. */
+ 0xD4, /* EF -- upper case O with circumflex accent. */
+ 0xBE, /* F0 -- Undefined <unused17 apple character> */
+ 0xD2, /* F1 -- upper case O with grave accent. */
+ 0xDA, /* F2 -- upper case U with accute accent. */
+ 0xDB, /* F3 -- upper case U with circumflex accent. */
+ 0xD9, /* F4 -- upper case U with grave accent. */
+ 0xD0, /* F5 -- Undefined <unsused18 i with no dot> */
+ 0x88, /* F6 -- Undefined <new hat ligature> */
+ 0x98, /* F7 -- Undefined <new tilde ligature> */
+ 0xAF, /* F8 -- Undefined <new bar ligature> */
+ 0xD7, /* F9 -- Undefined <unused18 upside-down bow ligature> */
+ 0xDD, /* FA -- Undefined <unused19 dot ligature> */
+ 0xDE, /* FB -- Undefined <unused20 open dot ligature> */
+ 0xB8, /* FC -- space with cedilla. */
+ 0xF0, /* FD -- Undefined <unused21 double upper smart quote> */
+ 0xFD, /* FE -- Undefined <unused22 lower right bow ligature> */
+ 0xFE /* FF -- Undefined <unused23 upside-down hat ligature> */
+};
+
+/*--- Default logical structures ---*/
+
+typedef struct
+{
+ BITMAPINFOHEADER bmiHeader;
+ RGBQUAD bmiColors[2];
+ DWORD pattern[8];
+
+} PatBrush, far * PatBrushLPtr;
+
+private PatBrush patBrushSkel =
+{
+ {
+ sizeof( BITMAPINFOHEADER ), // size of header structure
+ 8, // width = 8
+ 8, // height = 8
+ 1, // planes = 1
+ 1, // number of bits/pixel = 1
+ BI_RGB, // non-compressed bitmap
+ 8, // image size (in bytes)
+ (DWORD)(72 * 39.37), // XPelsPerMeter = 72 dpi * mm/inch
+ (DWORD)(72 * 39.37), // YPelsPerMeter = 72 dpi * mm/inch
+ 0, // all 2 colors used
+ 0 // all colors important
+ },
+ {
+ { 0, 0, 0, 0 }, // background color
+ { 0, 0, 0, 0 } // foreground (text) color
+ },
+ { 0, 0, 0, 0, 0, 0, 0, 0 } // uninitialized pattern data
+};
+
+
+private LOGFONT logFontSkel =
+{
+ 0, // height - will be set
+ 0, // width = match aspect ratio
+ 0, // escapement = no rotation
+ 0, // orientation = no rotation
+ FW_NORMAL, // weight = normal
+ 0, // italics = no
+ 0, // underline = no
+ 0, // strikeout = no
+ ANSI_CHARSET, // charset = ANSI
+ OUT_DEFAULT_PRECIS, // default output precision
+ CLIP_DEFAULT_PRECIS, // default clipping precision
+ DEFAULT_QUALITY, // default output quality
+ DEFAULT_PITCH | FF_DONTCARE, // default pitch and family
+ cNULL // no face name - will be set
+};
+
+
+/*********************** Private Function Definitions ***********************/
+
+private Boolean IsArithmeticMode( Integer mode );
+/* return TRUE if this is an arithmetic transfer mode */
+
+
+#define /* Boolean */ IsHiddenPenMode( /* Integer */ mode ) \
+/* return TRUE if this is a hidden pen transfer mode */ \
+(mode == QDHidePen)
+
+
+private void CalculatePenSize( Point startPt, Point endPt, Point penSize );
+/* calcuate the pen width to produce equivalent QuickDraw stroke */
+
+
+private Boolean SetAttributes( GrafVerb verb );
+/* set up pen and brush elements according to GrafVerb */
+
+
+private Boolean SetPenAttributes( GrafVerb verb );
+/* make sure that pen attributes are OK according to preferences */
+
+
+private Boolean SetBrushAttributes( GrafVerb verb );
+/* set up the correct brush (fill) for the ensuing primitive */
+
+
+private void MakePatternBrush( PixPatLPtr pixPatLPtr );
+/* Make a new pattern brush using pixelPat passed in */
+
+
+private Boolean IsSolidPattern( PixPatLPtr pixPatLPtr,
+ RGBColor far * rgbColor,
+ Boolean mixColors );
+/* return true if pattern is solid, false if not. If mixColors is TRUE, then
+ mixtures of 25%, 50%, and 75% grey are mixed into a solid color */
+
+
+private Boolean FrameMatchesFill( Word primType );
+/* return TRUE if the fill pattern (current brush ) matches frame pattern */
+
+
+private Boolean SetTextAttributes( void );
+/* set up text attributes - set mapChars to TRUE if should map to ANSI */
+
+
+private Integer FindGdiFont( void );
+/* return an index to the current font selection */
+
+
+private void MacToAnsi( StringLPtr string );
+/* convert extended characters from Mac to ANSI equivalent */
+
+
+private void MakeDIB( PixMapLPtr pixMapLPtr, Handle pixDataHandle,
+ Handle far * headerHandleLPtr,
+ Handle far * bitsHandleLPtr,
+ Boolean packDIB );
+/* Create a Windows device-independant bitmap */
+
+
+void GdiEPSData(PSBuf far* psbuf);
+/* Output PostScript data as GDI POSTSCRIPT_DATA Escape */
+
+
+private Boolean MakeMask( Handle mask, Boolean patBlt );
+/* Create a mask that will be used in the ensuing StretchDIBits call
+ Return TRUE if region was created, FALSE if rectangular region */
+
+
+void InvertBits( Byte far * byteLPtr, Integer start, Integer count );
+/* invert all bits in byteLPtr from bit offset start for count bits */
+
+
+void hmemcpy( Byte huge * src, Byte huge * dst, Integer count );
+/* copy count bytes from source to destination - assumes even count */
+
+
+void hexpcpy( Byte huge * src, Byte huge * dst, Integer count, Integer bits );
+/* copy count bytes to destination, expand each 2 bits to nibble of if
+ 16-bit image, expand to 24 bits */
+
+
+void hmrgcpy( Byte huge * srcLineHPtr, Byte huge * dstLineHPtr, Integer dibWidth );
+/* if the is a 24-bit image, then the components are separated into scanlines
+ of red, green and blue. Merge into single scanline of 24-bit RGB pixels */
+
+
+void hrlecpy256( Byte huge * srcLineHPtr, Byte huge * dstLineHPtr,
+ Integer dibWidth, DWord far * rleByteCount, Boolean writeDIB );
+/* 256 color DIB RLE compression. Provide source, destination pointers,
+ bytes in scanline. rleByteCount updated and write if writeDIB is TRUE */
+
+
+void hrlecpy16( Byte huge * srcLineHPtr, Byte huge * dstLineHPtr,
+ Integer dibWidth, DWord far * rleByteCount, Boolean writeDIB );
+/* 16 color DIB RLE compression. Provide source, destination pointers,
+ bytes in scanline. rleByteCount updated and write if writeDIB is TRUE */
+
+
+#define /* void */ GdiMarkAsCurrent( /* Integer */ attribCode ) \
+/* indicate that the current attribute is current */ \
+gdiEnv.state[attribCode] = Current
+
+
+#define /* void */ GdiAttribHasChanged( /* Integer */ attribCode ) \
+/* return TRUE if the attribute has changed */ \
+(gdiEnv.state[attribCode] == Changed)
+
+
+#define /* Boolean */ EmptyRect( /* Rect */ r ) \
+/* TRUE if a given rectangle has a zero delta in X or Y direction */ \
+(((r.right) - (r.left) == 0) || ((r.bottom) - (r.top) == 0))
+
+
+#define /* Boolean */ odd( /* Integer */ i ) \
+/* return TRUE if given integer is odd, FALSE if even */ \
+((i) & 0x0001)
+
+
+#define /* Integer */ RValue( /* RGBColor */ color ) \
+/* coerce the value of Byte color component to Integer */ \
+((Integer)(GetRValue( color )))
+
+
+#define /* Integer */ GValue( /* RGBColor */ color ) \
+/* coerce the value of Byte color component to Integer */ \
+((Integer)(GetGValue( color )))
+
+
+#define /* Integer */ BValue( /* RGBColor */ color ) \
+/* coerce the value of Byte color component to Integer */ \
+((Integer)(GetBValue( color )))
+
+
+/*********************** Function Implementation ****************************/
+
+void GdiOffsetOrigin( Point delta )
+/*=================*/
+/* offset the current window origin and picture bounding box */
+{
+ /* flush the cache */
+ CaFlushCache();
+
+ /* make sure to make this permanent change that won't be affected by
+ changes in clipping rectangles that are otherwise changed between
+ SaveDC/RestoreDC pair. */
+ CaRestoreDC();
+
+ /* offset the picture bounding box and cached clipping rectangles */
+ OffsetRect( &gdiPict.bbox, delta.x, delta.y );
+ OffsetRect( CaGetClipRect(), delta.x, delta.y );
+
+ /* call GDI to reset the origin */
+#ifdef WIN32
+ SetWindowOrgEx( gdiEnv.metafile, gdiPict.bbox.left, gdiPict.bbox.top, NULL );
+#else
+ SetWindowOrg( gdiEnv.metafile, gdiPict.bbox.left, gdiPict.bbox.top );
+#endif
+
+
+ /* set up the next clipping frame */
+ CaSaveDC();
+
+ /* determine if we need to resend the clipping rectangle */
+ if (!EqualRect( CaGetClipRect(), &gdiPict.bbox ))
+ {
+ /* retrieve the current clipping rectangle */
+ Rect rect = *CaGetClipRect();
+
+ /* newly offset clipping rectangle */
+ IntersectClipRect( gdiEnv.metafile,
+ rect.left, rect.top, rect.right, rect.bottom );
+ }
+}
+
+
+
+void GdiLineTo( Point newPt )
+/*============*/
+/* Emit line primitive with square endcaps */
+{
+ CGrafPort far * port;
+ CaPrimitive prim;
+
+ /* get port for updated pen location and pen size */
+ QDGetPort( &port );
+
+ /* check if the pen has been turned off */
+ if (gdiEnv.drawingEnabled &&
+ (port->pnSize.x != 0) && (port->pnSize.y != 0))
+ {
+ RGBColor solidRGB;
+
+ /* determine if we are trying to draw with a patterned pen */
+ if (!IsSolidPattern( &port->pnPixPat, &solidRGB, NOMIX ))
+ {
+ if (SetAttributes( GdiPaint))
+ {
+ Point delta;
+
+ /* determine if the dimensions in both directions */
+ delta.x = newPt.x - port->pnLoc.x;
+ delta.y = newPt.y - port->pnLoc.y;
+
+ /* determine if we can simulate using a rectangle primitive */
+ if (delta.x == 0 || delta.y == 0)
+ {
+ /* assign the structures into the cache type */
+ prim.type = CaRectangle;
+ prim.verb = GdiPaint;
+
+ /* make a rectangle with upper-left, lower-right coords */
+ prim.a.rect.bbox.left = min( port->pnLoc.x, newPt.x );
+ prim.a.rect.bbox.top = min( port->pnLoc.y, newPt.y );
+ prim.a.rect.bbox.right = max( port->pnLoc.x, newPt.x ) + port->pnSize.x;
+ prim.a.rect.bbox.bottom = max( port->pnLoc.y, newPt.y ) + port->pnSize.y;
+ }
+ else
+ {
+ Point start;
+ Point end;
+ Point poly[7];
+ Point pnSize = port->pnSize;
+
+ /* make sure that the points follow left->right x direction */
+ if (delta.x > 0)
+ {
+ start = port->pnLoc;
+ end = newPt;
+ }
+ else
+ {
+ start = newPt;
+ end = port->pnLoc;
+ delta.y = - delta.y;
+ }
+
+ /* create the simulation of the outline */
+ poly[0].x = start.x;
+ poly[0].y = start.y;
+ poly[1].x = (delta.y > 0) ? start.x + pnSize.x : end.x;
+ poly[1].y = (delta.y > 0) ? start.y : end.y;
+ poly[2].x = end.x + pnSize.x;
+ poly[2].y = end.y;
+ poly[3].x = end.x + pnSize.x;
+ poly[3].y = end.y + pnSize.y;
+ poly[4].x = (delta.y > 0) ? end.x : start.x + pnSize.x;
+ poly[4].y = (delta.y > 0) ? end.y + pnSize.y : start.y + pnSize.y;
+ poly[5].x = start.x;
+ poly[5].y = start.y + pnSize.y;
+ poly[6] = poly[0];
+
+ /* package the polygon for the cache module */
+ prim.type = CaPolygon;
+ prim.verb = GdiPaint;
+ prim.a.poly.numPoints = 7;
+ prim.a.poly.pointList = poly;
+ prim.a.poly.pnSize.x = 0;
+ prim.a.poly.pnSize.y = 0;
+ }
+
+ /* cache the primitive */
+ CaCachePrimitive( &prim );
+ }
+ }
+ /* eliminate OR'ing of white pen with display surface */
+ else if (port->pnMode != QDPatOr || solidRGB != RGB( 255, 255, 255))
+ {
+ /* set the correct pen size before calling SetPenAttributes() */
+ CalculatePenSize( port->pnLoc, newPt, port->pnSize );
+
+ /* setup the correct line color and check whether to continue */
+ if (SetPenAttributes( GdiFrame ))
+ {
+ /* package for the cache module */
+ prim.verb = GdiFrame;
+ prim.type = CaLine;
+ prim.a.line.start = port->pnLoc;
+ prim.a.line.end = newPt;
+ prim.a.line.pnSize = port->pnSize;
+
+ /* cache the primitive */
+ CaCachePrimitive( &prim );
+ }
+ }
+ }
+
+} /* GdiLineTo */
+
+
+
+void GdiRectangle( GrafVerb verb, Rect rect )
+/*===============*/
+/* Emit rectangle primitive using action and dimensions parameters */
+{
+ CGrafPort far * port;
+ CaPrimitive prim;
+
+ /* get port for pen size */
+ QDGetPort( &port );
+
+ /* make sure that drawing is enabled and non-empty rectangle destination */
+ if (gdiEnv.drawingEnabled && !EmptyRect( rect ))
+ {
+ RGBColor solidRGB;
+
+ /* check if the same primitive is being outlined as was just filled.
+ if this happens, then we don't need to set the frame (pen) */
+ if (verb == GdiFrame && FrameMatchesFill( CaRectangle ))
+ {
+ /* just flush the cache and return */
+ CaFlushCache();
+ }
+ /* determine if we are trying to draw with a patterned pen */
+ else if (verb == GdiFrame && !IsSolidPattern( &port->pnPixPat, &solidRGB, NOMIX ))
+ {
+ /* flush any pending graphics operations */
+ CaFlushCache();
+
+ /* set up the correct attributes for a simulated frameRect */
+ if (SetAttributes( GdiPaint))
+ {
+ Point poly[10];
+ Integer polyCount[2];
+ Point pnSize = port->pnSize;
+
+ /* make sure that the rectangle outline will fill properly */
+ if (Width( rect) < 2 * pnSize.x)
+ {
+ pnSize.x = Width( rect ) / 2;
+ }
+ if (Height( rect ) < 2 * pnSize.y)
+ {
+ pnSize.y = Height( rect ) / 2;
+ }
+
+ /* create the simulation of the outline */
+ poly[0].x = poly[3].x = rect.left;
+ poly[0].y = poly[1].y = rect.top;
+ poly[1].x = poly[2].x = rect.right;
+ poly[2].y = poly[3].y = rect.bottom;
+ poly[4] = poly[0];
+
+ poly[5].x = poly[8].x = rect.left + pnSize.x;
+ poly[5].y = poly[6].y = rect.top + pnSize.y;
+ poly[6].x = poly[7].x = rect.right - pnSize.x;
+ poly[7].y = poly[8].y = rect.bottom - pnSize.y;
+ poly[9] = poly[5];
+
+ /* set the poly point count for the subpolygons */
+ polyCount[0] = polyCount[1] = 5;
+
+ /* flush the cache attributes to set the pen and brush style */
+ CaFlushAttributes();
+
+ /* call GDI to render the polypolygon */
+ PolyPolygon( gdiEnv.metafile, poly, polyCount, 2);
+ }
+ }
+ /* setup the correct line and fill attribs, check to continue */
+ else if (SetAttributes( verb ))
+ {
+ /* package for the cache module */
+ prim.verb = verb;
+ prim.type = CaRectangle;
+ prim.a.rect.bbox = rect;
+
+ /* cache the primitive */
+ CaCachePrimitive( &prim );
+ }
+ }
+
+} /* GdiRectangle */
+
+
+
+void GdiRoundRect( GrafVerb verb, Rect rect, Point oval )
+/*===============*/
+/* Emit rounded rectangle primitive */
+{
+ CaPrimitive prim;
+
+ /* make sure that drawing is enabled and non-empty rectangle destination */
+ if (gdiEnv.drawingEnabled && !EmptyRect( rect ))
+ {
+ /* check if the same primitive is being outlined as was just filled.
+ if this happens, then we don't need to set the frame (pen) */
+ if (verb == GdiFrame && FrameMatchesFill( CaRoundRect ))
+ {
+ /* just flush the cache and return */
+ CaFlushCache();
+ }
+ /* setup the correct line and fill attribs, check to continue */
+ else if (SetAttributes( verb ))
+ {
+ /* package for the cache module */
+ prim.verb = verb;
+ prim.type = CaRoundRect;
+ prim.a.rect.bbox = rect;
+ prim.a.rect.oval = oval;
+
+ /* cache the primitive */
+ CaCachePrimitive( &prim );
+ }
+ }
+
+} /* GdiRRectProc */
+
+
+
+void GdiOval( GrafVerb verb, Rect rect )
+/*==========*/
+/* Emit an oval primitive */
+{
+ CaPrimitive prim;
+
+ /* make sure that drawing is enabled and non-empty rectangle destination */
+ if (gdiEnv.drawingEnabled && !EmptyRect( rect ))
+ {
+ /* check if the same primitive is being outlined as was just filled.
+ if this happens, then we don't need to set the frame (pen) */
+ if (verb == GdiFrame && FrameMatchesFill( CaEllipse ))
+ {
+ /* just flush the cache and return */
+ CaFlushCache();
+ }
+ /* setup the correct line and fill attribs, check to continue */
+ else if (SetAttributes( verb ))
+ {
+ /* package for the cache module */
+ prim.verb = verb;
+ prim.type = CaEllipse;
+ prim.a.rect.bbox = rect;
+
+ /* cache the primitive */
+ CaCachePrimitive( &prim );
+ }
+ }
+
+} /* GdiOvalProc */
+
+
+
+void GdiArc( GrafVerb verb, Rect rect, Integer startAngle, Integer arcAngle )
+/*=========*/
+/* Emit an arc primitive */
+{
+ Boolean allOk;
+ Point center;
+ Point startPoint;
+ Point endPoint;
+ Integer hypotenuse;
+ Integer rectWidth;
+ Integer rectHeight;
+ Real startRadian;
+ Real arcRadian;
+ Real scaleFactor;
+ Boolean scaleVertically;
+ CaPrimitive prim;
+
+ /* make sure that drawing is enabled and non-empty rectangle and sweep */
+ if (gdiEnv.drawingEnabled && !EmptyRect( rect ) && (arcAngle != 0 ))
+ {
+ /* see what type of primitive will be created */
+ prim.type = (verb == GdiFrame) ? CaArc : CaPie;
+
+ /* if drawing an arc, only the pen attributes need be set */
+ if (prim.type == CaArc)
+ {
+ /* set same object state to FALSE if framing - Gdi will render the
+ entire outline of the pie, whereas in QuickDraw, only the outer
+ edge of the pie is drawn. */
+ gdiEnv.sameObject = FALSE;
+
+ /* notify the cache module that this isn't the same object */
+ CaSamePrimitive( FALSE );
+
+ /* set up only the pen attributes */
+ allOk = SetPenAttributes( verb );
+ }
+ else
+ {
+ /* otherwise, set pen and brush attributes */
+ allOk = SetAttributes( verb );
+ }
+
+ /* check whether attributes were set up correctly and to proceed */
+ if (allOk)
+ {
+ /* Calculate width and height of source rectangle. */
+ rectWidth = Width( rect );
+ rectHeight = Height( rect );
+
+ /* Determine size of smallest enclosing square and set hypotenuse
+ to 1/2 width of resulting square */
+ if (rectWidth > rectHeight)
+ {
+ hypotenuse = rectWidth / 2;
+ scaleVertically = TRUE;
+ scaleFactor = (Real)rectHeight / (Real)rectWidth;
+ }
+ else
+ {
+ hypotenuse = rectHeight / 2;
+ scaleVertically = FALSE;
+ scaleFactor = (Real)rectWidth / (Real)rectHeight;
+ }
+
+ /* adjust hypotenuse size if possible GDI divide by zero possible */
+ if (hypotenuse < 100)
+ {
+ /* note that start and end points don't have to lie on arc */
+ hypotenuse = 100;
+ }
+
+ /* find the center point of bounding rectangle */
+ center.x = rect.left + rectWidth / 2;
+ center.y = rect.top + rectHeight /2;
+
+ /* check if the arc is drawn in a counter-clockwise direction */
+ if (arcAngle < 0)
+ {
+ Integer tempArcAngle;
+
+ /* if rendering counter-clockwise, then swap the start and end
+ points so the rendering will occur in clockwise direction */
+ tempArcAngle = arcAngle;
+ arcAngle = startAngle;
+ startAngle += tempArcAngle;
+ }
+ else
+ {
+ /* clockwise rendering - just add the arc angle to start angle */
+ arcAngle += startAngle;
+ }
+
+ /* Determine the start and arc angles in radians */
+ startRadian = ((Real)startAngle / 360.0) * TwoPi;
+ arcRadian = ((Real)arcAngle / 360.0) * TwoPi;
+
+ /* calculate the start and endpoints. Note negation of y coordinate since
+ the positive direction is downward. Also note that the start and
+ end points are being swapped, since QuickDraw renders in clock-
+ wise direction and GDI renders in counter-clockwise direction */
+ endPoint.x = (Integer)(sin( startRadian ) * hypotenuse);
+ endPoint.y = (Integer)(-cos( startRadian ) * hypotenuse);
+
+ startPoint.x = (Integer)(sin( arcRadian ) * hypotenuse);
+ startPoint.y = (Integer)(-cos( arcRadian ) * hypotenuse);
+
+ /* scale the resulting points in the vertical or horizontal direction
+ depending on the setting of scaleVertically boolean */
+ if (scaleVertically)
+ {
+ endPoint.y = (Integer)(endPoint.y * scaleFactor);
+ startPoint.y = (Integer)(startPoint.y * scaleFactor);
+ }
+ else
+ {
+ endPoint.x = (Integer)(endPoint.x * scaleFactor);
+ startPoint.x = (Integer)(startPoint.x * scaleFactor);
+ }
+
+ /* using the transformed points, use centerPoint to determine the correct
+ starting and ending points */
+ startPoint.x += center.x;
+ startPoint.y += center.y;
+
+ endPoint.x += center.x;
+ endPoint.y += center.y;
+
+ /* package for the cache module. The type was set at beginning */
+ prim.verb = verb;
+ prim.a.arc.bbox = rect;
+ prim.a.arc.start = startPoint;
+ prim.a.arc.end = endPoint;
+
+ /* cache the primitive */
+ CaCachePrimitive( &prim );
+ }
+ }
+
+} /* GdiArc */
+
+
+
+void GdiPolygon( GrafVerb verb, Handle poly )
+/*=============*/
+/* Emit polygon primitive */
+{
+ Integer numPoints;
+ Integer lastPoint;
+ Point far * pointList;
+ Integer far * polyCountLPtr;
+ Boolean closed;
+ Boolean allOk;
+ CGrafPort far * port;
+ CaPrimitive prim;
+
+ /* get port for updated pen location and pen size */
+ QDGetPort( &port );
+
+ /* make sure that drawing is enabled */
+ if (gdiEnv.drawingEnabled)
+ {
+ /* check if the same primitive is being outlined as was just filled.
+ if this happens, then we don't need to set the frame (pen) */
+ if (verb == GdiFrame && FrameMatchesFill( CaPolygon ) &&
+ (port->pnSize.x == 1 && port->pnSize.y == 1))
+ {
+ /* just flush the cache and return */
+ CaFlushCache();
+ return;
+ }
+
+ /* lock the polygon handle to access individual fields */
+ polyCountLPtr = (Integer far *)GlobalLock( poly );
+ pointList = (Point far *)(polyCountLPtr +
+ (PolyHeaderSize / sizeofMacWord));
+
+ /* determine number of points based on first word = length field */
+ numPoints = (*polyCountLPtr - PolyHeaderSize) / sizeofMacPoint;
+
+ /* determine if this is a closed polygon */
+ lastPoint = numPoints - 1;
+ closed = ((pointList->x == (pointList + lastPoint)->x) &&
+ (pointList->y == (pointList + lastPoint)->y));
+
+ /* determine what type of primitive to render */
+ prim.type = (verb == GdiFrame && !closed) ? CaPolyLine : CaPolygon;
+
+ /* if drawing a polyline, only the pen attributes need be set */
+ if (prim.type == CaPolyLine)
+ {
+ /* set same object state to FALSE if drawing a polyline */
+ gdiEnv.sameObject = FALSE;
+
+ /* notify the cache module that this isn't the same object */
+ CaSamePrimitive( FALSE );
+
+ /* set up only the pen attributes */
+ allOk = SetPenAttributes( verb );
+ }
+ else
+ {
+ /* otherwise, set pen and brush attributes */
+ allOk = SetAttributes( verb );
+ }
+
+ /* check whether attribute setup succeeded - continue or not */
+ if (allOk)
+ {
+ /* package for the cache module - type was set above */
+ prim.verb = verb;
+ prim.a.poly.numPoints = numPoints;
+ prim.a.poly.pointList = pointList;
+ prim.a.poly.pnSize = port->pnSize;
+
+ /* cache the primitive */
+ CaCachePrimitive( &prim );
+ }
+
+ /* Unlock the data */
+ GlobalUnlock( poly );
+ }
+
+} /* GdiPoly */
+
+
+
+void GdiRegion( GrafVerb verb, Handle rgn )
+/*=============*/
+/* Emit region primitive */
+{
+ Integer far * rgnCountLPtr;
+ Integer numPoints;
+ Rect rgnBBox;
+ CGrafPort far * port;
+
+ /* get port for updated pen location and pen size */
+ QDGetPort( &port );
+
+ /* lock the region handle to access individual fields */
+ rgnCountLPtr = (Integer far *)GlobalLock( rgn );
+
+ /* determine the bounding box of the region */
+ rgnBBox = *((Rect far *)(rgnCountLPtr + 1));
+
+ /* make sure that drawing is enabled and non-empty rectangle destination */
+ if (gdiEnv.drawingEnabled && !EmptyRect( rgnBBox ))
+ {
+ /* determine number of points based on first word = length field */
+ numPoints = (*rgnCountLPtr - RgnHeaderSize) / sizeofMacPoint;
+
+ /* determine if we should just be drawing a rectangle */
+ if (numPoints == 0 )
+ {
+ /* simulate region using rectangle primitive */
+ GdiRectangle( verb, *((Rect far *)(rgnCountLPtr + 1)) );
+ }
+ else
+ {
+ /* determine if we are filling using a pre-set brush */
+ switch (verb)
+ {
+ /* can simulate the region using a brush and mask */
+ case GdiPaint:
+ case GdiFill:
+ case GdiErase:
+ {
+ /* set up the brush attributes for the ensuing StretchBlt */
+ SetBrushAttributes( verb );
+
+ /* call to MakeMask() will generate the bitblt operations */
+ MakeMask( rgn, TRUE );
+ break;
+ }
+
+ /* otherwise, just ignore the opcode */
+ default:
+ break;
+ }
+ }
+ }
+
+ /* Unlock the data */
+ GlobalUnlock( rgn );
+
+} /* GdiRegion */
+
+
+
+void GdiTextOut( StringLPtr string, Point location )
+/*=============*/
+/* draw the text at the location specified. */
+{
+ CGrafPort far * port;
+
+ /* get port for updated pen location */
+ QDGetPort( &port );
+
+ /* make sure that drawing is enabled */
+ if (gdiEnv.drawingEnabled)
+ {
+ /* flush any cached primitive elements */
+ CaFlushCache();
+
+ /* set up the correct text attributes before continuing */
+ if (SetTextAttributes())
+ {
+ Integer strLen;
+
+ /* determine the number of characters in the string */
+ strLen = lstrlen( string );
+
+ /* convert the individual characters from Mac to ANSI char set */
+ MacToAnsi( string );
+
+ /* call textout to display the characters */
+ TextOut( gdiEnv.metafile, location.x, location.y,
+ string, strLen );
+ }
+ }
+
+} /* GdiTextOut */
+
+
+
+void GdiStretchDIBits( PixMapLPtr pixMapLPtr, Handle pixDataHandle,
+ Rect src, Rect dst, Word mode, Handle mask )
+/*===================*/
+/* Draw a Windows device-independant bitmap */
+{
+ Handle bitsInfoHandle;
+ Handle bitsHandle;
+ LPBITMAPINFO bitsInfoLPtr;
+ Byte far * bitsLPtr;
+ Boolean bitmapMask;
+ Boolean patternBlt;
+ Boolean clipRectSet;
+
+ /* for now, assume no rectangular clip rectangle is set up */
+ clipRectSet = FALSE;
+
+ /* if a mask is present, call MakeDIB to create it */
+ if (mask)
+ {
+ /* if a region mask is present, then call create the mask. This will
+ result in a recursive call to this routine. If the routine returns
+ FALSE, no region was created - this is a rectangular clip. */
+ clipRectSet = !MakeMask( mask, FALSE );
+
+ /* free the data block */
+ GlobalFree( mask );
+
+ if (clipRectSet)
+ {
+ /* if no mask was created, set mask to NULL to get SRCCOPY ROP */
+ mask = NULL;
+ }
+ }
+
+ /* make sure that drawing is enabled and non-empty source and/or
+ destination rectangles in the bitmap record */
+ if (gdiEnv.drawingEnabled && !EmptyRect( src ) && !EmptyRect( dst ))
+ {
+ /* determine if we are rendering the monochrome bitmap mask */
+ bitmapMask = (mode == -1 || mode == -2);
+ patternBlt = (mode == -2);
+
+ /* if this is the mask, change the mode to the correct setting */
+ if (bitmapMask)
+ {
+ /* yes, bitmap mask - change the mode to source copy */
+ mode = QDSrcCopy;
+ }
+
+ /* flush the cache before proceeding */
+ CaFlushCache();
+
+ /* Create a DIB using the information passed in */
+ MakeDIB( pixMapLPtr, pixDataHandle, &bitsInfoHandle, &bitsHandle, FALSE );
+
+ /* make sure that everything went OK */
+ if (ErGetGlobalError() == NOERR)
+ {
+ DWord ropCode;
+ RGBQUAD secondFgColor;
+ Byte pass;
+ Byte numPasses;
+ Boolean twoColorDIB;
+
+ /* determine if we are working with a 2 color DIB */
+ twoColorDIB = pixMapLPtr->pixelSize == 1;
+
+ if (mask)
+ {
+ /* if mask is already rendered, then AND in the remaining bits
+ to cover the areas that have been turned to white */
+ ropCode = SRCAND;
+ }
+ else if (patternBlt)
+ {
+ /* drawing a white on black bitmap - we want all the areas that
+ are black to leave the destination untouched, and where white
+ to draw with the currently selected brush. Check Petzold
+ "Programming Windows v3", pages 622-623. DSPDxax operation */
+ ropCode = 0x00E20746;
+ }
+ else if (bitmapMask)
+ {
+ /* drawing the mask bitmap - OR in all bits to create white mask
+ that will be overlaid in the ensuing operation with color */
+ ropCode = SRCPAINT;
+ }
+ else if (!twoColorDIB &&
+ (mode == QDSrcOr || mode == QDAdMin || mode == QDTransparent))
+ {
+ /* check for the special case found in Illustrator EPS images,
+ where a monochrome bitmap is used to clear an area, followed
+ by a multi-color DIB drawn in QDSrcOr mode - we don't want to
+ convert this to a SRCCOPY mode. Instead, this simulated
+ transparecy is done in a fashion similar to region masks. */
+ ropCode = SRCAND;
+ }
+ else
+ {
+ /* otherwise, use a "normal" transfer mode. This entails that
+ there is no transparency present in the bitmap rendering */
+ ropCode = SRCCOPY;
+ }
+
+ /* Lock the data to obtain pointers for call to StretchDIBits */
+ bitsLPtr = (Byte far *)GlobalLock( bitsHandle );
+ bitsInfoLPtr = (LPBITMAPINFO)GlobalLock( bitsInfoHandle );
+
+ /* assume that only one pass is required */
+ numPasses = 1;
+
+ /* some special handling of two-color DIBs for transparency */
+ if (twoColorDIB && (mode == QDSrcOr || mode == QDSrcBic))
+ {
+ RGBQUAD bmiWhite = { 255, 255, 255, 0 };
+ RGBQUAD bmiBlack = { 0, 0, 0, 0 };
+
+ /* determine if we should use the PowerPoint optimizations */
+ if (gdiPrefsLPtr->optimizePP)
+ {
+ /* use the specialized SRCPAINT rop code - flag transparency */
+ ropCode = SRCPAINT;
+
+ /* if trying to clear all bits... */
+ if (mode == QDSrcBic)
+ {
+ /* ... swap foreground with background color -
+ the background is set to white in ensuing operation */
+ bitsInfoLPtr->bmiColors[0] = bitsInfoLPtr->bmiColors[1];
+ }
+ }
+ else
+ {
+ /* save the foreground color for the second iteration ... */
+ secondFgColor = (mode == QDSrcOr) ? bitsInfoLPtr->bmiColors[0] :
+ bitsInfoLPtr->bmiColors[1] ;
+
+ /* assume two passes required - 1 for mask, 2 for color blt */
+ numPasses = 2;
+
+ /* check if all the RGB components are the same */
+ if ((mode == QDSrcOr) && (secondFgColor.rgbRed == 0) &&
+ (secondFgColor.rgbRed == secondFgColor.rgbGreen) &&
+ (secondFgColor.rgbRed == secondFgColor.rgbBlue))
+ {
+ /* if black or white, only one pass will be required */
+ numPasses = 1;
+ }
+
+ /* will draw a black transparent bitmap first, followed
+ on 2nd iteration is SRCPAINT - or'ing operation to color */
+ ropCode = SRCAND;
+
+ /* set the foreground to black */
+ bitsInfoLPtr->bmiColors[0] = bmiBlack;
+ }
+
+ /* set the background color to white */
+ bitsInfoLPtr->bmiColors[1] = bmiWhite;
+ }
+
+ /* call StretchDIBits once (PowerPoint) or twice (some others) */
+ for (pass = 0; pass < numPasses; pass++)
+ {
+ /* set up the text and background color for the metafile */
+ if (twoColorDIB)
+ {
+ RGBColor fgColor;
+ RGBColor bkColor;
+ RGBColor black = RGB( 0, 0, 0 );
+
+ /* determine fore- and background color in the DIB header */
+ fgColor = RGB( bitsInfoLPtr->bmiColors[0].rgbRed,
+ bitsInfoLPtr->bmiColors[0].rgbGreen,
+ bitsInfoLPtr->bmiColors[0].rgbBlue );
+ bkColor = RGB( bitsInfoLPtr->bmiColors[1].rgbRed,
+ bitsInfoLPtr->bmiColors[1].rgbGreen,
+ bitsInfoLPtr->bmiColors[1].rgbBlue );
+
+ /* don't change text and background colors if performing a
+ pattern blt. Otherwise, change to the DIB palette colors */
+ if (!patternBlt)
+ {
+ CaSetTextColor( fgColor );
+ CaSetBkColor( bkColor );
+ }
+
+ /* set the stretch mode to correct setting */
+ CaSetStretchBltMode( (fgColor == black) ? BLACKONWHITE :
+ WHITEONBLACK );
+ }
+ else
+ {
+ /* if drawing a color bitmap, set the stretch mode accordingly */
+ CaSetStretchBltMode( COLORONCOLOR );
+ }
+
+ /* call Gdi routine to draw bitmap */
+ StretchDIBits( gdiEnv.metafile,
+ dst.left, dst.top, Width( dst ), Height( dst ),
+ src.left - pixMapLPtr->bounds.left,
+ src.top - pixMapLPtr->bounds.top,
+ Width( src ), Height( src ),
+ bitsLPtr, bitsInfoLPtr, DIB_RGB_COLORS, ropCode );
+
+ /* if this is the first pass, and a second is required ... */
+ if (pass == 0 && numPasses == 2)
+ {
+ /* set the new ROP code */
+ ropCode = SRCPAINT;
+
+ /* set the new background (black) and foreground colors */
+ bitsInfoLPtr->bmiColors[1] = bitsInfoLPtr->bmiColors[0];
+ bitsInfoLPtr->bmiColors[0] = secondFgColor;
+ }
+ }
+
+ /* unlock the data and de-allocate it */
+ GlobalUnlock( bitsHandle );
+ GlobalUnlock( bitsInfoHandle );
+
+ GlobalFree( bitsHandle );
+ GlobalFree( bitsInfoHandle );
+ }
+ }
+
+ /* De-allocate memory used for the pixel data */
+ GlobalFree( pixDataHandle );
+
+ /* if a rectangular clipping region was set up, restore original clip */
+ if (clipRectSet)
+ {
+ /* Call Gdi module to change the clipping rectangle back to the
+ previous settting before bitblt operation */
+ gdiEnv.drawingEnabled = CaIntersectClipRect( gdiEnv.clipRect );
+ }
+
+} /* GdiStretchDIBits */
+
+
+
+void GdiSelectClipRegion( RgnHandle rgn )
+/*======================*/
+/* Create a clipping rectangle or region using handle passed */
+{
+ Integer far * sizeLPtr;
+ Boolean arbitraryClipRgn;
+ Comment gdiComment;
+
+ /* lock down the handle and emit rectangular clip region */
+ sizeLPtr = (Integer far *)GlobalLock( rgn );
+
+ /* Save the Gdi clip rectangle (used for EPS translation) */
+ gdiEnv.clipRect = *((Rect far *)(sizeLPtr + 1));
+
+ /* determine if this is a non-rectangular clipping region */
+ arbitraryClipRgn = (*sizeLPtr > RgnHeaderSize);
+
+ /* flag the clipping region if this is non-rectangular */
+ if (arbitraryClipRgn)
+ {
+ /* check preference memory to see what action to take */
+ if (gdiPrefsLPtr->nonRectRegionAction == GdiPrefAbort)
+ {
+ /* set global error if user request abort */
+ ErSetGlobalError( ErNonRectRegion );
+ return;
+ }
+ /* creating clipping region - emit comment to flag construct */
+ else
+ {
+ /* put this in as a private comment */
+ gdiComment.signature = POWERPOINT;
+ gdiComment.function = PP_BEGINCLIPREGION;
+ gdiComment.size = 0;
+
+ /* write the comment to the metafile */
+ GdiShortComment( &gdiComment );
+ }
+ }
+ /* make sure that the clipping rectangle is confined to the bounding
+ box of the image. This is a workaround go MacDraft images that
+ may contain clipping rectangles of (-32000, -32000),(32000, 32000) */
+ IntersectRect( &gdiEnv.clipRect, &gdiEnv.clipRect, &gdiPict.bbox );
+
+ /* Call Gdi module to change the clipping rectangle */
+ gdiEnv.drawingEnabled = CaIntersectClipRect( gdiEnv.clipRect );
+
+ /* determine if this is a non-rectangular clip region */
+ if (arbitraryClipRgn)
+ {
+ Integer excludeSeg[100];
+ Integer yStart[50];
+ Integer yBottom;
+ Integer numSegs;
+ Integer far * rgnLPtr;
+
+ /* notify cache that a non-rectangular clipping region is being set */
+ CaNonRectangularClip();
+
+ /* save off the current y offset and first excluded segment */
+ yStart[0] = gdiEnv.clipRect.top;
+ excludeSeg[0] = gdiEnv.clipRect.left;
+ excludeSeg[1] = gdiEnv.clipRect.right;
+ numSegs = 2;
+
+ /* get the beginning of the region data */
+ rgnLPtr = sizeLPtr + (RgnHeaderSize / sizeofMacWord);
+
+ /* loop until the end-of-region record is encountered */
+ while (*rgnLPtr != 0x7FFF)
+ {
+ /* copy the new y coordinate to merge */
+ yBottom = *rgnLPtr++;
+
+ /* continue looping until end of line marker encountered */
+ while (*rgnLPtr != 0x7FFF)
+ {
+ Integer start;
+ Integer end;
+ Integer s;
+ Integer e;
+ Boolean sEqual;
+ Boolean eEqual;
+ Integer yTop;
+ Integer left;
+
+ /* determine the start and end point of segment to exclude */
+ start = *rgnLPtr++;
+ end = *rgnLPtr++;
+
+ /* find where the insertion point should be */
+ for (s = 0; (s < numSegs) && (start > excludeSeg[s]); s++) ;
+ for (e = s; (e < numSegs) && (end > excludeSeg[e]); e++) ;
+
+ /* determine if start and end points == segment ends */
+ sEqual = ((s < numSegs) && (start == excludeSeg[s]));
+ eEqual = ((e < numSegs) && (end == excludeSeg[e]));
+
+ /* make sure that this isn't the first scanline, and that
+ a valid exclude segment will be referenced in the array.*/
+ if ((yBottom != gdiEnv.clipRect.top) && (s != numSegs))
+ {
+ /* ensure the excluded excludeSeg starts on even offset */
+ yTop = s / 2;
+ left = yTop * 2;
+
+ /* put the excluded rectangle record into the metafile */
+ ExcludeClipRect( gdiEnv.metafile,
+ excludeSeg[left], yStart[yTop],
+ excludeSeg[left + 1], yBottom);
+
+ /* reset the new y coordinate for the excludeSeg */
+ yStart[yTop] = yBottom;
+
+ /* determine if 2 segments are affected in merge */
+ if (((e - left >= 2 && eEqual && sEqual) ||
+ (e - left >= 2 && eEqual) ||
+ (e - left == 3 && sEqual)))
+ {
+ /* if so, put put eliminated cliprect in also */
+ ExcludeClipRect( gdiEnv.metafile,
+ excludeSeg[left + 2], yStart[yTop + 1],
+ excludeSeg[left + 3], yBottom);
+
+ /* reset the y coordinate for this new segment */
+ yStart[yTop + 1] = yBottom;
+ }
+ }
+
+ /* if start and end fall on existing excludeSegs */
+ if (sEqual && eEqual)
+ {
+ /* segment count reduced by 2 */
+ numSegs -= 2;
+
+ /* if two segments are involved in merge
+
+ 0 *---------* 1 2 *--------* 3
+ s *+++++++++++++++++++++++* e
+ 0 *======================* 1
+ */
+ if (e - s == 2)
+ {
+ /* move down the end point of the first segment */
+ excludeSeg[s] = excludeSeg[s + 1];
+ yStart[s / 2 + 1] = yStart[s / 2];
+
+ /* increment the start point for the segment shift */
+ s++;
+ }
+
+ /* handle case where a single segment is affected
+
+ 0 *---------* 1 2 *--------* 3
+ s *+++++++++++++* e
+ 0 *================================* 1
+ */
+ /* move all the flats two points to the left */
+ for ( ; s < numSegs; s += 2)
+ {
+ excludeSeg[s] = excludeSeg[s + 2];
+ excludeSeg[s + 1] = excludeSeg[s + 3];
+ yStart[s / 2] = yStart[s / 2 + 1];
+ }
+ }
+ /* if just the starting point is identical */
+ else if (sEqual)
+ {
+ /* if segment boundary was crossed - 2 segs affected
+
+ 0 *---------* 1 2 *-------------* 3
+ s *++++++++++++++++* e
+ 0 *==================* 1 2 *=====* 3
+ */
+ if ((excludeSeg[s + 1] < end) && (s + 1 < numSegs))
+ {
+ /* toggle the start/end points and insert end */
+ excludeSeg[s] = excludeSeg[s + 1];
+ excludeSeg[s + 1] = end;
+ }
+ /* otherwise, a simple extension of the segment is done
+
+ 0 *---------* 1
+ s *++++++++++++++++++++++* e
+ 0 *================================* 1
+ */
+ else
+ {
+ /* assign a new ending point for the excludeSeg */
+ excludeSeg[s] = end;
+ }
+ }
+ /* if just the ending point is identical */
+ else if (eEqual)
+ {
+ /* if segment boundary was crossed - 2 segs affected
+
+ 0 *------------* 1 2 *------* 3
+ s *++++++++++++++++++++* e
+ 0 *====* 1 2 *===================* 3
+ */
+ if ((excludeSeg[e - 1] > start) && (e - 1 > 0))
+ {
+ /* toggle the start/end points and insert start */
+ excludeSeg[s + 1] = excludeSeg[s];
+ excludeSeg[s] = start;
+ }
+ /* otherwise, a simple extension of the segment is done
+
+ 0 *---------* 1
+ s *++++++++++++++++++++++* e
+ 0 *================================* 1
+ */
+ else
+ {
+ /* assign a new starting point for the excludeSeg */
+ excludeSeg[e] = start;
+ }
+ }
+ /* if an entirely new excludeSeg is being created */
+ else
+ {
+ Integer idx;
+
+ /* create an new set of points */
+ numSegs += 2;
+
+ /* move all the flats two points to the right */
+ for (idx = numSegs - 1; idx > s; idx -= 2)
+ {
+ excludeSeg[idx] = excludeSeg[idx - 2];
+ excludeSeg[idx + 1] = excludeSeg[idx - 1];
+ yStart[idx / 2] = yStart[idx / 2 - 1];
+ }
+
+ /* start and endpoints are identical, insert new seg
+
+ 0 *--------------------------------------* 1
+ s *++++++++++++++++* e
+ 0 *=========* 1 2 *===========* 3
+ */
+ if (s == e)
+ {
+ /* and insert the new excludeSeg */
+ excludeSeg[s] = start;
+ excludeSeg[s + 1] = end;
+ yStart[s / 2] = yBottom;
+ }
+ /* otherwise, need to shift in the new points
+
+ 0 *---------------------* 1
+ s *++++++++++++++++++++++++++++* e
+ 0 *=========* 1 2 *================* 3
+ */
+ else
+ {
+ excludeSeg[s] = start;
+ excludeSeg[s + 1] = excludeSeg[s + 2];
+ excludeSeg[s + 2] = end;
+ yStart[s / 2] = yBottom;
+ yStart[s / 2 + 1] = yBottom;
+ }
+ }
+ }
+
+ /* increment past the end of line flag */
+ rgnLPtr++;
+ }
+
+ /* place the end of clip region comment into metafile */
+ gdiComment.function = PP_ENDCLIPREGION;
+ GdiShortComment( &gdiComment );
+ }
+
+ /* unlock the memory handle */
+ GlobalUnlock( rgn );
+
+} /* GdiSelectClipRegion */
+
+
+
+void GdiHatchPattern( Integer hatchIndex )
+/*==================*/
+/* Use the hatch pattern index passed down to perform all ensuing fill
+ operations - 0-6 for a hatch value, -1 turns off the substitution */
+{
+ gdiEnv.hatchIndex = hatchIndex;
+
+} /* GdiHatchPattern */
+
+
+
+void GdiFontName( Byte fontFamily, Byte charSet, StringLPtr fontName )
+/*==============*/
+/* Set font characteristics based upno metafile comment from GDI2QD */
+{
+ /* copy the passed values into the font table */
+ fontTable[FntFromGdi].family = fontFamily;
+ fontTable[FntFromGdi].charset = charSet;
+ lstrcpy( fontTable[FntFromGdi].gdiName, fontName );
+
+ /* indicate that the font name should be used - no table lookup */
+ gdiEnv.useGdiFont = TRUE;
+
+} /* GdiFontName */
+
+
+
+void GdiShortComment( CommentLPtr cmtLPtr )
+/*==================*/
+/* Write public or private comment with no associated data */
+{
+ /* write the comment into the metafile */
+ GdiEscape( MFCOMMENT, sizeof( Comment ), (StringLPtr)cmtLPtr );
+
+} /* GdiComment */
+
+
+
+void GdiEscape( Integer function, Integer count, StringLPtr data)
+/*============*/
+/* Write out a GDI Escape structure with no returned data */
+{
+ /* Flush the cache before emitting the new metafile record */
+ CaFlushCache();
+
+ /* write the comment into the metafile */
+ Escape( gdiEnv.metafile, function, count, data, NULL );
+
+} /* GdiEscape */
+
+
+
+void GdiSetConversionPrefs( ConvPrefsLPtr convPrefs)
+/*=====================*/
+/* Provide conversion preferences via global data block */
+{
+ /* Save the metafile prefs Open() is issued */
+ gdiPrefsLPtr = convPrefs;
+
+} /* GdiSetConversionPrefs */
+
+
+void GdiOpenMetafile( void )
+/*==================*/
+/* Open metafile passed by GdiSetMetafileName() and perform any
+ initialization of the graphics state */
+{
+ /* save metafile handle in global memory structure */
+ gdiEnv.metafile = CreateMetaFile( gdiPrefsLPtr->metafileName );
+ if (gdiEnv.metafile == NULL)
+ {
+ ErSetGlobalError( ErCreateMetafileFail );
+ }
+ else
+ {
+ /* get a handle to an information context for text metrics */
+ gdiEnv.infoContext = CreateIC( "DISPLAY", NULL, NULL, NULL );
+#ifdef _OLECNV32_
+ gdiEnv.fontFunction = EnumFontFunc;
+#else
+ gdiEnv.fontFunction = GetProcAddress( GetModuleHandle( "PICTIMP" ), "EnumFontFunc" );
+#endif
+
+ /* initialize the cache module */
+ CaInit( gdiEnv.metafile );
+
+ /* set up default logical font structures */
+ gdiEnv.newLogFont = logFontSkel;
+
+ /* enable drawing to metafile */
+ gdiEnv.drawingEnabled = TRUE;
+
+ /* don't override font table search until font comment is found */
+ gdiEnv.useGdiFont = FALSE;
+
+ /* don't use a hatch pattern substitution */
+ gdiEnv.hatchIndex = -1;
+
+ /* set the sameObject flag to FALSE and notify cache module */
+ gdiEnv.sameObject = FALSE;
+ CaSamePrimitive( FALSE );
+
+ /* determine if running on Windows 3.1 or higher */
+ if (LOBYTE( GetVersion() ) >= 3 && HIBYTE( GetVersion() ) >= 10 )
+ {
+ Byte i;
+
+ /* change the font substitution name to TrueType fonts */
+ for (i = 0; i < NumTTSubs; i++)
+ {
+ lstrcpy( fontTable[TTSubStart + i].gdiName, trueTypeSub[i] );
+ }
+
+ /* change the font family for "Symbol" to FF_ROMAN */
+ fontTable[FntSymbol].family = FF_ROMAN;
+
+ /* loop through all entries, changing FF_DECORATIVE to FF_DONTCARE */
+ for (i = 0; i < FntNoMatch; i++)
+ {
+ /* check for the family that needs to be changed */
+ if (fontTable[i].family == FF_DECORATIVE)
+ {
+ /* change to FF_DONTCARE */
+ fontTable[i].family = FF_DONTCARE;
+ }
+ }
+ }
+ }
+
+} /* GdiOpenMetafile */
+
+
+void GdiSetBoundingBox( Rect bbox, Integer resolution )
+/*====================*/
+/* Set the overall picture size and picture resoulution in dpi */
+{
+ /* make sure this isn't an empty bounding rectangle */
+ if (EmptyRect( bbox ))
+ {
+ /* if an error, then bail out */
+ ErSetGlobalError( ErNullBoundingRect );
+ }
+ /* check if either dimension exceeds 32K - this would be flagged by a
+ negative dimension signifying integer overflow condition */
+ else if ((Width( bbox ) < 0) || (Height( bbox ) < 0))
+ {
+ /* indicate that the 32K limit was exceeded */
+ ErSetGlobalError( Er32KBoundingRect );
+ }
+ else
+ {
+ /* Set up the Window origin in metafile and shadow DC */
+
+#ifdef WIN32
+ SetWindowOrgEx( gdiEnv.metafile, bbox.left, bbox.top, NULL );
+#else
+ SetWindowOrg( gdiEnv.metafile, bbox.left, bbox.top );
+#endif
+
+ /* Set window extent in metafile and shadow DC */
+
+#ifdef WIN32
+ SetWindowExtEx( gdiEnv.metafile, Width( bbox), Height( bbox ), NULL );
+#else
+ SetWindowExt( gdiEnv.metafile, Width( bbox), Height( bbox ) );
+#endif
+
+ /* Notify cache of the new clipping rectangle */
+ CaSetClipRect( bbox );
+
+ /* Notify cache that it should issue metafile defaults before SaveDC() */
+ CaSetMetafileDefaults();
+
+ /* Save display context, just in case clipping rect changes */
+ CaSaveDC();
+
+ /* Save overall dimensions and resolution in picture results structure */
+ gdiPict.bbox = bbox;
+ gdiPict.inch = resolution;
+
+ /* save the bounding box in the environment as the clipping rectangle */
+ gdiEnv.clipRect = bbox;
+ }
+
+} /* GdiSetBoundingBox */
+
+
+void GdiCloseMetafile( void )
+/*===================*/
+/* Close the metafile handle and end picture generation */
+{
+ /* flush the cache before proceeding */
+ CaFlushCache();
+
+ /* Balance CaSaveDC() issued at beginning of the metafile */
+ CaRestoreDC();
+
+ /* and close the metafile */
+ gdiPict.hmf = CloseMetaFile( gdiEnv.metafile );
+
+ /* check the return value from the closemetafile - may be out of memory? */
+ if (gdiPict.hmf == NULL)
+ {
+ ErSetGlobalError( ErCloseMetafileFail );
+ }
+
+ /* release the information context */
+ DeleteDC( gdiEnv.infoContext );
+
+ /* Close down the cache module */
+ CaFini();
+
+ /* if global error occurred, then remove metafile */
+ if (ErGetGlobalError() != NOERR)
+ {
+ DeleteMetaFile( gdiPict.hmf );
+ gdiPict.hmf = NULL;
+ }
+
+} /* GdiCloseMetafile */
+
+
+
+void GdiGetConversionResults( PictInfoLPtr pictInfoLPtr )
+/*==========================*/
+/* return results of the conversion */
+{
+ /* just assign the saved values into the pointer passed in */
+ *pictInfoLPtr = gdiPict;
+
+} /* GdiGetConversionResults */
+
+
+
+void GdiMarkAsChanged( Integer attribCode )
+/*===================*/
+/* indicate that the attribute passed in has changed */
+{
+ gdiEnv.state[attribCode] = Changed;
+
+} /* GdiMarkAsChanged */
+
+
+void GdiSamePrimitive( Boolean same )
+/*===================*/
+/* indicate whether next primitive is the same or new */
+{
+ /* save the state for merging of fill and frame operation */
+ gdiEnv.sameObject = (same && (CaGetCachedPrimitive() != CaEmpty));
+
+ CaSamePrimitive( same );
+
+} /* GdiSamePrimitive */
+
+
+#ifdef WIN32
+int WINAPI EnumFontFunc( CONST LOGFONT *logFontLPtr, CONST TEXTMETRIC *tmLPtr,
+ DWORD fontType, LPARAM dataLPtr )
+/*====================*/
+#else
+int FAR PASCAL EnumFontFunc( LPLOGFONT logFontLPtr, LPTEXTMETRIC tmLPtr,
+ short fontType, LPSTR dataLPtr )
+/*========================*/
+#endif
+/* Callback function used to determine if a given font is available */
+{
+ /* copy the passed values into the font table */
+ fontTable[FntNoMatch].family = logFontLPtr->lfPitchAndFamily;
+ fontTable[FntNoMatch].charset = logFontLPtr->lfCharSet;
+
+ /* this return value will be ignored */
+ return TRUE;
+
+ UnReferenced( tmLPtr );
+ UnReferenced( fontType );
+ UnReferenced( dataLPtr );
+
+} /* EnumFontFunc */
+
+
+
+/******************************* Private Routines ***************************/
+
+
+private Boolean IsArithmeticMode( Integer mode )
+/*------------------------------*/
+/* return TRUE if this is an arithmetic transfer mode */
+{
+ switch (mode)
+ {
+ case QDBlend:
+ case QDAddPin:
+ case QDAddOver:
+ case QDSubPin:
+ case QDAdMax:
+ case QDSubOver:
+ case QDAdMin:
+ {
+ return TRUE;
+ }
+
+ default:
+ {
+ return FALSE;
+ }
+ }
+
+} /* IsArithmeticMode */
+
+
+private void CalculatePenSize( Point startPt, Point endPt, Point penSize )
+/*---------------------------*/
+/* calcuate the pen width to produce equivalent QuickDraw stroke */
+{
+ Point delta;
+ Real lineLen;
+
+ /* calcuate x and y delta of line segment */
+ delta.x = abs( endPt.x - startPt.x );
+ delta.y = abs( endPt.y - startPt.y );
+
+ /* see if we have a vertical or horizontal line. Otherwise, calculate
+ the resulting line length on diagonal line. */
+ if (delta.x == 0)
+ {
+ gdiEnv.newLogPen.lopnWidth.x = penSize.x;
+ }
+ else if (delta.y == 0)
+ {
+ gdiEnv.newLogPen.lopnWidth.x = penSize.y;
+ }
+ /* check if the pen size is 1 in each direction */
+ else if ((penSize.x == 1) && (penSize.y == 1))
+ {
+ /* in this case, it should always be pen width of 1 */
+ gdiEnv.newLogPen.lopnWidth.x = 1;
+ }
+ else
+ {
+ /* calculate the line length using Pythagorean theorem */
+ lineLen = sqrt( ((Real)delta.x * (Real)delta.x) +
+ ((Real)delta.y * (Real)delta.y) );
+
+ /* calculate the correct line diameter */
+ gdiEnv.newLogPen.lopnWidth.x = (Integer)((penSize.y * delta.x +
+ penSize.x * delta.y) / lineLen);
+ }
+
+ /* make sure that SetPenAttributes() doesn't change pen width */
+ GdiMarkAsCurrent( GdiPnSize );
+
+} /* CalculatePenSize */
+
+
+
+private Boolean SetAttributes( GrafVerb verb )
+/*---------------------------*/
+/* set up pen and brush elements according to GrafVerb */
+{
+ Boolean allOK;
+
+ /* if call to SetPenAttributes() fails, then return false */
+ allOK = FALSE;
+
+ /* set up pen attributes */
+ if (SetPenAttributes( verb ))
+ {
+ /* set up brush attributes */
+ allOK = SetBrushAttributes( verb );
+ }
+
+ /* return continue or stop status */
+ return allOK;
+
+} /* SetAttributes */
+
+
+
+private Boolean SetPenAttributes( GrafVerb verb )
+/*-----------------------------*/
+/* make sure that pen attributes are OK according to preferences */
+{
+ CGrafPortLPtr port;
+
+ /* Get the QuickDraw port in order to check pen settings */
+ QDGetPort( &port );
+
+ /* see if we are drawing with a NULL pen and can skip all the checks */
+ if (verb == GdiFrame)
+ {
+ /* check for hidden pen mode - don't draw if invalid */
+ if (IsHiddenPenMode( port->pnMode ))
+ {
+ return FALSE;
+ }
+ /* check for zero-size pen width = don't draw anything */
+ else if (port->pnSize.x == 0 || port->pnSize.y == 0)
+ {
+ return FALSE;
+ }
+
+ /* use inside frame to best approximate the QD drawing model */
+ gdiEnv.newLogPen.lopnStyle = PS_INSIDEFRAME;
+ }
+ else
+ {
+ /* if paint, erase, invert, or fill, then there is no perimeter */
+ gdiEnv.newLogPen.lopnStyle = PS_NULL;
+ }
+
+ /* if NULL pen, then all the other fields don't change and don't matter */
+ if (gdiEnv.newLogPen.lopnStyle != PS_NULL)
+ {
+ /* make sure that we are changing the pen size */
+ if (GdiAttribHasChanged( GdiPnSize ))
+ {
+ /* check for non-square pen */
+ if (port->pnSize.x == port->pnSize.y)
+ {
+ /* use x dimensions as the pen size if square pen */
+ gdiEnv.newLogPen.lopnWidth.x = port->pnSize.x;
+ }
+ else
+ {
+ /* if non-square, do what the user requests */
+ switch (gdiPrefsLPtr->nonSquarePenAction)
+ {
+ case GdiPrefOmit: // omit line entirely
+ return FALSE;
+ break;
+
+ case 1: // use width
+ gdiEnv.newLogPen.lopnWidth.x = port->pnSize.x;
+ break;
+
+ case GdiPrefAbort: // abort conversion completely
+ ErSetGlobalError( ErNonSquarePen );
+ return FALSE;
+ break;
+
+ case 3: // use height
+ gdiEnv.newLogPen.lopnWidth.x = port->pnSize.y;
+ break;
+
+ case 4: // use minimum dimension
+ gdiEnv.newLogPen.lopnWidth.x = min( port->pnSize.x, port->pnSize.y );
+ break;
+
+ case 5: // use maximum dimension
+ gdiEnv.newLogPen.lopnWidth.x = max( port->pnSize.x, port->pnSize.y );
+ break;
+ }
+ }
+
+ /* indicate that the pen size is current */
+ GdiMarkAsCurrent( GdiPnSize );
+ }
+
+ /* get the correct pen color that we should draw with */
+ if (!IsSolidPattern( &port->pnPixPat, &gdiEnv.newLogPen.lopnColor, MIXGREY ) )
+ {
+ /* check what to do with patterned pen */
+ switch (gdiPrefsLPtr->penPatternAction)
+ {
+ case GdiPrefOmit: // omit line entirely
+ return FALSE;
+ break;
+
+ case 1: // use foreground color
+ gdiEnv.newLogPen.lopnColor = port->rgbFgColor;
+ break;
+
+ case GdiPrefAbort: // abort conversion completely
+ ErSetGlobalError( ErPatternedPen );
+ return FALSE;
+ break;
+ }
+ }
+
+ /* make sure that we are changing the pen size */
+ if (GdiAttribHasChanged( GdiPnMode ))
+ {
+ /* finally, check the transfer mode */
+ if (IsArithmeticMode( port->pnMode ))
+ {
+ switch (gdiPrefsLPtr->penModeAction)
+ {
+ case GdiPrefOmit: // omit line entirely
+ return FALSE;
+ break;
+
+ case 1: // use srcCopy
+ CaSetROP2( R2_COPYPEN );
+ break;
+
+ case GdiPrefAbort: // abort conversion completely
+ ErSetGlobalError( ErInvalidXferMode );
+ return FALSE;
+ break;
+ }
+ }
+
+ /* indicate that the pen pattern is current */
+ GdiMarkAsCurrent( GdiPnMode );
+ }
+ }
+
+ /* notify cache that it should attempt to merge fill and frame */
+ CaMergePen( verb );
+
+ /* call cache module to create new pen */
+ CaCreatePenIndirect( &gdiEnv.newLogPen );
+
+ /* check if we are framing a previously filled object */
+ if (gdiEnv.sameObject && verb == GdiFrame)
+ {
+ /* if so, flush the cache and indicate that nothing more to do */
+ CaFlushCache();
+ return FALSE;
+ }
+ else
+ {
+ /* return all systems go */
+ return TRUE;
+ }
+
+
+} /* SetPenAttributes */
+
+
+
+
+
+private Boolean SetBrushAttributes( GrafVerb verb )
+/*--------------------------------*/
+/* set up the correct brush (fill) for the ensuing primitive */
+{
+ CGrafPortLPtr port;
+ PixPatLPtr pixPatLPtr;
+
+ /* get the Quickdraw port to access brush patterns */
+ QDGetPort( &port );
+
+ /* Determine the brush pattern that should be used */
+ switch (verb)
+ {
+ /* fill with HOLLOW brush */
+ case GdiFrame:
+ gdiEnv.newLogBrush.lbStyle = BS_HOLLOW;
+ break;
+
+ /* fill using current pen pattern */
+ case GdiPaint:
+ pixPatLPtr = &port->pnPixPat;
+ gdiEnv.newLogBrush.lbStyle = BS_DIBPATTERN;
+ break;
+
+ /* fill using current fill pattern */
+ case GdiFill:
+ if (gdiEnv.hatchIndex == -1)
+ {
+ pixPatLPtr = &port->fillPixPat;
+ gdiEnv.newLogBrush.lbStyle = BS_DIBPATTERN;
+ }
+ else
+ {
+ /* override pattern with a hatch pattern index */
+ gdiEnv.newLogBrush.lbStyle = BS_HATCHED;
+ gdiEnv.newLogBrush.lbColor = port->rgbFgColor;
+ gdiEnv.newLogBrush.lbHatch = gdiEnv.hatchIndex;
+
+ /* set the background color and make the hatch opaque */
+ CaSetBkColor( port->rgbBkColor );
+ CaSetBkMode( OPAQUE );
+ }
+ break;
+
+ /* erase to current background pattern */
+ case GdiErase:
+ pixPatLPtr = &port->bkPixPat;
+ gdiEnv.newLogBrush.lbStyle = BS_DIBPATTERN;
+ break;
+
+ /* invert all bits using black brush */
+ case GdiInvert:
+ gdiEnv.newLogBrush.lbStyle = BS_SOLID;
+ gdiEnv.newLogBrush.lbColor = RGB( 0, 0, 0 );
+ break;
+ }
+
+ /* if this is a DIB pattern, check to see if we are using a solid brush */
+ if (gdiEnv.newLogBrush.lbStyle == BS_DIBPATTERN)
+ {
+ /* first check if this is a dithered pixmap pattern */
+ if (pixPatLPtr->patType == QDDitherPat)
+ {
+ /* read the color from the secret reserved field */
+ gdiEnv.newLogBrush.lbColor = pixPatLPtr->patMap.pmReserved;
+ gdiEnv.newLogBrush.lbStyle = BS_SOLID;
+
+ }
+ else
+ {
+ /* if this is a solid pattern, assign new solid pattern color. */
+ if (IsSolidPattern( pixPatLPtr, &gdiEnv.newLogBrush.lbColor, NOMIX ))
+ {
+ /* if this is a solid brush, change the logBrush desired attribs */
+ gdiEnv.newLogBrush.lbStyle = BS_SOLID;
+
+ /* make sure that the pen color is correct for Erase grafVerb */
+ if (verb == GdiErase)
+ {
+ /* check the new color setting */
+ if (gdiEnv.newLogBrush.lbColor == port->rgbFgColor)
+ {
+ gdiEnv.newLogBrush.lbColor = port->rgbBkColor;
+ }
+ else
+ {
+ gdiEnv.newLogBrush.lbColor = port->rgbFgColor;
+ }
+ }
+ }
+ else
+ {
+ /* save the type of pattern DIB that is being created */
+ gdiEnv.lastPatType = pixPatLPtr->patType;
+
+ /* set the color field to indicate that we are using RGB palette */
+ gdiEnv.newLogBrush.lbColor = DIB_RGB_COLORS;
+
+ /* create DIB pattern based upon pattern type */
+ switch (pixPatLPtr->patType)
+ {
+ /* create a simple 2-color pattern DIB brush */
+ case QDOldPat:
+ {
+ MakePatternBrush( pixPatLPtr );
+ break;
+ }
+
+ /* create full-scale pattern DIB brush */
+ case QDNewPat:
+ {
+ MakeDIB( &pixPatLPtr->patMap, pixPatLPtr->patData,
+ (Handle far *)&gdiEnv.newLogBrush.lbHatch,
+ (Handle far *)NULL,
+ TRUE );
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* call cache module to create brush and select it into metafile */
+ CaCreateBrushIndirect( &gdiEnv.newLogBrush );
+
+ /* all OK */
+ return TRUE;
+
+} /* SetBrushAttributes */
+
+
+private void MakePatternBrush( PixPatLPtr pixPatLPtr )
+/*---------------------------*/
+/* Make a new pattern brush using pixelPat passed in */
+{
+ CGrafPort far * port;
+ PatBrush far * patLPtr;
+ Byte i;
+ DWORD far * gdiPattern;
+ Byte far * qdPattern;
+ Byte far * savePattern;
+
+ /* allocate the new structure */
+ gdiEnv.newLogBrush.lbHatch = (Integer) GlobalAlloc( GHND, sizeof( PatBrush ) );
+
+ /* make sure that the memory could be allocated */
+ if (gdiEnv.newLogBrush.lbHatch == (Integer) NULL)
+ {
+ ErSetGlobalError( ErMemoryFull );
+ return;
+ }
+
+ /* Get QuickDraw port address to access fore and background colors */
+ QDGetPort( &port );
+
+ /* set the corresponding text and background colors for metafile */
+ CaSetBkColor( port->rgbBkColor );
+ CaSetTextColor( port->rgbFgColor );
+
+ /* lock down the data to access the individual elements */
+ patLPtr = (PatBrushLPtr)GlobalLock( (HANDLE) gdiEnv.newLogBrush.lbHatch );
+
+ /* copy over skelton brush structure */
+ *patLPtr = patBrushSkel;
+
+ /* save the fore- and background colors for later compares */
+ gdiEnv.lastFgColor = port->rgbFgColor;
+ gdiEnv.lastBkColor = port->rgbBkColor;
+
+ /* convert the current background color to RGBQUAD structure */
+ patLPtr->bmiColors[0].rgbRed = GetRValue( port->rgbFgColor );
+ patLPtr->bmiColors[0].rgbBlue = GetBValue( port->rgbFgColor );
+ patLPtr->bmiColors[0].rgbGreen = GetGValue( port->rgbFgColor );
+ patLPtr->bmiColors[0].rgbReserved = 0;
+
+ /* convert the current foreground color to RGBQUAD structure */
+ patLPtr->bmiColors[1].rgbRed = GetRValue( port->rgbBkColor );
+ patLPtr->bmiColors[1].rgbBlue = GetBValue( port->rgbBkColor );
+ patLPtr->bmiColors[1].rgbGreen = GetGValue( port->rgbBkColor );
+ patLPtr->bmiColors[1].rgbReserved = 0;
+
+ /* set up pointers to patterns in preparation for copy */
+ savePattern = (Byte far *)&gdiEnv.lastPattern[7];
+ qdPattern = (Byte far *)&pixPatLPtr->pat1Data[7];
+ gdiPattern = (DWORD far *)&patLPtr->pattern[0];
+
+ /* Copy the bitmap bits into the individual scanlines. Note that
+ we need to XOR the bits, since they are opposite to Windows GDI */
+ for (i = 0; i < sizeof( Pattern ); i++)
+ {
+ /* save off the pattern into the GDI environment for later compares */
+ *savePattern-- = *qdPattern;
+
+ /* note that scanlines are padded to a DWORD boundary */
+ *gdiPattern++ = (DWord)(*qdPattern-- ^ 0xFF);
+ }
+
+ /* Unlock the data for call to CreateBrushIndirect() */
+ GlobalUnlock( (HANDLE) gdiEnv.newLogBrush.lbHatch );
+
+} /* MakePatternBrush */
+
+
+
+
+private Boolean IsSolidPattern( PixPatLPtr pixPatLPtr,
+ RGBColor far * rgbColor,
+ Boolean mixColors )
+/*----------------------------*/
+/* return true if pattern is solid, false if not. If mixColors is TRUE, then
+ mixtures of 25%, 50%, and 75% grey are mixed into a solid color */
+{
+ Boolean solidPattern;
+ DWord repeatPattern;
+ DWord far * penBitsLPtr;
+ CGrafPort far * port;
+
+ /* get access to foreground and background colors */
+ QDGetPort( &port );
+
+ /* assume that the pattern isn't solid for now */
+ solidPattern = FALSE;
+
+ /* check whether to use old monochrome bitmap or new pixmap patterns */
+ if (pixPatLPtr->patType == QDOldPat)
+ {
+ /* check for patterned brush in 8x8 monochrome bitmap */
+ penBitsLPtr = (DWord far *)&pixPatLPtr->pat1Data;
+
+ /* save off the first DWord, and compare for matching scanlines */
+ repeatPattern = *penBitsLPtr;
+
+ /* check if either solid white (all 0's) or solid black (all 1's) */
+ if ((repeatPattern != 0x00000000) && (repeatPattern != 0xFFFFFFFF))
+ {
+ ; /* not solid black or white - just skip ensuing checks */
+ }
+ /* next, check if first block same as second block of bits */
+ else if (repeatPattern != penBitsLPtr[1])
+ {
+ ; /* first DWord doesn't match second - skip remaining checks */
+ }
+ /* so far, either a black or white pattern - check for black, first */
+ else if (repeatPattern == 0xFFFFFFFF)
+ {
+ /* solid black - use the port's foreground color */
+ *rgbColor = port->rgbFgColor;
+ solidPattern = TRUE;
+ }
+ /* finally, this must be a solid white pattern */
+ else /* if (repeatPattern == 0x00000000) */
+ {
+ /* solid white - use the background color in the QuickDraw port */
+ *rgbColor = port->rgbBkColor;
+ solidPattern = TRUE;
+ }
+
+ /* if this isn't a solid pattern, but we want to mix colors */
+ if (!solidPattern && mixColors)
+ {
+ Byte i;
+ Byte blackBits;
+ Byte whiteBits;
+
+ /* set solid to TRUE, since we will be using a blend of the colors */
+ solidPattern = TRUE;
+
+ /* count the number of 1 bits in the pattern */
+ for (i = 0, blackBits = 0; i < sizeof( DWord ) * 8; i++)
+ {
+ /* bitwise AND for the addition, then shift one bit to right */
+ blackBits += (Byte)(repeatPattern & 1);
+ repeatPattern /= 2;
+ }
+
+ /* perform the same calculation using the second DWord */
+ for (i = 0, repeatPattern = penBitsLPtr[1]; i < sizeof( DWord ) * 8; i++)
+ {
+ /* bitwise AND for the addition, then shift one bit to right */
+ blackBits += (Byte)(repeatPattern & 1);
+ repeatPattern /= 2;
+ }
+
+ /* calculate white bit count, since black + white bits == 64 */
+ whiteBits = (Byte)64 - blackBits;
+
+ /* using the 1 bit count, calculate weighted average of fore- and
+ background colors in the QuickDraw port */
+ *rgbColor = RGB( (Byte)((blackBits * RValue( port->rgbFgColor ) + whiteBits * RValue( port->rgbBkColor )) / 64),
+ (Byte)((blackBits * GValue( port->rgbFgColor ) + whiteBits * GValue( port->rgbBkColor )) / 64),
+ (Byte)((blackBits * BValue( port->rgbFgColor ) + whiteBits * BValue( port->rgbBkColor )) / 64) );
+ }
+ }
+
+ /* return results of compare */
+ return solidPattern;
+
+} /* IsSolidPattern */
+
+
+
+private Boolean FrameMatchesFill( Word primType )
+/*------------------------------*/
+/* return TRUE if the fill pattern (current brush ) matches frame pattern */
+{
+ CGrafPortLPtr port;
+
+ /* get the Quickdraw port to access brush patterns */
+ QDGetPort( &port );
+
+ /* make sure this is the parameters and same primitive type */
+ if (!gdiEnv.sameObject || (CaGetCachedPrimitive() != primType))
+ {
+ return FALSE;
+ }
+ /* check whether we are using an old (8 byte) pattern brush */
+ else if (port->pnPixPat.patType != QDOldPat || gdiEnv.lastPatType != QDOldPat)
+ {
+ return FALSE;
+ }
+ /* we are only interested in comparing DIB pattern brushes */
+ else if (gdiEnv.newLogBrush.lbStyle != BS_DIBPATTERN)
+ {
+ return FALSE;
+ }
+ /* compare the fore- and background colors first */
+ else if ((port->rgbFgColor != gdiEnv.lastFgColor) ||
+ (port->rgbBkColor != gdiEnv.lastBkColor) )
+ {
+ return FALSE;
+ }
+ else
+ {
+ Byte i;
+
+ /* Compare each of the pattern bits to determine if same. */
+ for (i = 0; i < sizeof( Pattern ); i++)
+ {
+ /* if patterns don't match, return FALSE and exit loop */
+ if (port->pnPixPat.pat1Data[i] != gdiEnv.lastPattern[i])
+ {
+ return FALSE;
+ }
+ }
+ }
+
+ /* all the compares indicate that the fill matches the frame */
+ return TRUE;
+
+} /* FrameMatchesFill */
+
+
+
+private Boolean SetTextAttributes( void )
+/*-------------------------------*/
+/* set up text attributes - set mapChars to TRUE if should map to ANSI */
+{
+ CGrafPortLPtr port;
+
+ /* Get the QuickDraw port in order to check font settings */
+ QDGetPort( &port );
+
+ /* set the text alignment to be baseline */
+ CaSetTextAlign( TA_LEFT | TA_BASELINE | TA_NOUPDATECP );
+
+ /* set the correct foreground and background colors */
+ switch (port->txMode)
+ {
+ case QDSrcCopy:
+ CaSetTextColor( port->rgbFgColor );
+ CaSetBkColor( port->rgbBkColor );
+ break;
+
+ case QDSrcBic:
+ CaSetTextColor( port->rgbBkColor );
+ break;
+
+ case QDSrcXor:
+ CaSetTextColor( RGB( 0, 0, 0 ) );
+ break;
+
+ case QDSrcOr:
+ default:
+ CaSetTextColor( port->rgbFgColor );
+ break;
+ }
+
+ /* set the background cell transparency mode */
+ CaSetBkMode( (port->txMode == QDSrcCopy) ? OPAQUE : TRANSPARENT );
+
+ /* check the character extra field */
+ if (GdiAttribHasChanged( GdiChExtra ))
+ {
+ /* call the cache to set charextra in metafile */
+ CaSetTextCharacterExtra( port->chExtra );
+
+ /* update the status */
+ GdiMarkAsCurrent( GdiChExtra );
+ }
+
+ /* convert the QuickDraw clockwise rotation to GDI counter-clockwise */
+ gdiEnv.newLogFont.lfEscapement = (port->txRotation == 0) ?
+ 0 :
+ 10 * (360 - port->txRotation);
+
+ /* make sure text flipping is taken into consiseration */
+ gdiEnv.newLogFont.lfOrientation = (port->txFlip == QDFlipNone) ?
+ gdiEnv.newLogFont.lfEscapement :
+ ((gdiEnv.newLogFont.lfEscapement > 1800) ?
+ gdiEnv.newLogFont.lfEscapement - 1800 :
+ 1800 - gdiEnv.newLogFont.lfEscapement);
+
+ /* make sure that we are changing the text font name */
+ if (GdiAttribHasChanged( GdiTxFont ))
+ {
+ Integer newFont;
+
+ /* call the routine to find a matching GDI font face name */
+ newFont = FindGdiFont();
+
+ /* fill in information from the font lookup table */
+ gdiEnv.newLogFont.lfPitchAndFamily = fontTable[newFont].family | (Byte)DEFAULT_PITCH;
+
+ /* copy the correct font character set */
+ gdiEnv.newLogFont.lfCharSet = fontTable[newFont].charset;
+
+ /* copy over the new font face name */
+ lstrcpy( gdiEnv.newLogFont.lfFaceName, fontTable[newFont].gdiName );
+
+ /* indicate that the pen size is current */
+ GdiMarkAsCurrent( GdiTxFont );
+ }
+
+ /* make sure that we are changing the text attributes */
+ if (GdiAttribHasChanged( GdiTxFace ))
+ {
+ /* note that attributes QDTxShadow, QDTxCondense, and QDTxExtend
+ are not handled by GDI and will be removed permanently - SBT.
+ Set italic, underline and bold attributes as needed */
+ gdiEnv.newLogFont.lfItalic = (Byte)(port->txFace & QDTxItalic);
+ gdiEnv.newLogFont.lfUnderline = (Byte)(port->txFace & QDTxUnderline);
+ gdiEnv.newLogFont.lfWeight = (port->txFace & QDTxBold ) ?
+ FW_BOLD : FW_NORMAL;
+
+ /* indicate that the font attributes are current */
+ GdiMarkAsCurrent( GdiTxFace );
+ }
+
+ /* check the new font size */
+ if (GdiAttribHasChanged( GdiTxSize) || GdiAttribHasChanged( GdiTxRatio))
+ {
+ /* check for any text rescaling factor in vertical direction */
+ if (port->txNumerator.y == port->txDenominator.y)
+ {
+ /* note that we negate the font size in order to specify the
+ character height = cell height - internal leading */
+ gdiEnv.newLogFont.lfHeight = -port->txSize;
+ }
+ else
+ {
+ Integer txHeight;
+
+ /* scale the font size by numerator/denominator - use LongInts to
+ avoid possibility of overflowing Integer multiplication */
+ txHeight = (Integer)(((LongInt)port->txSize *
+ (LongInt)port->txNumerator.y +
+ (LongInt)(port->txDenominator.y / 2)) /
+ (LongInt)port->txDenominator.y);
+
+ gdiEnv.newLogFont.lfHeight = -txHeight;
+ }
+
+ /* indicate that the font size and scaling is current */
+ GdiMarkAsCurrent( GdiTxSize );
+ GdiMarkAsCurrent( GdiTxRatio );
+ }
+
+ /* call cache module to create the font and select it */
+ CaCreateFontIndirect( &gdiEnv.newLogFont );
+
+ /* everything a-ok */
+ return TRUE;
+
+} /* SetTextAttributes */
+
+
+
+private Integer FindGdiFont( void )
+/*-------------------------*/
+/* return an index to the current font selection */
+{
+ CGrafPortLPtr port;
+ Boolean findName;
+ Byte i;
+
+ /* check if the search is overridden by a font name comment */
+ if (gdiEnv.useGdiFont)
+ {
+ /* return the table index that the name was copied into */
+ return FntFromGdi;
+ }
+
+ /* Get the QuickDraw port in order to check font settings */
+ QDGetPort( &port );
+
+ /* see if lookup should be done on face name */
+ findName = (port->txFontName[0] != cNULL);
+
+ /* search through all font table entries to find a match */
+ for (i = 0; i < FntNoMatch; i++)
+ {
+ /* if looking up the font name, compare the macName field */
+ if (findName)
+ {
+ /* look for an exact string compare - equivalent strings */
+ if (lstrcmpi( fontTable[i].macName, port->txFontName ) == 0)
+ {
+ break;
+ }
+ }
+ else
+ {
+ /* otherwise, compare the font numbers */
+ if (fontTable[i].fontNum == port->txFont)
+ {
+ break;
+ }
+ }
+ }
+
+ /* see if there was no match found in the table */
+ if (i == FntNoMatch)
+ {
+ /* see if if we are comparing font names, and no match was found */
+ if (findName)
+ {
+ /* copy the Mac name over into the font table */
+ lstrcpy( fontTable[FntNoMatch].gdiName, port->txFontName );
+
+ /* assign default values for the charSet and family if not found */
+ fontTable[FntNoMatch].family = FF_ROMAN;
+ fontTable[FntNoMatch].charset = ANSI_CHARSET;
+
+ /* call Windows to enumerate any fonts that have the facename */
+#ifdef WIN32
+ EnumFonts( gdiEnv.infoContext, port->txFontName, gdiEnv.fontFunction, ( LPARAM ) NULL );
+#else
+ EnumFonts( gdiEnv.infoContext, port->txFontName, gdiEnv.fontFunction, NULL );
+#endif
+ /* return the font index of the new entry */
+ return FntNoMatch;
+ }
+ else
+ {
+ /* otherwise, use the default Helvetica font */
+ return FntDefault;
+ }
+ }
+ else
+ {
+ /* a match was found - return the table index */
+ return i;
+ }
+
+} /* FindGdiFont */
+
+
+
+private void MacToAnsi( StringLPtr string )
+/*--------------------*/
+/* convert extended characters from Mac to ANSI equivalent */
+{
+ /* determine if there should be character translations on the chars */
+ if (gdiEnv.newLogFont.lfCharSet == ANSI_CHARSET)
+ {
+ /* continue until we hit the NULL end of string marker */
+ while (*string)
+ {
+ /* if translating an extended character */
+ if ((Byte)*string >= (Byte)128)
+ {
+ /* perform character table lookup */
+ *string = MacToAnsiTable[(Byte)*string - (Byte)128];
+ }
+
+ /* if we encounter a non-printable character, convert to space */
+ if ((Byte)*string < (Byte)0x20)
+ {
+ *string = ' ';
+ }
+
+ /* increment the string pointer */
+ string++;
+ }
+ }
+}
+
+#if( REMAPCOLORS )
+
+private void RemapColors( PixMapLPtr pixMapLPtr, Handle pixDataHandle )
+/*------------------*/
+/* Remap colors for black and white in 16- or 256-color DIB */
+{
+ Byte remapTable[256];
+ Integer blackIndex = 0;
+ Integer whiteIndex = 0;
+ Integer index;
+
+ ColorTableLPtr colorTabLPtr;
+ Integer numColors;
+ RGBColor far * curColorLPtr;
+
+ /* lock the color table before copying over the color table */
+ colorTabLPtr = (ColorTableLPtr)GlobalLock( pixMapLPtr->pmTable );
+
+ /* set up the color entry pointers */
+ curColorLPtr = colorTabLPtr->ctColors;
+
+ /* determine number of colors in DIB */
+ numColors = colorTabLPtr->ctSize;
+
+ /* copy over all the color entries */
+ for (index = 0; index < numColors; index++ )
+ {
+ /* copy color to local variable */
+ RGBColor color = *curColorLPtr;
+
+ /* is this the black entry? */
+ if( color == RGB( 0, 0, 0 ) )
+ blackIndex = index;
+ if( color == RGB( 255, 255, 255 ) )
+ whiteIndex = index;
+
+ /* just copy over the current assignment to the remap table */
+ remapTable[index] = (Byte)index;
+
+ /* increment the pointers */
+ curColorLPtr++;
+ }
+
+ if( blackIndex != 0 || whiteIndex != numColors - 1 )
+ {
+ if( whiteIndex == 0 )
+ {
+ // Direct swap of black and white colors.
+ remapTable[0] = (Byte)blackIndex;
+ remapTable[blackIndex] = (Byte)whiteIndex;
+
+ // Remap the colors in the palette, also
+ colorTabLPtr->ctColors[0] = colorTabLPtr->ctColors[blackIndex];
+ colorTabLPtr->ctColors[blackIndex] = colorTabLPtr->ctColors[whiteIndex];
+ }
+ else
+ {
+ Boolean doBlack;
+
+ for (index = 1, doBlack = TRUE; index < numColors; index++)
+ {
+ if( whiteIndex != index && blackIndex != index )
+ {
+ if( doBlack )
+ {
+ remapTable[index] = (Byte)blackIndex;
+ remapTable[blackIndex] = (Byte)index;
+ doBlack = FALSE;
+ }
+ else
+ {
+ remapTable[index] = (Byte)whiteIndex;
+ remapTable[whiteIndex] = (Byte)index;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* unlock color table and free associated memory */
+ GlobalUnlock( pixMapLPtr->pmTable );
+}
+
+#endif
+
+private void MakeDIB( PixMapLPtr pixMapLPtr, Handle pixDataHandle,
+ Handle far * headerHandleLPtr,
+ Handle far * bitsHandleLPtr,
+ Boolean packDIB )
+/*------------------*/
+/* Create a Windows device-independant bitmap */
+{
+ Integer pixelSize;
+ LongInt bitsInfoSize;
+ Boolean expandBits;
+ Boolean mergeRGB;
+ Boolean rleCompress;
+ DWord dibCompression;
+ Integer totalColors;
+ DWord dibWidth;
+ DWord dibHeight;
+ DWord totalBytes;
+ Integer rowBytes;
+ Integer bytesPerLine;
+ DWord rleByteCount;
+
+ /* determine the bitcount which will yield the size of the color table */
+ pixelSize = pixMapLPtr->pixelSize;
+
+#if( REMAPCOLORS )
+ /* if this is an 16 or 256 color DIB, we need to remap color indicies */
+ if( pixelSize == 4 || pixelSize == 8 )
+ {
+ RemapColors( pixMapLPtr, pixDataHandle );
+ }
+#endif
+
+ /* determine if RLE compression should be used in resulting DIB */
+ /* Use RLE for 4- & 8-bits/pixel, but not if calling app said no RLE */
+ if ((pixelSize == 4 || pixelSize == 8) && gdiPrefsLPtr->noRLE == 0)
+ {
+ /* use compression and set the correct bmiHeader compression */
+ rleCompress = TRUE;
+ dibCompression = (pixelSize == 4) ? BI_RLE4 : BI_RLE8;
+ }
+ else
+ {
+ /* no compression - the bytes are rgb palette indicies */
+ rleCompress = FALSE;
+ dibCompression = BI_RGB;
+ }
+
+ /* assume that no expansion will be required */
+ expandBits = FALSE;
+
+ /* round to 16-entry color table if this is a 4-entry pixel map or
+ to a 24-bit image if this is a 16-bit image */
+ if (pixelSize == 2 || pixelSize == 16)
+ {
+ expandBits = TRUE;
+ pixelSize = (pixelSize == 2) ? 4 : 24;
+ }
+ else if (pixelSize == 32)
+ {
+ /* change pixel size to 24 bits if this is a 32-bit pixMap */
+ pixelSize = 24;
+ }
+
+ /* if not creating a 24-bit DIB ... */
+ if (pixelSize <= 8)
+ {
+ /* calculate total number of colors used in resulting Windows DIB */
+ totalColors = 1 << pixelSize;
+ }
+ else
+ {
+ /* otherwise, we don't allocate for color table */
+ totalColors = 0;
+ }
+
+ /* calculate width and height - these are used frequently */
+ dibWidth = Width( pixMapLPtr->bounds );
+ dibHeight = Height( pixMapLPtr->bounds );
+
+ /* determine if the RGB components need to be merged in 24-bit image */
+ mergeRGB = (pixMapLPtr->packType == 4);
+
+ /* calculate the amount of memory required for header structure */
+ bitsInfoSize = sizeof( BITMAPINFOHEADER ) + totalColors * sizeof( RGBQUAD );
+
+ /* calculate the number of bytes per line - round to DWORD boundary */
+ bytesPerLine = (Word)((dibWidth * (LongInt)pixelSize + 31) / 32) * 4;
+
+ /* save off rowBytes size for later calculations */
+ rowBytes = pixMapLPtr->rowBytes & RowBytesMask;
+
+ /* calculate total amount of memory needed for bits */
+ totalBytes = dibHeight * bytesPerLine;
+
+ /* perform a pre-flight of compression to see if larger */
+ if (rleCompress)
+ {
+ DWord tempDibHeight = dibHeight;
+ Byte huge * srcLineHPtr;
+
+ /* lock source pixel bits, set pointer to last line in source bitmap */
+ srcLineHPtr = (Byte huge *)GlobalLock( pixDataHandle );
+ srcLineHPtr = srcLineHPtr + ((LongInt)rowBytes * ((LongInt)dibHeight - 1));
+
+ /* initialize rle byte count */
+ rleByteCount = 0;
+
+ /* continue looping while bytes remain */
+ while (tempDibHeight--)
+ {
+ /* if this is a 16 or 256 color DIB, then use RLE compression.
+ The rleByteCount is incremented inside the routine */
+ if (dibCompression == BI_RLE4)
+ {
+ hrlecpy16( srcLineHPtr, NULL, (Integer)dibWidth,
+ &rleByteCount, FALSE );
+ }
+ else
+ {
+ hrlecpy256( srcLineHPtr, NULL, (Integer)dibWidth,
+ &rleByteCount, FALSE );
+ }
+
+ /* move the source pointer */
+ srcLineHPtr -= rowBytes;
+ }
+
+ /* add in the end of bitmap record - increment total bytes */
+ rleByteCount += 2;
+
+ /* unlock the source pixel map */
+ GlobalUnlock( pixDataHandle );
+
+ /* check if the compression results in smaller DIB */
+ if (rleByteCount < totalBytes)
+ {
+ /* if smaller, adjust the total size to allocate */
+ totalBytes = rleByteCount;
+
+ /* re-initialize the byte count */
+ rleByteCount = 0;
+ }
+ else
+ {
+ /* larger - adjust compression technique */
+ rleCompress = FALSE;
+ dibCompression = BI_RGB;
+ }
+ }
+
+ /* if we are creating a packed DIB, then allocate only one data block */
+ if (packDIB)
+ {
+ *headerHandleLPtr = GlobalAlloc( GHND, (bitsInfoSize + totalBytes) );
+ }
+ else
+ {
+ /* allocate separate handles for header and bits */
+ *headerHandleLPtr = GlobalAlloc( GHND, bitsInfoSize );
+ *bitsHandleLPtr = GlobalAlloc( GHND, totalBytes );
+ }
+
+ /* check the results of the allocation for out-of-memory conditions */
+ if (*headerHandleLPtr == NULL)
+ {
+ ErSetGlobalError( ErMemoryFull );
+ }
+ else if (!packDIB)
+ {
+ if (*bitsHandleLPtr == NULL)
+ {
+ ErSetGlobalError( ErMemoryFull );
+ }
+ }
+
+ if (ErGetGlobalError() == NOERR)
+ {
+ BITMAPINFO far * bitsInfoLPtr;
+ Byte huge * srcLineHPtr;
+ Byte huge * dstLineHPtr;
+
+ /* lock the info header */
+ bitsInfoLPtr = (BITMAPINFO far *)GlobalLock( *headerHandleLPtr );
+
+ /* copy over all the header fields from the QuickDraw pixmap */
+ bitsInfoLPtr->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
+ bitsInfoLPtr->bmiHeader.biWidth = dibWidth;
+ bitsInfoLPtr->bmiHeader.biHeight = dibHeight;
+ bitsInfoLPtr->bmiHeader.biPlanes = 1;
+ bitsInfoLPtr->bmiHeader.biBitCount = pixelSize;
+ bitsInfoLPtr->bmiHeader.biCompression = dibCompression;
+ bitsInfoLPtr->bmiHeader.biSizeImage = (rleCompress ? totalBytes : 0);
+ bitsInfoLPtr->bmiHeader.biXPelsPerMeter = (DWord)(72 * 39.37);
+ bitsInfoLPtr->bmiHeader.biYPelsPerMeter = (DWord)(72 * 39.37);
+ bitsInfoLPtr->bmiHeader.biClrUsed = 0;
+ bitsInfoLPtr->bmiHeader.biClrImportant = 0;
+
+ /* make sure that there are colors to copy over */
+ if (totalColors)
+ {
+ ColorTableLPtr colorTabLPtr;
+ Integer numColors;
+ RGBQUAD far * curQuadLPtr;
+ RGBColor far * curColorLPtr;
+
+ /* lock the color table before copying over the color table */
+ colorTabLPtr = (ColorTableLPtr)GlobalLock( pixMapLPtr->pmTable );
+
+
+ /* set up the color entry pointers */
+ curColorLPtr = colorTabLPtr->ctColors;
+ curQuadLPtr = bitsInfoLPtr->bmiColors;
+
+ /* copy over all the color entries */
+ for (numColors = colorTabLPtr->ctSize; numColors; numColors-- )
+ {
+ RGBColor color;
+
+ /* copy color to local variable */
+ color = *curColorLPtr;
+
+ /* convert the color from COLORREF to RGBQUAD structure */
+ curQuadLPtr->rgbRed = GetRValue( color );
+ curQuadLPtr->rgbGreen = GetGValue( color );
+ curQuadLPtr->rgbBlue = GetBValue( color );
+ curQuadLPtr->rgbReserved = 0;
+
+ /* increment the pointers */
+ curQuadLPtr++;
+ curColorLPtr++;
+ }
+
+ /* fill in any empty color entries */
+ for (numColors = totalColors - colorTabLPtr->ctSize; numColors; numColors--)
+ {
+ /* put in a black color entry (unused) */
+ curQuadLPtr->rgbRed =
+ curQuadLPtr->rgbGreen =
+ curQuadLPtr->rgbBlue =
+ curQuadLPtr->rgbReserved = 0;
+
+ /* increment the pointers */
+ curQuadLPtr++;
+ }
+
+ /* unlock color table and free associated memory */
+ GlobalUnlock( pixMapLPtr->pmTable );
+
+ /* free the color table only if this isn't a pixel pattern */
+ if (!packDIB)
+ {
+ GlobalFree( pixMapLPtr->pmTable );
+ }
+ }
+
+ /* adjust for 24-bit images that have dropped high-order byte. Make
+ sure not to adjust for 16-bit images that will expand to 24-bit */
+ if (pixelSize == 24 && !expandBits)
+ {
+ rowBytes = rowBytes * 3 / 4;
+ }
+
+ /* determine where the data should be placed for the bitmap */
+ if (packDIB)
+ {
+ /* set the destination pointer to the end of the color table */
+ dstLineHPtr = (Byte huge *)((Byte far *)bitsInfoLPtr) + bitsInfoSize;
+ }
+ else
+ {
+ /* lock the data block handle if creating a normal DIB */
+ dstLineHPtr = (Byte huge *)GlobalLock( *bitsHandleLPtr );
+ }
+
+ /* lock source pixel bits, set pointer to last line in source bitmap */
+ srcLineHPtr = (Byte huge *)GlobalLock( pixDataHandle );
+ srcLineHPtr = srcLineHPtr + ((LongInt)rowBytes * ((LongInt)dibHeight - 1));
+
+ /* continue looping while bytes remain */
+ while (dibHeight--)
+ {
+ if (expandBits)
+ {
+ /* if expanding, expand each 2 bits to full nibble or if this
+ is a 16-bit image, expand to 24 bits */
+ hexpcpy( srcLineHPtr, dstLineHPtr, rowBytes, pixelSize );
+ }
+ else if (mergeRGB)
+ {
+ /* if the is a 24-bit image, then the components are separated
+ into scanlines of red, green and blue. Merge these into
+ a single RGB component for the entire line */
+ hmrgcpy( srcLineHPtr, dstLineHPtr, rowBytes / 3 );
+ }
+ else if (rleCompress)
+ {
+ /* if this is a 16 or 256 color DIB, then use RLE compression.
+ The rleByteCount is incremented inside the routine */
+ if (dibCompression == BI_RLE4)
+ {
+ hrlecpy16( srcLineHPtr, dstLineHPtr + rleByteCount,
+ (Integer)dibWidth, &rleByteCount, TRUE );
+ }
+ else
+ {
+ hrlecpy256( srcLineHPtr, dstLineHPtr + rleByteCount,
+ (Integer)dibWidth, &rleByteCount, TRUE );
+ }
+ }
+ else
+ {
+ /* if no expansion required, then this is a simple copy */
+ hmemcpy( srcLineHPtr, dstLineHPtr, rowBytes );
+ }
+
+ /* move the source pointer and destination if not compressed */
+ srcLineHPtr -= rowBytes;
+ if (!rleCompress)
+ {
+ dstLineHPtr += bytesPerLine;
+ }
+ }
+
+ /* if RLE compression was used, modify size field in the bmiHeader */
+ if (rleCompress)
+ {
+ /* add in the end of bitmap record - increment total bytes */
+ dstLineHPtr[rleByteCount++] = 0;
+ dstLineHPtr[rleByteCount++] = 1;
+ }
+
+ /* unlock the source pixel map */
+ GlobalUnlock( pixDataHandle );
+
+ /* unlock the destination header info handle */
+ GlobalUnlock( *headerHandleLPtr );
+
+ /* if this isn't packed, unlock the data pointer, also */
+ if (!packDIB)
+ {
+ GlobalUnlock( *bitsHandleLPtr );
+ }
+ }
+
+} /* MakeDIB */
+
+
+
+private Boolean MakeMask( Handle mask, Boolean patBlt)
+/*----------------------*/
+/* Create a mask that will be used in the ensuing StretchDIBits call.
+ Return TRUE if region was created, FALSE if rectangular region */
+{
+ PixMap pixMap;
+ Integer far * sizeLPtr;
+ LongInt bytesNeeded;
+ Boolean solidPatBlt;
+ Word mode;
+
+ /* determine if a solid pattern blt is being rendered - this can be
+ altered to render a "simple" StretchBlt that DOESN'T involve a brush */
+ solidPatBlt = patBlt && (gdiEnv.newLogBrush.lbStyle == BS_SOLID);
+
+ if (patBlt)
+ mode = (solidPatBlt) ? QDSrcOr : -2;
+ else
+ mode = (Word) -1;
+
+ /* Lock the region handle and retrieve the bounding box */
+ sizeLPtr = (Integer far *)GlobalLock( mask );
+
+ /* determine if we are just requesting a rectangular bitmap mask */
+ if (*sizeLPtr == RgnHeaderSize)
+ {
+ Rect clipRect;
+
+ /* determine the appropriate clipping rectangle */
+ clipRect = *((Rect far *)(sizeLPtr + 1));
+
+ /* Call Gdi module to change the clipping rectangle */
+ gdiEnv.drawingEnabled = CaIntersectClipRect( clipRect );
+
+ /* just unlock the mask and return to the calling routine */
+ GlobalUnlock( mask );
+
+ /* indicate that no region mask was created */
+ return FALSE;
+ }
+
+ /* determine bounding rectangle and rowBytes (rounded to word bondary) */
+ pixMap.bounds = *((Rect far *)(sizeLPtr + 1));
+
+ pixMap.rowBytes = ((Width( pixMap.bounds ) + 15) / 16) * sizeofMacWord;
+
+ /* if this is a bitmap, then we assign the various fields. */
+ pixMap.pmVersion = 0;
+ pixMap.packType = 0;
+ pixMap.packSize = 0;
+ pixMap.hRes = 0x00480000;
+ pixMap.vRes = 0x00480000;
+ pixMap.pixelType = 0;
+ pixMap.pixelSize = 1;
+ pixMap.cmpCount = 1;
+ pixMap.cmpSize = 1;
+ pixMap.planeBytes = 0;
+ pixMap.pmTable = 0;
+ pixMap.pmReserved = 0;
+
+ /* calculate the number of bytes needed for the color table */
+ bytesNeeded = sizeof( ColorTable ) + sizeof( RGBColor );
+
+ /* allocate the data block */
+ pixMap.pmTable = GlobalAlloc( GHND, bytesNeeded );
+
+ /* make sure that the allocation was successfull */
+ if (pixMap.pmTable == NULL)
+ {
+ ErSetGlobalError( ErMemoryFull );
+ }
+ else
+ {
+ ColorTable far * colorHeaderLPtr;
+ Handle maskBitmap;
+
+ /* lock the memory handle and prepare to assign color table */
+ colorHeaderLPtr = (ColorTable far *)GlobalLock( pixMap.pmTable );
+
+ /* 2 colors are present - black and white */
+ colorHeaderLPtr->ctSize = 2;
+ if (solidPatBlt)
+ {
+ colorHeaderLPtr->ctColors[0] = gdiEnv.newLogBrush.lbColor;
+ colorHeaderLPtr->ctColors[1] = RGB( 255, 255, 255 );
+ }
+ else
+ {
+ colorHeaderLPtr->ctColors[0] = RGB( 255, 255, 255 );
+ colorHeaderLPtr->ctColors[1] = RGB( 0, 0, 0 );
+ }
+
+ /* unlock the memory */
+ GlobalUnlock( pixMap.pmTable );
+
+ /* Create the correct bitmap from the mask region */
+ bytesNeeded = (LongInt)pixMap.rowBytes * (LongInt)(Height( pixMap.bounds ));
+
+ /* allocate the memory */
+ maskBitmap = GlobalAlloc( GHND, bytesNeeded );
+
+ /* make sure the allocation succeeded */
+ if (maskBitmap == NULL)
+ {
+ ErSetGlobalError( ErMemoryFull );
+ }
+ else
+ {
+ Integer far * maskLPtr;
+ Byte far * rowLPtr;
+ Integer curRow;
+
+ /* lock the memory for creation of the bitmap mask */
+ rowLPtr = GlobalLock( maskBitmap );
+
+ /* set the mask pointer to beginning of region information */
+ maskLPtr = sizeLPtr + 5;
+
+ /* loop until all rows have been traversed */
+ for (curRow = pixMap.bounds.top;
+ curRow < pixMap.bounds.bottom;
+ curRow++, rowLPtr += pixMap.rowBytes)
+ {
+ /* if this is the first row being created ... */
+ if (curRow == pixMap.bounds.top)
+ {
+ Integer i;
+
+ /* make all the bits the background color */
+ for (i = 0; i < pixMap.rowBytes; i++)
+ *(rowLPtr + i) = (Byte)0xFF;
+ }
+ else
+ {
+ /* copy over the information from the previous row */
+ hmemcpy( rowLPtr - pixMap.rowBytes, rowLPtr, pixMap.rowBytes );
+ }
+
+ /* determine if the desired mask line was reached */
+ if (*maskLPtr == curRow)
+ {
+ Integer start;
+ Integer end;
+
+ /* increment the mask pointer to get to the start/end values */
+ maskLPtr++;
+
+ /* continue looping until end of line marker encountered */
+ while (*maskLPtr != 0x7FFF)
+ {
+ /* determine the start and end point of bits to invert */
+ start = *maskLPtr++;
+ end = *maskLPtr++;
+
+ /* if reached, invert the desired bits in the mask */
+ InvertBits( rowLPtr, start - pixMap.bounds.left, end - start);
+ }
+
+ /* increment past the end of line flag */
+ maskLPtr++;
+ }
+ }
+
+ /* unlock the bitmap memory block */
+ GlobalUnlock( maskBitmap );
+
+ /* call the GdiStretchDIB() entry point to create the bitmap */
+ GdiStretchDIBits( &pixMap, maskBitmap,
+ pixMap.bounds, pixMap.bounds,
+ mode, NULL );
+
+ }
+
+ /* Unlock the mask region */
+ GlobalUnlock( mask );
+
+ /* indicate that a mask was created */
+ return TRUE;
+ }
+
+} /* MakeMask */
+
+
+
+void InvertBits( Byte far * byteLPtr, Integer start, Integer count )
+/*-------------*/
+/* invert all bits in byteLPtr from bit offset start for count bits */
+{
+ Byte byteMask;
+ Integer partialCount;
+
+ /* set the beginning byte index */
+ byteLPtr += start / 8;
+
+ /* determine the beginning mask offset = start % 8 */
+ partialCount = start & 0x0007;
+
+ /* set up the byte mask and decrement by number of bits processed */
+ byteMask = (Byte)(0xFF >> partialCount);
+ count -= 8 - partialCount;
+
+ /* continue looping while bits remain ... */
+ while (count >= 0)
+ {
+ /* invert all the mask bits */
+ *byteLPtr++ ^= byteMask;
+
+ /* set up the new byte mask - assume all bits will be set */
+ byteMask = 0xFF;
+
+ /* decrement the count */
+ count -= 8;
+ }
+
+ /* if a bitmask stilll remains */
+ if (count > -8 && count < 0)
+ {
+ /* the negative count indicates number of bits to be inverted */
+ count = -count;
+
+ /* shift right, then left to clear remaining bits */
+ byteMask = (Byte)((byteMask >> count) << count);
+
+ /* and XOR with current bits */
+ *byteLPtr ^= byteMask;
+ }
+
+} /* InvertBits */
+
+
+
+void hmemcpy( Byte huge * src, Byte huge * dst, Integer count )
+/*----------*/
+/* copy count bytes from source to destination - assumes even count */
+{
+ short huge * wSrc = (short far *)src;
+ short huge * wDst = (short far *)dst;
+ Integer wCount = count / sizeof ( short );
+
+ /* while words remain, copy to destination from source */
+ while (wCount--)
+ {
+ *wDst++ = *wSrc++;
+ }
+
+} /* hmemcpy */
+
+
+
+void hexpcpy( Byte huge * src, Byte huge * dst, Integer count, Integer bits )
+/*----------*/
+/* copy count bytes to destination, expand each 2 bits to nibble of if
+ 16-bit image, expand to 24 bits */
+{
+ /* check if expanding from 2 to 4 bits */
+ if (bits == 4)
+ {
+ Byte tempByte;
+ Byte result;
+
+ /* while bytes remain, copy to destination from source */
+ while (count--)
+ {
+ /* expand high nibble to full byte */
+ tempByte = *src;
+ result = (Byte)((tempByte >> 2) & (Byte)0x30);
+ result |= (Byte)((tempByte >> 6));
+ *dst++ = result;
+
+ /* expand low nibble to full byte */
+ tempByte = *src++;
+ result = (Byte)((tempByte & (Byte)0x0C) << 2);
+ result |= (Byte)((tempByte & (Byte)0x03));
+ *dst++ = result;
+ }
+ }
+ else /* if (bits == 24) */
+ {
+ Word tempWord;
+
+ /* while words remain, copy to destination from source */
+ while (count)
+ {
+ /* read the next two bytes into a full word, swapping bytes */
+ tempWord = (Word)(*src++ << 8);
+ tempWord |= (Word)(*src++);
+
+ /* 2 full bytes were read - decrement */
+ count -= 2;
+
+ /* expand each 5 bits to full byte */
+ *dst++ = (Byte)((tempWord & 0x001F) << 3);
+ *dst++ = (Byte)((tempWord & 0x03E0) >> 2);
+ *dst++ = (Byte)((tempWord & 0x7C00) >> 7);
+ }
+ }
+
+} /* hexpcpy */
+
+
+
+void hmrgcpy( Byte huge * srcLineHPtr, Byte huge * dstLineHPtr, Integer dibWidth )
+/*----------*/
+/* if the is a 24-bit image, then the components are separated into scanlines
+ of red, green and blue. Merge into single scanline of 24-bit RGB pixels */
+{
+ Integer component;
+ Byte huge * insert;
+ Integer offset;
+
+ /* for each red, green, and blue component ... */
+ for (component = 2; component >= 0; component--)
+ {
+ /* adjust the insertion point */
+ insert = dstLineHPtr + component;
+
+ /* for each component byte in the scanline ... */
+ for (offset = 0; offset < dibWidth; offset++)
+ {
+ /* copy the component to the correct destination insertion point */
+ *insert = *srcLineHPtr++;
+
+ /* increment to the next insertion point */
+ insert += 3;
+ }
+ }
+
+
+} /* hmrgcpy */
+
+
+void hrlecpy256( Byte huge * srcHPtr, Byte huge * dstHPtr,
+ Integer dibWidth, DWord far * rleByteCount, Boolean writeDIB )
+/*----------*/
+/* 256 color DIB RLE compression. Provide source, destination pointers,
+ bytes in scanline. rleByteCount updated and write if writeDIB is TRUE */
+{
+ DWord rleCount;
+ Integer bytesLeft;
+ Byte compareByte;
+ Byte runLength;
+ Byte huge * startRun;
+
+ /* initialize rleCount */
+ rleCount = 0;
+
+ /* all bytes remain to be processed */
+ bytesLeft = dibWidth;
+
+ /* continue compressing until all bytes are processed */
+ while (bytesLeft)
+ {
+ /* save off the start of the run length */
+ startRun = srcHPtr;
+
+ /* read the first byte from the scanline */
+ compareByte = *srcHPtr++;
+ bytesLeft--;
+
+ /* initialize the runLength */
+ runLength = 1;
+
+ /* continue comparing bytes until no match results */
+ while (bytesLeft && (compareByte == *srcHPtr) && (runLength < 0xFF))
+ {
+ /* if a match was made, increment runLength and source pointer */
+ runLength++;
+ srcHPtr++;
+ bytesLeft--;
+ }
+
+ /* check if only two more bytes remain in scanline */
+ if ((runLength == 1) && (bytesLeft == 1))
+ {
+ if (writeDIB)
+ {
+ /* in this case, we have reached then end of the line with 2
+ non-repeating bytes - have to write out to runlengths of 1 */
+ *dstHPtr++ = 1;
+ *dstHPtr++ = compareByte;
+ *dstHPtr++ = 1;
+ *dstHPtr++ = *srcHPtr;
+ }
+
+ /* decrement the byte counter so that the main loop ends */
+ bytesLeft--;
+
+ /* byte count incremented by 4 bytes */
+ rleCount += 4;
+ }
+ /* check if we have a run length of 3 or more - also check bytesLeft
+ to make sure that we don't attempt to read past memory block */
+ else if ((runLength == 1) && (bytesLeft > 2) &&
+ (*srcHPtr != *(srcHPtr + 1)))
+ {
+ Boolean oddCount;
+
+ /* set the correct run length, and reset the source pointer */
+ srcHPtr += 2;
+ runLength = 3;
+ bytesLeft -= 2;
+
+ /* continue comparing until some bytes match up */
+ while (bytesLeft && (runLength < 0xFF))
+ {
+ /* make sure we don't try to read past end of scanline &&
+ compare to see if the bytes are the same */
+ if ((bytesLeft == 1) || (*srcHPtr != *(srcHPtr + 1)))
+ {
+ /* we will run past the end of scanline, add the byte */
+ /* if byte pair doesn't match, increment pointer and count */
+ srcHPtr++;
+ runLength++;
+ bytesLeft--;
+ }
+ else
+ {
+ /* if not at scanline end, or bytes match, bail */
+ break;
+ }
+ }
+
+ /* determine if there is an odd number of bytes to move */
+ oddCount = runLength & (Byte)0x01;
+
+ /* increment to total RLE byte count */
+ rleCount += 2 + runLength + (Byte)oddCount;
+
+ if (writeDIB)
+ {
+ /* write out the number of unique bytes */
+ *dstHPtr++ = 0;
+ *dstHPtr++ = runLength;
+
+ /* write out the individual bytes until runLength is exhausted */
+ while (runLength--)
+ {
+ /* copy to the destination from the starting point */
+ *dstHPtr++ = *startRun++;
+ }
+
+ /* add a null pad byte to align to word boundary */
+ if (oddCount)
+ {
+ *dstHPtr++ = 0;
+ }
+ }
+ }
+ else
+ {
+ if (writeDIB)
+ {
+ /* successful run length found - write to destination */
+ *dstHPtr++ = runLength;
+ *dstHPtr++ = compareByte;
+ }
+
+ /* increment the byte count */
+ rleCount += 2;
+ }
+ }
+
+ if (writeDIB)
+ {
+ /* write out an end of line marker */
+ *dstHPtr++ = 0;
+ *dstHPtr = 0;
+ }
+
+ /* increment total number of bytes */
+ rleCount += 2;
+
+ /* assign the value into the address provided */
+ *rleByteCount += rleCount;
+
+} /* hrlecpy256 */
+
+
+
+
+void hrlecpy16( Byte huge * srcHPtr, Byte huge * dstHPtr,
+ Integer dibWidth, DWord far * rleByteCount, Boolean writeDIB )
+/*----------*/
+/* 16 color DIB RLE compression. Provide source, destination pointers,
+ bytes in scanline. rleByteCount updated and write if writeDIB is TRUE */
+{
+ DWord rleCount;
+ Integer pixelsLeft;
+ Boolean oddStart;
+ Boolean look4Same;
+ Byte compareByte;
+ Byte runLength;
+ Byte huge * startRun;
+
+ /* initialize rleCount */
+ rleCount = 0;
+
+ /* all pixels left to process */
+ pixelsLeft = dibWidth;
+
+ /* continue compressing until all pixels are processed */
+ while (pixelsLeft)
+ {
+ /* save off the start of the run length */
+ startRun = srcHPtr;
+ oddStart = odd( pixelsLeft + dibWidth );
+
+ /* assume that we are comparing for equality, right now */
+ look4Same = TRUE;
+
+ /* read the next set of 2 pixels from the scanline */
+ if (oddStart)
+ {
+ /* odd offset: swap high and low pixels for byte-aligned compares */
+ compareByte = *srcHPtr++ & (Byte)0x0F;
+
+ /* make sure we can access the next byte - count > 1 */
+ if (pixelsLeft > 1)
+ {
+ compareByte |= *srcHPtr << 4;
+ }
+ }
+ else
+ {
+ /* otherwise, just save off the next full byte */
+ compareByte = *srcHPtr++;
+ }
+
+ /* check if we have 2 or less pixels remaining in the scanline */
+ if (pixelsLeft <= 2)
+ {
+ /* if only one pixel left ... */
+ if (pixelsLeft == 1)
+ {
+ /* zero out low-order nibble and set runLength */
+ compareByte &= (Byte)0xF0;
+ runLength = 1;
+ }
+ else
+ {
+ /* otherwize, just set the runLength */
+ runLength = 2;
+ }
+
+ /* no more pixels left */
+ pixelsLeft = 0;
+ }
+ /* otherwise, proceed with the normal comparison loop */
+ else
+ {
+ /* we have runLength of 2 pixels, so far */
+ runLength = 2;
+ pixelsLeft -= 2;
+
+ /* continue comparing bytes until no match results */
+ do
+ {
+ /* if comparing for equality ... */
+ if (look4Same)
+ {
+ Byte match;
+
+ /* XOR compare byte and the source pointer byte */
+ match = compareByte ^ *srcHPtr;
+
+ /* was there a full 2 pixel compare? */
+ if (match == 0)
+ {
+ /* is this the last pixel in the scanline, runlength
+ maximum reached, or nibbles swapped and begin of
+ pattern matching */
+ if ((pixelsLeft == 1) || (runLength + 1) == 0xFF ||
+ (oddStart && runLength == 2))
+ {
+ /* if this is the begin of pattern matching following an
+ odd start, then increment the source pointer */
+ if (oddStart && runLength == 2)
+ {
+ srcHPtr++;
+ }
+
+ /* only one pixel handled in this case */
+ runLength++;
+ pixelsLeft--;
+ }
+ else
+ {
+ /* otherwise, a full byte compared correctly - 2 nibbles */
+ runLength += 2;
+ pixelsLeft -= 2;
+ srcHPtr++;
+ }
+ }
+ /* if no full byte compare, determine if patial match */
+ else if ((runLength != 2) && ((match & (Byte)0xF0) == 0))
+ {
+ /* only high-order nibble matched - increment counts */
+ runLength++;
+ pixelsLeft--;
+
+ /* exit the loop */
+ break;
+ }
+ else if (runLength == 2)
+ {
+ /* no match on first compare - look for non-matches */
+ look4Same = FALSE;
+
+ /* increment source pointer - sets up byte alignment */
+ srcHPtr++;
+
+ /* setup for the runLength of differing pixels */
+ if (oddStart || (pixelsLeft == 1))
+ {
+ /* increment runLength and decrement pixels left */
+ runLength++;
+ pixelsLeft--;
+ }
+ else
+ {
+ /* there are at least 4 non-exact pixels in a row */
+ runLength = 4;
+ pixelsLeft -= 2;
+ }
+ }
+ else
+ {
+ /* really the end of the line - exit main loop */
+ break;
+ }
+ }
+ else /* if (look4Same == FALSE) */
+ {
+ /* make sure we don't try to read past end of scanline */
+ if ((pixelsLeft == 1) || ((runLength + 1) == 0xFF))
+ {
+ /* if running past end, then add this single nibble */
+ pixelsLeft--;
+ runLength++;
+ }
+ /* compare the next two bytes */
+ else if (pixelsLeft == 2 || (*srcHPtr != *(srcHPtr + 1)))
+ {
+ /* if byte pair doesn't match, increment pointer and count */
+ srcHPtr++;
+ runLength += 2;
+ pixelsLeft -= 2;
+ }
+ else
+ {
+ /* if not at scanline end, or bytes match, bail */
+ break;
+ }
+ }
+
+ /* continue while pixels are left and max runLength not exceeded */
+ } while (pixelsLeft && (runLength < 0xFF));
+ }
+
+ /* check what the runLength consists of - same or different pixels */
+ if (look4Same)
+ {
+ /* increment the rle compression count */
+ rleCount += 2;
+
+ if (writeDIB)
+ {
+ /* successful run length found - write to destination */
+ *dstHPtr++ = runLength;
+ *dstHPtr++ = compareByte;
+ }
+ }
+ else /* if (look4Same == FALSE) */
+ {
+ Boolean oddCount;
+
+ /* determine if there is an odd number of bytes to move */
+ oddCount = (((runLength & (Byte)0x03) == 1) ||
+ ((runLength & (Byte)0x03) == 2));
+
+ /* RLE byte count = 2 (setup) + word aligned BYTE count */
+ rleCount += 2 + ((runLength + 1) / 2) + (Byte)oddCount;
+
+ if (writeDIB)
+ {
+ /* write out the number of unique bytes */
+ *dstHPtr++ = 0;
+ *dstHPtr++ = runLength;
+
+ /* write out the individual bytes until runLength is exhausted */
+ while (runLength)
+ {
+ /* check if reading nibble at a time or byte */
+ if (oddStart)
+ {
+ /* have to read nibbles and create byte alignment */
+ *dstHPtr = (Byte)(*startRun++ << 4);
+ *dstHPtr++ |= (Byte)(*startRun >> 4);
+ }
+ else
+ {
+ /* byte alignment already set up */
+ *dstHPtr++ = *startRun++;
+ }
+
+ /* check if this is the last byte written */
+ if (runLength == 1)
+ {
+ /* if so, zero low-order nibble and prepare for loop exit */
+ *(dstHPtr - 1) &= (Byte)0xF0;
+ runLength--;
+ }
+ else
+ {
+ /* otherwise, 2 or more bytes remain, decrement counter */
+ runLength -= 2;
+ }
+ }
+
+ /* add a null pad byte to align to word boundary */
+ if (oddCount)
+ {
+ *dstHPtr++ = 0;
+ }
+ }
+ }
+ }
+
+ /* increment total number of bytes */
+ rleCount += 2;
+
+ if (writeDIB)
+ {
+ /* write out an end of line marker */
+ *dstHPtr++ = 0;
+ *dstHPtr = 0;
+ }
+
+ /* assign the value into the address provided */
+ *rleByteCount += rleCount;
+
+} /* hrlecpy16 */
+
+
+
+/****
+ *
+ * GdiEPSPreamble(PSBuf far* psbuf, Rect far *ps_bbox)
+ * Parse the EPS bounding box and output the GDI PostScript preamble.
+ * Assuming BBOX_LEFT, BBOX_TOP, BBOX_RIGHT and BBOX_BOTTOM are
+ * the corners of the EPS bounding box parsed from the input string,
+ * the GDI EPS preamble looks like:
+ *
+ * POSTSCRIPT_DATA
+ * /pp_save save def ...
+ * /pp_bx1 ps_bbox->left def /pp_by1 ps_bbox->top def
+ * /pp_bx2 ps_bbox->right def /pp_by2 ps_bbox->bottom def
+ * ...
+ * POSTSCRIPT_IGNORE FALSE
+ * SaveDC
+ * CreateBrush NULL_BRUSH
+ * SelectObject
+ * CreatePen PS_SOLID 0 (255,255,254)
+ * SelectObject
+ * SetROP1(R2_NOP)
+ * Rectangle( qd_bbox )
+ * DeleteObject
+ * RestoreDC
+ * POSTSCRIPT_IGNORE TRUE
+ *
+ * POSTSCRIPT_DATA
+ * pp_cx pp_cy moveto ...
+ * pp_tx pp_ty translate
+ * pp_sx pp_sy scale end
+ *
+ * The input buffer contains the length in bytes of the PostScript
+ * data in the first word followed by the data itself.
+ * The GDI clip region has already been set to the frame of the
+ * PostScript image in QuickDraw coordinates.
+ *
+ ****/
+static char gdi_ps1[] =
+ "%%MSEPS Preamble %d %d %d %d %d %d %d %d\r/pp_save save def\r\
+ /showpage {} def\r\
+ 40 dict begin /pp_clip false def /pp_bbox false def\r\
+ /F { pop } def /S {} def\r\
+ /B { { /pp_dy1 exch def /pp_dx1 exch def\r\
+ /pp_dy2 exch def /pp_dx2 exch def }\r\
+ stopped not { /pp_bbox true def } if } def\r\
+ /CB { { /pp_cy exch def /pp_cx exch def\r\
+ /pp_cht exch def /pp_cwd exch def }\r\
+ stopped not { /pp_clip true def } if } def\n\
+ /pp_bx1 %d def /pp_by1 %d def /pp_bx2 %d def /pp_by2 %d def\n";
+
+static char gdi_ps2[] =
+ "pp_clip\r\
+ { pp_cx pp_cy moveto pp_cwd 0 rlineto 0 pp_cht rlineto\r\
+ pp_cwd neg 0 rlineto clip newpath } if\r\
+ pp_bbox {\r\
+ /pp_dy2 pp_dy2 pp_dy1 add def\r\
+ /pp_dx2 pp_dx2 pp_dx1 add def\r\
+ /pp_sx pp_dx2 pp_dx1 sub pp_bx2 pp_bx1 sub div def\r\
+ /pp_sy pp_dy2 pp_dy1 sub pp_by1 pp_by2 sub div def\r\
+ /pp_tx pp_dx1 pp_sx pp_bx1 mul sub def\r\
+ /pp_ty pp_dy1 pp_sy pp_by2 mul sub def\r\
+ pp_tx pp_ty translate pp_sx pp_sy scale } if\r\
+ end\r";
+
+/*
+ * Note: these structures must be kept compatible with
+ * what the POSTSCRIPT_DATA Escape needs as input.
+ */
+static struct { Word length; char data[31]; } gdi_ps3 =
+ { 31, "%MSEPS Trailer\rpp_save restore\r" };
+
+void GdiEPSPreamble(Rect far* ps_bbox)
+{
+Word false = 0;
+Word true = 1;
+HPEN pen;
+Handle h;
+Word len;
+PSBuf far *tmpbuf;
+Rect far *qd_bbox = &gdiEnv.clipRect;
+
+ len = sizeof(gdi_ps1) + 100; // allow for expansion of %d
+ len = max(len, sizeof(gdi_ps2)); // find longest string
+ if ((h = GlobalAlloc(GHND, (DWORD) len + sizeof(PSBuf))) == 0)
+ {
+ ErSetGlobalError(ErMemoryFull); // allocation error
+ return;
+ }
+ tmpbuf = (PSBuf far *) GlobalLock(h);
+ wsprintf(tmpbuf->data, (LPSTR) gdi_ps1,
+ ps_bbox->left, ps_bbox->top, ps_bbox->right, ps_bbox->bottom,
+ qd_bbox->left, qd_bbox->top, qd_bbox->right, qd_bbox->bottom,
+ ps_bbox->left, ps_bbox->top, ps_bbox->right, ps_bbox->bottom);
+ tmpbuf->length = lstrlen(tmpbuf->data); // length of first string
+ GdiEPSData(tmpbuf); // output begin preamble
+ GdiEscape(POSTSCRIPT_IGNORE, sizeof(WORD), (StringLPtr) &false);
+ SaveDC(gdiEnv.metafile); // output GDI transform code
+ SelectObject(gdiEnv.metafile, GetStockObject(NULL_BRUSH));
+ pen = CreatePen(PS_SOLID, 0, RGB(255, 255, 254));
+ SelectObject(gdiEnv.metafile, pen);
+ SetROP2(gdiEnv.metafile, R2_NOP);
+ Rectangle(gdiEnv.metafile, qd_bbox->left, qd_bbox->top,
+ qd_bbox->right, qd_bbox->bottom);
+ DeleteObject(pen);
+ RestoreDC(gdiEnv.metafile, -1);
+ GdiEscape(POSTSCRIPT_IGNORE, sizeof(WORD), (StringLPtr) &true);
+ tmpbuf->length = sizeof(gdi_ps2) - 1;
+ lstrcpy(tmpbuf->data, gdi_ps2);
+ GdiEPSData(tmpbuf); // output transform preamble
+ GlobalUnlock(h); // clean up
+ GlobalFree(h);
+}
+
+void GdiEPSTrailer()
+{
+ Word false = 0;
+
+ GdiEscape(POSTSCRIPT_IGNORE, sizeof(WORD), (StringLPtr) &false);
+ GdiEPSData((PSBuf far *) &gdi_ps3);
+}
+
+/****
+ *
+ * GdiEPSData(PSBuf far* psbuf)
+ * Output PostScript data to GDI as POSTSCRIPT_DATA Escape
+ *
+ * notes:
+ * Currently, this routine does not do any buffering. It just outputs
+ * a separate POSTSCRIPT_DATA Escape each time it is called.
+ *
+ ****/
+void GdiEPSData(PSBuf far* psbuf)
+{
+ GdiEscape(POSTSCRIPT_DATA, psbuf->length + sizeof(WORD), (StringLPtr) psbuf);
+}
diff --git a/private/ole32/olecnv32/gdiprim.h b/private/ole32/olecnv32/gdiprim.h
new file mode 100644
index 000000000..e1a07d463
--- /dev/null
+++ b/private/ole32/olecnv32/gdiprim.h
@@ -0,0 +1,257 @@
+/****************************************************************************
+ Unit GdiPrim; Interface
+*****************************************************************************
+
+ The Gdi module is called directly by the QuickDraw (QD) module in order
+ to emit metafile primitives. It is responsible for accessing the current
+ CGrafPort structure in order to access the individual attribute settings.
+
+ It also supports the caching and redundant elimination of duplicate
+ elements when writing to the metafile.
+
+ Module Prefix: Gdi
+
+*****************************************************************************/
+
+/*--- states ---*/
+
+#define Changed 0
+#define Current 1
+
+/*--- state table offsets ---*/
+
+#define GdiPnPat 0x0001 /* fill patterns */
+#define GdiBkPat 0x0002
+#define GdiFillPat 0x0003
+#define GdiPnSize 0x0004 /* pen attribs */
+#define GdiPnMode 0x0005
+#define GdiFgColor 0x0006 /* foreground, background */
+#define GdiBkColor 0x0007
+#define GdiPnFgColor 0x000A
+#define GdiBkFgColor 0x000B
+#define GdiFillFgColor 0x000C
+#define GdiPnBkColor 0x000D
+#define GdiBkBkColor 0x000E
+#define GdiFillBkColor 0x000F
+#define GdiTxFont 0x0010 /* text attribs */
+#define GdiTxFace 0x0011
+#define GdiTxSize 0x0012
+#define GdiTxMode 0x0013
+#define GdiTxRatio 0x0014
+#define GdiChExtra 0x0015
+#define GdiSpExtra 0x0016
+#define GdiLineJustify 0x0017
+#define GdiNumAttrib 0x0018
+
+
+/*--- Action verbs ---*/
+
+typedef Integer GrafVerb;
+
+#define GdiFrame 0
+#define GdiPaint 1
+#define GdiErase 2
+#define GdiInvert 3
+#define GdiFill 4
+
+
+/*--- metafile comment ---*/
+
+#define PUBLIC 0xFFFFFFFF /* '....' public */
+#define POWERPOINT_OLD 0x5050FE54 /* 'PP.T' PowerPoint 2.0 */
+#define POWERPOINT 0x50504E54 /* 'PPNT' PowerPoint 3.0 */
+#define PRIVATE 0x512D3E47 /* 'Q->G' QD2GDI */
+#define SUPERPAINT 0x53504E54 /* 'SPNT' SuperPaint */
+
+#define PC_REGISTERED 0x8000 /* PowerPoint callback flag */
+
+#define QG_SIGNATURE "QuickDraw -> GDI"
+
+#define BEGIN_GROUP 0 /* public comments */
+#define END_GROUP 1
+#define CREATOR 4
+#define BEGIN_BANDING 6
+#define END_BANDING 7
+
+#define PP_VERSION 0x00 /* PowerPoint comments */
+#define PP_BFILEBLOCK 0x01
+#define PP_BEGINPICTURE 0x02
+#define PP_ENDPICTURE 0x03
+#define PP_DEVINFO 0x04
+#define PP_BEGINHYPEROBJ 0x05
+#define PP_ENDHYPEROBJ 0x06
+#define PP_BEGINFADE 0x07
+#define PP_ENDFADE 0x08
+
+#define PP_FONTNAME 0x11 /* GDI2QD round-trip */
+#define PP_HATCHPATTERN 0x12
+
+#define PP_BEGINCLIPREGION 0x40 /* clip regions from QD2GDI */
+#define PP_ENDCLIPREGION 0x41
+#define PP_BEGINTRANSPARENCY 0x42
+#define PP_ENDTRANSPARENCY 0x43
+#define PP_MASK 0x44
+#define PP_TRANSPARENTOBJ 0x45
+
+#define PP_MACPP2COLOR 0x80
+#define PP_WINGRAPH 0xAB
+
+
+typedef struct
+{
+ DWord signature;
+ Word function;
+ DWord size;
+
+} Comment, far * CommentLPtr;
+
+
+/*--- PostScript data buffer (POSTSCRIPT_DATA Escape) ---*/
+
+typedef struct psbuf
+{
+ Word length;
+ char data[1];
+} PSBuf;
+
+
+/*--- Conversion preferences ---*/
+
+#define GdiPrefOmit 0
+#define GdiPrefAbort 2
+
+typedef struct
+{
+ StringLPtr metafileName;
+ Byte penPatternAction;
+ Byte nonSquarePenAction;
+ Byte penModeAction;
+ Byte textModeAction;
+ Byte nonRectRegionAction;
+ Boolean optimizePP;
+ Byte noRLE;
+} ConvPrefs, far * ConvPrefsLPtr;
+
+
+/*--- Conversion results ---*/
+
+typedef struct
+{
+ HANDLE hmf; /* Global memory handle to the metafile */
+ RECT bbox; /* Tightly bounding rectangle in metafile units */
+ short inch; /* Length of an inch in metafile units */
+} PICTINFO, FAR * PictInfoLPtr;
+
+
+
+/*********************** Exported Function Definitions **********************/
+
+void GdiOffsetOrigin( Point delta );
+/* offset the current window origin and picture bounding box */
+
+
+void GdiLineTo( Point newPt );
+/* Emit line primitive with square endcaps */
+
+
+void GdiRectangle( GrafVerb verb, Rect rect );
+/* Emit rectangle primitive using action and dimensions parameters */
+
+
+void GdiRoundRect( GrafVerb verb, Rect rect, Point oval );
+/* Emit rounded rectangle primitive */
+
+
+void GdiOval( GrafVerb verb, Rect rect );
+/* Emit an oval primitive */
+
+
+void GdiArc( GrafVerb verb, Rect rect, Integer startAngle, Integer arcAngle );
+/* Emit an arc primitive */
+
+
+void GdiPolygon( GrafVerb verb, Handle poly );
+/* Emit polygon primitive */
+
+
+void GdiRegion( GrafVerb verb, Handle rgn );
+/* Emit region primitive */
+
+
+void GdiTextOut( StringLPtr string, Point location );
+/* draw the text at the location specified by location parameter. */
+
+
+void GdiStretchDIBits( PixMapLPtr pixMapLPtr, Handle pixDataHandle,
+ Rect src, Rect dst, Word mode, Handle mask );
+/* Draw a Windows device-independant bitmap */
+
+
+void GdiSelectClipRegion( RgnHandle rgn );
+/* Create a clipping rectangle or region using handle passed */
+
+
+void GdiHatchPattern( Integer hatchIndex );
+/* Use the hatch pattern index passed down to perform all ensuing fill
+ operations - 0-6 for a hatch value, -1 turns off the substitution */
+
+
+void GdiFontName( Byte fontFamily, Byte charSet, StringLPtr fontName );
+/* Set font characteristics based upno metafile comment from GDI2QD */
+
+
+void GdiShortComment( CommentLPtr cmt );
+/* Write public or private comment with no associated data */
+
+
+void GdiEscape( Integer function, Integer count, StringLPtr data);
+/* Write out a GDI Escape structure with no returned data */
+
+
+void GdiSetConversionPrefs( ConvPrefsLPtr convPrefs);
+/* Provide conversion preferences via global data block */
+
+
+void GdiOpenMetafile( void );
+/* Open metafile passed by GdiSetMetafileName() and perform any
+ initialization of the graphics state */
+
+
+void GdiSetBoundingBox( Rect bbox, Integer resolution );
+/* Set the overall picture size and picture resoulution in dpi */
+
+
+void GdiCloseMetafile( void );
+/* Close the metafile handle and end picture generation */
+
+
+void GdiGetConversionResults( PictInfoLPtr pictInfoLPtr );
+/* return results of the conversion */
+
+
+void GdiMarkAsChanged( Integer attribCode );
+/* indicate that the attribute passed in has changed */
+
+
+#ifdef WIN32
+int WINAPI EnumFontFunc( CONST LOGFONT *logFontLPtr, CONST TEXTMETRIC *tmLPtr,
+ DWORD fontType, LPARAM dataLPtr );
+#else
+int FAR PASCAL EnumFontFunc( LPLOGFONT logFontLPtr, LPTEXTMETRIC tmLPtr,
+ short fontType, LPSTR dataLPtr );
+#endif
+/* Callback function used to determine if a given font is available */
+
+void GdiSamePrimitive( Boolean same );
+/* indicate whether next primitive is the same or new */
+
+void GdiEPSPreamble(Rect far *);
+/* output GDI EPS filter PostScript preamble */
+
+void GdiEPSTrailer( void );
+/* output GDI EPS filter PostScript trailer */
+
+void GdiEPSData(PSBuf far*);
+/* output EPS PostScript data as GDI POSTSCRIPT_DATA Escape */
+
+
diff --git a/private/ole32/olecnv32/getdata.c b/private/ole32/olecnv32/getdata.c
new file mode 100644
index 000000000..50b99c155
--- /dev/null
+++ b/private/ole32/olecnv32/getdata.c
@@ -0,0 +1,932 @@
+
+/****************************************************************************
+ Unit GetData; Implementation
+*****************************************************************************
+
+ GetData implements the structured reading of the imput stream. As such, it
+ will handle the necessary byte-swapping that must occur when reading a
+ native Macintosh file.
+
+ Module Prefix: Get
+
+****************************************************************************/
+
+#include "headers.c"
+#pragma hdrstop
+
+#include <math.h> /* for abs() function */
+
+#include "getdata.h" /* own module interface */
+
+/*********************** Exported Data **************************************/
+
+
+/*********************** Private Data ***************************************/
+
+/*--- octochrome color tables --- */
+
+#define blackColor 33
+#define whiteColor 30
+#define redColor 205
+#define greenColor 341
+#define blueColor 409
+#define cyanColor 273
+#define magentaColor 137
+#define yellowColor 69
+
+typedef struct
+{
+ LongInt octochromeColor;
+ RGBColor rgbColor;
+} colorEntry, * colorEntryPtr;
+
+private colorEntry octochromeLookup[8] =
+{
+ { blackColor, RGB( 0x00, 0x00, 0x00 ) },
+ { whiteColor, RGB( 0xFF, 0xFF, 0xFF ) },
+ { redColor, RGB( 0xDD, 0x08, 0x06 ) },
+ { greenColor, RGB( 0x00, 0x80, 0x11 ) },
+ { blueColor, RGB( 0x00, 0x00, 0xD4 ) },
+ { cyanColor, RGB( 0x02, 0xAB, 0xEA ) },
+ { magentaColor, RGB( 0xF2, 0x08, 0x84 ) },
+ { yellowColor, RGB( 0xFC, 0xF3, 0x05 ) }
+};
+
+/*********************** Private Function Definitions ***********************/
+
+
+/*********************** Function Implementation ****************************/
+
+
+void GetWord( Word far * wordLPtr )
+/*==========*/
+/* Retrieves an 16-bit unsigned integer from the input stream */
+{
+ Byte far * byteLPtr = (Byte far *)wordLPtr;
+
+ /* this initialization should be here for win32 */
+ *wordLPtr = 0;
+
+ /* Assign high-order byte first, followed by low-order byte. */
+ GetByte( byteLPtr + 1);
+ GetByte( byteLPtr );
+} /* GetWord */
+
+
+void GetDWord( DWord far * dwordLPtr )
+/*===========*/
+/* Retrieves a 32-bit unsigned long from the input stream */
+{
+ Byte far * byteLPtr = (Byte far *)dwordLPtr;
+
+ * dwordLPtr = 0;
+ GetByte( byteLPtr + 3);
+ GetByte( byteLPtr + 2);
+ GetByte( byteLPtr + 1);
+ GetByte( byteLPtr );
+} /* GetDWord */
+
+#ifdef WIN32
+void GetPoint( Point * pointLPtr )
+/*===========*/
+/* Retrieves 2 2-byte words from the input stream and assign them
+ to a POINT structure */
+{
+ Word * wordLPtr = (Word *)pointLPtr;
+
+ GetWord( wordLPtr + 1 );
+ // This is done to extend the sign bit
+ *( wordLPtr + 1 ) = (short)(*( wordLPtr + 1 ));
+
+ GetWord( wordLPtr );
+ *( wordLPtr ) = (short)(*( wordLPtr ));
+} /* GetPoint */
+#endif
+
+#ifdef WIN32
+void GetCoordinate( Point * pointLPtr )
+/*===========*/
+/* Retrieves 2 2-byte words from the input stream and assign them
+ to a POINT structure. Currently, there is no difference between
+ this function and GetPoint. GetCoordinate is provided to provide for
+ future modifications. */
+{
+ Word * wordLPtr = (Word *)pointLPtr;
+
+ GetWord( wordLPtr + 1 );
+ // This is done to extend the sign bit
+ *( wordLPtr + 1 ) = (short)(*( wordLPtr + 1 ));
+
+ GetWord( wordLPtr );
+ *( wordLPtr ) = (short)(*( wordLPtr ));
+} /* GetCoordinate */
+#endif
+
+void GetBoolean( Boolean far * bool )
+/*=============*/
+/* Retrieves an 8-bit Mac boolean and coverts to 16-bit Windows Boolean */
+{
+ /* make sure that the high-order byte is zeroed out */
+ *bool = 0;
+
+ /* read low-order byte */
+ GetByte( (Byte far *)bool );
+
+} /* GetBoolean */
+
+
+void GetRect( Rect far * rect)
+/*==========*/
+/* Returns a RECT structure consisting of upper left and lower right
+ coordinate pair */
+{
+ Integer temp;
+ Point far * pointLPtr = (Point far *)rect;
+
+ /* Get the bounding coordinates */
+ GetCoordinate( pointLPtr++ );
+ GetCoordinate( pointLPtr );
+
+ /* Make sure that the rectangle coords are upper-left and lower-right */
+ if (rect->left > rect->right)
+ {
+ temp = rect->right;
+ rect->right = rect->left;
+ rect->left = temp;
+ }
+
+ if (rect->top > rect->bottom)
+ {
+ temp = rect->bottom;
+ rect->bottom = rect->top;
+ rect->top = temp;
+ }
+
+} /* GetRect */
+
+
+void GetString( StringLPtr stringLPtr )
+/*============*/
+/* Retrieves a Pascal-style string and formats it C-style. If the input
+ parameter is NIL, then the ensuing data is simply skipped */
+{
+ Byte dataLen;
+ Byte unusedByte;
+ Byte increment;
+ StringLPtr destLPtr;
+
+ /* Determine if we should be savin the text string or whether it simply
+ ends up in the bit bucket. Set the correct destination pointer and
+ increment value. */
+ if (stringLPtr == NIL)
+ {
+ destLPtr = &unusedByte;
+ increment = 0;
+ }
+ else
+ {
+ destLPtr = stringLPtr;
+ increment = 1;
+ }
+
+ /* Determine exactly how many bytes should be read. */
+ GetByte( &dataLen );
+
+ /* continue reading bytes as determined by length. */
+ while (dataLen--)
+ {
+ GetByte( destLPtr );
+ destLPtr += increment;
+ }
+
+ /* terminate string with NUL byte */
+ *destLPtr = 0;
+
+} /* GetString */
+
+
+void GetRGBColor( RGBColor far * rgbLPtr )
+/*==============*/
+/* Returns an RGB color */
+{
+ Word red;
+ Word green;
+ Word blue;
+
+ /* read successive components from the stream */
+ GetWord( &red );
+ GetWord( &green );
+ GetWord( &blue );
+
+ /* use RGB macro to create an RGBColor */
+ *rgbLPtr = RGB( red>>8, green>>8 , blue>>8 );
+
+} /* GetRGBColor */
+
+
+void GetOctochromeColor( RGBColor far * rgbLPtr )
+/*=====================*/
+/* Returns an RGB color - this will be converted from a PICT octochrome
+ color if this is a version 1 picture */
+{
+ LongInt color;
+ colorEntryPtr entry;
+
+ /* read in the LongInt octochrome color from the I/O stream */
+ GetDWord( &color );
+
+ /* search through the table, looking for the matching entry */
+ entry = octochromeLookup;
+ while (entry->octochromeColor != color)
+ {
+ entry++;
+ }
+ *rgbLPtr = entry->rgbColor;
+}
+
+
+Boolean GetPolygon( Handle far * polyHandleLPtr, Boolean check4Same )
+/*================*/
+/* Retrieves a polygon definition from the I/O stream and places in the
+ Handle passed down. If the handle is previously != NIL, then the
+ previous data is de-allocated.
+ If check4Same is TRUE, then the routine will compare the point list
+ against the previous polygon definition, checking for equality. If
+ pointlists match, then the routine returns TRUE, otherwise, it will
+ always return FALSE. Use this to merge fill and frame operations. */
+{
+ Handle newPolyH;
+ Word polySize;
+ Word far * polySizeLPtr;
+ Point far * polyPointsLPtr;
+ Boolean sameCoordinates;
+
+ /* the polygon coordinates are assumed to be different */
+ sameCoordinates = FALSE;
+
+ /* determine how large the polygon buffer should be. */
+ GetWord( &polySize );
+
+ /* allocate the necessary size for the polygon. */
+#ifdef WIN32
+ {
+ DWord dwSizeToAllocate;
+ Word uNumPoints;
+
+ uNumPoints = (polySize - sizeofMacWord) / sizeofMacPoint;
+ // a Word is needed to store polySize then POINT * uNumPoints
+ dwSizeToAllocate = sizeof( Word ) +
+ ( uNumPoints * sizeof ( Point ));
+
+ newPolyH = GlobalAlloc( GHND, (DWord)dwSizeToAllocate );
+ }
+#else
+ newPolyH = GlobalAlloc( GHND, (DWord)polySize );
+#endif
+
+ /* check to make sure that the allocation succeeded. */
+ if (newPolyH == NIL)
+ {
+ ErSetGlobalError( ErMemoryFull );
+ }
+ else
+ {
+ Boolean check4Closure;
+ Point far * firstPtLPtr;
+
+ /* Lock the memory handle and make sure it succeeds */
+ polySizeLPtr = (Word far *)GlobalLock( newPolyH );
+
+ /* save the size parameter and adjust the counter variables */
+ *polySizeLPtr = polySize;
+ polySize -= ( sizeofMacWord );
+ polyPointsLPtr = (Point far *)(polySizeLPtr + 1);
+
+ /* determine if we should check adjust first point to match last
+ point if they are within 1 metafile unit of oneanother. */
+ check4Closure = (polySize / sizeofMacPoint >= 6);
+ firstPtLPtr = polyPointsLPtr + 2;
+
+ /* continue reading points until the buffer is completely filled. */
+ while (polySize)
+ {
+ GetCoordinate( polyPointsLPtr++ );
+ polySize -= sizeofMacPoint;
+ }
+
+ /* should we check adjust for start, end points off by 1 unit? */
+ if (check4Closure)
+ {
+ Point first;
+ Point last;
+
+ /* get the first and last points */
+ first = *firstPtLPtr;
+ last = *(--polyPointsLPtr);
+
+ /* compare x and y components - see if delta in x or y < 1 */
+ if ((abs( first.x - last.x ) <= 1) &&
+ (abs( first.y - last.y ) <= 1))
+ {
+ /* if small delta, set last point equal to first point */
+ *polyPointsLPtr = first;
+ }
+ }
+
+ /* find out if the first and last point are within one metafile unit
+ of oneanother - close the polygon in this case */
+
+
+ /* determine if we should check against previous coordinates */
+ if (*polyHandleLPtr != NIL && check4Same)
+ {
+ Word far * checkSizeLPtr;
+ DWord far * checkDWordLPtr;
+ DWord far * polyDWordLPtr;
+
+ /* go back and see if the same set of coordinates was specified -
+ first check to see if the sizes are the same */
+ checkSizeLPtr = (Word far *)GlobalLock( *polyHandleLPtr );
+ if (*checkSizeLPtr == *polySizeLPtr)
+ {
+ /* reset the coordinate pointers to beginning of lists */
+ polyDWordLPtr = (DWord far *)(polySizeLPtr + 1);
+ checkDWordLPtr= (DWord far *)(checkSizeLPtr + 1);
+ polySize = *checkSizeLPtr - sizeofMacWord;
+
+ /* assume at this point that they are the same pointList */
+ sameCoordinates = TRUE;
+
+ /* continue check for equality until pointlist is exhausted */
+ while (polySize)
+ {
+ /* compare the two coordinate pairs */
+ if (*polyDWordLPtr++ != *checkDWordLPtr++)
+ {
+ /* if one of the coordinates mis-compares, bail */
+ sameCoordinates = FALSE;
+ break;
+ }
+ else
+ {
+ /* otherwise, decrement the count and continue */
+ polySize -= sizeofMacDWord;
+ }
+ }
+ }
+
+ /* unlock the previous polygon handle */
+ GlobalUnlock( *polyHandleLPtr );
+ }
+
+ /* unlock the handle before returning */
+ GlobalUnlock( newPolyH );
+ }
+
+ /* de-allocate the previous handle before continuing */
+ if (*polyHandleLPtr != NIL)
+ {
+ GlobalFree( *polyHandleLPtr );
+ }
+
+ /* assign the new polygon handle */
+ *polyHandleLPtr = newPolyH;
+
+ /* return whether coordinates were same or not */
+ return sameCoordinates;
+
+} /* GetPolygon */
+
+
+void GetRegion( Handle far * rgnHandleLPtr )
+/*=============*/
+/* Retrieves a region definition from the I/O stream and places in the
+ Handle passed down. If the handle is previously != NIL, then the
+ previous data is de-allocated. */
+{
+ Word rgnSize;
+ Word far * rgnDataLPtr;
+ Word far * rgnSizeLPtr;
+
+ /* de-allocate the previous handle before continuing */
+ if (*rgnHandleLPtr != NIL)
+ {
+ GlobalFree( *rgnHandleLPtr );
+ }
+
+ // buffer should have enough room for a RECT and a series of Word's
+ /* determine how large the region buffer should be. */
+ GetWord( &rgnSize );
+
+#ifdef WIN32
+ /* allocate the necessary size for the region. */
+ {
+ Word uSizeToAllocate;
+
+ uSizeToAllocate = (((rgnSize - sizeofMacRect) / sizeofMacWord)
+ * sizeof ( Word ))
+ + sizeof ( RECT );
+
+ *rgnHandleLPtr = GlobalAlloc( GHND, (DWord)uSizeToAllocate );
+ }
+#else
+ /* allocate the necessary size for the polygon. */
+ *rgnHandleLPtr = GlobalAlloc( GHND, (DWord)rgnSize );
+#endif
+
+ /* check to make sure that the allocation succeeded. */
+ if (*rgnHandleLPtr == NIL)
+ {
+ ErSetGlobalError( ErMemoryFull );
+ }
+ else
+ {
+ /* Lock the memory handle and make sure it succeeds */
+ rgnSizeLPtr = (Word far *)GlobalLock( *rgnHandleLPtr );
+ if (rgnSizeLPtr == NIL)
+ {
+ ErSetGlobalError( ErMemoryFail );
+ GlobalFree( *rgnHandleLPtr );
+ }
+ else
+ {
+ /* save the size parameter and adjust the counter variables */
+ *rgnSizeLPtr++ = rgnSize;
+ rgnSize -= sizeofMacWord;
+ rgnDataLPtr = (Word far *)rgnSizeLPtr;
+
+ /* read out the bounding box */
+ GetRect( (Rect far *)rgnDataLPtr );
+ rgnDataLPtr += sizeofMacRect / sizeofMacWord;
+ rgnSize -= sizeofMacRect;
+
+ /* continue reading Data until the buffer is completely filled. */
+ while (rgnSize)
+ {
+ /* read the next value from the source file */
+ GetWord( rgnDataLPtr++ );
+ rgnSize -= sizeofMacWord;
+ }
+
+ /* unlock the handle before returning */
+ GlobalUnlock( *rgnHandleLPtr );
+ }
+ }
+
+} /* GetRegion */
+
+
+void GetPattern( Pattern far * patLPtr )
+/*=============*/
+/* Returns a Pattern structure */
+{
+ Byte i;
+ Byte far * byteLPtr = (Byte far *)patLPtr;
+
+ for (i = 0; i < sizeof( Pattern); i++)
+ {
+ GetByte( byteLPtr++ );
+ }
+
+} /* GetPattern */
+
+
+
+void GetColorTable( Handle far * colorHandleLPtr )
+/*================*/
+{
+ ColorTable cTab;
+ LongInt bytesNeeded;
+ ColorTable far * colorHeaderLPtr;
+ RGBColor far * colorEntryLPtr;
+
+ /* read in the header information */
+ GetDWord( (DWord far *)&cTab.ctSeed );
+ GetWord( (Word far *)&cTab.ctFlags );
+ GetWord( (Word far *)&cTab.ctSize );
+
+ /* calculate the number of bytes needed for the color table */
+ bytesNeeded = sizeof( ColorTable ) + cTab.ctSize * sizeof( RGBColor );
+
+ /* adjust the size of the color table size by 1 */
+ cTab.ctSize++;
+
+ /* allocate the data block */
+ *colorHandleLPtr = GlobalAlloc( GHND, bytesNeeded );
+
+ /* flag global error if memory is not available */
+ if (*colorHandleLPtr == NULL)
+ {
+ ErSetGlobalError( ErMemoryFull );
+ }
+ else
+ {
+ /* lock the memory */
+ colorHeaderLPtr = (ColorTable far *)GlobalLock( *colorHandleLPtr );
+
+ /* copy over the color handle header */
+ *colorHeaderLPtr = cTab;
+
+ /* convert the pointer to a RGBQUAD pointer */
+ colorEntryLPtr = (RGBColor far *)colorHeaderLPtr->ctColors;
+
+ /* read in the color table entries */
+ while (cTab.ctSize--)
+ {
+ Word unusedValue;
+
+ /* read the value field */
+ GetWord( &unusedValue );
+
+ /* read the ensuing RGB color */
+ GetRGBColor( colorEntryLPtr++ );
+ }
+
+ /* Unlock the data once finished */
+ GlobalUnlock( *colorHandleLPtr );
+ }
+
+} /* GetColorTable */
+
+
+
+void GetPixPattern( PixPatLPtr pixPatLPtr )
+/*================*/
+/* Retrieves a Pixel Pattern structure. */
+{
+ /* release the memory from the patData field before continuing */
+ if (pixPatLPtr->patData != NULL)
+ {
+ GlobalFree( pixPatLPtr->patMap.pmTable );
+ GlobalFree( pixPatLPtr->patData );
+ pixPatLPtr->patData = NULL;
+ }
+
+ /* read the pattern type to determine how the data is organized */
+ GetWord( &pixPatLPtr->patType );
+ GetPattern( &pixPatLPtr->pat1Data );
+
+ /* read the additional data depending on the pattern type */
+ if (pixPatLPtr->patType == QDDitherPat)
+ {
+ /* if this is a rare dither pattern, save off the desired color */
+ GetRGBColor( &pixPatLPtr->patMap.pmReserved );
+ }
+ else /* (patType == newPat) */
+ {
+ /* read in the pixMap header and create a pixmap bitmap */
+ GetPixMap( &pixPatLPtr->patMap, TRUE );
+ GetColorTable( &pixPatLPtr->patMap.pmTable );
+ GetPixData( &pixPatLPtr->patMap, &pixPatLPtr->patData );
+ }
+
+} /* GetPixPattern */
+
+
+
+void GetPixMap( PixMapLPtr pixMapLPtr, Boolean forcePixMap )
+/*============*/
+/* Retrieves a Pixel Map from input stream */
+{
+ Boolean readPixelMap;
+
+ /* Read the rowBytes number and check the high-order bit. If set, it
+ is a pixel map containing multiple bits per pixel; if not, it is
+ a bitmap containing one bit per pixel */
+ GetWord( (Word far *)&pixMapLPtr->rowBytes );
+ readPixelMap = forcePixMap || ((pixMapLPtr->rowBytes & PixelMapBit) != 0);
+
+ /* read the bitmap's bounding rectangle */
+ GetRect( (Rect far *)&pixMapLPtr->bounds );
+
+ if (readPixelMap)
+ {
+ /* read the different data fields into the record structure */
+ GetWord( (Word far *)&pixMapLPtr->pmVersion );
+ GetWord( (Word far *)&pixMapLPtr->packType );
+ GetDWord( (DWord far *)&pixMapLPtr->packSize );
+ GetFixed( (Fixed far *)&pixMapLPtr->hRes );
+ GetFixed( (Fixed far *)&pixMapLPtr->vRes );
+ GetWord( (Word far *)&pixMapLPtr->pixelType );
+ GetWord( (Word far *)&pixMapLPtr->pixelSize );
+ GetWord( (Word far *)&pixMapLPtr->cmpCount );
+ GetWord( (Word far *)&pixMapLPtr->cmpSize );
+ GetDWord( (DWord far *)&pixMapLPtr->planeBytes );
+ GetDWord( (DWord far *)&pixMapLPtr->pmTable );
+ GetDWord( (DWord far *)&pixMapLPtr->pmReserved );
+ }
+ else
+ {
+ LongInt bytesNeeded;
+ ColorTable far * colorHeaderLPtr;
+
+ /* if this is a bitmap, then we assign the various fields. */
+ pixMapLPtr->pmVersion = 0;
+ pixMapLPtr->packType = 0;
+ pixMapLPtr->packSize = 0;
+ pixMapLPtr->hRes = 0x00480000;
+ pixMapLPtr->vRes = 0x00480000;
+ pixMapLPtr->pixelType = 0;
+ pixMapLPtr->pixelSize = 1;
+ pixMapLPtr->cmpCount = 1;
+ pixMapLPtr->cmpSize = 1;
+ pixMapLPtr->planeBytes = 0;
+ pixMapLPtr->pmTable = 0;
+ pixMapLPtr->pmReserved = 0;
+
+ /* calculate the number of bytes needed for the color table */
+ bytesNeeded = sizeof( ColorTable ) + sizeof( RGBColor );
+
+ /* allocate the data block */
+ pixMapLPtr->pmTable = GlobalAlloc( GHND, bytesNeeded );
+
+ /* make sure that the allocation was successfull */
+ if (pixMapLPtr->pmTable == NULL)
+ {
+ ErSetGlobalError( ErMemoryFull );
+ }
+ else
+ {
+ CGrafPortLPtr port;
+
+ /* Get the QuickDraw port for foreground and bkground colors */
+ QDGetPort( &port );
+
+ /* lock the memory handle and prepare to assign color table */
+ colorHeaderLPtr = (ColorTable far *)GlobalLock( pixMapLPtr->pmTable );
+
+ /* 2 colors are present - black and white */
+ colorHeaderLPtr->ctSize = 2;
+ colorHeaderLPtr->ctColors[0] = port->rgbFgColor;
+ colorHeaderLPtr->ctColors[1] = port->rgbBkColor;
+
+ /* unlock the memory */
+ GlobalUnlock( pixMapLPtr->pmTable );
+ }
+ }
+
+} /* GetPixMap */
+
+
+
+void GetPixData( PixMapLPtr pixMapLPtr, Handle far * pixDataHandle )
+/*=============*/
+/* Read a pixel map from the data stream */
+{
+ Integer rowBytes;
+ Integer linesToRead;
+ LongInt bitmapBytes;
+ Integer bytesPerLine;
+
+ /* determine the number of lines in the pixel map */
+ linesToRead = Height( pixMapLPtr->bounds );
+
+ /* make sure to turn off high-order bit - used to signify pixel map */
+ rowBytes = pixMapLPtr->rowBytes & RowBytesMask;
+
+ /* determine number of bytes to read for each line */
+ if (pixMapLPtr->pixelSize <= 16)
+ {
+ /* use the masked rowBytes value (adjusted for pixel maps) */
+ bytesPerLine = rowBytes;
+ }
+ else /* if (pixMapLPtr->pixelSize == 24) */
+ {
+ /* adjust for 32-bit pixel images that don't contain high-order byte */
+ bytesPerLine = rowBytes * 3 / 4;
+ }
+
+ /* calculate the size of the bitmap that will be created */
+ bitmapBytes = (LongInt)linesToRead * (LongInt)bytesPerLine;
+
+ /* allocate the necessary memory */
+ *pixDataHandle = GlobalAlloc( GHND, bitmapBytes );
+
+ /* flag global error if memory is not available */
+ if (*pixDataHandle == NULL)
+ {
+ ErSetGlobalError( ErMemoryFull );
+ }
+ else
+ {
+ Boolean compressed;
+ Boolean invertBits;
+ Boolean doubleByte;
+ Byte huge * rowHPtr;
+ Byte huge * insertHPtr;
+
+ /* lock the memory handle and get a pointer to the first byte */
+ rowHPtr = (Byte huge *)GlobalLock( *pixDataHandle );
+
+ /* determine if the bitmap is compressed or not */
+ compressed = !((rowBytes < 8) ||
+ (pixMapLPtr->packType == 1) ||
+ (pixMapLPtr->packType == 2));
+
+ /* determine if we should read 2 bytes at a time (16-bit pixelmap) */
+ doubleByte = (pixMapLPtr->packType == 3);
+
+ /* determine if bits should be inverted (monochrome bitmap) */
+ /* must test for high bit of Mac word set, sign is not propagated
+ when a Mac word is read into a 32-bit Windows int */
+ invertBits = ((short)pixMapLPtr->rowBytes > 0 );
+
+ /* decompress the bitmap into the global memory block */
+ while (linesToRead-- && (ErGetGlobalError() == NOERR))
+ {
+ Integer runLength;
+ Integer bytesRead;
+ Integer bytesToSkip;
+
+ /* see if we need to read the scanline runlength */
+ if (compressed)
+ {
+ /* get the run length - depends on the rowbytes field */
+ if (rowBytes > 250)
+ {
+ GetWord( (Word far *)&runLength );
+ }
+ else
+ {
+ runLength = 0;
+ GetByte( (Byte far *)&runLength );
+ }
+ }
+ else
+ {
+ /* if not compressed, runLength is equal to rowBytes */
+ runLength = bytesPerLine;
+ }
+
+ /* set the next insertion point to the beginning of the scan line */
+ insertHPtr = rowHPtr;
+
+ /* if this is a 24-bit image that contains 32-bits of information,
+ then we must skip the high-order byte component. This byte was
+ originally spec'ed by Apple as a luminosity component, but is
+ unused in Windows 24-bit DIBs. */
+ bytesToSkip = (pixMapLPtr->cmpCount == 4) ? (rowBytes / 4) : 0;
+
+ /* continue decompressing until run-length is exhausted */
+ for (bytesRead = 0; bytesRead < runLength; )
+ {
+ SignedByte tempRepeatCount = 0;
+ Integer repeatCount;
+
+ /* check on how the data should be read */
+ if (compressed)
+ {
+ /* if compressed, get the repeat count byte */
+ GetByte( (Byte far *)&tempRepeatCount );
+ bytesRead++;
+ }
+ else
+ {
+ /* if no compression, fake the count of bytes to follow */
+ tempRepeatCount = 0;
+ }
+
+ /* make sure that we didn't read a byte used to word-align */
+ if (bytesRead == runLength)
+ {
+ /* this should force the read loop to be exited */
+ continue;
+ }
+
+ /* if less than 0, indicates repeat count of following byte */
+ if (tempRepeatCount < 0)
+ {
+ /* check for a flag-counter value of -128 (0x80) - QuickDraw
+ will never create this, but another application that packs
+ bits may. As noted in the January 1992 release of TechNote
+ #171, we need to ignore this value and use the next byte
+ as the flag-counter byte. */
+ if (tempRepeatCount != -128)
+ {
+ Byte repeatByte1;
+ Byte repeatByte2;
+
+ /* calculate the repeat count and retrieve repeat byte */
+ repeatCount = 1 - (Integer)tempRepeatCount;
+ GetByte( &repeatByte1 );
+
+ /* increment the number of bytes read */
+ bytesRead++;
+
+ /* check for special handling cases */
+ if (invertBits)
+ {
+ /* if this is a monochrome bitmap, then invert bits */
+ repeatByte1 ^= (Byte)0xFF;
+ }
+ else if (doubleByte)
+ {
+ /* 16-bit images (pixel chunks) - read second byte */
+ GetByte( &repeatByte2 );
+
+ /* and increment byte count */
+ bytesRead++;
+ }
+
+ /* continue stuffing byte until repeat count exhausted */
+ while (repeatCount--)
+ {
+ /* check if we are skipping the luminosity byte for
+ 32-bit images (this isn't used in Windows DIBs) */
+ if (bytesToSkip)
+ {
+ bytesToSkip--;
+ }
+ else
+ {
+ /* insert new Byte */
+ *insertHPtr++ = repeatByte1;
+ }
+
+ /* check if second repeat byte needs to be inserted */
+ if (doubleByte)
+ {
+ *insertHPtr++ = repeatByte2;
+ }
+ }
+ }
+ }
+ else /* if (tempRepeatCount >= 0) */
+ {
+ /* adjust the number of bytes that will be transferred */
+ if (compressed)
+ {
+ /* if greater than 0, is number of bytes that follow */
+ repeatCount = 1 + (Integer)tempRepeatCount;
+
+ /* double the number of bytes if 16-bit pixelmap */
+ if (doubleByte)
+ {
+ repeatCount *= 2;
+ }
+ }
+ else
+ {
+ /* the number of bytes to read = bytesPerLine */
+ repeatCount = bytesPerLine;
+ }
+
+ /* increment the number of bytes read */
+ bytesRead += repeatCount;
+
+ /* check if iversion is required */
+ if (invertBits)
+ {
+ /* if this is a monochrome bitmap, then invert bits */
+ while (repeatCount--)
+ {
+ GetByte( insertHPtr );
+ *insertHPtr++ ^= (Byte)0xFF;
+ }
+ }
+ else
+ {
+ /* continue reading bytes into the insert point */
+ while (repeatCount--)
+ {
+ /* check if we are skipping the luminosity byte for
+ 32-bit images (this isn't used in Windows DIBs) */
+ if (bytesToSkip)
+ {
+ /* pass the current insertion pointer, but don't
+ increment (overwritten in ensuing read). */
+ bytesToSkip--;
+ GetByte( insertHPtr );
+ }
+ else
+ {
+ GetByte( insertHPtr++ );
+ }
+ }
+ }
+ }
+ }
+
+ /* increment the line pointer to the next scan line */
+ rowHPtr += bytesPerLine;
+
+ /* call IO module to update current read position */
+ IOUpdateStatus();
+ }
+
+ /* Unlock the data block */
+ GlobalUnlock( *pixDataHandle );
+
+ /* if an error occured, make sure to remove the data block */
+ if (ErGetGlobalError() != NOERR)
+ {
+ GlobalFree( *pixDataHandle );
+ }
+ }
+
+} /* GetPixData */
+
+
+/******************************* Private Routines ***************************/
+
+
diff --git a/private/ole32/olecnv32/getdata.h b/private/ole32/olecnv32/getdata.h
new file mode 100644
index 000000000..de7456eb7
--- /dev/null
+++ b/private/ole32/olecnv32/getdata.h
@@ -0,0 +1,109 @@
+
+/****************************************************************************
+ Unit GetData; Interface
+*****************************************************************************
+
+ GetData implements the structured reading of the imput stream. As such, it
+ will handle the necessary byte-swapping that must occur when reading a
+ native Macintosh file. It will also perform some data validation and
+ perform limited coordinate transformations on the input data.
+
+ Module Prefix: Get
+
+*****************************************************************************/
+
+/*********************** Exported Function Definitions **********************/
+
+#define /* void */ GetByte( /* Byte far * */ byteLPtr ) \
+/* Retrieves an 8-bit unsigned byte from the input stream */ \
+IOGetByte( byteLPtr )
+
+
+void GetWord( Word far * wordLPtr );
+/* Clears destination then retrieves an 16-bit unsigned integer from the input
+ stream */
+
+
+void GetDWord( DWord far * dwordLPtr );
+/* Retrieves a 32-bit unsigned long from the input stream */
+
+
+void GetBoolean( Boolean far * bool );
+/* Retrieves an 8-bit Mac boolean and coverts to 16-bit Windows Boolean */
+
+
+#define /* void */ GetFixed( /* Fixed far * */ fixedLPtr ) \
+/* Retrieved a fixed point number consisting of 16-bit whole \
+ and 16-bit fraction */ \
+GetDWord( (DWord far *)fixedLPtr )
+
+/* Retrieves POINT structure without coordinate transforms */
+#ifdef WIN32
+void GetPoint( Point * pointLPtr );
+#else
+#define /* void */ GetPoint( /* Point far * */ pointLPtr ) \
+/* Retrieves POINT structure without coordinate transforms */ \
+GetDWord( (DWord far *)pointLPtr )
+#endif
+
+#ifdef WIN32
+void GetCoordinate( Point * pointLPtr );
+#else
+#define /* void */ GetCoordinate( /* Point far * */ pointLPtr ) \
+/* Retrieves POINT structure without coordinte transforms */ \
+GetDWord( (DWord far *)pointLPtr )
+#endif
+
+
+void GetRect( Rect far * rect);
+/* Returns a RECT structure consisting of upper left and lower right
+ coordinate pair */
+
+
+void GetString( StringLPtr stringLPtr );
+/* Retrieves a Pascal-style string and formats it C-style. If the input
+ parameter is NIL, then the ensuing data is simply skipped */
+
+
+void GetRGBColor( RGBColor far * rgbLPtr );
+/* Returns an RGB color */
+
+
+void GetOctochromeColor( RGBColor far * rgbLPtr );
+/* Returns an RGB color - this will be converted from a PICT octochrome
+ color if this is a version 1 picture */
+
+
+Boolean GetPolygon( Handle far * polyHandleLPtr, Boolean check4Same );
+/* Retrieves a polygon definition from the I/O stream and places in the
+ Handle passed down. If the handle is previously != NIL, then the
+ previous data is de-allocated.
+ If check4Same is TRUE, then the routine will compare the point list
+ against the previous polygon definition, checking for equality. If
+ pointlists match, then the routine returns TRUE, otherwise, it will
+ always return FALSE. Use this to merge fill and frame operations. */
+
+
+void GetRegion( Handle far * rgnHandleLPtr );
+/* Retrieves a region definition from the I/O stream and places in the
+ Handle passed down. If the handle is previously != NIL, then the
+ previous data is de-allocated. */
+
+
+void GetPattern( Pattern far * patLPtr );
+/* Returns a Pattern structure */
+
+
+void GetColorTable( Handle far * colorHandleLPtr );
+
+
+void GetPixPattern( PixPatLPtr pixPatLPtr );
+/* Retrieves a Pixel Pattern structure. */
+
+
+void GetPixMap( PixMapLPtr pixMapLPtr, Boolean forcePixMap );
+/* Retrieves a Pixel Map from input stream */
+
+
+void GetPixData( PixMapLPtr pixMapLPtr, Handle far * pixDataHandle );
+/* Read a pixel map from the data stream */
diff --git a/private/ole32/olecnv32/headers.c b/private/ole32/olecnv32/headers.c
new file mode 100644
index 000000000..c0146910a
--- /dev/null
+++ b/private/ole32/olecnv32/headers.c
@@ -0,0 +1,29 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994 - 1994.
+//
+// File: headers.c
+//
+// Contents: Precompiled header for olecnv32.dll
+//
+// History: 28-Mar-94 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#undef UNICODE
+#undef _UNICODE
+
+
+//
+// Prevent lego errors under Chicago.
+//
+#if defined(_CHICAGO_)
+#define _CTYPE_DISABLE_MACROS
+#endif
+
+#include "toolbox.h" /* the underlying toolbox environment */
+#include "error.h" /* for error codes */
+#include "quickdrw.h" /* for some typedefs */
+#include "bufio.h"
+#include "gdiprim.h"
diff --git a/private/ole32/olecnv32/olecnv32.rc b/private/ole32/olecnv32/olecnv32.rc
new file mode 100644
index 000000000..948b3f3a2
--- /dev/null
+++ b/private/ole32/olecnv32/olecnv32.rc
@@ -0,0 +1,13 @@
+#include <windows.h>
+//
+// Version resources
+//
+#include <ntverp.h>
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Microsoft OLE for Windows and Windows NT"
+#define VER_INTERNALNAME_STR "OLECNV32.DLL"
+#define VER_ORIGINALFILENAME_STR "OLECNV32.DLL"
+#include <common.ver>
+
+
diff --git a/private/ole32/olecnv32/qd2gdi.h b/private/ole32/olecnv32/qd2gdi.h
new file mode 100644
index 000000000..c497b786e
--- /dev/null
+++ b/private/ole32/olecnv32/qd2gdi.h
@@ -0,0 +1,181 @@
+
+/****************************************************************************
+
+ QuickDraw PICT Import Filter
+
+*****************************************************************************
+
+ This file contains the interface for the QuickDraw import filter
+ that reads Mac pictures from disk and/or memory. In addition to the
+ Aldus filter interface, it also supports a parameterized interface
+ for Microsoft applications to control some conversion results.
+
+****************************************************************************/
+
+/*--- Possible Aldus-defined error code returns ---*/
+
+#define NOERR 0 // Conversion succeeded
+
+#define IE_NOT_MY_FILE 5301 // Invalid version (not version 1 or 2 PICT)
+ // Invalid QD2GDI structure version (greater than 2)
+ // Ill-formed PICT header record sequence
+
+#define IE_TOO_BIG 5302 // Image extents exceed 32K
+
+#define IE_BAD_FILE_DATA 5309 // Image bounding box is empty
+ // Attempt to read past end of picture
+ // Corrupted input file
+ // Zero-length record
+
+#define IE_IMPORT_ABORT 5310 // Opening of source image failed
+ // Read failure (network failure, floppy popped)
+ // Most I/O errors
+
+#define IE_MEM_FULL 5311 // CreateMetaFile() failure
+ // CloseMetaFile() failure
+ // Unable to allocate memory (out of memory)
+
+#define IE_MEM_FAIL 5315 // Handle lock failure
+
+#define IE_NOPICTURES 5317 // Empty bounding rectangle or nothing drawn
+
+#define IE_UNSUPP_VERSION 5342 // User-defined abort performed
+
+
+/*--- Aldus-defined file access block ---*/
+
+typedef DWORD FILETYPE;
+
+typedef struct
+{
+ unsigned slippery : 1; /* TRUE if file may disappear. */
+ unsigned write : 1; /* TRUE if open for write. */
+ unsigned unnamed : 1; /* TRUE if unnamed. */
+ unsigned linked : 1; /* Linked to an FS FCB. */
+ unsigned mark : 1; /* Generic mark bit. */
+ FILETYPE fType; /* The file type. */
+#define IBMFNSIZE 124
+ short handle; /* MS-DOS open file handle. */
+ char fullName[IBMFNSIZE]; /* Device, path, file names. */
+ DWORD filePos; /* Our current file posn. */
+} FILESPEC, FAR *LPFILESPEC;
+
+
+/*--- Aldus-defined picture info structure ---*/
+
+typedef struct {
+ HANDLE hmf; /* Global memory handle to the metafile */
+ RECT bbox; /* Tightly bounding rectangle in metafile units */
+ DC inch; /* Length of an inch in metafile units */
+} PICTINFO;
+
+/*--- Preferences memory block ---*/
+
+typedef struct /* "old" version 1 USERPREFS */
+{
+ char signature[6];
+ WORD version;
+ LPSTR sourceFilename;
+ HANDLE sourceHandle;
+ LPSTR destinationFilename;
+ BYTE penPatternAction;
+ BYTE nonSquarePenAction;
+ BYTE penModeAction;
+ BYTE textModeAction;
+ BYTE charLock;
+ BYTE nonRectRegionAction;
+ BOOL PICTinComment;
+ BOOL optimizePP;
+ WORD lineClipWidthThreshold;
+ WORD reserved[6];
+} USERPREFS_V1, FAR *LPUSERPREFS_V1;
+
+
+typedef struct /* current version 3 USERPREFS */
+{
+ char signature[6];
+ WORD version;
+ WORD size;
+ LPSTR sourceFilename;
+ HANDLE sourceHandle;
+ LPSTR destinationFilename;
+ BYTE penPatternAction;
+ BYTE nonSquarePenAction;
+ BYTE penModeAction;
+ BYTE textModeAction;
+ BYTE nonRectRegionAction;
+ BOOL optimizePP;
+ BYTE noRLE; // new (split out from reserved[0] in version 3)
+ BYTE reservedByte; // rest of first reserved word
+ WORD reserved[5];
+
+} USERPREFS, FAR * LPUSERPREFS;
+
+
+/*********************** Exported Function Definitions **********************/
+
+#ifdef WIN32
+int WINAPI GetFilterInfo( short PM_Version, LPSTR lpIni,
+ HANDLE FAR * lphPrefMem,
+ HANDLE FAR * lphFileTypes );
+#else
+int FAR PASCAL GetFilterInfo( short PM_Version, LPSTR lpIni,
+ HANDLE FAR * lphPrefMem,
+ HANDLE FAR * lphFileTypes );
+#endif
+/* Returns information about this filter.
+ Input parameters are PM_Version which is the filter interface version#
+ and lpIni which is a copy of the win.ini entry
+ Output parameters are lphPrefMem which is a handle to moveable global
+ memory which will be allocated and initialized.
+ lphFileTypes is a structure that contains the file types
+ that this filter can import. (For MAC only)
+ This routine should be called once, just before the filter is to be used
+ the first time. */
+
+
+#ifdef WIN32
+void WINAPI GetFilterPref( HANDLE hInst, HANDLE hWnd, HANDLE hPrefMem, WORD wFlags );
+#else
+void FAR PASCAL GetFilterPref( HANDLE hInst, HANDLE hWnd, HANDLE hPrefMem, WORD wFlags );
+#endif
+/* Input parameters are hInst (in order to access resources), hWnd (to
+ allow the DLL to display a dialog box), and hPrefMem (memory allocated
+ in the GetFilterInfo() entry point). WFlags is currently unused, but
+ should be set to 1 for Aldus' compatability */
+
+
+#ifdef WIN32
+short WINAPI ImportGR( HDC hdcPrint, LPFILESPEC lpFileSpec,
+ PICTINFO FAR * lpPict, HANDLE hPrefMem );
+#else
+short FAR PASCAL ImportGR( HDC hdcPrint, LPFILESPEC lpFileSpec,
+ PICTINFO FAR * lpPict, HANDLE hPrefMem );
+#endif
+/* Import the metafile in the file indicated by the lpFileSpec. The
+ metafile generated will be returned in lpPict. */
+
+
+#ifdef WIN32
+short WINAPI ImportEmbeddedGr( HDC hdcPrint, LPFILESPEC lpFileSpec,
+ PICTINFO FAR * lpPict, HANDLE hPrefMem,
+ DWORD dwSize, LPSTR lpMetafileName );
+#else
+short FAR PASCAL ImportEmbeddedGr( HDC hdcPrint, LPFILESPEC lpFileSpec,
+ PICTINFO FAR * lpPict, HANDLE hPrefMem,
+ DWORD dwSize, LPSTR lpMetafileName );
+#endif
+/* Import the metafile in using the previously opened file handle in
+ the structure field lpFileSpec->handle. Reading begins at offset
+ lpFileSpect->filePos, and the convertor will NOT expect to find the
+ 512 byte PICT header. The metafile generated will be returned in
+ lpPict and can be specified via lpMetafileName (NIL = memory metafile,
+ otherwise, fully qualified filename. */
+
+#ifdef WIN32
+short WINAPI QD2GDI( LPUSERPREFS lpPrefMem, PICTINFO FAR * lpPict );
+#else
+short FAR PASCAL QD2GDI( LPUSERPREFS lpPrefMem, PICTINFO FAR * lpPict );
+#endif
+/* Import the metafile as specified using the parameters supplied in the
+ lpPrefMem. The metafile will be returned in lpPict. */
diff --git a/private/ole32/olecnv32/qdcoment.i b/private/ole32/olecnv32/qdcoment.i
new file mode 100644
index 000000000..36aabd326
--- /dev/null
+++ b/private/ole32/olecnv32/qdcoment.i
@@ -0,0 +1,62 @@
+/*
+ PICTcomments.h -- QuickDraw picture comment symbolic names
+*/
+
+#ifndef __PICTCOMMENTS__
+
+#define picLParen 0 /* Archaic grouping command (see IM I-159) */
+#define picRParen 1 /* Ends group begun by picRParen */
+#define picAppComment 100 /* Application-specific comment */
+#define picDwgBeg 130 /* Begin MacDraw picture */
+#define picDwgEnd 131 /* End MacDraw picture */
+#define picGrpBeg 140 /* Begin grouped objects */
+#define picGrpEnd 141 /* End grouped objects */
+#define picBitBeg 142 /* Begin series of bitmap bands */
+#define picBitEnd 143 /* End of bitmap bands */
+#define picTextBegin 150 /* Beginning of a text string */
+#define picTextEnd 151 /* End of text string */
+#define picStringBegin 152 /* Beginning of banded string */
+#define picStringEnd 153 /* End of banded string */
+#define picTextCenter 154 /* Center of rotation to picTextBegin */
+#define picLineLayoutOff 155 /* Turns off line layout */
+#define picLineLayoutOn 156 /* Turns on line layout */
+#define picLineLayout 157 /* Specify line layout for next text call */
+#define picPolyBegin 160 /* Following LineTo() operations are part of a polygon */
+#define picPolyEnd 161 /* End of special MacDraw polygon */
+#define picPlyByt 162 /* Following data part of freehand curve */
+#define picPolyIgnore 163 /* Ignore the following polygon */
+#define picPolySmooth 164 /* Close, fill, frame a polygon */
+#define picPlyClose 165 /* MacDraw polygon is closed */
+#define picArrw1 170 /* One arrow from point1 to point2 */
+#define picArrw2 171 /* One arrow from point2 to point1 */
+#define picArrw3 172 /* Two arrows, one on each end of a line */
+#define picArrwEnd 173 /* End of arrow comment */
+#define picDashedLine 180 /* Subsequent lines are PostScript dashed lines */
+#define picDashedStop 181 /* Ends picDashedLine comment */
+#define picSetLineWidth 182 /* Mult. fraction for pen size */
+#define picPostScriptBegin 190 /* Saves QD state; and send PostScript */
+#define picPostScriptEnd 191 /* Restore QD state */
+#define picPostScriptHandle 192 /* Remaining data is PostScript */
+#define picPostScriptFile 193 /* Use filename to send 'POST' resources */
+#define picTextIsPostScript 194 /* QD text is PostScript until picPostScriptEnd */
+#define picResourcePS 195 /* Send PostScript from 'STR ' or 'STR#' resources */
+#define picNewPostScriptBegin 196 /* Like picPostScriptBegin */
+#define picSetGrayLevel 197 /* Set gray level from fixed-point number */
+#define picRotateBegin 200 /* Begin rotation of the coordinate plane */
+#define picRotateEnd 201 /* End rotated plane */
+#define picRotateCenter 202 /* Specifies center of rotation */
+#define picFormsPrinting 210 /* DonÕt flush print buffer after each page */
+#define picEndFormsPrinting 211 /* Ends forms printing */
+#define picAutoNap 214 /* used by MacDraw II */
+#define picAutoWake 215 /* used by MacDraw II */
+#define picManNap 216 /* used by MacDraw II */
+#define picManWake 217 /* used by MacDraw II */
+#define picCreator 498 /* File creator for application */
+#define picPICTScale 499 /* Scaling of image */
+#define picBegBitmapThin 1000 /* Begin bitmap thinning */
+#define picEndBitmapThin 1001 /* End bitmap thinning */
+#define picLasso 12345 /* Image in the scrap created using lasso */
+
+#define __PICTCOMMENTS__
+#endif
+ \ No newline at end of file
diff --git a/private/ole32/olecnv32/qdopcode.i b/private/ole32/olecnv32/qdopcode.i
new file mode 100644
index 000000000..652e9dfe0
--- /dev/null
+++ b/private/ole32/olecnv32/qdopcode.i
@@ -0,0 +1,252 @@
+/* PICT opcodes */
+/* ________________________________________________________________________ */
+/* Name Opcode Description Data Size */
+/* (in bytes) */
+#define NOP 0x0000 /* nop 0 */
+#define Clip 0x0001 /* clip region size */
+#define BkPat 0x0002 /* background pattern 8 */
+#define TxFont 0x0003 /* text font (word) 2 */
+#define TxFace 0x0004 /* text face (byte) 1 */
+#define TxMode 0x0005 /* text mode (word) 2 */
+#define SpExtra 0x0006 /* space extra (fixed point) 4 */
+#define PnSize 0x0007 /* pen size (point) 4 */
+#define PnMode 0x0008 /* pen mode (word) 2 */
+#define PnPat 0x0009 /* pen pattern 8 */
+#define FillPat 0x000A /* fill pattern 8 */
+#define OvSize 0x000B /* oval size (point) 4 */
+#define Origin 0x000C /* dh, dv (word) 4 */
+#define TxSize 0x000D /* text size (word) 2 */
+#define FgColor 0x000E /* foreground color (long) 4 */
+#define BkColor 0x000F /* background color (long) 4 */
+#define TxRatio 0x0010 /* numer (point), denom (point) 8 */
+#define Version 0x0011 /* version (byte) 1 */
+#define BkPixPat 0x0012 /* color background pattern variable: */
+ /* see Table 4 */
+#define PnPixPat 0x0013 /* color pen pattern variable: */
+ /* see Table 4 */
+#define FillPixPat 0x0014 /* color fill pattern variable: */
+ /* see Table 4 */
+#define PnLocHFrac 0x0015 /* fractional pen position 2 */
+#define ChExtra 0x0016 /* extra for each character 2 */
+ /* reserved 0x0017 /* opcode 0 */
+ /* reserved 0x0018 /* opcode 0 */
+ /* reserved 0x0019 /* opcode 0 */
+#define RGBFgCol 0x001A /* RGB foreColor variable: */
+ /* see Table 4 */
+#define RGBBkCol 0x001B /* RGB backColor variable: */
+ /* see Table 4 */
+#define HiliteMode 0x001C /* hilite mode flag 0 */
+#define HiliteColor 0x001D /* RGB hilite color variable: */
+ /* see Table 4 */
+#define DefHilite 0x001E /* Use default hilite color 0 */
+#define OpColor 0x001F /* RGB OpColor for variable: */
+ /* arithmetic modes see Table 4 */
+#define Line 0x0020 /* pnLoc (point), newPt (point) 8 */
+#define LineFrom 0x0021 /* newPt (point) 4 */
+#define ShortLine 0x0022 /* pnLoc (point, dh, dv 6 */
+ /* (-128..127) */
+#define ShortLineFrom 0x0023 /* dh, dv (-128..127) 2 */
+ /* reserved 0x0024 /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+ /* reserved 0x0025 /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+ /* reserved 0x0026 /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+ /* reserved 0x0027 /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+#define LongText 0x0028 /* txLoc (point), count 5 + text */
+ /* (0..255), text */
+#define DHText 0x0029 /* dh (0..255), count 2 + text */
+ /* (0..255), text */
+#define DVText 0x002A /* dv (0..255), count 2 + text */
+ /* (0..255), text */
+#define DHDVText 0x002B /* dh, dv (0..255), count 3 + text */
+ /* (0..255), text */
+#define FontName 0x002C /* opcode + length (word) + old 2 + data */
+ /* font ID (word) + name length */
+ /* length (byte) + font name */
+#define LineJustify 0x002D /* opcode + length (word) + 2 + data */
+ /* interchar spacing (fixed) + length */
+ /* total extra space (fixed) */
+ /* reserved 0x002E /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+ /* reserved 0x002F /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+#define frameRect 0x0030 /* rect 8 */
+#define paintRect 0x0031 /* rect 8 */
+#define eraseRect 0x0032 /* rect 8 */
+#define invertRect 0x0033 /* rect 8 */
+#define fillRect 0x0034 /* rect 8 */
+ /* reserved 0x0035 /* opcode + 8 bytes data 8 */
+ /* reserved 0x0036 /* opcode + 8 bytes data 8 */
+ /* reserved 0x0037 /* opcode + 8 bytes data 8 */
+#define frameSameRect 0x0038 /* rect 0 */
+#define paintSameRect 0x0039 /* rect 0 */
+#define eraseSameRect 0x003A /* rect 0 */
+#define invertSameRect 0x003B /* rect 0 */
+#define fillSameRect 0x003C /* rectangle 0 */
+ /* reserved 0x003D /* opcode 0 */
+ /* reserved 0x003E /* opcode 0 */
+ /* reserved 0x003F /* opcode 0 */
+#define frameRRect 0x0040 /* rect (see Note # 5 ) 8 */
+#define paintRRect 0x0041 /* rect (see Note # 5 ) 8 */
+#define eraseRRect 0x0042 /* rect (see Note # 5 ) 8 */
+#define invertRRect 0x0043 /* rect (see Note # 5 ) 8 */
+#define fillRRect 0x0044 /* rect (see Note # 5 ) 8 */
+ /* reserved 0x0045 /* opcode + 8 bytes data 8 */
+ /* reserved 0x0046 /* opcode + 8 bytes data 8 */
+ /* reserved 0x0047 /* opcode + 8 bytes data 8 */
+#define frameSameRRect 0x0048 /* rect 0 */
+#define paintSameRRect 0x0049 /* rect 0 */
+#define eraseSameRRect 0x004A /* rect 0 */
+#define invertSameRRect 0x004B /* rect 0 */
+#define fillSameRRect 0x004C /* rect 0 */
+ /* reserved 0x004D /* opcode 0 */
+ /* reserved 0x004E /* opcode 0 */
+ /* reserved 0x004F /* opcode 0 */
+#define frameOval 0x0050 /* rect 8 */
+#define paintOval 0x0051 /* rect 8 */
+#define eraseOval 0x0052 /* rect 8 */
+#define invertOval 0x0053 /* rect 8 */
+#define fillOval 0x0054 /* rect 8 */
+ /* reserved 0x0055 /* opcode + 8 bytes data 8 */
+ /* reserved 0x0056 /* opcode + 8 bytes data 8 */
+ /* reserved 0x0057 /* opcode + 8 bytes data 8 */
+#define frameSameOval 0x0058 /* rect 0 */
+#define paintSameOval 0x0059 /* rect 0 */
+#define eraseSameOval 0x005A /* rect 0 */
+#define invertSameOval 0x005B /* rect 0 */
+#define fillSameOval 0x005C /* rect 0 */
+ /* reserved 0x005D /* opcode 0 */
+ /* reserved 0x005E /* opcode 0 */
+ /* reserved 0x005F /* opcode 0 */
+#define frameArc 0x0060 /* rect, startAngle, arcAngle 12 */
+#define paintArc 0x0061 /* rect, startAngle, arcAngle 12 */
+#define eraseArc 0x0062 /* rect, startAngle, arcAngle 12 */
+#define invertArc 0x0063 /* rect, startAngle, arcAngle 12 */
+#define fillArc 0x0064 /* rect, startAngle, arcAngle 12 */
+ /* reserved 0x0065 /* opcode + 12 bytes 12 */
+ /* reserved 0x0066 /* opcode + 12 bytes 12 */
+ /* reserved 0x0067 /* opcode + 12 bytes 12 */
+#define frameSameArc 0x0068 /* rect 4 */
+#define paintSameArc 0x0069 /* rect 4 */
+#define eraseSameArc 0x006A /* rect 4 */
+#define invertSameArc 0x006B /* rect 4 */
+#define fillSameArc 0x006C /* rect 4 */
+ /* reserved 0x006D /* opcode + 4 bytes 4 */
+ /* reserved 0x006E /* opcode + 4 bytes 4 */
+ /* reserved 0x006F /* opcode + 4 bytes 4 */
+ /* size */
+#define framePoly 0x0070 /* poly polygon */
+ /* size */
+#define paintPoly 0x0071 /* poly polygon */
+ /* size */
+#define erasePoly 0x0072 /* poly polygon */
+ /* size */
+#define invertPoly 0x0073 /* poly polygon */
+ /* size */
+#define fillPoly 0x0074 /* poly polygon */
+ /* size */
+ /* reserved 0x0075 /* opcode + poly */
+ /* reserved 0x0076 /* opcode + poly */
+ /* reserved 0x0077 /* opcode word + poly */
+#define frameSamePoly 0x0078 /* (not yet implemented: 0 */
+ /* same as 70, etc) */
+#define paintSamePoly 0x0079 /* (not yet implemented) 0 */
+#define eraseSamePoly 0x007A /* (not yet implemented) 0 */
+#define invertSamePoly 0x007B /* (not yet implemented) 0 */
+#define fillSamePoly 0x007C /* (not yet implemented) 0 */
+ /* reserved 0x007D /* opcode 0 */
+ /* reserved 0x007E /* opcode 0 */
+ /* reserved 0x007F /* opcode 0 */
+#define frameRgn 0x0080 /* rgn region size */
+#define paintRgn 0x0081 /* rgn region size */
+#define eraseRgn 0x0082 /* rgn region size */
+#define invertRgn 0x0083 /* rgn region size */
+#define fillRgn 0x0084 /* rgn region size */
+ /* reserved 0x0085 /* opcode + rgn region size */
+ /* reserved 0x0086 /* opcode + rgn region size */
+ /* reserved 0x0087 /* opcode + rgn region size */
+#define frameSameRgn 0x0088 /* (not yet implemented: 0 */
+ /* same as 80, etc.) */
+#define paintSameRgn 0x0089 /* (not yet implemented) 0 */
+#define eraseSameRgn 0x008A /* (not yet implemented) 0 */
+#define invertSameRgn 0x008B /* (not yet implemented) 0 */
+#define fillSameRgn 0x008C /* (not yet implemented) 0 */
+ /* reserved 0x008D /* opcode 0 */
+ /* reserved 0x008E /* opcode 0 */
+ /* reserved 0x008F /* opcode 0 */
+#define BitsRect 0x0090 /* copybits, rect clipped variable: */
+ /* see Table 4 */
+#define BitsRgn 0x0091 /* copybits, rgn clipped variable: */
+ /* see Table 4 */
+ /* reserved 0x0092 /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+ /* reserved 0x0093 /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+ /* reserved 0x0094 /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+ /* reserved 0x0095 /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+ /* reserved 0x0096 /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+ /* reserved 0x0097 /* opcode word + 2 bytes 2+ data */
+ /* length + data length */
+#define PackBitsRect 0x0098 /* packed copybits, rect variable: */
+ /* clipped see Table 4 */
+#define PackBitsRgn 0x0099 /* packed copybits, rgn variable: */
+ /* clipped see Table 4 */
+#define DirectBitsRect 0x009A /* pixMap, srcRect, dstRect, 2+ data */
+ /* mode (word), pixData length */
+#define DirectBitsRgn 0x009B /* pixMap, srcRect, dstRect, 2+ data */
+ /* mode (word), pixData length */
+ /* reserved 0x009C /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+ /* reserved 0x009D /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+ /* reserved 0x009E /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+ /* reserved 0x009F /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+#define ShortComment 0x00A0 /* kind (word) 2 */
+#define LongComment 0x00A1 /* kind (word), size 4+data */
+ /* (word), data */
+ /* reserved 0x00A2 /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+ /* : : /* */
+ /* : : /* */
+ /* reserved 0x00AF /* opcode + 2 bytes data 2+ data */
+ /* length + data length */
+ /* reserved 0x00B0 /* opcode 0 */
+ /* : : /* */
+ /* : : /* */
+ /* reserved 0x00CF /* opcode 0 */
+ /* reserved 0x00D0 /* opcode + 4 bytes data 4+ data */
+ /* length + data length */
+ /* : : /* */
+ /* : : /* */
+ /* reserved 0x00FE /* opcode + 4 bytes data 4+ data */
+ /* length + data length */
+#define opEndPic 0x00FF /* end of picture 2 */
+ /* reserved 0x0100 /* opcode + 2 bytes data 2 */
+ /* : : /* */
+ /* : : /* */
+ /* reserved 0x01FF /* opcode + 2 bytes data 2 */
+ /* reserved 0x0200 /* opcode + 4 bytes data 4 */
+ /* : : /* */
+ /* reserved 0x0BFF /* opcode + 4 bytes data 22 */
+#define HeaderOp 0x0C00 /* opcode 24 */
+ /* reserved 0x0C01 /* opcode + 4 bytes data 24 */
+ /* : : /* */
+ /* reserved 0x7F00 /* opcode + 254 bytes data 254 */
+ /* : : /* */
+ /* reserved 0x7FFF /* opcode + 254 bytes data 254 */
+ /* reserved 0x8000 /* opcode 0 */
+ /* : : /* */
+ /* reserved 0x80FF /* opcode 0 */
+ /* reserved 0x8100 /* opcode + 4 bytes data 4+ data */
+ /* length + data length */
+ /* : : /* */
+ /* reserved 0xFFFF /* opcode + 4 bytes data 4+ data */
+ /* length + data length */
+ \ No newline at end of file
diff --git a/private/ole32/olecnv32/quickdrw.c b/private/ole32/olecnv32/quickdrw.c
new file mode 100644
index 000000000..cde44b49b
--- /dev/null
+++ b/private/ole32/olecnv32/quickdrw.c
@@ -0,0 +1,2659 @@
+
+/****************************************************************************
+ Module Quickdrw: Implementation
+*****************************************************************************
+
+ This is the interpreter engine for the picture convertor. It uses a
+ modified CGrafPort structure to hold the intermediate results of a
+ translation that can later be accessed from the Gdi module. As such,
+ it provides an input cache for all attributes, with calls made
+ directly to the Gdi module for primitives.
+
+ It is called by the API module and will call the Get module in order
+ to read individual data or record elements from the data stream.
+
+ Module prefix: QD
+
+****************************************************************************/
+
+#include "headers.c"
+#pragma hdrstop
+
+/* C libraries */
+#include "string.h"
+#include <ctype.h>
+
+/* quickdrw's own interface */
+#include "qdopcode.i"
+#include "qdcoment.i"
+
+/* imported modules */
+#include <math.h>
+#include "filesys.h"
+#include "getdata.h"
+
+/*********************** Exported Data Initialization ***********************/
+
+
+/******************************* Private Data *******************************/
+
+/*--- QuickDraw grafPort simulation --- */
+
+#define Version1ID 0x1101
+#define Version2ID 0x02FF
+
+
+/*--- QuickDraw opcode fields --- */
+
+/* -1 is casted to Word to prevent warning in WIN32 compilation */
+#define Reserved (Word) -1
+
+#define Variable -1
+#define CommentSize -2
+#define RgnOrPolyLen -3
+#define WordDataLen -4
+#define DWordDataLen -5
+#define HiByteLen -6
+
+typedef struct
+{
+ Word function;
+ Integer length;
+} opcodeEntry, far * opcodeEntryLPtr;
+
+/* The following opcode table was taken from "Inside Macintosh, Volume V" on
+ pages V-97 to V-102 and supplemented by System 7 opcodes from "Inside
+ Macintosh, Volume VI", page 17-20. */
+
+#define LookupTableSize 0xA2
+
+private opcodeEntry opcodeLookup[LookupTableSize] =
+{
+ /* 0x00 */ { NOP, 0 },
+ /* 0x01 */ { Clip, RgnOrPolyLen },
+ /* 0x02 */ { BkPat, 8 },
+ /* 0x03 */ { TxFont, 2 },
+ /* 0x04 */ { TxFace, 1 },
+ /* 0x05 */ { TxMode, 2 },
+ /* 0x06 */ { SpExtra, 4 },
+ /* 0x07 */ { PnSize, 4 },
+ /* 0x08 */ { PnMode, 2 },
+ /* 0x09 */ { PnPat, 8 },
+ /* 0x0A */ { FillPat, 8 },
+ /* 0x0B */ { OvSize, 4 },
+ /* 0x0C */ { Origin, 4 },
+ /* 0x0D */ { TxSize, 2 },
+ /* 0x0E */ { FgColor, 4 },
+ /* 0x0F */ { BkColor, 4 },
+ /* 0x10 */ { TxRatio, 8 },
+ /* 0x11 */ { Version, 1 },
+ /* 0x12 */ { BkPixPat, Variable },
+ /* 0x13 */ { PnPixPat, Variable },
+ /* 0x14 */ { FillPixPat, Variable },
+ /* 0x15 */ { PnLocHFrac, 2 },
+ /* 0x16 */ { ChExtra, 2 },
+ /* 0x17 */ { Reserved, 0 },
+ /* 0x18 */ { Reserved, 0 },
+ /* 0x19 */ { Reserved, 0 },
+ /* 0x1A */ { RGBFgCol, 6 },
+ /* 0x1B */ { RGBBkCol, 6 },
+ /* 0x1C */ { HiliteMode, 0 },
+ /* 0x1D */ { HiliteColor, 6 },
+ /* 0x1E */ { DefHilite, 0 },
+ /* 0x1F */ { OpColor, 6 },
+ /* 0x20 */ { Line, 8 },
+ /* 0x21 */ { LineFrom, 4 },
+ /* 0x22 */ { ShortLine, 6 },
+ /* 0x23 */ { ShortLineFrom, 2 },
+ /* 0x24 */ { Reserved, WordDataLen },
+ /* 0x25 */ { Reserved, WordDataLen },
+ /* 0x26 */ { Reserved, WordDataLen },
+ /* 0x27 */ { Reserved, WordDataLen },
+ /* 0x28 */ { LongText, Variable },
+ /* 0x29 */ { DHText, Variable },
+ /* 0x2A */ { DVText, Variable },
+ /* 0x2B */ { DHDVText, Variable },
+ /* 0x2C */ { FontName, WordDataLen },
+ /* 0x2D */ { LineJustify, WordDataLen },
+ /* 0x2E */ { Reserved, WordDataLen },
+ /* 0x2F */ { Reserved, WordDataLen },
+ /* 0x30 */ { frameRect, 8 },
+ /* 0x31 */ { paintRect, 8 },
+ /* 0x32 */ { eraseRect, 8 },
+ /* 0x33 */ { invertRect, 8 },
+ /* 0x34 */ { fillRect, 8 },
+ /* 0x35 */ { Reserved, 8 },
+ /* 0x36 */ { Reserved, 8 },
+ /* 0x37 */ { Reserved, 8 },
+ /* 0x38 */ { frameSameRect, 0 },
+ /* 0x39 */ { paintSameRect, 0 },
+ /* 0x3A */ { eraseSameRect, 0 },
+ /* 0x3B */ { invertSameRect, 0 },
+ /* 0x3C */ { fillSameRect, 0 },
+ /* 0x3D */ { Reserved, 0 },
+ /* 0x3E */ { Reserved, 0 },
+ /* 0x3F */ { Reserved, 0 },
+ /* 0x40 */ { frameRRect, 8 },
+ /* 0x41 */ { paintRRect, 8 },
+ /* 0x42 */ { eraseRRect, 8 },
+ /* 0x43 */ { invertRRect, 8 },
+ /* 0x44 */ { fillRRect, 8 },
+ /* 0x45 */ { Reserved, 8 },
+ /* 0x46 */ { Reserved, 8 },
+ /* 0x47 */ { Reserved, 8 },
+ /* 0x48 */ { frameSameRRect, 0 },
+ /* 0x49 */ { paintSameRRect, 0 },
+ /* 0x4A */ { eraseSameRRect, 0 },
+ /* 0x4B */ { invertSameRRect, 0 },
+ /* 0x4C */ { fillSameRRect, 0 },
+ /* 0x4D */ { Reserved, 0 },
+ /* 0x4E */ { Reserved, 0 },
+ /* 0x4F */ { Reserved, 0 },
+ /* 0x50 */ { frameOval, 8 },
+ /* 0x51 */ { paintOval, 8 },
+ /* 0x52 */ { eraseOval, 8 },
+ /* 0x53 */ { invertOval, 8 },
+ /* 0x54 */ { fillOval, 8 },
+ /* 0x55 */ { Reserved, 8 },
+ /* 0x56 */ { Reserved, 8 },
+ /* 0x57 */ { Reserved, 8 },
+ /* 0x58 */ { frameSameOval, 0 },
+ /* 0x59 */ { paintSameOval, 0 },
+ /* 0x5A */ { eraseSameOval, 0 },
+ /* 0x5B */ { invertSameOval, 0 },
+ /* 0x5C */ { fillSameOval, 0 },
+ /* 0x5D */ { Reserved, 0 },
+ /* 0x5E */ { Reserved, 0 },
+ /* 0x5F */ { Reserved, 0 },
+ /* 0x60 */ { frameArc, 12 },
+ /* 0x61 */ { paintArc, 12 },
+ /* 0x62 */ { eraseArc, 12 },
+ /* 0x63 */ { invertArc, 12 },
+ /* 0x64 */ { fillArc, 12 },
+ /* 0x65 */ { Reserved, 12 },
+ /* 0x66 */ { Reserved, 12 },
+ /* 0x67 */ { Reserved, 12 },
+ /* 0x68 */ { frameSameArc, 4 },
+ /* 0x69 */ { paintSameArc, 4 },
+ /* 0x6A */ { eraseSameArc, 4 },
+ /* 0x6B */ { invertSameArc, 4 },
+ /* 0x6C */ { fillSameArc, 4 },
+ /* 0x6D */ { Reserved, 4 },
+ /* 0x6E */ { Reserved, 4 },
+ /* 0x6F */ { Reserved, 4 },
+ /* 0x70 */ { framePoly, RgnOrPolyLen },
+ /* 0x71 */ { paintPoly, RgnOrPolyLen },
+ /* 0x72 */ { erasePoly, RgnOrPolyLen },
+ /* 0x73 */ { invertPoly, RgnOrPolyLen },
+ /* 0x74 */ { fillPoly, RgnOrPolyLen },
+ /* 0x75 */ { Reserved, RgnOrPolyLen },
+ /* 0x76 */ { Reserved, RgnOrPolyLen },
+ /* 0x77 */ { Reserved, RgnOrPolyLen },
+ /* 0x78 */ { frameSamePoly, 0 },
+ /* 0x79 */ { paintSamePoly, 0 },
+ /* 0x7A */ { eraseSamePoly, 0 },
+ /* 0x7B */ { invertSamePoly, 0 },
+ /* 0x7C */ { fillSamePoly, 0 },
+ /* 0x7D */ { Reserved, 0 },
+ /* 0x7E */ { Reserved, 0 },
+ /* 0x7F */ { Reserved, 0 },
+ /* 0x80 */ { frameRgn, RgnOrPolyLen },
+ /* 0x81 */ { paintRgn, RgnOrPolyLen },
+ /* 0x82 */ { eraseRgn, RgnOrPolyLen },
+ /* 0x83 */ { invertRgn, RgnOrPolyLen },
+ /* 0x84 */ { fillRgn, RgnOrPolyLen },
+ /* 0x85 */ { Reserved, RgnOrPolyLen },
+ /* 0x86 */ { Reserved, RgnOrPolyLen },
+ /* 0x87 */ { Reserved, RgnOrPolyLen },
+ /* 0x88 */ { frameSameRgn, 0 },
+ /* 0x89 */ { paintSameRgn, 0 },
+ /* 0x8A */ { eraseSameRgn, 0 },
+ /* 0x8B */ { invertSameRgn, 0 },
+ /* 0x8C */ { fillSameRgn, 0 },
+ /* 0x8D */ { Reserved, 0 },
+ /* 0x8E */ { Reserved, 0 },
+ /* 0x8F */ { Reserved, 0 },
+ /* 0x90 */ { BitsRect, Variable },
+ /* 0x91 */ { BitsRgn, Variable },
+ /* 0x92 */ { Reserved, WordDataLen },
+ /* 0x93 */ { Reserved, WordDataLen },
+ /* 0x94 */ { Reserved, WordDataLen },
+ /* 0x95 */ { Reserved, WordDataLen },
+ /* 0x96 */ { Reserved, WordDataLen },
+ /* 0x97 */ { Reserved, WordDataLen },
+ /* 0x98 */ { PackBitsRect, Variable },
+ /* 0x99 */ { PackBitsRgn, Variable },
+ /* 0x9A */ { DirectBitsRect, WordDataLen },
+ /* 0x9B */ { DirectBitsRgn, WordDataLen },
+ /* 0x9C */ { Reserved, WordDataLen },
+ /* 0x9D */ { Reserved, WordDataLen },
+ /* 0x9E */ { Reserved, WordDataLen },
+ /* 0x9F */ { Reserved, WordDataLen },
+ /* 0xA0 */ { ShortComment, 2 },
+ /* 0xA1 */ { LongComment, CommentSize }
+};
+
+#define RangeTableSize 7
+
+private opcodeEntry opcodeRange[RangeTableSize] =
+{
+ /* 0x00A2 - 0x00AF */ { 0x00AF, WordDataLen },
+ /* 0x00B0 - 0x00CF */ { 0x00CF, 0 },
+ /* 0x00D0 - 0x00FE */ { 0x00FE, DWordDataLen },
+ /* 0x00FF - 0x00FF */ { opEndPic, 0 },
+ /* 0x0100 - 0x07FF */ { 0x8000, HiByteLen },
+ /* 0x8000 - 0x80FF */ { 0x80FF, 0 },
+ /* 0x8100 - 0xFFFF */ { 0xFFFF, DWordDataLen }
+};
+
+/*--- EPS Filter PostScript Strings ---*/
+
+#define MAC_PS_TRAILER "pse\rpsb\r"
+#define MAC_PS_PREAMBLE "pse\rcurrentpoint\r/picTop exch def\r/picLeft exch def\rpsb\r"
+
+#define SUPERPAINT_TEXTSTARTJUNK "P2_b ["
+#define SUPERPAINT_TEXTSTOPJUNK "] sb end\r"
+
+/*--- GrafPort allocation ---*/
+
+#define PARSEPOLY 1
+#define SKIPALTPOLY 2
+#define USEALTPOLY 3
+
+#define MASKPOLYBITS 0x07
+#define FRAMEPOLY 0x01
+#define FILLPOLY 0x02
+#define CLOSEPOLY 0x04
+#define FILLREQUIRED 0x08
+#define CHECK4SPLINE 0x10
+
+#define POLYLIST ((sizeof( Integer ) + sizeof( Rect )) / sizeof( Integer ))
+#define BBOX 1
+
+private CGrafPort grafPort;
+private Integer resolution;
+private Boolean skipFontID;
+private Integer maxPoints;
+private Integer numPoints;
+private Integer far * numPointsLPtr;
+private Rect polyBBox;
+private Point far * polyListLPtr;
+private Handle polyHandle;
+private Byte polyMode;
+private Byte polyParams;
+private RGBColor polyFgColor;
+private RGBColor polyBkColor;
+private Boolean zeroDeltaExpected;
+
+private Boolean textMode;
+private Boolean newTextCenter;
+private Point textCenter;
+private Boolean textClipCheck;
+private Real degCos;
+private Real degSin;
+
+private Boolean shadedObjectStarted;
+private Boolean superPaintFile;
+private Boolean badSuperPaintText;
+
+/*--- last Primitive sent ---*/
+
+private Rect saveRect;
+private Rect saveRRect;
+private Rect saveOval;
+private Point saveOvalSize;
+private Rect saveArc;
+private Integer saveStartAngle;
+private Integer saveArcAngle;
+
+/*--- Global allocated contstants ---*/
+
+private Pattern SolidPattern = { 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF };
+
+
+/*********************** Private Routine Declarations ***********************/
+
+private void ReadHeaderInfo( void );
+/* read the fixed size PICT header from the file. This provides information
+ about the file size (however, it may be invalid and is ignored) and the
+ picture bounding box, followed by the PICT version information. */
+
+private void ReadPictVersion( void );
+/* Read the PICT version number from the data file. If this isn't a
+ version 1 or 2 file, the routine returns IE_UNSUPP_VERSION error. */
+
+private void ReadOpcode( opcodeEntry far * nextOpcode );
+/* Reads the next opcode from the stream, depending on the PICT version */
+
+private void TranslateOpcode( opcodeEntry far * currOpcodeLPtr );
+/* read in the remaining data from the stream, based upon the opcode function
+ and then call the appropriate routine in Gdi module */
+
+private void SkipData( opcodeEntry far * currOpcodeLPtr );
+/* skip the data - the opcode won't be translated and Gdi module won't be
+ called to create anything in the metafile */
+
+private void OpenPort( void );
+/* initialize the grafPort */
+
+private void ClosePort( void );
+/* close grafPort and de-allocate any memory blocks */
+
+private void NewPolygon( void );
+/* initialize the state of the polygon buffer - flush any previous data */
+
+private void AddPolySegment( Point start, Point end );
+/* Add the line segment to the polygon buffer */
+
+private void DrawPolyBuffer( void );
+/* Draw the polygon definition if the points were read without errors */
+
+private void AdjustTextRotation( Point far * newPt );
+/* This will calculate the correct text position if text is rotated */
+
+private Integer EPSComment(Word comment);
+/* parse EPS Comment */
+
+private Integer EPSData(Integer state);
+/* process EPS Data */
+
+private Boolean EPSBbox(PSBuf far *, Rect far *);
+/* parse EPS bounding box description */
+
+private char far* parse_number(char far* ptr, Integer far *iptr);
+/* parse numeric string (local to EPSBbox) */
+
+#define IsCharDigit(c) (IsCharAlphaNumeric(c) && !IsCharAlpha(c))
+
+/**************************** Function Implementation ***********************/
+
+void QDConvertPicture( Handle dialogHandle )
+/*====================*/
+/* create a Windows metafile using the previously set parameters, returning
+ the converted picture information in the pictResult structure. */
+
+{
+ opcodeEntry currOpcode;
+
+ /* Open the file - if an error occured, return to main */
+ IOOpenPicture( dialogHandle );
+
+ /* Tell Gdi module to open the metafile */
+ GdiOpenMetafile();
+
+ /* initialize the grafPort */
+ OpenPort();
+
+ /* read and validate size, bounding box, and PICT version */
+ ReadHeaderInfo();
+
+ do
+ {
+ /* read the next opcode from the data stream */
+ ReadOpcode( &currOpcode );
+
+ /* read the ensuing data and call Gdi module entry points */
+ TranslateOpcode( &currOpcode );
+
+ /* align next memory read to Word boundary in the case of PICT 2 */
+ if (grafPort.portVersion == 2)
+ {
+ IOAlignToWordOffset();
+ }
+
+ /* update the status dialog with current progress */
+ IOUpdateStatus();
+
+ /* break out of loop if end picture opcode is encountered */
+ } while (currOpcode.function != opEndPic);
+
+ /* close grafPort and de-allocate any used memory blocks */
+ ClosePort();
+
+ /* Tell Gdi module that picture is ending - perform wrapup */
+ GdiCloseMetafile();
+
+ /* Close the file */
+ IOClosePicture();
+
+} /* ReFileToPicture */
+
+
+void QDGetPort( CGrafPort far * far * port )
+/*============*/
+/* return handle to grafPort structure */
+{
+ *port = &grafPort;
+}
+
+
+void QDCopyBytes( Byte far * src, Byte far * dest, Integer numBytes )
+/*==============*/
+/* copy a data from source to destination */
+{
+ /* loop through entire data length */
+ while (numBytes--)
+ {
+ *dest++ = *src++;
+ }
+
+} /* CopyBytes */
+
+
+/******************************* Private Routines ***************************/
+
+
+private void ReadHeaderInfo( void )
+/*-------------------------*/
+/* read the fixed size PICT header from the file. This provides information
+ about the file size (however, it may be invalid and is ignored) and the
+ picture bounding box, followed by the PICT version information. */
+{
+ Word unusedSize;
+
+ /* read file size - this value is ignored since it may be totally bogus */
+ GetWord( &unusedSize );
+
+ /* the next rectangle contains the picture bounding box */
+ GetRect( &grafPort.portRect );
+
+ /* Read the next record that indicates a PICT1 or PICT2 version picture */
+ ReadPictVersion();
+
+ /* Call Gdi module and provide bounding box coordinates. Note that these
+ may have been altered from rectangle specified above if a spatial
+ resolution other than 72 dpi is used in the picture. */
+ GdiSetBoundingBox( grafPort.portRect, resolution );
+
+} /* ReadHeaderInfo */
+
+
+private void ReadPictVersion( void )
+/*--------------------------*/
+/* Read the PICT version number from the data file. If this isn't a
+ version 1 or 2 file, the routine returns IE_UNSUPP_VERSION error. */
+{
+ opcodeEntry versionOpcode;
+ Word versionCheck = 0;
+ Word opcodeCheck = 0;
+
+ /* The following loop was added in order to read PixelPaint files
+ successfully. Although technically an invalid PICT image, these files
+ contain a series of NOP opcodes, followed by the version opcode. In
+ this case, we continue reading until the version opcode (non-zero
+ value) is encountered, after which the checking continues. */
+ do
+ {
+ /* read the first two bytes from the data stream - for PICT 1 this is
+ both the opcode and version; for PICT 2 this is the opcode only. */
+ GetWord( &versionCheck );
+
+ } while ((versionCheck == NOP) && (ErGetGlobalError() == ErNoError));
+
+ /* determine if a valid version opcode was encountered */
+ if (versionCheck == Version1ID )
+ {
+ /* version 1 == 0x1101 */
+ grafPort.portVersion = 1;
+ }
+ /* check for version 2 opcode which is a Word in length */
+ else if (versionCheck == Version)
+ {
+ /* Since we have only read the opcode, read the next word which should
+ contain the identifier for PICT 2 data. */
+ GetWord( &versionCheck );
+ if (versionCheck == Version2ID)
+ {
+ grafPort.portVersion = 2;
+
+ /* make sure that the next record is a header opcode. */
+ GetWord( &opcodeCheck );
+ if (opcodeCheck == HeaderOp)
+ {
+ /* set up a record structure for call to TranslateOpcode(). */
+ versionOpcode.function = HeaderOp;
+ versionOpcode.length = 24;
+ TranslateOpcode( &versionOpcode );
+ }
+ else
+ {
+ /* Header wasn't followed by correct Header opcode - error. */
+ ErSetGlobalError( ErBadHeaderSequence );
+ }
+ }
+ else
+ {
+ /* if version 2 identifier is invalid, return error state. */
+ ErSetGlobalError( ErInvalidVersionID );
+ }
+ }
+ else
+ {
+ /* if check for version 1 and 2 fails, return error state. */
+ ErSetGlobalError( ErInvalidVersion );
+ }
+
+} /* ReadPictVersion */
+
+
+
+
+private void ReadOpcode( opcodeEntry far * nextOpcode )
+/*---------------------*/
+/* Reads the next opcode from the stream, depending on the PICT version */
+{
+ opcodeEntryLPtr checkEntry;
+
+ /* Initialize the function, since we may be reading a version 1 opcode
+ that is only 1 byte in length. */
+ nextOpcode->function = 0;
+
+ /* Depending on the PICT version, we will read either a single byte
+ or word for the opcode. */
+ if (grafPort.portVersion == 1)
+ {
+ GetByte( (Byte far *)&nextOpcode->function );
+ }
+ else
+ {
+ GetWord( &nextOpcode->function );
+ }
+
+ /* check the current error code and force an exit from read loop if
+ something went wrong. */
+ if (ErGetGlobalError() != NOERR)
+ {
+ nextOpcode->function = opEndPic;
+ nextOpcode->length = 0;
+ return;
+ }
+
+ /* Check the opcode function number to determine if we can perform
+ a direct lookup, or if the opcode is part of the range table. */
+ if (nextOpcode->function < LookupTableSize )
+ {
+ nextOpcode->length = opcodeLookup[nextOpcode->function].length;
+ }
+ else
+ {
+ /* Walk through the range table to determine the data length of the
+ ensuing information past the opcode. */
+ for (checkEntry = opcodeRange;
+ checkEntry->function < nextOpcode->function;
+ checkEntry++) ;
+
+ nextOpcode->length = checkEntry->length;
+ }
+
+} /* ReadOpcode */
+
+
+private void TranslateOpcode( opcodeEntry far * currOpcodeLPtr )
+/*--------------------------*/
+/* read in the remaining data from the stream, based upon the opcode function
+ and then call the appropriate routine in Gdi module */
+{
+ Word function = currOpcodeLPtr->function;
+
+ /* perform appropriate action based on function code */
+ switch (function)
+ {
+ case NOP:
+ /* no data follows */
+ break;
+
+ case Clip:
+ {
+ Boolean doClip = FALSE;
+
+ /* read in clip region into grafPort */
+ GetRegion( &grafPort.clipRgn );
+
+ /* if in textmode, we need avoid clip regions, since they are used
+ to draw Postscript encoded text *or* bitmap representations.
+ We allow a clipping region to pass through only if it is being
+ set to the bounds of the picture image (fix for MacDraw, Canvas,
+ and SuperPaint images containing rotated text.) */
+ if (textMode && textClipCheck)
+ {
+ Word far * sizeLPtr;
+
+ /* the most common case is a sequence of : null clip, text,
+ non-null clip, bitmap. If first clip == portRect, then
+ we actually want to set the clip - doClip is set to TRUE. */
+ sizeLPtr = (Word far *)GlobalLock( grafPort.clipRgn );
+ doClip = *sizeLPtr == RgnHeaderSize &&
+ EqualRect( (Rect far *)(sizeLPtr + 1), &grafPort.portRect );
+ GlobalUnlock( grafPort.clipRgn );
+
+ /* perform this check only once after initial picTextBegin */
+ textClipCheck = FALSE;
+ }
+
+ /* issue the clip only if not in text mode, or a sanctioned clip */
+ if (!textMode || doClip)
+ {
+ /* Call Gdi to set the new clip region */
+ GdiSelectClipRegion( grafPort.clipRgn );
+ }
+ break;
+ }
+
+ case BkPat:
+ /* flag the pixel map type a Foreground/Background pixel pattern */
+ /* and read pattern into old data position */
+ grafPort.bkPixPat.patType = QDOldPat;
+ GetPattern( &grafPort.bkPixPat.pat1Data );
+
+ /* Notify Gdi that background color may have changed */
+ GdiMarkAsChanged( GdiBkPat );
+ break;
+
+ case TxFont:
+ /* read text font index */
+ GetWord( (Word far *)&grafPort.txFont );
+
+ /* check if the font name was provided in previous opcode */
+ if (!skipFontID)
+ {
+ /* Make sure that the font name is a null string */
+ grafPort.txFontName[0] = cNULL;
+ }
+
+ /* Notify Gdi that text font index may have changed */
+ GdiMarkAsChanged( GdiTxFont );
+ break;
+
+ case TxFace:
+ /* read font attributes */
+ GetByte( (Byte far *)&grafPort.txFace );
+
+ /* Notify Gdi that text style elements may have changed */
+ GdiMarkAsChanged( GdiTxFace );
+ break;
+
+ case TxMode:
+ /* read text transfer mode */
+ GetWord( (Word far *)&grafPort.txMode );
+
+ /* Notify Gdi that text transfer mode may have changed */
+ GdiMarkAsChanged( GdiTxMode );
+ break;
+
+ case SpExtra:
+ /* read text space extra */
+ GetFixed( (Fixed far *)&grafPort.spExtra );
+
+ /* Notify Gdi that space extra may have changed */
+ GdiMarkAsChanged( GdiSpExtra );
+ break;
+
+ case PnSize:
+ /* read x and y components of pen size */
+ GetPoint( (Point far *)&grafPort.pnSize );
+
+ /* Notify Gdi that pen size may have changed */
+ GdiMarkAsChanged( GdiPnSize );
+ break;
+
+ case PnMode:
+ /* read pen transfer mode */
+ GetWord( (Word far *)&grafPort.pnMode );
+
+ /* Notify Gdi that transferm mode may have changed */
+ GdiMarkAsChanged( GdiPnMode );
+ break;
+
+ case PnPat:
+ /* flag the pixel map type a Foreground/Background pixel pattern */
+ /* and read pattern into old data position */
+ grafPort.pnPixPat.patType = QDOldPat;
+ GetPattern( &grafPort.pnPixPat.pat1Data );
+
+ /* Notify Gdi that pen pattern may have changed */
+ GdiMarkAsChanged( GdiPnPat );
+ break;
+
+ case FillPat:
+ /* flag the pixel map type a Foreground/Background pixel pattern */
+ /* and read pattern into old data position */
+ grafPort.fillPixPat.patType = QDOldPat;
+ GetPattern( &grafPort.fillPixPat.pat1Data );
+
+ /* Notify Gdi that fill pattern may have changed */
+ GdiMarkAsChanged( GdiFillPat );
+ break;
+
+ case OvSize:
+ /* save point in new grafPort field */
+ GetPoint( &saveOvalSize );
+ break;
+
+ case Origin:
+ {
+ Point offset;
+
+ /* read the new origin in to the upper-left coordinate space */
+ GetWord( (Word far *)&offset.x );
+ GetWord( (Word far *)&offset.y );
+
+ /* call gdi module to reset the origin */
+ GdiOffsetOrigin( offset );
+ break;
+ }
+
+ case TxSize:
+ GetWord( (Word far *)&grafPort.txSize );
+
+ /* Notify Gdi that text size may have changed */
+ GdiMarkAsChanged( GdiTxSize );
+ break;
+
+ case FgColor:
+ GetOctochromeColor( &grafPort.rgbFgColor );
+
+ /* Notify Gdi that foreground color may have changed */
+ GdiMarkAsChanged( GdiFgColor );
+ break;
+
+ case BkColor:
+ GetOctochromeColor( &grafPort.rgbBkColor );
+
+ /* Notify Gdi that background color may have changed */
+ GdiMarkAsChanged( GdiBkColor );
+ break;
+
+ case TxRatio:
+ /* save the numerator and denominator in the grafPort */
+ GetPoint( &grafPort.txNumerator );
+ GetPoint( &grafPort.txDenominator );
+
+ /* Notify Gdi that text ratio may have changed */
+ GdiMarkAsChanged( GdiTxRatio );
+ break;
+
+ case Version:
+ /* just skip over the version information */
+ IOSkipBytes( currOpcodeLPtr->length );
+ break;
+
+ case BkPixPat:
+ GetPixPattern( &grafPort.bkPixPat );
+
+ /* Notify Gdi that background pattern may have changed */
+ GdiMarkAsChanged( GdiBkPat );
+ break;
+
+ case PnPixPat:
+ GetPixPattern( &grafPort.pnPixPat );
+
+ /* Notify Gdi that pen pattern may have changed */
+ GdiMarkAsChanged( GdiPnPat );
+ break;
+
+ case FillPixPat:
+ GetPixPattern( &grafPort.fillPixPat );
+
+ /* Notify Gdi that fill pattern may have changed */
+ GdiMarkAsChanged( GdiFillPat );
+ break;
+
+ case PnLocHFrac:
+ GetWord( (Word far *)&grafPort.pnLocHFrac );
+ break;
+
+ case ChExtra:
+ GetWord( (Word far *)&grafPort.chExtra );
+
+ /* Notify Gdi that text character extra may have changed */
+ GdiMarkAsChanged( GdiChExtra );
+ break;
+
+ case RGBFgCol:
+ GetRGBColor( &grafPort.rgbFgColor );
+
+ /* Notify Gdi that foregroudn color may have changed */
+ GdiMarkAsChanged( GdiFgColor );
+ break;
+
+ case RGBBkCol:
+ GetRGBColor( &grafPort.rgbBkColor );
+
+ /* Notify Gdi that background color may have changed */
+ GdiMarkAsChanged( GdiBkColor );
+ break;
+
+ case HiliteMode:
+ /* don't do anything for hilite mode */
+ break;
+
+ case HiliteColor:
+ {
+ RGBColor rgbUnused;
+
+ GetRGBColor( &rgbUnused );
+ break;
+
+ }
+
+ case DefHilite:
+ /* don't do anything for hilite */
+ break;
+
+ case OpColor:
+ {
+ RGBColor rgbUnused;
+
+ GetRGBColor( &rgbUnused );
+ break;
+ }
+
+ case Line:
+ case LineFrom:
+ case ShortLine:
+ case ShortLineFrom:
+ {
+ Point newPt;
+ SignedByte deltaX;
+ SignedByte deltaY;
+
+ /* see if we need to read the updated pen location first */
+ if (function == ShortLine || function == Line)
+ {
+ /* read in the new pen location */
+ GetCoordinate( &grafPort.pnLoc );
+ }
+
+ /* determine what the next data record contains */
+ if (function == Line || function == LineFrom)
+ {
+ /* get the new coordinate to draw to */
+ GetCoordinate( &newPt );
+ }
+ else /* if (function == ShortLine || function == ShortLineFrom) */
+ {
+ /* the the new x and y deltas */
+ GetByte( &deltaX );
+ GetByte( &deltaY );
+
+ /* calculate the endpoint for call to gdi */
+ newPt.x = grafPort.pnLoc.x + (Integer)deltaX;
+ newPt.y = grafPort.pnLoc.y + (Integer)deltaY;
+ }
+
+ /* check if buffering line segments (polygon mode != FALSE) */
+ if (polyMode)
+ {
+ /* add the line segment to the polygon buffer */
+ AddPolySegment( grafPort.pnLoc, newPt );
+ }
+ else
+ {
+ /* Call Gdi to draw line */
+ GdiLineTo( newPt );
+ }
+
+ /* update the new pen location in the grafPort */
+ grafPort.pnLoc = newPt;
+ break;
+ }
+
+ case LongText:
+ {
+ Str255 txString;
+ Point location;
+
+ /* read the new pen (baseline) location */
+ GetCoordinate( &grafPort.txLoc );
+ GetString( (StringLPtr)txString );
+
+ /* adjust for any text rotation that may be set */
+ location = grafPort.txLoc;
+ AdjustTextRotation( &location );
+
+ /* call Gdi to print the text at current pen location */
+ GdiTextOut( txString, location );
+ break;
+ }
+
+ case DHText:
+ case DVText:
+ case DHDVText:
+ {
+ Byte deltaX = 0;
+ Byte deltaY = 0;
+ Str255 txString;
+ Point location;
+
+ /* if command is DHText or DHDVText, read horizontal offset */
+ if (function != DVText)
+ {
+ GetByte( &deltaX );
+ }
+
+ /* if command is DVText or DHDVText, then read the vertical offset */
+ if (function != DHText)
+ {
+ GetByte( &deltaY );
+ }
+
+ /* update the current pen postion */
+ grafPort.txLoc.x += deltaX;
+ grafPort.txLoc.y += deltaY;
+
+ /* now read in the string */
+ GetString( (StringLPtr)txString );
+
+ /* adjust for any text rotation that may be set */
+ location = grafPort.txLoc;
+ AdjustTextRotation( &location );
+
+ /* call Gdi to print the text at current pen location */
+ GdiTextOut( txString, location );
+ break;
+ }
+
+ case FontName:
+ {
+ Word dataLen;
+
+ GetWord( (Word far *)&dataLen );
+ GetWord( (Word far *)&grafPort.txFont );
+ GetString( grafPort.txFontName );
+
+ /* Notify Gdi that font name may have changed */
+ GdiMarkAsChanged( GdiTxFont );
+ break;
+ }
+
+ case LineJustify:
+ {
+ Word dataLen;
+ Fixed interCharSpacing;
+ Fixed textExtra;
+
+ GetWord( (Word far *)&dataLen );
+ GetFixed( &interCharSpacing ); // !!! where to put this ?
+ GetFixed( &textExtra );
+
+ /* Notify Gdi that line justification may have changed */
+ GdiMarkAsChanged( GdiLineJustify );
+ break;
+ }
+
+
+ case frameRect:
+ case paintRect:
+ case eraseRect:
+ case invertRect:
+ case fillRect:
+ {
+ /* read in the rectangle */
+ GetRect( &saveRect );
+
+ /* call the correct GDI routine */
+ GdiRectangle( function - frameRect, saveRect );
+ break;
+ }
+
+ case frameSameRect:
+ case paintSameRect:
+ case eraseSameRect:
+ case invertSameRect:
+ case fillSameRect:
+ {
+ /* notify gdi that this is the same primitive */
+ GdiSamePrimitive( TRUE );
+
+ /* call the correct gdi routine using last rectangle coords */
+ GdiRectangle( function - frameSameRect, saveRect );
+
+ /* notify gdi that this is no longer the same primitive */
+ GdiSamePrimitive( FALSE );
+ break;
+ }
+
+ case frameRRect:
+ case paintRRect:
+ case eraseRRect:
+ case invertRRect:
+ case fillRRect:
+ {
+ /* save the rectangle */
+ GetRect( &saveRRect );
+
+ /* call the correct gdi routine using last rectangle coords */
+ GdiRoundRect( function - frameRRect, saveRRect, saveOvalSize );
+ break;
+ }
+
+ case frameSameRRect:
+ case paintSameRRect:
+ case eraseSameRRect:
+ case invertSameRRect:
+ case fillSameRRect:
+ {
+ /* notify gdi that this is the same primitive */
+ GdiSamePrimitive( TRUE );
+
+ /* call the correct gdi routine using last rectangle coords */
+ GdiRoundRect( function - frameSameRRect, saveRRect, saveOvalSize );
+
+ /* notify gdi that this is no longer the same primitive */
+ GdiSamePrimitive( FALSE );
+ break;
+ }
+
+ case frameOval:
+ case paintOval:
+ case eraseOval:
+ case invertOval:
+ case fillOval:
+ {
+ /* save off bounding rectangle */
+ GetRect( &saveOval );
+
+ /* call the correct gdi routine using last oval coords */
+ GdiOval( function - frameOval, saveOval );
+ break;
+ }
+
+ case frameSameOval:
+ case paintSameOval:
+ case eraseSameOval:
+ case invertSameOval:
+ case fillSameOval:
+ {
+ /* notify gdi that this is the same primitive */
+ GdiSamePrimitive( TRUE );
+
+ /* call the correct gdi routine using last oval coords */
+ GdiOval( function - frameSameOval, saveOval );
+
+ /* notify gdi that this is no longer the same primitive */
+ GdiSamePrimitive( FALSE );
+ break;
+ }
+
+ case frameArc:
+ case paintArc:
+ case eraseArc:
+ case invertArc:
+ case fillArc:
+ {
+ /* read rect into the save variables, new start and arc angles */
+ GetRect( &saveArc );
+ GetWord( (Word far *)&saveStartAngle );
+ GetWord( (Word far *)&saveArcAngle );
+#ifdef WIN32
+ /* have to extend the sign because GetWord doesn't */
+ saveStartAngle = (short)saveStartAngle;
+ saveArcAngle = (short)saveArcAngle;
+#endif
+ /* call the correct gdi routine using last arc angles */
+ GdiArc( function - frameArc, saveArc, saveStartAngle, saveArcAngle );
+ break;
+ }
+
+ case frameSameArc:
+ case paintSameArc:
+ case eraseSameArc:
+ case invertSameArc:
+ case fillSameArc:
+ {
+ Integer startAngle;
+ Integer arcAngle;
+
+ /* read new start and arc angles */
+ GetWord( (Word far *)&startAngle );
+ GetWord( (Word far *)&arcAngle );
+#ifdef WIN32
+ /* have to extend the sign because GetWord doesn't */
+ startAngle = (short)startAngle;
+ arcAngle = (short)arcAngle;
+#endif
+
+ /* notify gdi that this is the may be the same primitive */
+ GdiSamePrimitive( (startAngle == saveStartAngle) &&
+ (arcAngle == saveArcAngle) );
+
+ /* save off the start and arc angles */
+ saveStartAngle = startAngle;
+ saveArcAngle = arcAngle;
+
+ /* call the correct gdi routine using last rect and arc angles */
+ GdiArc( function - frameSameArc, saveArc, startAngle, arcAngle );
+
+ /* notify gdi that this is no longer the same primitive */
+ GdiSamePrimitive( FALSE );
+ break;
+ }
+
+ case framePoly:
+ case paintPoly:
+ case erasePoly:
+ case invertPoly:
+ case fillPoly:
+ {
+ /* save the polygon in the grafPort */
+ GdiSamePrimitive( GetPolygon( &grafPort.polySave, (function == framePoly) ) );
+
+ /* call gdi routine to draw polygon */
+ GdiPolygon( function - framePoly, grafPort.polySave );
+
+ /* turn off filling while in polygon mode */
+ polyParams &= ~FILLREQUIRED;
+
+ /* notify gdi that this is no longer the same primitive */
+ GdiSamePrimitive( FALSE );
+ break;
+ }
+
+ case frameSamePoly:
+ case paintSamePoly:
+ case eraseSamePoly:
+ case invertSamePoly:
+ case fillSamePoly:
+ {
+ /* notify gdi that this is the same primitive */
+ GdiSamePrimitive( TRUE );
+
+ /* call gdi routine to draw polygon */
+ GdiPolygon( function - frameSamePoly, grafPort.polySave );
+
+ /* notify gdi that this is no longer the same primitive */
+ GdiSamePrimitive( FALSE );
+ break;
+ }
+
+ case frameRgn:
+ case paintRgn:
+ case eraseRgn:
+ case invertRgn:
+ case fillRgn:
+ {
+ /* save the region in the grafPort */
+ GetRegion( &grafPort.rgnSave );
+
+ /* if in polygon mode and a fillRgn is encountered, this indicates
+ that the polygon should be filled once parsing is completed */
+ if (polyMode == PARSEPOLY)
+ {
+ /* make sure that a PaintPoly() hasn't been handled already */
+ if (!(polyParams & (FILLPOLY | FILLREQUIRED)))
+ {
+ /* set flags to fill polygon once polygon buffer is filled */
+ polyParams |= FILLPOLY | FILLREQUIRED;
+ }
+ }
+ else if (polyMode == FALSE ||
+ ((polyMode == USEALTPOLY) && !(polyParams & FRAMEPOLY)))
+ {
+ /* call gdi routine to draw polygon */
+ GdiRegion( function - frameRgn, grafPort.rgnSave );
+
+ /* make sure that the polygon isn't filled when the simulation
+ buffer is drawn at the end of the polygon definition */
+ polyParams &= ~FILLREQUIRED;
+ }
+
+ /* save off the current fore- and background colors for
+ polygon simulation routine to ensure correct fill colors */
+ if (polyMode && (grafPort.fillPixPat.patType == QDOldPat))
+ {
+ polyFgColor = grafPort.rgbFgColor;
+ polyBkColor = grafPort.rgbBkColor;
+ }
+
+ break;
+ }
+
+ case frameSameRgn:
+ case paintSameRgn:
+ case eraseSameRgn:
+ case invertSameRgn:
+ case fillSameRgn:
+ {
+ /* notify gdi that this is the same primitive */
+ GdiSamePrimitive( TRUE );
+
+ /* call gdi routine to draw polygon */
+ GdiRegion( function - frameSameRgn, grafPort.rgnSave );
+
+ /* notify gdi that this is no longer the same primitive */
+ GdiSamePrimitive( FALSE );
+ break;
+ }
+
+ case BitsRect:
+ case BitsRgn:
+ case PackBitsRect:
+ case PackBitsRgn:
+ case DirectBitsRect:
+ case DirectBitsRgn:
+ {
+ Boolean has24bits;
+ Boolean hasRegion;
+ Rect srcRect;
+ Rect dstRect;
+ Word mode;
+ PixMap pixMap;
+ Handle pixData;
+ DWord unusedBaseAddr;
+ RgnHandle rgn;
+
+ /* determine which type of bitmap we are reading */
+ has24bits = (function == DirectBitsRect ||
+ function == DirectBitsRgn);
+ hasRegion = (function == DirectBitsRgn ||
+ function == BitsRgn ||
+ function == PackBitsRgn);
+
+ /* currently there is no region created */
+ rgn = NULL;
+
+ /* if 24-bit, read in the base address which should == 0x000000FF */
+ if (has24bits)
+ {
+ GetDWord( &unusedBaseAddr );
+ }
+
+ /* read in the header structure */
+ GetPixMap( &pixMap, FALSE );
+
+ /* if this isn't an 24-bit RGB bitmap, read in the color table.
+ Also check the rowBytes field to signify bitmap w/2 colors */
+ if (!has24bits && (pixMap.rowBytes & PixelMapBit))
+ {
+ GetColorTable( &pixMap.pmTable );
+ }
+
+ /* call io module to update status indicator */
+ IOUpdateStatus();
+
+ /* read source and destination rects from stream */
+ GetRect( &srcRect );
+ GetRect( &dstRect );
+ GetWord( &mode );
+
+ /* if there is a region included, read this also */
+ if (hasRegion)
+ {
+ /* read in the region */
+ GetRegion( &rgn );
+ }
+
+ /* read the pixel bit data */
+ GetPixData( &pixMap, &pixData );
+
+ if (ErGetGlobalError() == NOERR && !textMode)
+ {
+ /* Call Gdi to render the bitmap and de-allocate the memory */
+ GdiStretchDIBits( &pixMap, pixData, srcRect, dstRect, mode, rgn );
+ }
+ else
+ {
+ /* deallocate any memory that may be allocated */
+ if (pixMap.pmTable != NULL)
+ {
+ GlobalFree( pixMap.pmTable );
+ }
+ if (hasRegion && (rgn != NULL))
+ {
+ GlobalFree( rgn );
+ }
+ if (pixData != NULL)
+ {
+ GlobalFree( pixData );
+ }
+ }
+ break;
+ }
+
+ case ShortComment:
+ {
+ Word comment;
+ Boolean doComment;
+ Comment gdiComment;
+
+ /* get the comment word */
+ GetWord( &comment );
+
+ /* assume that we won't be generating an metafile comment */
+ doComment = FALSE;
+
+ /* determine the corresponding GDI comment for the comment */
+ switch (comment)
+ {
+ case picPostScriptBegin:
+ case picPostScriptEnd:
+ EPSComment(comment);
+ break;
+
+ case picLParen:
+ case picGrpBeg:
+ doComment = TRUE;
+ gdiComment.function = BEGIN_GROUP;
+ break;
+
+ case picRParen:
+ case picGrpEnd:
+ doComment = TRUE;
+ gdiComment.function = END_GROUP;
+ break;
+
+ case picBitBeg:
+ doComment = TRUE;
+ gdiComment.function = BEGIN_BANDING;
+ break;
+
+ case picBitEnd:
+ doComment = TRUE;
+ gdiComment.function = END_BANDING;
+ break;
+
+ case picPolyBegin:
+ /* indicate that we are in polygon mode, and reset buffer */
+ polyMode = PARSEPOLY;
+ polyParams = FRAMEPOLY;
+ NewPolygon();
+ break;
+
+ case picPolyEnd:
+ /* flush the polygon buffer and exit polygon mode */
+ DrawPolyBuffer();
+ polyMode = FALSE;
+ break;
+
+ case picPolyIgnore:
+ /* see if we should reset the polygon buffer */
+ if (polyMode == USEALTPOLY)
+ {
+ /* use the alternate polygon definition to draw */
+ NewPolygon();
+ }
+ else
+ {
+ /* otherwise, just use the current saved polygon buffer */
+ polyMode = SKIPALTPOLY;
+ }
+ break;
+
+ case picTextEnd:
+ /* set the global flag indicating we are exiting text mode */
+ grafPort.txRotation = 0;
+ grafPort.txFlip = QDFlipNone;
+ textMode = FALSE;
+ break;
+
+ default:
+ break;
+ }
+
+ /* if there is some comment to emit, then call GDI module */
+ if (doComment)
+ {
+ /* make this a public comment */
+ gdiComment.signature = PUBLIC;
+ gdiComment.size = 0;
+
+ /* call the gdi entry point */
+ GdiShortComment( &gdiComment );
+ }
+
+ break;
+ }
+
+ case LongComment:
+ {
+ Word comment;
+ Integer length;
+
+ /* get the comment function */
+ GetWord(&comment);
+
+ /* determine what should be done with the comment */
+ switch (comment)
+ {
+ case picPostScriptBegin:
+ case picPostScriptEnd:
+ case picPostScriptHandle:
+ {
+ if (EPSComment(comment) == 0) /* not EPS? */
+ {
+ GetWord( &length ); /* skip it */
+ }
+ else
+ {
+ length = 0; /* EPS was already read */
+ }
+ break;
+ }
+
+ case picPolySmooth:
+ {
+ /* read the total length of comment */
+ GetWord( &length );
+
+ /* read polygon parameter mask and set flag bits */
+ GetByte( &polyParams );
+ polyParams &= MASKPOLYBITS;
+ polyParams |= CHECK4SPLINE;
+ length--;
+
+ /* if we are to fill the polygon, indicate that fill required
+ just in case a PaintPoly() record appears before picPolyEnd */
+ if (polyParams & FILLPOLY)
+ {
+ /* or in the fill required bit */
+ polyParams |= FILLREQUIRED;
+ }
+ break;
+ }
+
+ case picTextBegin:
+ {
+ Byte unusedAlignment;
+
+ /* read the comment length */
+ GetWord( &length );
+
+ /* read in only relevant parameters - align, flip, rotation */
+ GetByte( &unusedAlignment );
+ GetByte( &grafPort.txFlip );
+ GetWord( &grafPort.txRotation );
+ length -= 4;
+
+ /* set the global flag indicating we are in text mode. The
+ only case this isn't true if for badly mangled SuperPaint
+ files that have invalid rotation and pt size information. */
+ if( !(superPaintFile && badSuperPaintText) )
+ {
+ textMode = TRUE;
+ textClipCheck = TRUE;
+ }
+ break;
+ }
+
+ case picTextCenter:
+ {
+ Fixed textCenterX;
+ Fixed textCenterY;
+
+ /* read the comment length */
+ GetWord( &length );
+
+ /* read y and x offsets to center of text rotation */
+ GetFixed( &textCenterY );
+ GetFixed( &textCenterX );
+ length -= 8;
+
+ /* copy only the highword of the fixed value to textCenter */
+ textCenter.x = (short) (HIWORD( textCenterX ));
+ textCenter.y = (short) (HIWORD( textCenterY ));
+
+ /* make sure that the center is rounded, not truncated */
+ if (LOWORD( textCenterX) & 0x8000)
+ textCenter.x++;
+
+ if (LOWORD( textCenterY) & 0x8000)
+ textCenter.y++;
+
+ /* indicate that text center needs to be re-computed */
+ newTextCenter = TRUE;
+ break;
+ }
+
+ case picAppComment:
+ {
+ DWord signature;
+ Word function;
+ Word realFunc;
+
+ /* read total comment length */
+ GetWord( &length );
+
+ /* make sure that there's enough space to read signature */
+ if (length < sizeofMacDWord )
+ {
+ /* if insufficient, just skip remaining data */
+ break;
+ }
+
+ /* read the signature of the application */
+ GetDWord( &signature );
+ length -= sizeofMacDWord ;
+
+ /* is this PowerPoint 'PPNT' signature and function size enough? */
+ if ((signature != POWERPOINT && signature != POWERPOINT_OLD) ||
+ (length < sizeofMacWord ))
+ {
+ /* if SuperPaint signature matches, flag for text checks */
+ if (signature == SUPERPAINT)
+ superPaintFile = TRUE;
+
+ /* if wrong signature, or insufficient space, bail */
+ break;
+ }
+
+ /* read the application function ID */
+ GetWord( &function );
+ length -= sizeofMacWord ;
+
+ /* mask out high-order bit to get "real" opcode */
+ realFunc = function & ~PC_REGISTERED;
+
+ /* determine what to do with the function specified */
+ switch (realFunc)
+ {
+ case PP_FONTNAME:
+ {
+ Byte fontFamily;
+ Byte charSet;
+ Byte fontName[32];
+
+ /* font name from GDI2QD - read the LOGFONT info */
+ GetByte( &fontFamily );
+ GetByte( &charSet );
+ GetString( fontName );
+ length = 0;
+
+ /* call Gdi module to override font selection */
+ GdiFontName( fontFamily, charSet, fontName );
+ break;
+ }
+
+ case PP_HATCHPATTERN:
+ {
+ Integer hatchIndex;
+
+ /* hatch pattern from GDI2QD - read hatch index value */
+ GetWord( (Word far *)&hatchIndex );
+ length = 0;
+
+ /* notify Gdi module of hatch to override fill pattern */
+ GdiHatchPattern( hatchIndex );
+ break;
+ }
+
+ case PP_BEGINFADE:
+ case PP_BEGINPICTURE:
+ case PP_DEVINFO:
+ {
+ DWord cmntSize;
+ Boolean doComment;
+
+ struct
+ {
+ Comment gdiComment;
+ union
+ {
+ struct
+ {
+ Byte version;
+ Boolean isShape;
+ Integer shapeIndex;
+ Integer shapeParam1;
+ Boolean olpNIL;
+ Rect orectDR;
+ Rect orect;
+ Word shape;
+ Integer shapeParam2;
+ Rect location;
+ Integer gradient;
+ Boolean fromBackground;
+ Boolean darker;
+ Integer arcStart;
+ Integer arcSweep;
+ Word backR;
+ Word backG;
+ Word backB;
+ Rect rSImage;
+ } fade;
+
+ Word entity;
+
+ Point unitsPerPixel;
+
+ } parm;
+
+ } cmnt;
+
+#ifdef WIN32
+ memset( &cmnt, 0, sizeof( cmnt ));
+#endif
+
+ /* so far, we won't be writting the Escape comment */
+ doComment = FALSE;
+
+ /* can we read the comment size? */
+ if (length < sizeofMacDWord )
+ {
+ /* couldn't read the size - just exit */
+ break;
+ }
+
+ /* read in a size field and validate */
+ GetDWord( &cmntSize );
+ length -= sizeofMacDWord ;
+
+ /* is this is an invalid PP3 size field (Word len) */
+ if (HIWORD( cmntSize ) != 0)
+ {
+ /* yes - just skip the remaining data */
+ break;
+ }
+
+ /* a valid comment was found - fill in header struct */
+ cmnt.gdiComment.signature = POWERPOINT;
+ cmnt.gdiComment.function = function;
+ cmnt.gdiComment.size = 0;
+
+ /* check if this is a zero-length comment */
+ if (cmntSize == 0)
+ {
+ /* make sure that the comment gets written */
+ doComment = TRUE;
+ }
+ /* process the begin fade comment */
+ else if (realFunc == PP_BEGINFADE)
+ {
+ /* can we read the version field? */
+ if (length < sizeof( Byte ))
+ {
+ /* can't read version - just bail */
+ break;
+ }
+
+ /* read the version field */
+ GetByte( &cmnt.parm.fade.version );
+ length -= sizeof( Byte );
+
+ /* if this is version 1 or 2, copy the bytes */
+ if (cmnt.parm.fade.version == 1 || cmnt.parm.fade.version == 2)
+ {
+ Handle cmntHandle;
+ Comment far * cmntLPtr;
+ Byte far * cmntDataLPtr;
+ DWord escapeSize;
+ Word i;
+
+ /* determine size and allocate the required buffer */
+ escapeSize = cmntSize + sizeof( Comment );
+ cmntHandle = GlobalAlloc( GHND, escapeSize );
+
+ /* make sure allocation succeeded */
+ if (cmntHandle == NULL)
+ {
+ ErSetGlobalError( ErMemoryFull );
+ break;
+ }
+
+ /* lock the buffer and assign the comment header */
+ cmntLPtr = (Comment far *)GlobalLock( cmntHandle );
+
+ /* set the correct signature and parameters */
+ cmntLPtr->signature = POWERPOINT;
+ cmntLPtr->function = function;
+ cmntLPtr->size = cmntSize;
+
+ /* get pointer to the data and assign the version */
+ cmntDataLPtr = ((Byte far *)cmntLPtr) + sizeof( Comment );
+ *cmntDataLPtr++ = cmnt.parm.fade.version;
+
+ /* copy the byte over - start at 1 for version read */
+ for (i = 1; i < (Word)cmntSize; i++)
+ {
+ /* copy over byte and increment pointer */
+ GetByte( cmntDataLPtr++ );
+ }
+
+ /* put the comment into the metafile */
+ GdiEscape( MFCOMMENT, (Word)escapeSize, (StringLPtr)cmntLPtr );
+
+ /* release the memory allocated for the structure */
+ GlobalUnlock( cmntHandle );
+ GlobalFree( cmntHandle );
+ }
+ /* otherwise, perform swapping for PP3 fade */
+ else if (cmnt.parm.fade.version == 3)
+ {
+ Word unusedWord;
+
+ if (length < ( 1 + (11 * sizeofMacWord) +
+ ( 4 * sizeofMacRect) + 4
+ ))
+ /* The above magic numbers come from:
+ GetByte
+ GetWord GetWord GetWord GetWord GetWord GetWord
+ GetWord GetWord GetWord GetWord GetWord
+ GetRect GetRect GetRect GetRect
+ GetBoolean GetBoolean GetBoolean GetBoolean
+ This is to make sure enough input left for
+ parameters - note that the Mac size is one less
+ than the GDI fade */
+ {
+ /* no - just bail */
+ break;
+ }
+
+ /* read in all remaining parameters */
+ GetBoolean( (Boolean far *)(&cmnt.parm.fade.isShape) );
+ GetWord( (Word far *)(&cmnt.parm.fade.shapeIndex) );
+ GetWord( (Word far *)(&cmnt.parm.fade.shapeParam1) );
+ GetBoolean( (Boolean far *)(&cmnt.parm.fade.olpNIL) );
+ GetByte( (Byte far *)(&unusedWord) );
+ GetRect( (Rect far *)(&cmnt.parm.fade.orectDR) );
+ GetRect( (Rect far *)(&cmnt.parm.fade.orect) );
+ GetWord( (Word far *)(&cmnt.parm.fade.shape) );
+ GetWord( (Word far *)(&cmnt.parm.fade.shapeParam2) );
+ GetRect( (Rect far *)(&cmnt.parm.fade.location) );
+ GetWord( (Word far *)(&cmnt.parm.fade.gradient) );
+ GetBoolean( (Boolean far *)(&cmnt.parm.fade.fromBackground) );
+ GetBoolean( (Boolean far *)(&cmnt.parm.fade.darker ) );
+ GetWord( (Word far *)(&cmnt.parm.fade.arcStart) );
+ GetWord( (Word far *)(&cmnt.parm.fade.arcSweep) );
+ GetWord( (Word far *)(&unusedWord) );
+ GetWord( (Word far *)(&cmnt.parm.fade.backR) );
+ GetWord( (Word far *)(&cmnt.parm.fade.backG) );
+ GetWord( (Word far *)(&cmnt.parm.fade.backB) );
+ GetRect( (Rect far *)(&cmnt.parm.fade.rSImage) );
+
+ /* determine the comment size */
+ cmnt.gdiComment.size = sizeof( cmnt.parm.fade );
+
+ /* make sure comment gets written */
+ doComment = TRUE;
+ }
+
+ /* no more bytes to read, flag that faded object started */
+ length = 0;
+ shadedObjectStarted = TRUE;
+ }
+ else if (realFunc == PP_BEGINPICTURE)
+ {
+ /* can we read the entity reference? */
+ if (length < sizeofMacWord )
+ {
+ /* no - just bail */
+ break;
+ }
+
+ /* read the entity reference */
+ GetWord( &cmnt.parm.entity );
+ length -= sizeofMacWord;
+
+ /* assign the correct comment size */
+ cmnt.gdiComment.size = sizeof( cmnt.parm.entity );
+
+ /* make sure comment gets written */
+ doComment = TRUE;
+ }
+ else if (realFunc == PP_DEVINFO)
+ {
+ /* can we read the units per pixel? */
+ if (length < sizeofMacPoint)
+ {
+ /* no - just bail */
+ break;
+ }
+
+ /* read the units per pixel */
+ GetPoint( (Point far *)&cmnt.parm.unitsPerPixel );
+ length -= sizeofMacPoint;
+
+ /* assign the size field */
+ cmnt.gdiComment.size = sizeof( cmnt.parm.unitsPerPixel );
+
+ /* make sure comment gets written */
+ doComment = TRUE;
+ }
+
+ /* write out the Gdi Escape comment */
+ if (doComment)
+ {
+ /* call the gdi entry point */
+ GdiEscape( MFCOMMENT, sizeof( Comment ) + (Word)cmnt.gdiComment.size, (StringLPtr)&cmnt );
+ }
+ break;
+ }
+
+ case PP_ENDFADE:
+ {
+ /* make sure that the BEGINFADE was put into metafile */
+ if (!shadedObjectStarted)
+ {
+ /* if not, then bail out */
+ break;
+ }
+ /* otherwise, just drop into the next case statement */
+ }
+
+ case PP_ENDPICTURE:
+ {
+ Comment gdiComment;
+
+ /* make this a private PowerPoint comment */
+ gdiComment.signature = POWERPOINT;
+ gdiComment.function = function;
+ gdiComment.size = 0;
+
+ /* call the gdi entry point */
+ GdiShortComment( &gdiComment );
+
+ /* if this is the end of fade, mask out flag check */
+ if (realFunc == PP_ENDFADE)
+ {
+ /* end fade was processed successfully */
+ shadedObjectStarted = FALSE;
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ default:
+ {
+ /* any other comment is just skipped */
+ GetWord( &length );
+ break;
+ }
+ }
+
+ /* skip any remaining bytes to be read */
+ IOSkipBytes( length );
+ break;
+ }
+
+ case opEndPic:
+ /* do nothing - picture is closing */
+ break;
+
+ case HeaderOp:
+ {
+ Integer version;
+ Word unusedReserved1;
+ Fixed hRes;
+ Fixed vRes;
+ Rect unusedRect;
+ DWord unusedReserved2;
+
+ /* read in the the version to determine if OpenCPort() was used
+ to open the picture, thus containing spatial resoultion info. */
+ GetWord( (Word far *)&version );
+
+ /* read any other parameters - will check later if they are valid.
+ If version == -1, we are reading over the bounding rectangle. */
+ GetWord( &unusedReserved1 );
+ GetFixed( &hRes );
+ GetFixed( &vRes );
+
+ /* check if bounding rect and spatial resolution are changed */
+ if (version == -2)
+ {
+ /* read in the optimal source rectangle */
+ GetRect( &grafPort.portRect );
+
+ /* use the integer portion of hRes for the resolution dpi */
+ resolution = HIWORD( hRes );
+ }
+ else
+ {
+ /* otherwise, read an unused rectangle coordinate pair */
+ GetRect( &unusedRect );
+ }
+
+ /* read the trailing unused reserved LongInt */
+ GetDWord( &unusedReserved2 );
+
+ break;
+ }
+
+ default:
+ SkipData( currOpcodeLPtr );
+ break;
+ }
+
+ /* set flag to skip ensuing font index if font name was provided */
+ skipFontID = (currOpcodeLPtr->function == FontName);
+
+ /* if global error, set opcode to opEndPic to exit main loop */
+ if (ErGetGlobalError() != NOERR)
+ {
+ currOpcodeLPtr->function = opEndPic;
+ currOpcodeLPtr->length = 0;
+ }
+
+} /* TranslateOpcode */
+
+
+
+private void SkipData( opcodeEntry far * currOpcodeLPtr )
+/*-------------------*/
+/* skip the data - the opcode won't be translated and Gdi module won't be
+ called to create anything in the metafile */
+{
+ LongInt readLength = 0;
+
+ if (currOpcodeLPtr->length >= 0)
+ {
+ IOSkipBytes( currOpcodeLPtr->length );
+ }
+ else
+ {
+ readLength = 0;
+
+ switch (currOpcodeLPtr->length)
+ {
+ case CommentSize:
+ {
+ Word unusedFunction;
+
+ GetWord( (Word far *)&unusedFunction );
+ GetWord( (Word far *)&readLength );
+ break;
+ }
+
+ case RgnOrPolyLen:
+ {
+ GetWord( (Word far *)&readLength );
+ readLength -= 2;
+ break;
+ }
+
+ case WordDataLen:
+ {
+ GetWord( (Word far *)&readLength );
+ break;
+ }
+
+ case DWordDataLen:
+ {
+ GetDWord( (DWord far *)&readLength );
+ break;
+ }
+
+ case HiByteLen:
+ {
+ readLength = (currOpcodeLPtr->function >> 8) * 2;
+ break;
+ }
+
+ } /* switch () */
+
+ IOSkipBytes( readLength );
+
+ } /* else */
+
+} /* SkipData */
+
+
+
+void OpenPort( void )
+/*-----------*/
+/* initialize the grafPort */
+{
+ /* set port version to unintialized state */
+ grafPort.portVersion = 0;
+
+ /* no polygons or regions saved yet */
+ grafPort.clipRgn = NIL;
+ grafPort.rgnSave = NIL;
+ grafPort.polySave = NIL;
+
+ /* initialize all patterns to old-style patterns */
+ grafPort.bkPixPat.patType = QDOldPat;
+ grafPort.pnPixPat.patType = QDOldPat;
+ grafPort.fillPixPat.patType = QDOldPat;
+
+ /* make patterns all solid */
+ QDCopyBytes( (Byte far *)&SolidPattern,
+ (Byte far *)&grafPort.bkPixPat.pat1Data, sizeof( Pattern ) );
+ QDCopyBytes( (Byte far *)&SolidPattern,
+ (Byte far *)&grafPort.pnPixPat.pat1Data, sizeof( Pattern ) );
+ QDCopyBytes( (Byte far *)&SolidPattern,
+ (Byte far *)&grafPort.fillPixPat.pat1Data, sizeof( Pattern ) );
+
+ /* foreground/background set to black on white */
+ grafPort.rgbFgColor = RGB( 0x00, 0x00, 0x00 ); /* black */
+ grafPort.rgbBkColor = RGB( 0xFF, 0xFF, 0xFF ); /* white */
+
+ /* various pen attributes */
+ grafPort.pnLoc.x = 0; /* pen location (0,0) */
+ grafPort.pnLoc.y = 0;
+ grafPort.pnSize.x = 1; /* pen size (1,1) */
+ grafPort.pnSize.y = 1;
+ grafPort.pnVis = 0; /* pen is visible */
+ grafPort.pnMode = QDPatCopy; /* copy ROP */
+ grafPort.pnLocHFrac = 0x00008000; /* 1/2 */
+
+ /* font attributes */
+ grafPort.txFont = 0; /* system font */
+ grafPort.txFace = 0; /* plain style */
+ grafPort.txMode = QDSrcOr;
+ grafPort.txSize = 0; /* system font size */
+ grafPort.spExtra = 0;
+ grafPort.chExtra = 0;
+ grafPort.txNumerator.x = /* text scaling ratio */
+ grafPort.txNumerator.y =
+ grafPort.txDenominator.x =
+ grafPort.txDenominator.y = 1;
+ grafPort.txRotation = 0; /* no rotation or flipping */
+ grafPort.txFlip = QDFlipNone;
+
+ /* assume 72 dpi - this may be overridden in HeaderOp opcode */
+ resolution = 72;
+
+ /* private global initialization */
+ polyMode = FALSE;
+ textMode = FALSE;
+ shadedObjectStarted = FALSE;
+ superPaintFile = FALSE;
+
+ /* text rotation variables */
+ newTextCenter = FALSE;
+ textCenter.x = textCenter.y = 0;
+
+ /* allocate space for the polygon buffer */
+ maxPoints = 16;
+ polyHandle = GlobalAlloc( GHND, (maxPoints + 3) * sizeof( Point ) );
+ if (polyHandle == NULL)
+ {
+ ErSetGlobalError( ErMemoryFull);
+ }
+ else
+ {
+ /* get pointer address and address for the polygon coordinate list */
+ numPointsLPtr = (Integer far *)GlobalLock( polyHandle );
+ polyListLPtr = (Point far *)(numPointsLPtr + POLYLIST);
+ }
+
+} /* OpenPort */
+
+
+private void ClosePort( void )
+/*--------------------*/
+/* close grafPort and de-allocate any memory blocks */
+{
+ if (grafPort.clipRgn != NULL)
+ {
+ GlobalFree( grafPort.clipRgn );
+ grafPort.clipRgn = NULL;
+ }
+
+ if (grafPort.rgnSave != NULL)
+ {
+ GlobalFree( grafPort.rgnSave );
+ grafPort.rgnSave = NULL;
+ }
+
+ if (grafPort.polySave != NULL)
+ {
+ GlobalFree( grafPort.polySave );
+ grafPort.polySave = NULL;
+ }
+
+ /* make sure that all the possible pixel pattern bitmaps are freed */
+ if (grafPort.bkPixPat.patData != NULL)
+ {
+ GlobalFree( grafPort.bkPixPat.patMap.pmTable );
+ GlobalFree( grafPort.bkPixPat.patData );
+ grafPort.bkPixPat.patData = NULL;
+ }
+
+ if (grafPort.pnPixPat.patData != NULL)
+ {
+ GlobalFree( grafPort.pnPixPat.patMap.pmTable );
+ GlobalFree( grafPort.pnPixPat.patData );
+ grafPort.pnPixPat.patData = NULL;
+ }
+
+ if (grafPort.fillPixPat.patData != NULL)
+ {
+ GlobalFree( grafPort.fillPixPat.patMap.pmTable );
+ GlobalFree( grafPort.fillPixPat.patData );
+ grafPort.fillPixPat.patData = NULL;
+ }
+
+ /* deallocate the polygon buffer */
+ GlobalUnlock( polyHandle );
+ GlobalFree( polyHandle );
+
+} /* ClosePort */
+
+
+private void NewPolygon( void )
+/*---------------------*/
+/* initialize the state of the polygon buffer - flush any previous data */
+{
+ /* initialize number of points and bounding box */
+ numPoints = 0;
+ polyBBox.left = polyBBox.top = MAXINT;
+ polyBBox.right = polyBBox.bottom = -MAXINT;
+
+} /* NewPolygon */
+
+
+private void AddPolySegment( Point start, Point end )
+/*-------------------------*/
+/* Add the line segment to the polygon buffer */
+{
+ /* make sure that we are in polygon mode before adding vertex */
+ if (polyMode == PARSEPOLY || polyMode == USEALTPOLY)
+ {
+ Point pt;
+ Byte i;
+
+ /* loop through both points ... */
+ for (i = 0; i < 2; i++)
+ {
+ /* determine which point to process */
+ pt = (i == 0) ? start : end;
+
+ /* determine if we should expect a zero delta increment in both
+ dimensions, implying that the quadratic B-spline definition will
+ actually be rendered as a straight-edged polygon */
+ if ((numPoints <= 1) || (polyMode == USEALTPOLY))
+ {
+ zeroDeltaExpected = FALSE;
+ }
+
+ /* check if we are expecting a zero delta from last point */
+ if (zeroDeltaExpected && (polyParams & CHECK4SPLINE))
+ {
+ /* make sure we are adding a zero-length line segment */
+ if ((start.x == end.x) && (start.y == end.y))
+ {
+ /* just skip including this in the polygon buffer */
+ zeroDeltaExpected = FALSE;
+ break;
+ }
+ else
+ {
+ /* MacDraw is rendering a smoothed (quadratic B-spline) - flag
+ the fact that we should use the polygon simulation */
+ polyMode = USEALTPOLY;
+ }
+ }
+ else
+ {
+ /* make sure the point is different from last point */
+ if (numPoints == 0 ||
+ polyListLPtr[numPoints - 1].x != pt.x ||
+ polyListLPtr[numPoints - 1].y != pt.y)
+ {
+ /* make sure that we haven't reached maximum size */
+ if ((numPoints + 1) >= maxPoints)
+ {
+ /* expand the number of points that can be cached by 10 */
+ maxPoints += 16;
+
+ /* unlock to prepare for re-allocation */
+ GlobalUnlock( polyHandle);
+
+ /* re-allocate the memory handle by the given amount */
+ polyHandle = GlobalReAlloc(
+ polyHandle,
+ (maxPoints + 3) * sizeof( Point ),
+ GMEM_MOVEABLE);
+
+ /* make sure that the re-allocation succeeded */
+ if (polyHandle == NULL)
+ {
+ /* if not, flag global error and exit from here */
+ ErSetGlobalError( ErMemoryFull );
+ return;
+ }
+
+ /* get new pointer addresses the polygon coordinate list */
+ numPointsLPtr = (Integer far *)GlobalLock( polyHandle );
+ polyListLPtr = (Point far *)(numPointsLPtr + POLYLIST);
+ }
+
+ /* insert the new point and increment number of points */
+ polyListLPtr[numPoints++] = pt;
+
+ /* union new point with polygon bounding box */
+ polyBBox.left = min( polyBBox.left, pt.x );
+ polyBBox.top = min( polyBBox.top, pt.y );
+ polyBBox.right = max( polyBBox.right, pt.x );
+ polyBBox.bottom = max( polyBBox.bottom, pt.y );
+
+ /* toggle the state of zeroDeltaExpected - expect same point next time */
+ zeroDeltaExpected = TRUE;
+ }
+ }
+ }
+ }
+
+} /* AddPolyPt */
+
+
+
+private void DrawPolyBuffer( void )
+/*-------------------------*/
+/* Draw the polygon definition if the points were read without errors */
+{
+ /* copy the point count and bounding box into the memory block */
+ *numPointsLPtr = sizeofMacWord + sizeofMacRect + (numPoints * sizeofMacPoint);
+ *((Rect far *)(numPointsLPtr + BBOX)) = polyBBox;
+
+ /* lock the polygon handle before rendering */
+ GlobalUnlock( polyHandle );
+
+ /* check if we should fill the polygon or if already done */
+ if ((polyParams & FILLPOLY) && (polyParams & FILLREQUIRED))
+ {
+ Boolean resetFg;
+ Boolean resetBk;
+ RGBColor saveFg;
+ RGBColor saveBk;
+
+ /* set up fore- and background colors if they have changed */
+ resetFg = (polyFgColor != grafPort.rgbFgColor);
+ resetBk = (polyBkColor != grafPort.rgbBkColor);
+
+ if (resetFg)
+ {
+ /* change the foreground color and notify Gdi of change */
+ saveFg = grafPort.rgbFgColor;
+ grafPort.rgbFgColor = polyFgColor;
+ GdiMarkAsChanged( GdiFgColor );
+ }
+ if (resetBk)
+ {
+ /* change the background color and notify Gdi of change */
+ saveBk = grafPort.rgbBkColor;
+ grafPort.rgbBkColor = polyBkColor;
+ GdiMarkAsChanged( GdiBkColor );
+ }
+
+ /* call gdi routine to draw polygon */
+ GdiPolygon( GdiFill, polyHandle );
+
+ if (resetFg)
+ {
+ /* change the foreground color and notify Gdi of change */
+ grafPort.rgbFgColor = saveFg;
+ GdiMarkAsChanged( GdiFgColor );
+ }
+ if (resetBk)
+ {
+ /* change the background color and notify Gdi of change */
+ grafPort.rgbBkColor = saveBk;
+ GdiMarkAsChanged( GdiBkColor );
+ }
+
+ }
+
+ /* should the polygon be framed? */
+ if ((polyParams & FRAMEPOLY) &&
+ (grafPort.pnSize.x != 0) && (grafPort.pnSize.y != 0))
+ {
+ /* notify gdi that this is the same primitive */
+ GdiSamePrimitive( polyParams & FILLPOLY );
+
+ GdiPolygon( GdiFrame, polyHandle );
+
+ /* notify gdi that this is no longer the same primitive */
+ GdiSamePrimitive( FALSE );
+ }
+
+ /* get pointer address and address for the polygon coordinate list */
+ numPointsLPtr = (Integer far *)GlobalLock( polyHandle );
+ polyListLPtr = (Point far *)(numPointsLPtr + POLYLIST);
+
+} /* DrawPolyBuffer */
+
+
+
+private void AdjustTextRotation( Point far * newPt )
+/*-----------------------------*/
+/* This will calculate the correct text position if text is rotated */
+{
+ if (textMode && (grafPort.txRotation != 0) &&
+ ((textCenter.x != 0) || (textCenter.y != 0)))
+ {
+ Point location;
+ Point center;
+
+ /* copy the new location to local variable */
+ location = *newPt;
+
+ /* ensure that a new text rotation was specified - recompute center */
+ if (newTextCenter)
+ {
+ Real degRadian;
+
+ /* calculate the new center of rotation */
+ center.x = textCenter.x + location.x;
+ center.y = textCenter.y + location.y;
+
+ /* calculate the sin() and cos() of the specified angle of rotation */
+ degRadian = ((Real)grafPort.txRotation * TwoPi) / 360.0;
+ degCos = cos( degRadian );
+ degSin = sin( degRadian );
+
+ /* use transformation matrix to compute offset to text center */
+ textCenter.x = (Integer)((center.x * (1.0 - degCos)) +
+ (center.y * degSin));
+
+ textCenter.y = (Integer)((center.y * (1.0 - degCos)) -
+ (center.x * degSin));
+
+ /* indicate that the new text center was computed */
+ newTextCenter = FALSE;
+ }
+
+ /* use transformation matrix to compute the new text basline location */
+ newPt->x = (Integer)((location.x * degCos) -
+ (location.y * degSin) + textCenter.x);
+ newPt->y = (Integer)((location.x * degSin) +
+ (location.y * degCos) + textCenter.y);
+ }
+
+} /* AdjustTextRotation */
+
+
+
+/****
+ *
+ * EPSComment(comment)
+ * Encapsulated PostScript Handler which translates Mac EPS to GDI EPS.
+ * This routine has intimate knowledge of the implementation of both
+ * Mac and GDI EPS filters. It processes Mac PostScript comments.
+ *
+ * returns:
+ * >0 successfully parsed EPS data
+ * 0 not EPS comment
+ * <0 error
+ *
+ * How the EPS filter works:
+ * The Mac EPS filter uses special features in the LaserWriter driver
+ * to send the PICT bounding box to the printer whre it is examined
+ * by PostScript code. The filter outputs a preamble which is a
+ * combination of QuickDraw and PostScript. This preamble is sent
+ * before the PostScript date from the EPS file. It sets the pen
+ * position for opposing corners of the PICT bounding box using
+ * QuickDraw and reads the pen position back in PostScript. Any
+ * transformations which have been set up in QuickDraw by the
+ * application to position or scale the picture will be applied
+ * to the coordinates of the bounding box sent by the preamble.
+ * PostScript code determines the transformation necessary to map the
+ * EPS bounding box onto the physical bounding box read from
+ * QuickDraw. These transformations are then applied to the PostScript
+ * picture when it is displayed.
+ *
+ * Operation of the GDI EPS filter is very similar except that it
+ * outputs a combination of GDI and PostScript.
+ *
+ * Implementation:
+ * The code can be in one of several states. Recognition of specific
+ * PostScript strings causes transition between states.
+ * PS_NONE Initial state, indicates no PostScript has been seen yet
+ * In this state, QuickDraw to GDI translation proceeds
+ * normally but PostScript data is examined.
+ * When a PostScript record is found with the string
+ * "pse\rpsb\r", the start of the PostScript preamble
+ * has been found and the program goes into state PS_PREAMBLE.
+ * PS_PREAMBLE All PostScript encountered in this state is ignored
+ * PostScript record starting with the string "[" is found.
+ * This is the PostScript bounding box specification.
+ * As soon as we see the bounding box, we have enough
+ * information to output the GDI EPS preamble and we go
+ * to state PS_BBOX.
+ * PS_BBOX PostScript is still ignored until a record beginning
+ * with "%!PS" is found, putting us into state PS_DATA.
+ * PS_DATA In this state, PostScript records are not ignored because
+ * PostScript seen now is from the EPS file. These records
+ * are translated to GDI POSTSCRIPT_DATA escapes.
+ * If the PostScript trailer "pse\rpsb\r" is encountered,
+ * it is ignored. If a PostScriptEnd comment is found
+ * it signals the end of the EPS data. We output the
+ * GDI PostScript trailer and we go back to state PS_NONE.
+ *
+ * Comment PostScriptHandle:
+ * if state == PS_NONE & data == "pse\rpsb\r"
+ * state = PS_PREAMBLE
+ * else if state == PS_PREAMBLE & data == "[ %d %d %d %d ]"
+ * state = PS_BBOX; output GDI EPS preamble
+ * else if state == PS_BBOX & data begins with "%!PS"
+ * state = PS_DATA
+ * else if state == PS_DATA
+ * if data == "pse\rpsb\r" ignore (is Mac PS trailer)
+ * else output PostScript data to GDI
+ *
+ * Comment PostScriptEnd:
+ * if state == PS_DATA
+ * state = PS_NONE; output GDI EPS trailer; exit
+ *
+ * QuickDraw primitives:
+ * translate QuickDraw to GDI normally
+ *
+ ****/
+#define PS_ERROR (-1)
+#define PS_NONE 0
+#define PS_PREAMBLE 1
+#define PS_BBOX 2
+#define PS_DATA 3
+#define PS_ENDWAIT 4
+
+private Integer EPSComment(Word comment)
+{
+static Integer state = PS_NONE;
+
+ switch (comment)
+ {
+ case picPostScriptBegin:
+ break;
+
+ case picPostScriptEnd:
+ if (state == PS_DATA)
+ {
+ GdiEPSTrailer(); // output GDI trailer
+ state = PS_NONE; // end, successful translation
+ }
+ break;
+
+ case picPostScriptHandle:
+ if ((state = EPSData(state)) < 0) // process EPS data
+ return (-1); // error during processing
+ break;
+
+ default: // not a PostScript comment
+ return (0);
+ }
+ return (1);
+}
+
+/****
+ *
+ * Integer EPSData(Integer state)
+ * Process EPS Data found in the PostScriptHandle comment.
+ * What we do with the EPS data depends on the current state
+ * we are in and what the PostScript data looks like.
+ *
+ * State PS Data Action
+ * ----------------------------------------------------------------
+ * PS_NONE PS preamble string state = PS_BEGIN
+ * PS_PREAMBLE [ ... ] state = PS_BBOX, output GDI preamble
+ * PS_BBOX %!PS state = PS_DATA
+ * PS_DATA PS preamble string ignore, is Mac PS trailer
+ * PS_DATA PS data output as GDI PS data
+ *
+ * The Mac PostScript preamble string indicates that the PostScript
+ * data was from the Mac EPS filter. It puts us into PS_PREAMBLE state
+ * where we look for the bounding box specification (which begins
+ * with "["). When this is found, we go to state PS_BBOX and output
+ * the GDI EPS preamble using the bounding box. From PS_BBOX we can
+ * go into state PS_DATA when we find the record beginning with !PS
+ * which designates the start of the read EPS data.
+ *
+ * Once in state PS_DATA, PostScript data is buffered up into GDI
+ * printer escapes and output to the GDI stream. These are the only
+ * PostScript records that are translated - all others are ignored.
+ *
+ ****/
+private Integer EPSData(Integer state)
+{
+GLOBALHANDLE h;
+PSBuf far* psbuf;
+char far* ptr;
+Word len = 0;
+Rect ps_bbox;
+
+/*
+ * Allocate a buffer for the PostScript data. The first WORD
+ * of the buffer gives the number of bytes of PostScript data.
+ * The actual data follows. This is the format needed for
+ * the GDI Escape call.
+ */
+ GetWord(&len); // length of EPS comment
+ if ((h = GlobalAlloc(GHND, (DWORD) len + sizeof(PSBuf))) == 0)
+ {
+ ErSetGlobalError(ErMemoryFull); // memory allocation error
+ return (-1);
+ }
+ psbuf = (PSBuf far *) GlobalLock(h);
+ psbuf->length = len; // save byte length
+ ptr = (char far *) &psbuf->data; // -> PostScript data
+ while (len-- != 0) GetByte(ptr++); // read PS data into buffer
+ *ptr = 0 ; // null terminate it
+ ptr = (char far *) &psbuf->data; // -> PostScript data
+
+ /* If this is a superPaint file, and postscript is being processed,
+ check if this is a situation where text could be mangled beyond
+ belief and requires adjustment in the parsing process. */
+ if (superPaintFile && state == PS_NONE)
+ {
+ char save;
+ Word start = lstrlen( SUPERPAINT_TEXTSTARTJUNK );
+ Word stop = lstrlen( SUPERPAINT_TEXTSTOPJUNK );
+
+ /* Assume that this text is OK for now */
+ badSuperPaintText = FALSE;
+
+ /* If this buffer is long enough to hold the begin and end of the bogus
+ test Postcript commands (dealing with rotation and shearin)... */
+ if (psbuf->length > (start + stop))
+ {
+ /* Create a string and compare for the beginning sequence and ending
+ sequences. Restore the null "C" terminator after finished. */
+ save = *(ptr + start);
+ *(ptr + start) = 0;
+ badSuperPaintText = (lstrcmp(ptr, SUPERPAINT_TEXTSTARTJUNK) == 0 &&
+ lstrcmp(ptr + psbuf->length - stop, SUPERPAINT_TEXTSTOPJUNK) == 0);
+ *(ptr + start) = save;
+ }
+ }
+
+/*
+ * If PostScript preamble is found in state PS_NONE we can advance to
+ * state PS_PREAMBLE. If it is found again before state PS_DATA,
+ * we have an incorrect sequence and should not translate this EPS.
+ * On the MAC, the preamble is the same as the trailer and, if found
+ * during state PS_ENDWAIT, it signals the end of EPS processing.
+ */
+ if (lstrcmp(ptr, MAC_PS_PREAMBLE) == 0)
+ switch (state)
+ {
+ case PS_NONE: // waiting for preamble
+ state = PS_PREAMBLE;
+ break;
+
+ case PS_DATA: // ignore Mac trailer
+ break;
+
+ default: // error if found in other states
+ state = PS_NONE; // abort EPS processing
+ break;
+ }
+/*
+ * PostScript date was not MAC EPS preamble. Process other states
+ */
+ else switch (state)
+ {
+ case PS_PREAMBLE: // waiting for bbox
+ if (EPSBbox(psbuf, &ps_bbox))
+ {
+ GdiEPSPreamble(&ps_bbox);
+ state = PS_BBOX; // parsed bbox, wait for EPS data
+ }
+ break;
+
+ case PS_BBOX: // waiting for !PS
+ if ((ptr[0] == '%') &&
+ (ptr[1] == '!') &&
+ (ptr[2] == 'P') &&
+ (ptr[3] == 'S'))
+ state = PS_DATA; // found start of EPS data
+ else break;
+
+ case PS_DATA: // output EPS data to GDI
+ if (lstrcmp(ptr, MAC_PS_TRAILER) != 0)
+ GdiEPSData(psbuf); // but ignore PS trailer
+ state = PS_DATA;
+ break;
+ }
+ GlobalUnlock(h);
+ GlobalFree(h); // free PostScript buffer
+ return (state);
+}
+
+/****
+ *
+ * Boolean EPSBbox(PSBuf, Rect far *)
+ * Parse EPS bounding box string [ %d %d %d %d ] and store corners
+ * of bounding box in given rectangle.
+ *
+ * returns:
+ * 0 = cannot parse bounding box descriptor
+ * 1 = bounding box successfully parsed
+ *
+ ****/
+private Boolean EPSBbox(PSBuf far *psbuf, Rect far *bbox)
+{
+char far* ptr = psbuf->data;
+
+ while ((*ptr == ' ') || (*ptr == '\t') || (*ptr == '\n'))
+ ++ptr;
+ if (*ptr++ != '[') return (0);
+ if (!(ptr = parse_number(ptr, &bbox->left))) return (0);
+ if (!(ptr = parse_number(ptr, &bbox->top))) return (0);
+ if (!(ptr = parse_number(ptr, &bbox->right))) return (0);
+ if (!(ptr = parse_number(ptr, &bbox->bottom))) return (0);
+ if (*ptr != ']') return(0);
+ return(1);
+}
+
+private char far* parse_number(char far* ptr, Integer far *iptr)
+{
+Boolean isneg = 0; // assume positive
+Integer n = 0;
+
+ while ((*ptr == ' ') || (*ptr == '\t'))
+ ++ptr; // skip whitespace
+ if (*ptr == '-') // number is negative?
+ {
+ isneg = 1;
+ ++ptr;
+ }
+ if (!IsCharDigit(*ptr)) return(0); // digit must follow
+ do n = n * 10 + (*ptr++ - '0');
+ while (IsCharDigit(*ptr));
+ if (*ptr == '.') // skip any digits following decimal pt
+ {
+ do ++ptr;
+ while (IsCharDigit(*ptr));
+ }
+ while ((*ptr == ' ') || (*ptr == '\t'))
+ ++ptr; // skip whitespace
+ if (isneg) n = -n; // remember the sign
+ *iptr = n;
+ return (ptr);
+}
diff --git a/private/ole32/olecnv32/quickdrw.h b/private/ole32/olecnv32/quickdrw.h
new file mode 100644
index 000000000..056e31e43
--- /dev/null
+++ b/private/ole32/olecnv32/quickdrw.h
@@ -0,0 +1,192 @@
+
+/****************************************************************************
+ Module Quickdrw; Interface
+*****************************************************************************
+
+ This is the main module interface to the data stream interpreter. As such,
+ it will read individual opcode elements and the appropriate data
+ parameters associated with that opocode. These are either placed into
+ the CGrafPort structure or calls are made to the Gdi module to issue
+ the correct metafile function.
+
+ Module prefix: QD
+
+****************************************************************************/
+
+/*--- Source transfer modes ---*/
+
+#define QDSrcCopy 0
+#define QDSrcOr 1
+#define QDSrcXor 2
+#define QDSrcBic 3
+#define QDNotSrcCopy 4
+#define QDNotSrcOr 5
+#define QDNotSrcXor 6
+#define QDNotSrcBic 7
+
+/*--- Pattern transfer modes ---*/
+
+#define QDPatCopy 8
+#define QDPatOr 9
+#define QDPatXor 10
+#define QDPatBic 11
+#define QDNotPatCopy 12
+#define QDNotPatOr 13
+#define QDNotPatXor 14
+#define QDNotPatBic 15
+
+/*--- Arithmetic transfer modes ---*/
+
+#define QDBlend 32
+#define QDAddPin 33
+#define QDAddOver 34
+#define QDSubPin 35
+#define QDTransparent 36
+#define QDAdMax 37
+#define QDSubOver 38
+#define QDAdMin 39
+
+/*--- Undocumented hidden transfer mode ---*/
+
+#define QDHidePen 23
+
+
+/*--- Font styles ---*/
+
+#define QDTxBold 0x01
+#define QDTxItalic 0x02
+#define QDTxUnderline 0x04
+#define QDTxOutline 0x08
+#define QDTxShadow 0x10
+#define QDTxCondense 0x20
+#define QDTxExtend 0x40
+
+
+/*--- LaserWriter Text attributes ---*/
+
+#define QDAlignNone 0x00
+#define QDAlignLeft 0x01
+#define QDAlignCenter 0x02
+#define QDAlignRight 0x03
+#define QDAlignJustified 0x04
+
+#define QDFlipNone 0x00
+#define QDFlipHorizontal 0x01
+#define QDFlipVertical 0x02
+
+
+/*--- Polygon and Region structure sizes ---*/
+
+#define PolyHeaderSize (sizeofMacWord + sizeofMacRect)
+#define RgnHeaderSize (sizeofMacWord + sizeofMacRect)
+
+/*--- PixelMap structure ---*/
+
+#define PixelMapBit 0x8000
+#define RowBytesMask 0x7FFF
+
+typedef struct
+{
+ Integer rowBytes;
+ Rect bounds;
+ Integer pmVersion;
+ Word packType;
+ LongInt packSize;
+ Fixed hRes;
+ Fixed vRes;
+ Integer pixelType;
+ Integer pixelSize;
+ Integer cmpCount;
+ Integer cmpSize;
+ LongInt planeBytes;
+ Handle pmTable;
+ Word pmTableSlop;
+ LongInt pmReserved;
+} PixMap, far * PixMapLPtr;
+
+
+/*--- Pixel Pattern structure ---*/
+
+#define QDOldPat 0
+#define QDNewPat 1
+#define QDDitherPat 2
+
+typedef Byte Pattern[8];
+
+typedef struct
+{
+ Integer patType;
+ PixMap patMap;
+ Handle patData;
+ Pattern pat1Data;
+} PixPat, far * PixPatLPtr;
+
+
+/*--- Miscellaneous type declarations ---*/
+
+#define RgnHandle Handle
+#define PixPatHandle Handle
+#define RGBColor COLORREF
+
+
+/*--- Color Table structure ---*/
+
+typedef struct
+{
+ LongInt ctSeed;
+ Word ctFlags;
+ Word ctSize;
+ RGBColor ctColors[1];
+
+} ColorTable, far * ColorTableLPtr;
+
+
+/*--- QuickDraw grafPort simulation ---*/
+
+typedef struct
+{
+ Integer portVersion;
+ Integer chExtra;
+ Integer pnLocHFrac;
+ Rect portRect;
+ RgnHandle clipRgn;
+ PixPat bkPixPat;
+ RGBColor rgbFgColor;
+ RGBColor rgbBkColor;
+ Point pnLoc;
+ Point pnSize;
+ Integer pnMode;
+ PixPat pnPixPat;
+ PixPat fillPixPat;
+ Integer pnVis;
+ Integer txFont;
+ Byte txFace;
+ Integer txMode;
+ Integer txSize;
+ Fixed spExtra;
+ Handle rgnSave;
+ Handle polySave;
+ Byte txFontName[32];
+ Point txLoc;
+ Point txNumerator;
+ Point txDenominator;
+ Integer txRotation;
+ Byte txFlip;
+
+} CGrafPort, far * CGrafPortLPtr;
+
+
+/**************************** Exported Operations ***************************/
+
+void QDConvertPicture( Handle dialogHandle );
+/* create a Windows metafile using the previously set parameters, returning
+ the converted picture information in the pictResult structure. */
+
+
+void QDGetPort( CGrafPort far * far * port );
+/* return handle to grafPort structure */
+
+
+void QDCopyBytes( Byte far * src, Byte far * dest, Integer numBytes );
+/* copy a data from source to destination */
+
diff --git a/private/ole32/olecnv32/readme.txt b/private/ole32/olecnv32/readme.txt
new file mode 100644
index 000000000..3c9ded0c3
--- /dev/null
+++ b/private/ole32/olecnv32/readme.txt
@@ -0,0 +1,10 @@
+OLECNV32.DLL
+March 28, 1994
+
+This Pict to Metafile converter is shared technology. Please see the OLE team
+before modifying it.
+
+We rely on _OLECNV32_ being defined when compiling these sources to build
+OLECNV32.DLL. This allows us to disable unused code.
+
+This code has not been unit tested yet.
diff --git a/private/ole32/olecnv32/toolbox.h b/private/ole32/olecnv32/toolbox.h
new file mode 100644
index 000000000..a56c4e696
--- /dev/null
+++ b/private/ole32/olecnv32/toolbox.h
@@ -0,0 +1,168 @@
+/************** ToolBox.h ***************************************************
+
+ The purpose of ToolBox is to isolate all the Windows vs Mac Toolbox
+ DIFFERENCES THAT WE CARE TO ISOLATE AT ALL. Always include this module
+ instead of including Windows.h or "using" MemTypes.P, etc.
+
+*****************************************************************************/
+
+#ifdef WIN32
+#define huge
+#endif
+
+/************** Includes ****************************************************/
+
+#define NOHELP /* No help engine stuff */
+#define NOSOUND /* No sound stuff */
+#define NODRAWFRAME /* No DrawFrame stuff */
+#define NOCOMM /* Disable Windows communications interface */
+#define NOKANJI /* Disable Windows Kanji support */
+#define OEMRESOURCE /* Enable access to OEM resources (checkmark, etc.) */
+
+#include "windows.h"
+
+#define sizeofMacDWord 4
+#define sizeofMacPoint 4
+#define sizeofMacRect 8
+#define sizeofMacWord 2
+
+/************** Public Data *************************************************/
+
+#define Far far /* for use with function parameters only! */
+#define Pascal /* default set with compiler options */
+
+#define NA 0L /* use for 'Not Applicable' parms */
+#define NIL NULL /* alternate name for empty pointer */
+#define cNULL '\0' /* alternate name for null char */
+#define sNULL "" /* alternate name for null string */
+#define NOERR 0 /* success flag */
+
+
+typedef unsigned Char; /* MPW unsigned char */
+typedef char SignedByte; /* MPW signed char */
+typedef int Integer; /* MPW Pascal integer. Hide int type of compiler*/
+typedef long LongInt; /* MPW Pascal name */
+typedef double Real; /* MPW Pascal name */
+typedef BYTE Byte; /* MPW Byte. Hide Win/PM unsigned char type */
+typedef unsigned Word; /* MPW Word. Hide Win/PM unsigned int type */
+typedef DWORD DWord; /* Hide Win/PM unsigned long */
+typedef LongInt Fixed; /* MPW fixed point number */
+typedef LongInt Fract; /* MPW fraction point number [-2,2) */
+typedef void * Ptr; /* MPW opaque pointer */
+typedef void far * LPtr; /* Opaque far pointer */
+typedef HANDLE Handle; /* MPW opaque handle */
+typedef char Str255[256]; /* MPW string type. 255 characters + null */
+typedef char String[]; /* Indeterminate length string */
+typedef char StringRef; /* AR: String reference type? */
+typedef NPSTR StringPtr; /* MPW string type. Hide Win/PM string pointer*/
+typedef LPSTR StringLPtr; /* Hide Win/PM string far pointer type */
+typedef HANDLE StringHandle;/* MPW string handle */
+typedef BOOL Boolean; /* MPW Pascal name */
+typedef unsigned BitBoolean; /* Boolean type that can be used as a bitfield */
+typedef RECT Rect; /* MPW rectangle structure */
+typedef POINT Point; /* MPW point structure */
+typedef DWORD Size; /* MPW size. AR: size_t if included stddef.h */
+typedef WORD Param1; /* Hide Windows/PM message param differences */
+typedef LONG Param2; /* Hide Windows/PM message param differences */
+typedef unsigned Style; /* MPW text style */
+typedef Integer Interval; /* Array/RunArray/Text intervals */
+typedef Integer OSErr; /* OS Error */
+
+typedef union
+{ Handle handle;
+ Ptr ptr;
+ LPtr lptr;
+ Word word;
+ DWord dword;
+} LongOpaque; /* A 4-byte quantity whose type is unknown */
+
+#define INDETERMINATE 1
+
+#define TwoPi (2.0*3.141592) /* math constant */
+
+/* The following macro defeats the compiler warning for unreferenced vars.
+ Use it only where a statement would be permitted in C. */
+#define UnReferenced( v ) if(v)
+
+#define private static /* alternate (understandable) name */
+
+/* largest Integer value, expressed in an implementation-independent way */
+#define MAXINT ((Integer) (((Word) -1) >> 1))
+
+/* MAXLONG is defined in winnt.h as 0x7FFFFFFF */
+#ifndef WIN32
+#define MAXLONG ((LongInt) (((DWord) -1) >> 1))
+#endif
+
+Rect NULLRECT; /* empty rectangle */
+Rect UNIRECT; /* rectangle encompassing the universe */
+Point ZEROPT; /* zero (0,0) point */
+Point UNITPT; /* unit (1,1) point */
+
+void PASCAL BreakPoint( void );
+/* Execute a software breakpoint to the debugger if it is loaded, otherwise
+ continue execution. */
+
+/* private */ void AssertionFailed( String file, Integer line, String expression );
+/* Print the fact that 'expression' was not true at 'line' in 'file' to the
+ 'logFile', then execute a software breakpoint. Treat this function as
+ private to ToolBox; it is only exported because Assert() is a macro. */
+
+#define /* void */ Assert( /* Boolean */ expression ) \
+/*=====================*/ \
+/* Provides an Assert function for use with Windows. Note that the \
+ expression in the Assert should NOT be a function/procedure call which \
+ MUST be called, since Asserts may be disabled, disabling the function or \
+ procedure call. Also note that Asserts expand inline, therefore to \
+ minimize code size in cases where several Asserts are done at once, you \
+ can code the Assert as \
+ \
+ Assert( assertion1 && assertion2 ... ); \
+ \
+ This has the drawback of possibly not fitting on a source line or \
+ localizing an assertion failure accurately enough. */ \
+{ \
+ if( !( expression ) ) \
+ AssertionFailed( _FILE_, __LINE__, #expression ); \
+} /* Assert */
+
+#define /* Size */ Sizeof( expression ) \
+/*======================*/ \
+/* Return the Size of the 'expression' */ \
+((Size) sizeof( expression ))
+
+#define /* Word */ ToWord( /*DWord*/ d ) \
+/*=====================*/ \
+( LOWORD( d ))
+
+#define /* Integer */ ToInteger( /* LongInt */ l ) \
+/*===========================*/ \
+((Integer) (LOWORD( l )))
+
+
+#define /* Boolean */ RectEqual( /* Rect */ a, /* Rect */ b ) \
+/*===========================*/ \
+/* Return TRUE iff Rect 'a' is identical to Rect 'b'. */ \
+(Boolean) EqualRect( &(a), &(b) )
+
+/* HGET(pointer, field, structure name, type)
+ * Accesses a field from a structure without using the "->"
+ * construct. This is because "->" has a bug and does not work
+ * correctly with huge pointers. Instead we use "+" and obtain
+ * the offset of the structure field by casting 0 to be a
+ * pointer to the structure. The last argument is the type of
+ * the structure field.
+ */
+#define HGET( p, f, s, t ) ( *(( t huge * ) ((( char huge * )p ) + (( WORD ) &((( s * )0 )->f )))))
+
+#define /* Integer */ Width( /* Rect */ r ) \
+/*=======================*/ \
+/* Return width of the rectangle 'r'. */ \
+((r).right - (r).left)
+
+#define /* Integer */ Height( /* Rect */ r) \
+/*========================*/ \
+/* Return height of the rectangle 'r'. */ \
+((r).bottom - (r).top)
+
+
diff --git a/private/ole32/oledbg/daytona/makefile b/private/ole32/oledbg/daytona/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ole32/oledbg/daytona/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/oledbg/daytona/oledbg.def b/private/ole32/oledbg/daytona/oledbg.def
new file mode 100644
index 000000000..e316767c3
--- /dev/null
+++ b/private/ole32/oledbg/daytona/oledbg.def
@@ -0,0 +1,11 @@
+LIBRARY oledbg
+
+DESCRIPTION 'oledbg: Ole debugger extentions'
+
+EXPORTS
+ help
+ punk
+ vtbl
+ isdbg
+
+
diff --git a/private/ole32/oledbg/daytona/sources b/private/ole32/oledbg/daytona/sources
new file mode 100644
index 000000000..b3a73f90a
--- /dev/null
+++ b/private/ole32/oledbg/daytona/sources
@@ -0,0 +1,51 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+TARGETNAME=oledbg
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+
+INCLUDES=..;..\..\..\h
+
+DLLDEF=oledbg.def
+DLLENTRY=_DllMainCRTStartup
+DLLBASE=0x1110000
+
+SOURCES= \
+ ..\oledbg.cxx
+
+
+
+TARGETLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib
+
+C_DEFINES=$(C_DEFINES) -DRPC_NO_WINDOWS_H
+
+USE_CRTDLL=1
+
+
diff --git a/private/ole32/oledbg/dirs b/private/ole32/oledbg/dirs
new file mode 100644
index 000000000..be69887d6
--- /dev/null
+++ b/private/ole32/oledbg/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Rick Sailor (Ricksa) 24-Jan-1994
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/oledbg/oledbg.cxx b/private/ole32/oledbg/oledbg.cxx
new file mode 100644
index 000000000..68dd857e1
--- /dev/null
+++ b/private/ole32/oledbg/oledbg.cxx
@@ -0,0 +1,525 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: oledbg.cxx
+//
+// Contents: OLE debugger extention DLL
+//
+// Classes:
+//
+// Functions:
+//
+// History: 8-05-94 kevinro Created
+//
+//----------------------------------------------------------------------------
+extern "C" {
+#undef DBG
+#define DBG 1
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+}
+
+#include <windows.h>
+#include <rpc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <oledbg.h>
+
+#pragma hdrstop
+
+PNTSD_EXTENSION_APIS pExtApis;
+HANDLE hDbgThread;
+HANDLE hDbgProcess;
+
+//
+char achTokenBuf[1024];
+char *pszTokenNext = NULL;
+char *pszToken = NULL;
+
+void InitTokenStr(LPSTR lpszString)
+{
+ if (lpszString)
+ {
+ strcpy(achTokenBuf,lpszString);
+ }
+ else
+ {
+ achTokenBuf[0]=0;
+ }
+
+ pszTokenNext = achTokenBuf;
+ pszToken = NULL;
+}
+
+char *NextToken()
+{
+ return(NULL);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReadMemory
+//
+// Synopsis: Reads memory from the debuggee
+//
+// Effects:
+//
+// Arguments: [pvAddress] --
+// [cbMemory] --
+// [pvLocalMemory] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 8-05-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD
+ReadMemory( PVOID pvAddress,
+ ULONG cbMemory,
+ PVOID pvLocalMemory)
+{
+ ULONG cbActual = cbMemory;
+
+ if (ReadProcessMemory(hDbgProcess, pvAddress, pvLocalMemory, cbMemory, &cbActual))
+ {
+ if (cbActual != cbMemory)
+ {
+ return((DWORD)-1);
+ }
+ return(0);
+ }
+ return(GetLastError());
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteMemory
+//
+// Synopsis: Writes memory to the debuggee
+//
+// Effects:
+//
+// Arguments: [pvLocalMemory] --
+// [cbMemory] --
+// [pvAddress] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 8-05-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD
+WriteMemory(PVOID pvLocalMemory,
+ ULONG cbMemory,
+ PVOID pvAddress)
+{
+ ULONG cbActual = cbMemory;
+
+ if (WriteProcessMemory(hDbgProcess, pvAddress, pvLocalMemory, cbMemory, &cbActual))
+ {
+ if (cbActual != cbMemory)
+ {
+ return((DWORD)-1);
+ }
+ return(0);
+ }
+ return(GetLastError());
+}
+#define AllocHeap(x) RtlAllocateHeap(RtlProcessHeap(), 0, x)
+#define FreeHeap(x) RtlFreeHeap(RtlProcessHeap(), 0, x)
+
+
+DWORD
+GetTlsEntry(ULONG TlsValue,
+ PVOID * ppvValue)
+{
+ NTSTATUS Status;
+ THREAD_BASIC_INFORMATION ThreadInfo;
+ ULONG cbReturned;
+ PVOID *Slot;
+ PTEB Teb;
+
+ Status = NtQueryInformationThread( hDbgThread,
+ ThreadBasicInformation,
+ &ThreadInfo,
+ sizeof(ThreadInfo),
+ &cbReturned);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+ Teb = (PTEB) AllocHeap(sizeof(TEB));
+
+ ReadMemory(ThreadInfo.TebBaseAddress, sizeof(TEB), Teb);
+
+ Slot = &Teb->TlsSlots[TlsValue];
+ *ppvValue = *Slot;
+
+ FreeHeap(Teb);
+
+ return(0);
+
+}
+
+void ShowBinaryData(PBYTE pData,
+ DWORD cbData)
+{
+ DWORD i;
+ char line[20];
+ PNTSD_EXTENSION_APIS lpExt = pExtApis;
+
+ line[16] = '\0';
+ if (cbData > 65536)
+ {
+ ntsdPrintf("ShowBinaryData: Data @%x is said to be %d bytes in length\n");
+ ntsdPrintf(" Rejecting request. Corrupt data\n");
+ return;
+ }
+ for (; cbData > 0 ; )
+ {
+ for (i = 0; i < 16 && cbData > 0 ; i++, cbData-- )
+ {
+ ntsdPrintf(" %02x", (unsigned) *pData);
+ if (isprint(*pData))
+ line[i] = *pData;
+ else
+ line[i] = '.';
+ pData++;
+ }
+ if (i < 16)
+ {
+ for (;i < 16 ; i++ )
+ {
+ ntsdPrintf(" ");
+ line[i] = ' ';
+ }
+ }
+ ntsdPrintf("\t%s\n",line);
+ if (lpExt->lpCheckControlCRoutine())
+ {
+ break;
+ }
+
+ }
+}
+
+
+
+BOOL
+IsDebug_olethk32()
+{
+ ULONG addr;
+ DWORD dwValue;
+ addr = ntsdGetExpr("olethk32!oledbgCheck_olethk32");
+
+ if (addr == 0)
+ {
+ ntsdPrintf("warning: olethk32 not debug version\n");
+ return(0);
+ }
+
+ if (ReadMemory((LPVOID)addr,sizeof(dwValue),(PVOID)&dwValue))
+ {
+ ntsdPrintf("warning: could not read check value at %x\n",addr);
+ return(0);
+ }
+
+ if (dwValue != 0x12345678)
+ {
+ ntsdPrintf("warning: olethk32!oledbgCheck_olethk32 value wrong\n");
+ ntsdPrintf("warning: suspect wrong symbols for olethk32\n");
+ return(0);
+ }
+ return(1);
+}
+
+
+BOOL
+IsDebug_ole32()
+{
+ ULONG addr;
+ DWORD dwValue;
+ addr = ntsdGetExpr("ole32!oledbgCheck_ole32");
+ if (addr == 0)
+ {
+ ntsdPrintf("warning: ole32 not debug version\n");
+ return(0);
+ }
+
+ if (ReadMemory((LPVOID)addr,sizeof(dwValue),(PVOID)&dwValue))
+ {
+ ntsdPrintf("warning: could not read check value at %x\n",addr);
+ return(0);
+ }
+
+ if (dwValue != 0x12345678)
+ {
+ ntsdPrintf("warning: olethk32!oledbgCheck_ole32 value wrong\n");
+ ntsdPrintf("warning: suspect wrong symbols for ole32\n");
+ return(0);
+ }
+ return(1);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DumpVtbl
+//
+// Synopsis: Dumps a vtbl to the debugger
+//
+// Effects: Given a pointer to a vtbl, output the name of the vtbl, and
+// its contents to the debugger.
+//
+// Arguments: [pvtbl] -- Address of vtbl
+// [pszCommand] -- Symbolic expression for pvtbl
+//
+// History: 8-07-94 kevinro Created
+//
+//----------------------------------------------------------------------------
+extern "C"
+void
+DumpVtbl(PVOID pvtbl, LPSTR pszCommand)
+{
+ DWORD dwVtblOffset;
+ char achNextSymbol[256];
+
+ if (pvtbl == 0)
+ {
+ // Can't handle objects at zero
+ ntsdPrintf("%s has a vtbl pointer of NULL\n",pszCommand);
+ return;
+ }
+
+ if ((DWORD)pvtbl == 0xdededede)
+ {
+ // Can't handle objects at zero
+ ntsdPrintf("%s may be deleted memory. pvtbl==0xdededede\n",pszCommand);
+ return;
+ }
+
+ // This value points at the VTBL. Find a symbol for the VTBL
+ ntsdGetSymbol((LPVOID)pvtbl,(UCHAR *)achNextSymbol,(LPDWORD)&dwVtblOffset);
+
+ // If the dwVtblOffset is not zero, then we are pointing into the table.
+ // This could mean multiple inheritance. We could be tricky, and try to
+ // determine the vtbl by backing up here. Maybe later
+ if (dwVtblOffset != 0)
+ {
+ ntsdPrintf("Closest Previous symbol is %s at 0x%x (offset -0x%x)\n",
+ achNextSymbol,
+ (DWORD)pvtbl - dwVtblOffset,
+ dwVtblOffset);
+ return;
+ }
+ ntsdPrintf("0x%08x -->\t %s\n",pvtbl,achNextSymbol);
+ // vtbl entries should always point at functions. Therefore, we should
+ // always have a displacement of zero. To check for the end of the table
+ // we will reevaluate the vtbl pointer. If the offset isn't what we
+ // expected, then we are done.
+
+ DWORD dwIndex;
+ for (dwIndex = 0 ; dwIndex < 4096 ; dwIndex += 4)
+ {
+ DWORD dwVtblEntry;
+
+ ntsdGetSymbol((LPVOID)((DWORD)pvtbl+dwIndex),
+ (UCHAR *)achNextSymbol,
+ (LPDWORD)&dwVtblOffset);
+
+ if (dwVtblOffset != dwIndex)
+ {
+ //
+ // May have moved on to another vtable
+ //
+#ifdef DBG_OLEDBG
+ ntsdPrintf("?? %s + %x\n",achNextSymbol,dwVtblOffset);
+ ntsdPrintf("Moved to another table?\n");
+#endif
+ return;
+ }
+
+ if (ReadMemory((LPVOID)((DWORD)pvtbl+dwIndex),
+ sizeof(dwVtblEntry),
+ (PVOID)&dwVtblEntry))
+ {
+ //
+ // Must be off the end of a page or something.
+ //
+#ifdef DBG_OLEDBG
+ ntsdPrintf("End of page?\n");
+#endif
+ return;
+ }
+
+ // If the function is at zero, then must be at end of table
+ if (dwVtblEntry == 0)
+ {
+#ifdef DBG_OLEDBG
+ ntsdPrintf("dwVtblEntry is zero. Must be end of table\n");
+ return;
+#endif
+
+ }
+
+ // Now, determine the symbol for the entry in the vtbl
+ ntsdGetSymbol((LPVOID)dwVtblEntry,
+ (UCHAR *)achNextSymbol,
+ (LPDWORD)&dwVtblOffset);
+
+ // If it doesn't point to the start of a routine, then it
+ // probably isn't part of the vtbl
+ if (dwVtblOffset != 0)
+ {
+#ifdef DBG_OLEDBG
+ ntsdPrintf("?? %s + %x\n",achNextSymbol,dwVtblOffset);
+ ntsdPrintf("Doesn't point to function?\n");
+#endif
+ return;
+ }
+
+ ntsdPrintf(" 0x%08x\t %s\n",dwVtblEntry,achNextSymbol);
+ }
+ ntsdPrintf("Wow, there were at least 1024 entries in the table!\n");
+
+}
+
+extern "C"
+void
+punk( HANDLE hProcess,
+ HANDLE hThread,
+ DWORD dwCurrentPc,
+ PNTSD_EXTENSION_APIS lpExt,
+ LPSTR pszCommand)
+{
+ PVOID punk;
+ PVOID pvtbl;
+
+ InitDebugHelp(hProcess, hThread, lpExt);
+
+ // Evalute the first pointer. This is a pointer to the object
+ punk = (PVOID) ntsdGetExpr(pszCommand);
+
+ if (punk == NULL)
+ {
+ // Can't handle objects at zero
+ ntsdPrintf("%s is not a valid pointer\n",pszCommand);
+ return;
+ }
+ // Now, read the first DWORD of this memory location
+ // This is a pointer to the table
+ if (ReadMemory(punk,sizeof(pvtbl),(PVOID)&pvtbl))
+ {
+ ntsdPrintf("Couldn't read memory at %x\n",punk);
+ return;
+ }
+
+ DumpVtbl(pvtbl,pszCommand);
+
+}
+extern "C"
+void
+vtbl( HANDLE hProcess,
+ HANDLE hThread,
+ DWORD dwCurrentPc,
+ PNTSD_EXTENSION_APIS lpExt,
+ LPSTR pszCommand)
+{
+ PVOID pvtbl;
+
+ InitDebugHelp(hProcess, hThread, lpExt);
+
+ // Evalute the first pointer. This is a pointer to the table
+ pvtbl = (PVOID) ntsdGetExpr(pszCommand);
+ DumpVtbl(pvtbl,pszCommand);
+}
+
+extern "C"
+void
+expr( HANDLE hProcess,
+ HANDLE hThread,
+ DWORD dwCurrentPc,
+ PNTSD_EXTENSION_APIS lpExt,
+ LPSTR pszCommand)
+{
+ InitDebugHelp(hProcess, hThread, lpExt);
+
+ UCHAR symbol[256];
+ DWORD expr;
+ DWORD disp;
+
+ expr = ntsdGetExpr(pszCommand);
+
+ ntsdGetSymbol((LPVOID)expr,(UCHAR *)symbol,(LPDWORD)&disp);
+
+ ntsdPrintf("expr: %s = %x (%d) %s + %d\n",pszCommand,expr,expr,symbol,disp);
+
+}
+
+extern "C"
+void
+isdbg( HANDLE hProcess,
+ HANDLE hThread,
+ DWORD dwCurrentPc,
+ PNTSD_EXTENSION_APIS lpExt,
+ LPSTR pszCommand)
+{
+
+ InitDebugHelp(hProcess, hThread, lpExt);
+
+ if (IsDebug_ole32())
+ {
+ ntsdPrintf("ole32.dll is debug\n");
+ }
+ if (IsDebug_olethk32())
+ {
+ ntsdPrintf("olethk32.dll is debug\n");
+ }
+}
+
+extern "C"
+void
+help( HANDLE hProcess,
+ HANDLE hThread,
+ DWORD dwCurrentPc,
+ PNTSD_EXTENSION_APIS lpExt,
+ LPSTR pszCommand)
+{
+
+ InitDebugHelp(hProcess, hThread, lpExt);
+
+ ntsdPrintf(" help \tThis Message\n");
+ ntsdPrintf(" isdbg \tDetermine if DLL's are debug\n");
+ ntsdPrintf(" punk <expr> \tDump IUnknown vtbl\n");
+ ntsdPrintf(" vtbl <expr> \tDump vtbl\n");
+
+}
diff --git a/private/ole32/oledbg/oledbg.h b/private/ole32/oledbg/oledbg.h
new file mode 100644
index 000000000..9e8845bc6
--- /dev/null
+++ b/private/ole32/oledbg/oledbg.h
@@ -0,0 +1,40 @@
+//+-----------------------------------------------------------------------
+//
+// Microsoft Windows
+//
+// Copyright (c) Microsoft Corporation 1991 - 1992
+//
+// File:
+//
+// Contents:
+//
+//
+// History:
+//
+//------------------------------------------------------------------------
+
+#include <ntsdexts.h>
+
+
+extern "C" PNTSD_EXTENSION_APIS pExtApis;
+extern "C" HANDLE hDbgThread;
+extern "C" HANDLE hDbgProcess;
+extern "C" char *pszToken;
+extern "C" char *pszTokenNext;
+
+
+#define ntsdPrintf (pExtApis->lpOutputRoutine)
+#define ntsdGetSymbol (pExtApis->lpGetSymbolRoutine)
+#define ntsdGetExpr (pExtApis->lpGetExpressionRoutine)
+#define ntsdCheckC (pExtApis->lpCheckControlCRoutine)
+
+#define InitDebugHelp(hProc,hThd,pApis) {hDbgProcess = hProc; hDbgThread = hThd; pExtApis = pApis;}
+
+extern void InitTokenStr(LPSTR lpzString);
+extern DWORD ReadMemory( PVOID pvAddress, ULONG cbMemory, PVOID pvLocalMemory);
+extern DWORD WriteMemory(PVOID pvLocalMemory, ULONG cbMemory, PVOID pvAddress);
+extern void ShowBinaryData(PBYTE pData,DWORD cbData);
+extern BOOL IsDebug_olethk32();
+extern BOOL IsDebug_ole32();
+
+
diff --git a/private/ole32/oledbg/sources.inc b/private/ole32/oledbg/sources.inc
new file mode 100644
index 000000000..9a091ed81
--- /dev/null
+++ b/private/ole32/oledbg/sources.inc
@@ -0,0 +1 @@
+SYNCHRONIZE_DRAIN=1
diff --git a/private/ole32/oleprx32/dirs b/private/ole32/oleprx32/dirs
new file mode 100644
index 000000000..6e63533cd
--- /dev/null
+++ b/private/ole32/oleprx32/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Greg Jensenworth (GregJen) 11-08-94
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS= \
+ idl \
+ proxy \
+ wdt
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS=
diff --git a/private/ole32/oleprx32/idl/daytona/makefile b/private/ole32/oleprx32/idl/daytona/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ole32/oleprx32/idl/daytona/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/oleprx32/idl/daytona/makefile.inc b/private/ole32/oleprx32/idl/daytona/makefile.inc
new file mode 100644
index 000000000..10da92632
--- /dev/null
+++ b/private/ole32/oleprx32/idl/daytona/makefile.inc
@@ -0,0 +1,65 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Greg Jensenworth
+
+
+!ENDIF
+
+
+SDKINC=$(_NTDRIVE)$(_NTROOT)\public\sdk\inc
+DCOMIDL=$(_NTDRIVE)$(_NTROOT)\private\dcomidl
+
+unknwn.idl : $(SDKINC)\unknwn.idl
+ -erase proxy\unknwn_p.c
+ copy $(SDKINC)\unknwn.idl .
+
+objidl.idl : $(SDKINC)\objidl.idl
+ -erase proxy\objidl_p.c
+ copy $(SDKINC)\objidl.idl .
+
+oleidl.idl : $(SDKINC)\oleidl.idl
+ -erase proxy\oleidl_p.c
+ copy $(SDKINC)\oleidl.idl .
+
+oaidl.idl : $(SDKINC)\oaidl.idl
+ -erase proxy\oaidl_p.c
+ copy $(SDKINC)\oaidl.idl .
+
+srvhdl.idl : $(SDKINC)\srvhdl.idl
+ -erase proxy\srvhdl_p.c
+ copy $(SDKINC)\srvhdl.idl .
+
+
+remunk.idl : $(DCOMIDL)\remunk.idl
+ -erase proxy\remunk_p.c
+ copy $(DCOMIDL)\remunk.idl .
+
+..\proxy\unknwn_p.c : unknwn.idl
+
+..\proxy\objidl_p.c : objidl.idl
+
+..\proxy\oleidl_p.c : oleidl.idl
+
+..\proxy\oaidl_p.c : oaidl.idl
+
+..\proxy\srvhdl_p.c : srvhdl.idl
+
+..\proxy\remunk_p.c : remunk.idl
+
+..\proxy\connct_p.c : connct.idl
diff --git a/private/ole32/oleprx32/idl/daytona/mega.idl b/private/ole32/oleprx32/idl/daytona/mega.idl
new file mode 100644
index 000000000..e6cc3663c
--- /dev/null
+++ b/private/ole32/oleprx32/idl/daytona/mega.idl
@@ -0,0 +1,26 @@
+
+// a giant mega idl file to put the whole proxy together
+
+#define DO_NO_IMPORTS
+#define __INCLUDE_CPIFS
+
+import "wtypes.idl";
+
+#include "unknwn.idl"
+
+#include "objidl.idl"
+
+#include "oleidl.idl"
+
+//#include "oaidl.idl"
+
+#include "srvhdl.idl"
+
+#ifdef DCOM
+// internal interfaces used by DCOM
+#include "oleprv.idl"
+#endif
+
+#ifdef ASYNC
+#include "iconn.idl"
+#endif
diff --git a/private/ole32/oleprx32/idl/daytona/sources b/private/ole32/oleprx32/idl/daytona/sources
new file mode 100644
index 000000000..5d536d4d2
--- /dev/null
+++ b/private/ole32/oleprx32/idl/daytona/sources
@@ -0,0 +1,49 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Greg Jensenworth
+
+
+!ENDIF
+
+
+
+MAJORCOMP=cairo
+MINORCOMP=types
+
+C_DEFINES= -DWIN32=300 -D_CAIRO_=300 -DDCOM -DASYNC
+
+TARGETPATH=obj
+TARGETTYPE=NOTARGET
+
+SYNCHRONIZE_BLOCK=1
+
+SDKINC=$(BASEDIR)\public\sdk\inc
+
+PASS0_HEADERDIR=obj
+PASS0_SOURCEDIR=..\..\proxy\daytona
+MIDL_UUIDDIR=..\..\proxy\daytona
+
+MIDL_FLAGS=-hookole -no_format_opt
+
+INCLUDES=$(SDKINC)
+INCLUDES=$(INCLUDES);..\..\..\com\dcomidl;$(BASEDIR)\private\dcomidl
+INCLUDES=$(INCLUDES);..\..\..\stg\async\docfile
+
+SOURCES= \
+ mega.idl
diff --git a/private/ole32/oleprx32/idl/dirs b/private/ole32/oleprx32/idl/dirs
new file mode 100644
index 000000000..970cad00d
--- /dev/null
+++ b/private/ole32/oleprx32/idl/dirs
@@ -0,0 +1,37 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Greg Jensenworth (GregJen) 11-08-94
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ daytona \
+
diff --git a/private/ole32/oleprx32/makefil0 b/private/ole32/oleprx32/makefil0
new file mode 100644
index 000000000..4bcc3016c
--- /dev/null
+++ b/private/ole32/oleprx32/makefil0
@@ -0,0 +1,15 @@
+!include $(NTMAKEENV)\makefile.plt
+
+
+all:
+!IF "$(BUILDMSG)" != ""
+ @ech ; $(BUILDMSG) ;
+!ENDIF
+
+clean: cleanall all
+
+cleanall:
+ erase idl\objidl.idl idl\oaidl.idl idl\unknwn.idl idl\oleidl.idl >NUL 2>NUL
+ erase proxy\objidl_p.c proxy\oaidl_p.c proxy\unknwn_p.c proxy\oleidl_p.c >NUL 2>NUL
+ erase proxy\dlldata.c >NUL 2>NUL
+
diff --git a/private/ole32/oleprx32/proxy/bstr.cxx b/private/ole32/oleprx32/proxy/bstr.cxx
new file mode 100644
index 000000000..1bcf19638
--- /dev/null
+++ b/private/ole32/oleprx32/proxy/bstr.cxx
@@ -0,0 +1,224 @@
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ bstr.cxx
+
+Abstract:
+
+ Windows Data Type Support by means of [user_marshal] attribute.
+
+ Covers:
+ BSTR
+
+
+Author:
+
+ Bill Morel (billmo) Oct 14, 1995
+
+ These routines provide [wire_marshal] support for BSTRs.
+
+Revision History:
+
+ 14-Jun-96 MikeHill Converted to use the new PrivSysAllocString,
+ PrivSysReAllocString, & PrivSysFreeString routines
+ (defined elsewhere in OLE32).
+
+-------------------------------------------------------------------*/
+
+
+//#include "stdrpc.hxx"
+#pragma hdrstop
+
+#include <wtypes.h>
+#include "transmit.h"
+#include <privoa.h> // PrivSys* routines
+
+// round up string alloc requests to nearest N-byte boundary, since allocator
+// will round up anyway. Improves cache hits.
+//
+// UNDONE: optimal for Chicago is 4
+// UNDONE: optimal for Daytona is 32
+// UNDONE: 4 didn't help the a$ = a$ + "x" case at all.
+// UNDONE: 8 did (gave 50% cache hit)
+//
+#define WIN32_ALLOC_ALIGN (4 - 1)
+#define DEFAULT_ALLOC_ALIGN (2 - 1)
+
+
+/***
+*unsigned int PrivSysStringByteLen(BSTR)
+*Purpose:
+* return the length in bytes of the given BSTR.
+*
+*Entry:
+* bstr = the BSTR to return the length of
+*
+*Exit:
+* return value = unsigned int, length in bytes.
+*
+***********************************************************************/
+
+// #########################################################################
+//
+// BSTR
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: BSTR_UserSize
+//
+// Synopsis: Get the wire size for the BSTR handle and data.
+//
+// Derivation: Conformant struct with a flag field:
+// align + 12 + data size.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+BSTR_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ BSTR * pBstr)
+{
+ // Null bstr doesn't get marshalled.
+
+ if ( pBstr == NULL || *pBstr == NULL )
+ return Offset;
+
+ unsigned long ulDataSize;
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ // Takes the byte length of a unicode string
+
+ ulDataSize = PrivSysStringByteLen( *pBstr );
+
+ return( Offset + 12 + ulDataSize) ;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: BSTR_UserMarshall
+//
+// Synopsis: Marshalls an BSTR object into the RPC buffer.
+//
+// Derivation: Conformant struct with a flag field:
+// align, size, null flag, size, data (bytes, if any)
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+BSTR_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ BSTR * pBstr)
+{
+ // A null Bstr is not marshalled, the engine will take care of it.
+
+ if ( pBstr == NULL || *pBstr == NULL )
+ return pBuffer;
+
+ unsigned long ulDataSize;
+
+ // Data size (in bytes): a null bstr gets a data size of zero.
+
+ ulDataSize = PrivSysStringByteLen( *pBstr );
+
+ // Conformant size.
+
+ ALIGN( pBuffer, 3 );
+ *( PULONG_LV_CAST pBuffer)++ = (ulDataSize >> 1);
+
+ // FLAGGED_WORD_BLOB: Handle is the null/non-null flag
+
+ *( PULONG_LV_CAST pBuffer)++ = (unsigned long)*pBstr;
+
+ // Length on wire is in words.
+
+ *( PULONG_LV_CAST pBuffer)++ = (ulDataSize >> 1);
+
+ if( ulDataSize )
+ {
+ // we don't put the terminating string on wire
+
+ WdtpMemoryCopy( pBuffer, *pBstr, ulDataSize );
+ }
+
+ return( pBuffer + ulDataSize );
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: BSTR_UserUnmarshall
+//
+// Synopsis: Unmarshalls an BSTR object from the RPC buffer.
+//
+// Derivation: Conformant struct with a flag field:
+// align, size, null flag, size, data (bytes, if any)
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+BSTR_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ BSTR * pBstr)
+{
+ unsigned long ulDataSize, fHandle;
+ BSTR Bstr = NULL; // Default to NULL BSTR
+
+ ALIGN( pBuffer, 3 );
+
+ ulDataSize = *( PULONG_LV_CAST pBuffer)++;
+ fHandle = *(ulong *)pBuffer;
+ pBuffer += 8;
+
+ if ( fHandle )
+ {
+ // Length on wire is in words, and the string is unicode.
+
+ if ( *pBstr &&
+ *(((ulong *)*pBstr) -1) == (ulDataSize << 1) )
+ WdtpMemoryCopy( *pBstr, pBuffer, (ulDataSize << 1) );
+ else
+ {
+ if (!PrivSysReAllocStringLen( pBstr,
+ (OLECHAR *)pBuffer,
+ ulDataSize ))
+ RpcRaiseException( E_OUTOFMEMORY );
+ }
+ }
+ else
+ {
+ // free the old one, make it NULL.
+
+ PrivSysFreeString( *pBstr );
+ *pBstr = NULL;
+ }
+
+ return( pBuffer + (ulDataSize << 1) );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: BSTR_UserFree
+//
+// Synopsis: Free an BSTR.
+//
+//--------------------------------------------------------------------------
+void __RPC_USER
+BSTR_UserFree(
+ unsigned long * pFlags,
+ BSTR * pBstr)
+{
+ if( pBstr && *pBstr )
+ {
+ PrivSysFreeString(* pBstr);
+ *pBstr = NULL;
+ }
+}
diff --git a/private/ole32/oleprx32/proxy/call_as.c b/private/ole32/oleprx32/proxy/call_as.c
new file mode 100644
index 000000000..06be2ae02
--- /dev/null
+++ b/private/ole32/oleprx32/proxy/call_as.c
@@ -0,0 +1,3003 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994 - 1996.
+//
+// File: call_as.c
+//
+// Contents: [call_as] wrapper functions for COMMON\types.
+//
+// Functions: IAdviseSink2_OnLinkSrcChange_Proxy
+// IAdviseSink2_OnLinkSrcChange_Stub
+// IAdviseSink_OnDataChange_Proxy
+// IAdviseSink_OnDataChange_Stub
+// IAdviseSink_OnViewChange_Proxy
+// IAdviseSink_OnViewChange_Stub
+// IAdviseSink_OnRename_Proxy
+// IAdviseSink_OnRename_Stub
+// IAdviseSink_OnSave_Proxy
+// IAdviseSink_OnSave_Stub
+// IAdviseSink_OnClose_Proxy
+// IAdviseSink_OnClose_Stub
+// IBindCtx_GetBindOptions_Proxy
+// IBindCtx_GetBindOptions_Stub
+// IBindCtx_SetBindOptions_Proxy
+// IBindCtx_SetBindOptions_Stub
+// IClassFactory_CreateInstance_Proxy
+// IClassFactory_CreateInstance_Stub
+// IDataObject_GetData_Proxy
+// IDataObject_GetData_Stub
+// IDataObject_GetDataHere_Proxy
+// IDataObject_GetDataHere_Stub
+// IDataObject_SetData_Proxy
+// IDataObject_SetData_Stub
+// IEnumConnectionPoints_Next_Proxy
+// IEnumConnectionPoints_Next_Stub
+// IEnumConnections_Next_Proxy
+// IEnumConnections_Next_Stub
+// IEnumFORMATETC_Next_Proxy
+// IEnumFORMATETC_Next_Stub
+// IEnumMoniker_Next_Proxy
+// IEnumMoniker_Next_Stub
+// IEnumSTATDATA_Next_Proxy
+// IEnumSTATDATA_Next_Stub
+// IEnumSTATSTG_Next_Proxy
+// IEnumSTATSTG_Next_Stub
+// IEnumString_Next_Proxy
+// IEnumString_Next_Stub
+// IEnumUnknown_Next_Proxy
+// IEnumUnknown_Next_Stub
+// IEnumOLEVERB_Next_Proxy
+// IEnumOLEVERB_Next_Stub
+// ILockBytes_ReadAt_Proxy
+// ILockBytes_ReadAt_Stub
+// ILockBytes_WriteAt_Proxy
+// ILockBytes_WriteAt_Stub
+// IMoniker_BindToObject_Proxy
+// IMoniker_BindToObject_Stub
+// IMoniker_BindToStorage_Proxy
+// IMoniker_BindToStorage_Stub
+// IClientSiteHandler_PrivQueryInterface_Proxy
+// IClientSiteHandler_PrivQueryInterface_Stub
+// IOleInPlaceActiveObject_TranslateAccelerator_Proxy
+// IOleInPlaceActiveObject_TranslateAccelerator_Stub
+// IOleInPlaceActiveObject_ResizeBorder_Proxy
+// IOleInPlaceActiveObject_ResizeBorder_Stub
+// IOleItemContainer_GetObject_Proxy
+// IOleItemContainer_GetObject_Stub
+// IOleItemContainer_GetObjectStorage_Proxy
+// IOleItemContainer_GetObjectStorage_Stub
+// IRunnableObject_IsRunning_Proxy
+// IRunnableObject_IsRunning_Stub
+// IStorage_OpenStream_Proxy
+// IStorage_OpenStream_Stub
+// IStorage_EnumElements_Proxy
+// IStorage_EnumElements_Stub
+// ISequentialStream_Read_Proxy
+// ISequentialStream_Read_Stub
+// IStream_Seek_Proxy
+// IStream_Seek_Stub
+// ISequentialStream_Write_Proxy
+// ISequentialStream_Write_Stub
+// IStream_CopyTo_Proxy
+// IStream_CopyTo_Stub
+// IOverlappedStream_ReadOverlapped_Proxy
+// IOverlappedStream_ReadOverlapped_Stub
+// IOverlappedStream_WriteOverlapped_Proxy
+// IOverlappedStream_WriteOverlapped_Stub
+// IEnumSTATPROPSTG_Next_Proxy
+// IEnumSTATPROPSTG_Next_Stub
+// IEnumSTATPROPSETSTG_Next_Proxy
+// IEnumSTATPROPSETSTG_Next_Stub
+//
+//
+// History: May-01-94 ShannonC Created
+// Jul-10-94 ShannonC Fix memory leak (bug #20124)
+// Aug-09-94 AlexT Add ResizeBorder proxy, stub
+// Apr-25-95 RyszardK Rewrote STGMEDIUM support
+// Nov-03-95 JohannP Added IClientSite proxy, stub
+//
+//--------------------------------------------------------------------------
+
+#include <rpcproxy.h>
+#include <debnot.h>
+#include "mega.h"
+#include "transmit.h"
+
+#pragma code_seg(".orpc")
+
+#define ASSERT(expr) Win4Assert(expr)
+
+HRESULT CreateCallback(
+ BOOL (STDMETHODCALLTYPE *pfnContinue)(DWORD dwContinue),
+ DWORD dwContinue,
+ IContinue **ppContinue);
+
+//+-------------------------------------------------------------------------
+//
+// Function: IAdviseSink2_OnLinkSrcChange_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IAdviseSink2::OnLinkSrcChange.
+//
+// Returns: void
+//
+//--------------------------------------------------------------------------
+void STDMETHODCALLTYPE IAdviseSink2_OnLinkSrcChange_Proxy(
+ IAdviseSink2 __RPC_FAR * This,
+ IMoniker __RPC_FAR *pmk)
+{
+ __try
+ {
+ IAdviseSink2_RemoteOnLinkSrcChange_Proxy(This, pmk);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Just ignore the exception.
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IAdviseSink2_OnLinkSrcChange_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IAdviseSink2::OnLinkSrcChange.
+//
+// Returns: S_OK
+//
+//--------------------------------------------------------------------------
+void STDMETHODCALLTYPE IAdviseSink2_OnLinkSrcChange_Stub(
+ IAdviseSink2 __RPC_FAR * This,
+ IMoniker __RPC_FAR *pmk)
+{
+ This->lpVtbl->OnLinkSrcChange(This, pmk);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IAdviseSink_OnDataChange_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IAdviseSink::OnDataChange.
+// pMedium is [in].
+//
+// Returns: void
+//
+//--------------------------------------------------------------------------
+void STDMETHODCALLTYPE IAdviseSink_OnDataChange_Proxy(
+ IAdviseSink __RPC_FAR * This,
+ FORMATETC __RPC_FAR *pFormatetc,
+ STGMEDIUM __RPC_FAR *pStgmed)
+{
+ UserNdrDebugOut((UNDR_FORCE, "==OnDataChange_Proxy\n"));
+
+ __try
+ {
+ IAdviseSink_RemoteOnDataChange_Proxy(This, pFormatetc, pStgmed);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Just ignore the exception.
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IAdviseSink_OnDataChange_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IAdviseSink::OnDataChange.
+// pMedium is [in].
+//
+// Returns: S_OK
+//
+//--------------------------------------------------------------------------
+void STDMETHODCALLTYPE IAdviseSink_OnDataChange_Stub(
+ IAdviseSink __RPC_FAR * This,
+ FORMATETC __RPC_FAR *pFormatetc,
+ STGMEDIUM __RPC_FAR *pMedium)
+{
+ UserNdrDebugOut((UNDR_FORCE, "==OnDataChange_Stub\n"));
+
+ This->lpVtbl->OnDataChange(This, pFormatetc, pMedium);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IAdviseSink_OnViewChange_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IAdviseSink::OnViewChange.
+//
+// Returns: void
+//
+//--------------------------------------------------------------------------
+void STDMETHODCALLTYPE IAdviseSink_OnViewChange_Proxy(
+ IAdviseSink __RPC_FAR * This,
+ DWORD dwAspect,
+ LONG lindex)
+{
+ __try
+ {
+ IAdviseSink_RemoteOnViewChange_Proxy(This, dwAspect, lindex);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Just ignore the exception.
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IAdviseSink_OnViewChange_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IAdviseSink::OnViewChange.
+//
+// Returns: S_OK
+//
+//--------------------------------------------------------------------------
+void STDMETHODCALLTYPE IAdviseSink_OnViewChange_Stub(
+ IAdviseSink __RPC_FAR * This,
+ DWORD dwAspect,
+ LONG lindex)
+{
+ This->lpVtbl->OnViewChange(This, dwAspect, lindex);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IAdviseSink_OnRename_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IAdviseSink::OnRename.
+//
+// Returns: void
+//
+//--------------------------------------------------------------------------
+void STDMETHODCALLTYPE IAdviseSink_OnRename_Proxy(
+ IAdviseSink __RPC_FAR * This,
+ IMoniker __RPC_FAR *pmk)
+{
+ __try
+ {
+ IAdviseSink_RemoteOnRename_Proxy(This, pmk);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Just ignore the exception.
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IAdviseSink_OnRename_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IAdviseSink::OnRename_Stub.
+//
+// Returns: S_OK
+//
+//--------------------------------------------------------------------------
+void STDMETHODCALLTYPE IAdviseSink_OnRename_Stub(
+ IAdviseSink __RPC_FAR * This,
+ IMoniker __RPC_FAR *pmk)
+{
+ This->lpVtbl->OnRename(This, pmk);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IAdviseSink_OnSave_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IAdviseSink::OnSave.
+//
+// Returns: void
+//
+//--------------------------------------------------------------------------
+void STDMETHODCALLTYPE IAdviseSink_OnSave_Proxy(
+ IAdviseSink __RPC_FAR * This)
+{
+ __try
+ {
+ IAdviseSink_RemoteOnSave_Proxy(This);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Just ignore the exception.
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IAdviseSink_OnSave_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IAdviseSink::OnSave.
+//
+// Returns: S_OK
+//
+//--------------------------------------------------------------------------
+void STDMETHODCALLTYPE IAdviseSink_OnSave_Stub(
+ IAdviseSink __RPC_FAR * This)
+{
+ This->lpVtbl->OnSave(This);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IAdviseSink_OnClose_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IAdviseSink::OnClose.
+//
+// Returns: void
+//
+//--------------------------------------------------------------------------
+void STDMETHODCALLTYPE IAdviseSink_OnClose_Proxy(
+ IAdviseSink __RPC_FAR * This)
+{
+ __try
+ {
+ // ignore the HRESULT return
+ IAdviseSink_RemoteOnClose_Proxy(This);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ //Just ignore the exception.
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IAdviseSink_OnClose_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IAdviseSink::OnClose.
+//
+// Returns: S_OK
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IAdviseSink_OnClose_Stub(
+ IAdviseSink __RPC_FAR * This)
+{
+ This->lpVtbl->OnClose(This);
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IBindCtx_GetBindOptions_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IBindCtx::GetBindOptions.
+//
+// Returns: S_OK
+//
+// Notes: If the caller's BIND_OPTS is smaller than the current
+// BIND_OPTS definition, then we must truncate the results
+// so that we don't go off the end of the structure.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IBindCtx_GetBindOptions_Proxy(
+ IBindCtx __RPC_FAR * This,
+ BIND_OPTS __RPC_FAR *pbindopts)
+{
+ HRESULT hr;
+
+ if(pbindopts->cbStruct >= sizeof(BIND_OPTS2))
+ {
+ hr = IBindCtx_RemoteGetBindOptions_Proxy(This, (BIND_OPTS2 *) pbindopts);
+ }
+ else
+ {
+ BIND_OPTS2 bindOptions;
+
+ //The pbindopts supplied by the caller is too small.
+ //We need a BIND_OPTS2 for the marshalling code.
+ memset(&bindOptions, 0, sizeof(BIND_OPTS2));
+ memcpy(&bindOptions, pbindopts, pbindopts->cbStruct);
+
+ hr = IBindCtx_RemoteGetBindOptions_Proxy(This, &bindOptions);
+
+ if(SUCCEEDED(hr))
+ {
+ memcpy(pbindopts, &bindOptions, bindOptions.cbStruct);
+ }
+ }
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IBindCtx_GetBindOptions_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IBindCtx::GetBindOptions.
+//
+// Returns: S_OK
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IBindCtx_GetBindOptions_Stub(
+ IBindCtx __RPC_FAR * This,
+ BIND_OPTS2 __RPC_FAR *pbindopts)
+{
+ HRESULT hr;
+
+ //make sure we don't request more data than we can handle.
+ if(pbindopts->cbStruct > sizeof(BIND_OPTS2))
+ {
+ pbindopts->cbStruct = sizeof(BIND_OPTS2);
+ }
+
+ hr = This->lpVtbl->GetBindOptions(This, (BIND_OPTS *)pbindopts);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IBindCtx_SetBindOptions_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IBindCtx::SetBindOptions.
+//
+// Returns: S_OK
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IBindCtx_SetBindOptions_Proxy(
+ IBindCtx __RPC_FAR * This,
+ BIND_OPTS __RPC_FAR *pbindopts)
+{
+ HRESULT hr;
+
+ if(sizeof(BIND_OPTS2) == pbindopts->cbStruct)
+ {
+ hr = IBindCtx_RemoteSetBindOptions_Proxy(This, (BIND_OPTS2 *) pbindopts);
+ }
+ else if(sizeof(BIND_OPTS2) > pbindopts->cbStruct)
+ {
+ BIND_OPTS2 bindOptions;
+
+ memset(&bindOptions, 0, sizeof(bindOptions));
+ memcpy(&bindOptions, pbindopts, pbindopts->cbStruct);
+ hr = IBindCtx_RemoteSetBindOptions_Proxy(This, &bindOptions);
+ }
+ else
+ {
+ //The caller's BIND_OPTS is too large.
+ //We don't want to truncate, so we return an error.
+ hr = E_INVALIDARG;
+ }
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IBindCtx_SetBindOptions_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IBindCtx::SetBindOptions.
+//
+// Returns: S_OK
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IBindCtx_SetBindOptions_Stub(
+ IBindCtx __RPC_FAR * This,
+ BIND_OPTS2 __RPC_FAR *pbindopts)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->SetBindOptions(This, (BIND_OPTS *)pbindopts);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IClassFactory_CreateInstance_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IClassFactory::CreateInstance.
+//
+// Returns: CLASS_E_NO_AGGREGREGRATION - if punkOuter != 0.
+// Any errors returned by Remote_CreateInstance_Proxy.
+//
+// Notes: We don't support remote aggregation. punkOuter must be zero.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IClassFactory_CreateInstance_Proxy(
+ IClassFactory __RPC_FAR * This,
+ IUnknown __RPC_FAR *pUnkOuter,
+ REFIID riid,
+ void __RPC_FAR *__RPC_FAR *ppvObject)
+{
+ HRESULT hr;
+
+ *ppvObject = 0;
+
+ if(pUnkOuter != 0)
+ hr = CLASS_E_NOAGGREGATION;
+ else
+ hr = IClassFactory_RemoteCreateInstance_Proxy(This, riid, (IUnknown **)ppvObject);
+
+ return hr;
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IClassFactory_CreateInstance_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IClassFactory::CreateInstance.
+//
+// Returns: Any errors returned by CreateInstance.
+//
+// Notes: We don't support remote aggregation.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IClassFactory_CreateInstance_Stub(
+ IClassFactory __RPC_FAR * This,
+ REFIID riid,
+ IUnknown __RPC_FAR *__RPC_FAR *ppvObject)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->CreateInstance(This, 0, riid, ppvObject);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *ppvObject to zero.
+ ASSERT(*ppvObject == 0);
+
+ //Set it to zero, in case we have a badly behaved server.
+ *ppvObject = 0;
+ }
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IClassFactory_LockServer_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IClassFactory::LockServer.
+//
+// Returns: S_OK
+//
+// Notes: The server activation code does an implicit LockServer(TRUE)
+// when it marshals the class object, and an implicit
+// LockServer(FALSE) when the client releases it, so calls
+// made by the client are ignored.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IClassFactory_LockServer_Proxy(
+ IClassFactory __RPC_FAR * This,
+ BOOL fLock)
+{
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IClassFactory_LockServer_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IClassFactory::LockServer.
+//
+// Returns: S_OK
+//
+// Notes: The server activation code does an implicit LockServer(TRUE)
+// when it marshals the class object, and an implicit
+// LockServer(FALSE) when the client releases it, so calls
+// made by the client are ignored.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IClassFactory_LockServer_Stub(
+ IClassFactory __RPC_FAR * This,
+ BOOL fLock)
+{
+ return This->lpVtbl->LockServer(This, fLock);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IDataObject_GetData_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IDataObject::GetData.
+// pMedium is [out] only.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IDataObject_GetData_Proxy(
+ IDataObject __RPC_FAR * This,
+ FORMATETC __RPC_FAR *pformatetcIn,
+ STGMEDIUM __RPC_FAR *pMedium)
+{
+ HRESULT hr;
+
+ UserNdrDebugOut((UNDR_FORCE, "==GetData_Proxy\n"));
+
+ WdtpZeroMemory( pMedium, sizeof(STGMEDIUM) );
+ hr = IDataObject_RemoteGetData_Proxy(This, pformatetcIn, pMedium);
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IDataObject_GetData_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IDataObject::GetData.
+// pMedium is [out] only.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IDataObject_GetData_Stub(
+ IDataObject __RPC_FAR * This,
+ FORMATETC __RPC_FAR *pformatetcIn,
+ STGMEDIUM __RPC_FAR * pMedium)
+{
+ HRESULT hr;
+
+ UserNdrDebugOut((UNDR_FORCE, "==GetData_Stub\n"));
+
+ hr = This->lpVtbl->GetData(This, pformatetcIn, pMedium);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IDataObject_GetDataHere_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IDataObject::GetDataHere.
+// pMedium is [in,out].
+//
+// History: 05-19-94 AlexT Handle all cases correctly
+//
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IDataObject_GetDataHere_Proxy(
+ IDataObject __RPC_FAR * This,
+ FORMATETC __RPC_FAR *pformatetc,
+ STGMEDIUM __RPC_FAR *pmedium)
+{
+ HRESULT hr;
+ IUnknown * punkSaved;
+ IStorage * pStgSaved = NULL;
+
+ UserNdrDebugOut((UNDR_FORCE, "==GetDataHere_Proxy: %s\n", WdtpGetStgmedName(pmedium)));
+
+ if ((pmedium->tymed &
+ (TYMED_FILE | TYMED_ISTORAGE | TYMED_ISTREAM | TYMED_HGLOBAL)) == 0)
+ {
+ // We only support GetDataHere for files, storages, streams,
+ // and HGLOBALs
+
+ return(DV_E_TYMED);
+ }
+
+ if (pmedium->tymed != pformatetc->tymed)
+ {
+ // tymeds must match!
+ return(DV_E_TYMED);
+ }
+
+ // NULL the pUnkForRelease. It makes no sense to pass this parameter
+ // since the callee will never call it. NULLing saves all the marshalling
+ // and associated Rpc calls, and reduces complexity in this code.
+
+ punkSaved = pmedium->pUnkForRelease;
+ pmedium->pUnkForRelease = NULL;
+
+ // BUGBUG this is a hack to make Exchange 8.0.829.1 work HenryLee 04/18/96
+ if (pmedium->tymed == TYMED_ISTORAGE || pmedium->tymed == TYMED_ISTREAM)
+ {
+ pStgSaved = pmedium->pstg;
+ if (pStgSaved)
+ pStgSaved->lpVtbl->AddRef(pStgSaved); // save the old pointer
+ }
+
+ hr = IDataObject_RemoteGetDataHere_Proxy(This, pformatetc, pmedium );
+
+ pmedium->pUnkForRelease = punkSaved;
+
+ if (pStgSaved != NULL)
+ {
+ if (pmedium->pstg != NULL) // discard the new one
+ (pmedium->pstg)->lpVtbl->Release(pmedium->pstg);
+ pmedium->pstg = pStgSaved; // restore old one
+ }
+
+ if(SUCCEEDED(hr) )
+ {
+ UserNdrDebugOut((UNDR_FORCE, " (GetDataHere_ProxyO: new if ptr)\n"));
+ }
+ else
+ UserNdrDebugOut((UNDR_FORCE, " (GetDataHere_ProxyO: didn't succeed : %lx)\n", hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IDataObject_GetDataHere_Stub
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IDataObject::GetData.
+// pMedium is [in,out].
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IDataObject_GetDataHere_Stub(
+ IDataObject __RPC_FAR * This,
+ FORMATETC __RPC_FAR *pformatetc,
+ STGMEDIUM __RPC_FAR * pMedium)
+{
+ HRESULT hr;
+
+ UserNdrDebugOut((UNDR_FORCE, "==GetDataHere_Stub: %s\n", WdtpGetStgmedName(pMedium)));
+
+ hr = This->lpVtbl->GetDataHere(This, pformatetc, pMedium);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IDataObject_SetData_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IDataObject::SetData.
+// This wrapper function uses FLAG_STGMEDIUM type.
+// pMedium is [in].
+//
+// Notes: If fRelease is TRUE, then the callee is responsible for
+// freeing the STGMEDIUM.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IDataObject_SetData_Proxy(
+ IDataObject __RPC_FAR * This,
+ FORMATETC __RPC_FAR *pformatetc,
+ STGMEDIUM __RPC_FAR *pmedium,
+ BOOL fRelease)
+{
+ HRESULT hr;
+ FLAG_STGMEDIUM RemoteStgmed;
+
+#ifdef FUTURE
+ STGMEDIUM StgMedium;
+
+ // Potential performance improvement
+
+ if (!fRelease && pmedium->pUnkForRelease != NULL)
+ {
+ // Caller is retaining ownership of pmedium, but is providing
+ // a pUnkForRelease. We make sure the stub doesn't call the
+ // pUnkForRelease by sending a STGMEDIUM that has it as NULL.
+
+ StgMedium.tymed = pmedium->tymed;
+ StgMedium.hGlobal = pmedium->hGlobal;
+ StgMedium.pUnkForRelease = NULL;
+ pmedium = &StgMedium;
+ }
+#endif
+
+ UserNdrDebugOut((UNDR_FORCE, " SetData_Proxy %s\n", WdtpGetStgmedName(pmedium)));
+ UserNdrDebugOut((UNDR_FORCE, " fRelease=%d, punk=%p\n", fRelease, pmedium->pUnkForRelease));
+
+ __try
+ {
+ RemoteStgmed.ContextFlags = 0;
+ RemoteStgmed.fPassOwnership = fRelease;
+ RemoteStgmed.Stgmed = *pmedium;
+
+ hr = IDataObject_RemoteSetData_Proxy( This,
+ pformatetc,
+ & RemoteStgmed,
+ fRelease);
+
+ if (fRelease && SUCCEEDED(hr))
+ {
+ // Caller has given ownership to callee.
+ // Free the resources left on this side.
+ // Context flags have been set by the unmarshalling routine.
+
+ if ( pmedium->tymed != TYMED_FILE )
+ STGMEDIUM_UserFree( &RemoteStgmed.ContextFlags, pmedium );
+ else
+ {
+ // For files, STGMEDIUM_UserFree dereferences pStubMsg via pFlags
+ // to get to the right freeing routine. As the StubMsg is gone,
+ // we need to free the file here.
+
+ NdrOleFree( pmedium->lpszFileName );
+ NukeHandleAndReleasePunk( pmedium );
+ }
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DWORD dwExceptionCode = GetExceptionCode();
+
+ if(FAILED((HRESULT) dwExceptionCode))
+ hr = (HRESULT) dwExceptionCode;
+ else
+ hr = HRESULT_FROM_WIN32(dwExceptionCode);
+ }
+
+ UserNdrDebugOut((UNDR_FORCE, " SetData_Proxy hr=%lx\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IDataObject_SetData_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IDataObject::SetData.
+// pMedium is [in].
+//
+// Notes: If fRelease is TRUE, then the callee is responsible for
+// freeing the STGMEDIUM.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IDataObject_SetData_Stub(
+ IDataObject __RPC_FAR * This,
+ FORMATETC __RPC_FAR *pformatetc,
+ FLAG_STGMEDIUM __RPC_FAR *pFlagStgmed,
+ BOOL fRelease)
+{
+ HRESULT hr;
+ STGMEDIUM Stgmed;
+
+ __try
+ {
+ Stgmed = pFlagStgmed->Stgmed;
+
+ UserNdrDebugOut((UNDR_FORCE, " SetData_Stub %s\n", WdtpGetStgmedName(& Stgmed)));
+ UserNdrDebugOut((UNDR_FORCE, " fRelease=%d, punk=%p\n", fRelease, Stgmed.pUnkForRelease));
+
+
+ hr = This->lpVtbl->SetData( This,
+ pformatetc,
+ & Stgmed,
+ fRelease);
+
+ if ( fRelease && SUCCEEDED(hr) )
+ {
+ // The ownership was passed successfully.
+ // The user should free the object.
+ // Make it so that our userfree routine for user medium
+ // doesn't do anything to the user's object.
+
+ pFlagStgmed->Stgmed.tymed = TYMED_NULL;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ DWORD dwExceptionCode = GetExceptionCode();
+
+ if(FAILED((HRESULT) dwExceptionCode))
+ hr = (HRESULT) dwExceptionCode;
+ else
+ hr = HRESULT_FROM_WIN32(dwExceptionCode);
+ }
+
+
+ UserNdrDebugOut((UNDR_FORCE, " SetData_Stub hr=%lx\n", hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumConnectionPoints_Next_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IEnumConnectionPoints::Next. This wrapper function handles the
+// case where lpcFetched is NULL.
+//
+// Notes: If lpcFetched != 0, then the number of elements
+// fetched will be returned in *lpcFetched. If an error
+// occurs, then *lpcFetched is set to zero.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumConnectionPoints_Next_Proxy(
+ IEnumConnectionPoints __RPC_FAR * This,
+ ULONG cConnections,
+ IConnectionPoint __RPC_FAR *__RPC_FAR *rgpcn,
+ ULONG __RPC_FAR *lpcFetched)
+{
+ HRESULT hr;
+ ULONG cFetched = 0;
+
+ if((cConnections > 1) && (lpcFetched == 0))
+ return E_INVALIDARG;
+
+ hr = IEnumConnectionPoints_RemoteNext_Proxy(This, cConnections, rgpcn, &cFetched);
+
+ if(lpcFetched != 0)
+ *lpcFetched = cFetched;
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumConnectionPoints_Next_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IEnumConnectionPoints::Next.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumConnectionPoints_Next_Stub(
+ IEnumConnectionPoints __RPC_FAR * This,
+ ULONG cConnections,
+ IConnectionPoint __RPC_FAR *__RPC_FAR *rgpcn,
+ ULONG __RPC_FAR *lpcFetched)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->Next(This, cConnections, rgpcn, lpcFetched);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *lpcFetched to zero.
+ ASSERT(*lpcFetched == 0);
+
+ //Set *lpcFetched to zero in case we have a badly behaved server.
+ *lpcFetched = 0;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumConnections_Next_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IEnumConnections::Next. This wrapper function handles the
+// case where lpcFetched is NULL.
+//
+// Notes: If lpcFetched != 0, then the number of elements
+// fetched will be returned in *lpcFetched. If an error
+// occurs, then *lpcFetched is set to zero.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumConnections_Next_Proxy(
+ IEnumConnections __RPC_FAR * This,
+ ULONG cConnections,
+ CONNECTDATA __RPC_FAR *rgpunk,
+ ULONG __RPC_FAR *lpcFetched)
+{
+ HRESULT hr;
+ ULONG cFetched = 0;
+
+ if((cConnections > 1) && (lpcFetched == 0))
+ return E_INVALIDARG;
+
+ hr = IEnumConnections_RemoteNext_Proxy(This, cConnections, rgpunk, &cFetched);
+
+ if(lpcFetched != 0)
+ *lpcFetched = cFetched;
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumConnections_Next_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IEnumConnections::Next.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumConnections_Next_Stub(
+ IEnumConnections __RPC_FAR * This,
+ ULONG cConnections,
+ CONNECTDATA __RPC_FAR *rgpunk,
+ ULONG __RPC_FAR *lpcFetched)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->Next(This, cConnections, rgpunk, lpcFetched);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *lpcFetched to zero.
+ ASSERT(*lpcFetched == 0);
+
+ //Set *lpcFetched to zero in case we have a badly behaved server.
+ *lpcFetched = 0;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumFORMATETC_Next_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IEnumFORMATETC::Next.
+//
+// Notes: If pceltFetched != 0, then the number of elements
+// fetched will be returned in *pceltFetched. If an error
+// occurs, then *pceltFetched is set to zero.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumFORMATETC_Next_Proxy(
+ IEnumFORMATETC __RPC_FAR * This,
+ ULONG celt,
+ FORMATETC __RPC_FAR *rgelt,
+ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+ ULONG celtFetched = 0;
+
+ if((celt > 1) && (pceltFetched == 0))
+ return E_INVALIDARG;
+
+ hr = IEnumFORMATETC_RemoteNext_Proxy(This, celt, rgelt, &celtFetched);
+
+ if(pceltFetched != 0)
+ *pceltFetched = celtFetched;
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumFORMATETC_Next_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IEnumFORMATETC::Next.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumFORMATETC_Next_Stub(
+ IEnumFORMATETC __RPC_FAR * This,
+ ULONG celt,
+ FORMATETC __RPC_FAR *rgelt,
+ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->Next(This, celt, rgelt, pceltFetched);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *pceltFetched to zero.
+ ASSERT(*pceltFetched == 0);
+
+ //Set *pceltFetched to zero in case we have a badly behaved server.
+ *pceltFetched = 0;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumMoniker_Next_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IEnumMoniker::Next.
+//
+// Notes: If pceltFetched != 0, then the number of elements
+// fetched will be returned in *pceltFetched. If an error
+// occurs, then *pceltFetched is set to zero.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumMoniker_Next_Proxy(
+ IEnumMoniker __RPC_FAR * This,
+ ULONG celt,
+ IMoniker __RPC_FAR *__RPC_FAR *rgelt,
+ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+ ULONG celtFetched = 0;
+
+ if((celt > 1) && (pceltFetched == 0))
+ return E_INVALIDARG;
+
+ hr = IEnumMoniker_RemoteNext_Proxy(This, celt, rgelt, &celtFetched);
+
+ if(pceltFetched != 0)
+ *pceltFetched = celtFetched;
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumMoniker_Next_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IEnumMoniker::Next.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumMoniker_Next_Stub(
+ IEnumMoniker __RPC_FAR * This,
+ ULONG celt,
+ IMoniker __RPC_FAR *__RPC_FAR *rgelt,
+ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->Next(This, celt, rgelt, pceltFetched);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *pceltFetched to zero.
+ ASSERT(*pceltFetched == 0);
+
+ //Set *pceltFetched to zero in case we have a badly behaved server.
+ *pceltFetched = 0;
+ }
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumSTATDATA_Next_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IEnumSTATDATA::Next. This wrapper function handles the
+// case where pceltFetched is NULL.
+//
+// Notes: If pceltFetched != 0, then the number of elements
+// fetched will be returned in *pceltFetched. If an error
+// occurs, then *pceltFetched is set to zero.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumSTATDATA_Next_Proxy(
+ IEnumSTATDATA __RPC_FAR * This,
+ ULONG celt,
+ STATDATA __RPC_FAR *rgelt,
+ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+ ULONG celtFetched = 0;
+
+ if((celt > 1) && (pceltFetched == 0))
+ return E_INVALIDARG;
+
+ hr = IEnumSTATDATA_RemoteNext_Proxy(This, celt, rgelt, &celtFetched);
+
+ if(pceltFetched != 0)
+ *pceltFetched = celtFetched;
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumSTATDATA_Next_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IEnumSTATDATA::Next.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumSTATDATA_Next_Stub(
+ IEnumSTATDATA __RPC_FAR * This,
+ ULONG celt,
+ STATDATA __RPC_FAR *rgelt,
+ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->Next(This, celt, rgelt, pceltFetched);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *pceltFetched to zero.
+ ASSERT(*pceltFetched == 0);
+
+ //Set *pceltFetched to zero in case we have a badly behaved server.
+ *pceltFetched = 0;
+ }
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumSTATSTG_Next_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IEnumSTATSTG::Next. This wrapper function handles the case
+// where pceltFetched is NULL.
+//
+// Notes: If pceltFetched != 0, then the number of elements
+// fetched will be returned in *pceltFetched. If an error
+// occurs, then *pceltFetched is set to zero.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumSTATSTG_Next_Proxy(
+ IEnumSTATSTG __RPC_FAR * This,
+ ULONG celt,
+ STATSTG __RPC_FAR *rgelt,
+ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+ ULONG celtFetched = 0;
+
+ if((celt > 1) && (pceltFetched == 0))
+ return E_INVALIDARG;
+
+ hr = IEnumSTATSTG_RemoteNext_Proxy(This, celt, rgelt, &celtFetched);
+
+ if(pceltFetched != 0)
+ *pceltFetched = celtFetched;
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumSTATSTG_Next_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IEnumSTATSTG::Next.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumSTATSTG_Next_Stub(
+ IEnumSTATSTG __RPC_FAR * This,
+ ULONG celt,
+ STATSTG __RPC_FAR *rgelt,
+ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->Next(This, celt, rgelt, pceltFetched);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *pceltFetched to zero.
+ ASSERT(*pceltFetched == 0);
+
+ //Set *pceltFetched to zero in case we have a badly behaved server.
+ *pceltFetched = 0;
+ }
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumString_Next_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IEnumString::Next. This wrapper function handles the
+// case where pceltFetched is NULL.
+//
+// Notes: If pceltFetched != 0, then the number of elements
+// fetched will be returned in *pceltFetched. If an error
+// occurs, then *pceltFetched is set to zero.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumString_Next_Proxy(
+ IEnumString __RPC_FAR * This,
+ ULONG celt,
+ LPOLESTR __RPC_FAR *rgelt,
+ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+ ULONG celtFetched = 0;
+
+ if((celt > 1) && (pceltFetched == 0))
+ return E_INVALIDARG;
+
+ hr = IEnumString_RemoteNext_Proxy(This, celt, rgelt, &celtFetched);
+
+ if(pceltFetched != 0)
+ *pceltFetched = celtFetched;
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumString_Next_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IEnumString::Next.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumString_Next_Stub(
+ IEnumString __RPC_FAR * This,
+ ULONG celt,
+ LPOLESTR __RPC_FAR *rgelt,
+ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->Next(This, celt, rgelt, pceltFetched);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *pceltFetched to zero.
+ ASSERT(*pceltFetched == 0);
+
+ //Set *pceltFetched to zero in case we have a badly behaved server.
+ *pceltFetched = 0;
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumUnknown_Next_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IEnumUnknown::Next. This wrapper function handles the
+// case where pceltFetched is NULL.
+//
+// Notes: If pceltFetched != 0, then the number of elements
+// fetched will be returned in *pceltFetched. If an error
+// occurs, then *pceltFetched is set to zero.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumUnknown_Next_Proxy(
+ IEnumUnknown __RPC_FAR * This,
+ ULONG celt,
+ IUnknown __RPC_FAR *__RPC_FAR *rgelt,
+ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+ ULONG celtFetched = 0;
+
+ if((celt > 1) && (pceltFetched == 0))
+ return E_INVALIDARG;
+
+ hr = IEnumUnknown_RemoteNext_Proxy(This, celt, rgelt, &celtFetched);
+
+ if(pceltFetched != 0)
+ *pceltFetched = celtFetched;
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumUnknown_Next_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IEnumUnknown::Next.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumUnknown_Next_Stub(
+ IEnumUnknown __RPC_FAR * This,
+ ULONG celt,
+ IUnknown __RPC_FAR *__RPC_FAR *rgelt,
+ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->Next(This, celt, rgelt, pceltFetched);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *pceltFetched to zero.
+ ASSERT(*pceltFetched == 0);
+
+ //Set *pceltFetched to zero in case we have a badly behaved server.
+ *pceltFetched = 0;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumOLEVERB_Next_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IEnumOLEVERB::Next. This wrapper function handles the case
+// where pceltFetched is NULL.
+//
+// Notes: If pceltFetched != 0, then the number of elements
+// fetched will be returned in *pceltFetched. If an error
+// occurs, then *pceltFetched is set to zero.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumOLEVERB_Next_Proxy(
+ IEnumOLEVERB __RPC_FAR * This,
+ ULONG celt,
+ LPOLEVERB rgelt,
+ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+ ULONG celtFetched = 0;
+
+ if((celt > 1) && (pceltFetched == 0))
+ return E_INVALIDARG;
+
+ hr = IEnumOLEVERB_RemoteNext_Proxy(This, celt, rgelt, &celtFetched);
+
+ if(pceltFetched != 0)
+ *pceltFetched = celtFetched;
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumOLEVERB_Next_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IEnumOLEVERB::Next.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumOLEVERB_Next_Stub(
+ IEnumOLEVERB __RPC_FAR * This,
+ ULONG celt,
+ LPOLEVERB rgelt,
+ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->Next(This, celt, rgelt, pceltFetched);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *pceltFetched to zero.
+ ASSERT(*pceltFetched == 0);
+
+ //Set *pceltFetched to zero in case we have a badly behaved server.
+ *pceltFetched = 0;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ILockBytes_ReadAt_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// ILockBytes::ReadAt. This wrapper function
+// handles the case where pcbRead is NULL.
+//
+// Notes: If pcbRead != 0, then the number of bytes read
+// will be returned in *pcbRead. If an error
+// occurs, then *pcbRead is set to zero.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE ILockBytes_ReadAt_Proxy(
+ ILockBytes __RPC_FAR * This,
+ ULARGE_INTEGER ulOffset,
+ void __RPC_FAR *pv,
+ ULONG cb,
+ ULONG __RPC_FAR *pcbRead)
+{
+ HRESULT hr;
+ ULONG cbRead = 0;
+
+ hr = ILockBytes_RemoteReadAt_Proxy(This, ulOffset, (byte __RPC_FAR *) pv, cb, &cbRead);
+
+ if(pcbRead != 0)
+ *pcbRead = cbRead;
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ILockBytes_ReadAt_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// ILockBytes::ReadAt.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE ILockBytes_ReadAt_Stub(
+ ILockBytes __RPC_FAR * This,
+ ULARGE_INTEGER ulOffset,
+ byte __RPC_FAR *pv,
+ ULONG cb,
+ ULONG __RPC_FAR *pcbRead)
+{
+ HRESULT hr;
+
+ *pcbRead = 0;
+ hr = This->lpVtbl->ReadAt(This, ulOffset, (void __RPC_FAR *) pv, cb, pcbRead);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ILockBytes_WriteAt_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// ILockBytes::WriteAt. This wrapper function handles the
+// case where pcbWritten is NULL.
+//
+// Notes: If pcbWritten != 0, then the number of bytes written
+// will be returned in *pcbWritten. If an error
+// occurs, then *pcbWritten is set to zero.
+//
+// History: ? ? Created
+// 05-27-94 AlexT Actually return count of bytes written
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE ILockBytes_WriteAt_Proxy(
+ ILockBytes __RPC_FAR * This,
+ ULARGE_INTEGER ulOffset,
+ const void __RPC_FAR *pv,
+ ULONG cb,
+ ULONG __RPC_FAR *pcbWritten)
+{
+ HRESULT hr;
+ ULONG cbWritten = 0;
+
+#if DBG == 1
+ //validate parameters.
+ if(pv == 0)
+ return STG_E_INVALIDPOINTER;
+#endif
+
+ hr = ILockBytes_RemoteWriteAt_Proxy(This, ulOffset, (byte __RPC_FAR *)pv, cb, &cbWritten);
+
+ if(pcbWritten != 0)
+ *pcbWritten = cbWritten;
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ILockBytes_WriteAt_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// ILockBytes::WriteAt.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE ILockBytes_WriteAt_Stub(
+ ILockBytes __RPC_FAR * This,
+ ULARGE_INTEGER ulOffset,
+ const byte __RPC_FAR *pv,
+ ULONG cb,
+ ULONG __RPC_FAR *pcbWritten)
+{
+ HRESULT hr;
+
+ *pcbWritten = 0;
+ hr = This->lpVtbl->WriteAt(This, ulOffset, pv, cb, pcbWritten);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IMoniker_BindToObject_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IMoniker::BindToObject.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IMoniker_BindToObject_Proxy(
+ IMoniker __RPC_FAR * This,
+ IBindCtx __RPC_FAR *pbc,
+ IMoniker __RPC_FAR *pmkToLeft,
+ REFIID riid,
+ void __RPC_FAR *__RPC_FAR *ppvObj)
+{
+ HRESULT hr;
+
+ *ppvObj = 0;
+
+ hr = IMoniker_RemoteBindToObject_Proxy(
+ This, pbc, pmkToLeft, riid, (IUnknown **) ppvObj);
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IMoniker_BindToObject_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IMoniker::BindToObject.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IMoniker_BindToObject_Stub(
+ IMoniker __RPC_FAR * This,
+ IBindCtx __RPC_FAR *pbc,
+ IMoniker __RPC_FAR *pmkToLeft,
+ REFIID riid,
+ IUnknown __RPC_FAR *__RPC_FAR *ppvObj)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->BindToObject(
+ This, pbc, pmkToLeft, riid, (void **) ppvObj);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *ppvObj to zero.
+ ASSERT(*ppvObj == 0);
+
+ //Set it to zero in case we have a badly behaved server.
+ *ppvObj = 0;
+ }
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IMoniker_BindToStorage_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IMoniker::BindToStorage.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IMoniker_BindToStorage_Proxy(
+ IMoniker __RPC_FAR * This,
+ IBindCtx __RPC_FAR *pbc,
+ IMoniker __RPC_FAR *pmkToLeft,
+ REFIID riid,
+ void __RPC_FAR *__RPC_FAR *ppvObj)
+{
+ HRESULT hr;
+
+ *ppvObj = 0;
+
+ hr = IMoniker_RemoteBindToStorage_Proxy(
+ This, pbc, pmkToLeft, riid, (IUnknown **)ppvObj);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IMoniker_BindToStorage_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IMoniker::BindToStorage.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IMoniker_BindToStorage_Stub(
+ IMoniker __RPC_FAR * This,
+ IBindCtx __RPC_FAR *pbc,
+ IMoniker __RPC_FAR *pmkToLeft,
+ REFIID riid,
+ IUnknown __RPC_FAR *__RPC_FAR *ppvObj)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->BindToStorage(
+ This, pbc, pmkToLeft, riid, (void **) ppvObj);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *ppvObj to zero.
+ ASSERT(*ppvObj == 0);
+
+ //Set it to zero in case we have a badly behaved server.
+ *ppvObj = 0;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IClientSiteHandler_PrivQueryInterface_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IClientSiteHandler::PrivQueryInterface
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IClientSiteHandler_PrivQueryInterface_Proxy(
+ IClientSiteHandler __RPC_FAR * This,
+ DWORD dwId,
+ REFIID riid,
+ void __RPC_FAR *__RPC_FAR *ppvObj)
+{
+ HRESULT hr;
+
+ *ppvObj = 0;
+
+ hr = IClientSiteHandler_RemotePrivQueryInterface_Proxy(
+ This, dwId, riid, (IUnknown **) ppvObj);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IClientSiteHandler_PrivQueryInterface_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IClientSiteHandler::PrivQueryInterface
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IClientSiteHandler_PrivQueryInterface_Stub(
+ IClientSiteHandler __RPC_FAR * This,
+ DWORD dwId,
+ REFIID riid,
+ IUnknown __RPC_FAR *__RPC_FAR *ppvObj)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->PrivQueryInterface(
+ This, dwId, riid, (void **) ppvObj);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *ppvObj to zero.
+ ASSERT(*ppvObj == 0);
+
+ //Set it to zero in case we have a badly behaved server.
+ *ppvObj = 0;
+ }
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IOleCache2_UpdateCache_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IOleCache2:UpdateCache
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IOleCache2_UpdateCache_Proxy(
+ IOleCache2 __RPC_FAR * This,
+ LPDATAOBJECT pDataObject,
+ DWORD grfUpdf,
+ LPVOID pReserved)
+{
+ HRESULT hr;
+ hr = IOleCache2_RemoteUpdateCache_Proxy(This,
+ pDataObject,
+ grfUpdf,
+ (DWORD) pReserved);
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IOleCache2_UpdateCache_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IOleCache2::UpdateCache.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IOleCache2_UpdateCache_Stub(
+ IOleCache2 __RPC_FAR * This,
+ LPDATAOBJECT pDataObject,
+ DWORD grfUpdf,
+ DWORD pReserved)
+{
+ HRESULT hr;
+ hr = This->lpVtbl->UpdateCache(This,
+ pDataObject,
+ grfUpdf,
+ (void *)pReserved);
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IOleInPlaceActiveObject_TranslateAccelerator_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IOleInPlaceActiveObject::TranslateAccelerator.
+//
+// Returns: This function always returns S_FALSE.
+//
+// Notes: A container needs to process accelerators differently
+// depending on whether an inplace server is running
+// in process or as a local server. When the container
+// calls IOleInPlaceActiveObject::TranslateAccelerator on
+// an inprocess server, the server can return S_OK if it
+// successfully translated the message. When the container
+// calls IOleInPlaceActiveObject::TranslateAccelerator on
+// a local server, the proxy will always return S_FALSE.
+// In other words, a local server never gets the opportunity
+// to translate messages from the container.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IOleInPlaceActiveObject_TranslateAccelerator_Proxy(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ LPMSG lpmsg)
+{
+ return S_FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IOleInPlaceActiveObject_TranslateAccelerator_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IOleInPlaceActiveObject::TranslateAccelerator
+//
+// Notes: This function should never be called.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IOleInPlaceActiveObject_TranslateAccelerator_Stub(
+ IOleInPlaceActiveObject __RPC_FAR * This)
+{
+ return S_FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IOleInPlaceActiveObject_ResizeBorder_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IOleInPlaceActiveObject::ResizeBorder
+//
+// Notes: The pUIWindow interface is either an IOleInPlaceUIWindow or
+// an IOleInPlaceFrame, based on fFrameWindow. We use
+// fFrameWindow to tell the proxy exactly which interace it
+// is so that it gets marshalled and unmarshalled correctly.
+//
+//--------------------------------------------------------------------------
+
+HRESULT STDMETHODCALLTYPE IOleInPlaceActiveObject_ResizeBorder_Proxy(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ LPCRECT prcBorder,
+ IOleInPlaceUIWindow *pUIWindow,
+ BOOL fFrameWindow)
+{
+ HRESULT hr;
+ REFIID riid;
+
+ if (fFrameWindow)
+ {
+ riid = &IID_IOleInPlaceFrame;
+ }
+ else
+ {
+ riid = &IID_IOleInPlaceUIWindow;
+ }
+
+ hr = IOleInPlaceActiveObject_RemoteResizeBorder_Proxy(
+ This, prcBorder, riid, pUIWindow, fFrameWindow);
+
+ return(hr);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IOleInPlaceActiveObject_ResizeBorder_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IOleInPlaceActiveObject::ResizeBorder
+//
+//--------------------------------------------------------------------------
+
+HRESULT STDMETHODCALLTYPE IOleInPlaceActiveObject_ResizeBorder_Stub(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ LPCRECT prcBorder,
+ REFIID riid,
+ IOleInPlaceUIWindow *pUIWindow,
+ BOOL fFrameWindow)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->ResizeBorder(This, prcBorder, pUIWindow, fFrameWindow);
+
+ return(hr);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IOleItemContainer_GetObject_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IOleItemContainer::GetObject.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IOleItemContainer_GetObject_Proxy(
+ IOleItemContainer __RPC_FAR * This,
+ LPOLESTR pszItem,
+ DWORD dwSpeedNeeded,
+ IBindCtx __RPC_FAR *pbc,
+ REFIID riid,
+ void __RPC_FAR *__RPC_FAR *ppvObj)
+{
+ HRESULT hr;
+
+ *ppvObj = 0;
+
+ hr = IOleItemContainer_RemoteGetObject_Proxy(
+ This, pszItem, dwSpeedNeeded, pbc, riid, (IUnknown **) ppvObj);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IOleItemContainer_GetObject_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IOleItemContainer::GetObject.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IOleItemContainer_GetObject_Stub(
+ IOleItemContainer __RPC_FAR * This,
+ LPOLESTR pszItem,
+ DWORD dwSpeedNeeded,
+ IBindCtx __RPC_FAR *pbc,
+ REFIID riid,
+ IUnknown __RPC_FAR *__RPC_FAR *ppvObj)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->GetObject(
+ This, pszItem, dwSpeedNeeded, pbc, riid, (IUnknown **) ppvObj);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *ppvObj to zero.
+ ASSERT(*ppvObj == 0);
+
+ //Set it to zero in case we have a badly behaved server.
+ *ppvObj = 0;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IOleItemContainer_GetObjectStorage_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IOleItemContainer::GetObjectStorage.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IOleItemContainer_GetObjectStorage_Proxy(
+ IOleItemContainer __RPC_FAR * This,
+ LPOLESTR pszItem,
+ IBindCtx __RPC_FAR *pbc,
+ REFIID riid,
+ void __RPC_FAR *__RPC_FAR *ppvStorage)
+{
+ HRESULT hr;
+
+ *ppvStorage = 0;
+
+ hr = IOleItemContainer_RemoteGetObjectStorage_Proxy(
+ This, pszItem, pbc, riid, (IUnknown **) ppvStorage);
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IOleItemContainer_GetObjectStorage_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IOleItemContainer::GetObjectStorage.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IOleItemContainer_GetObjectStorage_Stub(
+ IOleItemContainer __RPC_FAR * This,
+ LPOLESTR pszItem,
+ IBindCtx __RPC_FAR *pbc,
+ REFIID riid,
+ IUnknown __RPC_FAR *__RPC_FAR *ppvStorage)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->GetObjectStorage(
+ This, pszItem, pbc, riid, ppvStorage);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *ppvStorage to zero.
+ ASSERT(*ppvStorage == 0);
+
+ //Set it to zero in case we have a badly behaved server.
+ *ppvStorage = 0;
+ }
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IStorage_OpenStream_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IStorage::OpenStream.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IStorage_OpenStream_Proxy(
+ IStorage __RPC_FAR * This,
+ const OLECHAR __RPC_FAR *pwcsName,
+ void __RPC_FAR *pReserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream __RPC_FAR *__RPC_FAR *ppstm)
+{
+ HRESULT hr;
+
+#if DBG == 1
+ if(pReserved1 != 0)
+ return STG_E_INVALIDPARAMETER;
+#endif
+
+ *ppstm = 0;
+
+ hr = IStorage_RemoteOpenStream_Proxy(
+ This, pwcsName, 0, 0, grfMode, reserved2, ppstm);
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IStorage_OpenStream_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IStorage::OpenStream.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IStorage_OpenStream_Stub(
+ IStorage __RPC_FAR * This,
+ const OLECHAR __RPC_FAR *pwcsName,
+ unsigned long cbReserved1,
+ byte __RPC_FAR *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream __RPC_FAR *__RPC_FAR *ppstm)
+{
+ HRESULT hr;
+
+
+ hr = This->lpVtbl->OpenStream(This, pwcsName, 0, grfMode, reserved2, ppstm);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *ppstm to zero.
+ ASSERT(*ppstm == 0);
+
+ //Set *ppstm to zero in case we have a badly behaved server.
+ *ppstm = 0;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IStorage_EnumElements_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IStorage_EnumElements_Proxy
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IStorage_EnumElements_Proxy(
+ IStorage __RPC_FAR * This,
+ DWORD reserved1,
+ void __RPC_FAR *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum)
+{
+ HRESULT hr;
+
+ *ppenum = 0;
+
+ hr = IStorage_RemoteEnumElements_Proxy(
+ This, reserved1, 0, 0, reserved3, ppenum);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IStorage_EnumElements_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IStorage::EnumElements.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IStorage_EnumElements_Stub(
+ IStorage __RPC_FAR * This,
+ DWORD reserved1,
+ unsigned long cbReserved2,
+ byte __RPC_FAR *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->EnumElements(This, reserved1, 0, reserved3, ppenum);
+
+ if(FAILED(hr))
+ {
+ //If the server returns an error code, it must set *ppenum to zero.
+ ASSERT(*ppenum == 0);
+
+ //Set *ppenum to zero in case we have a badly behaved server.
+ *ppenum = 0;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IRunnableObject_IsRunning_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IRunnableObject::IsRunning.
+//
+//--------------------------------------------------------------------------
+BOOL STDMETHODCALLTYPE IRunnableObject_IsRunning_Proxy(
+ IRunnableObject __RPC_FAR * This)
+{
+ BOOL bIsRunning = TRUE;
+ HRESULT hr;
+
+ hr = IRunnableObject_RemoteIsRunning_Proxy(This);
+
+ if(S_FALSE == hr)
+ bIsRunning = FALSE;
+
+ return bIsRunning;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IRunnableObject_IsRunning_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IRunnableObject::IsRunning.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IRunnableObject_IsRunning_Stub(
+ IRunnableObject __RPC_FAR * This)
+{
+ HRESULT hr;
+ BOOL bIsRunning;
+
+ bIsRunning = This->lpVtbl->IsRunning(This);
+
+ if(TRUE == bIsRunning)
+ hr = S_OK;
+ else
+ hr = S_FALSE;
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ISequentialStream_Read_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IStream::Read. This wrapper function handles the case
+// where pcbRead is NULL.
+//
+// Notes: If pcbRead != 0, then the number of bytes read
+// will be returned in *pcbRead. If an error
+// occurs, then *pcbRead is set to zero.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE ISequentialStream_Read_Proxy(
+ ISequentialStream __RPC_FAR * This,
+ void __RPC_FAR *pv,
+ ULONG cb,
+ ULONG __RPC_FAR *pcbRead)
+{
+ HRESULT hr;
+ ULONG cbRead = 0;
+
+#if DBG == 1
+ //validate parameters.
+ if(pv == 0)
+ return STG_E_INVALIDPOINTER;
+#endif //DBG == 1
+
+ hr = ISequentialStream_RemoteRead_Proxy(This, (byte *) pv, cb, &cbRead);
+
+ if(pcbRead != 0)
+ *pcbRead = cbRead;
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ISequentialStream_Read_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IStream::Read.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE ISequentialStream_Read_Stub(
+ ISequentialStream __RPC_FAR * This,
+ byte __RPC_FAR *pv,
+ ULONG cb,
+ ULONG __RPC_FAR *pcbRead)
+{
+ HRESULT hr;
+
+ *pcbRead = 0;
+ hr = This->lpVtbl->Read(This, (void *) pv, cb, pcbRead);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IStream_Seek_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IStream::Seek. This wrapper function handles the case
+// where plibNewPosition is NULL.
+//
+// Notes: If plibNewPosition != 0, then the new position
+// will be returned in *plibNewPosition.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IStream_Seek_Proxy(
+ IStream __RPC_FAR * This,
+ LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER __RPC_FAR *plibNewPosition)
+{
+ HRESULT hr;
+ ULARGE_INTEGER libNewPosition;
+
+ hr = IStream_RemoteSeek_Proxy(This, dlibMove, dwOrigin, &libNewPosition);
+
+ if(plibNewPosition != 0)
+ {
+ *plibNewPosition = libNewPosition;
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IStream_Seek_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IStream::Seek.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IStream_Seek_Stub(
+ IStream __RPC_FAR * This,
+ LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER __RPC_FAR *plibNewPosition)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->Seek(This, dlibMove, dwOrigin, plibNewPosition);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ISequentialStream_Write_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IStream::Write. This wrapper function handles the
+// case where pcbWritten is NULL.
+//
+// Notes: If pcbWritten != 0, then the number of bytes written
+// will be returned in *pcbWritten. If an error
+// occurs, then *pcbWritten is set to zero.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE ISequentialStream_Write_Proxy(
+ ISequentialStream __RPC_FAR * This,
+ const void __RPC_FAR *pv,
+ ULONG cb,
+ ULONG __RPC_FAR *pcbWritten)
+{
+ HRESULT hr;
+ ULONG cbWritten = 0;
+
+#if DBG == 1
+ //validate parameters.
+ if(pv == 0)
+ return STG_E_INVALIDPOINTER;
+#endif
+
+ hr = ISequentialStream_RemoteWrite_Proxy(This, (byte *) pv, cb, &cbWritten);
+
+ if(pcbWritten != 0)
+ *pcbWritten = cbWritten;
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ISequentialStream_Write_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// ISequentialStream::Write.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE ISequentialStream_Write_Stub(
+ ISequentialStream __RPC_FAR * This,
+ const byte __RPC_FAR *pv,
+ ULONG cb,
+ ULONG __RPC_FAR *pcbWritten)
+{
+ HRESULT hr;
+
+ *pcbWritten = 0;
+ hr = This->lpVtbl->Write(This, (const void __RPC_FAR *) pv, cb, pcbWritten);
+
+ return hr;
+}
+//+-------------------------------------------------------------------------
+//
+// Function: IStream_CopyTo_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IStream::CopyTo. This wrapper function handles the
+// cases where pcbRead is NULL or pcbWritten is NULL.
+//
+// Notes: If pcbRead != 0, then the number of bytes read
+// will be returned in *pcbRead. If an error
+// occurs, then *pcbRead is set to zero.
+//
+// If pcbWritten != 0, then the number of bytes written
+// will be returned in *pcbWritten. If an error
+// occurs, then *pcbWritten is set to zero.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IStream_CopyTo_Proxy(
+ IStream __RPC_FAR * This,
+ IStream __RPC_FAR *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER __RPC_FAR *pcbRead,
+ ULARGE_INTEGER __RPC_FAR *pcbWritten)
+{
+ HRESULT hr;
+ ULARGE_INTEGER cbRead;
+ ULARGE_INTEGER cbWritten;
+
+ cbRead.LowPart = 0;
+ cbRead.HighPart = 0;
+ cbWritten.LowPart = 0;
+ cbWritten.HighPart = 0;
+
+ hr = IStream_RemoteCopyTo_Proxy(This, pstm, cb, &cbRead, &cbWritten);
+
+ if(pcbRead != 0)
+ *pcbRead = cbRead;
+
+ if(pcbWritten != 0)
+ *pcbWritten = cbWritten;
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IStream_CopyTo_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IStream::CopyTo.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IStream_CopyTo_Stub(
+ IStream __RPC_FAR * This,
+ IStream __RPC_FAR *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER __RPC_FAR *pcbRead,
+ ULARGE_INTEGER __RPC_FAR *pcbWritten)
+{
+ HRESULT hr;
+
+ pcbRead->LowPart = 0;
+ pcbRead->HighPart = 0;
+ pcbWritten->LowPart = 0;
+ pcbWritten->HighPart = 0;
+
+ hr = This->lpVtbl->CopyTo(This, pstm, cb, pcbRead, pcbWritten);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IViewObject_Draw_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IViewObject::Draw.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IViewObject_Draw_Proxy(
+ IViewObject __RPC_FAR * This,
+ DWORD dwDrawAspect,
+ LONG lindex,
+ void __RPC_FAR *pvAspect,
+ DVTARGETDEVICE __RPC_FAR *ptd,
+ HDC hdcTargetDev,
+ HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ BOOL (STDMETHODCALLTYPE __RPC_FAR *pfnContinue )(DWORD dwContinue),
+ DWORD dwContinue)
+{
+ HRESULT hr;
+ IContinue *pContinue = 0;
+
+ if(pvAspect != 0)
+ return E_INVALIDARG;
+
+ if(pfnContinue != 0)
+ {
+ hr = CreateCallback(pfnContinue, dwContinue, &pContinue);
+ if(FAILED(hr))
+ {
+ return hr;
+ }
+ }
+
+ hr = IViewObject_RemoteDraw_Proxy(This,
+ dwDrawAspect,
+ lindex,
+ (DWORD) pvAspect,
+ ptd,
+ (DWORD) hdcTargetDev,
+ (DWORD) hdcDraw,
+ lprcBounds,
+ lprcWBounds,
+ pContinue);
+
+ if(pContinue != 0)
+ {
+ pContinue->lpVtbl->Release(pContinue);
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IViewObject_RemoteContinue
+//
+// Synopsis: Wrapper function for IContinue::FContinue. This function
+// is used for marshalling the pfnContinue parameter in
+// IViewObject::Draw.
+//
+// Algorithm: Cast the dwContinue to an IContinue * and then
+// call IContinue::FContinue.
+//
+//--------------------------------------------------------------------------
+BOOL STDAPICALLTYPE IViewObject_RemoteContinue(DWORD dwContinue)
+{
+ BOOL bContinue = TRUE;
+ HRESULT hr;
+ IContinue *pContinue = (IContinue *) dwContinue;
+
+ if(pContinue != 0)
+ {
+ hr = pContinue->lpVtbl->FContinue(pContinue);
+
+ if(S_FALSE == hr)
+ bContinue = FALSE;
+ }
+
+ return bContinue;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IViewObject_Draw_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IViewObject::Draw.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IViewObject_Draw_Stub(
+ IViewObject __RPC_FAR * This,
+ DWORD dwDrawAspect,
+ LONG lindex,
+ DWORD pvAspect,
+ DVTARGETDEVICE __RPC_FAR *ptd,
+ DWORD hdcTargetDev,
+ DWORD hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ IContinue *pContinue)
+{
+ HRESULT hr;
+ BOOL (STDMETHODCALLTYPE __RPC_FAR *pfnContinue )(DWORD dwContinue) = 0;
+ DWORD dwContinue = 0;
+
+ if(pContinue != 0)
+ {
+ pfnContinue = IViewObject_RemoteContinue;
+ dwContinue = (DWORD) pContinue;
+ }
+
+ hr = This->lpVtbl->Draw(This,
+ dwDrawAspect,
+ lindex,
+ (void *) pvAspect,
+ ptd,
+ (HDC) hdcTargetDev,
+ (HDC) hdcDraw,
+ lprcBounds,
+ lprcWBounds,
+ pfnContinue,
+ dwContinue);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IViewObject_Freeze_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IViewObject::Freeze.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IViewObject_Freeze_Proxy(
+ IViewObject __RPC_FAR * This,
+ DWORD dwDrawAspect,
+ LONG lindex,
+ void __RPC_FAR *pvAspect,
+ DWORD __RPC_FAR *pdwFreeze)
+{
+ HRESULT hr;
+
+ if(pvAspect != 0)
+ return E_INVALIDARG;
+
+ hr = IViewObject_RemoteFreeze_Proxy(This,
+ dwDrawAspect,
+ lindex,
+ (DWORD) pvAspect,
+ pdwFreeze);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IViewObject_Freeze_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IViewObject::Freeze.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IViewObject_Freeze_Stub(
+ IViewObject __RPC_FAR * This,
+ DWORD dwDrawAspect,
+ LONG lindex,
+ DWORD pvAspect,
+ DWORD __RPC_FAR *pdwFreeze)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->Freeze(This,
+ dwDrawAspect,
+ lindex,
+ (void *) pvAspect,
+ pdwFreeze);
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IViewObject_GetColorSet_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IViewObject::GetColorSet.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IViewObject_GetColorSet_Proxy(
+ IViewObject __RPC_FAR * This,
+ DWORD dwDrawAspect,
+ LONG lindex,
+ void __RPC_FAR *pvAspect,
+ DVTARGETDEVICE __RPC_FAR *ptd,
+ HDC hicTargetDev,
+ LOGPALETTE __RPC_FAR *__RPC_FAR *ppColorSet)
+{
+ HRESULT hr;
+
+ if(pvAspect != 0)
+ return E_INVALIDARG;
+
+ hr = IViewObject_RemoteGetColorSet_Proxy(This,
+ dwDrawAspect,
+ lindex,
+ (DWORD) pvAspect,
+ ptd,
+ (DWORD) hicTargetDev,
+ ppColorSet);
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IViewObject_GetColorSet_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IViewObject::GetColorSet.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IViewObject_GetColorSet_Stub(
+ IViewObject __RPC_FAR * This,
+ DWORD dwDrawAspect,
+ LONG lindex,
+ DWORD pvAspect,
+ DVTARGETDEVICE __RPC_FAR *ptd,
+ DWORD hicTargetDev,
+ LOGPALETTE __RPC_FAR *__RPC_FAR *ppColorSet)
+{
+ HRESULT hr;
+
+ hr = This->lpVtbl->GetColorSet(This,
+ dwDrawAspect,
+ lindex,
+ (void *)pvAspect,
+ ptd,
+ (HDC) hicTargetDev,
+ ppColorSet);
+
+ return hr;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumSTATPROPSTG_Next_Proxy
+//
+// Synopsis:
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumSTATPROPSTG_Next_Proxy(
+ IEnumSTATPROPSTG __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [out] */ STATPROPSTG __RPC_FAR *rgelt,
+ /* [unique][out][in] */ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+ ULONG celtFetched = 0;
+
+ if((celt > 1) && (pceltFetched == 0))
+ return E_INVALIDARG;
+
+ hr = IEnumSTATPROPSTG_RemoteNext_Proxy(This, celt, rgelt, &celtFetched);
+
+ if (pceltFetched != 0)
+ {
+ *pceltFetched = celtFetched;
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumSTATPROPSTG_Next_Stub
+//
+// Synopsis:
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumSTATPROPSTG_Next_Stub(
+ IEnumSTATPROPSTG __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ STATPROPSTG __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched)
+{
+ return This->lpVtbl->Next(This, celt, rgelt, pceltFetched);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumSTATPROPSETSTG_Next_Proxy
+//
+// Synopsis:
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumSTATPROPSETSTG_Next_Proxy(
+ IEnumSTATPROPSETSTG __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [out] */ STATPROPSETSTG __RPC_FAR *rgelt,
+ /* [unique][out][in] */ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+ ULONG celtFetched = 0;
+
+ if((celt > 1) && (pceltFetched == 0))
+ return E_INVALIDARG;
+
+ hr = IEnumSTATPROPSETSTG_RemoteNext_Proxy(This, celt, rgelt, &celtFetched);
+
+ if (pceltFetched != 0)
+ {
+ *pceltFetched = celtFetched;
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumSTATPROPSETSTG_Next_Stub
+//
+// Synopsis:
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumSTATPROPSETSTG_Next_Stub(
+ IEnumSTATPROPSETSTG __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ STATPROPSETSTG __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched)
+{
+ return This->lpVtbl->Next(This, celt, rgelt, pceltFetched);
+}
+
+#ifdef _CAIRO_
+//+-------------------------------------------------------------------------
+//
+// Function: IOverlappedStream_ReadOverlapped_Proxy
+//
+// Synopsis:
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IOverlappedStream_ReadOverlapped_Proxy(
+ IOverlappedStream __RPC_FAR *This,
+ /* [in, size_is(cb)] */ void * pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG * pcbRead,
+ /* [in,out] */ STGOVERLAPPED *lpOverlapped)
+{
+ HRESULT hr = IOverlappedStream_RemoteReadOverlapped_Proxy (
+ /* IOverlappedStream * */ This,
+ /* [in, size_is(cb)] */ (byte *) pv,
+ /* [in] */ cb,
+ /* [out] */ pcbRead,
+ /* [in,out] */ lpOverlapped);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IOverlappedStream_ReadOverlapped_Stub
+//
+// Synopsis:
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IOverlappedStream_ReadOverlapped_Stub (
+ IOverlappedStream __RPC_FAR *This,
+ /* [in, size_is(cb)] */ byte * pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG * pcbRead,
+ /* [in,out] */ STGOVERLAPPED *lpOverlapped)
+{
+ return This->lpVtbl->ReadOverlapped(
+ /* IOverlappedStream * */ This,
+ /* [in, size_is(cb)] */ pv,
+ /* [in] */ cb,
+ /* [out] */ pcbRead,
+ /* [in,out] */lpOverlapped);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IOverlappedStream_WriteOverlapped_Proxy
+//
+// Synopsis:
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IOverlappedStream_WriteOverlapped_Proxy(
+ IOverlappedStream __RPC_FAR *This,
+ /* [in, size_is(cb)] */ void *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG * pcbWritten,
+ /* [in,out] */ STGOVERLAPPED *lpOverlapped)
+{
+ HRESULT hr = IOverlappedStream_RemoteWriteOverlapped_Proxy (
+ /* IOverlappedStream * */ This,
+ /* [in, size_is(cb)] */ (byte *)pv,
+ /* [in] */ cb,
+ /* [out] */ pcbWritten,
+ /* [in,out] */ lpOverlapped);
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IOverlappedStream_WriteOverlapped_Stub
+//
+// Synopsis:
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IOverlappedStream_WriteOverlapped_Stub (
+ IOverlappedStream __RPC_FAR *This,
+ /* [in, size_is(cb)] */ byte *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG * pcbWritten,
+ /* [in,out] */ STGOVERLAPPED *lpOverlapped)
+{
+ return This->lpVtbl->WriteOverlapped(
+ /* IOverlappedStream * */ This,
+ /* [in, size_is(cb)] */ pv,
+ /* [in] */ cb,
+ /* [out] */ pcbWritten,
+ /* [in,out] */ lpOverlapped);
+}
+
+
+
+#endif // _CAIRO_
+
+//+-------------------------------------------------------------------------
+//
+// Function: IFillLockBytes_FillAt_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IFillLockBytes::FillAt. This wrapper function handles the
+// case where pcbWritten is NULL.
+//
+// Notes: If pcbWritten != 0, then the number of bytes written
+// will be returned in *pcbWritten. If an error
+// occurs, then *pcbWritten is set to zero.
+//
+// History: ? ? Created
+// 05-27-94 AlexT Actually return count of bytes written
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IFillLockBytes_FillAt_Proxy(
+ IFillLockBytes __RPC_FAR * This,
+ ULARGE_INTEGER ulOffset,
+ const void __RPC_FAR *pv,
+ ULONG cb,
+ ULONG __RPC_FAR *pcbWritten)
+{
+ HRESULT hr;
+ ULONG cbWritten = 0;
+
+#if DBG == 1
+ //validate parameters.
+ if(pv == 0)
+ return STG_E_INVALIDPOINTER;
+#endif
+
+ hr = IFillLockBytes_RemoteFillAt_Proxy(This, ulOffset, (byte __RPC_FAR *)pv, cb, &cbWritten);
+
+ if(pcbWritten != 0)
+ *pcbWritten = cbWritten;
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IFillLockBytes_FillAt_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IFillLockBytes::FillAt.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IFillLockBytes_FillAt_Stub(
+ IFillLockBytes __RPC_FAR * This,
+ ULARGE_INTEGER ulOffset,
+ const byte __RPC_FAR *pv,
+ ULONG cb,
+ ULONG __RPC_FAR *pcbWritten)
+{
+ HRESULT hr;
+
+ *pcbWritten = 0;
+ hr = This->lpVtbl->FillAt(This, ulOffset, pv, cb, pcbWritten);
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IFillLockBytes_FillAppend_Proxy
+//
+// Synopsis: Client-side [call_as] wrapper function for
+// IFillLockBytes::FillAppend. This wrapper function handles the
+// case where pcbWritten is NULL.
+//
+// Notes: If pcbWritten != 0, then the number of bytes written
+// will be returned in *pcbWritten. If an error
+// occurs, then *pcbWritten is set to zero.
+//
+// History: ? ? Created
+// 05-27-94 AlexT Actually return count of bytes written
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IFillLockBytes_FillAppend_Proxy(
+ IFillLockBytes __RPC_FAR * This,
+ const void __RPC_FAR *pv,
+ ULONG cb,
+ ULONG __RPC_FAR *pcbWritten)
+{
+ HRESULT hr;
+ ULONG cbWritten = 0;
+
+#if DBG == 1
+ //validate parameters.
+ if(pv == 0)
+ return STG_E_INVALIDPOINTER;
+#endif
+
+ hr = IFillLockBytes_RemoteFillAppend_Proxy(This, (byte __RPC_FAR *)pv, cb, &cbWritten);
+
+ if(pcbWritten != 0)
+ *pcbWritten = cbWritten;
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IFillLockBytes_FillAppend_Stub
+//
+// Synopsis: Server-side [call_as] wrapper function for
+// IFillLockBytes::FillAppend.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IFillLockBytes_FillAppend_Stub(
+ IFillLockBytes __RPC_FAR * This,
+ const byte __RPC_FAR *pv,
+ ULONG cb,
+ ULONG __RPC_FAR *pcbWritten)
+{
+ HRESULT hr;
+
+ *pcbWritten = 0;
+ hr = This->lpVtbl->FillAppend(This, pv, cb, pcbWritten);
+
+ return hr;
+}
diff --git a/private/ole32/oleprx32/proxy/daytona/makefile b/private/ole32/oleprx32/proxy/daytona/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ole32/oleprx32/proxy/daytona/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/oleprx32/proxy/daytona/sources b/private/ole32/oleprx32/proxy/daytona/sources
new file mode 100644
index 000000000..ed1d1e796
--- /dev/null
+++ b/private/ole32/oleprx32/proxy/daytona/sources
@@ -0,0 +1,39 @@
+
+NO_CAIRO_LIBS=1
+
+
+MAJORCOMP=oleprx32
+MINORCOMP=proxy
+TARGETNAME=oleprx32
+
+!include ..\..\..\daytona.inc
+
+#
+# We don't want the .lib file in sdk\lib. Binplace.exe will put the DLL in
+# the release tree.
+#
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+INCLUDES=..\.;..\..\..\ih
+INCLUDES=$(INCLUDES);..\..\..\com\dcomidl
+INCLUDES=$(INCLUDES);..\..\..\com\dcomidl\daytona
+INCLUDES=$(INCLUDES);..\..\..\stg\h
+INCLUDES=$(INCLUDES);$(BASEDIR)\private\dcomidl\obj
+
+CONDITIONAL_INCLUDES=
+
+
+SYNCHRONIZE_BLOCK=1
+SYNCHRONIZE_DRAIN=1
+
+
+# All the files listed below ending in _p.c are generated by MIDL
+
+SOURCES= \
+ ..\transmit.cxx \
+ ..\dlldatax.c \
+ ..\call_as.c \
+ mega_p.c \
+ mega_i.c \
+ ..\bstr.cxx
diff --git a/private/ole32/oleprx32/proxy/dirs b/private/ole32/oleprx32/proxy/dirs
new file mode 100644
index 000000000..c9fb62257
--- /dev/null
+++ b/private/ole32/oleprx32/proxy/dirs
@@ -0,0 +1,26 @@
+!if 0
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dirs
+//
+// Contents: dirs files for NT types project.
+//
+//
+// Functions:
+//
+// History: 12-20-93 terryru Created
+//
+//----------------------------------------------------------------------------
+
+!endif
+
+DIRS=
+
+OPTIONAL_DIRS= \
+ \
+ daytona \
+
+
diff --git a/private/ole32/oleprx32/proxy/dlldatax.c b/private/ole32/oleprx32/proxy/dlldatax.c
new file mode 100644
index 000000000..076764473
--- /dev/null
+++ b/private/ole32/oleprx32/proxy/dlldatax.c
@@ -0,0 +1,13 @@
+
+// wrapper for dlldata.c
+
+
+
+#define PROXY_CLSID CLSID_PSOlePrx32
+
+#define DllGetClassObject PrxDllGetClassObject
+#define DllCanUnloadNow PrxDllCanUnloadNow
+
+
+#include "dlldata.c"
+
diff --git a/private/ole32/oleprx32/proxy/mega.h b/private/ole32/oleprx32/proxy/mega.h
new file mode 100644
index 000000000..59553639a
--- /dev/null
+++ b/private/ole32/oleprx32/proxy/mega.h
@@ -0,0 +1,28 @@
+
+// a giant mega idl file to put the whole proxy together
+
+#include "unknwn.h"
+
+#include "objidl.h"
+
+#include "oleidl.h"
+
+#include "oaidl.h"
+
+#include "ocidl.h"
+
+#include "srvhdl.h"
+
+#ifdef DCOM
+// internal interfaces used by DCOM
+// this is private! (for now)
+#include "oleprv.h"
+#endif
+
+#ifdef ASYNC
+#include "iconn.h"
+#endif
+
+#ifdef _CAIRO_
+#include "storext.h"
+#endif
diff --git a/private/ole32/oleprx32/proxy/oleprx32.def b/private/ole32/oleprx32/proxy/oleprx32.def
new file mode 100644
index 000000000..6c30c34a2
--- /dev/null
+++ b/private/ole32/oleprx32/proxy/oleprx32.def
@@ -0,0 +1,34 @@
+#if 0
+
+ Microsoft Windows
+ Copyright (C) Microsoft Corporation, 1992 - 1994.
+ All rights reserved.
+
+ This .def file is preprocessed by the compiler to create the version for
+ the current build in the appropriate subdir. Basically, whatever you
+ would have used in your code to control what is compiled when can be
+ used in this file for the same purpose. The following defines are in
+ use at the time this file was written:
+
+ FLAT - Used to indicate a NT/DOS7 build
+ i386 - Intel i386/i486 build
+ MIPS - MIPS R3000/R4000 build
+ ALPHA - DEC Alpha build
+ DBG - Used to control Debug/Retail. Set to 1 if Debug,
+ 0 if Retail.
+ WIN31 - Win16 build
+ __OS2__ - OS/2 build (used by CT mostly)
+
+ If none of these are used, it is assumed the entire file can be used
+ for all builds.
+
+#endif
+
+LIBRARY OLEPRX32
+
+DESCRIPTION 'Microsoft (R) OLE 2.0 Proxy/Stub DLL 1.00'
+
+EXPORTS
+
+ DllGetClassObject PRIVATE
+ DllCanUnloadNow PRIVATE
diff --git a/private/ole32/oleprx32/proxy/stdrpc.hxx b/private/ole32/oleprx32/proxy/stdrpc.hxx
new file mode 100644
index 000000000..83524a570
--- /dev/null
+++ b/private/ole32/oleprx32/proxy/stdrpc.hxx
@@ -0,0 +1,66 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: stdrpc.hxx
+//
+// Contents: Private header file for building interface proxies and stubs.
+//
+// Classes: CStreamOnMessage
+//
+// Functions:
+//
+// History: 4-Jul-93 ShannonC Created
+// 3-Aug-93 ShannonC Changes for NT511 and IDispatch support.
+// 10-Oct-93 ShannonC Changed to new IRpcChannelBuffer interface.
+// 22-Sep-94 MikeSe Moved from CINC and simplified.
+//
+//--------------------------------------------------------------------------
+#ifndef __STDRPC_HXX__
+#define __STDRPC_HXX__
+
+#define _OLE2ANAC_H_
+#include <windows.h>
+
+class CStreamOnMessage : public IStream
+{
+
+ public:
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj);
+ virtual ULONG STDMETHODCALLTYPE AddRef();
+ virtual ULONG STDMETHODCALLTYPE Release();
+ virtual HRESULT STDMETHODCALLTYPE Read(VOID HUGEP *pv, ULONG cb, ULONG *pcbRead);
+ virtual HRESULT STDMETHODCALLTYPE Write(VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten) ;
+ virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition) ;
+ virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize) ;
+ virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten) ;
+ virtual HRESULT STDMETHODCALLTYPE Commit(DWORD grfCommitFlags) ;
+ virtual HRESULT STDMETHODCALLTYPE Revert();
+ virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) ;
+ virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) ;
+ virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG *pstatstg, DWORD grfStatFlag) ;
+ virtual HRESULT STDMETHODCALLTYPE Clone(IStream * *ppstm) ;
+
+ CStreamOnMessage(unsigned char **ppMessageBuffer);
+ CStreamOnMessage(unsigned char **ppMessageBuffer, unsigned long cbMax);
+
+ unsigned char *pStartOfStream;
+ unsigned char **ppBuffer;
+ unsigned long cbMaxStreamLength;
+ ULONG ref_count;
+};
+
+#endif //__STDRPC_HXX__
+
diff --git a/private/ole32/oleprx32/proxy/transmit.cxx b/private/ole32/oleprx32/proxy/transmit.cxx
new file mode 100644
index 000000000..8d3e7a75d
--- /dev/null
+++ b/private/ole32/oleprx32/proxy/transmit.cxx
@@ -0,0 +1,4246 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: transmit.cxx
+//
+// Contents: Support for Windows/OLE data types for oleprx32.dll.
+// Used to be transmit_as routines, now user_marshal routines.
+//
+// Functions: HGLOBAL_UserSize
+// HGLOBAL_UserMarshal
+// HGLOBAL_UserUnmarshal
+// HGLOBAL_UserFree
+// HMETAFILEPICT_UserSize
+// HMETAFILEPICT_UserMarshal
+// HMETAFILEPICT_UserUnmarshal
+// HMETAFILEPICT_UserFree
+// HENHMETAFILE_UserSize
+// HENHMETAFILE_UserMarshal
+// HENHMETAFILE_UserUnmarshal
+// HENHMETAFILE_UserFree
+// HBITMAP_UserSize
+// HBITMAP_UserMarshal
+// HBITMAP_UserUnmarshal
+// HBITMAP_UserFree
+// HBRUSH_UserSize
+// HBRUSH_UserMarshal
+// HBRUSH_UserUnmarshal
+// HBRUSH_UserFree
+// STGMEDIUM_UserSize
+// STGMEDIUM_UserMarshal
+// STGMEDIUM_UserUnmarshal
+// STGMEDIUM_UserFree
+// HACCEL_UserSize
+// HACCEL_UserMarshal
+// HACCEL_UserUnmarshal
+// HACCEL_UserFree
+// HWND_UserSize
+// HWND_UserMarshal
+// HWND_UserUnmarshal
+// HWND_UserFree
+// HMENU_UserSize
+// HMENU_UserMarshal
+// HMENU_UserUnmarshal
+// HMENU_UserFree
+// CLIPFORMAT_UserSize
+// CLIPFORMAT_UserMarshal
+// CLIPFORMAT_UserUnmarshal
+// CLIPFORMAT_UserFree
+//
+// History: 24-Aug-93 ShannonC Created
+// 24-Nov-93 ShannonC Added HGLOBAL
+// 14-May-94 DavePl Added HENHMETAFILE
+// 18-May-94 ShannonC Added HACCEL, UINT, WPARAM
+// 19-May-94 DavePl Added HENHMETAFILE to STGMEDIUM code
+// May-95 Ryszardk Wrote all the _User* routines
+// Feb-96 Ryszardk Added CLIPFORMAT support
+//
+//--------------------------------------------------------------------------
+#include "stdrpc.hxx"
+#pragma hdrstop
+
+#include <oleauto.h>
+#include <objbase.h>
+#include "transmit.h"
+#include <rpcwdt.h>
+#include <storext.h>
+#include "widewrap.h"
+
+
+WINOLEAPI_(void) ReleaseStgMedium(LPSTGMEDIUM pStgMed);
+
+#pragma code_seg(".orpc")
+
+EXTERN_C const CLSID CLSID_MyPSFactoryBuffer = {0x6f11fe5c,0x2fc5,0x101b,{0x9e,0x45,0x00,0x00,0x0b,0x65,0xc7,0xef}};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// class: CPunkForRelease
+//
+// purpose: special IUnknown for remoted STGMEDIUMs
+//
+// history: 02-Mar-94 Rickhi Created
+//
+// notes: This class is used to do the cleanup correctly when certain
+// types of storages are passed between processes or machines
+// in Nt and Chicago.
+//
+// On NT, GLOBAL, GDI, and BITMAP handles cannot be passed between
+// processes, so we actually copy the whole data and create a
+// new handle in the receiving process. However, STGMEDIUMs have
+// this weird behaviour where if PunkForRelease is non-NULL then
+// the sender is responsible for cleanup, not the receiver. Since
+// we create a new handle in the receiver, we would leak handles
+// if we didnt do some special processing. So, we do the
+// following...
+//
+// During STGMEDIUM_UserUnmarshal, if there is a pUnkForRelease
+// replace it with a CPunkForRelease. When Release is called
+// on the CPunkForRelease, do the necessary cleanup work,
+// then call the real PunkForRelease.
+//
+//+-------------------------------------------------------------------------
+
+class CPunkForRelease : public IUnknown
+{
+public:
+ CPunkForRelease( STGMEDIUM *pStgMed, ulong fTopLayerOnly);
+
+ // IUnknown Methods
+ STDMETHOD(QueryInterface)(REFIID riid, void **ppunk);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+private:
+ ~CPunkForRelease(void);
+
+ ULONG _cRefs; // reference count
+ ULONG _fTopLayerMFP:1; // optimisation flag for Chicago
+ STGMEDIUM _stgmed; // storage medium
+ IUnknown * _pUnkForRelease; // real pUnkForRelease
+};
+
+
+inline CPunkForRelease::CPunkForRelease(
+ STGMEDIUM * pStgMed,
+ ulong fTopLayerMFPict
+ ) :
+ _cRefs(1),
+ _fTopLayerMFP( fTopLayerMFPict),
+ _stgmed(*pStgMed)
+{
+ // NOTE: we assume the caller has verified pStgMed is not NULL,
+ // and the pUnkForRelease is non-null, otherwise there is no
+ // point in constructing this object. The tymed must also be
+ // one of the special ones.
+
+ UserNdrAssert(pStgMed);
+ UserNdrAssert(pStgMed->tymed == TYMED_HGLOBAL ||
+ pStgMed->tymed == TYMED_GDI ||
+ pStgMed->tymed == TYMED_MFPICT ||
+ pStgMed->tymed == TYMED_ENHMF);
+
+ _pUnkForRelease = pStgMed->pUnkForRelease;
+}
+
+
+inline CPunkForRelease::~CPunkForRelease()
+{
+ // since we really have our own copies of these handles' data, just
+ // pretend like the callee is responsible for the release, and
+ // recurse into ReleaseStgMedium to do the cleanup.
+
+ _stgmed.pUnkForRelease = NULL;
+
+ // There is this weird optimized case of Chicago MFPICT when we have two
+ // layers with a HENHMETAFILE handle inside. Top layer is an HGLOBAL.
+
+ if ( _fTopLayerMFP )
+ GlobalFree( _stgmed.hGlobal );
+ else
+ ReleaseStgMedium( &_stgmed );
+
+ // release the callers punk
+ _pUnkForRelease->Release();
+}
+
+STDMETHODIMP_(ULONG) CPunkForRelease::AddRef(void)
+{
+ InterlockedIncrement((LONG *)&_cRefs);
+ return _cRefs;
+}
+
+STDMETHODIMP_(ULONG) CPunkForRelease::Release(void)
+{
+ long Ref = _cRefs - 1;
+
+ UserNdrAssert( _cRefs );
+
+ if (InterlockedDecrement((LONG *)&_cRefs) == 0)
+ {
+ // null out the vtable.
+ long * p = (long *)this;
+ *p = 0;
+
+ delete this;
+ return 0;
+ }
+ else
+ return Ref;
+}
+
+STDMETHODIMP CPunkForRelease::QueryInterface(REFIID riid, void **ppv)
+{
+ if (IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppv = (void *)(IUnknown *) this;
+ AddRef();
+ return S_OK;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+}
+
+
+// These methods are needed as the object is used for interface marshaling.
+
+/***************************************************************************/
+STDMETHODIMP_(ULONG) CStreamOnMessage::AddRef( THIS )
+{
+ return ref_count += 1;
+}
+
+/***************************************************************************/
+STDMETHODIMP CStreamOnMessage::Clone(THIS_ IStream * *ppstm)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+/***************************************************************************/
+STDMETHODIMP CStreamOnMessage::Commit(THIS_ DWORD grfCommitFlags)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+/***************************************************************************/
+STDMETHODIMP CStreamOnMessage::CopyTo(THIS_ IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+/***************************************************************************/
+CStreamOnMessage::CStreamOnMessage(unsigned char **ppMessageBuffer)
+ : ref_count(1), ppBuffer(ppMessageBuffer), cbMaxStreamLength(0xFFFFFFFF)
+{
+ pStartOfStream = *ppMessageBuffer;
+}
+
+/***************************************************************************/
+STDMETHODIMP CStreamOnMessage::LockRegion(THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+/***************************************************************************/
+STDMETHODIMP CStreamOnMessage::QueryInterface( REFIID riid, LPVOID FAR* ppvObj)
+{
+ if (IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppvObj = (IUnknown *) this;
+ ref_count += 1;
+ return ResultFromScode(S_OK);
+ }
+ else if (IsEqualIID(riid, IID_IStream))
+ {
+ *ppvObj = (IStream *) this;
+ ref_count += 1;
+ return ResultFromScode(S_OK);
+ }
+ else
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+/***************************************************************************/
+STDMETHODIMP CStreamOnMessage::Read(THIS_ VOID HUGEP *pv,
+ ULONG cb, ULONG *pcbRead)
+{
+ memcpy( pv, *ppBuffer, cb );
+ *ppBuffer += cb;
+ if (pcbRead != NULL)
+ *pcbRead = cb;
+ return ResultFromScode(S_OK);
+}
+
+/***************************************************************************/
+STDMETHODIMP_(ULONG) CStreamOnMessage::Release( THIS )
+{
+ ref_count -= 1;
+ if (ref_count == 0)
+ {
+ delete this;
+ return 0;
+ }
+ else
+ return ref_count;
+
+}
+
+/***************************************************************************/
+STDMETHODIMP CStreamOnMessage::Revert(THIS)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+/***************************************************************************/
+STDMETHODIMP CStreamOnMessage::Seek(THIS_ LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition)
+{
+ ULONG pos;
+
+ // Verify that the offset isn't out of range.
+ if (dlibMove.HighPart != 0)
+ return ResultFromScode( E_FAIL );
+
+ // Determine the new seek pointer.
+ switch (dwOrigin)
+ {
+ case STREAM_SEEK_SET:
+ pos = dlibMove.LowPart;
+ break;
+
+ case STREAM_SEEK_CUR:
+ /* Must use signed math here. */
+ pos = *ppBuffer - pStartOfStream;
+ if ((long) dlibMove.LowPart < 0 &&
+ pos < (unsigned long) - (long) dlibMove.LowPart)
+ return ResultFromScode( E_FAIL );
+ pos += (long) dlibMove.LowPart;
+ break;
+
+ case STREAM_SEEK_END:
+ return ResultFromScode(E_NOTIMPL);
+ break;
+
+ default:
+ return ResultFromScode( E_FAIL );
+ }
+
+ // Set the seek pointer.
+ *ppBuffer = pStartOfStream + pos;
+ if (plibNewPosition != NULL)
+ {
+ plibNewPosition->LowPart = pos;
+ plibNewPosition->HighPart = 0;
+ }
+ return ResultFromScode(S_OK);
+}
+
+/***************************************************************************/
+STDMETHODIMP CStreamOnMessage::SetSize(THIS_ ULARGE_INTEGER libNewSize)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+/***************************************************************************/
+STDMETHODIMP CStreamOnMessage::Stat(THIS_ STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+/***************************************************************************/
+STDMETHODIMP CStreamOnMessage::UnlockRegion(THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+/***************************************************************************/
+STDMETHODIMP CStreamOnMessage::Write(THIS_ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ // Write the data.
+ memcpy( *ppBuffer, pv, cb );
+ if (pcbWritten != NULL)
+ *pcbWritten = cb;
+ *ppBuffer += cb;
+ return ResultFromScode(S_OK);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CLIPFORMAT_UserSize
+//
+// Synopsis: Sizes a CLIPFORMAT.
+//
+// Derivation: A union of a long and a string.
+//
+// history: Feb-96 Ryszardk Created
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+CLIPFORMAT_UserSize(
+ unsigned long * pFlags,
+ unsigned long Offset,
+ CLIPFORMAT * pObject )
+{
+ if ( !pObject )
+ return( Offset );
+
+ // userCLIPFORMAT is an encapsulated union with a string.
+
+ LENGTH_ALIGN( Offset, 3);
+ Offset += sizeof(long) + sizeof(void *);
+
+ if ( REMOTE_CLIPFORMAT( pFlags, pObject ) )
+ {
+ wchar_t temp[CLIPFORMAT_BUFFER_MAX];
+
+ int ret = GetClipboardFormatName( *pObject,
+ temp,
+ CLIPFORMAT_BUFFER_MAX - 1 );
+
+ if ( ret )
+ {
+ Offset += 3 * sizeof(long) + ret * sizeof(wchar_t);
+ }
+ else
+ RpcRaiseException( DV_E_CLIPFORMAT );
+ }
+
+ return( Offset );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CLIPFORMAT_UserMarshal
+//
+// Synopsis: Marshals a CLIPFORMAT.
+//
+// Derivation: A union of a long and a string.
+//
+// history: Feb-96 Ryszardk Created
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+CLIPFORMAT_UserMarshal(
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ CLIPFORMAT * pObject )
+{
+ if ( !pObject )
+ return pBuffer;
+
+ // userCLIPFORMAT is an encapsulated union with a string.
+
+ ALIGN( pBuffer, 3);
+
+ if ( REMOTE_CLIPFORMAT( pFlags, pObject ) )
+ {
+ // sending a wide string
+
+ unsigned long ret;
+
+ // Custom clipformat is between c000 and ffff.
+
+ *(PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER;
+ *(PULONG_LV_CAST pBuffer)++ = (ulong) *pObject;
+
+ // On Chicago this is GetClipboardFormatNameX.
+ // When the buffer is too short, this call would still
+ // return a decent, null terminated, truncated string.
+ //
+
+ ret = (ulong) GetClipboardFormatName( *pObject,
+ (wchar_t *)(pBuffer + 12),
+ CLIPFORMAT_BUFFER_MAX - 1
+ ) + 1;
+
+ // conformat size etc. for string.
+
+ *(PULONG_LV_CAST pBuffer)++ = ret;
+ *(PULONG_LV_CAST pBuffer)++ = 0;
+ *(PULONG_LV_CAST pBuffer)++ = ret;
+
+ if ( ret )
+ {
+ // skip the string in the bbuffer, including the terminator
+
+ pBuffer += ret * sizeof(wchar_t);
+ }
+ else
+ RpcRaiseException( DV_E_CLIPFORMAT );
+ }
+ else
+ {
+ // sending the number itself
+
+ *(PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER;
+ *(PULONG_LV_CAST pBuffer)++ = (ulong) *pObject;
+ }
+
+ return( pBuffer );
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CLIPFORMAT_UserUnmarshal
+//
+// Synopsis: Unmarshals a CLIPFORMAT; registers if needed.
+//
+// Derivation: A union of a long and a string.
+//
+// history: Feb-96 Ryszardk Created
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+CLIPFORMAT_UserUnmarshal(
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ CLIPFORMAT * pObject )
+{
+ ulong UnionDisc;
+ UINT cf;
+
+ ALIGN( pBuffer, 3);
+
+ UnionDisc = *(PULONG_LV_CAST pBuffer)++;
+ cf = (WORD) *(PULONG_LV_CAST pBuffer)++;
+
+ if ( WDT_DATA_MARKER == UnionDisc )
+ {
+ ulong ConfSize = *(ulong*)pBuffer;
+
+ // skip to the beginning of the string
+
+ pBuffer += 3 * sizeof(long);
+
+ // The string in the buffer terminates with null.
+ //
+ // On Chicago this is RegisterClipboardFormatX.
+
+ cf = RegisterClipboardFormat( (wchar_t *)pBuffer );
+
+ if ( cf == 0 )
+ RpcRaiseException( DV_E_CLIPFORMAT );
+
+ pBuffer += ConfSize * sizeof(wchar_t);
+ }
+
+ *pObject = cf;
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CLIPFORMAT_UserUnmarshal
+//
+// Synopsis: Frees remnants of CLIPFORMAT.
+//
+// Derivation: A union of a long and a string.
+//
+// history: Feb-96 Ryszardk Created
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+CLIPFORMAT_UserFree(
+ unsigned long * pFlags,
+ CLIPFORMAT * pObject )
+{
+ // Nothing to free, as nothing gets allocated when we unmarshal.
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: SNB_UserSize
+//
+// Synopsis: Sizes an SNB.
+//
+// Derivation: An array of strings in one block of memory.
+//
+// history: June-95 Ryszardk Created, based on SNB_*_xmit.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+SNB_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ SNB * pSnb )
+{
+ if ( ! pSnb )
+ return Offset;
+
+ // calculate the number of strings and characters (with their terminators)
+
+ ULONG ulCntStr = 0;
+ ULONG ulCntChar = 0;
+
+ if (pSnb && *pSnb)
+ {
+ SNB snb = *pSnb;
+
+ WCHAR *psz = *snb;
+ while (psz)
+ {
+ ulCntChar += lstrlenW(psz) + 1;
+ ulCntStr++;
+ snb++;
+ psz = *snb;
+ }
+ }
+
+ // The wire size is: conf size, 2 fields and the wchars.
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ return ( Offset + 3 * sizeof(long) + ulCntChar * sizeof( WCHAR ) );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SNB_UserMarshall
+//
+// Synopsis: Marshalls an SNB into the RPC buffer.
+//
+// Derivation: An array of strings in one block of memory.
+//
+// history: June-95 Ryszardk Created, based on SNB_*_xmit.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+SNB_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ SNB * pSnb )
+{
+ UserNdrDebugOut((UNDR_FORCE, "SNB_UserMarshal\n"));
+
+ if ( ! pSnb )
+ return pBuffer;
+
+ // calculate the number of strings and characters (with their terminators)
+
+ ULONG ulCntStr = 0;
+ ULONG ulCntChar = 0;
+
+ if (pSnb && *pSnb)
+ {
+ SNB snb = *pSnb;
+
+ WCHAR *psz = *snb;
+ while (psz)
+ {
+ ulCntChar += lstrlenW(psz) + 1;
+ ulCntStr++;
+ snb++;
+ psz = *snb;
+ }
+ }
+
+ // conformant size
+
+ ALIGN( pBuffer, 3 );
+ *( PULONG_LV_CAST pBuffer)++ = ulCntChar;
+
+ // fields
+
+ *( PULONG_LV_CAST pBuffer)++ = ulCntStr;
+ *( PULONG_LV_CAST pBuffer)++ = ulCntChar;
+
+ // actual strings only
+
+ if ( pSnb && *pSnb )
+ {
+ // There is a NULL string pointer to mark the end of the pointer array.
+ // However, the strings don't have to follow tightly.
+ // Hence, we have to copy one string at a time.
+
+ SNB snb = *pSnb;
+ WCHAR *pszSrc;
+
+ while (pszSrc = *snb++)
+ {
+ ULONG ulCopyLen = (lstrlenW(pszSrc) + 1) * sizeof(WCHAR);
+
+ WdtpMemoryCopy( pBuffer, pszSrc, ulCopyLen );
+ pBuffer += ulCopyLen;
+ }
+ }
+
+ return pBuffer;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SNB_UserUnmarshall
+//
+// Synopsis: Unmarshalls an SNB from the RPC buffer.
+//
+// Derivation: An array of strings in one block of memory.
+//
+// history: June-95 Ryszardk Created, based on SNB_*_xmit.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+SNB_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ SNB * pSnb )
+{
+ UserNdrDebugOut((UNDR_FORCE, "SNB_UserUnmarshal\n"));
+
+ ALIGN( pBuffer, 3 );
+
+ // conf size
+
+ unsigned long ulCntChar = *( PULONG_LV_CAST pBuffer)++;
+
+ // fields
+
+ unsigned long ulCntStr = *( PULONG_LV_CAST pBuffer)++;
+ pBuffer += sizeof(long);
+
+ // no reusage of pSNB.
+
+ if ( *pSnb )
+ WdtpFree( pFlags, *pSnb );
+
+ if ( ulCntStr == 0 )
+ {
+ *pSnb = NULL;
+ return pBuffer;
+ }
+
+ // construct the SNB.
+
+ SNB Snb = (SNB) WdtpAllocate( pFlags,
+ ( (ulCntStr + 1) * sizeof(WCHAR *) +
+ ulCntChar * sizeof(WCHAR)) );
+
+ *pSnb = Snb;
+
+ if (Snb)
+ {
+ // create the pointer array within the SNB.
+
+ WCHAR *pszSrc = (WCHAR *) pBuffer;
+ WCHAR *pszTgt = (WCHAR *) (Snb + ulCntStr + 1); // right behind array
+
+ for (ULONG i = ulCntStr; i > 0; i--)
+ {
+ *Snb++ = pszTgt;
+
+ ULONG ulLen = lstrlenW(pszSrc) + 1;
+ pszSrc += ulLen;
+ pszTgt += ulLen;
+ }
+
+ *Snb++ = NULL;
+
+ // Copy the actual strings.
+ // We can do a block copy here as we packed them tight in the buffer.
+ // Snb points right behind the lastarray of pointers within the SNB.
+
+ WdtpMemoryCopy( Snb, pBuffer, ulCntChar * sizeof(WCHAR) );
+ pBuffer += ulCntChar * sizeof(WCHAR);
+ }
+
+ return pBuffer;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SNB_UserFree
+//
+// Synopsis: Frees an SNB.
+//
+// Derivation: An array of strings in one block of memory.
+//
+// history: June-95 Ryszardk Created, based on SNB_*_xmit.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+SNB_UserFree(
+ unsigned long * pFlags,
+ SNB * pSnb )
+{
+ if ( pSnb && *pSnb )
+ WdtpFree( pFlags, *pSnb );
+}
+
+
+// #########################################################################
+//
+// WdtpVoidStar helper
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpVoidStar_UserSize
+//
+// Synopsis: Sizes a remotable void star as ulong.
+//
+// history: June-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+WdtpVoidStar_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ unsigned long * pVoid )
+{
+ if ( !pVoid )
+ return Offset;
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ return( Offset + 4 ) ;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpVoidStar_UserMarshall
+//
+// Synopsis: Marshalls a remotable void star as ulong.
+//
+// history: June-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+WdtpVoidStar_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ unsigned long * pVoid )
+{
+ if ( !pVoid )
+ return pBuffer;
+
+ ALIGN( pBuffer, 3 );
+
+ *( PULONG_LV_CAST pBuffer)++ = *pVoid;
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpVoidStar_UserUnmarshall
+//
+// Synopsis: Unmarshalls a remotable void star as ulong.
+//
+// history: June-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+WdtpVoidStar_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ unsigned long * pVoid )
+{
+ ALIGN( pBuffer, 3 );
+
+ *pVoid= *( PULONG_LV_CAST pBuffer)++;
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpVoidStar_UserFree
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+WdtpVoidStar_UserFree(
+ unsigned long * pFlags,
+ unsigned long * pVoid )
+{
+}
+
+
+// #########################################################################
+//
+// WdtpRemotableHandle helper
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpRemotableHandle_UserSize
+//
+// Synopsis: Sizes a void star handle as a union with ulong.
+//
+// history: Dec-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+WdtpRemotableHandle_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ unsigned long * pHandle )
+{
+ if ( !pHandle )
+ return Offset;
+
+ if ( *pHandle && DIFFERENT_MACHINE_CALL(*pFlags) )
+ RpcRaiseException( RPC_S_INVALID_TAG );
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ return( Offset + 8 ) ;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpRemotableHandle_UserMarshall
+//
+// Synopsis: Marshalls a handle a union with ulong.
+//
+// history: Dec-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+WdtpRemotableHandle_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ unsigned long * pHandle )
+{
+ if ( !pHandle )
+ return pBuffer;
+
+ if ( *pHandle && DIFFERENT_MACHINE_CALL(*pFlags) )
+ RpcRaiseException( RPC_S_INVALID_TAG );
+
+ ALIGN( pBuffer, 3 );
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = *pHandle;
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpRemotableHandle_UserUnmarshall
+//
+// Synopsis: Unmarshalls a remotable void star as union with ulong.
+//
+// history: Dec-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+WdtpRemotableHandle_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ unsigned long * pHandle )
+{
+ unsigned long HandleMarker;
+
+ ALIGN( pBuffer, 3 );
+
+ HandleMarker = *( PULONG_LV_CAST pBuffer)++;
+
+ if ( HandleMarker == WDT_HANDLE_MARKER )
+ *pHandle = *( PULONG_LV_CAST pBuffer)++;
+ else
+ RpcRaiseException( RPC_S_INVALID_TAG );
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpRemotableHandle_UserFree
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+WdtpRemotableHandle_UserFree(
+ unsigned long * pFlags,
+ unsigned long * pHandle )
+{
+}
+
+//+-------------------------------------------------------------------------
+
+//
+// Function: HWND_UserSize
+//
+// Synopsis: Sizes an HWND handle.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+HWND_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ HWND * pH )
+{
+ return WdtpRemotableHandle_UserSize( pFlags, Offset, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HWND_UserMarshall
+//
+// Synopsis: Marshalls an HWND handle into the RPC buffer.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HWND_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HWND * pH )
+{
+ return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HWND_UserUnmarshall
+//
+// Synopsis: Unmarshalls an HWND handle from the RPC buffer.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HWND_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HWND * pH )
+{
+ return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HWND_UserFree
+//
+// Synopsis: Shouldn't be called.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+HWND_UserFree(
+ unsigned long * pFlags,
+ HWND * pH )
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HMENU_UserSize
+//
+// Synopsis: Sizes an HMENU handle.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+HMENU_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ HMENU * pH )
+{
+ return WdtpRemotableHandle_UserSize( pFlags, Offset, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HMENU_UserMarshall
+//
+// Synopsis: Marshalls an HMENU handle into the RPC buffer.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HMENU_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HMENU * pH )
+{
+ return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HMENU_UserUnmarshall
+//
+// Synopsis: Unmarshalls an HMENU handle from the RPC buffer.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HMENU_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HMENU * pH )
+{
+ return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HMENU_UserFree
+//
+// Synopsis: Free an HMENU.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+HMENU_UserFree(
+ unsigned long * pFlags,
+ HMENU * pH )
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HACCEL_UserSize
+//
+// Synopsis: Sizes an HACCEL handle.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+HACCEL_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ HACCEL * pH )
+{
+ return WdtpRemotableHandle_UserSize( pFlags, Offset, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HACCEL_UserMarshall
+//
+// Synopsis: Marshalls an HACCEL handle into the RPC buffer.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HACCEL_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HACCEL * pH )
+{
+ return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HACCEL_UserUnmarshall
+//
+// Synopsis: Unmarshalls an HACCEL handle from the RPC buffer.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HACCEL_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HACCEL * pH )
+{
+ return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HACCEL_UserFree
+//
+// Synopsis: Free an HACCEL.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+HACCEL_UserFree(
+ unsigned long * pFlags,
+ HACCEL * pH )
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HBRUSH_UserSize
+//
+// Synopsis: Sizes an HBRUSH handle.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+HBRUSH_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ HBRUSH * pH )
+{
+ return WdtpRemotableHandle_UserSize( pFlags, Offset, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HBRUSH_UserMarshall
+//
+// Synopsis: Marshalls an HBRUSH handle into the RPC buffer.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HBRUSH_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HBRUSH * pH )
+{
+ return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HBRUSH_UserUnmarshall
+//
+// Synopsis: Unmarshalls an HBRUSH handle from the RPC buffer.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HBRUSH_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HBRUSH * pH )
+{
+ return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HBRUSH_UserFree
+//
+// Synopsis: Free an HBRUSH.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+HBRUSH_UserFree(
+ unsigned long * pFlags,
+ HBRUSH * pH )
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HICON_UserSize
+//
+// Synopsis: Sizes an HICON handle.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+HICON_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ HICON * pH )
+{
+ return WdtpRemotableHandle_UserSize( pFlags, Offset, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HICON_UserMarshall
+//
+// Synopsis: Marshalls an HICON handle into the RPC buffer.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HICON_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HICON * pH )
+{
+ return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HICON_UserUnmarshall
+//
+// Synopsis: Unmarshalls an HICON handle from the RPC buffer.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HICON_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HICON * pH )
+{
+ return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HICON_UserFree
+//
+// Synopsis: Free an HICON.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+HICON_UserFree(
+ unsigned long * pFlags,
+ HICON * pH )
+{
+}
+
+
+// #########################################################################
+//
+// HGLOBAL.
+// See transmit.h for explanation of global data/handle passing.
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: HGLOBAL_UserSize
+//
+// Synopsis: Get the wire size the HGLOBAL handle and data.
+//
+// Derivation: Conformant struct with a flag field:
+// align + 12 + data size.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+HGLOBAL_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ HGLOBAL * pGlobal)
+{
+ if ( !pGlobal )
+ return Offset;
+
+ // userHGLOBAL: the encapsulated union.
+ // Discriminant and then handle or pointer from the union arm.
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ Offset += sizeof(long) + sizeof(void*);
+
+ if ( ! *pGlobal )
+ return Offset;
+
+ if ( HGLOBAL_DATA_PASSING(*pFlags) )
+ {
+ unsigned long ulDataSize = GlobalSize( *pGlobal );
+
+ Offset += 3 * sizeof(long) + ulDataSize;
+ }
+
+ return( Offset );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HGLOBAL_UserMarshall
+//
+// Synopsis: Marshalls an HGLOBAL object into the RPC buffer.
+//
+// Derivation: Conformant struct with a flag field:
+// align, size, null flag, size, data (bytes, if any)
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HGLOBAL_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HGLOBAL * pGlobal)
+{
+ if ( !pGlobal )
+ return pBuffer;
+
+ // We marshal a null handle, too.
+
+ UserNdrDebugOut((UNDR_OUT4, "HGLOBAL_UserMarshal\n"));
+
+ ALIGN( pBuffer, 3 );
+
+ // Discriminant of the encapsulated union and union arm.
+
+ if ( HGLOBAL_DATA_PASSING(*pFlags) )
+ {
+ unsigned long ulDataSize;
+
+ // userHGLOBAL
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) *pGlobal;
+
+ if ( ! *pGlobal )
+ return pBuffer;
+
+ // FLAGGED_BYTE_BLOB
+
+ ulDataSize = GlobalSize( *pGlobal );
+
+ *( PULONG_LV_CAST pBuffer)++ = ulDataSize;
+
+ // Handle is the non-null flag
+
+ *( PULONG_LV_CAST pBuffer)++ = (ulong)*pGlobal;
+ *( PULONG_LV_CAST pBuffer)++ = ulDataSize;
+
+ if( ulDataSize )
+ {
+ void * pData = GlobalLock( *pGlobal);
+ memcpy( pBuffer, pData, ulDataSize );
+ GlobalUnlock( *pGlobal);
+ }
+
+ pBuffer += ulDataSize;
+ }
+ else
+ {
+ // Sending a handle.
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) *pGlobal;
+ }
+
+ return( pBuffer );
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpGlobalUnmarshal
+//
+// Synopsis: Unmarshalls an HGLOBAL object from the RPC buffer.
+//
+// Derivation: Conformant struct with a flag field:
+// align, size, null flag, size, data (bytes, if any)
+//
+// Note: Reallocation is forbidden when the hglobal is part of
+// an [in,out] STGMEDIUM in IDataObject::GetDataHere.
+// This affects only data passing with old handles being
+// non null.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+WdtpGlobalUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HGLOBAL * pGlobal,
+ BOOL fCanReallocate )
+{
+ unsigned long ulDataSize, fHandle, UnionDisc;
+ HGLOBAL hGlobal;
+
+ ALIGN( pBuffer, 3 );
+
+ UnionDisc = *( PULONG_LV_CAST pBuffer)++;
+ hGlobal = (HGLOBAL) *( PULONG_LV_CAST pBuffer)++;
+
+ if ( IS_DATA_MARKER( UnionDisc) )
+ {
+ if ( ! hGlobal )
+ {
+ if ( *pGlobal )
+ GlobalFree( *pGlobal );
+ *pGlobal = NULL;
+ return pBuffer;
+ }
+
+ // There is a handle data on wire.
+
+ ulDataSize = *( PULONG_LV_CAST pBuffer)++;
+ // fhandle and data size again.
+ pBuffer += 8;
+
+ if ( *pGlobal )
+ {
+ // Check for reallocation
+
+ if ( GlobalSize( *pGlobal ) == ulDataSize )
+ hGlobal = *pGlobal;
+ else
+ {
+ if ( fCanReallocate )
+ {
+ // hGlobal = GlobalReAlloc( *pGlobal, ulDataSize, GMEM_MOVEABLE );
+
+ GlobalFree( *pGlobal );
+ hGlobal = GlobalAlloc( GMEM_MOVEABLE, ulDataSize );
+ }
+ else
+ {
+ if ( GlobalSize(*pGlobal) < ulDataSize )
+ RpcRaiseException( STG_E_MEDIUMFULL );
+ else
+ hGlobal = *pGlobal;
+ }
+ }
+ }
+ else
+ {
+ // allocate a new block
+
+ hGlobal = GlobalAlloc( GMEM_MOVEABLE, ulDataSize );
+ }
+
+ if ( hGlobal == NULL )
+ RpcRaiseException(E_OUTOFMEMORY);
+ else
+ {
+ void * pData = GlobalLock( hGlobal);
+ memcpy( pData, pBuffer, ulDataSize );
+ pBuffer += ulDataSize;
+ GlobalUnlock( hGlobal);
+ }
+ }
+ else
+ {
+ // Sending a handle only.
+ // Reallocation problem doesn't apply to handle passing.
+
+ if ( *pGlobal != hGlobal && *pGlobal )
+ GlobalFree( *pGlobal );
+ }
+
+ *pGlobal = hGlobal;
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HGLOBAL_UserUnmarshall
+//
+// Synopsis: Unmarshalls an HGLOBAL object from the RPC buffer.
+//
+// Derivation: Conformant struct with a flag field:
+// align, size, null flag, size, data (bytes, if any)
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HGLOBAL_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HGLOBAL * pGlobal)
+{
+ return( WdtpGlobalUnmarshal( pFlags,
+ pBuffer,
+ pGlobal,
+ TRUE ) ); // reallocation possible
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HGLOBAL_UserFree
+//
+// Synopsis: Free an HGLOBAL.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+HGLOBAL_UserFree(
+ unsigned long * pFlags,
+ HGLOBAL * pGlobal)
+{
+ if( pGlobal && *pGlobal )
+ {
+ if ( HGLOBAL_DATA_PASSING(*pFlags) )
+ GlobalFree( *pGlobal);
+ }
+}
+
+
+// #########################################################################
+//
+// HMETAFILEPICT
+// See transmit.h for explanation of hglobal vs. gdi data/handle passing.
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: HMETAFILEPICT_UserSize
+//
+// Synopsis: Get the wire size the HMETAFILEPICT handle and data.
+//
+// Derivation: Union of a long and the meta file pict handle.
+// Then struct with top layer (and a hmetafile handle).
+// The the representation of the metafile.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+HMETAFILEPICT_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ HMETAFILEPICT * pHMetaFilePict )
+{
+ if ( !pHMetaFilePict )
+ return Offset;
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ // Discriminant of the encapsulated union and the union arm.
+
+ Offset += 8;
+
+ if ( ! *pHMetaFilePict )
+ return Offset;
+
+ if ( HGLOBAL_HANDLE_PASSING(*pFlags) )
+ return Offset;
+
+ // Now, this is a two layer object with HGLOBAL on top.
+ // Upper layer - hglobal part - needs to be sent as data.
+
+ METAFILEPICT *
+ pMFP = (METAFILEPICT*) GlobalLock( *(HANDLE *)pHMetaFilePict );
+
+ if ( pMFP == NULL )
+ RpcRaiseException( E_OUTOFMEMORY );
+
+ // Upper layer: 3 long fields + ptr marker + enc. union
+
+ Offset += 4 * sizeof(long) + sizeof(userHMETAFILE);
+
+ // The lower part is a metafile handle.
+
+ if ( GDI_DATA_PASSING( *pFlags) )
+ {
+ ulong ulDataSize = GetMetaFileBitsEx( pMFP->hMF, 0 , NULL );
+
+ Offset += 12 + ulDataSize;
+ }
+
+ GlobalUnlock( *(HANDLE *)pHMetaFilePict );
+
+ return( Offset ) ;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HMETAFILEPICT_UserMarshal
+//
+// Synopsis: Marshalls an HMETAFILEPICT object into the RPC buffer.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HMETAFILEPICT_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HMETAFILEPICT * pHMetaFilePict )
+{
+ if ( !pHMetaFilePict )
+ return pBuffer;
+
+ UserNdrDebugOut((UNDR_OUT4, "HMETAFILEPICT_UserMarshal\n"));
+
+ ALIGN( pBuffer, 3 );
+
+ if ( HGLOBAL_HANDLE_PASSING(*pFlags) )
+ {
+ // Sending only the top level global handle.
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong)*(HANDLE*)pHMetaFilePict;
+
+ return pBuffer;
+ }
+
+ // userHMETAFILEPICT
+ // We need to send the data from the top (hglobal) layer.
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong)*pHMetaFilePict;
+
+ if ( ! *pHMetaFilePict )
+ return pBuffer;
+
+ // remoteHMETAFILEPICT
+
+ METAFILEPICT * pMFP = (METAFILEPICT*) GlobalLock(
+ *(HANDLE *)pHMetaFilePict );
+ if ( pMFP == NULL )
+ RpcRaiseException( E_OUTOFMEMORY );
+
+ *( PULONG_LV_CAST pBuffer)++ = pMFP->mm;
+ *( PULONG_LV_CAST pBuffer)++ = pMFP->xExt;
+ *( PULONG_LV_CAST pBuffer)++ = pMFP->yExt;
+ *( PULONG_LV_CAST pBuffer)++ = USER_MARSHAL_MARKER;
+
+ // See if the HMETAFILE needs to be sent as data, too.
+
+ if ( GDI_DATA_PASSING(*pFlags) )
+ {
+ // userHMETAFILE
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) pMFP->hMF;
+
+ if ( pMFP->hMF )
+ {
+ ulong ulDataSize = GetMetaFileBitsEx( pMFP->hMF, 0 , NULL );
+
+ // conformant size then the size field
+
+ *( PULONG_LV_CAST pBuffer)++ = ulDataSize;
+ *( PULONG_LV_CAST pBuffer)++ = ulDataSize;
+
+ GetMetaFileBitsEx( pMFP->hMF, ulDataSize , pBuffer );
+
+ pBuffer += ulDataSize;
+ };
+ }
+ else
+ {
+ // Sending only an HMETAFILE handle.
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) pMFP->hMF;
+ }
+
+ GlobalUnlock( *(HANDLE *)pHMetaFilePict );
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HMETAFILEPICT_UserUnmarshal
+//
+// Synopsis: Unmarshalls an HMETAFILEPICT object from the RPC buffer.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HMETAFILEPICT_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBufferStart,
+ HMETAFILEPICT * pHMetaFilePict )
+{
+ unsigned long ulDataSize, fHandle;
+ unsigned char * pBuffer;
+ HMETAFILEPICT hMetaFilePict;
+
+ UserNdrDebugOut((UNDR_OUT4, "HMETAFILEPICT_UserUnmarshal\n"));
+
+ pBuffer = pBufferStart;
+ ALIGN( pBuffer, 3 );
+
+ unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++;
+ hMetaFilePict = (HMETAFILEPICT) *( PULONG_LV_CAST pBuffer)++;
+
+ if ( IS_DATA_MARKER( UnionDisc) && hMetaFilePict )
+ {
+ unsigned long PtrMarker;
+
+ HGLOBAL hGlobal = GlobalAlloc( GMEM_MOVEABLE, sizeof(METAFILEPICT) );
+ hMetaFilePict = (HMETAFILEPICT) hGlobal;
+
+ if ( hMetaFilePict == NULL )
+ RpcRaiseException( E_OUTOFMEMORY );
+
+ METAFILEPICT * pMFP = (METAFILEPICT*) GlobalLock(
+ (HANDLE) hMetaFilePict );
+ if ( pMFP == NULL )
+ RpcRaiseException( E_OUTOFMEMORY );
+
+ pMFP->mm = *( PULONG_LV_CAST pBuffer)++;
+ pMFP->xExt = *( PULONG_LV_CAST pBuffer)++;
+ pMFP->yExt = *( PULONG_LV_CAST pBuffer)++;
+ PtrMarker = *( PULONG_LV_CAST pBuffer)++; // skip marker
+
+ UnionDisc = *( PULONG_LV_CAST pBuffer)++;
+ pMFP->hMF = (HMETAFILE) *( PULONG_LV_CAST pBuffer)++;
+
+ if ( pMFP->hMF && IS_DATA_MARKER( UnionDisc ) )
+ {
+ // conformant size then the size field
+
+ ulong ulDataSize = *( PULONG_LV_CAST pBuffer)++;
+ pBuffer += 4;
+
+ pMFP->hMF = SetMetaFileBitsEx( ulDataSize, (uchar*)pBuffer );
+
+ pBuffer += ulDataSize;
+ }
+
+ GlobalUnlock( (HANDLE) hMetaFilePict );
+ }
+
+ // no reusage, just release the previous one.
+
+ if ( *pHMetaFilePict )
+ {
+ // This may happen on the client only and doesn't depend on
+ // how the other one was passed.
+
+ METAFILEPICT *
+ pMFP = (METAFILEPICT*) GlobalLock( *(HANDLE *)pHMetaFilePict );
+
+ if ( pMFP == NULL )
+ RpcRaiseException( E_OUTOFMEMORY );
+
+ if ( pMFP->hMF )
+ DeleteMetaFile( pMFP->hMF );
+
+ GlobalUnlock( *pHMetaFilePict );
+ GlobalFree( *pHMetaFilePict );
+ }
+
+ *pHMetaFilePict = hMetaFilePict;
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HMETAFILEPICT_UserFree
+//
+// Synopsis: Free an HMETAFILEPICT.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+HMETAFILEPICT_UserFree(
+ unsigned long * pFlags,
+ HMETAFILEPICT * pHMetaFilePict )
+{
+ UserNdrDebugOut((UNDR_FORCE, "HMETAFILEPICT_UserFree\n"));
+
+ if( pHMetaFilePict && *pHMetaFilePict )
+ {
+ if ( HGLOBAL_HANDLE_PASSING(*pFlags) )
+ return;
+
+ // Need to free the upper hglobal part.
+
+ METAFILEPICT *
+ pMFP = (METAFILEPICT*) GlobalLock( *(HANDLE *)pHMetaFilePict );
+
+ if ( pMFP == NULL )
+ RpcRaiseException( E_OUTOFMEMORY );
+
+ // See if we need to free the hglobal, too.
+
+ if ( pMFP->hMF && HGLOBAL_DATA_PASSING(*pFlags) )
+ DeleteMetaFile( pMFP->hMF );
+
+ GlobalUnlock( *pHMetaFilePict );
+ GlobalFree( *pHMetaFilePict );
+ }
+}
+
+
+
+// #########################################################################
+//
+// HENHMETAFILE
+// See transmit.h for explanation of gdi data/handle passing.
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: HENHMETAFILE_UserSize
+//
+// Synopsis: Get the wire size the HENHMETAFILE handle and data.
+//
+// Derivation: Union of a long and the meta file handle and then struct.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+HENHMETAFILE_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ HENHMETAFILE * pHEnhMetafile )
+{
+ if ( !pHEnhMetafile )
+ return Offset;
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ // The encapsulated union.
+ // Discriminant and then handle or pointer from the union arm.
+
+ Offset += sizeof(long) + sizeof(void*);
+
+ if ( ! *pHEnhMetafile )
+ return Offset;
+
+ if ( GDI_DATA_PASSING(*pFlags) )
+ {
+ // Pointee of the union arm for the remote case.
+ // Byte blob : conformant size, size field, data
+
+ Offset += 2 * sizeof(long);
+
+ ulong ulDataSize = GetEnhMetaFileBits( *pHEnhMetafile, 0, NULL );
+ Offset += ulDataSize;
+ }
+
+ return( Offset );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HENHMETAFILE_UserMarshall
+//
+// Synopsis: Marshalls an HENHMETAFILE object into the RPC buffer.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HENHMETAFILE_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HENHMETAFILE * pHEnhMetafile )
+{
+ if ( !pHEnhMetafile )
+ return pBuffer;
+
+ UserNdrDebugOut((UNDR_OUT4, "HENHMETAFILE_UserMarshal\n"));
+
+ ALIGN( pBuffer, 3 );
+
+ // Discriminant of the encapsulated union and union arm.
+
+ if ( GDI_DATA_PASSING(*pFlags) )
+ {
+ // userHENHMETAFILE
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) *pHEnhMetafile;
+
+ if ( !*pHEnhMetafile )
+ return pBuffer;
+
+ // BYTE_BLOB: conformant size, size field, data
+
+ ulong ulDataSize = GetEnhMetaFileBits( *pHEnhMetafile, 0, NULL );
+
+ *( PULONG_LV_CAST pBuffer)++ = ulDataSize;
+ *( PULONG_LV_CAST pBuffer)++ = ulDataSize;
+
+ if ( 0 == GetEnhMetaFileBits( *pHEnhMetafile,
+ ulDataSize,
+ (uchar*)pBuffer ) )
+ RpcRaiseException( HRESULT_FROM_WIN32(GetLastError()));
+
+ pBuffer += ulDataSize;
+ }
+ else
+ {
+ // Sending a handle.
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) *(HANDLE *)pHEnhMetafile;
+ }
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HENHMETAFILE_UserUnmarshall
+//
+// Synopsis: Unmarshalls an HENHMETAFILE object from the RPC buffer.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HENHMETAFILE_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HENHMETAFILE * pHEnhMetafile )
+{
+ HENHMETAFILE hEnhMetafile;
+
+ UserNdrDebugOut((UNDR_OUT4, "HENHMETAFILE_UserUnmarshal\n"));
+
+ ALIGN( pBuffer, 3 );
+
+ unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++;
+ hEnhMetafile = (HENHMETAFILE) *( PULONG_LV_CAST pBuffer)++;
+
+ if ( IS_DATA_MARKER( UnionDisc) )
+ {
+ if ( hEnhMetafile )
+ {
+ // Byte blob : conformant size, size field, data
+
+ ulong ulDataSize = *(ulong*)pBuffer;
+ pBuffer += 8;
+ hEnhMetafile = SetEnhMetaFileBits( ulDataSize, (uchar*) pBuffer );
+ pBuffer += ulDataSize;
+ }
+ }
+
+ // No reusage of the old object.
+
+ if (*pHEnhMetafile)
+ DeleteEnhMetaFile( *pHEnhMetafile );
+
+ *pHEnhMetafile = hEnhMetafile;
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HENHMETAFILE_UserFree
+//
+// Synopsis: Free an HENHMETAFILE.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+HENHMETAFILE_UserFree(
+ unsigned long * pFlags,
+ HENHMETAFILE * pHEnhMetafile )
+{
+ UserNdrDebugOut((UNDR_FORCE, "HENHMETAFILE_UserFree\n"));
+
+ if( pHEnhMetafile && *pHEnhMetafile )
+ {
+ if ( GDI_DATA_PASSING(*pFlags) )
+ {
+ DeleteEnhMetaFile( *pHEnhMetafile );
+ }
+ }
+}
+
+
+// #########################################################################
+//
+// HMETAFILE
+// See transmit.h for explanation of gdi data/handle passing.
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: HMETAFILE_UserSize
+//
+// Synopsis: Get the wire size the HMETAFILE handle and data.
+//
+// Derivation: Same wire layout as HENHMETAFILE
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+HMETAFILE_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ HMETAFILE * pHMetafile )
+{
+ if ( !pHMetafile )
+ return Offset;
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ // The encapsulated union.
+ // Discriminant and then handle or pointer from the union arm.
+
+ Offset += sizeof(long) + sizeof(void*);
+
+ if ( ! *pHMetafile )
+ return Offset;
+
+ if ( GDI_DATA_PASSING(*pFlags) )
+ {
+ // Pointee of the union arm for the remote case.
+ // Byte blob : conformant size, size field, data
+
+ Offset += 2 * sizeof(long);
+
+ ulong ulDataSize = GetMetaFileBitsEx( *pHMetafile, 0, NULL );
+ Offset += ulDataSize;
+ }
+
+ return( Offset );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HMETAFILE_UserMarshal
+//
+// Synopsis: Marshals an HMETAFILE object into the RPC buffer.
+//
+// Derivation: Same wire layout as HENHMETAFILE
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HMETAFILE_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HMETAFILE * pHMetafile )
+{
+ if ( !pHMetafile )
+ return pBuffer;
+
+ UserNdrDebugOut((UNDR_OUT4, "HMETAFILE_UserMarshal\n"));
+
+ ALIGN( pBuffer, 3 );
+
+ // Discriminant of the encapsulated union and union arm.
+
+ if ( GDI_DATA_PASSING(*pFlags) )
+ {
+ // userHMETAFILE
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) *pHMetafile;
+
+ if ( !*pHMetafile )
+ return pBuffer;
+
+ // BYTE_BLOB: conformant size, size field, data
+
+ ulong ulDataSize = GetMetaFileBitsEx( *pHMetafile, 0, NULL );
+
+ *( PULONG_LV_CAST pBuffer)++ = ulDataSize;
+ *( PULONG_LV_CAST pBuffer)++ = ulDataSize;
+
+ if ( 0 == GetMetaFileBitsEx( *pHMetafile,
+ ulDataSize,
+ (uchar*)pBuffer ) )
+ RpcRaiseException( HRESULT_FROM_WIN32(GetLastError()));
+
+ pBuffer += ulDataSize;
+ }
+ else
+ {
+ // Sending a handle.
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) *(HANDLE *)pHMetafile;
+ }
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HMETAFILE_UserUnmarshal
+//
+// Synopsis: Unmarshalls an HMETAFILE object from the RPC buffer.
+//
+// Derivation: Same wire layout as HENHMETAFILE
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HMETAFILE_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HMETAFILE * pHMetafile )
+{
+ HMETAFILE hMetafile;
+
+ UserNdrDebugOut((UNDR_OUT4, "HMETAFILE_UserUnmarshal\n"));
+
+ ALIGN( pBuffer, 3 );
+
+ unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++;
+ hMetafile = (HMETAFILE) *( PULONG_LV_CAST pBuffer)++;
+
+ if ( IS_DATA_MARKER( UnionDisc) )
+ {
+ if ( hMetafile )
+ {
+ // Byte blob : conformant size, size field, data
+
+ ulong ulDataSize = *(ulong*)pBuffer;
+ pBuffer += 8;
+ hMetafile = SetMetaFileBitsEx( ulDataSize, (uchar*) pBuffer );
+ pBuffer += ulDataSize;
+ }
+ }
+
+ // No reusage of the old object.
+
+ if (*pHMetafile)
+ DeleteMetaFile( *pHMetafile );
+
+ *pHMetafile = hMetafile;
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HMETAFILE_UserFree
+//
+// Synopsis: Free an HMETAFILE.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+HMETAFILE_UserFree(
+ unsigned long * pFlags,
+ HMETAFILE * pHMetafile )
+{
+ UserNdrDebugOut((UNDR_FORCE, "HMETAFILE_UserFree\n"));
+
+ if( pHMetafile && *pHMetafile )
+ {
+ if ( GDI_DATA_PASSING(*pFlags) )
+ {
+ DeleteMetaFile( *pHMetafile );
+ }
+ }
+}
+
+
+// #########################################################################
+//
+// HBITMAP
+// See transmit.h for explanation of gdi data/handle passing.
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: HBITMAP_UserSize
+//
+// Synopsis: Get the wire size the HBITMAP handle and data.
+//
+// Derivation: Union of a long and the bitmap handle and then struct.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+HBITMAP_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ HBITMAP * pHBitmap )
+{
+ if ( !pHBitmap )
+ return Offset;
+
+ BITMAP bm;
+ HBITMAP hBitmap = *pHBitmap;
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ // The encapsulated union.
+ // Discriminant and then handle or pointer from the union arm.
+
+ Offset += sizeof(long) + sizeof(void*);
+
+ if ( ! *pHBitmap )
+ return Offset;
+
+ if ( GDI_DATA_PASSING(*pFlags) )
+ {
+ // Pointee of the union arm for the remote case.
+ // Conformat size, 6 fields, size, conf array.
+
+ Offset += 4 + 4 * sizeof(LONG) + 2 * sizeof(WORD) + 4;
+
+ // Get information about the bitmap
+
+ #if defined(_CHICAGO_)
+ if (FALSE == GetObjectA(hBitmap, sizeof(BITMAP), &bm))
+ #else
+ if (FALSE == GetObject(hBitmap, sizeof(BITMAP), &bm))
+ #endif
+ {
+ RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
+ }
+
+ ULONG ulDataSize = bm.bmPlanes * bm.bmHeight * bm.bmWidthBytes;
+
+ Offset += ulDataSize;
+ }
+
+ return( Offset ) ;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HBITMAP_UserMarshall
+//
+// Synopsis: Marshalls an HBITMAP object into the RPC buffer.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HBITMAP_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HBITMAP * pHBitmap )
+{
+ if ( !pHBitmap )
+ return pBuffer;
+
+ UserNdrDebugOut((UNDR_OUT4, "HBITMAP_UserMarshal\n"));
+
+ ALIGN( pBuffer, 3 );
+
+ // Discriminant of the encapsulated union and union arm.
+
+ if ( GDI_DATA_PASSING(*pFlags) )
+ {
+ // userHBITMAP
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) *pHBitmap;
+
+ if ( ! *pHBitmap )
+ return pBuffer;
+
+ // Get information about the bitmap
+
+ BITMAP bm;
+ HBITMAP hBitmap = *pHBitmap;
+
+ #if defined(_CHICAGO_)
+ if (FALSE == GetObjectA(hBitmap, sizeof(BITMAP), &bm))
+ #else
+ if (FALSE == GetObject(hBitmap, sizeof(BITMAP), &bm))
+ #endif
+ {
+ RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
+ }
+
+ DWORD dwCount = bm.bmPlanes * bm.bmHeight * bm.bmWidthBytes;
+
+ *( PULONG_LV_CAST pBuffer)++ = dwCount;
+
+ // Get the bm structure fields.
+
+ ulong ulBmSize = 4 * sizeof(LONG) + 2 * sizeof( WORD );
+
+ memcpy( pBuffer, (void *) &bm, ulBmSize );
+ pBuffer += ulBmSize;
+
+ // Get the raw bits.
+
+ if (0 == GetBitmapBits( hBitmap, dwCount, pBuffer ) )
+ {
+ RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
+ }
+ pBuffer += dwCount;
+ }
+ else
+ {
+ // Sending a handle.
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) *(HANDLE *)pHBitmap;
+ }
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HBITMAP_UserUnmarshall
+//
+// Synopsis: Unmarshalls an HBITMAP object from the RPC buffer.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HBITMAP_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HBITMAP * pHBitmap )
+{
+ HBITMAP hBitmap;
+
+ UserNdrDebugOut((UNDR_OUT4, "HBITMAP_UserUnmarshal\n"));
+
+ ALIGN( pBuffer, 3 );
+
+ unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++;
+ hBitmap = (HBITMAP) *( PULONG_LV_CAST pBuffer)++;
+
+ if ( IS_DATA_MARKER( UnionDisc) )
+ {
+ if ( hBitmap )
+ {
+ DWORD dwCount = *( PULONG_LV_CAST pBuffer)++;
+ BITMAP * pBm = (BITMAP *) pBuffer;
+
+ ulong ulBmSize = 4 * sizeof(LONG) + 2 * sizeof( WORD );
+
+ pBuffer += ulBmSize;
+
+ // Create a bitmap based on the BITMAP structure and the raw bits in
+ // the transmission buffer
+
+ hBitmap = CreateBitmap( pBm->bmWidth,
+ pBm->bmHeight,
+ pBm->bmPlanes,
+ pBm->bmBitsPixel,
+ pBuffer );
+
+ pBuffer += dwCount;
+ }
+ }
+
+ // A new bitmap handle is ready, destroy the old one, if needed.
+
+ if ( *pHBitmap )
+ DeleteObject( *pHBitmap );
+
+ *pHBitmap = hBitmap;
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HBITMAP_UserFree
+//
+// Synopsis: Free an HBITMAP.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+HBITMAP_UserFree(
+ unsigned long * pFlags,
+ HBITMAP * pHBitmap )
+{
+ UserNdrDebugOut((UNDR_OUT4, "HBITMAP_UserFree\n"));
+
+ if( pHBitmap && *pHBitmap )
+ {
+ if ( GDI_DATA_PASSING(*pFlags) )
+ {
+ DeleteObject( *pHBitmap );
+ }
+ }
+}
+
+
+// #########################################################################
+//
+// HPALETTE
+// See transmit.h for explanation of gdi data/handle passing.
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: HPALETTE_UserSize
+//
+// Synopsis: Get the wire size the HPALETTE handle and data.
+//
+// Derivation: Union of a long and the hpalette handle.
+// Then the struct represents hpalette.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+HPALETTE_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ HPALETTE * pHPalette )
+{
+ if ( !pHPalette )
+ return Offset;
+
+ BITMAP bm;
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ // The encapsulated union.
+ // Discriminant and then handle or pointer from the union arm.
+
+ Offset += sizeof(long) + sizeof(void*);
+
+ if ( ! *pHPalette )
+ return Offset;
+
+ if ( GDI_DATA_PASSING(*pFlags) )
+ {
+ // Conformat struct with version and size and conf array of entries.
+
+ Offset += sizeof(long) + 2 * sizeof(short);
+
+ // Determine the number of color entries in the palette
+
+ DWORD cEntries = GetPaletteEntries(*pHPalette, 0, 0, NULL);
+
+ Offset += cEntries * sizeof(PALETTEENTRY);
+ }
+
+ return( Offset ) ;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HPALETTE_UserMarshall
+//
+// Synopsis: Marshalls an HPALETTE object into the RPC buffer.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HPALETTE_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HPALETTE * pHPalette )
+{
+ if ( !pHPalette )
+ return pBuffer;
+
+ UserNdrDebugOut((UNDR_OUT4, "HPALETTE_UserMarshal\n"));
+
+ ALIGN( pBuffer, 3 );
+
+ // Discriminant of the encapsulated union and union arm.
+
+ if ( GDI_DATA_PASSING(*pFlags) )
+ {
+ // userHPALETTE
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_DATA_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) *pHPalette;
+
+ if ( ! *pHPalette )
+ return pBuffer;
+
+ // rpcLOGPALETTE
+ // Logpalette is a conformant struct with a version field,
+ // size filed and conformant array of palentries.
+
+ // Determine the number of color entries in the palette
+
+ DWORD cEntries = GetPaletteEntries(*pHPalette, 0, 0, NULL);
+
+ // Conformant size
+
+ *( PULONG_LV_CAST pBuffer)++ = cEntries;
+
+ // Fields: both are short!
+ // The old code was just setting the version number.
+ // They say it has to be that way.
+
+ *( PUSHORT_LV_CAST pBuffer)++ = (ushort) 0x300;
+ *( PUSHORT_LV_CAST pBuffer)++ = (ushort) cEntries;
+
+ // Entries: each entry is a struct with 4 bytes.
+ // Calculate the resultant data size
+
+ DWORD cbData = cEntries * sizeof(PALETTEENTRY);
+
+ if (cbData)
+ {
+ if (0 == GetPaletteEntries( *pHPalette,
+ 0,
+ cEntries,
+ (PALETTEENTRY *)pBuffer ) )
+ {
+ RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
+ }
+ pBuffer += cbData;
+ }
+ }
+ else
+ {
+ // Sending a handle.
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) *(HANDLE *)pHPalette;
+ }
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HPALETTE_UserUnmarshall
+//
+// Synopsis: Unmarshalls an HPALETTE object from the RPC buffer.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HPALETTE_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HPALETTE * pHPalette )
+{
+ HPALETTE hPalette;
+
+ UserNdrDebugOut((UNDR_OUT4, "HPALETTE_UserUnmarshal\n"));
+
+ ALIGN( pBuffer, 3 );
+
+ unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++;
+ hPalette = (HPALETTE) *( PULONG_LV_CAST pBuffer)++;
+
+ if ( IS_DATA_MARKER( UnionDisc) )
+ {
+ if ( hPalette )
+ {
+ // Get the conformant size.
+
+ DWORD cEntries = *( PULONG_LV_CAST pBuffer)++;
+ LOGPALETTE * pLogPal;
+
+ // If there are 0 color entries, we need to allocate the LOGPALETTE
+ // structure with the one dummy entry (it's a variably sized struct).
+ // Otherwise, we need to allocate enough space for the extra n-1
+ // entries at the tail of the structure
+
+ if (0 == cEntries)
+ {
+ pLogPal = (LOGPALETTE *) WdtpAllocate( pFlags,
+ sizeof(LOGPALETTE));
+ }
+ else
+ {
+ pLogPal = (LOGPALETTE *)
+ WdtpAllocate( pFlags,
+ sizeof(LOGPALETTE) +
+ (cEntries - 1) * sizeof(PALETTEENTRY));
+ }
+
+ pLogPal->palVersion = *( PUSHORT_LV_CAST pBuffer)++;
+ pLogPal->palNumEntries = *( PUSHORT_LV_CAST pBuffer)++;
+
+ // If there are entries, move them into out LOGPALETTE structure
+
+ if (cEntries)
+ {
+ memcpy( &(pLogPal->palPalEntry[0]),
+ pBuffer,
+ cEntries * sizeof(PALETTEENTRY) );
+ pBuffer += cEntries * sizeof(PALETTEENTRY);
+ }
+
+ // Attempt to create the palette
+
+ hPalette = CreatePalette(pLogPal);
+
+ // Success or failure, we're done with the LOGPALETTE structure
+
+ WdtpFree( pFlags, pLogPal );
+
+ // If the creation failed, raise an exception
+
+ if (NULL == hPalette)
+ {
+ RpcRaiseException(HRESULT_FROM_WIN32(GetLastError()));
+ }
+ }
+ }
+
+ // A new palette is ready, destroy the old one, if needed.
+
+ if ( *pHPalette )
+ DeleteObject( *pHPalette );
+
+ *pHPalette = hPalette;
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HPALETTE_UserFree
+//
+// Synopsis: Free an HPALETTE.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+HPALETTE_UserFree(
+ unsigned long * pFlags,
+ HPALETTE * pHPalette )
+{
+ UserNdrDebugOut((UNDR_OUT4, "HPALETTE_UserFree\n"));
+
+ if( pHPalette && *pHPalette )
+ {
+ if ( GDI_DATA_PASSING(*pFlags) )
+ {
+ DeleteObject( *pHPalette );
+ }
+ }
+}
+
+
+// #########################################################################
+//
+// NON REMOTABLE GDI and other HANDLES
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpNonRemotableHandle_UserSize
+//
+// Synopsis: Get the wire size for a non remotable GDI handle.
+//
+// Derivation: Union of a long and nothing.
+// It is union just in case some remoting is needed.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+WdtpNonRemotableHandle_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ HANDLE * pHandle )
+{
+ if ( !pHandle || *pHandle == NULL )
+ return Offset;
+
+ if ( HGLOBAL_DATA_PASSING(*pFlags) )
+ RpcRaiseException(E_INVALIDARG );
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ // The encapsulated union.
+ // No remote case on any platform.
+
+ return( Offset + 8 ) ;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpNonRemotableHandle_UserMarshal
+//
+// Synopsis: Marshalls a non-remotable handle into the RPC buffer.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+WdtpNonRemotableHandle_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HANDLE * pHandle )
+{
+ if ( !pHandle || *pHandle == NULL )
+ return pBuffer;
+
+ ALIGN( pBuffer, 3 );
+
+ // Discriminant of the encapsulated union and union arm.
+
+ if ( HGLOBAL_DATA_PASSING(*pFlags) )
+ {
+ RpcRaiseException(E_INVALIDARG );
+ }
+ else
+ {
+ // Sending a handle.
+
+ *( PULONG_LV_CAST pBuffer)++ = WDT_HANDLE_MARKER;
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) *(HANDLE *)pHandle;
+ }
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpNonRemotableHandle_UserUnmarshal
+//
+// Synopsis: Unmarshalls a non-remotable handle from the RPC buffer.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+WdtpNonRemotableHandle_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HANDLE * pHandle )
+{
+ ALIGN( pBuffer, 3 );
+
+ unsigned long UnionDisc = *( PULONG_LV_CAST pBuffer)++;
+
+ if ( IS_DATA_MARKER( UnionDisc) )
+ {
+ RpcRaiseException(E_INVALIDARG );
+ }
+ else
+ {
+ // Sending a handle.
+
+ *pHandle = (HANDLE) *( PULONG_LV_CAST pBuffer)++;
+ }
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpNonRemotableHandle_UserFree
+//
+// Synopsis: Nothing to free.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+WdtpNonRemotableGdiHandle_UserFree(
+ unsigned long * pFlags,
+ HANDLE * pHandle )
+{
+}
+
+
+
+// #########################################################################
+//
+// Interface pointers.
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpInterfacePointer_UserSize
+//
+// Synopsis: Get the wire size for an interface pointer.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+WdtpInterfacePointer_UserSize (
+ USER_MARSHAL_CB * pContext,
+ unsigned long Flags,
+ unsigned long Offset,
+ IUnknown * pIf,
+ const IID & IId )
+{
+ if ( pIf )
+ {
+ LENGTH_ALIGN( Offset, 3 );
+
+ //Leave space for array bounds and length
+
+ Offset += 2 * sizeof(long);
+
+ HRESULT hr;
+ unsigned long cbSize = 0;
+
+ hr = CoGetMarshalSizeMax( &cbSize,
+ IId,
+ pIf,
+ USER_CALL_CTXT_MASK( Flags ),
+ pContext->pStubMsg->pvDestContext,
+ MSHLFLAGS_NORMAL );
+ if ( FAILED(hr) )
+ RpcRaiseException( hr );
+
+ Offset += cbSize;
+ }
+
+ return( Offset ) ;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpInterfacePointer_UserMarshal
+//
+// Synopsis: Marshalls an interface pointer.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+WdtpInterfacePointer_UserMarshal (
+ USER_MARSHAL_CB * pContext,
+ unsigned long Flags,
+ unsigned char * pBuffer,
+ IUnknown * pIf,
+ const IID & IId )
+{
+ unsigned long * pMaxCount, *pSize;
+ unsigned long cbData = 0;
+
+ UserNdrDebugOut((UNDR_OUT1, "WdtpInterface_PointerMarshal\n"));
+
+ if ( pIf )
+ {
+ // Always marshaled because of the apartment model.
+
+ CStreamOnMessage MemStream( (unsigned char **) &pBuffer );
+
+ ALIGN( pBuffer, 3 );
+
+ pMaxCount = (unsigned long *) pBuffer;
+ pBuffer += 4;
+
+ // Leave space for length
+
+ pSize = (unsigned long *) pBuffer;
+ pBuffer += 4;
+
+ HRESULT hr;
+ unsigned char * pBufferMark = pBuffer;
+
+ hr = CoMarshalInterface( &MemStream,
+ IId,
+ pIf,
+ USER_CALL_CTXT_MASK( Flags ),
+ pContext->pStubMsg->pvDestContext,
+ MSHLFLAGS_NORMAL );
+ if( FAILED(hr) )
+ {
+ RpcRaiseException(hr);
+ }
+
+ // Calculate the size of the data written
+
+ DWORD cbData = pBuffer - pBufferMark;
+
+ // Update the array bounds.
+
+ *pMaxCount = cbData;
+ *pSize = cbData;
+ }
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpInterfacePointer_UserUnmarshal
+//
+// Synopsis: Unmarshalls an interface pointer from the RPC buffer.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+WdtpInterfacePointer_UserUnmarshal (
+ USER_MARSHAL_CB * pContext,
+ unsigned char * pBuffer,
+ IUnknown ** ppIf,
+ const IID & IId )
+{
+ unsigned long *pMaxCount, *pSize;
+ unsigned long cbData = 0;
+
+ UserNdrDebugOut((UNDR_OUT1, "WdtpInterfacePointerUnmarshal\n"));
+
+ // Always unmarshaled because of the apartment model.
+
+ CStreamOnMessage MemStream((unsigned char **) &pBuffer);
+
+ ALIGN( pBuffer, 3 );
+
+ pMaxCount = (unsigned long *) pBuffer;
+ pBuffer += sizeof(long);
+
+ //Unmarshal count
+ pSize = (unsigned long *) pBuffer;
+ pBuffer += sizeof(long);
+
+ // Release the old pointer after unmarshalling the new one
+ // to prevent object from getting released too early.
+ // Then release the old one only when successful.
+
+ IUnknown * punkTemp = 0;
+
+ HRESULT hr = CoUnmarshalInterface( &MemStream,
+ IId,
+ (void **) &punkTemp );
+ if(FAILED(hr))
+ RpcRaiseException(hr);
+ else
+ {
+ // On the client side, release the [in,out] interface pointer.
+ // The pointer may be different from NULL only on the client side.
+
+ // release the old one, keep the new one.
+
+ if ( *ppIf )
+ (*ppIf)->Release();
+ *ppIf = punkTemp;
+ }
+
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpInterfacePointer_UserFree
+//
+// Synopsis: Releases an interface pointer.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+WdtpInterfacePointer_UserFree(
+ IUnknown * pIf )
+{
+ UserNdrDebugOut((UNDR_OUT1, "WdtpInterfacePointer_UserFree\n"));
+
+ if( pIf )
+ {
+ pIf->Release();
+ }
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: STGMEDIUM_UserSize
+//
+// Synopsis: Sizes a stgmedium pbject for RPC marshalling.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+STGMEDIUM_UserSize(
+ unsigned long * pFlags,
+ unsigned long Offset,
+ STGMEDIUM * pStgmed )
+{
+ if ( ! pStgmed )
+ return Offset;
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ if ( pStgmed->tymed == TYMED_NULL )
+ Offset += sizeof(long) + sizeof(void*); // switch, (empty arm), pUnk
+ else
+ Offset += sizeof(long) + 2 * sizeof(void*); // switch, handle, pUnk
+
+ // Pointee of the union arm.
+ // Only if the handle/pointer field is non-null.
+
+ if ( pStgmed->hGlobal )
+ {
+ switch( pStgmed->tymed )
+ {
+ case TYMED_NULL:
+ break;
+ case TYMED_MFPICT:
+ Offset = HMETAFILEPICT_UserSize( pFlags,
+ Offset,
+ &pStgmed->hMetaFilePict );
+ break;
+ case TYMED_ENHMF:
+ Offset = HENHMETAFILE_UserSize( pFlags,
+ Offset,
+ &pStgmed->hEnhMetaFile );
+ break;
+ case TYMED_GDI:
+
+ // A GDI object is not necesarrily a BITMAP. Therefore, we handle
+ // those types we know about based on the object type, and reject
+ // those which we do not support.
+
+ // switch for object type.
+
+ Offset += sizeof(long);
+
+ switch( GetObjectType( (HGDIOBJ)pStgmed->hBitmap ) )
+ {
+ case OBJ_BITMAP:
+ Offset = HBITMAP_UserSize( pFlags,
+ Offset,
+ &pStgmed->hBitmap );
+ break;
+
+ case OBJ_PAL:
+ Offset = HPALETTE_UserSize( pFlags,
+ Offset,
+ (HPALETTE *) & pStgmed->hBitmap );
+ break;
+
+ default:
+ RpcRaiseException(DV_E_TYMED);
+ break;
+ }
+ break;
+
+ case TYMED_HGLOBAL:
+ Offset = HGLOBAL_UserSize( pFlags,
+ Offset,
+ &pStgmed->hGlobal );
+ break;
+ case TYMED_FILE:
+ {
+ ulong ulDataSize = lstrlenW(pStgmed->lpszFileName) + 1;
+ Offset += 3 * sizeof(long); // [string]
+ Offset += ulDataSize * sizeof(wchar_t);
+ }
+ break;
+
+ case TYMED_ISTREAM:
+ case TYMED_ISTORAGE:
+ // Note, that we have to set the local flag for backward
+ // compatibility.
+
+ Offset = WdtpInterfacePointer_UserSize(
+ (USER_MARSHAL_CB *)pFlags,
+ *pFlags,
+ Offset,
+ pStgmed->pstg,
+ ((pStgmed->tymed == TYMED_ISTREAM) ? IID_IStream
+ : IID_IStorage));
+ break;
+
+ default:
+ break;
+
+ }
+ }
+
+ // pUnkForRelease, if not null.
+
+ if ( pStgmed->pUnkForRelease )
+ Offset = WdtpInterfacePointer_UserSize( (USER_MARSHAL_CB *)pFlags,
+ *pFlags,
+ Offset,
+ pStgmed->pUnkForRelease,
+ IID_IUnknown );
+
+ return( Offset );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: STGMEDIUM_UserMarshal
+//
+// Synopsis: Marshals a stgmedium pbject for RPC.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+STGMEDIUM_UserMarshal(
+ unsigned long * pFlags,
+ unsigned char * pBufferStart,
+ STGMEDIUM * pStgmed )
+{
+ unsigned char * pBuffer;
+ unsigned char * pUnionArmMark;
+
+ if ( ! pStgmed )
+ return pBufferStart;
+
+ UserNdrDebugOut((UNDR_FORCE, "--STGMEDIUM_UserMarshal: %s\n", WdtpGetStgmedName(pStgmed)));
+
+ pBuffer = pBufferStart;
+ ALIGN( pBuffer, 3 );
+
+ // userSTGMEDIUM: switch, union arm, pUnk ptr.
+
+ *( PULONG_LV_CAST pBuffer)++ = pStgmed->tymed;
+ pUnionArmMark = pBuffer;
+ if ( pStgmed->tymed != TYMED_NULL )
+ {
+ // hGlobal stands for any of these handles.
+
+ *( PULONG_LV_CAST pBuffer)++ = (ulong)pStgmed->hGlobal;
+ }
+
+ *( PULONG_LV_CAST pBuffer)++ = (ulong)pStgmed->pUnkForRelease;
+
+ // Now the pointee of the union arm.
+ // We need to marshal only if the handle/pointer field is non null.
+ // Otherwise it is already in the buffer.
+
+ if ( pStgmed->hGlobal )
+ {
+ switch( pStgmed->tymed )
+ {
+ case TYMED_NULL:
+ break;
+ case TYMED_MFPICT:
+ pBuffer = HMETAFILEPICT_UserMarshal( pFlags,
+ pBuffer,
+ &pStgmed->hMetaFilePict );
+ break;
+ case TYMED_ENHMF:
+ pBuffer = HENHMETAFILE_UserMarshal( pFlags,
+ pBuffer,
+ &pStgmed->hEnhMetaFile );
+ break;
+ case TYMED_GDI:
+
+ {
+ // A GDI object is not necesarrily a BITMAP. Therefore, we handle
+ // those types we know about based on the object type, and reject
+ // those which we do not support.
+
+ ulong GdiObjectType = GetObjectType( (HGDIOBJ)pStgmed->hBitmap );
+
+ // GDI_OBJECT
+
+ *( PULONG_LV_CAST pBuffer)++ = GdiObjectType;
+
+
+
+ switch( GdiObjectType )
+ {
+ case OBJ_BITMAP:
+ pBuffer = HBITMAP_UserMarshal( pFlags,
+ pBuffer,
+ &pStgmed->hBitmap );
+ break;
+
+ case OBJ_PAL:
+ pBuffer = HPALETTE_UserMarshal( pFlags,
+ pBuffer,
+ (HPALETTE *) & pStgmed->hBitmap );
+ break;
+
+ default:
+ RpcRaiseException(DV_E_TYMED);
+ }
+ }
+ break;
+
+ case TYMED_HGLOBAL:
+ pBuffer = HGLOBAL_UserMarshal( pFlags,
+ pBuffer,
+ & pStgmed->hGlobal );
+ break;
+ case TYMED_FILE:
+ {
+ // We marshal it as a [string].
+
+ ulong Count = (pStgmed->lpszFileName)
+ ? lstrlenW(pStgmed->lpszFileName) + 1
+ : 0;
+
+ *( PULONG_LV_CAST pBuffer)++ = Count;
+ *( PULONG_LV_CAST pBuffer)++ = 0;
+ *( PULONG_LV_CAST pBuffer)++ = Count;
+ memcpy( pBuffer, pStgmed->lpszFileName, Count * sizeof(wchar_t) );
+ pBuffer += Count * sizeof(wchar_t);
+ }
+ break;
+
+ case TYMED_ISTREAM:
+ case TYMED_ISTORAGE:
+ // Note, that we have to set the local flag for backward compatibility.
+
+ pBuffer = WdtpInterfacePointer_UserMarshal(
+ ((USER_MARSHAL_CB *)pFlags),
+ *pFlags,
+ pBuffer,
+ pStgmed->pstg,
+ ((pStgmed->tymed == TYMED_ISTREAM) ? IID_IStream
+ : IID_IStorage));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // Marker for this pointer is already in the buffer.
+
+ if ( pStgmed->pUnkForRelease )
+ pBuffer = WdtpInterfacePointer_UserMarshal( ((USER_MARSHAL_CB *)pFlags),
+ *pFlags,
+ pBuffer,
+ pStgmed->pUnkForRelease,
+ IID_IUnknown );
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: STGMEDIUM_UserUnmarshal
+//
+// Synopsis: Unmarshals a stgmedium object for RPC.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+STGMEDIUM_UserUnmarshal(
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ STGMEDIUM * pStgmed )
+{
+ unsigned long fUnkForRelease;
+ unsigned long Handle = 0;
+
+ // switch, union arm, pUnk .
+
+ ALIGN( pBuffer, 3 );
+
+ pStgmed->tymed = *( PULONG_LV_CAST pBuffer)++;
+
+ UserNdrDebugOut((UNDR_FORCE, "--STGMEDIUM_UserUnmarshal: %s\n", WdtpGetStgmedName(pStgmed) ));
+
+ if ( pStgmed->tymed != TYMED_NULL )
+ {
+ // handle or interface pointer (marker) from the buffer
+ Handle = *( PULONG_LV_CAST pBuffer)++;
+ }
+
+ // pUnkForRelease pointer marker.
+
+ fUnkForRelease = *( PULONG_LV_CAST pBuffer)++;
+
+ // First pointee
+
+ // Union arm pointee.
+ // We need to unmarshal only if the handle/pointer field was not NULL.
+
+ if ( Handle )
+ {
+ switch( pStgmed->tymed )
+ {
+ case TYMED_NULL:
+ break;
+ case TYMED_MFPICT:
+ pBuffer = HMETAFILEPICT_UserUnmarshal( pFlags,
+ pBuffer,
+ &pStgmed->hMetaFilePict );
+ break;
+ case TYMED_ENHMF:
+ pBuffer = HENHMETAFILE_UserUnmarshal( pFlags,
+ pBuffer,
+ &pStgmed->hEnhMetaFile );
+ break;
+ case TYMED_GDI:
+ {
+ // A GDI object is not necesarrily a BITMAP. Therefore, we handle
+ // those types we know about based on the object type, and reject
+ // those which we do not support.
+
+ DWORD GdiObjectType = *( PULONG_LV_CAST pBuffer)++;
+
+ switch( GdiObjectType )
+ {
+ case OBJ_BITMAP:
+ pBuffer = HBITMAP_UserUnmarshal( pFlags,
+ pBuffer,
+ &pStgmed->hBitmap );
+ break;
+
+ case OBJ_PAL:
+ pBuffer = HPALETTE_UserUnmarshal( pFlags,
+ pBuffer,
+ (HPALETTE *) & pStgmed->hBitmap );
+ break;
+
+ default:
+ RpcRaiseException(DV_E_TYMED);
+ }
+ }
+ break;
+
+ case TYMED_HGLOBAL:
+ // reallocation is forbidden for [in-out] hglobal in STGMEDIUM.
+
+ pBuffer = WdtpGlobalUnmarshal( pFlags,
+ pBuffer,
+ & pStgmed->hGlobal,
+ FALSE ); // realloc flag
+ break;
+
+ case TYMED_FILE:
+ {
+ // We marshal it as a [string].
+
+ ulong Count = *( PULONG_LV_CAST pBuffer)++;
+ pBuffer += 8;
+
+ if ( ! pStgmed->lpszFileName )
+ pStgmed->lpszFileName = (LPOLESTR)
+ WdtpAllocate( pFlags,
+ Count * sizeof(wchar_t) );
+ memcpy( pStgmed->lpszFileName, pBuffer, Count * sizeof(wchar_t) );
+ pBuffer += Count * sizeof(wchar_t);
+ }
+ break;
+
+ case TYMED_ISTREAM:
+ case TYMED_ISTORAGE:
+ // Non null pointer, retrieve the interface pointer
+
+ pBuffer = WdtpInterfacePointer_UserUnmarshal(
+ (USER_MARSHAL_CB *)pFlags,
+ pBuffer,
+ (IUnknown **) &pStgmed->pstm,
+ ((pStgmed->tymed == TYMED_ISTREAM)
+ ? IID_IStream
+ : IID_IStorage));
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // New handle/pointer field is null, so release the previous one
+ // if it wasn't null.
+
+ if ( pStgmed->hGlobal )
+ {
+ // This should never happen for GetDataHere.
+
+ // Note, that we release the handle field, not the stgmedium itself.
+ // Accordingly, we don't follow punkForRelease.
+
+ UserNdrDebugOut((UNDR_FORCE, "--STGMEDIUM_UserUnmarshal: %s: NULL in, freeing old one\n", WdtpGetStgmedName(pStgmed)));
+
+ STGMEDIUM TmpStg = *pStgmed;
+ TmpStg.pUnkForRelease = NULL;
+
+ if ( pStgmed->tymed == TYMED_HGLOBAL )
+ {
+ // Cannot reallocate.
+ RpcRaiseException(DV_E_TYMED);
+ }
+ else
+ {
+ ReleaseStgMedium( &TmpStg );
+ }
+ }
+
+ pStgmed->hGlobal = 0;
+ }
+
+ if ( fUnkForRelease )
+ {
+ // There is an interface pointer on the wire.
+
+ pBuffer = WdtpInterfacePointer_UserUnmarshal( (USER_MARSHAL_CB *)pFlags,
+ pBuffer,
+ &pStgmed->pUnkForRelease,
+ IID_IUnknown );
+ }
+
+ if ( pStgmed->pUnkForRelease )
+ {
+ // Replace the app's punkForRelease with our custom release
+ // handler for special situations.
+
+ // The special situation is when a handle is remoted with data
+ // and so we have to clean up a side effect of having a data copy
+ // around. UserFree does it properly but we need that for the callee.
+ // When the callee releases a stgmed, it would invoke
+ // ReleaseStgMedium and this API doesn't do anything for handles
+ // when the punkForRelease is not NULL.
+
+ ULONG fHandleWithData = 0;
+ ULONG fTopLevelOnly = 0;
+
+ switch ( pStgmed->tymed )
+ {
+ case TYMED_HGLOBAL:
+ fHandleWithData = HGLOBAL_DATA_PASSING( *pFlags );
+ break;
+
+ case TYMED_ENHMF:
+ case TYMED_GDI:
+ fHandleWithData = GDI_DATA_PASSING( *pFlags );
+ break;
+
+ case TYMED_MFPICT:
+ fHandleWithData = HGLOBAL_DATA_PASSING( *pFlags );
+ fTopLevelOnly = fHandleWithData &&
+ ! GDI_DATA_PASSING( *pFlags );
+ break;
+
+ default:
+ break;
+ }
+
+ if ( fHandleWithData )
+ {
+ IUnknown *
+ punkTmp = (IUnknown *) new CPunkForRelease( pStgmed,
+ fTopLevelOnly );
+ if (!punkTmp)
+ {
+ RpcRaiseException(E_OUTOFMEMORY);
+ }
+
+ pStgmed->pUnkForRelease = punkTmp;
+ }
+ }
+
+ return( pBuffer );
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: STGMEDIUM_UserFree
+//
+// Synopsis: Frees a stgmedium object for RPC.
+//
+// history: May-95 Ryszardk Created.
+//
+// Note: This routine is called from the freeing walk at server
+// or from the SetData *proxy*, when ownership has been passed.
+//
+//--------------------------------------------------------------------------
+
+EXTERN_C
+void NukeHandleAndReleasePunk(
+ STGMEDIUM * pStgmed )
+{
+ pStgmed->hGlobal = NULL;
+ pStgmed->tymed = TYMED_NULL;
+
+ if (pStgmed->pUnkForRelease)
+ {
+ pStgmed->pUnkForRelease->Release();
+ pStgmed->pUnkForRelease = 0;
+ }
+}
+
+void __RPC_USER
+STGMEDIUM_UserFree(
+ unsigned long * pFlags,
+ STGMEDIUM * pStgmed )
+{
+ UserNdrDebugOut((UNDR_FORCE, "--STGMEDIUM_UserFree: %s\n", WdtpGetStgmedName(pStgmed)));
+
+ if( pStgmed )
+ {
+ switch ( pStgmed->tymed )
+ {
+ case TYMED_FILE:
+ WdtpFree( pFlags, pStgmed->lpszFileName);
+ NukeHandleAndReleasePunk( pStgmed );
+ break;
+
+ case TYMED_NULL:
+ case TYMED_ISTREAM:
+ case TYMED_ISTORAGE:
+ ReleaseStgMedium( pStgmed );
+ break;
+
+ case TYMED_GDI:
+ case TYMED_ENHMF:
+
+ if ( GDI_HANDLE_PASSING(*pFlags) )
+ {
+ NukeHandleAndReleasePunk( pStgmed );
+ }
+ else
+ {
+ // Handle w/data: there is a side effect to clean up.
+ // For punk !=0, this will go to our CPunk object.
+
+ ReleaseStgMedium( pStgmed );
+ }
+ break;
+
+ case TYMED_HGLOBAL:
+
+ if ( HGLOBAL_HANDLE_PASSING(*pFlags) )
+ {
+ NukeHandleAndReleasePunk( pStgmed );
+ }
+ else
+ {
+ // Handle w/data: there is a side effect to clean up.
+ // For punk ==0, this will just release the data.
+ // For punk !=0, this will go to our CPunk object,
+ // release the data, and then call the original punk.
+
+ ReleaseStgMedium( pStgmed );
+ }
+ break;
+
+ case TYMED_MFPICT:
+
+ if ( HGLOBAL_HANDLE_PASSING(*pFlags) )
+ {
+ NukeHandleAndReleasePunk( pStgmed );
+ }
+ else if ( GDI_HANDLE_PASSING(*pFlags) )
+ {
+ if ( pStgmed->pUnkForRelease )
+ {
+ pStgmed->pUnkForRelease->Release();
+ }
+ else
+ {
+ if ( pStgmed->hGlobal )
+ GlobalFree( pStgmed->hGlobal );
+ pStgmed->hGlobal = NULL;
+ pStgmed->tymed = TYMED_NULL;
+ }
+ }
+ else
+ {
+ // Handle w/data: there is a side effect to clean up.
+ // For punk !=0, this will go to our CPunk object.
+
+ ReleaseStgMedium( pStgmed );
+ }
+ break;
+
+ default:
+ RpcRaiseException( E_INVALIDARG );
+ break;
+ }
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: FLAG_STGMEDIUM_UserSize
+//
+// Synopsis: Sizes a wrapper for stgmedium.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+FLAG_STGMEDIUM_UserSize(
+ unsigned long * pFlags,
+ unsigned long Offset,
+ FLAG_STGMEDIUM* pFlagStgmed )
+{
+ if ( ! pFlagStgmed )
+ return Offset;
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ Offset += sizeof(long);
+ Offset = STGMEDIUM_UserSize( pFlags, Offset, & pFlagStgmed->Stgmed );
+
+ return( Offset );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: FLAG_STGMEDIUM_UserMarshal
+//
+// Synopsis: Marshals a wrapper for stgmedium. Used in SetData.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+FLAG_STGMEDIUM_UserMarshal(
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ FLAG_STGMEDIUM* pFlagStgmed )
+{
+ if ( ! pFlagStgmed )
+ return pBuffer;
+
+ ALIGN( pBuffer, 3 );
+
+ // Flags: we need them when freeing in the client call_as routine
+
+ pFlagStgmed->ContextFlags = *pFlags;
+
+ *( PULONG_LV_CAST pBuffer)++ = *pFlags;
+ *( PULONG_LV_CAST pBuffer)++ = pFlagStgmed->fPassOwnership;
+
+ pBuffer = STGMEDIUM_UserMarshal( pFlags,
+ pBuffer,
+ & pFlagStgmed->Stgmed );
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: FLAG_STGMEDIUM_UserUnmarshal
+//
+// Synopsis: Unmarshals a wrapper for stgmedium.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+FLAG_STGMEDIUM_UserUnmarshal(
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ FLAG_STGMEDIUM* pFlagStgmed )
+{
+ ALIGN( pBuffer, 3 );
+
+ // Flags and buffer marker
+
+ pFlagStgmed->ContextFlags = *( PULONG_LV_CAST pBuffer)++;
+
+ // We need that in the Proxy, when we call the user free routine.
+
+ pFlagStgmed->fPassOwnership = *( PULONG_LV_CAST pBuffer)++;
+ pFlagStgmed->ContextFlags = *pFlags;
+
+ // We always unmarshal a FLAG_STGMEDIUM object.
+ // The engine will always free the FLAG_STGMEDIUM object later.
+ // Adjustments for passing the ownership are done within SetData_Stub.
+
+ pBuffer = STGMEDIUM_UserUnmarshal( pFlags,
+ pBuffer,
+ & pFlagStgmed->Stgmed );
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: FLAG_STGMEDIUM_UserFree
+//
+// Synopsis: Freess a wrapper for stgmedium.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+FLAG_STGMEDIUM_UserFree(
+ unsigned long * pFlags,
+ FLAG_STGMEDIUM* pFlagsStgmed )
+{
+ if ( ! pFlagsStgmed->fPassOwnership )
+ STGMEDIUM_UserFree( pFlags, & pFlagsStgmed->Stgmed );
+
+ // else the callee is supposed to release the stg medium.
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ASYNC_STGMEDIUM_UserSize
+//
+// Synopsis: Sizes a wrapper for stgmedium.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+ASYNC_STGMEDIUM_UserSize(
+ unsigned long * pFlags,
+ unsigned long Offset,
+ ASYNC_STGMEDIUM* pAsyncStgmed )
+{
+ if ( ! pAsyncStgmed )
+ return Offset;
+
+ // we cant do the inproc optimizations (which avoid copies of the data)
+ // on ASYNC calls, since on return the caller will delete the data
+ // before the server has run.
+
+ if (!REMOTE_CALL(*pFlags))
+ {
+ *pFlags &= ~0xff;
+ *pFlags |= MSHCTX_DIFFERENTMACHINE;
+ }
+
+ Offset = STGMEDIUM_UserSize( pFlags, Offset, pAsyncStgmed );
+
+ return( Offset );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ASYNC_STGMEDIUM_UserMarshal
+//
+// Synopsis: Marshals a wrapper for stgmedium. Used in SetData.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+ASYNC_STGMEDIUM_UserMarshal(
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ ASYNC_STGMEDIUM* pAsyncStgmed )
+{
+ if ( ! pAsyncStgmed )
+ return pBuffer;
+
+ // we cant do the inproc optimizations (which avoid copies of the data)
+ // on ASYNC calls, since on return the caller will delete the data
+ // before the server has run.
+
+ if (!REMOTE_CALL(*pFlags))
+ {
+ *pFlags &= ~0xff;
+ *pFlags |= MSHCTX_DIFFERENTMACHINE;
+ }
+
+ pBuffer = STGMEDIUM_UserMarshal( pFlags,
+ pBuffer,
+ pAsyncStgmed );
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ASYNC_STGMEDIUM_UserUnmarshal
+//
+// Synopsis: Unmarshals a wrapper for stgmedium.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+ASYNC_STGMEDIUM_UserUnmarshal(
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ ASYNC_STGMEDIUM* pAsyncStgmed )
+{
+ // we cant do the inproc optimizations (which avoid copies of the data)
+ // on ASYNC calls, since on return the caller will delete the data
+ // before the server has run.
+
+ if (!REMOTE_CALL(*pFlags))
+ {
+ // note: not strictly necessary to do this for Unmarshal, but it
+ // provides consistency.
+
+ *pFlags &= ~0xff;
+ *pFlags |= MSHCTX_DIFFERENTMACHINE;
+ }
+
+ pBuffer = STGMEDIUM_UserUnmarshal( pFlags,
+ pBuffer,
+ pAsyncStgmed );
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ASYNC_STGMEDIUM_UserFree
+//
+// Synopsis: Freess a wrapper for stgmedium.
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+ASYNC_STGMEDIUM_UserFree(
+ unsigned long * pFlags,
+ ASYNC_STGMEDIUM* pAsyncStgmed )
+{
+ // we cant do the inproc optimizations (which avoid copies of the data)
+ // on ASYNC calls, since on return the caller will delete the data
+ // before the server has run.
+
+ if (!REMOTE_CALL(*pFlags))
+ {
+ *pFlags &= ~0xff;
+ *pFlags |= MSHCTX_DIFFERENTMACHINE;
+ }
+
+ STGMEDIUM_UserFree( pFlags, pAsyncStgmed );
+}
+
+
+#if (DBG==1)
+//+-------------------------------------------------------------------------
+//
+// Function: WdtpGetStgmedName
+//
+// Synopsis: Debug support
+//
+// history: May-95 Ryszardk Created.
+//
+//--------------------------------------------------------------------------
+
+char *
+WdtpGetStgmedName( STGMEDIUM * pStgmed)
+
+{
+ char * Name;
+ if ( pStgmed )
+ {
+ switch (pStgmed->tymed)
+ {
+ case TYMED_NULL:
+ Name = "TYMED_NULL";
+ break;
+ case TYMED_MFPICT:
+ Name = "TYMED_MFPICT";
+ break;
+ case TYMED_ENHMF:
+ Name = "TYMED_ENHMF";
+ break;
+ case TYMED_GDI:
+ Name = "TYMED_GDI";
+ break;
+ case TYMED_HGLOBAL:
+ Name = "TYMED_HGLOBAL";
+ break;
+ case TYMED_FILE:
+ Name = "TYMED_FILE";
+ break;
+ case TYMED_ISTREAM:
+ Name = "TYMED_ISTREAM";
+ break;
+ case TYMED_ISTORAGE:
+ Name = "TYMED_ISTORAGE";
+ break;
+ default:
+ Name = "TYMED invalid";
+ break;
+ }
+ return Name;
+ }
+ else
+ return "STGMED * is null";
+}
+#endif
+
+#ifdef _CAIRO_
+//+-------------------------------------------------------------------------
+//
+// Function: HEVENT_UserSize
+//
+// Synopsis: Sizes an HEVENT handle.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+HEVENT_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ HEVENT * pH )
+{
+ return WdtpRemotableHandle_UserSize( pFlags, Offset, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HEVENT_UserMarshall
+//
+// Synopsis: Marshalls an HEVENT handle into the RPC buffer.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HEVENT_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HEVENT * pH )
+{
+ return WdtpRemotableHandle_UserMarshal( pFlags, pBuffer, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HEVENT_UserUnmarshall
+//
+// Synopsis: Unmarshalls an HEVENT handle from the RPC buffer.
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+HEVENT_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ HEVENT * pH )
+{
+ return WdtpRemotableHandle_UserUnmarshal( pFlags, pBuffer, (ulong*)pH );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: HEVENT_UserFree
+//
+// Synopsis: Free an HEVENT
+//
+//--------------------------------------------------------------------------
+
+void __RPC_USER
+HEVENT_UserFree(
+ unsigned long * pFlags,
+ HEVENT * pH )
+{
+}
+#endif
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CContinue
+//
+// Synopsis: Notification object
+//
+//--------------------------------------------------------------------------
+class CContinue : public IContinue
+{
+private:
+ long _cRef;
+ BOOL (__stdcall *_pfnContinue)(DWORD);
+ DWORD _dwContinue;
+ ~CContinue(void);
+
+public:
+ CContinue(BOOL (__stdcall *pfnContinue)(DWORD dwContinue), DWORD dwContinue);
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, void **);
+
+ ULONG STDMETHODCALLTYPE AddRef();
+
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE FContinue();
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CContinue::CContinue, public
+//
+// Synopsis: Constructor for CContinue
+//
+//--------------------------------------------------------------------------
+CContinue::CContinue(BOOL (__stdcall *pfnContinue)(DWORD dwContinue), DWORD dwContinue)
+: _cRef(1), _pfnContinue(pfnContinue), _dwContinue(dwContinue)
+{
+}
+
+CContinue::~CContinue()
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CContinue::QueryInterface, public
+//
+// Synopsis: Query for an interface on the notification object.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE
+CContinue::QueryInterface (
+ REFIID iid,
+ void **ppv )
+{
+ HRESULT hr = E_NOINTERFACE;
+
+ if ((IID_IUnknown == iid) || (IID_IContinue == iid))
+ {
+ this->AddRef();
+ *ppv = (IContinue *) this;
+ hr = S_OK;
+ }
+ else
+ {
+ *ppv = 0;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CContinue::AddRef, public
+//
+// Synopsis: Increment the reference count.
+//
+//--------------------------------------------------------------------------
+ULONG STDMETHODCALLTYPE
+CContinue::AddRef()
+{
+ InterlockedIncrement((long *) &_cRef);
+ return (unsigned long) _cRef;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CContinue::Release, public
+//
+// Synopsis: Decrement the reference count.
+//
+//--------------------------------------------------------------------------
+ULONG STDMETHODCALLTYPE
+CContinue::Release()
+{
+ unsigned long count = _cRef - 1;
+
+ if(0 == InterlockedDecrement((long *)&_cRef))
+ {
+ count = 0;
+ delete this;
+ }
+
+ return count;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CContinue::FContinue, public
+//
+// Synopsis: Calls the callback function.
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE
+CContinue::FContinue()
+{
+ HRESULT hr;
+ BOOL bResult;
+
+ bResult = (*_pfnContinue) (_dwContinue);
+
+ if(bResult == FALSE)
+ {
+ hr = S_FALSE;
+ }
+ else
+ {
+ hr = S_OK;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateCallback
+//
+// Synopsis: Create a callback notification object .
+//
+//--------------------------------------------------------------------------
+extern "C" HRESULT CreateCallback(
+ BOOL (__stdcall *pfnContinue)(DWORD dwContinue),
+ DWORD dwContinue,
+ IContinue **ppContinue)
+{
+ HRESULT hr;
+
+ if(pfnContinue != 0)
+ {
+ CContinue *pContinue = new CContinue(pfnContinue, dwContinue);
+
+ *ppContinue = (IContinue *) pContinue;
+
+ if(pContinue != 0)
+ {
+ hr = S_OK;
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ hr = E_INVALIDARG;
+ *ppContinue = 0;
+ }
+
+ return hr;
+}
diff --git a/private/ole32/oleprx32/proxy/transmit.h b/private/ole32/oleprx32/proxy/transmit.h
new file mode 100644
index 000000000..41a24894e
--- /dev/null
+++ b/private/ole32/oleprx32/proxy/transmit.h
@@ -0,0 +1,154 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994.
+//
+// File: transmit.h
+//
+// Contents: Function prototypes for STGMEDIUM marshalling.
+//
+// Functions: STGMEDIUM_to_xmit
+// STGMEDIUM_from_xmit
+// STGMEDIUM_free_inst
+//
+// History: May-10-94 ShannonC Created
+// History: May-10-95 Ryszardk wire_marshal changes
+//
+//--------------------------------------------------------------------------
+
+#ifndef __TRANSMIT_H__
+#define __TRANSMIT_H__
+
+#if (DBG==1)
+
+#include <debnot.h>
+
+DECLARE_DEBUG(UserNdr)
+//
+#define UserNdrDebugOut(x) UserNdrInlineDebugOut x
+#define UserNdrAssert(x) Win4Assert(x)
+#define UserNdrVerify(x) Win4Assert(x)
+
+//#define UNDR_FORCE DEB_FORCE
+#define UNDR_FORCE 0
+#define UNDR_OUT1 0
+#define UNDR_OUT4 0
+
+EXTERN_C char *
+WdtpGetStgmedName( STGMEDIUM * );
+
+#else
+
+#define UserNdrDebugOut(x)
+#define UserNdrAssert(x)
+#define UserNdrVerify(x)
+
+#define UNDR_FORCE 0
+#define UNDR_OUT1 0
+#define UNDR_OUT4 0
+
+#endif
+
+// Shortcut typedefs.
+
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+typedef unsigned int uint;
+
+#ifndef TRUE
+#define TRUE (1)
+#define FALSE (0)
+
+typedef unsigned short BOOL;
+#endif
+
+#define ALIGN( pStuff, cAlign ) \
+ pStuff = (unsigned char *)((ulong)((pStuff) + (cAlign)) & ~ (cAlign))
+
+#define LENGTH_ALIGN( Length, cAlign ) \
+ Length = (((Length) + (cAlign)) & ~ (cAlign))
+
+#define PCHAR_LV_CAST *(char __RPC_FAR * __RPC_FAR *)&
+#define PSHORT_LV_CAST *(short __RPC_FAR * __RPC_FAR *)&
+#define PLONG_LV_CAST *(long __RPC_FAR * __RPC_FAR *)&
+#define PHYPER_LV_CAST *(hyper __RPC_FAR * __RPC_FAR *)&
+
+#define PUSHORT_LV_CAST *(unsigned short __RPC_FAR * __RPC_FAR *)&
+#define PULONG_LV_CAST *(unsigned long __RPC_FAR * __RPC_FAR *)&
+
+#define USER_MARSHAL_MARKER 0x72657355
+
+// These are based on flags defined in wtypes.idl comming from the channel
+
+#define INPROC_CALL( Flags) (USER_CALL_CTXT_MASK(Flags) == MSHCTX_INPROC)
+#define REMOTE_CALL( Flags) ((USER_CALL_CTXT_MASK(Flags) == MSHCTX_DIFFERENTMACHINE) \
+ || (USER_CALL_CTXT_MASK(Flags) == MSHCTX_NOSHAREDMEM))
+#define DIFFERENT_MACHINE_CALL( Flags) \
+ (USER_CALL_CTXT_MASK(Flags) == MSHCTX_DIFFERENTMACHINE)
+
+// There is a difference in the scope of handles, Daytona vs. Chicago.
+// The following is an illustration of the notions of
+// HGLOBAL handle vs. data passing and GDI handle vs. data passing.
+// The type of an rpc call is defined by the flags above.
+
+// Daytona rules: GDI same as HGLOBAL
+//I------------I----------------I-----------------------------------I
+//I inproc I same machine I diff. machine (a.k.a "remote" ) I
+//I------------I----------------------------------------------------I
+//| HGLOBL h.p.| HGLOBAL data passing |
+//|------------|----------------------------------------------------|
+//| GDI h.p. | GDI data passing |
+//|------------|----------------------------------------------------|
+
+// Chicago rules: HGLOBAL stricter than GDI.
+//I------------I----------------I-----------------------------------I
+//I inproc I same machine I diff. machine (a.k.a "remote" ) I
+//I------------I----------------------------------------------------I
+//| HGLOBL h.p.| HGLOBAL data passing |
+//|-----------------------------------------------------------------|
+//| GDI handle passing | GDI data passing |
+//|-----------------------------|-----------------------------------|
+
+#define HGLOBAL_HANDLE_PASSING( Flags ) INPROC_CALL( Flags)
+#define HGLOBAL_DATA_PASSING( Flags ) (! INPROC_CALL( Flags))
+
+// On Chicago, some handles are valid between processes.
+
+#if defined(_CHICAGO_)
+#define GDI_HANDLE_PASSING( Flags ) (! REMOTE_CALL( Flags ))
+#define GDI_DATA_PASSING( Flags ) REMOTE_CALL( Flags )
+#else
+#define GDI_HANDLE_PASSING( Flags ) HGLOBAL_HANDLE_PASSING( Flags )
+#define GDI_DATA_PASSING( Flags ) HGLOBAL_DATA_PASSING( Flags )
+#endif
+
+#define WDT_DATA_MARKER WDT_REMOTE_CALL
+#define WDT_HANDLE_MARKER WDT_INPROC_CALL
+#define IS_DATA_MARKER( dw ) (WDT_REMOTE_CALL == dw)
+
+// CLIPFORMAT remoting
+
+#define CLIPFORMAT_BUFFER_MAX 248
+
+#define REMOTE_CLIPFORMAT(pFlags,pcf) ((0xC000<= *pcf) && (*pcf <=0xFFFF) && \
+ (USER_CALL_CTXT_MASK(*pFlags) == MSHCTX_DIFFERENTMACHINE) )
+
+
+#define WdtpMemoryCopy(Destination, Source, Length) \
+ RtlCopyMemory(Destination, Source, Length)
+#define WdtpZeroMemory(Destination, Length) \
+ RtlZeroMemory(Destination, Length)
+
+#define WdtpAllocate(p,size) \
+ ((USER_MARSHAL_CB *)p)->pStubMsg->pfnAllocate( size )
+#define WdtpFree(pf,ptr) \
+ ((USER_MARSHAL_CB *)pf)->pStubMsg->pfnFree( ptr )
+
+EXTERN_C
+void NukeHandleAndReleasePunk(
+ STGMEDIUM * pStgmed );
+
+#endif // __TRANSMIT_H__
+
+
diff --git a/private/ole32/oleprx32/wdt/daytona/makefile b/private/ole32/oleprx32/wdt/daytona/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ole32/oleprx32/wdt/daytona/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/oleprx32/wdt/daytona/sources b/private/ole32/oleprx32/wdt/daytona/sources
new file mode 100644
index 000000000..c804a12db
--- /dev/null
+++ b/private/ole32/oleprx32/wdt/daytona/sources
@@ -0,0 +1,43 @@
+
+
+
+MAJORCOMP=ole32
+MINORCOMP=wdt
+TARGETNAME=wdt32
+
+DLLDEF=obj\*\wdt32.def
+
+TARGETPATH= $(BASEDIR)\public\sdk\lib
+TARGETTYPE= DYNLINK
+DLLBASE= @$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,wdt32
+
+
+TARGETLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\gdi32p.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\oleaut32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\RpcRt4.lib
+
+
+LINKLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib
+
+INCLUDES=..\..\..\ih
+INCLUDES=$(INCLUDES)
+
+CONDITIONAL_INCLUDES=
+
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+
+SOURCES= \
+ ..\wdt.rc \
+ ..\wdt.cxx
+
+
+NO_CAIRO_LIBS=1
+
diff --git a/private/ole32/oleprx32/wdt/dirs b/private/ole32/oleprx32/wdt/dirs
new file mode 100644
index 000000000..6de069f1a
--- /dev/null
+++ b/private/ole32/oleprx32/wdt/dirs
@@ -0,0 +1,25 @@
+!if 0
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dirs
+//
+// Contents: dirs files for NT types project.
+//
+//
+// Functions:
+//
+// History: 12-20-93 terryru Created
+//
+//----------------------------------------------------------------------------
+
+!endif
+
+DIRS=
+
+OPTIONAL_DIRS= \
+ \
+
+
diff --git a/private/ole32/oleprx32/wdt/stdrpc.hxx b/private/ole32/oleprx32/wdt/stdrpc.hxx
new file mode 100644
index 000000000..83524a570
--- /dev/null
+++ b/private/ole32/oleprx32/wdt/stdrpc.hxx
@@ -0,0 +1,66 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: stdrpc.hxx
+//
+// Contents: Private header file for building interface proxies and stubs.
+//
+// Classes: CStreamOnMessage
+//
+// Functions:
+//
+// History: 4-Jul-93 ShannonC Created
+// 3-Aug-93 ShannonC Changes for NT511 and IDispatch support.
+// 10-Oct-93 ShannonC Changed to new IRpcChannelBuffer interface.
+// 22-Sep-94 MikeSe Moved from CINC and simplified.
+//
+//--------------------------------------------------------------------------
+#ifndef __STDRPC_HXX__
+#define __STDRPC_HXX__
+
+#define _OLE2ANAC_H_
+#include <windows.h>
+
+class CStreamOnMessage : public IStream
+{
+
+ public:
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj);
+ virtual ULONG STDMETHODCALLTYPE AddRef();
+ virtual ULONG STDMETHODCALLTYPE Release();
+ virtual HRESULT STDMETHODCALLTYPE Read(VOID HUGEP *pv, ULONG cb, ULONG *pcbRead);
+ virtual HRESULT STDMETHODCALLTYPE Write(VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten) ;
+ virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition) ;
+ virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize) ;
+ virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten) ;
+ virtual HRESULT STDMETHODCALLTYPE Commit(DWORD grfCommitFlags) ;
+ virtual HRESULT STDMETHODCALLTYPE Revert();
+ virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) ;
+ virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) ;
+ virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG *pstatstg, DWORD grfStatFlag) ;
+ virtual HRESULT STDMETHODCALLTYPE Clone(IStream * *ppstm) ;
+
+ CStreamOnMessage(unsigned char **ppMessageBuffer);
+ CStreamOnMessage(unsigned char **ppMessageBuffer, unsigned long cbMax);
+
+ unsigned char *pStartOfStream;
+ unsigned char **ppBuffer;
+ unsigned long cbMaxStreamLength;
+ ULONG ref_count;
+};
+
+#endif //__STDRPC_HXX__
+
diff --git a/private/ole32/oleprx32/wdt/transmit.h b/private/ole32/oleprx32/wdt/transmit.h
new file mode 100644
index 000000000..27f897976
--- /dev/null
+++ b/private/ole32/oleprx32/wdt/transmit.h
@@ -0,0 +1,82 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994.
+//
+// File: transmit.h
+//
+// Contents: Function prototypes for STGMEDIUM marshalling.
+//
+// Functions: STGMEDIUM_to_xmit
+// STGMEDIUM_from_xmit
+// STGMEDIUM_free_inst
+//
+// History: May-10-94 ShannonC Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __TRANSMIT_H__
+#define __TRANSMIT_H__
+
+#if (DBG==1)
+
+#include <debnot.h>
+
+//#define DEB_FORCE 0x7fffffff
+
+//DECLARE_DEBUG(UserNdr)
+//
+//#define UserNdrDebugOut(x) UserProxyInlineDebugOut x
+//#define UserNdreAssert(x) Win4Assert(x)
+//#define UserNdrVerify(x) Win4Assert(x)
+//
+
+DECLARE_DEBUG(Cairole)
+
+#define CairoleDebugOut(x) CairoleInlineDebugOut x
+#define CairoleAssert(x) Win4Assert(x)
+#define CairoleVerify(x) Win4Assert(x)
+
+#else
+
+#define CairoleDebugOut(x)
+#define CairoleAssert(x)
+#define CairoleVerify(x) (x)
+
+#endif
+
+EXTERN_C void
+WdtpPassOwnershipForStgmedium( FLAG_STGMEDIUM *, STGMEDIUM * );
+
+//EXTERN_C void __RPC_USER HENHMETAFILE_to_xmit (
+// HENHMETAFILE __RPC_FAR *pHEnhMetafile,
+// RemHENHMETAFILE __RPC_FAR * __RPC_FAR *ppxmit );
+//
+//EXTERN_C void __RPC_USER HENHMETAFILE_from_xmit(
+// RemHENHMETAFILE __RPC_FAR *pxmit,
+// HENHMETAFILE __RPC_FAR *pHEnhMetafile );
+//
+//EXTERN_C void __RPC_USER HENHMETAFILE_free_xmit( RemHENHMETAFILE __RPC_FAR *pxmit);
+//
+//EXTERN_C void __RPC_USER HPALETTE_to_xmit (
+// HPALETTE __RPC_FAR *pHPALETTE,
+// RemHPALETTE __RPC_FAR * __RPC_FAR *ppxmit);
+//
+//EXTERN_C void __RPC_USER HPALETTE_from_xmit(
+// RemHPALETTE __RPC_FAR *pxmit,
+// HPALETTE __RPC_FAR *pHPALETTE );
+//
+//EXTERN_C void __RPC_USER HPALETTE_free_xmit( RemHPALETTE __RPC_FAR *pxmit);
+//
+
+//// added for mega vs. mega2 split
+//
+//EXTERN_C void __RPC_USER SNB_to_xmit( SNB __RPC_FAR *, RemSNB __RPC_FAR * __RPC_FAR * );
+//EXTERN_C void __RPC_USER SNB_from_xmit( RemSNB __RPC_FAR *, SNB __RPC_FAR * );
+//EXTERN_C void __RPC_USER SNB_free_inst( SNB __RPC_FAR * );
+//EXTERN_C void __RPC_USER SNB_free_xmit( RemSNB __RPC_FAR * );
+//
+
+
+#endif // __TRANSMIT_H__
+
diff --git a/private/ole32/oleprx32/wdt/usermrsh.h b/private/ole32/oleprx32/wdt/usermrsh.h
new file mode 100644
index 000000000..70e26bf0c
--- /dev/null
+++ b/private/ole32/oleprx32/wdt/usermrsh.h
@@ -0,0 +1,76 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994.
+//
+// File: usermrsh.h
+//
+// Contents: Function prototypes related to user marshal support.
+//
+// History: Mar-15-95 RyszardK Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __USERMRSH_H__
+#define __USERMRSH_H__
+
+// Shortcut typedefs.
+
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+typedef unsigned int uint;
+
+#ifndef TRUE
+#define TRUE (1)
+#define FALSE (0)
+
+typedef unsigned short BOOL;
+#endif
+
+#define NDR_ASSERT( Expr, S )
+
+
+#define ALIGN( pStuff, cAlign ) \
+ pStuff = (unsigned char *)((ulong)((pStuff) + (cAlign)) & ~ (cAlign))
+
+#define LENGTH_ALIGN( Length, cAlign ) \
+ Length = (((Length) + (cAlign)) & ~ (cAlign))
+
+#define PCHAR_LV_CAST *(char __RPC_FAR * __RPC_FAR *)&
+#define PSHORT_LV_CAST *(short __RPC_FAR * __RPC_FAR *)&
+#define PLONG_LV_CAST *(long __RPC_FAR * __RPC_FAR *)&
+#define PHYPER_LV_CAST *(hyper __RPC_FAR * __RPC_FAR *)&
+
+#define PUSHORT_LV_CAST *(unsigned short __RPC_FAR * __RPC_FAR *)&
+#define PULONG_LV_CAST *(unsigned long __RPC_FAR * __RPC_FAR *)&
+
+#define USER_MARSHAL_MARKER 0x72657355
+
+// This are based on flags that come from wtypes.idl
+
+#define INPROC_CALL( Flags) (USER_CALL_CTXT_MASK(Flags) == MSHCTX_INPROC)
+#define REMOTE_CALL( Flags) (USER_CALL_CTXT_MASK(Flags) == MSHCTX_DIFFERENTMACHINE)
+#define GLOBAL_CALL( Flags) !INPROC_CALL(Flags) && !REMOTE_CALL(Flags)
+
+// Local handles are global on Chicago.
+// On NT, local handles are valid only within the same process.
+
+#if defined(_CHICAGO_)
+#define PASSING_DATA( Flags ) REMOTE_CALL( Flags )
+#define PASSING_HANDLE( Flags ) (! REMOTE_CALL( Flags ))
+#else
+#define PASSING_DATA( Flags ) (! INPROC_CALL( Flags ))
+#define PASSING_HANDLE( Flags ) INPROC_CALL( Flags )
+#endif
+
+#define WDT_DATA_MARKER WDT_REMOTE_CALL
+#define WDT_HANDLE_MARKER WDT_INPROC_CALL
+#define IS_DATA_MARKER( dw ) (WDT_REMOTE_CALL == dw)
+
+#define WdtpMemoryCopy(Destination, Source, Length) \
+ RtlCopyMemory(Destination, Source, Length)
+
+
+#endif // __USERMRSH_H__
+
diff --git a/private/ole32/oleprx32/wdt/wdt.cxx b/private/ole32/oleprx32/wdt/wdt.cxx
new file mode 100644
index 000000000..f869f40b8
--- /dev/null
+++ b/private/ole32/oleprx32/wdt/wdt.cxx
@@ -0,0 +1,1881 @@
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ wdt.cxx
+
+Abstract:
+
+ Windows Data Type Support by means of [user_marshal] attribute.
+
+ Covers:
+ BSTR
+ LPSAFEARRAY
+ VARIANT
+ DIPPARAMS
+ EXCEPINFO
+
+
+Author:
+
+ Ryszard K. Kott (ryszardk) Feb 14, 1995
+
+Revision History:
+
+-------------------------------------------------------------------*/
+
+
+//#include "stdrpc.hxx"
+#pragma hdrstop
+
+#include <wtypes.h>
+#include <objbase.h>
+#include <oleauto.h>
+#include <oaidl.h>
+
+//#include "..\ndr20\ndrole.h"
+
+#include "wdtp.h"
+#include <rpcwdt.h>
+#include <winerror.h>
+
+
+// #########################################################################
+//
+// BSTR
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: BSTR_UserSize
+//
+// Synopsis: Get the wire size for the BSTR handle and data.
+//
+// Derivation: Conformant struct with a flag field:
+// align + 12 + data size.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+BSTR_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ BSTR * pBstr)
+{
+ // Null bstr doesn't get marshalled.
+
+ if ( pBstr == NULL || *pBstr == NULL )
+ return Offset;
+
+ unsigned long ulDataSize;
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ // Takes the byte length of a unicode string
+
+ ulDataSize = (*pBstr) ? SysStringByteLen( *pBstr )
+ : 0;
+
+ return( Offset + 12 + ulDataSize) ;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: BSTR_UserMarshall
+//
+// Synopsis: Marshalls an BSTR object into the RPC buffer.
+//
+// Derivation: Conformant struct with a flag field:
+// align, size, null flag, size, data (bytes, if any)
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+BSTR_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ BSTR * pBstr)
+{
+ // A null Bstr is not marshalled, the engine will take care of it.
+
+ if ( pBstr == NULL || *pBstr == NULL )
+ return pBuffer;
+
+ unsigned long ulDataSize;
+
+ // Data size (in bytes): a null bstr gets a data size of zero.
+
+ ulDataSize = (*pBstr) ? SysStringByteLen( *pBstr )
+ : 0;
+
+ // Conformant size.
+
+ ALIGN( pBuffer, 3 );
+ *( PULONG_LV_CAST pBuffer)++ = (ulDataSize >> 1);
+
+ // FLAGGED_WORD_BLOB: Handle is the null/non-null flag
+
+ *( PULONG_LV_CAST pBuffer)++ = (unsigned long)*pBstr;
+
+ // Length on wire is in words.
+
+ *( PULONG_LV_CAST pBuffer)++ = (ulDataSize >> 1);
+
+ if( ulDataSize )
+ {
+ // we don't put the terminating string on wire
+
+ WdtpMemoryCopy( pBuffer, *pBstr, ulDataSize );
+ }
+
+ return( pBuffer + ulDataSize );
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: BSTR_UserUnmarshall
+//
+// Synopsis: Unmarshalls an BSTR object from the RPC buffer.
+//
+// Derivation: Conformant struct with a flag field:
+// align, size, null flag, size, data (bytes, if any)
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+BSTR_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ BSTR * pBstr)
+{
+ unsigned long ulDataSize, fHandle;
+ BSTR Bstr = NULL; // Default to NULL BSTR
+
+ ALIGN( pBuffer, 3 );
+
+ ulDataSize = *( PULONG_LV_CAST pBuffer)++;
+ fHandle = *(ulong *)pBuffer;
+ pBuffer += 8;
+
+ if ( fHandle )
+ {
+ // Length on wire is in words, and the string is unicode.
+
+ if ( *pBstr &&
+ *(((ulong *)*pBstr) -1) == (ulDataSize << 1) )
+ WdtpMemoryCopy( *pBstr, pBuffer, (ulDataSize << 1) );
+ else
+ {
+ if (! SysReAllocStringLen( pBstr,
+ (OLECHAR *)pBuffer,
+ ulDataSize ) )
+ RpcRaiseException( E_OUTOFMEMORY );
+ }
+ }
+ else
+ {
+ // free the old one, make it NULL.
+
+ SysFreeString( *pBstr );
+ *pBstr = NULL;
+ }
+
+ return( pBuffer + (ulDataSize << 1) );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: BSTR_UserFree
+//
+// Synopsis: Free an BSTR.
+//
+//--------------------------------------------------------------------------
+void __RPC_USER
+BSTR_UserFree(
+ unsigned long * pFlags,
+ BSTR * pBstr)
+{
+ if( pBstr && *pBstr )
+ {
+ SysFreeString(* pBstr);
+ *pBstr = NULL;
+ }
+}
+
+
+// #########################################################################
+//
+// VARIANT
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: VARIANT_UserSize
+//
+// Synopsis: Get the wire size the VARIANT handle and data.
+//
+// Derivation:
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+VARIANT_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ VARIANT * pVariant )
+{
+ if ( pVariant == NULL )
+ return Offset;
+
+ // alignment for the structure: DCE union is assumed for alignment.
+
+ LENGTH_ALIGN( Offset, 7 );
+
+ // Data size: common fields + switch
+
+ Offset += 4 * sizeof(short) + sizeof(long);
+
+ // Alignment for the union arm
+
+ switch ( pVariant->vt )
+ {
+ case VT_I8:
+ case VT_CY:
+ case VT_UI8:
+ case VT_R8:
+ case VT_DATE:
+ LENGTH_ALIGN( Offset, 7 );
+ break;
+
+ default:
+ break;
+ };
+
+ // now the field
+ // Account for the pointer, if there is one.
+
+ if ( pVariant->vt & VT_BYREF )
+ {
+ if ( NULL == pVariant->plVal )
+ RpcRaiseException( RPC_X_NULL_REF_POINTER );
+ Offset += 4;
+ }
+
+ VARTYPE vtDiscr = pVariant->vt;
+
+ if ( vtDiscr & VT_ARRAY )
+ vtDiscr = vtDiscr & (VT_ARRAY | VT_BYREF);
+
+ switch ( vtDiscr )
+ {
+ case VT_UI1:
+ case VT_UI1|VT_BYREF:
+ Offset += 1;
+ break;
+
+ case VT_I2:
+ case VT_BOOL:
+ case VT_I2 | VT_BYREF:
+ case VT_BOOL | VT_BYREF:
+ Offset += 2;
+ break;
+
+ case VT_I4:
+ case VT_R4:
+ case VT_ERROR:
+ case VT_I4 | VT_BYREF:
+ case VT_R4 | VT_BYREF:
+ case VT_ERROR | VT_BYREF:
+ Offset += 4;
+ break;
+
+ case VT_I8:
+ case VT_CY:
+ case VT_UI8:
+ case VT_R8:
+ case VT_DATE:
+ case VT_I8 | VT_BYREF:
+ case VT_CY | VT_BYREF:
+ case VT_UI8 | VT_BYREF:
+ case VT_R8 | VT_BYREF:
+ case VT_DATE | VT_BYREF:
+ Offset += 8;
+ break;
+
+ case VT_BSTR:
+ Offset += 4;
+ if ( pVariant->bstrVal )
+ Offset = BSTR_UserSize( pFlags, Offset, & pVariant->bstrVal );
+ break;
+
+ case VT_BSTR | VT_BYREF:
+ Offset += 4;
+ if ( * (pVariant->pbstrVal) )
+ Offset = BSTR_UserSize( pFlags, Offset, pVariant->pbstrVal );
+ break;
+
+ case VT_UNKNOWN:
+ case VT_DISPATCH:
+ Offset += 4;
+ if ( pVariant->punkVal )
+ Offset = WdtpInterfacePointer_UserSize(
+ (USER_MARSHAL_CB *)pFlags,
+ *pFlags,
+ Offset,
+ pVariant->punkVal,
+ ((pVariant->vt & VT_DISPATCH) ? IID_IDispatch
+ : IID_IUnknown) );
+ break;
+
+ case VT_UNKNOWN | VT_BYREF:
+ case VT_DISPATCH | VT_BYREF:
+ Offset += 4;
+ if ( *(pVariant->ppunkVal) )
+ Offset = WdtpInterfacePointer_UserSize(
+ (USER_MARSHAL_CB *)pFlags,
+ *pFlags,
+ Offset,
+ *pVariant->ppunkVal,
+ ((pVariant->vt & VT_DISPATCH) ? IID_IDispatch
+ : IID_IUnknown) );
+ break;
+
+ case VT_ARRAY:
+ Offset += 4;
+ Offset = LPSAFEARRAY_UserSize( pFlags,
+ Offset,
+ & pVariant->parray );
+ break;
+
+ case VT_ARRAY | VT_BYREF:
+ Offset += 4;
+ Offset = LPSAFEARRAY_UserSize( pFlags,
+ Offset,
+ pVariant->pparray );
+ break;
+
+ case VT_VARIANT:
+ RpcRaiseException( ERROR_BAD_ARGUMENTS );
+ break;
+
+ case VT_VARIANT|VT_BYREF:
+ Offset += 4;
+ Offset = VARIANT_UserSize( pFlags, Offset, pVariant->pvarVal );
+ break;
+
+ case VT_EMPTY:
+ case VT_NULL:
+ break;
+
+ default:
+ RpcRaiseException( ERROR_BAD_ARGUMENTS );
+ break;
+ }
+
+ return( Offset );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: VARIANT_UserMarshal
+//
+// Synopsis: Marshalls an VARIANT object into the RPC buffer.
+//
+// Derivation:
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+VARIANT_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ VARIANT * pVariant )
+{
+ if ( ! pVariant )
+ return pBuffer;
+
+ // userVARIANT: alignment for the structure
+
+ ALIGN( pBuffer, 7 );
+
+ // common fields: vt + 3 reserved shorts
+
+ WdtpMemoryCopy( pBuffer, pVariant, 4 * sizeof(short) );
+ pBuffer += 4 * sizeof(short);
+
+ // union switch
+
+ *( PULONG_LV_CAST pBuffer )++ = pVariant->vt;
+
+ // Alignment for the union arm
+
+ switch ( pVariant->vt )
+ {
+ case VT_I8:
+ case VT_CY:
+ case VT_UI8:
+ case VT_R8:
+ case VT_DATE:
+ ALIGN( pBuffer, 7 );
+ break;
+
+ default:
+ break;
+ };
+
+ // now the field
+ // Put the pointer, if there is one, as it has to go there, no matter what.
+
+ if ( pVariant->vt & VT_BYREF )
+ {
+ if ( NULL == pVariant->plVal )
+ RpcRaiseException( RPC_X_NULL_REF_POINTER );
+ *( PLONG_LV_CAST pBuffer )++ = (long)pVariant->plVal;
+ }
+
+ VARTYPE vtDiscr = pVariant->vt;
+
+ if ( vtDiscr & VT_ARRAY )
+ vtDiscr = vtDiscr & (VT_ARRAY | VT_BYREF);
+
+ switch ( vtDiscr )
+ {
+ case VT_UI1:
+ *( PCHAR_LV_CAST pBuffer )++ = pVariant->bVal;
+ break;
+
+ case VT_UI1|VT_BYREF:
+ *( PCHAR_LV_CAST pBuffer )++ = *pVariant->pbVal;
+ break;
+
+ case VT_I2:
+ case VT_BOOL:
+ *( PSHORT_LV_CAST pBuffer )++ = pVariant->iVal;
+ break;
+
+ case VT_I2 | VT_BYREF:
+ case VT_BOOL | VT_BYREF:
+ *( PSHORT_LV_CAST pBuffer )++ = * pVariant->piVal;
+ break;
+
+ case VT_I4:
+ case VT_R4:
+ case VT_ERROR:
+ *( PLONG_LV_CAST pBuffer )++ = pVariant->lVal;
+ break;
+
+ case VT_I4 | VT_BYREF:
+ case VT_R4 | VT_BYREF:
+ case VT_ERROR | VT_BYREF:
+ *( PLONG_LV_CAST pBuffer )++ = * pVariant->plVal;
+ break;
+
+ case VT_I8:
+ case VT_CY:
+ case VT_UI8:
+ case VT_R8:
+ case VT_DATE:
+ ALIGN( pBuffer, 7 );
+ WdtpMemoryCopy( pBuffer, & pVariant->dblVal, sizeof(double) );
+ pBuffer += sizeof(double);
+ break;
+
+ case VT_I8 | VT_BYREF:
+ case VT_CY | VT_BYREF:
+ case VT_UI8 | VT_BYREF:
+ case VT_R8 | VT_BYREF:
+ case VT_DATE | VT_BYREF:
+ // already aligned at 8
+ WdtpMemoryCopy( pBuffer, & pVariant->dblVal, sizeof(double) );
+ pBuffer += sizeof(double);
+ break;
+
+ case VT_BSTR:
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) pVariant->bstrVal;
+ if ( pVariant->bstrVal )
+ pBuffer = BSTR_UserMarshal( pFlags, pBuffer, & pVariant->bstrVal );
+ break;
+
+ case VT_BSTR | VT_BYREF:
+ // pbstrVal is already on the wire.
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) *(pVariant->pbstrVal);
+ if ( * (pVariant->pbstrVal) )
+ pBuffer = BSTR_UserMarshal( pFlags, pBuffer, pVariant->pbstrVal );
+ break;
+
+ case VT_UNKNOWN:
+ case VT_DISPATCH:
+ *( PULONG_LV_CAST pBuffer)++ = (unsigned long) pVariant->punkVal;
+ if ( pVariant->punkVal )
+ pBuffer = WdtpInterfacePointer_UserMarshal(
+ (USER_MARSHAL_CB *)pFlags,
+ *pFlags,
+ pBuffer,
+ pVariant->punkVal,
+ ((pVariant->vt & VT_DISPATCH) ? IID_IDispatch
+ : IID_IUnknown) );
+ break;
+
+ case VT_UNKNOWN | VT_BYREF:
+ case VT_DISPATCH | VT_BYREF:
+ // ppunkVal is already on the wire.
+ *( PULONG_LV_CAST pBuffer)++ = (unsigned long) *(pVariant->ppunkVal);
+ if ( * (pVariant->ppunkVal) )
+ pBuffer = WdtpInterfacePointer_UserMarshal(
+ (USER_MARSHAL_CB *)pFlags,
+ *pFlags,
+ pBuffer,
+ * pVariant->ppunkVal,
+ ((pVariant->vt & VT_DISPATCH) ? IID_IDispatch
+ : IID_IUnknown) );
+ break;
+
+ case VT_ARRAY:
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) pVariant->parray;
+ pBuffer = LPSAFEARRAY_UserMarshal( pFlags,
+ pBuffer,
+ & pVariant->parray );
+ break;
+
+ case VT_ARRAY | VT_BYREF:
+ // pparray is already on the wire.
+ *( PULONG_LV_CAST pBuffer)++ = (ulong) * (pVariant->pparray);
+ pBuffer = LPSAFEARRAY_UserMarshal( pFlags,
+ pBuffer,
+ pVariant->pparray );
+ break;
+
+ case VT_VARIANT|VT_BYREF:
+ *( PULONG_LV_CAST pBuffer)++ = USER_MARSHAL_MARKER;
+ pBuffer = VARIANT_UserMarshal( pFlags,
+ pBuffer,
+ pVariant->pvarVal );
+ break;
+
+ case VT_EMPTY:
+ case VT_NULL:
+ break;
+
+ default:
+ RpcRaiseException( ERROR_BAD_ARGUMENTS );
+ break;
+ }
+
+ return( pBuffer );
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: VARIANT_UserUnmarshall
+//
+// Synopsis: Unmarshalls an VARIANT object from the RPC buffer.
+//
+// Derivation:
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+VARIANT_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ VARIANT * pVariant)
+{
+ VARTYPE NewVt;
+
+ // alignment for the structure
+
+ ALIGN( pBuffer, 7 );
+
+ // See if we are going to reuse the variant.
+
+ NewVt = *(short*)pBuffer;
+
+ if ( pVariant->vt != VT_EMPTY && pVariant->vt != NewVt )
+ {
+ // We cannot use VARIANT_UserFree on the client,
+ // as it would attempt to free too much.
+
+ VariantClear( pVariant );
+ }
+
+ // common fields: vt and Res'es
+
+ WdtpMemoryCopy( pVariant, pBuffer, 4 * sizeof(short) );
+ pBuffer += 4 * sizeof(short);
+
+ // union switch: same as pVariant->vt
+
+ pBuffer += 4;
+
+ // Alignment for the union arm
+
+ switch ( pVariant->vt )
+ {
+ case VT_I8:
+ case VT_CY:
+ case VT_UI8:
+ case VT_R8:
+ case VT_DATE:
+ ALIGN( pBuffer, 7 );
+ break;
+
+ default:
+ break;
+ };
+
+ // now the field
+ // Skip the pointer, if there is one, as it is there, no matter what.
+
+ if ( pVariant->vt & VT_BYREF )
+ {
+ if ( NULL == *( PLONG_LV_CAST pBuffer)++ )
+ RpcRaiseException( RPC_X_NULL_REF_POINTER );
+ }
+
+ VARTYPE vtDiscr = pVariant->vt;
+
+ if ( vtDiscr & VT_ARRAY )
+ vtDiscr = vtDiscr & (VT_ARRAY | VT_BYREF);
+
+ switch ( vtDiscr )
+ {
+ case VT_UI1:
+ pVariant->bVal = *pBuffer++;
+ break;
+
+ case VT_UI1|VT_BYREF:
+ if ( ! pVariant->pbVal )
+ pVariant->pbVal = (unsigned char*)
+ WdtpAllocate( pFlags, sizeof(char) );
+ *pVariant->pbVal = *pBuffer++;
+ break;
+
+ case VT_I2:
+ case VT_BOOL:
+ pVariant->iVal = *( PSHORT_LV_CAST pBuffer)++;
+ break;
+
+ case VT_I2 | VT_BYREF:
+ case VT_BOOL | VT_BYREF:
+ if ( ! pVariant->piVal )
+ pVariant->piVal = (short *)
+ WdtpAllocate( pFlags, sizeof(short) );
+ *pVariant->piVal = *( PSHORT_LV_CAST pBuffer)++;
+ break;
+
+ case VT_I4:
+ case VT_R4:
+ case VT_ERROR:
+ pVariant->lVal = *( PLONG_LV_CAST pBuffer)++;
+ break;
+
+ case VT_I4 | VT_BYREF:
+ case VT_R4 | VT_BYREF:
+ case VT_ERROR | VT_BYREF:
+ if ( ! pVariant->plVal )
+ pVariant->plVal = (long *) WdtpAllocate( pFlags, sizeof(long));
+ *pVariant->plVal = *( PLONG_LV_CAST pBuffer)++;
+ break;
+
+ case VT_I8:
+ case VT_CY:
+ case VT_UI8:
+ case VT_R8:
+ case VT_DATE:
+ WdtpMemoryCopy( & pVariant->dblVal, pBuffer, sizeof(double) );
+ pBuffer += sizeof(double);
+ break;
+
+ case VT_I8 | VT_BYREF:
+ case VT_CY | VT_BYREF:
+ case VT_UI8 | VT_BYREF:
+ case VT_R8 | VT_BYREF:
+ case VT_DATE | VT_BYREF:
+ if ( ! pVariant->pdblVal )
+ pVariant->pdblVal = (double *)
+ WdtpAllocate( pFlags, sizeof(double) );
+ WdtpMemoryCopy( pVariant->pdblVal, pBuffer, sizeof(double) );
+ pBuffer += sizeof(double);
+ break;
+
+ case VT_BSTR:
+ // bstr value.
+ if ( *( PLONG_LV_CAST pBuffer)++ )
+ pBuffer = BSTR_UserUnmarshal( pFlags,
+ pBuffer,
+ & pVariant->bstrVal );
+ else
+ BSTR_UserFree( pFlags, & pVariant->bstrVal );
+ break;
+
+ case VT_BSTR | VT_BYREF:
+ if ( ! pVariant->pbstrVal )
+ {
+ pVariant->pbstrVal = (BSTR *)
+ WdtpAllocate( pFlags, sizeof(void*) );
+ *pVariant->pbstrVal = NULL;
+ }
+
+ // bstr value from the wire
+ if ( *( PLONG_LV_CAST pBuffer)++ )
+ pBuffer = BSTR_UserUnmarshal( pFlags,
+ pBuffer,
+ pVariant->pbstrVal );
+ else
+ BSTR_UserFree( pFlags, pVariant->pbstrVal );
+ break;
+
+ case VT_UNKNOWN:
+ case VT_DISPATCH:
+ pVariant->punkVal = (IUnknown*) *(PULONG_LV_CAST pBuffer)++;
+ if ( pVariant->punkVal )
+ {
+ pVariant->punkVal = NULL;
+ pBuffer = WdtpInterfacePointer_UserUnmarshal(
+ (USER_MARSHAL_CB *)pFlags,
+ pBuffer,
+ & pVariant->punkVal,
+ ((pVariant->vt & VT_DISPATCH) ? IID_IDispatch
+ : IID_IUnknown) );
+ }
+ else
+ WdtpInterfacePointer_UserFree( pVariant->punkVal );
+ break;
+
+ case VT_UNKNOWN | VT_BYREF:
+ case VT_DISPATCH | VT_BYREF:
+ if ( ! pVariant->ppunkVal )
+ {
+ pVariant->ppunkVal = (IUnknown **)
+ WdtpAllocate( pFlags, sizeof(void*));
+ *pVariant->ppunkVal = (IUnknown*) *(PULONG_LV_CAST pBuffer)++;
+ }
+
+ // pointer from the wire
+ if ( *( PLONG_LV_CAST pBuffer)++ )
+ {
+ pBuffer = WdtpInterfacePointer_UserUnmarshal(
+ (USER_MARSHAL_CB *)pFlags,
+ pBuffer,
+ pVariant->ppunkVal,
+ ((pVariant->vt & VT_DISPATCH) ? IID_IDispatch
+ : IID_IUnknown) );
+ }
+ else
+ WdtpInterfacePointer_UserFree( * (pVariant->ppunkVal) );
+ break;
+
+ case VT_ARRAY:
+ // Skip user marshal marker.
+ pBuffer += 4;
+ pBuffer = LPSAFEARRAY_UserUnmarshal( pFlags,
+ pBuffer,
+ & pVariant->parray );
+ break;
+
+ case VT_ARRAY | VT_BYREF:
+ if ( ! pVariant->pparray )
+ {
+ pVariant->pparray = (SAFEARRAY **)
+ WdtpAllocate( pFlags, sizeof(void*));
+ *pVariant->pparray = NULL;
+ }
+
+ pBuffer = LPSAFEARRAY_UserUnmarshal( pFlags,
+ pBuffer,
+ pVariant->pparray );
+ break;
+
+ case VT_VARIANT|VT_BYREF:
+ if ( ! pVariant->pvarVal )
+ {
+ pVariant->pvarVal = (VARIANT *)
+ WdtpAllocate( pFlags, sizeof(VARIANT) );
+ WdtpZeroMemory( pVariant->pvarVal, sizeof(VARIANT) );
+ }
+
+ pBuffer = VARIANT_UserUnmarshal( pFlags,
+ pBuffer,
+ pVariant->pvarVal );
+ break;
+
+ case VT_EMPTY:
+ case VT_NULL:
+ break;
+
+ default:
+ RpcRaiseException( ERROR_BAD_ARGUMENTS );
+ break;
+ }
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: VARIANT_UserFree
+//
+// Synopsis: Free a VARIANT.
+//
+// Note: We can't use VariantClear, as this one does not clean up
+// the way we need at the server side.
+//
+//--------------------------------------------------------------------------
+void __RPC_USER
+VARIANT_UserFree(
+ unsigned long * pFlags,
+ VARIANT * pVariant)
+{
+ if( pVariant)
+ {
+ long * pl = NULL;
+
+ // Account for the pointer, if there is one.
+
+ if ( pVariant->vt & VT_BYREF )
+ {
+ if ( NULL == pVariant->plVal )
+ RpcRaiseException( RPC_X_NULL_REF_POINTER );
+ pl = pVariant->plVal;
+
+ // remove the indirection in the variant
+
+ pVariant->bstrVal = * pVariant->pbstrVal;
+ }
+
+ VARTYPE vtDiscr = pVariant->vt;
+
+ if ( vtDiscr & VT_ARRAY )
+ vtDiscr = vtDiscr & (VT_ARRAY | VT_BYREF);
+
+ switch ( vtDiscr )
+ {
+ case VT_BSTR:
+ case VT_BSTR | VT_BYREF:
+ if ( pVariant->bstrVal )
+ BSTR_UserFree( pFlags, & pVariant->bstrVal );
+ break;
+
+ case VT_UNKNOWN:
+ case VT_DISPATCH:
+ case VT_UNKNOWN | VT_BYREF:
+ case VT_DISPATCH | VT_BYREF:
+ if ( pVariant->punkVal )
+ pVariant->punkVal->Release();
+ break;
+
+ case VT_ARRAY:
+ case VT_ARRAY | VT_BYREF:
+ LPSAFEARRAY_UserFree( pFlags, & pVariant->parray );
+ break;
+
+ default:
+ break;
+ }
+
+ // if there was BYREF, free the pointer itself.
+
+ if ( pl )
+ WdtpFree( pFlags, pl );
+ WdtpZeroMemory( pVariant, sizeof(VARIANT) );
+ }
+}
+
+
+// #########################################################################
+//
+// SAFEARRAY
+//
+// #########################################################################
+
+SF_TYPE
+GetSafeArrayDiscr( LPSAFEARRAY pSafeArray )
+/*
+ Finds out what type of olelment the safe array has.
+ SF_* constants are set to their VARTYPE (i.e. VT_*) equivalents.
+*/
+{
+ SF_TYPE sfDiscr = SF_ERROR;
+
+ switch ( pSafeArray->cbElements )
+ {
+ case 0:
+ break;
+ case 1:
+ sfDiscr = SF_I1;
+ break;
+ case 2:
+ sfDiscr = SF_I2;
+ break;
+ case 4:
+ {
+ sfDiscr = SF_I4;
+
+ ulong Feature = pSafeArray->fFeatures & 0x0f00;
+
+ switch ( Feature )
+ {
+ case FADF_BSTR:
+ sfDiscr = SF_BSTR;
+ break;
+ case FADF_UNKNOWN:
+ sfDiscr = SF_UNKNOWN;
+ break;
+ case FADF_DISPATCH:
+ sfDiscr = SF_DISPATCH;
+ break;
+ case FADF_VARIANT:
+ sfDiscr = SF_VARIANT;
+ break;
+ }
+ }
+ break;
+ case 8:
+ sfDiscr = SF_I8;
+ break;
+ default:
+ break;
+ }
+
+ if ( SF_ERROR == sfDiscr )
+ RpcRaiseException( ERROR_BAD_ARGUMENTS );
+
+ return sfDiscr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: LPSAFEARRAY_UserSize
+//
+// Synopsis: Get the wire size the SAFEARRAY handle and data.
+//
+// Derivation:
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+LPSAFEARRAY_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ LPSAFEARRAY * pPSafeArray )
+{
+ if ( NULL == pPSafeArray )
+ return Offset;
+
+ LENGTH_ALIGN( Offset, 3 );
+ Offset += 4;
+
+ if ( ! *pPSafeArray )
+ return Offset;
+
+ // userSAFEARRAY object
+
+ LPSAFEARRAY pSafeArray = *pPSafeArray;
+
+ // Data size: conf size, common fields, switch, union arm;
+ // then array bounds, and the array of pointers.
+ // Union arm is always a struct with a size field and the other field being
+ // a pointer to a conformant array.
+
+ Offset += sizeof(long) + 2 * sizeof(short) + 2 * sizeof(long) +
+ sizeof(SAFEARRAYUNION);
+
+ // Size of bounds
+
+ Offset += pSafeArray->cDims * sizeof(SAFEARRAYBOUND);
+
+ // Elements of the array pointed to by the arm.
+
+ long lElemCount = 1;
+
+ for (int i = 0; i < pSafeArray->cDims; i++)
+ lElemCount *= pSafeArray->rgsabound[i].cElements;
+
+ SF_TYPE sfDiscr = GetSafeArrayDiscr( pSafeArray );
+
+ // Size of the array itself.
+ // Size of elem is eaither size of data, pointer or user marshal marker.
+
+ long WireElemSize = pSafeArray->cbElements;
+
+ if ( pSafeArray->cbElements == sizeof(VARIANT) )
+ WireElemSize = sizeof(long);
+
+ if ( SF_I8 == sfDiscr )
+ {
+ LENGTH_ALIGN( Offset, 7 );
+ }
+
+ if ( lElemCount == 0 )
+ return Offset;
+
+ Offset += lElemCount * WireElemSize;
+
+ // Now the pointees: only for "non-integer" cases.
+
+ if ( sfDiscr != SF_BSTR && sfDiscr != SF_VARIANT &&
+ sfDiscr != SF_UNKNOWN && sfDiscr != SF_DISPATCH )
+ return( Offset );
+
+ for (i = 0; i < lElemCount; i++)
+ {
+ switch ( sfDiscr )
+ {
+ case SF_BSTR:
+ // an element is a BSTR
+ Offset = BSTR_UserSize( pFlags,
+ Offset,
+ & ((BSTR*)(pSafeArray->pvData))[i]);
+ break;
+ case SF_UNKNOWN:
+ // an element is a IUnknown *
+ Offset = WdtpInterfacePointer_UserSize(
+ (USER_MARSHAL_CB *)pFlags,
+ *pFlags,
+ Offset,
+ ((IUnknown**)(pSafeArray->pvData))[i],
+ IID_IUnknown );
+ break;
+ case SF_DISPATCH:
+ // an element is a IDispatch *
+ Offset = WdtpInterfacePointer_UserSize(
+ (USER_MARSHAL_CB *)pFlags,
+ *pFlags,
+ Offset,
+ ((IUnknown**)(pSafeArray->pvData))[i],
+ IID_IDispatch );
+ break;
+ case SF_VARIANT:
+ // an element is a VARIANT (not a pointer to it!)
+ Offset = VARIANT_UserSize( pFlags,
+ Offset,
+ & ((VARIANT*)(pSafeArray->pvData))[i] );
+ break;
+ }
+ }
+
+ return( Offset );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SAFEARRAY_UserMarshal
+//
+// Synopsis: Marshalls an SAFEARRAY object into the RPC buffer.
+//
+// Derivation: Conformant struct with a flag field:
+// align, size, null flag, size, data (bytes, if any)
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+LPSAFEARRAY_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ LPSAFEARRAY * pPSafeArray)
+{
+ if ( NULL == pPSafeArray )
+ return pBuffer;
+
+ ALIGN( pBuffer, 3 );
+ *( PULONG_LV_CAST pBuffer )++ = (ulong) *pPSafeArray;
+
+ if ( ! *pPSafeArray )
+ return pBuffer;
+
+ // userSAFEARRAY object
+ // See the sizing routine descr for the list of things to marshall.
+
+ LPSAFEARRAY pSafeArray = *pPSafeArray;
+
+ *( PULONG_LV_CAST pBuffer )++ = pSafeArray->cDims; // conf size
+
+ *( PUSHORT_LV_CAST pBuffer )++ = pSafeArray->cDims;
+ *( PUSHORT_LV_CAST pBuffer )++ = pSafeArray->fFeatures;
+ *( PULONG_LV_CAST pBuffer )++ = pSafeArray->cbElements;
+ *( PULONG_LV_CAST pBuffer )++ = pSafeArray->cLocks;
+
+ // Union switch: This cannot be just pSafeArray->fFeatures
+ // as this doesn't cover all that we need.
+
+ SF_TYPE sfDiscr = GetSafeArrayDiscr( pSafeArray );
+
+ *( PULONG_LV_CAST pBuffer )++ = sfDiscr;
+
+ // Compute the size of the array pointed to by the arm.
+
+ long lElemCount = 1;
+
+ for (int i = 0; i < pSafeArray->cDims; i++)
+ lElemCount *= pSafeArray->rgsabound[i].cElements;
+
+ // union arm
+
+ NDR_ASSERT( lElemCount == 0 && pSafeArray->pvData == 0 ||
+ lElemCount != 0 && pSafeArray->pvData != 0,
+ "Size and pointer inconsistent" );
+
+ *( PULONG_LV_CAST pBuffer )++ = lElemCount;
+ *( PULONG_LV_CAST pBuffer )++ = (ULONG) pSafeArray->pvData;
+
+ // the safe array bounds
+
+ for (i = 0; i < pSafeArray->cDims; i++)
+ {
+ *( PULONG_LV_CAST pBuffer )++ = pSafeArray->rgsabound[ i ].cElements;
+ *( PULONG_LV_CAST pBuffer )++ = pSafeArray->rgsabound[ i ].lLbound;
+ }
+
+ // Now the array of data, pointers, or markers.
+
+ if ( lElemCount )
+ {
+ unsigned char * pPointee;
+ unsigned long WireElemSize = pSafeArray->cbElements;
+ void * pvData;
+
+ if ( pSafeArray->cbElements == sizeof(VARIANT) )
+ WireElemSize = sizeof(long);
+
+ // This is a conformant array of something.
+
+ *( PULONG_LV_CAST pBuffer )++ = lElemCount;
+
+ // The array has either pointers (for interface ptrs) or
+ // user marshal markers (for BSTR and VARIANT) or plain data.
+
+ if ( S_OK != SafeArrayAccessData( pSafeArray, & pvData ))
+ RpcRaiseException( E_OUTOFMEMORY );
+
+ if ( sfDiscr != SF_BSTR && sfDiscr != SF_VARIANT &&
+ sfDiscr != SF_UNKNOWN && sfDiscr != SF_DISPATCH )
+ {
+ // A block copy of plain data.
+
+ unsigned long cbArraySize = lElemCount * WireElemSize;
+
+ if ( SF_I8 == sfDiscr )
+ {
+ ALIGN( pBuffer, 7 );
+ }
+
+ WdtpMemoryCopy( pBuffer, pvData, cbArraySize );
+ pBuffer += cbArraySize;
+ SafeArrayUnaccessData( pSafeArray );
+ return( pBuffer );
+ }
+
+ // We locked the array, to try finally is needed to unlock it
+ // in face of exception in the marshalling code.
+
+ __try
+ {
+ // Only pointers or user marshal markers in the array.
+
+ pPointee = pBuffer + sizeof(long) * WireElemSize;
+
+ for (i = 0; i < lElemCount; i++)
+ {
+ if ( ((BSTR*)pvData)[i] == NULL )
+ {
+ *( PULONG_LV_CAST pBuffer )++ = 0;
+ }
+ else
+ {
+ switch ( sfDiscr )
+ {
+ case SF_BSTR:
+ *( PULONG_LV_CAST pBuffer )++ = USER_MARSHAL_MARKER;
+ pPointee = BSTR_UserMarshal(
+ pFlags,
+ pPointee,
+ & ((BSTR*)(pvData))[i] );
+ break;
+
+ case SF_UNKNOWN:
+ *( PULONG_LV_CAST pBuffer )++ = ((ulong*)(pvData))[i];
+ pPointee = WdtpInterfacePointer_UserMarshal(
+ (USER_MARSHAL_CB *)pFlags,
+ *pFlags,
+ pPointee,
+ ((IUnknown**)(pvData))[i],
+ IID_IUnknown );
+ break;
+
+ case SF_DISPATCH:
+ *( PULONG_LV_CAST pBuffer )++ = ((ulong*)(pvData))[i];
+ pPointee = WdtpInterfacePointer_UserMarshal(
+ (USER_MARSHAL_CB *)pFlags,
+ *pFlags,
+ pPointee,
+ ((IUnknown**)(pvData))[i],
+ IID_IDispatch );
+ break;
+
+ case SF_VARIANT:
+ *( PULONG_LV_CAST pBuffer )++ = USER_MARSHAL_MARKER;
+ pPointee = VARIANT_UserMarshal(
+ pFlags,
+ pPointee,
+ & ((VARIANT*)(pvData))[i] );
+ break;
+
+ default:
+ RpcRaiseException(ERROR_BAD_ARGUMENTS);
+ break;
+ }
+ }
+ } // for
+
+ pBuffer = pPointee;
+
+ }
+ __finally
+ {
+ SafeArrayUnaccessData( pSafeArray );
+ }
+
+ } // if lElemCount
+
+ return( pBuffer );
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: SAFEARRAY_UserUnmarshal
+//
+// Synopsis: Unmarshalls an SAFEARRAY object from the RPC buffer.
+//
+// Derivation: Conformant struct with a flag field:
+// align, size, null flag, size, data (bytes, if any)
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+LPSAFEARRAY_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ LPSAFEARRAY * pPSafeArray)
+{
+ unsigned long ulDataSize, fNullHandle;
+
+ ALIGN( pBuffer, 3 );
+ SAFEARRAY * pSafeArray = (SAFEARRAY*)( PULONG_LV_CAST pBuffer )++;
+
+ if ( ! pSafeArray )
+ {
+ // A null safe array coming. Release the old one.
+
+ if ( *pPSafeArray )
+ SafeArrayDestroy( *pPSafeArray );
+
+ *pPSafeArray = pSafeArray;
+
+ return pBuffer;
+ }
+
+ // Non-null pointer: allocate a safe array.
+
+ pBuffer += sizeof(long); // skipping the conf size == cDims
+
+ unsigned short cDims = *( PUSHORT_LV_CAST pBuffer)++;
+ unsigned short fFeatures = *( PUSHORT_LV_CAST pBuffer)++;
+ unsigned long cbElements = *( PULONG_LV_CAST pBuffer)++;
+ unsigned long cLocks = *( PULONG_LV_CAST pBuffer)++;
+
+ // The union switch - it's not fFeatures, it's a FS_TYPE, i.e. a VARTYPE.
+ // It is set appropriately when marshalling.
+
+ VARTYPE sfDiscr = (VARTYPE) *( PULONG_LV_CAST pBuffer)++;
+
+ if ( VT_I8 == sfDiscr )
+ sfDiscr = VT_R8;
+
+ if ( VT_I1 == sfDiscr )
+ sfDiscr = VT_UI1;
+
+ // union arm: SAFEARRAY_*. Size of array pointed to by the arm.
+ // We can do for any discriminant: it is always 2 longs on wire.
+
+ unsigned long ElemCount = *( PULONG_LV_CAST pBuffer)++;
+ unsigned long pvData = *( PULONG_LV_CAST pBuffer)++;
+
+ // Array bounds are in the buffer behind the union.
+
+ SAFEARRAYBOUND * pBounds = (SAFEARRAYBOUND *) pBuffer;
+
+ pSafeArray = SafeArrayCreate( sfDiscr, cDims, pBounds );
+
+ if ( pSafeArray == NULL )
+ RpcRaiseException( E_OUTOFMEMORY );
+
+ // The safe array bounds:
+ // just skip them; they have been copied by SafeArrayCreate.
+
+ pBuffer += cDims * sizeof(SAFEARRAYBOUND);
+
+ // Fill in the safe object we've got.
+ // However, locks reflect this side locks, not he other side locks.
+ // BUGBUG: server side flags may be different from the originals.
+
+ pSafeArray->fFeatures = fFeatures;
+ pSafeArray->cbElements = cbElements;
+
+ // Now the array.
+ // This is a conformant array of data, pointers, or markers.
+
+ if ( ElemCount )
+ {
+ unsigned char * pPointee;
+ void * pvData;
+ unsigned long WireElemSize = pSafeArray->cbElements;
+
+ pBuffer += 4; // skipping the conf size
+
+ // The array has either pointers (for interface ptrs) or
+ // user marshal markers (for BSTR and VARIUANT) or plain data.
+
+ if ( pSafeArray->cbElements == sizeof(VARIANT) )
+ WireElemSize = sizeof(long);
+
+ if ( S_OK != SafeArrayAccessData( pSafeArray, & pvData ))
+ RpcRaiseException( E_OUTOFMEMORY );
+
+ unsigned long cbArraySize = ElemCount * WireElemSize;
+
+ if ( sfDiscr != SF_BSTR && sfDiscr != SF_VARIANT &&
+ sfDiscr != SF_UNKNOWN && sfDiscr != SF_DISPATCH )
+ {
+ // A block copy of plain data.
+
+ if ( VT_R8 == sfDiscr )
+ {
+ ALIGN( pBuffer, 7 );
+ }
+
+ WdtpMemoryCopy( pvData, pBuffer, cbArraySize );
+ pBuffer += cbArraySize;
+ SafeArrayUnaccessData( pSafeArray );
+ }
+ else
+ {
+ // Only pointers or user marshal markers in the array.
+
+ // We locked the array, so, try-finally is needed to unlock it
+ // in face of exception in the marshalling code.
+
+ __try
+ {
+ pPointee = pBuffer + cbArraySize;
+
+ WdtpZeroMemory( pvData, cbArraySize );
+
+ for (unsigned int i = 0; i < ElemCount; i++)
+ {
+ if ( *( PULONG_LV_CAST pBuffer )++ != 0 )
+ {
+ switch ( pSafeArray->fFeatures & 0x0f00 )
+ {
+ case SF_BSTR:
+ pPointee = BSTR_UserUnmarshal(
+ pFlags,
+ pPointee,
+ & ((BSTR*)(pvData))[i] );
+ break;
+
+ case SF_UNKNOWN:
+ pPointee = WdtpInterfacePointer_UserUnmarshal(
+ (USER_MARSHAL_CB *)pFlags,
+ pBuffer,
+ & ((IUnknown**)(pvData))[i],
+ IID_IUnknown );
+ break;
+
+ case SF_DISPATCH:
+ pPointee = WdtpInterfacePointer_UserUnmarshal(
+ (USER_MARSHAL_CB *)pFlags,
+ pBuffer,
+ & ((IUnknown**)(pvData))[i],
+ IID_IDispatch );
+ break;
+
+ case SF_VARIANT:
+ pPointee = VARIANT_UserUnmarshal(
+ pFlags,
+ pPointee,
+ & ((VARIANT*)(pvData))[i] );
+ break;
+
+ default:
+ RpcRaiseException( RPC_X_BAD_STUB_DATA );
+ break;
+ }
+ }
+ } // for
+
+ pBuffer = pPointee;
+
+ }
+ __finally
+ {
+ SafeArrayUnaccessData( pSafeArray );
+ }
+ }
+
+ } // if lElemCount
+
+ // No reusage, if it exists, the old one should be released.
+
+ if ( *pPSafeArray )
+ SafeArrayDestroy( *pPSafeArray );
+
+ *pPSafeArray = pSafeArray;
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: LPSAFEARRAY_UserFree
+//
+// Synopsis: Free an SAFEARRAY.
+//
+//--------------------------------------------------------------------------
+void __RPC_USER
+LPSAFEARRAY_UserFree(
+ unsigned long * pFlags,
+ LPSAFEARRAY * pPSafeArray)
+{
+ if( pPSafeArray && *pPSafeArray )
+ {
+ HRESULT hr = SafeArrayDestroy( *pPSafeArray );
+ if ( FAILED(hr) )
+ RpcRaiseException( hr );
+ }
+}
+
+
+// #########################################################################
+//
+// DISPPARAMS
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: DISPPARAMS_UserSize
+//
+// Synopsis: Get the wire size for the DISPPARAMS handle and data.
+//
+// Derivation: Conformant struct with a flag field:
+// align + 12 + data size.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+DISPPARAMS_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ DISPPARAMS * pDispParams)
+{
+ if ( !pDispParams )
+ return Offset;
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ Offset += sizeof(DISPPARAMS);
+
+ if ( pDispParams->cArgs && pDispParams->rgvarg )
+ {
+ // conformant size for the variant array.
+ Offset += sizeof(unsigned long);
+
+ // markers
+ Offset += pDispParams->cArgs * sizeof(unsigned long);
+
+ unsigned int carg = pDispParams->cArgs;
+
+ for (int i = 0; carg-- ; i++)
+ {
+ Offset = VARIANT_UserSize( pFlags,
+ Offset,
+ & pDispParams->rgvarg[i] );
+ }
+ }
+
+ // conformant size + dispid array.
+
+ if ( pDispParams->cNamedArgs && pDispParams->rgdispidNamedArgs )
+ Offset += sizeof (unsigned long) +
+ pDispParams->cNamedArgs * sizeof(DISPID);
+
+ return( Offset );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DISPPARAMS_UserMarshall
+//
+// Synopsis: Marshalls an DISPPARAMS object into the RPC buffer.
+//
+// Derivation:
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+DISPPARAMS_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ DISPPARAMS * pDispParams)
+{
+ if ( !pDispParams )
+ return pBuffer;
+
+ ALIGN( pBuffer, 3 );
+
+ WdtpMemoryCopy( pBuffer, pDispParams, sizeof(DISPPARAMS) );
+ pBuffer += sizeof(DISPPARAMS);
+
+ if ( pDispParams->cArgs && pDispParams->rgvarg )
+ {
+ uchar * pPointee;
+
+ // conformant size for the variant array.
+ *( PULONG_LV_CAST pBuffer)++ = pDispParams->cArgs;
+
+ pPointee = pBuffer + pDispParams->cArgs * sizeof(unsigned long);
+
+ unsigned int carg = pDispParams->cArgs;
+
+ for (int i = 0; carg-- ; i++)
+ {
+ *( PULONG_LV_CAST pBuffer)++ = USER_MARSHAL_MARKER;
+ pPointee = VARIANT_UserMarshal( pFlags,
+ pPointee,
+ & pDispParams->rgvarg[i] );
+ }
+
+ pBuffer = pPointee;
+ }
+
+ if ( pDispParams->cNamedArgs && pDispParams->rgdispidNamedArgs )
+ {
+ ALIGN( pBuffer, 3 );
+
+ *( PULONG_LV_CAST pBuffer)++ = pDispParams->cNamedArgs;
+ WdtpMemoryCopy( pBuffer,
+ pDispParams->rgdispidNamedArgs,
+ pDispParams->cNamedArgs * sizeof(DISPID) );
+ pBuffer += pDispParams->cNamedArgs * sizeof(DISPID);
+ }
+
+ return( pBuffer );
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DISPPARAMS_UserUnmarshall
+//
+// Synopsis: Unmarshalls an DISPPARAMS object from the RPC buffer.
+//
+// Derivation: Conformant struct with a flag field:
+// align, size, null flag, size, data (bytes, if any)
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+DISPPARAMS_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ DISPPARAMS * pDispParams)
+{
+ if ( !pDispParams )
+ return pBuffer;
+
+ // see if we can reuse
+
+ DISPPARAMS TmpDP;
+
+ ALIGN( pBuffer, 3 );
+ WdtpMemoryCopy( & TmpDP, pBuffer, sizeof(DISPPARAMS) );
+ pBuffer += sizeof(DISPPARAMS);
+
+ if ( TmpDP.cArgs != pDispParams->cArgs ||
+ TmpDP.cNamedArgs != pDispParams->cNamedArgs )
+ {
+ // cannot reuse it.
+
+ if ( pDispParams->cArgs || pDispParams->cNamedArgs )
+ DISPPARAMS_UserFree( pFlags, pDispParams );
+
+ pDispParams->cArgs = TmpDP.cArgs;
+ pDispParams->cNamedArgs = TmpDP.cNamedArgs;
+ }
+
+ if ( pDispParams->cArgs && ! pDispParams->rgvarg )
+ {
+ pDispParams->rgvarg = (VARIANT*) WdtpAllocate(
+ pFlags,
+ pDispParams->cArgs * sizeof( VARIANT ) );
+ WdtpZeroMemory( pDispParams->rgvarg,
+ pDispParams->cArgs * sizeof( VARIANT ) );
+ }
+
+
+ if ( pDispParams->cArgs && pDispParams->rgvarg )
+ {
+ // skip the conformant size for the variant array and the markers.
+
+ pBuffer += sizeof(unsigned long) +
+ pDispParams->cArgs * sizeof(unsigned long);
+
+ unsigned int carg = pDispParams->cArgs;
+
+ for (int i = 0; carg-- ; i++)
+ {
+ pBuffer = VARIANT_UserUnmarshal( pFlags,
+ pBuffer,
+ & pDispParams->rgvarg[i] );
+ }
+ }
+
+ if ( pDispParams->cNamedArgs && ! pDispParams->rgdispidNamedArgs )
+ {
+ pDispParams->rgdispidNamedArgs = (DISPID*) WdtpAllocate(
+ pFlags,
+ pDispParams->cNamedArgs * sizeof( DISPID ) );
+ }
+
+ if ( pDispParams->cNamedArgs && pDispParams->rgdispidNamedArgs )
+ {
+ // skip the conformant size.
+
+ ALIGN( pBuffer, 3 );
+ pBuffer += sizeof(unsigned long);
+
+ WdtpMemoryCopy( pDispParams->rgdispidNamedArgs,
+ pBuffer,
+ pDispParams->cNamedArgs * sizeof(DISPID) );
+ pBuffer += pDispParams->cNamedArgs * sizeof(DISPID);
+ }
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DISPPARAMS_UserFree
+//
+// Synopsis: Free an DISPPARAMS.
+//
+//--------------------------------------------------------------------------
+void __RPC_USER
+DISPPARAMS_UserFree(
+ unsigned long * pFlags,
+ DISPPARAMS * pDispParams)
+{
+
+ if( pDispParams)
+ {
+ if ( pDispParams->rgvarg )
+ {
+ unsigned int carg = pDispParams->cArgs;
+
+ for (int i = 0; carg-- ; i++)
+ VARIANT_UserFree( pFlags, & pDispParams->rgvarg[i] );
+
+ WdtpFree( pFlags, pDispParams->rgvarg );
+ }
+
+ if ( pDispParams->rgdispidNamedArgs )
+ WdtpFree( pFlags, pDispParams->rgdispidNamedArgs );
+
+ WdtpZeroMemory( pDispParams, sizeof(DISPPARAMS) );
+ }
+}
+
+
+
+// #########################################################################
+//
+// EXCEPINFO
+//
+// #########################################################################
+
+//+-------------------------------------------------------------------------
+//
+// Function: EXCEPINFO_UserSize
+//
+// Synopsis: Get the wire size for the EXCEPINFO handle and data.
+//
+// Derivation: Conformant struct with a flag field:
+// align + 12 + data size.
+//
+//--------------------------------------------------------------------------
+
+unsigned long __RPC_USER
+EXCEPINFO_UserSize (
+ unsigned long * pFlags,
+ unsigned long Offset,
+ EXCEPINFO * pExcepInfo)
+{
+ if ( pExcepInfo == NULL )
+ return Offset;
+
+ if ( pExcepInfo->pvReserved || pExcepInfo->pfnDeferredFillIn )
+ RpcRaiseException(ERROR_BAD_ARGUMENTS);
+
+ LENGTH_ALIGN( Offset, 3 );
+
+ Offset += sizeof( EXCEPINFO );
+ if ( pExcepInfo->bstrSource )
+ Offset = BSTR_UserSize( pFlags,
+ Offset,
+ & pExcepInfo->bstrSource );
+ if ( pExcepInfo->bstrDescription )
+ Offset = BSTR_UserSize( pFlags,
+ Offset,
+ & pExcepInfo->bstrDescription );
+ if ( pExcepInfo->bstrHelpFile )
+ Offset = BSTR_UserSize( pFlags,
+ Offset,
+ & pExcepInfo->bstrHelpFile );
+
+ return( Offset );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: EXCEPINFO_UserMarshall
+//
+// Synopsis: Marshalls an EXCEPINFO object into the RPC buffer.
+//
+// Derivation: Conformant struct with a flag field:
+// align, size, null flag, size, data (bytes, if any)
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+EXCEPINFO_UserMarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ EXCEPINFO * pExcepInfo)
+{
+ if ( pExcepInfo == NULL )
+ return pBuffer;
+
+ if ( pExcepInfo->pvReserved || pExcepInfo->pfnDeferredFillIn )
+ RpcRaiseException(ERROR_BAD_ARGUMENTS);
+
+ ALIGN( pBuffer, 3 );
+
+ WdtpMemoryCopy( pBuffer, pExcepInfo, sizeof(EXCEPINFO) );
+ pBuffer += sizeof( EXCEPINFO );
+
+ if ( pExcepInfo->bstrSource )
+ pBuffer = BSTR_UserMarshal( pFlags,
+ pBuffer,
+ & pExcepInfo->bstrSource );
+ if ( pExcepInfo->bstrDescription )
+ pBuffer = BSTR_UserMarshal( pFlags,
+ pBuffer,
+ & pExcepInfo->bstrDescription );
+ if ( pExcepInfo->bstrHelpFile )
+ pBuffer = BSTR_UserMarshal( pFlags,
+ pBuffer,
+ & pExcepInfo->bstrHelpFile );
+
+ return( pBuffer );
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: EXCEPINFO_UserUnmarshall
+//
+// Synopsis: Unmarshalls an EXCEPINFO object from the RPC buffer.
+//
+// Derivation: Conformant struct with a flag field:
+// align, size, null flag, size, data (bytes, if any)
+//
+//--------------------------------------------------------------------------
+
+unsigned char __RPC_FAR * __RPC_USER
+EXCEPINFO_UserUnmarshal (
+ unsigned long * pFlags,
+ unsigned char * pBuffer,
+ EXCEPINFO * pExcepInfo)
+{
+ ALIGN( pBuffer, 3 );
+
+ // no reusage for EXCEPINFO struct.
+
+ EXCEPINFO_UserFree( pFlags, pExcepInfo );
+
+ WdtpMemoryCopy( pExcepInfo, pBuffer, sizeof(EXCEPINFO) );
+ pBuffer += sizeof( EXCEPINFO );
+
+ if ( pExcepInfo->bstrSource )
+ {
+ pExcepInfo->bstrSource = NULL;
+ pBuffer = BSTR_UserUnmarshal( pFlags,
+ pBuffer,
+ & pExcepInfo->bstrSource );
+ }
+
+ if ( pExcepInfo->bstrDescription )
+ {
+ pExcepInfo->bstrDescription = NULL;
+ pBuffer = BSTR_UserUnmarshal( pFlags,
+ pBuffer,
+ & pExcepInfo->bstrDescription );
+ }
+
+ if ( pExcepInfo->bstrHelpFile )
+ {
+ pExcepInfo->bstrHelpFile = NULL;
+ pBuffer = BSTR_UserUnmarshal( pFlags,
+ pBuffer,
+ & pExcepInfo->bstrHelpFile );
+ }
+
+ return( pBuffer );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: EXCEPINFO_UserFree
+//
+// Synopsis: Free an EXCEPINFO.
+//
+//--------------------------------------------------------------------------
+void __RPC_USER
+EXCEPINFO_UserFree(
+ unsigned long * pFlags,
+ EXCEPINFO * pExcepInfo)
+{
+ if( pExcepInfo)
+ {
+ if ( pExcepInfo->bstrSource )
+ BSTR_UserFree( pFlags, & pExcepInfo->bstrSource );
+
+ if ( pExcepInfo->bstrDescription )
+ BSTR_UserFree( pFlags, & pExcepInfo->bstrDescription );
+
+ if ( pExcepInfo->bstrHelpFile )
+ BSTR_UserFree( pFlags, & pExcepInfo->bstrHelpFile );
+
+ pExcepInfo->pfnDeferredFillIn = 0;
+ }
+}
+
+
+
diff --git a/private/ole32/oleprx32/wdt/wdt32.def b/private/ole32/oleprx32/wdt/wdt32.def
new file mode 100644
index 000000000..cd65a8665
--- /dev/null
+++ b/private/ole32/oleprx32/wdt/wdt32.def
@@ -0,0 +1,63 @@
+#if 0
+
+ Microsoft Windows
+ Copyright (C) Microsoft Corporation, 1992 - 1994.
+ All rights reserved.
+
+ This .def file is preprocessed by the compiler to create the version for
+ the current build in the appropriate subdir. Basically, whatever you
+ would have used in your code to control what is compiled when can be
+ used in this file for the same purpose. The following defines are in
+ use at the time this file was written:
+
+ FLAT - Used to indicate a NT/DOS7 build
+ i386 - Intel i386/i486 build
+ MIPS - MIPS R3000/R4000 build
+ ALPHA - DEC Alpha build
+ DBG - Used to control Debug/Retail. Set to 1 if Debug,
+ 0 if Retail.
+ WIN31 - Win16 build
+ __OS2__ - OS/2 build (used by CT mostly)
+
+ If none of these are used, it is assumed the entire file can be used
+ for all builds.
+
+#endif
+
+LIBRARY WDT32
+
+DESCRIPTION 'Microsoft (R) OLE 2.0 Wdt DLL 1.00'
+
+EXPORTS
+
+ BSTR_UserSize
+ BSTR_UserMarshal
+ BSTR_UserUnmarshal
+ BSTR_UserFree
+
+ VARIANT_UserSize
+ VARIANT_UserMarshal
+ VARIANT_UserUnmarshal
+ VARIANT_UserFree
+
+ LPSAFEARRAY_UserSize
+ LPSAFEARRAY_UserMarshal
+ LPSAFEARRAY_UserUnmarshal
+ LPSAFEARRAY_UserFree
+
+ EXCEPINFO_UserSize
+ EXCEPINFO_UserMarshal
+ EXCEPINFO_UserUnmarshal
+ EXCEPINFO_UserFree
+
+ DISPPARAMS_UserSize
+ DISPPARAMS_UserMarshal
+ DISPPARAMS_UserUnmarshal
+ DISPPARAMS_UserFree
+
+; SMB_UserSize
+; SMB_UserMarshal
+; SMB_UserUnmarshal
+; SMB_UserFree
+
+
diff --git a/private/ole32/oleprx32/wdt/wdtp.h b/private/ole32/oleprx32/wdt/wdtp.h
new file mode 100644
index 000000000..5867d47d0
--- /dev/null
+++ b/private/ole32/oleprx32/wdt/wdtp.h
@@ -0,0 +1,118 @@
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Copyright <c> 1993 Microsoft Corporation
+
+Module Name :
+
+ ndrp.h
+
+Abtract :
+
+ Contains private definitions for Ndr files in this directory. This
+ file is included by all source files in this directory.
+
+Author :
+
+ David Kays dkays October 1993
+
+Revision History :
+
+--------------------------------------------------------------------*/
+
+#ifndef _WDTP_H_
+#define _WDTP_H_
+
+// Shortcut typedefs.
+
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned long ulong;
+typedef unsigned int uint;
+
+#ifndef TRUE
+#define TRUE (1)
+#define FALSE (0)
+
+typedef unsigned short BOOL;
+#endif
+
+#define NDR_ASSERT( Expr, S )
+
+#if 0
+
+#ifdef NEWNDR_INTERNAL
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <ntstatus.h>
+#include <ntrtl.h>
+#define NDR_ASSERT( Expr, S ) ASSERT( (Expr) || ! (S) )
+
+#else
+
+#include <ntrtl.h>
+#define NDR_ASSERT( Expr, S ) ASSERT( (Expr) || ! (S) )
+
+#endif
+
+#endif
+
+
+#define ALIGN( pStuff, cAlign ) \
+ pStuff = (unsigned char *)((ulong)((pStuff) + (cAlign)) & ~(cAlign))
+
+#define LENGTH_ALIGN( Length, cAlign ) \
+ Length = (((Length) + (cAlign)) & ~ (cAlign))
+
+#define PCHAR_LV_CAST *(char __RPC_FAR * __RPC_FAR *)&
+#define PSHORT_LV_CAST *(short __RPC_FAR * __RPC_FAR *)&
+#define PLONG_LV_CAST *(long __RPC_FAR * __RPC_FAR *)&
+#define PHYPER_LV_CAST *(hyper __RPC_FAR * __RPC_FAR *)&
+
+#define PUSHORT_LV_CAST *(unsigned short __RPC_FAR * __RPC_FAR *)&
+#define PULONG_LV_CAST *(unsigned long __RPC_FAR * __RPC_FAR *)&
+
+
+unsigned long __RPC_USER
+WdtpInterfacePointer_UserSize (
+ USER_MARSHAL_CB * pContext,
+ unsigned long Flags,
+ unsigned long Offset,
+ IUnknown * pIf,
+ const IID & IId );
+
+unsigned char __RPC_FAR * __RPC_USER
+WdtpInterfacePointer_UserMarshal (
+ USER_MARSHAL_CB * pContext,
+ unsigned long Flags,
+ unsigned char * pBuffer,
+ IUnknown * pIf,
+ const IID & IId );
+
+unsigned char __RPC_FAR * __RPC_USER
+WdtpInterfacePointer_UserUnmarshal (
+ USER_MARSHAL_CB * pContext,
+ unsigned char * pBuffer,
+ IUnknown ** ppIf,
+ const IID & IId );
+
+void __RPC_USER
+WdtpInterfacePointer_UserFree(
+ IUnknown * pIf );
+
+#define USER_MARSHAL_MARKER 0x72657355
+
+#define WdtpMemoryCopy(Destination, Source, Length) \
+ RtlCopyMemory(Destination, Source, Length)
+#define WdtpMemorySet(Destination, Source, Fill) \
+ RtlFillMemory(Destination, Length, Fill)
+#define WdtpZeroMemory(Destination, Length) \
+ RtlZeroMemory(Destination, Length)
+
+#define WdtpAllocate(p,size) \
+ ((USER_MARSHAL_CB *)p)->pStubMsg->pfnAllocate( size )
+#define WdtpFree(pf,ptr) \
+ ((USER_MARSHAL_CB *)pf)->pStubMsg->pfnFree( ptr )
+
+#endif // _WDTP_H_
diff --git a/private/ole32/olethunk/bin16/makefile b/private/ole32/olethunk/bin16/makefile
new file mode 100644
index 000000000..217a30ccc
--- /dev/null
+++ b/private/ole32/olethunk/bin16/makefile
@@ -0,0 +1,16 @@
+# OLETHUNK\bin16 makefile
+#
+# Copyright (c) 1994, Microsoft Corporation
+#
+# History:
+# 18-Jun-1994 Bob Day (bobday) Created.
+# 19-Oct-1994 KentCe Don't binplace all for Chicago.
+#
+
+all:
+ -binplace ole2disp.dll
+ -binplace ole2nls.dll
+ -binplace typelib.dll
+ -binplace stdole.tlb
+
+clean:
diff --git a/private/ole32/olethunk/bin16/ole2disp.map b/private/ole32/olethunk/bin16/ole2disp.map
new file mode 100644
index 000000000..edae9b68e
--- /dev/null
+++ b/private/ole32/olethunk/bin16/ole2disp.map
@@ -0,0 +1,3045 @@
+
+ OLE2DISP
+
+ Start Length Name Class
+ 0001:0000 03662H _TEXT CODE
+ 0002:0000 00472H _COMDATS CODE
+ 0003:0000 0932CH RT CODE
+ 0004:0000 06BF2H RPC CODE
+ 0005:0000 094D6H RPC2 CODE
+ 0006:0000 00642H BSTR CODE
+ 0007:0000 00000H RUNTIME CODE
+ 0007:0000 01A2CH STDIMPL CODE
+ 0008:0000 06780H UPS CODE
+ 0009:0000 00000H INVOKE_TEXT CODE
+ 0009:0000 00000H OLECONVA_TEXT CODE
+ 0009:0000 00054H WEP_TEXT CODE
+ 000A:0000 00010H NULL BEGDATA
+ 000A:0010 01922H _DATA DATA
+ 000A:1932 0000EH CDATA DATA
+ 000A:1940 00000H XIB DATA
+ 000A:1940 00004H XI DATA
+ 000A:1944 00000H XIE DATA
+ 000A:1944 00000H XIFB DATA
+ 000A:1944 00000H XIF DATA
+ 000A:1944 00000H XIFE DATA
+ 000A:1944 00000H XPB DATA
+ 000A:1944 00000H XP DATA
+ 000A:1944 00000H XPE DATA
+ 000A:1944 00000H XCB DATA
+ 000A:1944 00000H XC DATA
+ 000A:1944 00000H XCE DATA
+ 000A:1944 00000H XCFB DATA
+ 000A:1944 00000H XCFCRT DATA
+ 000A:1944 00000H XCF DATA
+ 000A:1944 00000H XCFE DATA
+ 000A:1944 00000H XIFCB DATA
+ 000A:1944 00000H XIFU DATA
+ 000A:1944 00000H XIFL DATA
+ 000A:1944 00000H XIFM DATA
+ 000A:1944 00000H XIFCE DATA
+ 000A:1944 00000H DBDATA DATA
+ 000A:1944 000E4H CONST CONST
+ 000A:1A28 00008H HDR MSG
+ 000A:1A30 0037CH MSG MSG
+ 000A:1DAC 00002H PAD MSG
+ 000A:1DAE 00001H EPAD MSG
+ 000A:1DB0 00024H _BSS BSS
+ 000A:1DD4 00000H XOB BSS
+ 000A:1DD4 00000H XO BSS
+ 000A:1DD4 00000H XOE BSS
+ 000A:1DD4 00000H XOFB BSS
+ 000A:1DD4 00000H XOF BSS
+ 000A:1DD4 00000H XOFE BSS
+ 000A:1DE0 0068AH c_common BSS
+
+ Origin Group
+ 000A:0 DGROUP
+
+ Address Export Alias
+
+ 0007:03B2 CREATEDISPTYPEINFO CREATEDISPTYPEINFO
+ 0001:08BC CREATEERRORINFO CREATEERRORINFO
+ 0007:15DC CREATESTDDISPATCH CREATESTDDISPATCH
+ 0003:00E8 DISPGETIDSOFNAMES DISPGETIDSOFNAMES
+ 0003:006C DISPGETPARAM DISPGETPARAM
+ 0003:011C DISPINVOKE DISPINVOKE
+ 0004:06D8 DLLCANUNLOADNOW DLLCANUNLOADNOW
+ 0004:0680 DLLGETCLASSOBJECT DLLGETCLASSOBJECT
+ 0007:0000 DOINVOKEMETHOD DOINVOKEMETHOD
+ 0003:0168 DOSDATETIMETOVARIANTTIME DOSDATETIMETOVARIANTTIME
+ 0001:0FF2 GETACTIVEOBJECT GETACTIVEOBJECT
+ 0001:083E GETERRORINFO GETERRORINFO
+ 0001:0E8E REGISTERACTIVEOBJECT REGISTERACTIVEOBJECT
+ 0001:0F7A REVOKEACTIVEOBJECT REVOKEACTIVEOBJECT
+ 0003:15DA SAFEARRAYACCESSDATA SAFEARRAYACCESSDATA
+ 0003:0620 SAFEARRAYALLOCDATA SAFEARRAYALLOCDATA
+ 0003:05B0 SAFEARRAYALLOCDESCRIPTOR SAFEARRAYALLOCDESCRIPTOR
+ 0003:1050 SAFEARRAYCOPY SAFEARRAYCOPY
+ 0003:0716 SAFEARRAYCREATE SAFEARRAYCREATE
+ 0003:0B8C SAFEARRAYDESTROY SAFEARRAYDESTROY
+ 0003:0A08 SAFEARRAYDESTROYDATA SAFEARRAYDESTROYDATA
+ 0003:0B4E SAFEARRAYDESTROYDESCRIPTOR SAFEARRAYDESTROYDESCRIPTOR
+ 0003:1474 SAFEARRAYGETDIM SAFEARRAYGETDIM
+ 0003:1708 SAFEARRAYGETELEMENT SAFEARRAYGETELEMENT
+ 0003:1488 SAFEARRAYGETELEMSIZE SAFEARRAYGETELEMSIZE
+ 0003:150A SAFEARRAYGETLBOUND SAFEARRAYGETLBOUND
+ 0003:149E SAFEARRAYGETUBOUND SAFEARRAYGETUBOUND
+ 0003:1566 SAFEARRAYLOCK SAFEARRAYLOCK
+ 0003:163E SAFEARRAYPTROFINDEX SAFEARRAYPTROFINDEX
+ 0003:1872 SAFEARRAYPUTELEMENT SAFEARRAYPUTELEMENT
+ 0003:0C00 SAFEARRAYREDIM SAFEARRAYREDIM
+ 0003:1626 SAFEARRAYUNACCESSDATA SAFEARRAYUNACCESSDATA
+ 0003:15A0 SAFEARRAYUNLOCK SAFEARRAYUNLOCK
+ 0001:07BC SETERRORINFO SETERRORINFO
+ 0006:0000 SYSALLOCSTRING SYSALLOCSTRING
+ 0006:003C SYSALLOCSTRINGLEN SYSALLOCSTRINGLEN
+ 0006:03CC SYSFREESTRING SYSFREESTRING
+ 0006:01BC SYSREALLOCSTRING SYSREALLOCSTRING
+ 0006:021C SYSREALLOCSTRINGLEN SYSREALLOCSTRINGLEN
+ 0006:051E SYSSTRINGLEN SYSSTRINGLEN
+ 0003:66C4 VARBOOLFROMCY VARBOOLFROMCY
+ 0003:66A0 VARBOOLFROMDATE VARBOOLFROMDATE
+ 0003:688E VARBOOLFROMDISP VARBOOLFROMDISP
+ 0003:65FC VARBOOLFROMI2 VARBOOLFROMI2
+ 0003:661A VARBOOLFROMI4 VARBOOLFROMI4
+ 0003:6640 VARBOOLFROMR4 VARBOOLFROMR4
+ 0003:6670 VARBOOLFROMR8 VARBOOLFROMR8
+ 0003:66F2 VARBOOLFROMSTR VARBOOLFROMSTR
+ 0003:65DE VARBOOLFROMUI1 VARBOOLFROMUI1
+ 0003:7F26 VARBSTRFROMBOOL VARBSTRFROMBOOL
+ 0003:8426 VARBSTRFROMCY VARBSTRFROMCY
+ 0003:4E44 VARBSTRFROMDATE VARBSTRFROMDATE
+ 0003:873C VARBSTRFROMDISP VARBSTRFROMDISP
+ 0003:7EFA VARBSTRFROMI2 VARBSTRFROMI2
+ 0003:7F80 VARBSTRFROMI4 VARBSTRFROMI4
+ 0003:82DE VARBSTRFROMR4 VARBSTRFROMR4
+ 0003:8384 VARBSTRFROMR8 VARBSTRFROMR8
+ 0003:7ED0 VARBSTRFROMUI1 VARBSTRFROMUI1
+ 0003:78D4 VARCYFROMBOOL VARCYFROMBOOL
+ 0003:78B0 VARCYFROMDATE VARCYFROMDATE
+ 0003:7D58 VARCYFROMDISP VARCYFROMDISP
+ 0003:7838 VARCYFROMI2 VARCYFROMI2
+ 0003:7854 VARCYFROMI4 VARCYFROMI4
+ 0003:7874 VARCYFROMR4 VARCYFROMR4
+ 0003:7892 VARCYFROMR8 VARCYFROMR8
+ 0003:78F0 VARCYFROMSTR VARCYFROMSTR
+ 0003:7818 VARCYFROMUI1 VARCYFROMUI1
+ 0003:765C VARDATEFROMBOOL VARDATEFROMBOOL
+ 0003:7738 VARDATEFROMCY VARDATEFROMCY
+ 0003:77CE VARDATEFROMDISP VARDATEFROMDISP
+ 0003:7614 VARDATEFROMI2 VARDATEFROMI2
+ 0003:7678 VARDATEFROMI4 VARDATEFROMI4
+ 0003:76B8 VARDATEFROMR4 VARDATEFROMR4
+ 0003:76F8 VARDATEFROMR8 VARDATEFROMR8
+ 0003:3DFC VARDATEFROMSTR VARDATEFROMSTR
+ 0003:75F6 VARDATEFROMUI1 VARDATEFROMUI1
+ 0003:6BDC VARI2FROMBOOL VARI2FROMBOOL
+ 0003:6B92 VARI2FROMCY VARI2FROMCY
+ 0003:6BB8 VARI2FROMDATE VARI2FROMDATE
+ 0003:6D72 VARI2FROMDISP VARI2FROMDISP
+ 0003:6AD4 VARI2FROMI4 VARI2FROMI4
+ 0003:6B18 VARI2FROMR4 VARI2FROMR4
+ 0003:6B40 VARI2FROMR8 VARI2FROMR8
+ 0003:6BF6 VARI2FROMSTR VARI2FROMSTR
+ 0003:6AB8 VARI2FROMUI1 VARI2FROMUI1
+ 0003:6DF0 VARI4FROMBOOL VARI4FROMBOOL
+ 0003:6E8A VARI4FROMCY VARI4FROMCY
+ 0003:6EB0 VARI4FROMDATE VARI4FROMDATE
+ 0003:70A4 VARI4FROMDISP VARI4FROMDISP
+ 0003:6DD0 VARI4FROMI2 VARI4FROMI2
+ 0003:6E0C VARI4FROMR4 VARI4FROMR4
+ 0003:6E34 VARI4FROMR8 VARI4FROMR8
+ 0003:6ED4 VARI4FROMSTR VARI4FROMSTR
+ 0003:6DB0 VARI4FROMUI1 VARI4FROMUI1
+ 0003:5626 VARIANTCHANGETYPE VARIANTCHANGETYPE
+ 0003:5650 VARIANTCHANGETYPEEX VARIANTCHANGETYPEEX
+ 0001:0A3C VARIANTCLEAR VARIANTCLEAR
+ 0001:0B38 VARIANTCOPY VARIANTCOPY
+ 0001:0C70 VARIANTCOPYIND VARIANTCOPYIND
+ 0001:0A26 VARIANTINIT VARIANTINIT
+ 0003:022C VARIANTTIMETODOSDATETIME VARIANTTIMETODOSDATETIME
+ 0003:71F6 VARR4FROMBOOL VARR4FROMBOOL
+ 0003:7282 VARR4FROMCY VARR4FROMCY
+ 0003:72A8 VARR4FROMDATE VARR4FROMDATE
+ 0003:731A VARR4FROMDISP VARR4FROMDISP
+ 0003:71D8 VARR4FROMI2 VARR4FROMI2
+ 0003:7212 VARR4FROMI4 VARR4FROMI4
+ 0003:7230 VARR4FROMR8 VARR4FROMR8
+ 0003:72CC VARR4FROMSTR VARR4FROMSTR
+ 0003:71A6 VARR4FROMUI1 VARR4FROMUI1
+ 0003:73B0 VARR8FROMBOOL VARR8FROMBOOL
+ 0003:7408 VARR8FROMCY VARR8FROMCY
+ 0003:742E VARR8FROMDATE VARR8FROMDATE
+ 0003:75AC VARR8FROMDISP VARR8FROMDISP
+ 0003:7392 VARR8FROMI2 VARR8FROMI2
+ 0003:73CC VARR8FROMI4 VARR8FROMI4
+ 0003:73EA VARR8FROMR4 VARR8FROMR4
+ 0003:7454 VARR8FROMSTR VARR8FROMSTR
+ 0003:7360 VARR8FROMUI1 VARR8FROMUI1
+ 0003:6A1C VARUI1FROMBOOL VARUI1FROMBOOL
+ 0003:69AA VARUI1FROMCY VARUI1FROMCY
+ 0003:69F8 VARUI1FROMDATE VARUI1FROMDATE
+ 0003:6A7A VARUI1FROMDISP VARUI1FROMDISP
+ 0003:68CC VARUI1FROMI2 VARUI1FROMI2
+ 0003:68FC VARUI1FROMI4 VARUI1FROMI4
+ 0003:6930 VARUI1FROMR4 VARUI1FROMR4
+ 0003:6958 VARUI1FROMR8 VARUI1FROMR8
+ 0003:6A36 VARUI1FROMSTR VARUI1FROMSTR
+ 0009:0000 WEP WEP
+ 0001:1124 _IID_ICreateErrorInfo _IID_ICreateErrorInfo
+ 0001:1104 _IID_IDispatch _IID_IDispatch
+ 0001:10F4 _IID_IEnumVARIANT _IID_IEnumVARIANT
+ 0001:1134 _IID_IErrorInfo _IID_IErrorInfo
+ 0001:1114 _IID_ISupportErrorInfo _IID_ISupportErrorInfo
+ 0001:28F0 ___ExportedStub ___ExportedStub
+
+ Address Publics by Name
+
+ 0001:2692 $i8_output
+ 0001:2A99 $i8_tpwr10
+ 0007:0408 ??0CDispTypeInfo@@REC@XZ
+ 0001:0388 ??0CErrorInfo@@REC@XZ
+ 0004:30B2 ??0CPDDispImpl@@REC@PEVCProxDisp@@@Z
+ 0004:2F06 ??0CPDProxImpl@@REC@PEVCProxDisp@@@Z
+ 0004:2D4E ??0CPDUnkImpl@@REC@PEVCProxDisp@@@Z
+ 0004:5308 ??0CPEVEnumVARIANTImpl@@REC@PEVCProxEnumVARIANT@@@Z
+ 0004:5186 ??0CPEVProxImpl@@REC@PEVCProxEnumVARIANT@@@Z
+ 0004:4FFE ??0CPEVUnkImpl@@REC@PEVCProxEnumVARIANT@@@Z
+ 0001:0070 ??0CProcessInfo@@REC@XZ
+ 0004:2C3A ??0CProxDisp@@BEC@PEUIUnknown@@AFUGUID@@@Z
+ 0004:4F48 ??0CProxEnumVARIANT@@BEC@PEUIUnknown@@@Z
+ 0005:8ED2 ??0CProxSupportErrorInfo@@BEC@PEUIUnknown@@@Z
+ 0005:73BC ??0CProxTypeComp@@BEC@PEUIUnknown@@@Z
+ 0005:0000 ??0CProxTypeInfo@@BEC@PEUIUnknown@@@Z
+ 0005:42CA ??0CProxTypeLib@@BEC@PEUIUnknown@@@Z
+ 0008:0236 ??0CProxUniv@@REC@PEUIUnknown@@@Z
+ 0005:9110 ??0CPSupErrProxImpl@@REC@PEVCProxSupportErrorInfo@@@Z
+ 0005:9292 ??0CPSupErrSupImpl@@REC@PEVCProxSupportErrorInfo@@@Z
+ 0005:8F88 ??0CPSupErrUnkImpl@@REC@PEVCProxSupportErrorInfo@@@Z
+ 0005:75E8 ??0CPTCompProxImpl@@REC@PEVCProxTypeComp@@@Z
+ 0005:7782 ??0CPTCompTypeCompImpl@@REC@PEVCProxTypeComp@@@Z
+ 0005:7472 ??0CPTCompUnkImpl@@REC@PEVCProxTypeComp@@@Z
+ 0005:023E ??0CPTIProxImpl@@REC@PEVCProxTypeInfo@@@Z
+ 0005:03C0 ??0CPTITypeInfoImpl@@REC@PEVCProxTypeInfo@@@Z
+ 0005:00B6 ??0CPTIUnkImpl@@REC@PEVCProxTypeInfo@@@Z
+ 0005:44F6 ??0CPTLibProxImpl@@REC@PEVCProxTypeLib@@@Z
+ 0005:4690 ??0CPTLibTypeLibImpl@@REC@PEVCProxTypeLib@@@Z
+ 0005:4380 ??0CPTLibUnkImpl@@REC@PEVCProxTypeLib@@@Z
+ 0007:160A ??0CStdDisp@@REC@XZ
+ 0007:1728 ??0CStdDispUnkImpl@@REC@PEVCStdDisp@@@Z
+ 0004:629A ??0CStreamOnBuffer@@REC@PEUIRpcChannelBuffer@@PEUtagRPCOLEMESSAG
+ 0004:3F7A ??0CStubDisp@@BEC@XZ
+ 0004:5A22 ??0CStubEnumVARIANT@@BEC@XZ
+ 0005:89E6 ??0CStubSupportErrorInfo@@BEC@XZ
+ 0005:8062 ??0CStubTypeComp@@BEC@XZ
+ 0005:2AD4 ??0CStubTypeInfo@@BEC@XZ
+ 0005:60C6 ??0CStubTypeLib@@BEC@XZ
+ 0008:12E2 ??0CStubUniv@@BEC@XZ
+ 0001:03FE ??1CErrorInfo@@REC@XZ
+ 0004:30DC ??1CPDDispImpl@@REC@XZ
+ 0004:2F30 ??1CPDProxImpl@@REC@XZ
+ 0004:2D78 ??1CPDUnkImpl@@REC@XZ
+ 0004:51B0 ??1CPEVProxImpl@@REC@XZ
+ 0001:00C2 ??1CProcessInfo@@REC@XZ
+ 0004:2CC6 ??1CProxDisp@@BEC@XZ
+ 0008:02CC ??1CProxUniv@@REC@XZ
+ 0005:913A ??1CPSupErrProxImpl@@REC@XZ
+ 0005:7612 ??1CPTCompProxImpl@@REC@XZ
+ 0005:0268 ??1CPTIProxImpl@@REC@XZ
+ 0005:4520 ??1CPTLibProxImpl@@REC@XZ
+ 0004:63A2 ??1CStreamOnBuffer@@REC@XZ
+ 0004:3FC4 ??1CStubDisp@@BEC@XZ
+ 0004:5A58 ??1CStubEnumVARIANT@@BEC@XZ
+ 0005:8A1C ??1CStubSupportErrorInfo@@BEC@XZ
+ 0005:80A6 ??1CStubTypeComp@@BEC@XZ
+ 0005:2B12 ??1CStubTypeInfo@@BEC@XZ
+ 0005:610A ??1CStubTypeLib@@BEC@XZ
+ 0008:1342 ??1CStubUniv@@BEC@XZ
+ 0001:091E ??2@ZAPAXI@Z
+ 0001:0924 ??2@ZAPEXI@Z
+ 0001:0922 ??3@ZAXPAX@Z
+ 0001:0988 ??3@ZAXPEX@Z
+ 0002:037C ??_7CDispTypeInfo@@6F@
+ 0002:01E0 ??_7CErrorInfo@@6FICreateErrorInfo@@@
+ 0002:01C0 ??_7CErrorInfo@@6FIErrorInfo@@@
+ 0002:0020 ??_7COleAutomationPSFactory@@6F@
+ 0002:0048 ??_7CPDDispImpl@@6F@
+ 0002:0034 ??_7CPDProxImpl@@6F@
+ 0002:0068 ??_7CPDUnkImpl@@6F@
+ 0002:009C ??_7CPEVEnumVARIANTImpl@@6F@
+ 0002:00C4 ??_7CPEVProxImpl@@6F@
+ 0002:00B8 ??_7CPEVUnkImpl@@6F@
+ 0002:02E4 ??_7CPriv@CProxUniv@@6F@
+ 0002:0200 ??_7CProcessInfo@@6F@
+ 0002:045E ??_7CPSupErrProxImpl@@6F@
+ 0002:0442 ??_7CPSupErrSupImpl@@6F@
+ 0002:0452 ??_7CPSupErrUnkImpl@@6F@
+ 0002:02A8 ??_7CPTCompProxImpl@@6F@
+ 0002:0288 ??_7CPTCompTypeCompImpl@@6F@
+ 0002:029C ??_7CPTCompUnkImpl@@6F@
+ 0002:0164 ??_7CPTIProxImpl@@6F@
+ 0002:0100 ??_7CPTITypeInfoImpl@@6F@
+ 0002:0158 ??_7CPTIUnkImpl@@6F@
+ 0002:024C ??_7CPTLibProxImpl@@6F@
+ 0002:020C ??_7CPTLibTypeLibImpl@@6F@
+ 0002:0240 ??_7CPTLibUnkImpl@@6F@
+ 0002:03FC ??_7CStdDisp@@6F@
+ 0002:03F0 ??_7CStdDispUnkImpl@@6F@
+ 0002:0334 ??_7CStreamOnBuffer@@6F@
+ 0002:0074 ??_7CStubDisp@@6F@
+ 0002:00D8 ??_7CStubEnumVARIANT@@6F@
+ 0002:041A ??_7CStubSupportErrorInfo@@6F@
+ 0002:02BC ??_7CStubTypeComp@@6F@
+ 0002:0178 ??_7CStubTypeInfo@@6F@
+ 0002:0260 ??_7CStubTypeLib@@6F@
+ 0002:030C ??_7CStubUniv@@6F@
+ 0002:03D4 ??_7IDispatch@@6F@
+ 0002:01A0 ??_7IErrorInfo@@6F@
+ 0002:0000 ??_7IPSFactoryBuffer@@6F@
+ 0002:02F8 ??_7IRpcProxyBuffer@@6F@
+ 0002:0014 ??_7IUnknown@@6F@
+ 0002:0418 ??_C@_01PIHH@?$CB?$AA@
+ 0007:04AA ?AddRef@CDispTypeInfo@@VEAKXZ
+ 0001:058C ?AddRef@CErrorInfo@@VEAKXZ
+ 0001:364A ?AddRef@CErrorInfo@@X3EAKXZ
+ 0004:00E6 ?AddRef@COleAutomationPSFactory@@VEAKXZ
+ 0004:3126 ?AddRef@CPDDispImpl@@VEAKXZ
+ 0004:2FB2 ?AddRef@CPDProxImpl@@VEAKXZ
+ 0004:2E82 ?AddRef@CPDUnkImpl@@VEAKXZ
+ 0004:5366 ?AddRef@CPEVEnumVARIANTImpl@@VEAKXZ
+ 0004:5220 ?AddRef@CPEVProxImpl@@VEAKXZ
+ 0004:50FA ?AddRef@CPEVUnkImpl@@VEAKXZ
+ 0008:093A ?AddRef@CPriv@CProxUniv@@VEAKXZ
+ 0001:01F4 ?AddRef@CProcessInfo@@VEAKXZ
+ 0005:91AA ?AddRef@CPSupErrProxImpl@@VEAKXZ
+ 0005:92F0 ?AddRef@CPSupErrSupImpl@@VEAKXZ
+ 0005:9084 ?AddRef@CPSupErrUnkImpl@@VEAKXZ
+ 0005:7682 ?AddRef@CPTCompProxImpl@@VEAKXZ
+ 0005:77E6 ?AddRef@CPTCompTypeCompImpl@@VEAKXZ
+ 0005:755C ?AddRef@CPTCompUnkImpl@@VEAKXZ
+ 0005:02D8 ?AddRef@CPTIProxImpl@@VEAKXZ
+ 0005:041E ?AddRef@CPTITypeInfoImpl@@VEAKXZ
+ 0005:01B2 ?AddRef@CPTIUnkImpl@@VEAKXZ
+ 0005:4590 ?AddRef@CPTLibProxImpl@@VEAKXZ
+ 0005:46F4 ?AddRef@CPTLibTypeLibImpl@@VEAKXZ
+ 0005:446A ?AddRef@CPTLibUnkImpl@@VEAKXZ
+ 0007:18B0 ?AddRef@CStdDisp@@VEAKXZ
+ 0007:17D6 ?AddRef@CStdDispUnkImpl@@VEAKXZ
+ 0004:645A ?AddRef@CStreamOnBuffer@@VEAKXZ
+ 0004:40F6 ?AddRef@CStubDisp@@VEAKXZ
+ 0004:5B5C ?AddRef@CStubEnumVARIANT@@VEAKXZ
+ 0005:8B20 ?AddRef@CStubSupportErrorInfo@@VEAKXZ
+ 0005:81AA ?AddRef@CStubTypeComp@@VEAKXZ
+ 0005:2C16 ?AddRef@CStubTypeInfo@@VEAKXZ
+ 0005:620E ?AddRef@CStubTypeLib@@VEAKXZ
+ 0008:146A ?AddRef@CStubUniv@@VEAKXZ
+ 0007:14C8 ?AddressOfMember@CDispTypeInfo@@VEAPEXJW4tagINVOKEKIND@@PEPEX@Z
+ 0005:1C7C ?AddressOfMember@CPTITypeInfoImpl@@VEAPEXJW4tagINVOKEKIND@@PEPEX
+ 0007:0F88 ?AllocInvokeArgs@CDispTypeInfo@@BECPEXIPEPEUtagINVOKEARGS@@@Z
+ 0005:7842 ?Bind@CPTCompTypeCompImpl@@VEAPEXPEDKGPEPEUITypeInfo@@PEW4tagDES
+ 0005:84B0 ?Bind@CStubTypeComp@@RECPEXXZ
+ 0005:7C84 ?BindType@CPTCompTypeCompImpl@@VEAPEXPEDKPEPEUITypeInfo@@PEPEUIT
+ 0005:87A8 ?BindType@CStubTypeComp@@RECPEXXZ
+ 0003:7FB0 ?BstrFromFloat@@ZAPEXNKKPEPEDH@Z
+ 0003:8B28 ?BstrFromVector@@ZCPEXPEUtagSAFEARRAY@@PEPED@Z
+ 0004:08D0 ?BstrRead@@ZAPEXPEUIStream@@PEPEDW4tagSYSKIND@@@Z
+ 0004:07E4 ?BstrWrite@@ZAPEXPEUIStream@@PEDW4tagSYSKIND@@@Z
+ 0008:0694 ?CacheFuncDescs@CProxUniv@@RECPEXPEUITypeInfo@@@Z
+ 0004:687C ?Call@CStreamOnBuffer@@VEAPEXXZ
+ 0008:0364 ?CanWeRemoteIt@@ZAPEXPEUITypeInfo@@PEGPEH@Z
+ 0004:58D6 ?Clone@CPEVEnumVARIANTImpl@@VEAPEXPEPEUIEnumVARIANT@@@Z
+ 0004:686A ?Clone@CStreamOnBuffer@@VEAPEXPEPEUIStream@@@Z
+ 0004:6810 ?Commit@CStreamOnBuffer@@VEAPEXK@Z
+ 0004:3006 ?Connect@CPDProxImpl@@VEAPEXPEUIRpcChannelBuffer@@@Z
+ 0004:5274 ?Connect@CPEVProxImpl@@VEAPEXPEUIRpcChannelBuffer@@@Z
+ 0008:09BA ?Connect@CPriv@CProxUniv@@VEAPEXPEUIRpcChannelBuffer@@@Z
+ 0005:91FE ?Connect@CPSupErrProxImpl@@VEAPEXPEUIRpcChannelBuffer@@@Z
+ 0005:76D6 ?Connect@CPTCompProxImpl@@VEAPEXPEUIRpcChannelBuffer@@@Z
+ 0005:032C ?Connect@CPTIProxImpl@@VEAPEXPEUIRpcChannelBuffer@@@Z
+ 0005:45E4 ?Connect@CPTLibProxImpl@@VEAPEXPEUIRpcChannelBuffer@@@Z
+ 0004:416E ?Connect@CStubDisp@@VEAPEXPEUIUnknown@@@Z
+ 0004:5BD4 ?Connect@CStubEnumVARIANT@@VEAPEXPEUIUnknown@@@Z
+ 0005:8B98 ?Connect@CStubSupportErrorInfo@@VEAPEXPEUIUnknown@@@Z
+ 0005:8222 ?Connect@CStubTypeComp@@VEAPEXPEUIUnknown@@@Z
+ 0005:2C8E ?Connect@CStubTypeInfo@@VEAPEXPEUIUnknown@@@Z
+ 0005:6286 ?Connect@CStubTypeLib@@VEAPEXPEUIUnknown@@@Z
+ 0008:14E2 ?Connect@CStubUniv@@VEAPEXPEUIUnknown@@@Z
+ 0004:67FE ?CopyTo@CStreamOnBuffer@@VEAPEXPEUIStream@@U_ULARGE_INTEGER@@PEU
+ 0004:4ED0 ?CountRefs@CStubDisp@@VEAKXZ
+ 0004:6222 ?CountRefs@CStubEnumVARIANT@@VEAKXZ
+ 0005:8E5A ?CountRefs@CStubSupportErrorInfo@@VEAKXZ
+ 0005:8468 ?CountRefs@CStubTypeComp@@VEAKXZ
+ 0005:2F6C ?CountRefs@CStubTypeInfo@@VEAKXZ
+ 0005:652E ?CountRefs@CStubTypeLib@@VEAKXZ
+ 0008:1828 ?CountRefs@CStubUniv@@VEAKXZ
+ 0007:0332 ?Create@CDispTypeInfo@@TAPEXW4tagTYPEKIND@@PEUtagINTERFACEDATA@@
+ 0001:0454 ?Create@CErrorInfo@@TAPEXPEPEV1@@Z
+ 0004:0000 ?Create@COleAutomationPSFactory@@TAPEUIPSFactoryBuffer@@XZ
+ 0004:2CFE ?Create@CProxDisp@@TAPEUIUnknown@@PEU2@AFUGUID@@@Z
+ 0004:4FB4 ?Create@CProxEnumVARIANT@@TAPEUIUnknown@@PEU2@@Z
+ 0005:8F3E ?Create@CProxSupportErrorInfo@@TAPEUIUnknown@@PEU2@@Z
+ 0005:7428 ?Create@CProxTypeComp@@TAPEUIUnknown@@PEU2@@Z
+ 0005:006C ?Create@CProxTypeInfo@@TAPEUIUnknown@@PEU2@@Z
+ 0005:4336 ?Create@CProxTypeLib@@TAPEUIUnknown@@PEU2@@Z
+ 0008:0418 ?Create@CProxUniv@@TAPEXPEUIUnknown@@AFUGUID@@PEPEU2@@Z
+ 0007:166A ?Create@CStdDisp@@TAPEXPEUIUnknown@@PEXPEUITypeInfo@@PEPEU2@@Z
+ 0004:3FE8 ?Create@CStubDisp@@TAPEXPEUIUnknown@@AFUGUID@@PEPEUIRpcStubBuffe
+ 0004:5A7C ?Create@CStubEnumVARIANT@@TAPEXPEUIUnknown@@PEPEUIRpcStubBuffer@
+ 0005:8A40 ?Create@CStubSupportErrorInfo@@TAPEXPEUIUnknown@@PEPEUIRpcStubBu
+ 0005:80CA ?Create@CStubTypeComp@@TAPEXPEUIUnknown@@PEPEUIRpcStubBuffer@@@Z
+ 0005:2B36 ?Create@CStubTypeInfo@@TAPEXPEUIUnknown@@PEPEUIRpcStubBuffer@@@Z
+ 0005:612E ?Create@CStubTypeLib@@TAPEXPEUIUnknown@@PEPEUIRpcStubBuffer@@@Z
+ 0008:1366 ?Create@CStubUniv@@TAPEXPEUIUnknown@@AFUGUID@@PEPEUIRpcStubBuffe
+ 0007:14DA ?CreateInstance@CDispTypeInfo@@VEAPEXPEUIUnknown@@AFUGUID@@PEPEX
+ 0005:1C8E ?CreateInstance@CPTITypeInfoImpl@@VEAPEXPEUIUnknown@@AFUGUID@@PE
+ 0005:3FC2 ?CreateInstance@CStubTypeInfo@@RECPEXXZ
+ 0004:014A ?CreateProxy@COleAutomationPSFactory@@VEAPEXPEUIUnknown@@AFUGUID
+ 0004:03BC ?CreateStub@COleAutomationPSFactory@@VEAPEXAFUGUID@@PEUIUnknown@
+ 0004:4F18 ?DebugServerQueryInterface@CStubDisp@@VEAPEXPEPEX@Z
+ 0004:626A ?DebugServerQueryInterface@CStubEnumVARIANT@@VEAPEXPEPEX@Z
+ 0005:8EA2 ?DebugServerQueryInterface@CStubSupportErrorInfo@@VEAPEXPEPEX@Z
+ 0005:89B6 ?DebugServerQueryInterface@CStubTypeComp@@VEAPEXPEPEX@Z
+ 0005:41E2 ?DebugServerQueryInterface@CStubTypeInfo@@VEAPEXPEPEX@Z
+ 0005:738C ?DebugServerQueryInterface@CStubTypeLib@@VEAPEXPEPEX@Z
+ 0008:1870 ?DebugServerQueryInterface@CStubUniv@@VEAPEXPEPEX@Z
+ 0004:4F3C ?DebugServerRelease@CStubDisp@@VEAXPEX@Z
+ 0004:628E ?DebugServerRelease@CStubEnumVARIANT@@VEAXPEX@Z
+ 0005:8EC6 ?DebugServerRelease@CStubSupportErrorInfo@@VEAXPEX@Z
+ 0005:89DA ?DebugServerRelease@CStubTypeComp@@VEAXPEX@Z
+ 0005:4206 ?DebugServerRelease@CStubTypeInfo@@VEAXPEX@Z
+ 0005:73B0 ?DebugServerRelease@CStubTypeLib@@VEAXPEX@Z
+ 0008:1894 ?DebugServerRelease@CStubUniv@@VEAXPEX@Z
+ 0004:3066 ?Disconnect@CPDProxImpl@@VEAXXZ
+ 0004:52BC ?Disconnect@CPEVProxImpl@@VEAXXZ
+ 0008:0A2E ?Disconnect@CPriv@CProxUniv@@VEAXXZ
+ 0005:9246 ?Disconnect@CPSupErrProxImpl@@VEAXXZ
+ 0005:7736 ?Disconnect@CPTCompProxImpl@@VEAXXZ
+ 0005:0374 ?Disconnect@CPTIProxImpl@@VEAXXZ
+ 0005:4644 ?Disconnect@CPTLibProxImpl@@VEAXXZ
+ 0004:41DE ?Disconnect@CStubDisp@@VEAXXZ
+ 0004:5C42 ?Disconnect@CStubEnumVARIANT@@VEAXXZ
+ 0005:8C06 ?Disconnect@CStubSupportErrorInfo@@VEAXXZ
+ 0005:8290 ?Disconnect@CStubTypeComp@@VEAXXZ
+ 0005:2CFC ?Disconnect@CStubTypeInfo@@VEAXXZ
+ 0005:62F4 ?Disconnect@CStubTypeLib@@VEAXXZ
+ 0008:1552 ?Disconnect@CStubUniv@@VEAXXZ
+ 0008:19C8 ?DispatchMethod@CStubUniv@@RECPEXH@Z
+ 0005:4750 ?DoGetTypeInfoCount@CPTLibTypeLibImpl@@RECPEXPEI@Z
+ 0005:4212 ?DoLoadTypeLib@@ZCPEXPFDPEPEUITypeLib@@@Z
+ 0005:2034 ?DoReleaseDanglingTypeDesc@@ZCXPEUtagTYPEDESC@@@Z
+ 0005:2118 ?DoReleaseFuncDesc@@ZCXPEUtagFUNCDESC@@@Z
+ 0005:21C8 ?DoReleaseVarDesc@@ZCXPEUtagVARDESC@@@Z
+ 0004:1406 ?ExcepinfoRead@@ZAPEXPEUIStream@@PEUtagEXCEPINFO@@W4tagSYSKIND@@
+ 0004:14DC ?ExcepinfoWrite@@ZAPEXPEUIStream@@PEUtagEXCEPINFO@@W4tagSYSKIND@
+ 0005:57F8 ?FindName@CPTLibTypeLibImpl@@VEAPEXPEDKPEPEUITypeInfo@@PEJPEG@Z
+ 0005:6F8A ?FindName@CStubTypeLib@@RECPEXXZ
+ 0008:2360 ?FIsLCID@@ZAHPED@Z
+ 0005:2820 ?FuncdescRead@@ZCPEXPEUIStream@@PEUtagFUNCDESC@@W4tagSYSKIND@@@Z
+ 0005:278E ?FuncdescWrite@@ZCPEXPEUIStream@@PEUtagFUNCDESC@@W4tagSYSKIND@@@
+ 0007:14FE ?GetContainingTypeLib@CDispTypeInfo@@VEAPEXPEPEUITypeLib@@PEI@Z
+ 0005:1E70 ?GetContainingTypeLib@CPTITypeInfoImpl@@VEAPEXPEPEUITypeLib@@PEI
+ 0005:40BA ?GetContainingTypeLib@CStubTypeInfo@@RECPEXXZ
+ 0001:0650 ?GetDescription@CErrorInfo@@VEAPEXPEPED@Z
+ 0007:143C ?GetDllEntry@CDispTypeInfo@@VEAPEXJW4tagINVOKEKIND@@PEPED1PEG@Z
+ 0005:1774 ?GetDllEntry@CPTITypeInfoImpl@@VEAPEXJW4tagINVOKEKIND@@PEPED1PEG
+ 0005:3C40 ?GetDllEntry@CStubTypeInfo@@RECPEXXZ
+ 0007:13B0 ?GetDocumentation@CDispTypeInfo@@VEAPEXJPEPED0PEK0@Z
+ 0005:13CA ?GetDocumentation@CPTITypeInfoImpl@@VEAPEXJPEPED0PEK0@Z
+ 0005:50E6 ?GetDocumentation@CPTLibTypeLibImpl@@VEAPEXHPEPED0PEK0@Z
+ 0005:39C0 ?GetDocumentation@CStubTypeInfo@@RECPEXXZ
+ 0005:6AAC ?GetDocumentation@CStubTypeLib@@RECPEXXZ
+ 0007:066A ?GetFuncDesc@CDispTypeInfo@@VEAPEXIPEPEUtagFUNCDESC@@@Z
+ 0005:07FE ?GetFuncDesc@CPTITypeInfoImpl@@VEAPEXIPEPEUtagFUNCDESC@@@Z
+ 0005:31DC ?GetFuncDesc@CStubTypeInfo@@RECPEXXZ
+ 0001:0604 ?GetGUID@CErrorInfo@@VEAPEXPEUGUID@@@Z
+ 0001:0694 ?GetHelpContext@CErrorInfo@@VEAPEXPEK@Z
+ 0001:0672 ?GetHelpFile@CErrorInfo@@VEAPEXPEPED@Z
+ 0007:0A14 ?GetIDsOfNames@CDispTypeInfo@@VEAPEXPEPEDIPEJ@Z
+ 0004:3A24 ?GetIDsOfNames@CPDDispImpl@@VEAPEXAFUGUID@@PEPEDIKPEJ@Z
+ 0005:13A6 ?GetIDsOfNames@CPTITypeInfoImpl@@VEAPEXPEPEDIPEJ@Z
+ 0007:1978 ?GetIDsOfNames@CStdDisp@@VEAPEXAFUGUID@@PEPEDIKPEJ@Z
+ 0005:39B6 ?GetIDsOfNames@CStubTypeInfo@@RECPEXXZ
+ 0007:0A02 ?GetImplTypeFlags@CDispTypeInfo@@VEAPEXIPEH@Z
+ 0005:11E4 ?GetImplTypeFlags@CPTITypeInfoImpl@@VEAPEXIPEH@Z
+ 0005:38B6 ?GetImplTypeFlags@CStubTypeInfo@@RECPEXXZ
+ 0007:109C ?GetInvokeArgs@CDispTypeInfo@@BECPEXPEUtagMETHODDATA@@GPEUtagDIS
+ 0005:4DC6 ?GetLibAttr@CPTLibTypeLibImpl@@VEAPEXPEPEUtagTLIBATTR@@@Z
+ 0005:6908 ?GetLibAttr@CStubTypeLib@@RECPEXXZ
+ 0007:14EC ?GetMops@CDispTypeInfo@@VEAPEXJPEPED@Z
+ 0005:1E44 ?GetMops@CPTITypeInfoImpl@@VEAPEXJPEPED@Z
+ 0007:086C ?GetNames@CDispTypeInfo@@VEAPEXJPEPEDIPEI@Z
+ 0005:0CA2 ?GetNames@CPTITypeInfoImpl@@VEAPEXJPEPEDIPEI@Z
+ 0005:3508 ?GetNames@CStubTypeInfo@@RECPEXXZ
+ 0008:0000 ?GetPrimaryInterface@@ZCPEXPEUITypeInfo@@PEPEU1@@Z
+ 0007:144E ?GetRefTypeInfo@CDispTypeInfo@@VEAPEXKPEPEUITypeInfo@@@Z
+ 0005:1AD4 ?GetRefTypeInfo@CPTITypeInfoImpl@@VEAPEXKPEPEUITypeInfo@@@Z
+ 0005:3EBC ?GetRefTypeInfo@CStubTypeInfo@@RECPEXXZ
+ 0007:09D6 ?GetRefTypeOfImplType@CDispTypeInfo@@VEAPEXIPEK@Z
+ 0005:1014 ?GetRefTypeOfImplType@CPTITypeInfoImpl@@VEAPEXIPEK@Z
+ 0005:37C0 ?GetRefTypeOfImplType@CStubTypeInfo@@RECPEXXZ
+ 0001:062E ?GetSource@CErrorInfo@@VEAPEXPEPED@Z
+ 0005:2238 ?GetStream@CPTITypeInfoImpl@@RECPEXHKPEPEUIStream@@@Z
+ 0007:050E ?GetTypeAttr@CDispTypeInfo@@VEAPEXPEPEUtagTYPEATTR@@@Z
+ 0005:047A ?GetTypeAttr@CPTITypeInfoImpl@@VEAPEXPEPEUtagTYPEATTR@@@Z
+ 0005:2FB4 ?GetTypeAttr@CStubTypeInfo@@RECPEXXZ
+ 0007:060A ?GetTypeComp@CDispTypeInfo@@VEAPEXPEPEUITypeComp@@@Z
+ 0005:068A ?GetTypeComp@CPTITypeInfoImpl@@VEAPEXPEPEUITypeComp@@@Z
+ 0005:4F72 ?GetTypeComp@CPTLibTypeLibImpl@@VEAPEXPEPEUITypeComp@@@Z
+ 0005:310C ?GetTypeComp@CStubTypeInfo@@RECPEXXZ
+ 0005:69E2 ?GetTypeComp@CStubTypeLib@@RECPEXXZ
+ 0004:360C ?GetTypeInfo@CPDDispImpl@@VEAPEXIKPEPEUITypeInfo@@@Z
+ 0005:48A6 ?GetTypeInfo@CPTLibTypeLibImpl@@VEAPEXIPEPEUITypeInfo@@@Z
+ 0007:192E ?GetTypeInfo@CStdDisp@@VEAPEXIKPEPEUITypeInfo@@@Z
+ 0005:65E8 ?GetTypeInfo@CStubTypeLib@@RECPEXXZ
+ 0004:3406 ?GetTypeInfoCount@CPDDispImpl@@VEAPEXPEI@Z
+ 0005:4870 ?GetTypeInfoCount@CPTLibTypeLibImpl@@VEAIXZ
+ 0007:1904 ?GetTypeInfoCount@CStdDisp@@VEAPEXPEI@Z
+ 0005:6576 ?GetTypeInfoCount@CStubTypeLib@@RECPEXXZ
+ 0005:4C1C ?GetTypeInfoOfGuid@CPTLibTypeLibImpl@@VEAPEXAFUGUID@@PEPEUITypeI
+ 0005:6800 ?GetTypeInfoOfGuid@CStubTypeLib@@RECPEXXZ
+ 0008:23CA ?GetTypeInfoOfIID@@ZAPEXAFUGUID@@PEPEUITypeInfo@@@Z
+ 0005:4A5A ?GetTypeInfoType@CPTLibTypeLibImpl@@VEAPEXIPEW4tagTYPEKIND@@@Z
+ 0005:66F4 ?GetTypeInfoType@CStubTypeLib@@RECPEXXZ
+ 0007:085A ?GetVarDesc@CDispTypeInfo@@VEAPEXIPEPEUtagVARDESC@@@Z
+ 0005:0A50 ?GetVarDesc@CPTITypeInfoImpl@@VEAPEXIPEPEUtagVARDESC@@@Z
+ 0005:3370 ?GetVarDesc@CStubTypeInfo@@RECPEXXZ
+ 000A:008E ?g_cbFtype@@3QEEE
+ 000A:007C ?g_cbVtSizes@@3QEEE
+ 000A:10FA ?g_cfnDisp@@3JE
+ 000A:10F6 ?g_cfnUnk@@3JE
+ 0003:0306 ?hAccessElement@@ZCPIXPEUtagSAFEARRAY@@K@Z
+ 0003:03E8 ?hAccessElement@@ZCPIXPIXGK@Z
+ 0003:04BC ?hmemset@@ZCXPIXHK@Z
+ 0003:02BA ?hSizeToAlloc@@ZCKPEUtagSAFEARRAY@@K@Z
+ 0005:934C ?InterfaceSupportsErrorInfo@CPSupErrSupImpl@@VEAPEXAFUGUID@@@Z
+ 0007:0CDA ?Invoke@CDispTypeInfo@@VEAPEXPEXJGPEUtagDISPPARAMS@@PEUtagVARIAN
+ 0004:3F22 ?Invoke@CPDDispImpl@@VEAPEXJAFUGUID@@KGPEUtagDISPPARAMS@@PEUtagV
+ 0005:13B8 ?Invoke@CPTITypeInfoImpl@@VEAPEXPEXJGPEUtagDISPPARAMS@@PEUtagVAR
+ 0007:19C2 ?Invoke@CStdDisp@@VEAPEXJAFUGUID@@KGPEUtagDISPPARAMS@@PEUtagVARI
+ 0004:4D42 ?Invoke@CStubDisp@@VEAPEXPEUtagRPCOLEMESSAGE@@PEUIRpcChannelBuff
+ 0004:60AA ?Invoke@CStubEnumVARIANT@@VEAPEXPEUtagRPCOLEMESSAGE@@PEUIRpcChan
+ 0005:8D2C ?Invoke@CStubSupportErrorInfo@@VEAPEXPEUtagRPCOLEMESSAGE@@PEUIRp
+ 0005:82FE ?Invoke@CStubTypeComp@@VEAPEXPEUtagRPCOLEMESSAGE@@PEUIRpcChannel
+ 0005:2D6A ?Invoke@CStubTypeInfo@@VEAPEXPEUtagRPCOLEMESSAGE@@PEUIRpcChannel
+ 0005:6362 ?Invoke@CStubTypeLib@@VEAPEXPEUtagRPCOLEMESSAGE@@PEUIRpcChannelB
+ 0008:15C0 ?Invoke@CStubUniv@@VEAPEXPEUtagRPCOLEMESSAGE@@PEUIRpcChannelBuff
+ 0004:05E8 ?IsAutomationCLSID@@ZAHAFUGUID@@@Z
+ 0004:4E80 ?IsIIDSupported@CStubDisp@@VEAPEUIRpcStubBuffer@@AFUGUID@@@Z
+ 0004:61D2 ?IsIIDSupported@CStubEnumVARIANT@@VEAPEUIRpcStubBuffer@@AFUGUID@
+ 0005:8E0A ?IsIIDSupported@CStubSupportErrorInfo@@VEAPEUIRpcStubBuffer@@AFU
+ 0005:8418 ?IsIIDSupported@CStubTypeComp@@VEAPEUIRpcStubBuffer@@AFUGUID@@@Z
+ 0005:2F1C ?IsIIDSupported@CStubTypeInfo@@VEAPEUIRpcStubBuffer@@AFUGUID@@@Z
+ 0005:64DE ?IsIIDSupported@CStubTypeLib@@VEAPEUIRpcStubBuffer@@AFUGUID@@@Z
+ 0008:17D6 ?IsIIDSupported@CStubUniv@@VEAPEUIRpcStubBuffer@@AFUGUID@@@Z
+ 0001:0E52 ?IsLegalVartype@@ZCPEXG@Z
+ 0005:5550 ?IsName@CPTLibTypeLibImpl@@VEAPEXPEDKPEH@Z
+ 0005:6E00 ?IsName@CStubTypeLib@@RECPEXXZ
+ 0003:7794 ?IsValidDate@@ZCPEXN@Z
+ 000A:192A ?ll0@?1??Rewind@@ZAPEXPEUIStream@@@Z@4U_LARGE_INTEGER@@B
+ 0004:6834 ?LockRegion@CStreamOnBuffer@@VEAPEXU_ULARGE_INTEGER@@0K@Z
+ 0005:223E ?LrpcCall@CPTITypeInfoImpl@@RECPEXPEUIStream@@PEPEX@Z
+ 0004:15D0 ?MarshalErrorInfo@@ZAPEXPEUIStream@@W4tagSYSKIND@@@Z
+ 0005:41BE ?MarshalResult@CStubTypeInfo@@RECPEXXZ
+ 0004:53C2 ?Next@CPEVEnumVARIANTImpl@@VEAPEXKPEUtagVARIANT@@PEK@Z
+ 0007:1568 ?PmdataOfDispid@CDispTypeInfo@@BECPEXJGPEPEUtagMETHODDATA@@@Z
+ 0004:3642 ?ProxyGetIDsOfNames@@ZAPEXPEUIRpcChannelBuffer@@W4tagSYSKIND@@AF
+ 0004:3438 ?ProxyGetTypeInfo@@ZAPEXPEUIRpcChannelBuffer@@W4tagSYSKIND@@IKPE
+ 0004:32A4 ?ProxyGetTypeInfoCount@@ZAPEXPEUIRpcChannelBuffer@@W4tagSYSKIND@
+ 0004:3A6A ?ProxyInvoke@@ZAPEXPEUIRpcChannelBuffer@@W4tagSYSKIND@@JAFUGUID@
+ 0004:06E8 ?ProxyStubCLSIDOfInterface@@ZAPEXAFUGUID@@PEU1@@Z
+ 0008:0A82 ?PSInit@CProxUniv@@RECPEXXZ
+ 0008:18A0 ?PSInit@CStubUniv@@RECPEXXZ
+ 000A:1450 ?pstrInd@@3QEDE
+ 000A:144C ?pstrInf@@3QEDE
+ 000A:1454 ?pstrNan@@3QEDE
+ 0007:0436 ?QueryInterface@CDispTypeInfo@@VEAPEXAFUGUID@@PEPEX@Z
+ 0001:04A6 ?QueryInterface@CErrorInfo@@VEAPEXAFUGUID@@PEPEX@Z
+ 0001:363E ?QueryInterface@CErrorInfo@@X3EAPEXAFUGUID@@PEPEX@Z
+ 0004:0078 ?QueryInterface@COleAutomationPSFactory@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:30F2 ?QueryInterface@CPDDispImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:2F82 ?QueryInterface@CPDProxImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:2D8E ?QueryInterface@CPDUnkImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:5332 ?QueryInterface@CPEVEnumVARIANTImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:51F0 ?QueryInterface@CPEVProxImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:5028 ?QueryInterface@CPEVUnkImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0008:087A ?QueryInterface@CPriv@CProxUniv@@VEAPEXAFUGUID@@PEPEX@Z
+ 0001:0186 ?QueryInterface@CProcessInfo@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:917A ?QueryInterface@CPSupErrProxImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:92BC ?QueryInterface@CPSupErrSupImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:8FB2 ?QueryInterface@CPSupErrUnkImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:7652 ?QueryInterface@CPTCompProxImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:77B2 ?QueryInterface@CPTCompTypeCompImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:749C ?QueryInterface@CPTCompUnkImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:02A8 ?QueryInterface@CPTIProxImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:03EA ?QueryInterface@CPTITypeInfoImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:00E0 ?QueryInterface@CPTIUnkImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:4560 ?QueryInterface@CPTLibProxImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:46C0 ?QueryInterface@CPTLibTypeLibImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:43AA ?QueryInterface@CPTLibUnkImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0007:1880 ?QueryInterface@CStdDisp@@VEAPEXAFUGUID@@PEPEX@Z
+ 0007:1752 ?QueryInterface@CStdDispUnkImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:63E4 ?QueryInterface@CStreamOnBuffer@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:408A ?QueryInterface@CStubDisp@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:5AF0 ?QueryInterface@CStubEnumVARIANT@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:8AB4 ?QueryInterface@CStubSupportErrorInfo@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:813E ?QueryInterface@CStubTypeComp@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:2BAA ?QueryInterface@CStubTypeInfo@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:61A2 ?QueryInterface@CStubTypeLib@@VEAPEXAFUGUID@@PEPEX@Z
+ 0008:13FE ?QueryInterface@CStubUniv@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:64F4 ?Read@CStreamOnBuffer@@VEAPEXPIXKPEK@Z
+ 0005:5DE8 ?ReadLibAttr@@ZCPEXPEUIStream@@PEUtagTLIBATTR@@@Z
+ 0007:04CC ?Release@CDispTypeInfo@@VEAKXZ
+ 0001:05AE ?Release@CErrorInfo@@VEAKXZ
+ 0001:3656 ?Release@CErrorInfo@@X3EAKXZ
+ 0004:0108 ?Release@COleAutomationPSFactory@@VEAKXZ
+ 0004:3154 ?Release@CPDDispImpl@@VEAKXZ
+ 0004:2FDC ?Release@CPDProxImpl@@VEAKXZ
+ 0004:2EA8 ?Release@CPDUnkImpl@@VEAKXZ
+ 0004:5394 ?Release@CPEVEnumVARIANTImpl@@VEAKXZ
+ 0004:524A ?Release@CPEVProxImpl@@VEAKXZ
+ 0004:5120 ?Release@CPEVUnkImpl@@VEAKXZ
+ 0008:095C ?Release@CPriv@CProxUniv@@VEAKXZ
+ 0001:0216 ?Release@CProcessInfo@@VEAKXZ
+ 0005:91D4 ?Release@CPSupErrProxImpl@@VEAKXZ
+ 0005:931E ?Release@CPSupErrSupImpl@@VEAKXZ
+ 0005:90AA ?Release@CPSupErrUnkImpl@@VEAKXZ
+ 0005:76AC ?Release@CPTCompProxImpl@@VEAKXZ
+ 0005:7814 ?Release@CPTCompTypeCompImpl@@VEAKXZ
+ 0005:7582 ?Release@CPTCompUnkImpl@@VEAKXZ
+ 0005:0302 ?Release@CPTIProxImpl@@VEAKXZ
+ 0005:044C ?Release@CPTITypeInfoImpl@@VEAKXZ
+ 0005:01D8 ?Release@CPTIUnkImpl@@VEAKXZ
+ 0005:45BA ?Release@CPTLibProxImpl@@VEAKXZ
+ 0005:4722 ?Release@CPTLibTypeLibImpl@@VEAKXZ
+ 0005:4490 ?Release@CPTLibUnkImpl@@VEAKXZ
+ 0007:18DA ?Release@CStdDisp@@VEAKXZ
+ 0007:17FC ?Release@CStdDispUnkImpl@@VEAKXZ
+ 0004:647C ?Release@CStreamOnBuffer@@VEAKXZ
+ 0004:4118 ?Release@CStubDisp@@VEAKXZ
+ 0004:5B7E ?Release@CStubEnumVARIANT@@VEAKXZ
+ 0005:8B42 ?Release@CStubSupportErrorInfo@@VEAKXZ
+ 0005:81CC ?Release@CStubTypeComp@@VEAKXZ
+ 0005:2C38 ?Release@CStubTypeInfo@@VEAKXZ
+ 0005:6230 ?Release@CStubTypeLib@@VEAKXZ
+ 0008:148C ?Release@CStubUniv@@VEAKXZ
+ 0007:152A ?ReleaseFuncDesc@CDispTypeInfo@@VEAXPEUtagFUNCDESC@@@Z
+ 0005:21A8 ?ReleaseFuncDesc@CPTITypeInfoImpl@@VEAXPEUtagFUNCDESC@@@Z
+ 0007:1304 ?ReleaseInvokeArgs@CDispTypeInfo@@BECXPEUtagINVOKEARGS@@@Z
+ 0003:0858 ?ReleaseResources@@ZCXPIXKGG@Z
+ 0005:5C6A ?ReleaseTLibAttr@CPTLibTypeLibImpl@@VEAXPEUtagTLIBATTR@@@Z
+ 0007:1510 ?ReleaseTypeAttr@CDispTypeInfo@@VEAXPEUtagTYPEATTR@@@Z
+ 0005:20D0 ?ReleaseTypeAttr@CPTITypeInfoImpl@@VEAXPEUtagTYPEATTR@@@Z
+ 0007:155C ?ReleaseVarDesc@CDispTypeInfo@@VEAXPEUtagVARDESC@@@Z
+ 0005:2218 ?ReleaseVarDesc@CPTITypeInfoImpl@@VEAXPEUtagVARDESC@@@Z
+ 0004:57C2 ?Reset@CPEVEnumVARIANTImpl@@VEAPEXXZ
+ 0004:6A04 ?ResetBuffer@CStreamOnBuffer@@VEAPEXXZ
+ 0004:6AC8 ?ResizeBuffer@CStreamOnBuffer@@VEAPEXK@Z
+ 0004:6822 ?Revert@CStreamOnBuffer@@VEAPEXXZ
+ 0004:69B8 ?RewindBuffer@CStreamOnBuffer@@VEAPEXXZ
+ 0003:1A0E ?SafeArraySize@@ZCKPEUtagSAFEARRAY@@@Z
+ 0004:6706 ?Seek@CStreamOnBuffer@@VEAPEXU_LARGE_INTEGER@@KPEU_ULARGE_INTEGE
+ 0001:0720 ?SetDescription@CErrorInfo@@VEAPEXPED@Z
+ 0001:06B8 ?SetGUID@CErrorInfo@@VEAPEXAFUGUID@@@Z
+ 0001:079C ?SetHelpContext@CErrorInfo@@VEAPEXK@Z
+ 0001:075E ?SetHelpFile@CErrorInfo@@VEAPEXPED@Z
+ 0004:67EC ?SetSize@CStreamOnBuffer@@VEAPEXU_ULARGE_INTEGER@@@Z
+ 0001:06E2 ?SetSource@CErrorInfo@@VEAPEXPED@Z
+ 0004:567A ?Skip@CPEVEnumVARIANTImpl@@VEAPEXK@Z
+ 0004:6858 ?Stat@CStreamOnBuffer@@VEAPEXPEUtagSTATSTG@@K@Z
+ 0004:290E ?StructRead@@ZAPEXPEUIStream@@PEUtagFIELDDESC@@PEXW4tagSYSKIND@@
+ 0004:2772 ?StructWrite@@ZAPEXPEUIStream@@PEUtagFIELDDESC@@PEXW4tagSYSKIND@
+ 0004:447C ?StubGetIDsOfNames@@ZAPEXPEUIDispatch@@PEUIStream@@@Z
+ 0004:4354 ?StubGetTypeInfo@@ZAPEXPEUIDispatch@@PEUIStream@@@Z
+ 0004:42B2 ?StubGetTypeInfoCount@@ZAPEXPEUIDispatch@@PEUIStream@@@Z
+ 0004:4778 ?StubInvoke@@ZAPEXPEUIDispatch@@PEUIStream@@@Z
+ 0004:3182 ?SysKind@CPDDispImpl@@VEAPEXXZ
+ 0005:7F08 ?SysKind@CPTCompTypeCompImpl@@RECPEXXZ
+ 0005:5C8E ?SysKind@CPTLibTypeLibImpl@@RECPEXXZ
+ 0005:8906 ?SysKind@CStubTypeComp@@RECPEXXZ
+ 0005:72DC ?SysKind@CStubTypeLib@@RECPEXXZ
+ 0008:22BE ?SzLibIdOfIID@@ZAPEXAFUGUID@@PEDJ@Z
+ 0005:2706 ?TypeattrRead@@ZCPEXPEUIStream@@PEUtagTYPEATTR@@W4tagSYSKIND@@@Z
+ 0005:2696 ?TypeattrWrite@@ZCPEXPEUIStream@@PEUtagTYPEATTR@@W4tagSYSKIND@@@
+ 0005:2478 ?TypedescWrite@@ZAPEXPEUIStream@@PEUtagTYPEDESC@@W4tagSYSKIND@@@
+ 000A:1458 ?ulPower10@@3QEKE
+ 0008:3418 ?UM100@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3436 ?UM101@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3454 ?UM102@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3472 ?UM103@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3490 ?UM104@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:34AE ?UM105@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:34CC ?UM106@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:34EA ?UM107@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3508 ?UM108@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3526 ?UM109@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:298C ?UM10@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3544 ?UM110@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3562 ?UM111@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3580 ?UM112@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:359E ?UM113@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:35BC ?UM114@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:35DA ?UM115@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:35F8 ?UM116@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3616 ?UM117@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3634 ?UM118@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3652 ?UM119@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:29AA ?UM11@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3670 ?UM120@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:368E ?UM121@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:36AC ?UM122@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:36CA ?UM123@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:36E8 ?UM124@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3706 ?UM125@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3724 ?UM126@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3742 ?UM127@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3760 ?UM128@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3780 ?UM129@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:29C8 ?UM12@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:37A0 ?UM130@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:37C0 ?UM131@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:37E0 ?UM132@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3800 ?UM133@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3820 ?UM134@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3840 ?UM135@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3860 ?UM136@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3880 ?UM137@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:38A0 ?UM138@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:38C0 ?UM139@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:29E6 ?UM13@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:38E0 ?UM140@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3900 ?UM141@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3920 ?UM142@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3940 ?UM143@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3960 ?UM144@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3980 ?UM145@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:39A0 ?UM146@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:39C0 ?UM147@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:39E0 ?UM148@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3A00 ?UM149@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2A04 ?UM14@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3A20 ?UM150@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3A40 ?UM151@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3A60 ?UM152@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3A80 ?UM153@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3AA0 ?UM154@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3AC0 ?UM155@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3AE0 ?UM156@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3B00 ?UM157@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3B20 ?UM158@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3B40 ?UM159@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2A22 ?UM15@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3B60 ?UM160@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3B80 ?UM161@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3BA0 ?UM162@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3BC0 ?UM163@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3BE0 ?UM164@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3C00 ?UM165@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3C20 ?UM166@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3C40 ?UM167@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3C60 ?UM168@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3C80 ?UM169@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2A40 ?UM16@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3CA0 ?UM170@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3CC0 ?UM171@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3CE0 ?UM172@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3D00 ?UM173@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3D20 ?UM174@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3D40 ?UM175@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3D60 ?UM176@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3D80 ?UM177@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3DA0 ?UM178@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3DC0 ?UM179@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2A5E ?UM17@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3DE0 ?UM180@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3E00 ?UM181@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3E20 ?UM182@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3E40 ?UM183@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3E60 ?UM184@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3E80 ?UM185@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3EA0 ?UM186@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3EC0 ?UM187@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3EE0 ?UM188@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3F00 ?UM189@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2A7C ?UM18@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3F20 ?UM190@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3F40 ?UM191@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3F60 ?UM192@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3F80 ?UM193@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3FA0 ?UM194@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3FC0 ?UM195@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3FE0 ?UM196@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4000 ?UM197@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4020 ?UM198@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4040 ?UM199@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2A9A ?UM19@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4060 ?UM200@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4080 ?UM201@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:40A0 ?UM202@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:40C0 ?UM203@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:40E0 ?UM204@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4100 ?UM205@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4120 ?UM206@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4140 ?UM207@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4160 ?UM208@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4180 ?UM209@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2AB8 ?UM20@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:41A0 ?UM210@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:41C0 ?UM211@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:41E0 ?UM212@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4200 ?UM213@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4220 ?UM214@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4240 ?UM215@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4260 ?UM216@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4280 ?UM217@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:42A0 ?UM218@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:42C0 ?UM219@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2AD6 ?UM21@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:42E0 ?UM220@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4300 ?UM221@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4320 ?UM222@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4340 ?UM223@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4360 ?UM224@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4380 ?UM225@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:43A0 ?UM226@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:43C0 ?UM227@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:43E0 ?UM228@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4400 ?UM229@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2AF4 ?UM22@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4420 ?UM230@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4440 ?UM231@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4460 ?UM232@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4480 ?UM233@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:44A0 ?UM234@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:44C0 ?UM235@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:44E0 ?UM236@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4500 ?UM237@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4520 ?UM238@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4540 ?UM239@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2B12 ?UM23@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4560 ?UM240@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4580 ?UM241@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:45A0 ?UM242@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:45C0 ?UM243@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:45E0 ?UM244@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4600 ?UM245@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4620 ?UM246@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4640 ?UM247@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4660 ?UM248@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4680 ?UM249@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2B30 ?UM24@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:46A0 ?UM250@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:46C0 ?UM251@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:46E0 ?UM252@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4700 ?UM253@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4720 ?UM254@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4740 ?UM255@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4760 ?UM256@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4780 ?UM257@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:47A0 ?UM258@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:47C0 ?UM259@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2B4E ?UM25@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:47E0 ?UM260@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4800 ?UM261@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4820 ?UM262@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4840 ?UM263@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4860 ?UM264@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4880 ?UM265@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:48A0 ?UM266@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:48C0 ?UM267@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:48E0 ?UM268@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4900 ?UM269@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2B6C ?UM26@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4920 ?UM270@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4940 ?UM271@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4960 ?UM272@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4980 ?UM273@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:49A0 ?UM274@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:49C0 ?UM275@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:49E0 ?UM276@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4A00 ?UM277@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4A20 ?UM278@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4A40 ?UM279@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2B8A ?UM27@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4A60 ?UM280@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4A80 ?UM281@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4AA0 ?UM282@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4AC0 ?UM283@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4AE0 ?UM284@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4B00 ?UM285@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4B20 ?UM286@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4B40 ?UM287@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4B60 ?UM288@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4B80 ?UM289@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2BA8 ?UM28@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4BA0 ?UM290@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4BC0 ?UM291@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4BE0 ?UM292@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4C00 ?UM293@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4C20 ?UM294@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4C40 ?UM295@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4C60 ?UM296@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4C80 ?UM297@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4CA0 ?UM298@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4CC0 ?UM299@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2BC6 ?UM29@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4CE0 ?UM300@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4D00 ?UM301@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4D20 ?UM302@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4D40 ?UM303@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4D60 ?UM304@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4D80 ?UM305@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4DA0 ?UM306@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4DC0 ?UM307@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4DE0 ?UM308@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4E00 ?UM309@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2BE4 ?UM30@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4E20 ?UM310@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4E40 ?UM311@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4E60 ?UM312@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4E80 ?UM313@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4EA0 ?UM314@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4EC0 ?UM315@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4EE0 ?UM316@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4F00 ?UM317@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4F20 ?UM318@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4F40 ?UM319@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2C02 ?UM31@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4F60 ?UM320@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4F80 ?UM321@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4FA0 ?UM322@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4FC0 ?UM323@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4FE0 ?UM324@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5000 ?UM325@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5020 ?UM326@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5040 ?UM327@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5060 ?UM328@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5080 ?UM329@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2C20 ?UM32@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:50A0 ?UM330@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:50C0 ?UM331@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:50E0 ?UM332@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5100 ?UM333@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5120 ?UM334@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5140 ?UM335@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5160 ?UM336@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5180 ?UM337@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:51A0 ?UM338@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:51C0 ?UM339@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2C3E ?UM33@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:51E0 ?UM340@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5200 ?UM341@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5220 ?UM342@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5240 ?UM343@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5260 ?UM344@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5280 ?UM345@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:52A0 ?UM346@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:52C0 ?UM347@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:52E0 ?UM348@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5300 ?UM349@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2C5C ?UM34@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5320 ?UM350@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5340 ?UM351@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5360 ?UM352@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5380 ?UM353@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:53A0 ?UM354@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:53C0 ?UM355@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:53E0 ?UM356@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5400 ?UM357@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5420 ?UM358@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5440 ?UM359@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2C7A ?UM35@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5460 ?UM360@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5480 ?UM361@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:54A0 ?UM362@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:54C0 ?UM363@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:54E0 ?UM364@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5500 ?UM365@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5520 ?UM366@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5540 ?UM367@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5560 ?UM368@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5580 ?UM369@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2C98 ?UM36@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:55A0 ?UM370@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:55C0 ?UM371@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:55E0 ?UM372@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5600 ?UM373@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5620 ?UM374@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5640 ?UM375@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5660 ?UM376@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5680 ?UM377@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:56A0 ?UM378@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:56C0 ?UM379@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2CB6 ?UM37@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:56E0 ?UM380@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5700 ?UM381@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5720 ?UM382@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5740 ?UM383@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5760 ?UM384@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5780 ?UM385@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:57A0 ?UM386@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:57C0 ?UM387@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:57E0 ?UM388@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5800 ?UM389@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2CD4 ?UM38@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5820 ?UM390@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5840 ?UM391@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5860 ?UM392@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5880 ?UM393@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:58A0 ?UM394@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:58C0 ?UM395@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:58E0 ?UM396@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5900 ?UM397@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5920 ?UM398@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5940 ?UM399@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2CF2 ?UM39@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:28BA ?UM3@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5960 ?UM400@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5980 ?UM401@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:59A0 ?UM402@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:59C0 ?UM403@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:59E0 ?UM404@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5A00 ?UM405@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5A20 ?UM406@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5A40 ?UM407@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5A60 ?UM408@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5A80 ?UM409@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2D10 ?UM40@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5AA0 ?UM410@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5AC0 ?UM411@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5AE0 ?UM412@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5B00 ?UM413@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5B20 ?UM414@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5B40 ?UM415@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5B60 ?UM416@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5B80 ?UM417@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5BA0 ?UM418@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5BC0 ?UM419@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2D2E ?UM41@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5BE0 ?UM420@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5C00 ?UM421@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5C20 ?UM422@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5C40 ?UM423@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5C60 ?UM424@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5C80 ?UM425@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5CA0 ?UM426@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5CC0 ?UM427@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5CE0 ?UM428@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5D00 ?UM429@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2D4C ?UM42@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5D20 ?UM430@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5D40 ?UM431@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5D60 ?UM432@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5D80 ?UM433@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5DA0 ?UM434@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5DC0 ?UM435@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5DE0 ?UM436@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5E00 ?UM437@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5E20 ?UM438@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5E40 ?UM439@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2D6A ?UM43@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5E60 ?UM440@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5E80 ?UM441@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5EA0 ?UM442@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5EC0 ?UM443@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5EE0 ?UM444@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5F00 ?UM445@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5F20 ?UM446@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5F40 ?UM447@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5F60 ?UM448@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5F80 ?UM449@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2D88 ?UM44@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5FA0 ?UM450@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5FC0 ?UM451@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5FE0 ?UM452@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6000 ?UM453@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6020 ?UM454@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6040 ?UM455@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6060 ?UM456@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6080 ?UM457@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:60A0 ?UM458@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:60C0 ?UM459@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2DA6 ?UM45@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:60E0 ?UM460@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6100 ?UM461@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6120 ?UM462@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6140 ?UM463@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6160 ?UM464@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6180 ?UM465@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:61A0 ?UM466@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:61C0 ?UM467@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:61E0 ?UM468@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6200 ?UM469@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2DC4 ?UM46@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6220 ?UM470@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6240 ?UM471@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6260 ?UM472@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6280 ?UM473@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:62A0 ?UM474@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:62C0 ?UM475@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:62E0 ?UM476@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6300 ?UM477@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6320 ?UM478@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6340 ?UM479@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2DE2 ?UM47@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6360 ?UM480@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6380 ?UM481@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:63A0 ?UM482@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:63C0 ?UM483@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:63E0 ?UM484@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6400 ?UM485@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6420 ?UM486@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6440 ?UM487@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6460 ?UM488@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6480 ?UM489@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2E00 ?UM48@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:64A0 ?UM490@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:64C0 ?UM491@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:64E0 ?UM492@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6500 ?UM493@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6520 ?UM494@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6540 ?UM495@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6560 ?UM496@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6580 ?UM497@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:65A0 ?UM498@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:65C0 ?UM499@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2E1E ?UM49@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:28D8 ?UM4@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:65E0 ?UM500@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6600 ?UM501@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6620 ?UM502@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6640 ?UM503@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6660 ?UM504@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6680 ?UM505@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:66A0 ?UM506@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:66C0 ?UM507@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:66E0 ?UM508@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6700 ?UM509@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2E3C ?UM50@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6720 ?UM510@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6740 ?UM511@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6760 ?UM512@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2E5A ?UM51@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2E78 ?UM52@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2E96 ?UM53@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2EB4 ?UM54@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2ED2 ?UM55@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2EF0 ?UM56@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2F0E ?UM57@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2F2C ?UM58@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2F4A ?UM59@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:28F6 ?UM5@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2F68 ?UM60@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2F86 ?UM61@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2FA4 ?UM62@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2FC2 ?UM63@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2FE0 ?UM64@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2FFE ?UM65@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:301C ?UM66@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:303A ?UM67@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3058 ?UM68@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3076 ?UM69@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2914 ?UM6@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3094 ?UM70@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:30B2 ?UM71@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:30D0 ?UM72@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:30EE ?UM73@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:310C ?UM74@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:312A ?UM75@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3148 ?UM76@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3166 ?UM77@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3184 ?UM78@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:31A2 ?UM79@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2932 ?UM7@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:31C0 ?UM80@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:31DE ?UM81@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:31FC ?UM82@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:321A ?UM83@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3238 ?UM84@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3256 ?UM85@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3274 ?UM86@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3292 ?UM87@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:32B0 ?UM88@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:32CE ?UM89@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2950 ?UM8@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:32EC ?UM90@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:330A ?UM91@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3328 ?UM92@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3346 ?UM93@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3364 ?UM94@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3382 ?UM95@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:33A0 ?UM96@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:33BE ?UM97@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:33DC ?UM98@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:33FA ?UM99@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:296E ?UM9@@ZAPEXPEVCProxUniv@@ZZ
+ 0004:6846 ?UnlockRegion@CStreamOnBuffer@@VEAPEXU_ULARGE_INTEGER@@0K@Z
+ 0004:180E ?UnmarshalErrorInfo@@ZAPEXPEUIStream@@W4tagSYSKIND@@@Z
+ 0005:29D6 ?VardescRead@@ZCPEXPEUIStream@@PEUtagVARDESC@@W4tagSYSKIND@@@Z
+ 0005:2938 ?VardescWrite@@ZCPEXPEUIStream@@PEUtagVARDESC@@W4tagSYSKIND@@@Z
+ 0004:0C98 ?VariantRead@@ZAPEXPEUIStream@@PEUtagVARIANT@@1W4tagSYSKIND@@@Z
+ 0004:0F74 ?VariantReadType@@ZAPEXPEUIStream@@PEUtagVARIANT@@W4tagSYSKIND@@
+ 0004:09FA ?VariantWrite@@ZAPEXPEUIStream@@PEUtagVARIANT@@W4tagSYSKIND@@@Z
+ 0008:1EA6 ?VarVtOfIface@@ZAPEXPEUITypeInfo@@PEUtagTYPEATTR@@PEGPEUGUID@@@Z
+ 0008:20C2 ?VarVtOfTypeDesc@@ZAPEXPEUITypeInfo@@PEUtagTYPEDESC@@PEGPEUGUID@
+ 0008:1EFE ?VarVtOfUDT@@ZAPEXPEUITypeInfo@@PEUtagTYPEDESC@@PEGPEUGUID@@@Z
+ 0003:8A8C ?VectorFromBstr@@ZCPEXPEDPEPEUtagSAFEARRAY@@@Z
+ 0004:65AA ?Write@CStreamOnBuffer@@VEAPEXPJXKPEK@Z
+ 0005:5F50 ?WriteLibAttr@@ZCPEXPEUIStream@@PEUtagTLIBATTR@@@Z
+ 0000:0000 Imp COGETMALLOC (COMPOBJ.4)
+ 0000:0000 Imp COGETSTATE (COMPOBJ.COGETSTATE)
+ 0000:0000 Imp COMARSHALHRESULT (COMPOBJ.32)
+ 0000:0000 Imp COMARSHALINTERFACE (COMPOBJ.8)
+ 0000:0000 Imp COMPARESTRINGA (OLE2NLS.8)
+ 0003:532B CONVDECTOFLOAT
+ 0003:52E5 CONVFLOATTOASCII
+ 0000:0000 Imp COSETSTATE (COMPOBJ.COSETSTATE)
+ 0000:0000 Imp COUNMARSHALHRESULT (COMPOBJ.33)
+ 0000:0000 Imp COUNMARSHALINTERFACE (COMPOBJ.9)
+ 0007:03B2 CREATEDISPTYPEINFO
+ 0001:08BC CREATEERRORINFO
+ 0000:0000 Imp CREATEITEMMONIKER (OLE2.27)
+ 0007:15DC CREATESTDDISPATCH
+ 0001:0A0E DETECTFBSTPIMPLEMENTED
+ 0003:62BE DISPALLOC
+ 0003:6372 DISPFREE
+ 0003:00E8 DISPGETIDSOFNAMES
+ 0003:006C DISPGETPARAM
+ 0003:011C DISPINVOKE
+ 0004:2AEE DISPMARSHALINTERFACE
+ 0004:2BB4 DISPUNMARSHALINTERFACE
+ 0003:21F4 DISP_GCVT
+ 0003:2186 DISP_ITOA
+ 0003:21BE DISP_LTOA
+ 0004:06D8 DLLCANUNLOADNOW
+ 0004:0680 DLLGETCLASSOBJECT
+ 0003:527A DOFBSTP
+ 0007:0000 DOINVOKEMETHOD
+ 0000:0000 Imp DOS3CALL (KERNEL.102)
+ 0003:0168 DOSDATETIMETOVARIANTTIME
+ 0003:5060 ERRCYFROMI2
+ 0003:5087 ERRCYFROMI4
+ 0003:50C8 ERRCYFROMR4
+ 0003:510C ERRCYFROMR8
+ 0003:5150 ERRI2FROMCY
+ 0003:5194 ERRI4FROMCY
+ 0003:5238 ERRMULTCYI4
+ 0003:1B42 ERRPACKDATE
+ 0003:51D8 ERRR4FROMCY
+ 0003:5208 ERRR8FROMCY
+ 0006:05BA ERRSTRINGCOPY
+ 0006:0608 ERRSTRINGCOPYNONULL
+ 0006:0544 ERRSYSALLOCSTRING
+ 0006:058A ERRSYSALLOCSTRINGLEN
+ 0003:1DBE ERRUNPACKDATE
+ 0000:0000 Imp FATALAPPEXIT (KERNEL.137)
+ 0000:0000 Imp FATALEXIT (KERNEL.1)
+ 0000:FE32 Abs FIARQQ
+ 0000:0E32 Abs FICRQQ
+ 0000:5C32 Abs FIDRQQ
+ 0000:1632 Abs FIERQQ
+ 0000:0632 Abs FISRQQ
+ 0000:A23D Abs FIWRQQ
+ 0000:4000 Abs FJARQQ
+ 0000:C000 Abs FJCRQQ
+ 0000:8000 Abs FJSRQQ
+ 0000:0000 Imp FREELIBRARY (KERNEL.96)
+ 0001:0FF2 GETACTIVEOBJECT
+ 0003:20D2 GETCURRENTYEAR
+ 0000:0000 Imp GETDOSENVIRONMENT (KERNEL.131)
+ 0001:083E GETERRORINFO
+ 0000:0000 Imp GETLOCALEINFOA (OLE2NLS.5)
+ 0000:0000 Imp GETMODULEUSAGE (KERNEL.48)
+ 0000:0000 Imp GETPROCADDRESS (KERNEL.50)
+ 0000:0000 Imp GETPROFILEINT (KERNEL.57)
+ 0000:0000 Imp GETRUNNINGOBJECTTABLE (OLE2.30)
+ 0000:0000 Imp GETSTRINGTYPEA (OLE2NLS.7)
+ 0000:0000 Imp GETUSERDEFAULTLCID (OLE2NLS.1)
+ 0000:0000 Imp GETVERSION (KERNEL.3)
+ 0000:0000 Imp GETWINFLAGS (KERNEL.132)
+ 0000:0000 Imp GLOBALALLOC (KERNEL.15)
+ 0000:0000 Imp GLOBALFREE (KERNEL.17)
+ 0000:0000 Imp GLOBALLOCK (KERNEL.18)
+ 0000:0000 Imp GLOBALREALLOC (KERNEL.16)
+ 0000:0000 Imp GLOBALSIZE (KERNEL.20)
+ 0000:0000 Imp GLOBALUNLOCK (KERNEL.19)
+ 0000:0000 Imp HMEMCPY (KERNEL.348)
+ 0003:0000 INDEXOFPARAM
+ 0000:0000 Imp INITTASK (KERNEL.91)
+ 0003:4F5E INTOFSTRING
+ 0003:8CC2 ISCHINA
+ 0003:8BA2 ISDBCS
+ 0000:0000 Imp ISEQUALGUID (COMPOBJ.18)
+ 0003:8C08 ISJAPAN
+ 0003:8C46 ISKOREA
+ 0003:8C84 ISTAIWAN
+ 0000:0000 Imp LCMAPSTRINGA (OLE2NLS.6)
+ 0001:0010 LIBMAIN
+ 0000:0000 Imp LOADLIBRARY (KERNEL.95)
+ 0000:0000 Imp LOCALINIT (KERNEL.4)
+ 0000:0000 Imp LOCKSEGMENT (KERNEL.23)
+ 0003:7DA2 MAPHALFWIDTH
+ 0001:09F0 NLSINFOCHANGEDHANDLER
+ 0003:8D00 PARSESTRTONUM
+ 0008:0C4C PROXYMETHOD
+ 0000:0000 Imp REGCLOSEKEY (SHELL.3)
+ 0000:0000 Imp REGENUMKEY (SHELL.7)
+ 0001:0E8E REGISTERACTIVEOBJECT
+ 0000:0000 Imp REGISTERNLSINFOCHANGED (OLE2NLS.9)
+ 0000:0000 Imp REGOPENKEY (SHELL.1)
+ 0000:0000 Imp REGQUERYVALUE (SHELL.6)
+ 0001:0F7A REVOKEACTIVEOBJECT
+ 000A:0004 rsrvptrs
+ 0003:15DA SAFEARRAYACCESSDATA
+ 0003:0620 SAFEARRAYALLOCDATA
+ 0003:05B0 SAFEARRAYALLOCDESCRIPTOR
+ 0003:1050 SAFEARRAYCOPY
+ 0003:0716 SAFEARRAYCREATE
+ 0003:0B8C SAFEARRAYDESTROY
+ 0003:0A08 SAFEARRAYDESTROYDATA
+ 0003:0B4E SAFEARRAYDESTROYDESCRIPTOR
+ 0003:1474 SAFEARRAYGETDIM
+ 0003:1708 SAFEARRAYGETELEMENT
+ 0003:1488 SAFEARRAYGETELEMSIZE
+ 0003:150A SAFEARRAYGETLBOUND
+ 0003:149E SAFEARRAYGETUBOUND
+ 0003:1566 SAFEARRAYLOCK
+ 0003:163E SAFEARRAYPTROFINDEX
+ 0003:1872 SAFEARRAYPUTELEMENT
+ 0003:0C00 SAFEARRAYREDIM
+ 0003:1626 SAFEARRAYUNACCESSDATA
+ 0003:15A0 SAFEARRAYUNLOCK
+ 0003:2408 SAFEGETLOCALEINFO
+ 0003:24B0 SAFEGETLOCALESHORT
+ 0001:07BC SETERRORINFO
+ 0000:0000 Imp SETERRORMODE (KERNEL.107)
+ 0000:0000 Imp STRINGFROMGUID2 (COMPOBJ.76)
+ 0006:0000 SYSALLOCSTRING
+ 0006:003C SYSALLOCSTRINGLEN
+ 0006:03CC SYSFREESTRING
+ 0006:01BC SYSREALLOCSTRING
+ 0006:021C SYSREALLOCSTRINGLEN
+ 0006:051E SYSSTRINGLEN
+ 0003:66C4 VARBOOLFROMCY
+ 0003:66A0 VARBOOLFROMDATE
+ 0003:688E VARBOOLFROMDISP
+ 0003:65FC VARBOOLFROMI2
+ 0003:661A VARBOOLFROMI4
+ 0003:6640 VARBOOLFROMR4
+ 0003:6670 VARBOOLFROMR8
+ 0003:66F2 VARBOOLFROMSTR
+ 0003:65DE VARBOOLFROMUI1
+ 0003:7F26 VARBSTRFROMBOOL
+ 0003:8426 VARBSTRFROMCY
+ 0003:4E44 VARBSTRFROMDATE
+ 0003:873C VARBSTRFROMDISP
+ 0003:7EFA VARBSTRFROMI2
+ 0003:7F80 VARBSTRFROMI4
+ 0003:82DE VARBSTRFROMR4
+ 0003:8384 VARBSTRFROMR8
+ 0003:7ED0 VARBSTRFROMUI1
+ 0003:78D4 VARCYFROMBOOL
+ 0003:78B0 VARCYFROMDATE
+ 0003:7D58 VARCYFROMDISP
+ 0003:7838 VARCYFROMI2
+ 0003:7854 VARCYFROMI4
+ 0003:7874 VARCYFROMR4
+ 0003:7892 VARCYFROMR8
+ 0003:78F0 VARCYFROMSTR
+ 0003:7818 VARCYFROMUI1
+ 0003:765C VARDATEFROMBOOL
+ 0003:7738 VARDATEFROMCY
+ 0003:77CE VARDATEFROMDISP
+ 0003:7614 VARDATEFROMI2
+ 0003:7678 VARDATEFROMI4
+ 0003:76B8 VARDATEFROMR4
+ 0003:76F8 VARDATEFROMR8
+ 0003:3DFC VARDATEFROMSTR
+ 0003:75F6 VARDATEFROMUI1
+ 0003:6BDC VARI2FROMBOOL
+ 0003:6B92 VARI2FROMCY
+ 0003:6BB8 VARI2FROMDATE
+ 0003:6D72 VARI2FROMDISP
+ 0003:6AD4 VARI2FROMI4
+ 0003:6B18 VARI2FROMR4
+ 0003:6B40 VARI2FROMR8
+ 0003:6BF6 VARI2FROMSTR
+ 0003:6AB8 VARI2FROMUI1
+ 0003:6DF0 VARI4FROMBOOL
+ 0003:6E8A VARI4FROMCY
+ 0003:6EB0 VARI4FROMDATE
+ 0003:70A4 VARI4FROMDISP
+ 0003:6DD0 VARI4FROMI2
+ 0003:6E0C VARI4FROMR4
+ 0003:6E34 VARI4FROMR8
+ 0003:6ED4 VARI4FROMSTR
+ 0003:6DB0 VARI4FROMUI1
+ 0003:5626 VARIANTCHANGETYPE
+ 0003:5650 VARIANTCHANGETYPEEX
+ 0001:0A3C VARIANTCLEAR
+ 0001:0B38 VARIANTCOPY
+ 0001:0C70 VARIANTCOPYIND
+ 0001:0A26 VARIANTINIT
+ 0003:022C VARIANTTIMETODOSDATETIME
+ 0003:71F6 VARR4FROMBOOL
+ 0003:7282 VARR4FROMCY
+ 0003:72A8 VARR4FROMDATE
+ 0003:731A VARR4FROMDISP
+ 0003:71D8 VARR4FROMI2
+ 0003:7212 VARR4FROMI4
+ 0003:7230 VARR4FROMR8
+ 0003:72CC VARR4FROMSTR
+ 0003:71A6 VARR4FROMUI1
+ 0003:73B0 VARR8FROMBOOL
+ 0003:7408 VARR8FROMCY
+ 0003:742E VARR8FROMDATE
+ 0003:75AC VARR8FROMDISP
+ 0003:7392 VARR8FROMI2
+ 0003:73CC VARR8FROMI4
+ 0003:73EA VARR8FROMR4
+ 0003:7454 VARR8FROMSTR
+ 0003:7360 VARR8FROMUI1
+ 0003:6A1C VARUI1FROMBOOL
+ 0003:69AA VARUI1FROMCY
+ 0003:69F8 VARUI1FROMDATE
+ 0003:6A7A VARUI1FROMDISP
+ 0003:68CC VARUI1FROMI2
+ 0003:68FC VARUI1FROMI4
+ 0003:6930 VARUI1FROMR4
+ 0003:6958 VARUI1FROMR8
+ 0003:6A36 VARUI1FROMSTR
+ 0009:0000 WEP
+ 0003:20E6 XTOA
+ 000A:1709 _aseghi
+ 000A:1707 _aseglo
+ 0001:249A _atof
+ 0001:146A _atoi
+ 0001:1214 _CLSID_PSAutomation
+ 0001:1254 _CLSID_PSDispatch
+ 0001:1244 _CLSID_PSEnumVARIANT
+ 0001:11F4 _CLSID_PSSupportErrorInfo
+ 0001:1204 _CLSID_PSTypeComp
+ 0001:1234 _CLSID_PSTypeInfo
+ 0001:1224 _CLSID_PSTypeLib
+ 000A:1120 _dblSecPerDay
+ 000A:1DB0 _edata
+ 000A:246A _end
+ 000A:1834 _errno
+ 0001:19E5 _floor
+ 0001:11E4 _GUID_NULL
+ 000A:1DFA _g_DateInfo
+ 000A:1334 _g_dpsNext
+ 000A:1102 _g_E_INVALIDARG
+ 000A:1DB0 _g_fbstpImplemented
+ 000A:1426 _g_fDay31th
+ 000A:0010 _g_hinstDLL
+ 000A:1DE0 _g_NumInfo
+ 000A:1DB2 _g_pinfoProcess
+ 000A:14DA _g_rgfdescElemdesc
+ 000A:160A _g_rgfdescFuncdesc
+ 000A:14AA _g_rgfdescIdldesc
+ 000A:150A _g_rgfdescTypeattr
+ 000A:16AA _g_rgfdescVardesc
+ 000A:08F2 _g_rgpfnDisp
+ 000A:00EE _g_rgpfnUnk
+ 000A:118C _g_rgszPolishMonth2
+ 000A:120E _g_rgszRussianMonth2
+ 000A:10FE _g_S_OK
+ 0001:1124 _IID_ICreateErrorInfo
+ 0001:10B4 _IID_ICreateTypeInfo
+ 0001:10A4 _IID_ICreateTypeLib
+ 0001:1104 _IID_IDispatch
+ 0001:10F4 _IID_IEnumVARIANT
+ 0001:1134 _IID_IErrorInfo
+ 0001:1194 _IID_IPSFactory
+ 0001:11A4 _IID_IPSFactoryBuffer
+ 0001:1154 _IID_IRpcChannelBuffer
+ 0001:11B4 _IID_IRpcProxy
+ 0001:1174 _IID_IRpcProxyBuffer
+ 0001:11C4 _IID_IRpcStub
+ 0001:1164 _IID_IRpcStubBuffer
+ 0001:1184 _IID_IStream
+ 0001:1114 _IID_ISupportErrorInfo
+ 0001:10C4 _IID_ITypeComp
+ 0001:10E4 _IID_ITypeInfo
+ 0001:10D4 _IID_ITypeLib
+ 0001:11D4 _IID_IUnknown
+ 0001:1144 _IID_StdOle
+ 0007:01DB _InvokeCdecl
+ 0007:0080 _InvokePascal
+ 0003:2216 _IsCharType
+ 0003:2252 _IsPrefix
+ 0001:1A4A _modf
+ 000A:1106 _mpmmdd
+ 0003:428C _SetUDSfromYMD
+ 000A:16FA _STKHQQ
+ 0001:2904 _strlen
+ 0001:149A _strtol
+ 0001:148E _strtoul
+ 0005:2244 _TypedescRead
+ 0005:2662 _TypedescReadOrWrite
+ 0008:276C _UnivAddRef
+ 0008:2820 _UnivGetIDsOfNames
+ 0008:27EE _UnivGetTypeInfo
+ 0008:27C0 _UnivGetTypeInfoCount
+ 0008:2864 _UnivInvoke
+ 0008:273C _UnivQueryInterface
+ 0008:2796 _UnivRelease
+ 0001:02C4 _UpdateProcessInfo
+ 000A:1DB6 _uProcessID
+ 0001:003E _WEP
+ 0000:9876 Abs __acrtmsg
+ 0000:9876 Abs __acrtused
+ 0000:D6D6 Abs __aDBdoswp
+ 000A:186A __adbgmsg
+ 0000:D6D6 Abs __aDBused
+ 0001:146E __aFahdiff
+ 0001:19B0 __aFCIfloor
+ 0001:15D2 __aFFalmul
+ 0001:15F4 __aFFalrem
+ 0001:1616 __aFFauldiv
+ 0001:15D2 __aFFaulmul
+ 0001:1A0C __aFftol
+ 0001:1638 __aFldiv
+ 0001:16D2 __aFlmul
+ 0001:1704 __aFlrem
+ 0001:17A4 __aFuldiv
+ 0001:16D2 __aFulmul
+ 0001:1804 __aFulrem
+ 0000:0000 Imp __AHINCR (KERNEL.114)
+ 0000:0000 Imp __AHSHIFT (KERNEL.113)
+ 000A:1826 __aintdiv
+ 000A:190C __amblksiz
+ 0001:1C84 __amsg_exit
+ 000A:188E __asizeC
+ 000A:188F __asizeD
+ 0001:12A8 __astart
+ 0001:1CC6 __catox
+ 0001:1B22 __cexit
+ 0001:22EA __cfltcvt
+ 000A:186E __cfltcvt_tab
+ 0001:1EA6 __cftoe
+ 0001:2072 __cftof
+ 0001:220A __cftog
+ 000A:1867 __child
+ 0001:1ADA __cinit
+ 0001:1C7A __cintDIV
+ 000A:183F __cpumode
+ 0001:1D92 __cropzeros
+ 0001:1B81 __ctermsub
+ 000A:1710 __ctype
+ 000A:1710 __ctype_
+ 0001:1B33 __c_exit
+ 000A:1706 __dllinit
+ 000A:1840 __doserrno
+ 000A:1DB0 __edata
+ 000A:246A __end
+ 000A:185E __environ
+ 000A:1869 __exitflag
+ 000A:182A __fac
+ 0001:1E4E __fassign
+ 0001:2B3A __ffree
+ 0001:1BBE __FF_MSGBANNER
+ 000A:191C __fheap
+ 0001:28CF __findlast
+ 0001:2AD6 __fltin
+ 0001:238C __fltout
+ 0000:9876 Abs __fltused
+ 0001:2B5B __fmalloc
+ 0001:18E6 __fmemmove
+ 0001:25FC __fmemset
+ 0001:1D1C __forcdecpt
+ 000A:1934 __fpinit
+ 0000:0000 Imp __fpmath (WIN87EM.1)
+ 0001:23E2 __fpsignal
+ 0000:9876 Abs __fptaskdata
+ 0001:24F8 __fptostr
+ 0001:2454 __fptrap
+ 0001:15CC __fpurecall
+ 0001:2CEC __freefarheap
+ 0001:2FDE __freelist
+ 0001:186E __fstrchr
+ 0001:25C0 __fstrcpy
+ 0001:18A0 __fstricmp
+ 0001:25A6 __fstrlen
+ 0001:1A0C __ftol
+ 0001:1362 __gcvt
+ 0001:2488 __GetDGROUP
+ 0001:27D8 __growseg
+ 000A:16FC __hModule
+ 0001:2869 __incseg
+ 0001:3008 __initseg
+ 0001:33FF __LD12MULT
+ 0001:332A __LD12MULTTENPOWER
+ 0001:303C __linkseg
+ 000A:1702 __lpszCmdLine
+ 0001:3584 __MANTOLD12
+ 000A:2462 __mbac
+ 0001:245A __myalloc
+ 0001:2498 __nearstub
+ 0001:2C6A __newseg
+ 000A:1842 __nfile
+ 0001:2406 __NMSG_TEXT
+ 0001:243D __NMSG_WRITE
+ 0001:134A __nomain
+ 0001:15CC __npurecall
+ 000A:1840 __oserr
+ 000A:1844 __osfile
+ 000A:183B __osmajor
+ 000A:183A __osminor
+ 000A:183E __osmode
+ 000A:183A __osver
+ 000A:183C __osversion
+ 000A:1862 __pgmptr
+ 000A:190E __pnhFarHeap
+ 0001:1E16 __positive
+ 0001:15CC __purecall
+ 0001:2CFA __searchseg
+ 0001:1BE2 __setenvp
+ 000A:188C __sigintoff
+ 000A:188A __sigintseg
+ 0000:0001 Abs __sizec
+ 0000:0001 Abs __sized
+ 0001:2C02 __STRINGTOD
+ 0001:2D76 __STRINGTOLD
+ 0001:1AAE __stubmain
+ 0009:003C __STUBWEP
+ 000A:1836 __umaskval
+ 000A:16FE __wDataSeg
+ 0001:1264 __wflags
+ 000A:1700 __wHeapSize
+ 0000:0000 Imp __WINFLAGS (KERNEL.178)
+ 000A:1839 __winmajor
+ 000A:1838 __winminor
+ 000A:1838 __winver
+ 000A:170D ___aDBrterr
+ 000A:170B ___aDBswpflg
+ 000A:1858 ___argc
+ 000A:185A ___argv
+ 0001:28F0 ___ExportedStub
+
+ Address Publics by Value
+
+ 0000:0000 Imp COMARSHALHRESULT (COMPOBJ.32)
+ 0000:0000 Imp GETMODULEUSAGE (KERNEL.48)
+ 0000:0000 Imp COGETSTATE (COMPOBJ.COGETSTATE)
+ 0000:0000 Imp GETPROCADDRESS (KERNEL.50)
+ 0000:0000 Imp GETDOSENVIRONMENT (KERNEL.131)
+ 0000:0000 Imp GLOBALFREE (KERNEL.17)
+ 0000:0000 Imp GLOBALSIZE (KERNEL.20)
+ 0000:0000 Imp REGENUMKEY (SHELL.7)
+ 0000:0000 Imp COSETSTATE (COMPOBJ.COSETSTATE)
+ 0000:0000 Imp GETPROFILEINT (KERNEL.57)
+ 0000:0000 Imp __fpmath (WIN87EM.1)
+ 0000:0000 Imp REGOPENKEY (SHELL.1)
+ 0000:0000 Imp __WINFLAGS (KERNEL.178)
+ 0000:0000 Imp GETWINFLAGS (KERNEL.132)
+ 0000:0000 Imp GETUSERDEFAULTLCID (OLE2NLS.1)
+ 0000:0000 Imp REGISTERNLSINFOCHANGED (OLE2NLS.9)
+ 0000:0000 Imp COGETMALLOC (COMPOBJ.4)
+ 0000:0000 Imp GETVERSION (KERNEL.3)
+ 0000:0000 Imp __AHSHIFT (KERNEL.113)
+ 0000:0000 Imp COUNMARSHALHRESULT (COMPOBJ.33)
+ 0000:0000 Imp COUNMARSHALINTERFACE (COMPOBJ.9)
+ 0000:0000 Imp GLOBALUNLOCK (KERNEL.19)
+ 0000:0000 Imp CREATEITEMMONIKER (OLE2.27)
+ 0000:0000 Imp GETRUNNINGOBJECTTABLE (OLE2.30)
+ 0000:0000 Imp GLOBALLOCK (KERNEL.18)
+ 0000:0000 Imp REGQUERYVALUE (SHELL.6)
+ 0000:0000 Imp LOADLIBRARY (KERNEL.95)
+ 0000:0000 Imp ISEQUALGUID (COMPOBJ.18)
+ 0000:0000 Imp SETERRORMODE (KERNEL.107)
+ 0000:0000 Imp HMEMCPY (KERNEL.348)
+ 0000:0000 Imp FREELIBRARY (KERNEL.96)
+ 0000:0000 Imp GETLOCALEINFOA (OLE2NLS.5)
+ 0000:0000 Imp REGCLOSEKEY (SHELL.3)
+ 0000:0000 Imp COMPARESTRINGA (OLE2NLS.8)
+ 0000:0000 Imp LOCKSEGMENT (KERNEL.23)
+ 0000:0000 Imp __AHINCR (KERNEL.114)
+ 0000:0000 Imp STRINGFROMGUID2 (COMPOBJ.76)
+ 0000:0000 Imp LCMAPSTRINGA (OLE2NLS.6)
+ 0000:0000 Imp FATALAPPEXIT (KERNEL.137)
+ 0000:0000 Imp GETSTRINGTYPEA (OLE2NLS.7)
+ 0000:0000 Imp DOS3CALL (KERNEL.102)
+ 0000:0000 Imp GLOBALALLOC (KERNEL.15)
+ 0000:0000 Imp COMARSHALINTERFACE (COMPOBJ.8)
+ 0000:0000 Imp GLOBALREALLOC (KERNEL.16)
+ 0000:0000 Imp LOCALINIT (KERNEL.4)
+ 0000:0000 Imp FATALEXIT (KERNEL.1)
+ 0000:0000 Imp INITTASK (KERNEL.91)
+ 0000:0001 Abs __sized
+ 0000:0001 Abs __sizec
+ 0000:0632 Abs FISRQQ
+ 0000:0E32 Abs FICRQQ
+ 0000:1632 Abs FIERQQ
+ 0000:9876 Abs __acrtused
+ 0000:9876 Abs __fptaskdata
+ 0000:9876 Abs __acrtmsg
+ 0000:9876 Abs __fltused
+ 0000:D6D6 Abs __aDBused
+ 0000:D6D6 Abs __aDBdoswp
+ 0001:0010 LIBMAIN
+ 0001:003E _WEP
+ 0001:0070 ??0CProcessInfo@@REC@XZ
+ 0001:00C2 ??1CProcessInfo@@REC@XZ
+ 0001:0186 ?QueryInterface@CProcessInfo@@VEAPEXAFUGUID@@PEPEX@Z
+ 0001:01F4 ?AddRef@CProcessInfo@@VEAKXZ
+ 0001:0216 ?Release@CProcessInfo@@VEAKXZ
+ 0001:02C4 _UpdateProcessInfo
+ 0001:0388 ??0CErrorInfo@@REC@XZ
+ 0001:03FE ??1CErrorInfo@@REC@XZ
+ 0001:0454 ?Create@CErrorInfo@@TAPEXPEPEV1@@Z
+ 0001:04A6 ?QueryInterface@CErrorInfo@@VEAPEXAFUGUID@@PEPEX@Z
+ 0001:058C ?AddRef@CErrorInfo@@VEAKXZ
+ 0001:05AE ?Release@CErrorInfo@@VEAKXZ
+ 0001:0604 ?GetGUID@CErrorInfo@@VEAPEXPEUGUID@@@Z
+ 0001:062E ?GetSource@CErrorInfo@@VEAPEXPEPED@Z
+ 0001:0650 ?GetDescription@CErrorInfo@@VEAPEXPEPED@Z
+ 0001:0672 ?GetHelpFile@CErrorInfo@@VEAPEXPEPED@Z
+ 0001:0694 ?GetHelpContext@CErrorInfo@@VEAPEXPEK@Z
+ 0001:06B8 ?SetGUID@CErrorInfo@@VEAPEXAFUGUID@@@Z
+ 0001:06E2 ?SetSource@CErrorInfo@@VEAPEXPED@Z
+ 0001:0720 ?SetDescription@CErrorInfo@@VEAPEXPED@Z
+ 0001:075E ?SetHelpFile@CErrorInfo@@VEAPEXPED@Z
+ 0001:079C ?SetHelpContext@CErrorInfo@@VEAPEXK@Z
+ 0001:07BC SETERRORINFO
+ 0001:083E GETERRORINFO
+ 0001:08BC CREATEERRORINFO
+ 0001:091E ??2@ZAPAXI@Z
+ 0001:0922 ??3@ZAXPAX@Z
+ 0001:0924 ??2@ZAPEXI@Z
+ 0001:0988 ??3@ZAXPEX@Z
+ 0001:09F0 NLSINFOCHANGEDHANDLER
+ 0001:0A0E DETECTFBSTPIMPLEMENTED
+ 0001:0A26 VARIANTINIT
+ 0001:0A3C VARIANTCLEAR
+ 0001:0B38 VARIANTCOPY
+ 0001:0C70 VARIANTCOPYIND
+ 0001:0E52 ?IsLegalVartype@@ZCPEXG@Z
+ 0001:0E8E REGISTERACTIVEOBJECT
+ 0001:0F7A REVOKEACTIVEOBJECT
+ 0001:0FF2 GETACTIVEOBJECT
+ 0001:10A4 _IID_ICreateTypeLib
+ 0001:10B4 _IID_ICreateTypeInfo
+ 0001:10C4 _IID_ITypeComp
+ 0001:10D4 _IID_ITypeLib
+ 0001:10E4 _IID_ITypeInfo
+ 0001:10F4 _IID_IEnumVARIANT
+ 0001:1104 _IID_IDispatch
+ 0001:1114 _IID_ISupportErrorInfo
+ 0001:1124 _IID_ICreateErrorInfo
+ 0001:1134 _IID_IErrorInfo
+ 0001:1144 _IID_StdOle
+ 0001:1154 _IID_IRpcChannelBuffer
+ 0001:1164 _IID_IRpcStubBuffer
+ 0001:1174 _IID_IRpcProxyBuffer
+ 0001:1184 _IID_IStream
+ 0001:1194 _IID_IPSFactory
+ 0001:11A4 _IID_IPSFactoryBuffer
+ 0001:11B4 _IID_IRpcProxy
+ 0001:11C4 _IID_IRpcStub
+ 0001:11D4 _IID_IUnknown
+ 0001:11E4 _GUID_NULL
+ 0001:11F4 _CLSID_PSSupportErrorInfo
+ 0001:1204 _CLSID_PSTypeComp
+ 0001:1214 _CLSID_PSAutomation
+ 0001:1224 _CLSID_PSTypeLib
+ 0001:1234 _CLSID_PSTypeInfo
+ 0001:1244 _CLSID_PSEnumVARIANT
+ 0001:1254 _CLSID_PSDispatch
+ 0001:1264 __wflags
+ 0001:12A8 __astart
+ 0001:134A __nomain
+ 0001:1362 __gcvt
+ 0001:146A _atoi
+ 0001:146E __aFahdiff
+ 0001:148E _strtoul
+ 0001:149A _strtol
+ 0001:15CC __npurecall
+ 0001:15CC __purecall
+ 0001:15CC __fpurecall
+ 0001:15D2 __aFFalmul
+ 0001:15D2 __aFFaulmul
+ 0001:15F4 __aFFalrem
+ 0001:1616 __aFFauldiv
+ 0001:1638 __aFldiv
+ 0001:16D2 __aFlmul
+ 0001:16D2 __aFulmul
+ 0001:1704 __aFlrem
+ 0001:17A4 __aFuldiv
+ 0001:1804 __aFulrem
+ 0001:186E __fstrchr
+ 0001:18A0 __fstricmp
+ 0001:18E6 __fmemmove
+ 0001:19B0 __aFCIfloor
+ 0001:19E5 _floor
+ 0001:1A0C __aFftol
+ 0001:1A0C __ftol
+ 0001:1A4A _modf
+ 0001:1AAE __stubmain
+ 0001:1ADA __cinit
+ 0001:1B22 __cexit
+ 0001:1B33 __c_exit
+ 0001:1B81 __ctermsub
+ 0001:1BBE __FF_MSGBANNER
+ 0001:1BE2 __setenvp
+ 0001:1C7A __cintDIV
+ 0001:1C84 __amsg_exit
+ 0001:1CC6 __catox
+ 0001:1D1C __forcdecpt
+ 0001:1D92 __cropzeros
+ 0001:1E16 __positive
+ 0001:1E4E __fassign
+ 0001:1EA6 __cftoe
+ 0001:2072 __cftof
+ 0001:220A __cftog
+ 0001:22EA __cfltcvt
+ 0001:238C __fltout
+ 0001:23E2 __fpsignal
+ 0001:2406 __NMSG_TEXT
+ 0001:243D __NMSG_WRITE
+ 0001:2454 __fptrap
+ 0001:245A __myalloc
+ 0001:2488 __GetDGROUP
+ 0001:2498 __nearstub
+ 0001:249A _atof
+ 0001:24F8 __fptostr
+ 0001:25A6 __fstrlen
+ 0001:25C0 __fstrcpy
+ 0001:25FC __fmemset
+ 0001:2692 $i8_output
+ 0001:27D8 __growseg
+ 0001:2869 __incseg
+ 0001:28CF __findlast
+ 0001:28F0 ___ExportedStub
+ 0001:2904 _strlen
+ 0001:2A99 $i8_tpwr10
+ 0001:2AD6 __fltin
+ 0001:2B3A __ffree
+ 0001:2B5B __fmalloc
+ 0001:2C02 __STRINGTOD
+ 0001:2C6A __newseg
+ 0001:2CEC __freefarheap
+ 0001:2CFA __searchseg
+ 0001:2D76 __STRINGTOLD
+ 0001:2FDE __freelist
+ 0001:3008 __initseg
+ 0001:303C __linkseg
+ 0001:332A __LD12MULTTENPOWER
+ 0001:33FF __LD12MULT
+ 0001:3584 __MANTOLD12
+ 0001:363E ?QueryInterface@CErrorInfo@@X3EAPEXAFUGUID@@PEPEX@Z
+ 0001:364A ?AddRef@CErrorInfo@@X3EAKXZ
+ 0001:3656 ?Release@CErrorInfo@@X3EAKXZ
+ 0002:0000 ??_7IPSFactoryBuffer@@6F@
+ 0002:0014 ??_7IUnknown@@6F@
+ 0002:0020 ??_7COleAutomationPSFactory@@6F@
+ 0002:0034 ??_7CPDProxImpl@@6F@
+ 0002:0048 ??_7CPDDispImpl@@6F@
+ 0002:0068 ??_7CPDUnkImpl@@6F@
+ 0002:0074 ??_7CStubDisp@@6F@
+ 0002:009C ??_7CPEVEnumVARIANTImpl@@6F@
+ 0002:00B8 ??_7CPEVUnkImpl@@6F@
+ 0002:00C4 ??_7CPEVProxImpl@@6F@
+ 0002:00D8 ??_7CStubEnumVARIANT@@6F@
+ 0002:0100 ??_7CPTITypeInfoImpl@@6F@
+ 0002:0158 ??_7CPTIUnkImpl@@6F@
+ 0002:0164 ??_7CPTIProxImpl@@6F@
+ 0002:0178 ??_7CStubTypeInfo@@6F@
+ 0002:01A0 ??_7IErrorInfo@@6F@
+ 0002:01C0 ??_7CErrorInfo@@6FIErrorInfo@@@
+ 0002:01E0 ??_7CErrorInfo@@6FICreateErrorInfo@@@
+ 0002:0200 ??_7CProcessInfo@@6F@
+ 0002:020C ??_7CPTLibTypeLibImpl@@6F@
+ 0002:0240 ??_7CPTLibUnkImpl@@6F@
+ 0002:024C ??_7CPTLibProxImpl@@6F@
+ 0002:0260 ??_7CStubTypeLib@@6F@
+ 0002:0288 ??_7CPTCompTypeCompImpl@@6F@
+ 0002:029C ??_7CPTCompUnkImpl@@6F@
+ 0002:02A8 ??_7CPTCompProxImpl@@6F@
+ 0002:02BC ??_7CStubTypeComp@@6F@
+ 0002:02E4 ??_7CPriv@CProxUniv@@6F@
+ 0002:02F8 ??_7IRpcProxyBuffer@@6F@
+ 0002:030C ??_7CStubUniv@@6F@
+ 0002:0334 ??_7CStreamOnBuffer@@6F@
+ 0002:037C ??_7CDispTypeInfo@@6F@
+ 0002:03D4 ??_7IDispatch@@6F@
+ 0002:03F0 ??_7CStdDispUnkImpl@@6F@
+ 0002:03FC ??_7CStdDisp@@6F@
+ 0002:0418 ??_C@_01PIHH@?$CB?$AA@
+ 0002:041A ??_7CStubSupportErrorInfo@@6F@
+ 0002:0442 ??_7CPSupErrSupImpl@@6F@
+ 0002:0452 ??_7CPSupErrUnkImpl@@6F@
+ 0002:045E ??_7CPSupErrProxImpl@@6F@
+ 0003:0000 INDEXOFPARAM
+ 0003:006C DISPGETPARAM
+ 0003:00E8 DISPGETIDSOFNAMES
+ 0003:011C DISPINVOKE
+ 0003:0168 DOSDATETIMETOVARIANTTIME
+ 0003:022C VARIANTTIMETODOSDATETIME
+ 0003:02BA ?hSizeToAlloc@@ZCKPEUtagSAFEARRAY@@K@Z
+ 0003:0306 ?hAccessElement@@ZCPIXPEUtagSAFEARRAY@@K@Z
+ 0003:03E8 ?hAccessElement@@ZCPIXPIXGK@Z
+ 0003:04BC ?hmemset@@ZCXPIXHK@Z
+ 0003:05B0 SAFEARRAYALLOCDESCRIPTOR
+ 0003:0620 SAFEARRAYALLOCDATA
+ 0003:0716 SAFEARRAYCREATE
+ 0003:0858 ?ReleaseResources@@ZCXPIXKGG@Z
+ 0003:0A08 SAFEARRAYDESTROYDATA
+ 0003:0B4E SAFEARRAYDESTROYDESCRIPTOR
+ 0003:0B8C SAFEARRAYDESTROY
+ 0003:0C00 SAFEARRAYREDIM
+ 0003:1050 SAFEARRAYCOPY
+ 0003:1474 SAFEARRAYGETDIM
+ 0003:1488 SAFEARRAYGETELEMSIZE
+ 0003:149E SAFEARRAYGETUBOUND
+ 0003:150A SAFEARRAYGETLBOUND
+ 0003:1566 SAFEARRAYLOCK
+ 0003:15A0 SAFEARRAYUNLOCK
+ 0003:15DA SAFEARRAYACCESSDATA
+ 0003:1626 SAFEARRAYUNACCESSDATA
+ 0003:163E SAFEARRAYPTROFINDEX
+ 0003:1708 SAFEARRAYGETELEMENT
+ 0003:1872 SAFEARRAYPUTELEMENT
+ 0003:1A0E ?SafeArraySize@@ZCKPEUtagSAFEARRAY@@@Z
+ 0003:1B42 ERRPACKDATE
+ 0003:1DBE ERRUNPACKDATE
+ 0003:20D2 GETCURRENTYEAR
+ 0003:20E6 XTOA
+ 0003:2186 DISP_ITOA
+ 0003:21BE DISP_LTOA
+ 0003:21F4 DISP_GCVT
+ 0003:2216 _IsCharType
+ 0003:2252 _IsPrefix
+ 0003:2408 SAFEGETLOCALEINFO
+ 0003:24B0 SAFEGETLOCALESHORT
+ 0003:3DFC VARDATEFROMSTR
+ 0003:428C _SetUDSfromYMD
+ 0003:4E44 VARBSTRFROMDATE
+ 0003:4F5E INTOFSTRING
+ 0003:5060 ERRCYFROMI2
+ 0003:5087 ERRCYFROMI4
+ 0003:50C8 ERRCYFROMR4
+ 0003:510C ERRCYFROMR8
+ 0003:5150 ERRI2FROMCY
+ 0003:5194 ERRI4FROMCY
+ 0003:51D8 ERRR4FROMCY
+ 0003:5208 ERRR8FROMCY
+ 0003:5238 ERRMULTCYI4
+ 0003:527A DOFBSTP
+ 0003:52E5 CONVFLOATTOASCII
+ 0003:532B CONVDECTOFLOAT
+ 0003:5626 VARIANTCHANGETYPE
+ 0003:5650 VARIANTCHANGETYPEEX
+ 0003:62BE DISPALLOC
+ 0003:6372 DISPFREE
+ 0003:65DE VARBOOLFROMUI1
+ 0003:65FC VARBOOLFROMI2
+ 0003:661A VARBOOLFROMI4
+ 0003:6640 VARBOOLFROMR4
+ 0003:6670 VARBOOLFROMR8
+ 0003:66A0 VARBOOLFROMDATE
+ 0003:66C4 VARBOOLFROMCY
+ 0003:66F2 VARBOOLFROMSTR
+ 0003:688E VARBOOLFROMDISP
+ 0003:68CC VARUI1FROMI2
+ 0003:68FC VARUI1FROMI4
+ 0003:6930 VARUI1FROMR4
+ 0003:6958 VARUI1FROMR8
+ 0003:69AA VARUI1FROMCY
+ 0003:69F8 VARUI1FROMDATE
+ 0003:6A1C VARUI1FROMBOOL
+ 0003:6A36 VARUI1FROMSTR
+ 0003:6A7A VARUI1FROMDISP
+ 0003:6AB8 VARI2FROMUI1
+ 0003:6AD4 VARI2FROMI4
+ 0003:6B18 VARI2FROMR4
+ 0003:6B40 VARI2FROMR8
+ 0003:6B92 VARI2FROMCY
+ 0003:6BB8 VARI2FROMDATE
+ 0003:6BDC VARI2FROMBOOL
+ 0003:6BF6 VARI2FROMSTR
+ 0003:6D72 VARI2FROMDISP
+ 0003:6DB0 VARI4FROMUI1
+ 0003:6DD0 VARI4FROMI2
+ 0003:6DF0 VARI4FROMBOOL
+ 0003:6E0C VARI4FROMR4
+ 0003:6E34 VARI4FROMR8
+ 0003:6E8A VARI4FROMCY
+ 0003:6EB0 VARI4FROMDATE
+ 0003:6ED4 VARI4FROMSTR
+ 0003:70A4 VARI4FROMDISP
+ 0003:71A6 VARR4FROMUI1
+ 0003:71D8 VARR4FROMI2
+ 0003:71F6 VARR4FROMBOOL
+ 0003:7212 VARR4FROMI4
+ 0003:7230 VARR4FROMR8
+ 0003:7282 VARR4FROMCY
+ 0003:72A8 VARR4FROMDATE
+ 0003:72CC VARR4FROMSTR
+ 0003:731A VARR4FROMDISP
+ 0003:7360 VARR8FROMUI1
+ 0003:7392 VARR8FROMI2
+ 0003:73B0 VARR8FROMBOOL
+ 0003:73CC VARR8FROMI4
+ 0003:73EA VARR8FROMR4
+ 0003:7408 VARR8FROMCY
+ 0003:742E VARR8FROMDATE
+ 0003:7454 VARR8FROMSTR
+ 0003:75AC VARR8FROMDISP
+ 0003:75F6 VARDATEFROMUI1
+ 0003:7614 VARDATEFROMI2
+ 0003:765C VARDATEFROMBOOL
+ 0003:7678 VARDATEFROMI4
+ 0003:76B8 VARDATEFROMR4
+ 0003:76F8 VARDATEFROMR8
+ 0003:7738 VARDATEFROMCY
+ 0003:7794 ?IsValidDate@@ZCPEXN@Z
+ 0003:77CE VARDATEFROMDISP
+ 0003:7818 VARCYFROMUI1
+ 0003:7838 VARCYFROMI2
+ 0003:7854 VARCYFROMI4
+ 0003:7874 VARCYFROMR4
+ 0003:7892 VARCYFROMR8
+ 0003:78B0 VARCYFROMDATE
+ 0003:78D4 VARCYFROMBOOL
+ 0003:78F0 VARCYFROMSTR
+ 0003:7D58 VARCYFROMDISP
+ 0003:7DA2 MAPHALFWIDTH
+ 0003:7ED0 VARBSTRFROMUI1
+ 0003:7EFA VARBSTRFROMI2
+ 0003:7F26 VARBSTRFROMBOOL
+ 0003:7F80 VARBSTRFROMI4
+ 0003:7FB0 ?BstrFromFloat@@ZAPEXNKKPEPEDH@Z
+ 0003:82DE VARBSTRFROMR4
+ 0003:8384 VARBSTRFROMR8
+ 0003:8426 VARBSTRFROMCY
+ 0003:873C VARBSTRFROMDISP
+ 0003:8A8C ?VectorFromBstr@@ZCPEXPEDPEPEUtagSAFEARRAY@@@Z
+ 0003:8B28 ?BstrFromVector@@ZCPEXPEUtagSAFEARRAY@@PEPED@Z
+ 0003:8BA2 ISDBCS
+ 0003:8C08 ISJAPAN
+ 0003:8C46 ISKOREA
+ 0003:8C84 ISTAIWAN
+ 0003:8CC2 ISCHINA
+ 0003:8D00 PARSESTRTONUM
+ 0004:0000 ?Create@COleAutomationPSFactory@@TAPEUIPSFactoryBuffer@@XZ
+ 0004:0078 ?QueryInterface@COleAutomationPSFactory@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:00E6 ?AddRef@COleAutomationPSFactory@@VEAKXZ
+ 0004:0108 ?Release@COleAutomationPSFactory@@VEAKXZ
+ 0004:014A ?CreateProxy@COleAutomationPSFactory@@VEAPEXPEUIUnknown@@AFUGUID
+ 0004:03BC ?CreateStub@COleAutomationPSFactory@@VEAPEXAFUGUID@@PEUIUnknown@
+ 0004:05E8 ?IsAutomationCLSID@@ZAHAFUGUID@@@Z
+ 0004:0680 DLLGETCLASSOBJECT
+ 0004:06D8 DLLCANUNLOADNOW
+ 0004:06E8 ?ProxyStubCLSIDOfInterface@@ZAPEXAFUGUID@@PEU1@@Z
+ 0004:07E4 ?BstrWrite@@ZAPEXPEUIStream@@PEDW4tagSYSKIND@@@Z
+ 0004:08D0 ?BstrRead@@ZAPEXPEUIStream@@PEPEDW4tagSYSKIND@@@Z
+ 0004:09FA ?VariantWrite@@ZAPEXPEUIStream@@PEUtagVARIANT@@W4tagSYSKIND@@@Z
+ 0004:0C98 ?VariantRead@@ZAPEXPEUIStream@@PEUtagVARIANT@@1W4tagSYSKIND@@@Z
+ 0004:0F74 ?VariantReadType@@ZAPEXPEUIStream@@PEUtagVARIANT@@W4tagSYSKIND@@
+ 0004:1406 ?ExcepinfoRead@@ZAPEXPEUIStream@@PEUtagEXCEPINFO@@W4tagSYSKIND@@
+ 0004:14DC ?ExcepinfoWrite@@ZAPEXPEUIStream@@PEUtagEXCEPINFO@@W4tagSYSKIND@
+ 0004:15D0 ?MarshalErrorInfo@@ZAPEXPEUIStream@@W4tagSYSKIND@@@Z
+ 0004:180E ?UnmarshalErrorInfo@@ZAPEXPEUIStream@@W4tagSYSKIND@@@Z
+ 0004:2772 ?StructWrite@@ZAPEXPEUIStream@@PEUtagFIELDDESC@@PEXW4tagSYSKIND@
+ 0004:290E ?StructRead@@ZAPEXPEUIStream@@PEUtagFIELDDESC@@PEXW4tagSYSKIND@@
+ 0004:2AEE DISPMARSHALINTERFACE
+ 0004:2BB4 DISPUNMARSHALINTERFACE
+ 0004:2C3A ??0CProxDisp@@BEC@PEUIUnknown@@AFUGUID@@@Z
+ 0004:2CC6 ??1CProxDisp@@BEC@XZ
+ 0004:2CFE ?Create@CProxDisp@@TAPEUIUnknown@@PEU2@AFUGUID@@@Z
+ 0004:2D4E ??0CPDUnkImpl@@REC@PEVCProxDisp@@@Z
+ 0004:2D78 ??1CPDUnkImpl@@REC@XZ
+ 0004:2D8E ?QueryInterface@CPDUnkImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:2E82 ?AddRef@CPDUnkImpl@@VEAKXZ
+ 0004:2EA8 ?Release@CPDUnkImpl@@VEAKXZ
+ 0004:2F06 ??0CPDProxImpl@@REC@PEVCProxDisp@@@Z
+ 0004:2F30 ??1CPDProxImpl@@REC@XZ
+ 0004:2F82 ?QueryInterface@CPDProxImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:2FB2 ?AddRef@CPDProxImpl@@VEAKXZ
+ 0004:2FDC ?Release@CPDProxImpl@@VEAKXZ
+ 0004:3006 ?Connect@CPDProxImpl@@VEAPEXPEUIRpcChannelBuffer@@@Z
+ 0004:3066 ?Disconnect@CPDProxImpl@@VEAXXZ
+ 0004:30B2 ??0CPDDispImpl@@REC@PEVCProxDisp@@@Z
+ 0004:30DC ??1CPDDispImpl@@REC@XZ
+ 0004:30F2 ?QueryInterface@CPDDispImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:3126 ?AddRef@CPDDispImpl@@VEAKXZ
+ 0004:3154 ?Release@CPDDispImpl@@VEAKXZ
+ 0004:3182 ?SysKind@CPDDispImpl@@VEAPEXXZ
+ 0004:32A4 ?ProxyGetTypeInfoCount@@ZAPEXPEUIRpcChannelBuffer@@W4tagSYSKIND@
+ 0004:3406 ?GetTypeInfoCount@CPDDispImpl@@VEAPEXPEI@Z
+ 0004:3438 ?ProxyGetTypeInfo@@ZAPEXPEUIRpcChannelBuffer@@W4tagSYSKIND@@IKPE
+ 0004:360C ?GetTypeInfo@CPDDispImpl@@VEAPEXIKPEPEUITypeInfo@@@Z
+ 0004:3642 ?ProxyGetIDsOfNames@@ZAPEXPEUIRpcChannelBuffer@@W4tagSYSKIND@@AF
+ 0004:3A24 ?GetIDsOfNames@CPDDispImpl@@VEAPEXAFUGUID@@PEPEDIKPEJ@Z
+ 0004:3A6A ?ProxyInvoke@@ZAPEXPEUIRpcChannelBuffer@@W4tagSYSKIND@@JAFUGUID@
+ 0004:3F22 ?Invoke@CPDDispImpl@@VEAPEXJAFUGUID@@KGPEUtagDISPPARAMS@@PEUtagV
+ 0004:3F7A ??0CStubDisp@@BEC@XZ
+ 0004:3FC4 ??1CStubDisp@@BEC@XZ
+ 0004:3FE8 ?Create@CStubDisp@@TAPEXPEUIUnknown@@AFUGUID@@PEPEUIRpcStubBuffe
+ 0004:408A ?QueryInterface@CStubDisp@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:40F6 ?AddRef@CStubDisp@@VEAKXZ
+ 0004:4118 ?Release@CStubDisp@@VEAKXZ
+ 0004:416E ?Connect@CStubDisp@@VEAPEXPEUIUnknown@@@Z
+ 0004:41DE ?Disconnect@CStubDisp@@VEAXXZ
+ 0004:42B2 ?StubGetTypeInfoCount@@ZAPEXPEUIDispatch@@PEUIStream@@@Z
+ 0004:4354 ?StubGetTypeInfo@@ZAPEXPEUIDispatch@@PEUIStream@@@Z
+ 0004:447C ?StubGetIDsOfNames@@ZAPEXPEUIDispatch@@PEUIStream@@@Z
+ 0004:4778 ?StubInvoke@@ZAPEXPEUIDispatch@@PEUIStream@@@Z
+ 0004:4D42 ?Invoke@CStubDisp@@VEAPEXPEUtagRPCOLEMESSAGE@@PEUIRpcChannelBuff
+ 0004:4E80 ?IsIIDSupported@CStubDisp@@VEAPEUIRpcStubBuffer@@AFUGUID@@@Z
+ 0004:4ED0 ?CountRefs@CStubDisp@@VEAKXZ
+ 0004:4F18 ?DebugServerQueryInterface@CStubDisp@@VEAPEXPEPEX@Z
+ 0004:4F3C ?DebugServerRelease@CStubDisp@@VEAXPEX@Z
+ 0004:4F48 ??0CProxEnumVARIANT@@BEC@PEUIUnknown@@@Z
+ 0004:4FB4 ?Create@CProxEnumVARIANT@@TAPEUIUnknown@@PEU2@@Z
+ 0004:4FFE ??0CPEVUnkImpl@@REC@PEVCProxEnumVARIANT@@@Z
+ 0004:5028 ?QueryInterface@CPEVUnkImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:50FA ?AddRef@CPEVUnkImpl@@VEAKXZ
+ 0004:5120 ?Release@CPEVUnkImpl@@VEAKXZ
+ 0004:5186 ??0CPEVProxImpl@@REC@PEVCProxEnumVARIANT@@@Z
+ 0004:51B0 ??1CPEVProxImpl@@REC@XZ
+ 0004:51F0 ?QueryInterface@CPEVProxImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:5220 ?AddRef@CPEVProxImpl@@VEAKXZ
+ 0004:524A ?Release@CPEVProxImpl@@VEAKXZ
+ 0004:5274 ?Connect@CPEVProxImpl@@VEAPEXPEUIRpcChannelBuffer@@@Z
+ 0004:52BC ?Disconnect@CPEVProxImpl@@VEAXXZ
+ 0004:5308 ??0CPEVEnumVARIANTImpl@@REC@PEVCProxEnumVARIANT@@@Z
+ 0004:5332 ?QueryInterface@CPEVEnumVARIANTImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:5366 ?AddRef@CPEVEnumVARIANTImpl@@VEAKXZ
+ 0004:5394 ?Release@CPEVEnumVARIANTImpl@@VEAKXZ
+ 0004:53C2 ?Next@CPEVEnumVARIANTImpl@@VEAPEXKPEUtagVARIANT@@PEK@Z
+ 0004:567A ?Skip@CPEVEnumVARIANTImpl@@VEAPEXK@Z
+ 0004:57C2 ?Reset@CPEVEnumVARIANTImpl@@VEAPEXXZ
+ 0004:58D6 ?Clone@CPEVEnumVARIANTImpl@@VEAPEXPEPEUIEnumVARIANT@@@Z
+ 0004:5A22 ??0CStubEnumVARIANT@@BEC@XZ
+ 0004:5A58 ??1CStubEnumVARIANT@@BEC@XZ
+ 0004:5A7C ?Create@CStubEnumVARIANT@@TAPEXPEUIUnknown@@PEPEUIRpcStubBuffer@
+ 0004:5AF0 ?QueryInterface@CStubEnumVARIANT@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:5B5C ?AddRef@CStubEnumVARIANT@@VEAKXZ
+ 0004:5B7E ?Release@CStubEnumVARIANT@@VEAKXZ
+ 0004:5BD4 ?Connect@CStubEnumVARIANT@@VEAPEXPEUIUnknown@@@Z
+ 0004:5C42 ?Disconnect@CStubEnumVARIANT@@VEAXXZ
+ 0004:60AA ?Invoke@CStubEnumVARIANT@@VEAPEXPEUtagRPCOLEMESSAGE@@PEUIRpcChan
+ 0004:61D2 ?IsIIDSupported@CStubEnumVARIANT@@VEAPEUIRpcStubBuffer@@AFUGUID@
+ 0004:6222 ?CountRefs@CStubEnumVARIANT@@VEAKXZ
+ 0004:626A ?DebugServerQueryInterface@CStubEnumVARIANT@@VEAPEXPEPEX@Z
+ 0004:628E ?DebugServerRelease@CStubEnumVARIANT@@VEAXPEX@Z
+ 0004:629A ??0CStreamOnBuffer@@REC@PEUIRpcChannelBuffer@@PEUtagRPCOLEMESSAG
+ 0004:63A2 ??1CStreamOnBuffer@@REC@XZ
+ 0004:63E4 ?QueryInterface@CStreamOnBuffer@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:645A ?AddRef@CStreamOnBuffer@@VEAKXZ
+ 0004:647C ?Release@CStreamOnBuffer@@VEAKXZ
+ 0004:64F4 ?Read@CStreamOnBuffer@@VEAPEXPIXKPEK@Z
+ 0004:65AA ?Write@CStreamOnBuffer@@VEAPEXPJXKPEK@Z
+ 0004:6706 ?Seek@CStreamOnBuffer@@VEAPEXU_LARGE_INTEGER@@KPEU_ULARGE_INTEGE
+ 0004:67EC ?SetSize@CStreamOnBuffer@@VEAPEXU_ULARGE_INTEGER@@@Z
+ 0004:67FE ?CopyTo@CStreamOnBuffer@@VEAPEXPEUIStream@@U_ULARGE_INTEGER@@PEU
+ 0004:6810 ?Commit@CStreamOnBuffer@@VEAPEXK@Z
+ 0004:6822 ?Revert@CStreamOnBuffer@@VEAPEXXZ
+ 0004:6834 ?LockRegion@CStreamOnBuffer@@VEAPEXU_ULARGE_INTEGER@@0K@Z
+ 0004:6846 ?UnlockRegion@CStreamOnBuffer@@VEAPEXU_ULARGE_INTEGER@@0K@Z
+ 0004:6858 ?Stat@CStreamOnBuffer@@VEAPEXPEUtagSTATSTG@@K@Z
+ 0004:686A ?Clone@CStreamOnBuffer@@VEAPEXPEPEUIStream@@@Z
+ 0004:687C ?Call@CStreamOnBuffer@@VEAPEXXZ
+ 0004:69B8 ?RewindBuffer@CStreamOnBuffer@@VEAPEXXZ
+ 0004:6A04 ?ResetBuffer@CStreamOnBuffer@@VEAPEXXZ
+ 0004:6AC8 ?ResizeBuffer@CStreamOnBuffer@@VEAPEXK@Z
+ 0005:0000 ??0CProxTypeInfo@@BEC@PEUIUnknown@@@Z
+ 0005:006C ?Create@CProxTypeInfo@@TAPEUIUnknown@@PEU2@@Z
+ 0005:00B6 ??0CPTIUnkImpl@@REC@PEVCProxTypeInfo@@@Z
+ 0005:00E0 ?QueryInterface@CPTIUnkImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:01B2 ?AddRef@CPTIUnkImpl@@VEAKXZ
+ 0005:01D8 ?Release@CPTIUnkImpl@@VEAKXZ
+ 0005:023E ??0CPTIProxImpl@@REC@PEVCProxTypeInfo@@@Z
+ 0005:0268 ??1CPTIProxImpl@@REC@XZ
+ 0005:02A8 ?QueryInterface@CPTIProxImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:02D8 ?AddRef@CPTIProxImpl@@VEAKXZ
+ 0005:0302 ?Release@CPTIProxImpl@@VEAKXZ
+ 0005:032C ?Connect@CPTIProxImpl@@VEAPEXPEUIRpcChannelBuffer@@@Z
+ 0005:0374 ?Disconnect@CPTIProxImpl@@VEAXXZ
+ 0005:03C0 ??0CPTITypeInfoImpl@@REC@PEVCProxTypeInfo@@@Z
+ 0005:03EA ?QueryInterface@CPTITypeInfoImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:041E ?AddRef@CPTITypeInfoImpl@@VEAKXZ
+ 0005:044C ?Release@CPTITypeInfoImpl@@VEAKXZ
+ 0005:047A ?GetTypeAttr@CPTITypeInfoImpl@@VEAPEXPEPEUtagTYPEATTR@@@Z
+ 0005:068A ?GetTypeComp@CPTITypeInfoImpl@@VEAPEXPEPEUITypeComp@@@Z
+ 0005:07FE ?GetFuncDesc@CPTITypeInfoImpl@@VEAPEXIPEPEUtagFUNCDESC@@@Z
+ 0005:0A50 ?GetVarDesc@CPTITypeInfoImpl@@VEAPEXIPEPEUtagVARDESC@@@Z
+ 0005:0CA2 ?GetNames@CPTITypeInfoImpl@@VEAPEXJPEPEDIPEI@Z
+ 0005:1014 ?GetRefTypeOfImplType@CPTITypeInfoImpl@@VEAPEXIPEK@Z
+ 0005:11E4 ?GetImplTypeFlags@CPTITypeInfoImpl@@VEAPEXIPEH@Z
+ 0005:13A6 ?GetIDsOfNames@CPTITypeInfoImpl@@VEAPEXPEPEDIPEJ@Z
+ 0005:13B8 ?Invoke@CPTITypeInfoImpl@@VEAPEXPEXJGPEUtagDISPPARAMS@@PEUtagVAR
+ 0005:13CA ?GetDocumentation@CPTITypeInfoImpl@@VEAPEXJPEPED0PEK0@Z
+ 0005:1774 ?GetDllEntry@CPTITypeInfoImpl@@VEAPEXJW4tagINVOKEKIND@@PEPED1PEG
+ 0005:1AD4 ?GetRefTypeInfo@CPTITypeInfoImpl@@VEAPEXKPEPEUITypeInfo@@@Z
+ 0005:1C7C ?AddressOfMember@CPTITypeInfoImpl@@VEAPEXJW4tagINVOKEKIND@@PEPEX
+ 0005:1C8E ?CreateInstance@CPTITypeInfoImpl@@VEAPEXPEUIUnknown@@AFUGUID@@PE
+ 0005:1E44 ?GetMops@CPTITypeInfoImpl@@VEAPEXJPEPED@Z
+ 0005:1E70 ?GetContainingTypeLib@CPTITypeInfoImpl@@VEAPEXPEPEUITypeLib@@PEI
+ 0005:2034 ?DoReleaseDanglingTypeDesc@@ZCXPEUtagTYPEDESC@@@Z
+ 0005:20D0 ?ReleaseTypeAttr@CPTITypeInfoImpl@@VEAXPEUtagTYPEATTR@@@Z
+ 0005:2118 ?DoReleaseFuncDesc@@ZCXPEUtagFUNCDESC@@@Z
+ 0005:21A8 ?ReleaseFuncDesc@CPTITypeInfoImpl@@VEAXPEUtagFUNCDESC@@@Z
+ 0005:21C8 ?DoReleaseVarDesc@@ZCXPEUtagVARDESC@@@Z
+ 0005:2218 ?ReleaseVarDesc@CPTITypeInfoImpl@@VEAXPEUtagVARDESC@@@Z
+ 0005:2238 ?GetStream@CPTITypeInfoImpl@@RECPEXHKPEPEUIStream@@@Z
+ 0005:223E ?LrpcCall@CPTITypeInfoImpl@@RECPEXPEUIStream@@PEPEX@Z
+ 0005:2244 _TypedescRead
+ 0005:2478 ?TypedescWrite@@ZAPEXPEUIStream@@PEUtagTYPEDESC@@W4tagSYSKIND@@@
+ 0005:2662 _TypedescReadOrWrite
+ 0005:2696 ?TypeattrWrite@@ZCPEXPEUIStream@@PEUtagTYPEATTR@@W4tagSYSKIND@@@
+ 0005:2706 ?TypeattrRead@@ZCPEXPEUIStream@@PEUtagTYPEATTR@@W4tagSYSKIND@@@Z
+ 0005:278E ?FuncdescWrite@@ZCPEXPEUIStream@@PEUtagFUNCDESC@@W4tagSYSKIND@@@
+ 0005:2820 ?FuncdescRead@@ZCPEXPEUIStream@@PEUtagFUNCDESC@@W4tagSYSKIND@@@Z
+ 0005:2938 ?VardescWrite@@ZCPEXPEUIStream@@PEUtagVARDESC@@W4tagSYSKIND@@@Z
+ 0005:29D6 ?VardescRead@@ZCPEXPEUIStream@@PEUtagVARDESC@@W4tagSYSKIND@@@Z
+ 0005:2AD4 ??0CStubTypeInfo@@BEC@XZ
+ 0005:2B12 ??1CStubTypeInfo@@BEC@XZ
+ 0005:2B36 ?Create@CStubTypeInfo@@TAPEXPEUIUnknown@@PEPEUIRpcStubBuffer@@@Z
+ 0005:2BAA ?QueryInterface@CStubTypeInfo@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:2C16 ?AddRef@CStubTypeInfo@@VEAKXZ
+ 0005:2C38 ?Release@CStubTypeInfo@@VEAKXZ
+ 0005:2C8E ?Connect@CStubTypeInfo@@VEAPEXPEUIUnknown@@@Z
+ 0005:2CFC ?Disconnect@CStubTypeInfo@@VEAXXZ
+ 0005:2D6A ?Invoke@CStubTypeInfo@@VEAPEXPEUtagRPCOLEMESSAGE@@PEUIRpcChannel
+ 0005:2F1C ?IsIIDSupported@CStubTypeInfo@@VEAPEUIRpcStubBuffer@@AFUGUID@@@Z
+ 0005:2F6C ?CountRefs@CStubTypeInfo@@VEAKXZ
+ 0005:2FB4 ?GetTypeAttr@CStubTypeInfo@@RECPEXXZ
+ 0005:310C ?GetTypeComp@CStubTypeInfo@@RECPEXXZ
+ 0005:31DC ?GetFuncDesc@CStubTypeInfo@@RECPEXXZ
+ 0005:3370 ?GetVarDesc@CStubTypeInfo@@RECPEXXZ
+ 0005:3508 ?GetNames@CStubTypeInfo@@RECPEXXZ
+ 0005:37C0 ?GetRefTypeOfImplType@CStubTypeInfo@@RECPEXXZ
+ 0005:38B6 ?GetImplTypeFlags@CStubTypeInfo@@RECPEXXZ
+ 0005:39B6 ?GetIDsOfNames@CStubTypeInfo@@RECPEXXZ
+ 0005:39C0 ?GetDocumentation@CStubTypeInfo@@RECPEXXZ
+ 0005:3C40 ?GetDllEntry@CStubTypeInfo@@RECPEXXZ
+ 0005:3EBC ?GetRefTypeInfo@CStubTypeInfo@@RECPEXXZ
+ 0005:3FC2 ?CreateInstance@CStubTypeInfo@@RECPEXXZ
+ 0005:40BA ?GetContainingTypeLib@CStubTypeInfo@@RECPEXXZ
+ 0005:41BE ?MarshalResult@CStubTypeInfo@@RECPEXXZ
+ 0005:41E2 ?DebugServerQueryInterface@CStubTypeInfo@@VEAPEXPEPEX@Z
+ 0005:4206 ?DebugServerRelease@CStubTypeInfo@@VEAXPEX@Z
+ 0005:4212 ?DoLoadTypeLib@@ZCPEXPFDPEPEUITypeLib@@@Z
+ 0005:42CA ??0CProxTypeLib@@BEC@PEUIUnknown@@@Z
+ 0005:4336 ?Create@CProxTypeLib@@TAPEUIUnknown@@PEU2@@Z
+ 0005:4380 ??0CPTLibUnkImpl@@REC@PEVCProxTypeLib@@@Z
+ 0005:43AA ?QueryInterface@CPTLibUnkImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:446A ?AddRef@CPTLibUnkImpl@@VEAKXZ
+ 0005:4490 ?Release@CPTLibUnkImpl@@VEAKXZ
+ 0005:44F6 ??0CPTLibProxImpl@@REC@PEVCProxTypeLib@@@Z
+ 0005:4520 ??1CPTLibProxImpl@@REC@XZ
+ 0005:4560 ?QueryInterface@CPTLibProxImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:4590 ?AddRef@CPTLibProxImpl@@VEAKXZ
+ 0005:45BA ?Release@CPTLibProxImpl@@VEAKXZ
+ 0005:45E4 ?Connect@CPTLibProxImpl@@VEAPEXPEUIRpcChannelBuffer@@@Z
+ 0005:4644 ?Disconnect@CPTLibProxImpl@@VEAXXZ
+ 0005:4690 ??0CPTLibTypeLibImpl@@REC@PEVCProxTypeLib@@@Z
+ 0005:46C0 ?QueryInterface@CPTLibTypeLibImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:46F4 ?AddRef@CPTLibTypeLibImpl@@VEAKXZ
+ 0005:4722 ?Release@CPTLibTypeLibImpl@@VEAKXZ
+ 0005:4750 ?DoGetTypeInfoCount@CPTLibTypeLibImpl@@RECPEXPEI@Z
+ 0005:4870 ?GetTypeInfoCount@CPTLibTypeLibImpl@@VEAIXZ
+ 0005:48A6 ?GetTypeInfo@CPTLibTypeLibImpl@@VEAPEXIPEPEUITypeInfo@@@Z
+ 0005:4A5A ?GetTypeInfoType@CPTLibTypeLibImpl@@VEAPEXIPEW4tagTYPEKIND@@@Z
+ 0005:4C1C ?GetTypeInfoOfGuid@CPTLibTypeLibImpl@@VEAPEXAFUGUID@@PEPEUITypeI
+ 0005:4DC6 ?GetLibAttr@CPTLibTypeLibImpl@@VEAPEXPEPEUtagTLIBATTR@@@Z
+ 0005:4F72 ?GetTypeComp@CPTLibTypeLibImpl@@VEAPEXPEPEUITypeComp@@@Z
+ 0005:50E6 ?GetDocumentation@CPTLibTypeLibImpl@@VEAPEXHPEPED0PEK0@Z
+ 0005:5550 ?IsName@CPTLibTypeLibImpl@@VEAPEXPEDKPEH@Z
+ 0005:57F8 ?FindName@CPTLibTypeLibImpl@@VEAPEXPEDKPEPEUITypeInfo@@PEJPEG@Z
+ 0005:5C6A ?ReleaseTLibAttr@CPTLibTypeLibImpl@@VEAXPEUtagTLIBATTR@@@Z
+ 0005:5C8E ?SysKind@CPTLibTypeLibImpl@@RECPEXXZ
+ 0005:5DE8 ?ReadLibAttr@@ZCPEXPEUIStream@@PEUtagTLIBATTR@@@Z
+ 0005:5F50 ?WriteLibAttr@@ZCPEXPEUIStream@@PEUtagTLIBATTR@@@Z
+ 0005:60C6 ??0CStubTypeLib@@BEC@XZ
+ 0005:610A ??1CStubTypeLib@@BEC@XZ
+ 0005:612E ?Create@CStubTypeLib@@TAPEXPEUIUnknown@@PEPEUIRpcStubBuffer@@@Z
+ 0005:61A2 ?QueryInterface@CStubTypeLib@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:620E ?AddRef@CStubTypeLib@@VEAKXZ
+ 0005:6230 ?Release@CStubTypeLib@@VEAKXZ
+ 0005:6286 ?Connect@CStubTypeLib@@VEAPEXPEUIUnknown@@@Z
+ 0005:62F4 ?Disconnect@CStubTypeLib@@VEAXXZ
+ 0005:6362 ?Invoke@CStubTypeLib@@VEAPEXPEUtagRPCOLEMESSAGE@@PEUIRpcChannelB
+ 0005:64DE ?IsIIDSupported@CStubTypeLib@@VEAPEUIRpcStubBuffer@@AFUGUID@@@Z
+ 0005:652E ?CountRefs@CStubTypeLib@@VEAKXZ
+ 0005:6576 ?GetTypeInfoCount@CStubTypeLib@@RECPEXXZ
+ 0005:65E8 ?GetTypeInfo@CStubTypeLib@@RECPEXXZ
+ 0005:66F4 ?GetTypeInfoType@CStubTypeLib@@RECPEXXZ
+ 0005:6800 ?GetTypeInfoOfGuid@CStubTypeLib@@RECPEXXZ
+ 0005:6908 ?GetLibAttr@CStubTypeLib@@RECPEXXZ
+ 0005:69E2 ?GetTypeComp@CStubTypeLib@@RECPEXXZ
+ 0005:6AAC ?GetDocumentation@CStubTypeLib@@RECPEXXZ
+ 0005:6E00 ?IsName@CStubTypeLib@@RECPEXXZ
+ 0005:6F8A ?FindName@CStubTypeLib@@RECPEXXZ
+ 0005:72DC ?SysKind@CStubTypeLib@@RECPEXXZ
+ 0005:738C ?DebugServerQueryInterface@CStubTypeLib@@VEAPEXPEPEX@Z
+ 0005:73B0 ?DebugServerRelease@CStubTypeLib@@VEAXPEX@Z
+ 0005:73BC ??0CProxTypeComp@@BEC@PEUIUnknown@@@Z
+ 0005:7428 ?Create@CProxTypeComp@@TAPEUIUnknown@@PEU2@@Z
+ 0005:7472 ??0CPTCompUnkImpl@@REC@PEVCProxTypeComp@@@Z
+ 0005:749C ?QueryInterface@CPTCompUnkImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:755C ?AddRef@CPTCompUnkImpl@@VEAKXZ
+ 0005:7582 ?Release@CPTCompUnkImpl@@VEAKXZ
+ 0005:75E8 ??0CPTCompProxImpl@@REC@PEVCProxTypeComp@@@Z
+ 0005:7612 ??1CPTCompProxImpl@@REC@XZ
+ 0005:7652 ?QueryInterface@CPTCompProxImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:7682 ?AddRef@CPTCompProxImpl@@VEAKXZ
+ 0005:76AC ?Release@CPTCompProxImpl@@VEAKXZ
+ 0005:76D6 ?Connect@CPTCompProxImpl@@VEAPEXPEUIRpcChannelBuffer@@@Z
+ 0005:7736 ?Disconnect@CPTCompProxImpl@@VEAXXZ
+ 0005:7782 ??0CPTCompTypeCompImpl@@REC@PEVCProxTypeComp@@@Z
+ 0005:77B2 ?QueryInterface@CPTCompTypeCompImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:77E6 ?AddRef@CPTCompTypeCompImpl@@VEAKXZ
+ 0005:7814 ?Release@CPTCompTypeCompImpl@@VEAKXZ
+ 0005:7842 ?Bind@CPTCompTypeCompImpl@@VEAPEXPEDKGPEPEUITypeInfo@@PEW4tagDES
+ 0005:7C84 ?BindType@CPTCompTypeCompImpl@@VEAPEXPEDKPEPEUITypeInfo@@PEPEUIT
+ 0005:7F08 ?SysKind@CPTCompTypeCompImpl@@RECPEXXZ
+ 0005:8062 ??0CStubTypeComp@@BEC@XZ
+ 0005:80A6 ??1CStubTypeComp@@BEC@XZ
+ 0005:80CA ?Create@CStubTypeComp@@TAPEXPEUIUnknown@@PEPEUIRpcStubBuffer@@@Z
+ 0005:813E ?QueryInterface@CStubTypeComp@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:81AA ?AddRef@CStubTypeComp@@VEAKXZ
+ 0005:81CC ?Release@CStubTypeComp@@VEAKXZ
+ 0005:8222 ?Connect@CStubTypeComp@@VEAPEXPEUIUnknown@@@Z
+ 0005:8290 ?Disconnect@CStubTypeComp@@VEAXXZ
+ 0005:82FE ?Invoke@CStubTypeComp@@VEAPEXPEUtagRPCOLEMESSAGE@@PEUIRpcChannel
+ 0005:8418 ?IsIIDSupported@CStubTypeComp@@VEAPEUIRpcStubBuffer@@AFUGUID@@@Z
+ 0005:8468 ?CountRefs@CStubTypeComp@@VEAKXZ
+ 0005:84B0 ?Bind@CStubTypeComp@@RECPEXXZ
+ 0005:87A8 ?BindType@CStubTypeComp@@RECPEXXZ
+ 0005:8906 ?SysKind@CStubTypeComp@@RECPEXXZ
+ 0005:89B6 ?DebugServerQueryInterface@CStubTypeComp@@VEAPEXPEPEX@Z
+ 0005:89DA ?DebugServerRelease@CStubTypeComp@@VEAXPEX@Z
+ 0005:89E6 ??0CStubSupportErrorInfo@@BEC@XZ
+ 0005:8A1C ??1CStubSupportErrorInfo@@BEC@XZ
+ 0005:8A40 ?Create@CStubSupportErrorInfo@@TAPEXPEUIUnknown@@PEPEUIRpcStubBu
+ 0005:8AB4 ?QueryInterface@CStubSupportErrorInfo@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:8B20 ?AddRef@CStubSupportErrorInfo@@VEAKXZ
+ 0005:8B42 ?Release@CStubSupportErrorInfo@@VEAKXZ
+ 0005:8B98 ?Connect@CStubSupportErrorInfo@@VEAPEXPEUIUnknown@@@Z
+ 0005:8C06 ?Disconnect@CStubSupportErrorInfo@@VEAXXZ
+ 0005:8D2C ?Invoke@CStubSupportErrorInfo@@VEAPEXPEUtagRPCOLEMESSAGE@@PEUIRp
+ 0005:8E0A ?IsIIDSupported@CStubSupportErrorInfo@@VEAPEUIRpcStubBuffer@@AFU
+ 0005:8E5A ?CountRefs@CStubSupportErrorInfo@@VEAKXZ
+ 0005:8EA2 ?DebugServerQueryInterface@CStubSupportErrorInfo@@VEAPEXPEPEX@Z
+ 0005:8EC6 ?DebugServerRelease@CStubSupportErrorInfo@@VEAXPEX@Z
+ 0005:8ED2 ??0CProxSupportErrorInfo@@BEC@PEUIUnknown@@@Z
+ 0005:8F3E ?Create@CProxSupportErrorInfo@@TAPEUIUnknown@@PEU2@@Z
+ 0005:8F88 ??0CPSupErrUnkImpl@@REC@PEVCProxSupportErrorInfo@@@Z
+ 0005:8FB2 ?QueryInterface@CPSupErrUnkImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:9084 ?AddRef@CPSupErrUnkImpl@@VEAKXZ
+ 0005:90AA ?Release@CPSupErrUnkImpl@@VEAKXZ
+ 0005:9110 ??0CPSupErrProxImpl@@REC@PEVCProxSupportErrorInfo@@@Z
+ 0005:913A ??1CPSupErrProxImpl@@REC@XZ
+ 0005:917A ?QueryInterface@CPSupErrProxImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:91AA ?AddRef@CPSupErrProxImpl@@VEAKXZ
+ 0005:91D4 ?Release@CPSupErrProxImpl@@VEAKXZ
+ 0005:91FE ?Connect@CPSupErrProxImpl@@VEAPEXPEUIRpcChannelBuffer@@@Z
+ 0005:9246 ?Disconnect@CPSupErrProxImpl@@VEAXXZ
+ 0005:9292 ??0CPSupErrSupImpl@@REC@PEVCProxSupportErrorInfo@@@Z
+ 0005:92BC ?QueryInterface@CPSupErrSupImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:92F0 ?AddRef@CPSupErrSupImpl@@VEAKXZ
+ 0005:931E ?Release@CPSupErrSupImpl@@VEAKXZ
+ 0005:934C ?InterfaceSupportsErrorInfo@CPSupErrSupImpl@@VEAPEXAFUGUID@@@Z
+ 0006:0000 SYSALLOCSTRING
+ 0006:003C SYSALLOCSTRINGLEN
+ 0006:01BC SYSREALLOCSTRING
+ 0006:021C SYSREALLOCSTRINGLEN
+ 0006:03CC SYSFREESTRING
+ 0006:051E SYSSTRINGLEN
+ 0006:0544 ERRSYSALLOCSTRING
+ 0006:058A ERRSYSALLOCSTRINGLEN
+ 0006:05BA ERRSTRINGCOPY
+ 0006:0608 ERRSTRINGCOPYNONULL
+ 0007:0000 DOINVOKEMETHOD
+ 0007:0080 _InvokePascal
+ 0007:01DB _InvokeCdecl
+ 0007:0332 ?Create@CDispTypeInfo@@TAPEXW4tagTYPEKIND@@PEUtagINTERFACEDATA@@
+ 0007:03B2 CREATEDISPTYPEINFO
+ 0007:0408 ??0CDispTypeInfo@@REC@XZ
+ 0007:0436 ?QueryInterface@CDispTypeInfo@@VEAPEXAFUGUID@@PEPEX@Z
+ 0007:04AA ?AddRef@CDispTypeInfo@@VEAKXZ
+ 0007:04CC ?Release@CDispTypeInfo@@VEAKXZ
+ 0007:050E ?GetTypeAttr@CDispTypeInfo@@VEAPEXPEPEUtagTYPEATTR@@@Z
+ 0007:060A ?GetTypeComp@CDispTypeInfo@@VEAPEXPEPEUITypeComp@@@Z
+ 0007:066A ?GetFuncDesc@CDispTypeInfo@@VEAPEXIPEPEUtagFUNCDESC@@@Z
+ 0007:085A ?GetVarDesc@CDispTypeInfo@@VEAPEXIPEPEUtagVARDESC@@@Z
+ 0007:086C ?GetNames@CDispTypeInfo@@VEAPEXJPEPEDIPEI@Z
+ 0007:09D6 ?GetRefTypeOfImplType@CDispTypeInfo@@VEAPEXIPEK@Z
+ 0007:0A02 ?GetImplTypeFlags@CDispTypeInfo@@VEAPEXIPEH@Z
+ 0007:0A14 ?GetIDsOfNames@CDispTypeInfo@@VEAPEXPEPEDIPEJ@Z
+ 0007:0CDA ?Invoke@CDispTypeInfo@@VEAPEXPEXJGPEUtagDISPPARAMS@@PEUtagVARIAN
+ 0007:0F88 ?AllocInvokeArgs@CDispTypeInfo@@BECPEXIPEPEUtagINVOKEARGS@@@Z
+ 0007:109C ?GetInvokeArgs@CDispTypeInfo@@BECPEXPEUtagMETHODDATA@@GPEUtagDIS
+ 0007:1304 ?ReleaseInvokeArgs@CDispTypeInfo@@BECXPEUtagINVOKEARGS@@@Z
+ 0007:13B0 ?GetDocumentation@CDispTypeInfo@@VEAPEXJPEPED0PEK0@Z
+ 0007:143C ?GetDllEntry@CDispTypeInfo@@VEAPEXJW4tagINVOKEKIND@@PEPED1PEG@Z
+ 0007:144E ?GetRefTypeInfo@CDispTypeInfo@@VEAPEXKPEPEUITypeInfo@@@Z
+ 0007:14C8 ?AddressOfMember@CDispTypeInfo@@VEAPEXJW4tagINVOKEKIND@@PEPEX@Z
+ 0007:14DA ?CreateInstance@CDispTypeInfo@@VEAPEXPEUIUnknown@@AFUGUID@@PEPEX
+ 0007:14EC ?GetMops@CDispTypeInfo@@VEAPEXJPEPED@Z
+ 0007:14FE ?GetContainingTypeLib@CDispTypeInfo@@VEAPEXPEPEUITypeLib@@PEI@Z
+ 0007:1510 ?ReleaseTypeAttr@CDispTypeInfo@@VEAXPEUtagTYPEATTR@@@Z
+ 0007:152A ?ReleaseFuncDesc@CDispTypeInfo@@VEAXPEUtagFUNCDESC@@@Z
+ 0007:155C ?ReleaseVarDesc@CDispTypeInfo@@VEAXPEUtagVARDESC@@@Z
+ 0007:1568 ?PmdataOfDispid@CDispTypeInfo@@BECPEXJGPEPEUtagMETHODDATA@@@Z
+ 0007:15DC CREATESTDDISPATCH
+ 0007:160A ??0CStdDisp@@REC@XZ
+ 0007:166A ?Create@CStdDisp@@TAPEXPEUIUnknown@@PEXPEUITypeInfo@@PEPEU2@@Z
+ 0007:1728 ??0CStdDispUnkImpl@@REC@PEVCStdDisp@@@Z
+ 0007:1752 ?QueryInterface@CStdDispUnkImpl@@VEAPEXAFUGUID@@PEPEX@Z
+ 0007:17D6 ?AddRef@CStdDispUnkImpl@@VEAKXZ
+ 0007:17FC ?Release@CStdDispUnkImpl@@VEAKXZ
+ 0007:1880 ?QueryInterface@CStdDisp@@VEAPEXAFUGUID@@PEPEX@Z
+ 0007:18B0 ?AddRef@CStdDisp@@VEAKXZ
+ 0007:18DA ?Release@CStdDisp@@VEAKXZ
+ 0007:1904 ?GetTypeInfoCount@CStdDisp@@VEAPEXPEI@Z
+ 0007:192E ?GetTypeInfo@CStdDisp@@VEAPEXIKPEPEUITypeInfo@@@Z
+ 0007:1978 ?GetIDsOfNames@CStdDisp@@VEAPEXAFUGUID@@PEPEDIKPEJ@Z
+ 0007:19C2 ?Invoke@CStdDisp@@VEAPEXJAFUGUID@@KGPEUtagDISPPARAMS@@PEUtagVARI
+ 0008:0000 ?GetPrimaryInterface@@ZCPEXPEUITypeInfo@@PEPEU1@@Z
+ 0008:0236 ??0CProxUniv@@REC@PEUIUnknown@@@Z
+ 0008:02CC ??1CProxUniv@@REC@XZ
+ 0008:0364 ?CanWeRemoteIt@@ZAPEXPEUITypeInfo@@PEGPEH@Z
+ 0008:0418 ?Create@CProxUniv@@TAPEXPEUIUnknown@@AFUGUID@@PEPEU2@@Z
+ 0008:0694 ?CacheFuncDescs@CProxUniv@@RECPEXPEUITypeInfo@@@Z
+ 0008:087A ?QueryInterface@CPriv@CProxUniv@@VEAPEXAFUGUID@@PEPEX@Z
+ 0008:093A ?AddRef@CPriv@CProxUniv@@VEAKXZ
+ 0008:095C ?Release@CPriv@CProxUniv@@VEAKXZ
+ 0008:09BA ?Connect@CPriv@CProxUniv@@VEAPEXPEUIRpcChannelBuffer@@@Z
+ 0008:0A2E ?Disconnect@CPriv@CProxUniv@@VEAXXZ
+ 0008:0A82 ?PSInit@CProxUniv@@RECPEXXZ
+ 0008:0C4C PROXYMETHOD
+ 0008:12E2 ??0CStubUniv@@BEC@XZ
+ 0008:1342 ??1CStubUniv@@BEC@XZ
+ 0008:1366 ?Create@CStubUniv@@TAPEXPEUIUnknown@@AFUGUID@@PEPEUIRpcStubBuffe
+ 0008:13FE ?QueryInterface@CStubUniv@@VEAPEXAFUGUID@@PEPEX@Z
+ 0008:146A ?AddRef@CStubUniv@@VEAKXZ
+ 0008:148C ?Release@CStubUniv@@VEAKXZ
+ 0008:14E2 ?Connect@CStubUniv@@VEAPEXPEUIUnknown@@@Z
+ 0008:1552 ?Disconnect@CStubUniv@@VEAXXZ
+ 0008:15C0 ?Invoke@CStubUniv@@VEAPEXPEUtagRPCOLEMESSAGE@@PEUIRpcChannelBuff
+ 0008:17D6 ?IsIIDSupported@CStubUniv@@VEAPEUIRpcStubBuffer@@AFUGUID@@@Z
+ 0008:1828 ?CountRefs@CStubUniv@@VEAKXZ
+ 0008:1870 ?DebugServerQueryInterface@CStubUniv@@VEAPEXPEPEX@Z
+ 0008:1894 ?DebugServerRelease@CStubUniv@@VEAXPEX@Z
+ 0008:18A0 ?PSInit@CStubUniv@@RECPEXXZ
+ 0008:19C8 ?DispatchMethod@CStubUniv@@RECPEXH@Z
+ 0008:1EA6 ?VarVtOfIface@@ZAPEXPEUITypeInfo@@PEUtagTYPEATTR@@PEGPEUGUID@@@Z
+ 0008:1EFE ?VarVtOfUDT@@ZAPEXPEUITypeInfo@@PEUtagTYPEDESC@@PEGPEUGUID@@@Z
+ 0008:20C2 ?VarVtOfTypeDesc@@ZAPEXPEUITypeInfo@@PEUtagTYPEDESC@@PEGPEUGUID@
+ 0008:22BE ?SzLibIdOfIID@@ZAPEXAFUGUID@@PEDJ@Z
+ 0008:2360 ?FIsLCID@@ZAHPED@Z
+ 0008:23CA ?GetTypeInfoOfIID@@ZAPEXAFUGUID@@PEPEUITypeInfo@@@Z
+ 0008:273C _UnivQueryInterface
+ 0008:276C _UnivAddRef
+ 0008:2796 _UnivRelease
+ 0008:27C0 _UnivGetTypeInfoCount
+ 0008:27EE _UnivGetTypeInfo
+ 0008:2820 _UnivGetIDsOfNames
+ 0008:2864 _UnivInvoke
+ 0008:28BA ?UM3@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:28D8 ?UM4@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:28F6 ?UM5@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2914 ?UM6@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2932 ?UM7@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2950 ?UM8@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:296E ?UM9@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:298C ?UM10@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:29AA ?UM11@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:29C8 ?UM12@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:29E6 ?UM13@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2A04 ?UM14@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2A22 ?UM15@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2A40 ?UM16@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2A5E ?UM17@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2A7C ?UM18@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2A9A ?UM19@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2AB8 ?UM20@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2AD6 ?UM21@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2AF4 ?UM22@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2B12 ?UM23@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2B30 ?UM24@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2B4E ?UM25@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2B6C ?UM26@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2B8A ?UM27@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2BA8 ?UM28@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2BC6 ?UM29@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2BE4 ?UM30@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2C02 ?UM31@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2C20 ?UM32@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2C3E ?UM33@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2C5C ?UM34@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2C7A ?UM35@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2C98 ?UM36@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2CB6 ?UM37@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2CD4 ?UM38@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2CF2 ?UM39@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2D10 ?UM40@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2D2E ?UM41@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2D4C ?UM42@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2D6A ?UM43@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2D88 ?UM44@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2DA6 ?UM45@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2DC4 ?UM46@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2DE2 ?UM47@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2E00 ?UM48@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2E1E ?UM49@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2E3C ?UM50@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2E5A ?UM51@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2E78 ?UM52@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2E96 ?UM53@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2EB4 ?UM54@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2ED2 ?UM55@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2EF0 ?UM56@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2F0E ?UM57@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2F2C ?UM58@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2F4A ?UM59@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2F68 ?UM60@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2F86 ?UM61@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2FA4 ?UM62@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2FC2 ?UM63@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2FE0 ?UM64@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:2FFE ?UM65@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:301C ?UM66@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:303A ?UM67@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3058 ?UM68@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3076 ?UM69@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3094 ?UM70@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:30B2 ?UM71@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:30D0 ?UM72@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:30EE ?UM73@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:310C ?UM74@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:312A ?UM75@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3148 ?UM76@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3166 ?UM77@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3184 ?UM78@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:31A2 ?UM79@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:31C0 ?UM80@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:31DE ?UM81@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:31FC ?UM82@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:321A ?UM83@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3238 ?UM84@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3256 ?UM85@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3274 ?UM86@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3292 ?UM87@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:32B0 ?UM88@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:32CE ?UM89@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:32EC ?UM90@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:330A ?UM91@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3328 ?UM92@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3346 ?UM93@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3364 ?UM94@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3382 ?UM95@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:33A0 ?UM96@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:33BE ?UM97@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:33DC ?UM98@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:33FA ?UM99@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3418 ?UM100@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3436 ?UM101@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3454 ?UM102@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3472 ?UM103@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3490 ?UM104@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:34AE ?UM105@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:34CC ?UM106@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:34EA ?UM107@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3508 ?UM108@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3526 ?UM109@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3544 ?UM110@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3562 ?UM111@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3580 ?UM112@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:359E ?UM113@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:35BC ?UM114@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:35DA ?UM115@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:35F8 ?UM116@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3616 ?UM117@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3634 ?UM118@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3652 ?UM119@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3670 ?UM120@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:368E ?UM121@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:36AC ?UM122@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:36CA ?UM123@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:36E8 ?UM124@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3706 ?UM125@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3724 ?UM126@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3742 ?UM127@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3760 ?UM128@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3780 ?UM129@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:37A0 ?UM130@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:37C0 ?UM131@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:37E0 ?UM132@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3800 ?UM133@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3820 ?UM134@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3840 ?UM135@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3860 ?UM136@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3880 ?UM137@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:38A0 ?UM138@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:38C0 ?UM139@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:38E0 ?UM140@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3900 ?UM141@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3920 ?UM142@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3940 ?UM143@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3960 ?UM144@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3980 ?UM145@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:39A0 ?UM146@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:39C0 ?UM147@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:39E0 ?UM148@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3A00 ?UM149@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3A20 ?UM150@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3A40 ?UM151@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3A60 ?UM152@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3A80 ?UM153@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3AA0 ?UM154@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3AC0 ?UM155@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3AE0 ?UM156@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3B00 ?UM157@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3B20 ?UM158@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3B40 ?UM159@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3B60 ?UM160@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3B80 ?UM161@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3BA0 ?UM162@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3BC0 ?UM163@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3BE0 ?UM164@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3C00 ?UM165@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3C20 ?UM166@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3C40 ?UM167@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3C60 ?UM168@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3C80 ?UM169@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3CA0 ?UM170@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3CC0 ?UM171@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3CE0 ?UM172@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3D00 ?UM173@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3D20 ?UM174@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3D40 ?UM175@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3D60 ?UM176@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3D80 ?UM177@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3DA0 ?UM178@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3DC0 ?UM179@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3DE0 ?UM180@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3E00 ?UM181@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3E20 ?UM182@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3E40 ?UM183@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3E60 ?UM184@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3E80 ?UM185@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3EA0 ?UM186@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3EC0 ?UM187@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3EE0 ?UM188@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3F00 ?UM189@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3F20 ?UM190@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3F40 ?UM191@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3F60 ?UM192@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3F80 ?UM193@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3FA0 ?UM194@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3FC0 ?UM195@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:3FE0 ?UM196@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4000 ?UM197@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4020 ?UM198@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4040 ?UM199@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4060 ?UM200@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4080 ?UM201@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:40A0 ?UM202@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:40C0 ?UM203@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:40E0 ?UM204@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4100 ?UM205@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4120 ?UM206@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4140 ?UM207@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4160 ?UM208@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4180 ?UM209@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:41A0 ?UM210@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:41C0 ?UM211@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:41E0 ?UM212@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4200 ?UM213@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4220 ?UM214@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4240 ?UM215@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4260 ?UM216@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4280 ?UM217@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:42A0 ?UM218@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:42C0 ?UM219@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:42E0 ?UM220@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4300 ?UM221@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4320 ?UM222@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4340 ?UM223@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4360 ?UM224@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4380 ?UM225@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:43A0 ?UM226@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:43C0 ?UM227@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:43E0 ?UM228@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4400 ?UM229@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4420 ?UM230@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4440 ?UM231@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4460 ?UM232@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4480 ?UM233@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:44A0 ?UM234@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:44C0 ?UM235@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:44E0 ?UM236@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4500 ?UM237@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4520 ?UM238@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4540 ?UM239@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4560 ?UM240@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4580 ?UM241@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:45A0 ?UM242@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:45C0 ?UM243@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:45E0 ?UM244@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4600 ?UM245@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4620 ?UM246@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4640 ?UM247@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4660 ?UM248@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4680 ?UM249@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:46A0 ?UM250@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:46C0 ?UM251@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:46E0 ?UM252@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4700 ?UM253@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4720 ?UM254@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4740 ?UM255@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4760 ?UM256@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4780 ?UM257@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:47A0 ?UM258@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:47C0 ?UM259@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:47E0 ?UM260@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4800 ?UM261@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4820 ?UM262@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4840 ?UM263@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4860 ?UM264@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4880 ?UM265@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:48A0 ?UM266@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:48C0 ?UM267@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:48E0 ?UM268@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4900 ?UM269@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4920 ?UM270@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4940 ?UM271@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4960 ?UM272@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4980 ?UM273@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:49A0 ?UM274@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:49C0 ?UM275@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:49E0 ?UM276@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4A00 ?UM277@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4A20 ?UM278@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4A40 ?UM279@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4A60 ?UM280@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4A80 ?UM281@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4AA0 ?UM282@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4AC0 ?UM283@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4AE0 ?UM284@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4B00 ?UM285@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4B20 ?UM286@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4B40 ?UM287@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4B60 ?UM288@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4B80 ?UM289@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4BA0 ?UM290@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4BC0 ?UM291@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4BE0 ?UM292@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4C00 ?UM293@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4C20 ?UM294@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4C40 ?UM295@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4C60 ?UM296@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4C80 ?UM297@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4CA0 ?UM298@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4CC0 ?UM299@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4CE0 ?UM300@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4D00 ?UM301@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4D20 ?UM302@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4D40 ?UM303@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4D60 ?UM304@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4D80 ?UM305@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4DA0 ?UM306@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4DC0 ?UM307@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4DE0 ?UM308@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4E00 ?UM309@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4E20 ?UM310@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4E40 ?UM311@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4E60 ?UM312@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4E80 ?UM313@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4EA0 ?UM314@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4EC0 ?UM315@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4EE0 ?UM316@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4F00 ?UM317@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4F20 ?UM318@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4F40 ?UM319@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4F60 ?UM320@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4F80 ?UM321@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4FA0 ?UM322@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4FC0 ?UM323@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:4FE0 ?UM324@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5000 ?UM325@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5020 ?UM326@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5040 ?UM327@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5060 ?UM328@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5080 ?UM329@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:50A0 ?UM330@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:50C0 ?UM331@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:50E0 ?UM332@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5100 ?UM333@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5120 ?UM334@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5140 ?UM335@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5160 ?UM336@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5180 ?UM337@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:51A0 ?UM338@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:51C0 ?UM339@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:51E0 ?UM340@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5200 ?UM341@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5220 ?UM342@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5240 ?UM343@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5260 ?UM344@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5280 ?UM345@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:52A0 ?UM346@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:52C0 ?UM347@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:52E0 ?UM348@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5300 ?UM349@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5320 ?UM350@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5340 ?UM351@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5360 ?UM352@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5380 ?UM353@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:53A0 ?UM354@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:53C0 ?UM355@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:53E0 ?UM356@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5400 ?UM357@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5420 ?UM358@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5440 ?UM359@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5460 ?UM360@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5480 ?UM361@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:54A0 ?UM362@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:54C0 ?UM363@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:54E0 ?UM364@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5500 ?UM365@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5520 ?UM366@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5540 ?UM367@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5560 ?UM368@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5580 ?UM369@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:55A0 ?UM370@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:55C0 ?UM371@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:55E0 ?UM372@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5600 ?UM373@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5620 ?UM374@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5640 ?UM375@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5660 ?UM376@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5680 ?UM377@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:56A0 ?UM378@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:56C0 ?UM379@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:56E0 ?UM380@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5700 ?UM381@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5720 ?UM382@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5740 ?UM383@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5760 ?UM384@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5780 ?UM385@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:57A0 ?UM386@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:57C0 ?UM387@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:57E0 ?UM388@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5800 ?UM389@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5820 ?UM390@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5840 ?UM391@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5860 ?UM392@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5880 ?UM393@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:58A0 ?UM394@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:58C0 ?UM395@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:58E0 ?UM396@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5900 ?UM397@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5920 ?UM398@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5940 ?UM399@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5960 ?UM400@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5980 ?UM401@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:59A0 ?UM402@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:59C0 ?UM403@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:59E0 ?UM404@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5A00 ?UM405@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5A20 ?UM406@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5A40 ?UM407@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5A60 ?UM408@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5A80 ?UM409@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5AA0 ?UM410@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5AC0 ?UM411@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5AE0 ?UM412@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5B00 ?UM413@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5B20 ?UM414@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5B40 ?UM415@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5B60 ?UM416@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5B80 ?UM417@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5BA0 ?UM418@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5BC0 ?UM419@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5BE0 ?UM420@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5C00 ?UM421@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5C20 ?UM422@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5C40 ?UM423@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5C60 ?UM424@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5C80 ?UM425@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5CA0 ?UM426@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5CC0 ?UM427@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5CE0 ?UM428@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5D00 ?UM429@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5D20 ?UM430@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5D40 ?UM431@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5D60 ?UM432@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5D80 ?UM433@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5DA0 ?UM434@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5DC0 ?UM435@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5DE0 ?UM436@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5E00 ?UM437@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5E20 ?UM438@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5E40 ?UM439@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5E60 ?UM440@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5E80 ?UM441@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5EA0 ?UM442@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5EC0 ?UM443@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5EE0 ?UM444@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5F00 ?UM445@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5F20 ?UM446@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5F40 ?UM447@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5F60 ?UM448@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5F80 ?UM449@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5FA0 ?UM450@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5FC0 ?UM451@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:5FE0 ?UM452@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6000 ?UM453@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6020 ?UM454@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6040 ?UM455@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6060 ?UM456@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6080 ?UM457@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:60A0 ?UM458@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:60C0 ?UM459@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:60E0 ?UM460@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6100 ?UM461@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6120 ?UM462@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6140 ?UM463@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6160 ?UM464@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6180 ?UM465@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:61A0 ?UM466@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:61C0 ?UM467@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:61E0 ?UM468@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6200 ?UM469@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6220 ?UM470@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6240 ?UM471@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6260 ?UM472@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6280 ?UM473@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:62A0 ?UM474@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:62C0 ?UM475@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:62E0 ?UM476@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6300 ?UM477@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6320 ?UM478@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6340 ?UM479@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6360 ?UM480@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6380 ?UM481@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:63A0 ?UM482@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:63C0 ?UM483@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:63E0 ?UM484@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6400 ?UM485@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6420 ?UM486@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6440 ?UM487@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6460 ?UM488@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6480 ?UM489@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:64A0 ?UM490@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:64C0 ?UM491@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:64E0 ?UM492@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6500 ?UM493@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6520 ?UM494@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6540 ?UM495@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6560 ?UM496@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6580 ?UM497@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:65A0 ?UM498@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:65C0 ?UM499@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:65E0 ?UM500@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6600 ?UM501@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6620 ?UM502@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6640 ?UM503@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6660 ?UM504@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6680 ?UM505@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:66A0 ?UM506@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:66C0 ?UM507@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:66E0 ?UM508@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6700 ?UM509@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6720 ?UM510@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6740 ?UM511@@ZAPEXPEVCProxUniv@@ZZ
+ 0008:6760 ?UM512@@ZAPEXPEVCProxUniv@@ZZ
+ 0009:0000 WEP
+ 0009:003C __STUBWEP
+ 000A:0004 rsrvptrs
+ 000A:0010 _g_hinstDLL
+ 000A:007C ?g_cbVtSizes@@3QEEE
+ 000A:008E ?g_cbFtype@@3QEEE
+ 000A:00EE _g_rgpfnUnk
+ 000A:08F2 _g_rgpfnDisp
+ 000A:10F6 ?g_cfnUnk@@3JE
+ 000A:10FA ?g_cfnDisp@@3JE
+ 000A:10FE _g_S_OK
+ 000A:1102 _g_E_INVALIDARG
+ 000A:1106 _mpmmdd
+ 000A:1120 _dblSecPerDay
+ 000A:118C _g_rgszPolishMonth2
+ 000A:120E _g_rgszRussianMonth2
+ 000A:1334 _g_dpsNext
+ 000A:1426 _g_fDay31th
+ 000A:144C ?pstrInf@@3QEDE
+ 000A:1450 ?pstrInd@@3QEDE
+ 000A:1454 ?pstrNan@@3QEDE
+ 000A:1458 ?ulPower10@@3QEKE
+ 000A:14AA _g_rgfdescIdldesc
+ 000A:14DA _g_rgfdescElemdesc
+ 000A:150A _g_rgfdescTypeattr
+ 000A:160A _g_rgfdescFuncdesc
+ 000A:16AA _g_rgfdescVardesc
+ 000A:16FA _STKHQQ
+ 000A:16FC __hModule
+ 000A:16FE __wDataSeg
+ 000A:1700 __wHeapSize
+ 000A:1702 __lpszCmdLine
+ 000A:1706 __dllinit
+ 000A:1707 _aseglo
+ 000A:1709 _aseghi
+ 000A:170B ___aDBswpflg
+ 000A:170D ___aDBrterr
+ 000A:1710 __ctype_
+ 000A:1710 __ctype
+ 000A:1826 __aintdiv
+ 000A:182A __fac
+ 000A:1834 _errno
+ 000A:1836 __umaskval
+ 000A:1838 __winver
+ 000A:1838 __winminor
+ 000A:1839 __winmajor
+ 000A:183A __osminor
+ 000A:183A __osver
+ 000A:183B __osmajor
+ 000A:183C __osversion
+ 000A:183E __osmode
+ 000A:183F __cpumode
+ 000A:1840 __oserr
+ 000A:1840 __doserrno
+ 000A:1842 __nfile
+ 000A:1844 __osfile
+ 000A:1858 ___argc
+ 000A:185A ___argv
+ 000A:185E __environ
+ 000A:1862 __pgmptr
+ 000A:1867 __child
+ 000A:1869 __exitflag
+ 000A:186A __adbgmsg
+ 000A:186E __cfltcvt_tab
+ 000A:188A __sigintseg
+ 000A:188C __sigintoff
+ 000A:188E __asizeC
+ 000A:188F __asizeD
+ 000A:190C __amblksiz
+ 000A:190E __pnhFarHeap
+ 000A:191C __fheap
+ 000A:192A ?ll0@?1??Rewind@@ZAPEXPEUIStream@@@Z@4U_LARGE_INTEGER@@B
+ 000A:1934 __fpinit
+ 000A:1DB0 _edata
+ 000A:1DB0 _g_fbstpImplemented
+ 000A:1DB0 __edata
+ 000A:1DB2 _g_pinfoProcess
+ 000A:1DB6 _uProcessID
+ 000A:1DE0 _g_NumInfo
+ 000A:1DFA _g_DateInfo
+ 000A:2462 __mbac
+ 000A:246A _end
+ 000A:246A __end
+ 0000:4000 Abs FJARQQ
+ 0000:5C32 Abs FIDRQQ
+ 0000:8000 Abs FJSRQQ
+ 0000:A23D Abs FIWRQQ
+ 0000:C000 Abs FJCRQQ
+ 0000:FE32 Abs FIARQQ
+
+Program entry point at 0001:12a8
diff --git a/private/ole32/olethunk/bin16/ole2disp.sym b/private/ole32/olethunk/bin16/ole2disp.sym
new file mode 100644
index 000000000..04121d1f3
--- /dev/null
+++ b/private/ole32/olethunk/bin16/ole2disp.sym
Binary files differ
diff --git a/private/ole32/olethunk/bin16/ole2disp.txt b/private/ole32/olethunk/bin16/ole2disp.txt
new file mode 100644
index 000000000..6f1c4520b
--- /dev/null
+++ b/private/ole32/olethunk/bin16/ole2disp.txt
@@ -0,0 +1,6 @@
+These versions of OLE Automation are the WOW-enabled versions (distinct
+from the re-distributable win31/win32s versions). This set of files was
+taken from OLE Automation drop 102194.622 on \\blw\drop2 (kjashbcd)
+\ole2auto\oa94.
+
+DougF
diff --git a/private/ole32/olethunk/bin16/ole2nls.map b/private/ole32/olethunk/bin16/ole2nls.map
new file mode 100644
index 000000000..72a171c14
--- /dev/null
+++ b/private/ole32/olethunk/bin16/ole2nls.map
@@ -0,0 +1,652 @@
+
+ OLE2NLS
+
+ Start Length Name Class
+ 0001:0000 02DB8H _TEXT CODE
+ 0002:0000 00B86H NLS0405_TEXT CODE
+ 0003:0000 00B8EH NLS0406_TEXT CODE
+ 0004:0000 0037EH NLS0407_TEXT CODE
+ 0005:0000 00BC0H NLS0409_TEXT CODE
+ 0006:0000 00BF0H NLS040a_TEXT CODE
+ 0007:0000 003AAH NLS040b_TEXT CODE
+ 0008:0000 00386H NLS040c_TEXT CODE
+ 0009:0000 00C12H NLS040e_TEXT CODE
+ 000A:0000 00388H NLS0410_TEXT CODE
+ 000B:0000 00388H NLS0413_TEXT CODE
+ 000C:0000 0037AH NLS0414_TEXT CODE
+ 000D:0000 00B74H NLS0415_TEXT CODE
+ 000E:0000 003B8H NLS0416_TEXT CODE
+ 000F:0000 00B74H NLS0419_TEXT CODE
+ 0010:0000 00B84H NLS041b_TEXT CODE
+ 0011:0000 00B8EH NLS041d_TEXT CODE
+ 0012:0000 00386H NLS0807_TEXT CODE
+ 0013:0000 0039CH NLS0809_TEXT CODE
+ 0014:0000 003A0H NLS080a_TEXT CODE
+ 0015:0000 00392H NLS080c_TEXT CODE
+ 0016:0000 003A0H NLS0810_TEXT CODE
+ 0017:0000 00384H NLS0813_TEXT CODE
+ 0018:0000 003BCH NLS0816_TEXT CODE
+ 0019:0000 00386H NLS0c07_TEXT CODE
+ 001A:0000 00398H NLS0c09_TEXT CODE
+ 001B:0000 00BCAH NLS0c0a_TEXT CODE
+ 001C:0000 0038CH NLS0c0c_TEXT CODE
+ 001D:0000 0038CH NLS1009_TEXT CODE
+ 001E:0000 00398H NLS100c_TEXT CODE
+ 001F:0000 003A2H NLS1409_TEXT CODE
+ 0020:0000 00986H NLS0404_TEXT CODE
+ 0021:0000 0481AH NLS0411_TEXT CODE
+ 0022:0000 08088H NLS0412_TEXT CODE
+ 0023:0000 00596H NLS0804_TEXT CODE
+ 0024:0000 0038EH NLS1809_TEXT CODE
+ 0025:0000 00382H NLS0814_TEXT CODE
+ 0026:0000 00B8EH NLS041f_TEXT CODE
+ 0027:0000 00BB2H NLS040f_TEXT CODE
+ 0028:0000 00BAAH NLS0408_TEXT CODE
+ 0029:0000 0038EH NLS0403_TEXT CODE
+ 002A:0000 003B8H NLS0429_TEXT CODE
+ 002B:0000 00B60H NLS040d_TEXT CODE
+ 002C:0000 00BC6H NLS0401_TEXT CODE
+ 002D:0000 00398H NLS0801_TEXT CODE
+ 002E:0000 00396H NLS0c01_TEXT CODE
+ 002F:0000 0039CH NLS1001_TEXT CODE
+ 0030:0000 0039AH NLS1401_TEXT CODE
+ 0031:0000 003A2H NLS1801_TEXT CODE
+ 0032:0000 00394H NLS1c01_TEXT CODE
+ 0033:0000 00396H NLS2001_TEXT CODE
+ 0034:0000 0039CH NLS2401_TEXT CODE
+ 0035:0000 003BAH NLS2801_TEXT CODE
+ 0036:0000 003BAH NLS2c01_TEXT CODE
+ 0037:0000 003BEH NLS3001_TEXT CODE
+ 0038:0000 0039CH NLS3401_TEXT CODE
+ 0039:0000 003AEH NLS3801_TEXT CODE
+ 003A:0000 003A2H NLS3c01_TEXT CODE
+ 003B:0000 0039AH NLS4001_TEXT CODE
+ 003C:0000 00000H NLS0424_TEXT CODE
+ 003C:0000 00010H NULL BEGDATA
+ 003C:0010 007E8H _DATA DATA
+ 003C:07F8 00000H CDATA DATA
+ 003C:07F8 00000H CONST CONST
+ 003C:07F8 00022H _BSS BSS
+ 003C:0820 00005H c_common BSS
+
+ Origin Group
+ 003C:0 DGROUP
+
+ Address Export Alias
+
+ 0001:1034 COMPARESTRINGA COMPARESTRINGA
+ 0001:0726 GETLOCALEINFOA GETLOCALEINFOA
+ 0001:2382 GETSTRINGTYPEA GETSTRINGTYPEA
+ 0001:0716 GETSYSTEMDEFAULTLANGID GETSYSTEMDEFAULTLANGID
+ 0001:06F6 GETSYSTEMDEFAULTLCID GETSYSTEMDEFAULTLCID
+ 0001:0706 GETUSERDEFAULTLANGID GETUSERDEFAULTLANGID
+ 0001:06E6 GETUSERDEFAULTLCID GETUSERDEFAULTLCID
+ 0001:1F6C LCMAPSTRINGA LCMAPSTRINGA
+ 0001:002C LibMain LibMain
+ 0001:2582 NOTIFYWINDOWPROC NOTIFYWINDOWPROC
+ 0001:25D0 REGISTERNLSINFOCHANGED REGISTERNLSINFOCHANGED
+ 0001:0044 WEP WEP
+
+ Address Publics by Name
+
+ 0000:0000 Imp ANSIUPPER (USER.431)
+ 0000:0000 Imp ANSIUPPERBUFF (USER.437)
+ 0001:1034 COMPARESTRINGA
+ 0000:0000 Imp CREATEWINDOW (USER.41)
+ 0000:0000 Imp DEFWINDOWPROC (USER.107)
+ 0000:0000 Imp DESTROYWINDOW (USER.53)
+ 0000:0000 Imp GETCLASSINFO (USER.404)
+ 0001:0726 GETLOCALEINFOA
+ 0000:0000 Imp GETPROFILESTRING (KERNEL.58)
+ 0001:2382 GETSTRINGTYPEA
+ 0001:0716 GETSYSTEMDEFAULTLANGID
+ 0001:06F6 GETSYSTEMDEFAULTLCID
+ 0001:0706 GETUSERDEFAULTLANGID
+ 0001:06E6 GETUSERDEFAULTLCID
+ 0000:0000 Imp GETWINDOWWORD (USER.133)
+ 0000:0000 Imp ISWINDOW (USER.47)
+ 0001:005C LCIDFROMWININI
+ 0001:1F6C LCMAPSTRINGA
+ 0001:0010 LibEntry
+ 0001:002C LibMain
+ 0000:0000 Imp LocalInit (KERNEL.4)
+ 0000:0000 Imp LSTRCMP (USER.430)
+ 0000:0000 Imp LSTRLEN (KERNEL.90)
+ 0001:2582 NOTIFYWINDOWPROC
+ 0000:0000 Imp REGISTERCLASS (USER.57)
+ 0001:25D0 REGISTERNLSINFOCHANGED
+ 003C:0004 rsrvptrs
+ 0001:0044 WEP
+ 003C:07F2 _aseghi
+ 003C:07F0 _aseglo
+ 003C:0824 _bFEflag
+ 0001:0BAA _CompareStringJ
+ 0001:0E74 _CompareStringKTP
+ 0001:1366 _CreateSortKeyJ
+ 0001:168A _CreateSortKeyKTP
+ 0001:2916 _DefCompareStringA
+ 0001:254C _DestroyHiddenWindow
+ 003C:07F8 _edata
+ 003C:0825 _end
+ 0001:248E _fCreateHiddenWindow
+ 0001:093C _GetSortWeightJ
+ 0001:0D3C _GetSortWeightKTP
+ 0001:20DE _GetStringTypeJ
+ 0001:2206 _GetStringTypeKTP
+ 003C:0820 _g_dwFlags
+ 003C:06C2 _g_hinstDLL
+ 003C:06BA _g_lcidSystem
+ 003C:06B4 _g_pnls
+ 003C:06B6 _g_pstrinfo
+ 002C:09B4 _g_rglcinfo0401
+ 0029:017C _g_rglcinfo0403
+ 0020:0780 _g_rglcinfo0404
+ 0002:0974 _g_rglcinfo0405
+ 0003:097C _g_rglcinfo0406
+ 0004:016C _g_rglcinfo0407
+ 0028:0998 _g_rglcinfo0408
+ 0005:09AE _g_rglcinfo0409
+ 0006:09DE _g_rglcinfo040a
+ 0007:0198 _g_rglcinfo040b
+ 0008:0174 _g_rglcinfo040c
+ 002B:094E _g_rglcinfo040d
+ 0009:0A00 _g_rglcinfo040e
+ 0027:09A0 _g_rglcinfo040f
+ 000A:0176 _g_rglcinfo0410
+ 0021:45FE _g_rglcinfo0411
+ 0022:7E82 _g_rglcinfo0412
+ 000B:0176 _g_rglcinfo0413
+ 000C:0168 _g_rglcinfo0414
+ 000D:0962 _g_rglcinfo0415
+ 000E:01A6 _g_rglcinfo0416
+ 000F:0962 _g_rglcinfo0419
+ 0010:0972 _g_rglcinfo041b
+ 0011:097C _g_rglcinfo041d
+ 0026:097C _g_rglcinfo041f
+ 002A:01A6 _g_rglcinfo0429
+ 002D:0186 _g_rglcinfo0801
+ 0023:0390 _g_rglcinfo0804
+ 0012:0174 _g_rglcinfo0807
+ 0013:018A _g_rglcinfo0809
+ 0014:018E _g_rglcinfo080a
+ 0015:0180 _g_rglcinfo080c
+ 0016:018E _g_rglcinfo0810
+ 0017:0172 _g_rglcinfo0813
+ 0025:0170 _g_rglcinfo0814
+ 0018:01AA _g_rglcinfo0816
+ 002E:0184 _g_rglcinfo0c01
+ 0019:0174 _g_rglcinfo0c07
+ 001A:0186 _g_rglcinfo0c09
+ 001B:09B8 _g_rglcinfo0c0a
+ 001C:017A _g_rglcinfo0c0c
+ 002F:018A _g_rglcinfo1001
+ 001D:017A _g_rglcinfo1009
+ 001E:0186 _g_rglcinfo100c
+ 0030:0188 _g_rglcinfo1401
+ 001F:0190 _g_rglcinfo1409
+ 0031:0190 _g_rglcinfo1801
+ 0024:017C _g_rglcinfo1809
+ 0032:0182 _g_rglcinfo1c01
+ 0033:0184 _g_rglcinfo2001
+ 0034:018A _g_rglcinfo2401
+ 0035:01A8 _g_rglcinfo2801
+ 0036:01A8 _g_rglcinfo2c01
+ 0037:01AC _g_rglcinfo3001
+ 0038:018A _g_rglcinfo3401
+ 0039:019C _g_rglcinfo3801
+ 003A:0190 _g_rglcinfo3c01
+ 003B:0188 _g_rglcinfo4001
+ 002C:0BA8 _g_strinfo0401
+ 0029:0370 _g_strinfo0403
+ 0020:0974 _g_strinfo0404
+ 0002:0B68 _g_strinfo0405
+ 0003:0B70 _g_strinfo0406
+ 0004:0360 _g_strinfo0407
+ 0028:0B8C _g_strinfo0408
+ 0005:0BA2 _g_strinfo0409
+ 0006:0BD2 _g_strinfo040a
+ 0007:038C _g_strinfo040b
+ 0008:0368 _g_strinfo040c
+ 002B:0B42 _g_strinfo040d
+ 0009:0BF4 _g_strinfo040e
+ 0027:0B94 _g_strinfo040f
+ 000A:036A _g_strinfo0410
+ 0021:47F2 _g_strinfo0411
+ 0022:8076 _g_strinfo0412
+ 000B:036A _g_strinfo0413
+ 000C:035C _g_strinfo0414
+ 000D:0B56 _g_strinfo0415
+ 000E:039A _g_strinfo0416
+ 000F:0B56 _g_strinfo0419
+ 0010:0B66 _g_strinfo041b
+ 0011:0B70 _g_strinfo041d
+ 0026:0B70 _g_strinfo041f
+ 002A:039A _g_strinfo0429
+ 002D:037A _g_strinfo0801
+ 0023:0584 _g_strinfo0804
+ 0012:0368 _g_strinfo0807
+ 0013:037E _g_strinfo0809
+ 0014:0382 _g_strinfo080a
+ 0015:0374 _g_strinfo080c
+ 0016:0382 _g_strinfo0810
+ 0017:0366 _g_strinfo0813
+ 0025:0364 _g_strinfo0814
+ 0018:039E _g_strinfo0816
+ 002E:0378 _g_strinfo0c01
+ 0019:0368 _g_strinfo0c07
+ 001A:037A _g_strinfo0c09
+ 001B:0BAC _g_strinfo0c0a
+ 001C:036E _g_strinfo0c0c
+ 002F:037E _g_strinfo1001
+ 001D:036E _g_strinfo1009
+ 001E:037A _g_strinfo100c
+ 0030:037C _g_strinfo1401
+ 001F:0384 _g_strinfo1409
+ 0031:0384 _g_strinfo1801
+ 0024:0370 _g_strinfo1809
+ 0032:0376 _g_strinfo1c01
+ 0033:0378 _g_strinfo2001
+ 0034:037E _g_strinfo2401
+ 0035:039C _g_strinfo2801
+ 0036:039C _g_strinfo2c01
+ 0037:03A0 _g_strinfo3001
+ 0038:037E _g_strinfo3401
+ 0039:0390 _g_strinfo3801
+ 003A:0384 _g_strinfo3c01
+ 003B:037C _g_strinfo4001
+ 0001:19B0 _MapStringJ
+ 0001:1D52 _MapStringKTP
+ 0001:18E2 _nDecodeSortWeightJ
+ 002C:070C _rgbLCase_0401
+ 0002:0714 _rgbLCase_0405
+ 0003:0724 _rgbLCase_0406
+ 0028:0700 _rgbLCase_0408
+ 0005:071C _rgbLCase_0409
+ 0006:073A _rgbLCase_040a
+ 002B:0700 _rgbLCase_040d
+ 0009:077C _rgbLCase_040e
+ 0027:070C _rgbLCase_040f
+ 000D:0704 _rgbLCase_0415
+ 000F:0700 _rgbLCase_0419
+ 0010:0714 _rgbLCase_041b
+ 0011:071C _rgbLCase_041d
+ 0026:0714 _rgbLCase_041f
+ 001B:071C _rgbLCase_0c0a
+ 002C:060C _rgbUCase_0401
+ 0002:0614 _rgbUCase_0405
+ 0003:0624 _rgbUCase_0406
+ 0028:0600 _rgbUCase_0408
+ 0005:061C _rgbUCase_0409
+ 0006:063A _rgbUCase_040a
+ 002B:0600 _rgbUCase_040d
+ 0009:067C _rgbUCase_040e
+ 0027:060C _rgbUCase_040f
+ 000D:0604 _rgbUCase_0415
+ 000F:0600 _rgbUCase_0419
+ 0010:0614 _rgbUCase_041b
+ 0011:061C _rgbUCase_041d
+ 0026:0614 _rgbUCase_041f
+ 001B:061C _rgbUCase_0c0a
+ 0002:0200 _rgdig_0405
+ 0003:0200 _rgdig_0406
+ 0006:0200 _rgdig_040a
+ 0009:0200 _rgdig_040e
+ 0010:0200 _rgdig_041b
+ 002C:0200 _rgexp_0401
+ 0002:0210 _rgexp_0405
+ 0003:0210 _rgexp_0406
+ 0005:0200 _rgexp_0409
+ 0006:021E _rgexp_040a
+ 0009:0278 _rgexp_040e
+ 0027:0200 _rgexp_040f
+ 000D:0200 _rgexp_0415
+ 0010:0210 _rgexp_041b
+ 0011:0200 _rgexp_041d
+ 0026:0200 _rgexp_041f
+ 001B:0200 _rgexp_0c0a
+ 002C:020C _rgwCType12_0401
+ 0002:0214 _rgwCType12_0405
+ 0003:0224 _rgwCType12_0406
+ 0028:0200 _rgwCType12_0408
+ 0005:021C _rgwCType12_0409
+ 0006:023A _rgwCType12_040a
+ 002B:0200 _rgwCType12_040d
+ 0009:027C _rgwCType12_040e
+ 0027:020C _rgwCType12_040f
+ 000D:0204 _rgwCType12_0415
+ 000F:0200 _rgwCType12_0419
+ 0010:0214 _rgwCType12_041b
+ 0011:021C _rgwCType12_041d
+ 0026:0214 _rgwCType12_041f
+ 001B:021C _rgwCType12_0c0a
+ 002C:040C _rgwCType3_0401
+ 0002:0414 _rgwCType3_0405
+ 0003:0424 _rgwCType3_0406
+ 0028:0400 _rgwCType3_0408
+ 0005:041C _rgwCType3_0409
+ 0006:043A _rgwCType3_040a
+ 002B:0400 _rgwCType3_040d
+ 0009:047C _rgwCType3_040e
+ 0027:040C _rgwCType3_040f
+ 000D:0404 _rgwCType3_0415
+ 000F:0400 _rgwCType3_0419
+ 0010:0414 _rgwCType3_041b
+ 0011:041C _rgwCType3_041d
+ 0026:0414 _rgwCType3_041f
+ 001B:041C _rgwCType3_0c0a
+ 002C:0000 _rgwSort_0401
+ 0002:0000 _rgwSort_0405
+ 0003:0000 _rgwSort_0406
+ 0028:0000 _rgwSort_0408
+ 0005:0000 _rgwSort_0409
+ 0006:0000 _rgwSort_040a
+ 002B:0000 _rgwSort_040d
+ 0009:0000 _rgwSort_040e
+ 0027:0000 _rgwSort_040f
+ 000D:0000 _rgwSort_0415
+ 000F:0000 _rgwSort_0419
+ 0010:0000 _rgwSort_041b
+ 0011:0000 _rgwSort_041d
+ 0026:0000 _rgwSort_041f
+ 001B:0000 _rgwSort_0c0a
+ 003C:07E4 _STKHQQ
+ 0001:2610 _ZeroTermNoIgnoreSym
+ 0000:9876 Abs __acrtused
+ 0000:D6D6 Abs __aDBdoswp
+ 0000:D6D6 Abs __aDBused
+ 003C:07F8 __edata
+ 003C:0825 __end
+ 0000:9876 Abs __fptaskdata
+ 003C:07E6 __hModule
+ 003C:07EC __lpszCmdLine
+ 0000:0000 Abs __sizec
+ 0000:0000 Abs __sized
+ 003C:07E8 __wDataSeg
+ 0001:2DB6 __wflags
+ 003C:07EA __wHeapSize
+ 0000:0000 Imp __WINFLAGS (KERNEL.178)
+ 003C:07F6 ___aDBrterr
+ 003C:07F4 ___aDBswpflg
+
+ Address Publics by Value
+
+ 0000:0000 Imp CREATEWINDOW (USER.41)
+ 0000:0000 Imp LocalInit (KERNEL.4)
+ 0000:0000 Abs __sizec
+ 0000:0000 Imp DESTROYWINDOW (USER.53)
+ 0000:0000 Imp ANSIUPPER (USER.431)
+ 0000:0000 Abs __sized
+ 0000:0000 Imp ISWINDOW (USER.47)
+ 0000:0000 Imp GETCLASSINFO (USER.404)
+ 0000:0000 Imp GETWINDOWWORD (USER.133)
+ 0000:0000 Imp ANSIUPPERBUFF (USER.437)
+ 0000:0000 Imp DEFWINDOWPROC (USER.107)
+ 0000:0000 Imp LSTRLEN (KERNEL.90)
+ 0000:0000 Imp LSTRCMP (USER.430)
+ 0000:0000 Imp __WINFLAGS (KERNEL.178)
+ 0000:0000 Imp GETPROFILESTRING (KERNEL.58)
+ 0000:0000 Imp REGISTERCLASS (USER.57)
+ 0000:9876 Abs __fptaskdata
+ 0000:9876 Abs __acrtused
+ 0000:D6D6 Abs __aDBdoswp
+ 0000:D6D6 Abs __aDBused
+ 0001:0010 LibEntry
+ 0001:002C LibMain
+ 0001:0044 WEP
+ 0001:005C LCIDFROMWININI
+ 0001:06E6 GETUSERDEFAULTLCID
+ 0001:06F6 GETSYSTEMDEFAULTLCID
+ 0001:0706 GETUSERDEFAULTLANGID
+ 0001:0716 GETSYSTEMDEFAULTLANGID
+ 0001:0726 GETLOCALEINFOA
+ 0001:093C _GetSortWeightJ
+ 0001:0BAA _CompareStringJ
+ 0001:0D3C _GetSortWeightKTP
+ 0001:0E74 _CompareStringKTP
+ 0001:1034 COMPARESTRINGA
+ 0001:1366 _CreateSortKeyJ
+ 0001:168A _CreateSortKeyKTP
+ 0001:18E2 _nDecodeSortWeightJ
+ 0001:19B0 _MapStringJ
+ 0001:1D52 _MapStringKTP
+ 0001:1F6C LCMAPSTRINGA
+ 0001:20DE _GetStringTypeJ
+ 0001:2206 _GetStringTypeKTP
+ 0001:2382 GETSTRINGTYPEA
+ 0001:248E _fCreateHiddenWindow
+ 0001:254C _DestroyHiddenWindow
+ 0001:2582 NOTIFYWINDOWPROC
+ 0001:25D0 REGISTERNLSINFOCHANGED
+ 0001:2610 _ZeroTermNoIgnoreSym
+ 0001:2916 _DefCompareStringA
+ 0001:2DB6 __wflags
+ 0002:0000 _rgwSort_0405
+ 0002:0200 _rgdig_0405
+ 0002:0210 _rgexp_0405
+ 0002:0214 _rgwCType12_0405
+ 0002:0414 _rgwCType3_0405
+ 0002:0614 _rgbUCase_0405
+ 0002:0714 _rgbLCase_0405
+ 0002:0974 _g_rglcinfo0405
+ 0002:0B68 _g_strinfo0405
+ 0003:0000 _rgwSort_0406
+ 0003:0200 _rgdig_0406
+ 0003:0210 _rgexp_0406
+ 0003:0224 _rgwCType12_0406
+ 0003:0424 _rgwCType3_0406
+ 0003:0624 _rgbUCase_0406
+ 0003:0724 _rgbLCase_0406
+ 0003:097C _g_rglcinfo0406
+ 0003:0B70 _g_strinfo0406
+ 0004:016C _g_rglcinfo0407
+ 0004:0360 _g_strinfo0407
+ 0005:0000 _rgwSort_0409
+ 0005:0200 _rgexp_0409
+ 0005:021C _rgwCType12_0409
+ 0005:041C _rgwCType3_0409
+ 0005:061C _rgbUCase_0409
+ 0005:071C _rgbLCase_0409
+ 0005:09AE _g_rglcinfo0409
+ 0005:0BA2 _g_strinfo0409
+ 0006:0000 _rgwSort_040a
+ 0006:0200 _rgdig_040a
+ 0006:021E _rgexp_040a
+ 0006:023A _rgwCType12_040a
+ 0006:043A _rgwCType3_040a
+ 0006:063A _rgbUCase_040a
+ 0006:073A _rgbLCase_040a
+ 0006:09DE _g_rglcinfo040a
+ 0006:0BD2 _g_strinfo040a
+ 0007:0198 _g_rglcinfo040b
+ 0007:038C _g_strinfo040b
+ 0008:0174 _g_rglcinfo040c
+ 0008:0368 _g_strinfo040c
+ 0009:0000 _rgwSort_040e
+ 0009:0200 _rgdig_040e
+ 0009:0278 _rgexp_040e
+ 0009:027C _rgwCType12_040e
+ 0009:047C _rgwCType3_040e
+ 0009:067C _rgbUCase_040e
+ 0009:077C _rgbLCase_040e
+ 0009:0A00 _g_rglcinfo040e
+ 0009:0BF4 _g_strinfo040e
+ 000A:0176 _g_rglcinfo0410
+ 000A:036A _g_strinfo0410
+ 000B:0176 _g_rglcinfo0413
+ 000B:036A _g_strinfo0413
+ 000C:0168 _g_rglcinfo0414
+ 000C:035C _g_strinfo0414
+ 000D:0000 _rgwSort_0415
+ 000D:0200 _rgexp_0415
+ 000D:0204 _rgwCType12_0415
+ 000D:0404 _rgwCType3_0415
+ 000D:0604 _rgbUCase_0415
+ 000D:0704 _rgbLCase_0415
+ 000D:0962 _g_rglcinfo0415
+ 000D:0B56 _g_strinfo0415
+ 000E:01A6 _g_rglcinfo0416
+ 000E:039A _g_strinfo0416
+ 000F:0000 _rgwSort_0419
+ 000F:0200 _rgwCType12_0419
+ 000F:0400 _rgwCType3_0419
+ 000F:0600 _rgbUCase_0419
+ 000F:0700 _rgbLCase_0419
+ 000F:0962 _g_rglcinfo0419
+ 000F:0B56 _g_strinfo0419
+ 0010:0000 _rgwSort_041b
+ 0010:0200 _rgdig_041b
+ 0010:0210 _rgexp_041b
+ 0010:0214 _rgwCType12_041b
+ 0010:0414 _rgwCType3_041b
+ 0010:0614 _rgbUCase_041b
+ 0010:0714 _rgbLCase_041b
+ 0010:0972 _g_rglcinfo041b
+ 0010:0B66 _g_strinfo041b
+ 0011:0000 _rgwSort_041d
+ 0011:0200 _rgexp_041d
+ 0011:021C _rgwCType12_041d
+ 0011:041C _rgwCType3_041d
+ 0011:061C _rgbUCase_041d
+ 0011:071C _rgbLCase_041d
+ 0011:097C _g_rglcinfo041d
+ 0011:0B70 _g_strinfo041d
+ 0012:0174 _g_rglcinfo0807
+ 0012:0368 _g_strinfo0807
+ 0013:018A _g_rglcinfo0809
+ 0013:037E _g_strinfo0809
+ 0014:018E _g_rglcinfo080a
+ 0014:0382 _g_strinfo080a
+ 0015:0180 _g_rglcinfo080c
+ 0015:0374 _g_strinfo080c
+ 0016:018E _g_rglcinfo0810
+ 0016:0382 _g_strinfo0810
+ 0017:0172 _g_rglcinfo0813
+ 0017:0366 _g_strinfo0813
+ 0018:01AA _g_rglcinfo0816
+ 0018:039E _g_strinfo0816
+ 0019:0174 _g_rglcinfo0c07
+ 0019:0368 _g_strinfo0c07
+ 001A:0186 _g_rglcinfo0c09
+ 001A:037A _g_strinfo0c09
+ 001B:0000 _rgwSort_0c0a
+ 001B:0200 _rgexp_0c0a
+ 001B:021C _rgwCType12_0c0a
+ 001B:041C _rgwCType3_0c0a
+ 001B:061C _rgbUCase_0c0a
+ 001B:071C _rgbLCase_0c0a
+ 001B:09B8 _g_rglcinfo0c0a
+ 001B:0BAC _g_strinfo0c0a
+ 001C:017A _g_rglcinfo0c0c
+ 001C:036E _g_strinfo0c0c
+ 001D:017A _g_rglcinfo1009
+ 001D:036E _g_strinfo1009
+ 001E:0186 _g_rglcinfo100c
+ 001E:037A _g_strinfo100c
+ 001F:0190 _g_rglcinfo1409
+ 001F:0384 _g_strinfo1409
+ 0020:0780 _g_rglcinfo0404
+ 0020:0974 _g_strinfo0404
+ 0021:45FE _g_rglcinfo0411
+ 0021:47F2 _g_strinfo0411
+ 0022:7E82 _g_rglcinfo0412
+ 0022:8076 _g_strinfo0412
+ 0023:0390 _g_rglcinfo0804
+ 0023:0584 _g_strinfo0804
+ 0024:017C _g_rglcinfo1809
+ 0024:0370 _g_strinfo1809
+ 0025:0170 _g_rglcinfo0814
+ 0025:0364 _g_strinfo0814
+ 0026:0000 _rgwSort_041f
+ 0026:0200 _rgexp_041f
+ 0026:0214 _rgwCType12_041f
+ 0026:0414 _rgwCType3_041f
+ 0026:0614 _rgbUCase_041f
+ 0026:0714 _rgbLCase_041f
+ 0026:097C _g_rglcinfo041f
+ 0026:0B70 _g_strinfo041f
+ 0027:0000 _rgwSort_040f
+ 0027:0200 _rgexp_040f
+ 0027:020C _rgwCType12_040f
+ 0027:040C _rgwCType3_040f
+ 0027:060C _rgbUCase_040f
+ 0027:070C _rgbLCase_040f
+ 0027:09A0 _g_rglcinfo040f
+ 0027:0B94 _g_strinfo040f
+ 0028:0000 _rgwSort_0408
+ 0028:0200 _rgwCType12_0408
+ 0028:0400 _rgwCType3_0408
+ 0028:0600 _rgbUCase_0408
+ 0028:0700 _rgbLCase_0408
+ 0028:0998 _g_rglcinfo0408
+ 0028:0B8C _g_strinfo0408
+ 0029:017C _g_rglcinfo0403
+ 0029:0370 _g_strinfo0403
+ 002A:01A6 _g_rglcinfo0429
+ 002A:039A _g_strinfo0429
+ 002B:0000 _rgwSort_040d
+ 002B:0200 _rgwCType12_040d
+ 002B:0400 _rgwCType3_040d
+ 002B:0600 _rgbUCase_040d
+ 002B:0700 _rgbLCase_040d
+ 002B:094E _g_rglcinfo040d
+ 002B:0B42 _g_strinfo040d
+ 002C:0000 _rgwSort_0401
+ 002C:0200 _rgexp_0401
+ 002C:020C _rgwCType12_0401
+ 002C:040C _rgwCType3_0401
+ 002C:060C _rgbUCase_0401
+ 002C:070C _rgbLCase_0401
+ 002C:09B4 _g_rglcinfo0401
+ 002C:0BA8 _g_strinfo0401
+ 002D:0186 _g_rglcinfo0801
+ 002D:037A _g_strinfo0801
+ 002E:0184 _g_rglcinfo0c01
+ 002E:0378 _g_strinfo0c01
+ 002F:018A _g_rglcinfo1001
+ 002F:037E _g_strinfo1001
+ 0030:0188 _g_rglcinfo1401
+ 0030:037C _g_strinfo1401
+ 0031:0190 _g_rglcinfo1801
+ 0031:0384 _g_strinfo1801
+ 0032:0182 _g_rglcinfo1c01
+ 0032:0376 _g_strinfo1c01
+ 0033:0184 _g_rglcinfo2001
+ 0033:0378 _g_strinfo2001
+ 0034:018A _g_rglcinfo2401
+ 0034:037E _g_strinfo2401
+ 0035:01A8 _g_rglcinfo2801
+ 0035:039C _g_strinfo2801
+ 0036:01A8 _g_rglcinfo2c01
+ 0036:039C _g_strinfo2c01
+ 0037:01AC _g_rglcinfo3001
+ 0037:03A0 _g_strinfo3001
+ 0038:018A _g_rglcinfo3401
+ 0038:037E _g_strinfo3401
+ 0039:019C _g_rglcinfo3801
+ 0039:0390 _g_strinfo3801
+ 003A:0190 _g_rglcinfo3c01
+ 003A:0384 _g_strinfo3c01
+ 003B:0188 _g_rglcinfo4001
+ 003B:037C _g_strinfo4001
+ 003C:0004 rsrvptrs
+ 003C:06B4 _g_pnls
+ 003C:06B6 _g_pstrinfo
+ 003C:06BA _g_lcidSystem
+ 003C:06C2 _g_hinstDLL
+ 003C:07E4 _STKHQQ
+ 003C:07E6 __hModule
+ 003C:07E8 __wDataSeg
+ 003C:07EA __wHeapSize
+ 003C:07EC __lpszCmdLine
+ 003C:07F0 _aseglo
+ 003C:07F2 _aseghi
+ 003C:07F4 ___aDBswpflg
+ 003C:07F6 ___aDBrterr
+ 003C:07F8 _edata
+ 003C:07F8 __edata
+ 003C:0820 _g_dwFlags
+ 003C:0824 _bFEflag
+ 003C:0825 _end
+ 003C:0825 __end
+
+Program entry point at 0001:0010
diff --git a/private/ole32/olethunk/bin16/ole2nls.sym b/private/ole32/olethunk/bin16/ole2nls.sym
new file mode 100644
index 000000000..fa31c3490
--- /dev/null
+++ b/private/ole32/olethunk/bin16/ole2nls.sym
Binary files differ
diff --git a/private/ole32/olethunk/bin16/stdole.tlb b/private/ole32/olethunk/bin16/stdole.tlb
new file mode 100644
index 000000000..ffdee1a54
--- /dev/null
+++ b/private/ole32/olethunk/bin16/stdole.tlb
Binary files differ
diff --git a/private/ole32/olethunk/bin16/typelib.map b/private/ole32/olethunk/bin16/typelib.map
new file mode 100644
index 000000000..cf530937e
--- /dev/null
+++ b/private/ole32/olethunk/bin16/typelib.map
@@ -0,0 +1,2363 @@
+
+ TYPELIB
+
+ Start Length Name Class
+ 0001:0000 01D54H _TEXT CODE
+ 0001:1D54 00790H TlibQuery CODE
+ 0001:24E4 00070H WEP_TEXT CODE
+ 0002:0000 08A26H TlibCreate CODE
+ 0003:0000 00000H SEGORDER_TEXT CODE
+ 0003:0000 00000H MEM_TEXT CODE
+ 0003:0000 00176H DFSTREAM_TEXT CODE
+ 0003:0176 004E2H ENTRYMGR_TEXT CODE
+ 0003:0658 00074H DFNTBIND_TEXT CODE
+ 0003:06CC 0023AH GBINDTBL_TEXT CODE
+ 0003:0906 005F2H DSTRMGR_TEXT CODE
+ 0003:0EF8 0106AH GPTBIND_TEXT CODE
+ 0003:1F62 0083AH DFNTCOMP_TEXT CODE
+ 0004:0000 00178H BLKMGR_TEXT CODE
+ 0004:0178 000BEH FSTREAM_TEXT CODE
+ 0004:0236 00472H SHEAPMGR_TEXT CODE
+ 0004:06A8 00050H RTSHEAP_TEXT CODE
+ 0004:06F8 00210H TLIBUTIL_TEXT CODE
+ 0004:0908 00070H TLIBGUID_TEXT CODE
+ 0004:0978 00070H OBGUID_TEXT CODE
+ 0004:09E8 00108H STLTINFO_TEXT CODE
+ 0004:0AF0 00260H NAMMGR_TEXT CODE
+ 0004:0D50 00BD4H GTLIBOLE_TEXT CODE
+ 0004:1924 007C6H IMPMGR_TEXT CODE
+ 0005:0000 001BAH ERRMAP_TEXT CODE
+ 0005:01BA 012C6H CLUTIL_TEXT CODE
+ 0005:1480 00E0CH TDATA1_TEXT CODE
+ 0005:228C 01C12H TDATA2_TEXT CODE
+ 0005:3E9E 01160H DTMBRS_TEXT CODE
+ 0005:4FFE 00C3CH DTBIND_TEXT CODE
+ 0005:5C3A 00000H OLECONST CODE
+ 0005:5C3A 005FCH DBINDTBL_TEXT CODE
+ 0005:6236 00240H GTLIBSTG_TEXT CODE
+ 0005:6480 00DE0H COMDAT_SEG1 CODE
+ 0006:0000 0468CH TLIBCORE CODE
+ 0006:468C 003B6H MBSTRING_TEXT CODE
+ 0007:0000 00000H DEBUG2_TEXT CODE
+ 0007:0000 0681CH TLibLoad CODE
+ 0008:0000 00000H DASSERT_TEXT CODE
+ 0008:0000 00000H TLS_TEXT CODE
+ 0008:0000 00100H TLibCP1252 CODE
+ 0009:0000 00100H TLibCP10000 CODE
+ 000A:0000 00100H TLibCP1250 CODE
+ 000B:0000 00100H TLibCP1251 CODE
+ 000C:0000 00100H TLibCP10029 CODE
+ 000D:0000 00100H TLibCP10007 CODE
+ 000E:0000 00100H TLibCPWGre CODE
+ 000F:0000 00100H TLibCPWIce CODE
+ 0010:0000 00874H TLibHash CODE
+ 0011:0000 00100H TLibCPWTur CODE
+ 0012:0000 00100H TLibCPWNor CODE
+ 0013:0000 00100H TLibCPWIre CODE
+ 0014:0000 00100H TLibCPMGre CODE
+ 0015:0000 00100H TLibCPMNor CODE
+ 0016:0000 00100H TLibCPMIre CODE
+ 0017:0000 00100H TLibCP1255 CODE
+ 0018:0000 00100H TLibCP1256 CODE
+ 0019:0000 00100H TLibCP10004 CODE
+ 001A:0000 00100H TLibCP10005 CODE
+ 001B:0000 02578H GDTINFO_TEXT CODE
+ 001C:0000 01464H TLibLayOut CODE
+ 001D:0000 001F6H TLibRare CODE
+ 001E:0000 0292EH GDTRT_TEXT CODE
+ 001F:0000 00000H OLETMGR_TEXT CODE
+ 001F:0000 00000H OAUTIL_TEXT CODE
+ 001F:0000 00000H TLIBPCH_TEXT CODE
+ 001F:0000 00010H NULL BEGDATA
+ 001F:0010 00522H _DATA DATA
+ 001F:0532 0000EH CDATA DATA
+ 001F:0540 00000H DBDATA DATA
+ 001F:0540 00000H XIFB DATA
+ 001F:0540 00000H XIF DATA
+ 001F:0540 00000H XIFE DATA
+ 001F:0540 00000H XIB DATA
+ 001F:0540 00000H XI DATA
+ 001F:0540 00000H XIE DATA
+ 001F:0540 00000H XPB DATA
+ 001F:0540 00000H XP DATA
+ 001F:0540 00000H XPE DATA
+ 001F:0540 00000H XCB DATA
+ 001F:0540 00000H XC DATA
+ 001F:0540 00000H XCE DATA
+ 001F:0540 00000H XCFB DATA
+ 001F:0540 00000H XCFCRT DATA
+ 001F:0540 00000H XCF DATA
+ 001F:0540 00000H XCFE DATA
+ 001F:0540 00000H XIFCB DATA
+ 001F:0540 00000H XIFU DATA
+ 001F:0540 00000H XIFL DATA
+ 001F:0540 00000H XIFM DATA
+ 001F:0540 00000H XIFCE DATA
+ 001F:0540 00006H CONST CONST
+ 001F:0546 00008H HDR MSG
+ 001F:054E 000D4H MSG MSG
+ 001F:0622 00002H PAD MSG
+ 001F:0624 00001H EPAD MSG
+ 001F:0626 003A2H _BSS BSS
+ 001F:09C8 00000H XOB BSS
+ 001F:09C8 00000H XO BSS
+ 001F:09C8 00000H XOE BSS
+ 001F:09C8 00000H XOFB BSS
+ 001F:09C8 00000H XOF BSS
+ 001F:09C8 00000H XOFE BSS
+ 001F:09D0 002C4H c_common BSS
+
+ Origin Group
+ 001F:0 DGROUP
+ 0004:0 MISC1GROUP
+ 0005:0 MISC2GROUP
+ 0001:0 INITGROUP
+ 0003:0 RAREGROUP
+ 0006:0 COREGROUP
+
+ Address Export Alias
+
+ 0002:13CE CREATETYPELIB CREATETYPELIB
+ 0004:0770 LHASHVALOFNAMESYS LHASHVALOFNAMESYS
+ 0005:04E2 LOADREGTYPELIB LOADREGTYPELIB
+ 0007:2010 LOADTYPELIB LOADTYPELIB
+ 0001:24D2 OABUILDVERSION OABUILDVERSION
+ 0001:201A QUERYPATHOFREGTYPELIB QUERYPATHOFREGTYPELIB
+ 0007:24C0 REGISTERTYPELIB REGISTERTYPELIB
+ 0001:2500 WEP WEP
+ 0004:0908 _IID_ICreateTypeInfo _IID_ICreateTypeInfo
+ 0004:0968 _IID_ICreateTypeLib _IID_ICreateTypeLib
+ 0004:0918 _IID_ITypeComp _IID_ITypeComp
+ 0004:0938 _IID_ITypeInfo _IID_ITypeInfo
+ 0004:0928 _IID_ITypeLib _IID_ITypeLib
+ 0001:0BDE ___ExportedStub ___ExportedStub
+
+ Address Publics by Name
+
+ 0007:0A04 ??0BLK_DESC@@REC@XZ
+ 0004:0000 ??0BLK_MGR@@REC@XZ
+ 0003:1F62 ??0CDefnTypeComp@@REC@XZ
+ 0007:4BE6 ??0DOCFILE_STREAM@@JEC@XZ
+ 0007:5654 ??0DOCSTR_MGR@@REC@XZ
+ 0006:3E5E ??0DYN_BINDNAME_TABLE@@REC@XZ
+ 0006:3D80 ??0DYN_TYPEBIND@@REC@XZ
+ 0006:3A34 ??0DYN_TYPEMEMBERS@@REC@XZ
+ 0006:0E54 ??0DYN_TYPEROOT@@JEC@XZ
+ 0006:3C46 ??0ENTRYMGR@@REC@XZ
+ 0007:64BA ??0FileLockBytes@@JEC@XZ
+ 0005:6DCA ??0FUNC_DEFN@@REC@XZ
+ 0007:2F02 ??0GenericTypeLibOLE@@JEC@XZ
+ 0007:53FC ??0GENPROJ_BINDNAME_TABLE@@REC@XZ
+ 0007:5A3E ??0GENPROJ_TYPEBIND@@REC@XZ
+ 0006:0A52 ??0GEN_DTINFO@@JEC@XZ
+ 0007:5DF8 ??0GTLibStorage@@JEC@XZ
+ 0007:6150 ??0GTLibStream@@JEC@XZ
+ 0007:5278 ??0IMPMGR@@REC@XZ
+ 0007:0E4C ??0NAMMGR@@REC@XZ
+ 0007:080A ??0SHEAP_MGR@@REC@XZ
+ 0005:6D8E ??0VAR_DEFN@@REC@XZ
+ 0007:0A2E ??1BLK_DESC@@REC@XZ
+ 0003:1FA2 ??1CDefnTypeComp@@VEC@XZ
+ 0007:4C4C ??1DOCFILE_STREAM@@JEC@XZ
+ 0007:56A6 ??1DOCSTR_MGR@@REC@XZ
+ 0006:3EA2 ??1DYN_BINDNAME_TABLE@@VEC@XZ
+ 0006:3E10 ??1DYN_TYPEBIND@@VEC@XZ
+ 0006:39F6 ??1DYN_TYPEMEMBERS@@JEC@XZ
+ 0006:1046 ??1DYN_TYPEROOT@@JEC@XZ
+ 0006:3C6C ??1ENTRYMGR@@REC@XZ
+ 0007:64F8 ??1FileLockBytes@@JEC@XZ
+ 0007:3158 ??1GenericTypeLibOLE@@NEC@XZ
+ 0007:5450 ??1GENPROJ_BINDNAME_TABLE@@REC@XZ
+ 0007:598C ??1GENPROJ_TYPEBIND@@VEC@XZ
+ 0006:0B22 ??1GEN_DTINFO@@NEC@XZ
+ 0007:5E88 ??1GTLibStorage@@JEC@XZ
+ 0007:6182 ??1GTLibStream@@JEC@XZ
+ 0006:3454 ??1IMPMGR@@REC@XZ
+ 0007:0E7C ??1NAMMGR@@REC@XZ
+ 0005:6EA4 ??1PROPERTY_NODE@@REC@XZ
+ 0007:0842 ??1SHEAP_MGR@@REC@XZ
+ 0006:1B50 ??1STL_TYPEINFO@@NEC@XZ
+ 0006:397C ??1TYPE_DATA@@REC@XZ
+ 0005:6480 ??2@ZAPEXI@Z
+ 0007:2C82 ??2GenericTypeLibOLE@@LAPEXI@Z
+ 0004:02F2 ??2SHEAP_MGR@@LAPEXI@Z
+ 0005:6484 ??3@ZAXPEX@Z
+ 0006:0EDE ??3DYN_TYPEROOT@@TAXPEX@Z
+ 0007:07FC ??3SHEAP_MGR@@TAXPEX@Z
+ 0005:70F8 ??_7CDefnTypeComp@@6F@
+ 0005:7002 ??_7DEFN_TYPEBIND@@6F@
+ 0005:6D5E ??_7DOCFILE_STREAM@@6F@
+ 0005:6AF8 ??_7DYNTYPEINFO@@6F@
+ 0005:7058 ??_7DYN_BINDNAME_TABLE@@6F@
+ 0005:6FC6 ??_7DYN_TYPEBIND@@6F@
+ 0005:6F74 ??_7DYN_TYPEMEMBERS@@6F@
+ 0005:6BE4 ??_7DYN_TYPEROOT@@6F@
+ 0005:7180 ??_7FileLockBytes@@6F@
+ 0005:6CC2 ??_7GenericTypeLibOLE@@6FICreateTypeLib@@@
+ 0005:6C82 ??_7GenericTypeLibOLE@@6FITypeLib@@@
+ 0005:708A ??_7GENPROJ_TYPEBIND@@6F@
+ 0005:6818 ??_7GEN_DTINFO@@6FDYNTYPEINFO@@@
+ 0005:68C0 ??_7GEN_DTINFO@@6FICreateTypeInfo@@@
+ 0005:71A8 ??_7GTLibStorage@@6F@
+ 0005:7148 ??_7GTLibStream@@6F@
+ 0005:6B7C ??_7ICreateTypeInfo@@6F@
+ 0005:6D2A ??_7ICreateTypeLib@@6F@
+ 0005:71F0 ??_7ILockBytes@@6F@
+ 0005:7218 ??_7IStorage@@6F@
+ 0005:7110 ??_7IStream@@6F@
+ 0005:70E4 ??_7ITypeComp@@6F@
+ 0005:6928 ??_7ITypeInfo@@6F@
+ 0005:6CF6 ??_7ITypeLib@@6F@
+ 0005:6980 ??_7IUnknown@@6F@
+ 0005:698C ??_7STL_TYPEINFO@@6FDYNTYPEINFO@@@
+ 0005:6A2C ??_7STL_TYPEINFO@@6FICreateTypeInfo@@@
+ 0005:6D76 ??_7STREAM@@6F@
+ 0005:6A94 ??_7TYPEINFO@@6F@
+ 0005:70CA ??_GCDefnTypeComp@@VECPEXI@Z
+ 0005:703E ??_GDYN_BINDNAME_TABLE@@VECPEXI@Z
+ 0005:6FAC ??_GDYN_TYPEBIND@@VECPEXI@Z
+ 0005:6C2E ??_GGenericTypeLibOLE@@VECPEXI@Z
+ 0005:7070 ??_GGENPROJ_TYPEBIND@@VECPEXI@Z
+ 0005:67FE ??_GGEN_DTINFO@@VECPEXI@Z
+ 0005:67E4 ??_GSTL_TYPEINFO@@VECPEXI@Z
+ 0002:1F0A ?Add@GenericTypeLibOLE@@RECPEXPEVGEN_DTINFO@@PED@Z
+ 0007:09A6 ?AddBlkdesc@SHEAP_MGR@@JECXPEVBLK_DESC@@K@Z
+ 0007:010E ?AddChunkToFreeList@BLK_MGR@@BECXII@Z
+ 0006:1CEA ?AddEntry@NAMMGR@@BECXI@Z
+ 0002:11E0 ?AddFuncDesc@GEN_DTINFO@@VEAPEXIPEUtagFUNCDESC@@@Z
+ 0005:65EA ?AddFuncDesc@STL_TYPEINFO@@VEAPEXIPEUtagFUNCDESC@@@Z
+ 0002:3510 ?AddFuncDesc@TYPE_DATA@@RECPEXIPEUtagFUNCDESC@@PEI@Z
+ 0005:5D34 ?AddHdefn@DYN_BINDNAME_TABLE@@RECXI@Z
+ 001C:0156 ?AddImplType@GEN_DTINFO@@VEAPEXIK@Z
+ 0005:65FA ?AddImplType@STL_TYPEINFO@@VEAPEXIK@Z
+ 001C:0B26 ?AddImplType@TYPE_DATA@@RECPEXIK@Z
+ 0005:506C ?AddInternalRef@DYN_TYPEBIND@@RECXXZ
+ 0005:3ED2 ?AddInternalRef@DYN_TYPEMEMBERS@@RECXXZ
+ 0004:17E2 ?AddNameToCache@GenericTypeLibOLE@@RECPEXIK@Z
+ 0006:401E ?AddNameToTable@GENPROJ_BINDNAME_TABLE@@RECPEXIIHH@Z
+ 0006:4554 ?AddNameToTable@GENPROJ_TYPEBIND@@RECPEXPEDIH@Z
+ 0002:6F6C ?AddNewWord@DOCSTR_MGR@@BECPEXPEDPEPEUWORD_ENTRY@@@Z
+ 0006:413A ?AddQgpbinddesc@GENPROJ_BINDNAME_TABLE@@JECXPEUGENPROJ_BIND_DESC@@@Z
+ 0003:212A ?AddRef@CDefnTypeComp@@VEAKXZ
+ 0007:4E48 ?AddRef@DOCFILE_STREAM@@RECXXZ
+ 0005:5044 ?AddRef@DYN_TYPEBIND@@VECXXZ
+ 0005:3E9E ?AddRef@DYN_TYPEMEMBERS@@VECXXZ
+ 0007:6526 ?AddRef@FileLockBytes@@VEAKXZ
+ 0006:2616 ?AddRef@GenericTypeLibOLE@@VEAKXZ
+ 0006:4680 ?AddRef@GenericTypeLibOLE@@X3EAKXZ
+ 0003:10DE ?AddRef@GENPROJ_TYPEBIND@@VECXXZ
+ 0007:5ED6 ?AddRef@GTLibStorage@@VEAKXZ
+ 0007:62D4 ?AddRef@GTLibStream@@VEAKXZ
+ 0006:18BE ?AddRef@STL_TYPEINFO@@VEAKXZ
+ 0005:6706 ?AddRef@STL_TYPEINFO@@X3EAKXZ
+ 001B:1E66 ?AddRefDtmbrs@DYN_TYPEROOT@@RECXXZ
+ 001C:0000 ?AddRefTypeInfo@GEN_DTINFO@@VEAPEXPEUITypeInfo@@PEK@Z
+ 0005:65DA ?AddRefTypeInfo@STL_TYPEINFO@@VEAPEXPEUITypeInfo@@PEK@Z
+ 001B:1CA4 ?AddressOfMember@GEN_DTINFO@@VEAPEXJW4tagINVOKEKIND@@PEPEX@Z
+ 0005:6536 ?AddressOfMember@STL_TYPEINFO@@VEAPEXJW4tagINVOKEKIND@@PEPEX@Z
+ 0002:1B0C ?AddTypeEntry@GenericTypeLibOLE@@JECPEXPEDPEG@Z
+ 0002:10DC ?AddVarDesc@GEN_DTINFO@@VEAPEXIPEUtagVARDESC@@@Z
+ 0005:663A ?AddVarDesc@STL_TYPEINFO@@VEAPEXIPEUtagVARDESC@@@Z
+ 0002:46C0 ?AddVarDesc@TYPE_DATA@@RECPEXIPEUtagVARDESC@@PEI@Z
+ 0002:6E92 ?AddWord@DOCSTR_MGR@@BECPEXPEDPEPEUWORD_ENTRY@@@Z
+ 001C:13B4 ?AdjustForAlignment@DYN_TYPEMEMBERS@@LAIIIH@Z
+ 001C:13E6 ?AlignMember@DYN_TYPEMEMBERS@@LAIPEGIIH@Z
+ 0002:684C ?AlignmentTdesckind@DYN_TYPEMEMBERS@@RECGW4TYPEDESCKIND@@@Z
+ 0002:1092 ?AllDepReady@GEN_DTINFO@@VECPEXXZ
+ 0004:02F6 ?Alloc@SHEAP_MGR@@JECPEXPEVBLK_DESC@@K@Z
+ 0002:33D8 ?AllocArrayDescriptor@TYPE_DATA@@BECPEXIPEG@Z
+ 0006:4248 ?AllocCaches@GENPROJ_BINDNAME_TABLE@@JECPEXII@Z
+ 0007:03C6 ?AllocChunk2@BLK_MGR@@BECPEXPEIII@Z
+ 0002:3CDA ?AllocConstValOfVariant@TYPE_DATA@@BECPEXPEUtagVARIANT@@I@Z
+ 0003:01DC ?AllocDllentrydefn@ENTRYMGR@@BECPEXPEIIH@Z
+ 0005:1CCA ?AllocFuncDefn@TYPE_DATA@@BECPEXPEGI@Z
+ 0002:61EA ?AllocHmembers@DYN_TYPEMEMBERS@@JECPEXXZ
+ 001E:242A ?AllocInvokeArgs@GEN_DTINFO@@QECPEXIIPEPEUINVOKEARGS@1@@Z
+ 0005:1C1E ?AllocMbrVarDefn@TYPE_DATA@@BECPEXPEGI@Z
+ 0004:0236 ?AllocSeg@@ZAGK@Z
+ 0002:3352 ?AllocTypeDefn@TYPE_DATA@@BECPEXIQEW4TYPEDESCKIND@@PEG@Z
+ 0002:4034 ?AllocTypeDefnOfTypeDesc@TYPE_DATA@@RECPEXPEUtagTYPEDESC@@IPEGHPEH@Z
+ 0005:2EB0 ?AllocTypeDescOfTypeDefn@TYPE_DATA@@RECPEXIHPEUtagTYPEDESC@@@Z
+ 0005:1FFC ?AllocVardefnPredeclared@TYPE_DATA@@RECPEXXZ
+ 0005:1D50 ?AllocVirtualFuncDefn@TYPE_DATA@@BECPEXPEGI@Z
+ 001C:0A4A ?AppendDefn@TYPE_DATA@@BECXIPEG0@Z
+ 001C:0AB0 ?AppendMbrVarDefn@TYPE_DATA@@BECXI@Z
+ 001F:0036 ?bCurVersion@DYN_TYPEROOT@@1EF
+ 001F:01A1 ?bCurVersion@IMPMGR@@0EE
+ 0002:0FD2 ?BeginDepIteration@GEN_DTINFO@@VECPEXPEPEUTINODE@@PEPEPEU2@@Z
+ 001F:0037 ?bFirstSerByte@DYN_TYPEROOT@@1EF
+ 001F:01A0 ?bFirstSerByte@IMPMGR@@0EE
+ 0003:218A ?Bind@CDefnTypeComp@@VEAPEXPEDKGPEPEUITypeInfo@@PEW4tagDESCKIND@@PETtagBINDPTR@@@Z
+ 0003:0FF8 ?BindAll@GENPROJ_TYPEBIND@@RECPEXHKIW4ACCESS@@W4COMPSTATE@@PEVEXBIND@@@Z
+ 0005:5112 ?BindBase@DYN_TYPEBIND@@JECPEXHIIKIW4ACCESS@@PEVEXBIND@@PEVGenericTypeLibOLE@@@Z
+ 0005:55AC ?BindDefnCur@DYN_TYPEBIND@@RECPEXHKIW4ACCESS@@PEVEXBIND@@@Z
+ 0005:5C2E ?BindDefnProjLevelStr@DYN_TYPEBIND@@VECPEXPEDIW4ACCESS@@1PEVEXBIND@@@Z
+ 0003:1EB6 ?BindDefnProjLevelStr@GENPROJ_TYPEBIND@@VECPEXPEDIW4ACCESS@@1PEVEXBIND@@@Z
+ 0005:595E ?BindDefnStr@DYN_TYPEBIND@@VECPEXPEDIW4ACCESS@@PEVEXBIND@@@Z
+ 0003:1024 ?BindDefnStr@GENPROJ_TYPEBIND@@VECPEXPEDIW4ACCESS@@PEVEXBIND@@@Z
+ 0005:527E ?BindIdDefn@DYN_TYPEBIND@@RECPEXHKIW4ACCESS@@PEVEXBIND@@@Z
+ 0003:1ADC ?BindItyp@GENPROJ_TYPEBIND@@JECPEXIHKIW4ACCESS@@0W4COMPSTATE@@PEVEXBIND@@@Z
+ 0003:170A ?BindModulesWithCaches@GENPROJ_TYPEBIND@@JECPEXHKIW4ACCESS@@0W4COMPSTATE@@PEVEXBIND@@@Z
+ 0003:1998 ?BindModulesWithNammgr@GENPROJ_TYPEBIND@@JECPEXHKIW4ACCESS@@0W4COMPSTATE@@PEVEXBIND@@@Z
+ 0003:1210 ?BindProjLevel@GENPROJ_TYPEBIND@@RECPEXHKIW4ACCESS@@0W4COMPSTATE@@PEVEXBIND@@@Z
+ 0003:2578 ?BindType@CDefnTypeComp@@VEAPEXPEDKPEPEUITypeInfo@@PEPEUITypeComp@@@Z
+ 0003:06C6 ?BindType@DEFN_TYPEBIND@@VECPEXKPEDI@Z
+ 0005:5C34 ?BindTypeDefnProjLevelStr@DYN_TYPEBIND@@VECPEXPEDIW4ACCESS@@1PEVEXBIND@@@Z
+ 0003:1E0C ?BindTypeDefnProjLevelStr@GENPROJ_TYPEBIND@@VECPEXPEDIW4ACCESS@@1PEVEXBIND@@@Z
+ 0005:59FE ?BindTypeDefnStr@DYN_TYPEBIND@@VECPEXPEDIW4ACCESS@@PEVEXBIND@@@Z
+ 0003:118E ?BindTypeDefnStr@GENPROJ_TYPEBIND@@VECPEXPEDIW4ACCESS@@PEVEXBIND@@@Z
+ 001F:0014 ?BM_cbSizeInitial@@3IF
+ 0006:2226 ?BstrOfHlnam@NAMMGR@@RFCPEXIPEPED@Z
+ 0005:50FA ?BuildBindNameTable@DYN_TYPEBIND@@RECPEXXZ
+ 0005:4566 ?BuildBindNameTable@DYN_TYPEMEMBERS@@RECPEXXZ
+ 0002:76FC ?BuildCmptHuffmanTree@DOCSTR_MGR@@BECPEXPEUHUFFMAN_TREE_MEM@@@Z
+ 0002:7384 ?BuildHuffmanTree@DOCSTR_MGR@@BECPEXPEPEUWORD_ENTRY@@PEJPEI@Z
+ 0005:4C80 ?BuildNameCache@DYN_TYPEMEMBERS@@RECPEXI@Z
+ 0005:5C78 ?BuildTable@DYN_BINDNAME_TABLE@@RECPEXXZ
+ 001F:0038 ?cbSizeDir@DYN_TYPEROOT@@1GF
+ 001F:0262 ?cbSizeSerMem@ENTRYMGR@@0GF
+ 0006:31B6 ?CheckRemainingDep@IMPMGR@@RECPEXPEW4DEPEND_KIND@@@Z
+ 001F:0073 ?chLibIdSep@GenericTypeLibOLE@@1DF
+ 001F:0072 ?chMinorVerNumSep@GenericTypeLibOLE@@1DF
+ 0005:079A ?ClearArrayDesc@@ZAXPEUtagARRAYDESC@@@Z
+ 0005:07AA ?ClearElemDesc@@ZAXPEUtagELEMDESC@@@Z
+ 0005:0786 ?ClearIdlDesc@@ZAXPEUtagIDLDESC@@@Z
+ 0005:0748 ?ClearTypeDesc@@ZAXPEUtagTYPEDESC@@@Z
+ 001D:019E ?Clone@GTLibStream@@VEAPEXPEPEUIStream@@@Z
+ 0001:22EA ?CloseTypeLibKey@@ZAXPEUTLIBKEY@@@Z
+ 001E:1746 ?CoerceArg@GEN_DTINFO@@QECPEXPEUtagVARIANT@@GGPEUGUID@@PEUINVOKEARGS@1@I@Z
+ 0002:85CE ?Commit@GTLibStorage@@VEAPEXK@Z
+ 0002:8988 ?Commit@GTLibStream@@VEAPEXK@Z
+ 0005:02BC ?CompareHimptypes@@ZAPEXQEVTYPE_DATA@@I0IPEH@Z
+ 0004:0038 ?ConsChunkToFreeList@BLK_MGR@@BECXII@Z
+ 0005:122E ?ConvertPathToUNC@@ZAPEXPEDPEPED@Z
+ 0005:0906 ?CopyArrayDesc@@ZAPEXPEPEUtagARRAYDESC@@PEU1@@Z
+ 001E:2632 ?CopyBackByrefArgs@GEN_DTINFO@@QECPEXPEUINVOKEARGS@1@@Z
+ 001D:00A2 ?CopyTo@GTLibStorage@@VEAPEXKPFUGUID@@PEPEDPEUIStorage@@@Z
+ 001D:0144 ?CopyTo@GTLibStream@@VEAPEXPEUIStream@@U_ULARGE_INTEGER@@PEU3@2@Z
+ 0005:0966 ?CopyTypeDesc@@ZAPEXPEUtagTYPEDESC@@0@Z
+ 0003:1FD0 ?Create@CDefnTypeComp@@TAPEXPEPEV1@PEVDEFN_TYPEBIND@@@Z
+ 0007:2E50 ?Create@GenericTypeLibOLE@@TAPEXPEUIStorage@@PEPEV1@@Z
+ 001B:0482 ?Create@GEN_DTINFO@@TAPEXPEPEV1@W4tagTYPEKIND@@HW4ACCESS@@W4tagSYSKIND@@@Z
+ 0002:7FA2 ?Create@GTLibStorage@@TAPEXPEUILockBytes@@IPEPEUIStorage@@@Z
+ 0002:881A ?Create@GTLibStream@@TAPEXPEUILockBytes@@KPEVGTLibStorage@@PEPEUIStream@@@Z
+ 0007:4F96 ?Create@OLE_TYPEMGR@@TAPEXPEPEV1@@Z
+ 0007:074C ?Create@SHEAP_MGR@@TAPEXPEPEV1@I@Z
+ 0007:645C ?CreateFileLockBytesOnHFILE@@ZAPEXHHKKPEPEUILockBytes@@@Z
+ 0007:4536 ?CreateHsz@GenericTypeLibOLE@@JECPEXPEDPEI@Z
+ 0006:286C ?CreateInstance@GenericTypeLibOLE@@JECPEXPEPEX@Z
+ 001B:0674 ?CreateInstance@GEN_DTINFO@@VEAPEXPEUIUnknown@@AFUGUID@@PEPEX@Z
+ 0005:6546 ?CreateInstance@STL_TYPEINFO@@VEAPEXPEUIUnknown@@AFUGUID@@PEPEX@Z
+ 0007:0000 ?CreateStandalone@BLK_MGR@@TAPEXPEPEV1@H@Z
+ 001D:007E ?CreateStorage@GTLibStorage@@VEAPEXPFDKKKPEPEUIStorage@@@Z
+ 0002:80CA ?CreateStream@GTLibStorage@@VEAPEXPFDKKKPEPEUIStream@@@Z
+ 0002:72CE ?CreateSubTree@DOCSTR_MGR@@BECPEXPEUHUFFMAN_TREE_MEM@@0PEPEU2@@Z
+ 0002:14E6 ?CreateTypeInfo@GenericTypeLibOLE@@VEAPEXPEDW4tagTYPEKIND@@PEPEUICreateTypeInfo@@@Z
+ 0006:3CD6 ?Decompile@ENTRYMGR@@RECXW4COMPSTATE@@@Z
+ 0002:08D2 ?DefineFuncAsDllEntry@GEN_DTINFO@@VEAPEXIPED0@Z
+ 0005:667A ?DefineFuncAsDllEntry@STL_TYPEINFO@@VEAPEXIPED0@Z
+ 0005:1F84 ?DefnSize@TYPE_DEFN@@RECIXZ
+ 0004:0D50 ?Deleting@GenericTypeLibOLE@@JECXG@Z
+ 001D:00EA ?DestroyElement@GTLibStorage@@VEAPEXPFD@Z
+ 0003:0176 ?DllEntryNameOfHchunk@ENTRYMGR@@RECPEXIPEDI@Z
+ 0002:7BC2 ?EncodeWords@DOCSTR_MGR@@BECPEXXZ
+ 0005:67A8 ?EndDepIteration@GEN_DTINFO@@VECXXZ
+ 001C:071A ?EnsureInDeclaredState@DYN_TYPEROOT@@RECPEXXZ
+ 001C:07E6 ?EnsureInSemiDeclaredState@DYN_TYPEROOT@@RECPEXXZ
+ 0006:167A ?EnsurePartsRead@DYN_TYPEROOT@@NECPEXXZ
+ 0006:1658 ?EnsurePartsRead@GEN_DTINFO@@VECPEXXZ
+ 001D:00D8 ?EnumElements@GTLibStorage@@VEAPEXKPEXKPEPEUIEnumSTATSTG@@@Z
+ 0002:5592 ?EquivTypeDefns@@ZAPEXPEVTYPE_DATA@@HG0HGGPEH@Z
+ 0002:53C4 ?EquivTypeDefnsIgnoreByRef@@ZAPEXPEVTYPE_DATA@@HG0HGGPEHH@Z
+ 0007:10C6 ?ErrOpen@@ZAPEXPFDPEH@Z
+ 0007:107C ?ErrOpenFile@@ZAPEXPFDPEHPED@Z
+ 0001:2326 ?FExistsRegisteredTypelib@@ZAHKPEDPEPED@Z
+ 0001:2474 ?FFileExists@@ZAHPFD@Z
+ 0007:4D36 ?FillBuffer@DOCFILE_STREAM@@JECPEXXZ
+ 0006:1DDE ?FindHash@NAMMGR@@BFCIII@Z
+ 0005:5E1C ?FindIndexOfHlnam@DYN_BINDNAME_TABLE@@JFCIII@Z
+ 0004:10E6 ?FindMembers@GenericTypeLibOLE@@RECPEXPEDKPEPEUITypeInfo@@PEJPEG@Z
+ 0004:0E54 ?FindName@GenericTypeLibOLE@@VEAPEXPEDKPEPEUITypeInfo@@PEJPEG@Z
+ 0006:1E66 ?FindTextNam@NAMMGR@@BECIPFDIHPEHH@Z
+ 0007:1EA0 ?FindTypeLib@@ZAPEXPFDPEULoadInfo@@H@Z
+ 0007:1D48 ?FindTypeLibUnqual@@ZAPEXPFDPEULoadInfo@@@Z
+ 0002:8A16 ?Flush@FileLockBytes@@VEAPEXXZ
+ 0003:00C4 ?FlushBuffer@DOCFILE_STREAM@@JECPEXXZ
+ 0006:1C16 ?ForEachDescendant@NAMMGR@@BECXIP91@CXI@ZH@Z
+ 0007:0566 ?Free@BLK_MGR@@RECXXZ
+ 0004:046A ?Free@SHEAP_MGR@@JECXPEVBLK_DESC@@@Z
+ 0005:08DA ?FreeArrayDesc@@ZAXPEUtagARRAYDESC@@@Z
+ 0005:151E ?FreeArrayDescriptor@TYPE_DATA@@RECXI@Z
+ 0007:5504 ?FreeCaches@GENPROJ_BINDNAME_TABLE@@JECXXZ
+ 0007:04D4 ?FreeChunk@BLK_MGR@@RECXII@Z
+ 0005:179A ?FreeFuncDefn@TYPE_DATA@@RECXI@Z
+ 0005:082C ?FreeFuncDesc@@ZAXPEUtagFUNCDESC@@@Z
+ 0005:1612 ?FreeMbrVarDefn@TYPE_DATA@@RECXI@Z
+ 0005:19AC ?FreeParamDefn@TYPE_DATA@@RECXI@Z
+ 0004:02D0 ?FreeSeg@@ZAPEXG@Z
+ 0007:00CA ?FreeStandalone@BLK_MGR@@TAXPEV1@@Z
+ 0006:39A6 ?FreeTypeDefn@TYPE_DATA@@RECXI@Z
+ 0005:1554 ?FreeTypeDefnResources@TYPE_DATA@@RECXI@Z
+ 0005:08AE ?FreeTypeDesc@@ZAXPEUtagTYPEDESC@@@Z
+ 0005:07D2 ?FreeVarDesc@@ZAXPEUtagVARDESC@@@Z
+ 0002:66E4 ?GenerateOverrides@DYN_TYPEMEMBERS@@JECPEXXZ
+ 0006:2404 ?GenerateSortKey@NAMMGR@@RECPEXXZ
+ 0003:040A ?GetAddressOfDllentry@ENTRYMGR@@RECPEXIPEPEX@Z
+ 0005:5AD2 ?GetAlignment@DYN_TYPEBIND@@VECGXZ
+ 0003:111A ?GetAlignment@GENPROJ_TYPEBIND@@VECGXZ
+ 0001:23B8 ?GetBestLcidMatch@@ZAPEXKKPEKPEPED@Z
+ 0006:29BC ?GetBinddescOfSzName@GenericTypeLibOLE@@RECPEXPEDPEUGENPROJ_BIND_DESC@@@Z
+ 0005:6C04 ?GetBit@NAME_CACHE@@BFCHI@Z
+ 0007:52C4 ?GetBStrOfHsz@@ZAPEXPEVBLK_MGR@@IPEPED@Z
+ 0006:1BEC ?GetBucketOfHash@NAMMGR@@BFCII@Z
+ 0005:5C3A ?GetBucketOfHlnam@DYN_BINDNAME_TABLE@@JFCII@Z
+ 0005:5AC4 ?GetCbSize@DYN_TYPEBIND@@VECGXZ
+ 0003:1114 ?GetCbSize@GENPROJ_TYPEBIND@@VECGXZ
+ 0003:06C0 ?GetCbSizeVft@DEFN_TYPEBIND@@VECGXZ
+ 0005:6F8C ?GetCbSizeVft@DYN_TYPEBIND@@VECGXZ
+ 0002:1820 ?GetCompressedTypeId@GenericTypeLibOLE@@RECPEXPEUITypeInfo@@PEPED@Z
+ 0006:1B74 ?GetContainingTypeLib@STL_TYPEINFO@@VEAPEXPEPEUITypeLib@@PEI@Z
+ 0003:0C40 ?GetDecodedDocStrOfHst@DOCSTR_MGR@@RECPEXPEEPEPED@Z
+ 0005:3F38 ?GetDefnTypeBind@DYN_TYPEMEMBERS@@RECPEXPEPEVDEFN_TYPEBIND@@@Z
+ 001B:05F2 ?GetDefnTypeBind@GEN_DTINFO@@VECPEXPEPEVDEFN_TYPEBIND@@@Z
+ 001B:19CE ?GetDllEntry@GEN_DTINFO@@VEAPEXJW4tagINVOKEKIND@@PEPED1PEG@Z
+ 0005:6516 ?GetDllEntry@STL_TYPEINFO@@VEAPEXJW4tagINVOKEKIND@@PEPED1PEG@Z
+ 0007:341E ?GetDocumentation@GenericTypeLibOLE@@VEAPEXHPEPED0PEK0@Z
+ 0006:0C26 ?GetDocumentation@GEN_DTINFO@@VEAPEXJPEPED0PEK0@Z
+ 0005:6506 ?GetDocumentation@STL_TYPEINFO@@VEAPEXJPEPED0PEK0@Z
+ 0005:3746 ?GetDocumentation@TYPE_DATA@@RECPEXJPEPED0PEK0@Z
+ 0004:184E ?GetDstrMgr@GenericTypeLibOLE@@RECPEXPEPEVDOCSTR_MGR@@@Z
+ 0006:14AA ?GetDtmbrs@DYN_TYPEROOT@@VECPEXPEPEVDYN_TYPEMEMBERS@@@Z
+ 0005:3B9E ?GetDynTypeBindOfHvdefn@TYPE_DATA@@RECPEXIPEPEVDYN_TYPEBIND@@PEI@Z
+ 001B:0594 ?GetDynTypeMembers@GEN_DTINFO@@VECPEXPEPEVDYN_TYPEMEMBERS@@@Z
+ 001D:0050 ?GetEmbeddedTypeInfo@GEN_DTINFO@@VECPEXPEDPEPEVTYPEINFO@@@Z
+ 0002:7E18 ?GetEncodedDocStrOfHst@DOCSTR_MGR@@RECPEXIPEPEDPEI@Z
+ 0005:39F4 ?GetEncodedHelpContext@TYPE_DATA@@RECPEXKPEG@Z
+ 0006:131E ?GetEntMgr@DYN_TYPEROOT@@RECPEXPEPEVENTRYMGR@@@Z
+ 0005:0000 ?GetErrorInfo@@ZAPEXPEUtagEXCEPINFO@@@Z
+ 0002:4F36 ?GetFuncDefnForDoc@TYPE_DATA@@RECII@Z
+ 001B:234E ?GetFuncDesc@GEN_DTINFO@@VEAPEXIPEPEUtagFUNCDESC@@@Z
+ 0005:64A6 ?GetFuncDesc@STL_TYPEINFO@@VEAPEXIPEPEUtagFUNCDESC@@@Z
+ 0005:285A ?GetFuncDesc@TYPE_DATA@@RECPEXIPEPEUtagFUNCDESC@@@Z
+ 0005:2412 ?GetFuncDescOfHfdefn@TYPE_DATA@@RECPEXIPEPEUtagFUNCDESC@@@Z
+ 0006:2822 ?GetGdtiOfItyp@GenericTypeLibOLE@@RECPEXIPEPEVGEN_DTINFO@@@Z
+ 0004:0B5E ?GetHgnamOfStrLhash@NAMMGR@@RECPEXPEDKPEK@Z
+ 0004:1C8C ?GetHimptype@IMPMGR@@RECPEXPEUITypeInfo@@W4DEPEND_KIND@@PEG@Z
+ 0006:3124 ?GetHimptypeIfExists@IMPMGR@@RECIPEUITypeInfo@@@Z
+ 0002:7050 ?GetHstOfHelpString@DOCSTR_MGR@@RECPEXPFDPEI@Z
+ 001E:014A ?GetIDsOfNames@GEN_DTINFO@@VEAPEXPEPEDIPEJ@Z
+ 0005:64F6 ?GetIDsOfNames@STL_TYPEINFO@@VEAPEXPEPEDIPEJ@Z
+ 001B:1576 ?GetImplTypeFlags@GEN_DTINFO@@VEAPEXIPEH@Z
+ 0005:64E6 ?GetImplTypeFlags@STL_TYPEINFO@@VEAPEXIPEH@Z
+ 0005:32F8 ?GetImplTypeFlags@TYPE_DATA@@RECPEXIPEH@Z
+ 0006:1184 ?GetImpMgr@DYN_TYPEROOT@@RECPEXPEPEVIMPMGR@@@Z
+ 0006:2A9E ?GetIndexOfName@GenericTypeLibOLE@@RECPEXPEDPEG@Z
+ 0006:009E ?GetInsensitiveCompTbl@@ZAXKW4tagSYSKIND@@PED@Z
+ 001E:1CDE ?GetInvokeArgs@GEN_DTINFO@@QECPEXIPEVTYPE_DATA@@GPEUtagDISPPARAMS@@PEPEUtagVARIANT@@PEXPEPEUINVOKEARGS@1@PEIH@Z
+ 0004:09E8 ?GetLcid@STL_TYPEINFO@@JECPEXPEK@Z
+ 0007:391E ?GetLibAttr@GenericTypeLibOLE@@VEAPEXPEPEUtagTLIBATTR@@@Z
+ 0005:0376 ?GetLibIdKind@@ZA?EW4LIBIDKIND@@PED@Z
+ 0005:0A5A ?GetLibIdOfRegLib@@ZAPEXPEDGGK00PEPED@Z
+ 0005:0C5A ?GetLibIdOfTypeLib@@ZAPEXPEUITypeLib@@PEPED@Z
+ 001D:0000 ?GetMops@GEN_DTINFO@@VEAPEXJPEPED@Z
+ 0005:6556 ?GetMops@STL_TYPEINFO@@VEAPEXJPEPED@Z
+ 001B:1172 ?GetNames@GEN_DTINFO@@VEAPEXJPEPEDIPEI@Z
+ 0005:64C6 ?GetNames@STL_TYPEINFO@@VEAPEXJPEPEDIPEI@Z
+ 0005:345E ?GetNames@TYPE_DATA@@RECPEXJPEPEDIPEI@Z
+ 0006:1162 ?GetNamMgr@DYN_TYPEROOT@@RECPEXPEPEVNAMMGR@@@Z
+ 0007:4680 ?GetNamMgr@GenericTypeLibOLE@@RECPEXPEPEVNAMMGR@@@Z
+ 0002:0FD8 ?GetNextDepTypeInfo@GEN_DTINFO@@VECPEXPEPEVDYNTYPEINFO@@@Z
+ 0003:0AD2 ?GetNthBit@DOCSTR_MGR@@BEC?EW4HCODE@@IPEE@Z
+ 0007:154A ?GetOffsetOfResource@@ZAPEXHPEDHPEU_IMAGE_DOS_HEADER@@PEJ2@Z
+ 0007:1B4A ?GetOffsetOfTypeLibResource@@ZAPEXHHPEU_IMAGE_DOS_HEADER@@PEJ1@Z
+ 0003:06B8 ?GetOPvft@DEFN_TYPEBIND@@VECJXZ
+ 0005:6F9A ?GetOPvft@DYN_TYPEBIND@@VECJXZ
+ 0007:53B2 ?GetPathEnd@@ZAPEDPED@Z
+ 0007:4DD2 ?GetPos@DOCFILE_STREAM@@VECPEXPEJ@Z
+ 001B:15EA ?GetRefTypeInfo@GEN_DTINFO@@VEAPEXKPEPEUITypeInfo@@@Z
+ 0005:6526 ?GetRefTypeInfo@STL_TYPEINFO@@VEAPEXKPEPEUITypeInfo@@@Z
+ 001B:1440 ?GetRefTypeOfImplType@GEN_DTINFO@@VEAPEXIPEK@Z
+ 0005:64D6 ?GetRefTypeOfImplType@STL_TYPEINFO@@VEAPEXIPEK@Z
+ 0005:336E ?GetRefTypeOfImplType@TYPE_DATA@@RECPEXIPEK@Z
+ 0001:1ED0 ?GetRegInfoForTypeLibOfSzGuid@@ZAPEXPEDGGK0H@Z
+ 0001:1E7E ?GetRegisteredPath@@ZAPEXKPED0PEJH@Z
+ 0006:37E0 ?GetRegLibOfLibId@@ZAPEXPEDPEPEUITypeLib@@@Z
+ 0007:11A4 ?GetRsrcDirEntry@@ZAPEXHKPEGKPEU_IMAGE_RESOURCE_DIRECTORY_ENTRY@@@Z
+ 0004:0158 ?GetSize@BLK_MGR@@RFCIXZ
+ 0005:4FE4 ?GetSize@DYN_TYPEMEMBERS@@VECIXZ
+ 0005:4072 ?GetSizeAlignmentOfArray@DYN_TYPEMEMBERS@@RECPEXW4tagTYPEKIND@@IPEI1@Z
+ 0005:4274 ?GetSizeAlignmentOfHtdefn@DYN_TYPEMEMBERS@@RECPEXW4tagTYPEKIND@@HIPEI1@Z
+ 0005:4418 ?GetSizeAlignmentOfHtdefnNonUdt@DYN_TYPEMEMBERS@@RECPEXW4tagTYPEKIND@@HIPEI1@Z
+ 0005:3F78 ?GetSizeAlignmentOfHtdefnUdt@DYN_TYPEMEMBERS@@RECPEXIPEI0@Z
+ 0007:3B22 ?GetStorage@GenericTypeLibOLE@@RECPEXKPEPEUIStorage@@@Z
+ 0006:359E ?GetTimeStamp@@ZAXPED@Z
+ 001B:0BF4 ?GetTypeAttr@GEN_DTINFO@@VEAPEXPEPEUtagTYPEATTR@@@Z
+ 0005:6486 ?GetTypeAttr@STL_TYPEINFO@@VEAPEXPEPEUtagTYPEATTR@@@Z
+ 0006:289E ?GetTypeBind@GenericTypeLibOLE@@RECPEXXZ
+ 0004:0FA0 ?GetTypeComp@GenericTypeLibOLE@@VEAPEXPEPEUITypeComp@@@Z
+ 001B:10B6 ?GetTypeComp@GEN_DTINFO@@VEAPEXPEPEUITypeComp@@@Z
+ 0005:6496 ?GetTypeComp@STL_TYPEINFO@@VEAPEXPEPEUITypeComp@@@Z
+ 001D:005A ?GetTypeFixups@GEN_DTINFO@@VECPEXPEPEVTYPEFIXUPS@@@Z
+ 0005:50B8 ?GetTypeInfo@DYN_TYPEBIND@@VECPEXPEPEVTYPEINFO@@@Z
+ 0006:265C ?GetTypeInfo@GenericTypeLibOLE@@VEAPEXIPEPEUITypeInfo@@@Z
+ 0005:705C ?GetTypeInfo@GENPROJ_TYPEBIND@@VECPEXPEPEVTYPEINFO@@@Z
+ 0004:1DB4 ?GetTypeInfo@IMPMGR@@RECPEXIW4DEPEND_KIND@@PEPEUITypeInfo@@@Z
+ 0006:2648 ?GetTypeInfoCount@GenericTypeLibOLE@@VEAIXZ
+ 0004:1026 ?GetTypeInfoOfGuid@GenericTypeLibOLE@@VEAPEXAFUGUID@@PEPEUITypeInfo@@@Z
+ 0005:3C6E ?GetTypeInfoOfHvdefn@TYPE_DATA@@RECPEXIPEPEUITypeInfo@@PEI@Z
+ 001B:0178 ?GetTypeInfoOfImplType@@ZAPEXPEVGEN_DTINFO@@IPEPEUITypeInfo@@@Z
+ 0005:0D20 ?GetTypeInfoOfTypeId@@ZAPEXPEDPEPEUITypeInfo@@@Z
+ 0007:3ACE ?GetTypeInfoType@GenericTypeLibOLE@@VEAPEXIPEW4tagTYPEKIND@@@Z
+ 0005:5A9C ?GetTypeKind@DYN_TYPEBIND@@VEC?EW4tagTYPEKIND@@XZ
+ 0006:3C1C ?GetTypeKind@DYN_TYPEMEMBERS@@VEC?EW4tagTYPEKIND@@XZ
+ 0003:1108 ?GetTypeKind@GENPROJ_TYPEBIND@@VEC?EW4tagTYPEKIND@@XZ
+ 001B:22BA ?GetVarDesc@GEN_DTINFO@@VEAPEXIPEPEUtagVARDESC@@@Z
+ 0005:64B6 ?GetVarDesc@STL_TYPEINFO@@VEAPEXIPEPEUtagVARDESC@@@Z
+ 0005:2DE8 ?GetVarDesc@TYPE_DATA@@RECPEXIPEPEUtagVARDESC@@@Z
+ 0005:2902 ?GetVarDescOfHvdefn@TYPE_DATA@@RECPEXIPEPEUtagVARDESC@@@Z
+ 0003:0B70 ?GetWord@DOCSTR_MGR@@BECPEXPEXPEEPEIPED@Z
+ 001F:002C ?g_fSBCS@@3HE
+ 001F:02D0 ?g_itlsAppData@@3GE
+ 0006:04BE ?g_prgbPartialBaseTbl@@3QEY01PEEE
+ 0004:06F8 ?g_prgHashTbl@@3QEY01PEEE
+ 0009:0000 ?g_rgbCodePage10000@@3QEEE
+ 0019:0000 ?g_rgbCodePage10004@@3QEEE
+ 001A:0000 ?g_rgbCodePage10005@@3QEEE
+ 000D:0000 ?g_rgbCodePage10007@@3QEEE
+ 000C:0000 ?g_rgbCodePage10029@@3QEEE
+ 000A:0000 ?g_rgbCodePage1250@@3QEEE
+ 000B:0000 ?g_rgbCodePage1251@@3QEEE
+ 0008:0000 ?g_rgbCodePage1252@@3QEEE
+ 0017:0000 ?g_rgbCodePage1255@@3QEEE
+ 0018:0000 ?g_rgbCodePage1256@@3QEEE
+ 0016:0000 ?g_rgbCodePageMEngIreland@@3QEEE
+ 0014:0000 ?g_rgbCodePageMGreek@@3QEEE
+ 0015:0000 ?g_rgbCodePageMNorwegian@@3QEEE
+ 0013:0000 ?g_rgbCodePageWEngIreland@@3QEEE
+ 000E:0000 ?g_rgbCodePageWGreek@@3QEEE
+ 000F:0000 ?g_rgbCodePageWIceland@@3QEEE
+ 0012:0000 ?g_rgbCodePageWNorwegian@@3QEEE
+ 0011:0000 ?g_rgbCodePageWTurkish@@3QEEE
+ 0006:07D0 ?g_rgbExcepTblMac1030@@3QEY01EE
+ 0006:0634 ?g_rgbExcepTblMac1034@@3QEY01EE
+ 0006:04A4 ?g_rgbExcepTblMac1035@@3QEY01EE
+ 0006:0358 ?g_rgbExcepTblMac1038@@3QEY01EE
+ 0006:099E ?g_rgbExcepTblMac1045@@3QEY01EE
+ 0006:090C ?g_rgbExcepTblMac1051@@3QEY01EE
+ 0006:0888 ?g_rgbExcepTblNew@@3QEY01EE
+ 0006:086A ?g_rgbExcepTblWin1030@@3QEY01EE
+ 0006:063A ?g_rgbExcepTblWin1034@@3QEY01EE
+ 0006:0596 ?g_rgbExcepTblWin1035@@3QEY01EE
+ 0006:03FE ?g_rgbExcepTblWin1038@@3QEY01EE
+ 0006:02A4 ?g_rgbExcepTblWin1045@@3QEY01EE
+ 0006:0914 ?g_rgbExcepTblWin1051@@3QEY01EE
+ 0006:037E ?g_rgbPartialBaseTbl10000@@3QEEE
+ 0006:09D2 ?g_rgbPartialBaseTbl10007@@3QEEE
+ 0006:02D8 ?g_rgbPartialBaseTbl10029@@3QEEE
+ 0006:0424 ?g_rgbPartialBaseTbl1250@@3QEEE
+ 0006:0516 ?g_rgbPartialBaseTbl1252@@3QEEE
+ 0006:05B4 ?g_rgbPartialBaseTblMEngIreland@@3QEEE
+ 0006:0640 ?g_rgbPartialBaseTblMNorwegian@@3QEEE
+ 0006:07EA ?g_rgbPartialBaseTblWEngIreland@@3QEEE
+ 0006:088C ?g_rgbPartialBaseTblWNorwegian@@3QEEE
+ 0006:091E ?g_rgbPartialBaseTblWTurkish@@3QEEE
+ 001F:021A ?g_rgcbAlignment@@3QADA
+ 0006:06C0 ?g_rgLcidToExcepTbl@@3QEY01ULcidToExcep@@E
+ 001F:01BA ?g_rgrgcbSizeType@@3QAY0CA@DA
+ 001F:0032 ?g_szGuidStdole@@3PEDE
+ 0006:247C ?HashOfHlnam@NAMMGR@@RECKI@Z
+ 0006:3668 ?HashSzTerm@@ZAIPEDD@Z
+ 0002:533E ?HchunkOfString@TYPE_DATA@@BECPEXPEDPEI@Z
+ 0005:1DE6 ?HdefnOfHmember@TYPE_DATA@@RECIKPEI@Z
+ 0005:2404 ?HfdefnFirstAvailMeth@TYPE_DATA@@RECIXZ
+ 0005:2344 ?HfdefnFirstOfHlnam@TYPE_DATA@@RECIIPEW4tagINVOKEKIND@@@Z
+ 0005:2370 ?HfdefnNextOfHlnam@TYPE_DATA@@RECIIIPEW4tagINVOKEKIND@@@Z
+ 0005:1E3A ?HfdefnOfHmember@TYPE_DATA@@RFCIKI@Z
+ 0005:3DF8 ?HfdefnOfIndex@TYPE_DATA@@RECPEXIPEI@Z
+ 0007:029C ?HfreechunkOfCbSize@BLK_MGR@@BECII@Z
+ 0006:227C ?HgnamOfHlnam@NAMMGR@@RECPEXIPEK@Z
+ 0006:22A2 ?HgnamOfStr@NAMMGR@@RECPEXPEDPEK@Z
+ 0004:1A5A ?HimptypeAlloc@IMPMGR@@BECPEXPEG@Z
+ 0006:31A0 ?HimptypeFirst@IMPMGR@@RFCIXZ
+ 0004:1E54 ?HimptypeNext@IMPMGR@@RFCII@Z
+ 0006:2026 ?HlnamOfStr@NAMMGR@@RECPEXPFDPEIHPEHHH@Z
+ 0006:1FC0 ?HlnamOfStrIfExist@NAMMGR@@RECIPFD@Z
+ 0005:1EDE ?HmvdefnOfHmember@TYPE_DATA@@RFCIK@Z
+ 0005:32B2 ?HmvdefnOfIndex@TYPE_DATA@@BECII@Z
+ 0007:051A ?HszLen@BLK_MGR@@RFCII@Z
+ 0005:3E62 ?HtdefnAlias@TYPE_DATA@@RFCIXZ
+ 0005:22F4 ?HvdefnOfHlnam@TYPE_DATA@@RECII@Z
+ 0005:592C ?HvdefnPredeclared@DYN_TYPEBIND@@RECIXZ
+ 0005:1ED0 ?HvdefnPredeclared@TYPE_DATA@@RFCIXZ
+ 0006:2886 ?IhteHash@GenericTypeLibOLE@@JECIPED@Z
+ 0006:3F5E ?IndexOfHlnam@GENPROJ_BINDNAME_TABLE@@RFCII@Z
+ 001E:07B8 ?IndexOfParam@GEN_DTINFO@@QECPEXPEUtagDISPPARAMS@@IPEI@Z
+ 0007:0A74 ?Init@BLK_DESC@@RECPEXPEVSHEAP_MGR@@I@Z
+ 0004:0072 ?Init@BLK_MGR@@RECPEXPEVSHEAP_MGR@@HH@Z
+ 0003:2068 ?Init@CDefnTypeComp@@JECPEXPEVDEFN_TYPEBIND@@@Z
+ 0007:5880 ?Init@DOCSTR_MGR@@RECPEXXZ
+ 0006:3EB8 ?Init@DYN_BINDNAME_TABLE@@RECPEXPEVBLK_MGR@@PEVDYN_TYPEROOT@@@Z
+ 0006:3D54 ?Init@DYN_TYPEBIND@@RECPEXPEVBLK_MGR@@PEVDYN_TYPEROOT@@@Z
+ 0006:3B08 ?Init@DYN_TYPEMEMBERS@@RECPEXPEVSHEAP_MGR@@PEVDYN_TYPEROOT@@@Z
+ 0006:0F10 ?Init@DYN_TYPEROOT@@RECPEXPEVGEN_DTINFO@@IIHW4ACCESS@@W4tagTYPEKIND@@W4tagSYSKIND@@@Z
+ 0006:3C92 ?Init@ENTRYMGR@@RECPEXPEVSHEAP_MGR@@PEVDYN_TYPEROOT@@@Z
+ 0007:2CB0 ?Init@GenericTypeLibOLE@@VECPEXXZ
+ 0007:5482 ?Init@GENPROJ_BINDNAME_TABLE@@RECPEXPEVSHEAP_MGR@@PEVNAMMGR@@@Z
+ 0007:59DA ?Init@GENPROJ_TYPEBIND@@RECPEXPEVSHEAP_MGR@@@Z
+ 0006:2FBE ?Init@IMPMGR@@RECPEXPEVSHEAP_MGR@@PEVBLK_DESC@@1PEVDYN_TYPEROOT@@@Z
+ 0007:0EA6 ?Init@NAMMGR@@RECPEXPEVSHEAP_MGR@@PEVDYN_TYPEROOT@@@Z
+ 0007:0846 ?Init@SHEAP_MGR@@JECPEXI@Z
+ 0006:3896 ?Init@TYPE_DATA@@RECPEXPEVSHEAP_MGR@@PEVDYN_TYPEROOT@@@Z
+ 0007:665A ?InitAppData@@ZAPEXXZ
+ 0005:06CC ?InitElemDesc@@ZAXPEUtagELEMDESC@@@Z
+ 0005:0714 ?InitFuncDesc@@ZAXPEUtagFUNCDESC@@@Z
+ 0006:172C ?InitializeIteration@GEN_DTINFO@@VECPEXXZ
+ 0005:06BA ?InitIdlDesc@@ZAXPEUtagIDLDESC@@@Z
+ 0007:1B70 ?InitLoadInfo@@ZAXPEULoadInfo@@@Z
+ 0005:06AC ?InitTypeDesc@@ZAXPEUtagTYPEDESC@@@Z
+ 0005:06F4 ?InitVarDesc@@ZAXPEUtagVARDESC@@@Z
+ 001B:007E ?InterfaceFuncdescToDispatch@@ZAXPEUtagFUNCDESC@@@Z
+ 0006:2D8A ?InvalidateNameCache@GenericTypeLibOLE@@RECXI@Z
+ 001E:0BEA ?Invoke@GEN_DTINFO@@VEAPEXPEXJGPEUtagDISPPARAMS@@PEUtagVARIANT@@PEUtagEXCEPINFO@@PEI@Z
+ 0004:0AE0 ?Invoke@STL_TYPEINFO@@VEAPEXPEXJGPEUtagDISPPARAMS@@PEUtagVARIANT@@PEUtagEXCEPINFO@@PEI@Z
+ 001B:0000 ?IsFunkyDispinterface@@ZAPEXPEVGEN_DTINFO@@PEH@Z
+ 001B:2132 ?IsIdMungable@DYN_TYPEROOT@@RECHKPEG@Z
+ 001B:0350 ?IsInterfaceSupported@@ZAPEXPEUITypeInfo@@PEH@Z
+ 0005:3F66 ?IsLaidOut@DYN_TYPEMEMBERS@@VECHXZ
+ 0004:0D78 ?IsName@GenericTypeLibOLE@@VEAPEXPEDKPEH@Z
+ 0004:0C64 ?IsName@NAMMGR@@RECPEXPEDKPEH@Z
+ 0005:13E6 ?IsolateFilename@@ZAPEDPED@Z
+ 0003:110E ?IsProtocol@GENPROJ_TYPEBIND@@VECHXZ
+ 0005:67C6 ?IsReady@GEN_DTINFO@@VECHXZ
+ 0005:0260 ?IsSimpleType@@ZAHW4TYPEDESCKIND@@@Z
+ 0005:3E8C ?IsSimpleTypeAlias@TYPE_DATA@@RFCHXZ
+ 0005:6E64 ?IsSub@FUNC_DEFN@@RFCHXZ
+ 0006:3568 ?IsUnqualifiable@@ZAHPEVGEN_DTINFO@@@Z
+ 0005:671E ?IterationNotInProgress@GEN_DTINFO@@VECHXZ
+ 001C:127A ?Layout@DYN_TYPEMEMBERS@@JECPEXXZ
+ 001C:039C ?LayOut@GEN_DTINFO@@VEAPEXXZ
+ 0005:66EA ?LayOut@STL_TYPEINFO@@VEAPEXXZ
+ 001C:0D2E ?LayoutBases@DYN_TYPEMEMBERS@@JECPEXW4tagTYPEKIND@@PEI1@Z
+ 001C:104E ?LayoutDataMembers@DYN_TYPEMEMBERS@@JECPEXW4tagTYPEKIND@@PEI1I@Z
+ 001C:10DE ?LayoutMembers@DYN_TYPEMEMBERS@@JECPEXXZ
+ 001C:0E88 ?LayoutVarOfHvdefn@DYN_TYPEMEMBERS@@RECPEXW4tagTYPEKIND@@IPEGPEIHIH@Z
+ 0010:0000 ?LHashValOfDBCSName@@ZAKW4tagSYSKIND@@KPFD@Z
+ 0006:2C50 ?LoadNameCache@GenericTypeLibOLE@@RECPEXXZ
+ 001D:01C2 ?LockRegion@FileLockBytes@@VEAPEXU_ULARGE_INTEGER@@0K@Z
+ 001D:0168 ?LockRegion@GTLibStream@@VEAPEXU_ULARGE_INTEGER@@0K@Z
+ 0007:5F46 ?LookupStream@GTLibStorage@@JECPEUStreamInfo@@PFD@Z
+ 0007:51C8 ?LookupTypeLib@OLE_TYPEMGR@@RECPEUITypeLib@@PFD@Z
+ 0004:0D26 ?LpstrOfHgnam@NAMMGR@@RFCPEDK@Z
+ 0005:0F86 ?MakeAbsolutePath@@ZAPEXPED0PEPED@Z
+ 001B:07BA ?MakeDual@GEN_DTINFO@@RECPEXXZ
+ 001B:0A5A ?MakeHimptypeLevels@DYN_TYPEROOT@@RECPEXXZ
+ 001C:0CA2 ?MakeLaidOut@DYN_TYPEMEMBERS@@VECPEXXZ
+ 0006:2DFA ?MakeLocalTypeId@GenericTypeLibOLE@@JECPEXPEI@Z
+ 0010:0800 ?MapDBChar@@ZAGGK@Z
+ 001D:00B4 ?MoveElementTo@GTLibStorage@@VEAPEXPFDPEUIStorage@@0K@Z
+ 001F:0020 ?m_cbSizeInitial@SHEAP_MGR@@2IF
+ 0010:015B ?m_rgChinaSExcepMap@@3QEY01GE
+ 0010:0257 ?m_rgChinaTExcepMap@@3QEY01GE
+ 0010:0453 ?m_rgJapneseExcepMap@@3QEY01GE
+ 0010:0353 ?m_rgKoreaExcepMap@@3QEY01GE
+ 0004:1BF8 ?NewEntry@IMPMGR@@BECPEXPEPEVUB_IMPTYPE@@PEG@Z
+ 0002:820A ?NotifyStreamClosed@GTLibStorage@@JECXK@Z
+ 0002:1098 ?NotReady@GEN_DTINFO@@VECPEXXZ
+ 001F:026C ?oDbindnametbl@DYN_TYPEBIND@@2IF
+ 001F:025C ?oDtbind@DYN_TYPEMEMBERS@@2IF
+ 001F:02B4 ?oGbindnametbl@GENPROJ_TYPEBIND@@2IF
+ 001F:0078 ?oGptbind@GenericTypeLibOLE@@2IF
+ 0007:4A4A ?Open@DOCFILE_STREAM@@TAPEXPEPEUIStorage@@0HPEDW4STREAM_OPEN_MODE@@PEPEVSTREAM@@@Z
+ 0007:49B0 ?Open@DOCFILE_STREAM@@TAPEXPEPEUIStorage@@0PEVGenericTypeLibOLE@@IHPEDW4STREAM_OPEN_MODE@@PEPEVSTREAM@@@Z
+ 0007:621C ?Open@GTLibStream@@TAPEXPEUILockBytes@@KKPEPEUIStream@@@Z
+ 0007:63E2 ?OpenFileLockBytes@@ZAPEXHPEDPEPEUILockBytes@@@Z
+ 0007:5AB4 ?OpenForReadOnly@GTLibStorage@@TAPEXPEUILockBytes@@PEPEUIStorage@@@Z
+ 001D:0090 ?OpenStorage@GTLibStorage@@VEAPEXPFDPEUIStorage@@KPEPEDKPEPEU2@@Z
+ 0007:5FE2 ?OpenStream@GTLibStorage@@VEAPEXPFDPEXKKPEPEUIStream@@@Z
+ 0001:20D0 ?OpenTypeLibKey@@ZAPEXPEDGGPEUTLIBKEY@@@Z
+ 0007:4778 ?OpenTypeStream@GenericTypeLibOLE@@RECPEXIW4STREAM_OPEN_MODE@@PEPEVSTREAM@@@Z
+ 0007:661E ?Pappdata@@ZAPEUAPP_DATA@@XZ
+ 0002:6C9E ?ParseString@DOCSTR_MGR@@BECPEXPFDPEPEPEDPEI@Z
+ 0005:228C ?PbConstVal@@ZAPEEPEVTYPE_DATA@@PEVVAR_DEFN@@@Z
+ 001B:20C2 ?PdfntbindSemiDeclared@DYN_TYPEROOT@@RECPEXPEPEVDEFN_TYPEBIND@@@Z
+ 0006:3E4C ?Pdtmbrs@DYN_TYPEBIND@@RFCPEVDYN_TYPEMEMBERS@@XZ
+ 0007:59C8 ?Pgtlibole@GENPROJ_TYPEBIND@@RFCPEVGenericTypeLibOLE@@XZ
+ 0005:6F02 ?PnodeOfHlnam@PROPERTY_NODE@@RECPEU1@I@Z
+ 0007:53A0 ?Poletmgr@@ZAPEVOLE_TYPEMGR@@XZ
+ 0006:174A ?PrepareForDestruction@GEN_DTINFO@@VECXXZ
+ 0004:0ADC ?PrepareForDestruction@STL_TYPEINFO@@VECXXZ
+ 0002:7866 ?ProcessDocStrings@DOCSTR_MGR@@RECPEXXZ
+ 0005:5948 ?Ptdata@DYN_TYPEBIND@@RECPEVTYPE_DATA@@XZ
+ 0007:08DE ?PtrOfBlkDescLast@SHEAP_MGR@@JFCPEVBLK_DESC@@XZ
+ 0007:0878 ?PtrOfBlkDescPrev@SHEAP_MGR@@JFCPEVBLK_DESC@@PEV2@@Z
+ 0005:6E42 ?QdefnOfHdefn@TYPE_DATA@@RFCPEVDEFN@@II@Z
+ 0006:2E70 ?QHteRef@GenericTypeLibOLE@@JECPEGG@Z
+ 0007:44E6 ?QszLibIdOrFile@GenericTypeLibOLE@@JECPEDXZ
+ 0006:2DCA ?QszOfHsz@GenericTypeLibOLE@@JECPEDI@Z
+ 0006:4656 ?QtrOfHandle@BLK_MGR@@RFCPEEI@Z
+ 0007:44B8 ?QtrOfHChunk@GenericTypeLibOLE@@JECPEXI@Z
+ 0003:20A4 ?QueryInterface@CDefnTypeComp@@VEAPEXAFUGUID@@PEPEX@Z
+ 0006:1826 ?QueryInterface@DYNTYPEINFO@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:640C ?QueryInterface@FileLockBytes@@VEAPEXAFUGUID@@PEPEX@Z
+ 0006:2510 ?QueryInterface@GenericTypeLibOLE@@VEAPEXAFUGUID@@PEPEX@Z
+ 0006:4674 ?QueryInterface@GenericTypeLibOLE@@X3EAPEXAFUGUID@@PEPEX@Z
+ 0006:0BAE ?QueryInterface@GEN_DTINFO@@VEAPEXAFUGUID@@PEPEX@Z
+ 0006:464A ?QueryInterface@GEN_DTINFO@@X3EAPEXAFUGUID@@PEPEX@Z
+ 0005:6236 ?QueryInterface@GTLibStorage@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:62CA ?QueryInterface@GTLibStream@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:0A1C ?QueryInterface@STL_TYPEINFO@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:66FA ?QueryInterface@STL_TYPEINFO@@X3EAPEXAFUGUID@@PEPEX@Z
+ 0003:0658 ?QueryProtocol@DEFN_TYPEBIND@@VECPEXPED@Z
+ 0005:4FFE ?QueryProtocol@DYN_TYPEBIND@@VECPEXPED@Z
+ 0003:0EF8 ?QueryProtocol@GENPROJ_TYPEBIND@@VECPEXPED@Z
+ 0002:2F4E ?QuickSortIndex@@ZAXPEKPEII@Z
+ 0004:0634 ?Read@BLK_DESC@@RECPEXPEVSTREAM@@@Z
+ 0004:00E2 ?Read@BLK_MGR@@RECPEXPEVSTREAM@@@Z
+ 0007:4C70 ?Read@DOCFILE_STREAM@@VECPEXPEXK@Z
+ 0003:0906 ?Read@DOCSTR_MGR@@RECPEXPEVSTREAM@@@Z
+ 0005:5DB6 ?Read@DYN_BINDNAME_TABLE@@RECPEXPEVSTREAM@@@Z
+ 0005:5AE0 ?Read@DYN_TYPEBIND@@RECPEXPEVSTREAM@@@Z
+ 0005:44E8 ?Read@DYN_TYPEMEMBERS@@RECPEXPEVSTREAM@@@Z
+ 001B:1E90 ?Read@DYN_TYPEROOT@@NECPEXXZ
+ 0003:033C ?Read@ENTRYMGR@@RECPEXPEVSTREAM@@@Z
+ 0007:3EAE ?Read@GenericTypeLibOLE@@JECPEXPEVSTREAM@@@Z
+ 0007:3D36 ?Read@GenericTypeLibOLE@@JECPEXXZ
+ 0003:06CC ?Read@GENPROJ_BINDNAME_TABLE@@RECPEXPEVSTREAM@@@Z
+ 0003:1120 ?Read@GENPROJ_TYPEBIND@@RECPEXPEVSTREAM@@@Z
+ 0005:673C ?Read@GEN_DTINFO@@VECPEXXZ
+ 0007:6344 ?Read@GTLibStream@@VEAPEXPIXKPEK@Z
+ 0004:1F16 ?Read@IMPMGR@@RECPEXPEVSTREAM@@@Z
+ 0004:0AF0 ?Read@NAMMGR@@RECPEXPEVSTREAM@@@Z
+ 0005:19E8 ?Read@TYPE_DATA@@RECPEXPEVSTREAM@@@Z
+ 0007:6596 ?ReadAt@FileLockBytes@@VEAPEXU_ULARGE_INTEGER@@PIXKPEK@Z
+ 0004:0212 ?ReadByte@STREAM@@RECPEXPEE@Z
+ 001B:1FCE ?ReadFixed@DYN_TYPEROOT@@NECPEXPEVSTREAM@@@Z
+ 0006:2AFA ?ReadNameCacheArray@GenericTypeLibOLE@@JECPEXXZ
+ 0007:3DBE ?ReadString@GenericTypeLibOLE@@JECPEXPEVSTREAM@@PEI@Z
+ 0004:0178 ?ReadSz@STREAM@@RECPEXPEPED@Z
+ 0007:4D2C ?ReadTextLine@DOCFILE_STREAM@@VECPEXPEDI@Z
+ 0007:05DE ?ReadULong@STREAM@@RECPEXPEK@Z
+ 0007:05BA ?ReadUShort@STREAM@@RECPEXPEG@Z
+ 0007:0AB8 ?Realloc@BLK_DESC@@RECPEXK@Z
+ 0004:04AE ?Realloc@SHEAP_MGR@@JECPEXPEVBLK_DESC@@K@Z
+ 0004:05C6 ?ReallocHeap@SHEAP_MGR@@BECPEXK@Z
+ 0004:0282 ?ReallocSeg@@ZAPEXKG@Z
+ 0007:245A ?RegCreateSubKey@@ZAPEXKPED0H@Z
+ 0004:1E74 ?RegisterDeclRefDep@IMPMGR@@RECPEXPEUITypeInfo@@@Z
+ 0003:2144 ?Release@CDefnTypeComp@@VEAKXZ
+ 0007:4E56 ?Release@DOCFILE_STREAM@@VECPEXXZ
+ 0005:50A0 ?Release@DYN_TYPEBIND@@VECXXZ
+ 0005:3EB8 ?Release@DYN_TYPEMEMBERS@@VECXXZ
+ 0007:6548 ?Release@FileLockBytes@@VEAKXZ
+ 0007:30A4 ?Release@GenericTypeLibOLE@@VEAKXZ
+ 0007:6810 ?Release@GenericTypeLibOLE@@X3EAKXZ
+ 0003:10B4 ?Release@GENPROJ_TYPEBIND@@VECXXZ
+ 0007:5EF8 ?Release@GTLibStorage@@VEAKXZ
+ 0007:62F6 ?Release@GTLibStream@@VEAKXZ
+ 0007:4FFA ?Release@OLE_TYPEMGR@@RECXXZ
+ 0006:1922 ?Release@STL_TYPEINFO@@VEAKXZ
+ 0005:6712 ?Release@STL_TYPEINFO@@X3EAKXZ
+ 0007:67A0 ?ReleaseAppData@@ZAXXZ
+ 0006:3CDA ?ReleaseDllEntries@@ZAXPEX@Z
+ 0003:027E ?ReleaseDllentrydefn@ENTRYMGR@@RECXI@Z
+ 0005:14F2 ?ReleaseDllentrydefn@TYPE_DATA@@RECXI@Z
+ 001B:1E3C ?ReleaseDtmbrs@DYN_TYPEROOT@@RECXXZ
+ 001B:1020 ?ReleaseFuncDesc@GEN_DTINFO@@VEAXPEUtagFUNCDESC@@@Z
+ 0005:6572 ?ReleaseFuncDesc@STL_TYPEINFO@@VEAXPEUtagFUNCDESC@@@Z
+ 0003:0E28 ?ReleaseHuffmanTree@DOCSTR_MGR@@BECXPEUHUFFMAN_TREE_MEM@@@Z
+ 001E:25CC ?ReleaseInvokeArgs@GEN_DTINFO@@QECXPEUINVOKEARGS@1@@Z
+ 0003:03F6 ?ReleaseLibrary@@ZAXPBUHINSTANCE__@@@Z
+ 0006:305C ?ReleasePtinfo@IMPMGR@@BECXI@Z
+ 001B:0438 ?ReleasePublicResources@GEN_DTINFO@@VECXXZ
+ 0007:451E ?ReleaseResources@GenericTypeLibOLE@@RECXXZ
+ 0007:55AE ?ReleaseResources@GENPROJ_BINDNAME_TABLE@@RECXXZ
+ 0007:5A9C ?ReleaseResources@GENPROJ_TYPEBIND@@RECXXZ
+ 0006:3F24 ?ReleaseTable@DYN_BINDNAME_TABLE@@RECXXZ
+ 0007:5562 ?ReleaseTable@GENPROJ_BINDNAME_TABLE@@RECXXZ
+ 0007:3A02 ?ReleaseTLibAttr@GenericTypeLibOLE@@VEAXPEUtagTLIBATTR@@@Z
+ 001B:1054 ?ReleaseTypeAttr@GEN_DTINFO@@VEAXPEUtagTYPEATTR@@@Z
+ 0005:6566 ?ReleaseTypeAttr@STL_TYPEINFO@@VEAXPEUtagTYPEATTR@@@Z
+ 001B:103A ?ReleaseVarDesc@GEN_DTINFO@@VEAXPEUtagVARDESC@@@Z
+ 0005:657E ?ReleaseVarDesc@STL_TYPEINFO@@VEAXPEUtagVARDESC@@@Z
+ 0005:5086 ?RelInternalRef@DYN_TYPEBIND@@RECXXZ
+ 0005:3F1C ?RelInternalRef@DYN_TYPEMEMBERS@@RECXXZ
+ 0006:174E ?RelInternalRef@STL_TYPEINFO@@RECXXZ
+ 0007:094C ?RemoveBlkdesc@SHEAP_MGR@@JECXPEVBLK_DESC@@@Z
+ 0006:0B82 ?RemoveInternalRefs@GEN_DTINFO@@VECXXZ
+ 0006:34DA ?RemoveInternalRefs@IMPMGR@@RECXXZ
+ 0003:0F3E ?RemoveNameFromTable@GENPROJ_TYPEBIND@@RECPEXPED@Z
+ 0003:08CC ?RemoveNameFromTableOfHlnam@GENPROJ_BINDNAME_TABLE@@RECPEXI@Z
+ 0003:07BA ?RemoveNameFromTableOfIbucket@GENPROJ_BINDNAME_TABLE@@JECPEXI@Z
+ 001D:00FC ?RenameElement@GTLibStorage@@VEAPEXPFD0@Z
+ 0007:45C4 ?ResetHsz@GenericTypeLibOLE@@JECPEXPEDPEI@Z
+ 001D:00C6 ?Revert@GTLibStorage@@VEAPEXXZ
+ 001D:0156 ?Revert@GTLibStream@@VEAPEXXZ
+ 0005:149C ?rtArrayInit@@ZCXPEUtagSAFEARRAY@@I@Z
+ 0002:2B10 ?SaveAllChanges@GenericTypeLibOLE@@VEAPEXPEUIStorage@@@Z
+ 0002:287E ?SaveAllChanges@GenericTypeLibOLE@@VEAPEXXZ
+ 0002:2708 ?SaveOrCopyChanges@GenericTypeLibOLE@@RECPEXPEUIStorage@@H@Z
+ 0005:6334 ?Seek@GTLibStream@@VEAPEXU_LARGE_INTEGER@@KPEU_ULARGE_INTEGER@@@Z
+ 0002:133E ?SetAlignment@GEN_DTINFO@@VEAPEXG@Z
+ 0005:661A ?SetAlignment@STL_TYPEINFO@@VEAPEXG@Z
+ 0007:0F84 ?SetBucketOfHash@NAMMGR@@BECXII@Z
+ 0005:62A0 ?SetClass@GTLibStorage@@VEAPEXAFUGUID@@@Z
+ 0006:1A9C ?SetContainingTypeLib@STL_TYPEINFO@@JECXPEVGenericTypeLibOLE@@@Z
+ 0007:3A26 ?SetDirectory@GenericTypeLibOLE@@JECPEXPED@Z
+ 0002:55C0 ?SetDllEntryDefn@TYPE_DATA@@RECPEXII@Z
+ 0002:15AE ?SetDocString@GenericTypeLibOLE@@VEAPEXPED@Z
+ 0002:0320 ?SetDocString@GEN_DTINFO@@VEAPEXPED@Z
+ 0005:65AA ?SetDocString@STL_TYPEINFO@@VEAPEXPED@Z
+ 001D:010E ?SetElementTimes@GTLibStorage@@VEAPEXPFDPFUtagFILETIME@@11@Z
+ 0002:0664 ?SetFuncAndParamNames@GEN_DTINFO@@VEAPEXIPEPEDI@Z
+ 0005:664A ?SetFuncAndParamNames@STL_TYPEINFO@@VEAPEXIPEPEDI@Z
+ 0002:4C22 ?SetFuncAndParamNames@TYPE_DATA@@RECPEXIPEPEDI@Z
+ 0002:4C98 ?SetFuncAndParamNamesOfHfdefn@TYPE_DATA@@RECPEXIPEPEDI@Z
+ 0002:0834 ?SetFuncDocString@GEN_DTINFO@@VEAPEXIPED@Z
+ 0005:668A ?SetFuncDocString@STL_TYPEINFO@@VEAPEXIPED@Z
+ 0002:50CC ?SetFuncDocString@TYPE_DATA@@RECPEXIPED@Z
+ 0002:0BA0 ?SetFuncHelpContext@GEN_DTINFO@@VEAPEXIK@Z
+ 0005:66AA ?SetFuncHelpContext@STL_TYPEINFO@@VEAPEXIK@Z
+ 0002:521A ?SetFuncHelpContext@TYPE_DATA@@RECPEXIK@Z
+ 0007:0F68 ?SetGtlibole@NAMMGR@@RECPEXPEVGenericTypeLibOLE@@@Z
+ 0002:2C8A ?SetGuid@GenericTypeLibOLE@@VEAPEXAFUGUID@@@Z
+ 0002:02B6 ?SetGuid@GEN_DTINFO@@VEAPEXAFUGUID@@@Z
+ 0005:658A ?SetGuid@STL_TYPEINFO@@VEAPEXAFUGUID@@@Z
+ 0002:34AA ?SetHchunkConstVal@@ZAXPEVVAR_DEFN@@I@Z
+ 0002:1710 ?SetHelpContext@GenericTypeLibOLE@@VEAPEXK@Z
+ 0002:037A ?SetHelpContext@GEN_DTINFO@@VEAPEXK@Z
+ 0005:65BA ?SetHelpContext@STL_TYPEINFO@@VEAPEXK@Z
+ 0002:15EC ?SetHelpFileName@GenericTypeLibOLE@@VEAPEXPED@Z
+ 0006:39E4 ?SetHvdefnPredeclared@TYPE_DATA@@RECXI@Z
+ 0002:12CE ?SetImplTypeFlags@GEN_DTINFO@@VEAPEXIH@Z
+ 0005:660A ?SetImplTypeFlags@STL_TYPEINFO@@VEAPEXIH@Z
+ 0002:3FD6 ?SetImplTypeFlags@TYPE_DATA@@RECPEXIH@Z
+ 0005:3E70 ?SetIsSimpleTypeAlias@TYPE_DATA@@RECXH@Z
+ 0002:1760 ?SetLcid@GenericTypeLibOLE@@VEAPEXK@Z
+ 0002:1732 ?SetLibFlags@GenericTypeLibOLE@@VEAPEXI@Z
+ 0007:3A88 ?SetLibId@GenericTypeLibOLE@@RECPEXPED@Z
+ 0007:4658 ?SetModified@GenericTypeLibOLE@@RECPEXH@Z
+ 0006:1A1C ?SetModified@STL_TYPEINFO@@RECPEXH@Z
+ 001D:002C ?SetMops@GEN_DTINFO@@VEAPEXIPED@Z
+ 0005:66CA ?SetMops@STL_TYPEINFO@@VEAPEXIPED@Z
+ 0002:2BEE ?SetName@GenericTypeLibOLE@@VEAPEXPED@Z
+ 0002:7CFC ?SetNthBit@DOCSTR_MGR@@BECXIPEEW4HCODE@@@Z
+ 0006:2F28 ?SetPos@DOCFILE_STREAM@@VECPEXJ@Z
+ 0004:1924 ?SetPtinfo@IMPMGR@@BECPEXIPEUITypeInfo@@H@Z
+ 001D:006C ?SetSchema@GEN_DTINFO@@VEAPEXPED@Z
+ 0005:662A ?SetSchema@STL_TYPEINFO@@VEAPEXPED@Z
+ 001D:01B0 ?SetSize@FileLockBytes@@VEAPEXU_ULARGE_INTEGER@@@Z
+ 001D:0132 ?SetSize@GTLibStream@@VEAPEXU_ULARGE_INTEGER@@@Z
+ 001D:0120 ?SetStateBits@GTLibStorage@@VEAPEXKK@Z
+ 0005:616E ?SetTableSize@DYN_BINDNAME_TABLE@@JECPEXI@Z
+ 0006:42F4 ?SetTableSize@GENPROJ_BINDNAME_TABLE@@JECPEXI@Z
+ 0002:3F82 ?SetTypeDefnAlias@TYPE_DATA@@RECPEXPEUtagTYPEDESC@@@Z
+ 0002:0788 ?SetTypeDescAlias@GEN_DTINFO@@VEAPEXPEUtagTYPEDESC@@@Z
+ 0005:666A ?SetTypeDescAlias@STL_TYPEINFO@@VEAPEXPEUtagTYPEDESC@@@Z
+ 0002:2B30 ?SetTypeDocString@GenericTypeLibOLE@@RECPEXIPED@Z
+ 0002:0470 ?SetTypeFlags@GEN_DTINFO@@VEAPEXI@Z
+ 0005:659A ?SetTypeFlags@STL_TYPEINFO@@VEAPEXI@Z
+ 0002:2B9A ?SetTypeHelpContext@GenericTypeLibOLE@@RECPEXIK@Z
+ 001D:003E ?SetTypeIdldesc@GEN_DTINFO@@VEAPEXPEUtagIDLDESC@@@Z
+ 0005:66DA ?SetTypeIdldesc@STL_TYPEINFO@@VEAPEXPEUtagIDLDESC@@@Z
+ 0002:0B1A ?SetVarDocString@GEN_DTINFO@@VEAPEXIPED@Z
+ 0005:669A ?SetVarDocString@STL_TYPEINFO@@VEAPEXIPED@Z
+ 0002:5158 ?SetVarDocString@TYPE_DATA@@RECPEXIPED@Z
+ 0002:0C26 ?SetVarHelpContext@GEN_DTINFO@@VEAPEXIK@Z
+ 0005:66BA ?SetVarHelpContext@STL_TYPEINFO@@VEAPEXIK@Z
+ 0002:52A2 ?SetVarHelpContext@TYPE_DATA@@RECPEXIK@Z
+ 0002:0702 ?SetVarName@GEN_DTINFO@@VEAPEXIPED@Z
+ 0005:665A ?SetVarName@STL_TYPEINFO@@VEAPEXIPED@Z
+ 0002:4B4C ?SetVarName@TYPE_DATA@@RECPEXIPED@Z
+ 0002:2BC8 ?SetVersion@GenericTypeLibOLE@@VEAPEXGG@Z
+ 0002:03D8 ?SetVersion@GEN_DTINFO@@VEAPEXGG@Z
+ 0005:65CA ?SetVersion@STL_TYPEINFO@@VEAPEXGG@Z
+ 0004:03AC ?ShiftHeap@SHEAP_MGR@@BECXPEVBLK_DESC@@J@Z
+ 0005:16FC ?SizeofConstVal@TYPE_DATA@@RECIPEVVAR_DEFN@@I@Z
+ 0005:1F5C ?SizeOfTypeDefn@TYPE_DATA@@RFCII@Z
+ 0002:344C ?SizeTypeDefnOfTDescKind@TYPE_DATA@@BFCIIPEW4TYPEDESCKIND@@@Z
+ 0002:835A ?SortStreamInfo@GTLibStorage@@JECXPEUStreamInfo@@I@Z
+ 0006:36A8 ?SplitGuidLibId@@ZAPEXPEDPEPED1PEG2PEK11@Z
+ 0007:1CB6 ?SplitResID@@ZAPEXPEDPEPED@Z
+ 001D:01E4 ?Stat@FileLockBytes@@VEAPEXPEUtagSTATSTG@@K@Z
+ 0007:60AC ?Stat@GTLibStorage@@VEAPEXPEUtagSTATSTG@@K@Z
+ 001D:018C ?Stat@GTLibStream@@VEAPEXPEUtagSTATSTG@@K@Z
+ 0006:22FE ?StriEq@NAMMGR@@RECHPFD0@Z
+ 0005:3AEE ?StringOfHchunk@TYPE_DATA@@RECPEXIPEPED@Z
+ 0006:21AE ?StrOfHlnam@NAMMGR@@RFCPEXIPEDI@Z
+ 0002:2EBC ?SwapElementIndex@@YAXPEKPEIII@Z
+ 0002:826C ?SwapStreamInfos@GTLibStorage@@JECXPEUStreamInfo@@0@Z
+ 001F:0284 ?szBaseName@DEFN_TYPEBIND@@2PEDE
+ 001F:0074 ?szDirStreamName@GenericTypeLibOLE@@1QEDE
+ 0005:01BA ?SzLibIdLocalTypeIdOfTypeId@@ZAPEXPEDPEPED1@Z
+ 001F:01A6 ?szPlatSubkey1@@3PEDE
+ 001F:01AA ?szPlatSubkey2@@3PEDE
+ 001F:0280 ?szProtocolName@DEFN_TYPEBIND@@2PEDE
+ 001F:0268 ?szProtocolName@DYN_TYPEBIND@@2PEDE
+ 001F:02B0 ?szProtocolName@GENPROJ_TYPEBIND@@2PEDE
+ 0003:0FD6 ?tcomp@@ZAPEXPEUITypeLib@@PEPEUITypeComp@@@Z
+ 0005:00B2 ?TiperrOfOFErr@@ZAPEXI@Z
+ 0005:5EAC ?TraverseDefnList@DYN_BINDNAME_TABLE@@JECPEXI@Z
+ 0002:7BF8 ?TraverseHuffmanTree@DOCSTR_MGR@@BECPEXPEUHUFFMAN_TREE_MEM@@PEEI@Z
+ 0002:0046 ?Trim@BLK_MGR@@BECPEXPEI@Z
+ 0002:0000 ?Trim@BLK_MGR@@RECPEXXZ
+ 0004:1680 ?TypeInfoFromCompressedTypeId@GenericTypeLibOLE@@RECPEXPEDPEPEUITypeInfo@@@Z
+ 0007:5026 ?TypeLibLoaded@OLE_TYPEMGR@@RECPEXPFDPEUITypeLib@@@Z
+ 0007:512C ?TypeLibUnloaded@OLE_TYPEMGR@@RECXPEUITypeLib@@@Z
+ 0005:3970 ?UHelpContextOfEncoding@TYPE_DATA@@RECKG@Z
+ 0002:1DA4 ?UnAddTypeEntry@GenericTypeLibOLE@@JECXI@Z
+ 0007:1BA2 ?UninitLoadInfo@@ZAXPEULoadInfo@@@Z
+ 001D:01D4 ?UnlockRegion@FileLockBytes@@VEAPEXU_ULARGE_INTEGER@@0K@Z
+ 001D:017A ?UnlockRegion@GTLibStream@@VEAPEXU_ULARGE_INTEGER@@0K@Z
+ 0004:1E24 ?Unref@IMPMGR@@RECXI@Z
+ 0002:586A ?UpdateADocString@TYPE_DATA@@RECPEXPEVDOCSTR_MGR@@IPEI@Z
+ 0005:462C ?UpdateBinderOptimization@DYN_TYPEMEMBERS@@JECPEXIIH@Z
+ 0002:561E ?UpdateDocStrings@TYPE_DATA@@RECPEXXZ
+ 0005:48C2 ?UpdateNameCacheOfBaseClass@DYN_TYPEMEMBERS@@JECPEXPEUITypeInfo@@I@Z
+ 0005:47E4 ?UpdateNameCacheOfHdefnList@DYN_TYPEMEMBERS@@JECPEXIW4INFOKIND@@I@Z
+ 001C:097E ?UpdateTypeId@GenericTypeLibOLE@@RECPEXI@Z
+ 0002:34BC ?ValidateMemid@@ZAPEXJ@Z
+ 001E:0B86 ?VariantVtOfHtdefn@GEN_DTINFO@@QECPEXIPEVTYPE_DATA@@HPEGPEUGUID@@1@Z
+ 001E:0822 ?VariantVtOfTypedesc@GEN_DTINFO@@QECPEXPEUtagTYPEDESC@@PEGPEUGUID@@1@Z
+ 0007:1BE4 ?VerifyIsExeOrTlb@@YAPEXPEULoadInfo@@@Z
+ 0002:5E90 ?VerifyProperties@@ZAPEXPEVDYN_TYPEROOT@@PEUPROPERTY_NODE@@@Z
+ 0002:58FE ?VerifyTwoProperties@@ZAPEXPEVDYN_TYPEROOT@@PEVTYPE_DATA@@IW4PROPKIND@@I2@Z
+ 0007:1134 ?wcsicmp@@ZAIPEG0@Z
+ 0007:1114 ?wcslen@@ZAIPEG@Z
+ 001F:0264 ?wCurFormat@ENTRYMGR@@0GF
+ 001F:006C ?wDefaultVersion@GenericTypeLibOLE@@1GF
+ 001F:006E ?wDualVersion@GenericTypeLibOLE@@1GF
+ 001F:0260 ?wFirstSerWord@ENTRYMGR@@0GF
+ 001F:006A ?wFirstSerWord@GenericTypeLibOLE@@1GF
+ 001F:0070 ?wMaxVersion@GenericTypeLibOLE@@1GF
+ 0002:025A ?Write@BLK_DESC@@RECPEXPEVSTREAM@@@Z
+ 0002:016E ?Write@BLK_MGR@@RECPEXPEVSTREAM@@@Z
+ 0003:0000 ?Write@DOCFILE_STREAM@@VECPEXPFXK@Z
+ 0002:6BB0 ?Write@DOCSTR_MGR@@RECPEXPEVSTREAM@@@Z
+ 0002:6A74 ?Write@DYN_BINDNAME_TABLE@@RECPEXPEVSTREAM@@@Z
+ 0002:693E ?Write@DYN_TYPEBIND@@RECPEXPEVSTREAM@@@Z
+ 0002:67D0 ?Write@DYN_TYPEMEMBERS@@RECPEXPEVSTREAM@@@Z
+ 001C:0866 ?Write@DYN_TYPEROOT@@NECPEXXZ
+ 0002:68BA ?Write@ENTRYMGR@@RECPEXPEVSTREAM@@@Z
+ 0002:209A ?Write@GenericTypeLibOLE@@JECPEXPEVSTREAM@@@Z
+ 0002:201C ?Write@GenericTypeLibOLE@@JECPEXXZ
+ 0002:6ACC ?Write@GENPROJ_BINDNAME_TABLE@@RECPEXPEVSTREAM@@@Z
+ 0002:7F36 ?Write@GENPROJ_TYPEBIND@@RECPEXPEVSTREAM@@@Z
+ 0005:675E ?Write@GEN_DTINFO@@VECPEXXZ
+ 0002:88F4 ?Write@GTLibStream@@VEAPEXPJXKPEK@Z
+ 0002:2CB6 ?Write@IMPMGR@@RECPEXPEVSTREAM@@@Z
+ 0002:136A ?Write@NAMMGR@@RECPEXPEVSTREAM@@@Z
+ 0002:3160 ?Write@TYPE_DATA@@RECPEXPEVSTREAM@@@Z
+ 0002:8998 ?WriteAt@FileLockBytes@@VEAPEXU_ULARGE_INTEGER@@PJXKPEK@Z
+ 0002:01EE ?WriteByte@STREAM@@RECPEXE@Z
+ 0002:0DBC ?WriteFixed@DYN_TYPEROOT@@NECPEXPEVSTREAM@@@Z
+ 0002:2DD2 ?WriteLayoutEntries@IMPMGR@@RECPEXPEVSTREAM@@H@Z
+ 0002:0E76 ?WriteParts@DYN_TYPEROOT@@NECPEXPEVSTREAM@@@Z
+ 0002:1E66 ?WriteString@GenericTypeLibOLE@@JECPEXPEVSTREAM@@I@Z
+ 0002:0CAC ?WriteToStream@DYN_TYPEROOT@@NECPEXPEVSTREAM@@@Z
+ 0005:6780 ?WriteToStream@GEN_DTINFO@@VECPEXPEVSTREAM@@@Z
+ 0002:1A82 ?WriteTypeId@GenericTypeLibOLE@@RECPEXPEVSTREAM@@PEUITypeInfo@@@Z
+ 0002:0236 ?WriteULong@STREAM@@RECPEXK@Z
+ 0002:0212 ?WriteUShort@STREAM@@RECPEXG@Z
+ 0007:5950 ?ZeroFill@@ZAXPIXK@Z
+ 001F:002E ?_mbascii@@3IE
+ 0000:0000 Imp ANSITOOEMBUFF (KEYBOARD.134)
+ 0005:1480 CBSIZEARRAYDESC
+ 0000:0000 Imp COCREATEINSTANCE (COMPOBJ.13)
+ 0000:0000 Imp COGETCURRENTPROCESS (COMPOBJ.34)
+ 0000:0000 Imp COGETMALLOC (COMPOBJ.4)
+ 0000:0000 Imp COMPARESTRINGA (OLE2NLS.8)
+ 0000:0000 Imp CREATEBINDCTX (OLE2.26)
+ 0002:13CE CREATETYPELIB
+ 0000:0000 Imp DOINVOKEMETHOD (OLE2DISP.107)
+ 0000:0000 Imp DOS3CALL (KERNEL.102)
+ 0000:0000 Imp FATALAPPEXIT (KERNEL.137)
+ 0000:0000 Imp FATALEXIT (KERNEL.1)
+ 0006:005C FREEHSYS
+ 0000:0000 Imp FREELIBRARY (KERNEL.96)
+ 0000:0000 Imp GETACTIVEOBJECT (OLE2DISP.37)
+ 0000:0000 Imp GETDOSENVIRONMENT (KERNEL.131)
+ 0000:0000 Imp GETDRIVETYPE (KERNEL.136)
+ 0000:0000 Imp GETERRORINFO (OLE2DISP.111)
+ 0000:0000 Imp GETMODULEUSAGE (KERNEL.48)
+ 0000:0000 Imp GETPROCADDRESS (KERNEL.50)
+ 0000:0000 Imp GETSYSTEMDEFAULTLCID (OLE2NLS.2)
+ 0000:0000 Imp GETUSERDEFAULTLCID (OLE2NLS.1)
+ 0000:0000 Imp GETVERSION (KERNEL.3)
+ 0000:0000 Imp GLOBALALLOC (KERNEL.15)
+ 0000:0000 Imp GLOBALFREE (KERNEL.17)
+ 0000:0000 Imp GLOBALHANDLE (KERNEL.21)
+ 0000:0000 Imp GLOBALLOCK (KERNEL.18)
+ 0000:0000 Imp GLOBALREALLOC (KERNEL.16)
+ 0000:0000 Imp GLOBALSIZE (KERNEL.20)
+ 0000:0000 Imp GLOBALUNLOCK (KERNEL.19)
+ 0000:0000 Imp HMEMCPY (KERNEL.348)
+ 0006:001C HSYSALLOC
+ 0004:06A8 HSYSREALLOCHSYS
+ 0000:0000 Imp INITTASK (KERNEL.91)
+ 0000:0000 Imp ISDBCSLEADBYTE (KERNEL.207)
+ 0000:0000 Imp ISEQUALGUID (COMPOBJ.18)
+ 0004:0770 LHASHVALOFNAMESYS
+ 0001:24E4 LIBMAIN
+ 0000:0000 Imp LOADLIBRARY (KERNEL.95)
+ 0005:04E2 LOADREGTYPELIB
+ 0005:03BC LOADREGTYPELIBOFSZGUID
+ 0007:2010 LOADTYPELIB
+ 0000:0000 Imp LOCALINIT (KERNEL.4)
+ 0000:0000 Imp LOCKSEGMENT (KERNEL.23)
+ 0000:0000 Imp LSTRCMPI (USER.471)
+ 0000:0000 Imp MKPARSEDISPLAYNAME (OLE2.23)
+ 0001:24D2 OABUILDVERSION
+ 0000:0000 Imp OEMTOANSI (KEYBOARD.6)
+ 0000:0000 Imp OPENFILE (KERNEL.74)
+ 0005:1416 OWNETGETCONNECTION
+ 0000:0008 Abs pAtomTable
+ 0000:0006 Abs pLocalHeap
+ 0000:000E Abs pStackBot
+ 0000:000C Abs pStackMin
+ 0000:000A Abs pStackTop
+ 0001:201A QUERYPATHOFREGTYPELIB
+ 0000:0000 Imp READCLASSSTG (OLE2.18)
+ 0000:0000 Imp REGCLOSEKEY (SHELL.3)
+ 0000:0000 Imp REGCREATEKEY (SHELL.2)
+ 0000:0000 Imp REGENUMKEY (SHELL.7)
+ 0007:24C0 REGISTERTYPELIB
+ 0000:0000 Imp REGOPENKEY (SHELL.1)
+ 0000:0000 Imp REGQUERYVALUE (SHELL.6)
+ 0000:0000 Imp REGSETVALUE (SHELL.5)
+ 001F:0004 rsrvptrs
+ 0000:0000 Imp SAFEARRAYALLOCDESCRIPTOR (OLE2DISP.38)
+ 0000:0000 Imp SAFEARRAYCREATE (OLE2DISP.15)
+ 0000:0000 Imp SAFEARRAYDESTROY (OLE2DISP.16)
+ 0000:0000 Imp SAFEARRAYDESTROYDATA (OLE2DISP.41)
+ 0000:0000 Imp SAFEARRAYPUTELEMENT (OLE2DISP.26)
+ 0000:0000 Imp SETERRORMODE (KERNEL.107)
+ 0000:0000 Imp SETHANDLECOUNT (KERNEL.199)
+ 0000:0000 Imp STRINGFROMGUID2 (COMPOBJ.76)
+ 0000:0000 Imp SYSALLOCSTRING (OLE2DISP.2)
+ 0000:0000 Imp SYSALLOCSTRINGLEN (OLE2DISP.4)
+ 0000:0000 Imp SYSFREESTRING (OLE2DISP.6)
+ 0007:0B36 TLSALLOC
+ 0006:0000 TLSFREE
+ 0007:0C56 TLSGETVALUE
+ 0007:0B6E TLSSETVALUE
+ 0000:0000 Imp VARIANTCHANGETYPEEX (OLE2DISP.108)
+ 0000:0000 Imp VARIANTCLEAR (OLE2DISP.9)
+ 0000:0000 Imp VARIANTCOPY (OLE2DISP.10)
+ 0001:2500 WEP
+ 0000:0000 Imp WNETGETCONNECTION (USER.512)
+ 0000:0000 Imp WRITECLASSSTG (OLE2.19)
+ 0000:0000 Imp WRITEFMTUSERTYPESTG (OLE2.75)
+ 001F:02ED _aseghi
+ 001F:02EB _aseglo
+ 0001:0504 _atoi
+ 0001:19F4 _atol
+ 0004:09A8 _CLSID_GenericTypeLibOLE
+ 0004:0958 _CLSID_PSDispatch
+ 0004:0948 _CLSID_PSRemoteTypeInfo
+ 0004:09C8 _CLSID_TypeLibCF
+ 001F:0626 _edata
+ 001F:0C94 _end
+ 001F:0434 _errno
+ 0001:19F8 _getenv
+ 0000:0000 Imp _GUID_NULL (COMPOBJ.37)
+ 001F:02D4 _g_pAppdataCache
+ 001F:0C8E _g_pthreadCache
+ 001F:0022 _g_pthreadEnd
+ 001F:09D0 _g_rgbSlot
+ 001F:0626 _g_rgchLeadByteTable
+ 001F:09D2 _g_rgthread
+ 001F:02D2 _g_tidAppdataCache
+ 001F:0C92 _g_tidThreadCache
+ 0004:0978 _IID_CDefnTypeComp
+ 0004:0988 _IID_DYNTYPEINFO
+ 0004:0908 _IID_ICreateTypeInfo
+ 0004:0968 _IID_ICreateTypeLib
+ 0000:0000 Imp _IID_IDispatch (OLE2DISP.33)
+ 0004:09B8 _IID_IGenericTypeLibOLE
+ 0000:0000 Imp _IID_ILockBytes (COMPOBJ.48)
+ 0000:0000 Imp _IID_IStorage (COMPOBJ.49)
+ 0000:0000 Imp _IID_IStream (COMPOBJ.50)
+ 0004:0918 _IID_ITypeComp
+ 0004:0938 _IID_ITypeInfo
+ 0004:0928 _IID_ITypeLib
+ 0000:0000 Imp _IID_IUnknown (COMPOBJ.38)
+ 0004:0998 _IID_TYPEINFO
+ 0004:09D8 _IID_TYPELIB_GEN_DTINFO
+ 0001:1E3A _InitMbString
+ 0000:0000 Imp _LCLOSE (KERNEL.81)
+ 0000:0000 Imp _LLSEEK (KERNEL.84)
+ 0000:0000 Imp _LOPEN (KERNEL.85)
+ 0000:0000 Imp _LREAD (KERNEL.82)
+ 0000:0000 Imp _LWRITE (KERNEL.86)
+ 0001:0E08 _mblen
+ 0001:079C _mbstowcs
+ 0001:0E3A _mbtowc
+ 0007:0602 _MemAlloc
+ 0001:1D54 _MemFree
+ 0001:0594 _memmove
+ 0007:06B8 _MemRealloc
+ 0007:0684 _MemZalloc
+ 0001:080A _remove
+ 001F:02DE _STKHQQ
+ 0001:052E _strchr
+ 0001:19B8 _strcpy
+ 0001:0BF2 _strlen
+ 0001:04C8 _strncmp
+ 0001:049E _strncpy
+ 0001:0D46 _strpbrk
+ 0001:0560 _strrchr
+ 0001:066A _strtol
+ 0001:065E _strtoul
+ 0001:1DCA _TlsCleanupDeadTasks
+ 0007:5358 _VerifyLcid
+ 0001:24FA _WEP
+ 0006:49C6 _xstrdec
+ 001F:02DA __aaltstkovr
+ 0000:9876 Abs __acrtmsg
+ 0000:9876 Abs __acrtused
+ 0000:D6D6 Abs __aDBdoswp
+ 001F:040C __adbgmsg
+ 0000:D6D6 Abs __aDBused
+ 0001:0C62 __aFahdiff
+ 0001:0030 __aFchkstk
+ 0001:0830 __aFFalmul
+ 0001:0830 __aFFaulmul
+ 0001:0852 __aFlmul
+ 0001:1A94 __aFlrem
+ 0001:0884 __aFuldiv
+ 0001:0852 __aFulmul
+ 0001:08E4 __aFulrem
+ 0000:0000 Imp __AHINCR (KERNEL.114)
+ 0000:0000 Imp __AHSHIFT (KERNEL.113)
+ 001F:0426 __aintdiv
+ 001F:051E __amblksiz
+ 0001:0174 __amsg_exit
+ 0001:0010 __aNchkstk
+ 0001:00B6 __astart
+ 0001:0C0C __catox
+ 0001:132F __cexit
+ 0001:0EBE __chdrive
+ 001F:048D __child
+ 0001:0030 __chkstk
+ 0001:12DE __cinit
+ 0001:016A __cintDIV
+ 0001:0DA4 __cltoasub
+ 001F:043D __cpumode
+ 0001:1391 __ctermsub
+ 001F:030A __ctype
+ 001F:030A __ctype_
+ 0001:0DB1 __cxtoa
+ 0001:1340 __c_exit
+ 001F:04D0 __daylight
+ 001F:04B2 __days
+ 001F:02EA __dllinit
+ 001F:043E __doserrno
+ 001F:043A __dosmajor
+ 001F:043B __dosminor
+ 0001:0B80 __dosret0
+ 0001:0B9F __dosretax
+ 0001:0B8D __dosreturn
+ 001F:043A __dosversion
+ 0001:1264 __dos_findfirst
+ 0001:1252 __dos_findnext
+ 0001:0A82 __dtoxtime
+ 001F:0626 __edata
+ 001F:0C94 __end
+ 001F:0484 __environ
+ 001F:048F __exitflag
+ 001F:042A __fac
+ 0001:18F0 __ffree
+ 0001:097A __FF_MSGBANNER
+ 001F:0524 __fheap
+ 0001:18CF __findlast
+ 0001:1911 __fmalloc
+ 001F:0534 __fpinit
+ 0000:9876 Abs __fptaskdata
+ 0001:17A2 __fptrap
+ 0001:1C36 __freefarheap
+ 0001:1CC0 __freelist
+ 0001:1B9A __fstrlen
+ 0001:1B34 __fstrncmp
+ 0001:1B70 __fstrncpy
+ 0001:0F08 __fullpath
+ 0001:13B2 __getcwd
+ 0001:13D0 __getdcwd
+ 0001:048E __GetDGROUP
+ 0001:0E94 __getdrive
+ 0001:17D8 __growseg
+ 001F:02E0 __hModule
+ 0001:1869 __incseg
+ 0001:1CEA __initseg
+ 0001:0C82 __intdosx
+ 0001:16BC __isindst
+ 0001:0508 __itoa
+ 0001:1D1E __linkseg
+ 001F:0498 __lpdays
+ 001F:02E6 __lpszCmdLine
+ 0001:0BB1 __maperror
+ 0007:0CD6 __mbschr
+ 0006:491E __mbscmp
+ 0006:485C __mbsicmp
+ 0006:468C __mbslen
+ 0006:46E0 __mbsnbcpy
+ 0006:47A4 __mbsncmp
+ 0007:0D8C __mbsrchr
+ 0001:17A8 __myalloc
+ 0001:17D6 __nearstub
+ 0001:1BB4 __newseg
+ 001F:0440 __nfile
+ 0001:099E __NMSG_TEXT
+ 0001:09D5 __NMSG_WRITE
+ 0001:0151 __nomain
+ 001F:043E __oserr
+ 001F:0442 __osfile
+ 001F:0438 __osmajor
+ 001F:0439 __osminor
+ 001F:043C __osmode
+ 001F:0438 __osversion
+ 001F:0488 __pgmptr
+ 001F:0520 __pnhFarHeap
+ 0001:1C44 __searchseg
+ 0001:09EC __setenvp
+ 0000:0001 Abs __sizec
+ 0000:0001 Abs __sized
+ 0001:02A0 __stat
+ 0001:0D00 __strcmpi
+ 0001:0D00 __stricmp
+ 0001:094E __stubmain
+ 0001:253C __STUBWEP
+ 001F:04CC __timezone
+ 001F:04D2 __tzname
+ 0001:14F2 __tzset
+ 0001:0524 __ultoa
+ 001F:0436 __umaskval
+ 0001:080A __unlink
+ 001F:02E2 __wDataSeg
+ 0001:0072 __wflags
+ 001F:02E4 __wHeapSize
+ 0000:0000 Imp __WINFLAGS (KERNEL.178)
+ 001F:02F1 ___aDBrterr
+ 001F:02EF ___aDBswpflg
+ 001F:047E ___argc
+ 001F:0480 ___argv
+ 001F:04DA ___dnames
+ 0001:0BDE ___ExportedStub
+ 001F:0424 ___mb_cur_max
+ 001F:04F0 ___mnames
+ 0001:14D6 ___tzset
+
+ Address Publics by Value
+
+ 0000:0000 Imp SYSFREESTRING (OLE2DISP.6)
+ 0000:0000 Imp SYSALLOCSTRINGLEN (OLE2DISP.4)
+ 0000:0000 Imp HMEMCPY (KERNEL.348)
+ 0000:0000 Imp COCREATEINSTANCE (COMPOBJ.13)
+ 0000:0000 Imp _LREAD (KERNEL.82)
+ 0000:0000 Imp _LOPEN (KERNEL.85)
+ 0000:0000 Imp GETMODULEUSAGE (KERNEL.48)
+ 0000:0000 Imp LSTRCMPI (USER.471)
+ 0000:0000 Imp GLOBALALLOC (KERNEL.15)
+ 0000:0000 Imp CREATEBINDCTX (OLE2.26)
+ 0000:0000 Imp _IID_IStream (COMPOBJ.50)
+ 0000:0000 Imp WRITECLASSSTG (OLE2.19)
+ 0000:0000 Imp __WINFLAGS (KERNEL.178)
+ 0000:0000 Imp GLOBALUNLOCK (KERNEL.19)
+ 0000:0000 Imp MKPARSEDISPLAYNAME (OLE2.23)
+ 0000:0000 Imp _IID_IStorage (COMPOBJ.49)
+ 0000:0000 Imp ISEQUALGUID (COMPOBJ.18)
+ 0000:0000 Imp _GUID_NULL (COMPOBJ.37)
+ 0000:0000 Imp COGETMALLOC (COMPOBJ.4)
+ 0000:0000 Imp REGOPENKEY (SHELL.1)
+ 0000:0000 Imp REGCREATEKEY (SHELL.2)
+ 0000:0000 Imp REGCLOSEKEY (SHELL.3)
+ 0000:0000 Imp _IID_ILockBytes (COMPOBJ.48)
+ 0000:0000 Imp ISDBCSLEADBYTE (KERNEL.207)
+ 0000:0000 Imp GETERRORINFO (OLE2DISP.111)
+ 0000:0000 Imp SETERRORMODE (KERNEL.107)
+ 0000:0000 Imp VARIANTCLEAR (OLE2DISP.9)
+ 0000:0000 Imp FATALEXIT (KERNEL.1)
+ 0000:0000 Imp _LLSEEK (KERNEL.84)
+ 0000:0000 Imp ANSITOOEMBUFF (KEYBOARD.134)
+ 0000:0000 Imp GLOBALLOCK (KERNEL.18)
+ 0000:0000 Imp COMPARESTRINGA (OLE2NLS.8)
+ 0000:0000 Imp GLOBALFREE (KERNEL.17)
+ 0000:0000 Imp GLOBALREALLOC (KERNEL.16)
+ 0000:0000 Imp COGETCURRENTPROCESS (COMPOBJ.34)
+ 0000:0000 Imp SAFEARRAYDESTROY (OLE2DISP.16)
+ 0000:0000 Imp WNETGETCONNECTION (USER.512)
+ 0000:0000 Imp REGENUMKEY (SHELL.7)
+ 0000:0000 Imp SAFEARRAYALLOCDESCRIPTOR (OLE2DISP.38)
+ 0000:0000 Imp REGQUERYVALUE (SHELL.6)
+ 0000:0000 Imp VARIANTCHANGETYPEEX (OLE2DISP.108)
+ 0000:0000 Imp STRINGFROMGUID2 (COMPOBJ.76)
+ 0000:0000 Imp LOCALINIT (KERNEL.4)
+ 0000:0000 Imp GETDRIVETYPE (KERNEL.136)
+ 0000:0000 Imp GETSYSTEMDEFAULTLCID (OLE2NLS.2)
+ 0000:0000 Imp INITTASK (KERNEL.91)
+ 0000:0000 Imp GETACTIVEOBJECT (OLE2DISP.37)
+ 0000:0000 Imp SAFEARRAYCREATE (OLE2DISP.15)
+ 0000:0000 Imp WRITEFMTUSERTYPESTG (OLE2.75)
+ 0000:0000 Imp REGSETVALUE (SHELL.5)
+ 0000:0000 Imp _LCLOSE (KERNEL.81)
+ 0000:0000 Imp GETVERSION (KERNEL.3)
+ 0000:0000 Imp OPENFILE (KERNEL.74)
+ 0000:0000 Imp _LWRITE (KERNEL.86)
+ 0000:0000 Imp GLOBALHANDLE (KERNEL.21)
+ 0000:0000 Imp GETDOSENVIRONMENT (KERNEL.131)
+ 0000:0000 Imp GETUSERDEFAULTLCID (OLE2NLS.1)
+ 0000:0000 Imp FREELIBRARY (KERNEL.96)
+ 0000:0000 Imp VARIANTCOPY (OLE2DISP.10)
+ 0000:0000 Imp LOADLIBRARY (KERNEL.95)
+ 0000:0000 Imp READCLASSSTG (OLE2.18)
+ 0000:0000 Imp SAFEARRAYDESTROYDATA (OLE2DISP.41)
+ 0000:0000 Imp OEMTOANSI (KEYBOARD.6)
+ 0000:0000 Imp SYSALLOCSTRING (OLE2DISP.2)
+ 0000:0000 Imp GETPROCADDRESS (KERNEL.50)
+ 0000:0000 Imp DOINVOKEMETHOD (OLE2DISP.107)
+ 0000:0000 Imp FATALAPPEXIT (KERNEL.137)
+ 0000:0000 Imp __AHSHIFT (KERNEL.113)
+ 0000:0000 Imp GLOBALSIZE (KERNEL.20)
+ 0000:0000 Imp LOCKSEGMENT (KERNEL.23)
+ 0000:0000 Imp SAFEARRAYPUTELEMENT (OLE2DISP.26)
+ 0000:0000 Imp _IID_IDispatch (OLE2DISP.33)
+ 0000:0000 Imp __AHINCR (KERNEL.114)
+ 0000:0000 Imp SETHANDLECOUNT (KERNEL.199)
+ 0000:0000 Imp _IID_IUnknown (COMPOBJ.38)
+ 0000:0000 Imp DOS3CALL (KERNEL.102)
+ 0000:0001 Abs __sizec
+ 0000:0001 Abs __sized
+ 0000:0006 Abs pLocalHeap
+ 0000:0008 Abs pAtomTable
+ 0000:000A Abs pStackTop
+ 0000:000C Abs pStackMin
+ 0000:000E Abs pStackBot
+ 0000:9876 Abs __acrtused
+ 0000:9876 Abs __acrtmsg
+ 0000:9876 Abs __fptaskdata
+ 0000:D6D6 Abs __aDBused
+ 0000:D6D6 Abs __aDBdoswp
+ 0001:0010 __aNchkstk
+ 0001:0030 __chkstk
+ 0001:0030 __aFchkstk
+ 0001:0072 __wflags
+ 0001:00B6 __astart
+ 0001:0151 __nomain
+ 0001:016A __cintDIV
+ 0001:0174 __amsg_exit
+ 0001:02A0 __stat
+ 0001:048E __GetDGROUP
+ 0001:049E _strncpy
+ 0001:04C8 _strncmp
+ 0001:0504 _atoi
+ 0001:0508 __itoa
+ 0001:0524 __ultoa
+ 0001:052E _strchr
+ 0001:0560 _strrchr
+ 0001:0594 _memmove
+ 0001:065E _strtoul
+ 0001:066A _strtol
+ 0001:079C _mbstowcs
+ 0001:080A _remove
+ 0001:080A __unlink
+ 0001:0830 __aFFaulmul
+ 0001:0830 __aFFalmul
+ 0001:0852 __aFlmul
+ 0001:0852 __aFulmul
+ 0001:0884 __aFuldiv
+ 0001:08E4 __aFulrem
+ 0001:094E __stubmain
+ 0001:097A __FF_MSGBANNER
+ 0001:099E __NMSG_TEXT
+ 0001:09D5 __NMSG_WRITE
+ 0001:09EC __setenvp
+ 0001:0A82 __dtoxtime
+ 0001:0B80 __dosret0
+ 0001:0B8D __dosreturn
+ 0001:0B9F __dosretax
+ 0001:0BB1 __maperror
+ 0001:0BDE ___ExportedStub
+ 0001:0BF2 _strlen
+ 0001:0C0C __catox
+ 0001:0C62 __aFahdiff
+ 0001:0C82 __intdosx
+ 0001:0D00 __strcmpi
+ 0001:0D00 __stricmp
+ 0001:0D46 _strpbrk
+ 0001:0DA4 __cltoasub
+ 0001:0DB1 __cxtoa
+ 0001:0E08 _mblen
+ 0001:0E3A _mbtowc
+ 0001:0E94 __getdrive
+ 0001:0EBE __chdrive
+ 0001:0F08 __fullpath
+ 0001:1252 __dos_findnext
+ 0001:1264 __dos_findfirst
+ 0001:12DE __cinit
+ 0001:132F __cexit
+ 0001:1340 __c_exit
+ 0001:1391 __ctermsub
+ 0001:13B2 __getcwd
+ 0001:13D0 __getdcwd
+ 0001:14D6 ___tzset
+ 0001:14F2 __tzset
+ 0001:16BC __isindst
+ 0001:17A2 __fptrap
+ 0001:17A8 __myalloc
+ 0001:17D6 __nearstub
+ 0001:17D8 __growseg
+ 0001:1869 __incseg
+ 0001:18CF __findlast
+ 0001:18F0 __ffree
+ 0001:1911 __fmalloc
+ 0001:19B8 _strcpy
+ 0001:19F4 _atol
+ 0001:19F8 _getenv
+ 0001:1A94 __aFlrem
+ 0001:1B34 __fstrncmp
+ 0001:1B70 __fstrncpy
+ 0001:1B9A __fstrlen
+ 0001:1BB4 __newseg
+ 0001:1C36 __freefarheap
+ 0001:1C44 __searchseg
+ 0001:1CC0 __freelist
+ 0001:1CEA __initseg
+ 0001:1D1E __linkseg
+ 0001:1D54 _MemFree
+ 0001:1DCA _TlsCleanupDeadTasks
+ 0001:1E3A _InitMbString
+ 0001:1E7E ?GetRegisteredPath@@ZAPEXKPED0PEJH@Z
+ 0001:1ED0 ?GetRegInfoForTypeLibOfSzGuid@@ZAPEXPEDGGK0H@Z
+ 0001:201A QUERYPATHOFREGTYPELIB
+ 0001:20D0 ?OpenTypeLibKey@@ZAPEXPEDGGPEUTLIBKEY@@@Z
+ 0001:22EA ?CloseTypeLibKey@@ZAXPEUTLIBKEY@@@Z
+ 0001:2326 ?FExistsRegisteredTypelib@@ZAHKPEDPEPED@Z
+ 0001:23B8 ?GetBestLcidMatch@@ZAPEXKKPEKPEPED@Z
+ 0001:2474 ?FFileExists@@ZAHPFD@Z
+ 0001:24D2 OABUILDVERSION
+ 0001:24E4 LIBMAIN
+ 0001:24FA _WEP
+ 0001:2500 WEP
+ 0001:253C __STUBWEP
+ 0002:0000 ?Trim@BLK_MGR@@RECPEXXZ
+ 0002:0046 ?Trim@BLK_MGR@@BECPEXPEI@Z
+ 0002:016E ?Write@BLK_MGR@@RECPEXPEVSTREAM@@@Z
+ 0002:01EE ?WriteByte@STREAM@@RECPEXE@Z
+ 0002:0212 ?WriteUShort@STREAM@@RECPEXG@Z
+ 0002:0236 ?WriteULong@STREAM@@RECPEXK@Z
+ 0002:025A ?Write@BLK_DESC@@RECPEXPEVSTREAM@@@Z
+ 0002:02B6 ?SetGuid@GEN_DTINFO@@VEAPEXAFUGUID@@@Z
+ 0002:0320 ?SetDocString@GEN_DTINFO@@VEAPEXPED@Z
+ 0002:037A ?SetHelpContext@GEN_DTINFO@@VEAPEXK@Z
+ 0002:03D8 ?SetVersion@GEN_DTINFO@@VEAPEXGG@Z
+ 0002:0470 ?SetTypeFlags@GEN_DTINFO@@VEAPEXI@Z
+ 0002:0664 ?SetFuncAndParamNames@GEN_DTINFO@@VEAPEXIPEPEDI@Z
+ 0002:0702 ?SetVarName@GEN_DTINFO@@VEAPEXIPED@Z
+ 0002:0788 ?SetTypeDescAlias@GEN_DTINFO@@VEAPEXPEUtagTYPEDESC@@@Z
+ 0002:0834 ?SetFuncDocString@GEN_DTINFO@@VEAPEXIPED@Z
+ 0002:08D2 ?DefineFuncAsDllEntry@GEN_DTINFO@@VEAPEXIPED0@Z
+ 0002:0B1A ?SetVarDocString@GEN_DTINFO@@VEAPEXIPED@Z
+ 0002:0BA0 ?SetFuncHelpContext@GEN_DTINFO@@VEAPEXIK@Z
+ 0002:0C26 ?SetVarHelpContext@GEN_DTINFO@@VEAPEXIK@Z
+ 0002:0CAC ?WriteToStream@DYN_TYPEROOT@@NECPEXPEVSTREAM@@@Z
+ 0002:0DBC ?WriteFixed@DYN_TYPEROOT@@NECPEXPEVSTREAM@@@Z
+ 0002:0E76 ?WriteParts@DYN_TYPEROOT@@NECPEXPEVSTREAM@@@Z
+ 0002:0FD2 ?BeginDepIteration@GEN_DTINFO@@VECPEXPEPEUTINODE@@PEPEPEU2@@Z
+ 0002:0FD8 ?GetNextDepTypeInfo@GEN_DTINFO@@VECPEXPEPEVDYNTYPEINFO@@@Z
+ 0002:1092 ?AllDepReady@GEN_DTINFO@@VECPEXXZ
+ 0002:1098 ?NotReady@GEN_DTINFO@@VECPEXXZ
+ 0002:10DC ?AddVarDesc@GEN_DTINFO@@VEAPEXIPEUtagVARDESC@@@Z
+ 0002:11E0 ?AddFuncDesc@GEN_DTINFO@@VEAPEXIPEUtagFUNCDESC@@@Z
+ 0002:12CE ?SetImplTypeFlags@GEN_DTINFO@@VEAPEXIH@Z
+ 0002:133E ?SetAlignment@GEN_DTINFO@@VEAPEXG@Z
+ 0002:136A ?Write@NAMMGR@@RECPEXPEVSTREAM@@@Z
+ 0002:13CE CREATETYPELIB
+ 0002:14E6 ?CreateTypeInfo@GenericTypeLibOLE@@VEAPEXPEDW4tagTYPEKIND@@PEPEUICreateTypeInfo@@@Z
+ 0002:15AE ?SetDocString@GenericTypeLibOLE@@VEAPEXPED@Z
+ 0002:15EC ?SetHelpFileName@GenericTypeLibOLE@@VEAPEXPED@Z
+ 0002:1710 ?SetHelpContext@GenericTypeLibOLE@@VEAPEXK@Z
+ 0002:1732 ?SetLibFlags@GenericTypeLibOLE@@VEAPEXI@Z
+ 0002:1760 ?SetLcid@GenericTypeLibOLE@@VEAPEXK@Z
+ 0002:1820 ?GetCompressedTypeId@GenericTypeLibOLE@@RECPEXPEUITypeInfo@@PEPED@Z
+ 0002:1A82 ?WriteTypeId@GenericTypeLibOLE@@RECPEXPEVSTREAM@@PEUITypeInfo@@@Z
+ 0002:1B0C ?AddTypeEntry@GenericTypeLibOLE@@JECPEXPEDPEG@Z
+ 0002:1DA4 ?UnAddTypeEntry@GenericTypeLibOLE@@JECXI@Z
+ 0002:1E66 ?WriteString@GenericTypeLibOLE@@JECPEXPEVSTREAM@@I@Z
+ 0002:1F0A ?Add@GenericTypeLibOLE@@RECPEXPEVGEN_DTINFO@@PED@Z
+ 0002:201C ?Write@GenericTypeLibOLE@@JECPEXXZ
+ 0002:209A ?Write@GenericTypeLibOLE@@JECPEXPEVSTREAM@@@Z
+ 0002:2708 ?SaveOrCopyChanges@GenericTypeLibOLE@@RECPEXPEUIStorage@@H@Z
+ 0002:287E ?SaveAllChanges@GenericTypeLibOLE@@VEAPEXXZ
+ 0002:2B10 ?SaveAllChanges@GenericTypeLibOLE@@VEAPEXPEUIStorage@@@Z
+ 0002:2B30 ?SetTypeDocString@GenericTypeLibOLE@@RECPEXIPED@Z
+ 0002:2B9A ?SetTypeHelpContext@GenericTypeLibOLE@@RECPEXIK@Z
+ 0002:2BC8 ?SetVersion@GenericTypeLibOLE@@VEAPEXGG@Z
+ 0002:2BEE ?SetName@GenericTypeLibOLE@@VEAPEXPED@Z
+ 0002:2C8A ?SetGuid@GenericTypeLibOLE@@VEAPEXAFUGUID@@@Z
+ 0002:2CB6 ?Write@IMPMGR@@RECPEXPEVSTREAM@@@Z
+ 0002:2DD2 ?WriteLayoutEntries@IMPMGR@@RECPEXPEVSTREAM@@H@Z
+ 0002:2EBC ?SwapElementIndex@@YAXPEKPEIII@Z
+ 0002:2F4E ?QuickSortIndex@@ZAXPEKPEII@Z
+ 0002:3160 ?Write@TYPE_DATA@@RECPEXPEVSTREAM@@@Z
+ 0002:3352 ?AllocTypeDefn@TYPE_DATA@@BECPEXIQEW4TYPEDESCKIND@@PEG@Z
+ 0002:33D8 ?AllocArrayDescriptor@TYPE_DATA@@BECPEXIPEG@Z
+ 0002:344C ?SizeTypeDefnOfTDescKind@TYPE_DATA@@BFCIIPEW4TYPEDESCKIND@@@Z
+ 0002:34AA ?SetHchunkConstVal@@ZAXPEVVAR_DEFN@@I@Z
+ 0002:34BC ?ValidateMemid@@ZAPEXJ@Z
+ 0002:3510 ?AddFuncDesc@TYPE_DATA@@RECPEXIPEUtagFUNCDESC@@PEI@Z
+ 0002:3CDA ?AllocConstValOfVariant@TYPE_DATA@@BECPEXPEUtagVARIANT@@I@Z
+ 0002:3F82 ?SetTypeDefnAlias@TYPE_DATA@@RECPEXPEUtagTYPEDESC@@@Z
+ 0002:3FD6 ?SetImplTypeFlags@TYPE_DATA@@RECPEXIH@Z
+ 0002:4034 ?AllocTypeDefnOfTypeDesc@TYPE_DATA@@RECPEXPEUtagTYPEDESC@@IPEGHPEH@Z
+ 0002:46C0 ?AddVarDesc@TYPE_DATA@@RECPEXIPEUtagVARDESC@@PEI@Z
+ 0002:4B4C ?SetVarName@TYPE_DATA@@RECPEXIPED@Z
+ 0002:4C22 ?SetFuncAndParamNames@TYPE_DATA@@RECPEXIPEPEDI@Z
+ 0002:4C98 ?SetFuncAndParamNamesOfHfdefn@TYPE_DATA@@RECPEXIPEPEDI@Z
+ 0002:4F36 ?GetFuncDefnForDoc@TYPE_DATA@@RECII@Z
+ 0002:50CC ?SetFuncDocString@TYPE_DATA@@RECPEXIPED@Z
+ 0002:5158 ?SetVarDocString@TYPE_DATA@@RECPEXIPED@Z
+ 0002:521A ?SetFuncHelpContext@TYPE_DATA@@RECPEXIK@Z
+ 0002:52A2 ?SetVarHelpContext@TYPE_DATA@@RECPEXIK@Z
+ 0002:533E ?HchunkOfString@TYPE_DATA@@BECPEXPEDPEI@Z
+ 0002:53C4 ?EquivTypeDefnsIgnoreByRef@@ZAPEXPEVTYPE_DATA@@HG0HGGPEHH@Z
+ 0002:5592 ?EquivTypeDefns@@ZAPEXPEVTYPE_DATA@@HG0HGGPEH@Z
+ 0002:55C0 ?SetDllEntryDefn@TYPE_DATA@@RECPEXII@Z
+ 0002:561E ?UpdateDocStrings@TYPE_DATA@@RECPEXXZ
+ 0002:586A ?UpdateADocString@TYPE_DATA@@RECPEXPEVDOCSTR_MGR@@IPEI@Z
+ 0002:58FE ?VerifyTwoProperties@@ZAPEXPEVDYN_TYPEROOT@@PEVTYPE_DATA@@IW4PROPKIND@@I2@Z
+ 0002:5E90 ?VerifyProperties@@ZAPEXPEVDYN_TYPEROOT@@PEUPROPERTY_NODE@@@Z
+ 0002:61EA ?AllocHmembers@DYN_TYPEMEMBERS@@JECPEXXZ
+ 0002:66E4 ?GenerateOverrides@DYN_TYPEMEMBERS@@JECPEXXZ
+ 0002:67D0 ?Write@DYN_TYPEMEMBERS@@RECPEXPEVSTREAM@@@Z
+ 0002:684C ?AlignmentTdesckind@DYN_TYPEMEMBERS@@RECGW4TYPEDESCKIND@@@Z
+ 0002:68BA ?Write@ENTRYMGR@@RECPEXPEVSTREAM@@@Z
+ 0002:693E ?Write@DYN_TYPEBIND@@RECPEXPEVSTREAM@@@Z
+ 0002:6A74 ?Write@DYN_BINDNAME_TABLE@@RECPEXPEVSTREAM@@@Z
+ 0002:6ACC ?Write@GENPROJ_BINDNAME_TABLE@@RECPEXPEVSTREAM@@@Z
+ 0002:6BB0 ?Write@DOCSTR_MGR@@RECPEXPEVSTREAM@@@Z
+ 0002:6C9E ?ParseString@DOCSTR_MGR@@BECPEXPFDPEPEPEDPEI@Z
+ 0002:6E92 ?AddWord@DOCSTR_MGR@@BECPEXPEDPEPEUWORD_ENTRY@@@Z
+ 0002:6F6C ?AddNewWord@DOCSTR_MGR@@BECPEXPEDPEPEUWORD_ENTRY@@@Z
+ 0002:7050 ?GetHstOfHelpString@DOCSTR_MGR@@RECPEXPFDPEI@Z
+ 0002:72CE ?CreateSubTree@DOCSTR_MGR@@BECPEXPEUHUFFMAN_TREE_MEM@@0PEPEU2@@Z
+ 0002:7384 ?BuildHuffmanTree@DOCSTR_MGR@@BECPEXPEPEUWORD_ENTRY@@PEJPEI@Z
+ 0002:76FC ?BuildCmptHuffmanTree@DOCSTR_MGR@@BECPEXPEUHUFFMAN_TREE_MEM@@@Z
+ 0002:7866 ?ProcessDocStrings@DOCSTR_MGR@@RECPEXXZ
+ 0002:7BC2 ?EncodeWords@DOCSTR_MGR@@BECPEXXZ
+ 0002:7BF8 ?TraverseHuffmanTree@DOCSTR_MGR@@BECPEXPEUHUFFMAN_TREE_MEM@@PEEI@Z
+ 0002:7CFC ?SetNthBit@DOCSTR_MGR@@BECXIPEEW4HCODE@@@Z
+ 0002:7E18 ?GetEncodedDocStrOfHst@DOCSTR_MGR@@RECPEXIPEPEDPEI@Z
+ 0002:7F36 ?Write@GENPROJ_TYPEBIND@@RECPEXPEVSTREAM@@@Z
+ 0002:7FA2 ?Create@GTLibStorage@@TAPEXPEUILockBytes@@IPEPEUIStorage@@@Z
+ 0002:80CA ?CreateStream@GTLibStorage@@VEAPEXPFDKKKPEPEUIStream@@@Z
+ 0002:820A ?NotifyStreamClosed@GTLibStorage@@JECXK@Z
+ 0002:826C ?SwapStreamInfos@GTLibStorage@@JECXPEUStreamInfo@@0@Z
+ 0002:835A ?SortStreamInfo@GTLibStorage@@JECXPEUStreamInfo@@I@Z
+ 0002:85CE ?Commit@GTLibStorage@@VEAPEXK@Z
+ 0002:881A ?Create@GTLibStream@@TAPEXPEUILockBytes@@KPEVGTLibStorage@@PEPEUIStream@@@Z
+ 0002:88F4 ?Write@GTLibStream@@VEAPEXPJXKPEK@Z
+ 0002:8988 ?Commit@GTLibStream@@VEAPEXK@Z
+ 0002:8998 ?WriteAt@FileLockBytes@@VEAPEXU_ULARGE_INTEGER@@PJXKPEK@Z
+ 0002:8A16 ?Flush@FileLockBytes@@VEAPEXXZ
+ 0003:0000 ?Write@DOCFILE_STREAM@@VECPEXPFXK@Z
+ 0003:00C4 ?FlushBuffer@DOCFILE_STREAM@@JECPEXXZ
+ 0003:0176 ?DllEntryNameOfHchunk@ENTRYMGR@@RECPEXIPEDI@Z
+ 0003:01DC ?AllocDllentrydefn@ENTRYMGR@@BECPEXPEIIH@Z
+ 0003:027E ?ReleaseDllentrydefn@ENTRYMGR@@RECXI@Z
+ 0003:033C ?Read@ENTRYMGR@@RECPEXPEVSTREAM@@@Z
+ 0003:03F6 ?ReleaseLibrary@@ZAXPBUHINSTANCE__@@@Z
+ 0003:040A ?GetAddressOfDllentry@ENTRYMGR@@RECPEXIPEPEX@Z
+ 0003:0658 ?QueryProtocol@DEFN_TYPEBIND@@VECPEXPED@Z
+ 0003:06B8 ?GetOPvft@DEFN_TYPEBIND@@VECJXZ
+ 0003:06C0 ?GetCbSizeVft@DEFN_TYPEBIND@@VECGXZ
+ 0003:06C6 ?BindType@DEFN_TYPEBIND@@VECPEXKPEDI@Z
+ 0003:06CC ?Read@GENPROJ_BINDNAME_TABLE@@RECPEXPEVSTREAM@@@Z
+ 0003:07BA ?RemoveNameFromTableOfIbucket@GENPROJ_BINDNAME_TABLE@@JECPEXI@Z
+ 0003:08CC ?RemoveNameFromTableOfHlnam@GENPROJ_BINDNAME_TABLE@@RECPEXI@Z
+ 0003:0906 ?Read@DOCSTR_MGR@@RECPEXPEVSTREAM@@@Z
+ 0003:0AD2 ?GetNthBit@DOCSTR_MGR@@BEC?EW4HCODE@@IPEE@Z
+ 0003:0B70 ?GetWord@DOCSTR_MGR@@BECPEXPEXPEEPEIPED@Z
+ 0003:0C40 ?GetDecodedDocStrOfHst@DOCSTR_MGR@@RECPEXPEEPEPED@Z
+ 0003:0E28 ?ReleaseHuffmanTree@DOCSTR_MGR@@BECXPEUHUFFMAN_TREE_MEM@@@Z
+ 0003:0EF8 ?QueryProtocol@GENPROJ_TYPEBIND@@VECPEXPED@Z
+ 0003:0F3E ?RemoveNameFromTable@GENPROJ_TYPEBIND@@RECPEXPED@Z
+ 0003:0FD6 ?tcomp@@ZAPEXPEUITypeLib@@PEPEUITypeComp@@@Z
+ 0003:0FF8 ?BindAll@GENPROJ_TYPEBIND@@RECPEXHKIW4ACCESS@@W4COMPSTATE@@PEVEXBIND@@@Z
+ 0003:1024 ?BindDefnStr@GENPROJ_TYPEBIND@@VECPEXPEDIW4ACCESS@@PEVEXBIND@@@Z
+ 0003:10B4 ?Release@GENPROJ_TYPEBIND@@VECXXZ
+ 0003:10DE ?AddRef@GENPROJ_TYPEBIND@@VECXXZ
+ 0003:1108 ?GetTypeKind@GENPROJ_TYPEBIND@@VEC?EW4tagTYPEKIND@@XZ
+ 0003:110E ?IsProtocol@GENPROJ_TYPEBIND@@VECHXZ
+ 0003:1114 ?GetCbSize@GENPROJ_TYPEBIND@@VECGXZ
+ 0003:111A ?GetAlignment@GENPROJ_TYPEBIND@@VECGXZ
+ 0003:1120 ?Read@GENPROJ_TYPEBIND@@RECPEXPEVSTREAM@@@Z
+ 0003:118E ?BindTypeDefnStr@GENPROJ_TYPEBIND@@VECPEXPEDIW4ACCESS@@PEVEXBIND@@@Z
+ 0003:1210 ?BindProjLevel@GENPROJ_TYPEBIND@@RECPEXHKIW4ACCESS@@0W4COMPSTATE@@PEVEXBIND@@@Z
+ 0003:170A ?BindModulesWithCaches@GENPROJ_TYPEBIND@@JECPEXHKIW4ACCESS@@0W4COMPSTATE@@PEVEXBIND@@@Z
+ 0003:1998 ?BindModulesWithNammgr@GENPROJ_TYPEBIND@@JECPEXHKIW4ACCESS@@0W4COMPSTATE@@PEVEXBIND@@@Z
+ 0003:1ADC ?BindItyp@GENPROJ_TYPEBIND@@JECPEXIHKIW4ACCESS@@0W4COMPSTATE@@PEVEXBIND@@@Z
+ 0003:1E0C ?BindTypeDefnProjLevelStr@GENPROJ_TYPEBIND@@VECPEXPEDIW4ACCESS@@1PEVEXBIND@@@Z
+ 0003:1EB6 ?BindDefnProjLevelStr@GENPROJ_TYPEBIND@@VECPEXPEDIW4ACCESS@@1PEVEXBIND@@@Z
+ 0003:1F62 ??0CDefnTypeComp@@REC@XZ
+ 0003:1FA2 ??1CDefnTypeComp@@VEC@XZ
+ 0003:1FD0 ?Create@CDefnTypeComp@@TAPEXPEPEV1@PEVDEFN_TYPEBIND@@@Z
+ 0003:2068 ?Init@CDefnTypeComp@@JECPEXPEVDEFN_TYPEBIND@@@Z
+ 0003:20A4 ?QueryInterface@CDefnTypeComp@@VEAPEXAFUGUID@@PEPEX@Z
+ 0003:212A ?AddRef@CDefnTypeComp@@VEAKXZ
+ 0003:2144 ?Release@CDefnTypeComp@@VEAKXZ
+ 0003:218A ?Bind@CDefnTypeComp@@VEAPEXPEDKGPEPEUITypeInfo@@PEW4tagDESCKIND@@PETtagBINDPTR@@@Z
+ 0003:2578 ?BindType@CDefnTypeComp@@VEAPEXPEDKPEPEUITypeInfo@@PEPEUITypeComp@@@Z
+ 0004:0000 ??0BLK_MGR@@REC@XZ
+ 0004:0038 ?ConsChunkToFreeList@BLK_MGR@@BECXII@Z
+ 0004:0072 ?Init@BLK_MGR@@RECPEXPEVSHEAP_MGR@@HH@Z
+ 0004:00E2 ?Read@BLK_MGR@@RECPEXPEVSTREAM@@@Z
+ 0004:0158 ?GetSize@BLK_MGR@@RFCIXZ
+ 0004:0178 ?ReadSz@STREAM@@RECPEXPEPED@Z
+ 0004:0212 ?ReadByte@STREAM@@RECPEXPEE@Z
+ 0004:0236 ?AllocSeg@@ZAGK@Z
+ 0004:0282 ?ReallocSeg@@ZAPEXKG@Z
+ 0004:02D0 ?FreeSeg@@ZAPEXG@Z
+ 0004:02F2 ??2SHEAP_MGR@@LAPEXI@Z
+ 0004:02F6 ?Alloc@SHEAP_MGR@@JECPEXPEVBLK_DESC@@K@Z
+ 0004:03AC ?ShiftHeap@SHEAP_MGR@@BECXPEVBLK_DESC@@J@Z
+ 0004:046A ?Free@SHEAP_MGR@@JECXPEVBLK_DESC@@@Z
+ 0004:04AE ?Realloc@SHEAP_MGR@@JECPEXPEVBLK_DESC@@K@Z
+ 0004:05C6 ?ReallocHeap@SHEAP_MGR@@BECPEXK@Z
+ 0004:0634 ?Read@BLK_DESC@@RECPEXPEVSTREAM@@@Z
+ 0004:06A8 HSYSREALLOCHSYS
+ 0004:06F8 ?g_prgHashTbl@@3QEY01PEEE
+ 0004:0770 LHASHVALOFNAMESYS
+ 0004:0908 _IID_ICreateTypeInfo
+ 0004:0918 _IID_ITypeComp
+ 0004:0928 _IID_ITypeLib
+ 0004:0938 _IID_ITypeInfo
+ 0004:0948 _CLSID_PSRemoteTypeInfo
+ 0004:0958 _CLSID_PSDispatch
+ 0004:0968 _IID_ICreateTypeLib
+ 0004:0978 _IID_CDefnTypeComp
+ 0004:0988 _IID_DYNTYPEINFO
+ 0004:0998 _IID_TYPEINFO
+ 0004:09A8 _CLSID_GenericTypeLibOLE
+ 0004:09B8 _IID_IGenericTypeLibOLE
+ 0004:09C8 _CLSID_TypeLibCF
+ 0004:09D8 _IID_TYPELIB_GEN_DTINFO
+ 0004:09E8 ?GetLcid@STL_TYPEINFO@@JECPEXPEK@Z
+ 0004:0A1C ?QueryInterface@STL_TYPEINFO@@VEAPEXAFUGUID@@PEPEX@Z
+ 0004:0ADC ?PrepareForDestruction@STL_TYPEINFO@@VECXXZ
+ 0004:0AE0 ?Invoke@STL_TYPEINFO@@VEAPEXPEXJGPEUtagDISPPARAMS@@PEUtagVARIANT@@PEUtagEXCEPINFO@@PEI@Z
+ 0004:0AF0 ?Read@NAMMGR@@RECPEXPEVSTREAM@@@Z
+ 0004:0B5E ?GetHgnamOfStrLhash@NAMMGR@@RECPEXPEDKPEK@Z
+ 0004:0C64 ?IsName@NAMMGR@@RECPEXPEDKPEH@Z
+ 0004:0D26 ?LpstrOfHgnam@NAMMGR@@RFCPEDK@Z
+ 0004:0D50 ?Deleting@GenericTypeLibOLE@@JECXG@Z
+ 0004:0D78 ?IsName@GenericTypeLibOLE@@VEAPEXPEDKPEH@Z
+ 0004:0E54 ?FindName@GenericTypeLibOLE@@VEAPEXPEDKPEPEUITypeInfo@@PEJPEG@Z
+ 0004:0FA0 ?GetTypeComp@GenericTypeLibOLE@@VEAPEXPEPEUITypeComp@@@Z
+ 0004:1026 ?GetTypeInfoOfGuid@GenericTypeLibOLE@@VEAPEXAFUGUID@@PEPEUITypeInfo@@@Z
+ 0004:10E6 ?FindMembers@GenericTypeLibOLE@@RECPEXPEDKPEPEUITypeInfo@@PEJPEG@Z
+ 0004:1680 ?TypeInfoFromCompressedTypeId@GenericTypeLibOLE@@RECPEXPEDPEPEUITypeInfo@@@Z
+ 0004:17E2 ?AddNameToCache@GenericTypeLibOLE@@RECPEXIK@Z
+ 0004:184E ?GetDstrMgr@GenericTypeLibOLE@@RECPEXPEPEVDOCSTR_MGR@@@Z
+ 0004:1924 ?SetPtinfo@IMPMGR@@BECPEXIPEUITypeInfo@@H@Z
+ 0004:1A5A ?HimptypeAlloc@IMPMGR@@BECPEXPEG@Z
+ 0004:1BF8 ?NewEntry@IMPMGR@@BECPEXPEPEVUB_IMPTYPE@@PEG@Z
+ 0004:1C8C ?GetHimptype@IMPMGR@@RECPEXPEUITypeInfo@@W4DEPEND_KIND@@PEG@Z
+ 0004:1DB4 ?GetTypeInfo@IMPMGR@@RECPEXIW4DEPEND_KIND@@PEPEUITypeInfo@@@Z
+ 0004:1E24 ?Unref@IMPMGR@@RECXI@Z
+ 0004:1E54 ?HimptypeNext@IMPMGR@@RFCII@Z
+ 0004:1E74 ?RegisterDeclRefDep@IMPMGR@@RECPEXPEUITypeInfo@@@Z
+ 0004:1F16 ?Read@IMPMGR@@RECPEXPEVSTREAM@@@Z
+ 0005:0000 ?GetErrorInfo@@ZAPEXPEUtagEXCEPINFO@@@Z
+ 0005:00B2 ?TiperrOfOFErr@@ZAPEXI@Z
+ 0005:01BA ?SzLibIdLocalTypeIdOfTypeId@@ZAPEXPEDPEPED1@Z
+ 0005:0260 ?IsSimpleType@@ZAHW4TYPEDESCKIND@@@Z
+ 0005:02BC ?CompareHimptypes@@ZAPEXQEVTYPE_DATA@@I0IPEH@Z
+ 0005:0376 ?GetLibIdKind@@ZA?EW4LIBIDKIND@@PED@Z
+ 0005:03BC LOADREGTYPELIBOFSZGUID
+ 0005:04E2 LOADREGTYPELIB
+ 0005:06AC ?InitTypeDesc@@ZAXPEUtagTYPEDESC@@@Z
+ 0005:06BA ?InitIdlDesc@@ZAXPEUtagIDLDESC@@@Z
+ 0005:06CC ?InitElemDesc@@ZAXPEUtagELEMDESC@@@Z
+ 0005:06F4 ?InitVarDesc@@ZAXPEUtagVARDESC@@@Z
+ 0005:0714 ?InitFuncDesc@@ZAXPEUtagFUNCDESC@@@Z
+ 0005:0748 ?ClearTypeDesc@@ZAXPEUtagTYPEDESC@@@Z
+ 0005:0786 ?ClearIdlDesc@@ZAXPEUtagIDLDESC@@@Z
+ 0005:079A ?ClearArrayDesc@@ZAXPEUtagARRAYDESC@@@Z
+ 0005:07AA ?ClearElemDesc@@ZAXPEUtagELEMDESC@@@Z
+ 0005:07D2 ?FreeVarDesc@@ZAXPEUtagVARDESC@@@Z
+ 0005:082C ?FreeFuncDesc@@ZAXPEUtagFUNCDESC@@@Z
+ 0005:08AE ?FreeTypeDesc@@ZAXPEUtagTYPEDESC@@@Z
+ 0005:08DA ?FreeArrayDesc@@ZAXPEUtagARRAYDESC@@@Z
+ 0005:0906 ?CopyArrayDesc@@ZAPEXPEPEUtagARRAYDESC@@PEU1@@Z
+ 0005:0966 ?CopyTypeDesc@@ZAPEXPEUtagTYPEDESC@@0@Z
+ 0005:0A5A ?GetLibIdOfRegLib@@ZAPEXPEDGGK00PEPED@Z
+ 0005:0C5A ?GetLibIdOfTypeLib@@ZAPEXPEUITypeLib@@PEPED@Z
+ 0005:0D20 ?GetTypeInfoOfTypeId@@ZAPEXPEDPEPEUITypeInfo@@@Z
+ 0005:0F86 ?MakeAbsolutePath@@ZAPEXPED0PEPED@Z
+ 0005:122E ?ConvertPathToUNC@@ZAPEXPEDPEPED@Z
+ 0005:13E6 ?IsolateFilename@@ZAPEDPED@Z
+ 0005:1416 OWNETGETCONNECTION
+ 0005:1480 CBSIZEARRAYDESC
+ 0005:149C ?rtArrayInit@@ZCXPEUtagSAFEARRAY@@I@Z
+ 0005:14F2 ?ReleaseDllentrydefn@TYPE_DATA@@RECXI@Z
+ 0005:151E ?FreeArrayDescriptor@TYPE_DATA@@RECXI@Z
+ 0005:1554 ?FreeTypeDefnResources@TYPE_DATA@@RECXI@Z
+ 0005:1612 ?FreeMbrVarDefn@TYPE_DATA@@RECXI@Z
+ 0005:16FC ?SizeofConstVal@TYPE_DATA@@RECIPEVVAR_DEFN@@I@Z
+ 0005:179A ?FreeFuncDefn@TYPE_DATA@@RECXI@Z
+ 0005:19AC ?FreeParamDefn@TYPE_DATA@@RECXI@Z
+ 0005:19E8 ?Read@TYPE_DATA@@RECPEXPEVSTREAM@@@Z
+ 0005:1C1E ?AllocMbrVarDefn@TYPE_DATA@@BECPEXPEGI@Z
+ 0005:1CCA ?AllocFuncDefn@TYPE_DATA@@BECPEXPEGI@Z
+ 0005:1D50 ?AllocVirtualFuncDefn@TYPE_DATA@@BECPEXPEGI@Z
+ 0005:1DE6 ?HdefnOfHmember@TYPE_DATA@@RECIKPEI@Z
+ 0005:1E3A ?HfdefnOfHmember@TYPE_DATA@@RFCIKI@Z
+ 0005:1ED0 ?HvdefnPredeclared@TYPE_DATA@@RFCIXZ
+ 0005:1EDE ?HmvdefnOfHmember@TYPE_DATA@@RFCIK@Z
+ 0005:1F5C ?SizeOfTypeDefn@TYPE_DATA@@RFCII@Z
+ 0005:1F84 ?DefnSize@TYPE_DEFN@@RECIXZ
+ 0005:1FFC ?AllocVardefnPredeclared@TYPE_DATA@@RECPEXXZ
+ 0005:228C ?PbConstVal@@ZAPEEPEVTYPE_DATA@@PEVVAR_DEFN@@@Z
+ 0005:22F4 ?HvdefnOfHlnam@TYPE_DATA@@RECII@Z
+ 0005:2344 ?HfdefnFirstOfHlnam@TYPE_DATA@@RECIIPEW4tagINVOKEKIND@@@Z
+ 0005:2370 ?HfdefnNextOfHlnam@TYPE_DATA@@RECIIIPEW4tagINVOKEKIND@@@Z
+ 0005:2404 ?HfdefnFirstAvailMeth@TYPE_DATA@@RECIXZ
+ 0005:2412 ?GetFuncDescOfHfdefn@TYPE_DATA@@RECPEXIPEPEUtagFUNCDESC@@@Z
+ 0005:285A ?GetFuncDesc@TYPE_DATA@@RECPEXIPEPEUtagFUNCDESC@@@Z
+ 0005:2902 ?GetVarDescOfHvdefn@TYPE_DATA@@RECPEXIPEPEUtagVARDESC@@@Z
+ 0005:2DE8 ?GetVarDesc@TYPE_DATA@@RECPEXIPEPEUtagVARDESC@@@Z
+ 0005:2EB0 ?AllocTypeDescOfTypeDefn@TYPE_DATA@@RECPEXIHPEUtagTYPEDESC@@@Z
+ 0005:32B2 ?HmvdefnOfIndex@TYPE_DATA@@BECII@Z
+ 0005:32F8 ?GetImplTypeFlags@TYPE_DATA@@RECPEXIPEH@Z
+ 0005:336E ?GetRefTypeOfImplType@TYPE_DATA@@RECPEXIPEK@Z
+ 0005:345E ?GetNames@TYPE_DATA@@RECPEXJPEPEDIPEI@Z
+ 0005:3746 ?GetDocumentation@TYPE_DATA@@RECPEXJPEPED0PEK0@Z
+ 0005:3970 ?UHelpContextOfEncoding@TYPE_DATA@@RECKG@Z
+ 0005:39F4 ?GetEncodedHelpContext@TYPE_DATA@@RECPEXKPEG@Z
+ 0005:3AEE ?StringOfHchunk@TYPE_DATA@@RECPEXIPEPED@Z
+ 0005:3B9E ?GetDynTypeBindOfHvdefn@TYPE_DATA@@RECPEXIPEPEVDYN_TYPEBIND@@PEI@Z
+ 0005:3C6E ?GetTypeInfoOfHvdefn@TYPE_DATA@@RECPEXIPEPEUITypeInfo@@PEI@Z
+ 0005:3DF8 ?HfdefnOfIndex@TYPE_DATA@@RECPEXIPEI@Z
+ 0005:3E62 ?HtdefnAlias@TYPE_DATA@@RFCIXZ
+ 0005:3E70 ?SetIsSimpleTypeAlias@TYPE_DATA@@RECXH@Z
+ 0005:3E8C ?IsSimpleTypeAlias@TYPE_DATA@@RFCHXZ
+ 0005:3E9E ?AddRef@DYN_TYPEMEMBERS@@VECXXZ
+ 0005:3EB8 ?Release@DYN_TYPEMEMBERS@@VECXXZ
+ 0005:3ED2 ?AddInternalRef@DYN_TYPEMEMBERS@@RECXXZ
+ 0005:3F1C ?RelInternalRef@DYN_TYPEMEMBERS@@RECXXZ
+ 0005:3F38 ?GetDefnTypeBind@DYN_TYPEMEMBERS@@RECPEXPEPEVDEFN_TYPEBIND@@@Z
+ 0005:3F66 ?IsLaidOut@DYN_TYPEMEMBERS@@VECHXZ
+ 0005:3F78 ?GetSizeAlignmentOfHtdefnUdt@DYN_TYPEMEMBERS@@RECPEXIPEI0@Z
+ 0005:4072 ?GetSizeAlignmentOfArray@DYN_TYPEMEMBERS@@RECPEXW4tagTYPEKIND@@IPEI1@Z
+ 0005:4274 ?GetSizeAlignmentOfHtdefn@DYN_TYPEMEMBERS@@RECPEXW4tagTYPEKIND@@HIPEI1@Z
+ 0005:4418 ?GetSizeAlignmentOfHtdefnNonUdt@DYN_TYPEMEMBERS@@RECPEXW4tagTYPEKIND@@HIPEI1@Z
+ 0005:44E8 ?Read@DYN_TYPEMEMBERS@@RECPEXPEVSTREAM@@@Z
+ 0005:4566 ?BuildBindNameTable@DYN_TYPEMEMBERS@@RECPEXXZ
+ 0005:462C ?UpdateBinderOptimization@DYN_TYPEMEMBERS@@JECPEXIIH@Z
+ 0005:47E4 ?UpdateNameCacheOfHdefnList@DYN_TYPEMEMBERS@@JECPEXIW4INFOKIND@@I@Z
+ 0005:48C2 ?UpdateNameCacheOfBaseClass@DYN_TYPEMEMBERS@@JECPEXPEUITypeInfo@@I@Z
+ 0005:4C80 ?BuildNameCache@DYN_TYPEMEMBERS@@RECPEXI@Z
+ 0005:4FE4 ?GetSize@DYN_TYPEMEMBERS@@VECIXZ
+ 0005:4FFE ?QueryProtocol@DYN_TYPEBIND@@VECPEXPED@Z
+ 0005:5044 ?AddRef@DYN_TYPEBIND@@VECXXZ
+ 0005:506C ?AddInternalRef@DYN_TYPEBIND@@RECXXZ
+ 0005:5086 ?RelInternalRef@DYN_TYPEBIND@@RECXXZ
+ 0005:50A0 ?Release@DYN_TYPEBIND@@VECXXZ
+ 0005:50B8 ?GetTypeInfo@DYN_TYPEBIND@@VECPEXPEPEVTYPEINFO@@@Z
+ 0005:50FA ?BuildBindNameTable@DYN_TYPEBIND@@RECPEXXZ
+ 0005:5112 ?BindBase@DYN_TYPEBIND@@JECPEXHIIKIW4ACCESS@@PEVEXBIND@@PEVGenericTypeLibOLE@@@Z
+ 0005:527E ?BindIdDefn@DYN_TYPEBIND@@RECPEXHKIW4ACCESS@@PEVEXBIND@@@Z
+ 0005:55AC ?BindDefnCur@DYN_TYPEBIND@@RECPEXHKIW4ACCESS@@PEVEXBIND@@@Z
+ 0005:592C ?HvdefnPredeclared@DYN_TYPEBIND@@RECIXZ
+ 0005:5948 ?Ptdata@DYN_TYPEBIND@@RECPEVTYPE_DATA@@XZ
+ 0005:595E ?BindDefnStr@DYN_TYPEBIND@@VECPEXPEDIW4ACCESS@@PEVEXBIND@@@Z
+ 0005:59FE ?BindTypeDefnStr@DYN_TYPEBIND@@VECPEXPEDIW4ACCESS@@PEVEXBIND@@@Z
+ 0005:5A9C ?GetTypeKind@DYN_TYPEBIND@@VEC?EW4tagTYPEKIND@@XZ
+ 0005:5AC4 ?GetCbSize@DYN_TYPEBIND@@VECGXZ
+ 0005:5AD2 ?GetAlignment@DYN_TYPEBIND@@VECGXZ
+ 0005:5AE0 ?Read@DYN_TYPEBIND@@RECPEXPEVSTREAM@@@Z
+ 0005:5C2E ?BindDefnProjLevelStr@DYN_TYPEBIND@@VECPEXPEDIW4ACCESS@@1PEVEXBIND@@@Z
+ 0005:5C34 ?BindTypeDefnProjLevelStr@DYN_TYPEBIND@@VECPEXPEDIW4ACCESS@@1PEVEXBIND@@@Z
+ 0005:5C3A ?GetBucketOfHlnam@DYN_BINDNAME_TABLE@@JFCII@Z
+ 0005:5C78 ?BuildTable@DYN_BINDNAME_TABLE@@RECPEXXZ
+ 0005:5D34 ?AddHdefn@DYN_BINDNAME_TABLE@@RECXI@Z
+ 0005:5DB6 ?Read@DYN_BINDNAME_TABLE@@RECPEXPEVSTREAM@@@Z
+ 0005:5E1C ?FindIndexOfHlnam@DYN_BINDNAME_TABLE@@JFCIII@Z
+ 0005:5EAC ?TraverseDefnList@DYN_BINDNAME_TABLE@@JECPEXI@Z
+ 0005:616E ?SetTableSize@DYN_BINDNAME_TABLE@@JECPEXI@Z
+ 0005:6236 ?QueryInterface@GTLibStorage@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:62A0 ?SetClass@GTLibStorage@@VEAPEXAFUGUID@@@Z
+ 0005:62CA ?QueryInterface@GTLibStream@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:6334 ?Seek@GTLibStream@@VEAPEXU_LARGE_INTEGER@@KPEU_ULARGE_INTEGER@@@Z
+ 0005:640C ?QueryInterface@FileLockBytes@@VEAPEXAFUGUID@@PEPEX@Z
+ 0005:6480 ??2@ZAPEXI@Z
+ 0005:6484 ??3@ZAXPEX@Z
+ 0005:6486 ?GetTypeAttr@STL_TYPEINFO@@VEAPEXPEPEUtagTYPEATTR@@@Z
+ 0005:6496 ?GetTypeComp@STL_TYPEINFO@@VEAPEXPEPEUITypeComp@@@Z
+ 0005:64A6 ?GetFuncDesc@STL_TYPEINFO@@VEAPEXIPEPEUtagFUNCDESC@@@Z
+ 0005:64B6 ?GetVarDesc@STL_TYPEINFO@@VEAPEXIPEPEUtagVARDESC@@@Z
+ 0005:64C6 ?GetNames@STL_TYPEINFO@@VEAPEXJPEPEDIPEI@Z
+ 0005:64D6 ?GetRefTypeOfImplType@STL_TYPEINFO@@VEAPEXIPEK@Z
+ 0005:64E6 ?GetImplTypeFlags@STL_TYPEINFO@@VEAPEXIPEH@Z
+ 0005:64F6 ?GetIDsOfNames@STL_TYPEINFO@@VEAPEXPEPEDIPEJ@Z
+ 0005:6506 ?GetDocumentation@STL_TYPEINFO@@VEAPEXJPEPED0PEK0@Z
+ 0005:6516 ?GetDllEntry@STL_TYPEINFO@@VEAPEXJW4tagINVOKEKIND@@PEPED1PEG@Z
+ 0005:6526 ?GetRefTypeInfo@STL_TYPEINFO@@VEAPEXKPEPEUITypeInfo@@@Z
+ 0005:6536 ?AddressOfMember@STL_TYPEINFO@@VEAPEXJW4tagINVOKEKIND@@PEPEX@Z
+ 0005:6546 ?CreateInstance@STL_TYPEINFO@@VEAPEXPEUIUnknown@@AFUGUID@@PEPEX@Z
+ 0005:6556 ?GetMops@STL_TYPEINFO@@VEAPEXJPEPED@Z
+ 0005:6566 ?ReleaseTypeAttr@STL_TYPEINFO@@VEAXPEUtagTYPEATTR@@@Z
+ 0005:6572 ?ReleaseFuncDesc@STL_TYPEINFO@@VEAXPEUtagFUNCDESC@@@Z
+ 0005:657E ?ReleaseVarDesc@STL_TYPEINFO@@VEAXPEUtagVARDESC@@@Z
+ 0005:658A ?SetGuid@STL_TYPEINFO@@VEAPEXAFUGUID@@@Z
+ 0005:659A ?SetTypeFlags@STL_TYPEINFO@@VEAPEXI@Z
+ 0005:65AA ?SetDocString@STL_TYPEINFO@@VEAPEXPED@Z
+ 0005:65BA ?SetHelpContext@STL_TYPEINFO@@VEAPEXK@Z
+ 0005:65CA ?SetVersion@STL_TYPEINFO@@VEAPEXGG@Z
+ 0005:65DA ?AddRefTypeInfo@STL_TYPEINFO@@VEAPEXPEUITypeInfo@@PEK@Z
+ 0005:65EA ?AddFuncDesc@STL_TYPEINFO@@VEAPEXIPEUtagFUNCDESC@@@Z
+ 0005:65FA ?AddImplType@STL_TYPEINFO@@VEAPEXIK@Z
+ 0005:660A ?SetImplTypeFlags@STL_TYPEINFO@@VEAPEXIH@Z
+ 0005:661A ?SetAlignment@STL_TYPEINFO@@VEAPEXG@Z
+ 0005:662A ?SetSchema@STL_TYPEINFO@@VEAPEXPED@Z
+ 0005:663A ?AddVarDesc@STL_TYPEINFO@@VEAPEXIPEUtagVARDESC@@@Z
+ 0005:664A ?SetFuncAndParamNames@STL_TYPEINFO@@VEAPEXIPEPEDI@Z
+ 0005:665A ?SetVarName@STL_TYPEINFO@@VEAPEXIPED@Z
+ 0005:666A ?SetTypeDescAlias@STL_TYPEINFO@@VEAPEXPEUtagTYPEDESC@@@Z
+ 0005:667A ?DefineFuncAsDllEntry@STL_TYPEINFO@@VEAPEXIPED0@Z
+ 0005:668A ?SetFuncDocString@STL_TYPEINFO@@VEAPEXIPED@Z
+ 0005:669A ?SetVarDocString@STL_TYPEINFO@@VEAPEXIPED@Z
+ 0005:66AA ?SetFuncHelpContext@STL_TYPEINFO@@VEAPEXIK@Z
+ 0005:66BA ?SetVarHelpContext@STL_TYPEINFO@@VEAPEXIK@Z
+ 0005:66CA ?SetMops@STL_TYPEINFO@@VEAPEXIPED@Z
+ 0005:66DA ?SetTypeIdldesc@STL_TYPEINFO@@VEAPEXPEUtagIDLDESC@@@Z
+ 0005:66EA ?LayOut@STL_TYPEINFO@@VEAPEXXZ
+ 0005:66FA ?QueryInterface@STL_TYPEINFO@@X3EAPEXAFUGUID@@PEPEX@Z
+ 0005:6706 ?AddRef@STL_TYPEINFO@@X3EAKXZ
+ 0005:6712 ?Release@STL_TYPEINFO@@X3EAKXZ
+ 0005:671E ?IterationNotInProgress@GEN_DTINFO@@VECHXZ
+ 0005:673C ?Read@GEN_DTINFO@@VECPEXXZ
+ 0005:675E ?Write@GEN_DTINFO@@VECPEXXZ
+ 0005:6780 ?WriteToStream@GEN_DTINFO@@VECPEXPEVSTREAM@@@Z
+ 0005:67A8 ?EndDepIteration@GEN_DTINFO@@VECXXZ
+ 0005:67C6 ?IsReady@GEN_DTINFO@@VECHXZ
+ 0005:67E4 ??_GSTL_TYPEINFO@@VECPEXI@Z
+ 0005:67FE ??_GGEN_DTINFO@@VECPEXI@Z
+ 0005:6818 ??_7GEN_DTINFO@@6FDYNTYPEINFO@@@
+ 0005:68C0 ??_7GEN_DTINFO@@6FICreateTypeInfo@@@
+ 0005:6928 ??_7ITypeInfo@@6F@
+ 0005:6980 ??_7IUnknown@@6F@
+ 0005:698C ??_7STL_TYPEINFO@@6FDYNTYPEINFO@@@
+ 0005:6A2C ??_7STL_TYPEINFO@@6FICreateTypeInfo@@@
+ 0005:6A94 ??_7TYPEINFO@@6F@
+ 0005:6AF8 ??_7DYNTYPEINFO@@6F@
+ 0005:6B7C ??_7ICreateTypeInfo@@6F@
+ 0005:6BE4 ??_7DYN_TYPEROOT@@6F@
+ 0005:6C04 ?GetBit@NAME_CACHE@@BFCHI@Z
+ 0005:6C2E ??_GGenericTypeLibOLE@@VECPEXI@Z
+ 0005:6C82 ??_7GenericTypeLibOLE@@6FITypeLib@@@
+ 0005:6CC2 ??_7GenericTypeLibOLE@@6FICreateTypeLib@@@
+ 0005:6CF6 ??_7ITypeLib@@6F@
+ 0005:6D2A ??_7ICreateTypeLib@@6F@
+ 0005:6D5E ??_7DOCFILE_STREAM@@6F@
+ 0005:6D76 ??_7STREAM@@6F@
+ 0005:6D8E ??0VAR_DEFN@@REC@XZ
+ 0005:6DCA ??0FUNC_DEFN@@REC@XZ
+ 0005:6E42 ?QdefnOfHdefn@TYPE_DATA@@RFCPEVDEFN@@II@Z
+ 0005:6E64 ?IsSub@FUNC_DEFN@@RFCHXZ
+ 0005:6EA4 ??1PROPERTY_NODE@@REC@XZ
+ 0005:6F02 ?PnodeOfHlnam@PROPERTY_NODE@@RECPEU1@I@Z
+ 0005:6F74 ??_7DYN_TYPEMEMBERS@@6F@
+ 0005:6F8C ?GetCbSizeVft@DYN_TYPEBIND@@VECGXZ
+ 0005:6F9A ?GetOPvft@DYN_TYPEBIND@@VECJXZ
+ 0005:6FAC ??_GDYN_TYPEBIND@@VECPEXI@Z
+ 0005:6FC6 ??_7DYN_TYPEBIND@@6F@
+ 0005:7002 ??_7DEFN_TYPEBIND@@6F@
+ 0005:703E ??_GDYN_BINDNAME_TABLE@@VECPEXI@Z
+ 0005:7058 ??_7DYN_BINDNAME_TABLE@@6F@
+ 0005:705C ?GetTypeInfo@GENPROJ_TYPEBIND@@VECPEXPEPEVTYPEINFO@@@Z
+ 0005:7070 ??_GGENPROJ_TYPEBIND@@VECPEXI@Z
+ 0005:708A ??_7GENPROJ_TYPEBIND@@6F@
+ 0005:70CA ??_GCDefnTypeComp@@VECPEXI@Z
+ 0005:70E4 ??_7ITypeComp@@6F@
+ 0005:70F8 ??_7CDefnTypeComp@@6F@
+ 0005:7110 ??_7IStream@@6F@
+ 0005:7148 ??_7GTLibStream@@6F@
+ 0005:7180 ??_7FileLockBytes@@6F@
+ 0005:71A8 ??_7GTLibStorage@@6F@
+ 0005:71F0 ??_7ILockBytes@@6F@
+ 0005:7218 ??_7IStorage@@6F@
+ 0006:0000 TLSFREE
+ 0006:001C HSYSALLOC
+ 0006:005C FREEHSYS
+ 0006:009E ?GetInsensitiveCompTbl@@ZAXKW4tagSYSKIND@@PED@Z
+ 0006:02A4 ?g_rgbExcepTblWin1045@@3QEY01EE
+ 0006:02D8 ?g_rgbPartialBaseTbl10029@@3QEEE
+ 0006:0358 ?g_rgbExcepTblMac1038@@3QEY01EE
+ 0006:037E ?g_rgbPartialBaseTbl10000@@3QEEE
+ 0006:03FE ?g_rgbExcepTblWin1038@@3QEY01EE
+ 0006:0424 ?g_rgbPartialBaseTbl1250@@3QEEE
+ 0006:04A4 ?g_rgbExcepTblMac1035@@3QEY01EE
+ 0006:04BE ?g_prgbPartialBaseTbl@@3QEY01PEEE
+ 0006:0516 ?g_rgbPartialBaseTbl1252@@3QEEE
+ 0006:0596 ?g_rgbExcepTblWin1035@@3QEY01EE
+ 0006:05B4 ?g_rgbPartialBaseTblMEngIreland@@3QEEE
+ 0006:0634 ?g_rgbExcepTblMac1034@@3QEY01EE
+ 0006:063A ?g_rgbExcepTblWin1034@@3QEY01EE
+ 0006:0640 ?g_rgbPartialBaseTblMNorwegian@@3QEEE
+ 0006:06C0 ?g_rgLcidToExcepTbl@@3QEY01ULcidToExcep@@E
+ 0006:07D0 ?g_rgbExcepTblMac1030@@3QEY01EE
+ 0006:07EA ?g_rgbPartialBaseTblWEngIreland@@3QEEE
+ 0006:086A ?g_rgbExcepTblWin1030@@3QEY01EE
+ 0006:0888 ?g_rgbExcepTblNew@@3QEY01EE
+ 0006:088C ?g_rgbPartialBaseTblWNorwegian@@3QEEE
+ 0006:090C ?g_rgbExcepTblMac1051@@3QEY01EE
+ 0006:0914 ?g_rgbExcepTblWin1051@@3QEY01EE
+ 0006:091E ?g_rgbPartialBaseTblWTurkish@@3QEEE
+ 0006:099E ?g_rgbExcepTblMac1045@@3QEY01EE
+ 0006:09D2 ?g_rgbPartialBaseTbl10007@@3QEEE
+ 0006:0A52 ??0GEN_DTINFO@@JEC@XZ
+ 0006:0B22 ??1GEN_DTINFO@@NEC@XZ
+ 0006:0B82 ?RemoveInternalRefs@GEN_DTINFO@@VECXXZ
+ 0006:0BAE ?QueryInterface@GEN_DTINFO@@VEAPEXAFUGUID@@PEPEX@Z
+ 0006:0C26 ?GetDocumentation@GEN_DTINFO@@VEAPEXJPEPED0PEK0@Z
+ 0006:0E54 ??0DYN_TYPEROOT@@JEC@XZ
+ 0006:0EDE ??3DYN_TYPEROOT@@TAXPEX@Z
+ 0006:0F10 ?Init@DYN_TYPEROOT@@RECPEXPEVGEN_DTINFO@@IIHW4ACCESS@@W4tagTYPEKIND@@W4tagSYSKIND@@@Z
+ 0006:1046 ??1DYN_TYPEROOT@@JEC@XZ
+ 0006:1162 ?GetNamMgr@DYN_TYPEROOT@@RECPEXPEPEVNAMMGR@@@Z
+ 0006:1184 ?GetImpMgr@DYN_TYPEROOT@@RECPEXPEPEVIMPMGR@@@Z
+ 0006:131E ?GetEntMgr@DYN_TYPEROOT@@RECPEXPEPEVENTRYMGR@@@Z
+ 0006:14AA ?GetDtmbrs@DYN_TYPEROOT@@VECPEXPEPEVDYN_TYPEMEMBERS@@@Z
+ 0006:1658 ?EnsurePartsRead@GEN_DTINFO@@VECPEXXZ
+ 0006:167A ?EnsurePartsRead@DYN_TYPEROOT@@NECPEXXZ
+ 0006:172C ?InitializeIteration@GEN_DTINFO@@VECPEXXZ
+ 0006:174A ?PrepareForDestruction@GEN_DTINFO@@VECXXZ
+ 0006:174E ?RelInternalRef@STL_TYPEINFO@@RECXXZ
+ 0006:1826 ?QueryInterface@DYNTYPEINFO@@VEAPEXAFUGUID@@PEPEX@Z
+ 0006:18BE ?AddRef@STL_TYPEINFO@@VEAKXZ
+ 0006:1922 ?Release@STL_TYPEINFO@@VEAKXZ
+ 0006:1A1C ?SetModified@STL_TYPEINFO@@RECPEXH@Z
+ 0006:1A9C ?SetContainingTypeLib@STL_TYPEINFO@@JECXPEVGenericTypeLibOLE@@@Z
+ 0006:1B50 ??1STL_TYPEINFO@@NEC@XZ
+ 0006:1B74 ?GetContainingTypeLib@STL_TYPEINFO@@VEAPEXPEPEUITypeLib@@PEI@Z
+ 0006:1BEC ?GetBucketOfHash@NAMMGR@@BFCII@Z
+ 0006:1C16 ?ForEachDescendant@NAMMGR@@BECXIP91@CXI@ZH@Z
+ 0006:1CEA ?AddEntry@NAMMGR@@BECXI@Z
+ 0006:1DDE ?FindHash@NAMMGR@@BFCIII@Z
+ 0006:1E66 ?FindTextNam@NAMMGR@@BECIPFDIHPEHH@Z
+ 0006:1FC0 ?HlnamOfStrIfExist@NAMMGR@@RECIPFD@Z
+ 0006:2026 ?HlnamOfStr@NAMMGR@@RECPEXPFDPEIHPEHHH@Z
+ 0006:21AE ?StrOfHlnam@NAMMGR@@RFCPEXIPEDI@Z
+ 0006:2226 ?BstrOfHlnam@NAMMGR@@RFCPEXIPEPED@Z
+ 0006:227C ?HgnamOfHlnam@NAMMGR@@RECPEXIPEK@Z
+ 0006:22A2 ?HgnamOfStr@NAMMGR@@RECPEXPEDPEK@Z
+ 0006:22FE ?StriEq@NAMMGR@@RECHPFD0@Z
+ 0006:2404 ?GenerateSortKey@NAMMGR@@RECPEXXZ
+ 0006:247C ?HashOfHlnam@NAMMGR@@RECKI@Z
+ 0006:2510 ?QueryInterface@GenericTypeLibOLE@@VEAPEXAFUGUID@@PEPEX@Z
+ 0006:2616 ?AddRef@GenericTypeLibOLE@@VEAKXZ
+ 0006:2648 ?GetTypeInfoCount@GenericTypeLibOLE@@VEAIXZ
+ 0006:265C ?GetTypeInfo@GenericTypeLibOLE@@VEAPEXIPEPEUITypeInfo@@@Z
+ 0006:2822 ?GetGdtiOfItyp@GenericTypeLibOLE@@RECPEXIPEPEVGEN_DTINFO@@@Z
+ 0006:286C ?CreateInstance@GenericTypeLibOLE@@JECPEXPEPEX@Z
+ 0006:2886 ?IhteHash@GenericTypeLibOLE@@JECIPED@Z
+ 0006:289E ?GetTypeBind@GenericTypeLibOLE@@RECPEXXZ
+ 0006:29BC ?GetBinddescOfSzName@GenericTypeLibOLE@@RECPEXPEDPEUGENPROJ_BIND_DESC@@@Z
+ 0006:2A9E ?GetIndexOfName@GenericTypeLibOLE@@RECPEXPEDPEG@Z
+ 0006:2AFA ?ReadNameCacheArray@GenericTypeLibOLE@@JECPEXXZ
+ 0006:2C50 ?LoadNameCache@GenericTypeLibOLE@@RECPEXXZ
+ 0006:2D8A ?InvalidateNameCache@GenericTypeLibOLE@@RECXI@Z
+ 0006:2DCA ?QszOfHsz@GenericTypeLibOLE@@JECPEDI@Z
+ 0006:2DFA ?MakeLocalTypeId@GenericTypeLibOLE@@JECPEXPEI@Z
+ 0006:2E70 ?QHteRef@GenericTypeLibOLE@@JECPEGG@Z
+ 0006:2F28 ?SetPos@DOCFILE_STREAM@@VECPEXJ@Z
+ 0006:2FBE ?Init@IMPMGR@@RECPEXPEVSHEAP_MGR@@PEVBLK_DESC@@1PEVDYN_TYPEROOT@@@Z
+ 0006:305C ?ReleasePtinfo@IMPMGR@@BECXI@Z
+ 0006:3124 ?GetHimptypeIfExists@IMPMGR@@RECIPEUITypeInfo@@@Z
+ 0006:31A0 ?HimptypeFirst@IMPMGR@@RFCIXZ
+ 0006:31B6 ?CheckRemainingDep@IMPMGR@@RECPEXPEW4DEPEND_KIND@@@Z
+ 0006:3454 ??1IMPMGR@@REC@XZ
+ 0006:34DA ?RemoveInternalRefs@IMPMGR@@RECXXZ
+ 0006:3568 ?IsUnqualifiable@@ZAHPEVGEN_DTINFO@@@Z
+ 0006:359E ?GetTimeStamp@@ZAXPED@Z
+ 0006:3668 ?HashSzTerm@@ZAIPEDD@Z
+ 0006:36A8 ?SplitGuidLibId@@ZAPEXPEDPEPED1PEG2PEK11@Z
+ 0006:37E0 ?GetRegLibOfLibId@@ZAPEXPEDPEPEUITypeLib@@@Z
+ 0006:3896 ?Init@TYPE_DATA@@RECPEXPEVSHEAP_MGR@@PEVDYN_TYPEROOT@@@Z
+ 0006:397C ??1TYPE_DATA@@REC@XZ
+ 0006:39A6 ?FreeTypeDefn@TYPE_DATA@@RECXI@Z
+ 0006:39E4 ?SetHvdefnPredeclared@TYPE_DATA@@RECXI@Z
+ 0006:39F6 ??1DYN_TYPEMEMBERS@@JEC@XZ
+ 0006:3A34 ??0DYN_TYPEMEMBERS@@REC@XZ
+ 0006:3B08 ?Init@DYN_TYPEMEMBERS@@RECPEXPEVSHEAP_MGR@@PEVDYN_TYPEROOT@@@Z
+ 0006:3C1C ?GetTypeKind@DYN_TYPEMEMBERS@@VEC?EW4tagTYPEKIND@@XZ
+ 0006:3C46 ??0ENTRYMGR@@REC@XZ
+ 0006:3C6C ??1ENTRYMGR@@REC@XZ
+ 0006:3C92 ?Init@ENTRYMGR@@RECPEXPEVSHEAP_MGR@@PEVDYN_TYPEROOT@@@Z
+ 0006:3CD6 ?Decompile@ENTRYMGR@@RECXW4COMPSTATE@@@Z
+ 0006:3CDA ?ReleaseDllEntries@@ZAXPEX@Z
+ 0006:3D54 ?Init@DYN_TYPEBIND@@RECPEXPEVBLK_MGR@@PEVDYN_TYPEROOT@@@Z
+ 0006:3D80 ??0DYN_TYPEBIND@@REC@XZ
+ 0006:3E10 ??1DYN_TYPEBIND@@VEC@XZ
+ 0006:3E4C ?Pdtmbrs@DYN_TYPEBIND@@RFCPEVDYN_TYPEMEMBERS@@XZ
+ 0006:3E5E ??0DYN_BINDNAME_TABLE@@REC@XZ
+ 0006:3EA2 ??1DYN_BINDNAME_TABLE@@VEC@XZ
+ 0006:3EB8 ?Init@DYN_BINDNAME_TABLE@@RECPEXPEVBLK_MGR@@PEVDYN_TYPEROOT@@@Z
+ 0006:3F24 ?ReleaseTable@DYN_BINDNAME_TABLE@@RECXXZ
+ 0006:3F5E ?IndexOfHlnam@GENPROJ_BINDNAME_TABLE@@RFCII@Z
+ 0006:401E ?AddNameToTable@GENPROJ_BINDNAME_TABLE@@RECPEXIIHH@Z
+ 0006:413A ?AddQgpbinddesc@GENPROJ_BINDNAME_TABLE@@JECXPEUGENPROJ_BIND_DESC@@@Z
+ 0006:4248 ?AllocCaches@GENPROJ_BINDNAME_TABLE@@JECPEXII@Z
+ 0006:42F4 ?SetTableSize@GENPROJ_BINDNAME_TABLE@@JECPEXI@Z
+ 0006:4554 ?AddNameToTable@GENPROJ_TYPEBIND@@RECPEXPEDIH@Z
+ 0006:464A ?QueryInterface@GEN_DTINFO@@X3EAPEXAFUGUID@@PEPEX@Z
+ 0006:4656 ?QtrOfHandle@BLK_MGR@@RFCPEEI@Z
+ 0006:4674 ?QueryInterface@GenericTypeLibOLE@@X3EAPEXAFUGUID@@PEPEX@Z
+ 0006:4680 ?AddRef@GenericTypeLibOLE@@X3EAKXZ
+ 0006:468C __mbslen
+ 0006:46E0 __mbsnbcpy
+ 0006:47A4 __mbsncmp
+ 0006:485C __mbsicmp
+ 0006:491E __mbscmp
+ 0006:49C6 _xstrdec
+ 0007:0000 ?CreateStandalone@BLK_MGR@@TAPEXPEPEV1@H@Z
+ 0007:00CA ?FreeStandalone@BLK_MGR@@TAXPEV1@@Z
+ 0007:010E ?AddChunkToFreeList@BLK_MGR@@BECXII@Z
+ 0007:029C ?HfreechunkOfCbSize@BLK_MGR@@BECII@Z
+ 0007:03C6 ?AllocChunk2@BLK_MGR@@BECPEXPEIII@Z
+ 0007:04D4 ?FreeChunk@BLK_MGR@@RECXII@Z
+ 0007:051A ?HszLen@BLK_MGR@@RFCII@Z
+ 0007:0566 ?Free@BLK_MGR@@RECXXZ
+ 0007:05BA ?ReadUShort@STREAM@@RECPEXPEG@Z
+ 0007:05DE ?ReadULong@STREAM@@RECPEXPEK@Z
+ 0007:0602 _MemAlloc
+ 0007:0684 _MemZalloc
+ 0007:06B8 _MemRealloc
+ 0007:074C ?Create@SHEAP_MGR@@TAPEXPEPEV1@I@Z
+ 0007:07FC ??3SHEAP_MGR@@TAXPEX@Z
+ 0007:080A ??0SHEAP_MGR@@REC@XZ
+ 0007:0842 ??1SHEAP_MGR@@REC@XZ
+ 0007:0846 ?Init@SHEAP_MGR@@JECPEXI@Z
+ 0007:0878 ?PtrOfBlkDescPrev@SHEAP_MGR@@JFCPEVBLK_DESC@@PEV2@@Z
+ 0007:08DE ?PtrOfBlkDescLast@SHEAP_MGR@@JFCPEVBLK_DESC@@XZ
+ 0007:094C ?RemoveBlkdesc@SHEAP_MGR@@JECXPEVBLK_DESC@@@Z
+ 0007:09A6 ?AddBlkdesc@SHEAP_MGR@@JECXPEVBLK_DESC@@K@Z
+ 0007:0A04 ??0BLK_DESC@@REC@XZ
+ 0007:0A2E ??1BLK_DESC@@REC@XZ
+ 0007:0A74 ?Init@BLK_DESC@@RECPEXPEVSHEAP_MGR@@I@Z
+ 0007:0AB8 ?Realloc@BLK_DESC@@RECPEXK@Z
+ 0007:0B36 TLSALLOC
+ 0007:0B6E TLSSETVALUE
+ 0007:0C56 TLSGETVALUE
+ 0007:0CD6 __mbschr
+ 0007:0D8C __mbsrchr
+ 0007:0E4C ??0NAMMGR@@REC@XZ
+ 0007:0E7C ??1NAMMGR@@REC@XZ
+ 0007:0EA6 ?Init@NAMMGR@@RECPEXPEVSHEAP_MGR@@PEVDYN_TYPEROOT@@@Z
+ 0007:0F68 ?SetGtlibole@NAMMGR@@RECPEXPEVGenericTypeLibOLE@@@Z
+ 0007:0F84 ?SetBucketOfHash@NAMMGR@@BECXII@Z
+ 0007:107C ?ErrOpenFile@@ZAPEXPFDPEHPED@Z
+ 0007:10C6 ?ErrOpen@@ZAPEXPFDPEH@Z
+ 0007:1114 ?wcslen@@ZAIPEG@Z
+ 0007:1134 ?wcsicmp@@ZAIPEG0@Z
+ 0007:11A4 ?GetRsrcDirEntry@@ZAPEXHKPEGKPEU_IMAGE_RESOURCE_DIRECTORY_ENTRY@@@Z
+ 0007:154A ?GetOffsetOfResource@@ZAPEXHPEDHPEU_IMAGE_DOS_HEADER@@PEJ2@Z
+ 0007:1B4A ?GetOffsetOfTypeLibResource@@ZAPEXHHPEU_IMAGE_DOS_HEADER@@PEJ1@Z
+ 0007:1B70 ?InitLoadInfo@@ZAXPEULoadInfo@@@Z
+ 0007:1BA2 ?UninitLoadInfo@@ZAXPEULoadInfo@@@Z
+ 0007:1BE4 ?VerifyIsExeOrTlb@@YAPEXPEULoadInfo@@@Z
+ 0007:1CB6 ?SplitResID@@ZAPEXPEDPEPED@Z
+ 0007:1D48 ?FindTypeLibUnqual@@ZAPEXPFDPEULoadInfo@@@Z
+ 0007:1EA0 ?FindTypeLib@@ZAPEXPFDPEULoadInfo@@H@Z
+ 0007:2010 LOADTYPELIB
+ 0007:245A ?RegCreateSubKey@@ZAPEXKPED0H@Z
+ 0007:24C0 REGISTERTYPELIB
+ 0007:2C82 ??2GenericTypeLibOLE@@LAPEXI@Z
+ 0007:2CB0 ?Init@GenericTypeLibOLE@@VECPEXXZ
+ 0007:2E50 ?Create@GenericTypeLibOLE@@TAPEXPEUIStorage@@PEPEV1@@Z
+ 0007:2F02 ??0GenericTypeLibOLE@@JEC@XZ
+ 0007:30A4 ?Release@GenericTypeLibOLE@@VEAKXZ
+ 0007:3158 ??1GenericTypeLibOLE@@NEC@XZ
+ 0007:341E ?GetDocumentation@GenericTypeLibOLE@@VEAPEXHPEPED0PEK0@Z
+ 0007:391E ?GetLibAttr@GenericTypeLibOLE@@VEAPEXPEPEUtagTLIBATTR@@@Z
+ 0007:3A02 ?ReleaseTLibAttr@GenericTypeLibOLE@@VEAXPEUtagTLIBATTR@@@Z
+ 0007:3A26 ?SetDirectory@GenericTypeLibOLE@@JECPEXPED@Z
+ 0007:3A88 ?SetLibId@GenericTypeLibOLE@@RECPEXPED@Z
+ 0007:3ACE ?GetTypeInfoType@GenericTypeLibOLE@@VEAPEXIPEW4tagTYPEKIND@@@Z
+ 0007:3B22 ?GetStorage@GenericTypeLibOLE@@RECPEXKPEPEUIStorage@@@Z
+ 0007:3D36 ?Read@GenericTypeLibOLE@@JECPEXXZ
+ 0007:3DBE ?ReadString@GenericTypeLibOLE@@JECPEXPEVSTREAM@@PEI@Z
+ 0007:3EAE ?Read@GenericTypeLibOLE@@JECPEXPEVSTREAM@@@Z
+ 0007:44B8 ?QtrOfHChunk@GenericTypeLibOLE@@JECPEXI@Z
+ 0007:44E6 ?QszLibIdOrFile@GenericTypeLibOLE@@JECPEDXZ
+ 0007:451E ?ReleaseResources@GenericTypeLibOLE@@RECXXZ
+ 0007:4536 ?CreateHsz@GenericTypeLibOLE@@JECPEXPEDPEI@Z
+ 0007:45C4 ?ResetHsz@GenericTypeLibOLE@@JECPEXPEDPEI@Z
+ 0007:4658 ?SetModified@GenericTypeLibOLE@@RECPEXH@Z
+ 0007:4680 ?GetNamMgr@GenericTypeLibOLE@@RECPEXPEPEVNAMMGR@@@Z
+ 0007:4778 ?OpenTypeStream@GenericTypeLibOLE@@RECPEXIW4STREAM_OPEN_MODE@@PEPEVSTREAM@@@Z
+ 0007:49B0 ?Open@DOCFILE_STREAM@@TAPEXPEPEUIStorage@@0PEVGenericTypeLibOLE@@IHPEDW4STREAM_OPEN_MODE@@PEPEVSTREAM@@@Z
+ 0007:4A4A ?Open@DOCFILE_STREAM@@TAPEXPEPEUIStorage@@0HPEDW4STREAM_OPEN_MODE@@PEPEVSTREAM@@@Z
+ 0007:4BE6 ??0DOCFILE_STREAM@@JEC@XZ
+ 0007:4C4C ??1DOCFILE_STREAM@@JEC@XZ
+ 0007:4C70 ?Read@DOCFILE_STREAM@@VECPEXPEXK@Z
+ 0007:4D2C ?ReadTextLine@DOCFILE_STREAM@@VECPEXPEDI@Z
+ 0007:4D36 ?FillBuffer@DOCFILE_STREAM@@JECPEXXZ
+ 0007:4DD2 ?GetPos@DOCFILE_STREAM@@VECPEXPEJ@Z
+ 0007:4E48 ?AddRef@DOCFILE_STREAM@@RECXXZ
+ 0007:4E56 ?Release@DOCFILE_STREAM@@VECPEXXZ
+ 0007:4F96 ?Create@OLE_TYPEMGR@@TAPEXPEPEV1@@Z
+ 0007:4FFA ?Release@OLE_TYPEMGR@@RECXXZ
+ 0007:5026 ?TypeLibLoaded@OLE_TYPEMGR@@RECPEXPFDPEUITypeLib@@@Z
+ 0007:512C ?TypeLibUnloaded@OLE_TYPEMGR@@RECXPEUITypeLib@@@Z
+ 0007:51C8 ?LookupTypeLib@OLE_TYPEMGR@@RECPEUITypeLib@@PFD@Z
+ 0007:5278 ??0IMPMGR@@REC@XZ
+ 0007:52C4 ?GetBStrOfHsz@@ZAPEXPEVBLK_MGR@@IPEPED@Z
+ 0007:5358 _VerifyLcid
+ 0007:53A0 ?Poletmgr@@ZAPEVOLE_TYPEMGR@@XZ
+ 0007:53B2 ?GetPathEnd@@ZAPEDPED@Z
+ 0007:53FC ??0GENPROJ_BINDNAME_TABLE@@REC@XZ
+ 0007:5450 ??1GENPROJ_BINDNAME_TABLE@@REC@XZ
+ 0007:5482 ?Init@GENPROJ_BINDNAME_TABLE@@RECPEXPEVSHEAP_MGR@@PEVNAMMGR@@@Z
+ 0007:5504 ?FreeCaches@GENPROJ_BINDNAME_TABLE@@JECXXZ
+ 0007:5562 ?ReleaseTable@GENPROJ_BINDNAME_TABLE@@RECXXZ
+ 0007:55AE ?ReleaseResources@GENPROJ_BINDNAME_TABLE@@RECXXZ
+ 0007:5654 ??0DOCSTR_MGR@@REC@XZ
+ 0007:56A6 ??1DOCSTR_MGR@@REC@XZ
+ 0007:5880 ?Init@DOCSTR_MGR@@RECPEXXZ
+ 0007:5950 ?ZeroFill@@ZAXPIXK@Z
+ 0007:598C ??1GENPROJ_TYPEBIND@@VEC@XZ
+ 0007:59C8 ?Pgtlibole@GENPROJ_TYPEBIND@@RFCPEVGenericTypeLibOLE@@XZ
+ 0007:59DA ?Init@GENPROJ_TYPEBIND@@RECPEXPEVSHEAP_MGR@@@Z
+ 0007:5A3E ??0GENPROJ_TYPEBIND@@REC@XZ
+ 0007:5A9C ?ReleaseResources@GENPROJ_TYPEBIND@@RECXXZ
+ 0007:5AB4 ?OpenForReadOnly@GTLibStorage@@TAPEXPEUILockBytes@@PEPEUIStorage@@@Z
+ 0007:5DF8 ??0GTLibStorage@@JEC@XZ
+ 0007:5E88 ??1GTLibStorage@@JEC@XZ
+ 0007:5ED6 ?AddRef@GTLibStorage@@VEAKXZ
+ 0007:5EF8 ?Release@GTLibStorage@@VEAKXZ
+ 0007:5F46 ?LookupStream@GTLibStorage@@JECPEUStreamInfo@@PFD@Z
+ 0007:5FE2 ?OpenStream@GTLibStorage@@VEAPEXPFDPEXKKPEPEUIStream@@@Z
+ 0007:60AC ?Stat@GTLibStorage@@VEAPEXPEUtagSTATSTG@@K@Z
+ 0007:6150 ??0GTLibStream@@JEC@XZ
+ 0007:6182 ??1GTLibStream@@JEC@XZ
+ 0007:621C ?Open@GTLibStream@@TAPEXPEUILockBytes@@KKPEPEUIStream@@@Z
+ 0007:62D4 ?AddRef@GTLibStream@@VEAKXZ
+ 0007:62F6 ?Release@GTLibStream@@VEAKXZ
+ 0007:6344 ?Read@GTLibStream@@VEAPEXPIXKPEK@Z
+ 0007:63E2 ?OpenFileLockBytes@@ZAPEXHPEDPEPEUILockBytes@@@Z
+ 0007:645C ?CreateFileLockBytesOnHFILE@@ZAPEXHHKKPEPEUILockBytes@@@Z
+ 0007:64BA ??0FileLockBytes@@JEC@XZ
+ 0007:64F8 ??1FileLockBytes@@JEC@XZ
+ 0007:6526 ?AddRef@FileLockBytes@@VEAKXZ
+ 0007:6548 ?Release@FileLockBytes@@VEAKXZ
+ 0007:6596 ?ReadAt@FileLockBytes@@VEAPEXU_ULARGE_INTEGER@@PIXKPEK@Z
+ 0007:661E ?Pappdata@@ZAPEUAPP_DATA@@XZ
+ 0007:665A ?InitAppData@@ZAPEXXZ
+ 0007:67A0 ?ReleaseAppData@@ZAXXZ
+ 0007:6810 ?Release@GenericTypeLibOLE@@X3EAKXZ
+ 0008:0000 ?g_rgbCodePage1252@@3QEEE
+ 0009:0000 ?g_rgbCodePage10000@@3QEEE
+ 000A:0000 ?g_rgbCodePage1250@@3QEEE
+ 000B:0000 ?g_rgbCodePage1251@@3QEEE
+ 000C:0000 ?g_rgbCodePage10029@@3QEEE
+ 000D:0000 ?g_rgbCodePage10007@@3QEEE
+ 000E:0000 ?g_rgbCodePageWGreek@@3QEEE
+ 000F:0000 ?g_rgbCodePageWIceland@@3QEEE
+ 0010:0000 ?LHashValOfDBCSName@@ZAKW4tagSYSKIND@@KPFD@Z
+ 0010:015B ?m_rgChinaSExcepMap@@3QEY01GE
+ 0010:0257 ?m_rgChinaTExcepMap@@3QEY01GE
+ 0010:0353 ?m_rgKoreaExcepMap@@3QEY01GE
+ 0010:0453 ?m_rgJapneseExcepMap@@3QEY01GE
+ 0010:0800 ?MapDBChar@@ZAGGK@Z
+ 0011:0000 ?g_rgbCodePageWTurkish@@3QEEE
+ 0012:0000 ?g_rgbCodePageWNorwegian@@3QEEE
+ 0013:0000 ?g_rgbCodePageWEngIreland@@3QEEE
+ 0014:0000 ?g_rgbCodePageMGreek@@3QEEE
+ 0015:0000 ?g_rgbCodePageMNorwegian@@3QEEE
+ 0016:0000 ?g_rgbCodePageMEngIreland@@3QEEE
+ 0017:0000 ?g_rgbCodePage1255@@3QEEE
+ 0018:0000 ?g_rgbCodePage1256@@3QEEE
+ 0019:0000 ?g_rgbCodePage10004@@3QEEE
+ 001A:0000 ?g_rgbCodePage10005@@3QEEE
+ 001B:0000 ?IsFunkyDispinterface@@ZAPEXPEVGEN_DTINFO@@PEH@Z
+ 001B:007E ?InterfaceFuncdescToDispatch@@ZAXPEUtagFUNCDESC@@@Z
+ 001B:0178 ?GetTypeInfoOfImplType@@ZAPEXPEVGEN_DTINFO@@IPEPEUITypeInfo@@@Z
+ 001B:0350 ?IsInterfaceSupported@@ZAPEXPEUITypeInfo@@PEH@Z
+ 001B:0438 ?ReleasePublicResources@GEN_DTINFO@@VECXXZ
+ 001B:0482 ?Create@GEN_DTINFO@@TAPEXPEPEV1@W4tagTYPEKIND@@HW4ACCESS@@W4tagSYSKIND@@@Z
+ 001B:0594 ?GetDynTypeMembers@GEN_DTINFO@@VECPEXPEPEVDYN_TYPEMEMBERS@@@Z
+ 001B:05F2 ?GetDefnTypeBind@GEN_DTINFO@@VECPEXPEPEVDEFN_TYPEBIND@@@Z
+ 001B:0674 ?CreateInstance@GEN_DTINFO@@VEAPEXPEUIUnknown@@AFUGUID@@PEPEX@Z
+ 001B:07BA ?MakeDual@GEN_DTINFO@@RECPEXXZ
+ 001B:0A5A ?MakeHimptypeLevels@DYN_TYPEROOT@@RECPEXXZ
+ 001B:0BF4 ?GetTypeAttr@GEN_DTINFO@@VEAPEXPEPEUtagTYPEATTR@@@Z
+ 001B:1020 ?ReleaseFuncDesc@GEN_DTINFO@@VEAXPEUtagFUNCDESC@@@Z
+ 001B:103A ?ReleaseVarDesc@GEN_DTINFO@@VEAXPEUtagVARDESC@@@Z
+ 001B:1054 ?ReleaseTypeAttr@GEN_DTINFO@@VEAXPEUtagTYPEATTR@@@Z
+ 001B:10B6 ?GetTypeComp@GEN_DTINFO@@VEAPEXPEPEUITypeComp@@@Z
+ 001B:1172 ?GetNames@GEN_DTINFO@@VEAPEXJPEPEDIPEI@Z
+ 001B:1440 ?GetRefTypeOfImplType@GEN_DTINFO@@VEAPEXIPEK@Z
+ 001B:1576 ?GetImplTypeFlags@GEN_DTINFO@@VEAPEXIPEH@Z
+ 001B:15EA ?GetRefTypeInfo@GEN_DTINFO@@VEAPEXKPEPEUITypeInfo@@@Z
+ 001B:19CE ?GetDllEntry@GEN_DTINFO@@VEAPEXJW4tagINVOKEKIND@@PEPED1PEG@Z
+ 001B:1CA4 ?AddressOfMember@GEN_DTINFO@@VEAPEXJW4tagINVOKEKIND@@PEPEX@Z
+ 001B:1E3C ?ReleaseDtmbrs@DYN_TYPEROOT@@RECXXZ
+ 001B:1E66 ?AddRefDtmbrs@DYN_TYPEROOT@@RECXXZ
+ 001B:1E90 ?Read@DYN_TYPEROOT@@NECPEXXZ
+ 001B:1FCE ?ReadFixed@DYN_TYPEROOT@@NECPEXPEVSTREAM@@@Z
+ 001B:20C2 ?PdfntbindSemiDeclared@DYN_TYPEROOT@@RECPEXPEPEVDEFN_TYPEBIND@@@Z
+ 001B:2132 ?IsIdMungable@DYN_TYPEROOT@@RECHKPEG@Z
+ 001B:22BA ?GetVarDesc@GEN_DTINFO@@VEAPEXIPEPEUtagVARDESC@@@Z
+ 001B:234E ?GetFuncDesc@GEN_DTINFO@@VEAPEXIPEPEUtagFUNCDESC@@@Z
+ 001C:0000 ?AddRefTypeInfo@GEN_DTINFO@@VEAPEXPEUITypeInfo@@PEK@Z
+ 001C:0156 ?AddImplType@GEN_DTINFO@@VEAPEXIK@Z
+ 001C:039C ?LayOut@GEN_DTINFO@@VEAPEXXZ
+ 001C:071A ?EnsureInDeclaredState@DYN_TYPEROOT@@RECPEXXZ
+ 001C:07E6 ?EnsureInSemiDeclaredState@DYN_TYPEROOT@@RECPEXXZ
+ 001C:0866 ?Write@DYN_TYPEROOT@@NECPEXXZ
+ 001C:097E ?UpdateTypeId@GenericTypeLibOLE@@RECPEXI@Z
+ 001C:0A4A ?AppendDefn@TYPE_DATA@@BECXIPEG0@Z
+ 001C:0AB0 ?AppendMbrVarDefn@TYPE_DATA@@BECXI@Z
+ 001C:0B26 ?AddImplType@TYPE_DATA@@RECPEXIK@Z
+ 001C:0CA2 ?MakeLaidOut@DYN_TYPEMEMBERS@@VECPEXXZ
+ 001C:0D2E ?LayoutBases@DYN_TYPEMEMBERS@@JECPEXW4tagTYPEKIND@@PEI1@Z
+ 001C:0E88 ?LayoutVarOfHvdefn@DYN_TYPEMEMBERS@@RECPEXW4tagTYPEKIND@@IPEGPEIHIH@Z
+ 001C:104E ?LayoutDataMembers@DYN_TYPEMEMBERS@@JECPEXW4tagTYPEKIND@@PEI1I@Z
+ 001C:10DE ?LayoutMembers@DYN_TYPEMEMBERS@@JECPEXXZ
+ 001C:127A ?Layout@DYN_TYPEMEMBERS@@JECPEXXZ
+ 001C:13B4 ?AdjustForAlignment@DYN_TYPEMEMBERS@@LAIIIH@Z
+ 001C:13E6 ?AlignMember@DYN_TYPEMEMBERS@@LAIPEGIIH@Z
+ 001D:0000 ?GetMops@GEN_DTINFO@@VEAPEXJPEPED@Z
+ 001D:002C ?SetMops@GEN_DTINFO@@VEAPEXIPED@Z
+ 001D:003E ?SetTypeIdldesc@GEN_DTINFO@@VEAPEXPEUtagIDLDESC@@@Z
+ 001D:0050 ?GetEmbeddedTypeInfo@GEN_DTINFO@@VECPEXPEDPEPEVTYPEINFO@@@Z
+ 001D:005A ?GetTypeFixups@GEN_DTINFO@@VECPEXPEPEVTYPEFIXUPS@@@Z
+ 001D:006C ?SetSchema@GEN_DTINFO@@VEAPEXPED@Z
+ 001D:007E ?CreateStorage@GTLibStorage@@VEAPEXPFDKKKPEPEUIStorage@@@Z
+ 001D:0090 ?OpenStorage@GTLibStorage@@VEAPEXPFDPEUIStorage@@KPEPEDKPEPEU2@@Z
+ 001D:00A2 ?CopyTo@GTLibStorage@@VEAPEXKPFUGUID@@PEPEDPEUIStorage@@@Z
+ 001D:00B4 ?MoveElementTo@GTLibStorage@@VEAPEXPFDPEUIStorage@@0K@Z
+ 001D:00C6 ?Revert@GTLibStorage@@VEAPEXXZ
+ 001D:00D8 ?EnumElements@GTLibStorage@@VEAPEXKPEXKPEPEUIEnumSTATSTG@@@Z
+ 001D:00EA ?DestroyElement@GTLibStorage@@VEAPEXPFD@Z
+ 001D:00FC ?RenameElement@GTLibStorage@@VEAPEXPFD0@Z
+ 001D:010E ?SetElementTimes@GTLibStorage@@VEAPEXPFDPFUtagFILETIME@@11@Z
+ 001D:0120 ?SetStateBits@GTLibStorage@@VEAPEXKK@Z
+ 001D:0132 ?SetSize@GTLibStream@@VEAPEXU_ULARGE_INTEGER@@@Z
+ 001D:0144 ?CopyTo@GTLibStream@@VEAPEXPEUIStream@@U_ULARGE_INTEGER@@PEU3@2@Z
+ 001D:0156 ?Revert@GTLibStream@@VEAPEXXZ
+ 001D:0168 ?LockRegion@GTLibStream@@VEAPEXU_ULARGE_INTEGER@@0K@Z
+ 001D:017A ?UnlockRegion@GTLibStream@@VEAPEXU_ULARGE_INTEGER@@0K@Z
+ 001D:018C ?Stat@GTLibStream@@VEAPEXPEUtagSTATSTG@@K@Z
+ 001D:019E ?Clone@GTLibStream@@VEAPEXPEPEUIStream@@@Z
+ 001D:01B0 ?SetSize@FileLockBytes@@VEAPEXU_ULARGE_INTEGER@@@Z
+ 001D:01C2 ?LockRegion@FileLockBytes@@VEAPEXU_ULARGE_INTEGER@@0K@Z
+ 001D:01D4 ?UnlockRegion@FileLockBytes@@VEAPEXU_ULARGE_INTEGER@@0K@Z
+ 001D:01E4 ?Stat@FileLockBytes@@VEAPEXPEUtagSTATSTG@@K@Z
+ 001E:014A ?GetIDsOfNames@GEN_DTINFO@@VEAPEXPEPEDIPEJ@Z
+ 001E:07B8 ?IndexOfParam@GEN_DTINFO@@QECPEXPEUtagDISPPARAMS@@IPEI@Z
+ 001E:0822 ?VariantVtOfTypedesc@GEN_DTINFO@@QECPEXPEUtagTYPEDESC@@PEGPEUGUID@@1@Z
+ 001E:0B86 ?VariantVtOfHtdefn@GEN_DTINFO@@QECPEXIPEVTYPE_DATA@@HPEGPEUGUID@@1@Z
+ 001E:0BEA ?Invoke@GEN_DTINFO@@VEAPEXPEXJGPEUtagDISPPARAMS@@PEUtagVARIANT@@PEUtagEXCEPINFO@@PEI@Z
+ 001E:1746 ?CoerceArg@GEN_DTINFO@@QECPEXPEUtagVARIANT@@GGPEUGUID@@PEUINVOKEARGS@1@I@Z
+ 001E:1CDE ?GetInvokeArgs@GEN_DTINFO@@QECPEXIPEVTYPE_DATA@@GPEUtagDISPPARAMS@@PEPEUtagVARIANT@@PEXPEPEUINVOKEARGS@1@PEIH@Z
+ 001E:242A ?AllocInvokeArgs@GEN_DTINFO@@QECPEXIIPEPEUINVOKEARGS@1@@Z
+ 001E:25CC ?ReleaseInvokeArgs@GEN_DTINFO@@QECXPEUINVOKEARGS@1@@Z
+ 001E:2632 ?CopyBackByrefArgs@GEN_DTINFO@@QECPEXPEUINVOKEARGS@1@@Z
+ 001F:0004 rsrvptrs
+ 001F:0014 ?BM_cbSizeInitial@@3IF
+ 001F:0020 ?m_cbSizeInitial@SHEAP_MGR@@2IF
+ 001F:0022 _g_pthreadEnd
+ 001F:002C ?g_fSBCS@@3HE
+ 001F:002E ?_mbascii@@3IE
+ 001F:0032 ?g_szGuidStdole@@3PEDE
+ 001F:0036 ?bCurVersion@DYN_TYPEROOT@@1EF
+ 001F:0037 ?bFirstSerByte@DYN_TYPEROOT@@1EF
+ 001F:0038 ?cbSizeDir@DYN_TYPEROOT@@1GF
+ 001F:006A ?wFirstSerWord@GenericTypeLibOLE@@1GF
+ 001F:006C ?wDefaultVersion@GenericTypeLibOLE@@1GF
+ 001F:006E ?wDualVersion@GenericTypeLibOLE@@1GF
+ 001F:0070 ?wMaxVersion@GenericTypeLibOLE@@1GF
+ 001F:0072 ?chMinorVerNumSep@GenericTypeLibOLE@@1DF
+ 001F:0073 ?chLibIdSep@GenericTypeLibOLE@@1DF
+ 001F:0074 ?szDirStreamName@GenericTypeLibOLE@@1QEDE
+ 001F:0078 ?oGptbind@GenericTypeLibOLE@@2IF
+ 001F:01A0 ?bFirstSerByte@IMPMGR@@0EE
+ 001F:01A1 ?bCurVersion@IMPMGR@@0EE
+ 001F:01A6 ?szPlatSubkey1@@3PEDE
+ 001F:01AA ?szPlatSubkey2@@3PEDE
+ 001F:01BA ?g_rgrgcbSizeType@@3QAY0CA@DA
+ 001F:021A ?g_rgcbAlignment@@3QADA
+ 001F:025C ?oDtbind@DYN_TYPEMEMBERS@@2IF
+ 001F:0260 ?wFirstSerWord@ENTRYMGR@@0GF
+ 001F:0262 ?cbSizeSerMem@ENTRYMGR@@0GF
+ 001F:0264 ?wCurFormat@ENTRYMGR@@0GF
+ 001F:0268 ?szProtocolName@DYN_TYPEBIND@@2PEDE
+ 001F:026C ?oDbindnametbl@DYN_TYPEBIND@@2IF
+ 001F:0280 ?szProtocolName@DEFN_TYPEBIND@@2PEDE
+ 001F:0284 ?szBaseName@DEFN_TYPEBIND@@2PEDE
+ 001F:02B0 ?szProtocolName@GENPROJ_TYPEBIND@@2PEDE
+ 001F:02B4 ?oGbindnametbl@GENPROJ_TYPEBIND@@2IF
+ 001F:02D0 ?g_itlsAppData@@3GE
+ 001F:02D2 _g_tidAppdataCache
+ 001F:02D4 _g_pAppdataCache
+ 001F:02DA __aaltstkovr
+ 001F:02DE _STKHQQ
+ 001F:02E0 __hModule
+ 001F:02E2 __wDataSeg
+ 001F:02E4 __wHeapSize
+ 001F:02E6 __lpszCmdLine
+ 001F:02EA __dllinit
+ 001F:02EB _aseglo
+ 001F:02ED _aseghi
+ 001F:02EF ___aDBswpflg
+ 001F:02F1 ___aDBrterr
+ 001F:030A __ctype
+ 001F:030A __ctype_
+ 001F:040C __adbgmsg
+ 001F:0424 ___mb_cur_max
+ 001F:0426 __aintdiv
+ 001F:042A __fac
+ 001F:0434 _errno
+ 001F:0436 __umaskval
+ 001F:0438 __osmajor
+ 001F:0438 __osversion
+ 001F:0439 __osminor
+ 001F:043A __dosmajor
+ 001F:043A __dosversion
+ 001F:043B __dosminor
+ 001F:043C __osmode
+ 001F:043D __cpumode
+ 001F:043E __oserr
+ 001F:043E __doserrno
+ 001F:0440 __nfile
+ 001F:0442 __osfile
+ 001F:047E ___argc
+ 001F:0480 ___argv
+ 001F:0484 __environ
+ 001F:0488 __pgmptr
+ 001F:048D __child
+ 001F:048F __exitflag
+ 001F:0498 __lpdays
+ 001F:04B2 __days
+ 001F:04CC __timezone
+ 001F:04D0 __daylight
+ 001F:04D2 __tzname
+ 001F:04DA ___dnames
+ 001F:04F0 ___mnames
+ 001F:051E __amblksiz
+ 001F:0520 __pnhFarHeap
+ 001F:0524 __fheap
+ 001F:0534 __fpinit
+ 001F:0626 __edata
+ 001F:0626 _g_rgchLeadByteTable
+ 001F:0626 _edata
+ 001F:09D0 _g_rgbSlot
+ 001F:09D2 _g_rgthread
+ 001F:0C8E _g_pthreadCache
+ 001F:0C92 _g_tidThreadCache
+ 001F:0C94 _end
+ 001F:0C94 __end
+
+Program entry point at 0001:00B6
diff --git a/private/ole32/olethunk/bin16/typelib.sym b/private/ole32/olethunk/bin16/typelib.sym
new file mode 100644
index 000000000..c137a5438
--- /dev/null
+++ b/private/ole32/olethunk/bin16/typelib.sym
Binary files differ
diff --git a/private/ole32/olethunk/daytona/dirs b/private/ole32/olethunk/daytona/dirs
new file mode 100644
index 000000000..c1241068c
--- /dev/null
+++ b/private/ole32/olethunk/daytona/dirs
@@ -0,0 +1,29 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ ?
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
diff --git a/private/ole32/olethunk/daytona/makefil0 b/private/ole32/olethunk/daytona/makefil0
new file mode 100644
index 000000000..9215b1c44
--- /dev/null
+++ b/private/ole32/olethunk/daytona/makefil0
@@ -0,0 +1,11 @@
+# INTEROP makefile
+#
+# Copyright (c) 1994, Microsoft Corporation
+#
+
+all:
+ cd ..\bin16
+ $(MAKE)
+ cd ..
+
+clean: all
diff --git a/private/ole32/olethunk/debnot/assert.cxx b/private/ole32/olethunk/debnot/assert.cxx
new file mode 100644
index 000000000..d6125e5e4
--- /dev/null
+++ b/private/ole32/olethunk/debnot/assert.cxx
@@ -0,0 +1,252 @@
+//+---------------------------------------------------------------------------
+// Copyright (C) 1991, Microsoft Corporation.
+//
+// File: assert.cxx
+//
+// Contents: Debugging output routines for idsmgr.dll
+//
+// Functions: _Assert
+// _PopUpError
+//
+// History: 23-Jul-91 KyleP Created.
+// 09-Oct-91 KevinRo Major changes and comments added
+// 18-Oct-91 vich moved debug print routines out
+// 10-Jun-92 BryanT Switched to w4crt.h instead of wchar.h
+//
+//----------------------------------------------------------------------------
+
+//
+// This one file **always** uses debugging options
+//
+
+#if DBG == 1
+
+#include <stdarg.h>
+
+# include <debnot.h>
+# include "dprintf.h" // w4printf, w4dprintf prototypes
+
+extern "C"
+{
+#include <windows.h>
+
+#ifndef WIN32
+#define MessageBoxA MessageBox
+#define wsprintfA wsprintf
+#endif
+}
+
+int APINOT _PopUpError(char const FAR *szMsg,
+ int iLine,
+ char const FAR *szFile);
+
+unsigned long Win4InfoLevel = DEF_INFOLEVEL;
+unsigned long Win4InfoMask = 0xffffffff;
+unsigned long Win4AssertLevel = ASSRT_MESSAGE | ASSRT_BREAK | ASSRT_POPUP;
+
+//+---------------------------------------------------------------------------
+//
+// Function: _asdprintf
+//
+// Synopsis: Calls vdprintf to output a formatted message.
+//
+// History: 18-Oct-91 vich Created
+//
+//----------------------------------------------------------------------------
+inline void _asdprintf(char const FAR *pszfmt, ...)
+{
+ va_list va;
+ va_start(va, pszfmt);
+
+ vdprintf(DEB_FORCE, "Assert", pszfmt, va);
+
+ va_end(va);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: _Win4Assert, private
+//
+// Synopsis: Display assertion information
+//
+// Effects: Called when an assertion is hit.
+//
+// History: 12-Jul-91 AlexT Created.
+// 05-Sep-91 AlexT Catch Throws and Catches
+// 19-Oct-92 HoiV Added events for TOM
+//
+//----------------------------------------------------------------------------
+
+void APINOT _Win4Assert(char const FAR * szFile,
+ int iLine,
+ char const FAR * szMessage)
+{
+ if (Win4AssertLevel & ASSRT_MESSAGE)
+ {
+ _asdprintf("%s File: %s Line: %u\n", szMessage, szFile, iLine);
+ }
+
+ if (Win4AssertLevel & ASSRT_POPUP)
+ {
+ int id = _PopUpError(szMessage,iLine,szFile);
+
+ if (id == IDCANCEL)
+ {
+#ifndef FLAT
+ _asm int 3;
+#else
+ DebugBreak();
+#endif
+ }
+ }
+ else if (Win4AssertLevel & ASSRT_BREAK)
+ {
+#ifndef FLAT
+ _asm int 3;
+#else
+ DebugBreak();
+#endif
+ }
+}
+
+
+//+------------------------------------------------------------
+// Function: _SetWin4InfoLevel(unsigned long ulNewLevel)
+//
+// Synopsis: Sets the global info level for debugging output
+// Returns: Old info level
+//
+//-------------------------------------------------------------
+
+unsigned long APINOT _SetWin4InfoLevel(unsigned long ulNewLevel)
+{
+ unsigned long ul;
+
+ ul = Win4InfoLevel;
+ Win4InfoLevel = ulNewLevel;
+ return(ul);
+}
+
+
+//+------------------------------------------------------------
+// Function: _SetWin4InfoMask(unsigned long ulNewMask)
+//
+// Synopsis: Sets the global info mask for debugging output
+// Returns: Old info mask
+//
+//-------------------------------------------------------------
+
+unsigned long APINOT _SetWin4InfoMask(unsigned long ulNewMask)
+{
+ unsigned long ul;
+
+ ul = Win4InfoMask;
+ Win4InfoMask = ulNewMask;
+ return(ul);
+}
+
+
+//+------------------------------------------------------------
+// Function: _SetWin4AssertLevel(unsigned long ulNewLevel)
+//
+// Synopsis: Sets the global assert level for debugging output
+// Returns: Old assert level
+//
+//-------------------------------------------------------------
+
+unsigned long APINOT _SetWin4AssertLevel(unsigned long ulNewLevel)
+{
+ unsigned long ul;
+
+ ul = Win4AssertLevel;
+ Win4AssertLevel = ulNewLevel;
+ return(ul);
+}
+
+//+------------------------------------------------------------
+// Function: _PopUpError
+//
+// Synopsis: Displays a dialog box using provided text,
+// and presents the user with the option to
+// continue or cancel.
+//
+// Arguments:
+// szMsg -- The string to display in main body of dialog
+// iLine -- Line number of file in error
+// szFile -- Filename of file in error
+//
+// Returns:
+// IDCANCEL -- User selected the CANCEL button
+// IDOK -- User selected the OK button
+//-------------------------------------------------------------
+
+int APINOT _PopUpError(char const FAR *szMsg,int iLine, char const FAR *szFile)
+{
+
+ int id;
+ static char szAssertCaption[100];
+ wsprintfA(szAssertCaption, "File: %s line %u", szFile,iLine);
+
+ id = MessageBoxA(NULL,
+ (char FAR *) szMsg,
+ (LPSTR) szAssertCaption,
+ MB_TASKMODAL | MB_ICONEXCLAMATION | MB_OKCANCEL);
+ return id;
+}
+
+
+//+------------------------------------------------------------
+// Function: vdprintf
+//
+// Synopsis: Prints debug output using a pointer to the
+// variable information. Used primarily by the
+// xxDebugOut macros
+//
+// Arguements:
+// ulCompMask -- Component level mask used to determine
+// output ability
+// pszComp -- String const of component prefix.
+// ppszfmt -- Pointer to output format and data
+//
+//-------------------------------------------------------------
+
+void APINOT vdprintf(unsigned long ulCompMask,
+ char const FAR *pszComp,
+ char const FAR *ppszfmt,
+ va_list pargs)
+{
+ if ((ulCompMask & DEB_FORCE) == DEB_FORCE ||
+ ((ulCompMask | Win4InfoLevel) & Win4InfoMask))
+ {
+ if (! (ulCompMask & DEB_NOCOMPNAME))
+ {
+#ifdef WIN32
+#if defined(_CHICAGO_)
+ //
+ // Hex Process/Thread ID's are better for Chicago since both
+ // are memory addresses.
+ //
+ w4dprintf("%08x.%08x> %s: ",
+#else
+ w4dprintf("%03d.%03d> %s: ",
+#endif
+ GetCurrentProcessId(),
+ GetCurrentThreadId(),
+ pszComp);
+#else
+ w4dprintf("%07x> %s: ",
+ GetCurrentTask(),
+ pszComp);
+#endif
+ }
+ w4vdprintf(ppszfmt, pargs);
+
+ // Chicago and Win32s debugging is usually through wdeb386
+ // which needs carriage returns
+#if WIN32 == 50 || WIN32 == 200
+ w4dprintf("\r");
+#endif
+ }
+}
+
+#endif // DBG == 1
diff --git a/private/ole32/olethunk/debnot/daytona/makefile b/private/ole32/olethunk/debnot/daytona/makefile
new file mode 100644
index 000000000..9452d9ca9
--- /dev/null
+++ b/private/ole32/olethunk/debnot/daytona/makefile
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 1991, Microsoft Corporation
+#
+# History:
+#
+# 28-Sept-1994 TerryRu
+
+all:
+!if "$(PROCESSOR_ARCHITECTURE)" == "x86"
+ @echo making dos mode binaries under NTVDM.
+ cd ..
+ $(MAKE) "OPST=dayt" /f win16.mk
+ cd $(MAKEDIR)
+!endif
+
+
+clean:
+!if "$(PROCESSOR_ARCHITECTURE)" == "x86"
+ cd ..
+ $(MAKE) "OPST=dayt" /f win16.mk clean
+ cd $(MAKEDIR)
+!endif
+
diff --git a/private/ole32/olethunk/debnot/daytona/sources b/private/ole32/olethunk/debnot/daytona/sources
new file mode 100644
index 000000000..dc4f04989
--- /dev/null
+++ b/private/ole32/olethunk/debnot/daytona/sources
@@ -0,0 +1,33 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Terry Rusell
+
+
+!ENDIF
+
+MAJORCOMP=cairole
+MINORCOMP=olethunk
+
+
+
+TARGETNAME=olethunk
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+SOURCES=
diff --git a/private/ole32/olethunk/debnot/dirs b/private/ole32/olethunk/debnot/dirs
new file mode 100644
index 000000000..b055cc6f8
--- /dev/null
+++ b/private/ole32/olethunk/debnot/dirs
@@ -0,0 +1,36 @@
+
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Terry Russell (TerryRu) 28-Sep-1994
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+
+DIRS=WIN32
+
+
+OPTIONAL_DIRS= \
+ daytona
+
+
+
diff --git a/private/ole32/olethunk/debnot/dprintf.c b/private/ole32/olethunk/debnot/dprintf.c
new file mode 100644
index 000000000..88d6047a2
--- /dev/null
+++ b/private/ole32/olethunk/debnot/dprintf.c
@@ -0,0 +1,19 @@
+/***
+*dprintf.c - print formatted to debug port
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4dprintf() - print formatted data to debug port
+* defines w4vdprintf() - print formatted output to debug port, get data
+* from an argument ptr instead of explicit args.
+*******************************************************************************/
+
+#if DBG == 1
+
+#include "dprintf.h" // function prototypes
+
+#define _W4DPRINTF_
+#include "printf.h"
+
+#endif // DBG == 1
diff --git a/private/ole32/olethunk/debnot/dprintf.h b/private/ole32/olethunk/debnot/dprintf.h
new file mode 100644
index 000000000..7cf0affff
--- /dev/null
+++ b/private/ole32/olethunk/debnot/dprintf.h
@@ -0,0 +1,33 @@
+//+---------------------------------------------------------------------------
+// Copyright (C) 1991, Microsoft Corporation.
+//
+// File: dprintf.h
+//
+// Contents: Debugging output routine function prototypes
+//
+// Functions: w4printf
+// w4vprintf
+// w4dprintf
+// w4vdprintf
+//
+// History: 18-Oct-91 vich Created
+//
+//----------------------------------------------------------------------------
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef WIN32
+int _cdecl w4dprintf(const char __far *format, ...);
+int _cdecl w4vdprintf(const char __far *format, va_list arglist);
+#else
+int _cdecl w4dprintf(const char *format, ...);
+int _cdecl w4vdprintf(const char *format, va_list arglist);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/private/ole32/olethunk/debnot/output.c b/private/ole32/olethunk/debnot/output.c
new file mode 100644
index 000000000..4f2f14fdb
--- /dev/null
+++ b/private/ole32/olethunk/debnot/output.c
@@ -0,0 +1,806 @@
+/***
+*output.c - printf style output to a struct w4io
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the code that does all the work for the
+* printf family of functions. It should not be called directly, only
+* by the *printf functions. We don't make any assumtions about the
+* sizes of ints, longs, shorts, or long doubles, but if types do overlap, we
+* also try to be efficient. We do assume that pointers are the same size
+* as either ints or longs.
+*
+*Revision History:
+* 06-01-89 PHG Module created
+* 08-28-89 JCR Added cast to get rid of warning (no object changes)
+* 02-15-90 GJF Fixed copyright
+* 10-03-90 WHB Defined LOCAL(x) to "static x" for local procedures
+*
+*******************************************************************************/
+
+#if DBG == 1
+
+#include <limits.h>
+#include <string.h>
+#include <stdarg.h>
+#include "w4io.h"
+
+
+/* this macro defines a function which is private and as fast as possible: */
+/* for example, in C 6.0, it might be static _fastcall <type>. */
+#define LOCAL(x) static x // 100390--WHB
+
+#define NOFLOATS // Win 4 doesn't need floating point
+
+/* int/long/short/pointer sizes */
+
+/* the following should be set depending on the sizes of various types */
+// FLAT or LARGE model is assumed
+#ifdef FLAT
+# define LONG_IS_INT 1 /* 1 means long is same size as int */
+# define SHORT_IS_INT 0 /* 1 means short is same size as int */
+# define PTR_IS_INT 1 /* 1 means ptr is same size as int */
+# define PTR_IS_LONG 0 /* 1 means ptr is same size as long */
+#else // LARGE model
+# define LONG_IS_INT 0 /* 1 means long is same size as int */
+# define SHORT_IS_INT 1 /* 1 means short is same size as int */
+# define PTR_IS_INT 0 /* 1 means ptr is same size as int */
+# define PTR_IS_LONG 1 /* 1 means ptr is same size as long */
+#endif
+#define LONGDOUBLE_IS_DOUBLE 0 /* 1 means long double is same as double */
+
+#if LONG_IS_INT
+ #define get_long_arg(x) (long)get_int_arg(x)
+#endif
+
+#if PTR_IS_INT
+ #define get_ptr_arg(x) (void FAR *)get_int_arg(x)
+#elif PTR_IS_LONG
+ #define get_ptr_arg(x) (void FAR *)get_long_arg(x)
+#else
+ #error Size of pointer must be same as size of int or long
+#endif
+
+#ifndef NOFLOATS
+/* These are "fake" double and long doubles to fool the compiler,
+ so we don't drag in floating point. */
+typedef struct {
+ char x[sizeof(double)];
+} DOUBLE;
+typedef struct {
+ char x[sizeof(long double)];
+} LONGDOUBLE;
+#endif
+
+
+/* CONSTANTS */
+
+//#define BUFFERSIZE CVTBUFSIZE /* buffer size for maximum double conv */
+#define BUFFERSIZE 20
+
+/* flag definitions */
+#define FL_SIGN 0x0001 /* put plus or minus in front */
+#define FL_SIGNSP 0x0002 /* put space or minus in front */
+#define FL_LEFT 0x0004 /* left justify */
+#define FL_LEADZERO 0x0008 /* pad with leading zeros */
+#define FL_LONG 0x0010 /* long value given */
+#define FL_SHORT 0x0020 /* short value given */
+#define FL_SIGNED 0x0040 /* signed data given */
+#define FL_ALTERNATE 0x0080 /* alternate form requested */
+#define FL_NEGATIVE 0x0100 /* value is negative */
+#define FL_FORCEOCTAL 0x0200 /* force leading '0' for octals */
+#define FL_LONGDOUBLE 0x0400 /* long double value given */
+#define FL_WIDE 0x0800 /* wide character/string given */
+
+/* state definitions */
+enum STATE {
+ ST_NORMAL, /* normal state; outputting literal chars */
+ ST_PERCENT, /* just read '%' */
+ ST_FLAG, /* just read flag character */
+ ST_WIDTH, /* just read width specifier */
+ ST_DOT, /* just read '.' */
+ ST_PRECIS, /* just read precision specifier */
+ ST_SIZE, /* just read size specifier */
+ ST_TYPE /* just read type specifier */
+};
+#define NUMSTATES (ST_TYPE + 1)
+
+/* character type values */
+enum CHARTYPE {
+ CH_OTHER, /* character with no special meaning */
+ CH_PERCENT, /* '%' */
+ CH_DOT, /* '.' */
+ CH_STAR, /* '*' */
+ CH_ZERO, /* '0' */
+ CH_DIGIT, /* '1'..'9' */
+ CH_FLAG, /* ' ', '+', '-', '#' */
+ CH_SIZE, /* 'h', 'l', 'L', 'N', 'F' */
+ CH_TYPE /* type specifying character */
+};
+
+/* static data (read only, since we are re-entrant) */
+char *nullstring = "(null)"; /* string to print on null ptr */
+
+/* The state table. This table is actually two tables combined into one. */
+/* The lower nybble of each byte gives the character class of any */
+/* character; while the uper nybble of the byte gives the next state */
+/* to enter. See the macros below the table for details. */
+/* */
+/* The table is generated by maketab.c -- use the maketab program to make */
+/* changes. */
+
+static char lookuptable[] = {
+ 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00,
+ 0x10, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x10,
+ 0x04, 0x45, 0x45, 0x45, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x35, 0x30, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x28, 0x38, 0x50, 0x58, 0x07, 0x08,
+ 0x00, 0x30, 0x30, 0x30, 0x57, 0x50, 0x07, 0x00,
+ 0x00, 0x20, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00,
+ 0x00, 0x70, 0x70, 0x78, 0x78, 0x78, 0x78, 0x08,
+ 0x07, 0x08, 0x00, 0x00, 0x07, 0x00, 0x08, 0x08,
+ 0x08, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07,
+ 0x08
+};
+
+#define find_char_class(c) \
+ ((c) < ' ' || (c) > 'x' ? \
+ CH_OTHER \
+ : \
+ lookuptable[(c)-' '] & 0xF)
+
+#define find_next_state(class, state) \
+ (lookuptable[(class) * NUMSTATES + (state)] >> 4)
+
+#if !LONG_IS_INT
+LOCAL(long) get_long_arg(va_list FAR *pargptr);
+#endif
+LOCAL(int) get_int_arg(va_list FAR *pargptr);
+LOCAL(void) writestring(char FAR *string,
+ int len,
+ struct w4io FAR *f,
+ int FAR *pcchwritten,
+ int fwide);
+
+#ifndef NOFLOATS
+/* extern float convert routines */
+typedef int (FAR * PFI)();
+extern PFI _cfltcvt_tab[5];
+#define _cfltcvt(a,b,c,d,e) (*_cfltcvt_tab[0])(a,b,c,d,e)
+#define _cropzeros(a) (*_cfltcvt_tab[1])(a)
+#define _fassign(a,b,c) (*_cfltcvt_tab[2])(a,b,c)
+#define _forcdecpt(a) (*_cfltcvt_tab[3])(a)
+#define _positive(a) (*_cfltcvt_tab[4])(a)
+#define _cldcvt(a,b,c,d,e) (*_cfltcvt_tab[5])(a,b,c,d,e)
+#endif
+
+
+/***
+*int w4iooutput(f, format, argptr)
+*
+*Purpose:
+* Output performs printf style output onto a stream. It is called by
+* printf/fprintf/sprintf/vprintf/vfprintf/vsprintf to so the dirty
+* work. In multi-thread situations, w4iooutput assumes that the given
+* stream is already locked.
+*
+* Algorithm:
+* The format string is parsed by using a finite state automaton
+* based on the current state and the current character read from
+* the format string. Thus, looping is on a per-character basis,
+* not a per conversion specifier basis. Once the format specififying
+* character is read, output is performed.
+*
+*Entry:
+* struct w4io *f - stream for output
+* char *format - printf style format string
+* va_list argptr - pointer to list of subsidiary arguments
+*
+*Exit:
+* Returns the number of characters written, or -1 if an output error
+* occurs.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _cdecl w4iooutput(struct w4io FAR *f, const char FAR *format, va_list argptr)
+{
+ int hexadd; /* offset to add to number to get 'a'..'f' */
+ char ch; /* character just read */
+ wchar_t wc; /* wide character temp */
+ wchar_t FAR *pwc; /* wide character temp pointer */
+ int flags; /* flag word -- see #defines above for flag values */
+ enum STATE state; /* current state */
+ enum CHARTYPE chclass; /* class of current character */
+ int radix; /* current conversion radix */
+ int charsout; /* characters currently written so far, -1 = IO error */
+ int fldwidth; /* selected field with -- 0 means default */
+ int fwide;
+ int precision; /* selected precision -- -1 means default */
+ char prefix[2]; /* numeric prefix -- up to two characters */
+ int prefixlen; /* length of prefix -- 0 means no prefix */
+ int capexp; /* non-zero = 'E' exponent signifiet, zero = 'e' */
+ int no_output; /* non-zero = prodcue no output for this specifier */
+ char FAR *text; /* pointer text to be printed, not zero terminated */
+ int textlen; /* length of the text to be printed */
+ char buffer[BUFFERSIZE]; /* buffer for conversions */
+
+ charsout = 0; /* no characters written yet */
+ state = ST_NORMAL; /* starting state */
+
+ /* main loop -- loop while format character exist and no I/O errors */
+ while ((ch = *format++) != '\0' && charsout >= 0) {
+ chclass = find_char_class(ch); /* find character class */
+ state = find_next_state(chclass, state); /* find next state */
+
+ /* execute code for each state */
+ switch (state) {
+
+ case ST_NORMAL:
+ /* normal state -- just write character */
+ f->writechar(ch, 1, f, &charsout);
+ break;
+
+ case ST_PERCENT:
+ /* set default value of conversion parameters */
+ prefixlen = fldwidth = no_output = capexp = 0;
+ flags = 0;
+ precision = -1;
+ fwide = 0;
+ break;
+
+ case ST_FLAG:
+ /* set flag based on which flag character */
+ switch (ch) {
+ case '-':
+ flags |= FL_LEFT; /* '-' => left justify */
+ break;
+ case '+':
+ flags |= FL_SIGN; /* '+' => force sign indicator */
+ break;
+ case ' ':
+ flags |= FL_SIGNSP; /* ' ' => force sign or space */
+ break;
+ case '#':
+ flags |= FL_ALTERNATE; /* '#' => alternate form */
+ break;
+ case '0':
+ flags |= FL_LEADZERO; /* '0' => pad with leading zeros */
+ break;
+ }
+ break;
+
+ case ST_WIDTH:
+ /* update width value */
+ if (ch == '*') {
+ /* get width from arg list */
+ fldwidth = get_int_arg(&argptr);
+ if (fldwidth < 0) {
+ /* ANSI says neg fld width means '-' flag and pos width */
+ flags |= FL_LEFT;
+ fldwidth = -fldwidth;
+ }
+ }
+ else {
+ /* add digit to current field width */
+ fldwidth = fldwidth * 10 + (ch - '0');
+ }
+ break;
+
+ case ST_DOT:
+ /* zero the precision, since dot with no number means 0
+ not default, according to ANSI */
+ precision = 0;
+ break;
+
+ case ST_PRECIS:
+ /* update precison value */
+ if (ch == '*') {
+ /* get precision from arg list */
+ precision = get_int_arg(&argptr);
+ if (precision < 0)
+ precision = -1; /* neg precision means default */
+ }
+ else {
+ /* add digit to current precision */
+ precision = precision * 10 + (ch - '0');
+ }
+ break;
+
+ case ST_SIZE:
+ /* just read a size specifier, set the flags based on it */
+ switch (ch) {
+#if !LONG_IS_INT
+ case 'l':
+ flags |= FL_LONG; /* 'l' => long int */
+ break;
+#endif
+
+#if !LONGDOUBLE_IS_DOUBLE
+ case 'L':
+ flags |= FL_LONGDOUBLE; /* 'L' => long double */
+ break;
+#endif
+
+#if !SHORT_IS_INT
+ case 'h':
+ flags |= FL_SHORT; /* 'h' => short int */
+ break;
+#endif
+ case 'w':
+ flags |= FL_WIDE; /* 'w' => wide character */
+ break;
+ }
+ break;
+
+ case ST_TYPE:
+ /* we have finally read the actual type character, so we */
+ /* now format and "print" the output. We use a big switch */
+ /* statement that sets 'text' to point to the text that should */
+ /* be printed, and 'textlen' to the length of this text. */
+ /* Common code later on takes care of justifying it and */
+ /* other miscellaneous chores. Note that cases share code, */
+ /* in particular, all integer formatting is doen in one place. */
+ /* Look at those funky goto statements! */
+
+ switch (ch) {
+
+ case 'c': {
+ /* print a single character specified by int argument */
+ wc = (wchar_t) get_int_arg(&argptr); /* get char to print */
+ * (wchar_t FAR *) buffer = wc;
+ text = buffer;
+ textlen = 1; /* print just a single character */
+ }
+ break;
+
+ case 'S': {
+ /* print a Counted String
+
+ int i;
+ char FAR *p; /* temps */
+ struct string {
+ short Length;
+ short MaximumLength;
+ char FAR *Buffer;
+ } *pstr;
+
+ pstr = get_ptr_arg(&argptr);
+ if (pstr == NULL || pstr->Buffer == NULL) {
+ /* null ptr passed, use special string */
+ text = nullstring;
+#ifdef FLAT
+ textlen = strlen(text);
+#else
+ textlen = _fstrlen(text);
+#endif
+ flags &= ~FL_WIDE;
+ } else {
+ text = pstr->Buffer;
+ textlen = pstr->Length;
+ }
+
+ }
+ break;
+
+ case 's': {
+ /* print a string -- */
+ /* ANSI rules on how much of string to print: */
+ /* all if precision is default, */
+ /* min(precision, length) if precision given. */
+ /* prints '(null)' if a null string is passed */
+
+ int i;
+ char FAR *p; /* temps */
+
+ text = get_ptr_arg(&argptr);
+ if (text == NULL) {
+ /* null ptr passed, use special string */
+ text = nullstring;
+ flags &= ~FL_WIDE;
+ }
+
+ /* At this point it is tempting to use strlen(), but */
+ /* if a precision is specified, we're not allowed to */
+ /* scan past there, because there might be no null */
+ /* at all. Thus, we must do our own scan. */
+
+ i = (precision == -1) ? INT_MAX : precision;
+
+ /* scan for null upto i characters */
+ if (flags & FL_WIDE) {
+ pwc = (wchar_t FAR *) text;
+ while (i-- && (wc = *pwc) && (wc & 0x00ff)) {
+ ++pwc;
+ if (wc & 0xff00) { // if high byte set,
+ break; // error will be indicated
+ }
+ }
+ textlen = pwc - (wchar_t FAR *) text; /* length of string */
+ } else {
+ p = text;
+ while (i-- && *p) {
+ ++p;
+ }
+ textlen = p - text; /* length of the string */
+ }
+ }
+ break;
+
+ case 'n': {
+ /* write count of characters seen so far into */
+ /* short/int/long thru ptr read from args */
+
+ void FAR *p; /* temp */
+
+ p = get_ptr_arg(&argptr);
+
+ /* store chars out into short/long/int depending on flags */
+#if !LONG_IS_INT
+ if (flags & FL_LONG)
+ *(long FAR *)p = charsout;
+ else
+#endif
+
+#if !SHORT_IS_INT
+ if (flags & FL_SHORT)
+ *(short FAR *)p = (short) charsout;
+ else
+#endif
+ *(int FAR *)p = charsout;
+
+ no_output = 1; /* force no output */
+ }
+ break;
+
+
+#ifndef NOFLOATS
+ case 'E':
+ case 'G':
+ capexp = 1; /* capitalize exponent */
+ ch += 'a' - 'A'; /* convert format char to lower */
+ /* DROP THROUGH */
+ case 'e':
+ case 'f':
+ case 'g': {
+ /* floating point conversion -- we call cfltcvt routines */
+ /* to do the work for us. */
+ flags |= FL_SIGNED; /* floating point is signed conversion */
+ text = buffer; /* put result in buffer */
+ flags &= ~FL_WIDE; /* 8 bit string */
+
+ /* compute the precision value */
+ if (precision < 0)
+ precision = 6; /* default precision: 6 */
+ else if (precision == 0 && ch == 'g')
+ precision = 1; /* ANSI specified */
+
+#if !LONGDOUBLE_IS_DOUBLE
+ /* do the conversion */
+ if (flags & FL_LONGDOUBLE) {
+ _cldcvt(argptr, text, ch, precision, capexp);
+ va_arg(argptr, LONGDOUBLE);
+ }
+ else
+#endif
+ {
+ _cfltcvt(argptr, text, ch, precision, capexp);
+ va_arg(argptr, DOUBLE);
+ }
+
+ /* '#' and precision == 0 means force a decimal point */
+ if ((flags & FL_ALTERNATE) && precision == 0)
+ _forcdecpt(text);
+
+ /* 'g' format means crop zero unless '#' given */
+ if (ch == 'g' && !(flags & FL_ALTERNATE))
+ _cropzeros(text);
+
+ /* check if result was negative, save '-' for later */
+ /* and point to positive part (this is for '0' padding) */
+ if (*text == '-') {
+ flags |= FL_NEGATIVE;
+ ++text;
+ }
+
+ textlen = strlen(text); /* compute length of text */
+ }
+ break;
+#endif // NOFLOATS
+
+ case 'd':
+ case 'i':
+ /* signed decimal output */
+ flags |= FL_SIGNED;
+ radix = 10;
+ goto COMMON_INT;
+
+ case 'u':
+ radix = 10;
+ goto COMMON_INT;
+
+ case 'p':
+ /* write a pointer -- this is like an integer or long */
+ /* except we force precision to pad with zeros and */
+ /* output in big hex. */
+
+ precision = 2 * sizeof(void FAR *); /* number of hex digits needed */
+#if !PTR_IS_INT
+ flags |= FL_LONG; /* assume we're converting a long */
+#endif
+ /* DROP THROUGH to hex formatting */
+
+ case 'C':
+ case 'X':
+ /* unsigned upper hex output */
+ hexadd = 'A' - '9' - 1; /* set hexadd for uppercase hex */
+ goto COMMON_HEX;
+
+ case 'x':
+ /* unsigned lower hex output */
+ hexadd = 'a' - '9' - 1; /* set hexadd for lowercase hex */
+ /* DROP THROUGH TO COMMON_HEX */
+
+ COMMON_HEX:
+ radix = 16;
+ if (flags & FL_ALTERNATE) {
+ /* alternate form means '0x' prefix */
+ prefix[0] = '0';
+ prefix[1] = (char)('x' - 'a' + '9' + 1 + hexadd); /* 'x' or 'X' */
+ prefixlen = 2;
+ }
+ goto COMMON_INT;
+
+ case 'o':
+ /* unsigned octal output */
+ radix = 8;
+ if (flags & FL_ALTERNATE) {
+ /* alternate form means force a leading 0 */
+ flags |= FL_FORCEOCTAL;
+ }
+ /* DROP THROUGH to COMMON_INT */
+
+ COMMON_INT: {
+ /* This is the general integer formatting routine. */
+ /* Basically, we get an argument, make it positive */
+ /* if necessary, and convert it according to the */
+ /* correct radix, setting text and textlen */
+ /* appropriately. */
+
+ unsigned long number; /* number to convert */
+ int digit; /* ascii value of digit */
+ long l; /* temp long value */
+
+ /* 1. read argument into l, sign extend as needed */
+#if !LONG_IS_INT
+ if (flags & FL_LONG)
+ l = get_long_arg(&argptr);
+ else
+#endif
+
+#if !SHORT_IS_INT
+ if (flags & FL_SHORT) {
+ if (flags & FL_SIGNED)
+ l = (short) get_int_arg(&argptr); /* sign extend */
+ else
+ l = (unsigned short) get_int_arg(&argptr); /* zero-extend*/
+ }
+ else
+#endif
+ {
+ if (flags & FL_SIGNED)
+ l = get_int_arg(&argptr); /* sign extend */
+ else
+ l = (unsigned int) get_int_arg(&argptr); /* zero-extend*/
+ }
+
+ /* 2. check for negative; copy into number */
+ if ( (flags & FL_SIGNED) && l < 0) {
+ number = -l;
+ flags |= FL_NEGATIVE; /* remember negative sign */
+ }
+ else {
+ number = l;
+ }
+
+ /* 3. check precision value for default; non-default */
+ /* turns off 0 flag, according to ANSI. */
+ if (precision < 0)
+ precision = 1; /* default precision */
+ else
+ flags &= ~FL_LEADZERO;
+
+ /* 4. Check if data is 0; if so, turn off hex prefix */
+ if (number == 0)
+ prefixlen = 0;
+
+ /* 5. Convert data to ASCII -- note if precision is zero */
+ /* and number is zero, we get no digits at all. */
+
+ text = &buffer[BUFFERSIZE-1]; // last digit at end of buffer
+ flags &= ~FL_WIDE; // 8 bit characters
+
+ while (precision-- > 0 || number != 0) {
+ digit = (int)(number % radix) + '0';
+ number /= radix; /* reduce number */
+ if (digit > '9') {
+ /* a hex digit, make it a letter */
+ digit += hexadd;
+ }
+ *text-- = (char)digit; /* store the digit */
+ }
+
+ textlen = (char FAR *)&buffer[BUFFERSIZE-1] - text; /* compute length of number */
+ ++text; /* text points to first digit now */
+
+
+ /* 6. Force a leading zero if FORCEOCTAL flag set */
+ if ((flags & FL_FORCEOCTAL) && (text[0] != '0' || textlen == 0)) {
+ *--text = '0';
+ ++textlen; /* add a zero */
+ }
+ }
+ break;
+ }
+
+ /* At this point, we have done the specific conversion, and */
+ /* 'text' points to text to print; 'textlen' is length. Now we */
+ /* justify it, put on prefixes, leading zeros, and then */
+ /* print it. */
+
+ if (!no_output) {
+ int padding; /* amount of padding, negative means zero */
+
+ if (flags & FL_SIGNED) {
+ if (flags & FL_NEGATIVE) {
+ /* prefix is a '-' */
+ prefix[0] = '-';
+ prefixlen = 1;
+ }
+ else if (flags & FL_SIGN) {
+ /* prefix is '+' */
+ prefix[0] = '+';
+ prefixlen = 1;
+ }
+ else if (flags & FL_SIGNSP) {
+ /* prefix is ' ' */
+ prefix[0] = ' ';
+ prefixlen = 1;
+ }
+ }
+
+ /* calculate amount of padding -- might be negative, */
+ /* but this will just mean zero */
+ padding = fldwidth - textlen - prefixlen;
+
+ /* put out the padding, prefix, and text, in the correct order */
+
+ if (!(flags & (FL_LEFT | FL_LEADZERO))) {
+ /* pad on left with blanks */
+ f->writechar(' ', padding, f, &charsout);
+ }
+
+ /* write prefix */
+ writestring(prefix, prefixlen, f, &charsout, 0);
+
+ if ((flags & FL_LEADZERO) && !(flags & FL_LEFT)) {
+ /* write leading zeros */
+ f->writechar('0', padding, f, &charsout);
+ }
+
+ /* write text */
+ writestring(text, textlen, f, &charsout, flags & FL_WIDE);
+
+ if (flags & FL_LEFT) {
+ /* pad on right with blanks */
+ f->writechar(' ', padding, f, &charsout);
+ }
+
+ /* we're done! */
+ }
+ break;
+ }
+ }
+
+ return charsout; /* return value = number of characters written */
+}
+
+
+/***
+*int get_int_arg(va_list pargptr)
+*
+*Purpose:
+* Gets an int argument off the given argument list and updates *pargptr.
+*
+*Entry:
+* va_list pargptr - pointer to argument list; updated by function
+*
+*Exit:
+* Returns the integer argument read from the argument list.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+LOCAL(int) get_int_arg(va_list FAR *pargptr)
+{
+ return va_arg(*pargptr, int);
+}
+
+/***
+*long get_long_arg(va_list pargptr)
+*
+*Purpose:
+* Gets an long argument off the given argument list and updates pargptr.
+*
+*Entry:
+* va_list pargptr - pointer to argument list; updated by function
+*
+*Exit:
+* Returns the long argument read from the argument list.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+#if !LONG_IS_INT
+LOCAL(long) get_long_arg(va_list FAR *pargptr)
+{
+ return va_arg(*pargptr, long);
+}
+#endif
+
+
+
+/***
+*void writestring(char *string, int len, struct w4io *f, int *pcchwritten, int fwide)
+*
+*Purpose:
+* Writes a string of the given length to the given file. If no error occurs,
+* then *pcchwritten is incremented by len; otherwise, *pcchwritten is set
+* to -1. If len is negative, it is treated as zero.
+*
+*Entry:
+* char *string - string to write (NOT null-terminated)
+* int len - length of string
+* struct w4io *f - file to write to
+* int *pcchwritten - pointer to integer to update with total chars written
+* int fwide - wide character flag
+*
+*Exit:
+* No return value.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+LOCAL(void) writestring(
+ char FAR *string,
+ int len,
+ struct w4io FAR *f,
+ int FAR *pcchwritten,
+ int fwide)
+{
+ wchar_t FAR *pwc;
+
+ //printf("string: str=%.*s, len=%d, cch=%d, f=%d\n", len, string, len, *pcchwritten, fwide);
+ if (fwide) {
+ pwc = (wchar_t FAR *) string;
+ while (len-- > 0) {
+ if (*pwc & 0xff00) {
+ f->writechar('^', 1, f, pcchwritten);
+ }
+ f->writechar((char) *pwc++, 1, f, pcchwritten);
+ }
+ } else {
+ while (len-- > 0) {
+ f->writechar(*string++, 1, f, pcchwritten);
+ }
+ }
+}
+
+#endif // DBG == 1
diff --git a/private/ole32/olethunk/debnot/printf.h b/private/ole32/olethunk/debnot/printf.h
new file mode 100644
index 000000000..1cba796f9
--- /dev/null
+++ b/private/ole32/olethunk/debnot/printf.h
@@ -0,0 +1,261 @@
+/***
+*printf.h - print formatted
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4*printf() - print formatted data
+* defines w4v*printf() - print formatted output, get data from an
+* argument ptr instead of explicit args.
+*
+*Revision History:
+* 09-02-83 RN original sprintf
+* 06-17-85 TC rewrote to use new varargs macros, and to be vsprintf
+* 04-13-87 JCR added const to declaration
+* 11-07-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-13-88 JCR Fake _iob entry is now static so that other routines
+* can assume _iob entries are in DGROUP.
+* 08-25-88 GJF Define MAXSTR to be INT_MAX (from LIMITS.H).
+* 06-06-89 JCR 386 mthread support
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-16-90 GJF Fixed copyright
+*
+*******************************************************************************/
+
+#include <stdarg.h>
+#include <limits.h>
+#include <windows.h>
+#include "w4io.h"
+
+#if defined(_W4PRINTF_)
+ static long fh;
+// extern long GetStdHandle(long);
+// extern void WriteFile(long fh, char FAR *s, long cch, long FAR * pcchret, long);
+# define _PRINTF_
+#elif defined(_W4DPRINTF_)
+# define _pwritechar _dwritechar
+# define _pflushbuf _dflushbuf
+# define w4printf w4dprintf
+# define w4vprintf w4vdprintf
+# define _PRINTF_
+#elif defined(_W4SPRINTF_)
+# define _pwritechar _swritechar
+# define w4printf w4sprintf
+# define w4vprintf w4vsprintf
+#elif defined(_W4WCSPRINTF_)
+# define _TCHAR_ wchar_t
+# define _PBUF_ pwcbuf
+# define _PSTART_ pwcstart
+# define w4printf w4wcsprintf
+# define w4vprintf w4vwcsprintf
+# define _pwritechar _wwritechar
+#else
+# error configuration problem
+#endif
+
+#ifndef _TCHAR_
+# define _TCHAR_ char
+# define _PBUF_ pchbuf
+# define _PSTART_ pchstart
+#endif
+
+
+#ifdef _PRINTF_
+# ifndef FLAT
+# define OutputDebugStringA OutputDebugString
+# endif
+ int _cdecl _pflushbuf(struct w4io FAR *f);
+# define SPR(a)
+# define MAXSTR 128
+#else
+# define SPR(a) a,
+# define MAXSTR INT_MAX
+#endif
+
+void _cdecl _pwritechar(int ch, int num, struct w4io FAR *f, int FAR *pcchwritten);
+int _cdecl w4vprintf(SPR(_TCHAR_ FAR *string) const char FAR *format, va_list arglist);
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+DWORD FAR PASCAL CallProc32W(DWORD dw1, DWORD dw2, DWORD dw3,
+ LPVOID pfn32, DWORD dwPtrTranslate,
+ DWORD dwArgCount);
+#ifdef __cplusplus
+}
+#endif
+LPVOID lpThkCallOutputFunctionsProc;
+
+
+/***
+*int w4printf(format, ...) - print formatted data
+*
+*Purpose:
+* Prints formatted data using the format string to
+* format data and getting as many arguments as called for
+* Sets up a w4io so file i/o operations can be used.
+* w4iooutput does the real work here
+*
+*Entry:
+* char *format - format string to control data format/number
+* of arguments followed by list of arguments, number and type
+* controlled by format string
+*
+*Exit:
+* returns number of characters written
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+int _cdecl
+w4printf(SPR(_TCHAR_ FAR *string) const char FAR *format, ...)
+/*
+ * 'PRINT', 'F'ormatted
+ */
+{
+ va_list arglist;
+
+ va_start(arglist, format);
+ return(w4vprintf(SPR(string) format, arglist));
+}
+
+
+/***
+*int w4vprintf(format, arglist) - print formatted data from arg ptr
+*
+*Purpose:
+* Prints formatted data, but gets data from an argument pointer.
+* Sets up a w4io so file i/o operations can be used, make string look
+* like a huge buffer to it, but _flsbuf will refuse to flush it if it
+* fills up. Appends '\0' to make it a true string.
+*
+* Multi-thread: (1) Since there is no stream, this routine must never try
+* to get the stream lock (i.e., there is no stream lock either). (2)
+* Also, since there is only one staticly allocated 'fake' iob, we must
+* lock/unlock to prevent collisions.
+*
+*Entry:
+* char *format - format string, describes format of data
+* va_list arglist - varargs argument pointer
+*
+*Exit:
+* returns number of characters written
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _cdecl
+w4vprintf(SPR(_TCHAR_ FAR *string) const char FAR *format, va_list arglist)
+/*
+ * 'V'ariable argument 'PRINT', 'F'ormatted
+ */
+{
+ struct w4io outfile;
+ register int retval;
+#ifdef _PRINTF_
+ char string[MAXSTR + 1]; // leave room for null termination
+#else
+ int dummy;
+#endif
+
+#ifdef _W4PRINTF_
+ long ldummy;
+
+ if (fh == 0 || fh == -1)
+ {
+ ldummy = -11; // C7 bug workaround
+ if ((fh = (long)GetStdHandle(ldummy)) == 0 || fh == -1)
+ {
+ OutputDebugStringA("GetStdHandle in " __FILE__ " failed\n");
+ return(-1);
+ }
+ }
+#endif
+
+ outfile._PBUF_ = outfile._PSTART_ = string;
+ outfile.cchleft = MAXSTR;
+ outfile.writechar = _pwritechar;
+
+ retval = w4iooutput(&outfile, format, arglist);
+
+#ifdef _PRINTF_
+ if (_pflushbuf(&outfile) == -1) {
+ return(-1);
+ }
+#else
+ _pwritechar('\0', 1, &outfile, &dummy);
+#endif
+ return(retval);
+}
+
+
+void _cdecl _pwritechar(int ch, int num, struct w4io FAR *f, int FAR *pcchwritten)
+{
+ //printf(" char: ch=%c, cnt=%d, cch=%d\n", ch, num, *pcchwritten);
+ while (num-- > 0) {
+#ifdef _PRINTF_
+ if (f->cchleft < 2 && _pflushbuf(f) == -1) {
+ *pcchwritten = -1;
+ return;
+ }
+#endif
+#ifdef _W4DPRINTF_
+# ifndef FLAT
+ if (ch == '\n')
+ {
+ *f->_PBUF_++ = '\r';
+ f->cchleft--;
+ (*pcchwritten)++;
+ }
+# endif
+#endif
+ *f->_PBUF_++ = (char) ch;
+ f->cchleft--;
+ (*pcchwritten)++;
+ }
+}
+
+
+#ifdef _PRINTF_
+int _cdecl _pflushbuf(struct w4io FAR *f)
+{
+ int cch;
+
+ if (cch = (f->pchbuf - f->pchstart))
+ {
+#ifdef _W4DPRINTF_
+ *f->pchbuf = '\0'; // null terminate
+ if (lpThkCallOutputFunctionsProc == NULL)
+ {
+ OutputDebugStringA(f->pchstart);
+ }
+ else
+ {
+ // note casting and dummy arguments to match other uses of it (see interop.hxx)
+ CallProc32W((DWORD) f->pchstart, 0, 0, lpThkCallOutputFunctionsProc, 0x00000004, 3); // thunk it to olethk32.dll
+ }
+#else
+ long cchret;
+
+ //*f->pchbuf = '\0'; // null terminate
+ //printf("%d chars: \"%s\"\n", cch, f->pchstart);
+ WriteFile((HANDLE)fh, f->pchstart, cch, &cchret, 0);
+ if (cch != cchret)
+ {
+ OutputDebugString("WriteFile in " __FILE__ " failed\n");
+ return(-1);
+ }
+#endif
+ f->pchbuf -= cch; // reset pointer
+ f->cchleft += cch; // reset count
+ }
+ return(0);
+}
+#endif // _PRINTF_
diff --git a/private/ole32/olethunk/debnot/sprintf.c b/private/ole32/olethunk/debnot/sprintf.c
new file mode 100644
index 000000000..c4d9dfcdf
--- /dev/null
+++ b/private/ole32/olethunk/debnot/sprintf.c
@@ -0,0 +1,17 @@
+/***
+*sprintf.c - print formatted to string
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4sprintf() - print formatted data to string
+* defines w4vsprintf() - print formatted output to a string, get data
+* from an argument ptr instead of explicit args.
+*******************************************************************************/
+
+#if DBG == 1
+
+#define _W4SPRINTF_
+#include "printf.h"
+
+#endif
diff --git a/private/ole32/olethunk/debnot/w4io.h b/private/ole32/olethunk/debnot/w4io.h
new file mode 100644
index 000000000..22d280084
--- /dev/null
+++ b/private/ole32/olethunk/debnot/w4io.h
@@ -0,0 +1,59 @@
+/***
+*w4io.h - fake FILE structure for Win 4 printf/sprintf/debug printf support
+*
+*/
+
+#if defined(M_I386) || defined(FLAT)
+#ifndef FAR
+#define FAR
+#endif
+# ifndef FLAT
+# define FLAT
+# endif
+#else
+#ifndef FAR
+#define FAR __far
+#endif
+#endif
+
+#ifndef NULL
+# define NULL 0
+#endif
+
+#ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+struct w4io
+{
+ union
+ {
+ struct
+ {
+ wchar_t FAR *_pwcbuf; // wchar_t output buffer
+ wchar_t FAR *_pwcstart;
+ } wc;
+ struct
+ {
+ char FAR *_pchbuf; // char output buffer
+ char FAR *_pchstart;
+ } ch;
+ } buf ;
+ unsigned int cchleft; // output buffer character count
+ void (_cdecl *writechar)(int ch,
+ int num,
+ struct w4io FAR *f,
+ int FAR *pcchwritten);
+};
+
+#define pwcbuf buf.wc._pwcbuf
+#define pwcstart buf.wc._pwcstart
+#define pchbuf buf.ch._pchbuf
+#define pchstart buf.ch._pchstart
+
+#define REG1 register
+#define REG2 register
+
+/* prototypes */
+int _cdecl w4iooutput(struct w4io FAR *stream, const char FAR *format, va_list argptr);
diff --git a/private/ole32/olethunk/debnot/win16.mk b/private/ole32/olethunk/debnot/win16.mk
new file mode 100644
index 000000000..a8859c50b
--- /dev/null
+++ b/private/ole32/olethunk/debnot/win16.mk
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 1991, Microsoft Corporation
+#
+# History:
+#
+# 18-Feb-1994 BobDay Adapted from MVDM\WOW16\GDI\MAKEFILE
+#
+
+TARGET = debnot.lib
+
+CFILES = \
+ .\output.c\
+ .\dprintf.c\
+ .\sprintf.c
+
+CXXFILES = \
+ .\assert.cxx
+
+!include ..\ole16\makefile.inc
+
+$(OBJDIR)\output.obj: output.c
+$(OBJDIR)\dprintf.obj: dprintf.c
+$(OBJDIR)\sprintf.obj: sprintf.c
+$(OBJDIR)\assert.obj: assert.cxx
diff --git a/private/ole32/olethunk/debnot/win32/makefile b/private/ole32/olethunk/debnot/win32/makefile
new file mode 100644
index 000000000..734e18727
--- /dev/null
+++ b/private/ole32/olethunk/debnot/win32/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the subcomponents of NTOS.
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/olethunk/debnot/win32/sources b/private/ole32/olethunk/debnot/win32/sources
new file mode 100644
index 000000000..c88938dfa
--- /dev/null
+++ b/private/ole32/olethunk/debnot/win32/sources
@@ -0,0 +1,45 @@
+!IF 0
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ Standard definitions file for debnot.lib
+
+Author:
+
+ Drew Bliss (drewb) 23-Feb-1994
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=cairole
+MINORCOMP=interop
+
+TARGETNAME=debnot
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+INCLUDES=..; \
+ $(BASEDIR)\public\sdk\inc;
+
+C_DEFINES=$(C_DEFINES) \
+ -DFLAT \
+ -DWIN32=100 \
+ -D_NT1X_=100 \
+ -DUNICODE \
+ -D_UNICODE
+
+USE_CRTDLL=1
+BLDCRT=1
+
+SOURCES=\
+ ..\assert.cxx \
+ ..\output.c \
+ ..\dprintf.c \
+ ..\sprintf.c
diff --git a/private/ole32/olethunk/dirs b/private/ole32/olethunk/dirs
new file mode 100644
index 000000000..203c047f6
--- /dev/null
+++ b/private/ole32/olethunk/dirs
@@ -0,0 +1,41 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ ?
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=debnot \
+ olethk32 \
+ ole16
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+#
+# Note that is currently omitted because there is no difference
+# from the daytona binary.
+OPTIONAL_DIRS= \
+ daytona
diff --git a/private/ole32/olethunk/h/apilist.hxx b/private/ole32/olethunk/h/apilist.hxx
new file mode 100644
index 000000000..9e5fd1cfc
--- /dev/null
+++ b/private/ole32/olethunk/h/apilist.hxx
@@ -0,0 +1,118 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: apilist.hxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#define THK_API_CoInitialize 0
+#define THK_API_CoUninitialize 1
+#define THK_API_CoGetClassObject 2
+#define THK_API_CoRegisterClassObject 3
+#define THK_API_CoRevokeClassObject 4
+#define THK_API_CoMarshalInterface 5
+#define THK_API_CoUnmarshalInterface 6
+#define THK_API_CoReleaseMarshalData 7
+#define THK_API_CoDisconnectObject 8
+#define THK_API_CoLockObjectExternal 9
+#define THK_API_CoGetStandardMarshal 10
+#define THK_API_CoIsHandlerConnected 11
+#define THK_API_CoFreeAllLibraries 12
+#define THK_API_CoFreeUnusedLibraries 13
+#define THK_API_CoCreateInstance 14
+#define THK_API_CLSIDFromString 15
+#define THK_API_CoIsOle1Class 16
+#define THK_API_ProgIDFromCLSID 17
+#define THK_API_CLSIDFromProgID 18
+#define THK_API_CoCreateGuid 19
+#define THK_API_CoFileTimeToDosDateTime 20
+#define THK_API_CoDosDateTimeToFileTime 21
+#define THK_API_CoFileTimeNow 22
+#define THK_API_CoRegisterMessageFilter 23
+#define THK_API_CoGetTreatAsClass 24
+#define THK_API_CoTreatAsClass 25
+#define THK_API_DllGetClassObject 26
+#define THK_API_StgCreateDocfile 27
+#define THK_API_StgCreateDocfileOnILockBytes 28
+#define THK_API_StgOpenStorage 29
+#define THK_API_StgOpenStorageOnILockBytes 30
+#define THK_API_StgIsStorageFile 31
+#define THK_API_StgIsStorageILockBytes 32
+#define THK_API_StgSetTimes 33
+#define THK_API_CreateDataAdviseHolder 34
+#define THK_API_CreateDataCache 35
+#define THK_API_BindMoniker 36
+#define THK_API_MkParseDisplayName 37
+#define THK_API_MonikerRelativePathTo 38
+#define THK_API_MonikerCommonPrefixWith 39
+#define THK_API_CreateBindCtx 40
+#define THK_API_CreateGenericComposite 41
+#define THK_API_GetClassFile 42
+#define THK_API_CreateFileMoniker 43
+#define THK_API_CreateItemMoniker 44
+#define THK_API_CreateAntiMoniker 45
+#define THK_API_CreatePointerMoniker 46
+#define THK_API_GetRunningObjectTable 47
+#define THK_API_ReadClassStg 48
+#define THK_API_WriteClassStg 49
+#define THK_API_ReadClassStm 50
+#define THK_API_WriteClassStm 51
+#define THK_API_WriteFmtUserTypeStg 52
+#define THK_API_ReadFmtUserTypeStg 53
+#define THK_API_OleInitialize 54
+#define THK_API_OleUninitialize 55
+#define THK_API_OleQueryLinkFromData 56
+#define THK_API_OleQueryCreateFromData 57
+#define THK_API_OleCreate 58
+#define THK_API_OleCreateFromData 59
+#define THK_API_OleCreateLinkFromData 60
+#define THK_API_OleCreateStaticFromData 61
+#define THK_API_OleCreateLink 62
+#define THK_API_OleCreateLinkToFile 63
+#define THK_API_OleCreateFromFile 64
+#define THK_API_OleLoad 65
+#define THK_API_OleSave 66
+#define THK_API_OleLoadFromStream 67
+#define THK_API_OleSaveToStream 68
+#define THK_API_OleSetContainedObject 69
+#define THK_API_OleNoteObjectVisible 70
+#define THK_API_RegisterDragDrop 71
+#define THK_API_RevokeDragDrop 72
+#define THK_API_DoDragDrop 73
+#define THK_API_OleSetClipboard 74
+#define THK_API_OleGetClipboard 75
+#define THK_API_OleFlushClipboard 76
+#define THK_API_OleIsCurrentClipboard 77
+#define THK_API_OleCreateMenuDescriptor 78
+#define THK_API_OleSetMenuDescriptor 79
+#define THK_API_OleDestroyMenuDescriptor 80
+#define THK_API_OleDraw 81
+#define THK_API_OleRun 82
+#define THK_API_OleIsRunning 83
+#define THK_API_OleLockRunning 84
+#define THK_API_CreateOleAdviseHolder 85
+#define THK_API_OleCreateDefaultHandler 86
+#define THK_API_OleCreateEmbeddingHelper 87
+#define THK_API_OleRegGetUserType 88
+#define THK_API_OleRegGetMiscStatus 89
+#define THK_API_OleRegEnumFormatEtc 90
+#define THK_API_OleRegEnumVerbs 91
+#define THK_API_OleConvertIStorageToOLESTREAM 92
+#define THK_API_OleConvertOLESTREAMToIStorage 93
+#define THK_API_OleConvertIStorageToOLESTREAMEx 94
+#define THK_API_OleConvertOLESTREAMToIStorageEx 95
+#define THK_API_OleDoAutoConvert 96
+#define THK_API_OleGetAutoConvert 97
+#define THK_API_OleSetAutoConvert 98
+#define THK_API_GetConvertStg 99
+#define THK_API_SetConvertStg 100
+#define THK_API_ReadOleStg 101
+#define THK_API_WriteOleStg 102
+#define THK_API_COUNT 103
diff --git a/private/ole32/olethunk/h/call32.hxx b/private/ole32/olethunk/h/call32.hxx
new file mode 100644
index 000000000..edd8ca8d1
--- /dev/null
+++ b/private/ole32/olethunk/h/call32.hxx
@@ -0,0 +1,34 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: call32.hxx
+//
+// Contents: 16->32 call helpers
+//
+// History: 18-Feb-94 DrewB Created
+// 15-Mar-95 AlexGo Added AddAppCompatFlag
+//
+//----------------------------------------------------------------------------
+
+#ifndef __CALL32_HXX__
+#define __CALL32_HXX__
+
+extern LPVOID lpIUnknownObj32; // Address of IUnknown methods on 32-bits
+
+STDAPI_(BOOL) Call32Initialize(void);
+STDAPI_(void) Call32Uninitialize(void);
+
+STDAPI CallThkMgrInitialize(void);
+STDAPI_(void) CallThkMgrUninitialize(void);
+
+STDAPI_(DWORD) CallObjectInWOW(DWORD dwMethod, LPVOID pvStack);
+STDAPI_(DWORD) CallObjectInWOWCheckInit(DWORD dwMethod, LPVOID pvStack);
+STDAPI_(DWORD) CallObjectInWOWCheckThkMgr(DWORD dwMethod, LPVOID pvStack);
+
+STDAPI_(DWORD) LoadLibraryInWOW(LPCSTR pszLibName, DWORD dwFlags);
+STDAPI_(LPVOID) GetProcAddressInWOW(DWORD hModule, LPCSTR pszProcName);
+STDAPI_(void) AddAppCompatFlag( DWORD dwFlag );
+
+#endif // #ifndef __CALL32_HXX__
diff --git a/private/ole32/olethunk/h/interop.hxx b/private/ole32/olethunk/h/interop.hxx
new file mode 100644
index 000000000..00bff5df0
--- /dev/null
+++ b/private/ole32/olethunk/h/interop.hxx
@@ -0,0 +1,266 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: interop.hxx
+//
+// Contents: Common definitions for the interop project
+//
+// History: 18-Feb-94 DrewB Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __INTEROP_HXX__
+#define __INTEROP_HXX__
+
+//+---------------------------------------------------------------------------
+//
+// Purpose: Standard debugging support
+//
+// History: 18-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <debnot.h>
+
+//
+// The rest of the OACF flags are defined in thunkapi.hxx. This one is here
+// because it is shared between ole2.dll and olethk32.dll. The 16-bit binaries
+// do not include thunkapi.hxx at the moment. KevinRo promises to fix this someday
+// Feel free to fix this if you wish.
+//
+
+#define OACF_CORELTRASHMEM 0x10000000 // CorelDraw relies on the fact that
+ // OLE16 trashed memory during paste-
+ // link. Therefore, we'll go ahead
+ // and trash it for them if this
+ // flag is on.
+
+#if DBG == 1
+#ifdef WIN32
+DECLARE_DEBUG(thk);
+#else
+DECLARE_DEBUG(thk1);
+#endif
+
+#define DEB_DLL 0x0008
+#define DEB_THOPS DEB_USER1
+#define DEB_INVOKES DEB_USER2
+#define DEB_ARGS DEB_USER3
+#define DEB_NESTING DEB_USER4
+#define DEB_CALLTRACE DEB_USER5
+#define DEB_THUNKMGR DEB_USER6
+#define DEB_MEMORY DEB_USER7
+#define DEB_TLSTHK DEB_USER8
+#define DEB_UNKNOWN DEB_USER9
+#define DEB_FAILURES DEB_USER10
+#define DEB_DLLS16 DEB_USER11
+#define DEB_APIS16 DEB_USER12 // api calls to 16 bit entry point
+#endif
+
+#if DBG == 1
+
+#ifdef WIN32
+#define thkDebugOut(x) thkInlineDebugOut x
+#else
+#define thkDebugOut(x) thk1InlineDebugOut x
+#endif
+
+#define thkAssert(e) Win4Assert(e)
+#define thkVerify(e) Win4Assert(e)
+
+#else
+
+#define thkDebugOut(x)
+#define thkAssert(e)
+#define thkVerify(e) (e)
+
+#endif
+
+#define OLETHUNK_DLL16NOTFOUND 0x88880002
+
+//+---------------------------------------------------------------------------
+//
+// Purpose: Declarations and definitions shared across everything
+//
+// History: 18-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+// An IID pointer or an index into the list of known interfaces
+// If the high word is zero, it's an index, otherwise it's a pointer
+typedef DWORD IIDIDX;
+
+#define IIDIDX_IS_INDEX(ii) (HIWORD(ii) == 0)
+#define IIDIDX_IS_IID(ii) (!IIDIDX_IS_INDEX(ii))
+
+#define IIDIDX_INVALID ((IIDIDX)0xffff)
+#define INDEX_IIDIDX(idx) ((IIDIDX)(idx))
+#define IID_IIDIDX(piid) ((IIDIDX)(piid))
+#define IIDIDX_INDEX(ii) ((int)(ii))
+#define IIDIDX_IID(ii) ((IID const *)(ii))
+
+// Methods are treated as if they all existed on a single interface
+// Their method numbers are biased to distinguish them from real methods
+#define THK_API_BASE 0xf0000000
+#define THK_API_METHOD(method) (THK_API_BASE+(method))
+
+// Standard method indices in the vtable
+#define SMI_QUERYINTERFACE 0
+#define SMI_ADDREF 1
+#define SMI_RELEASE 2
+#define SMI_COUNT 3
+
+#ifndef WIN32
+#define UNALIGNED
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Struct: CALLDATA
+//
+// Purpose: Data describing a 16-bit call to be made on behalf of
+// the 32-bit code, used since Callback16 can only pass
+// one parameter
+//
+// History: 18-Feb-94 JohannP Created
+//
+//----------------------------------------------------------------------------
+
+typedef struct tagCallData
+{
+ DWORD vpfn;
+ DWORD vpvStack16;
+ DWORD cbStack;
+} CALLDATA;
+
+typedef CALLDATA UNALIGNED FAR *LPCALLDATA;
+
+//+---------------------------------------------------------------------------
+//
+// Struct: DATA16
+//
+// Purpose: Data describing things in the 16-bit world that need to be
+// known to the 32-bit world.
+//
+// History: 3-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+typedef struct tagDATA16
+{
+ DWORD atfnProxy1632Vtbl;
+ DWORD fnCallbackHandler;
+ DWORD fnTaskAlloc;
+ DWORD fnTaskFree;
+ DWORD fnLoadProcDll;
+ DWORD fnUnloadProcDll;
+ DWORD fnCallGetClassObject;
+ DWORD fnCallCanUnloadNow;
+ DWORD fnQueryInterface16;
+ DWORD fnAddRef16;
+ DWORD fnRelease16;
+ DWORD fnReleaseStgMedium16;
+ DWORD avpfnSm16ReleaseHandlerVtbl;
+ DWORD fnTouchPointer16;
+ DWORD fnStgMediumStreamHandler16;
+ DWORD fnCallStub16;
+ DWORD fnSetOwnerPublic16;
+ DWORD fnWinExec16;
+} DATA16;
+typedef DATA16 UNALIGNED FAR * LPDATA16;
+//+---------------------------------------------------------------------------
+//
+// Struct: LOADPROCDLLSTRUCT
+//
+// Purpose: Data passed to the LoadProcDll function that is called from
+// the 32-bit function of similar name.
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+typedef struct tagLOADPROCDLLSTRUCT
+{
+ DWORD vpDllName;
+ DWORD vpfnGetClassObject;
+ DWORD vpfnCanUnloadNow;
+ DWORD vhmodule;
+} LOADPROCDLLSTRUCT;
+typedef LOADPROCDLLSTRUCT UNALIGNED FAR * LPLOADPROCDLLSTRUCT;
+
+//+---------------------------------------------------------------------------
+//
+// Struct: CALLGETCLASSOBJECTSTRUCT
+//
+// Purpose: Data passed to the CallGetClassObject function that is called
+// from the 32-bit function of similar name.
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+typedef struct tagCALLGETCLASSOBJECTSTRUCT
+{
+ DWORD vpfnGetClassObject;
+ CLSID clsid;
+ IID iid;
+ DWORD iface;
+} CALLGETCLASSOBJECTSTRUCT;
+typedef CALLGETCLASSOBJECTSTRUCT UNALIGNED FAR * LPCALLGETCLASSOBJECTSTRUCT;
+
+//+---------------------------------------------------------------------------
+//
+// Struct: WINEXEC16STRUCT
+//
+// Purpose: Data passed to the WinExec16 function that is called from
+// the 32-bit function of similar name.
+//
+// History: 27-Jul-94 AlexT Created
+//
+//----------------------------------------------------------------------------
+
+typedef struct tagWINEXEC16STRUCT
+{
+ DWORD vpCommandLine;
+ unsigned short vusShow;
+} WINEXEC16STRUCT;
+typedef WINEXEC16STRUCT UNALIGNED FAR * LPWINEXEC16STRUCT;
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSm16ReleaseHandler (srh)
+//
+// Purpose: Provides punkForRelease for 32->16 STGMEDIUM conversion
+//
+// Interface: IUnknown
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef __cplusplus
+
+class CSm16ReleaseHandler
+{
+public:
+ void Init(IUnknown *pUnk,
+ STGMEDIUM *psm32,
+ STGMEDIUM UNALIGNED *psm16,
+ DWORD vpvProxyForRelease,
+ CLIPFORMAT cfFormat);
+ void Uninit(void);
+
+ DWORD _avpfnVtbl;
+ STGMEDIUM _sm32;
+ STGMEDIUM _sm16;
+ DWORD _vpvUnkForRelease;
+ LONG _cReferences;
+ CLIPFORMAT _cfFormat;
+ IUnknown *_pUnkThkMgr;
+};
+
+#endif
+
+#endif // __INTEROP_HXX__
diff --git a/private/ole32/olethunk/h/io16.h b/private/ole32/olethunk/h/io16.h
new file mode 100644
index 000000000..9e09dcdf0
--- /dev/null
+++ b/private/ole32/olethunk/h/io16.h
@@ -0,0 +1,25 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: io16.h
+//
+// Contents: 16-bit generic include
+//
+// History: 18-Feb-94 DrewB Created
+// 07-Mar-94 BobDay Pre-adjusted STACK_PTR, prepared for
+// removal of other macros
+//
+//----------------------------------------------------------------------------
+
+#ifndef __IO16_H__
+#define __IO16_H__
+
+// Get a pointer to a _pascal stack via an argument
+#define PASCAL_STACK_PTR(v) ((LPVOID)((DWORD)&(v)+sizeof(v)))
+
+// Get a pointer to a _cdecl stack via an argument
+#define CDECL_STACK_PTR(v) ((LPVOID)(&(v)))
+
+#endif // #ifndef __IO16_H__
diff --git a/private/ole32/olethunk/h/obj16.hxx b/private/ole32/olethunk/h/obj16.hxx
new file mode 100644
index 000000000..6087727e7
--- /dev/null
+++ b/private/ole32/olethunk/h/obj16.hxx
@@ -0,0 +1,151 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: obj16.hxx
+//
+// Contents: 16->32 object definition header
+//
+// History: 23-Mar-94 JohannP Created
+// 22-May-94 BobDay Split thkmgr.hxx into a mode
+// independent file
+//
+// WARNING: THIS HEADER FILE IS INCLUDED IN BOTH 16-bit CODE and 32-bit CODE
+// ANY DECLARATIONS SHOULD BE MODE NEUTRAL.
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OBJ16_HXX__
+#define __OBJ16_HXX__
+
+//+---------------------------------------------------------------------------
+//
+// Structure: PROXYPTR (pprx)
+//
+// Purpose: A 16:16 or 32-bit pointer to a proxy
+//
+// History: 15-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#define PPRX_16 0
+#define PPRX_32 1
+
+struct PROXYPTR
+{
+ PROXYPTR(void)
+ {
+ };
+
+ PROXYPTR(DWORD dwVal, WORD wTy)
+ {
+ dwPtrVal = dwVal;
+ wType = wTy;
+ };
+
+ DWORD dwPtrVal;
+ WORD wType;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Structure: PROXYHOLDER (ph)
+//
+// Purpose: Provides object identity for multiple proxies
+//
+// History: 07-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CProxy;
+
+// Proxy holder flags
+#define PH_NONAGGREGATE 0x00000000
+#define PH_AGGREGATE 0x00000001
+#define PH_AGGREGATE_RELEASE 0x00000002
+
+typedef struct tagPROXYHOLDER
+{
+ LONG cProxies;
+ DWORD dwFlags;
+ PROXYPTR pprxProxies;
+
+ struct tagPROXYHOLDER FAR *pphNext;
+} PROXYHOLDER;
+
+//+---------------------------------------------------------------------------
+//
+// Class: CProxy (prx)
+//
+// Purpose: Common proxy data
+//
+// History: 07-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+// Define some signatures for doing proxy memory validation
+
+#define PSIG1632 0x32333631 // '1632'
+#define PSIG1632DEAD 0x20203631 // '16 '
+#define PSIG1632TEMP 0x31333631 // '1631'
+#define PSIG3216 0x36313233 // '3216'
+#define PSIG3216DEAD 0x20203233 // '32 '
+#endif
+
+#define PROXYFLAG_NORMAL 0x0000
+#define PROXYFLAG_LOCKED 0x0001
+#define PROXYFLAG_TEMPORARY 0x0002
+#define PROXYFLAG_CLEANEDUP 0x0004
+
+#define PROXYFLAG_PUNKOUTER 0x0010
+#define PROXYFLAG_PUNK 0x0020
+#define PROXYFLAG_PUNKRELEASED 0x0040
+
+class CProxy
+{
+public:
+ // Vtable pointer
+ DWORD pfnVtbl;
+
+ // References passed on to the real object
+ LONG cRef;
+ // Proxy ref count
+ LONG cRefLocal;
+
+ // Interface being proxied
+ // Currently the iidx here is always an index
+ IIDIDX iidx;
+
+ // Object that this proxy is part of
+ PROXYHOLDER FAR *pphHolder;
+ // Sibling proxy pointer within an object
+ PROXYPTR pprxObject;
+
+ // Flags, combines with word in PROXYPTR for alignment
+ WORD grfFlags;
+
+#if DBG == 1
+ DWORD dwSignature;
+#endif
+};
+
+// 16->32 proxy
+class CProxy1632 : public CProxy
+{
+public:
+ LPUNKNOWN punkThis32;
+};
+
+// 32->16 proxy
+class CProxy3216 : public CProxy
+{
+public:
+ DWORD vpvThis16;
+};
+
+typedef CProxy1632 THUNK1632OBJ;
+typedef CProxy3216 THUNK3216OBJ;
+
+#endif // #ifndef __OBJ16_HXX__
diff --git a/private/ole32/olethunk/h/stksw.hxx b/private/ole32/olethunk/h/stksw.hxx
new file mode 100644
index 000000000..9ac726bf1
--- /dev/null
+++ b/private/ole32/olethunk/h/stksw.hxx
@@ -0,0 +1,59 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: stksw.hxx
+//
+// Contents: 32-bit private function declarations
+//
+// History: 5-Dec-94 JohannP Created
+//
+//----------------------------------------------------------------------------
+#ifndef _STKSW_
+#define _STKSW_
+
+#ifdef _CHICAGO_
+DWORD WINAPI SSCallback16(DWORD vpfn16, DWORD dwParam);
+BOOL WINAPI SSCallback16Ex(
+ DWORD vpfn16,
+ DWORD dwFlags,
+ DWORD cbArgs,
+ PVOID pArgs,
+ PDWORD pdwRetCode
+ );
+
+#define CallbackTo16(a,b) SSCallback16(a,b)
+#define CallbackTo16Ex(a,b,c,d,e) SSCallback16Ex(a,b,c,d,e)
+
+STDAPI_(DWORD) SSAPI(InvokeOn32)(DWORD dw1, DWORD dwMethod, LPVOID pvStack16);
+
+#undef SSONBIGSTACK
+#undef SSONSMALLSTACK
+
+#if DBG==1
+
+extern BOOL fSSOn;
+#define SSONBIGSTACK() (fSSOn && SSOnBigStack())
+#define SSONSMALLSTACK() (fSSOn && !SSOnBigStack())
+
+#else
+
+#define SSONBIGSTACK() (SSOnBigStack())
+#define SSONSMALLSTACK() (!SSOnBigStack())
+
+#endif
+
+
+#else
+
+#define CallbackTo16(a,b) WOWCallback16(a,b)
+#define CallbackTo16Ex(a,b,c,d,e) WOWCallback16Ex(a,b,c,d,e)
+#define SSONBIGSTACK() (SSOnBigStack())
+#define SSONSMALLSTACK() (!SSOnBigStack())
+
+#endif // _CHICAGO
+
+#endif // _STKSW_
+
+
diff --git a/private/ole32/olethunk/h/wow16fn.h b/private/ole32/olethunk/h/wow16fn.h
new file mode 100644
index 000000000..4ee9f58d1
--- /dev/null
+++ b/private/ole32/olethunk/h/wow16fn.h
@@ -0,0 +1,62 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: wow16fn.h
+//
+// Contents: WOW 16-bit private function declarations
+//
+// History: 18-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __WOW16FN_H__
+#define __WOW16FN_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+DWORD FAR PASCAL LoadLibraryEx32W(LPCSTR pszDll, DWORD reserved,
+ DWORD dwFlags);
+BOOL FAR PASCAL FreeLibrary32W(DWORD hLibrary);
+LPVOID FAR PASCAL GetProcAddress32W(DWORD hMod, LPCSTR pszProc);
+DWORD FAR PASCAL GetVDMPointer32W(LPVOID pv, UINT cb);
+
+/* This API actually takes a variable number of user arguments before
+ the three required arguments. We only need three user arguments at
+ most so that's the way we declare it.
+ When using this call, dwArgCount must always be three.
+ Use CP32_NARGS to track changes*/
+
+#define CP32_NARGS 3
+DWORD FAR PASCAL CallProc32W(DWORD dw1, DWORD dw2, DWORD dw3,
+ LPVOID pfn32, DWORD dwPtrTranslate,
+ DWORD dwArgCount);
+
+#ifdef _CHICAGO_
+
+DWORD FAR PASCAL SSCallProc32(DWORD dw1, DWORD dw2, DWORD dw3,
+ LPVOID pfn32, DWORD dwPtrTranslate,
+ DWORD dwArgCount);
+
+#ifdef _STACKSWITCHON16_
+#define CallProcIn32(a,b,c,d,e,f) SSCallProc32(a,b,c,d,e,f)
+#else
+#define CallProcIn32(a,b,c,d,e,f) CallProc32W(a,b,c,d,e,f)
+#endif // _STACKSWITCHON16_
+
+#else
+
+#define CallProcIn32(a,b,c,d,e,f) CallProc32W(a,b,c,d,e,f)
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef __WOW16FN_H__
diff --git a/private/ole32/olethunk/h/wow32fn.h b/private/ole32/olethunk/h/wow32fn.h
new file mode 100644
index 000000000..287ca8f2f
--- /dev/null
+++ b/private/ole32/olethunk/h/wow32fn.h
@@ -0,0 +1,92 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: wow32fn.h
+//
+// Contents: WOW 32-bit private function declarations
+//
+// History: 18-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __WOW32FN_H__
+#define __WOW32FN_H__
+
+//
+// WOW types
+//
+
+// 'V'DM pointers
+typedef DWORD VPVOID;
+typedef DWORD VPSTR;
+
+typedef HANDLE HAND32;
+typedef WORD HAND16;
+
+typedef HAND16 HMEM16;
+typedef HAND16 HWND16;
+typedef HAND16 HDC16;
+typedef HAND16 HRGN16;
+typedef HAND16 HMENU16;
+typedef HAND16 HICON16;
+typedef HAND16 HBITMAP16;
+typedef HAND16 HACCEL16;
+typedef HAND16 HTASK16;
+typedef HAND16 HMETAFILE16;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+// Macros to handle conversion of 16:16 pointers to 0:32 pointers
+// On NT this mapping is guaranteed to stay stable in a WOW process
+// as long as a 32->16 transition doesn't occur
+//
+// On Chicago 32-bit code can be preempted at any time so selectors
+// must be fixed to protect them from being remapped
+
+#if defined(_CHICAGO_)
+
+#define WOWFIXVDMPTR(vp, cb) WOWGetVDMPointerFix(vp, cb, TRUE)
+#define WOWRELVDMPTR(vp) WOWGetVDMPointerUnfix(vp)
+
+#else
+
+#define WOWFIXVDMPTR(vp, cb) WOWGetVDMPointer(vp, cb, TRUE)
+#define WOWRELVDMPTR(vp) (vp)
+
+#endif
+
+#define FIXVDMPTR(vp, type) \
+ (type UNALIGNED *)WOWFIXVDMPTR(vp, sizeof(type))
+#define RELVDMPTR(vp) \
+ WOWRELVDMPTR(vp)
+
+#if !defined(_CHICAGO_)
+
+HAND16 CopyDropFilesFrom32(HANDLE h32);
+HANDLE CopyDropFilesFrom16(HAND16 h16);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+// 16-bit HGLOBAL tracking functions
+#if DBG == 1
+VPVOID WgtAllocLock(WORD wFlags, DWORD cb, HMEM16 *ph);
+void WgtUnlockFree(VPVOID vpv);
+void WgtDump(void);
+#else
+#define WgtAllocLock(wFlags, cb, ph) \
+ WOWGlobalAllocLock16(wFlags, cb, ph)
+#define WgtUnlockFree(vpv) \
+ WOWGlobalUnlockFree16(vpv)
+#define WgtDump()
+#endif
+
+#endif // #ifndef __WOW32FN_H__
diff --git a/private/ole32/olethunk/makefil0 b/private/ole32/olethunk/makefil0
new file mode 100644
index 000000000..5d9846aaa
--- /dev/null
+++ b/private/ole32/olethunk/makefil0
@@ -0,0 +1,30 @@
+# INTEROP makefile
+#
+# Copyright (c) 1994, Microsoft Corporation
+#
+# History:
+# 18-Feb-1994 Bob Day (bobday)
+# Adapted from MVDM makefile
+#
+# If you add a new sub-component , make sure to add it in cleanup
+# section too.
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.plt
+
+all:
+!IF "$(BUILDMSG)" != ""
+ @ech ; $(BUILDMSG) ;
+!ENDIF
+
+cleanup:
+!if "$(PROCESSOR_ARCHITECTURE)" == "x86"
+ cd debnot
+ $(MAKE) OPST=chic /f win16.mk clean
+ $(MAKE) OPST=dayt /f win16.mk clean
+ cd ..\ole16
+ $(MAKE) clean -f makefil0
+ cd ..
+!endif
+
+clean: cleanup all
diff --git a/private/ole32/olethunk/ole16/coll/array_fv.cxx b/private/ole32/olethunk/ole16/coll/array_fv.cxx
new file mode 100644
index 000000000..b9f7218d5
--- /dev/null
+++ b/private/ole32/olethunk/ole16/coll/array_fv.cxx
@@ -0,0 +1,312 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// Implementation of Array of values
+//
+/////////////////////////////////////////////////////////////////////////////
+// NOTE: we allocate an array of 'm_nMaxSize' elements, but only
+// the current size 'm_nSize' contains properly initialized elements
+
+#include <windows.h>
+#include <ole2.h>
+#include <ole2sp.h>
+#include <olecoll.h>
+#include <memctx.hxx>
+
+ASSERTDATA
+
+#include "array_fv.h"
+
+#include <limits.h>
+#define SIZE_T_MAX UINT_MAX /* max size for a size_t */
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+CArrayFValue::CArrayFValue(DWORD memctx, UINT cbValue)
+{
+ m_pData = NULL;
+ m_cbValue = cbValue;
+ m_nSize = m_nMaxSize = m_nGrowBy = 0;
+ if (memctx == MEMCTX_SAME)
+ memctx = CoMemctxOf(this);
+ m_memctx = memctx;
+ Assert(m_memctx != MEMCTX_UNKNOWN);
+}
+
+CArrayFValue::~CArrayFValue()
+{
+ ASSERT_VALID(this);
+
+ CoMemFree(m_pData, m_memctx);
+}
+
+// set new size; return FALSE if OOM
+
+BOOL CArrayFValue::SetSize(int nNewSize, int nGrowBy /* = -1 */)
+{
+ ASSERT_VALID(this);
+ Assert(nNewSize >= 0);
+
+ if (nGrowBy != -1)
+ m_nGrowBy = nGrowBy; // set new size
+
+ if (nNewSize == 0)
+ {
+ // shrink to nothing
+ CoMemFree(m_pData, m_memctx);
+ m_pData = NULL;
+ m_nSize = m_nMaxSize = 0;
+ }
+ else if (m_pData == NULL)
+ {
+ // create one with exact size
+ Assert((long)nNewSize * m_cbValue <= SIZE_T_MAX); // no overflow
+
+ m_pData = (BYTE FAR*)CoMemAlloc(nNewSize * m_cbValue, m_memctx, NULL);
+ if (m_pData == NULL)
+ return FALSE;
+
+ _fmemset(m_pData, 0, nNewSize * m_cbValue); // zero fill
+ m_nSize = m_nMaxSize = nNewSize;
+ }
+ else if (nNewSize <= m_nMaxSize)
+ {
+ // it fits
+ if (nNewSize > m_nSize)
+ {
+ // initialize the new elements
+ _fmemset(&m_pData[m_nSize * m_cbValue], 0, (nNewSize-m_nSize) * m_cbValue);
+ }
+ m_nSize = nNewSize;
+ }
+ else
+ {
+ // Otherwise grow array
+ int nNewMax;
+ if (nNewSize < m_nMaxSize + m_nGrowBy)
+ nNewMax = m_nMaxSize + m_nGrowBy; // granularity
+ else
+ nNewMax = nNewSize; // no slush
+
+ Assert((long)nNewMax * m_cbValue <= SIZE_T_MAX); // no overflow
+
+ BYTE FAR* pNewData = (BYTE FAR*)CoMemAlloc(nNewMax * m_cbValue, m_memctx, NULL);
+ if (pNewData == NULL)
+ return FALSE;
+
+ // copy new data from old
+ _fmemcpy(pNewData, m_pData, m_nSize * m_cbValue);
+
+ // construct remaining elements
+ Assert(nNewSize > m_nSize);
+ _fmemset(&pNewData[m_nSize * m_cbValue], 0, (nNewSize-m_nSize) * m_cbValue);
+
+ // get rid of old stuff (note: no destructors called)
+ CoMemFree(m_pData, m_memctx);
+ m_pData = pNewData;
+ m_nSize = nNewSize;
+ m_nMaxSize = nNewMax;
+ }
+ ASSERT_VALID(this);
+
+ return TRUE;
+}
+
+void CArrayFValue::FreeExtra()
+{
+ ASSERT_VALID(this);
+
+ if (m_nSize != m_nMaxSize)
+ {
+ // shrink to desired size
+ Assert((long)m_nSize * m_cbValue <= SIZE_T_MAX); // no overflow
+
+ BYTE FAR* pNewData = (BYTE FAR*)CoMemAlloc(m_nSize * m_cbValue, m_memctx, NULL);
+ if (pNewData == NULL)
+ return; // can't shrink; don't to anything
+
+ // copy new data from old
+ _fmemcpy(pNewData, m_pData, m_nSize * m_cbValue);
+
+ // get rid of old stuff (note: no destructors called)
+ CoMemFree(m_pData, m_memctx);
+ m_pData = pNewData;
+ m_nMaxSize = m_nSize;
+ }
+ ASSERT_VALID(this);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+LPVOID CArrayFValue::_GetAt(int nIndex) const
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0 && nIndex < m_nSize);
+ return &m_pData[nIndex * m_cbValue];
+}
+
+void CArrayFValue::SetAt(int nIndex, LPVOID pValue)
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0 && nIndex < m_nSize);
+
+ _fmemcpy(&m_pData[nIndex * m_cbValue], pValue, m_cbValue);
+}
+
+BOOL CArrayFValue::SetAtGrow(int nIndex, LPVOID pValue)
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0);
+ if (nIndex >= m_nSize && !SetSize(nIndex+1))
+ return FALSE;
+
+ SetAt(nIndex, pValue);
+
+ return TRUE;
+}
+
+BOOL CArrayFValue::InsertAt(int nIndex, LPVOID pValue, int nCount /*=1*/)
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0); // will expand to meet need
+ Assert(nCount > 0); // zero or negative size not allowed
+
+ if (nIndex >= m_nSize)
+ {
+ // adding after the end of the array
+ if (!SetSize(nIndex + nCount)) // grow so nIndex is valid
+ return FALSE;
+ }
+ else
+ {
+ // inserting in the middle of the array
+ int nOldSize = m_nSize;
+ if (!SetSize(m_nSize + nCount)) // grow it to new size
+ return FALSE;
+
+ // shift old data up to fill gap
+ _fmemmove(&m_pData[(nIndex+nCount) * m_cbValue],
+ &m_pData[nIndex * m_cbValue],
+ (nOldSize-nIndex) * m_cbValue);
+
+ // re-init slots we copied from
+ _fmemset(&m_pData[nIndex * m_cbValue], 0, nCount * m_cbValue);
+ }
+
+ // insert new value in the gap
+ Assert(nIndex + nCount <= m_nSize);
+ while (nCount--)
+ _fmemcpy(&m_pData[nIndex++ * m_cbValue], pValue, m_cbValue);
+
+ ASSERT_VALID(this);
+
+ return TRUE;
+}
+
+void CArrayFValue::RemoveAt(int nIndex, int nCount /* = 1 */)
+{
+ ASSERT_VALID(this);
+ Assert(nIndex >= 0);
+ Assert(nIndex < m_nSize);
+ Assert(nCount >= 0);
+ Assert(nIndex + nCount <= m_nSize);
+
+ // just remove a range
+ int nMoveCount = m_nSize - (nIndex + nCount);
+ if (nMoveCount)
+ _fmemcpy(&m_pData[nIndex * m_cbValue],
+ &m_pData[(nIndex + nCount) * m_cbValue],
+ nMoveCount * m_cbValue);
+ m_nSize -= nCount;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// find element given part of one; offset is offset into value; returns
+// -1 if element not found; use IndexOf(NULL, cb, offset) to find zeros;
+// will be optimized for appropriate value size and param combinations
+int CArrayFValue::IndexOf(LPVOID pData, UINT cbData, UINT offset)
+{
+ Assert(offset <= m_cbValue);
+ Assert(cbData <= m_cbValue);
+ Assert((long)offset + cbData <= m_cbValue);
+ Assert(!IsBadReadPtr(pData, cbData));
+
+#ifdef LATER
+ if (cbData == sizeof(WORD) && m_cbValue == sizeof(WORD))
+ {
+ int iwRet;
+ _asm
+ {
+ push di
+ les di,pData ;* get value
+ mov ax,es:[di] ;* from *(WORD FAR*)pData
+ les di,this
+ mov cx,[di].m_nSize ;* get size (in WORDs) of array
+ les di,[di].m_pData ;* get ptr to WORD array
+ repne scasw ;* look for *(WORD FAR*)pData
+ jeq retcx ;* brif found
+ xor cx,cx ;* return -1
+ retcx:
+ dec cx
+ mov iwRet,cx
+ pop di
+ }
+
+ return iwRet;
+ }
+#endif
+ BYTE FAR* pCompare = m_pData + offset; // points to the value to compare
+ int nIndex = 0;
+
+ if (cbData == sizeof(WORD)) {
+ for (; nIndex < m_nSize; pCompare += m_cbValue, nIndex++)
+ {
+ if (*(WORD FAR*)pCompare == *(WORD FAR*)pData)
+ return nIndex;
+ }
+ } else if (cbData == sizeof(LONG)) {
+ for (; nIndex < m_nSize; pCompare += m_cbValue, nIndex++)
+ {
+ if (*(LONG FAR*)pCompare == *(LONG FAR*)pData)
+ return nIndex;
+ }
+ } else {
+ for (; nIndex < m_nSize; pCompare += m_cbValue, nIndex++)
+ {
+ if (_fmemcmp(pCompare, pData, cbData) == 0)
+ return nIndex;
+ }
+ }
+
+ return -1;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+void CArrayFValue::AssertValid() const
+{
+#ifdef _DEBUG
+ if (m_pData == NULL)
+ {
+ Assert(m_nSize == 0);
+ Assert(m_nMaxSize == 0);
+ }
+ else
+ {
+ Assert(m_nSize <= m_nMaxSize);
+ Assert((long)m_nMaxSize * m_cbValue <= SIZE_T_MAX); // no overflow
+ Assert(!IsBadReadPtr(m_pData, m_nMaxSize * m_cbValue));
+ }
+
+ // some collections live as global variables in the libraries, but
+ // have their existance in some context. Also, we can't check shared
+ // collections since we might be checking the etask collection
+ // which would cause an infinite recursion.
+ Assert(m_memctx == MEMCTX_SHARED || CoMemctxOf(this) == MEMCTX_UNKNOWN || CoMemctxOf(this) == m_memctx);
+#endif //_DEBUG
+}
diff --git a/private/ole32/olethunk/ole16/coll/makefile b/private/ole32/olethunk/ole16/coll/makefile
new file mode 100644
index 000000000..8b6f9a452
--- /dev/null
+++ b/private/ole32/olethunk/ole16/coll/makefile
@@ -0,0 +1,36 @@
+#
+# Copyright (c) 1991, Microsoft Corporation
+#
+# History:
+#
+# 18-Feb-1994 BobDay Adapted from MVDM\WOW16\GDI\MAKEFILE
+#
+
+!IFDEF USEBUILD
+
+# If using BUILD.EXE, edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2.
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!ELSE
+
+default: all
+
+TARGET = coll.lib
+
+CXXFILES = \
+ .\array_fv.cxx \
+ .\map_kv.cxx \
+ .\plex.cxx
+
+!include ..\makefile.inc
+
+array_fv.obj: array_fv.cxx
+
+map_kv.obj: map_kv.cxx
+
+plex.obj: plex.cxx
+
+!ENDIF
diff --git a/private/ole32/olethunk/ole16/coll/map_kv.cxx b/private/ole32/olethunk/ole16/coll/map_kv.cxx
new file mode 100644
index 000000000..0d88ef71d
--- /dev/null
+++ b/private/ole32/olethunk/ole16/coll/map_kv.cxx
@@ -0,0 +1,536 @@
+/////////////////////////////////////////////////////////////////////////////
+// class CMapKeyToValue - a mapping from 'KEY's to 'VALUE's, passed in as
+// pv/cb pairs. The keys can be variable length, although we optmizize the
+// case when they are all the same.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include <windows.h>
+#include <ole2.h>
+#include <ole2sp.h>
+#include <olecoll.h>
+#include <memctx.hxx>
+
+
+#include "map_kv.h"
+
+#include "plex.h"
+ASSERTDATA
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+CMapKeyToValue::CMapKeyToValue(DWORD memctx, UINT cbValue, UINT cbKey,
+ int nBlockSize, LPFNHASHKEY lpfnHashKey, UINT nHashSize)
+{
+ Assert(nBlockSize > 0);
+
+ m_cbValue = cbValue;
+ m_cbKey = cbKey;
+ m_cbKeyInAssoc = cbKey == 0 ? sizeof(CKeyWrap) : cbKey;
+
+ m_pHashTable = NULL;
+ m_nHashTableSize = nHashSize;
+ m_lpfnHashKey = lpfnHashKey;
+
+ m_nCount = 0;
+ m_pFreeList = NULL;
+ m_pBlocks = NULL;
+ m_nBlockSize = nBlockSize;
+ if (memctx == MEMCTX_SAME)
+ memctx = CoMemctxOf(this);
+ m_memctx = memctx;
+ Assert(m_memctx != MEMCTX_UNKNOWN);
+}
+
+CMapKeyToValue::~CMapKeyToValue()
+{
+ ASSERT_VALID(this);
+ RemoveAll();
+ Assert(m_nCount == 0);
+}
+
+
+// simple, default hash function
+// REVIEW: need to check the value in this for GUIDs and strings
+STDAPI_(UINT) MKVDefaultHashKey(LPVOID pKey, UINT cbKey)
+{
+ UINT hash = 0;
+ BYTE FAR* lpb = (BYTE FAR*)pKey;
+
+ while (cbKey-- != 0)
+ hash = 257 * hash + *lpb++;
+
+ return hash;
+}
+
+
+BOOL CMapKeyToValue::InitHashTable()
+{
+ ASSERT_VALID(this);
+ Assert(m_nHashTableSize > 0);
+
+ if (m_pHashTable != NULL)
+ return TRUE;
+
+ Assert(m_nCount == 0);
+
+ if ((m_pHashTable = (CAssoc FAR* FAR*)CoMemAlloc(m_nHashTableSize * sizeof(CAssoc FAR*), m_memctx, NULL)) == NULL)
+ return FALSE;
+
+ _fmemset(m_pHashTable, 0, sizeof(CAssoc FAR*) * m_nHashTableSize);
+
+ ASSERT_VALID(this);
+
+ return TRUE;
+}
+
+
+void CMapKeyToValue::RemoveAll()
+{
+ ASSERT_VALID(this);
+
+ // free all key values and then hash table
+ if (m_pHashTable != NULL)
+ {
+ // destroy assocs
+ for (UINT nHash = 0; nHash < m_nHashTableSize; nHash++)
+ {
+ register CAssoc FAR* pAssoc;
+ for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL;
+ pAssoc = pAssoc->pNext)
+ // assoc itself is freed by FreeDataChain below
+ FreeAssocKey(pAssoc);
+ }
+
+ // free hash table
+ CoMemFree(m_pHashTable, m_memctx);
+ m_pHashTable = NULL;
+ }
+
+ m_nCount = 0;
+ m_pFreeList = NULL;
+ m_pBlocks->FreeDataChain(m_memctx);
+ m_pBlocks = NULL;
+
+ ASSERT_VALID(this);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Assoc helpers
+// CAssoc's are singly linked all the time
+
+CMapKeyToValue::CAssoc FAR*
+ CMapKeyToValue::NewAssoc(UINT hash, LPVOID pKey, UINT cbKey, LPVOID pValue)
+{
+ if (m_pFreeList == NULL)
+ {
+ // add another block
+ CPlex FAR* newBlock = CPlex::Create(m_pBlocks, m_memctx, m_nBlockSize, SizeAssoc());
+
+ if (newBlock == NULL)
+ return NULL;
+
+ // chain them into free list
+ register BYTE FAR* pbAssoc = (BYTE FAR*) newBlock->data();
+ // free in reverse order to make it easier to debug
+ pbAssoc += (m_nBlockSize - 1) * SizeAssoc();
+ for (int i = m_nBlockSize-1; i >= 0; i--, pbAssoc -= SizeAssoc())
+ {
+ ((CAssoc FAR*)pbAssoc)->pNext = m_pFreeList;
+ m_pFreeList = (CAssoc FAR*)pbAssoc;
+ }
+ }
+ Assert(m_pFreeList != NULL); // we must have something
+
+ CMapKeyToValue::CAssoc FAR* pAssoc = m_pFreeList;
+
+ // init all fields except pNext while still on free list
+ pAssoc->nHashValue = hash;
+ if (!SetAssocKey(pAssoc, pKey, cbKey))
+ return NULL;
+
+ SetAssocValue(pAssoc, pValue);
+
+ // remove from free list after successfully initializing it (except pNext)
+ m_pFreeList = m_pFreeList->pNext;
+ m_nCount++;
+ Assert(m_nCount > 0); // make sure we don't overflow
+
+ return pAssoc;
+}
+
+
+// free individual assoc by freeing key and putting on free list
+void CMapKeyToValue::FreeAssoc(CMapKeyToValue::CAssoc FAR* pAssoc)
+{
+ pAssoc->pNext = m_pFreeList;
+ m_pFreeList = pAssoc;
+ m_nCount--;
+ Assert(m_nCount >= 0); // make sure we don't underflow
+
+ FreeAssocKey(pAssoc);
+}
+
+
+// find association (or return NULL)
+CMapKeyToValue::CAssoc FAR*
+CMapKeyToValue::GetAssocAt(LPVOID pKey, UINT cbKey, UINT FAR& nHash) const
+{
+ if (m_lpfnHashKey)
+ nHash = (*m_lpfnHashKey)(pKey, cbKey) % m_nHashTableSize;
+ else {
+ Assert(m_lpfnHashKey);
+ return NULL;
+ }
+
+ if (m_pHashTable == NULL)
+ return NULL;
+
+ // see if it exists
+ register CAssoc FAR* pAssoc;
+ for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext)
+ {
+ if (CompareAssocKey(pAssoc, pKey, cbKey))
+ return pAssoc;
+ }
+ return NULL;
+}
+
+
+BOOL CMapKeyToValue::CompareAssocKey(CAssoc FAR* pAssoc, LPVOID pKey2, UINT cbKey2) const
+{
+ LPVOID pKey1;
+ UINT cbKey1;
+
+ GetAssocKeyPtr(pAssoc, &pKey1, &cbKey1);
+ return cbKey1 == cbKey2 && _fmemcmp(pKey1, pKey2, cbKey1) == 0;
+}
+
+
+BOOL CMapKeyToValue::SetAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const
+{
+ Assert(cbKey == m_cbKey || m_cbKey == 0);
+
+ if (m_cbKey == 0)
+ {
+ Assert(m_cbKeyInAssoc == sizeof(CKeyWrap));
+
+ // alloc, set size and pointer
+ if ((pAssoc->key.pKey = CoMemAlloc(cbKey, m_memctx, NULL)) == NULL)
+ return FALSE;
+
+ pAssoc->key.cbKey = cbKey;
+ }
+
+ LPVOID pKeyTo;
+
+ GetAssocKeyPtr(pAssoc, &pKeyTo, &cbKey);
+
+ _fmemcpy(pKeyTo, pKey, cbKey);
+
+ return TRUE;
+}
+
+
+// gets pointer to key and its length
+void CMapKeyToValue::GetAssocKeyPtr(CAssoc FAR* pAssoc, LPVOID FAR* ppKey,UINT FAR* pcbKey) const
+{
+ if (m_cbKey == 0)
+ {
+ // variable length key; go indirect
+ *ppKey = pAssoc->key.pKey;
+ *pcbKey = pAssoc->key.cbKey;
+ }
+ else
+ {
+ // fixed length key; key in assoc
+ *ppKey = (LPVOID)&pAssoc->key;
+ *pcbKey = m_cbKey;
+ }
+}
+
+
+void CMapKeyToValue::FreeAssocKey(CAssoc FAR* pAssoc) const
+{
+ if (m_cbKey == 0)
+ CoMemFree(pAssoc->key.pKey, m_memctx);
+}
+
+
+void CMapKeyToValue::GetAssocValuePtr(CAssoc FAR* pAssoc, LPVOID FAR* ppValue) const
+{
+ *ppValue = (char FAR*)&pAssoc->key + m_cbKeyInAssoc;
+}
+
+
+void CMapKeyToValue::GetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const
+{
+ LPVOID pValueFrom;
+ GetAssocValuePtr(pAssoc, &pValueFrom);
+ Assert(pValue != NULL);
+ _fmemcpy(pValue, pValueFrom, m_cbValue);
+}
+
+
+void CMapKeyToValue::SetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const
+{
+ LPVOID pValueTo;
+ GetAssocValuePtr(pAssoc, &pValueTo);
+ if (pValue == NULL)
+ _fmemset(pValueTo, 0, m_cbValue);
+ else
+ _fmemcpy(pValueTo, pValue, m_cbValue);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// lookup value given key; return FALSE if key not found; in that
+// case, the value is set to all zeros
+BOOL CMapKeyToValue::Lookup(LPVOID pKey, UINT cbKey, LPVOID pValue) const
+{
+ UINT nHash;
+ return LookupHKey((HMAPKEY)GetAssocAt(pKey, cbKey, nHash), pValue);
+}
+
+
+// lookup value given key; return FALSE if NULL (or bad) key; in that
+// case, the value is set to all zeros
+BOOL CMapKeyToValue::LookupHKey(HMAPKEY hKey, LPVOID pValue) const
+{
+ // REVIEW: would like some way to verify that hKey is valid
+ register CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+ if (pAssoc == NULL)
+ {
+ _fmemset(pValue, 0, m_cbValue);
+ return FALSE; // not in map
+ }
+
+ ASSERT_VALID(this);
+
+ GetAssocValue(pAssoc, pValue);
+ return TRUE;
+}
+
+
+// lookup and if not found add; returns FALSE only if OOM; if added,
+// value added and pointer passed are set to zeros.
+BOOL CMapKeyToValue::LookupAdd(LPVOID pKey, UINT cbKey, LPVOID pValue) const
+{
+ if (Lookup(pKey, cbKey, pValue))
+ return TRUE;
+
+ // value set to zeros since lookup failed
+
+ return ((CMapKeyToValue FAR*)this)->SetAt(pKey, cbKey, NULL);
+}
+
+
+// the only place new assocs are created; return FALSE if OOM;
+// never returns FALSE if keys already exists
+BOOL CMapKeyToValue::SetAt(LPVOID pKey, UINT cbKey, LPVOID pValue)
+{
+ UINT nHash;
+ register CAssoc FAR* pAssoc;
+
+ ASSERT_VALID(this);
+
+ if ((pAssoc = GetAssocAt(pKey, cbKey, nHash)) == NULL)
+ {
+ if (!InitHashTable())
+ // out of memory
+ return FALSE;
+
+ // it doesn't exist, add a new Association
+ if ((pAssoc = NewAssoc(nHash, pKey, cbKey, pValue)) == NULL)
+ return FALSE;
+
+ // put into hash table
+ pAssoc->pNext = m_pHashTable[nHash];
+ m_pHashTable[nHash] = pAssoc;
+
+ ASSERT_VALID(this);
+ }
+ else
+ {
+ SetAssocValue(pAssoc, pValue);
+ }
+
+ return TRUE;
+}
+
+
+// set existing hkey to value; return FALSE if NULL or bad key
+BOOL CMapKeyToValue::SetAtHKey(HMAPKEY hKey, LPVOID pValue)
+{
+ // REVIEW: would like some way to verify that hKey is valid
+ register CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+ if (pAssoc == NULL)
+ return FALSE; // not in map
+
+ ASSERT_VALID(this);
+
+ SetAssocValue(pAssoc, pValue);
+ return TRUE;
+}
+
+
+// remove key - return TRUE if removed
+BOOL CMapKeyToValue::RemoveKey(LPVOID pKey, UINT cbKey)
+{
+ ASSERT_VALID(this);
+
+ if (m_pHashTable == NULL)
+ return FALSE; // nothing in the table
+
+ register CAssoc FAR* FAR* ppAssocPrev;
+ ppAssocPrev = &m_pHashTable[(*m_lpfnHashKey)(pKey, cbKey) % m_nHashTableSize];
+
+ CAssoc FAR* pAssoc;
+ for (pAssoc = *ppAssocPrev; pAssoc != NULL; pAssoc = pAssoc->pNext)
+ {
+ if (CompareAssocKey(pAssoc, pKey, cbKey))
+ {
+ // remove it
+ *ppAssocPrev = pAssoc->pNext; // remove from list
+ FreeAssoc(pAssoc);
+ ASSERT_VALID(this);
+ return TRUE;
+ }
+ ppAssocPrev = &pAssoc->pNext;
+ }
+ return FALSE; // not found
+}
+
+
+// remove key based on pAssoc (HMAPKEY)
+BOOL CMapKeyToValue::RemoveHKey(HMAPKEY hKey)
+{
+ ASSERT_VALID(this);
+
+ if (m_pHashTable == NULL)
+ return FALSE; // nothing in the table
+
+ // REVIEW: would like some way to verify that hKey is valid
+ CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+ if (pAssoc == NULL || pAssoc->nHashValue >= m_nHashTableSize)
+ // null hkey or bad hash value
+ return FALSE;
+
+ register CAssoc FAR* FAR* ppAssocPrev;
+ ppAssocPrev = &m_pHashTable[pAssoc->nHashValue];
+
+ while (*ppAssocPrev != NULL)
+ {
+ if (*ppAssocPrev == pAssoc)
+ {
+ // remove it
+ *ppAssocPrev = pAssoc->pNext; // remove from list
+ FreeAssoc(pAssoc);
+ ASSERT_VALID(this);
+ return TRUE;
+ }
+ ppAssocPrev = &(*ppAssocPrev)->pNext;
+ }
+
+ return FALSE; // not found (must have a screwed up list or passed
+ // a key from another list)
+}
+
+
+HMAPKEY CMapKeyToValue::GetHKey(LPVOID pKey, UINT cbKey) const
+{
+ UINT nHash;
+
+ ASSERT_VALID(this);
+
+ return (HMAPKEY)GetAssocAt(pKey, cbKey, nHash);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Iterating
+
+// for fixed length keys, copies key to pKey; pcbKey can be NULL;
+// for variable length keys, copies pointer to key to pKey; sets pcbKey.
+
+void CMapKeyToValue::GetNextAssoc(POSITION FAR* pNextPosition,
+ LPVOID pKey, UINT FAR* pcbKey, LPVOID pValue) const
+{
+ ASSERT_VALID(this);
+
+ Assert(m_pHashTable != NULL); // never call on empty map
+
+ register CAssoc FAR* pAssocRet = (CAssoc FAR*)*pNextPosition;
+ Assert(pAssocRet != NULL);
+
+ if (pAssocRet == (CAssoc FAR*) BEFORE_START_POSITION)
+ {
+ // find the first association
+ for (UINT nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
+ if ((pAssocRet = m_pHashTable[nBucket]) != NULL)
+ break;
+ Assert(pAssocRet != NULL); // must find something
+ }
+
+ // find next association
+ CAssoc FAR* pAssocNext;
+ if ((pAssocNext = pAssocRet->pNext) == NULL)
+ {
+ // go to next bucket
+ for (UINT nBucket = pAssocRet->nHashValue + 1;
+ nBucket < m_nHashTableSize; nBucket++)
+ if ((pAssocNext = m_pHashTable[nBucket]) != NULL)
+ break;
+ }
+
+ // fill in return data
+ *pNextPosition = (POSITION) pAssocNext;
+
+ // fill in key/pointer to key
+ LPVOID pKeyFrom;
+ UINT cbKey;
+ GetAssocKeyPtr(pAssocRet, &pKeyFrom, &cbKey);
+ if (m_cbKey == 0)
+ // variable length key; just return pointer to key itself
+ *(void FAR* FAR*)pKey = pKeyFrom;
+ else
+ _fmemcpy(pKey, pKeyFrom, cbKey);
+
+ if (pcbKey != NULL)
+ *pcbKey = cbKey;
+
+ // get value
+ GetAssocValue(pAssocRet, pValue);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CMapKeyToValue::AssertValid() const
+{
+#ifdef _DEBUG
+ Assert(m_cbKeyInAssoc == (m_cbKey == 0 ? sizeof(CKeyWrap) : m_cbKey));
+
+ Assert(m_nHashTableSize > 0);
+ Assert(m_nCount == 0 || m_pHashTable != NULL);
+
+ if (m_pHashTable != NULL)
+ Assert(!IsBadReadPtr(m_pHashTable, m_nHashTableSize * sizeof(CAssoc FAR*)));
+
+ Assert(!IsBadCodePtr((FARPROC)m_lpfnHashKey));
+
+ if (m_pFreeList != NULL)
+ Assert(!IsBadReadPtr(m_pFreeList, SizeAssoc()));
+
+ if (m_pBlocks != NULL)
+ Assert(!IsBadReadPtr(m_pBlocks, SizeAssoc() * m_nBlockSize));
+
+ // some collections live as global variables in the libraries, but
+ // have their existance in some context. Also, we can't check shared
+ // collections since we might be checking the etask collection
+ // which would cause an infinite recursion.
+ Assert(m_memctx == MEMCTX_SHARED || CoMemctxOf(this) == MEMCTX_UNKNOWN || CoMemctxOf(this) == m_memctx);
+#endif //_DEBUG
+}
diff --git a/private/ole32/olethunk/ole16/coll/plex.cxx b/private/ole32/olethunk/ole16/coll/plex.cxx
new file mode 100644
index 000000000..5cf60af74
--- /dev/null
+++ b/private/ole32/olethunk/ole16/coll/plex.cxx
@@ -0,0 +1,47 @@
+// This is a part of the Microsoft Foundation Classes C++ library.
+// Copyright (C) 1992 Microsoft Corporation
+// All rights reserved.
+//
+// This source code is only intended as a supplement to the
+// Microsoft Foundation Classes Reference and Microsoft
+// QuickHelp documentation provided with the library.
+// See these sources for detailed information regarding the
+// Microsoft Foundation Classes product.
+
+#include <windows.h>
+#include <ole2.h>
+#include <ole2sp.h>
+#include <olecoll.h>
+#include <memctx.hxx>
+
+
+#include "plex.h"
+ASSERTDATA
+
+
+
+CPlex FAR* CPlex::Create(CPlex FAR* FAR& pHead, DWORD mp, UINT nMax, UINT cbElement)
+{
+ AssertSz(nMax > 0 && cbElement > 0,0);
+ CPlex FAR* p = (CPlex FAR*)CoMemAlloc(sizeof(CPlex) + nMax * cbElement, mp, NULL);
+ if (p == NULL)
+ return NULL;
+
+ p->nMax = nMax;
+ p->nCur = 0;
+ p->pNext = pHead;
+ pHead = p; // change head (adds in reverse order for simplicity)
+ return p;
+}
+
+void CPlex::FreeDataChain(DWORD mp) // free this one and links
+{
+ CPlex FAR* pThis;
+ CPlex FAR* pNext;
+
+ for (pThis = this; pThis != NULL; pThis = pNext) {
+ pNext = pThis->pNext;
+ pThis->pNext = NULL; // So compiler won't do nasty optimizations
+ CoMemFree(pThis, mp);
+ }
+}
diff --git a/private/ole32/olethunk/ole16/compobj/assrtdlg.h b/private/ole32/olethunk/ole16/compobj/assrtdlg.h
new file mode 100644
index 000000000..f61ae784c
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/assrtdlg.h
@@ -0,0 +1,9 @@
+#define AssertFail 5100
+#define Expr 5101
+#define Location 5102
+#define ASSRT_ID_BREAK 5103
+#define ASSRT_ID_EXIT 5104
+#define ASSRT_ID_IGNORE 5105
+#define ASSRT_ID_LOC 5106
+#define ASSRT_ID_EXPR 5107
+#define ASSRT_ID_MSG 5108
diff --git a/private/ole32/olethunk/ole16/compobj/call32.cxx b/private/ole32/olethunk/ole16/compobj/call32.cxx
new file mode 100644
index 000000000..0cc3e6360
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/call32.cxx
@@ -0,0 +1,1313 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: call32.cxx (16 bit target)
+//
+// Contents: Functions to call 32 bit dll in WOW
+//
+// Functions:
+//
+// History: 16-Dec-93 JohannP Created
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <ole2ver.h>
+
+#include <ole2sp.h>
+
+#include <olecoll.h>
+#include <map_kv.h>
+
+#include "map_htsk.h"
+#include "etask.hxx"
+
+#include <call32.hxx>
+#include <obj16.hxx>
+#include <go1632pr.hxx>
+#include <comlocal.hxx>
+
+static LPVOID lpInvokeOn32Proc; // Address of InvokeOn32() in 32-bits
+static LPVOID lpSSInvokeOn32Proc; // Address of InvokeOn32() in 32-bits
+LPVOID lpIUnknownObj32; // Address of IUnknown methods handler
+static LPVOID lpCallbackProcessing; // Address of CallbackProcessing_3216
+static LPVOID pfnCSm16ReleaseHandler_Release32;
+
+static LPVOID pfnConvertHr1632; // TranslateHRESULT_1632
+static LPVOID pfnConvertHr3216; // TranslateHRESULT_3216
+static LPVOID pfnThkAddAppCompatFlag; // Add an AppCompatibility flag
+
+static DWORD hmodOLEThunkDLL; // Module handle of 32-bit OLE interop DLL
+EXTERN_C LPVOID lpThkCallOutputFunctionsProc; // Address of ThkCallOutputFunctions in olethk32.dll
+
+//
+// Not used on Win95
+//
+
+#ifndef _CHICAGO_
+static LPVOID pfnIntOpUninitialize; // Uninitialize function
+#else
+BOOL gfReleaseDLL = TRUE;
+#endif
+
+
+DWORD __loadds FAR PASCAL CallStub16(LPCALLDATA pcd);
+
+// Address of ThkInitialize() in 32-bits
+static LPVOID lpThkInitializeProc;
+// Address of ThkUninitialize() in 32-bits
+static LPVOID lpThkUninitializeProc;
+
+BOOL __loadds FAR PASCAL CallbackHandler( DWORD dwContinue );
+DWORD __loadds FAR PASCAL LoadProcDll( LPLOADPROCDLLSTRUCT lplpds );
+DWORD __loadds FAR PASCAL UnloadProcDll( DWORD vhmodule );
+DWORD __loadds FAR PASCAL CallGetClassObject( LPCALLGETCLASSOBJECTSTRUCT
+ lpcgcos );
+DWORD __loadds FAR PASCAL CallCanUnloadNow( DWORD vpfnCanUnloadNow );
+DWORD __loadds FAR PASCAL QueryInterface16(IUnknown FAR *punk,
+ REFIID riid,
+ void FAR * FAR *ppv);
+DWORD __loadds FAR PASCAL AddRef16(IUnknown FAR *punk);
+DWORD __loadds FAR PASCAL Release16(IUnknown FAR *punk);
+DWORD __loadds FAR PASCAL ReleaseStgMedium16(STGMEDIUM FAR *psm);
+DWORD __loadds FAR PASCAL TouchPointer16(BYTE FAR *pb);
+DWORD __loadds FAR PASCAL StgMediumStreamHandler16(IStream FAR *pstmFrom,
+ IStream FAR *pstmTo);
+DWORD __loadds FAR PASCAL SetOwnerPublic16( DWORD hMem16 );
+ULONG __loadds FAR PASCAL WinExec16( LPWINEXEC16STRUCT lpwes );
+
+
+extern DWORD Sm16RhVtbl[SMI_COUNT];
+
+// This DBG block allows assertion that the list is the same size
+// as a DATA16
+#if DBG == 1
+DWORD gdata16[] =
+#else
+DATA16 gdata16 =
+#endif
+{
+ (DWORD)atfnProxy1632Vtbl,
+ (DWORD)CallbackHandler,
+ (DWORD)TaskAlloc,
+ (DWORD)TaskFree,
+ (DWORD)LoadProcDll,
+ (DWORD)UnloadProcDll,
+ (DWORD)CallGetClassObject,
+ (DWORD)CallCanUnloadNow,
+ (DWORD)QueryInterface16,
+ (DWORD)AddRef16,
+ (DWORD)Release16,
+ (DWORD)ReleaseStgMedium16,
+ (DWORD)Sm16RhVtbl,
+ (DWORD)TouchPointer16,
+ (DWORD)StgMediumStreamHandler16,
+ (DWORD)CallStub16,
+ (DWORD)SetOwnerPublic16,
+ (DWORD)WinExec16
+};
+
+//+---------------------------------------------------------------------------
+//
+// Function: CallbackHandler
+//
+// Synopsis: Provides 16-bit address that will allow calling back into
+// the 32-bit world's callback handler. See IViewObject::Draw
+// lpfnContinue function parameter for the reasons for this
+// function.
+//
+// Returns: BOOL
+//
+// History: 3-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+BOOL __loadds FAR PASCAL CallbackHandler( DWORD dwContinue )
+{
+ BOOL fResult;
+
+ thkDebugOut((DEB_ITRACE, "CallbackHandler\n"));
+
+ fResult = (BOOL)CallProcIn32( dwContinue, 0, 0,
+ lpCallbackProcessing, 0, CP32_NARGS);
+
+ return fResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Call32Initialize, public
+//
+// Synopsis: Called once when compobj.dll gets loaded.
+// Connects to the interop DLL on the 32-bit side and
+// finds entry points
+//
+// Returns: BOOL
+//
+// History: 18-Feb-94 JohannP Created
+//
+// Notes: Called at library initialization time
+//
+//----------------------------------------------------------------------------
+#ifdef _CHICAGO_
+extern "C" BOOL FAR PASCAL SSInit( void );
+extern "C" DWORD _cdecl SSCall(DWORD cbParamBytes,
+ DWORD flags,
+ LPVOID lpfnProcAddress,
+ DWORD param1,...);
+
+#define SSF_BigStack 1
+#endif // _CHICAGO_
+
+STDAPI_(BOOL) Call32Initialize(void)
+{
+ LPVOID lpAddr;
+ BOOL fRet;
+ DWORD hr;
+
+ thkDebugOut((DEB_ITRACE | DEB_THUNKMGR, "In Call32Initialize\n"));
+
+ thkAssert(sizeof(gdata16) == sizeof(DATA16));
+
+ fRet = FALSE;
+ do
+ {
+ // initialize the 32 bit stack
+
+#ifdef _CHICAGO_
+ if (SSInit() == FALSE)
+ {
+ thkDebugOut((DEB_ERROR, "In Call32Initialize; SSInit failed.\n"));
+ break;
+ }
+#endif // _CHICAGO_
+
+ //
+ // Load the OLETHK32.DLL in WOW
+ //
+ hmodOLEThunkDLL = LoadLibraryEx32W("OLETHK32.DLL", 0, 0);
+ if (hmodOLEThunkDLL == 0)
+ {
+ thkDebugOut((DEB_ERROR, "Call32Initialize; LoadLibary failed.\n"));
+ break;
+ }
+
+ //
+ // Get the 32-bit initalization routine
+ //
+ lpAddr = GetProcAddress32W(hmodOLEThunkDLL, "IntOpInitialize");
+ if (lpAddr == NULL)
+ {
+ thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress IntOpInitialize failed.\n"));
+ break;
+ }
+
+ // Call the initialization routine and pass the 16-bit
+ // invocation and proxy setup routine pointers
+ // We want to keep these pointers in VDM form for Callback16
+ // so we do not have them mapped flat
+
+ if ((hr = CallProcIn32((DWORD)(LPDATA16)(&gdata16), 0, 0, lpAddr, 1 << 2, CP32_NARGS)) != NOERROR)
+ {
+ thkDebugOut((DEB_ERROR, "Call32Initialize; Call IntOpInitialize failed. hr = %x\n", hr));
+ break;
+ }
+
+ //
+ // Get the address of the start of the 32-bit thunk interpreter
+ //
+ lpInvokeOn32Proc = GetProcAddress32W(hmodOLEThunkDLL, "InvokeOn32");
+ if (lpInvokeOn32Proc == NULL)
+ {
+ thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress InvokeOn32 failed.\n"));
+ break;
+ }
+#ifdef _CHICAGO_
+ lpSSInvokeOn32Proc = GetProcAddress32W(hmodOLEThunkDLL, "SSInvokeOn32");
+ if (lpSSInvokeOn32Proc == NULL)
+ {
+ thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress SSInvokeOn32 failed.\n"));
+ break;
+ }
+#endif
+
+ lpIUnknownObj32 = GetProcAddress32W(hmodOLEThunkDLL, "IUnknownObj32");
+ if (lpIUnknownObj32 == NULL)
+ {
+ thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress IUnknowObj32 failed.\n"));
+ break;
+ }
+
+ // proc address to initialize the thunk manager for
+ // needs to be called for each apartment
+ lpThkInitializeProc = GetProcAddress32W(hmodOLEThunkDLL,
+ "ThkMgrInitialize");
+ if (lpThkInitializeProc == NULL)
+ {
+ break;
+ }
+
+ lpThkUninitializeProc = GetProcAddress32W(hmodOLEThunkDLL,
+ "ThkMgrUninitialize");
+ if (lpThkUninitializeProc == NULL)
+ {
+ break;
+ }
+
+ pfnCSm16ReleaseHandler_Release32 =
+ GetProcAddress32W(hmodOLEThunkDLL,
+ "CSm16ReleaseHandler_Release32");
+ if (pfnCSm16ReleaseHandler_Release32 == NULL)
+ {
+ break;
+ }
+
+ //
+ // Get the address of the callback procedure for 32-bit callbacks
+ //
+ lpCallbackProcessing = GetProcAddress32W(hmodOLEThunkDLL,
+ "CallbackProcessing_3216");
+ if ( lpCallbackProcessing == NULL )
+ {
+ break;
+ }
+
+ pfnConvertHr1632 = GetProcAddress32W(hmodOLEThunkDLL,
+ "ConvertHr1632Thunk");
+ if (pfnConvertHr1632 == NULL)
+ {
+ break;
+ }
+
+ pfnConvertHr3216 = GetProcAddress32W(hmodOLEThunkDLL,
+ "ConvertHr3216Thunk");
+ if (pfnConvertHr3216 == NULL)
+ {
+ break;
+ }
+
+ //
+ // pfnIntOpUninitialize is not used on Win95
+ //
+#ifndef _CHICAGO_
+ pfnIntOpUninitialize = GetProcAddress32W(hmodOLEThunkDLL,
+ "IntOpUninitialize");
+ if (pfnIntOpUninitialize == NULL)
+ {
+ break;
+ }
+#endif
+ pfnThkAddAppCompatFlag = GetProcAddress32W(hmodOLEThunkDLL,
+ "ThkAddAppCompatFlag");
+
+ if (pfnThkAddAppCompatFlag == NULL )
+ {
+ break;
+ }
+
+#if DBG == 1
+ lpThkCallOutputFunctionsProc = GetProcAddress32W(hmodOLEThunkDLL, "ThkCallOutputFunctions");
+ if (lpThkCallOutputFunctionsProc == NULL)
+ {
+ // Ignore error as stuff will go to debugger screen by default
+ thkDebugOut((DEB_ERROR, "Call32Initialize; GetProcAddress ThkCallOutputFunctions failed.\n"));
+ }
+#endif
+
+ fRet = TRUE;
+ }
+ while (FALSE);
+
+ if (!fRet && hmodOLEThunkDLL != 0)
+ {
+ FreeLibrary32W(hmodOLEThunkDLL);
+ }
+
+ thkDebugOut((DEB_ITRACE | DEB_THUNKMGR, "Out Call32Initialize exit, %d\n", fRet));
+ return fRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Call32Uninitialize, public
+//
+// Synopsis: Called once when compobj.dll gets unloaded.
+// Disconnects to the interop DLL on the 32-bit side
+//
+// History: 13-Jul-94 BobDay Created
+//
+// Notes: Called at library WEP time
+//
+//----------------------------------------------------------------------------
+STDAPI_(void) Call32Uninitialize(void)
+{
+ //
+ // The notification is only sent on Windows/NT. On Win95, the 32-bit
+ // side has already been cleaned up at this point, so calling over to
+ // 32-bits is a really bad idea. We could fault.
+ //
+#ifndef _CHICAGO_
+ // Notify olethk32 that the 16-bit half of interop is going away
+ if (pfnIntOpUninitialize != NULL)
+ {
+ CallProc32W(0, 0, 0, pfnIntOpUninitialize, 0, CP32_NARGS);
+ }
+#endif
+ //
+ // Free OLETHK32.DLL
+ //
+ if ( hmodOLEThunkDLL != 0 )
+ {
+ FreeLibrary32W(hmodOLEThunkDLL);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CallThkUninitialize
+//
+// Synopsis: Uninitialize the thunk manager and the tls data
+//
+// History: 5-24-94 JohannP (Johann Posch) Created
+//
+// Notes: Is called after CoUnintialize returned.
+//
+//----------------------------------------------------------------------------
+STDAPI_(void) CallThkMgrUninitialize(void)
+{
+ thkAssert(lpThkUninitializeProc != NULL);
+
+ CallProc32W(0, 0, 0,
+ lpThkUninitializeProc, 0, CP32_NARGS);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CallThkInitialize
+//
+// Synopsis: Initializes the thunk manager and the tls data
+//
+// Returns: Appropriate status code
+//
+// History: 5-24-94 JohannP (Johann Posch) Created
+//
+// Notes: Called during CoInitialize.
+//
+//----------------------------------------------------------------------------
+
+STDAPI CallThkMgrInitialize(void)
+{
+ thkAssert(lpThkInitializeProc != NULL);
+
+ return (HRESULT)CallProc32W(0, 0, 0,
+ lpThkInitializeProc, 0, CP32_NARGS);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CallObjectInWOW, public
+//
+// Synopsis: Wrapper for CallProcIn32 which handles our particular
+// form of call for thunked APIs and methods
+//
+// Arguments: [oid] - Object ID
+// [dwMethod] - Method index
+// [pvStack] - Beginning of stack in 16-bits
+//
+// Returns: 32-bit call result
+//
+// History: 18-Feb-94 JohannP Created
+//
+//----------------------------------------------------------------------------
+STDAPI_(DWORD) CallObjectInWOW(DWORD dwMethod, LPVOID pvStack)
+{
+
+ thkDebugOut((DEB_ITRACE, "CallObjectInWOW\n"));
+ thkAssert(lpInvokeOn32Proc != NULL);
+
+
+#ifdef _CHICAGO_
+ // Note: only call if this process is still initialized
+ HTASK htask;
+ Etask etask;
+
+ if (! ( LookupEtask(htask, etask)
+ && (etask.m_htask == GetCurrentProcess()) ) )
+ {
+ thkDebugOut((DEB_ITRACE, "CallObjectInWOW failed not ETask (%08lX)(0x%08lX, %p)\n",
+ lpInvokeOn32Proc, dwMethod, pvStack));
+ return (DWORD)E_UNEXPECTED;
+ }
+#endif
+
+
+ // If the stack pointer is NULL then pass along our own stack
+ // It won't be used but we need a valid pointer for CallProcIn32
+ // to work on
+ if (pvStack == NULL)
+ {
+ pvStack = PASCAL_STACK_PTR(dwMethod);
+ }
+
+ thkDebugOut((DEB_ITRACE, "CallProcIn32(%08lX)(0x%08lX, %p)\n",
+ lpInvokeOn32Proc, dwMethod, pvStack));
+
+ // Translate the stack pointer from 16:16 to flat 32
+ // The other user parameters aren't pointers
+ return CallProcIn32(0, dwMethod, (DWORD)pvStack,
+ lpInvokeOn32Proc, (1 << 0), CP32_NARGS);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: SSCallObjectInWOW
+//
+// Synopsis:
+//
+// Arguments: [dwMetho] --
+// [pvStack] --
+//
+// Returns:
+//
+// History: 1-24-95 JohannP (Johann Posch) Created
+//
+// Notes: Same functionality as CallObjectInWOW except
+// not switching to 32 bit stack first.
+//
+//----------------------------------------------------------------------------
+STDAPI_(DWORD) SSCallObjectInWOW(DWORD dwMethod, LPVOID pvStack)
+{
+ thkDebugOut((DEB_ITRACE, "CallObjectInWOW\n"));
+ thkAssert(lpInvokeOn32Proc != NULL);
+
+ // If the stack pointer is NULL then pass along our own stack
+ // It won't be used but we need a valid pointer for CallProcIn32
+ // to work on
+ if (pvStack == NULL)
+ {
+ pvStack = PASCAL_STACK_PTR(dwMethod);
+ }
+
+ thkDebugOut((DEB_ITRACE, "CallProcIn32(%08lX)(0x%08lX, %p)\n",
+ lpInvokeOn32Proc, dwMethod, pvStack));
+
+ // Translate the stack pointer from 16:16 to flat 32
+ // The other user parameters aren't pointers
+ return CallProcIn32(0, dwMethod, (DWORD)pvStack,
+ lpSSInvokeOn32Proc, (1 << 0), CP32_NARGS);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CallObjectInWOWCheckInit, public
+//
+// Synopsis: Performs CallObjectInWOW with guaranteed initialization
+//
+// Arguments: [oid] - Object ID
+// [dwMethod] - Method index
+// [pvStack] - Beginning of stack in 16-bits
+//
+// Returns: 32-bit call result
+//
+// History: 18-Feb-94 JohannP Created
+//
+// Notes: Since this function can return an error code from
+// CoInitialize, it should only be used directly for
+// functions which return HRESULTs
+// Other functions should check the HRESULT and map
+// it into an appropriate return value
+//
+//----------------------------------------------------------------------------
+STDAPI_(DWORD) CallObjectInWOWCheckInit(DWORD dwMethod, LPVOID pvStack)
+{
+ Etask etask;
+ HTASK htask;
+ HRESULT hr;
+
+ thkDebugOut((DEB_ITRACE, "CallObjectInWOWCheckInit\n"));
+
+ if (!IsEtaskInit(htask, etask))
+ {
+ hr = CoInitialize( NULL );
+ if (FAILED(hr))
+ {
+ return (DWORD)hr;
+ }
+
+ thkVerify(LookupEtask( htask, etask ));
+ etask.m_inits = ETASK_FAKE_INIT;
+ thkVerify(SetEtask(htask, etask));
+ }
+
+ return( CallObjectInWOW( dwMethod, pvStack) );
+}
+//+---------------------------------------------------------------------------
+//
+// Function: CallObjectInWOWCheckThkMgr, public
+//
+// Synopsis: Performs CallObjectInWOW with guaranteed initialization
+// of ThkMgr.
+//
+// Arguments: [oid] - Object ID
+// [dwMethod] - Method index
+// [pvStack] - Beginning of stack in 16-bits
+//
+// Returns: 32-bit call result
+//
+// History: 25-Aug-94 JohannP Created
+//
+// Notes: Since this function can return an error code from
+// ThkMgrInitialize, it should only be used directly for
+// functions which return HRESULTs
+// Other functions should check the HRESULT and map
+// it into an appropriate return value
+// This function is used by Storage api's since
+// they do not need compobj.
+//
+//----------------------------------------------------------------------------
+STDAPI_(DWORD) CallObjectInWOWCheckThkMgr(DWORD dwMethod, LPVOID pvStack)
+{
+ Etask etask;
+ HTASK htask;
+ HRESULT hr;
+
+ thkDebugOut((DEB_ITRACE, "CallObjectInWOWCheckThkMgr\n"));
+
+ // Note: IsEtaskInit will fail until CoInitialize
+ // gets called.
+ // ThkMgrInitialize can be called mutliple time
+ // on the same apartment. This is inefficient but
+ // the simplest solution; there are only a few
+ // apps out there which use Storage api's without
+ // compobj and ole2.
+ if (!IsEtaskInit(htask, etask))
+ {
+ // Note:
+ // Under Chicago 32-bit DLL's are loaded into a 16-bit apps private
+ // memory address space. (Under Daytona, 32-bit DLL's are loaded in
+ // common memory). This causes an abort as the logic assumes that
+ // OLETHK32.DLL is loaded at this point.
+ //
+ // So if not initialize, initialize the thunk layer now.
+ //
+ hr = CallThkMgrInitialize();
+ if (FAILED(hr))
+ {
+ return (DWORD)hr;
+ }
+ }
+
+ return( CallObjectInWOW( dwMethod, pvStack) );
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: LoadProcDll, public
+//
+// Synopsis: Routine to load a 16-bit DLL and get the OLE entry points
+//
+// Arguments: [lplpds] - LoadProcDll struct full of needed goodies
+//
+// Returns:
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD __loadds FAR PASCAL LoadProcDll( LPLOADPROCDLLSTRUCT lplpds )
+{
+ DWORD dwResult;
+ HMODULE hmod16;
+ LPDWORD lpdw;
+
+ thkDebugOut((DEB_ITRACE, "LoadProcDll\n"));
+
+ hmod16 = LoadLibrary( (LPSTR)lplpds->vpDllName );
+
+ if ( hmod16 < HINSTANCE_ERROR )
+ {
+ return OLETHUNK_DLL16NOTFOUND;
+ }
+
+ lplpds->vpfnGetClassObject =
+ (DWORD)GetProcAddress( hmod16, "DllGetClassObject" );
+ lplpds->vpfnCanUnloadNow =
+ (DWORD)GetProcAddress( hmod16, "DllCanUnloadNow" );
+
+ lplpds->vhmodule = (DWORD) hmod16;
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: UnloadProcDll, public
+//
+// Synopsis: Routine to unload a 16-bit DLL
+//
+// Arguments: [vhmodule] - hmodule to unload
+//
+// Returns:
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD __loadds FAR PASCAL UnloadProcDll( DWORD vhmodule )
+{
+ DWORD dwResult;
+ HMODULE hmod16;
+
+ thkDebugOut((DEB_ITRACE, "UnloadProcDll\n"));
+
+ hmod16 = (HMODULE)vhmodule;
+
+ FreeLibrary( hmod16 );
+
+ return (DWORD)0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CallGetClassObject, public
+//
+// Synopsis: Routine to call 16-bit DLL's DllGetClassObject entrypoint
+//
+// Arguments: [lpcgcos] - CallGetClassObject struct full of needed goodies
+//
+// Returns:
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD __loadds FAR PASCAL CallGetClassObject(
+ LPCALLGETCLASSOBJECTSTRUCT lpcgcos )
+{
+ HRESULT hresult;
+ HRESULT (FAR PASCAL *lpfn)(CLSID &,IID &,LPVOID FAR *);
+
+ thkDebugOut((DEB_ITRACE, "CallGetClassObject\n"));
+
+ lpfn = (HRESULT (FAR PASCAL *)(CLSID &,IID &,LPVOID FAR*))
+ lpcgcos->vpfnGetClassObject;
+
+ hresult = (*lpfn)( lpcgcos->clsid,
+ lpcgcos->iid,
+ (LPVOID FAR *)&lpcgcos->iface );
+
+ return (DWORD)hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CallCanUnloadNow, public
+//
+// Synopsis: Routine to call 16-bit DLL's DllCanUnloadNow entrypoint
+//
+// Arguments: [vpfnCanUnloadNow] - 16:16 address of DllCanUnloadNow in DLL
+//
+// Returns:
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD __loadds FAR PASCAL CallCanUnloadNow( DWORD vpfnCanUnloadNow )
+{
+ HRESULT hresult;
+ HRESULT (FAR PASCAL *lpfn)(void);
+
+ thkDebugOut((DEB_ITRACE, "CallGetClassObject\n"));
+
+ lpfn = (HRESULT (FAR PASCAL *)(void))vpfnCanUnloadNow;
+
+ hresult = (*lpfn)();
+
+ return (DWORD)hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: QueryInterface16, public
+//
+// Synopsis: Calls QueryInterface on behalf of the 32-bit code
+//
+// Arguments: [punk] - Object
+// [riid] - IID
+// [ppv] - Interface return
+//
+// Returns: HRESULT
+//
+// History: 24-Mar-94 JohannP Created
+//
+//----------------------------------------------------------------------------
+DWORD __loadds FAR PASCAL QueryInterface16(IUnknown *punk,
+ REFIID riid,
+ void **ppv)
+{
+ DWORD dwRet;
+
+ thkAssert(punk != NULL);
+
+ // There are shutdown cases where we will attempt to release objects
+ // which no longer exist in the 16-bit world
+ // According to CraigWi, in 16-bit OLE objects which had an
+ // external reference were not cleaned up in CoUninitialize,
+ // while in 32-bit OLE things are always cleaned up. This
+ // means that apps which are leaking objects with external locks
+ // (Word can in some situations) get Releases that they do not
+ // expect, so protect against calling invalid objects
+ if (!IsValidInterface(punk))
+ {
+ thkDebugOut((DEB_ERROR, "QueryInterface16(%p) - Object invalid\n",
+ punk));
+ return (DWORD)E_UNEXPECTED;
+ }
+
+ thkDebugOut((DEB_THUNKMGR, "In QueryInterface16(%p, %p, %p)\n",
+ punk, &riid, ppv));
+
+ dwRet = (DWORD)punk->QueryInterface(riid, ppv);
+
+ // There are some apps (Works is one) that return an IOleItemContainer
+ // as an IOleContainer but neglect to respond to IOleContainer
+ // in their QueryInterface implementations
+ // In that event, retry with IOleItemContainer. This is legal
+ // to return as an IOleContainer since IOleItemContainer is
+ // derived from IOleContainer
+
+ // There are other derivation cases in the same vein
+
+ if (dwRet == (DWORD)E_NOINTERFACE)
+ {
+ if (IsEqualIID(riid, IID_IOleContainer))
+ {
+ // Works has this problem
+
+ dwRet = (DWORD)punk->QueryInterface(IID_IOleItemContainer, ppv);
+ }
+ else if (IsEqualIID(riid, IID_IPersist))
+ {
+ // According to the OLE 2.01 16-bit sources, Corel PhotoPaint
+ // supports IPersistStorage but not IPersist. Try all persist
+ // combinations.
+
+ dwRet = (DWORD)punk->QueryInterface(IID_IPersistStorage, ppv);
+ if (dwRet == (DWORD)E_NOINTERFACE)
+ {
+ dwRet = (DWORD)punk->QueryInterface(IID_IPersistFile, ppv);
+ if (dwRet == (DWORD)E_NOINTERFACE)
+ {
+ dwRet = (DWORD)punk->QueryInterface(IID_IPersistStream,
+ ppv);
+ }
+ }
+ }
+ }
+
+ thkDebugOut((DEB_THUNKMGR,
+ " >>IUnknowObj16:QueryInterface (%p):0x%08lx\n",
+ *ppv, dwRet));
+
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: AddRef16, public
+//
+// Synopsis: Calls AddRef on behalf of the 32-bit code
+//
+// Arguments: [punk] - Object
+//
+// Returns: 16-bit call return
+//
+// History: 07-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD __loadds FAR PASCAL AddRef16(IUnknown *punk)
+{
+ // There are shutdown cases where we will attempt to release objects
+ // which no longer exist in the 16-bit world
+ // According to CraigWi, in 16-bit OLE objects which had an
+ // external reference were not cleaned up in CoUninitialize,
+ // while in 32-bit OLE things are always cleaned up. This
+ // means that apps which are leaking objects with external locks
+ // (Word can in some situations) get Releases that they do not
+ // expect, so protect against calling invalid objects
+ if (!IsValidInterface(punk))
+ {
+ thkDebugOut((DEB_ERROR, "AddRef16(%p) - Object invalid\n", punk));
+ return 0;
+ }
+
+ return punk->AddRef();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Release16, public
+//
+// Synopsis: Calls Release on behalf of the 32-bit code
+//
+// Arguments: [punk] - Object
+//
+// Returns: 16-bit call return
+//
+// History: 07-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD __loadds FAR PASCAL Release16(IUnknown *punk)
+{
+ // There are shutdown cases where we will attempt to release objects
+ // which no longer exist in the 16-bit world
+ // According to CraigWi, in 16-bit OLE objects which had an
+ // external reference were not cleaned up in CoUninitialize,
+ // while in 32-bit OLE things are always cleaned up. This
+ // means that apps which are leaking objects with external locks
+ // (Word can in some situations) get Releases that they do not
+ // expect, so protect against calling invalid objects
+ if (!IsValidInterface(punk))
+ {
+ thkDebugOut((DEB_ERROR, "Release16(%p) - Object invalid\n", punk));
+ return 0;
+ }
+
+ return punk->Release();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReleaseStgMedium16, public
+//
+// Synopsis: Calls ReleaseStgMedium
+//
+// Arguments: [psm] - STGMEDIUM
+//
+// Returns: Appropriate status code
+//
+// History: 25-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD __loadds FAR PASCAL ReleaseStgMedium16(STGMEDIUM FAR *psm)
+{
+ ReleaseStgMedium(psm);
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSm16ReleaseHandler routines, public
+//
+// Synopsis: Method implementations for CSm16ReleaseHandler
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) Sm16RhAddRef(CSm16ReleaseHandler FAR *psrh)
+{
+ return ++psrh->_cReferences;
+}
+
+STDMETHODIMP Sm16RhQI(CSm16ReleaseHandler FAR *psrh,
+ REFIID riid,
+ void FAR * FAR *ppv)
+{
+ if ( IsEqualIID(riid,IID_IUnknown) )
+ {
+ *ppv = psrh;
+ Sm16RhAddRef(psrh);
+ return NOERROR;
+ }
+ else
+ {
+ *ppv = NULL;
+ return ResultFromScode(E_NOINTERFACE);
+ }
+}
+
+STDMETHODIMP_(ULONG) Sm16RhRelease(CSm16ReleaseHandler FAR *psrh)
+{
+ STGMEDIUM *psm;
+ METAFILEPICT *pmfp;
+ HGLOBAL hg;
+
+ if (--psrh->_cReferences != 0)
+ {
+ return psrh->_cReferences;
+ }
+
+ psm = &psrh->_sm16;
+ switch(psm->tymed)
+ {
+ case TYMED_HGLOBAL:
+ // Don't free this because copyback needs to occur in the
+ // 32-bit world
+ break;
+
+ case TYMED_MFPICT:
+#ifndef _CHICAGO_
+ // Win95 thunking shares HMETAFILEs between 16/32 so we don't
+ // need to clean up our copy
+ pmfp = (METAFILEPICT *)GlobalLock(psm->hGlobal);
+ DeleteMetaFile(pmfp->hMF);
+ GlobalUnlock(psm->hGlobal);
+#endif
+ GlobalFree(psm->hGlobal);
+ break;
+
+ case TYMED_FILE:
+ case TYMED_ISTREAM:
+ case TYMED_ISTORAGE:
+ // Handled by ReleaseStgMedium
+ // 32-bit name handled by 32-bit part of processing
+ break;
+
+ case TYMED_GDI:
+ case TYMED_NULL:
+ // Nothing to release
+ break;
+
+ default:
+ thkAssert(!"Unknown tymed in CSm16ReleaseHandler::Release");
+ break;
+ }
+
+ // Continue call in 32-bits where 32-bit task allocations
+ // and other 32-bit objects are cleaned up
+ CallProcIn32( (DWORD)psrh, 0, 0,
+ pfnCSm16ReleaseHandler_Release32, (1 << 2), CP32_NARGS);
+
+ // Call Release through proxy
+ ((IUnknown *)psrh->_vpvUnkForRelease)->Release();
+
+ // Clean up this
+ hg = LOWORD(GlobalHandle(HIWORD((unsigned long)psrh)));
+ GlobalUnlock(hg);
+ GlobalFree(hg);
+
+ return 0;
+}
+
+DWORD Sm16RhVtbl[SMI_COUNT] =
+{
+ (DWORD)Sm16RhQI,
+ (DWORD)Sm16RhAddRef,
+ (DWORD)Sm16RhRelease
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgMediumStreamHandler16
+//
+// Synopsis: Copies one stream to another
+//
+// Effects: Turns out that Excel does the wrong thing with STGMEDIUM's
+// when its GetDataHere() method is called. Instead of using
+// the provided stream, like it was supposed to, it creates its
+// own stream, and smashes the passed in streams pointer. This
+// appears to be happening on the Clipboard object for Excel.
+// To fix this, the thop function for STGMEDIUM input is going to
+// watch for changes to the stream pointer. If it changes, then
+// the 'app' (excel) has done something wrong.
+//
+// To recover from this, the thop will call this routine passing
+// the bogus stream and the stream that was supposed to be used.
+// This routine will do a pstmFrom->CopyTo(pstmTo), and then
+// release the 'bogus' stream pointer.
+//
+// Arguments: [pstmFrom] -- Stream to copy then release
+// [pstmTo] -- Destination stream
+//
+// History: 7-07-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD __loadds FAR PASCAL StgMediumStreamHandler16(IStream FAR *pstmFrom,
+ IStream FAR *pstmTo)
+{
+ HRESULT hresult;
+ LARGE_INTEGER li;
+ ULARGE_INTEGER uli;
+ ULONG ul;
+
+ thkDebugOut((DEB_ITRACE,
+ "*** StgMediumStreamHandler16(pstmFrom=%p,pstmTo=%p)\n",
+ pstmFrom,pstmTo));
+
+ //
+ // Assume that the entire stream is the data set to be copied.
+ // Seek to the start of the stream
+ //
+ ULISet32(li,0);
+ hresult = pstmFrom->Seek(li,STREAM_SEEK_SET,NULL);
+ if (hresult != NOERROR)
+ {
+ thkDebugOut((DEB_ITRACE,
+ "StgMediumStreamHandler16 failed on seek %lx\n",hresult));
+ goto exitRtn;
+ }
+
+ //
+ // To copy the entire stream, specify the maximum size possible.
+ //
+ uli.LowPart = -1;
+ uli.HighPart = -1;
+ hresult = pstmFrom->CopyTo(pstmTo,uli,NULL,NULL);
+ if (hresult != NOERROR)
+ {
+ thkDebugOut((DEB_ITRACE,
+ "StgMediumStreamHandler16 failed CopyTo %lx\n",hresult));
+ goto exitRtn;
+ }
+
+exitRtn:
+ //
+ // In all cases, it is proper to release the pstmFrom, since we didn't
+ // want it on the 32-bit side at all.
+ //
+
+ ul = pstmFrom->Release();
+
+
+ if (ul != 0)
+ {
+ //
+ // Whoops, we expected this stream pointer to go to zero. We can
+ // only print a message, then let it leak.
+ //
+ thkDebugOut((DEB_ITRACE,
+ "StgMediumStreamHandler16() Stream not released. ref=%lx\n",ul));
+ }
+
+ thkDebugOut((DEB_ITRACE,
+ "*** StgMediumStreamHandler16(pstmFrom=%p,pstmTo=%p) returns %lx\n",
+ pstmFrom,pstmTo,hresult));
+
+ return((DWORD)hresult);
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TouchPointer16, public
+//
+// Synopsis: Touches a byte at the given pointer's address to
+// bring in not-present segments
+//
+// Arguments: [pb] - Pointer
+//
+// History: 25-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD __loadds FAR PASCAL TouchPointer16(BYTE FAR *pb)
+{
+ BYTE b = 0;
+
+ if (pb)
+ {
+ b = *pb;
+ }
+
+#ifdef _CHICAGO_
+ // On Win95, fix the memory block before returning to 32-bit code
+ // to lock the segment in place. If we tried to do this in 32-bit
+ // code we could be preempted before we successfully lock the memory
+ GlobalFix(LOWORD(HIWORD((DWORD)pb)));
+#endif
+
+ return b;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetOwnerPublic16, public
+//
+// Synopsis: Sets a given 16-bit memory handle to be owned by nobody
+// (everybody)
+//
+// Arguments: [hmem] - 16-bit memory handle
+//
+// History: 13-Jul-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+extern "C" void FAR PASCAL KERNEL_SetOwner( WORD hMem16, WORD wOwner );
+
+DWORD __loadds FAR PASCAL SetOwnerPublic16(DWORD hmem)
+{
+ KERNEL_SetOwner( (WORD)hmem, (WORD)-1 );
+
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WinExec16, public
+//
+// Synopsis: Routine to run an application on behalf of ole32.dll
+//
+// Arguments: [lpwes] - WinExec16 struct full of needed goodies
+//
+// Returns:
+//
+// History: 27-Jul-94 AlexT Created
+//
+//----------------------------------------------------------------------------
+
+ULONG __loadds FAR PASCAL WinExec16( LPWINEXEC16STRUCT lpwes )
+{
+ ULONG ulResult;
+
+ thkDebugOut((DEB_ITRACE, "WinExec16(%s, %d)\n",
+ lpwes->vpCommandLine, lpwes->vusShow));
+
+ ulResult = (ULONG) WinExec((LPSTR)lpwes->vpCommandLine,
+ (UINT)lpwes->vusShow);
+ thkDebugOut((DEB_ITRACE, "WinExec returned %ld\n", ulResult));
+
+ return ulResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertHr1632, public
+//
+// Synopsis: Converts a 16-bit HRESULT into a 32-bit HRESULT
+//
+// Arguments: [hr] - 16-bit HRESULT
+//
+// Returns: Appropriate status code
+//
+// History: 26-Sep-94 DrewB Created
+//
+// Notes: Delegates to 32-bit functions
+//
+//----------------------------------------------------------------------------
+
+STDAPI ConvertHr1632(HRESULT hr)
+{
+ return (HRESULT)CallProcIn32( (DWORD)hr, 0, 0,
+ pfnConvertHr1632, 0, CP32_NARGS);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertHr3216, public
+//
+// Synopsis: Converts a 32-bit HRESULT into a 16-bit HRESULT
+//
+// Arguments: [hr] - 32-bit HRESULT
+//
+// Returns: Appropriate status code
+//
+// History: 26-Sep-94 DrewB Created
+//
+// Notes: Delegates to 32-bit functions
+//
+//----------------------------------------------------------------------------
+
+STDAPI ConvertHr3216(HRESULT hr)
+{
+ return (HRESULT)CallProcIn32( (DWORD)hr, 0, 0,
+ pfnConvertHr3216, 0, CP32_NARGS);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SSCallProc32, public
+//
+// Synopsis: Wrapper for CallProc32W which switches to a bigger stack
+//
+// Arguments: [dw1] - argumensts similar to CallProc32W
+// [dw2]
+// [dw3]
+// [pfn32]
+// [dwPtrTranslate]
+// [dwArgCount]
+//
+// Returns: 32-bit call result
+//
+// History: 5-Dec-94 JohannP Created
+//
+// Note: this will be enabled as soon as I get the CallProc32WFix from
+// Win95
+//----------------------------------------------------------------------------
+#ifdef _STACKSWITCHON16_
+DWORD FAR PASCAL SSCallProc32(DWORD dw1, DWORD dw2, DWORD dw3,
+ LPVOID pfn32, DWORD dwPtrTranslate,
+ DWORD dwArgCount)
+{
+ DWORD dwRet = 0;
+ // switch to the 32 bit stack
+ //
+ // return SSCall(24,SSF_BigStack, (LPVOID)CallProc32W, dw1, dw2, dw3, pfn32, dwPtrTranslate, dwArgCount);
+ thkDebugOut((DEB_ERROR, "SSCallProc32(dwArgCount:%x, dwPtrTranslate:%x, pfn32:%x, dw3:%x, dw2:%x, dw1:%x)\n",
+ dwArgCount, dwPtrTranslate, pfn32, dw3, dw2, dw1));
+#if DBG == 1
+ if (fSSOn)
+ {
+ dwRet = SSCall(24,SSF_BigStack, (LPVOID)CallProc32WFix, dwArgCount, dwPtrTranslate, pfn32, dw3, dw2, dw1);
+ }
+ else
+#endif // DBG==1
+ {
+ dwRet = CallProc32W(dw1, dw2, dw3, pfn32, dwPtrTranslate, dwArgCount);
+ }
+
+ return dwRet;
+}
+#endif // _STACKSWITCHON16_
+
+//+-------------------------------------------------------------------------
+//
+// Function: AddAppCompatFlag
+//
+// Synopsis: calls into olethk32 to add an app compability flag.
+//
+// Effects:
+//
+// Arguments: [dwFlag] -- the flag to add
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Mar-95 alexgo author
+//
+// Notes: this function is exported so that ole2.dll can also call it
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(void) AddAppCompatFlag( DWORD dwFlag )
+{
+ CallProcIn32( (DWORD)dwFlag, 0, 0,
+ pfnThkAddAppCompatFlag, 0, CP32_NARGS);
+}
+
+
+
+
+
+
+
diff --git a/private/ole32/olethunk/ole16/compobj/clstub16.cxx b/private/ole32/olethunk/ole16/compobj/clstub16.cxx
new file mode 100644
index 000000000..8af78910b
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/clstub16.cxx
@@ -0,0 +1,109 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: clstub16.cxx
+//
+// Contents: 32->16 bit call forwarding stub
+//
+// History: 25-Feb-93 DrewB Created
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+//+---------------------------------------------------------------------------
+//
+// Function: CallStub16, public
+//
+// Synopsis: Invokes a 16-bit routine on behalf of the 32-bit code
+//
+// Arguments: [pcd] - Data describing the call to be made
+//
+// Returns: Appropriate status code
+//
+// History: 18-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD __loadds FAR PASCAL CallStub16(LPCALLDATA pcd)
+{
+ DWORD dwRes;
+ DWORD pfn;
+ WORD cbStack;
+ DWORD pvStack;
+
+ thkAssert(pcd != NULL);
+
+ pfn = pcd->vpfn;
+ cbStack = (WORD)pcd->cbStack;
+ pvStack = pcd->vpvStack16;
+
+ thkDebugOut((DEB_ITRACE, "In CallStub16(%08lX, %u, %08lX)\n",
+ pfn, cbStack, pvStack));
+
+ // Check for wildly out-of-range stack sizes
+ thkAssert(cbStack < 0x100);
+
+ // Make sure that the stack size is even to
+ // maintain alignment and allow free use of movsw
+ thkAssert((cbStack & 1) == 0);
+
+ __asm
+ {
+ // Make space on the real stack for the stack given to us from 32-bits
+ sub sp, cbStack
+
+ // Simple sanity checks on new stack pointer
+ jc StackOverflow
+ cmp sp, 512
+ jb StackOverflow
+
+ // Copy pvStack to the real stack
+ push ds
+ push si
+ push es
+ push di
+
+ mov ds, WORD PTR pvStack+2
+ mov si, WORD PTR pvStack
+
+ mov ax, ss
+ mov es, ax
+ mov di, sp
+ // Skip over saved registers
+ add di, 8
+
+ mov cx, cbStack
+ shr cx, 1
+ cld
+ rep movsw
+
+ pop di
+ pop es
+ pop si
+ pop ds
+
+ // Call the routine
+ call DWORD PTR pfn
+
+ jmp End
+
+ StackOverflow:
+ // E_OUTOFMEMORY
+ mov dx, 8000h
+ mov ax, 0002h
+
+ End:
+ mov WORD PTR dwRes, ax
+ mov WORD PTR dwRes+2, dx
+
+ add sp, cbStack
+ }
+
+ thkDebugOut((DEB_ITRACE, "Out CallStub16: return %ld\n",dwRes));
+
+ return dwRes;
+}
diff --git a/private/ole32/olethunk/ole16/compobj/comdthk.c b/private/ole32/olethunk/ole16/compobj/comdthk.c
new file mode 100644
index 000000000..b57c317f9
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/comdthk.c
@@ -0,0 +1,800 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: Comdthk.c (16 bit target)
+//
+// Contents: CompObj Directly Thunked APIs
+//
+// Functions:
+//
+// History: 16-Dec-93 JohannP Created
+// 07-Mar-94 BobDay Moved into COMTHUNK.C from COMAPI.CXX
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <call32.hxx>
+#include <apilist.hxx>
+
+STDAPI_(BOOL) GUIDFromString(LPCSTR lpsz, LPGUID pguid);
+
+//+---------------------------------------------------------------------------
+//
+// Function: Straight thunk routines
+//
+// Synopsis: The following routines do not need to do any special
+// processing on the 16-bit side so they thunk straight
+// through
+//
+// History: 18-Feb-94 JohannP Created
+//
+// Notes: BUGBUG - Review to ensure these don't have to do any work
+//
+//----------------------------------------------------------------------------
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLSIDFromString, Remote
+//
+// History: Straight from OLE2 sources
+//
+//----------------------------------------------------------------------------
+STDAPI CLSIDFromString(LPSTR lpsz, LPCLSID pclsid)
+{
+ HRESULT hr;
+
+ thkDebugOut((DEB_ITRACE, "CLSIDFromString\n"));
+
+ //
+ // The 16-bit OLE2 application "Family Tree Maker" always passes a bad
+ // string to CLSIDFromString. We need to make sure we fail in the exact
+ // same way with the interop layer. This will also provide a speed
+ // improvement since we only need to remote to the 32bit version of
+ // CLSIDFromString when the string provided does not start with '{'.
+ //
+ if (lpsz[0] == '{')
+ return GUIDFromString(lpsz, pclsid)
+ ? NOERROR : ResultFromScode(CO_E_CLASSSTRING);
+
+ // Note: Corel calls this function prior to calling
+ // CoInitialize so use CheckInit
+
+ return (HRESULT)CallObjectInWOWCheckInit(THK_API_METHOD(THK_API_CLSIDFromString),
+ PASCAL_STACK_PTR(lpsz));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoGetClassObject, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [rclsid] --
+// [dwClsContext] --
+// [pvReserved] --
+// [riid] --
+// [ppv] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoGetClassObject(REFCLSID rclsid, DWORD dwClsContext, LPVOID pvReserved,
+ REFIID riid, LPVOID FAR* ppv)
+{
+ thkDebugOut((DEB_ITRACE, " CoGetClassObject\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoGetClassObject),
+ PASCAL_STACK_PTR(rclsid) );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoRegisterClassObject, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [rclsid] --
+// [pUnk] --
+// [dwClsContext] --
+// [flags] --
+// [lpdwRegister] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoRegisterClassObject(REFCLSID rclsid, LPUNKNOWN pUnk,
+ DWORD dwClsContext, DWORD flags,
+ LPDWORD lpdwRegister)
+{
+ thkDebugOut((DEB_ITRACE, " CoRegisterClassObject\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoRegisterClassObject),
+ PASCAL_STACK_PTR(rclsid));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoRevokeClassObject, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [dwRegister] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoRevokeClassObject(DWORD dwRegister)
+{
+ thkDebugOut((DEB_ITRACE, " CoRevokeClassObject\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoRevokeClassObject),
+ PASCAL_STACK_PTR(dwRegister) );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoMarshalInterface, Unknown
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pStm] --
+// [riid] --
+// [pUnk] --
+// [dwDestContext] --
+// [pvDestContext] --
+// [mshlflags] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoMarshalInterface(LPSTREAM pStm, REFIID riid, LPUNKNOWN pUnk,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ thkDebugOut((DEB_ITRACE, " CoMarshalInterface\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoMarshalInterface),
+ PASCAL_STACK_PTR(pStm));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoUnmarshalInterface, Unknown
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pStm] --
+// [riid] --
+// [ppv] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoUnmarshalInterface(LPSTREAM pStm, REFIID riid, LPVOID FAR* ppv)
+{
+ thkDebugOut((DEB_ITRACE, "CoUnmarshalInterface\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoUnmarshalInterface),
+ PASCAL_STACK_PTR(pStm));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoReleaseMarshalData, Unknown
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pStm] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoReleaseMarshalData(LPSTREAM pStm)
+{
+ thkDebugOut((DEB_ITRACE, "CoReleaseMarshalData\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoReleaseMarshalData),
+ PASCAL_STACK_PTR(pStm));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoDisconnectObject, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pUnk] --
+// [dwReserved] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoDisconnectObject(LPUNKNOWN pUnk, DWORD dwReserved)
+{
+ thkDebugOut((DEB_ITRACE, "CoDisconnectObject\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoDisconnectObject),
+ PASCAL_STACK_PTR(pUnk));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoLockObjectExternal, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pUnk] --
+// [fLock] --
+// [fLastUnlockReleases] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoLockObjectExternal(LPUNKNOWN pUnk, BOOL fLock,
+ BOOL fLastUnlockReleases)
+{
+ thkDebugOut((DEB_ITRACE, "CoLockObjectExternal\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoLockObjectExternal),
+ PASCAL_STACK_PTR(pUnk));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoGetStandardMarshal, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [riid] --
+// [pUnk] --
+// [dwDestContext] --
+// [pvDestContext] --
+// [mshlflags] --
+// [ppMarshal] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoGetStandardMarshal(REFIID riid, LPUNKNOWN pUnk,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPMARSHAL FAR* ppMarshal)
+{
+ thkDebugOut((DEB_ITRACE, "CoGetStandardMarshal\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoGetStandardMarshal),
+ PASCAL_STACK_PTR(riid));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoIsHandlerConnected, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pUnk] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(BOOL) CoIsHandlerConnected(LPUNKNOWN pUnk)
+{
+ thkDebugOut((DEB_ITRACE, "CoIsHandlerConnected\n"));
+ return (BOOL)CallObjectInWOW(THK_API_METHOD(THK_API_CoIsHandlerConnected),
+ PASCAL_STACK_PTR(pUnk));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoCreateInstance, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [rclsid] --
+// [pUnkOuter] --
+// [dwClsContext] --
+// [riid] --
+// [ppv] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
+ DWORD dwClsContext, REFIID riid, LPVOID FAR* ppv)
+{
+ thkDebugOut((DEB_ITRACE, "CoCreateInstance\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoCreateInstance),
+ PASCAL_STACK_PTR(rclsid) );
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoIsOle1Class, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [rclsid] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(BOOL) CoIsOle1Class(REFCLSID rclsid)
+{
+ thkDebugOut((DEB_ITRACE, "CoIsOle1Class\n"));
+ return (BOOL)CallObjectInWOW(THK_API_METHOD(THK_API_CoIsOle1Class),
+ PASCAL_STACK_PTR(rclsid) );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ProgIDFromCLSID, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [clsid] --
+// [lplpszProgID] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI ProgIDFromCLSID(REFCLSID clsid, LPSTR FAR* lplpszProgID)
+{
+ thkDebugOut((DEB_ITRACE, "ProgIDFromCLSID\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_ProgIDFromCLSID),
+ PASCAL_STACK_PTR(clsid) );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLSIDFromProgID, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [lpszProgID] --
+// [lpclsid] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CLSIDFromProgID(LPCSTR lpszProgID, LPCLSID lpclsid)
+{
+ thkDebugOut((DEB_ITRACE, "CLSIDFromProgID\n"));
+
+ // Note: Word 6 calls this function prior to calling
+ // CoInitialize so use CheckInit
+
+ return (HRESULT)CallObjectInWOWCheckInit(THK_API_METHOD(THK_API_CLSIDFromProgID),
+ PASCAL_STACK_PTR(lpszProgID) );
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoCreateGuid, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pguid] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoCreateGuid(GUID FAR *pguid)
+{
+ thkDebugOut((DEB_ITRACE, "CoCreateGuid\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoCreateGuid),
+ PASCAL_STACK_PTR(pguid));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoFileTimeToDosDateTime, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [lpFileTime] --
+// [lpDosDate] --
+// [lpDosTime] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(BOOL) CoFileTimeToDosDateTime(FILETIME FAR* lpFileTime,
+ LPWORD lpDosDate, LPWORD lpDosTime)
+{
+ thkDebugOut((DEB_ITRACE, "CoFileTimeToDosDateTime\n"));
+ return (BOOL)CallObjectInWOW(THK_API_METHOD(THK_API_CoFileTimeToDosDateTime),
+ PASCAL_STACK_PTR(lpFileTime));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoDosDateTimeToFileTime, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [nDosDate] --
+// [nDosTime] --
+// [lpFileTime] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(BOOL) CoDosDateTimeToFileTime(WORD nDosDate, WORD nDosTime,
+ FILETIME FAR* lpFileTime)
+{
+ thkDebugOut((DEB_ITRACE, "CoDosDateTimeToFileTime\n"));
+ return (BOOL)CallObjectInWOW(THK_API_METHOD(THK_API_CoDosDateTimeToFileTime),
+ PASCAL_STACK_PTR(nDosDate));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoFileTimeNow, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [lpFileTime] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoFileTimeNow(FILETIME FAR* lpFileTime)
+{
+ thkDebugOut((DEB_ITRACE, "CoFileTimeNow\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoFileTimeNow),
+ PASCAL_STACK_PTR(lpFileTime));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoRegisterMessageFilter, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [lpMessageFilter] --
+// [lplpMessageFilter] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoRegisterMessageFilter(LPMESSAGEFILTER lpMessageFilter,
+ LPMESSAGEFILTER FAR* lplpMessageFilter)
+{
+ thkDebugOut((DEB_ITRACE, "CoRegisterMessageFilter\n"));
+
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoRegisterMessageFilter),
+ PASCAL_STACK_PTR(lpMessageFilter) );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoGetTreatAsClass, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [clsidOld] --
+// [pClsidNew] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID pClsidNew)
+{
+ thkDebugOut((DEB_ITRACE, "CoGetTreatAsClass\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoGetTreatAsClass),
+ PASCAL_STACK_PTR(clsidOld) );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoTreatAsClass, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [clsidOld] --
+// [clsidNew] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew)
+{
+ thkDebugOut((DEB_ITRACE, "CoTreatAsClass\n"));
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoTreatAsClass),
+ PASCAL_STACK_PTR(clsidOld) );
+}
diff --git a/private/ole32/olethunk/ole16/compobj/comguid.cxx b/private/ole32/olethunk/ole16/compobj/comguid.cxx
new file mode 100644
index 000000000..488bf1000
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/comguid.cxx
@@ -0,0 +1,20 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ComGUID.cxx (16 bit target)
+//
+// Contents: GUIDs for CompObj
+//
+// Functions:
+//
+// History: 17-Dec-93 JohannP Created
+//
+//--------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include "initguid.h"
+#include "coguid.h"
diff --git a/private/ole32/olethunk/ole16/compobj/comlocal.cxx b/private/ole32/olethunk/ole16/compobj/comlocal.cxx
new file mode 100644
index 000000000..2c4f0714a
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/comlocal.cxx
@@ -0,0 +1,1276 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: COMLOCAL.CXX (16 bit target)
+//
+// Contents: CompObj APIs
+//
+// Functions:
+//
+// History: 16-Dec-93 JohannP Created
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <ole2ver.h>
+
+#include <ole2sp.h>
+
+#include <olecoll.h>
+#include <map_kv.h>
+
+#include "comlocal.hxx"
+#include "map_htsk.h"
+#include "etask.hxx"
+
+#include "call32.hxx"
+#include "apilist.hxx"
+
+UINT v_pidHighWord = 1; // incremented each time used
+IMalloc FAR* v_pMallocShared = NULL; // is not addrefed
+
+// Note: bug 3698
+// MsPub is not calling CoInitialize befor calling OpenStorage to
+// preview templates. This pointer has an addref!
+// When this pointer is not NULL CoGetMalloc was called prior to CoInitialize
+// The pointer is transfered as soon as CoInitialize is called by any task.
+IMalloc FAR* v_pMallocPreShared = NULL;
+BOOL SetupSharedAllocator(Etask FAR& etask);
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: TaskAlloc, private
+//
+// Synopsis: Allocates task memory
+//
+// Arguments: [cb] - Number of bytes to allocate
+//
+// Returns: Pointer to memory or NULL
+//
+// History: 03-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+LPVOID __loadds FAR PASCAL TaskAlloc(ULONG cb)
+{
+ HRESULT hr;
+ LPMALLOC lpMalloc = NULL;
+ LPVOID lpv;
+
+ hr = CoGetMalloc(MEMCTX_TASK, &lpMalloc);
+ if (FAILED(GetScode(hr)) )
+ {
+ lpv = NULL;
+ }
+ else
+ {
+ thkAssert(lpMalloc != NULL && "CoGetMalloc pMalloce is NULL\n");
+ lpv = lpMalloc->Alloc(cb);
+ lpMalloc->Release();
+ }
+
+ return lpv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TaskFree, private
+//
+// Synopsis: Free task memory
+//
+// Arguments: [pv] - Memory
+//
+// History: 03-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void __loadds FAR PASCAL TaskFree(LPVOID pv)
+{
+ HRESULT hr;
+ LPMALLOC lpMalloc;
+
+ hr = CoGetMalloc(MEMCTX_TASK, &lpMalloc);
+ if (SUCCEEDED(GetScode(hr)))
+ {
+ lpMalloc->Free(pv);
+ lpMalloc->Release();
+ }
+}
+
+
+#if defined(_CHICAGO_)
+//+---------------------------------------------------------------------------
+//
+// Function: IsProcessIn32Context, private
+//
+// Synopsis: Returns true if current process is 32-bits.
+//
+// Arguments: None.
+//
+// History: 03-Jan-95 KentCe Created
+//
+// Remarks: This function takes advantage of internal Chicago data
+// structures. No other method available.
+//
+//----------------------------------------------------------------------------
+
+BOOL IsProcessIn32Context(void)
+{
+ LPBYTE pTaskFlag;
+
+
+ //
+ // Create a pointer to the 0x16 byte of the task structure.
+ //
+ pTaskFlag = (LPBYTE)MAKELONG(0x16, GetCurrentTask());
+
+ //
+ // Bit 4 (0x10) is only true when we are a 32-bit process.
+ //
+ if (*pTaskFlag & 0x10)
+ return TRUE;
+
+ return FALSE;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Method: SetupSharedAllocator
+//
+// Synopsis: Allocats the shared allocator and
+// initializes the etask shared allocator
+//
+// Arguments: [etask] --
+//
+// Returns:
+//
+// History: 2-03-95 JohannP (Johann Posch) Created
+//
+// Notes: call by CoInitialize and DllEntryPoint
+//
+//----------------------------------------------------------------------------
+BOOL SetupSharedAllocator(Etask FAR& etask)
+{
+ // we must ensure we have a shared allocator now since that is where the
+ // etask map wiil be stored; if another process already created it, use it;
+ // this is so we always use the same shared pool of memory for all
+ // processes (so the DidAlloc method returns 1 for the same call from
+ // different process); the pointer refers to shared memory within
+ // the blocks managed by the IMalloc implementation and the
+ // vtable is always valid on Windows; the global pointer carries
+ // no ref count on its own; changes might be requires on
+ // other platforms.
+ if (v_pMallocPreShared != NULL)
+ {
+ // Note: fix for bug 3698;l MsPub not calling CoInitialize
+ // transfer addref from preshared to task entry
+ etask.m_pMallocShared = v_pMallocPreShared;
+ v_pMallocShared = v_pMallocPreShared;
+ v_pMallocPreShared = NULL;
+ }
+ else if (v_pMallocShared != NULL)
+ {
+ (etask.m_pMallocShared = v_pMallocShared)->AddRef();
+ }
+ else
+ {
+ // sets pMalloc to NULL on error
+ CoCreateStandardMalloc(MEMCTX_SHARED, &etask.m_pMallocShared);
+ v_pMallocShared = etask.m_pMallocShared;
+ thkAssert(v_pMallocShared != NULL && "SetupSharedAllocator failed!");
+ }
+ return (v_pMallocShared != NULL) ? TRUE : FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoInitialize, Split
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pMalloc] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+// 3-08-94 BobDay Added code from \\ole\slm\...\compobj.cpp
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+// initialize compobj; errors: S_FALSE, E_OUTOFMEMORY
+STDAPI CoInitialize(IMalloc FAR* pMalloc)
+{
+ LPMALLOC pmlNull = NULL;
+ HRESULT hresult;
+ HTASK htask;
+ Etask etask;
+
+ thkDebugOut((DEB_ITRACE, "CoInitialize\n"));
+ thkDebugOut((DEB_APIS16, "CoInitilaize called on Process (%X) \n", GetCurrentProcess()));
+
+#if defined(_CHICAGO_)
+ //
+ // Prevent 32-bit MPLAYER from loading a 16-bit DLL's which in turns
+ // uses 16-bit OLE2. We can't handle the condition of a 32-bit process
+ // thunking up thru the 16:32 OLE2 interop layer. So return an error
+ // and not fault out.
+ //
+ if (IsProcessIn32Context())
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ etask.m_Dllinits = 0;
+#endif
+
+
+ // if already init, bump count and return S_FALSE
+ if ( IsEtaskInit(htask, etask)
+ && IsValidInterface((etask.m_pMalloc)) )
+ {
+ if ( etask.m_inits != ETASK_FAKE_INIT )
+ {
+ etask.m_inits++;
+ thkVerify(SetEtask(htask, etask));
+ return ResultFromScode(S_FALSE);
+ }
+
+ //
+ // CoInitialize has been called after we've done a fake call for them
+ // we can just take over their allocator and get rid of our fake one.
+ //
+
+ if ( pMalloc != NULL )
+ {
+ etask.m_pMalloc->Release(); // Get rid of the old task allocator
+ etask.m_pMalloc = pMalloc;
+ etask.m_pMalloc->AddRef();
+ }
+ else
+ {
+ //
+ // It would be nice if we could assert that the fake task
+ // allocator was a default task allocator. i.e. no operation
+ // were really needed!
+ //
+ }
+
+ //
+ // BUGBUG - We need to have a way to clean up any fake calls to
+ // CoInitialize. Should the application go away after using one of
+ // the apis that caused us to do a fake CoInitialize in the first
+ // place, and should the application exit without really making a
+ // call to CoInitialize eventually, then we wouldn't know enough to
+ // clean up... I think this is ok for now. Most apps do call
+ // CoInitialize eventually.
+ //
+ etask.m_inits = 1;
+
+ thkAssert(etask.m_pMalloc != NULL); // now have task allocator in all cases
+ thkVerify(SetEtask(htask, etask));
+ return ResultFromScode(S_OK);
+ }
+#ifdef _CHICAGO_
+ else if (etask.m_Dllinits == 0)
+ {
+ // Note: we might end up here since some app call
+ // CoInitialize in LibMain. The call to our DllEntryPoint
+ // will follow.
+ if (!Call32Initialize())
+ {
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+ etask.m_htask = GetCurrentProcess();
+ }
+#endif
+ // set/create task malloc
+ if (pMalloc != NULL)
+ {
+ VDATEIFACE( pMalloc );
+ (etask.m_pMalloc = pMalloc)->AddRef();
+ }
+ else
+ {
+ if ((hresult = CoCreateStandardMalloc(MEMCTX_TASK,
+ &etask.m_pMalloc)) != NOERROR)
+ return hresult;
+ }
+ thkAssert(etask.m_pMalloc != NULL); // now have task allocator in all cases
+
+
+ // set up the shared allocator
+ if ( etask.m_pMallocShared == NULL
+ && SetupSharedAllocator(etask) == FALSE)
+ {
+ etask.m_pMalloc->Release(); // was created or AddRef'd above
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // now have shared allocator in all cases
+ thkAssert(etask.m_pMallocShared != NULL);
+
+ // init remaining entries and add entry to table for this app/task pair;
+ // leave maps null for now (they are allocated on demand)
+ etask.m_pMallocSBlock = NULL;
+ etask.m_pMallocPrivate = NULL;
+ etask.m_pid = MAKELONG(GetCurrentProcess(),v_pidHighWord++);
+ etask.m_inits = 1;
+ etask.m_oleinits = 0;
+ etask.m_reserved = 0;
+ etask.m_pDlls = NULL;
+ etask.m_pMapToServerCO = NULL;
+ etask.m_pMapToHandlerCO = NULL;
+ etask.m_pArraySH = NULL;
+ etask.m_pCThrd = NULL;
+ etask.m_hwndClip = NULL;
+ etask.m_hwndDde = NULL;
+ etask.m_punkState = NULL;
+
+ if (!SetEtask(htask, etask))
+ {
+ ReleaseEtask(NULL, etask);
+ thkAssert(0 && "CompObj: CoInitialize SetEtask failed.");
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ // Initialize the thunk manager for this apartment.
+ if (SUCCEEDED(hresult = CallThkMgrInitialize()))
+ {
+ //
+ // Now transition into 32-bit world to give it a chance for
+ // initialization at this time.
+ //
+ // Never pass the 16-bit allocator on to 32-bits
+ pMalloc = NULL;
+ hresult = (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoInitialize),
+ PASCAL_STACK_PTR(pMalloc) );
+ }
+
+ if (FAILED(GetScode(hresult)))
+ {
+ ReleaseEtask(htask, etask);
+ }
+
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoUninitialize, Split
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+// 10-Mar-94 BobDay Copied & Merged with compobj.cpp 16-bit
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(void) CoUninitialize(void)
+{
+ HTASK htask;
+ Etask etask;
+
+ thkDebugOut((DEB_ITRACE, "CoUninitialize\n"));
+ thkDebugOut((DEB_APIS16, "CoUninitilaize called on Process (%X) \n", GetCurrentProcess()));
+
+ if (!IsEtaskInit(htask, etask))
+ return;
+
+ // if not last uninit, just decrement count and return.
+ if (etask.m_inits != 1)
+ {
+ //
+ // If a fake init, then just ignore as if we haven't ever init'd
+ //
+ if ( etask.m_inits == ETASK_FAKE_INIT )
+ {
+ //
+ // Some slimy app doesn't call CoInitialize but does eventually
+ // call CoUninitialize. Lets find them if they do!
+ //
+ thkAssert(FALSE &&
+ "CoUninitialize called after fake CoInitialize\n");
+ }
+ else
+ {
+ etask.m_inits--;
+ thkVerify(SetEtask(htask, etask));
+ }
+ return ;
+ }
+
+//
+// BUGBUG - Do we need Rem in the 16-bit world?
+//
+#ifdef LATER
+ RemUninitialize();
+#endif
+
+//
+// BUGBUG - This needs to be done in the 32-bit world, in the CoUninitialize
+//
+#ifdef LATER
+ // free all class objects
+ ReleaseAllClassObjects();
+#endif
+
+ // Some applications pass on module handle of loaded dlls.
+ // As a result LibMain and WEP is not called in the same process.
+ // To prevent premature unloading of OleThk32.dll call
+ // SetReleaseDLL(FALSE)
+
+ SetReleaseDLL(FALSE);
+
+ //
+ // Now transition into 32-bit world to give it a chance for
+ // initialization at this time.
+ //
+ CallObjectInWOW(THK_API_METHOD(THK_API_CoUninitialize), NULL );
+
+ // Reset dll unloading - see above
+ SetReleaseDLL(TRUE);
+
+ CoFreeAllLibraries();
+
+ //
+ // We do not uninitialize the thunk manager at this point. The app may attempt
+ // to call additional API's after CoUninitialize. For example, Lotus 1-2-3
+ // is known to do this, as is Publisher. The thunk manager will clean up
+ // as part of its thread detach.
+ //
+
+ // the last thing is to remove the allocator and delete the etask for us;
+ // must lookup again in case contents changed.
+
+ if (LookupEtask(htask, etask))
+ ReleaseEtask(htask, etask);
+
+ thkDebugOut((DEB_APIS16, "CoUninitilaize on Process (%X) done.\n", GetCurrentProcess()));
+ thkDebugOut((DEB_ITRACE, "CoUninitialize exit\n"));
+
+ // Note: some apps check the return value if the void function CoUninitialize
+ // and they fail if it is not NULL like WinOffice Setup 4.3
+ // Please don't take it out.
+ _asm mov ax,0;
+ _asm mov dx,0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoGetMalloc, Local
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [dwMemContext] --
+// [ppMalloc] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+// 10-Mar-94 BobDay Copied & Merged with compobj.cpp 16-bit
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+// return pMalloc for the current task; errors: E_INVALIDARG,
+// CO_E_NOTINITIALIZED, E_OUTOFMEMORY (not for task or shared allocators)
+STDAPI CoGetMalloc(DWORD dwContext, IMalloc FAR* FAR* ppMalloc)
+{
+ Etask etask;
+ HTASK htask;
+
+ thkDebugOut((DEB_ITRACE, " CoGetMalloc\n"));
+
+ VDATEPTROUT( ppMalloc, IMalloc FAR* );
+ // NOTE: we set *ppMalloc to NULL only in the error cases below
+
+ // MOre work here!
+ // need this for the bootstrap case
+ if (dwContext == MEMCTX_SHARED)
+ {
+ if (v_pMallocShared != NULL)
+ {
+ *ppMalloc = v_pMallocShared;
+ goto Exit;
+ }
+ // pMallocShared is NULL -- CoInitialize was not called yet.
+ if (v_pMallocPreShared == NULL)
+ {
+ CoCreateStandardMalloc(MEMCTX_SHARED, &v_pMallocPreShared);
+ if (v_pMallocPreShared != NULL)
+ {
+ *ppMalloc = v_pMallocPreShared;
+ goto Exit;
+ }
+ else
+ {
+ *ppMalloc = NULL;
+ return ResultFromScode(CO_E_NOTINITIALIZED);
+ }
+ }
+ else
+ {
+ *ppMalloc = v_pMallocPreShared;
+ goto Exit;
+ }
+ }
+
+ //
+ // Clip Art Gallery will call pStream->Stat before calling CoInitialize.
+ // This causes the thunk logic to allocation 16bit memory which will
+ // fail at this point. The below code to auto-initialize should this
+ // happen. (Really just a hack for Clip Art Gallery).
+ //
+ if ( !IsEtaskInit(htask, etask)
+ || !IsValidInterface((etask.m_pMalloc)) )
+ {
+ if (FAILED(CoInitialize(NULL)))
+ {
+ *ppMalloc = NULL;
+ return ResultFromScode(CO_E_NOTINITIALIZED);
+ }
+
+ thkVerify(LookupEtask( htask, etask ));
+ etask.m_inits = ETASK_FAKE_INIT;
+ thkVerify(SetEtask(htask, etask));
+ }
+
+ // shared always available if initialized; no need to handle here
+ thkAssert(dwContext != MEMCTX_SHARED);
+
+ if (dwContext == MEMCTX_TASK)
+ {
+ thkAssert(etask.m_pMalloc != NULL);
+ *ppMalloc = etask.m_pMalloc;
+ }
+ else
+ {
+#ifdef NOTYET
+ // contexts which are delay-created
+ IMalloc FAR* FAR* ppMallocStore;
+
+ if (dwContext == MEMCTX_SHAREDBLOCK)
+ ppMallocStore = &etask.m_pMallocSBlock;
+ else if (dwContext == MEMCTX_COPRIVATE)
+ ppMallocStore = &etask.m_pMallocPrivate;
+ else
+ {
+ // invalid context
+ *ppMalloc = NULL;
+ return ResultFromScode(E_INVALIDARG);
+ }
+
+ if (*ppMallocStore == NULL)
+ {
+ // sets pMalloc to NULL on error
+ if (CoCreateStandardMalloc(dwContext, ppMallocStore) != NOERROR)
+ {
+ *ppMalloc = NULL;
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ thkVerify(SetEtask(htask, etask));
+ }
+
+ *ppMalloc = *ppMallocStore;
+#else
+ // invalid context
+ thkAssert(!"Unknown memctx in CoGetMalloc");
+ *ppMalloc = NULL;
+ return ResultFromScode(E_INVALIDARG);
+#endif // NOTYET
+ }
+
+ Exit: // have non-null *ppMalloc
+ thkAssert(*ppMalloc != NULL);
+ (*ppMalloc)->AddRef();
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoGetState, Local
+//
+// Synopsis: Retrieves task-specific state
+//
+// Arguments: [ppunk] - IUnknown pointer to fill in
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-94 DrewB Created
+//
+// Notes: Private API for OLE automation
+//
+//----------------------------------------------------------------------------
+
+STDAPI CoGetState(IUnknown FAR * FAR *ppunk)
+{
+ Etask etask;
+ HTASK htask;
+
+ thkDebugOut((DEB_APIS16, "CoGetState called\n"));
+ if (IsBadWritePtr(ppunk, sizeof(IUnknown *)))
+ {
+ thkDebugOut((DEB_APIS16, "CoGetState failed\n"));
+ return ResultFromScode(E_INVALIDARG);
+ }
+
+ if (!LookupEtask(htask, etask) || etask.m_punkState == NULL )
+ {
+ *ppunk = NULL;
+ thkDebugOut((DEB_APIS16, "CoGetState failed\n"));
+ return ResultFromScode(S_FALSE);
+ }
+
+ if ( !IsValidInterface((etask.m_punkState)) )
+ {
+ *ppunk = NULL;
+ etask.m_punkState = NULL;
+ thkDebugOut((DEB_APIS16, "CoGetState failed (invalid interface)\n"));
+ return ResultFromScode(S_FALSE);
+ }
+
+
+ *ppunk = etask.m_punkState;
+ etask.m_punkState->AddRef();
+
+ thkDebugOut((DEB_APIS16, "CoGetState done %p\n", *ppunk));
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoSetState, Local
+//
+// Synopsis: Sets task-specific state
+//
+// Arguments: [punk] - State to set
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-94 DrewB Created
+//
+// Notes: Private API for OLE automation
+//
+//----------------------------------------------------------------------------
+
+STDAPI CoSetState(IUnknown FAR *punk)
+{
+ Etask etask;
+ HTASK htask;
+ IUnknown FAR *punkStateOld;
+
+ thkDebugOut((DEB_APIS16, "CoSetState called %p\n", punk));
+
+ if (punk != NULL && !IsValidInterface(punk))
+ {
+ thkDebugOut((DEB_APIS16, "CoSetState called %p failed\n", punk));
+ return ResultFromScode(E_INVALIDARG);
+ }
+
+ if (!IsEtaskInit(htask, etask))
+ {
+ thkDebugOut((DEB_APIS16, "CoSetState called %p failed\n", punk));
+ return ResultFromScode(S_FALSE);
+ }
+
+ if (punk != NULL)
+ {
+ punk->AddRef();
+ }
+
+ punkStateOld = etask.m_punkState;
+ etask.m_punkState = punk;
+
+ thkVerify(SetEtask(htask, etask));
+
+ if (punkStateOld != NULL && IsValidInterface(punkStateOld))
+ {
+ punkStateOld->Release();
+ }
+
+ thkDebugOut((DEB_APIS16, "CoSetState called %p done\n", punk));
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoGetCurrentProcess, Local
+//
+//----------------------------------------------------------------------------
+// returns a unique value for the current task; this routine is
+// necessary because htask values from Window get reused periodically.
+STDAPI_(DWORD) CoGetCurrentProcess(void)
+{
+ HTASK htask;
+ Etask etask;
+
+ thkDebugOut((DEB_ITRACE, " CoGetCurrentProcess\n"));
+
+ if (!IsEtaskInit(htask, etask))
+ return 0;
+
+ return etask.m_pid;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoBuildVersion, Local
+//
+//----------------------------------------------------------------------------
+STDAPI_(DWORD) CoBuildVersion(VOID)
+{
+ thkDebugOut((DEB_ITRACE, " CoBuildVersion\n"));
+
+ // We must return 23 as our major version number to remain
+ // compatible with shipped OLE 2.01
+ // OLE 2.01 shipped with minor version 640
+ // We return a number slightly higher to differentiate
+ // our product while indicating compatibility
+ return MAKELONG(700, 23);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoMarshalHresult, Local
+//
+// History: Taken straight from OLE2 sources
+//
+//----------------------------------------------------------------------------
+STDAPI CoMarshalHresult(LPSTREAM pstm, HRESULT hresult)
+{
+ HRESULT hr;
+
+ thkDebugOut((DEB_ITRACE, "CoMarshalHresult\n"));
+
+ if (!IsValidInterface(pstm))
+ {
+ hr = ResultFromScode(E_INVALIDARG);
+ }
+ else
+ {
+ SCODE sc;
+ ULONG cb;
+
+ sc = GetScode(hresult);
+ hr = pstm->Write(&sc, sizeof(sc), &cb);
+ if (SUCCEEDED(GetScode(hr)) && cb != sizeof(sc))
+ {
+ hr = ResultFromScode(STG_E_WRITEFAULT);
+ }
+ }
+ return hr;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoUnmarshalHresult, Local
+//
+// History: Taken straight from OLE2 sources
+//
+//----------------------------------------------------------------------------
+STDAPI CoUnmarshalHresult(LPSTREAM pstm, HRESULT FAR * phresult)
+{
+ HRESULT hr;
+
+ thkDebugOut((DEB_ITRACE, "CoUnmarshalHresult\n"));
+
+ if (!IsValidPtrOut(phresult, sizeof(HRESULT)))
+ {
+ hr = ResultFromScode(E_INVALIDARG);
+ }
+ else
+ {
+ *phresult = 0;
+
+ if (!IsValidInterface(pstm))
+ {
+ hr = ResultFromScode(E_INVALIDARG);
+ }
+ else
+ {
+ SCODE sc;
+ ULONG cb;
+
+ hr = pstm->Read(&sc, sizeof(sc), &cb);
+ if (SUCCEEDED(GetScode(hr)))
+ {
+ if (cb != sizeof(sc))
+ {
+ hr = ResultFromScode(STG_E_READFAULT);
+ }
+ else
+ {
+ *phresult = ResultFromScode(sc);
+ }
+ }
+ }
+ }
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsEqualGUID, Local
+//
+// History: Taken straight from OLE2 sources
+//
+//----------------------------------------------------------------------------
+#pragma intrinsic(_fmemcmp)
+STDAPI_(BOOL) IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
+{
+ //thkDebugOut((DEB_ITRACE, "IsEqualGUID\n"));
+
+ return !_fmemcmp(&rguid1, &rguid2, sizeof(GUID));
+}
+#pragma function(_fmemcmp)
+
+#define GUIDSTR_MAX (1+ 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
+
+//+---------------------------------------------------------------------------
+//
+// Function: HexStringToDword, private
+//
+// History: Straight from OLE2 sources
+//
+//----------------------------------------------------------------------------
+
+static BOOL HexStringToDword(LPCSTR FAR& lpsz, DWORD FAR& Value, int cDigits,
+ char chDelim)
+{
+ int Count;
+
+ Value = 0;
+ for (Count = 0; Count < cDigits; Count++, lpsz++)
+ {
+ if (*lpsz >= '0' && *lpsz <= '9')
+ {
+ Value = (Value << 4) + *lpsz - '0';
+ }
+ else if (*lpsz >= 'A' && *lpsz <= 'F')
+ {
+ Value = (Value << 4) + *lpsz - 'A' + 10;
+ }
+ else if (*lpsz >= 'a' && *lpsz <= 'f')
+ {
+ Value = (Value << 4) + *lpsz - 'a' + 10;
+ }
+ else
+ {
+ return(FALSE);
+ }
+ }
+ if (chDelim != 0)
+ {
+ return *lpsz++ == chDelim;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GUIDFromString, private
+//
+// History: Straight from OLE2 sources
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(BOOL) GUIDFromString(LPCSTR lpsz, LPGUID pguid)
+{
+ DWORD dw;
+
+ if (*lpsz++ != '{')
+ return FALSE;
+
+ if (!HexStringToDword(lpsz, pguid->Data1, sizeof(DWORD)*2, '-'))
+ return FALSE;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
+ return FALSE;
+
+ pguid->Data2 = (WORD)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
+ return FALSE;
+
+ pguid->Data3 = (WORD)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pguid->Data4[0] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '-'))
+ return FALSE;
+
+ pguid->Data4[1] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pguid->Data4[2] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pguid->Data4[3] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pguid->Data4[4] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pguid->Data4[5] = (BYTE)dw;
+
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
+ return FALSE;
+
+ pguid->Data4[6] = (BYTE)dw;
+ if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '}'))
+ return FALSE;
+
+ pguid->Data4[7] = (BYTE)dw;
+
+ return TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StringFromCLSID, Local
+//
+// History: Straight from OLE2 sources
+//
+//----------------------------------------------------------------------------
+
+#define CLSIDSTR_MAX (GUIDSTR_MAX)
+
+STDAPI StringFromCLSID(REFCLSID rclsid, LPSTR FAR* lplpsz)
+{
+ SCODE sc;
+ char *psz;
+
+ thkDebugOut((DEB_ITRACE, "StringFromCLSID\n"));
+
+ psz = NULL;
+ do
+ {
+ if (!IsValidPtrOut(lplpsz, sizeof(LPSTR)))
+ {
+ sc = E_INVALIDARG;
+ break;
+ }
+ *lplpsz = NULL;
+
+ if (!IsValidPtrIn(&rclsid, sizeof(CLSID)))
+ {
+ sc = E_INVALIDARG;
+ break;
+ }
+
+ psz = (char *)TaskAlloc(CLSIDSTR_MAX);
+ if (psz == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ break;
+ }
+
+ if (StringFromGUID2(rclsid, psz, CLSIDSTR_MAX) == 0)
+ {
+ sc = E_INVALIDARG;
+ TaskFree(psz);
+ break;
+ }
+
+ *lplpsz = psz;
+ sc = S_OK;
+ } while (FALSE);
+
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StringFromIID, Local
+//
+// History: Straight from OLE2 sources
+//
+//----------------------------------------------------------------------------
+STDAPI StringFromIID(REFIID rclsid, LPSTR FAR* lplpsz)
+{
+ SCODE sc;
+ char *psz;
+
+ thkDebugOut((DEB_ITRACE, "StringFromIID\n"));
+
+ do
+ {
+ if (!IsValidPtrOut(lplpsz, sizeof(LPSTR)))
+ {
+ sc = E_INVALIDARG;
+ break;
+ }
+ *lplpsz = NULL;
+
+ if (!IsValidPtrIn(&rclsid, sizeof(IID)))
+ {
+ sc = E_INVALIDARG;
+ break;
+ }
+
+ psz = (char *)TaskAlloc(GUIDSTR_MAX);
+ if (psz == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ break;
+ }
+
+ if (StringFromGUID2(rclsid, psz, GUIDSTR_MAX) == 0)
+ {
+ sc = E_INVALIDARG;
+ TaskFree(psz);
+ break;
+ }
+
+ *lplpsz = psz;
+ sc = S_OK;
+ } while (FALSE);
+
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IIDFromString, Local
+//
+// History: Straight from OLE2 sources
+//
+//----------------------------------------------------------------------------
+STDAPI IIDFromString(LPSTR lpsz, LPIID lpiid)
+{
+ SCODE sc;
+
+ thkDebugOut((DEB_ITRACE, "IIDFromString\n"));
+
+ sc = S_OK;
+ if (!IsValidPtrOut(lpiid, sizeof(IID)))
+ {
+ sc = E_INVALIDARG;
+ }
+ else if (lpsz == NULL)
+ {
+ *lpiid = IID_NULL;
+ }
+ else if (!IsValidPtrIn(lpsz, sizeof(LPSTR)))
+ {
+ sc = E_INVALIDARG;
+ }
+ else if (!GUIDFromString(lpsz, lpiid))
+ {
+ sc = CO_E_IIDSTRING;
+ }
+
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StringFromGUID2, Local
+//
+// History: Straight from OLE2 sources
+//
+//----------------------------------------------------------------------------
+STDAPI_(int) StringFromGUID2(REFGUID rguid, LPSTR lpsz, int cbMax)
+{
+ thkDebugOut((DEB_ITRACE, "StringFromGUID2\n"));
+
+ if (cbMax < GUIDSTR_MAX)
+ {
+ return 0;
+ }
+
+ wsprintf(lpsz, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ rguid.Data1, rguid.Data2, rguid.Data3,
+ rguid.Data4[0], rguid.Data4[1],
+ rguid.Data4[2], rguid.Data4[3],
+ rguid.Data4[4], rguid.Data4[5],
+ rguid.Data4[6], rguid.Data4[7]);
+
+ return GUIDSTR_MAX;
+}
+
+// The following two APIs are now macros but must still be exported
+// so use PASCAL-form names to avoid problems with the macros
+
+//+---------------------------------------------------------------------------
+//
+// Function: GETSCODE, Local
+//
+// History: Straight from OLE2 sources
+//
+//----------------------------------------------------------------------------
+STDAPI_(SCODE) GETSCODE(HRESULT hr)
+{
+ return GetScode(hr);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: RESULTFROMSCODE, Local
+//
+// History: Straight from OLE2 sources
+//
+//----------------------------------------------------------------------------
+STDAPI RESULTFROMSCODE(SCODE sc)
+{
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: PropagateResult, Local
+//
+// History: Straight from OLE2 sources
+//
+//----------------------------------------------------------------------------
+STDAPI PropagateResult(HRESULT hrPrev, SCODE scNew)
+{
+ thkDebugOut((DEB_ITRACE, "PropagateResult\n"));
+
+ return (HRESULT)((scNew & 0x800FFFFF) | ((DWORD)hrPrev & 0x7FF00000)
+ + 0x100000);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: FnAssert, Local
+//
+// History: Straight from OLE2 sources
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+static char lpBuffer[512];
+static char lpLocBuffer[256];
+#endif
+
+STDAPI FnAssert( LPSTR lpstrExpr,
+ LPSTR lpstrMsg,
+ LPSTR lpstrFileName,
+ UINT iLine )
+{
+#if DBG == 1
+ int iResult;
+
+ wsprintf(lpBuffer, "Assertion \"%s\" failed! %s", lpstrExpr, lpstrMsg);
+ wsprintf(lpLocBuffer, "File %s, line %d; (A=exit; R=break; I=continue)",
+ lpstrFileName, iLine);
+ iResult = MessageBox(NULL, lpLocBuffer, lpBuffer,
+ MB_ABORTRETRYIGNORE | MB_SYSTEMMODAL);
+
+ if (iResult == IDRETRY)
+ {
+ DebugBreak();
+ }
+ else if (iResult == IDABORT)
+ {
+ CoFreeAllLibraries();
+ FatalAppExit(0, "Assertion failure");
+ }
+#endif
+ return NOERROR;
+}
+
+//
+// BUGBUG - These APIs are exported by the .DEF file, but are not documented,
+// nor is there any code in the 16-bit world to deal with them. Each of these
+// needs to be investigated to determine what we need to do to implement them.
+//
+// LRPCDISPATCH
+// REMCONNECTTOOBJECT
+// REMCREATEREMOTEHANDLER
+// REMALLOCOID
+// LRPCFREEMONITORDATA
+// TIMERCALLBACKPROC
+// COSETACKSTATE
+// COGETCLASSEXT
+// LRPCCALL
+// LRPCREGISTERMONITOR
+// CLSIDFROMOLE1CLASS
+// COOPENCLASSKEY
+// LRPCGETTHREADWINDOW
+// LRPCREVOKEMONITOR
+// COHANDLEINCOMINGCALL
+// REMGETINFOFORCID
+//
+// The below stubs probably don't clean up the stack properly either!!!
+
+#define UNDEFINED_DEF_ENTRY(x) STDAPI x ( void ) \
+ { return ResultFromScode(E_NOTIMPL); }
+
+
+UNDEFINED_DEF_ENTRY( LRPCDISPATCH )
+UNDEFINED_DEF_ENTRY( REMCONNECTTOOBJECT )
+UNDEFINED_DEF_ENTRY( REMCREATEREMOTEHANDLER )
+UNDEFINED_DEF_ENTRY( REMALLOCOID )
+UNDEFINED_DEF_ENTRY( LRPCFREEMONITORDATA )
+UNDEFINED_DEF_ENTRY( TIMERCALLBACKPROC )
+UNDEFINED_DEF_ENTRY( COSETACKSTATE )
+UNDEFINED_DEF_ENTRY( COGETCLASSEXT )
+UNDEFINED_DEF_ENTRY( LRPCCALL )
+UNDEFINED_DEF_ENTRY( LRPCREGISTERMONITOR )
+UNDEFINED_DEF_ENTRY( CLSIDFROMOLE1CLASS )
+UNDEFINED_DEF_ENTRY( COOPENCLASSKEY )
+UNDEFINED_DEF_ENTRY( LRPCGETTHREADWINDOW )
+UNDEFINED_DEF_ENTRY( LRPCREVOKEMONITOR )
+UNDEFINED_DEF_ENTRY( COHANDLEINCOMINGCALL )
+UNDEFINED_DEF_ENTRY( REMGETINFOFORCID )
+UNDEFINED_DEF_ENTRY( OLE1CLASSFROMCLSID2 )
+UNDEFINED_DEF_ENTRY( REMLOOKUPSHUNK )
+UNDEFINED_DEF_ENTRY( REMFREEOID )
diff --git a/private/ole32/olethunk/ole16/compobj/comlocal.hxx b/private/ole32/olethunk/ole16/compobj/comlocal.hxx
new file mode 100644
index 000000000..3b619e3b0
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/comlocal.hxx
@@ -0,0 +1,35 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: comlocal.hxx
+//
+// Contents: Local functions header and external definitions
+//
+// History: 10-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __COMLOCAL_HXX__
+#define __COMLOCAL_HXX__
+
+extern IMalloc FAR* v_pMallocShared;
+
+LPVOID __loadds FAR PASCAL TaskAlloc(ULONG cb);
+void __loadds FAR PASCAL TaskFree(LPVOID pv);
+
+#if defined(_CHICAGO_)
+extern BOOL gfReleaseDLL;
+
+#define SetReleaseDLL(x) gfReleaseDLL = x
+#define CanReleaseDLL() gfReleaseDLL
+
+#else
+
+#define SetReleaseDLL(x)
+#define CanReleaseDLL() TRUE
+
+#endif
+
+#endif // #ifndef __COMLOCAL_HXX__
diff --git a/private/ole32/olethunk/ole16/compobj/compobj.cxx b/private/ole32/olethunk/ole16/compobj/compobj.cxx
new file mode 100644
index 000000000..5ac18b792
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/compobj.cxx
@@ -0,0 +1,355 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ComAPIs.cxx (16 bit target)
+//
+// Contents: CompObj APIs
+//
+// Functions:
+//
+// History: 16-Dec-93 JohannP Created
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+#include <ole2sp.h>
+#include <olecoll.h>
+#include <map_kv.h>
+#include <stdlib.h>
+
+#include "map_htsk.h"
+#include "etask.hxx"
+#include "call32.hxx"
+#include "apilist.hxx"
+
+// BUGBUG - Opmodes should be removed
+// They don't seem to be necessary any more
+
+DECLARE_INFOLEVEL(thk1);
+DECLARE_INFOLEVEL(Stack1);
+
+CMapHandleEtask NEAR v_mapToEtask(MEMCTX_SHARED);
+
+#if defined(_CHICAGO_)
+Etask getask = {0,0,0,0,0,0,0,0};
+extern IMalloc FAR* v_pMallocShared; // is not addrefed
+BOOL SetupSharedAllocator(Etask FAR& etask);
+STDAPI_(BOOL) RemoveEtask(HTASK FAR& hTask, Etask FAR& etask);
+#endif // _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Function: LibMain, public
+//
+// Synopsis: DLL initialization function
+//
+// Arguments: [hinst] - Instance handle
+// [wDataSeg] - Current DS
+// [cbHeapSize] - Heap size for the DLL
+// [lpszCmdLine] - Command line information
+//
+// Returns: One for success, zero for failure
+//
+// History: 21-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+static char achInfoLevel[32];
+
+#ifdef _CHICAGO_
+BOOL fSSOn = TRUE;
+#endif // _CHICAGO_
+
+#endif
+
+extern "C" int CALLBACK LibMain(HINSTANCE hinst,
+ WORD wDataSeg,
+ WORD cbHeapSize,
+ LPSTR lpszCmdLine)
+{
+
+#if DBG == 1
+ if (GetProfileString("olethk32", "InfoLevel", "3", achInfoLevel,
+ sizeof(achInfoLevel)) > 0)
+ {
+ thk1InfoLevel = strtoul(achInfoLevel, NULL, 0);
+ }
+
+#ifdef _CHICAGO_
+ if (GetProfileString("CairOLE InfoLevels",
+ "Stack", "3", achInfoLevel,
+ sizeof(achInfoLevel)) > 0)
+ {
+ Stack1InfoLevel = strtoul(achInfoLevel, NULL, 0);
+ }
+
+ if (GetProfileString("CairOLE InfoLevels",
+ "StackOn", "3", achInfoLevel,
+ sizeof(achInfoLevel)) > 0)
+ {
+ fSSOn = (BOOL) strtoul(achInfoLevel, NULL, 0);
+ }
+#endif // _CHICAGO_
+
+#endif
+
+ thkDebugOut((DEB_DLLS16, "CompObj16: LibMain called on Process (%X) \n", GetCurrentProcess() ));
+
+#if defined(_CHICAGO_)
+ //
+ // BUGBUGCHICAGO
+ //
+ // The Chicago debugger doesn't like hinst not being wired.
+ //
+ GlobalWire(hinst);
+#else
+ // NOTE: on WIN95 Call32Initialize is called by DLLEntryPoint
+ if (!Call32Initialize())
+ {
+ return 0;
+ }
+#endif
+
+#ifdef _DEBUG
+ v_mapToEtask.AssertValid();
+#endif
+
+ UNREFERENCED(cbHeapSize);
+
+ // Leave our DS unlocked when we're not running
+ UnlockData( 0 );
+
+#if defined(_CHIC_INIT_IN_LIBMAIN_)
+ if (SetupSharedAllocator(getask) == FALSE)
+ {
+ return FALSE;
+ }
+#endif // _CHIC_INIT_IN_LIBMAIN_
+
+ thkDebugOut((DEB_DLLS16, "CompObj16: LibMain called on Process (%X) Exitype (%ld)\n", GetCurrentProcess() ));
+
+ return TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WEP, public
+//
+// Synopsis: Windows Exit Point routine, for receiving DLL unload
+// notification
+//
+// Arguments: [nExitType] - Type of exit occurring
+//
+// Returns: One for success, zero for failure
+//
+// History: 21-Feb-94 DrewB Created
+//
+// Note: Does nothing on WIN95. Call32Unitialize is called in
+// DllEntryPoint when load count goes to zero.
+//
+//----------------------------------------------------------------------------
+
+extern "C" int CALLBACK WEP(int nExitType)
+{
+ thkDebugOut((DEB_DLLS16, "CompObj16: WEP called on Process (%X) Exitype (%ld)\n", GetCurrentProcess(),nExitType));
+
+#if defined(_CHICAGO_)
+#if defined(_CHIC_INIT_IN_LIBMAIN_)
+
+ if (v_pMallocShared != NULL)
+ {
+ getask.m_pMallocShared->Release();
+ getask.m_pMallocShared = NULL;
+ v_pMallocShared = NULL;
+ thkDebugOut((DEB_DLLS16, "CompObj16: WEP v_pMallocShared to NULL (%X) \n",GetCurrentProcess()));
+ }
+#endif // _CHIC_INIT_IN_LIBMAIN_
+#else
+ HTASK htask;
+ Etask etask;
+ if (LookupEtask(htask, etask))
+ {
+ //
+ // There is an etask. Check to see if the etask for this task has
+ // its init count set to ETASK_FAKE_INIT. If it does, we cheated
+ // and called CoInitialize on the processes behalf, but it never
+ // called CoUninitialize(). Some apps that only make storage calls
+ // demonstrate this behaviour. If it is ETASK_FAKE_INIT, then we
+ // are going to call CoUninitialize on the apps behalf.
+ //
+ if (etask.m_inits == ETASK_FAKE_INIT)
+ {
+ //
+ // We are going to set the m_inits == 1, since we called it
+ // once. Then we are going to call our very own CoUninitialize()
+ // to let it handle the rest of the cleanup.
+ //
+ etask.m_inits = 1;
+ thkVerify(SetEtask(htask, etask));
+ CoUninitialize();
+ }
+ }
+
+ //
+ // Now uninit the thunk layer
+ //
+ Call32Uninitialize();
+#endif
+
+ thkDebugOut((DEB_DLLS16, "CompObj16: WEP called on Process (%X) done\n", GetCurrentProcess()));
+ return 1;
+}
+
+#if defined(_CHICAGO_)
+//+---------------------------------------------------------------------------
+//
+// Function: DllEntryPoint, public
+//
+// Synopsis: Chicago's 16-bit DLL Load/Unload Entry Point.
+//
+// Arguments: [dwReason] - 1 DLL load, 0 DLL unload
+// [hInst] - hInstance
+// [wDS] - Data Segment
+// [wHeapSize] - Heap Size
+// [dwReserved1] - Reserved
+// [wReserved2] - Reserved
+//
+// Returns: True for success, False for failure
+//
+// Remarks: This DLL must be marked as 4.0 for Chicago to call this entry
+// point. DllEntryPoint is called between LibMain and WEP. See
+// etask.hxx for information of it's elements.
+//
+// History: 18-Jan-95 JohannP Created
+//
+// Note: The shared allocator gets initialized first time this function
+// gets called with DLL_LOAD. The gets removed when the dll gets
+// unloaded.
+//
+//----------------------------------------------------------------------------
+#define DLL_LOAD 1
+#define DLL_UNLOAD 0
+
+extern "C" BOOL FAR PASCAL
+__export DllEntryPoint(DWORD dwReason,WORD hInst,WORD wDS,
+ WORD wHeapSize,DWORD dwReserved1,WORD wReserved2)
+{
+ HTASK htask;
+ Etask etask;
+
+ thkDebugOut((DEB_DLLS16, "CompObj16: DllEntryPoint called on Process (%X) Reason: (%ld)\n", GetCurrentProcess(),dwReason));
+ if (dwReason == DLL_LOAD) // DLL refcount increment
+ {
+ etask.m_htask = 0;
+ etask.m_Dllinits = 0;
+ // if not init call and init 32 bit
+ if ( !LookupEtask(htask, etask)
+ || etask.m_htask != GetCurrentProcess() )
+ {
+ // Set up the shared allocator.
+ if (SetupSharedAllocator(etask) == FALSE)
+ {
+ thkAssert(v_pMallocShared != NULL && "CompObj: DllEntryPoint: pMallocShared not initialized");
+ return FALSE;
+ }
+ // Initialize the interop call mechanism
+ if (!Call32Initialize())
+ {
+ thkDebugOut((DEB_DLLS16, "CompObj16: DllEntryPoint Call32Initialize failed\n"));
+ return FALSE;
+ }
+
+ etask.m_Dllinits = 1;
+ etask.m_htask = GetCurrentProcess();
+ etask.m_pMallocSBlock = NULL;
+ etask.m_pMallocPrivate = NULL;
+ etask.m_pid = 0;
+ etask.m_inits = ETASK_NO_INIT;
+ etask.m_oleinits = 0;
+ etask.m_reserved = 0;
+ etask.m_pDlls = NULL;
+ etask.m_pMapToServerCO = NULL;
+ etask.m_pMapToHandlerCO = NULL;
+ etask.m_pArraySH = NULL;
+ etask.m_pCThrd = NULL;
+ etask.m_hwndClip = NULL;
+ etask.m_hwndDde = NULL;
+ etask.m_punkState = NULL;
+ SetEtask(htask, etask);
+
+ // BUGBUG: this should be simplified
+
+ // verify the initialzation
+ etask.m_Dllinits = 0;
+ etask.m_htask = 0;
+ if ( !LookupEtask(htask, etask)
+ || etask.m_Dllinits == 0
+ || etask.m_htask != GetCurrentProcess() )
+ {
+ thkDebugOut((DEB_DLLS16, "CompObj16: DllEntryPoint Etask not initialized; Process (%X) done (%ld)\n", GetCurrentProcess(),dwReason));
+ thkAssert(0 && "CompObj: DllEntryPoint Etask not initialized.");
+ return FALSE;
+ }
+ thkDebugOut((DEB_DLLS16, "CompObj16: Added Etask\n"));
+ }
+ else
+ {
+ etask.m_Dllinits++;
+ if (!SetEtask(htask, etask))
+ {
+ thkAssert(0 && "CompObj16: Etask could not be updated.");
+ }
+ else
+ {
+ thkDebugOut((DEB_DLLS16, "CompObj16: Updated Etask\n"));
+ }
+ }
+ }
+ else if (dwReason == DLL_UNLOAD) // dll refcount decrement
+ {
+ if (LookupEtask(htask, etask))
+ {
+ if (etask.m_Dllinits > 0)
+ {
+ etask.m_Dllinits--;
+
+ if ( etask.m_Dllinits == 0 )
+ {
+ Call32Uninitialize();
+ thkDebugOut((DEB_DLLS16, "CompObj16: Removing Etask\n"));
+ thkVerify(RemoveEtask(htask,etask));
+ }
+ else
+ {
+ if (!SetEtask(htask, etask))
+ {
+ thkAssert(0 && "CompObj16: Etask could not be updated.");
+ }
+ else
+ {
+ thkDebugOut((DEB_DLLS16, "CompObj16: Updated Etask\n"));
+ }
+ }
+ }
+ else
+ {
+ thkAssert(0 && "Dllinit count invalid");
+ }
+ }
+ else
+ {
+ thkAssert(0 && "DllEntryPoint on CompObj - no etask");
+ }
+ }
+ else
+ {
+ thkAssert(0 && "Chicago BUG - Someone changed DllEntryPoint protocol");
+ }
+ thkDebugOut((DEB_DLLS16, "CompObj16: DllEntryPoint on Process (%X) done (%ld)\n", GetCurrentProcess(),dwReason));
+ return TRUE;
+}
+#endif
+
diff --git a/private/ole32/olethunk/ole16/compobj/compobj.def b/private/ole32/olethunk/ole16/compobj/compobj.def
new file mode 100644
index 000000000..80c561eb5
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/compobj.def
@@ -0,0 +1,236 @@
+;********************************************************************
+;** Microsoft Windows **
+;** Copyright(c) Microsoft Corp., 1992 - 1994 **
+;********************************************************************
+
+LIBRARY COMPOBJ
+DESCRIPTION 'WOW REPLACEMENT COMPOBJ'
+EXETYPE WINDOWS
+
+;
+; Since we are thunking both code and data addresses up into the 32bit world
+; the code and data segments shouldn't move around (we're a virtual memory
+; environment so there is no performance hit). This will also keep the
+; Chicago debugger from breaking due to non-wired segments when we call up
+; to 32bit code.
+;
+
+CODE FIXED DISCARDABLE LOADONCALL SHARED
+
+DATA FIXED SINGLE
+
+HEAPSIZE 4096 ; Need heap for C++ environment cache
+
+
+EXPORTS
+ WEP @0 RESIDENTNAME
+ COBUILDVERSION @1
+ COINITIALIZE @2
+ COUNINITIALIZE @3
+ COGETMALLOC @4
+ COREGISTERCLASSOBJECT @5
+ COREVOKECLASSOBJECT @6
+ COGETCLASSOBJECT @7
+ COMARSHALINTERFACE @8
+ COUNMARSHALINTERFACE @9
+ COLOADLIBRARY @10
+ COFREELIBRARY @11
+ COFREEALLLIBRARIES @12
+ COCREATEINSTANCE @13
+ STRINGFROMIID @14
+ CODISCONNECTOBJECT @15
+ CORELEASEMARSHALDATA @16
+ COFREEUNUSEDLIBRARIES @17
+ ISEQUALGUID @18
+ STRINGFROMCLSID @19
+ CLSIDFROMSTRING @20
+
+ ISVALIDPTRIN @21
+ ISVALIDPTROUT @22
+ ISVALIDINTERFACE @23
+ ISVALIDIID @24
+
+ RESULTFROMSCODE @25
+ GETSCODE @26
+
+ COREGISTERMESSAGEFILTER @27
+ COISHANDLERCONNECTED @28
+ ;; UNUSED @29
+
+ COFILETIMETODOSDATETIME @30
+ CODOSDATETIMETOFILETIME @31
+
+ COMARSHALHRESULT @32
+ COUNMARSHALHRESULT @33
+
+ COGETCURRENTPROCESS @34
+
+ COISOLE1CLASS @36
+
+ _GUID_NULL @37
+ _IID_IUnknown @38
+ _IID_IClassFactory @39
+ _IID_IMalloc @40
+ _IID_IMarshal @41
+ _IID_IRpcChannel @42
+ _IID_IRpcStub @43
+ _IID_IStubManager @44
+ _IID_IRpcProxy @45
+ _IID_IProxyManager @46
+ _IID_IPSFactory @47
+ _IID_ILockBytes @48
+ _IID_IStorage @49
+ _IID_IStream @50
+ _IID_IEnumSTATSTG @51
+ _IID_IBindCtx @52
+ _IID_IMoniker @53
+ _IID_IRunningObjectTable @54
+ _IID_IInternalMoniker @55
+ _IID_IRootStorage @56
+ _IID_IDfReserved1 @57
+ _IID_IDfReserved2 @58
+ _IID_IDfReserved3 @59
+ _IID_IMessageFilter @60
+
+ CLSIDFROMPROGID @61
+ PROGIDFROMCLSID @62
+
+ COLOCKOBJECTEXTERNAL @63
+
+ _CLSID_StdMarshal @64
+
+ COGETTREATASCLASS @65
+ COTREATASCLASS @66
+
+ COGETSTANDARDMARSHAL @67
+ PROPAGATERESULT @68
+
+ IIDFROMSTRING @69
+
+ _IID_IStdMarshalInfo @70
+
+ COCREATESTANDARDMALLOC @71
+
+ _IID_IExternalConnection @72
+
+ COCREATEGUID @73
+
+ ;; internal calls below this point
+
+ FNASSERT @75
+
+ STRINGFROMGUID2 @76
+ COGETCLASSEXT @77
+ OLE1CLASSFROMCLSID2 @78
+ CLSIDFROMOLE1CLASS @79
+ COOPENCLASSKEY @80
+ GUIDFROMSTRING @81
+ COFILETIMENOW @82
+
+ REMALLOCOID @83
+ REMFREEOID @84
+ REMCREATEREMOTEHANDLER @85
+ REMCONNECTTOOBJECT @86
+ REMGETINFOFORCID @87
+
+ LRPCCALL @88
+ LRPCDISPATCH @89
+ LRPCREGISTERMONITOR @90
+ LRPCREVOKEMONITOR @91
+ LRPCGETTHREADWINDOW @92
+ TIMERCALLBACKPROC @93
+
+ LOOKUPETASK @94
+ SETETASK @95
+
+
+ LRPCFREEMONITORDATA @96
+; REMLOOKUPSHUNK @97
+
+ ;; collection class entry points
+
+ ??0CArrayFValue@@REC@KI@Z @100
+ ??1CArrayFValue@@REC@XZ @101
+ ?AssertValid@CArrayFValue@@RFCXXZ @102
+ ?FreeExtra@CArrayFValue@@RECXXZ @103
+ ?_GetAt@CArrayFValue@@RFCPEXH@Z @104
+ ?GetSize@CArrayFValue@@RFCHXZ @105
+; ?GetSizeValue@CArrayFValue@@RFCHXZ @106
+; ?GetUpperBound@CArrayFValue@@RFCHXZ @107
+ ?IndexOf@CArrayFValue@@RECHPEXII@Z @108
+ ?InsertAt@CArrayFValue@@RECHHPEXH@Z @109
+ ?RemoveAt@CArrayFValue@@RECXHH@Z @111
+ ?SetAt@CArrayFValue@@RECXHPEX@Z @112
+ ?SetAtGrow@CArrayFValue@@RECHHPEX@Z @113
+ ?SetSize@CArrayFValue@@RECHHH@Z @114
+
+ ; Added for OLE automation
+ COGETSTATE @115
+ COSETSTATE @110
+
+ ?GetAssocAt@CMapKeyToValue@@BFCPEUCAssoc@1@PEXIAEI@Z @120
+ ?SetAssocKey@CMapKeyToValue@@BFCHPEUCAssoc@1@PEXI@Z @121
+ ??1CMapKeyToValue@@REC@XZ @122
+ ?GetAssocKeyPtr@CMapKeyToValue@@BFCXPEUCAssoc@1@PEPEXPEI@Z @123
+ ?NewAssoc@CMapKeyToValue@@BECPEUCAssoc@1@IPEXI0@Z @124
+ ?SizeAssoc@CMapKeyToValue@@BFCIXZ @125
+ ?FreeAssoc@CMapKeyToValue@@BECXPEUCAssoc@1@@Z @126
+ ?GetStartPosition@CMapKeyToValue@@RFCPEXXZ @127
+ ?GetNextAssoc@CMapKeyToValue@@RFCXPEPEXPEXPEI1@Z @128
+ ?CompareAssocKey@CMapKeyToValue@@BFCHPEUCAssoc@1@PEXI@Z @129
+ ?RemoveHKey@CMapKeyToValue@@RECHK@Z @130
+ ?GetHKey@CMapKeyToValue@@RFCKPEXI@Z @131
+ ?GetCount@CMapKeyToValue@@RFCHXZ @132
+ ?Lookup@CMapKeyToValue@@RFCHPEXI0@Z @133
+ ?GetAssocValue@CMapKeyToValue@@BFCXPEUCAssoc@1@PEX@Z @134
+ ?RemoveKey@CMapKeyToValue@@RECHPEXI@Z @135
+ ?RemoveAll@CMapKeyToValue@@RECXXZ @136
+; ?IsEmpty@CMapKeyToValue@@RFCHXZ @137
+ ?FreeAssocKey@CMapKeyToValue@@BFCXPEUCAssoc@1@@Z @138
+ ?SetAt@CMapKeyToValue@@RECHPEXI0@Z @139
+ ?LookupHKey@CMapKeyToValue@@RFCHKPEX@Z @140
+ ?AssertValid@CMapKeyToValue@@RFCXXZ @141
+ ?SetAssocValue@CMapKeyToValue@@BFCXPEUCAssoc@1@PEX@Z @142
+ ?SetAtHKey@CMapKeyToValue@@RECHKPEX@Z @143
+ ??0CMapKeyToValue@@REC@KIIHP7CIPEXI@ZI@Z @144
+ ?InitHashTable@CMapKeyToValue@@BECHXZ @145
+ ?GetAssocValuePtr@CMapKeyToValue@@BFCXPEUCAssoc@1@PEPEX@Z @146
+ ?LookupAdd@CMapKeyToValue@@RFCHPEXI0@Z @147
+ MKVDEFAULTHASHKEY @148
+
+
+
+
+ COMEMCTXOF @150
+ COMEMALLOC @151
+ COMEMFREE @152
+
+ CORUNMODALLOOP @160
+ COHANDLEINCOMINGCALL @161
+ COSETACKSTATE @162
+
+
+ ; Additional exports for 16/32 interop
+ CALL32INITIALIZE @200
+ CALLOBJECTINWOW @201
+ CALLOBJECTINWOWCHECKINIT @203
+ CALLOBJECTINWOWCHECKTHKMGR @204
+
+ ; Added for 16-bit conversion clients
+ CONVERTHR1632 @205
+ CONVERTHR3216 @206
+
+ ; let's 16bit thunk dll's setup special behaviour
+ ADDAPPCOMPATFLAG @207
+
+IMPORTS
+ KERNEL.LOADLIBRARYEX32W ;;@513 NODATA ;;
+ KERNEL.FREELIBRARY32W ;;@514 NODATA ;;
+ KERNEL.GETPROCADDRESS32W ;;@515 NODATA ;;
+ KERNEL.GETVDMPOINTER32W ;;@516 NODATA ;;
+ KERNEL.CALLPROC32W ;;@517 NODATA ;;
+
+ KERNEL_SETOWNER = KERNEL.403
+ SSINIT = KERNEL.700
+ SSONBIGSTACK = KERNEL.701
+ _SSCALL = KERNEL.702
diff --git a/private/ole32/olethunk/ole16/compobj/compobj.rc b/private/ole32/olethunk/ole16/compobj/compobj.rc
new file mode 100644
index 000000000..3bc70c7f0
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/compobj.rc
@@ -0,0 +1,49 @@
+#include <windows.h>
+#include <assrtdlg.h>
+
+#include "verinfo.h"
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION VER_FILEVERSION
+PRODUCTVERSION VER_PRODUCTVERSION
+FILEFLAGSMASK VER_FILEFLAGSMASK
+FILEFLAGS VER_FILEFLAGS
+FILEOS VER_FILEOS
+FILETYPE VER_FILETYPE
+FILESUBTYPE VER_FILESUBTYPE
+{
+ BLOCK "StringFileInfo"
+ {
+ BLOCK "040904E4"
+ {
+ VALUE "CompanyName", VER_COMPANYNAME_STR
+ VALUE "FileDescription", VER_FILEDESCRIPTION_STR
+ VALUE "FileVersion", VER_FILEVERSION_STR
+ VALUE "InternalName", "COMPOBJ.DLL\0"
+ VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
+ VALUE "LegalTrademarks", VER_LEGALTRADEMARKS_STR
+ VALUE "ProductName", VER_PRODUCTNAME_STR
+ VALUE "ProductVersion", VER_PRODUCTVERSION_STR
+ VALUE "Comments", VER_COMMENT_STR
+ }
+ }
+ BLOCK "VarFileInfo"
+ {
+ VALUE "Translation", 0x409, 1252
+ }
+}
+
+
+ASSERTFAILDLG DIALOG 72, 32, 260, 67
+STYLE DS_SYSMODAL | WS_POPUP | WS_VISIBLE | WS_CAPTION
+CAPTION "Assertion failure!"
+FONT 8, "MS Sans Serif"
+BEGIN
+ CTEXT "", ASSRT_ID_EXPR, 11, 13, 240, 8
+ CTEXT "", ASSRT_ID_LOC, 11, 21, 240, 8
+ CTEXT "", ASSRT_ID_MSG, 11, 33, 240, 8
+ PUSHBUTTON "&Break", ASSRT_ID_BREAK, 54, 47, 40, 14
+ PUSHBUTTON "E&xit", ASSRT_ID_EXIT, 110, 47, 40, 14
+ PUSHBUTTON "&Ignore", ASSRT_ID_IGNORE, 166, 47, 40, 14
+END
+
diff --git a/private/ole32/olethunk/ole16/compobj/cpkt.cxx b/private/ole32/olethunk/ole16/compobj/cpkt.cxx
new file mode 100644
index 000000000..d1521e443
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/cpkt.cxx
@@ -0,0 +1,461 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: CPKT.CXX
+//
+// Contents: CPkt implementation for RPC/LRPC
+//
+// Functions:
+//
+// History: 30-Mar-94 BobDay Adapted from 16-bit OLE2.0, CPKT.CPP
+//
+//--------------------------------------------------------------------------
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <ole2ver.h>
+
+#include <ole2sp.h>
+#include "rpc16.hxx"
+#include "comlocal.hxx"
+
+//
+// Standard IUnknown method. Not used but need to be supported to comply
+// with the IUnknown.
+//
+
+STDMETHODIMP CPkt::QueryInterface(
+ REFIID iidInterface,
+ void FAR* FAR* ppvObj )
+{
+ HRESULT hresult;
+
+ // Three interfaces supported (each, and extension of the previous):
+ // IUnknown, IStream, ICPkt
+
+ if ( (iidInterface == IID_CPkt ||
+ iidInterface == IID_IStream ||
+ iidInterface == IID_IUnknown )) {
+
+ m_refs++; // A pointer to this object is returned
+ *ppvObj = this;
+ hresult = NOERROR;
+ }
+ else { // Not accessible or unsupported interface
+ *ppvObj = NULL;
+ hresult = ResultFromScode(E_NOINTERFACE);
+ }
+
+ return hresult;
+}
+
+//
+// Called when CPkt is referenced by an additional pointer.
+//
+
+STDMETHODIMP_(ULONG) CPkt::AddRef(void)
+{
+ return ++m_refs;
+}
+
+//
+// Called when a pointer to this CPkt is discarded
+//
+
+STDMETHODIMP_(ULONG) CPkt::Release(void)
+{
+ if (--m_refs != 0) // Still used by others
+ return m_refs;
+
+ if (m_rom16.Buffer != NULL)
+ {
+ TaskFree(m_rom16.Buffer);
+ }
+
+ delete this; // Free storage
+
+ return 0;
+}
+
+
+STDMETHODIMP CPkt::Read(void HUGEP* pb, ULONG cb, ULONG FAR* pcbRead)
+{
+ HRESULT hresult = NOERROR;
+ ULONG cbRead = cb;
+
+
+ if (pcbRead != NULL)
+ {
+ *pcbRead = 0;
+ }
+
+ if (cbRead + m_pos > m_rom16.cbBuffer) {
+ if (m_pos < m_rom16.cbBuffer)
+ {
+ cbRead = m_rom16.cbBuffer - m_pos;
+ }
+ else
+ {
+ cbRead = 0;
+ }
+ hresult = ResultFromScode(E_UNSPEC); // PKT (tried to read passed EOS)
+ }
+
+ if ( cbRead != 0 )
+ {
+ hmemcpy(pb,(LPSTR)m_rom16.Buffer + m_pos, cbRead);
+ m_pos += cbRead;
+ }
+
+ if (pcbRead != NULL)
+ {
+ *pcbRead = cbRead;
+ }
+
+ return hresult;
+}
+
+
+STDMETHODIMP CPkt::Write(void const HUGEP* pb, ULONG cb, ULONG FAR* pcbWritten)
+{
+ HRESULT hresult = NOERROR;
+ ULONG cbWritten = cb;
+
+
+ if (pcbWritten != NULL)
+ {
+ *pcbWritten = 0;
+ }
+
+ if (cbWritten + m_pos > m_rom16.cbBuffer)
+ {
+ ULARGE_INTEGER ularge_integer;
+
+ ULISet32(ularge_integer,m_pos+cbWritten);
+
+ hresult = SetSize(ularge_integer);
+ if (hresult != NOERROR)
+ {
+ return hresult;
+ }
+ }
+
+ if ( cbWritten != 0 )
+ {
+ hmemcpy((LPSTR)m_rom16.Buffer + m_pos,pb, cbWritten);
+ m_pos += cbWritten;
+ }
+
+ if (pcbWritten != NULL)
+ {
+ *pcbWritten = cbWritten;
+ }
+
+ return hresult;
+}
+
+STDMETHODIMP CPkt::Seek(LARGE_INTEGER dlibMoveIn, DWORD dwOrigin, ULARGE_INTEGER FAR* plibNewPosition)
+{
+ HRESULT hresult = NOERROR;
+ LONG dlibMove = dlibMoveIn.LowPart;
+ ULONG cbNewPos = dlibMove;
+
+
+ if (plibNewPosition != NULL)
+ {
+ ULISet32(*plibNewPosition, m_pos);
+ }
+
+ switch(dwOrigin)
+ {
+ case STREAM_SEEK_SET:
+ if (dlibMove >= 0)
+ {
+ m_pos = dlibMove;
+ }
+ else
+ {
+ hresult = ResultFromScode(E_UNSPEC); // PKT (Invalid seek)
+ }
+ break;
+
+ case STREAM_SEEK_CUR:
+ if (!(dlibMove < 0 && ((ULONG) -dlibMove) > m_pos))
+ {
+ m_pos += dlibMove;
+ }
+ else
+ {
+ hresult = ResultFromScode(E_UNSPEC); // PKT (Invalid seek)
+ }
+ break;
+
+ case STREAM_SEEK_END:
+ if (!(dlibMove < 0 && ((ULONG) -dlibMove) > m_rom16.cbBuffer))
+ {
+ m_pos = m_rom16.cbBuffer + dlibMove;
+ }
+ else
+ {
+ hresult = ResultFromScode(E_UNSPEC); // PKT (Invalid seek)
+ }
+ break;
+
+ default:
+ hresult = ResultFromScode(E_UNSPEC); // PKT (Invalid seek mode)
+ }
+
+ if (plibNewPosition != NULL)
+ {
+ ULISet32(*plibNewPosition,m_pos);
+ }
+
+ return hresult;
+}
+
+//
+// Note: if the cpkt data needs to be reallocate extra space
+//
+#define CBEXTRABYTES 128
+
+STDMETHODIMP CPkt::SetSize(ULARGE_INTEGER cb)
+{
+ HRESULT hresult = NOERROR;
+ ULONG ulNewSize;
+
+ if (m_opd.cbSize && m_opd.cbSize > cb.LowPart) {
+ m_rom16.cbBuffer = cb.LowPart;
+ goto Exit;
+ }
+
+ if (m_rom16.cbBuffer == cb.LowPart)
+ goto Exit;
+
+ ulNewSize = cb.LowPart + CBEXTRABYTES;
+ TaskFree(m_rom16.Buffer);
+ m_rom16.Buffer = TaskAlloc(ulNewSize);
+ if ( m_rom16.Buffer == NULL )
+ {
+ m_rom16.cbBuffer = 0;
+ m_opd.cbSize = 0;
+ hresult = ResultFromScode(S_OOM);
+ goto Exit;
+ }
+
+ m_rom16.cbBuffer = cb.LowPart;
+
+ m_opd.cbSize = ulNewSize;
+
+Exit:
+ return hresult;
+}
+
+
+STDMETHODIMP CPkt::CopyTo(IStream FAR *pstm, ULARGE_INTEGER cb,
+ ULARGE_INTEGER FAR * pcbRead, ULARGE_INTEGER FAR * pcbWritten)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+
+STDMETHODIMP CPkt::Commit(DWORD grfCommitFlags)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+
+
+STDMETHODIMP CPkt::Revert(void)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+
+
+STDMETHODIMP CPkt::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER, DWORD dwLockType)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+STDMETHODIMP CPkt::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+
+
+STDMETHODIMP CPkt::Stat(STATSTG FAR *pstatstg, DWORD statflag)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+
+
+STDMETHODIMP CPkt::Clone(THIS_ IStream FAR * FAR *ppstm)
+{
+ return ResultFromScode(E_NOTIMPL);
+}
+
+//
+// Create untyped CPkt. Used by other create functions (is private)
+//
+
+
+CPkt FAR* CPkt::Create(IUnknown FAR *pUnk, DWORD cbExt)
+{
+ CPkt FAR* pCPkt;
+
+ pCPkt = new CPkt;
+
+ if (pCPkt == NULL)
+ return NULL;
+
+ pCPkt->m_rom16.Buffer = TaskAlloc( cbExt );
+ if ( pCPkt->m_rom16.Buffer == NULL )
+ {
+ delete pCPkt;
+ return NULL;
+ }
+
+ pCPkt->m_rom16.cbBuffer = cbExt;
+ pCPkt->m_opd.cbSize = cbExt;
+
+ return pCPkt;
+}
+
+//
+// CPkt used to make a call
+//
+
+CPkt FAR* CPkt::CreateForCall(
+ IUnknown FAR *pUnk,
+ REFIID iid,
+ int iMethod,
+ BOOL fSend,
+ BOOL fAsync,
+ DWORD size )
+{
+ CPkt FAR * pCPkt;
+
+ if (fAsync && fSend) {
+ fSend = FALSE;
+ //Assert(0,"Async CPkt with fSend == TRUE not implemented");
+ //return NULL;
+ }
+
+ pCPkt = CPkt::Create(pUnk, size);
+ if (pCPkt == NULL)
+ {
+ return NULL;
+ }
+
+ pCPkt->m_opd.iid = iid;
+
+ pCPkt->m_rom16.iMethod = iMethod;
+ pCPkt->m_rom16.rpcFlags = 0;
+
+ if ( fSend )
+ {
+ pCPkt->m_rom16.rpcFlags |= RPCFLG_INPUT_SYNCHRONOUS;
+ }
+
+ if ( fAsync )
+ {
+ pCPkt->m_rom16.rpcFlags |= RPCFLG_ASYNCHRONOUS;
+ }
+ return pCPkt;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetRpcChannelBuffer, public
+//
+// Synopsis: Sets the RpcChannelBuffer to call when CallRpcChannelBuffer
+// is called.
+//
+// Arguments: [prcb] - IRpcChannelBuffer interface
+//
+// Returns: NOERROR always
+//
+// History: 30-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPkt::SetRpcChannelBuffer(
+ CRpcChannelBuffer FAR * prcb )
+{
+ m_prcb = prcb;
+
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CallRpcChannelBuffer, public
+//
+// Synopsis: Calls the RpcChannelBuffer with the parameters accumulated in
+// the CPkt buffer.
+//
+// Arguments: none
+//
+// Returns: HRESULT for success/failure of call or procedure
+//
+// History: 30-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CPkt::CallRpcChannelBuffer( void )
+{
+ HRESULT hresult;
+ RPCOLEMESSAGE16 rom16;
+ ULONG ulStatus;
+
+ //
+ // Allocate a buffer from the Channel
+ //
+ memset(&rom16, 0, sizeof(rom16)); // Zero out everything
+
+ rom16.cbBuffer = m_rom16.cbBuffer; // Tell it how big we want it!
+ rom16.rpcFlags = m_rom16.rpcFlags;
+ rom16.iMethod = m_rom16.iMethod;
+
+ hresult = m_prcb->GetBuffer( &rom16, m_opd.iid );
+ if ( FAILED(hresult) )
+ {
+ return hresult;
+ }
+
+ //
+ // BUGBUG - For speed, we could get away without doing the copy here
+ // by passing the buffer to the 32-bit world in the GetBuffer
+ // call above.
+ //
+ hmemcpy( rom16.Buffer, m_rom16.Buffer, m_rom16.cbBuffer );
+
+ //
+ // Call the channel
+ //
+ ulStatus = 0;
+ hresult = m_prcb->SendReceive( &rom16, &ulStatus );
+ if ( SUCCEEDED(hresult) )
+ {
+ ULARGE_INTEGER ularge_integer;
+
+ hresult = (HRESULT)ulStatus;
+
+ //
+ // Copy the buffer back!
+ //
+ ULISet32(ularge_integer,rom16.cbBuffer);
+ SetSize( ularge_integer ); // Make it big enough!
+
+ hmemcpy( m_rom16.Buffer, rom16.Buffer, rom16.cbBuffer );
+ }
+
+ //
+ // Free up the buffer
+ //
+ m_prcb->FreeBuffer( &rom16 );
+
+ return hresult;
+}
diff --git a/private/ole32/olethunk/ole16/compobj/dlltable.cxx b/private/ole32/olethunk/ole16/compobj/dlltable.cxx
new file mode 100644
index 000000000..a4418a5f3
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/dlltable.cxx
@@ -0,0 +1,285 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dlltable.cxx
+//
+// Contents: DLL table management
+//
+// History: 16-Mar-94 DrewB Taken from OLE2 16-bit sources
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <ole2int.h>
+#include <taskmap.h>
+#include <call32.hxx>
+#include <apilist.hxx>
+
+#include "dlltable.h"
+
+// FUTURE: move to some private header file
+INTERNAL_(void) ReleaseDemandLoadCO(Etask FAR& etask);
+
+// Keep only hInst. Always do LoadLibrary; if hInst already exist
+// do FreeLibrary. This is because GetModuleHandle(pLibName) doesn't
+// neccessarily return same value as LoadLibrary(pLibName).
+//
+HINSTANCE CDlls::GetLibrary(LPSTR pLibName, BOOL fAutoFree)
+{
+ UINT i, nFree, nOldErrorMode;
+ HINSTANCE hInst;
+
+#ifndef _MAC
+// REVIEW: The SetErrorMode calls turn of the Windows "File not found"
+// message box, assuming that the app will respond to the error code.
+// The name of the file that was not found will be lost by the time we
+// return to the app, however. We may want to reconsider this.
+
+ nOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
+ hInst = LoadLibrary(pLibName);
+ SetErrorMode(nOldErrorMode);
+#ifdef WIN32
+ if (hInst == NULL)
+#else
+ if (hInst < HINSTANCE_ERROR)
+#endif
+ return hInst;
+#else
+ hInst = WinLoadLibrary(pLibName);
+
+ if (hInst == HINSTANCE_ERROR)
+ return hInst;
+#endif
+
+ for (nFree = m_size, i = 0; i < m_size; i++) {
+
+ if (m_pDlls[i].refsTotal == 0) {
+ if (nFree > i)
+ nFree = i;
+ continue;
+ }
+
+ if (hInst == m_pDlls[i].hInst) {
+ m_pDlls[i].refsTotal++;
+ if (fAutoFree)
+ m_pDlls[i].refsAuto++;
+ FreeLibrary(hInst);
+ return hInst;
+ }
+ }
+
+ if (nFree == m_size) {
+ UINT newsize = m_size + 10;
+ void FAR* pMem = NULL;
+ IMalloc FAR* pMalloc;
+
+ if (CoGetMalloc(MEMCTX_TASK, &pMalloc) == 0) {
+ pMem = pMalloc->Realloc(m_pDlls, newsize * sizeof(m_pDlls[0]));
+ pMalloc->Release();
+ }
+
+ if (pMem == NULL) {
+ FreeLibrary(hInst);
+ return NULL; // Out of memory
+ }
+
+ _fmemset(((char FAR*) pMem) + m_size * sizeof(m_pDlls[0]),0,
+ (newsize - m_size) * sizeof(m_pDlls[0]));
+ *((void FAR* FAR*) &m_pDlls) = pMem;
+ m_size = newsize;
+ }
+
+ m_pDlls[nFree].hInst = hInst;
+ m_pDlls[nFree].refsTotal = 1;
+ m_pDlls[nFree].refsAuto = fAutoFree != 0;
+ m_pDlls[nFree].lpfnDllCanUnloadNow =
+ (LPFNCANUNLOADNOW)IGetProcAddress(hInst, "DllCanUnloadNow");
+
+#ifdef _DEBUG
+ // call it now to prevent dlls from using it to indicate they will be
+ // unloaded.
+ if (m_pDlls[nFree].lpfnDllCanUnloadNow != NULL)
+ (void)(*m_pDlls[nFree].lpfnDllCanUnloadNow)();
+#endif // _DEBUG
+
+ return hInst;
+}
+
+
+
+// unload library.
+void CDlls::ReleaseLibrary(HINSTANCE hInst)
+{
+ UINT i;
+
+ for (i = 0; i < m_size; i++) {
+
+ if (m_pDlls[i].refsTotal == 0)
+ continue;
+
+ if (hInst == m_pDlls[i].hInst) {
+
+ if (--m_pDlls[i].refsTotal == 0) {
+ Assert(m_pDlls[i].refsAuto == 0);
+ FreeLibrary(m_pDlls[i].hInst);
+ m_pDlls[i].hInst = NULL;
+ m_pDlls[i].lpfnDllCanUnloadNow = NULL;
+ }
+
+ return;
+ }
+ }
+}
+
+void CDlls::FreeAllLibraries(void)
+{
+ UINT i;
+
+ for (i = 0; i < m_size; i++) {
+
+ if (m_pDlls[i].refsTotal == 0)
+ continue;
+
+ // A dll loaded on behalf of this app hasn't been freed by it
+ //
+#ifdef _DEBUG
+ if (m_pDlls[i].refsTotal != m_pDlls[i].refsAuto) {
+ // not all references to this dll are auto load; print message
+ char pln[_MAX_PATH];
+
+ if (GetModuleFileName(m_pDlls[i].hInst,pln,_MAX_PATH) == 0)
+ lstrcpy(pln,"<unknown>");
+ Puts("WARNING in Uninitialize: Did not free ");
+ Puts(pln);
+ Puts("\r\n");
+ }
+#endif
+ FreeLibrary(m_pDlls[i].hInst);
+ }
+
+ CoMemFree(m_pDlls, MEMCTX_TASK);
+ m_size = 0;
+ m_pDlls = NULL;
+}
+
+
+// for all dlls, find lpfnDllCanUnloadNow; call it; do it
+void CDlls::FreeUnusedLibraries(void)
+{
+ static BOOL v_fReadUnloadOption = FALSE;
+ static BOOL v_fAllowUnloading = TRUE;
+ UINT i;
+
+ for (i = 0; i < m_size; i++) {
+
+ if (m_pDlls[i].refsTotal == 0)
+ continue;
+
+ if (m_pDlls[i].refsTotal != m_pDlls[i].refsAuto)
+ continue;
+
+ // have an auto-free dll (total refs == auto refs)
+
+ if (m_pDlls[i].lpfnDllCanUnloadNow == NULL)
+ continue;
+
+ if (!v_fReadUnloadOption) {
+ v_fAllowUnloading = GetProfileInt("windows",
+ "AllowOptimalDllUnload", TRUE);
+
+ v_fReadUnloadOption = TRUE;
+ }
+
+ // we want to actually make the call and then check the flag; that
+ // way, we ensure that the dlls are exercising their code, but we
+ // don't take action on it.
+ if ((*m_pDlls[i].lpfnDllCanUnloadNow)() == NOERROR &&
+ v_fAllowUnloading) {
+ FreeLibrary(m_pDlls[i].hInst);
+ m_pDlls[i].refsTotal = NULL;
+ m_pDlls[i].refsAuto = NULL;
+ m_pDlls[i].hInst = NULL;
+ m_pDlls[i].lpfnDllCanUnloadNow = NULL;
+ }
+ }
+}
+
+
+static INTERNAL_(BOOL) EnsureDllMap(CDlls FAR* FAR* ppDlls)
+{
+ HTASK hTask;
+ Etask etask;
+
+ if (!LookupEtask(hTask, etask))
+ return FALSE;
+
+ // BUGBUG - The original code used TASK-allocating operator new
+ if (etask.m_pDlls == NULL) {
+ if ((etask.m_pDlls = new FAR CDlls) == NULL)
+ return FALSE;
+
+ SetEtask(hTask, etask);
+ }
+
+ *ppDlls = etask.m_pDlls;
+ return TRUE;
+}
+
+
+STDAPI_(HINSTANCE) CoLoadLibrary(LPSTR pLibName, BOOL fAutoFree)
+{
+ CDlls FAR* pCDlls;
+
+ if (!EnsureDllMap(&pCDlls))
+ return NULL;
+
+ return pCDlls->GetLibrary(pLibName, fAutoFree);
+}
+
+STDAPI_(void) CoFreeLibrary(HINSTANCE hInst)
+{
+ CDlls FAR* pCDlls;
+
+ if (!EnsureDllMap(&pCDlls))
+ return;
+
+ pCDlls->ReleaseLibrary(hInst);
+}
+
+STDAPI_(void) CoFreeAllLibraries(void)
+{
+ thkDebugOut((DEB_ITRACE, "CoFreeAllLibraries\n"));
+ CDlls FAR* pCDlls;
+
+ if (!EnsureDllMap(&pCDlls))
+ return;
+
+ pCDlls->FreeAllLibraries();
+
+ // Also thunk the call to 32-bits
+ CallObjectInWOW(THK_API_METHOD(THK_API_CoFreeAllLibraries), NULL);
+ thkDebugOut((DEB_ITRACE, "CoFreeAllLibraries exit\n"));
+}
+
+STDAPI_(void) CoFreeUnusedLibraries(void)
+{
+ HTASK hTask;
+ Etask etask;
+
+ if (!LookupEtask(hTask, etask) || etask.m_pDlls == NULL)
+ return;
+
+#if 0
+ // BUGBUG - Do we need this? We won't be loading any class objects?
+ ReleaseDemandLoadCO(etask);
+#endif
+
+ etask.m_pDlls->FreeUnusedLibraries();
+
+ // Also thunk the call to 32-bits
+ CallObjectInWOW(THK_API_METHOD(THK_API_CoFreeUnusedLibraries), NULL);
+}
diff --git a/private/ole32/olethunk/ole16/compobj/dlltable.h b/private/ole32/olethunk/ole16/compobj/dlltable.h
new file mode 100644
index 000000000..a1e582d1b
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/dlltable.h
@@ -0,0 +1,40 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dlltable.h
+//
+// Contents: DLL tracking class
+//
+// Classes: CDll
+//
+// History: 16-Mar-94 DrewB Taken from OLE2 16-bit sources
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DLLTABLE_H__
+#define __DLLTABLE_H__
+
+class FAR CDlls
+{
+public:
+ HINSTANCE GetLibrary(LPSTR pLibName, BOOL fAutoFree);
+ void ReleaseLibrary(HINSTANCE hInst);
+ void FreeAllLibraries(void);
+ void FreeUnusedLibraries(void);
+
+ CDlls() { m_size = 0; m_pDlls = NULL; }
+ ~CDlls() {}
+
+private:
+ UINT m_size; // Number of entries
+ struct {
+ HINSTANCE hInst;
+ ULONG refsTotal; // total number of refs
+ ULONG refsAuto; // number of autounload refs
+ LPFNCANUNLOADNOW lpfnDllCanUnloadNow; // set on first load
+ } FAR* m_pDlls;
+};
+
+#endif // #ifndef __DLLTABLE_H__
diff --git a/private/ole32/olethunk/ole16/compobj/etask.cxx b/private/ole32/olethunk/ole16/compobj/etask.cxx
new file mode 100644
index 000000000..429a7def8
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/etask.cxx
@@ -0,0 +1,337 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ETASK.CXX (16 bit target)
+//
+// Contents: ETask management code, taken from 16-bit COMPOBJ.CPP
+//
+// Functions:
+//
+// History: 08-Mar-94 BobDay Copied parts from \\ole\slm\...\compobj.cpp
+// 01-Feb-95 JohannP modified/simplified
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <ole2sp.h>
+
+#include <olecoll.h>
+#include <map_kv.h>
+
+#include "comlocal.hxx"
+#include "map_htsk.h"
+#include "etask.hxx"
+
+#include "call32.hxx"
+#include "apilist.hxx"
+
+// NOTE: NEAR forces this variable to be in the default data segment; without
+// NEAR, the ambient model of the class CMapHandleEtask, which is FAR,
+// causes the variable to be in a far_data segment.
+//
+// BUGBUG32 - For WIN32/NT this table is in instance data, the table contains
+// exactly one entry
+//
+HTASK v_hTaskCache = NULL;
+Etask NEAR v_etaskCache;
+
+
+// quick check that the etask is valid (e.g., pointers are valid)
+INTERNAL_(BOOL) IsValidEtask(HTASK hTask, Etask FAR& etask)
+{
+ Win(Assert(GetCurrentProcess() == hTask));
+ thkDebugOut((DEB_DLLS16, "IsValidEtask (%X) pMalloc(%p)\n", hTask, etask.m_pMalloc));
+
+#ifdef _CHICAGO_
+ if ( etask.m_pMalloc != NULL
+ && !IsValidInterface(etask.m_pMalloc))
+#else
+ if (!IsValidInterface(etask.m_pMalloc))
+#endif
+ {
+ thkDebugOut((DEB_DLLS16, "IsValidEtask (%X) FALSE\n", hTask));
+ return FALSE;
+ }
+
+ // FUTURE: verify that stack segment is the same
+ // FUTURE: verify that hInst/hMod are the same
+ thkDebugOut((DEB_DLLS16, "IsValidEtask (%X) TRUE\n", hTask));
+
+ return TRUE;
+}
+
+
+// if task map empty, clear globals in case lib doesn't get unloaded
+INTERNAL_(void) CheckIfMapEmpty(void)
+{
+ // if no more entries, clear v_pMallocShared; this ensures we clear the
+ // variable if the app holds onto this pointer erroneously.
+ if (v_mapToEtask.IsEmpty()) {
+ v_pMallocShared = NULL;
+
+//
+// BUGBUG - Do we really need to do this? The real variable comes from
+// the 16-bit OLE remoting stuff... Since we are doing remoting in the 32-bit
+// world, do we need this?
+//
+#ifdef LATER
+ // HACK: clear this pointer too
+ extern CMapGUIDToPtr FAR* v_pMapCidToCFList;
+ v_pMapCidToCFList = NULL;
+#endif
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: LookupEtask
+//
+// Synopsis: get etask for current task (and also return hTask);
+// does not create if none
+//
+// Arguments: [hTask] --
+// [etask] --
+//
+// Returns:
+//
+// History: Ole16 created for CompObj 16 bit for Ole2
+// 2-03-95 JohannP (Johann Posch) modified/simplified
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(BOOL) LookupEtask(HTASK FAR& hTask, Etask FAR& etask)
+{
+ hTask = GetCurrentProcess();
+ thkDebugOut((DEB_DLLS16, "LookupEtask on Process (%X) \n", hTask));
+
+ if (hTask == v_hTaskCache)
+ {
+ thkDebugOut((DEB_DLLS16, "LookupEtask found in cache (%X) \n", hTask));
+ etask = v_etaskCache;
+ goto CheckEtask;
+ }
+
+ if (!v_mapToEtask.Lookup(hTask, etask))
+ {
+ thkDebugOut((DEB_DLLS16, "LookupEtask faild on lookup (%X) \n", hTask));
+ return FALSE;
+ }
+ else
+ {
+ thkDebugOut((DEB_DLLS16, "LookupEtask found in lookup (%X) \n", hTask));
+ }
+
+ // found etask; make this the current cache
+ v_hTaskCache = hTask;
+ v_etaskCache = etask;
+
+CheckEtask:
+ if (IsValidEtask(hTask, etask))
+ {
+ return TRUE;
+ }
+ else
+ {
+ // task got reused; kill cache and entry in map
+ v_hTaskCache = NULL;
+ v_mapToEtask.RemoveKey(hTask);
+ CheckIfMapEmpty();
+ thkAssert(0 && "LookupEtask - failed (invalid Etask)");
+ return FALSE;
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: SetEtask
+//
+// Synopsis: set etask for task given (must be current task); return FALSE
+// if OOM (only first time; all other times should return TRUE).
+//
+// Arguments: [hTask] --
+// [etask] --
+//
+// Returns:
+//
+// History: Ole16 created for CompObj 16 bit for Ole2
+// 02-03-95 JohannP (Johann Posch) modified/simplified
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(BOOL) SetEtask(HTASK hTask, Etask FAR& etask)
+{
+ Win(Assert(GetCurrentProcess() == hTask));
+
+ if (!v_mapToEtask.SetAt(hTask, etask))
+ return FALSE;
+
+ Assert(IsValidEtask(hTask, etask));
+
+ // map set; make this the current cache
+ v_hTaskCache = hTask;
+ v_etaskCache = etask;
+ return TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: ReleaseEtask
+//
+// Synopsis: release all fields in the etask; do all the task memory
+// (except the task allocator) first; then all the shared
+// memory (except the shared allocator); then the shared
+// allocator and finally the task allocator.
+// Also removes key if htask is given.
+//
+// Arguments: [htask] --
+// [etask] --
+//
+// Returns:
+//
+// History: Ole16 created for CompObj 16 bit for Ole2
+// 2-03-95 JohannP (Johann Posch) modified/simplified
+//
+// Notes: Called by daytona and chicago.
+//
+//----------------------------------------------------------------------------
+void ReleaseEtask(HTASK htask, Etask FAR& etask)
+{
+ thkDebugOut((DEB_DLLS16, "ReleaseEtask on Process (%X) \n", htask));
+ Assert(etask.m_inits == 1);
+ Assert(etask.m_oleinits == 0);
+ Assert(etask.m_reserved == 0);
+
+ // Release any state that may have been set
+ if (etask.m_punkState != NULL && IsValidInterface(etask.m_punkState))
+ {
+ etask.m_punkState->Release();
+#ifdef _CHICAGO_
+ if (!LookupEtask(htask, etask))
+ return;
+#endif
+ }
+ // first delete all task memory items
+ delete etask.m_pDlls; // task memory
+ delete etask.m_pMapToServerCO; // task memory
+ delete etask.m_pMapToHandlerCO; // task memory
+ delete etask.m_pArraySH; // task memory
+ Assert(etask.m_pCThrd == NULL); // task memory; must be gone by now
+
+
+ // remove key now that all task memory that will be freed is freed
+#ifdef _CHICAGO_
+ // Note: just null this out
+ // Key is removed later in RemoveEtask called
+ etask.m_pDlls = 0;
+ etask.m_pMapToServerCO = 0;
+ etask.m_pMapToHandlerCO = 0;
+ etask.m_pArraySH = 0;
+ etask.m_pCThrd = 0;
+
+#else
+
+ if (htask != NULL) {
+ v_mapToEtask.RemoveKey(htask);
+ }
+ // if no more entries, remove last remaining memory; this prevents
+ // problems if the dll is not unloaded for some reason before being
+ // used again.
+ if (v_mapToEtask.IsEmpty())
+ v_mapToEtask.RemoveAll();
+#endif
+
+
+ // now remove all shared memory (doesn't need access to task pMalloc)
+#ifdef NOTYET
+ if (etask.m_pMallocSBlock != NULL)
+ etask.m_pMallocSBlock->Release(); // in shared memory
+ if (etask.m_pMallocPrivate != NULL)
+ etask.m_pMallocPrivate->Release(); // in shared memory
+#endif
+
+#ifndef _CHICAGO_
+
+ Assert(etask.m_pMallocShared != NULL);
+ if (etask.m_pMallocShared->Release() == 0) { // in shared memory
+ // last use of the shared allocator; set global to null
+ v_pMallocShared = NULL;
+ Assert(v_mapToEtask.IsEmpty());
+ }
+
+ CheckIfMapEmpty();
+#endif
+
+
+ // finally, release the task memory
+ Assert(etask.m_pMalloc != NULL);
+ etask.m_pMalloc->Release(); // in task memory
+ etask.m_pMalloc = NULL;
+ thkDebugOut((DEB_DLLS16, "ReleaseEtask (%X) pMalloc(%p)\n", htask, etask.m_pMalloc));
+
+#if defined(_CHICAGO_)
+ // Note: update the etask now. Will be deleted on
+ // DllEntryPoint when refcount is zero by Remove Etask.
+ SetEtask(htask,etask);
+#endif
+
+
+ // invalidate cache
+ v_hTaskCache = NULL;
+ thkDebugOut((DEB_DLLS16, "ReleaseEtask done on (%X) \n", htask));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: RemoveEtask
+//
+// Synopsis: Releases the shares allocator and removes
+// the etask from the global list
+//
+// Arguments: [hTask] -- htask
+// [etask] -- etask
+//
+// Returns:
+//
+// History: 2-03-95 JohannP (Johann Posch) Created
+//
+// Notes: Called only by Chicago.
+//
+//----------------------------------------------------------------------------
+STDAPI_(BOOL) RemoveEtask(HTASK FAR& hTask, Etask FAR& etask)
+{
+ hTask = GetCurrentProcess();
+ thkDebugOut((DEB_DLLS16, "RemoveEtask on Process (%X) \n", hTask));
+
+ if (hTask == v_hTaskCache)
+ {
+ v_hTaskCache = NULL;
+ }
+ v_mapToEtask.RemoveKey(hTask);
+
+ if (v_mapToEtask.IsEmpty())
+ v_mapToEtask.RemoveAll();
+
+ thkAssert(etask.m_pMallocShared != NULL);
+ if(etask.m_pMallocShared->Release() == 0)
+ {
+ // in shared memory
+ // last use of the shared allocator; set global to null
+ v_pMallocShared = NULL;
+ thkDebugOut((DEB_DLLS16, "RemoveEtask Set v_pMallocShared to NULL (%X) \n", hTask));
+ Assert(v_mapToEtask.IsEmpty());
+ }
+
+ CheckIfMapEmpty();
+
+ thkDebugOut((DEB_DLLS16, "RemoveEtask done (%X) \n", hTask));
+
+ return TRUE;
+}
+
diff --git a/private/ole32/olethunk/ole16/compobj/go1632pr.cxx b/private/ole32/olethunk/ole16/compobj/go1632pr.cxx
new file mode 100644
index 000000000..b2aaff328
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/go1632pr.cxx
@@ -0,0 +1,230 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: GO1632Pr.cxx (16 bit target)
+//
+// Contents: Functions to thunk interface pointer from 16 to 32 bit.
+//
+// Functions:
+//
+// History: 13-Dec-93 JohannP Created
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <call32.hxx>
+#include <obj16.hxx>
+#include <go1632pr.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Macro: DEFINE_METHOD
+//
+// Synopsis: Defines a generic 16->32 proxy method
+//
+// History: 23-Feb-94 DrewB Created
+//
+//
+// Notes: A proxy method's primary reason for existence is to
+// get into the 32-bit world with a pointer to the 16-bit
+// stack. This is accomplished by taking the address of
+// the this pointer. Since methods are cdecl, this works
+// for methods with any number of parameters because the
+// first parameter is always the one closest to the return
+// address.
+// The method also passed on the object ID and the method
+// index so that the method's arguments can be properly
+// thunked on the 32-bit side
+//
+//----------------------------------------------------------------------------
+
+#define DEFINE_METHOD(n) \
+STDMETHODIMP_(DWORD) Proxy1632Method##n(THUNK1632OBJ FAR *ptoThis16) \
+{ \
+ thkDebugOut((DEB_THUNKMGR, "Proxy1632Method: %p(%d)\n", ptoThis16, n)); \
+ return CallObjectInWOW( n, CDECL_STACK_PTR(ptoThis16)); \
+}
+
+
+#if DBG == 1
+
+#pragma pack(1)
+struct SplitGuid
+{
+ DWORD dw1;
+ WORD w1;
+ WORD w2;
+ BYTE b[8];
+};
+#pragma pack()
+
+char *GuidString(GUID const *pguid)
+{
+ static char ach[39];
+ SplitGuid *psg = (SplitGuid *)pguid;
+
+ wsprintf(ach, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
+ psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
+ return ach;
+}
+
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: Proxy1632QueryInterface, public
+//
+// Synopsis: QueryInterface for the proxy object.
+//
+// History: 01-Apr-94 JohannP Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(DWORD) Proxy1632QueryInterface(THUNK1632OBJ FAR *ptoThis16,
+ REFIID refiid,
+ LPVOID *ppv)
+{
+ DWORD dwRet;
+ LPVOID lpvoid = (LPVOID)&refiid;
+ IID iid = refiid;
+
+ thkDebugOut((DEB_THUNKMGR, " Proxy1632QueryInterface: %p %s\n",
+ ptoThis16, GuidString((IID const *)&iid) ));
+
+ // BUGBUG - Why do we make a copy of the iid only so that we can over-write
+ // it so that we can return the pointer to it in it? This should be
+ // re-written.
+ //
+ dwRet = CallProcIn32((DWORD)ptoThis16, SMI_QUERYINTERFACE, (DWORD)&iid,
+ lpIUnknownObj32, 0, CP32_NARGS);
+ *ppv = (LPVOID) iid.Data1;
+
+ thkDebugOut(( DEB_THUNKMGR,
+ "Out Proxy1632QueryInterface: (%p)->%p scRet:0x%08lx\n",
+ ptoThis16, *ppv, dwRet));
+
+ return dwRet;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Proxy1632AddRef, public
+//
+// Synopsis: AddRef for the generic proxy object
+//
+// History: 01-Apr-94 JohannP Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(DWORD) Proxy1632AddRef(THUNK1632OBJ FAR *ptoThis16)
+{
+ DWORD dwRet;
+
+ thkDebugOut(( DEB_THUNKMGR, "In Proxy1632AddRef: %p \n",ptoThis16));
+
+ dwRet = CallProcIn32((DWORD)ptoThis16, SMI_ADDREF, 0,
+ lpIUnknownObj32, 0, CP32_NARGS);
+
+ thkDebugOut(( DEB_THUNKMGR, "Out Proxy1632AddRef: %p dwRet:%ld\n",
+ ptoThis16, dwRet));
+
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Proxy1632Release, public
+//
+// Synopsis: Release for the proxy object.
+//
+// History: 01-Apr-94 JohannP Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(DWORD) Proxy1632Release(THUNK1632OBJ FAR *ptoThis16)
+{
+ DWORD dwRet;
+
+ thkDebugOut(( DEB_THUNKMGR, "In Proxy1632Release: %p\n", ptoThis16));
+
+ dwRet = CallProcIn32((DWORD)ptoThis16, SMI_RELEASE, 0,
+ lpIUnknownObj32, 0, CP32_NARGS);
+
+ thkDebugOut(( DEB_THUNKMGR, "Out Proxy1632Release: %p dwRet:%ld\n",
+ ptoThis16,dwRet));
+
+ return dwRet;
+}
+
+// Additional methods so that any possible interface can be represented
+// using the vtable made up out of all the methods
+
+DEFINE_METHOD(3)
+DEFINE_METHOD(4)
+DEFINE_METHOD(5)
+DEFINE_METHOD(6)
+DEFINE_METHOD(7)
+DEFINE_METHOD(8)
+DEFINE_METHOD(9)
+DEFINE_METHOD(10)
+DEFINE_METHOD(11)
+DEFINE_METHOD(12)
+DEFINE_METHOD(13)
+DEFINE_METHOD(14)
+DEFINE_METHOD(15)
+DEFINE_METHOD(16)
+DEFINE_METHOD(17)
+DEFINE_METHOD(18)
+DEFINE_METHOD(19)
+DEFINE_METHOD(20)
+DEFINE_METHOD(21)
+DEFINE_METHOD(22)
+DEFINE_METHOD(23)
+DEFINE_METHOD(24)
+DEFINE_METHOD(25)
+DEFINE_METHOD(26)
+DEFINE_METHOD(27)
+DEFINE_METHOD(28)
+DEFINE_METHOD(29)
+DEFINE_METHOD(30)
+DEFINE_METHOD(31)
+
+// A vtable which will end up calling back to our proxy methods
+DWORD atfnProxy1632Vtbl[] =
+{
+ (DWORD)Proxy1632QueryInterface,
+ (DWORD)Proxy1632AddRef,
+ (DWORD)Proxy1632Release,
+ (DWORD)Proxy1632Method3,
+ (DWORD)Proxy1632Method4,
+ (DWORD)Proxy1632Method5,
+ (DWORD)Proxy1632Method6,
+ (DWORD)Proxy1632Method7,
+ (DWORD)Proxy1632Method8,
+ (DWORD)Proxy1632Method9,
+ (DWORD)Proxy1632Method10,
+ (DWORD)Proxy1632Method11,
+ (DWORD)Proxy1632Method12,
+ (DWORD)Proxy1632Method13,
+ (DWORD)Proxy1632Method14,
+ (DWORD)Proxy1632Method15,
+ (DWORD)Proxy1632Method16,
+ (DWORD)Proxy1632Method17,
+ (DWORD)Proxy1632Method18,
+ (DWORD)Proxy1632Method19,
+ (DWORD)Proxy1632Method20,
+ (DWORD)Proxy1632Method21,
+ (DWORD)Proxy1632Method22,
+ (DWORD)Proxy1632Method23,
+ (DWORD)Proxy1632Method24,
+ (DWORD)Proxy1632Method25,
+ (DWORD)Proxy1632Method26,
+ (DWORD)Proxy1632Method27,
+ (DWORD)Proxy1632Method28,
+ (DWORD)Proxy1632Method29,
+ (DWORD)Proxy1632Method30,
+ (DWORD)Proxy1632Method31
+};
diff --git a/private/ole32/olethunk/ole16/compobj/go1632pr.hxx b/private/ole32/olethunk/ole16/compobj/go1632pr.hxx
new file mode 100644
index 000000000..c77024adb
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/go1632pr.hxx
@@ -0,0 +1,22 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: go1632pr.hxx
+//
+// Contents: 16->32 generic object proxy
+//
+// History: 18-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __GO1632PR_HXX__
+#define __GO1632PR_HXX__
+
+STDMETHODIMP_(DWORD) Proxy1632QueryInterface(THUNK1632OBJ FAR *ptoThis16,
+ REFIID refiid, LPVOID *ppv);
+
+extern DWORD atfnProxy1632Vtbl[];
+
+#endif // #ifndef __GO1632PR_HXX__
diff --git a/private/ole32/olethunk/ole16/compobj/headers.cxx b/private/ole32/olethunk/ole16/compobj/headers.cxx
new file mode 100644
index 000000000..ece0b03c5
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/headers.cxx
@@ -0,0 +1,21 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: headers.cxx
+//
+// Contents: Precompiled header file
+//
+// History: 18-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <windows.h>
+#include <string.h>
+#include <ole2.h>
+#include <valid.h>
+
+#include <interop.hxx>
+#include <wow16fn.h>
+#include <io16.h>
diff --git a/private/ole32/olethunk/ole16/compobj/makefile b/private/ole32/olethunk/ole16/compobj/makefile
new file mode 100644
index 000000000..715c69977
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/makefile
@@ -0,0 +1,76 @@
+#
+# Copyright (c) 1991, Microsoft Corporation
+#
+# History:
+#
+# 18-Feb-1994 BobDay Adapted from MVDM\WOW16\GDI\MAKEFILE
+#
+
+!IFDEF USEBUILD
+
+# If using BUILD.EXE, edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2.
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!ELSE
+
+default: copy_bin
+
+TARGET = compobj.dll
+
+CFILES = \
+ .\comdthk.c
+
+CXXFILES = \
+ .\compobj.cxx \
+ .\comlocal.cxx \
+ .\etask.cxx \
+ .\call32.cxx \
+ .\comguid.cxx \
+ .\go1632pr.cxx \
+ .\stdalloc.cxx \
+ .\memctx.cxx \
+ .\clstub16.cxx \
+ .\valid.cxx \
+ .\dlltable.cxx
+
+RCFILES = .\compobj.rc
+
+LIBS = $(LIBS)\
+ ..\coll\$(OBJDIR)\coll.lib \
+ ..\lib\ole2.lib
+
+!if "$(NTDEBUG)" != "" && "$(NTDEBUG)" != "retail"
+LIBS = $(LIBS) $(OLETHUNK)\debnot\$(OBJDIR)\debnot.lib
+!endif
+
+!include ..\makefile.inc
+
+copy_bin: all
+ -binplace $(OBJDIR)\compobj.dll
+ -binplace $(OBJDIR)\compobj.sym
+ -binplace $(OBJDIR)\compobj.map
+
+compobj.obj: compobj.cxx
+
+comdthk.obj: comdthk.c
+
+comlocal.obj: comlocal.cxx
+
+etask.obj: etask.cxx
+
+call32.obj: call32.cxx
+
+comguid.obj: comguid.cxx
+
+go1632pr.obj: go1632pr.cxx
+
+stdalloc.obj: stdalloc.cxx
+
+valid.obj: valid.cxx
+
+clstub16.obj: clstub16.cxx
+
+!ENDIF
diff --git a/private/ole32/olethunk/ole16/compobj/memctx.cxx b/private/ole32/olethunk/ole16/compobj/memctx.cxx
new file mode 100644
index 000000000..41542ca4f
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/memctx.cxx
@@ -0,0 +1,109 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: memctx.cxx
+//
+// Contents: all memory management for compobj dll (exported as well)
+//
+// Classes:
+//
+// Functions:
+//
+// History: 10-Mar-94 bobday Ported from ole2.01 (16-bit)
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <ole2sp.h>
+
+#include <olecoll.h>
+#include <map_kv.h>
+#include <memctx.hxx>
+
+#include "comlocal.hxx"
+#include "map_htsk.h"
+#include "etask.hxx"
+
+
+ASSERTDATA
+
+STDAPI_(DWORD) CoMemctxOf(void const FAR* lpv)
+{
+ Etask etask;
+ HTASK htask;
+ int iDidTaskAlloc;
+
+ if (lpv == NULL)
+ return MEMCTX_UNKNOWN;
+
+ // try shared memory first because of a bootstrapping problem when setting
+ // the Etask the first time.
+ if (v_pMallocShared != NULL && v_pMallocShared->DidAlloc((LPVOID)lpv) == 1)
+ return MEMCTX_SHARED;
+
+ // now try the other contexts by getting the pointers to their mallocs
+ if (!LookupEtask(htask, etask))
+ return MEMCTX_UNKNOWN;
+
+ Assert(etask.m_pMalloc != NULL); // should always have one
+ if ((iDidTaskAlloc = etask.m_pMalloc->DidAlloc((LPVOID)lpv)) == 1)
+ return MEMCTX_TASK;
+
+ Assert(etask.m_pMallocShared == NULL || etask.m_pMallocShared == v_pMallocShared);
+
+#ifdef NOTYET
+ if (etask.m_pMallocSBlock != NULL && etask.m_pMallocSBlock->DidAlloc((LPVOID)lpv) == 1)
+ return MEMCTX_SHAREDBLOCK;
+
+ if (etask.m_pMallocPrivate != NULL && etask.m_pMallocPrivate->DidAlloc((LPVOID)lpv) == 1)
+ return MEMCTX_COPRIVATE;
+#endif
+
+ // last ditch effort: if the task allocator returned -1 (may have alloc'd),
+ // then we assume it is task memory. We do this after the above tests
+ // since we would prefer to be exact.
+ if (iDidTaskAlloc == -1)
+ return MEMCTX_TASK;
+
+ return MEMCTX_UNKNOWN;
+}
+
+
+STDAPI_(void FAR*) CoMemAlloc(ULONG size, DWORD memctx, void FAR* lpvNear)
+{
+ if (memctx == MEMCTX_SAME)
+ {
+ AssertSz(lpvNear != NULL,0);
+ memctx = CoMemctxOf(lpvNear);
+ }
+ else
+ AssertSz(lpvNear == NULL,0);
+
+ IMalloc FAR* pMalloc;
+ void FAR* lpv = NULL; // stays null if bad context or out of memory
+ if (CoGetMalloc(memctx, &pMalloc) == 0) {
+ lpv = pMalloc->Alloc(size);
+ pMalloc->Release();
+ }
+ return lpv;
+}
+
+
+STDAPI_(void) CoMemFree(void FAR* lpv, DWORD memctx)
+{
+ if (lpv == NULL)
+ return;
+
+ if (memctx == MEMCTX_UNKNOWN)
+ memctx = CoMemctxOf(lpv);
+
+ IMalloc FAR* pMalloc;
+ if (CoGetMalloc(memctx, &pMalloc) == 0) {
+ pMalloc->Free(lpv);
+ pMalloc->Release();
+ }
+}
diff --git a/private/ole32/olethunk/ole16/compobj/rpc16.cxx b/private/ole32/olethunk/ole16/compobj/rpc16.cxx
new file mode 100644
index 000000000..e1ab2e019
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/rpc16.cxx
@@ -0,0 +1,379 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: rpc16.cxx
+//
+// Contents: Maps the 16-bit IRpcChannel implementation to a 16-bit
+// implementation of IRpcChannelBuffer.
+//
+// This is required to support custom interface marshalling.
+//
+// History: 30-Mar-94 BobDay Adapted from OLELRPC.CPP
+//
+//--------------------------------------------------------------------------
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <ole2ver.h>
+
+#include <ole2sp.h>
+
+#include "rpc16.hxx"
+
+interface IRpcChannel : public IUnknown
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE GetStream
+ (
+ REFIID riid,
+ int iMethod,
+ BOOL fSend,
+ BOOL fNoWait,
+ DWORD size,
+ IStream FAR * FAR *ppIStream
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Call
+ (
+ IStream FAR * pIStream
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDestCtx
+ (
+ DWORD *pdwDestContext,
+ void **ppvDestContext
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsConnected
+ (
+ void
+ ) = 0;
+
+};
+
+//
+// 16-bit IRpcChannel interface, stream-based
+//
+// This is the interface seen by the 16-bit proxy implementations
+//
+class CRpcChannel : public IRpcChannel
+{
+public:
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppvObject);
+ ULONG STDMETHODCALLTYPE AddRef(void);
+ ULONG STDMETHODCALLTYPE Release(void);
+
+ STDMETHOD(GetStream)(REFIID iid, int iMethod, BOOL fSend,
+ BOOL fNoWait, DWORD size, IStream FAR* FAR* ppIStream);
+ STDMETHOD(Call)(IStream FAR* pIStream);
+ STDMETHOD(GetDestCtx)(DWORD FAR* lpdwDestCtx, LPVOID FAR* lplpvDestCtx);
+ STDMETHOD(IsConnected)(void);
+
+ CRpcChannel FAR *CRpcChannel::Create( CRpcChannelBuffer FAR *prcb );
+
+private:
+ CRpcChannel::CRpcChannel( CRpcChannelBuffer FAR *prcb );
+ CRpcChannel::~CRpcChannel( void );
+
+ ULONG m_refs; // Reference count
+ CRpcChannelBuffer FAR * m_prcb; // ChannelBuffer to talk through
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Implementation of CRpcChannel
+//
+//--------------------------------------------------------------------------
+
+//+---------------------------------------------------------------------------
+//
+// Function: Create, public
+//
+// Synopsis: Creates a 16-bit CRpcChannel and gives it the
+// IRpcChannelBuffer that in needs to call.
+//
+// Arguments: [prcb] - IRpcChannelBuffer to call when called
+//
+// Returns: IRpcChannel *, Null on failure
+//
+// History: 30-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+CRpcChannel FAR *CRpcChannel::Create( CRpcChannelBuffer FAR *prcb )
+{
+ CRpcChannel FAR *pRC;
+
+ pRC = new CRpcChannel( prcb );
+
+ return( pRC );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Constructor, private
+//
+// Synopsis: Creates a 16-bit CRpcChannel and gives it the
+// IRpcChannelBuffer that in needs to call.
+//
+// Arguments: [prcb] - IRpcChannelBuffer to call when called
+//
+// Returns: IRpcChannel *, Null on failure
+//
+// History: 30-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+CRpcChannel::CRpcChannel( CRpcChannelBuffer FAR *prcb )
+{
+ m_refs = 1;
+ m_prcb = prcb; // Save it and addref it
+ if ( m_prcb != NULL )
+ {
+ m_prcb->AddRef();
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Destructor, private
+//
+// Synopsis: Destroys the CRpcChannel object
+//
+// Arguments: none
+//
+// Returns: nothing
+//
+// History: 30-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+CRpcChannel::~CRpcChannel( void )
+{
+ if ( m_prcb != NULL )
+ {
+ m_prcb->Release(); // Release it and zero it
+ m_prcb = NULL;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: QueryInterface, public
+//
+// Synopsis: Allows querying for other interfaces supported by this
+// object
+//
+// Arguments: [iidInterface] - iid to query for
+// [ppv] - interface pointer returned
+//
+// Returns: nothing
+//
+// History: 30-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CRpcChannel::QueryInterface(
+ REFIID iidInterface,
+ void FAR* FAR* ppvObj )
+{
+ HRESULT hresult;
+
+ // Two interfaces supported: IUnknown, IRpcChannel
+
+ if (iidInterface == IID_IUnknown || iidInterface == IID_IRpcChannel)
+ {
+ m_refs++; // A pointer to this object is returned
+ *ppvObj = this;
+ hresult = NOERROR;
+ }
+ else
+ {
+ *ppvObj = NULL;
+ hresult = ResultFromScode(E_NOINTERFACE);
+ }
+
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: AddRef, public
+//
+// Synopsis: Increments object reference count, called when object is
+// referenced by another pointer/client.
+//
+// Arguments: none
+//
+// Returns: new reference count
+//
+// History: 30-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CRpcChannel::AddRef(void)
+{
+ return ++m_refs;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Release, public
+//
+// Synopsis: Decrements object reference count and handles necessary
+// self-destruction and sub-releasing, called when object is
+// no longer referenced by another pointer/client.
+//
+// Arguments: none
+//
+// Returns: new reference count
+//
+// History: 30-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CRpcChannel::Release(void)
+{
+ if (--m_refs != 0) // Object still alive?
+ {
+ return m_refs;
+ }
+
+ delete this; // Suicide
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetStream, public
+//
+// Synopsis: Create an IStream onto which the client can write in
+// preparation for making an RPC call with the stream contents
+// as parameters.
+//
+// Arguments: [iid] - IID of interface being RPC'd
+// [iMethod] - Method # within interface
+// [fSend] - Should we use SendMessage?
+// [fNoWait] - Should we be asynchronous?
+// [size] - Initial size of stream
+// [ppIStream] - Output IStream
+//
+// Returns: HRESULT for success/failure
+// [ppIStream] - IStream for writing parameters
+//
+// History: 30-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CRpcChannel::GetStream(
+ REFIID iid,
+ int iMethod,
+ BOOL fSend,
+ BOOL fNoWait,
+ DWORD size,
+ IStream FAR* FAR* ppIStream )
+{
+ CPkt FAR* pCPkt;
+
+ // no point in allowing this to succeed if we are not connected
+ if ( IsConnected() != NOERROR )
+ {
+ // Connection terminated (server died or disconnectd)
+ return ResultFromScode(RPC_E_CONNECTION_TERMINATED);
+ }
+
+ pCPkt = CPkt::CreateForCall(this,iid,iMethod,fSend,fNoWait,size);
+ if (pCPkt == NULL)
+ {
+ *ppIStream = NULL;
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ if (pCPkt->QueryInterface(IID_IStream,(void FAR* FAR*) ppIStream)
+ != NOERROR)
+ {
+ pCPkt->Release();
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ pCPkt->SetRpcChannelBuffer( m_prcb );
+
+ pCPkt->Release();
+
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Call, public
+//
+// Synopsis: Sends a call to a remote procedure. Previously, all of the
+// parameters for the procedure were serialized into the IStream
+// which was passed in.
+//
+// Arguments: [pIStream] - IStream for parameters to procedure
+//
+// Returns: HRESULT for success/failure of call or procedure
+//
+// History: 30-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CRpcChannel::Call(
+ IStream FAR * pIStream )
+{
+ HRESULT hresult;
+ CPkt FAR * pCPkt;
+
+ hresult = pIStream->QueryInterface(IID_CPkt,(void FAR* FAR*) &pCPkt);
+ if (hresult != NOERROR)
+ {
+ return ResultFromScode(E_INVALIDARG);
+ }
+
+ return pCPkt->CallRpcChannelBuffer();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetDestCtx, public
+//
+// Synopsis: According to the code in OLELRPC.CPP, this is all this code
+// does, presumably, it might be expanded in the future.
+//
+// Arguments:
+//
+// Returns:
+//
+// History: 30-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CRpcChannel::GetDestCtx(
+ DWORD FAR * lpdwDestCtx,
+ LPVOID FAR * lplpvDestCtx )
+{
+ *lpdwDestCtx = NULL;
+ if (lplpvDestCtx)
+ {
+ *lplpvDestCtx = NULL;
+ }
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsConnected, public
+//
+// Synopsis: According to the code in OLELRPC.CPP, this is all this code
+// does, presumably, it might be expanded in the future.
+//
+// Arguments: none
+//
+// Returns: HRESULT indicating connection status
+//
+// History: 30-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CRpcChannel::IsConnected( void )
+{
+ if ( m_prcb == NULL )
+ {
+ return ResultFromScode(E_UNEXPECTED);
+ }
+ return m_prcb->IsConnected();
+}
diff --git a/private/ole32/olethunk/ole16/compobj/rpc16.hxx b/private/ole32/olethunk/ole16/compobj/rpc16.hxx
new file mode 100644
index 000000000..340004e15
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/rpc16.hxx
@@ -0,0 +1,138 @@
+//
+// Common stuff between RPC16.CXX and CPKT.CXX
+//
+
+typedef unsigned long RPCOLEDATAREP16;
+
+#define RPCFLG_ASYNCHRONOUS 0x40000000
+#define RPCFLG_INPUT_SYNCHRONOUS 0x20000000
+
+typedef struct tagRPCOLEMESSAGE16
+{
+ LPVOID reserved1;
+ RPCOLEDATAREP16 dataRepresentation;
+ LPVOID Buffer;
+ ULONG cbBuffer;
+ ULONG iMethod;
+ LPVOID reserved2[5];
+ ULONG rpcFlags;
+} RPCOLEMESSAGE16, FAR *LPRPCOLEMESSAGE16;
+
+typedef struct tagOTHERPKTDATA
+{
+ IID iid;
+ ULONG cbSize;
+} OTHERPKTDATA, FAR *LPOTHERPKTDATA;
+
+interface IRpcChannelBuffer : public IUnknown
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE GetBuffer
+ (
+ RPCOLEMESSAGE16 *pMessage,
+ REFIID riid
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SendReceive
+ (
+ RPCOLEMESSAGE16 *pMessage,
+ ULONG *pStatus
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FreeBuffer
+ (
+ RPCOLEMESSAGE16 *pMessage
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDestCtx
+ (
+ DWORD *pdwDestContext,
+ void **ppvDestContext
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsConnected
+ (
+ void
+ ) = 0;
+
+};
+
+//
+// 16-bit IRpcChannelBuffer interface, buffer-based
+//
+// This is the interface that will be seen by the 32-bit proxy implementations
+//
+class CRpcChannelBuffer : public IRpcChannelBuffer
+{
+public:
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppvObject);
+ ULONG STDMETHODCALLTYPE AddRef(void);
+ ULONG STDMETHODCALLTYPE Release(void);
+
+ HRESULT STDMETHODCALLTYPE GetBuffer(RPCOLEMESSAGE16 *pMessage,REFIID riid);
+ HRESULT STDMETHODCALLTYPE SendReceive(RPCOLEMESSAGE16 *pMessage,ULONG *pStatus);
+ HRESULT STDMETHODCALLTYPE FreeBuffer(RPCOLEMESSAGE16 *pMessage);
+ HRESULT STDMETHODCALLTYPE GetDestCtx(DWORD *pdwDestContext,void **ppvDestContext);
+ HRESULT STDMETHODCALLTYPE IsConnected( void);
+private:
+
+};
+
+#define IID_CPkt IID_NULL // BUGBUG in OLELRPC.H (you gotta love it)
+
+class FAR CPkt : public IStream // Passed between client, server
+{
+public:
+ STDMETHOD(QueryInterface) (REFIID iidInterface, void FAR* FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+ STDMETHOD(Read) (VOID HUGEP* pv, ULONG cb, ULONG FAR* pcbRead);
+ STDMETHOD(Write) (VOID const HUGEP* pv, ULONG cb, ULONG FAR* pcbWritten);
+ STDMETHOD(Seek) (LARGE_INTEGER dlibMove, DWORD dwOrigin,
+ ULARGE_INTEGER FAR* plibNewPosition);
+ STDMETHOD(SetSize) (ULARGE_INTEGER cb);
+ STDMETHOD(CopyTo) (IStream FAR* pstm, ULARGE_INTEGER cb,
+ ULARGE_INTEGER FAR* pcbRead,
+ ULARGE_INTEGER FAR* pcbWritten);
+ STDMETHOD(Commit) (DWORD grfCommitFlags);
+ STDMETHOD(Revert) (void);
+ STDMETHOD(LockRegion) (ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion) (ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat) (STATSTG FAR* pstatstg, DWORD statflag);
+ STDMETHOD(Clone)(IStream FAR * FAR *ppstm);
+
+ STDMETHOD(SetRpcChannelBuffer) ( CRpcChannelBuffer FAR *pRpcCB );
+ STDMETHOD(CallRpcChannelBuffer) ( void );
+
+ static CPkt FAR* CreateForCall(IUnknown FAR *pUnk, REFIID iid,
+ int iMethod, BOOL fSend, BOOL fAsync,
+ DWORD size);
+
+ ~CPkt() {}
+
+ctor_dtor:
+ CPkt()
+ {
+ m_refs = 1;
+ m_pos = 0;
+ m_prcb = NULL;
+
+ memset( &m_rom16, 0, sizeof(m_rom16)); // Zero out RPCOLEMESSAGE16
+ memset( &m_opd, 0, sizeof(m_opd)); // Zero out OTHERPKTDATA
+ }
+
+private:
+ ULONG m_refs; // Number of references to this CPkt
+ ULONG m_pos; // Seek pointer for Read/Write
+
+ CRpcChannelBuffer FAR * m_prcb; // IRpcChannelBuffer to call
+
+ RPCOLEMESSAGE16 m_rom16; // For IRpcChannelBuffer transportability
+ OTHERPKTDATA m_opd; // Saving of other info
+
+
+ // uninitialized CPkt
+ static CPkt FAR* Create(IUnknown FAR *pUnk, DWORD cbExt);
+};
diff --git a/private/ole32/olethunk/ole16/compobj/stdalloc.cxx b/private/ole32/olethunk/ole16/compobj/stdalloc.cxx
new file mode 100644
index 000000000..908577da4
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/stdalloc.cxx
@@ -0,0 +1,493 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: stdalloc.cxx
+//
+// Contents: 16-bit OLE allocator
+//
+// Classes:
+//
+// Functions:
+//
+// History: 3-07-94 kevinro Ported from ole2.01 (16-bit)
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <ole2sp.h>
+
+/****** Standard Task/Shared Allocator **********************************/
+
+#define NULLSAB ((__segment)0)
+
+typedef __segment SAB;
+
+// amount of space windows reserves at start of segment
+#define cbWinRes 16
+
+// amount of space LocalInit takes (somewhat empirical)
+#define cbWinOH (6+10+46)
+
+// total overhead per global block
+#define cbTotalOH (cbWinRes + sizeof(StdAllocHdr) + cbWinOH + 32)
+
+// maximum sized object in a SAB (fudged to include space for per-block
+// overhead and most anything else we missed).
+#define cbMaxSAB (0xfffe - cbTotalOH)
+
+//+---------------------------------------------------------------------------
+//
+// Class: CStdMalloc ()
+//
+// Purpose: Standard task allocator
+//
+// History: 3-04-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+class FAR CStdMalloc : public IMalloc
+{
+public:
+ CStdMalloc(DWORD memctx)
+ {
+ m_refs = 1;
+ m_pStdAllocHead = NULL;
+ m_flags = (memctx == MEMCTX_TASK)? GMEM_MOVEABLE :
+ GMEM_MOVEABLE|GMEM_SHARE;
+ }
+
+ STDMETHOD(QueryInterface)(REFIID iid, void FAR* FAR* ppvObj)
+ {
+ VDATEPTROUT( ppvObj, LPVOID );
+ *ppvObj = NULL;
+ VDATEIID( iid );
+
+ if (iid == IID_IUnknown || iid == IID_IMalloc) {
+ *ppvObj = this;
+ ++m_refs;
+ return NOERROR;
+ } else {
+ *ppvObj = NULL;
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+ }
+
+ STDMETHOD_(ULONG,AddRef)(void) { return ++m_refs; }
+
+ STDMETHOD_(ULONG,Release)(void)
+ {
+ if (--m_refs == 0) {
+ // free all memory (includes the memory for this class)
+ FreeAllMem();
+ return 0;
+ } else
+ return m_refs;
+ }
+
+ STDMETHOD_(void FAR*, Alloc) (ULONG cb);
+ STDMETHOD_(void FAR*, Realloc) (void FAR* pv, ULONG cb);
+ STDMETHOD_(void, Free) (void FAR* pv);
+ STDMETHOD_(ULONG, GetSize) (void FAR* pv);
+ STDMETHOD_(int, DidAlloc) (void FAR* pv);
+ STDMETHOD_(void, HeapMinimize) ();
+
+private:
+ ULONG m_refs;
+ UINT m_flags;
+
+ #define STDALLOC_SIG 0x4D445453 // 'STDM'
+
+ struct StdAllocHdr
+ {
+ ULONG m_Signature;
+ HTASK m_hTask; // task which owns this block
+ StdAllocHdr FAR* m_pStdAllocNext;
+ };
+
+ StdAllocHdr FAR* m_pStdAllocHead;
+
+ INTERNAL_(StdAllocHdr FAR*) MapBlockToSA(SAB sab) { return (StdAllocHdr FAR*)MAKELONG(cbWinRes, sab); }
+ INTERNAL_(SAB) MapSAToBlock(StdAllocHdr FAR* pSA) { return (__segment)pSA; }
+ INTERNAL_(void FAR*) AllocInBlock(SAB seg, UINT cb);
+ INTERNAL_(SAB) AllocNewBlock(UINT cb);
+ INTERNAL_(SAB) MapPtrToBlock(void FAR* pv);
+
+ INTERNAL_(CStdMalloc FAR*) MoveSelf(LPVOID lpv);
+ friend HRESULT STDAPICALLTYPE CoCreateStandardMalloc(DWORD memctx, IMalloc FAR* FAR* ppMalloc);
+
+
+ INTERNAL_(void) FreeAllMem(void);
+};
+
+
+INTERNAL_(void FAR*) CStdMalloc::AllocInBlock(SAB sab, UINT cb)
+{
+#ifdef _DEBUG
+ WINDEBUGINFO Olddebuginfo, debuginfo;
+
+ //get initial debug state
+
+ GetWinDebugInfo(&debuginfo, WDI_OPTIONS);
+ Olddebuginfo = debuginfo;
+
+ //turn off alerts (see bug 3502)
+ debuginfo.dwOptions |= DBO_SILENT;
+ SetWinDebugInfo(&debuginfo);
+
+#endif // _DEBUG
+
+ // must make alloc of 0 mean alloc something; LocalAlloc fails on cb == 0
+ if (0==cb)
+ cb = 2;
+
+ _asm push DS;
+ _asm mov DS, sab;
+ void NEAR *npv = (void NEAR*)LocalAlloc(LMEM_FIXED, cb);
+ _asm pop DS;
+
+#ifdef _DEBUG
+ //restore Debug state
+ SetWinDebugInfo(&Olddebuginfo);
+#endif // _DEBUG
+
+ if (npv == NULL) // npv is near pointer
+ return NULL; // returned value is far pointer
+
+ return (void FAR*)MAKELONG(npv, sab);
+}
+
+
+INTERNAL_(SAB) CStdMalloc::AllocNewBlock(UINT cb)
+{
+ if (cb > cbMaxSAB)
+ // overflow
+ return NULLSAB;
+
+ if (cb < 4096 - cbTotalOH)
+ // minimum is 4k global block
+ cb = 4096;
+ else
+ // size will be larger than 4K; must include total overhead
+ cb += cbTotalOH;
+
+ // allocate block and get segment value
+ HGLOBAL h;
+ if ((h = GlobalAlloc(m_flags, cb)) == NULL)
+ return NULLSAB;
+
+ UINT segment;
+ segment = HIWORD(GlobalHandle(h));
+
+ // init windows local heap
+ if (!LocalInit(segment, cbWinRes + sizeof(StdAllocHdr), cb)) {
+ GlobalFree(h);
+ return NULLSAB;
+ }
+
+ // init block and put it on front of list
+ StdAllocHdr FAR* pSA;
+ pSA = MapBlockToSA((SAB)segment);
+ pSA->m_Signature = STDALLOC_SIG;
+ pSA->m_hTask = (m_flags & GMEM_SHARE) != 0 ? NULL : GetCurrentTask();
+ pSA->m_pStdAllocNext = m_pStdAllocHead;
+ m_pStdAllocHead = pSA;
+
+ return (SAB)segment;
+}
+
+
+INTERNAL_(SAB) CStdMalloc::MapPtrToBlock(void FAR* pv)
+{
+ if (pv == NULL)
+ return NULLSAB;
+
+ StdAllocHdr FAR* pSA;
+ pSA = MapBlockToSA((SAB)pv);
+ if (pSA->m_Signature != STDALLOC_SIG)
+ return NULLSAB;
+
+#ifdef DOESNTWORK
+ UINT flags = GlobalFlags((HGLOBAL)GlobalHandle((SAB)pv));
+#endif
+ if (m_flags & GMEM_SHARE) {
+ if (pSA->m_hTask != NULL)
+ // owned by task; not shared memory
+ return NULLSAB;
+
+#ifdef DOESNTWORK
+ if ((flags & GMEM_SHARE) == 0)
+ // flags not shared, not shared memory
+ return NULLSAB;
+#endif
+ } else {
+ if (pSA->m_hTask != GetCurrentTask()) {
+ // if not same task, not this allocator; if different task,
+ // something is wrong.
+ AssertSz(pSA->m_hTask == NULL, "pointer used in wrong task");
+ return NULLSAB;
+ }
+
+#ifdef DOESNTWORK
+ if ((flags & GMEM_SHARE) != 0)
+ // flags shared, not task memory
+ return NULLSAB;
+#endif
+ }
+
+ return MapSAToBlock(pSA);
+}
+
+
+STDMETHODIMP_(void FAR*) CStdMalloc::Alloc(ULONG cb)
+{
+ if (cb > cbMaxSAB)
+ // can't deal with objects larger than 64k
+ return NULL;
+
+ // try all sab in order (newest allocated sab on front)
+ StdAllocHdr FAR* pSA = m_pStdAllocHead;
+ while (pSA != NULL) {
+ // try allocating the memory; if successful, return
+
+ void FAR* pv;
+ if ((pv = AllocInBlock(MapSAToBlock(pSA), (UINT)cb)) != NULL)
+ return pv;
+
+ pSA = pSA->m_pStdAllocNext;
+ }
+
+ SAB sab;
+ if ((sab = AllocNewBlock((UINT)cb)) == NULLSAB)
+ return NULL;
+
+ // this should really succeed (i.e., an assert would be better)
+ return AllocInBlock(sab, (UINT)cb);
+}
+
+
+STDMETHODIMP_(void FAR*) CStdMalloc::Realloc(void FAR* pv, ULONG cb)
+{
+
+
+ if (cb > cbMaxSAB)
+ // can't deal with objects larger than 64k
+ return NULL;
+
+ SAB sab;
+ if (pv == NULL)
+ // same as allocating a new pointer
+ return Alloc(cb);
+
+ //VDATEPTRIN rejects NULL (changed by alexgo 8/3/93)
+ GEN_VDATEPTRIN( pv, int, (LPVOID)NULL );
+ if ((sab = MapPtrToBlock(pv)) == NULLSAB)
+ // attempt to realloc a pointer from some other allocator
+ return NULL;
+ else if (cb == 0) {
+ // Realloc(pv, 0) -> frees and returns NULL; this is C library behavior
+ Free(pv);
+ return NULL;
+ }
+
+ void NEAR* npv;
+ npv = (void NEAR*)(ULONG)pv;
+
+ // first try realloc within same sab
+ Assert(sab != NULLSAB);
+ {
+ void NEAR* npvT;
+
+ _asm push DS;
+ _asm mov DS, sab;
+ npvT = (void NEAR*)LocalReAlloc((HLOCAL)npv, (UINT)cb, LMEM_MOVEABLE);
+ _asm pop DS;
+
+ if (npvT != NULL)
+ return (void FAR*)MAKELONG(npvT, sab);
+ }
+
+ // now try allocating new sab and copying
+ void FAR* pvT;
+ if ((pvT = Alloc(cb)) == NULL)
+ return NULL;
+
+ // only copy the smaller of the old and new size
+ _asm push ds;
+ _asm mov ds,sab;
+ UINT cbCopy = LocalSize((HLOCAL)npv);
+ _asm pop ds;
+
+ if ((UINT)cb < cbCopy)
+ // new size smaller
+ cbCopy = (UINT)cb;
+
+ _fmemcpy(pvT, pv, cbCopy);
+
+
+ Free(pv);
+
+ return pvT;
+}
+
+
+STDMETHODIMP_(void) CStdMalloc::Free(void FAR* pv)
+{
+ SAB sab;
+
+ if (pv == NULL)
+ return;
+
+ //VDATEPTRIN rejects NULL (changed by alexgo 8/3/93)
+ VOID_VDATEPTRIN( pv, int );
+
+ if ((sab = MapPtrToBlock(pv)) == NULLSAB) {
+#ifdef _DEBUG
+ AssertSz(FALSE, "Pointer freed by wrong allocator; filling with 0xcc");
+
+ // we don't own block; this is an error; fill it with 0xcccc anyway
+ UINT cb = (UINT)GlobalSize((HGLOBAL)GlobalHandle((__segment)pv));
+ cb -= (UINT)(ULONG)pv;
+
+ _fmemset(pv, 0xcc, (size_t)cb);
+#endif
+ } else {
+#ifdef _DEBUG
+ // we own block; fill it with 0xcccc
+ _fmemset(pv, 0xcc, (size_t)GetSize(pv));
+#endif
+ _asm push ds;
+ _asm mov ds,sab;
+ LocalFree((HLOCAL)(void NEAR*)(ULONG)pv);
+ _asm pop ds;
+ }
+}
+
+
+STDMETHODIMP_(ULONG) CStdMalloc::GetSize(void FAR* pv)
+{
+ ULONG size = 0;
+ SAB sab;
+
+ //VDATEPTRIN rejects NULL (added by alexgo 8/3/93)
+ if( pv == NULL )
+ return -1;
+
+ GEN_VDATEPTRIN( pv , int, 0 );
+
+ if ((sab = MapPtrToBlock(pv)) != NULLSAB) {
+ _asm push ds;
+ _asm mov ds,sab;
+ size = LocalSize((HLOCAL)(void NEAR*)(ULONG)pv);
+ _asm pop ds;
+ }
+
+ return size;
+}
+
+
+STDMETHODIMP_(int) CStdMalloc::DidAlloc(void FAR* pv)
+{
+
+
+ if (pv == NULL)
+ return -1;
+
+ //VDATEPTRIN rejects NULL (added by alexgo 8/3/93)
+ GEN_VDATEPTRIN( pv , int, 0 );
+
+ // returns 1 if we allocated, 0 if not; this impl never returns -1.
+ return MapPtrToBlock(pv) != NULLSAB;
+}
+
+
+STDMETHODIMP_(void) CStdMalloc::HeapMinimize()
+{
+ // LATER : could do local compact here
+}
+
+
+// move this instance of stdmalloc to lpv (which must be large enough)
+INTERNAL_(CStdMalloc FAR*) CStdMalloc::MoveSelf(LPVOID lpv)
+{
+ _fmemcpy(lpv, this, sizeof(*this));
+ m_pStdAllocHead = NULL;
+ return (CStdMalloc FAR*)lpv;
+}
+
+
+INTERNAL_(void) CStdMalloc::FreeAllMem(void)
+{
+ // get/null out head of list; null now in case we are freeing self.
+ StdAllocHdr FAR* pSA = m_pStdAllocHead;
+ m_pStdAllocHead = NULL;
+
+ // free all blocks
+ while (pSA != NULL) {
+ StdAllocHdr FAR* pSANext = pSA->m_pStdAllocNext;
+ pSA->m_pStdAllocNext = NULL; // to prevent incorrect compiler opt
+
+ GlobalFree(LOWORD(GlobalHandle((UINT)MapSAToBlock(pSA))));
+
+ pSA = pSANext;
+ }
+}
+
+
+/****** Global API for creating *****************************************/
+
+
+// create and return an impl of IMalloc of given memctx
+//+---------------------------------------------------------------------------
+//
+// Function: CoCreateStandardMalloc, Local
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [memctx] --
+// [ppMalloc] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CoCreateStandardMalloc(DWORD memctx, IMalloc FAR* FAR* ppMalloc)
+{
+ thkDebugOut((DEB_ITRACE, " CoCreateStandardMalloc\n"));
+ *ppMalloc = NULL;
+
+ switch (memctx) {
+
+ case MEMCTX_TASK:
+ case MEMCTX_SHARED:
+ {
+ CStdMalloc sm(memctx); // local one
+
+ void FAR* lpv;
+ if ((lpv = sm.Alloc(sizeof(CStdMalloc))) == NULL)
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ *ppMalloc = sm.MoveSelf(lpv); // move to newly allocated memory
+ return NOERROR;
+ }
+ default:
+ return ResultFromScode(E_INVALIDARG);
+ }
+}
diff --git a/private/ole32/olethunk/ole16/compobj/valid.cxx b/private/ole32/olethunk/ole16/compobj/valid.cxx
new file mode 100644
index 000000000..a6877852c
--- /dev/null
+++ b/private/ole32/olethunk/ole16/compobj/valid.cxx
@@ -0,0 +1,200 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: Valid.cxx (16 bit target)
+//
+// Contents: Validation APIs exported by CompObj
+//
+// Functions:
+//
+// History: 93 OLE 2.0 Dev team Cretead
+// 17-Dec-93 JohannP
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+/*
+ * IsValidPtrIn -- Check if the pointer points to a readable segment
+ * and if the pointer + #of bytes stays within the segment.
+ *
+ * NULL will fail
+ *
+ * cb == 0 will FAIL
+ *
+ * This function exists only for compatibility with already-compiled apps.
+ * We now use macros for IsValidPtrIn and IsValidPtrOut
+ * Check out the comments in inc\valid.h
+ */
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ISVALIDPTRIN, Local
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pv] --
+// [cb] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(BOOL)
+ISVALIDPTRIN( const void FAR* pv, UINT cb )
+{
+ return !IsBadReadPtr (pv, cb);
+ // We cannot use inline assembly here because the VERR instruction does
+ // not work if the segment has been discarded (but is still valid).
+}
+
+
+// This function exists only for compatibility with already-compiled apps.
+// We now use macros for IsValidPtrIn and IsValidPtrOut
+//
+// Check out the comments in inc\valid.h
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ISVALIDPTROUT, Local
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pv] --
+// [cb] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(BOOL)
+ISVALIDPTROUT( void FAR* pv, UINT cb )
+ // NULL is not acceptable
+{
+ return !IsBadWritePtr (pv, cb);
+}
+
+
+// valid code begins 0xb8, ??, ??, followed by:
+
+// BYTE validcode[6] = { 0x55, 0x8b, 0xec, 0x1e, 0x8e, 0xd8};
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsValidInterface, Local
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pv] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(BOOL) IsValidInterface( void FAR* pv )
+{
+ BYTE FAR* pb;
+
+ // NULL is not acceptable as input.
+
+ if (!IsValidPtrIn(pv,4)) goto false;
+#ifdef _STRICT_VALIDATION
+ // if the interface was compiled with C++, the virtual function table
+ // will be in a code segment
+ if (IsBadCodePtr(*(FARPROC FAR*)pv)) goto false;
+#endif
+ pb = *(BYTE FAR* FAR*)pv; // pb points to beginning of vftable
+ if (!IsValidPtrIn(pb, 4)) goto false;
+ if (IsBadCodePtr(*(FARPROC FAR*)pb)) goto false;
+ pb = *(BYTE FAR* FAR*)pb;
+ if (!IsValidPtrIn(pb, 9)) goto false;
+// if (*pb != 0xb8) goto false;
+// pb += 3;
+// if (_fmemcmp(pb, validcode, 6)) goto false;
+ return TRUE;
+false:
+// AssertSz(FALSE, "Invalid interface pointer");
+ return FALSE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsValidIid, Local
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [iid] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(BOOL)
+IsValidIid( REFIID iid )
+{
+ IID iidTemp = iid;
+ DWORD FAR* pdw = (DWORD FAR*)&iidTemp;
+ *pdw = 0;
+ if (IID_IUnknown == iidTemp) return TRUE;
+ thkDebugOut((DEB_IERROR, "WARNING: Nonstandard IID parameter"));
+ return TRUE;
+}
diff --git a/private/ole32/olethunk/ole16/daytona/makefile b/private/ole32/olethunk/ole16/daytona/makefile
new file mode 100644
index 000000000..70c83082c
--- /dev/null
+++ b/private/ole32/olethunk/ole16/daytona/makefile
@@ -0,0 +1,49 @@
+# INTEROP makefile
+#
+# Copyright (c) 1994, Microsoft Corporation
+#
+# History:
+# 18-Feb-1994 Bob Day (bobday)
+# Adapted from MVDM makefile
+#
+# If you add a new sub-component , make sure to add it in cleanup
+# section too.
+#
+
+
+
+!INCLUDE $(NTMAKEENV)\makefile.plt
+
+all:
+!if "$(PROCESSOR_ARCHITECTURE)" == "x86"
+ @echo making dos mode binaries under NTVDM.
+ cd ..\lib
+ $(MAKE) "DEFINES=/D_DAYTONA_" "OPST=dayt"
+ cd ..\coll
+ $(MAKE) "DEFINES=/D_DAYTONA_" "OPST=dayt"
+ cd ..\compobj
+ $(MAKE) "DEFINES=/D_DAYTONA_" "OPST=dayt"
+ cd ..\storage
+ $(MAKE) "DEFINES=/D_DAYTONA_" "OPST=dayt"
+ cd ..\ole2
+ $(MAKE) "DEFINES=/D_DAYTONA_" "OPST=dayt"
+ cd ..
+!endif
+!IF "$(BUILDMSG)" != ""
+ @ech ; $(BUILDMSG) ;
+!ENDIF
+
+clean:
+!if "$(PROCESSOR_ARCHITECTURE)" == "x86"
+ cd ..\lib
+ $(MAKE) "OPST=dayt" clean
+ cd ..\coll
+ $(MAKE) "OPST=dayt" clean
+ cd ..\compobj
+ $(MAKE) "OPST=dayt" clean
+ cd ..\storage
+ $(MAKE) "OPST=dayt" clean
+ cd ..\ole2
+ $(MAKE) "OPST=dayt" clean
+ cd ..
+!endif
diff --git a/private/ole32/olethunk/ole16/daytona/sources b/private/ole32/olethunk/ole16/daytona/sources
new file mode 100644
index 000000000..dc4f04989
--- /dev/null
+++ b/private/ole32/olethunk/ole16/daytona/sources
@@ -0,0 +1,33 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Terry Rusell
+
+
+!ENDIF
+
+MAJORCOMP=cairole
+MINORCOMP=olethunk
+
+
+
+TARGETNAME=olethunk
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+SOURCES=
diff --git a/private/ole32/olethunk/ole16/dirs b/private/ole32/olethunk/ole16/dirs
new file mode 100644
index 000000000..57f650b0a
--- /dev/null
+++ b/private/ole32/olethunk/ole16/dirs
@@ -0,0 +1,37 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Terry Russell (TerryRu) 28-Sep-1994
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ daytona \
+
+
diff --git a/private/ole32/olethunk/ole16/inc/array_fv.h b/private/ole32/olethunk/ole16/inc/array_fv.h
new file mode 100644
index 000000000..51316561b
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/array_fv.h
@@ -0,0 +1,74 @@
+#ifndef __ARRAY_FV_H__
+#define __ARRAY_FV_H__
+
+////////////////////////////////////////////////////////////////////////////
+// class CArrayFValue - an array containing fixed size elements,
+//
+////////////////////////////////////////////////////////////////////////////
+
+
+class FAR __export CArrayFValue
+{
+public:
+
+// Construction
+ CArrayFValue(DWORD memctx, UINT cbValue);
+ ~CArrayFValue();
+
+// Attributes
+ int GetSize() const
+ { return m_nSize; }
+ int GetUpperBound() const
+ { return m_nSize-1; }
+ BOOL SetSize(int nNewSize, int nGrowBy = -1);
+ int GetSizeValue() const
+ { return m_cbValue; }
+
+// Operations
+ // Clean up
+ void FreeExtra();
+ void RemoveAll()
+ { SetSize(0); }
+
+ // return pointer to element; index must be in range
+#ifdef _DEBUG
+ // with debug checks
+ LPVOID GetAt(int nIndex) const
+ { return _GetAt(nIndex); }
+#else
+ // no debug checks
+ LPVOID GetAt(int nIndex) const
+ { return &m_pData[nIndex * m_cbValue]; }
+#endif
+ LPVOID _GetAt(int nIndex) const;
+
+ // set element; index must be in range
+ void SetAt(int nIndex, LPVOID pValue);
+
+ // find element given part of one; offset is offset into value; returns
+ // -1 if element not found; use IndexOf(NULL, cb, offset) to find zeros;
+ // will be optimized for appropriate value size and param combinations
+ int IndexOf(LPVOID pData, UINT cbData, UINT offset);
+
+ // set/add element; Potentially growing the array; return FALSE/-1 if
+ // not possible (due to OOM)
+ BOOL SetAtGrow(int nIndex, LPVOID pValue);
+
+ // Operations that move elements around
+ BOOL InsertAt(int nIndex, LPVOID pValue, int nCount = 1);
+ void RemoveAt(int nIndex, int nCount = 1);
+
+ void AssertValid() const;
+
+// Implementation
+private:
+ BYTE FAR* m_pData; // the actual array of data
+ UINT m_cbValue; // size of each value (in bytes)
+ int m_nSize; // current # of elements (m_cbValue bytes in length)
+ int m_nMaxSize; // max # of elements (m_cbValue bytes in length)
+ int m_nGrowBy; // grow amount (in # elements)
+ DWORD m_memctx; // the memctx where the array data should be allocd
+};
+
+
+#endif // !__ARRAY_FV_H__
diff --git a/private/ole32/olethunk/ole16/inc/assert.h b/private/ole32/olethunk/ole16/inc/assert.h
new file mode 100644
index 000000000..b57c7b245
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/assert.h
@@ -0,0 +1,35 @@
+/***
+*assert.h - define the assert macro
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the assert(exp) macro.
+* [ANSI/System V]
+*
+****/
+
+#if (_MSC_VER <= 600)
+#define __cdecl _cdecl
+#define __far _far
+#endif
+
+#undef assert
+
+#ifdef NDEBUG
+
+#define assert(exp) ((void)0)
+
+#else
+#ifdef __cplusplus
+extern "C" {
+#endif
+void __cdecl _assert(void *, void *, unsigned);
+#ifdef __cplusplus
+}
+#endif
+
+#define assert(exp) \
+ ( (exp) ? (void) 0 : _assert(#exp, __FILE__, __LINE__) )
+
+#endif
diff --git a/private/ole32/olethunk/ole16/inc/cderr.h b/private/ole32/olethunk/ole16/inc/cderr.h
new file mode 100644
index 000000000..cdaeebbe1
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/cderr.h
@@ -0,0 +1,48 @@
+#ifndef _CDERR_INCLUDED_
+#define _CDERR_INCLUDED_
+
+#define CDERR_DIALOGFAILURE 0xFFFF
+
+#define CDERR_GENERALCODES 0x0000
+#define CDERR_STRUCTSIZE 0x0001
+#define CDERR_INITIALIZATION 0x0002
+#define CDERR_NOTEMPLATE 0x0003
+#define CDERR_NOHINSTANCE 0x0004
+#define CDERR_LOADSTRFAILURE 0x0005
+#define CDERR_FINDRESFAILURE 0x0006
+#define CDERR_LOADRESFAILURE 0x0007
+#define CDERR_LOCKRESFAILURE 0x0008
+#define CDERR_MEMALLOCFAILURE 0x0009
+#define CDERR_MEMLOCKFAILURE 0x000A
+#define CDERR_NOHOOK 0x000B
+#define CDERR_REGISTERMSGFAIL 0x000C
+
+#define PDERR_PRINTERCODES 0x1000
+#define PDERR_SETUPFAILURE 0x1001
+#define PDERR_PARSEFAILURE 0x1002
+#define PDERR_RETDEFFAILURE 0x1003
+#define PDERR_LOADDRVFAILURE 0x1004
+#define PDERR_GETDEVMODEFAIL 0x1005
+#define PDERR_INITFAILURE 0x1006
+#define PDERR_NODEVICES 0x1007
+#define PDERR_NODEFAULTPRN 0x1008
+#define PDERR_DNDMMISMATCH 0x1009
+#define PDERR_CREATEICFAILURE 0x100A
+#define PDERR_PRINTERNOTFOUND 0x100B
+#define PDERR_DEFAULTDIFFERENT 0x100C
+
+#define CFERR_CHOOSEFONTCODES 0x2000
+#define CFERR_NOFONTS 0x2001
+#define CFERR_MAXLESSTHANMIN 0x2002
+
+#define FNERR_FILENAMECODES 0x3000
+#define FNERR_SUBCLASSFAILURE 0x3001
+#define FNERR_INVALIDFILENAME 0x3002
+#define FNERR_BUFFERTOOSMALL 0x3003
+
+#define FRERR_FINDREPLACECODES 0x4000
+#define FRERR_BUFFERLENGTHZERO 0x4001
+
+#define CCERR_CHOOSECOLORCODES 0x5000
+
+#endif // _CDERR_INCLUDED_
diff --git a/private/ole32/olethunk/ole16/inc/cmacros.inc b/private/ole32/olethunk/ole16/inc/cmacros.inc
new file mode 100644
index 000000000..eb7dfad7b
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/cmacros.inc
@@ -0,0 +1,1410 @@
+comment $
+cmacros - assembly macros for interfacing to hlls
+(C)Copyright Microsoft Corp. 1984-1988
+$
+.xcref
+.xcref ??_out
+??_out macro t
+ifndef ?QUIET
+%out t
+endif
+endm
+outif macro name,defval,onmsg,offmsg
+ifndef name
+ifb <defval>
+name=0
+else
+name=defval
+endif
+endif
+if name
+name=1
+ifnb <onmsg>
+??_out <! onmsg>
+endif
+else
+ifnb <offmsg>
+??_out <! offmsg>
+endif
+endif
+endm
+.xcref ??error
+??error macro msg
+e r r o r ----- msg
+.err
+endm
+.xcref ASMpass
+.xcref memS,memM,memL,memC,memH,memMOD,sizec,sized
+if1
+ASMpass=1
+ifdef ?SMALL
+memS=1
+endif
+ifdef ?MEDIUM
+memM=1
+endif
+ifdef ?COMPACT
+memC=1
+endif
+ifdef ?LARGE
+memL=1
+endif
+ifdef ?HUGE
+memH=1
+endif
+??_out <cMacros Version 5.20 - Copyright (c) Microsoft Corp. 1984-1988>
+outif memS,0,<Small model>
+outif memM,0,<Medium model>
+outif memL,0,<Large model>
+outif memC,0,<Compact model>
+outif memH,0,<Huge model>
+memMOD= memS + memM + memL + memC + memH
+if memMOD ne 1
+if memMOD eq 0
+memS = 1
+else
+??error <more than 1 memory model selected>
+endif
+endif
+sizec= memM + memL + memH
+sized= memL + memC + (memH*2)
+outif ?DF,0,<No segments or groups will be defined>
+outif ?TF,0,<Epilog sequences assume valid SP>
+outif ?WIN,1,<Windows support>
+ifdef PMODE
+?pmd=1
+??_out <! 286 protect mode>
+else
+?pmd=0
+endif
+ifdef ?386regs
+if ?386regs
+??_out <! 386 registers enabled>
+endif
+else
+?386regs=0
+endif
+if ?WIN eq 1
+outif ?PLM,1,<>
+else
+outif ?PLM,1,<Pascal calling convention>
+endif
+ifndef ?NODATA
+?nodata1=0
+else
+?nodata1=1
+??_out <! NODATA module>
+endif
+ifndef ?CHKSTK
+?chkstk1=0
+else
+?chkstk1=1
+ifdef ?CHKSTKPROC
+??_out <! Private stack checking enabled>
+else
+??_out <! Stack checking enabled>
+endif
+endif
+ifndef DOS5
+?DOS5=0
+else
+?DOS5=1
+??_out <! DOS5 module>
+endif
+ifdef ?PROFILE
+??_out <! Native profiling enabled>
+endif
+else
+ASMpass=2
+endif
+ifdef ?pmd
+.286p
+endif
+if ?386regs
+.xcref ?n,?ax,?eax,?bx,?ebx
+.xcref ?cx,?ecx,?dx,?edx
+.xcref ?si,?esi,?di,?edi,?es,?ds,?fs
+.xcref ?gs
+else
+.xcref ?n,?ax,?ah,?al,?bx,?bh
+.xcref ?bl,?cx,?ch,?cl,?dx,?dh
+.xcref ?dl,?si,?di,?es,?ds,?bp
+.xcref ?sp,?ss,?cs
+endif
+.xcref ?rsl,?cpd,?argl,?argc,?ba
+.xcref ?acb,???,?po
+.xcref ?pas,?pc
+.xcref uconcat,mpush,mpop
+.xcref ?ri,?pp,?pp1,?al1
+.xcref ?ad,?ap,?atal,?dd,?dd1,?dd2
+.xcref ?pg,?pg1,?aloc,?cs1,?cs2
+.xcref ?DF,?TF,?ff,?PLM,?WIN,?ia,?pu,?adj
+.xcref ?uf,?rp,?nx,?nd,?nodata1,?chkstk1,?DOS5,?pmd,?lds,?exp
+.xcref ?wfp,arg,cCall,cProc,assumes,?cs3,?cs2,?cs1
+.xcref defgrp,addseg,createSeg
+.xcref save,outif,errnz,errn$,errnz1
+.xcref ?PLMPrevParm,?gcc
+.xcref ?cCall1,?pcc
+?rsl = 0
+?cpd = 0
+?argl = 0
+?argc = 0
+?ba = 0
+?acb = 0
+??? = 0
+?po = 0
+?pas = 0
+?pc = 0
+?ia = 0
+?pu = 0
+?adj = 0
+?rp = 0
+?uf = 0
+?nd = 0
+?nx = 0
+?wfp = 0
+?lds = 0
+?exp = 0
+?ff = 0
+?dd2 = 0
+?cCall1 = 0
+?pcc = 0
+?PLMPrevParm = 0
+.xcref ?casen
+if1
+?casen = 0
+endif
+if ?386regs
+?n = 0000000000000000b
+?ax = 0000000000000001b
+?eax = 0000000000000010b
+?bx = 0000000000000100b
+?ebx = 0000000000001000b
+?cx = 0000000000010000b
+?ecx = 0000000000100000b
+?dx = 0000000001000000b
+?edx = 0000000010000000b
+?si = 0000000100000000b
+?esi = 0000001000000000b
+?di = 0000010000000000b
+?edi = 0000100000000000b
+?ds = 0001000000000000b
+?es = 0010000000000000b
+?fs = 0100000000000000b
+?gs = 1000000000000000b
+else
+?n = 0000000000000000b
+?ax = 0000000000000011b
+?ah = 0000000000000001b
+?al = 0000000000000010b
+?bx = 0000000000001100b
+?bh = 0000000000000100b
+?bl = 0000000000001000b
+?cx = 0000000000110000b
+?ch = 0000000000010000b
+?cl = 0000000000100000b
+?dx = 0000000011000000b
+?dh = 0000000001000000b
+?dl = 0000000010000000b
+?si = 0000000100000000b
+?di = 0000001000000000b
+?es = 0000010000000000b
+?ds = 0000100000000000b
+?bp = 0001000000000000b
+?sp = 0010000000000000b
+?ss = 0100000000000000b
+?cs = 1000000000000000b
+endif
+.cref
+uconcat macro a,b,c,d,e,f,g
+a&b c&d e&f&g
+endm
+if ?386regs
+mpush macro r
+irp x,<ax,eax,bx,ebx,cx,ecx,dx,edx,si,esi,di,edi,ds,es,fs,gs>
+if (r and ?&&x)
+ push x
+endif
+endm
+endm
+else
+mpush macro r
+irp x,<ax,bx,cx,dx,si,di,es,ds,bp,sp,ss,cs>
+if (r and ?&&x)
+ push x
+endif
+endm
+endm
+endif
+if ?386regs
+mpop macro r
+irp x,<gs,fs,es,ds,edi,di,esi,si,edx,dx,ecx,cx,ebx,bx,eax,ax>
+if (r and ?&&x)
+ pop x
+endif
+endm
+endm
+else
+mpop macro r
+irp x,<cs,ss,sp,bp,ds,es,di,si,dx,cx,bx,ax>
+if (r and ?&&x)
+ pop x
+endif
+endm
+endm
+endif
+save macro r
+?rsl=0
+?ri ?rsl,<r>
+endm
+?ri macro n,r
+irp x,<r>
+.ERRNDEF ?&&x
+n=n or ?&&x
+endm
+endm
+.xcref
+.xcref parmB,parmW,parmD,parmQ,parmT,parmCP,parmDP
+.cref
+parmB macro n
+?pp <n>,<byte>,2,1
+endm
+parmW macro n
+?pp <n>,<word>,2,2
+endm
+parmD macro n
+ife ?PLM
+irp x,<n>
+?pp <&&x>,<dword>,0,4
+?pp <off_&&x>,<word>,2,2
+?pp <seg_&&x>,<word>,2,2
+endm
+else
+irp x,<n>
+?pp <seg_&&x>,<word>,2,2
+?pp <off_&&x>,<word>,2,2
+?pp <&&x>,<dword>,0,4
+endm
+endif
+endm
+parmQ macro n
+?pp <n>,<qword>,8,8
+endm
+parmT macro n
+?pp <n>,<tbyte>,10,10
+endm
+if sizec
+parmCP macro n
+parmD <n>
+endm
+else
+parmCP macro n
+parmW <n>
+endm
+endif
+if sized
+parmDP macro n
+parmD <n>
+endm
+else
+parmDP macro n
+parmW <n>
+endm
+endif
+?pp macro n,t,l,s
+if ?cpd
+.xcref
+irp x,<n>
+.xcref ?t&&x
+?t&&x=s
+ife ?PLM
+?pp1 x,<t>,,,%(?po+?adj)
+?po=?po+l
+else
+?PLMPrevParm=?PLMPrevParm+1
+?po=?po+l
+?pp1 x,<t>,%?po,%?adj,,%?PLMPrevParm,%(?PLMPrevParm-1)
+endif
+endm
+.cref
+else
+??error <parm(s) "&n" declared outside proc def>
+endif
+endm
+?pp1 macro n,t,o,a,b,cpc,ppc
+ife ?PLM
+n equ (t ptr [bp+b])
+else
+.xcref
+.xcref ?PLMParm&cpc
+.cref
+?PLMParm&cpc &macro po
+uconcat <n>,,<equ>,,<(t ptr [bp+>,%(a+po-o),<])>
+?PLMParm&ppc po
+purge ?PLMParm&cpc
+&endm
+endif
+endm
+ifndef ?NOPARMR
+if ?pmd
+parmR macro n,r,r2
+??error <Sorry: ParmR can't be used with PMODE=1>
+endm
+else
+.xcref
+.xcref ?pr,parmR
+.cref
+parmR macro n,r,r2
+?pr n,r,r2,%?rp,%(?ia+2)
+endm
+?pr macro n,r,r2,i,o
+.xcref
+ifnb <r2>
+parmR seg_&n,r
+parmR off_&n,r2
+n equ (dword ptr [bp-o-2])
+.xcref ?t&n
+?t&n=4
+else
+.xcref ?rp&i
+?rp&i=0
+ifdef ?&r
+?rp&i=?&r
+endif
+if ??? or (?cpd eq 0) or (?rp&i eq 0)
+??error <invalid parmR encountered: &n,&r>
+exitm
+endif
+n equ (word ptr [bp-o])
+?t&n=2
+irp x,<bh,ch,dh,bl,cl,dl,ah,al>
+if ?&&x eq ?&r
+n equ (byte ptr [bp-o])
+?t&n=1
+exitm
+endif
+endm
+?ia=?ia+2
+?rp=?rp+1
+endif
+.cref
+endm
+endif
+endif
+.xcref
+.xcref localB,localW,localD,localQ,localT,localCP,localDP,localV
+.cref
+localB macro n
+?aloc <n>,<byte ptr>,1,1,0
+endm
+localW macro n
+?aloc <n>,<word ptr>,2,2,1
+endm
+localD macro n
+irp x,<n>
+?aloc <seg_&&x>,<word ptr>,2,2,1
+?aloc <off_&&x>,<word ptr>,2,2,1
+?aloc <&&x>,<dword ptr>,0,4,1
+endm
+endm
+localQ macro n
+?aloc <n>,<qword ptr>,8,8,1
+endm
+localT macro n
+?aloc <n>,<tbyte ptr>,10,10,1
+endm
+if sizec
+localCP macro n
+localD <n>
+endm
+else
+localCP macro n
+localW <n>
+endm
+endif
+if sized
+localDP macro n
+localD <n>
+endm
+else
+localDP macro n
+localW <n>
+endm
+endif
+localV macro n,a
+?aloc <n>,,%(a),0,1
+endm
+?aloc macro n,t,l,s,a
+if ?cpd
+.xcref
+irp x,<n>
+???=???+l
+if a
+???=((??? + 1) and 0fffeh)
+endif
+?al1 x,<t>,%(???+?ia)
+.xcref ?t&&x
+?t&&x=s
+endm
+.cref
+else
+??error <locals "&n" declared outside procedure def>
+endif
+endm
+?al1 macro n,t,o
+n equ (t [bp-o])
+endm
+?gcc macro s,i,cc
+s = i
+ifnb <cc>
+ifidn <cc>,<C>
+s=0
+endif
+ifidn <cc>,<PLM>
+s=1
+endif
+ifidn <cc>,<PASCAL>
+s=1
+endif
+endif
+endm
+ifndef ?NOGLOBAL
+.xcref
+.xcref globalB,globalW,globalD,globalQ,globalT,globalCP,globalDP
+.cref
+globalB macro n,i,s,c
+?ad <n>,1
+?dd n,1,<byte>,<db>,<i>,<s>,<c>
+endm
+globalW macro n,i,s,c
+?ad <n>,2
+?dd n,1,<word>,<dw>,<i>,<s>,<c>
+endm
+globalD macro n,i,s,c
+?ad <n>,4
+?dd n,1,<dword>,<dd>,<i>,<s>,<c>
+off_&n equ n
+seg_&n equ n[2]
+endm
+globalQ macro n,i,s,c
+?ad <n>,8
+?dd n,1,<qword>,<dq>,<i>,<s>,<c>
+endm
+globalT macro n,i,s,c
+?ad <n>,10
+?dd n,1,<tbyte>,<dt>,<i>,<s>,<c>
+endm
+if sizec
+globalCP macro n,i,s,c
+globalD n,<i>,<s>,<c>
+endm
+else
+globalCP macro n,i,s,c
+globalW n,<i>,<s>,<c>
+endm
+endif
+if sized
+globalDP macro n,i,s,c
+globalD n,<i>,<s>,<c>
+endm
+else
+globalDP macro n,i,s,c
+globalW n,<i>,<s>,<c>
+endm
+endif
+endif
+ifndef ?NOSTATIC
+.xcref
+.xcref staticB,staticW,staticD,staticQ,staticT,staticCP,staticDP
+.cref
+staticB macro n,i,s
+?ad <n>,1
+?dd n,0,<byte>,<db>,<i>,<s>,<PLM>
+endm
+staticW macro n,i,s
+?ad <n>,2
+?dd n,0,<word>,<dw>,<i>,<s>,<PLM>
+endm
+staticD macro n,i,s
+?ad <n>,4
+?dd n,0,<dword>,<dd>,<i>,<s>,<PLM>
+endm
+staticQ macro n,i,s
+?ad <n>,8
+?dd n,0,<qword>,<dq>,<i>,<s>,<PLM>
+endm
+staticT macro n,i,s
+?ad <n>,10
+?dd n,0,<tbyte>,<dt>,<i>,<s>,<PLM>
+endm
+if sizec
+staticCP macro n,i,s
+staticD n,<i>,<s>
+endm
+else
+staticCP macro n,i,s
+staticW n,<i>,<s>
+endm
+endif
+if sized
+staticDP macro n,i,s
+staticD n,<i>,<s>
+endm
+else
+staticDP macro n,i,s
+staticW n,<i>,<s>
+endm
+endif
+endif
+?dd macro n,p,t,d,i,s,c
+?gcc ?dd2,%?PLM,<c>
+ife ?dd2
+n label t
+?dd1 _&n,p,<d>,<i>,<s>
+else
+?dd1 n,p,<d>,<i>,<s>
+endif
+endm
+?dd1 macro n,p,d,i,s
+if p
+public n
+endif
+ifb <s>
+n d i
+else
+ifb <i>
+n d s dup (?)
+else
+n d s dup (i)
+endif
+endif
+endm
+ifndef ?NOEXTERN
+.xcref
+.xcref ?ex1,?ex2,externB,externW,externD,externQ,externT
+.xcref externNP,externFP,externP,externCP,externDP,externA
+.cref
+?ex2 = 0
+externA macro n,c
+?ex1 <n>,40h,<abs>,<c>,<>
+endm
+externB macro n,c
+?ex1 <n>,1,<byte>,<c>,<>
+endm
+externW macro n,c
+?ex1 <n>,2,<word>,<c>,<>
+endm
+externD macro n,c
+?ex1 <n>,4,<dword>,<c>,<>
+endm
+externQ macro n,c
+?ex1 <n>,8,<qword>,<c>,<>
+endm
+externT macro n,c
+?ex1 <n>,10,<tbyte>,<c>,<>
+endm
+externNP macro n,c
+?ex1 <n>,2,<near>,<c>,<cc>
+endm
+externFP macro n,c
+?ex1 <n>,4,<far>,<c>,<cc>
+endm
+if sizec
+externP macro n,c
+?ex1 <n>,4,<far>,<c>,<cc>
+endm
+else
+externP macro n,c
+?ex1 <n>,2,<near>,<c>,<cc>
+endm
+endif
+if sizec
+externCP macro n,c
+?ex1 <n>,4,<dword>,<c>,<>
+endm
+else
+externCP macro n,c
+?ex1 <n>,2,<word>,<c>,<>
+endm
+endif
+if sized
+externDP macro n,c
+?ex1 <n>,4,<dword>,<c>,<>
+endm
+else
+externDP macro n,c
+?ex1 <n>,2,<word>,<c>,<>
+endm
+endif
+?ex1 macro n,s,d,c,scv
+?gcc ?ex2,%?PLM,<c>
+irp x,<n>
+.xcref
+.xcref ?t&&x
+.cref
+?t&&x=s
+ife ?ex2
+extrn _&&x:&d
+x equ _&&x
+else
+extrn x:&d
+endif
+ifidn <scv>,<cc>
+.xcref
+.xcref ?CC&&x
+.cref
+?CC&&x=?ex2
+endif
+endm
+endm
+endif
+ifndef ?NOLABEL
+.xcref
+.xcref ?lb1,?lblpu,?lb2
+.xcref labelB,labelW,labelD,labelQ,labelT
+.xcref labelNP,labelFP,labelP,labelCP,labelDP
+.cref
+?lblpu = 0
+?lb2 = 0
+labelB macro n,c
+?lb1 <n>,1,<byte>,<c>
+endm
+labelW macro n,c
+?lb1 <n>,2,<word>,<c>
+endm
+labelD macro n,c
+?lb1 <n>,4,<dword>,<c>
+endm
+labelQ macro n,c
+?lb1 <n>,8,<qword>,<c>
+endm
+labelT macro n,c
+?lb1 <n>,10,<tbyte>,<c>
+endm
+labelNP macro n,c
+?lb1 <n>,2,<near>,<c>
+endm
+labelFP macro n,c
+?lb1 <n>,4,<far>,<c>
+endm
+if sizec
+labelP macro n,c
+?lb1 <n>,4,<far>,<c>
+endm
+else
+labelP macro n,c
+?lb1 <n>,2,<near>,<c>
+endm
+endif
+if sizec
+labelCP macro n,c
+?lb1 <n>,4,<dword>,<c>
+endm
+else
+labelCP macro n,c
+?lb1 <n>,2,<word>,<c>
+endm
+endif
+if sized
+labelDP macro n,c
+?lb1 <n>,4,<dword>,<c>
+endm
+else
+labelDP macro n,c
+?lb1 <n>,2,<word>,<c>
+endm
+endif
+?lb1 macro n,s,d,c
+?gcc ?lb2,%?PLM,<c>
+?lblpu=0
+irp x,<n>
+ifidn <x>,<PUBLIC>
+?lblpu=1
+else
+.xcref
+.xcref ?t&&x
+.cref
+?t&&x=s
+ife ?lb2
+if ?lblpu
+public _&&x
+endif
+_&&x label &d
+x equ _&&x
+else
+if ?lblpu
+public x
+endif
+x label &d
+endif
+endif
+endm
+endm
+endif
+ifndef ?NODEF
+.xcref
+.xcref defB,defW,defD,defQ,defT,defCP,defDP
+.cref
+defB macro n
+?ad <n>,1
+endm
+defW macro n
+?ad <n>,2
+endm
+defD macro n
+?ad <n>,4
+endm
+defQ macro n
+?ad <n>,8
+endm
+defT macro n
+?ad <n>,10
+endm
+if sizec
+defCP macro n
+defD <n>
+endm
+else
+defCP macro n
+defW <n>
+endm
+endif
+if sized
+defDP macro n
+defD <n>
+endm
+else
+defDP macro n
+defW <n>
+endm
+endif
+endif
+?ad macro n,s
+irp x,<n>
+.xcref
+.xcref ?t&&x
+.cref
+?t&&x=s
+endm
+endm
+ifndef ?NOPTR
+.xcref
+.xcref regPtr,farPtr
+.cref
+regPtr macro n,s,o
+farPtr n,s,o
+endm
+farPtr macro n,s,o
+.xcref
+.xcref ?t&n
+.cref
+n &macro
+ push s
+ push o
+&endm
+?t&n=80h
+endm
+endif
+arg macro a
+irp x,<a>
+?argc=?argc+1
+?atal <x>,%?argc
+endm
+endm
+?atal macro n,i
+.xcref
+.xcref ?ali&i
+.cref
+?ali&i &macro
+?ap n
+&endm
+endm
+?ap macro n
+?argl=?argl+2
+ifdef ?t&n
+ife ?t&n-1
+ push word ptr (n)
+exitm
+endif
+ife ?t&n-2
+ push n
+exitm
+endif
+ife ?t&n-4
+ push word ptr (n)[2]
+ push word ptr (n)
+?argl=?argl+2
+exitm
+endif
+ife ?t&n-8
+ push word ptr (n)[6]
+ push word ptr (n)[4]
+ push word ptr (n)[2]
+ push word ptr (n)
+?argl=?argl+6
+exitm
+endif
+if ?t&n and 80h
+n
+?argl=?argl+2
+exitm
+endif
+ife ?t&n
+ push word ptr (n)
+exitm
+endif
+endif
+ push n
+endm
+cCall macro n,a,c
+ifnb <a>
+arg <a>
+endif
+mpush %?rsl
+ifdef ?CC&n
+?cCall1=?CC&n
+else
+?cCall1=?PLM
+endif
+ifnb <c>
+?gcc ?cCall1,%?cCall1,<c>
+endif
+?argl=0
+ife ?cCall1
+?acb=?argc
+else
+?acb=1
+endif
+rept ?argc
+uconcat <?ali>,%?acb
+uconcat <purge>,,<?ali>,%?acb
+ife ?cCall1
+?acb=?acb-1
+else
+?acb=?acb+1
+endif
+endm
+ call n
+if ((?cCall1 eq 0) and (?argl ne 0))
+ add sp,?argl
+endif
+mpop %?rsl
+?rsl=0
+?argc= 0
+?argl= 0
+endm
+cProc macro n,cf,a
+if ?cpd
+?utpe
+endif
+?cpd=1
+???=0
+?argc=0
+?ba=0
+?po=0
+?pu=0
+?ia=0
+?adj=4
+?rp=0
+?uf=0
+?wfp=?WIN
+?ff=0
+?pas=0
+?pcc=?PLM
+?lds=0
+?exp=0
+ifnb <a>
+?ri ?pas,<a>
+endif
+?pc=sizec
+?nd=?nodata1
+?nx=0
+irp x,<cf>
+ifidn <x>,<FAR>
+?pc=1
+endif
+ifidn <x>,<NEAR>
+?pc=0
+endif
+ifidn <x>,<PUBLIC>
+?pu=1
+endif
+ifidn <x>,<SMALL>
+?uf=1
+endif
+ifidn <x>,<DATA>
+?nd=0
+endif
+ifidn <x>,<NODATA>
+?nd=1
+endif
+ifidn <x>,<ATOMIC>
+?nx=1
+endif
+ifidn <x>,<C>
+?pcc=0
+endif
+ifidn <x>,<PLM>
+?pcc=1
+endif
+ifidn <x>,<PASCAL>
+?pcc=1
+endif
+ifidn <x>,<WIN>
+?wfp=1
+endif
+ifidn <x>,<NONWIN>
+?wfp=0
+endif
+ifidn <x>,<LOADDS>
+?lds=1
+endif
+ifidn <x>,<EXPORTED>
+?exp=1
+endif
+endm
+if ?pcc
+?PLMPrevParm=0
+.xcref
+.xcref ?PLMParm0
+.cref
+?PLMParm0 &macro
+purge ?PLMParm0
+&endm
+endif
+.xcref
+.xcref ?CC&n
+.cref
+?CC&n=?pcc
+if (?nx eq 1) and (?nd eq 0)
+?nx = 0
+??error <ATOMIC specified without NODATA - ATOMIC ignored>
+endif
+if ?pc
+if ?wfp+?exp+?lds
+ife ?nx
+ife ?pmd
+?ia=2
+endif
+?pas = ?pas and (not ?ds)
+endif
+endif
+?adj=?adj+2
+else
+?wfp=0
+endif
+ife ?386regs
+?pas = ?pas and (not (?sp+?cs+?ss))
+endif
+if ?uf
+if ?386regs
+?pas = ?pas and (not (?si+?di))
+else
+?pas = ?pas and (not (?bp+?si+?di))
+endif
+endif
+ife ?pcc
+?pg <_&n>,%?pu,%?pc,%?pas,%?wfp,<n>,%?pcc
+else
+?pg <n>,%?pu,%?pc,%?pas,%?wfp,<n>,%?pcc
+endif
+endm
+?pg macro n,p,c,a,w,nnu,cc
+.xcref
+if ?uf
+if ?nd
+??error <NODATA encountered in &n - user frame ignored>
+?uf=0
+endif
+endif
+.xcref cBegin
+cBegin &macro g
+.xcref
+if cc
+uconcat <?PLMParm>,%?PLMPrevParm,%?po
+endif
+if ?uf
+if ?rp
+??error <parmR encountered in &n - user frame ignored>
+?uf=0
+endif
+endif
+?pg1 <n>,c,a,%?po,w,%?uf,%?nd,%?rp,cc
+?cpd=0
+?argc=0
+?ba=1
+???=(???+1) and 0fffeh
+if p
+public n
+endif
+ife c
+n proc near
+else
+n proc far
+endif
+ife cc
+nnu equ n
+endif
+ifidn <g>,<nogen>
+if ???+?po+a+?rp
+??_out <cBegin - possible invalid use of nogen>
+endif
+else
+if ?uf
+?mf c,%???,%?po
+mpush a
+else
+if w+?exp+?lds
+if ?pmd
+ife ?nd
+if ?lds
+mov ax,_DATA
+else
+if ?exp
+mov ax,ds
+nop
+endif
+endif
+endif
+ife ?nx
+if ???+?po
+if ?chkstk1
+push bp
+mov bp,sp
+else
+if ???
+enter ???,0
+else
+push bp
+mov bp,sp
+endif
+endif
+endif
+push ds
+if ?lds+?exp
+mov ds,ax
+endif
+else
+if ?ff+???+?po+?rp
+ push bp
+ mov bp,sp
+endif
+endif
+else
+ife ?nd
+ mov ax,ds
+ nop
+endif
+ife ?nx
+ife ?DOS5
+ inc bp
+endif
+ push bp
+ mov bp,sp
+ push ds
+else
+if ?ff+???+?po+?rp
+ push bp
+ mov bp,sp
+endif
+endif
+ife ?nd
+ mov ds,ax
+endif
+endif
+else
+if ?pmd
+if ?exp
+mov ax,ds
+nop
+else
+if ?lds
+mov ax,_DATA
+endif
+endif
+if ?ff+???+?po+?rp
+if ?chkstk1
+push bp
+mov bp,sp
+else
+if ???
+enter ???,0
+else
+push bp
+mov bp,sp
+endif
+endif
+endif
+if ?exp+?lds
+push ds
+mov ds,ax
+endif
+else
+if ?ff+???+?po+?rp
+ push bp
+ mov bp,sp
+endif
+endif
+endif
+if ?rp
+?uf=0
+rept ?rp
+uconcat mpush,,?rp,%?uf
+?uf=?uf+1
+endm
+endif
+if ???
+if ?chkstk1
+ifdef ?CHKSTKPROC
+?CHKSTKPROC %???
+else
+ mov ax,???
+ife cc
+ call _chkstk
+else
+ call chkstk
+endif
+endif
+else
+ife ?pmd
+ sub sp,???
+endif
+endif
+endif
+mpush a
+endif
+ifdef ?PROFILE
+if c
+ call StartNMeas
+endif
+endif
+endif
+.cref
+purge cBegin
+&endm
+.xcref ?utpe
+?utpe &macro
+??error <unterminated procedure definition: "&n">
+&endm
+.cref
+endm
+?pg1 macro n,c,a,o,w,f,d,r,cc
+.xcref
+.xcref cEnd
+cEnd &macro g
+.xcref
+?ba=0
+ifidn <g>,<nogen>
+if o+a+r
+??_out <cEnd - possible invalid use of nogen>
+endif
+else
+ifdef ?PROFILE
+if c
+call StopNMeas
+endif
+endif
+mpop a
+if f
+ db 0c3h
+else
+if w+?exp+?lds
+if ?pmd
+ife ?nx
+pop ds
+endif
+ife ?nx
+if ?chkstk1+???+?po
+leave
+endif
+else
+if ?ff+???+?po+?rp
+leave
+endif
+endif
+else
+ife ?nx
+if (?TF eq 0) or (???+?rp)
+ lea sp,-2[bp]
+endif
+ pop ds
+ pop bp
+ife ?DOS5
+ dec bp
+endif
+else
+if (?TF eq 0) or (???+?rp)
+ mov sp,bp
+endif
+if ???+?po+?rp
+ pop bp
+endif
+endif
+endif
+else
+if ?pmd
+if ?ff+???+?po+?rp
+leave
+endif
+else
+if ?ff+???+?po+?rp
+if (?TF eq 0) or (???+?rp)
+ mov sp,bp
+endif
+ pop bp
+endif
+endif
+endif
+ife cc
+ ret
+else
+ ret o
+endif
+endif
+endif
+n endp
+.cref
+purge cEnd
+&endm
+.cref
+endm
+assumes macro s,ln
+ifndef ln&_assumes
+assume s:ln
+else
+ln&_assumes s
+endif
+endm
+createSeg macro n,ln,a,co,cl,grp
+ifnb <grp>
+addseg grp,n
+else
+ln&OFFSET equ offset n:
+ln&BASE equ n
+?cs3 <ln>,<n>
+endif
+ifnb <cl>
+n segment a co '&cl'
+else
+n segment a co
+endif
+n ends
+?cs1 <ln>,<n>
+endm
+addseg macro grp,seg
+.xcref
+.xcref grp&_def
+.cref
+ifndef grp&_def
+grp&_def=0
+endif
+if grp&_def ne ASMpass
+.xcref
+.xcref grp&_add
+.cref
+grp&_add &macro s
+grp&_in <seg>,s
+&endm
+.xcref
+.xcref grp&_in
+.cref
+grp&_in &macro sl,s
+ifb <s>
+grp group sl
+else
+grp&_add &macro ns
+grp&_in <sl,s>,ns
+&endm
+endif
+&endm
+grp&_def=ASMpass
+else
+grp&_add seg
+endif
+endm
+defgrp macro grp,ln
+addseg grp
+ifnb <ln>
+irp x,<ln>
+?cs3 <&x>,<grp>
+x&&OFFSET equ offset grp:
+x&&BASE equ grp
+endm
+endif
+endm
+?cs1 macro ln,n
+.xcref
+.xcref ln&_sbegin
+.cref
+ln&_sbegin &macro
+.xcref
+.xcref ?mf
+.cref
+?mf &&macro c,l,p
+if c
+ extrn n&_FARFRAME:near
+ call n&_FARFRAME
+else
+ extrn n&_NEARFRAME:near
+ call n&_NEARFRAME
+endif
+ db l shr 1
+ db p shr 1
+&&endm
+?cs2 <ln>,<n>
+n segment
+&endm
+endm
+?cs2 macro ln,n
+.xcref
+.xcref sEnd
+.cref
+sEnd &macro
+n ends
+purge ?mf
+purge sEnd
+&endm
+endm
+?cs3 macro ln,n
+.xcref
+.xcref ln&_assumes
+.cref
+ln&_assumes &macro s
+assume s:&n
+&endm
+endm
+.xcref
+.xcref sBegin
+.cref
+sBegin macro ln
+ln&_sbegin
+endm
+ife ?DF
+createSeg _TEXT,Code,word,public,CODE
+ife ?nodata1
+createSeg _DATA,Data,word,public,DATA,DGROUP
+defgrp DGROUP,Data
+endif
+if ?chkstk1
+ifndef ?CHKSTKPROC
+externp <chkstk>
+endif
+endif
+endif
+errnz macro x
+if2
+if x
+errnz1 <x>,%(x)
+endif
+endif
+endm
+errnz1 macro x1,x2
+= *errnz* x1 = x2
+.err
+endm
+errn$ macro l,x
+errnz <offset $ - offset l x>
+endm
+ifdef ?PROFILE
+externFP <StartNMeas,StopNMeas>
+endif
diff --git a/private/ole32/olethunk/ole16/inc/cmacs.h b/private/ole32/olethunk/ole16/inc/cmacs.h
new file mode 100644
index 000000000..97fda4457
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/cmacs.h
@@ -0,0 +1,72 @@
+/*
+ * **************************** Module Header ******************************\
+ * Module Name: CMACS.H
+ *
+ * This module contains common macros used by C routines.
+ *
+ * Created: 9-Feb-1989
+ *
+ * Copyright (c) 1985 - 1989 Microsoft Corporation
+ *
+ * History:
+ * Created by Raor
+ *
+ * This will eventually be removed completely. Right now, we
+ * define ASSERT in terms of AssertSz.
+ *
+ * \**************************************************************************
+ */
+
+#if !defined( _CMACS_H_ )
+#define _CMACS_H_
+
+#ifndef _MAC
+
+#define DLL_USE
+
+
+#ifdef FIREWALLS
+extern short ole_flags;
+
+#ifndef _DEBUG
+#define _DEBUG
+#endif
+
+#include <debug.h>
+
+#define DEBUG_PUTS 0x01
+#define DEBUG_DEBUG_OUT 0x02
+#define DEBUG_MESSAGEBOX 0x04
+
+extern char szDebugBuffer[];
+
+#define DEBUG_OUT(parm1,parm2){\
+ if(ole_flags & DEBUG_DEBUG_OUT){\
+ wsprintf(szDebugBuffer,parm1,parm2);\
+ OutputDebugString(szDebugBuffer);\
+ OutputDebugString ("^^^ ");\
+ }\
+ }
+
+#define ASSERT(x,y) AssertSz(x,y)
+
+#define Puts(msg) {\
+ if(ole_flags & DEBUG_PUTS){\
+ OutputDebugString ((LPSTR)(msg));\
+ OutputDebugString ("** ");\
+ }\
+ }
+
+#else // FIREWALLS
+
+#define DEBUG_OUT(err, val) ;
+#define ASSERT(cond, msg)
+// #define Puts(msg)
+// FIREWALLS is never defined so let the Puts from debug.h remain defined
+
+#endif // FIREWALLS
+
+#endif // !_MAC
+
+#endif // _CMACS_H_
+
diff --git a/private/ole32/olethunk/ole16/inc/cobjps.h b/private/ole32/olethunk/ole16/inc/cobjps.h
new file mode 100644
index 000000000..ff0359005
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/cobjps.h
@@ -0,0 +1,69 @@
+/*****************************************************************************\
+* *
+* cobjps.h - Definitions for writing standard proxies and stubs *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+#if !defined( _COBJPS_H_ )
+#define _COBJPS_H_
+
+
+/****** IRpcChannel Interface ***********************************************/
+
+interface IRpcChannel : IUnknown
+{
+ STDMETHOD(GetStream)(REFIID iid, int iMethod, BOOL fSend,
+ BOOL fNoWait, DWORD size, IStream FAR* FAR* ppIStream) = 0;
+ STDMETHOD(Call)(IStream FAR* pIStream) = 0;
+ STDMETHOD(GetDestCtx)(DWORD FAR* lpdwDestCtx, LPVOID FAR* lplpvDestCtx) = 0;
+ STDMETHOD(IsConnected)(void) = 0;
+};
+
+
+/****** IRpcProxy Interface *************************************************/
+
+// IRpcProxy is an interface implemented by proxy objects. A proxy object has
+// exactly the same interfaces as the real object in addition to IRpcProxy.
+//
+
+interface IRpcProxy : IUnknown
+{
+ STDMETHOD(Connect)(IRpcChannel FAR* pRpcChannel) = 0;
+ STDMETHOD_(void, Disconnect)(void) = 0;
+};
+
+
+/****** IRpcStub Interface **************************************************/
+
+// IRpcStub is an interface implemented by stub objects.
+//
+
+interface IRpcStub : IUnknown
+{
+ STDMETHOD(Connect)(IUnknown FAR* pUnk) = 0;
+ STDMETHOD_(void, Disconnect)(void) = 0;
+ STDMETHOD(Invoke)(REFIID iid, int iMethod, IStream FAR* pIStream,
+ DWORD dwDestCtx, LPVOID lpvDestCtx) = 0;
+ STDMETHOD_(BOOL, IsIIDSupported)(REFIID iid) = 0;
+ STDMETHOD_(ULONG, CountRefs)(void) = 0;
+};
+
+
+/****** IPSFactory Interface ************************************************/
+
+// IPSFactory - creates proxies and stubs
+//
+
+interface IPSFactory : IUnknown
+{
+ STDMETHOD(CreateProxy)(IUnknown FAR* pUnkOuter, REFIID riid,
+ IRpcProxy FAR* FAR* ppProxy, void FAR* FAR* ppv) = 0;
+ STDMETHOD(CreateStub)(REFIID riid, IUnknown FAR* pUnkServer,
+ IRpcStub FAR* FAR* ppStub) = 0;
+};
+
+#endif // _COBJPS_H_
diff --git a/private/ole32/olethunk/ole16/inc/coguid.h b/private/ole32/olethunk/ole16/inc/coguid.h
new file mode 100644
index 000000000..049884168
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/coguid.h
@@ -0,0 +1,65 @@
+/*****************************************************************************\
+* *
+* coguid.h - Master definition of GUIDs for compobj.dll *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+/* this file is the master definition of all GUIDs for the component object
+ model and is included in compobj.h. Some GUIDs for moinkers and storage
+ appear here as well. All of these GUIDs are OLE GUIDs only in the sense
+ that part of the GUID range owned by OLE was used to define them.
+
+ NOTE: The second byte of all of these GUIDs is 0.
+*/
+
+
+DEFINE_GUID(GUID_NULL, 0L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+DEFINE_OLEGUID(IID_IUnknown, 0x00000000L, 0, 0);
+DEFINE_OLEGUID(IID_IClassFactory, 0x00000001L, 0, 0);
+DEFINE_OLEGUID(IID_IMalloc, 0x00000002L, 0, 0);
+DEFINE_OLEGUID(IID_IMarshal, 0x00000003L, 0, 0);
+
+/* RPC related interfaces */
+DEFINE_OLEGUID(IID_IRpcChannel, 0x00000004L, 0, 0);
+DEFINE_OLEGUID(IID_IRpcStub, 0x00000005L, 0, 0);
+DEFINE_OLEGUID(IID_IStubManager, 0x00000006L, 0, 0);
+DEFINE_OLEGUID(IID_IRpcProxy, 0x00000007L, 0, 0);
+DEFINE_OLEGUID(IID_IProxyManager, 0x00000008L, 0, 0);
+DEFINE_OLEGUID(IID_IPSFactory, 0x00000009L, 0, 0);
+
+/* storage related interfaces */
+DEFINE_OLEGUID(IID_ILockBytes, 0x0000000aL, 0, 0);
+DEFINE_OLEGUID(IID_IStorage, 0x0000000bL, 0, 0);
+DEFINE_OLEGUID(IID_IStream, 0x0000000cL, 0, 0);
+DEFINE_OLEGUID(IID_IEnumSTATSTG, 0x0000000dL, 0, 0);
+
+/* moniker related interfaces */
+DEFINE_OLEGUID(IID_IBindCtx, 0x0000000eL, 0, 0);
+DEFINE_OLEGUID(IID_IMoniker, 0x0000000fL, 0, 0);
+DEFINE_OLEGUID(IID_IRunningObjectTable, 0x00000010L, 0, 0);
+DEFINE_OLEGUID(IID_IInternalMoniker, 0x00000011L, 0, 0);
+
+/* storage related interfaces */
+DEFINE_OLEGUID(IID_IRootStorage, 0x00000012L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved1, 0x00000013L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved2, 0x00000014L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved3, 0x00000015L, 0, 0);
+
+/* concurrency releated interfaces */
+DEFINE_OLEGUID(IID_IMessageFilter, 0x00000016L, 0, 0);
+
+/* CLSID of standard marshaler */
+DEFINE_OLEGUID(CLSID_StdMarshal, 0x00000017L, 0, 0);
+
+/* interface on server for getting info for std marshaler */
+DEFINE_OLEGUID(IID_IStdMarshalInfo, 0x00000018L, 0, 0);
+
+/* interface to inform object of number of external connections */
+DEFINE_OLEGUID(IID_IExternalConnection, 0x00000019L, 0, 0);
+
+/* NOTE: LSB 0x1a through 0xff are reserved for future use */
diff --git a/private/ole32/olethunk/ole16/inc/commdlg.h b/private/ole32/olethunk/ole16/inc/commdlg.h
new file mode 100644
index 000000000..723f7b4d3
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/commdlg.h
@@ -0,0 +1,318 @@
+/*****************************************************************************\
+* *
+* commdlg.h - Common dialog functions, types, and definitions *
+* *
+* Version 1.0 *
+* *
+* NOTE: windows.h must be #included first *
+* *
+* Copyright (c) 1992, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+#ifndef _INC_COMMDLG
+#define _INC_COMMDLG
+
+#ifndef RC_INVOKED
+#pragma pack(1) /* Assume byte packing throughout */
+#endif /* !RC_INVOKED */
+
+#ifdef __cplusplus
+extern "C" { /* Assume C declarations for C++ */
+#endif /* __cplusplus */
+
+#ifndef WINAPI /* If not included with 3.1 headers... */
+#define WINAPI FAR PASCAL
+#define CALLBACK FAR PASCAL
+#define LPCSTR LPSTR
+#define UINT WORD
+#define LPARAM LONG
+#define WPARAM WORD
+#define LRESULT LONG
+#define HMODULE HANDLE
+#define HINSTANCE HANDLE
+#define HLOCAL HANDLE
+#define HGLOBAL HANDLE
+#endif /* _INC_WINDOWS */
+
+typedef struct tagOFN
+{
+ DWORD lStructSize;
+ HWND hwndOwner;
+ HINSTANCE hInstance;
+ LPCSTR lpstrFilter;
+ LPSTR lpstrCustomFilter;
+ DWORD nMaxCustFilter;
+ DWORD nFilterIndex;
+ LPSTR lpstrFile;
+ DWORD nMaxFile;
+ LPSTR lpstrFileTitle;
+ DWORD nMaxFileTitle;
+ LPCSTR lpstrInitialDir;
+ LPCSTR lpstrTitle;
+ DWORD Flags;
+ UINT nFileOffset;
+ UINT nFileExtension;
+ LPCSTR lpstrDefExt;
+ LPARAM lCustData;
+ UINT (CALLBACK *lpfnHook)(HWND, UINT, WPARAM, LPARAM);
+ LPCSTR lpTemplateName;
+} OPENFILENAME;
+typedef OPENFILENAME FAR* LPOPENFILENAME;
+
+BOOL WINAPI GetOpenFileName(OPENFILENAME FAR*);
+BOOL WINAPI GetSaveFileName(OPENFILENAME FAR*);
+int WINAPI GetFileTitle(LPCSTR, LPSTR, UINT);
+
+#define OFN_READONLY 0x00000001
+#define OFN_OVERWRITEPROMPT 0x00000002
+#define OFN_HIDEREADONLY 0x00000004
+#define OFN_NOCHANGEDIR 0x00000008
+#define OFN_SHOWHELP 0x00000010
+#define OFN_ENABLEHOOK 0x00000020
+#define OFN_ENABLETEMPLATE 0x00000040
+#define OFN_ENABLETEMPLATEHANDLE 0x00000080
+#define OFN_NOVALIDATE 0x00000100
+#define OFN_ALLOWMULTISELECT 0x00000200
+#define OFN_EXTENSIONDIFFERENT 0x00000400
+#define OFN_PATHMUSTEXIST 0x00000800
+#define OFN_FILEMUSTEXIST 0x00001000
+#define OFN_CREATEPROMPT 0x00002000
+#define OFN_SHAREAWARE 0x00004000
+#define OFN_NOREADONLYRETURN 0x00008000
+#define OFN_NOTESTFILECREATE 0x00010000
+
+/* Return values for the registered message sent to the hook function
+ * when a sharing violation occurs. OFN_SHAREFALLTHROUGH allows the
+ * filename to be accepted, OFN_SHARENOWARN rejects the name but puts
+ * up no warning (returned when the app has already put up a warning
+ * message), and OFN_SHAREWARN puts up the default warning message
+ * for sharing violations.
+ *
+ * Note: Undefined return values map to OFN_SHAREWARN, but are
+ * reserved for future use.
+ */
+
+#define OFN_SHAREFALLTHROUGH 2
+#define OFN_SHARENOWARN 1
+#define OFN_SHAREWARN 0
+
+typedef struct tagCHOOSECOLOR
+{
+ DWORD lStructSize;
+ HWND hwndOwner;
+ HWND hInstance;
+ COLORREF rgbResult;
+ COLORREF FAR* lpCustColors;
+ DWORD Flags;
+ LPARAM lCustData;
+ UINT (CALLBACK* lpfnHook)(HWND, UINT, WPARAM, LPARAM);
+ LPCSTR lpTemplateName;
+} CHOOSECOLOR;
+typedef CHOOSECOLOR FAR *LPCHOOSECOLOR;
+
+BOOL WINAPI ChooseColor(CHOOSECOLOR FAR*);
+
+#define CC_RGBINIT 0x00000001
+#define CC_FULLOPEN 0x00000002
+#define CC_PREVENTFULLOPEN 0x00000004
+#define CC_SHOWHELP 0x00000008
+#define CC_ENABLEHOOK 0x00000010
+#define CC_ENABLETEMPLATE 0x00000020
+#define CC_ENABLETEMPLATEHANDLE 0x00000040
+
+typedef struct tagFINDREPLACE
+{
+ DWORD lStructSize; /* size of this struct 0x20 */
+ HWND hwndOwner; /* handle to owner's window */
+ HINSTANCE hInstance; /* instance handle of.EXE that
+ * contains cust. dlg. template
+ */
+ DWORD Flags; /* one or more of the FR_?? */
+ LPSTR lpstrFindWhat; /* ptr. to search string */
+ LPSTR lpstrReplaceWith; /* ptr. to replace string */
+ UINT wFindWhatLen; /* size of find buffer */
+ UINT wReplaceWithLen; /* size of replace buffer */
+ LPARAM lCustData; /* data passed to hook fn. */
+ UINT (CALLBACK* lpfnHook)(HWND, UINT, WPARAM, LPARAM);
+ /* ptr. to hook fn. or NULL */
+ LPCSTR lpTemplateName; /* custom template name */
+} FINDREPLACE;
+typedef FINDREPLACE FAR *LPFINDREPLACE;
+
+#define FR_DOWN 0x00000001
+#define FR_WHOLEWORD 0x00000002
+#define FR_MATCHCASE 0x00000004
+#define FR_FINDNEXT 0x00000008
+#define FR_REPLACE 0x00000010
+#define FR_REPLACEALL 0x00000020
+#define FR_DIALOGTERM 0x00000040
+#define FR_SHOWHELP 0x00000080
+#define FR_ENABLEHOOK 0x00000100
+#define FR_ENABLETEMPLATE 0x00000200
+#define FR_NOUPDOWN 0x00000400
+#define FR_NOMATCHCASE 0x00000800
+#define FR_NOWHOLEWORD 0x00001000
+#define FR_ENABLETEMPLATEHANDLE 0x00002000
+#define FR_HIDEUPDOWN 0x00004000
+#define FR_HIDEMATCHCASE 0x00008000
+#define FR_HIDEWHOLEWORD 0x00010000
+
+HWND WINAPI FindText(FINDREPLACE FAR*);
+HWND WINAPI ReplaceText(FINDREPLACE FAR*);
+
+typedef struct tagCHOOSEFONT
+{
+ DWORD lStructSize; /* */
+ HWND hwndOwner; /* caller's window handle */
+ HDC hDC; /* printer DC/IC or NULL */
+ LOGFONT FAR* lpLogFont; /* ptr. to a LOGFONT struct */
+ int iPointSize; /* 10 * size in points of selected font */
+ DWORD Flags; /* enum. type flags */
+ COLORREF rgbColors; /* returned text color */
+ LPARAM lCustData; /* data passed to hook fn. */
+ UINT (CALLBACK* lpfnHook)(HWND, UINT, WPARAM, LPARAM);
+ /* ptr. to hook function */
+ LPCSTR lpTemplateName; /* custom template name */
+ HINSTANCE hInstance; /* instance handle of.EXE that
+ * contains cust. dlg. template
+ */
+ LPSTR lpszStyle; /* return the style field here
+ * must be LF_FACESIZE or bigger */
+ UINT nFontType; /* same value reported to the EnumFonts
+ * call back with the extra FONTTYPE_
+ * bits added */
+ int nSizeMin; /* minimum pt size allowed & */
+ int nSizeMax; /* max pt size allowed if */
+ /* CF_LIMITSIZE is used */
+} CHOOSEFONT;
+typedef CHOOSEFONT FAR *LPCHOOSEFONT;
+
+BOOL WINAPI ChooseFont(CHOOSEFONT FAR*);
+
+#define CF_SCREENFONTS 0x00000001
+#define CF_PRINTERFONTS 0x00000002
+#define CF_BOTH (CF_SCREENFONTS | CF_PRINTERFONTS)
+#define CF_SHOWHELP 0x00000004L
+#define CF_ENABLEHOOK 0x00000008L
+#define CF_ENABLETEMPLATE 0x00000010L
+#define CF_ENABLETEMPLATEHANDLE 0x00000020L
+#define CF_INITTOLOGFONTSTRUCT 0x00000040L
+#define CF_USESTYLE 0x00000080L
+#define CF_EFFECTS 0x00000100L
+#define CF_APPLY 0x00000200L
+#define CF_ANSIONLY 0x00000400L
+#define CF_NOVECTORFONTS 0x00000800L
+#define CF_NOOEMFONTS CF_NOVECTORFONTS
+#define CF_NOSIMULATIONS 0x00001000L
+#define CF_LIMITSIZE 0x00002000L
+#define CF_FIXEDPITCHONLY 0x00004000L
+#define CF_WYSIWYG 0x00008000L /* must also have CF_SCREENFONTS & CF_PRINTERFONTS */
+#define CF_FORCEFONTEXIST 0x00010000L
+#define CF_SCALABLEONLY 0x00020000L
+#define CF_TTONLY 0x00040000L
+#define CF_NOFACESEL 0x00080000L
+#define CF_NOSTYLESEL 0x00100000L
+#define CF_NOSIZESEL 0x00200000L
+
+/* these are extra nFontType bits that are added to what is returned to the
+ * EnumFonts callback routine */
+
+#define SIMULATED_FONTTYPE 0x8000
+#define PRINTER_FONTTYPE 0x4000
+#define SCREEN_FONTTYPE 0x2000
+#define BOLD_FONTTYPE 0x0100
+#define ITALIC_FONTTYPE 0x0200
+#define REGULAR_FONTTYPE 0x0400
+
+#define WM_CHOOSEFONT_GETLOGFONT (WM_USER + 1)
+
+
+/* strings used to obtain unique window message for communication
+ * between dialog and caller
+ */
+#define LBSELCHSTRING "commdlg_LBSelChangedNotify"
+#define SHAREVISTRING "commdlg_ShareViolation"
+#define FILEOKSTRING "commdlg_FileNameOK"
+#define COLOROKSTRING "commdlg_ColorOK"
+#define SETRGBSTRING "commdlg_SetRGBColor"
+#define FINDMSGSTRING "commdlg_FindReplace"
+#define HELPMSGSTRING "commdlg_help"
+
+/* HIWORD values for lParam of commdlg_LBSelChangeNotify message */
+#define CD_LBSELNOITEMS -1
+#define CD_LBSELCHANGE 0
+#define CD_LBSELSUB 1
+#define CD_LBSELADD 2
+
+typedef struct tagPD
+{
+ DWORD lStructSize;
+ HWND hwndOwner;
+ HGLOBAL hDevMode;
+ HGLOBAL hDevNames;
+ HDC hDC;
+ DWORD Flags;
+ UINT nFromPage;
+ UINT nToPage;
+ UINT nMinPage;
+ UINT nMaxPage;
+ UINT nCopies;
+ HINSTANCE hInstance;
+ LPARAM lCustData;
+ UINT (CALLBACK* lpfnPrintHook)(HWND, UINT, WPARAM, LPARAM);
+ UINT (CALLBACK* lpfnSetupHook)(HWND, UINT, WPARAM, LPARAM);
+ LPCSTR lpPrintTemplateName;
+ LPCSTR lpSetupTemplateName;
+ HGLOBAL hPrintTemplate;
+ HGLOBAL hSetupTemplate;
+} PRINTDLG;
+typedef PRINTDLG FAR* LPPRINTDLG;
+
+BOOL WINAPI PrintDlg(PRINTDLG FAR*);
+
+#define PD_ALLPAGES 0x00000000
+#define PD_SELECTION 0x00000001
+#define PD_PAGENUMS 0x00000002
+#define PD_NOSELECTION 0x00000004
+#define PD_NOPAGENUMS 0x00000008
+#define PD_COLLATE 0x00000010
+#define PD_PRINTTOFILE 0x00000020
+#define PD_PRINTSETUP 0x00000040
+#define PD_NOWARNING 0x00000080
+#define PD_RETURNDC 0x00000100
+#define PD_RETURNIC 0x00000200
+#define PD_RETURNDEFAULT 0x00000400
+#define PD_SHOWHELP 0x00000800
+#define PD_ENABLEPRINTHOOK 0x00001000
+#define PD_ENABLESETUPHOOK 0x00002000
+#define PD_ENABLEPRINTTEMPLATE 0x00004000
+#define PD_ENABLESETUPTEMPLATE 0x00008000
+#define PD_ENABLEPRINTTEMPLATEHANDLE 0x00010000
+#define PD_ENABLESETUPTEMPLATEHANDLE 0x00020000
+#define PD_USEDEVMODECOPIES 0x00040000
+#define PD_DISABLEPRINTTOFILE 0x00080000
+#define PD_HIDEPRINTTOFILE 0x00100000
+
+typedef struct tagDEVNAMES
+{
+ UINT wDriverOffset;
+ UINT wDeviceOffset;
+ UINT wOutputOffset;
+ UINT wDefault;
+} DEVNAMES;
+typedef DEVNAMES FAR* LPDEVNAMES;
+
+#define DN_DEFAULTPRN 0x0001
+
+DWORD WINAPI CommDlgExtendedError(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#ifndef RC_INVOKED
+#pragma pack()
+#endif /* !RC_INVOKED */
+
+#endif /* !_INC_COMMDLG */
diff --git a/private/ole32/olethunk/ole16/inc/compobj.h b/private/ole32/olethunk/ole16/inc/compobj.h
new file mode 100644
index 000000000..a438db8e4
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/compobj.h
@@ -0,0 +1,1031 @@
+/*****************************************************************************\
+* *
+* compobj.h - Component object model definitions *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#if !defined( _COMPOBJ_H_ )
+#define _COMPOBJ_H_
+
+/****** Linkage Definitions *************************************************/
+
+/*
+ * These are macros for declaring methods/functions. They exist so that
+ * control over the use of keywords (CDECL, PASCAL, __export,
+ * extern "C") resides in one place, and because this is the least
+ * intrusive way of writing function declarations that do not have
+ * to be modified in order to port to the Mac.
+ *
+ * The macros without the trailing underscore are for functions/methods
+ * which a return value of type HRESULT; this is by far the most common
+ * case in OLE. The macros with a trailing underscore take a return
+ * type as a parameter.
+ *
+ * WARNING: STDAPI is hard coded into the LPFNGETCLASSOBJECT typedef below.
+ */
+
+#ifdef __cplusplus
+ #define EXTERN_C extern "C"
+#else
+ #define EXTERN_C extern
+#endif
+
+#ifdef _MAC
+#define STDMETHODCALLTYPE
+#define STDAPICALLTYPE pascal
+
+#define STDAPI EXTERN_C STDAPICALLTYPE HRESULT
+#define STDAPI_(type) EXTERN_C STDAPICALLTYPE type
+
+#else // !_MAC
+
+#ifdef WIN32
+#define STDMETHODCALLTYPE __export __cdecl
+#define STDAPICALLTYPE __export __stdcall
+
+#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE
+#define STDAPI_(type) EXTERN_C type STDAPICALLTYPE
+
+#else
+#define STDMETHODCALLTYPE __export FAR CDECL
+#define STDAPICALLTYPE __export FAR PASCAL
+
+#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE
+#define STDAPI_(type) EXTERN_C type STDAPICALLTYPE
+
+#endif
+
+#endif //!_MAC
+
+#define STDMETHODIMP HRESULT STDMETHODCALLTYPE
+#define STDMETHODIMP_(type) type STDMETHODCALLTYPE
+
+
+/****** Interface Declaration ***********************************************/
+
+/*
+ * These are macros for declaring interfaces. They exist so that
+ * a single definition of the interface is simulataneously a proper
+ * declaration of the interface structures (C++ abstract classes)
+ * for both C and C++.
+ *
+ * DECLARE_INTERFACE(iface) is used to declare an interface that does
+ * not derive from a base interface.
+ * DECLARE_INTERFACE_(iface, baseiface) is used to declare an interface
+ * that does derive from a base interface.
+ *
+ * By default if the source file has a .c extension the C version of
+ * the interface declaratations will be expanded; if it has a .cpp
+ * extension the C++ version will be expanded. if you want to force
+ * the C version expansion even though the source file has a .cpp
+ * extension, then define the macro "CINTERFACE".
+ * eg. cl -DCINTERFACE file.cpp
+ *
+ * Example Interface declaration:
+ *
+ * #undef INTERFACE
+ * #define INTERFACE IClassFactory
+ *
+ * DECLARE_INTERFACE_(IClassFactory, IUnknown)
+ * {
+ * // *** IUnknown methods ***
+ * STDMETHOD(QueryInterface) (THIS_
+ * REFIID riid,
+ * LPVOID FAR* ppvObj) PURE;
+ * STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ * STDMETHOD_(ULONG,Release) (THIS) PURE;
+ *
+ * // *** IClassFactory methods ***
+ * STDMETHOD(CreateInstance) (THIS_
+ * LPUNKNOWN pUnkOuter,
+ * REFIID riid,
+ * LPVOID FAR* ppvObject) PURE;
+ * };
+ *
+ * Example C++ expansion:
+ *
+ * struct FAR IClassFactory : public IUnknown
+ * {
+ * virtual HRESULT STDMETHODCALLTYPE QueryInterface(
+ * IID FAR& riid,
+ * LPVOID FAR* ppvObj) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE AddRef(void) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE Release(void) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE CreateInstance(
+ * LPUNKNOWN pUnkOuter,
+ * IID FAR& riid,
+ * LPVOID FAR* ppvObject) = 0;
+ * };
+ *
+ * NOTE: Our documentation says '#define interface class' but we use
+ * 'struct' instead of 'class' to keep a lot of 'public:' lines
+ * out of the interfaces. The 'FAR' forces the 'this' pointers to
+ * be far, which is what we need.
+ *
+ * Example C expansion:
+ *
+ * typedef struct IClassFactory
+ * {
+ * const struct IClassFactoryVtbl FAR* lpVtbl;
+ * } IClassFactory;
+ *
+ * typedef struct IClassFactoryVtbl IClassFactoryVtbl;
+ *
+ * struct IClassFactoryVtbl
+ * {
+ * HRESULT (STDMETHODCALLTYPE * QueryInterface) (
+ * IClassFactory FAR* This,
+ * IID FAR* riid,
+ * LPVOID FAR* ppvObj) ;
+ * HRESULT (STDMETHODCALLTYPE * AddRef) (IClassFactory FAR* This) ;
+ * HRESULT (STDMETHODCALLTYPE * Release) (IClassFactory FAR* This) ;
+ * HRESULT (STDMETHODCALLTYPE * CreateInstance) (
+ * IClassFactory FAR* This,
+ * LPUNKNOWN pUnkOuter,
+ * IID FAR* riid,
+ * LPVOID FAR* ppvObject);
+ * HRESULT (STDMETHODCALLTYPE * LockServer) (
+ * IClassFactory FAR* This,
+ * BOOL fLock);
+ * };
+ */
+
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+#ifdef __TURBOC__
+#define interface struct huge
+#else
+#define interface struct FAR
+#endif
+#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method
+#define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method
+#define PURE = 0
+#define THIS_
+#define THIS void
+#define DECLARE_INTERFACE(iface) interface iface
+#define DECLARE_INTERFACE_(iface, baseiface) interface iface : public baseiface
+
+#else
+#define interface struct
+
+#ifdef _MAC
+
+#define STDMETHOD(method) long method##pad;\
+ HRESULT (STDMETHODCALLTYPE * method)
+#define STDMETHOD_(type,method) long method##pad;\
+ type (STDMETHODCALLTYPE * method)
+
+#else // _MAC
+
+#define STDMETHOD(method) HRESULT (STDMETHODCALLTYPE * method)
+#define STDMETHOD_(type,method) type (STDMETHODCALLTYPE * method)
+
+#endif // !_MAC
+
+#define PURE
+#define THIS_ INTERFACE FAR* This,
+#define THIS INTERFACE FAR* This
+#ifdef CONST_VTABLE
+#define DECLARE_INTERFACE(iface) typedef interface iface { \
+ const struct iface##Vtbl FAR* lpVtbl; \
+ } iface; \
+ typedef const struct iface##Vtbl iface##Vtbl; \
+ const struct iface##Vtbl
+#else
+#define DECLARE_INTERFACE(iface) typedef interface iface { \
+ struct iface##Vtbl FAR* lpVtbl; \
+ } iface; \
+ typedef struct iface##Vtbl iface##Vtbl; \
+ struct iface##Vtbl
+#endif
+#define DECLARE_INTERFACE_(iface, baseiface) DECLARE_INTERFACE(iface)
+
+#endif
+
+
+/****** Additional basic types **********************************************/
+
+
+#ifndef FARSTRUCT
+#ifdef __cplusplus
+#define FARSTRUCT FAR
+#else
+#define FARSTRUCT
+#endif // __cplusplus
+#endif // FARSTRUCT
+
+
+#ifndef WINAPI /* If not included with 3.1 headers... */
+
+#ifdef WIN32
+#define FAR
+#define PASCAL __stdcall
+#define CDECL
+#else
+#define FAR _far
+#define PASCAL _pascal
+#define CDECL _cdecl
+#endif
+
+#define VOID void
+#define WINAPI FAR PASCAL
+#define CALLBACK FAR PASCAL
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+typedef int BOOL;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned int UINT;
+
+typedef long LONG;
+typedef unsigned long DWORD;
+
+
+typedef UINT WPARAM;
+typedef LONG LPARAM;
+typedef LONG LRESULT;
+
+typedef unsigned int HANDLE;
+#define DECLARE_HANDLE(name) typedef UINT name
+
+DECLARE_HANDLE(HMODULE);
+DECLARE_HANDLE(HINSTANCE);
+DECLARE_HANDLE(HLOCAL);
+DECLARE_HANDLE(HGLOBAL);
+DECLARE_HANDLE(HDC);
+DECLARE_HANDLE(HRGN);
+DECLARE_HANDLE(HWND);
+DECLARE_HANDLE(HMENU);
+DECLARE_HANDLE(HACCEL);
+DECLARE_HANDLE(HTASK);
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+typedef void FAR * LPVOID;
+typedef WORD FAR * LPWORD;
+typedef DWORD FAR * LPDWORD;
+typedef char FAR* LPSTR;
+typedef const char FAR* LPCSTR;
+typedef void FAR* LPLOGPALETTE;
+typedef void FAR* LPMSG;
+//typedef struct tagMSG FAR *LPMSG;
+
+typedef HANDLE FAR *LPHANDLE;
+typedef struct tagRECT FAR *LPRECT;
+
+typedef struct FARSTRUCT tagSIZE
+{
+ int cx;
+ int cy;
+} SIZE;
+typedef SIZE* PSIZE;
+
+
+#endif /* WINAPI */
+
+
+typedef short SHORT;
+typedef unsigned short USHORT;
+typedef DWORD ULONG;
+
+
+#ifndef HUGEP
+#ifdef WIN32
+#define HUGEP
+#else
+#define HUGEP __huge
+#endif // WIN32
+#endif // HUGEP
+
+typedef WORD WCHAR;
+
+#ifndef WIN32
+typedef struct FARSTRUCT _LARGE_INTEGER {
+ DWORD LowPart;
+ LONG HighPart;
+} LARGE_INTEGER, *PLARGE_INTEGER;
+#endif
+#define LISet32(li, v) ((li).HighPart = ((LONG)(v)) < 0 ? -1 : 0, (li).LowPart = (v))
+
+#ifndef WIN32
+typedef struct FARSTRUCT _ULARGE_INTEGER {
+ DWORD LowPart;
+ DWORD HighPart;
+} ULARGE_INTEGER, *PULARGE_INTEGER;
+#endif
+#define ULISet32(li, v) ((li).HighPart = 0, (li).LowPart = (v))
+
+#ifndef _WINDOWS_
+#ifndef _FILETIME_
+#define _FILETIME_
+typedef struct FARSTRUCT tagFILETIME
+{
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+} FILETIME;
+#endif
+#endif
+
+#ifdef WIN32
+#define HTASK DWORD
+#endif
+
+#include "scode.h"
+
+
+
+// *********************** Compobj errors **********************************
+
+#define CO_E_NOTINITIALIZED (CO_E_FIRST + 0x0)
+// CoInitialize has not been called and must be
+
+#define CO_E_ALREADYINITIALIZED (CO_E_FIRST + 0x1)
+// CoInitialize has already been called and cannot be called again (temporary)
+
+#define CO_E_CANTDETERMINECLASS (CO_E_FIRST + 0x2)
+// can't determine clsid (e.g., extension not in reg.dat)
+
+#define CO_E_CLASSSTRING (CO_E_FIRST + 0x3)
+// the string form of the clsid is invalid (including ole1 classes)
+
+#define CO_E_IIDSTRING (CO_E_FIRST + 0x4)
+// the string form of the iid is invalid
+
+#define CO_E_APPNOTFOUND (CO_E_FIRST + 0x5)
+// application not found
+
+#define CO_E_APPSINGLEUSE (CO_E_FIRST + 0x6)
+// application cannot be run more than once
+
+#define CO_E_ERRORINAPP (CO_E_FIRST + 0x7)
+// some error in the app program file
+
+#define CO_E_DLLNOTFOUND (CO_E_FIRST + 0x8)
+// dll not found
+
+#define CO_E_ERRORINDLL (CO_E_FIRST + 0x9)
+// some error in the dll file
+
+#define CO_E_WRONGOSFORAPP (CO_E_FIRST + 0xa)
+// app written for other version of OS or other OS altogether
+
+#define CO_E_OBJNOTREG (CO_E_FIRST + 0xb)
+// object is not registered
+
+#define CO_E_OBJISREG (CO_E_FIRST + 0xc)
+// object is already registered
+
+#define CO_E_OBJNOTCONNECTED (CO_E_FIRST + 0xd)
+// handler is not connected to server
+
+#define CO_E_APPDIDNTREG (CO_E_FIRST + 0xe)
+// app was launched, but didn't registered a class factory
+
+
+// ********************* ClassObject errors ********************************
+
+#define CLASS_E_NOAGGREGATION (CLASSFACTORY_E_FIRST + 0x0)
+// class does not support aggregation (or class object is remote)
+
+#define CLASS_E_CLASSNOTAVAILABLE (CLASSFACTORY_E_FIRST + 0x1)
+// dll doesn't support that class (returned from DllGetClassObject)
+
+
+// *********************** Reg.dat errors **********************************
+
+#define REGDB_E_READREGDB (REGDB_E_FIRST + 0x0)
+// some error reading the registration database
+
+#define REGDB_E_WRITEREGDB (REGDB_E_FIRST + 0x1)
+// some error reading the registration database
+
+#define REGDB_E_KEYMISSING (REGDB_E_FIRST + 0x2)
+// some error reading the registration database
+
+#define REGDB_E_INVALIDVALUE (REGDB_E_FIRST + 0x3)
+// some error reading the registration database
+
+#define REGDB_E_CLASSNOTREG (REGDB_E_FIRST + 0x4)
+// some error reading the registration database
+
+#define REGDB_E_IIDNOTREG (REGDB_E_FIRST + 0x5)
+// some error reading the registration database
+
+
+// *************************** RPC errors **********************************
+
+#define RPC_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_RPC, 0x000)
+
+// call was rejected by callee, either by MF::HandleIncomingCall or
+#define RPC_E_CALL_REJECTED (RPC_E_FIRST + 0x1)
+
+// call was canceld by call - returned by MessagePending
+// this code only occurs if MessagePending return cancel
+#define RPC_E_CALL_CANCELED (RPC_E_FIRST + 0x2)
+
+// the caller is dispatching an intertask SendMessage call and
+// can NOT call out via PostMessage
+#define RPC_E_CANTPOST_INSENDCALL (RPC_E_FIRST + 0x3)
+
+// the caller is dispatching an asynchronus call can NOT
+// make an outgoing call on behalf of this call
+#define RPC_E_CANTCALLOUT_INASYNCCALL (RPC_E_FIRST + 0x4)
+
+// the caller is not in a state where an outgoing call can be made
+// this is the case if the caller has an outstandig call and
+// another incoming call was excepted by HIC; now the caller is
+// not allowed to call out again
+#define RPC_E_CANTCALLOUT_INEXTERNALCALL (RPC_E_FIRST + 0x5)
+
+// the connection terminated or is in a bogus state
+// and can not be used any more. Other connections
+// are still valid.
+#define RPC_E_CONNECTION_TERMINATED (RPC_E_FIRST + 0x6)
+
+// the callee (server [not server application]) is not available
+// and disappeared; all connections are invalid
+#define RPC_E_SERVER_DIED (RPC_E_FIRST + 0x7)
+
+// the caller (client ) disappeared while the callee (server) was
+// processing a call
+#define RPC_E_CLIENT_DIED (RPC_E_FIRST + 0x8)
+
+// the date paket with the marshalled parameter data is
+// incorrect
+#define RPC_E_INVALID_DATAPACKET (RPC_E_FIRST + 0x9)
+
+// the call was not transmitted properly; the message queue
+// was full and was not emptied after yielding
+#define RPC_E_CANTTRANSMIT_CALL (RPC_E_FIRST + 0xa)
+
+// the client (caller) can not marshall the parameter data
+// or unmarshall the return data - low memory etc.
+#define RPC_E_CLIENT_CANTMARSHAL_DATA (RPC_E_FIRST + 0xb)
+#define RPC_E_CLIENT_CANTUNMARSHAL_DATA (RPC_E_FIRST + 0xc)
+
+// the server (caller) can not unmarshall the parameter data
+// or marshall the return data - low memory
+#define RPC_E_SERVER_CANTMARSHAL_DATA (RPC_E_FIRST + 0xd)
+#define RPC_E_SERVER_CANTUNMARSHAL_DATA (RPC_E_FIRST + 0xe)
+
+// received data are invalid; can be server or
+// client data
+#define RPC_E_INVALID_DATA (RPC_E_FIRST + 0xf)
+
+// a particular parameter is invalid and can not be un/marshalled
+#define RPC_E_INVALID_PARAMETER (RPC_E_FIRST + 0x10)
+
+// DDE conversation - no second outgoing call on same channel
+#define RPC_E_CANTCALLOUT_AGAIN (RPC_E_FIRST + 0x11)
+
+// a internal error occured
+#define RPC_E_UNEXPECTED (RPC_E_FIRST + 0xFFFF)
+
+
+/****** Globally Unique Ids *************************************************/
+
+#ifdef __cplusplus
+
+struct FAR GUID
+{
+ DWORD Data1;
+ WORD Data2;
+ WORD Data3;
+ BYTE Data4[8];
+
+ BOOL operator==(const GUID& iidOther) const
+
+#ifdef WIN32
+ { return !memcmp(&Data1,&iidOther.Data1,sizeof(GUID)); }
+#else
+ { return !_fmemcmp(&Data1,&iidOther.Data1,sizeof(GUID)); }
+#endif
+ BOOL operator!=(const GUID& iidOther) const
+ { return !((*this) == iidOther); }
+};
+
+#else
+typedef struct GUID
+{
+ DWORD Data1;
+ WORD Data2;
+ WORD Data3;
+ BYTE Data4[8];
+} GUID;
+#endif
+
+typedef GUID FAR* LPGUID;
+
+
+// macros to define byte pattern for a GUID.
+// Example: DEFINE_GUID(GUID_XXX, a, b, c, ...);
+//
+// Each dll/exe must initialize the GUIDs once. This is done in one of
+// two ways. If you are not using precompiled headers for the file(s) which
+// initializes the GUIDs, define INITGUID before including compobj.h. This
+// is how OLE builds the initialized versions of the GUIDs which are included
+// in compobj.dll.
+//
+// The alternative (which some versions of the compiler don't handle properly;
+// they wind up with the initialized GUIDs in a data, not a text segment),
+// is to use a precompiled version of compobj.h and then include initguid.h
+// after compobj.h followed by one or more of the guid defintion files.
+
+
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID CDECL FAR name
+
+#ifdef INITGUID
+#include "initguid.h"
+#endif
+
+#define DEFINE_OLEGUID(name, l, w1, w2) \
+ DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)
+
+
+// Interface ID are just a kind of GUID
+typedef GUID IID;
+typedef IID FAR* LPIID;
+#define IID_NULL GUID_NULL
+#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2)
+
+
+// Class ID are just a kind of GUID
+typedef GUID CLSID;
+typedef CLSID FAR* LPCLSID;
+#define CLSID_NULL GUID_NULL
+#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2)
+
+
+#if defined(__cplusplus)
+#define REFGUID const GUID FAR&
+#define REFIID const IID FAR&
+#define REFCLSID const CLSID FAR&
+#else
+#define REFGUID const GUID FAR* const
+#define REFIID const IID FAR* const
+#define REFCLSID const CLSID FAR* const
+#endif
+
+
+#ifndef INITGUID
+#include "coguid.h"
+#endif
+
+/****** Other value types ***************************************************/
+
+// memory context values; passed to CoGetMalloc
+typedef enum tagMEMCTX
+{
+ MEMCTX_TASK = 1, // task (private) memory
+ MEMCTX_SHARED = 2, // shared memory (between processes)
+#ifdef _MAC
+ MEMCTX_MACSYSTEM = 3, // on the mac, the system heap
+#endif
+
+ // these are mostly for internal use...
+ MEMCTX_UNKNOWN = -1, // unknown context (when asked about it)
+ MEMCTX_SAME = -2, // same context (as some other pointer)
+} MEMCTX;
+
+
+
+// class context: used to determine what scope and kind of class object to use
+// NOTE: this is a bitwise enum
+typedef enum tagCLSCTX
+{
+ CLSCTX_INPROC_SERVER = 1, // server dll (runs in same process as caller)
+ CLSCTX_INPROC_HANDLER = 2, // handler dll (runs in same process as caller)
+ CLSCTX_LOCAL_SERVER = 4 // server exe (runs on same machine; diff proc)
+} CLSCTX;
+
+#define CLSCTX_ALL (CLSCTX_INPROC_SERVER| \
+ CLSCTX_INPROC_HANDLER| \
+ CLSCTX_LOCAL_SERVER)
+
+#define CLSCTX_INPROC (CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER)
+
+#define CLSCTX_SERVER (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER)
+
+
+// class registration flags; passed to CoRegisterClassObject
+typedef enum tagREGCLS
+{
+ REGCLS_SINGLEUSE = 0, // class object only generates one instance
+ REGCLS_MULTIPLEUSE = 1, // same class object genereates multiple inst.
+ // and local automatically goes into inproc tbl.
+ REGCLS_MULTI_SEPARATE = 2, // multiple use, but separate control over each
+ // context.
+
+ // NOTE: CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE is the same as
+ // (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER), REGCLS_MULTI_SEPARATE, but
+ // not the same as CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE.
+} REGCLS;
+
+
+// interface marshaling definitions
+#define MARSHALINTERFACE_MIN 40 // minimum number of bytes for interface marshl
+
+// marshaling flags; passed to CoMarshalInterface
+typedef enum tagMSHLFLAGS
+{
+ MSHLFLAGS_NORMAL = 0, // normal marshaling via proxy/stub
+ MSHLFLAGS_TABLESTRONG = 1, // keep object alive; must explicitly release
+ MSHLFLAGS_TABLEWEAK = 2 // doesn't hold object alive; still must release
+} MSHLFLAGS;
+
+// marshal context: determines the destination context of the marshal operation
+typedef enum tagMSHCTX
+{
+ MSHCTX_LOCAL = 0, // unmarshal context is local (eg.shared memory)
+ MSHCTX_NOSHAREDMEM = 1, // unmarshal context has no shared memory access
+} MSHCTX;
+
+
+// call type used by IMessageFilter::HandleIncommingMessage
+typedef enum tagCALLTYPE
+{
+ CALLTYPE_TOPLEVEL = 1, // toplevel call - no outgoing call
+ CALLTYPE_NESTED = 2, // callback on behalf of previous outgoing call - should always handle
+ CALLTYPE_ASYNC = 3, // aysnchronous call - can NOT be rejected
+ CALLTYPE_TOPLEVEL_CALLPENDING = 4, // new toplevel call with new LID
+ CALLTYPE_ASYNC_CALLPENDING = 5 // async call - can NOT be rejected
+} CALLTYPE;
+
+typedef struct tagINTERFACEINFO
+{
+ interface IUnknown FAR *pUnk; // the pointer to the object
+ IID iid; // interface id
+ WORD wMethod; // interface methode
+} INTERFACEINFO, FAR * LPINTERFACEINFO;
+
+// status of server call - returned by IMessageFilter::HandleIncommingCall
+// and passed to IMessageFilter::RetryRejectedCall
+typedef enum tagSERVERCALL
+{
+ SERVERCALL_ISHANDLED = 0,
+ SERVERCALL_REJECTED = 1,
+ SERVERCALL_RETRYLATER = 2
+} SERVERCALL;
+
+
+// Pending type indicates the level of nesting
+typedef enum tagPENDINGTYPE
+{
+ PENDINGTYPE_TOPLEVEL = 1, // toplevel call
+ PENDINGTYPE_NESTED = 2, // nested call
+} PENDINGTYPE;
+
+// return values of MessagePending
+typedef enum tagPENDINGMSG
+{
+ PENDINGMSG_CANCELCALL = 0, // cancel the outgoing call
+ PENDINGMSG_WAITNOPROCESS = 1, // wait for the return and don't dispatch the message
+ PENDINGMSG_WAITDEFPROCESS = 2 // wait and dispatch the message
+
+} PENDINGMSG;
+
+
+// bit flags for IExternalConnection
+typedef enum tagEXTCONN
+{
+ EXTCONN_STRONG = 0x0001 // strong connection
+} EXTCONN;
+
+
+/****** IUnknown Interface **************************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IUnknown
+
+DECLARE_INTERFACE(IUnknown)
+{
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+};
+
+typedef IUnknown FAR* LPUNKNOWN;
+
+
+/****** Class Factory Interface *******************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IClassFactory
+
+DECLARE_INTERFACE_(IClassFactory, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IClassFactory methods ***
+ STDMETHOD(CreateInstance) (THIS_ LPUNKNOWN pUnkOuter,
+ REFIID riid,
+ LPVOID FAR* ppvObject) PURE;
+ STDMETHOD(LockServer) (THIS_ BOOL fLock) PURE;
+
+};
+typedef IClassFactory FAR* LPCLASSFACTORY;
+
+
+/****** Memory Allocation Interface ***************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IMalloc
+
+DECLARE_INTERFACE_(IMalloc, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IMalloc methods ***
+ STDMETHOD_(void FAR*, Alloc) (THIS_ ULONG cb) PURE;
+ STDMETHOD_(void FAR*, Realloc) (THIS_ void FAR* pv, ULONG cb) PURE;
+ STDMETHOD_(void, Free) (THIS_ void FAR* pv) PURE;
+ STDMETHOD_(ULONG, GetSize) (THIS_ void FAR* pv) PURE;
+ STDMETHOD_(int, DidAlloc) (THIS_ void FAR* pv) PURE;
+ STDMETHOD_(void, HeapMinimize) (THIS) PURE;
+};
+typedef IMalloc FAR* LPMALLOC;
+
+
+/****** IMarshal Interface ************************************************/
+
+// forward declaration for IStream; must include storage.h later to use
+#ifdef __cplusplus
+interface IStream;
+#else
+typedef interface IStream IStream;
+#endif
+typedef IStream FAR* LPSTREAM;
+
+
+#undef INTERFACE
+#define INTERFACE IMarshal
+
+DECLARE_INTERFACE_(IMarshal, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IMarshal methods ***
+ STDMETHOD(GetUnmarshalClass)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid) PURE;
+ STDMETHOD(GetMarshalSizeMax)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize) PURE;
+ STDMETHOD(MarshalInterface)(THIS_ LPSTREAM pStm, REFIID riid,
+ LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags) PURE;
+ STDMETHOD(UnmarshalInterface)(THIS_ LPSTREAM pStm, REFIID riid,
+ LPVOID FAR* ppv) PURE;
+ STDMETHOD(ReleaseMarshalData)(THIS_ LPSTREAM pStm) PURE;
+ STDMETHOD(DisconnectObject)(THIS_ DWORD dwReserved) PURE;
+};
+typedef IMarshal FAR* LPMARSHAL;
+
+
+#undef INTERFACE
+#define INTERFACE IStdMarshalInfo
+
+DECLARE_INTERFACE_(IStdMarshalInfo, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IStdMarshalInfo methods ***
+ STDMETHOD(GetClassForHandler)(THIS_ DWORD dwDestContext,
+ LPVOID pvDestContext, LPCLSID pClsid) PURE;
+};
+typedef IStdMarshalInfo FAR* LPSTDMARSHALINFO;
+
+
+/****** Message Filter Interface *******************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IMessageFilter
+
+DECLARE_INTERFACE_(IMessageFilter, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IMessageFilter methods ***
+ STDMETHOD_(DWORD, HandleInComingCall) (THIS_ DWORD dwCallType,
+ HTASK htaskCaller, DWORD dwTickCount,
+ DWORD dwReserved ) PURE;
+ STDMETHOD_(DWORD, RetryRejectedCall) (THIS_
+ HTASK htaskCallee, DWORD dwTickCount,
+ DWORD dwRejectType ) PURE;
+ STDMETHOD_(DWORD, MessagePending) (THIS_
+ HTASK htaskCallee, DWORD dwTickCount,
+ DWORD dwPendingType ) PURE;
+};
+typedef IMessageFilter FAR* LPMESSAGEFILTER;
+
+
+/****** External Connection Information ***********************************/
+
+#undef INTERFACE
+#define INTERFACE IExternalConnection
+
+DECLARE_INTERFACE_(IExternalConnection, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IExternalConnection methods ***
+ STDMETHOD_(DWORD, AddConnection) (THIS_ DWORD extconn, DWORD reserved) PURE;
+ STDMETHOD_(DWORD, ReleaseConnection) (THIS_ DWORD extconn, DWORD reserved, BOOL fLastReleaseCloses) PURE;
+};
+typedef IExternalConnection FAR* LPEXTERNALCONNECTION;
+
+
+/****** Enumerator Interfaces *********************************************/
+
+/*
+ * Since we don't use parametrized types, we put in explicit declarations
+ * of the enumerators we need.
+ */
+
+
+#undef INTERFACE
+#define INTERFACE IEnumString
+
+DECLARE_INTERFACE_(IEnumString, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumString methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt,
+ LPSTR FAR* rgelt,
+ ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumString FAR* FAR* ppenm) PURE;
+};
+typedef IEnumString FAR* LPENUMSTRING;
+
+
+#undef INTERFACE
+#define INTERFACE IEnumUnknown
+
+DECLARE_INTERFACE_(IEnumUnknown, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumUnknown methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, LPUNKNOWN FAR* rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumUnknown FAR* FAR* ppenm) PURE;
+};
+typedef IEnumUnknown FAR* LPENUMUNKNOWN;
+
+
+/****** STD Object API Prototypes *****************************************/
+
+STDAPI_(DWORD) CoBuildVersion( VOID );
+
+/* init/uninit */
+
+STDAPI CoInitialize(LPMALLOC pMalloc);
+STDAPI_(void) CoUninitialize(void);
+STDAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC FAR* ppMalloc);
+STDAPI_(DWORD) CoGetCurrentProcess(void);
+STDAPI CoCreateStandardMalloc(DWORD memctx, IMalloc FAR* FAR* ppMalloc);
+
+
+/* register/revoke/get class objects */
+
+STDAPI CoGetClassObject(REFCLSID rclsid, DWORD dwClsContext, LPVOID pvReserved,
+ REFIID riid, LPVOID FAR* ppv);
+STDAPI CoRegisterClassObject(REFCLSID rclsid, LPUNKNOWN pUnk,
+ DWORD dwClsContext, DWORD flags, LPDWORD lpdwRegister);
+STDAPI CoRevokeClassObject(DWORD dwRegister);
+
+
+/* marshaling interface pointers */
+
+STDAPI CoMarshalInterface(LPSTREAM pStm, REFIID riid, LPUNKNOWN pUnk,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags);
+STDAPI CoUnmarshalInterface(LPSTREAM pStm, REFIID riid, LPVOID FAR* ppv);
+STDAPI CoMarshalHresult(LPSTREAM pstm, HRESULT hresult);
+STDAPI CoUnmarshalHresult(LPSTREAM pstm, HRESULT FAR * phresult);
+STDAPI CoReleaseMarshalData(LPSTREAM pStm);
+STDAPI CoDisconnectObject(LPUNKNOWN pUnk, DWORD dwReserved);
+STDAPI CoLockObjectExternal(LPUNKNOWN pUnk, BOOL fLock, BOOL fLastUnlockReleases);
+STDAPI CoGetStandardMarshal(REFIID riid, LPUNKNOWN pUnk,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags,
+ LPMARSHAL FAR* ppMarshal);
+
+STDAPI_(BOOL) CoIsHandlerConnected(LPUNKNOWN pUnk);
+
+/* dll loading helpers; keeps track of ref counts and unloads all on exit */
+
+STDAPI_(HINSTANCE) CoLoadLibrary(LPSTR lpszLibName, BOOL bAutoFree);
+STDAPI_(void) CoFreeLibrary(HINSTANCE hInst);
+STDAPI_(void) CoFreeAllLibraries(void);
+STDAPI_(void) CoFreeUnusedLibraries(void);
+
+
+/* helper for creating instances */
+
+STDAPI CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
+ DWORD dwClsContext, REFIID riid, LPVOID FAR* ppv);
+
+
+/* other helpers */
+STDAPI_(BOOL) IsEqualGUID(REFGUID rguid1, REFGUID rguid2);
+STDAPI StringFromCLSID(REFCLSID rclsid, LPSTR FAR* lplpsz);
+STDAPI CLSIDFromString(LPSTR lpsz, LPCLSID pclsid);
+STDAPI StringFromIID(REFIID rclsid, LPSTR FAR* lplpsz);
+STDAPI IIDFromString(LPSTR lpsz, LPIID lpiid);
+STDAPI_(BOOL) CoIsOle1Class(REFCLSID rclsid);
+STDAPI ProgIDFromCLSID (REFCLSID clsid, LPSTR FAR* lplpszProgID);
+STDAPI CLSIDFromProgID (LPCSTR lpszProgID, LPCLSID lpclsid);
+STDAPI_(int) StringFromGUID2(REFGUID rguid, LPSTR lpsz, int cbMax);
+
+STDAPI CoCreateGuid(GUID FAR *pguid);
+
+STDAPI_(BOOL) CoFileTimeToDosDateTime(
+ FILETIME FAR* lpFileTime, LPWORD lpDosDate, LPWORD lpDosTime);
+STDAPI_(BOOL) CoDosDateTimeToFileTime(
+ WORD nDosDate, WORD nDosTime, FILETIME FAR* lpFileTime);
+STDAPI CoFileTimeNow( FILETIME FAR* lpFileTime );
+
+
+STDAPI CoRegisterMessageFilter( LPMESSAGEFILTER lpMessageFilter,
+ LPMESSAGEFILTER FAR* lplpMessageFilter );
+
+
+/* TreatAs APIS */
+
+STDAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID pClsidNew);
+STDAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew);
+
+
+/* the server dlls must define their DllGetClassObject and DllCanUnloadNow
+ * to match these; the typedefs are located here to ensure all are changed at
+ * the same time.
+ */
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID FAR* ppv);
+#ifdef _MAC
+typedef STDAPICALLTYPE HRESULT (FAR* LPFNGETCLASSOBJECT) (REFCLSID, REFIID, LPVOID FAR*);
+#else
+typedef HRESULT (STDAPICALLTYPE FAR* LPFNGETCLASSOBJECT) (REFCLSID, REFIID, LPVOID FAR*);
+#endif
+
+
+STDAPI DllCanUnloadNow(void);
+#ifdef _MAC
+typedef STDAPICALLTYPE HRESULT (FAR* LPFNCANUNLOADNOW)(void);
+#else
+typedef HRESULT (STDAPICALLTYPE FAR* LPFNCANUNLOADNOW)(void);
+#endif
+
+
+/****** Debugging Helpers *************************************************/
+
+#ifdef _DEBUG
+// writes to the debug port and displays a message box
+STDAPI FnAssert(LPSTR lpstrExpr, LPSTR lpstrMsg, LPSTR lpstrFileName, UINT iLine);
+#endif // _DEBUG
+
+#endif // _COMPOBJ_H_
diff --git a/private/ole32/olethunk/ole16/inc/cosegs.h b/private/ole32/olethunk/ole16/inc/cosegs.h
new file mode 100644
index 000000000..139597f9c
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/cosegs.h
@@ -0,0 +1,2 @@
+
+
diff --git a/private/ole32/olethunk/ole16/inc/ctype.h b/private/ole32/olethunk/ole16/inc/ctype.h
new file mode 100644
index 000000000..46749e148
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/ctype.h
@@ -0,0 +1,116 @@
+/***
+*ctype.h - character conversion macros and ctype macros
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines macros for character classification/conversion.
+* [ANSI/System V]
+*
+****/
+
+#ifndef _INC_CTYPE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (_MSC_VER <= 600)
+#define __cdecl _cdecl
+#define __far _far
+#define __near _near
+#endif
+
+/*
+ * This declaration allows the user access to the ctype look-up
+ * array _ctype defined in ctype.obj by simply including ctype.h
+ */
+
+extern unsigned char __near __cdecl _ctype[];
+
+/* set bit masks for the possible character types */
+
+#define _UPPER 0x1 /* upper case letter */
+#define _LOWER 0x2 /* lower case letter */
+#define _DIGIT 0x4 /* digit[0-9] */
+#define _SPACE 0x8 /* tab, carriage return, newline, */
+ /* vertical tab or form feed */
+#define _PUNCT 0x10 /* punctuation character */
+#define _CONTROL 0x20 /* control character */
+#define _BLANK 0x40 /* space char */
+#define _HEX 0x80 /* hexadecimal digit */
+
+/* character classification function prototypes */
+
+#ifndef _CTYPE_DEFINED
+int __cdecl isalpha(int);
+int __cdecl isupper(int);
+int __cdecl islower(int);
+int __cdecl isdigit(int);
+int __cdecl isxdigit(int);
+int __cdecl isspace(int);
+int __cdecl ispunct(int);
+int __cdecl isalnum(int);
+int __cdecl isprint(int);
+int __cdecl isgraph(int);
+int __cdecl iscntrl(int);
+int __cdecl toupper(int);
+int __cdecl tolower(int);
+int __cdecl _tolower(int);
+int __cdecl _toupper(int);
+int __cdecl __isascii(int);
+int __cdecl __toascii(int);
+int __cdecl __iscsymf(int);
+int __cdecl __iscsym(int);
+#define _CTYPE_DEFINED
+#endif
+
+
+/* the character classification macro definitions */
+
+#define isalpha(_c) ( (_ctype+1)[_c] & (_UPPER|_LOWER) )
+#define isupper(_c) ( (_ctype+1)[_c] & _UPPER )
+#define islower(_c) ( (_ctype+1)[_c] & _LOWER )
+#define isdigit(_c) ( (_ctype+1)[_c] & _DIGIT )
+#define isxdigit(_c) ( (_ctype+1)[_c] & _HEX )
+#define isspace(_c) ( (_ctype+1)[_c] & _SPACE )
+#define ispunct(_c) ( (_ctype+1)[_c] & _PUNCT )
+#define isalnum(_c) ( (_ctype+1)[_c] & (_UPPER|_LOWER|_DIGIT) )
+#define isprint(_c) ( (_ctype+1)[_c] & (_BLANK|_PUNCT|_UPPER|_LOWER|_DIGIT) )
+#define isgraph(_c) ( (_ctype+1)[_c] & (_PUNCT|_UPPER|_LOWER|_DIGIT) )
+#define iscntrl(_c) ( (_ctype+1)[_c] & _CONTROL )
+#ifndef __STDC__
+#define toupper(_c) ( (islower(_c)) ? _toupper(_c) : (_c) )
+#define tolower(_c) ( (isupper(_c)) ? _tolower(_c) : (_c) )
+#endif
+#define _tolower(_c) ( (_c)-'A'+'a' )
+#define _toupper(_c) ( (_c)-'a'+'A' )
+#define __isascii(_c) ( (unsigned)(_c) < 0x80 )
+#define __toascii(_c) ( (_c) & 0x7f )
+
+/* extended ctype macros */
+
+#define __iscsymf(_c) (isalpha(_c) || ((_c) == '_'))
+#define __iscsym(_c) (isalnum(_c) || ((_c) == '_'))
+
+#ifndef __STDC__
+/* Non-ANSI names for compatibility */
+#ifndef _CTYPE_DEFINED
+int __cdecl isascii(int);
+int __cdecl toascii(int);
+int __cdecl iscsymf(int);
+int __cdecl iscsym(int);
+#else
+#define isascii __isascii
+#define toascii __toascii
+#define iscsymf __iscsymf
+#define iscsym __iscsym
+#endif
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_CTYPE
+#endif /* _INC_CTYPE */
diff --git a/private/ole32/olethunk/ole16/inc/ddesegs.h b/private/ole32/olethunk/ole16/inc/ddesegs.h
new file mode 100644
index 000000000..139597f9c
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/ddesegs.h
@@ -0,0 +1,2 @@
+
+
diff --git a/private/ole32/olethunk/ole16/inc/debnot.h b/private/ole32/olethunk/ole16/inc/debnot.h
new file mode 100644
index 000000000..26b89fae1
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/debnot.h
@@ -0,0 +1,685 @@
+//+---------------------------------------------------------------------------
+// Copyright (C) 1991, Microsoft Corporation.
+//
+// File: DEBNOT.h
+//
+// Contents: Private project-wide Win 4 definitions
+//
+// History: 23-Jul-91 KyleP Created.
+// 15-Oct-91 KevinRo Major changes and comments added
+// 18-Oct-91 vich Consolidated win4p.hxx
+// 22-Oct-91 SatoNa Added SHLSTRICT
+// 29-Apr-92 BartoszM Moved from win4p.h
+// 3-Jun-92 BruceFo Added SMUISTRICT
+// 17-Dec-92 AlexT Moved UN..._PARM out of DEVL==1
+// 30-Sep-93 KyleP DEVL obsolete
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DEBNOT_H__
+#define __DEBNOT_H__
+
+#include <stdarg.h>
+
+//----------------------------------------------------------------------------
+// Parameter Macros
+//
+// To avoid compiler warnings for unimplemented functions, use
+// UNIMPLEMENTED_PARM(x) for each unreferenced parameter. This will
+// later be defined to nul to reveal functions that we forgot to implement.
+//
+// For functions which will never use a parameter, use
+// UNREFERENCED_PARM(x).
+//
+
+#define UNIMPLEMENTED_PARM(x) (x)
+
+#define UNREFERENCED_PARM(x) (x)
+
+//----------------------------------------------------------------------------
+//
+// New STRICT defines should be added in two places below:
+//
+// 1) Add the following within the ifdef ALLSTRICT/endif:
+//
+// #ifndef xxSTRICT
+// # define xxSTRICT
+// #endif
+//
+// These entries are in alphabetical order.
+//
+// 2) Add the following to the #if clause that defines ANYSTRICT:
+//
+// #if ... || defined(xxSTRICT) || ...
+//
+// so that ANYSTRICT is defined if any of the STRICT defines are.
+//
+
+#if (DBG == 1) || (OFSDBG == 1)
+
+# ifndef CATSTRICT
+# define CATSTRICT
+# endif
+
+# ifndef CISTRICT
+# define CISTRICT
+# endif
+
+# ifndef CMSSTRICT
+# define CMSSTRICT
+# endif
+
+# ifndef DLOSSTRICT
+# define DLOSSTRICT
+# endif
+
+# ifndef EVSTRICT
+# define EVSTRICT
+# endif
+
+# ifndef ICLSTRICT
+# define ICLSTRICT
+# endif
+
+# ifndef INSSTRICT
+# define INSSTRICT
+# endif
+
+# ifndef JWSTRICT
+# define JWSTRICT
+# endif
+
+# ifndef NSSTRICT
+# define NSSTRICT
+# endif
+
+# ifndef OLSTRICT
+# define OLSTRICT
+# endif
+
+# ifndef OMSTRICT
+# define OMSTRICT
+# endif
+
+# ifndef REPLSTRICT
+# define REPLSTRICT
+# endif
+
+# ifndef SHLSTRICT
+# define SHLSTRICT
+# endif
+
+# ifndef SLSTRICT
+# define SLSTRICT
+# endif
+
+# ifndef SMUISTRICT
+# define SMUISTRICT
+# endif
+
+# ifndef SOMSTRICT
+# define SOMSTRICT
+# endif
+
+# ifndef VCSTRICT
+# define VCSTRICT
+# endif
+
+# ifndef VQSTRICT
+# define VQSTRICT
+# endif
+
+# ifndef WMASTRICT
+# define WMASTRICT
+# endif
+
+
+#endif // (DBG == 1) || (OFSDBG == 1)
+
+//
+// ANYSTRICT
+//
+
+#if defined(CATSTRICT) || \
+ defined(CISTRICT) || \
+ defined(CMSSTRICT) || \
+ defined(DLOSSTRICT)|| \
+ defined(ICLSTRICT) || \
+ defined(INSSTRICT) || \
+ defined(JWSTRICT) || \
+ defined(NSSTRICT) || \
+ defined(OLSTRICT) || \
+ defined(OMSTRICT) || \
+ defined(REPLSTRICT)|| \
+ defined(SHLSTRICT) || \
+ defined(SLSTRICT) || \
+ defined(SMUISTRICT)|| \
+ defined(SOMSTRICT) || \
+ defined(VCSTRICT) || \
+ defined(VQSTRICT) || \
+ defined(WMASTRICT)
+
+# define ANYSTRICT
+
+#endif
+
+#if (DBG != 1 && OFSDBG != 1) && defined(ANYSTRICT)
+#pragma message BUGBUG: Asserts are defined in a RETAIL build...
+#endif
+
+
+#if defined(WIN32)
+#ifndef DEBFAR
+#define DEBFAR
+#endif
+ #include <windef.h>
+ #if WIN32 > 200
+ #include <winnot.h>
+ #endif
+#else
+#ifndef DEBFAR
+#define DEBFAR __far
+#endif
+#endif
+
+#ifndef EXPORTDEF
+ #define EXPORTDEF
+#endif
+#ifndef EXPORTIMP
+ #define EXPORTIMP
+#endif
+#ifndef EXPORTED
+ #define EXPORTED _cdecl
+#endif
+#ifndef APINOT
+#ifdef _X86_
+ #define APINOT _stdcall
+#else
+ #define APINOT _cdecl
+#endif
+#endif
+
+//
+// DEBUG -- DEBUG -- DEBUG -- DEBUG -- DEBUG
+//
+
+#if (DBG == 1) || (OFSDBG == 1)
+
+//
+// Debug print functions.
+//
+
+#ifdef __cplusplus
+extern "C" {
+# define EXTRNC "C"
+#else
+# define EXTRNC
+#endif
+
+
+
+// vdprintf should only be called from xxDebugOut()
+
+ EXPORTDEF void APINOT
+ vdprintf(
+ unsigned long ulCompMask,
+ char const DEBFAR *pszComp,
+ char const DEBFAR *ppszfmt,
+ va_list ArgList);
+
+ #define _Win4Assert Win4AssertEx
+
+ EXPORTDEF void APINOT
+ Win4AssertEx(
+ char const DEBFAR *pszFile,
+ int iLine,
+ char const DEBFAR *pszMsg);
+
+ EXPORTDEF int APINOT
+ PopUpError(
+ char const DEBFAR *pszMsg,
+ int iLine,
+ char const DEBFAR *pszFile);
+
+ #define _SetWin4InfoLevel SetWin4InfoLevel
+
+ EXPORTDEF unsigned long APINOT
+ SetWin4InfoLevel(
+ unsigned long ulNewLevel);
+
+ EXPORTDEF unsigned long APINOT
+ SetWin4InfoMask(
+ unsigned long ulNewMask);
+
+ #define _SetWin4AssertLevel SetWin4AssertLevel
+
+ EXPORTDEF unsigned long APINOT
+ SetWin4AssertLevel(
+ unsigned long ulNewLevel);
+
+ EXPORTDEF unsigned long APINOT
+ SetWin4ExceptionLevel(
+ unsigned long ulNewLevel);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+# define EXSTRICT // (EXception STRICT) - Enabled if ANYSTRICT is enabled
+
+# define Win4Assert(x) if ( !(x) ) \
+ Win4AssertEx ( __FILE__, __LINE__, #x );
+
+
+//
+// Debug print macros
+//
+
+# define DEB_ERROR 0x00000001 // exported error paths
+# define DEB_WARN 0x00000002 // exported warnings
+# define DEB_TRACE 0x00000004 // exported trace messages
+
+# define DEB_DBGOUT 0x00000010 // Output to debugger
+# define DEB_STDOUT 0x00000020 // Output to stdout
+
+# define DEB_IERROR 0x00000100 // internal error paths
+# define DEB_IWARN 0x00000200 // internal warnings
+# define DEB_ITRACE 0x00000400 // internal trace messages
+
+# define DEB_USER1 0x00010000 // User defined
+# define DEB_USER2 0x00020000 // User defined
+# define DEB_USER3 0x00040000 // User defined
+# define DEB_USER4 0x00080000 // User defined
+# define DEB_USER5 0x00100000 // User defined
+# define DEB_USER6 0x00200000 // User defined
+# define DEB_USER7 0x00400000 // User defined
+# define DEB_USER8 0x00800000 // User defined
+# define DEB_USER9 0x01000000 // User defined
+# define DEB_USER10 0x02000000 // User defined
+# define DEB_USER11 0x04000000 // User defined
+# define DEB_USER12 0x08000000 // User defined
+# define DEB_USER13 0x10000000 // User defined
+# define DEB_USER14 0x20000000 // User defined
+# define DEB_USER15 0x40000000 // User defined
+
+# define DEB_NOCOMPNAME 0x80000000 // suppress component name
+
+# define DEB_FORCE 0x7fffffff // force message
+
+# define ASSRT_MESSAGE 0x00000001 // Output a message
+# define ASSRT_BREAK 0x00000002 // Int 3 on assertion
+# define ASSRT_POPUP 0x00000004 // And popup message
+
+# define EXCEPT_MESSAGE 0x00000001 // Output a message
+# define EXCEPT_BREAK 0x00000002 // Int 3 on exception
+# define EXCEPT_POPUP 0x00000004 // Popup message
+# define EXCEPT_FAULT 0x00000008 // generate int 3 on access violation
+
+
+//+----------------------------------------------------------------------
+//
+// DECLARE_DEBUG(comp)
+// DECLARE_INFOLEVEL(comp)
+//
+// This macro defines xxDebugOut where xx is the component prefix
+// to be defined. This declares a static variable 'xxInfoLevel', which
+// can be used to control the type of xxDebugOut messages printed to
+// the terminal. For example, xxInfoLevel may be set at the debug terminal.
+// This will enable the user to turn debugging messages on or off, based
+// on the type desired. The predefined types are defined below. Component
+// specific values should use the upper 24 bits
+//
+// To Use:
+//
+// 1) In your components main include file, include the line
+// DECLARE_DEBUG(comp)
+// where comp is your component prefix
+//
+// 2) In one of your components source files, include the line
+// DECLARE_INFOLEVEL(comp)
+// where comp is your component prefix. This will define the
+// global variable that will control output.
+//
+// It is suggested that any component define bits be combined with
+// existing bits. For example, if you had a specific error path that you
+// wanted, you might define DEB_<comp>_ERRORxxx as being
+//
+// (0x100 | DEB_ERROR)
+//
+// This way, we can turn on DEB_ERROR and get the error, or just 0x100
+// and get only your error.
+//
+// Define values that are specific to your xxInfoLevel variable in your
+// own file, like ciquery.hxx.
+//
+//-----------------------------------------------------------------------
+
+# ifndef DEF_INFOLEVEL
+# define DEF_INFOLEVEL (DEB_ERROR | DEB_WARN)
+# endif
+
+
+# if (WIN32 > 200) && defined(WIN32) && defined(__cplusplus) && !defined(KERNEL)
+# include <dbgpoint.hxx>
+# endif
+
+//+----------------------------------------------------------------------
+//
+// This next section makes for some really dense reading! Most of it is
+// used for the debugging window. It defines some macros that make it
+// easier to define debug groups and debug break points, since the macros
+// expand to nothing if DEVL != 1. Check out dbgpoint.hxx for more info.
+//
+//
+// The following macros allow you to do things like this
+//
+// DECLARE_GROUP(FooDebugingGroup)
+//
+// DECLARE_BREAKPOINT(FooBreakPoint,FooDebuggingGroup,FALSE)
+//
+// foo()
+// {
+// TEST_BREAKPOINT(FooBreakPoint);
+// }
+//
+//
+//-----------------------------------------------------------------------
+
+# if (WIN32 > 200) && defined(__cplusplus) && defined(WIN32) && !defined(KERNEL)
+
+//
+// The following class is used to register debug groups as static
+// members. Its only needed when DBG is set.
+//
+//
+// The easy way to declare a group, and have it registered for you
+//
+# define DECLARE_GROUP(grpName) \
+ CDebugGroupClass grpName ((L#grpName));
+
+//
+// The easy way to define a group in a header file for use cross module
+//
+# define DEFINE_GROUP(grpName) extern CDebugGroupClass grpName;
+
+//
+// The easy way to declare a breakpoint is with the following macro.
+//
+# define DECLARE_BREAKPOINT(Name,hGroup,fEnabled) \
+ CDebugBreakPoint Name((L#Name),hGroup,fEnabled)
+
+//
+// If you need to have global access to a break point, use this in
+// an include file
+//
+
+# define DEFINE_BREAKPOINT(Name) \
+ extern CDebugBreakPoint Name;
+
+
+//
+// A debug value is a class that allows you to wrap the contents of any
+// integer value, and publish it in the debug window. The actual debug
+// value keeps a reference to the actual value. Therefore, you can attach
+// it to any long in the program.
+//
+// If you use the CDebugValue::SetValue() to change it, the change will
+// be reflected in the window immediately.
+//
+// DECLARE_DEBUGVALUE( Name of Debug Value, Group, Reference to data object)
+//
+# define DECLARE_DEBUGVALUE(Name,hGroup,Value) \
+ CDebugValue Name((L#Name),hGroup,Value)
+
+# define DEFINE_DEBUGVALUE(Name) \
+ extern CDebugValue Name;
+
+
+//
+// This is the same as above, only you can specify your own title for the
+// debug value.
+//
+// DECLARE_DEBUGVALUEEX( Name of Debug Value, Title, Group, Reference to data object)
+//
+# define DECLARE_DEBUGVALUEEX(Name,Title,hGroup,Value) \
+ CDebugValue Name(Title,hGroup,Value)
+
+//
+// If you need to have global access to a break point, use this in
+// an include file
+//
+
+# define DEFINE_BREAKPOINT(Name) \
+ extern CDebugBreakPoint Name;
+
+
+//
+// This test uses a default value for the HRESULT in the window. Use it
+// when you don't have one. If you have an HRESULT you could display,
+// please use TEST_BREAKPOINTHR
+//
+
+# define TEST_BREAKPOINT(x) if( (x).BreakPointTest() && \
+ (x).BreakPointMessage(__FILE__,__LINE__) )\
+ { DebugBreak(); }
+
+//
+// This test includes an HRESULT as a parameter. You should use this one
+//
+# define TEST_BREAKPOINTHR(x,hr) if( (x).BreakPointTest() && \
+ (x).BreakPointMessage(__FILE__,__LINE__,hr) )\
+ { DebugBreak(); }
+
+
+# define MAKE_CINFOLEVEL(comp) \
+ CInfoLevel comp##CInfoLevel((L#comp),comp##InfoLevel);
+
+# else // (WIN32 > 200) && defined(__cplusplus) && defined(WIN32) && !defined(KERNEL)
+
+
+//
+// In the non debug version or C version, don't define these
+//
+
+# define MAKE_CINFOLEVEL(comp)
+# define DECLARE_GROUP(Name)
+# define DEFINE_GROUP(Name)
+# define DEFINE_BREAKPOINT(Name)
+# define DECLARE_BREAKPOINT(Name,hGroup,fEnabled)
+# define TEST_BREAKPOINT(x)
+# define TEST_BREAKPOINTHR(x,hr)
+# define DECLARE_DEBUGVALUE(Name,hGroup,Value)
+# define DECLARE_DEBUGVALUEEX(Name,Title,hGroup,Value)
+# define DEFINE_DEBUGVALUE(Name)
+
+# endif // #if (WIN32 > 200) && defined(__cplusplus) && defined(WIN32) && !defined(KERNEL)
+
+
+//
+// Back to the info level stuff.
+//
+
+# ifdef __cplusplus
+extern "C" {
+# endif // __cplusplus
+
+# define DECLARE_INFOLEVEL(comp) \
+ extern EXTRNC unsigned long comp##InfoLevel = DEF_INFOLEVEL;\
+ extern EXTRNC char *comp##InfoLevelString = #comp;\
+ MAKE_CINFOLEVEL(comp)
+
+# ifdef __cplusplus
+}
+# endif
+
+# ifdef __cplusplus
+
+# define DECLARE_DEBUG(comp) \
+ extern EXTRNC unsigned long comp##InfoLevel; \
+ extern EXTRNC char *comp##InfoLevelString; \
+ _inline void \
+ comp##InlineDebugOut(unsigned long fDebugMask, char const DEBFAR *pszfmt, ...) \
+ { \
+ if (comp##InfoLevel & fDebugMask) \
+ { \
+ va_list va; \
+ va_start (va, pszfmt); \
+ vdprintf(fDebugMask, comp##InfoLevelString, pszfmt, va);\
+ va_end(va); \
+ } \
+ } \
+ \
+ class comp##CDbgTrace\
+ {\
+ private:\
+ unsigned long _ulFlags;\
+ char const DEBFAR * const _pszName;\
+ public:\
+ comp##CDbgTrace(unsigned long ulFlags, char const DEBFAR * const pszName);\
+ ~comp##CDbgTrace();\
+ };\
+ \
+ inline comp##CDbgTrace::comp##CDbgTrace(\
+ unsigned long ulFlags,\
+ char const DEBFAR * const pszName)\
+ : _ulFlags(ulFlags), _pszName(pszName)\
+ {\
+ comp##InlineDebugOut(_ulFlags, "Entering %s\n", _pszName);\
+ }\
+ \
+ inline comp##CDbgTrace::~comp##CDbgTrace()\
+ {\
+ comp##InlineDebugOut(_ulFlags, "Exiting %s\n", _pszName);\
+ }
+
+# else // ! __cplusplus
+
+# define DECLARE_DEBUG(comp) \
+ extern EXTRNC unsigned long comp##InfoLevel; \
+ extern EXTRNC char *comp##InfoLevelString; \
+ _inline void \
+ comp##InlineDebugOut(unsigned long fDebugMask, char const DEBFAR *pszfmt, ...) \
+ { \
+ if (comp##InfoLevel & fDebugMask) \
+ { \
+ va_list va; \
+ va_start (va, pszfmt); \
+ vdprintf(fDebugMask, comp##InfoLevelString, pszfmt, va);\
+ va_end(va); \
+ } \
+ }
+
+# endif // ! __cplusplus
+
+#else // DBG == 0
+
+//
+// NO DEBUG -- NO DEBUG -- NO DEBUG -- NO DEBUG -- NO DEBUG
+//
+
+# define Win4Assert(x)
+# define Assert(x) // OBSOLETE!
+# define Verify(x) (x) // OBSOLETE!
+
+# define MAKE_CINFOLEVEL(comp)
+# define DECLARE_GROUP(Name)
+# define DEFINE_GROUP(Name)
+# define DEFINE_BREAKPOINT(Name)
+# define DECLARE_BREAKPOINT(Name,hGroup,fEnabled)
+# define TEST_BREAKPOINT(x)
+# define TEST_BREAKPOINTHR(x,hr)
+# define DECLARE_DEBUGVALUE(Name,hGroup,Value)
+# define DECLARE_DEBUGVALUEEX(Name,Title,hGroup,Value)
+# define DEFINE_DEBUGVALUE(Name)
+# define DECLARE_DEBUG(comp)
+# define DECLARE_INFOLEVEL(comp)
+
+#endif // DBG == 0
+
+
+//
+// The following section adds the API's used for the performance snapshots
+//
+
+
+#if PERFSNAP == 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void _stdcall InitPerformanceMetering(char const DEBFAR * const);
+void _stdcall Perfon(char const DEBFAR * const);
+void _stdcall Perfsnap(char const DEBFAR * const, int const);
+void _stdcall Perfcomment(char const DEBFAR * const s);
+void _stdcall Perfdelta(char const DEBFAR * const, int const);
+void _stdcall Perfoff(char const DEBFAR * const);
+void _stdcall EndPerformanceMetering(char const DEBFAR * const);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define PSNAPINIT(pszFileKey) InitPerformanceMetering(pszFileKey)
+#define PSNAPEND() EndPerformanceMetering(NULL)
+#define PSNAP(s) Perfsnap(s,0)
+#define PSNAPL(s,l) Perfsnap(s,l)
+#define PSNAPC(s) Perfcomment(s)
+#define PSNAPDELTA(s) Perfdelta(s,0)
+#define PSNAPDELTAL(s,l) Perfdelta(s,l)
+#define PSNAPON(s) Perfon(s)
+#define PSNAPOFF(s) Perfoff(s)
+
+#else // PERFSNAP == 1
+
+#define InitPerformanceMetering(x)
+#define Perfon(x)
+#define Perfsnap(x,y)
+#define Perfcomment(x)
+#define Perfdelta(x,y)
+#define Perfoff(x)
+#define EndPerformanceMetering(x)
+
+#define PSNAPINIT(pszFileKey)
+#define PSNAPEND()
+#define PSNAP(s)
+#define PSNAPL(s,l)
+#define PSNAPC(s)
+#define PSNAPDELTA(s)
+#define PSNAPDELTAL(s,l)
+#define PSNAPON(s)
+#define PSNAPOFF(s)
+
+#endif
+
+
+//
+// If the sampling profiler is to be used, then here are its includes
+//
+//
+
+#ifdef WIN32
+#if (DBG == 1) || (RTLPROFILE == 1)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+void _stdcall InitSamplingProfiler(void);
+void _stdcall EndSamplingProfiler(void);
+#ifdef __cplusplus
+}
+#endif
+
+
+#define INITSAMPLINGPROFILER InitSamplingProfiler()
+#define ENDSAMPLINGPROFILER EndSamplingProfiler()
+
+#else // RTLPROFILE == 1
+
+#define INITSAMPLINGPROFILER
+#define ENDSAMPLINGPROFILER
+
+#endif // RTLPROFILE == 1
+#endif // WIN32
+
+#endif // __DEBNOT_H__
diff --git a/private/ole32/olethunk/ole16/inc/debug.h b/private/ole32/olethunk/ole16/inc/debug.h
new file mode 100644
index 000000000..64d155256
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/debug.h
@@ -0,0 +1,306 @@
+/*
+ * DEBUG code - Contains declarations and macros for include debug support;
+ * Contains null definitions when !_DEBUG
+ */
+
+#ifndef _DEBUG_H_
+#define _DEBUG_H_
+
+#ifndef RC_INVOKED
+#ifdef _DEBUG
+#define DBGSTATE " Debug is on"
+#else
+#define DBGSTATE " Debug is off"
+#endif
+#endif /* RC_INVOKED */
+
+#include <ole2dbg.h>
+
+//these are bogus APIs (they do nothing)
+STDAPI_(BOOL) ValidateAllObjects( BOOL fSuspicious );
+STDAPI_(void) DumpAllObjects( void );
+
+#ifdef _DEBUG
+BOOL InstallHooks(void);
+BOOL UnInstallHooks(void);
+
+#undef ASSERTDATA
+#ifdef _MAC
+#ifdef __cplusplus
+extern "C" {
+#endif
+void OutputDebugString(const char *);
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+#define ASSERTDATA static char _szAssertFile[]= __FILE__;
+
+#undef Assert
+// MAC compiler barfs on '(void)0'.
+#ifdef _MAC
+#define Assert(a) { if (!(a)) FnAssert(#a, NULL, _szAssertFile, __LINE__); }
+#undef AssertSz
+#define AssertSz(a, b) { if (!(a)) FnAssert(#a, b, _szAssertFile, __LINE__); }
+#else
+#undef AssertSz
+#define AssertSz(a,b) ((a) ? NOERROR : FnAssert(#a, b, _szAssertFile, __LINE__))
+#endif
+#undef Verify
+#define Verify(a) Assert(a)
+#undef Puts
+#define Puts(s) OutputDebugString(s)
+
+#define ASSERT(cond, msg)
+
+#else // !_DEBUG
+
+#define ASSERTDATA
+#define Assert(a)
+#define AssertSz(a, b)
+#define Verify(a) (a)
+#define ASSERT(cond, msg)
+#define Puts(s)
+
+#endif // _DEBUG
+
+#ifdef __cplusplus
+
+interface IDebugStream;
+
+/*
+ * Class CBool wraps boolean values in such a way that they are
+ * readily distinguishable fron integers by the compiler so we can
+ * overload the stream << operator.
+ */
+
+class FAR CBool
+{
+ BOOL value;
+public:
+ CBool (BOOL& b) {value = b;}
+ operator BOOL( void ) { return value; }
+};
+
+
+/*
+ * Class CHwnd wraps HWND values in such a way that they are
+ * readily distinguishable from UINTS by the compiler so we can
+ * overload the stream << operator
+ */
+
+class FAR CHwnd
+{
+ HWND m_hwnd;
+ public:
+ CHwnd (HWND hwnd) {m_hwnd = hwnd; }
+ operator HWND( void ) {return m_hwnd;}
+};
+
+/*
+ * Class CAtom wraps ATOM values in such a way that they are
+ * readily distinguishable from UINTS by the compiler so we can
+ * overload the stream << operator
+ */
+
+class FAR CAtom
+{
+ ATOM m_atom;
+ public:
+ CAtom (ATOM atom) {m_atom = atom; }
+ operator ATOM( void ) {return m_atom; }
+};
+
+/*
+ * IDebugStream is a stream to be used for debug output. One
+ * implementation uses the OutputDebugString function of Windows.
+ *
+ * The style is modeled on that of AT&T streams, and so uses
+ * overloaded operators. You can write to a stream in the
+ * following ways:
+ *
+ * *pdbstm << pUnk; // calls the IDebug::Dump function to
+ * display the object, if IDebug is supported.
+ * int n;
+ * *pdbstm << n; // writes n in decimal
+ *
+ * LPSTR sz;
+ * *pdbstm << sz; // writes a string
+ *
+ * CBool b(TRUE);
+ * *pdbstm << b; // writes True or False
+ *
+ * void FAR * pv;
+ * *pdbstm << pv; // writes the address pv in hex
+ *
+ * char ch;
+ * *pdbstm << ch; // writes the character
+ *
+ * ATOM atom;
+ * *pdbstm << CAtom(atom); // writes the string extracted from the atom
+ *
+ * HWND hwnd;
+ * *pdbstm << CHwnd(hwnd); // writes the info about a window handle
+ *
+ * These can be chained together, as such (somewhat artificial
+ * example):
+ *
+ * REFCLSID rclsid;
+ * pUnk->GetClass(&rclsid);
+ * *pdbstm << rclsid << " at " << (void FAR *)pUnk <<':' << pUnk;
+ *
+ * This produces something like:
+ *
+ * CFoo at A7360008: <description of object>
+ *
+ * The other useful feature is the Indent and UnIndent functions
+ * which allow an object to print some information, indent, print
+ * the info on its member objects, and unindent. This gives
+ * nicely formatted output.
+ *
+ * WARNING: do not (while implementing Dump) write
+ *
+ * *pdbstm << pUnkOuter
+ *
+ * since this will do a QueryInterface for IDebug, and start
+ * recursing! It is acceptable to write
+ *
+ * *pdbstm << (VOID FAR *)pUnkOuter
+ *
+ * as this will simply write the address of pUnkOuter.
+ *
+ */
+
+
+interface IDebugStream : public IUnknown
+{
+ STDMETHOD_(IDebugStream&, operator << ) ( IUnknown FAR * pDebug ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( REFCLSID rclsid ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( int n ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( long l ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( ULONG l ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( LPSTR sz ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( char ch ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( void FAR * pv ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( CBool b ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( CHwnd hwnd ) = 0;
+ STDMETHOD_(IDebugStream&, operator << ) ( CAtom atom ) = 0;
+ STDMETHOD_(IDebugStream&, Tab )( void ) = 0;
+ STDMETHOD_(IDebugStream&, Indent )( void ) = 0;
+ STDMETHOD_(IDebugStream&, UnIndent )( void ) = 0;
+ STDMETHOD_(IDebugStream&, Return )( void ) = 0;
+ STDMETHOD_(IDebugStream&, LF )( void ) = 0;
+};
+
+STDAPI_(IDebugStream FAR*) MakeDebugStream( short margin=70, short tabsize=4, BOOL fHeader=1);
+
+
+interface IDebug
+{
+ STDMETHOD_(void, Dump )( IDebugStream FAR * pdbstm ) = 0;
+ STDMETHOD_(BOOL, IsValid )( BOOL fSuspicious = FALSE ) = 0;
+
+#ifdef NEVER
+ __export IDebug(void);
+ __export ~IDebug(void);
+private:
+
+#if _DEBUG
+ IDebug FAR * pIDPrev;
+ IDebug FAR * pIDNext;
+
+ friend void STDAPICALLTYPE DumpAllObjects( void );
+ friend BOOL STDAPICALLTYPE ValidateAllObjects( BOOL fSuspicious );
+#endif
+#endif
+};
+
+
+#ifdef _MAC
+typedef short HFILE;
+#endif
+
+
+/*************************************************************************
+** The following functions can be used to log debug messages to a file
+** and simutaneously write them to the dbwin debug window.
+** The CDebugStream implementation automatically writes to a debug
+** log file called "debug.log" in the current working directory.
+** NOTE: The functions are only intended for C programmers. C++
+** programmers should use the "MakeDebugStream" instead.
+*************************************************************************/
+
+// Open a log file.
+STDAPI_(HFILE) DbgLogOpen(LPSTR lpszFile, LPSTR lpszMode);
+
+// Close the log file.
+STDAPI_(void) DbgLogClose(HFILE fh);
+
+// Write to debug log and debug window (used with cvw.exe or dbwin.exe).
+STDAPI_(void) DbgLogOutputDebugString(HFILE fh, LPSTR lpsz);
+
+// Write to debug log only.
+STDAPI_(void) DbgLogWrite(HFILE fh, LPSTR lpsz);
+
+// Write the current Date and Time to the log file.
+STDAPI_(void) DbgLogTimeStamp(HFILE fh, LPSTR lpsz);
+
+// Write a banner separater to the log to separate sections.
+STDAPI_(void) DbgLogWriteBanner(HFILE fh, LPSTR lpsz);
+
+
+
+
+/*
+ * STDDEBDECL macro - helper for debug declaration
+ *
+ */
+
+#ifdef _DEBUG
+
+ #ifdef _MAC
+
+ //#define STDDEBDECL(cclassname,classname)
+
+ //#if 0
+ #define STDDEBDECL(cclassname,classname) NESTED_CLASS(cclassname, CDebug):IDebug { public: \
+ NC1(cclassname,CDebug)( cclassname FAR * p##classname ) { m_p##classname = p##classname;} \
+ ~##NC1(cclassname,CDebug)(void){} \
+ STDMETHOD_(void, Dump)(THIS_ IDebugStream FAR * pdbstm ); \
+ STDMETHOD_(BOOL, IsValid)(THIS_ BOOL fSuspicious ); \
+ private: cclassname FAR* m_p##classname; }; \
+ DECLARE_NC2(cclassname, CDebug) \
+ NC(cclassname, CDebug) m_Debug;
+ //#endif
+
+ #else // _MAC
+
+ #define STDDEBDECL(ignore, classname ) implement CDebug:public IDebug { public: \
+ CDebug( C##classname FAR * p##classname ) { m_p##classname = p##classname;} \
+ ~CDebug(void) {} \
+ STDMETHOD_(void, Dump)(IDebugStream FAR * pdbstm ); \
+ STDMETHOD_(BOOL, IsValid)(BOOL fSuspicious ); \
+ private: C##classname FAR* m_p##classname; }; \
+ DECLARE_NC(C##classname, CDebug) \
+ CDebug m_Debug;
+ #endif
+
+ //#ifdef _MAC
+ //#define CONSTRUCT_DEBUG
+ //#else
+ #define CONSTRUCT_DEBUG m_Debug(this),
+ //#endif
+
+#else // _DEBUG
+
+// no debugging
+#define STDDEBDECL(cclassname,classname)
+#define CONSTRUCT_DEBUG
+
+#endif // _DEBUG
+
+#endif __cplusplus
+
+#endif !_DEBUG_H_
+
diff --git a/private/ole32/olethunk/ole16/inc/dlgs.h b/private/ole32/olethunk/ole16/inc/dlgs.h
new file mode 100644
index 000000000..048dfef18
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/dlgs.h
@@ -0,0 +1,201 @@
+#ifndef _DLGSH_INCLUDED_
+#define _DLGSH_INCLUDED_
+
+/*---------------------------------------------------------------------------*/
+/* Dlgs.h : UI dialog header */
+/* */
+/* Copyright (c) Microsoft Corporation, 1990-1993 */
+/*---------------------------------------------------------------------------*/
+
+/*----Constants--------------------------------------------------------------*/
+#define ctlFirst 0x0400
+#define ctlLast 0x04ff
+ /* Push buttons */
+#define psh1 0x0400
+#define psh2 0x0401
+#define psh3 0x0402
+#define psh4 0x0403
+#define psh5 0x0404
+#define psh6 0x0405
+#define psh7 0x0406
+#define psh8 0x0407
+#define psh9 0x0408
+#define psh10 0x0409
+#define psh11 0x040a
+#define psh12 0x040b
+#define psh13 0x040c
+#define psh14 0x040d
+#define psh15 0x040e
+#define pshHelp psh15
+#define psh16 0x040f
+ /* Checkboxes */
+#define chx1 0x0410
+#define chx2 0x0411
+#define chx3 0x0412
+#define chx4 0x0413
+#define chx5 0x0414
+#define chx6 0x0415
+#define chx7 0x0416
+#define chx8 0x0417
+#define chx9 0x0418
+#define chx10 0x0419
+#define chx11 0x041a
+#define chx12 0x041b
+#define chx13 0x041c
+#define chx14 0x041d
+#define chx15 0x041e
+#define chx16 0x041d
+ /* Radio buttons */
+#define rad1 0x0420
+#define rad2 0x0421
+#define rad3 0x0422
+#define rad4 0x0423
+#define rad5 0x0424
+#define rad6 0x0425
+#define rad7 0x0426
+#define rad8 0x0427
+#define rad9 0x0428
+#define rad10 0x0429
+#define rad11 0x042a
+#define rad12 0x042b
+#define rad13 0x042c
+#define rad14 0x042d
+#define rad15 0x042e
+#define rad16 0x042f
+ /* Groups, frames, rectangles, and icons */
+#define grp1 0x0430
+#define grp2 0x0431
+#define grp3 0x0432
+#define grp4 0x0433
+#define frm1 0x0434
+#define frm2 0x0435
+#define frm3 0x0436
+#define frm4 0x0437
+#define rct1 0x0438
+#define rct2 0x0439
+#define rct3 0x043a
+#define rct4 0x043b
+#define ico1 0x043c
+#define ico2 0x043d
+#define ico3 0x043e
+#define ico4 0x043f
+ /* Static text */
+#define stc1 0x0440
+#define stc2 0x0441
+#define stc3 0x0442
+#define stc4 0x0443
+#define stc5 0x0444
+#define stc6 0x0445
+#define stc7 0x0446
+#define stc8 0x0447
+#define stc9 0x0448
+#define stc10 0x0449
+#define stc11 0x044a
+#define stc12 0x044b
+#define stc13 0x044c
+#define stc14 0x044d
+#define stc15 0x044e
+#define stc16 0x044f
+#define stc17 0x0450
+#define stc18 0x0451
+#define stc19 0x0452
+#define stc20 0x0453
+#define stc21 0x0454
+#define stc22 0x0455
+#define stc23 0x0456
+#define stc24 0x0457
+#define stc25 0x0458
+#define stc26 0x0459
+#define stc27 0x045a
+#define stc28 0x045b
+#define stc29 0x045c
+#define stc30 0x045d
+#define stc31 0x045e
+#define stc32 0x045f
+ /* Listboxes */
+#define lst1 0x0460
+#define lst2 0x0461
+#define lst3 0x0462
+#define lst4 0x0463
+#define lst5 0x0464
+#define lst6 0x0465
+#define lst7 0x0466
+#define lst8 0x0467
+#define lst9 0x0468
+#define lst10 0x0469
+#define lst11 0x046a
+#define lst12 0x046b
+#define lst13 0x046c
+#define lst14 0x046d
+#define lst15 0x046e
+#define lst16 0x046f
+ /* Combo boxes */
+#define cmb1 0x0470
+#define cmb2 0x0471
+#define cmb3 0x0472
+#define cmb4 0x0473
+#define cmb5 0x0474
+#define cmb6 0x0475
+#define cmb7 0x0476
+#define cmb8 0x0477
+#define cmb9 0x0478
+#define cmb10 0x0479
+#define cmb11 0x047a
+#define cmb12 0x047b
+#define cmb13 0x047c
+#define cmb14 0x047d
+#define cmb15 0x047e
+#define cmb16 0x047f
+ /* Edit controls */
+#define edt1 0x0480
+#define edt2 0x0481
+#define edt3 0x0482
+#define edt4 0x0483
+#define edt5 0x0484
+#define edt6 0x0485
+#define edt7 0x0486
+#define edt8 0x0487
+#define edt9 0x0488
+#define edt10 0x0489
+#define edt11 0x048a
+#define edt12 0x048b
+#define edt13 0x048c
+#define edt14 0x048d
+#define edt15 0x048e
+#define edt16 0x048f
+ /* Scroll bars */
+#define scr1 0x0490
+#define scr2 0x0491
+#define scr3 0x0492
+#define scr4 0x0493
+#define scr5 0x0494
+#define scr6 0x0495
+#define scr7 0x0496
+#define scr8 0x0497
+
+/* These dialog resource ordinals really start at 0x0600, but the
+ * RC Compiler can't handle hex for resource IDs, hence the decimal.
+ * 27 March 1991 clarkc
+ */
+#define FILEOPENORD 1536
+#define MULTIFILEOPENORD 1537
+#define PRINTDLGORD 1538
+#define PRNSETUPDLGORD 1539
+#define FINDDLGORD 1540
+#define REPLACEDLGORD 1541
+#define FONTDLGORD 1542
+#define FORMATDLGORD31 1543
+#define FORMATDLGORD30 1544
+
+/*----Types------------------------------------------------------------------*/
+typedef struct tagCRGB
+ {
+ BYTE bRed;
+ BYTE bGreen;
+ BYTE bBlue;
+ BYTE bExtra;
+ }
+CRGB; /* RGB Color */
+
+
+#endif // _DLGSH_INCLUDED_
diff --git a/private/ole32/olethunk/ole16/inc/dos.h b/private/ole32/olethunk/ole16/inc/dos.h
new file mode 100644
index 000000000..ac7d26535
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/dos.h
@@ -0,0 +1,330 @@
+/***
+*dos.h - definitions for MS-DOS interface routines
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Defines the structs and unions used for the direct DOS interface
+* routines; includes macros to access the segment and offset
+* values of far pointers, so that they may be used by the routines; and
+* provides function prototypes for direct DOS interface functions.
+*
+****/
+
+#ifndef _INC_DOS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (_MSC_VER <= 600)
+#define __cdecl _cdecl
+#define __far _far
+#define __interrupt _interrupt
+#define __near _near
+#endif
+
+#ifndef _REGS_DEFINED
+
+/* word registers */
+
+struct _WORDREGS {
+ unsigned int ax;
+ unsigned int bx;
+ unsigned int cx;
+ unsigned int dx;
+ unsigned int si;
+ unsigned int di;
+ unsigned int cflag;
+ };
+
+/* byte registers */
+
+struct _BYTEREGS {
+ unsigned char al, ah;
+ unsigned char bl, bh;
+ unsigned char cl, ch;
+ unsigned char dl, dh;
+ };
+
+/* general purpose registers union -
+ * overlays the corresponding word and byte registers.
+ */
+
+union _REGS {
+ struct _WORDREGS x;
+ struct _BYTEREGS h;
+ };
+
+/* segment registers */
+
+struct _SREGS {
+ unsigned int es;
+ unsigned int cs;
+ unsigned int ss;
+ unsigned int ds;
+ };
+
+#ifndef __STDC__
+/* Non-ANSI names for compatibility */
+
+struct WORDREGS {
+ unsigned int ax;
+ unsigned int bx;
+ unsigned int cx;
+ unsigned int dx;
+ unsigned int si;
+ unsigned int di;
+ unsigned int cflag;
+ };
+
+struct BYTEREGS {
+ unsigned char al, ah;
+ unsigned char bl, bh;
+ unsigned char cl, ch;
+ unsigned char dl, dh;
+ };
+
+union REGS {
+ struct WORDREGS x;
+ struct BYTEREGS h;
+ };
+
+struct SREGS {
+ unsigned int es;
+ unsigned int cs;
+ unsigned int ss;
+ unsigned int ds;
+ };
+
+#endif
+
+#define _REGS_DEFINED
+#endif
+
+
+/* dosexterror structure */
+
+#ifndef _DOSERROR_DEFINED
+#pragma pack(2)
+
+struct _DOSERROR {
+ int exterror;
+ char errclass;
+ char action;
+ char locus;
+ };
+
+#if ((!defined (__STDC__)) && (!defined (__cplusplus)))
+/* Non-ANSI name for compatibility */
+struct DOSERROR {
+ int exterror;
+ char class;
+ char action;
+ char locus;
+ };
+#endif
+
+#pragma pack()
+#define _DOSERROR_DEFINED
+#endif
+
+
+/* _dos_findfirst structure */
+
+#ifndef _FIND_T_DEFINED
+#pragma pack(2)
+
+struct _find_t {
+ char reserved[21];
+ char attrib;
+ unsigned wr_time;
+ unsigned wr_date;
+ long size;
+ char name[13];
+ };
+
+#ifndef __STDC__
+/* Non-ANSI name for compatibility */
+#define find_t _find_t
+#endif
+
+#pragma pack()
+#define _FIND_T_DEFINED
+#endif
+
+
+/* _dos_getdate/_dossetdate and _dos_gettime/_dos_settime structures */
+
+#ifndef _DATETIME_T_DEFINED
+#pragma pack(2)
+
+struct _dosdate_t {
+ unsigned char day; /* 1-31 */
+ unsigned char month; /* 1-12 */
+ unsigned int year; /* 1980-2099 */
+ unsigned char dayofweek; /* 0-6, 0=Sunday */
+ };
+
+struct _dostime_t {
+ unsigned char hour; /* 0-23 */
+ unsigned char minute; /* 0-59 */
+ unsigned char second; /* 0-59 */
+ unsigned char hsecond; /* 0-99 */
+ };
+
+#ifndef __STDC__
+/* Non-ANSI names for compatibility */
+#define dosdate_t _dosdate_t
+#define dostime_t _dostime_t
+#endif
+
+#pragma pack()
+#define _DATETIME_T_DEFINED
+#endif
+
+
+/* _dos_getdiskfree structure */
+
+#ifndef _DISKFREE_T_DEFINED
+
+struct _diskfree_t {
+ unsigned total_clusters;
+ unsigned avail_clusters;
+ unsigned sectors_per_cluster;
+ unsigned bytes_per_sector;
+ };
+
+#ifndef __STDC__
+/* Non-ANSI name for compatibility */
+#define diskfree_t _diskfree_t
+#endif
+
+#define _DISKFREE_T_DEFINED
+#endif
+
+
+/* manifest constants for _hardresume result parameter */
+
+#define _HARDERR_IGNORE 0 /* Ignore the error */
+#define _HARDERR_RETRY 1 /* Retry the operation */
+#define _HARDERR_ABORT 2 /* Abort program issuing Interrupt 23h */
+#define _HARDERR_FAIL 3 /* Fail the system call in progress */
+ /* _HARDERR_FAIL is not supported on DOS 2.x */
+
+/* File attribute constants */
+
+#define _A_NORMAL 0x00 /* Normal file - No read/write restrictions */
+#define _A_RDONLY 0x01 /* Read only file */
+#define _A_HIDDEN 0x02 /* Hidden file */
+#define _A_SYSTEM 0x04 /* System file */
+#define _A_VOLID 0x08 /* Volume ID file */
+#define _A_SUBDIR 0x10 /* Subdirectory */
+#define _A_ARCH 0x20 /* Archive file */
+
+/* macros to break C "far" pointers into their segment and offset components
+ */
+
+#define _FP_SEG(fp) (*((unsigned __far *)&(fp)+1))
+#define _FP_OFF(fp) (*((unsigned __far *)&(fp)))
+
+/* macro to construct a far pointer from segment and offset values
+ */
+
+#define _MK_FP(seg, offset) (void __far *)(((unsigned long)seg << 16) \
+ + (unsigned long)(unsigned)offset)
+
+/* external variable declarations */
+
+extern unsigned int __near __cdecl _osversion;
+
+
+/* function prototypes */
+
+#ifndef _MT
+int __cdecl _bdos(int, unsigned int, unsigned int);
+#ifndef _WINDOWS
+void __cdecl _chain_intr(void (__cdecl __interrupt __far *)());
+#endif
+void __cdecl _disable(void);
+#ifndef _WINDOWS
+unsigned __cdecl _dos_allocmem(unsigned, unsigned *);
+#endif
+unsigned __cdecl _dos_close(int);
+unsigned __cdecl _dos_commit(int);
+unsigned __cdecl _dos_creat(const char *, unsigned, int *);
+unsigned __cdecl _dos_creatnew(const char *, unsigned, int *);
+unsigned __cdecl _dos_findfirst(const char *, unsigned, struct _find_t *);
+unsigned __cdecl _dos_findnext(struct _find_t *);
+#ifndef _WINDOWS
+unsigned __cdecl _dos_freemem(unsigned);
+#endif
+void __cdecl _dos_getdate(struct _dosdate_t *);
+void __cdecl _dos_getdrive(unsigned *);
+unsigned __cdecl _dos_getdiskfree(unsigned, struct _diskfree_t *);
+unsigned __cdecl _dos_getfileattr(const char *, unsigned *);
+unsigned __cdecl _dos_getftime(int, unsigned *, unsigned *);
+void __cdecl _dos_gettime(struct _dostime_t *);
+void (__cdecl __interrupt __far * __cdecl _dos_getvect(unsigned))();
+#ifndef _WINDOWS
+void __cdecl _dos_keep(unsigned, unsigned);
+#endif
+unsigned __cdecl _dos_lock(int, int, unsigned long, unsigned long);
+unsigned __cdecl _dos_open(const char *, unsigned, int *);
+unsigned __cdecl _dos_read(int, void __far *, unsigned, unsigned *);
+unsigned long __cdecl _dos_seek(int, unsigned long, int);
+#ifndef _WINDOWS
+unsigned __cdecl _dos_setblock(unsigned, unsigned, unsigned *);
+#endif
+unsigned __cdecl _dos_setdate(struct _dosdate_t *);
+void __cdecl _dos_setdrive(unsigned, unsigned *);
+unsigned __cdecl _dos_setfileattr(const char *, unsigned);
+unsigned __cdecl _dos_setftime(int, unsigned, unsigned);
+unsigned __cdecl _dos_settime(struct _dostime_t *);
+#ifndef _WINDOWS
+void __cdecl _dos_setvect(unsigned, void (__cdecl __interrupt __far *)());
+#endif
+unsigned __cdecl _dos_write(int, const void __far *, unsigned, unsigned *);
+int __cdecl _dosexterr(struct _DOSERROR *);
+void __cdecl _enable(void);
+#ifndef _WINDOWS
+void __cdecl _harderr(void (__far __cdecl *)(unsigned, unsigned,
+ unsigned __far *));
+void __cdecl _hardresume(int);
+void __cdecl _hardretn(int);
+#endif
+int __cdecl _intdos(union _REGS *, union _REGS *);
+int __cdecl _intdosx(union _REGS *, union _REGS *, struct _SREGS *);
+int __cdecl _int86(int, union _REGS *, union _REGS *);
+int __cdecl _int86x(int, union _REGS *, union _REGS *, struct _SREGS *);
+#endif
+
+void __cdecl _segread(struct _SREGS *);
+
+#ifndef __STDC__
+/* Non-ANSI names for compatibility */
+
+#define FP_SEG _FP_SEG
+#define FP_OFF _FP_OFF
+#define MK_FP _MK_FP
+
+#ifndef _MT
+int __cdecl bdos(int, unsigned int, unsigned int);
+int __cdecl intdos(union REGS *, union REGS *);
+int __cdecl intdosx(union REGS *, union REGS *, struct SREGS *);
+int __cdecl int86(int, union REGS *, union REGS *);
+int __cdecl int86x(int, union REGS *, union REGS *, struct SREGS *);
+#ifndef __cplusplus
+int __cdecl dosexterr(struct DOSERROR *);
+#endif
+#endif
+void __cdecl segread(struct SREGS *);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_DOS
+#endif
diff --git a/private/ole32/olethunk/ole16/inc/dvobj.h b/private/ole32/olethunk/ole16/inc/dvobj.h
new file mode 100644
index 000000000..9c3dac58f
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/dvobj.h
@@ -0,0 +1,480 @@
+/*****************************************************************************\
+* *
+* dvobj.h - Data/View object definitions *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+#if !defined( _DVOBJ_H_ )
+#define _DVOBJ_H_
+
+/****** DV value types ******************************************************/
+
+// forward type declarations
+#if defined(__cplusplus)
+interface IStorage;
+interface IStream;
+interface IAdviseSink;
+interface IMoniker;
+#else
+typedef interface IStorage IStorage;
+typedef interface IStream IStream;
+typedef interface IAdviseSink IAdviseSink;
+typedef interface IMoniker IMoniker;
+#endif
+
+typedef IStorage FAR* LPSTORAGE;
+typedef IStream FAR* LPSTREAM;
+typedef IAdviseSink FAR* LPADVISESINK;
+typedef IMoniker FAR* LPMONIKER;
+
+
+#if !defined(_MAC)
+typedef WORD CLIPFORMAT;
+#else
+typedef unsigned long CLIPFORMAT; // ResType
+#endif
+typedef CLIPFORMAT FAR* LPCLIPFORMAT;
+
+
+// Data/View aspect; specifies the desired aspect of the object when
+// drawing or getting data.
+typedef enum tagDVASPECT
+{
+ DVASPECT_CONTENT = 1,
+ DVASPECT_THUMBNAIL = 2,
+ DVASPECT_ICON = 4,
+ DVASPECT_DOCPRINT = 8
+} DVASPECT;
+
+
+// Data/View target device; determines the device for drawing or gettting data
+typedef struct FARSTRUCT tagDVTARGETDEVICE
+{
+ DWORD tdSize;
+ WORD tdDriverNameOffset;
+ WORD tdDeviceNameOffset;
+ WORD tdPortNameOffset;
+ WORD tdExtDevmodeOffset;
+ BYTE tdData[1];
+} DVTARGETDEVICE;
+
+
+// Format, etc.; completely specifices the kind of data desired, including tymed
+typedef struct FARSTRUCT tagFORMATETC
+{
+ CLIPFORMAT cfFormat;
+ DVTARGETDEVICE FAR* ptd;
+ DWORD dwAspect;
+ LONG lindex;
+ DWORD tymed;
+} FORMATETC, FAR* LPFORMATETC;
+
+
+// TYpes of storage MEDiums; determines how data is stored or passed around
+typedef enum tagTYMED
+{
+ TYMED_HGLOBAL = 1,
+ TYMED_FILE = 2,
+ TYMED_ISTREAM = 4,
+ TYMED_ISTORAGE = 8,
+ TYMED_GDI = 16,
+ TYMED_MFPICT = 32,
+ TYMED_NULL = 0
+} TYMED;
+
+
+// DATA format DIRection
+typedef enum tagDATADIR
+{
+ DATADIR_GET = 1,
+ DATADIR_SET = 2,
+} DATADIR;
+
+
+// SToraGe MEDIUM; a block of data on a particular medium
+typedef struct FARSTRUCT tagSTGMEDIUM
+{
+ DWORD tymed;
+ union
+ {
+ HANDLE hGlobal;
+ LPSTR lpszFileName;
+ IStream FAR* pstm;
+ IStorage FAR* pstg;
+ }
+#ifdef NONAMELESSUNION
+ u // add a tag when name less unions not supported
+#endif
+ ;
+ IUnknown FAR* pUnkForRelease;
+} STGMEDIUM, FAR* LPSTGMEDIUM;
+
+
+// Advise Flags
+typedef enum tagADVF
+{
+ ADVF_NODATA = 1,
+ ADVF_PRIMEFIRST = 2,
+ ADVF_ONLYONCE = 4,
+ ADVF_DATAONSTOP = 64,
+ ADVFCACHE_NOHANDLER = 8,
+ ADVFCACHE_FORCEBUILTIN = 16,
+ ADVFCACHE_ONSAVE = 32
+} ADVF;
+
+
+// Stats for data; used by several enumerations and by at least one
+// implementation of IDataAdviseHolder; if a field is not used, it
+// will be NULL.
+typedef struct FARSTRUCT tagSTATDATA
+{ // field used by:
+ FORMATETC formatetc; // EnumAdvise, EnumData (cache), EnumFormats
+ DWORD advf; // EnumAdvise, EnumData (cache)
+ IAdviseSink FAR* pAdvSink; // EnumAdvise
+ DWORD dwConnection; // EnumAdvise
+} STATDATA;
+
+typedef STATDATA FAR* LPSTATDATA;
+
+
+
+/****** DV Interfaces ***************************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IEnumFORMATETC
+
+DECLARE_INTERFACE_(IEnumFORMATETC, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumFORMATETC methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, FORMATETC FAR * rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumFORMATETC FAR* FAR* ppenum) PURE;
+};
+typedef IEnumFORMATETC FAR* LPENUMFORMATETC;
+
+
+#undef INTERFACE
+#define INTERFACE IEnumSTATDATA
+
+DECLARE_INTERFACE_(IEnumSTATDATA, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG, Release) (THIS) PURE;
+
+ // *** IEnumSTATDATA methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, STATDATA FAR * rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumSTATDATA FAR* FAR* ppenum) PURE;
+};
+typedef IEnumSTATDATA FAR* LPENUMSTATDATA;
+
+
+
+#undef INTERFACE
+#define INTERFACE IDataObject
+
+#define DATA_E_FORMATETC DV_E_FORMATETC
+#define DATA_S_SAMEFORMATETC (DATA_S_FIRST + 0)
+
+DECLARE_INTERFACE_(IDataObject, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG, Release) (THIS) PURE;
+
+ // *** IDataObject methods ***
+ STDMETHOD(GetData) (THIS_ LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium ) PURE;
+ STDMETHOD(GetDataHere) (THIS_ LPFORMATETC pformatetc,
+ LPSTGMEDIUM pmedium ) PURE;
+ STDMETHOD(QueryGetData) (THIS_ LPFORMATETC pformatetc ) PURE;
+ STDMETHOD(GetCanonicalFormatEtc) (THIS_ LPFORMATETC pformatetc,
+ LPFORMATETC pformatetcOut) PURE;
+ STDMETHOD(SetData) (THIS_ LPFORMATETC pformatetc, STGMEDIUM FAR * pmedium,
+ BOOL fRelease) PURE;
+ STDMETHOD(EnumFormatEtc) (THIS_ DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenumFormatEtc) PURE;
+
+ STDMETHOD(DAdvise) (THIS_ FORMATETC FAR* pFormatetc, DWORD advf,
+ LPADVISESINK pAdvSink, DWORD FAR* pdwConnection) PURE;
+ STDMETHOD(DUnadvise) (THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumDAdvise) (THIS_ LPENUMSTATDATA FAR* ppenumAdvise) PURE;
+};
+typedef IDataObject FAR* LPDATAOBJECT;
+
+
+
+#undef INTERFACE
+#define INTERFACE IViewObject
+
+#define VIEW_E_DRAW (VIEW_E_FIRST)
+#define E_DRAW VIEW_E_DRAW
+
+#define VIEW_S_ALREADY_FROZEN (VIEW_S_FIRST)
+
+DECLARE_INTERFACE_(IViewObject, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IViewObject methods ***
+ STDMETHOD(Draw) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev,
+ HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ BOOL (CALLBACK * pfnContinue) (DWORD),
+ DWORD dwContinue) PURE;
+
+ STDMETHOD(GetColorSet) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev,
+ LPLOGPALETTE FAR* ppColorSet) PURE;
+
+ STDMETHOD(Freeze)(THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect,
+ DWORD FAR* pdwFreeze) PURE;
+ STDMETHOD(Unfreeze) (THIS_ DWORD dwFreeze) PURE;
+ STDMETHOD(SetAdvise) (THIS_ DWORD aspects, DWORD advf,
+ LPADVISESINK pAdvSink) PURE;
+ STDMETHOD(GetAdvise) (THIS_ DWORD FAR* pAspects, DWORD FAR* pAdvf,
+ LPADVISESINK FAR* ppAdvSink) PURE;
+};
+typedef IViewObject FAR* LPVIEWOBJECT;
+
+
+#undef INTERFACE
+#define INTERFACE IViewObject2
+
+DECLARE_INTERFACE_(IViewObject2, IViewObject)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IViewObject methods ***
+ STDMETHOD(Draw) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev,
+ HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ BOOL (CALLBACK * pfnContinue) (DWORD),
+ DWORD dwContinue) PURE;
+
+ STDMETHOD(GetColorSet) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev,
+ LPLOGPALETTE FAR* ppColorSet) PURE;
+
+ STDMETHOD(Freeze)(THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect,
+ DWORD FAR* pdwFreeze) PURE;
+ STDMETHOD(Unfreeze) (THIS_ DWORD dwFreeze) PURE;
+ STDMETHOD(SetAdvise) (THIS_ DWORD aspects, DWORD advf,
+ LPADVISESINK pAdvSink) PURE;
+ STDMETHOD(GetAdvise) (THIS_ DWORD FAR* pAspects, DWORD FAR* pAdvf,
+ LPADVISESINK FAR* ppAdvSink) PURE;
+
+ // *** IViewObject2 methods ***
+ STDMETHOD(GetExtent) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ DVTARGETDEVICE FAR * ptd, LPSIZEL lpsizel) PURE;
+
+};
+typedef IViewObject2 FAR* LPVIEWOBJECT2;
+
+
+#undef INTERFACE
+#define INTERFACE IAdviseSink
+
+DECLARE_INTERFACE_(IAdviseSink, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IAdviseSink methods ***
+ STDMETHOD_(void,OnDataChange)(THIS_ FORMATETC FAR* pFormatetc,
+ STGMEDIUM FAR* pStgmed) PURE;
+ STDMETHOD_(void,OnViewChange)(THIS_ DWORD dwAspect, LONG lindex) PURE;
+ STDMETHOD_(void,OnRename)(THIS_ LPMONIKER pmk) PURE;
+ STDMETHOD_(void,OnSave)(THIS) PURE;
+ STDMETHOD_(void,OnClose)(THIS) PURE;
+};
+typedef IAdviseSink FAR* LPADVISESINK;
+
+
+
+#undef INTERFACE
+#define INTERFACE IAdviseSink2
+
+DECLARE_INTERFACE_(IAdviseSink2, IAdviseSink)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IAdviseSink methods ***
+ STDMETHOD_(void,OnDataChange)(THIS_ FORMATETC FAR* pFormatetc,
+ STGMEDIUM FAR* pStgmed) PURE;
+ STDMETHOD_(void,OnViewChange)(THIS_ DWORD dwAspect, LONG lindex) PURE;
+ STDMETHOD_(void,OnRename)(THIS_ LPMONIKER pmk) PURE;
+ STDMETHOD_(void,OnSave)(THIS) PURE;
+ STDMETHOD_(void,OnClose)(THIS) PURE;
+
+ // *** IAdviseSink2 methods ***
+ STDMETHOD_(void,OnLinkSrcChange)(THIS_ LPMONIKER pmk) PURE;
+};
+typedef IAdviseSink2 FAR* LPADVISESINK2;
+
+
+
+#undef INTERFACE
+#define INTERFACE IDataAdviseHolder
+
+DECLARE_INTERFACE_(IDataAdviseHolder, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IDataAdviseHolder methods ***
+ STDMETHOD(Advise)(THIS_ LPDATAOBJECT pDataObject, FORMATETC FAR* pFetc,
+ DWORD advf, LPADVISESINK pAdvise, DWORD FAR* pdwConnection) PURE;
+ STDMETHOD(Unadvise)(THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumAdvise)(THIS_ LPENUMSTATDATA FAR* ppenumAdvise) PURE;
+
+ STDMETHOD(SendOnDataChange)(THIS_ LPDATAOBJECT pDataObject, DWORD dwReserved, DWORD advf) PURE;
+};
+typedef IDataAdviseHolder FAR* LPDATAADVISEHOLDER;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleCache
+
+#define CACHE_E_NOCACHE_UPDATED (CACHE_E_FIRST)
+
+#define CACHE_S_FORMATETC_NOTSUPPORTED (CACHE_S_FIRST)
+#define CACHE_S_SAMECACHE (CACHE_S_FIRST+1)
+#define CACHE_S_SOMECACHES_NOTUPDATED (CACHE_S_FIRST+2)
+
+
+DECLARE_INTERFACE_(IOleCache, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleCache methods ***
+ STDMETHOD(Cache) (THIS_ LPFORMATETC lpFormatetc, DWORD advf, LPDWORD lpdwConnection) PURE;
+ STDMETHOD(Uncache) (THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumCache) (THIS_ LPENUMSTATDATA FAR* ppenumStatData) PURE;
+ STDMETHOD(InitCache) (THIS_ LPDATAOBJECT pDataObject) PURE;
+ STDMETHOD(SetData) (THIS_ LPFORMATETC pformatetc, STGMEDIUM FAR * pmedium,
+ BOOL fRelease) PURE;
+};
+typedef IOleCache FAR* LPOLECACHE;
+
+
+
+// Cache update Flags
+
+#define UPDFCACHE_NODATACACHE 0x00000001
+#define UPDFCACHE_ONSAVECACHE 0x00000002
+#define UPDFCACHE_ONSTOPCACHE 0x00000004
+#define UPDFCACHE_NORMALCACHE 0x00000008
+#define UPDFCACHE_IFBLANK 0x00000010
+#define UPDFCACHE_ONLYIFBLANK 0x80000000
+
+#define UPDFCACHE_IFBLANKORONSAVECACHE (UPDFCACHE_IFBLANK | UPDFCACHE_ONSAVECACHE )
+#define UPDFCACHE_ALL (~UPDFCACHE_ONLYIFBLANK)
+#define UPDFCACHE_ALLBUTNODATACACHE (UPDFCACHE_ALL & ~UPDFCACHE_NODATACACHE)
+
+
+// IOleCache2::DiscardCache options
+typedef enum tagDISCARDCACHE
+{
+ DISCARDCACHE_SAVEIFDIRTY = 0, // Save all dirty cache before discarding
+ DISCARDCACHE_NOSAVE = 1 // Don't save dirty caches before
+ // discarding
+} DISCARDCACHE;
+
+
+#undef INTERFACE
+#define INTERFACE IOleCache2
+
+DECLARE_INTERFACE_(IOleCache2, IOleCache)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG, Release) (THIS) PURE;
+
+ // *** IOleCache methods ***
+ STDMETHOD(Cache) (THIS_ LPFORMATETC lpFormatetc, DWORD advf, LPDWORD lpdwConnection) PURE;
+ STDMETHOD(Uncache) (THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumCache) (THIS_ LPENUMSTATDATA FAR* ppenumStatData) PURE;
+ STDMETHOD(InitCache) (THIS_ LPDATAOBJECT pDataObject) PURE;
+ STDMETHOD(SetData) (THIS_ LPFORMATETC pformatetc, STGMEDIUM FAR * pmedium,
+ BOOL fRelease) PURE;
+
+ // *** IOleCache2 methods ***
+ STDMETHOD(UpdateCache) (THIS_ LPDATAOBJECT pDataObject, DWORD grfUpdf,
+ LPVOID pReserved) PURE;
+ STDMETHOD(DiscardCache) (THIS_ DWORD dwDiscardOptions) PURE;
+
+};
+typedef IOleCache2 FAR* LPOLECACHE2;
+
+
+#undef INTERFACE
+#define INTERFACE IOleCacheControl
+
+DECLARE_INTERFACE_(IOleCacheControl, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG, Release) (THIS) PURE;
+
+ // *** IDataObject methods ***
+ STDMETHOD(OnRun) (THIS_ LPDATAOBJECT pDataObject) PURE;
+ STDMETHOD(OnStop) (THIS) PURE;
+};
+typedef IOleCacheControl FAR* LPOLECACHECONTROL;
+
+
+
+/****** DV APIs ***********************************************************/
+
+
+STDAPI CreateDataAdviseHolder(LPDATAADVISEHOLDER FAR* ppDAHolder);
+
+STDAPI CreateDataCache(LPUNKNOWN pUnkOuter, REFCLSID rclsid,
+ REFIID iid, LPVOID FAR* ppv);
+
+#endif // _DVOBJ_H_
diff --git a/private/ole32/olethunk/ole16/inc/enumfetc.h b/private/ole32/olethunk/ole16/inc/enumfetc.h
new file mode 100644
index 000000000..60b82d151
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/enumfetc.h
@@ -0,0 +1,13 @@
+// This file is now OBSOLETE (include olestd.h instead)
+
+/*************************************************************************
+**
+** OLE 2 Utility Code
+**
+** enumfetc.c
+**
+** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+**
+*************************************************************************/
+
+// Function prototypes moved to olestd.h
diff --git a/private/ole32/olethunk/ole16/inc/etask.hxx b/private/ole32/olethunk/ole16/inc/etask.hxx
new file mode 100644
index 000000000..ed4f8a3fc
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/etask.hxx
@@ -0,0 +1,69 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: etask.hxx
+//
+// Contents: extern definitions from etask.hxx
+//
+// History: 08-Mar-94 BobDay Taken from OLE2INT.H & OLECOLL.H
+//
+//----------------------------------------------------------------------------
+
+#ifdef WIN32
+#define HTASK DWORD // Use Proccess id / Thread id
+#define GetCurrentThread() GetCurrentThreadId()
+#define GetCurrentProcess() GetCurrentProcessId()
+#define GetWindowThread(h) ((HTASK)GetWindowTask(h))
+#else
+#define GetCurrentThread() GetCurrentTask()
+#define GetCurrentProcess() GetCurrentTask()
+#define GetWindowThread(h) GetWindowTask(h)
+#endif
+
+/*
+ * MACROS for Mac/PC core code
+ *
+ * The following macros reduce the proliferation of #ifdefs. They
+ * allow tagging a fragment of code as Mac only, PC only, or with
+ * variants which differ on the PC and the Mac.
+ *
+ * Usage:
+ *
+ *
+ * h = GetHandle();
+ * Mac(DisposeHandle(h));
+ *
+ *
+ * h = GetHandle();
+ * MacWin(h2 = h, CopyHandle(h, h2));
+ *
+ */
+#ifdef _MAC
+#define Mac(x) x
+#define Win(x)
+#define MacWin(x,y) x
+#else
+#define Mac(x)
+#define Win(x) x
+#define MacWin(x,y) y
+#endif
+
+extern CMapHandleEtask NEAR v_mapToEtask;
+
+STDAPI_(BOOL) LookupEtask(HTASK FAR& hTask, Etask FAR& etask);
+STDAPI_(BOOL) SetEtask(HTASK hTask, Etask FAR& etask);
+void ReleaseEtask(HTASK htask, Etask FAR& etask);
+
+#define ETASK_FAKE_INIT 0
+#define ETASK_NO_INIT 0xffffffff
+
+#ifdef _CHICAGO_
+#define IsEtaskInit(htask, etask) \
+ ( LookupEtask( htask, etask ) \
+ && etask.m_inits != ETASK_NO_INIT)
+
+#else
+#define IsEtaskInit(htask, etask) LookupEtask( htask, etask )
+#endif
diff --git a/private/ole32/olethunk/ole16/inc/initguid.h b/private/ole32/olethunk/ole16/inc/initguid.h
new file mode 100644
index 000000000..e7406e3c2
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/initguid.h
@@ -0,0 +1,38 @@
+/*****************************************************************************\
+* *
+* initguid.h - Definitions for controlling GUID initialization *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+// Include after compobj.h to enable GUID initialization. This
+// must be done once per exe/dll.
+//
+// After this file, include one or more of the GUID definition files.
+//
+// NOTE: ole2.lib contains references to all GUIDs defined by OLE.
+
+#ifndef DEFINE_GUID
+#pragma error "initguid: must include compobj.h first."
+#endif
+
+#undef DEFINE_GUID
+
+#ifdef _MAC
+#define __based(a)
+#endif
+
+#ifdef WIN32
+#define __based(a)
+#endif
+
+#ifdef __TURBOC__
+#define __based(a)
+#endif
+
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID CDECL __based(__segname("_CODE")) name \
+ = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
diff --git a/private/ole32/olethunk/ole16/inc/limits.h b/private/ole32/olethunk/ole16/inc/limits.h
new file mode 100644
index 000000000..da38e6944
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/limits.h
@@ -0,0 +1,44 @@
+/***
+*limits.h - implementation dependent values
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains defines for a number of implementation dependent values
+* which are commonly used in C programs.
+* [ANSI]
+*
+****/
+
+#ifndef _INC_LIMITS
+
+#define CHAR_BIT 8 /* number of bits in a char */
+#define SCHAR_MIN (-127) /* minimum signed char value */
+#define SCHAR_MAX 127 /* maximum signed char value */
+#define UCHAR_MAX 0xff /* maximum unsigned char value */
+#ifndef _CHAR_UNSIGNED
+#define CHAR_MIN SCHAR_MIN /* mimimum char value */
+#define CHAR_MAX SCHAR_MAX /* maximum char value */
+#else
+#define CHAR_MIN 0
+#define CHAR_MAX UCHAR_MAX
+#ifndef __cplusplus
+unsigned int _charmax; /* unsigned CHAR_MAX value */
+#else
+extern "C" unsigned int _charmax; /* unsigned CHAR_MAX value */
+static unsigned int *_char_max = &_charmax;
+#endif
+#endif
+#define MB_LEN_MAX 2 /* max. # bytes in multibyte char */
+#define SHRT_MIN (-32767) /* minimum (signed) short value */
+#define SHRT_MAX 32767 /* maximum (signed) short value */
+#define USHRT_MAX 0xffff /* maximum unsigned short value */
+#define INT_MIN (-32767) /* minimum (signed) int value */
+#define INT_MAX 32767 /* maximum (signed) int value */
+#define UINT_MAX 0xffff /* maximum unsigned int value */
+#define LONG_MIN (-2147483647) /* minimum (signed) long value */
+#define LONG_MAX 2147483647 /* maximum (signed) long value */
+#define ULONG_MAX 0xffffffff /* maximum unsigned long value */
+
+#define _INC_LIMITS
+#endif /* _INC_LIMITS */
diff --git a/private/ole32/olethunk/ole16/inc/lrpcmon.h b/private/ole32/olethunk/ole16/inc/lrpcmon.h
new file mode 100644
index 000000000..38678c4a6
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/lrpcmon.h
@@ -0,0 +1,18 @@
+#ifndef _LRPCMON_H
+#define _LRPCMON_H
+
+// Creates a window and registers it with LRPC. Also saves the address, size
+// of the given static buffer; address of Notification routine.
+//
+// For every LRPC message processed LRPC posts an identical message to this
+// window. The message is processed: it content is formatted into the buffer.
+// It then calls the notification routine.
+//
+STDAPI_(BOOL) StartMonitor(HINSTANCE hInst, FARPROC pNotify,
+ LPSTR pBuf, DWORD dwBufSize);
+
+STDAPI_(void) StopMonitor(void);
+
+#define MINBUFSIZE 32 /* Minimum buffer size passed to StartMonitor */
+
+#endif
diff --git a/private/ole32/olethunk/ole16/inc/malloc.h b/private/ole32/olethunk/ole16/inc/malloc.h
new file mode 100644
index 000000000..f26210834
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/malloc.h
@@ -0,0 +1,159 @@
+/***
+*malloc.h - declarations and definitions for memory allocation functions
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Contains the function declarations for memory allocation functions;
+* also defines manifest constants and types used by the heap routines.
+* [System V]
+*
+****/
+
+#ifndef _INC_MALLOC
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (_MSC_VER <= 600)
+#define __based _based
+#define __cdecl _cdecl
+#define __far _far
+#define __huge _huge
+#define __near _near
+#define __segment _segment
+#endif
+
+/* constants for based heap routines */
+
+#define _NULLSEG ((__segment)0)
+#define _NULLOFF ((void __based(void) *)0xffff)
+
+/* constants for _heapchk/_heapset/_heapwalk routines */
+
+#define _HEAPEMPTY (-1)
+#define _HEAPOK (-2)
+#define _HEAPBADBEGIN (-3)
+#define _HEAPBADNODE (-4)
+#define _HEAPEND (-5)
+#define _HEAPBADPTR (-6)
+#define _FREEENTRY 0
+#define _USEDENTRY 1
+
+/* maximum heap request that can ever be honored */
+
+#ifdef _WINDOWS
+#define _HEAP_MAXREQ 0xFFE6
+#else
+#define _HEAP_MAXREQ 0xFFE8
+#endif
+
+/* types and structures */
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+#ifndef _HEAPINFO_DEFINED
+typedef struct _heapinfo {
+ int __far * _pentry;
+ size_t _size;
+ int _useflag;
+ } _HEAPINFO;
+#define _HEAPINFO_DEFINED
+#endif
+
+
+/* external variable declarations */
+
+extern unsigned int __near __cdecl _amblksiz;
+
+
+/* based heap function prototypes */
+
+void __based(void) * __cdecl _bcalloc(__segment, size_t, size_t);
+void __based(void) * __cdecl _bexpand(__segment,
+ void __based(void) *, size_t);
+void __cdecl _bfree(__segment, void __based(void) *);
+int __cdecl _bfreeseg(__segment);
+int __cdecl _bheapadd(__segment, void __based(void) *, size_t);
+int __cdecl _bheapchk(__segment);
+int __cdecl _bheapmin(__segment);
+__segment __cdecl _bheapseg(size_t);
+int __cdecl _bheapset(__segment, unsigned int);
+int __cdecl _bheapwalk(__segment, _HEAPINFO *);
+void __based(void) * __cdecl _bmalloc(__segment, size_t);
+size_t __cdecl _bmsize(__segment, void __based(void) *);
+void __based(void) * __cdecl _brealloc(__segment,
+ void __based(void) *, size_t);
+
+
+/* function prototypes */
+
+#ifndef _WINDOWS
+void * __cdecl _alloca(size_t);
+#endif
+void * __cdecl calloc(size_t, size_t);
+void * __cdecl _expand(void *, size_t);
+void __far * __cdecl _fcalloc(size_t, size_t);
+void __far * __cdecl _fexpand(void __far *, size_t);
+void __cdecl _ffree(void __far *);
+int __cdecl _fheapchk(void);
+int __cdecl _fheapmin(void);
+int __cdecl _fheapset(unsigned int);
+int __cdecl _fheapwalk(_HEAPINFO *);
+void __far * __cdecl _fmalloc(size_t);
+size_t __cdecl _fmsize(void __far *);
+void __far * __cdecl _frealloc(void __far *, size_t);
+unsigned int __cdecl _freect(size_t);
+void __cdecl free(void *);
+void __huge * __cdecl _halloc(long, size_t);
+void __cdecl _hfree(void __huge *);
+#ifndef _WINDOWS
+int __cdecl _heapadd(void __far *, size_t);
+int __cdecl _heapchk(void);
+#endif
+int __cdecl _heapmin(void);
+#ifndef _WINDOWS
+int __cdecl _heapset(unsigned int);
+int __cdecl _heapwalk(_HEAPINFO *);
+#endif
+void * __cdecl malloc(size_t);
+size_t __cdecl _memavl(void);
+size_t __cdecl _memmax(void);
+size_t __cdecl _msize(void *);
+void __near * __cdecl _ncalloc(size_t, size_t);
+void __near * __cdecl _nexpand(void __near *, size_t);
+void __cdecl _nfree(void __near *);
+#ifndef _WINDOWS
+int __cdecl _nheapchk(void);
+#endif
+int __cdecl _nheapmin(void);
+#ifndef _WINDOWS
+int __cdecl _nheapset(unsigned int);
+int __cdecl _nheapwalk(_HEAPINFO *);
+#endif
+void __near * __cdecl _nmalloc(size_t);
+size_t __cdecl _nmsize(void __near *);
+void __near * __cdecl _nrealloc(void __near *, size_t);
+void * __cdecl realloc(void *, size_t);
+size_t __cdecl _stackavail(void);
+
+#ifndef __STDC__
+/* Non-ANSI names for compatibility */
+#ifndef _WINDOWS
+void * __cdecl alloca(size_t);
+#endif
+void __huge * __cdecl halloc(long, size_t);
+void __cdecl hfree(void __huge *);
+size_t __cdecl stackavail(void);
+#endif /* __STDC__*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_MALLOC
+#endif /* _INC_MALLOC */
diff --git a/private/ole32/olethunk/ole16/inc/map_htsk.h b/private/ole32/olethunk/ole16/inc/map_htsk.h
new file mode 100644
index 000000000..51ed6fad8
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/map_htsk.h
@@ -0,0 +1,69 @@
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+
+class FAR CMapHandleEtask
+{
+public:
+ // Construction
+ CMapHandleEtask(DWORD memctx, UINT nBlockSize=10)
+ : m_mkv(memctx, sizeof(Etask), sizeof(HTASK), nBlockSize) { }
+ CMapHandleEtask(DWORD memctx, UINT nBlockSize, UINT nHashTableSize)
+ : m_mkv(memctx, sizeof(Etask), sizeof(HTASK), nBlockSize,
+ &MKVDefaultHashKey, nHashTableSize) { }
+
+ // Attributes
+ // number of elements
+ int GetCount() const
+ { return m_mkv.GetCount(); }
+ BOOL IsEmpty() const
+ { return GetCount() == 0; }
+
+ // Lookup
+ BOOL Lookup(HTASK key, Etask FAR& value) const
+ { return m_mkv.Lookup((LPVOID)&key, sizeof(HTASK), (LPVOID)&value); }
+
+ BOOL LookupHKey(HMAPKEY hKey, Etask FAR& value) const
+ { return m_mkv.LookupHKey(hKey, (LPVOID)&value); }
+
+ BOOL LookupAdd(HTASK key, Etask FAR& value) const
+ { return m_mkv.LookupAdd((LPVOID)&key, sizeof(HTASK), (LPVOID)&value); }
+
+ // Add/Delete
+ // add a new (key, value) pair
+ BOOL SetAt(HTASK key, Etask& value)
+ { return m_mkv.SetAt((LPVOID)&key, sizeof(HTASK), (LPVOID)&value); }
+ BOOL SetAtHKey(HMAPKEY hKey, Etask& value)
+ { return m_mkv.SetAtHKey(hKey, (LPVOID)&value); }
+
+ // removing existing (key, ?) pair
+ BOOL RemoveKey(HTASK key)
+ { return m_mkv.RemoveKey((LPVOID)&key, sizeof(HTASK)); }
+
+ BOOL RemoveHKey(HMAPKEY hKey)
+ { return m_mkv.RemoveHKey(hKey); }
+
+ void RemoveAll()
+ { m_mkv.RemoveAll(); }
+
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return m_mkv.GetStartPosition(); }
+
+ void GetNextAssoc(POSITION FAR& rNextPosition, HTASK FAR& rKey, Etask FAR& rValue) const
+ { m_mkv.GetNextAssoc(&rNextPosition, (LPVOID)&rKey, NULL, (LPVOID)&rValue); }
+
+ HMAPKEY GetHKey(HTASK key) const
+ { return m_mkv.GetHKey((LPVOID)&key, sizeof(HTASK)); }
+
+#ifdef _DEBUG
+ void AssertValid() const
+ { m_mkv.AssertValid(); }
+#endif
+
+private:
+ CMapKeyToValue m_mkv;
+};
diff --git a/private/ole32/olethunk/ole16/inc/map_kv.h b/private/ole32/olethunk/ole16/inc/map_kv.h
new file mode 100644
index 000000000..0a85ba8bd
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/map_kv.h
@@ -0,0 +1,109 @@
+#ifndef __MAP_KV_H__
+#define __MAP_KV_H__
+
+/////////////////////////////////////////////////////////////////////////////
+// class CMapKeyToValue - a mapping from 'KEY's to 'VALUE's, passed in as
+// pv/cb pairs. The keys can be variable length, although we optmizize the
+// case when they are all the same.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+STDAPI_(UINT) MKVDefaultHashKey(LPVOID pKey, UINT cbKey);
+
+DECLARE_HANDLE32(HMAPKEY);
+typedef UINT (STDAPICALLTYPE FAR* LPFNHASHKEY)(LPVOID, UINT);
+
+class __export CMapKeyToValue
+{
+public:
+ CMapKeyToValue(DWORD memctx, UINT cbValue, UINT cbKey = 0,
+ int nBlockSize=10, LPFNHASHKEY lpfnHashKey = &MKVDefaultHashKey,
+ UINT nHashSize = 17);
+ ~CMapKeyToValue();
+
+ // number of elements
+ int GetCount() const { return m_nCount; }
+ BOOL IsEmpty() const { return m_nCount == 0; }
+
+ // Lookup; return FALSE if not found
+ BOOL Lookup(LPVOID pKey, UINT cbKey, LPVOID pValue) const;
+ BOOL LookupHKey(HMAPKEY hKey, LPVOID pValue) const;
+ BOOL LookupAdd(LPVOID pKey, UINT cbKey, LPVOID pValue) const;
+
+ // add a new (key, value) pair; return FALSE if out of memory
+ BOOL SetAt(LPVOID pKey, UINT cbKey, LPVOID pValue);
+ BOOL SetAtHKey(HMAPKEY hKey, LPVOID pValue);
+
+ // removing existing (key, ?) pair; return FALSE if no such key
+ BOOL RemoveKey(LPVOID pKey, UINT cbKey);
+ BOOL RemoveHKey(HMAPKEY hKey);
+ void RemoveAll();
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return (m_nCount == 0) ? (POSITION)NULL : BEFORE_START_POSITION; }
+ void GetNextAssoc(POSITION FAR* pNextPosition, LPVOID pKey,
+ UINT FAR* pcbKey, LPVOID pValue) const;
+
+ // return HMAPKEY for given key; returns NULL if not currently in map
+ HMAPKEY GetHKey(LPVOID pKey, UINT cbKey) const;
+
+ void AssertValid() const;
+
+private:
+ // abstracts, somewhat, variable and fixed sized keys; size is really
+ // m_cbKeyInAssoc.
+ union CKeyWrap
+ {
+ BYTE rgbKey[sizeof(LPVOID) + sizeof(UINT)];
+ struct
+ {
+ LPVOID pKey;
+ UINT cbKey;
+ };
+ };
+
+ // Association of one key and one value; NOTE: even though in general
+ // the size of the key and value varies, for any given map,
+ // the size of an assoc is fixed.
+ struct CAssoc
+ {
+ CAssoc FAR* pNext;
+ UINT nHashValue; // needed for efficient iteration
+ CKeyWrap key; // size is really m_cbKeyInAssoc
+ // BYTE rgbValue[m_cbValue];
+ };
+
+ UINT SizeAssoc() const
+ { return sizeof(CAssoc)-sizeof(CKeyWrap) + m_cbKeyInAssoc + m_cbValue; }
+ CAssoc FAR* NewAssoc(UINT hash, LPVOID pKey, UINT cbKey, LPVOID pValue);
+ void FreeAssoc(CAssoc FAR* pAssoc);
+ BOOL CompareAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const;
+ CAssoc FAR* GetAssocAt(LPVOID pKey, UINT cbKey, UINT FAR& nHash) const;
+
+ BOOL SetAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const;
+ void GetAssocKeyPtr(CAssoc FAR* pAssoc, LPVOID FAR* ppKey,UINT FAR* pcbKey) const;
+ void FreeAssocKey(CAssoc FAR* pAssoc) const;
+ void GetAssocValuePtr(CAssoc FAR* pAssoc, LPVOID FAR* ppValue) const;
+ void GetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const;
+ void SetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const;
+
+ BOOL InitHashTable();
+
+ UINT m_cbValue;
+ UINT m_cbKey; // variable length if 0
+ UINT m_cbKeyInAssoc; // always non-zero
+
+ CAssoc FAR* FAR* m_pHashTable;
+ UINT m_nHashTableSize;
+ LPFNHASHKEY m_lpfnHashKey;
+
+ int m_nCount;
+ CAssoc FAR* m_pFreeList;
+ struct CPlex FAR* m_pBlocks;
+ int m_nBlockSize;
+ DWORD m_memctx;
+};
+
+
+#endif // !__MAP_KV_H__
diff --git a/private/ole32/olethunk/ole16/inc/math.h b/private/ole32/olethunk/ole16/inc/math.h
new file mode 100644
index 000000000..39a4af3d5
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/math.h
@@ -0,0 +1,303 @@
+/***
+*math.h - definitions and declarations for math library
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains constant definitions and external subroutine
+* declarations for the math subroutine library.
+* [ANSI/System V]
+*
+****/
+
+#ifndef _INC_MATH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (_MSC_VER <= 600)
+#define __cdecl _cdecl
+#define __far _far
+#define __near _near
+#define __pascal _pascal
+#endif
+
+/* definition of _exception struct - this struct is passed to the _matherr
+ * routine when a floating point exception is detected
+ */
+
+#ifndef _EXCEPTION_DEFINED
+#pragma pack(2)
+
+struct _exception {
+ int type; /* exception type - see below */
+ char *name; /* name of function where error occured */
+ double arg1; /* first argument to function */
+ double arg2; /* second argument (if any) to function */
+ double retval; /* value to be returned by function */
+ } ;
+
+#ifndef __STDC__
+/* Non-ANSI name for compatibility */
+#define exception _exception
+#endif
+
+#pragma pack()
+#define _EXCEPTION_DEFINED
+#endif
+
+
+/* definition of a _complex struct to be used by those who use cabs and
+ * want type checking on their argument
+ */
+
+#ifndef _COMPLEX_DEFINED
+
+struct _complex {
+ double x,y; /* real and imaginary parts */
+ } ;
+
+#ifndef __cplusplus
+#ifndef __STDC__
+/* Non-ANSI name for compatibility */
+struct complex {
+ double x,y; /* real and imaginary parts */
+ } ;
+#endif
+#endif
+
+#define _COMPLEX_DEFINED
+#endif
+
+
+/* Constant definitions for the exception type passed in the _exception struct
+ */
+
+#define _DOMAIN 1 /* argument domain error */
+#define _SING 2 /* argument singularity */
+#define _OVERFLOW 3 /* overflow range error */
+#define _UNDERFLOW 4 /* underflow range error */
+#define _TLOSS 5 /* total loss of precision */
+#define _PLOSS 6 /* partial loss of precision */
+
+#define EDOM 33
+#define ERANGE 34
+
+
+/* definitions of _HUGE (XENIX) and HUGE_VAL (ANSI) error return values used
+ * by several floating point math routines
+ */
+
+extern double __near __cdecl _HUGE;
+#define HUGE_VAL _HUGE
+
+
+/* function prototypes */
+
+#ifdef _MT
+int __cdecl abs(int);
+double __pascal acos(double);
+double __pascal asin(double);
+double __pascal atan(double);
+double __pascal atan2(double, double);
+double __pascal atof(const char *);
+double __pascal _cabs(struct _complex);
+double __pascal ceil(double);
+double __pascal cos(double);
+double __pascal cosh(double);
+int __cdecl _dieeetomsbin(double *, double *);
+int __cdecl _dmsbintoieee(double *, double *);
+double __pascal exp(double);
+double __pascal fabs(double);
+int __cdecl _fieeetomsbin(float *, float *);
+double __pascal floor(double);
+double __pascal fmod(double, double);
+int __cdecl _fmsbintoieee(float *, float *);
+double __pascal frexp(double, int *);
+double __pascal _hypot(double, double);
+double __pascal _j0(double);
+double __pascal _j1(double);
+double __pascal _jn(int, double);
+long __cdecl labs(long);
+double __pascal ldexp(double, int);
+double __pascal log(double);
+double __pascal log10(double);
+int __cdecl _matherr(struct _exception *);
+double __pascal modf(double, double *);
+double __pascal pow(double, double);
+double __pascal sin(double);
+double __pascal sinh(double);
+double __pascal sqrt(double);
+double __pascal tan(double);
+double __pascal tanh(double);
+double __pascal _y0(double);
+double __pascal _y1(double);
+double __pascal _yn(int, double);
+
+#else
+int __cdecl abs(int);
+double __cdecl acos(double);
+double __cdecl asin(double);
+double __cdecl atan(double);
+double __cdecl atan2(double, double);
+double __cdecl atof(const char *);
+double __cdecl _cabs(struct _complex);
+double __cdecl ceil(double);
+double __cdecl cos(double);
+double __cdecl cosh(double);
+int __cdecl _dieeetomsbin(double *, double *);
+int __cdecl _dmsbintoieee(double *, double *);
+double __cdecl exp(double);
+double __cdecl fabs(double);
+int __cdecl _fieeetomsbin(float *, float *);
+double __cdecl floor(double);
+double __cdecl fmod(double, double);
+int __cdecl _fmsbintoieee(float *, float *);
+double __cdecl frexp(double, int *);
+double __cdecl _hypot(double, double);
+double __cdecl _j0(double);
+double __cdecl _j1(double);
+double __cdecl _jn(int, double);
+long __cdecl labs(long);
+double __cdecl ldexp(double, int);
+double __cdecl log(double);
+double __cdecl log10(double);
+int __cdecl _matherr(struct _exception *);
+double __cdecl modf(double, double *);
+double __cdecl pow(double, double);
+double __cdecl sin(double);
+double __cdecl sinh(double);
+double __cdecl sqrt(double);
+double __cdecl tan(double);
+double __cdecl tanh(double);
+double __cdecl _y0(double);
+double __cdecl _y1(double);
+double __cdecl _yn(int, double);
+#endif
+
+
+/* definition of _exceptionl struct - this struct is passed to the _matherrl
+ * routine when a floating point exception is detected in a long double routine
+ */
+
+#ifndef _LD_EXCEPTION_DEFINED
+#pragma pack(2)
+struct _exceptionl {
+ int type; /* exception type - see below */
+ char *name; /* name of function where error occured */
+ long double arg1; /* first argument to function */
+ long double arg2; /* second argument (if any) to function */
+ long double retval; /* value to be returned by function */
+ } ;
+#pragma pack()
+#define _LD_EXCEPTION_DEFINED
+#endif
+
+
+/* definition of a _complexl struct to be used by those who use _cabsl and
+ * want type checking on their argument
+ */
+
+#ifndef _LD_COMPLEX_DEFINED
+#pragma pack(2)
+struct _complexl {
+ long double x,y; /* real and imaginary parts */
+ } ;
+#pragma pack()
+#define _LD_COMPLEX_DEFINED
+#endif
+
+extern long double __near __cdecl _LHUGE;
+#define _LHUGE_VAL _LHUGE
+
+
+long double __cdecl acosl(long double);
+long double __cdecl asinl(long double);
+long double __cdecl atanl(long double);
+long double __cdecl atan2l(long double, long double);
+long double __cdecl _atold(const char *);
+long double __cdecl _cabsl(struct _complexl);
+long double __cdecl ceill(long double);
+long double __cdecl cosl(long double);
+long double __cdecl coshl(long double);
+long double __cdecl expl(long double);
+long double __cdecl fabsl(long double);
+long double __cdecl floorl(long double);
+long double __cdecl fmodl(long double, long double);
+long double __cdecl frexpl(long double, int *);
+long double __cdecl _hypotl(long double, long double);
+long double __cdecl _j0l(long double);
+long double __cdecl _j1l(long double);
+long double __cdecl _jnl(int, long double);
+long double __cdecl ldexpl(long double, int);
+long double __cdecl logl(long double);
+long double __cdecl log10l(long double);
+int __cdecl _matherrl(struct _exceptionl *);
+long double __cdecl modfl(long double, long double *);
+long double __cdecl powl(long double, long double);
+long double __cdecl sinl(long double);
+long double __cdecl sinhl(long double);
+long double __cdecl sqrtl(long double);
+long double __cdecl tanl(long double);
+long double __cdecl tanhl(long double);
+long double __cdecl _y0l(long double);
+long double __cdecl _y1l(long double);
+long double __cdecl _ynl(int, long double);
+
+
+#ifndef __STDC__
+/* Non-ANSI names for compatibility */
+
+#define DOMAIN _DOMAIN
+#define SING _SING
+#define OVERFLOW _OVERFLOW
+#define UNDERFLOW _UNDERFLOW
+#define TLOSS _TLOSS
+#define PLOSS _PLOSS
+
+#define matherr _matherr
+
+extern double __near __cdecl HUGE;
+
+#ifdef _MT
+#ifndef __cplusplus
+double __pascal cabs(struct complex);
+#endif
+double __pascal hypot(double, double);
+double __pascal j0(double);
+double __pascal j1(double);
+double __pascal jn(int, double);
+double __pascal y0(double);
+double __pascal y1(double);
+double __pascal yn(int, double);
+#else
+#ifndef __cplusplus
+double __cdecl cabs(struct complex);
+#endif
+double __cdecl hypot(double, double);
+double __cdecl j0(double);
+double __cdecl j1(double);
+double __cdecl jn(int, double);
+double __cdecl y0(double);
+double __cdecl y1(double);
+double __cdecl yn(int, double);
+#endif
+
+int __cdecl dieeetomsbin(double *, double *);
+int __cdecl dmsbintoieee(double *, double *);
+int __cdecl fieeetomsbin(float *, float *);
+int __cdecl fmsbintoieee(float *, float *);
+
+long double __cdecl cabsl(struct _complexl);
+long double __cdecl hypotl(long double, long double);
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_MATH
+#endif
diff --git a/private/ole32/olethunk/ole16/inc/memctx.hxx b/private/ole32/olethunk/ole16/inc/memctx.hxx
new file mode 100644
index 000000000..522b327d8
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/memctx.hxx
@@ -0,0 +1,16 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: memctx.hxx
+//
+// Contents: extern definitions from memctx.cxx
+//
+// History: 08-Mar-94 BobDay Derived from MEMCTX.HXX
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(DWORD) CoMemctxOf(void const FAR* lpv);
+STDAPI_(void FAR*) CoMemAlloc(ULONG size, DWORD memctx, void FAR* lpvNear);
+STDAPI_(void) CoMemFree(void FAR* lpv, DWORD memctx);
diff --git a/private/ole32/olethunk/ole16/inc/memory.h b/private/ole32/olethunk/ole16/inc/memory.h
new file mode 100644
index 000000000..c43f796aa
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/memory.h
@@ -0,0 +1,75 @@
+/***
+*memory.h - declarations for buffer (memory) manipulation routines
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This include file contains the function declarations for the
+* buffer (memory) manipulation routines.
+* [System V]
+*
+****/
+
+#ifndef _INC_MEMORY
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (_MSC_VER <= 600)
+#define __cdecl _cdecl
+#define __far _far
+#endif
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+
+/* function prototypes */
+
+void * __cdecl _memccpy(void *, const void *,
+ int, unsigned int);
+void * __cdecl memchr(const void *, int, size_t);
+int __cdecl memcmp(const void *, const void *,
+ size_t);
+void * __cdecl memcpy(void *, const void *,
+ size_t);
+int __cdecl _memicmp(const void *, const void *,
+ unsigned int);
+void * __cdecl memset(void *, int, size_t);
+void __cdecl _movedata(unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int);
+
+
+/* model independent function prototypes */
+
+void __far * __far __cdecl _fmemccpy(void __far *, const void __far *,
+ int, unsigned int);
+void __far * __far __cdecl _fmemchr(const void __far *, int, size_t);
+int __far __cdecl _fmemcmp(const void __far *, const void __far *,
+ size_t);
+void __far * __far __cdecl _fmemcpy(void __far *, const void __far *,
+ size_t);
+int __far __cdecl _fmemicmp(const void __far *, const void __far *,
+ unsigned int);
+void __far * __far __cdecl _fmemset(void __far *, int, size_t);
+
+
+#ifndef __STDC__
+/* Non-ANSI names for compatibility */
+void * __cdecl memccpy(void *, const void *,
+ int, unsigned int);
+int __cdecl memicmp(const void *, const void *,
+ unsigned int);
+void __cdecl movedata(unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_MEMORY
+#endif /* _INC_MEMORY */
diff --git a/private/ole32/olethunk/ole16/inc/moniker.h b/private/ole32/olethunk/ole16/inc/moniker.h
new file mode 100644
index 000000000..0f1761ff8
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/moniker.h
@@ -0,0 +1,248 @@
+/*****************************************************************************\
+* *
+* moniker.h - Moniker and related interfaces and APIs *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#if !defined( _MONIKER_H_ )
+#define _MONIKER_H_
+
+#define MK_E_CONNECTMANUALLY MK_E_FIRST
+#define MK_E_EXCEEDEDDEADLINE (MK_E_FIRST + 1)
+#define MK_E_NEEDGENERIC (MK_E_FIRST + 2)
+#define MK_E_UNAVAILABLE (MK_E_FIRST + 3)
+#define MK_E_SYNTAX (MK_E_FIRST + 4)
+#define MK_E_NOOBJECT (MK_E_FIRST + 5)
+#define MK_E_INVALIDEXTENSION (MK_E_FIRST + 6)
+#define MK_E_INTERMEDIATEINTERFACENOTSUPPORTED (MK_E_FIRST + 7)
+#define MK_E_NOTBINDABLE (MK_E_FIRST + 8)
+#define MK_E_NOTBOUND (MK_E_FIRST + 9)
+ // called IBindCtx->RevokeObjectBound for an
+ // object which was not bound
+#define MK_E_CANTOPENFILE (MK_E_FIRST + 10)
+#define MK_E_MUSTBOTHERUSER (MK_E_FIRST + 11)
+#define MK_E_NOINVERSE (MK_E_FIRST + 12)
+#define MK_E_NOSTORAGE (MK_E_FIRST + 13)
+#define MK_E_NOPREFIX (MK_E_FIRST + 14)
+
+
+// reserved MK_S_FIRST
+// reserved (MK_S_FIRST + 1)
+#define MK_S_REDUCED_TO_SELF (MK_S_FIRST + 2)
+// reserved (MK_S_FIRST + 3)
+#define MK_S_ME (MK_S_FIRST + 4)
+#define MK_S_HIM (MK_S_FIRST + 5)
+#define MK_S_US (MK_S_FIRST + 6)
+#define MK_S_MONIKERALREADYREGISTERED (MK_S_FIRST + 7)
+
+
+// bind options; variable sized
+typedef struct FARSTRUCT tagBIND_OPTS
+{
+ DWORD cbStruct; // sizeof(BIND_OPTS)
+ DWORD grfFlags;
+ DWORD grfMode;
+ DWORD dwTickCountDeadline;
+} BIND_OPTS, FAR* LPBIND_OPTS;
+
+
+// bind flags; controls binding; stored in bind options above
+typedef enum
+{
+ BIND_MAYBOTHERUSER = 1,
+ BIND_JUSTTESTEXISTENCE = 2
+} BIND_FLAGS;
+
+
+// system moniker types; returned from IsSystemMoniker.
+typedef enum tagMKSYS
+{
+ MKSYS_NONE = 0,
+ MKSYS_GENERICCOMPOSITE = 1,
+ MKSYS_FILEMONIKER = 2,
+ MKSYS_ANTIMONIKER = 3,
+ MKSYS_ITEMMONIKER = 4,
+ MKSYS_POINTERMONIKER = 5
+}MKSYS;
+
+
+// bit wise enum to control how much reduction takes place.
+typedef enum tagMKREDUCE
+{
+ MKRREDUCE_ONE = 3<<16,
+ MKRREDUCE_TOUSER = 2<<16,
+ MKRREDUCE_THROUGHUSER = 1<<16,
+ MKRREDUCE_ALL = 0
+} MKRREDUCE;
+
+
+#if defined(__cplusplus)
+interface IEnumMoniker;
+interface IRunningObjectTable;
+#else
+typedef interface IEnumMoniker IEnumMoniker;
+typedef interface IRunningObjectTable IRunningObjectTable;
+#endif
+
+typedef IEnumMoniker FAR* LPENUMMONIKER;
+typedef IRunningObjectTable FAR* LPRUNNINGOBJECTTABLE;
+
+
+
+#undef INTERFACE
+#define INTERFACE IBindCtx
+
+DECLARE_INTERFACE_(IBindCtx, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IBindCtx methods ***
+ STDMETHOD(RegisterObjectBound) (THIS_ LPUNKNOWN punk) PURE;
+ STDMETHOD(RevokeObjectBound) (THIS_ LPUNKNOWN punk) PURE;
+ STDMETHOD(ReleaseBoundObjects) (THIS) PURE;
+
+ STDMETHOD(SetBindOptions) (THIS_ LPBIND_OPTS pbindopts) PURE;
+ STDMETHOD(GetBindOptions) (THIS_ LPBIND_OPTS pbindopts) PURE;
+ STDMETHOD(GetRunningObjectTable) (THIS_ LPRUNNINGOBJECTTABLE FAR*
+ pprot) PURE;
+ STDMETHOD(RegisterObjectParam) (THIS_ LPSTR lpszKey, LPUNKNOWN punk) PURE;
+ STDMETHOD(GetObjectParam) (THIS_ LPSTR lpszKey, LPUNKNOWN FAR* ppunk) PURE;
+ STDMETHOD(EnumObjectParam) (THIS_ LPENUMSTRING FAR* ppenum) PURE;
+ STDMETHOD(RevokeObjectParam) (THIS_ LPSTR lpszKey) PURE;
+};
+typedef IBindCtx FAR* LPBC;
+typedef IBindCtx FAR* LPBINDCTX;
+
+
+
+#undef INTERFACE
+#define INTERFACE IMoniker
+
+DECLARE_INTERFACE_(IMoniker, IPersistStream)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+
+ // *** IPersistStream methods ***
+ STDMETHOD(IsDirty) (THIS) PURE;
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm) PURE;
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty) PURE;
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR * pcbSize) PURE;
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID FAR* ppvResult) PURE;
+ STDMETHOD(BindToStorage) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD(Reduce) (THIS_ LPBC pbc, DWORD dwReduceHowFar, LPMONIKER FAR*
+ ppmkToLeft, LPMONIKER FAR * ppmkReduced) PURE;
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNotGeneric,
+ LPMONIKER FAR* ppmkComposite) PURE;
+ STDMETHOD(Enum) (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker)
+ PURE;
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker) PURE;
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash) PURE;
+ STDMETHOD(IsRunning) (THIS_ LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+ pmkNewlyRunning) PURE;
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime) PURE;
+ STDMETHOD(Inverse) (THIS_ LPMONIKER FAR* ppmk) PURE;
+ STDMETHOD(CommonPrefixWith) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix) PURE;
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath) PURE;
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPSTR FAR* lplpszDisplayName) PURE;
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut) PURE;
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys) PURE;
+};
+typedef IMoniker FAR* LPMONIKER;
+
+
+// IRunningObjectTable::Register flags
+#define ROTFLAGS_REGISTRATIONKEEPSALIVE 1
+
+#undef INTERFACE
+#define INTERFACE IRunningObjectTable
+
+DECLARE_INTERFACE_(IRunningObjectTable, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IRunningObjectTable methods ***
+ STDMETHOD(Register) (THIS_ DWORD grfFlags, LPUNKNOWN punkObject,
+ LPMONIKER pmkObjectName, DWORD FAR * pdwRegister) PURE;
+ STDMETHOD(Revoke) (THIS_ DWORD dwRegister) PURE;
+ STDMETHOD(IsRunning) (THIS_ LPMONIKER pmkObjectName) PURE;
+ STDMETHOD(GetObject) (THIS_ LPMONIKER pmkObjectName,
+ LPUNKNOWN FAR* ppunkObject) PURE;
+ STDMETHOD(NoteChangeTime) (THIS_ DWORD dwRegister, FILETIME FAR * pfiletime) PURE;
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPMONIKER pmkObjectName, FILETIME FAR * pfiletime) PURE;
+ STDMETHOD(EnumRunning) (THIS_ LPENUMMONIKER FAR * ppenumMoniker ) PURE;
+};
+typedef IRunningObjectTable FAR* LPRUNNINGOBJECTTABLE;
+
+
+
+#undef INTERFACE
+#define INTERFACE IEnumMoniker
+
+DECLARE_INTERFACE_(IEnumMoniker, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumOleDataObject methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, LPMONIKER FAR* rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumMoniker FAR* FAR* ppenm) PURE;
+};
+typedef IEnumMoniker FAR* LPENUMMONIKER;
+
+
+
+
+STDAPI BindMoniker(LPMONIKER pmk, DWORD grfOpt, REFIID iidResult, LPVOID FAR* ppvResult);
+STDAPI MkParseDisplayName(LPBC pbc, LPSTR szUserName,
+ ULONG FAR * pchEaten, LPMONIKER FAR * ppmk);
+STDAPI MonikerRelativePathTo(LPMONIKER pmkSrc, LPMONIKER pmkDest, LPMONIKER
+ FAR* ppmkRelPath, BOOL fCalledFromMethod);
+STDAPI MonikerCommonPrefixWith(LPMONIKER pmkThis, LPMONIKER pmkOther,
+ LPMONIKER FAR* ppmkCommon);
+STDAPI CreateBindCtx(DWORD reserved, LPBC FAR* ppbc);
+STDAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest,
+ LPMONIKER FAR* ppmkComposite);
+STDAPI GetClassFile (LPCSTR szFilename, CLSID FAR* pclsid);
+
+STDAPI CreateFileMoniker(LPSTR lpszPathName, LPMONIKER FAR* ppmk);
+STDAPI CreateItemMoniker(LPSTR lpszDelim, LPSTR lpszItem,
+ LPMONIKER FAR* ppmk);
+STDAPI CreateAntiMoniker(LPMONIKER FAR* ppmk);
+STDAPI CreatePointerMoniker(LPUNKNOWN punk, LPMONIKER FAR* ppmk);
+
+STDAPI GetRunningObjectTable( DWORD reserved, LPRUNNINGOBJECTTABLE FAR* pprot);
+
+
+#endif // _MONIKER_H_
diff --git a/private/ole32/olethunk/ole16/inc/monsegs.h b/private/ole32/olethunk/ole16/inc/monsegs.h
new file mode 100644
index 000000000..139597f9c
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/monsegs.h
@@ -0,0 +1,2 @@
+
+
diff --git a/private/ole32/olethunk/ole16/inc/ole1cls.h b/private/ole32/olethunk/ole16/inc/ole1cls.h
new file mode 100644
index 000000000..eeae62ba4
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/ole1cls.h
@@ -0,0 +1,141 @@
+/*****************************************************************************\
+* *
+* ole1cls.h - Master definition of GUIDs for OLE1 classes *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+/* This file is the master definition of all GUIDs for OLE1 classes.
+
+ All such GUIDs are of the form:
+
+ 0003xxxx-0000-0000-C000-000000000046
+
+ The last parameter to DEFINE_OLE1GUID is the old 1.0 class name,
+ i.e., its key in the registration database.
+
+ Do not remove or change GUIDs.
+
+ Do not add anything to this file except comments and DEFINE_OLE1GUID macros.
+*/
+
+#ifndef DEFINE_OLE1GUID
+#define DEFINE_OLE1GUID(a,b,c,d,e) DEFINE_OLEGUID (a,b,c,d)
+#endif
+
+DEFINE_OLE1GUID(CLSID_ExcelWorksheet, 0x00030000, 0, 0, "ExcelWorksheet");
+DEFINE_OLE1GUID(CLSID_ExcelChart, 0x00030001, 0, 0, "ExcelChart");
+DEFINE_OLE1GUID(CLSID_ExcelMacrosheet, 0x00030002, 0, 0, "ExcelMacrosheet");
+DEFINE_OLE1GUID(CLSID_WordDocument, 0x00030003, 0, 0, "WordDocument");
+DEFINE_OLE1GUID(CLSID_MSPowerPoint, 0x00030004, 0, 0, "MSPowerPoint");
+DEFINE_OLE1GUID(CLSID_MSPowerPointSho, 0x00030005, 0, 0, "MSPowerPointSho");
+DEFINE_OLE1GUID(CLSID_MSGraph, 0x00030006, 0, 0, "MSGraph");
+DEFINE_OLE1GUID(CLSID_MSDraw, 0x00030007, 0, 0, "MSDraw");
+DEFINE_OLE1GUID(CLSID_Note_It, 0x00030008, 0, 0, "Note-It");
+DEFINE_OLE1GUID(CLSID_WordArt, 0x00030009, 0, 0, "WordArt");
+DEFINE_OLE1GUID(CLSID_PBrush, 0x0003000a, 0, 0, "PBrush");
+DEFINE_OLE1GUID(CLSID_Equation, 0x0003000b, 0, 0, "Equation");
+DEFINE_OLE1GUID(CLSID_Package, 0x0003000c, 0, 0, "Package");
+DEFINE_OLE1GUID(CLSID_SoundRec, 0x0003000d, 0, 0, "SoundRec");
+DEFINE_OLE1GUID(CLSID_MPlayer, 0x0003000e, 0, 0, "MPlayer");
+
+/* test apps */
+DEFINE_OLE1GUID(CLSID_ServerDemo, 0x0003000f, 0, 0, "ServerDemo");
+DEFINE_OLE1GUID(CLSID_Srtest, 0x00030010, 0, 0, "Srtest");
+DEFINE_OLE1GUID(CLSID_SrtInv, 0x00030011, 0, 0, "SrtInv");
+DEFINE_OLE1GUID(CLSID_OleDemo, 0x00030012, 0, 0, "OleDemo");
+
+/* External ISVs */
+// Coromandel / Dorai Swamy / 718-793-7963
+DEFINE_OLE1GUID(CLSID_CoromandelIntegra, 0x00030013, 0, 0, "CoromandelIntegra");
+DEFINE_OLE1GUID(CLSID_CoromandelObjServer,0x00030014, 0, 0, "CoromandelObjServer");
+
+// 3-d Visions Corp / Peter Hirsch / 310-325-1339
+DEFINE_OLE1GUID(CLSID_StanfordGraphics, 0x00030015, 0, 0, "StanfordGraphics");
+
+// Deltapoint / Nigel Hearne / 408-648-4000
+DEFINE_OLE1GUID(CLSID_DGraphCHART, 0x00030016, 0, 0, "DGraphCHART");
+DEFINE_OLE1GUID(CLSID_DGraphDATA, 0x00030017, 0, 0, "DGraphDATA");
+
+// Corel / Richard V. Woodend / 613-728-8200 x1153
+DEFINE_OLE1GUID(CLSID_PhotoPaint, 0x00030018, 0, 0, "PhotoPaint");
+DEFINE_OLE1GUID(CLSID_CShow, 0x00030019, 0, 0, "CShow");
+DEFINE_OLE1GUID(CLSID_CorelChart, 0x0003001a, 0, 0, "CorelChart");
+DEFINE_OLE1GUID(CLSID_CDraw, 0x0003001b, 0, 0, "CDraw");
+
+// Inset Systems / Mark Skiba / 203-740-2400
+DEFINE_OLE1GUID(CLSID_HJWIN1_0, 0x0003001c, 0, 0, "HJWIN1.0");
+
+// Mark V Systems / Mark McGraw / 818-995-7671
+DEFINE_OLE1GUID(CLSID_ObjMakerOLE, 0x0003001d, 0, 0, "ObjMakerOLE");
+
+// IdentiTech / Mike Gilger / 407-951-9503
+DEFINE_OLE1GUID(CLSID_FYI, 0x0003001e, 0, 0, "FYI");
+DEFINE_OLE1GUID(CLSID_FYIView, 0x0003001f, 0, 0, "FYIView");
+
+// Inventa Corporation / Balaji Varadarajan / 408-987-0220
+DEFINE_OLE1GUID(CLSID_Stickynote, 0x00030020, 0, 0, "Stickynote");
+
+// ShapeWare Corp. / Lori Pearce / 206-467-6723
+DEFINE_OLE1GUID(CLSID_ShapewareVISIO10, 0x00030021, 0, 0, "ShapewareVISIO10");
+DEFINE_OLE1GUID(CLSID_ImportServer, 0x00030022, 0, 0, "ImportServer");
+
+
+// test app SrTest
+DEFINE_OLE1GUID(CLSID_SrvrTest, 0x00030023, 0, 0, "SrvrTest");
+
+// Special clsid for when a 1.0 client pastes an embedded object
+// that is a link.
+// **This CLSID is obsolete. Do not reuse number.
+//DEFINE_OLE1GUID(CLSID_10EmbedObj, 0x00030024, 0, 0, "OLE2_Embedded_Link");
+
+// test app ClTest. Doesn't really work as a server but is in reg db
+DEFINE_OLE1GUID(CLSID_ClTest, 0x00030025, 0, 0, "Cltest");
+
+// Microsoft ClipArt Gallery Sherry Larsen-Holmes
+DEFINE_OLE1GUID(CLSID_MS_ClipArt_Gallery,0x00030026, 0, 0, "MS_ClipArt_Gallery");
+
+// Microsoft Project Cory Reina
+DEFINE_OLE1GUID(CLSID_MSProject, 0x00030027, 0, 0, "MSProject");
+
+// Microsoft Works Chart
+DEFINE_OLE1GUID(CLSID_MSWorksChart, 0x00030028, 0, 0, "MSWorksChart");
+
+// Microsoft Works Spreadsheet
+DEFINE_OLE1GUID(CLSID_MSWorksSpreadsheet,0x00030029, 0, 0, "MSWorksSpreadsheet");
+
+// AFX apps - Dean McCrory
+DEFINE_OLE1GUID(CLSID_MinSvr, 0x0003002A, 0, 0, "MinSvr");
+DEFINE_OLE1GUID(CLSID_HierarchyList, 0x0003002B, 0, 0, "HierarchyList");
+DEFINE_OLE1GUID(CLSID_BibRef, 0x0003002C, 0, 0, "BibRef");
+DEFINE_OLE1GUID(CLSID_MinSvrMI, 0x0003002D, 0, 0, "MinSvrMI");
+DEFINE_OLE1GUID(CLSID_TestServ, 0x0003002E, 0, 0, "TestServ");
+
+// Ami Pro
+DEFINE_OLE1GUID(CLSID_AmiProDocument, 0x0003002F, 0, 0, "AmiProDocument");
+
+// WordPerfect Presentations For Windows
+DEFINE_OLE1GUID(CLSID_WPGraphics, 0x00030030, 0, 0, "WPGraphics");
+DEFINE_OLE1GUID(CLSID_WPCharts, 0x00030031, 0, 0, "WPCharts");
+
+
+// MicroGrafx Charisma
+DEFINE_OLE1GUID(CLSID_Charisma, 0x00030032, 0, 0, "Charisma");
+DEFINE_OLE1GUID(CLSID_Charisma_30, 0x00030033, 0, 0, "Charisma_30");
+DEFINE_OLE1GUID(CLSID_CharPres_30, 0x00030034, 0, 0, "CharPres_30");
+
+// MicroGrafx Draw
+DEFINE_OLE1GUID(CLSID_Draw, 0x00030035, 0, 0, "Draw");
+
+// MicroGrafx Designer
+DEFINE_OLE1GUID(CLSID_Designer_40, 0x00030036, 0, 0, "Designer_40");
+
+
+#undef DEFINE_OLE1GUID
+
+/* as we discover OLE 1 servers we will add them to the end of this list;
+ there is room for 64K of them!
+*/
diff --git a/private/ole32/olethunk/ole16/inc/ole2.h b/private/ole32/olethunk/ole16/inc/ole2.h
new file mode 100644
index 000000000..c5daea6f0
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/ole2.h
@@ -0,0 +1,1336 @@
+/*****************************************************************************\
+* *
+* ole2.h - Main OLE2 header; includes all subcomponents *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#if !defined( _OLE2_H_ )
+#define _OLE2_H_
+
+#ifndef RC_INVOKED
+#pragma warning(disable:4001)
+#endif /* RC_INVOKED */
+
+#include <string.h>
+
+/****** Standard Object Definitions *****************************************/
+
+#include <compobj.h>
+
+
+// *************** FACILITY_ITF scodes common to all interfaces ************
+//
+// By convention, OLE interfaces divide the FACILITY_ITF range of errors
+// into nonoverlapping subranges. If an interface returns a FACILITY_ITF
+// scode, it must be from the range associated with that interface or from
+// the shared range: OLE_E_FIRST...OLE_E_LAST.
+//
+
+// error codes
+
+#define OLE_E_OLEVERB (OLE_E_FIRST)
+// invalid OLEVERB structure
+
+#define OLE_E_ADVF (OLE_E_FIRST+1)
+// invalid advise flags
+
+#define OLE_E_ENUM_NOMORE (OLE_E_FIRST+2)
+// you can't enuemrate any more, because the associated data is missing
+
+#define OLE_E_ADVISENOTSUPPORTED (OLE_E_FIRST+3)
+// this implementation doesn't take advises
+
+#define OLE_E_NOCONNECTION (OLE_E_FIRST+4)
+// there is no connection for this connection id
+
+#define OLE_E_NOTRUNNING (OLE_E_FIRST+5)
+// need run the object to perform this operation
+
+#define OLE_E_NOCACHE (OLE_E_FIRST+6)
+// there is no cache to operate on
+
+#define OLE_E_BLANK (OLE_E_FIRST+7)
+// Uninitialized object
+
+#define OLE_E_CLASSDIFF (OLE_E_FIRST+8)
+// linked object's source class has changed
+
+#define OLE_E_CANT_GETMONIKER (OLE_E_FIRST+9)
+// not able to get the moniker of the object
+
+#define OLE_E_CANT_BINDTOSOURCE (OLE_E_FIRST+10)
+// not able to bind to the source
+
+#define OLE_E_STATIC (OLE_E_FIRST+11)
+// object is static, operation not allowed
+
+#define OLE_E_PROMPTSAVECANCELLED (OLE_E_FIRST+12)
+// user cancelled out of save dialog
+
+#define OLE_E_INVALIDRECT (OLE_E_FIRST+13)
+// invalid rectangle
+
+#define OLE_E_WRONGCOMPOBJ (OLE_E_FIRST+14)
+// compobj.dll is too old for the ole2.dll initialized
+
+#define OLE_E_INVALIDHWND (OLE_E_FIRST+15)
+// invalid window handle
+
+#define OLE_E_NOT_INPLACEACTIVE (OLE_E_FIRST+16)
+// object is not in any of the inplace active states
+
+#define OLE_E_CANTCONVERT (OLE_E_FIRST+17)
+// not able to convert the object
+
+#define OLE_E_NOSTORAGE (OLE_E_FIRST+18)
+// not able to perform the operation because object is not given storage yet.
+
+
+#define DVGEN_E_FIRST (OLE_E_FIRST+100)
+
+#define DV_E_FORMATETC (DVGEN_E_FIRST)
+// invalid FORMATETC structure
+
+#define DV_E_DVTARGETDEVICE (DVGEN_E_FIRST+1)
+// invalid DVTARGETDEVICE structure
+
+#define DV_E_STGMEDIUM (DVGEN_E_FIRST+2)
+// invalid STDGMEDIUM structure
+
+#define DV_E_STATDATA (DVGEN_E_FIRST+3)
+// invalid STATDATA structure
+
+#define DV_E_LINDEX (DVGEN_E_FIRST+4)
+// invalid lindex
+
+#define DV_E_TYMED (DVGEN_E_FIRST+5)
+// invalid tymed
+
+#define DV_E_CLIPFORMAT (DVGEN_E_FIRST+6)
+// invalid clipboard format
+
+#define DV_E_DVASPECT (DVGEN_E_FIRST+7)
+// invalid aspect(s)
+
+#define DV_E_DVTARGETDEVICE_SIZE (DVGEN_E_FIRST+8)
+// tdSize paramter of the DVTARGETDEVICE structure is invalid
+
+#define DV_E_NOIVIEWOBJECT (DVGEN_E_FIRST+9)
+// object doesn't support IViewObject interface
+
+
+// Success codes
+
+#define OLE_S_USEREG (OLE_S_FIRST)
+// use the reg database to provide the requested info
+
+#define OLE_S_STATIC (OLE_S_FIRST+1)
+// success, but static
+
+#define OLE_S_MAC_CLIPFORMAT (OLE_S_FIRST+2)
+// macintosh clipboard format
+
+//*************************** Interface or API specific scodes *************
+
+// Errors for OleConvertOLESTREAMToIStorage and OleConvertIStorageToOLESTREAM
+
+// OLESTREAM Get method failed
+#define CONVERT10_E_OLESTREAM_GET (CONVERT10_E_FIRST + 0)
+
+// OLESTREAM Put method failed
+#define CONVERT10_E_OLESTREAM_PUT (CONVERT10_E_FIRST + 1)
+
+// Contents of the OLESTREAM not in correct format
+#define CONVERT10_E_OLESTREAM_FMT (CONVERT10_E_FIRST + 2)
+
+// There was in an error in a Windows GDI call while converting the bitmap
+// to a DIB.
+#define CONVERT10_E_OLESTREAM_BITMAP_TO_DIB (CONVERT10_E_FIRST + 3)
+
+// Contents of the IStorage not in correct format
+#define CONVERT10_E_STG_FMT (CONVERT10_E_FIRST + 4)
+
+// Contents of IStorage is missing one of the standard streams ("\1CompObj",
+// "\1Ole", "\2OlePres000"). This may be the storage for a DLL object, or a
+// class that does not use the def handler.
+#define CONVERT10_E_STG_NO_STD_STREAM (CONVERT10_E_FIRST + 5)
+
+// There was in an error in a Windows GDI call while converting the DIB
+// to a bitmap.
+#define CONVERT10_E_STG_DIB_TO_BITMAP (CONVERT10_E_FIRST + 6)
+
+
+// Returned by either API, this scode indicates that the original object
+// had no presentation, therefore the converted object does not either.
+#define CONVERT10_S_NO_PRESENTATION (CONVERT10_S_FIRST + 0)
+
+
+// Errors for Clipboard functions
+
+// OpenClipboard Failed
+#define CLIPBRD_E_CANT_OPEN (CLIPBRD_E_FIRST + 0)
+
+// EmptyClipboard Failed
+#define CLIPBRD_E_CANT_EMPTY (CLIPBRD_E_FIRST + 1)
+
+// SetClipboard Failed
+#define CLIPBRD_E_CANT_SET (CLIPBRD_E_FIRST + 2)
+
+// Data on clipboard is invalid
+#define CLIPBRD_E_BAD_DATA (CLIPBRD_E_FIRST + 3)
+
+// CloseClipboard Failed
+#define CLIPBRD_E_CANT_CLOSE (CLIPBRD_E_FIRST + 4)
+
+
+/****** OLE value types *****************************************************/
+
+/* rendering options */
+typedef enum tagOLERENDER
+{
+ OLERENDER_NONE = 0,
+ OLERENDER_DRAW = 1,
+ OLERENDER_FORMAT = 2,
+ OLERENDER_ASIS = 3
+} OLERENDER;
+typedef OLERENDER FAR* LPOLERENDER;
+
+// OLE verb; returned by IEnumOLEVERB
+typedef struct FARSTRUCT tagOLEVERB
+{
+ LONG lVerb;
+ LPSTR lpszVerbName;
+ DWORD fuFlags;
+ DWORD grfAttribs;
+} OLEVERB, FAR* LPOLEVERB;
+
+
+// Bitwise verb attributes used in OLEVERB.grfAttribs
+typedef enum tagOLEVERBATTRIB // bitwise
+{
+ OLEVERBATTRIB_NEVERDIRTIES = 1,
+ OLEVERBATTRIB_ONCONTAINERMENU = 2
+} OLEVERBATTRIB;
+
+
+// IOleObject::GetUserType optons; determines which form of the string to use
+typedef enum tagUSERCLASSTYPE
+{
+ USERCLASSTYPE_FULL = 1,
+ USERCLASSTYPE_SHORT= 2,
+ USERCLASSTYPE_APPNAME= 3,
+} USERCLASSTYPE;
+
+
+// bits returned from IOleObject::GetMistStatus
+typedef enum tagOLEMISC // bitwise
+{
+ OLEMISC_RECOMPOSEONRESIZE = 1,
+ OLEMISC_ONLYICONIC = 2,
+ OLEMISC_INSERTNOTREPLACE = 4,
+ OLEMISC_STATIC = 8,
+ OLEMISC_CANTLINKINSIDE = 16,
+ OLEMISC_CANLINKBYOLE1 = 32,
+ OLEMISC_ISLINKOBJECT = 64,
+ OLEMISC_INSIDEOUT = 128,
+ OLEMISC_ACTIVATEWHENVISIBLE = 256,
+ OLEMISC_RENDERINGISDEVICEINDEPENDENT = 512
+} OLEMISC;
+
+
+// IOleObject::Close options
+typedef enum tagOLECLOSE
+{
+ OLECLOSE_SAVEIFDIRTY = 0,
+ OLECLOSE_NOSAVE = 1,
+ OLECLOSE_PROMPTSAVE = 2
+} OLECLOSE;
+
+
+// IOleObject::GetMoniker and IOleClientSite::GetMoniker options; determines
+// if and how monikers should be assigned.
+typedef enum tagOLEGETMONIKER
+{
+ OLEGETMONIKER_ONLYIFTHERE=1,
+ OLEGETMONIKER_FORCEASSIGN=2,
+ OLEGETMONIKER_UNASSIGN=3,
+ OLEGETMONIKER_TEMPFORUSER=4
+} OLEGETMONIKER;
+
+
+// IOleObject::GetMoniker, IOleObject::SetMoniker and
+// IOleClientSite::GetMoniker options; determines which moniker to use
+typedef enum tagOLEWHICHMK
+{
+ OLEWHICHMK_CONTAINER=1,
+ OLEWHICHMK_OBJREL=2,
+ OLEWHICHMK_OBJFULL=3
+} OLEWHICHMK;
+
+
+#ifdef WIN32
+#define LPSIZEL PSIZEL
+#else
+typedef struct FARSTRUCT tagSIZEL
+{
+ long cx;
+ long cy;
+} SIZEL, FAR* LPSIZEL;
+#endif
+
+
+#ifdef WIN32
+#define LPRECTL PRECTL
+#else
+typedef struct FARSTRUCT tagRECTL
+{
+ long left;
+ long top;
+ long right;
+ long bottom;
+} RECTL, FAR* LPRECTL;
+
+typedef struct FARSTRUCT tagPOINTL {
+ LONG x;
+ LONG y;
+} POINTL;
+
+#endif
+
+
+#ifndef LPCRECT
+typedef const RECT FAR* LPCRECT;
+#endif
+
+#ifndef LPCRECTL
+typedef const RECTL FAR* LPCRECTL;
+#endif
+
+
+// for OleCreateEmbeddingHelper flags; roles in low word; options in high word
+#define EMBDHLP_INPROC_HANDLER 0x0000L // role is handler; implementation is
+ // default handler; pCF can be NULL
+#define EMBDHLP_INPROC_SERVER 0x0001L // role is server; pCF can't be NULL
+
+#define EMBDHLP_CREATENOW 0x00000000L // create using pCF immediately; if pCF
+ // is NULL, uses std remoting handler
+#define EMBDHLP_DELAYCREATE 0x00010000L // delayed create; must supply pCF
+
+
+// NOTE: OleCreateEmbeddingHelper(clsid, pUnkOuter,
+// EMBDHLP_INPROC_HANDLER | EMBDHLP_CREATENOW, NULL, riid, lplpObj)
+// is the same as OleCreateDefaultHandler(clsid, pUnkOuter, riid, lplpObj);
+// i.e., the embedding helper is the default handler in various roles.
+
+
+/***** OLE 1.0 OLESTREAM declarations *************************************/
+
+typedef struct _OLESTREAM FAR* LPOLESTREAM;
+
+typedef struct _OLESTREAMVTBL
+{
+ DWORD (CALLBACK* Get)(LPOLESTREAM, void FAR*, DWORD);
+ DWORD (CALLBACK* Put)(LPOLESTREAM, const void FAR*, DWORD);
+} OLESTREAMVTBL;
+typedef OLESTREAMVTBL FAR* LPOLESTREAMVTBL;
+
+typedef struct _OLESTREAM
+{
+ LPOLESTREAMVTBL lpstbl;
+} OLESTREAM;
+
+
+/****** Clipboard Data structures *****************************************/
+
+typedef struct tagOBJECTDESCRIPTOR
+{
+ ULONG cbSize; // Size of structure in bytes
+ CLSID clsid; // CLSID of data being transferred
+ DWORD dwDrawAspect; // Display aspect of the object
+ // normally DVASPECT_CONTENT or ICON.
+ // dwDrawAspect will be 0 (which is NOT
+ // DVASPECT_CONTENT) if the copier or
+ // dragsource didn't draw the object to
+ // begin with.
+ SIZEL sizel; // size of the object in HIMETRIC
+ // sizel is opt.: will be (0,0) for apps
+ // which don't draw the object being
+ // transferred
+ POINTL pointl; // Offset in HIMETRIC units from the
+ // upper-left corner of the obj where the
+ // mouse went down for the drag.
+ // NOTE: y coordinates increase downward.
+ // x coordinates increase to right
+ // pointl is opt.; it is only meaningful
+ // if object is transfered via drag/drop.
+ // (0, 0) if mouse position is unspecified
+ // (eg. when obj transfered via clipboard)
+ DWORD dwStatus; // Misc. status flags for object. Flags are
+ // defined by OLEMISC enum. these flags
+ // are as would be returned
+ // by IOleObject::GetMiscStatus.
+ DWORD dwFullUserTypeName; // Offset from beginning of structure to
+ // null-terminated string that specifies
+ // Full User Type Name of the object.
+ // 0 indicates string not present.
+ DWORD dwSrcOfCopy; // Offset from beginning of structure to
+ // null-terminated string that specifies
+ // source of the transfer.
+ // dwSrcOfCOpy is normally implemented as
+ // the display name of the temp-for-user
+ // moniker which identifies the source of
+ // the data.
+ // 0 indicates string not present.
+ // NOTE: moniker assignment is NOT forced.
+ // see IOleObject::GetMoniker(
+ // OLEGETMONIKER_TEMPFORUSER)
+
+ /* variable sized string data may appear here */
+
+} OBJECTDESCRIPTOR, *POBJECTDESCRIPTOR, FAR *LPOBJECTDESCRIPTOR,
+ LINKSRCDESCRIPTOR, *PLINKSRCDESCRIPTOR, FAR *LPLINKSRCDESCRIPTOR;
+
+
+
+/* verbs */
+#define OLEIVERB_PRIMARY (0L)
+#define OLEIVERB_SHOW (-1L)
+#define OLEIVERB_OPEN (-2L)
+#define OLEIVERB_HIDE (-3L)
+#define OLEIVERB_UIACTIVATE (-4L)
+#define OLEIVERB_INPLACEACTIVATE (-5L)
+#define OLEIVERB_DISCARDUNDOSTATE (-6L)
+
+
+// forward type declarations
+#if defined(__cplusplus)
+interface IOleClientSite;
+interface IOleContainer;
+interface IOleObject;
+#else
+typedef interface IOleClientSite IOleClientSite;
+typedef interface IOleContainer IOleContainer;
+typedef interface IOleObject IOleObject;
+#endif
+
+typedef IOleObject FAR* LPOLEOBJECT;
+typedef IOleClientSite FAR* LPOLECLIENTSITE;
+typedef IOleContainer FAR* LPOLECONTAINER;
+
+
+/****** OLE GUIDs *********************************************************/
+
+#ifndef INITGUID
+#include "oleguid.h"
+#endif
+
+
+/****** Other Major Interfaces ********************************************/
+
+#include <dvobj.h>
+
+#include <storage.h>
+
+
+
+/****** IDrop??? Interfaces ********************************************/
+
+#define MK_ALT 0x0020
+
+
+#define DROPEFFECT_NONE 0
+#define DROPEFFECT_COPY 1
+#define DROPEFFECT_MOVE 2
+#define DROPEFFECT_LINK 4
+#define DROPEFFECT_SCROLL 0x80000000
+
+// default inset-width of the hot zone, in pixels
+// typical use: GetProfileInt("windows","DragScrollInset",DD_DEFSCROLLINSET)
+#define DD_DEFSCROLLINSET 11
+
+// default delay before scrolling, in milliseconds
+// typical use: GetProfileInt("windows","DragScrollDelay",DD_DEFSCROLLDELAY)
+#define DD_DEFSCROLLDELAY 50
+
+// default scroll interval, in milliseconds
+// typical use: GetProfileInt("windows","DragScrollInterval",
+// DD_DEFSCROLLINTERVAL)
+#define DD_DEFSCROLLINTERVAL 50
+
+// default delay before dragging should start, in milliseconds
+// typical use: GetProfileInt("windows", "DragDelay", DD_DEFDRAGDELAY)
+#define DD_DEFDRAGDELAY 200
+
+// default minimum distance (radius) before dragging should start, in pixels
+// typical use: GetProfileInt("windows", "DragMinDist", DD_DEFDRAGMINDIST)
+#define DD_DEFDRAGMINDIST 2
+
+
+
+/* Dragdrop specific error codes */
+
+#define DRAGDROP_E_NOTREGISTERED (DRAGDROP_E_FIRST)
+// trying to revoke a drop target that has not been registered
+
+#define DRAGDROP_E_ALREADYREGISTERED (DRAGDROP_E_FIRST+1)
+// this window has already been registered as a drop target
+
+#define DRAGDROP_E_INVALIDHWND (DRAGDROP_E_FIRST+2)
+// invalid HWND
+
+
+#define DRAGDROP_S_DROP (DRAGDROP_S_FIRST + 0)
+// successful drop took place
+
+#define DRAGDROP_S_CANCEL (DRAGDROP_S_FIRST + 1)
+// drag-drop operation canceled
+
+#define DRAGDROP_S_USEDEFAULTCURSORS (DRAGDROP_S_FIRST + 2)
+// use the default cursor
+
+
+#undef INTERFACE
+#define INTERFACE IDropTarget
+
+DECLARE_INTERFACE_(IDropTarget, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IDropTarget methods ***
+ STDMETHOD(DragEnter) (THIS_ LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) PURE;
+ STDMETHOD(DragOver) (THIS_ DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) PURE;
+ STDMETHOD(DragLeave) (THIS) PURE;
+ STDMETHOD(Drop) (THIS_ LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) PURE;
+};
+typedef IDropTarget FAR* LPDROPTARGET;
+
+
+
+#undef INTERFACE
+#define INTERFACE IDropSource
+
+DECLARE_INTERFACE_(IDropSource, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IDropSource methods ***
+ STDMETHOD(QueryContinueDrag) (THIS_ BOOL fEscapePressed, DWORD grfKeyState) PURE;
+ STDMETHOD(GiveFeedback) (THIS_ DWORD dwEffect) PURE;
+};
+typedef IDropSource FAR* LPDROPSOURCE;
+
+
+
+/****** IPersist??? Interfaces ********************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IPersist
+
+DECLARE_INTERFACE_(IPersist, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+};
+typedef IPersist FAR* LPPERSIST;
+
+
+
+#undef INTERFACE
+#define INTERFACE IPersistStorage
+
+DECLARE_INTERFACE_(IPersistStorage, IPersist)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+
+ // *** IPersistStorage methods ***
+ STDMETHOD(IsDirty) (THIS) PURE;
+ STDMETHOD(InitNew) (THIS_ LPSTORAGE pStg) PURE;
+ STDMETHOD(Load) (THIS_ LPSTORAGE pStg) PURE;
+ STDMETHOD(Save) (THIS_ LPSTORAGE pStgSave, BOOL fSameAsLoad) PURE;
+ STDMETHOD(SaveCompleted) (THIS_ LPSTORAGE pStgNew) PURE;
+ STDMETHOD(HandsOffStorage) (THIS) PURE;
+};
+typedef IPersistStorage FAR* LPPERSISTSTORAGE;
+
+
+
+#undef INTERFACE
+#define INTERFACE IPersistStream
+
+DECLARE_INTERFACE_(IPersistStream, IPersist)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+
+ // *** IPersistStream methods ***
+ STDMETHOD(IsDirty) (THIS) PURE;
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm) PURE;
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty) PURE;
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR* pcbSize) PURE;
+};
+typedef IPersistStream FAR* LPPERSISTSTREAM;
+
+
+
+#undef INTERFACE
+#define INTERFACE IPersistFile
+
+DECLARE_INTERFACE_(IPersistFile, IPersist)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+
+ // *** IPersistFile methods ***
+ STDMETHOD(IsDirty) (THIS) PURE;
+ STDMETHOD(Load) (THIS_ LPCSTR lpszFileName, DWORD grfMode) PURE;
+ STDMETHOD(Save) (THIS_ LPCSTR lpszFileName, BOOL fRemember) PURE;
+ STDMETHOD(SaveCompleted) (THIS_ LPCSTR lpszFileName) PURE;
+ STDMETHOD(GetCurFile) (THIS_ LPSTR FAR* lplpszFileName) PURE;
+};
+typedef IPersistFile FAR* LPPERSISTFILE;
+
+
+/****** Moniker Object Interfaces ******************************************/
+
+#include <moniker.h>
+
+
+/****** OLE Object Interfaces ******************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IEnumOLEVERB
+
+DECLARE_INTERFACE_(IEnumOLEVERB, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumOLEVERB methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, LPOLEVERB rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumOLEVERB FAR* FAR* ppenm) PURE;
+};
+typedef IEnumOLEVERB FAR* LPENUMOLEVERB;
+
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleObject
+
+#define OLEOBJ_E_NOVERBS (OLEOBJ_E_FIRST + 0)
+
+#define OLEOBJ_E_INVALIDVERB (OLEOBJ_E_FIRST + 1)
+
+#define OLEOBJ_S_INVALIDVERB (OLEOBJ_S_FIRST + 0)
+
+#define OLEOBJ_S_CANNOT_DOVERB_NOW (OLEOBJ_S_FIRST + 1)
+// verb number is valid but verb cannot be done now, for instance
+// hiding a link or hiding a visible OLE 1.0 server
+
+#define OLEOBJ_S_INVALIDHWND (OLEOBJ_S_FIRST + 2)
+// invalid hwnd passed
+
+
+DECLARE_INTERFACE_(IOleObject, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleObject methods ***
+ STDMETHOD(SetClientSite) (THIS_ LPOLECLIENTSITE pClientSite) PURE;
+ STDMETHOD(GetClientSite) (THIS_ LPOLECLIENTSITE FAR* ppClientSite) PURE;
+ STDMETHOD(SetHostNames) (THIS_ LPCSTR szContainerApp, LPCSTR szContainerObj) PURE;
+ STDMETHOD(Close) (THIS_ DWORD dwSaveOption) PURE;
+ STDMETHOD(SetMoniker) (THIS_ DWORD dwWhichMoniker, LPMONIKER pmk) PURE;
+ STDMETHOD(GetMoniker) (THIS_ DWORD dwAssign, DWORD dwWhichMoniker,
+ LPMONIKER FAR* ppmk) PURE;
+ STDMETHOD(InitFromData) (THIS_ LPDATAOBJECT pDataObject,
+ BOOL fCreation,
+ DWORD dwReserved) PURE;
+ STDMETHOD(GetClipboardData) (THIS_ DWORD dwReserved,
+ LPDATAOBJECT FAR* ppDataObject) PURE;
+ STDMETHOD(DoVerb) (THIS_ LONG iVerb,
+ LPMSG lpmsg,
+ LPOLECLIENTSITE pActiveSite,
+ LONG lindex,
+ HWND hwndParent,
+ LPCRECT lprcPosRect) PURE;
+ STDMETHOD(EnumVerbs) (THIS_ LPENUMOLEVERB FAR* ppenumOleVerb) PURE;
+ STDMETHOD(Update) (THIS) PURE;
+ STDMETHOD(IsUpToDate) (THIS) PURE;
+ STDMETHOD(GetUserClassID) (THIS_ CLSID FAR* pClsid) PURE;
+ STDMETHOD(GetUserType) (THIS_ DWORD dwFormOfType, LPSTR FAR* pszUserType) PURE;
+ STDMETHOD(SetExtent) (THIS_ DWORD dwDrawAspect, LPSIZEL lpsizel) PURE;
+ STDMETHOD(GetExtent) (THIS_ DWORD dwDrawAspect, LPSIZEL lpsizel) PURE;
+
+ STDMETHOD(Advise)(THIS_ LPADVISESINK pAdvSink, DWORD FAR* pdwConnection) PURE;
+ STDMETHOD(Unadvise)(THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumAdvise) (THIS_ LPENUMSTATDATA FAR* ppenumAdvise) PURE;
+ STDMETHOD(GetMiscStatus) (THIS_ DWORD dwAspect, DWORD FAR* pdwStatus) PURE;
+ STDMETHOD(SetColorScheme) (THIS_ LPLOGPALETTE lpLogpal) PURE;
+};
+typedef IOleObject FAR* LPOLEOBJECT;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleClientSite
+
+DECLARE_INTERFACE_(IOleClientSite, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleClientSite methods ***
+ STDMETHOD(SaveObject) (THIS) PURE;
+ STDMETHOD(GetMoniker) (THIS_ DWORD dwAssign, DWORD dwWhichMoniker,
+ LPMONIKER FAR* ppmk) PURE;
+ STDMETHOD(GetContainer) (THIS_ LPOLECONTAINER FAR* ppContainer) PURE;
+ STDMETHOD(ShowObject) (THIS) PURE;
+ STDMETHOD(OnShowWindow) (THIS_ BOOL fShow) PURE;
+ STDMETHOD(RequestNewObjectLayout) (THIS) PURE;
+};
+typedef IOleClientSite FAR* LPOLECLIENTSITE;
+
+
+/****** OLE Runnable Object Interface **********************************/
+
+#undef INTERFACE
+#define INTERFACE IRunnableObject
+
+DECLARE_INTERFACE_(IRunnableObject, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IRunnableObject methods ***
+ STDMETHOD(GetRunningClass) (THIS_ LPCLSID lpClsid) PURE;
+ STDMETHOD(Run) (THIS_ LPBINDCTX pbc) PURE;
+ STDMETHOD_(BOOL, IsRunning) (THIS) PURE;
+ STDMETHOD(LockRunning)(THIS_ BOOL fLock, BOOL fLastUnlockCloses) PURE;
+ STDMETHOD(SetContainedObject)(THIS_ BOOL fContained) PURE;
+};
+typedef IRunnableObject FAR* LPRUNNABLEOBJECT;
+
+
+/****** OLE Container Interfaces ***************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IParseDisplayName
+
+DECLARE_INTERFACE_(IParseDisplayName, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IParseDisplayName method ***
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPSTR lpszDisplayName,
+ ULONG FAR* pchEaten, LPMONIKER FAR* ppmkOut) PURE;
+};
+typedef IParseDisplayName FAR* LPPARSEDISPLAYNAME;
+
+
+#undef INTERFACE
+#define INTERFACE IOleContainer
+
+DECLARE_INTERFACE_(IOleContainer, IParseDisplayName)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IParseDisplayName method ***
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPSTR lpszDisplayName,
+ ULONG FAR* pchEaten, LPMONIKER FAR* ppmkOut) PURE;
+
+ // *** IOleContainer methods ***
+ STDMETHOD(EnumObjects) ( DWORD grfFlags, LPENUMUNKNOWN FAR* ppenumUnknown) PURE;
+ STDMETHOD(LockContainer) (THIS_ BOOL fLock) PURE;
+};
+typedef IOleContainer FAR* LPOLECONTAINER;
+
+
+typedef enum tagBINDSPEED
+{
+ BINDSPEED_INDEFINITE = 1,
+ BINDSPEED_MODERATE = 2,
+ BINDSPEED_IMMEDIATE = 3
+} BINDSPEED;
+
+typedef enum tagOLECONTF
+{
+ OLECONTF_EMBEDDINGS = 1,
+ OLECONTF_LINKS = 2,
+ OLECONTF_OTHERS = 4,
+ OLECONTF_ONLYUSER = 8,
+ OLECONTF_ONLYIFRUNNING = 16
+} OLECONTF;
+
+
+#undef INTERFACE
+#define INTERFACE IOleItemContainer
+
+DECLARE_INTERFACE_(IOleItemContainer, IOleContainer)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IParseDisplayName method ***
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPSTR lpszDisplayName,
+ ULONG FAR* pchEaten, LPMONIKER FAR* ppmkOut) PURE;
+
+ // *** IOleContainer methods ***
+ STDMETHOD(EnumObjects) (THIS_ DWORD grfFlags, LPENUMUNKNOWN FAR* ppenumUnknown) PURE;
+ STDMETHOD(LockContainer) (THIS_ BOOL fLock) PURE;
+
+ // *** IOleItemContainer methods ***
+ STDMETHOD(GetObject) (THIS_ LPSTR lpszItem, DWORD dwSpeedNeeded,
+ LPBINDCTX pbc, REFIID riid, LPVOID FAR* ppvObject) PURE;
+ STDMETHOD(GetObjectStorage) (THIS_ LPSTR lpszItem, LPBINDCTX pbc,
+ REFIID riid, LPVOID FAR* ppvStorage) PURE;
+ STDMETHOD(IsRunning) (THIS_ LPSTR lpszItem) PURE;
+};
+typedef IOleItemContainer FAR* LPOLEITEMCONTAINER;
+
+
+/****** OLE Advise Holder Interface ***************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IOleAdviseHolder
+
+DECLARE_INTERFACE_(IOleAdviseHolder, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleAdviseHolder methods ***
+ STDMETHOD(Advise)(THIS_ LPADVISESINK pAdvise, DWORD FAR* pdwConnection) PURE;
+ STDMETHOD(Unadvise)(THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumAdvise)(THIS_ LPENUMSTATDATA FAR* ppenumAdvise) PURE;
+
+ STDMETHOD(SendOnRename)(THIS_ LPMONIKER pmk) PURE;
+ STDMETHOD(SendOnSave)(THIS) PURE;
+ STDMETHOD(SendOnClose)(THIS) PURE;
+};
+typedef IOleAdviseHolder FAR* LPOLEADVISEHOLDER;
+
+
+/****** OLE Link Interface ************************************************/
+
+/* Link update options */
+typedef enum tagOLEUPDATE
+{
+ OLEUPDATE_ALWAYS=1,
+ OLEUPDATE_ONCALL=3
+} OLEUPDATE;
+typedef OLEUPDATE FAR* LPOLEUPDATE;
+
+
+// for IOleLink::BindToSource
+typedef enum tagOLELINKBIND
+{
+ OLELINKBIND_EVENIFCLASSDIFF = 1,
+} OLELINKBIND;
+
+
+#undef INTERFACE
+#define INTERFACE IOleLink
+
+DECLARE_INTERFACE_(IOleLink, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleLink methods ***
+ STDMETHOD(SetUpdateOptions) (THIS_ DWORD dwUpdateOpt) PURE;
+ STDMETHOD(GetUpdateOptions) (THIS_ LPDWORD pdwUpdateOpt) PURE;
+ STDMETHOD(SetSourceMoniker) (THIS_ LPMONIKER pmk, REFCLSID rclsid) PURE;
+ STDMETHOD(GetSourceMoniker) (THIS_ LPMONIKER FAR* ppmk) PURE;
+ STDMETHOD(SetSourceDisplayName) (THIS_ LPCSTR lpszDisplayName) PURE;
+ STDMETHOD(GetSourceDisplayName) (THIS_ LPSTR FAR* lplpszDisplayName) PURE;
+ STDMETHOD(BindToSource) (THIS_ DWORD bindflags, LPBINDCTX pbc) PURE;
+ STDMETHOD(BindIfRunning) (THIS) PURE;
+ STDMETHOD(GetBoundSource) (THIS_ LPUNKNOWN FAR* ppUnk) PURE;
+ STDMETHOD(UnbindSource) (THIS) PURE;
+ STDMETHOD(Update) (THIS_ LPBINDCTX pbc) PURE;
+};
+typedef IOleLink FAR* LPOLELINK;
+
+
+/****** OLE InPlace Editing Interfaces ************************************/
+
+#ifdef _MAC
+typedef Handle HOLEMENU;
+typedef long SIZE;
+typedef long HACCEL;
+#else
+DECLARE_HANDLE(HOLEMENU);
+#endif
+
+typedef struct FARSTRUCT tagOIFI // OleInPlaceFrameInfo
+{
+ UINT cb;
+ BOOL fMDIApp;
+ HWND hwndFrame;
+ HACCEL haccel;
+ int cAccelEntries;
+} OLEINPLACEFRAMEINFO, FAR* LPOLEINPLACEFRAMEINFO;
+
+
+typedef struct FARSTRUCT tagOleMenuGroupWidths
+{
+ LONG width[6];
+} OLEMENUGROUPWIDTHS, FAR* LPOLEMENUGROUPWIDTHS;
+
+typedef RECT BORDERWIDTHS;
+typedef LPRECT LPBORDERWIDTHS;
+typedef LPCRECT LPCBORDERWIDTHS;
+
+/* Inplace editing specific error codes */
+
+#define INPLACE_E_NOTUNDOABLE (INPLACE_E_FIRST)
+// undo is not avaiable
+
+#define INPLACE_E_NOTOOLSPACE (INPLACE_E_FIRST+1)
+// Space for tools is not available
+
+#define INPLACE_S_TRUNCATED (INPLACE_S_FIRST)
+// Message is too long, some of it had to be truncated before displaying
+
+//misc definitions
+#define INPLACE_DEFBORDERWIDTH 4
+
+// forward type declarations
+#if defined(__cplusplus)
+interface IOleInPlaceUIWindow;
+#else
+typedef interface IOleInPlaceUIWindow IOleInPlaceUIWindow;
+#endif
+
+typedef IOleInPlaceUIWindow FAR* LPOLEINPLACEUIWINDOW;
+
+
+#undef INTERFACE
+#define INTERFACE IOleWindow
+
+DECLARE_INTERFACE_(IOleWindow, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+};
+
+typedef IOleWindow FAR* LPOLEWINDOW;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceObject
+
+DECLARE_INTERFACE_(IOleInPlaceObject, IOleWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceObject methods ***
+ STDMETHOD(InPlaceDeactivate) (THIS) PURE;
+ STDMETHOD(UIDeactivate) (THIS) PURE;
+ STDMETHOD(SetObjectRects) (THIS_ LPCRECT lprcPosRect,
+ LPCRECT lprcClipRect) PURE;
+ STDMETHOD(ReactivateAndUndo) (THIS) PURE;
+};
+typedef IOleInPlaceObject FAR* LPOLEINPLACEOBJECT;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceActiveObject
+
+DECLARE_INTERFACE_(IOleInPlaceActiveObject, IOleWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceActiveObject methods ***
+ STDMETHOD(TranslateAccelerator) (THIS_ LPMSG lpmsg) PURE;
+ STDMETHOD(OnFrameWindowActivate) (THIS_ BOOL fActivate) PURE;
+ STDMETHOD(OnDocWindowActivate) (THIS_ BOOL fActivate) PURE;
+ STDMETHOD(ResizeBorder) (THIS_ LPCRECT lprectBorder, LPOLEINPLACEUIWINDOW lpUIWindow, BOOL fFrameWindow) PURE;
+ STDMETHOD(EnableModeless) (THIS_ BOOL fEnable) PURE;
+};
+typedef IOleInPlaceActiveObject FAR* LPOLEINPLACEACTIVEOBJECT;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceUIWindow
+
+DECLARE_INTERFACE_(IOleInPlaceUIWindow, IOleWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceUIWindow methods ***
+ STDMETHOD(GetBorder) (THIS_ LPRECT lprectBorder) PURE;
+ STDMETHOD(RequestBorderSpace) (THIS_ LPCBORDERWIDTHS lpborderwidths) PURE;
+ STDMETHOD(SetBorderSpace) (THIS_ LPCBORDERWIDTHS lpborderwidths) PURE;
+ STDMETHOD(SetActiveObject) (THIS_ LPOLEINPLACEACTIVEOBJECT lpActiveObject,
+ LPCSTR lpszObjName) PURE;
+};
+typedef IOleInPlaceUIWindow FAR* LPOLEINPLACEUIWINDOW;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceFrame
+
+DECLARE_INTERFACE_(IOleInPlaceFrame, IOleInPlaceUIWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceUIWindow methods ***
+ STDMETHOD(GetBorder) (THIS_ LPRECT lprectBorder) PURE;
+ STDMETHOD(RequestBorderSpace) (THIS_ LPCBORDERWIDTHS lpborderwidths) PURE;
+ STDMETHOD(SetBorderSpace) (THIS_ LPCBORDERWIDTHS lpborderwidths) PURE;
+ STDMETHOD(SetActiveObject) (THIS_ LPOLEINPLACEACTIVEOBJECT lpActiveObject,
+ LPCSTR lpszObjName) PURE;
+
+
+ // *** IOleInPlaceFrame methods ***
+ STDMETHOD(InsertMenus) (THIS_ HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) PURE;
+ STDMETHOD(SetMenu) (THIS_ HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) PURE;
+ STDMETHOD(RemoveMenus) (THIS_ HMENU hmenuShared) PURE;
+ STDMETHOD(SetStatusText) (THIS_ LPCSTR lpszStatusText) PURE;
+ STDMETHOD(EnableModeless) (THIS_ BOOL fEnable) PURE;
+ STDMETHOD(TranslateAccelerator) (THIS_ LPMSG lpmsg, WORD wID) PURE;
+};
+typedef IOleInPlaceFrame FAR* LPOLEINPLACEFRAME;
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceSite
+
+DECLARE_INTERFACE_(IOleInPlaceSite, IOleWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceSite methods ***
+ STDMETHOD(CanInPlaceActivate) (THIS) PURE;
+ STDMETHOD(OnInPlaceActivate) (THIS) PURE;
+ STDMETHOD(OnUIActivate) (THIS) PURE;
+ STDMETHOD(GetWindowContext) (THIS_ LPOLEINPLACEFRAME FAR* lplpFrame,
+ LPOLEINPLACEUIWINDOW FAR* lplpDoc,
+ LPRECT lprcPosRect,
+ LPRECT lprcClipRect,
+ LPOLEINPLACEFRAMEINFO lpFrameInfo) PURE;
+ STDMETHOD(Scroll) (THIS_ SIZE scrollExtent) PURE;
+ STDMETHOD(OnUIDeactivate) (THIS_ BOOL fUndoable) PURE;
+ STDMETHOD(OnInPlaceDeactivate) (THIS) PURE;
+ STDMETHOD(DiscardUndoState) (THIS) PURE;
+ STDMETHOD(DeactivateAndUndo) (THIS) PURE;
+ STDMETHOD(OnPosRectChange) (THIS_ LPCRECT lprcPosRect) PURE;
+};
+typedef IOleInPlaceSite FAR* LPOLEINPLACESITE;
+
+
+
+/****** OLE API Prototypes ************************************************/
+
+STDAPI_(DWORD) OleBuildVersion( VOID );
+
+/* helper functions */
+STDAPI ReadClassStg(LPSTORAGE pStg, CLSID FAR* pclsid);
+STDAPI WriteClassStg(LPSTORAGE pStg, REFCLSID rclsid);
+STDAPI ReadClassStm(LPSTREAM pStm, CLSID FAR* pclsid);
+STDAPI WriteClassStm(LPSTREAM pStm, REFCLSID rclsid);
+STDAPI WriteFmtUserTypeStg (LPSTORAGE pstg, CLIPFORMAT cf, LPSTR lpszUserType);
+STDAPI ReadFmtUserTypeStg (LPSTORAGE pstg, CLIPFORMAT FAR* pcf, LPSTR FAR* lplpszUserType);
+
+
+/* init/term */
+
+STDAPI OleInitialize(LPMALLOC pMalloc);
+STDAPI_(void) OleUninitialize(void);
+
+
+/* APIs to query whether (Embedded/Linked) object can be created from
+ the data object */
+
+STDAPI OleQueryLinkFromData(LPDATAOBJECT pSrcDataObject);
+STDAPI OleQueryCreateFromData(LPDATAOBJECT pSrcDataObject);
+
+
+/* Object creation APIs */
+
+STDAPI OleCreate(REFCLSID rclsid, REFIID riid, DWORD renderopt,
+ LPFORMATETC pFormatEtc, LPOLECLIENTSITE pClientSite,
+ LPSTORAGE pStg, LPVOID FAR* ppvObj);
+
+STDAPI OleCreateFromData(LPDATAOBJECT pSrcDataObj, REFIID riid,
+ DWORD renderopt, LPFORMATETC pFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
+ LPVOID FAR* ppvObj);
+
+STDAPI OleCreateLinkFromData(LPDATAOBJECT pSrcDataObj, REFIID riid,
+ DWORD renderopt, LPFORMATETC pFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
+ LPVOID FAR* ppvObj);
+
+STDAPI OleCreateStaticFromData(LPDATAOBJECT pSrcDataObj, REFIID iid,
+ DWORD renderopt, LPFORMATETC pFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
+ LPVOID FAR* ppvObj);
+
+
+STDAPI OleCreateLink(LPMONIKER pmkLinkSrc, REFIID riid,
+ DWORD renderopt, LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg, LPVOID FAR* ppvObj);
+
+STDAPI OleCreateLinkToFile(LPCSTR lpszFileName, REFIID riid,
+ DWORD renderopt, LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg, LPVOID FAR* ppvObj);
+
+STDAPI OleCreateFromFile(REFCLSID rclsid, LPCSTR lpszFileName, REFIID riid,
+ DWORD renderopt, LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg, LPVOID FAR* ppvObj);
+
+STDAPI OleLoad(LPSTORAGE pStg, REFIID riid, LPOLECLIENTSITE pClientSite,
+ LPVOID FAR* ppvObj);
+
+STDAPI OleSave(LPPERSISTSTORAGE pPS, LPSTORAGE pStg, BOOL fSameAsLoad);
+
+STDAPI OleLoadFromStream( LPSTREAM pStm, REFIID iidInterface, LPVOID FAR* ppvObj);
+STDAPI OleSaveToStream( LPPERSISTSTREAM pPStm, LPSTREAM pStm );
+
+
+STDAPI OleSetContainedObject(LPUNKNOWN pUnknown, BOOL fContained);
+STDAPI OleNoteObjectVisible(LPUNKNOWN pUnknown, BOOL fVisible);
+
+
+/* Drag/Drop APIs */
+
+STDAPI RegisterDragDrop(HWND hwnd, LPDROPTARGET pDropTarget);
+STDAPI RevokeDragDrop(HWND hwnd);
+STDAPI DoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
+ DWORD dwOKEffects, LPDWORD pdwEffect);
+
+/* Clipboard APIs */
+
+STDAPI OleSetClipboard(LPDATAOBJECT pDataObj);
+STDAPI OleGetClipboard(LPDATAOBJECT FAR* ppDataObj);
+STDAPI OleFlushClipboard(void);
+STDAPI OleIsCurrentClipboard(LPDATAOBJECT pDataObj);
+
+
+/* InPlace Editing APIs */
+
+STDAPI_(HOLEMENU) OleCreateMenuDescriptor (HMENU hmenuCombined,
+ LPOLEMENUGROUPWIDTHS lpMenuWidths);
+STDAPI OleSetMenuDescriptor (HOLEMENU holemenu, HWND hwndFrame,
+ HWND hwndActiveObject,
+ LPOLEINPLACEFRAME lpFrame,
+ LPOLEINPLACEACTIVEOBJECT lpActiveObj);
+STDAPI OleDestroyMenuDescriptor (HOLEMENU holemenu);
+
+STDAPI OleTranslateAccelerator (LPOLEINPLACEFRAME lpFrame,
+ LPOLEINPLACEFRAMEINFO lpFrameInfo, LPMSG lpmsg);
+
+
+/* Helper APIs */
+STDAPI_(HANDLE) OleDuplicateData (HANDLE hSrc, CLIPFORMAT cfFormat,
+ UINT uiFlags);
+
+STDAPI OleDraw (LPUNKNOWN pUnknown, DWORD dwAspect, HDC hdcDraw,
+ LPCRECT lprcBounds);
+
+STDAPI OleRun(LPUNKNOWN pUnknown);
+STDAPI_(BOOL) OleIsRunning(LPOLEOBJECT pObject);
+STDAPI OleLockRunning(LPUNKNOWN pUnknown, BOOL fLock, BOOL fLastUnlockCloses);
+
+STDAPI_(void) ReleaseStgMedium(LPSTGMEDIUM);
+STDAPI CreateOleAdviseHolder(LPOLEADVISEHOLDER FAR* ppOAHolder);
+
+STDAPI OleCreateDefaultHandler(REFCLSID clsid, LPUNKNOWN pUnkOuter,
+ REFIID riid, LPVOID FAR* lplpObj);
+
+STDAPI OleCreateEmbeddingHelper(REFCLSID clsid, LPUNKNOWN pUnkOuter,
+ DWORD flags, LPCLASSFACTORY pCF,
+ REFIID riid, LPVOID FAR* lplpObj);
+
+STDAPI_(BOOL) IsAccelerator(HACCEL hAccel, int cAccelEntries, LPMSG lpMsg,
+ WORD FAR* lpwCmd);
+
+
+/* Icon extraction Helper APIs */
+
+STDAPI_(HGLOBAL) OleGetIconOfFile(LPSTR lpszPath, BOOL fUseFileAsLabel);
+
+STDAPI_(HGLOBAL) OleGetIconOfClass(REFCLSID rclsid, LPSTR lpszLabel,
+ BOOL fUseTypeAsLabel);
+
+STDAPI_(HGLOBAL) OleMetafilePictFromIconAndLabel(HICON hIcon, LPSTR lpszLabel,
+ LPSTR lpszSourceFile, UINT iIconIndex);
+
+
+
+/* Registration Database Helper APIs */
+
+STDAPI OleRegGetUserType (REFCLSID clsid, DWORD dwFormOfType,
+ LPSTR FAR* pszUserType);
+
+STDAPI OleRegGetMiscStatus (REFCLSID clsid, DWORD dwAspect,
+ DWORD FAR* pdwStatus);
+
+STDAPI OleRegEnumFormatEtc (REFCLSID clsid, DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenum);
+
+STDAPI OleRegEnumVerbs (REFCLSID clsid, LPENUMOLEVERB FAR* ppenum);
+
+
+
+/* OLE 1.0 conversion APIS */
+
+STDAPI OleConvertIStorageToOLESTREAM
+ (LPSTORAGE pstg,
+ LPOLESTREAM polestm);
+
+STDAPI OleConvertOLESTREAMToIStorage
+ (LPOLESTREAM polestm,
+ LPSTORAGE pstg,
+ const DVTARGETDEVICE FAR* ptd);
+
+STDAPI OleConvertIStorageToOLESTREAMEx
+ (LPSTORAGE pstg,
+ // Presentation data to OLESTREAM
+ CLIPFORMAT cfFormat, // format
+ LONG lWidth, // width
+ LONG lHeight, // height
+ DWORD dwSize, // size in bytes
+ LPSTGMEDIUM pmedium, // bits
+ LPOLESTREAM polestm);
+
+STDAPI OleConvertOLESTREAMToIStorageEx
+ (LPOLESTREAM polestm,
+ LPSTORAGE pstg,
+ // Presentation data from OLESTREAM
+ CLIPFORMAT FAR* pcfFormat, // format
+ LONG FAR* plwWidth, // width
+ LONG FAR* plHeight, // height
+ DWORD FAR* pdwSize, // size in bytes
+ LPSTGMEDIUM pmedium); // bits
+
+
+
+/* Storage Utility APIs */
+STDAPI GetHGlobalFromILockBytes (LPLOCKBYTES plkbyt, HGLOBAL FAR* phglobal);
+STDAPI CreateILockBytesOnHGlobal (HGLOBAL hGlobal, BOOL fDeleteOnRelease,
+ LPLOCKBYTES FAR* pplkbyt);
+
+STDAPI GetHGlobalFromStream (LPSTREAM pstm, HGLOBAL FAR* phglobal);
+STDAPI CreateStreamOnHGlobal (HGLOBAL hGlobal, BOOL fDeleteOnRelease,
+ LPSTREAM FAR* ppstm);
+
+
+/* ConvertTo APIS */
+
+STDAPI OleDoAutoConvert(LPSTORAGE pStg, LPCLSID pClsidNew);
+STDAPI OleGetAutoConvert(REFCLSID clsidOld, LPCLSID pClsidNew);
+STDAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew);
+STDAPI GetConvertStg(LPSTORAGE pStg);
+STDAPI SetConvertStg(LPSTORAGE pStg, BOOL fConvert);
+
+
+#endif // _OLE2_H_
diff --git a/private/ole32/olethunk/ole16/inc/ole2anac.h b/private/ole32/olethunk/ole16/inc/ole2anac.h
new file mode 100644
index 000000000..d046acb66
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/ole2anac.h
@@ -0,0 +1,91 @@
+// ole2anac.h - anachronisms for pre-release code
+
+#if !defined( _OLE2ANAC_H_ )
+#define _OLE2ANAC_H_
+
+#define IIDEQ(riid1, riid2) IsEqualIID(riid1, riid2)
+#define CLSIDEQ(rclsid1, rclsid2) IsEqualCLSID(rclsid1, rclsid2)
+
+#define RetryRejectedCall RetryRejectedMessage
+
+#define FileTimeToDosDateTime(pft,pdd,pdt) CoFileTimeToDosDateTime(pft,pdd,pdt)
+#define DosDateTimeToFileTime(pdd,pdt,pft) CoDosDateTimeToFileTime(pdd,pdt,pft)
+
+typedef enum tagSTGSTATE
+{
+ STGSTATE_DOC = 1,
+ STGSTATE_CONVERT = 2,
+ STGSTATE_FILESTGSAME = 4
+} STGSTATE;
+
+
+#define MK_E_EXCEEDED_DEADLINE MK_E_EXCEEDEDDEADLINE
+#define MK_E_NEED_GENERIC MK_E_NEEDGENERIC
+#define MK_E_INVALID_EXTENSION MK_E_INVALIDEXTENSION
+#define MK_E_INTERMEDIATE_INTERFACE_NOT_SUPPORTED \
+ MK_E_INTERMEDIATEINTERFACENONOT_SUPPORTED
+#define MK_E_NOT_BINDABLE MK_E_NOTBINDABLE
+#define S_TRUE S_OK
+
+
+#define OLEMETHODCALLTYPE STDMETHODCALLTYPE
+#define OLEAPICALLTYPE STDAPICALLTYPE
+
+#define OLEAPI STDAPI
+#define OLEAPI_(type) STDAPI_(type)
+
+#define OLEMETHOD(method) STDMETHOD(method)
+#define OLEMETHOD_(type,method) STDMETHOD_(type,method)
+
+#define OLEMETHODIMP STDMETHODIMP
+#define OLEMETHODIMP_(type) STDMETHODIMP_(type)
+
+#define OLESTATIC_(type) static type __export
+#define OLESTATICIMP_(type) type __export
+
+
+#define E_BLANK OLE_E_BLANK
+#define E_STATIC OLE_E_STATIC
+#define E_NOTRUNNING OLE_E_NOTRUNNING
+#define E_FORMAT DV_E_CLIPFORMAT
+#define E_UNSPEC E_FAIL
+#define OLE_E_CLSID REGDB_E_CLASSNOTREG
+#define OLE_E_NOTSUPPORTED E_NOTIMPL
+#define OLE_E_REGDB_KEY REGDB_E_KEYMISSING
+#define OLE_E_REGDB_FMT REGDB_E_INVALIDVALUE
+
+
+#define OLEVERB_PRIMARY OLEIVERB_PRIMARY
+#define OLEVERB_SHOW OLEIVERB_SHOW
+
+#define DAdvise Advise
+#define DUnadvise Unadvise
+#define EnumDAdvise EnumAdvise
+
+
+// these DDE error codes are not returned anymore; these definitions are
+// here just to make existing code compile without changes.
+#define RPC_E_DDE_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_RPC, 0x100)
+
+#define RPC_E_DDE_BUSY (RPC_E_DDE_FIRST + 0x0)
+#define RPC_E_DDE_CANT_UPDATE (RPC_E_DDE_FIRST + 0x1)
+#define RPC_E_DDE_INIT (RPC_E_DDE_FIRST + 0x2)
+#define RPC_E_DDE_NACK E_FAIL
+#define RPC_E_DDE_LAUNCH CO_E_APPNOTFOUND
+#define RPC_E_DDE_POST RPC_E_SERVER_DIED
+#define RPC_E_DDE_PROTOCOL (RPC_E_DDE_FIRST + 0x6)
+#define RPC_E_DDE_REVOKE (RPC_E_DDE_FIRST + 0x7)
+#define RPC_E_DDE_SYNTAX_EXECUTE RPC_E_INVALID_PARAMETER
+#define RPC_E_DDE_SYNTAX_ITEM RPC_E_INVALID_PARAMETER
+#define RPC_E_DDE_UNEXP_MSG (RPC_E_DDE_FIRST + 0xa)
+#define RPC_E_DDE_DATA RPC_E_INVALID_PARAMETER
+
+
+#define RPC_E_CONNECTION_LOST (RPC_E_FIRST + 0x6)
+#define RPC_E_BUSY (RPC_E_FIRST + 0x0)
+#define RPC_E_MSG_REJECTED (RPC_E_FIRST + 0x1)
+#define RPC_E_CANCELLED (RPC_E_FIRST + 0x2)
+#define RPC_E_DISPATCH_ASYNCCALL (RPC_E_FIRST + 0x4)
+
+
+#endif // _OLE2ANAC_H_
diff --git a/private/ole32/olethunk/ole16/inc/ole2dbg.h b/private/ole32/olethunk/ole16/inc/ole2dbg.h
new file mode 100644
index 000000000..34fbf8384
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/ole2dbg.h
@@ -0,0 +1,19 @@
+/*
+ ole2dbg.h: This header file contains the function declarations for the publicly
+ exported debugging interfaces.
+
+ Include *after* standard OLE2 includes.
+
+ Copyright (c) 1992-1993, Microsoft Corp. All rights reserved.
+*/
+
+#ifndef __OLE2DBG_H
+#define __OLE2DBG_H
+
+STDAPI_(void) DbgDumpObject( IUnknown FAR * pUnk, DWORD dwReserved);
+STDAPI_(void) DbgDumpExternalObject( IUnknown FAR * pUnk, DWORD dwReserved );
+
+STDAPI_(BOOL) DbgIsObjectValid( IUnknown FAR * pUnk );
+STDAPI_(void) DbgDumpClassName( IUnknown FAR * pUnk );
+
+#endif
diff --git a/private/ole32/olethunk/ole16/inc/ole2int.h b/private/ole32/olethunk/ole16/inc/ole2int.h
new file mode 100644
index 000000000..dbd3597de
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/ole2int.h
@@ -0,0 +1,550 @@
+/*
+ * This is the internal ole2 header, which means it contains those
+ * interfaces which might eventually be exposed to the outside
+ * and which will be exposed to our implementations. We don't want
+ * to expose these now, so I have put them in a separate file.
+ */
+
+#if !defined( _OLE2INT_H_ )
+#define _OLE2INT_H_
+
+#ifndef RC_INVOKED
+#pragma message ("INCLUDING OLE2INT.H from " __FILE__)
+#endif /* RC_INVOKED */
+
+// ------------------------------------
+// system includes
+#include <string.h>
+#include <StdLib.h>
+
+#ifndef _MAC
+
+#ifdef WIN32
+#define _INC_OLE // Don't include ole.h (ole2.h included below)
+#define __RPC_H__ // Don't include rpc.h (compobj.h included below)
+#endif
+
+#include <windows.h>
+
+#include <malloc.h>
+
+#include <shellapi.h>
+#else
+#include <mac.h>
+#endif
+
+#ifdef WIN32
+
+#define __loadds // Not used
+#define UnlockData(ds) // Not used
+
+#define GlobalLock(h) ((LPSTR) GlobalLock(h)) // Retunred type has changed
+
+#define _fmalloc malloc
+#define _frealloc realloc
+#define _ffree free
+
+#define _fmemset memset
+#define _fmemcpy memcpy
+#define _fmemcmp memcmp
+#define _fmemmove memmove
+
+#define _fstrcpy strcpy // BUGBUG32 - should use strcpy
+#define _fstrcat strcat // BUGBUG32 - should use strcat
+#define _fstrlen strlen // BUGBUG32 - should use strlen
+#define _fstrchr strchr // BUGBUG32 - should use strchr
+#define _fstrcmp strcmp // BUGBUG32 - should use strcmp
+#define _fstrncmp strncmp // BUGBUG32 - should use strncmp
+#define _fstricmp stricmp // BUGBUG32 - should use stricmp
+#define _fstrnicmp strnicmp // BUGBUG32 - should use strnicmp
+#define _fstrtok strtok // BUGBUG32 - should use strtok
+
+#endif
+
+#ifdef WIN32
+#define HTASK DWORD // Use Proccess id / Thread id
+#define GetCurrentThread() GetCurrentThreadId()
+#define GetCurrentProcess() GetCurrentProcessId()
+#define GetWindowThread(h) ((HTASK)GetWindowTask(h))
+#else
+#define GetCurrentThread() GetCurrentTask()
+#define GetCurrentProcess() GetCurrentTask()
+#define GetWindowThread(h) GetWindowTask(h)
+#endif
+
+#ifdef WIN32
+#define LocalHandle(p) LocalHandle((void*)(p))
+#else
+#define LocalHandle(p) LocalHandle((UINT)(p))
+#endif
+
+#ifdef WIN32
+#define SetWindowOrg(h,x,y) SetWindowOrgEx((h),(x),(y),NULL)
+#define SetWindowExt(h,x,y) SetWindowExtEx((h),(x),(y),NULL)
+#define SetViewportOrg(h,x,y) SetViewportOrgEx((h),(x),(y),NULL)
+#define SetViewportExt(h,x,y) SetViewportExtEx((h),(x),(y),NULL)
+#define SetBitmapDimension(h,x,y) SetBitmapDimensionEx((h),(x),(y),NULL)
+#endif
+
+
+#ifdef WIN32
+#define WEP_FREE_DLL 0 // BUGBUG32
+#define WEP_SYSTEM_EXIT 1
+#endif
+
+
+#ifdef WIN32
+// BUGBUG32 - BarryM needs to look at this
+// Probably reverse the logic (that is do path to drive index translation
+// within a GetDriveTypeEx(char FAR* pszRoot))
+// This also is used by dde code
+
+inline UINT GetDriveType16(int i)
+{
+ char s[4];
+ if (i < 0 || i > 26)
+ return 0;
+
+ s[0] = i + 'A'; s[1] = ':'; s[2] = '\\'; s[3] = '\0';
+
+ return GetDriveTypeA(s); // GetDriveType already mapped to GetDriveType16
+}
+
+#undef GetDriveType // Remove mapping to GetDriveTypeA
+
+#define GetDriveType(i) GetDriveType16(i)
+
+#endif
+
+#ifdef WIN32
+#undef RegQueryValue // Remove mapping to RegQueryValueA
+#define RegQueryValue(hkey,lpszKey,lpszVal,lpcb) \
+ RegQueryValueA((hkey),(lpszKey),(lpszVal),((DWORD*) (lpcb)))
+#undef RegOpenKey // Remove mapping to RegOpenKeyA
+#define RegOpenKey(hkey,lpszSubKey,phkey) \
+ RegOpenKeyA((hkey),((LPSTR)(lpszSubKey)),(phkey))
+#endif
+
+
+#ifdef WIN32
+extern void *pvtblIDebug;
+extern void *pvtblCBaseMoniker;
+extern void *pvtblCFileMoniker;
+extern void *pvtblCItemMoniker;
+extern void *pvtblCCompositeMoniker;
+extern void *pvtblCAntiMoniker;
+extern void *pvtblCPointerMoniker;
+extern void *pvtblCRunningObjectTable;
+extern void *pvtblCROTEnumMoniker;
+extern void SetpVtbl(void *pvtbl);
+#define SETPVTBL(Name) if (PlacementOf(this) == SHARED) SetpVtbl(pvtbl##Name)
+#else
+#define SETPVTBL(Name)
+#endif
+
+// ------------------------------------
+// public includes
+#include <ole2anac.h>
+#include <ole2.h>
+#include <cobjps.h>
+#include <ole2sp.h>
+
+// ------------------------------------
+// internal includes
+#include <olemem.h>
+#include <cmacs.h>
+#include <utils.h>
+#include <olecoll.h>
+#include <valid.h>
+#include <array_fv.h>
+#include <map_kv.h>
+#include <privguid.h>
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+#if defined(_M_I86SM) || defined(_M_I86MM)
+#define _NEARDATA
+#endif
+
+#include <utstream.h>
+
+/*
+ * Warning disables:
+ *
+ * We compile with warning level 4, with the following warnings
+ * disabled:
+ *
+ * 4355: 'this' used in base member initializer list
+ *
+ * We don't see the point of this message and we do this all
+ * the time.
+ *
+ * 4505: Unreferenced local function has been removed -- the given
+ * function is local and not referenced in the body of the module.
+ *
+ * Unfortunately, this is generated for every inline function
+ * seen in the header files that is not used in the module.
+ * Since we use a number of inlines, this is a nuisance
+ * warning. It would be nice if the compiler distinguished
+ * between inlines and regular functions.
+ *
+ * 4706: Assignment within conditional expression.
+ *
+ * We use this style of programming extensively, so this
+ * warning is disabled.
+ */
+
+#pragma warning(disable:4355)
+#pragma warning(disable:4068)
+/*
+ * MACROS for Mac/PC core code
+ *
+ * The following macros reduce the proliferation of #ifdefs. They
+ * allow tagging a fragment of code as Mac only, PC only, or with
+ * variants which differ on the PC and the Mac.
+ *
+ * Usage:
+ *
+ *
+ * h = GetHandle();
+ * Mac(DisposeHandle(h));
+ *
+ *
+ * h = GetHandle();
+ * MacWin(h2 = h, CopyHandle(h, h2));
+ *
+ */
+#ifdef _MAC
+#define Mac(x) x
+#define Win(x)
+#define MacWin(x,y) x
+#else
+#define Mac(x)
+#define Win(x) x
+#define MacWin(x,y) y
+#endif
+
+
+#define _DBCS
+
+// Macros for Double-Byte Character Support (DBCS)
+#ifdef _DBCS
+ #ifdef _MAC
+ #define IncLpch IncLpch
+ #define DecLpch DecLpch
+ #else
+ // Beware of double evaluation
+ #define IncLpch(sz) ((sz)=AnsiNext((sz)))
+ #define DecLpch(szStart, sz) ((sz)=AnsiPrev ((szStart),(sz)))
+ #endif
+#else
+ #define IncLpch(sz) (++(sz))
+ #define DecLpch(szStart,sz) (--(sz))
+#endif
+
+
+#ifndef _MAC
+/* dlls instance and module handles */
+
+extern HMODULE hmodOLE2;
+
+/* Variables for registered clipboard formats */
+
+extern CLIPFORMAT cfObjectLink;
+extern CLIPFORMAT cfOwnerLink;
+extern CLIPFORMAT cfNative;
+extern CLIPFORMAT cfLink;
+extern CLIPFORMAT cfBinary;
+extern CLIPFORMAT cfFileName;
+extern CLIPFORMAT cfNetworkName;
+extern CLIPFORMAT cfDataObject;
+extern CLIPFORMAT cfEmbeddedObject;
+extern CLIPFORMAT cfEmbedSource;
+extern CLIPFORMAT cfLinkSource;
+extern CLIPFORMAT cfOleDraw;
+extern CLIPFORMAT cfLinkSrcDescriptor;
+extern CLIPFORMAT cfObjectDescriptor;
+extern CLIPFORMAT cfCustomLinkSource;
+extern CLIPFORMAT cfPBrush;
+extern CLIPFORMAT cfMSDraw;
+
+#endif
+
+
+/* Number of logical pixels per inch for current driver */
+extern int giPpliX;
+extern int giPpliY;
+
+
+/* Exported CLSIDs.. */
+#define CLSID_StaticMetafile CLSID_Picture_Metafile
+#define CLSID_StaticDib CLSID_Picture_Dib
+
+
+// special Assert for asserts below (since the expression is so large)
+#ifdef _DEBUG
+#define AssertOut(a, b) { if (!(a)) FnAssert(szCheckOutParam, b, _szAssertFile, __LINE__); }
+#else
+#define AssertOut(a, b) ((void)0)
+#endif
+
+#define AssertOutPtrParam(hr, p) \
+ AssertOut(SUCCEEDED(hr) && IsValidPtrIn(p, sizeof(char)) || \
+ FAILED(hr) && (p) == NULL, \
+ szBadOutParam)
+
+#define AssertOutPtrIface(hr, p) \
+ AssertOut(SUCCEEDED(hr) && IsValidInterface(p) || \
+ FAILED(hr) && (p) == NULL, \
+ szBadOutIface)
+
+#define AssertOutPtrFailed(p) \
+ AssertOut((p) == NULL, \
+ szNonNULLOutPtr)
+
+#define AssertOutStgmedium(hr, pstgm) \
+ AssertOut(SUCCEEDED(hr) && (pstgm)->tymed != TYMED_NULL || \
+ FAILED(hr) && (pstgm)->tymed == TYMED_NULL, \
+ szBadOutStgm)
+
+
+// assert data for above assert out macros; once per dll
+#define ASSERTOUTDATA \
+ char szCheckOutParam[] = "check out param"; \
+ char szBadOutParam[] = "Out pointer param conventions not followed"; \
+ char szBadOutIface[] = "Out pointer interface conventions not followed"; \
+ char szNonNULLOutPtr[] = "Out pointer not NULL on error"; \
+ char szBadOutStgm[] = "Out stgmed param conventions not followed";
+
+extern char szCheckOutParam[];
+extern char szBadOutParam[];
+extern char szBadOutIface[];
+extern char szNonNULLOutPtr[];
+extern char szBadOutStgm[];
+
+
+/***********************************************************************/
+/**** C++ memory management ****/
+/***********************************************************************/
+
+
+// these should never be called (and assert if they are)
+void * operator new(size_t size);
+void operator delete(void * ptr);
+
+
+
+void FAR* operator new(size_t size); // same as new (MEMCTX_TASK)
+void FAR* operator new(size_t size, DWORD memctx, void FAR* lpvSame=NULL);
+void operator delete(void FAR* ptr);
+
+// example usage:
+// lp = new(MEMCTX_TASK) CClass;
+// lp = new(MEMCTX_SHARED) CClass;
+// lp = new(MEMCTX_SAME, lpv) CClass;
+
+// MEMCTX for compobj internal memory (only used by compobj code)
+// NOTE: this value is not represented in the MEMCTX enum in compobj.h
+#define MEMCTX_COPRIVATE 5
+
+// exports from compobj.dll:
+// returns MEMCTX of existing pointer
+STDAPI_(DWORD) CoMemctxOf(void const FAR* lpv);
+STDAPI_(void FAR*) CoMemAlloc(ULONG cb ,DWORD memctx, void FAR* lpvSame);
+STDAPI_(void) CoMemFree(void FAR* lpv, DWORD memctx);
+
+
+// old names
+#define MemoryPlacement DWORD
+#define PlacementOf CoMemctxOf
+#define TASK MEMCTX_TASK, NULL
+#define SHARED MEMCTX_SHARED, NULL
+#define SAME MEMCTX_SAME, NULL
+
+
+/***********************************************************************/
+/**** FILE FORMAT RELATED INFO ****/
+/***********************************************************************/
+
+// Coponent object stream information
+
+#define COMPOBJ_STREAM "\1CompObj"
+#define BYTE_ORDER_INDICATOR 0xfffe // for MAC it could be different
+#define COMPOBJ_STREAM_VERSION 0x0001
+
+// OLE defines values for different OSs
+#define OS_WIN 0x0000
+#define OS_MAC 0x0001
+#define OS_NT 0x0002
+
+// HIGH WORD is OS indicator, LOW WORD is OS version number
+extern DWORD gdwOrgOSVersion;
+extern DWORD gdwOleVersion;
+
+
+// Ole streams information
+#define OLE_STREAM "\1Ole"
+#define OLE_PRODUCT_VERSION 0x0200 // (HIGH BYTE major version)
+#define OLE_STREAM_VERSION 0x0001
+
+#define OLE10_NATIVE_STREAM "\1Ole10Native"
+#define OLE10_ITEMNAME_STREAM "\1Ole10ItemName"
+#define OLE_PRESENTATION_STREAM "\2OlePres000"
+#define CONTENTS_STREAM "CONTENTS"
+
+/***********************************************************************
+ Storage APIs internally used
+*************************************************************************/
+
+OLEAPI ReadClipformatStm(LPSTREAM lpstream, DWORD FAR* lpdwCf);
+OLEAPI WriteClipformatStm(LPSTREAM lpstream, CLIPFORMAT cf);
+
+OLEAPI WriteMonikerStm (LPSTREAM pstm, LPMONIKER pmk);
+OLEAPI ReadMonikerStm (LPSTREAM pstm, LPMONIKER FAR* pmk);
+
+OLEAPI_(LPSTREAM) CreateMemStm(DWORD cb, LPHANDLE phMem);
+OLEAPI_(LPSTREAM) CloneMemStm(HANDLE hMem);
+OLEAPI_(void) ReleaseMemStm (LPHANDLE hMem, BOOL fInternalOnly = FALSE);
+
+/*************************************************************************
+ Initialization code for individual modules
+*************************************************************************/
+
+INTERNAL_(void) DDEWEP (
+ BOOL fSystemExit
+);
+
+INTERNAL_(BOOL) DDELibMain (
+ HANDLE hInst,
+ WORD wDataSeg,
+ WORD cbHeapSize,
+ LPSTR lpszCmdLine
+);
+
+BOOL InitializeRunningObjectTable(void);
+void DestroyRunningObjectTable(void);
+
+
+#ifdef _MAC
+#define BITMAP_TO_DIB(foretc)
+#else
+#define BITMAP_TO_DIB(foretc) \
+ if (foretc.cfFormat == CF_BITMAP) {\
+ foretc.cfFormat = CF_DIB;\
+ foretc.tymed = TYMED_HGLOBAL;\
+ }
+#endif
+
+
+#define VERIFY_ASPECT_SINGLE(dwAsp) {\
+ if (!(dwAsp && !(dwAsp & (dwAsp-1)) && (dwAsp <= DVASPECT_DOCPRINT))) {\
+ AssertSz(FALSE, "More than 1 aspect is specified");\
+ return ResultFromScode(DV_E_DVASPECT);\
+ }\
+}
+
+
+#define VERIFY_TYMED_SINGLE(tymed) {\
+ if (!(tymed && !(tymed & (tymed-1)) && (tymed <= TYMED_MFPICT))) \
+ return ResultFromScode(DV_E_TYMED); \
+}
+
+
+#define VERIFY_TYMED_SINGLE_VALID_FOR_CLIPFORMAT(pfetc) {\
+ if ((pfetc->cfFormat==CF_METAFILEPICT && pfetc->tymed!=TYMED_MFPICT)\
+ || (pfetc->cfFormat==CF_BITMAP && pfetc->tymed!=TYMED_GDI)\
+ || (pfetc->cfFormat!=CF_METAFILEPICT && \
+ pfetc->cfFormat!=CF_BITMAP && \
+ pfetc->tymed!=TYMED_HGLOBAL))\
+ return ResultFromScode(DV_E_TYMED); \
+}
+
+
+
+
+// REVIEW ...
+// Only DDE layer will test for these values. And only for advises on cached
+// formats do we use these values
+
+#define ADVFDDE_ONSAVE 0x40000000
+#define ADVFDDE_ONCLOSE 0x80000000
+
+
+// Used in Ole Private Stream
+typedef enum tagOBJFLAGS
+{
+ OBJFLAGS_LINK=1L,
+ OBJFLAGS_DOCUMENT=2L, // this bit is owned by container and is
+ // propogated through saves
+ OBJFLAGS_CONVERT=4L,
+} OBJFLAGS;
+
+
+
+/*****************************************
+ Prototypes for dde\client\ddemnker.cpp
+******************************************/
+
+INTERNAL DdeBindToObject
+ (LPCSTR szFile,
+ REFCLSID clsid,
+ BOOL fPackageLink,
+ LPBC pbc, // not used
+ LPMONIKER pmkToLeft, // not used
+ REFIID iid,
+ LPLPVOID ppv);
+
+INTERNAL DdeIsRunning
+ (CLSID clsid,
+ LPCSTR szFile,
+ LPBC pbc,
+ LPMONIKER pmkToLeft,
+ LPMONIKER pmkNewlyRunning);
+
+
+/**************************************
+ Prototypes for moniker\mkparse.cpp
+***************************************/
+
+INTERNAL Ole10_ParseMoniker
+ (LPMONIKER pmk,
+ LPSTR FAR* pszFile,
+ LPSTR FAR* pszItem);
+
+
+/****************************************************************************/
+/* Utility APIs, might get exposed later */
+/****************************************************************************/
+
+OLEAPI OleGetData(LPDATAOBJECT lpDataObj, LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium, BOOL fGetOwnership);
+OLEAPI OleSetData(LPDATAOBJECT lpDataObj, LPFORMATETC pformatetc,
+ STGMEDIUM FAR * pmedium, BOOL fRelease);
+STDAPI OleDuplicateMedium(LPSTGMEDIUM lpMediumSrc, LPSTGMEDIUM lpMediumDest);
+
+OLEAPI_(BOOL) OleIsDcMeta (HDC hdc);
+
+INTERNAL SzFixNet( LPBINDCTX pbc, LPSTR szUNCName, LPSTR FAR * lplpszReturn,
+ UINT FAR * pEndServer, BOOL fForceConnection = TRUE);
+
+FARINTERNAL ReadFmtUserTypeProgIdStg
+ (IStorage FAR * pstg,
+ CLIPFORMAT FAR* pcf,
+ LPSTR FAR* pszUserType,
+ LPSTR szProgID);
+
+/****************************************************************************/
+/* Internal StubManager APIs, might get exposed later */
+/****************************************************************************/
+OLEAPI CoDisconnectWeakExternal(IUnknown FAR* pUnk, DWORD dwReserved);
+
+
+#pragma warning(disable: 4073) // disable warning about using init_seg
+#pragma init_seg(lib)
+#include "ole2segs.h"
+#include "cosegs.h"
+#include "prxsegs.h"
+#endif // _OLE2INT_H_
diff --git a/private/ole32/olethunk/ole16/inc/ole2segs.h b/private/ole32/olethunk/ole16/inc/ole2segs.h
new file mode 100644
index 000000000..139597f9c
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/ole2segs.h
@@ -0,0 +1,2 @@
+
+
diff --git a/private/ole32/olethunk/ole16/inc/ole2sp.h b/private/ole32/olethunk/ole16/inc/ole2sp.h
new file mode 100644
index 000000000..3a7e6bf4a
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/ole2sp.h
@@ -0,0 +1,346 @@
+/* ole2sp.h - semi-private info; only for test apps within the development group
+*/
+
+#if !defined( _OLE2SP_H_ )
+#define _OLE2SP_H_
+
+#include <shellapi.h>
+
+// For MAC, M_PROLOG and M_EPILOG are macros which assist us in setting up the A5
+// world for a DLL when a method in the DLL is called from outside the DLL.
+
+#ifdef _MAC
+
+#define _MAX_PATH 260
+
+#ifdef __cplusplus
+
+class CSetA5
+{
+public:
+ CSetA5 (ULONG savedA5){ A5save = SetA5(savedA5);}
+ ~CSetA5 (){ SetA5(A5save);}
+
+private:
+ ULONG A5save;
+};
+
+pascal long GetA5(void) = 0x2E8D;
+
+#define M_PROLOG(where) CSetA5 Dummy((where)->savedA5)
+#define SET_A5 ULONG savedA5
+#define GET_A5() savedA5 = GetA5()
+
+// These macros assist Mac in manually saving/setting/restoring A5 in routines that contain
+// goto's.
+
+#define A5_PROLOG(where) ULONG A5save = SetA5(where->savedA5)
+#define RESTORE_A5() SetA5(A5save)
+
+// Lets MAC name our segments without ifdef's.
+
+#define NAME_SEG(x)
+
+#endif // ccplus
+
+#else
+
+#define M_PROLOG(where)
+#define SET_A5
+#define GET_A5()
+#define A5_PROLOG(where)
+#define RESTORE_A5()
+#define NAME_SEG(x)
+
+
+#define IGetProcAddress(a,b) GetProcAddress((a),(b))
+
+#endif
+
+
+#define ReportResult(a,b,c,d) ResultFromScode(b)
+
+
+#ifdef WIN32
+#define MAP16(v16)
+#define MAP32(v32) v32
+#define MAP1632(v16,v32) v32
+#else
+#define MAP16(v16) v16
+#define MAP32(v32)
+#define MAP1632(v16,v32) v16
+#endif
+
+
+/****** Misc defintions ***************************************************/
+
+#ifdef __TURBOC__
+#define implement struct huge
+#else
+#define implement struct
+#endif
+#define ctor_dtor private
+#define implementations private
+#define shared_state private
+
+// helpers for internal methods and functions which follow the same convention
+// as the external ones
+
+#ifdef __cplusplus
+#define INTERNALAPI_(type) extern "C" type
+#else
+#define INTERNALAPI_(type) type
+#endif
+
+#define INTERNAL HRESULT
+#define INTERNAL_(type) type
+#define FARINTERNAL HRESULT FAR
+#define FARINTERNAL_(type) type FAR
+#define NEARINTERNAL HRESULT NEAR
+#define NEARINTERNAL_(type) type NEAR
+
+
+
+//BEGIN REVIEW: We may not need all the following ones
+
+#define OT_LINK 1L
+#define OT_EMBEDDED 2L
+#define OT_STATIC 3L
+
+
+//END REVIEW .....
+
+
+/****** Old Error Codes ************************************************/
+
+#define S_OOM E_OUTOFMEMORY
+#define S_BADARG E_INVALIDARG
+#define S_BLANK E_BLANK
+#define S_FORMAT E_FORMAT
+#define S_NOT_RUNNING E_NOTRUNNING
+#define E_UNSPEC E_FAIL
+
+
+
+/****** Macros for nested clases ******************************************/
+
+/* To overcome problems with nested classes on MAC
+ *
+ * NC(a,b) is used to define a member function of a nested class:
+ *
+ * STDMETHODIMP_(type) NC(ClassName,NestedClassName)::MemberFunction(...)
+ *
+ * DECLARE_NC(a,b) is used within a class declaration to let a nested class
+ * access it container class:
+ *
+ * class ClassName {
+ * ..............
+ *
+ * class NestedClassName {
+ * .............
+ * };
+ * DECLARE_NC(ClassName,NestedClassName)
+ * ..............
+ * };
+ */
+
+#ifdef _MAC
+
+#define NESTED_CLASS(a,b) struct a##_##b
+#define NC(a,b) a##__##b
+#define NC1(a,b) a##_##b
+#define DECLARE_NC(a,b) typedef a##::##b a##__##b; friend a##__##b;
+#define DECLARE_NC2(a,b) typedef a##::a##_##b a##__##b; friend a##__##b;
+
+#else
+
+#define NC(a,b) a##::##b
+#define DECLARE_NC(a,b) friend b;
+
+#endif
+
+
+/****** More Misc defintions **********************************************/
+
+
+// LPLPVOID should not be made a typedef. typedef won't compile; worse
+// within complicated macros the compiler generates unclear error messages
+//
+#define LPLPVOID void FAR * FAR *
+
+#define UNREFERENCED(a) ((void)(a))
+
+#ifndef BASED_CODE
+#ifdef WIN32
+#define BASED_CODE
+#else
+#define BASED_CODE __based(__segname("_CODE"))
+#endif
+#endif
+
+
+/****** Standard IUnknown Implementation **********************************/
+
+/*
+ * The following macro declares a nested class CUnknownImpl,
+ * creates an object of that class in the outer class, and
+ * declares CUnknownImpl to be a friend of the outer class. After
+ * writing about 20 class headers, it became evident that the
+ * implementation of CUnknownImpl was very similar in all cases,
+ * and this macro captures the similarity. The classname
+ * parameter is the name of the outer class WITHOUT the leading
+ * "C"; i.e., for CFileMoniker, classname is FileMoniker.
+ */
+
+#define noError return NOERROR
+
+#ifdef _MAC
+
+#define STDUNKDECL(cclassname,classname) NESTED_CLASS(cclassname, CUnknownImpl):IUnknown { public: \
+ NC1(cclassname,CUnknownImpl)( cclassname FAR * p##classname ) { m_p##classname = p##classname;} \
+ STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPLPVOID ppvObj); \
+ STDMETHOD_(ULONG,AddRef)(THIS); \
+ STDMETHOD_(ULONG,Release)(THIS); \
+ private: cclassname FAR* m_p##classname; }; \
+ DECLARE_NC2(cclassname, CUnknownImpl) \
+ NC(cclassname, CUnknownImpl) m_Unknown;
+
+#else // _MAC
+
+#define STDUNKDECL( ignore, classname ) implement CUnknownImpl:IUnknown { public: \
+ CUnknownImpl( C##classname FAR * p##classname ) { m_p##classname = p##classname;} \
+ STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPLPVOID ppvObj); \
+ STDMETHOD_(ULONG,AddRef)(THIS); \
+ STDMETHOD_(ULONG,Release)(THIS); \
+ private: C##classname FAR* m_p##classname; }; \
+ DECLARE_NC(C##classname, CUnknownImpl) \
+ CUnknownImpl m_Unknown;
+#endif
+
+/*
+ * The following macro implements all the methods of a nested
+ * CUnknownImpl class EXCEPT FOR QUERYINTERFACE. This macro was
+ * written after about 20 classes were written in which the
+ * implementations of CUnknownImpl were all the same.
+ */
+
+#define STDUNKIMPL(classname) \
+STDMETHODIMP_(ULONG) NC(C##classname,CUnknownImpl)::AddRef( void ){ \
+ return ++m_p##classname->m_refs; } \
+STDMETHODIMP_(ULONG) NC(C##classname,CUnknownImpl)::Release( void ){ \
+ if (--m_p##classname->m_refs == 0) { delete m_p##classname; return 0; } \
+ return m_p##classname->m_refs;}
+
+
+/*
+ * The following macro implements class::CUnknownImpl::QueryInterface IN
+ * THE SPECIAL CASE IN WHICH THE OUTER CLASS PRESENTS ONLY ONE INTERFACE
+ * OTHER THAN IUNKNOWN AND IDEBUG. This is not universally the case,
+ * but it is common enough that this macro will save time and space.
+ */
+
+#ifdef _DEBUG
+#define STDDEB_QI(classname) \
+ if (iidInterface == IID_IDebug) {*ppv = (void FAR *)&(m_p##classname->m_Debug); return 0;} else
+#else
+#define STDDEB_QI(classname)
+#endif
+
+#define STDUNK_QI_IMPL(classname, interfacename) \
+STDMETHODIMP NC(C##classname,CUnknownImpl)::QueryInterface \
+ (REFIID iidInterface, void FAR * FAR * ppv) { \
+ if (iidInterface == IID_IUnknown) {\
+ *ppv = (void FAR *)&m_p##classname->m_Unknown;\
+ AddRef(); noError;\
+ } else if (iidInterface == IID_I##interfacename) { \
+ *ppv = (void FAR *) &(m_p##classname->m_##classname); \
+ m_p##classname->m_pUnkOuter->AddRef(); return NOERROR; \
+ } else \
+ STDDEB_QI(classname) \
+ {*ppv = NULL; return ResultFromScode(E_NOINTERFACE);} \
+}
+
+
+/*
+ * The following macro implements the IUnknown methods inherited
+ * by the implementation of another interface. The implementation
+ * is simply to delegate all calls to m_pUnkOuter. Parameters:
+ * ocname is the outer class name, icname is the implementation
+ * class name.
+ *
+ */
+
+#define STDUNKIMPL_FORDERIVED(ocname, icname) \
+STDMETHODIMP NC(C##ocname,C##icname)::QueryInterface \
+(REFIID iidInterface, LPLPVOID ppvObj) { \
+ return m_p##ocname->m_pUnkOuter->QueryInterface(iidInterface, ppvObj);} \
+STDMETHODIMP_(ULONG) NC(C##ocname,C##icname)::AddRef(void) { \
+ return m_p##ocname->m_pUnkOuter->AddRef(); } \
+STDMETHODIMP_(ULONG) NC(C##ocname,C##icname)::Release(void) { \
+ return m_p##ocname->m_pUnkOuter->Release(); }
+
+
+/****** Debug defintions **************************************************/
+
+#include <debug.h>
+
+
+/****** Other API defintions **********************************************/
+
+// Utility function not in the spec; in ole2.dll.
+// Read and write length-prefixed strings. Open/Create stream.
+// ReadStringStream does allocation, returns length of
+// required buffer (strlen + 1 for terminating null)
+
+STDAPI ReadStringStream( LPSTREAM pstm, LPSTR FAR * ppsz );
+STDAPI WriteStringStream( LPSTREAM pstm, LPCSTR psz );
+STDAPI OpenOrCreateStream( IStorage FAR * pstg, const char FAR * pwcsName,
+ IStream FAR* FAR* ppstm);
+
+
+// read and write ole control stream (in ole2.dll)
+STDAPI WriteOleStg (LPSTORAGE pstg, IOleObject FAR* pOleObj,
+ DWORD dwReserved, LPSTREAM FAR* ppstmOut);
+STDAPI ReadOleStg (LPSTORAGE pstg, DWORD FAR* pdwFlags,
+ DWORD FAR* pdwOptUpdate, DWORD FAR* pdwReserved,
+ LPMONIKER FAR* ppmk, LPSTREAM FAR* pstmOut);
+STDAPI ReadM1ClassStm(LPSTREAM pStm, CLSID FAR* pclsid);
+STDAPI WriteM1ClassStm(LPSTREAM pStm, REFCLSID rclsid);
+
+
+// low level reg.dat access (in compobj.dll)
+STDAPI CoGetInProcDll(REFCLSID rclsid, BOOL fServer, LPSTR lpszDll, int cbMax);
+STDAPI CoGetLocalExe(REFCLSID rclsid, LPSTR lpszExe, int cbMax);
+STDAPI CoGetPSClsid(REFIID iid, LPCLSID lpclsid);
+
+
+// simpler alternatives to public apis
+#define StringFromCLSID2(rclsid, lpsz, cbMax) \
+ StringFromGUID2(rclsid, lpsz, cbMax)
+
+#define StringFromIID2(riid, lpsz, cbMax) \
+ StringFromGUID2(riid, lpsz, cbMax)
+
+STDAPI_(int) Ole1ClassFromCLSID2(REFCLSID rclsid, LPSTR lpsz, int cbMax);
+STDAPI_(BOOL) GUIDFromString(LPCSTR lpsz, LPGUID pguid);
+STDAPI CLSIDFromOle1Class(LPCSTR lpsz, LPCLSID lpclsid, BOOL fForceAssign=FALSE);
+STDAPI_(BOOL) CoIsHashedOle1Class(REFCLSID rclsid);
+STDAPI CoOpenClassKey(REFCLSID clsid, HKEY FAR* lphkeyClsid);
+
+
+// were public; now not
+STDAPI SetDocumentBitStg(LPSTORAGE pStg, BOOL fDocument);
+STDAPI GetDocumentBitStg(LPSTORAGE pStg);
+
+
+
+/*
+ * Some docfiles stuff
+ */
+
+#define STGM_DFRALL (STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE)
+#define STGM_DFALL (STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE)
+#define STGM_SALL (STGM_READWRITE | STGM_SHARE_EXCLUSIVE)
+
+
+#endif // _OLE2SP_H_
diff --git a/private/ole32/olethunk/ole16/inc/ole2ui.h b/private/ole32/olethunk/ole16/inc/ole2ui.h
new file mode 100644
index 000000000..4691c005b
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/ole2ui.h
@@ -0,0 +1,918 @@
+/*
+ * OLE2UI.H
+ *
+ * Published definitions, structures, types, and function prototypes for the
+ * OLE 2.0 User Interface support library.
+ *
+ * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
+ */
+
+/* NOTE: All dialog and string resource ID's defined in this file are
+ * in the range:
+ * 32248 - 32504 (0x7DF8 - 0x7EF8)
+*/
+
+
+#ifndef _OLE2UI_H_
+#define _OLE2UI_H_
+
+#ifndef RC_INVOKED
+#pragma message ("Including OLE2UI.H from " __FILE__)
+#endif //RC_INVOKED
+
+#ifdef WIN32
+#define _INC_OLE
+#define __RPC_H__
+#endif
+
+#if !defined(__cplusplus) && !defined( __TURBOC__)
+#define NONAMELESSUNION // use strict ANSI standard (for DVOBJ.H)
+#endif
+
+#include <windows.h>
+#include <shellapi.h>
+#include <ole2.h>
+#include <string.h>
+#include <dlgs.h> //For fileopen dlg; standard include
+#include "olestd.h"
+
+#ifdef __TURBOC__
+#define _getcwd getcwd
+#define _itoa itoa
+#define __max max
+#define _find_t find_t
+#endif // __TURBOC__
+
+#ifdef WIN32
+#define _fmemset memset
+#define _fmemcpy memcpy
+#define _fmemcmp memcmp
+#define _fstrcpy strcpy
+#define _fstrlen strlen
+#define _fstrrchr strrchr
+#define _fstrtok strtok
+#define lstrcpyn strncpy
+
+// BUGBUG32: isspace function does not seem to work properly
+#undef isspace
+#define isspace(j) (j==' ' || j=='\t' || j=='\n')
+#endif // WIN32
+
+#if !defined( EXPORT )
+#ifdef WIN32
+#define EXPORT
+#else
+#define EXPORT __export
+#endif // WIN32
+#endif // !EXPORT
+
+/*
+ * Initialization / Uninitialization routines. OleUIInitialize
+ * must be called prior to using any functions in OLE2UI, and OleUIUnInitialize
+ * must be called before you app shuts down and when you are done using the
+ * library.
+ *
+ * NOTE: If you are using the DLL version of this library, these functions
+ * are automatically called in the DLL's LibMain and WEP, so you should
+ * not call them directly from your application.
+ */
+
+// Backward compatibility with older library
+#define OleUIUninitialize OleUIUnInitialize
+
+STDAPI_(BOOL) OleUIInitialize(HINSTANCE hInstance, HINSTANCE hPrevInst);
+STDAPI_(BOOL) OleUIUninitialize(void);
+
+#if !defined( SZCLASSICONBOX )
+#define SZCLASSICONBOX "ole2uiIBCls"
+#endif
+
+#if !defined( SZCLASSRESULTIMAGE )
+#define SZCLASSRESULTIMAGE "ole2uiRICls"
+#endif
+
+// object count, used to support DllCanUnloadNow and OleUICanUnloadNow
+extern DWORD g_dwObjectCount;
+
+STDAPI OleUICanUnloadNow(void);
+STDAPI OleUILockLibrary(BOOL fLock);
+
+
+//Dialog Identifiers as passed in Help messages to identify the source.
+#define IDD_INSERTOBJECT 32248
+#define IDD_CHANGEICON 32249
+#define IDD_CONVERT 32250
+#define IDD_PASTESPECIAL 32251
+#define IDD_EDITLINKS 32252
+#define IDD_FILEOPEN 32253
+#define IDD_BUSY 32254
+#define IDD_UPDATELINKS 32255
+#define IDD_CANNOTUPDATELINK 32256
+#define IDD_CHANGESOURCE 32257
+#define IDD_INSERTFILEBROWSE 32258
+#define IDD_CHANGEICONBROWSE 32259
+
+// The following Dialogs are message dialogs used by OleUIPromptUser API
+#define IDD_LINKSOURCEUNAVAILABLE 32260
+#define IDD_SERVERNOTREG 32261
+#define IDD_LINKTYPECHANGED 32262
+#define IDD_SERVERNOTFOUND 32263
+#define IDD_OUTOFMEMORY 32264
+
+// Stringtable identifers
+#define IDS_OLE2UIUNKNOWN 32300
+#define IDS_OLE2UILINK 32301
+#define IDS_OLE2UIOBJECT 32302
+#define IDS_OLE2UIEDIT 32303
+#define IDS_OLE2UICONVERT 32304
+#define IDS_OLE2UIEDITLINKCMD_1VERB 32305
+#define IDS_OLE2UIEDITOBJECTCMD_1VERB 32306
+#define IDS_OLE2UIEDITLINKCMD_NVERB 32307
+#define IDS_OLE2UIEDITOBJECTCMD_NVERB 32308
+#define IDS_OLE2UIEDITNOOBJCMD 32309
+// def. icon label (usu. "Document")
+#define IDS_DEFICONLABEL 32310
+#define IDS_OLE2UIPASTELINKEDTYPE 32311
+
+
+#define IDS_FILTERS 32320
+#define IDS_ICONFILTERS 32321
+#define IDS_BROWSE 32322
+
+//Resource identifiers for bitmaps
+#define IDB_RESULTSEGA 32325
+#define IDB_RESULTSVGA 32326
+#define IDB_RESULTSHIRESVGA 32327
+
+
+//Missing from windows.h
+#ifndef PVOID
+typedef VOID *PVOID;
+#endif
+
+
+//Hook type used in all structures.
+typedef UINT (CALLBACK *LPFNOLEUIHOOK)(HWND, UINT, WPARAM, LPARAM);
+
+
+//Strings for registered messages
+#define SZOLEUI_MSG_HELP "OLEUI_MSG_HELP"
+#define SZOLEUI_MSG_ENDDIALOG "OLEUI_MSG_ENDDIALOG"
+#define SZOLEUI_MSG_BROWSE "OLEUI_MSG_BROWSE"
+#define SZOLEUI_MSG_CHANGEICON "OLEUI_MSG_CHANGEICON"
+#define SZOLEUI_MSG_CLOSEBUSYDIALOG "OLEUI_MSG_CLOSEBUSYDIALOG"
+#define SZOLEUI_MSG_FILEOKSTRING "OLEUI_MSG_FILEOKSTRING"
+
+//Standard error definitions
+#define OLEUI_FALSE 0
+#define OLEUI_SUCCESS 1 //No error, same as OLEUI_OK
+#define OLEUI_OK 1 //OK button pressed
+#define OLEUI_CANCEL 2 //Cancel button pressed
+
+#define OLEUI_ERR_STANDARDMIN 100
+#define OLEUI_ERR_STRUCTURENULL 101 //Standard field validation
+#define OLEUI_ERR_STRUCTUREINVALID 102
+#define OLEUI_ERR_CBSTRUCTINCORRECT 103
+#define OLEUI_ERR_HWNDOWNERINVALID 104
+#define OLEUI_ERR_LPSZCAPTIONINVALID 105
+#define OLEUI_ERR_LPFNHOOKINVALID 106
+#define OLEUI_ERR_HINSTANCEINVALID 107
+#define OLEUI_ERR_LPSZTEMPLATEINVALID 108
+#define OLEUI_ERR_HRESOURCEINVALID 109
+
+#define OLEUI_ERR_FINDTEMPLATEFAILURE 110 //Initialization errors
+#define OLEUI_ERR_LOADTEMPLATEFAILURE 111
+#define OLEUI_ERR_DIALOGFAILURE 112
+#define OLEUI_ERR_LOCALMEMALLOC 113
+#define OLEUI_ERR_GLOBALMEMALLOC 114
+#define OLEUI_ERR_LOADSTRING 115
+
+#define OLEUI_ERR_STANDARDMAX 116 //Start here for specific errors.
+
+
+
+//Help Button Identifier
+#define ID_OLEUIHELP 99
+
+// Help button for fileopen.dlg (need this for resizing) 1038 is pshHelp
+#define IDHELP 1038
+
+// Static text control (use this instead of -1 so things work correctly for
+// localization
+#define ID_STATIC 98
+
+//Maximum key size we read from the RegDB.
+#define OLEUI_CCHKEYMAX 256 // make any changes to this in geticon.c too
+
+//Maximum verb length and length of Object menu
+#define OLEUI_CCHVERBMAX 32
+#define OLEUI_OBJECTMENUMAX 256
+
+//Maximum MS-DOS pathname.
+#define OLEUI_CCHPATHMAX 256 // make any changes to this in geticon.c too
+#define OLEUI_CCHFILEMAX 13
+
+//Icon label length
+#define OLEUI_CCHLABELMAX 40 // make any changes to this in geticon.c too
+
+//Length of the CLSID string
+#define OLEUI_CCHCLSIDSTRING 39
+
+
+/*
+ * What follows here are first function prototypes for general utility
+ * functions, then sections laid out by dialog. Each dialog section
+ * defines the dialog structure, the API prototype, flags for the dwFlags
+ * field, the dialog-specific error values, and dialog control IDs (for
+ * hooks and custom templates.
+ */
+
+
+//Miscellaneous utility functions.
+STDAPI_(BOOL) OleUIAddVerbMenu(LPOLEOBJECT lpOleObj,
+ LPSTR lpszShortType,
+ HMENU hMenu,
+ UINT uPos,
+ UINT uIDVerbMin,
+ UINT uIDVerbMax,
+ BOOL bAddConvert,
+ UINT idConvert,
+ HMENU FAR *lphMenu);
+
+//Metafile utility functions
+STDAPI_(HGLOBAL) OleUIMetafilePictFromIconAndLabel(HICON, LPSTR, LPSTR, UINT);
+STDAPI_(void) OleUIMetafilePictIconFree(HGLOBAL);
+STDAPI_(BOOL) OleUIMetafilePictIconDraw(HDC, LPRECT, HGLOBAL, BOOL);
+STDAPI_(UINT) OleUIMetafilePictExtractLabel(HGLOBAL, LPSTR, UINT, LPDWORD);
+STDAPI_(HICON) OleUIMetafilePictExtractIcon(HGLOBAL);
+STDAPI_(BOOL) OleUIMetafilePictExtractIconSource(HGLOBAL,LPSTR,UINT FAR *);
+
+
+
+
+
+/*************************************************************************
+** INSERT OBJECT DIALOG
+*************************************************************************/
+
+
+typedef struct tagOLEUIINSERTOBJECT
+ {
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags
+ HWND hWndOwner; //Owning window
+ LPCSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+
+ //Specifics for OLEUIINSERTOBJECT. All are IN-OUT unless otherwise spec.
+ CLSID clsid; //Return space for class ID
+ LPSTR lpszFile; //Filename for inserts or links
+ UINT cchFile; //Size of lpszFile buffer: OLEUI_CCHPATHMAX
+ UINT cClsidExclude; //IN only: CLSIDs in lpClsidExclude
+ LPCLSID lpClsidExclude; //List of CLSIDs to exclude from listing.
+
+ //Specific to create objects if flags say so
+ IID iid; //Requested interface on creation.
+ DWORD oleRender; //Rendering option
+ LPFORMATETC lpFormatEtc; //Desired format
+ LPOLECLIENTSITE lpIOleClientSite; //Site to be use for the object.
+ LPSTORAGE lpIStorage; //Storage used for the object
+ LPVOID FAR *ppvObj; //Where the object is returned.
+ SCODE sc; //Result of creation calls.
+ HGLOBAL hMetaPict; //OUT: METAFILEPICT containing iconic aspect.
+ //IFF we couldn't stuff it in the cache.
+ } OLEUIINSERTOBJECT, *POLEUIINSERTOBJECT, FAR *LPOLEUIINSERTOBJECT;
+
+//API prototype
+STDAPI_(UINT) OleUIInsertObject(LPOLEUIINSERTOBJECT);
+
+
+//Insert Object flags
+#define IOF_SHOWHELP 0x00000001L
+#define IOF_SELECTCREATENEW 0x00000002L
+#define IOF_SELECTCREATEFROMFILE 0x00000004L
+#define IOF_CHECKLINK 0x00000008L
+#define IOF_CHECKDISPLAYASICON 0x00000010L
+#define IOF_CREATENEWOBJECT 0x00000020L
+#define IOF_CREATEFILEOBJECT 0x00000040L
+#define IOF_CREATELINKOBJECT 0x00000080L
+#define IOF_DISABLELINK 0x00000100L
+#define IOF_VERIFYSERVERSEXIST 0x00000200L
+#define IOF_DISABLEDISPLAYASICON 0x00000400L
+
+
+//Insert Object specific error codes
+#define OLEUI_IOERR_LPSZFILEINVALID (OLEUI_ERR_STANDARDMAX+0)
+#define OLEUI_IOERR_LPSZLABELINVALID (OLEUI_ERR_STANDARDMAX+1)
+#define OLEUI_IOERR_HICONINVALID (OLEUI_ERR_STANDARDMAX+2)
+#define OLEUI_IOERR_LPFORMATETCINVALID (OLEUI_ERR_STANDARDMAX+3)
+#define OLEUI_IOERR_PPVOBJINVALID (OLEUI_ERR_STANDARDMAX+4)
+#define OLEUI_IOERR_LPIOLECLIENTSITEINVALID (OLEUI_ERR_STANDARDMAX+5)
+#define OLEUI_IOERR_LPISTORAGEINVALID (OLEUI_ERR_STANDARDMAX+6)
+#define OLEUI_IOERR_SCODEHASERROR (OLEUI_ERR_STANDARDMAX+7)
+#define OLEUI_IOERR_LPCLSIDEXCLUDEINVALID (OLEUI_ERR_STANDARDMAX+8)
+#define OLEUI_IOERR_CCHFILEINVALID (OLEUI_ERR_STANDARDMAX+9)
+
+
+//Insert Object Dialog identifiers
+#define ID_IO_CREATENEW 2100
+#define ID_IO_CREATEFROMFILE 2101
+#define ID_IO_LINKFILE 2102
+#define ID_IO_OBJECTTYPELIST 2103
+#define ID_IO_DISPLAYASICON 2104
+#define ID_IO_CHANGEICON 2105
+#define ID_IO_FILE 2106
+#define ID_IO_FILEDISPLAY 2107
+#define ID_IO_RESULTIMAGE 2108
+#define ID_IO_RESULTTEXT 2109
+#define ID_IO_ICONDISPLAY 2110
+#define ID_IO_OBJECTTYPETEXT 2111
+#define ID_IO_FILETEXT 2112
+#define ID_IO_FILETYPE 2113
+
+// Strings in OLE2UI resources
+#define IDS_IORESULTNEW 32400
+#define IDS_IORESULTNEWICON 32401
+#define IDS_IORESULTFROMFILE1 32402
+#define IDS_IORESULTFROMFILE2 32403
+#define IDS_IORESULTFROMFILEICON2 32404
+#define IDS_IORESULTLINKFILE1 32405
+#define IDS_IORESULTLINKFILE2 32406
+#define IDS_IORESULTLINKFILEICON1 32407
+#define IDS_IORESULTLINKFILEICON2 32408
+
+/*************************************************************************
+** PASTE SPECIAL DIALOG
+*************************************************************************/
+
+// Maximum number of link types
+#define PS_MAXLINKTYPES 8
+
+//NOTE: OLEUIPASTEENTRY and OLEUIPASTEFLAG structs are defined in OLESTD.H
+
+typedef struct tagOLEUIPASTESPECIAL
+ {
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags
+ HWND hWndOwner; //Owning window
+ LPCSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+
+ //Specifics for OLEUIPASTESPECIAL.
+
+ //IN fields
+ LPDATAOBJECT lpSrcDataObj; //Source IDataObject* (on the
+ // clipboard) for data to paste
+
+ LPOLEUIPASTEENTRY arrPasteEntries; //OLEUIPASTEENTRY array which
+ // specifies acceptable formats. See
+ // OLEUIPASTEENTRY for more info.
+ int cPasteEntries; //No. of OLEUIPASTEENTRY array entries
+
+ UINT FAR *arrLinkTypes; //List of link types that are
+ // acceptable. Link types are referred
+ // to using OLEUIPASTEFLAGS in
+ // arrPasteEntries
+ int cLinkTypes; //Number of link types
+ UINT cClsidExclude; //Number of CLSIDs in lpClsidExclude
+ LPCLSID lpClsidExclude; //List of CLSIDs to exclude from list.
+
+ //OUT fields
+ int nSelectedIndex; //Index of arrPasteEntries[] that the
+ // user selected
+ BOOL fLink; //Indicates if Paste or Paste Link was
+ // selected by the user
+ HGLOBAL hMetaPict; //Handle to Metafile containing icon
+ // and icon title selected by the user
+ // Use the Metafile utility functions
+ // defined in this header to
+ // manipulate hMetaPict
+ SIZEL sizel; // size of object/link in its source
+ // if the display aspect chosen by
+ // the user matches the aspect
+ // displayed in the source. if
+ // different aspect is chosen then
+ // sizel.cx=sizel.cy=0 is returned.
+ // sizel displayed in source is
+ // retrieved from the
+ // ObjectDescriptor if fLink is FALSE
+ // LinkSrcDescriptor if fLink is TRUE
+ } OLEUIPASTESPECIAL, *POLEUIPASTESPECIAL, FAR *LPOLEUIPASTESPECIAL;
+
+
+//API to bring up PasteSpecial dialog
+STDAPI_(UINT) OleUIPasteSpecial(LPOLEUIPASTESPECIAL);
+
+
+//Paste Special flags
+// Show Help button. IN flag.
+#define PSF_SHOWHELP 0x00000001L
+
+//Select Paste radio button at dialog startup. This is the default if
+// PSF_SELECTPASTE or PSF_SELECTPASTELINK are not specified. Also specifies
+// state of button on dialog termination. IN/OUT flag.
+#define PSF_SELECTPASTE 0x00000002L
+
+//Select PasteLink radio button at dialog startup. Also specifies state of
+// button on dialog termination. IN/OUT flag.
+#define PSF_SELECTPASTELINK 0x00000004L
+
+//Specfies if DisplayAsIcon button was checked on dialog termination. OUT flag
+#define PSF_CHECKDISPLAYASICON 0x00000008L
+#define PSF_DISABLEDISPLAYASICON 0x00000010L
+
+
+//Paste Special specific error codes
+#define OLEUI_IOERR_SRCDATAOBJECTINVALID (OLEUI_ERR_STANDARDMAX+0)
+#define OLEUI_IOERR_ARRPASTEENTRIESINVALID (OLEUI_ERR_STANDARDMAX+1)
+#define OLEUI_IOERR_ARRLINKTYPESINVALID (OLEUI_ERR_STANDARDMAX+2)
+#define OLEUI_PSERR_CLIPBOARDCHANGED (OLEUI_ERR_STANDARDMAX+3)
+
+//Paste Special Dialog identifiers
+#define ID_PS_PASTE 500
+#define ID_PS_PASTELINK 501
+#define ID_PS_SOURCETEXT 502
+#define ID_PS_PASTELIST 503
+#define ID_PS_PASTELINKLIST 504
+#define ID_PS_DISPLAYLIST 505
+#define ID_PS_DISPLAYASICON 506
+#define ID_PS_ICONDISPLAY 507
+#define ID_PS_CHANGEICON 508
+#define ID_PS_RESULTIMAGE 509
+#define ID_PS_RESULTTEXT 510
+#define ID_PS_RESULTGROUP 511
+#define ID_PS_STXSOURCE 512
+#define ID_PS_STXAS 513
+
+// Paste Special String IDs
+#define IDS_PSPASTEDATA 32410
+#define IDS_PSPASTEOBJECT 32411
+#define IDS_PSPASTEOBJECTASICON 32412
+#define IDS_PSPASTELINKDATA 32413
+#define IDS_PSPASTELINKOBJECT 32414
+#define IDS_PSPASTELINKOBJECTASICON 32415
+#define IDS_PSNONOLE 32416
+#define IDS_PSUNKNOWNTYPE 32417
+#define IDS_PSUNKNOWNSRC 32418
+#define IDS_PSUNKNOWNAPP 32419
+
+
+/*************************************************************************
+** EDIT LINKS DIALOG
+*************************************************************************/
+
+
+
+/* IOleUILinkContainer Interface
+** -----------------------------
+** This interface must be implemented by container applications that
+** want to use the EditLinks dialog. the EditLinks dialog calls back
+** to the container app to perform the OLE functions to manipulate
+** the links within the container.
+*/
+
+#define LPOLEUILINKCONTAINER IOleUILinkContainer FAR*
+
+#undef INTERFACE
+#define INTERFACE IOleUILinkContainer
+
+DECLARE_INTERFACE_(IOleUILinkContainer, IUnknown)
+{
+ //*** IUnknown methods ***/
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ STDMETHOD_(DWORD,GetNextLink) (THIS_ DWORD dwLink) PURE;
+ STDMETHOD(SetLinkUpdateOptions) (THIS_ DWORD dwLink, DWORD dwUpdateOpt) PURE;
+ STDMETHOD(GetLinkUpdateOptions) (THIS_ DWORD dwLink, DWORD FAR* lpdwUpdateOpt) PURE;
+ STDMETHOD(SetLinkSource) (THIS_
+ DWORD dwLink,
+ LPSTR lpszDisplayName,
+ ULONG lenFileName,
+ ULONG FAR* pchEaten,
+ BOOL fValidateSource) PURE;
+ STDMETHOD(GetLinkSource) (THIS_
+ DWORD dwLink,
+ LPSTR FAR* lplpszDisplayName,
+ ULONG FAR* lplenFileName,
+ LPSTR FAR* lplpszFullLinkType,
+ LPSTR FAR* lplpszShortLinkType,
+ BOOL FAR* lpfSourceAvailable,
+ BOOL FAR* lpfIsSelected) PURE;
+ STDMETHOD(OpenLinkSource) (THIS_ DWORD dwLink) PURE;
+ STDMETHOD(UpdateLink) (THIS_
+ DWORD dwLink,
+ BOOL fErrorMessage,
+ BOOL fErrorAction) PURE;
+ STDMETHOD(CancelLink) (THIS_ DWORD dwLink) PURE;
+};
+
+
+typedef struct tagOLEUIEDITLINKS
+ {
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags
+ HWND hWndOwner; //Owning window
+ LPCSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+
+ //Specifics for OLEUI<STRUCT>. All are IN-OUT unless otherwise spec.
+
+ LPOLEUILINKCONTAINER lpOleUILinkContainer; //IN: Interface to manipulate
+ //links in the container
+ } OLEUIEDITLINKS, *POLEUIEDITLINKS, FAR *LPOLEUIEDITLINKS;
+
+
+//API Prototype
+STDAPI_(UINT) OleUIEditLinks(LPOLEUIEDITLINKS);
+
+
+// Edit Links flags
+#define ELF_SHOWHELP 0x00000001L
+#define ELF_DISABLEUPDATENOW 0x00000002L
+#define ELF_DISABLEOPENSOURCE 0x00000004L
+#define ELF_DISABLECHANGESOURCE 0x00000008L
+#define ELF_DISABLECANCELLINK 0x00000010L
+
+// Edit Links Dialog identifiers
+#define ID_EL_CHANGESOURCE 201
+#define ID_EL_AUTOMATIC 202
+#define ID_EL_CLOSE 208
+#define ID_EL_CANCELLINK 209
+#define ID_EL_UPDATENOW 210
+#define ID_EL_OPENSOURCE 211
+#define ID_EL_MANUAL 212
+#define ID_EL_LINKSOURCE 216
+#define ID_EL_LINKTYPE 217
+#define ID_EL_UPDATE 218
+#define ID_EL_NULL -1
+#define ID_EL_LINKSLISTBOX 206
+#define ID_EL_COL1 220
+#define ID_EL_COL2 221
+#define ID_EL_COL3 222
+
+
+
+/*************************************************************************
+** CHANGE ICON DIALOG
+*************************************************************************/
+
+typedef struct tagOLEUICHANGEICON
+ {
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags
+ HWND hWndOwner; //Owning window
+ LPCSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+
+ //Specifics for OLEUICHANGEICON. All are IN-OUT unless otherwise spec.
+ HGLOBAL hMetaPict; //Current and final image. Source of the
+ //icon is embedded in the metafile itself.
+ CLSID clsid; //IN only: class used to get Default icon
+ char szIconExe[OLEUI_CCHPATHMAX];
+ int cchIconExe;
+ } OLEUICHANGEICON, *POLEUICHANGEICON, FAR *LPOLEUICHANGEICON;
+
+
+//API prototype
+STDAPI_(UINT) OleUIChangeIcon(LPOLEUICHANGEICON);
+
+
+//Change Icon flags
+#define CIF_SHOWHELP 0x00000001L
+#define CIF_SELECTCURRENT 0x00000002L
+#define CIF_SELECTDEFAULT 0x00000004L
+#define CIF_SELECTFROMFILE 0x00000008L
+#define CIF_USEICONEXE 0x0000000aL
+
+
+//Change Icon specific error codes
+#define OLEUI_CIERR_MUSTHAVECLSID (OLEUI_ERR_STANDARDMAX+0)
+#define OLEUI_CIERR_MUSTHAVECURRENTMETAFILE (OLEUI_ERR_STANDARDMAX+1)
+#define OLEUI_CIERR_SZICONEXEINVALID (OLEUI_ERR_STANDARDMAX+2)
+
+
+//Change Icon Dialog identifiers
+#define ID_GROUP 120
+#define ID_CURRENT 121
+#define ID_CURRENTICON 122
+#define ID_DEFAULT 123
+#define ID_DEFAULTICON 124
+#define ID_FROMFILE 125
+#define ID_FROMFILEEDIT 126
+#define ID_ICONLIST 127
+#define ID_LABEL 128
+#define ID_LABELEDIT 129
+#define ID_BROWSE 130
+#define ID_RESULTICON 132
+#define ID_RESULTLABEL 133
+
+// Stringtable defines for Change Icon
+#define IDS_CINOICONSINFILE 32430
+#define IDS_CIINVALIDFILE 32431
+#define IDS_CIFILEACCESS 32432
+#define IDS_CIFILESHARE 32433
+#define IDS_CIFILEOPENFAIL 32434
+
+
+
+/*************************************************************************
+** CONVERT DIALOG
+*************************************************************************/
+
+typedef struct tagOLEUICONVERT
+ {
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags
+ HWND hWndOwner; //Owning window
+ LPCSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+
+ //Specifics for OLEUICONVERT. All are IN-OUT unless otherwise spec.
+ CLSID clsid; //Class ID sent in to dialog: IN only
+ CLSID clsidConvertDefault; //Class ID to use as convert default: IN only
+ CLSID clsidActivateDefault; //Class ID to use as activate default: IN only
+
+ CLSID clsidNew; //Selected Class ID: OUT only
+ DWORD dvAspect; //IN-OUT, either DVASPECT_CONTENT or
+ //DVASPECT_ICON
+ WORD wFormat; //Original data format
+ BOOL fIsLinkedObject; //IN only; true if object is linked
+ HGLOBAL hMetaPict; //IN-OUT: METAFILEPICT containing iconic aspect.
+ LPSTR lpszUserType; //IN-OUT: user type name of original class.
+ // We'll do lookup if it's NULL.
+ // This gets freed on exit.
+ BOOL fObjectsIconChanged; // OUT; TRUE if ChangeIcon was called (and not cancelled)
+ LPSTR lpszDefLabel; //IN-OUT: default label to use for icon.
+ // if NULL, the short user type name
+ // will be used. if the object is a
+ // link, the caller should pass the
+ // DisplayName of the link source
+ // This gets freed on exit.
+
+ UINT cClsidExclude; //IN: No. of CLSIDs in lpClsidExclude
+ LPCLSID lpClsidExclude; //IN: List of CLSIDs to exclude from list
+ } OLEUICONVERT, *POLEUICONVERT, FAR *LPOLEUICONVERT;
+
+
+//API prototype
+STDAPI_(UINT) OleUIConvert(LPOLEUICONVERT);
+
+// Determine if there is at least one class that can Convert or ActivateAs
+// the given clsid.
+STDAPI_(BOOL) OleUICanConvertOrActivateAs(
+ REFCLSID rClsid,
+ BOOL fIsLinkedObject,
+ WORD wFormat
+);
+
+//Convert Dialog flags
+
+// IN only: Shows "HELP" button
+#define CF_SHOWHELPBUTTON 0x00000001L
+
+// IN only: lets you set the convert default object - the one that is
+// selected as default in the convert listbox.
+#define CF_SETCONVERTDEFAULT 0x00000002L
+
+
+// IN only: lets you set the activate default object - the one that is
+// selected as default in the activate listbox.
+
+#define CF_SETACTIVATEDEFAULT 0x00000004L
+
+
+// IN/OUT: Selects the "Convert To" radio button, is set on exit if
+// this button was selected
+#define CF_SELECTCONVERTTO 0x00000008L
+
+// IN/OUT: Selects the "Activate As" radio button, is set on exit if
+// this button was selected
+#define CF_SELECTACTIVATEAS 0x00000010L
+#define CF_DISABLEDISPLAYASICON 0x00000020L
+#define CF_DISABLEACTIVATEAS 0x00000040L
+
+
+//Convert specific error codes
+#define OLEUI_CTERR_CLASSIDINVALID (OLEUI_ERR_STANDARDMAX+1)
+#define OLEUI_CTERR_DVASPECTINVALID (OLEUI_ERR_STANDARDMAX+2)
+#define OLEUI_CTERR_CBFORMATINVALID (OLEUI_ERR_STANDARDMAX+3)
+#define OLEUI_CTERR_HMETAPICTINVALID (OLEUI_ERR_STANDARDMAX+4)
+#define OLEUI_CTERR_STRINGINVALID (OLEUI_ERR_STANDARDMAX+5)
+
+
+//Convert Dialog identifiers
+#define IDCV_OBJECTTYPE 150
+#define IDCV_DISPLAYASICON 152
+#define IDCV_CHANGEICON 153
+#define IDCV_ACTIVATELIST 154
+#define IDCV_CONVERTTO 155
+#define IDCV_ACTIVATEAS 156
+#define IDCV_RESULTTEXT 157
+#define IDCV_CONVERTLIST 158
+#define IDCV_ICON 159
+#define IDCV_ICONLABEL1 160
+#define IDCV_ICONLABEL2 161
+#define IDCV_STXCURTYPE 162
+#define IDCV_GRPRESULT 163
+#define IDCV_STXCONVERTTO 164
+
+// String IDs for Convert dialog
+#define IDS_CVRESULTCONVERTLINK 32440
+#define IDS_CVRESULTCONVERTTO 32441
+#define IDS_CVRESULTNOCHANGE 32442
+#define IDS_CVRESULTDISPLAYASICON 32443
+#define IDS_CVRESULTACTIVATEAS 32444
+#define IDS_CVRESULTACTIVATEDIFF 32445
+
+
+/*************************************************************************
+** BUSY DIALOG
+*************************************************************************/
+
+typedef struct tagOLEUIBUSY
+ {
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags ** NOTE ** this dialog has no flags
+ HWND hWndOwner; //Owning window
+ LPCSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+
+ //Specifics for OLEUIBUSY.
+ HTASK hTask; //IN: HTask which is blocking
+ HWND FAR * lphWndDialog; //IN: Dialog's HWND is placed here
+ } OLEUIBUSY, *POLEUIBUSY, FAR *LPOLEUIBUSY;
+
+//API prototype
+STDAPI_(UINT) OleUIBusy(LPOLEUIBUSY);
+
+// Flags for this dialog
+
+// IN only: Disables "Cancel" button
+#define BZ_DISABLECANCELBUTTON 0x00000001L
+
+// IN only: Disables "Switch To..." button
+#define BZ_DISABLESWITCHTOBUTTON 0x00000002L
+
+// IN only: Disables "Retry" button
+#define BZ_DISABLERETRYBUTTON 0x00000004L
+
+// IN only: Generates a "Not Responding" dialog as opposed to the
+// "Busy" dialog. The wording in the text is slightly different, and
+// the "Cancel" button is grayed out if you set this flag.
+#define BZ_NOTRESPONDINGDIALOG 0x00000008L
+
+// Busy specific error/return codes
+#define OLEUI_BZERR_HTASKINVALID (OLEUI_ERR_STANDARDMAX+0)
+
+// SWITCHTOSELECTED is returned when user hit "switch to"
+#define OLEUI_BZ_SWITCHTOSELECTED (OLEUI_ERR_STANDARDMAX+1)
+
+// RETRYSELECTED is returned when user hit "retry"
+#define OLEUI_BZ_RETRYSELECTED (OLEUI_ERR_STANDARDMAX+2)
+
+// CALLUNBLOCKED is returned when call has been unblocked
+#define OLEUI_BZ_CALLUNBLOCKED (OLEUI_ERR_STANDARDMAX+3)
+
+// Busy dialog identifiers
+#define IDBZ_RETRY 600
+#define IDBZ_ICON 601
+#define IDBZ_MESSAGE1 602
+#define IDBZ_SWITCHTO 604
+
+// Busy dialog stringtable defines
+#define IDS_BZRESULTTEXTBUSY 32447
+#define IDS_BZRESULTTEXTNOTRESPONDING 32448
+
+// Links dialog stringtable defines
+#define IDS_LINK_AUTO 32450
+#define IDS_LINK_MANUAL 32451
+#define IDS_LINK_UNKNOWN 32452
+#define IDS_LINKS 32453
+#define IDS_FAILED 32454
+#define IDS_CHANGESOURCE 32455
+#define IDS_INVALIDSOURCE 32456
+#define IDS_ERR_GETLINKSOURCE 32457
+#define IDS_ERR_GETLINKUPDATEOPTIONS 32458
+#define IDS_ERR_ADDSTRING 32459
+#define IDS_CHANGEADDITIONALLINKS 32460
+#define IDS_CLOSE 32461
+
+
+/*************************************************************************
+** PROMPT USER DIALOGS
+*************************************************************************/
+#define ID_PU_LINKS 900
+#define ID_PU_TEXT 901
+#define ID_PU_CONVERT 902
+#define ID_PU_BROWSE 904
+#define ID_PU_METER 905
+#define ID_PU_PERCENT 906
+#define ID_PU_STOP 907
+
+// used for -1 ids in dialogs:
+#define ID_DUMMY 999
+
+/* inside ole2ui.c */
+#ifdef __cplusplus
+extern "C"
+#endif
+int EXPORT FAR CDECL OleUIPromptUser(WORD nTemplate, HWND hwndParent, ...);
+
+#define UPDATELINKS_STARTDELAY 2000 // Delay before 1st link updates
+ // to give the user a chance to
+ // dismiss the dialog before any
+ // links update.
+
+STDAPI_(BOOL) OleUIUpdateLinks(
+ LPOLEUILINKCONTAINER lpOleUILinkCntr,
+ HWND hwndParent,
+ LPSTR lpszTitle,
+ int cLinks);
+
+
+/*************************************************************************
+** OLE OBJECT FEEDBACK EFFECTS
+*************************************************************************/
+
+#define OLEUI_HANDLES_USEINVERSE 0x00000001L
+#define OLEUI_HANDLES_NOBORDER 0x00000002L
+#define OLEUI_HANDLES_INSIDE 0x00000004L
+#define OLEUI_HANDLES_OUTSIDE 0x00000008L
+
+
+#define OLEUI_SHADE_FULLRECT 1
+#define OLEUI_SHADE_BORDERIN 2
+#define OLEUI_SHADE_BORDEROUT 3
+
+/* objfdbk.c function prototypes */
+STDAPI_(void) OleUIDrawHandles(LPRECT lpRect, HDC hdc, DWORD dwFlags, UINT cSize, BOOL fDraw);
+STDAPI_(void) OleUIDrawShading(LPRECT lpRect, HDC hdc, DWORD dwFlags, UINT cWidth);
+STDAPI_(void) OleUIShowObject(LPCRECT lprc, HDC hdc, BOOL fIsLink);
+
+
+/*************************************************************************
+** Hatch window definitions and prototypes **
+*************************************************************************/
+#define DEFAULT_HATCHBORDER_WIDTH 4
+
+STDAPI_(BOOL) RegisterHatchWindowClass(HINSTANCE hInst);
+STDAPI_(HWND) CreateHatchWindow(HWND hWndParent, HINSTANCE hInst);
+STDAPI_(UINT) GetHatchWidth(HWND hWndHatch);
+STDAPI_(void) GetHatchRect(HWND hWndHatch, LPRECT lpHatchRect);
+STDAPI_(void) SetHatchRect(HWND hWndHatch, LPRECT lprcHatchRect);
+STDAPI_(void) SetHatchWindowSize(
+ HWND hWndHatch,
+ LPRECT lprcIPObjRect,
+ LPRECT lprcClipRect,
+ LPPOINT lpptOffset
+);
+
+
+
+/*************************************************************************
+** VERSION VERIFICATION INFORMATION
+*************************************************************************/
+
+// The following magic number is used to verify that the resources we bind
+// to our EXE are the same "version" as the LIB (or DLL) file which
+// contains these routines. This is not the same as the Version information
+// resource that we place in OLE2UI.RC, this is a special ID that we will
+// have compiled in to our EXE. Upon initialization of OLE2UI, we will
+// look in our resources for an RCDATA called "VERIFICATION" (see OLE2UI.RC),
+// and make sure that the magic number there equals the magic number below.
+
+#define OLEUI_VERSION_MAGIC 0x4D42
+
+#endif //_OLE2UI_H_
diff --git a/private/ole32/olethunk/ole16/inc/ole2ver.h b/private/ole32/olethunk/ole16/inc/ole2ver.h
new file mode 100644
index 000000000..5b14d7aac
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/ole2ver.h
@@ -0,0 +1,4 @@
+#define rmj 0
+#define rmm 23
+#define rup 640
+#define szVerName ""
diff --git a/private/ole32/olethunk/ole16/inc/olecoll.h b/private/ole32/olethunk/ole16/inc/olecoll.h
new file mode 100644
index 000000000..a6fc98ecf
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/olecoll.h
@@ -0,0 +1,73 @@
+// Microsoft OLE library.
+// Copyright (C) 1992 Microsoft Corporation,
+// All rights reserved.
+
+// olecoll.h - global defines for collections and element definitions
+
+#ifndef __OLECOLL_H__
+#define __OLECOLL_H__
+
+
+// ---------------------------------------------------------------------------
+// general defines for collections
+
+typedef void FAR* POSITION;
+
+#define BEFORE_START_POSITION ((POSITION)(ULONG)-1L)
+#define _AFX_FP_OFF(thing) (*((UINT FAR*)&(thing)))
+#define _AFX_FP_SEG(lp) (*((UINT FAR*)&(lp)+1))
+
+#ifdef _DEBUG
+#define ASSERT_VALID(p) p->AssertValid()
+#else
+#define ASSERT_VALID(p)
+#endif
+
+
+// ---------------------------------------------------------------------------
+// element defintions; can only depend upon definitions in ole2int.h
+
+// per-task data; warning, there is no destructor and so
+// releasing the elements of the mapping must be done by hand;
+// this also means that RemoveAll should not be called and that
+// RemoveKey should be called only after freeing the contained maps.
+typedef struct FAR Etask
+{
+ DWORD m_pid; // unique process id
+ DWORD m_Dllinits; // number of times init'd
+ HTASK m_htask;
+ DWORD m_inits; // number of times init'd
+ DWORD m_oleinits; // number of OleInit
+ DWORD m_reserved; // reserved
+ IMalloc FAR* m_pMalloc; // task allocator (always one)
+ IMalloc FAR* m_pMallocShared; // shared allocator (always one)
+ IMalloc FAR* m_pMallocSBlock; // shared block allocator (if one)
+ IMalloc FAR* m_pMallocPrivate; // private allocator (if one)
+ class CDlls FAR* m_pDlls; // list of dlls loaded and their counts
+ class CMapGUIDToPtr FAR* m_pMapToServerCO;//server class obj if reg/loaded
+ class CMapGUIDToPtr FAR* m_pMapToHandlerCO;//handler CO obj if reg/loaded
+
+ class CSHArray FAR* m_pArraySH; // array of server/handler entries
+
+ class CThrd FAR* m_pCThrd; // pointer to header of thread list
+ HWND m_hwndClip; // hwnd of our clip window
+ HWND m_hwndDde; // hwnd of system dde window
+ IUnknown FAR* m_punkState; // Storage for CoGet/SetState
+} _Etask;
+
+//
+// BUGBUG - This header file was taken from \\ole\slm\src\dll\src\inc
+// But it appears to need everything in the world, even though it doesn't
+// use it. Bad factoring of header file info I bet. For now I'm commenting
+// this out until its proven that I need it.
+//
+#ifdef LATER
+// per-proxy/stub dll info (Epsdll); must release elements by hand as above.
+struct FAR Epsdll
+{
+ IPSFactory FAR* m_pPSFactory; // pointer to ps factory
+ class CPtrArray FAR* m_rgPS; // proxies/stubs which are loaded
+};
+#endif
+
+#endif //!__OLECOLL_H__
diff --git a/private/ole32/olethunk/ole16/inc/oleguid.h b/private/ole32/olethunk/ole16/inc/oleguid.h
new file mode 100644
index 000000000..723fa50d7
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/oleguid.h
@@ -0,0 +1,80 @@
+/*****************************************************************************\
+* *
+* oleguid.h - Master definition of GUIDs for ole2.dll *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+/* this file is the master definition of all public GUIDs specific to OLE
+ and is included in ole2.h.
+
+ NOTE: The second least significant byte of all of these GUIDs is 1.
+*/
+
+
+DEFINE_OLEGUID(IID_IEnumUnknown, 0x00000100, 0, 0);
+DEFINE_OLEGUID(IID_IEnumString, 0x00000101, 0, 0);
+DEFINE_OLEGUID(IID_IEnumMoniker, 0x00000102, 0, 0);
+DEFINE_OLEGUID(IID_IEnumFORMATETC, 0x00000103, 0, 0);
+DEFINE_OLEGUID(IID_IEnumOLEVERB, 0x00000104, 0, 0);
+DEFINE_OLEGUID(IID_IEnumSTATDATA, 0x00000105, 0, 0);
+
+DEFINE_OLEGUID(IID_IEnumGeneric, 0x00000106, 0, 0);
+DEFINE_OLEGUID(IID_IEnumHolder, 0x00000107, 0, 0);
+DEFINE_OLEGUID(IID_IEnumCallback, 0x00000108, 0, 0);
+
+DEFINE_OLEGUID(IID_IPersistStream, 0x00000109, 0, 0);
+DEFINE_OLEGUID(IID_IPersistStorage, 0x0000010a, 0, 0);
+DEFINE_OLEGUID(IID_IPersistFile, 0x0000010b, 0, 0);
+DEFINE_OLEGUID(IID_IPersist, 0x0000010c, 0, 0);
+
+DEFINE_OLEGUID(IID_IViewObject, 0x0000010d, 0, 0);
+DEFINE_OLEGUID(IID_IDataObject, 0x0000010e, 0, 0);
+DEFINE_OLEGUID(IID_IAdviseSink, 0x0000010f, 0, 0);
+DEFINE_OLEGUID(IID_IDataAdviseHolder, 0x00000110, 0, 0);
+DEFINE_OLEGUID(IID_IOleAdviseHolder, 0x00000111, 0, 0);
+
+DEFINE_OLEGUID(IID_IOleObject, 0x00000112, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceObject, 0x00000113, 0, 0);
+DEFINE_OLEGUID(IID_IOleWindow, 0x00000114, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceUIWindow, 0x00000115, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceFrame, 0x00000116, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceActiveObject, 0x00000117, 0, 0);
+
+DEFINE_OLEGUID(IID_IOleClientSite, 0x00000118, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceSite, 0x00000119, 0, 0);
+
+DEFINE_OLEGUID(IID_IParseDisplayName, 0x0000011a, 0, 0);
+DEFINE_OLEGUID(IID_IOleContainer, 0x0000011b, 0, 0);
+DEFINE_OLEGUID(IID_IOleItemContainer, 0x0000011c, 0, 0);
+
+DEFINE_OLEGUID(IID_IOleLink, 0x0000011d, 0, 0);
+DEFINE_OLEGUID(IID_IOleCache, 0x0000011e, 0, 0);
+DEFINE_OLEGUID(IID_IOleManager, 0x0000011f, 0, 0); // unused
+DEFINE_OLEGUID(IID_IOlePresObj, 0x00000120, 0, 0);
+
+DEFINE_OLEGUID(IID_IDropSource, 0x00000121, 0, 0);
+DEFINE_OLEGUID(IID_IDropTarget, 0x00000122, 0, 0);
+
+DEFINE_OLEGUID(IID_IDebug, 0x00000123, 0, 0);
+DEFINE_OLEGUID(IID_IDebugStream, 0x00000124, 0, 0);
+
+DEFINE_OLEGUID(IID_IAdviseSink2, 0x00000125, 0, 0);
+
+DEFINE_OLEGUID(IID_IRunnableObject, 0x00000126, 0, 0);
+
+DEFINE_OLEGUID(IID_IViewObject2, 0x00000127, 0, 0);
+DEFINE_OLEGUID(IID_IOleCache2, 0x00000128, 0, 0);
+DEFINE_OLEGUID(IID_IOleCacheControl, 0x00000129, 0, 0);
+
+/* NOTE: LSB values 0x27 through 0xff are reserved */
+
+
+/* GUIDs defined in OLE's private range */
+DEFINE_OLEGUID(CLSID_Picture_Metafile, 0x00000315, 0, 0);
+DEFINE_OLEGUID(CLSID_Picture_Dib, 0x00000316, 0, 0);
+
+
diff --git a/private/ole32/olethunk/ole16/inc/olemem.h b/private/ole32/olethunk/ole16/inc/olemem.h
new file mode 100644
index 000000000..6da9dc8eb
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/olemem.h
@@ -0,0 +1,59 @@
+#if !defined( _OLEMEM_H_ )
+#define _OLEMEM_H_
+
+// All the following Global calls deal with LPSTR
+
+#ifdef _MAC
+pascal DWORD OleGlobalSize(HANDLE);
+pascal LPSTR OleGlobalAlloc(WORD, DWORD);
+pascal BOOL OleGlobalFree(LPSTR); // true success, false fail
+pascal LPSTR OleGlobalLock(HANDLE);
+pascal BOOL OleGlobalUnlock(LPSTR); // true success, false fail
+
+#else
+
+#define OleGlobalAlloc(flags,dwSize) ( \
+ Win(GlobalLock(GlobalAlloc(flags, dwSize)))\
+)
+
+#define OleGlobalFree(lp) ( \
+ Win(GlobalFree((HANDLE)GlobalHandle((__segment)lp))) \
+)
+
+#define OleGlobalLock(hMem) ( \
+ Win(GlobalLock(hMem))\
+)
+
+#define OleGlobalUnlock(lp) ( \
+ Win(GlobalUnlock((HANDLE)GlobalHandle((__segment)lp))) \
+)
+
+#endif
+
+
+
+#ifndef _MAC // Windows
+
+// All the following Local calls deal with PSTR
+
+#define OleLocalAlloc(flags,wSize) (LocalLock(LocalAlloc(flags, wSize)))
+
+#define OleLocalFree(np) {\
+ LocalUnlock((HANDLE)LocalHandle((WORD)np)); \
+ LocalFree((HANDLE)LocalHandle((WORD)np)); \
+}
+
+#define OleLocalLock(hMem) (LocalLock(hMem))
+
+#define OleLocalUnlock(np) (LocalUnlock((HANDLE)LocalHandle((WORD)np)))
+
+#else // MAC
+
+#define OleLocalAlloc(flags,wSize) OleGlobalAlloc(flags, wSize)
+#define OleLocalFree (ptr) OleGlobalFree(ptr)
+#define OleLocalLock(hMem) OleGlobalLock(hMem)
+#define OleLocalUnlock(ptr) OleGlobalUnlock(ptr)
+
+#endif
+
+#endif // _OLEMEM_H
diff --git a/private/ole32/olethunk/ole16/inc/olerem.h b/private/ole32/olethunk/ole16/inc/olerem.h
new file mode 100644
index 000000000..5d6bd5700
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/olerem.h
@@ -0,0 +1,523 @@
+// olerem.h - private defintions for OLE implementation of REMoting
+
+#if !defined( _OLEREM_H_ )
+#define _OLEREM_H_
+
+// name changes
+#define ILrpc IRpcChannel
+#define IStub IRpcStub
+#define IProxy IRpcProxy
+#define Dispatch Invoke
+
+#define IID_ILrpc IID_IRpcChannel
+#define IID_IStub IID_IRpcStub
+#define IID_IProxy IID_IRpcProxy
+
+// -----------------------------------------------------------------------
+// init/term
+
+STDAPI RemInitialize(void);
+STDAPI_(void) RemUninitialize(void);
+
+#ifdef _MAC
+// entry point for lrpc HLE's
+STDAPI RemProcessLrpcHLE(EventRecord *pHle);
+#endif
+
+// -----------------------------------------------------------------------
+// Communications Layer
+
+typedef LONG OID;
+
+STDAPI_(OID) RemAllocOID(interface IStubManager FAR* pSM);
+STDAPI_(BOOL) RemFreeOID(OID oid);
+
+// NOTE: ILrpc defined in stdps.h
+
+STDAPI RemConnectToObject(OID oid, ILrpc FAR* FAR* ppLrpc);
+STDAPI RemDisconnectObject(OID oid, DWORD dwReserved);
+
+
+// -----------------------------------------------------------------------
+// State Management
+
+// Class Factory Table
+
+STDAPI RemRegisterFactory(REFCLSID rclsid, IUnknown FAR* pUnk, DWORD dwContext,
+ DWORD flags, LPDWORD lpdwRegister);
+STDAPI RemRevokeFactory(DWORD dwRegister, LPCLSID lpclsid,
+ IUnknown FAR* FAR* ppUnk, LPDWORD lpdwContext);
+STDAPI RemLookupFactory(REFCLSID rclsid, BOOL fHide, OID FAR *pOid);
+
+
+// Handler Table
+
+interface IProxyManager : public IUnknown
+{
+ STDMETHOD(CreateServer)(REFCLSID rclsid) = 0;
+ STDMETHOD(Connect)(OID oid, REFCLSID rclsid) = 0;
+ STDMETHOD(LockConnection)(BOOL fLock, BOOL fLastUnlockReleases) = 0;
+ STDMETHOD_(void, GetClassID)(CLSID FAR* pClsid) = 0;
+ STDMETHOD_(OID, GetOID)() = 0;
+ STDMETHOD_(BOOL, IsConnected)(void) = 0;
+ STDMETHOD(EstablishIID)(REFIID iid, LPVOID FAR* ppv) = 0;
+ STDMETHOD_(void, Disconnect)() = 0;
+};
+
+INTERNAL RemSetHandler(OID oid, REFCLSID clsid, IProxyManager FAR* pPM);
+INTERNAL RemClearHandler(OID oid, IProxyManager FAR* pPM);
+
+
+
+// Server Table
+
+interface IStubManager : public IUnknown
+{
+ STDMETHOD_(void, SetReg)(OID oid) = 0;
+ STDMETHOD_(void, Connect)(IUnknown FAR* pUnk) = 0;
+ STDMETHOD_(void, Disconnect)() = 0;
+ STDMETHOD_(OID, GetOID)() = 0;
+ STDMETHOD_(IUnknown FAR*, GetServer)(BOOL fAddRef) = 0;
+ STDMETHOD_(void, AddRefRegConn)(DWORD mshlflags) = 0;
+ STDMETHOD_(void, ReleaseRegConn)(DWORD mshlflags, BOOL fLastUR) = 0;
+ STDMETHOD (Dispatch)(REFIID iid, int iMethod, IStream FAR* pIStream,
+ DWORD dwDestCtx, LPVOID lpvDestCtx, BOOL FAR* lpfStrongConn) = 0;
+};
+
+// tables are now merged; combined registration:
+
+// MSHLHDR: first part of what is written to marshal stream
+struct FAR MSHLHDR
+{
+ CLSID clsid; // oid == NULL -> unmarshal class
+ // oid != NULL -> class of handler
+ OID oid; // global id for object
+ DWORD mshlflags; // marshal flags
+};
+
+
+struct FAR SHREG
+{
+ MSHLHDR m_hdr; // simplifies things; see below
+ IUnknown FAR* m_pUnkLookup; // NOTE: no addref
+ IStubManager FAR* m_pSM; // if NULL, have handler
+};
+
+// There are two forms of SHREG:
+// 1. server registration:
+// m_hdr.clsid is class of handler
+// m_hdr.oid is non-NULL
+// m_hdr.mshlflags is NULL
+// m_pUnkLookup = non-addref'd pointer to server; not necessarily valid
+// (not valid when stubmgr disconnected, but still registered)
+// m_pSM = addref'd pointer to stubmgr.
+//
+// 2. handler registration (when connected to server)
+// m_hdr.clsid is class of handler (same as above)
+// m_hdr.oid is non-NULL
+// m_hdr.mshlflags is NULL
+// m_pUnkLookup = non-addref'd pProxyManager of handler; always valid
+// m_pSM = NULL
+//
+// NOTE: the MSHLHDR is present in the SHREG so as to make CoMarshalInterface
+// faster. The m_hdr.mshlflags is always zero in a reg entry; is set before
+// writing the hdr to a stream.
+//
+// We get and save the clsid so that we don't have to figure it out each
+// time we marshal the interface.
+
+// see olerem2.h for inline functions that manipulate SHREGs.
+
+STDAPI RemRegisterServer(IUnknown FAR* pUnk, DWORD mshlflags, SHREG FAR* pshreg);
+STDAPI RemRevokeServer(OID oid);
+STDAPI RemLookupSHOID(OID oid, IProxyManager FAR* FAR* ppPM,
+ IStubManager FAR* FAR* ppSM);
+STDAPI RemLookupSHUnk(IUnknown FAR* pUnkGiven, IUnknown FAR* FAR* ppUnkServer, SHREG FAR* pshreg);
+
+
+// -----------------------------------------------------------------------
+// Other Routines
+
+STDAPI RemCreateRemoteHandler(REFCLSID rclsid, IUnknown FAR* pUnkOuter, REFIID riid, void FAR* FAR* ppv);
+
+INTERNAL RemCreateRHClassObject(REFCLSID rclsid, IID iid, void FAR* FAR* ppv);
+
+INTERNAL RemEnsureLocalClassObject(REFCLSID rclsid, OID FAR* pOidCF);
+
+INTERNAL RemEnsureUniqueHandler(REFCLSID rclsid, OID oid,
+ IUnknown FAR* FAR* ppUnk, IProxyManager FAR* FAR* ppPM);
+
+
+// REVIEW MM2 (craigwi): these aren't used much; do we keep them?
+
+/* -----------------------------------------------------------------------
+ * Proxy/Stub macros
+ *
+ * The follwoing macros can be used to implement Proxy/Stub classes for
+ * classes that support only one or more interfaces other then IUnknown
+ * (and maybe IDebug). The resulting classes will support IProxy, IStub
+ * interface in addition to the interfaces supported by the original class.
+ * Assuming the interfaces supported is IName and it is implemented
+ * by a class CName:
+ *
+ * Declaration (in *.h):
+ *
+ * class CName { class CNameProxy { class CNameStub {
+ * ............ ............ ............
+ * STDUNKDECL(CName,Name) STDUNKDECL(CNameProxy,NameProxy) STDUNKDECL(CNameStub,NameStub)
+ * STDDEBDECL(CName,Name) STDDEBDECL(CNameProxy,NameProxy) STDDEBDECL(CNameStub,NameStub)
+ * STDPROXYDECL(CNameProxy,NameProxy) STDSTUBDECL(NameStub,1)
+ * <IName Declaration> <IName for proxy> <IName for stub>
+ * ............ ............ ............
+ * }; }; };
+ *
+ * Implementation (in *.cpp):
+ *
+ * For original object:
+ *
+ * STDUNKIMPL(Name)
+ *
+ * STDUNK_QI_IMPL(Name,Name)
+ *
+ * STDUNKIMPL_FORDERIVED(Name,NameImpl)
+ *
+ * <Implementation of IName: CNameImpl>
+ *
+ *
+ * For proxy object:
+ *
+ * STDUNKIMPL(NameProxy)
+ *
+ * STDUNK_PROXY_QI_IMPL(NameProxy,Name)
+ *
+ * STDUNKIMPL_FORDERIVED(NameProxy,NameProxyImpl)
+ *
+ * STDPROXYIMPL(NameProxy)
+ *
+ * <Implementation of IName: CNameProxyImpl>
+ *
+ *
+ * For stub object:
+ *
+ * STDUNKIMPL(NameStub)
+ *
+ * STDUNK_STUB_QI_IMPL(NameStub,Name)
+ *
+ * STDUNKIMPL_FORDERIVED(NameStub,NameStubImpl)
+ *
+ * STDSTUBIMPL(NameStub)
+ *
+ * <Implementation of IName: CNameStubImpl>
+ *
+ *
+ */
+
+// Mattp: I have moved the body of destructor to the implementation macro. ( STDPROXYIMPL)
+
+#define STDPROXYDECL(ignore, classname) \
+ implement CProxy : IProxy { public: \
+ CProxy(C##classname FAR* p##classname) \
+ { m_p##classname = p##classname; } \
+ ~CProxy(void); \
+ STDMETHOD(QueryInterface)(REFIID iid, LPLPVOID ppvObj);\
+ STDMETHOD_(ULONG,AddRef)(void); \
+ STDMETHOD_(ULONG,Release)(void); \
+ STDMETHOD(Connect)(ILrpc FAR* pILrpc); \
+ STDMETHOD_(void, Disconnect)(void); \
+ private: C##classname FAR* m_p##classname; }; \
+ DECLARE_NC(C##classname,CProxy) \
+ CProxy m_Proxy;
+
+
+#define STDSTUBDECL(ignore, classname,cIface) \
+ implement CStub : IStub { public: \
+ CStub(C##classname FAR* p##classname) \
+ { m_p##classname = p##classname; m_pUnkObject = NULL; } \
+ ~CStub(void) \
+ { M_PROLOG(m_p##classname); if (m_pUnkObject != NULL) m_pUnkObject->Release(); } \
+ INTERNAL_(BOOL) Init(IUnknown FAR* pUnkObject); \
+ STDMETHOD(QueryInterface)(REFIID iid, LPLPVOID ppvObj);\
+ STDMETHOD_(ULONG,AddRef)(void); \
+ STDMETHOD_(ULONG,Release)(void); \
+ STDMETHOD(Connect)(IUnknown FAR* pUnkObject); \
+ STDMETHOD_(void, Disconnect)(void); \
+ STDMETHOD(Dispatch)(REFIID iid, int iMethod, IStream FAR* pIStream, \
+ DWORD dwDestCtx, LPVOID lpvDestCtx); \
+ STDMETHOD_(BOOL, IsIIDSupported)(REFIID iid); \
+ STDMETHOD_(ULONG, CountRefs)(void); \
+ private: C##classname FAR* m_p##classname; \
+ IUnknown FAR* m_pUnkObject; \
+ IUnknown FAR* m_aStubIface[cIface]; }; \
+ DECLARE_NC(C##classname,CStub) \
+ CStub m_Stub;
+
+
+#define CONSTRUCT_PROXY m_Proxy(this),
+#define CONSTRUCT_STUB m_Stub(this),
+
+
+#define STDUNK_PROXY_QI_IMPL(classname,interfacename) \
+STDMETHODIMP NC(C##classname,CUnknownImpl)::QueryInterface \
+ (REFIID iidInterface, void FAR* FAR* ppv) { \
+ M_PROLOG(m_p##classname); \
+ if (iidInterface == IID_IUnknown) \
+ { *ppv = (void FAR*)&m_p##classname->m_Unknown; AddRef(); noError; } \
+ else if (iidInterface == IID_I##interfacename) \
+ { *ppv = (void FAR*) &(m_p##classname->m_##classname); \
+ m_p##classname->m_pUnkOuter->AddRef(); noError; } \
+ else if (iidInterface == IID_IProxy) \
+ { *ppv = (void FAR*) &(m_p##classname->m_Proxy); AddRef(); noError; } \
+ else \
+ STDDEB_QI(classname) \
+ { *ppv = NULL; return ResultFromScode(E_NOINTERFACE); } \
+ }
+
+
+#define STDUNK_STUB_QI_IMPL(classname,interfacename) \
+STDMETHODIMP NC(C##classname,CUnknownImpl)::QueryInterface \
+ (REFIID iidInterface, void FAR* FAR* ppv) { \
+ A5_PROLOG(m_p##classname); \
+ if (iidInterface == IID_IUnknown) \
+ *ppv = (void FAR*)&m_p##classname->m_Unknown; \
+ else if (iidInterface == IID_IStub) \
+ *ppv = (void FAR*) &(m_p##classname->m_Stub); \
+ else \
+ STDDEB_QI(classname) \
+ { *ppv = NULL; RESTORE_A5(); return ResultFromScode(E_NOINTERFACE); } \
+ ++(m_p##classname->m_refs); RESTORE_A5(); noError; }
+
+// Mattp: The destructor implementation has been moved to here to allow us the outer
+// reference to 'm_pILrpc'.
+
+#define STDPROXYIMPL(classname) \
+ NC(C##classname,CProxy)::~CProxy(void) \
+ { M_PROLOG(m_p##classname);if (m_p##classname->m_pILrpc) m_p##classname->m_pILrpc->Release();}\
+ STDMETHODIMP NC(C##classname,CProxy)::QueryInterface(REFIID iid, LPLPVOID ppvObj) \
+ { M_PROLOG(m_p##classname);return m_p##classname->m_Unknown.QueryInterface (iid, ppvObj); } \
+ STDMETHODIMP_(ULONG) NC(C##classname,CProxy)::AddRef(void) \
+ { M_PROLOG(m_p##classname);return m_p##classname->m_Unknown.AddRef(); } \
+ STDMETHODIMP_(ULONG) NC(C##classname,CProxy)::Release(void) \
+ { M_PROLOG(m_p##classname);return m_p##classname->m_Unknown.Release(); } \
+ STDMETHODIMP NC(C##classname,CProxy)::Connect(ILrpc FAR* pILrpc) \
+ { \
+ M_PROLOG(m_p##classname); \
+ if (pILrpc) { \
+ pILrpc->AddRef(); \
+ m_p##classname->m_pILrpc = pILrpc; \
+ return NOERROR; \
+ } else \
+ return ResultFromScode(E_UNSPEC); \
+ } \
+ STDMETHODIMP_(void) NC(C##classname,CProxy)::Disconnect(void) \
+ { \
+ M_PROLOG(m_p##classname); \
+ if (m_p##classname->m_pILrpc) \
+ m_p##classname->m_pILrpc->Release(); \
+ m_p##classname->m_pILrpc = NULL; \
+ }
+
+
+#define STDSTUBIMPL(classname) STDUNKIMPL_FORDERIVED(classname,Stub) \
+ STDMETHODIMP NC(C##classname,CStub)::Connect(IUnknown FAR* pUnkObject) \
+ { M_PROLOG(m_p##classname);return Init(pUnkObject) ? NOERROR : ResultFromScode(E_UNSPEC); } \
+ STDMETHODIMP_(void) NC(C##classname,CStub)::Disconnect(void) \
+ {M_PROLOG(m_p##classname); Init(NULL); }
+
+
+/*
+ * Ole2 marshalling stuff
+ *
+ * REVIEW: this should go into ole2sp.h, but ILrpc is defined here and
+ * olerem.h is included after ole2sp.h ...
+ */
+
+//
+// MOP is a single instruction to the interpreter that encodes,
+// decodes parameters sent via LRPC. A string of Mops describes how to
+// marshal, unmarshal function's paramaters.
+//
+//
+
+typedef enum MOP {
+ NilMop,
+ // Basic types size of type (win3.1)
+ Void, // No value 0b
+ This, // FAR* this -- BUGBUG Not used
+ Int, // (INT == int) 2b
+ uInt, // (UINT == unsigned int) 2b
+ Long, // (LONG == long) 4b
+ uLong, // (ULONG == unsigned long) 4b
+ Word, // WORD 2b
+ dWord, // DWORD 4b
+ Bool, // BOOL 2b
+ lpStr, // LPSTR -- (zero terminated)
+ lplpStr, // LPLPSTR -- (zero terminated)
+ pBuf, // void FAR* -- (size in following long)
+
+ // Windows types
+ wParam, // WPARAM 2b
+ lParam, // LPARAM 4b
+ _Handle, // HANDLE 2b
+ hWnd, // HWND 2b
+ hDc, // HDC 2b
+ hRgn, // HRGN 2b
+ hClip, // HANDLE 2b
+ _Point, // POINT 4b
+ _Size, // SIZE 4b
+ _Rect, // RECT 8b
+ Msg, // MSG 18b
+
+ // Ole/Win32 types
+ _Pointl, // POINTL 8b
+ _Sizel, // SIZEL 8b
+ _Rectl, // RECTL 16b
+
+ // Ole types
+ Hresult, // HRESULT 4b
+ Cid, // CID 16b
+ Iid, // IID 16b
+ wChar, // WCHAR 2b
+ Time, // TIME_T 4b
+ StatStg, // STATSTG > 38b + size of member lpstr
+ Layout, // OLELAYOUT 2b BUGBUG - bad size
+ ClipFor, // CLIPFORMAT 2b BUGBUG - MAC bad size
+ DAspect, // DVASPECT 4b
+ TyMed, // TYMED 4b
+ Verb, // OLEVERB > 14b + size of member lpstr
+ TDev, // DVTARGETDEVICE > 16b
+ SMedium, // STGMEDIUM > 12b + size of member lpstr
+ ForEtc, // FORMATETC > 18b + size of member tdev
+ StatDat, // STATDATA > 48b + size of member foretc
+ IFace, // interface FAR* > 40b
+ MenuWidths, // OLEMENUGROUP_WIDTHS 24b
+ hMenu, // HMENU 2b
+ hOMenu, // HOLEMENU 2b
+ hAccel, // HACCEL 2b
+ FrameInfo, // OLEINPLACEFRAMEINFO 10b
+ BindOpt, // BIND_OPTS 12b BUGBUG might change
+ LogPal, // LOGPALETTE > 8b
+
+ ArraySize, // the following is an array arg list
+ GenMops, // generic mop: used for with eg. Enum Next
+ RunArg, // inidicates a run modifier: Min or Mout based of return or not
+ // ->see example
+
+ // Modifiers
+ MMask = 0xc0,
+ MIn = 0x40, // FAR Pointer to in parameter
+ MOut = 0x80, // FAR Pointer to out parameter
+ MIO = 0xc0, // FAR Pointer to in, out parameter
+
+ // Interface indexes (overlap mop values)
+ ILast = 1, // Use last marshalled interface
+ IUnk, // IUnknown
+ IMnk, // IMoniker
+ IStg, // IStorage
+
+ IDObj, // IDataObject
+ IVObj, // IViewObject
+ IOleObj, // IOleObject
+ IIpObj, // IOleInPlaceObject
+
+ ICSite, // IOleClientSite
+ IIpSite, // IOleInPlaceSite
+ IAdvSink, // IAdviseSink
+
+ IPDName, // IParseDisplayName
+ IOleCont, // IOleContainer
+ IOleItemCont, // IOleItemContainer
+ IBCtx, // IBindCtx
+
+ IEStatData, // IEnumSTATDATA
+ IEForEtc, // IEnumFORMATETC
+ IEStr, // IEnumString
+ IEVerbs, // IEnumOLEVERB
+ IEMnk, // IEnumMoniker
+
+ IOleWnd, // IOleWIndow
+ IIpUiWnd, // IOleInPlaceUIWindow
+ IIpFrame, // IOleInPlaceFrame
+ IIpAObj, // IOleInPlaceActiveObject
+
+ IStStream,
+ IEnumStatStg
+} MOP;
+//
+// Modifiers combine with other types to indicate pointer to the type:
+// - MIn values are passed on call, but not updated upon return
+// - MOut values are not passed on call, but are updated upon return
+// - MIO values are passed on call, and updated upon return.
+//
+// M** indicates the argument is a pointer to the type. For types
+// which imply pointer (lpStr, pBuf, IMnk) M** indicates pointer to a pointer
+// (as in LPSTR FAR*, IEnumClipFormat FAR* FAR*). For MOut the value pointed
+// (i.e. the interface pointer) is ignored. MIn, MIO not supported.
+//
+// Interface indexes follow IFace mop to specify type of interface being
+// marshalled. ILast specify last IID marshalled.
+//
+// By convention the return value is always an HRESULT.
+//
+// MOP is an 8-bit value; it fits in a BYTE. Example:
+//
+// static mopsSomeFunc[] { pBuf | MIn, uLong, IFace, IDObj, ..., NilMop };
+//
+
+// Example for generic mops!
+// static BYTE ForEtcMop[] = { MopSize(22), ClipFor, RunArg, TDev, DAspect, Long, TyMed, NilMop };
+// static BYTE mopsForEtcNext[] = { uLong, ArraySize, GenMops | MOut, MopPtr(ForEtcMop), uLong | MOut, NilMop };
+//
+
+
+
+// FNI describes how to marshal, unmarshal specific function
+//
+typedef int FNITYPE;
+
+#define FNITYPE_NilFni 0
+#define FNITYPE_RevArg 0x01 // Arguments pushed left-to-right (pascal)
+#define FNITYPE_Clean 0x02 // Callee cleans stack (pascal)
+#define FNITYPE_Method 0x04 // Class method.
+#define FNITYPE_Virtual 0x08 // Virtual function
+#define FNITYPE_Send 0x10 // Use SendMessage (not PostMessage)
+#define FNITYPE_NoWait 0x20 // Do not wait for reply (only when PostMessage)
+
+struct FAR FNI { // Static data for function marshalling
+ FNITYPE m_type; // Function description
+ struct { // For virtual function
+ const IID FAR* lpIID;// far pointer to Interface ID
+ int iMethod; // Method index
+ } m_loc; // ----
+ UINT m_cbStk; // Stack space for pushing all arguments
+ UINT m_cbStm; // Stream space for marshalling arguments
+ UINT m_cbExtStm; // Additional stream space for strings, buffers
+ BYTE FAR* m_args; // Arguments MOPs
+};
+
+//
+// Example
+//
+//static FNI fniSomeFunc = {
+// FNITYPE_Method | FNITYPE_Virtual,
+// { //interface and method Indices
+// &_IID_ISomeIface,
+// IFUNC_SomeFunc
+// },
+// 64, // Stack space
+// 96, // Minimun Stream space
+// 48, // Estimated extra stream space
+// mopsSomeFunc // The mops
+//};
+//
+// _IID_ISomeIface is the IID for the interface of this object,
+// IIFACE_SomeFunc is the index of this method within the interface.
+//
+
+
+STDAPI LrpcCall(ILrpc FAR* pILrpc, FNI FAR* pfni, void FAR* pFirstArg);
+
+STDAPI LrpcDispatch(IStream FAR* pIStream, FNI FAR* pfni, void FAR* pObj);
+
+BOOL IsValidOID(OID oid);
+
+#endif // _OLEREM_H
diff --git a/private/ole32/olethunk/ole16/inc/olestd.h b/private/ole32/olethunk/ole16/inc/olestd.h
new file mode 100644
index 000000000..dc218f7da
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/olestd.h
@@ -0,0 +1,837 @@
+/*************************************************************************
+**
+** OLE 2.0 Standard Utilities
+**
+** olestd.h
+**
+** This file contains file contains data structure defintions,
+** function prototypes, constants, etc. for the common OLE 2.0
+** utilities.
+** These utilities include the following:
+** Debuging Assert/Verify macros
+** HIMETRIC conversion routines
+** reference counting debug support
+** OleStd API's for common compound-document app support
+**
+** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+**
+*************************************************************************/
+
+#if !defined( _OLESTD_H_ )
+#define _OLESTD_H_
+
+#ifndef RC_INVOKED
+#pragma message ("INCLUDING OLESTD.H from " __FILE__)
+#endif /* RC_INVOKED */
+
+#if defined( __TURBOC__ ) || defined( WIN32 )
+#define _based(a)
+#endif
+
+#ifndef RC_INVOKED
+#include <dos.h> // needed for filetime
+#endif /* RC_INVOKED */
+
+#include <commdlg.h> // needed for LPPRINTDLG
+#include <shellapi.h> // needed for HKEY
+
+// String table defines...
+#define IDS_OLESTDNOCREATEFILE 700
+#define IDS_OLESTDNOOPENFILE 701
+#define IDS_OLESTDDISKFULL 702
+
+
+/*
+ * Some C interface declaration stuff
+ */
+
+#if ! defined(__cplusplus)
+typedef struct tagINTERFACEIMPL {
+ IUnknownVtbl FAR* lpVtbl;
+ LPVOID lpBack;
+ int cRef; // interface specific ref count.
+} INTERFACEIMPL, FAR* LPINTERFACEIMPL;
+
+#define INIT_INTERFACEIMPL(lpIFace, pVtbl, pBack) \
+ ((lpIFace)->lpVtbl = pVtbl, \
+ ((LPINTERFACEIMPL)(lpIFace))->lpBack = (LPVOID)pBack, \
+ ((LPINTERFACEIMPL)(lpIFace))->cRef = 0 \
+ )
+
+#if defined( _DEBUG )
+#define OleDbgQueryInterfaceMethod(lpUnk) \
+ ((lpUnk) != NULL ? ((LPINTERFACEIMPL)(lpUnk))->cRef++ : 0)
+#define OleDbgAddRefMethod(lpThis, iface) \
+ ((LPINTERFACEIMPL)(lpThis))->cRef++
+
+#if _DEBUGLEVEL >= 2
+#define OleDbgReleaseMethod(lpThis, iface) \
+ (--((LPINTERFACEIMPL)(lpThis))->cRef == 0 ? \
+ OleDbgOut("\t" iface "* RELEASED (cRef == 0)\r\n"),1 : \
+ (((LPINTERFACEIMPL)(lpThis))->cRef < 0) ? \
+ ( \
+ DebugBreak(), \
+ OleDbgOut( \
+ "\tERROR: " iface "* RELEASED TOO MANY TIMES\r\n") \
+ ),1 : \
+ 1)
+
+#else // if _DEBUGLEVEL < 2
+#define OleDbgReleaseMethod(lpThis, iface) \
+ (--((LPINTERFACEIMPL)(lpThis))->cRef == 0 ? \
+ 1 : \
+ (((LPINTERFACEIMPL)(lpThis))->cRef < 0) ? \
+ ( \
+ OleDbgOut( \
+ "\tERROR: " iface "* RELEASED TOO MANY TIMES\r\n") \
+ ),1 : \
+ 1)
+
+#endif // if _DEBUGLEVEL < 2
+
+#else // ! defined (_DEBUG)
+
+#define OleDbgQueryInterfaceMethod(lpUnk)
+#define OleDbgAddRefMethod(lpThis, iface)
+#define OleDbgReleaseMethod(lpThis, iface)
+
+#endif // if defined( _DEBUG )
+
+#endif // ! defined(__cplusplus)
+
+/*
+ * Some docfiles stuff
+ */
+
+#define STGM_DFRALL (STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE)
+#define STGM_DFALL (STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE)
+#define STGM_SALL (STGM_READWRITE | STGM_SHARE_EXCLUSIVE)
+
+/*
+ * Some moniker stuff
+ */
+
+// Delimeter used to separate ItemMoniker pieces of a composite moniker
+#if defined( _MAC )
+#define OLESTDDELIM ":"
+#else
+#define OLESTDDELIM "\\"
+#endif
+
+/*
+ * Some Concurrency stuff
+ */
+
+/* standard Delay (in msec) to wait before retrying an LRPC call.
+** this value is returned from IMessageFilter::RetryRejectedCall
+*/
+#define OLESTDRETRYDELAY (DWORD)5000
+
+/* Cancel the pending outgoing LRPC call.
+** this value is returned from IMessageFilter::RetryRejectedCall
+*/
+#define OLESTDCANCELRETRY (DWORD)-1
+
+/*
+ * Some Icon support stuff.
+ *
+ * The following API's are now OBSOLETE because equivalent API's have been
+ * added to the OLE2.DLL library
+ * GetIconOfFile superceeded by OleGetIconOfFile
+ * GetIconOfClass superceeded by OleGetIconOfClass
+ * OleUIMetafilePictFromIconAndLabel
+ * superceeded by OleMetafilePictFromIconAndLabel
+ *
+ * The following macros are defined for backward compatibility with previous
+ * versions of the OLE2UI library. It is recommended that the new Ole* API's
+ * should be used instead.
+ */
+#define GetIconOfFile(hInst, lpszFileName, fUseFileAsLabel) \
+ OleGetIconOfFile(lpszFileName, fUseFileAsLabel)
+
+#define GetIconOfClass(hInst, rclsid, lpszLabel, fUseTypeAsLabel) \
+ OleGetIconOfClass(rclsid, lpszLabel, fUseTypeAsLabel)
+
+#define OleUIMetafilePictFromIconAndLabel(hIcon,pszLabel,pszSourceFile,iIcon)\
+ OleMetafilePictFromIconAndLabel(hIcon, pszLabel, pszSourceFile, iIcon)
+
+
+/*
+ * Some Clipboard Copy/Paste & Drag/Drop support stuff
+ */
+
+//Macro to set all FormatEtc fields
+#define SETFORMATETC(fe, cf, asp, td, med, li) \
+ ((fe).cfFormat=cf, \
+ (fe).dwAspect=asp, \
+ (fe).ptd=td, \
+ (fe).tymed=med, \
+ (fe).lindex=li)
+
+//Macro to set interesting FormatEtc fields defaulting the others.
+#define SETDEFAULTFORMATETC(fe, cf, med) \
+ ((fe).cfFormat=cf, \
+ (fe).dwAspect=DVASPECT_CONTENT, \
+ (fe).ptd=NULL, \
+ (fe).tymed=med, \
+ (fe).lindex=-1)
+
+// Macro to test if two FormatEtc structures are an exact match
+#define IsEqualFORMATETC(fe1, fe2) \
+ (OleStdCompareFormatEtc(&(fe1), &(fe2))==0)
+
+// Clipboard format strings
+#define CF_EMBEDSOURCE "Embed Source"
+#define CF_EMBEDDEDOBJECT "Embedded Object"
+#define CF_LINKSOURCE "Link Source"
+#define CF_CUSTOMLINKSOURCE "Custom Link Source"
+#define CF_OBJECTDESCRIPTOR "Object Descriptor"
+#define CF_LINKSRCDESCRIPTOR "Link Source Descriptor"
+#define CF_OWNERLINK "OwnerLink"
+#define CF_FILENAME "FileName"
+
+#define OleStdQueryOleObjectData(lpformatetc) \
+ (((lpformatetc)->tymed & TYMED_ISTORAGE) ? \
+ NOERROR : ResultFromScode(DV_E_FORMATETC))
+
+#define OleStdQueryLinkSourceData(lpformatetc) \
+ (((lpformatetc)->tymed & TYMED_ISTREAM) ? \
+ NOERROR : ResultFromScode(DV_E_FORMATETC))
+
+#define OleStdQueryObjectDescriptorData(lpformatetc) \
+ (((lpformatetc)->tymed & TYMED_HGLOBAL) ? \
+ NOERROR : ResultFromScode(DV_E_FORMATETC))
+
+#define OleStdQueryFormatMedium(lpformatetc, tymd) \
+ (((lpformatetc)->tymed & tymd) ? \
+ NOERROR : ResultFromScode(DV_E_FORMATETC))
+
+// Make an independent copy of a MetafilePict
+#define OleStdCopyMetafilePict(hpictin, phpictout) \
+ (*(phpictout) = OleDuplicateData(hpictin,CF_METAFILEPICT,GHND|GMEM_SHARE))
+
+
+// REVIEW: these need to be added to OLE2.H
+#if !defined( DD_DEFSCROLLINTERVAL )
+#define DD_DEFSCROLLINTERVAL 50
+#endif
+
+#if !defined( DD_DEFDRAGDELAY )
+#define DD_DEFDRAGDELAY 200
+#endif
+
+#if !defined( DD_DEFDRAGMINDIST )
+#define DD_DEFDRAGMINDIST 2
+#endif
+
+
+/* OleStdGetDropEffect
+** -------------------
+**
+** Convert a keyboard state into a DROPEFFECT.
+**
+** returns the DROPEFFECT value derived from the key state.
+** the following is the standard interpretation:
+** no modifier -- Default Drop (NULL is returned)
+** CTRL -- DROPEFFECT_COPY
+** SHIFT -- DROPEFFECT_MOVE
+** CTRL-SHIFT -- DROPEFFECT_LINK
+**
+** Default Drop: this depends on the type of the target application.
+** this is re-interpretable by each target application. a typical
+** interpretation is if the drag is local to the same document
+** (which is source of the drag) then a MOVE operation is
+** performed. if the drag is not local, then a COPY operation is
+** performed.
+*/
+#define OleStdGetDropEffect(grfKeyState) \
+ ( (grfKeyState & MK_CONTROL) ? \
+ ( (grfKeyState & MK_SHIFT) ? DROPEFFECT_LINK : DROPEFFECT_COPY ) : \
+ ( (grfKeyState & MK_SHIFT) ? DROPEFFECT_MOVE : 0 ) )
+
+
+/* The OLEUIPASTEFLAG enumeration is used by the OLEUIPASTEENTRY structure.
+ *
+ * OLEUIPASTE_ENABLEICON If the container does not specify this flag for the entry in the
+ * OLEUIPASTEENTRY array passed as input to OleUIPasteSpecial, the DisplayAsIcon button will be
+ * unchecked and disabled when the the user selects the format that corresponds to the entry.
+ *
+ * OLEUIPASTE_PASTEONLY Indicates that the entry in the OLEUIPASTEENTRY array is valid for pasting only.
+ * OLEUIPASTE_PASTE Indicates that the entry in the OLEUIPASTEENTRY array is valid for pasting. It
+ * may also be valid for linking if any of the following linking flags are specified.
+ *
+ * If the entry in the OLEUIPASTEENTRY array is valid for linking, the following flags indicate which link
+ * types are acceptable by OR'ing together the appropriate OLEUIPASTE_LINKTYPE<#> values.
+ * These values correspond as follows to the array of link types passed to OleUIPasteSpecial:
+ * OLEUIPASTE_LINKTYPE1=arrLinkTypes[0]
+ * OLEUIPASTE_LINKTYPE2=arrLinkTypes[1]
+ * OLEUIPASTE_LINKTYPE3=arrLinkTypes[2]
+ * OLEUIPASTE_LINKTYPE4=arrLinkTypes[3]
+ * OLEUIPASTE_LINKTYPE5=arrLinkTypes[4]
+ * OLEUIPASTE_LINKTYPE6=arrLinkTypes[5]
+ * OLEUIPASTE_LINKTYPE7=arrLinkTypes[6]
+ * OLEUIPASTE_LINKTYPE8=arrLinkTypes[7]
+ *
+ * where,
+ * UINT arrLinkTypes[8] is an array of registered clipboard formats for linking. A maximium of 8 link
+ * types are allowed.
+ */
+
+typedef enum tagOLEUIPASTEFLAG
+{
+ OLEUIPASTE_ENABLEICON = 2048, // enable display as icon
+ OLEUIPASTE_PASTEONLY = 0,
+ OLEUIPASTE_PASTE = 512,
+ OLEUIPASTE_LINKANYTYPE = 1024,
+ OLEUIPASTE_LINKTYPE1 = 1,
+ OLEUIPASTE_LINKTYPE2 = 2,
+ OLEUIPASTE_LINKTYPE3 = 4,
+ OLEUIPASTE_LINKTYPE4 = 8,
+ OLEUIPASTE_LINKTYPE5 = 16,
+ OLEUIPASTE_LINKTYPE6 = 32,
+ OLEUIPASTE_LINKTYPE7 = 64,
+ OLEUIPASTE_LINKTYPE8 = 128
+} OLEUIPASTEFLAG;
+
+/*
+ * PasteEntry structure
+ * --------------------
+ * An array of OLEUIPASTEENTRY entries is specified for the PasteSpecial dialog
+ * box. Each entry includes a FORMATETC which specifies the formats that are
+ * acceptable, a string that is to represent the format in the dialog's list
+ * box, a string to customize the result text of the dialog and a set of flags
+ * from the OLEUIPASTEFLAG enumeration. The flags indicate if the entry is
+ * valid for pasting only, linking only or both pasting and linking. If the
+ * entry is valid for linking, the flags indicate which link types are
+ * acceptable by OR'ing together the appropriate OLEUIPASTE_LINKTYPE<#> values.
+ * These values correspond to the array of link types as follows:
+ * OLEUIPASTE_LINKTYPE1=arrLinkTypes[0]
+ * OLEUIPASTE_LINKTYPE2=arrLinkTypes[1]
+ * OLEUIPASTE_LINKTYPE3=arrLinkTypes[2]
+ * OLEUIPASTE_LINKTYPE4=arrLinkTypes[3]
+ * OLEUIPASTE_LINKTYPE5=arrLinkTypes[4]
+ * OLEUIPASTE_LINKTYPE6=arrLinkTypes[5]
+ * OLEUIPASTE_LINKTYPE7=arrLinkTypes[6]
+ * OLEUIPASTE_LINKTYPE8=arrLinkTypes[7]
+ * UINT arrLinkTypes[8]; is an array of registered clipboard formats
+ * for linking. A maximium of 8 link types are allowed.
+ */
+
+typedef struct tagOLEUIPASTEENTRY
+{
+ FORMATETC fmtetc; // Format that is acceptable. The paste
+ // dialog checks if this format is
+ // offered by the object on the
+ // clipboard and if so offers it for
+ // selection to the user.
+ LPCSTR lpstrFormatName; // String that represents the format to the user. Any %s
+ // in this string is replaced by the FullUserTypeName
+ // of the object on the clipboard and the resulting string
+ // is placed in the list box of the dialog. Atmost
+ // one %s is allowed. The presence or absence of %s indicates
+ // if the result text is to indicate that data is
+ // being pasted or that an object that can be activated by
+ // an application is being pasted. If %s is
+ // present, the result-text says that an object is being pasted.
+ // Otherwise it says that data is being pasted.
+ LPCSTR lpstrResultText; // String to customize the result text of the dialog when
+ // the user selects the format correspoding to this
+ // entry. Any %s in this string is replaced by the the application
+ // name or FullUserTypeName of the object on
+ // the clipboard. Atmost one %s is allowed.
+ DWORD dwFlags; // Values from OLEUIPASTEFLAG enum
+ DWORD dwScratchSpace; // Scratch space available to be used
+ // by routines which loop through an
+ // IEnumFORMATETC* to mark if the
+ // PasteEntry format is available.
+ // this field CAN be left uninitialized.
+} OLEUIPASTEENTRY, *POLEUIPASTEENTRY, FAR *LPOLEUIPASTEENTRY;
+
+#define OLESTDDROP_NONE 0
+#define OLESTDDROP_DEFAULT 1
+#define OLESTDDROP_NONDEFAULT 2
+
+
+/*
+ * Some misc stuff
+ */
+
+#define EMBEDDINGFLAG "Embedding" // Cmd line switch for launching a srvr
+
+#define HIMETRIC_PER_INCH 2540 // number HIMETRIC units per inch
+#define PTS_PER_INCH 72 // number points (font size) per inch
+
+#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
+#define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH)
+
+// Returns TRUE if all fields of the two Rect's are equal, else FALSE.
+#define AreRectsEqual(lprc1, lprc2) \
+ (((lprc1->top == lprc2->top) && \
+ (lprc1->left == lprc2->left) && \
+ (lprc1->right == lprc2->right) && \
+ (lprc1->bottom == lprc2->bottom)) ? TRUE : FALSE)
+
+#define LSTRCPYN(lpdst, lpsrc, cch) \
+(\
+ (lpdst)[(cch)-1] = '\0', \
+ (cch>1 ? lstrcpyn(lpdst, lpsrc, (cch)-1) : 0)\
+)
+
+
+/****** DEBUG Stuff *****************************************************/
+
+#ifdef _DEBUG
+
+#if !defined( _DBGTRACE )
+#define _DEBUGLEVEL 2
+#else
+#define _DEBUGLEVEL _DBGTRACE
+#endif
+
+
+#if defined( NOASSERT )
+
+#define OLEDBGASSERTDATA
+#define OleDbgAssert(a)
+#define OleDbgAssertSz(a, b)
+#define OleDbgVerify(a)
+#define OleDbgVerifySz(a, b)
+
+#else // ! NOASSERT
+
+#define OLEDBGASSERTDATA \
+ static char _based(_segname("_CODE")) _szAssertFile[]= __FILE__;
+
+#define OleDbgAssert(a) \
+ (!(a) ? FnAssert(#a, NULL, _szAssertFile, __LINE__) : (HRESULT)1)
+
+#define OleDbgAssertSz(a, b) \
+ (!(a) ? FnAssert(#a, b, _szAssertFile, __LINE__) : (HRESULT)1)
+
+#define OleDbgVerify(a) \
+ OleDbgAssert(a)
+
+#define OleDbgVerifySz(a, b) \
+ OleDbgAssertSz(a, b)
+
+#endif // ! NOASSERT
+
+
+#define OLEDBGDATA_MAIN(szPrefix) \
+ char near g_szDbgPrefix[] = szPrefix; \
+ OLEDBGASSERTDATA
+#define OLEDBGDATA \
+ extern char near g_szDbgPrefix[]; \
+ OLEDBGASSERTDATA
+
+#define OLEDBG_BEGIN(lpsz) \
+ OleDbgPrintAlways(g_szDbgPrefix,lpsz,1);
+
+#define OLEDBG_END \
+ OleDbgPrintAlways(g_szDbgPrefix,"End\r\n",-1);
+
+#define OleDbgOut(lpsz) \
+ OleDbgPrintAlways(g_szDbgPrefix,lpsz,0)
+
+#define OleDbgOutNoPrefix(lpsz) \
+ OleDbgPrintAlways("",lpsz,0)
+
+#define OleDbgOutRefCnt(lpsz,lpObj,refcnt) \
+ OleDbgPrintRefCntAlways(g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt)
+
+#define OleDbgOutRect(lpsz,lpRect) \
+ OleDbgPrintRectAlways(g_szDbgPrefix,lpsz,lpRect)
+
+#define OleDbgOutHResult(lpsz,hr) \
+ OleDbgPrintScodeAlways(g_szDbgPrefix,lpsz,GetScode(hr))
+
+#define OleDbgOutScode(lpsz,sc) \
+ OleDbgPrintScodeAlways(g_szDbgPrefix,lpsz,sc)
+
+#define OleDbgOut1(lpsz) \
+ OleDbgPrint(1,g_szDbgPrefix,lpsz,0)
+
+#define OleDbgOutNoPrefix1(lpsz) \
+ OleDbgPrint(1,"",lpsz,0)
+
+#define OLEDBG_BEGIN1(lpsz) \
+ OleDbgPrint(1,g_szDbgPrefix,lpsz,1);
+
+#define OLEDBG_END1 \
+ OleDbgPrint(1,g_szDbgPrefix,"End\r\n",-1);
+
+#define OleDbgOutRefCnt1(lpsz,lpObj,refcnt) \
+ OleDbgPrintRefCnt(1,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt)
+
+#define OleDbgOutRect1(lpsz,lpRect) \
+ OleDbgPrintRect(1,g_szDbgPrefix,lpsz,lpRect)
+
+#define OleDbgOut2(lpsz) \
+ OleDbgPrint(2,g_szDbgPrefix,lpsz,0)
+
+#define OleDbgOutNoPrefix2(lpsz) \
+ OleDbgPrint(2,"",lpsz,0)
+
+#define OLEDBG_BEGIN2(lpsz) \
+ OleDbgPrint(2,g_szDbgPrefix,lpsz,1);
+
+#define OLEDBG_END2 \
+ OleDbgPrint(2,g_szDbgPrefix,"End\r\n",-1);
+
+#define OleDbgOutRefCnt2(lpsz,lpObj,refcnt) \
+ OleDbgPrintRefCnt(2,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt)
+
+#define OleDbgOutRect2(lpsz,lpRect) \
+ OleDbgPrintRect(2,g_szDbgPrefix,lpsz,lpRect)
+
+#define OleDbgOut3(lpsz) \
+ OleDbgPrint(3,g_szDbgPrefix,lpsz,0)
+
+#define OleDbgOutNoPrefix3(lpsz) \
+ OleDbgPrint(3,"",lpsz,0)
+
+#define OLEDBG_BEGIN3(lpsz) \
+ OleDbgPrint(3,g_szDbgPrefix,lpsz,1);
+
+#define OLEDBG_END3 \
+ OleDbgPrint(3,g_szDbgPrefix,"End\r\n",-1);
+
+#define OleDbgOutRefCnt3(lpsz,lpObj,refcnt) \
+ OleDbgPrintRefCnt(3,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt)
+
+#define OleDbgOutRect3(lpsz,lpRect) \
+ OleDbgPrintRect(3,g_szDbgPrefix,lpsz,lpRect)
+
+#define OleDbgOut4(lpsz) \
+ OleDbgPrint(4,g_szDbgPrefix,lpsz,0)
+
+#define OleDbgOutNoPrefix4(lpsz) \
+ OleDbgPrint(4,"",lpsz,0)
+
+#define OLEDBG_BEGIN4(lpsz) \
+ OleDbgPrint(4,g_szDbgPrefix,lpsz,1);
+
+#define OLEDBG_END4 \
+ OleDbgPrint(4,g_szDbgPrefix,"End\r\n",-1);
+
+#define OleDbgOutRefCnt4(lpsz,lpObj,refcnt) \
+ OleDbgPrintRefCnt(4,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt)
+
+#define OleDbgOutRect4(lpsz,lpRect) \
+ OleDbgPrintRect(4,g_szDbgPrefix,lpsz,lpRect)
+
+#else // !_DEBUG
+
+#define OLEDBGDATA_MAIN(szPrefix)
+#define OLEDBGDATA
+#define OleDbgAssert(a)
+#define OleDbgAssertSz(a, b)
+#define OleDbgVerify(a) (a)
+#define OleDbgVerifySz(a, b) (a)
+#define OleDbgOutHResult(lpsz,hr)
+#define OleDbgOutScode(lpsz,sc)
+#define OLEDBG_BEGIN(lpsz)
+#define OLEDBG_END
+#define OleDbgOut(lpsz)
+#define OleDbgOut1(lpsz)
+#define OleDbgOut2(lpsz)
+#define OleDbgOut3(lpsz)
+#define OleDbgOut4(lpsz)
+#define OleDbgOutNoPrefix(lpsz)
+#define OleDbgOutNoPrefix1(lpsz)
+#define OleDbgOutNoPrefix2(lpsz)
+#define OleDbgOutNoPrefix3(lpsz)
+#define OleDbgOutNoPrefix4(lpsz)
+#define OLEDBG_BEGIN1(lpsz)
+#define OLEDBG_BEGIN2(lpsz)
+#define OLEDBG_BEGIN3(lpsz)
+#define OLEDBG_BEGIN4(lpsz)
+#define OLEDBG_END1
+#define OLEDBG_END2
+#define OLEDBG_END3
+#define OLEDBG_END4
+#define OleDbgOutRefCnt(lpsz,lpObj,refcnt)
+#define OleDbgOutRefCnt1(lpsz,lpObj,refcnt)
+#define OleDbgOutRefCnt2(lpsz,lpObj,refcnt)
+#define OleDbgOutRefCnt3(lpsz,lpObj,refcnt)
+#define OleDbgOutRefCnt4(lpsz,lpObj,refcnt)
+#define OleDbgOutRect(lpsz,lpRect)
+#define OleDbgOutRect1(lpsz,lpRect)
+#define OleDbgOutRect2(lpsz,lpRect)
+#define OleDbgOutRect3(lpsz,lpRect)
+#define OleDbgOutRect4(lpsz,lpRect)
+
+#endif // _DEBUG
+
+
+/*************************************************************************
+** Function prototypes
+*************************************************************************/
+
+
+//OLESTD.C
+STDAPI_(int) SetDCToAnisotropic(HDC hDC, LPRECT lprcPhysical, LPRECT lprcLogical, LPRECT lprcWindowOld, LPRECT lprcViewportOld);
+STDAPI_(int) SetDCToDrawInHimetricRect(HDC, LPRECT, LPRECT, LPRECT, LPRECT);
+STDAPI_(int) ResetOrigDC(HDC, int, LPRECT, LPRECT);
+
+STDAPI_(int) XformWidthInHimetricToPixels(HDC, int);
+STDAPI_(int) XformWidthInPixelsToHimetric(HDC, int);
+STDAPI_(int) XformHeightInHimetricToPixels(HDC, int);
+STDAPI_(int) XformHeightInPixelsToHimetric(HDC, int);
+
+STDAPI_(void) XformRectInPixelsToHimetric(HDC, LPRECT, LPRECT);
+STDAPI_(void) XformRectInHimetricToPixels(HDC, LPRECT, LPRECT);
+STDAPI_(void) XformSizeInPixelsToHimetric(HDC, LPSIZEL, LPSIZEL);
+STDAPI_(void) XformSizeInHimetricToPixels(HDC, LPSIZEL, LPSIZEL);
+STDAPI_(int) XformWidthInHimetricToPixels(HDC, int);
+STDAPI_(int) XformWidthInPixelsToHimetric(HDC, int);
+STDAPI_(int) XformHeightInHimetricToPixels(HDC, int);
+STDAPI_(int) XformHeightInPixelsToHimetric(HDC, int);
+
+STDAPI_(void) ParseCmdLine(LPSTR, BOOL FAR *, LPSTR);
+
+STDAPI_(BOOL) OleStdIsOleLink(LPUNKNOWN lpUnk);
+STDAPI_(LPUNKNOWN) OleStdQueryInterface(LPUNKNOWN lpUnk, REFIID riid);
+STDAPI_(LPSTORAGE) OleStdCreateRootStorage(LPSTR lpszStgName, DWORD grfMode);
+STDAPI_(LPSTORAGE) OleStdOpenRootStorage(LPSTR lpszStgName, DWORD grfMode);
+STDAPI_(LPSTORAGE) OleStdOpenOrCreateRootStorage(LPSTR lpszStgName, DWORD grfMode);
+STDAPI_(LPSTORAGE) OleStdCreateChildStorage(LPSTORAGE lpStg, LPSTR lpszStgName);
+STDAPI_(LPSTORAGE) OleStdOpenChildStorage(LPSTORAGE lpStg, LPSTR lpszStgName, DWORD grfMode);
+STDAPI_(BOOL) OleStdCommitStorage(LPSTORAGE lpStg);
+STDAPI OleStdDestroyAllElements(LPSTORAGE lpStg);
+
+STDAPI_(LPSTORAGE) OleStdCreateStorageOnHGlobal(
+ HANDLE hGlobal,
+ BOOL fDeleteOnRelease,
+ DWORD dwgrfMode
+);
+STDAPI_(LPSTORAGE) OleStdCreateTempStorage(BOOL fUseMemory, DWORD grfMode);
+STDAPI OleStdDoConvert(LPSTORAGE lpStg, REFCLSID rClsidNew);
+STDAPI_(BOOL) OleStdGetTreatAsFmtUserType(
+ REFCLSID rClsidApp,
+ LPSTORAGE lpStg,
+ CLSID FAR* lpclsid,
+ CLIPFORMAT FAR* lpcfFmt,
+ LPSTR FAR* lplpszType
+);
+STDAPI OleStdDoTreatAsClass(LPSTR lpszUserType, REFCLSID rclsid, REFCLSID rclsidNew);
+STDAPI_(BOOL) OleStdSetupAdvises(LPOLEOBJECT lpOleObject, DWORD dwDrawAspect,
+ LPSTR lpszContainerApp, LPSTR lpszContainerObj,
+ LPADVISESINK lpAdviseSink, BOOL fCreate);
+STDAPI OleStdSwitchDisplayAspect(
+ LPOLEOBJECT lpOleObj,
+ LPDWORD lpdwCurAspect,
+ DWORD dwNewAspect,
+ HGLOBAL hMetaPict,
+ BOOL fDeleteOldAspect,
+ BOOL fSetupViewAdvise,
+ LPADVISESINK lpAdviseSink,
+ BOOL FAR* lpfMustUpdate
+);
+STDAPI OleStdSetIconInCache(LPOLEOBJECT lpOleObj, HGLOBAL hMetaPict);
+STDAPI_(HGLOBAL) OleStdGetData(
+ LPDATAOBJECT lpDataObj,
+ CLIPFORMAT cfFormat,
+ DVTARGETDEVICE FAR* lpTargetDevice,
+ DWORD dwAspect,
+ LPSTGMEDIUM lpMedium
+);
+STDAPI_(void) OleStdMarkPasteEntryList(
+ LPDATAOBJECT lpSrcDataObj,
+ LPOLEUIPASTEENTRY lpPriorityList,
+ int cEntries
+);
+STDAPI_(int) OleStdGetPriorityClipboardFormat(
+ LPDATAOBJECT lpSrcDataObj,
+ LPOLEUIPASTEENTRY lpPriorityList,
+ int cEntries
+);
+STDAPI_(BOOL) OleStdIsDuplicateFormat(
+ LPFORMATETC lpFmtEtc,
+ LPFORMATETC arrFmtEtc,
+ int nFmtEtc
+);
+STDAPI_(void) OleStdRegisterAsRunning(LPUNKNOWN lpUnk, LPMONIKER lpmkFull, DWORD FAR* lpdwRegister);
+STDAPI_(void) OleStdRevokeAsRunning(DWORD FAR* lpdwRegister);
+STDAPI_(void) OleStdNoteFileChangeTime(LPSTR lpszFileName, DWORD dwRegister);
+STDAPI_(void) OleStdNoteObjectChangeTime(DWORD dwRegister);
+STDAPI OleStdGetOleObjectData(
+ LPPERSISTSTORAGE lpPStg,
+ LPFORMATETC lpformatetc,
+ LPSTGMEDIUM lpMedium,
+ BOOL fUseMemory
+);
+STDAPI OleStdGetLinkSourceData(
+ LPMONIKER lpmk,
+ LPCLSID lpClsID,
+ LPFORMATETC lpformatetc,
+ LPSTGMEDIUM lpMedium
+);
+STDAPI_(HGLOBAL) OleStdGetObjectDescriptorData(
+ CLSID clsid,
+ DWORD dwAspect,
+ SIZEL sizel,
+ POINTL pointl,
+ DWORD dwStatus,
+ LPSTR lpszFullUserTypeName,
+ LPSTR lpszSrcOfCopy
+);
+STDAPI_(HGLOBAL) OleStdGetObjectDescriptorDataFromOleObject(
+ LPOLEOBJECT lpOleObj,
+ LPSTR lpszSrcOfCopy,
+ DWORD dwAspect,
+ POINTL pointl,
+ LPSIZEL lpSizelHim
+);
+STDAPI_(HGLOBAL) OleStdFillObjectDescriptorFromData(
+ LPDATAOBJECT lpDataObject,
+ LPSTGMEDIUM lpmedium,
+ CLIPFORMAT FAR* lpcfFmt
+);
+STDAPI_(HANDLE) OleStdGetMetafilePictFromOleObject(
+ LPOLEOBJECT lpOleObj,
+ DWORD dwDrawAspect,
+ LPSIZEL lpSizelHim,
+ DVTARGETDEVICE FAR* ptd
+);
+
+STDAPI_(void) OleStdCreateTempFileMoniker(LPSTR lpszPrefixString, UINT FAR* lpuUnique, LPSTR lpszName, LPMONIKER FAR* lplpmk);
+STDAPI_(LPMONIKER) OleStdGetFirstMoniker(LPMONIKER lpmk);
+STDAPI_(ULONG) OleStdGetLenFilePrefixOfMoniker(LPMONIKER lpmk);
+STDAPI OleStdMkParseDisplayName(
+ REFCLSID rClsid,
+ LPBC lpbc,
+ LPSTR lpszUserName,
+ ULONG FAR* lpchEaten,
+ LPMONIKER FAR* lplpmk
+);
+STDAPI_(LPVOID) OleStdMalloc(ULONG ulSize);
+STDAPI_(LPVOID) OleStdRealloc(LPVOID pmem, ULONG ulSize);
+STDAPI_(void) OleStdFree(LPVOID pmem);
+STDAPI_(ULONG) OleStdGetSize(LPVOID pmem);
+STDAPI_(void) OleStdFreeString(LPSTR lpsz, LPMALLOC lpMalloc);
+STDAPI_(LPSTR) OleStdCopyString(LPSTR lpszSrc, LPMALLOC lpMalloc);
+STDAPI_(ULONG) OleStdGetItemToken(LPSTR lpszSrc, LPSTR lpszDst,int nMaxChars);
+
+STDAPI_(UINT) OleStdIconLabelTextOut(HDC hDC,
+ HFONT hFont,
+ int nXStart,
+ int nYStart,
+ UINT fuOptions,
+ RECT FAR * lpRect,
+ LPSTR lpszString,
+ UINT cchString,
+ int FAR * lpDX);
+
+// registration database query functions
+STDAPI_(UINT) OleStdGetAuxUserType(REFCLSID rclsid,
+ WORD wAuxUserType,
+ LPSTR lpszAuxUserType,
+ int cch,
+ HKEY hKey);
+
+STDAPI_(UINT) OleStdGetUserTypeOfClass(REFCLSID rclsid,
+ LPSTR lpszUserType,
+ UINT cch,
+ HKEY hKey);
+
+STDAPI_(BOOL) OleStdGetMiscStatusOfClass(REFCLSID, HKEY, DWORD FAR *);
+STDAPI_(CLIPFORMAT) OleStdGetDefaultFileFormatOfClass(
+ REFCLSID rclsid,
+ HKEY hKey
+);
+
+STDAPI_(void) OleStdInitVtbl(LPVOID lpVtbl, UINT nSizeOfVtbl);
+STDMETHODIMP OleStdNullMethod(LPUNKNOWN lpThis);
+STDAPI_(BOOL) OleStdCheckVtbl(LPVOID lpVtbl, UINT nSizeOfVtbl, LPSTR lpszIface);
+STDAPI_(ULONG) OleStdVerifyRelease(LPUNKNOWN lpUnk, LPSTR lpszMsg);
+STDAPI_(ULONG) OleStdRelease(LPUNKNOWN lpUnk);
+
+STDAPI_(HDC) OleStdCreateDC(DVTARGETDEVICE FAR* ptd);
+STDAPI_(HDC) OleStdCreateIC(DVTARGETDEVICE FAR* ptd);
+STDAPI_(DVTARGETDEVICE FAR*) OleStdCreateTargetDevice(LPPRINTDLG lpPrintDlg);
+STDAPI_(BOOL) OleStdDeleteTargetDevice(DVTARGETDEVICE FAR* ptd);
+STDAPI_(DVTARGETDEVICE FAR*) OleStdCopyTargetDevice(DVTARGETDEVICE FAR* ptdSrc);
+STDAPI_(BOOL) OleStdCopyFormatEtc(LPFORMATETC petcDest, LPFORMATETC petcSrc);
+STDAPI_(int) OleStdCompareFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight);
+STDAPI_(BOOL) OleStdCompareTargetDevice
+ (DVTARGETDEVICE FAR* ptdLeft, DVTARGETDEVICE FAR* ptdRight);
+
+
+STDAPI_(void) OleDbgPrint(
+ int nDbgLvl,
+ LPSTR lpszPrefix,
+ LPSTR lpszMsg,
+ int nIndent
+);
+STDAPI_(void) OleDbgPrintAlways(LPSTR lpszPrefix, LPSTR lpszMsg, int nIndent);
+STDAPI_(void) OleDbgSetDbgLevel(int nDbgLvl);
+STDAPI_(int) OleDbgGetDbgLevel( void );
+STDAPI_(void) OleDbgIndent(int n);
+STDAPI_(void) OleDbgPrintRefCnt(
+ int nDbgLvl,
+ LPSTR lpszPrefix,
+ LPSTR lpszMsg,
+ LPVOID lpObj,
+ ULONG refcnt
+);
+STDAPI_(void) OleDbgPrintRefCntAlways(
+ LPSTR lpszPrefix,
+ LPSTR lpszMsg,
+ LPVOID lpObj,
+ ULONG refcnt
+);
+STDAPI_(void) OleDbgPrintRect(
+ int nDbgLvl,
+ LPSTR lpszPrefix,
+ LPSTR lpszMsg,
+ LPRECT lpRect
+);
+STDAPI_(void) OleDbgPrintRectAlways(
+ LPSTR lpszPrefix,
+ LPSTR lpszMsg,
+ LPRECT lpRect
+);
+STDAPI_(void) OleDbgPrintScodeAlways(LPSTR lpszPrefix, LPSTR lpszMsg, SCODE sc);
+
+// debug implementation of the IMalloc interface.
+STDAPI OleStdCreateDbAlloc(ULONG reserved, IMalloc FAR* FAR* ppmalloc);
+
+
+STDAPI_(LPENUMFORMATETC)
+ OleStdEnumFmtEtc_Create(ULONG nCount, LPFORMATETC lpEtc);
+
+STDAPI_(LPENUMSTATDATA)
+ OleStdEnumStatData_Create(ULONG nCount, LPSTATDATA lpStat);
+
+STDAPI_(BOOL)
+ OleStdCopyStatData(LPSTATDATA pDest, LPSTATDATA pSrc);
+
+STDAPI_(HPALETTE)
+ OleStdCreateStandardPalette(void);
+
+#if defined( OBSOLETE )
+
+/*************************************************************************
+** The following API's have been converted into macros:
+** OleStdQueryOleObjectData
+** OleStdQueryLinkSourceData
+** OleStdQueryObjectDescriptorData
+** OleStdQueryFormatMedium
+** OleStdCopyMetafilePict
+** AreRectsEqual
+** OleStdGetDropEffect
+**
+** These macros are defined above
+*************************************************************************/
+STDAPI_(BOOL) AreRectsEqual(LPRECT lprc1, LPRECT lprc2);
+STDAPI_(BOOL) OleStdCopyMetafilePict(HANDLE hpictin, HANDLE FAR* phpictout);
+STDAPI OleStdQueryOleObjectData(LPFORMATETC lpformatetc);
+STDAPI OleStdQueryLinkSourceData(LPFORMATETC lpformatetc);
+STDAPI OleStdQueryObjectDescriptorData(LPFORMATETC lpformatetc);
+STDAPI OleStdQueryFormatMedium(LPFORMATETC lpformatetc, TYMED tymed);
+STDAPI_(DWORD) OleStdGetDropEffect ( DWORD grfKeyState );
+#endif // OBSOLETE
+
+
+#endif // _OLESTD_H_
diff --git a/private/ole32/olethunk/ole16/inc/plex.h b/private/ole32/olethunk/ole16/inc/plex.h
new file mode 100644
index 000000000..ca55bfa5a
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/plex.h
@@ -0,0 +1,28 @@
+// This is a part of the Microsoft Foundation Classes C++ library.
+// Copyright (C) 1992 Microsoft Corporation
+// All rights reserved.
+//
+// This source code is only intended as a supplement to the
+// Microsoft Foundation Classes Reference and Microsoft
+// QuickHelp documentation provided with the library.
+// See these sources for detailed information regarding the
+// Microsoft Foundation Classes product.
+
+#ifndef __PLEX_H__
+#define __PLEX_H__
+
+struct FAR CPlex // warning variable length structure
+{
+ CPlex FAR* pNext;
+ UINT nMax;
+ UINT nCur;
+ /* BYTE data[maxNum*elementSize]; */
+
+ INTERNAL_(void FAR*) data() { return this+1; }
+
+ static INTERNAL_(CPlex FAR*) Create(CPlex FAR* FAR& head, DWORD mp, UINT nMax, UINT cbElement);
+
+ INTERNAL_(void) FreeDataChain(DWORD mp); // free this one and links
+};
+
+#endif //__PLEX_H__
diff --git a/private/ole32/olethunk/ole16/inc/privguid.h b/private/ole32/olethunk/ole16/inc/privguid.h
new file mode 100644
index 000000000..2ebaf39fc
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/privguid.h
@@ -0,0 +1,60 @@
+/* this file is the master definition of all OLE2 product GUIDs (public and
+ private). All GUIDs used by the ole2 product are of the form:
+
+ xxxxxxxx-xxxx-xxxY-C000-000000000046
+
+ This range is broken down as follows:
+
+ 000000xx-0000-0000-C000-000000000046 compobj IIDs (coguid.h)
+ 000001xx-0000-0000-C000-000000000046 ole2 IIDs (oleguid.h)
+ 000002xx-0000-0000-C000-000000000046 smoke test (testguid.h)
+ 000003xx-0000-0000-C000-000000000046 ole2 CLSIDs (privguid.h; this file)
+ 000004xx-0000-0000-C000-000000000046 ole2 sample apps (see DouglasH)
+
+ Other interesting ranges are as follows:
+
+ 0003xxxx-0000-0000-C000-000000000046 ole1 CLSIDs (ole1cls.h)
+ 0004xxxx-0000-0000-C000-000000000046 hashed ole1 CLSIDs
+
+*/
+
+
+DEFINE_OLEGUID(CLSID_StdOleLink, 0x00000300, 0, 0);
+DEFINE_OLEGUID(CLSID_StdMemStm, 0x00000301, 0, 0);
+DEFINE_OLEGUID(CLSID_StdMemBytes, 0x00000302, 0, 0);
+DEFINE_OLEGUID(CLSID_FileMoniker, 0x00000303, 0, 0);
+DEFINE_OLEGUID(CLSID_ItemMoniker, 0x00000304, 0, 0);
+DEFINE_OLEGUID(CLSID_AntiMoniker, 0x00000305, 0, 0);
+DEFINE_OLEGUID(CLSID_PointerMoniker, 0x00000306, 0, 0);
+// NOT TO BE USED 0x00000307, 0, 0);
+DEFINE_OLEGUID(CLSID_PackagerMoniker, 0x00000308, 0, 0);
+DEFINE_OLEGUID(CLSID_CompositeMoniker, 0x00000309, 0, 0);
+// NOT TO BE USED 0x0000030a, 0, 0);
+DEFINE_OLEGUID(CLSID_DfMarshal, 0x0000030b, 0, 0);
+
+// clsids for proxy/stub objects
+DEFINE_OLEGUID(CLSID_PSGenObject, 0x0000030c, 0, 0);
+DEFINE_OLEGUID(CLSID_PSClientSite, 0x0000030d, 0, 0);
+DEFINE_OLEGUID(CLSID_PSClassObject, 0x0000030e, 0, 0);
+DEFINE_OLEGUID(CLSID_PSInPlaceActive, 0x0000030f, 0, 0);
+DEFINE_OLEGUID(CLSID_PSInPlaceFrame, 0x00000310, 0, 0);
+DEFINE_OLEGUID(CLSID_PSDragDrop, 0x00000311, 0, 0);
+DEFINE_OLEGUID(CLSID_PSBindCtx, 0x00000312, 0, 0);
+DEFINE_OLEGUID(CLSID_PSEnumerators, 0x00000313, 0, 0);
+DEFINE_OLEGUID(CLSID_PSStore, 0x00000314, 0, 0);
+
+/* These 2 are defined in "oleguid.h"
+DEFINE_OLEGUID(CLSID_StaticMetafile, 0x00000315, 0, 0);
+DEFINE_OLEGUID(CLSID_StaticDib, 0x00000316, 0, 0);
+*/
+
+/* NOTE: LSB values 0x17 through 0xff are reserved */
+
+// copies from ole1cls.h; reduces the size of ole2.dll
+DEFINE_OLEGUID(CLSID_MSDraw, 0x00030007, 0, 0);
+DEFINE_OLEGUID(CLSID_Package, 0x0003000c, 0, 0);
+DEFINE_OLEGUID(CLSID_ExcelWorksheet, 0x00030000, 0, 0);
+DEFINE_OLEGUID(CLSID_ExcelChart, 0x00030001, 0, 0);
+DEFINE_OLEGUID(CLSID_ExcelMacrosheet, 0x00030002, 0, 0);
+DEFINE_OLEGUID(CLSID_PBrush, 0x0003000a, 0, 0);
+DEFINE_OLEGUID(CLSID_WordDocument, 0x00030003, 0, 0);
diff --git a/private/ole32/olethunk/ole16/inc/prxsegs.h b/private/ole32/olethunk/ole16/inc/prxsegs.h
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/prxsegs.h
@@ -0,0 +1 @@
+
diff --git a/private/ole32/olethunk/ole16/inc/reterr.h b/private/ole32/olethunk/ole16/inc/reterr.h
new file mode 100644
index 000000000..3c5788a87
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/reterr.h
@@ -0,0 +1,44 @@
+/* Jason's error handling macros */
+
+#ifndef fRetErr_h
+#define fRetErr_h
+
+#ifdef _DEBUG
+FARINTERNAL_(void) wWarn (LPSTR sz, LPSTR szFile, int iLine);
+#define Warn(sz) wWarn(sz,_szAssertFile,__LINE__)
+#else
+#define Warn(sz)
+#endif // _DEBUG
+
+// Call x. If hresult is not NOERROR, goto errRtn.
+#define ErrRtn(x) do {if (NOERROR != (x)) {Warn(NULL); goto errRtn;}} while (0)
+
+// Call x. If hresult is not NOERROR, store it in hresult and goto errRtn.
+#define ErrRtnH(x) do {if (NOERROR != (hresult=(x))) {Warn(NULL); goto errRtn;}} while (0)
+
+// If x, goto errRtn.
+#define ErrNz(x) do {if (x) {Warn(NULL); goto errRtn;}} while (0)
+
+// If x==0, goto errRtn.
+#define ErrZ(x) do {if (!(x)) {Warn(NULL); goto errRtn;}} while (0)
+
+// If x==0, goto errRtn with a specific scode
+#define ErrZS(x, scode) do {if (!(x)) {Warn(NULL); hresult=ResultFromScode(scode); goto errRtn;}} while (0)
+
+
+// Call x. If hresult is not NOERROR, return that hresult.
+#define RetErr(x) do {HRESULT hresult; if (NOERROR != (hresult=(x))) {Warn(NULL); return hresult;}} while (0)
+
+// Return unexpected error if x is non-zero
+#define RetNz(x) do {if (x) {AssertSz(0,#x); return ReportResult(0, E_UNEXPECTED, 0, 0);}} while (0)
+
+// Return specific scode if x is non-zero
+#define RetNzS(x, scode) do {if (x) {Warn(NULL); return ResultFromScode (scode);}} while (0)
+
+// Return unexpected error if x is zero
+#define RetZ(x) do {if (!(x)) {AssertSz(0,#x); return ReportResult(0, E_UNEXPECTED, 0, 0);}} while (0)
+
+// Return specific scode if x is zero
+#define RetZS(x, scode) do {if (!(x)) {Warn(NULL); return ResultFromScode (scode);}} while (0)
+
+#endif
diff --git a/private/ole32/olethunk/ole16/inc/scode.h b/private/ole32/olethunk/ole16/inc/scode.h
new file mode 100644
index 000000000..cbfb2751c
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/scode.h
@@ -0,0 +1,283 @@
+/*****************************************************************************\
+* *
+* scode.h - Defines standard status code services. *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#ifndef __SCODE_H__
+#define __SCODE_H__
+
+//
+// SCODE
+//
+
+typedef long SCODE;
+typedef SCODE *PSCODE;
+typedef void FAR * HRESULT;
+#define NOERROR 0
+
+//
+// Status values are 32 bit values layed out as follows:
+//
+// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-+---------------------+-------+-------------------------------+
+// |S| Context | Facil | Code |
+// +-+---------------------+-------+-------------------------------+
+//
+// where
+//
+// S - is the severity code
+//
+// 0 - Success
+// 1 - Error
+//
+// Context - context info
+//
+// Facility - is the facility code
+//
+// Code - is the facility's status code
+//
+
+//
+// Severity values
+//
+
+#define SEVERITY_SUCCESS 0
+#define SEVERITY_ERROR 1
+
+
+
+#define SUCCEEDED(Status) ((SCODE)(Status) >= 0)
+
+#define FAILED(Status) ((SCODE)(Status)<0)
+
+
+//
+// Return the code
+//
+
+#define SCODE_CODE(sc) ((sc) & 0xFFFF)
+
+//
+// Return the facility
+//
+
+#define SCODE_FACILITY(sc) (((sc) >> 16) & 0x1fff)
+
+//
+// Return the severity
+//
+
+#define SCODE_SEVERITY(sc) (((sc) >> 31) & 0x1)
+
+//
+// Create an SCODE value from component pieces
+//
+
+#define MAKE_SCODE(sev,fac,code) \
+ ((SCODE) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
+
+
+
+// --------------------- Functions ---------------------------------------
+
+#define GetScode(hr) ((SCODE)(hr) & 0x800FFFFF)
+#define ResultFromScode(sc) ((HRESULT)((SCODE)(sc) & 0x800FFFFF))
+
+STDAPI PropagateResult(HRESULT hrPrev, SCODE scNew);
+
+
+// -------------------------- Facility definitions -------------------------
+
+#define FACILITY_NULL 0x0000 // generally useful errors ([SE]_*)
+#define FACILITY_RPC 0x0001 // remote procedure call errors (RPC_E_*)
+#define FACILITY_DISPATCH 0x0002 // late binding dispatch errors
+#define FACILITY_STORAGE 0x0003 // storage errors (STG_E_*)
+#define FACILITY_ITF 0x0004 // interface-specific errors
+
+
+
+#define S_OK 0L
+#define S_FALSE MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 1)
+
+
+
+// --------------------- FACILITY_NULL errors ------------------------------
+
+#define E_UNEXPECTED MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 0xffff)
+ // relatively catastrophic failure
+
+#define E_NOTIMPL MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 1)
+ // not implemented
+
+#define E_OUTOFMEMORY MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 2)
+ // ran out of memory
+
+#define E_INVALIDARG MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 3)
+ // one or more arguments are invalid
+
+#define E_NOINTERFACE MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 4)
+ // no such interface supported
+
+
+#define E_POINTER MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 5)
+ // invalid pointer
+
+#define E_HANDLE MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 6)
+ // invalid handle
+
+#define E_ABORT MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 7)
+ // operation aborted
+
+#define E_FAIL MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 8)
+ // unspecified error
+
+
+#define E_ACCESSDENIED MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 9)
+ // general access denied error
+
+
+// ----------------- FACILITY_ITF errors used by OLE ---------------------
+//
+// By convention, OLE interfaces divide the FACILITY_ITF range of errors
+// into nonoverlapping subranges. If an OLE interface returns a FACILITY_ITF
+// scode, it must be from the range associated with that interface or from
+// the shared range: OLE_E_FIRST...OLE_E_LAST.
+//
+// The ranges, their associated interfaces, and the header file that defines
+// the actual scodes are given below.
+//
+
+// Generic OLE errors that may be returned by many interfaces
+#define OLE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0000)
+#define OLE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x00FF)
+#define OLE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0000)
+#define OLE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x00FF)
+// interfaces: all
+// file: ole2.h
+
+
+#define DRAGDROP_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0100)
+#define DRAGDROP_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x010F)
+#define DRAGDROP_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0100)
+#define DRAGDROP_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x010F)
+// interfaces: IDropSource, IDropTarget
+// file: ole2.h
+
+#define CLASSFACTORY_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0110)
+#define CLASSFACTORY_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x011F)
+#define CLASSFACTORY_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0110)
+#define CLASSFACTORY_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x011F)
+// interfaces: IClassFactory
+// file:
+
+#define MARSHAL_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0120)
+#define MARSHAL_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x012F)
+#define MARSHAL_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0120)
+#define MARSHAL_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x012F)
+// interfaces: IMarshal, IStdMarshalInfo, marshal APIs
+// file:
+
+#define DATA_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0130)
+#define DATA_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x013F)
+#define DATA_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0130)
+#define DATA_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x013F)
+// interfaces: IDataObject
+// file: dvobj.h
+
+#define VIEW_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0140)
+#define VIEW_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x014F)
+#define VIEW_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0140)
+#define VIEW_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x014F)
+// interfaces: IViewObject
+// file: dvobj.h
+
+#define REGDB_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0150)
+#define REGDB_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x015F)
+#define REGDB_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0150)
+#define REGDB_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x015F)
+// API: reg.dat manipulation
+// file:
+
+
+// range 160 - 16F reserved
+
+#define CACHE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0170)
+#define CACHE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x017F)
+#define CACHE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0170)
+#define CACHE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x017F)
+// interfaces: IOleCache
+// file:
+
+#define OLEOBJ_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0180)
+#define OLEOBJ_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x018F)
+#define OLEOBJ_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0180)
+#define OLEOBJ_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x018F)
+// interfaces: IOleObject
+// file:
+
+#define CLIENTSITE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0190)
+#define CLIENTSITE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x019F)
+#define CLIENTSITE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0190)
+#define CLIENTSITE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x019F)
+// interfaces: IOleClientSite
+// file:
+
+#define INPLACE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01A0)
+#define INPLACE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01AF)
+#define INPLACE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01A0)
+#define INPLACE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01AF)
+// interfaces: IOleWindow, IOleInPlaceObject, IOleInPlaceActiveObject,
+// IOleInPlaceUIWindow, IOleInPlaceFrame, IOleInPlaceSite
+// file:
+
+#define ENUM_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01B0)
+#define ENUM_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01BF)
+#define ENUM_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01B0)
+#define ENUM_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01BF)
+// interfaces: IEnum*
+// file:
+
+#define CONVERT10_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01C0)
+#define CONVERT10_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01CF)
+#define CONVERT10_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01C0)
+#define CONVERT10_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01CF)
+// API: OleConvertOLESTREAMToIStorage, OleConvertIStorageToOLESTREAM
+// file:
+
+
+#define CLIPBRD_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01D0)
+#define CLIPBRD_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01DF)
+#define CLIPBRD_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01D0)
+#define CLIPBRD_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01DF)
+// interfaces: OleSetClipboard, OleGetClipboard, OleFlushClipboard
+// file: ole2.h
+
+#define MK_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01E0)
+#define MK_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01EF)
+#define MK_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01E0)
+#define MK_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01EF)
+// interfaces: IMoniker, IBindCtx, IRunningObjectTable, IParseDisplayName,
+// IOleContainer, IOleItemContainer, IOleLink
+// file: moniker.h
+
+
+#define CO_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01F0)
+#define CO_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01FF)
+#define CO_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01F0)
+#define CO_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01FF)
+// all Co* API
+// file: compobj.h
+
+
+// range 200 - ffff for new error codes
+
+
+
+#endif // ifndef __SCODE_H__
diff --git a/private/ole32/olethunk/ole16/inc/shellapi.h b/private/ole32/olethunk/ole16/inc/shellapi.h
new file mode 100644
index 000000000..af978b924
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/shellapi.h
@@ -0,0 +1,88 @@
+/*****************************************************************************\
+* *
+* shellapi.h - SHELL.DLL functions, types, and definitions *
+* *
+* Copyright (c) 1992, Microsoft Corp. All rights reserved *
+* *
+\*****************************************************************************/
+
+#ifndef _INC_SHELLAPI
+#define _INC_SHELLAPI
+
+#ifndef RC_INVOKED
+#pragma pack(1) /* Assume byte packing throughout */
+#endif /* RC_INVOKED */
+
+#ifdef __cplusplus
+extern "C" { /* Assume C declarations for C++ */
+#endif /* __cplusplus */
+
+/* If included with Windows 3.0 windows.h: define 3.1-compatible types */
+
+#ifndef _INC_WINDOWS
+
+#define HDROP HANDLE
+#define WINAPI FAR PASCAL
+#define LPCSTR LPSTR
+#define UINT WORD
+
+#else
+
+DECLARE_HANDLE(HDROP);
+
+#endif
+
+/* return codes from Registration functions */
+#define ERROR_SUCCESS 0L
+#define ERROR_BADDB 1L
+#define ERROR_BADKEY 2L
+#define ERROR_CANTOPEN 3L
+#define ERROR_CANTREAD 4L
+#define ERROR_CANTWRITE 5L
+#define ERROR_OUTOFMEMORY 6L
+#define ERROR_INVALID_PARAMETER 7L
+#define ERROR_ACCESS_DENIED 8L
+
+#define REG_SZ 1 /* string type */
+
+#define HKEY_CLASSES_ROOT 1
+
+typedef DWORD HKEY;
+typedef HKEY FAR* PHKEY;
+
+LONG WINAPI RegOpenKey(HKEY, LPCSTR, HKEY FAR*);
+LONG WINAPI RegCreateKey(HKEY, LPCSTR, HKEY FAR*);
+LONG WINAPI RegCloseKey(HKEY);
+LONG WINAPI RegDeleteKey(HKEY, LPCSTR);
+LONG WINAPI RegSetValue(HKEY, LPCSTR, DWORD, LPCSTR, DWORD);
+LONG WINAPI RegQueryValue(HKEY, LPCSTR, LPSTR, LONG FAR*);
+LONG WINAPI RegEnumKey(HKEY, DWORD, LPSTR, DWORD);
+
+UINT WINAPI DragQueryFile(HDROP, UINT, LPSTR, UINT);
+BOOL WINAPI DragQueryPoint(HDROP, POINT FAR*);
+void WINAPI DragFinish(HDROP);
+void WINAPI DragAcceptFiles(HWND, BOOL);
+
+HICON WINAPI ExtractIcon(HINSTANCE hInst, LPCSTR lpszExeFileName, UINT nIconIndex);
+
+/* error values for ShellExecute() beyond the regular WinExec() codes */
+#define SE_ERR_SHARE 26
+#define SE_ERR_ASSOCINCOMPLETE 27
+#define SE_ERR_DDETIMEOUT 28
+#define SE_ERR_DDEFAIL 29
+#define SE_ERR_DDEBUSY 30
+#define SE_ERR_NOASSOC 31
+
+HINSTANCE WINAPI ShellExecute(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, int iShowCmd);
+HINSTANCE WINAPI FindExecutable(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#ifndef RC_INVOKED
+#pragma pack()
+#endif /* RC_INVOKED */
+
+#endif /* _INC_SHELLAPI */
diff --git a/private/ole32/olethunk/ole16/inc/stdarg.h b/private/ole32/olethunk/ole16/inc/stdarg.h
new file mode 100644
index 000000000..7a06e7dca
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/stdarg.h
@@ -0,0 +1,52 @@
+/***
+*stdarg.h - defines ANSI-style macros for variable argument functions
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines ANSI-style macros for accessing arguments
+* of functions which take a variable number of arguments.
+* [ANSI]
+*
+****/
+
+#ifndef _INC_STDARG
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _WINDLL
+#define _FARARG_ __far
+#else
+#define _FARARG_
+#endif
+
+#if (_MSC_VER <= 600)
+#define __far _far
+#endif
+
+#ifndef _VA_LIST_DEFINED
+typedef char _FARARG_ *va_list;
+#define _VA_LIST_DEFINED
+#endif
+
+/*
+ * define a macro to compute the size of a type, variable or expression,
+ * rounded up to the nearest multiple of sizeof(int). This number is its
+ * size as function argument (Intel architecture). Note that the macro
+ * depends on sizeof(int) being a power of 2!
+ */
+
+#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
+
+#define va_start(ap,v) ap = (va_list)&v + _INTSIZEOF(v)
+#define va_arg(ap,t) ( *(t _FARARG_ *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
+#define va_end(ap) ap = (va_list)0
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_STDARG
+#endif /* _INC_STDARG */
diff --git a/private/ole32/olethunk/ole16/inc/stdio.h b/private/ole32/olethunk/ole16/inc/stdio.h
new file mode 100644
index 000000000..d43890feb
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/stdio.h
@@ -0,0 +1,338 @@
+/***
+*stdio.h - definitions/declarations for standard I/O routines
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file defines the structures, values, macros, and functions
+* used by the level 2 I/O ("standard I/O") routines.
+* [ANSI/System V]
+*
+****/
+
+#ifndef _INC_STDIO
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (_MSC_VER <= 600)
+#define __cdecl _cdecl
+#define __far _far
+#define __near _near
+#endif
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+#ifndef _VA_LIST_DEFINED
+typedef char *va_list;
+#define _VA_LIST_DEFINED
+#endif
+
+/* buffered I/O macros */
+
+#define BUFSIZ 512
+#define _NFILE 20
+#define EOF (-1)
+
+#ifndef _FILE_DEFINED
+#pragma pack(2)
+struct _iobuf {
+ char *_ptr;
+ int _cnt;
+ char *_base;
+ char _flag;
+ char _file;
+ };
+typedef struct _iobuf FILE;
+#pragma pack()
+#define _FILE_DEFINED
+#endif
+
+
+/* _P_tmpnam: Directory where temporary files may be created.
+ * L_tmpnam size = size of _P_tmpdir
+ * + 1 (in case _P_tmpdir does not end in "\\")
+ * + 6 (for the temp number string)
+ * + 1 (for the null terminator)
+ */
+
+#define _P_tmpdir "\\"
+#define L_tmpnam sizeof(_P_tmpdir)+8
+
+
+/* fseek constants */
+
+#define SEEK_CUR 1
+#define SEEK_END 2
+#define SEEK_SET 0
+
+
+/* minimum guaranteed filename length, open file count, and unique
+ * tmpnam filenames.
+ */
+
+#define FILENAME_MAX 63
+#define FOPEN_MAX 18
+#define TMP_MAX 32767
+#define _SYS_OPEN 20
+
+
+/* define NULL pointer value */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+
+/* declare _iob[] array */
+
+#ifndef _STDIO_DEFINED
+extern FILE __near __cdecl _iob[];
+#endif
+
+
+/* define file position type */
+
+#ifndef _FPOS_T_DEFINED
+typedef long fpos_t;
+#define _FPOS_T_DEFINED
+#endif
+
+
+/* standard file pointers */
+
+#ifndef _WINDLL
+#define stdin (&_iob[0])
+#define stdout (&_iob[1])
+#define stderr (&_iob[2])
+#endif
+#ifndef _WINDOWS
+#define _stdaux (&_iob[3])
+#define _stdprn (&_iob[4])
+#endif
+
+
+#define _IOREAD 0x01
+#define _IOWRT 0x02
+
+#define _IOFBF 0x0
+#define _IOLBF 0x40
+#define _IONBF 0x04
+
+#define _IOMYBUF 0x08
+#define _IOEOF 0x10
+#define _IOERR 0x20
+#define _IOSTRG 0x40
+#define _IORW 0x80
+
+
+#ifdef _WINDOWS
+#ifndef _WINDLL
+#ifndef _WINFO_DEFINED
+/* interface version number */
+#define _QWINVER 0
+
+/* max number of windows */
+#define _WFILE 20
+
+/* values for windows screen buffer size */
+#define _WINBUFINF 0
+#define _WINBUFDEF -1
+
+/* size/move settings */
+#define _WINSIZEMIN 1
+#define _WINSIZEMAX 2
+#define _WINSIZERESTORE 3
+#define _WINSIZECHAR 4
+
+/* size/move query types */
+#define _WINMAXREQ 100
+#define _WINCURRREQ 101
+
+/* values for closing window */
+#define _WINPERSIST 1
+#define _WINNOPERSIST 0
+
+/* pseudo file handle for frame window */
+#define _WINFRAMEHAND -1
+
+/* menu items */
+#define _WINSTATBAR 1
+#define _WINTILE 2
+#define _WINCASCADE 3
+#define _WINARRANGE 4
+
+/* quickwin exit options */
+#define _WINEXITPROMPT 1
+#define _WINEXITNOPERSIST 2
+#define _WINEXITPERSIST 3
+
+/* open structure */
+#pragma pack(2)
+struct _wopeninfo {
+ unsigned int _version;
+ const char __far * _title;
+ long _wbufsize;
+ };
+#pragma pack()
+
+/* size/move structure */
+struct _wsizeinfo {
+ unsigned int _version;
+ unsigned int _type;
+ unsigned int _x;
+ unsigned int _y;
+ unsigned int _h;
+ unsigned int _w;
+ };
+#define _WINFO_DEFINED
+#endif
+#endif
+#endif
+
+/* function prototypes */
+
+#ifndef _STDIO_DEFINED
+int __cdecl _filbuf(FILE *);
+int __cdecl _flsbuf(int, FILE *);
+FILE * __cdecl _fsopen(const char *,
+ const char *, int);
+void __cdecl clearerr(FILE *);
+int __cdecl fclose(FILE *);
+int __cdecl _fcloseall(void);
+FILE * __cdecl _fdopen(int, const char *);
+int __cdecl feof(FILE *);
+int __cdecl ferror(FILE *);
+int __cdecl fflush(FILE *);
+int __cdecl fgetc(FILE *);
+#ifndef _WINDLL
+int __cdecl _fgetchar(void);
+#endif
+int __cdecl fgetpos(FILE *, fpos_t *);
+char * __cdecl fgets(char *, int, FILE *);
+int __cdecl _fileno(FILE *);
+int __cdecl _flushall(void);
+FILE * __cdecl fopen(const char *,
+ const char *);
+int __cdecl fprintf(FILE *, const char *, ...);
+int __cdecl fputc(int, FILE *);
+#ifndef _WINDLL
+int __cdecl _fputchar(int);
+#endif
+int __cdecl fputs(const char *, FILE *);
+size_t __cdecl fread(void *, size_t, size_t, FILE *);
+FILE * __cdecl freopen(const char *,
+ const char *, FILE *);
+#ifndef _WINDLL
+int __cdecl fscanf(FILE *, const char *, ...);
+#endif
+int __cdecl fsetpos(FILE *, const fpos_t *);
+int __cdecl fseek(FILE *, long, int);
+long __cdecl ftell(FILE *);
+#ifdef _WINDOWS
+#ifndef _WINDLL
+FILE * __cdecl _fwopen(struct _wopeninfo *, struct _wsizeinfo *, const char *);
+#endif
+#endif
+size_t __cdecl fwrite(const void *, size_t, size_t,
+ FILE *);
+int __cdecl getc(FILE *);
+#ifndef _WINDLL
+int __cdecl getchar(void);
+char * __cdecl gets(char *);
+#endif
+int __cdecl _getw(FILE *);
+#ifndef _WINDLL
+void __cdecl perror(const char *);
+#endif
+int __cdecl printf(const char *, ...);
+int __cdecl putc(int, FILE *);
+#ifndef _WINDLL
+int __cdecl putchar(int);
+int __cdecl puts(const char *);
+#endif
+int __cdecl _putw(int, FILE *);
+int __cdecl remove(const char *);
+int __cdecl rename(const char *, const char *);
+void __cdecl rewind(FILE *);
+int __cdecl _rmtmp(void);
+#ifndef _WINDLL
+int __cdecl scanf(const char *, ...);
+#endif
+void __cdecl setbuf(FILE *, char *);
+int __cdecl setvbuf(FILE *, char *, int, size_t);
+int __cdecl _snprintf(char *, size_t, const char *, ...);
+int __cdecl sprintf(char *, const char *, ...);
+#ifndef _WINDLL
+int __cdecl sscanf(const char *, const char *, ...);
+#endif
+char * __cdecl _tempnam(char *, char *);
+FILE * __cdecl tmpfile(void);
+char * __cdecl tmpnam(char *);
+int __cdecl ungetc(int, FILE *);
+int __cdecl _unlink(const char *);
+int __cdecl vfprintf(FILE *, const char *, va_list);
+int __cdecl vprintf(const char *, va_list);
+int __cdecl _vsnprintf(char *, size_t, const char *, va_list);
+int __cdecl vsprintf(char *, const char *, va_list);
+#define _STDIO_DEFINED
+#endif
+
+/* macro definitions */
+
+#define feof(_stream) ((_stream)->_flag & _IOEOF)
+#define ferror(_stream) ((_stream)->_flag & _IOERR)
+#define _fileno(_stream) ((int)(unsigned char)(_stream)->_file)
+#define getc(_stream) (--(_stream)->_cnt >= 0 ? 0xff & *(_stream)->_ptr++ \
+ : _filbuf(_stream))
+#define putc(_c,_stream) (--(_stream)->_cnt >= 0 \
+ ? 0xff & (*(_stream)->_ptr++ = (char)(_c)) : _flsbuf((_c),(_stream)))
+#ifndef _WINDLL
+#define getchar() getc(stdin)
+#define putchar(_c) putc((_c),stdout)
+#endif
+
+
+#ifndef __STDC__
+/* Non-ANSI names for compatibility */
+
+#define P_tmpdir _P_tmpdir
+#define SYS_OPEN _SYS_OPEN
+
+#ifndef _WINDOWS
+#define stdaux _stdaux
+#define stdprn _stdprn
+#endif
+
+int __cdecl fcloseall(void);
+FILE * __cdecl fdopen(int, const char *);
+#ifndef _WINDLL
+int __cdecl fgetchar(void);
+#endif
+int __cdecl fileno(FILE *);
+int __cdecl flushall(void);
+#ifndef _WINDLL
+int __cdecl fputchar(int);
+#endif
+int __cdecl getw(FILE *);
+int __cdecl putw(int, FILE *);
+int __cdecl rmtmp(void);
+char * __cdecl tempnam(char *, char *);
+int __cdecl unlink(const char *);
+
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_STDIO
+#endif /* _INC_STDIO */
diff --git a/private/ole32/olethunk/ole16/inc/stdlib.h b/private/ole32/olethunk/ole16/inc/stdlib.h
new file mode 100644
index 000000000..d56b6a12b
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/stdlib.h
@@ -0,0 +1,263 @@
+/***
+*stdlib.h - declarations/definitions for commonly used library functions
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This include file contains the function declarations for
+* commonly used library functions which either don't fit somewhere
+* else, or, like toupper/tolower, can't be declared in the normal
+* place for other reasons.
+* [ANSI]
+*
+****/
+
+#ifndef _INC_STDLIB
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (_MSC_VER <= 600)
+#define __cdecl _cdecl
+#define __far _far
+#define __near _near
+#define __pascal _pascal
+#endif
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+#ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+/* define NULL pointer value */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+/* exit() arg values */
+
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+
+#ifndef _ONEXIT_T_DEFINED
+typedef int (__cdecl * _onexit_t)();
+typedef int (__far __cdecl * _fonexit_t)();
+#ifndef __STDC__
+/* Non-ANSI name for compatibility */
+typedef int (__cdecl * onexit_t)();
+#endif
+#define _ONEXIT_T_DEFINED
+#endif
+
+
+/* data structure definitions for div and ldiv runtimes. */
+
+#ifndef _DIV_T_DEFINED
+
+typedef struct _div_t {
+ int quot;
+ int rem;
+} div_t;
+
+typedef struct _ldiv_t {
+ long quot;
+ long rem;
+} ldiv_t;
+
+#define _DIV_T_DEFINED
+#endif
+
+/* maximum value that can be returned by the rand function. */
+
+#define RAND_MAX 0x7fff
+
+extern unsigned short __mb_cur_max; /* mb-len for curr. locale */
+#define MB_CUR_MAX __mb_cur_max
+
+
+/* min and max macros */
+
+#define __max(a,b) (((a) > (b)) ? (a) : (b))
+#define __min(a,b) (((a) < (b)) ? (a) : (b))
+
+
+/* sizes for buffers used by the _makepath() and _splitpath() functions.
+ * note that the sizes include space for 0-terminator
+ */
+
+#define _MAX_PATH 260 /* max. length of full pathname */
+#define _MAX_DRIVE 3 /* max. length of drive component */
+#define _MAX_DIR 256 /* max. length of path component */
+#define _MAX_FNAME 256 /* max. length of file name component */
+#define _MAX_EXT 256 /* max. length of extension component */
+
+/* external variable declarations */
+
+extern int __near __cdecl volatile errno; /* error value */
+extern int __near __cdecl _doserrno; /* OS system error value */
+
+extern char * __near __cdecl _sys_errlist[]; /* perror error message table */
+extern int __near __cdecl _sys_nerr; /* # of entries in sys_errlist table */
+extern char ** __near __cdecl _environ; /* pointer to environment table */
+extern int __near __cdecl _fmode; /* default file translation mode */
+#ifndef _WINDOWS
+extern int __near __cdecl _fileinfo; /* open file info mode (for spawn) */
+#endif
+
+extern unsigned int __near __cdecl _psp; /* Program Segment Prefix */
+
+/* OS major/minor version numbers */
+
+extern unsigned char __near __cdecl _osmajor;
+extern unsigned char __near __cdecl _osminor;
+
+/* OS mode */
+
+#define _DOS_MODE 0 /* DOS */
+#define _OS2_MODE 1 /* OS/2 */
+#define _WIN_MODE 2 /* Windows */
+
+extern unsigned char __near __cdecl _osmode;
+
+/* CPU mode */
+
+#define _REAL_MODE 0 /* real mode */
+#define _PROT_MODE 1 /* protect mode */
+
+extern unsigned char __near __cdecl _cpumode;
+
+/* function prototypes */
+
+double __cdecl atof(const char *);
+double __cdecl strtod(const char *, char * *);
+ldiv_t __cdecl ldiv(long, long);
+
+void __cdecl abort(void);
+int __cdecl abs(int);
+int __cdecl atexit(void (__cdecl *)(void));
+int __cdecl atoi(const char *);
+long __cdecl atol(const char *);
+long double __cdecl _atold(const char *);
+void * __cdecl bsearch(const void *, const void *,
+ size_t, size_t, int (__cdecl *)(const void *,
+ const void *));
+void * __cdecl calloc(size_t, size_t);
+div_t __cdecl div(int, int);
+char * __cdecl _ecvt(double, int, int *, int *);
+#ifndef _WINDLL
+void __cdecl exit(int);
+void __cdecl _exit(int);
+#endif
+int __far __cdecl _fatexit(void (__cdecl __far *)(void));
+char * __cdecl _fcvt(double, int, int *, int *);
+_fonexit_t __far __cdecl _fonexit(_fonexit_t);
+void __cdecl free(void *);
+char * __cdecl _fullpath(char *, const char *,
+ size_t);
+char * __cdecl _gcvt(double, int, char *);
+char * __cdecl getenv(const char *);
+char * __cdecl _itoa(int, char *, int);
+long __cdecl labs(long);
+unsigned long __cdecl _lrotl(unsigned long, int);
+unsigned long __cdecl _lrotr(unsigned long, int);
+char * __cdecl _ltoa(long, char *, int);
+void __cdecl _makepath(char *, const char *,
+ const char *, const char *, const char *);
+void * __cdecl malloc(size_t);
+_onexit_t __cdecl _onexit(_onexit_t);
+#ifndef _WINDLL
+void __cdecl perror(const char *);
+#endif
+int __cdecl _putenv(const char *);
+void __cdecl qsort(void *, size_t, size_t, int (__cdecl *)
+ (const void *, const void *));
+unsigned int __cdecl _rotl(unsigned int, int);
+unsigned int __cdecl _rotr(unsigned int, int);
+int __cdecl rand(void);
+void * __cdecl realloc(void *, size_t);
+void __cdecl _searchenv(const char *, const char *,
+ char *);
+void __cdecl _splitpath(const char *, char *,
+ char *, char *, char *);
+void __cdecl srand(unsigned int);
+long __cdecl strtol(const char *, char * *,
+ int);
+long double __cdecl _strtold(const char *,
+ char * *);
+unsigned long __cdecl strtoul(const char *,
+ char * *, int);
+void __cdecl _swab(char *, char *, int);
+#ifndef _WINDOWS
+int __cdecl system(const char *);
+#endif
+char * __cdecl _ultoa(unsigned long, char *, int);
+
+int __cdecl mblen(const char *, size_t);
+int __cdecl mbtowc(wchar_t *, const char *, size_t);
+int __cdecl wctomb(char *, wchar_t);
+size_t __cdecl mbstowcs(wchar_t *, const char *, size_t);
+size_t __cdecl wcstombs(char *, const wchar_t *, size_t);
+
+/* model-independent function prototypes */
+
+int __far __cdecl _fmblen(const char __far *, size_t);
+int __far __cdecl _fmbtowc(wchar_t __far *, const char __far *,
+ size_t);
+int __far __cdecl _fwctomb(char __far *, wchar_t);
+size_t __far __cdecl _fmbstowcs(wchar_t __far *, const char __far *,
+ size_t);
+size_t __far __cdecl _fwcstombs(char __far *, const wchar_t __far *,
+ size_t);
+
+#ifndef tolower /* tolower has been undefined - use function */
+int __cdecl tolower(int);
+#endif /* tolower */
+
+#ifndef toupper /* toupper has been undefined - use function */
+int __cdecl toupper(int);
+#endif /* toupper */
+
+#ifndef __STDC__
+/* Non-ANSI names for compatibility */
+
+#ifndef __cplusplus
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+extern char * __near __cdecl sys_errlist[];
+extern int __near __cdecl sys_nerr;
+extern char ** __near __cdecl environ;
+
+#define DOS_MODE _DOS_MODE
+#define OS2_MODE _OS2_MODE
+
+char * __cdecl ecvt(double, int, int *, int *);
+char * __cdecl fcvt(double, int, int *, int *);
+char * __cdecl gcvt(double, int, char *);
+char * __cdecl itoa(int, char *, int);
+char * __cdecl ltoa(long, char *, int);
+onexit_t __cdecl onexit(onexit_t);
+int __cdecl putenv(const char *);
+void __cdecl swab(char *, char *, int);
+char * __cdecl ultoa(unsigned long, char *, int);
+
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_STDLIB
+#endif /* _INC_STDLIB */
diff --git a/private/ole32/olethunk/ole16/inc/storage.h b/private/ole32/olethunk/ole16/inc/storage.h
new file mode 100644
index 000000000..e111c1d8f
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/storage.h
@@ -0,0 +1,457 @@
+/*****************************************************************************\
+* *
+* storage.h - Definitions for the strutured storage system
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#if !defined( _STORAGE_H_ )
+#define _STORAGE_H_
+
+
+#include <compobj.h>
+
+
+/****** Storage Error Codes *************************************************/
+
+/* DOS-based error codes */
+#define STG_E_INVALIDFUNCTION \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x01)
+
+#define STG_E_FILENOTFOUND \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x02)
+
+#define STG_E_PATHNOTFOUND \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x03)
+
+#define STG_E_TOOMANYOPENFILES \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x04)
+
+#define STG_E_ACCESSDENIED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x05)
+
+#define STG_E_INVALIDHANDLE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x06)
+
+#define STG_E_INSUFFICIENTMEMORY \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x08)
+
+#define STG_E_INVALIDPOINTER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x09)
+
+#define STG_E_NOMOREFILES \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x12)
+
+#define STG_E_DISKISWRITEPROTECTED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x13)
+
+#define STG_E_SEEKERROR \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x19)
+
+#define STG_E_WRITEFAULT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x1d)
+
+#define STG_E_READFAULT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x1e)
+
+#define STG_E_SHAREVIOLATION \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x20)
+
+#define STG_E_LOCKVIOLATION \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x21)
+
+#define STG_E_FILEALREADYEXISTS \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x50)
+
+#define STG_E_INVALIDPARAMETER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x57)
+
+#define STG_E_MEDIUMFULL \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x70)
+
+#define STG_E_ABNORMALAPIEXIT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfa)
+
+#define STG_E_INVALIDHEADER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfb)
+
+#define STG_E_INVALIDNAME \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfc)
+
+#define STG_E_UNKNOWN \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfd)
+
+#define STG_E_UNIMPLEMENTEDFUNCTION\
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfe)
+
+#define STG_E_INVALIDFLAG \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xff)
+
+/* Standard storage error codes */
+#define STG_E_INUSE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x100)
+
+#define STG_E_NOTCURRENT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x101)
+
+#define STG_E_REVERTED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x102)
+
+#define STG_E_CANTSAVE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x103)
+
+#define STG_E_OLDFORMAT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x104)
+
+#define STG_E_OLDDLL \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x105)
+
+#define STG_E_SHAREREQUIRED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x106)
+
+#define STG_E_NOTFILEBASEDSTORAGE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x107)
+
+#define STG_E_EXTANTMARSHALLINGS \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x108)
+
+/* Information returns */
+#define STG_S_CONVERTED \
+ MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_STORAGE, 0x200)
+
+/****** Storage types *******************************************************/
+
+#if defined(_M_I286)
+typedef char TCHAR;
+#ifndef HUGEP
+#define HUGEP _huge
+#endif
+#else
+typedef char TCHAR;
+#ifndef HUGEP
+#define HUGEP
+#endif
+#endif
+
+#define CWCSTORAGENAME 32
+
+/* Storage instantiation modes */
+#define STGM_DIRECT 0x00000000L
+#define STGM_TRANSACTED 0x00010000L
+
+#define STGM_READ 0x00000000L
+#define STGM_WRITE 0x00000001L
+#define STGM_READWRITE 0x00000002L
+
+#define STGM_SHARE_DENY_NONE 0x00000040L
+#define STGM_SHARE_DENY_READ 0x00000030L
+#define STGM_SHARE_DENY_WRITE 0x00000020L
+#define STGM_SHARE_EXCLUSIVE 0x00000010L
+
+#define STGM_PRIORITY 0x00040000L
+#define STGM_DELETEONRELEASE 0x04000000L
+
+#define STGM_CREATE 0x00001000L
+#define STGM_CONVERT 0x00020000L
+#define STGM_FAILIFTHERE 0x00000000L
+
+/* Storage commit types */
+typedef enum tagSTGC
+{
+ STGC_DEFAULT = 0,
+ STGC_OVERWRITE = 1,
+ STGC_ONLYIFCURRENT = 2,
+ STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4
+} STGC;
+
+/* Stream name block definitions */
+typedef char FAR * FAR *SNB;
+
+
+#ifndef _WINDOWS_
+#ifndef _FILETIME_
+#define _FILETIME_
+typedef struct FARSTRUCT tagFILETIME
+{
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+} FILETIME;
+#endif
+#endif
+
+
+/* Storage stat buffer */
+
+typedef struct FARSTRUCT tagSTATSTG
+{
+ char FAR* pwcsName;
+ DWORD type;
+ ULARGE_INTEGER cbSize;
+ FILETIME mtime;
+ FILETIME ctime;
+ FILETIME atime;
+ DWORD grfMode;
+ DWORD grfLocksSupported;
+ CLSID clsid;
+ DWORD grfStateBits;
+ DWORD reserved;
+} STATSTG;
+
+
+/* Storage element types */
+typedef enum tagSTGTY
+{
+ STGTY_STORAGE = 1,
+ STGTY_STREAM = 2,
+ STGTY_LOCKBYTES = 3,
+ STGTY_PROPERTY = 4
+} STGTY;
+
+typedef enum tagSTREAM_SEEK
+{
+ STREAM_SEEK_SET = 0,
+ STREAM_SEEK_CUR = 1,
+ STREAM_SEEK_END = 2
+} STREAM_SEEK;
+
+typedef enum tagLOCKTYPE
+{
+ LOCK_WRITE = 1,
+ LOCK_EXCLUSIVE = 2,
+ LOCK_ONLYONCE = 4
+} LOCKTYPE;
+
+typedef enum tagSTGMOVE
+{
+ STGMOVE_MOVE = 0,
+ STGMOVE_COPY = 1
+} STGMOVE;
+
+typedef enum tagSTATFLAG
+{
+ STATFLAG_DEFAULT = 0,
+ STATFLAG_NONAME = 1
+} STATFLAG;
+
+
+/****** Storage Enumerators *************************************************/
+
+#undef INTERFACE
+#define INTERFACE IEnumSTATSTG
+
+DECLARE_INTERFACE_(IEnumSTATSTG, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IENUMSTATSTG methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, STATSTG FAR * rgelt, ULONG FAR *pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumSTATSTG FAR *FAR *ppenm) PURE;
+};
+
+typedef IEnumSTATSTG FAR* LPENUMSTATSTG;
+
+
+
+/****** ILockBytes Interface ************************************************/
+
+#undef INTERFACE
+#define INTERFACE ILockBytes
+
+DECLARE_INTERFACE_(ILockBytes, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** ILockBytes methods ***
+ STDMETHOD(ReadAt) (THIS_ ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbRead) PURE;
+ STDMETHOD(WriteAt) (THIS_ ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten) PURE;
+ STDMETHOD(Flush) (THIS) PURE;
+ STDMETHOD(SetSize) (THIS_ ULARGE_INTEGER cb) PURE;
+ STDMETHOD(LockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(UnlockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+};
+
+typedef ILockBytes FAR* LPLOCKBYTES;
+
+
+
+/****** IStream Interface ***************************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IStream
+
+DECLARE_INTERFACE_(IStream, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IStream methods ***
+ STDMETHOD(Read) (THIS_ VOID HUGEP *pv,
+ ULONG cb, ULONG FAR *pcbRead) PURE;
+ STDMETHOD(Write) (THIS_ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten) PURE;
+ STDMETHOD(Seek) (THIS_ LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER FAR *plibNewPosition) PURE;
+ STDMETHOD(SetSize) (THIS_ ULARGE_INTEGER libNewSize) PURE;
+ STDMETHOD(CopyTo) (THIS_ IStream FAR *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER FAR *pcbRead,
+ ULARGE_INTEGER FAR *pcbWritten) PURE;
+ STDMETHOD(Commit) (THIS_ DWORD grfCommitFlags) PURE;
+ STDMETHOD(Revert) (THIS) PURE;
+ STDMETHOD(LockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(UnlockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+ STDMETHOD(Clone)(THIS_ IStream FAR * FAR *ppstm) PURE;
+};
+
+typedef IStream FAR* LPSTREAM;
+
+
+
+/****** IStorage Interface **************************************************/
+
+#undef INTERFACE
+#define INTERFACE IStorage
+
+DECLARE_INTERFACE_(IStorage, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IStorage methods ***
+ STDMETHOD(CreateStream) (THIS_ const char FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream FAR *FAR *ppstm) PURE;
+ STDMETHOD(OpenStream) (THIS_ const char FAR* pwcsName,
+ void FAR *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream FAR *FAR *ppstm) PURE;
+ STDMETHOD(CreateStorage) (THIS_ const char FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStorage FAR *FAR *ppstg) PURE;
+ STDMETHOD(OpenStorage) (THIS_ const char FAR* pwcsName,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR *FAR *ppstg) PURE;
+ STDMETHOD(CopyTo) (THIS_ DWORD ciidExclude,
+ IID const FAR *rgiidExclude,
+ SNB snbExclude,
+ IStorage FAR *pstgDest) PURE;
+ STDMETHOD(MoveElementTo) (THIS_ char const FAR* lpszName,
+ IStorage FAR *pstgDest,
+ char const FAR* lpszNewName,
+ DWORD grfFlags) PURE;
+ STDMETHOD(Commit) (THIS_ DWORD grfCommitFlags) PURE;
+ STDMETHOD(Revert) (THIS) PURE;
+ STDMETHOD(EnumElements) (THIS_ DWORD reserved1,
+ void FAR *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG FAR *FAR *ppenm) PURE;
+ STDMETHOD(DestroyElement) (THIS_ const char FAR* pwcsName) PURE;
+ STDMETHOD(RenameElement) (THIS_ const char FAR* pwcsOldName,
+ const char FAR* pwcsNewName) PURE;
+ STDMETHOD(SetElementTimes) (THIS_ const char FAR *lpszName,
+ FILETIME const FAR *pctime,
+ FILETIME const FAR *patime,
+ FILETIME const FAR *pmtime) PURE;
+ STDMETHOD(SetClass) (THIS_ REFCLSID clsid) PURE;
+ STDMETHOD(SetStateBits) (THIS_ DWORD grfStateBits, DWORD grfMask) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+};
+
+typedef IStorage FAR* LPSTORAGE;
+
+
+
+/****** IRootStorage Interface **********************************************/
+
+#undef INTERFACE
+#define INTERFACE IRootStorage
+
+DECLARE_INTERFACE_(IRootStorage, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IRootStorage methods ***
+ STDMETHOD(SwitchToFile) (THIS_ LPSTR lpstrFile) PURE;
+};
+
+typedef IRootStorage FAR* LPROOTSTORAGE;
+
+
+
+/****** Storage API Prototypes ********************************************/
+
+STDAPI StgCreateDocfile(const char FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgCreateDocfileOnILockBytes(ILockBytes FAR *plkbyt,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgOpenStorage(const char FAR* pwcsName,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgOpenStorageOnILockBytes(ILockBytes FAR *plkbyt,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgIsStorageFile(const char FAR* pwcsName);
+STDAPI StgIsStorageILockBytes(ILockBytes FAR* plkbyt);
+
+STDAPI StgSetTimes(char const FAR* lpszName,
+ FILETIME const FAR* pctime,
+ FILETIME const FAR* patime,
+ FILETIME const FAR* pmtime);
+
+#endif
diff --git a/private/ole32/olethunk/ole16/inc/string.h b/private/ole32/olethunk/ole16/inc/string.h
new file mode 100644
index 000000000..97aafb672
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/string.h
@@ -0,0 +1,167 @@
+/***
+*string.h - declarations for string manipulation functions
+*
+* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the function declarations for the string
+* manipulation functions.
+* [ANSI/System V]
+*
+****/
+
+#ifndef _INC_STRING
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (_MSC_VER <= 600)
+#define __cdecl _cdecl
+#define __far _far
+#define __near _near
+#endif
+
+#ifndef _SIZE_T_DEFINED
+typedef unsigned int size_t;
+#define _SIZE_T_DEFINED
+#endif
+
+#ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+/* define NULL pointer value */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+/* function prototypes */
+
+void * __cdecl _memccpy(void *, const void *,
+ int, unsigned int);
+void * __cdecl memchr(const void *, int, size_t);
+int __cdecl memcmp(const void *, const void *,
+ size_t);
+int __cdecl _memicmp(const void *, const void *,
+ unsigned int);
+void * __cdecl memcpy(void *, const void *,
+ size_t);
+void * __cdecl memmove(void *, const void *,
+ size_t);
+void * __cdecl memset(void *, int, size_t);
+void __cdecl _movedata(unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int);
+char * __cdecl strcat(char *, const char *);
+char * __cdecl strchr(const char *, int);
+int __cdecl strcmp(const char *, const char *);
+int __cdecl _strcmpi(const char *, const char *);
+int __cdecl strcoll(const char *, const char *);
+int __cdecl _stricmp(const char *, const char *);
+char * __cdecl strcpy(char *, const char *);
+size_t __cdecl strcspn(const char *, const char *);
+char * __cdecl _strdup(const char *);
+char * __cdecl _strerror(const char *);
+char * __cdecl strerror(int);
+size_t __cdecl strlen(const char *);
+char * __cdecl _strlwr(char *);
+char * __cdecl strncat(char *, const char *,
+ size_t);
+int __cdecl strncmp(const char *, const char *,
+ size_t);
+int __cdecl _strnicmp(const char *, const char *,
+ size_t);
+char * __cdecl strncpy(char *, const char *,
+ size_t);
+char * __cdecl _strnset(char *, int, size_t);
+char * __cdecl strpbrk(const char *,
+ const char *);
+char * __cdecl strrchr(const char *, int);
+char * __cdecl _strrev(char *);
+char * __cdecl _strset(char *, int);
+size_t __cdecl strspn(const char *, const char *);
+char * __cdecl strstr(const char *,
+ const char *);
+char * __cdecl strtok(char *, const char *);
+char * __cdecl _strupr(char *);
+size_t __cdecl strxfrm (char *, const char *,
+ size_t);
+
+
+/* model independent function prototypes */
+
+void __far * __far __cdecl _fmemccpy(void __far *, const void __far *,
+ int, unsigned int);
+void __far * __far __cdecl _fmemchr(const void __far *, int, size_t);
+int __far __cdecl _fmemcmp(const void __far *, const void __far *,
+ size_t);
+void __far * __far __cdecl _fmemcpy(void __far *, const void __far *,
+ size_t);
+int __far __cdecl _fmemicmp(const void __far *, const void __far *,
+ unsigned int);
+void __far * __far __cdecl _fmemmove(void __far *, const void __far *,
+ size_t);
+void __far * __far __cdecl _fmemset(void __far *, int, size_t);
+char __far * __far __cdecl _fstrcat(char __far *, const char __far *);
+char __far * __far __cdecl _fstrchr(const char __far *, int);
+int __far __cdecl _fstrcmp(const char __far *, const char __far *);
+int __far __cdecl _fstricmp(const char __far *, const char __far *);
+char __far * __far __cdecl _fstrcpy(char __far *, const char __far *);
+size_t __far __cdecl _fstrcspn(const char __far *, const char __far *);
+char __far * __far __cdecl _fstrdup(const char __far *);
+char __near * __far __cdecl _nstrdup(const char __far *);
+size_t __far __cdecl _fstrlen(const char __far *);
+char __far * __far __cdecl _fstrlwr(char __far *);
+char __far * __far __cdecl _fstrncat(char __far *, const char __far *,
+ size_t);
+int __far __cdecl _fstrncmp(const char __far *, const char __far *,
+ size_t);
+int __far __cdecl _fstrnicmp(const char __far *, const char __far *,
+ size_t);
+char __far * __far __cdecl _fstrncpy(char __far *, const char __far *,
+ size_t);
+char __far * __far __cdecl _fstrnset(char __far *, int, size_t);
+char __far * __far __cdecl _fstrpbrk(const char __far *,
+ const char __far *);
+char __far * __far __cdecl _fstrrchr(const char __far *, int);
+char __far * __far __cdecl _fstrrev(char __far *);
+char __far * __far __cdecl _fstrset(char __far *, int);
+size_t __far __cdecl _fstrspn(const char __far *, const char __far *);
+char __far * __far __cdecl _fstrstr(const char __far *,
+ const char __far *);
+char __far * __far __cdecl _fstrtok(char __far *, const char __far *);
+char __far * __far __cdecl _fstrupr(char __far *);
+
+
+#ifndef __STDC__
+/* Non-ANSI names for compatibility */
+void * __cdecl memccpy(void *, const void *,
+ int, unsigned int);
+int __cdecl memicmp(const void *, const void *,
+ unsigned int);
+void __cdecl movedata(unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int);
+int __cdecl strcmpi(const char *, const char *);
+int __cdecl stricmp(const char *, const char *);
+char * __cdecl strdup(const char *);
+char * __cdecl strlwr(char *);
+int __cdecl strnicmp(const char *, const char *,
+ size_t);
+char * __cdecl strnset(char *, int, size_t);
+char * __cdecl strrev(char *);
+char * __cdecl strset(char *, int);
+char * __cdecl strupr(char *);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_STRING
+#endif /* _INC_STRING */
diff --git a/private/ole32/olethunk/ole16/inc/taskmap.h b/private/ole32/olethunk/ole16/inc/taskmap.h
new file mode 100644
index 000000000..36fe232cd
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/taskmap.h
@@ -0,0 +1,8 @@
+// taskmap.h - definitions for managing the etask (per task data).
+
+// NOTE: this is private to compobj.dll for now; it can be made public if necc.
+
+STDAPI_(BOOL) LookupEtask(HTASK FAR& hTask, Etask FAR& etask);
+STDAPI_(BOOL) SetEtask(HTASK hTask, Etask FAR& etask);
+
+extern IMalloc FAR* v_pMallocShared;
diff --git a/private/ole32/olethunk/ole16/inc/tchar.h b/private/ole32/olethunk/ole16/inc/tchar.h
new file mode 100644
index 000000000..8af064730
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/tchar.h
@@ -0,0 +1,555 @@
+/***
+*tchar.h - definitions for generic international text functions
+*
+* Copyright (c) 1991-1993, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Definitions for generic international functions, mostly defines
+* which map string/formatted-io/ctype functions to char, wchar_t, or
+* MBCS versions. To be used for compatibility between single-byte,
+* multi-byte and Unicode text models.
+*
+*
+*
+****/
+
+#ifndef _INC_TCHAR
+
+#ifdef _MSC_VER
+#pragma warning(disable:4505) /* disable unwanted C++ /W4 warning */
+/* #pragma warning(default:4505) */ /* use this to reenable, if necessary */
+#endif /* _MSC_VER */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* No Model-independent functions under Win32 */
+
+#define __far
+
+
+/* Default for Win32 is no inlining. Define _USE_INLINING to overide */
+
+#ifndef _USE_INLINING
+#define _NO_INLINING
+#endif
+
+
+/* No model-independent string functions for Win32 */
+
+#define _ftcscat _tcscat
+#define _ftcschr _tcschr
+#define _ftcscmp _tcscmp
+#define _ftcscpy _tcscpy
+#define _ftcscspn _tcscspn
+#define _ftcslen _tcslen
+#define _ftcsncat _tcsncat
+#define _ftcsncmp _tcsncmp
+#define _ftcsncpy _tcsncpy
+#define _ftcspbrk _tcspbrk
+#define _ftcsrchr _tcsrchr
+#define _ftcsspn _tcsspn
+#define _ftcsstr _tcsstr
+#define _ftcstok _tcstok
+
+#define _ftcsdup _tcsdup
+#define _ftcsicmp _tcsicmp
+#define _ftcsnicmp _tcsnicmp
+#define _ftcsnset _tcsnset
+#define _ftcsrev _tcsrev
+#define _ftcsset _tcsset
+
+
+/* Redundant "logical-character" mappings */
+
+#define _ftcsclen _tcsclen
+#define _ftcsnccat _tcsnccat
+#define _ftcsnccpy _tcsnccpy
+#define _ftcsnccmp _tcsnccmp
+#define _ftcsncicmp _tcsncicmp
+#define _ftcsncset _tcsncset
+
+#define _ftcsdec _tcsdec
+#define _ftcsinc _tcsinc
+#define _ftcsnbcnt _tcsncnt
+#define _ftcsnccnt _tcsncnt
+#define _ftcsnextc _tcsnextc
+#define _ftcsninc _tcsninc
+#define _ftcsspnp _tcsspnp
+
+#define _ftcslwr _tcslwr
+#define _ftcsupr _tcsupr
+
+#define _ftclen _tclen
+#define _ftccpy _tccpy
+#define _ftccmp _tccmp
+
+
+#ifdef _UNICODE
+
+
+#ifndef _WCTYPE_T_DEFINED
+typedef wchar_t wint_t;
+typedef wchar_t wctype_t;
+#define _WCTYPE_T_DEFINED
+#endif
+
+#ifndef __TCHAR_DEFINED
+typedef wchar_t _TCHAR;
+typedef wint_t _TINT;
+#define __TCHAR_DEFINED
+#endif
+
+#ifndef _TCHAR_DEFINED
+#if !__STDC__
+typedef wchar_t TCHAR;
+#endif
+#define _TCHAR_DEFINED
+#endif
+
+#define _TEOF WEOF
+
+#define __T(x) L ## x
+
+
+/* Formatted i/o */
+
+#define _tprintf wprintf
+#define _ftprintf fwprintf
+#define _stprintf swprintf
+#define _sntprintf _snwprintf
+#define _vtprintf vwprintf
+#define _vftprintf vfwprintf
+#define _vstprintf vswprintf
+#define _vsntprintf _vsnwprintf
+#define _tscanf wscanf
+#define _ftscanf fwscanf
+#define _stscanf swscanf
+
+
+/* Unformatted i/o */
+
+#define _fgettc fgetwc
+#define _fgettchar _fgetwchar
+#define _fgetts fgetws
+#define _fputtc fputwc
+#define _fputtchar _fputwchar
+#define _fputts fputws
+#define _gettc getwc
+#define _gettchar getwchar
+#define _puttc putwc
+#define _puttchar putwchar
+#define _ungettc ungetwc
+
+
+/* String conversion functions */
+
+#define _tcstod wcstod
+#define _tcstol wcstol
+#define _tcstoul wcstoul
+
+
+/* String functions */
+
+#define _tcscat wcscat
+#define _tcschr wcschr
+#define _tcscmp wcscmp
+#define _tcscpy wcscpy
+#define _tcscspn wcscspn
+#define _tcslen wcslen
+#define _tcsncat wcsncat
+#define _tcsncmp wcsncmp
+#define _tcsncpy wcsncpy
+#define _tcspbrk wcspbrk
+#define _tcsrchr wcsrchr
+#define _tcsspn wcsspn
+#define _tcsstr wcsstr
+#define _tcstok wcstok
+
+#define _tcsdup _wcsdup
+#define _tcsicmp _wcsicmp
+#define _tcsnicmp _wcsnicmp
+#define _tcsnset _wcsnset
+#define _tcsrev _wcsrev
+#define _tcsset _wcsset
+
+
+/* Redundant "logical-character" mappings */
+
+#define _tcsclen wcslen
+#define _tcsnccat wcsncat
+#define _tcsnccpy wcsncpy
+#define _tcsnccmp wcsncmp
+#define _tcsncicmp _wcsnicmp
+#define _tcsncset _wcsnset
+
+#define _tcsdec _wcsdec
+#define _tcsinc _wcsinc
+#define _tcsnbcnt _wcsncnt
+#define _tcsnccnt _wcsncnt
+#define _tcsnextc _wcsnextc
+#define _tcsninc _wcsninc
+#define _tcsspnp _wcsspnp
+
+#define _tcslwr _wcslwr
+#define _tcsupr _wcsupr
+#define _tcsxfrm wcsxfrm
+#define _tcscoll wcscoll
+#define _tcsicoll _wcsicoll
+
+
+#if !__STDC__ || defined(_NO_INLINING)
+#define _tclen(_pc) (1)
+#define _tccpy(_pc1,_cpc2) ((*(_pc1) = *(_cpc2)))
+#define _tccmp(_cpc1,_cpc2) ((*(_cpc1))-(*(_cpc2)))
+#else
+__inline size_t _tclen(const wchar_t *_cpc) { return (_cpc,1); }
+__inline void _tccpy(wchar_t *_pc1, const wchar_t *_cpc2) { *_pc1 = (wchar_t)*_cpc2; }
+__inline int _tccmp(const wchar_t *_cpc1, const wchar_t *_cpc2) { return (int) ((*_cpc1)-(*_cpc2)); }
+#endif
+
+
+/* ctype functions */
+
+#define _istalpha iswalpha
+#define _istupper iswupper
+#define _istlower iswlower
+#define _istdigit iswdigit
+#define _istxdigit iswxdigit
+#define _istspace iswspace
+#define _istpunct iswpunct
+#define _istalnum iswalnum
+#define _istprint iswprint
+#define _istgraph iswgraph
+#define _istcntrl iswcntrl
+#define _istascii iswascii
+
+#define _totupper towupper
+#define _totlower towlower
+
+#define _istlegal (1)
+
+
+#if !__STDC__ || defined(_NO_INLINING)
+#define _wcsdec(_cpc, _pc) ((_pc)-1)
+#define _wcsinc(_pc) ((_pc)+1)
+#define _wcsnextc(_cpc) ((unsigned int) *(_cpc))
+#define _wcsninc(_pc, _sz) (((_pc)+(_sz)))
+#define _wcsncnt(_cpc, _sz) ((wcslen(_cpc)>_sz) ? _sz : wcslen(_cpc))
+#define _wcsspnp(_cpc1, _cpc2) ((*((_cpc1)+wcsspn(_cpc1,_cpc2))) ? ((_cpc1)+wcsspn(_cpc1,_cpc2)) : NULL)
+#else
+__inline wchar_t * _wcsdec(const wchar_t * _cpc, const wchar_t * _pc) { return (wchar_t *)(_cpc,(_pc-1)); }
+__inline wchar_t * _wcsinc(const wchar_t * _pc) { return (wchar_t *)(_pc+1); }
+__inline unsigned int _wcsnextc(const wchar_t * _cpc) { return (unsigned int)*_cpc; }
+__inline wchar_t * _wcsninc(const wchar_t * _pc, size_t _sz) { return (wchar_t *)(_pc+_sz); }
+__inline size_t _wcsncnt( const wchar_t * _cpc, size_t _sz) { size_t len; len = wcslen(_cpc); return (len>_sz) ? _sz : len; }
+__inline wchar_t * _wcsspnp( const wchar_t * _cpc1, const wchar_t * _cpc2) { return (*(_cpc1 += wcsspn(_cpc1,_cpc2))!='\0') ? (wchar_t*)_cpc1 : NULL; }
+#endif
+
+
+#else /* ndef _UNICODE */
+
+
+#if !defined(_CHAR_UNSIGNED) && !defined(_JWARNING_DEFINED)
+/* #pragma message("TCHAR.H: Warning: The /J option is recommended for international compilation") */
+#define _JWARNING_DEFINED
+#endif
+
+
+#include <string.h>
+
+
+#define __T(x) x
+
+
+/* Formatted i/o */
+
+#define _tprintf printf
+#define _ftprintf fprintf
+#define _stprintf sprintf
+#define _sntprintf _snprintf
+#define _vtprintf vprintf
+#define _vftprintf vfprintf
+#define _vstprintf vsprintf
+#define _vsntprintf _vsnprintf
+#define _tscanf scanf
+#define _ftscanf fscanf
+#define _stscanf sscanf
+
+
+/* Unformatted i/o */
+
+#define _fgettc(_f) (_TINT)fgetc((_f))
+#define _fgettchar (_TINT)_fgetchar
+#define _fgetts(_s,_i,_f) fgets((_s),(_i),(_f))
+#define _fputtc(_i,_f) (_TINT)fputc((int)(_i),(_f))
+#define _fputtchar(_i) (_TINT)_fputchar((int)(_i))
+#define _fputts(_s,_f) (_TINT)fputs((_s),(_f))
+#define _gettc(_f) (_TINT)getc((_f))
+#define _gettchar (_TINT)getchar
+#define _puttc(_i,_f) (_TINT)putc((int)(_i),(_f))
+#define _puttchar(_i) (_TINT)putchar((int)(_i))
+#define _ungettc(_i,_f) (_TINT)ungetc((int)(_i),(_f))
+
+
+/* String conversion functions */
+
+#define _tcstod strtod
+#define _tcstol strtol
+#define _tcstoul strtoul
+
+
+#ifdef _MBCS
+
+#ifndef __TCHAR_DEFINED
+typedef char _TCHAR;
+typedef unsigned int _TINT;
+#define __TCHAR_DEFINED
+#endif
+
+#ifndef _TCHAR_DEFINED
+#if !__STDC__
+typedef char TCHAR;
+#endif
+#define _TCHAR_DEFINED
+#endif
+
+#define _TEOF EOF
+
+
+#include <mbstring.h>
+
+
+/* Helper macros for MB casts */
+
+#define _MB(_s) ((unsigned char *)(_s))
+#define _CMB(_s) ((const unsigned char *)(_s))
+
+
+/* String functions */
+
+#define _tcscat(_s1,_s2) (_TCHAR*)_mbscat(_MB(_s1),_CMB(_s2))
+#define _tcschr(_s,_i) (_TCHAR*)_mbschr(_CMB(_s),(_i))
+#define _tcscmp(_s1,_s2) _mbscmp(_CMB(_s1),_CMB(_s2))
+#define _tcscpy(_s1,_s2) (_TCHAR*)_mbscpy(_MB(_s1),_CMB(_s2))
+#define _tcscspn(_s1,_s2) _mbscspn(_CMB(_s1),_CMB(_s2))
+#define _tcslen(_s) strlen((_s))
+#define _tcsncat(_s1,_s2,_n) (_TCHAR*)_mbsnbcat(_MB(_s1),_CMB(_s2),(_n))
+#define _tcsncmp(_s1,_s2,_n) _mbsnbcmp(_CMB(_s1),_CMB(_s2),(_n))
+#define _tcsncpy(_s1,_s2,_n) (_TCHAR*)_mbsnbcpy(_MB(_s1),_CMB(_s2),(_n))
+#define _tcspbrk(_s1,_s2) (_TCHAR*)_mbspbrk(_CMB(_s1),_CMB(_s2))
+#define _tcsrchr(_s,_i) (_TCHAR*)_mbsrchr(_CMB(_s),(_i))
+#define _tcsspn(_s1,_s2) _mbsspn(_CMB(_s1),_CMB(_s2))
+#define _tcsstr(_s1,_s2) (_TCHAR*)_mbsstr(_CMB(_s1),_CMB(_s2))
+#define _tcstok(_s1,_s2) (_TCHAR*)_mbstok(_MB(_s1),_CMB(_s2))
+
+#define _tcsdup(_s) (_TCHAR*)_mbsdup(_CMB(_s))
+#define _tcsicmp(_s1,_s2) _mbsicmp(_CMB(_s1),_CMB(_s2))
+#define _tcsnicmp(_s1,_s2,_n) _mbsnbicmp(_CMB(_s1),_CMB(_s2),(_n))
+#define _tcsnset(_s,_i,_n) (_TCHAR*)_mbsnbset(_MB(_s),(_i),(_n))
+#define _tcsrev(_s) (_TCHAR*)_mbsrev(_MB(_s))
+#define _tcsset(_s,_i) (_TCHAR*)_mbsset(_MB(_s),(_i))
+
+
+/* "logical-character" mappings */
+
+#define _tcsclen(_s) _mbslen(_MB(_s))
+#define _tcsnccat(_s1,_s2,_n) (_TCHAR*)_mbsncat(_MB(_s1),_CMB(_s2),(_n))
+#define _tcsnccpy(_s1,_s2,_n) (_TCHAR*)_mbsncpy(_MB(_s1),_CMB(_s2),(_n))
+#define _tcsnccmp(_s1,_s2,_n) _mbsncmp(_CMB(_s1),_CMB(_s2),(_n))
+#define _tcsncicmp(_s1,_s2,_n) _mbsnicmp(_CMB(_s1),_CMB(_s2),(_n))
+#define _tcsncset(_s,_i,_n) (_TCHAR*)_mbsnset(_MB(_s),(_i),(_n))
+
+
+/* MBCS-specific mappings */
+
+#define _tcsdec(_s1,_s2) (_TCHAR*)_mbsdec(_CMB(_s1),_CMB(_s2))
+#define _tcsinc(_s) (_TCHAR*)_mbsinc(_CMB(_s))
+#define _tcsnbcnt(_s,_n) _mbsnbcnt(_CMB(_s),(_n))
+#define _tcsnccnt(_s,_n) _mbsnccnt(_CMB(_s),(_n))
+#define _tcsnextc(_s) _mbsnextc(_CMB(_s))
+#define _tcsninc(_s,_n) (_TCHAR*)_mbsninc(_CMB(_s),(_n))
+#define _tcsspnp(_s1,_s2) (_TCHAR*)_mbsspnp(_CMB(_s1),_CMB(_s2))
+
+#define _tcslwr(_s) (_TCHAR*)_mbslwr(_MB(_s))
+#define _tcsupr(_s) (_TCHAR*)_mbsupr(_MB(_s))
+#define _tcsxfrm(_d,_s,_n) (strncpy((_d),(_s),(_n)),strlen((_s)))
+#define _tcscoll _tcscmp
+#define _tcsicoll _tcsicmp
+
+#define _tclen(_s) _mbclen(_CMB(_s))
+#define _tccpy(_s1,_s2) _mbccpy(_MB(_s1),_CMB(_s2))
+#define _tccmp(_s1,_s2) _tcsnccmp((_s1),(_s2),1)
+
+
+/* ctype functions */
+
+#define _istalpha _ismbcalpha
+#define _istupper _ismbcupper
+#define _istlower _ismbclower
+#define _istdigit _ismbcdigit
+#define _istxdigit _isxdigit
+#define _istspace _ismbcspace
+#define _istprint _ismbcprint
+#define _istcntrl _iscntrl
+#define _istascii _isascii
+
+#define _totupper _mbctoupper
+#define _totlower _mbctolower
+
+#define _istlegal _ismbclegal
+
+
+#else /* !_MBCS */
+
+
+#ifndef __TCHAR_DEFINED
+typedef char _TCHAR;
+typedef int _TINT;
+#define __TCHAR_DEFINED
+#endif
+
+#ifndef _TCHAR_DEFINED
+#if !__STDC__
+typedef char TCHAR;
+#endif
+#define _TCHAR_DEFINED
+#endif
+
+#define _TEOF EOF
+
+
+/* String functions */
+
+#define _tcscat strcat
+#define _tcschr strchr
+#define _tcscmp strcmp
+#define _tcscpy strcpy
+#define _tcscspn strcspn
+#define _tcslen strlen
+#define _tcsncat strncat
+#define _tcsncmp strncmp
+#define _tcsncpy strncpy
+#define _tcspbrk strpbrk
+#define _tcsrchr strrchr
+#define _tcsspn strspn
+#define _tcsstr strstr
+#define _tcstok strtok
+
+#define _tcsdup _strdup
+#define _tcsicmp _stricmp
+#define _tcsnicmp _strnicmp
+#define _tcsnset _strnset
+#define _tcsrev _strrev
+#define _tcsset _strset
+
+
+/* "logical-character" mappings */
+
+#define _tcsclen strlen
+#define _tcsnccat strncat
+#define _tcsnccpy strncpy
+#define _tcsnccmp strncmp
+#define _tcsncicmp _strnicmp
+#define _tcsncset _strnset
+
+
+/* MBCS-specific functions */
+
+#define _tcsdec _strdec
+#define _tcsinc _strinc
+#define _tcsnbcnt _strncnt
+#define _tcsnccnt _strncnt
+#define _tcsnextc _strnextc
+#define _tcsninc _strninc
+#define _tcsspnp _strspnp
+
+#define _tcslwr _strlwr
+#define _tcsupr _strupr
+#define _tcsxfrm strxfrm
+#define _tcscoll strcoll
+#define _tcsicoll _stricoll
+
+
+#if !__STDC__ || defined(_NO_INLINING)
+#define _tclen(_pc) (1)
+#define _tccpy(_pc1,_cpc2) (*(_pc1) = *(_cpc2))
+#define _tccmp(_cpc1,_cpc2) (((unsigned char)*(_cpc1))-((unsigned char)*(_cpc2)))
+#else
+__inline size_t _tclen(const char *_cpc) { return (_cpc,1); }
+__inline void _tccpy(char *_pc1, const char *_cpc2) { *_pc1 = *_cpc2; }
+__inline int _tccmp(const char *_cpc1, const char *_cpc2) { return (int) (((unsigned char)*_cpc1)-((unsigned char)*_cpc2)); }
+#endif
+
+
+/* ctype-functions */
+
+#define _istalpha isalpha
+#define _istupper isupper
+#define _istlower islower
+#define _istdigit isdigit
+#define _istxdigit isxdigit
+#define _istspace isspace
+#define _istpunct ispunct
+#define _istalnum isalnum
+#define _istprint isprint
+#define _istgraph isgraph
+#define _istcntrl iscntrl
+#define _istascii isascii
+
+#define _totupper toupper
+#define _totlower tolower
+
+#define _istlegal (1)
+
+
+/* the following is optional if functional versions are available */
+
+/* define NULL pointer value */
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+
+#if !__STDC__ || defined(_NO_INLINING)
+#define _strdec(_cpc, _pc) ((_pc)-1)
+#define _strinc(_pc) ((_pc)+1)
+#define _strnextc(_cpc) ((unsigned int) *(_cpc))
+#define _strninc(_pc, _sz) (((_pc)+(_sz)))
+#define _strncnt(_cpc, _sz) ((strlen(_cpc)>_sz) ? _sz : strlen(_cpc))
+#define _strspnp(_cpc1, _cpc2) ((*((_cpc1)+strspn(_cpc1,_cpc2))) ? ((_cpc1)+strspn(_cpc1,_cpc2)) : NULL)
+#else /* __STDC__ */
+__inline char * _strdec(const char * _cpc, const char * _pc) { return (char *)(_cpc,(_pc-1)); }
+__inline char * _strinc(const char * _pc) { return (char *)(_pc+1); }
+__inline unsigned int _strnextc(const char * _cpc) { return (unsigned int)*_cpc; }
+__inline char * _strninc(const char * _pc, size_t _sz) { return (char *)(_pc+_sz); }
+__inline size_t _strncnt( const char * _cpc, size_t _sz) { size_t len; len = strlen(_cpc); return (len>_sz) ? _sz : len; }
+__inline char * _strspnp( const char * _cpc1, const char * _cpc2) { return (*(_cpc1 += strspn(_cpc1,_cpc2))!='\0') ? (char*)_cpc1 : NULL; }
+#endif /* __STDC__ */
+
+
+#endif /* _MBCS */
+
+#endif /* _UNICODE */
+
+
+/* Generic text macros to be used with string literals and character constants.
+ Will also allow symbolic constants that resolve to same. */
+
+#define _T(x) __T(x)
+#define _TEXT(x) __T(x)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#define _INC_TCHAR
+#endif /* _INC_TCHAR */
diff --git a/private/ole32/olethunk/ole16/inc/testmess.h b/private/ole32/olethunk/ole16/inc/testmess.h
new file mode 100644
index 000000000..0669b2a1e
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/testmess.h
@@ -0,0 +1,52 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: testmess.h
+//
+// Contents: Declarations for private test messages
+//
+// Classes:
+//
+// Functions:
+//
+// History: dd-mmm-yy Author Comment
+// 06-Feb-94 alexgo author
+//
+//--------------------------------------------------------------------------
+
+#ifndef __TESTMESS_H
+#define __TESTMESS_H
+
+#define TEST_SUCCESS 0
+#define TEST_FAILURE 1
+#define TEST_UNKNOWN 2
+
+// Test End: sent back to the driver from the test app idicating the
+// success or failure of the test (and optionally a failure code)
+// wParam == TEST_SUCCESS | TEST_FAILURE
+// lParam == HRESULT (optional)
+#define WM_TESTEND WM_USER + 1
+
+// Test Register: sent back to the driver from the test app giving
+// the driver a window handle that it can send messages to.
+// wParam == HWND of the test app
+#define WM_TESTREG WM_USER + 2
+
+// Tests Completed: used to indicate that all requested tests have
+// been completed
+#define WM_TESTSCOMPLETED WM_USER + 3
+
+// Test Start: used to kick the task stack interpreter into action
+#define WM_TESTSTART WM_USER + 4
+
+// Individual test messages. Sent by the driver app to the test app
+// telling it to start an individual test.
+#define WM_TEST1 WM_USER + 10
+#define WM_TEST2 WM_USER + 11
+#define WM_TEST3 WM_USER + 12
+#define WM_TEST4 WM_USER + 13
+#define WM_TEST5 WM_USER + 14
+
+#endif // !__TESTMESS_H
diff --git a/private/ole32/olethunk/ole16/inc/toolhelp.h b/private/ole32/olethunk/ole16/inc/toolhelp.h
new file mode 100644
index 000000000..25b918f80
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/toolhelp.h
@@ -0,0 +1,469 @@
+/*****************************************************************************\
+* *
+* toolhelp.h - toolhelp.dll functions, types, and definitions *
+* *
+* Version 1.0 *
+* *
+* NOTE: windows.h must be #included first *
+* *
+* Copyright (c) 1992, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+#ifndef _INC_TOOLHELP
+#define _INC_TOOLHELP
+
+#ifndef RC_INVOKED
+#pragma pack(1) /* Assume byte packing throughout */
+#endif
+
+#ifdef __cplusplus
+extern "C" { /* Assume C declarations for C++ */
+#endif /* __cplusplus */
+
+#ifndef _INC_WINDOWS /* If included with 3.0 headers... */
+#define LPCSTR LPSTR
+#define WINAPI FAR PASCAL
+#define CALLBACK FAR PASCAL
+#define UINT WORD
+#define HMODULE HANDLE
+#define HINSTANCE HANDLE
+#define HLOCAL HANDLE
+#define HGLOBAL HANDLE
+#define HTASK HANDLE
+#endif /* _INC_WINDOWS */
+
+/****** General symbols ******************************************************/
+#define MAX_DATA 11
+#define MAX_PATH 255
+#define MAX_MODULE_NAME 8 + 1
+#define MAX_CLASSNAME 255
+
+/****** Global heap walking ***************************************************/
+typedef struct tagGLOBALINFO
+{
+ DWORD dwSize;
+ WORD wcItems;
+ WORD wcItemsFree;
+ WORD wcItemsLRU;
+} GLOBALINFO;
+
+typedef struct tagGLOBALENTRY
+{
+ DWORD dwSize;
+ DWORD dwAddress;
+ DWORD dwBlockSize;
+ HGLOBAL hBlock;
+ WORD wcLock;
+ WORD wcPageLock;
+ WORD wFlags;
+ BOOL wHeapPresent;
+ HGLOBAL hOwner;
+ WORD wType;
+ WORD wData;
+ DWORD dwNext;
+ DWORD dwNextAlt;
+} GLOBALENTRY;
+
+/* GlobalFirst()/GlobalNext() flags */
+#define GLOBAL_ALL 0
+#define GLOBAL_LRU 1
+#define GLOBAL_FREE 2
+
+/* GLOBALENTRY.wType entries */
+#define GT_UNKNOWN 0
+#define GT_DGROUP 1
+#define GT_DATA 2
+#define GT_CODE 3
+#define GT_TASK 4
+#define GT_RESOURCE 5
+#define GT_MODULE 6
+#define GT_FREE 7
+#define GT_INTERNAL 8
+#define GT_SENTINEL 9
+#define GT_BURGERMASTER 10
+
+/* If GLOBALENTRY.wType==GT_RESOURCE, the following is GLOBALENTRY.wData: */
+#define GD_USERDEFINED 0
+#define GD_CURSORCOMPONENT 1
+#define GD_BITMAP 2
+#define GD_ICONCOMPONENT 3
+#define GD_MENU 4
+#define GD_DIALOG 5
+#define GD_STRING 6
+#define GD_FONTDIR 7
+#define GD_FONT 8
+#define GD_ACCELERATORS 9
+#define GD_RCDATA 10
+#define GD_ERRTABLE 11
+#define GD_CURSOR 12
+#define GD_ICON 14
+#define GD_NAMETABLE 15
+#define GD_MAX_RESOURCE 15
+
+/* GLOBALENTRY.wFlags */
+#define GF_PDB_OWNER 0x0100 /* Low byte is KERNEL flags */
+
+BOOL WINAPI GlobalInfo(GLOBALINFO FAR* lpGlobalInfo);
+BOOL WINAPI GlobalFirst(GLOBALENTRY FAR* lpGlobal, WORD wFlags);
+BOOL WINAPI GlobalNext(GLOBALENTRY FAR* lpGlobal, WORD wFlags);
+BOOL WINAPI GlobalEntryHandle(GLOBALENTRY FAR* lpGlobal, HGLOBAL hItem);
+BOOL WINAPI GlobalEntryModule(GLOBALENTRY FAR* lpGlobal, HMODULE hModule, WORD wSeg);
+WORD WINAPI GlobalHandleToSel(HGLOBAL hMem);
+
+/****** Local heap walking ***************************************************/
+
+typedef struct tagLOCALINFO
+{
+ DWORD dwSize;
+ WORD wcItems;
+} LOCALINFO;
+
+typedef struct tagLOCALENTRY
+{
+ DWORD dwSize;
+ HLOCAL hHandle;
+ WORD wAddress;
+ WORD wSize;
+ WORD wFlags;
+ WORD wcLock;
+ WORD wType;
+ WORD hHeap;
+ WORD wHeapType;
+ WORD wNext;
+} LOCALENTRY;
+
+/* LOCALENTRY.wHeapType flags */
+#define NORMAL_HEAP 0
+#define USER_HEAP 1
+#define GDI_HEAP 2
+
+/* LOCALENTRY.wFlags */
+#define LF_FIXED 1
+#define LF_FREE 2
+#define LF_MOVEABLE 4
+
+/* LOCALENTRY.wType */
+#define LT_NORMAL 0
+#define LT_FREE 0xff
+#define LT_GDI_PEN 1 /* LT_GDI_* is for GDI's heap */
+#define LT_GDI_BRUSH 2
+#define LT_GDI_FONT 3
+#define LT_GDI_PALETTE 4
+#define LT_GDI_BITMAP 5
+#define LT_GDI_RGN 6
+#define LT_GDI_DC 7
+#define LT_GDI_DISABLED_DC 8
+#define LT_GDI_METADC 9
+#define LT_GDI_METAFILE 10
+#define LT_GDI_MAX LT_GDI_METAFILE
+#define LT_USER_CLASS 1 /* LT_USER_* is for USER's heap */
+#define LT_USER_WND 2
+#define LT_USER_STRING 3
+#define LT_USER_MENU 4
+#define LT_USER_CLIP 5
+#define LT_USER_CBOX 6
+#define LT_USER_PALETTE 7
+#define LT_USER_ED 8
+#define LT_USER_BWL 9
+#define LT_USER_OWNERDRAW 10
+#define LT_USER_SPB 11
+#define LT_USER_CHECKPOINT 12
+#define LT_USER_DCE 13
+#define LT_USER_MWP 14
+#define LT_USER_PROP 15
+#define LT_USER_LBIV 16
+#define LT_USER_MISC 17
+#define LT_USER_ATOMS 18
+#define LT_USER_LOCKINPUTSTATE 19
+#define LT_USER_HOOKLIST 20
+#define LT_USER_USERSEEUSERDOALLOC 21
+#define LT_USER_HOTKEYLIST 22
+#define LT_USER_POPUPMENU 23
+#define LT_USER_HANDLETABLE 32
+#define LT_USER_MAX LT_USER_HANDLETABLE
+
+BOOL WINAPI LocalInfo(LOCALINFO FAR* lpLocal, HGLOBAL hHeap);
+BOOL WINAPI LocalFirst(LOCALENTRY FAR* lpLocal, HGLOBAL hHeap);
+BOOL WINAPI LocalNext(LOCALENTRY FAR* lpLocal);
+
+/****** Stack Tracing ********************************************************/
+
+typedef struct tagSTACKTRACEENTRY
+{
+ DWORD dwSize;
+ HTASK hTask;
+ WORD wSS;
+ WORD wBP;
+ WORD wCS;
+ WORD wIP;
+ HMODULE hModule;
+ WORD wSegment;
+ WORD wFlags;
+} STACKTRACEENTRY;
+
+/* STACKTRACEENTRY.wFlags values */
+#define FRAME_FAR 0
+#define FRAME_NEAR 1
+
+BOOL WINAPI StackTraceFirst(STACKTRACEENTRY FAR* lpStackTrace, HTASK hTask);
+BOOL WINAPI StackTraceCSIPFirst(STACKTRACEENTRY FAR* lpStackTrace,
+ WORD wSS, WORD wCS, WORD wIP, WORD wBP);
+BOOL WINAPI StackTraceNext(STACKTRACEENTRY FAR* lpStackTrace);
+
+/****** Module list walking **************************************************/
+
+typedef struct tagMODULEENTRY
+{
+ DWORD dwSize;
+ char szModule[MAX_MODULE_NAME + 1];
+ HMODULE hModule;
+ WORD wcUsage;
+ char szExePath[MAX_PATH + 1];
+ WORD wNext;
+} MODULEENTRY;
+
+BOOL WINAPI ModuleFirst(MODULEENTRY FAR* lpModule);
+BOOL WINAPI ModuleNext(MODULEENTRY FAR* lpModule);
+HMODULE WINAPI ModuleFindName(MODULEENTRY FAR* lpModule, LPCSTR lpstrName);
+HMODULE WINAPI ModuleFindHandle(MODULEENTRY FAR* lpModule, HMODULE hModule);
+
+/****** Task list walking *****************************************************/
+
+typedef struct tagTASKENTRY
+{
+ DWORD dwSize;
+ HTASK hTask;
+ HTASK hTaskParent;
+ HINSTANCE hInst;
+ HMODULE hModule;
+ WORD wSS;
+ WORD wSP;
+ WORD wStackTop;
+ WORD wStackMinimum;
+ WORD wStackBottom;
+ WORD wcEvents;
+ HGLOBAL hQueue;
+ char szModule[MAX_MODULE_NAME + 1];
+ WORD wPSPOffset;
+ HANDLE hNext;
+} TASKENTRY;
+
+BOOL WINAPI TaskFirst(TASKENTRY FAR* lpTask);
+BOOL WINAPI TaskNext(TASKENTRY FAR* lpTask);
+BOOL WINAPI TaskFindHandle(TASKENTRY FAR* lpTask, HTASK hTask);
+DWORD WINAPI TaskSetCSIP(HTASK hTask, WORD wCS, WORD wIP);
+DWORD WINAPI TaskGetCSIP(HTASK hTask);
+BOOL WINAPI TaskSwitch(HTASK hTask, DWORD dwNewCSIP);
+
+/****** Window Class enumeration **********************************************/
+
+typedef struct tagCLASSENTRY
+{
+ DWORD dwSize;
+ HMODULE hInst; /* This is really an hModule */
+ char szClassName[MAX_CLASSNAME + 1];
+ WORD wNext;
+} CLASSENTRY;
+
+BOOL WINAPI ClassFirst(CLASSENTRY FAR* lpClass);
+BOOL WINAPI ClassNext(CLASSENTRY FAR* lpClass);
+
+/****** Information functions *************************************************/
+
+typedef struct tagMEMMANINFO
+{
+ DWORD dwSize;
+ DWORD dwLargestFreeBlock;
+ DWORD dwMaxPagesAvailable;
+ DWORD dwMaxPagesLockable;
+ DWORD dwTotalLinearSpace;
+ DWORD dwTotalUnlockedPages;
+ DWORD dwFreePages;
+ DWORD dwTotalPages;
+ DWORD dwFreeLinearSpace;
+ DWORD dwSwapFilePages;
+ WORD wPageSize;
+} MEMMANINFO;
+
+BOOL WINAPI MemManInfo(MEMMANINFO FAR* lpEnhMode);
+
+typedef struct tagSYSHEAPINFO
+{
+ DWORD dwSize;
+ WORD wUserFreePercent;
+ WORD wGDIFreePercent;
+ HGLOBAL hUserSegment;
+ HGLOBAL hGDISegment;
+} SYSHEAPINFO;
+
+BOOL WINAPI SystemHeapInfo(SYSHEAPINFO FAR* lpSysHeap);
+
+/****** Interrupt Handling ****************************************************/
+
+/* Hooked interrupts */
+#define INT_DIV0 0
+#define INT_1 1
+#define INT_3 3
+#define INT_UDINSTR 6
+#define INT_STKFAULT 12
+#define INT_GPFAULT 13
+#define INT_BADPAGEFAULT 14
+#define INT_CTLALTSYSRQ 256
+
+/* TOOLHELP Interrupt callbacks registered with InterruptRegister should
+ * always be written in assembly language. The stack frame is not
+ * compatible with high level language conventions.
+ *
+ * This stack frame looks as follows to the callback. All registers
+ * should be preserved across this callback to allow restarting fault.
+ * ------------
+ * | Flags | [SP + 0Eh]
+ * | CS | [SP + 0Ch]
+ * | IP | [SP + 0Ah]
+ * | Handle | [SP + 08h]
+ * |Exception#| [SP + 06h]
+ * | AX | [SP + 04h] AX Saved to allow MakeProcInstance
+ * | Ret CS | [SP + 02h]
+ * SP---> | Ret IP | [SP + 00h]
+ * ------------
+ */
+BOOL WINAPI InterruptRegister(HTASK hTask, FARPROC lpfnIntCallback);
+BOOL WINAPI InterruptUnRegister(HTASK hTask);
+
+/* Notifications:
+ * When a notification callback is called, two parameters are passed
+ * in: a WORD, wID, and another DWORD, dwData. wID is one of
+ * the values NFY_* below. Callback routines should ignore unrecog-
+ * nized values to preserve future compatibility. Callback routines
+ * are also passed a dwData value. This may contain data or may be
+ * a FAR pointer to a structure, or may not be used depending on
+ * which notification is being received.
+ *
+ * In all cases, if the return value of the callback is TRUE, the
+ * notification will NOT be passed on to other callbacks. It has
+ * been handled. This should be used sparingly and only with certain
+ * notifications. Callbacks almost always return FALSE.
+ */
+
+/* NFY_UNKNOWN: An unknown notification has been returned from KERNEL. Apps
+ * should ignore these.
+ */
+#define NFY_UNKNOWN 0
+
+/* NFY_LOADSEG: dwData points to a NFYLOADSEG structure */
+#define NFY_LOADSEG 1
+typedef struct tagNFYLOADSEG
+{
+ DWORD dwSize;
+ WORD wSelector;
+ WORD wSegNum;
+ WORD wType; /* Low bit set if data seg, clear if code seg */
+ WORD wcInstance; /* Instance count ONLY VALID FOR DATA SEG */
+ LPCSTR lpstrModuleName;
+} NFYLOADSEG;
+
+/* NFY_FREESEG: LOWORD(dwData) is the selector of the segment being freed */
+#define NFY_FREESEG 2
+
+/* NFY_STARTDLL: dwData points to a NFYLOADSEG structure */
+#define NFY_STARTDLL 3
+typedef struct tagNFYSTARTDLL
+{
+ DWORD dwSize;
+ HMODULE hModule;
+ WORD wCS;
+ WORD wIP;
+} NFYSTARTDLL;
+
+/* NFY_STARTTASK: dwData is the CS:IP of the start address of the task */
+#define NFY_STARTTASK 4
+
+/* NFY_EXITTASK: The low byte of dwData contains the program exit code */
+#define NFY_EXITTASK 5
+
+/* NFY_DELMODULE: LOWORD(dwData) is the handle of the module to be freed */
+#define NFY_DELMODULE 6
+
+/* NFY_RIP: dwData points to a NFYRIP structure */
+#define NFY_RIP 7
+typedef struct tagNFYRIP
+{
+ DWORD dwSize;
+ WORD wIP;
+ WORD wCS;
+ WORD wSS;
+ WORD wBP;
+ WORD wExitCode;
+} NFYRIP;
+
+/* NFY_TASKIN: No data. Callback should do GetCurrentTask() */
+#define NFY_TASKIN 8
+
+/* NFY_TASKOUT: No data. Callback should do GetCurrentTask() */
+#define NFY_TASKOUT 9
+
+/* NFY_INCHAR: Return value from callback is used. If NULL, mapped to 'i' */
+#define NFY_INCHAR 10
+
+/* NFY_OUTSTR: dwData points to the string to be displayed */
+#define NFY_OUTSTR 11
+
+/* NFY_LOGERROR: dwData points to a NFYLOGERROR struct */
+#define NFY_LOGERROR 12
+typedef struct tagNFYLOGERROR
+{
+ DWORD dwSize;
+ UINT wErrCode;
+ void FAR* lpInfo; /* Error code-dependent */
+} NFYLOGERROR;
+
+/* NFY_LOGPARAMERROR: dwData points to a NFYLOGPARAMERROR struct */
+#define NFY_LOGPARAMERROR 13
+typedef struct tagNFYLOGPARAMERROR
+{
+ DWORD dwSize;
+ UINT wErrCode;
+ FARPROC lpfnErrorAddr;
+ void FAR* FAR* lpBadParam;
+} NFYLOGPARAMERROR;
+
+/* NotifyRegister() flags */
+#define NF_NORMAL 0
+#define NF_TASKSWITCH 1
+#define NF_RIP 2
+
+typedef BOOL (CALLBACK* LPFNNOTIFYCALLBACK)(WORD wID, DWORD dwData);
+
+BOOL WINAPI NotifyRegister(HTASK hTask, LPFNNOTIFYCALLBACK lpfn, WORD wFlags);
+BOOL WINAPI NotifyUnRegister(HTASK hTask);
+
+/****** Miscellaneous *********************************************************/
+
+void WINAPI TerminateApp(HTASK hTask, WORD wFlags);
+
+/* TerminateApp() flag values */
+#define UAE_BOX 0
+#define NO_UAE_BOX 1
+
+DWORD WINAPI MemoryRead(WORD wSel, DWORD dwOffset, void FAR* lpBuffer, DWORD dwcb);
+DWORD WINAPI MemoryWrite(WORD wSel, DWORD dwOffset, void FAR* lpBuffer, DWORD dwcb);
+
+typedef struct tagTIMERINFO
+{
+ DWORD dwSize;
+ DWORD dwmsSinceStart;
+ DWORD dwmsThisVM;
+} TIMERINFO;
+
+BOOL WINAPI TimerCount(TIMERINFO FAR* lpTimer);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#ifndef RC_INVOKED
+#pragma pack() /* Revert to default packing */
+#endif
+
+#endif /* !_INC_TOOLHELP */
diff --git a/private/ole32/olethunk/ole16/inc/utils.h b/private/ole32/olethunk/ole16/inc/utils.h
new file mode 100644
index 000000000..653c164ef
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/utils.h
@@ -0,0 +1,182 @@
+#if !defined( _UTILS_H_ )
+#define _UTILS_H_
+
+
+#define STREAMTYPE_CONTROL 0x00000001
+#define STREAMTYPE_CACHE 0x00000002
+#define STREAMTYPE_CONTAINER 0x00000004
+#define STREAMTYPE_OTHER \
+ (!(STREAMTYPE_CONTROL | STREAMTYPE_CACHE | STREAMTYPE_CONTAINER))
+#define STREAMTYPE_ALL 0xFFFFFFFF
+
+
+#define OPCODE_COPY 1
+#define OPCODE_REMOVE 2
+#define OPCODE_MOVE 3
+#define OPCODE_EXCLUDEFROMCOPY 4
+
+#define CONVERT_NOSOURCE 1
+#define CONVERT_NODESTINATION 2
+
+typedef struct tagPLACEABLEMETAHEADER {
+ DWORD key; /* must be 0x9AC6CDD7L */
+ HANDLE hmf; /* must be zero */
+ RECT bbox; /* bounding rectangle of the metafile */
+ WORD inch; /* # of metafile units per inch must be < 1440 */
+ /* most apps use 576 or 1000 */
+ DWORD reserved; /* must be zero */
+ WORD checksum;
+} PLACEABLEMETAHEADER;
+
+
+
+
+#ifdef _MAC
+#define UtMemCpy(lpdst,lpsrc,dwCount) (BlockMove(lpsrc, lpdst, dwCount))
+#else
+#define UtMemCpy(lpdst,lpsrc,dwCount) (hmemcpy(lpdst, lpsrc, dwCount))
+#endif
+
+FARINTERNAL_(BOOL) UtGlobalHandleCpy(HANDLE FAR* lphdst, HANDLE hsrc);
+
+FARINTERNAL_(HANDLE) UtDupGlobal (HANDLE hSrc, UINT uiFlags=GMEM_MOVEABLE);
+
+FARINTERNAL_(BOOL) UtIsFormatSupported (LPDATAOBJECT lpObj, BOOL fGet,
+ BOOL fSet, CLIPFORMAT cfFormat);
+
+FARINTERNAL_(LPSTR) UtDupString(LPCSTR lpszIn);
+
+
+FARINTERNAL_(BOOL) UtCopyFormatEtc(FORMATETC FAR* pFetcIn,
+ FORMATETC FAR* pFetcCopy);
+
+FARINTERNAL_(int) UtCompareFormatEtc(FORMATETC FAR* pFetcLeft,
+ FORMATETC FAR* pFetcRight);
+
+FARINTERNAL_(BOOL) UtCompareTargetDevice(DVTARGETDEVICE FAR* ptdLeft,
+ DVTARGETDEVICE FAR* ptdRight);
+
+FARINTERNAL_(BOOL) UtCopyStatData(STATDATA FAR* pSDIn,
+ STATDATA FAR* pSDCopy);
+
+FARINTERNAL_(void) UtReleaseStatData(STATDATA FAR* pStatData);
+
+
+FARINTERNAL_(HPALETTE) UtDupPalette(HPALETTE hpalette);
+
+FARINTERNAL_(int) UtPaletteSize (int iBitCount);
+
+FARINTERNAL_(DWORD) UtFormatToTymed (CLIPFORMAT cf);
+
+
+FARINTERNAL_(BOOL) UtQueryPictFormat(LPDATAOBJECT lpSrcDataObj,
+ LPFORMATETC lpforetc);
+
+FARINTERNAL_(HBITMAP) UtConvertDibToBitmap(HANDLE hDib);
+
+FARINTERNAL_(HANDLE) UtConvertBitmapToDib(HBITMAP hBitmapm,
+ HPALETTE hpal = NULL);
+
+FARINTERNAL_(void) UtGetClassID(LPUNKNOWN lpUnk, CLSID FAR* lpClsid);
+
+FARINTERNAL_(DVTARGETDEVICE FAR*) UtCopyTargetDevice(DVTARGETDEVICE FAR* ptd);
+
+FARINTERNAL UtGetIconData(LPDATAOBJECT lpSrcDataObj,
+ REFCLSID rclsid, LPFORMATETC lpforetc,
+ LPSTGMEDIUM lpstgmed);
+
+OLEAPI UtDoStreamOperation (LPSTORAGE pstgSrc,
+ LPSTORAGE pstgDst, int iOpCode,
+ DWORD grfAllowedStmTypes);
+
+
+FARINTERNAL_(LPSTR) UtStrRChr (LPCSTR sz, const char ch);
+
+FARINTERNAL_(void) UtGetPresStreamName (LPSTR lpszName, int iStreamNum);
+
+FARINTERNAL_(void) UtRemoveExtraOlePresStreams (LPSTORAGE pstg,
+ int iStart);
+
+
+
+/*** Following routines can be found in convert.cpp *****/
+
+FARINTERNAL UtGetHGLOBALFromStm(LPSTREAM lpstream, DWORD dwSize,
+ HANDLE FAR* lphPres);
+
+FARINTERNAL UtGetHDIBFromDIBFileStm(LPSTREAM pstm,
+ HANDLE FAR* lphdata);
+
+FARINTERNAL_(HANDLE) UtGetHMFPICT(HMETAFILE hMF, BOOL fDeletOnError,
+ DWORD xExt, DWORD yExt);
+
+FARINTERNAL UtGetHMFFromMFStm(LPSTREAM lpstream, DWORD dwSize,
+ BOOL fConvert, HANDLE FAR* lphPres);
+
+FARINTERNAL UtGetSizeAndExtentsFromPlaceableMFStm(LPSTREAM pstm,
+ DWORD FAR* dwSize, LONG FAR* plWidth,
+ LONG FAR* plHeight);
+
+FARINTERNAL UtGetHMFPICTFromPlaceableMFStm(LPSTREAM pstm,
+ HANDLE FAR* lphdata);
+
+FARINTERNAL UtHGLOBALToStm(HANDLE hdata, DWORD dwSize,
+ LPSTREAM pstm);
+
+FARINTERNAL_(void) UtGetDibExtents (LPBITMAPINFOHEADER lpbmi,
+ LONG FAR* plWidth, LONG FAR* plHeight);
+
+FARINTERNAL UtHDIBToDIBFileStm(HANDLE hdata,
+ DWORD dwSize, LPSTREAM pstm);
+
+FARINTERNAL UtDIBStmToDIBFileStm(LPSTREAM pstmDIB,
+ DWORD dwSize, LPSTREAM pstmDIBFile);
+
+FARINTERNAL UtHDIBFileToOlePresStm(HANDLE hdata, LPSTREAM pstm);
+
+FARINTERNAL UtHMFToMFStm(HANDLE FAR* lphMF, DWORD dwSize,
+ LPSTREAM lpstream);
+
+FARINTERNAL UtHMFToPlaceableMFStm(HANDLE FAR* lphMF,
+ DWORD dwSize, LONG lWidth, LONG lHeight,
+ LPSTREAM pstm);
+
+FARINTERNAL UtMFStmToPlaceableMFStm(LPSTREAM pstmMF,
+ DWORD dwSize, LONG lWidth, LONG lHeight,
+ LPSTREAM pstmPMF);
+
+FARINTERNAL UtReadOlePresStmHeader (LPSTREAM pstm,
+ LPFORMATETC pforetc, DWORD FAR* pdwAdvf,
+ BOOL FAR* pfConvert);
+
+FARINTERNAL UtWriteOlePresStmHeader(LPSTREAM lppstream,
+ LPFORMATETC pforetc, DWORD dwAdvf);
+
+FARINTERNAL UtOlePresStmToContentsStm (LPSTORAGE pstg,
+ LPSTR lpszPresStm, BOOL fDeletePresStm,
+ UINT FAR* puiStatus);
+
+/*** Following routines can be found in ..\dde\client\ddecnvrt.cpp *****/
+
+
+FARINTERNAL UtGetHMFPICTFromMSDrawNativeStm (LPSTREAM pstm,
+ DWORD dwSize, HANDLE FAR* lphdata);
+
+FARINTERNAL UtPlaceableMFStmToMSDrawNativeStm (LPSTREAM pstmPMF,
+ LPSTREAM pstmMSDraw);
+
+FARINTERNAL UtDIBFileStmToPBrushNativeStm (LPSTREAM pstmDIBFile,
+ LPSTREAM pstmPBrush);
+
+FARINTERNAL_(HANDLE) UtGetHPRESFromNative (LPSTORAGE pstg,
+ CLIPFORMAT cfFormat, BOOL fOle10Native);
+
+FARINTERNAL UtContentsStmTo10NativeStm (LPSTORAGE pstg,
+ REFCLSID rclsid, BOOL fDeleteContents,
+ UINT FAR* puiStatus);
+
+FARINTERNAL Ut10NativeStmToContentsStm(LPSTORAGE pstg,
+ REFCLSID rclsid, BOOL fDeleteSrcStm);
+
+#endif // _UTILS_H
+
diff --git a/private/ole32/olethunk/ole16/inc/utstream.h b/private/ole32/olethunk/ole16/inc/utstream.h
new file mode 100644
index 000000000..1e4c24e50
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/utstream.h
@@ -0,0 +1,19 @@
+#if !defined( _UTSTREAM_H_ )
+#define _UTSTREAM_H_
+
+/* stream ids used in the call to StGetStream */
+
+FARINTERNAL_(HRESULT) StRead (IStream FAR * lpstream, LPVOID lpBuf, ULONG ulLen);
+#define StWrite(lpstream, lpBuf, ulLen) lpstream->Write(lpBuf, ulLen, NULL)
+FARINTERNAL_(ATOM) StReadAtom (IStream FAR * lpstream);
+FARINTERNAL_(HRESULT) StWriteAtom (IStream FAR * lpstream, ATOM at);
+
+FARINTERNAL StSave10NativeData(IStorage FAR* pstgSave, HANDLE hNative, BOOL fIsOle1Interop);
+FARINTERNAL StRead10NativeData(IStorage FAR* pstgSave, HANDLE FAR *phNative);
+FARINTERNAL StSave10ItemName (IStorage FAR* pstg, LPCSTR szItemName);
+OLEAPI ReadStringStream( LPSTREAM pstm, LPSTR FAR * ppsz);
+OLEAPI WriteStringStream( LPSTREAM pstm, LPCSTR psz);
+
+FARINTERNAL StSetSize(LPSTREAM pstm, DWORD dwSize = 0, BOOL fRelative = TRUE);
+
+#endif // _UTSTREAM_H
diff --git a/private/ole32/olethunk/ole16/inc/valid.h b/private/ole32/olethunk/ole16/inc/valid.h
new file mode 100644
index 000000000..7dd991a76
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/valid.h
@@ -0,0 +1,81 @@
+
+//
+// WARNING: IsValidPtrIn and IsValidPtrOut are defined as macros
+// here. They are also defined as ISVALIDPTRIN and ISVALIDPTROUT
+// in compobj\valid.cxx, which are functions. The functions are
+// used to keep backward compatibility, while the macros are
+// smaller and faster to use.
+//
+
+#define IsValidPtrIn(pv,cb) (!IsBadReadPtr ((pv),(cb)))
+#define IsValidPtrOut(pv,cb) (!IsBadWritePtr((pv),(cb)))
+
+STDAPI_(BOOL) IsValidInterface( void FAR* pv );
+STDAPI_(BOOL) IsValidIid( REFIID riid );
+
+
+#ifdef _DEBUG
+
+//** POINTER IN validation macros:
+#define VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid in ptr", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTRIN( pv, TYPE, retval ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid in ptr", _szAssertFile, __LINE__), retval)
+#define VOID_VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) {\
+ FnAssert(#pv,"Invalid in ptr", _szAssertFile, __LINE__); return; }
+
+//** POINTER OUT validation macros:
+#define VDATEPTROUT( pv, TYPE ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid out ptr", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTROUT( pv, TYPE, retval ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid out ptr", _szAssertFile, __LINE__), retval)
+
+//** INTERFACE validation macro:
+#define GEN_VDATEIFACE( pv, retval ) if (!IsValidInterface(pv)) \
+ return (FnAssert(#pv,"Invalid interface", _szAssertFile, __LINE__), retval)
+#define VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return (FnAssert(#pv,"Invalid interface", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define VOID_VDATEIFACE( pv ) if (!IsValidInterface(pv)) {\
+ FnAssert(#pv,"Invalid interface", _szAssertFile, __LINE__); return; }
+
+//** INTERFACE ID validation macro:
+#define VDATEIID( iid ) if (!IsValidIid( iid )) \
+ return (FnAssert(#iid,"Invalid iid", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEIID( iid, retval ) if (!IsValidIid( iid )) {\
+ FnAssert(#iid,"Invalid iid", _szAssertFile, __LINE__); return retval; }
+#else
+
+
+
+// --assertless macros for non-debug case
+//** POINTER IN validation macros:
+#define VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTRIN( pv, TYPE, retval ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (retval)
+#define VOID_VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) {\
+ return; }
+
+//** POINTER OUT validation macros:
+#define VDATEPTROUT( pv, TYPE ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (ResultFromScode(E_INVALIDARG))
+
+#define GEN_VDATEPTROUT( pv, TYPE, retval ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (retval)
+
+//** INTERFACE validation macro:
+#define VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return (ResultFromScode(E_INVALIDARG))
+#define VOID_VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return;
+#define GEN_VDATEIFACE( pv, retval ) if (!IsValidInterface(pv)) \
+ return (retval)
+
+//** INTERFACE ID validation macro:
+#define VDATEIID( iid ) if (!IsValidIid( iid )) \
+ return (ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEIID( iid, retval ) if (!IsValidIid( iid )) \
+ return retval;
+
+#endif
+
diff --git a/private/ole32/olethunk/ole16/inc/ver.h b/private/ole32/olethunk/ole16/inc/ver.h
new file mode 100644
index 000000000..cc8f0501e
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/ver.h
@@ -0,0 +1,255 @@
+/*****************************************************************************\
+* *
+* ver.h - Version management functions, types, and definitions *
+* *
+* Include file for VER.DLL and VER.LIB. These libraries are *
+* designed to allow version stamping of Windows executable files*
+* and of special .VER files for DOS executable files. *
+* *
+* The API is unchanged for LIB and DLL versions. *
+* *
+* Copyright (c) 1992, Microsoft Corp. All rights reserved *
+* *
+*******************************************************************************
+*
+* #define LIB - To be used with VER.LIB (default is for VER.DLL)
+*
+\*****************************************************************************/
+
+#ifndef _INC_VER
+#define _INC_VER
+
+#ifndef RC_INVOKED
+#pragma pack(1) /* Assume byte packing throughout */
+#endif /* RC_INVOKED */
+
+#ifdef __cplusplus
+extern "C" { /* Assume C declarations for C++ */
+#endif /* __cplusplus */
+
+/*
+ * If .lib version is being used, declare types used in this file.
+ */
+#ifdef LIB
+
+#ifndef WINAPI /* don't declare if they're already declared */
+#define WINAPI _far _pascal
+#define NEAR _near
+#define FAR _far
+#define PASCAL _pascal
+typedef int BOOL;
+#define TRUE 1
+#define FALSE 0
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned int UINT;
+typedef signed long LONG;
+typedef unsigned long DWORD;
+typedef char far* LPSTR;
+typedef const char far* LPCSTR;
+typedef int HFILE;
+#define OFSTRUCT void /* Not used by the .lib version */
+#define LOWORD(l) ((WORD)(l))
+#define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF))
+#define MAKEINTRESOURCE(i) (LPSTR)((DWORD)((WORD)(i)))
+#endif /* WINAPI */
+
+#else /* LIB */
+
+/* If .dll version is being used and we're being included with
+ * the 3.0 windows.h, #define compatible type aliases.
+ * If included with the 3.0 windows.h, #define compatible aliases
+ */
+#ifndef _INC_WINDOWS
+#define UINT WORD
+#define LPCSTR LPSTR
+#define HFILE int
+#endif /* !_INC_WINDOWS */
+
+#endif /* !LIB */
+
+/* ----- RC defines ----- */
+#ifdef RC_INVOKED
+#define ID(id) id
+#else
+#define ID(id) MAKEINTRESOURCE(id)
+#endif
+
+/* ----- Symbols ----- */
+#define VS_FILE_INFO ID(16) /* Version stamp res type */
+#define VS_VERSION_INFO ID(1) /* Version stamp res ID */
+#define VS_USER_DEFINED ID(100) /* User-defined res IDs */
+
+/* ----- VS_VERSION.dwFileFlags ----- */
+#define VS_FFI_SIGNATURE 0xFEEF04BDL
+#define VS_FFI_STRUCVERSION 0x00010000L
+#define VS_FFI_FILEFLAGSMASK 0x0000003FL
+
+/* ----- VS_VERSION.dwFileFlags ----- */
+#define VS_FF_DEBUG 0x00000001L
+#define VS_FF_PRERELEASE 0x00000002L
+#define VS_FF_PATCHED 0x00000004L
+#define VS_FF_PRIVATEBUILD 0x00000008L
+#define VS_FF_INFOINFERRED 0x00000010L
+#define VS_FF_SPECIALBUILD 0x00000020L
+
+/* ----- VS_VERSION.dwFileOS ----- */
+#define VOS_UNKNOWN 0x00000000L
+#define VOS_DOS 0x00010000L
+#define VOS_OS216 0x00020000L
+#define VOS_OS232 0x00030000L
+#define VOS_NT 0x00040000L
+
+#define VOS__BASE 0x00000000L
+#define VOS__WINDOWS16 0x00000001L
+#define VOS__PM16 0x00000002L
+#define VOS__PM32 0x00000003L
+#define VOS__WINDOWS32 0x00000004L
+
+#define VOS_DOS_WINDOWS16 0x00010001L
+#define VOS_DOS_WINDOWS32 0x00010004L
+#define VOS_OS216_PM16 0x00020002L
+#define VOS_OS232_PM32 0x00030003L
+#define VOS_NT_WINDOWS32 0x00040004L
+
+/* ----- VS_VERSION.dwFileType ----- */
+#define VFT_UNKNOWN 0x00000000L
+#define VFT_APP 0x00000001L
+#define VFT_DLL 0x00000002L
+#define VFT_DRV 0x00000003L
+#define VFT_FONT 0x00000004L
+#define VFT_VXD 0x00000005L
+#define VFT_STATIC_LIB 0x00000007L
+
+/* ----- VS_VERSION.dwFileSubtype for VFT_WINDOWS_DRV ----- */
+#define VFT2_UNKNOWN 0x00000000L
+#define VFT2_DRV_PRINTER 0x00000001L
+#define VFT2_DRV_KEYBOARD 0x00000002L
+#define VFT2_DRV_LANGUAGE 0x00000003L
+#define VFT2_DRV_DISPLAY 0x00000004L
+#define VFT2_DRV_MOUSE 0x00000005L
+#define VFT2_DRV_NETWORK 0x00000006L
+#define VFT2_DRV_SYSTEM 0x00000007L
+#define VFT2_DRV_INSTALLABLE 0x00000008L
+#define VFT2_DRV_SOUND 0x00000009L
+#define VFT2_DRV_COMM 0x0000000AL
+
+/* ----- VS_VERSION.dwFileSubtype for VFT_WINDOWS_FONT ----- */
+#define VFT2_FONT_RASTER 0x00000001L
+#define VFT2_FONT_VECTOR 0x00000002L
+#define VFT2_FONT_TRUETYPE 0x00000003L
+
+/* ----- VerFindFile() flags ----- */
+#define VFFF_ISSHAREDFILE 0x0001
+
+#define VFF_CURNEDEST 0x0001
+#define VFF_FILEINUSE 0x0002
+#define VFF_BUFFTOOSMALL 0x0004
+
+/* ----- VerInstallFile() flags ----- */
+#define VIFF_FORCEINSTALL 0x0001
+#define VIFF_DONTDELETEOLD 0x0002
+
+#define VIF_TEMPFILE 0x00000001L
+#define VIF_MISMATCH 0x00000002L
+#define VIF_SRCOLD 0x00000004L
+
+#define VIF_DIFFLANG 0x00000008L
+#define VIF_DIFFCODEPG 0x00000010L
+#define VIF_DIFFTYPE 0x00000020L
+
+#define VIF_WRITEPROT 0x00000040L
+#define VIF_FILEINUSE 0x00000080L
+#define VIF_OUTOFSPACE 0x00000100L
+#define VIF_ACCESSVIOLATION 0x00000200L
+#define VIF_SHARINGVIOLATION 0x00000400L
+#define VIF_CANNOTCREATE 0x00000800L
+#define VIF_CANNOTDELETE 0x00001000L
+#define VIF_CANNOTRENAME 0x00002000L
+#define VIF_CANNOTDELETECUR 0x00004000L
+#define VIF_OUTOFMEMORY 0x00008000L
+
+#define VIF_CANNOTREADSRC 0x00010000L
+#define VIF_CANNOTREADDST 0x00020000L
+
+#define VIF_BUFFTOOSMALL 0x00040000L
+
+#ifndef RC_INVOKED /* RC doesn't need to see the rest of this */
+
+/* ----- Types and structures ----- */
+
+typedef signed short int SHORT;
+
+typedef struct tagVS_FIXEDFILEINFO
+{
+ DWORD dwSignature; /* e.g. 0xfeef04bd */
+ DWORD dwStrucVersion; /* e.g. 0x00000042 = "0.42" */
+ DWORD dwFileVersionMS; /* e.g. 0x00030075 = "3.75" */
+ DWORD dwFileVersionLS; /* e.g. 0x00000031 = "0.31" */
+ DWORD dwProductVersionMS; /* e.g. 0x00030010 = "3.10" */
+ DWORD dwProductVersionLS; /* e.g. 0x00000031 = "0.31" */
+ DWORD dwFileFlagsMask; /* = 0x3F for version "0.42" */
+ DWORD dwFileFlags; /* e.g. VFF_DEBUG | VFF_PRERELEASE */
+ DWORD dwFileOS; /* e.g. VOS_DOS_WINDOWS16 */
+ DWORD dwFileType; /* e.g. VFT_DRIVER */
+ DWORD dwFileSubtype; /* e.g. VFT2_DRV_KEYBOARD */
+ DWORD dwFileDateMS; /* e.g. 0 */
+ DWORD dwFileDateLS; /* e.g. 0 */
+} VS_FIXEDFILEINFO;
+
+/* ----- Function prototypes ----- */
+
+UINT WINAPI VerFindFile(UINT uFlags, LPCSTR szFileName,
+ LPCSTR szWinDir, LPCSTR szAppDir,
+ LPSTR szCurDir, UINT FAR* lpuCurDirLen,
+ LPSTR szDestDir, UINT FAR* lpuDestDirLen);
+
+DWORD WINAPI VerInstallFile(UINT uFlags,
+ LPCSTR szSrcFileName, LPCSTR szDestFileName, LPCSTR szSrcDir,
+ LPCSTR szDestDir, LPCSTR szCurDir, LPSTR szTmpFile, UINT FAR* lpuTmpFileLen);
+
+/* Returns size of version info in bytes */
+DWORD WINAPI GetFileVersionInfoSize(
+ LPCSTR lpstrFilename, /* Filename of version stamped file */
+ DWORD FAR *lpdwHandle); /* Information for use by GetFileVersionInfo */
+
+/* Read version info into buffer */
+BOOL WINAPI GetFileVersionInfo(
+ LPCSTR lpstrFilename, /* Filename of version stamped file */
+ DWORD dwHandle, /* Information from GetFileVersionSize */
+ DWORD dwLen, /* Length of buffer for info */
+ void FAR* lpData); /* Buffer to place the data structure */
+
+/* Returns size of resource in bytes */
+DWORD WINAPI GetFileResourceSize(
+ LPCSTR lpstrFilename, /* Filename of version stamped file */
+ LPCSTR lpstrResType, /* Type: normally VS_FILE_INFO */
+ LPCSTR lpstrResID, /* ID: normally VS_VERSION_INFO */
+ DWORD FAR *lpdwFileOffset); /* Returns file offset of resource */
+
+/* Reads file resource into buffer */
+BOOL WINAPI GetFileResource(
+ LPCSTR lpstrFilename, /* Filename of version stamped file */
+ LPCSTR lpstrResType, /* Type: normally VS_FILE_INFO */
+ LPCSTR lpstrResID, /* ID: normally VS_VERSION_INFO */
+ DWORD dwFileOffset, /* File offset or NULL */
+ DWORD dwResLen, /* Length of resource to read or NULL */
+ void FAR* lpData); /* Pointer to data buffer */
+
+UINT WINAPI VerLanguageName(UINT wLang, LPSTR szLang, UINT nSize);
+
+UINT WINAPI GetWindowsDir(LPCSTR szAppDir, LPSTR lpBuffer, int nSize);
+
+UINT WINAPI GetSystemDir(LPCSTR szAppDir, LPSTR lpBuffer, int nSize);
+
+BOOL WINAPI VerQueryValue(const void FAR* pBlock, LPCSTR lpSubBlock,
+ void FAR* FAR* lplpBuffer, UINT FAR* lpuLen);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#pragma pack()
+
+#endif /* !RC_INVOKED */
+#endif /* !_INC_VER */
diff --git a/private/ole32/olethunk/ole16/inc/verinfo.h b/private/ole32/olethunk/ole16/inc/verinfo.h
new file mode 100644
index 000000000..7ff0f1578
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/verinfo.h
@@ -0,0 +1,23 @@
+
+#ifdef RC_INVOKED
+
+#include <ver.h>
+
+#define VER_FILEVERSION_STR "2.1\0"
+#define VER_FILEVERSION 2,0010,0035,0035
+
+#define VER_PRODUCTNAME_STR "Microsoft OLE 2.1 16/32 Interoperability for Windows NT\0"
+#define VER_COMPANYNAME_STR "Microsoft Corporation\0"
+#define VER_LEGALTRADEMARKS_STR "Microsoft\256 is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation\0"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corp. 1992 - 1994\0"
+#define VER_PRODUCTVERSION_STR "2.1\0"
+#define VER_PRODUCTVERSION 2,0010,0035,0035
+#define VER_COMMENT_STR "Windows NT OLE 16/32 Interoperability DLLs\0"
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE 0
+#define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#define VER_FILEFLAGS 0L
+#define VER_FILEOS VOS_DOS_WINDOWS32
+#define VER_FILEDESCRIPTION_STR "OLE 2.1 16/32 Interoperability Library\0"
+
+#endif /* RC_INVOKED */
diff --git a/private/ole32/olethunk/ole16/inc/windows.h b/private/ole32/olethunk/ole16/inc/windows.h
new file mode 100644
index 000000000..ab1c8ba04
--- /dev/null
+++ b/private/ole32/olethunk/ole16/inc/windows.h
@@ -0,0 +1,5373 @@
+/*****************************************************************************\
+* *
+* windows.h - Windows functions, types, and definitions *
+* *
+* Version 3.10 *
+* *
+* Copyright (c) 1985-1992, Microsoft Corp. All rights reserved. *
+* *
+*******************************************************************************
+*
+* The following symbols control inclusion of various parts of this file:
+*
+* WINVER Windows version number (0x030a). To exclude
+* definitions introduced in version 3.1 (or above)
+* #define WINVER 0x0300 before #including <windows.h>
+*
+* #define: To prevent inclusion of:
+*
+* NOKERNEL KERNEL APIs and definitions
+* NOGDI GDI APIs and definitions
+* NOUSER USER APIs and definitions
+* NOSOUND Sound APIs and definitions
+* NOCOMM Comm driver APIs and definitions
+* NODRIVERS Installable driver APIs and definitions
+*
+* NOMINMAX min() and max() macros
+* NOLOGERROR LogError() and related definitions
+* NOPROFILER Profiler APIs
+* NOMEMMGR Local and global memory management
+* NOLFILEIO _l* file I/O routines
+* NOOPENFILE OpenFile and related definitions
+* NORESOURCE Resource management
+* NOATOM Atom management
+* NOLANGUAGE Character test routines
+* NOLSTRING lstr* string management routines
+* NODBCS Double-byte character set routines
+* NOKEYBOARDINFO Keyboard driver routines
+* NOGDICAPMASKS GDI device capability constants
+* NOCOLOR COLOR_* color values
+* NOGDIOBJ GDI pens, brushes, fonts
+* NODRAWTEXT DrawText() and related definitions
+* NOTEXTMETRIC TEXTMETRIC and related APIs
+* NOSCALABLEFONT Truetype scalable font support
+* NOBITMAP Bitmap support
+* NORASTEROPS GDI Raster operation definitions
+* NOMETAFILE Metafile support
+* NOSYSMETRICS GetSystemMetrics() and related SM_* definitions
+* NOSYSTEMPARAMSINFO SystemParametersInfo() and SPI_* definitions
+* NOMSG APIs and definitions that use MSG structure
+* NOWINSTYLES Window style definitions
+* NOWINOFFSETS Get/SetWindowWord/Long offset definitions
+* NOSHOWWINDOW ShowWindow and related definitions
+* NODEFERWINDOWPOS DeferWindowPos and related definitions
+* NOVIRTUALKEYCODES VK_* virtual key codes
+* NOKEYSTATES MK_* message key state flags
+* NOWH SetWindowsHook and related WH_* definitions
+* NOMENUS Menu APIs
+* NOSCROLL Scrolling APIs and scroll bar control
+* NOCLIPBOARD Clipboard APIs and definitions
+* NOICONS IDI_* icon IDs
+* NOMB MessageBox and related definitions
+* NOSYSCOMMANDS WM_SYSCOMMAND SC_* definitions
+* NOMDI MDI support
+* NOCTLMGR Control management and controls
+* NOWINMESSAGES WM_* window messages
+* NOHELP Help support
+*
+\****************************************************************************/
+
+#ifndef _INC_WINDOWS
+#define _INC_WINDOWS /* #defined if windows.h has been included */
+
+#ifndef RC_INVOKED
+#pragma pack(1) /* Assume byte packing throughout */
+#endif /* RC_INVOKED */
+
+#ifdef __cplusplus
+extern "C" { /* Assume C declarations for C++ */
+#endif /* __cplusplus */
+
+/* If WINVER is not defined, assume version 3.1 */
+#ifndef WINVER
+#define WINVER 0x030a
+#endif
+
+#ifdef RC_INVOKED
+/* Don't include definitions that RC.EXE can't parse */
+#define NOATOM
+#define NOGDI
+#define NOGDICAPMASKS
+#define NOMETAFILE
+#define NOMINMAX
+#define NOMSG
+#define NOOPENFILE
+#define NORASTEROPS
+#define NOSCROLL
+#define NOSOUND
+#define NOSYSMETRICS
+#define NOTEXTMETRIC
+#define NOWH
+#define NODBCS
+#define NOSYSTEMPARAMSINFO
+#define NOCOMM
+#define NOOEMRESOURCE
+#endif /* RC_INVOKED */
+
+/* Handle OEMRESOURCE for 3.0 compatibility */
+#if (WINVER < 0x030a)
+#define NOOEMRESOURCE
+#ifdef OEMRESOURCE
+#undef NOOEMRESOURCE
+#endif
+#endif
+
+/******* Common definitions and typedefs ***********************************/
+
+#define VOID void
+
+#define FAR _far
+#define NEAR _near
+#define PASCAL _pascal
+#define CDECL _cdecl
+
+#define WINAPI _far _pascal
+#define CALLBACK _far _pascal
+
+/****** Simple types & common helper macros *********************************/
+
+typedef int BOOL;
+#define FALSE 0
+#define TRUE 1
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+
+typedef unsigned int UINT;
+
+#ifdef STRICT
+typedef signed long LONG;
+#else
+#define LONG long
+#endif
+
+#define LOBYTE(w) ((BYTE)(w))
+#define HIBYTE(w) ((BYTE)(((UINT)(w) >> 8) & 0xFF))
+
+#define LOWORD(l) ((WORD)(DWORD)(l))
+#define HIWORD(l) ((WORD)((((DWORD)(l)) >> 16) & 0xFFFF))
+
+#define MAKELONG(low, high) ((LONG)(((WORD)(low)) | (((DWORD)((WORD)(high))) << 16)))
+
+#ifndef NOMINMAX
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+#endif /* NOMINMAX */
+
+/* Types use for passing & returning polymorphic values */
+typedef UINT WPARAM;
+typedef LONG LPARAM;
+typedef LONG LRESULT;
+
+#define MAKELPARAM(low, high) ((LPARAM)MAKELONG(low, high))
+#define MAKELRESULT(low, high) ((LRESULT)MAKELONG(low, high))
+
+/****** Common pointer types ************************************************/
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+typedef char NEAR* PSTR;
+typedef char NEAR* NPSTR;
+
+
+typedef char FAR* LPSTR;
+typedef const char FAR* LPCSTR;
+
+typedef BYTE NEAR* PBYTE;
+typedef BYTE FAR* LPBYTE;
+
+typedef int NEAR* PINT;
+typedef int FAR* LPINT;
+
+typedef WORD NEAR* PWORD;
+typedef WORD FAR* LPWORD;
+
+typedef long NEAR* PLONG;
+typedef long FAR* LPLONG;
+
+typedef DWORD NEAR* PDWORD;
+typedef DWORD FAR* LPDWORD;
+
+typedef void FAR* LPVOID;
+
+#define MAKELP(sel, off) ((void FAR*)MAKELONG((off), (sel)))
+#define SELECTOROF(lp) HIWORD(lp)
+#define OFFSETOF(lp) LOWORD(lp)
+
+#define FIELDOFFSET(type, field) ((int)(&((type NEAR*)1)->field)-1)
+
+/****** Common handle types *************************************************/
+
+#ifdef STRICT
+typedef const void NEAR* HANDLE;
+#define DECLARE_HANDLE(name) struct name##__ { int unused; }; \
+ typedef const struct name##__ NEAR* name
+#define DECLARE_HANDLE32(name) struct name##__ { int unused; }; \
+ typedef const struct name##__ FAR* name
+#else /* STRICT */
+typedef UINT HANDLE;
+#define DECLARE_HANDLE(name) typedef UINT name
+#define DECLARE_HANDLE32(name) typedef DWORD name
+#endif /* !STRICT */
+
+typedef HANDLE* PHANDLE;
+typedef HANDLE NEAR* SPHANDLE;
+typedef HANDLE FAR* LPHANDLE;
+
+typedef HANDLE HGLOBAL;
+typedef HANDLE HLOCAL;
+
+typedef HANDLE GLOBALHANDLE;
+typedef HANDLE LOCALHANDLE;
+
+typedef UINT ATOM;
+
+#ifdef STRICT
+typedef void (CALLBACK* FARPROC)(void);
+typedef void (NEAR PASCAL* NEARPROC)(void);
+#else
+typedef int (CALLBACK* FARPROC)();
+typedef int (NEAR PASCAL* NEARPROC)();
+#endif
+
+DECLARE_HANDLE(HSTR);
+
+/****** KERNEL typedefs, structures, and functions **************************/
+
+DECLARE_HANDLE(HINSTANCE);
+typedef HINSTANCE HMODULE; /* HMODULEs can be used in place of HINSTANCEs */
+
+#ifndef NOKERNEL
+
+/****** Application entry point function ************************************/
+
+#ifdef STRICT
+int PASCAL WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
+#endif
+
+/****** System Information **************************************************/
+
+DWORD WINAPI GetVersion(void);
+
+DWORD WINAPI GetFreeSpace(UINT);
+UINT WINAPI GetCurrentPDB(void);
+
+UINT WINAPI GetWindowsDirectory(LPSTR, UINT);
+UINT WINAPI GetSystemDirectory(LPSTR, UINT);
+
+#if (WINVER >= 0x030a)
+UINT WINAPI GetFreeSystemResources(UINT);
+#define GFSR_SYSTEMRESOURCES 0x0000
+#define GFSR_GDIRESOURCES 0x0001
+#define GFSR_USERRESOURCES 0x0002
+#endif /* WINVER >= 0x030a */
+
+DWORD WINAPI GetWinFlags(void);
+
+#define WF_PMODE 0x0001
+#define WF_CPU286 0x0002
+#define WF_CPU386 0x0004
+#define WF_CPU486 0x0008
+#define WF_STANDARD 0x0010
+#define WF_WIN286 0x0010
+#define WF_ENHANCED 0x0020
+#define WF_WIN386 0x0020
+#define WF_CPU086 0x0040
+#define WF_CPU186 0x0080
+#define WF_LARGEFRAME 0x0100
+#define WF_SMALLFRAME 0x0200
+#define WF_80x87 0x0400
+#define WF_PAGING 0x0800
+#define WF_WLO 0x8000
+
+LPSTR WINAPI GetDOSEnvironment(void);
+
+DWORD WINAPI GetCurrentTime(void);
+DWORD WINAPI GetTickCount(void);
+DWORD WINAPI GetTimerResolution(void);
+
+/****** Error handling ******************************************************/
+
+#if (WINVER >= 0x030a)
+#ifndef NOLOGERROR
+
+void WINAPI LogError(UINT err, void FAR* lpInfo);
+void WINAPI LogParamError(UINT err, FARPROC lpfn, void FAR* param);
+
+/****** LogParamError/LogError values */
+
+/* Error modifier bits */
+
+#define ERR_WARNING 0x8000
+#define ERR_PARAM 0x4000
+
+#define ERR_SIZE_MASK 0x3000
+#define ERR_BYTE 0x1000
+#define ERR_WORD 0x2000
+#define ERR_DWORD 0x3000
+
+/****** LogParamError() values */
+
+/* Generic parameter values */
+#define ERR_BAD_VALUE 0x6001
+#define ERR_BAD_FLAGS 0x6002
+#define ERR_BAD_INDEX 0x6003
+#define ERR_BAD_DVALUE 0x7004
+#define ERR_BAD_DFLAGS 0x7005
+#define ERR_BAD_DINDEX 0x7006
+#define ERR_BAD_PTR 0x7007
+#define ERR_BAD_FUNC_PTR 0x7008
+#define ERR_BAD_SELECTOR 0x6009
+#define ERR_BAD_STRING_PTR 0x700a
+#define ERR_BAD_HANDLE 0x600b
+
+/* KERNEL parameter errors */
+#define ERR_BAD_HINSTANCE 0x6020
+#define ERR_BAD_HMODULE 0x6021
+#define ERR_BAD_GLOBAL_HANDLE 0x6022
+#define ERR_BAD_LOCAL_HANDLE 0x6023
+#define ERR_BAD_ATOM 0x6024
+#define ERR_BAD_HFILE 0x6025
+
+/* USER parameter errors */
+#define ERR_BAD_HWND 0x6040
+#define ERR_BAD_HMENU 0x6041
+#define ERR_BAD_HCURSOR 0x6042
+#define ERR_BAD_HICON 0x6043
+#define ERR_BAD_HDWP 0x6044
+#define ERR_BAD_CID 0x6045
+#define ERR_BAD_HDRVR 0x6046
+
+/* GDI parameter errors */
+#define ERR_BAD_COORDS 0x7060
+#define ERR_BAD_GDI_OBJECT 0x6061
+#define ERR_BAD_HDC 0x6062
+#define ERR_BAD_HPEN 0x6063
+#define ERR_BAD_HFONT 0x6064
+#define ERR_BAD_HBRUSH 0x6065
+#define ERR_BAD_HBITMAP 0x6066
+#define ERR_BAD_HRGN 0x6067
+#define ERR_BAD_HPALETTE 0x6068
+#define ERR_BAD_HMETAFILE 0x6069
+
+
+/**** LogError() values */
+
+/* KERNEL errors */
+#define ERR_GALLOC 0x0001
+#define ERR_GREALLOC 0x0002
+#define ERR_GLOCK 0x0003
+#define ERR_LALLOC 0x0004
+#define ERR_LREALLOC 0x0005
+#define ERR_LLOCK 0x0006
+#define ERR_ALLOCRES 0x0007
+#define ERR_LOCKRES 0x0008
+#define ERR_LOADMODULE 0x0009
+
+/* USER errors */
+#define ERR_CREATEDLG 0x0040
+#define ERR_CREATEDLG2 0x0041
+#define ERR_REGISTERCLASS 0x0042
+#define ERR_DCBUSY 0x0043
+#define ERR_CREATEWND 0x0044
+#define ERR_STRUCEXTRA 0x0045
+#define ERR_LOADSTR 0x0046
+#define ERR_LOADMENU 0x0047
+#define ERR_NESTEDBEGINPAINT 0x0048
+#define ERR_BADINDEX 0x0049
+#define ERR_CREATEMENU 0x004a
+
+/* GDI errors */
+#define ERR_CREATEDC 0x0080
+#define ERR_CREATEMETA 0x0081
+#define ERR_DELOBJSELECTED 0x0082
+#define ERR_SELBITMAP 0x0083
+
+/* Debugging support (DEBUG SYSTEM ONLY) */
+typedef struct tagWINDEBUGINFO
+{
+ UINT flags;
+ DWORD dwOptions;
+ DWORD dwFilter;
+ char achAllocModule[8];
+ DWORD dwAllocBreak;
+ DWORD dwAllocCount;
+} WINDEBUGINFO;
+
+BOOL WINAPI GetWinDebugInfo(WINDEBUGINFO FAR* lpwdi, UINT flags);
+BOOL WINAPI SetWinDebugInfo(const WINDEBUGINFO FAR* lpwdi);
+
+void FAR _cdecl DebugOutput(UINT flags, LPCSTR lpsz, ...);
+
+/* WINDEBUGINFO flags values */
+#define WDI_OPTIONS 0x0001
+#define WDI_FILTER 0x0002
+#define WDI_ALLOCBREAK 0x0004
+
+/* dwOptions values */
+#define DBO_CHECKHEAP 0x0001
+#define DBO_BUFFERFILL 0x0004
+#define DBO_DISABLEGPTRAPPING 0x0010
+#define DBO_CHECKFREE 0x0020
+
+#define DBO_SILENT 0x8000
+
+#define DBO_TRACEBREAK 0x2000
+#define DBO_WARNINGBREAK 0x1000
+#define DBO_NOERRORBREAK 0x0800
+#define DBO_NOFATALBREAK 0x0400
+#define DBO_INT3BREAK 0x0100
+
+/* DebugOutput flags values */
+#define DBF_TRACE 0x0000
+#define DBF_WARNING 0x4000
+#define DBF_ERROR 0x8000
+#define DBF_FATAL 0xc000
+
+/* dwFilter values */
+#define DBF_KERNEL 0x1000
+#define DBF_KRN_MEMMAN 0x0001
+#define DBF_KRN_LOADMODULE 0x0002
+#define DBF_KRN_SEGMENTLOAD 0x0004
+#define DBF_USER 0x0800
+#define DBF_GDI 0x0400
+#define DBF_MMSYSTEM 0x0040
+#define DBF_PENWIN 0x0020
+#define DBF_APPLICATION 0x0008
+#define DBF_DRIVER 0x0010
+
+#endif /* NOLOGERROR */
+#endif /* WINVER >= 0x030a */
+
+void WINAPI FatalExit(int);
+void WINAPI FatalAppExit(UINT, LPCSTR);
+
+BOOL WINAPI ExitWindows(DWORD dwReturnCode, UINT wReserved);
+
+#define EW_RESTARTWINDOWS 0x42
+#if (WINVER >= 0x030a)
+#define EW_REBOOTSYSTEM 0x43
+
+BOOL WINAPI ExitWindowsExec(LPCSTR, LPCSTR);
+#endif /* WINVER >= 0x030a */
+
+void WINAPI DebugBreak(void);
+void WINAPI OutputDebugString(LPCSTR);
+
+/* SetErrorMode() constants */
+#define SEM_FAILCRITICALERRORS 0x0001
+#define SEM_NOGPFAULTERRORBOX 0x0002
+#define SEM_NOOPENFILEERRORBOX 0x8000
+
+UINT WINAPI SetErrorMode(UINT);
+
+/****** Pointer validation **************************************************/
+
+#if (WINVER >= 0x030a)
+
+BOOL WINAPI IsBadReadPtr(const void FAR* lp, UINT cb);
+BOOL WINAPI IsBadWritePtr(void FAR* lp, UINT cb);
+BOOL WINAPI IsBadHugeReadPtr(const void _huge* lp, DWORD cb);
+BOOL WINAPI IsBadHugeWritePtr(void _huge* lp, DWORD cb);
+BOOL WINAPI IsBadCodePtr(FARPROC lpfn);
+BOOL WINAPI IsBadStringPtr(const void FAR* lpsz, UINT cchMax);
+#endif /* WINVER >= 0x030a */
+
+/****** Profiling support ***************************************************/
+
+#ifndef NOPROFILER
+
+int WINAPI ProfInsChk(void);
+void WINAPI ProfSetup(int,int);
+void WINAPI ProfSampRate(int,int);
+void WINAPI ProfStart(void);
+void WINAPI ProfStop(void);
+void WINAPI ProfClear(void);
+void WINAPI ProfFlush(void);
+void WINAPI ProfFinish(void);
+#endif /* NOPROFILER */
+
+/****** Catch/Throw and stack management ************************************/
+
+typedef int CATCHBUF[9];
+typedef int FAR* LPCATCHBUF;
+
+int WINAPI Catch(int FAR*);
+void WINAPI Throw(const int FAR*, int);
+
+void WINAPI SwitchStackBack(void);
+void WINAPI SwitchStackTo(UINT, UINT, UINT);
+
+/****** Module Management ***************************************************/
+
+#define HINSTANCE_ERROR ((HINSTANCE)32)
+
+
+HINSTANCE WINAPI LoadModule(LPCSTR, LPVOID);
+BOOL WINAPI FreeModule(HINSTANCE);
+
+HINSTANCE WINAPI LoadLibrary(LPCSTR);
+void WINAPI FreeLibrary(HINSTANCE);
+
+UINT WINAPI WinExec(LPCSTR, UINT);
+
+HMODULE WINAPI GetModuleHandle(LPCSTR);
+
+int WINAPI GetModuleUsage(HINSTANCE);
+int WINAPI GetModuleFileName(HINSTANCE, LPSTR, int);
+
+FARPROC WINAPI GetProcAddress(HINSTANCE, LPCSTR);
+
+int WINAPI GetInstanceData(HINSTANCE, BYTE*, int);
+
+HGLOBAL WINAPI GetCodeHandle(FARPROC);
+
+typedef struct tagSEGINFO
+{
+ UINT offSegment;
+ UINT cbSegment;
+ UINT flags;
+ UINT cbAlloc;
+ HGLOBAL h;
+ UINT alignShift;
+ UINT reserved[2];
+} SEGINFO;
+typedef SEGINFO FAR* LPSEGINFO;
+
+void WINAPI GetCodeInfo(FARPROC lpProc, SEGINFO FAR* lpSegInfo);
+
+FARPROC WINAPI MakeProcInstance(FARPROC, HINSTANCE);
+void WINAPI FreeProcInstance(FARPROC);
+
+LONG WINAPI SetSwapAreaSize(UINT);
+void WINAPI SwapRecording(UINT);
+void WINAPI ValidateCodeSegments(void);
+
+/* Windows Exit Procedure flag values */
+#define WEP_SYSTEM_EXIT 1
+#define WEP_FREE_DLL 0
+
+/****** Task Management *****************************************************/
+
+#endif /* NOKERNEL */
+
+DECLARE_HANDLE(HTASK);
+
+#ifndef NOKERNEL
+
+UINT WINAPI GetNumTasks(void);
+
+#if (WINVER >= 0x030a)
+BOOL WINAPI IsTask(HTASK);
+#endif /* WINVER >= 0x030a */
+
+HTASK WINAPI GetCurrentTask(void);
+
+void WINAPI Yield(void);
+void WINAPI DirectedYield(HTASK);
+
+
+/****** Global memory management ********************************************/
+
+#ifndef NOMEMMGR
+
+/* Global Memory Flags */
+
+#define GMEM_FIXED 0x0000
+#define GMEM_MOVEABLE 0x0002
+#define GMEM_NOCOMPACT 0x0010
+#define GMEM_NODISCARD 0x0020
+#define GMEM_ZEROINIT 0x0040
+#define GMEM_MODIFY 0x0080
+#define GMEM_DISCARDABLE 0x0100
+#define GMEM_NOT_BANKED 0x1000
+#define GMEM_SHARE 0x2000
+#define GMEM_DDESHARE 0x2000
+#define GMEM_NOTIFY 0x4000
+#define GMEM_LOWER GMEM_NOT_BANKED
+
+#define GHND (GMEM_MOVEABLE | GMEM_ZEROINIT)
+#define GPTR (GMEM_FIXED | GMEM_ZEROINIT)
+
+#define GlobalDiscard(h) GlobalReAlloc(h, 0L, GMEM_MOVEABLE)
+
+HGLOBAL WINAPI GlobalAlloc(UINT, DWORD);
+HGLOBAL WINAPI GlobalReAlloc(HGLOBAL, DWORD, UINT);
+HGLOBAL WINAPI GlobalFree(HGLOBAL);
+
+DWORD WINAPI GlobalDosAlloc(DWORD);
+UINT WINAPI GlobalDosFree(UINT);
+
+#ifdef STRICT
+void FAR* WINAPI GlobalLock(HGLOBAL);
+#else
+char FAR* WINAPI GlobalLock(HGLOBAL);
+#endif
+
+BOOL WINAPI GlobalUnlock(HGLOBAL);
+
+DWORD WINAPI GlobalSize(HGLOBAL);
+DWORD WINAPI GlobalHandle(UINT);
+
+/* GlobalFlags return flags (in addition to GMEM_DISCARDABLE) */
+#define GMEM_DISCARDED 0x4000
+#define GMEM_LOCKCOUNT 0x00FF
+UINT WINAPI GlobalFlags(HGLOBAL);
+
+#ifdef STRICT
+void FAR* WINAPI GlobalWire(HGLOBAL);
+#else
+char FAR* WINAPI GlobalWire(HGLOBAL);
+#endif
+
+BOOL WINAPI GlobalUnWire(HGLOBAL);
+
+UINT WINAPI GlobalPageLock(HGLOBAL);
+UINT WINAPI GlobalPageUnlock(HGLOBAL);
+
+void WINAPI GlobalFix(HGLOBAL);
+void WINAPI GlobalUnfix(HGLOBAL);
+
+HGLOBAL WINAPI GlobalLRUNewest(HGLOBAL);
+HGLOBAL WINAPI GlobalLRUOldest(HGLOBAL);
+
+DWORD WINAPI GlobalCompact(DWORD);
+
+#ifdef STRICT
+typedef BOOL (CALLBACK* GNOTIFYPROC)(HGLOBAL);
+#else
+typedef FARPROC GNOTIFYPROC;
+#endif
+
+void WINAPI GlobalNotify(GNOTIFYPROC);
+
+HGLOBAL WINAPI LockSegment(UINT);
+void WINAPI UnlockSegment(UINT);
+
+#define LockData(dummy) LockSegment((UINT)-1)
+#define UnlockData(dummy) UnlockSegment((UINT)-1)
+
+UINT WINAPI AllocSelector(UINT);
+UINT WINAPI FreeSelector(UINT);
+UINT WINAPI AllocDStoCSAlias(UINT);
+UINT WINAPI PrestoChangoSelector(UINT sourceSel, UINT destSel);
+DWORD WINAPI GetSelectorBase(UINT);
+UINT WINAPI SetSelectorBase(UINT, DWORD);
+DWORD WINAPI GetSelectorLimit(UINT);
+UINT WINAPI SetSelectorLimit(UINT, DWORD);
+
+void WINAPI LimitEmsPages(DWORD);
+
+void WINAPI ValidateFreeSpaces(void);
+
+/* Low system memory notification message */
+#define WM_COMPACTING 0x0041
+
+/***** Local Memory Management */
+
+/* Local Memory Flags */
+#define LMEM_FIXED 0x0000
+#define LMEM_MOVEABLE 0x0002
+#define LMEM_NOCOMPACT 0x0010
+#define LMEM_NODISCARD 0x0020
+#define LMEM_ZEROINIT 0x0040
+#define LMEM_MODIFY 0x0080
+#define LMEM_DISCARDABLE 0x0F00
+
+#define LHND (LMEM_MOVEABLE | LMEM_ZEROINIT)
+#define LPTR (LMEM_FIXED | LMEM_ZEROINIT)
+
+#define NONZEROLHND (LMEM_MOVEABLE)
+#define NONZEROLPTR (LMEM_FIXED)
+
+
+#define LocalDiscard(h) LocalReAlloc(h, 0, LMEM_MOVEABLE)
+
+
+HLOCAL WINAPI LocalAlloc(UINT, UINT);
+HLOCAL WINAPI LocalReAlloc(HLOCAL, UINT, UINT);
+HLOCAL WINAPI LocalFree(HLOCAL);
+
+#ifdef STRICT
+void NEAR* WINAPI LocalLock(HLOCAL);
+#else
+char NEAR* WINAPI LocalLock(HLOCAL);
+#endif
+
+BOOL WINAPI LocalUnlock(HLOCAL);
+
+UINT WINAPI LocalSize(HLOCAL);
+#ifdef STRICT
+HLOCAL WINAPI LocalHandle(void NEAR*);
+#else
+HLOCAL WINAPI LocalHandle(UINT);
+#endif
+
+/* LocalFlags return flags (in addition to LMEM_DISCARDABLE) */
+#define LMEM_DISCARDED 0x4000
+#define LMEM_LOCKCOUNT 0x00FF
+
+UINT WINAPI LocalFlags(HLOCAL);
+
+BOOL WINAPI LocalInit(UINT, UINT, UINT);
+UINT WINAPI LocalCompact(UINT);
+UINT WINAPI LocalShrink(HLOCAL, UINT);
+
+#endif /* NOMEMMGR */
+
+/****** File I/O ************************************************************/
+
+#ifndef NOLFILEIO
+
+typedef int HFILE; /* Polymorphic with C runtime file handle type */
+
+#define HFILE_ERROR ((HFILE)-1)
+
+#ifndef NOOPENFILE
+
+/* OpenFile() Structure */
+typedef struct tagOFSTRUCT
+{
+ BYTE cBytes;
+ BYTE fFixedDisk;
+ UINT nErrCode;
+ BYTE reserved[4];
+ char szPathName[128];
+} OFSTRUCT;
+typedef OFSTRUCT* POFSTRUCT;
+typedef OFSTRUCT NEAR* NPOFSTRUCT;
+typedef OFSTRUCT FAR* LPOFSTRUCT;
+
+/* OpenFile() Flags */
+#define OF_READ 0x0000
+#define OF_WRITE 0x0001
+#define OF_READWRITE 0x0002
+#define OF_SHARE_COMPAT 0x0000
+#define OF_SHARE_EXCLUSIVE 0x0010
+#define OF_SHARE_DENY_WRITE 0x0020
+#define OF_SHARE_DENY_READ 0x0030
+#define OF_SHARE_DENY_NONE 0x0040
+#define OF_PARSE 0x0100
+#define OF_DELETE 0x0200
+#define OF_VERIFY 0x0400 /* Used with OF_REOPEN */
+#define OF_SEARCH 0x0400 /* Used without OF_REOPEN */
+#define OF_CANCEL 0x0800
+#define OF_CREATE 0x1000
+#define OF_PROMPT 0x2000
+#define OF_EXIST 0x4000
+#define OF_REOPEN 0x8000
+
+HFILE WINAPI OpenFile(LPCSTR, OFSTRUCT FAR*, UINT);
+
+#endif /* NOOPENFILE */
+
+/* _lopen() flags */
+#define READ 0
+#define WRITE 1
+#define READ_WRITE 2
+
+HFILE WINAPI _lopen(LPCSTR, int);
+HFILE WINAPI _lcreat(LPCSTR, int);
+
+HFILE WINAPI _lclose(HFILE);
+
+LONG WINAPI _llseek(HFILE, LONG, int);
+
+/* _llseek origin values */
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+
+UINT WINAPI _lread(HFILE, void _huge*, UINT);
+UINT WINAPI _lwrite(HFILE, const void _huge*, UINT);
+
+#if (WINVER >= 0x030a)
+long WINAPI _hread(HFILE, void _huge*, long);
+long WINAPI _hwrite(HFILE, const void _huge*, long);
+#endif /* WINVER >= 0x030a */
+
+
+#endif /* NOLFILEIO */
+
+/* GetTempFileName() Flags */
+#define TF_FORCEDRIVE (BYTE)0x80
+
+int WINAPI GetTempFileName(BYTE, LPCSTR, UINT, LPSTR);
+BYTE WINAPI GetTempDrive(char);
+
+/* GetDriveType return values */
+#define DRIVE_REMOVABLE 2
+#define DRIVE_FIXED 3
+#define DRIVE_REMOTE 4
+UINT WINAPI GetDriveType(int);
+
+UINT WINAPI SetHandleCount(UINT);
+
+/****** Network support *****************************************************/
+UINT WINAPI WNetAddConnection(LPSTR, LPSTR, LPSTR);
+UINT WINAPI WNetGetConnection(LPSTR, LPSTR, UINT FAR*);
+UINT WINAPI WNetCancelConnection(LPSTR, BOOL);
+/* Errors */
+#define WN_SUCCESS 0x0000
+#define WN_NOT_SUPPORTED 0x0001
+#define WN_NET_ERROR 0x0002
+#define WN_MORE_DATA 0x0003
+#define WN_BAD_POINTER 0x0004
+#define WN_BAD_VALUE 0x0005
+#define WN_BAD_PASSWORD 0x0006
+#define WN_ACCESS_DENIED 0x0007
+#define WN_FUNCTION_BUSY 0x0008
+#define WN_WINDOWS_ERROR 0x0009
+#define WN_BAD_USER 0x000A
+#define WN_OUT_OF_MEMORY 0x000B
+#define WN_CANCEL 0x000C
+#define WN_CONTINUE 0x000D
+
+/* Connection errors */
+#define WN_NOT_CONNECTED 0x0030
+#define WN_OPEN_FILES 0x0031
+#define WN_BAD_NETNAME 0x0032
+#define WN_BAD_LOCALNAME 0x0033
+#define WN_ALREADY_CONNECTED 0x0034
+#define WN_DEVICE_ERROR 0x0035
+#define WN_CONNECTION_CLOSED 0x0036
+
+/****** Resource Management *************************************************/
+
+DECLARE_HANDLE(HRSRC);
+
+HRSRC WINAPI FindResource(HINSTANCE, LPCSTR, LPCSTR);
+HGLOBAL WINAPI LoadResource(HINSTANCE, HRSRC);
+BOOL WINAPI FreeResource(HGLOBAL);
+
+#ifdef STRICT
+void FAR* WINAPI LockResource(HGLOBAL);
+#else
+char FAR* WINAPI LockResource(HGLOBAL);
+#endif
+
+#define UnlockResource(h) GlobalUnlock(h)
+
+DWORD WINAPI SizeofResource(HINSTANCE, HRSRC);
+
+int WINAPI AccessResource(HINSTANCE, HRSRC);
+
+HGLOBAL WINAPI AllocResource(HINSTANCE, HRSRC, DWORD);
+
+#ifdef STRICT
+typedef HGLOBAL (CALLBACK* RSRCHDLRPROC)(HGLOBAL, HINSTANCE, HRSRC);
+#else
+typedef FARPROC RSRCHDLRPROC;
+#endif
+
+RSRCHDLRPROC WINAPI SetResourceHandler(HINSTANCE, LPCSTR, RSRCHDLRPROC);
+
+#define MAKEINTRESOURCE(i) ((LPCSTR)MAKELP(0, (i)))
+
+#ifndef NORESOURCE
+
+/* Predefined Resource Types */
+#define RT_CURSOR MAKEINTRESOURCE(1)
+#define RT_BITMAP MAKEINTRESOURCE(2)
+#define RT_ICON MAKEINTRESOURCE(3)
+#define RT_MENU MAKEINTRESOURCE(4)
+#define RT_DIALOG MAKEINTRESOURCE(5)
+#define RT_STRING MAKEINTRESOURCE(6)
+#define RT_FONTDIR MAKEINTRESOURCE(7)
+#define RT_FONT MAKEINTRESOURCE(8)
+#define RT_ACCELERATOR MAKEINTRESOURCE(9)
+#define RT_RCDATA MAKEINTRESOURCE(10)
+
+#define RT_GROUP_CURSOR MAKEINTRESOURCE(12)
+#define RT_GROUP_ICON MAKEINTRESOURCE(14)
+
+#endif /* NORESOURCE */
+
+#ifdef OEMRESOURCE
+
+/* OEM Resource Ordinal Numbers */
+#define OBM_CLOSE 32754
+#define OBM_UPARROW 32753
+#define OBM_DNARROW 32752
+#define OBM_RGARROW 32751
+#define OBM_LFARROW 32750
+#define OBM_REDUCE 32749
+#define OBM_ZOOM 32748
+#define OBM_RESTORE 32747
+#define OBM_REDUCED 32746
+#define OBM_ZOOMD 32745
+#define OBM_RESTORED 32744
+#define OBM_UPARROWD 32743
+#define OBM_DNARROWD 32742
+#define OBM_RGARROWD 32741
+#define OBM_LFARROWD 32740
+#define OBM_MNARROW 32739
+#define OBM_COMBO 32738
+#if (WINVER >= 0x030a)
+#define OBM_UPARROWI 32737
+#define OBM_DNARROWI 32736
+#define OBM_RGARROWI 32735
+#define OBM_LFARROWI 32734
+#endif /* WINVER >= 0x030a */
+
+#define OBM_OLD_CLOSE 32767
+#define OBM_SIZE 32766
+#define OBM_OLD_UPARROW 32765
+#define OBM_OLD_DNARROW 32764
+#define OBM_OLD_RGARROW 32763
+#define OBM_OLD_LFARROW 32762
+#define OBM_BTSIZE 32761
+#define OBM_CHECK 32760
+#define OBM_CHECKBOXES 32759
+#define OBM_BTNCORNERS 32758
+#define OBM_OLD_REDUCE 32757
+#define OBM_OLD_ZOOM 32756
+#define OBM_OLD_RESTORE 32755
+
+#define OCR_NORMAL 32512
+#define OCR_IBEAM 32513
+#define OCR_WAIT 32514
+#define OCR_CROSS 32515
+#define OCR_UP 32516
+#define OCR_SIZE 32640
+#define OCR_ICON 32641
+#define OCR_SIZENWSE 32642
+#define OCR_SIZENESW 32643
+#define OCR_SIZEWE 32644
+#define OCR_SIZENS 32645
+#define OCR_SIZEALL 32646
+#define OCR_ICOCUR 32647
+
+#define OIC_SAMPLE 32512
+#define OIC_HAND 32513
+#define OIC_QUES 32514
+#define OIC_BANG 32515
+#define OIC_NOTE 32516
+
+#endif /* OEMRESOURCE */
+
+/****** Atom Management *****************************************************/
+
+#define MAKEINTATOM(i) ((LPCSTR)MAKELP(0, (i)))
+
+#ifndef NOATOM
+
+BOOL WINAPI InitAtomTable(int);
+ATOM WINAPI AddAtom(LPCSTR);
+ATOM WINAPI DeleteAtom(ATOM);
+ATOM WINAPI FindAtom(LPCSTR);
+UINT WINAPI GetAtomName(ATOM, LPSTR, int);
+ATOM WINAPI GlobalAddAtom(LPCSTR);
+ATOM WINAPI GlobalDeleteAtom(ATOM);
+ATOM WINAPI GlobalFindAtom(LPCSTR);
+UINT WINAPI GlobalGetAtomName(ATOM, LPSTR, int);
+HLOCAL WINAPI GetAtomHandle(ATOM);
+
+#endif /* NOATOM */
+
+/****** WIN.INI Support *****************************************************/
+
+/* User Profile Routines */
+UINT WINAPI GetProfileInt(LPCSTR, LPCSTR, int);
+int WINAPI GetProfileString(LPCSTR, LPCSTR, LPCSTR, LPSTR, int);
+BOOL WINAPI WriteProfileString(LPCSTR, LPCSTR, LPCSTR);
+
+UINT WINAPI GetPrivateProfileInt(LPCSTR, LPCSTR, int, LPCSTR);
+int WINAPI GetPrivateProfileString(LPCSTR, LPCSTR, LPCSTR, LPSTR, int, LPCSTR);
+BOOL WINAPI WritePrivateProfileString(LPCSTR, LPCSTR, LPCSTR, LPCSTR);
+
+#define WM_WININICHANGE 0x001A
+
+/****** International & Char Translation Support ****************************/
+
+void WINAPI AnsiToOem(const char _huge*, char _huge*);
+void WINAPI OemToAnsi(const char _huge*, char _huge*);
+
+void WINAPI AnsiToOemBuff(LPCSTR, LPSTR, UINT);
+void WINAPI OemToAnsiBuff(LPCSTR, LPSTR, UINT);
+
+LPSTR WINAPI AnsiNext(LPCSTR);
+LPSTR WINAPI AnsiPrev(LPCSTR, LPCSTR);
+
+LPSTR WINAPI AnsiUpper(LPSTR);
+LPSTR WINAPI AnsiLower(LPSTR);
+
+UINT WINAPI AnsiUpperBuff(LPSTR, UINT);
+UINT WINAPI AnsiLowerBuff(LPSTR, UINT);
+
+
+#ifndef NOLANGUAGE
+BOOL WINAPI IsCharAlpha(char);
+BOOL WINAPI IsCharAlphaNumeric(char);
+BOOL WINAPI IsCharUpper(char);
+BOOL WINAPI IsCharLower(char);
+#endif
+
+#ifndef NOLSTRING
+int WINAPI lstrcmp(LPCSTR, LPCSTR);
+int WINAPI lstrcmpi(LPCSTR, LPCSTR);
+LPSTR WINAPI lstrcpy(LPSTR, LPCSTR);
+LPSTR WINAPI lstrcat(LPSTR, LPCSTR);
+int WINAPI lstrlen(LPCSTR);
+#if (WINVER >= 0x030a)
+LPSTR WINAPI lstrcpyn(LPSTR, LPCSTR, int);
+void WINAPI hmemcpy(void _huge*, const void _huge*, long);
+#endif /* WINVER >= 0x030a */
+#endif /* NOLSTRING */
+
+#if (WINVER >= 0x030a)
+#ifndef NODBCS
+BOOL WINAPI IsDBCSLeadByte(BYTE);
+#endif /* NODBCS */
+#endif /* WINVER >= 0x030a */
+
+int WINAPI LoadString(HINSTANCE, UINT, LPSTR, int);
+
+/****** Keyboard Driver Functions *******************************************/
+
+#ifndef NOKEYBOARDINFO
+
+DWORD WINAPI OemKeyScan(UINT);
+UINT WINAPI VkKeyScan(UINT);
+int WINAPI GetKeyboardType(int);
+UINT WINAPI MapVirtualKey(UINT, UINT);
+int WINAPI GetKBCodePage(void);
+int WINAPI GetKeyNameText(LONG, LPSTR, int);
+int WINAPI ToAscii(UINT wVirtKey, UINT wScanCode, BYTE FAR* lpKeyState, DWORD FAR* lpChar, UINT wFlags);
+
+#endif
+
+#endif /* NOKERNEL */
+
+/****** GDI typedefs, structures, and functions *****************************/
+
+DECLARE_HANDLE(HDC);
+
+#ifndef NOGDI
+
+#ifdef STRICT
+typedef const void NEAR* HGDIOBJ;
+#else
+DECLARE_HANDLE(HGDIOBJ);
+#endif
+
+#endif /* NOGDI */
+
+DECLARE_HANDLE(HBITMAP);
+DECLARE_HANDLE(HPEN);
+DECLARE_HANDLE(HBRUSH);
+DECLARE_HANDLE(HRGN);
+DECLARE_HANDLE(HPALETTE);
+DECLARE_HANDLE(HFONT);
+
+typedef struct tagRECT
+{
+ int left;
+ int top;
+ int right;
+ int bottom;
+} RECT;
+typedef RECT* PRECT;
+typedef RECT NEAR* NPRECT;
+typedef RECT FAR* LPRECT;
+
+typedef struct tagPOINT
+{
+ int x;
+ int y;
+} POINT;
+typedef POINT* PPOINT;
+typedef POINT NEAR* NPPOINT;
+typedef POINT FAR* LPPOINT;
+
+#if (WINVER >= 0x030a)
+typedef struct tagSIZE
+{
+ int cx;
+ int cy;
+} SIZE;
+typedef SIZE* PSIZE;
+typedef SIZE NEAR* NPSIZE;
+typedef SIZE FAR* LPSIZE;
+#endif /* WINVER >= 0x030a */
+
+#define MAKEPOINT(l) (*((POINT FAR*)&(l)))
+
+#ifndef NOGDI
+
+/****** DC Management *******************************************************/
+
+HDC WINAPI CreateDC(LPCSTR, LPCSTR, LPCSTR, const void FAR*);
+HDC WINAPI CreateIC(LPCSTR, LPCSTR, LPCSTR, const void FAR*);
+HDC WINAPI CreateCompatibleDC(HDC);
+
+BOOL WINAPI DeleteDC(HDC);
+
+DWORD WINAPI GetDCOrg(HDC);
+
+int WINAPI SaveDC(HDC);
+BOOL WINAPI RestoreDC(HDC, int);
+
+int WINAPI SetEnvironment(LPCSTR, const void FAR*, UINT);
+int WINAPI GetEnvironment(LPCSTR, void FAR*, UINT);
+
+int WINAPI MulDiv(int, int, int);
+
+#if (WINVER >= 0x030a)
+/* Drawing bounds accumulation APIs */
+UINT WINAPI SetBoundsRect(HDC hDC, const RECT FAR* lprcBounds, UINT flags);
+UINT WINAPI GetBoundsRect(HDC hDC, RECT FAR* lprcBounds, UINT flags);
+
+#define DCB_RESET 0x0001
+#define DCB_ACCUMULATE 0x0002
+#define DCB_DIRTY DCB_ACCUMULATE
+#define DCB_SET (DCB_RESET | DCB_ACCUMULATE)
+#define DCB_ENABLE 0x0004
+#define DCB_DISABLE 0x0008
+#endif /* WINVER >= 0x030a */
+
+/****** Device Capabilities *************************************************/
+
+int WINAPI GetDeviceCaps(HDC, int);
+
+/* Device Parameters for GetDeviceCaps() */
+#define DRIVERVERSION 0
+#define TECHNOLOGY 2
+#define HORZSIZE 4
+#define VERTSIZE 6
+#define HORZRES 8
+#define VERTRES 10
+#define BITSPIXEL 12
+#define PLANES 14
+#define NUMBRUSHES 16
+#define NUMPENS 18
+#define NUMMARKERS 20
+#define NUMFONTS 22
+#define NUMCOLORS 24
+#define PDEVICESIZE 26
+#define CURVECAPS 28
+#define LINECAPS 30
+#define POLYGONALCAPS 32
+#define TEXTCAPS 34
+#define CLIPCAPS 36
+#define RASTERCAPS 38
+#define ASPECTX 40
+#define ASPECTY 42
+#define ASPECTXY 44
+
+#define LOGPIXELSX 88
+#define LOGPIXELSY 90
+
+#define SIZEPALETTE 104
+#define NUMRESERVED 106
+#define COLORRES 108
+
+#ifndef NOGDICAPMASKS
+
+/* GetDeviceCaps() return value masks */
+
+/* TECHNOLOGY */
+#define DT_PLOTTER 0
+#define DT_RASDISPLAY 1
+#define DT_RASPRINTER 2
+#define DT_RASCAMERA 3
+#define DT_CHARSTREAM 4
+#define DT_METAFILE 5
+#define DT_DISPFILE 6
+
+/* CURVECAPS */
+#define CC_NONE 0x0000
+#define CC_CIRCLES 0x0001
+#define CC_PIE 0x0002
+#define CC_CHORD 0x0004
+#define CC_ELLIPSES 0x0008
+#define CC_WIDE 0x0010
+#define CC_STYLED 0x0020
+#define CC_WIDESTYLED 0x0040
+#define CC_INTERIORS 0x0080
+#define CC_ROUNDRECT 0x0100
+
+/* LINECAPS */
+#define LC_NONE 0x0000
+#define LC_POLYLINE 0x0002
+#define LC_MARKER 0x0004
+#define LC_POLYMARKER 0x0008
+#define LC_WIDE 0x0010
+#define LC_STYLED 0x0020
+#define LC_WIDESTYLED 0x0040
+#define LC_INTERIORS 0x0080
+
+/* POLYGONALCAPS */
+#define PC_NONE 0x0000
+#define PC_POLYGON 0x0001
+#define PC_RECTANGLE 0x0002
+#define PC_WINDPOLYGON 0x0004
+#define PC_SCANLINE 0x0008
+#define PC_WIDE 0x0010
+#define PC_STYLED 0x0020
+#define PC_WIDESTYLED 0x0040
+#define PC_INTERIORS 0x0080
+
+/* TEXTCAPS */
+#define TC_OP_CHARACTER 0x0001
+#define TC_OP_STROKE 0x0002
+#define TC_CP_STROKE 0x0004
+#define TC_CR_90 0x0008
+#define TC_CR_ANY 0x0010
+#define TC_SF_X_YINDEP 0x0020
+#define TC_SA_DOUBLE 0x0040
+#define TC_SA_INTEGER 0x0080
+#define TC_SA_CONTIN 0x0100
+#define TC_EA_DOUBLE 0x0200
+#define TC_IA_ABLE 0x0400
+#define TC_UA_ABLE 0x0800
+#define TC_SO_ABLE 0x1000
+#define TC_RA_ABLE 0x2000
+#define TC_VA_ABLE 0x4000
+#define TC_RESERVED 0x8000
+
+/* CLIPCAPS */
+#define CP_NONE 0x0000
+#define CP_RECTANGLE 0x0001
+#define CP_REGION 0x0002
+
+/* RASTERCAPS */
+#define RC_NONE
+#define RC_BITBLT 0x0001
+#define RC_BANDING 0x0002
+#define RC_SCALING 0x0004
+#define RC_BITMAP64 0x0008
+#define RC_GDI20_OUTPUT 0x0010
+#define RC_GDI20_STATE 0x0020
+#define RC_SAVEBITMAP 0x0040
+#define RC_DI_BITMAP 0x0080
+#define RC_PALETTE 0x0100
+#define RC_DIBTODEV 0x0200
+#define RC_BIGFONT 0x0400
+#define RC_STRETCHBLT 0x0800
+#define RC_FLOODFILL 0x1000
+#define RC_STRETCHDIB 0x2000
+#define RC_OP_DX_OUTPUT 0x4000
+#define RC_DEVBITS 0x8000
+
+#endif /* NOGDICAPMASKS */
+
+/****** Coordinate transformation support ***********************************/
+
+int WINAPI SetMapMode(HDC, int);
+int WINAPI GetMapMode(HDC);
+
+/* Map modes */
+#define MM_TEXT 1
+#define MM_LOMETRIC 2
+#define MM_HIMETRIC 3
+#define MM_LOENGLISH 4
+#define MM_HIENGLISH 5
+#define MM_TWIPS 6
+#define MM_ISOTROPIC 7
+#define MM_ANISOTROPIC 8
+
+DWORD WINAPI SetWindowOrg(HDC, int, int);
+DWORD WINAPI GetWindowOrg(HDC);
+
+DWORD WINAPI SetWindowExt(HDC, int, int);
+DWORD WINAPI GetWindowExt(HDC);
+
+DWORD WINAPI OffsetWindowOrg(HDC, int, int);
+DWORD WINAPI ScaleWindowExt(HDC, int, int, int, int);
+
+DWORD WINAPI SetViewportOrg(HDC, int, int);
+DWORD WINAPI GetViewportOrg(HDC);
+
+DWORD WINAPI SetViewportExt(HDC, int, int);
+DWORD WINAPI GetViewportExt(HDC);
+
+DWORD WINAPI OffsetViewportOrg(HDC, int, int);
+DWORD WINAPI ScaleViewportExt(HDC, int, int, int, int);
+
+#if (WINVER >= 0x030a)
+BOOL WINAPI SetWindowOrgEx(HDC, int, int, POINT FAR*);
+BOOL WINAPI GetWindowOrgEx(HDC, POINT FAR*);
+
+BOOL WINAPI SetWindowExtEx(HDC, int, int, SIZE FAR*);
+BOOL WINAPI GetWindowExtEx(HDC, SIZE FAR*);
+
+BOOL WINAPI OffsetWindowOrgEx(HDC, int, int, POINT FAR*);
+BOOL WINAPI ScaleWindowExtEx(HDC, int, int, int, int, SIZE FAR*);
+
+BOOL WINAPI SetViewportExtEx(HDC, int, int, SIZE FAR*);
+BOOL WINAPI GetViewportExtEx(HDC, SIZE FAR*);
+
+BOOL WINAPI SetViewportOrgEx(HDC, int, int, POINT FAR*);
+BOOL WINAPI GetViewportOrgEx(HDC, POINT FAR*);
+
+BOOL WINAPI OffsetViewportOrgEx(HDC, int, int, POINT FAR*);
+BOOL WINAPI ScaleViewportExtEx(HDC, int, int, int, int, SIZE FAR*);
+#endif /* WINVER >= 0x030a */
+
+BOOL WINAPI DPtoLP(HDC, POINT FAR*, int);
+BOOL WINAPI LPtoDP(HDC, POINT FAR*, int);
+
+
+/* Coordinate Modes */
+#define ABSOLUTE 1
+#define RELATIVE 2
+
+/****** Color support *******************************************************/
+
+typedef DWORD COLORREF;
+
+#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)(g)<<8))|(((DWORD)(BYTE)(b))<<16)))
+
+#define GetRValue(rgb) ((BYTE)(rgb))
+#define GetGValue(rgb) ((BYTE)(((WORD)(rgb)) >> 8))
+#define GetBValue(rgb) ((BYTE)((rgb)>>16))
+
+COLORREF WINAPI GetNearestColor(HDC, COLORREF);
+
+#ifndef NOCOLOR
+
+COLORREF WINAPI GetSysColor(int);
+void WINAPI SetSysColors(int, const int FAR*, const COLORREF FAR*);
+
+#define COLOR_SCROLLBAR 0
+#define COLOR_BACKGROUND 1
+#define COLOR_ACTIVECAPTION 2
+#define COLOR_INACTIVECAPTION 3
+#define COLOR_MENU 4
+#define COLOR_WINDOW 5
+#define COLOR_WINDOWFRAME 6
+#define COLOR_MENUTEXT 7
+#define COLOR_WINDOWTEXT 8
+#define COLOR_CAPTIONTEXT 9
+#define COLOR_ACTIVEBORDER 10
+#define COLOR_INACTIVEBORDER 11
+#define COLOR_APPWORKSPACE 12
+#define COLOR_HIGHLIGHT 13
+#define COLOR_HIGHLIGHTTEXT 14
+#define COLOR_BTNFACE 15
+#define COLOR_BTNSHADOW 16
+#define COLOR_GRAYTEXT 17
+#define COLOR_BTNTEXT 18
+#if (WINVER >= 0x030a)
+#define COLOR_INACTIVECAPTIONTEXT 19
+#define COLOR_BTNHIGHLIGHT 20
+#endif /* WINVER >= 0x030a */
+
+#endif /* NOCOLOR */
+
+#define WM_SYSCOLORCHANGE 0x0015
+
+/****** GDI Object Support **************************************************/
+
+#ifndef NOGDIOBJ
+
+HGDIOBJ WINAPI GetStockObject(int);
+
+BOOL WINAPI IsGDIObject(HGDIOBJ);
+
+BOOL WINAPI DeleteObject(HGDIOBJ);
+HGDIOBJ WINAPI SelectObject(HDC, HGDIOBJ);
+int WINAPI GetObject(HGDIOBJ, int, void FAR*);
+BOOL WINAPI UnrealizeObject(HGDIOBJ);
+
+#ifdef STRICT
+typedef (CALLBACK* GOBJENUMPROC)(void FAR*, LPARAM);
+#else
+typedef FARPROC GOBJENUMPROC;
+#endif
+
+#ifdef STRICT
+int WINAPI EnumObjects(HDC, int, GOBJENUMPROC, LPARAM);
+#else
+int WINAPI EnumObjects(HDC, int, GOBJENUMPROC, LPSTR);
+#endif
+
+/* Object types for EnumObjects() */
+#define OBJ_PEN 1
+#define OBJ_BRUSH 2
+
+/****** Pen support *********************************************************/
+
+/* Logical Pen */
+typedef struct tagLOGPEN
+{
+ UINT lopnStyle;
+ POINT lopnWidth;
+ COLORREF lopnColor;
+} LOGPEN;
+typedef LOGPEN* PLOGPEN;
+typedef LOGPEN NEAR* NPLOGPEN;
+typedef LOGPEN FAR* LPLOGPEN;
+
+/* Pen Styles */
+#define PS_SOLID 0
+#define PS_DASH 1
+#define PS_DOT 2
+#define PS_DASHDOT 3
+#define PS_DASHDOTDOT 4
+#define PS_NULL 5
+#define PS_INSIDEFRAME 6
+
+HPEN WINAPI CreatePen(int, int, COLORREF);
+HPEN WINAPI CreatePenIndirect(LOGPEN FAR*);
+
+/* Stock pens for use with GetStockObject(); */
+#define WHITE_PEN 6
+#define BLACK_PEN 7
+#define NULL_PEN 8
+
+/****** Brush support *******************************************************/
+
+/* Brush Styles */
+#define BS_SOLID 0
+#define BS_NULL 1
+#define BS_HOLLOW BS_NULL
+#define BS_HATCHED 2
+#define BS_PATTERN 3
+#define BS_INDEXED 4
+#define BS_DIBPATTERN 5
+
+/* Hatch Styles */
+#define HS_HORIZONTAL 0
+#define HS_VERTICAL 1
+#define HS_FDIAGONAL 2
+#define HS_BDIAGONAL 3
+#define HS_CROSS 4
+#define HS_DIAGCROSS 5
+
+/* Logical Brush (or Pattern) */
+typedef struct tagLOGBRUSH
+{
+ UINT lbStyle;
+ COLORREF lbColor;
+ int lbHatch;
+} LOGBRUSH;
+typedef LOGBRUSH* PLOGBRUSH;
+typedef LOGBRUSH NEAR* NPLOGBRUSH;
+typedef LOGBRUSH FAR* LPLOGBRUSH;
+
+typedef LOGBRUSH PATTERN;
+typedef PATTERN* PPATTERN;
+typedef PATTERN NEAR* NPPATTERN;
+typedef PATTERN FAR* LPPATTERN;
+
+HBRUSH WINAPI CreateSolidBrush(COLORREF);
+HBRUSH WINAPI CreateHatchBrush(int, COLORREF);
+HBRUSH WINAPI CreatePatternBrush(HBITMAP);
+HBRUSH WINAPI CreateDIBPatternBrush(HGLOBAL, UINT);
+HBRUSH WINAPI CreateBrushIndirect(LOGBRUSH FAR*);
+
+/* Stock brushes for use with GetStockObject() */
+#define WHITE_BRUSH 0
+#define LTGRAY_BRUSH 1
+#define GRAY_BRUSH 2
+#define DKGRAY_BRUSH 3
+#define BLACK_BRUSH 4
+#define NULL_BRUSH 5
+#define HOLLOW_BRUSH NULL_BRUSH
+
+DWORD WINAPI SetBrushOrg(HDC, int, int);
+DWORD WINAPI GetBrushOrg(HDC);
+
+#if (WINVER >= 0x030a)
+BOOL WINAPI GetBrushOrgEx(HDC, POINT FAR*);
+#endif /* WINVER >= 0x030a */
+#endif /* NOGDIOBJ */
+
+/****** Region support ******************************************************/
+
+HRGN WINAPI CreateRectRgn(int, int, int, int);
+HRGN WINAPI CreateRectRgnIndirect(const RECT FAR*);
+HRGN WINAPI CreateEllipticRgnIndirect(const RECT FAR*);
+HRGN WINAPI CreateEllipticRgn(int, int, int, int);
+HRGN WINAPI CreatePolygonRgn(const POINT FAR*, int, int);
+HRGN WINAPI CreatePolyPolygonRgn(const POINT FAR*, const int FAR*, int, int);
+HRGN WINAPI CreateRoundRectRgn(int, int, int, int, int, int);
+
+/* Region type flags */
+#define ERROR 0
+#define NULLREGION 1
+#define SIMPLEREGION 2
+#define COMPLEXREGION 3
+
+void WINAPI SetRectRgn(HRGN, int, int, int, int);
+
+int WINAPI CombineRgn(HRGN, HRGN, HRGN, int);
+
+/* CombineRgn() command values */
+#define RGN_AND 1
+#define RGN_OR 2
+#define RGN_XOR 3
+#define RGN_DIFF 4
+#define RGN_COPY 5
+
+BOOL WINAPI EqualRgn(HRGN, HRGN);
+int WINAPI OffsetRgn(HRGN, int, int);
+
+int WINAPI GetRgnBox(HRGN, RECT FAR*);
+
+BOOL WINAPI RectInRegion(HRGN, const RECT FAR*);
+BOOL WINAPI PtInRegion(HRGN, int, int);
+
+/****** Color palette Support ************************************************/
+
+#define PALETTERGB(r,g,b) (0x02000000L | RGB(r,g,b))
+#define PALETTEINDEX(i) ((COLORREF)(0x01000000L | (DWORD)(WORD)(i)))
+
+typedef struct tagPALETTEENTRY
+{
+ BYTE peRed;
+ BYTE peGreen;
+ BYTE peBlue;
+ BYTE peFlags;
+} PALETTEENTRY;
+typedef PALETTEENTRY FAR* LPPALETTEENTRY;
+
+/* Palette entry flags */
+#define PC_RESERVED 0x01 /* palette index used for animation */
+#define PC_EXPLICIT 0x02 /* palette index is explicit to device */
+#define PC_NOCOLLAPSE 0x04 /* do not match color to system palette */
+
+/* Logical Palette */
+typedef struct tagLOGPALETTE
+{
+ WORD palVersion;
+ WORD palNumEntries;
+ PALETTEENTRY palPalEntry[1];
+} LOGPALETTE;
+typedef LOGPALETTE* PLOGPALETTE;
+typedef LOGPALETTE NEAR* NPLOGPALETTE;
+typedef LOGPALETTE FAR* LPLOGPALETTE;
+
+HPALETTE WINAPI CreatePalette(const LOGPALETTE FAR*);
+
+HPALETTE WINAPI SelectPalette(HDC, HPALETTE, BOOL);
+
+UINT WINAPI RealizePalette(HDC);
+
+int WINAPI UpdateColors(HDC);
+void WINAPI AnimatePalette(HPALETTE, UINT, UINT, const PALETTEENTRY FAR*);
+
+UINT WINAPI SetPaletteEntries(HPALETTE, UINT, UINT, const PALETTEENTRY FAR*);
+UINT WINAPI GetPaletteEntries(HPALETTE, UINT, UINT, PALETTEENTRY FAR*);
+
+UINT WINAPI GetNearestPaletteIndex(HPALETTE, COLORREF);
+
+BOOL WINAPI ResizePalette(HPALETTE, UINT);
+
+UINT WINAPI GetSystemPaletteEntries(HDC, UINT, UINT, PALETTEENTRY FAR*);
+
+UINT WINAPI GetSystemPaletteUse(HDC);
+UINT WINAPI SetSystemPaletteUse(HDC, UINT);
+
+/* Get/SetSystemPaletteUse() values */
+#define SYSPAL_STATIC 1
+#define SYSPAL_NOSTATIC 2
+
+/* Palette window messages */
+#define WM_QUERYNEWPALETTE 0x030F
+#define WM_PALETTEISCHANGING 0x0310
+#define WM_PALETTECHANGED 0x0311
+
+/****** Clipping support *****************************************************/
+
+int WINAPI SelectClipRgn(HDC, HRGN);
+int WINAPI GetClipBox(HDC, RECT FAR*);
+
+int WINAPI IntersectClipRect(HDC, int, int, int, int);
+int WINAPI OffsetClipRgn(HDC, int, int);
+int WINAPI ExcludeClipRect(HDC, int, int, int, int);
+
+BOOL WINAPI PtVisible(HDC, int, int);
+BOOL WINAPI RectVisible(HDC, const RECT FAR*);
+
+
+/****** General drawing support ********************************************/
+
+DWORD WINAPI MoveTo(HDC, int, int);
+DWORD WINAPI GetCurrentPosition(HDC);
+
+#if (WINVER >= 0x030a)
+BOOL WINAPI MoveToEx(HDC, int, int, POINT FAR*);
+BOOL WINAPI GetCurrentPositionEx(HDC, POINT FAR*);
+#endif /* WINVER >= 0x030a */
+
+BOOL WINAPI LineTo(HDC, int, int);
+BOOL WINAPI Polyline(HDC, const POINT FAR*, int);
+
+#ifdef STRICT
+typedef void (CALLBACK* LINEDDAPROC)(int, int, LPARAM);
+#else
+typedef FARPROC LINEDDAPROC;
+#endif
+
+void WINAPI LineDDA(int, int, int, int, LINEDDAPROC, LPARAM);
+
+BOOL WINAPI Rectangle(HDC, int, int, int, int);
+BOOL WINAPI RoundRect(HDC, int, int, int, int, int, int);
+
+BOOL WINAPI Ellipse(HDC, int, int, int, int);
+BOOL WINAPI Arc(HDC, int, int, int, int, int, int, int, int);
+BOOL WINAPI Chord(HDC, int, int, int, int, int, int, int, int);
+BOOL WINAPI Pie(HDC, int, int, int, int, int, int, int, int);
+
+BOOL WINAPI Polygon(HDC, const POINT FAR*, int);
+BOOL WINAPI PolyPolygon(HDC, const POINT FAR*, int FAR*, int);
+
+/* PolyFill Modes */
+#define ALTERNATE 1
+#define WINDING 2
+
+int WINAPI SetPolyFillMode(HDC, int);
+int WINAPI GetPolyFillMode(HDC);
+
+BOOL WINAPI FloodFill(HDC, int, int, COLORREF);
+BOOL WINAPI ExtFloodFill(HDC, int, int, COLORREF, UINT);
+
+/* ExtFloodFill style flags */
+#define FLOODFILLBORDER 0
+#define FLOODFILLSURFACE 1
+
+BOOL WINAPI FillRgn(HDC, HRGN, HBRUSH);
+BOOL WINAPI FrameRgn(HDC, HRGN, HBRUSH, int, int);
+BOOL WINAPI InvertRgn(HDC, HRGN);
+BOOL WINAPI PaintRgn(HDC, HRGN);
+
+/* Rectangle output routines */
+int WINAPI FillRect(HDC, const RECT FAR*, HBRUSH);
+int WINAPI FrameRect(HDC, const RECT FAR*, HBRUSH);
+void WINAPI InvertRect(HDC, const RECT FAR*);
+
+void WINAPI DrawFocusRect(HDC, const RECT FAR*);
+
+
+/****** Text support ********************************************************/
+
+BOOL WINAPI TextOut(HDC, int, int, LPCSTR, int);
+LONG WINAPI TabbedTextOut(HDC, int, int, LPCSTR, int, int, int FAR*, int);
+BOOL WINAPI ExtTextOut(HDC, int, int, UINT, const RECT FAR*, LPCSTR, UINT, int FAR*);
+
+#define ETO_GRAYED 0x0001
+#define ETO_OPAQUE 0x0002
+#define ETO_CLIPPED 0x0004
+
+DWORD WINAPI GetTextExtent(HDC, LPCSTR, int);
+DWORD WINAPI GetTabbedTextExtent(HDC, LPCSTR, int, int, int FAR*);
+
+#if (WINVER >= 0x030a)
+BOOL WINAPI GetTextExtentPoint(HDC, LPCSTR, int, SIZE FAR*);
+#endif /* WINVER >= 0x030a */
+
+/* DrawText() Format Flags */
+#ifndef NODRAWTEXT
+#define DT_TOP 0x0000
+#define DT_LEFT 0x0000
+#define DT_CENTER 0x0001
+#define DT_RIGHT 0x0002
+#define DT_VCENTER 0x0004
+#define DT_BOTTOM 0x0008
+#define DT_WORDBREAK 0x0010
+#define DT_SINGLELINE 0x0020
+#define DT_EXPANDTABS 0x0040
+#define DT_TABSTOP 0x0080
+#define DT_NOCLIP 0x0100
+#define DT_EXTERNALLEADING 0x0200
+#define DT_CALCRECT 0x0400
+#define DT_NOPREFIX 0x0800
+#define DT_INTERNAL 0x1000
+
+int WINAPI DrawText(HDC, LPCSTR, int, RECT FAR*, UINT);
+#endif /* NODRAWTEXT */
+
+#ifdef STRICT
+typedef BOOL (CALLBACK* GRAYSTRINGPROC)(HDC, LPARAM, int);
+#else
+typedef FARPROC GRAYSTRINGPROC;
+#endif
+
+BOOL WINAPI GrayString(HDC, HBRUSH, GRAYSTRINGPROC, LPARAM, int, int, int, int, int);
+
+BOOL WINAPI GetCharWidth(HDC, UINT, UINT, int FAR*);
+
+COLORREF WINAPI SetTextColor(HDC, COLORREF);
+COLORREF WINAPI GetTextColor(HDC);
+
+COLORREF WINAPI SetBkColor(HDC, COLORREF);
+COLORREF WINAPI GetBkColor(HDC);
+
+int WINAPI SetBkMode(HDC, int);
+int WINAPI GetBkMode(HDC);
+
+/* Background Modes */
+#define TRANSPARENT 1
+#define OPAQUE 2
+
+UINT WINAPI SetTextAlign(HDC, UINT);
+UINT WINAPI GetTextAlign(HDC);
+
+/* Text Alignment Options */
+#define TA_NOUPDATECP 0x0000
+#define TA_UPDATECP 0x0001
+#define TA_LEFT 0x0000
+#define TA_RIGHT 0x0002
+#define TA_CENTER 0x0006
+#define TA_TOP 0x0000
+#define TA_BOTTOM 0x0008
+#define TA_BASELINE 0x0018
+
+int WINAPI SetTextCharacterExtra(HDC, int);
+int WINAPI GetTextCharacterExtra(HDC);
+
+int WINAPI SetTextJustification(HDC, int, int);
+
+/****** Font support ********************************************************/
+
+#ifndef NOGDIOBJ
+/* Logical Font */
+#define LF_FACESIZE 32
+typedef struct tagLOGFONT
+{
+ int lfHeight;
+ int lfWidth;
+ int lfEscapement;
+ int lfOrientation;
+ int lfWeight;
+ BYTE lfItalic;
+ BYTE lfUnderline;
+ BYTE lfStrikeOut;
+ BYTE lfCharSet;
+ BYTE lfOutPrecision;
+ BYTE lfClipPrecision;
+ BYTE lfQuality;
+ BYTE lfPitchAndFamily;
+ char lfFaceName[LF_FACESIZE];
+} LOGFONT;
+typedef LOGFONT* PLOGFONT;
+typedef LOGFONT NEAR* NPLOGFONT;
+typedef LOGFONT FAR* LPLOGFONT;
+
+/* weight values */
+#define FW_DONTCARE 0
+#define FW_THIN 100
+#define FW_EXTRALIGHT 200
+#define FW_LIGHT 300
+#define FW_NORMAL 400
+#define FW_MEDIUM 500
+#define FW_SEMIBOLD 600
+#define FW_BOLD 700
+#define FW_EXTRABOLD 800
+#define FW_HEAVY 900
+
+#define FW_ULTRALIGHT FW_EXTRALIGHT
+#define FW_REGULAR FW_NORMAL
+#define FW_DEMIBOLD FW_SEMIBOLD
+#define FW_ULTRABOLD FW_EXTRABOLD
+#define FW_BLACK FW_HEAVY
+
+/* CharSet values */
+#define ANSI_CHARSET 0
+#define DEFAULT_CHARSET 1
+#define SYMBOL_CHARSET 2
+#define SHIFTJIS_CHARSET 128
+#define HANGEUL_CHARSET 129
+#define CHINESEBIG5_CHARSET 136
+#define OEM_CHARSET 255
+
+/* OutPrecision values */
+#define OUT_DEFAULT_PRECIS 0
+#define OUT_STRING_PRECIS 1
+#define OUT_CHARACTER_PRECIS 2
+#define OUT_STROKE_PRECIS 3
+#if (WINVER >= 0x030a)
+#define OUT_TT_PRECIS 4
+#define OUT_DEVICE_PRECIS 5
+#define OUT_RASTER_PRECIS 6
+#define OUT_TT_ONLY_PRECIS 7
+#endif /* WINVER >= 0x030a */
+
+/* ClipPrecision values */
+#define CLIP_DEFAULT_PRECIS 0x00
+#define CLIP_CHARACTER_PRECIS 0x01
+#define CLIP_STROKE_PRECIS 0x02
+#define CLIP_MASK 0x0F
+#if (WINVER >= 0x030a)
+#define CLIP_LH_ANGLES 0x10
+#define CLIP_TT_ALWAYS 0x20
+#define CLIP_EMBEDDED 0x80
+#endif /* WINVER >= 0x030a */
+
+/* Quality values */
+#define DEFAULT_QUALITY 0
+#define DRAFT_QUALITY 1
+#define PROOF_QUALITY 2
+
+/* PitchAndFamily pitch values (low 4 bits) */
+#define DEFAULT_PITCH 0x00
+#define FIXED_PITCH 0x01
+#define VARIABLE_PITCH 0x02
+
+/* PitchAndFamily family values (high 4 bits) */
+#define FF_DONTCARE 0x00
+#define FF_ROMAN 0x10
+#define FF_SWISS 0x20
+#define FF_MODERN 0x30
+#define FF_SCRIPT 0x40
+#define FF_DECORATIVE 0x50
+
+HFONT WINAPI CreateFont(int, int, int, int, int, BYTE, BYTE, BYTE, BYTE, BYTE, BYTE, BYTE, BYTE, LPCSTR);
+HFONT WINAPI CreateFontIndirect(const LOGFONT FAR*);
+
+/* Stock fonts for use with GetStockObject() */
+#define OEM_FIXED_FONT 10
+#define ANSI_FIXED_FONT 11
+#define ANSI_VAR_FONT 12
+#define SYSTEM_FONT 13
+#define DEVICE_DEFAULT_FONT 14
+#define DEFAULT_PALETTE 15
+#define SYSTEM_FIXED_FONT 16
+
+
+DWORD WINAPI SetMapperFlags(HDC, DWORD);
+#define ASPECT_FILTERING 0x00000001L
+
+int WINAPI AddFontResource(LPCSTR);
+BOOL WINAPI RemoveFontResource(LPCSTR);
+
+#define WM_FONTCHANGE 0x001D
+
+int WINAPI GetTextFace(HDC, int, LPSTR);
+
+DWORD WINAPI GetAspectRatioFilter(HDC);
+#if (WINVER >= 0x030a)
+BOOL WINAPI GetAspectRatioFilterEx(HDC, SIZE FAR*);
+#endif /* WINVER >= 0x030a */
+
+#endif /* NOGDIOBJ */
+
+#ifndef NOTEXTMETRIC
+
+typedef struct tagTEXTMETRIC
+{
+ int tmHeight;
+ int tmAscent;
+ int tmDescent;
+ int tmInternalLeading;
+ int tmExternalLeading;
+ int tmAveCharWidth;
+ int tmMaxCharWidth;
+ int tmWeight;
+ BYTE tmItalic;
+ BYTE tmUnderlined;
+ BYTE tmStruckOut;
+ BYTE tmFirstChar;
+ BYTE tmLastChar;
+ BYTE tmDefaultChar;
+ BYTE tmBreakChar;
+ BYTE tmPitchAndFamily;
+ BYTE tmCharSet;
+ int tmOverhang;
+ int tmDigitizedAspectX;
+ int tmDigitizedAspectY;
+} TEXTMETRIC;
+typedef TEXTMETRIC* PTEXTMETRIC;
+typedef TEXTMETRIC NEAR* NPTEXTMETRIC;
+typedef TEXTMETRIC FAR* LPTEXTMETRIC;
+
+/* tmPitchAndFamily values */
+#define TMPF_FIXED_PITCH 0x01
+#define TMPF_VECTOR 0x02
+#define TMPF_DEVICE 0x08
+#if (WINVER >= 0x030a)
+#define TMPF_TRUETYPE 0x04
+#endif /* WINVER >= 0x030a */
+
+BOOL WINAPI GetTextMetrics(HDC, TEXTMETRIC FAR*);
+
+#if (WINVER >= 0x030a)
+#ifndef NOSCALABLEFONT
+
+typedef struct tagPANOSE
+{
+ BYTE bFamilyType;
+ BYTE bSerifStyle;
+ BYTE bWeight;
+ BYTE bProportion;
+ BYTE bContrast;
+ BYTE bStrokeVariation;
+ BYTE bArmStyle;
+ BYTE bLetterform;
+ BYTE bMidline;
+ BYTE bXHeight;
+} PANOSE, FAR* LPPANOSE;
+
+typedef struct tagOUTLINETEXTMETRIC
+{
+ UINT otmSize;
+ TEXTMETRIC otmTextMetrics;
+ BYTE otmFiller;
+ PANOSE otmPanoseNumber;
+ UINT otmfsSelection;
+ UINT otmfsType;
+ int otmsCharSlopeRise;
+ int otmsCharSlopeRun;
+ int otmItalicAngle;
+ UINT otmEMSquare;
+ int otmAscent;
+ int otmDescent;
+ UINT otmLineGap;
+ UINT otmsCapEmHeight;
+ UINT otmsXHeight;
+ RECT otmrcFontBox;
+ int otmMacAscent;
+ int otmMacDescent;
+ UINT otmMacLineGap;
+ UINT otmusMinimumPPEM;
+ POINT otmptSubscriptSize;
+ POINT otmptSubscriptOffset;
+ POINT otmptSuperscriptSize;
+ POINT otmptSuperscriptOffset;
+ UINT otmsStrikeoutSize;
+ int otmsStrikeoutPosition;
+ int otmsUnderscorePosition;
+ int otmsUnderscoreSize;
+ PSTR otmpFamilyName;
+ PSTR otmpFaceName;
+ PSTR otmpStyleName;
+ PSTR otmpFullName;
+} OUTLINETEXTMETRIC, FAR* LPOUTLINETEXTMETRIC;
+
+WORD WINAPI GetOutlineTextMetrics(HDC, UINT, OUTLINETEXTMETRIC FAR*);
+
+#endif /* WINVER >= 0x030a */
+#endif /* NOSCALABLEFONT */
+
+#ifndef NOGDIOBJ
+#if (WINVER >= 0x030a)
+
+/* Structure passed to FONTENUMPROC */
+/* NOTE: NEWTEXTMETRIC is the same as TEXTMETRIC plus 4 new fields */
+typedef struct tagNEWTEXTMETRIC
+{
+ int tmHeight;
+ int tmAscent;
+ int tmDescent;
+ int tmInternalLeading;
+ int tmExternalLeading;
+ int tmAveCharWidth;
+ int tmMaxCharWidth;
+ int tmWeight;
+ BYTE tmItalic;
+ BYTE tmUnderlined;
+ BYTE tmStruckOut;
+ BYTE tmFirstChar;
+ BYTE tmLastChar;
+ BYTE tmDefaultChar;
+ BYTE tmBreakChar;
+ BYTE tmPitchAndFamily;
+ BYTE tmCharSet;
+ int tmOverhang;
+ int tmDigitizedAspectX;
+ int tmDigitizedAspectY;
+ DWORD ntmFlags;
+ UINT ntmSizeEM;
+ UINT ntmCellHeight;
+ UINT ntmAvgWidth;
+} NEWTEXTMETRIC;
+typedef NEWTEXTMETRIC* PNEWTEXTMETRIC;
+typedef NEWTEXTMETRIC NEAR* NPNEWTEXTMETRIC;
+typedef NEWTEXTMETRIC FAR* LPNEWTEXTMETRIC;
+
+/* ntmFlags field flags */
+#define NTM_REGULAR 0x00000040L
+#define NTM_BOLD 0x00000020L
+#define NTM_ITALIC 0x00000001L
+
+#define LF_FULLFACESIZE 64
+
+/* Structure passed to FONTENUMPROC */
+typedef struct tagENUMLOGFONT
+{
+ LOGFONT elfLogFont;
+ char elfFullName[LF_FULLFACESIZE];
+ char elfStyle[LF_FACESIZE];
+} ENUMLOGFONT, FAR* LPENUMLOGFONT;
+
+#endif /* WINVER >= 0x030a */
+#endif /* NOGDIOBJ */
+
+#ifdef STRICT
+#ifndef NOGDIOBJ
+
+typedef int (CALLBACK* OLDFONTENUMPROC)(const LOGFONT FAR*, const TEXTMETRIC FAR*, int, LPARAM);
+
+#if (WINVER >= 0x030a)
+typedef int (CALLBACK* FONTENUMPROC)(const ENUMLOGFONT FAR*, const NEWTEXTMETRIC FAR*, int, LPARAM);
+
+int WINAPI EnumFontFamilies(HDC, LPCSTR, FONTENUMPROC, LPARAM);
+
+#else /* WINVER >= 0x030a */
+typedef OLDFONTENUMPROC FONTENUMPROC;
+#endif /* WINVER >= 0x030a) */
+
+int WINAPI EnumFonts(HDC, LPCSTR, OLDFONTENUMPROC, LPARAM);
+#endif /* NOGDIOBJ */
+
+#else /* STRICT */
+
+typedef FARPROC OLDFONTENUMPROC;
+typedef FARPROC FONTENUMPROC;
+
+int WINAPI EnumFonts(HDC, LPCSTR, OLDFONTENUMPROC, LPSTR);
+
+#if (WINVER >= 0x030a)
+int WINAPI EnumFontFamilies(HDC, LPCSTR, FONTENUMPROC, LPSTR);
+#endif /* WINVER >= 0x030a */
+
+#endif /* !STRICT */
+
+/* EnumFonts font type values */
+#define RASTER_FONTTYPE 0x0001
+#define DEVICE_FONTTYPE 0X0002
+#if (WINVER >= 0x030a)
+#define TRUETYPE_FONTTYPE 0x0004
+#endif /* WINVER >= 0x030a */
+
+#endif /* NOTEXTMETRIC */
+
+#ifndef NOSCALABLEFONT
+#if (WINVER >= 0x030a)
+
+DWORD WINAPI GetFontData(HDC, DWORD, DWORD, void FAR*, DWORD);
+BOOL WINAPI CreateScalableFontResource(UINT, LPCSTR, LPCSTR, LPCSTR);
+
+typedef struct tagGLYPHMETRICS
+{
+ UINT gmBlackBoxX;
+ UINT gmBlackBoxY;
+ POINT gmptGlyphOrigin;
+ int gmCellIncX;
+ int gmCellIncY;
+} GLYPHMETRICS, FAR* LPGLYPHMETRICS;
+
+typedef struct tagFIXED
+{
+ UINT fract;
+ int value;
+} FIXED, FAR* LPFIXED;
+
+typedef struct tagMAT2
+{
+ FIXED eM11;
+ FIXED eM12;
+ FIXED eM21;
+ FIXED eM22;
+} MAT2, FAR* LPMAT2;
+
+DWORD WINAPI GetGlyphOutline(HDC, UINT, UINT, GLYPHMETRICS FAR*, DWORD, void FAR*, const MAT2 FAR*);
+
+/* GetGlyphOutline constants */
+#define GGO_METRICS 0
+#define GGO_BITMAP 1
+#define GGO_NATIVE 2
+
+#define TT_POLYGON_TYPE 24
+
+#define TT_PRIM_LINE 1
+#define TT_PRIM_QSPLINE 2
+
+typedef struct tagPOINTFX
+{
+ FIXED x;
+ FIXED y;
+} POINTFX, FAR* LPPOINTFX;
+
+typedef struct tagTTPOLYCURVE
+{
+ UINT wType;
+ UINT cpfx;
+ POINTFX apfx[1];
+} TTPOLYCURVE, FAR* LPTTPOLYCURVE;
+
+typedef struct tagTTPOLYGONHEADER
+{
+ DWORD cb;
+ DWORD dwType;
+ POINTFX pfxStart;
+} TTPOLYGONHEADER, FAR* LPTTPOLYGONHEADER;
+
+typedef struct tagABC
+{
+ int abcA;
+ UINT abcB;
+ int abcC;
+} ABC;
+typedef ABC FAR* LPABC;
+
+BOOL WINAPI GetCharABCWidths(HDC, UINT, UINT, ABC FAR*);
+
+typedef struct tagKERNINGPAIR
+{
+ WORD wFirst;
+ WORD wSecond;
+ int iKernAmount;
+} KERNINGPAIR, FAR* LPKERNINGPAIR;
+
+int WINAPI GetKerningPairs(HDC, int, KERNINGPAIR FAR*);
+
+typedef struct tagRASTERIZER_STATUS
+{
+ int nSize;
+ int wFlags;
+ int nLanguageID;
+} RASTERIZER_STATUS;
+typedef RASTERIZER_STATUS FAR* LPRASTERIZER_STATUS;
+
+/* bits defined in wFlags of RASTERIZER_STATUS */
+#define TT_AVAILABLE 0x0001
+#define TT_ENABLED 0x0002
+
+BOOL WINAPI GetRasterizerCaps(RASTERIZER_STATUS FAR*, int);
+
+#endif /* WINVER >= 0x030a */
+#endif /* NOSCALABLEFONT */
+
+/****** Bitmap support ******************************************************/
+
+#ifndef NOBITMAP
+typedef struct tagBITMAP
+{
+ int bmType;
+ int bmWidth;
+ int bmHeight;
+ int bmWidthBytes;
+ BYTE bmPlanes;
+ BYTE bmBitsPixel;
+ void FAR* bmBits;
+} BITMAP;
+typedef BITMAP* PBITMAP;
+typedef BITMAP NEAR* NPBITMAP;
+typedef BITMAP FAR* LPBITMAP;
+
+/* Bitmap Header structures */
+typedef struct tagRGBTRIPLE
+{
+ BYTE rgbtBlue;
+ BYTE rgbtGreen;
+ BYTE rgbtRed;
+} RGBTRIPLE;
+typedef RGBTRIPLE FAR* LPRGBTRIPLE;
+
+typedef struct tagRGBQUAD
+{
+ BYTE rgbBlue;
+ BYTE rgbGreen;
+ BYTE rgbRed;
+ BYTE rgbReserved;
+} RGBQUAD;
+typedef RGBQUAD FAR* LPRGBQUAD;
+
+/* structures for defining DIBs */
+typedef struct tagBITMAPCOREHEADER
+{
+ DWORD bcSize;
+ short bcWidth;
+ short bcHeight;
+ WORD bcPlanes;
+ WORD bcBitCount;
+} BITMAPCOREHEADER;
+typedef BITMAPCOREHEADER* PBITMAPCOREHEADER;
+typedef BITMAPCOREHEADER FAR* LPBITMAPCOREHEADER;
+
+typedef struct tagBITMAPINFOHEADER
+{
+ DWORD biSize;
+ LONG biWidth;
+ LONG biHeight;
+ WORD biPlanes;
+ WORD biBitCount;
+ DWORD biCompression;
+ DWORD biSizeImage;
+ LONG biXPelsPerMeter;
+ LONG biYPelsPerMeter;
+ DWORD biClrUsed;
+ DWORD biClrImportant;
+} BITMAPINFOHEADER;
+typedef BITMAPINFOHEADER* PBITMAPINFOHEADER;
+typedef BITMAPINFOHEADER FAR* LPBITMAPINFOHEADER;
+
+/* constants for the biCompression field */
+#define BI_RGB 0L
+#define BI_RLE8 1L
+#define BI_RLE4 2L
+
+typedef struct tagBITMAPINFO
+{
+ BITMAPINFOHEADER bmiHeader;
+ RGBQUAD bmiColors[1];
+} BITMAPINFO;
+typedef BITMAPINFO* PBITMAPINFO;
+typedef BITMAPINFO FAR* LPBITMAPINFO;
+
+typedef struct tagBITMAPCOREINFO
+{
+ BITMAPCOREHEADER bmciHeader;
+ RGBTRIPLE bmciColors[1];
+} BITMAPCOREINFO;
+typedef BITMAPCOREINFO* PBITMAPCOREINFO;
+typedef BITMAPCOREINFO FAR* LPBITMAPCOREINFO;
+
+typedef struct tagBITMAPFILEHEADER
+{
+ UINT bfType;
+ DWORD bfSize;
+ UINT bfReserved1;
+ UINT bfReserved2;
+ DWORD bfOffBits;
+} BITMAPFILEHEADER;
+typedef BITMAPFILEHEADER* PBITMAPFILEHEADER;
+typedef BITMAPFILEHEADER FAR* LPBITMAPFILEHEADER;
+
+
+HBITMAP WINAPI CreateBitmap(int, int, UINT, UINT, const void FAR*);
+HBITMAP WINAPI CreateBitmapIndirect(BITMAP FAR* );
+HBITMAP WINAPI CreateCompatibleBitmap(HDC, int, int);
+HBITMAP WINAPI CreateDiscardableBitmap(HDC, int, int);
+HBITMAP WINAPI CreateDIBitmap(HDC, BITMAPINFOHEADER FAR*, DWORD, const void FAR*, BITMAPINFO FAR*, UINT);
+
+HBITMAP WINAPI LoadBitmap(HINSTANCE, LPCSTR);
+
+/* DIB color table identifiers */
+#define DIB_RGB_COLORS 0
+#define DIB_PAL_COLORS 1
+
+/* constants for CreateDIBitmap */
+#define CBM_INIT 0x00000004L
+#endif /* NOBITMAP */
+
+#ifndef NORASTEROPS
+
+/* Binary raster ops */
+#define R2_BLACK 1
+#define R2_NOTMERGEPEN 2
+#define R2_MASKNOTPEN 3
+#define R2_NOTCOPYPEN 4
+#define R2_MASKPENNOT 5
+#define R2_NOT 6
+#define R2_XORPEN 7
+#define R2_NOTMASKPEN 8
+#define R2_MASKPEN 9
+#define R2_NOTXORPEN 10
+#define R2_NOP 11
+#define R2_MERGENOTPEN 12
+#define R2_COPYPEN 13
+#define R2_MERGEPENNOT 14
+#define R2_MERGEPEN 15
+#define R2_WHITE 16
+
+/* Ternary raster operations */
+#define SRCCOPY 0x00CC0020L
+#define SRCPAINT 0x00EE0086L
+#define SRCAND 0x008800C6L
+#define SRCINVERT 0x00660046L
+#define SRCERASE 0x00440328L
+#define NOTSRCCOPY 0x00330008L
+#define NOTSRCERASE 0x001100A6L
+#define MERGECOPY 0x00C000CAL
+#define MERGEPAINT 0x00BB0226L
+#define PATCOPY 0x00F00021L
+#define PATPAINT 0x00FB0A09L
+#define PATINVERT 0x005A0049L
+#define DSTINVERT 0x00550009L
+#define BLACKNESS 0x00000042L
+#define WHITENESS 0x00FF0062L
+
+#endif /* NORASTEROPS */
+
+#ifndef NOBITMAP
+BOOL WINAPI BitBlt(HDC, int, int, int, int, HDC, int, int, DWORD);
+
+BOOL WINAPI PatBlt(HDC, int, int, int, int, DWORD);
+
+BOOL WINAPI StretchBlt(HDC, int, int, int, int, HDC, int, int, int, int, DWORD);
+int WINAPI StretchDIBits(HDC, int, int, int, int, int,
+ int, int, int, const void FAR*, LPBITMAPINFO, UINT, DWORD);
+
+COLORREF WINAPI SetPixel(HDC, int, int, COLORREF);
+COLORREF WINAPI GetPixel(HDC, int, int);
+
+/* StretchBlt() Modes */
+#define BLACKONWHITE 1
+#define WHITEONBLACK 2
+#define COLORONCOLOR 3
+
+/* new StretchBlt() Modes (simpler names) */
+#define STRETCH_ANDSCANS 1
+#define STRETCH_ORSCANS 2
+#define STRETCH_DELETESCANS 3
+
+int WINAPI SetStretchBltMode(HDC, int);
+int WINAPI GetStretchBltMode(HDC);
+
+DWORD WINAPI SetBitmapDimension(HBITMAP, int, int);
+DWORD WINAPI GetBitmapDimension(HBITMAP);
+#if (WINVER >= 0x030a)
+BOOL WINAPI SetBitmapDimensionEx(HBITMAP, int, int, SIZE FAR*);
+BOOL WINAPI GetBitmapDimensionEx(HBITMAP, SIZE FAR*);
+#endif /* WINVER >= 0x030a */
+int WINAPI SetROP2(HDC, int);
+int WINAPI GetROP2(HDC);
+
+LONG WINAPI SetBitmapBits(HBITMAP, DWORD, const void FAR*);
+LONG WINAPI GetBitmapBits(HBITMAP, LONG, void FAR*);
+
+int WINAPI SetDIBits(HDC, HBITMAP, UINT, UINT, const void FAR*, BITMAPINFO FAR*, UINT);
+int WINAPI GetDIBits(HDC, HBITMAP, UINT, UINT, void FAR*, BITMAPINFO FAR*, UINT);
+
+int WINAPI SetDIBitsToDevice(HDC, int, int, int, int, int, int, UINT, UINT,
+ void FAR*, BITMAPINFO FAR*, UINT);
+#endif /* NOBITMAP */
+
+/****** Metafile support ****************************************************/
+
+#ifndef NOMETAFILE
+
+DECLARE_HANDLE(HMETAFILE);
+
+HDC WINAPI CreateMetaFile(LPCSTR);
+HMETAFILE WINAPI CloseMetaFile(HDC);
+
+HMETAFILE WINAPI GetMetaFile(LPCSTR);
+BOOL WINAPI DeleteMetaFile(HMETAFILE);
+HMETAFILE WINAPI CopyMetaFile(HMETAFILE, LPCSTR);
+
+BOOL WINAPI PlayMetaFile(HDC, HMETAFILE);
+
+HGLOBAL WINAPI GetMetaFileBits(HMETAFILE);
+HMETAFILE WINAPI SetMetaFileBits(HGLOBAL);
+#if (WINVER >= 0x030a)
+HMETAFILE WINAPI SetMetaFileBitsBetter(HGLOBAL);
+#endif /* WINVER >= 0x030a */
+
+/* Clipboard Metafile Picture Structure */
+typedef struct tagMETAFILEPICT
+{
+ int mm;
+ int xExt;
+ int yExt;
+ HMETAFILE hMF;
+} METAFILEPICT;
+typedef METAFILEPICT FAR* LPMETAFILEPICT;
+
+typedef struct tagMETAHEADER
+{
+ UINT mtType;
+ UINT mtHeaderSize;
+ UINT mtVersion;
+ DWORD mtSize;
+ UINT mtNoObjects;
+ DWORD mtMaxRecord;
+ UINT mtNoParameters;
+} METAHEADER;
+
+typedef struct tagHANDLETABLE
+{
+ HGDIOBJ objectHandle[1];
+} HANDLETABLE;
+typedef HANDLETABLE* PHANDLETABLE;
+typedef HANDLETABLE FAR* LPHANDLETABLE;
+
+typedef struct tagMETARECORD
+{
+ DWORD rdSize;
+ UINT rdFunction;
+ UINT rdParm[1];
+} METARECORD;
+typedef METARECORD* PMETARECORD;
+typedef METARECORD FAR* LPMETARECORD;
+
+/* Metafile Functions */
+#define META_SETBKCOLOR 0x0201
+#define META_SETBKMODE 0x0102
+#define META_SETMAPMODE 0x0103
+#define META_SETROP2 0x0104
+#define META_SETRELABS 0x0105
+#define META_SETPOLYFILLMODE 0x0106
+#define META_SETSTRETCHBLTMODE 0x0107
+#define META_SETTEXTCHAREXTRA 0x0108
+#define META_SETTEXTCOLOR 0x0209
+#define META_SETTEXTJUSTIFICATION 0x020A
+#define META_SETWINDOWORG 0x020B
+#define META_SETWINDOWEXT 0x020C
+#define META_SETVIEWPORTORG 0x020D
+#define META_SETVIEWPORTEXT 0x020E
+#define META_OFFSETWINDOWORG 0x020F
+#define META_SCALEWINDOWEXT 0x0410
+#define META_OFFSETVIEWPORTORG 0x0211
+#define META_SCALEVIEWPORTEXT 0x0412
+#define META_LINETO 0x0213
+#define META_MOVETO 0x0214
+#define META_EXCLUDECLIPRECT 0x0415
+#define META_INTERSECTCLIPRECT 0x0416
+#define META_ARC 0x0817
+#define META_ELLIPSE 0x0418
+#define META_FLOODFILL 0x0419
+#define META_PIE 0x081A
+#define META_RECTANGLE 0x041B
+#define META_ROUNDRECT 0x061C
+#define META_PATBLT 0x061D
+#define META_SAVEDC 0x001E
+#define META_SETPIXEL 0x041F
+#define META_OFFSETCLIPRGN 0x0220
+#define META_TEXTOUT 0x0521
+#define META_BITBLT 0x0922
+#define META_STRETCHBLT 0x0B23
+#define META_POLYGON 0x0324
+#define META_POLYLINE 0x0325
+#define META_ESCAPE 0x0626
+#define META_RESTOREDC 0x0127
+#define META_FILLREGION 0x0228
+#define META_FRAMEREGION 0x0429
+#define META_INVERTREGION 0x012A
+#define META_PAINTREGION 0x012B
+#define META_SELECTCLIPREGION 0x012C
+#define META_SELECTOBJECT 0x012D
+#define META_SETTEXTALIGN 0x012E
+#define META_DRAWTEXT 0x062F
+
+#define META_CHORD 0x0830
+#define META_SETMAPPERFLAGS 0x0231
+#define META_EXTTEXTOUT 0x0a32
+#define META_SETDIBTODEV 0x0d33
+#define META_SELECTPALETTE 0x0234
+#define META_REALIZEPALETTE 0x0035
+#define META_ANIMATEPALETTE 0x0436
+#define META_SETPALENTRIES 0x0037
+#define META_POLYPOLYGON 0x0538
+#define META_RESIZEPALETTE 0x0139
+
+#define META_DIBBITBLT 0x0940
+#define META_DIBSTRETCHBLT 0x0b41
+#define META_DIBCREATEPATTERNBRUSH 0x0142
+#define META_STRETCHDIB 0x0f43
+
+#define META_EXTFLOODFILL 0x0548
+
+#define META_RESETDC 0x014C
+#define META_STARTDOC 0x014D
+#define META_STARTPAGE 0x004F
+#define META_ENDPAGE 0x0050
+#define META_ABORTDOC 0x0052
+#define META_ENDDOC 0x005E
+
+#define META_DELETEOBJECT 0x01f0
+
+#define META_CREATEPALETTE 0x00f7
+#define META_CREATEBRUSH 0x00F8
+#define META_CREATEPATTERNBRUSH 0x01F9
+#define META_CREATEPENINDIRECT 0x02FA
+#define META_CREATEFONTINDIRECT 0x02FB
+#define META_CREATEBRUSHINDIRECT 0x02FC
+#define META_CREATEBITMAPINDIRECT 0x02FD
+#define META_CREATEBITMAP 0x06FE
+#define META_CREATEREGION 0x06FF
+
+void WINAPI PlayMetaFileRecord(HDC, HANDLETABLE FAR*, METARECORD FAR*, UINT);
+
+#ifdef STRICT
+typedef int (CALLBACK* MFENUMPROC)(HDC, HANDLETABLE FAR*, METARECORD FAR*, int, LPARAM);
+#else
+typedef FARPROC MFENUMPROC;
+#endif
+
+BOOL WINAPI EnumMetaFile(HDC, HMETAFILE, MFENUMPROC, LPARAM);
+
+#endif /* NOMETAFILE */
+
+/****** Printing support ****************************************************/
+
+#ifdef STRICT
+typedef BOOL (CALLBACK* ABORTPROC)(HDC, int);
+#else
+typedef FARPROC ABORTPROC;
+#endif
+
+#if (WINVER >= 0x030a)
+
+typedef struct
+{
+ int cbSize;
+ LPCSTR lpszDocName;
+ LPCSTR lpszOutput;
+} DOCINFO;
+typedef DOCINFO FAR* LPDOCINFO;
+
+int WINAPI StartDoc(HDC, DOCINFO FAR*);
+int WINAPI StartPage(HDC);
+int WINAPI EndPage(HDC);
+int WINAPI EndDoc(HDC);
+int WINAPI AbortDoc(HDC);
+
+int WINAPI SetAbortProc(HDC, ABORTPROC);
+HANDLE WINAPI SpoolFile(LPSTR, LPSTR, LPSTR, LPSTR);
+#endif /* WINVER >= 0x030a */
+
+BOOL WINAPI QueryAbort(HDC, int);
+
+/* Spooler Error Codes */
+#define SP_NOTREPORTED 0x4000
+#define SP_ERROR (-1)
+#define SP_APPABORT (-2)
+#define SP_USERABORT (-3)
+#define SP_OUTOFDISK (-4)
+#define SP_OUTOFMEMORY (-5)
+
+#define PR_JOBSTATUS 0x0000
+
+#endif /* NOGDI */
+
+/* Spooler status notification message */
+#define WM_SPOOLERSTATUS 0x002A
+
+#ifndef NOGDI
+
+/******* GDI Escape support *************************************************/
+
+int WINAPI Escape(HDC, int, int, LPCSTR, void FAR*);
+
+/* GDI Escapes */
+#define NEWFRAME 1
+#define ABORTDOC 2
+#define NEXTBAND 3
+#define SETCOLORTABLE 4
+#define GETCOLORTABLE 5
+#define FLUSHOUTPUT 6
+#define DRAFTMODE 7
+#define QUERYESCSUPPORT 8
+#define SETABORTPROC 9
+#define STARTDOC 10
+#define ENDDOC 11
+#define GETPHYSPAGESIZE 12
+#define GETPRINTINGOFFSET 13
+#define GETSCALINGFACTOR 14
+#define MFCOMMENT 15
+#define GETPENWIDTH 16
+#define SETCOPYCOUNT 17
+#define SELECTPAPERSOURCE 18
+#define DEVICEDATA 19
+#define PASSTHROUGH 19
+#define GETTECHNOLGY 20
+#define GETTECHNOLOGY 20
+#define SETLINECAP 21
+#define SETLINEJOIN 22
+#define SETMITERLIMIT 23
+#define BANDINFO 24
+#define DRAWPATTERNRECT 25
+#define GETVECTORPENSIZE 26
+#define GETVECTORBRUSHSIZE 27
+#define ENABLEDUPLEX 28
+#define GETSETPAPERBINS 29
+#define GETSETPRINTORIENT 30
+#define ENUMPAPERBINS 31
+#define SETDIBSCALING 32
+#define EPSPRINTING 33
+#define ENUMPAPERMETRICS 34
+#define GETSETPAPERMETRICS 35
+#define POSTSCRIPT_DATA 37
+#define POSTSCRIPT_IGNORE 38
+#define MOUSETRAILS 39
+
+#define GETEXTENDEDTEXTMETRICS 256
+#define GETEXTENTTABLE 257
+#define GETPAIRKERNTABLE 258
+#define GETTRACKKERNTABLE 259
+#define EXTTEXTOUT 512
+#define GETFACENAME 513
+#define ENABLERELATIVEWIDTHS 768
+#define ENABLEPAIRKERNING 769
+#define SETKERNTRACK 770
+#define SETALLJUSTVALUES 771
+#define SETCHARSET 772
+
+#define STRETCHBLT 2048
+
+#define GETSETSCREENPARAMS 3072
+
+#define BEGIN_PATH 4096
+#define CLIP_TO_PATH 4097
+#define END_PATH 4098
+#define EXT_DEVICE_CAPS 4099
+#define RESTORE_CTM 4100
+#define SAVE_CTM 4101
+#define SET_ARC_DIRECTION 4102
+#define SET_BACKGROUND_COLOR 4103
+#define SET_POLY_MODE 4104
+#define SET_SCREEN_ANGLE 4105
+#define SET_SPREAD 4106
+#define TRANSFORM_CTM 4107
+#define SET_CLIP_BOX 4108
+#define SET_BOUNDS 4109
+
+#endif /* NOGDI */
+
+/****** USER typedefs, structures, and functions *****************************/
+
+DECLARE_HANDLE(HWND);
+
+#ifndef NOUSER
+
+DECLARE_HANDLE(HMENU);
+
+DECLARE_HANDLE(HICON);
+typedef HICON HCURSOR; /* HICONs & HCURSORs are polymorphic */
+
+/****** System Metrics *******************************************************/
+
+#ifndef NOSYSMETRICS
+
+int WINAPI GetSystemMetrics(int);
+
+/* GetSystemMetrics() codes */
+#define SM_CXSCREEN 0
+#define SM_CYSCREEN 1
+#define SM_CXVSCROLL 2
+#define SM_CYHSCROLL 3
+#define SM_CYCAPTION 4
+#define SM_CXBORDER 5
+#define SM_CYBORDER 6
+#define SM_CXDLGFRAME 7
+#define SM_CYDLGFRAME 8
+#define SM_CYVTHUMB 9
+#define SM_CXHTHUMB 10
+#define SM_CXICON 11
+#define SM_CYICON 12
+#define SM_CXCURSOR 13
+#define SM_CYCURSOR 14
+#define SM_CYMENU 15
+#define SM_CXFULLSCREEN 16
+#define SM_CYFULLSCREEN 17
+#define SM_CYKANJIWINDOW 18
+#define SM_MOUSEPRESENT 19
+#define SM_CYVSCROLL 20
+#define SM_CXHSCROLL 21
+#define SM_DEBUG 22
+#define SM_SWAPBUTTON 23
+#define SM_RESERVED1 24
+#define SM_RESERVED2 25
+#define SM_RESERVED3 26
+#define SM_RESERVED4 27
+#define SM_CXMIN 28
+#define SM_CYMIN 29
+#define SM_CXSIZE 30
+#define SM_CYSIZE 31
+#define SM_CXFRAME 32
+#define SM_CYFRAME 33
+#define SM_CXMINTRACK 34
+#define SM_CYMINTRACK 35
+
+#if (WINVER >= 0x030a)
+#define SM_CXDOUBLECLK 36
+#define SM_CYDOUBLECLK 37
+#define SM_CXICONSPACING 38
+#define SM_CYICONSPACING 39
+#define SM_MENUDROPALIGNMENT 40
+#define SM_PENWINDOWS 41
+#define SM_DBCSENABLED 42
+#endif /* WINVER >= 0x030a */
+
+#define SM_CMETRICS 43
+
+#endif /* NOSYSMETRICS */
+
+UINT WINAPI GetDoubleClickTime(void);
+void WINAPI SetDoubleClickTime(UINT);
+
+#define WM_DEVMODECHANGE 0x001B
+#define WM_TIMECHANGE 0x001E
+
+/****** System Parameters support ********************************************/
+
+#if (WINVER >= 0x030a)
+#ifndef NOSYSTEMPARAMSINFO
+
+BOOL WINAPI SystemParametersInfo(UINT, UINT, VOID FAR*, UINT);
+
+#define SPI_GETBEEP 1
+#define SPI_SETBEEP 2
+#define SPI_GETMOUSE 3
+#define SPI_SETMOUSE 4
+#define SPI_GETBORDER 5
+#define SPI_SETBORDER 6
+#define SPI_GETKEYBOARDSPEED 10
+#define SPI_SETKEYBOARDSPEED 11
+#define SPI_LANGDRIVER 12
+#define SPI_ICONHORIZONTALSPACING 13
+#define SPI_GETSCREENSAVETIMEOUT 14
+#define SPI_SETSCREENSAVETIMEOUT 15
+#define SPI_GETSCREENSAVEACTIVE 16
+#define SPI_SETSCREENSAVEACTIVE 17
+#define SPI_GETGRIDGRANULARITY 18
+#define SPI_SETGRIDGRANULARITY 19
+#define SPI_SETDESKWALLPAPER 20
+#define SPI_SETDESKPATTERN 21
+#define SPI_GETKEYBOARDDELAY 22
+#define SPI_SETKEYBOARDDELAY 23
+#define SPI_ICONVERTICALSPACING 24
+#define SPI_GETICONTITLEWRAP 25
+#define SPI_SETICONTITLEWRAP 26
+#define SPI_GETMENUDROPALIGNMENT 27
+#define SPI_SETMENUDROPALIGNMENT 28
+#define SPI_SETDOUBLECLKWIDTH 29
+#define SPI_SETDOUBLECLKHEIGHT 30
+#define SPI_GETICONTITLELOGFONT 31
+#define SPI_SETDOUBLECLICKTIME 32
+#define SPI_SETMOUSEBUTTONSWAP 33
+#define SPI_SETICONTITLELOGFONT 34
+#define SPI_GETFASTTASKSWITCH 35
+#define SPI_SETFASTTASKSWITCH 36
+
+/* SystemParametersInfo flags */
+#define SPIF_UPDATEINIFILE 0x0001
+#define SPIF_SENDWININICHANGE 0x0002
+
+#endif /* NOSYSTEMPARAMSINFO */
+#endif /* WINVER >= 0x030a */
+
+/****** Rectangle support ****************************************************/
+
+void WINAPI SetRect(RECT FAR*, int, int, int, int);
+void WINAPI SetRectEmpty(RECT FAR*);
+
+void WINAPI CopyRect(RECT FAR*, const RECT FAR*);
+
+BOOL WINAPI IsRectEmpty(const RECT FAR*);
+
+BOOL WINAPI EqualRect(const RECT FAR*, const RECT FAR*);
+
+BOOL WINAPI IntersectRect(RECT FAR*, const RECT FAR*, const RECT FAR*);
+BOOL WINAPI UnionRect(RECT FAR*, const RECT FAR*, const RECT FAR*);
+BOOL WINAPI SubtractRect(RECT FAR*, const RECT FAR*, const RECT FAR*);
+
+void WINAPI OffsetRect(RECT FAR*, int, int);
+void WINAPI InflateRect(RECT FAR*, int, int);
+
+BOOL WINAPI PtInRect(const RECT FAR*, POINT);
+
+/****** Window message support ***********************************************/
+
+UINT WINAPI RegisterWindowMessage(LPCSTR);
+
+#define WM_NULL 0x0000
+
+/* NOTE: All messages below 0x0400 are RESERVED by Windows */
+#define WM_USER 0x0400
+
+#ifndef NOMSG
+
+/* Queued message structure */
+typedef struct tagMSG
+{
+ HWND hwnd;
+ UINT message;
+ WPARAM wParam;
+ LPARAM lParam;
+ DWORD time;
+ POINT pt;
+} MSG;
+typedef MSG* PMSG;
+typedef MSG NEAR* NPMSG;
+typedef MSG FAR* LPMSG;
+
+BOOL WINAPI GetMessage(MSG FAR*, HWND, UINT, UINT);
+BOOL WINAPI PeekMessage(MSG FAR*, HWND, UINT, UINT, UINT);
+
+/* PeekMessage() options */
+#define PM_NOREMOVE 0x0000
+#define PM_REMOVE 0x0001
+#define PM_NOYIELD 0x0002
+
+void WINAPI WaitMessage(void);
+
+DWORD WINAPI GetMessagePos(void);
+LONG WINAPI GetMessageTime(void);
+#if (WINVER >= 0x030a)
+LPARAM WINAPI GetMessageExtraInfo(void);
+#endif /* WINVER >= 0x030a */
+
+BOOL WINAPI TranslateMessage(const MSG FAR*);
+LONG WINAPI DispatchMessage(const MSG FAR*);
+
+BOOL WINAPI SetMessageQueue(int);
+
+BOOL WINAPI GetInputState(void);
+
+#if (WINVER >= 0x030a)
+DWORD WINAPI GetQueueStatus(UINT flags);
+
+/* GetQueueStatus flags */
+#define QS_KEY 0x0001
+#define QS_MOUSEMOVE 0x0002
+#define QS_MOUSEBUTTON 0x0004
+#define QS_MOUSE (QS_MOUSEMOVE | QS_MOUSEBUTTON)
+#define QS_POSTMESSAGE 0x0008
+#define QS_TIMER 0x0010
+#define QS_PAINT 0x0020
+#define QS_SENDMESSAGE 0x0040
+
+#define QS_ALLINPUT 0x007f
+#endif /* WINVER >= 0x030a */
+
+#endif /* NOMSG */
+
+BOOL WINAPI PostMessage(HWND, UINT, WPARAM, LPARAM);
+LRESULT WINAPI SendMessage(HWND, UINT, WPARAM, LPARAM);
+
+#ifndef NOMSG
+
+BOOL WINAPI PostAppMessage(HTASK, UINT, WPARAM, LPARAM);
+
+void WINAPI ReplyMessage(LRESULT);
+BOOL WINAPI InSendMessage(void);
+
+/* Special HWND value for use with PostMessage() and SendMessage() */
+#define HWND_BROADCAST ((HWND)0xffff)
+
+BOOL WINAPI CallMsgFilter(MSG FAR*, int);
+
+#define WH_GETMESSAGE 3
+
+#define WH_CALLWNDPROC 4
+
+#define WH_MSGFILTER (-1)
+#define WH_SYSMSGFILTER 6
+
+/* CallMsgFilter() and WH_SYS/MSGFILTER context codes */
+#define MSGF_DIALOGBOX 0
+#define MSGF_MENU 2
+#define MSGF_MOVE 3
+#define MSGF_SIZE 4
+#define MSGF_SCROLLBAR 5
+#define MSGF_NEXTWINDOW 6
+#define MSGF_MAINLOOP 8
+#define MSGF_USER 4096
+#endif /* NOMSG */
+
+/* Standard window messages */
+/* PenWindows specific messages */
+#define WM_PENWINFIRST 0x0380
+#define WM_PENWINLAST 0x038F
+
+/* Coalescing messages */
+#define WM_COALESCE_FIRST 0x0390
+#define WM_COALESCE_LAST 0x039F
+
+
+#if (WINVER >= 0x030a)
+/****** Power management ****************************************************/
+#define WM_POWER 0x0048
+
+/* wParam for WM_POWER window message and DRV_POWER driver notification */
+#define PWR_OK 1
+#define PWR_FAIL (-1)
+#define PWR_SUSPENDREQUEST 1
+#define PWR_SUSPENDRESUME 2
+#define PWR_CRITICALRESUME 3
+#endif /* WINVER >= 0x030a */
+
+/****** Application termination *********************************************/
+
+#define WM_QUERYENDSESSION 0x0011
+#define WM_ENDSESSION 0x0016
+
+#define WM_QUIT 0x0012
+
+void WINAPI PostQuitMessage(int);
+
+#define WM_SYSTEMERROR 0x0017
+
+/****** Window class management *********************************************/
+
+typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
+
+typedef struct tagWNDCLASS
+{
+ UINT style;
+ WNDPROC lpfnWndProc;
+ int cbClsExtra;
+ int cbWndExtra;
+ HINSTANCE hInstance;
+ HICON hIcon;
+ HCURSOR hCursor;
+ HBRUSH hbrBackground;
+ LPCSTR lpszMenuName;
+ LPCSTR lpszClassName;
+} WNDCLASS;
+typedef WNDCLASS* PWNDCLASS;
+typedef WNDCLASS NEAR* NPWNDCLASS;
+typedef WNDCLASS FAR* LPWNDCLASS;
+
+ATOM WINAPI RegisterClass(const WNDCLASS FAR*);
+BOOL WINAPI UnregisterClass(LPCSTR, HINSTANCE);
+
+BOOL WINAPI GetClassInfo(HINSTANCE, LPCSTR, WNDCLASS FAR*);
+int WINAPI GetClassName(HWND, LPSTR, int);
+
+#ifndef NOWINSTYLES
+
+/* Class styles */
+#define CS_VREDRAW 0x0001
+#define CS_HREDRAW 0x0002
+
+#define CS_OWNDC 0x0020
+#define CS_CLASSDC 0x0040
+#define CS_PARENTDC 0x0080
+
+#define CS_SAVEBITS 0x0800
+
+#define CS_DBLCLKS 0x0008
+
+#define CS_BYTEALIGNCLIENT 0x1000
+#define CS_BYTEALIGNWINDOW 0x2000
+
+#define CS_NOCLOSE 0x0200
+
+#define CS_KEYCVTWINDOW 0x0004
+#define CS_NOKEYCVT 0x0100
+
+#define CS_GLOBALCLASS 0x4000
+#endif /* NOWINSTYLES */
+
+#ifndef NOWINOFFSETS
+
+WORD WINAPI GetClassWord(HWND, int);
+WORD WINAPI SetClassWord(HWND, int, WORD);
+LONG WINAPI GetClassLong(HWND, int);
+LONG WINAPI SetClassLong(HWND, int, LONG);
+
+/* Class field offsets for GetClassLong() and GetClassWord() */
+#define GCL_MENUNAME (-8)
+#define GCW_HBRBACKGROUND (-10)
+#define GCW_HCURSOR (-12)
+#define GCW_HICON (-14)
+#define GCW_HMODULE (-16)
+#define GCW_CBWNDEXTRA (-18)
+#define GCW_CBCLSEXTRA (-20)
+#define GCL_WNDPROC (-24)
+#define GCW_STYLE (-26)
+
+#if (WINVER >= 0x030a)
+#define GCW_ATOM (-32)
+#endif /* WINVER >= 0x030a */
+
+#endif /* NOWINOFFSETS */
+
+/****** Window creation/destroy *********************************************/
+
+/* Window Styles */
+#ifndef NOWINSTYLES
+
+/* Basic window types */
+#define WS_OVERLAPPED 0x00000000L
+#define WS_POPUP 0x80000000L
+#define WS_CHILD 0x40000000L
+
+/* Clipping styles */
+#define WS_CLIPSIBLINGS 0x04000000L
+#define WS_CLIPCHILDREN 0x02000000L
+
+/* Generic window states */
+#define WS_VISIBLE 0x10000000L
+#define WS_DISABLED 0x08000000L
+
+/* Main window states */
+#define WS_MINIMIZE 0x20000000L
+#define WS_MAXIMIZE 0x01000000L
+
+/* Main window styles */
+#define WS_CAPTION 0x00C00000L /* WS_BORDER | WS_DLGFRAME */
+#define WS_BORDER 0x00800000L
+#define WS_DLGFRAME 0x00400000L
+#define WS_VSCROLL 0x00200000L
+#define WS_HSCROLL 0x00100000L
+#define WS_SYSMENU 0x00080000L
+#define WS_THICKFRAME 0x00040000L
+#define WS_MINIMIZEBOX 0x00020000L
+#define WS_MAXIMIZEBOX 0x00010000L
+
+/* Control window styles */
+#define WS_GROUP 0x00020000L
+#define WS_TABSTOP 0x00010000L
+
+/* Common Window Styles */
+#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)
+#define WS_POPUPWINDOW (WS_POPUP | WS_BORDER | WS_SYSMENU)
+#define WS_CHILDWINDOW (WS_CHILD)
+
+/* Extended Window Styles */
+#define WS_EX_DLGMODALFRAME 0x00000001L
+#define WS_EX_NOPARENTNOTIFY 0x00000004L
+
+#if (WINVER >= 0x030a)
+#define WS_EX_TOPMOST 0x00000008L
+#define WS_EX_ACCEPTFILES 0x00000010L
+#define WS_EX_TRANSPARENT 0x00000020L
+#endif /* WINVER >= 0x030a */
+
+/* Obsolete style names */
+#define WS_TILED WS_OVERLAPPED
+#define WS_ICONIC WS_MINIMIZE
+#define WS_SIZEBOX WS_THICKFRAME
+#define WS_TILEDWINDOW WS_OVERLAPPEDWINDOW
+
+
+#endif /* NOWINSTYLES */
+
+/* Special value for CreateWindow, et al. */
+#define HWND_DESKTOP ((HWND)0)
+
+BOOL WINAPI IsWindow(HWND);
+
+HWND WINAPI CreateWindowEx(DWORD, LPCSTR, LPCSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, void FAR*);
+HWND WINAPI CreateWindow(LPCSTR, LPCSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, void FAR*);
+
+#define WM_CREATE 0x0001
+#define WM_NCCREATE 0x0081
+
+/* WM_CREATE/WM_NCCREATE lParam struct */
+typedef struct tagCREATESTRUCT
+{
+ void FAR* lpCreateParams;
+ HINSTANCE hInstance;
+ HMENU hMenu;
+ HWND hwndParent;
+ int cy;
+ int cx;
+ int y;
+ int x;
+ LONG style;
+ LPCSTR lpszName;
+ LPCSTR lpszClass;
+ DWORD dwExStyle;
+} CREATESTRUCT;
+typedef CREATESTRUCT FAR* LPCREATESTRUCT;
+
+BOOL WINAPI DestroyWindow(HWND);
+
+#define WM_DESTROY 0x0002
+#define WM_NCDESTROY 0x0082
+
+/* Basic window attributes */
+
+HTASK WINAPI GetWindowTask(HWND);
+
+BOOL WINAPI IsChild(HWND, HWND);
+
+HWND WINAPI GetParent(HWND);
+HWND WINAPI SetParent(HWND, HWND);
+
+BOOL WINAPI IsWindowVisible(HWND);
+
+BOOL WINAPI ShowWindow(HWND, int);
+
+
+#ifndef NOSHOWWINDOW
+
+#define SW_HIDE 0
+#define SW_SHOWNORMAL 1
+#define SW_NORMAL 1
+#define SW_SHOWMINIMIZED 2
+#define SW_SHOWMAXIMIZED 3
+#define SW_MAXIMIZE 3
+#define SW_SHOWNOACTIVATE 4
+#define SW_SHOW 5
+#define SW_MINIMIZE 6
+#define SW_SHOWMINNOACTIVE 7
+#define SW_SHOWNA 8
+#define SW_RESTORE 9
+
+/* Obsolete ShowWindow() command names */
+#define HIDE_WINDOW 0
+#define SHOW_OPENWINDOW 1
+#define SHOW_ICONWINDOW 2
+#define SHOW_FULLSCREEN 3
+#define SHOW_OPENNOACTIVATE 4
+
+#define WM_SHOWWINDOW 0x0018
+
+/* WM_SHOWWINDOW wParam codes */
+#define SW_PARENTCLOSING 1
+#define SW_OTHERMAXIMIZED 2
+#define SW_PARENTOPENING 3
+#define SW_OTHERRESTORED 4
+
+/* Obsolete constant names */
+#define SW_OTHERZOOM SW_OTHERMAXIMIZED
+#define SW_OTHERUNZOOM SW_OTHERRESTORED
+#endif /* NOSHOWWINDOW */
+
+#define WM_SETREDRAW 0x000B
+
+/* Enabled state */
+BOOL WINAPI EnableWindow(HWND,BOOL);
+BOOL WINAPI IsWindowEnabled(HWND);
+
+#define WM_ENABLE 0x000A
+
+/* Window text */
+void WINAPI SetWindowText(HWND, LPCSTR);
+int WINAPI GetWindowText(HWND, LPSTR, int);
+int WINAPI GetWindowTextLength(HWND);
+
+#define WM_SETTEXT 0x000C
+#define WM_GETTEXT 0x000D
+#define WM_GETTEXTLENGTH 0x000E
+
+/* Window words */
+WORD WINAPI GetWindowWord(HWND, int);
+WORD WINAPI SetWindowWord(HWND, int, WORD);
+LONG WINAPI GetWindowLong(HWND, int);
+LONG WINAPI SetWindowLong(HWND, int, LONG);
+
+/* Window field offsets for GetWindowLong() and GetWindowWord() */
+#ifndef NOWINOFFSETS
+#define GWL_WNDPROC (-4)
+#define GWW_HINSTANCE (-6)
+#define GWW_HWNDPARENT (-8)
+#define GWW_ID (-12)
+#define GWL_STYLE (-16)
+#define GWL_EXSTYLE (-20)
+#endif /* NOWINOFFSETS */
+
+/****** Window size, position, Z-order, and visibility **********************/
+
+#define CW_USEDEFAULT ((int)0x8000)
+
+void WINAPI GetClientRect(HWND, RECT FAR*);
+void WINAPI GetWindowRect(HWND, RECT FAR*);
+
+
+#if (WINVER >= 0x030a)
+typedef struct tagWINDOWPLACEMENT
+{
+ UINT length;
+ UINT flags;
+ UINT showCmd;
+ POINT ptMinPosition;
+ POINT ptMaxPosition;
+ RECT rcNormalPosition;
+} WINDOWPLACEMENT;
+typedef WINDOWPLACEMENT *PWINDOWPLACEMENT;
+typedef WINDOWPLACEMENT FAR* LPWINDOWPLACEMENT;
+
+#define WPF_SETMINPOSITION 0x0001
+#define WPF_RESTORETOMAXIMIZED 0x0002
+
+BOOL WINAPI GetWindowPlacement(HWND, WINDOWPLACEMENT FAR*);
+BOOL WINAPI SetWindowPlacement(HWND, const WINDOWPLACEMENT FAR*);
+#endif /* WINVER >= 0x030a */
+
+BOOL WINAPI SetWindowPos(HWND, HWND, int, int, int, int, UINT);
+
+/* SetWindowPos() and WINDOWPOS flags */
+#define SWP_NOSIZE 0x0001
+#define SWP_NOMOVE 0x0002
+#define SWP_NOZORDER 0x0004
+#define SWP_NOREDRAW 0x0008
+#define SWP_NOACTIVATE 0x0010
+#define SWP_FRAMECHANGED 0x0020 /* The frame changed: send WM_NCCALCSIZE */
+#define SWP_SHOWWINDOW 0x0040
+#define SWP_HIDEWINDOW 0x0080
+#define SWP_NOCOPYBITS 0x0100
+#define SWP_NOOWNERZORDER 0x0200 /* Don't do owner Z ordering */
+
+#define SWP_DRAWFRAME SWP_FRAMECHANGED
+#define SWP_NOREPOSITION SWP_NOOWNERZORDER
+
+#define SWP_NOSENDCHANGING 0x0400
+#define SWP_DEFERERASE 0x2000
+
+/* SetWindowPos() hwndInsertAfter field values */
+#define HWND_TOP ((HWND)0)
+#define HWND_BOTTOM ((HWND)1)
+#define HWND_TOPMOST ((HWND)-1)
+#define HWND_NOTOPMOST ((HWND)-2)
+
+#ifndef NODEFERWINDOWPOS
+
+DECLARE_HANDLE(HDWP);
+
+HDWP WINAPI BeginDeferWindowPos(int);
+HDWP WINAPI DeferWindowPos(HDWP, HWND, HWND, int, int, int, int, UINT);
+BOOL WINAPI EndDeferWindowPos(HDWP);
+
+#endif /* NODEFERWINDOWPOS */
+
+BOOL WINAPI MoveWindow(HWND, int, int, int, int, BOOL);
+BOOL WINAPI BringWindowToTop(HWND);
+
+#if (WINVER >= 0x030a)
+
+#define WM_WINDOWPOSCHANGING 0x0046
+#define WM_WINDOWPOSCHANGED 0x0047
+
+/* WM_WINDOWPOSCHANGING/CHANGED struct pointed to by lParam */
+typedef struct tagWINDOWPOS
+{
+ HWND hwnd;
+ HWND hwndInsertAfter;
+ int x;
+ int y;
+ int cx;
+ int cy;
+ UINT flags;
+} WINDOWPOS;
+typedef WINDOWPOS FAR* LPWINDOWPOS;
+#endif /* WINVER >= 0x030a */
+
+#define WM_MOVE 0x0003
+#define WM_SIZE 0x0005
+
+/* WM_SIZE message wParam values */
+#define SIZE_RESTORED 0
+#define SIZE_MINIMIZED 1
+#define SIZE_MAXIMIZED 2
+#define SIZE_MAXSHOW 3
+#define SIZE_MAXHIDE 4
+
+/* Obsolete constant names */
+#define SIZENORMAL SIZE_RESTORED
+#define SIZEICONIC SIZE_MINIMIZED
+#define SIZEFULLSCREEN SIZE_MAXIMIZED
+#define SIZEZOOMSHOW SIZE_MAXSHOW
+#define SIZEZOOMHIDE SIZE_MAXHIDE
+
+/****** Window proc implementation & subclassing support *********************/
+
+LRESULT WINAPI DefWindowProc(HWND, UINT, WPARAM, LPARAM);
+
+#ifdef STRICT
+LRESULT WINAPI CallWindowProc(WNDPROC, HWND, UINT, WPARAM, LPARAM);
+#else
+LRESULT WINAPI CallWindowProc(FARPROC, HWND, UINT, WPARAM, LPARAM);
+#endif
+
+/****** Main window support **************************************************/
+
+void WINAPI AdjustWindowRect(RECT FAR*, DWORD, BOOL);
+void WINAPI AdjustWindowRectEx(RECT FAR*, DWORD, BOOL, DWORD);
+
+#define WM_QUERYOPEN 0x0013
+#define WM_CLOSE 0x0010
+
+/* Struct pointed to by WM_GETMINMAXINFO lParam */
+typedef struct tagMINMAXINFO
+{
+ POINT ptReserved;
+ POINT ptMaxSize;
+ POINT ptMaxPosition;
+ POINT ptMinTrackSize;
+ POINT ptMaxTrackSize;
+} MINMAXINFO;
+#define WM_GETMINMAXINFO 0x0024
+
+
+BOOL WINAPI FlashWindow(HWND, BOOL);
+
+void WINAPI ShowOwnedPopups(HWND, BOOL);
+
+/* Obsolete functions */
+BOOL WINAPI OpenIcon(HWND);
+void WINAPI CloseWindow(HWND);
+BOOL WINAPI AnyPopup(void);
+BOOL WINAPI IsIconic(HWND);
+BOOL WINAPI IsZoomed(HWND);
+
+/****** Window coordinate mapping and hit-testing ***************************/
+
+void WINAPI ClientToScreen(HWND, POINT FAR*);
+void WINAPI ScreenToClient(HWND, POINT FAR*);
+
+#if (WINVER >= 0x030a)
+void WINAPI MapWindowPoints(HWND hwndFrom, HWND hwndTo, POINT FAR* lppt, UINT cpt);
+#endif /* WINVER >= 0x030a */
+
+HWND WINAPI WindowFromPoint(POINT);
+HWND WINAPI ChildWindowFromPoint(HWND, POINT);
+
+/****** Window query and enumeration ****************************************/
+
+HWND WINAPI GetDesktopWindow(void);
+
+HWND WINAPI FindWindow(LPCSTR, LPCSTR);
+
+#ifdef STRICT
+typedef BOOL (CALLBACK* WNDENUMPROC)(HWND, LPARAM);
+#else
+typedef FARPROC WNDENUMPROC;
+#endif
+
+BOOL WINAPI EnumWindows(WNDENUMPROC, LPARAM);
+BOOL WINAPI EnumChildWindows(HWND, WNDENUMPROC, LPARAM);
+BOOL WINAPI EnumTaskWindows(HTASK, WNDENUMPROC, LPARAM);
+
+HWND WINAPI GetTopWindow(HWND);
+
+HWND WINAPI GetWindow(HWND, UINT);
+HWND WINAPI GetNextWindow(HWND, UINT);
+
+/* GetWindow() constants */
+#define GW_HWNDFIRST 0
+#define GW_HWNDLAST 1
+#define GW_HWNDNEXT 2
+#define GW_HWNDPREV 3
+#define GW_OWNER 4
+#define GW_CHILD 5
+
+
+/****** Window property support *********************************************/
+
+BOOL WINAPI SetProp(HWND, LPCSTR, HANDLE);
+HANDLE WINAPI GetProp(HWND, LPCSTR);
+HANDLE WINAPI RemoveProp(HWND, LPCSTR);
+
+#ifdef STRICT
+typedef BOOL (CALLBACK* PROPENUMPROC)(HWND, LPCSTR, HANDLE);
+#else
+typedef FARPROC PROPENUMPROC;
+#endif
+
+int WINAPI EnumProps(HWND, PROPENUMPROC);
+
+/****** Window drawing support **********************************************/
+
+HDC WINAPI GetDC(HWND);
+int WINAPI ReleaseDC(HWND, HDC);
+
+HDC WINAPI GetWindowDC(HWND);
+
+#if (WINVER >= 0x030a)
+HDC WINAPI GetDCEx(register HWND hwnd, HRGN hrgnClip, DWORD flags);
+
+#define DCX_WINDOW 0x00000001L
+#define DCX_CACHE 0x00000002L
+#define DCX_CLIPCHILDREN 0x00000008L
+#define DCX_CLIPSIBLINGS 0x00000010L
+#define DCX_PARENTCLIP 0x00000020L
+
+#define DCX_EXCLUDERGN 0x00000040L
+#define DCX_INTERSECTRGN 0x00000080L
+
+
+#define DCX_LOCKWINDOWUPDATE 0x00000400L
+
+
+#define DCX_USESTYLE 0x00010000L
+
+#endif /* WINVER >= 0x030a */
+
+/****** Window repainting ***************************************************/
+
+#define WM_PAINT 0x000F
+#define WM_ERASEBKGND 0x0014
+#define WM_ICONERASEBKGND 0x0027
+
+/* BeginPaint() return structure */
+typedef struct tagPAINTSTRUCT
+{
+ HDC hdc;
+ BOOL fErase;
+ RECT rcPaint;
+ BOOL fRestore;
+ BOOL fIncUpdate;
+ BYTE rgbReserved[16];
+} PAINTSTRUCT;
+typedef PAINTSTRUCT* PPAINTSTRUCT;
+typedef PAINTSTRUCT NEAR* NPPAINTSTRUCT;
+typedef PAINTSTRUCT FAR* LPPAINTSTRUCT;
+
+HDC WINAPI BeginPaint(HWND, PAINTSTRUCT FAR*);
+void WINAPI EndPaint(HWND, const PAINTSTRUCT FAR*);
+
+void WINAPI UpdateWindow(HWND);
+
+int WINAPI ExcludeUpdateRgn(HDC, HWND);
+
+#if (WINVER >= 0x030a)
+BOOL WINAPI LockWindowUpdate(HWND hwndLock);
+#endif /* WINVER >= 0x030a */
+
+BOOL WINAPI GetUpdateRect(HWND, RECT FAR*, BOOL);
+int WINAPI GetUpdateRgn(HWND, HRGN, BOOL);
+
+void WINAPI InvalidateRect(HWND, const RECT FAR*, BOOL);
+void WINAPI ValidateRect(HWND, const RECT FAR*);
+
+void WINAPI InvalidateRgn(HWND, HRGN, BOOL);
+void WINAPI ValidateRgn(HWND, HRGN);
+
+#if (WINVER >= 0x030a)
+BOOL WINAPI RedrawWindow(HWND hwnd, const RECT FAR* lprcUpdate, HRGN hrgnUpdate, UINT flags);
+
+#define RDW_INVALIDATE 0x0001
+#define RDW_INTERNALPAINT 0x0002
+#define RDW_ERASE 0x0004
+
+#define RDW_VALIDATE 0x0008
+#define RDW_NOINTERNALPAINT 0x0010
+#define RDW_NOERASE 0x0020
+
+#define RDW_NOCHILDREN 0x0040
+#define RDW_ALLCHILDREN 0x0080
+
+#define RDW_UPDATENOW 0x0100
+#define RDW_ERASENOW 0x0200
+
+#define RDW_FRAME 0x0400
+#define RDW_NOFRAME 0x0800
+
+#endif /* WINVER >= 0x030a */
+
+/****** Window scrolling ****************************************************/
+
+void WINAPI ScrollWindow(HWND, int, int, const RECT FAR*, const RECT FAR*);
+BOOL WINAPI ScrollDC(HDC, int, int, const RECT FAR*, const RECT FAR*, HRGN, RECT FAR*);
+
+#if (WINVER >= 0x030a)
+
+int WINAPI ScrollWindowEx(HWND hwnd, int dx, int dy,
+ const RECT FAR* prcScroll, const RECT FAR* prcClip,
+ HRGN hrgnUpdate, RECT FAR* prcUpdate, UINT flags);
+
+#define SW_SCROLLCHILDREN 0x0001
+#define SW_INVALIDATE 0x0002
+#define SW_ERASE 0x0004
+
+
+#endif /* WINVER >= 0x030a */
+
+/****** Non-client window area management ************************************/
+
+#define WM_NCPAINT 0x0085
+
+#define WM_NCCALCSIZE 0x0083
+
+#if (WINVER >= 0x030a)
+/* WM_NCCALCSIZE return flags */
+#define WVR_ALIGNTOP 0x0010
+#define WVR_ALIGNLEFT 0x0020
+#define WVR_ALIGNBOTTOM 0x0040
+#define WVR_ALIGNRIGHT 0x0080
+#define WVR_HREDRAW 0x0100
+#define WVR_VREDRAW 0x0200
+#define WVR_REDRAW (WVR_HREDRAW | WVR_VREDRAW)
+#define WVR_VALIDRECTS 0x0400
+
+
+/* WM_NCCALCSIZE parameter structure */
+typedef struct tagNCCALCSIZE_PARAMS
+{
+ RECT rgrc[3];
+ WINDOWPOS FAR* lppos;
+} NCCALCSIZE_PARAMS;
+#else /* WINVER >= 0x030a */
+typedef struct tagNCCALCSIZE_PARAMS
+{
+ RECT rgrc[2];
+} NCCALCSIZE_PARAMS;
+#endif /* WINVER >= 0x030a */
+typedef NCCALCSIZE_PARAMS FAR* LPNCCALCSIZE_PARAMS;
+
+#define WM_NCHITTEST 0x0084
+
+/* WM_NCHITTEST return codes */
+#define HTERROR (-2)
+#define HTTRANSPARENT (-1)
+#define HTNOWHERE 0
+#define HTCLIENT 1
+#define HTCAPTION 2
+#define HTSYSMENU 3
+#define HTSIZE 4
+#define HTMENU 5
+#define HTHSCROLL 6
+#define HTVSCROLL 7
+#define HTMINBUTTON 8
+#define HTMAXBUTTON 9
+#define HTLEFT 10
+#define HTRIGHT 11
+#define HTTOP 12
+#define HTTOPLEFT 13
+#define HTTOPRIGHT 14
+#define HTBOTTOM 15
+#define HTBOTTOMLEFT 16
+#define HTBOTTOMRIGHT 17
+#define HTBORDER 18
+#define HTGROWBOX HTSIZE
+#define HTREDUCE HTMINBUTTON
+#define HTZOOM HTMAXBUTTON
+
+/****** Drag-and-drop support ***********************************************/
+
+#define WM_QUERYDRAGICON 0x0037
+#define WM_DROPFILES 0x0233
+
+/****** Window activation ***************************************************/
+
+HWND WINAPI SetActiveWindow(HWND);
+HWND WINAPI GetActiveWindow(void);
+
+HWND WINAPI GetLastActivePopup(HWND);
+
+/* WM_ACTIVATE state values */
+#define WA_INACTIVE 0
+#define WA_ACTIVE 1
+#define WA_CLICKACTIVE 2
+
+#define WM_ACTIVATE 0x0006
+#define WM_ACTIVATEAPP 0x001C
+#define WM_NCACTIVATE 0x0086
+
+/****** Keyboard input support **********************************************/
+
+HWND WINAPI SetFocus(HWND);
+HWND WINAPI GetFocus(void);
+
+int WINAPI GetKeyState(int);
+int WINAPI GetAsyncKeyState(int);
+
+void WINAPI GetKeyboardState(BYTE FAR* );
+void WINAPI SetKeyboardState(BYTE FAR* );
+
+#define WM_SETFOCUS 0x0007
+#define WM_KILLFOCUS 0x0008
+
+#define WM_KEYDOWN 0x0100
+#define WM_KEYUP 0x0101
+
+#define WM_CHAR 0x0102
+#define WM_DEADCHAR 0x0103
+
+#define WM_SYSKEYDOWN 0x0104
+#define WM_SYSKEYUP 0x0105
+
+#define WM_SYSCHAR 0x0106
+#define WM_SYSDEADCHAR 0x0107
+
+
+/* Keyboard message range */
+#define WM_KEYFIRST 0x0100
+#define WM_KEYLAST 0x0108
+
+/* WM_KEYUP/DOWN/CHAR HIWORD(lParam) flags */
+#define KF_EXTENDED 0x0100
+#define KF_DLGMODE 0x0800
+#define KF_MENUMODE 0x1000
+#define KF_ALTDOWN 0x2000
+#define KF_REPEAT 0x4000
+#define KF_UP 0x8000
+
+/* Virtual key codes */
+#ifndef NOVIRTUALKEYCODES
+#define VK_LBUTTON 0x01
+#define VK_RBUTTON 0x02
+#define VK_CANCEL 0x03
+#define VK_MBUTTON 0x04
+#define VK_BACK 0x08
+#define VK_TAB 0x09
+#define VK_CLEAR 0x0C
+#define VK_RETURN 0x0D
+#define VK_SHIFT 0x10
+#define VK_CONTROL 0x11
+#define VK_MENU 0x12
+#define VK_PAUSE 0x13
+#define VK_CAPITAL 0x14
+#define VK_ESCAPE 0x1B
+#define VK_SPACE 0x20
+#define VK_PRIOR 0x21
+#define VK_NEXT 0x22
+#define VK_END 0x23
+#define VK_HOME 0x24
+#define VK_LEFT 0x25
+#define VK_UP 0x26
+#define VK_RIGHT 0x27
+#define VK_DOWN 0x28
+#define VK_SELECT 0x29
+#define VK_PRINT 0x2A
+#define VK_EXECUTE 0x2B
+#define VK_SNAPSHOT 0x2C
+#define VK_INSERT 0x2D
+#define VK_DELETE 0x2E
+#define VK_HELP 0x2F
+#define VK_NUMPAD0 0x60
+#define VK_NUMPAD1 0x61
+#define VK_NUMPAD2 0x62
+#define VK_NUMPAD3 0x63
+#define VK_NUMPAD4 0x64
+#define VK_NUMPAD5 0x65
+#define VK_NUMPAD6 0x66
+#define VK_NUMPAD7 0x67
+#define VK_NUMPAD8 0x68
+#define VK_NUMPAD9 0x69
+#define VK_MULTIPLY 0x6A
+#define VK_ADD 0x6B
+#define VK_SEPARATOR 0x6C
+#define VK_SUBTRACT 0x6D
+#define VK_DECIMAL 0x6E
+#define VK_DIVIDE 0x6F
+#define VK_F1 0x70
+#define VK_F2 0x71
+#define VK_F3 0x72
+#define VK_F4 0x73
+#define VK_F5 0x74
+#define VK_F6 0x75
+#define VK_F7 0x76
+#define VK_F8 0x77
+#define VK_F9 0x78
+#define VK_F10 0x79
+#define VK_F11 0x7A
+#define VK_F12 0x7B
+#define VK_F13 0x7C
+#define VK_F14 0x7D
+#define VK_F15 0x7E
+#define VK_F16 0x7F
+#define VK_F17 0x80
+#define VK_F18 0x81
+#define VK_F19 0x82
+#define VK_F20 0x83
+#define VK_F21 0x84
+#define VK_F22 0x85
+#define VK_F23 0x86
+#define VK_F24 0x87
+#define VK_NUMLOCK 0x90
+#define VK_SCROLL 0x91
+
+/* VK_A thru VK_Z are the same as their ASCII equivalents: 'A' thru 'Z' */
+/* VK_0 thru VK_9 are the same as their ASCII equivalents: '0' thru '0' */
+
+#endif /* NOVIRTUALKEYCODES */
+
+
+/* SetWindowsHook() keyboard hook */
+#define WH_KEYBOARD 2
+
+/****** Mouse input support *************************************************/
+
+HWND WINAPI SetCapture(HWND);
+void WINAPI ReleaseCapture(void);
+HWND WINAPI GetCapture(void);
+
+BOOL WINAPI SwapMouseButton(BOOL);
+
+/* Mouse input messages */
+#define WM_MOUSEMOVE 0x0200
+#define WM_LBUTTONDOWN 0x0201
+#define WM_LBUTTONUP 0x0202
+#define WM_LBUTTONDBLCLK 0x0203
+#define WM_RBUTTONDOWN 0x0204
+#define WM_RBUTTONUP 0x0205
+#define WM_RBUTTONDBLCLK 0x0206
+#define WM_MBUTTONDOWN 0x0207
+#define WM_MBUTTONUP 0x0208
+#define WM_MBUTTONDBLCLK 0x0209
+
+/* Mouse input message range */
+#define WM_MOUSEFIRST 0x0200
+#define WM_MOUSELAST 0x0209
+
+/* Mouse message wParam key states */
+#ifndef NOKEYSTATES
+#define MK_LBUTTON 0x0001
+#define MK_RBUTTON 0x0002
+#define MK_SHIFT 0x0004
+#define MK_CONTROL 0x0008
+#define MK_MBUTTON 0x0010
+#endif /* NOKEYSTATES */
+
+/* Non-client mouse messages */
+#define WM_NCMOUSEMOVE 0x00A0
+#define WM_NCLBUTTONDOWN 0x00A1
+#define WM_NCLBUTTONUP 0x00A2
+#define WM_NCLBUTTONDBLCLK 0x00A3
+#define WM_NCRBUTTONDOWN 0x00A4
+#define WM_NCRBUTTONUP 0x00A5
+#define WM_NCRBUTTONDBLCLK 0x00A6
+#define WM_NCMBUTTONDOWN 0x00A7
+#define WM_NCMBUTTONUP 0x00A8
+#define WM_NCMBUTTONDBLCLK 0x00A9
+
+/* Mouse click activation support */
+#define WM_MOUSEACTIVATE 0x0021
+
+/* WM_MOUSEACTIVATE return codes */
+#define MA_ACTIVATE 1
+#define MA_ACTIVATEANDEAT 2
+#define MA_NOACTIVATE 3
+#if (WINVER >= 0x030a)
+#define MA_NOACTIVATEANDEAT 4
+#endif /* WINVER >= 0x030a */
+
+/* SetWindowsHook() mouse hook */
+#ifndef NOWH
+#define WH_MOUSE 7
+
+typedef struct tagMOUSEHOOKSTRUCT
+{
+ POINT pt;
+ HWND hwnd;
+ UINT wHitTestCode;
+ DWORD dwExtraInfo;
+} MOUSEHOOKSTRUCT;
+typedef MOUSEHOOKSTRUCT FAR* LPMOUSEHOOKSTRUCT;
+#endif /* NOWH */
+
+/****** Mode control ********************************************************/
+
+#define WM_CANCELMODE 0x001F
+
+/****** System modal window support *****************************************/
+
+HWND WINAPI GetSysModalWindow(void);
+HWND WINAPI SetSysModalWindow(HWND);
+
+/****** Timer support *******************************************************/
+
+#ifdef STRICT
+typedef void (CALLBACK* TIMERPROC)(HWND, UINT, UINT, DWORD);
+#else
+typedef FARPROC TIMERPROC;
+#endif
+
+UINT WINAPI SetTimer(HWND, UINT, UINT, TIMERPROC);
+
+BOOL WINAPI KillTimer(HWND, UINT);
+
+#define WM_TIMER 0x0113
+
+/****** Accelerator support *************************************************/
+
+DECLARE_HANDLE(HACCEL);
+
+HACCEL WINAPI LoadAccelerators(HINSTANCE, LPCSTR);
+
+#ifndef NOMSG
+int WINAPI TranslateAccelerator(HWND, HACCEL, MSG FAR*);
+#endif
+
+/****** Menu support ********************************************************/
+
+#ifndef NOMENUS
+
+/* Menu template header */
+typedef struct
+{
+ UINT versionNumber;
+ UINT offset;
+} MENUITEMTEMPLATEHEADER;
+
+/* Menu template item struct */
+typedef struct
+{
+ UINT mtOption;
+ UINT mtID;
+ char mtString[1];
+} MENUITEMTEMPLATE;
+
+#if (WINVER >= 0x030a)
+BOOL WINAPI IsMenu(HMENU);
+#endif /* WINVER >= 0x030a */
+
+HMENU WINAPI CreateMenu(void);
+HMENU WINAPI CreatePopupMenu(void);
+HMENU WINAPI LoadMenu(HINSTANCE, LPCSTR);
+HMENU WINAPI LoadMenuIndirect(const void FAR*);
+
+BOOL WINAPI DestroyMenu(HMENU);
+
+HMENU WINAPI GetMenu(HWND);
+BOOL WINAPI SetMenu(HWND, HMENU);
+
+HMENU WINAPI GetSystemMenu(HWND, BOOL);
+
+void WINAPI DrawMenuBar(HWND);
+
+BOOL WINAPI HiliteMenuItem(HWND, HMENU, UINT, UINT);
+
+BOOL WINAPI InsertMenu(HMENU, UINT, UINT, UINT, LPCSTR);
+BOOL WINAPI AppendMenu(HMENU, UINT, UINT, LPCSTR);
+BOOL WINAPI ModifyMenu(HMENU, UINT, UINT, UINT, LPCSTR);
+BOOL WINAPI RemoveMenu(HMENU, UINT, UINT);
+BOOL WINAPI DeleteMenu(HMENU, UINT, UINT);
+
+BOOL WINAPI ChangeMenu(HMENU, UINT, LPCSTR, UINT, UINT);
+
+#define MF_INSERT 0x0000
+#define MF_CHANGE 0x0080
+#define MF_APPEND 0x0100
+#define MF_DELETE 0x0200
+#define MF_REMOVE 0x1000
+
+/* Menu flags for Add/Check/EnableMenuItem() */
+#define MF_BYCOMMAND 0x0000
+#define MF_BYPOSITION 0x0400
+
+#define MF_SEPARATOR 0x0800
+
+#define MF_ENABLED 0x0000
+#define MF_GRAYED 0x0001
+#define MF_DISABLED 0x0002
+
+#define MF_UNCHECKED 0x0000
+#define MF_CHECKED 0x0008
+#define MF_USECHECKBITMAPS 0x0200
+
+#define MF_STRING 0x0000
+#define MF_BITMAP 0x0004
+#define MF_OWNERDRAW 0x0100
+
+#define MF_POPUP 0x0010
+#define MF_MENUBARBREAK 0x0020
+#define MF_MENUBREAK 0x0040
+
+#define MF_UNHILITE 0x0000
+#define MF_HILITE 0x0080
+
+#define MF_SYSMENU 0x2000
+#define MF_HELP 0x4000
+#define MF_MOUSESELECT 0x8000
+
+
+#define MF_END 0x0080 /* Only valid in menu resource templates */
+
+BOOL WINAPI EnableMenuItem(HMENU, UINT, UINT);
+BOOL WINAPI CheckMenuItem(HMENU, UINT, UINT);
+
+HMENU WINAPI GetSubMenu(HMENU, int);
+
+int WINAPI GetMenuItemCount(HMENU);
+UINT WINAPI GetMenuItemID(HMENU, int);
+
+int WINAPI GetMenuString(HMENU, UINT, LPSTR, int, UINT);
+UINT WINAPI GetMenuState(HMENU, UINT, UINT);
+
+BOOL WINAPI SetMenuItemBitmaps(HMENU, UINT, UINT, HBITMAP, HBITMAP);
+DWORD WINAPI GetMenuCheckMarkDimensions(void);
+
+BOOL WINAPI TrackPopupMenu(HMENU, UINT, int, int, int, HWND, const RECT FAR*);
+
+/* Flags for TrackPopupMenu */
+#define TPM_LEFTBUTTON 0x0000
+#if (WINVER >= 0x030a)
+#define TPM_RIGHTBUTTON 0x0002
+#define TPM_LEFTALIGN 0x0000
+#define TPM_CENTERALIGN 0x0004
+#define TPM_RIGHTALIGN 0x0008
+#endif /* WINVER >= 0x030a */
+
+#endif /* NOMENUS */
+
+/* Menu messages */
+#define WM_INITMENU 0x0116
+#define WM_INITMENUPOPUP 0x0117
+
+#ifndef NOMENUS
+
+#define WM_MENUSELECT 0x011F
+#define WM_MENUCHAR 0x0120
+
+#endif /* NOMENUS */
+
+/* Menu and control command messages */
+#define WM_COMMAND 0x0111
+
+/****** Scroll bar support **************************************************/
+
+#ifndef NOSCROLL
+
+#define WM_HSCROLL 0x0114
+#define WM_VSCROLL 0x0115
+
+/* WM_H/VSCROLL commands */
+#define SB_LINEUP 0
+#define SB_LINELEFT 0
+#define SB_LINEDOWN 1
+#define SB_LINERIGHT 1
+#define SB_PAGEUP 2
+#define SB_PAGELEFT 2
+#define SB_PAGEDOWN 3
+#define SB_PAGERIGHT 3
+#define SB_THUMBPOSITION 4
+#define SB_THUMBTRACK 5
+#define SB_TOP 6
+#define SB_LEFT 6
+#define SB_BOTTOM 7
+#define SB_RIGHT 7
+#define SB_ENDSCROLL 8
+
+/* Scroll bar selection constants */
+#define SB_HORZ 0
+#define SB_VERT 1
+#define SB_CTL 2
+#define SB_BOTH 3
+
+int WINAPI SetScrollPos(HWND, int, int, BOOL);
+int WINAPI GetScrollPos(HWND, int);
+void WINAPI SetScrollRange(HWND, int, int, int, BOOL);
+void WINAPI GetScrollRange(HWND, int, int FAR*, int FAR*);
+void WINAPI ShowScrollBar(HWND, int, BOOL);
+BOOL WINAPI EnableScrollBar(HWND, int, UINT);
+
+/* EnableScrollBar() flags */
+#define ESB_ENABLE_BOTH 0x0000
+#define ESB_DISABLE_BOTH 0x0003
+
+#define ESB_DISABLE_LEFT 0x0001
+#define ESB_DISABLE_RIGHT 0x0002
+
+#define ESB_DISABLE_UP 0x0001
+#define ESB_DISABLE_DOWN 0x0002
+
+#define ESB_DISABLE_LTUP ESB_DISABLE_LEFT
+#define ESB_DISABLE_RTDN ESB_DISABLE_RIGHT
+
+#endif /* NOSCROLL */
+
+/******* Clipboard manager **************************************************/
+
+#ifndef NOCLIPBOARD
+
+/* Predefined Clipboard Formats */
+#define CF_TEXT 1
+#define CF_BITMAP 2
+#define CF_METAFILEPICT 3
+#define CF_SYLK 4
+#define CF_DIF 5
+#define CF_TIFF 6
+#define CF_OEMTEXT 7
+#define CF_DIB 8
+#define CF_PALETTE 9
+#define CF_PENDATA 10
+#define CF_RIFF 11
+#define CF_WAVE 12
+
+#define CF_OWNERDISPLAY 0x0080
+#define CF_DSPTEXT 0x0081
+#define CF_DSPBITMAP 0x0082
+#define CF_DSPMETAFILEPICT 0x0083
+
+/* "Private" formats don't get GlobalFree()'d */
+#define CF_PRIVATEFIRST 0x0200
+#define CF_PRIVATELAST 0x02FF
+
+/* "GDIOBJ" formats do get DeleteObject()'d */
+#define CF_GDIOBJFIRST 0x0300
+#define CF_GDIOBJLAST 0x03FF
+
+/* Clipboard Manager Functions */
+BOOL WINAPI OpenClipboard(HWND);
+BOOL WINAPI CloseClipboard(void);
+BOOL WINAPI EmptyClipboard(void);
+
+#if (WINVER >= 0x030a)
+HWND WINAPI GetOpenClipboardWindow(void);
+#endif /* WINVER >= 0x030a */
+
+HWND WINAPI GetClipboardOwner(void);
+
+HWND WINAPI SetClipboardViewer(HWND);
+HWND WINAPI GetClipboardViewer(void);
+
+HANDLE WINAPI SetClipboardData(UINT, HANDLE);
+HANDLE WINAPI GetClipboardData(UINT);
+
+BOOL WINAPI IsClipboardFormatAvailable(UINT);
+int WINAPI GetPriorityClipboardFormat(UINT FAR*, int);
+
+UINT WINAPI RegisterClipboardFormat(LPCSTR);
+int WINAPI CountClipboardFormats(void);
+UINT WINAPI EnumClipboardFormats(UINT);
+int WINAPI GetClipboardFormatName(UINT, LPSTR, int);
+
+BOOL WINAPI ChangeClipboardChain(HWND, HWND);
+
+/* Clipboard command messages */
+#define WM_CUT 0x0300
+#define WM_COPY 0x0301
+#define WM_PASTE 0x0302
+#define WM_CLEAR 0x0303
+#define WM_UNDO 0x0304
+
+/* Clipboard owner messages */
+#define WM_RENDERFORMAT 0x0305
+#define WM_RENDERALLFORMATS 0x0306
+#define WM_DESTROYCLIPBOARD 0x0307
+
+/* Clipboard viewer messages */
+#define WM_DRAWCLIPBOARD 0x0308
+#define WM_PAINTCLIPBOARD 0x0309
+#define WM_SIZECLIPBOARD 0x030B
+#define WM_VSCROLLCLIPBOARD 0x030A
+#define WM_HSCROLLCLIPBOARD 0x030E
+#define WM_ASKCBFORMATNAME 0x030C
+#define WM_CHANGECBCHAIN 0x030D
+
+#endif /* NOCLIPBOARD */
+
+/****** Mouse cursor support *************************************************/
+
+HCURSOR WINAPI LoadCursor(HINSTANCE, LPCSTR);
+HCURSOR WINAPI CreateCursor(HINSTANCE, int, int, int, int, const void FAR*, const void FAR*);
+BOOL WINAPI DestroyCursor(HCURSOR);
+
+#if (WINVER >= 0x030a)
+HCURSOR WINAPI CopyCursor(HINSTANCE, HCURSOR);
+#endif /* WINVER >= 0x030a */
+
+int WINAPI ShowCursor(BOOL);
+
+void WINAPI SetCursorPos(int, int);
+void WINAPI GetCursorPos(POINT FAR*);
+
+HCURSOR WINAPI SetCursor(HCURSOR);
+
+#if (WINVER >= 0x030a)
+HCURSOR WINAPI GetCursor(void);
+#endif /* WINVER >= 0x030a */
+
+void WINAPI ClipCursor(const RECT FAR*);
+#if (WINVER >= 0x030a)
+void WINAPI GetClipCursor(RECT FAR*);
+#endif /* WINVER >= 0x030a */
+
+/* Standard cursor resource IDs */
+#define IDC_ARROW MAKEINTRESOURCE(32512)
+#define IDC_IBEAM MAKEINTRESOURCE(32513)
+#define IDC_WAIT MAKEINTRESOURCE(32514)
+#define IDC_CROSS MAKEINTRESOURCE(32515)
+#define IDC_UPARROW MAKEINTRESOURCE(32516)
+#define IDC_SIZE MAKEINTRESOURCE(32640)
+#define IDC_ICON MAKEINTRESOURCE(32641)
+#define IDC_SIZENWSE MAKEINTRESOURCE(32642)
+#define IDC_SIZENESW MAKEINTRESOURCE(32643)
+#define IDC_SIZEWE MAKEINTRESOURCE(32644)
+#define IDC_SIZENS MAKEINTRESOURCE(32645)
+
+#define WM_SETCURSOR 0x0020
+
+/****** Icon support *********************************************************/
+
+HICON WINAPI LoadIcon(HINSTANCE, LPCSTR);
+HICON WINAPI CreateIcon(HINSTANCE, int, int, BYTE, BYTE, const void FAR*, const void FAR*);
+BOOL WINAPI DestroyIcon(HICON);
+
+#if (WINVER >= 0x030a)
+HICON WINAPI CopyIcon(HINSTANCE, HICON);
+#endif /* WINVER >= 0x030a */
+
+BOOL WINAPI DrawIcon(HDC, int, int, HICON);
+
+#ifndef NOICONS
+
+/* Standard icon resource IDs */
+#define IDI_APPLICATION MAKEINTRESOURCE(32512)
+#define IDI_HAND MAKEINTRESOURCE(32513)
+#define IDI_QUESTION MAKEINTRESOURCE(32514)
+#define IDI_EXCLAMATION MAKEINTRESOURCE(32515)
+#define IDI_ASTERISK MAKEINTRESOURCE(32516)
+
+#endif /* NOICONS */
+
+/****** Message Box support *************************************************/
+
+#ifndef NOMB
+
+int WINAPI MessageBox(HWND, LPCSTR, LPCSTR, UINT);
+void WINAPI MessageBeep(UINT);
+
+#define MB_OK 0x0000
+#define MB_OKCANCEL 0x0001
+#define MB_ABORTRETRYIGNORE 0x0002
+#define MB_YESNOCANCEL 0x0003
+#define MB_YESNO 0x0004
+#define MB_RETRYCANCEL 0x0005
+#define MB_TYPEMASK 0x000F
+
+#define MB_ICONHAND 0x0010
+#define MB_ICONQUESTION 0x0020
+#define MB_ICONEXCLAMATION 0x0030
+#define MB_ICONASTERISK 0x0040
+#define MB_ICONMASK 0x00F0
+
+#define MB_ICONINFORMATION MB_ICONASTERISK
+#define MB_ICONSTOP MB_ICONHAND
+
+#define MB_DEFBUTTON1 0x0000
+#define MB_DEFBUTTON2 0x0100
+#define MB_DEFBUTTON3 0x0200
+#define MB_DEFMASK 0x0F00
+
+#define MB_APPLMODAL 0x0000
+#define MB_SYSTEMMODAL 0x1000
+#define MB_TASKMODAL 0x2000
+
+#define MB_NOFOCUS 0x8000
+
+
+
+#endif /* NOMB */
+
+/****** Caret support ********************************************************/
+
+void WINAPI CreateCaret(HWND, HBITMAP, int, int);
+void WINAPI DestroyCaret(void);
+
+void WINAPI SetCaretPos(int, int);
+void WINAPI GetCaretPos(POINT FAR*);
+
+void WINAPI HideCaret(HWND);
+void WINAPI ShowCaret(HWND);
+
+UINT WINAPI GetCaretBlinkTime(void);
+void WINAPI SetCaretBlinkTime(UINT);
+
+/****** WM_SYSCOMMAND support ***********************************************/
+
+#define WM_SYSCOMMAND 0x0112
+
+#ifndef NOSYSCOMMANDS
+
+/* System Menu Command Values */
+#define SC_SIZE 0xF000
+#define SC_MOVE 0xF010
+#define SC_MINIMIZE 0xF020
+#define SC_MAXIMIZE 0xF030
+#define SC_NEXTWINDOW 0xF040
+#define SC_PREVWINDOW 0xF050
+#define SC_CLOSE 0xF060
+#define SC_VSCROLL 0xF070
+#define SC_HSCROLL 0xF080
+#define SC_MOUSEMENU 0xF090
+#define SC_KEYMENU 0xF100
+#define SC_ARRANGE 0xF110
+#define SC_RESTORE 0xF120
+#define SC_TASKLIST 0xF130
+#define SC_SCREENSAVE 0xF140
+#define SC_HOTKEY 0xF150
+
+/* Obsolete names */
+#define SC_ICON SC_MINIMIZE
+#define SC_ZOOM SC_MAXIMIZE
+
+
+#endif /* NOSYSCOMMANDS */
+
+/****** MDI Support *********************************************************/
+
+#ifndef NOMDI
+
+/* CreateWindow lpParams structure for creating MDI client */
+typedef struct tagCLIENTCREATESTRUCT
+{
+ HMENU hWindowMenu;
+ UINT idFirstChild;
+} CLIENTCREATESTRUCT;
+typedef CLIENTCREATESTRUCT FAR* LPCLIENTCREATESTRUCT;
+
+/* MDI client style bits */
+#if (WINVER >= 0x030a)
+#define MDIS_ALLCHILDSTYLES 0x0001
+#endif /* WINVER >= 0x030a */
+
+/* MDI messages */
+#define WM_MDICREATE 0x0220
+#define WM_MDIDESTROY 0x0221
+#define WM_MDIACTIVATE 0x0222
+#define WM_MDIRESTORE 0x0223
+#define WM_MDINEXT 0x0224
+#define WM_MDIMAXIMIZE 0x0225
+#define WM_MDITILE 0x0226
+#define WM_MDICASCADE 0x0227
+#define WM_MDIICONARRANGE 0x0228
+#define WM_MDIGETACTIVE 0x0229
+#define WM_MDISETMENU 0x0230
+
+/* WM_MDICREATE message structure */
+typedef struct tagMDICREATESTRUCT
+{
+ LPCSTR szClass;
+ LPCSTR szTitle;
+ HINSTANCE hOwner;
+ int x;
+ int y;
+ int cx;
+ int cy;
+ DWORD style;
+ LPARAM lParam;
+} MDICREATESTRUCT;
+typedef MDICREATESTRUCT FAR* LPMDICREATESTRUCT;
+
+#if (WINVER >= 0x030a)
+/* wParam values for WM_MDITILE and WM_MDICASCADE messages. */
+#define MDITILE_VERTICAL 0x0000
+#define MDITILE_HORIZONTAL 0x0001
+#define MDITILE_SKIPDISABLED 0x0002
+#endif /* WINVER >= 0x030a */
+
+#define WM_CHILDACTIVATE 0x0022
+
+LRESULT WINAPI DefFrameProc(HWND, HWND, UINT, WPARAM, LPARAM);
+LRESULT WINAPI DefMDIChildProc(HWND, UINT, WPARAM, LPARAM);
+
+#ifndef NOMSG
+BOOL WINAPI TranslateMDISysAccel(HWND, MSG FAR*);
+#endif
+
+UINT WINAPI ArrangeIconicWindows(HWND);
+
+#endif /* NOMDI */
+
+/****** Dialog and Control Management ***************************************/
+
+#ifndef NOCTLMGR
+
+/* Dialog window class */
+#define WC_DIALOG (MAKEINTATOM(0x8002))
+
+/* cbWndExtra bytes needed by dialog manager for dialog classes */
+#define DLGWINDOWEXTRA 30
+
+/* Dialog styles */
+#define DS_ABSALIGN 0x01L
+#define DS_SYSMODAL 0x02L
+#define DS_LOCALEDIT 0x20L
+#define DS_SETFONT 0x40L
+#define DS_MODALFRAME 0x80L
+#define DS_NOIDLEMSG 0x100L
+
+/* Dialog messages */
+#define DM_GETDEFID (WM_USER+0)
+#define DM_SETDEFID (WM_USER+1)
+
+/* Returned in HIWORD() of DM_GETDEFID result if msg is supported */
+#define DC_HASDEFID 0x534B
+
+#endif /* NOCTLMGR */
+
+/* Dialog notification messages */
+#define WM_INITDIALOG 0x0110
+#define WM_NEXTDLGCTL 0x0028
+
+#define WM_PARENTNOTIFY 0x0210
+
+#define WM_ENTERIDLE 0x0121
+
+
+#ifndef NOCTLMGR
+
+#ifdef STRICT
+typedef BOOL (CALLBACK* DLGPROC)(HWND, UINT, WPARAM, LPARAM);
+#else
+typedef FARPROC DLGPROC;
+#endif
+
+/* Get/SetWindowWord/Long offsets for use with WC_DIALOG windows */
+#define DWL_MSGRESULT 0
+#define DWL_DLGPROC 4
+#define DWL_USER 8
+
+#ifndef NOMSG
+BOOL WINAPI IsDialogMessage(HWND, MSG FAR*);
+#endif
+
+LRESULT WINAPI DefDlgProc(HWND, UINT, WPARAM, LPARAM);
+
+HWND WINAPI CreateDialog(HINSTANCE, LPCSTR, HWND, DLGPROC);
+HWND WINAPI CreateDialogIndirect(HINSTANCE, const void FAR*, HWND, DLGPROC);
+HWND WINAPI CreateDialogParam(HINSTANCE, LPCSTR, HWND, DLGPROC, LPARAM);
+HWND WINAPI CreateDialogIndirectParam(HINSTANCE, const void FAR*, HWND, DLGPROC, LPARAM);
+
+int WINAPI DialogBox(HINSTANCE, LPCSTR, HWND, DLGPROC);
+int WINAPI DialogBoxIndirect(HINSTANCE, HGLOBAL, HWND, DLGPROC);
+int WINAPI DialogBoxParam(HINSTANCE, LPCSTR, HWND, DLGPROC, LPARAM);
+int WINAPI DialogBoxIndirectParam(HINSTANCE, HGLOBAL, HWND, DLGPROC, LPARAM);
+
+void WINAPI EndDialog(HWND, int);
+
+int WINAPI GetDlgCtrlID(HWND);
+HWND WINAPI GetDlgItem(HWND, int);
+LRESULT WINAPI SendDlgItemMessage(HWND, int, UINT, WPARAM, LPARAM);
+
+void WINAPI SetDlgItemInt(HWND, int, UINT, BOOL);
+UINT WINAPI GetDlgItemInt(HWND, int, BOOL FAR* , BOOL);
+
+void WINAPI SetDlgItemText(HWND, int, LPCSTR);
+int WINAPI GetDlgItemText(HWND, int, LPSTR, int);
+
+void WINAPI CheckDlgButton(HWND, int, UINT);
+void WINAPI CheckRadioButton(HWND, int, int, int);
+UINT WINAPI IsDlgButtonChecked(HWND, int);
+
+HWND WINAPI GetNextDlgGroupItem(HWND, HWND, BOOL);
+HWND WINAPI GetNextDlgTabItem(HWND, HWND, BOOL);
+
+void WINAPI MapDialogRect(HWND, RECT FAR*);
+DWORD WINAPI GetDialogBaseUnits(void);
+
+#define WM_GETDLGCODE 0x0087
+
+/* dialog codes */
+#define DLGC_WANTARROWS 0x0001
+#define DLGC_WANTTAB 0x0002
+#define DLGC_WANTALLKEYS 0x0004
+#define DLGC_WANTMESSAGE 0x0004
+#define DLGC_HASSETSEL 0x0008
+#define DLGC_DEFPUSHBUTTON 0x0010
+#define DLGC_UNDEFPUSHBUTTON 0x0020
+#define DLGC_RADIOBUTTON 0x0040
+#define DLGC_WANTCHARS 0x0080
+#define DLGC_STATIC 0x0100
+#define DLGC_BUTTON 0x2000
+
+#define WM_CTLCOLOR 0x0019
+
+/* WM_CTLCOLOR control IDs */
+#define CTLCOLOR_MSGBOX 0
+#define CTLCOLOR_EDIT 1
+#define CTLCOLOR_LISTBOX 2
+#define CTLCOLOR_BTN 3
+#define CTLCOLOR_DLG 4
+#define CTLCOLOR_SCROLLBAR 5
+#define CTLCOLOR_STATIC 6
+
+#define WM_SETFONT 0x0030
+#define WM_GETFONT 0x0031
+
+#endif /* NOCTLMGR */
+
+/* Standard dialog button IDs */
+#define IDOK 1
+#define IDCANCEL 2
+#define IDABORT 3
+#define IDRETRY 4
+#define IDIGNORE 5
+#define IDYES 6
+#define IDNO 7
+
+/****** Owner draw control support ******************************************/
+
+/* Owner draw control types */
+#define ODT_MENU 1
+#define ODT_LISTBOX 2
+#define ODT_COMBOBOX 3
+#define ODT_BUTTON 4
+
+/* Owner draw actions */
+#define ODA_DRAWENTIRE 0x0001
+#define ODA_SELECT 0x0002
+#define ODA_FOCUS 0x0004
+
+/* Owner draw state */
+#define ODS_SELECTED 0x0001
+#define ODS_GRAYED 0x0002
+#define ODS_DISABLED 0x0004
+#define ODS_CHECKED 0x0008
+#define ODS_FOCUS 0x0010
+
+#define WM_DRAWITEM 0x002B
+
+typedef struct tagDRAWITEMSTRUCT
+{
+ UINT CtlType;
+ UINT CtlID;
+ UINT itemID;
+ UINT itemAction;
+ UINT itemState;
+ HWND hwndItem;
+ HDC hDC;
+ RECT rcItem;
+ DWORD itemData;
+} DRAWITEMSTRUCT;
+typedef DRAWITEMSTRUCT NEAR* PDRAWITEMSTRUCT;
+typedef DRAWITEMSTRUCT FAR* LPDRAWITEMSTRUCT;
+
+#define WM_MEASUREITEM 0x002C
+
+typedef struct tagMEASUREITEMSTRUCT
+{
+ UINT CtlType;
+ UINT CtlID;
+ UINT itemID;
+ UINT itemWidth;
+ UINT itemHeight;
+ DWORD itemData;
+} MEASUREITEMSTRUCT;
+typedef MEASUREITEMSTRUCT NEAR* PMEASUREITEMSTRUCT;
+typedef MEASUREITEMSTRUCT FAR* LPMEASUREITEMSTRUCT;
+
+#define WM_DELETEITEM 0x002D
+
+typedef struct tagDELETEITEMSTRUCT
+{
+ UINT CtlType;
+ UINT CtlID;
+ UINT itemID;
+ HWND hwndItem;
+ DWORD itemData;
+} DELETEITEMSTRUCT;
+typedef DELETEITEMSTRUCT NEAR* PDELETEITEMSTRUCT;
+typedef DELETEITEMSTRUCT FAR* LPDELETEITEMSTRUCT;
+
+#define WM_COMPAREITEM 0x0039
+
+typedef struct tagCOMPAREITEMSTRUCT
+{
+ UINT CtlType;
+ UINT CtlID;
+ HWND hwndItem;
+ UINT itemID1;
+ DWORD itemData1;
+ UINT itemID2;
+ DWORD itemData2;
+} COMPAREITEMSTRUCT;
+typedef COMPAREITEMSTRUCT NEAR* PCOMPAREITEMSTRUCT;
+typedef COMPAREITEMSTRUCT FAR* LPCOMPAREITEMSTRUCT;
+
+/****** Static control ******************************************************/
+
+#ifndef NOCTLMGR
+
+/* Static Control Styles */
+#define SS_LEFT 0x00000000L
+#define SS_CENTER 0x00000001L
+#define SS_RIGHT 0x00000002L
+#define SS_ICON 0x00000003L
+#define SS_BLACKRECT 0x00000004L
+#define SS_GRAYRECT 0x00000005L
+#define SS_WHITERECT 0x00000006L
+#define SS_BLACKFRAME 0x00000007L
+#define SS_GRAYFRAME 0x00000008L
+#define SS_WHITEFRAME 0x00000009L
+#define SS_SIMPLE 0x0000000BL
+#define SS_LEFTNOWORDWRAP 0x0000000CL
+#define SS_NOPREFIX 0x00000080L
+
+#if (WINVER >= 0x030a)
+#ifndef NOWINMESSAGES
+/* Static Control Mesages */
+#define STM_SETICON (WM_USER+0)
+#define STM_GETICON (WM_USER+1)
+#endif /* NOWINMESSAGES */
+#endif /* WINVER >= 0x030a */
+
+#endif /* NOCTLMGR */
+
+/****** Button control *****************************************************/
+
+#ifndef NOCTLMGR
+
+/* Button Control Styles */
+#define BS_PUSHBUTTON 0x00000000L
+#define BS_DEFPUSHBUTTON 0x00000001L
+#define BS_CHECKBOX 0x00000002L
+#define BS_AUTOCHECKBOX 0x00000003L
+#define BS_RADIOBUTTON 0x00000004L
+#define BS_3STATE 0x00000005L
+#define BS_AUTO3STATE 0x00000006L
+#define BS_GROUPBOX 0x00000007L
+#define BS_USERBUTTON 0x00000008L
+#define BS_AUTORADIOBUTTON 0x00000009L
+#define BS_OWNERDRAW 0x0000000BL
+#define BS_LEFTTEXT 0x00000020L
+
+/* Button Control Messages */
+#define BM_GETCHECK (WM_USER+0)
+#define BM_SETCHECK (WM_USER+1)
+#define BM_GETSTATE (WM_USER+2)
+#define BM_SETSTATE (WM_USER+3)
+#define BM_SETSTYLE (WM_USER+4)
+
+/* User Button Notification Codes */
+#define BN_CLICKED 0
+#define BN_PAINT 1
+#define BN_HILITE 2
+#define BN_UNHILITE 3
+#define BN_DISABLE 4
+#define BN_DOUBLECLICKED 5
+
+#endif /* NOCTLMGR */
+
+/****** Edit control *******************************************************/
+
+#ifndef NOCTLMGR
+
+/* Edit control styles */
+#ifndef NOWINSTYLES
+#define ES_LEFT 0x00000000L
+#define ES_CENTER 0x00000001L
+#define ES_RIGHT 0x00000002L
+#define ES_MULTILINE 0x00000004L
+#define ES_UPPERCASE 0x00000008L
+#define ES_LOWERCASE 0x00000010L
+#define ES_PASSWORD 0x00000020L
+#define ES_AUTOVSCROLL 0x00000040L
+#define ES_AUTOHSCROLL 0x00000080L
+#define ES_NOHIDESEL 0x00000100L
+#define ES_OEMCONVERT 0x00000400L
+#if (WINVER >= 0x030a)
+#define ES_READONLY 0x00000800L
+#define ES_WANTRETURN 0x00001000L
+#endif /* WINVER >= 0x030a */
+#endif /* NOWINSTYLES */
+
+/* Edit control messages */
+#ifndef NOWINMESSAGES
+#define EM_GETSEL (WM_USER+0)
+#define EM_SETSEL (WM_USER+1)
+#define EM_GETRECT (WM_USER+2)
+#define EM_SETRECT (WM_USER+3)
+#define EM_SETRECTNP (WM_USER+4)
+#define EM_LINESCROLL (WM_USER+6)
+#define EM_GETMODIFY (WM_USER+8)
+#define EM_SETMODIFY (WM_USER+9)
+#define EM_GETLINECOUNT (WM_USER+10)
+#define EM_LINEINDEX (WM_USER+11)
+#define EM_SETHANDLE (WM_USER+12)
+#define EM_GETHANDLE (WM_USER+13)
+#define EM_LINELENGTH (WM_USER+17)
+#define EM_REPLACESEL (WM_USER+18)
+#define EM_SETFONT (WM_USER+19) /* NOT IMPLEMENTED: use WM_SETFONT */
+#define EM_GETLINE (WM_USER+20)
+#define EM_LIMITTEXT (WM_USER+21)
+#define EM_CANUNDO (WM_USER+22)
+#define EM_UNDO (WM_USER+23)
+#define EM_FMTLINES (WM_USER+24)
+#define EM_LINEFROMCHAR (WM_USER+25)
+#define EM_SETWORDBREAK (WM_USER+26) /* NOT IMPLEMENTED: use EM_SETWORDBREAK */
+#define EM_SETTABSTOPS (WM_USER+27)
+#define EM_SETPASSWORDCHAR (WM_USER+28)
+#define EM_EMPTYUNDOBUFFER (WM_USER+29)
+#if (WINVER >= 0x030a)
+#define EM_GETFIRSTVISIBLELINE (WM_USER+30)
+#define EM_SETREADONLY (WM_USER+31)
+#define EM_SETWORDBREAKPROC (WM_USER+32)
+#define EM_GETWORDBREAKPROC (WM_USER+33)
+#define EM_GETPASSWORDCHAR (WM_USER+34)
+#endif /* WINVER >= 0x030a */
+#endif /* NOWINMESSAGES */
+
+#if (WINVER >= 0x030a)
+typedef int (CALLBACK* EDITWORDBREAKPROC)(LPSTR lpch, int ichCurrent, int cch, int code);
+
+/* EDITWORDBREAKPROC code values */
+#define WB_LEFT 0
+#define WB_RIGHT 1
+#define WB_ISDELIMITER 2
+#endif /* WINVER >= 0x030a */
+
+/* Edit control notification codes */
+#define EN_SETFOCUS 0x0100
+#define EN_KILLFOCUS 0x0200
+#define EN_CHANGE 0x0300
+#define EN_UPDATE 0x0400
+#define EN_ERRSPACE 0x0500
+#define EN_MAXTEXT 0x0501
+#define EN_HSCROLL 0x0601
+#define EN_VSCROLL 0x0602
+
+#endif /* NOCTLMGR */
+
+/****** Scroll bar control *************************************************/
+/* Also see scrolling support */
+
+#ifndef NOCTLMGR
+
+#ifndef NOWINSTYLES
+
+/* Scroll bar styles */
+#define SBS_HORZ 0x0000L
+#define SBS_VERT 0x0001L
+#define SBS_TOPALIGN 0x0002L
+#define SBS_LEFTALIGN 0x0002L
+#define SBS_BOTTOMALIGN 0x0004L
+#define SBS_RIGHTALIGN 0x0004L
+#define SBS_SIZEBOXTOPLEFTALIGN 0x0002L
+#define SBS_SIZEBOXBOTTOMRIGHTALIGN 0x0004L
+#define SBS_SIZEBOX 0x0008L
+
+#endif /* NOWINSTYLES */
+
+#endif /* NOCTLMGR */
+
+/****** Listbox control ****************************************************/
+
+#ifndef NOCTLMGR
+
+/* Listbox styles */
+#ifndef NOWINSTYLES
+#define LBS_NOTIFY 0x0001L
+#define LBS_SORT 0x0002L
+#define LBS_NOREDRAW 0x0004L
+#define LBS_MULTIPLESEL 0x0008L
+#define LBS_OWNERDRAWFIXED 0x0010L
+#define LBS_OWNERDRAWVARIABLE 0x0020L
+#define LBS_HASSTRINGS 0x0040L
+#define LBS_USETABSTOPS 0x0080L
+#define LBS_NOINTEGRALHEIGHT 0x0100L
+#define LBS_MULTICOLUMN 0x0200L
+#define LBS_WANTKEYBOARDINPUT 0x0400L
+#define LBS_EXTENDEDSEL 0x0800L
+#if (WINVER >= 0x030a)
+#define LBS_DISABLENOSCROLL 0x1000L
+#endif /* WINVER >= 0x030a */
+#define LBS_STANDARD (LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER)
+#endif /* NOWINSTYLES */
+
+/* Listbox messages */
+#ifndef NOWINMESSAGES
+#define LB_ADDSTRING (WM_USER+1)
+#define LB_INSERTSTRING (WM_USER+2)
+#define LB_DELETESTRING (WM_USER+3)
+#define LB_RESETCONTENT (WM_USER+5)
+#define LB_SETSEL (WM_USER+6)
+#define LB_SETCURSEL (WM_USER+7)
+#define LB_GETSEL (WM_USER+8)
+#define LB_GETCURSEL (WM_USER+9)
+#define LB_GETTEXT (WM_USER+10)
+#define LB_GETTEXTLEN (WM_USER+11)
+#define LB_GETCOUNT (WM_USER+12)
+#define LB_SELECTSTRING (WM_USER+13)
+#define LB_DIR (WM_USER+14)
+#define LB_GETTOPINDEX (WM_USER+15)
+#define LB_FINDSTRING (WM_USER+16)
+#define LB_GETSELCOUNT (WM_USER+17)
+#define LB_GETSELITEMS (WM_USER+18)
+#define LB_SETTABSTOPS (WM_USER+19)
+#define LB_GETHORIZONTALEXTENT (WM_USER+20)
+#define LB_SETHORIZONTALEXTENT (WM_USER+21)
+#define LB_SETCOLUMNWIDTH (WM_USER+22)
+#define LB_SETTOPINDEX (WM_USER+24)
+#define LB_GETITEMRECT (WM_USER+25)
+#define LB_GETITEMDATA (WM_USER+26)
+#define LB_SETITEMDATA (WM_USER+27)
+#define LB_SELITEMRANGE (WM_USER+28)
+#define LB_SETCARETINDEX (WM_USER+31)
+#define LB_GETCARETINDEX (WM_USER+32)
+
+#if (WINVER >= 0x030a)
+#define LB_SETITEMHEIGHT (WM_USER+33)
+#define LB_GETITEMHEIGHT (WM_USER+34)
+#define LB_FINDSTRINGEXACT (WM_USER+35)
+#endif /* WINVER >= 0x030a */
+
+#endif /* NOWINMESSAGES */
+
+/* Listbox notification codes */
+#define LBN_ERRSPACE (-2)
+#define LBN_SELCHANGE 1
+#define LBN_DBLCLK 2
+#define LBN_SELCANCEL 3
+#define LBN_SETFOCUS 4
+#define LBN_KILLFOCUS 5
+
+/* Listbox notification messages */
+#define WM_VKEYTOITEM 0x002E
+#define WM_CHARTOITEM 0x002F
+
+/* Listbox message return values */
+#define LB_OKAY 0
+#define LB_ERR (-1)
+#define LB_ERRSPACE (-2)
+
+#define LB_CTLCODE 0L
+
+/****** Dialog directory support ********************************************/
+
+int WINAPI DlgDirList(HWND, LPSTR, int, int, UINT);
+BOOL WINAPI DlgDirSelect(HWND, LPSTR, int);
+
+int WINAPI DlgDirListComboBox(HWND, LPSTR, int, int, UINT);
+BOOL WINAPI DlgDirSelectComboBox(HWND, LPSTR, int);
+
+#if (WINVER >= 0x030a)
+BOOL WINAPI DlgDirSelectEx(HWND, LPSTR, int, int);
+BOOL WINAPI DlgDirSelectComboBoxEx(HWND, LPSTR, int, int);
+#endif /* WINVER >= 0x030a */
+
+
+/* DlgDirList, DlgDirListComboBox flags values */
+#define DDL_READWRITE 0x0000
+#define DDL_READONLY 0x0001
+#define DDL_HIDDEN 0x0002
+#define DDL_SYSTEM 0x0004
+#define DDL_DIRECTORY 0x0010
+#define DDL_ARCHIVE 0x0020
+
+#define DDL_POSTMSGS 0x2000
+#define DDL_DRIVES 0x4000
+#define DDL_EXCLUSIVE 0x8000
+
+#endif /* NOCTLMGR */
+
+/****** Combo box control **************************************************/
+
+#ifndef NOCTLMGR
+
+/* Combo box styles */
+#ifndef NOWINSTYLES
+#define CBS_SIMPLE 0x0001L
+#define CBS_DROPDOWN 0x0002L
+#define CBS_DROPDOWNLIST 0x0003L
+#define CBS_OWNERDRAWFIXED 0x0010L
+#define CBS_OWNERDRAWVARIABLE 0x0020L
+#define CBS_AUTOHSCROLL 0x0040L
+#define CBS_OEMCONVERT 0x0080L
+#define CBS_SORT 0x0100L
+#define CBS_HASSTRINGS 0x0200L
+#define CBS_NOINTEGRALHEIGHT 0x0400L
+#if (WINVER >= 0x030a)
+#define CBS_DISABLENOSCROLL 0x0800L
+#endif /* WINVER >= 0x030a */
+#endif /* NOWINSTYLES */
+
+/* Combo box messages */
+#ifndef NOWINMESSAGES
+#define CB_GETEDITSEL (WM_USER+0)
+#define CB_LIMITTEXT (WM_USER+1)
+#define CB_SETEDITSEL (WM_USER+2)
+#define CB_ADDSTRING (WM_USER+3)
+#define CB_DELETESTRING (WM_USER+4)
+#define CB_DIR (WM_USER+5)
+#define CB_GETCOUNT (WM_USER+6)
+#define CB_GETCURSEL (WM_USER+7)
+#define CB_GETLBTEXT (WM_USER+8)
+#define CB_GETLBTEXTLEN (WM_USER+9)
+#define CB_INSERTSTRING (WM_USER+10)
+#define CB_RESETCONTENT (WM_USER+11)
+#define CB_FINDSTRING (WM_USER+12)
+#define CB_SELECTSTRING (WM_USER+13)
+#define CB_SETCURSEL (WM_USER+14)
+#define CB_SHOWDROPDOWN (WM_USER+15)
+#define CB_GETITEMDATA (WM_USER+16)
+#define CB_SETITEMDATA (WM_USER+17)
+#if (WINVER >= 0x030a)
+#define CB_GETDROPPEDCONTROLRECT (WM_USER+18)
+#define CB_SETITEMHEIGHT (WM_USER+19)
+#define CB_GETITEMHEIGHT (WM_USER+20)
+#define CB_SETEXTENDEDUI (WM_USER+21)
+#define CB_GETEXTENDEDUI (WM_USER+22)
+#define CB_GETDROPPEDSTATE (WM_USER+23)
+#define CB_FINDSTRINGEXACT (WM_USER+24)
+#endif /* WINVER >= 0x030a */
+
+#endif /* NOWINMESSAGES */
+
+/* Combo box notification codes */
+#define CBN_ERRSPACE (-1)
+#define CBN_SELCHANGE 1
+#define CBN_DBLCLK 2
+#define CBN_SETFOCUS 3
+#define CBN_KILLFOCUS 4
+#define CBN_EDITCHANGE 5
+#define CBN_EDITUPDATE 6
+#define CBN_DROPDOWN 7
+#if (WINVER >= 0x030a)
+#define CBN_CLOSEUP 8
+#define CBN_SELENDOK 9
+#define CBN_SELENDCANCEL 10
+#endif /* WINVER >= 0x030a */
+
+/* Combo box message return values */
+#define CB_OKAY 0
+#define CB_ERR (-1)
+#define CB_ERRSPACE (-2)
+
+#endif /* NOCTLMGR */
+
+/******* Windows hook support **********************************************/
+
+#ifndef NOWH
+
+DECLARE_HANDLE32(HHOOK);
+
+#ifdef STRICT
+typedef LRESULT (CALLBACK* HOOKPROC)(int code, WPARAM wParam, LPARAM lParam);
+#else
+typedef FARPROC HOOKPROC;
+#endif
+
+#ifdef STRICT
+HHOOK WINAPI SetWindowsHook(int, HOOKPROC);
+LRESULT WINAPI DefHookProc(int, WPARAM, LPARAM, HHOOK FAR*);
+#else
+HOOKPROC WINAPI SetWindowsHook(int, HOOKPROC);
+LRESULT WINAPI DefHookProc(int, WPARAM, LPARAM, HOOKPROC FAR*);
+#endif
+BOOL WINAPI UnhookWindowsHook(int, HOOKPROC);
+
+#if (WINVER >= 0x030a)
+
+HHOOK WINAPI SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hInstance, HTASK hTask);
+BOOL WINAPI UnhookWindowsHookEx(HHOOK hHook);
+LRESULT WINAPI CallNextHookEx(HHOOK hHook, int code, WPARAM wParam, LPARAM lParam);
+
+#endif /* WINVER >= 0x030a */
+
+
+/* Standard hook code */
+#define HC_ACTION 0
+
+/* Obsolete hook codes (NO LONGER SUPPORTED) */
+#define HC_GETLPLPFN (-3)
+#define HC_LPLPFNNEXT (-2)
+#define HC_LPFNNEXT (-1)
+
+#endif /* NOWH */
+
+/****** Computer-based-training (CBT) support *******************************/
+
+#define WM_QUEUESYNC 0x0023
+
+#ifndef NOWH
+
+/* SetWindowsHook() code */
+#define WH_CBT 5
+
+#define HCBT_MOVESIZE 0
+#define HCBT_MINMAX 1
+#define HCBT_QS 2
+#define HCBT_CREATEWND 3
+#define HCBT_DESTROYWND 4
+#define HCBT_ACTIVATE 5
+#define HCBT_CLICKSKIPPED 6
+#define HCBT_KEYSKIPPED 7
+#define HCBT_SYSCOMMAND 8
+#define HCBT_SETFOCUS 9
+
+#if (WINVER >= 0x030a)
+/* HCBT_CREATEWND parameters pointed to by lParam */
+typedef struct tagCBT_CREATEWND
+{
+ CREATESTRUCT FAR* lpcs;
+ HWND hwndInsertAfter;
+} CBT_CREATEWND;
+typedef CBT_CREATEWND FAR* LPCBT_CREATEWND;
+
+/* HCBT_ACTIVATE structure pointed to by lParam */
+typedef struct tagCBTACTIVATESTRUCT
+{
+ BOOL fMouse;
+ HWND hWndActive;
+} CBTACTIVATESTRUCT;
+
+#endif /* WINVER >= 0x030a */
+#endif /* NOWH */
+
+/****** Hardware hook support ***********************************************/
+
+#ifndef NOWH
+#if (WINVER >= 0x030a)
+#define WH_HARDWARE 8
+
+typedef struct tagHARDWAREHOOKSTRUCT
+{
+ HWND hWnd;
+ UINT wMessage;
+ WPARAM wParam;
+ LPARAM lParam;
+} HARDWAREHOOKSTRUCT;
+#endif /* WINVER >= 0x030a */
+#endif /* NOWH */
+
+/****** Shell support *******************************************************/
+
+#ifndef NOWH
+#if (WINVER >= 0x030a)
+/* SetWindowsHook() Shell hook code */
+#define WH_SHELL 10
+
+#define HSHELL_WINDOWCREATED 1
+#define HSHELL_WINDOWDESTROYED 2
+#define HSHELL_ACTIVATESHELLWINDOW 3
+
+#endif /* WINVER >= 0x030a */
+#endif /* NOWH */
+
+/****** Journalling support *************************************************/
+
+#ifndef NOWH
+#define WH_JOURNALRECORD 0
+#define WH_JOURNALPLAYBACK 1
+
+/* Journalling hook codes */
+#define HC_GETNEXT 1
+#define HC_SKIP 2
+#define HC_NOREMOVE 3
+#define HC_NOREM HC_NOREMOVE
+#define HC_SYSMODALON 4
+#define HC_SYSMODALOFF 5
+
+/* Journalling message structure */
+typedef struct tagEVENTMSG
+{
+ UINT message;
+ UINT paramL;
+ UINT paramH;
+ DWORD time;
+} EVENTMSG;
+typedef EVENTMSG *PEVENTMSG;
+typedef EVENTMSG NEAR* NPEVENTMSG;
+typedef EVENTMSG FAR* LPEVENTMSG;
+
+BOOL WINAPI EnableHardwareInput(BOOL);
+
+#endif /* NOWH */
+
+
+/****** Debugger support ****************************************************/
+
+#if (WINVER >= 0x030a)
+/* SetWindowsHook debug hook support */
+#define WH_DEBUG 9
+
+typedef struct tagDEBUGHOOKINFO
+{
+ HMODULE hModuleHook;
+ LPARAM reserved;
+ LPARAM lParam;
+ WPARAM wParam;
+ int code;
+} DEBUGHOOKINFO;
+typedef DEBUGHOOKINFO FAR* LPDEBUGHOOKINFO;
+
+#ifndef NOMSG
+BOOL WINAPI QuerySendMessage(HANDLE h1, HANDLE h2, HANDLE h3, LPMSG lpmsg);
+#endif /* NOMSG */
+
+BOOL WINAPI LockInput(HANDLE h1, HWND hwndInput, BOOL fLock);
+
+LONG WINAPI GetSystemDebugState(void);
+/* Flags returned by GetSystemDebugState.
+ */
+#define SDS_MENU 0x0001
+#define SDS_SYSMODAL 0x0002
+#define SDS_NOTASKQUEUE 0x0004
+#define SDS_DIALOG 0x0008
+#define SDS_TASKLOCKED 0x0010
+#endif /* WINVER >= 0x030a */
+
+/****** Help support ********************************************************/
+
+#ifndef NOHELP
+
+BOOL WINAPI WinHelp(HWND hwndMain, LPCSTR lpszHelp, UINT usCommand, DWORD ulData);
+
+/* WinHelp() commands */
+#define HELP_CONTEXT 0x0001
+#define HELP_QUIT 0x0002
+#define HELP_INDEX 0x0003
+#define HELP_CONTENTS 0x0003
+#define HELP_HELPONHELP 0x0004
+#define HELP_SETINDEX 0x0005
+#define HELP_SETCONTENTS 0x0005
+#define HELP_CONTEXTPOPUP 0x0008
+#define HELP_FORCEFILE 0x0009
+#define HELP_KEY 0x0101
+#define HELP_COMMAND 0x0102
+#define HELP_PARTIALKEY 0x0105
+#define HELP_MULTIKEY 0x0201
+#define HELP_SETWINPOS 0x0203
+
+typedef struct tagMULTIKEYHELP
+{
+ UINT mkSize;
+ BYTE mkKeylist;
+ BYTE szKeyphrase[1];
+} MULTIKEYHELP;
+
+
+typedef struct
+{
+ int wStructSize;
+ int x;
+ int y;
+ int dx;
+ int dy;
+ int wMax;
+ char rgchMember[2];
+} HELPWININFO;
+typedef HELPWININFO NEAR* PHELPWININFO;
+typedef HELPWININFO FAR* LPHELPWININFO;
+
+#endif /* NOHELP */
+
+/****** Sound support ******************************************************/
+
+#ifndef NOSOUND
+
+int WINAPI OpenSound(void);
+void WINAPI CloseSound(void);
+
+int WINAPI StartSound(void);
+int WINAPI StopSound(void);
+
+int WINAPI SetVoiceQueueSize(int, int);
+int WINAPI SetVoiceNote(int, int, int, int);
+int WINAPI SetVoiceAccent(int, int, int, int, int);
+int WINAPI SetVoiceEnvelope(int, int, int);
+int WINAPI SetVoiceSound(int, DWORD, int);
+
+int WINAPI SetVoiceThreshold(int, int);
+int FAR* WINAPI GetThresholdEvent(void);
+int WINAPI GetThresholdStatus(void);
+
+int WINAPI SetSoundNoise(int, int);
+
+/* SetSoundNoise() Sources */
+#define S_PERIOD512 0
+#define S_PERIOD1024 1
+#define S_PERIOD2048 2
+#define S_PERIODVOICE 3
+#define S_WHITE512 4
+#define S_WHITE1024 5
+#define S_WHITE2048 6
+#define S_WHITEVOICE 7
+
+int WINAPI WaitSoundState(int);
+
+/* WaitSoundState() constants */
+#define S_QUEUEEMPTY 0
+#define S_THRESHOLD 1
+#define S_ALLTHRESHOLD 2
+
+int WINAPI SyncAllVoices(void);
+int WINAPI CountVoiceNotes(int);
+
+/* Accent Modes */
+#define S_NORMAL 0
+#define S_LEGATO 1
+#define S_STACCATO 2
+
+/* Error return values */
+#define S_SERDVNA (-1)
+#define S_SEROFM (-2)
+#define S_SERMACT (-3)
+#define S_SERQFUL (-4)
+#define S_SERBDNT (-5)
+#define S_SERDLN (-6)
+#define S_SERDCC (-7)
+#define S_SERDTP (-8)
+#define S_SERDVL (-9)
+#define S_SERDMD (-10)
+#define S_SERDSH (-11)
+#define S_SERDPT (-12)
+#define S_SERDFQ (-13)
+#define S_SERDDR (-14)
+#define S_SERDSR (-15)
+#define S_SERDST (-16)
+
+#endif /* NOSOUND */
+
+/****** Comm support ******************************************************/
+
+#ifndef NOCOMM
+
+#define NOPARITY 0
+#define ODDPARITY 1
+#define EVENPARITY 2
+#define MARKPARITY 3
+#define SPACEPARITY 4
+
+#define ONESTOPBIT 0
+#define ONE5STOPBITS 1
+#define TWOSTOPBITS 2
+
+#define IGNORE 0
+#define INFINITE 0xFFFF
+
+/* Error Flags */
+#define CE_RXOVER 0x0001
+#define CE_OVERRUN 0x0002
+#define CE_RXPARITY 0x0004
+#define CE_FRAME 0x0008
+#define CE_BREAK 0x0010
+#define CE_CTSTO 0x0020
+#define CE_DSRTO 0x0040
+#define CE_RLSDTO 0x0080
+#define CE_TXFULL 0x0100
+#define CE_PTO 0x0200
+#define CE_IOE 0x0400
+#define CE_DNS 0x0800
+#define CE_OOP 0x1000
+#define CE_MODE 0x8000
+
+#define IE_BADID (-1)
+#define IE_OPEN (-2)
+#define IE_NOPEN (-3)
+#define IE_MEMORY (-4)
+#define IE_DEFAULT (-5)
+#define IE_HARDWARE (-10)
+#define IE_BYTESIZE (-11)
+#define IE_BAUDRATE (-12)
+
+/* Events */
+#define EV_RXCHAR 0x0001
+#define EV_RXFLAG 0x0002
+#define EV_TXEMPTY 0x0004
+#define EV_CTS 0x0008
+#define EV_DSR 0x0010
+#define EV_RLSD 0x0020
+#define EV_BREAK 0x0040
+#define EV_ERR 0x0080
+#define EV_RING 0x0100
+#define EV_PERR 0x0200
+#define EV_CTSS 0x0400
+#define EV_DSRS 0x0800
+#define EV_RLSDS 0x1000
+#define EV_RingTe 0x2000
+#define EV_RINGTE EV_RingTe
+
+/* Escape Functions */
+#define SETXOFF 1
+#define SETXON 2
+#define SETRTS 3
+#define CLRRTS 4
+#define SETDTR 5
+#define CLRDTR 6
+#define RESETDEV 7
+
+#define LPTx 0x80
+
+#if (WINVER >= 0x030a)
+
+/* new escape functions */
+#define GETMAXLPT 8
+#define GETMAXCOM 9
+#define GETBASEIRQ 10
+
+/* Comm Baud Rate indices */
+#define CBR_110 0xFF10
+#define CBR_300 0xFF11
+#define CBR_600 0xFF12
+#define CBR_1200 0xFF13
+#define CBR_2400 0xFF14
+#define CBR_4800 0xFF15
+#define CBR_9600 0xFF16
+#define CBR_14400 0xFF17
+#define CBR_19200 0xFF18
+#define CBR_38400 0xFF1B
+#define CBR_56000 0xFF1F
+#define CBR_128000 0xFF23
+#define CBR_256000 0xFF27
+
+/* notifications passed in low word of lParam on WM_COMMNOTIFY messages */
+#define CN_RECEIVE 0x0001
+#define CN_TRANSMIT 0x0002
+#define CN_EVENT 0x0004
+
+#endif /* WINVER >= 0x030a */
+
+typedef struct tagDCB
+{
+ BYTE Id;
+ UINT BaudRate;
+ BYTE ByteSize;
+ BYTE Parity;
+ BYTE StopBits;
+ UINT RlsTimeout;
+ UINT CtsTimeout;
+ UINT DsrTimeout;
+
+ UINT fBinary :1;
+ UINT fRtsDisable :1;
+ UINT fParity :1;
+ UINT fOutxCtsFlow :1;
+ UINT fOutxDsrFlow :1;
+ UINT fDummy :2;
+ UINT fDtrDisable :1;
+
+ UINT fOutX :1;
+ UINT fInX :1;
+ UINT fPeChar :1;
+ UINT fNull :1;
+ UINT fChEvt :1;
+ UINT fDtrflow :1;
+ UINT fRtsflow :1;
+ UINT fDummy2 :1;
+
+ char XonChar;
+ char XoffChar;
+ UINT XonLim;
+ UINT XoffLim;
+ char PeChar;
+ char EofChar;
+ char EvtChar;
+ UINT TxDelay;
+} DCB;
+typedef DCB FAR* LPDCB;
+
+#if (defined(STRICT) | (WINVER >= 0x030a))
+
+typedef struct tagCOMSTAT
+{
+ BYTE status;
+ UINT cbInQue;
+ UINT cbOutQue;
+} COMSTAT;
+
+#define CSTF_CTSHOLD 0x01
+#define CSTF_DSRHOLD 0x02
+#define CSTF_RLSDHOLD 0x04
+#define CSTF_XOFFHOLD 0x08
+#define CSTF_XOFFSENT 0x10
+#define CSTF_EOF 0x20
+#define CSTF_TXIM 0x40
+
+#else /* (STRICT | WINVER >= 0x030a) */
+
+/* NOTE: This structure declaration is not ANSI compatible! */
+typedef struct tagCOMSTAT
+{
+ BYTE fCtsHold :1;
+ BYTE fDsrHold :1;
+ BYTE fRlsdHold :1;
+ BYTE fXoffHold :1;
+ BYTE fXoffSent :1;
+ BYTE fEof :1;
+ BYTE fTxim :1;
+ UINT cbInQue;
+ UINT cbOutQue;
+} COMSTAT;
+
+#endif /* !(STRICT | WINVER >= 0x030a */
+
+int WINAPI BuildCommDCB(LPCSTR, DCB FAR*);
+
+int WINAPI OpenComm(LPCSTR, UINT, UINT);
+int WINAPI CloseComm(int);
+
+int WINAPI ReadComm(int, void FAR*, int);
+int WINAPI WriteComm(int, const void FAR*, int);
+int WINAPI UngetCommChar(int, char);
+int WINAPI FlushComm(int, int);
+int WINAPI TransmitCommChar(int, char);
+
+int WINAPI SetCommState(const DCB FAR*);
+int WINAPI GetCommState(int, DCB FAR*);
+int WINAPI GetCommError(int, COMSTAT FAR* );
+
+int WINAPI SetCommBreak(int);
+int WINAPI ClearCommBreak(int);
+
+UINT FAR* WINAPI SetCommEventMask(int, UINT);
+UINT WINAPI GetCommEventMask(int, int);
+
+LONG WINAPI EscapeCommFunction(int, int);
+
+#if (WINVER >= 0x030a)
+BOOL WINAPI EnableCommNotification(int, HWND, int, int);
+
+#define WM_COMMNOTIFY 0x0044
+#endif /* WINVER >= 0x030a */
+
+#endif /* NOCOMM */
+
+/****** String formatting support *******************************************/
+
+int WINAPI wvsprintf(LPSTR lpszOut, LPCSTR lpszFmt, const void FAR* lpParams);
+
+int FAR CDECL wsprintf(LPSTR lpszOut, LPCSTR lpszFmt, ...);
+
+
+/****** Driver support ******************************************************/
+
+#if (WINVER >= 0x030a)
+
+#ifndef NODRIVERS
+
+DECLARE_HANDLE(HDRVR);
+
+typedef LRESULT (CALLBACK* DRIVERPROC)(DWORD, HDRVR, UINT, LPARAM, LPARAM);
+
+/* Driver messages */
+#define DRV_LOAD 0x0001
+#define DRV_ENABLE 0x0002
+#define DRV_OPEN 0x0003
+#define DRV_CLOSE 0x0004
+#define DRV_DISABLE 0x0005
+#define DRV_FREE 0x0006
+#define DRV_CONFIGURE 0x0007
+#define DRV_QUERYCONFIGURE 0x0008
+#define DRV_INSTALL 0x0009
+#define DRV_REMOVE 0x000A
+#define DRV_EXITSESSION 0x000B
+#define DRV_EXITAPPLICATION 0x000C
+#define DRV_POWER 0x000F
+
+#define DRV_RESERVED 0x0800
+#define DRV_USER 0x4000
+
+/* LPARAM of DRV_CONFIGURE message */
+typedef struct tagDRVCONFIGINFO
+{
+ DWORD dwDCISize;
+ LPCSTR lpszDCISectionName;
+ LPCSTR lpszDCIAliasName;
+} DRVCONFIGINFO;
+typedef DRVCONFIGINFO NEAR* PDRVCONFIGINFO;
+typedef DRVCONFIGINFO FAR* LPDRVCONFIGINFO;
+
+/* Supported return values for DRV_CONFIGURE message */
+#define DRVCNF_CANCEL 0x0000
+#define DRVCNF_OK 0x0001
+#define DRVCNF_RESTART 0x0002
+
+/* Supported lParam1 of DRV_EXITAPPLICATION notification */
+#define DRVEA_NORMALEXIT 0x0001
+#define DRVEA_ABNORMALEXIT 0x0002
+
+LRESULT WINAPI DefDriverProc(DWORD dwDriverIdentifier, HDRVR driverID, UINT message, LPARAM lParam1, LPARAM lParam2);
+
+HDRVR WINAPI OpenDriver(LPCSTR szDriverName, LPCSTR szSectionName, LPARAM lParam2);
+LRESULT WINAPI CloseDriver(HDRVR hDriver, LPARAM lParam1, LPARAM lParam2);
+
+LRESULT WINAPI SendDriverMessage(HDRVR hDriver, UINT message, LPARAM lParam1, LPARAM lParam2);
+
+HINSTANCE WINAPI GetDriverModuleHandle(HDRVR hDriver);
+
+HDRVR WINAPI GetNextDriver(HDRVR, DWORD);
+
+/* GetNextDriver flags */
+#define GND_FIRSTINSTANCEONLY 0x00000001
+
+#define GND_FORWARD 0x00000000
+#define GND_REVERSE 0x00000002
+
+typedef struct tagDRIVERINFOSTRUCT
+{
+ UINT length;
+ HDRVR hDriver;
+ HINSTANCE hModule;
+ char szAliasName[128];
+} DRIVERINFOSTRUCT;
+typedef DRIVERINFOSTRUCT FAR* LPDRIVERINFOSTRUCT;
+
+BOOL WINAPI GetDriverInfo(HDRVR, DRIVERINFOSTRUCT FAR*);
+
+#endif /* !NODRIVERS */
+#endif /* WINVER >= 0x030a */
+#endif /* NOUSER */
+
+#ifndef RC_INVOKED
+#pragma pack() /* Revert to default packing */
+#endif /* RC_INVOKED */
+
+#ifdef __cplusplus
+} /* End of extern "C" { */
+#endif /* __cplusplus */
+
+#endif /* _INC_WINDOWS */
diff --git a/private/ole32/olethunk/ole16/lib/makefile b/private/ole32/olethunk/ole16/lib/makefile
new file mode 100644
index 000000000..418fa24a1
--- /dev/null
+++ b/private/ole32/olethunk/ole16/lib/makefile
@@ -0,0 +1,18 @@
+
+all: ole2.lib compobj.lib storage.lib
+
+clean:
+ -del compobj.lib
+ -del storage.lib
+ -del ole2.lib
+
+IMPLIB = ..\tools\implib
+
+compobj.lib: ..\compobj\compobj.def
+ $(IMPLIB) -nologo compobj.lib ..\compobj\compobj.def
+
+storage.lib: ..\storage\storage.def
+ $(IMPLIB) -nologo storage.lib ..\storage\storage.def
+
+ole2.lib: ..\ole2\ole2.def
+ $(IMPLIB) -nologo ole2.lib ..\ole2\ole2.def
diff --git a/private/ole32/olethunk/ole16/makefil0 b/private/ole32/olethunk/ole16/makefil0
new file mode 100644
index 000000000..4b8d297ea
--- /dev/null
+++ b/private/ole32/olethunk/ole16/makefil0
@@ -0,0 +1,38 @@
+# INTEROP makefile
+#
+# Copyright (c) 1994, Microsoft Corporation
+#
+# History:
+# 28-Sep-1994 Terry Russell (terryru)
+#
+# If you add a new sub-component , make sure to add it in cleanup
+# section too.
+#
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.plt
+
+
+# Add the following line so 'default' will be built on
+# non-clean builds.
+default:
+
+
+clean:
+ cd .\lib
+ $(MAKE) OPST=chic clean
+ cd ..\coll
+ $(MAKE) OPST=chic clean
+ $(MAKE) OPST=dayt clean
+ cd ..\compobj
+ $(MAKE) OPST=chic clean
+ $(MAKE) OPST=dayt clean
+ cd ..\storage
+ $(MAKE) OPST=chic clean
+ $(MAKE) OPST=dayt clean
+ cd ..\ole2
+ $(MAKE) OPST=chic clean
+ $(MAKE) OPST=dayt clean
+ cd ..
+
+
diff --git a/private/ole32/olethunk/ole16/makefile.inc b/private/ole32/olethunk/ole16/makefile.inc
new file mode 100644
index 000000000..1b6f55ae8
--- /dev/null
+++ b/private/ole32/olethunk/ole16/makefile.inc
@@ -0,0 +1,358 @@
+# 16-bit makefile
+#
+# Copyright (c) 1991, Microsoft Corporation
+#
+# History:
+#
+# 18-Feb-1994 KevinRo
+# 24-Feb-1994 DrewB, added OBJDIR and some other niceties from win40.mk
+#
+
+.SUFFIXES:
+.SUFFIXES: .c .cxx .cpp .asm .h .inc .obj .lst
+.SUFFIXES: .sys .exe .com .map .sym .def .lib .rc .res
+
+!if "$(TARGET)" == ""
+!error TARGET must be defined
+!endif
+
+
+!if "$(OPST)" == ""
+!error OPSTR must be defined [chic|dayt]
+!endif
+
+
+
+OUTNUL= 1>nul 2>nul
+
+!if "$(NTDEBUG)" != "" && "$(NTDEBUG)" != "retail"
+OBJDIR = objd$(OPST)
+!else
+OBJDIR = objr$(OPST)
+!endif
+
+# Build up lists of files to produce from sources
+
+!if "$(CFILES)" != ""
+OBJFILES = $(OBJFILES) $(CFILES:.c=.obj)
+!endif
+!if "$(CXXFILES)" != ""
+OBJFILES = $(OBJFILES) $(CXXFILES:.cxx=.obj)
+!endif
+!if "$(CPPFILES)" != ""
+OBJFILES = $(OBJFILES) $(CPPFILES:.cpp=.obj)
+!endif
+
+!if "$(ASMFILES)" != ""
+OBJFILES = $(OBJFILES) $(ASMFILES:.asm=.obj)
+!endif
+
+!if "$(RCFILES)" != ""
+RESFILES = $(RCFILES:.rc=.res)
+!endif
+
+# Replace .\ with $(OBJDIR)
+# Unfortunately we can't do this directly so we have to explicitly check
+# the value of OBJDIR
+
+!if "$(OBJDIR)" == "objdchic"
+OBJFILES = $(OBJFILES:.\=objdchic\)
+RESFILES = $(RESFILES:.\=objdchic\)
+
+!elseif "$(OBJDIR)" == "objrchic"
+OBJFILES = $(OBJFILES:.\=objrchic\)
+RESFILES = $(RESFILES:.\=objrchic\)
+
+!elseif "$(OBJDIR)" == "objddayt"
+OBJFILES = $(OBJFILES:.\=objddayt\)
+RESFILES = $(RESFILES:.\=objddayt\)
+
+!elseif "$(OBJDIR)" == "objrdayt"
+OBJFILES = $(OBJFILES:.\=objrdayt\)
+RESFILES = $(RESFILES:.\=objrdayt\)
+
+!else
+!error Unknown OBJDIR: $(OBJDIR)
+!endif
+
+# Default target
+
+all: $(OBJDIR)\$(TARGET)
+
+# Determine target type and base name
+
+# Is it a DLL?
+TARGETBASE=$(TARGET:.dll=)
+!if "$(TARGETBASE)" != "$(TARGET)"
+TARGETTYPE=dll
+!else
+
+# Is it an EXE?
+TARGETBASE=$(TARGET:.exe=)
+! if "$(TARGETBASE)" != "$(TARGET)"
+TARGETTYPE=exe
+! else
+
+# Is it a LIB?
+TARGETBASE=$(TARGET:.lib=)
+! if "$(TARGETBASE)" != "$(TARGET)"
+TARGETTYPE=lib
+! endif
+! endif
+!endif
+
+!if "$(TARGETTYPE)" == ""
+!error Unknown target type for "$(TARGET)"
+!endif
+
+!if "$(BUILDDETAILS)" != ""
+BLDKEEP= KEEP
+!endif
+BLDKEEP= KEEP
+
+OLETHUNK= $(_NTDRIVE)$(_NTROOT)\private\ole32\olethunk
+OLE16= $(OLETHUNK)\ole16
+
+!if "$(OPST)" == "chic"
+RCINC = $(RCINC) -i..\inc\chicago -i..\inc
+!else
+RCINC = $(RCINC) -i$(OLE16)\inc
+!endif
+INCS = -I$(OLE16)\inc -I$(OLETHUNK)\h -I$(_NTDRIVE)$(_NTROOT)\private\cinc
+
+
+PATH = $(OLE16)\tools;$(PATH)
+LINK = link16
+#
+# We need to mark our Windows 95 components as version 4.0.
+#
+!if "$(OPST)" == "chic"
+RCT = rc_chic -40
+!else
+RCT = rc16
+!endif
+RC = rc16
+CL = cl16
+IMPLIB = implib
+LIBUTIL = lib16
+MAPSYM = mapsym
+MASM = masm
+
+DEFINES = $(DEFINES) -DWOW
+
+AOBJ = -Mx -t $(DEFINES) $(INCS)
+
+!if "$(TARGETTYPE)" == "exe"
+CW16 = -GA
+!else
+CW16 = -GD
+DEFINES = $(DEFINES) -D_WINDLL
+!endif
+
+CW16 = $(CW16) -G2 -Alfw $(DEFINES) $(INCS) /NMSEG_CODE
+
+LFLAGS = $(LFLAGS) /nod /noe /map:0 /align:16
+
+!if "$(NTDEBUG)" != "" && "$(NTDEBUG)" != "retail"
+
+DEFINES = $(DEFINES) -DDBG=1 -DDEVL=1
+
+!if ("$(NTDEBUGTYPE)" == "windbg") || ("$(NTDEBUGTYPE)" == "both")
+AOBJ = $(AOBJ) -Zi
+CW16 = $(CW16) /Odi /Zip -DDBG=1 -DDEVL=1
+LFLAGS = $(LFLAGS) /CO
+!else
+AOBJ = $(AOBJ) -Zd
+CW16 = $(CW16) /Odi /Zd
+LFLAGS = $(LFLAGS) /LI
+!endif
+
+!else
+CW16 = $(CW16) /Os /Zp /Gs -DDBG=0 -DDEVL=1
+DEFINES = $(DEFINES) -DDBG=0 -DDEVL=1
+!endif
+
+!if "$(TARGETTYPE)" == "dll"
+W16LIBS = $(OLE16)\lib\ldllcew.lib
+!else
+!if "$(QUICKWINDOWS)" != ""
+W16LIBS = $(OLE16)\lib\llibcewq.lib
+!else
+W16LIBS = $(OLE16)\lib\llibcew.lib
+!endif
+!endif
+
+W16LIBS = $(W16LIBS) $(OLE16)\lib\libw.lib
+
+!if "$(TARGETTYPE)" == "dll" || "$(TARGETTYPE)" == "exe"
+LIBS = $(LIBS) $(W16LIBS)
+!endif
+
+.asm{$(OBJDIR)}.obj:
+ @-md $(OBJDIR) $(OUTNUL)
+ $(MASM) $(AOBJ) $*,$*;
+
+.asm.lst:
+ @-md $(OBJDIR) $(OUTNUL)
+ $(MASM) $(AOBJ) -l $*,nul,$*.lst;
+
+
+.c{$(OBJDIR)}.obj:
+ @-md $(OBJDIR) $(OUTNUL)
+ $(CL) -c -nologo @<<$*.rsp
+$(CW16: =
+)
+-Fo$*.obj
+$<
+<<$(BLDKEEP)
+
+.c.lst:
+ @-md $(OBJDIR) $(OUTNUL)
+ $(CL) -c -nologo @<<$(OBJDIR)\$*.rsp
+$(CW16: =
+)
+-Fonul
+-Fc$*.lst
+$<
+<<$(BLDKEEP)
+
+.cxx{$(OBJDIR)}.obj:
+ @-md $(OBJDIR) $(OUTNUL)
+ $(CL) -c -nologo @<<$*.rsp
+$(CW16: =
+)
+-Fo$*.obj
+-Tp$<
+<<$(BLDKEEP)
+
+.cxx.lst:
+ @-md $(OBJDIR) $(OUTNUL)
+ $(CL) -c -nologo @<<$(OBJDIR)\$*.rsp
+$(CW16: =
+)
+-Fc$*.lst
+-Fonul
+-Tp$<
+<<$(BLDKEEP)
+
+.cxx.pp:
+ @-md $(OBJDIR) $(OUTNUL)
+ $(CL) -c -nologo @<<$(OBJDIR)\$*.rsp > $*.pp
+$(CW16: =
+)
+-E
+-Fonul
+-Tp$<
+<<$(BLDKEEP)
+
+
+.cpp{$(OBJDIR)}.obj:
+ @-md $(OBJDIR) $(OUTNUL)
+ $(CL) -c -nologo @<<$*.rsp
+$(CW16: =
+)
+-Fo$*.obj
+-Tp$<
+<<$(BLDKEEP)
+
+.cpp.lst:
+ @-md $(OBJDIR) $(OUTNUL)
+ $(CL) -c -nologo @<<$(OBJDIR)\$*.rsp
+$(CW16: =
+)
+-Fc$*.lst
+-Fonul
+-Tp$<
+<<$(BLDKEEP)
+
+.cpp.pp:
+ @-md $(OBJDIR) $(OUTNUL)
+ $(CL) -c -nologo @<<$(OBJDIR)\$*.rsp > $*.pp
+$(CW16: =
+)
+-E
+-Fonul
+-Tp$<
+<<$(BLDKEEP)
+
+
+.def{$(OBJDIR)}.lib:
+ @-md $(OBJDIR) $(OUTNUL)
+ $(IMPLIB) $*.lib $<
+
+{$(OBJDIR)}.map{$(OBJDIR)}.sym:
+ @-md $(OBJDIR) $(OUTNUL)
+ $(MAPSYM) $<
+
+.rc{$(OBJDIR)}.res:
+ @-md $(OBJDIR) $(OUTNUL)
+ $(RC) -r $(RCINC) -fo $*.res $<
+
+
+cleanup:
+ if exist $(OBJDIR)\*.lrf del $(OBJDIR)\*.lrf
+ if exist $(OBJDIR)\*.obj del $(OBJDIR)\*.obj
+ if exist $(OBJDIR)\*.exe del $(OBJDIR)\*.exe
+ if exist $(OBJDIR)\*.map del $(OBJDIR)\*.map
+ if exist $(OBJDIR)\*.sym del $(OBJDIR)\*.sym
+ if exist $(OBJDIR)\*.res del $(OBJDIR)\*.res
+
+clean: cleanup
+
+!if "$(TARGETTYPE)" == "dll"
+
+$(OBJDIR)\$(TARGETBASE).lib: $(TARGETBASE).def
+
+$(OBJDIR)\$(TARGET) $(OBJDIR)\$(TARGETBASE).map: $(OBJFILES) $(RESFILES) \
+ $(TARGETBASE).def $(OBJDIR)\$(TARGETBASE).lib $(LIBS)
+ @-md $(OBJDIR) $(OUTNUL)
+ $(LINK) $(LFLAGS) @<<$(OBJDIR)\$(TARGETBASE).rsp
+$(OBJFILES: =+^
+)
+$(OBJDIR)\$(TARGET)
+$(OBJDIR)\$(TARGETBASE).map
+$(LIBS: =+^
+)
+$(TARGETBASE).def
+<<$(BLDKEEP)
+ $(MAPSYM) -o $(OBJDIR)\$(TARGETBASE).sym $(OBJDIR)\$(TARGETBASE).map
+!if "$(RCFILES)" != ""
+ $(RCT) -t $(OBJDIR)\$(TARGETBASE).res $(OBJDIR)\$(TARGET)
+!endif
+
+!elseif "$(TARGETTYPE)" == "lib"
+
+$(OBJDIR)\$(TARGET): $(OBJFILES) $(LIBS)
+ @-md $(OBJDIR) $(OUTNUL)
+ -del $@ $(OUTNUL)
+ $(LIBUTIL) @<<$*.lnb
+$(OBJDIR)\$(TARGET)
+y
+$(OBJFILES: = &^
+)&
+$(LIBS: = &^
+)&
+
+$*.lls
+<<$(BLDKEEP)
+
+!elseif "$(TARGETTYPE)" == "exe"
+
+$(OBJDIR)\$(TARGET) $(OBJDIR)\$(TARGETBASE).map: $(OBJFILES) $(RESFILES) \
+ $(TARGETBASE).def $(LIBS)
+ @-md $(OBJDIR) $(OUTNUL)
+ $(LINK) $(LFLAGS) @<<$(OBJDIR)\$(TARGETBASE).rsp
+$(OBJFILES: =+^
+)
+$(OBJDIR)\$(TARGET)
+$(OBJDIR)\$(TARGETBASE).map
+$(LIBS: =+^
+)
+$(TARGETBASE).def
+<<$(BLDKEEP)
+!if "$(RCFILES)" != ""
+ $(RCT) -t $(OBJDIR)\$(TARGETBASE).res $(OBJDIR)\$(TARGET)
+!endif
+ $(MAPSYM) -o $(OBJDIR)\$(TARGETBASE).sym $(OBJDIR)\$(TARGETBASE).map
+
+!endif
diff --git a/private/ole32/olethunk/ole16/ole2/cdebug.cxx b/private/ole32/olethunk/ole16/ole2/cdebug.cxx
new file mode 100644
index 000000000..24d62c086
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/cdebug.cxx
@@ -0,0 +1,1044 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: OleAPIs.cxx (16 bit target)
+//
+// Contents: OLE2 APIs
+//
+// Functions:
+//
+// History: 17-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+// cdebug.cpp - implemention of debugstream and IDebug interface/class
+/*
+#include <olerem.h> //for RemLookupSHUnk
+
+#pragma SEG(cdebug)
+#include <string.h>
+#include <toolhelp.h>
+*/
+
+//some constants used only in this file
+#define DBGMARGIN 45
+#define DBGTABSIZE 4
+#define HEADER 1
+#define NOHEADER 0
+
+
+#define DBGLOGFILENAME "debug.log"
+static void GetCurDateTime(LPSTR lpsz);
+
+
+STDAPI_(HFILE) DbgLogOpen(LPSTR lpszFile, LPSTR lpszMode)
+{
+#ifdef _DEBUG
+#ifndef _MAC
+ HFILE fh;
+
+ AssertSz( lpszFile && lpszMode, "Invalid arguments to DbgLogOpen");
+
+ switch (lpszMode[0]) {
+ case 'w':
+ // Open for writing (overwrite if exists)
+ fh = _lcreat(lpszFile, 0);
+ break;
+
+ case 'r':
+ // Open for reading
+ fh = _lopen(lpszFile, OF_READ);
+ break;
+
+ case 'a':
+ // Open for appending
+ // to append to log file seek to end before writing
+ if ((fh = _lopen(lpszFile, OF_READWRITE)) != -1) {
+ _llseek(fh, 0L, SEEK_END);
+ } else {
+ // file does not exist, create a new one.
+ fh = _lcreat(lpszFile, 0);
+ }
+ break;
+ }
+ return fh;
+#endif //_MAC
+#else
+ (void) lpszFile;
+ (void) lpszMode;
+ return -1;
+#endif //_DEBUG
+}
+
+
+STDAPI_(void) DbgLogClose(HFILE fh)
+{
+#ifdef _DEBUG
+#ifndef _MAC
+ if (fh != -1)
+ _lclose(fh);
+#endif
+#else
+ (void) fh;
+#endif
+}
+
+
+STDAPI_(void) DbgLogWrite(HFILE fh, LPSTR lpsz)
+{
+#ifdef _DEBUG
+#ifndef _MAC
+ if (fh != -1 && lpsz)
+ _lwrite(fh, lpsz, lstrlen(lpsz));
+#endif
+#else
+ (void) fh;
+ (void) lpsz;
+#endif
+}
+
+
+STDAPI_(void) DbgLogTimeStamp(HFILE fh, LPSTR lpsz)
+{
+#ifdef _DEBUG
+ char buffer[80];
+
+ GetCurDateTime(buffer);
+
+ DbgLogOutputDebugString(fh, "\n***************************************\n");
+ if (lpsz) DbgLogOutputDebugString(fh, lpsz);
+ DbgLogOutputDebugString(fh, ": ");
+ DbgLogOutputDebugString(fh, buffer);
+ DbgLogOutputDebugString(fh, "\n");
+ DbgLogOutputDebugString(fh, ".......................................\n\n");
+#else
+ (void) fh;
+ (void) lpsz;
+#endif
+}
+
+
+STDAPI_(void) DbgLogWriteBanner(HFILE fh, LPSTR lpsz)
+{
+#ifdef _DEBUG
+ DbgLogOutputDebugString(fh, "\n***************************************\n");
+ if (lpsz) DbgLogOutputDebugString(fh, lpsz);
+ DbgLogOutputDebugString(fh, "\n");
+ DbgLogOutputDebugString(fh, ".......................................\n\n");
+#else
+ (void) fh;
+ (void) lpsz;
+#endif
+}
+
+
+STDAPI_(void) DbgLogOutputDebugString(HFILE fh, LPSTR lpsz)
+{
+#ifdef _DEBUG
+#ifndef _MAC
+ if (fh != -1)
+ DbgLogWrite(fh, lpsz);
+ OutputDebugString(lpsz);
+#endif
+#else
+ (void)fh;
+ (void)lpsz;
+#endif
+}
+
+
+#ifdef _DEBUG
+
+static void GetCurDateTime(LPSTR lpsz)
+{
+ unsigned year, month, day, dayOfweek, hours, min, sec;
+ static char FAR* dayNames[7] =
+ { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+ static char FAR* monthNames[12] =
+ { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+#ifndef _MAC
+#ifdef WIN32
+ SYSTEMTIME st;
+ GetLocalTime(&st);
+ year = st.wYear;
+ month = st.wMonth - 1;
+ dayOfweek = st.wDayOfWeek;
+ day = st.wDay;
+ hours = st.wHour;
+ min = st.wMinute;
+ sec = st.wSecond;
+#else
+ _asm {
+ // Call GetDate
+ mov ah, 0x2a
+ int 0x21
+ mov year, cx
+ mov month, dx
+ mov day, dx
+ mov dayOfweek, ax
+
+ // Call GetTime
+ mov ah, 0x2c
+ int 0x21
+ mov hours, cx
+ mov min, cx
+ mov sec, dx
+ }
+
+ month >>= 8;
+ month -= 1;
+ day &= 0xFF;
+ dayOfweek &= 0xFF;
+ hours >>= 8;
+ min &= 0xFF;
+ sec >>= 8;
+#endif //_WIN32
+#else // defined(_MAC)
+
+ // REVIEW MAC -- need function here to get current date & time
+ day = 9;
+ month = 1;
+ year = 1960;
+ hours = 12;
+ min = 30;
+ sec = 17;
+
+#endif //_MAC
+
+ // Format time as: Wed Jan 02 02:03:55 1990
+ // Format time as: Wed 05/02/1992 02:03:55
+
+ wsprintf(lpsz, "%s %s %02d %02d:%02d:%02d %d",
+ dayNames[dayOfweek],monthNames[month], day, hours, min, sec, year);
+}
+
+
+class FAR CDebugLog
+{
+private:
+ HFILE m_fhLog;
+
+public:
+ CDebugLog( ) { m_fhLog = -1; }
+ CDebugLog( LPSTR lpszFileName );
+ ~CDebugLog() { DbgLogClose(m_fhLog); }
+ HFILE Open(LPSTR lpszFileName, LPSTR lpszMode)
+ { return (m_fhLog = DbgLogOpen(lpszFileName, lpszMode)); }
+ void Close(void) { DbgLogClose(m_fhLog); m_fhLog = -1; }
+ void OutputDebugString(LPSTR lpsz) { DbgLogOutputDebugString(m_fhLog, lpsz); }
+ void TimeStamp(LPSTR lpsz) { DbgLogTimeStamp(m_fhLog, lpsz); }
+ void WriteBanner(LPSTR lpsz) { DbgLogWriteBanner(m_fhLog, lpsz); }
+
+};
+
+#if 0
+
+class FAR CDebugStream
+{
+
+public:
+ OLESTATIC_(IDebugStream FAR *) Create( // no aggregation
+ int margin, int tabsize, BOOL fHeader);
+
+private:
+ CDebugStream( int margin, int tabsize, BOOL fHeader );
+ ~CDebugStream();
+ void OutputDebugString( LPSTR lpsz ) {m_DbgLog.OutputDebugString(lpsz);}
+
+
+implementations:
+ implement CDSImpl : IDebugStream
+ {
+
+ public:
+ CDSImpl( CDebugStream FAR * pDebugStream )
+ { m_pDebugStream = pDebugStream; }
+ ~CDSImpl( void ) ; //{ if (m_pDebugStream->m_pendingReturn) ForceReturn(); }
+ void PrintString( LPSTR );
+ void ForceReturn( void );
+ void ReturnIfPending( void );
+ OLEMETHOD(QueryInterface)(REFIID iid, LPVOID FAR* ppvObj );
+ OLEMETHOD_(ULONG,AddRef)( void );
+ OLEMETHOD_(ULONG,Release)( void );
+
+ OLEMETHOD_(IDebugStream&, operator << ) ( IUnknown FAR * pDebug );
+ OLEMETHOD_(IDebugStream&, operator << ) ( REFCLSID rclsid );
+ OLEMETHOD_(IDebugStream&, operator << ) ( int n );
+ OLEMETHOD_(IDebugStream&, operator << ) ( long l );
+ OLEMETHOD_(IDebugStream&, operator << ) ( ULONG l );
+ OLEMETHOD_(IDebugStream&, operator << ) ( LPSTR sz );
+ OLEMETHOD_(IDebugStream&, operator << ) ( char ch );
+ OLEMETHOD_(IDebugStream&, operator << ) ( void FAR * pv );
+ OLEMETHOD_(IDebugStream&, operator << ) ( CBool b );
+ OLEMETHOD_(IDebugStream&, operator << ) ( CAtom atom );
+ OLEMETHOD_(IDebugStream&, operator << ) ( CHwnd hwnd );
+ OLEMETHOD_(IDebugStream&, Tab) ( void );
+ OLEMETHOD_(IDebugStream&, Indent) ( void );
+ OLEMETHOD_(IDebugStream&, UnIndent) ( void );
+ OLEMETHOD_(IDebugStream&, Return) ( void );
+ OLEMETHOD_(IDebugStream&, LF) ( void );
+ CDebugStream FAR * m_pDebugStream;
+ };
+ DECLARE_NC(CDebugStream,CDSImpl)
+
+ CDSImpl m_DebugStream;
+
+shared_state:
+ ULONG m_refs;
+ int m_indent;
+ int m_position;
+ int m_margin;
+ int m_tabsize;
+ BOOL m_pendingReturn;
+ CDebugLog m_DbgLog;
+};
+#endif
+
+#endif // _DEBUG
+
+
+
+/*
+ * The member variable m_pendingReturn is a hack to allow
+ * the sequence of operations Return, UnIndent put the character
+ * at the *beginning of the unindented line* The debugwindow does
+ * not seem to support going to the beginning of the line or
+ * backspacing, so we do not actually do a Return until we know
+ * that the next operation is not UnIndent.
+ *
+ */
+
+
+
+/*
+ * Implementation of per process list heads
+ */
+
+#ifdef NEVER // per-proces debug lists not used
+
+static IDebug FAR * GetIDHead()
+{
+ if this gets enabled, the map should be in the etask
+}
+
+static void SetIDHead(IDebug FAR* pIDHead)
+{
+ if this gets enabled, the map should be in the etask
+}
+
+#endif // NEVER
+
+
+/*
+ * Implementation of IDebug constructor and destructor
+ */
+
+
+#ifdef NEVER
+__export IDebug::IDebug( void )
+{
+ SETPVTBL(IDebug);
+//#ifdef _DEBUG
+ BOOL fIsShared = (SHARED == PlacementOf(this));
+ IDebug FAR* pIDHead = (fIsShared ? pIDHeadShared : GetIDHead());
+
+ pIDPrev = NULL;
+ if (pIDHead)
+ pIDHead->pIDPrev = this;
+ pIDNext = pIDHead;
+ if (fIsShared) pIDHeadShared = this;
+ else SetIDHead(this);
+}
+#endif //NEVER
+
+
+#ifdef NEVER
+__export IDebug::~IDebug( void )
+{
+//#ifdef _DEBUG
+ BOOL fIsShared = (SHARED == PlacementOf(this));
+ if (pIDPrev)
+ pIDPrev->pIDNext = pIDNext;
+ else
+ if (fIsShared) pIDHeadShared = pIDNext;
+ else
+ SetIDHead(pIDNext);
+ if (pIDNext)
+ pIDNext->pIDPrev = pIDPrev;
+}
+#endif //NEVER
+
+//REVIEW: maybe we should expose this later
+STDAPI OleGetClassID( LPUNKNOWN pUnk, LPCLSID lpclsid )
+{
+ HRESULT hresult = NOERROR;
+#if 0
+ LPRUNNABLEOBJECT lpRunnableObject = NULL;
+ LPPERSIST lpPersist = NULL;
+
+ VDATEIFACE(pUnk);
+ VDATEPTROUT(lpclsid, LPCLSID);
+
+ *lpclsid = CLSID_NULL;
+
+ pUnk->QueryInterface(IID_IRunnableObject, (LPLPVOID)&lpRunnableObject);
+ if( lpRunnableObject ){
+ hresult = lpRunnableObject->GetRunningClass(lpclsid);
+ lpRunnableObject->Release();
+ } else {
+ pUnk->QueryInterface(IID_IPersist, (LPLPVOID)&lpPersist);
+ if( lpPersist ){
+ hresult = lpPersist->GetClassID( lpclsid );
+ lpPersist->Release();
+ }
+ }
+#endif
+ return hresult;
+}
+
+#ifdef _DEBUG
+
+CDebugStream::CDebugStream( int margin, int tabsize, BOOL fHeader) : m_DebugStream(this)
+{
+#ifndef _MAC
+ static BOOL fAppendFile = FALSE;
+
+ // Create the debug log file. Overwrite the existing file if it exists.
+ m_DbgLog.Open(DBGLOGFILENAME, (fAppendFile ? "a" : "w"));
+
+ if( fHeader )
+ // only add creation timestamp to top of file.
+ if (! fAppendFile) {
+ m_DbgLog.TimeStamp("Created");
+ fAppendFile = TRUE;
+ } else {
+ m_DbgLog.WriteBanner(NULL);
+ }
+#endif
+ m_indent = 0;
+ m_position = m_indent;
+ m_margin = margin;
+ m_tabsize = tabsize;
+ m_refs = 1;
+ m_pendingReturn = FALSE;
+}
+
+
+CDebugStream::~CDebugStream()
+{
+ m_DbgLog.Close();
+}
+
+
+NC(CDebugStream,CDSImpl)::~CDSImpl(void)
+{
+ if (m_pDebugStream->m_pendingReturn) ForceReturn();
+}
+
+
+OLEMETHODIMP NC(CDebugStream,CDSImpl)::QueryInterface(REFIID iidInterface,
+ void FAR* FAR* ppvObj )
+{
+ VDATEPTROUT(ppvObj, LPLPVOID);
+
+ if (iidInterface == IID_IUnknown || iidInterface == IID_IDebugStream) {
+ *ppvObj = (void FAR *)this;
+ return NOERROR;
+ } else {
+ *ppvObj = NULL;
+ return ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+}
+
+
+OLEMETHODIMP_(ULONG) NC(CDebugStream,CDSImpl)::AddRef( void )
+{
+ return ++m_pDebugStream->m_refs;
+}
+
+
+OLEMETHODIMP_(ULONG) NC(CDebugStream,CDSImpl)::Release( void )
+{
+ if (--m_pDebugStream->m_refs == 0) {
+ delete m_pDebugStream;
+ return 0;
+ }
+
+ return m_pDebugStream->m_refs;
+}
+
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (int n)
+{
+ char buffer[12];
+ ReturnIfPending();
+ buffer[wsprintf(buffer, "%d", n)] = '\0';
+ PrintString(buffer);
+ return *this;
+}
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (long l)
+{
+ char buffer[16];
+ ReturnIfPending();
+ buffer[wsprintf(buffer, "%ld", l)] = '\0';
+ PrintString(buffer);
+ return *this;
+}
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (ULONG l)
+{
+ char buffer[16];
+ ReturnIfPending();
+ buffer[wsprintf(buffer, "%lu", l)] = '\0';
+ PrintString(buffer);
+ return *this;
+}
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (CAtom atom)
+{
+ char buffer[128];
+ ReturnIfPending();
+
+ if( (ATOM)atom ){
+ if( !GetAtomName((ATOM)atom, (LPSTR)buffer, sizeof(buffer)) )
+ buffer[wsprintf(buffer, "Invalid atom")] = '\0';
+ }else
+ buffer[wsprintf(buffer, "NULL atom")] = '\0';
+
+ PrintString(buffer);
+ return *this;
+}
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (CHwnd hwnd)
+{
+ char szBuf[128];
+
+ ReturnIfPending();
+
+ if( (HWND)hwnd )
+ szBuf[wsprintf(szBuf, "window handle: %x", (HWND)hwnd)] = '\0';
+ else
+ szBuf[wsprintf(szBuf, "NULL window handle")] = '\0';
+
+ PrintString(szBuf);
+ return *this;
+}
+
+LPSTR FindBreak( LPSTR sz, int currentPosition, int margin )
+{
+ LPSTR szBreak = sz;
+ LPSTR szPtr = sz;
+
+ if( !sz )
+ return NULL;
+
+ while (*szPtr)
+ {
+ while (*(szPtr) && *(szPtr++) <= ' ');
+ while (*(szPtr) && *(szPtr++) > ' ');
+ if (currentPosition+(szPtr-sz) < margin)
+ {
+ szBreak = szPtr;
+ }
+ else return szBreak;
+ }
+ return szPtr;
+}
+
+/*
+ * PrintString is an internal utility routine that can assume that
+ * everything in the string (other than the null at the end) is >=
+ * ' '. Thus it knows that when it prints a single character, the
+ * position on the debug terminal advances a single columm. This
+ * would not be the case if the string could contain tabs,
+ * returns, etc.
+ */
+
+
+void NC(CDebugStream,CDSImpl)::PrintString (LPSTR sz)
+{
+ // assert sz != NULL
+ LPSTR szUnprinted = sz;
+ LPSTR szPtr = sz;
+ char chSave;
+
+ #ifdef _MAC
+ Puts(sz);
+ return;
+ #endif
+
+ if( !sz )
+ return;
+
+ while (*szUnprinted)
+ {
+ szPtr = FindBreak( szUnprinted, m_pDebugStream->m_position, m_pDebugStream->m_margin );
+ if (szPtr == szUnprinted && m_pDebugStream->m_position > m_pDebugStream->m_indent)
+ {
+ Return();
+ szPtr = FindBreak( szUnprinted, m_pDebugStream->m_position, m_pDebugStream->m_margin );
+ if (szPtr == szUnprinted) // text won't fit even after word wrapping
+ {
+ m_pDebugStream->OutputDebugString(szUnprinted);
+ m_pDebugStream->m_position += _fstrlen(szUnprinted);
+ return;
+ }
+ }
+ chSave = *szPtr;
+ *szPtr = '\0';
+ if (m_pDebugStream->m_position == m_pDebugStream->m_indent) // no text on line, skip blanks
+ {
+ while (*szUnprinted == ' ') szUnprinted++;
+ }
+ m_pDebugStream->OutputDebugString(szUnprinted);
+ *szPtr = chSave;
+ m_pDebugStream->m_position += (szPtr - szUnprinted);
+ szUnprinted = szPtr;
+ }
+}
+
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (char ch)
+{
+ char buffer[2] = "a";
+ if (ch=='\n') Return();
+ else if (ch=='\t') Tab();
+ else if (ch >= ' ')
+ {
+ ReturnIfPending();
+ if (m_pDebugStream->m_position >= m_pDebugStream->m_margin) Return();
+ *buffer = ch;
+ m_pDebugStream->OutputDebugString(buffer);
+ m_pDebugStream->m_position++;
+ }
+ return *this;
+}
+
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (LPSTR sz)
+{
+ LPSTR szCopy;
+ char chSave;
+ LPSTR szPtr;
+ LPSTR szPtrSave;
+
+ ReturnIfPending();
+
+ if (!sz)
+ return *this;
+
+ szCopy = new FAR (TASK) char[2+_fstrlen(sz)];
+ if (!szCopy)
+ {
+ Return();
+ PrintString("Memory allocation error in DebugStream");
+ Return();
+ return *this;
+ }
+
+ _fstrcpy( szCopy, sz );
+ for (szPtr = szCopy, szPtrSave = szCopy; *szPtr; szPtr++)
+ {
+ if ( *szPtr < ' ') // we hit a control character or the end
+ {
+ chSave = *szPtr;
+ *szPtr = '\0';
+ PrintString( szPtrSave );
+ if (chSave != '\0')
+ *szPtr = chSave;
+ szPtrSave = szPtr+1;
+ switch (chSave)
+ {
+ case '\t': Tab();
+ break;
+ case '\n': Return();
+ break;
+ case '\r': m_pDebugStream->OutputDebugString("\r");
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ PrintString( szPtrSave );
+
+ delete szCopy;
+
+ return *this;
+}
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << (CBool b)
+{
+ ReturnIfPending();
+ if (b) PrintString("TRUE");
+ else PrintString("FALSE");
+ return *this;
+}
+
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator << ( void FAR * pv )
+{
+ char buffer[12];
+ LPSTR sz = "NULL";
+ ReturnIfPending();
+ if (pv != NULL)
+ {
+ buffer[wsprintf(buffer, "%lX", pv)] = '\0';
+ sz = buffer;
+ }
+ PrintString(sz);
+ return *this;
+}
+
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator <<
+ ( REFCLSID rclsid )
+{
+ char sz[256];
+
+ // REVIEW: do lookup in reg.dat for user type name
+
+ if( rclsid == CLSID_NULL )
+ _fstrcpy(sz, "NULL CLSID");
+ else if (StringFromCLSID2(rclsid, sz, sizeof(sz)) == 0)
+ _fstrcpy(sz, "Unknown CLSID");
+
+ *this << sz;
+
+ return *this;
+}
+
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::operator <<
+ ( IUnknown FAR * pUnk )
+{
+ IDebug FAR * pDebug = NULL;
+ CLSID clsid = CLSID_NULL;
+
+ ReturnIfPending();
+
+ if( IsValidInterface(pUnk) ){
+ pUnk->QueryInterface(IID_IDebug, (void FAR* FAR*)&pDebug);
+ if (pDebug) {
+ pDebug->Dump( this );
+ if ( !pDebug->IsValid( 0 ) )
+ *this << "Object is not valid" << '\n';
+ /*
+ * NB: Debug interfaces are *not* ref counted (so as not to skew the
+ * counts of the objects they are debugging! :)
+ */
+ } else {
+ OleGetClassID(pUnk, (LPCLSID)&clsid);
+ *this << clsid << " @ "<<(VOID FAR *)pUnk << " doesn't support debug dumping";
+ }
+ } else if (!pUnk)
+ *this << "NULL interface";
+ else
+ *this << "Invalid interface @ " << (VOID FAR *)pUnk;
+
+ return *this;
+}
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::Tab( void )
+{
+ ReturnIfPending();
+ int advance = m_pDebugStream->m_tabsize * ( 1 + m_pDebugStream->m_position/m_pDebugStream->m_tabsize) - m_pDebugStream->m_position;
+
+ if (m_pDebugStream->m_position + advance < m_pDebugStream->m_margin)
+ {
+ for (int i = 0; i < advance; i++)
+ m_pDebugStream->OutputDebugString(" ");
+ m_pDebugStream->m_position += advance;
+ }
+ return *this;
+}
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::Indent( void )
+{
+ if (m_pDebugStream->m_indent + m_pDebugStream->m_tabsize < m_pDebugStream->m_margin)
+ m_pDebugStream->m_indent += m_pDebugStream->m_tabsize;
+ if (!m_pDebugStream->m_pendingReturn)
+ while (m_pDebugStream->m_position < m_pDebugStream->m_indent)
+ operator<<(' ');
+
+ return *this;
+}
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::UnIndent( void )
+{
+ if (m_pDebugStream->m_indent > 0) m_pDebugStream->m_indent -= m_pDebugStream->m_tabsize;
+ return *this;
+}
+
+
+void NC(CDebugStream,CDSImpl)::ForceReturn( void )
+{
+ m_pDebugStream->OutputDebugString("\n");
+ for (int i = 0; i<m_pDebugStream->m_indent; i++)
+ m_pDebugStream->OutputDebugString(" ");
+ m_pDebugStream->m_position = m_pDebugStream->m_indent;
+ m_pDebugStream->m_pendingReturn = FALSE;
+}
+
+void NC(CDebugStream,CDSImpl)::ReturnIfPending( void )
+{
+ if (m_pDebugStream->m_pendingReturn) ForceReturn();
+}
+
+
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::Return( void )
+{
+ ReturnIfPending();
+ m_pDebugStream->m_pendingReturn = TRUE;
+ Yield(); // let dbwin get control
+ return *this;
+}
+
+OLEMETHODIMP_(IDebugStream&) NC(CDebugStream,CDSImpl)::LF( void )
+{
+ return Return();
+}
+
+OLESTATICIMP_(IDebugStream FAR *) CDebugStream::Create( // no aggregation
+ int margin, int tabsize, BOOL fHeader )
+{
+ CDebugStream FAR * pcds = new FAR (TASK)CDebugStream( margin, tabsize, fHeader );
+ if( !pcds ){
+ AssertSz( pcds, "Out of Memory");
+ return NULL;
+ }
+ return &(pcds->m_DebugStream);
+}
+#endif // _DEBUG
+
+
+#if 0
+STDAPI_(IDebugStream FAR *) MakeDebugStream( short margin, short tabsize, BOOL fHeader)
+{
+#ifdef _DEBUG
+ return CDebugStream::Create( margin, tabsize, fHeader );
+#else
+ (void) margin;
+ (void) tabsize;
+ (void) fHeader;
+ return NULL;
+#endif // _DEBUG
+}
+#else
+STDAPI_(void FAR *) MakeDebugStream( short margin, short tabsize, BOOL fHeader)
+{
+ return NULL;
+}
+#endif
+
+
+//
+// IDebug helpers
+//
+
+STDAPI_(void) DbgDumpObject( IUnknown FAR * pUnk, DWORD dwReserved )
+{
+#ifdef _DEBUG
+ IDebugStream FAR * pcds = MakeDebugStream( DBGMARGIN, DBGTABSIZE, NOHEADER );
+ (void)dwReserved;
+
+ if( pcds ) {
+ *pcds << pUnk;
+ pcds->Return();
+ pcds->Release();
+ }
+#else
+ (void) pUnk;
+ (void) dwReserved;
+#endif
+}
+
+STDAPI_(void) DbgDumpExternalObject( IUnknown FAR * pUnk, DWORD dwReserved )
+{
+#ifdef _DEBUG
+ SHREG shreg;
+
+ (void) dwReserved;
+
+ if( IsValidInterface(pUnk) ){
+ if( RemLookupSHUnk(pUnk, NULL, &shreg) == NOERROR ){
+ DbgDumpObject(shreg.m_pSM, 0);
+ shreg.m_pSM->Release();
+ }
+ }
+
+#else
+ (void) dwReserved;
+ (void) pUnk;
+#endif
+}
+
+STDAPI_(BOOL) DbgIsObjectValid( IUnknown FAR * pUnk )
+{
+#ifdef _DEBUG
+ BOOL fReturn = TRUE; // default value for objects that don't
+ // support IDebug
+ IDebug FAR * pDebug = NULL;
+
+ if( IsValidInterface(pUnk) ){
+ pUnk->QueryInterface( IID_IDebug, (void FAR* FAR*)&pDebug);
+ if (pDebug)
+ fReturn = pDebug->IsValid();
+ //IDebug is not addref'd
+ return fReturn;
+ }
+ return FALSE;
+#else
+ (void) pUnk;
+ return TRUE;
+#endif
+}
+
+
+STDAPI_(void) DbgDumpClassName( IUnknown FAR * pUnk )
+{
+#ifdef _DEBUG
+ CLSID clsid;
+
+ IDebugStream FAR * pcds = MakeDebugStream( DBGMARGIN, DBGTABSIZE, NOHEADER );
+
+ if( pcds ) {
+ if( IsValidInterface(pUnk) ){
+ OleGetClassID( pUnk, (LPCLSID)&clsid);
+ *pcds << clsid << " @ " << (void FAR* )pUnk << '\n';
+ }else if (!pUnk)
+ *pcds << "NULL interface" << '\n';
+ else
+ *pcds << (void FAR *)pUnk << " is not a valid interface" << '\n';
+ pcds->Release();
+ }
+#else
+ (void)pUnk;
+#endif
+}
+
+STDAPI_(void) DumpAllObjects( void )
+{
+//#ifdef _DEBUG
+#ifdef NEVER
+ IDebug FAR * pID = GetIDHead();
+ IDebugStream FAR * pcds = MakeDebugStream( DBGMARGIN, DBGTABSIZE, NOHEADER );
+
+ *pcds << "----TASK OBJECTS-------\n";
+ while (pID)
+ {
+ pID->Dump( pcds );
+ pID = pID->pIDNext;
+ }
+ *pcds << "----SHARED OBJECTS-------\n";
+ pID = pIDHeadShared;
+ while (pID)
+ {
+ pID->Dump( pcds );
+ pID = pID->pIDNext;
+ }
+
+ pcds->Release();
+#endif
+}
+
+
+STDAPI_(BOOL) ValidateAllObjects( BOOL fSuspicious )
+{
+//#ifdef _DEBUG
+#ifdef NEVER
+ IDebug FAR * pID = GetIDHead();
+ int pass = 0;
+ IDebugStream FAR * pcds = MakeDebugStream( DBGMARGIN, DBGTABSIZE, NOHEADER);
+ BOOL fReturn = TRUE;
+
+ while (pID)
+ {
+ if (!(pID->IsValid(fSuspicious)))
+ {
+ fReturn = FALSE;
+ if (pass == 0)
+ *pcds <<
+ "\n****INVALID OBJECT*****\n";
+ else
+ *pcds << "\n****INVALID SHARED MEMORY OBJECT*****\n";
+ pID->Dump( pcds );
+ pcds->Return();
+ }
+ pID = pID->pIDNext;
+ if ((pID == NULL) && (pass++ == 0))
+ pID = pIDHeadShared;
+ }
+ pcds->Release();
+ return fReturn;
+#endif //NEVER
+ (void) fSuspicious;
+ return TRUE;
+}
+
+
+#ifdef _DEBUG
+
+
+extern "C"
+BOOL CALLBACK __loadds DebCallBack(WORD wID, DWORD dwData)
+{
+// char rgchBuf[50];
+//// BOOL fTraceStack = FALSE;
+//// STACKTRACEENTRY ste;
+//// WORD wSS, wCS, wIP, wBP;
+// NFYLOADSEG FAR* pNFY = (NFYLOADSEG FAR *)dwData;
+//
+// if (wID == NFY_LOADSEG)
+// {
+// if (0 == _fstrcmp(pNFY->lpstrModuleName,"OLE2"))
+// {
+// wsprintf(rgchBuf, "Load seg %02x(%#04x), module %s", pNFY->wSegNum,
+// pNFY->wSelector, pNFY->lpstrModuleName);
+// OutputDebugString(rgchBuf);
+// _asm int 3
+//// if (fTraceStack)
+//// {
+//// _asm mov wSS, SS
+//// _asm mov wCS, CS
+//// _asm mov wIP, IP
+//// _asm mov wBP, BP
+//// ste.dwSize = sizeof(STACKTRACEENTRY);
+//// if (StackTraceCSIPFirst(&ste, wSS, wCS, wIP, wBP))
+//// {
+//// while (fTraceStack && StackTraceNext(&ste));
+//// }
+////
+//// }
+// }
+// }
+// else if (wID == NFY_FREESEG)
+// {
+// }
+ (void) wID;
+ (void) dwData;
+ return FALSE;
+}
+
+BOOL InstallHooks(void)
+{
+// return NotifyRegister(NULL, (LPFNNOTIFYCALLBACK)DebCallBack, NF_NORMAL);
+return TRUE;
+}
+
+BOOL UnInstallHooks()
+{
+// return NotifyUnRegister(NULL);
+return TRUE;
+}
+
+
+#endif
diff --git a/private/ole32/olethunk/ole16/ole2/default.ico b/private/ole32/olethunk/ole16/ole2/default.ico
new file mode 100644
index 000000000..4542c57d3
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/default.ico
Binary files differ
diff --git a/private/ole32/olethunk/ole16/ole2/dragcopy.cur b/private/ole32/olethunk/ole16/ole2/dragcopy.cur
new file mode 100644
index 000000000..89c7c960d
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/dragcopy.cur
Binary files differ
diff --git a/private/ole32/olethunk/ole16/ole2/draglink.cur b/private/ole32/olethunk/ole16/ole2/draglink.cur
new file mode 100644
index 000000000..fca1fc090
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/draglink.cur
Binary files differ
diff --git a/private/ole32/olethunk/ole16/ole2/dragmove.cur b/private/ole32/olethunk/ole16/ole2/dragmove.cur
new file mode 100644
index 000000000..a9a9bd636
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/dragmove.cur
Binary files differ
diff --git a/private/ole32/olethunk/ole16/ole2/dragnone.cur b/private/ole32/olethunk/ole16/ole2/dragnone.cur
new file mode 100644
index 000000000..b002e96b3
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/dragnone.cur
Binary files differ
diff --git a/private/ole32/olethunk/ole16/ole2/headers.cxx b/private/ole32/olethunk/ole16/ole2/headers.cxx
new file mode 100644
index 000000000..97655cd81
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/headers.cxx
@@ -0,0 +1,22 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: headers.cxx
+//
+// Contents: Precompiled header file
+//
+// History: 18-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <windows.h>
+#include <string.h>
+#include <compobj.h>
+#include <storage.h>
+#include <ole2.h>
+
+#include <interop.hxx>
+#include <wow16fn.h>
+#include <io16.h>
diff --git a/private/ole32/olethunk/ole16/ole2/icon.cxx b/private/ole32/olethunk/ole16/ole2/icon.cxx
new file mode 100644
index 000000000..caa79dbe8
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/icon.cxx
@@ -0,0 +1,1465 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: icon.cxx
+//
+// Contents: icon.cpp from OLE2
+//
+// History: 11-Apr-94 DrewB Copied from OLE2
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+/*
+ * ICON.CPP
+ *
+ * Functions to create DVASPECT_ICON metafile from filename or classname.
+ *
+ * OleGetIconOfFile
+ * OleGetIconOfClass
+ * OleMetafilePictFromIconAndLabel
+ *
+ * HIconAndSourceFromClass Extracts the first icon in a class's server path
+ * and returns the path and icon index to caller.
+ * FIconFileFromClass Retrieves the path to the exe/dll containing the
+ * default icon, and the index of the icon.
+ * OleStdIconLabelTextOut
+ * PointerToNthField
+ * XformWidthInPixelsToHimetric Converts an int width into HiMetric units
+ * XformWidthInHimetricToPixels Converts an int width from HiMetric units
+ * XformHeightInPixelsToHimetric Converts an int height into HiMetric units
+ * XformHeightInHimetricToPixels Converts an int height from HiMetric units
+ *
+ * (c) Copyright Microsoft Corp. 1992-1993 All Rights Reserved
+ */
+
+#include <ole2int.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <commdlg.h>
+#include <memory.h>
+#include <cderr.h>
+
+#include "icon.h"
+
+static char szMaxWidth[] ="WWWWWWWWWW";
+
+//Strings for metafile comments.
+static char szIconOnly[]="IconOnly"; //Where to stop to exclude label.
+
+#define OLEUI_CCHKEYMAX 256
+#define OLEUI_CCHPATHMAX 256
+#define OLEUI_CCHLABELMAX 40
+
+#define ICONINDEX 0
+
+#define AUXUSERTYPE_SHORTNAME USERCLASSTYPE_SHORT // short name
+#define HIMETRIC_PER_INCH 2540 // number HIMETRIC units per inch
+#define PTS_PER_INCH 72 // number points (font size) per inch
+
+#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
+#define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH)
+
+static char szVanillaDocIcon[] = "DefIcon";
+
+static char szDocument[OLEUI_CCHLABELMAX] = "";
+static char szSeparators[] = " \t\\/!:";
+static const char szDefIconLabelKey[] = "Software\\Microsoft\\OLE2\\DefaultIconLabel";
+
+#define IS_SEPARATOR(c) ( (c) == ' ' || (c) == '\\' || (c) == '/' || (c) == '\t' || (c) == '!' || (c) == ':' )
+#define IS_FILENAME_DELIM(c) ( (c) == '\\' || (c) == '/' || (c) == ':' )
+
+#define LSTRCPYN(lpdst, lpsrc, cch) \
+(\
+ lpdst[cch-1] = '\0', \
+ lstrcpyn(lpdst, lpsrc, cch-1)\
+)
+
+
+/*******
+ *
+ * ICON METAFILE FORMAT:
+ *
+ * The metafile generated with OleMetafilePictFromIconAndLabel contains
+ * the following records which are used by the functions in DRAWICON.C
+ * to draw the icon with and without the label and to extract the icon,
+ * label, and icon source/index.
+ *
+ * SetWindowOrg
+ * SetWindowExt
+ * DrawIcon:
+ * Inserts records of DIBBITBLT or DIBSTRETCHBLT, once for the
+ * AND mask, one for the image bits.
+ * Escape with the comment "IconOnly"
+ * This indicates where to stop record enumeration to draw only
+ * the icon.
+ * SetTextColor
+ * SetBkColor
+ * CreateFont
+ * SelectObject on the font.
+ * ExtTextOut
+ * One or more ExtTextOuts occur if the label is wrapped. The
+ * text in these records is used to extract the label.
+ * SelectObject on the old font.
+ * DeleteObject on the font.
+ * Escape with a comment that contains the path to the icon source.
+ * Escape with a comment that is the ASCII of the icon index.
+ *
+ *******/
+
+
+
+
+/*
+ * OleGetIconOfFile(LPSTR lpszPath, BOOL fUseFileAsLabel)
+ *
+ * Purpose:
+ * Returns a hMetaPict containing an icon and label (filename) for the
+ * specified filename.
+ *
+ * Parameters:
+ * lpszPath LPSTR path including filename to use
+ * fUseFileAsLabel BOOL TRUE if the icon's label is the filename, FALSE if
+ * there should be no label.
+ *
+ * Return Value:
+ * HGLOBAL hMetaPict containing the icon and label - if there's no
+ * class in reg db for the file in lpszPath, then we use
+ * Document. If lpszPath is NULL, then we return NULL.
+ */
+
+STDAPI_(HGLOBAL) OleGetIconOfFile(LPSTR lpszPath, BOOL fUseFileAsLabel)
+{
+
+
+ char szIconFile[OLEUI_CCHPATHMAX];
+ char szLabel[OLEUI_CCHLABELMAX];
+ LPSTR lpszClsid = NULL;
+ CLSID clsid;
+ HICON hDefIcon = NULL;
+ UINT IconIndex = 0;
+ HGLOBAL hMetaPict;
+ HRESULT hResult;
+
+ if (NULL == lpszPath) // even if fUseFileAsLabel is FALSE, we still
+ return NULL; // need a valid filename to get the class.
+
+ hResult = GetClassFile(lpszPath, &clsid);
+
+ if (NOERROR == hResult) // use the clsid we got to get to the icon
+ {
+ hDefIcon = HIconAndSourceFromClass(clsid,
+ (LPSTR)szIconFile,
+ &IconIndex);
+ }
+
+ if ( (NOERROR != hResult) || (NULL == hDefIcon) )
+ {
+ // Here, either GetClassFile failed or HIconAndSourceFromClass failed.
+
+ LPSTR lpszTemp;
+
+ lpszTemp = lpszPath;
+
+ while ((*lpszTemp != '.') && (*lpszTemp != '\0'))
+ lpszTemp++;
+
+
+ if ('.' != *lpszTemp)
+ goto UseVanillaDocument;
+
+
+ if (FALSE == GetAssociatedExecutable(lpszTemp, (LPSTR)szIconFile))
+ goto UseVanillaDocument;
+
+ hDefIcon = ExtractIcon(hmodOLE2, szIconFile, IconIndex);
+ }
+
+ if (hDefIcon <= (HICON)1) // ExtractIcon returns 1 if szExecutable is not exe,
+ { // 0 if there are no icons.
+UseVanillaDocument:
+
+ GetModuleFileName(hmodOLE2, (LPSTR)szIconFile, OLEUI_CCHPATHMAX);
+ IconIndex = ICONINDEX;
+ hDefIcon = LoadIcon(hmodOLE2, (LPSTR)szVanillaDocIcon);
+ }
+
+ // Now let's get the label we want to use.
+
+ if (fUseFileAsLabel) // strip off path, so we just have the filename.
+ {
+ int istrlen;
+ LPSTR lpszBeginFile;
+
+ istrlen = lstrlen(lpszPath);
+
+ // set pointer to END of path, so we can walk backwards through it.
+ lpszBeginFile = lpszPath + istrlen -1;
+
+ while ( (lpszBeginFile >= lpszPath)
+ && (!IS_FILENAME_DELIM(*lpszBeginFile)) )
+ lpszBeginFile--;
+
+
+ lpszBeginFile++; // step back over the delimiter
+
+
+ LSTRCPYN(szLabel, lpszBeginFile, sizeof(szLabel));
+ }
+
+ else // use the short user type (AuxUserType2) for the label
+ {
+
+ if (0 == OleStdGetAuxUserType(clsid, AUXUSERTYPE_SHORTNAME,
+ (LPSTR)szLabel, OLEUI_CCHLABELMAX, NULL)) {
+
+ if ('\0'==szDocument[0]) {
+ LONG cb = sizeof (szDocument);
+ RegQueryValue (HKEY_CLASSES_ROOT, szDefIconLabelKey, szDocument,
+ &cb);
+ // if szDocument is not big enough, RegQueryValue puts a NULL
+ // at the end so we are safe.
+ // if RegQueryValue fails, szDocument[0]=='\0' so we'll use that.
+ }
+ lstrcpy(szLabel, szDocument);
+ }
+ }
+
+
+ hMetaPict = OleMetafilePictFromIconAndLabel(hDefIcon,
+ szLabel,
+ (LPSTR)szIconFile,
+ IconIndex);
+
+ DestroyIcon(hDefIcon);
+
+ return hMetaPict;
+
+}
+
+/*
+ * GetAssociatedExecutable
+ *
+ * Purpose: Finds the executable associated with the provided extension
+ *
+ * Parameters:
+ * lpszExtension LPSTR points to the extension we're trying to find an exe
+ * for. Does **NO** validation.
+ *
+ * lpszExecutable LPSTR points to where the exe name will be returned.
+ * No validation here either - pass in 128 char buffer.
+ *
+ * Return:
+ * BOOL TRUE if we found an exe, FALSE if we didn't.
+ *
+ */
+
+BOOL FAR PASCAL GetAssociatedExecutable(LPSTR lpszExtension, LPSTR lpszExecutable)
+
+{
+ HKEY hKey;
+ LONG dw;
+ LRESULT lRet;
+ char szValue[OLEUI_CCHKEYMAX];
+ char szKey[OLEUI_CCHKEYMAX];
+ LPSTR lpszTemp, lpszExe;
+
+
+ lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
+
+ if (ERROR_SUCCESS != lRet)
+ return FALSE;
+
+ dw = OLEUI_CCHPATHMAX;
+ lRet = RegQueryValue(hKey, lpszExtension, (LPSTR)szValue, &dw); //ProgId
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+
+
+ // szValue now has ProgID
+ lstrcpy(szKey, szValue);
+ lstrcat(szKey, "\\Shell\\Open\\Command");
+
+
+ dw = OLEUI_CCHPATHMAX;
+ lRet = RegQueryValue(hKey, (LPSTR)szKey, (LPSTR)szValue, &dw);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+
+ // szValue now has an executable name in it. Let's null-terminate
+ // at the first post-executable space (so we don't have cmd line
+ // args.
+
+ lpszTemp = (LPSTR)szValue;
+
+ while (('\0' != *lpszTemp) && (isspace(*lpszTemp)))
+ lpszTemp++; // Strip off leading spaces
+
+ lpszExe = lpszTemp;
+
+ while (('\0' != *lpszTemp) && (!isspace(*lpszTemp)))
+ lpszTemp++; // Set through exe name
+
+ *lpszTemp = '\0'; // null terminate at first space (or at end).
+
+
+ lstrcpy(lpszExecutable, lpszExe);
+
+ return TRUE;
+
+}
+
+
+
+
+
+/*
+ * OleGetIconOfClass(REFCLSID rclsid, LPSTR lpszLabel, BOOL fUseTypeAsLabel)
+ *
+ * Purpose:
+ * Returns a hMetaPict containing an icon and label (human-readable form
+ * of class) for the specified clsid.
+ *
+ * Parameters:
+ * rclsid REFCLSID pointing to clsid to use.
+ * lpszLabel label to use for icon.
+ * fUseTypeAsLabel Use the clsid's user type name as the icon's label.
+ *
+ * Return Value:
+ * HGLOBAL hMetaPict containing the icon and label - if we
+ * don't find the clsid in the reg db then we
+ * return NULL.
+ */
+
+STDAPI_(HGLOBAL) OleGetIconOfClass(REFCLSID rclsid, LPSTR lpszLabel, BOOL fUseTypeAsLabel)
+{
+
+ char szLabel[OLEUI_CCHLABELMAX];
+ char szIconFile[OLEUI_CCHPATHMAX];
+ HICON hDefIcon;
+ UINT IconIndex;
+ HGLOBAL hMetaPict;
+
+ if (!fUseTypeAsLabel) // Use string passed in as label
+ {
+ if (NULL != lpszLabel)
+ LSTRCPYN(szLabel, lpszLabel, sizeof(szLabel));
+ else
+ *szLabel = '\0';
+ }
+ else // Use AuxUserType2 (short name) as label
+ {
+
+ if (0 == OleStdGetAuxUserType(rclsid,
+ AUXUSERTYPE_SHORTNAME,
+ (LPSTR)szLabel,
+ OLEUI_CCHLABELMAX,
+ NULL))
+
+ // If we can't get the AuxUserType2, then try the long name
+ if (0 == OleStdGetUserTypeOfClass(rclsid, szLabel, OLEUI_CCHKEYMAX, NULL)) {
+ if ('\0'==szDocument[0]) {
+ LONG cb = sizeof (szDocument);
+ RegQueryValue (HKEY_CLASSES_ROOT, szDefIconLabelKey, szDocument,
+ &cb);
+ // if RegQueryValue fails, szDocument=="" so we'll use that.
+ }
+ lstrcpy(szLabel, szDocument); // last resort
+ }
+ }
+
+ // Get the icon, icon index, and path to icon file
+ hDefIcon = HIconAndSourceFromClass(rclsid,
+ (LPSTR)szIconFile,
+ &IconIndex);
+
+ if (NULL == hDefIcon) // Use Vanilla Document
+ {
+ GetModuleFileName(hmodOLE2, (LPSTR)szIconFile, OLEUI_CCHPATHMAX);
+ IconIndex = ICONINDEX;
+ hDefIcon = LoadIcon(hmodOLE2, (LPSTR)szVanillaDocIcon);
+ }
+
+ // Create the metafile
+ hMetaPict = OleMetafilePictFromIconAndLabel(hDefIcon, szLabel,
+ (LPSTR)szIconFile, IconIndex);
+
+ DestroyIcon(hDefIcon);
+
+ return hMetaPict;
+
+}
+
+
+
+
+
+/*
+ * HIconAndSourceFromClass
+ *
+ * Purpose:
+ * Given an object class name, finds an associated executable in the
+ * registration database and extracts the first icon from that
+ * executable. If none is available or the class has no associated
+ * executable, this function returns NULL.
+ *
+ * Parameters:
+ * rclsid pointer to clsid to look up.
+ * pszSource LPSTR in which to place the source of the icon.
+ * This is assumed to be OLEUI_CCHPATHMAX
+ * puIcon UINT FAR * in which to store the index of the
+ * icon in pszSource.
+ *
+ * Return Value:
+ * HICON Handle to the extracted icon if there is a module
+ * associated to pszClass. NULL on failure to either
+ * find the executable or extract and icon.
+ */
+
+HICON FAR PASCAL HIconAndSourceFromClass(REFCLSID rclsid, LPSTR pszSource, UINT FAR *puIcon)
+ {
+ HICON hIcon;
+ UINT IconIndex;
+
+ if (CLSID_NULL==rclsid || NULL==pszSource)
+ return NULL;
+
+ if (!FIconFileFromClass(rclsid, pszSource, OLEUI_CCHPATHMAX, &IconIndex))
+ return NULL;
+
+ hIcon=ExtractIcon(hmodOLE2, pszSource, IconIndex);
+
+ if ((HICON)32 > hIcon)
+ hIcon=NULL;
+ else
+ *puIcon= IconIndex;
+
+ return hIcon;
+ }
+
+
+
+/*
+ * FIconFileFromClass
+ *
+ * Purpose:
+ * Looks up the path to executable that contains the class default icon.
+ *
+ * Parameters:
+ * rclsid pointer to CLSID to look up.
+ * pszEXE LPSTR at which to store the server name
+ * cch UINT size of pszEXE
+ * lpIndex LPUINT to index of icon within executable
+ *
+ * Return Value:
+ * BOOL TRUE if one or more characters were loaded into pszEXE.
+ * FALSE otherwise.
+ */
+
+BOOL FAR PASCAL FIconFileFromClass(REFCLSID rclsid, LPSTR pszEXE, UINT cch, UINT FAR *lpIndex)
+{
+
+ LONG dw;
+ LONG lRet;
+ HKEY hKey;
+ LPMALLOC lpIMalloc;
+ HRESULT hrErr;
+ LPSTR lpBuffer;
+ LPSTR lpIndexString;
+ UINT cBufferSize = 136; // room for 128 char path and icon's index
+ char szKey[64];
+ LPSTR pszClass;
+
+
+ if (CLSID_NULL==rclsid || NULL==pszEXE || 0==cch)
+ return FALSE;
+
+ //Here, we use CoGetMalloc and alloc a buffer (maxpathlen + 8) to
+ //pass to RegQueryValue. Then, we copy the exe to pszEXE and the
+ //index to *lpIndex.
+
+ hrErr = CoGetMalloc(MEMCTX_TASK, &lpIMalloc);
+
+ if (NOERROR != hrErr)
+ return FALSE;
+
+ lpBuffer = (LPSTR)lpIMalloc->Alloc(cBufferSize);
+
+ if (NULL == lpBuffer)
+ {
+ lpIMalloc->Release();
+ return FALSE;
+ }
+
+
+ if (CoIsOle1Class(rclsid))
+ {
+
+ LPSTR lpszProgID;
+
+ // we've got an ole 1.0 class on our hands, so we look at
+ // progID\protocol\stdfileedting\server to get the
+ // name of the executable.
+
+ ProgIDFromCLSID(rclsid, &lpszProgID);
+
+ //Open up the class key
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, lpszProgID, &hKey);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ lpIMalloc->Free(lpszProgID);
+ lpIMalloc->Free(lpBuffer);
+ lpIMalloc->Release();
+ return FALSE;
+ }
+
+ dw=(LONG)cBufferSize;
+ lRet = RegQueryValue(hKey, "Protocol\\StdFileEditing\\Server", lpBuffer, &dw);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+
+ RegCloseKey(hKey);
+ lpIMalloc->Free(lpszProgID);
+ lpIMalloc->Free(lpBuffer);
+ lpIMalloc->Release();
+ return FALSE;
+ }
+
+
+ // Use server and 0 as the icon index
+ LSTRCPYN(pszEXE, lpBuffer, cch);
+
+ *lpIndex = 0;
+
+ RegCloseKey(hKey);
+ lpIMalloc->Free(lpszProgID);
+ lpIMalloc->Free(lpBuffer);
+ lpIMalloc->Release();
+ return TRUE;
+
+ }
+
+
+
+ /*
+ * We have to go walking in the registration database under the
+ * classname, so we first open the classname key and then check
+ * under "\\DefaultIcon" to get the file that contains the icon.
+ */
+
+ StringFromCLSID(rclsid, &pszClass);
+
+ lstrcpy(szKey, "CLSID\\");
+ lstrcat(szKey, pszClass);
+
+ //Open up the class key
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, szKey, &hKey);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ lpIMalloc->Free(lpBuffer);
+ lpIMalloc->Free(pszClass);
+ lpIMalloc->Release();
+ return FALSE;
+ }
+
+ //Get the executable path and icon index.
+
+ dw=(LONG)cBufferSize;
+ lRet=RegQueryValue(hKey, "DefaultIcon", lpBuffer, &dw);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ // no DefaultIcon key...try LocalServer
+
+ dw=(LONG)cBufferSize;
+ lRet=RegQueryValue(hKey, "LocalServer", lpBuffer, &dw);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ // no LocalServer entry either...they're outta luck.
+
+ RegCloseKey(hKey);
+ lpIMalloc->Free(lpBuffer);
+ lpIMalloc->Free(pszClass);
+ lpIMalloc->Release();
+ return FALSE;
+ }
+
+
+ // Use server from LocalServer or Server and 0 as the icon index
+ LSTRCPYN(pszEXE, lpBuffer, cch);
+
+ *lpIndex = 0;
+
+ RegCloseKey(hKey);
+ lpIMalloc->Free(lpBuffer);
+ lpIMalloc->Free(pszClass);
+ lpIMalloc->Release();
+ return TRUE;
+ }
+
+ RegCloseKey(hKey);
+
+ // lpBuffer contains a string that looks like "<pathtoexe>,<iconindex>",
+ // so we need to separate the path and the icon index.
+
+ lpIndexString = PointerToNthField(lpBuffer, 2, ',');
+
+ if ('\0' == *lpIndexString) // no icon index specified - use 0 as default.
+ {
+ *lpIndex = 0;
+
+ }
+ else
+ {
+ LPSTR lpTemp;
+ static char szTemp[16];
+
+ lstrcpy((LPSTR)szTemp, lpIndexString);
+
+ // Put the icon index part into *pIconIndex
+ *lpIndex = atoi((const char *)szTemp);
+
+ // Null-terminate the exe part.
+ lpTemp = AnsiPrev(lpBuffer, lpIndexString);
+ *lpTemp = '\0';
+ }
+
+ if (!LSTRCPYN(pszEXE, lpBuffer, cch))
+ {
+ lpIMalloc->Free(lpBuffer);
+ lpIMalloc->Free(pszClass);
+ lpIMalloc->Release();
+ return FALSE;
+ }
+
+ // Free the memory we alloc'd and leave.
+ lpIMalloc->Free(lpBuffer);
+ lpIMalloc->Free(pszClass);
+ lpIMalloc->Release();
+ return TRUE;
+}
+
+
+
+
+/*
+ * OleMetafilePictFromIconAndLabel
+ *
+ * Purpose:
+ * Creates a METAFILEPICT structure that container a metafile in which
+ * the icon and label are drawn. A comment record is inserted between
+ * the icon and the label code so our special draw function can stop
+ * playing before the label.
+ *
+ * Parameters:
+ * hIcon HICON to draw into the metafile
+ * pszLabel LPSTR to the label string.
+ * pszSourceFile LPSTR containing the local pathname of the icon
+ * as we either get from the user or from the reg DB.
+ * iIcon UINT providing the index into pszSourceFile where
+ * the icon came from.
+ *
+ * Return Value:
+ * HGLOBAL Global memory handle containing a METAFILEPICT where
+ * the metafile uses the MM_ANISOTROPIC mapping mode. The
+ * extents reflect both icon and label.
+ */
+
+STDAPI_(HGLOBAL) OleMetafilePictFromIconAndLabel(HICON hIcon, LPSTR pszLabel
+ , LPSTR pszSourceFile, UINT iIcon)
+ {
+ HDC hDC, hDCScreen;
+ HMETAFILE hMF;
+ HGLOBAL hMem;
+ LPMETAFILEPICT pMF;
+ UINT cxIcon, cyIcon;
+ UINT cxText, cyText;
+ UINT cx, cy;
+ UINT cchLabel = 0;
+ HFONT hFont, hSysFont, hFontT;
+ int cyFont;
+ char szIndex[10];
+ RECT TextRect;
+ SIZE size;
+ POINT point;
+ LOGFONT logfont;
+
+ if (NULL==hIcon) // null icon is valid
+ return NULL;
+
+ //Create a memory metafile
+ hDC=(HDC)CreateMetaFile(NULL);
+
+ if (NULL==hDC)
+ return NULL;
+
+ //Allocate the metafilepict
+ hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(METAFILEPICT));
+
+ if (NULL==hMem)
+ {
+ hMF=CloseMetaFile(hDC);
+ DeleteMetaFile(hMF);
+ return NULL;
+ }
+
+
+ if (NULL!=pszLabel)
+ {
+ cchLabel=lstrlen(pszLabel);
+
+ if (cchLabel >= OLEUI_CCHLABELMAX)
+ pszLabel[cchLabel] = '\0'; // truncate string
+ }
+
+ //Need to use the screen DC for these operations
+ hDCScreen=GetDC(NULL);
+ cyFont=-(8*GetDeviceCaps(hDCScreen, LOGPIXELSY))/72;
+
+ //cyFont was calculated to give us 8 point.
+
+ // We use the system font as the basis for the character set,
+ // allowing us to handle DBCS strings better
+ hSysFont = GetStockObject( SYSTEM_FONT );
+ GetObject(hSysFont, sizeof(LOGFONT), &logfont);
+ hFont=CreateFont(cyFont, 5, 0, 0, FW_NORMAL, 0, 0, 0, logfont.lfCharSet
+ , OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY
+ , FF_SWISS, "MS Sans Serif");
+
+ hFontT=SelectObject(hDCScreen, hFont);
+
+ GetTextExtentPoint(hDCScreen,szMaxWidth,lstrlen(szMaxWidth),&size);
+ SelectObject(hDCScreen, hFontT);
+
+ cxText = size.cx;
+ cyText = size.cy * 2;
+
+ cxIcon = GetSystemMetrics(SM_CXICON);
+ cyIcon = GetSystemMetrics(SM_CYICON);
+
+
+ // If we have no label, then we want the metafile to be the width of
+ // the icon (plus margin), not the width of the fattest string.
+ if ( (NULL == pszLabel) || (NULL == *pszLabel) )
+ cx = cxIcon + cxIcon / 4;
+ else
+ cx = max(cxText, cxIcon);
+
+ cy=cyIcon+cyText+4;
+
+ //Set the metafile size to fit the icon and label
+ SetWindowOrgEx(hDC, 0, 0, &point);
+ SetWindowExtEx(hDC, cx, cy, &size);
+
+ //Set up rectangle to pass to OleStdIconLabelTextOut
+ SetRectEmpty(&TextRect);
+
+ TextRect.right = cx;
+ TextRect.bottom = cy;
+
+ //Draw the icon and the text, centered with respect to each other.
+ DrawIcon(hDC, (cx-cxIcon)/2, 0, hIcon);
+
+ //String that indicates where to stop if we're only doing icons
+ Escape(hDC, MFCOMMENT, lstrlen(szIconOnly)+1, szIconOnly, NULL);
+
+ SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
+ SetBkMode(hDC, TRANSPARENT);
+
+ OleStdIconLabelTextOut(hDC,
+ hFont,
+ 0,
+ cy - cyText,
+ ETO_CLIPPED,
+ &TextRect,
+ pszLabel,
+ cchLabel,
+ NULL);
+
+ //Write comments containing the icon source file and index.
+ if (NULL!=pszSourceFile)
+ {
+ //+1 on string lengths insures the null terminator is embedded.
+ Escape(hDC, MFCOMMENT, lstrlen(pszSourceFile)+1, pszSourceFile, NULL);
+
+ cchLabel=wsprintf(szIndex, "%u", iIcon);
+ Escape(hDC, MFCOMMENT, cchLabel+1, szIndex, NULL);
+ }
+
+ //All done with the metafile, now stuff it all into a METAFILEPICT.
+ hMF=CloseMetaFile(hDC);
+
+ if (NULL==hMF)
+ {
+ GlobalFree(hMem);
+ ReleaseDC(NULL, hDCScreen);
+ return NULL;
+ }
+
+ //Fill out the structure
+ pMF=(LPMETAFILEPICT)GlobalLock(hMem);
+
+ //Transform to HIMETRICS
+ cx=XformWidthInPixelsToHimetric(hDCScreen, cx);
+ cy=XformHeightInPixelsToHimetric(hDCScreen, cy);
+ ReleaseDC(NULL, hDCScreen);
+
+ pMF->mm=MM_ANISOTROPIC;
+ pMF->xExt=cx;
+ pMF->yExt=cy;
+ pMF->hMF=hMF;
+
+ GlobalUnlock(hMem);
+
+ DeleteObject(hFont);
+
+ return hMem;
+ }
+
+
+
+/*
+ * OleStdIconLabelTextOut
+ *
+ * Purpose:
+ * Replacement for DrawText to be used in the "Display as Icon" metafile.
+ * Uses ExtTextOut to output a string center on (at most) two lines.
+ * Uses a very simple word wrap algorithm to split the lines.
+ *
+ * Parameters: (same as for ExtTextOut, except for hFont)
+ * hDC device context to draw into; if this is NULL, then we don't
+ * ETO the text, we just return the index of the beginning
+ * of the second line
+ * hFont font to use
+ * nXStart x-coordinate of starting position
+ * nYStart y-coordinate of starting position
+ * fuOptions rectangle type
+ * lpRect rect far * containing rectangle to draw text in.
+ * lpszString string to draw
+ * cchString length of string (truncated if over OLEUI_CCHLABELMAX)
+ * lpDX spacing between character cells
+ *
+ * Return Value:
+ * UINT Index of beginning of last line (0 if there's only one
+ * line of text).
+ *
+ */
+
+STDAPI_(UINT) OleStdIconLabelTextOut(HDC hDC,
+ HFONT hFont,
+ int nXStart,
+ int nYStart,
+ UINT fuOptions,
+ RECT FAR * lpRect,
+ LPSTR lpszString,
+ UINT cchString,
+ int FAR * lpDX)
+{
+
+ HDC hDCScreen;
+ static char szTempBuff[OLEUI_CCHLABELMAX];
+ int cxString, cyString, cxMaxString;
+ int cxFirstLine, cyFirstLine, cxSecondLine;
+ int index;
+ int cch = cchString;
+ char chKeep;
+ LPSTR lpszSecondLine;
+ HFONT hFontT;
+ BOOL fPrintText = TRUE;
+ UINT iLastLineStart = 0;
+ SIZE size;
+
+ // Initialization stuff...
+
+ if (NULL == hDC) // If we got NULL as the hDC, then we don't actually call ETO
+ fPrintText = FALSE;
+
+
+ // Make a copy of the string (NULL or non-NULL) that we're using
+ if (NULL == lpszString)
+ *szTempBuff = '\0';
+
+ else
+ LSTRCPYN(szTempBuff, lpszString, sizeof(szTempBuff));
+
+ // set maximum width
+ cxMaxString = lpRect->right - lpRect->left;
+
+ // get screen DC to do text size calculations
+ hDCScreen = GetDC(NULL);
+
+ hFontT=SelectObject(hDCScreen, hFont);
+
+ // get the extent of our label
+ GetTextExtentPoint(hDCScreen, szTempBuff, cch, &size);
+
+ cxString = size.cx;
+ cyString = size.cy;
+
+ // Select in the font we want to use
+ if (fPrintText)
+ SelectObject(hDC, hFont);
+
+ // String is smaller than max string - just center, ETO, and return.
+ if (cxString <= cxMaxString)
+ {
+
+ if (fPrintText)
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxString) / 2,
+ nYStart,
+ fuOptions,
+ lpRect,
+ szTempBuff,
+ cch,
+ NULL);
+
+ iLastLineStart = 0; // only 1 line of text
+ goto CleanupAndLeave;
+ }
+
+ // String is too long...we've got to word-wrap it.
+
+
+ // Are there any spaces, slashes, tabs, or bangs in string?
+
+ if (lstrlen(szTempBuff) != (int)strcspn(szTempBuff, szSeparators))
+ {
+ // Yep, we've got spaces, so we'll try to find the largest
+ // space-terminated string that will fit on the first line.
+
+ index = cch;
+
+
+ while (index >= 0)
+ {
+
+ char cchKeep;
+
+ // scan the string backwards for spaces, slashes, tabs, or bangs
+
+ while (!IS_SEPARATOR(szTempBuff[index]) )
+ index--;
+
+
+ if (index <= 0)
+ break;
+
+ cchKeep = szTempBuff[index]; // remember what char was there
+
+ szTempBuff[index] = '\0'; // just for now
+
+ GetTextExtentPoint(
+ hDCScreen, (LPSTR)szTempBuff,lstrlen((LPSTR)szTempBuff),&size);
+
+ cxFirstLine = size.cx;
+ cyFirstLine = size.cy;
+
+ szTempBuff[index] = cchKeep; // put the right char back
+
+ if (cxFirstLine <= cxMaxString)
+ {
+
+ iLastLineStart = index + 1;
+
+ if (!fPrintText)
+ goto CleanupAndLeave;
+
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxFirstLine) / 2,
+ nYStart,
+ fuOptions,
+ lpRect,
+ (LPSTR)szTempBuff,
+ index + 1,
+ lpDX);
+
+ lpszSecondLine = (LPSTR)szTempBuff;
+
+ lpszSecondLine += index + 1;
+
+ GetTextExtentPoint(hDCScreen,
+ lpszSecondLine,
+ lstrlen(lpszSecondLine),
+ &size);
+
+ // If the second line is wider than the rectangle, we
+ // just want to clip the text.
+ cxSecondLine = min(size.cx, cxMaxString);
+
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxSecondLine) / 2,
+ nYStart + cyFirstLine,
+ fuOptions,
+ lpRect,
+ lpszSecondLine,
+ lstrlen(lpszSecondLine),
+ lpDX);
+
+ goto CleanupAndLeave;
+
+ } // end if
+
+ index--;
+
+ } // end while
+
+ } // end if
+
+ // Here, there are either no spaces in the string (strchr(szTempBuff, ' ')
+ // returned NULL), or there spaces in the string, but they are
+ // positioned so that the first space terminated string is still
+ // longer than one line. So, we walk backwards from the end of the
+ // string until we find the largest string that will fit on the first
+ // line , and then we just clip the second line.
+
+ cch = lstrlen((LPSTR)szTempBuff);
+
+ chKeep = szTempBuff[cch];
+ szTempBuff[cch] = '\0';
+
+ GetTextExtentPoint(hDCScreen, szTempBuff, lstrlen(szTempBuff),&size);
+
+ cxFirstLine = size.cx;
+ cyFirstLine = size.cy;
+
+ while (cxFirstLine > cxMaxString)
+ {
+ // We allow 40 characters in the label, but the metafile is
+ // only as wide as 10 W's (for aesthetics - 20 W's wide looked
+ // dumb. This means that if we split a long string in half (in
+ // terms of characters), then we could still be wider than the
+ // metafile. So, if this is the case, we just step backwards
+ // from the halfway point until we get something that will fit.
+ // Since we just let ETO clip the second line
+
+ szTempBuff[cch--] = chKeep;
+ if (0 == cch)
+ goto CleanupAndLeave;
+
+ chKeep = szTempBuff[cch];
+ szTempBuff[cch] = '\0';
+
+ GetTextExtentPoint(
+ hDCScreen, szTempBuff, lstrlen(szTempBuff), &size);
+ cxFirstLine = size.cx;
+ }
+
+ iLastLineStart = cch;
+
+ if (!fPrintText)
+ goto CleanupAndLeave;
+
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxFirstLine) / 2,
+ nYStart,
+ fuOptions,
+ lpRect,
+ (LPSTR)szTempBuff,
+ lstrlen((LPSTR)szTempBuff),
+ lpDX);
+
+ szTempBuff[cch] = chKeep;
+ lpszSecondLine = szTempBuff;
+ lpszSecondLine += cch;
+
+ GetTextExtentPoint(
+ hDCScreen, (LPSTR)lpszSecondLine, lstrlen(lpszSecondLine), &size);
+
+ // If the second line is wider than the rectangle, we
+ // just want to clip the text.
+ cxSecondLine = min(size.cx, cxMaxString);
+
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxSecondLine) / 2,
+ nYStart + cyFirstLine,
+ fuOptions,
+ lpRect,
+ lpszSecondLine,
+ lstrlen(lpszSecondLine),
+ lpDX);
+
+CleanupAndLeave:
+ SelectObject(hDCScreen, hFontT);
+ ReleaseDC(NULL, hDCScreen);
+ return iLastLineStart;
+
+}
+
+
+/*
+ * OleStdGetUserTypeOfClass(REFCLSID, LPSTR, UINT, HKEY)
+ *
+ * Purpose:
+ * Returns the user type (human readable class name) of the specified class.
+ *
+ * Parameters:
+ * rclsid pointer to the clsid to retrieve user type of.
+ * lpszUserType pointer to buffer to return user type in.
+ * cch length of buffer pointed to by lpszUserType
+ * hKey hKey for reg db - if this is NULL, then we
+ * open and close the reg db within this function. If it
+ * is non-NULL, then we assume it's a valid key to the
+ * \ root and use it without closing it. (useful
+ * if you're doing lots of reg db stuff).
+ *
+ * Return Value:
+ * UINT Number of characters in returned string. 0 on error.
+ *
+ */
+STDAPI_(UINT) OleStdGetUserTypeOfClass(REFCLSID rclsid, LPSTR lpszUserType, UINT cch, HKEY hKey)
+{
+
+ LONG dw;
+ LONG lRet;
+ LPSTR lpszCLSID, lpszProgID;
+ BOOL fFreeProgID = FALSE;
+ BOOL bCloseRegDB = FALSE;
+ char szKey[128];
+ LPMALLOC lpIMalloc;
+
+ if (hKey == NULL)
+ {
+
+ //Open up the root key.
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ return (UINT)FALSE;
+
+ bCloseRegDB = TRUE;
+ }
+
+ // Get a string containing the class name
+ StringFromCLSID(rclsid, &lpszCLSID);
+
+ wsprintf(szKey, "CLSID\\%s", lpszCLSID);
+
+
+ dw=cch;
+ lRet = RegQueryValue(hKey, szKey, lpszUserType, &dw);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ dw = 0;
+
+ if ( ((LONG)ERROR_SUCCESS!=lRet) && (CoIsOle1Class(rclsid)) )
+ {
+ // We've got an OLE 1.0 class, so let's try to get the user type
+ // name from the ProgID entry.
+
+ ProgIDFromCLSID(rclsid, &lpszProgID);
+ fFreeProgID = TRUE;
+
+ dw = cch;
+ lRet = RegQueryValue(hKey, lpszProgID, lpszUserType, &dw);
+
+ if ((LONG)ERROR_SUCCESS != lRet)
+ dw = 0;
+ }
+
+
+ if (NOERROR == CoGetMalloc(MEMCTX_TASK, &lpIMalloc))
+ {
+ if (fFreeProgID)
+ lpIMalloc->Free((LPVOID)lpszProgID);
+
+ lpIMalloc->Free((LPVOID)lpszCLSID);
+ lpIMalloc->Release();
+ }
+
+ if (bCloseRegDB)
+ RegCloseKey(hKey);
+
+ return (UINT)dw;
+
+}
+
+
+
+/*
+ * OleStdGetAuxUserType(RCLSID, WORD, LPSTR, int, HKEY)
+ *
+ * Purpose:
+ * Returns the specified AuxUserType from the reg db.
+ *
+ * Parameters:
+ * rclsid pointer to the clsid to retrieve aux user type of.
+ * hKey hKey for reg db - if this is NULL, then we
+ * open and close the reg db within this function. If it
+ * is non-NULL, then we assume it's a valid key to the
+ * \ root and use it without closing it. (useful
+ * if you're doing lots of reg db stuff).
+ * wAuxUserType which aux user type field to look for. In 4/93 release
+ * 2 is short name and 3 is exe name.
+ * lpszUserType pointer to buffer to return user type in.
+ * cch length of buffer pointed to by lpszUserType
+ *
+ * Return Value:
+ * UINT Number of characters in returned string. 0 on error.
+ *
+ */
+STDAPI_(UINT) OleStdGetAuxUserType(REFCLSID rclsid,
+ WORD wAuxUserType,
+ LPSTR lpszAuxUserType,
+ int cch,
+ HKEY hKey)
+{
+ HKEY hThisKey;
+ BOOL fCloseRegDB = FALSE;
+ LONG dw;
+ LRESULT lRet;
+ LPSTR lpszCLSID;
+ LPMALLOC lpIMalloc;
+ char szKey[OLEUI_CCHKEYMAX];
+ char szTemp[32];
+
+ lpszAuxUserType[0] = '\0';
+
+ if (NULL == hKey)
+ {
+ lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hThisKey);
+
+ if (ERROR_SUCCESS != lRet)
+ return 0;
+ }
+ else
+ hThisKey = hKey;
+
+ StringFromCLSID(rclsid, &lpszCLSID);
+
+ lstrcpy(szKey, "CLSID\\");
+ lstrcat(szKey, lpszCLSID);
+ wsprintf(szTemp, "\\AuxUserType\\%d", wAuxUserType);
+ lstrcat(szKey, szTemp);
+
+ dw = cch;
+
+ lRet = RegQueryValue(hThisKey, szKey, lpszAuxUserType, &dw);
+
+ if (ERROR_SUCCESS != lRet) {
+ dw = 0;
+ lpszAuxUserType[0] = '\0';
+ }
+
+
+ if (fCloseRegDB)
+ RegCloseKey(hThisKey);
+
+ if (NOERROR == CoGetMalloc(MEMCTX_TASK, &lpIMalloc))
+ {
+ lpIMalloc->Free((LPVOID)lpszCLSID);
+ lpIMalloc->Release();
+ }
+
+ return (UINT)dw;
+}
+
+
+
+/*
+ * PointerToNthField
+ *
+ * Purpose:
+ * Returns a pointer to the beginning of the nth field.
+ * Assumes null-terminated string.
+ *
+ * Parameters:
+ * lpszString string to parse
+ * nField field to return starting index of.
+ * chDelimiter char that delimits fields
+ *
+ * Return Value:
+ * LPSTR pointer to beginning of nField field.
+ * NOTE: If the null terminator is found
+ * Before we find the Nth field, then
+ * we return a pointer to the null terminator -
+ * calling app should be sure to check for
+ * this case.
+ *
+ */
+LPSTR FAR PASCAL PointerToNthField(LPSTR lpszString, int nField, char chDelimiter)
+{
+ LPSTR lpField = lpszString;
+ int cFieldFound = 1;
+
+ if (1 ==nField)
+ return lpszString;
+
+ while (*lpField != '\0')
+ {
+
+ if (*lpField++ == chDelimiter)
+ {
+
+ cFieldFound++;
+
+ if (nField == cFieldFound)
+ return lpField;
+ }
+ }
+
+ return lpField;
+
+}
+
+
+
+/*
+ * XformWidthInPixelsToHimetric
+ * XformWidthInHimetricToPixels
+ * XformHeightInPixelsToHimetric
+ * XformHeightInHimetricToPixels
+ *
+ * Functions to convert an int between a device coordinate system and
+ * logical HiMetric units.
+ *
+ * Parameters:
+ * hDC HDC providing reference to the pixel mapping. If
+ * NULL, a screen DC is used.
+ *
+ * Size Functions:
+ * lpSizeSrc LPSIZEL providing the structure to convert. This
+ * contains pixels in XformSizeInPixelsToHimetric and
+ * logical HiMetric units in the complement function.
+ * lpSizeDst LPSIZEL providing the structure to receive converted
+ * units. This contains pixels in
+ * XformSizeInPixelsToHimetric and logical HiMetric
+ * units in the complement function.
+ *
+ * Width Functions:
+ * iWidth int containing the value to convert.
+ *
+ * Return Value:
+ * Size Functions: None
+ * Width Functions: Converted value of the input parameters.
+ *
+ * NOTE:
+ * When displaying on the screen, Window apps display everything enlarged
+ * from its actual size so that it is easier to read. For example, if an
+ * app wants to display a 1in. horizontal line, that when printed is
+ * actually a 1in. line on the printed page, then it will display the line
+ * on the screen physically larger than 1in. This is described as a line
+ * that is "logically" 1in. along the display width. Windows maintains as
+ * part of the device-specific information about a given display device:
+ * LOGPIXELSX -- no. of pixels per logical in along the display width
+ * LOGPIXELSY -- no. of pixels per logical in along the display height
+ *
+ * The following formula converts a distance in pixels into its equivalent
+ * logical HIMETRIC units:
+ *
+ * DistInHiMetric = (HIMETRIC_PER_INCH * DistInPix)
+ * -------------------------------
+ * PIXELS_PER_LOGICAL_IN
+ *
+ */
+STDAPI_(int) XformWidthInPixelsToHimetric(HDC hDC, int iWidthInPix)
+ {
+ int iXppli; //Pixels per logical inch along width
+ int iWidthInHiMetric;
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
+
+ //We got pixel units, convert them to logical HIMETRIC along the display
+ iWidthInHiMetric = MAP_PIX_TO_LOGHIM(iWidthInPix, iXppli);
+
+ if (fSystemDC)
+ ReleaseDC(NULL, hDC);
+
+ return iWidthInHiMetric;
+ }
+
+
+STDAPI_(int) XformWidthInHimetricToPixels(HDC hDC, int iWidthInHiMetric)
+ {
+ int iXppli; //Pixels per logical inch along width
+ int iWidthInPix;
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
+
+ //We got logical HIMETRIC along the display, convert them to pixel units
+ iWidthInPix = MAP_LOGHIM_TO_PIX(iWidthInHiMetric, iXppli);
+
+ if (fSystemDC)
+ ReleaseDC(NULL, hDC);
+
+ return iWidthInPix;
+ }
+
+
+STDAPI_(int) XformHeightInPixelsToHimetric(HDC hDC, int iHeightInPix)
+ {
+ int iYppli; //Pixels per logical inch along height
+ int iHeightInHiMetric;
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iYppli = GetDeviceCaps (hDC, LOGPIXELSY);
+
+ //* We got pixel units, convert them to logical HIMETRIC along the display
+ iHeightInHiMetric = MAP_PIX_TO_LOGHIM(iHeightInPix, iYppli);
+
+ if (fSystemDC)
+ ReleaseDC(NULL, hDC);
+
+ return iHeightInHiMetric;
+ }
+
+
+STDAPI_(int) XformHeightInHimetricToPixels(HDC hDC, int iHeightInHiMetric)
+ {
+ int iYppli; //Pixels per logical inch along height
+ int iHeightInPix;
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iYppli = GetDeviceCaps (hDC, LOGPIXELSY);
+
+ //* We got logical HIMETRIC along the display, convert them to pixel units
+ iHeightInPix = MAP_LOGHIM_TO_PIX(iHeightInHiMetric, iYppli);
+
+ if (fSystemDC)
+ ReleaseDC(NULL, hDC);
+
+ return iHeightInPix;
+ }
diff --git a/private/ole32/olethunk/ole16/ole2/icon.h b/private/ole32/olethunk/ole16/ole2/icon.h
new file mode 100644
index 000000000..fa337d6ce
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/icon.h
@@ -0,0 +1,64 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: icon.h
+//
+// Contents: icon.h from OLE2
+//
+// History: 11-Apr-94 DrewB Copied from OLE2
+//
+//----------------------------------------------------------------------------
+
+/*
+ * ICON.H
+ *
+ * This file contains definitions and function prototypes used in geticon.c
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#if !defined( _ICON_H )
+#define _ICON_H_
+
+#if !defined( IDS_DEFICONLABEL )
+#define IDS_DEFICONLABEL 310
+#endif
+
+STDAPI_(int) XformWidthInHimetricToPixels(HDC, int);
+STDAPI_(int) XformWidthInPixelsToHimetric(HDC, int);
+STDAPI_(int) XformHeightInHimetricToPixels(HDC, int);
+STDAPI_(int) XformHeightInPixelsToHimetric(HDC, int);
+
+HICON FAR PASCAL HIconAndSourceFromClass(REFCLSID, LPSTR, UINT FAR *);
+
+BOOL FAR PASCAL FIconFileFromClass(REFCLSID, LPSTR, UINT, UINT FAR *);
+
+LPSTR FAR PASCAL PointerToNthField(LPSTR, int, char);
+
+BOOL FAR PASCAL GetAssociatedExecutable(LPSTR, LPSTR);
+
+
+STDAPI_(UINT) OleStdGetAuxUserType(REFCLSID rclsid,
+ WORD wAuxUserType,
+ LPSTR lpszAuxUserType,
+ int cch,
+ HKEY hKey);
+
+STDAPI_(UINT) OleStdGetUserTypeOfClass(REFCLSID rclsid,
+ LPSTR lpszUserType,
+ UINT cch,
+ HKEY hKey);
+
+STDAPI_(UINT) OleStdIconLabelTextOut(HDC hDC,
+ HFONT hFont,
+ int nXStart,
+ int nYStart,
+ UINT fuOptions,
+ RECT FAR * lpRect,
+ LPSTR lpszString,
+ UINT cchString,
+ int FAR * lpDX);
+
+#endif // _ICON_H
diff --git a/private/ole32/olethunk/ole16/ole2/inplace.cxx b/private/ole32/olethunk/ole16/ole2/inplace.cxx
new file mode 100644
index 000000000..33f372b73
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/inplace.cxx
@@ -0,0 +1,224 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: inplace.cxx
+//
+// Contents: Stripped-down OLE2 inplace.cpp
+//
+// History: 11-Apr-94 DrewB Copied from OLE2
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <ole2int.h>
+
+#ifndef _MAC
+#include "inplace.h"
+#endif
+
+#ifndef _MAC
+
+WORD wSignature; // = (WORD) {'S', 'K'};
+
+UINT uOleMessage;
+
+#define OM_CLEAR_MENU_STATE 0 // lParam is NULL
+#define OM_COMMAND_ID 1 // LOWORD(lParam) contains the command ID
+
+OLEAPI OleTranslateAccelerator
+ (LPOLEINPLACEFRAME lpFrame, LPOLEINPLACEFRAMEINFO lpFrameInfo, LPMSG lpMsg)
+{
+ WORD cmd;
+ BOOL fFound;
+
+ fFound = IsAccelerator(lpFrameInfo->haccel, lpFrameInfo->cAccelEntries,
+ lpMsg, &cmd);
+
+ if (!fFound && lpFrameInfo->fMDIApp)
+ fFound = IsMDIAccelerator(lpMsg, &cmd);
+
+ if (fFound) {
+ AssertSz(lpFrameInfo->hwndFrame,
+ "OleTranslateAccelerator: Invalid lpFrameInfo->hwndFrame");
+ SendMessage(lpFrameInfo->hwndFrame, uOleMessage, OM_COMMAND_ID,
+ MAKELONG(cmd, 0));
+#ifdef _DEBUG
+ OutputDebugString((LPSTR)"IOleInPlaceFrame::TranslateAccelerator called\r\n");
+#endif
+ return lpFrame->TranslateAccelerator(lpMsg, cmd);
+
+ } else {
+ if (wSysKeyToKey(lpMsg) == WM_SYSCHAR) {
+ // Eat the message if it is "Alt -". This is supposed to bring
+ // MDI system menu down. But we can not support it. And we also
+ // don't want the message to be Translated by the object
+ // application either. So, we return as if it has been accepted by
+ // the container as an accelerator.
+
+ // If the container wants to support this it can have an
+ // accelerator for this. This is not an issue for SDI apps,
+ // because it will be thrown away by USER anyway.
+
+ if (lpMsg->wParam != '-')
+ SendMessage(lpFrameInfo->hwndFrame, lpMsg->message,
+ lpMsg->wParam, lpMsg->lParam);
+#ifdef _DEBUG
+ else
+ OutputDebugString((LPSTR)"OleTranslateAccelerator: Alt+ - key is discarded\r\n");
+#endif
+
+ return NOERROR;
+ }
+ }
+
+ return ResultFromScode(S_FALSE);
+}
+
+inline UINT wSysKeyToKey(LPMSG lpMsg)
+{
+ UINT message = lpMsg->message;
+
+ // if the ALT key is down when a key is pressed, then the 29th bit of the
+ // LPARAM will be set
+
+ // If the message was not made with the ALT key down, convert the message
+ // from a WM_SYSKEY* to a WM_KEY* message.
+
+ if (!(HIWORD(lpMsg->lParam) & 0x2000)
+ && (message >= WM_SYSKEYDOWN && message <= WM_SYSDEADCHAR))
+ message -= (WM_SYSKEYDOWN - WM_KEYDOWN);
+
+ return message;
+}
+
+
+OLEAPI_(BOOL) IsAccelerator
+ (HACCEL hAccel, int cAccelEntries, LPMSG lpMsg, WORD FAR* lpwCmd)
+{
+ WORD cmd = NULL;
+ WORD flags;
+ BOOL fFound = FALSE;
+ BOOL fVirt;
+ LPACCEL lpAccel = NULL;
+ UINT message;
+
+ message = wSysKeyToKey(lpMsg);
+
+ switch (message) {
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ fVirt = TRUE;
+ break;
+
+ case WM_CHAR:
+ case WM_SYSCHAR:
+ fVirt = FALSE;
+ break;
+
+ default:
+ goto errRtn;
+ }
+
+ if (! (hAccel && (lpAccel = (LPACCEL) LockResource(hAccel))))
+ goto errRtn;
+
+ if (! cAccelEntries)
+ goto errRtn;
+
+ do {
+ flags = lpAccel->fVirt;
+ if ((lpAccel->key != (WORD) lpMsg->wParam) ||
+ ((fVirt != 0) != ((flags & FVIRTKEY) != 0)))
+ goto Next;
+
+ if (fVirt) {
+ if ((GetKeyState(VK_SHIFT) < 0) != ((flags & FSHIFT) != 0))
+ goto Next;
+ if ((GetKeyState(VK_CONTROL) < 0) != ((flags & FCONTROL) != 0))
+ goto Next;
+ }
+
+ if ((GetKeyState(VK_MENU) < 0) != ((flags & FALT) != 0))
+ goto Next;
+
+ if (cmd = lpAccel->cmd)
+ fFound = TRUE;
+
+ goto errRtn;
+
+Next:
+ lpAccel++;
+
+ } while (--cAccelEntries);
+
+
+errRtn:
+ if (lpAccel)
+ UnlockResource(hAccel);
+
+ if (lpwCmd)
+ *lpwCmd = cmd;
+
+ return fFound;
+}
+
+
+
+BOOL IsMDIAccelerator(LPMSG lpMsg, WORD FAR* lpCmd)
+{
+ if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
+ return FALSE;
+
+ /* All of these have the control key down */
+ if (GetKeyState(VK_CONTROL) >= 0)
+ return FALSE;
+
+ if (GetKeyState(VK_MENU) < 0)
+ return FALSE;
+
+ switch ((WORD)lpMsg->wParam) {
+ case VK_F4:
+ *lpCmd = SC_CLOSE;
+
+ case VK_F6:
+ case VK_TAB:
+ if (GetKeyState(VK_SHIFT) < 0)
+ *lpCmd = SC_PREVWINDOW;
+ else
+ *lpCmd = SC_NEXTWINDOW;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+LPOLEMENU wGetOleMenuPtr(HOLEMENU holemenu)
+{
+ LPOLEMENU lpOleMenu;
+
+ if (! (holemenu
+ && (lpOleMenu = (LPOLEMENU) GlobalLock((HGLOBAL) holemenu))))
+ return NULL;
+
+ if (lpOleMenu->wSignature != wSignature) {
+ AssertSz(FALSE, "Error - handle is not a HOLEMENU");
+ GlobalUnlock((HGLOBAL) holemenu);
+ return NULL;
+ }
+
+ return lpOleMenu;
+}
+
+inline void wReleaseOleMenuPtr(HOLEMENU holemenu)
+{
+ GlobalUnlock((HGLOBAL) holemenu);
+}
+
+#endif // !_MAC
diff --git a/private/ole32/olethunk/ole16/ole2/inplace.h b/private/ole32/olethunk/ole16/ole2/inplace.h
new file mode 100644
index 000000000..7446d184a
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/inplace.h
@@ -0,0 +1,114 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: inplace.h
+//
+// Contents: inplace.h from OLE2
+//
+// History: 11-Apr-94 DrewB Copied from OLE2
+//
+//----------------------------------------------------------------------------
+
+#if !defined( _INPLACE_H_ )
+#define _INPLACE_H_
+
+// This ACCEL structure and the related constants definitions come with WIN32.
+// Win31 also uses the same stuff internally but it's not exposed in the
+// header files.
+
+#ifndef FVIRTKEY
+
+#define FVIRTKEY TRUE // Assumed to be == TRUE
+#define FLASTKEY 0x80 // Indicates last key in the table
+#define FNOINVERT 0x02
+#define FSHIFT 0x04
+#define FCONTROL 0x08
+#define FALT 0x10
+
+#pragma pack(1)
+typedef struct tagACCEL { // Accelerator Table structure
+ BYTE fVirt;
+ WORD key;
+ WORD cmd;
+} ACCEL, FAR* LPACCEL;
+#pragma pack()
+
+#endif // FVIRTKEY
+
+
+typedef struct tagOLEMENUITEM {
+ UINT item;
+ WORD fwPopup;
+ BOOL fObjectMenu;
+} OLEMENUITEM;
+typedef OLEMENUITEM FAR* LPOLEMENUITEM;
+
+typedef struct tagOLEMENU {
+ WORD wSignature;
+ HWND hwndFrame;
+ HMENU hmenuCombined;
+ OLEMENUGROUPWIDTHS MenuWidths;
+ LONG lMenuCnt;
+ OLEMENUITEM menuitem[1];
+} OLEMENU;
+typedef OLEMENU FAR* LPOLEMENU;
+
+
+class FAR CFrameFilter
+{
+public:
+ static HRESULT Create(HOLEMENU hOleMenu, HMENU hmenuCombined,
+ HWND hwndFrame, HWND hwndActiveObj,
+ LPOLEINPLACEFRAME lpFrame,
+ LPOLEINPLACEACTIVEOBJECT lpActiveObj);
+
+ CFrameFilter (HWND hwndFrame, HWND hwndActiveObj);
+ ~CFrameFilter(void);
+
+ inline LRESULT OnSysCommand(UINT uParam, LONG lParam);
+ inline void OnEnterMenuMode(void);
+ inline void OnExitMenuMode(void);
+ inline void OnEnterAltTabMode(void);
+ inline void OnExitAltTabMode(void);
+ inline LRESULT OnMessage(UINT msg, UINT uParam, LONG lParam);
+ inline void IsObjectMenu (UINT uMenuItem, UINT fwMenu);
+ inline BOOL IsMenuCollision(UINT uParam, LONG lParam);
+ inline BOOL DoContextSensitiveHelp();
+
+private:
+ HWND m_hwndObject;
+ HWND m_hwndFrame;
+ LPOLEINPLACEFRAME m_lpFrame;
+ LPOLEINPLACEACTIVEOBJECT m_lpObject;
+ WNDPROC m_lpfnPrevWndProc;
+ BOOL m_fObjectMenu;
+ BOOL m_fCurItemPopup;
+ BOOL m_fInMenuMode;
+ BOOL m_fDiscardWmCommand;
+ BOOL m_fGotMenuCloseEvent;
+ UINT m_cmdId;
+ UINT m_uCurItemID;
+ HOLEMENU m_hOleMenu;
+ HMENU m_hmenuCombined;
+ HWND m_hwndFocusOnEnter;
+ int m_cAltTab;
+};
+
+typedef CFrameFilter FAR* PCFRAMEFILTER;
+
+
+OLEAPI_(LRESULT) FrameWndFilterProc (HWND hwnd, UINT msg, UINT uParam, LONG lParam);
+OLEAPI_(LRESULT) MessageFilterProc(int nCode, WPARAM wParam, LPARAM lParam);
+
+BOOL IsMDIAccelerator(LPMSG lpMsg, WORD FAR* cmd);
+
+inline PCFRAMEFILTER wGetFrameFilterPtr(HWND hwndFrame);
+
+LPOLEMENU wGetOleMenuPtr(HOLEMENU holemenu);
+inline void wReleaseOleMenuPtr(HOLEMENU holemenu);
+
+inline UINT wSysKeyToKey(LPMSG lpMsg);
+
+#endif // _INPLACE_H
diff --git a/private/ole32/olethunk/ole16/ole2/lockbyte.cxx b/private/ole32/olethunk/ole16/ole2/lockbyte.cxx
new file mode 100644
index 000000000..61e1899b1
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/lockbyte.cxx
@@ -0,0 +1,120 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: lockbyte.cxx
+//
+// Contents: lockbyte.cpp from OLE2
+//
+// History: 11-Apr-94 DrewB Copied from OLE2
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <ole2int.h>
+
+#include "memstm.h"
+#include <reterr.h>
+
+// CreateILockBytesOnHGlobal
+//
+
+OLEAPI CreateILockBytesOnHGlobal
+ (HGLOBAL hGlobal,
+ BOOL fDeleteOnRelease,
+ LPLOCKBYTES FAR* pplkbyt)
+{
+ HANDLE hMem = NULL; // point to
+ struct MEMSTM FAR* pData = NULL; // a struct MEMSTM
+ ILockBytes FAR* pBytes = NULL;
+ DWORD cbSize = -1L;
+
+ VDATEPTRIN (pplkbyt, LPLOCKBYTES);
+ *pplkbyt = NULL;
+
+ if (NULL==hGlobal)
+ {
+ hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, 0);
+ if (hGlobal == NULL)
+ goto ErrorExit;
+ cbSize = 0;
+
+ // REVIEW: need to free this block if error below
+ }
+ else
+ {
+ cbSize = GlobalSize (hGlobal);
+ // Is there a way to verify a zero-sized handle?
+ if (cbSize!=0)
+ {
+ // verify validity of passed-in handle
+ if (NULL==GlobalLock(hGlobal))
+ {
+ // bad handle
+ return ResultFromScode (E_INVALIDARG);
+ }
+ GlobalUnlock (hGlobal);
+ }
+ }
+
+ hMem = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, sizeof (MEMSTM));
+ if (hMem == NULL)
+ goto ErrorExit;
+
+ pData = (MEMSTM FAR*)MAKELONG(0, HIWORD(GlobalHandle(hMem)));
+ if (pData == NULL)
+ goto FreeMem;
+
+ pData->cRef = 0;
+ pData->cb = cbSize;
+ pData->fDeleteOnRelease = fDeleteOnRelease;
+ pData->hGlobal = hGlobal;
+
+ pBytes = CMemBytes::Create(hMem); // Create the ILockBytes
+ if (pBytes == NULL)
+ goto FreeMem;
+
+ *pplkbyt = pBytes;
+ return NOERROR;
+
+FreeMem:
+ if (hMem)
+ GlobalFree(hMem);
+ErrorExit:
+ Assert (0);
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+}
+
+
+
+
+OLEAPI GetHGlobalFromILockBytes
+ (LPLOCKBYTES plkbyt,
+ HGLOBAL FAR* phglobal)
+{
+ VDATEIFACE (plkbyt);
+ VDATEPTRIN (phglobal, HANDLE);
+ *phglobal = NULL;
+ CMemBytes FAR* pCMemByte = (CMemBytes FAR*)plkbyt;
+
+ if (IsBadReadPtr (&(pCMemByte->m_dwSig), sizeof(ULONG))
+ || pCMemByte->m_dwSig != LOCKBYTE_SIG)
+ {
+ // we were passed someone else's implementation of ILockBytes
+ return ResultFromScode (E_INVALIDARG);
+ }
+
+ MEMSTM FAR* pMem= pCMemByte->m_pData;
+ if (NULL==pMem)
+ {
+ Assert (0);
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+ Assert (pMem->cb <= GlobalSize (pMem->hGlobal));
+ Verify (*phglobal = pMem->hGlobal);
+
+ return NOERROR;
+}
diff --git a/private/ole32/olethunk/ole16/ole2/makefile b/private/ole32/olethunk/ole16/ole2/makefile
new file mode 100644
index 000000000..fbeb7f7ff
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/makefile
@@ -0,0 +1,77 @@
+# ole2 Thunk DLL makefile
+#
+# Copyright (c) 1991, Microsoft Corporation
+#
+# History:
+#
+# 18-Feb-1994 BobDay Adapted from MVDM\WOW16\GDI\MAKEFILE
+#
+
+!IFDEF USEBUILD
+
+# If using BUILD.EXE, edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2.
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!ELSE
+
+default: copy_bin
+
+TARGET = ole2.dll
+CFILES = \
+ .\ole2dthk.c\
+ .\mondthk.c
+
+CXXFILES = \
+ .\ole2.cxx\
+ .\ole2guid.cxx\
+ .\ole2splt.cxx\
+ .\ole2lcl.cxx\
+ .\cdebug.cxx\
+ .\inplace.cxx\
+ .\lockbyte.cxx\
+ .\memstm.cxx\
+ .\icon.cxx
+
+RCFILES = .\ole2.rc
+LIBS = $(LIBS) \
+ ..\lib\shell.lib\
+ ..\lib\compobj.lib\
+ ..\lib\storage.lib
+
+!if "$(NTDEBUG)" != "" && "$(NTDEBUG)" != "retail"
+LIBS = $(LIBS) $(OLETHUNK)\debnot\$(OBJDIR)\debnot.lib
+!endif
+
+!include ..\makefile.inc
+
+copy_bin: all
+ -binplace $(OBJDIR)\ole2.dll
+ -binplace $(OBJDIR)\ole2.sym
+ -binplace $(OBJDIR)\ole2.map
+
+ole2.obj: ole2.cxx
+
+ole2dthk.obj: ole2dthk.c
+
+ole2splt.obj: ole2splt.cxx
+
+ole2lcl.obj: ole2lcl.cxx
+
+mondthk.obj: mondthk.c
+
+ole2guid.obj: ole2guid.cxx
+
+cdebug.obj: cdebug.cxx
+
+inplace.obj: inplace.cxx
+
+lockbyte.obj: lockbyte.cxx
+
+memstm.obj: memstm.cxx
+
+icon.obj: icon.cxx
+
+!ENDIF
diff --git a/private/ole32/olethunk/ole16/ole2/memstm.cxx b/private/ole32/olethunk/ole16/ole2/memstm.cxx
new file mode 100644
index 000000000..d7c686084
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/memstm.cxx
@@ -0,0 +1,1330 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: memstm.cxx
+//
+// Contents: memstm.cpp from OLE2
+//
+// History: 11-Apr-94 DrewB Copied from OLE2
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <ole2int.h>
+
+#include "memstm.h"
+#include <reterr.h>
+
+static const UINT grfMem = GMEM_SHARE | GMEM_MOVEABLE;
+
+// REVIEW: there is a lot of duplicate code. There used to be two separate
+// but identical structs: MEMSTM and MEMBYTES; the structs have be merged and
+// common code should be pulled out including: Release, AddRef, marshal, SetSize
+
+
+// Shared memory IStream implementation
+//
+
+OLEMETHODIMP CMemStm::QueryInterface(REFIID iidInterface, void FAR* FAR* ppvObj)
+{
+ M_PROLOG(this);
+ HRESULT error;
+
+ VDATEPTROUT( ppvObj, LPVOID );
+ *ppvObj = NULL;
+ VDATEIID( iidInterface );
+
+ // Two interfaces supported: IUnknown, IStream
+
+ if (m_pData != NULL &&
+ (iidInterface == IID_IStream || iidInterface == IID_IUnknown)) {
+
+ m_refs++; // A pointer to this object is returned
+ *ppvObj = this;
+ error = NOERROR;
+ } else
+//
+// BUGBUG - Renable this once CraigWi seperates Custom Marshalling stuff from
+// standard identity stuff. (Right now you can't get in between the standard
+// marshaller and the code which calls it, you're either completely custom
+// marshalling, or your not). Once it is better organized, we could marshall
+// a heap handle and the custom marshalling stuff. Then when unmarshalling in
+// the same wow, we unmarshal the heap handle, when not in the same wow, then
+// use the standard marshalling stuff.
+// Same goes for ILockBytesonHglobal below...
+//
+#define BOBDAY_DISABLE_MARSHAL_FOR_NOW
+#ifdef BOBDAY_DISABLE_MARSHAL_FOR_NOW
+#else
+ if (iidInterface == IID_IMarshal) {
+ *ppvObj = (LPVOID) CMarshalMemStm::Create(this);
+ if (*ppvObj != NULL)
+ error = NOERROR;
+ else
+ error = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ else
+#endif
+ { // Not accessible or unsupported interface
+ *ppvObj = NULL;
+ error = ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+
+ return error;
+}
+
+
+// Called when CMemStm is referenced by an additional pointer.
+//
+
+OLEMETHODIMP_(ULONG) CMemStm::AddRef(void)
+{
+ M_PROLOG(this);
+ return ++m_refs;
+}
+
+// Called when a pointer to this CMemStm is discarded
+//
+
+OLEMETHODIMP_(ULONG) CMemStm::Release(void)
+{
+ M_PROLOG(this);
+
+ if (--m_refs != 0) // Still used by others
+ return m_refs;
+
+ ReleaseMemStm(&m_hMem);
+
+ delete this; // Free storage
+ return 0;
+}
+
+
+OLEMETHODIMP CMemStm::Read(void HUGEP* pb, ULONG cb, ULONG FAR* pcbRead)
+{
+ M_PROLOG(this);
+ thkDebugOut((DEB_ITRACE,
+ "%p _IN CMemStm16::Read(pb=%p,cb=%lx)\n",
+ this,pb,cb));
+ HRESULT error = NOERROR;
+ ULONG cbRead = cb;
+
+ VDATEPTROUT( pb, char);
+ if (pcbRead) {
+ VDATEPTROUT( pcbRead, ULONG );
+ *pcbRead = 0L;
+ }
+
+ if (pcbRead != NULL)
+ *pcbRead = 0;
+
+ if (cbRead + m_pos > m_pData->cb)
+ {
+ // Caller is asking for more bytes than we have left
+ cbRead = m_pData->cb - m_pos;
+ }
+
+ if (cbRead > 0)
+ {
+ Assert (m_pData->hGlobal);
+ char HUGEP* pGlobal = GlobalLock (m_pData->hGlobal);
+ if (NULL==pGlobal)
+ {
+ Assert (0);
+ error = ResultFromScode (STG_E_READFAULT);
+ goto exitRtn;
+ }
+ UtMemCpy (pb, pGlobal + m_pos, cbRead);
+ GlobalUnlock (m_pData->hGlobal);
+ m_pos += cbRead;
+ }
+
+ if (pcbRead != NULL)
+ *pcbRead = cbRead;
+exitRtn:
+ thkDebugOut((DEB_ITRACE,
+ "%p OUT CMemStm16::Read() returns %lx\n",
+ this,error));
+ return error;
+}
+
+
+OLEMETHODIMP CMemStm::Write(void const HUGEP* pb, ULONG cb, ULONG FAR* pcbWritten)
+{
+ A5_PROLOG(this);
+ HRESULT error = NOERROR;
+ thkDebugOut((DEB_ITRACE,
+ "%p _IN CMemStm16::Write(pb=%p,cb=%lx)\n",
+ this,pb,cb));
+
+ ULONG cbWritten = cb;
+ ULARGE_INTEGER ularge_integer;
+ char HUGEP* pGlobal;
+
+ if ( pcbWritten ) {
+ VDATEPTROUT( pcbWritten, ULONG );
+ *pcbWritten = 0L;
+ }
+ VDATEPTRIN( pb , char );
+
+ if (pcbWritten != NULL)
+ *pcbWritten = 0;
+
+ if (cbWritten + m_pos > m_pData->cb) {
+ ULISet32( ularge_integer, m_pos+cbWritten );
+ error = SetSize(ularge_integer);
+ if (error != NOERROR)
+ goto Exit;
+ }
+
+ pGlobal = GlobalLock (m_pData->hGlobal);
+ if (NULL==pGlobal)
+ {
+ Assert (0);
+ error = ResultFromScode (STG_E_WRITEFAULT);
+ goto Exit;
+ }
+ UtMemCpy (pGlobal + m_pos, pb, cbWritten);
+ GlobalUnlock (m_pData->hGlobal);
+
+ m_pos += cbWritten;
+
+ if (pcbWritten != NULL)
+ *pcbWritten = cbWritten;
+
+Exit:
+ RESTORE_A5();
+ thkDebugOut((DEB_ITRACE,
+ "%p OUT CMemStm16::Write() returns %lx\n",
+ this,error));
+
+ return error;
+}
+
+OLEMETHODIMP CMemStm::Seek(LARGE_INTEGER dlibMoveIN, DWORD dwOrigin, ULARGE_INTEGER FAR* plibNewPosition)
+{
+ M_PROLOG(this);
+ thkDebugOut((DEB_ITRACE,"%p _IN CMemStm16::Seek()\n",this));
+
+ HRESULT error = NOERROR;
+ LONG dlibMove = dlibMoveIN.LowPart ;
+ ULONG cbNewPos = dlibMove;
+
+ if (plibNewPosition != NULL){
+ VDATEPTROUT( plibNewPosition, ULONG );
+ ULISet32(*plibNewPosition, m_pos);
+ }
+
+ switch(dwOrigin) {
+
+ case STREAM_SEEK_SET:
+ if (dlibMove >= 0)
+ m_pos = dlibMove;
+ else
+ error = ReportResult(0, E_UNSPEC, 0, 0); // BUGBUG - should return invalid seek
+ break;
+
+ case STREAM_SEEK_CUR:
+ if (!(dlibMove < 0 && ((ULONG) -dlibMove) > m_pos))
+ m_pos += dlibMove;
+ else
+ error = ReportResult(0, E_UNSPEC, 0, 0); // BUGBUG - should return invalid seek
+ break;
+
+ case STREAM_SEEK_END:
+ if (!(dlibMove < 0 && ((ULONG) -dlibMove) > m_pData->cb))
+ m_pos = m_pData->cb + dlibMove;
+ else
+ error = ReportResult(0, E_UNSPEC, 0, 0); // BUGBUG - should return invalid seek
+ break;
+
+ default:
+ error = ReportResult(0, E_UNSPEC, 0, 0); // BUGBUG - should return invalid seek mode
+ }
+
+ if (plibNewPosition != NULL)
+ ULISet32(*plibNewPosition, m_pos);
+
+ thkDebugOut((DEB_ITRACE,"%p OUT CMemStm16::Seek() returns %lx\n",this,error));
+
+ return error;
+}
+
+
+
+OLEMETHODIMP CMemStm::SetSize(ULARGE_INTEGER cb)
+{
+ M_PROLOG(this);
+ thkDebugOut((DEB_ITRACE,
+ "%p _IN CMemStm16::SetSize(cb=%lx%lx)\n",
+ this,cb.HighPart,cb.LowPart));
+ HANDLE hMemNew;
+ HRESULT hresult = NOERROR;
+
+ if (m_pData->cb == cb.LowPart)
+ {
+ goto errRtn;
+ }
+
+
+ hMemNew = GlobalReAlloc(m_pData->hGlobal,max (cb.LowPart,1),grfMem);
+
+ if (hMemNew == NULL)
+ {
+ hresult = ResultFromScode (E_OUTOFMEMORY);
+ goto errRtn;
+ }
+
+ m_pData->hGlobal = hMemNew;
+ m_pData->cb = cb.LowPart;
+
+errRtn:
+ thkDebugOut((DEB_ITRACE,
+ "%p OUT CMemStm16::SetSize() returns %lx\n",
+ this,
+ hresult));
+
+ return hresult;
+}
+
+
+OLEMETHODIMP CMemStm::CopyTo(IStream FAR *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER FAR * pcbRead,
+ ULARGE_INTEGER FAR * pcbWritten)
+{
+ thkDebugOut((DEB_ITRACE,
+ "%p _IN CMemStm16::CopyTo(pstm=%p)\n",
+ this,
+ pstm));
+
+ ULONG cbRead = cb.LowPart;
+ ULONG cbWritten = 0;
+ HRESULT hresult = NOERROR;
+
+ // pstm cannot be NULL
+
+ VDATEPTRIN(pstm, LPSTREAM);
+
+ // the spec says that if cb is it's maximum value (all bits set,
+ // since it's unsigned), then we will simply read the copy of
+ // this stream
+
+ if ( ~(cb.LowPart) == 0 && ~(cb.HighPart) == 0 )
+ {
+ cbRead = m_pData->cb - m_pos;
+ }
+ else if ( cb.HighPart > 0 )
+ {
+ // we assume that our memory stream cannot
+ // be large enough to accomodate very large (>32bit)
+ // copy to requests. Since this is probably an error
+ // on the caller's part, we assert.
+
+ thkAssert(!"WARNING: CopyTo request exceeds 32 bits");
+
+ // set the Read value to what's left, so that "Ignore"ing
+ // the assert works properly.
+
+ cbRead = m_pData->cb - m_pos;
+ }
+ else if ( cbRead + m_pos > m_pData->cb )
+ {
+ // more bytes were requested to read than we had left.
+ // cbRead is set to the amount remaining.
+
+ cbRead = m_pData->cb - m_pos;
+ }
+
+ // now write the data to the stream
+
+ if ( cbRead > 0 )
+ {
+ BYTE HUGEP* pGlobal = (BYTE HUGEP *)GlobalLock(
+ m_pData->hGlobal);
+
+ if( pGlobal == NULL )
+ {
+ thkAssert(!"GlobalLock failed");
+ hresult = (HRESULT)STG_E_INSUFFICIENTMEMORY;
+ goto errRtn;
+ }
+
+ hresult = pstm->Write(pGlobal + m_pos, cbRead, &cbWritten);
+
+ // in the error case, the spec says that the return values
+ // may be meaningless, so we do not need to do any special
+ // error handling here
+
+ GlobalUnlock(m_pData->hGlobal);
+ }
+
+ // increment our seek pointer and set the out parameters
+
+ m_pos += cbRead;
+
+ if( pcbRead )
+ {
+ ULISet32(*pcbRead, cbRead);
+ }
+
+ if( pcbWritten )
+ {
+ ULISet32(*pcbWritten, cbWritten);
+ }
+
+errRtn:
+ thkDebugOut((DEB_ITRACE,
+ "%p OUT CMemStm16::CopyTo(pstm=%p) returns %lx\n",
+ this,
+ pstm,
+ hresult));
+ return hresult;
+
+}
+
+OLEMETHODIMP CMemStm::Commit(DWORD grfCommitFlags)
+{
+ M_PROLOG(this);
+ return NOERROR; // since this stream is not transacted, no error
+}
+
+OLEMETHODIMP CMemStm::Revert(void)
+{
+ M_PROLOG(this);
+ return NOERROR; // nothing done
+}
+
+OLEMETHODIMP CMemStm::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
+{
+ M_PROLOG(this);
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+OLEMETHODIMP CMemStm::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
+{
+ M_PROLOG(this);
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+OLEMETHODIMP CMemStm::Stat(STATSTG FAR *pstatstg, DWORD statflag)
+{
+ M_PROLOG(this);
+ VDATEPTROUT( pstatstg, STATSTG );
+
+ pstatstg->pwcsName = NULL;
+ pstatstg->type = 0;
+ pstatstg->cbSize.HighPart = 0;
+ pstatstg->cbSize.LowPart = m_pData->cb;
+ pstatstg->mtime.dwLowDateTime = 0;
+ pstatstg->mtime.dwHighDateTime = 0;
+ pstatstg->ctime.dwLowDateTime = 0;
+ pstatstg->ctime.dwHighDateTime = 0;
+ pstatstg->atime.dwLowDateTime = 0;
+ pstatstg->atime.dwHighDateTime = 0;
+ pstatstg->grfMode = 0;
+ pstatstg->grfLocksSupported = 0;
+ pstatstg->clsid = CLSID_NULL;
+ pstatstg->grfStateBits = 0;
+ pstatstg->reserved = 0;
+
+ return NOERROR;
+}
+
+
+// returns new instance of pstm pointing to same data at same position.
+OLEMETHODIMP CMemStm::Clone(IStream FAR * FAR *ppstm)
+{
+ M_PROLOG(this);
+ CMemStm FAR* pCMemStm;
+
+ VDATEPTROUT (ppstm, LPSTREAM);
+
+ *ppstm = pCMemStm = CMemStm::Create(m_hMem);
+ if (pCMemStm == NULL)
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ pCMemStm->m_pos = m_pos;
+ return NOERROR;
+}
+
+
+// Create CMemStm. Handle must be a MEMSTM block.
+//
+
+OLESTATICIMP_(CMemStm FAR*) CMemStm::Create(HANDLE hMem)
+{
+ CMemStm FAR* pCMemStm;
+ struct MEMSTM FAR* pData;
+
+ pData = (MEMSTM FAR*)MAKELONG(0, HIWORD(GlobalHandle(hMem)));
+ if (pData == NULL)
+ return NULL;
+
+ // BUGBUG - Task alloc?
+ pCMemStm = new CMemStm;
+
+ if (pCMemStm == NULL)
+ return NULL;
+
+ // Initialize CMemStm
+ //
+ pCMemStm->m_hMem = hMem;
+ (pCMemStm->m_pData = pData)->cRef++; // AddRefMemStm
+ pCMemStm->m_refs = 1;
+ pCMemStm->m_dwSig = STREAM_SIG;
+
+ return pCMemStm;
+}
+
+
+
+
+// Allocate shared memory and create CMemStm on top of it.
+// Return pointer to the stream if done, NULL if error.
+// If the handle is returned, it must be free with ReleaseMemStm
+// (because of ref counting and the nested global handle).
+//
+
+
+OLEAPI_(LPSTREAM) CreateMemStm(DWORD cb, LPHANDLE phMem)
+{
+ HANDLE h;
+ thkDebugOut((DEB_ITRACE,
+ "%p _IN CreateMemStm16(cb=%lx,phMem=%p\n",0,cb,phMem));
+
+
+ LPSTREAM pstm = NULL;
+
+ if (phMem)
+ {
+ *phMem = NULL;
+ }
+
+
+ h = GlobalAlloc (grfMem, cb);
+ if (NULL==h)
+ {
+ goto errRtn;
+ }
+
+ if (CreateStreamOnHGlobal (h, TRUE, &pstm) != NOERROR)
+ {
+ pstm = NULL;
+ goto errRtn;
+ }
+ if (phMem)
+ {
+ // retrieve handle from just-created CMemStm
+ *phMem = ((CMemStm FAR*)pstm)->m_hMem;
+
+ // use pointer to bump ref count
+ Assert(((CMemStm FAR*)pstm)->m_pData != NULL);
+ ((CMemStm FAR*)pstm)->m_pData->cRef++; // AddRefMemStm
+ }
+
+errRtn:
+ thkDebugOut((DEB_ITRACE,
+ "%p OUT CreateMemStm16(cb=%lx,phMem=%p) returns %p\n",0,pstm));
+
+ return pstm;
+}
+
+
+// Create CMemStm on top of the specified hMem (which must be a MEMSTM block).
+// Return pointer to the stream if done, NULL if error.
+//
+OLEAPI_(LPSTREAM) CloneMemStm(HANDLE hMem)
+{
+ return CMemStm::Create(hMem); // Create the stream
+}
+
+
+
+OLEAPI_(void) ReleaseMemStm (LPHANDLE phMem, BOOL fInternalOnly)
+{
+ struct MEMSTM FAR* pData;
+
+ pData = (MEMSTM FAR*)MAKELONG(0, HIWORD(GlobalHandle(*phMem)));
+
+ // check for NULL pointer in case handle got freed already
+ // decrement ref count and free if no refs left
+ if (pData != NULL && --pData->cRef == 0)
+ {
+ if (pData->fDeleteOnRelease)
+ {
+ Verify (0==GlobalFree (pData->hGlobal));
+ }
+
+ if (!fInternalOnly)
+ {
+ Verify (0==GlobalFree(*phMem));
+ }
+ }
+ *phMem = NULL;
+}
+
+
+
+OLEAPI CreateStreamOnHGlobal
+ (HANDLE hGlobal,
+ BOOL fDeleteOnRelease,
+ LPSTREAM FAR* ppstm)
+{
+ thkDebugOut((DEB_ITRACE,
+ "%p _IN CreateStreamOnHGlobal16(hGlobal=%x)\n",0,hGlobal));
+
+ HANDLE hMem = NULL; // point to
+ struct MEMSTM FAR* pData = NULL; // a struct MEMSTM
+ LPSTREAM pstm = NULL;
+ DWORD cbSize = -1L;
+
+ VDATEPTRIN (ppstm, LPSTREAM);
+ *ppstm = NULL;
+ if (NULL==hGlobal)
+ {
+ hGlobal = GlobalAlloc(grfMem, 0);
+ if (hGlobal == NULL)
+ goto ErrorExit;
+ cbSize = 0;
+ }
+ else
+ {
+ cbSize = GlobalSize (hGlobal);
+ // Is there a way to verify a zero-sized handle?
+ if (cbSize!=0)
+ {
+ // verify validity of passed-in handle
+ if (NULL==GlobalLock(hGlobal))
+ {
+ // bad handle
+ return ResultFromScode (E_INVALIDARG);
+ }
+ GlobalUnlock (hGlobal);
+ }
+ }
+
+ hMem = GlobalAlloc (grfMem, sizeof (MEMSTM));
+ if (hMem == NULL)
+ goto ErrorExit;
+
+ pData = (MEMSTM FAR*)MAKELONG(0, HIWORD(GlobalHandle(hMem)));
+ if (pData == NULL)
+ goto FreeMem;
+
+ pData->cRef = 0;
+ pData->cb = cbSize;
+ pData->fDeleteOnRelease = fDeleteOnRelease;
+ pData->hGlobal = hGlobal;
+
+ pstm = CMemStm::Create(hMem);
+ if (pstm == NULL)
+ goto FreeMem;
+
+ *ppstm = pstm;
+ thkDebugOut((DEB_ITRACE,
+ "%p OUT CreateStreamOnHGlobal16() returns NOERROR\n",0));
+ return NOERROR;
+
+FreeMem:
+ if (hMem)
+ {
+ Verify(0==GlobalFree(hMem));
+ }
+ErrorExit:
+ Assert (0);
+ thkDebugOut((DEB_ITRACE,
+ "%p OUT CreateStreamOnHGlobal16() returns E_OUTOFMEMORY\n",0));
+
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+}
+
+
+OLEAPI GetHGlobalFromStream
+ (LPSTREAM pstm,
+ HGLOBAL FAR* phglobal)
+{
+ VDATEIFACE (pstm);
+ VDATEPTRIN (phglobal, HANDLE);
+
+ CMemStm FAR* pCMemStm = (CMemStm FAR*) pstm;
+ if (IsBadReadPtr (&(pCMemStm->m_dwSig), sizeof(ULONG))
+ || pCMemStm->m_dwSig != STREAM_SIG)
+ {
+ // we were passed someone else's implementation of ILockBytes
+ return ResultFromScode (E_INVALIDARG);
+ }
+
+ MEMSTM FAR* pMem= pCMemStm->m_pData;
+ if (NULL==pMem)
+ {
+ Assert (0);
+ return ResultFromScode (E_OUTOFMEMORY);
+ }
+ Assert (pMem->cb <= GlobalSize (pMem->hGlobal));
+ Verify (*phglobal = pMem->hGlobal);
+
+ return NOERROR;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Shared memory ILockBytes implementation
+//
+
+OLEMETHODIMP CMemBytes::QueryInterface(REFIID iidInterface,
+ void FAR* FAR* ppvObj)
+{
+ M_PROLOG(this);
+ HRESULT error;
+ VDATEPTROUT( ppvObj, LPVOID );
+ *ppvObj = NULL;
+ VDATEIID( iidInterface );
+
+ // Two interfaces supported: IUnknown, ILockBytes
+
+ if (m_pData != NULL &&
+ (iidInterface == IID_ILockBytes || iidInterface == IID_IUnknown)) {
+
+ m_refs++; // A pointer to this object is returned
+ *ppvObj = this;
+ error = NOERROR;
+ } else
+//
+// BUGBUG - See comment above for CMemStm::Queryinterface and IID_IMarshal
+//
+#ifdef BOBDAY_DISABLE_MARSHAL_FOR_NOW
+#else
+ if (iidInterface == IID_IMarshal) {
+ *ppvObj = (LPVOID) CMarshalMemBytes::Create(this);
+ if (*ppvObj != NULL)
+ error = NOERROR;
+ else
+ error = ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+ else
+#endif
+ { // Not accessible or unsupported interface
+ *ppvObj = NULL;
+ error = ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+
+ return error;
+}
+
+
+// Called when CMemBytes is referenced by an additional pointer.
+//
+OLEMETHODIMP_(ULONG) CMemBytes::AddRef(void)
+{
+ M_PROLOG(this);
+ return ++m_refs;
+}
+
+// Called when a pointer to this CMemBytes is discarded
+//
+OLEMETHODIMP_(ULONG) CMemBytes::Release(void)
+{
+ M_PROLOG(this);
+ if (--m_refs != 0) // Still used by others
+ return m_refs;
+
+ ReleaseMemStm(&m_hMem);
+
+ delete this; // Free storage
+ return 0;
+}
+
+
+OLEMETHODIMP CMemBytes::ReadAt(ULARGE_INTEGER ulOffset, void HUGEP* pb,
+ ULONG cb, ULONG FAR* pcbRead)
+{
+ M_PROLOG(this);
+ HRESULT error = NOERROR;
+ ULONG cbRead = cb;
+
+ VDATEPTROUT( pb, char );
+ if (pcbRead) {
+ VDATEPTROUT( pcbRead, ULONG );
+ *pcbRead = 0L;
+ }
+
+ if (cbRead + ulOffset.LowPart > m_pData->cb) {
+
+ if (ulOffset.LowPart > m_pData->cb)
+ cbRead = 0;
+ else
+ cbRead = m_pData->cb - ulOffset.LowPart;
+ }
+
+ if (cbRead > 0)
+ {
+ char HUGEP* pGlobal = GlobalLock (m_pData->hGlobal);
+ if (NULL==pGlobal)
+ {
+ Assert (0);
+ return ResultFromScode (STG_E_READFAULT);
+ }
+ UtMemCpy (pb, pGlobal + ulOffset.LowPart, cbRead);
+ GlobalUnlock (m_pData->hGlobal);
+ }
+
+ if (pcbRead != NULL)
+ *pcbRead = cbRead;
+
+ return error;
+}
+
+
+OLEMETHODIMP CMemBytes::WriteAt(ULARGE_INTEGER ulOffset, void const HUGEP* pb,
+ ULONG cb, ULONG FAR* pcbWritten)
+{
+ A5_PROLOG(this);
+ HRESULT error = NOERROR;
+ ULONG cbWritten = cb;
+ char HUGEP* pGlobal;
+
+ VDATEPTRIN( pb, char );
+
+ if (pcbWritten) {
+ VDATEPTROUT( pcbWritten, ULONG );
+ *pcbWritten = 0;
+ }
+
+ if (cbWritten + ulOffset.LowPart > m_pData->cb) {
+ ULARGE_INTEGER ularge_integer;
+ ULISet32( ularge_integer, ulOffset.LowPart + cbWritten);
+ error = SetSize( ularge_integer );
+ if (error != NOERROR)
+ goto Exit;
+ }
+
+ pGlobal = GlobalLock (m_pData->hGlobal);
+ if (NULL==pGlobal)
+ {
+ Assert (0);
+ return ResultFromScode (STG_E_WRITEFAULT);
+ }
+ UtMemCpy (pGlobal + ulOffset.LowPart, pb, cbWritten);
+ GlobalUnlock (m_pData->hGlobal);
+
+
+ if (pcbWritten != NULL)
+ *pcbWritten = cbWritten;
+
+Exit:
+ RESTORE_A5();
+ return error;
+}
+
+OLEMETHODIMP CMemBytes::Flush(void)
+{
+ M_PROLOG(this);
+ return NOERROR;
+}
+
+
+OLEMETHODIMP CMemBytes::SetSize(ULARGE_INTEGER cb)
+{
+ M_PROLOG(this);
+ HANDLE hMemNew;
+
+ if (m_pData->cb == cb.LowPart)
+ return NOERROR;
+
+ hMemNew = GlobalReAlloc(m_pData->hGlobal,
+ max (cb.LowPart, 1),
+ grfMem);
+
+ if (hMemNew == NULL)
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+ m_pData->hGlobal = hMemNew;
+ m_pData->cb = cb.LowPart;
+
+ return NOERROR;
+}
+
+
+OLEMETHODIMP CMemBytes::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
+{
+ // REVIEW - Docfile bug. Must return NOERROR for StgCreateDocfileOnILockbytes
+ M_PROLOG(this);
+ return NOERROR;
+}
+
+OLEMETHODIMP CMemBytes::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ // REVIEW - Docfiel bug. Must return NOERROR for StgCreateDocfileOnILockbytes
+ M_PROLOG(this);
+ return NOERROR;
+}
+
+
+OLEMETHODIMP CMemBytes::Stat(STATSTG FAR *pstatstg, DWORD statflag)
+{
+ M_PROLOG(this);
+ VDATEPTROUT( pstatstg, STATSTG );
+
+ pstatstg->pwcsName = NULL;
+ pstatstg->type = 0;
+ pstatstg->cbSize.HighPart = 0;
+ pstatstg->cbSize.LowPart = m_pData->cb;
+ pstatstg->mtime.dwLowDateTime = 0;
+ pstatstg->mtime.dwHighDateTime = 0;
+ pstatstg->ctime.dwLowDateTime = 0;
+ pstatstg->ctime.dwHighDateTime = 0;
+ pstatstg->atime.dwLowDateTime = 0;
+ pstatstg->atime.dwHighDateTime = 0;
+ pstatstg->grfMode = 0;
+ pstatstg->grfLocksSupported = 0;
+ pstatstg->clsid = CLSID_NULL;
+ pstatstg->grfStateBits = 0;
+ pstatstg->reserved = 0;
+
+ return NOERROR;
+}
+
+
+// Create CMemBytes. Handle must be a MEMSTM block.
+//
+OLESTATICIMP_(CMemBytes FAR*) CMemBytes::Create(HANDLE hMem)
+{
+ CMemBytes FAR* pCMemBytes;
+ struct MEMSTM FAR* pData;
+
+ pData = (MEMSTM FAR*)MAKELONG(0, HIWORD(GlobalHandle(hMem)));
+ if (pData == NULL)
+ return NULL;
+ Assert (pData->hGlobal);
+
+ // BUGBUG - Task alloc?
+ pCMemBytes = new CMemBytes;
+
+ if (pCMemBytes == NULL)
+ return NULL;
+
+ // Initialize CMemBytes
+ //
+ pCMemBytes->m_dwSig = LOCKBYTE_SIG;
+ pCMemBytes->m_hMem = hMem;
+ (pCMemBytes->m_pData = pData)->cRef++; // AddRefMemStm
+ pCMemBytes->m_refs = 1;
+
+ return pCMemBytes;
+}
+
+
+
+// CMemStm object's IMarshal implementation
+//
+
+OLEMETHODIMP CMarshalMemStm::QueryInterface(REFIID iidInterface,
+ void FAR* FAR* ppvObj)
+{
+ M_PROLOG(this);
+ HRESULT error;
+
+ VDATEPTROUT( ppvObj, LPVOID );
+ *ppvObj = NULL;
+ VDATEIID( iidInterface );
+
+ // Two interfaces supported: IUnknown, IMarshal
+
+ if (iidInterface == IID_IMarshal || iidInterface == IID_IUnknown) {
+ m_refs++; // A pointer to this object is returned
+ *ppvObj = this;
+ error = NOERROR;
+ }
+ else { // Not accessible or unsupported interface
+ *ppvObj = NULL;
+ error = ResultFromScode (E_NOINTERFACE);
+ }
+
+ return error;
+}
+
+
+// Called when CMarshalMemStm is referenced by an additional pointer.
+//
+
+OLEMETHODIMP_(ULONG) CMarshalMemStm::AddRef(void)
+{
+ M_PROLOG(this);
+ return ++m_refs;
+}
+
+// Called when a pointer to this CMarshalMemStm is discarded
+//
+
+
+OLEMETHODIMP_(ULONG) CMarshalMemStm::Release(void)
+{
+ M_PROLOG(this);
+ if (--m_refs != 0) // Still used by others
+ return m_refs;
+
+ if (m_pMemStm != NULL)
+ m_pMemStm->Release();
+
+ delete this; // Free storage
+ return 0;
+}
+
+
+// Returns the clsid of the object that created this CMarshalMemStm.
+//
+
+OLEMETHODIMP CMarshalMemStm::GetUnmarshalClass(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, CLSID FAR* pCid)
+{
+ M_PROLOG(this);
+ VDATEPTROUT( pCid, CLSID);
+ VDATEIID( riid );
+
+ *pCid = m_clsid;
+ return NOERROR;
+}
+
+
+OLEMETHODIMP CMarshalMemStm::GetMarshalSizeMax(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, DWORD FAR* pSize)
+{
+ M_PROLOG(this);
+ VDATEIID( riid );
+ VDATEIFACE( pv );
+ if (pSize) {
+ VDATEPTROUT( pSize, DWORD );
+ *pSize = NULL;
+ }
+
+ *pSize = sizeof(m_pMemStm->m_hMem);
+ return NOERROR;
+}
+
+
+OLEMETHODIMP CMarshalMemStm::MarshalInterface(IStream FAR* pStm,
+ REFIID riid, void FAR* pv,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags)
+{
+ M_PROLOG(this);
+ VDATEPTRIN( pStm, IStream );
+ VDATEIID( riid );
+ VDATEIFACE( pv );
+
+ if (m_pMemStm == NULL)
+ return ReportResult(0, E_UNSPEC, 0, 0);
+
+ if ((riid != IID_IStream && riid != IID_IUnknown) || pv != m_pMemStm)
+ return ReportResult(0, E_INVALIDARG, 0, 0);
+
+ // increase ref count on hglobal (ReleaseMarshalData has -- to match)
+ HRESULT error;
+ if ((error = pStm->Write(&m_pMemStm->m_hMem, sizeof(m_pMemStm->m_hMem),
+ NULL)) == NOERROR)
+ m_pMemStm->m_pData->cRef++; // AddRefMemStm
+
+ return error;
+}
+
+
+OLEMETHODIMP CMarshalMemStm::UnmarshalInterface(IStream FAR* pStm,
+ REFIID riid, void FAR* FAR* ppv)
+{
+ M_PROLOG(this);
+ HRESULT error;
+ HANDLE hMem;
+
+ VDATEPTROUT( ppv, LPVOID );
+ *ppv = NULL;
+ VDATEPTRIN( pStm, IStream );
+ VDATEIID( riid );
+
+ if (riid != IID_IStream && riid != IID_IUnknown)
+ return ReportResult(0, E_INVALIDARG, 0, 0);
+
+ error = pStm->Read(&hMem,sizeof(hMem),NULL);
+ if (error != NOERROR)
+ return error;
+
+ if (m_pMemStm != NULL) {
+
+ if (hMem != m_pMemStm->m_hMem)
+ return ReportResult(0, E_UNSPEC, 0, 0);
+ }
+ else {
+ m_pMemStm = (CMemStm FAR*) CloneMemStm(hMem);
+ if (m_pMemStm == NULL)
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ m_pMemStm->AddRef();
+ *ppv = (LPVOID) m_pMemStm;
+ return NOERROR;
+}
+
+
+OLEMETHODIMP CMarshalMemStm::ReleaseMarshalData(IStream FAR* pStm)
+{
+ M_PROLOG(this);
+ // reduce ref count on hglobal (matches that done in MarshalInterface)
+ HRESULT error;
+ HANDLE hMem;
+
+ VDATEIFACE( pStm );
+
+ error = pStm->Read(&hMem,sizeof(hMem),NULL);
+ if (error == NOERROR)
+ ReleaseMemStm(&hMem);
+
+ return error;
+}
+
+
+OLEMETHODIMP CMarshalMemStm::DisconnectObject(DWORD dwReserved)
+{
+ M_PROLOG(this);
+ return NOERROR;
+}
+
+
+OLESTATICIMP_(CMarshalMemStm FAR*) CMarshalMemStm::Create(CMemStm FAR* pMemStm)
+{
+ CMarshalMemStm FAR* pMMS;
+
+ //VDATEPTRIN rejects NULL
+ if( pMemStm )
+ GEN_VDATEPTRIN( pMemStm, CMemStm, (CMarshalMemStm FAR *) NULL );
+
+ // BUGBUG - Task alloc?
+ pMMS = new CMarshalMemStm;
+
+ if (pMMS == NULL)
+ return NULL;
+
+ if (pMemStm != NULL) {
+ pMMS->m_pMemStm = pMemStm;
+ pMMS->m_pMemStm->AddRef();
+ }
+
+ pMMS->m_clsid = CLSID_StdMemStm;
+
+ pMMS->m_refs = 1;
+
+ return pMMS;
+}
+
+
+OLEAPI_(IUnknown FAR*) CMemStmUnMarshal(void)
+{
+ return CMarshalMemStm::Create(NULL);
+}
+
+
+
+// CMemBytes object's IMarshal implementation
+//
+
+OLEMETHODIMP CMarshalMemBytes::QueryInterface(REFIID iidInterface,
+ void FAR* FAR* ppvObj)
+{
+ M_PROLOG(this);
+ HRESULT error;
+
+ VDATEIID( iidInterface );
+ VDATEPTROUT( ppvObj, LPVOID );
+ *ppvObj = NULL;
+
+ // Two interfaces supported: IUnknown, IMarshal
+
+ if (iidInterface == IID_IMarshal || iidInterface == IID_IUnknown) {
+ m_refs++; // A pointer to this object is returned
+ *ppvObj = this;
+ error = NOERROR;
+ }
+ else { // Not accessible or unsupported interface
+ *ppvObj = NULL;
+ error = ReportResult(0, E_NOINTERFACE, 0, 0);
+ }
+
+ return error;
+}
+
+
+// Called when CMarshalMemBytes is referenced by an additional pointer.
+//
+
+OLEMETHODIMP_(ULONG) CMarshalMemBytes::AddRef(void)
+{
+ M_PROLOG(this);
+ return ++m_refs;
+}
+
+// Called when a pointer to this CMarshalMemBytes is discarded
+//
+OLEMETHODIMP_(ULONG) CMarshalMemBytes::Release(void)
+{
+ M_PROLOG(this);
+ if (--m_refs != 0) // Still used by others
+ return m_refs;
+
+ if (m_pMemBytes != NULL)
+ m_pMemBytes->Release();
+
+ delete this; // Free storage
+ return 0;
+}
+
+
+// Returns the clsid of the object that created this CMarshalMemBytes.
+//
+OLEMETHODIMP CMarshalMemBytes::GetUnmarshalClass(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, CLSID FAR* pCid)
+{
+ M_PROLOG(this);
+ VDATEIID( riid );
+ VDATEIFACE( pv );
+
+ *pCid = m_clsid;
+ return NOERROR;
+}
+
+
+OLEMETHODIMP CMarshalMemBytes::GetMarshalSizeMax(REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags, DWORD FAR* pSize)
+{
+ M_PROLOG(this);
+ VDATEPTROUT( pSize, DWORD );
+ VDATEIID( riid );
+ VDATEIFACE( pv );
+
+ *pSize = sizeof(m_pMemBytes->m_hMem);
+ return NOERROR;
+}
+
+
+OLEMETHODIMP CMarshalMemBytes::MarshalInterface(IStream FAR* pStm,
+ REFIID riid, void FAR* pv, DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags)
+{
+ M_PROLOG(this);
+ VDATEPTRIN(pStm, IStream );
+ VDATEIID( riid );
+ if ( pv )
+ VDATEPTRIN( pv , char );
+
+ if (m_pMemBytes == NULL)
+ return ReportResult(0, E_UNSPEC, 0, 0);
+
+ if ((riid != IID_ILockBytes && riid != IID_IUnknown) || pv != m_pMemBytes)
+ return ReportResult(0, E_INVALIDARG, 0, 0);
+
+ // increase ref count on hglobal (ReleaseMarshalData has -- to match)
+ HRESULT error;
+ if ((error = pStm->Write(&m_pMemBytes->m_hMem, sizeof(m_pMemBytes->m_hMem),
+ NULL)) == NOERROR)
+ m_pMemBytes->m_pData->cRef++; // AddRefMemStm
+
+ return error;
+}
+
+
+OLEMETHODIMP CMarshalMemBytes::UnmarshalInterface(IStream FAR* pStm,
+ REFIID riid, void FAR* FAR* ppv)
+{
+ M_PROLOG(this);
+ HRESULT error;
+ HANDLE hMem;
+
+ VDATEPTROUT( ppv , LPVOID );
+ *ppv = NULL;
+ VDATEIFACE( pStm );
+ VDATEIID( riid );
+
+
+ if (riid != IID_ILockBytes && riid != IID_IUnknown)
+ return ReportResult(0, E_INVALIDARG, 0, 0);
+
+ error = pStm->Read(&hMem,sizeof(hMem),NULL);
+ if (error != NOERROR)
+ return error;
+
+ if (m_pMemBytes != NULL) {
+
+ if (hMem != m_pMemBytes->m_hMem)
+ return ReportResult(0, E_UNSPEC, 0, 0);
+ }
+ else {
+ m_pMemBytes = CMemBytes::Create(hMem); // Create the lockbytes
+
+ if (m_pMemBytes == NULL)
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+ }
+
+ m_pMemBytes->AddRef();
+ *ppv = (LPVOID) m_pMemBytes;
+ return NOERROR;
+}
+
+
+OLEMETHODIMP CMarshalMemBytes::ReleaseMarshalData(IStream FAR* pStm)
+{
+ // reduce ref count on hglobal (matches that done in MarshalInterface)
+ M_PROLOG(this);
+ HRESULT error;
+ MEMSTM FAR* pData;
+ HANDLE hMem;
+
+ VDATEIFACE( pStm );
+
+ error = pStm->Read(&hMem,sizeof(hMem),NULL);
+ if (error == NOERROR)
+ ReleaseMemStm(&hMem);
+
+ return error;
+}
+
+
+OLEMETHODIMP CMarshalMemBytes::DisconnectObject(DWORD dwReserved)
+{
+ M_PROLOG(this);
+ return NOERROR;
+}
+
+
+OLESTATICIMP_(CMarshalMemBytes FAR*) CMarshalMemBytes::Create(
+ CMemBytes FAR* pMemBytes)
+{
+ CMarshalMemBytes FAR* pMMB;
+
+ //VDATEPTRIN rejects NULL
+ if( pMemBytes )
+ GEN_VDATEPTRIN( pMemBytes, CMemBytes, (CMarshalMemBytes FAR *)NULL );
+
+ // BUGBUG - Task alloc?
+ pMMB = new CMarshalMemBytes;
+
+ if (pMMB == NULL)
+ return NULL;
+
+ if (pMemBytes != NULL) {
+ pMMB->m_pMemBytes = pMemBytes;
+ pMMB->m_pMemBytes->AddRef();
+ }
+
+ pMMB->m_clsid = CLSID_StdMemBytes;
+
+ pMMB->m_refs = 1;
+
+ return pMMB;
+}
+
+OLEAPI_(IUnknown FAR*) CMemBytesUnMarshal(void)
+{
+ return CMarshalMemBytes::Create(NULL);
+}
diff --git a/private/ole32/olethunk/ole16/ole2/memstm.h b/private/ole32/olethunk/ole16/ole2/memstm.h
new file mode 100644
index 000000000..440c0d7a8
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/memstm.h
@@ -0,0 +1,228 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: memstm.h
+//
+// Contents: memstm.h from OLE2
+//
+// History: 11-Apr-94 DrewB Copied from OLE2
+//
+//----------------------------------------------------------------------------
+
+#if !defined( _MEMSTM_H_ )
+#define _MEMSTM_H_
+
+// These defines shorten the class name so that the compiler doesn't
+// choke on really long decorated names for MarshalInterface
+#define CMarshalMemStm CMMS
+#define CMarshalMemBytes CMMB
+
+class FAR CMarshalMemStm;
+class FAR CMarshalMemBytes;
+
+// CMemStm is a stream implementation on top of global shared memory MEMSTM
+//
+// CMemStm
+// +---------+
+// + pvtf + Shared memory
+// +---------+ +--------------+
+// + m_pMem +-->|cb |
+// +---------+ |cRef |
+// |hGlobal |--->+--------------+
+// +--------------+ | Actual Data |
+// CMemStm MEMSTM +--------------+
+//
+struct MEMSTM { // Data in shared memory
+ DWORD cb; // Size of hGlobal
+ DWORD cRef; // See below
+ HANDLE hGlobal; // The data
+ BOOL fDeleteOnRelease;
+};
+
+// cRef counts all CMemStm pointers to this MEMSTM plus the number of times
+// a hMem handle to MEMSTM had been returned
+//
+#define STREAM_SIG (0x4d525453L)
+
+class FAR CMemStm : public IStream { // Shared emmory stream
+public:
+ OLEMETHOD(QueryInterface) (REFIID iidInterface, void FAR* FAR* ppvObj);
+ OLEMETHOD_(ULONG,AddRef) (void);
+ OLEMETHOD_(ULONG,Release) (void);
+ OLEMETHOD(Read) (VOID HUGEP* pv, ULONG cb, ULONG FAR* pcbRead);
+ OLEMETHOD(Write) (VOID const HUGEP* pv, ULONG cb, ULONG FAR* pcbWritten);
+ OLEMETHOD(Seek) (LARGE_INTEGER dlibMove,
+ DWORD dwOrigin, ULARGE_INTEGER FAR* plibNewPosition);
+ OLEMETHOD(SetSize) (ULARGE_INTEGER cb);
+ OLEMETHOD(CopyTo) (IStream FAR* pstm,
+ ULARGE_INTEGER cb, ULARGE_INTEGER FAR* pcbRead, ULARGE_INTEGER FAR* pcbWritten);
+ OLEMETHOD(Commit) (DWORD grfCommitFlags);
+ OLEMETHOD(Revert) (void);
+ OLEMETHOD(LockRegion) (ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType);
+ OLEMETHOD(UnlockRegion) (ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType);
+ OLEMETHOD(Stat) (STATSTG FAR* pstatstg, DWORD statflag);
+ OLEMETHOD(Clone)(IStream FAR * FAR *ppstm);
+
+ OLESTATIC_(CMemStm FAR*) Create(HANDLE hMem);
+
+ctor_dtor:
+ CMemStm() { GET_A5(); m_hMem = NULL; m_pData = NULL; m_pos = 0; m_refs = 0; }
+ ~CMemStm() {}
+
+private:
+ DWORD m_dwSig; // Signature indicating this is our
+ // implementation of IStream: STREAM_SIG
+ ULONG m_refs; // Number of references to this CmemStm
+ ULONG m_pos; // Seek pointer for Read/Write
+ HANDLE m_hMem; // Memory Handle passed on creation
+ MEMSTM FAR* m_pData; // Pointer to that memroy
+
+ friend HRESULT STDAPICALLTYPE GetHGlobalFromStream (LPSTREAM, HGLOBAL FAR*);
+ friend LPSTREAM STDAPICALLTYPE CreateMemStm (DWORD, LPHANDLE);
+ friend class CMarshalMemStm;
+ SET_A5;
+};
+
+
+
+
+// CMemBytes is an ILockBytes implementation on top of global shared
+// memory MEMSTM
+//
+// CMemBytes
+// +---------+
+// + pvtf + Shared memory
+// +---------+ +--------------+
+// + m_pData +-->| cb |
+// +---------+ | cRef |
+// | hGlobal |--->+-------------+
+// +--------------+ | Actual data |
+// CMemBytes MEMSTM +-------------+
+//
+
+#define LOCKBYTE_SIG (0x0046574A)
+
+// cRef counts all CMemBytes pointers to this MEMSTM.
+// It and fDeleteOnRelease control the GlobalFree'ing of the hGlobal.
+
+class FAR CMemBytes : public ILockBytes { // Shared memory lock bytes
+public:
+ OLEMETHOD(QueryInterface) (REFIID iidInterface, void FAR* FAR* ppvObj);
+ OLEMETHOD_(ULONG,AddRef) (void);
+ OLEMETHOD_(ULONG,Release) (void);
+ OLEMETHOD(ReadAt) (ULARGE_INTEGER ulOffset, VOID HUGEP *pv, ULONG cb,
+ ULONG FAR *pcbRead);
+ OLEMETHOD(WriteAt) (ULARGE_INTEGER ulOffset, VOID const HUGEP *pv, ULONG cb,
+ ULONG FAR *pcbWritten);
+ OLEMETHOD(Flush) (void);
+ OLEMETHOD(SetSize) (ULARGE_INTEGER cb);
+ OLEMETHOD(LockRegion) (ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType);
+ OLEMETHOD(UnlockRegion) (ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType);
+ OLEMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD statflag);
+
+ OLESTATIC_(CMemBytes FAR*) Create(HANDLE hMem);
+
+ctor_dtor:
+ CMemBytes() { GET_A5(); m_hMem = NULL; m_pData = NULL; m_refs = 0; }
+ ~CMemBytes() {}
+
+private:
+ DWORD m_dwSig; // Signature indicating this is our
+ // implementation of ILockBytes: LOCKBYTE_SIG
+ ULONG m_refs; // Normal reference count
+ HANDLE m_hMem; // Handle for bookeeping info (MEMSTM)
+ MEMSTM FAR* m_pData; // Pointer to that memroy
+
+ friend HRESULT STDAPICALLTYPE GetHGlobalFromILockBytes (LPLOCKBYTES, HGLOBAL FAR*);
+ friend class CMarshalMemBytes;
+ SET_A5;
+};
+
+
+// CMarshalMemStm can Marshal, Unmarshal CMemStm. It is impletented as
+// a seperate object accessible from CMemStm, CMemBytes: QueryIntreface of
+// IMarshal on CMemStm's IStream will return an IMarshal pointer to
+// CMarshalMemStm, but QueryInterface of IStream on that IMarshal will
+// fail.
+// Also QueryInterface of IUnknown on IMarshal will not return the same value
+// As QueryInterface of IUnkown on the original IStream.
+//
+class FAR CMarshalMemStm : public IMarshal {
+public:
+ OLEMETHOD(QueryInterface) (REFIID riid, LPVOID FAR* ppvObj);
+ OLEMETHOD_(ULONG,AddRef) (void);
+ OLEMETHOD_(ULONG,Release) (void);
+
+ OLEMETHOD(GetUnmarshalClass)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid);
+ OLEMETHOD(GetMarshalSizeMax)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize);
+ OLEMETHOD(MarshalInterface)(THIS_ IStream FAR* pStm, REFIID riid,
+ LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags);
+ OLEMETHOD(UnmarshalInterface)(THIS_ IStream FAR* pStm, REFIID riid,
+ LPVOID FAR* ppv);
+ OLEMETHOD(ReleaseMarshalData)(THIS_ IStream FAR* pStm);
+ OLEMETHOD(DisconnectObject)(THIS_ DWORD dwReserved);
+
+ OLESTATIC_(CMarshalMemStm FAR*) Create(CMemStm FAR* pMemStm);
+
+ctor_dtor:
+ CMarshalMemStm() { GET_A5();m_pMemStm = NULL; m_refs = 0; }
+ ~CMarshalMemStm() {}
+
+private:
+ ULONG m_refs; // Number of references to this CmemStm
+ CMemStm FAR* m_pMemStm; // Pointer to object [Un]Marshalled
+ CLSID m_clsid; // Class of object pointed by pUnk
+ SET_A5;
+};
+
+
+// CMarshalMemBytes can Marshal, Unmarshal CMemBytes. It is impletented as
+// a seperate object accessible from CMemBytes, CMemBytes: QueryIntreface of
+// IMarshal on CMemBytes's ILocBytes will return an IMarshal pointer to
+// CMarshalMemBytes, but QueryInterface of ILockBytes on that IMarshal will
+// fail.
+// Also QueryInterface of IUnknown on IMarshal will not return the same value
+// As QueryInterface of IUnkown on the original ILockBytes.
+//
+class FAR CMarshalMemBytes : public IMarshal {
+public:
+ OLEMETHOD(QueryInterface) (REFIID riid, LPVOID FAR* ppvObj);
+ OLEMETHOD_(ULONG,AddRef) (void);
+ OLEMETHOD_(ULONG,Release) (void);
+
+ OLEMETHOD(GetUnmarshalClass)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid);
+ OLEMETHOD(GetMarshalSizeMax)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize);
+ OLEMETHOD(MarshalInterface)(THIS_ IStream FAR* pStm, REFIID riid,
+ LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags);
+ OLEMETHOD(UnmarshalInterface)(THIS_ IStream FAR* pStm, REFIID riid,
+ LPVOID FAR* ppv);
+ OLEMETHOD(ReleaseMarshalData)(THIS_ IStream FAR* pStm);
+ OLEMETHOD(DisconnectObject)(THIS_ DWORD dwReserved);
+
+ OLESTATIC_(CMarshalMemBytes FAR*) Create(CMemBytes FAR* pMemBytes);
+
+ctor_dtor:
+ CMarshalMemBytes() { GET_A5();m_pMemBytes = NULL; m_refs = 0; }
+ ~CMarshalMemBytes() {}
+
+private:
+ ULONG m_refs; // Number of references to this CMemBytes
+ CMemBytes FAR* m_pMemBytes; // Pointer to object [Un]Marshalled
+ CLSID m_clsid; // Class of object pointed by pUnk
+ SET_A5;
+};
+
+
+#endif // _MemBytes_H
diff --git a/private/ole32/olethunk/ole16/ole2/mondthk.c b/private/ole32/olethunk/ole16/ole2/mondthk.c
new file mode 100644
index 000000000..daeb9fe51
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/mondthk.c
@@ -0,0 +1,451 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: mondthk.c (16 bit target)
+//
+// Contents: Moniker APIs that are directly thunked
+//
+// History: 17-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <call32.hxx>
+#include <apilist.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Function: BindMoniker, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pmk] --
+// [grfOpt] --
+// [iidResult] --
+// [ppvResult] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI BindMoniker(LPMONIKER pmk, DWORD grfOpt, REFIID iidResult,
+ LPVOID FAR* ppvResult)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_BindMoniker),
+ PASCAL_STACK_PTR(pmk));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: MkParseDisplayName, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pbc] --
+// [szUserName] --
+// [pchEaten] --
+// [ppmk] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI MkParseDisplayName(LPBC pbc, LPSTR szUserName,
+ ULONG FAR * pchEaten, LPMONIKER FAR * ppmk)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_MkParseDisplayName),
+ PASCAL_STACK_PTR(pbc));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: MonikerRelativePathTo, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pmkSrc] --
+// [pmkDest] --
+// [ppmkRelPath] --
+// [fCalledFromMethod] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI MonikerRelativePathTo(LPMONIKER pmkSrc, LPMONIKER pmkDest, LPMONIKER
+ FAR* ppmkRelPath, BOOL fCalledFromMethod)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_MonikerRelativePathTo),
+ PASCAL_STACK_PTR(pmkSrc));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: MonikerCommonPrefixWith, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pmkThis] --
+// [pmkOther] --
+// [ppmkCommon] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI MonikerCommonPrefixWith(LPMONIKER pmkThis, LPMONIKER pmkOther,
+ LPMONIKER FAR* ppmkCommon)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_MonikerCommonPrefixWith),
+ PASCAL_STACK_PTR(pmkThis));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateBindCtx, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [reserved] --
+// [ppbc] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CreateBindCtx(DWORD reserved, LPBC FAR* ppbc)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CreateBindCtx),
+ PASCAL_STACK_PTR(reserved));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateGenericComposite, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pmkFirst] --
+// [pmkRest] --
+// [ppmkComposite] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest,
+ LPMONIKER FAR* ppmkComposite)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CreateGenericComposite),
+ PASCAL_STACK_PTR(pmkFirst));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetClassFile, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [szFilename] --
+// [pclsid] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI GetClassFile (LPCSTR szFilename, CLSID FAR* pclsid)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_GetClassFile),
+ PASCAL_STACK_PTR(szFilename));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateFileMoniker, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [lpszPathName] --
+// [ppmk] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+// 3-15-95 alexgo Added hack for CorelDraw
+//
+// Notes: When Corel5.0 starts up, it creates a file moniker
+// with it's string clsid as the name. If the path name
+// is really CorelDraw, then call into olethk32 to set
+// an app compatibility flag.
+//
+// The flag that we set disables paste-link to yourself. CorelDraw
+// does not support this feature (because of a trashed memory
+// bug in 16bit OLE).
+//
+//----------------------------------------------------------------------------
+STDAPI CreateFileMoniker(LPSTR lpszPathName, LPMONIKER FAR* ppmk)
+{
+ static const char szCorelDraw[] =
+ "{11A11440-0394-101B-A72E-04021C007002}";
+
+
+ // just do a quick, manual string compare so we don't have to load
+ // the c runtime.
+
+ if( lpszPathName )
+ {
+ LPCSTR lpszCD = szCorelDraw;
+ LPSTR lpszPN = lpszPathName;
+
+ while( *lpszPN != '\0' && *lpszPN == *lpszCD && *lpszCD != '\0' )
+ {
+ lpszPN++;
+ lpszCD++;
+ }
+
+ if( *lpszCD == '\0' && *lpszPN == '\0' )
+ {
+ // the strings matched! Set the compatibility flag for CorelDraw
+ AddAppCompatFlag(OACF_CORELTRASHMEM);
+ }
+ }
+
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CreateFileMoniker),
+ PASCAL_STACK_PTR(lpszPathName));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateItemMoniker, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [lpszDelim] --
+// [lpszItem] --
+// [ppmk] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CreateItemMoniker(LPSTR lpszDelim, LPSTR lpszItem,
+ LPMONIKER FAR* ppmk)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CreateItemMoniker),
+ PASCAL_STACK_PTR(lpszDelim));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateAntiMoniker, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [ppmk] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CreateAntiMoniker(LPMONIKER FAR* ppmk)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CreateAntiMoniker),
+ PASCAL_STACK_PTR(ppmk));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreatePointerMoniker, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [punk] --
+// [ppmk] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CreatePointerMoniker(LPUNKNOWN punk, LPMONIKER FAR* ppmk)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CreatePointerMoniker),
+ PASCAL_STACK_PTR(punk));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetRunningObjectTable, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [reserved] --
+// [pprot] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI GetRunningObjectTable( DWORD reserved, LPRUNNINGOBJECTTABLE FAR* pprot)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_GetRunningObjectTable),
+ PASCAL_STACK_PTR(reserved));
+}
diff --git a/private/ole32/olethunk/ole16/ole2/ole2.cxx b/private/ole32/olethunk/ole16/ole2/ole2.cxx
new file mode 100644
index 000000000..3ec71dd00
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/ole2.cxx
@@ -0,0 +1,108 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ole2.cxx
+//
+// Contents: Thunk ole2.dll common code
+//
+// History: 07-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <call32.hxx>
+#include <apilist.hxx>
+
+#include <ole2int.h>
+
+DECLARE_INFOLEVEL(thk1);
+
+// Not in any OLE2 header
+extern UINT uOleMessage;
+
+HMODULE hmodOLE2 = NULL;
+
+//+---------------------------------------------------------------------------
+//
+// Function: LibMain, public, Local
+//
+// Synopsis: DLL initialization function
+//
+// Arguments: [hinst] - Instance handle
+// [wDataSeg] - Current DS
+// [cbHeapSize] - Heap size for the DLL
+// [lpszCmdLine] - Command line information
+//
+// Returns: One for success, zero for failure
+//
+// History: 21-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+static char achInfoLevel[32];
+#endif
+
+extern "C" int CALLBACK LibMain(HINSTANCE hinst,
+ WORD wDataSeg,
+ WORD cbHeapSize,
+ LPSTR lpszCmdLine)
+{
+#if DBG == 1
+ if (GetProfileString("olethk32", "ole2", "3", achInfoLevel,
+ sizeof(achInfoLevel)) > 0)
+ {
+ thk1InfoLevel = strtoul(achInfoLevel, NULL, 0);
+ }
+
+
+ if ((thk1InfoLevel == 3) &&
+ GetProfileString("olethk32", "Infolevel", "3", achInfoLevel,
+ sizeof(achInfoLevel)) > 0)
+ {
+ thk1InfoLevel = strtoul(achInfoLevel, NULL, 0);
+ }
+#endif
+
+#if defined(_CHICAGO_)
+ //
+ // BUGBUGCHICAGO
+ //
+ // The Chicago debugger doesn't like hinst not being wired.
+ //
+ GlobalWire(hinst);
+#endif
+
+ // The original OLE2 code does not check for success on this call
+ // so neither do we
+ uOleMessage = RegisterWindowMessage("OLE_MESSAHE");
+
+ hmodOLE2 = hinst;
+
+ return 1;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WEP, public, Local
+//
+// Synopsis: Windows Exit Point routine, for receiving DLL unload
+// notification
+//
+// Arguments: [nExitType] - Type of exit occurring
+//
+// Returns: One for success, zero for failure
+//
+// History: 21-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+extern "C" int CALLBACK WEP(int nExitType)
+{
+ // BUGBUG - Clean up thunk objects?
+ return 1;
+}
diff --git a/private/ole32/olethunk/ole16/ole2/ole2.def b/private/ole32/olethunk/ole16/ole2/ole2.def
new file mode 100644
index 000000000..03f4151e8
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/ole2.def
@@ -0,0 +1,183 @@
+LIBRARY OLE2
+;EXETYPE WINDOWS 3.0
+
+CODE MOVEABLE DISCARDABLE LOADONCALL SHARED
+
+SEGMENTS O_Init PRELOAD
+
+DATA MOVEABLE SINGLE
+
+HEAPSIZE 512
+
+EXPORTS
+ WEP @0 RESIDENTNAME
+ OLEBUILDVERSION @1
+ OLEINITIALIZE @2
+ OLEUNINITIALIZE @3
+ DLLGETCLASSOBJECT @4
+ ;; UNUSED @5
+ OLEQUERYLINKFROMDATA @6
+ OLEQUERYCREATEFROMDATA @7
+ OLECREATEFROMDATA @8
+ OLECREATELINKFROMDATA @9
+ OLECREATE @10
+ OLECREATELINK @11
+ OLELOAD @12
+ OLESAVE @13
+ OLERUN @14
+ ;; UNUSED @15
+ OLEISRUNNING @16
+ OLELOCKRUNNING @17
+ READCLASSSTG @18
+ WRITECLASSSTG @19
+ READCLASSSTM @20
+ WRITECLASSSTM @21
+ BINDMONIKER @22
+ MKPARSEDISPLAYNAME @23
+ OLESAVETOSTREAM @24
+ OLELOADFROMSTREAM @25
+ CREATEBINDCTX @26
+ CREATEITEMMONIKER @27
+ CREATEFILEMONIKER @28
+ CREATEGENERICCOMPOSITE @29
+ GETRUNNINGOBJECTTABLE @30
+ OLEGETMALLOC @31
+ RELEASESTGMEDIUM @32
+ READSTRINGSTREAM @33
+ WRITESTRINGSTREAM @34
+ REGISTERDRAGDROP @35
+ REVOKEDRAGDROP @36
+ DODRAGDROP @37
+ CREATEOLEADVISEHOLDER @38
+ CREATEDATAADVISEHOLDER @39
+ OLECREATEMENUDESCRIPTOR @40
+ OLESETMENUDESCRIPTOR @41
+ OLEDESTROYMENUDESCRIPTOR @42
+ OPENORCREATESTREAM @43
+ CREATEANTIMONIKER @44
+ CREATEPOINTERMONIKER @45
+ MONIKERRELATIVEPATHTO @46
+ MONIKERCOMMONPREFIXWITH @47
+ ISACCELERATOR @48
+ OLESETCLIPBOARD @49
+ OLEGETCLIPBOARD @50
+ OLEDUPLICATEDATA @51
+ OLEGETICONOFFILE @52
+ OLEGETICONOFCLASS @53
+ CREATEILOCKBYTESONHGLOBAL @54
+ GETHGLOBALFROMILOCKBYTES @55
+ OLEMETAFILEPICTFROMICONANDLABEL @56
+ GETCLASSFILE @57
+ OLEDRAW @58
+ OLECREATEDEFAULTHANDLER @59
+ OLECREATEEMBEDDINGHELPER @60
+ OLECONVERTISTORAGETOOLESTREAMEX @61
+ OLECONVERTOLESTREAMTOISTORAGEEX @62
+ SETDOCUMENTBITSTG @63
+ GETDOCUMENTBITSTG @64
+ WRITEOLESTG @65
+ READOLESTG @66
+ OLECREATEFROMFILE @67
+ OLECREATELINKTOFILE @68
+ CREATEDATACACHE @69
+ OLECONVERTISTORAGETOOLESTREAM @70
+ OLECONVERTOLESTREAMTOISTORAGE @71
+ READFMTUSERTYPESTG @74
+ WRITEFMTUSERTYPESTG @75
+ OLEFLUSHCLIPBOARD @76
+ OLEISCURRENTCLIPBOARD @77
+ OLETRANSLATEACCELERATOR @78
+ OLEDOAUTOCONVERT @79
+ OLEGETAUTOCONVERT @80
+ OLESETAUTOCONVERT @81
+ GETCONVERTSTG @82
+ SETCONVERTSTG @83
+ CREATESTREAMONHGLOBAL @84
+ GETHGLOBALFROMSTREAM @85
+
+ OLESETCONTAINEDOBJECT @86
+ OLENOTEOBJECTVISIBLE @87
+
+ OLECREATESTATICFROMDATA @88
+
+ OLEREGGETUSERTYPE @89
+ OLEREGGETMISCSTATUS @90
+ OLEREGENUMFORMATETC @91
+ OLEREGENUMVERBS @92
+ ;;OLEGETENUMFORMATETC @93 ; Used internally
+
+ ;; NOTE: API routines above this pointer (all upper case); DEBUG below
+ ;; *except* for the routines DbgDumpObject, DbgDumpExternalObject,
+ ;; DbgIsObjectValid, DbgDumpClassName, which are exposed in the debug
+ ;; version of the dll's shipped to ISV's
+
+ MAKEDEBUGSTREAM @100
+ ;; unused @101
+ ;; unused @102
+ ;; unused @103
+ DBGLOGOPEN @104
+ DBGLOGCLOSE @105
+ DBGLOGOUTPUTDEBUGSTRING @106
+ DBGLOGWRITE @107
+ DBGLOGTIMESTAMP @108
+ DBGLOGWRITEBANNER @109
+ DBGDUMPOBJECT @110
+ DBGISOBJECTVALID @111
+ DUMPALLOBJECTS @112
+ VALIDATEALLOBJECTS @113
+ DBGDUMPCLASSNAME @114
+ DBGDUMPEXTERNALOBJECT @115
+ ;; IIDs here
+
+ _IID_IEnumUnknown @120
+ _IID_IEnumString @121
+ _IID_IEnumMoniker @122
+ _IID_IEnumFORMATETC @123
+ _IID_IEnumOLEVERB @124
+ _IID_IEnumSTATDATA @125
+ _IID_IEnumGeneric @126
+ _IID_IEnumHolder @127
+ _IID_IEnumCallback @128
+ _IID_IPersistStream @129
+ _IID_IPersistStorage @130
+ _IID_IPersistFile @131
+ _IID_IPersist @132
+ _IID_IViewObject @133
+ _IID_IDataObject @134
+ _IID_IAdviseSink @135
+ _IID_IDataAdviseHolder @136
+ _IID_IOleAdviseHolder @137
+ _IID_IOleObject @138
+ _IID_IOleInPlaceObject @139
+ _IID_IOleWindow @140
+ _IID_IOleInPlaceUIWindow @141
+ _IID_IOleInPlaceFrame @142
+ _IID_IOleInPlaceActiveObject @143
+ _IID_IOleClientSite @144
+ _IID_IOleInPlaceSite @145
+ _IID_IParseDisplayName @146
+ _IID_IOleContainer @147
+ _IID_IOleItemContainer @148
+ _IID_IOleLink @149
+ _IID_IOleCache @150
+ _IID_IOleManager @151
+ _IID_IOlePresObj @152
+ _IID_IDropSource @153
+ _IID_IDropTarget @154
+ _IID_IDebug @155
+ _IID_IDebugStream @156
+ _IID_IAdviseSink2 @157
+ _IID_IViewObject2 @158
+ _IID_IOleCache2 @159
+ _IID_IOleCacheControl @160
+ _IID_IRunnableObject @161
+
+IMPORTS
+ KERNEL.LOADLIBRARYEX32W ;;@513 NODATA ;;
+ KERNEL.FREELIBRARY32W ;;@514 NODATA ;;
+ KERNEL.GETPROCADDRESS32W ;;@515 NODATA ;;
+ KERNEL.GETVDMPOINTER32W ;;@516 NODATA ;;
+ KERNEL.CALLPROC32W ;;@517 NODATA ;;
+
+;
+; functions statement file (appended by the makefile)
diff --git a/private/ole32/olethunk/ole16/ole2/ole2.rc b/private/ole32/olethunk/ole16/ole2/ole2.rc
new file mode 100644
index 000000000..b273e1f2d
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/ole2.rc
@@ -0,0 +1,42 @@
+#include "verinfo.h"
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION VER_FILEVERSION
+PRODUCTVERSION VER_PRODUCTVERSION
+FILEFLAGSMASK VER_FILEFLAGSMASK
+FILEFLAGS VER_FILEFLAGS
+FILEOS VER_FILEOS
+FILETYPE VER_FILETYPE
+FILESUBTYPE VER_FILESUBTYPE
+{
+ BLOCK "StringFileInfo"
+ {
+ BLOCK "040904E4"
+ {
+ VALUE "CompanyName", VER_COMPANYNAME_STR
+ VALUE "FileDescription", VER_FILEDESCRIPTION_STR
+ VALUE "FileVersion", VER_FILEVERSION_STR
+ VALUE "InternalName", "OLE2.DLL\0"
+ VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
+ VALUE "LegalTrademarks", VER_LEGALTRADEMARKS_STR
+ VALUE "ProductName", VER_PRODUCTNAME_STR
+ VALUE "ProductVersion", VER_PRODUCTVERSION_STR
+ VALUE "Comments", VER_COMMENT_STR
+ }
+ }
+ BLOCK "VarFileInfo"
+ {
+ VALUE "Translation", 0x409, 1252
+ }
+}
+
+CurNone CURSOR dragnone.cur
+CurMove CURSOR dragmove.cur
+CurCopy CURSOR dragcopy.cur
+CurLink CURSOR draglink.cur
+CurScrollMove CURSOR scrlmove.cur
+CurScrollCopy CURSOR scrlcopy.cur
+CurScrollLink CURSOR scrllink.cur
+
+;used by "..\src\def\geticon.c"
+DefIcon ICON default.ico
diff --git a/private/ole32/olethunk/ole16/ole2/ole2dthk.c b/private/ole32/olethunk/ole16/ole2/ole2dthk.c
new file mode 100644
index 000000000..a15116ffd
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/ole2dthk.c
@@ -0,0 +1,1803 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ole2dthk.cxx (16 bit target)
+//
+// Contents: OLE2 APIs that are directly thunked
+//
+// History: 17-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <ole2ver.h>
+
+#include <call32.hxx>
+#include <apilist.hxx>
+
+STDAPI_(HOLEMENU) OleCreateMenuDescriptor (HMENU hmenuCombined,
+ LPOLEMENUGROUPWIDTHS lplMenuWidths)
+{
+ return (HOLEMENU)CallObjectInWOW(THK_API_METHOD(THK_API_OleCreateMenuDescriptor),
+ PASCAL_STACK_PTR(hmenuCombined));
+}
+
+STDAPI OleDestroyMenuDescriptor (HOLEMENU holemenu)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleDestroyMenuDescriptor),
+ PASCAL_STACK_PTR(holemenu));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DllGetClassObject, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [clsid] --
+// [iid] --
+// [ppv] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void FAR* FAR* ppv)
+{
+ /* Relies on the fact that storage and ole2.dll both use the
+ same DllGetClassObject in ole32.dll */
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_DllGetClassObject),
+ PASCAL_STACK_PTR(clsid));
+}
+
+/* helper functions */
+//+---------------------------------------------------------------------------
+//
+// Function: ReadClassStg, Remote
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pStg] --
+// [pclsid] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI ReadClassStg(LPSTORAGE pStg, CLSID FAR* pclsid)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_ReadClassStg),
+ PASCAL_STACK_PTR(pStg));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteClassStg, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pStg] --
+// [rclsid] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI WriteClassStg(LPSTORAGE pStg, REFCLSID rclsid)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_WriteClassStg),
+ PASCAL_STACK_PTR(pStg));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteFmtUserTypeStg, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pstg] --
+// [cf] --
+// [lpszUserType] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI WriteFmtUserTypeStg (LPSTORAGE pstg, CLIPFORMAT cf, LPSTR lpszUserType)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_WriteFmtUserTypeStg),
+ PASCAL_STACK_PTR(pstg));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReadFmtUserTypeStg, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pstg] --
+// [pcf] --
+// [lplpszUserType] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI ReadFmtUserTypeStg (LPSTORAGE pstg, CLIPFORMAT FAR* pcf,
+ LPSTR FAR* lplpszUserType)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_ReadFmtUserTypeStg),
+ PASCAL_STACK_PTR(pstg));
+}
+
+/* APIs to query whether (Embedded/Linked) object can be created from
+ the data object */
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleQueryLinkFromData, Unknown
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pSrcDataObject] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleQueryLinkFromData(LPDATAOBJECT pSrcDataObject)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleQueryLinkFromData),
+ PASCAL_STACK_PTR(pSrcDataObject));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleQueryCreateFromData, Unknown
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pSrcDataObject] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleQueryCreateFromData(LPDATAOBJECT pSrcDataObject)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleQueryCreateFromData),
+ PASCAL_STACK_PTR(pSrcDataObject) );
+}
+
+
+
+/* Object creation APIs */
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleCreate, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [rclsid] --
+// [riid] --
+// [renderopt] --
+// [pFormatEtc] --
+// [pClientSite] --
+// [pStg] --
+// [ppvObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleCreate(REFCLSID rclsid, REFIID riid, DWORD renderopt,
+ LPFORMATETC pFormatEtc, LPOLECLIENTSITE pClientSite,
+ LPSTORAGE pStg, LPVOID FAR* ppvObj)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleCreate),
+ PASCAL_STACK_PTR(rclsid));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleCreateFromData, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pSrcDataObj] --
+// [riid] --
+// [renderopt] --
+// [pFormatEtc] --
+// [pClientSite] --
+// [pStg] --
+// [ppvObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleCreateFromData(LPDATAOBJECT pSrcDataObj, REFIID riid,
+ DWORD renderopt, LPFORMATETC pFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
+ LPVOID FAR* ppvObj)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleCreateFromData),
+ PASCAL_STACK_PTR(pSrcDataObj));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleCreateLinkFromData, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pSrcDataObj] --
+// [riid] --
+// [renderopt] --
+// [pFormatEtc] --
+// [pClientSite] --
+// [pStg] --
+// [ppvObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleCreateLinkFromData(LPDATAOBJECT pSrcDataObj, REFIID riid,
+ DWORD renderopt, LPFORMATETC pFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
+ LPVOID FAR* ppvObj)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleCreateLinkFromData),
+ PASCAL_STACK_PTR(pSrcDataObj));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleCreateStaticFromData, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pSrcDataObj] --
+// [iid] --
+// [renderopt] --
+// [pFormatEtc] --
+// [pClientSite] --
+// [pStg] --
+// [ppvObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleCreateStaticFromData(LPDATAOBJECT pSrcDataObj, REFIID iid,
+ DWORD renderopt, LPFORMATETC pFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
+ LPVOID FAR* ppvObj)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleCreateStaticFromData),
+ PASCAL_STACK_PTR(pSrcDataObj));
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleCreateLink, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pmkLinkSrc] --
+// [riid] --
+// [renderopt] --
+// [lpFormatEtc] --
+// [pClientSite] --
+// [pStg] --
+// [ppvObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleCreateLink(LPMONIKER pmkLinkSrc, REFIID riid,
+ DWORD renderopt, LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
+ LPVOID FAR* ppvObj)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleCreateLink),
+ PASCAL_STACK_PTR(pmkLinkSrc));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleCreateLinkToFile, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [lpszFileName] --
+// [riid] --
+// [renderopt] --
+// [lpFormatEtc] --
+// [pClientSite] --
+// [pStg] --
+// [ppvObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleCreateLinkToFile(LPCSTR lpszFileName, REFIID riid,
+ DWORD renderopt, LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg, LPVOID FAR* ppvObj)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleCreateLinkToFile),
+ PASCAL_STACK_PTR(lpszFileName));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleCreateFromFile, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [rclsid] --
+// [lpszFileName] --
+// [riid] --
+// [renderopt] --
+// [lpFormatEtc] --
+// [pClientSite] --
+// [pStg] --
+// [ppvObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleCreateFromFile(REFCLSID rclsid, LPCSTR lpszFileName, REFIID riid,
+ DWORD renderopt, LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
+ LPVOID FAR* ppvObj)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleCreateFromFile),
+ PASCAL_STACK_PTR(rclsid));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleLoad, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pStg] --
+// [riid] --
+// [pClientSite] --
+// [ppvObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleLoad(LPSTORAGE pStg, REFIID riid, LPOLECLIENTSITE pClientSite,
+ LPVOID FAR* ppvObj)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleLoad),
+ PASCAL_STACK_PTR(pStg));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleSave, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pPS] --
+// [pStg] --
+// [fSameAsLoad] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleSave(LPPERSISTSTORAGE pPS, LPSTORAGE pStg, BOOL fSameAsLoad)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleSave),
+ PASCAL_STACK_PTR(pPS));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleLoadFromStream, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pStm] --
+// [iidInterface] --
+// [ppvObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleLoadFromStream( LPSTREAM pStm, REFIID iidInterface,
+ LPVOID FAR* ppvObj)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleLoadFromStream),
+ PASCAL_STACK_PTR(pStm));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleSaveToStream, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pPStm] --
+// [pStm] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleSaveToStream( LPPERSISTSTREAM pPStm, LPSTREAM pStm )
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleSaveToStream),
+ PASCAL_STACK_PTR(pPStm));
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleSetContainedObject, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pUnknown] --
+// [fContained] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleSetContainedObject(LPUNKNOWN pUnknown, BOOL fContained)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleSetContainedObject),
+ PASCAL_STACK_PTR(pUnknown));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleNoteObjectVisible, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pUnknown] --
+// [fVisible] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleNoteObjectVisible(LPUNKNOWN pUnknown, BOOL fVisible)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleNoteObjectVisible),
+ PASCAL_STACK_PTR(pUnknown));
+}
+
+
+/* Drag/Drop APIs */
+
+//+---------------------------------------------------------------------------
+//
+// Function: RegisterDragDrop, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [hwnd] --
+// [pDropTarget] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI RegisterDragDrop(HWND hwnd, LPDROPTARGET pDropTarget)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_RegisterDragDrop),
+ PASCAL_STACK_PTR(hwnd));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: RevokeDragDrop, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [hwnd] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI RevokeDragDrop(HWND hwnd)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_RevokeDragDrop),
+ PASCAL_STACK_PTR(hwnd));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoDragDrop, Unknown
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pDataObj] --
+// [pDropSource] --
+// [dwOKEffects] --
+// [pdwEffect] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI DoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
+ DWORD dwOKEffects, LPDWORD pdwEffect)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_DoDragDrop),
+ PASCAL_STACK_PTR(pDataObj));
+}
+
+
+/* Clipboard APIs */
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleSetClipboard, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pDataObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleSetClipboard(LPDATAOBJECT pDataObj)
+{
+ if (pDataObj != NULL)
+ {
+ HRESULT hr;
+ IDataObject FAR *pdoNull = NULL;
+
+ /* If we are setting the clipboard's data object we first force
+ the clipboard to an empty state. This avoids a problem with
+ Word where it always uses the same data object pointer in
+ every clipboard call which results in the reference counts
+ being too high since we reuse the proxy and addref it on
+ the way in */
+ hr = (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleSetClipboard),
+ PASCAL_STACK_PTR(pdoNull));
+ if (FAILED(GetScode(hr)))
+ {
+ return hr;
+ }
+ }
+
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleSetClipboard),
+ PASCAL_STACK_PTR(pDataObj));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleGetClipboard, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [ppDataObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleGetClipboard(LPDATAOBJECT FAR* ppDataObj)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleGetClipboard),
+ PASCAL_STACK_PTR(ppDataObj));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleFlushClipboard, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleFlushClipboard(void)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleFlushClipboard),
+ NULL);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleIsCurrentClipboard, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pDataObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleIsCurrentClipboard(LPDATAOBJECT pDataObj)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleIsCurrentClipboard),
+ PASCAL_STACK_PTR(pDataObj));
+}
+
+
+/* InPlace Editing APIs */
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleSetMenuDescriptor, Unknown
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [holemenu] --
+// [hwndFrame] --
+// [hwndActiveObject] --
+// [lpFrame] --
+// [lpActiveObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleSetMenuDescriptor (HOLEMENU holemenu, HWND hwndFrame,
+ HWND hwndActiveObject,
+ LPOLEINPLACEFRAME lpFrame,
+ LPOLEINPLACEACTIVEOBJECT lpActiveObj)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleSetMenuDescriptor),
+ PASCAL_STACK_PTR(holemenu));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleDraw, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pUnknown] --
+// [dwAspect] --
+// [hdcDraw] --
+// [lprcBounds] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleDraw (LPUNKNOWN pUnknown, DWORD dwAspect, HDC hdcDraw,
+ LPCRECT lprcBounds)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleDraw),
+ PASCAL_STACK_PTR(pUnknown));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleRun, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pUnknown] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleRun(LPUNKNOWN pUnknown)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleRun),
+ PASCAL_STACK_PTR(pUnknown));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleIsRunning
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pObject] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(BOOL) OleIsRunning(LPOLEOBJECT pObject)
+{
+ return (BOOL)CallObjectInWOW(THK_API_METHOD(THK_API_OleIsRunning),
+ PASCAL_STACK_PTR(pObject));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleLockRunning, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pUnknown] --
+// [fLock] --
+// [fLastUnlockCloses] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleLockRunning(LPUNKNOWN pUnknown, BOOL fLock, BOOL fLastUnlockCloses)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleLockRunning),
+ PASCAL_STACK_PTR(pUnknown));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateOleAdviseHolder, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [ppOAHolder] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CreateOleAdviseHolder(LPOLEADVISEHOLDER FAR* ppOAHolder)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CreateOleAdviseHolder),
+ PASCAL_STACK_PTR(ppOAHolder));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleCreateDefaultHandler, Unknown
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [clsid] --
+// [pUnkOuter] --
+// [riid] --
+// [lplpObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleCreateDefaultHandler(REFCLSID clsid, LPUNKNOWN pUnkOuter,
+ REFIID riid, LPVOID FAR* lplpObj)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleCreateDefaultHandler),
+ PASCAL_STACK_PTR(clsid));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleCreateEmbeddingHelper, Unknown
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [clsid] --
+// [pUnkOuter] --
+// [flags] --
+// [pCF] --
+// [riid] --
+// [lplpObj] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleCreateEmbeddingHelper(REFCLSID clsid, LPUNKNOWN pUnkOuter,
+ DWORD flags, LPCLASSFACTORY pCF,
+ REFIID riid, LPVOID FAR* lplpObj)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleCreateEmbeddingHelper),
+ PASCAL_STACK_PTR(clsid));
+}
+
+/* Registration Database Helper APIs */
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleRegGetUserType, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [clsid] --
+// [dwFormOfType] --
+// [pszUserType] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleRegGetUserType (REFCLSID clsid, DWORD dwFormOfType,
+ LPSTR FAR* pszUserType)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleRegGetUserType),
+ PASCAL_STACK_PTR(clsid));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleRegGetMiscStatus, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [clsid] --
+// [dwAspect] --
+// [pdwStatus] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleRegGetMiscStatus(REFCLSID clsid, DWORD dwAspect,
+ DWORD FAR* pdwStatus)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleRegGetMiscStatus),
+ PASCAL_STACK_PTR(clsid));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleRegEnumFormatEtc, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [clsid] --
+// [dwDirection] --
+// [ppenum] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleRegEnumFormatEtc(REFCLSID clsid, DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenum)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleRegEnumFormatEtc),
+ PASCAL_STACK_PTR(clsid));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleRegEnumVerbs, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [clsid] --
+// [ppenum] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleRegEnumVerbs(REFCLSID clsid, LPENUMOLEVERB FAR* ppenum)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleRegEnumVerbs),
+ PASCAL_STACK_PTR(clsid));
+}
+
+/* OLE 1.0 conversion APIS */
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleConvertIStorageToOLESTREAM, Unknown
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pstg] --
+// [polestm] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleConvertIStorageToOLESTREAM(LPSTORAGE pstg,
+ LPOLESTREAM polestm)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleConvertIStorageToOLESTREAM),
+ PASCAL_STACK_PTR(pstg));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleConvertOLESTREAMToIStorage, Unknown
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [polestm] --
+// [pstg] --
+// [ptd] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleConvertOLESTREAMToIStorage(LPOLESTREAM polestm,
+ LPSTORAGE pstg,
+ const DVTARGETDEVICE FAR* ptd)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleConvertOLESTREAMToIStorage),
+ PASCAL_STACK_PTR(polestm));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleConvertIStorageToOLESTREAMEx, Unknown
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pstg] --
+// [cfFormat] --
+// [lWidth] --
+// [lHeight] --
+// [dwSize] --
+// [pmedium] --
+// [polestm] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleConvertIStorageToOLESTREAMEx(
+ LPSTORAGE pstg, // Presentation data to OLESTREAM
+ CLIPFORMAT cfFormat, // format
+ LONG lWidth, // width
+ LONG lHeight, // height
+ DWORD dwSize, // size in bytes
+ LPSTGMEDIUM pmedium, // bits
+ LPOLESTREAM polestm)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleConvertIStorageToOLESTREAMEx),
+ PASCAL_STACK_PTR(pstg));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleConvertOLESTREAMToIStorageEx, Unknown
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [polestm] --
+// [pstg] --
+// [pcfFormat] --
+// [plwWidth] --
+// [plHeight] --
+// [pdwSize] --
+// [pmedium] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleConvertOLESTREAMToIStorageEx(
+ LPOLESTREAM polestm,
+ LPSTORAGE pstg, // Presentation data from OLESTREAM
+ CLIPFORMAT FAR* pcfFormat, // format
+ LONG FAR* plwWidth, // width
+ LONG FAR* plHeight, // height
+ DWORD FAR* pdwSize, // size in bytes
+ LPSTGMEDIUM pmedium)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleConvertOLESTREAMToIStorageEx),
+ PASCAL_STACK_PTR(polestm));
+}
+
+/* ConvertTo APIS */
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleGetAutoConvert, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [clsidOld] --
+// [pClsidNew] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleGetAutoConvert(REFCLSID clsidOld, LPCLSID pClsidNew)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleGetAutoConvert),
+ PASCAL_STACK_PTR(clsidOld));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleSetAutoConvert, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [clsidOld] --
+// [clsidNew] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleSetAutoConvert),
+ PASCAL_STACK_PTR(clsidOld));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetConvertStg, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pStg] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI GetConvertStg(LPSTORAGE pStg)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_GetConvertStg),
+ PASCAL_STACK_PTR(pStg));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetConvertStg, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pStg] --
+// [fConvert] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI SetConvertStg(LPSTORAGE pStg, BOOL fConvert)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_SetConvertStg),
+ PASCAL_STACK_PTR(pStg));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateDataAdviseHolder, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [ppDAHolder] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CreateDataAdviseHolder(LPDATAADVISEHOLDER FAR* ppDAHolder)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CreateDataAdviseHolder),
+ PASCAL_STACK_PTR(ppDAHolder));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateDataCache, Unknown
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pUnkOuter] --
+// [rclsid] --
+// [iid] --
+// [ppv] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI CreateDataCache(LPUNKNOWN pUnkOuter, REFCLSID rclsid,
+ REFIID iid, LPVOID FAR* ppv)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CreateDataCache),
+ PASCAL_STACK_PTR(pUnkOuter));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Utility functions not in the spec; in ole2.dll.
+//
+// History: 20-Apr-94 DrewB Taken from OLE2 sources
+//
+//----------------------------------------------------------------------------
+
+STDAPI ReadOleStg
+ (LPSTORAGE pstg, DWORD FAR* pdwFlags, DWORD FAR* pdwOptUpdate,
+ DWORD FAR* pdwReserved, LPMONIKER FAR* ppmk, LPSTREAM FAR* ppstmOut)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_ReadOleStg),
+ PASCAL_STACK_PTR(pstg));
+}
+
+STDAPI WriteOleStg
+ (LPSTORAGE pstg, IOleObject FAR* pOleObj,
+ DWORD dwReserved, LPSTREAM FAR* ppstmOut)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_WriteOleStg),
+ PASCAL_STACK_PTR(pstg));
+}
diff --git a/private/ole32/olethunk/ole16/ole2/ole2guid.cxx b/private/ole32/olethunk/ole16/ole2/ole2guid.cxx
new file mode 100644
index 000000000..0e92719ba
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/ole2guid.cxx
@@ -0,0 +1,22 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: OLE2GUID.cxx (16 bit target)
+//
+// Contents: GUIDs for OLE2
+//
+// Functions:
+//
+// History: 17-Dec-93 JohannP Created
+//
+//--------------------------------------------------------------------------
+
+#pragma hdrstop
+#define INITGUID
+#include <string.h>
+#include "compobj.h"
+#include "initguid.h"
+#include "oleguid.h"
+#include "privguid.h"
diff --git a/private/ole32/olethunk/ole16/ole2/ole2lcl.cxx b/private/ole32/olethunk/ole16/ole2/ole2lcl.cxx
new file mode 100644
index 000000000..75fc12b67
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/ole2lcl.cxx
@@ -0,0 +1,727 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ole2lcl.cxx (16 bit target)
+//
+// Contents: OLE2 APIs implemented locally
+//
+// Functions:
+//
+// History: 17-Dec-93 Johann Posch (johannp) Created
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <limits.h>
+
+#include <ole2sp.h>
+#include <ole2ver.h>
+#include <valid.h>
+#include <ole2int.h>
+
+#include <call32.hxx>
+#include <apilist.hxx>
+
+DWORD gdwOleVersion = MAKELONG(OLE_STREAM_VERSION, OLE_PRODUCT_VERSION);
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleGetMalloc, Local
+//
+//----------------------------------------------------------------------------
+STDAPI OleGetMalloc(DWORD dwContext, IMalloc FAR* FAR* ppMalloc)
+{
+ return CoGetMalloc(dwContext, ppMalloc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleBuildVersion, Local
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(DWORD) OleBuildVersion( VOID )
+{
+ return CoBuildVersion();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleDuplicateData, Local
+//
+// Synopsis: Duplicates the given data
+//
+// History: 11-Apr-94 DrewB Copied from various places in OLE2
+//
+//----------------------------------------------------------------------------
+
+FARINTERNAL_(HBITMAP) BmDuplicate
+ (HBITMAP hold, DWORD FAR* lpdwSize, LPBITMAP lpBm)
+{
+ HBITMAP hnew = NULL;
+ HANDLE hMem;
+ LPSTR lpMem;
+ DWORD dwSize;
+ BITMAP bm;
+ SIZE extents;
+
+ extents.cx = extents.cy = 0;
+
+ GetObject (hold, sizeof(BITMAP), (LPSTR) &bm);
+ dwSize = ((DWORD) bm.bmHeight) * ((DWORD) bm.bmWidthBytes) *
+ ((DWORD) bm.bmPlanes);
+
+ if (!(hMem = GlobalAlloc (GMEM_MOVEABLE, dwSize)))
+ return NULL;
+
+ if (!(lpMem = (LPSTR) GlobalLock (hMem)))
+ goto errRtn;
+ GlobalUnlock (hMem);
+
+ GetBitmapBits (hold, dwSize, lpMem);
+ if (hnew = CreateBitmap (bm.bmWidth, bm.bmHeight,
+ bm.bmPlanes, bm.bmBitsPixel, NULL)) {
+ if (!SetBitmapBits (hnew, dwSize, lpMem)) {
+ DeleteObject (hnew);
+ hnew = NULL;
+ goto errRtn;
+ }
+ }
+
+ if (lpdwSize)
+ *lpdwSize = dwSize;
+
+ if (lpBm)
+ *lpBm = bm;
+
+ if (GetBitmapDimensionEx(hold, &extents) && extents.cx && extents.cy)
+ SetBitmapDimensionEx(hnew, extents.cx, extents.cy, NULL);
+
+errRtn:
+ if (hMem)
+ GlobalFree (hMem);
+
+ return hnew;
+}
+
+FARINTERNAL_(HPALETTE) UtDupPalette
+ (HPALETTE hpalette)
+{
+ WORD cEntries = 0;
+ HANDLE hLogPal = NULL;
+ LPLOGPALETTE pLogPal = NULL;
+ HPALETTE hpaletteNew = NULL;
+
+ if (0==GetObject (hpalette, sizeof(cEntries), &cEntries))
+ return NULL;
+
+ if (NULL==(hLogPal = GlobalAlloc (GMEM_MOVEABLE, sizeof (LOGPALETTE) +
+ cEntries * sizeof (PALETTEENTRY))))
+ return NULL;
+
+ if (NULL==(pLogPal = (LPLOGPALETTE) GlobalLock (hLogPal)))
+ goto errRtn;
+
+ if (0==GetPaletteEntries (hpalette, 0, cEntries, pLogPal->palPalEntry))
+ goto errRtn;
+
+ pLogPal->palVersion = 0x300;
+ pLogPal->palNumEntries = cEntries;
+
+ if (NULL==(hpaletteNew = CreatePalette (pLogPal)))
+ goto errRtn;
+
+errRtn:
+ if (pLogPal)
+ GlobalUnlock (hLogPal);
+ if (hLogPal)
+ GlobalFree (hLogPal);
+ AssertSz (hpaletteNew, "Warning: UtDupPalette Failed");
+ return hpaletteNew;
+}
+
+FARINTERNAL_(HANDLE) UtDupGlobal (HANDLE hsrc, UINT uiFlags)
+{
+ HANDLE hdst;
+ DWORD dwSize;
+#ifndef _MAC
+ LPSTR lpdst = NULL;
+ LPSTR lpsrc = NULL;
+#endif
+
+ if (!hsrc)
+ return NULL;
+
+#ifdef _MAC
+ if (!(hdst = NewHandle(dwSize = GetHandleSize(hsrc))))
+ return NULL;
+ BlockMove(*hsrc, *hdst, dwSize);
+ return hdst;
+#else
+ if (!(lpsrc = GlobalLock (hsrc)))
+ return NULL;
+
+ hdst = GlobalAlloc (uiFlags, (dwSize = GlobalSize(hsrc)));
+ if (hdst == NULL || (lpdst = GlobalLock (hdst)) == NULL)
+ goto errRtn;
+
+ UtMemCpy (lpdst, lpsrc, dwSize);
+ GlobalUnlock (hsrc);
+ GlobalUnlock (hdst);
+ return hdst;
+
+errRtn:
+ if (hdst)
+ GlobalFree (hdst);
+
+ return NULL;
+#endif
+}
+
+OLEAPI_(HANDLE) OleDuplicateData
+ (HANDLE hSrc, CLIPFORMAT cfFormat, UINT uiFlags)
+{
+#ifndef _MAC
+ if (!hSrc)
+ return NULL;
+
+ if (cfFormat == CF_BITMAP)
+ return (HANDLE) BmDuplicate ((HBITMAP)hSrc, NULL, NULL);
+
+ if (cfFormat == CF_PALETTE)
+ return (HANDLE) UtDupPalette ((HPALETTE)hSrc);
+
+ if (uiFlags == NULL)
+ uiFlags = GMEM_MOVEABLE;
+
+ if (cfFormat == CF_METAFILEPICT) {
+ HANDLE hDst;
+
+ LPMETAFILEPICT lpmfpSrc;
+ LPMETAFILEPICT lpmfpDst;
+
+ if (!(lpmfpSrc = (LPMETAFILEPICT) GlobalLock (hSrc)))
+ return NULL;
+
+ if (!(hDst = UtDupGlobal (hSrc, uiFlags)))
+ return NULL;
+
+ if (!(lpmfpDst = (LPMETAFILEPICT) GlobalLock (hDst))) {
+ GlobalFree (hDst);
+ return NULL;
+ }
+
+ *lpmfpDst = *lpmfpSrc;
+ lpmfpDst->hMF = CopyMetaFile (lpmfpSrc->hMF, NULL);
+ GlobalUnlock (hSrc);
+ GlobalUnlock (hDst);
+ return hDst;
+
+ } else {
+ return UtDupGlobal (hSrc, uiFlags);
+ }
+#else
+ AssertSz(0,"OleDuplicateData NYI");
+ return NULL;
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetBitOleStg, private
+//
+// Synopsis: Sets bit in ole stream; doc bit preserved even when stream
+// rewritten above; the value written is (old & mask) | value.
+//
+// Arguments: [pstg] - Storage
+// [mask] - Mask
+// [value] - Value
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 DrewB Created
+//
+// Notes: Taken straight from OLE2 source
+//
+//----------------------------------------------------------------------------
+
+static INTERNAL SetBitOleStg(LPSTORAGE pstg, DWORD mask, DWORD value)
+{
+ IStream FAR * pstm = NULL;
+ HRESULT error;
+ DWORD objflags = 0;
+ LARGE_INTEGER large_integer;
+ ULONG cbRead;
+
+ VDATEIFACE( pstg );
+
+ if (error = pstg->OpenStream(OLE_STREAM, NULL, STGM_SALL, 0, &pstm))
+ {
+ if (STG_E_FILENOTFOUND != GetScode(error))
+ {
+ goto errRtn;
+ }
+
+ if (error = pstg->CreateStream(OLE_STREAM, STGM_SALL, 0, 0, &pstm))
+ {
+ goto errRtn;
+ }
+
+ DWORD dwBuf[5];
+
+ dwBuf[0] = gdwOleVersion;
+ dwBuf[1] = objflags;
+ dwBuf[2] = 0L;
+ dwBuf[3] = 0L;
+ dwBuf[4] = 0L;
+
+ if ((error = pstm->Write(dwBuf, 5*sizeof(DWORD), NULL)) != NOERROR)
+ {
+ goto errRtn;
+ }
+ }
+
+ // seek directly to word, read, modify, seek back and write.
+ LISet32( large_integer, sizeof(DWORD) );
+ if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ if ((error = pstm->Read(&objflags, sizeof(objflags), &cbRead)) != NOERROR)
+ {
+ goto errRtn;
+ }
+ if (cbRead != sizeof(objflags))
+ {
+ goto errRtn;
+ }
+
+ objflags = (objflags & mask) | value;
+
+ LISet32( large_integer, sizeof(DWORD) );
+ if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ error = pstm->Write(&objflags, sizeof(DWORD), NULL);
+
+ errRtn:
+ // close and return error code.
+ if (pstm)
+ {
+ pstm->Release();
+ }
+
+ return error;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetFlagsOleStg, private
+//
+// Synopsis: Return long word of flags from the ole stream
+//
+// Arguments: [pstg] - Storage
+// [lpobjflags] - Flags return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [lpobjflags]
+//
+// History: 11-Mar-94 DrewB Created
+//
+// Notes: Taken straight from OLE2 source
+//
+//----------------------------------------------------------------------------
+
+static INTERNAL GetFlagsOleStg(LPSTORAGE pstg, LPDWORD lpobjflags)
+{
+ IStream FAR * pstm = NULL;
+ HRESULT error;
+ LARGE_INTEGER large_integer;
+ ULONG cbRead;
+
+ VDATEIFACE( pstg );
+
+ if ((error = pstg->OpenStream(OLE_STREAM, NULL,
+ (STGM_READ | STGM_SHARE_EXCLUSIVE),
+ 0, &pstm)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ // seek directly to word, read, modify, seek back and write.
+ LISet32( large_integer, sizeof(DWORD) );
+ if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ error = pstm->Read(lpobjflags, sizeof(*lpobjflags), &cbRead);
+ if (SUCCEEDED(GetScode(error)) && cbRead != sizeof(*lpobjflags))
+ {
+ error = ResultFromScode(STG_E_READFAULT);
+ }
+
+ errRtn:
+ // close and return error NOERROR (document)/S_FALSE (embedding);
+ if (pstm)
+ {
+ pstm->Release();
+ }
+
+ return error == NOERROR ? NOERROR : ReportResult(0, S_FALSE, 0, 0);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetDocumentBitStg, semi-private
+//
+// Synopsis: Get doc bit; return NOERROR if on; S_FALSE if off
+//
+// Arguments: [pStg] - Storage
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 DrewB Created
+//
+// Notes: Taken straight from OLE2 source
+//
+//----------------------------------------------------------------------------
+
+STDAPI GetDocumentBitStg(LPSTORAGE pStg)
+{
+ DWORD objflags;
+ HRESULT error;
+
+ if ((error = GetFlagsOleStg(pStg, &objflags)) != NOERROR)
+ {
+ return error;
+ }
+
+ return (objflags&OBJFLAGS_DOCUMENT) ? NOERROR : ResultFromScode(S_FALSE);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetDocumentBitStg, semi-private
+//
+// Synopsis: Set doc bit according to fDocument
+//
+// Arguments: [pStg] - Storage
+// [fDocument] - Document flag
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 DrewB Created
+//
+// Notes: Taken straight from OLE2 source
+//
+//----------------------------------------------------------------------------
+
+STDAPI SetDocumentBitStg(LPSTORAGE pStg, BOOL fDocument)
+{
+ return SetBitOleStg(pStg, fDocument ? -1L : ~OBJFLAGS_DOCUMENT,
+ fDocument ? OBJFLAGS_DOCUMENT : 0);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReleaseStgMedium, public
+//
+// History: 18-Mar-94 Taken straight from OLE2 source
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(void) ReleaseStgMedium(LPSTGMEDIUM pMedium)
+{
+ if (pMedium)
+ {
+ //VDATEPTRIN rejects NULL
+ VOID_VDATEPTRIN( pMedium, STGMEDIUM );
+ BOOL fPunkRel = pMedium->pUnkForRelease != NULL;
+
+ switch (pMedium->tymed)
+ {
+ case TYMED_HGLOBAL:
+ if (pMedium->hGlobal != NULL && !fPunkRel)
+ Verify(GlobalFree(pMedium->hGlobal) == 0);
+ break;
+
+ case TYMED_GDI:
+ if (pMedium->hGlobal != NULL && !fPunkRel)
+ DeleteObject(pMedium->hGlobal);
+ break;
+
+ case TYMED_MFPICT:
+ if (pMedium->hGlobal != NULL && !fPunkRel)
+ {
+ LPMETAFILEPICT pmfp;
+
+ if ((pmfp = (LPMETAFILEPICT)GlobalLock(pMedium->hGlobal)) ==
+ NULL)
+ break;
+
+ DeleteMetaFile(pmfp->hMF);
+ GlobalUnlock(pMedium->hGlobal);
+ Verify(GlobalFree(pMedium->hGlobal) == 0);
+ }
+ break;
+
+ case TYMED_FILE:
+ if (pMedium->lpszFileName != NULL)
+ {
+ if (!IsValidPtrIn(pMedium->lpszFileName, 1))
+ break;
+ if (!fPunkRel)
+ {
+#ifdef WIN32
+ DeleteFile(pMedium->lpszFileName);
+#else
+#ifdef _MAC
+ /* the libraries are essentially small model on the MAC */
+ Verify(0==remove(pMedium->lpszFileName));
+#else
+#ifdef OLD_AND_NICE_ASSEMBLER_VERSION
+ /* Win 3.1 specific code to call DOS to delete the file
+ given a far pointer to the file name */
+ extern void WINAPI DOS3Call(void);
+ _asm
+ {
+ mov ah,41H
+ push ds
+ lds bx,pMedium
+ lds dx,[bx].lpszFileName
+ call DOS3Call
+ pop ds
+ }
+#else
+ {
+ OFSTRUCT of;
+ OpenFile(pMedium->lpszFileName, &of, OF_DELETE);
+ }
+#endif
+#endif
+#endif
+ delete pMedium->lpszFileName;
+ }
+ }
+ break;
+
+ case TYMED_ISTREAM:
+ if (pMedium->pstm != NULL &&
+ IsValidInterface(pMedium->pstm))
+ pMedium->pstm->Release();
+ break;
+
+ case TYMED_ISTORAGE:
+ if (pMedium->pstg != NULL &&
+ IsValidInterface(pMedium->pstg))
+ pMedium->pstg->Release();
+ break;
+
+ case TYMED_NULL:
+ break;
+
+ default:
+ thkAssert(!"Invalid medium in ReleaseStgMedium");
+ }
+
+ // NULL out to prevent unwanted use of just freed data
+ pMedium->tymed = TYMED_NULL;
+
+ if (pMedium->pUnkForRelease)
+ {
+ if (IsValidInterface(pMedium->pUnkForRelease))
+ pMedium->pUnkForRelease->Release();
+ pMedium->pUnkForRelease = NULL;
+ }
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleDoAutoConvert, local
+//
+// Synopsis: Taken from ole32 code
+//
+// History: 06-Oct-94 DrewB Created
+//
+// Notes: This routine must be local because it can return
+// information through pClsidNew even when it is
+// returning an error
+//
+//----------------------------------------------------------------------------
+
+STDAPI OleDoAutoConvert(LPSTORAGE pStg, LPCLSID pClsidNew)
+{
+ HRESULT error;
+ CLSID clsidOld;
+ CLIPFORMAT cfOld;
+ LPSTR lpszOld = NULL;
+ LPSTR lpszNew = NULL;
+ LPMALLOC pma;
+
+ if ((error = ReadClassStg(pStg, &clsidOld)) != NOERROR)
+ {
+ clsidOld = CLSID_NULL;
+ goto errRtn;
+ }
+
+ if ((error = OleGetAutoConvert(clsidOld, pClsidNew)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ // read old fmt/old user type; sets out params to NULL on error
+ error = ReadFmtUserTypeStg(pStg, &cfOld, &lpszOld);
+ Assert(error == NOERROR || (cfOld == NULL && lpszOld == NULL));
+
+ // get new user type name; if error, set to NULL string
+ if ((error = OleRegGetUserType(*pClsidNew, USERCLASSTYPE_FULL,
+ &lpszNew)) != NOERROR)
+ {
+ lpszNew = NULL;
+ }
+
+ // write class stg
+ if ((error = WriteClassStg(pStg, *pClsidNew)) != NOERROR)
+ {
+ goto errRtn;
+ }
+
+ // write old fmt/new user type;
+ if ((error = WriteFmtUserTypeStg(pStg, cfOld, lpszNew)) != NOERROR)
+ {
+ goto errRewriteInfo;
+ }
+
+ // set convert bit
+ if ((error = SetConvertStg(pStg, TRUE)) != NOERROR)
+ {
+ goto errRewriteInfo;
+ }
+
+ goto okRtn;
+
+ errRewriteInfo:
+ (void)WriteClassStg(pStg, clsidOld);
+ (void)WriteFmtUserTypeStg(pStg, cfOld, lpszOld);
+
+ errRtn:
+ *pClsidNew = clsidOld;
+
+ okRtn:
+ if (CoGetMalloc(MEMCTX_TASK, &pma) == NOERROR)
+ {
+ pma->Free(lpszOld);
+ pma->Free(lpszNew);
+ pma->Release();
+ }
+
+ return error;
+}
+
+/****** Other API defintions **********************************************/
+
+//+---------------------------------------------------------------------------
+//
+// Function: Utility functions not in the spec; in ole2.dll.
+//
+// History: 20-Apr-94 DrewB Taken from OLE2 sources
+//
+//----------------------------------------------------------------------------
+
+#define AVERAGE_STR_SIZE 64
+
+FARINTERNAL_(HRESULT) StRead (IStream FAR * lpstream, LPVOID lpBuf, ULONG ulLen)
+{
+ HRESULT error;
+ ULONG cbRead;
+
+ if ((error = lpstream->Read( lpBuf, ulLen, &cbRead)) != NOERROR)
+ return error;
+
+ return ((cbRead != ulLen) ? ResultFromScode(STG_E_READFAULT) : NOERROR);
+}
+
+// returns S_OK when string read and allocated (even if zero length)
+OLEAPI ReadStringStream( LPSTREAM pstm, LPSTR FAR * ppsz )
+{
+ ULONG cb;
+ HRESULT hresult;
+
+ *ppsz = NULL;
+
+ if ((hresult = StRead(pstm, (void FAR *)&cb, sizeof(ULONG))) != NOERROR)
+ return hresult;
+
+ if (cb == NULL)
+ // NULL string case
+ return NOERROR;
+
+ if ((LONG)cb < 0 || cb > INT_MAX)
+ // out of range
+ return ReportResult(0, E_UNSPEC, 0, 0);
+
+ if (!(*ppsz = new FAR char[(int)cb]))
+ return ReportResult(0, E_OUTOFMEMORY, 0, 0);
+
+ if ((hresult = StRead(pstm, (void FAR *)(*ppsz), cb)) != NOERROR)
+ goto errRtn;
+
+ return NOERROR;
+
+errRtn:
+ delete *ppsz;
+ *ppsz = NULL;
+ return hresult;
+}
+
+OLEAPI WriteStringStream(LPSTREAM pstm, LPCSTR psz)
+{
+ HRESULT error;
+ ULONG cb = NULL;
+
+ if (psz) {
+ cb = 1 + _fstrlen(psz);
+
+ // if possible, do a single write instead of two
+
+ if (cb <= AVERAGE_STR_SIZE-4) {
+ char szBuf[AVERAGE_STR_SIZE];
+
+ *((ULONG FAR*) szBuf) = cb;
+ lstrcpy(szBuf+sizeof(ULONG), psz);
+
+ return pstm->Write((VOID FAR *)szBuf, cb+sizeof(ULONG), NULL);
+ }
+ }
+
+ if (error = pstm->Write((VOID FAR *)&cb, sizeof(ULONG), NULL))
+ return error;
+
+ if (psz == NULL)
+ // we are done writing the string
+ return NOERROR;
+
+ return pstm->Write((VOID FAR *)psz, cb, NULL);
+}
+
+OLEAPI OpenOrCreateStream( IStorage FAR * pstg, char const FAR * pwcsName,
+ IStream FAR* FAR* ppstm)
+{
+ HRESULT error;
+ error = pstg->CreateStream(pwcsName,
+ STGM_SALL | STGM_FAILIFTHERE, 0, 0, ppstm);
+ if (GetScode(error) == STG_E_FILEALREADYEXISTS)
+ error = pstg->OpenStream(pwcsName, NULL, STGM_SALL, 0, ppstm);
+
+ return error;
+}
diff --git a/private/ole32/olethunk/ole16/ole2/ole2splt.cxx b/private/ole32/olethunk/ole16/ole2/ole2splt.cxx
new file mode 100644
index 000000000..d9f8a2d19
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/ole2splt.cxx
@@ -0,0 +1,271 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ole2splt.cxx
+//
+// Contents: OLE2 API whose implementation is split between 16/32
+//
+// History: 07-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <ole2sp.h>
+#include <ole2int.h>
+#include <ole2ver.h>
+#include <olecoll.h>
+#include <map_kv.h>
+#include <map_htsk.h>
+#include <etask.hxx>
+
+#include <call32.hxx>
+#include <apilist.hxx>
+
+// MFC HACK ALERT!!! The followind constant is needed
+// for an MFC workaround. See OleInitialize for details
+
+#define CLIPBOARDWNDCLASS "CLIPBOARDWNDCLASS"
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleInitialize, Split
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pMalloc] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+// 05-26-94 AlexT Return correct success code
+// 08-22-94 AlexGo added MFC CreateWindow hack
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDAPI OleInitialize(LPMALLOC pMalloc)
+{
+ HTASK htask;
+ Etask etask;
+ HRESULT hrCoInit, hrOleInit;
+ static BOOL fCreatedClipWindowClass = FALSE;
+
+ /* This version of ole2.dll simply needs to work with the same major build
+ of compobj.dll. Future versions of ole2.dll might be restricted to
+ certain builds of compobj.dll. */
+ if (HIWORD(CoBuildVersion()) != rmm)
+ {
+ return ResultFromScode(OLE_E_WRONGCOMPOBJ);
+ }
+
+ /* if already initialize one or more times, just bump count and return. */
+ if (LookupEtask(htask, etask) && etask.m_oleinits != 0)
+ {
+ etask.m_oleinits++;
+ thkVerify(SetEtask(htask, etask));
+ return ResultFromScode(S_FALSE);
+ }
+
+ /* Initialize the 16-bit side of compobj */
+ hrCoInit = CoInitialize(pMalloc);
+ if (SUCCEEDED(GetScode(hrCoInit)))
+ {
+ /* Thunk OleInitialize
+ Never pass on the IMalloc */
+ pMalloc = NULL;
+ hrOleInit = (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_OleInitialize),
+ PASCAL_STACK_PTR(pMalloc) );
+ if (FAILED(GetScode(hrOleInit)))
+ {
+ CoUninitialize();
+ return(hrOleInit);
+ }
+
+ thkVerify(LookupEtask(htask, etask) && etask.m_oleinits == 0);
+ etask.m_oleinits++;
+ thkVerify(SetEtask(htask, etask));
+ }
+
+ // Since we call 32-bit CoInitialize and then call 32-bit OleInitialize,
+ // and since the latter internally calls CoInitialize (a second time), we
+ // want to return the HRESULT of the call to CoInitialize since some
+ // applications look for S_OK (and our call to OleInitialize will return
+ // S_FALSE since it will be the second call to CoInitialize).
+
+
+ // MFC HACK ALERT!! MFC2.5 (16bit) has a hack where they scan the
+ // window hierarchy for a window named "CLIPBOARDWNDCLASS". They then
+ // subclass this window and do their own processing for clipboard
+ // windows messages.
+ //
+ // In order to make them work, we create a dummy window for MFC to party
+ // on. This allows them to successfully subclass and not interfere
+ // with 32bit OLE processing. (since it's a dummy window)
+ //
+ // NB!! We do not bother with resource cleanup; we'll leave this window
+ // around until the process exits. We also don't care about errors
+ // here. In the off chance that one of the calls fails and we *don't*
+ // create a window that MFC can party on, then MFC *debug* apps will
+ // popup an assert dialog. You can safely click 'OK' on this dialog
+ // and the app will proceed without undue trauma.
+
+ if( !fCreatedClipWindowClass )
+ {
+ WNDCLASS wc;
+
+ // Register Clipboard window class
+ //
+ wc.style = 0;
+ wc.lpfnWndProc = DefWindowProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 4;
+ wc.hInstance = hmodOLE2;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = CLIPBOARDWNDCLASS;
+
+ // don't bother checking for errors
+ RegisterClass(&wc);
+ fCreatedClipWindowClass = TRUE;
+ }
+
+ CreateWindow(CLIPBOARDWNDCLASS,"",WS_POPUP,CW_USEDEFAULT,
+ CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
+ NULL,NULL,hmodOLE2,NULL);
+
+ return hrOleInit;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleUninitialize, Split
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(void) OleUninitialize(void)
+{
+ HTASK htask;
+ Etask etask;
+
+ /* If not init, just return */
+ if (!LookupEtask(htask, etask) || etask.m_oleinits == 0)
+ {
+ return;
+ }
+
+ /* Must always decrement count and set since compobj may still be init'd */
+ etask.m_oleinits--;
+ thkVerify(SetEtask(htask, etask));
+
+ /* if not last uninit, now return */
+ if (etask.m_oleinits != 0)
+ {
+ return;
+ }
+
+ /* After this point, the uninit should not fail (because we don't have
+ code to redo the init). */
+
+ CallObjectInWOW(THK_API_METHOD(THK_API_OleUninitialize), NULL );
+ CoUninitialize();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReadClassStm, Split
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pStm] --
+// [pclsid] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI ReadClassStm(LPSTREAM pStm, CLSID FAR* pclsid)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_ReadClassStm),
+ PASCAL_STACK_PTR(pStm) );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WriteClassStm, Split
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pStm] --
+// [rclsid] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI WriteClassStm(LPSTREAM pStm, REFCLSID rclsid)
+{
+ return (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_WriteClassStm) ,
+ PASCAL_STACK_PTR(pStm) );
+}
diff --git a/private/ole32/olethunk/ole16/ole2/scrlcopy.cur b/private/ole32/olethunk/ole16/ole2/scrlcopy.cur
new file mode 100644
index 000000000..b1e5cc214
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/scrlcopy.cur
Binary files differ
diff --git a/private/ole32/olethunk/ole16/ole2/scrllink.cur b/private/ole32/olethunk/ole16/ole2/scrllink.cur
new file mode 100644
index 000000000..5126c9905
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/scrllink.cur
Binary files differ
diff --git a/private/ole32/olethunk/ole16/ole2/scrlmove.cur b/private/ole32/olethunk/ole16/ole2/scrlmove.cur
new file mode 100644
index 000000000..4fb5331f0
--- /dev/null
+++ b/private/ole32/olethunk/ole16/ole2/scrlmove.cur
Binary files differ
diff --git a/private/ole32/olethunk/ole16/storage/headers.cxx b/private/ole32/olethunk/ole16/storage/headers.cxx
new file mode 100644
index 000000000..f4a35afba
--- /dev/null
+++ b/private/ole32/olethunk/ole16/storage/headers.cxx
@@ -0,0 +1,21 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: headers.cxx
+//
+// Contents: Precompiled header file
+//
+// History: 18-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <windows.h>
+#include <string.h>
+#include <compobj.h>
+#include <storage.h>
+
+#include <interop.hxx>
+#include <wow16fn.h>
+#include <io16.h>
diff --git a/private/ole32/olethunk/ole16/storage/makefile b/private/ole32/olethunk/ole16/storage/makefile
new file mode 100644
index 000000000..622f7f913
--- /dev/null
+++ b/private/ole32/olethunk/ole16/storage/makefile
@@ -0,0 +1,44 @@
+# storage Thunk DLL makefile
+#
+# Copyright (c) 1991, Microsoft Corporation
+#
+# History:
+#
+# 18-Feb-1994 BobDay Adapted from MVDM\WOW16\GDI\MAKEFILE
+#
+
+!IFDEF USEBUILD
+
+# If using BUILD.EXE, edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2.
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!ELSE
+
+default: copy_bin
+
+TARGET = storage.dll
+CFILES = \
+ .\storage.c\
+ .\stgdthk.c
+RCFILES = .\storage.rc
+LIBS = $(LIBS) ..\lib\compobj.lib
+
+!if "$(NTDEBUG)" != "" && "$(NTDEBUG)" != "retail"
+LIBS = $(LIBS) $(OLETHUNK)\debnot\$(OBJDIR)\debnot.lib
+!endif
+
+!include ..\makefile.inc
+
+copy_bin: all
+ -binplace $(OBJDIR)\storage.dll
+ -binplace $(OBJDIR)\storage.sym
+ -binplace $(OBJDIR)\storage.map
+
+storage.obj: storage.c
+
+stgdthk.obj: stgdthk.c
+
+!ENDIF
diff --git a/private/ole32/olethunk/ole16/storage/stgdthk.c b/private/ole32/olethunk/ole16/storage/stgdthk.c
new file mode 100644
index 000000000..a706ead1b
--- /dev/null
+++ b/private/ole32/olethunk/ole16/storage/stgdthk.c
@@ -0,0 +1,307 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: stgdthk.cxx (16 bit target)
+//
+// Contents: Storage APIs that are directly thunked
+//
+// History: 17-Dec-93 JohannP Created
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <call32.hxx>
+#include <apilist.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Function: Straight thunk routines
+//
+// Synopsis: The following routines thunk straight through
+//
+// History: 24-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void FAR* FAR* ppv)
+{
+ /* Relies on the fact that storage and ole2.dll both use the
+ same DllGetClassObject in ole32.dll */
+ return (HRESULT)CallObjectInWOWCheckThkMgr(THK_API_METHOD(THK_API_DllGetClassObject),
+ PASCAL_STACK_PTR(clsid));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgCreateDocfile, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pwcsName] --
+// [grfMode] --
+// [reserved] --
+// [ppstgOpen] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 DrewB Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI StgCreateDocfile(const char FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen)
+{
+ return (HRESULT)CallObjectInWOWCheckThkMgr(THK_API_METHOD(THK_API_StgCreateDocfile),
+ PASCAL_STACK_PTR(pwcsName));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgCreateDocfileOnILockBytes, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [plkbyt] --
+// [grfMode] --
+// [reserved] --
+// [ppstgOpen] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 DrewB Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI StgCreateDocfileOnILockBytes(ILockBytes FAR *plkbyt,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen)
+{
+ return (HRESULT)CallObjectInWOWCheckThkMgr(THK_API_METHOD(THK_API_StgCreateDocfileOnILockBytes),
+ PASCAL_STACK_PTR(plkbyt));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgOpenStorage, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pwcsName] --
+// [pstgPriority] --
+// [grfMode] --
+// [snbExclude] --
+// [reserved] --
+// [ppstgOpen] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 DrewB Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI StgOpenStorage(const char FAR* pwcsName,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen)
+{
+ // STGM_CREATE and STGM_CONVERT are illegal for open calls
+ // 16-bit code did not enforce this, so mask out these flags
+ // before passing grfMode on
+ grfMode &= ~(STGM_CREATE | STGM_CONVERT);
+
+ return (HRESULT)CallObjectInWOWCheckThkMgr(THK_API_METHOD(THK_API_StgOpenStorage),
+ PASCAL_STACK_PTR(pwcsName));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgOpenStorageOnILockBytes, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [plkbyt] --
+// [pstgPriority] --
+// [grfMode] --
+// [snbExclude] --
+// [reserved] --
+// [ppstgOpen] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 DrewB Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI StgOpenStorageOnILockBytes(ILockBytes FAR *plkbyt,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen)
+{
+ // STGM_CREATE and STGM_CONVERT are illegal for open calls
+ // 16-bit code did not enforce this, so mask out these flags
+ // before passing grfMode on
+ grfMode &= ~(STGM_CREATE | STGM_CONVERT);
+
+ return
+ (HRESULT)CallObjectInWOWCheckThkMgr(THK_API_METHOD(THK_API_StgOpenStorageOnILockBytes),
+ PASCAL_STACK_PTR(plkbyt));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgIsStorageFile, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [pwcsName] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 DrewB Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI StgIsStorageFile(const char FAR* pwcsName)
+{
+ //
+ // MSPUB 2.0a hack - We call the "CheckInit" version because they forgot
+ // to call CoInitialize/OleInitialize first.
+ //
+ return
+ (HRESULT)CallObjectInWOWCheckThkMgr(THK_API_METHOD(THK_API_StgIsStorageFile),
+ PASCAL_STACK_PTR(pwcsName));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgIsStorageILockBytes, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [plkbyt] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 DrewB Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI StgIsStorageILockBytes(ILockBytes FAR* plkbyt)
+{
+ return (HRESULT)CallObjectInWOWCheckThkMgr(THK_API_METHOD(THK_API_StgIsStorageILockBytes),
+ PASCAL_STACK_PTR(plkbyt));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgSetTimes, Remoted
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments: [lpszName] --
+// [pctime] --
+// [patime] --
+// [pmtime] --
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 2-28-94 DrewB Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI StgSetTimes(char const FAR* lpszName,
+ FILETIME const FAR* pctime,
+ FILETIME const FAR* patime,
+ FILETIME const FAR* pmtime)
+{
+ return (HRESULT)CallObjectInWOWCheckThkMgr(THK_API_METHOD(THK_API_StgSetTimes),
+ PASCAL_STACK_PTR(lpszName));
+}
diff --git a/private/ole32/olethunk/ole16/storage/storage.c b/private/ole32/olethunk/ole16/storage/storage.c
new file mode 100644
index 000000000..b449d2e71
--- /dev/null
+++ b/private/ole32/olethunk/ole16/storage/storage.c
@@ -0,0 +1,87 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: storage.c (16 bit target)
+//
+// Contents: Storage.dll common code
+//
+// History: 17-Dec-93 JohannP Created
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <call32.hxx>
+#include <apilist.hxx>
+
+DECLARE_INFOLEVEL(thk1);
+
+//+---------------------------------------------------------------------------
+//
+// Function: LibMain, public
+//
+// Synopsis: DLL initialization function
+//
+// Arguments: [hinst] - Instance handle
+// [wDataSeg] - Current DS
+// [cbHeapSize] - Heap size for the DLL
+// [lpszCmdLine] - Command line information
+//
+// Returns: One for success, zero for failure
+//
+// History: 21-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+static char achInfoLevel[32];
+#endif
+
+int CALLBACK LibMain(HINSTANCE hinst,
+ WORD wDataSeg,
+ WORD cbHeapSize,
+ LPSTR lpszCmdLine)
+{
+#if DBG == 1
+ if (GetProfileString("olethk32", "InfoLevel", "3", achInfoLevel,
+ sizeof(achInfoLevel)) > 0)
+ {
+ thk1InfoLevel = strtoul(achInfoLevel, NULL, 0);
+ }
+#endif
+
+#if defined(_CHICAGO_)
+ //
+ // BUGBUGCHICAGO
+ //
+ // The Chicago debugger doesn't like hinst not being wired.
+ //
+ GlobalWire(hinst);
+#endif
+
+ return 1;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WEP, public
+//
+// Synopsis: Windows Exit Point routine, for receiving DLL unload
+// notification
+//
+// Arguments: [nExitType] - Type of exit occurring
+//
+// Returns: One for success, zero for failure
+//
+// History: 21-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+int CALLBACK WEP(int nExitType)
+{
+ // BUGBUG - Clean up thunk objects?
+ return 1;
+}
diff --git a/private/ole32/olethunk/ole16/storage/storage.def b/private/ole32/olethunk/ole16/storage/storage.def
new file mode 100644
index 000000000..0d3fd4cab
--- /dev/null
+++ b/private/ole32/olethunk/ole16/storage/storage.def
@@ -0,0 +1,49 @@
+;//+-------------------------------------------------------------------------
+;//
+;// Microsoft Windows
+;// Copyright (C) Microsoft Corporation, 1992 - 1993.
+;//
+;// File: storage.def
+;//
+;// Contents: storage.dll module definition file
+;//
+;// History: 23-Sep-92 DrewB Created from multiple def files
+;// 09-Oct-92 AlexT Added HEAPSIZE to 16-bit definitions
+;// 03-Feb-93 DrewB Changed docfile.def to storage.def
+;//
+;// Note: $(OLE)\storage.def is used for 16-bit and OLE32 32-bit builds
+;// $(COMMON)\ilib\storage.def is used for Cairo 32-bit builds
+;//
+;//--------------------------------------------------------------------------
+
+LIBRARY STORAGE
+DESCRIPTION 'Storage DLL'
+;EXETYPE WINDOWS 3.1
+
+CODE DISCARDABLE LOADONCALL MOVABLE SHARED
+DATA LOADONCALL SINGLE MOVABLE
+
+; HEAPSIZE is required for RETAIL 16-bit builds where
+; we do some local allocations.
+
+HEAPSIZE 1024
+
+EXPORTS
+ WEP @0 RESIDENTNAME
+
+ STGCREATEDOCFILE @1
+ STGCREATEDOCFILEONILOCKBYTES @2
+ STGOPENSTORAGE @3
+ STGOPENSTORAGEONILOCKBYTES @4
+ STGISSTORAGEFILE @5
+ STGISSTORAGEILOCKBYTES @6
+ STGSETTIMES @7
+
+ DLLGETCLASSOBJECT @103
+
+IMPORTS
+ KERNEL.LOADLIBRARYEX32W ;;@513 NODATA ;;
+ KERNEL.FREELIBRARY32W ;;@514 NODATA ;;
+ KERNEL.GETPROCADDRESS32W ;;@515 NODATA ;;
+ KERNEL.GETVDMPOINTER32W ;;@516 NODATA ;;
+ KERNEL.CALLPROC32W ;;@517 NODATA ;;
diff --git a/private/ole32/olethunk/ole16/storage/storage.rc b/private/ole32/olethunk/ole16/storage/storage.rc
new file mode 100644
index 000000000..266736186
--- /dev/null
+++ b/private/ole32/olethunk/ole16/storage/storage.rc
@@ -0,0 +1,33 @@
+#include <windows.h>
+
+#include "verinfo.h"
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION VER_FILEVERSION
+PRODUCTVERSION VER_PRODUCTVERSION
+FILEFLAGSMASK VER_FILEFLAGSMASK
+FILEFLAGS VER_FILEFLAGS
+FILEOS VER_FILEOS
+FILETYPE VER_FILETYPE
+FILESUBTYPE VER_FILESUBTYPE
+{
+ BLOCK "StringFileInfo"
+ {
+ BLOCK "040904E4"
+ {
+ VALUE "CompanyName", VER_COMPANYNAME_STR
+ VALUE "FileDescription", VER_FILEDESCRIPTION_STR
+ VALUE "FileVersion", VER_FILEVERSION_STR
+ VALUE "InternalName", "STORAGE.DLL\0"
+ VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
+ VALUE "LegalTrademarks", VER_LEGALTRADEMARKS_STR
+ VALUE "ProductName", VER_PRODUCTNAME_STR
+ VALUE "ProductVersion", VER_PRODUCTVERSION_STR
+ VALUE "Comments", VER_COMMENT_STR
+ }
+ }
+ BLOCK "VarFileInfo"
+ {
+ VALUE "Translation", 0x409, 1252
+ }
+}
diff --git a/private/ole32/olethunk/ole16/tools/c1.err b/private/ole32/olethunk/ole16/tools/c1.err
new file mode 100644
index 000000000..27d7b71e0
--- /dev/null
+++ b/private/ole32/olethunk/ole16/tools/c1.err
@@ -0,0 +1,1029 @@
+
+
+
+
+4001 "nonstandard extension '%Fs' was used"
+4002 "too many actual parameters for macro '%s'"
+4003 "not enough actual parameters for macro '%s'"
+4004 "incorrect construction after 'defined'"
+4005 "'%Fs' : macro redefinition"
+4006 "#undef expected an identifier"
+4007 "'%Fs' : must be '%Fs'"
+4008 "'%Fs' : '%Fs' attribute ignored"
+4009 "string too big; trailing characters truncated"
+4010 "single-line comment contains line-continuation character"
+4011 "'%Fs' : identifier was truncated to '%d' characters"
+4012 "float constant in a cross compilation"
+4013 "'%Fs' undefined; assuming extern returning int"
+4014 "concatenating mismatched wide strings"
+4015 "'%Fs' : type of bit field must be integral"
+4016 "'%s' : no function return type; using 'int' as default"
+4017 "cast of 'int' expression to far pointer"
+4018 "'%Fs' : signed/unsigned mismatch"
+4019 "empty statement at global scope"
+4020 "'%Fs' : too many actual parameters"
+4021 "'%Fs' : too few actual parameters"
+4022 "'%Fs' : pointer mismatch for actual parameter %d"
+4023 "'%Fs' : based pointer passed to unprototyped function : parameter %d"
+4024 "'%Fs' : different types for formal and actual parameter %d"
+4025 "'%Fs' : based pointer passed to function with variable arguments: parameter %d"
+4026 "function declared with formal parameter list"
+4027 "function declared without formal parameter list"
+4028 "formal parameter %d different from declaration"
+4029 "declared formal parameter list different from definition"
+4030 "first formal parameter list longer than the second list"
+4031 "second formal parameter list longer than the first list"
+4032 "formal parameter %d has different type when promoted"
+4033 "'%Fs' must return a value"
+4034 "sizeof returns 0"
+4035 "'%Fs' : no return value"
+4036 "unnamed %Fs as actual parameter"
+4037 "conflicting ambient class modifiers"
+4038 "'%Fs' : illegal ambient class modifier"
+4039 "ambient class modifier on reference ignored"
+4040 "memory attribute on '%Fs' ignored"
+4041 "illegal modifier for 'this' pointer"
+4042 "'%Fs' : has bad storage class"
+4043 "function specifier used more than once"
+4044 "specifier __huge on '%Fs' ignored; can only be applied to array"
+4045 "'%Fs' : array bounds overflow"
+4046 "'%Fs' : unsized array treated as %Fs"
+4047 "'%Fs' : different levels of indirection"
+4048 "different declared array subscripts"
+4049 "'%Fs' : indirection to different types"
+4050 "'%Fs' : different code attributes"
+4051 "type conversion; possible loss of data"
+4052 "function declarations different; one contains variable arguments"
+4053 "one void operand for '?:'"
+4054 "function pointer cast to a data pointer"
+4055 "data pointer cast to a function pointer"
+4056 "overflow in floating point constant arithmetic"
+4057 "'%Fs' : indirection to slightly different base types"
+4058 "unions are now aligned on alignment requirement, not size"
+
+4067 "unexpected characters following '%Fs' directive - newline expected"
+4068 "unknown pragma"
+
+4070 "return of a 'void' expression"
+4071 "'%Fs' : no function prototype given"
+4072 "'%Fs' : no function prototype on __fastcall function"
+4073 "initializers put in library initialization area"
+4074 "initializers put in compiler reserved initialization area"
+4075 "initializers put in unrecognized initialization area"
+4076 "'%Fs' : may be used on integral types only"
+4077 "unknown check_stack option"
+4078 "case constant '%ld' too big for the type of the switch expression"
+4079 "unexpected token '%Fs'"
+4080 "expected identifier for segment name; found '%Fs'"
+4081 "expected a comma; found '%Fs'"
+4082 "expected an identifier; found '%Fs'"
+4083 "expected '('; found '%Fs'"
+4084 "expected a pragma directive; found '%Fs'"
+4085 "expected 'on' or 'off'"
+4086 "expected '1', '2', '4', or '8'"
+4087 "'%Fs' : declared with 'void' parameter list"
+4088 "'%Fs' : pointer mismatch in actual parameter %d, formal parameter %d"
+4089 "'%Fs' : different types in actual parameter %d, formal parameter %d"
+4090 "'%Fs' : different const or volatile qualifiers"
+4091 "no symbols were declared"
+4092 "sizeof returns 'unsigned long'"
+4093 "unescaped newline in character constant in inactive code"
+4094 "untagged '%Fs' declared no symbols"
+4095 "expected ')'; found '%Fs'"
+4096 "'%Fs' must be used with '%Fs'"
+4097 "nonstandard extension : typedef-name '%Fs' used as synonym for class-name '%Fs'"
+4098 "'%Fs' : 'void' function returning a value"
+4099 "type declared with '%Fs' is defined with '%Fs'"
+4100 "'%Fs' : unreferenced formal parameter"
+4101 "'%Fs' : unreferenced local variable"
+4102 "'%Fs' : unreferenced label"
+4103 "'%Fs' : used #pragma pack to change alignment"
+4104 "'%Fs' : near data in same_seg pragma; ignored"
+4105 "'%Fs' : code modifiers only on function or pointer to function"
+4106 "pragma requires an integer between 1 and 127"
+4107 "pragma requires an integer between 15 and 255"
+4108 "pragma requires an integer between 79 and 132"
+4109 "unexpected identifier '%Fs'"
+4110 "unexpected token 'number'"
+4111 "unexpected token 'string'"
+4112 "#line requires an integer between 1 and 32767"
+4113 "function parameter lists differed"
+4114 "same type qualifier used more than once"
+4115 "'%Fs' : named type definition in parentheses"
+4116 "unnamed type definition in parentheses"
+4117 "macro name '%Fs' is reserved, '%Fs' ignored"
+4118 "pragma not supported"
+4119 "different bases '%Fs' and '%Fs' specified"
+4120 "based/unbased mismatch"
+4121 "'%Fs' : alignment of a member was sensitive to packing"
+4122 "'%Fs' : alloc_text applicable only to functions with C linkage"
+4123 "different base expressions specified"
+4124 "__fastcall with stack checking is inefficient"
+4125 "decimal digit terminates octal escape sequence"
+4126 "'%c' : unknown memory-model command-line option"
+4127 "conditional expression is constant"
+4128 "storage-class specifier after type"
+4129 "'%c' : unrecognized character escape sequence"
+4130 "'%Fs' : logical operation on address of string constant"
+4131 "'%Fs' : uses old-style declarator"
+4132 "'%Fs' : const object should be initialized"
+4133 "'%Fs' : incompatible types - 'void' pointer combined with non-'void' pointer"
+4134 "conversion between pointers to members of same class"
+4135 "conversion between different integral types"
+4136 "conversion between different floating-point types"
+4137 "'%Fs' : no return value from floating-point function"
+4138 "'*/' found outside of comment"
+4139 "'0x%lx' : hex escape sequence is out of range"
+4140 "'%Fs' : redefined, preceding references may be invalid"
+4141 "'%Fs' : used more than once"
+4142 "benign redefinition of type"
+4143 "pragma 'same_seg' not supported; use __based allocation"
+4144 "'%Fs' : relational expression as switch expression"
+4145 "'%Fs' : relational expression as switch expression; possible confusion with '%Fs'"
+
+4146 "unary minus operator applied to unsigned type, result still unsigned"
+4147 "'%Fs' : '%Fs' ignored on pointer and reference declarations"
+4148 "'%Fs' : DS != SS for '__near' '%Fs'"
+4149 "'%Fs' : different ambient model than base class '%Fs'"
+4150 "deletion of pointer to incomplete type '%Fs'; no destructor called"
+4151 "'%Fs' : operator should be explicitly '%Fs'"
+4152 "non standard extension, function/data ptr conversion in expression"
+4153 "function/data ptr conversion in expression"
+4154 "deletion of an array expression; conversion to pointer supplied"
+4155 "deletion of an array expression without using the array form of 'delete'"
+4156 "deletion of an array expression without using the array form of 'delete'; array form substituted"
+
+4184 "near call to thunk for '%Fs' in a different segment"
+
+4241 "'%Fs' : member access is restricted"
+
+4245 "'friend' specified for nonexistent function '%Fs'"
+
+4247 "'%Fs' not accessible because '%Fs' uses '%Fs' to inherit from '%Fs'"
+4248 "'%Fs' : cannot access '%Fs' member declared in class '%Fs'"
+4249 "'%Fs' : no path to '%Fs' member declared in virtual base '%Fs'"
+4250 "'%Fs' : inherits '%Fs::%Fs' via dominance"
+4251 "'%Fs' : base type '%Fs' should be exported to export %Fs '%Fs'"
+4252 "'%Fs' is not defined; cannot specify CV information."
+
+4260 "no override, '%Fs::%Fs' has %Fs 'this' memory model whereas '%Fs::%Fs' has %Fs 'this' memory model"
+4261 "no override, '%Fs::%Fs' has %Fs calling convention whereas '%Fs::%Fs' has %Fs calling convention"
+
+4300 "conversion of pointer to nonintegral type"
+4301 "truncation during conversion of pointer to integral type"
+4302 "truncation during conversion of pointer to function"
+4303 "truncation during conversion of pointer to function to pointer to object"
+4304 "truncation during pointer conversion"
+4305 "truncation during conversion of integral type to pointer"
+4306 "conversion of integral type to pointer of greater size"
+4307 "'%Fs' : integral constant overflow; result truncated"
+4308 "negative integral constant converted to unsigned type"
+4309 "'%Fs' : truncation of constant value"
+
+4341 "signed value out of range for enum constant"
+4342 "precision lost in initialization of enum constant"
+
+4354 "'%Fs' : initialization of reference to member requires a temporary variable"
+4355 "'this' : used in base member initializer list"
+
+4385 "%Fs the '%Fs' in base '%Fs'"
+4386 "%Fs to the '%Fs' in base '%Fs'"
+
+4401 "'%Fs' : member is bit field"
+4402 "must use PTR operator"
+4403 "illegal PTR operator"
+4404 "period on directive ignored"
+4405 "'%Fs' : identifier is reserved word"
+4406 "operand on directive ignored"
+
+4409 "illegal instruction size"
+4410 "illegal size for operand"
+4411 "'%Fs' : symbol resolves to displacement register"
+
+4414 "'%Fs' : short jump to function converted to near"
+
+4500 "'%Fs' : class has private/protected data members; user-defined constructor advised"
+4501 "'%Fs' : use of '::' unnecessary here"
+4502 "'linkage' requires use of keyword 'extern'"
+
+4505 "'%Fs' : unreferenced local function has been removed"
+4506 "no definition for inline function '%Fs'"
+4507 "explicit linkage specified after default linkage was used"
+4508 "'%Fs' : function should return a value; 'void' return type assumed"
+
+4510 "'%Fs' : default constructor could not be generated"
+4511 "'%Fs' : copy constructor could not be generated"
+4512 "'%Fs' : assignment operator could not be generated"
+4513 "'%Fs' : destructor could not be generated"
+
+4520 "'%Fs' : multiple default constructors specified"
+4521 "'%Fs' : multiple copy constructors specified"
+4522 "'%Fs' : multiple assignment operators specified"
+4523 "'%Fs' : multiple destructors specified"
+4524 "'%Fs' : redundant use of 'friend' on destructor"
+4525 "'%Fs' : redundant use of 'friend' on constructor"
+
+4527 "instances of %Fs '%Fs' can never be destroyed - user-defined destructor required"
+4528 "illegal 'pure' syntax, must be '= 0'"
+
+4607 "'%Fs' : must be initialized in constructor base/member initializer list"
+
+4610 "%Fs '%Fs' can never be instantiated - user defined constructor required"
+
+4612 "bad #pragma syntax, pragma ignored"
+4613 "'%Fs' : class of segment cannot be changed"
+4614 "'%Fs' : varargs parameters with this type were promoted"
+4615 "#pragma warning : unknown user warning type"
+4616 "#pragma warning : warning number '%d' out of range, must be between '%d' and '%d'"
+4617 "#pragma warning : invalid warning number"
+
+4620 "no postfix form of 'operator ++' found for type '%Fs', using prefix form"
+4621 "no postfix form of 'operator --' found for type '%Fs', using prefix form"
+4622 "Overwriting debug information formed during creation of the precompiled header in object file: '%s'"
+
+4630 "'%Fs' : '%Fs' storage class specifier illegal on member definition"
+
+4650 "debugging information not in precompiled header; only global symbols from the header will be available"
+4651 "'/D%s' specified for precompiled header but not for current compile"
+4652 "command-line option '%Fs' inconsistant with precompiled header; PCH option ignored"
+
+4706 "assignment within conditional expression"
+
+4710 "'%Fs' : function not expanded"
+
+4726 "'%c' : unknown memory model command-line option"
+4727 "conditional expression is constant"
+
+4741 "/Oq option ignored for __fastcall function '%Fs'"
+
+4746 "'%Fs' : unsized array given size %Fs"
+
+4756 "overflow in constant arithmetic"
+
+4758 "address of automatic (local) variable taken, DS != SS"
+4759 "segment lost in conversion"
+
+4761 "integral size mismatch in argument : conversion supplied"
+4762 "near/far mismatch in argument : conversion supplied"
+
+4769 "conversion of near pointer to long integer"
+
+4785 "near call to '%Fs' in different segment"
+
+4788 "'%Fs' : identifier was truncated to '%d' characters"
+
+4793 "native code generated for p-code function '%Fs' with inline assembly"
+
+4900 "Il mismatch between '%s' version '%ld' and '%s' version '%ld'"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4000 "UNKNOWN WARNING\n\t\tContact Microsoft Product Support Services"
+
+
+2001 "newline in constant"
+2002 "invalid wide-character constant"
+2003 "expected 'defined id'"
+2004 "expected 'defined(id)'"
+2005 "#line expected a line number, found '%Fs'"
+2006 "#include expected a file name, found '%Fs'"
+2007 "#define syntax"
+2008 "'%c' : unexpected in macro definition"
+2009 "reuse of macro formal '%Fs'"
+2010 "'%c' : unexpected in macro formal parameter list"
+2011 "'%Fs' : '%Fs' type redefinition"
+2012 "missing name following '<'"
+2013 "missing '>'"
+2014 "preprocessor command must start as first nonwhite space"
+2015 "too many characters in constant"
+2016 "no closing single quotation mark"
+2017 "illegal escape sequence"
+2018 "unknown character '0x%x'"
+2019 "expected preprocessor directive, found '%c'"
+2020 "'%Fs' : '%Fs' member redefinition"
+2021 "expected exponent value, not '%c'"
+2022 "'%ld' : too big for character"
+2023 "divide by 0"
+2024 "mod by 0"
+2025 "'%s' : enum/struct/union type redefinition"
+2026 "string too big, trailing characters truncated"
+2027 "use of undefined type '%Fs'"
+2028 "struct/union member must be inside a struct/union"
+2029 "left of '%s' specifies undefined class/struct/union '%Fs'"
+2030 "'%Fs' : struct/union member redefinition"
+2031 "'%Fs' : function cannot be struct/union member"
+2032 "'%Fs' : function cannot be member of %Fs '%Fs'"
+2033 "'%Fs' : bit field cannot have indirection"
+2034 "'%Fs' : type of bit field too small for number of bits"
+2035 "struct/union '%Fs' : unknown size"
+2036 "'%Fs' : unknown size"
+2037 "left of '%s' specifies undefined struct/union '%Fs'"
+2038 "'%s' : not struct/union member"
+2039 "'%Fs' : is not a member of '%Fs'"
+2040 "'%Fs' : different levels of indirection"
+2041 "illegal digit '%c' for base '%d'"
+2042 "signed/unsigned keywords mutually exclusive"
+2043 "illegal break"
+2044 "illegal continue"
+2045 "'%Fs' : label redefined"
+2046 "illegal case"
+2047 "illegal default"
+2048 "more than one default"
+2049 "case value '%ld' already used"
+2050 "nonintegral switch expression"
+2051 "case expression not constant"
+2052 "case expression not integral"
+2053 "'%Fs' : wide string mismatch"
+2054 "expected '(' to follow '%Fs'"
+2055 "expected formal parameter list, not a type list"
+2056 "illegal expression"
+2057 "expected constant expression"
+2058 "constant expression is not integral"
+2059 "syntax error : '%Fs'"
+2060 "syntax error : end-of-file found"
+2061 "syntax error : identifier '%Fs'"
+2062 "type '%Fs' unexpected"
+2063 "'%Fs' : not a function"
+2064 "term does not evaluate to a function"
+2065 "'%Fs' : undeclared identifier"
+2066 "cast to function type is illegal"
+2067 "cast to array type is illegal"
+2068 "illegal cast"
+2069 "cast of 'void' term to non-'void'"
+2070 "illegal sizeof operand"
+2071 "'%Fs' : illegal storage class"
+2072 "'%Fs' : initialization of a function"
+2073 "'%Fs' : partially initialized array requires a default constructor"
+2074 "'%Fs' : '%Fs' initialization needs curly braces"
+2075 "'%Fs' : array initialization needs curly braces"
+2076 "'%Fs' : struct/union initialization needs curly braces"
+2077 "nonscalar field initializer '%Fs'"
+2078 "too many initializers"
+2079 "'%Fs' uses undefined class/struct/union '%Fs'"
+2080 "illegal __far __fastcall function or __saveregs function"
+2081 "'%Fs' : name in formal parameter list illegal"
+2082 "redefinition of formal parameter '%Fs'"
+2083 "%Fs comparison illegal"
+2084 "function '%Fs' already has a body"
+2085 "'%Fs' : not in formal parameter list"
+2086 "'%Fs' : redefinition"
+2087 "'%Fs' : missing subscript"
+2088 "'%Fs' : illegal for %Fs"
+2089 "'%Fs' : '%Fs' too large"
+2090 "function returns array"
+2091 "function returns function"
+2092 "array element type cannot be function"
+2093 "cannot use address of automatic variable as static initializer"
+2094 "label '%Fs' was undefined"
+2095 "'%Fs' : actual has type 'void' : parameter %d"
+2096 "struct/union comparison illegal"
+2097 "illegal initialization"
+2098 "nonaddress expression"
+2099 "nonconstant initializer"
+2100 "illegal indirection"
+2101 "'%Fs' on constant"
+2102 "'%Fs' requires lvalue"
+2103 "'%Fs' on register variable"
+2104 "'%Fs' on bit field ignored"
+2105 "'%Fs' needs lvalue"
+2106 "'%Fs' : left operand must be lvalue"
+2107 "illegal index, indirection not allowed"
+2108 "nonintegral index"
+2109 "subscript on nonarray"
+2110 "pointer + pointer"
+2111 "pointer + nonintegral value"
+2112 "illegal pointer subtraction"
+2113 "pointer subtracted from nonpointer"
+2114 "'%Fs' : pointer on left; needs integral value on right"
+2115 "'%Fs' : incompatible types"
+2116 "function parameter lists differed"
+2117 "'%Fs' : array bounds overflow"
+2118 "negative subscript"
+2119 "typedef types both define indirection"
+2120 "'void' illegal with all types"
+2121 "'%Fs' : bad %Fs operand"
+2122 "'%Fs' : prototype parameter in name list illegal"
+2123 "'%Fs' : cannot call __fastcall function '%Fs' from p-code"
+2124 "divide or mod by zero"
+2125 "'%Fs' : allocation exceeds 64K"
+2126 "'%Fs' : incorrect operand"
+2127 "parameter allocation exceeds 32K"
+2128 "'%Fs' : alloc_text/same_seg applicable only to functions with C linkage"
+2129 "static function '%Fs' declared but not defined"
+2130 "#line expected a string containing the file name, found '%Fs'"
+2131 "more than one memory attribute"
+2132 "syntax error : unexpected identifier"
+2133 "'%Fs' : unknown size"
+2134 "'%Fs' : struct/union too large"
+2135 "'%Fs' : illegal bit field operation"
+2136 "'%Fs' : prototype must have parameter types"
+2137 "empty character constant"
+2138 "illegal to define an enumeration without any members"
+2139 "type following '%s' is illegal"
+2140 "parameter cannot be function type"
+2141 "value out of range for enum constant"
+2142 "function declarations differ, variable parameters specified only in one of them"
+2143 "syntax error : missing '%Fs' before '%Fs'"
+2144 "syntax error : missing '%Fs' before type '%Fs'"
+2145 "syntax error : missing '%Fs' before identifier"
+2146 "syntax error : missing '%Fs' before identifier '%Fs'"
+2147 "'%Fs' : const array must be fully initialized"
+2148 "array too large"
+2149 "'%Fs' : named bit field cannot have zero width"
+2150 "'%Fs' : bit field must have type 'int', 'signed int', or 'unsigned int'"
+2151 "more than one language attribute"
+2152 "'%Fs' : pointers to functions with different attributes"
+2153 "hex constants must have at least one hex digit"
+2154 "'%Fs' : does not refer to a segment name"
+
+2156 "pragma must be outside function"
+2157 "'%Fs' : must be declared before use in pragma list"
+2158 "'%Fs' : is a function"
+2159 "more than one storage class specified"
+2160 "## cannot occur at the beginning of a macro definition"
+2161 "## cannot occur at the end of a macro definition"
+2162 "expected macro formal parameter"
+2163 "'%Fs' : not available as an intrinsic function"
+2164 "'%Fs' : intrinsic function not declared"
+2165 "'%Fs' : cannot modify pointers to data"
+2166 "lvalue specifies const object"
+2167 "'%Fs' : too many actual parameters for intrinsic function"
+2168 "'%Fs' : too few actual parameters for intrinsic function"
+2169 "'%Fs' : intrinsic function, cannot be defined"
+2170 "'%Fs' : not declared as a function, cannot be intrinsic"
+2171 "'%Fs' : illegal operand"
+2172 "'%Fs' : actual parameter is not a pointer : parameter %d"
+2173 "'%Fs' : actual parameter is not a pointer : parameter %d, parameter list %d"
+2174 "'%Fs' : actual parameter has type 'void' : parameter %d, parameter list %d"
+
+2176 "static huge data not supported by '%Fs'"
+2177 "constant too big"
+2178 "'%Fs' : storage class for same_seg variables must be extern"
+2179 "'%Fs' : was used in same_seg, but storage class is no longer extern"
+2180 "controlling expression has type 'void'"
+
+2182 "'%Fs' : has type 'void'"
+
+2184 "illegal return of a 'void' value"
+2185 "'%Fs' : illegal based allocation"
+2186 "'%Fs' : illegal operand of type 'void'"
+2187 "cast of near function pointer to far function pointer"
+2188 "'%ld' : too big for wide character"
+2189 "#error : %Fs"
+2190 "first parameter list longer than second"
+2191 "second parameter list longer than first"
+2192 "parameter '%d' declaration different"
+2193 "'%Fs' : already in a segment"
+2194 "'%Fs' : is a text segment"
+2195 "'%Fs' : is a data segment"
+2197 "'%Fs' : too many actual parameters"
+2198 "'%Fs' : too few actual parameters"
+2199 "syntax error : found '%Fs (' at global scope. (was a declaration intended?)"
+2200 "'%Fs' : function has already been defined"
+2201 "'%Fs' : cannot export static declarations"
+2202 "'%Fs' : not all control paths return a value"
+2203 "delete operator cannot specify bounds for an array"
+2204 "'%Fs' : parenthesized type definition"
+2205 "'%Fs' : cannot initialize extern block scoped variables"
+2206 "'%Fs' : typedef cannot be used for function definition"
+2207 "'%Fs' in struct/union '%Fs' has a zero-sized array"
+2208 "'%Fs' : no members defined using this type"
+2209 "type cast in __based construct must be (__segment)"
+2210 "'%Fs' : must be near/far data pointer"
+2211 "(__segment) applied to function identifier '%Fs'"
+2212 "'%Fs' : __based not available for pointers to functions"
+2213 "'%Fs' : illegal argument to __based"
+2214 "pointers based on 'void' require the use of :>"
+2215 ":> operator only for objects based on 'void'"
+2216 "'%Fs' cannot be used with '%Fs'"
+2217 "'%Fs' must be used with '%Fs'"
+2218 "type in __based construct must be 'void'"
+2219 "syntax error : type qualifier must be after '*'"
+2220 "warning treated as error - no object file generated"
+2221 "'.' : left operand points to class/struct/union, use '->'"
+2222 "'->' : left operand has struct/union type, use '.'"
+2223 "left of '->%Fs' must point to class/struct/union"
+2224 "left of '.%Fs' must have class/struct/union type"
+2225 "'%Fs' : function allocation must be in a named segment"
+2226 "syntax error : unexpected type '%Fs'"
+2227 "left of '->%Fs' must point to class/struct/union"
+2228 "left of '.%Fs' must have class/struct/union type"
+2229 "%Fs '%Fs' has an illegal zero-sized array"
+2230 "'%Fs' : indirection to different types"
+2231 "'.' : left operand points to '%Fs', use '->'"
+2232 "'->' : left operand has '%Fs' type, use '.'"
+
+2234 "arrays of references are illegal"
+2235 "';' in formal parameter list"
+2236 "unexpected '%Fs' '%Fs'"
+2237 "unexpected %Fs '%Fs'"
+2238 "unexpected token[s] preceding '%s'"
+2239 "unexpected token '%Fs' following declaration of '%Fs'"
+2240 "unexpected '%Fs' following formal list. (only modifiers are allowed.)"
+2241 "'%Fs' : member access is restricted"
+
+2244 "'%Fs' : unable to resolve function overload"
+2245 "nonexistent function '%Fs' specified as friend"
+2246 "'%Fs' : illegal static data member in locally defined class"
+2247 "'%Fs' not accessible because '%Fs' uses '%Fs' to inherit from '%Fs'"
+2248 "'%Fs' : cannot access '%Fs' member declared in class '%Fs'"
+2249 "'%Fs' : no accessible path to '%Fs' member declared in virtual base '%Fs'"
+2250 "'%Fs' : ambiguous inheritance of '%Fs::%Fs'"
+
+2252 "'%Fs' : pure specifier can only be specified for functions"
+2253 "'%Fs' : pure specifier only applies to virtual function -- specifier ignored"
+2254 "'%Fs' : pure specifier not allowed on friend functions"
+2255 "'%Fs' : a friend function can only be declared in a class"
+2256 "illegal use of friend specifier on '%Fs'"
+2257 "p-code generation pragma not allowed without /Oq"
+2258 "illegal pure syntax, must be '= 0'"
+2259 "'%Fs' : illegal attempt to instantiate abstract class"
+2260 "function pointer cast to a data pointer "
+2261 "data pointer cast to a function pointer"
+2262 "'%Fs' : cannot be destroyed"
+2263 "function returns pointer based on __self"
+2264 "'%Fs' : error in function definition or declaration; function not called"
+2265 "'%Fs' : reference to a zero sized array is illegal"
+2266 "'%Fs' : reference to a nonconstant bounded array is illegal"
+2267 "'%Fs' : block scoped static functions are illegal"
+2268 "'%Fs' : different const or volatile qualifiers"
+2269 "'%Fs' : different ambient model than base class '%Fs'"
+2270 "'%Fs' : modifiers not allowed on nonmember functions"
+2271 "'%Fs' : new/delete cannot have formal list modifiers"
+2272 "'%Fs' : modifiers not allowed on static member functions"
+2273 "'%Fs' : illegal as right side of '->' operator"
+2274 "'%Fs' : illegal as right side of '.' operator"
+2275 "'%Fs' : illegal use of this type as an expression"
+2276 "illegal address of bound member function expression"
+2277 "'%Fs' : cannot take the address of a constructor"
+2278 "'%Fs' : no function with C linkage found"
+2279 "cannot use braces to initialize default arguments"
+2280 "missing '{' before identifier '%Fs'?"
+2281 "'%Fs' : is not a function, but contains <function returning>. '%Fs' is unexpected."
+2282 "'%Fs' is followed by '%Fs'. (missing ','?)"
+2283 "'%Fs' : pure specifier not allowed on un-named %Fs"
+
+2290 "C++ '%Fs' syntax is reserved for future use"
+
+2350 "'%Fs' is not a static member"
+2351 "obsolete C++ constructor initialization syntax"
+2352 "'%Fs::%Fs' : illegal call of non-static member function"
+2353 "'%Fs' : improper use of constructor initializers"
+2354 "'%Fs' : initialization of reference member requires a temporary variable"
+2355 "'this' : can only be referenced inside non-static member functions"
+2356 "initialization segment must not change during translation unit"
+
+2360 "Initialization of '%Fs' is skipped by 'case' label"
+2361 "Initialization of '%Fs' is skipped by 'default' label"
+2362 "Initialization of '%Fs' is skipped by 'goto %Fs'"
+
+2370 "'%Fs' : redefinition; different storage class"
+2371 "'%Fs' : redefinition; different basic types"
+2372 "'%Fs' : redefinition; different types of indirection"
+2373 "'%Fs' : redefinition; different type modifiers"
+2374 "'%Fs' : redefinition; multiple initialization"
+2375 "'%Fs' : redefinition; different linkage"
+
+2377 "'%Fs' : redefinition; typedef cannot be overloaded with any other symbol"
+2378 "'%Fs' : redefinition; symbol cannot be overloaded with a typedef"
+2379 "formal parameter %d has different type when promoted"
+2380 "type[s] preceding '%Fs'. (constructor with return type, or illegal redefinition of current class-name?)"
+
+2385 "'%Fs::%Fs' is ambiguous"
+2386 "ambiguous conversion from '%Fs*' to '%Fs*'"
+2387 "ambiguous conversion from '%Fs&' to '%Fs&'"
+
+2390 "'%Fs' : incorrect storage class '%Fs'"
+
+2400 "inline syntax error in '%Fs'; found '%Fs'"
+2401 "'%Fs' : register must be base in '%Fs'"
+2402 "'%Fs' : register must be index in '%Fs'"
+2403 "'%Fs' : register must be base/index in '%Fs'"
+2404 "'%Fs' : illegal register in '%Fs'"
+2405 "illegal short forward reference with offset"
+2406 "'%Fs' : name undefined in '%Fs'"
+2407 "illegal 'float' register in '%Fs'"
+2408 "illegal type on PTR operator in '%Fs'"
+2409 "illegal type used as operator in '%s'"
+2410 "'%Fs' : ambiguous member name in '%Fs'"
+2411 "'%Fs' : illegal struct/union member in '%Fs'"
+2412 "'%Fs' : case-insensitive label redefined"
+2413 "'%Fs' : illegal align size"
+2414 "illegal number of operands"
+2415 "improper operand type"
+2416 "'%Fs' : illegal opcode for processor"
+2417 "divide by zero in '%Fs'"
+2418 "'%Fs' : not in a register"
+2419 "mod by zero in '%Fs'"
+2420 "'%Fs' : illegal symbol in %Fs"
+2421 "PTR operator used with register in '%Fs'"
+2422 "illegal segment override in '%Fs'"
+2423 "'%ld' : illegal scale"
+2424 "'%Fs' : improper expression in '%Fs'"
+2425 "'%Fs' : nonconstant expression in '%Fs'"
+2426 "'%Fs' : illegal operator in '%Fs'"
+2427 "'%Fs' : jump referencing label is out of range"
+
+2429 "'%Fs' : illegal far label reference"
+2430 "more than one index register in '%Fs'"
+2431 "illegal index register in '%Fs'"
+2432 "illegal reference to 16-bit data in '%Fs'"
+2433 "'%Fs' : '%Fs' not permitted on data declarations"
+2434 "'%Fs' : cannot convert default argument from '%Fs' to '%Fs'"
+
+2436 "'%Fs' : cannot initialize member functions"
+2437 "'%Fs' : already initialized"
+2438 "'%Fs' : cannot initialize static class data via constructor"
+2439 "'%Fs' : member could not be initialized"
+2440 "'%Fs' : cannot convert from '%Fs' to '%Fs'"
+
+2442 "p-code expression too complex for setjmp or Catch"
+2443 "operand size conflict"
+
+2446 "'%Fs' : no conversion between '%Fs' and '%Fs'"
+2447 "missing function header (old-style formal list?)"
+2448 "'%Fs' : function-style initializer appears to be a function definition"
+
+2450 "switch expression of type '%Fs' is illegal"
+2451 "conditional expression of type '%Fs' is illegal"
+
+2458 "'%Fs' : redefinition within definition"
+2459 "'%Fs' : is being defined; cannot add as an anonymous member"
+2460 "'%Fs' : uses '%Fs', which is being defined"
+2461 "'%Fs' : constructor syntax missing formal parameters"
+2462 "'%Fs' : cannot define a type in a 'new-expression'"
+2463 "cannot define an anonymous type in a 'new-expression'"
+2464 "'%Fs' : cannot use 'new' to allocate a reference"
+2465 "cannot define an anonymous type inside parentheses"
+2466 "cannot allocate an array of constant size 0"
+2467 "illegal declaration of anonymous '%Fs'"
+
+2500 "'%Fs' : '%Fs' is already a direct base class"
+2501 "'%Fs' : missing decl-specifiers"
+2502 "'%Fs' : too many access modifiers on the base class"
+2503 "'%Fs' : base classes cannot contain zero-sized arrays"
+2504 "'%Fs' : base class undefined"
+2505 "'%Fs' : is not a legal base class"
+2506 "'%Fs::%Fs' : ambiguous"
+2507 "'%Fs' : too many virtual modifiers on the base class"
+2508 "'%Fs' : access denied"
+2509 "'%Fs' : member function not declared in '%Fs'"
+2510 "'%Fs' : left of '::' must be a class/struct/union"
+2511 "'%Fs' : overloaded member function not found in '%Fs'"
+2512 "'%Fs' : no appropriate default constructor available"
+2513 "'%Fs' : decl-specifier is missing a declarator before '='"
+2514 "'%Fs' : class has no constructors"
+2515 "'%Fs' : not in class '%Fs'"
+
+2517 "'%Fs' : right of '::' is undefined"
+
+2519 "cannot convert '%Fs *' to '%Fs *'"
+
+2523 "'%Fs::~%Fs' : destructor tag mismatch"
+2524 "'%Fs' : destructors must have a 'void' formal parameter list"
+
+2527 "'%Fs' : array of references must be fully initialized"
+2528 "illegal pointer to reference"
+2529 "illegal reference to a reference"
+2530 "'%Fs' : references must be initialized"
+2531 "'%Fs' : reference to a bit field illegal"
+2532 "'%s' : cannot modify references"
+2533 "'%Fs' : constructors not allowed a return type"
+2534 "'%Fs' : constructor cannot return a value"
+2535 "'%Fs' : member function already defined or declared"
+2536 "'%Fs::%Fs' : cannot specify explicit initializer for arrays"
+2537 "'%Fs' : illegal linkage specification"
+2538 "new : cannot specify initializer for arrays"
+2539 "new : '%Fs' no default constructor to initialize arrays of objects"
+2540 "nonconstant expression as array bound"
+2541 "delete : cannot delete nonpointer objects"
+2542 "'%Fs' : class object has no constructor for initialization"
+2543 "expected ']' for operator '[]'"
+2544 "expected ')' for operator '()'"
+2545 "'%Fs' : unable to find overloaded operator"
+2546 "'%Fs' : illegal mix of 'void' pointer with non-'void' pointer"
+2547 "illegal cast of overloaded function"
+2548 "'%Fs::%Fs' : missing default parameter for parameter %s"
+2549 "user-defined conversion cannot specify a return type"
+
+2551 "'void *' type needs explicit cast to non-'void' pointer type"
+2552 "'%Fs' : non-aggregates cannot be initialized with initializer list"
+2553 "no legal conversion of return value to return type '%Fs'"
+2555 "'%Fs::%Fs' : overriding virtual function differs from '%Fs::%Fs' only by return type"
+2556 "'%Fs' : overloaded functions only differ by return type"
+2557 "'%Fs' : non-public members cannot be initialized without a constructor"
+2558 "'%Fs' : no copy constructor available"
+2559 "'%Fs' : no match for specified operator"
+2560 "'%Fs' : overloaded function differs only by calling convention/memory model"
+2561 "'%Fs' : function must return a value"
+2562 "'%Fs' : 'void' function returning a value"
+2563 "mismatch in formal parameter list"
+2564 "formal/actual parameters mismatch in call through pointer to function"
+2565 "'::%Fs' was previously declared as a global function"
+2566 "overloaded function in conditional expression"
+
+2568 "'%Fs' : unable to resolve function overload '%Fs'"
+2569 "'%Fs' : union cannot be used as a base class"
+2570 "'%Fs' : union cannot have base classes"
+2571 "'%Fs' : union cannot have virtual function '%Fs'"
+2572 "'%Fs::%Fs' : redefinition of default parameter : parameter %s"
+2573 "'%Fs' : simple type cast must have exactly one expression"
+2574 "'%Fs' : illegal static destructor declaration"
+2575 "'%Fs' : only member functions and bases can be virtual"
+2576 "'%Fs' : virtual used for static member function"
+2577 "'%Fs' : destructor cannot return a value"
+
+2579 "'%Fs::%Fs(%s)' : parameter list not sufficiently different to '%Fs::%Fs(%s)'"
+2580 "redefinition of class name '%Fs'"
+2581 "'%Fs' : static 'operator =' function is illegal"
+2582 "'%Fs' : 'operator =' function is unavailable"
+2583 "'%Fs' : illegal const/volatile 'this' pointer used for constructors/destructors"
+2584 "'%Fs' : direct base '%Fs' is inaccessible; already a base of '%Fs'"
+2585 "explicit conversion to '%Fs' is ambiguous"
+2586 "incorrect user-defined conversion syntax : illegal indirections"
+2587 "'%Fs' : illegal use of local variable as default parameter"
+2588 "'::~%Fs' : illegal global destructor"
+2589 "'%Fs' : illegal token on right side of '::'"
+2590 "'%Fs' : ambiguous user-defined conversions in switch expression"
+2591 "'%Fs' : ambiguous user-defined conversions in conditional expression"
+2592 "no legal conversion of initialization expression to type '%Fs'"
+2593 "'operator %Fs' is ambiguous"
+2594 "'%Fs' : ambiguous conversions from '%Fs' to '%Fs'"
+2595 "'%Fs' : qualified name already has a constructor"
+2596 "'%Fs' : qualified name already has a destructor"
+2597 "'%Fs' : does not specify an object"
+2598 "linkage specification must be at global scope"
+2599 "'%Fs' : local functions are not supported"
+2601 "functions cannot be defined in local classes"
+2602 "'%Fs::%Fs' is not a member of a base of '%Fs'"
+2603 "illegal access declaration: '%Fs' is not a direct base of '%Fs'"
+2604 "cannot declare %Fs access to %Fs member '%Fs::%Fs'"
+2605 "overloaded functions '%Fs::%Fs' do not have same access"
+2606 "'%Fs::%Fs': illegal private access declaration"
+2607 "'%Fs' : cannot implicitly convert a '%Fs' to a non-const '%Fs'"
+2608 "illegal reference cast - operand not an lvalue"
+
+2610 "%Fs '%Fs' can never be instantiated; user defined constructor is required"
+2611 "'%Fs' : illegal following '~' (expected identifier)"
+2612 "trailing '%Fs' illegal in base/member initializer list"
+2613 "trailing '%Fs' illegal in base class list"
+2614 "'%Fs' : illegal member initialization: '%Fs' is not a base or member"
+2615 "memory attribute must appear before class name in pointer to member"
+2617 "'%Fs' : inconsistent return statement"
+2618 "'%Fs' : inconsistent return statement"
+2619 "union '%Fs' : can not have static member variable '%Fs'"
+2620 "union '%Fs' : member '%Fs' has default constructor"
+2621 "union '%Fs' : member '%Fs' has copy constructor"
+2622 "union '%Fs' : member '%Fs' has assignment operator"
+2623 "union '%Fs' : member '%Fs' has destructor"
+2624 "'%Fs' : references to 'void' are illegal"
+2625 "anonymous union did not declare any non-static data members"
+2626 "anonymous union defines %Fs member '%Fs'"
+2627 "member function defined in unnamed class"
+2628 "'%Fs' followed by '%Fs' is illegal. (did you forget a ';'?)"
+2629 "unexpected '%s ('"
+2630 "'%Fs' found in what should be a comma separated list"
+2631 "'%Fs' : destructors not allowed a return type"
+2632 "'%Fs' followed by '%Fs' is illegal"
+2633 "'%Fs' : 'inline' is the only legal storage class for constructors"
+2634 "'&%Fs::%Fs' : pointer to reference member is illegal"
+2635 "cannot convert a '%Fs*' to a '%Fs*'; conversion from a virtual base class is implied"
+2636 "pointer to reference member is illegal"
+2637 "'%s' : cannot modify pointers to data members"
+2638 "'%Fs' : memory model modifier illegal on pointer to data member"
+2639 "cannot use pointer to member expression &%Fs::%Fs - base '%Fs' is inherited as virtual"
+2640 "cannot convert a pointer to member across a virtual inheritance path"
+2641 "illegal pointer to member cast across virtual inheritance path"
+2642 "cast to pointer to member must be from related pointer to member"
+2643 "illegal cast from pointer to member"
+2644 "basis class '%Fs' for pointer to member has not been defined"
+2645 "no qualified name for pointer to member (found ':: *')"
+2646 "global anonymous unions must be declared static"
+2647 "'%Fs' : cannot dereference a '%Fs' on a '%Fs'"
+2648 "'%Fs' : use of non-static member as default parameter"
+2649 "'%Fs' : is not a '%Fs'"
+2650 "'%Fs' : cannot be a virtual function"
+
+2652 "'%Fs' : illegal copy constructor: first parameter must not be a '%Fs'"
+2653 "'%Fs' : is not a class name"
+2654 "'%Fs' : attempt to access member outside a member function"
+2655 "'%Fs' : definition or redeclaration illegal in current scope"
+2656 "'%Fs' : function not allowed as a bit field"
+2657 "'%Fs::*' found a the start of a statement. (did you forget to specify a type?)"
+2658 "multiple conversions : %Fs(%Fs) and %Fs::operator %Fs()"
+2659 "'%Fs' : overloaded function as left operand"
+2660 "'%Fs' : function does not take %d parameters"
+2661 "'%Fs' : no overloaded function takes %d parameters"
+2662 "'%Fs' : cannot convert 'this' pointer from '%Fs' to '%Fs'"
+2663 "'%Fs' : %d overloads have no legal conversion for 'this' pointer"
+2664 "'%Fs' : cannot convert parameter %d from '%Fs' to '%Fs'"
+2665 "'%Fs' : %d overloads have no legal conversion for parameter %d"
+2666 "'%Fs' : %d overloads have similar conversions"
+2667 "'%Fs' : none of %d overload have a best conversion"
+2668 "'%Fs' : ambiguous call to overloaded function"
+
+2671 "'%Fs' : static member functions do not have 'this' pointers"
+2672 "'%Fs' : new/delete member functions do not have 'this' pointers"
+2673 "'%Fs' : global functions do not have 'this' pointers"
+2674 "'%Fs' : no acceptable conversions from '%Fs' to '%Fs'"
+2675 "unary '%Fs' : '%Fs' does not define this operator or a conversion to a type acceptable to the builtin operator"
+2676 "binary '%Fs' : '%Fs' does not define this operator or a conversion to a type acceptable to the builtin operator"
+2677 "binary '%Fs' : no global operator defined which takes type '%Fs' (or there is no acceptable conversion)"
+
+2701 "'%Fs' : __oldcall function defined with varargs"
+2702 "'%Fs' : __try may not appear in termination block"
+
+2704 "'%Fs' : __va_start intrinsic only allowed in varargs"
+2705 "'%Fs' : illegal jump into __try scope"
+
+2707 "'%Fs' : bad context for intrinsic function"
+
+2710 "cannot delete a pointer to a const object"
+2711 "cannot delete a pointer to a function"
+
+2720 "'%Fs' : '%Fs' storage class specifier illegal on members"
+2721 "'%Fs' : storage class specifier illegal between operator keyword and type"
+2722 "'::%Fs' : illegal following operator command; use 'operator %Fs'"
+2723 "'%Fs' : '%Fs' storage class specifier illegal on function definition"
+
+2730 "'%Fs' : cannot be a base class of itself"
+
+2732 "linkage specification contradicts earlier specification for %Fs"
+2733 "second C linkage of overloaded function '%Fs' not allowed"
+2734 "'%Fs' : non-extern const object must be initialized"
+2735 "'%Fs' keyword is not permitted in formal parameter type specifier"
+2736 "'%Fs' keyword is not permitted in cast"
+2737 "'%Fs' : base class '%Fs' must be exported"
+
+2750 "'%Fs' : 'const T' to 'T' : '%Fs' to '%Fs'"
+2751 "'%Fs' : 'volatile T' to 'T' : '%Fs' to '%Fs'"
+2752 "'%Fs' : 'const T *' to 'T *' : '%Fs' to '%Fs'"
+2753 "'%Fs' : 'volatile T *' to 'T *' : '%Fs' to '%Fs'"
+2754 "'%Fs' : 'const T **' to 'T **' : '%Fs' to '%Fs'"
+2755 "'%Fs' : 'volatile T **' to 'T **' : '%Fs' to '%Fs'"
+2756 "'%Fs' : 'memory model mismatch' : '%Fs' to '%Fs'"
+2757 "'%Fs' : 'language modifier mismatch: '%Fs' to '%Fs'"
+2758 "'%Fs' : must be initialized in constructor base/member initializer list"
+
+2800 "'operator %Fs' cannot be overloaded"
+2801 "'operator %Fs' must be a%Fs member"
+2802 "static member 'operator %Fs' has no formal parameters"
+2803 "'operator %Fs' must have at least one formal parameter of class type"
+2804 "binary 'operator %Fs' has too many parameters"
+2805 "binary 'operator %Fs' has too few parameters"
+2806 "'operator %Fs' has too many formal parameters"
+2807 "the second formal parameter to postfix 'operator %Fs' must be 'int'"
+2808 "unary 'operator %Fs' has too many formal parameters"
+2809 "'operator %Fs' has no formal parameters"
+2810 "second formal parameter for 'operator delete' must be 'unsigned int'"
+2811 "too many formal parameters for based form of 'operator delete'"
+2812 "second formal parameter required for based form of 'operator delete'"
+2813 "too many formal parameters for non-based 'operator delete'"
+2814 "second actual parameter for based form of 'operator delete' must be '__based(void)*'"
+2815 "first actual parameter for based form of 'operator delete' must be '__segment'"
+2816 "alternative form of 'operator delete' must be a member"
+2817 "return type for 'operator delete' must be 'void'"
+2818 "incorrect return type for 'operator ->'"
+2819 "recursive return type for 'operator ->'"
+2820 "second formal parameter required for based form of 'operator new'"
+2821 "first formal parameter to 'operator new' must be 'unsigned int'"
+2822 "second formal parameter for __huge form of 'operator new' must be 'unsigned int'"
+2823 "return type for based form of 'operator new' must be 'void __based(void)*'"
+2824 "return type for 'operator new' must be 'void *'"
+2825 "first formal parameter for huge form of 'operator new' must be 'unsigned long'"
+2826 "second formal parameter required for __huge form of 'operator new'"
+2827 "'operator %s' cannot be globally overridden with unary form"
+2828 "'operator %s' cannot be globally overridden with binary form"
+2829 "'operator %Fs' cannot have a variable parameter list"
+2830 "only placement parameters to 'operator new' can have default values"
+2831 "'operator %Fs' may not have default parameters"
+
+2833 "'operator %Fs' is not a recognized operator or type"
+2834 "'operator %Fs' must be globally qualified"
+2835 "user-defined conversion '%Fs' takes no formal parameters"
+2836 "cannot export '%Fs': a previous declaration did not export it"
+2837 "'%Fs' : illegal local static variable in exported inline function"
+2838 "illegal qualified name in member declaration"
+
+2850 "#pragma hdrstop cannot be nested in a function or definition"
+2851 "#pragma hdrstop required for /Yu command-line option without filename"
+2852 "'%Fs' is not a valid precompiled header file"
+2853 "'%Fs' is not a precompiled header file created with this compiler"
+2854 "syntax error in #pragma hdrstop"
+2855 "command-line option '%Fs' inconsistant with precompiled header"
+2856 "#pragma hdrstop cannot be inside an #if block"
+2857 "'#include' statement specified with the /Yc%Fs command-line option was not found in the source file"
+
+2000 "UNKNOWN ERROR\n\t\tContact Microsoft Product Support Services"
+
+
+
+1001 "INTERNAL COMPILER ERROR\n\t\t(compiler file '%s', line %d)\n\t\tContact Microsoft Product Support Services"
+
+1003 "error count exceeds %d; stopping compilation"
+1004 "unexpected end of file found"
+1005 "string too big for buffer"
+1006 "write error on compiler-generated file"
+1007 "unrecognized flag '%Fs' in '%Fs'"
+1008 "no input file specified"
+1009 "compiler limit : macros nested too deeply"
+1010 "unexpected end of file while looking for precompiled header directive"
+1011 "compiler limit : '%Fs' : macro definition too big"
+1012 "unmatched parenthesis : missing '%c'"
+1013 "compiler limit : too many open parentheses"
+1014 "too many include files : depth = %d"
+1015 "compiler limit : too many segments"
+1016 "#if[n]def expected an identifier"
+1017 "invalid integer constant expression"
+1018 "unexpected #elif"
+1019 "unexpected #else"
+1020 "unexpected #endif"
+1021 "invalid preprocessor command '%Fs'"
+1022 "expected #endif"
+1023 "cannot open source file '%Fs'"
+1024 "cannot open include file '%Fs'"
+1025 "compiler terminated by user"
+1026 "parser stack overflow, program too complex"
+1027 "DGROUP data allocation exceeds 64K"
+1028 "'%s' : segment allocation exceeds 64K"
+1029 "there are > 512 bytes of arguments"
+1030 "there are > 512 bytes of local variables"
+1031 "compiler limit : function calls nested too deeply"
+1032 "cannot open object code listing file '%s'"
+
+1035 "expression too complex; simplify expression"
+
+1037 "cannot open object file '%s'"
+1038 "compiler limit : '%Fs' : control flow state too complex; simplify function"
+
+1041 "cannot open compiler intermediate file - no more files"
+1042 "cannot open compiler intermediate file - no such file or directory"
+1043 "cannot open compiler intermediate file"
+1044 "out of disk space for compiler intermediate file"
+1045 "compiler limit : linkage specifications nested too deeply"
+1046 "compiler limit : %Fs nested too deeply"
+1047 "limit of %Fs exceeded at '%Fs'"
+1048 "unknown option '%c' in '%s'"
+1049 "invalid numerical argument '%s'"
+1050 "'%s' : code segment too large"
+
+1052 "compiler limit : #if or #ifdef blocks nested too deeply"
+1053 "compiler limit : struct/union nested too deeply"
+1054 "compiler limit : initializers nested too deeply"
+1055 "compiler limit : out of keys"
+1056 "compiler limit : out of macro expansion space"
+1057 "unexpected end of file in macro expansion"
+1058 "compiler limit : too many formal arguments"
+1059 "compiler is out of near heap space"
+1060 "compiler is out of far heap space"
+1061 "compiler limit : blocks nested too deeply"
+1062 "error while writing to preprocessor output file"
+1063 "compiler limit : compiler stack overflow"
+1064 "compiler limit : token overflowed internal buffer"
+1065 "compiler limit : out of tags"
+1066 "compiler limit : decorated name length exceeded"
+
+1068 "cannot open file '%Fs'"
+1069 "write error on file '%s'"
+1070 "mismatched #if/#endif pair in file '%Fs'"
+1071 "unexpected end of file found in comment"
+1072 "'%Fs' : cannot read file"
+
+1090 "data allocation exceeds 64K"
+
+1126 "'%Fs' : automatic allocation exceeds %s"
+1127 "'%Fs' : segment redefinition"
+
+1500 "'%Fs' : cannot open inline function definition file"
+1501 "compiler limit : too many temporary variables"
+1502 "inline member-function definition missing '}'"
+1503 "default parameter definition missing ',' or ')'"
+1504 "type still ambiguous after parsing %d tokens"
+1505 "unrecoverable parser lookahead error"
+1506 "unrecoverable block scoping error"
+1507 "previous user errors and subsequent error recovery halt further compilation"
+
+1852 "'%Fs' is not a valid precompiled header file (C2852)"
+1853 "'%Fs' is not a precompiled header file created with this compiler (C2853)"
+1855 "command-line option '%Fs' inconsistent with precompiled header (C2855)"
+
+1000 "UNKNOWN FATAL ERROR\n\t\tContact Microsoft Product Support Services"
diff --git a/private/ole32/olethunk/ole16/tools/c23.err b/private/ole32/olethunk/ole16/tools/c23.err
new file mode 100644
index 000000000..1797efc7e
--- /dev/null
+++ b/private/ole32/olethunk/ole16/tools/c23.err
@@ -0,0 +1,95 @@
+
+
+
+1001 "INTERNAL COMPILER ERROR\n\t\t(compiler file '%s', line %d)\n\t\tContact Microsoft Product Support Services"
+1002 "compiler is out of heap space in pass 2"
+1003 "error count exceeds %d; stopping compilation"
+1004 "unexpected end of file found"
+1005 "string too big for buffer"
+1006 "write error on compiler intermediate file"
+1007 "unrecognized flag '%s' in '%s'"
+1015 "compiler limit : too many segments"
+1023 "cannot open source file '%s'"
+1027 "DGROUP data allocation exceeds 64K"
+1029 "there are > 512 bytes of arguments"
+1030 "there are > 512 bytes of local variables"
+1032 "cannot open object code listing file '%s'"
+1033 "cannot open assembly language output file '%s'"
+1035 "expression too complex; simplify expression"
+1036 "cannot open source listing file '%s'"
+1037 "cannot open object file '%s'"
+1039 "unrecoverable heap overflow in pass 3"
+1040 "unexpected end-of-file condition in source file '%s'"
+1041 "cannot open compiler intermediate file - no more files"
+1042 "cannot open compiler intermediate file - no such file or directory"
+1043 "cannot open compiler intermediate file"
+1044 "out of disk space for compiler intermediate file"
+1048 "unknown option '%c' in '%s'"
+1049 "invalid numerical argument '%s'"
+1050 "'%s' : code segment too large"
+
+1055 "compiler limit : out of keys"
+1067 "intrinsic not implemented"
+1073 "bad '%s' flag, would overwrite '%s' with '%s'"
+1074 "too many '%s' flags, '%s'"
+
+1090 "'%s' data allocation exceeds 64K"
+1126 "'%s' : automatic allocation exceeds %s"
+1127 "'%s' : segment redefinition"
+1000 "UNKNOWN FATAL ERROR\n\t\tContact Microsoft Product Support Services"
+
+
+
+2125 "'%s' : allocation exceeds 64K"
+2127 "parameter allocation exceeds 32K"
+2128 "'%s' : huge array cannot be aligned to segment boundary"
+2129 "static function '%s' not found"
+2220 "warning treated as error - no object file generated"
+2418 "'%s' : not in a register"
+2427 "'%s' : jump referencing label is out of range"
+2000 "UNKNOWN ERROR\n\t\tContact Microsoft Product Support Services"
+
+
+
+4700 "local variable '%s' used without having been initialized"
+4701 "local variable '%s' may be used without having been initialized"
+4702 "unreachable code"
+4703 "'%s' : function too large for global optimizations"
+4704 "'%s' : inline assembler precludes global optimizations"
+4705 "statement has no effect"
+4706 "assignment within conditional expression"
+4707 "'%s' : function too large for global optimizations (%s)"
+4708 "ran out of heap at: %s"
+4709 "comma operator within array index expression"
+4710 "function '%s' not expanded"
+4711 "function '%s' selected for inline expansion"
+4712 "'%s' : used as register - loss of debugging information"
+4713 "%s: INTERNAL COMPILER ERROR; restarting\n\t\t(compiler file '%s', line %d)\n\t\tContact Microsoft Product Support Services"
+4723 "potential divide by 0"
+4724 "potential mod by 0"
+4726 "'%c' : unknown memory-model command-line option"
+4727 "conditional expression is constant"
+4741 "/Oq option ignored for __fastcall or __saveregs function '%Fs'"
+4746 "'%s' : unsized array treated as '%s'"
+4756 "overflow in constant arithmetic"
+4758 "address of automatic (local) variable taken; DS != SS"
+4759 "segment lost in conversion"
+4761 "integral size mismatch in argument; conversion supplied"
+4762 "near/far mismatch in argument; conversion supplied"
+4763 "'%s' : function too large for postoptimizer"
+4765 "recoverable heap overflow in postoptimizer"
+4766 "local symbol-table overflow"
+4769 "conversion of near pointer to long integer"
+4772 "'%s' : too many debug entry points, maximum %d"
+4773 "scoping too deep; symbolic debugging information lost for this module."
+4785 "near call to '%s' in different segment"
+4786 "string too long - truncated to %d characters"
+4787 "unprototyped function '%s' called in exception"
+4788 "'%Fs' : identifier was truncated to '%d' characters"
+4790 "insufficient memory to process debugging information"
+4791 "loss of debugging information caused by optimization"
+4792 "long double type not supported by alternate math library"
+
+4900 "Il mismatch between '%s' version '%ld' and '%s' version '%ld'"
+
+4000 "UNKNOWN WARNING\n\t\tContact Microsoft Product Support Services"
diff --git a/private/ole32/olethunk/ole16/tools/cl.def b/private/ole32/olethunk/ole16/tools/cl.def
new file mode 100644
index 000000000..6b7b1fc8c
--- /dev/null
+++ b/private/ole32/olethunk/ole16/tools/cl.def
@@ -0,0 +1,62 @@
+;
+; CL.DEF - Default .def file for C Windows applications
+;
+; Copyright (C) Microsoft Corp 1991. All rights reserved.
+;
+
+NAME WINDOWAPI
+
+;
+; The NAME statement tells the linker that a Windows application is being
+; built. The linker supplies the actual name of the application from the
+; base name of the executable file.
+;
+
+EXETYPE WINDOWS 3.0
+
+;
+; The EXETYPE statement tells the linker to build a Windows 3.0 executable
+; file. This statement should be used in all applications built with
+; C 7.0 for Windows 3.0.
+;
+
+PROTMODE
+
+;
+; The PROTMODE statement tells the linker to mark the application for execution
+; in Windows standard or enhanced mode.
+;
+
+CODE PRELOAD MOVEABLE DISCARDABLE
+DATA PRELOAD MOVEABLE
+
+;
+; The CODE and DATA statements set the attributes of the applications CODE and
+; DATA segments.
+;
+
+HEAPSIZE 1024
+STACKSIZE 8096
+
+;
+; The HEAPSIZE and STACKSIZE statements set the applications near heap and
+; stack sizes. The values specified are recomended for QuickWin applications.
+;
+
+;
+; Uncomment these lines for DLL module definition file model.
+;
+;EXPORTS
+; WEP @1 RESIDENTNAME
+;
+;SEGMENTS 'WEP_TEXT' FIXED PRELOAD
+;
+;
+; The above section should be uncommented if this .DEF file is to be used as
+; a model for a C 7.0 dynamic-link library (DLL) .DEF file. The WEP
+; routine is included in the C 7.0 startup code, but the symbol must
+; be explicitly exported. If a DLL already has a user-defined WEP routine,
+; the routine should be renamed _WEP. The startup code will call _WEP,
+; if present, during DLL termination. For additional information concerning
+; the WEP function, see the C 7.0 and Windows 3.0 SDK documentation.
+;
diff --git a/private/ole32/olethunk/ole16/tools/cl.err b/private/ole32/olethunk/ole16/tools/cl.err
new file mode 100644
index 000000000..3d828316a
--- /dev/null
+++ b/private/ole32/olethunk/ole16/tools/cl.err
@@ -0,0 +1,41 @@
+ /* error messages */
+
+2001 "too many symbols predefined with /D"
+2002 "memory-model conflict"
+2003 "missing source filename"
+2008 "limit of %s exceeded at '%s'"
+2011 "only one floating-point option allowed"
+2012 "too many linker arguments"
+2013 "incomplete model specification"
+2016 "%s and %s command-line options are incompatible"
+2018 "cannot create linker response file"
+2019 "cannot overwrite source or object file '%s'"
+2020 "%s option requires extended keywords to be enabled (/Ze)"
+2021 "invalid numeric argument '%s'"
+2022 "cannot open '%s'"
+2023 "invalid model specification - flat model only"
+2027 "cannot execute '%s'"
+2028 "too many open files; cannot redirect '%s'"
+2030 "INTERNAL COMPILER ERROR in '%s'\n\t\tContact Microsoft Product Support Services"
+2031 "too many command-line options"
+2000 "UNKNOWN COMMAND-LINE ERROR\n\t\tContact Microsoft Product Support Services"
+
+ /* warning messages */
+
+4001 "listing overrides assembly output"
+4002 "ignoring unknown option '%s'"
+4003 "processor-option conflict"
+4005 "cannot find '%s';\nPlease enter new filename (full path) or CTRL+C to quit: "
+4007 "'%s' requires '%s'; option ignored"
+4009 "threshold only for far or huge data; ignored"
+4011 "preprocessing overrides source listing"
+4012 "function declarations override source listing"
+4013 "combined listing overrides object listing"
+4014 "invalid value '%d' for '%s'; assuming '%d'"
+4018 ".DEF files supported for segmented executable files only"
+4019 "string too long; truncated to %d characters"
+4020 "'%s' : missing argument; option ignored"
+4021 "no action performed"
+4022 "option '%s' invalid for %d-bit target"
+4023 "option '%s' forces use of optimizing compiler"
+4000 "UNKNOWN COMMAND-LINE WARNING\n\t\tContact Microsoft Product Support Services"
diff --git a/private/ole32/olethunk/ole16/tools/cl.msg b/private/ole32/olethunk/ole16/tools/cl.msg
new file mode 100644
index 000000000..db6e641ee
--- /dev/null
+++ b/private/ole32/olethunk/ole16/tools/cl.msg
@@ -0,0 +1,126 @@
+C COMPILER OPTIONS
+-MEMORY MODEL-
+/AS small model (default)
+/AC compact model
+/AM medium model
+/AL large model
+/AH huge model
+/AT tiny model (.COM files)
+/A<string> (custom memory model)
+-OPTIMIZATION-
+/O enable optimization (same as /Ot)
+/Oa assume no aliasing
+/Ob<n> inline expansion
+/Oc local common subexpression opt.
+/Od disable optimization (default)
+/Oe enable registers allocation
+/Of[-] toggle p-code quoting
+/Og global common subexpression opt.
+/Oi enable intrinsic functions
+/Ol enable loop optimizations
+/On disable "unsafe" optimizations
+/Oo[-] toggle post code-gen. opt.
+/Op[-] improve floating-pt consistency
+/Oq enable maximum p-code optimization
+/Or gen. common exit code (CodeView)
+/Os optimize for space
+/Ot optimize for speed
+/Ov[-] toggle p-code frame sorting
+/Ow assume cross-function aliasing
+/Ox maximum opts. (/Ob1cegilnot /Gs)
+/Oz enable "unsafe" optimizations
+-CODE GENERATION-
+/G0 8086 instructions (default)
+/G1 186 instructions
+/G2 286 instructions
+/GA protected-mode Win entry/exit code
+/GD protected-mode Win entry/exit code
+/GE<x> customize Windows entry/exit
+/Gq backwards compatibility with v. 6
+/Gc Pascal style calling conventions
+/Gd C style calling conventions
+/Ge use stack-check calls
+/Gs remove stack-check calls
+/Gn remove p-code native entry points
+/Gp<num> specify p-code entry tables
+/Gr _fastcall style calling convention
+/Gt[num] data size threshold
+/GW real-mode Windows entry/exit code
+/Gw real-mode Windows entry/exit code
+/Gx assume that data is near
+/Gy separate functions for linker
+/Zr check null pointers (/f only)
+-OUTPUT FILES-
+/Fa[file] name assembly listing file
+/Fc[file] name source/object listing
+/Fe<file> name executable filename
+/Fl[file] name object listing filename
+/Fm[file] name map filename
+/Fo<file> name object filename
+/Fr[file] name .SBR filename
+/Fp<file> name .PCH filename
+/FR[file] name extended .SBR filename
+/Fs[file] name source listing filename
+-PREPROCESSOR-
+/C don't strip comments
+/D<name>[=|#text] define macro
+/E preprocess to stdout
+/EP same as /E but no #line
+/I<directory> add #include path
+/P preprocess to file
+/U<name> remove predefined macro
+/u remove all defined macros
+/X ignore "standard places"
+-LANGUAGE-
+/Za disable extensions (implies /Op)
+/Zd line number information
+/Ze enable extensions (default)
+/Zg generate function prototypes
+/Zi prepare for debugging (CodeView)
+/Zl omit default library name in .OBJ
+/Zp[n] pack structs on n-byte boundary
+/Zs check syntax only
+-FLOATING POINT-
+/FPa calls with altmath
+/FPc calls with emulator
+/FPc87 calls with 8087 library
+/FPi inline with emulator (default)
+/FPi87 inline with 8087
+-SOURCE LISTING-
+/Sl<columns> set line width
+/Sp<lines> set page length
+/St<string> set title string
+/Ss<string> set subtitle string
+-MISCELLANEOUS-
+/batch specify batch mode compilation
+/Bm<num> set compiler's available mem.
+/c compile only, no link
+/H<num> external name length
+/J default char type is unsigned
+/f select fast compiler
+/f- select optimizing compiler
+/Yc create .PCH file
+/Yd put debug info in .PCH file
+/Yu use .PCH file
+/nologo suppress copyright message
+/Mq compile for QuickWin
+/ND<name> name data segment
+/NM<name> name code segment
+/NQ<name> combine p-code temp segments
+/NT<name> name code segment
+/NV<name> name far v-table segment
+/Tc<file> compile file without .c
+/Tp<file> compile file without .cpp
+/V<string> set version string
+/W<num> warning level (0..4,X)
+/Zn turn off SBRPACK for .SBR files
+-MASM SUPPORT-
+/MA<MASM switch>
+/Ta<file> assemble file without .asm
+-LINKING-
+/F <hex_num> stack size (hex. bytes)
+/Lr append 'r' to default lib in .OBJ
+/link [lib] give lib name to linker
+/Ln do not link CRT.LIB
+/Ld select dynamically-linked library
+/Lw select statically-linked library
diff --git a/private/ole32/olethunk/ole16/tools/interop.reg b/private/ole32/olethunk/ole16/tools/interop.reg
new file mode 100644
index 000000000..4a269569e
--- /dev/null
+++ b/private/ole32/olethunk/ole16/tools/interop.reg
@@ -0,0 +1,118 @@
+REGEDIT
+
+HKEY_CLASSES_ROOT\CLSID\{00000300-0000-0000-C000-000000000046} = StdOleLink
+HKEY_CLASSES_ROOT\CLSID\{00000300-0000-0000-C000-000000000046}\InprocServer = ole2.dll
+HKEY_CLASSES_ROOT\CLSID\{00000301-0000-0000-C000-000000000046} = StdMemStm
+HKEY_CLASSES_ROOT\CLSID\{00000301-0000-0000-C000-000000000046}\InprocServer = ole2.dll
+HKEY_CLASSES_ROOT\CLSID\{00000302-0000-0000-C000-000000000046} = StdMemBytes
+HKEY_CLASSES_ROOT\CLSID\{00000302-0000-0000-C000-000000000046}\InprocServer = ole2.dll
+HKEY_CLASSES_ROOT\CLSID\{00000303-0000-0000-C000-000000000046} = FileMoniker
+HKEY_CLASSES_ROOT\CLSID\{00000303-0000-0000-C000-000000000046}\InprocServer = ole2.dll
+HKEY_CLASSES_ROOT\CLSID\{00000304-0000-0000-C000-000000000046} = ItemMoniker
+HKEY_CLASSES_ROOT\CLSID\{00000304-0000-0000-C000-000000000046}\InprocServer = ole2.dll
+HKEY_CLASSES_ROOT\CLSID\{00000305-0000-0000-C000-000000000046} = AntiMoniker
+HKEY_CLASSES_ROOT\CLSID\{00000305-0000-0000-C000-000000000046}\InprocServer = ole2.dll
+HKEY_CLASSES_ROOT\CLSID\{00000306-0000-0000-C000-000000000046} = PointerMoniker
+HKEY_CLASSES_ROOT\CLSID\{00000306-0000-0000-C000-000000000046}\InprocServer = ole2.dll
+HKEY_CLASSES_ROOT\CLSID\{00000308-0000-0000-C000-000000000046} = PackagerMoniker
+HKEY_CLASSES_ROOT\CLSID\{00000308-0000-0000-C000-000000000046}\InprocServer = ole2.dll
+HKEY_CLASSES_ROOT\CLSID\{00000309-0000-0000-C000-000000000046} = CompositeMoniker
+HKEY_CLASSES_ROOT\CLSID\{00000309-0000-0000-C000-000000000046}\InprocServer = ole2.dll
+HKEY_CLASSES_ROOT\CLSID\{0000030A-0000-0000-C000-000000000046} = DdeCompositeMoniker
+HKEY_CLASSES_ROOT\CLSID\{0000030A-0000-0000-C000-000000000046}\InprocServer = ole2.dll
+HKEY_CLASSES_ROOT\CLSID\{0000030B-0000-0000-C000-000000000046} = DfMarshal
+HKEY_CLASSES_ROOT\CLSID\{0000030B-0000-0000-C000-000000000046}\InprocServer = storage.dll
+HKEY_CLASSES_ROOT\CLSID\{0000030C-0000-0000-C000-000000000046} = PSGenObject
+HKEY_CLASSES_ROOT\CLSID\{0000030C-0000-0000-C000-000000000046}\InprocServer = ole2prox.dll
+HKEY_CLASSES_ROOT\CLSID\{0000030D-0000-0000-C000-000000000046} = PSClientSite
+HKEY_CLASSES_ROOT\CLSID\{0000030D-0000-0000-C000-000000000046}\InprocServer = ole2prox.dll
+HKEY_CLASSES_ROOT\CLSID\{0000030E-0000-0000-C000-000000000046} = PSClassObject
+HKEY_CLASSES_ROOT\CLSID\{0000030E-0000-0000-C000-000000000046}\InprocServer = ole2prox.dll
+HKEY_CLASSES_ROOT\CLSID\{0000030F-0000-0000-C000-000000000046} = PSInPlaceActive
+HKEY_CLASSES_ROOT\CLSID\{0000030F-0000-0000-C000-000000000046}\InprocServer = ole2prox.dll
+HKEY_CLASSES_ROOT\CLSID\{00000310-0000-0000-C000-000000000046} = PSInPlaceFrame
+HKEY_CLASSES_ROOT\CLSID\{00000310-0000-0000-C000-000000000046}\InprocServer = ole2prox.dll
+HKEY_CLASSES_ROOT\CLSID\{00000311-0000-0000-C000-000000000046} = PSDragDrop
+HKEY_CLASSES_ROOT\CLSID\{00000311-0000-0000-C000-000000000046}\InprocServer = ole2prox.dll
+HKEY_CLASSES_ROOT\CLSID\{00000312-0000-0000-C000-000000000046} = PSBindCtx
+HKEY_CLASSES_ROOT\CLSID\{00000312-0000-0000-C000-000000000046}\InprocServer = ole2prox.dll
+HKEY_CLASSES_ROOT\CLSID\{00000313-0000-0000-C000-000000000046} = PSEnumerators
+HKEY_CLASSES_ROOT\CLSID\{00000313-0000-0000-C000-000000000046}\InprocServer = ole2prox.dll
+HKEY_CLASSES_ROOT\CLSID\{00000314-0000-0000-C000-000000000046} = PSStore
+HKEY_CLASSES_ROOT\CLSID\{00000314-0000-0000-C000-000000000046}\InprocServer = ole2prox.dll
+HKEY_CLASSES_ROOT\CLSID\{00000315-0000-0000-C000-000000000046} = Metafile
+HKEY_CLASSES_ROOT\CLSID\{00000315-0000-0000-C000-000000000046}\InprocServer = ole2.dll
+HKEY_CLASSES_ROOT\CLSID\{00000316-0000-0000-C000-000000000046} = Device Independent Bitmap
+HKEY_CLASSES_ROOT\CLSID\{00000316-0000-0000-C000-000000000046}\InprocServer = ole2.dll
+HKEY_CLASSES_ROOT\Interface\{0000010e-0000-0000-C000-000000000046} = IDataObject
+HKEY_CLASSES_ROOT\Interface\{0000010e-0000-0000-C000-000000000046}\ProxyStubClsid = {0000030C-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000112-0000-0000-C000-000000000046} = IOleObject
+HKEY_CLASSES_ROOT\Interface\{00000112-0000-0000-C000-000000000046}\ProxyStubClsid = {0000030C-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000113-0000-0000-C000-000000000046} = IOleInPlaceObject
+HKEY_CLASSES_ROOT\Interface\{00000113-0000-0000-C000-000000000046}\ProxyStubClsid = {0000030C-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000011a-0000-0000-C000-000000000046} = IParseDisplayName
+HKEY_CLASSES_ROOT\Interface\{0000011a-0000-0000-C000-000000000046}\ProxyStubClsid = {0000030C-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000011b-0000-0000-C000-000000000046} = IOleContainer
+HKEY_CLASSES_ROOT\Interface\{0000011b-0000-0000-C000-000000000046}\ProxyStubClsid = {0000030C-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000011c-0000-0000-C000-000000000046} = IOleItemContainer
+HKEY_CLASSES_ROOT\Interface\{0000011c-0000-0000-C000-000000000046}\ProxyStubClsid = {0000030C-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000010c-0000-0000-C000-000000000046} = IPersist
+HKEY_CLASSES_ROOT\Interface\{0000010c-0000-0000-C000-000000000046}\ProxyStubClsid = {0000030C-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000010a-0000-0000-C000-000000000046} = IPersistStorage
+HKEY_CLASSES_ROOT\Interface\{0000010a-0000-0000-C000-000000000046}\ProxyStubClsid = {0000030C-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000010b-0000-0000-C000-000000000046} = IPersistFile
+HKEY_CLASSES_ROOT\Interface\{0000010b-0000-0000-C000-000000000046}\ProxyStubClsid = {0000030C-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000118-0000-0000-C000-000000000046} = IOleClientSite
+HKEY_CLASSES_ROOT\Interface\{00000118-0000-0000-C000-000000000046}\ProxyStubClsid = {0000030D-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000119-0000-0000-C000-000000000046} = IOleInPlaceSite
+HKEY_CLASSES_ROOT\Interface\{00000119-0000-0000-C000-000000000046}\ProxyStubClsid = {0000030D-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000010f-0000-0000-C000-000000000046} = IAdviseSink
+HKEY_CLASSES_ROOT\Interface\{0000010f-0000-0000-C000-000000000046}\ProxyStubClsid = {0000030D-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000001-0000-0000-C000-000000000046} = IClassFactory
+HKEY_CLASSES_ROOT\Interface\{00000001-0000-0000-C000-000000000046}\ProxyStubClsid = {0000030E-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000117-0000-0000-C000-000000000046} = IOleInPlaceActiveObject
+HKEY_CLASSES_ROOT\Interface\{00000117-0000-0000-C000-000000000046}\ProxyStubClsid = {0000030F-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000115-0000-0000-C000-000000000046} = IOleInPlaceUIWindow
+HKEY_CLASSES_ROOT\Interface\{00000115-0000-0000-C000-000000000046}\ProxyStubClsid = {00000310-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000116-0000-0000-C000-000000000046} = IOleInPlaceFrame
+HKEY_CLASSES_ROOT\Interface\{00000116-0000-0000-C000-000000000046}\ProxyStubClsid = {00000310-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000122-0000-0000-C000-000000000046} = IDropTarget
+HKEY_CLASSES_ROOT\Interface\{00000122-0000-0000-C000-000000000046}\ProxyStubClsid = {00000311-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000000e-0000-0000-C000-000000000046} = IBindCtx
+HKEY_CLASSES_ROOT\Interface\{0000000e-0000-0000-C000-000000000046}\ProxyStubClsid = {00000312-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000103-0000-0000-C000-000000000046} = IEnumFORMATETC
+HKEY_CLASSES_ROOT\Interface\{00000103-0000-0000-C000-000000000046}\ProxyStubClsid = {00000313-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000105-0000-0000-C000-000000000046} = IEnumSTATDATA
+HKEY_CLASSES_ROOT\Interface\{00000105-0000-0000-C000-000000000046}\ProxyStubClsid = {00000313-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00000104-0000-0000-C000-000000000046} = IEnumOLEVERB
+HKEY_CLASSES_ROOT\Interface\{00000104-0000-0000-C000-000000000046}\ProxyStubClsid = {00000313-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000000A-0000-0000-C000-000000000046} = ILockBytes
+HKEY_CLASSES_ROOT\Interface\{0000000A-0000-0000-C000-000000000046}\ProxyStubClsid = {00000314-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000000B-0000-0000-C000-000000000046} = IStorage
+HKEY_CLASSES_ROOT\Interface\{0000000B-0000-0000-C000-000000000046}\ProxyStubClsid = {00000314-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{0000000C-0000-0000-C000-000000000046} = IStream
+HKEY_CLASSES_ROOT\Interface\{0000000C-0000-0000-C000-000000000046}\ProxyStubClsid = {00000314-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00020400-0000-0000-C000-000000000046} = IDispatch
+HKEY_CLASSES_ROOT\Interface\{00020400-0000-0000-C000-000000000046}\ProxyStubClsid = {00020420-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00020404-0000-0000-C000-000000000046} = IEnumVARIANT
+HKEY_CLASSES_ROOT\Interface\{00020404-0000-0000-C000-000000000046}\ProxyStubClsid = {00020421-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00020401-0000-0000-C000-000000000046} = ITypeInfo
+HKEY_CLASSES_ROOT\Interface\{00020401-0000-0000-C000-000000000046}\ProxyStubClsid = {00020422-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00020402-0000-0000-C000-000000000046} = ITypeLib
+HKEY_CLASSES_ROOT\Interface\{00020402-0000-0000-C000-000000000046}\ProxyStubClsid = {00020423-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00020403-0000-0000-C000-000000000046} = ITypeComp
+HKEY_CLASSES_ROOT\Interface\{00020403-0000-0000-C000-000000000046}\ProxyStubClsid = {00020425-0000-0000-C000-000000000046}
+HKEY_CLASSES_ROOT\Interface\{00020405-0000-0000-C000-000000000046} = ICreateTypeInfo
+HKEY_CLASSES_ROOT\Interface\{00020406-0000-0000-C000-000000000046} = ICreateTypeLib
+HKEY_CLASSES_ROOT\CLSID\{00020420-0000-0000-C000-000000000046} = PSDispatch
+HKEY_CLASSES_ROOT\CLSID\{00020420-0000-0000-C000-000000000046}\InprocServer = ole2disp.dll
+HKEY_CLASSES_ROOT\CLSID\{00020422-0000-0000-C000-000000000046} = PSTypeInfo
+HKEY_CLASSES_ROOT\CLSID\{00020422-0000-0000-C000-000000000046}\InprocServer = ole2disp.dll
+HKEY_CLASSES_ROOT\CLSID\{00020421-0000-0000-C000-000000000046} = PSEnumVARIANT
+HKEY_CLASSES_ROOT\CLSID\{00020421-0000-0000-C000-000000000046}\InprocServer = ole2disp.dll
+HKEY_CLASSES_ROOT\CLSID\{00020423-0000-0000-C000-000000000046} = PSTypeLib
+HKEY_CLASSES_ROOT\CLSID\{00020423-0000-0000-C000-000000000046}\InprocServer = ole2disp.dll
+HKEY_CLASSES_ROOT\CLSID\{00020425-0000-0000-C000-000000000046} = PSTypeComp
+HKEY_CLASSES_ROOT\CLSID\{00020425-0000-0000-C000-000000000046}\InprocServer = ole2disp.dll
+HKEY_CLASSES_ROOT\CLSID\{00020424-0000-0000-C000-000000000046} = PSAutomation
+HKEY_CLASSES_ROOT\CLSID\{00020424-0000-0000-C000-000000000046}\InprocServer = ole2disp.dll
diff --git a/private/ole32/olethunk/ole16/tools/ole1632.bat b/private/ole32/olethunk/ole16/tools/ole1632.bat
new file mode 100644
index 000000000..78dfd73e0
--- /dev/null
+++ b/private/ole32/olethunk/ole16/tools/ole1632.bat
@@ -0,0 +1,93 @@
+@echo off
+
+rem
+rem This batch file was written by the Hammer to enable OLE's
+rem 16bit to/from 32bit interop support.
+rem
+
+set windir=C:\WINDOWS
+if %1n==n goto Usage
+set windir=%1
+goto Start
+
+:Usage
+
+echo ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+echo ³ Usage: OLE1632 win95dir
+echo ³ Example: OLE1632 C:\WINDOWS
+echo ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+
+goto Done
+
+:Start
+
+if exist ole1632.bat goto ThunkToggle
+
+echo Must run from the SDK\Samples\Ole\Interop directory.
+goto Done
+
+
+:ThunkToggle
+@echo This batch file will enable or disable OLE2 16:32 interop.
+CHOICE.COM /C:EDC "Enable, Disable or Cancel"
+if ERRORLEVEL 3 goto Done
+if ERRORLEVEL 2 goto ThunkOff
+
+:ThunkOn
+
+@del %windir%\system\compobj.dll
+if exist %windir%\system\compobj.dll goto Reboot
+del %windir%\system\storage.dll
+del %windir%\system\ole2.dll
+del %windir%\system\ole2prox.dll
+del %windir%\system\ole2disp.dll
+del %windir%\system\ole2nls.dll
+del %windir%\system\stdole.tlb
+del %windir%\system\typelib.dll
+
+copy compobj.dll %windir%\system
+copy storage.dll %windir%\system
+copy ole2.dll %windir%\system
+copy ole2prox.dll %windir%\system
+copy ole2disp.dll %windir%\system
+copy ole2nls.dll %windir%\system
+copy stdole.tlb %windir%\system
+copy typelib.dll %windir%\system
+
+@echo OLE 16:32 interop has been enabled.
+
+goto Done
+
+:ThunkOff
+
+@del %windir%\system\compobj.dll
+if exist %windir%\system\compobj.dll goto Reboot
+del %windir%\system\storage.dll
+del %windir%\system\ole2.dll
+del %windir%\system\ole2prox.dll
+del %windir%\system\ole2disp.dll
+del %windir%\system\ole2nls.dll
+del %windir%\system\stdole.tlb
+del %windir%\system\typelib.dll
+
+copy compobj.w16 %windir%\system\compobj.dll
+copy storage.w16 %windir%\system\storage.dll
+copy ole2.w16 %windir%\system\ole2.dll
+copy ole2disp.w16 %windir%\system\ole2disp.dll
+copy ole2prox.w16 %windir%\system\ole2prox.dll
+copy ole2nls.w16 %windir%\system\ole2nls.dll
+copy stdole.w16 %windir%\system\stdole.tlb
+copy typelib.w16 %windir%\system\typelib.dll
+
+start /w regedit /s interop.reg
+
+echo OLE 16/32 interop has been disabled.
+
+goto Done
+
+
+:Reboot
+echo The 16bit OLE DLL's are busy, please reboot and run OLE1632 again.
+
+
+:Done
diff --git a/private/ole32/olethunk/ole16/tools/rcqq.err b/private/ole32/olethunk/ole16/tools/rcqq.err
new file mode 100644
index 000000000..d26c8494d
--- /dev/null
+++ b/private/ole32/olethunk/ole16/tools/rcqq.err
@@ -0,0 +1,334 @@
+/* SCCSWHAT( "@(#)c1.err 2.29 88/02/25 18:18:00 " ) */
+ /* fatals */
+
+1001 "Internal Compiler Error\n\t\t(compiler file '%s', line %d)\n\t\tContact Microsoft Technical Support"
+1002 "out of heap space"
+1003 "error count exceeds %d; stopping compilation"
+1004 "unexpected EOF"
+1005 "string too big for buffer"
+1006 "write error on compiler intermediate file"
+1007 "unrecognized flag '%s' in '%s'"
+1008 "no input file specified"
+1009 "compiler limit : macros too deeply nested"
+1010 "compiler limit : macro expansion too big"
+1012 "bad parenthesis nesting - missing '%c'"
+1013 "cannot open source file '%s'"
+1014 "too many include files"
+1015 "cannot open include file '%s'"
+1016 "#if[n]def expected an identifier"
+1017 "invalid integer constant expression"
+1018 "unexpected '#elif'"
+1019 "unexpected '#else'"
+1020 "unexpected '#endif'"
+1021 "bad preprocessor command '%s'"
+1022 "expected '#endif'"
+1023 "no int size specified"
+1024 "no ptr size specified"
+1025 "no function size specified"
+1026 "parser stack overflow, please simplify your program"
+1027 "DGROUP data allocation exceeds 64K" /* QC, c23 */
+1028 "%s segment allocation exceeds 64K" /* QC */
+1031 "compiler limit : function calls too deeply nested" /* QC, c23 */
+1032 "cannot open object listing file '%s'" /* QC, c23 */
+1035 "expression too complex, please simplify" /* QC, c23 */
+1037 "cannot open object file '%s'" /* QC, c23 */
+1041 "cannot open compiler intermediate file - no more files"
+1042 "cannot open compiler intermediate file - no such file or directory"
+1043 "cannot open compiler intermediate file"
+1044 "out of disk space for compiler intermediate file"
+1045 "floating point overflow"
+1047 "too many %s flags, '%s'"
+1048 "unknown option '%c' in '%s'"
+1049 "invalid numerical argument '%s'"
+1052 "too many #if/#ifdef's"
+1053 "compiler limit : struct/union nesting"
+1054 "compiler limit : initializers too deeply nested"
+1055 "compiler limit : out of keys"
+1056 "compiler limit : out of macro expansion space"
+1057 "unexpected EOF in macro expansion (missing ')'?)"
+1059 "out of near heap space"
+1060 "out of far heap space"
+1061 "compiler limit : blocks too deeply nested" /* QC */
+1062 "error writing to preprocessor output file"
+1063 "compiler limit : compiler stack overflow" /* QC */
+1064 "compiler limit : identifier overflowed internal buffer"
+1065 "compiler limit : declarator too complex"
+1000 "UNKNOWN FATAL ERROR\n\t\tContact Microsoft Technical Support"
+
+ /* errors */
+
+2001 "newline in constant"
+2002 "out of macro actual parameter space"
+2003 "expected 'defined id'"
+2004 "expected 'defined(id)'"
+2005 "#line expected a line number, found '%s'"
+2006 "#include expected a file name, found '%s'"
+2007 "#define syntax"
+2008 "'%c' : unexpected in macro definition"
+2009 "reuse of macro formal '%s'"
+2010 "'%c' : unexpected in formal list"
+2011 "'%s' : definition too big"
+2012 "missing name following '<'"
+2013 "missing '>'"
+2014 "preprocessor command must start as first non-whitespace"
+2015 "too many chars in constant"
+2016 "no closing single quote"
+2017 "illegal escape sequence"
+2018 "unknown character '0x%x'"
+2019 "expected preprocessor command, found '%c'"
+2020 "bad octal number '%c'"
+2021 "expected exponent value, not '%c'"
+2022 "'%ld' : too big for char"
+2023 "divide by 0"
+2024 "mod by 0"
+2025 "'%s' : enum/struct/union type redefinition"
+2026 "'%s' : member of enum redefinition"
+2028 "struct/union member needs to be inside a struct/union"
+2029 "'%Fs' : bit-fields only allowed in structs"
+2030 "'%Fs' : struct/union member redefinition"
+2031 "'%Fs' : function cannot be struct/union member"
+2032 "'%Fs' : base type with near/far/huge not allowed"
+2033 "'%Fs' : bit-field cannot have indirection"
+2034 "'%Fs' : bit-field type too small for number of bits"
+2035 "enum/struct/union '%Fs' : unknown size"
+2036 "left of '%s%s' must have a struct/union type"
+2037 "left of '%s' specifies undefined struct/union '%Fs'"
+2038 "'%s' : not struct/union member"
+2039 "'->' requires struct/union pointer"
+2040 "'.' requires struct/union name"
+2042 "signed/unsigned keywords mutually exclusive"
+2043 "illegal break"
+2044 "illegal continue"
+2045 "'%s' : label redefined"
+2046 "illegal case"
+2047 "illegal default"
+2048 "more than one default"
+2050 "non-integral switch expression"
+2051 "case expression not constant"
+2052 "case expression not integral"
+2053 "case value %d already used"
+2054 "expected '(' to follow '%Fs'"
+2055 "expected formal parameter list, not a type list"
+2056 "illegal expression"
+2057 "expected constant expression"
+2058 "constant expression is not integral"
+2059 "syntax error : '%s'"
+2060 "syntax error : EOF"
+2061 "syntax error : identifier '%s'"
+2062 "type '%s' unexpected"
+2063 "'%s' : not a function"
+2064 "term does not evaluate to a function"
+2065 "'%s' : undefined"
+2066 "cast to function returning . . . is illegal"
+2067 "cast to array type is illegal"
+2068 "illegal cast"
+2069 "cast of 'void' term to non-void"
+2070 "illegal sizeof operand"
+2071 "'%Fs' : bad storage class"
+2072 "'%Fs' : initialization of a function"
+2073 "'%Fs' : cannot initialize array in function"
+2074 "'%Fs' : cannot initialize struct/union in function"
+2075 "'%Fs' : array initialization needs curly braces"
+2076 "'%Fs' : struct/union initialization needs curly braces"
+2077 "non-integral field initializer '%Fs'"
+2078 "too many initializers"
+2079 "'%Fs' uses undefined struct/union '%Fs'"
+2082 "redefinition of formal parameter '%Fs'"
+2083 "array '%Fs' already has a size"
+2084 "function '%Fs' already has a body"
+2085 "'%Fs' : not in formal parameter list"
+2086 "'%Fs' : redefinition"
+2087 "'%Fs' : missing subscript"
+2088 "use of undefined enum/struct/union '%s'"
+2089 "typedef specifies a near/far function"
+2090 "function returns array"
+2091 "function returns function"
+2092 "array element type cannot be function"
+2093 "cannot initialize a static or struct with address of automatic vars"
+2094 "label '%Fs' was undefined"
+2095 "'%Fs' : actual has type void : parameter %d"
+2096 "struct/union comparison illegal"
+2097 "illegal initialization"
+2098 "non-address expression"
+2099 "non-constant offset"
+2100 "illegal indirection"
+2101 "'&' on constant"
+2102 "'&' requires lvalue"
+2103 "'&' on register variable"
+2104 "'&' on bit-field ignored"
+2105 "'%s' needs lvalue"
+2106 "'%s' : left operand must be lvalue"
+2107 "illegal index, indirection not allowed"
+2108 "non-integral index"
+2109 "subscript on non-array"
+2110 "'+' : 2 pointers"
+2111 "pointer + non-integral value"
+2112 "illegal pointer subtraction"
+2113 "'-' : right operand pointer"
+2114 "'%s' : pointer on left; needs integral right"
+2115 "'%s' : incompatible types"
+2116 "'%s' : bad %s operand"
+2117 "'%s' : illegal for struct/union"
+2118 "negative subscript"
+2119 "'typedefs' both define indirection"
+2120 "'void' illegal with all types"
+2121 "typedef specifies different enum"
+2122 "typedef specifies different struct"
+2123 "typedef specifies different union"
+2125 "%Fs : allocation exceeds 64K" /* QC, c23 */
+2126 "%Fs : auto allocation exceeds %s" /* QC, c23 */
+2127 "parameter allocation exceeds 32K" /* QC, c23 */
+2130 "#line expected a string containing the file name, found '%s'"
+2131 "attributes specify more than one near/far/huge"
+2132 "syntax error : unexpected identifier"
+2133 "array '%Fs' : unknown size"
+2134 "'%Fs' : struct/union too large"
+2135 "missing ')' in macro expansion"
+2137 "empty character constant"
+2138 "unmatched close comment '*/'"
+2139 "type following '%s' is illegal"
+2140 "argument type cannot be function returning . . ."
+2141 "value out of range for enum constant"
+2142 "ellipsis requires three periods"
+2143 "syntax error : missing '%s' before '%s'"
+2144 "syntax error : missing '%s' before type '%Fs'"
+2145 "syntax error : missing '%s' before identifier"
+2146 "syntax error : missing '%s' before identifier '%s'"
+2147 "unknown size"
+2148 "array too large"
+2149 "'%Fs' : named bit-field cannot have 0 width"
+2150 "'%Fs' : bit-field must have type int, signed int, or unsigned int"
+2151 "more than one cdecl/fortran/pascal attribute specified"
+2152 "'%s' : pointers to functions with different attributes"
+2153 "hex constants must have at least 1 hex digit"
+2154 "'%s' : does not refer to a segment"
+2155 "'%s' : already in a segment"
+2156 "pragma must be at outer level"
+2157 "'%s' : must be declared before use in pragma list"
+2158 "'%s' : is a function"
+2159 "more than one storage class specified"
+2160 "## cannot occur at the beginning of a macro definition"
+2161 "## cannot occur at the end of a macro definition"
+2162 "expected macro formal parameter"
+2163 "'%s' : not available as an intrinsic"
+2164 "'%s' : intrinsic was not declared"
+2165 "'%s' : cannot modify pointers to data"
+2166 "lval specifies 'const' object"
+2167 "'%Fs' : too many actual parameters for intrinsic"
+2168 "'%Fs' : too few actual parameters for intrinsic"
+2169 "'%Fs' : is an intrinsic, it cannot be defined"
+2170 "'%s' : intrinsic not declared as a function"
+2171 "'%s' : bad operand"
+2172 "'%Fs' : actual is not a pointer : parameter %d"
+2173 "'%Fs' : actual is not a pointer : parameter %d, parameter list %d"
+2174 "'%Fs' : actual has type void : parameter %d, parameter list %d"
+2175 "'%Fs' : unresolved external" /* QC */
+2176 "static far data not supported" /* QC */
+2177 "constant too big"
+2178 "'%s' : storage class for same_seg variables must be 'extern'"
+2179 "'%Fs' : was used in same_seg, but storage class is no longer 'extern'"
+2180 "controlling expression has type 'void'"
+2181 "pragma requires command line option '%s'" /* QC */
+2182 "'%Fs' : 'void' on variable"
+2183 "'%Fs' : 'interrupt' function must be 'far'"
+2184 "'%Fs' : '%s' function cannot be 'pascal/fortran'"
+2186 "'%Fs' : 'saveregs/interrupt' modifiers mutually exclusive"
+2187 "cast of near function pointer to far function pointer"
+2188 "#error : %s"
+2190 "'%s' : is a text segment"
+2191 "'%s' : is a data segment"
+2192 "'%s' : function has already been defined"
+2000 "UNKNOWN ERROR\n\t\tContact Microsoft Technical Support"
+
+ /* warnings */
+
+4001 "macro '%s' requires parameters"
+4002 "too many actual parameters for macro '%s'"
+4003 "not enough actual parameters for macro '%s'"
+4004 "missing close parenthesis after 'defined'"
+4005 "'%s' : redefinition"
+4006 "#undef expected an identifier"
+4009 "string too big, trailing chars truncated"
+4011 "identifier truncated to '%s'"
+4012 "float constant in a cross compilation"
+4013 "constant too big"
+4014 "'%Fs' : bit-field type must be unsigned"
+4015 "'%Fs' : bit-field type must be integral"
+4016 "'%s' : no function return type, using 'int' as default"
+4017 "cast of int expression to far pointer"
+4020 "'%Fs' : too many actual parameters"
+4021 "'%Fs' : too few actual parameters"
+4022 "'%Fs' : pointer mismatch : parameter %d"
+4024 "'%Fs' : different types : parameter %d"
+4025 "function declaration specified variable argument list"
+4026 "function was declared with formal argument list"
+4027 "function was declared without formal argument list"
+4028 "parameter %d declaration different"
+4029 "declared parameter list different from definition"
+4030 "first parameter list is longer than the second"
+4031 "second parameter list is longer than the first"
+4032 "unnamed struct/union as parameter"
+4033 "function must return a value"
+4034 "sizeof returns 0"
+4035 "'%Fs' : no return value"
+4036 "unexpected formal parameter list"
+4037 "'%Fs' : formal parameters ignored"
+4038 "'%Fs' : formal parameter has bad storage class"
+4039 "'%Fs' : function used as an argument"
+4040 "near/far/huge on '%Fs' ignored"
+4041 "formal parameter '%s' is redefined"
+4042 "'%Fs' : has bad storage class"
+4044 "huge on '%Fs' ignored, must be an array"
+4045 "'%s' : array bounds overflow"
+4046 "'&' on function/array, ignored"
+4047 "'%s' : different levels of indirection"
+4048 "array's declared subscripts different"
+4049 "'%s' : indirection to different types"
+4051 "data conversion"
+4052 "different enum types"
+4053 "at least one void operand"
+4060 "conversion of long address to short address" /* QC, c23 */
+4061 "long/short mismatch in argument : conversion supplied" /* QC, c23 */
+4062 "near/far mismatch in argument : conversion supplied" /* QC, c23 */
+4067 "unexpected characters following '%s' directive - newline expected"
+4068 "unknown pragma"
+4071 "'%Fs' : no function prototype given"
+4074 "non standard extension used - '%s'"
+4075 "size of switch expression or case constant too large - converted to int"
+4076 "'%s' : may be used on integral types only"
+4077 "unknown check_stack option"
+4079 "unexpected token '%s'"
+4080 "expected 'identifier' for segment name, found '%s'"
+4081 "expected a comma, found '%s'"
+4082 "expected an identifier, found '%s'"
+4083 "expected '(', found '%s'"
+4084 "expected a pragma keyword, found '%s'"
+4085 "expected [on | off]"
+4086 "expected [1 | 2 | 4]"
+4087 "'%Fs' : declared with 'void' parameter list"
+4088 "'%Fs' : pointer mismatch : parameter %d, parameter list %d"
+4089 "'%Fs' : different types : parameter %d, parameter list %d"
+4090 "different 'const' attributes"
+4091 "no symbols were declared"
+4092 "untagged enum/struct/union declared no symbols"
+4093 "unescaped newline in character constant in non-active code"
+4094 "unexpected newline"
+4095 "expected ')', found '%s'"
+4096 "huge treated as far" /* QC */
+4098 "void function returning a value"
+4099 "expected ')', (too many arguments?)"
+4100 "'%Fs' : unreferenced formal parameter"
+4101 "'%Fs' : unreferenced local variable"
+4102 "'%Fs' : unreferenced label"
+4103 "'%Fs' : function definition used as prototype"
+4104 "'%s' : near data in same_seg pragma, ignored"
+4105 "'%Fs' : code modifiers only on function or pointer to function"
+4106 "pragma requires integer between 1 and 127"
+4107 "pragma requires integer between 15 and 255"
+4108 "pragma requires integer between 79 and 132"
+4109 "unexpected identifier '%s'"
+4110 "unexpected token 'int constant'"
+4111 "unexpected token 'string'"
+4112 "macro name '%s' is reserved, %s ignored"
+4113 "function parameter lists differed"
+4000 "UNKNOWN WARNING\n\t\tContact Microsoft Technical Support"
diff --git a/private/ole32/olethunk/ole16/utest/basic/base16.cxx b/private/ole32/olethunk/ole16/utest/basic/base16.cxx
new file mode 100644
index 000000000..668385e64
--- /dev/null
+++ b/private/ole32/olethunk/ole16/utest/basic/base16.cxx
@@ -0,0 +1,41 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: base16.cxx
+//
+// Contents: Base 16 bit thunk test
+//
+// Classes:
+//
+// Functions:
+//
+// History: 3-04-94 kevinro Created
+//
+//----------------------------------------------------------------------------
+
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <windows.h>
+#include <compobj.h>
+#include <storage.h>
+
+void _cdecl main (int argc, char *argv[])
+{
+ HRESULT hr;
+ IStorage FAR *pstg;
+
+ printf("Start test\n");
+ hr = CoInitialize(NULL);
+ if (FAILED(hr))
+ {
+ printf("CoInitialize failed, 0x%08lX\n", hr);
+ }
+
+
+ CoUninitialize();
+ printf("End test\n");
+}
diff --git a/private/ole32/olethunk/ole16/utest/basic/base16.def b/private/ole32/olethunk/ole16/utest/basic/base16.def
new file mode 100644
index 000000000..663dd5f2e
--- /dev/null
+++ b/private/ole32/olethunk/ole16/utest/basic/base16.def
@@ -0,0 +1,7 @@
+;EXETYPE WINDOWS
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 20000
+STACKSIZE 8000
diff --git a/private/ole32/olethunk/ole16/utest/basic/makefile b/private/ole32/olethunk/ole16/utest/basic/makefile
new file mode 100644
index 000000000..f3ba09925
--- /dev/null
+++ b/private/ole32/olethunk/ole16/utest/basic/makefile
@@ -0,0 +1,35 @@
+#
+# Copyright (c) 1991, Microsoft Corporation
+#
+# History:
+#
+# 24-Feb-1994 DrewB
+#
+
+!IFDEF USEBUILD
+
+# If using BUILD.EXE, edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2.
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!ELSE
+
+default: copy_bin
+
+TARGET = base16.exe
+CXXFILES = .\base16.cxx
+QUICKWINDOWS = 1
+LIBS = $(LIBS) \
+ ..\..\compobj\$(OBJDIR)\compobj.lib\
+ ..\..\storage\$(OBJDIR)\storage.lib
+
+!include ..\..\makefile.inc
+
+copy_bin: all
+ binplace $(OBJDIR)\base16.exe
+
+base16.obj: base16.cxx
+
+!ENDIF
diff --git a/private/ole32/olethunk/ole16/utest/triv/makefile b/private/ole32/olethunk/ole16/utest/triv/makefile
new file mode 100644
index 000000000..1e8bdfafb
--- /dev/null
+++ b/private/ole32/olethunk/ole16/utest/triv/makefile
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 1991, Microsoft Corporation
+#
+# History:
+#
+# 24-Feb-1994 DrewB
+#
+
+!IFDEF USEBUILD
+
+# If using BUILD.EXE, edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2.
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!ELSE
+
+default: copy_bin
+
+TARGET = triv.exe
+CXXFILES = .\triv.cxx
+LIBS = $(LIBS) \
+ ..\..\compobj\$(OBJDIR)\compobj.lib\
+ ..\..\storage\$(OBJDIR)\storage.lib
+
+!include ..\..\makefile.inc
+
+copy_bin: all
+ binplace $(OBJDIR)\triv.exe
+
+triv.obj: triv.cxx
+
+!ENDIF
diff --git a/private/ole32/olethunk/ole16/utest/triv/triv.cxx b/private/ole32/olethunk/ole16/utest/triv/triv.cxx
new file mode 100644
index 000000000..6d9409c91
--- /dev/null
+++ b/private/ole32/olethunk/ole16/utest/triv/triv.cxx
@@ -0,0 +1,60 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: triv.cxx
+//
+// Contents: Trivial thunking test
+//
+// History: 24-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <windows.h>
+#include <compobj.h>
+#include <storage.h>
+
+void DbgOut(char *fmt, ...)
+{
+ va_list args;
+ char str[80];
+
+ va_start(args, fmt);
+ wvsprintf(str, fmt, args);
+ OutputDebugString(str);
+ va_end(args);
+}
+
+int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ LPSTR lpszCmdLine, int nCmdShow)
+{
+ HRESULT hr;
+ IStorage FAR *pstg;
+
+ hr = CoInitialize(NULL);
+ if (FAILED(GetScode(hr)))
+ {
+ DbgOut("CoInitialize failed, 0x%08lX\n", hr);
+ }
+ else
+ {
+ hr = StgCreateDocfile("test.dfl", STGM_DIRECT | STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, &pstg);
+ if (FAILED(GetScode(hr)))
+ {
+ DbgOut("StgCreateDocfile failed, 0x%08lX\n", hr);
+ }
+ else
+ {
+ pstg->Release();
+ }
+
+ CoUninitialize();
+ }
+
+ return TRUE;
+}
diff --git a/private/ole32/olethunk/ole16/utest/triv/triv.def b/private/ole32/olethunk/ole16/utest/triv/triv.def
new file mode 100644
index 000000000..663dd5f2e
--- /dev/null
+++ b/private/ole32/olethunk/ole16/utest/triv/triv.def
@@ -0,0 +1,7 @@
+;EXETYPE WINDOWS
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 20000
+STACKSIZE 8000
diff --git a/private/ole32/olethunk/olethk32/alias.cxx b/private/ole32/olethunk/olethk32/alias.cxx
new file mode 100644
index 000000000..0f60dd989
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/alias.cxx
@@ -0,0 +1,405 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: alias.cxx
+//
+// Contents: Alias implementations
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAliasBlock::CAliasBlock, public
+//
+// Synopsis: Constructor
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CAliasBlock::CAliasBlock(ALIAS aliasBase,
+ CAliasBlock *pabNext)
+{
+ _aliasBase = aliasBase;
+ _iFilled = 0;
+ _pabNext = pabNext;
+
+ // Since INVALID_VALUE is a DWORD we can't directly memset it,
+ // but we'd like to use memset so assert that it's a known value
+ // and go ahead
+ thkAssert(INVALID_VALUE == 0);
+ memset(_dwValues, 0, sizeof(_dwValues));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAliasBlock::ValueAlias, public
+//
+// Synopsis: Find the alias for a value
+//
+// Arguments: [dwValue] - Value
+//
+// Returns: Alias or INVALID_ALIAS
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+ALIAS CAliasBlock::ValueAlias(DWORD dwValue)
+{
+ int i;
+ DWORD *pdw;
+
+ thkAssert(dwValue != INVALID_VALUE);
+
+#if DBG == 1
+ CheckFree();
+#endif
+
+ if (_iFilled == 0)
+ {
+ return INVALID_ALIAS;
+ }
+
+ pdw = _dwValues;
+ for (i = 0; i < ALIAS_BLOCK_SIZE; i++)
+ {
+ if (*pdw == dwValue)
+ {
+ return IndexAlias(i);
+ }
+
+ pdw++;
+ }
+
+ return INVALID_ALIAS;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAliasBlock::AddValue, public
+//
+// Synopsis: Adds a new value
+//
+// Arguments: [dwValue] - New value
+//
+// Returns: Alias for block or INVALID_ALIAS
+//
+// History: 26-May-94 DrewB Created
+//
+// Notes: Duplicates are not allowed
+//
+//----------------------------------------------------------------------------
+
+ALIAS CAliasBlock::AddValue(DWORD dwValue)
+{
+ int i;
+ DWORD *pdw;
+
+ thkAssert(dwValue != INVALID_VALUE);
+
+#if DBG == 1
+ CheckFree();
+#endif
+
+ if (_iFilled == ALIAS_BLOCK_SIZE)
+ {
+ return INVALID_ALIAS;
+ }
+
+ // Check for duplicates
+ thkAssert(ValueAlias(dwValue) == INVALID_ALIAS);
+
+ pdw = _dwValues;
+ for (i = 0; i < ALIAS_BLOCK_SIZE; i++)
+ {
+ if (*pdw == INVALID_VALUE)
+ {
+ break;
+ }
+
+ pdw++;
+ }
+
+ thkAssert(i < ALIAS_BLOCK_SIZE);
+
+ _iFilled++;
+ _dwValues[i] = dwValue;
+
+ return IndexAlias(i);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAliasBlock::CheckFree, public debug
+//
+// Synopsis: Checks to make sure that _iFilled is correct
+//
+// History: 30-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+void CAliasBlock::CheckFree(void)
+{
+ int i, iFilled;
+ DWORD *pdw;
+
+ iFilled = 0;
+ pdw = _dwValues;
+ for (i = 0; i < ALIAS_BLOCK_SIZE; i++)
+ {
+ if (*pdw != INVALID_VALUE)
+ {
+ iFilled++;
+ }
+
+ pdw++;
+ }
+
+ thkAssert(iFilled == _iFilled);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: CAliases::~CAliases, public
+//
+// Synopsis: Destructor
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CAliases::~CAliases(void)
+{
+ CAliasBlock *pab;
+
+ while (_pabAliases)
+ {
+ pab = _pabAliases->GetNext();
+ //
+ // The first alias block added to the list is a static one. We
+ // cannot call the heap to deallocate it.
+ //
+ if (_pabAliases != &_abStatic)
+ {
+ delete _pabAliases;
+ }
+
+ _pabAliases = pab;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAliases::AliasValue, public
+//
+// Synopsis: Returns the value for an alias
+//
+// Arguments: [alias] - Alias
+//
+// Returns: Value
+//
+// History: 26-May-94 DrewB Created
+//
+// Notes: Alias must be valid
+//
+//----------------------------------------------------------------------------
+
+DWORD CAliases::AliasValue(ALIAS alias)
+{
+ CAliasBlock *pab;
+
+ for (pab = _pabAliases; pab; pab = pab->GetNext())
+ {
+ if (pab->ContainsAlias(alias))
+ {
+ return pab->AliasValue(alias);
+ }
+ }
+
+ thkAssert(!"Invalid alias in CAliases::AliasValue");
+
+ return 0xffffffff;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CAliases::ValueAlias, public
+//
+// Synopsis: Returns the alias for a value
+//
+// Arguments: [dwValue] - Value
+//
+// Returns: Alias
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+ALIAS CAliases::ValueAlias(DWORD dwValue)
+{
+ CAliasBlock *pab;
+ ALIAS alias;
+
+ for (pab = _pabAliases; pab; pab = pab->GetNext())
+ {
+ alias = pab->ValueAlias(dwValue);
+ if (alias != INVALID_ALIAS)
+ {
+ return alias;
+ }
+ }
+
+ return INVALID_ALIAS;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CAliases::AddValue, public
+//
+// Synopsis: Adds a value and returns its alias
+//
+// Arguments: [dwValue] - Value
+//
+// Returns: Alias or INVALID_ALIAS
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+ALIAS CAliases::AddValue(DWORD dwValue)
+{
+ CAliasBlock *pab;
+ ALIAS alias;
+
+ for (pab = _pabAliases; pab; pab = pab->GetNext())
+ {
+ alias = pab->AddValue(dwValue);
+ if (alias != INVALID_ALIAS)
+ {
+ return alias;
+ }
+ }
+
+ if ((long)_aliasBase+ALIAS_BLOCK_SIZE >= INVALID_ALIAS)
+ {
+ return INVALID_ALIAS;
+ }
+
+ pab = new CAliasBlock(_aliasBase+ALIAS_BLOCK_SIZE, _pabAliases);
+ if (pab == NULL)
+ {
+ return INVALID_ALIAS;
+ }
+
+ _aliasBase += ALIAS_BLOCK_SIZE;
+ _pabAliases = pab;
+
+ alias = pab->AddValue(dwValue);
+
+ thkAssert(alias != INVALID_ALIAS);
+
+ return alias;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CAliases::RemoveAlias, public
+//
+// Synopsis: Removes an alias
+//
+// Arguments: [alias] - Alias
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CAliases::RemoveAlias(ALIAS alias)
+{
+ CAliasBlock *pab, *pabPrev;
+
+ pabPrev = NULL;
+ for (pab = _pabAliases; pab; pabPrev = pab, pab = pab->GetNext())
+ {
+ if (pab->ContainsAlias(alias))
+ {
+ pab->RemoveAlias(alias);
+
+ if (pab->AliasesFilled() == 0)
+ {
+ DeleteBlock(pab, pabPrev);
+ }
+
+ return;
+ }
+ }
+
+ thkAssert(!"Invalid alias in CAliases::RemoveAlias");
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CAliases::SetValue, public
+//
+// Synopsis: Sets the value for an alias
+//
+// Arguments: [alias] - Alias
+// [dwValue] - Value
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CAliases::SetValue(ALIAS alias, DWORD dwValue)
+{
+ CAliasBlock *pab;
+
+ for (pab = _pabAliases; pab; pab = pab->GetNext())
+ {
+ if (pab->ContainsAlias(alias))
+ {
+ pab->SetValue(alias, dwValue);
+ }
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAliases::DeleteBlock, private
+//
+// Synopsis: Deletes an alias block if it's not the static block
+//
+// Arguments: [pab] - Alias block
+// [pabPrev] - Previous alias block
+//
+// History: 27-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CAliases::DeleteBlock(CAliasBlock *pab, CAliasBlock *pabPrev)
+{
+ if (pab == &_abStatic)
+ {
+ return;
+ }
+
+ if (pabPrev)
+ {
+ pabPrev->SetNext(pab->GetNext());
+ }
+ else
+ {
+ _pabAliases = pab->GetNext();
+ }
+
+ delete pab;
+}
diff --git a/private/ole32/olethunk/olethk32/alias.hxx b/private/ole32/olethunk/olethk32/alias.hxx
new file mode 100644
index 000000000..0718e84b9
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/alias.hxx
@@ -0,0 +1,163 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: alias.hxx
+//
+// Classes: CAliasBlock
+// CAliases
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ALIAS_HXX__
+#define __ALIAS_HXX__
+
+// Number of alias slots to allocate in a chunk
+#define ALIAS_BLOCK_SIZE 64
+
+typedef WORD ALIAS;
+#define INVALID_ALIAS ((ALIAS)0xffff)
+
+// Aliases should not be zero because this causes error detection problems
+#define INITIAL_ALIAS ((ALIAS)1)
+
+// Values cannot be zero, this allows us to detect free slots in the
+// value array
+#define INVALID_VALUE ((DWORD)0)
+
+//+---------------------------------------------------------------------------
+//
+// Class: CAliasBlock (ab)
+//
+// Purpose: A block of values indexed by alias
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CAliasBlock
+{
+public:
+ CAliasBlock(ALIAS aliasBase,
+ CAliasBlock *pabNext);
+
+ BOOL ContainsAlias(ALIAS alias)
+ {
+ return alias >= _aliasBase && alias < _aliasBase+ALIAS_BLOCK_SIZE;
+ }
+ DWORD AliasValue(ALIAS alias)
+ {
+ thkAssert(!IsFree(alias));
+
+ return _dwValues[AliasIndex(alias)];
+ }
+ void RemoveAlias(ALIAS alias)
+ {
+ thkAssert(!IsFree(alias));
+#if DBG == 1
+ CheckFree();
+#endif
+ thkAssert(_iFilled > 0);
+
+ _iFilled--;
+ _dwValues[AliasIndex(alias)] = INVALID_VALUE;
+ }
+ void SetValue(ALIAS alias, DWORD dwValue)
+ {
+ thkAssert(!IsFree(alias));
+ thkAssert(dwValue != INVALID_VALUE);
+
+ _dwValues[AliasIndex(alias)] = dwValue;
+ }
+
+ ALIAS ValueAlias(DWORD dwValue);
+ ALIAS AddValue(DWORD dwValue);
+
+ CAliasBlock *GetNext(void)
+ {
+ return _pabNext;
+ }
+ void SetNext(CAliasBlock *pab)
+ {
+ _pabNext = pab;
+ }
+ int AliasesFilled(void)
+ {
+ return _iFilled;
+ }
+
+#if DBG == 1
+ BOOL IsFree(ALIAS alias)
+ {
+ return _dwValues[AliasIndex(alias)] == INVALID_VALUE;
+ }
+#endif
+
+private:
+ int AliasIndex(ALIAS alias)
+ {
+ thkAssert(ContainsAlias(alias));
+
+ return (int)(alias-_aliasBase);
+ }
+ ALIAS IndexAlias(int iIndex)
+ {
+ thkAssert(iIndex >= 0 && iIndex < ALIAS_BLOCK_SIZE);
+
+ return (ALIAS)(iIndex+_aliasBase);
+ }
+
+#if DBG == 1
+ void CheckFree(void);
+#endif
+
+ ALIAS _aliasBase;
+ int _iFilled;
+ DWORD _dwValues[ALIAS_BLOCK_SIZE];
+ CAliasBlock *_pabNext;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Class: CAliases (aliases)
+//
+// Purpose: Maintains a set of aliases for values
+//
+// History: 26-May-94 DrewB Created
+//
+// Notes: Values must be unique
+//
+//----------------------------------------------------------------------------
+
+class CAliases
+{
+public:
+ CAliases(void)
+ : _abStatic(INITIAL_ALIAS, NULL)
+ {
+ // Start alias list with the static block
+ _pabAliases = &_abStatic;
+
+ // The static block takes the first block of aliases
+ _aliasBase = INITIAL_ALIAS+ALIAS_BLOCK_SIZE;
+ }
+ ~CAliases(void);
+
+ DWORD AliasValue(ALIAS alias);
+ ALIAS ValueAlias(DWORD dwValue);
+ ALIAS AddValue(DWORD dwValue);
+ void RemoveAlias(ALIAS alias);
+ void SetValue(ALIAS alias, DWORD dwValue);
+
+private:
+ void DeleteBlock(CAliasBlock *pab, CAliasBlock *pabPrev);
+
+ CAliasBlock _abStatic;
+ CAliasBlock *_pabAliases;
+ ALIAS _aliasBase;
+};
+
+#endif // #ifndef __ALIAS_HXX__
diff --git a/private/ole32/olethunk/olethk32/apinot.cxx b/private/ole32/olethunk/olethk32/apinot.cxx
new file mode 100644
index 000000000..de850d67e
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/apinot.cxx
@@ -0,0 +1,990 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: apinot.cxx
+//
+// Contents: Implementation of non-API thunks
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <thunkapi.hxx>
+#include <wownt32.h>
+#include "olethk32.hxx"
+#include "apinot.hxx"
+#include "tlsthk.hxx"
+
+//
+// The following is a global static used by OLE32 to call back into
+// this DLL. There is no static data associated with the static, so
+// it merely defines a virtual interface that OLE32 can use.
+//
+
+OleThunkWOW g_thkOleThunkWOW;
+
+//
+// The following API is exported from WOW32.DLL. There is no global include
+// file that it exists in yet.
+//
+#if defined(_CHICAGO_)
+#define WOWFreeMetafile(x) (0) /* BUGBUGCHICAGO - Not supported under Chicago yet. */
+#else
+extern "C" BOOL WINAPI WOWFreeMetafile( HANDLE h32 );
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoInitializeNot, public
+//
+// Synopsis: Thunks for the 16-bit applications call to CoInitialize
+//
+// Arguments: [lpmalloc] - Parameter from the 16-bit world
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(DWORD) CoInitializeNot( LPMALLOC lpMalloc )
+{
+ HRESULT hresult;
+
+ hresult = CoInitializeWOW( lpMalloc, &g_thkOleThunkWOW );
+
+ return (DWORD)hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleInitializeNot, public
+//
+// Synopsis: Thunks for the 16-bit applications call to OleInitialize
+//
+// Arguments: [lpmalloc] - Parameter from the 16-bit world
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(DWORD) OleInitializeNot( LPMALLOC lpMalloc )
+{
+ HRESULT hresult;
+
+ hresult = OleInitializeWOW( lpMalloc, &g_thkOleThunkWOW );
+
+ return (DWORD)hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: RegisterDelayedClassFactories
+//
+// Synopsis: This function is called to actually do the registration of
+// the delayed class factories.
+//
+// Effects: When the application specific 'trigger' is hit
+// (ie OleRegGetUserType for WordPerfect), this routine is
+// called to actually do all of the delayed class factory
+// registrations.
+//
+// Arguments: (none)
+//
+// Requires:
+//
+// Returns: nothing
+//
+// History: 4-18-95 kevinro Created
+//
+//----------------------------------------------------------------------------
+void RegisterDelayedClassFactories()
+{
+ thkDebugOut((DEB_ITRACE,
+ "_IN RegisterDelayedClassFactories()\n"));
+
+ PThreadData pdata;
+ IUnknown *punk;
+ HRESULT hr;
+ DelayedRegistrationTable *pTable = NULL;
+ DelayRegistration *pdelayed;
+ DWORD dwReg;
+
+ int i;
+ //
+ // Get the thread specific data and table to determine if there are
+ // any delayed registrations. If not, just call the real routine.
+ //
+ pdata = TlsThkGetData();
+
+ if (pdata == NULL)
+ {
+ goto exitRtn;
+ }
+
+ if ((pTable = pdata->pDelayedRegs) == NULL)
+ {
+ goto exitRtn;
+ }
+
+ //
+ //
+ //
+ for (i = 0 ; i < MAX_DELAYED_REGISTRATIONS ; i++)
+ {
+ pdelayed = &(pTable->_Entries[i]);
+
+ if((pdelayed->_punk != NULL) && (pdelayed->_dwRealKey == 0))
+ {
+ hr = CoRegisterClassObject(pdelayed->_clsid,
+ pdelayed->_punk,
+ pdelayed->_dwClsContext,
+ pdelayed->_flags,
+ &(pdelayed->_dwRealKey));
+ if (FAILED(hr))
+ {
+ thkDebugOut((DEB_ERROR,
+ "RegisterDelayedClassFactory gets %x\n",hr));
+ }
+ }
+ }
+
+exitRtn:
+
+ thkDebugOut((DEB_ITRACE,
+ "OUT RegisterDelayedClassFactories()\n"));
+
+}
+//+---------------------------------------------------------------------------
+//
+// Function: CoRevokeClassObjectNot
+//
+// Synopsis: Unregisters a class object that might have been delayed
+//
+// Effects: The 16-bit API CoRevokeClassObject has been directed to this
+// routine. This routine will check the list of interfaces that
+// have been registered, and will try to determine if the key
+// needs to be translated.
+//
+// Arguments: [dwKey] -- Key to revoke
+//
+// History: 4-18-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CoRevokeClassObjectNot( DWORD dwKey)
+{
+ thkDebugOut((DEB_ITRACE,
+ "_IN CoRevokeClassObjectNot(dwKey = %x)\n",
+ dwKey));
+
+ PThreadData pdata;
+ IUnknown *punk;
+ HRESULT hr;
+ DelayedRegistrationTable *pTable = NULL;
+
+ DWORD dwReg = ~dwKey;
+
+ //
+ // Get the thread specific data and table to determine if there are
+ // any delayed registrations. If not, just call the real routine.
+ //
+ pdata = TlsThkGetData();
+
+ if (pdata == NULL)
+ {
+ goto exitRtn;
+ }
+
+ if ((pTable = pdata->pDelayedRegs) == NULL)
+ {
+ goto exitRtn;
+ }
+
+ //
+ // the 'fake' key is really the bitwise not of the index
+ //
+
+ if ( dwReg >= MAX_DELAYED_REGISTRATIONS)
+ {
+ goto exitRtn;
+ }
+
+ if(pTable->_Entries[dwReg]._punk != NULL)
+ {
+ punk = pTable->_Entries[dwReg]._punk;
+ pTable->_Entries[dwReg]._punk = NULL;
+
+ dwKey = pTable->_Entries[dwReg]._dwRealKey;
+ pTable->_Entries[dwReg]._dwRealKey = 0;
+
+ //
+ // The class object table normally does an addref on the class factory.
+ // We are also holding an addref on the punk. Release it.
+ //
+ if (punk != NULL)
+ {
+ punk->Release();
+
+ //
+ // If the real key is zero, then we never did actually finish
+ // the registration. In this case, we return S_OK, because we
+ // are faking the app out anyway. This might happen if the app
+ // decides to shutdown for some reason without triggering the
+ // operation that causes us to register its class objects
+ //
+ if (dwKey == 0)
+ {
+ hr = S_OK;
+ goto exitNow;
+ }
+ }
+ }
+
+exitRtn:
+
+ hr = CoRevokeClassObject(dwKey);
+
+exitNow:
+ thkDebugOut((DEB_ITRACE,"OUT CoRevokeClassObjectNot():%x\n",hr));
+ return(hr);
+
+}
+//+---------------------------------------------------------------------------
+//
+// Function: CoRegisterClassObjectDelayed
+//
+// Synopsis: Delay the registration of class objects. Some applications,
+// such as Word Perfect 6.1, register their class objects then
+// do peek message operations BEFORE they are fully initialized.
+// This causes problems because we can call in and do
+// CreateInstance calls before they are ready for them. This
+// wonderful hack will delay the registration of class objects
+// until someone calls RegisterClassObjectsNow(), which is
+// called when we know it is safe.
+//
+// Novell knows about this hack, and promised not to change
+// the 16-bit code on us.
+//
+// Effects: Store all of the registration information in an array, and
+// return a special key value.
+//
+//
+// Arguments: ( Same as CoRegisterClassObject)
+//
+// Requires: The associated routine CoUnregisterClassObjectDelayed needs
+// to be called in the CoRevokeClassObject path to check to see
+// if the key being passed in is a special key. That way we
+// can translate the key before calling the real routine.
+//
+// The special key value is not of the key
+//
+// Returns: S_OK or E_UNEXPECTED
+//
+// History: 4-14-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+HRESULT CoRegisterClassObjectDelayed( REFCLSID refclsid, LPUNKNOWN punk,
+ DWORD dwClsContext, DWORD flags, DWORD *pdwReg)
+{
+ thkDebugOut((DEB_ITRACE,"_IN CoRegisterClassObjectDelayed\n"));
+ PThreadData pdata;
+ int i;
+ DelayedRegistrationTable *pTable = NULL;
+
+ //
+ // Assume this is going to fail
+ //
+ HRESULT hr = E_UNEXPECTED;
+ *pdwReg = 0;
+
+ pdata = TlsThkGetData();
+ if (pdata == NULL)
+ {
+ goto exitRtn;
+ }
+
+ if ((pTable = pdata->pDelayedRegs) == NULL)
+ {
+ pTable = pdata->pDelayedRegs = new DelayedRegistrationTable();
+ }
+
+ if (pTable != NULL)
+ {
+ for (i = 0 ; i < MAX_DELAYED_REGISTRATIONS ; i++)
+ {
+ if(pTable->_Entries[i]._punk == NULL)
+ {
+ pTable->_Entries[i]._punk = punk;
+ pTable->_Entries[i]._clsid = refclsid;
+ pTable->_Entries[i]._dwClsContext = dwClsContext;
+ pTable->_Entries[i]._flags = flags;
+ //
+ // The class object table normally does an
+ // addref on the class factory. We will hang on to this
+ // to keep the class factory and the 3216 proxy alive
+ //
+ punk->AddRef();
+ *pdwReg = ~i;
+ hr = S_OK;
+ break;
+ }
+ }
+ }
+
+exitRtn:
+ thkDebugOut((DEB_ITRACE,"OUT CoRegisterClassObjectDelayed() : %x\n",hr));
+ return(hr);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoRegisterClassObjectNot, public
+//
+// Synopsis: Thunks for the 16-bit applications call CoRegisterClassObject
+// Here we check for the registered class objects to set the
+// thread's compatability bits.
+//
+// Arguments: [refclsid] - CLSID for the class to register
+// [punk] - ClassFactory interface
+// [dwClsContext] - Class context
+// [flags] - flags
+// [lpdwreg] - register
+//
+// Returns: Appropriate status code
+//
+// History: 18-Jul-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+EXTERN_C const CLSID CDECL CLSID_EXCEL5_WORKSHEET =
+ { 0x020810, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}};
+
+EXTERN_C const CLSID CDECL CLSID_WORD6_DOCUMENT =
+ { 0x020900, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}};
+
+EXTERN_C const CLSID CDECL CLSID_WPWIN61 =
+ { 0x89FE3FE3, 0x9FF6, 0x101B, {0xB6, 0x78, 0x04, 0x02, 0x1C, 0x00, 0x70, 0x02}};
+
+EXTERN_C const CLSID CDECL CLSID_WPWIN61_FILE =
+ { 0x1395F281, 0x4326, 0x101b, {0x8B, 0x9A, 0xCE, 0x29, 0x3E, 0xF3, 0x84, 0x49}};
+
+EXTERN_C const CLSID CDECL CLSID_IKITARO_130 =
+ { 0x02B501, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}};
+
+
+DEFINE_OLEGUID(CLSID_EXCEL5_WORKSHEET, 0x20810, 0, 0);
+
+
+
+STDAPI_(DWORD) CoRegisterClassObjectNot( REFCLSID refclsid, LPUNKNOWN punk,
+ DWORD dwClsContext, DWORD flags,
+ LPDWORD lpdwreg )
+{
+ //
+ // Excel didn't AddRef the IOleObjectClientSite returned from
+ // the IOleObject::GetClientSite method.
+ //
+ if ( IsEqualCLSID(refclsid,CLSID_EXCEL5_WORKSHEET) )
+ {
+ DWORD dw;
+
+ dw = TlsThkGetAppCompatFlags();
+ TlsThkSetAppCompatFlags(dw | OACF_CLIENTSITE_REF);
+
+ thkDebugOut((DEB_WARN,"AppCompatFlag: OACF_CLIENTSITE_REF enabled\n"));
+ }
+
+ //
+ // WinWord didn't call OleSetMenuDescriptor(NULL) during
+ // IOleInPlaceFrame::RemoveMenus. We do it for them.
+ //
+ // Also WinWord thinks GDI objects like palettes and bitmaps can be
+ // transferred on HGLOBALs during GetData calls. In order to thunk
+ // them properly, we need to patch up the STGMEDIUMS given to use
+ // by word. This is controlled by OACF_USEGDI.
+ //
+ // YAWC: Word chokes and dies because it fails to disconnect some of its
+ // objects. During shutdown of a link, for example, cleaning up the stdid
+ // table causes WORD to fault.
+ //
+ else if ( IsEqualCLSID(refclsid,CLSID_WORD6_DOCUMENT) )
+ {
+ DWORD dw;
+
+ dw = TlsThkGetAppCompatFlags();
+ TlsThkSetAppCompatFlags(dw | OACF_RESETMENU | OACF_USEGDI | OACF_NO_UNINIT_CLEANUP);
+
+ thkDebugOut((DEB_WARN,"AppCompatFlag: OACF_RESETMENU enabled\n"));
+ thkDebugOut((DEB_WARN,"AppCompatFlag: OACF_USEGDI enabled\n"));
+ thkDebugOut((DEB_WARN,"AppCompatFlag: OACF_NO_UNINIT_CLEANUP enabled\n"));
+ }
+ else if ( IsEqualCLSID(refclsid,CLSID_WPWIN61) )
+ {
+ thkDebugOut((DEB_WARN,"WordPerfect hack triggered\n"));
+ thkDebugOut((DEB_WARN,"Intercepting CoRegisterClassObject(WPWIN61)\n"));
+
+ return CoRegisterClassObjectDelayed( refclsid,punk,dwClsContext,flags,lpdwreg);
+
+ }
+ else if ( IsEqualCLSID(refclsid,CLSID_WPWIN61_FILE) )
+ {
+ thkDebugOut((DEB_WARN,"WordPerfect hack triggered\n"));
+ thkDebugOut((DEB_WARN,"Intercepting CoRegisterClassObject(WPWIN61_FILE)\n"));
+ return CoRegisterClassObjectDelayed( refclsid,punk,dwClsContext,flags,lpdwreg);
+ }
+ else if ( IsEqualCLSID(refclsid,CLSID_IKITARO_130) )
+ {
+ // Note: Ikitaro queries for IViewObject and uses it as IViewObject2
+ DWORD dw = TlsThkGetAppCompatFlags();
+ thkDebugOut((DEB_WARN,"Ikitaro hack triggered\n"));
+ TlsThkSetAppCompatFlags(dw | OACF_IVIEWOBJECT2);
+ }
+
+ return (DWORD)CoRegisterClassObject( refclsid, punk, dwClsContext,
+ flags, lpdwreg );
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleRegGetUserTypeNot
+//
+// Synopsis: Adds a hook for a WordPerfect hack. Check out the functions
+// CoRegisterClassObjectDelayed and
+// RegisterDelayedClassFactories for details. In essence, when
+// this function is called for the WPWIN61 classID, we know
+// that it is safe to register all of the delayed class objects.
+// This determination was done by debugging Wordperfect. When
+// they call this API, then are actually done initializing the
+// internals of their app.
+//
+// Effects:
+//
+// History: 4-18-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(DWORD)
+OleRegGetUserTypeNot(REFCLSID clsid,DWORD dwFormOfType,LPOLESTR *pszUserType)
+{
+ //
+ // Wordperfect has a bug. When they call OleRegGetUserType for their
+ // classid, we know that it is safe to register their class objects for
+ // real.
+ //
+ // See CoRegisterClassObjectDelayed for details
+ //
+ if ( IsEqualCLSID(clsid,CLSID_WPWIN61) )
+ {
+ thkDebugOut((DEB_WARN,"Registering WordPerfects class objects\n"));
+ RegisterDelayedClassFactories();
+ }
+ return OleRegGetUserType(clsid,dwFormOfType,pszUserType);
+}
+//+---------------------------------------------------------------------------
+//
+// Member: OleThunkWOW::LoadProcDll, public
+//
+// Synopsis: Callback function for 32-bit OLE to load a 16-bit DLL
+//
+// Arguments: [pszDllName] - Name of 16-bit DLL
+// [lpvpfnGetClassObject] - returned 16:16 address of
+// "DllGetClassObject"
+// [lpvpfnCanUnloadNow] - returned 16:16 address of
+// "DllCanUnloadNow"
+// [lpvhmodule] - returned 16-bit hmodule
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP
+OleThunkWOW::LoadProcDll(
+ LPCTSTR pszDllName,
+ LPDWORD lpvpfnGetClassObject,
+ LPDWORD lpvpfnCanUnloadNow,
+ LPDWORD lpvhmodule
+)
+{
+ HRESULT hr;
+ UINT uiSize;
+ VPSTR vpstr16;
+ VPVOID vplpds16;
+ LOADPROCDLLSTRUCT UNALIGNED *lplpds16;
+
+ uiSize = lstrlen(pszDllName) + 1;
+
+ vpstr16 = STACKALLOC16(uiSize*sizeof(TCHAR));
+ if (vpstr16 == 0)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+#ifndef _CHICAGO_
+ hr = Convert_LPOLESTR_to_VPSTR(pszDllName, vpstr16,
+ uiSize, uiSize*sizeof(TCHAR));
+#else
+ hr = Convert_LPSTR_to_VPSTR(pszDllName, vpstr16,
+ uiSize, uiSize*sizeof(TCHAR));
+#endif
+
+ if (FAILED(hr))
+ {
+ goto EH_vpstr16;
+ }
+
+ vplpds16 = STACKALLOC16(sizeof(LOADPROCDLLSTRUCT));
+ if (vplpds16 == 0)
+ {
+ hr = E_OUTOFMEMORY;
+ goto EH_vpstr16;
+ }
+
+ lplpds16 = FIXVDMPTR(vplpds16, LOADPROCDLLSTRUCT);
+
+ lplpds16->vpDllName = vpstr16;
+ lplpds16->vpfnGetClassObject = 0;
+ lplpds16->vpfnCanUnloadNow = 0;
+ lplpds16->vhmodule = 0;
+
+ RELVDMPTR(vplpds16);
+
+ hr = CallbackTo16( gdata16Data.fnLoadProcDll, vplpds16 );
+
+ if (SUCCEEDED(hr))
+ {
+ lplpds16 = FIXVDMPTR(vplpds16, LOADPROCDLLSTRUCT);
+ *lpvpfnGetClassObject = lplpds16->vpfnGetClassObject;
+ *lpvpfnCanUnloadNow = lplpds16->vpfnCanUnloadNow;
+ *lpvhmodule = lplpds16->vhmodule;
+ RELVDMPTR(vplpds16);
+ }
+ else
+ {
+ hr = CO_E_DLLNOTFOUND;
+ }
+
+ STACKFREE16(vplpds16, sizeof(LOADPROCDLLSTRUCT));
+
+ EH_vpstr16:
+ STACKFREE16(vpstr16,uiSize*sizeof(TCHAR));
+
+ Exit:
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: OleThunkWOW::UnloadProcDll, public
+//
+// Synopsis: Callback function for 32-bit OLE to unload a 16-bit DLL
+//
+// Arguments: [vhmodule] - 16-bit hmodule
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP
+OleThunkWOW::UnloadProcDll(
+ DWORD vhmodule
+)
+{
+ return CallbackTo16( gdata16Data.fnUnloadProcDll, vhmodule );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: OleThunkWOW::CallGetClassObject, public
+//
+// Synopsis: Callback function for 32-bit OLE to call 16-bit
+// DllGetClassObject
+//
+// Arguments: [vpfnGetClassObject] - 16:16 address of DllGetClassObject
+// [rclsid] - CLSID of object
+// [riid] - IID of interface on object
+// [ppv] - returned object interface
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP
+OleThunkWOW::CallGetClassObject(
+ DWORD vpfnGetClassObject,
+ REFCLSID rclsid,
+ REFIID riid,
+ LPVOID FAR *ppv
+)
+{
+ DWORD dwResult;
+ VPVOID vpcgcos16;
+ CALLGETCLASSOBJECTSTRUCT UNALIGNED *lpcgcos16;
+ VPVOID iface16;
+ IIDIDX iidx;
+ IUnknown *punkThis32;
+ CThkMgr *pThkMgr;
+ ThreadData *ptd;
+
+ ptd = TlsThkGetData();
+ if (ptd == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: CallGetClassObject refused\n"));
+
+ dwResult = (DWORD)E_FAIL;
+ goto Exit;
+ }
+ pThkMgr = ptd->pCThkMgr;
+
+ vpcgcos16 = STACKALLOC16(sizeof(CALLGETCLASSOBJECTSTRUCT));
+ if (vpcgcos16 == 0)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ lpcgcos16 = FIXVDMPTR(vpcgcos16, CALLGETCLASSOBJECTSTRUCT);
+
+ lpcgcos16->vpfnGetClassObject = vpfnGetClassObject;
+ lpcgcos16->clsid = rclsid;
+ lpcgcos16->iid = riid;
+ lpcgcos16->iface = 0;
+
+ RELVDMPTR(vpcgcos16);
+
+ dwResult = CallbackTo16( gdata16Data.fnCallGetClassObject, vpcgcos16 );
+
+ if ( SUCCEEDED(dwResult) )
+ {
+ lpcgcos16 = FIXVDMPTR(vpcgcos16, CALLGETCLASSOBJECTSTRUCT);
+ iface16 = lpcgcos16->iface;
+
+ iidx = IidToIidIdx(riid);
+
+ // We're on the way out creating a proxy so set the state
+ // appropriately
+ pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT32);
+
+ // Get a 32-bit proxy object for the 16-bit object
+ punkThis32 = pThkMgr->FindProxy3216(NULL, iface16, iidx, NULL);
+
+ pThkMgr->SetThkState(THKSTATE_NOCALL);
+
+ // Set the out param
+ *(IUnknown **)ppv = punkThis32;
+
+ if (punkThis32 == NULL)
+ {
+ // Release the class object we just retrieved
+ ReleaseOnObj16(iface16);
+
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+
+ RELVDMPTR(vpcgcos16);
+ }
+
+ STACKFREE16(vpcgcos16, sizeof(CALLGETCLASSOBJECTSTRUCT));
+
+ Exit:
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: OleThunkWOW::CallCanUnloadNow, public
+//
+// Synopsis: Callback function for 32-bit OLE to call 16-bit
+// CanUnloadNow
+//
+// Arguments: [vpfnCanUnloadNow] - 16:16 address of DllCanUnloadNow
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP OleThunkWOW::CallCanUnloadNow(
+ DWORD vpfnCanUnloadNow)
+{
+ return CallbackTo16( gdata16Data.fnCallCanUnloadNow, vpfnCanUnloadNow );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: OleThunkWOW::GetThunkManager, public
+//
+// Synopsis: Callback function for 32-bit OLE to retrieve the thunkmanager
+//
+// Arguments: [ppThkMgr] - Thunk manager return
+//
+// Returns: Appropriate status code
+//
+// History: 11-May-94 JohannP Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP OleThunkWOW::GetThunkManager(IThunkManager **ppThkMgr)
+{
+ thkDebugOut((DEB_THUNKMGR, "%sIn OleThunkWOW::GetThunkManager\n",
+ NestingLevelString()));
+
+ thkAssert(ppThkMgr != NULL);
+
+ IUnknown *pUnk = TlsThkGetThkMgr();
+ thkAssert(pUnk && "Invalid Thunkmanager");
+
+ *ppThkMgr = (IThunkManager *)pUnk;
+ pUnk->AddRef();
+
+ thkDebugOut((DEB_THUNKMGR, "%sOut OleThunkWOW::GetThunkManager: (%p)\n",
+ NestingLevelString(), pUnk));
+
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: OleThunkWOW::WinExec16, public
+//
+// Synopsis: Callback function for 32-bit OLE to run an application
+//
+// Arguments: [pszCommandLine] - command line for WinExec
+// [usShow] - fShow for WinExec
+//
+// Returns: Appropriate status code
+//
+// History: 27-Jul-94 AlexT Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP OleThunkWOW::WinExec16(
+ LPCOLESTR pszCommandLine,
+ USHORT usShow
+)
+{
+ HRESULT hr;
+ UINT uiSize;
+ VPSTR vpstr16;
+ VPVOID vplpds16;
+ WINEXEC16STRUCT UNALIGNED *lpwes16;
+ ULONG ulRet;
+
+ uiSize = lstrlenW(pszCommandLine) + 1;
+
+ vpstr16 = STACKALLOC16(uiSize*2);
+ if (vpstr16 == 0)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ hr = Convert_LPOLESTR_to_VPSTR(pszCommandLine, vpstr16,
+ uiSize, uiSize*2);
+ if (FAILED(hr))
+ {
+ goto EH_vpstr16;
+ }
+
+ vplpds16 = STACKALLOC16(sizeof(WINEXEC16STRUCT));
+ if (vplpds16 == 0)
+ {
+ hr = E_OUTOFMEMORY;
+ goto EH_vpstr16;
+ }
+
+ lpwes16 = FIXVDMPTR(vplpds16, WINEXEC16STRUCT);
+
+ lpwes16->vpCommandLine = vpstr16;
+ lpwes16->vusShow = usShow;
+
+ RELVDMPTR(vplpds16);
+
+ ulRet = CallbackTo16( gdata16Data.fnWinExec16, vplpds16 );
+ thkDebugOut((DEB_ITRACE,
+ "CallbackTo16(WinExec16) returned %ld\n", ulRet));
+
+ // According to the Windows spec, return values greater than 31 indicate
+ // success.
+
+ if (ulRet > 31)
+ {
+ hr = S_OK;
+ }
+ else if (0 == ulRet)
+ {
+ // 0 indicates lack of some kind of resource
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ {
+ hr = HRESULT_FROM_WIN32(ulRet);
+ }
+
+ STACKFREE16(vplpds16, sizeof(WINEXEC16STRUCT));
+
+ EH_vpstr16:
+ STACKFREE16(vpstr16, uiSize*2);
+
+ Exit:
+ return hr;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: OleThunkWOW::ConvertHwndToFullHwnd
+//
+// Synopsis: Converts a 16 bit HWND into a 32-bit HWND
+//
+// Effects: Since OLE32 doesn't directly link to WOW, this function allows
+// the DDE layer to access the routine that maps 16 bit HWND to
+// full 32-bit HWND's.
+//
+// Arguments: [hwnd] -- HWND to convert
+//
+// History: 8-03-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(HWND) OleThunkWOW::ConvertHwndToFullHwnd(HWND hwnd)
+{
+ return(FULLHWND_32((USHORT)hwnd));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: OleThunkWOW::FreeMetaFile
+//
+// Synopsis: Calls wow to delete a metafile that has memory reserved in
+// the 16 bit address space
+//
+// Effects: Since OLE32 doesn't directly link to WOW, this function allows
+// the DDE layer to access the routine in WOW
+//
+// Arguments: [hmf] -- HANDLE to delete
+//
+// History: 8-03-94 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(BOOL) OleThunkWOW::FreeMetaFile(HANDLE hmf)
+{
+ return(WOWFreeMetafile(hmf));
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: OleThunkWOW::YieldTask16, public
+//
+// Synopsis: Callback function for 32-bit OLE to yield
+//
+// History: 08-Aug-94 Ricksa Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP OleThunkWOW::YieldTask16(void)
+{
+ WOWYield16();
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: OleThunkWOW::DirectedYield, public
+//
+// Synopsis: Does a directed yield in the VDM.
+//
+// History: 08-Aug-94 Rickhi Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP OleThunkWOW::DirectedYield(DWORD dwCalleeTID)
+{
+ WORD hTask16 = WOWHandle16((void *)dwCalleeTID, WOW_TYPE_HTASK);
+
+ thkDebugOut((DEB_ITRACE, "WOWDirectedYield16(%x)\n", hTask16));
+
+ WOWDirectedYield16(hTask16);
+
+ thkDebugOut((DEB_ITRACE, "WOWDirectedYield16() returned\n"));
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: OleThunkWOW::PrepareForCleanup
+//
+// Synopsis: Prepares OLETHK32 for OLE32.DLL's cleanup.
+//
+// Effects: It does this by taking all of the remaining 3216 proxies
+// and marking them such that no callbacks into the 16-bit
+// world are possible.
+//
+// Arguments: -none-
+//
+// History: 24-Aug-94 bobday Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(void) OleThunkWOW::PrepareForCleanup(void)
+{
+ CThkMgr *pcthkmgr;
+
+ if ( TlsThkGetData() != NULL )
+ {
+ pcthkmgr = (CThkMgr*)TlsThkGetThkMgr();
+
+ //
+ // Tell the thkmgr to prepare for cleaning itself up
+ //
+ pcthkmgr->PrepareForCleanup();
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Method: OleThunkWOW::GetAppCompatibilityFlags
+//
+// Synopsis: Used to return the current THK app compatibility flags to
+// OLE32.DLL
+// Arguments: [void] --
+//
+// Requires:
+//
+// Returns: Flags defined in ih\thunkapi.hxx
+//
+// History: 1-11-96 kevinro Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(DWORD) OleThunkWOW::GetAppCompatibilityFlags(void)
+{
+ return(TlsThkGetAppCompatFlags());
+}
diff --git a/private/ole32/olethunk/olethk32/apinot.hxx b/private/ole32/olethunk/olethk32/apinot.hxx
new file mode 100644
index 000000000..be02e1e45
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/apinot.hxx
@@ -0,0 +1,25 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: apinot.hxx
+//
+// Contents: Function header for thunks which are not direct APIs
+//
+// History: 11-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __APINOT_HXX__
+#define __APINOT_HXX__
+
+STDAPI_(DWORD) OleRegGetUserTypeNot(REFCLSID clsid,DWORD dwFormOfType,LPOLESTR *pszUserType);
+STDAPI_(DWORD) CoInitializeNot( LPMALLOC lpMalloc );
+STDAPI_(DWORD) OleInitializeNot( LPMALLOC lpMalloc );
+STDAPI_(DWORD) CoRegisterClassObjectNot( REFCLSID refclsid, LPUNKNOWN punk,
+ DWORD dwClsContext, DWORD flags,
+ LPDWORD lpdwreg );
+STDAPI CoRevokeClassObjectNot( DWORD dwKey );
+
+#endif // #ifndef __APINOT_HXX__
diff --git a/private/ole32/olethunk/olethk32/cthkmgr.cxx b/private/ole32/olethunk/olethk32/cthkmgr.cxx
new file mode 100644
index 000000000..1753c56c4
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/cthkmgr.cxx
@@ -0,0 +1,3031 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: cthkmgr.cxx
+//
+// Contents: cthunkmanager for an apartment
+//
+// Classes: CThkMgr derived from IThunkManager
+//
+// Functions:
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+#include "headers.cxx"
+#pragma hdrstop
+#include <olepfn.hxx>
+#if DBG == 1
+BOOL fDebugDump = FALSE;
+#define DBG_DUMP(x) if (fDebugDump) { x; }
+#else
+#define DBG_DUMP(x)
+#endif
+
+#define PprxNull(pprx) ((pprx).dwPtrVal = 0)
+#define PprxIsNull(pprx) ((pprx).dwPtrVal == 0)
+#define Pprx16(vpv) PROXYPTR((DWORD)vpv, PPRX_16)
+#define Pprx32(pto) PROXYPTR((DWORD)pto, PPRX_32)
+
+//+---------------------------------------------------------------------------
+//
+// Function: ResolvePprx, public
+//
+// Synopsis: Converts a PROXYPTR to a CProxy *
+//
+// Arguments: [ppprx] - PROXYPTR
+//
+// Returns: Pointer or NULL
+//
+// History: 15-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CProxy *ResolvePprx(PROXYPTR *ppprx)
+{
+ if (ppprx->wType == PPRX_32)
+ {
+ return (CProxy *)ppprx->dwPtrVal;
+ }
+ else
+ {
+ // Get a pointer to all of the proxy rather than just the CProxy part
+ return FIXVDMPTR(ppprx->dwPtrVal, THUNK1632OBJ);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReleasePprx, public
+//
+// Synopsis: Releases a resolved PROXYPTR
+//
+// Arguments: [ppprx] - PROXYPTR
+//
+// History: 10-Oct-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void ReleasePprx(PROXYPTR *ppprx)
+{
+ if (ppprx->wType == PPRX_16)
+ {
+ RELVDMPTR(ppprx->dwPtrVal);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::NewHolder, public
+//
+// Synopsis: Creates a new proxy holder
+//
+// Arguments: [dwFlags] - Flags
+//
+// Returns: Holder or NULL
+//
+// History: 16-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+PROXYHOLDER *CThkMgr::NewHolder(DWORD dwFlags)
+{
+ PROXYHOLDER *pph;
+
+ thkDebugOut((DEB_THUNKMGR, "In CThkMgr::NewHolder(0x%X)\n",
+ dwFlags));
+
+ pph = (PROXYHOLDER *)flHolderFreeList.AllocElement();
+ if (pph == NULL)
+ {
+ goto Exit;
+ }
+
+ pph->dwFlags = dwFlags;
+
+ // Start out without any listed proxies
+ pph->cProxies = 0;
+ PprxNull(pph->pprxProxies);
+
+ // Add to list of holders
+ pph->pphNext = _pphHolders;
+ _pphHolders = pph;
+
+ Exit:
+ thkDebugOut((DEB_THUNKMGR, "Out CThkMgr::NewHolder => %p\n",
+ pph));
+
+ return pph;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::AddProxyToHolder, public
+//
+// Synopsis: Adds a new proxy to a holder
+//
+// Arguments: [pph] - Holder
+// [pprxReal] - Proxy
+// [pprx] - Abstract pointer
+//
+// History: 07-Jul-94 DrewB Extracted
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::AddProxyToHolder(PROXYHOLDER *pph,CProxy *pprxReal,
+ PROXYPTR &pprx)
+{
+ thkDebugOut((DEB_THUNKMGR, "In AddProxyToHolder(%p, %p) cProxies %d\n",
+ pph, pprx.dwPtrVal, pph->cProxies));
+
+ thkAssert(ResolvePprx(&pprx) == pprxReal &&
+ (ReleasePprx(&pprx), TRUE));
+
+ // Bump count of held proxies
+ AddRefHolder(pph);
+
+ // Add proxy into list of object proxies
+ thkAssert(PprxIsNull(pprxReal->pprxObject));
+ pprxReal->pprxObject = pph->pprxProxies;
+ pph->pprxProxies = pprx;
+
+ thkAssert(pprxReal->pphHolder == NULL);
+ pprxReal->pphHolder = pph;
+
+ thkDebugOut((DEB_THUNKMGR, "out AddProxyToHolder(%p, %p) cProxies %d\n",
+ pph, pprx.dwPtrVal, pph->cProxies));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::AddRefHolder, public
+//
+// Synopsis: Increments the proxy count for a holder
+//
+// Arguments: [pph] - Holder
+//
+// History: 07-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::AddRefHolder(PROXYHOLDER *pph)
+{
+ pph->cProxies++;
+
+ thkDebugOut((DEB_THUNKMGR, "AddRefHolder(%p) cProxies %d\n",
+ pph, pph->cProxies));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::ReleaseHolder, public
+//
+// Synopsis: Releases a proxy reference on the holder
+// Cleans up the holder if it was the last reference
+//
+// Arguments: [pph] - Holder
+//
+// History: 06-21-94 JohannP Created ReleaseAggregateProxies
+// 07-Jul-94 DrewB Modified
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::ReleaseHolder(PROXYHOLDER *pph)
+{
+ PROXYHOLDER *pphTmp, *pphPrev;
+
+ thkDebugOut((DEB_THUNKMGR, "ReleaseHolder(%p) pre cProxies %d\n",
+ pph, pph->cProxies));
+
+ thkAssert(pph->cProxies > 0);
+
+ // Decrement the holder's proxy count
+ pph->cProxies--;
+
+ if (pph->cProxies == 0)
+ {
+ CProxy *pprxReal;
+ PROXYPTR pprx, pprxNext;
+
+ // All interfaces for the object have been freed so we can
+ // clean up the object
+
+ pprx = pph->pprxProxies;
+ while (!PprxIsNull(pprx))
+ {
+ pprxReal = ResolvePprx(&pprx);
+ pprxNext = pprxReal->pprxObject;
+
+ thkAssert(pprxReal->cRefLocal == 0);
+ thkAssert(pprxReal->pphHolder == pph);
+
+ if (pprx.wType == PPRX_16)
+ {
+ // Releases pointer
+ RemoveProxy1632((VPVOID)pprx.dwPtrVal,
+ (THUNK1632OBJ *)pprxReal);
+ }
+ else
+ {
+ RemoveProxy3216((THUNK3216OBJ *)pprxReal);
+ }
+
+ pprx = pprxNext;
+ }
+
+ // Remove holder from list
+
+ pphPrev = NULL;
+ for (pphTmp = _pphHolders;
+ pphTmp && pphTmp != pph;
+ pphPrev = pphTmp, pphTmp = pphTmp->pphNext)
+ {
+ NULL;
+ }
+
+ // If we didn't find the holder in the holder list then our
+ // list is trashed
+ thkAssert(pphTmp == pph);
+
+ if (pphPrev == NULL)
+ {
+ _pphHolders = pph->pphNext;
+ }
+ else
+ {
+ pphPrev->pphNext = pph->pphNext;
+ }
+
+ flHolderFreeList.FreeElement((DWORD)pph);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::Create
+//
+// Synopsis: static member - creates complete thunkmanager
+//
+// Arguments: [void] --
+//
+// Returns: pointer to cthkmgr
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+CThkMgr *CThkMgr::Create(void)
+{
+ CThkMgr *pcthkmgr = NULL;
+ CMapDwordPtr *pPT1632 = new CMapDwordPtr(MEMCTX_TASK);
+ CMapDwordPtr *pPT3216 = new CMapDwordPtr(MEMCTX_TASK);
+
+ if ( (pPT1632 != NULL)
+ && (pPT3216 != NULL)
+ && (pcthkmgr = new CThkMgr( pPT1632, pPT3216 )) )
+ {
+ // install the new thunkmanager
+ TlsThkSetThkMgr(pcthkmgr);
+ }
+ else
+ {
+ if (pPT1632)
+ {
+ delete pPT1632;
+ }
+ if (pPT3216)
+ {
+ delete pPT3216;
+ }
+ }
+ return pcthkmgr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::CThkMgr
+//
+// Synopsis: private constructor - called by Create
+//
+// Arguments: [pPT1632] -- 16/32 proxy table
+// [pPT3216] -- 32/16 proxy table
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+CThkMgr::CThkMgr(CMapDwordPtr *pPT1632,
+ CMapDwordPtr *pPT3216)
+
+{
+ _cRefs = 1;
+ _thkstate = THKSTATE_NOCALL;
+ _piidnode = NULL;
+
+ _pProxyTbl1632 = pPT1632;
+ _pProxyTbl3216 = pPT3216;
+
+ _pphHolders = NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::~CThkMgr
+//
+// Synopsis: destructor
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+CThkMgr::~CThkMgr()
+{
+ PROXYHOLDER *pph;
+ PIIDNODE pin;
+
+ thkDebugOut((DEB_ITRACE, "_IN CThkMgr::~CThkMgr()\n"));
+
+ RemoveAllProxies();
+ delete _pProxyTbl1632;
+ delete _pProxyTbl3216;
+
+ // Clean up IID requests
+#if DBG == 1
+ if (_piidnode != NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: IID requests active at shutdown\n"));
+ }
+#endif
+
+ while (_piidnode != NULL)
+ {
+ pin = _piidnode->pNextNode;
+
+ thkDebugOut((DEB_IWARN, "IID request leak: %p {%s}\n",
+ _piidnode, IidOrInterfaceString(_piidnode->piid)));
+
+ flRequestFreeList.FreeElement((DWORD)_piidnode);
+
+ _piidnode = pin;
+ }
+
+#if DBG == 1
+ if (_pphHolders != NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: Proxy holders active at shutdown\n"));
+ }
+#endif
+
+ // Clean up any proxy holders
+ while (_pphHolders)
+ {
+ pph = _pphHolders->pphNext;
+
+ thkDebugOut((DEB_IWARN, "Proxy holder leak: %p {%d, 0x%X}\n",
+ _pphHolders, _pphHolders->cProxies,
+ _pphHolders->dwFlags));
+
+ flHolderFreeList.FreeElement((DWORD)_pphHolders);
+
+ _pphHolders = pph;
+ }
+ thkDebugOut((DEB_ITRACE, "OUT CThkMgr::~CThkMgr()\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::RemoveAllProxies, public
+//
+// Synopsis: Removes all live proxies from the proxy tables
+//
+// History: 01-Dec-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::RemoveAllProxies(void)
+{
+ POSITION pos;
+ DWORD dwKey;
+ VPVOID vpv;
+
+ thkDebugOut((DEB_ITRACE, "_IN CThkMgr::RemoveAllProxies()\n"));
+
+ // Make sure that we disable 3216 proxies first to guard against calling
+ // back into 16 bit land.
+
+#if DBG == 1
+ DWORD dwCount;
+
+ dwCount = _pProxyTbl3216->GetCount();
+
+ if (dwCount > 0)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: %d 3216 proxies left\n", dwCount));
+ }
+#endif
+
+ // delete the 3216 proxy table
+ while (pos = _pProxyTbl3216->GetStartPosition())
+ {
+ THUNK3216OBJ *pto3216;
+
+ _pProxyTbl3216->GetNextAssoc(pos, dwKey, (void FAR* FAR&) pto3216);
+
+ thkDebugOut((DEB_IWARN, "3216: %p {%d,%d, %p, %p} %s\n",
+ pto3216, pto3216->cRefLocal, pto3216->cRef,
+ pto3216->vpvThis16, pto3216->pphHolder,
+ IidIdxString(pto3216->iidx)));
+
+ pto3216->grfFlags |= PROXYFLAG_CLEANEDUP;
+
+ RemoveProxy3216(pto3216);
+ }
+
+#if DBG == 1
+ dwCount = _pProxyTbl1632->GetCount();
+
+ if (dwCount > 0)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: %d 1632 proxies left\n", dwCount));
+ }
+#endif
+
+ // delete the 1632 proxy table
+ while (pos = _pProxyTbl1632->GetStartPosition())
+ {
+ THUNK1632OBJ *pto1632;
+
+ _pProxyTbl1632->GetNextAssoc(pos, dwKey, (void FAR* FAR&) vpv);
+
+ pto1632 = FIXVDMPTR(vpv, THUNK1632OBJ);
+
+#if DBG == 1
+ thkDebugOut((DEB_IWARN, "1632: %p {%d,%d, %p, %p} %s\n",
+ vpv, pto1632->cRefLocal, pto1632->cRef,
+ pto1632->punkThis32, pto1632->pphHolder,
+ IidIdxString(pto1632->iidx)));
+#endif
+ //
+ // Determine if this is a 'special' object that we know we want
+ // to release. If it is, then remove all of the references this
+ // proxy has on it.
+ //
+ if (CoQueryReleaseObject(pto1632->punkThis32) == NOERROR)
+ {
+ thkDebugOut((DEB_WARN,
+ "1632: %p is recognized Releasing object %d times\n",
+ pto1632->punkThis32,pto1632->cRef));
+
+ while (pto1632->cRef)
+ {
+ IUnknown *punk;
+
+ pto1632->cRef--;
+ punk = pto1632->punkThis32;
+
+ RELVDMPTR(vpv);
+
+ if (punk->Release() == 0)
+ {
+ break;
+ }
+
+ pto1632 = FIXVDMPTR(vpv, THUNK1632OBJ);
+ }
+ }
+
+ // Releases pointer
+ RemoveProxy1632(vpv, pto1632);
+ }
+
+ thkDebugOut((DEB_ITRACE, "OUT CThkMgr::RemoveAllProxies()\n"));
+}
+
+// *** IUnknown methods ***
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::QueryInterface
+//
+// Synopsis: QueryInterface on the thunkmanager itself
+//
+// Arguments: [riid] -- IID of interface to return
+// [ppvObj] -- Interface return
+//
+// Returns: HRESULT
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CThkMgr::QueryInterface (REFIID riid, LPVOID FAR* ppvObj)
+{
+ if (IsBadWritePtr(ppvObj, sizeof(void *)))
+ {
+ return E_INVALIDARG;
+ }
+
+ *ppvObj = NULL;
+
+ // There is no IID_IThunkManager because nobody needs it
+
+ if (IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppvObj = (IUnknown *) this;
+ AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Methode: CThkMgr::AddRef
+//
+// Synopsis: Adds a reference
+//
+// Returns: New ref count
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CThkMgr::AddRef ()
+{
+ InterlockedIncrement( &_cRefs );
+ return _cRefs;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Methode: CThkMgr::Release
+//
+// Synopsis: Releases a reference
+//
+// Returns: New ref count
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_(ULONG) CThkMgr::Release()
+{
+ if (InterlockedDecrement( &_cRefs ) == 0)
+ {
+
+ return 0;
+ }
+ return _cRefs;
+}
+
+// *** IThunkManager methods ***
+//
+//
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::IsIIDRequested
+//
+// Synopsis: checks if given refiid was requested by WOW
+//
+// Arguments: [riid] -- refiid
+//
+// Returns: true if requested by 16 bit
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP_ (BOOL) CThkMgr::IsIIDRequested(REFIID riid)
+{
+ PIIDNODE piidnode = _piidnode;
+ BOOL fRet = FALSE;
+
+ while (piidnode)
+ {
+ if (*piidnode->piid == riid)
+ {
+ fRet = TRUE;
+ break;
+ }
+
+ piidnode = piidnode->pNextNode;
+ }
+
+ thkDebugOut((DEB_THUNKMGR, "IsIIDRequested(%s) => %d\n",
+ GuidString(&riid), fRet));
+
+ return fRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::IsCustom3216Proxy, public
+//
+// Synopsis: Attempts to identify the given IUnknown as a 32->16 proxy
+// and also checks whether it is a thunked interface or not
+//
+// Arguments: [punk] - Object
+//
+// Returns: BOOL
+//
+// History: 11-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(BOOL) CThkMgr::IsCustom3216Proxy(IUnknown *punk,
+ REFIID riid)
+{
+ return !IsIIDSupported(riid) && IsProxy3216(punk) != 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::IsIIDSupported
+//
+// Synopsis: Return whether the given interface is thunked or not
+//
+// Arguments: [riid] -- Interface
+//
+// Returns: BOOL
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+BOOL CThkMgr::IsIIDSupported(REFIID riid)
+{
+ return IIDIDX_IS_INDEX(IidToIidIdx(riid));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::AddIIDRequest
+//
+// Synopsis: adds the refiid to the request list
+//
+// Arguments: [riid] -- Interface
+//
+// Returns: true on success
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+BOOL CThkMgr::AddIIDRequest(REFIID riid)
+{
+ PIIDNODE piidnode = _piidnode;
+
+ thkAssert(!IsIIDSupported(riid));
+
+ // create a new node and add at front
+ piidnode = (PIIDNODE)flRequestFreeList.AllocElement();
+ if (piidnode == NULL)
+ {
+ return FALSE;
+ }
+
+ piidnode->pNextNode = _piidnode;
+ _piidnode = piidnode;
+
+ // IID requests are only valid for the lifetime of the call that
+ // requested a custom interface, so there's no need to copy
+ // the IID's memory since it must remain valid for the same time
+ // period
+ piidnode->piid = (IID *)&riid;
+
+ thkDebugOut((DEB_THUNKMGR, "AddIIDRequest(%s)\n", GuidString(&riid)));
+
+ return TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::RemoveIIDRequest
+//
+// Synopsis: removes a request for the request list
+//
+// Arguments: [riid] -- Interface
+//
+// Returns: true on success
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void CThkMgr::RemoveIIDRequest(REFIID riid)
+{
+ PIIDNODE piidnode;
+ PIIDNODE pinPrev;
+
+ thkAssert(!IsIIDSupported(riid));
+
+ pinPrev = NULL;
+ piidnode = _piidnode;
+ while (piidnode)
+ {
+ if (*piidnode->piid == riid)
+ {
+ break;
+ }
+
+ pinPrev = piidnode;
+ piidnode = piidnode->pNextNode;
+ }
+
+ thkAssert(piidnode != NULL && "RemoveIIDRequest: IID not found");
+
+ thkDebugOut((DEB_THUNKMGR, "RemoveIIDRequest(%s)\n", GuidString(&riid)));
+
+ if (pinPrev == NULL)
+ {
+ _piidnode = piidnode->pNextNode;
+ }
+ else
+ {
+ pinPrev->pNextNode = piidnode->pNextNode;
+ }
+
+ flRequestFreeList.FreeElement((DWORD)piidnode);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::CanGetNewProxy1632
+//
+// Synopsis: Preallocates proxy memory
+//
+// Arguments: [iidx] - Custom interface or known index
+//
+// Returns: vpv pointer if proxy is available, fails otherwise
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+VPVOID CThkMgr::CanGetNewProxy1632(IIDIDX iidx)
+{
+ VPVOID vpv;
+ THUNK1632OBJ UNALIGNED *pto;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn CanGetNewProxy1632(%s)\n",
+ NestingLevelString(), IidIdxString(iidx)));
+
+ // Allocate proxy memory
+ vpv = (VPVOID)flFreeList16.AllocElement();
+ if (vpv == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: Failed to allocate memory "
+ "for 16-bit proxies\n"));
+ goto Exit;
+ }
+
+ // Add custom interface request if necessary
+ if (vpv && IIDIDX_IS_IID(iidx))
+ {
+ // add the request for the unknown interface
+ if ( !AddIIDRequest(*IIDIDX_IID(iidx)) )
+ {
+ flFreeList16.FreeElement( (DWORD)vpv );
+ vpv = 0;
+ }
+ }
+
+ // Set up the preallocated proxy as a temporary proxy so that
+ // we can hand it out for nested callbacks
+ pto = FIXVDMPTR(vpv, THUNK1632OBJ);
+ thkAssert(pto != NULL);
+
+ pto->pfnVtbl = gdata16Data.atfnProxy1632Vtbl;
+ pto->cRefLocal = 0;
+ pto->cRef = 0;
+ pto->iidx = iidx;
+ pto->punkThis32 = NULL;
+ pto->pphHolder = NULL;
+ PprxNull(pto->pprxObject);
+ pto->grfFlags = PROXYFLAG_TEMPORARY;
+#if DBG == 1
+ // Deliberately make this an invalid proxy. We want it to be used
+ // in as few places as possible
+ pto->dwSignature = PSIG1632TEMP;
+#endif
+
+ RELVDMPTR(vpv);
+
+ Exit:
+ thkDebugOut((DEB_THUNKMGR, "%sOut CanGetNewProxy1632: %p\n",
+ NestingLevelString(), vpv));
+
+ return vpv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FreeNewProxy1632
+//
+// Synopsis: frees unused preallocated proxies
+//
+// Arguments: [iidx] - Custom interface or known index
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void CThkMgr::FreeNewProxy1632(VPVOID vpv, IIDIDX iidx)
+{
+ thkDebugOut((DEB_THUNKMGR, "%sIn FreeNewProxy1632(%s)\n",
+ NestingLevelString(), IidIdxString(iidx)));
+
+ thkAssert(vpv != 0);
+
+ if (IIDIDX_IS_IID(iidx))
+ {
+ // remove the request for the unknown interface
+ RemoveIIDRequest(*IIDIDX_IID(iidx));
+ }
+
+#if DBG == 1
+ // Ensure that we're not getting rid of a temporary proxy that's
+ // in use
+ THUNK1632OBJ UNALIGNED *pto;
+
+ pto = FIXVDMPTR(vpv, THUNK1632OBJ);
+ if (pto->grfFlags & PROXYFLAG_TEMPORARY)
+ {
+ thkAssert(pto->cRefLocal == 0 && pto->cRef == 0);
+ }
+ RELVDMPTR(vpv);
+#endif
+
+ // add element to free list
+ flFreeList16.FreeElement( (DWORD)vpv );
+
+ thkDebugOut((DEB_THUNKMGR, "%sOut FreeNewProxy1632\n",
+ NestingLevelString()));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::IsProxy1632
+//
+// Synopsis: checks if given object is an 16/32 object
+//
+// Arguments: [vpvObj16] -- Object to check
+//
+// Returns: 32-bit object being proxied or NULL
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+IUnknown *CThkMgr::IsProxy1632(VPVOID vpvObj16)
+{
+ VPVOID vpvProxy;
+ DWORD dwKey;
+ POSITION pos;
+ THUNK1632OBJ UNALIGNED *pto;
+ THUNKINFO ti;
+
+ // First check and see if the vtable pointer is the one for
+ // 16-bit proxies. If it's not, this can't be a proxy
+ // Since we don't know anything about this pointer, we need
+ // to do safe translation
+ pto = (THUNK1632OBJ UNALIGNED *)
+ GetReadPtr16(&ti, vpvObj16, sizeof(THUNK1632OBJ));
+ if (pto != NULL && pto->pfnVtbl == gdata16Data.atfnProxy1632Vtbl)
+ {
+ // The proxy may be freed memory or just random memory which
+ // happens to have the right value, so make sure that it's
+ // a proxy by looking it up in the proxy table
+
+ pos = _pProxyTbl1632->GetStartPosition();
+ while (pos)
+ {
+ _pProxyTbl1632->GetNextAssoc(pos, dwKey,
+ (void FAR* FAR&) vpvProxy);
+ if (vpvProxy == vpvObj16)
+ {
+ RELVDMPTR(vpvObj16);
+ return (IUnknown *)dwKey;
+ }
+ }
+
+ // Check to see if we're returning no for what we think is
+ // a valid proxy
+ // It's possible for this to occur if somebody made a copy
+ // of a proxy's memory, but in general this assert should
+ // be extremely unlikely
+ thkAssert(pto->dwSignature != PSIG1632);
+ }
+
+ if (pto != NULL)
+ {
+ RELVDMPTR(vpvObj16);
+ }
+
+ return NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FindProxy1632
+//
+// Synopsis: retrieves a 16/32 object (most cases proxy) for a given
+// 32 bit IUnknown, it can be a real object -> shortcut
+//
+// Arguments: [vpvPrealloc] -- preallocated proxy
+// [punkThis32] -- 32 bit object to be proxied
+// [iidx] - Interface index or IID
+// [pfst] - Return what kind of object was found
+//
+// Returns: 16/32 object (proxy or real object)
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+VPVOID CThkMgr::FindProxy1632(VPVOID vpvPrealloc,
+ IUnknown *punkThis32,
+ IIDIDX iidx,
+ DWORD *pfst)
+{
+ THUNK1632OBJ UNALIGNED *pto;
+ VPVOID vpv;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn FindProxy1632(%p, %p, %s)\n",
+ NestingLevelString(), vpvPrealloc, punkThis32,
+ IidIdxString(iidx)));
+ DebugIncrementNestingLevel();
+
+ thkAssert(punkThis32 != NULL);
+
+#if DBG == 1
+ // Ensure that we're not reusing a temporary proxy that's in use
+ if (vpvPrealloc)
+ {
+ pto = FIXVDMPTR(vpvPrealloc, THUNK1632OBJ);
+ if (pto->grfFlags & PROXYFLAG_TEMPORARY)
+ {
+ thkAssert(pto->cRefLocal == 0 && pto->cRef == 0);
+ }
+ RELVDMPTR(vpvPrealloc);
+ }
+#endif
+
+ // If we preallocated a proxy with an IID then a request was added
+ // in CanGetNewProxy. Clean it up now
+ if (vpvPrealloc != 0 && IIDIDX_IS_IID(iidx))
+ {
+ RemoveIIDRequest(*IIDIDX_IID(iidx));
+ }
+
+ // Check the proxy table for an existing proxy for the given object pointer
+ // the 32 bit pointer is the key to the 16/32 proxy
+ vpv = LookupProxy1632(punkThis32);
+ if (vpv != NULL)
+ {
+ thkDebugOut((DEB_THUNKMGR,
+ "%sFindProxy1632 found existing proxy,(%p)->%p\n",
+ NestingLevelString(), punkThis32, vpv));
+
+ // We found an existing proxy, so reuse it
+
+ pto = FIXVDMPTR(vpv, THUNK1632OBJ);
+
+ // If a proxy's refcount is zero, it must be part of an aggregate
+ thkAssert(pto->cRefLocal > 0 ||
+ (pto->pphHolder != NULL &&
+ (pto->pphHolder->dwFlags & PH_AGGREGATE) != 0));
+
+ //Note: IIDIDXs are related to interfaces in our tables
+ // we have our table organized such that more derived
+ // interfaces are higher than less derived
+ // * Custom interfaces will have an IID rather than an index
+ // and will never be promoted above IUnknown in the
+ // below statement (johannp)
+ if (IIDIDX_IS_INDEX(iidx) &&
+ IIDIDX_INDEX(iidx) > IIDIDX_INDEX(pto->iidx))
+ {
+ // 16-bit proxy vtables are all the same so there's no
+ // need to manipulate the vtable pointer here as we
+ // do in the 32-bit case
+
+ pto->iidx = iidx;
+ }
+
+ RELVDMPTR(vpv);
+
+ // AddRef the proxy we found since we're passing out a new reference
+ AddRefProxy1632(vpv);
+
+ if (pfst)
+ {
+ *pfst = FST_USED_EXISTING;
+ }
+
+ goto Exit;
+ }
+
+ // Check and see whether the object we're supposed to proxy is
+ // actually a proxy itself
+ if ( (vpv = IsProxy3216(punkThis32)) != NULL)
+ {
+ thkDebugOut((DEB_THUNKMGR,
+ "%sFindProxy1632 shortcut proxy,(%p)->%p\n",
+ NestingLevelString(), punkThis32, vpv));
+
+ // We've discovered that the object that we're supposed to
+ // proxy is actually a proxy itself. In that case, we can
+ // avoid creating a full-circle proxy chain by returning
+ // the real pointer rather than creating a new proxy
+ //
+ // If we're shortcutting proxies for in parameters, we
+ // don't need to manipulate the reference count
+ // In the out parameter case, though, we're actually transferring
+ // ownership so we need to AddRef the real object and clean
+ // up the proxy we shortcut around
+ if (IsOutParamObj())
+ {
+ THKSTATE thkstate;
+
+ // We want to temporarily suspend our out state since
+ // we want this AddRef to really occur if it comes
+ // back to a proxy
+ thkstate = GetThkState();
+ SetThkState(THKSTATE_NOCALL);
+
+ AddRefOnObj16(vpv);
+
+ SetThkState(thkstate);
+
+ // Release the ignored proxy
+ // This avoids leaking proxies in round-trip calls
+ // where nobody holds a pointer to the proxy
+ ReleaseProxy3216((THUNK3216OBJ *)punkThis32);
+ }
+
+ if (pfst)
+ {
+ *pfst = FST_SHORTCUT;
+ }
+
+ goto Exit;
+ }
+
+ // We didn't find an existing proxy and the object to be proxied
+ // is a real object so we need to fill out a new proxy for it
+ // We might have a preallocated proxy provided; if we don't
+ // we need to go to the free list and get a new one
+
+ if (vpvPrealloc != NULL)
+ {
+ vpv = vpvPrealloc;
+
+ // If we successfully created a proxy using the preallocated
+ // proxy, mark the preallocated proxy as used so it's not cleaned up
+ vpvPrealloc = NULL;
+ }
+ else
+ {
+ vpv = (VPVOID)flFreeList16.AllocElement();
+ }
+
+ if (vpv != NULL)
+ {
+ // Put the new proxy in the proxy list
+ if (!_pProxyTbl1632->SetAt((DWORD)punkThis32, (void *&)vpv))
+ {
+ // Note that we can put vpv on the free list even it's
+ // the preallocated proxy since that's what the prealloc
+ // cleanup does
+ flFreeList16.FreeElement(vpv);
+
+ vpv = NULL;
+ goto Exit;
+ }
+
+ if (IIDIDX_IS_IID(iidx))
+ {
+ // We're creating a proxy for a custom interface
+ // so just hand out an IUnknown
+ iidx = INDEX_IIDIDX(THI_IUnknown);
+ }
+
+ pto = FIXVDMPTR(vpv, THUNK1632OBJ);
+ thkAssert(pto != NULL);
+
+ pto->pfnVtbl = gdata16Data.atfnProxy1632Vtbl;
+ pto->cRefLocal = 1;
+ pto->cRef = (IsOutParamObj()) ? 1 : 0;
+ pto->iidx = iidx;
+ pto->punkThis32 = punkThis32;
+ pto->pphHolder = NULL;
+ PprxNull(pto->pprxObject);
+ pto->grfFlags = PROXYFLAG_NORMAL;
+
+#if DBG == 1
+ pto->dwSignature = PSIG1632;
+#endif
+
+ RELVDMPTR(vpv);
+
+ if (pfst)
+ {
+ *pfst = FST_CREATED_NEW;
+ }
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%sFindProxy1632 added new proxy, %s (%p)->%p (%d,%d)\n",
+ NestingLevelString(),
+ inInterfaceNames[pto->iidx].pszInterface,
+ punkThis32, vpv,
+ pto->cRefLocal, pto->cRef));
+ }
+
+ Exit:
+ // If we didn't use the preallocated proxy for some reason
+ // then put it back on the free list
+ if (vpvPrealloc != NULL)
+ {
+ flFreeList16.FreeElement( (DWORD)vpvPrealloc );
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut FindProxy1632: (%p)->%p\n",
+ NestingLevelString(), punkThis32, vpv));
+
+ return vpv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FindAggregate1632
+//
+// Synopsis: retrieves an aggregate for 1632 with the given cntrl. unknown
+//
+// Arguments: [vpvPrealloc] - Preallocated proxy or NULL
+// [punkOuter3216] -- the controlling unknown
+// [punkThis32] -- the 32 bit interface - key
+// [iidx] -- Index or IID of interface
+//
+// Returns: 16/32 proxy object
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+VPVOID CThkMgr::FindAggregate1632(VPVOID vpvPrealloc,
+ IUnknown *punkOuter3216,
+ IUnknown *punkThis32,
+ IIDIDX iidx)
+{
+ THUNK1632OBJ UNALIGNED *pto1632;
+ VPVOID vpv;
+ DWORD fst;
+ BOOL fMarkPUnk1632 = FALSE;
+
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%sIn FindAggregate1632(%p, %p, %p, %s)\n",
+ NestingLevelString(), vpvPrealloc, punkOuter3216, punkThis32,
+ IidIdxString(iidx)));
+ DebugIncrementNestingLevel();
+
+ thkAssert(punkOuter3216 != NULL && punkThis32 != NULL);
+
+ // Get back an object for the object to be proxied
+ // This may be a proxy or a real object from a shortcut
+ vpv = FindProxy1632(vpvPrealloc, punkThis32, iidx, &fst);
+ if (vpv == 0)
+ {
+ goto Exit;
+ }
+
+ // If we got an object and it's not a proxy, we're done
+ // There's nothing we can do since we can't link a real object to
+ // a holder; we can only hope that things work out right
+ if (fst & FST_OBJECT_STATUS)
+ {
+ goto Exit;
+ }
+
+ // Otherwise, we need to set up a holder for whatever proxies we
+ // have
+
+ THUNK3216OBJ *ptoUnkOuter3216;
+ PROXYHOLDER *pph;
+ VPVOID vpvProxiedUnkOuter3216;
+
+ // Determine whether the outer unknown is a proxy or not
+ vpvProxiedUnkOuter3216 = IsProxy3216(punkOuter3216);
+
+ // This cast is only valid if vpvProxiedUnkOuter3216 is non-NULL
+ ptoUnkOuter3216 = (THUNK3216OBJ *)punkOuter3216;
+
+ if (vpvProxiedUnkOuter3216 != 0 && ptoUnkOuter3216->pphHolder != NULL)
+ {
+ // Use the existing holder if there is one
+ pph = ptoUnkOuter3216->pphHolder;
+ }
+ else
+ {
+ // Create a new holder
+ pph = NewHolder(PH_AGGREGATE);
+ if (pph == NULL)
+ {
+ FreeProxy1632(punkThis32);
+ vpv = NULL;
+ goto Exit;
+ }
+
+ // If the outer unknown is a proxy we know its holder hasn't
+ // been set, so add it to the holder we created
+ if (vpvProxiedUnkOuter3216 != 0)
+ {
+ AddProxyToHolder(pph, ptoUnkOuter3216, Pprx32(ptoUnkOuter3216));
+ // Mark the pUnkOuter3216 as such; needed for aggregation rules
+ thkDebugOut((DEB_THUNKMGR,
+ "%s FindAggregate1632,(%p)->%p marked as pUnkOuter3216\n",
+ NestingLevelString(), ptoUnkOuter3216,Pprx32(ptoUnkOuter3216) ));
+ ptoUnkOuter3216->grfFlags |= PROXYFLAG_PUNKOUTER;
+ fMarkPUnk1632 = TRUE;
+ }
+ }
+
+ thkAssert(vpvProxiedUnkOuter3216 == 0 || ptoUnkOuter3216->pphHolder == pph);
+
+ // Add the new interface to the holder
+ // Since this proxy was just created, we know its holder
+ // hasn't been set yet
+ pto1632 = FIXVDMPTR(vpv, THUNK1632OBJ);
+ AddProxyToHolder(pph, pto1632, Pprx16(vpv));
+ if (fMarkPUnk1632)
+ {
+ pto1632->grfFlags |= PROXYFLAG_PUNK;
+ thkDebugOut((DEB_THUNKMGR,
+ "%s FindAggregate1632,(%p)->%p marked as pUnk1632\n",
+ NestingLevelString(), punkThis32, vpv));
+ }
+
+ RELVDMPTR(vpv);
+
+ Exit:
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR,
+ "%sOut FindAggregate1632,(%p)->%p\n",
+ NestingLevelString(), punkThis32, vpv));
+
+ return vpv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::QueryInterfaceProxy1632
+//
+// Synopsis: QueryInterface on 32 bit object
+//
+// Arguments: [vpvThis16] -- Proxy
+// [refiid] -- IID
+// [ppv] -- new object (proxy or real object) for queried
+// interface
+//
+// Returns: HRESULT
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+SCODE CThkMgr::QueryInterfaceProxy1632(VPVOID vpvThis16,
+ REFIID refiidIn,
+ LPVOID *ppv)
+{
+ SCODE scRet;
+ THUNK1632OBJ UNALIGNED *ptoThis;
+ THUNK1632OBJ UNALIGNED *ptoProxy;
+ VPVOID vpvProxy;
+ IIDIDX iidx;
+ IUnknown *punk32, *punkThis32;
+ DWORD fst;
+ BOOL fNotSupported = FALSE;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn QueryInterfaceProxy1632(%p)\n",
+ NestingLevelString(), vpvThis16));
+ DebugIncrementNestingLevel();
+
+ ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
+ thkAssert(ptoThis != NULL);
+
+ // Don't validate temporary proxies
+ // We need to support temporary proxies in this method since
+ // Corel Draw 5.0 QI's on a temporary proxy
+ //
+ // BUGBUG - There are many potential problems with object identity,
+ // for example QI'ing where the return is the same object as the
+ // souce. Since the source is temporary it doesn't exist in the
+ // tables so identity will be broken. Of course, this won't cause
+ // any regressions for apps which don't use temporary proxies,
+ // so I think this is acceptable
+ if ((ptoThis->grfFlags & PROXYFLAG_TEMPORARY) == 0)
+ {
+ DebugValidateProxy1632(vpvThis16);
+ }
+ else
+ {
+ thkDebugOut((DEB_WARN, "WARNING: QueryInterfaceProxy1632 on "
+ "temporary %s proxy\n", IidIdxString(ptoThis->iidx)));
+ }
+
+ *ppv = NULL;
+ // Note: Ikitaro queries for IViewObject and uses it as IViewObject2
+ REFIID refiid = ( (TlsThkGetAppCompatFlags() & OACF_IVIEWOBJECT2) && IsEqualIID(refiidIn, IID_IViewObject))
+ ? IID_IViewObject2 : refiidIn;
+
+#if DBG==1
+ if ( (TlsThkGetAppCompatFlags() & OACF_IVIEWOBJECT2)
+ && IsEqualIID(refiidIn, IID_IViewObject))
+ {
+ thkDebugOut((DEB_WARN,"Ikitaro: return IViewObject2 instead IViewObject\n"));
+ }
+#endif // DBG==1
+
+ iidx = IidToIidIdx(refiid);
+
+ // see if this a supported interface
+ if (IIDIDX_IS_IID(iidx))
+ {
+ // add the request for the unknown interface
+ if (!AddIIDRequest(refiid))
+ {
+ RELVDMPTR(vpvThis16);
+ return E_OUTOFMEMORY;
+ }
+ fNotSupported = TRUE;
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%sQueryInterfaceProxy1632: unknown iid %s\n",
+ NestingLevelString(), IidIdxString(iidx)));
+ }
+
+ // We force the object we're QI'ing to have a holder so that
+ // all objects have object refcounting. This should only be
+ // necessary for aggregation but it seems that some apps rely
+ // on all objects having aggregation-like refcounting qualities
+ // BobDay identified PowerPoint as one
+ // We only want to do this in cases where we've identified it's
+ // necessary, which presently is only for
+ // IDataObject
+ // so we only do it then
+
+ if (ptoThis->pphHolder == NULL &&
+ (ptoThis->grfFlags & PROXYFLAG_TEMPORARY) == 0 &&
+ IsEqualIID(refiid, IID_IDataObject))
+ {
+ PROXYHOLDER *pph;
+
+ pph = NewHolder(PH_NONAGGREGATE);
+ if (pph == NULL)
+ {
+ RELVDMPTR(vpvThis16);
+ scRet = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ AddProxyToHolder(pph, ptoThis, Pprx16(vpvThis16));
+
+ // It's not necessary to clean this up if later calls fail
+ // since it doesn't alter the lifetime of the proxy if there's
+ // only one proxy for the holder
+ }
+
+ if (ptoThis->grfFlags & PROXYFLAG_TEMPORARY)
+ {
+ punkThis32 = *(IUnknown **)ptoThis->punkThis32;
+ }
+ else
+ {
+ punkThis32 = ptoThis->punkThis32;
+ }
+
+ RELVDMPTR(vpvThis16);
+
+ if (punkThis32 == NULL)
+ {
+ scRet = E_NOINTERFACE;
+ goto Exit;
+ }
+ thkDebugOut((DEB_THUNKMGR,
+ "%sQueryInterfaceProxy1632: on iid %s\n",
+ NestingLevelString(), IidIdxString(iidx)));
+
+ scRet = punkThis32->QueryInterface(refiid, (void **)&punk32);
+
+ if (FAILED(scRet))
+ {
+ goto Exit;
+ }
+
+ SetThkState(THKSTATE_INVOKETHKOUT16);
+
+ vpvProxy = FindProxy1632(NULL, punk32, iidx, &fst);
+ if (vpvProxy == NULL)
+ {
+ // we were unable to create a proxy for the new interface so
+ // clean up the interface and quit
+
+ punk32->Release();
+
+ scRet = E_OUTOFMEMORY;
+ goto ResetState;
+ }
+
+ if (fNotSupported && !(fst & FST_SHORTCUT))
+ {
+ // proxy of unknow interface can not be promoted
+ // clean up the interface and quit
+
+ ReleaseProxy1632(vpvProxy);
+
+ scRet = E_NOINTERFACE;
+ goto ResetState;
+ }
+
+
+ *ppv = (LPVOID)vpvProxy;
+
+ // If we're returning a proxy, we need to make sure that
+ // it is listed in the proxy holder for this object
+ if (fst & FST_PROXY_STATUS)
+ {
+ // We are returning a proxy. If its holder isn't set,
+ // add it to the holder of the object that was QI'ed
+
+ // Reconvert 16:16 pointer since calls may have caused
+ // nested calls and flat remapping
+ ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
+
+ ptoProxy = FIXVDMPTR(vpvProxy, THUNK1632OBJ);
+ if (ptoProxy->pphHolder == NULL)
+ {
+ if (ptoThis->pphHolder != NULL)
+ {
+ AddProxyToHolder(ptoThis->pphHolder, ptoProxy,
+ Pprx16(vpvProxy));
+ }
+ }
+ else if (ptoThis->pphHolder == NULL &&
+ (ptoThis->grfFlags & PROXYFLAG_TEMPORARY) == 0)
+ {
+ // ptoThis may not have a holder because it was produced
+ // by a non-QI method such as IOleItemContainer::GetObject
+ // If we find that an interface returned by it does
+ // have a holder, hook it up to the holder
+
+ // It shouldn't be necessary to do anything unusual with
+ // local references even if ptoThis is really part of an
+ // aggregate since ptoThis must have been produced by
+ // a method where aggregation can't be assumed and all
+ // references must be released on ptoThis itself
+ AddProxyToHolder(ptoProxy->pphHolder, ptoThis,
+ Pprx16(vpvThis16));
+ }
+
+#if DBG == 1
+ // It's possible for holders to not match because of the above
+ // case with interfaces being returned from non-QI methods
+ // The lifetime for such interfaces must be defined by
+ // strong references, though, so it's not catastrophic
+ // Still, we'd like to be aware of such mismatches just in case
+ if (ptoProxy->pphHolder != ptoThis->pphHolder)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: QueryInterfaceProxy1632: "
+ "this %p has holder %p, proxy %p has holder %p\n",
+ vpvThis16, ptoThis->pphHolder,
+ vpvProxy, ptoProxy->pphHolder));
+ }
+#endif
+
+ RELVDMPTR(vpvThis16);
+ RELVDMPTR(vpvProxy);
+ }
+
+ ResetState:
+ SetThkState(THKSTATE_NOCALL);
+
+ Exit:
+ // Clean up our custom interface request if there is one
+ if (IIDIDX_IS_IID(iidx))
+ {
+ RemoveIIDRequest(refiid);
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR,
+ "%sOut QueryInterfaceProxy1632(%p) => %p, 0x%08lX\n",
+ NestingLevelString(), vpvThis16, *ppv, scRet));
+
+ return scRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::LocalAddRefProxy, public
+//
+// Synopsis: Increment a proxy's local refcount
+//
+// Arguments: [pprx] - Proxy
+//
+// History: 02-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::LocalAddRefProxy(CProxy *pprx)
+{
+ pprx->cRefLocal++;
+
+ thkDebugOut(( DEB_THUNKMGR,
+ "%s LocalAddRefProxy1632 <%08lX> RefCounts: %d,%d\n",
+ NestingLevelString(),
+ pprx, pprx->cRefLocal, pprx->cRef ));
+
+ // Check for proxies rising from the dead
+
+ // If we're not part of an aggregate our refcount shouldn't be
+ // one or lower. If it is we're reviving a dead proxy which won't
+ // be in the proxy list and this could cause problems
+ //
+ // Note: With the new proxy stabilization code this can and does
+ // happen so this is only a debug out
+#if DBG == 1
+ if (!(pprx->cRefLocal > 1 ||
+ (pprx->pphHolder != NULL &&
+ (pprx->pphHolder->dwFlags & PH_AGGREGATE) != 0)))
+ {
+ thkDebugOut((DEB_WARN, "WARNING: Proxy %p unlisted with refs %d,%d\n",
+ pprx, pprx->cRefLocal, pprx->cRef));
+ }
+#endif
+
+ if (pprx->cRefLocal == 1)
+ {
+ // We just resurrected a proxy with a zero refcount,
+ // so increment its holder's proxy count since it
+ // was decremented when the proxy released to zero
+ if (pprx->pphHolder != NULL)
+ {
+ AddRefHolder(pprx->pphHolder);
+ }
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::LockProxy, public
+//
+// Synopsis: Locks a proxy so that it can't be freed
+//
+// Arguments: [pprx] - Proxy
+//
+// History: 11-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::LockProxy(CProxy *pprx)
+{
+ pprx->grfFlags |= PROXYFLAG_LOCKED;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::AddRefProxy1632
+//
+// Synopsis: addrefs proxy object - delegate call on to real object
+//
+// Arguments: [vpvThis16] -- 16/32 proxy
+//
+// Returns: local refcount
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+// Notes: AddRef rules
+// * cRef is the addref passed on to the real object
+// * cRefLocal is the addref collected locally
+// - the refcount can be 0 if the object was created as on in-param
+//----------------------------------------------------------------------------
+DWORD CThkMgr::AddRefProxy1632(VPVOID vpvThis16)
+{
+ THUNK1632OBJ UNALIGNED *ptoThis;
+ BOOL fAggregate;
+ LONG cRef;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn AddRefProxy1632(%p)\n",
+ NestingLevelString(), vpvThis16));
+ DebugIncrementNestingLevel();
+
+ DebugValidateProxy1632(vpvThis16);
+
+ ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
+
+ thkDebugOut(( DEB_THUNKMGR,
+ "%s AddRefProxy1632 %08lX RefCounts: %d,%d\n",
+ NestingLevelString(),
+ vpvThis16, ptoThis->cRefLocal, ptoThis->cRef ));
+
+ // Always increment the proxy local refcount
+ LocalAddRefProxy(ptoThis);
+
+ // Aggregations rely on all reference counts being forwarded on
+ // to the controlling unknown. Therefore, if we have a proxy
+ // that is part of an aggregate, we must ensure that the proxy
+ // doesn't collect references locally. If it did, they would
+ // not be passed on to the controlling unknown (via the real object)
+ // and the controlling unknown's refcount would be too low
+ if (ptoThis->pphHolder == NULL)
+ {
+ fAggregate = FALSE;
+ }
+ else
+ {
+ fAggregate = (ptoThis->pphHolder->dwFlags & PH_AGGREGATE) != 0;
+ }
+
+ if (IsOutParamObj())
+ {
+ // If we're on the way out we're assuming that the object
+ // given to us has its own reference so we bump cRef to
+ // indicate that but we don't call the real object
+ ptoThis->cRef++;
+ }
+ else if (ptoThis->cRef == 0 || fAggregate)
+ {
+ DWORD dwRet;
+ IUnknown *punk;
+
+ // It's also necessary to pass on real references when the
+ // ref count is zero. This handles the case where an
+ // in parameter, created as 1,0, is AddRef'ed after
+ // its creation, in which case the reference needs to
+ // be passed on to the real object so that the proxy has
+ // at least one real reference since it will stay alive
+ ptoThis->cRef++;
+ punk = ptoThis->punkThis32;
+ RELVDMPTR(vpvThis16);
+ dwRet = punk->AddRef();
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%s AddRefProxy1632: AddRef called on (%p):%ld\n",
+ NestingLevelString(), punk, dwRet));
+
+ // Reconvert 16:16 pointer since real AddRef may have caused
+ // nested calls and flat remapping
+ ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
+ }
+ else
+ {
+ // Just a local addref
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut AddRefProxy1632(%p), (%ld,%ld)\n",
+ NestingLevelString(), vpvThis16,
+ ptoThis->cRefLocal, ptoThis->cRef));
+
+ cRef = ptoThis->cRefLocal;
+ RELVDMPTR(vpvThis16);
+
+ return cRef;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::ReleaseProxy1632
+//
+// Synopsis: release on 16/32 proxy - delegate call on to real object
+//
+// Arguments: [vpvThis16] -- proxy
+//
+// Returns: local refcount
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+DWORD CThkMgr::ReleaseProxy1632(VPVOID vpvThis16)
+{
+ THUNK1632OBJ UNALIGNED *ptoThis;
+ PROXYHOLDER *pph;
+ LONG cRef, cRefLocal;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn ReleaseProxy1632(%p)\n",
+ NestingLevelString(), vpvThis16));
+ DebugIncrementNestingLevel();
+
+ DebugValidateProxy1632(vpvThis16);
+
+ ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
+
+ // There are cases where releasing the real object causes
+ // an entire object to go away so the proxy is gone after
+ // that call. Fortunately these cases only occur when
+ // cRef == cRefLocal == 0, so we can avoid problems by
+ // copying them locally
+
+ cRef = ptoThis->cRef;
+ cRefLocal = ptoThis->cRefLocal;
+
+ thkDebugOut(( DEB_THUNKMGR,
+ "%s ReleaseProxy1632 %08lX RefCounts: %d,%d\n",
+ NestingLevelString(),
+ vpvThis16, ptoThis->cRefLocal, ptoThis->cRef ));
+
+
+ if (cRef <= 0 && cRefLocal == cRef)
+ {
+ thkDebugOut((DEB_ERROR, "ERROR: ReleaseProxy1632(%p) cRef: %d; cRef: %d\n",
+ vpvThis16, ptoThis->cRef, ptoThis->cRefLocal));
+
+ goto Done;
+ }
+
+ // If our local refcount is the same as the count of references
+ // that we've passed on to the object, then we need to pass
+ // on this release to the real object
+ if (ptoThis->cRef == ptoThis->cRefLocal)
+ {
+ DWORD dwRet;
+ IUnknown *punk;
+
+#if DBG == 1
+ // We'd like to assert this but some apps (Works is one)
+ // release an aggregated object too many times through one
+ // interface. The overall aggregate refcount is ok, though,
+ // so this doesn't cause a problem
+
+ // thkAssert(ptoThis->cRef > 0);
+
+ if (ptoThis->cRef <= 0)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: ReleaseProxy1632(%p) cRef: %d\n",
+ vpvThis16, ptoThis->cRef));
+ }
+#endif
+
+ // Use local cRef here for safety
+ if (cRef > 0)
+ {
+ // Decrement cRef after making the real call to ensure that
+ // the proxy lives throughout the call
+ --ptoThis->cRef;
+ }
+
+
+
+ punk = ptoThis->punkThis32;
+ RELVDMPTR(vpvThis16);
+
+ // check if this is an pUnk proxy in an aggregation
+ // if so mark the pUnkOuter for cleanup
+ if (ptoThis->grfFlags & PROXYFLAG_PUNK)
+ {
+ thkDebugOut((DEB_THUNKMGR,
+ "%s ReleaseProxy1632: Release called on (%p)->%p\n",
+ NestingLevelString(), punk, vpvThis16));
+ pph = ptoThis->pphHolder;
+ pph->dwFlags |= PH_AGGREGATE_RELEASE;
+ }
+
+ // Decremente cRefLocal to prevent loops in release
+ --ptoThis->cRefLocal;
+
+ dwRet = punk->Release();
+
+ // Refresh pointer
+ ptoThis = FIXVDMPTR(vpvThis16, THUNK1632OBJ);
+
+ // Increment cRefLocal after making the real call to ensure that
+ // the proxy lives throughout the call
+ ++ptoThis->cRefLocal;
+
+ // rese the aggreagation flag
+ if (ptoThis->grfFlags & PROXYFLAG_PUNK)
+ {
+ pph = ptoThis->pphHolder;
+ pph->dwFlags &= !PH_AGGREGATE_RELEASE;
+ }
+
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%s ReleaseProxy1632: Release called on (%p):%ld \n",
+ NestingLevelString(), ptoThis->punkThis32, dwRet));
+ }
+
+ // Now that we've handled the real object's refcount, decrement
+ // the proxy's refcount and clean it up if necessary
+ // We need to use the local cRefLocal in case the proxy has gone away
+
+#if DBG == 1
+ // We'd like to assert this but some apps (Works is one)
+ // release an aggregated object too many times through one
+ // interface. The overall aggregate refcount is ok, though,
+ // so this doesn't cause a problem
+
+ thkAssert(cRefLocal > 0);
+
+ if (cRefLocal <= 0)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: ReleaseProxy1632(%p) cRefLocal: %d\n",
+ vpvThis16, cRefLocal));
+ }
+#endif
+
+ if (cRefLocal <= 0)
+ {
+ ptoThis = NULL;
+ }
+ else if (--ptoThis->cRefLocal == 0)
+ {
+
+ // Proxies that have no outer unknown can be cleaned
+ // up immediately. If they do have an outer unknown then
+ // they must live as long as the entire object lives,
+ // so we don't clean them up here. They'll be cleaned up
+ // when the object dies
+
+ pph = ptoThis->pphHolder;
+ if (pph)
+ {
+ // If this proxy isn't part of an aggregate, remove it
+ // from the proxy list so it can't be reused
+ // The only thing this proxy will be good for is
+ // calling through
+ if ((pph->dwFlags & PH_AGGREGATE) == 0)
+ {
+ _pProxyTbl1632->RemoveKey((DWORD)ptoThis->punkThis32);
+ }
+
+ RELVDMPTR(vpvThis16);
+
+ // We have a holder, so notify it that one of its
+ // proxies just died
+ // This can cause cleanup of all proxies if the
+ // holder releases to zero
+ ReleaseHolder(pph);
+ }
+ else
+ {
+ // We don't have a holder so we can clean up this proxy
+ // immediately
+
+ // Releases pointer
+ RemoveProxy1632(vpvThis16, ptoThis);
+ }
+
+ ptoThis = NULL;
+
+ DBG_DUMP(DebugDump1632());
+ }
+
+Done:
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut ReleaseProxy1632(%p) => %d,%d\n",
+ NestingLevelString(), vpvThis16,
+ ptoThis ? ptoThis->cRefLocal : 0,
+ ptoThis ? ptoThis->cRef : 0));
+
+ if (ptoThis)
+ {
+ cRef = ptoThis->cRefLocal;
+ RELVDMPTR(vpvThis16);
+ }
+ else
+ {
+ cRef = 0;
+ }
+
+ return cRef;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FreeProxy1632
+//
+// Synopsis: frees object for given pUnk (key)
+//
+// Arguments: [punkThis32] -- 32 bit unknown - key
+//
+// Returns: Refcount
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+DWORD CThkMgr::FreeProxy1632(IUnknown *punkThis32)
+{
+ thkDebugOut((DEB_THUNKMGR, "%sIn FreeProxy1632(%p)\n",
+ NestingLevelString(), punkThis32));
+ DebugIncrementNestingLevel();
+
+ thkAssert(punkThis32 != NULL && "FreeProxy1632: invalid object pointer.");
+
+ DWORD dwRet = 0;
+ VPVOID vpv;
+
+ vpv = LookupProxy1632(punkThis32);
+ if (vpv != NULL)
+ {
+ thkDebugOut((DEB_THUNKMGR,
+ "%sFreeProxy1632(%p) found existing proxy %p\n",
+ NestingLevelString(), punkThis32, vpv));
+
+ // punkThis32 is a proxy and not a real object, so release it
+ dwRet = ReleaseProxy1632(vpv);
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut FreeProxy1632(%p):%ld \n",
+ NestingLevelString(), punkThis32, dwRet));
+
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::RemoveProxy1632, public
+//
+// Synopsis: Destroys the given proxy
+//
+// Arguments: [vpv] - 16-bit proxy pointer
+// [pto] - Flat proxy pointer
+//
+// History: 11-Aug-94 DrewB Created
+//
+// Notes: Unfixes fixed pointer passed in
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::RemoveProxy1632(VPVOID vpv, THUNK1632OBJ *pto)
+{
+ _pProxyTbl1632->RemoveKey((DWORD)pto->punkThis32);
+
+ if ((pto->grfFlags & PROXYFLAG_LOCKED) == 0)
+ {
+#if DBG == 1
+ pto->dwSignature = PSIG1632DEAD;
+#endif
+
+ RELVDMPTR(vpv);
+
+#if DBG == 1
+ if (!fSaveProxy)
+#endif
+ {
+ flFreeList16.FreeElement((DWORD)vpv);
+ }
+ }
+ else
+ {
+ RELVDMPTR(vpv);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::CanGetNewProxy3216
+//
+// Synopsis: checks if new proxy is available
+//
+// Arguments: [iidx] - Custom interface or known index
+//
+// Returns: Preallocated proxy or NULL
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+THUNK3216OBJ *CThkMgr::CanGetNewProxy3216(IIDIDX iidx)
+{
+ thkDebugOut((DEB_THUNKMGR, "%sIn CanGetNewProxy3216(%s)\n",
+ NestingLevelString(), IidIdxString(iidx)));
+
+ LPVOID pvoid;
+
+ pvoid = (LPVOID)flFreeList32.AllocElement();
+ if ( pvoid == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: CThkMgr::CanGetNewProxy3216, "
+ "AllocElement failed\n"));
+ return NULL;
+ }
+
+ // check if the proxy is requested for a no-thop-interface
+ if (pvoid && IIDIDX_IS_IID(iidx))
+ {
+ // add the request for the unknown interface
+ if ( !AddIIDRequest(*IIDIDX_IID(iidx)) )
+ {
+ flFreeList32.FreeElement( (DWORD)pvoid );
+ pvoid = NULL;
+ }
+ }
+
+ thkDebugOut((DEB_THUNKMGR, "%sOut CanGetNewProxy3216: %p \n",
+ NestingLevelString(), pvoid));
+
+ return (THUNK3216OBJ *)pvoid;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FreeNewProxy3216
+//
+// Synopsis: frees previous reserved proxy
+//
+// Arguments: [pto] - Proxy
+// [iidx] - Custom interface or known index
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void CThkMgr::FreeNewProxy3216(THUNK3216OBJ *pto, IIDIDX iidx)
+{
+ thkDebugOut((DEB_THUNKMGR, "%sIn FreeNewProxy3216(%p, %s)\n",
+ NestingLevelString(), pto, IidIdxString(iidx)));
+
+ thkAssert(pto != NULL);
+
+ if (IIDIDX_IS_IID(iidx))
+ {
+ // add the request for the unknown interface
+ RemoveIIDRequest(*IIDIDX_IID(iidx));
+ }
+
+ thkAssert(pto != NULL);
+ flFreeList32.FreeElement( (DWORD)pto );
+
+ thkDebugOut((DEB_THUNKMGR, "%sOut FreeNewProxy3216\n",
+ NestingLevelString()));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::IsProxy3216
+//
+// Synopsis: checks if the given object is a 32/16 proxy
+//
+// Arguments: [punk] -- punk of 32 bit object
+//
+// Returns: Object being proxied or NULL
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+VPVOID CThkMgr::IsProxy3216(IUnknown *punk)
+{
+ LPVOID pvVtbl, pvFn;
+ THUNK3216OBJ *pto3216;
+
+ // First check the initial entry in the vtable
+ // If it's not QueryInterfaceProxy3216 then this can't possibly
+ // be a 32/16 proxy
+ pvVtbl = *(void **)punk;
+ pvFn = *(void **)pvVtbl;
+ if (pvFn == ::QueryInterfaceProxy3216)
+ {
+ DWORD dwKey;
+ POSITION pos;
+
+ // This object has a proxy's vtable but it may be dead, copied
+ // or coincidentally correct random memory, so look for it in
+ // the table
+
+ pos = _pProxyTbl3216->GetStartPosition();
+ while (pos)
+ {
+ _pProxyTbl3216->GetNextAssoc(pos, dwKey, (void FAR* FAR&) pto3216);
+
+ if (pto3216 == (THUNK3216OBJ *)punk)
+ {
+ return (VPVOID)dwKey;
+ }
+ }
+
+ // Check to see if we're returning no for what we think is
+ // a valid proxy
+ // It's possible for this to occur but it's very unlikely
+ thkAssert(pto3216->dwSignature != PSIG3216);
+ }
+
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FindProxy3216
+//
+// Synopsis: retrieves a 32/16 proxy
+//
+// Arguments: [ptoPrealloc] - Preallocated proxy or NULL
+// [vpvThis16] -- 16 bit object (key)
+// [iidx] - Custom interface or known index
+// [pfst] - Status return
+//
+// Returns: pointer to 32/16 proxy or real object
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+IUnknown *CThkMgr::FindProxy3216(THUNK3216OBJ *ptoPrealloc,
+ VPVOID vpvThis16,
+ IIDIDX iidx,
+ DWORD *pfst)
+{
+ IUnknown *punk;
+ THUNK3216OBJ *pto;
+ THKSTATE thkstate;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn FindProxy3216(%p, %p, %s)\n",
+ NestingLevelString(), ptoPrealloc, vpvThis16,
+ IidIdxString(iidx)));
+ DebugIncrementNestingLevel();
+
+ thkAssert(vpvThis16 != 0);
+
+ // If we preallocated a proxy with an IID then a request was added
+ // in CanGetNewProxy. Clean it up now
+ if (ptoPrealloc != 0 && IIDIDX_IS_IID(iidx))
+ {
+ RemoveIIDRequest(*IIDIDX_IID(iidx));
+ }
+
+ thkstate = GetThkState();
+
+ // Check and see whether a proxy already exists for this object
+ pto = LookupProxy3216(vpvThis16);
+ if (pto != NULL)
+ {
+ thkDebugOut((DEB_THUNKMGR,
+ "%sFindProxy3216 found existing proxy,(%p)->%p\n",
+ NestingLevelString(), vpvThis16, pto));
+
+ // If a proxy's refcount is zero, it must be part of an aggregate
+ thkAssert(pto->cRefLocal > 0 ||
+ (pto->pphHolder != NULL &&
+ (pto->pphHolder->dwFlags & PH_AGGREGATE) != 0));
+
+ // We found an existing proxy, so use it
+ punk = (IUnknown *)pto;
+
+ // Check and see whether we need to promote the proxy
+ // This occurs in derivation situations where a less-specialized
+ // proxy already exists for the given object. For example,
+ // we might already have an IPersist proxy for this object when
+ // we're looking up IPersistFile. In such cases, we promote
+ // the proxy to the most derived interface
+ if (IIDIDX_IS_INDEX(iidx) &&
+ IIDIDX_INDEX(iidx) > IIDIDX_INDEX(pto->iidx))
+ {
+ pto->pfnVtbl =
+ (DWORD)athopiInterfaceThopis[IIDIDX_INDEX(iidx)].pt3216fn;
+ pto->iidx = iidx;
+ }
+
+ // AddRef the proxy we found since we're passing out a reference
+ AddRefProxy3216(pto);
+
+ if (pfst)
+ {
+ *pfst = FST_USED_EXISTING;
+ }
+
+ goto Exit;
+ }
+
+ // Check and see whether the object to be proxied is in fact a
+ // proxy itself. If it is, we can just return the real object
+ // rather than creating chains of proxies
+ if ( ( punk = IsProxy1632(vpvThis16)) != NULL)
+ {
+ thkDebugOut((DEB_THUNKMGR,
+ "%sFindProxy3216 shortcut proxy,(%p)->%p\n",
+ NestingLevelString(), vpvThis16, punk));
+
+ // In the out parameter case, we are transferring ownership
+ // so we need to AddRef the thing we're returning
+ // Since we're shortcutting around a proxy we lose a reference
+ // to the proxy so release it
+ if (IsOutParamObj())
+ {
+ // vpvThis16 is a pointer to a proxy
+ // addref the real object and release the proxy
+
+ // We want to temporarily suspend our out state since
+ // we want this AddRef to really occur if it comes back
+ // to a proxy
+ SetThkState(THKSTATE_NOCALL);
+
+ punk->AddRef();
+
+ SetThkState(thkstate);
+
+ // Excel lands here with one too few addrefs so don't release
+ if (thkstate != THKSTATE_INVOKETHKOUT16_CLIENTSITE)
+ {
+ ReleaseProxy1632(vpvThis16);
+ }
+ }
+
+ if (pfst)
+ {
+ *pfst = FST_SHORTCUT;
+ }
+
+ goto Exit;
+ }
+
+ // We didn't find an existing proxy or shortcut so we need
+ // to create a new proxy for the given object
+ // We use preallocated memory if possible, otherwise we
+ // get a new proxy from the free list
+
+ if (ptoPrealloc != NULL)
+ {
+ pto = ptoPrealloc;
+
+ // Since we're using the preallocated proxy, mark it as used
+ // so we don't clean it up later
+ ptoPrealloc = NULL;
+ }
+ else
+ {
+ pto = (THUNK3216OBJ *)flFreeList32.AllocElement();
+ }
+
+ if (pto != NULL)
+ {
+ // Put the new proxy in the proxy table
+ if (!_pProxyTbl3216->SetAt(vpvThis16, pto))
+ {
+ // Note that we can put the new proxy back on the free
+ // list even if it's the preallocated proxy because
+ // that's what the prealloc cleanup does
+ flFreeList32.FreeElement((DWORD)pto);
+
+ pto = NULL;
+ goto Exit;
+ }
+
+ if (IIDIDX_IS_IID(iidx))
+ {
+ // give out IUnknown for custom interfaces
+ iidx = INDEX_IIDIDX(THI_IUnknown);
+ }
+
+ punk = (IUnknown *)pto;
+
+ pto->pfnVtbl = (DWORD)athopiInterfaceThopis[iidx].pt3216fn;
+ pto->cRefLocal = 1;
+ pto->cRef = (IsOutParamObj()) ? 1 : 0;
+ pto->iidx = iidx;
+ pto->vpvThis16 = vpvThis16;
+ pto->pphHolder = NULL;
+ PprxNull(pto->pprxObject);
+ pto->grfFlags = PROXYFLAG_NORMAL;
+
+
+#if DBG == 1
+ pto->dwSignature = PSIG3216;
+#endif
+
+ if (pfst)
+ {
+ *pfst = FST_CREATED_NEW;
+ }
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%sFindProxy3216 created new proxy, %s (%p)->%p:(%d,%d)\n",
+ NestingLevelString(),
+ inInterfaceNames[pto->iidx].pszInterface,
+ vpvThis16, pto, pto->cRefLocal, pto->cRef));
+
+ }
+
+ Exit:
+ //
+ // If we are succeeding punk will not be NULL. Then do this hack for Excel
+ //
+ if ( punk != NULL && thkstate == THKSTATE_INVOKETHKOUT16_CLIENTSITE )
+ {
+ SetThkState(THKSTATE_NOCALL);
+ //
+ // Excel 5.0a has a bug where it doesn't addref the proxy
+ // that it returns from the IOleObject::GetClientSite call
+ // this means that we can't release the proxy or we'd kill it
+ // prematurely.
+ //
+ thkDebugOut((DEB_WARN, "FindProxy1632: "
+ "Addrefing proxy for compatability\n"));
+ AddRefOnObj16( vpvThis16 );
+
+ SetThkState(thkstate);
+ }
+
+ // If we haven't used the preallocated proxy, return it to the freelist
+ if (ptoPrealloc)
+ {
+ flFreeList32.FreeElement( (DWORD)ptoPrealloc );
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut FindProxy3216: (%p)->%p\n",
+ NestingLevelString(), vpvThis16, punk));
+
+ return punk;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FindAggregate3216
+//
+// Synopsis: finds/creates an aggregate
+//
+// Arguments: [ptoPrealloc] - Preallocated proxy or NULL
+// [vpvOuter16] -- controlling unknown
+// [vpvThis16] -- 16 bit object (key)
+// [iidx] - IID or index of interface
+//
+// Returns: 32/16 proxy object
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+IUnknown *CThkMgr::FindAggregate3216(THUNK3216OBJ *ptoPrealloc,
+ VPVOID vpvOuter16,
+ VPVOID vpvThis16,
+ IIDIDX iidx)
+{
+ THUNK3216OBJ *pto3216;
+ IUnknown *punk;
+ DWORD fst;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn FindAggregate3216(%p, %p, %p, %s)\n",
+ NestingLevelString(), ptoPrealloc, vpvOuter16,
+ vpvThis16, IidIdxString(iidx)));
+ DebugIncrementNestingLevel();
+
+ thkAssert(vpvThis16 != NULL && vpvOuter16 != NULL);
+
+ // Get back an object for the object to be proxied
+ // This may be a proxy or a real object from a shortcut
+ punk = FindProxy3216(ptoPrealloc, vpvThis16, iidx, &fst);
+ if (punk == NULL)
+ {
+ goto Exit;
+ }
+
+ // If we got an object and it's not a proxy, we're done
+ // There's nothing we can do since we can't link a real object to
+ // a holder; we can only hope that things work out right
+ if (fst & FST_OBJECT_STATUS)
+ {
+ goto Exit;
+ }
+
+ // Otherwise, we need to set up a holder for whatever proxies we
+ // have
+
+ THUNK1632OBJ UNALIGNED *pto1632;
+ PROXYHOLDER *pph;
+ IUnknown *punkProxiedObject;
+
+ // We know punk is a proxy
+ pto3216 = (THUNK3216OBJ *)punk;
+
+ // Determine whether the outer unknown is a proxy or not
+ punkProxiedObject = IsProxy1632(vpvOuter16);
+
+ // Get the proxy pointer if it is
+ if (punkProxiedObject != 0)
+ {
+ pto1632 = FIXVDMPTR(vpvOuter16, THUNK1632OBJ);
+ }
+
+ if (punkProxiedObject != 0 && pto1632->pphHolder != NULL)
+ {
+ // Use the existing holder if there is one
+ pph = pto1632->pphHolder;
+ }
+ else
+ {
+ // Create a new holder
+ pph = NewHolder(PH_AGGREGATE);
+ if (pph == NULL)
+ {
+ FreeProxy3216(vpvThis16);
+ punk = NULL;
+ goto Exit;
+ }
+
+ // If the outer unknown is a proxy we know its holder hasn't
+ // been set, so add it to the holder we created
+ if (punkProxiedObject != 0)
+ {
+ AddProxyToHolder(pph, pto1632, Pprx16(vpvOuter16));
+ }
+ }
+
+ thkAssert(punkProxiedObject == 0 || pto1632->pphHolder == pph);
+
+ // Add the new interface to the holder
+ // Since this proxy was just created, we know its holder
+ // hasn't been set yet
+ AddProxyToHolder(pph, pto3216, Pprx32(pto3216));
+
+ Exit:
+ if (punkProxiedObject != 0)
+ {
+ RELVDMPTR(vpvOuter16);
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut FindAggregate3216,(%p)->%p\n",
+ NestingLevelString(), vpvThis16, pto3216));
+
+ return punk;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::QueryInterfaceProxy3216
+//
+// Synopsis: QueryInterface on the given proxy
+//
+// Arguments: [ptoThis] -- proxy object
+// [refiid] -- interface
+// [ppv] -- out parameter
+//
+// Returns: HRESULT
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+SCODE CThkMgr::QueryInterfaceProxy3216(THUNK3216OBJ *ptoThis,
+ REFIID refiid,
+ LPVOID *ppv)
+{
+ SCODE scRet;
+ IUnknown *punkProxy;
+ VPVOID vpvUnk;
+ DWORD fst;
+
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn QueryInterfaceProxy3216(%p)\n",
+ NestingLevelString(), ptoThis));
+ DebugIncrementNestingLevel();
+
+ DebugValidateProxy3216(ptoThis);
+
+ *ppv = NULL;
+
+ IIDIDX iidx = IidToIidIdx(refiid);
+
+ if (IIDIDX_IS_IID(iidx))
+ {
+ // add the request for the unknown interface
+ if (!AddIIDRequest(refiid))
+ {
+ return E_OUTOFMEMORY;
+ }
+ thkDebugOut((DEB_THUNKMGR,
+ "%sQueryInterfaceProxy3216: unknown iid %s\n",
+ NestingLevelString(), IidIdxString(iidx)));
+
+ }
+
+ // We force the object we're QI'ing to have a holder so that
+ // all objects have object refcounting. This should only be
+ // necessary for aggregation but it seems that some apps rely
+ // on all objects having aggregation-like refcounting qualities
+ // BobDay identified PowerPoint as one
+ // We only want to do this in cases where we've identified it's
+ // necessary, which presently is only for
+ // IDataObject
+ // so we only do it then
+
+ if (ptoThis->pphHolder == NULL && IsEqualIID(refiid, IID_IDataObject))
+ {
+ PROXYHOLDER *pph;
+
+ pph = NewHolder(PH_NONAGGREGATE);
+ if (pph == NULL)
+ {
+ scRet = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ AddProxyToHolder(pph, ptoThis, Pprx32(ptoThis));
+
+ // It's not necessary to clean this up if later calls fail
+ // since it doesn't alter the lifetime of the proxy if there's
+ // only one proxy for the holder
+ }
+
+ // see if the interface is supported
+ scRet = QueryInterfaceOnObj16(ptoThis->vpvThis16, refiid,
+ (void **)&vpvUnk);
+ if (FAILED(scRet))
+ {
+ goto Exit;
+ }
+
+ if (NULL == vpvUnk)
+ {
+ // Although it is invalid, an app can return NULL for the
+ // output interface and NOERROR for the result on a QueryInterface.
+ // Corel draw has this behavior. Anyway, we nullify these errors
+ // here.
+ scRet = E_NOINTERFACE;
+ goto Exit;
+ }
+
+ SetThkState(THKSTATE_INVOKETHKOUT32);
+
+ punkProxy = FindProxy3216(NULL, vpvUnk, iidx, &fst);
+ if (punkProxy == NULL)
+ {
+ // We were unable to create a proxy for the new interface so
+ // clean up the interface and quit
+
+ ReleaseOnObj16(vpvUnk);
+
+ scRet = E_OUTOFMEMORY;
+ goto ResetState;
+ }
+
+ *ppv = punkProxy;
+
+ // If we're returning a proxy, we need to make sure that
+ // it is listed in the proxy holder for this object
+ if (fst & FST_PROXY_STATUS)
+ {
+ THUNK3216OBJ *ptoProxy;
+
+ // We are returning a proxy. If its holder isn't set,
+ // add it to the holder of the object that was QI'ed
+
+ ptoProxy = (THUNK3216OBJ *)punkProxy;
+ if (ptoProxy->pphHolder == NULL)
+ {
+ if (ptoThis->pphHolder != NULL)
+ {
+ AddProxyToHolder(ptoThis->pphHolder, ptoProxy,
+ Pprx32(ptoProxy));
+ }
+ }
+ else if (ptoThis->pphHolder == NULL)
+ {
+ // ptoThis may not have a holder because it was produced
+ // by a non-QI method such as IOleItemContainer::GetObject
+ // If we find that an interface returned by it does
+ // have a holder, hook it up to the holder
+
+ // It shouldn't be necessary to do anything unusual with
+ // local references even if ptoThis is really part of an
+ // aggregate since ptoThis must have been produced by
+ // a method where aggregation can't be assumed and all
+ // references must be released on ptoThis itself
+ AddProxyToHolder(ptoProxy->pphHolder, ptoThis,
+ Pprx32(ptoThis));
+ }
+
+#if DBG == 1
+ // It's possible for holders to not match because of the above
+ // case with interfaces being returned from non-QI methods
+ // The lifetime for such interfaces must be defined by
+ // strong references, though, so it's not catastrophic
+ // Still, we'd like to be aware of such mismatches just in case
+ if (ptoProxy->pphHolder != ptoThis->pphHolder)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: QueryInterfaceProxy3216: "
+ "this %p has holder %p, proxy %p has holder %p\n",
+ ptoThis, ptoThis->pphHolder,
+ ptoProxy, ptoProxy->pphHolder));
+ }
+#endif
+ }
+
+ ResetState:
+ SetThkState(THKSTATE_NOCALL);
+
+ Exit:
+ // Clean up our custom interface request if necessary
+ if (IIDIDX_IS_IID(iidx))
+ {
+ // add the request for the unknown interface
+ RemoveIIDRequest(refiid);
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR,
+ "%sOut QueryInterfaceProxy3216(%p) => %p, 0x%08lX\n",
+ NestingLevelString(), ptoThis, *ppv, scRet));
+
+ return scRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::AddRefProxy3216
+//
+// Synopsis: addref on the given object - can addref the real object
+//
+// Arguments: [ptoThis] -- proxy object
+//
+// Returns: local refcount
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+DWORD CThkMgr::AddRefProxy3216(THUNK3216OBJ *ptoThis)
+{
+ PROXYHOLDER *pph;
+ BOOL fAggregate;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn AddRefProxy3216(%p)\n",
+ NestingLevelString(), ptoThis));
+ DebugIncrementNestingLevel();
+
+ DebugValidateProxy3216(ptoThis);
+
+ thkDebugOut(( DEB_THUNKMGR,
+ "%s AddRefProxy3216 %08lX RefCounts: %d,%d\n",
+ NestingLevelString(),
+ ptoThis, ptoThis->cRefLocal, ptoThis->cRef ));
+
+
+ pph = ptoThis->pphHolder;
+ if (pph && (pph->dwFlags & PH_AGGREGATE_RELEASE))
+ {
+ // we are about to call release on pUnkOuter
+ // Release on PUnk was called and addref or release
+ // calls to pUnkOuter are not supposted to be passed
+ // on any more
+ thkDebugOut((DEB_THUNKMGR, "%s About to addref pUnkOuter3216(%p)\n",
+ NestingLevelString(), ptoThis));
+
+ goto Exit;
+ }
+
+ // Always increment the proxy local refcount
+ LocalAddRefProxy(ptoThis);
+
+ // Aggregations rely on all reference counts being forwarded on
+ // to the controlling unknown. Therefore, if we have a proxy
+ // that is part of an aggregate, we must ensure that the proxy
+ // doesn't collect references locally. If it did, they would
+ // not be passed on to the controlling unknown (via the real object)
+ // and the controlling unknown's refcount would be too low
+ if (ptoThis->pphHolder == NULL)
+ {
+ fAggregate = FALSE;
+ }
+ else
+ {
+ fAggregate = (ptoThis->pphHolder->dwFlags & PH_AGGREGATE) != 0;
+ }
+
+ if (IsOutParamObj())
+ {
+ // If we're on the way out we're assuming that the object
+ // given to us has its own reference so we bump cRef to
+ // indicate that but we don't call the real object
+ ptoThis->cRef++;
+ }
+ else if (ptoThis->cRef == 0 || fAggregate)
+ {
+ DWORD dwRet;
+
+ // It's also necessary to pass on real references when the
+ // ref count is zero. This handles the case where an
+ // in parameter, created as 1,0, is AddRef'ed after
+ // its creation, in which case the reference needs to
+ // be passed on to the real object so that the proxy has
+ // at least one real reference since it will stay alive
+ ptoThis->cRef++;
+ dwRet = AddRefOnObj16(ptoThis->vpvThis16);
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%s AddRefProxy3216: AddRef called on (%p):%ld\n",
+ NestingLevelString(), ptoThis->vpvThis16, dwRet));
+ }
+ else
+ {
+ // Local-only AddRef
+ }
+
+Exit:
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut AddRefProxy3216(%p),(%ld,%ld)\n",
+ NestingLevelString(), ptoThis, ptoThis->cRefLocal,
+ ptoThis->cRef));
+
+ return ptoThis->cRefLocal;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::ReleaseProxy3216
+//
+// Synopsis: release on the proxy or aggregate
+//
+// Arguments: [ptoThis] -- proxy object
+//
+// Returns: local refcount
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+DWORD CThkMgr::ReleaseProxy3216(THUNK3216OBJ *ptoThis)
+{
+ PROXYHOLDER *pph;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn ReleaseProxy3216(%p)\n",
+ NestingLevelString(), ptoThis));
+ DebugIncrementNestingLevel();
+
+ DebugValidateProxy3216(ptoThis);
+
+ thkDebugOut(( DEB_THUNKMGR,
+ "%s ReleaseProxy3216 %08lX RefCounts: %d,%d\n",
+ NestingLevelString(),
+ ptoThis, ptoThis->cRefLocal, ptoThis->cRef ));
+
+ pph = ptoThis->pphHolder;
+ if (pph && (pph->dwFlags & PH_AGGREGATE_RELEASE))
+ {
+ // we are about to call release on pUnkOuter
+ // Release on PUnk was called and addref and
+ // release calls to pUnkOuter are not supposted
+ // to be passed on any more
+ thkDebugOut((DEB_THUNKMGR, "%s About to release pUnkOuter3216(%p)\n",
+ NestingLevelString(), ptoThis));
+ thkDebugOut((DEB_THUNKMGR, "%s ReleaseProxy3216 pUnkOuter stop passing releases on(%p) => %ld,%ld\n",
+ NestingLevelString(), ptoThis,
+ ptoThis ? ptoThis->cRefLocal : 0 ,
+ ptoThis ? ptoThis->cRef : 0));
+
+ if (ptoThis->cRef == 0 && ptoThis->cRef == ptoThis->cRefLocal)
+ {
+ goto Done;
+ }
+ }
+
+
+ // If our local refcount is the same as the count of references
+ // that we've passed on to the object, then we need to pass
+ // on this release to the real object
+ if (ptoThis->cRef == ptoThis->cRefLocal)
+ {
+ DWORD dwRet;
+
+ thkAssert(ptoThis->cRef > 0);
+
+ dwRet = ReleaseOnObj16(ptoThis->vpvThis16);
+
+ // Decrement cRef after making the real call to ensure that
+ // the proxy lives throughout the call
+ --ptoThis->cRef;
+
+ thkDebugOut((DEB_THUNKMGR,
+ "%s ReleaseProxy3216: Release called on (%p):%ld \n",
+ NestingLevelString(), ptoThis->vpvThis16, dwRet));
+ }
+
+ // Now that we've handled the real object's refcount, decrement
+ // the proxy's refcount and clean it up if necessary
+ thkAssert(ptoThis->cRefLocal > 0);
+ if (--ptoThis->cRefLocal == 0)
+ {
+ // Proxies that have no outer unknown can be cleaned
+ // up immediately. If they do have an outer unknown then
+ // they must live as long as the entire object lives,
+ // so we don't clean them up here. They'll be cleaned up
+ // when the object dies
+
+ if (ptoThis->pphHolder)
+ {
+ // If this proxy isn't part of an aggregate, remove it
+ // from the proxy list so it can't be reused
+ // The only thing this proxy will be good for is
+ // calling through
+ if ((ptoThis->pphHolder->dwFlags & PH_AGGREGATE) == 0)
+ {
+ _pProxyTbl3216->RemoveKey((DWORD)ptoThis->vpvThis16);
+ }
+
+ // We have a holder, so notify it that one of its
+ // proxies just died
+ // This can cause cleanup of all proxies if the
+ // holder releases to zero
+ ReleaseHolder(ptoThis->pphHolder);
+ }
+ else
+ {
+ // We don't have a holder so we can clean up this proxy
+ // immediately
+
+ RemoveProxy3216(ptoThis);
+ }
+
+ ptoThis = NULL;
+
+ DBG_DUMP(DebugDump3216());
+ }
+Done:
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut ReleaseProxy3216(%p) => %ld,%ld\n",
+ NestingLevelString(), ptoThis,
+ ptoThis ? ptoThis->cRefLocal : 0 ,
+ ptoThis ? ptoThis->cRef : 0));
+
+ return ptoThis ? ptoThis->cRefLocal : 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::ReleaseUnreferencedProxy3216, public
+//
+// Synopsis: Releases a proxy in the special case where the proxy
+// was created for a non-addrefed object
+//
+// Arguments: [ptoThis] - 32/16 proxy
+//
+// History: 11-Jul-94 DrewB Created
+//
+// Notes: Needed to clean up proxies from DebugServerQueryInterface
+// in DebugServerRelease
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::ReleaseUnreferencedProxy3216(THUNK3216OBJ *ptoThis)
+{
+ thkAssert(IsProxy3216((IUnknown *)ptoThis) != 0);
+
+ // Since the object is non-addref'ed, we have to be careful
+ // to ensure that the ReleaseProxy call doesn't end up releasing
+ // the real object, so we force cRef to be different from
+ // cRefLocal. We know that DebugServerQueryInterface gave the
+ // proxy a cRef because it's an out parameter, so we should
+ // always be able to decrement cRef and achieve the desired
+ // effect
+
+ thkAssert(ptoThis->cRef > 0);
+ ptoThis->cRef--;
+
+ // Now release the proxy to clean it up
+ // If it was addref'ed, this will just remove a local reference
+ // If it wasn't, this will clean up the proxy
+ // In both cases, no Release should occur on the real object
+
+ thkAssert(ptoThis->cRefLocal != ptoThis->cRef);
+
+ ReleaseProxy3216(ptoThis);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CThkMgr::FreeProxy3216
+//
+// Synopsis: releases the object for the given vpUnk16 (key)
+//
+// Arguments: [vpvObj16] - Proxy or object
+//
+// Returns: local refcount
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+DWORD CThkMgr::FreeProxy3216(VPVOID vpvObj16)
+{
+ thkDebugOut((DEB_THUNKMGR, "%sIn FreeProxy3216(%p)\n",
+ NestingLevelString(), vpvObj16));
+
+ DWORD dwRet = 0;
+ THUNK3216OBJ *pto;
+
+ thkAssert(vpvObj16 != 0);
+
+ // get the object by the 16 bit this pointer
+ pto = LookupProxy3216(vpvObj16);
+ if (pto != NULL)
+ {
+ thkDebugOut((DEB_THUNKMGR, "%sFreeProxy3216(%p) "
+ "found existing proxy %p\n",
+ NestingLevelString(), vpvObj16, pto));
+
+ dwRet = ReleaseProxy3216(pto);
+ }
+
+ thkDebugOut((DEB_THUNKMGR, "%sOut FreeProxy3216(%p):%ld \n",
+ NestingLevelString(), vpvObj16, dwRet));
+
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::RemoveProxy3216, public
+//
+// Synopsis: Destroys the given proxy
+//
+// Arguments: [pto] - Flat proxy pointer
+//
+// History: 11-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::RemoveProxy3216(THUNK3216OBJ *pto)
+{
+ _pProxyTbl3216->RemoveKey((DWORD)pto->vpvThis16);
+
+ if ((pto->grfFlags & PROXYFLAG_LOCKED) == 0)
+ {
+#if DBG == 1
+ pto->dwSignature = PSIG3216DEAD;
+ if (!fSaveProxy)
+#endif
+ {
+ flFreeList32.FreeElement((DWORD)pto);
+ }
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CThkMgr::PrepareForCleanup, public
+//
+// Synopsis: Marks the 3216 Proxies so that OLE32 cannot call them.
+//
+// Arguments: -none-
+//
+// History: 24-Aug-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void CThkMgr::PrepareForCleanup( void )
+{
+ POSITION pos;
+ DWORD dwKey;
+ THUNK3216OBJ *pto3216;
+
+ //
+ // CODEWORK: OLE32 should be setup so that it doesn't callback while the
+ // thread is detaching. Then this function becomes obsolete.
+ //
+
+ // delete the 3216 proxy table
+ pos = _pProxyTbl3216->GetStartPosition();
+
+ while (pos)
+ {
+ _pProxyTbl3216->GetNextAssoc(pos, dwKey, (void FAR* FAR&) pto3216);
+
+ thkDebugOut((DEB_IWARN, "Preparing 3216 Proxy for cleanup: "
+ "%08lX %08lX %s\n",
+ pto3216,
+ pto3216->vpvThis16,
+ IidIdxString(pto3216->iidx)));
+
+ pto3216->grfFlags |= PROXYFLAG_CLEANEDUP;
+ }
+}
+
+#if DBG == 1
+void CThkMgr::DebugDump3216()
+{
+ THUNK3216OBJ *pto3216;
+ DWORD dwKey;
+ POSITION pos;
+
+ thkDebugOut((DEB_THUNKMGR, "%s DebugDump3216\n",NestingLevelString()));
+
+ pos = _pProxyTbl3216->GetStartPosition();
+ while (pos)
+ {
+ _pProxyTbl3216->GetNextAssoc(pos, dwKey, (void FAR* FAR&) pto3216);
+ thkDebugOut((DEB_THUNKMGR,
+ "%s Proxy3216:Key:%p->%p, (%s) (%d,%d)\n",
+ NestingLevelString(), dwKey, pto3216,
+ IidIdxString(pto3216->iidx), pto3216->cRefLocal,
+ pto3216->cRef));
+ }
+}
+
+
+void CThkMgr::DebugDump1632()
+{
+ THUNK1632OBJ UNALIGNED *pto1632;
+ DWORD dwKey;
+ VPVOID vpv;
+ POSITION pos;
+
+ thkDebugOut((DEB_THUNKMGR, "%s DebugDump1632\n",NestingLevelString()));
+
+ pos = _pProxyTbl1632->GetStartPosition();
+ while (pos)
+ {
+ _pProxyTbl1632->GetNextAssoc(pos, dwKey, (void FAR* FAR&) vpv);
+ pto1632 = FIXVDMPTR(vpv, THUNK1632OBJ);
+ thkDebugOut((DEB_THUNKMGR,
+ "%s Proxy1632:key:%p->%p, (%s) (%d,%d)\n",
+ NestingLevelString(), dwKey, pto1632,
+ IidIdxString(pto1632->iidx), pto1632->cRefLocal,
+ pto1632->cRef));
+ RELVDMPTR(vpv);
+ }
+}
+#endif
diff --git a/private/ole32/olethunk/olethk32/cthkmgr.hxx b/private/ole32/olethunk/olethk32/cthkmgr.hxx
new file mode 100644
index 000000000..affb7a206
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/cthkmgr.hxx
@@ -0,0 +1,243 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: cthkmgr.hxx
+//
+// Contents: CThkMgr deklaration
+//
+// Classes: CThkMgr
+//
+// Functions:
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __CTHKMGR_HXX__
+#define __CTHKMGR_HXX__
+
+//
+// Describes a request for a custom interface
+//
+typedef struct tagIIDNODE IIDNODE, *PIIDNODE;
+struct tagIIDNODE
+{
+ IID *piid;
+ PIIDNODE pNextNode;
+};
+
+//
+// state of thunk call - before or after the 32 or 16 bit call
+//
+typedef enum
+{
+ THKSTATE_NOCALL = 0x0000,
+ THKSTATE_INVOKETHKIN32 = 0x0001,
+ THKSTATE_INVOKETHKOUT32 = 0x0002,
+ THKSTATE_INVOKETHKIN16 = 0x0004,
+ THKSTATE_INVOKETHKOUT16 = 0x0008,
+ THKSTATE_INVOKETHKOUT16_CLIENTSITE = 0x0010
+} THKSTATE;
+
+#define THKSTATE_OUT (THKSTATE_INVOKETHKOUT32 | THKSTATE_INVOKETHKOUT16 | \
+ THKSTATE_INVOKETHKOUT16_CLIENTSITE)
+
+//+---------------------------------------------------------------------------
+//
+// Class: CThkMgr ()
+//
+// Purpose:
+//
+// Interface: QueryInterface --
+// AddRef --
+// Release --
+// IsIIDRequested --
+// SetThkState --
+// IsIIDSupported --
+// AddIIDRequest --
+// RemoveIIDRequest --
+// ResetThkState --
+// GetThkState --
+// IsOutParamObj --
+// IsProxy1632 --
+// FreeProxy1632 --
+// QueryInterfaceProxy1632 --
+// AddRefProxy1632 --
+// ReleaseProxy1632 --
+// IsProxy3216 --
+// FreeProxy3216 --
+// QueryInterfaceProxy3216 --
+// AddRefProxy3216 --
+// ReleaseProxy3216 --
+// PrepareForCleanup --
+// DebugDump3216 --
+// Create --
+// ~CThkMgr --
+// CThkMgr --
+// _cRefs --
+// _thkstate --
+// _pProxyTbl3216 --
+// _pProxyTbl1632 --
+// _pCFL1632 --
+// _pCFL3216 --
+// _piidnode --
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+// Returns from FindProxy
+#define FST_CREATED_NEW 1
+#define FST_USED_EXISTING 2
+#define FST_SHORTCUT 4
+
+#define FST_PROXY_STATUS (FST_CREATED_NEW | FST_USED_EXISTING)
+#define FST_OBJECT_STATUS (FST_SHORTCUT)
+
+class CThkMgr : public IThunkManager
+{
+public:
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ // *** IThunkManager methods ***
+ STDMETHOD_(BOOL, IsIIDRequested) (THIS_ REFIID riid);
+ STDMETHOD_(BOOL, IsCustom3216Proxy) (THIS_ IUnknown *punk,
+ REFIID riid);
+
+ // private methods
+ THKSTATE GetThkState(void)
+ {
+ return _thkstate;
+ };
+ void SetThkState(THKSTATE thkstate)
+ {
+ _thkstate = thkstate;
+ };
+ BOOL IsOutParamObj(void)
+ {
+ return (_thkstate & THKSTATE_OUT) != 0;
+ }
+
+ BOOL IsIIDSupported (REFIID riid);
+ BOOL AddIIDRequest (REFIID riid);
+ void RemoveIIDRequest (REFIID riid);
+
+ void LocalAddRefProxy(CProxy *pprx);
+ void LockProxy(CProxy *pprx);
+
+ VPVOID CanGetNewProxy1632(IIDIDX iidx);
+ void FreeNewProxy1632(VPVOID vpv, IIDIDX iidx);
+
+ IUnknown *IsProxy1632(VPVOID vpvObj16);
+ VPVOID LookupProxy1632(IUnknown *punkThis32)
+ {
+ VPVOID vpv;
+
+ if (_pProxyTbl1632->Lookup((DWORD)punkThis32, (void*&)vpv))
+ {
+ return vpv;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ VPVOID FindProxy1632(VPVOID vpvPrealloc,
+ IUnknown *punkThis32,
+ IIDIDX iidx,
+ DWORD *pfst);
+ VPVOID FindAggregate1632(VPVOID vpvPrealloc,
+ IUnknown *punkOuter32,
+ IUnknown *punkThis32,
+ IIDIDX iidx);
+ DWORD FreeProxy1632(IUnknown *pUnk32);
+ void RemoveProxy1632(VPVOID vpv, THUNK1632OBJ *pto);
+
+ SCODE QueryInterfaceProxy1632(VPVOID vpvThis16,
+ REFIID refiid,
+ LPVOID *ppv);
+ DWORD AddRefProxy1632(VPVOID vpvThis16);
+ DWORD ReleaseProxy1632(VPVOID vpvThis16);
+
+ THUNK3216OBJ *CanGetNewProxy3216(IIDIDX iidx);
+ void FreeNewProxy3216(THUNK3216OBJ *ptoProxy, IIDIDX iidx);
+
+ VPVOID IsProxy3216(IUnknown *punkObj);
+ THUNK3216OBJ *LookupProxy3216(VPVOID vpvObj16)
+ {
+ THUNK3216OBJ *pto;
+
+ if (_pProxyTbl3216->Lookup((DWORD)vpvObj16, (void *&)pto))
+ {
+ return pto;
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ IUnknown *FindProxy3216(THUNK3216OBJ *ptoPrealloc,
+ VPVOID vpvThis16,
+ IIDIDX iidx,
+ DWORD *pfst);
+ IUnknown *FindAggregate3216(THUNK3216OBJ *ptoPrealloc,
+ VPVOID vpvOuter16,
+ VPVOID vpvThis16,
+ IIDIDX iidx);
+ DWORD FreeProxy3216(VPVOID vpUnk16);
+ void RemoveProxy3216(THUNK3216OBJ *pto);
+
+ SCODE QueryInterfaceProxy3216(THUNK3216OBJ *pto,
+ REFIID refiid,
+ LPVOID *ppv);
+ DWORD AddRefProxy3216(THUNK3216OBJ *pto);
+ DWORD ReleaseProxy3216(THUNK3216OBJ *pto);
+ void ReleaseUnreferencedProxy3216(THUNK3216OBJ *pto);
+
+ void PrepareForCleanup( void );
+
+#if DBG == 1
+ void DebugDump1632(void);
+ void DebugDump3216(void);
+#endif
+
+ void RemoveAllProxies(void);
+
+ // creation
+ static CThkMgr * Create(void);
+ ~CThkMgr();
+
+private:
+ CThkMgr(CMapDwordPtr *pPT1632, CMapDwordPtr *pPT3216);
+
+ LONG _cRefs;
+ THKSTATE _thkstate;
+
+ CMapDwordPtr *_pProxyTbl3216;
+ CMapDwordPtr *_pProxyTbl1632;
+
+ // list of requested iids
+ PIIDNODE _piidnode;
+
+ // List of proxy holders for controlling unknowns
+ PROXYHOLDER *_pphHolders;
+
+ // Holder manipulation routines
+ void ReleaseHolder(PROXYHOLDER *pph);
+ inline void AddRefHolder(PROXYHOLDER *pph);
+ void AddProxyToHolder(PROXYHOLDER *pph,
+ CProxy *pprxReal,
+ PROXYPTR &pprx);
+ PROXYHOLDER *NewHolder(DWORD dwFlags);
+};
+
+#endif // ifndef __CTHKMGR_HXX__
diff --git a/private/ole32/olethunk/olethk32/daytona/makefile b/private/ole32/olethunk/olethk32/daytona/makefile
new file mode 100644
index 000000000..734e18727
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/daytona/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the subcomponents of NTOS.
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/olethunk/olethk32/daytona/olethk32.def b/private/ole32/olethunk/olethk32/daytona/olethk32.def
new file mode 100644
index 000000000..722e5dbdc
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/daytona/olethk32.def
@@ -0,0 +1,27 @@
+#ifdef FLAT
+
+LIBRARY OLETHK32
+
+DESCRIPTION '32-bit Ole 2.0 Interoperability Code'
+
+EXPORTS
+ InvokeOn32 @3
+ IntOpInitialize @4
+ CallbackProcessing_3216 @5
+ IUnknownObj32 @6
+ CSm16ReleaseHandler_Release32 @8
+ ThkMgrInitialize @9
+ ThkMgrUninitialize @10
+ TransformHRESULT_1632 @11
+ TransformHRESULT_3216 @12
+ ConvertObjDescriptor @13
+ ConvertHr1632Thunk @14
+ ConvertHr3216Thunk @15
+ IntOpUninitialize @16
+ ThkAddAppCompatFlag @18
+#if DBG == 1
+ ThkCallOutputFunctions @19
+#endif
+
+#endif // FLAT
+
diff --git a/private/ole32/olethunk/olethk32/daytona/sources b/private/ole32/olethunk/olethk32/daytona/sources
new file mode 100644
index 000000000..d838f82b5
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/daytona/sources
@@ -0,0 +1,103 @@
+!IF 0
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ Standard definitions file for olethk32.dll, the OLE 2.0 interoperability
+ 32-bit thunk handler.
+
+Author:
+
+ Bob Day (bobday) 18-Feb-1994
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+# ..\..\com\coll\daytona\obj\*\coll.lib
+
+!ENDIF
+
+MAJORCOMP=cairole
+MINORCOMP=interop
+
+TARGETNAME=olethk32
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DYNLINK
+TARGETLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntvdm.lib \
+ $(BASEDIR)\public\sdk\lib\*\oemuni.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \
+ $(BASEDIR)\public\sdk\lib\*\wow32.lib \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+ ..\..\..\common\cruntime\daytona\obj\*\cruntime.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib
+
+INCLUDES=..\.; \
+ $(BASEDIR)\public\sdk\inc; \
+ ..\..\h; \
+ ..\..\..\ih;
+
+
+#
+# 0x6000000 should be fairly safe even though it is in usermode address range.
+# This DLL should only be loaded by WOW and since WOW doesn't normally load any
+# usermode DLLs, we can get away with loading it wherever we want. Feel free
+# to move it about if you really understand coffbase.txt. -BobDay
+#
+DLLBASE=0x6000000
+DLLENTRY=DllEntryPoint
+DLLDEF=obj\*\olethk32.def
+
+C_DEFINES=$(C_DEFINES) \
+ -DFLAT \
+ -DWIN32=100 \
+ -D_NT1X_=100 \
+ -DUNICODE \
+ -D_UNICODE
+
+!IF $(386)
+USE_NOLIBS=1
+!ELSE
+USE_CRTDLL=1
+!ENDIF
+
+SOURCES=\
+ ..\dllentry.cxx \
+ ..\tlsthk.cxx \
+ ..\thkmgr.cxx \
+ ..\freelist.cxx \
+ ..\cthkmgr.cxx \
+ ..\olethk32.cxx \
+ ..\inv16.cxx \
+ ..\inv32.cxx \
+ ..\thoputil.cxx \
+ ..\thop16.cxx \
+ ..\thop32.cxx \
+ ..\thopiint.cxx \
+ ..\tc1632.cxx \
+ ..\thtblapi.cxx \
+ ..\vtblapi.cxx \
+ ..\iidtothi.cxx \
+ ..\dbgapi.cxx \
+ ..\dbgitbl.cxx \
+ ..\map_kv.cxx \
+ ..\plex.cxx \
+ ..\apinot.cxx \
+ ..\olethk32.rc \
+ ..\alias.cxx \
+ ..\mmodel.cxx \
+ ..\stalloc.cxx \
+ ..\heap.cxx
+
+PRECOMPILED_INCLUDE=..\headers.cxx
+PRECOMPILED_PCH=headers.pch
+PRECOMPILED_OBJ=headers.obj
diff --git a/private/ole32/olethunk/olethk32/dbgapi.cxx b/private/ole32/olethunk/olethk32/dbgapi.cxx
new file mode 100644
index 000000000..f69ec776c
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/dbgapi.cxx
@@ -0,0 +1,127 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dbgapi.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#if DBG == 1
+
+char *apszApiNames[] =
+{
+ "CoInitialize"
+, "CoUninitialize"
+, "CoGetClassObject"
+, "CoRegisterClassObject"
+, "CoRevokeClassObject"
+, "CoMarshalInterface"
+, "CoUnmarshalInterface"
+, "CoReleaseMarshalData"
+, "CoDisconnectObject"
+, "CoLockObjectExternal"
+, "CoGetStandardMarshal"
+, "CoIsHandlerConnected"
+, "CoFreeAllLibraries"
+, "CoFreeUnusedLibraries"
+, "CoCreateInstance"
+, "CLSIDFromString"
+, "CoIsOle1Class"
+, "ProgIDFromCLSID"
+, "CLSIDFromProgID"
+, "CoCreateGuid"
+, "CoFileTimeToDosDateTime"
+, "CoDosDateTimeToFileTime"
+, "CoFileTimeNow"
+, "CoRegisterMessageFilter"
+, "CoGetTreatAsClass"
+, "CoTreatAsClass"
+, "DllGetClassObject"
+, "StgCreateDocfile"
+, "StgCreateDocfileOnILockBytes"
+, "StgOpenStorage"
+, "StgOpenStorageOnILockBytes"
+, "StgIsStorageFile"
+, "StgIsStorageILockBytes"
+, "StgSetTimes"
+, "CreateDataAdviseHolder"
+, "CreateDataCache"
+, "BindMoniker"
+, "MkParseDisplayName"
+, "MonikerRelativePathTo"
+, "MonikerCommonPrefixWith"
+, "CreateBindCtx"
+, "CreateGenericComposite"
+, "GetClassFile"
+, "CreateFileMoniker"
+, "CreateItemMoniker"
+, "CreateAntiMoniker"
+, "CreatePointerMoniker"
+, "GetRunningObjectTable"
+, "ReadClassStg"
+, "WriteClassStg"
+, "ReadClassStm"
+, "WriteClassStm"
+, "WriteFmtUserTypeStg"
+, "ReadFmtUserTypeStg"
+, "OleInitialize"
+, "OleUninitialize"
+, "OleQueryLinkFromData"
+, "OleQueryCreateFromData"
+, "OleCreate"
+, "OleCreateFromData"
+, "OleCreateLinkFromData"
+, "OleCreateStaticFromData"
+, "OleCreateLink"
+, "OleCreateLinkToFile"
+, "OleCreateFromFile"
+, "OleLoad"
+, "OleSave"
+, "OleLoadFromStream"
+, "OleSaveToStream"
+, "OleSetContainedObject"
+, "OleNoteObjectVisible"
+, "RegisterDragDrop"
+, "RevokeDragDrop"
+, "DoDragDrop"
+, "OleSetClipboard"
+, "OleGetClipboard"
+, "OleFlushClipboard"
+, "OleIsCurrentClipboard"
+, "OleCreateMenuDescriptor"
+, "OleSetMenuDescriptor"
+, "OleDestroyMenuDescriptor"
+, "OleDraw"
+, "OleRun"
+, "OleIsRunning"
+, "OleLockRunning"
+, "CreateOleAdviseHolder"
+, "OleCreateDefaultHandler"
+, "OleCreateEmbeddingHelper"
+, "OleRegGetUserType"
+, "OleRegGetMiscStatus"
+, "OleRegEnumFormatEtc"
+, "OleRegEnumVerbs"
+, "OleConvertIStorageToOLESTREAM"
+, "OleConvertOLESTREAMToIStorage"
+, "OleConvertIStorageToOLESTREAMEx"
+, "OleConvertOLESTREAMToIStorageEx"
+, "OleDoAutoConvert"
+, "OleGetAutoConvert"
+, "OleSetAutoConvert"
+, "GetConvertStg"
+, "SetConvertStg"
+, "ReadOleStg"
+, "WriteOleStg"
+};
+
+#endif // DBG
diff --git a/private/ole32/olethunk/olethk32/dbgint.cxx b/private/ole32/olethunk/olethk32/dbgint.cxx
new file mode 100644
index 000000000..5dd572448
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/dbgint.cxx
@@ -0,0 +1,682 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dbgint.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+
+char *apszIUnknownNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+};
+char *apszIClassFactoryNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "CreateInstance"
+, "LockServer"
+};
+char *apszIMarshalNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetUnmarshalClass"
+, "GetMarshalSizeMax"
+, "MarshalInterface"
+, "UnmarshalInterface"
+, "ReleaseMarshalData"
+, "DisconnectObject"
+};
+char *apszIStdMarshalInfoNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassForHandler"
+};
+char *apszIMessageFilterNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "HandleInComingCall"
+, "RetryRejectedCall"
+, "MessagePending"
+};
+char *apszIExternalConnectionNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "AddConnection"
+, "ReleaseConnection"
+};
+char *apszIEnumStringNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIEnumUnknownNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIEnumSTATSTGNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszILockBytesNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "ReadAt"
+, "WriteAt"
+, "Flush"
+, "SetSize"
+, "LockRegion"
+, "UnlockRegion"
+, "Stat"
+};
+char *apszIStreamNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Read"
+, "Write"
+, "Seek"
+, "SetSize"
+, "CopyTo"
+, "Commit"
+, "Revert"
+, "LockRegion"
+, "UnlockRegion"
+, "Stat"
+, "Clone"
+};
+char *apszIStorageNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "CreateStream"
+, "OpenStream"
+, "CreateStorage"
+, "OpenStorage"
+, "CopyTo"
+, "MoveElementTo"
+, "Commit"
+, "Revert"
+, "EnumElements"
+, "DestroyElement"
+, "RenameElement"
+, "SetElementTimes"
+, "SetClass"
+, "SetStateBits"
+, "Stat"
+};
+char *apszIRootStorageNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "SwitchToFile"
+};
+char *apszIEnumFORMATETCNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIEnumSTATDATANames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIDataObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetData"
+, "GetDataHere"
+, "QueryGetData"
+, "GetCanonicalFormatEtc"
+, "SetData"
+, "EnumFormatEtc"
+, "DAdvise"
+, "DUnadvise"
+, "EnumDAdvise"
+};
+char *apszIViewObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Draw"
+, "GetColorSet"
+, "Freeze"
+, "Unfreeze"
+, "SetAdvise"
+, "GetAdvise"
+};
+char *apszIViewObject2Names[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Draw"
+, "GetColorSet"
+, "Freeze"
+, "Unfreeze"
+, "SetAdvise"
+, "GetAdvise"
+, "GetExtent"
+};
+char *apszIAdviseSinkNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "OnDataChange"
+, "OnViewChange"
+, "OnRename"
+, "OnSave"
+, "OnClose"
+};
+char *apszIAdviseSink2Names[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "OnDataChange"
+, "OnViewChange"
+, "OnRename"
+, "OnSave"
+, "OnClose"
+, "OnLinkSrcChange"
+};
+char *apszIDataAdviseHolderNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Advise"
+, "Unadvise"
+, "EnumAdvise"
+, "SendOnDataChange"
+};
+char *apszIOleCacheNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Cache"
+, "Uncache"
+, "EnumCache"
+, "InitCache"
+, "SetData"
+};
+char *apszIOleCache2Names[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Cache"
+, "Uncache"
+, "EnumCache"
+, "InitCache"
+, "SetData"
+, "UpdateCache"
+, "DiscardCache"
+};
+char *apszIOleCacheControlNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "OnRun"
+, "OnStop"
+};
+char *apszIDropTargetNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "DragEnter"
+, "DragOver"
+, "DragLeave"
+, "Drop"
+};
+char *apszIDropSourceNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "QueryContinueDrag"
+, "GiveFeedback"
+};
+char *apszIPersistNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+};
+char *apszIPersistStorageNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+, "IsDirty"
+, "InitNew"
+, "Load"
+, "Save"
+, "SaveCompleted"
+, "HandsOffStorage"
+};
+char *apszIPersistStreamNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+, "IsDirty"
+, "Load"
+, "Save"
+, "GetSizeMax"
+};
+char *apszIPersistFileNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+, "IsDirty"
+, "Load"
+, "Save"
+, "SaveCompleted"
+, "GetCurFile"
+};
+char *apszIBindCtxNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "RegisterObjectBound"
+, "RevokeObjectBound"
+, "ReleaseBoundObjects"
+, "SetBindOptions"
+, "GetBindOptions"
+, "GetRunningObjectTable"
+, "RegisterObjectParam"
+, "GetObjectParam"
+, "EnumObjectParam"
+, "RevokeObjectParam"
+};
+char *apszIMonikerNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetClassID"
+, "IsDirty"
+, "Load"
+, "Save"
+, "GetSizeMax"
+, "BindToObject"
+, "BindToStorage"
+, "Reduce"
+, "ComposeWith"
+, "Enum"
+, "IsEqual"
+, "Hash"
+, "IsRunning"
+, "GetTimeOfLastChange"
+, "Inverse"
+, "CommonPrefixWith"
+, "RelativePathTo"
+, "GetDisplayName"
+, "ParseDisplayName"
+, "IsSystemMoniker"
+};
+char *apszIRunningObjectTableNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Register"
+, "Revoke"
+, "IsRunning"
+, "GetObject"
+, "NoteChangeTime"
+, "GetTimeOfLastChange"
+, "EnumRunning"
+};
+char *apszIEnumMonikerNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIEnumOLEVERBNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Next"
+, "Skip"
+, "Reset"
+, "Clone"
+};
+char *apszIOleObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "SetClientSite"
+, "GetClientSite"
+, "SetHostNames"
+, "Close"
+, "SetMoniker"
+, "GetMoniker"
+, "InitFromData"
+, "GetClipboardData"
+, "DoVerb"
+, "EnumVerbs"
+, "Update"
+, "IsUpToDate"
+, "GetUserClassID"
+, "GetUserType"
+, "SetExtent"
+, "GetExtent"
+, "Advise"
+, "Unadvise"
+, "EnumAdvise"
+, "GetMiscStatus"
+, "SetColorScheme"
+};
+char *apszIOleClientSiteNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "SaveObject"
+, "GetMoniker"
+, "GetContainer"
+, "ShowObject"
+, "OnShowWindow"
+, "RequestNewObjectLayout"
+};
+char *apszIRunnableObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetRunningClass"
+, "Run"
+, "IsRunning"
+, "LockRunning"
+, "SetContainedObject"
+};
+char *apszIParseDisplayNameNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "ParseDisplayName"
+};
+char *apszIOleContainerNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "ParseDisplayName"
+, "EnumObjects"
+, "LockContainer"
+};
+char *apszIOleItemContainerNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "ParseDisplayName"
+, "EnumObjects"
+, "LockContainer"
+, "GetObject"
+, "GetObjectStorage"
+, "IsRunning"
+};
+char *apszIOleAdviseHolderNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Advise"
+, "Unadvise"
+, "EnumAdvise"
+, "SendOnRename"
+, "SendOnSave"
+, "SendOnClose"
+};
+char *apszIOleLinkNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "SetUpdateOptions"
+, "GetUpdateOptions"
+, "SetSourceMoniker"
+, "GetSourceMoniker"
+, "SetSourceDisplayName"
+, "GetSourceDisplayName"
+, "BindToSource"
+, "BindIfRunning"
+, "GetBoundSource"
+, "UnbindSource"
+, "Update"
+};
+char *apszIOleWindowNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+};
+char *apszIOleInPlaceObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "InPlaceDeactivate"
+, "UIDeactivate"
+, "SetObjectRects"
+, "ReactivateAndUndo"
+};
+char *apszIOleInPlaceActiveObjectNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "TranslateAccelerator"
+, "OnFrameWindowActivate"
+, "OnDocWindowActivate"
+, "ResizeBorder"
+, "EnableModeless"
+};
+char *apszIOleInPlaceUIWindowNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "GetBorder"
+, "RequestBorderSpace"
+, "SetBorderSpace"
+, "SetActiveObject"
+};
+char *apszIOleInPlaceFrameNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "GetBorder"
+, "RequestBorderSpace"
+, "SetBorderSpace"
+, "SetActiveObject"
+, "InsertMenus"
+, "SetMenu"
+, "RemoveMenus"
+, "SetStatusText"
+, "EnableModeless"
+, "TranslateAccelerator"
+};
+char *apszIOleInPlaceSiteNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetWindow"
+, "ContextSensitiveHelp"
+, "CanInPlaceActivate"
+, "OnInPlaceActivate"
+, "OnUIActivate"
+, "GetWindowContext"
+, "Scroll"
+, "OnUIDeactivate"
+, "OnInPlaceDeactivate"
+, "DiscardUndoState"
+, "DeactivateAndUndo"
+, "OnPosRectChange"
+};
+char *apszIRpcChannelBufferNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetBuffer"
+, "SendReceive"
+, "FreeBuffer"
+, "GetDestCtx"
+, "IsConnected"
+};
+char *apszIRpcProxyBufferNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Connect"
+, "Disconnect"
+};
+char *apszIRpcStubBufferNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Connect"
+, "Disconnect"
+, "Invoke"
+, "IsIIDSupported"
+, "CountRefs"
+, "DebugServerQueryInterface"
+, "DebugServerRelease"
+};
+char *apszIPSFactoryBufferNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "CreateProxy"
+, "CreateStub"
+};
+char *apszIRpcChannelNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "GetStream"
+, "Call"
+, "GetDestCtx"
+, "IsConnected"
+};
+char *apszIRpcProxyNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Connect"
+, "Disconnect"
+};
+char *apszIRpcStubNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "Connect"
+, "Disconnect"
+, "Invoke"
+, "IsIIDSupported"
+, "CountRefs"
+};
+char *apszIPSFactoryNames[] =
+{
+ "QueryInterface"
+, "AddRef"
+, "Release"
+, "CreateProxy"
+, "CreateStub"
+};
+
+#endif // DBG
diff --git a/private/ole32/olethunk/olethk32/dbginv.hxx b/private/ole32/olethunk/olethk32/dbginv.hxx
new file mode 100644
index 000000000..274e0dd09
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/dbginv.hxx
@@ -0,0 +1,26 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dbginv.hxx
+//
+// Contents: Header for invocation debugging
+//
+// History: 08-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DBGINV_HXX__
+#define __DBGINV_HXX__
+
+typedef struct _INTERFACENAMES
+{
+ char *pszInterface;
+ char **ppszMethodNames;
+} INTERFACENAMES;
+
+extern INTERFACENAMES inInterfaceNames[];
+extern char *apszApiNames[];
+
+#endif // #ifndef __DBGINV_HXX__
diff --git a/private/ole32/olethunk/olethk32/dbgitbl.cxx b/private/ole32/olethunk/olethk32/dbgitbl.cxx
new file mode 100644
index 000000000..2c0c78cb6
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/dbgitbl.cxx
@@ -0,0 +1,82 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dbgitbl.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include "dbgint.cxx"
+#if DBG == 1
+
+INTERFACENAMES inInterfaceNames[] =
+{
+ "IUnknown", apszIUnknownNames
+, "IClassFactory", apszIClassFactoryNames
+, "IMarshal", apszIMarshalNames
+, "IStdMarshalInfo", apszIStdMarshalInfoNames
+, "IMessageFilter", apszIMessageFilterNames
+, "IExternalConnection", apszIExternalConnectionNames
+, "IEnumString", apszIEnumStringNames
+, "IEnumUnknown", apszIEnumUnknownNames
+, "IEnumSTATSTG", apszIEnumSTATSTGNames
+, "ILockBytes", apszILockBytesNames
+, "IStream", apszIStreamNames
+, "IStorage", apszIStorageNames
+, "IRootStorage", apszIRootStorageNames
+, "IEnumFORMATETC", apszIEnumFORMATETCNames
+, "IEnumSTATDATA", apszIEnumSTATDATANames
+, "IDataObject", apszIDataObjectNames
+, "IViewObject", apszIViewObjectNames
+, "IViewObject2", apszIViewObject2Names
+, "IAdviseSink", apszIAdviseSinkNames
+, "IAdviseSink2", apszIAdviseSink2Names
+, "IDataAdviseHolder", apszIDataAdviseHolderNames
+, "IOleCache", apszIOleCacheNames
+, "IOleCache2", apszIOleCache2Names
+, "IOleCacheControl", apszIOleCacheControlNames
+, "IDropTarget", apszIDropTargetNames
+, "IDropSource", apszIDropSourceNames
+, "IPersist", apszIPersistNames
+, "IPersistStorage", apszIPersistStorageNames
+, "IPersistStream", apszIPersistStreamNames
+, "IPersistFile", apszIPersistFileNames
+, "IBindCtx", apszIBindCtxNames
+, "IMoniker", apszIMonikerNames
+, "IRunningObjectTable", apszIRunningObjectTableNames
+, "IEnumMoniker", apszIEnumMonikerNames
+, "IEnumOLEVERB", apszIEnumOLEVERBNames
+, "IOleObject", apszIOleObjectNames
+, "IOleClientSite", apszIOleClientSiteNames
+, "IRunnableObject", apszIRunnableObjectNames
+, "IParseDisplayName", apszIParseDisplayNameNames
+, "IOleContainer", apszIOleContainerNames
+, "IOleItemContainer", apszIOleItemContainerNames
+, "IOleAdviseHolder", apszIOleAdviseHolderNames
+, "IOleLink", apszIOleLinkNames
+, "IOleWindow", apszIOleWindowNames
+, "IOleInPlaceObject", apszIOleInPlaceObjectNames
+, "IOleInPlaceActiveObject", apszIOleInPlaceActiveObjectNames
+, "IOleInPlaceUIWindow", apszIOleInPlaceUIWindowNames
+, "IOleInPlaceFrame", apszIOleInPlaceFrameNames
+, "IOleInPlaceSite", apszIOleInPlaceSiteNames
+, "IRpcChannelBuffer", apszIRpcChannelBufferNames
+, "IRpcProxyBuffer", apszIRpcProxyBufferNames
+, "IRpcStubBuffer", apszIRpcStubBufferNames
+, "IPSFactoryBuffer", apszIPSFactoryBufferNames
+, "IRpcChannel", apszIRpcChannelNames
+, "IRpcProxy", apszIRpcProxyNames
+, "IRpcStub", apszIRpcStubNames
+, "IPSFactory", apszIPSFactoryNames
+};
+
+#endif // DBG
diff --git a/private/ole32/olethunk/olethk32/dirs b/private/ole32/olethunk/olethk32/dirs
new file mode 100644
index 000000000..b7d4cd275
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/dirs
@@ -0,0 +1,40 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+#
+# Note that is currently omitted because there is no difference
+# from the daytona binary.
+OPTIONAL_DIRS= \
+ \
+ daytona
diff --git a/private/ole32/olethunk/olethk32/dllentry.cxx b/private/ole32/olethunk/olethk32/dllentry.cxx
new file mode 100644
index 000000000..394b4bc8b
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/dllentry.cxx
@@ -0,0 +1,56 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dllentry.cxx
+//
+// Contents: DLL entry point code
+//
+// History: 24-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+extern "C"
+{
+BOOL WINAPI _CRT_INIT (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
+BOOL _CRTAPI1 LibMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
+};
+
+extern "C" BOOL __stdcall DllEntryPoint (HANDLE hDll, DWORD dwReason,
+ LPVOID lpReserved)
+{
+ BOOL fRc;
+
+ if ((dwReason == DLL_PROCESS_ATTACH) || (dwReason == DLL_THREAD_ATTACH))
+ {
+ // If this is an attach, initialize the Cruntimes first
+ if (fRc = _CRT_INIT(hDll, dwReason, lpReserved))
+ {
+ fRc = LibMain(hDll, dwReason, lpReserved);
+ }
+ }
+ else
+ {
+ // This is a detach so call the Cruntimes second
+ LibMain(hDll, dwReason, lpReserved);
+ fRc = _CRT_INIT(hDll, dwReason, lpReserved);
+ }
+
+ return fRc;
+}
+
+extern "C" BOOL __stdcall DllMain (HANDLE hDll, DWORD dwReason,
+ LPVOID lpReserved)
+{
+ // This is not currently used...but must be present to avoid
+ // an undefined symbol
+
+ return FALSE;
+}
+
+
+
diff --git a/private/ole32/olethunk/olethk32/fntomthd.cxx b/private/ole32/olethunk/olethk32/fntomthd.cxx
new file mode 100644
index 000000000..ec62999e6
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/fntomthd.cxx
@@ -0,0 +1,2082 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: fntomthd.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+BYTE CONST ftmIClassFactory[] =
+{
+ 3,
+ 4
+};
+BYTE CONST ftmIMarshal[] =
+{
+ 6,
+ 0,
+ 0,
+ 0,
+ 8,
+ 7,
+ 0,
+ 3,
+ 4,
+ 5
+};
+BYTE CONST ftmIStdMarshalInfo[] =
+{
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIMessageFilter[] =
+{
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 5
+};
+BYTE CONST ftmIExternalConnection[] =
+{
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4
+};
+BYTE CONST ftmIEnumString[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3
+};
+BYTE CONST ftmIEnumUnknown[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3
+};
+BYTE CONST ftmIEnumSTATSTG[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3
+};
+BYTE CONST ftmILockBytes[] =
+{
+ 0,
+ 0,
+ 9,
+ 0,
+ 0,
+ 0,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 4,
+ 6,
+ 7,
+ 8
+};
+BYTE CONST ftmIStream[] =
+{
+ 4,
+ 0,
+ 12,
+ 0,
+ 13,
+ 8,
+ 9,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 6,
+ 11,
+ 10,
+ 5,
+ 7
+};
+BYTE CONST ftmIStorage[] =
+{
+ 0,
+ 0,
+ 13,
+ 15,
+ 12,
+ 9,
+ 10,
+ 0,
+ 0,
+ 6,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 4,
+ 5,
+ 8,
+ 11,
+ 14,
+ 16,
+ 17
+};
+BYTE CONST ftmIRootStorage[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIEnumFORMATETC[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIEnumSTATDATA[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIDataObject[] =
+{
+ 0,
+ 0,
+ 6,
+ 11,
+ 10,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 9,
+ 4,
+ 3,
+ 8
+};
+BYTE CONST ftmIViewObject[] =
+{
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 0,
+ 0,
+ 0,
+ 3
+};
+BYTE CONST ftmIViewObject2[] =
+{
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 9,
+ 5,
+ 0,
+ 0,
+ 0,
+ 3
+};
+BYTE CONST ftmIAdviseSink[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 3,
+ 0,
+ 7
+};
+BYTE CONST ftmIAdviseSink2[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 8,
+ 5,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 3,
+ 0,
+ 6
+};
+BYTE CONST ftmIDataAdviseHolder[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIOleCache[] =
+{
+ 7,
+ 0,
+ 0,
+ 6,
+ 5,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIOleCache2[] =
+{
+ 7,
+ 9,
+ 0,
+ 6,
+ 5,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8
+};
+BYTE CONST ftmIOleCacheControl[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0
+};
+BYTE CONST ftmIDropTarget[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 0,
+ 3,
+ 4,
+ 6
+};
+BYTE CONST ftmIDropSource[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIPersist[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIPersistStorage[] =
+{
+ 0,
+ 8,
+ 0,
+ 6,
+ 5,
+ 3,
+ 9,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIPersistStream[] =
+{
+ 0,
+ 0,
+ 0,
+ 7,
+ 5,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIPersistFile[] =
+{
+ 0,
+ 0,
+ 0,
+ 8,
+ 7,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 5,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIBindCtx[] =
+{
+ 0,
+ 7,
+ 0,
+ 6,
+ 4,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 10,
+ 9,
+ 0,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8,
+ 11,
+ 12
+};
+BYTE CONST ftmIMoniker[] =
+{
+ 16,
+ 22,
+ 19,
+ 17,
+ 14,
+ 13,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 15,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 21,
+ 10,
+ 9,
+ 8,
+ 18,
+ 12,
+ 6,
+ 0,
+ 4,
+ 11,
+ 0,
+ 0,
+ 0,
+ 7,
+ 5,
+ 3,
+ 20
+};
+BYTE CONST ftmIRunningObjectTable[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 8,
+ 7,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 9,
+ 5,
+ 4,
+ 0
+};
+BYTE CONST ftmIEnumMoniker[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 3
+};
+BYTE CONST ftmIEnumOLEVERB[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 3
+};
+BYTE CONST ftmIOleObject[] =
+{
+ 0,
+ 21,
+ 16,
+ 20,
+ 15,
+ 12,
+ 14,
+ 0,
+ 0,
+ 11,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 10,
+ 7,
+ 5,
+ 0,
+ 13,
+ 9,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 3,
+ 8,
+ 17,
+ 18,
+ 19,
+ 22,
+ 23
+};
+BYTE CONST ftmIOleClientSite[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 8
+};
+BYTE CONST ftmIRunnableObject[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 3,
+ 5
+};
+BYTE CONST ftmIParseDisplayName[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIOleContainer[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 5,
+ 0
+};
+BYTE CONST ftmIOleItemContainer[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 7,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 5,
+ 0
+};
+BYTE CONST ftmIOleAdviseHolder[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 4,
+ 7
+};
+BYTE CONST ftmIOleLink[] =
+{
+ 0,
+ 0,
+ 0,
+ 13,
+ 11,
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 12,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 6,
+ 4,
+ 0,
+ 0,
+ 0,
+ 9,
+ 5,
+ 3,
+ 10
+};
+BYTE CONST ftmIOleWindow[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0
+};
+BYTE CONST ftmIOleInPlaceObject[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 3,
+ 5
+};
+BYTE CONST ftmIOleInPlaceActiveObject[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 9,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 5,
+ 4,
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0
+};
+BYTE CONST ftmIOleInPlaceUIWindow[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 5,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8,
+ 3,
+ 0
+};
+BYTE CONST ftmIOleInPlaceFrame[] =
+{
+ 0,
+ 13,
+ 0,
+ 12,
+ 11,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 5,
+ 4,
+ 10,
+ 0,
+ 0,
+ 9,
+ 8,
+ 3,
+ 0,
+ 14
+};
+BYTE CONST ftmIOleInPlaceSite[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 8,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 14,
+ 10,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 5,
+ 0,
+ 9,
+ 11,
+ 12,
+ 13
+};
+BYTE CONST ftmIRpcChannelBuffer[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 4,
+ 3,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7
+};
+BYTE CONST ftmIRpcProxyBuffer[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4
+};
+BYTE CONST ftmIRpcStubBuffer[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 9,
+ 8,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 4
+};
+BYTE CONST ftmIPSFactoryBuffer[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+BYTE CONST ftmIRpcChannel[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6
+};
+BYTE CONST ftmIRpcProxy[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4
+};
+BYTE CONST ftmIRpcStub[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 5,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 6,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 7,
+ 4
+};
+BYTE CONST ftmIPSFactory[] =
+{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 4,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
diff --git a/private/ole32/olethunk/olethk32/freelist.cxx b/private/ole32/olethunk/olethk32/freelist.cxx
new file mode 100644
index 000000000..6ba44e5e9
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/freelist.cxx
@@ -0,0 +1,468 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: freelist.cxx
+//
+// Contents: CFreeList implementations
+//
+// History: 07-Jul-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+//
+// Each element, when it is free, has a pointer stored within it that
+// points to the next free element. We can do this because we know that
+// the element is free, all of its data is unused. These pointers are used
+// as DWORDs since they can be virtual pointers (16:16).
+//
+#define CALC_NEXTPTR(lpElement) \
+ ((LPDWORD)((DWORD)(lpElement) + m_iNextPtrOffset))
+
+//
+// Each block of elements has a pointer to the next block of elements. We
+// allocate extra room for this pointer just after all of the elements within
+// the block. These pointers are used as DWORDs since they can be virtual
+// pointers (16:16).
+
+#define CALC_BLOCKNEXTPTR(lpBlock,dwElementSectionSize) \
+ ((LPDWORD)((DWORD)(lpBlock) + (dwElementSectionSize)))
+
+//
+// Here are our global free lists, created on DLL load
+// The block sizes are generally -1 to allow space for block
+// list overhead
+//
+CFreeList flFreeList16( // THUNK1632OBJ free list
+ &mmodel16Public,
+ sizeof(THUNK1632OBJ),
+ 63,
+ FIELD_OFFSET(THUNK1632OBJ, pphHolder));
+
+CFreeList flFreeList32( // THUNK3216OBJ free list
+ &mmodel32,
+ sizeof(THUNK3216OBJ),
+ 63,
+ FIELD_OFFSET(THUNK3216OBJ, pphHolder));
+
+CFreeList flHolderFreeList( // PROXYHOLDER free list
+ &mmodel32,
+ sizeof(PROXYHOLDER),
+ 63,
+ FIELD_OFFSET(PROXYHOLDER, pphNext));
+
+CFreeList flRequestFreeList( // IID request free list
+ &mmodel32,
+ sizeof(IIDNODE),
+ 7,
+ FIELD_OFFSET(IIDNODE, pNextNode));
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFreeList::CFreeList
+//
+// Arguments: pmm - Memory model to use
+// iElementSize - The size of the structure being made into a
+// free list. e.g. sizeof THUNK1632OBJ
+// iElementsPerBlock - How many elements to allocate at a time
+// (a block contains this many elements).
+// iNextPtrOffset - Offset within the element's structure for
+// the place to store the free list's next
+// element pointer. Sometimes (for debugging,
+// etc.) it is desirable to make this NOT 0
+// (the beginning of the element structure).
+//
+// Synopsis: constructor for CFreeList class
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+// 7-05-94 BobDay (Bob Day) Changed it to be list based
+//
+//----------------------------------------------------------------------------
+CFreeList::CFreeList( CMemoryModel *pmm,
+ UINT iElementSize,
+ UINT iElementsPerBlock,
+ UINT iNextPtrOffset )
+{
+ //
+ // Save away the allocator information
+ //
+ m_pmm = pmm;
+ m_iElementSize = iElementSize;
+ m_iElementsPerBlock = iElementsPerBlock;
+ m_iNextPtrOffset = iNextPtrOffset;
+
+ //
+ // Set the list of elements to empty
+ //
+ m_dwHeadElement = 0;
+ m_dwTailElement = 0;
+
+ //
+ // Set the list of blocks to empty
+ //
+ m_dwHeadBlock = 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFreeList::AllocElement
+//
+// Synopsis: Allocates an element from the various blocks of elements
+// and allocates a new block if necessary.
+//
+// Returns: 0 if failed to alloc an element,
+// otherwise the DWORD representing the alloc'd element.
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+//----------------------------------------------------------------------------
+DWORD CFreeList::AllocElement( void )
+{
+ DWORD dwNewHeadBlock;
+ DWORD dwElementSectionSize;
+ DWORD dwBlockSize;
+ LPVOID lpBlock;
+ UINT iCnt;
+ DWORD dwElement;
+ LPVOID lpElement;
+ LPDWORD lpElementNextPtr;
+
+ //
+ // If the list of available elements is empty, callback to the derived
+ // class and make them add an entire new block of elements.
+ //
+ if ( m_dwHeadElement == 0 )
+ {
+ //
+ // Allocate a new block
+ //
+ iCnt = m_iElementsPerBlock;
+ dwElementSectionSize = m_iElementSize * m_iElementsPerBlock;
+
+ //
+ // Here we allocate an extra DWORD so that we can store in the block
+ // the address of the next block. In this way we have a list of
+ // blocks so that when the time comes to free them, we can find them
+ // all.
+ //
+ dwBlockSize = dwElementSectionSize + sizeof(DWORD);
+
+ dwNewHeadBlock = m_pmm->AllocMemory( dwBlockSize );
+
+ if ( dwNewHeadBlock == 0 )
+ {
+ //
+ // Yikes, the block allocator failed!
+ //
+ thkDebugOut((DEB_ERROR,
+ "CFreeList::AllocElement, AllocMemory failed\n"));
+ return 0;
+ }
+ //
+ // Now initialize the block and link it into the block list.
+ //
+
+ lpBlock = m_pmm->ResolvePtr( dwNewHeadBlock, dwBlockSize );
+ if ( lpBlock == NULL )
+ {
+ //
+ // Couldn't get a pointer to the block, some memory mapping
+ // problem?
+ //
+ thkDebugOut((DEB_ERROR,
+ "CFreeList::AllocElement, "
+ "ResolvePtr for block failed "
+ "for address %08lX, size %08lX\n",
+ dwNewHeadBlock, dwBlockSize ));
+ // Try to return bad block to pool
+ m_pmm->FreeMemory( dwNewHeadBlock );
+ return 0;
+ }
+
+#if DBG == 1
+ // 0xDE = Alloc'd but not init'd
+ memset( lpBlock, 0xDE, dwBlockSize );
+#endif
+
+ //
+ // Make this block point to the previous block
+ //
+ *CALC_BLOCKNEXTPTR(lpBlock,dwElementSectionSize) = m_dwHeadBlock;
+ m_dwHeadBlock = dwNewHeadBlock; // Update block list
+
+ m_pmm->ReleasePtr(dwNewHeadBlock);
+
+ //
+ // Now initialize all of the elements within the block to be free.
+ //
+ // The below loop skips the first element, free's all of the remaining
+ // ones. This way we can return the first one and all of the rest will
+ // be in accending order; The order doesn't really matter, but its
+ // nice.
+ //
+ dwElement = dwNewHeadBlock;
+
+ while ( iCnt > 1 ) // Free n-1 items (we skip the first)
+ {
+ --iCnt;
+ dwElement += m_iElementSize; // Skip to next one (miss 1st one)
+
+ FreeElement( dwElement );
+ }
+
+ dwElement = dwNewHeadBlock; // Use the first one as our alloc'd one
+ }
+ else
+ {
+ // We better have some blocks by now
+ thkAssert( m_dwHeadBlock != 0 );
+
+ // Better have a "end of list" too!
+ thkAssert( m_dwTailElement != 0 );
+
+ //
+ // Grab an available element off the top (head) of the list.
+ //
+ dwElement = m_dwHeadElement;
+
+ lpElement = m_pmm->ResolvePtr( dwElement, m_iElementSize );
+ if ( lpElement == NULL )
+ {
+ //
+ // Yikes, we weren't able to get a pointer to the element!
+ //
+ thkDebugOut((DEB_ERROR,
+ "CFreeList::AllocElement, "
+ "ResolvePtr for element failed "
+ "for address %08lX, size %08lX\n",
+ dwElement, m_iElementSize ));
+ return 0;
+ }
+
+ //
+ // Update the list to reflect the fact that we just removed the head
+ // and replace it with the one which was pointed to by the head.
+ //
+ lpElementNextPtr = CALC_NEXTPTR(lpElement);
+ m_dwHeadElement = *lpElementNextPtr;
+
+ m_pmm->ReleasePtr(dwElement);
+
+ //
+ // Also, if we are now at the end of the list, then the tail element
+ // should point to nowhere (i.e. there is nothing to insert after).
+ //
+ if ( m_dwHeadElement == 0 )
+ {
+ m_dwTailElement = 0;
+ }
+ }
+
+#if DBG == 1
+ // Erase the memory being returned to highlight reuse of dead values
+
+ lpElement = m_pmm->ResolvePtr( dwElement, m_iElementSize );
+ memset( lpElement, 0xED, m_iElementSize );
+ m_pmm->ReleasePtr(dwElement);
+
+ thkDebugOut((DEB_ITRACE,
+ "CFreeList::AllocElement, allocated element at %08lX\n",
+ dwElement ));
+#endif
+
+ return dwElement;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFreeList::FreeElement
+//
+// Synopsis: Un-Allocates an element from the various blocks of elements,
+// basically put the element back on the free list.
+//
+// Arguments: dwElement - Element to free
+//
+// Returns: -none- Asserts if failed.
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+//----------------------------------------------------------------------------
+void CFreeList::FreeElement( DWORD dwElement )
+{
+ LPVOID lpElement;
+ LPDWORD lpElementNextPtr;
+ DWORD dwResolved;
+
+ //
+ // First, make sure we can set this new element's next element pointer
+ // to zero (he's going to be a the end of the list).
+ //
+ lpElement = m_pmm->ResolvePtr( dwElement, m_iElementSize );
+ if ( lpElement == NULL )
+ {
+ //
+ // Yikes, we couldn't get a pointer to this element's place to store
+ // its next pointer.
+ //
+ thkDebugOut((DEB_ERROR,
+ "CFreeList::FreeElement, "
+ "ResolvePtr failed for free'd element\n"
+ "for address %08lX, size %08lX\n",
+ dwElement, m_iElementSize ));
+ thkAssert(FALSE && "CFreeList::FreeElement, "
+ "Resolve Ptr failed for free'd element\n");
+ return;
+ }
+
+#if DBG == 1
+ // Fill memory so its values can't be reused
+ if ( fZapProxy ) // Not doing this is important for
+ // the "PrepareForCleanup" processing the OLE32
+ // does on thread detach. ZapProxy can be used
+ // to turn it back on.
+ {
+ memset(lpElement, 0xDD, m_iElementSize);
+ }
+#endif
+
+ lpElementNextPtr = CALC_NEXTPTR(lpElement);
+
+ *lpElementNextPtr = 0; // Zap his next pointer since he'll be on the end
+
+ m_pmm->ReleasePtr(dwElement);
+
+ //
+ // Add this element back onto the end (tail) of the list.
+ //
+ if ( m_dwTailElement == 0 )
+ {
+ //
+ // Well, the list was empty, time to set it up
+ //
+ thkAssert( m_dwHeadElement == 0 );
+
+ lpElementNextPtr = &m_dwHeadElement;
+ dwResolved = 0;
+ }
+ else
+ {
+ //
+ // Ok, the list wasn't empty, so we add this new one onto the end.
+ //
+ thkAssert( m_dwHeadElement != 0 );
+
+ dwResolved = m_dwTailElement;
+ lpElement = m_pmm->ResolvePtr( m_dwTailElement, m_iElementSize );
+ if ( lpElement == NULL )
+ {
+ //
+ // Oh no, we couldn't get a pointer to the next element pointer for
+ // the guy who is currently the tail of the list.
+ //
+ thkDebugOut((DEB_ERROR,
+ "CFreeList::FreeElement, "
+ "ResolvePtr failed for last element\n"
+ "for address %08lX, size %08lX\n",
+ m_dwTailElement, m_iElementSize ));
+ thkAssert(FALSE && "CFreeList::FreeElement, "
+ "Resolve Ptr failed for last element\n");
+ return;
+ }
+
+ lpElementNextPtr = CALC_NEXTPTR(lpElement);
+ }
+
+ //
+ // Update our tail pointer to point to our newly free'd guy.
+ //
+ m_dwTailElement = dwElement;
+
+ //
+ // Make the last guy point to this newly free'd guy
+ //
+ *lpElementNextPtr = dwElement;
+
+ if (dwResolved != 0)
+ {
+ m_pmm->ReleasePtr(dwResolved);
+ }
+
+ thkDebugOut((DEB_ITRACE,
+ "CFreeList::FreeElement, free'd element at %08lX\n",
+ dwElement ));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CFreeList::FreeMemoryBlocks
+//
+// Arguments: -none-
+//
+// Returns: -nothing-
+//
+// Synopsis: Called by derived destructors to allow them to free up their
+// contents before going away.
+//
+// History: 7-05-94 BobDay (Bob Day) Created it
+//
+//----------------------------------------------------------------------------
+
+void CFreeList::FreeMemoryBlocks( void )
+{
+ DWORD dwBlock;
+ DWORD dwElementSectionSize;
+ DWORD dwBlockSize;
+ DWORD dwNextBlock;
+ LPVOID lpBlock;
+
+ //
+ // Compute some constants for this list ahead of time
+ //
+ dwElementSectionSize = m_iElementSize * m_iElementsPerBlock;
+
+ //
+ // Add room for that extra DWORD, block next pointer. (See comment in
+ // AllocElement where it allocates an extra DWORD)
+ //
+ dwBlockSize = dwElementSectionSize + sizeof(DWORD);
+
+ //
+ // Iterate through the list of blocks free'ing them
+ //
+ dwBlock = m_dwHeadBlock;
+
+ while( dwBlock != 0 )
+ {
+ //
+ // Find the next block ptr
+ //
+ lpBlock = m_pmm->ResolvePtr( dwBlock, dwBlockSize );
+ if ( lpBlock == NULL )
+ {
+ //
+ // If we get an error here, we just drop out of loop
+ //
+ dwNextBlock = 0;
+ }
+ else
+ {
+ dwNextBlock = *CALC_BLOCKNEXTPTR(lpBlock,dwElementSectionSize);
+
+#if DBG == 1
+ memset(lpBlock, 0xEE, dwBlockSize);
+#endif
+
+ m_pmm->ReleasePtr(dwBlock);
+ m_pmm->FreeMemory( dwBlock );
+ }
+ dwBlock = dwNextBlock;
+ }
+
+ m_dwHeadElement = 0;
+ m_dwTailElement = 0;
+ m_dwHeadBlock = 0;
+}
diff --git a/private/ole32/olethunk/olethk32/freelist.hxx b/private/ole32/olethunk/olethk32/freelist.hxx
new file mode 100644
index 000000000..139de795a
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/freelist.hxx
@@ -0,0 +1,65 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: freelist.hxx
+//
+// Contents: CFreeList classes
+//
+// History: 07-Jul-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FREELIST_HXX__
+#define __FREELIST_HXX__
+
+//+---------------------------------------------------------------------------
+//
+// Class: CFreeList (fl)
+//
+// Purpose: Implements a block allocator with replaceable underlying
+// memory strategies
+//
+// Interface: AllocElement - To allocate a proxy
+// ReleaseElement - To return an element to the free pool
+// AllocBlock - Callback for block allocation
+// GetElementNextPtr - Callback for list traversal
+//
+// Notes: At some point we might want to make this have one free list per
+// block. Then we would easily be able to tell which blocks have
+// all free elements within them and we able to be freed.
+//
+// History: 6-01-94 JohannP (Johann Posch) Created
+// 6-29-94 BobDay (Bob Day) Made list based
+//
+//----------------------------------------------------------------------------
+class CFreeList
+{
+public:
+ DWORD AllocElement( void );
+ void FreeElement( DWORD dwElement );
+ void FreeMemoryBlocks( void );
+
+ CFreeList( CMemoryModel *pmm,
+ UINT iElementSize,
+ UINT iElementsPerBlock,
+ UINT iNextPtrOffset );
+private:
+ CMemoryModel *m_pmm;
+
+ DWORD m_iElementSize;
+ DWORD m_iElementsPerBlock;
+ DWORD m_iNextPtrOffset;
+ DWORD m_dwHeadElement;
+ DWORD m_dwTailElement;
+ DWORD m_dwHeadBlock;
+};
+
+// Free lists
+extern CFreeList flFreeList16;
+extern CFreeList flFreeList32;
+extern CFreeList flHolderFreeList;
+extern CFreeList flRequestFreeList;
+
+#endif // #ifndef __FREELIST_HXX__
diff --git a/private/ole32/olethunk/olethk32/headers.cxx b/private/ole32/olethunk/olethk32/headers.cxx
new file mode 100644
index 000000000..50f0513e8
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/headers.cxx
@@ -0,0 +1,59 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: headers.cxx
+//
+// Contents: Precompiled headers file
+//
+// History: 21-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+extern "C" {
+#include <malloc.h>
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <wownt32.h>
+}
+
+#include <ole2.h>
+#include <olecoll.h>
+#include <privguid.h>
+#include <ole2sp.h>
+#include <ole2com.h>
+#include <utils.h>
+#include <memapi.hxx>
+
+#include <interop.hxx>
+#include <wow32fn.h>
+#include <thunkapi.hxx>
+#include <stksw.hxx>
+#include "mmodel.hxx"
+#include "stalloc.hxx"
+#include "nest.hxx"
+#include "olethk32.hxx"
+#include "map_kv.h"
+#include "map_dwp.h"
+#include "obj16.hxx"
+#include "thkmgr.hxx"
+#include "freelist.hxx"
+#include "cthkmgr.hxx"
+
+#include "tlsthk.hxx"
+#include "thop.hxx"
+#include "thi.hxx"
+#include "the.hxx"
+#include "thopapi.hxx"
+#include "thopint.hxx"
+#include "inv16.hxx"
+#include "alias.hxx"
+#include "thoputil.hxx"
+#include "apinot.hxx"
+
+#if DBG == 1
+#include "dbginv.hxx"
+#endif
diff --git a/private/ole32/olethunk/olethk32/heap.cxx b/private/ole32/olethunk/olethk32/heap.cxx
new file mode 100644
index 000000000..9268967cc
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/heap.cxx
@@ -0,0 +1,63 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: heap.cxx
+//
+// Contents: memory management
+//
+// Classes:
+//
+// Functions: operator new
+// operator delete
+//
+// History: 5-Dec-95 JeffE Created
+//
+//--------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+//+---------------------------------------------------------------------------
+//
+// Function: operator new, public
+//
+// Synopsis: Global operator new which does not throw exceptions.
+//
+// Arguments: [size] -- Size of the memory to allocate.
+//
+// Returns: A pointer to the allocated memory. Is *NOT* initialized to 0!
+//
+// Notes: We override new to make delete easier.
+//
+//----------------------------------------------------------------------------
+void* _CRTAPI1
+operator new (size_t size)
+{
+ return(CoTaskMemAlloc(size));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: ::operator delete
+//
+// Synopsis: Free a block of memory
+//
+// Arguments: [lpv] - block to free.
+//
+// History: 18-Nov-92 Ricksa Created
+//
+//--------------------------------------------------------------------------
+
+void _CRTAPI1 operator delete(void FAR* lpv)
+{
+ CoTaskMemFree (lpv);
+}
+
+
+
+
+
+
diff --git a/private/ole32/olethunk/olethk32/ichannel.cxx b/private/ole32/olethunk/olethk32/ichannel.cxx
new file mode 100644
index 000000000..7896e04e6
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/ichannel.cxx
@@ -0,0 +1,49 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ichannel.cxx
+//
+// Contents: Maps the RpcChannel to RpcChannelBuffer
+// This is required to support custom interface marshalling.
+//
+// History: 24-Mar-94 JohannP Created
+//
+//--------------------------------------------------------------------------
+
+
+//
+// the new 32 bit channel interface - buffer based
+//
+class CRpcChannelBuffer : public IPpcChannelBuffer
+{
+public:
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppvObject);
+ ULONG STDMETHODCALLTYPE AddRef(void);
+ ULONG STDMETHODCALLTYPE Release(void);
+
+ HRESULT STDMETHODCALLTYPE GetBuffer(RPCOLEMESSAGE *pMessage,REFIID riid);
+ HRESULT STDMETHODCALLTYPE SendReceive(RPCOLEMESSAGE *pMessage,ULONG *pStatus);
+ HRESULT STDMETHODCALLTYPE FreeBuffer(RPCOLEMESSAGE *pMessage);
+ HRESULT STDMETHODCALLTYPE GetDestCtx(DWORD *pdwDestContext,void **ppvDestContext);
+ HRESULT STDMETHODCALLTYPE IsConnected( void);
+};
+
+// 16 bit channel interface - stream based
+// class see by the 16 bit implemantation
+// needs to be mapped to the RpcChannelBuffer
+class CRpcChannel : public IRpcChannel
+{
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void **ppvObject);
+ ULONG STDMETHODCALLTYPE AddRef(void);
+ ULONG STDMETHODCALLTYPE Release(void);
+
+ STDMETHOD(GetStream)(REFIID iid, int iMethod, BOOL fSend,
+ BOOL fNoWait, DWORD size, IStream FAR* FAR* ppIStream);
+ STDMETHOD(Call)(IStream FAR* pIStream);
+ STDMETHOD(GetDestCtx)(DWORD FAR* lpdwDestCtx, LPVOID FAR* lplpvDestCtx);
+ STDMETHOD(IsConnected)(void);
+};
+
+
diff --git a/private/ole32/olethunk/olethk32/iidtothi.cxx b/private/ole32/olethunk/olethk32/iidtothi.cxx
new file mode 100644
index 000000000..54c250227
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/iidtothi.cxx
@@ -0,0 +1,79 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: iidtothi.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <coguid.h>
+#include <oleguid.h>
+IIDTOTHI CONST aittIidToThi[] =
+{
+ &IID_IUnknown, THI_IUnknown
+, &IID_IClassFactory, THI_IClassFactory
+, &IID_IMarshal, THI_IMarshal
+, &IID_IStdMarshalInfo, THI_IStdMarshalInfo
+, &IID_IMessageFilter, THI_IMessageFilter
+, &IID_IExternalConnection, THI_IExternalConnection
+, &IID_IEnumString, THI_IEnumString
+, &IID_IEnumUnknown, THI_IEnumUnknown
+, &IID_IEnumSTATSTG, THI_IEnumSTATSTG
+, &IID_ILockBytes, THI_ILockBytes
+, &IID_IStream, THI_IStream
+, &IID_IStorage, THI_IStorage
+, &IID_IRootStorage, THI_IRootStorage
+, &IID_IEnumFORMATETC, THI_IEnumFORMATETC
+, &IID_IEnumSTATDATA, THI_IEnumSTATDATA
+, &IID_IDataObject, THI_IDataObject
+, &IID_IViewObject, THI_IViewObject
+, &IID_IViewObject2, THI_IViewObject2
+, &IID_IAdviseSink, THI_IAdviseSink
+, &IID_IAdviseSink2, THI_IAdviseSink2
+, &IID_IDataAdviseHolder, THI_IDataAdviseHolder
+, &IID_IOleCache, THI_IOleCache
+, &IID_IOleCache2, THI_IOleCache2
+, &IID_IOleCacheControl, THI_IOleCacheControl
+, &IID_IDropTarget, THI_IDropTarget
+, &IID_IDropSource, THI_IDropSource
+, &IID_IPersist, THI_IPersist
+, &IID_IPersistStorage, THI_IPersistStorage
+, &IID_IPersistStream, THI_IPersistStream
+, &IID_IPersistFile, THI_IPersistFile
+, &IID_IBindCtx, THI_IBindCtx
+, &IID_IMoniker, THI_IMoniker
+, &IID_IRunningObjectTable, THI_IRunningObjectTable
+, &IID_IEnumMoniker, THI_IEnumMoniker
+, &IID_IEnumOLEVERB, THI_IEnumOLEVERB
+, &IID_IOleObject, THI_IOleObject
+, &IID_IOleClientSite, THI_IOleClientSite
+, &IID_IRunnableObject, THI_IRunnableObject
+, &IID_IParseDisplayName, THI_IParseDisplayName
+, &IID_IOleContainer, THI_IOleContainer
+, &IID_IOleItemContainer, THI_IOleItemContainer
+, &IID_IOleAdviseHolder, THI_IOleAdviseHolder
+, &IID_IOleLink, THI_IOleLink
+, &IID_IOleWindow, THI_IOleWindow
+, &IID_IOleInPlaceObject, THI_IOleInPlaceObject
+, &IID_IOleInPlaceActiveObject, THI_IOleInPlaceActiveObject
+, &IID_IOleInPlaceUIWindow, THI_IOleInPlaceUIWindow
+, &IID_IOleInPlaceFrame, THI_IOleInPlaceFrame
+, &IID_IOleInPlaceSite, THI_IOleInPlaceSite
+, &IID_IRpcChannelBuffer, THI_IRpcChannelBuffer
+, &IID_IRpcProxyBuffer, THI_IRpcProxyBuffer
+, &IID_IRpcStubBuffer, THI_IRpcStubBuffer
+, &IID_IPSFactoryBuffer, THI_IPSFactoryBuffer
+, &IID_IRpcChannel, THI_IRpcChannel
+, &IID_IRpcProxy, THI_IRpcProxy
+, &IID_IRpcStub, THI_IRpcStub
+, &IID_IPSFactory, THI_IPSFactory
+};
diff --git a/private/ole32/olethunk/olethk32/inv16.cxx b/private/ole32/olethunk/olethk32/inv16.cxx
new file mode 100644
index 000000000..a381b048d
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/inv16.cxx
@@ -0,0 +1,608 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: inv16.cxx
+//
+// Contents: 32->16 Call thunking
+//
+// History: 25-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include "..\..\ole232\inplace\inplace.h" // We need CFrameFilter for
+ // WinWord 6 Hack
+
+//+---------------------------------------------------------------------------
+//
+// Function: InvokeOn16, public
+//
+// Synopsis: Sets up the THUNKINFO and starts thunking for a 32->16 call
+//
+// Arguments: [iidx] - Custom interface or known interface index
+// [dwMethod] - Method index
+// [pvStack32] - 32-bit stack
+//
+// Returns: Appropriate status code
+//
+// History: 25-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+extern "C"
+{
+ULONG InvokeOn16_count = 0;
+ULONG InvokeOn16_break = 0;
+
+int _iInvokeOn16BreakIidx = -1;
+int _iInvokeOn16BreakMethod = -1;
+};
+#endif
+
+// InvokeOn16 uses a lot of local variables so allocate its locals
+// rather than declaring them on the stack. This saves roughly
+// 150 bytes of stack per call
+
+struct INVOKE16RECORD
+{
+ THOP CONST *pThop;
+ THOP CONST * CONST *ppThop;
+ UINT uiThop;
+ VTBLFN UNALIGNED CONST *pvfnVtbl;
+ VPVOID vpvThis16;
+ VPVOID vpvVtbl16;
+ VPVOID UNALIGNED CONST *pvpvThis16;
+ DWORD dwStack16[MAX_PARAMS];
+ THUNKINFO ti;
+ THUNK3216OBJ *ptoThis32;
+ ThreadData *ptd;
+};
+
+DWORD InvokeOn16(IIDIDX iidx, DWORD dwMethod, LPVOID pvStack32)
+{
+ // NOTE: Do not declare local variables in this routine
+ // except for debug builds
+ INVOKE16RECORD *pir;
+ DWORD dwResult;
+
+#if DBG == 1
+ ULONG ulInvokeOn16_count = ++InvokeOn16_count;
+ if (InvokeOn16_count == InvokeOn16_break)
+ {
+ DebugBreak();
+ }
+
+ thkDebugOut((DEB_ITRACE, "%sInvokeOn16(0x%x, 0x%x, %p)\n",
+ NestingLevelString(), iidx, dwMethod, pvStack32));
+#endif
+
+ pir = (INVOKE16RECORD *)STACKALLOC32(sizeof(INVOKE16RECORD));
+ if (pir == NULL)
+ {
+ // BUGBUG - This error isn't guaranteed to mean anything for
+ // this call. Not much else we can do, though
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ // pvStack32 is a pointer to an array of arguments from the
+ // 32-bit call. It's always laid out with the first
+ // argument low and increasing from there
+
+ pir->ti.s32.pbStart = (BYTE *)pvStack32;
+ pir->ti.s32.pbCurrent = pir->ti.s32.pbStart;
+
+ pir->ti.s16.pbStart = (BYTE *)pir->dwStack16;
+ pir->ti.s16.pbCurrent = pir->ti.s16.pbStart;
+
+ pir->ti.scResult = S_OK;
+ pir->ti.fResultThunked = FALSE;
+
+ pir->ptd = TlsThkGetData();
+ if (pir->ptd == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: InvokeOn16: Call refused\n"));
+
+ STACKFREE32(pir, sizeof(INVOKE16RECORD));
+ return (DWORD)E_FAIL;
+ }
+
+ pir->ti.pThkMgr = pir->ptd->pCThkMgr;
+ thkAssert(pir->ti.pThkMgr != NULL);
+
+ thkAssert(iidx >= 0 && iidx < THI_COUNT);
+
+ // For each interface there is an array of thop strings, one for
+ // each method. The IUnknown methods don't have thop strings so
+ // bias the thop string pointer to account for that
+
+ thkAssert(dwMethod >= SMI_COUNT);
+
+ pir->ppThop = athopiInterfaceThopis[iidx].ppThops-SMI_COUNT;
+ pir->uiThop = athopiInterfaceThopis[iidx].uiSize;
+
+ // Methods are cdecl so we need to move upwards in memory to
+ // get to the next parameter
+ pir->ti.s16.iDir = 1;
+
+ // We need to look up the appropriate method pointer by
+ // looking in the 16-bit object's vtable
+ GET_STACK32(&pir->ti, pir->ptoThis32, THUNK3216OBJ *);
+
+ thkDebugOut((DEB_INVOKES,
+ "InvokeOn16: ptoThis32 = %08lX\n", pir->ptoThis32 ));
+
+ if ( pir->ptoThis32->grfFlags & PROXYFLAG_CLEANEDUP )
+ {
+ thkDebugOut((DEB_WARN,
+ "InvokeOn16: Attempt to call %s::%s"
+ "on cleaned-up proxy %08lX for 16-bit object %08lX\n",
+ inInterfaceNames[iidx].pszInterface,
+ inInterfaceNames[iidx].ppszMethodNames[dwMethod],
+ pir->ptoThis32, pir->ptoThis32->vpvThis16));
+ STACKFREE32(pir, sizeof(INVOKE16RECORD));
+ return (DWORD)E_FAIL;
+ }
+
+ // check PROXYFLAG_CLEANEDUP before calling DebugValidateProxy3216.
+ // Otherwise we might get asserts on checked OLE.
+ DebugValidateProxy3216(pir->ptoThis32);
+
+ pir->ti.dwCallerProxy = (DWORD)pir->ptoThis32;
+ pir->vpvThis16 = pir->ptoThis32->vpvThis16;
+ pir->pvpvThis16 = (VPVOID UNALIGNED *)
+ GetReadPtr16(&pir->ti, pir->vpvThis16, sizeof(VPVOID));
+ if (pir->pvpvThis16 == NULL)
+ {
+ dwResult = pir->ti.scResult;
+ STACKFREE32(pir, sizeof(INVOKE16RECORD));
+ return dwResult;
+ }
+
+ pir->vpvVtbl16 = *pir->pvpvThis16;
+ pir->pvfnVtbl = (VTBLFN UNALIGNED *)
+ GetReadPtr16(&pir->ti, pir->vpvVtbl16, sizeof(VPVOID)*pir->uiThop);
+
+ WOWRELVDMPTR(pir->vpvThis16);
+
+ if (pir->pvfnVtbl == NULL)
+ {
+ dwResult = pir->ti.scResult;
+ STACKFREE32(pir, sizeof(INVOKE16RECORD));
+ return dwResult;
+ }
+
+ // Push the 16-bit this pointer on the stack first
+ TO_STACK16(&pir->ti, pir->vpvThis16, VPVOID);
+
+ thkAssert(dwMethod < pir->uiThop);
+
+ pir->pThop = pir->ppThop[dwMethod];
+
+ thkAssert(pir->pThop != NULL);
+
+ pir->ti.pThop = pir->pThop;
+ pir->ti.pvfn = pir->pvfnVtbl[dwMethod];
+ pir->ti.iidx = iidx;
+ pir->ti.dwMethod = dwMethod;
+ pir->ti.this32 = (IUnknown *)pir->ptoThis32;
+
+ WOWRELVDMPTR(pir->vpvVtbl16);
+
+ thkDebugOut((DEB_INVOKES, "%s#(%04X):InvokeOn16 on %p:%p, %s::%s\n",
+ NestingLevelString(), ulInvokeOn16_count,
+ pir->vpvThis16, pir->ti.pvfn,
+ inInterfaceNames[iidx].pszInterface,
+ inInterfaceNames[iidx].ppszMethodNames[dwMethod]));
+
+ DebugIncrementNestingLevel();
+
+ pir->ti.pThkMgr->SetThkState(THKSTATE_INVOKETHKIN16);
+
+#if DBG == 1
+ SStackRecord sr;
+
+ RecordStackState16(&sr);
+#endif
+
+#if DBG == 1
+ if ((_iInvokeOn16BreakIidx > 0 && _iInvokeOn16BreakIidx == (int)iidx) &&
+ (_iInvokeOn16BreakMethod < 0 ||
+ _iInvokeOn16BreakMethod == (int)dwMethod))
+ {
+ DebugBreak();
+ }
+#endif
+
+ dwResult = EXECUTE_THOP3216(&pir->ti);
+
+#if DBG == 1
+
+ if ( !pir->ti.fResultThunked && FAILED(dwResult) )
+ {
+ thkDebugOut((DEB_FAILURES,
+ "InvokeOn16 probable failure %s::%s sc = %08lX\n",
+ inInterfaceNames[iidx].pszInterface,
+ inInterfaceNames[iidx].ppszMethodNames[dwMethod],
+ dwResult));
+ }
+
+ CheckStackState16(&sr);
+
+#endif
+
+ pir->ti.pThkMgr->SetThkState(THKSTATE_NOCALL);
+
+ DebugDecrementNestingLevel();
+
+ thkDebugOut((DEB_INVOKES,
+ "%s#(%04X):InvokeOn16 on %p:%p, %s::%s returns 0x%08lX\n",
+ NestingLevelString(), ulInvokeOn16_count,
+ pir->vpvThis16, pir->ti.pvfn,
+ inInterfaceNames[iidx].pszInterface,
+ inInterfaceNames[iidx].ppszMethodNames[dwMethod],
+ dwResult));
+
+ STACKFREE32(pir, sizeof(INVOKE16RECORD));
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Call3216, private
+//
+// Synopsis: Sets up stack and transitions to 16-bit
+//
+// Arguments: [pvfn] - Function to call
+// [pbStack] - Stack in 32-bits
+// [cbStack] - Size of stack
+//
+// Returns: Appropriate status code
+//
+// History: 04-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+#if DBG == 1
+extern "C" ULONG Call3216_count = 0;
+extern "C" ULONG Call3216_break = 0;
+#endif
+
+DWORD Call3216(VPVOID pvfn, BYTE *pbStack, UINT cbStack)
+{
+#if DBG == 1
+ ULONG ulCall3216_count = ++Call3216_count;
+ if (Call3216_count == Call3216_break)
+ {
+ DebugBreak();
+ }
+#endif
+
+ VPVOID vpvStack16;
+ DWORD dwResult;
+ void *pvStack16;
+
+ dwResult = (DWORD)S_OK;
+
+ if (cbStack <= WCB16_MAX_CBARGS)
+ {
+ thkDebugOut((DEB_ITRACE, "CallbackTo16Ex(%p, %lu, %p) #(%x)\n",
+ pvfn, cbStack, pbStack, ulCall3216_count));
+
+ // pbStack must have at least WCB16_MAX_CBARGS bytes of valid memory
+ // since 16V always copies that many bytes
+
+ // In our case pbStack is from InvokeOn16 which should be large enough
+ thkAssert(MAX_PARAMS*sizeof(DWORD) >= WCB16_MAX_CBARGS);
+
+ if (!CallbackTo16Ex(pvfn, WCB16_CDECL, cbStack, pbStack,
+ &dwResult))
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ }
+ else
+ {
+ CALLDATA UNALIGNED *pcd;
+ UINT cbAlloc;
+
+ cbAlloc = cbStack+sizeof(CALLDATA);
+
+ vpvStack16 = STACKALLOC16(cbAlloc);
+ if (vpvStack16 == 0)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ else
+ {
+ pvStack16 = (void *)WOWFIXVDMPTR(vpvStack16, cbAlloc);
+
+ pcd = (CALLDATA UNALIGNED *)((BYTE *)pvStack16+cbStack);
+ pcd->vpfn = (DWORD)pvfn;
+ pcd->vpvStack16 = vpvStack16;
+ pcd->cbStack = cbStack;
+
+ memcpy(pvStack16, pbStack, cbStack);
+
+ WOWRELVDMPTR(vpvStack16);
+
+ thkDebugOut((DEB_ITRACE, "CallbackTo16(%p, (%p, %p, %lu)) #(%x)\n",
+ gdata16Data.fnCallStub16, pvfn, vpvStack16,
+ cbStack, ulCall3216_count));
+ dwResult = CallbackTo16(gdata16Data.fnCallStub16,
+ vpvStack16+cbStack);
+
+ STACKFREE16(vpvStack16, cbAlloc);
+ }
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThunkCall3216, public
+//
+// Synopsis: Sets up the 16-bit stack and makes a 32->16 call
+//
+// Arguments: [pti] - Thunk state info
+//
+// Returns: Appropriate status code
+//
+// History: 25-Feb-94 DrewB Created
+// 08-Aug-94 AlexT Add IOleClientSite::OnShowWindow code
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+extern "C" ULONG ThunkCall3216_count = 0;
+extern "C" ULONG ThunkCall3216_break = 0;
+#endif
+
+DWORD ThunkCall3216(THUNKINFO *pti)
+{
+ DWORD dwReturn;
+ UINT cbStack;
+ DWORD dwCallerTID;
+ HRESULT hrCaller;
+
+
+#if DBG == 1
+ ULONG ulThunkCall3216_count = ++ThunkCall3216_count;
+ thkAssert( (ThunkCall3216_count != ThunkCall3216_break) &&
+ "Break Count Hit");
+#endif
+
+ thkAssert(*pti->pThop == THOP_END);
+ pti->pThop++;
+ thkAssert(*pti->pThop == THOP_ROUTINEINDEX);
+ pti->pThop++;
+
+ thkDebugOut((DEB_ITRACE, "ThunkCall3216 #(%x) %p, index %d\n",
+ ulThunkCall3216_count, pti->pvfn, *pti->pThop));
+
+ cbStack = pti->s16.pbCurrent-pti->s16.pbStart;
+
+ // The this pointer should always be on the stack
+ thkAssert(cbStack >= sizeof(VPVOID));
+
+ //
+ // Hacks for specific interface member functions.
+ // The placement of these hacks here is by no means an optimal solution.
+ // It just happens to be convienient for now since everything goes through
+ // here. This section is for pre-processing.
+ //
+ if ( IIDIDX_IS_INDEX(pti->iidx) )
+ {
+ switch( IIDIDX_INDEX(pti->iidx) )
+ {
+ case THI_IOleClientSite:
+#define METHOD_ONSHOWWINDOW 7
+ if ( pti->dwMethod == METHOD_ONSHOWWINDOW )
+ {
+ //
+ // Here we merge the input queues for the sole reason so that
+ // we can link the object's window activations into the calling
+ // thread's window z-order.
+ //
+
+ hrCaller = CoGetCallerTID( &dwCallerTID );
+
+ if ( hrCaller == S_FALSE )
+ {
+ AttachThreadInput( dwCallerTID, GetCurrentThreadId(),
+ TRUE );
+ }
+ }
+ break;
+
+ case THI_IOleObject:
+#define METHOD_DOVERB 11
+ if ( pti->dwMethod == METHOD_DOVERB )
+ {
+ //
+ // Here we merge the input queues for the sole reason so
+ // that we can link the object's window activations into
+ // the calling thread's window z-order.
+ //
+
+ hrCaller = CoGetCallerTID( &dwCallerTID );
+
+ if ( hrCaller == S_FALSE )
+ {
+ AttachThreadInput( dwCallerTID, GetCurrentThreadId(),
+ TRUE );
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ pti->pThkMgr->SetThkState(THKSTATE_NOCALL);
+
+ dwReturn = Call3216((VPVOID)pti->pvfn, pti->s16.pbStart, cbStack);
+
+ pti->pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT16);
+
+ //
+ // Hacks for specific interface member functions.
+ // Again, the placement of these is by no means an optimal solution.
+ // They can be moved as long as they have the same effect for just these
+ // interfaces. This section is for post-processing.
+ //
+ if ( IIDIDX_IS_INDEX(pti->iidx) )
+ {
+ switch( IIDIDX_INDEX(pti->iidx) )
+ {
+ case THI_IOleClientSite:
+ if ( pti->dwMethod == METHOD_ONSHOWWINDOW )
+ {
+ //
+ // Unmerge the input queues afterward.
+ //
+ if ( hrCaller == S_FALSE )
+ {
+ AttachThreadInput( dwCallerTID, GetCurrentThreadId(),
+ FALSE );
+ }
+ }
+ break;
+
+ case THI_IOleObject:
+ if ( pti->dwMethod == METHOD_DOVERB )
+ {
+ //
+ // Unmerge the input queues afterward.
+ //
+ if ( hrCaller == S_FALSE )
+ {
+ AttachThreadInput( dwCallerTID, GetCurrentThreadId(),
+ FALSE );
+ }
+ }
+
+#define METHOD_GETCLIENTSITE 4
+ if ( pti->dwMethod == METHOD_GETCLIENTSITE )
+ {
+ //
+ // Excel 5.0a needs to perform some special processing
+ // on the way out of a IOleObject::GetClientSite call.
+ // See CTHKMGR.CXX and APINOT.CXX for more details.
+ //
+ if ( TlsThkGetAppCompatFlags() & OACF_CLIENTSITE_REF )
+ {
+ //
+ // Tell the thkmgr that we are thunking a bad
+ // IOleObject::GetClientSite reference on the way out.
+ //
+ thkDebugOut((DEB_WARN,"TC3216: OACF_CLIENTSITE_REF used: "
+ "Setting to clientsite thunk state\n"));
+
+ pti->pThkMgr->SetThkState(
+ THKSTATE_INVOKETHKOUT16_CLIENTSITE);
+ }
+ }
+ break;
+
+ case THI_IOleInPlaceFrame:
+#define METHOD_REMOVEMENUS 11
+ //
+ // Winword 6.0a didn't call OleSetMenuDescriptor(NULL)
+ // during its IOleInPlaceFrame::RemoveMenus. This leaves
+ // OLE's frame filter in place. The frame filter holds references
+ // to some objects so everybody's refcounting gets thrown off
+ // Here, when we see a RemoveMenus call completing we force
+ // the OleSetMenuDescriptor(NULL) call to occur. This shuts
+ // down the frame filter and corrects the reference counts.
+ //
+ // There is one other hack necessary: Word unsubclasses the
+ // window itself directly rather than going through
+ // OleSetMenuDescriptor. Therefore the frame filter code
+ // is patched to only unhook if it detects that it is the
+ // current hook
+ //
+ // See APINOT.CXX for more hack code.
+ //
+ if (pti->dwMethod == METHOD_REMOVEMENUS)
+ {
+ if ( TlsThkGetAppCompatFlags() & OACF_RESETMENU )
+ {
+ HRESULT hr;
+ HWND hwnd;
+ LPOLEINPLACEFRAME lpoipf;
+
+ pti->pThkMgr->SetThkState(THKSTATE_NOCALL);
+
+ lpoipf = (LPOLEINPLACEFRAME)pti->this32;
+ hr = lpoipf->GetWindow( &hwnd );
+
+ pti->pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT16);
+
+ if ( FAILED(hr) )
+ {
+ break;
+ }
+
+ thkDebugOut((DEB_WARN,
+ "TC3216: OACF_RESETMENU used: "
+ "Setting menu descriptor "
+ "to NULL on %p\n", hwnd));
+
+ OleSetMenuDescriptor(NULL, hwnd, NULL, NULL, NULL);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if ( !pti->fResultThunked )
+ {
+ dwReturn = TransformHRESULT_1632( dwReturn );
+
+#if DBG == 1
+ if (FAILED(dwReturn) )
+ {
+ thkDebugOut((DEB_FAILURES,
+ "Call3216 pvfn = %08lX Probably failed hr = %08lX\n",
+ pti->pvfn, dwReturn));
+ }
+#endif
+ }
+
+ thkDebugOut((DEB_ITRACE,
+ "ThunkCall3216 #(%x) returns 0x%08lX\n",
+ ulThunkCall3216_count,
+ dwReturn));
+
+ return dwReturn;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetOwnerPublicHMEM16, public
+//
+// Synopsis: Changes the 16-bit memory handle into a public selector, owned
+// by nobody. This prevents any app from taking it away when it
+// is cleaned up.
+//
+// Arguments: [hmem] - 16-bit memory handle
+//
+// Returns: Appropriate status code
+//
+// History: 13-Jul-94 BobDay Created it
+//
+//----------------------------------------------------------------------------
+void SetOwnerPublicHMEM16( DWORD hmem )
+{
+ CallbackTo16(gdata16Data.fnSetOwnerPublic16, hmem );
+}
diff --git a/private/ole32/olethunk/olethk32/inv16.hxx b/private/ole32/olethunk/olethk32/inv16.hxx
new file mode 100644
index 000000000..a317ad370
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/inv16.hxx
@@ -0,0 +1,21 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: inv16.hxx
+//
+// Contents: 32->16 invoke function header
+//
+// History: 25-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __INV16_HXX__
+#define __INV16_HXX__
+
+DWORD InvokeOn16(IIDIDX iidx, DWORD dwMethod, LPVOID pvStack32);
+DWORD ThunkCall3216(THUNKINFO *pti);
+void SetOwnerPublicHMEM16( DWORD hMem16 );
+
+#endif // #ifndef __INV16_HXX__
diff --git a/private/ole32/olethunk/olethk32/inv32.cxx b/private/ole32/olethunk/olethk32/inv32.cxx
new file mode 100644
index 000000000..25245d2fc
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/inv32.cxx
@@ -0,0 +1,496 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: inv32.cxx
+//
+// Contents: Implementation of InvokeOn32
+//
+// History: 22-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+STDAPI_(BOOL) IsValidInterface( void FAR* pv );
+
+#include <apilist.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Function: InvokeOn32, public
+//
+// Synopsis: Sets up the THUNKINFO and starts thunking for a 16->32 call
+//
+// Arguments: [dw1] - Ignored
+// [dwMethod] - Method index
+// [pvStack32] - 32-bit stack
+//
+// Returns: Appropriate status code
+//
+// History: 18-Dec-93 JohannP Created
+// 21-Feb-94 DrewB Modified
+// 09-Dec-94 JohannP added stack switching
+//
+// Note: On WIN95 this function get is executed on the 32 bit stack.
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+extern "C"
+{
+ULONG InvokeOn32_count = 0;
+ULONG InvokeOn32_break = 0;
+
+int _iInvokeOn32BreakIidx = -1;
+int _iInvokeOn32BreakMethod = -1;
+};
+#endif
+
+
+// InvokeOn32 uses a lot of local variables so allocate its locals
+// rather than declaring them on the stack. This saves roughly
+// 150 bytes of stack per call
+
+struct INVOKE32RECORD
+{
+ THOP CONST *pThop;
+ THOP CONST * CONST *ppThop;
+ UINT uiThop;
+ VTBLFN CONST *pvfnVtbl;
+ VTBLFN CONST * CONST *ppvfnThis32;
+ DWORD dwStack32[MAX_PARAMS];
+ THUNKINFO ti;
+ VPVOID vpvThis16;
+ THUNK1632OBJ UNALIGNED *pto;
+ IIDIDX iidx;
+ ThreadData *ptd;
+};
+
+STDAPI_(DWORD) SSAPI(InvokeOn32)(DWORD dw1, DWORD dwMethod, LPVOID pvStack16)
+{
+ // NOTE: Do not declare local variables in this routine
+ // except for debug builds
+ INVOKE32RECORD *pir;
+ DWORD dwResult;
+
+#if DBG == 1
+ ULONG ulInvokeOn32_count = ++InvokeOn32_count;
+
+ if (InvokeOn32_count == InvokeOn32_break)
+ {
+ DebugBreak();
+ }
+
+ thkDebugOut((DEB_ITRACE, "%sInvokeOn32(0x%08x, %p)\n",
+ NestingLevelString(),
+ dwMethod, pvStack16));
+#endif // DBG
+
+ pir = (INVOKE32RECORD *)STACKALLOC32(sizeof(INVOKE32RECORD));
+ if (pir == NULL)
+ {
+ // BUGBUG - This error isn't guaranteed to mean anything for
+ // this call. Not much else we can do, though
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ // pvStack16 is the pointer to the first parameter of the 16-bit
+ // routine. The compiler will adjust it appropriately according
+ // to the calling convention of the routine so for PASCAL APIs
+ // it will be high and for CDECL methods it will be low
+
+ pir->ti.s16.pbStart = (BYTE *)pvStack16;
+ pir->ti.s16.pbCurrent = pir->ti.s16.pbStart;
+
+ pir->ti.s32.pbStart = (BYTE *)pir->dwStack32;
+ pir->ti.s32.pbCurrent = pir->ti.s32.pbStart;
+
+ pir->ti.scResult = S_OK;
+ pir->ti.fResultThunked = FALSE;
+
+ if (dwMethod >= THK_API_BASE)
+ {
+ dwMethod -= THK_API_BASE;
+ pir->iidx = IIDIDX_INVALID;
+
+ // APIs are handled as if there were a giant interface which
+ // contains all the APIs as methods.
+ pir->ppThop = apthopsApiThops;
+ pir->uiThop = THK_API_COUNT;
+
+ pir->pvfnVtbl = apfnApiFunctions;
+
+ // APIs are pascal so we need to move downward in memory to
+ // get to the next parameter
+ pir->ti.s16.iDir = -1;
+
+ pir->ti.dwCallerProxy = 0;
+ }
+ else
+ {
+ // For each interface there is an array of thop strings, one for
+ // each method. The IUnknown methods don't have thop strings so
+ // bias the thop string pointer to account for that
+
+ thkAssert(dwMethod >= SMI_COUNT);
+
+ // Methods are cdecl so we need to move upwards in memory to
+ // get to the next parameter
+ pir->ti.s16.iDir = 1;
+
+ // We need to look up the appropriate method pointer by
+ // looking in the 32-bit object's vtable
+ GET_STACK16(&pir->ti, pir->vpvThis16, VPVOID);
+
+ thkDebugOut((DEB_INVOKES,
+ "InvokeOn32: vpvThis16 = %08lX\n", pir->vpvThis16 ));
+
+ pir->pto = FIXVDMPTR(pir->vpvThis16, THUNK1632OBJ);
+ if (pir->pto == NULL)
+ {
+ STACKFREE32(pir, sizeof(INVOKE32RECORD));
+ return (DWORD)E_INVALIDARG;
+ }
+
+ if ((pir->pto->grfFlags & PROXYFLAG_TEMPORARY) == 0)
+ {
+ // Make sure proxy is still valid.
+ // BUGBUG: After PPC/Win95 we might want to look at using
+ // a signiture for validating this rather than IsValidInterface
+ // because it will speed this code path up.
+ if (!IsValidInterface(pir->pto->punkThis32))
+ {
+ thkDebugOut((
+ DEB_ERROR, "InvokeOn32: %p: Invalid proxied object %p\n",
+ pir->vpvThis16, pir->pto->punkThis32));
+ STACKFREE32(pir, sizeof(INVOKE32RECORD));
+ RELVDMPTR(pir->vpvThis16);
+ return (DWORD)E_INVALIDARG;
+ }
+
+ DebugValidateProxy1632(pir->vpvThis16);
+
+ pir->ppvfnThis32 = (VTBLFN CONST * CONST*)pir->pto->punkThis32;
+ }
+ else
+ {
+ // Temporary proxies cannot be validated
+
+ // A temporary proxy's this pointer is actually a pointer
+ // to the real this pointer, so indirect through the this
+ // pointer to retrieve the real this pointer
+ pir->ppvfnThis32 = (VTBLFN CONST * CONST *)*(void **)pir->pto->punkThis32;
+ thkAssert(pir->ppvfnThis32 != NULL);
+ thkDebugOut((DEB_WARN, "WARNING: InvokeOn32 on temporary "
+ "%s proxy for %p\n", IidIdxString(pir->pto->iidx),
+ pir->ppvfnThis32));
+ }
+
+ pir->iidx = pir->pto->iidx;
+ RELVDMPTR(pir->vpvThis16);
+
+ if (pir->ppvfnThis32 == NULL)
+ {
+ STACKFREE32(pir, sizeof(INVOKE32RECORD));
+ return (DWORD)E_FAIL;
+ }
+
+ pir->ti.dwCallerProxy = pir->vpvThis16;
+
+ thkAssert(pir->iidx >= 0 && pir->iidx < THI_COUNT);
+
+ pir->ppThop = athopiInterfaceThopis[pir->iidx].ppThops-SMI_COUNT;
+ pir->uiThop = athopiInterfaceThopis[pir->iidx].uiSize;
+
+ pir->pvfnVtbl = *pir->ppvfnThis32;
+
+ // Push the 32-bit this pointer on the stack first
+ TO_STACK32(&pir->ti, pir->ppvfnThis32, VTBLFN CONST * CONST*);
+ }
+
+ thkAssert(dwMethod < pir->uiThop);
+
+ pir->pThop = pir->ppThop[dwMethod];
+
+ thkAssert(pir->pThop != NULL);
+
+ pir->ti.pThop = pir->pThop;
+ pir->ti.pvfn = pir->pvfnVtbl[dwMethod];
+ pir->ti.iidx = pir->iidx;
+ pir->ti.dwMethod = dwMethod;
+
+ pir->ptd = TlsThkGetData();
+ if (pir->ptd == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: InvokeOn32: Call refused\n"));
+
+ STACKFREE32(pir, sizeof(INVOKE32RECORD));
+ return (DWORD)E_FAIL;
+ }
+
+ pir->ti.pThkMgr = pir->ptd->pCThkMgr;
+ thkAssert(pir->ti.pThkMgr != NULL);
+
+#if DBG == 1
+ if (pir->iidx == IIDIDX_INVALID)
+ {
+ thkDebugOut((DEB_INVOKES, "%s#(%04X):InvokeOn32 on %p, %s\n",
+ NestingLevelString(), ulInvokeOn32_count,
+ pir->ti.pvfn, apszApiNames[dwMethod]));
+ }
+ else
+ {
+ thkDebugOut((DEB_INVOKES, "%s#(%04X):InvokeOn32 on %p:%p, %s::%s (0x%0x:0x%0x)\n",
+ NestingLevelString(), ulInvokeOn32_count,
+ pir->ppvfnThis32, pir->ti.pvfn,
+ inInterfaceNames[pir->iidx].pszInterface,
+ inInterfaceNames[pir->iidx].ppszMethodNames[dwMethod],
+ pir->iidx,
+ dwMethod));
+ }
+#endif
+
+ DebugIncrementNestingLevel();
+ // save and set the new thunk state
+
+ pir->ti.pThkMgr->SetThkState(THKSTATE_INVOKETHKIN32);
+
+#if DBG == 1
+ if ((_iInvokeOn32BreakIidx > 0 &&
+ _iInvokeOn32BreakIidx == (int)pir->iidx) &&
+ (_iInvokeOn32BreakMethod < 0 ||
+ _iInvokeOn32BreakMethod == (int)dwMethod))
+ {
+ DebugBreak();
+ }
+#endif
+
+#if DBG == 1
+ SStackRecord sr;
+
+ RecordStackState16(&sr);
+#endif
+
+#if DBG == 1
+ if (fStabilizeProxies)
+#endif
+ {
+ // HACK HACK HACK
+ // Because of changes in the way refcounting rules work between
+ // 16 and 32-bits, we have to stabilize this pointers for
+ // 16->32 calls. To effect this, we do a purely local AddRef
+ //
+ // Temporary proxies are not valid proxies so they cannot
+ // be stabilized
+ if (pir->iidx != IIDIDX_INVALID)
+ {
+ pir->pto = FIXVDMPTR(pir->vpvThis16, THUNK1632OBJ);
+ if ((pir->pto->grfFlags & PROXYFLAG_TEMPORARY) == 0)
+ {
+ pir->ti.pThkMgr->LocalAddRefProxy(pir->pto);
+ }
+ RELVDMPTR(pir->vpvThis16);
+ }
+ }
+
+ dwResult = EXECUTE_THOP1632(&pir->ti);
+
+#if DBG == 1
+ if (fStabilizeProxies)
+#endif
+ {
+ // Remove our stabilization reference
+ // Note that we don't really know whether the proxy is
+ // still valid, so we're just crossing our fingers here
+ // and hoping that things continue to work
+ if (pir->iidx != IIDIDX_INVALID)
+ {
+ pir->pto = FIXVDMPTR(pir->vpvThis16, THUNK1632OBJ);
+ if ((pir->pto->grfFlags & PROXYFLAG_TEMPORARY) == 0)
+ {
+ RELVDMPTR(pir->vpvThis16);
+
+ DebugValidateProxy1632(pir->vpvThis16);
+
+ pir->ti.pThkMgr->ReleaseProxy1632(pir->vpvThis16);
+ }
+ else
+ {
+ RELVDMPTR(pir->vpvThis16);
+ }
+ }
+ }
+
+#if DBG == 1
+
+ if ( !pir->ti.fResultThunked && FAILED(dwResult) )
+ {
+ if (pir->iidx == IIDIDX_INVALID)
+ {
+ thkDebugOut((DEB_FAILURES,
+ "InvokeOn32 probable failure %s sc = %08lX\n",
+ apszApiNames[dwMethod],
+ dwResult));
+ }
+ else
+ {
+ thkDebugOut((DEB_FAILURES,
+ "InvokeOn32 probable failure %s::%s sc = %08lX\n",
+ inInterfaceNames[pir->iidx].pszInterface,
+ inInterfaceNames[pir->iidx].ppszMethodNames[dwMethod],
+ dwResult));
+ }
+ }
+
+ CheckStackState16(&sr);
+
+#endif
+
+ pir->ti.pThkMgr->SetThkState(THKSTATE_NOCALL);
+
+ DebugDecrementNestingLevel();
+
+ if ( !pir->ti.fResultThunked )
+ {
+ dwResult = TransformHRESULT_3216( dwResult );
+ }
+
+#if DBG == 1
+ if (pir->iidx == IIDIDX_INVALID)
+ {
+ thkDebugOut((DEB_INVOKES,
+ "%s#(%04X):InvokeOn32 on %p, %s returns 0x%08lX\n",
+ NestingLevelString(), ulInvokeOn32_count, pir->ti.pvfn,
+ apszApiNames[dwMethod], dwResult ));
+ }
+ else
+ {
+ thkDebugOut((DEB_INVOKES,
+ "%s#(%04X):InvokeOn32 on %p:%p, %s::%s returns 0x%08lX\n",
+ NestingLevelString(), ulInvokeOn32_count,
+ pir->ppvfnThis32,
+ pir->ti.pvfn, inInterfaceNames[pir->iidx].pszInterface,
+ inInterfaceNames[pir->iidx].ppszMethodNames[dwMethod],
+ dwResult));
+ }
+#endif
+
+ STACKFREE32(pir, sizeof(INVOKE32RECORD));
+
+ return dwResult;
+}
+
+
+#ifdef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Function: SSCallback16
+//
+// Synopsis: Switches to 16 bit and calls back to 16 bit.
+//
+// Arguments: [vpfn16] -- function pointer
+// [dwParam] -- pointer to parameter
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD WINAPI SSCallback16(DWORD vpfn16, DWORD dwParam)
+{
+ DWORD dwRet;
+ // switch to the 16 bit stack
+ //
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "%sSSCallback16 32->16(%p)\n",NestingLevelString(), vpfn16));
+ dwRet = SSCall(8, SSF_SmallStack, WOWCallback16, vpfn16, dwParam);
+ StackDebugOut((DEB_STCKSWTCH, "%sSSCallback16 32<-16 done\n",NestingLevelString() ));
+ }
+ else
+ {
+ dwRet = WOWCallback16(vpfn16, dwParam);
+ }
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SSCallback16Ex
+//
+// Synopsis: Like SSCallback16 except can handle up 16 bytes of parametes
+//
+// Arguments: [vpfn16] -- see Callback16Ex
+// [dwFlags] --
+// [cbArgs] --
+// [pArgs] --
+// [pdwRetCode] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+BOOL WINAPI SSCallback16Ex(DWORD vpfn16, DWORD dwFlags,
+ DWORD cbArgs, PVOID pArgs, PDWORD pdwRetCode)
+{
+ DWORD dwRet;
+ // switch to the 16 bit stack
+ //
+ if (SSONBIGSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "%sSSCallback16Ex 32->16 (%p)\n",NestingLevelString(), vpfn16));
+ dwRet = SSCall(20, SSF_SmallStack, WOWCallback16Ex,vpfn16, dwFlags, cbArgs, pArgs, pdwRetCode);
+ StackDebugOut((DEB_STCKSWTCH, "%sSSCallback16Ex 32<-16 done\n",NestingLevelString() ));
+ }
+ else
+ {
+ dwRet = WOWCallback16Ex(vpfn16, dwFlags, cbArgs, pArgs, pdwRetCode);
+ }
+ return dwRet;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: InvokeOn32
+//
+// Synopsis: Switches to the 32 bit stack and calls SSAPI(InvokeOn32)
+//
+// Arguments: [dw1] -- See SSAPI(InvokeOn32)
+// [dwMethod] --
+// [pvStack16] --
+//
+// Returns:
+//
+// History: 12-08-94 JohannP (Johann Posch) Created
+//
+// Notes: Only executed under WIN95
+//
+//----------------------------------------------------------------------------
+STDAPI_(DWORD) InvokeOn32 (DWORD dw1, DWORD dwMethod, LPVOID pvStack16)
+{
+ DWORD dwRes;
+ if (SSONSMALLSTACK())
+ {
+ StackDebugOut((DEB_STCKSWTCH, "%sSSInvokeOn32 16->32 (0x%08x, %p)\n",
+ NestingLevelString(), dwMethod, pvStack16));
+ dwRes = SSCall(12 ,SSF_BigStack, SSInvokeOn32, dw1, dwMethod, pvStack16);
+ StackDebugOut((DEB_STCKSWTCH, "%sSSInvokeOn32 16<-32 done(0x%08x, %p)\n",
+ NestingLevelString(), dwMethod, pvStack16));
+ }
+ else
+ dwRes = SSInvokeOn32(dw1, dwMethod, pvStack16);
+
+ return dwRes;
+}
+
+#endif // _CHICAGO_
+
diff --git a/private/ole32/olethunk/olethk32/map_dwp.h b/private/ole32/olethunk/olethk32/map_dwp.h
new file mode 100644
index 000000000..7c2173143
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/map_dwp.h
@@ -0,0 +1,66 @@
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+
+class FAR CMapDwordPtr
+{
+public:
+ // Construction
+ CMapDwordPtr(UINT nBlockSize=10)
+ : m_mkv(sizeof(void FAR*), sizeof(DWORD), nBlockSize) { }
+
+ // Attributes
+ // number of elements
+ int GetCount() const
+ { return m_mkv.GetCount(); }
+ BOOL IsEmpty() const
+ { return GetCount() == 0; }
+
+ // Lookup
+ BOOL Lookup(DWORD key, void FAR* FAR& value) const
+ { return m_mkv.Lookup((LPVOID) &key, sizeof(DWORD), (LPVOID)&value); }
+
+ BOOL LookupHKey(HMAPKEY hKey, void FAR* FAR& value) const
+ { return m_mkv.LookupHKey(hKey, (LPVOID)&value); }
+
+ BOOL LookupAdd(DWORD key, void FAR* FAR& value) const
+ { return m_mkv.LookupAdd((LPVOID)&key, sizeof(DWORD), (LPVOID)&value); }
+
+ // Add/Delete
+ // add a new (key, value) pair
+ BOOL SetAt(DWORD key, void FAR* value)
+ { return m_mkv.SetAt((LPVOID) &key, sizeof(DWORD), (LPVOID)&value); }
+ BOOL SetAtHKey(HMAPKEY hKey, void FAR* value)
+ { return m_mkv.SetAtHKey(hKey, (LPVOID)&value); }
+
+ // removing existing (key, ?) pair
+ BOOL RemoveKey(DWORD key)
+ { return m_mkv.RemoveKey((LPVOID) &key, sizeof(DWORD)); }
+
+ BOOL RemoveHKey(HMAPKEY hKey)
+ { return m_mkv.RemoveHKey(hKey); }
+
+ void RemoveAll()
+ { m_mkv.RemoveAll(); }
+
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return m_mkv.GetStartPosition(); }
+
+ void GetNextAssoc(POSITION FAR& rNextPosition, DWORD FAR& rKey, void FAR* FAR& rValue) const
+ { m_mkv.GetNextAssoc(&rNextPosition, (LPVOID)&rKey, NULL, (LPVOID)&rValue); }
+
+ HMAPKEY GetHKey(DWORD key) const
+ { return m_mkv.GetHKey((LPVOID)&key, sizeof(DWORD)); }
+
+#ifdef _DEBUG
+ void AssertValid() const
+ { m_mkv.AssertValid(); }
+#endif
+
+private:
+ CMapKeyToValue m_mkv;
+};
diff --git a/private/ole32/olethunk/olethk32/map_kv.cxx b/private/ole32/olethunk/olethk32/map_kv.cxx
new file mode 100644
index 000000000..152c717d3
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/map_kv.cxx
@@ -0,0 +1,540 @@
+/////////////////////////////////////////////////////////////////////////////
+// class CMapKeyToValue - a mapping from 'KEY's to 'VALUE's, passed in as
+// pv/cb pairs. The keys can be variable length, although we optmizize the
+// case when they are all the same.
+//
+/////////////////////////////////////////////////////////////////////////////
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <olecoll.h>
+#include "map_kv.h"
+#include "plex.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+//CMapKeyToValue::CMapKeyToValue(DWORD memctx, UINT cbValue, UINT cbKey,
+CMapKeyToValue::CMapKeyToValue(UINT cbValue, UINT cbKey,
+ int nBlockSize, LPFNHASHKEY lpfnHashKey, UINT nHashSize)
+{
+ Assert(nBlockSize > 0);
+
+ m_cbValue = cbValue;
+ m_cbKey = cbKey;
+ m_cbKeyInAssoc = cbKey == 0 ? sizeof(CKeyWrap) : cbKey;
+
+ m_pHashTable = NULL;
+ m_nHashTableSize = nHashSize;
+ m_lpfnHashKey = lpfnHashKey;
+
+ m_nCount = 0;
+ m_pFreeList = NULL;
+ m_pBlocks = NULL;
+ m_nBlockSize = nBlockSize;
+ //if (memctx == MEMCTX_SAME)
+ // memctx = CoMemctxOf(this);
+ //m_memctx = memctx;
+ //Assert(m_memctx != MEMCTX_UNKNOWN);
+}
+
+CMapKeyToValue::~CMapKeyToValue()
+{
+ ASSERT_VALID(this);
+ RemoveAll();
+ Assert(m_nCount == 0);
+}
+
+
+// simple, default hash function
+// REVIEW: need to check the value in this for GUIDs and strings
+STDAPI_(UINT) MKVDefaultHashKey(LPVOID pKey, UINT cbKey)
+{
+ UINT hash = 0;
+ BYTE FAR* lpb = (BYTE FAR*)pKey;
+
+ while (cbKey-- != 0)
+ hash = 257 * hash + *lpb++;
+
+ return hash;
+}
+
+
+BOOL CMapKeyToValue::InitHashTable()
+{
+ ASSERT_VALID(this);
+ Assert(m_nHashTableSize > 0);
+
+ if (m_pHashTable != NULL)
+ return TRUE;
+
+ Assert(m_nCount == 0);
+
+ if ((m_pHashTable = (CAssoc FAR* FAR*)CoTaskMemAlloc(m_nHashTableSize * sizeof(CAssoc FAR*))) == NULL)
+ return FALSE;
+
+ memset(m_pHashTable, 0, sizeof(CAssoc FAR*) * m_nHashTableSize);
+
+ ASSERT_VALID(this);
+
+ return TRUE;
+}
+
+
+void CMapKeyToValue::RemoveAll()
+{
+ ASSERT_VALID(this);
+
+ // free all key values and then hash table
+ if (m_pHashTable != NULL)
+ {
+ // destroy assocs
+ for (UINT nHash = 0; nHash < m_nHashTableSize; nHash++)
+ {
+ register CAssoc FAR* pAssoc;
+ for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL;
+ pAssoc = pAssoc->pNext)
+ // assoc itself is freed by FreeDataChain below
+ FreeAssocKey(pAssoc);
+ }
+
+ // free hash table
+ CoTaskMemFree(m_pHashTable);
+ m_pHashTable = NULL;
+ }
+
+ m_nCount = 0;
+ m_pFreeList = NULL;
+ m_pBlocks->FreeDataChain();
+ m_pBlocks = NULL;
+
+ ASSERT_VALID(this);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Assoc helpers
+// CAssoc's are singly linked all the time
+
+CMapKeyToValue::CAssoc FAR*
+ CMapKeyToValue::NewAssoc(UINT hash, LPVOID pKey, UINT cbKey, LPVOID pValue)
+{
+ if (m_pFreeList == NULL)
+ {
+ // add another block
+ CPlex FAR* newBlock = CPlex::Create(m_pBlocks, m_nBlockSize, SizeAssoc());
+
+ if (newBlock == NULL)
+ return NULL;
+
+ // chain them into free list
+ register BYTE FAR* pbAssoc = (BYTE FAR*) newBlock->data();
+ // free in reverse order to make it easier to debug
+ pbAssoc += (m_nBlockSize - 1) * SizeAssoc();
+ for (int i = m_nBlockSize-1; i >= 0; i--, pbAssoc -= SizeAssoc())
+ {
+ ((CAssoc FAR*)pbAssoc)->pNext = m_pFreeList;
+ m_pFreeList = (CAssoc FAR*)pbAssoc;
+ }
+ }
+ Assert(m_pFreeList != NULL); // we must have something
+
+ CMapKeyToValue::CAssoc FAR* pAssoc = m_pFreeList;
+
+ // init all fields except pNext while still on free list
+ pAssoc->nHashValue = hash;
+ if (!SetAssocKey(pAssoc, pKey, cbKey))
+ return NULL;
+
+ SetAssocValue(pAssoc, pValue);
+
+ // remove from free list after successfully initializing it (except pNext)
+ m_pFreeList = m_pFreeList->pNext;
+ m_nCount++;
+ Assert(m_nCount > 0); // make sure we don't overflow
+
+ return pAssoc;
+}
+
+
+// free individual assoc by freeing key and putting on free list
+void CMapKeyToValue::FreeAssoc(CMapKeyToValue::CAssoc FAR* pAssoc)
+{
+ pAssoc->pNext = m_pFreeList;
+ m_pFreeList = pAssoc;
+ m_nCount--;
+ Assert(m_nCount >= 0); // make sure we don't underflow
+
+ FreeAssocKey(pAssoc);
+}
+
+
+// find association (or return NULL)
+CMapKeyToValue::CAssoc FAR*
+CMapKeyToValue::GetAssocAt(LPVOID pKey, UINT cbKey, UINT FAR& nHash) const
+{
+ if (m_lpfnHashKey)
+ nHash = (*m_lpfnHashKey)(pKey, cbKey) % m_nHashTableSize;
+ else
+ nHash = MKVDefaultHashKey(pKey, cbKey) % m_nHashTableSize;
+
+ if (m_pHashTable == NULL)
+ return NULL;
+
+ // see if it exists
+ register CAssoc FAR* pAssoc;
+ for (pAssoc = m_pHashTable[nHash]; pAssoc != NULL; pAssoc = pAssoc->pNext)
+ {
+ if (CompareAssocKey(pAssoc, pKey, cbKey))
+ return pAssoc;
+ }
+ return NULL;
+}
+
+
+BOOL CMapKeyToValue::CompareAssocKey(CAssoc FAR* pAssoc, LPVOID pKey2, UINT cbKey2) const
+{
+ LPVOID pKey1;
+ UINT cbKey1;
+
+ GetAssocKeyPtr(pAssoc, &pKey1, &cbKey1);
+ return cbKey1 == cbKey2 && memcmp(pKey1, pKey2, cbKey1) == 0;
+}
+
+
+BOOL CMapKeyToValue::SetAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const
+{
+ Assert(cbKey == m_cbKey || m_cbKey == 0);
+
+ if (m_cbKey == 0)
+ {
+ Assert(m_cbKeyInAssoc == sizeof(CKeyWrap));
+
+ // alloc, set size and pointer
+ if ((pAssoc->key.pKey = CoTaskMemAlloc(cbKey)) == NULL)
+ return FALSE;
+
+ pAssoc->key.cbKey = cbKey;
+ }
+
+ LPVOID pKeyTo;
+
+ GetAssocKeyPtr(pAssoc, &pKeyTo, &cbKey);
+
+ memcpy(pKeyTo, pKey, cbKey);
+
+ return TRUE;
+}
+
+
+// gets pointer to key and its length
+void CMapKeyToValue::GetAssocKeyPtr(CAssoc FAR* pAssoc, LPVOID FAR* ppKey,UINT FAR* pcbKey) const
+{
+ if (m_cbKey == 0)
+ {
+ // variable length key; go indirect
+ *ppKey = pAssoc->key.pKey;
+ *pcbKey = pAssoc->key.cbKey;
+ }
+ else
+ {
+ // fixed length key; key in assoc
+ *ppKey = (LPVOID)&pAssoc->key;
+ *pcbKey = m_cbKey;
+ }
+}
+
+
+void CMapKeyToValue::FreeAssocKey(CAssoc FAR* pAssoc) const
+{
+ if (m_cbKey == 0)
+ CoTaskMemFree(pAssoc->key.pKey);
+}
+
+
+void CMapKeyToValue::GetAssocValuePtr(CAssoc FAR* pAssoc, LPVOID FAR* ppValue) const
+{
+ *ppValue = (char FAR*)&pAssoc->key + m_cbKeyInAssoc;
+}
+
+
+void CMapKeyToValue::GetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const
+{
+ LPVOID pValueFrom;
+ GetAssocValuePtr(pAssoc, &pValueFrom);
+ Assert(pValue != NULL);
+ memcpy(pValue, pValueFrom, m_cbValue);
+}
+
+
+void CMapKeyToValue::SetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const
+{
+ LPVOID pValueTo;
+ GetAssocValuePtr(pAssoc, &pValueTo);
+ if (pValue == NULL)
+ memset(pValueTo, 0, m_cbValue);
+ else
+ memcpy(pValueTo, pValue, m_cbValue);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// lookup value given key; return FALSE if key not found; in that
+// case, the value is set to all zeros
+BOOL CMapKeyToValue::Lookup(LPVOID pKey, UINT cbKey, LPVOID pValue) const
+{
+ UINT nHash;
+ HMAPKEY hmapkey = (HMAPKEY)GetAssocAt(pKey, cbKey, nHash);
+ return LookupHKey(hmapkey, pValue);
+ //return LookupHKey((HMAPKEY)GetAssocAt(pKey, cbKey, nHash), pValue);
+}
+
+
+// lookup value given key; return FALSE if NULL (or bad) key; in that
+// case, the value is set to all zeros
+BOOL CMapKeyToValue::LookupHKey(HMAPKEY hKey, LPVOID pValue) const
+{
+ // REVIEW: would like some way to verify that hKey is valid
+ register CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+ if (pAssoc == NULL)
+ {
+ memset(pValue, 0, m_cbValue);
+ return FALSE; // not in map
+ }
+
+ ASSERT_VALID(this);
+
+ GetAssocValue(pAssoc, pValue);
+ return TRUE;
+}
+
+
+// lookup and if not found add; returns FALSE only if OOM; if added,
+// value added and pointer passed are set to zeros.
+BOOL CMapKeyToValue::LookupAdd(LPVOID pKey, UINT cbKey, LPVOID pValue) const
+{
+ if (Lookup(pKey, cbKey, pValue))
+ return TRUE;
+
+ // value set to zeros since lookup failed
+
+ return ((CMapKeyToValue FAR*)this)->SetAt(pKey, cbKey, NULL);
+}
+
+
+// the only place new assocs are created; return FALSE if OOM;
+// never returns FALSE if keys already exists
+BOOL CMapKeyToValue::SetAt(LPVOID pKey, UINT cbKey, LPVOID pValue)
+{
+ UINT nHash;
+ register CAssoc FAR* pAssoc;
+
+ ASSERT_VALID(this);
+
+ if ((pAssoc = GetAssocAt(pKey, cbKey, nHash)) == NULL)
+ {
+ if (!InitHashTable())
+ // out of memory
+ return FALSE;
+
+ // it doesn't exist, add a new Association
+ if ((pAssoc = NewAssoc(nHash, pKey, cbKey, pValue)) == NULL)
+ return FALSE;
+
+ // put into hash table
+ pAssoc->pNext = m_pHashTable[nHash];
+ m_pHashTable[nHash] = pAssoc;
+
+ ASSERT_VALID(this);
+ }
+ else
+ {
+ SetAssocValue(pAssoc, pValue);
+ }
+
+ return TRUE;
+}
+
+
+// set existing hkey to value; return FALSE if NULL or bad key
+BOOL CMapKeyToValue::SetAtHKey(HMAPKEY hKey, LPVOID pValue)
+{
+ // REVIEW: would like some way to verify that hKey is valid
+ register CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+ if (pAssoc == NULL)
+ return FALSE; // not in map
+
+ ASSERT_VALID(this);
+
+ SetAssocValue(pAssoc, pValue);
+ return TRUE;
+}
+
+
+// remove key - return TRUE if removed
+BOOL CMapKeyToValue::RemoveKey(LPVOID pKey, UINT cbKey)
+{
+ ASSERT_VALID(this);
+
+ if (m_pHashTable == NULL)
+ return FALSE; // nothing in the table
+
+ register CAssoc FAR* FAR* ppAssocPrev;
+ UINT i;
+ if (m_lpfnHashKey)
+ i = (*m_lpfnHashKey)(pKey, cbKey) % m_nHashTableSize;
+ else
+ i = MKVDefaultHashKey(pKey, cbKey) % m_nHashTableSize;
+
+ ppAssocPrev = &m_pHashTable[i];
+
+ CAssoc FAR* pAssoc;
+ for (pAssoc = *ppAssocPrev; pAssoc != NULL; pAssoc = pAssoc->pNext)
+ {
+ if (CompareAssocKey(pAssoc, pKey, cbKey))
+ {
+ // remove it
+ *ppAssocPrev = pAssoc->pNext; // remove from list
+ FreeAssoc(pAssoc);
+ ASSERT_VALID(this);
+ return TRUE;
+ }
+ ppAssocPrev = &pAssoc->pNext;
+ }
+ return FALSE; // not found
+}
+
+
+// remove key based on pAssoc (HMAPKEY)
+BOOL CMapKeyToValue::RemoveHKey(HMAPKEY hKey)
+{
+ ASSERT_VALID(this);
+
+ if (m_pHashTable == NULL)
+ return FALSE; // nothing in the table
+
+ // REVIEW: would like some way to verify that hKey is valid
+ CAssoc FAR* pAssoc = (CAssoc FAR*)hKey;
+ if (pAssoc == NULL || pAssoc->nHashValue >= m_nHashTableSize)
+ // null hkey or bad hash value
+ return FALSE;
+
+ register CAssoc FAR* FAR* ppAssocPrev;
+ ppAssocPrev = &m_pHashTable[pAssoc->nHashValue];
+
+ while (*ppAssocPrev != NULL)
+ {
+ if (*ppAssocPrev == pAssoc)
+ {
+ // remove it
+ *ppAssocPrev = pAssoc->pNext; // remove from list
+ FreeAssoc(pAssoc);
+ ASSERT_VALID(this);
+ return TRUE;
+ }
+ ppAssocPrev = &(*ppAssocPrev)->pNext;
+ }
+
+ return FALSE; // not found (must have a screwed up list or passed
+ // a key from another list)
+}
+
+
+HMAPKEY CMapKeyToValue::GetHKey(LPVOID pKey, UINT cbKey) const
+{
+ UINT nHash;
+
+ ASSERT_VALID(this);
+
+ return (HMAPKEY)GetAssocAt(pKey, cbKey, nHash);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Iterating
+
+// for fixed length keys, copies key to pKey; pcbKey can be NULL;
+// for variable length keys, copies pointer to key to pKey; sets pcbKey.
+
+void CMapKeyToValue::GetNextAssoc(POSITION FAR* pNextPosition,
+ LPVOID pKey, UINT FAR* pcbKey, LPVOID pValue) const
+{
+ ASSERT_VALID(this);
+
+ Assert(m_pHashTable != NULL); // never call on empty map
+
+ register CAssoc FAR* pAssocRet = (CAssoc FAR*)*pNextPosition;
+ Assert(pAssocRet != NULL);
+
+ if (pAssocRet == (CAssoc FAR*) BEFORE_START_POSITION)
+ {
+ // find the first association
+ for (UINT nBucket = 0; nBucket < m_nHashTableSize; nBucket++)
+ if ((pAssocRet = m_pHashTable[nBucket]) != NULL)
+ break;
+ Assert(pAssocRet != NULL); // must find something
+ }
+
+ // find next association
+ CAssoc FAR* pAssocNext;
+ if ((pAssocNext = pAssocRet->pNext) == NULL)
+ {
+ // go to next bucket
+ for (UINT nBucket = pAssocRet->nHashValue + 1;
+ nBucket < m_nHashTableSize; nBucket++)
+ if ((pAssocNext = m_pHashTable[nBucket]) != NULL)
+ break;
+ }
+
+ // fill in return data
+ *pNextPosition = (POSITION) pAssocNext;
+
+ // fill in key/pointer to key
+ LPVOID pKeyFrom;
+ UINT cbKey;
+ GetAssocKeyPtr(pAssocRet, &pKeyFrom, &cbKey);
+ if (m_cbKey == 0)
+ // variable length key; just return pointer to key itself
+ *(void FAR* FAR*)pKey = pKeyFrom;
+ else
+ memcpy(pKey, pKeyFrom, cbKey);
+
+ if (pcbKey != NULL)
+ *pcbKey = cbKey;
+
+ // get value
+ GetAssocValue(pAssocRet, pValue);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CMapKeyToValue::AssertValid() const
+{
+#ifdef _DEBUG
+ Assert(m_cbKeyInAssoc == (m_cbKey == 0 ? sizeof(CKeyWrap) : m_cbKey));
+
+ Assert(m_nHashTableSize > 0);
+ Assert(m_nCount == 0 || m_pHashTable != NULL);
+
+ if (m_pHashTable != NULL)
+ Assert(!IsBadReadPtr(m_pHashTable, m_nHashTableSize * sizeof(CAssoc FAR*)));
+
+ if (m_lpfnHashKey)
+ Assert(!IsBadCodePtr((FARPROC)m_lpfnHashKey));
+
+ if (m_pFreeList != NULL)
+ Assert(!IsBadReadPtr(m_pFreeList, SizeAssoc()));
+
+ if (m_pBlocks != NULL)
+ Assert(!IsBadReadPtr(m_pBlocks, SizeAssoc() * m_nBlockSize));
+
+ // some collections live as global variables in the libraries, but
+ // have their existance in some context. Also, we can't check shared
+ // collections since we might be checking the etask collection
+ // which would cause an infinite recursion.
+ // REVIEW: Assert(m_memctx == MEMCTX_SHARED ||
+ // CoMemctxOf(this) == MEMCTX_UNKNOWN || CoMemctxOf(this) == m_memctx);
+#endif //_DEBUG
+}
+
diff --git a/private/ole32/olethunk/olethk32/map_kv.h b/private/ole32/olethunk/olethk32/map_kv.h
new file mode 100644
index 000000000..608b6bf32
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/map_kv.h
@@ -0,0 +1,116 @@
+#ifndef __MAP_KV_H__
+#define __MAP_KV_H__
+
+//#include <memapi.hxx>
+
+/////////////////////////////////////////////////////////////////////////////
+// class CMapKeyToValue - a mapping from 'KEY's to 'VALUE's, passed in as
+// pv/cb pairs. The keys can be variable length, although we optmizize the
+// case when they are all the same.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+STDAPI_(UINT) MKVDefaultHashKey(LPVOID pKey, UINT cbKey);
+
+#ifdef WIN32
+DECLARE_HANDLE(HMAPKEY);
+#else
+DECLARE_HANDLE32(HMAPKEY);
+#endif
+
+typedef UINT (STDAPICALLTYPE FAR* LPFNHASHKEY)(LPVOID, UINT);
+
+class FAR CMapKeyToValue
+{
+public:
+ CMapKeyToValue(UINT cbValue, UINT cbKey = 0,
+ int nBlockSize=10,
+ LPFNHASHKEY lpfnHashKey = NULL,
+ UINT nHashSize = 17);
+ ~CMapKeyToValue();
+
+ // number of elements
+ int GetCount() const { return m_nCount; }
+ BOOL IsEmpty() const { return m_nCount == 0; }
+
+ // Lookup; return FALSE if not found
+ BOOL Lookup(LPVOID pKey, UINT cbKey, LPVOID pValue) const;
+ BOOL LookupHKey(HMAPKEY hKey, LPVOID pValue) const;
+ BOOL LookupAdd(LPVOID pKey, UINT cbKey, LPVOID pValue) const;
+
+ // add a new (key, value) pair; return FALSE if out of memory
+ BOOL SetAt(LPVOID pKey, UINT cbKey, LPVOID pValue);
+ BOOL SetAtHKey(HMAPKEY hKey, LPVOID pValue);
+
+ // removing existing (key, ?) pair; return FALSE if no such key
+ BOOL RemoveKey(LPVOID pKey, UINT cbKey);
+ BOOL RemoveHKey(HMAPKEY hKey);
+ void RemoveAll();
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return (m_nCount == 0) ? (POSITION)NULL : BEFORE_START_POSITION; }
+ void GetNextAssoc(POSITION FAR* pNextPosition, LPVOID pKey,
+ UINT FAR* pcbKey, LPVOID pValue) const;
+
+ // return HMAPKEY for given key; returns NULL if not currently in map
+ HMAPKEY GetHKey(LPVOID pKey, UINT cbKey) const;
+
+ void AssertValid() const;
+
+private:
+ // abstracts, somewhat, variable and fixed sized keys; size is really
+ // m_cbKeyInAssoc.
+ union CKeyWrap
+ {
+ BYTE rgbKey[sizeof(LPVOID) + sizeof(UINT)];
+ struct
+ {
+ LPVOID pKey;
+ UINT cbKey;
+ };
+ };
+
+ // Association of one key and one value; NOTE: even though in general
+ // the size of the key and value varies, for any given map,
+ // the size of an assoc is fixed.
+ struct CAssoc
+ {
+ CAssoc FAR* pNext;
+ UINT nHashValue; // needed for efficient iteration
+ CKeyWrap key; // size is really m_cbKeyInAssoc
+ // BYTE rgbValue[m_cbValue];
+ };
+
+ UINT SizeAssoc() const
+ { return sizeof(CAssoc)-sizeof(CKeyWrap) + m_cbKeyInAssoc + m_cbValue; }
+ CAssoc FAR* NewAssoc(UINT hash, LPVOID pKey, UINT cbKey, LPVOID pValue);
+ void FreeAssoc(CAssoc FAR* pAssoc);
+ BOOL CompareAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const;
+ CAssoc FAR* GetAssocAt(LPVOID pKey, UINT cbKey, UINT FAR& nHash) const;
+
+ BOOL SetAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const;
+ void GetAssocKeyPtr(CAssoc FAR* pAssoc, LPVOID FAR* ppKey,UINT FAR* pcbKey) const;
+ void FreeAssocKey(CAssoc FAR* pAssoc) const;
+ void GetAssocValuePtr(CAssoc FAR* pAssoc, LPVOID FAR* ppValue) const;
+ void GetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const;
+ void SetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const;
+
+ BOOL InitHashTable();
+
+ UINT m_cbValue;
+ UINT m_cbKey; // variable length if 0
+ UINT m_cbKeyInAssoc; // always non-zero
+
+ CAssoc FAR* FAR* m_pHashTable;
+ UINT m_nHashTableSize;
+ LPFNHASHKEY m_lpfnHashKey;
+
+ int m_nCount;
+ CAssoc FAR* m_pFreeList;
+ struct CPlex FAR* m_pBlocks;
+ int m_nBlockSize;
+};
+
+
+#endif // !__MAP_KV_H__
diff --git a/private/ole32/olethunk/olethk32/map_kv.hxx b/private/ole32/olethunk/olethk32/map_kv.hxx
new file mode 100644
index 000000000..37e0ed7a1
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/map_kv.hxx
@@ -0,0 +1,114 @@
+#ifndef __MAP_KV_H__
+#define __MAP_KV_H__
+
+/////////////////////////////////////////////////////////////////////////////
+// class CMapKeyToValue - a mapping from 'KEY's to 'VALUE's, passed in as
+// pv/cb pairs. The keys can be variable length, although we optmizize the
+// case when they are all the same.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+STDAPI_(UINT) MKVDefaultHashKey(LPVOID pKey, UINT cbKey);
+
+#ifdef WIN32
+DECLARE_HANDLE(HMAPKEY);
+#else
+DECLARE_HANDLE32(HMAPKEY);
+#endif
+
+typedef UINT (STDAPICALLTYPE FAR* LPFNHASHKEY)(LPVOID, UINT);
+
+class FAR CMapKeyToValue
+{
+public:
+ CMapKeyToValue(DWORD memctx, UINT cbValue, UINT cbKey = 0,
+ int nBlockSize=10, LPFNHASHKEY lpfnHashKey = &MKVDefaultHashKey,
+ UINT nHashSize = 17);
+ ~CMapKeyToValue();
+
+ // number of elements
+ int GetCount() const { return m_nCount; }
+ BOOL IsEmpty() const { return m_nCount == 0; }
+
+ // Lookup; return FALSE if not found
+ BOOL Lookup(LPVOID pKey, UINT cbKey, LPVOID pValue) const;
+ BOOL LookupHKey(HMAPKEY hKey, LPVOID pValue) const;
+ BOOL LookupAdd(LPVOID pKey, UINT cbKey, LPVOID pValue) const;
+
+ // add a new (key, value) pair; return FALSE if out of memory
+ BOOL SetAt(LPVOID pKey, UINT cbKey, LPVOID pValue);
+ BOOL SetAtHKey(HMAPKEY hKey, LPVOID pValue);
+
+ // removing existing (key, ?) pair; return FALSE if no such key
+ BOOL RemoveKey(LPVOID pKey, UINT cbKey);
+ BOOL RemoveHKey(HMAPKEY hKey);
+ void RemoveAll();
+
+ // iterating all (key, value) pairs
+ POSITION GetStartPosition() const
+ { return (m_nCount == 0) ? (POSITION)NULL : BEFORE_START_POSITION; }
+ void GetNextAssoc(POSITION FAR* pNextPosition, LPVOID pKey,
+ UINT FAR* pcbKey, LPVOID pValue) const;
+
+ // return HMAPKEY for given key; returns NULL if not currently in map
+ HMAPKEY GetHKey(LPVOID pKey, UINT cbKey) const;
+
+ void AssertValid() const;
+
+private:
+ // abstracts, somewhat, variable and fixed sized keys; size is really
+ // m_cbKeyInAssoc.
+ union CKeyWrap
+ {
+ BYTE rgbKey[sizeof(LPVOID) + sizeof(UINT)];
+ struct
+ {
+ LPVOID pKey;
+ UINT cbKey;
+ };
+ };
+
+ // Association of one key and one value; NOTE: even though in general
+ // the size of the key and value varies, for any given map,
+ // the size of an assoc is fixed.
+ struct CAssoc
+ {
+ CAssoc FAR* pNext;
+ UINT nHashValue; // needed for efficient iteration
+ CKeyWrap key; // size is really m_cbKeyInAssoc
+ // BYTE rgbValue[m_cbValue];
+ };
+
+ UINT SizeAssoc() const
+ { return sizeof(CAssoc)-sizeof(CKeyWrap) + m_cbKeyInAssoc + m_cbValue; }
+ CAssoc FAR* NewAssoc(UINT hash, LPVOID pKey, UINT cbKey, LPVOID pValue);
+ void FreeAssoc(CAssoc FAR* pAssoc);
+ BOOL CompareAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const;
+ CAssoc FAR* GetAssocAt(LPVOID pKey, UINT cbKey, UINT FAR& nHash) const;
+
+ BOOL SetAssocKey(CAssoc FAR* pAssoc, LPVOID pKey, UINT cbKey) const;
+ void GetAssocKeyPtr(CAssoc FAR* pAssoc, LPVOID FAR* ppKey,UINT FAR* pcbKey) const;
+ void FreeAssocKey(CAssoc FAR* pAssoc) const;
+ void GetAssocValuePtr(CAssoc FAR* pAssoc, LPVOID FAR* ppValue) const;
+ void GetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const;
+ void SetAssocValue(CAssoc FAR* pAssoc, LPVOID pValue) const;
+
+ BOOL InitHashTable();
+
+ UINT m_cbValue;
+ UINT m_cbKey; // variable length if 0
+ UINT m_cbKeyInAssoc; // always non-zero
+
+ CAssoc FAR* FAR* m_pHashTable;
+ UINT m_nHashTableSize;
+ LPFNHASHKEY m_lpfnHashKey;
+
+ int m_nCount;
+ CAssoc FAR* m_pFreeList;
+ struct CPlex FAR* m_pBlocks;
+ int m_nBlockSize;
+ DWORD m_memctx;
+};
+
+
+#endif // !__MAP_KV_H__
diff --git a/private/ole32/olethunk/olethk32/mmodel.cxx b/private/ole32/olethunk/olethk32/mmodel.cxx
new file mode 100644
index 000000000..e097b16cb
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/mmodel.cxx
@@ -0,0 +1,232 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: mmodel.cxx
+//
+// Contents: CMemoryModel
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+CMemoryModel16 mmodel16Public(TRUE);
+CMemoryModel16 mmodel16Owned(FALSE);
+CMemoryModel32 mmodel32;
+
+//+---------------------------------------------------------------------------
+//
+// Method: CMemoryModel16::AllocMemory
+//
+// Synopsis: Allocates memory
+//
+// Arguments: [cb] - Size of block to allocate
+//
+// Returns: New address of block or NULL
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+//----------------------------------------------------------------------------
+
+DWORD CMemoryModel16::AllocMemory(DWORD cb)
+{
+ VPVOID vpv;
+ HMEM16 hmem16;
+
+ thkAssert(cb > 0);
+
+ vpv = WgtAllocLock(GMEM_MOVEABLE, cb, &hmem16);
+ if (vpv == 0)
+ {
+ //
+ // Not able to allocate a 16-bit memory block!
+ //
+ thkDebugOut((DEB_ERROR,
+ "CMemoryModel16::AllocMemory, "
+ "Allocation failed, size %08lX\n",
+ cb));
+ return 0;
+ }
+
+ if (_fPublic)
+ {
+ SetOwnerPublicHMEM16(hmem16);
+ }
+
+ return vpv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CMemoryModel16::FreeMemory
+//
+// Synopsis: Deallocates a block of memory previously allocated
+//
+// Arguments: [dwMem] - Address of memory block to free
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+//----------------------------------------------------------------------------
+
+void CMemoryModel16::FreeMemory(DWORD dwMem)
+{
+ thkAssert(dwMem != 0);
+
+ WgtUnlockFree(dwMem);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CMemoryModel16::ResolvePtr
+//
+// Synopsis: Returns a resolved pointer given an abstract pointer
+//
+// Arguments: [dwMem] - Address to get pointer from
+// [cb] - Length, starting at given address, to make valid
+// pointers for.
+//
+// Returns: LPVOID - A real pointer equivalent to the abstract pointer.
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+// Notes: Be careful of alignment issues
+//
+//----------------------------------------------------------------------------
+
+LPVOID CMemoryModel16::ResolvePtr(DWORD dwMem, DWORD cb)
+{
+ LPVOID pv;
+
+ thkAssert(dwMem != 0 && cb > 0);
+
+ pv = (LPVOID)WOWFIXVDMPTR(dwMem, cb);
+ if (pv == NULL)
+ {
+ thkDebugOut((DEB_ERROR,
+ "CMemoryModel16::ResolvePtr, "
+ "WOWGetVDMPointer failed on %08lX, size %08lX\n",
+ dwMem, cb));
+ }
+
+ return pv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMemoryModel16::ReleasePtr, public
+//
+// Synopsis: Releases a resolved pointer
+//
+// Arguments: [dwMem] - Abstract pointer to release
+//
+// History: 10-Oct-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CMemoryModel16::ReleasePtr(DWORD dwMem)
+{
+ thkAssert(dwMem != 0);
+
+ WOWRELVDMPTR(dwMem);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CMemoryModel32::AllocMemory
+//
+// Synopsis: Allocates memory
+//
+// Arguments: [cb] - Size of block to allocate
+//
+// Returns: New address of block or NULL
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+//----------------------------------------------------------------------------
+
+DWORD CMemoryModel32::AllocMemory(DWORD cb)
+{
+ DWORD dwMem;
+
+ thkAssert(cb > 0);
+
+ dwMem = (DWORD)CoTaskMemAlloc(cb);
+ if (dwMem == 0)
+ {
+ //
+ // Not able to allocate a 32-bit memory block!
+ //
+ thkDebugOut((DEB_ERROR,
+ "CMemoryModel32::AllocBlock, "
+ "CoTaskMemAlloc failed size %08lX\n",
+ cb));
+ return 0;
+ }
+
+ return dwMem;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CMemoryModel32::FreeMemory
+//
+// Synopsis: Deallocates a block of memory previously allocated
+//
+// Arguments: [dwMem] - Address of memory block to free
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+//----------------------------------------------------------------------------
+
+void CMemoryModel32::FreeMemory(DWORD dwMem)
+{
+ thkAssert(dwMem != 0);
+
+ CoTaskMemFree((LPVOID)dwMem);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Method: CMemoryModel32::ResolvePtr
+//
+// Synopsis: Returns a resolved pointer given an abstract pointer
+//
+// Arguments: [dwMem] - Address to get pointer from
+// [cb] - Length, starting at given address, to make valid
+// pointers for.
+//
+// Returns: LPVOID - A real pointer equivalent to the abstract pointer.
+//
+// History: 7-05-94 BobDay (Bob Day) Created
+//
+// Notes: Be careful of alignment issues
+//
+//----------------------------------------------------------------------------
+
+LPVOID CMemoryModel32::ResolvePtr(DWORD dwMem, DWORD cb)
+{
+ thkAssert(dwMem != 0 && cb > 0);
+
+ return (LPVOID)dwMem;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMemoryModel32::ReleasePtr, public
+//
+// Synopsis: Releases a resolved pointer
+//
+// Arguments: [dwMem] - Abstract pointer to release
+//
+// History: 10-Oct-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CMemoryModel32::ReleasePtr(DWORD dwMem)
+{
+ thkAssert(dwMem != 0);
+}
diff --git a/private/ole32/olethunk/olethk32/mmodel.hxx b/private/ole32/olethunk/olethk32/mmodel.hxx
new file mode 100644
index 000000000..be7da2be2
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/mmodel.hxx
@@ -0,0 +1,88 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: mmodel.hxx
+//
+// Contents: CMemoryModel
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __MMODEL_HXX__
+#define __MMODEL_HXX__
+
+//+---------------------------------------------------------------------------
+//
+// Class: CMemoryModel (mm)
+//
+// Purpose: Defines an abstract interface to memory allocation
+// so that code can be written which uses both 16 and
+// 32-bit memory
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CMemoryModel
+{
+public:
+ virtual DWORD AllocMemory(DWORD cb) = 0;
+ virtual void FreeMemory(DWORD dwMem) = 0;
+ virtual LPVOID ResolvePtr(DWORD dwMem, DWORD cb) = 0;
+ virtual void ReleasePtr(DWORD dwMem) = 0;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Class: CMemoryModel16 (mm16)
+//
+// Purpose: 16-bit memory model
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CMemoryModel16 : public CMemoryModel
+{
+public:
+ CMemoryModel16(BOOL fPublic)
+ {
+ _fPublic = fPublic;
+ }
+
+ virtual DWORD AllocMemory(DWORD cb);
+ virtual void FreeMemory(DWORD dwMem);
+ virtual LPVOID ResolvePtr(DWORD dwMem, DWORD cb);
+ virtual void ReleasePtr(DWORD dwMem);
+
+private:
+ BOOL _fPublic;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Class: CMemoryModel32 (mm32)
+//
+// Purpose: 16-bit memory model
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CMemoryModel32 : public CMemoryModel
+{
+public:
+ virtual DWORD AllocMemory(DWORD cb);
+ virtual void FreeMemory(DWORD dwMem);
+ virtual LPVOID ResolvePtr(DWORD dwMem, DWORD cb);
+ virtual void ReleasePtr(DWORD dwMem);
+};
+
+extern CMemoryModel16 mmodel16Public;
+extern CMemoryModel16 mmodel16Owned;
+extern CMemoryModel32 mmodel32;
+
+#endif // #ifndef __MMODEL_HXX__
diff --git a/private/ole32/olethunk/olethk32/nest.hxx b/private/ole32/olethunk/olethk32/nest.hxx
new file mode 100644
index 000000000..42b3f6aba
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/nest.hxx
@@ -0,0 +1,32 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: nest.hxx
+//
+// Contents: Nested Log Helping macros & function
+//
+// History: 17-Jul-94 BobDay Split off from THOPUTIL.HXX due
+// to header ordering problems.
+//
+//----------------------------------------------------------------------------
+#ifndef __NEST_HXX__
+#define __NEST_HXX__
+
+#if DBG == 1
+
+extern int _iThunkNestingLevel;
+
+char *NestingLevelString(void);
+#define DebugIncrementNestingLevel() (_iThunkNestingLevel++)
+#define DebugDecrementNestingLevel() (_iThunkNestingLevel--)
+
+#else
+
+#define DebugIncrementNestingLevel()
+#define DebugDecrementNestingLevel()
+
+#endif
+
+#endif // #ifndef __NEST_HXX__
diff --git a/private/ole32/olethunk/olethk32/olethk32.cxx b/private/ole32/olethunk/olethk32/olethk32.cxx
new file mode 100644
index 000000000..520a04b9f
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/olethk32.cxx
@@ -0,0 +1,616 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: olethk32.cxx
+//
+// Contents: Main routines for olethk32.dll
+//
+// History: 22-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#include <userapis.h>
+#pragma hdrstop
+
+#include <thkmgr.hxx>
+#include <stdio.h>
+
+
+DECLARE_INFOLEVEL(thk);
+DECLARE_INFOLEVEL(Stack);
+
+DATA16 gdata16Data;
+
+#if DBG == 1
+BOOL fSaveProxy = FALSE; // Used to find apps who call dead proxies
+BOOL fStabilizeProxies = TRUE; // Used to easily disable stabilization
+BOOL fZapProxy = FALSE; // Used to zap entries in freelist
+
+#ifdef _CHICAGO_
+BOOL fSSOn = TRUE;
+#endif // _CHICAGO_
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+void CallOutputFunctions(const char *buffer);
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
+CLIPFORMAT g_cfLinkSourceDescriptor, g_cfObjectDescriptor;
+
+BYTE g_abLeadTable[256];
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoThreadDetach
+//
+// Synopsis: When a thread is detaching, cleanup for it.
+//
+// Effects: This is called during both DLL_THREAD_DETACH, and
+// DLL_PROCESS_DETACH.
+//
+// Arguments: (none)
+//
+// History: 3-18-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void
+DoThreadDetach()
+{
+ thkDebugOut((DEB_DLL,"_IN DoThreadDetach\n"));
+ //
+ // If there is thunk data, clean it up now.
+ //
+ if (TlsGetValue(dwTlsThkIndex) != NULL)
+ {
+ thkDebugOut((DEB_DLL,"DoThreadDetach calling ThkMgrUninitialize\n"));
+ ThkMgrUninitialize(0, 0, 0);
+ }
+ thkDebugOut((DEB_DLL,"OUT DoThreadDetach\n"));
+}
+//+---------------------------------------------------------------------------
+//
+// Function: LibMain, public
+//
+// Synopsis: DLL initialization entry point
+//
+// History: 23-Feb-94 DrewB Created
+//
+// Notes:
+//
+// (KevinRo 19-Mar-95)
+//
+// Caution needs to be exercised during cleanup. OLE32.DLL has
+// a pointer that we pass in during CoInitializeWOW. This pointer
+// is used to call back into OLETHK32 for cleanup purposes, as well as
+// accessing functions exposed by the 16-bit side. It is important that
+// when OLETHK32 unloads, the pointer in OLE32 is marked as invalid.
+// There is a call during the DLL_PROCESS_DETACH below that causes
+// OLE32 to invalidate its pointer.
+//
+// In addition, the last thread attached to a DLL will not generate
+// a DLL_THREAD_DETACH. Instead, it generates a DLL_PROCESS_DETACH. This
+// means that DLL_PROCESS_DETACH should perform all the steps that
+// DLL_THREAD_DETACH does in addition to whatever DLL_PROCESS_DETACH work
+// that needs to be done.
+//
+// Lastly, OLETHK32.DLL is statically linked to OLE32.DLL. This means
+// that OLETHK32.DLL's DLL_PROCESS_DETACH will be called before OLE32's.
+// That is why it is safe for us to call the OLE32 entry point during
+// DLL_PROCESS_DETACH
+//----------------------------------------------------------------------------
+
+extern "C" BOOL _CRTAPI1 LibMain(HANDLE hDll,
+ DWORD dwReason,
+ LPVOID lpReserved)
+{
+ switch( dwReason )
+ {
+ case DLL_PROCESS_ATTACH:
+#if DBG == 1
+ char achInfoLevel[80];
+
+ if (GetProfileStringA("olethk32", "InfoLevel", "3", achInfoLevel,
+ sizeof(achInfoLevel)) > 0)
+ {
+ thkInfoLevel = strtol (achInfoLevel, NULL, 0);
+ }
+#endif
+ thkDebugOut((DEB_DLL,"_IN DLL_PROCESS_ATTACH\n"));
+
+ //
+ // Save a slot in the thread local storage for our PSTACK (pseudo-
+ // stack) pointer.
+ //
+
+ if (!TlsThkAlloc())
+ {
+ thkDebugOut((DEB_WARN, "TlsThkAlloc failed\n"));
+ return FALSE;
+ }
+ thkDebugOut((DEB_DLL,"OUT DLL_PROCESS_ATTACH\n"));
+ break;
+
+ case DLL_THREAD_ATTACH:
+ thkDebugOut((DEB_DLL,"_IN DLL_THREAD_ATTACH\n"));
+ TlsSetValue(dwTlsThkIndex, NULL);
+ thkDebugOut((DEB_DLL,"OUT DLL_THREAD_ATTACH\n"));
+ break;
+
+ case DLL_THREAD_DETACH:
+ thkDebugOut((DEB_DLL,"_IN DLL_THREAD_DETACH\n"));
+
+ //
+ // Call OLE32.DLL and tell it to cleanup for this thread. This will
+ // not mark OLE32's ptr invalid since this is only a thread detach
+ // and not a process detach. This is a private API between OLE32 and
+ // OLETHK32.
+ //
+ thkDebugOut((DEB_DLL,"Calling Unload WOW for Thread Detach\n"));
+
+ CoUnloadingWOW(FALSE);
+
+ //
+ // When the thread for this task goes away, we need to clean out
+ // the thunk manager.
+ //
+
+ DoThreadDetach();
+
+ thkDebugOut((DEB_DLL,"OUT DLL_THREAD_DETACH\n"));
+ break;
+
+ case DLL_PROCESS_DETACH:
+ thkDebugOut((DEB_DLL,
+ "IN DLL_PROCESS_DETACH: %s\n",
+ lpReserved?"Process Exit":"Dll Unload"));
+
+ //
+ // The last threads cleanup needs to be done here.
+ //
+ if (lpReserved == NULL)
+ {
+ //
+ // Call OLE32.DLL and tell it to cleanup for this thread, and to
+ // never call us again, since we are going away. This is a private
+ // API between OLE32 and OLETHK32. This call will mark OLE32's
+ // private pointer to us as invalid.
+ //
+ thkDebugOut((DEB_DLL,"Calling Unload WOW\n"));
+
+ CoUnloadingWOW(TRUE);
+
+ //
+ // lpReserved being NULL means this cleanup is due to
+ // a FreeLibrary. If it was due to process exit, there
+ // is no way for us to determine the state of the data
+ // structures in the system. Other threads may have been
+ // right smack in the middle of taking apart data structures.
+ //
+ //
+ // Chicago unloads DLL's differently than NT. On Chicago, the
+ // 32-bit side cleans up first, plus resources allocated on
+ // the 32-bit side are released when the 16-bit process goes
+ // away. On NT, the 16-bit process is treated like a thread,
+ // so we have to cleanup.
+ //
+
+#ifndef _CHICAGO_
+ DoThreadDetach();
+#endif
+ //
+ // Only cleanup the memory if the process is not going away.
+ // On Windows NT, there are cases when the NTVDM needs to be
+ // blown away. We shouldn't be calling back to the 16-bit
+ // side in this case. Therefore, we explicitly call free here
+ // instead of putting it in the destructor.
+ //
+ flFreeList32.FreeMemoryBlocks();
+ flHolderFreeList.FreeMemoryBlocks();
+ flRequestFreeList.FreeMemoryBlocks();
+ }
+
+ TlsThkFree();
+
+ //
+ // Call to cleanup 16-bit memory if we are running on Win95.
+ // This should free up the 16-bit memory associated with this
+ // process. This is called in IntOpUninitialize on NT, since it
+ // needs to be called before the 16-bit side goes away.
+ //
+
+#ifdef _CHICAGO_
+ flFreeList16.FreeMemoryBlocks();
+#endif
+
+
+ thkDebugOut((DEB_DLL,"OUT DLL_PROCESS_DETACH\n"));
+ break;
+ }
+
+ return TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IntOpInitialize, public
+//
+// Synopsis: Initializes the 32-bit interoperability code
+//
+// Arguments: [lpdata16] - 16-bit call data
+// [dw1] - Ignored
+// [dw2] - Ignored
+//
+// Returns: Appropriate status code
+//
+// History: 22-Feb-94 JohannP Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI IntOpInitialize(LPDATA16 lpdata16, DWORD dw1, DWORD dw2)
+{
+ int i;
+
+ thkDebugOut((DEB_ITRACE | DEB_THUNKMGR, "_IN IntOpInitialize (%08lX)\n",
+ lpdata16));
+
+ thkAssert((THOP_LASTOP & ~THOP_OPMASK) == 0);
+
+#if DBG == 1
+ char achInfoLevel[80];
+#ifdef _CHICAGO_
+ if (GetProfileStringA("CairOLE InfoLevels",
+ "Stack", "3", achInfoLevel,
+ sizeof(achInfoLevel)) > 0)
+ {
+ StackInfoLevel = strtol (achInfoLevel, NULL, 0);
+ }
+
+ if (GetProfileStringA("CairOLE InfoLevels",
+ "StackOn", "3", achInfoLevel,
+ sizeof(achInfoLevel)) > 0)
+ {
+ fSSOn = strtol (achInfoLevel, NULL, 0);
+ }
+#endif // _CHICAGO_
+
+ if (GetProfileIntA("olethk32", "BreakOnInit", FALSE))
+ {
+ // DebugBreak's in WOW are fatal unless the exception
+ // is handled somehow. If a debugger is hooked up,
+ // it'll get first crack at the break exception
+ // If not, our handler will ignore the exception so
+ // execution can continue
+
+ __try
+ {
+ DebugBreak();
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ }
+ }
+
+ fSaveProxy = GetProfileIntA("olethk32", "SaveProxy", FALSE);
+ fZapProxy = GetProfileIntA("olethk32", "ZapProxy", FALSE);
+ fStabilizeProxies = GetProfileIntA("olethk32", "Stabilize", TRUE);
+#endif
+
+ // Copy passed parameter from 16-bit world...
+ memcpy( (LPVOID)&gdata16Data, (LPVOID)lpdata16, sizeof( DATA16 ) );
+
+#if defined(_CHICAGO_)
+ g_cfObjectDescriptor =
+ RegisterClipboardFormatA("Object Descriptor");
+ g_cfLinkSourceDescriptor =
+ RegisterClipboardFormatA("Link Source Descriptor");
+#else
+ g_cfObjectDescriptor =
+ RegisterClipboardFormat(__TEXT("Object Descriptor"));
+ g_cfLinkSourceDescriptor =
+ RegisterClipboardFormat(__TEXT("Link Source Descriptor"));
+#endif
+ if (g_cfObjectDescriptor == 0 || g_cfLinkSourceDescriptor == 0)
+ {
+ thkDebugOut((DEB_WARN, "IntOpInitialize: "
+ "Unable to register clipboard formats\n"));
+ return E_UNEXPECTED;
+ }
+
+ // Create a lookup table for lead-byte-ness
+ // so we can avoid calling IsDBCSLeadByte on every character
+ // during string validation
+ for (i = 0; i < 256; i++)
+ {
+ g_abLeadTable[i] = (BYTE)IsDBCSLeadByte((BYTE)i);
+ }
+
+ thkDebugOut((DEB_THUNKMGR | DEB_ITRACE, "OUT IntOpInitialize (%08lX)\n",
+ lpdata16));
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IntOpUninitialize, public
+//
+// Synopsis: Cleanup initiated by 16-bit DLL unload
+//
+// Arguments: [dw1]
+// [dw2]
+// [dw3]
+//
+// History: 29-Nov-94 DrewB Created
+//
+// Notes: (KevinRo) This routine is only called by compobj.dll. To make
+// things even more interesting, it is only called on Windows/NT. Win95
+// does the flFreeList16.FreeMemoryBlocks during PROCESS_DETACH. Cleanup
+// of the proxies is not neccessary on Win95, since the 16-bit process will
+// clean them up for us.
+//
+//----------------------------------------------------------------------------
+
+STDAPI IntOpUninitialize(DWORD dw1, DWORD dw2, DWORD dw3)
+{
+ thkDebugOut((DEB_THUNKMGR | DEB_ITRACE, "_IN IntOpUninitialize\n"));
+#ifndef _CHICAGO_
+ // Remove all existing proxies since we're going to free the
+ // proxy memory in the next step
+ if (TlsThkGetData() != NULL)
+ {
+ CThkMgr *ptm = TlsThkGetThkMgr();
+
+ if (ptm)
+ {
+ ptm->RemoveAllProxies();
+ }
+ }
+
+ // Clean up the 16-bit freelist at this time because we know
+ // that 16-bit code is still active and available for callback
+ // If we waited for the freelist destructor to be called, 16-bit
+ // code would already be cleaned up and the WOWGlobalFree calls
+ // would fail
+ flFreeList16.FreeMemoryBlocks();
+
+ WgtDump();
+#else
+ thkAssert(!"IntOpUninitialize called on Win95");
+#endif
+ thkDebugOut((DEB_THUNKMGR | DEB_ITRACE, "OUT IntOpUninitialize\n"));
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertHr1632Thunk, public
+//
+// Synopsis: Trivial function to allow calling HRESULT conversion
+// functions from 16-bit
+//
+// Arguments: [hr] - HRESULT to convert
+// [dw1]
+// [dw2]
+//
+// Returns: Appropriate status code
+//
+// History: 26-Sep-94 DrewB Created
+//
+// Notes: Required because 16-bit calls to CallProc32W use three
+// arguments
+//
+//----------------------------------------------------------------------------
+
+STDAPI ConvertHr1632Thunk(HRESULT hr, DWORD dw1, DWORD dw2)
+{
+ return TransformHRESULT_1632(hr);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertHr3216Thunk, public
+//
+// Synopsis: Trivial function to allow calling HRESULT conversion
+// functions from 16-bit
+//
+// Arguments: [hr] - HRESULT to convert
+// [dw1]
+// [dw2]
+//
+// Returns: Appropriate status code
+//
+// History: 26-Sep-94 DrewB Created
+//
+// Notes: Required because 16-bit calls to CallProc32W use three
+// arguments
+//
+//----------------------------------------------------------------------------
+
+STDAPI ConvertHr3216Thunk(HRESULT hr, DWORD dw1, DWORD dw2)
+{
+ return TransformHRESULT_3216(hr);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ThkAddAppCompatFlag
+//
+// Synopsis: Takes the given flag and ORs it into the current app
+// compatibility flag set
+//
+// Effects:
+//
+// Arguments: [dwFlag] -- flag to set
+//
+// Requires:
+//
+// Returns: void
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: dd-mmm-yy Author Comment
+// 15-Mar-95 alexgo author
+//
+// Notes: This function exists so that 16bit thunk dll's may
+// also set app compatibility flags. olethk32 code typically
+// sets the flags directly via TlsThkSetAppCompatFlags
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(void) ThkAddAppCompatFlag( DWORD dwFlag )
+{
+ DWORD dw;
+
+ dw = TlsThkGetAppCompatFlags();
+
+ dw |= dwFlag;
+
+ TlsThkSetAppCompatFlags(dw);
+}
+
+
+#if DBG == 1
+static LONG _wgtAllocated = 0;
+
+//+---------------------------------------------------------------------------
+//
+// Function: WgtAllocLock, public debug
+//
+// Synopsis: Tracking for WOWGlobalAllocLock16
+//
+// History: 29-Nov-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+VPVOID WgtAllocLock(WORD wFlags, DWORD cb, HMEM16 *ph)
+{
+ HMEM16 h;
+ VPVOID vpv;
+
+ vpv = WOWGlobalAllocLock16(wFlags, cb, &h);
+ if (vpv != 0)
+ {
+#ifdef WGT_TRACK
+ if (WOWGlobalLockSize16(h, &cb) != 0)
+ {
+ _wgtAllocated += cb;
+ WOWGlobalUnlock16(h);
+ }
+ else
+ {
+ thkDebugOut((DEB_WARN,
+ "Unable to get size of allocated block 0x%04lX\n",
+ h));
+
+ // This is a guess at how big a block Win16 will allocate
+ _wgtAllocated += (cb+31) & 31;
+ }
+#endif
+
+ if (ph != NULL)
+ {
+ *ph = h;
+ }
+ }
+ else
+ {
+ thkDebugOut((DEB_WARN,
+ "Unable to allocate %d bytes of 16-bit memory\n",
+ cb));
+ }
+
+ return vpv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WgtUnlockFree, public
+//
+// Synopsis: Tracking for WOWGlobalUnlockFree16
+//
+// History: 29-Nov-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void WgtUnlockFree(VPVOID vpv)
+{
+ HMEM16 h;
+ DWORD cb;
+
+ if (vpv == 0)
+ {
+ thkDebugOut((DEB_WARN, "Attempt to free NULL\n"));
+ }
+ else
+ {
+#ifdef WGT_TRACK
+ // BUGBUG - Total hack, incorrect
+ h = (HMEM16)(vpv >> 16);
+
+ if (WOWGlobalLockSize16(h, &cb) != 0)
+ {
+ _wgtAllocated -= cb;
+ WOWGlobalUnlock16(h);
+ }
+ else
+ {
+ thkDebugOut((DEB_WARN,
+ "Unable to get size of allocated block 0x%04lX\n",
+ h));
+ }
+#endif
+
+ WOWGlobalUnlockFree16(vpv);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WgtDump, public
+//
+// Synopsis: Dumps global tracking information
+//
+// History: 29-Nov-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void WgtDump(void)
+{
+ if (_wgtAllocated != 0)
+ {
+ thkDebugOut((DEB_WARN,
+ "%d bytes of 16-bit memory currently allocated\n",
+ _wgtAllocated));
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThkCallOutputFunctions, public
+//
+// Synopsis: thunked pass-thru to Ole32 CallOutputFunctions for 16-bit land
+//
+// History: 23-Jan-95 murthys Created
+//
+//----------------------------------------------------------------------------
+
+void ThkCallOutputFunctions(const char * buffer, PVOID dummy1, PVOID dummy2)
+{
+ CallOutputFunctions(buffer);
+}
+
+#endif // DBG == 1
diff --git a/private/ole32/olethunk/olethk32/olethk32.hxx b/private/ole32/olethunk/olethk32/olethk32.hxx
new file mode 100644
index 000000000..f78d48232
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/olethk32.hxx
@@ -0,0 +1,31 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: olethk32.hxx
+//
+// Contents: Global definitions
+//
+// History: 23-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OLETHK32_HXX__
+#define __OLETHK32_HXX__
+
+extern DATA16 gdata16Data;
+
+#if DBG == 1
+extern BOOL fSaveProxy;
+extern BOOL fStabilizeProxies;
+extern BOOL fZapProxy;
+#endif
+
+extern CLIPFORMAT g_cfLinkSourceDescriptor, g_cfObjectDescriptor;
+
+extern BYTE g_abLeadTable[];
+
+extern DWORD dwTlsThkIndex;
+
+#endif // #ifndef __OLETHK32_HXX__
diff --git a/private/ole32/olethunk/olethk32/olethk32.rc b/private/ole32/olethunk/olethk32/olethk32.rc
new file mode 100644
index 000000000..87034fe3b
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/olethk32.rc
@@ -0,0 +1,14 @@
+#include <windows.h>
+
+//
+// Version resources
+//
+#include <ntverp.h>
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Microsoft OLE for Windows and Windows NT"
+#define VER_INTERNALNAME_STR "OLETHK32.DLL"
+#define VER_ORIGINALFILENAME_STR "OLETHK32.DLL"
+#include <common.ver>
+
+
diff --git a/private/ole32/olethunk/olethk32/plex.cxx b/private/ole32/olethunk/olethk32/plex.cxx
new file mode 100644
index 000000000..a00245bf2
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/plex.cxx
@@ -0,0 +1,45 @@
+// This is a part of the Microsoft Foundation Classes C++ library.
+// Copyright (C) 1992 Microsoft Corporation
+// All rights reserved.
+//
+// This source code is only intended as a supplement to the
+// Microsoft Foundation Classes Reference and Microsoft
+// QuickHelp documentation provided with the library.
+// See these sources for detailed information regarding the
+// Microsoft Foundation Classes product.
+
+#include "headers.cxx"
+#pragma hdrstop
+
+//#include <ole2int.h>
+#include "plex.h"
+
+// Collection support
+
+#define CairoleAssert(x) thkAssert(x)
+
+CPlex FAR* CPlex::Create(CPlex FAR* FAR& pHead, UINT nMax, UINT cbElement)
+{
+ CairoleAssert(nMax > 0 && cbElement > 0);
+ CPlex FAR* p = (CPlex FAR*)CoTaskMemAlloc(sizeof(CPlex) + nMax * cbElement);
+ if (p == NULL)
+ return NULL;
+
+ p->nMax = nMax;
+ p->nCur = 0;
+ p->pNext = pHead;
+ pHead = p; // change head (adds in reverse order for simplicity)
+ return p;
+}
+
+void CPlex::FreeDataChain() // free this one and links
+{
+ CPlex FAR* pThis;
+ CPlex FAR* pNext;
+
+ for (pThis = this; pThis != NULL; pThis = pNext) {
+ pNext = pThis->pNext;
+ pThis->pNext = NULL; // So compiler won't do nasty optimizations
+ CoTaskMemFree(pThis);
+ }
+}
diff --git a/private/ole32/olethunk/olethk32/plex.h b/private/ole32/olethunk/olethk32/plex.h
new file mode 100644
index 000000000..7095bb7ae
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/plex.h
@@ -0,0 +1,30 @@
+// This is a part of the Microsoft Foundation Classes C++ library.
+// Copyright (C) 1992 Microsoft Corporation
+// All rights reserved.
+//
+// This source code is only intended as a supplement to the
+// Microsoft Foundation Classes Reference and Microsoft
+// QuickHelp documentation provided with the library.
+// See these sources for detailed information regarding the
+// Microsoft Foundation Classes product.
+
+#ifndef __PLEX_H__
+#define __PLEX_H__
+
+#define INTERNAL_(x) x
+
+struct FAR CPlex // warning variable length structure
+{
+ CPlex FAR* pNext;
+ UINT nMax;
+ UINT nCur;
+ /* BYTE data[maxNum*elementSize]; */
+
+ INTERNAL_(void FAR*) data() { return this+1; }
+
+ static INTERNAL_(CPlex FAR*) Create(CPlex FAR* FAR& head, UINT nMax, UINT cbElement);
+
+ INTERNAL_(void) FreeDataChain(); // free this one and links
+};
+
+#endif //__PLEX_H__
diff --git a/private/ole32/olethunk/olethk32/stalloc.cxx b/private/ole32/olethunk/olethk32/stalloc.cxx
new file mode 100644
index 000000000..363d49d9a
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/stalloc.cxx
@@ -0,0 +1,397 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: stalloc.cxx
+//
+// Contents: CStackAllocator
+//
+// History: 29-Sep-94 DrewB Created
+//
+// Notes: Loosely based on BobDay's original PSTACK implementation
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+// Pad a count to the given alignment
+// Alignment must be 2^n-1
+#define ALIGN_CB(cb, align) \
+ (((cb)+(align)) & ~(align))
+
+//+---------------------------------------------------------------------------
+//
+// Structure: SStackBlock (sb)
+//
+// Purpose: Header information for stack blocks
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+struct SStackBlock
+{
+ DWORD dwNextBlock;
+ DWORD dwStackTop;
+};
+
+#define BLOCK_OVERHEAD (sizeof(SStackBlock))
+#define BLOCK_START(mem) ((mem)+BLOCK_OVERHEAD)
+#define BLOCK_AVAILABLE(cb) ((cb)-BLOCK_OVERHEAD)
+
+//+---------------------------------------------------------------------------
+//
+// Function: CStackAllocator::CStackAllocator, public
+//
+// Arguments: [pmm] - Memory model to use
+// [cbBlock] - Size of chunk to allocate when necessary
+// [cbAlignment] - Alignment size, must be 2^N
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CStackAllocator::CStackAllocator(CMemoryModel *pmm,
+ DWORD cbBlock,
+ DWORD cbAlignment)
+{
+ thkAssert(BLOCK_AVAILABLE(cbBlock) > 0);
+
+ // Ensure that the alignment is a power of two
+ thkAssert((cbAlignment & (cbAlignment-1)) == 0);
+ // Store alignment - 1 since that's the actual value we need for
+ // alignment computations
+ _cbAlignment = cbAlignment-1;
+
+ // Ensure that overhead and tracking will not affect alignment
+ thkAssert(ALIGN_CB(BLOCK_OVERHEAD, _cbAlignment) == BLOCK_OVERHEAD &&
+ ALIGN_CB(sizeof(SStackMemTrace), _cbAlignment) ==
+ sizeof(SStackMemTrace));
+
+ _pmm = pmm;
+ _cbBlock = cbBlock;
+ _dwBlocks = 0;
+ _dwCurrent = 0;
+ _cbAvailable = 0;
+
+ _psaNext = NULL;
+ _fActive = TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStackAllocator::~CStackAllocator, public virtual
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CStackAllocator::~CStackAllocator(void)
+{
+ Reset();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CStackAllocator::Alloc, public
+//
+// Synopsis: Allocates a chunk of memory from the stack
+//
+// Arguments: [cb] - Amount of memory to allocate
+//
+// Returns: Pointer to memory or NULL
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD CStackAllocator::Alloc(DWORD cb)
+{
+ DWORD dwMem;
+
+ thkAssert(cb > 0);
+
+ // Round size up to maintain alignment of stack
+ cb = ALIGN_CB(cb, _cbAlignment);
+
+#if DBG == 1
+ // Reserve space to record caller
+ cb += sizeof(SStackMemTrace);
+#endif
+
+ thkAssert(cb <= BLOCK_AVAILABLE(_cbBlock));
+
+ // Check to see if the current block can hold the new allocation
+ if (cb > _cbAvailable)
+ {
+ DWORD dwBlock;
+ SStackBlock UNALIGNED *psb;
+
+ // It's too big, so allocate a new block
+ dwBlock = _pmm->AllocMemory(_cbBlock);
+ if (dwBlock == 0)
+ {
+ return 0;
+ }
+
+ if (_dwBlocks != 0)
+ {
+ // Update current top block
+ psb = (SStackBlock UNALIGNED *)
+ _pmm->ResolvePtr(_dwBlocks, sizeof(SStackBlock));
+ psb->dwStackTop = _dwCurrent;
+ _pmm->ReleasePtr(_dwBlocks);
+ }
+
+ // Make the new block the top block
+ psb = (SStackBlock UNALIGNED *)
+ _pmm->ResolvePtr(dwBlock, sizeof(SStackBlock));
+ psb->dwNextBlock = _dwBlocks;
+ _dwBlocks = dwBlock;
+ _pmm->ReleasePtr(dwBlock);
+
+ _dwCurrent = BLOCK_START(dwBlock);
+ _cbAvailable = BLOCK_AVAILABLE(_cbBlock);
+ }
+
+ thkAssert(_cbAvailable >= cb);
+
+ dwMem = _dwCurrent;
+ _dwCurrent += cb;
+ _cbAvailable -= cb;
+
+#if DBG == 1
+ void *pvMem;
+
+ // Fill memory to show reuse problems
+ pvMem = _pmm->ResolvePtr(dwMem, cb);
+ memset(pvMem, 0xED, cb);
+ _pmm->ReleasePtr(dwMem);
+#endif
+
+#if DBG == 1
+ SStackMemTrace UNALIGNED *psmt;
+
+ psmt = (SStackMemTrace UNALIGNED *)
+ _pmm->ResolvePtr(_dwCurrent-sizeof(SStackMemTrace),
+ sizeof(SStackMemTrace));
+ psmt->cbSize = cb-sizeof(SStackMemTrace);
+
+#if !defined(_CHICAGO_)
+ //
+ // On RISC platforms, psmt points to an unaligned structure.
+ // Use a temp variable so we don't get an alignment fault
+ // when RtlGetCallersAddress returns the value.
+ //
+ void *pv;
+ void *pvCaller;
+ RtlGetCallersAddress(&pvCaller, &pv);
+ psmt->pvCaller = pvCaller;
+#else
+ // Depends on return address being directly below first argument
+ psmt->pvCaller = *((void **)&cb-1);
+#endif
+
+ thkDebugOut((DEB_MEMORY, "Stack: %p alloc 0x%08lX:%3d, avail %d\n",
+ psmt->pvCaller, dwMem, cb, _cbAvailable));
+
+ _pmm->ReleasePtr(_dwCurrent-sizeof(SStackMemTrace));
+#endif
+
+ return dwMem;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CStackAllocator::Free, public
+//
+// Synopsis: Frees allocated memory
+//
+// Arguments: [dwMem] - Memory
+// [cb] - Amount of memory allocated
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CStackAllocator::Free(DWORD dwMem, DWORD cb)
+{
+ thkAssert(dwMem != 0);
+ thkAssert(cb > 0);
+
+ // Round size up to maintain alignment of stack
+ cb = ALIGN_CB(cb, _cbAlignment);
+
+#if DBG == 1
+ cb += sizeof(SStackMemTrace);
+#endif
+
+ thkAssert(cb <= BLOCK_AVAILABLE(_cbBlock));
+
+#if DBG == 1
+ void *pvCaller;
+
+#if !defined(_CHICAGO_)
+ void *pv;
+ RtlGetCallersAddress(&pvCaller, &pv);
+#else
+ // Depends on return address being directly below first argument
+ pvCaller = *((void **)&dwMem-1);
+#endif
+
+ thkDebugOut((DEB_MEMORY, "Stack: %p frees 0x%08lX:%3d, avail %d\n",
+ pvCaller, dwMem, cb, _cbAvailable));
+#endif
+
+#if DBG == 1
+ if (_dwCurrent-cb != dwMem)
+ {
+ thkDebugOut((DEB_ERROR, "Free of %d:%d is not TOS (0x%08lX)\n",
+ dwMem, cb, _dwCurrent));
+
+ thkAssert(_dwCurrent-cb == dwMem);
+ }
+#endif
+
+ _dwCurrent -= cb;
+ _cbAvailable += cb;
+
+#if DBG == 1
+ void *pvMem;
+
+ // Fill memory to show reuse problems
+ pvMem = _pmm->ResolvePtr(dwMem, cb);
+ memset(pvMem, 0xDD, cb);
+ _pmm->ReleasePtr(dwMem);
+#endif
+
+ if (_dwCurrent == BLOCK_START(_dwBlocks))
+ {
+ SStackBlock UNALIGNED *psb;
+ DWORD dwBlock;
+
+ // If we've just freed up an entire block and it's not the
+ // only block for the stack, free the block itself and
+ // restore stack state from the next block
+ // We keep the first block around forever to avoid memory
+ // thrashing
+
+ psb = (SStackBlock UNALIGNED *)
+ _pmm->ResolvePtr(_dwBlocks, sizeof(SStackBlock));
+ dwBlock = psb->dwNextBlock;
+ _pmm->ReleasePtr(_dwBlocks);
+
+ if (dwBlock != 0)
+ {
+ _pmm->FreeMemory(_dwBlocks);
+
+ _dwBlocks = dwBlock;
+ psb = (SStackBlock UNALIGNED *)
+ _pmm->ResolvePtr(_dwBlocks, sizeof(SStackBlock));
+ _dwCurrent = psb->dwStackTop;
+ _cbAvailable = _cbBlock-(_dwCurrent-_dwBlocks);
+ _pmm->ReleasePtr(_dwBlocks);
+ }
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStackAllocator::Reset, public
+//
+// Synopsis: Releases all memory in the stack
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CStackAllocator::Reset(void)
+{
+ DWORD dwBlock;
+ SStackBlock UNALIGNED *psb;
+
+ while (_dwBlocks != 0)
+ {
+ psb = (SStackBlock UNALIGNED *)
+ _pmm->ResolvePtr(_dwBlocks, sizeof(SStackBlock));
+ dwBlock = psb->dwNextBlock;
+ _pmm->ReleasePtr(_dwBlocks);
+
+ _pmm->FreeMemory(_dwBlocks);
+
+ _dwBlocks = dwBlock;
+ }
+
+ _dwCurrent = 0;
+ _cbAvailable = 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CStackAllocator::RecordState, public debug
+//
+// Synopsis: Records the current state of the stack
+//
+// Arguments: [psr] - Storage space for information
+//
+// Modifies: [psr]
+//
+// History: 28-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+void CStackAllocator::RecordState(SStackRecord *psr)
+{
+ psr->dwStackPointer = _dwCurrent;
+ psr->dwThreadId = GetCurrentThreadId();
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: CStackAllocator::CheckState, public debug
+//
+// Synopsis: Checks recorded information about the stack against its
+// current state
+//
+// Arguments: [psr] - Recorded information
+//
+// History: 28-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+void CStackAllocator::CheckState(SStackRecord *psr)
+{
+ thkAssert(psr->dwThreadId == GetCurrentThreadId());
+
+ if ((psr->dwStackPointer != 0 && psr->dwStackPointer != _dwCurrent) ||
+ (psr->dwStackPointer == 0 &&
+ _dwCurrent != 0 && _dwCurrent != BLOCK_START(_dwBlocks)))
+ {
+ thkDebugOut((DEB_ERROR, "Stack alloc change: 0x%08lX to 0x%08lX\n",
+ psr->dwStackPointer, _dwCurrent));
+
+ if (_dwCurrent > BLOCK_START(_dwBlocks))
+ {
+ SStackMemTrace UNALIGNED *psmt;
+
+ psmt = (SStackMemTrace UNALIGNED *)
+ _pmm->ResolvePtr(_dwCurrent-sizeof(SStackMemTrace),
+ sizeof(SStackMemTrace));
+ thkDebugOut((DEB_ERROR, "Top alloc: %d bytes by %p\n",
+ psmt->cbSize, psmt->pvCaller));
+ _pmm->ReleasePtr(_dwCurrent-sizeof(SStackMemTrace));
+ }
+
+ thkAssert(!((psr->dwStackPointer != 0 &&
+ psr->dwStackPointer != _dwCurrent) ||
+ (psr->dwStackPointer == 0 &&
+ _dwCurrent != 0 ||
+ _dwCurrent != BLOCK_START(_dwBlocks))));
+ }
+}
+#endif
diff --git a/private/ole32/olethunk/olethk32/stalloc.hxx b/private/ole32/olethunk/olethk32/stalloc.hxx
new file mode 100644
index 000000000..7e4a35afc
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/stalloc.hxx
@@ -0,0 +1,113 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: stalloc.hxx
+//
+// Contents: CStackAllocator
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __STALLOC_HXX__
+#define __STALLOC_HXX__
+
+//+---------------------------------------------------------------------------
+//
+// Struct: SStackMemTrace (smt)
+//
+// Purpose: Stack memory size/leak checking information
+//
+// History: 28-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+struct SStackMemTrace
+{
+ void *pvCaller;
+ UINT cbSize;
+};
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Class: SStackRecord (sr)
+//
+// Purpose: Capture stack allocation state
+//
+// History: 28-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+struct SStackRecord
+{
+ DWORD dwStackPointer;
+ DWORD dwThreadId;
+};
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Class: CStackAllocator (sa)
+//
+// Purpose: Abstract definition of a stack allocator with
+// replaceable underlying memory allocator
+//
+// History: 29-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CStackAllocator
+{
+public:
+ CStackAllocator(CMemoryModel *pmm,
+ DWORD cbBlock,
+ DWORD cbAlignment);
+ ~CStackAllocator(void);
+
+ DWORD Alloc(DWORD cb);
+ void Free(DWORD dwMem, DWORD cb);
+
+#if DBG == 1
+ void RecordState(SStackRecord *psr);
+ void CheckState(SStackRecord *psr);
+#endif
+
+ void Reset(void);
+
+ CStackAllocator *GetNextAllocator(void)
+ {
+ return _psaNext;
+ }
+ void SetNextAllocator(CStackAllocator *psa)
+ {
+ _psaNext = psa;
+ }
+
+ BOOL GetActive(void)
+ {
+ return _fActive;
+ }
+ void SetActive(BOOL fActive)
+ {
+ _fActive = fActive;
+ }
+
+private:
+ DWORD _cbBlock;
+ DWORD _cbAlignment;
+ CMemoryModel *_pmm;
+
+ DWORD _dwBlocks;
+ DWORD _dwCurrent;
+ DWORD _cbAvailable;
+
+ CStackAllocator *_psaNext;
+ BOOL _fActive;
+};
+
+#endif // #ifndef __STALLOC_HXX__
diff --git a/private/ole32/olethunk/olethk32/struct16.hxx b/private/ole32/olethunk/olethk32/struct16.hxx
new file mode 100644
index 000000000..5c2674061
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/struct16.hxx
@@ -0,0 +1,91 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: struct16.hxx
+//
+// Contents: 16-bit structures for use in 32-bit code
+//
+// History: 01-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+#ifndef __STRUCT16_HXX__
+#define __STRUCT16_HXX__
+
+#pragma pack(2)
+
+typedef struct tagRECT16
+{
+ SHORT left;
+ SHORT top;
+ SHORT right;
+ SHORT bottom;
+} RECT16;
+typedef RECT16 UNALIGNED FAR *LPRECT16;
+
+typedef struct tagFORMATETC16
+{
+ CLIPFORMAT cfFormat;
+ VPVOID ptd;
+ DWORD dwAspect;
+ LONG lindex;
+ DWORD tymed;
+} FORMATETC16;
+typedef FORMATETC16 UNALIGNED FAR* LPFORMATETC16;
+
+typedef struct tagOIFI16
+{
+ WORD cb;
+ WORD fMDIApp;
+ HAND16 hwndFrame;
+ HAND16 haccel;
+ SHORT cAccelEntries;
+} OIFI16;
+typedef OIFI16 UNALIGNED FAR* LPOIFI16;
+
+typedef struct tagSTATDATA16
+{ // field used by:
+ FORMATETC16 formatetc; // EnumAdvise, EnumData (cache),
+ // EnumFormats
+ DWORD advf; // EnumAdvise, EnumData (cache)
+ VPVOID pAdvSink; // EnumAdvise
+ DWORD dwConnection; // EnumAdvise
+} STATDATA16;
+typedef STATDATA16 UNALIGNED FAR * LPSTATDATA16;
+
+typedef struct tagMSG16
+{
+ HWND16 hwnd;
+ WORD message;
+ WORD wParam;
+ LONG lParam;
+ DWORD time;
+ ULONG pt;
+} MSG16;
+typedef MSG16 UNALIGNED FAR *LPMSG16;
+
+typedef struct tagSIZE16
+{
+ SHORT cx;
+ SHORT cy;
+} SIZE16;
+
+typedef struct tagMETAFILEPICT16
+{
+ SHORT mm;
+ SHORT xExt;
+ SHORT yExt;
+ HMETAFILE16 hMF;
+} METAFILEPICT16;
+
+typedef struct tagINTERFACEINFO16
+{
+ VPVOID pUnk;
+ IID iid;
+ WORD wMethod;
+} INTERFACEINFO16;
+
+#pragma pack()
+
+#endif // #ifndef __STRUCT16_HXX__
diff --git a/private/ole32/olethunk/olethk32/tc1632.cxx b/private/ole32/olethunk/olethk32/tc1632.cxx
new file mode 100644
index 000000000..a7a66b70b
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/tc1632.cxx
@@ -0,0 +1,323 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: tc1632.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+DWORD ThunkCall1632(THUNKINFO *pti)
+{
+ DWORD dwReturn;
+ thkAssert(pti->pvfn != NULL);
+ thkAssert(*pti->pThop == THOP_END);
+ pti->pThop++;
+ thkAssert(*pti->pThop == THOP_ROUTINEINDEX);
+ pti->pThop++;
+ if (FAILED(pti->scResult))
+ {
+ return (DWORD)pti->scResult;
+ }
+ pti->pThkMgr->SetThkState(THKSTATE_NOCALL);
+ switch(*pti->pThop)
+ {
+ case 0:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8)
+ );
+ break;
+ case 1:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0)
+ );
+ break;
+ case 2:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+12)
+ );
+ break;
+ case 3:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4)
+ );
+ break;
+ case 4:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16),
+ *(DWORD *)(pti->s32.pbStart+20),
+ *(DWORD *)(pti->s32.pbStart+24)
+ );
+ break;
+ case 5:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16)
+ );
+ break;
+ case 6:
+ dwReturn = (*(DWORD (__stdcall *)())pti->pvfn)(
+ );
+ break;
+ case 7:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16),
+ *(DWORD *)(pti->s32.pbStart+20)
+ );
+ break;
+ case 8:
+ dwReturn = (*(DWORD (__stdcall *)(
+ WORD,
+ WORD,
+ DWORD))pti->pvfn)(
+ *(WORD *)(pti->s32.pbStart+0),
+ *(WORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8)
+ );
+ break;
+ case 9:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ ULARGE_INTEGER,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(ULARGE_INTEGER UNALIGNED *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16),
+ *(DWORD *)(pti->s32.pbStart+20)
+ );
+ break;
+ case 10:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ ULARGE_INTEGER))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(ULARGE_INTEGER UNALIGNED *)(pti->s32.pbStart+4)
+ );
+ break;
+ case 11:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ ULARGE_INTEGER,
+ ULARGE_INTEGER,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(ULARGE_INTEGER UNALIGNED *)(pti->s32.pbStart+4),
+ *(ULARGE_INTEGER UNALIGNED *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+20)
+ );
+ break;
+ case 12:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ ULARGE_INTEGER,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(ULARGE_INTEGER UNALIGNED *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16)
+ );
+ break;
+ case 13:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ ULARGE_INTEGER,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(ULARGE_INTEGER UNALIGNED *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+16),
+ *(DWORD *)(pti->s32.pbStart+20)
+ );
+ break;
+ case 14:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16),
+ *(DWORD *)(pti->s32.pbStart+20),
+ *(DWORD *)(pti->s32.pbStart+24),
+ *(DWORD *)(pti->s32.pbStart+28),
+ *(DWORD *)(pti->s32.pbStart+32),
+ *(DWORD *)(pti->s32.pbStart+36),
+ *(DWORD *)(pti->s32.pbStart+40)
+ );
+ break;
+ case 15:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD,
+ SIZEL,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(SIZEL *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+20)
+ );
+ break;
+ case 16:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ SIZEL,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(SIZEL *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+16)
+ );
+ break;
+ case 17:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ WORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(WORD *)(pti->s32.pbStart+8)
+ );
+ break;
+ case 18:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ SIZEL))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(SIZEL *)(pti->s32.pbStart+4)
+ );
+ break;
+ case 19:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ WORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(WORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8)
+ );
+ break;
+ case 20:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(DWORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16),
+ *(DWORD *)(pti->s32.pbStart+20),
+ *(DWORD *)(pti->s32.pbStart+24),
+ *(DWORD *)(pti->s32.pbStart+28)
+ );
+ break;
+ case 21:
+ dwReturn = (*(DWORD (__stdcall *)(
+ DWORD,
+ WORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD,
+ DWORD))pti->pvfn)(
+ *(DWORD *)(pti->s32.pbStart+0),
+ *(WORD *)(pti->s32.pbStart+4),
+ *(DWORD *)(pti->s32.pbStart+8),
+ *(DWORD *)(pti->s32.pbStart+12),
+ *(DWORD *)(pti->s32.pbStart+16),
+ *(DWORD *)(pti->s32.pbStart+20),
+ *(DWORD *)(pti->s32.pbStart+24)
+ );
+ break;
+ }
+
+#if DBG == 1
+ if ( !pti->fResultThunked && FAILED(dwReturn) )
+ {
+ thkDebugOut((DEB_FAILURES,
+ "ThunkCall1632 pvfn = %08lX Probably failed hr = %08lX\n",
+ pti->pvfn, dwReturn));
+ }
+
+#endif
+
+ pti->pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT32);
+ return dwReturn;
+}
diff --git a/private/ole32/olethunk/olethk32/the.hxx b/private/ole32/olethunk/olethk32/the.hxx
new file mode 100644
index 000000000..69d320238
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/the.hxx
@@ -0,0 +1,21 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: the.hxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#define THE_IEnumString 0
+#define THE_IEnumUnknown 1
+#define THE_IEnumSTATSTG 2
+#define THE_IEnumFORMATETC 3
+#define THE_IEnumSTATDATA 4
+#define THE_IEnumMoniker 5
+#define THE_IEnumOLEVERB 6
diff --git a/private/ole32/olethunk/olethk32/thi.hxx b/private/ole32/olethunk/olethk32/thi.hxx
new file mode 100644
index 000000000..5f754af85
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thi.hxx
@@ -0,0 +1,73 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thi.hxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#define THI_IUnknown 0
+#define THI_IClassFactory 1
+#define THI_IMalloc THI_COUNT
+#define THI_IMarshal 2
+#define THI_IStdMarshalInfo 3
+#define THI_IMessageFilter 4
+#define THI_IExternalConnection 5
+#define THI_IEnumString 6
+#define THI_IEnumUnknown 7
+#define THI_IEnumSTATSTG 8
+#define THI_ILockBytes 9
+#define THI_IStream 10
+#define THI_IStorage 11
+#define THI_IRootStorage 12
+#define THI_IEnumFORMATETC 13
+#define THI_IEnumSTATDATA 14
+#define THI_IDataObject 15
+#define THI_IViewObject 16
+#define THI_IViewObject2 17
+#define THI_IAdviseSink 18
+#define THI_IAdviseSink2 19
+#define THI_IDataAdviseHolder 20
+#define THI_IOleCache 21
+#define THI_IOleCache2 22
+#define THI_IOleCacheControl 23
+#define THI_IDropTarget 24
+#define THI_IDropSource 25
+#define THI_IPersist 26
+#define THI_IPersistStorage 27
+#define THI_IPersistStream 28
+#define THI_IPersistFile 29
+#define THI_IBindCtx 30
+#define THI_IMoniker 31
+#define THI_IRunningObjectTable 32
+#define THI_IEnumMoniker 33
+#define THI_IEnumOLEVERB 34
+#define THI_IOleObject 35
+#define THI_IOleClientSite 36
+#define THI_IRunnableObject 37
+#define THI_IParseDisplayName 38
+#define THI_IOleContainer 39
+#define THI_IOleItemContainer 40
+#define THI_IOleAdviseHolder 41
+#define THI_IOleLink 42
+#define THI_IOleWindow 43
+#define THI_IOleInPlaceObject 44
+#define THI_IOleInPlaceActiveObject 45
+#define THI_IOleInPlaceUIWindow 46
+#define THI_IOleInPlaceFrame 47
+#define THI_IOleInPlaceSite 48
+#define THI_IRpcChannelBuffer 49
+#define THI_IRpcProxyBuffer 50
+#define THI_IRpcStubBuffer 51
+#define THI_IPSFactoryBuffer 52
+#define THI_IRpcChannel 53
+#define THI_IRpcProxy 54
+#define THI_IRpcStub 55
+#define THI_IPSFactory 56
+#define THI_COUNT 57
diff --git a/private/ole32/olethunk/olethk32/thkmgr.cxx b/private/ole32/olethunk/olethk32/thkmgr.cxx
new file mode 100644
index 000000000..983bdbecb
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thkmgr.cxx
@@ -0,0 +1,536 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thkmgr.cxx
+//
+// Contents: Thunk manager initialization
+// IUnknown transition functions
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThkMgrInitialize
+//
+// Synopsis: Creates a new thunkmanager and set it for given thread
+//
+// Arguments: [dw1]
+// [dw2]
+// [dw3]
+//
+// Returns: HRESULT
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+// Notes: Called from CoInitialize
+//
+//----------------------------------------------------------------------------
+STDAPI ThkMgrInitialize(DWORD dw1, DWORD dw2, DWORD dw3)
+{
+ CThkMgr *pcthkmgr = NULL;
+
+ thkDebugOut((DEB_THUNKMGR, "In ThkMgrInitialize()\n"));
+
+ //
+ // If we are already initialized, do nothing.
+ //
+ if (TlsGetValue(dwTlsThkIndex) != NULL)
+ {
+ thkDebugOut((DEB_THUNKMGR, "OUT ThkMgrInitialize() Already Init\n"));
+ return(NOERROR);
+ }
+
+ //
+ // initialize the Tls storage
+ //
+ if ( NOERROR != TlsThkInitialize())
+ {
+ thkDebugOut((DEB_ERROR, "TlsThkInitialize failed"));
+
+ return E_OUTOFMEMORY;
+ }
+
+ thkAssert(TlsThkGetThkMgr() == NULL);
+
+ pcthkmgr = CThkMgr::Create();
+ TlsThkSetThkMgr(pcthkmgr);
+
+ thkDebugOut((DEB_THUNKMGR, "Out ThkMgrInitialize() => %p\n",
+ pcthkmgr));
+
+ return (pcthkmgr == NULL) ? E_OUTOFMEMORY : NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThkMgrUninitialize
+//
+// Synopsis: deletes the thunkmanager and removes it from thread data
+// tls data are removed as well
+//
+// Arguments: [dw1]
+// [dw2]
+// [dw3]
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+// Notes: Called during CoUninitialize
+//
+//----------------------------------------------------------------------------
+STDAPI_(void) ThkMgrUninitialize(DWORD dw1, DWORD dw2, DWORD dw3)
+{
+ thkDebugOut((DEB_THUNKMGR, "In ThkMgrUninitialize()\n"));
+
+ thkAssert(TlsGetValue(dwTlsThkIndex) != NULL);
+
+ CThkMgr *pcthkmgr = (CThkMgr*)TlsThkGetThkMgr();
+ if (pcthkmgr != NULL)
+ {
+ // Note: the thunkmanger gets removed from tlsthk
+ delete pcthkmgr;
+ }
+
+ // If we weren't called from 16-bit code then it's not safe to reset
+ // the 16-bit stack allocator here because we may be doing this
+ // in thread cleanup and it may not be safe to call back into
+ // 16-bit code
+
+ TlsThkGetStack32()->Reset();
+
+ // uninitialize the tls data for this apartment
+ TlsThkUninitialize();
+
+ thkDebugOut((DEB_THUNKMGR, "Out ThkMgrUninitialize()\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IUnknownObj32
+//
+// Synopsis: Entry point from 16bit for IUnknown methods
+//
+// Arguments: [vpvThis16] -- Proxy object
+// [wMethod] -- IUnknown method
+// [vpvData] -- Call data
+//
+// Returns: Call result, pdata contains out data for particular call
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+STDAPI_(DWORD) IUnknownObj32(VPVOID vpvThis16, DWORD wMethod, VPVOID vpvData)
+{
+ DWORD dwRet;
+ LONG vpvInterface;
+ IID iid;
+
+ if (TlsThkGetData() == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: IUnknownObj32 call refused\n"));
+
+ if (wMethod == SMI_QUERYINTERFACE)
+ {
+ return (DWORD)E_FAIL;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ // Note: at this point we should always get a thunkmanager
+ CThkMgr *pcthkmgr = (CThkMgr*)TlsThkGetThkMgr();
+ thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
+
+ thkAssert(vpvThis16 != 0 && "IUnknownObj32: invalid pointer." );
+ thkAssert(wMethod >= 0 && wMethod < SMI_COUNT);
+
+ switch (wMethod)
+ {
+ case SMI_QUERYINTERFACE:
+ thkAssert(vpvData != NULL &&
+ "IUnknownObj32.QueryInterface without IID");
+
+ // Copy the 16-bit IID into 32-bit memory for the real call
+ iid = *FIXVDMPTR(vpvData, IID);
+ RELVDMPTR(vpvData);
+
+ thkDebugOut((DEB_UNKNOWN,
+ "%sIn QueryInterface1632(%p, %s)\n",
+ NestingLevelString(), vpvThis16,
+ IidOrInterfaceString(&iid)));
+
+ dwRet = pcthkmgr->QueryInterfaceProxy1632(vpvThis16, iid,
+ (void **)&vpvInterface);
+
+ // Translate the 32-bit HRESULT to a 16-bit HRESULT
+ dwRet = (DWORD)TransformHRESULT_3216((HRESULT)dwRet);
+
+ // Pass the return interface pointer back through the IID
+ // memory. We re-resolve the data pointer since nested
+ // calls may have occurred
+ (FIXVDMPTR(vpvData, IID))->Data1 = vpvInterface;
+ RELVDMPTR(vpvData);
+
+ thkDebugOut((DEB_UNKNOWN,
+ "%sOut QueryInterface1632(%p) => %p, 0x%08lX\n",
+ NestingLevelString(), vpvThis16, vpvInterface, dwRet));
+ break;
+
+ case SMI_ADDREF:
+ thkDebugOut((DEB_UNKNOWN, "%sIn AddRef1632(%p)\n",
+ NestingLevelString(), vpvThis16));
+
+ dwRet = pcthkmgr->AddRefProxy1632(vpvThis16);
+
+ thkDebugOut((DEB_UNKNOWN, "%sOut AddRef1632(%p) => %d\n",
+ NestingLevelString(), vpvThis16, dwRet));
+ break;
+
+ case SMI_RELEASE:
+ thkDebugOut((DEB_UNKNOWN, "%sIn Release1632(%p)\n",
+ NestingLevelString(), vpvThis16));
+
+ dwRet = pcthkmgr->ReleaseProxy1632(vpvThis16);
+
+ thkDebugOut((DEB_UNKNOWN, "%sOut Release1632(%p) => %d\n",
+ NestingLevelString(), vpvThis16, dwRet));
+ break;
+ }
+
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: QueryInterfaceProxy3216
+//
+// Synopsis: call QueryInterface on a 32 bit proxy
+//
+// Arguments: [pto] -- This pointer (a 32->16 proxy)
+// [refiid] -- Interface queried for
+// [ppv] -- Interface return
+//
+// Returns: HRESULT
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+SCODE QueryInterfaceProxy3216(THUNK3216OBJ *pto, REFIID refiid, LPVOID *ppv)
+{
+ HRESULT hrRet;
+
+ thkDebugOut((DEB_UNKNOWN, "%sIn QueryInterface3216(%p, %s)\n",
+ NestingLevelString(), pto,
+ IidOrInterfaceString(&refiid)));
+ DebugIncrementNestingLevel();
+
+ if (TlsThkGetData() == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: QIProxy3216 call refused\n"));
+
+ return E_FAIL;
+ }
+
+ CThkMgr *pcthkmgr = TlsThkGetThkMgr();
+ thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
+
+ if ( pto->grfFlags & PROXYFLAG_CLEANEDUP )
+ {
+ thkDebugOut((DEB_WARN,
+ "QueryInterfaceProxy3216: Attempt to QI "
+ "on cleaned-up proxy %08lX for 16-bit object %08lX %s\n",
+ pto, pto->vpvThis16,
+ IidIdxString(IID_IIDIDX(&refiid)) ));
+ *ppv = NULL;
+ return E_FAIL;
+ }
+
+ hrRet = pcthkmgr->QueryInterfaceProxy3216(pto, refiid, ppv);
+
+ //
+ // If the QI for IUnknown failed, then return the current this
+ // pointer as the IUnknown. Watermark 1.02 appears to not support
+ // IUnknown in its IOleInPlaceActiveObject interface, which causes
+ // CoMarshalInterface to fail. The reason it used to work is the
+ // original 16-bit DLL's would just use the provided pointer as
+ // the punk if IUnknown wasn't supported. The following lines of
+ // code emulate that behaviour.
+ //
+ if ((hrRet == E_NOINTERFACE) && IsEqualIID(refiid,IID_IUnknown))
+ {
+ thkDebugOut((DEB_UNKNOWN,
+ "%s Object %p didn't support QI(IID_IUnknown): Faking it\n",
+ NestingLevelString(), pto));
+ ((IUnknown *)pto)->AddRef();
+ *ppv = pto;
+ hrRet = S_OK;
+ }
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_UNKNOWN,
+ "%sOut QueryInterface3216(%p) => %p, ret:0x%08lX\n",
+ NestingLevelString(), pto, *ppv, hrRet));
+ return hrRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: AddRefProxy3216
+//
+// Synopsis: call addref on an 16 bit object
+//
+// Arguments: [pto] -- This pointer (a 32->16 proxy)
+//
+// Returns: New refcount
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+DWORD AddRefProxy3216(THUNK3216OBJ *pto)
+{
+ DWORD dwRet;
+
+ thkDebugOut((DEB_UNKNOWN, "%sIn AddRef3216(%p)\n",
+ NestingLevelString(), pto));
+ DebugIncrementNestingLevel();
+
+ if (TlsThkGetData() == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: AddRefProxy3216 call refused\n"));
+
+ return 0;
+ }
+
+ CThkMgr *pcthkmgr = TlsThkGetThkMgr();
+ thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
+
+ if ( pto->grfFlags & PROXYFLAG_CLEANEDUP )
+ {
+ thkDebugOut((DEB_WARN,
+ "AddRefProxy3216: Attempt to AddRef "
+ "on cleaned-up proxy %08lX for 16-bit object %08lX\n",
+ pto, pto->vpvThis16));
+ return 0;
+ }
+
+ dwRet = pcthkmgr->AddRefProxy3216(pto);
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_UNKNOWN, "%sOut AddRef3216(%p) => %ld\n",
+ NestingLevelString(), pto, dwRet));
+
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReleaseProxy3216
+//
+// Synopsis: Release implementation for 32->16 proxies
+//
+// Arguments: [pto] -- This pointer (a 32->16 proxy)
+//
+// Returns: New refcount
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+DWORD ReleaseProxy3216(THUNK3216OBJ *pto)
+{
+ DWORD dwRet;
+
+ thkDebugOut((DEB_UNKNOWN, "%sIn Release3216(%p)\n",
+ NestingLevelString(), pto));
+ DebugIncrementNestingLevel();
+
+ if (TlsThkGetData() == NULL)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: ReleaseProxy3216 call refused\n"));
+
+ return 0;
+ }
+
+ CThkMgr *pcthkmgr = TlsThkGetThkMgr();
+ thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
+
+ if ( pto->grfFlags & PROXYFLAG_CLEANEDUP )
+ {
+ thkDebugOut((DEB_WARN,
+ "ReleaseProxy3216: Attempt to Release "
+ "on cleaned-up proxy %08lX for 16-bit object %08lX\n",
+ pto, pto->vpvThis16));
+ return 0;
+ }
+
+ dwRet = pcthkmgr->ReleaseProxy3216(pto);
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_UNKNOWN, "%sOut Release3216(%p) => %ld\n",
+ NestingLevelString(), pto, dwRet));
+
+ return dwRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: QueryInterfaceOnObj16
+//
+// Synopsis: call QueryInterface on an 16 bit object
+//
+// Arguments: [vpvThis16] -- 16-bit this pointer
+// [refiid] -- IID
+// [ppv] -- Interface return
+//
+// Returns: HRESULT
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+struct QIARGS
+{
+ IID iid;
+ void *pvObject;
+};
+
+HRESULT QueryInterfaceOnObj16(VPVOID vpvThis16, REFIID refiid, LPVOID *ppv)
+{
+ HRESULT hrRet;
+ VPVOID vpvArgs;
+ QIARGS UNALIGNED *pqa;
+ BYTE bArgs32[WCB16_MAX_CBARGS];
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn QueryInterfaceOnObj16(%p, %s)\n",
+ NestingLevelString(), vpvThis16,
+ IidOrInterfaceString(&refiid)));
+ DebugIncrementNestingLevel();
+
+ thkAssert(WCB16_MAX_CBARGS >= 3*sizeof(DWORD));
+ thkAssert(vpvThis16 != 0 && "QueryInterfaceOnObj16: invalid pointer.");
+
+ // Allocate space for the sixteen bit arguments memory
+ vpvArgs = STACKALLOC16(sizeof(QIARGS));
+ if (vpvArgs == 0)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ // Fill in the in-param memory
+ pqa = FIXVDMPTR(vpvArgs, QIARGS);
+ pqa->iid = refiid;
+
+ // Set up the 16-bit stack in pascal order
+ *(VPVOID *)(bArgs32+0*sizeof(VPVOID)) = vpvArgs+
+ FIELD_OFFSET(QIARGS, pvObject);
+ *(VPVOID *)(bArgs32+1*sizeof(VPVOID)) = vpvArgs;
+ *(VPVOID *)(bArgs32+2*sizeof(VPVOID)) = vpvThis16;
+
+ RELVDMPTR(vpvArgs);
+
+ // Call to 16-bit stub
+ if (!CallbackTo16Ex(gdata16Data.fnQueryInterface16, WCB16_PASCAL,
+ 3*sizeof(DWORD), bArgs32, (DWORD *)&hrRet))
+ {
+ hrRet = E_UNEXPECTED;
+ }
+
+ // Transform the 16-bit HRESULT to a 32-bit HRESULT
+ hrRet = TransformHRESULT_1632(hrRet);
+
+ // Copy back out-param memory
+ pqa = FIXVDMPTR(vpvArgs, QIARGS);
+ *ppv = pqa->pvObject;
+ RELVDMPTR(vpvArgs);
+
+ STACKFREE16(vpvArgs, sizeof(QIARGS));
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR,
+ "%sOut QueryInterfaceOnObj16(%p) => %p, ret:0x%08lX\n",
+ NestingLevelString(), vpvThis16, *ppv, hrRet));
+
+ return hrRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: AddRefOnObj16
+//
+// Synopsis: calls addref on an 16 bit object
+//
+// Arguments: [vpvThis16] -- 16-bit this pointer
+//
+// Returns: New ref count
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+#if DBG == 1
+DWORD AddRefOnObj16(VPVOID vpvThis16)
+{
+ DWORD dwRet;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn AddRefOnObj16(%p)\n",
+ NestingLevelString(), vpvThis16));
+ DebugIncrementNestingLevel();
+
+ dwRet = CallbackTo16(gdata16Data.fnAddRef16, vpvThis16);
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut AddRefOnObj16(%p) => %ld\n",
+ NestingLevelString(), vpvThis16, dwRet));
+
+ return dwRet;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReleaseOnObj16
+//
+// Synopsis: Release a 16-bit object
+//
+// Arguments: [vpvThis16] -- 16-bit this pointer
+//
+// Returns: New ref count
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+#if DBG == 1
+DWORD ReleaseOnObj16(VPVOID vpvThis16)
+{
+ DWORD dwRet;
+
+ thkDebugOut((DEB_THUNKMGR, "%sIn ReleaseOnObj16(%p)\n",
+ NestingLevelString(), vpvThis16));
+ DebugIncrementNestingLevel();
+
+ dwRet = CallbackTo16(gdata16Data.fnRelease16, vpvThis16);
+
+ DebugDecrementNestingLevel();
+ thkDebugOut((DEB_THUNKMGR, "%sOut ReleaseOnObj16(%p) => %ld\n",
+ NestingLevelString(), vpvThis16, dwRet));
+
+ return dwRet;
+}
+#endif
+
+#if DBG == 1
+void DebugDump()
+{
+ CThkMgr *pcthkmgr = (CThkMgr*)TlsThkGetThkMgr();
+ thkAssert(pcthkmgr != NULL && "ThunkManager was not initialized");
+ pcthkmgr->DebugDump3216();
+ pcthkmgr->DebugDump1632();
+}
+#endif
+
diff --git a/private/ole32/olethunk/olethk32/thkmgr.hxx b/private/ole32/olethunk/olethk32/thkmgr.hxx
new file mode 100644
index 000000000..28ed5cbb4
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thkmgr.hxx
@@ -0,0 +1,40 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thkmgr.hxx
+//
+// Contents: 16->32 and 32->16 thunk manager definitions
+//
+// History: 23-Mar-94 JohannP Created
+// 22-May-94 BobDay Split out 16-bit definitions
+// into obj16.hxx
+//
+//----------------------------------------------------------------------------
+
+#ifndef __THKMGR_HXX__
+#define __THKMGR_HXX__
+
+STDAPI ThkMgrInitialize(DWORD dw1, DWORD dw2, DWORD dw3);
+STDAPI_(void) ThkMgrUninitialize(DWORD dw1, DWORD dw2, DWORD dw3);
+
+//
+// 32->16 prototypes
+//
+
+SCODE QueryInterfaceProxy3216(THUNK3216OBJ *pto, REFIID refiid, LPVOID *ppv);
+DWORD AddRefProxy3216(THUNK3216OBJ *pto);
+DWORD ReleaseProxy3216(THUNK3216OBJ *pto);
+
+HRESULT QueryInterfaceOnObj16(VPVOID vpvThis16, REFIID refiid, LPVOID *ppv);
+
+#if DBG == 1
+DWORD AddRefOnObj16(VPVOID vpvThis16);
+DWORD ReleaseOnObj16(VPVOID vpvThis16);
+#else
+#define AddRefOnObj16(this) CallbackTo16(gdata16Data.fnAddRef16, this)
+#define ReleaseOnObj16(this) CallbackTo16(gdata16Data.fnRelease16, this)
+#endif
+
+#endif // #ifndef __THKMGR_HXX__
diff --git a/private/ole32/olethunk/olethk32/thop.hxx b/private/ole32/olethunk/olethk32/thop.hxx
new file mode 100644
index 000000000..159eabfa5
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thop.hxx
@@ -0,0 +1,241 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thop.hxx
+//
+// Contents: Defines the available thops
+//
+// History: 22-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __THOP_HXX__
+#define __THOP_HXX__
+
+//
+// THOP is a single instruction to the interpreter that encodes,
+// decodes parameters sent via LRPC. A string of THOPs describes how to
+// marshal, unmarshal function's paramaters.
+//
+//
+
+typedef enum
+{
+ THOP_END,
+ // Basic types size of type (win3.1)
+ THOP_SHORTLONG, // Signed ints 2b
+ THOP_WORDDWORD, // Unsigned int 2b
+ THOP_COPY, // Direct copies
+ THOP_LPSTR, // LPSTR -- (zero terminated)
+ THOP_LPLPSTR, // LPLPSTR -- (zero terminated)
+ THOP_BUFFER, // void FAR* -- (size in next long)
+
+ // Windows types
+ THOP_HUSER, // HWND, HMENU 2b
+ THOP_HGDI, // HDC, HICON 2b
+ THOP_SIZE, // SIZE 4b
+ THOP_RECT, // RECT 8b
+ THOP_MSG, // MSG 18b
+
+ // Ole types
+ THOP_HRESULT, // HRESULT 4b
+ THOP_STATSTG, // STATSTG > 38b + size of member lpstr
+ THOP_DVTARGETDEVICE, // DVTARGETDEVICE > 16b
+ THOP_STGMEDIUM, // STGMEDIUM > 12b + size of member lpstr
+ THOP_FORMATETC, // FORMATETC > 18b + size of member tdev
+ THOP_HACCEL, // HACCEL 2b
+ THOP_OIFI, // OLEINPLACEFRAMEINFO 10b
+ THOP_BINDOPTS, // BIND_OPTS > 12b
+ THOP_LOGPALETTE, // LOGPALETTE > 8b
+ THOP_SNB, // SNBs in storage Varies
+ THOP_CRGIID, // ciid, rgiid pair from storage
+ THOP_OLESTREAM, // OLESTREAM
+ THOP_HTASK, // HTASK
+ THOP_INTERFACEINFO, // INTERFACEINFO
+
+ THOP_IFACE, // Known interface type
+ THOP_IFACEOWNER, // For IFACE cases with weak references
+ THOP_IFACENOADDREF, // For IFACE cases with no references by user (IOleCacheControl)
+ THOP_IFACECLEAN, // For IRpcStubBuffer::DebugServerRelease
+ THOP_IFACEGEN, // for QueryInterface, etc (refiid, **ppUnk)
+ THOP_IFACEGENOWNER, // For IFACEGEN cases with weak references
+
+ THOP_ROUTINEINDEX, // Thop for indicating the call type index
+ THOP_RETURNTYPE, // Thop for indicating return type of a routine if
+ // not HRESULT
+ THOP_NULL, // NULL ptr, for checking of reserved fields
+ THOP_ERROR, // Invalid thop, for debugging
+ THOP_ENUM, // Enumerator thop start
+ THOP_CALLBACK, // Callback function and argument
+ THOP_RPCOLEMESSAGE, // RPCOLEMESSAGE
+ THOP_ALIAS32, // 16-bit alias for 32-bit quantity
+ THOP_CLSCONTEXT, // Flags DWORD with special handling
+ THOP_FILENAME, // String which is a filename, needs long/short cvt
+ THOP_SIZEDSTRING, // String which cannot exceed a certain length
+
+ THOP_LASTOP, // Marker for last op
+
+ THOP_OPMASK = 0x3f, // Mask for basic operation code
+
+ // Modifiers
+ THOP_IOMASK = 0xc0,
+ THOP_IN = 0x40, // FAR Pointer to in parameter
+ THOP_OUT = 0x80, // FAR Pointer to out parameter
+ THOP_INOUT = 0xc0 // FAR Pointer to in, out parameter
+} THOP_TYPE;
+
+typedef unsigned char THOP;
+
+#define ALIAS_CREATE 0
+#define ALIAS_RESOLVE 1
+#define ALIAS_REMOVE 2
+
+#define MAX_PARAMS 16
+
+typedef DWORD (__stdcall * VTBLFN)(DWORD dw);
+
+typedef struct tagSTACK16INFO
+{
+ BYTE UNALIGNED *pbStart;
+ BYTE UNALIGNED *pbCurrent;
+ int iDir;
+} STACK16INFO;
+
+typedef struct tagSTACK32INFO
+{
+ BYTE *pbStart;
+ BYTE *pbCurrent;
+} STACK32INFO;
+
+typedef struct tagTHUNKINFO
+{
+ STACK16INFO s16;
+ STACK32INFO s32;
+ THOP CONST *pThop;
+ VTBLFN pvfn;
+ SCODE scResult;
+ BOOL fResultThunked;
+ DWORD dwCallerProxy;
+ CThkMgr *pThkMgr;
+ IIDIDX iidx;
+ DWORD dwMethod;
+ IUnknown *this32;
+} THUNKINFO;
+
+// These are declared extern "C" because there was a bug in the
+// PPC compiler (aug '95) where the const related decorations on
+// the global data symbols was not done consistantly. By using
+// extern "C" the bug is simply avoided.
+// The problem was only with aThopFunctions*[] but I added
+// aThopEnumFunctions*[] for a consistent look and usage. A related
+// bug is fixed with apthopsApiThops[].
+
+extern "C" DWORD (* CONST aThopFunctions1632[])(THUNKINFO *);
+extern "C" DWORD (* CONST aThopFunctions3216[])(THUNKINFO *);
+extern "C" DWORD (* CONST aThopEnumFunctions1632[])(THUNKINFO *);
+extern "C" DWORD (* CONST aThopEnumFunctions3216[])(THUNKINFO *);
+
+#define SKIP_STACK16(s16, cb) \
+ (s16)->pbCurrent = (s16)->iDir < 0 ? \
+ (s16)->pbCurrent-(cb) : \
+ (s16)->pbCurrent+(cb)
+
+#define PTR_STACK16(s16, cb) \
+ ((s16)->pbCurrent-((s16)->iDir < 0 ? (cb) : 0))
+
+#define GET_STACK16(pti, val, typ) \
+ if ((pti)->s16.iDir < 0) \
+ { \
+ (pti)->s16.pbCurrent -= sizeof(typ); \
+ (val) = *(typ UNALIGNED *)(pti)->s16.pbCurrent; \
+ } \
+ else \
+ { \
+ (val) = *(typ UNALIGNED *)(pti)->s16.pbCurrent; \
+ (pti)->s16.pbCurrent += sizeof(typ); \
+ }
+
+#define TO_STACK16(pti, val, typ) \
+ if ((pti)->s16.iDir < 0) \
+ { \
+ (pti)->s16.pbCurrent -= sizeof(typ); \
+ *(typ UNALIGNED *)(pti)->s16.pbCurrent = (val); \
+ } \
+ else \
+ { \
+ *(typ UNALIGNED *)(pti)->s16.pbCurrent = (val); \
+ (pti)->s16.pbCurrent += sizeof(typ); \
+ }
+
+#define PEEK_STACK16(pti, val, typ) \
+ (val) = *(typ UNALIGNED *)(pti)->s16.pbCurrent
+
+#define INDEX_STACK16(pti, val, typ, idx, predec) \
+ (val) = *(typ UNALIGNED *)((pti)->s16.iDir < 0 ? \
+ ((pti)->s16.pbCurrent+(idx)-(predec)) : \
+ ((pti)->s16.pbCurrent-(idx)))
+
+#define SKIP_STACK32(s32, cb) \
+ (s32)->pbCurrent += (cb)
+
+#define PTR_STACK32(s32) \
+ (s32)->pbCurrent
+
+#define GET_STACK32(pti, val, typ) \
+ (val) = *(typ *)(pti)->s32.pbCurrent; \
+ SKIP_STACK32(&(pti)->s32, sizeof(typ))
+
+#define TO_STACK32(pti, val, typ) \
+ *(typ *)(pti)->s32.pbCurrent = (val);\
+ SKIP_STACK32(&(pti)->s32, sizeof(typ))
+
+#define PEEK_STACK32(pti, val, typ) \
+ (val) = *(typ *)(pti)->s32.pbCurrent
+
+#define INDEX_STACK32(pti, val, typ, idx) \
+ (val) = *(typ *)((pti)->s32.pbCurrent-(idx))
+
+#if DBG == 0
+
+// In debug builds this goes through a function that can emit
+// debug info about thops being executed
+#define EXECUTE_THOP1632(pti) \
+ (*aThopFunctions1632[*((pti)->pThop) & THOP_OPMASK])(pti)
+#define EXECUTE_THOP3216(pti) \
+ (*aThopFunctions3216[*((pti)->pThop) & THOP_OPMASK])(pti)
+#define EXECUTE_ENUMTHOP1632(pti) \
+ (*aThopEnumFunctions1632[*(pti)->pThop])(pti)
+#define EXECUTE_ENUMTHOP3216(pti) \
+ (*aThopEnumFunctions3216[*(pti)->pThop])(pti)
+
+#else
+
+DWORD EXECUTE_THOP1632(THUNKINFO *pti);
+DWORD EXECUTE_THOP3216(THUNKINFO *pti);
+DWORD EXECUTE_ENUMTHOP1632(THUNKINFO *pti);
+DWORD EXECUTE_ENUMTHOP3216(THUNKINFO *pti);
+
+#endif
+
+#define IS_THOP_IN(pti) ((*((pti)->pThop) & THOP_IN) == THOP_IN)
+#define IS_THOP_OUT(pti) ((*((pti)->pThop) & THOP_OUT) == THOP_OUT)
+
+// Max size of preallocated strings
+#define CBSTRINGPREALLOC 512
+#define CWCSTRINGPREALLOC (CBSTRINGPREALLOC/sizeof(WCHAR))
+
+// BUGBUG - Max size?
+#define CCHMAXSTRING 0x1000
+
+// Max size of preallocated palettes
+#define NPALETTEPREALLOC 256
+
+// Size of a LOGPALETTE structure with N entries
+#define CBPALETTE(n) (sizeof(LOGPALETTE)+((n)-1)*sizeof(PALETTEENTRY))
+
+// Hide the exact field in the RPCOLEMESSAGE we use to store thunking data
+#define ROM_THUNK_FIELD(rom) ((rom)->reserved1)
+
+#endif // #ifndef __THOP_HXX__
diff --git a/private/ole32/olethunk/olethk32/thop16.cxx b/private/ole32/olethunk/olethk32/thop16.cxx
new file mode 100644
index 000000000..32d0ec207
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thop16.cxx
@@ -0,0 +1,4114 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thop16.cxx
+//
+// Contents: Thop implementations for 16->32
+//
+// History: 22-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <ole2.h>
+#include <valid.h>
+#include <string.h>
+
+#include "struct16.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Function: EXECUTE_THOP1632, public
+//
+// Synopsis: Debugging version of thop dispatch routine
+//
+// Arguments: [pti] - Thunking info
+//
+// Returns: Appropriate status
+//
+// History: 24-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+DWORD EXECUTE_THOP1632(THUNKINFO *pti)
+{
+ thkDebugOut((DEB_THOPS, "ExThop1632: %s (0x%02X), s16 %p, s32 %p\n",
+ ThopName(*pti->pThop), *pti->pThop, pti->s16.pbCurrent,
+ pti->s32.pbCurrent));
+ thkAssert((*pti->pThop & THOP_OPMASK) < THOP_LASTOP);
+ return (*aThopFunctions1632[*((pti)->pThop) & THOP_OPMASK])(pti);
+}
+#endif
+
+#if DBG == 1
+DWORD EXECUTE_ENUMTHOP1632(THUNKINFO *pti)
+{
+ thkDebugOut((DEB_THOPS, "ExEnumThop1632: %s (0x%02X), s16 %p, s32 %p\n",
+ EnumThopName(*pti->pThop), *pti->pThop, pti->s16.pbCurrent,
+ pti->s32.pbCurrent));
+ return (*aThopEnumFunctions1632[*(pti)->pThop])(pti);
+}
+#endif
+
+// Generated by the tool, in tc1632.cxx
+DWORD ThunkCall1632( THUNKINFO * );
+
+//+---------------------------------------------------------------------------
+//
+// Function: FixedThopHandler, public
+//
+// Synopsis: Generic function which handles the high-level details
+// of thop execution for thops that operate on known-size
+// data
+//
+// Arguments: [pti] - Thunking state information
+// [thop] - Thop being executed
+// [cb16] - 16-bit size
+// [pfn1632] - 16->32 conversion routine
+// [cb32] - 32-bit size
+// [pfn3216] - 32->16 conversion routine
+//
+// Returns: Appropriate status code
+//
+// History: 05-Apr-94 DrewB Created
+//
+// Notes: Automatically increments pThop
+//
+//----------------------------------------------------------------------------
+
+DWORD FixedThopHandler1632(THUNKINFO *pti,
+ THOP thop,
+ UINT cb16,
+ FIXEDHANDLERROUTINE pfn1632,
+ UINT cb32,
+ FIXEDHANDLERROUTINE pfn3216)
+{
+ DWORD dwResult;
+ VPVOID vp16;
+ BYTE *pb16;
+ BYTE *pb32;
+
+ if ((thop & (THOP_IN | THOP_OUT)) != 0)
+ {
+ pb32 = NULL;
+
+ GET_STACK16(pti, vp16, VPVOID);
+ if ( vp16 != 0 )
+ {
+ pb16 = (BYTE *)ValidatePtr16(pti, vp16, cb16, thop);
+ if (pb16 != NULL)
+ {
+ pb32 = (BYTE *)STACKALLOC32(cb32);
+ if (pb32 == NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ else if ((thop & THOP_IN) != 0)
+ {
+ (pfn1632)(pb16, pb32, cb16, cb32);
+ }
+
+ WOWRELVDMPTR(vp16);
+ }
+ }
+
+ TO_STACK32(pti, pb32, BYTE *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ((thop & THOP_OUT) != 0 && vp16 != 0)
+ {
+ pb16 = (BYTE *)WOWFIXVDMPTR(vp16, cb16);
+
+ if (SUCCEEDED(dwResult))
+ {
+ (pfn3216)(pb32, pb16, cb32, cb16);
+ }
+ else if ((thop & THOP_IN) == 0)
+ {
+ // Zero out-only parameters on failure
+ memset(pb16, 0, cb16);
+ }
+
+ WOWRELVDMPTR(vp16);
+ }
+
+ if (pb32 != NULL)
+ {
+ STACKFREE32(pb32, cb32);
+ }
+ }
+ else
+ {
+ (pfn1632)(PTR_STACK16(&pti->s16, cb16), PTR_STACK32(&pti->s32),
+ cb16, cb32);
+ SKIP_STACK16(&pti->s16, cb16);
+ SKIP_STACK32(&pti->s32, cb32);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+ }
+
+ return dwResult;
+}
+
+//-----------------------------------------------------------------------------
+//
+// Handler-based thunks
+//
+// These thunks use the fixed-size generic thop handler to do their work
+//
+//-----------------------------------------------------------------------------
+
+// Handle straight copy
+DWORD Thop_Copy_1632(THUNKINFO *pti)
+{
+ THOP thopSize;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_COPY);
+
+ thopSize = *++pti->pThop;
+ return FixedThopHandler1632(pti,
+ *(pti->pThop-1),
+ thopSize, FhCopyMemory,
+ thopSize, FhCopyMemory);
+}
+
+DWORD Thop_ShortToLong_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SHORTLONG);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(SHORT), FhShortToLong,
+ sizeof(LONG), FhLongToShort);
+}
+
+DWORD Thop_WordToDword_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_WORDDWORD);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(WORD), FhWordToDword,
+ sizeof(DWORD), FhDwordToWord);
+}
+
+DWORD Thop_GdiHandle_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HGDI);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhGdiHandle1632,
+ sizeof(HANDLE), FhGdiHandle3216);
+}
+
+DWORD Thop_UserHandle_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HUSER);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhUserHandle1632,
+ sizeof(HANDLE), FhUserHandle3216);
+}
+
+DWORD Thop_HACCEL_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HACCEL);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhHaccel1632,
+ sizeof(HANDLE), FhHaccel3216);
+}
+
+DWORD Thop_HTASK_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HTASK);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhHtask1632,
+ sizeof(HANDLE), FhHtask3216);
+}
+
+DWORD Thop_HRESULT_1632( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HRESULT);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(HRESULT), FhHresult1632,
+ sizeof(HRESULT), FhHresult3216);
+}
+
+DWORD Thop_NULL_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_NULL);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(void *), FhNull,
+ sizeof(void *), FhNull);
+}
+
+DWORD Thop_RECT_1632( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RECT);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(RECT16), FhRect1632,
+ sizeof(RECT), FhRect3216);
+}
+
+DWORD Thop_BINDOPTS_1632( THUNKINFO *pti )
+{
+ VPVOID vpbo16;
+ BIND_OPTS UNALIGNED *pbo;
+ UINT cb;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_BINDOPTS);
+
+ PEEK_STACK16(pti, vpbo16, VPVOID);
+ pbo = (BIND_OPTS UNALIGNED *)GetReadPtr16(pti, vpbo16, sizeof(BIND_OPTS));
+ if (pbo != NULL)
+ {
+ cb = pbo->cbStruct;
+ WOWRELVDMPTR(vpbo16);
+ }
+ else
+ {
+ // Doesn't really matter, since pti->scResult was set to error
+ // by GetReadPtr16
+ cb = sizeof(BIND_OPTS);
+ }
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ cb, FhCopyMemory,
+ cb, FhCopyMemory);
+}
+
+DWORD Thop_SIZE_1632( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SIZE);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(SIZE16), FhSize1632,
+ sizeof(SIZE), FhSize3216);
+}
+
+DWORD Thop_MSG_1632( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_MSG);
+
+ return FixedThopHandler1632(pti,
+ *pti->pThop,
+ sizeof(MSG16), FhMsg1632,
+ sizeof(MSG), FhMsg3216);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_ERROR_1632, public
+//
+// Synopsis: Any Thop type which should just fail with an error
+// should go be directed here.
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_ERROR_1632 ( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ERROR);
+
+ thkAssert( FALSE && "Hey we hit an ERROR Thop in 16->32" );
+
+ return (DWORD)E_UNEXPECTED;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThunkInString1632, public
+//
+// Synopsis: Converts an in-parameter string
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD ThunkInString1632(THUNKINFO *pti)
+{
+ DWORD dwResult;
+ VPSTR vpstr;
+ LPOLESTR lpstrDest;
+ OLECHAR *ptcStackText;
+
+ dwResult = (DWORD)S_OK;
+ ptcStackText = NULL;
+
+ GET_STACK16(pti, vpstr, VPSTR);
+
+ if (vpstr == 0)
+ {
+ lpstrDest = NULL;
+ }
+ else
+ {
+ ptcStackText = (OLECHAR *)STACKALLOC32(CWCSTRINGPREALLOC*
+ sizeof(OLECHAR));
+ if (ptcStackText == NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ else
+ {
+ lpstrDest = Convert_VPSTR_to_LPOLESTR( pti, vpstr, ptcStackText,
+ CWCSTRINGPREALLOC );
+ }
+ }
+
+ thkDebugOut((DEB_ARGS, "In1632 LPSTR: %p -> %p '%ws'\n",
+ vpstr, lpstrDest, lpstrDest));
+
+ TO_STACK32(pti, lpstrDest, LPOLESTR );
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if (lpstrDest != NULL)
+ {
+ Convert_VPSTR_to_LPOLESTR_free( ptcStackText, lpstrDest );
+ }
+
+ if (ptcStackText != NULL)
+ {
+ STACKFREE32(ptcStackText, CWCSTRINGPREALLOC*sizeof(OLECHAR));
+ }
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_LPSTR_1632, public
+//
+// Synopsis: Converts 16-bit LPSTR to 32-bit LPSTR pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_LPSTR_1632( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LPSTR);
+ //
+ // We have only input LPSTRs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_IN &&
+ "LPSTR must be input only!" );
+
+ return ThunkInString1632(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertTaskString3216, public
+//
+// Synopsis: Converts a task-memory string
+//
+// Arguments: [pti] - Thunk info
+// [pos32] - String
+// [vpstrPreAlloc] - Preallocated string or NULL
+// [cchPreAlloc] - Preallocated size or zero
+// [pvpstr16] - String
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pti]
+// [pvpstr16]
+//
+// History: 14-May-94 DrewB Created
+//
+// Notes: Frees preallocation if successful and:
+// Name is too large or
+// Name is NULL
+//
+// Always frees source string if non-zero and valid
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertTaskString3216(THUNKINFO *pti,
+ LPOLESTR pos32,
+ VPSTR vpstrPreAlloc,
+ UINT cchPreAlloc,
+ VPSTR UNALIGNED *pvpstr16)
+{
+ VPVOID vpstr16;
+ UINT cch;
+ SCODE sc;
+
+ sc = S_OK;
+
+ if (pos32 == NULL)
+ {
+ vpstr16 = 0;
+ }
+ else
+ {
+ if (IsBadStringPtrW(pos32, CCHMAXSTRING))
+ {
+ sc = E_INVALIDARG;
+ }
+ else
+ {
+ cch = lstrlenW(pos32)+1;
+
+ if (cch > cchPreAlloc)
+ {
+ // Our prealloc buffer is too small, so try and get a
+ // new one
+
+ // Allow for each Unicode character to take two
+ // bytes in case of multibyte expansion
+ vpstr16 = (VPSTR)TaskMalloc16( cch*2 );
+ if (vpstr16 == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ vpstr16 = vpstrPreAlloc;
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ sc = Convert_LPOLESTR_to_VPSTR(pos32, vpstr16, cch, cch*2);
+ if (FAILED(sc) && vpstr16 != vpstrPreAlloc)
+ {
+ TaskFree16(vpstr16);
+ }
+ }
+
+ TaskFree32(pos32);
+ }
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ // If there was a preallocated string we didn't use,
+ // free it
+ if (vpstrPreAlloc != 0 && vpstrPreAlloc != vpstr16)
+ {
+ TaskFree16(vpstrPreAlloc);
+ }
+
+ *pvpstr16 = vpstr16;
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThunkOutString1632, public
+//
+// Synopsis: Converts an out param string or filename
+//
+// Arguments: [pti] - Thunk state information
+// [fFile] - Filename or plain string
+//
+// Returns: Appropriate status code
+//
+// History: 24-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD ThunkOutString1632(THUNKINFO *pti,
+ BOOL fFile)
+{
+ DWORD dwResult;
+ VPVOID vpvpstr16;
+ VPSTR vpstr16;
+ VPSTR UNALIGNED *lpvpstr16;
+ LPOLESTR *lplpstr32;
+ LPOLESTR lpstr;
+
+ GET_STACK16(pti, vpvpstr16, VPSTR);
+
+ lplpstr32 = NULL;
+ if ( vpvpstr16 != 0 )
+ {
+ lpvpstr16 = (VPSTR UNALIGNED *)GetWritePtr16(pti, vpvpstr16,
+ sizeof(VPSTR));
+ if ( lpvpstr16 != NULL )
+ {
+ WOWRELVDMPTR(vpvpstr16);
+
+ lplpstr32 = &lpstr;
+
+ vpstr16 = (VPSTR)TaskMalloc16(CBSTRINGPREALLOC);
+ if (vpstr16 == 0)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ }
+ }
+
+ TO_STACK32(pti, lplpstr32, LPOLESTR FAR *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( lplpstr32 != NULL )
+ {
+ if ( SUCCEEDED(dwResult) )
+ {
+ SCODE sc;
+
+ if (fFile)
+ {
+ UINT cch;
+
+ // The string pointed to by lpstr is ours so we
+ // can do the long->short conversion in place
+ // without worrying about trashing the memory
+ // The short path name should always be able
+ // to fit in the long path name's buffer since
+ // the file names that we are thunking are always
+ // absolute paths
+
+ cch = lstrlenW(lpstr)+1;
+
+ // Ignore failures; if we can't convert the name
+ // then we simply pass on what we were given
+ GetShortPathName(lpstr, lpstr, cch);
+ }
+
+ sc = ConvertTaskString3216(pti, lpstr, vpstr16,
+ CWCSTRINGPREALLOC, &vpstr16);
+ if (FAILED(sc))
+ {
+ dwResult = sc;
+ }
+ }
+
+ if (FAILED(dwResult))
+ {
+ TaskFree16(vpstr16);
+ vpstr16 = 0;
+ }
+
+ lpvpstr16 = FIXVDMPTR( vpvpstr16, VPSTR );
+ *lpvpstr16 = vpstr16;
+
+#if DBG==1
+ thkDebugOut((DEB_ARGS, "Out1632 LPLPSTR: %p -> %p '%s'\n",
+ lpstr, vpstr16,
+ vpstr16 != 0 ? WOWFIXVDMPTR(vpstr16, 0) : "<null>"));
+ if (vpstr16 != 0)
+ {
+ WOWRELVDMPTR(vpstr16);
+ }
+#endif
+
+ RELVDMPTR( vpvpstr16 );
+ }
+ else
+ {
+ thkDebugOut((DEB_ARGS, "Out1632 LPLPSTR NULL\n"));
+ }
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_LPLPSTR_1632, public
+//
+// Synopsis: Converts 32-bit LPSTR to 16-bit LPSTR pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 25-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_LPLPSTR_1632( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LPLPSTR);
+ //
+ // We don't have anything but unmodified LPLPSTRs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == 0 &&
+ "LPLPSTR must be unmodified only!" );
+
+ return ThunkOutString1632(pti, FALSE);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_BUFFER_1632, public
+//
+// Synopsis: Converts 16-bit block of memory to 32-bit block of memory
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 25-Feb-94 BobDay Created
+// 14-Mar-95 KentCe Buffer copy not required for Win95.
+//
+// Notes: WARNING! WARNING! WARNING! For an out parameter this expects
+// three parameters on the stack in the following format and order:
+// VOID * pointer to buffer
+// DWORD count of bytes in buffer
+// DWORD * count of bytes returned in the buffer
+//
+//----------------------------------------------------------------------------
+
+#define WATCH_VALUE 0xfef1f0
+
+DWORD Thop_BUFFER_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+ VPVOID vp16;
+ LPVOID lp16;
+ LPVOID lp32;
+ DWORD dwCount;
+ VPVOID vp16CountOut;
+ DWORD dwCountOut32 = 0;
+ DWORD * pdwCountOut32 = &dwCountOut32;
+#if DBG == 1
+ DWORD dwWatch;
+#endif
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_BUFFER);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ //
+ // We only have in and out BUFFER thops
+ //
+ thkAssert((fThopInput || fThopOutput)
+ && (fThopInput != fThopOutput)
+ && "BUFFER must be in or out only!" );
+
+ GET_STACK16(pti, vp16, VPVOID);
+ GET_STACK16(pti, dwCount, DWORD);
+
+ if (fThopOutput)
+ {
+ // Get the pointer to the returned value off the stack
+ GET_STACK16(pti, vp16CountOut, VPVOID);
+ }
+
+ lp32 = NULL;
+
+ if (vp16 == 0)
+ {
+ // lp32 is already NULL
+ }
+ else if (dwCount == 0)
+ {
+ // If the count is zero then we can pass any valid 32-bit
+ // pointer
+
+#if DBG == 1
+ // In debug, make sure that no data is written back to the
+ // memory we pass on
+ dwWatch = WATCH_VALUE;
+ lp32 = &dwWatch;
+#else
+ lp32 = &dwResult;
+#endif
+ }
+ else
+ {
+ //
+ // Under Win95 we can lock down 16-bit memory so a duplicate
+ // buffer is not required.
+ //
+#if defined(_CHICAGO_)
+ lp32 = WOWFIXVDMPTR(vp16, dwCount);
+#else
+ lp16 = ValidatePtr16(pti, vp16, dwCount, *pti->pThop);
+
+ if ( lp16 != NULL )
+ {
+ lp32 = (LPVOID)CoTaskMemAlloc( dwCount );
+ if ( lp32 == NULL )
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ else
+ {
+ if ( fThopInput )
+ {
+ memcpy( lp32, lp16, dwCount );
+ }
+ }
+
+ WOWRELVDMPTR(vp16);
+ }
+#endif
+ }
+
+ thkDebugOut((DEB_ARGS, "1632 BUFFER: %p -> %p, %u\n",
+ vp16, lp32, dwCount));
+
+ TO_STACK32(pti, lp32, LPVOID );
+ TO_STACK32(pti, dwCount, DWORD );
+
+ if (fThopOutput)
+ {
+ TO_STACK32(pti, pdwCountOut32, LPVOID );
+ }
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if (fThopOutput)
+ {
+ // If the pointer in sixteen bit land is non-null then return the
+ // count of bytes written to the buffer.
+ DWORD UNALIGNED *lpdw16 = (DWORD UNALIGNED *)
+ ValidatePtr16(pti, vp16CountOut, sizeof(DWORD), *pti->pThop);
+
+ if (lpdw16 != NULL)
+ {
+ *lpdw16 = dwCountOut32;
+ WOWRELVDMPTR(vp16CountOut);
+ }
+
+#if !defined(_CHICAGO_)
+ //
+ // Under Win95 we can lock down 16-bit memory so a duplicate
+ // buffer is not required.
+ //
+ if ( SUCCEEDED(dwResult) )
+ {
+ if (dwCountOut32 > 0 && vp16 != 0)
+ {
+ lp16 = (LPVOID)WOWFIXVDMPTR( vp16, dwCountOut32 );
+
+ memcpy( lp16, lp32, dwCountOut32 );
+
+ WOWRELVDMPTR(vp16);
+ }
+ }
+#endif // _CHICAGO_
+ }
+
+#if DBG == 1
+ if (lp32 != NULL && dwCount == 0)
+ {
+ thkAssert(dwWatch == WATCH_VALUE);
+ }
+#endif
+
+ //
+ // Under Win95 we can lock down 16-bit memory so a duplicate
+ // buffer is not required.
+ //
+#if !defined(_CHICAGO_)
+ //
+ // Now free the buffer
+ //
+ if ( lp32 != NULL && dwCount > 0 )
+ {
+ CoTaskMemFree( lp32 );
+ }
+#endif
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_SNB_1632, public
+//
+// Synopsis: Converts 16-bit SNB to 32-bit SNB pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_SNB_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+ VPVOID snb16;
+ VPSTR *lpvpstr;
+ VPSTR UNALIGNED *lpvpstrTemp;
+ VPSTR vpstr;
+ SNB snb32;
+ UINT cStr;
+ UINT cStrTemp;
+ LPOLESTR *lplpstr;
+ UINT cbStrings;
+ OLECHAR *pocStr;
+ LPSTR lpstr16;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SNB);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ //
+ // We don't have anything but unmodified SNBs
+ //
+ thkAssert( !fThopInput && !fThopOutput && "SNB must be unmodified only!" );
+
+ GET_STACK16(pti, snb16, VPVOID);
+
+ snb32 = NULL;
+ if ( snb16 != 0 )
+ {
+ //
+ // Count the strings in the 16-bit snb
+ //
+ lpvpstr = (VPSTR FAR *)GetReadPtr16( pti, snb16, sizeof(VPSTR) );
+ if ( lpvpstr != 0 )
+ {
+ lpvpstrTemp = lpvpstr;
+ cStr = 0;
+ cbStrings = 0;
+ do
+ {
+ cStr++;
+ vpstr = *lpvpstrTemp++;
+
+ if ( vpstr == 0 )
+ {
+ break;
+ }
+
+ lpstr16 = GetStringPtr16(pti, vpstr, CCHMAXSTRING,
+ &cStrTemp);
+ if ( lpstr16 == 0 )
+ {
+ WOWRELVDMPTR(snb16);
+ lpvpstr = NULL;
+ break; // Leave with snb32 still NULL
+ }
+
+ WOWRELVDMPTR(vpstr);
+
+ cbStrings += cStrTemp;
+ }
+ while ( TRUE );
+ }
+
+ if ( lpvpstr != NULL )
+ {
+ thkDebugOut((DEB_ARGS, "In1632 SNB: %d strings\n", cStr));
+
+ //
+ // Allocate space for the 32-bit snb
+ //
+ snb32 = (LPOLESTR FAR *)CoTaskMemAlloc( cStr*sizeof(LPOLESTR) +
+ cbStrings*sizeof(WCHAR));
+ if (snb32 == NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ else
+ {
+ pocStr = (OLECHAR *)((BYTE *)snb32+cStr*sizeof(LPOLESTR));
+
+ //
+ // Now convert the strings
+ //
+ lpvpstrTemp = lpvpstr;
+ lplpstr = snb32;
+ cStrTemp = cStr - 1;
+
+ while ( cStrTemp > 0 )
+ {
+ --cStrTemp;
+
+ vpstr = *lpvpstrTemp++;
+
+ thkAssert( vpstr != 0 &&
+ "Loop is processing end of snb\n" );
+
+ // Guaranteed to use pocStr as storage since cbStrings is
+ // large enough to contain all the strings
+ *lplpstr = Convert_VPSTR_to_LPOLESTR( pti, vpstr,
+ pocStr, cbStrings );
+
+ if (*lplpstr == NULL)
+ {
+ CoTaskMemFree(snb32);
+ snb32 = NULL;
+ break;
+ }
+
+#if DBG == 1
+ thkDebugOut((DEB_ARGS, "In1632 SNB: %p '%s' -> "
+ "%p '%ws'\n",
+ vpstr, WOWFIXVDMPTR(vpstr, 0),
+ *lplpstr, *lplpstr));
+ WOWRELVDMPTR(vpstr);
+#endif
+
+ pocStr += lstrlenW(pocStr)+1;
+ lplpstr++;
+ }
+
+ // Terminate SNB
+ *lplpstr = NULL;
+
+ thkAssert(*lpvpstrTemp == 0);
+
+ WOWRELVDMPTR(snb16);
+ }
+ }
+ }
+
+ thkDebugOut((DEB_ARGS, "In1632 SNB: %p -> %p\n", snb16, snb32));
+
+ TO_STACK32(pti, snb32, SNB );
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ //
+ // Free SNB memory if necessary
+ //
+ if ( snb32 != 0 )
+ {
+ CoTaskMemFree(snb32);
+ }
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThunkInterface1632, private
+//
+// Synopsis: Handles interface thunking for THOP_IFACE and
+// THOP_IFACEGEN
+//
+// Arguments: [pti] - Thunking state information
+// [iidx] - Interface index or IID
+// [thop] - Thop being executed
+// [punkOuter] - Controlling IUnknown or NULL
+//
+// Returns: Appropriate status code
+//
+// History: 01-Mar-94 DrewB Created
+//
+// Notes: Assumes caller has already adjusted pti->pThop
+//
+//----------------------------------------------------------------------------
+
+DWORD ThunkInterface1632(THUNKINFO *pti,
+ IIDIDX iidx,
+ THOP thop,
+ IUnknown *punkOuter)
+{
+ VPVOID vpv;
+ DWORD dwResult;
+ IUnknown *punkThis32In;
+ IUnknown *punkThis32Out;
+ VPVOID vpvThis16;
+ VPVOID vpvIn;
+ VPVOID UNALIGNED *pvpvOut;
+ VPVOID vpPreAlloc = NULL;
+ THUNK1632OBJ UNALIGNED *pto;
+
+ punkThis32In = NULL;
+
+ // Retrieve in or out interface pointer
+ GET_STACK16(pti, vpv, VPVOID);
+
+ // Out takes precedence over in for determining indirection depth
+
+ if ((thop & THOP_OUT) != 0 && vpv != 0)
+ {
+ pvpvOut = (VPVOID UNALIGNED *)GetWritePtr16(pti, vpv, sizeof(VPVOID));
+ if (pvpvOut != NULL)
+ {
+ vpvIn = *pvpvOut;
+ WOWRELVDMPTR(vpv);
+ }
+ else
+ {
+ thkDebugOut((DEB_WARN, "WARNING: ThunkInterface1632 - bad "
+ "pointer %p\n", vpv));
+ }
+ }
+ else
+ {
+ vpvIn = vpv;
+ }
+
+ if ((thop & THOP_IN) != 0 && SUCCEEDED(pti->scResult))
+ {
+ if (vpvIn == 0)
+ {
+ punkThis32In = NULL;
+ }
+ else
+ {
+ if ( !IsValidInterface16(pti, vpvIn) )
+ {
+ thkDebugOut((DEB_WARN, "WARNING: ThunkInterface1632 - invalid "
+ "interface %p\n", vpvIn));
+ }
+ else
+ {
+ thkAssert(IIDIDX_IS_IID(iidx) ||
+ (IIDIDX_INDEX(iidx) >= 0 &&
+ IIDIDX_INDEX(iidx) < THI_COUNT));
+
+ punkThis32In = pti->pThkMgr->FindProxy3216(NULL, vpvIn, iidx,
+ NULL);
+
+ if (punkThis32In == NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ thkDebugOut((DEB_WARN, "WARNING: ThunkInterface1632 - "
+ "Can't create proxy for %p\n", vpvIn));
+ }
+ }
+ }
+
+ thkDebugOut((DEB_ARGS, "In1632 %s %p -> %p\n",
+ IidIdxString(iidx), vpvIn, punkThis32In));
+ }
+
+ if ((thop & THOP_OUT) != 0 && vpv != 0 && SUCCEEDED(pti->scResult))
+ {
+ thkAssert(IIDIDX_IS_IID(iidx) ||
+ (IIDIDX_INDEX(iidx) >= 0 &&
+ IIDIDX_INDEX(iidx) < THI_COUNT));
+
+ // Preallocate a proxy for the out parameter
+ if ((vpPreAlloc = pti->pThkMgr->CanGetNewProxy1632(iidx))== NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ thkDebugOut((DEB_WARN, "WARNING: ThunkInterface1632 - "
+ "Cannot preallocate %s proxy\n", IidIdxString(iidx)));
+ }
+
+ punkThis32Out = punkThis32In;
+ TO_STACK32(pti, &punkThis32Out, IUnknown **);
+
+ // Set the temporary proxy's this pointer to point to the place
+ // to fetch the real this pointer from
+ pto = FIXVDMPTR(vpPreAlloc, THUNK1632OBJ);
+ pto->punkThis32 = (IUnknown *)&punkThis32Out;
+ RELVDMPTR(vpPreAlloc);
+
+ // Set the out pointer to the temporary proxy so that there's
+ // an object available to all back through even before the
+ // current call has completed
+ // Certain apps (Corel Draw 5.0 is one) point out pointers to
+ // objects which are used inside of calls which fill out the
+ // out pointer and they require that the out pointer be filled
+ // in to operate correctly
+ // This will get NULLed out in failure cases
+ *FIXVDMPTR(vpv, VPVOID) = vpPreAlloc;
+ RELVDMPTR(vpv);
+ }
+ else
+ {
+ TO_STACK32(pti, punkThis32In, IUnknown *);
+ }
+
+ // Assume that our caller has already adjusted pThop
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( ((thop & THOP_OPMASK) == THOP_IFACENOADDREF)
+ && (punkThis32In != NULL)
+ && ((thop & THOP_IN) != 0)
+ && (vpv != 0)
+ && (SUCCEEDED((SCODE)dwResult))
+ && (punkOuter != NULL)
+ )
+ {
+ // NOTE: the 3216 bit pointer did not get addref'd by the users
+ // but should remain until the outer object goes away
+ // Steps:
+ // - Local addref the 3216 proxy
+ // - aggregate it with punkOuter
+
+ THUNK3216OBJ *pto = pti->pThkMgr->LookupProxy3216(vpvIn);
+
+ if (pto)
+ pto->cRefLocal++;
+ vpvThis16 =
+ pti->pThkMgr->FindAggregate1632(NULL, punkOuter,
+ punkThis32In, iidx);
+ }
+ else if (punkThis32In != NULL)
+ {
+ // The rules for [in,out] require that we NOT release here.
+ // Passing an Interface [in,out] has already given the reference away.
+ if( (thop & THOP_INOUT) != THOP_INOUT )
+ {
+ // Note that if the routine called keeps the proxy around
+ // it should AddRef it so this won't really remove the object
+ pti->pThkMgr->FreeProxy3216(vpvIn);
+ }
+ }
+
+ if ((thop & THOP_OUT) != 0 && vpv != 0)
+ {
+ vpvThis16 = 0;
+
+ if (SUCCEEDED((SCODE)dwResult) && punkThis32Out != NULL)
+ {
+ // Get a 16-bit proxy object for the 32-bit object
+
+ if (punkOuter != NULL)
+ {
+ vpvThis16 =
+ pti->pThkMgr->FindAggregate1632(vpPreAlloc, punkOuter,
+ punkThis32Out, iidx);
+ }
+ else
+ {
+ vpvThis16 = pti->pThkMgr->FindProxy1632(vpPreAlloc,
+ punkThis32Out, iidx,
+ NULL);
+ }
+ }
+ else if (vpPreAlloc != NULL)
+ {
+ // Return our preallocated proxy because we don't need it
+ pti->pThkMgr->FreeNewProxy1632(vpPreAlloc, iidx);
+ }
+
+ // Set the out param
+ // Get the VDM pointer again since we may have done nested
+ // transitions since we last got it
+ pvpvOut = FIXVDMPTR(vpv, VPVOID);
+ *pvpvOut = vpvThis16;
+ RELVDMPTR(vpv);
+
+ thkDebugOut((DEB_ARGS, "Out1632 %s %p -> %p\n",
+ IidIdxString(iidx), punkThis32Out, vpvThis16));
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_IFACEGEN_1632, public
+//
+// Synopsis: Thunks interfaces out through ppvs from 16->32
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_IFACEGEN_1632(THUNKINFO *pti)
+{
+ IIDIDX iidx;
+ THOP thop, thopOp, thopWeakOffset;
+ VPVOID vpvIid;
+ IUnknown *punkOuter;
+ IID UNALIGNED const *piid;
+
+ thop = *pti->pThop++;
+ thopOp = thop & THOP_OPMASK;
+
+ thkAssert(thopOp == THOP_IFACEGEN ||
+ thopOp == THOP_IFACEGENOWNER);
+
+ // The current thop byte indicates how many bytes to look
+ // back in the stack to find the IID which identifies the
+ // interface being returned
+ INDEX_STACK16(pti, vpvIid, VPVOID, *pti->pThop, sizeof(VPVOID));
+ pti->pThop++;
+
+ piid = (IID const *)GetReadPtr16(pti, vpvIid, sizeof(IID const));
+ if (piid == NULL)
+ {
+ pti->scResult = E_INVALIDARG;
+ }
+ else
+ {
+#if DBG == 1
+ if (!IsValidIid(*piid))
+ {
+ pti->scResult = E_INVALIDARG;
+ }
+ else
+#endif
+ {
+ iidx = IidToIidIdx(*piid);
+ }
+
+ WOWRELVDMPTR(vpvIid);
+ }
+
+ punkOuter = NULL;
+ if (thopOp == THOP_IFACEGENOWNER)
+ {
+ // For cases where the controlling unknown is known,
+ // index back on the stack and find the 32-bit unknown
+ // pointer to use
+ thopWeakOffset = *pti->pThop++;
+ INDEX_STACK32(pti, punkOuter, IUnknown *, thopWeakOffset);
+ }
+
+ return ThunkInterface1632(pti, iidx, thop, punkOuter);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_OIFI_1632, public
+//
+// Synopsis: Convert OLEINPLACEFRAMEINFO
+//
+// Arguments: [pti] - Thunking state information
+//
+// Returns: Appropriate status code
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_OIFI_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ VPVOID vpoifi16;
+ OIFI16 UNALIGNED *poifi16;
+ OLEINPLACEFRAMEINFO oifi32;
+ OLEINPLACEFRAMEINFO *poifi32;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_OIFI);
+ thkAssert((*pti->pThop & THOP_IOMASK) == THOP_OUT);
+
+ // OIFIs are out-only parameters for their contents
+ // However, cb is in/out, so we need to copy cb on the way in
+ // Furthermore, cb may not be set to a valid value, in which
+ // case the documentation mentions that it should be assumed
+ // that this is an OLE 2.0 OIFI
+ // This thop simply ignores cb on the way in and always sets
+ // it to the OLE 2.0 size
+ // Since we're out-only, this always works since the number of
+ // fields we thunk is the size of the structure that we give out
+ // If OLEINPLACEFRAMEINFO is extended, this thop will break
+
+ // Assert that OLEINPLACEFRAMEINFO is what we expect it to be
+ thkAssert(sizeof(OLEINPLACEFRAMEINFO) == 20);
+
+ GET_STACK16(pti, vpoifi16, VPVOID);
+
+ poifi32 = NULL;
+ if (vpoifi16 != 0)
+ {
+ poifi16 = (OIFI16 UNALIGNED *) GetWritePtr16(pti, vpoifi16, sizeof(OIFI16));
+ if (NULL != poifi16)
+ {
+ poifi32 = &oifi32;
+
+ // OIFI's may be an out only parameters but if the "cb" field is
+ // "in" RPC doesn't slice up structs, so the whole thing is "in"
+ // as well. We are Thoping here but if we want this to match
+ // the RPC sematics then we need to copy all the fields.
+
+ poifi32 = &oifi32;
+ poifi32->cb = sizeof(OLEINPLACEFRAMEINFO);
+ poifi32->fMDIApp = (BOOL)poifi16->fMDIApp;
+ poifi32->hwndFrame = HWND_32(poifi16->hwndFrame);
+ poifi32->cAccelEntries = (UINT)poifi16->cAccelEntries;
+
+ if (poifi16->haccel == NULL)
+ {
+ poifi32->haccel = NULL;
+ }
+ else
+ {
+ // WOW will clean up any dangling accelerator tables when
+ // tasks die
+ poifi32->haccel = HACCEL_32(poifi16->haccel);
+ if (poifi32->haccel == NULL)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ }
+
+ WOWRELVDMPTR(vpoifi16);
+ }
+ }
+
+ TO_STACK32(pti, poifi32, OLEINPLACEFRAMEINFO *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if (poifi32 != NULL)
+ {
+ poifi16 = FIXVDMPTR(vpoifi16, OIFI16);
+
+ if (SUCCEEDED(dwResult))
+ {
+ poifi16->cb = sizeof(OIFI16);
+ poifi16->fMDIApp = (WORD)poifi32->fMDIApp;
+ poifi16->hwndFrame = HWND_16(poifi32->hwndFrame);
+ poifi16->cAccelEntries =
+ ClampULongToUShort(poifi32->cAccelEntries);
+
+ if (poifi32->haccel == NULL)
+ {
+ poifi16->haccel = NULL;
+ }
+ else
+ {
+ // WOW will clean up any dangling accelerator tables when
+ // tasks die
+ poifi16->haccel = HACCEL_16(poifi32->haccel);
+ if (poifi16->haccel == NULL)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ }
+
+#if DBG == 1
+ if (SUCCEEDED(dwResult))
+ {
+ thkDebugOut((DEB_ARGS, "Out1632 OIFI: "
+ "%p {%d, %d, 0x%p, 0x%p, %d} -> "
+ "%p {%d, %d, 0x%04X, 0x%04X, %d}\n",
+ poifi32, poifi32->cb, poifi32->fMDIApp,
+ poifi32->hwndFrame, poifi32->haccel,
+ poifi32->cAccelEntries,
+ vpoifi16, poifi16->cb, (BOOL)poifi16->fMDIApp,
+ (DWORD)poifi16->hwndFrame, (DWORD)poifi16->haccel,
+ poifi16->cAccelEntries));
+ }
+#endif
+ }
+
+ if (FAILED(dwResult))
+ {
+ memset(poifi16, 0, sizeof(OIFI16));
+ }
+
+ RELVDMPTR(vpoifi16);
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_STGMEDIUM_1632, public
+//
+// Synopsis: Converts 32-bit STGMEDIUM to 16-bit STGMEDIUM returned
+// structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_STGMEDIUM_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+ VPVOID vpstgmedium16;
+ STGMEDIUM UNALIGNED *lpstgmedium16;
+ STGMEDIUM *lpstgmedium32;
+ STGMEDIUM stgmedium32;
+ DWORD dwSize;
+ SCODE sc;
+ BOOL fReleaseParam;
+ SHORT fTransferOwnership;
+ FORMATETC *pfe;
+ THOP thopFeOffset;
+ BOOL fReversedTYMED_NULL = FALSE;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_STGMEDIUM);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ //
+ // We currently don't have any unmodified or inout thops for STGMEDIUMs
+ //
+ thkAssert( (fThopInput || fThopOutput) &&
+ (fThopInput != fThopOutput) &&
+ "STGMEDIUM must be input or output only" );
+
+ // +2 thop byte indicates whether there's a FORMATETC to look at
+ // or not
+ // We need to reference this now before the stack is modified
+ // by argument recovery
+ thopFeOffset = *(pti->pThop+2);
+ if (thopFeOffset > 0)
+ {
+ INDEX_STACK32(pti, pfe, FORMATETC *, thopFeOffset);
+ }
+ else
+ {
+ pfe = NULL;
+ }
+
+ GET_STACK16(pti, vpstgmedium16, VPVOID);
+
+ // Next thop byte indicates whether there's an ownership transfer
+ // argument or not
+ pti->pThop++;
+ fReleaseParam = (BOOL)*pti->pThop++;
+
+ if (fReleaseParam)
+ {
+ GET_STACK16(pti, fTransferOwnership, SHORT);
+ }
+ else
+ {
+ fTransferOwnership = FALSE;
+ }
+
+ // Skip FORMATETC offset thop
+ pti->pThop++;
+
+ lpstgmedium32 = NULL;
+
+ if ( vpstgmedium16 != 0 )
+ {
+ if ( fThopInput )
+ {
+ // This code supports GetDataHere() passing TYMED_NULL. It then
+ // behaves like GetData(). This is not per the OLE spec.
+ // According to every OLE spec TYMED_NULL is an invalid type in
+ // GetDataHere(). But AlexGo says that 16bit inproc servers
+ // did support this, especially the Default Handler / Clipboard.
+
+ lpstgmedium16 = (STGMEDIUM FAR *)GetReadPtr16(pti, vpstgmedium16,
+ sizeof(STGMEDIUM));
+
+ if (lpstgmedium16->tymed == TYMED_NULL &&
+ !fTransferOwnership)
+ {
+ WOWRELVDMPTR(vpstgmedium16);
+
+ memset(&stgmedium32, 0, sizeof(stgmedium32));
+ thkAssert( TYMED_NULL == 0 ); // Don't need to set tymed to 0
+
+ fThopInput = FALSE;
+ fThopOutput = TRUE;
+ fReversedTYMED_NULL = TRUE;
+ }
+ else
+ {
+ WOWRELVDMPTR(vpstgmedium16);
+
+ sc = ConvertStgMed1632(pti, vpstgmedium16, &stgmedium32,
+ pfe, fTransferOwnership, &dwSize);
+ if (SUCCEEDED(sc))
+ {
+ lpstgmedium32 = &stgmedium32;
+ }
+ }
+ }
+
+ if ( fThopOutput )
+ {
+ thkAssert( fThopOutput );
+
+ lpstgmedium16 = (STGMEDIUM FAR *)GetWritePtr16(pti, vpstgmedium16,
+ sizeof(STGMEDIUM));
+ if ( lpstgmedium16 != NULL )
+ {
+ lpstgmedium32 = &stgmedium32;
+ WOWRELVDMPTR(vpstgmedium16);
+ }
+
+ // BUGBUG - 32->16 sets tymed to TYMED_NULL before passing
+ // on the STGMEDIUM because some apps incorrectly check for this
+ // I'm assuming this isn't necessary for 16->32 because 32-bit
+ // apps can't rely on tymed being NULL since nothing in the 32-bit
+ // code sets it that way for out parameters
+ // DrewB 5/30
+ }
+ }
+
+ TO_STACK32(pti, lpstgmedium32, STGMEDIUM FAR *);
+
+ if (fReleaseParam)
+ {
+ TO_STACK32(pti, (BOOL)fTransferOwnership, BOOL);
+ }
+
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( lpstgmedium32 != NULL)
+ {
+ if ( fThopInput )
+ {
+ if (!fTransferOwnership || FAILED(dwResult))
+ {
+ sc = CleanStgMed32(pti, lpstgmedium32, vpstgmedium16,
+ dwSize, TRUE, pfe);
+ if (FAILED(sc))
+ {
+ dwResult = (DWORD)sc;
+ }
+ }
+ else if (SUCCEEDED(dwResult))
+ {
+ lpstgmedium16 = FIXVDMPTR(vpstgmedium16, STGMEDIUM);
+ if (lpstgmedium16->pUnkForRelease == NULL)
+ {
+ RELVDMPTR(vpstgmedium16);
+ sc = CleanStgMed16(pti, vpstgmedium16, lpstgmedium32,
+ 0, FALSE, pfe);
+ thkAssert(SUCCEEDED(sc));
+ }
+ else
+ {
+ RELVDMPTR(vpstgmedium16);
+ }
+ }
+ }
+ else
+ {
+ thkAssert( fThopOutput );
+
+ if (SUCCEEDED(dwResult))
+ {
+ sc = ConvertStgMed3216(pti, lpstgmedium32, vpstgmedium16,
+ pfe, FALSE, &dwSize);
+ if (FAILED(sc))
+ {
+ dwResult = (DWORD)sc;
+ ReleaseStgMedium(lpstgmedium32);
+ }
+ else if (lpstgmedium32->pUnkForRelease == NULL)
+ {
+ sc = CleanStgMed32(pti, lpstgmedium32, vpstgmedium16,
+ dwSize, FALSE, pfe);
+ thkAssert(SUCCEEDED(sc));
+ }
+ }
+
+ // Clear the [out] parameters if the call failed.
+ // Unless it had previously been an [in] parameter.
+ // We don't want to erase the caller's [in] argument.
+
+ if (FAILED(dwResult) && !fReversedTYMED_NULL)
+ {
+ lpstgmedium16 = FIXVDMPTR(vpstgmedium16, STGMEDIUM);
+ memset(lpstgmedium16, 0, sizeof(STGMEDIUM));
+ RELVDMPTR(vpstgmedium16);
+ }
+ }
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertStatStg3216, public
+//
+// Synopsis: Converts a STATSTG
+//
+// Arguments: [pti] - Thunk info
+// [pss32] - STATSTG
+// [vpss16] - STATSTG
+// [vpstrPreAlloc] - Preallocated string memory or NULL
+// [cchPreAlloc] - Amount preallocated
+//
+// Returns: Appropriate status code
+//
+// Modifies: [vpss16]
+//
+// History: 14-May-94 DrewB Created
+//
+// Notes: Assumes input STATSTG memory is valid
+// Assumes task memory for the string
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertStatStg3216(THUNKINFO *pti,
+ STATSTG *pss32,
+ VPVOID vpss16,
+ VPSTR vpstrPreAlloc,
+ UINT cchPreAlloc)
+{
+ STATSTG UNALIGNED *pss16;
+ SCODE sc;
+ VPSTR vpstr16;
+
+ sc = ConvertTaskString3216(pti, pss32->pwcsName,
+ vpstrPreAlloc, cchPreAlloc,
+ &vpstr16);
+ if (SUCCEEDED(sc))
+ {
+ pss16 = FIXVDMPTR(vpss16, STATSTG);
+ memcpy(pss16, pss32, sizeof(STATSTG));
+ pss16->pwcsName = (LPOLESTR)vpstr16;
+ RELVDMPTR(vpss16);
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_STATSTG_1632, public
+//
+// Synopsis: Converts 32-bit STATSTG to 16-bit STATSTG returned structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_STATSTG_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ VPVOID vpstatstg16;
+ STATSTG UNALIGNED *lpstatstg16;
+ VPSTR vpstr;
+ STATSTG statstg32;
+ STATSTG *lpstatstg32;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_STATSTG);
+
+ //
+ // We currently don't have any input thops for STATSTGs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_OUT &&
+ "STATSTG must be output only" );
+
+ GET_STACK16(pti, vpstatstg16, VPVOID);
+
+ lpstatstg32 = NULL;
+
+ lpstatstg16 = (STATSTG FAR *)GetWritePtr16( pti, vpstatstg16,
+ sizeof(STATSTG) );
+ if ( lpstatstg16 != NULL )
+ {
+ statstg32.pwcsName = NULL;
+ lpstatstg32 = &statstg32;
+
+ vpstr = (VPSTR)TaskMalloc16(CBSTRINGPREALLOC);
+ if (vpstr == 0)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+
+ WOWRELVDMPTR(vpstatstg16);
+ }
+
+ TO_STACK32(pti, lpstatstg32, STATSTG FAR *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( lpstatstg32 != NULL )
+ {
+ if ( SUCCEEDED(dwResult) )
+ {
+ SCODE sc;
+
+ sc = ConvertStatStg3216(pti, &statstg32, vpstatstg16,
+ vpstr, CWCSTRINGPREALLOC);
+ if (FAILED(sc))
+ {
+ dwResult = sc;
+ }
+ }
+
+ if (FAILED(dwResult))
+ {
+ TaskFree16(vpstr);
+
+ lpstatstg16 = FIXVDMPTR(vpstatstg16, STATSTG);
+ memset(lpstatstg16, 0, sizeof(STATSTG));
+ RELVDMPTR(vpstatstg16);
+ }
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_DVTARGETDEVICE_1632, public
+//
+// Synopsis: Converts 16-bit DVTARGETDEVICE to 32-bit DVTARGETDEVICE
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_DVTARGETDEVICE_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ UINT uiSize;
+ DVTARGETDEVICE *lpdv32;
+ VPVOID vpdv16;
+ SCODE sc;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_DVTARGETDEVICE);
+
+ //
+ // We currently don't have any output thops for DVTARGETDEVICEs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_IN &&
+ "DVTARGETDEVICE must be input only" );
+
+ //
+ // Processing for a DVTARGETDEVICE FAR * as input
+ //
+ GET_STACK16(pti, vpdv16, VPVOID);
+
+ lpdv32 = NULL;
+
+ if ( vpdv16 != 0 )
+ {
+ sc = ConvertDvtd1632(pti, vpdv16, ArStack32, FrStack32, &lpdv32,
+ &uiSize);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ }
+ }
+
+ TO_STACK32(pti, lpdv32, DVTARGETDEVICE FAR *);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if (lpdv32 != NULL)
+ {
+ FrStack32(lpdv32, uiSize);
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_FORMATETC_1632, public
+//
+// Synopsis: Converts 16-bit FORMATETC to 32-bit FORMATETC and back
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_FORMATETC_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+ VPVOID vpformatetc16;
+ FORMATETC16 UNALIGNED *lpformatetc16;
+ LPFORMATETC lpformatetc32;
+ FORMATETC formatetc32;
+ DVTARGETDEVICE *lpdv32;
+ SCODE sc;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_FORMATETC);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ //
+ // We have only input and output thops, not both, or neither
+ //
+ thkAssert( (fThopInput || fThopOutput) &&
+ (fThopInput != fThopOutput) &&
+ "formatetc must be input or output only" );
+
+ lpdv32 = NULL;
+
+ GET_STACK16(pti, vpformatetc16, VPVOID);
+
+ if ( vpformatetc16 == 0 )
+ {
+ lpformatetc32 = NULL;
+ }
+ else
+ {
+ lpformatetc32 = &formatetc32;
+
+ if ( fThopInput )
+ {
+ sc = ConvertFetc1632(pti, vpformatetc16, lpformatetc32, FALSE);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ }
+ }
+ else
+ {
+ thkAssert( fThopOutput );
+ //
+ // The below memset is needed at least for the DATA_S_SAMEFORMATETC
+ // case. This allows it to be cleaned up because all its pointers
+ // will be null.
+ //
+ memset( &formatetc32, 0, sizeof(formatetc32) );
+ lpformatetc16 = (LPFORMATETC16)GetWritePtr16(pti, vpformatetc16,
+ sizeof(FORMATETC16));
+ WOWRELVDMPTR(vpformatetc16);
+ }
+ }
+
+ TO_STACK32(pti, lpformatetc32, LPFORMATETC);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( fThopInput )
+ {
+ if (lpformatetc32 != NULL && lpformatetc32->ptd != NULL)
+ {
+ TaskFree32(lpformatetc32->ptd);
+ }
+ }
+
+ if ( fThopOutput && vpformatetc16 != NULL)
+ {
+ if (SUCCEEDED(dwResult))
+ {
+ sc = ConvertFetc3216(pti, lpformatetc32, vpformatetc16, TRUE);
+ if (FAILED(sc))
+ {
+ dwResult = sc;
+ }
+ }
+
+ if (FAILED(dwResult))
+ {
+ lpformatetc16 = FIXVDMPTR(vpformatetc16, FORMATETC16);
+ memset(lpformatetc16, 0, sizeof(FORMATETC16));
+ RELVDMPTR(vpformatetc16);
+ }
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_LOGPALETTE_1632, public
+//
+// Synopsis: Converts 16-bit LOGPALLETE to 32-bit LOGPALETTE
+// and converts 32-bit LOGPALETTE returned to 16-bit structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_LOGPALETTE_1632 ( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ UINT uiSize;
+ LPLOGPALETTE lplogpal32;
+ VPVOID vplogpal16;
+ LOGPALETTE UNALIGNED *lplogpal16;
+ VPVOID vp16;
+ LPVOID UNALIGNED *lp16;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LOGPALETTE);
+
+ //
+ // It must be either an input or output LOGPALETTE
+ //
+ thkAssert( ((*pti->pThop & THOP_IOMASK) == THOP_IN ||
+ (*pti->pThop & THOP_IOMASK) == THOP_OUT) &&
+ "Hey, LOGPALETTE can't be input and output!" );
+
+ lplogpal32 = NULL;
+
+ if ( (*pti->pThop & THOP_IN) != 0 )
+ {
+ //
+ // Processing for a LPLOGPALETTE as input
+ //
+ GET_STACK16(pti, vplogpal16, VPVOID);
+
+ if ( vplogpal16 != 0 )
+ {
+ // Copy over the input LOGPALETTE structure
+ lplogpal16 = (LPLOGPALETTE)GetReadPtr16( pti, vplogpal16,
+ sizeof(LOGPALETTE) );
+
+ if ( lplogpal16 != NULL )
+ {
+ uiSize = CBPALETTE(lplogpal16->palNumEntries);
+
+ WOWRELVDMPTR(vplogpal16);
+
+ lplogpal16 = (LPLOGPALETTE)GetReadPtr16(pti, vplogpal16,
+ uiSize);
+ if ( lplogpal16 != NULL )
+ {
+ lplogpal32 = (LPLOGPALETTE)CoTaskMemAlloc(uiSize);
+ if ( lplogpal32 == NULL )
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ else
+ {
+ memcpy( lplogpal32, lplogpal16, uiSize );
+ }
+
+ WOWRELVDMPTR(vplogpal16);
+ }
+ }
+ }
+
+ TO_STACK32(pti, lplogpal32, LPLOGPALETTE);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( lplogpal32 )
+ {
+ CoTaskMemFree( lplogpal32 );
+ }
+ }
+ else
+ {
+ //
+ // Processing for LPLPLOGPALETTE as output
+ //
+
+ thkAssert((*pti->pThop & THOP_OUT) != 0);
+
+ GET_STACK16(pti, vp16, VPVOID);
+
+ vplogpal16 = (VPVOID)TaskMalloc16(CBPALETTE(NPALETTEPREALLOC));
+ if (vplogpal16 == 0)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+
+ TO_STACK32(pti, &lplogpal32, LPLOGPALETTE *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( SUCCEEDED(dwResult) && lplogpal32 != NULL )
+ {
+ //
+ // Copy the returned LOGPALETTE into 16-bit memory
+ //
+ uiSize = CBPALETTE(lplogpal32->palNumEntries);
+ if (uiSize > CBPALETTE(NPALETTEPREALLOC))
+ {
+ TaskFree16(vplogpal16);
+ vplogpal16 = (VPVOID)TaskMalloc16(uiSize);
+ if ( vplogpal16 == 0 )
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ }
+
+ if (vplogpal16 != 0)
+ {
+ lplogpal16 = (LPLOGPALETTE)WOWFIXVDMPTR(vplogpal16, uiSize);
+ if ( lplogpal16 == NULL )
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ vplogpal16 = 0;
+ }
+ else
+ {
+ memcpy( lplogpal16, lplogpal32, uiSize );
+
+ WOWRELVDMPTR(vplogpal16);
+ }
+ }
+
+ TaskFree32( lplogpal32 );
+ }
+ else
+ {
+ TaskFree16(vplogpal16);
+ vplogpal16 = 0;
+ }
+
+ //
+ // Update the value pointed to by the parameter on the 16-bit stack
+ //
+ lp16 = FIXVDMPTR(vp16, LPVOID);
+ if ( lp16 == NULL )
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ else
+ {
+ *lp16 = (LPVOID)vplogpal16;
+ RELVDMPTR(vp16);
+ }
+ }
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_CRGIID_1632, public
+//
+// Synopsis: Converts 16-bit CRGIID to 32-bit CRGIID structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_CRGIID_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ DWORD dwCount;
+ VPVOID vpiid16;
+ IID UNALIGNED *lpiid16;
+ IID *lpiid32;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CRGIID);
+
+ //
+ // We currently don't have any output thops for CRGIIDs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == 0 &&
+ "CRGIID must be unmodified only" );
+
+ GET_STACK16(pti, dwCount, DWORD);
+ GET_STACK16(pti, vpiid16, VPVOID);
+
+ lpiid32 = NULL;
+
+ if ( vpiid16 != 0 )
+ {
+ lpiid16 = (IID UNALIGNED *)GetReadPtr16( pti, vpiid16,
+ dwCount*sizeof(IID) );
+ if ( lpiid16 != NULL )
+ {
+ lpiid32 = (IID FAR *)CoTaskMemAlloc( dwCount * sizeof(IID) );
+ if ( lpiid32 == NULL )
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ else
+ {
+ memcpy( lpiid32, lpiid16, dwCount*sizeof(IID) );
+ }
+
+ WOWRELVDMPTR(vpiid16);
+ }
+ }
+
+ TO_STACK32(pti, dwCount, DWORD);
+ TO_STACK32(pti, lpiid32, IID FAR *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( lpiid32 != NULL )
+ {
+ CoTaskMemFree( lpiid32 );
+ }
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_INTERFACEINFO_1632, public
+//
+// Synopsis: Converts an INTERFACEINFO
+//
+// Arguments: [pti] - Thunking state information
+//
+// Returns: Appropriate status code
+//
+// History: 19-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_INTERFACEINFO_1632(THUNKINFO *pti)
+{
+ INTERFACEINFO *pii32;
+ INTERFACEINFO ii32;
+ INTERFACEINFO16 UNALIGNED *pii16;
+ VPVOID vpii16;
+ DWORD dwResult;
+ IUnknown *punk32;
+ VPVOID vpvUnk16;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_INTERFACEINFO);
+ thkAssert((*pti->pThop & THOP_INOUT) == THOP_IN);
+
+ pii32 = NULL;
+ punk32 = NULL;
+
+ GET_STACK16(pti, vpii16, VPVOID);
+ if (vpii16 != 0)
+ {
+ pii16 = (INTERFACEINFO16 UNALIGNED *)
+ GetReadPtr16(pti, vpii16, sizeof(INTERFACEINFO16));
+ if (pii16 != NULL)
+ {
+ if (pii16->pUnk != NULL)
+ {
+ vpvUnk16 = pii16->pUnk;
+
+ WOWRELVDMPTR(vpii16);
+
+ punk32 =
+ pti->pThkMgr->FindProxy3216(NULL, vpvUnk16,
+ INDEX_IIDIDX(THI_IUnknown),
+ NULL);
+ if (punk32 == NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+
+ pii16 = FIXVDMPTR(vpii16, INTERFACEINFO16);
+ }
+
+ pii32 = &ii32;
+ pii32->pUnk = punk32;
+ pii32->iid = pii16->iid;
+ pii32->wMethod = pii16->wMethod;
+
+ WOWRELVDMPTR(vpii16);
+
+ thkDebugOut((DEB_ARGS,
+ "In1632 INTERFACEINFO: %p -> %p {%p (%p), %s, %u}\n",
+ vpii16, pii32, pii32->pUnk, pii16->pUnk,
+ IidOrInterfaceString(&pii32->iid), pii32->wMethod));
+ }
+ }
+
+ TO_STACK32(pti, pii32, INTERFACEINFO *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if (punk32 != NULL)
+ {
+ pii16 = FIXVDMPTR(vpii16, INTERFACEINFO16);
+ vpvUnk16 = pii16->pUnk;
+ RELVDMPTR(vpii16);
+ pti->pThkMgr->FreeProxy3216(vpvUnk16);
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_RETURNTYPE_1632, public
+//
+// Synopsis: Thunks the return value of a call
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-94 DrewB Created
+//
+// Notes: This thunk assumes that the return value will always fit
+// in 32 bits and that the thops for it are only one thop
+// long. This fits the existing APIs and methods
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_RETURNTYPE_1632(THUNKINFO *pti)
+{
+ THOP thops[2];
+ DWORD dwResult;
+ ALIAS alias;
+ VPVOID vpPreAlloc = NULL;
+ IIDIDX iidx;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RETURNTYPE);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ pti->fResultThunked = TRUE;
+
+ pti->pThop++;
+
+ // Remember return type thop
+ thops[0] = *pti->pThop++;
+ if ((thops[0] & THOP_OPMASK) == THOP_COPY ||
+ (thops[0] & THOP_OPMASK) == THOP_IFACE ||
+ (thops[0] & THOP_OPMASK) == THOP_ALIAS32)
+ {
+ thops[1] = *pti->pThop++;
+ }
+
+ // Preallocate any necessary resources
+ switch(thops[0])
+ {
+ case THOP_IFACE | THOP_IN:
+ iidx = INDEX_IIDIDX(thops[1]);
+ if ((vpPreAlloc =
+ pti->pThkMgr->CanGetNewProxy1632(iidx)) == NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ break;
+
+ case THOP_ALIAS32:
+ thkAssert(thops[1] == ALIAS_CREATE);
+
+ // The value used for preallocation doesn't really matter
+ // as long as it's unique and not INVALID_VALUE
+ // In our case we know that we won't have to deal with nested
+ // preallocations so uniqueness is not as much of an issue
+ // By using INVALID_HANDLE_VALUE, we can be sure that there
+ // won't already be an entry with that value already in the
+ // alias table since we're aliasing handles
+ alias = gAliases32.AddValue((DWORD)INVALID_HANDLE_VALUE);
+ if (alias == INVALID_ALIAS)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ }
+ break;
+ }
+
+ dwResult = EXECUTE_THOP1632(pti);
+
+ // Now that we have the return value thunk it from 32->16
+ // We must use pti->scResult to check for failure rather than
+ // dwResult because dwResult may not be an SCODE
+
+ switch(thops[0])
+ {
+ case THOP_COPY:
+ // Only handle DWORD copies
+ thkAssert(thops[1] == sizeof(DWORD));
+ break;
+
+ case THOP_SHORTLONG:
+ // For boolean results, not necessary to clamp
+ dwResult = (DWORD)(SHORT)*(LONG *)&dwResult;
+ break;
+
+ case THOP_IFACE | THOP_IN:
+ if (dwResult != 0)
+ {
+ if (FAILED(pti->scResult))
+ {
+ dwResult = 0;
+ }
+ else
+ {
+ dwResult =
+ (DWORD)pti->pThkMgr->FindProxy1632(vpPreAlloc,
+ (IUnknown *)dwResult,
+ iidx, NULL);
+ thkAssert(dwResult != 0);
+
+ thkDebugOut((DEB_ARGS, "Ret1632 %s %p\n",
+ inInterfaceNames[thops[1]].pszInterface,
+ dwResult));
+ }
+ }
+ else
+ {
+ pti->pThkMgr->FreeNewProxy1632(vpPreAlloc, iidx);
+ }
+ break;
+
+ case THOP_ALIAS32:
+ if (dwResult != 0)
+ {
+ if (FAILED(pti->scResult))
+ {
+ dwResult = 0;
+ }
+ else
+ {
+ gAliases32.SetValue(alias, dwResult);
+
+ thkDebugOut((DEB_ARGS, "Ret1632 ALIAS32: 0x%08lX -> 0x%04lX\n",
+ dwResult, alias));
+
+ dwResult = (DWORD)alias;
+ }
+ }
+ break;
+
+ default:
+ thkAssert(!"Unhandled 1632 return type");
+ break;
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_IFACE_1632, public
+//
+// Synopsis: Thunks a known interface pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_IFACE_1632(THUNKINFO *pti)
+{
+ IIDIDX iidx;
+ THOP thop, thopOp, thopWeakOffset;
+ IUnknown *punkOuter;
+
+ thop = *pti->pThop++;
+ thopOp = thop & THOP_OPMASK;
+
+ thkAssert( thopOp == THOP_IFACE
+ || thopOp == THOP_IFACEOWNER
+ || thopOp == THOP_IFACENOADDREF);
+
+ iidx = INDEX_IIDIDX(*pti->pThop++);
+
+ // There's a bit of a special case here in that IMalloc is
+ // not thunked so it doesn't have a real index but it's used
+ // in thop strings so it has a fake index to function as a placeholder
+ // The fake index is THI_COUNT so allow that in the assert
+ thkAssert(IIDIDX_INDEX(iidx) >= 0 && IIDIDX_INDEX(iidx) <= THI_COUNT);
+
+ punkOuter = NULL;
+ if ( thopOp == THOP_IFACEOWNER
+ || thopOp == THOP_IFACENOADDREF)
+ {
+ thopWeakOffset = *pti->pThop++;
+ INDEX_STACK32(pti, punkOuter, IUnknown *, thopWeakOffset);
+ }
+
+ return ThunkInterface1632(pti, iidx, thop, punkOuter);
+}
+
+typedef struct tagOLESTREAMOBJECT
+{
+ OLESTREAM os;
+ VPVOID vpolestream16;
+} OLESTREAMOBJECT, FAR * LPOLESTREAMOBJECT;
+
+#define OLESTREAM_GET 0
+#define OLESTREAM_PUT 1
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OLESTREAM_Callback, private
+//
+// Synopsis: Handles callbacks into 16-bit world for OLESTREAM methods
+//
+// Arguments: [dwMethod] - Index of method to invoke
+// [lposo] - Pointer to 32 LPOLESTREAM
+// [lpv] - Pointer to 32 bit buffer
+// [dwCount] - Size of 32 bit buffer
+//
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 BobDay Created
+// 29-May-94 TerryRu Converted to call WOWCallBackEx directly.
+//
+//----------------------------------------------------------------------------
+
+DWORD OLESTREAM_Callback( DWORD dwMethod,
+ LPOLESTREAM lpos,
+ LPVOID lpv,
+ DWORD dwCount )
+{
+ const DWORD cbStack = sizeof( DWORD ) +
+ sizeof( VPVOID ) + sizeof( VPVOID );
+
+ BYTE b32Args[cbStack];
+ DWORD dwResult;
+
+ VPVOID vpvVtbl16;
+ VTBLFN vpfn16;
+
+ VPVOID vpolestream16;
+ LPOLESTREAMOBJECT lposo;
+
+ VPVOID vp16;
+ LPVOID lp16;
+
+
+ lposo = (LPOLESTREAMOBJECT)lpos;
+ vpolestream16 = lposo->vpolestream16;
+
+ // Get pointer to 16 bit this pointer
+
+ vpvVtbl16 = (VPVOID)*FIXVDMPTR( vpolestream16, VPVOID );
+ RELVDMPTR(vpolestream16);
+ vpfn16 = (VTBLFN)*FIXVDMPTR( vpvVtbl16+dwMethod*sizeof(VPVOID),
+ VPVOID );
+ RELVDMPTR(vpvVtbl16+dwMethod*sizeof(VPVOID));
+
+ //
+ // now thop the IN 32 bit-block of memory to 16 bit block
+ //
+
+ vp16 = WgtAllocLock( GMEM_MOVEABLE, dwCount, NULL );
+ if ( vp16 == NULL )
+ {
+ return (DWORD) E_OUTOFMEMORY;
+ }
+
+ if ( dwMethod == OLESTREAM_PUT )
+ {
+ lp16 = WOWFIXVDMPTR( vp16, dwCount );
+ memcpy( lp16, lpv, dwCount );
+ WOWRELVDMPTR(vp16);
+ }
+
+ // setup 32 bit arguements.
+ *(DWORD *)(b32Args) = dwCount;
+ *(VPVOID *)(b32Args+4) = vp16;
+ *(VPVOID *)(b32Args+8) = vpolestream16;
+
+ if ( !CallbackTo16Ex( (DWORD)vpfn16, WCB16_PASCAL, cbStack, b32Args,
+ &dwResult) )
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+
+ if ( dwMethod == OLESTREAM_GET )
+ {
+
+ lp16 = WOWFIXVDMPTR( vp16, dwCount );
+ memcpy( (LPVOID) lpv, lp16, dwCount );
+ WOWRELVDMPTR(vp16);
+
+ }
+
+ WgtUnlockFree(vp16);
+
+ thkDebugOut((DEB_INVOKES, "OLESTREAM_Callback returns 0x%08lX\n",
+ dwResult));
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OLESTREAM_Get_Proxy, private
+//
+// Synopsis: Handles callbacks into 16-bit world for OLESTREAM::Get
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 BobDay Created
+// 29-May-94 TerryRu Now calls OLESTREAM::Get using Pascal
+// calling conventions.
+//
+//----------------------------------------------------------------------------
+
+DWORD OLESTREAM_Get_Proxy(
+ LPOLESTREAM lpos,
+ void FAR * lpv,
+ DWORD dwCount
+)
+{
+ return OLESTREAM_Callback( OLESTREAM_GET, lpos, lpv, dwCount );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OLESTREAM_Put_Proxy, private
+//
+// Synopsis: Handles callbacks into 16-bit world for OLESTREAM::Put
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 11-Mar-94 BobDay Created
+// 29-May-94 TerryRu Now call OLESTREAM::Put using pascal
+// calling conventions.
+//
+//----------------------------------------------------------------------------
+
+DWORD OLESTREAM_Put_Proxy(
+ LPOLESTREAM lpos,
+ const void FAR* lpv,
+ DWORD dwCount
+)
+{
+ return OLESTREAM_Callback( OLESTREAM_PUT, lpos,(LPVOID) lpv, dwCount );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_OLESTREAM_1632, public
+//
+// Synopsis: Thunks an OLESTREAM parameter from 16-bit to 32-bit
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 14-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+_OLESTREAMVTBL osVtbl =
+{
+ OLESTREAM_Get_Proxy,
+ OLESTREAM_Put_Proxy
+};
+
+DWORD Thop_OLESTREAM_1632(THUNKINFO *pti)
+{
+ OLESTREAMOBJECT osObject;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_OLESTREAM);
+
+ //
+ // Ignore the THOP_INPUT/THOP_OUTPUT, it is always just an interface
+ //
+
+ osObject.os.lpstbl = &osVtbl;
+ GET_STACK16(pti, osObject.vpolestream16, VPVOID);
+
+ TO_STACK32(pti, &osObject, LPOLESTREAMOBJECT );
+
+ pti->pThop++;
+ return EXECUTE_THOP1632(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_RPCOLEMESSAGE_1632, public
+//
+// Synopsis: Converts 16-bit RPCOLEMESSAGE to 32-bit RPCOLEMESSAGE
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+// 28-May-94 JohannP Rewritten
+// 13-Aug-94 Rickhi made it work for GetBuffer when the
+// buffer size grows, commented better
+//
+// CODEWORK: this routine is inefficient. since it cant tell why it was
+// called (GetBuffer/SendReceive/Invoke/FreeBuffer) it always
+// copies the data, when it only really needs to in Invoke and
+// in SendReceive.
+//
+// Context: This routine will "Thop" a client side RPCOLEMESSGE (aka "rom")
+// three times. The first time for the "getbuffer" call, the second
+// time for the "SendRecieve", and the third time for the "freebuffer".
+// This make it confusing, some calls allocate a buffer but don't
+// free it. Other calls free a buffer they didn't allocate. A good
+// way to see what is happening is to step through several calls to
+// this routine with a debugger and note the pointer values.
+//
+//----------------------------------------------------------------------------
+DWORD Thop_RPCOLEMESSAGE_1632( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ PRPCOLEMESSAGE prom32;
+ VPVOID vprom16;
+ RPCOLEMESSAGE UNALIGNED *prom16;
+ LPVOID lp16;
+ RPCOLEMESSAGE rom32;
+ BOOL fAllocNew = FALSE;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RPCOLEMESSAGE);
+
+ //
+ // We currently have only INOUT RPCOLEMESSAGE
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == (THOP_IN | THOP_OUT) &&
+ "RPCOLEMESSAGE must be input/output only" );
+
+ //
+ // Processing for a RPCOLEMESSAGE FAR * as input/output
+ //
+ GET_STACK16(pti, vprom16, VPVOID);
+
+ prom32 = NULL;
+ if ( vprom16 != 0 )
+ {
+ // Copy over the input RPCOLEMESSAGE structure
+ prom16 = (RPCOLEMESSAGE UNALIGNED *)
+ GetReadWritePtr16( pti, vprom16, sizeof(RPCOLEMESSAGE) );
+ if ( prom16 != NULL )
+ {
+ // Note: ROM_THUNK_FIELD(prom) holds the pointer to the 32 bit rom
+ // in case the buffer is not NULL
+
+ // Note: this assert is not valid when a fault happens on the
+ // server side. In that case, the return buffer is NULLed
+ // by the 16bit stub but the THUNK_FIELD is non-null.
+
+ //thkAssert((prom16->Buffer == NULL &&
+ // ROM_THUNK_FIELD(prom16) == NULL) ||
+ // (prom16->Buffer != NULL &&
+ // ROM_THUNK_FIELD(prom16) != NULL));
+
+ if (prom16->Buffer != NULL)
+ {
+ prom32 = (RPCOLEMESSAGE *)ROM_THUNK_FIELD(prom16);
+
+ if ( prom32->Buffer != NULL )
+ {
+ // we use the min size of the two buffers because when
+ // the stub (server side) calls GetBuffer he is supplying
+ // the old pBuffer with the new (and potentially larger)
+ // cbBuffer
+
+ DWORD cbSizeMin = (prom16->cbBuffer <= prom32->cbBuffer) ?
+ prom16->cbBuffer : prom32->cbBuffer;
+
+ lp16 = (LPVOID)GetReadPtr16(pti,
+ (VPVOID)prom16->Buffer,
+ cbSizeMin);
+ if (lp16 == NULL)
+ {
+ prom32 = NULL;
+ }
+ else
+ {
+ memcpy( prom32->Buffer, lp16, prom32->cbBuffer );
+ WOWRELVDMPTR((VPVOID)prom16->Buffer);
+ }
+ }
+
+ // the stub might be asking for a larger buffer for output
+ // parameters than it was given for input parameters. We have
+ // to figure that out here by comparing the 16bit size with
+ // the 32bit size.
+
+ fAllocNew = (prom32->cbBuffer < prom16->cbBuffer);
+ prom32->cbBuffer = prom16->cbBuffer;
+ }
+ else
+ {
+ rom32 = *prom16;
+ prom32 = &rom32;
+ }
+
+ WOWRELVDMPTR(vprom16);
+ }
+ }
+
+ TO_STACK32(pti, prom32, PRPCOLEMESSAGE);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+
+ if ( prom32 != NULL )
+ {
+ prom16 = (RPCOLEMESSAGE UNALIGNED *)
+ GetReadWritePtr16( pti, vprom16, sizeof(RPCOLEMESSAGE) );
+ if ( prom16 == NULL )
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ else
+ {
+ if (SUCCEEDED(dwResult))
+ {
+ if (prom32->Buffer == NULL)
+ {
+ // RELEASE THE BUFFER AND ROM:
+ // Free the 16 bit buffer, copy the 32 bit rom into
+ // the 16 bit rom and free the 32bit rom, if it was
+ // allocated
+ //
+ if (prom16->Buffer != 0)
+ {
+ TaskFree16((VPVOID)prom16->Buffer);
+ }
+
+ *prom16 = *prom32;
+
+ if (prom32 != &rom32)
+ {
+ TaskFree32(prom32);
+ prom32 = NULL;
+ }
+ ROM_THUNK_FIELD(prom16) = NULL;
+ }
+ else
+ {
+ // ALLOCATE AND/OR COPYBACK THE BUFFER AND ROM:
+ RPCOLEMESSAGE *pr32;
+ LPVOID pBuffer;
+
+ // Create a message to save the 32-bit message in
+ // Use the existing one in the thunk field if we can
+ if (ROM_THUNK_FIELD(prom16) == NULL)
+ {
+ pr32 = (RPCOLEMESSAGE *)
+ TaskMalloc32(sizeof(RPCOLEMESSAGE));
+ }
+ else
+ {
+ pr32 = (RPCOLEMESSAGE *)ROM_THUNK_FIELD(prom16);
+ }
+ *pr32 = *prom32;
+
+ //
+ // Allocate an output buffer and copy the buffer back
+ //
+ if ( (prom16->Buffer == NULL)
+ || (prom16->cbBuffer < prom32->cbBuffer)
+ || fAllocNew)
+ {
+ if (prom16->Buffer != NULL)
+ {
+ TaskFree16((VPVOID) prom16->Buffer);
+ }
+
+ pBuffer = (LPVOID)TaskMalloc16(prom32->cbBuffer );
+ }
+ else
+ {
+ pBuffer = prom16->Buffer;
+ }
+
+ *prom16 = *prom32;
+ prom16->Buffer = pBuffer;
+ ROM_THUNK_FIELD(prom16) = pr32;
+
+ if (prom16->Buffer == NULL)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ else
+ {
+ lp16 = (LPVOID)GetReadPtr16(pti,
+ (VPVOID)prom16->Buffer,
+ prom16->cbBuffer);
+ if ( lp16 == NULL )
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ else
+ {
+ memcpy( lp16, prom32->Buffer,
+ prom32->cbBuffer );
+ WOWRELVDMPTR((VPVOID)prom16->Buffer);
+ }
+ }
+ }
+ }
+
+ WOWRELVDMPTR(vprom16);
+ }
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_ALIAS32_1632, public
+//
+// Synopsis: Handles 16-bit aliases to 32-bit quantities
+//
+// Arguments: [pti] - Thunking state information
+//
+// Returns: Appropriate status code
+//
+// History: 27-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_ALIAS32_1632(THUNKINFO *pti)
+{
+ ALIAS alias;
+ DWORD dwValue;
+ THOP thopAction;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ALIAS32);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ pti->pThop++;
+
+ GET_STACK16(pti, alias, ALIAS);
+
+ // Second byte indicates how the alias should be handled
+ thopAction = *pti->pThop++;
+
+ if (alias != 0)
+ {
+ switch(thopAction)
+ {
+ case ALIAS_RESOLVE:
+ dwValue = gAliases32.AliasValue(alias);
+ break;
+
+ case ALIAS_REMOVE:
+ dwValue = gAliases32.AliasValue(alias);
+ gAliases32.RemoveAlias(alias);
+ break;
+
+ default:
+ thkAssert(!"Default hit in Thop_ALIAS32_1632");
+ break;
+ }
+ }
+ else
+ {
+ dwValue = 0;
+ }
+
+ thkDebugOut((DEB_ARGS, "In1632 ALIAS32: 0x%04X -> 0x%08lX\n",
+ alias, dwValue));
+
+ TO_STACK32(pti, dwValue, DWORD);
+
+ return EXECUTE_THOP1632(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_ENUM_1632, public
+//
+// Synopsis: Thunks Enum::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is the start of a 2-byte thop. The next thop
+// byte references a function in the enumerator table, rather
+// than the standard thop table.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_ENUM_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ENUM);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ //
+ // Get then next thop byte and execute it as a Enum thop
+ //
+ pti->pThop++;
+ return EXECUTE_ENUMTHOP1632(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CallbackProcessing_1632, public
+//
+// Synopsis: Thunks IOleObject::Draw pfnContinue & DWORD parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 3-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+typedef struct tagCallbackControl
+{
+ DWORD dwContinue;
+ VPVOID vpfn16;
+} CALLBACKCONTROL;
+
+BOOL CallbackProcessing_1632( DWORD dwContinue )
+{
+ DWORD dwResult;
+ CALLBACKCONTROL *lpcbc;
+
+ lpcbc = (CALLBACKCONTROL *)dwContinue;
+
+ // The callback function must be FAR PASCAL
+ // It's declared CALLBACK in the methods so this is ensured
+ dwResult = CallbackTo16( lpcbc->vpfn16, lpcbc->dwContinue );
+
+ return (BOOL)((WORD)dwResult); // Ignore HIWORD
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_CALLBACK_1632, public
+//
+// Synopsis: Thunks IOleObject::Draw pfnContinue & DWORD parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 3-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_CALLBACK_1632(THUNKINFO *pti)
+{
+ VPVOID vpfn16;
+ DWORD dwContinue;
+ CALLBACKCONTROL cbc;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CALLBACK);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ GET_STACK16(pti, vpfn16, VPVOID);
+ GET_STACK16(pti, dwContinue, DWORD);
+
+ if ( vpfn16 == 0 )
+ {
+ TO_STACK32(pti, NULL, LPVOID);
+ TO_STACK32(pti, dwContinue, DWORD);
+ }
+ else
+ {
+ cbc.vpfn16 = vpfn16;
+ cbc.dwContinue = dwContinue;
+
+ TO_STACK32(pti, CallbackProcessing_1632, LPVOID);
+ TO_STACK32(pti, (DWORD)&cbc, DWORD);
+ }
+
+ pti->pThop++;
+ return EXECUTE_THOP1632(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_CLSCONTEXT_1632, public
+//
+// Synopsis: Converts a class context flags DWORD
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 29-Jun-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_CLSCONTEXT_1632(THUNKINFO *pti)
+{
+ DWORD dwClsContext;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CLSCONTEXT);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ GET_STACK16(pti, dwClsContext, DWORD);
+
+ // When passing a 16-bit class context on to 32-bits,
+ // add on a flag to indicate that this is a 16-bit request
+ // in the inproc server case
+
+ if (dwClsContext & CLSCTX_INPROC_SERVER)
+ {
+ dwClsContext |= CLSCTX_INPROC_SERVER16;
+ }
+
+ TO_STACK32(pti, dwClsContext, DWORD);
+
+ pti->pThop++;
+ return EXECUTE_THOP1632(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_FILENAME_1632, public
+//
+// Synopsis: Converts a filename string
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_FILENAME_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_FILENAME);
+
+ // Can be in or out only
+ thkAssert((*pti->pThop & THOP_IOMASK) == THOP_IN ||
+ (*pti->pThop & THOP_IOMASK) == THOP_OUT);
+
+ if ((*pti->pThop & THOP_IN) != 0)
+ {
+ // No special processing is necessary for filenames going
+ // from 16->32 since it isn't possible for 16-bit code to
+ // generate a filename which can't be handled in 32-bits
+
+ return ThunkInString1632(pti);
+ }
+ else
+ {
+ thkAssert((*pti->pThop & THOP_OUT) != 0);
+
+ // Convert filenames going from 32->16 to short filenames
+ // to avoid any possible problems with non-8.3 names.
+
+ return ThunkOutString1632(pti, TRUE);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_SIZEDSTRING_1632, public
+//
+// Synopsis: Converts strings which cannot exceed a given length
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 02-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_SIZEDSTRING_1632(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SIZEDSTRING);
+ thkAssert((*pti->pThop & THOP_IOMASK) == THOP_IN);
+
+ // For 16->32, there are no limits on string length so
+ // thunk the string normally
+
+ // Advance once to account for the length byte
+ // ThunkInString will advance again
+
+ pti->pThop++;
+ return ThunkInString1632(pti);
+}
+
+#define THOP_FN(x) Thop_ ## x ## _1632
+
+DWORD (*CONST aThopFunctions1632[])(THUNKINFO *) =
+{
+
+ // x = Implemented
+ // ? = Mysteriously not needed
+ // = Left to do
+ //
+ // ^
+ // |
+ // +===+
+ // |
+ // v
+ //
+ ThunkCall1632, // x Terminating THOP
+ Thop_ShortToLong_1632, // x SHORTLONG
+ Thop_WordToDword_1632, // x WORDDWORD
+ Thop_Copy_1632, // x COPY
+ THOP_FN(LPSTR), // x LPSTR
+ THOP_FN(LPLPSTR), // x LPLPSTR
+ THOP_FN(BUFFER), // x BUFFER
+ Thop_UserHandle_1632, // x HUSER
+ Thop_GdiHandle_1632, // x HGDI
+ THOP_FN(SIZE), // x SIZE
+ THOP_FN(RECT), // x RECT
+ THOP_FN(MSG), // x MSG
+ THOP_FN(HRESULT), // x HRESULT
+ THOP_FN(STATSTG), // x STATSTG
+ THOP_FN(DVTARGETDEVICE), // x DVTARGETDEVICE
+ THOP_FN(STGMEDIUM), // x STGMEDIUM
+ THOP_FN(FORMATETC), // x FORMATETC
+ THOP_FN(HACCEL), // x HACCEL
+ THOP_FN(OIFI), // x OLEINPLACEFRAMEINFO
+ THOP_FN(BINDOPTS), // x BIND_OPTS
+ THOP_FN(LOGPALETTE), // x LOGPALETTE
+ THOP_FN(SNB), // x SNB
+ THOP_FN(CRGIID), // x CRGIID
+ THOP_FN(OLESTREAM), // x OLESTREAM
+ THOP_FN(HTASK), // x HTASK
+ THOP_FN(INTERFACEINFO), // x INTERFACEINFO
+ THOP_FN(IFACE), // x IFACE
+ THOP_FN(IFACE), // x IFACEOWNER
+ THOP_FN(IFACE), // x IFACENOADDREF
+ Thop_ERROR_1632, // x IFACECLEAN
+ THOP_FN(IFACEGEN), // x IFACEGEN
+ THOP_FN(IFACEGEN), // x IFACEGENOWNER
+ Thop_ERROR_1632, // x ROUTINE_INDEX
+ THOP_FN(RETURNTYPE), // x RETURN_TYPE
+ THOP_FN(NULL), // x NULL
+ Thop_ERROR_1632, // x ERROR
+ THOP_FN(ENUM), // x ENUM
+ THOP_FN(CALLBACK), // x CALLBACK
+ THOP_FN(RPCOLEMESSAGE), // x RPCOLEMESSAGE
+ THOP_FN(ALIAS32), // x ALIAS32
+ THOP_FN(CLSCONTEXT), // x CLSCONTEXT
+ THOP_FN(FILENAME), // x FILENAME
+ THOP_FN(SIZEDSTRING), // x SIZEDSTRING
+};
+
+//+---------------------------------------------------------------------------
+//
+// Function: General_Enum_1632, private
+//
+// Synopsis: Thunking for standard OLE enumerator interface ::Next member
+// function.
+//
+// Arguments: [pti] - Thunk state information
+// [uiSize32] - 32-bit information size
+// [uiSize16] - 16-bit information size
+// [pfnCallback] - Data thunking callback
+// [pfnCleanup] - Thunking cleanup
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This handler is called from many IXXXEnum::Next handlers thop
+// thunks to do the standard sorts of "buffer of structures"
+// processing.
+//
+//----------------------------------------------------------------------------
+#define MAX_ALLOCA_STRUCT 10
+
+DWORD General_Enum_1632(
+ THUNKINFO *pti,
+ UINT uiSize32,
+ UINT uiSize16,
+ SCODE (*pfnCallback)( THUNKINFO *, LPVOID, VPVOID),
+ void (*pfnCleanup)( THUNKINFO *, LPVOID, VPVOID) )
+{
+ DWORD dwResult;
+ ULONG ulCount;
+ VPVOID vpstruct16;
+ VPVOID vpfetched16;
+ LPVOID lpstruct32;
+ LPVOID lpstruct32Iterate;
+ VPVOID vpstruct16Iterate;
+ ULONG ulFetched32;
+ ULONG *lpfetched32;
+ ULONG UNALIGNED *lpfetched16;
+ ULONG ulIterate;
+ LPVOID lp16;
+ BOOL fError;
+ SCODE sc;
+
+ dwResult = (DWORD)S_OK;
+
+ GET_STACK16(pti, ulCount, ULONG );
+ GET_STACK16(pti, vpstruct16, VPVOID );
+ GET_STACK16(pti, vpfetched16, VPVOID );
+
+ //
+ // THIS ROUTINE CAN DEAL WITH dwResult RATHER THAN pti->scResult BECAUSE
+ // WE KNOW THIS IS THE ONLY THOP FOR THIS FUNCTION! NO OTHER CLEANUP
+ // WILL HAVE TO BE DONE!
+ //
+ ulFetched32 = 0;
+ lpfetched32 = &ulFetched32;
+ lp16 = NULL;
+ lpstruct32 = NULL;
+
+ if ( vpstruct16 != 0 )
+ {
+ if ( ulCount == 0 )
+ {
+ dwResult = (DWORD)E_INVALIDARG;
+ }
+ else
+ {
+ //
+ // Verify we have write access to the 16-bit memory.
+ //
+ lp16 = GetWritePtr16(pti, vpstruct16, uiSize16*ulCount);
+ if ( lp16 == NULL )
+ {
+ dwResult = (DWORD)E_INVALIDARG;
+ }
+ else
+ {
+ if ( ulCount > MAX_ALLOCA_STRUCT )
+ {
+ lpstruct32 = (LPVOID)CoTaskMemAlloc( ulCount * uiSize32 );
+ if (lpstruct32 == NULL)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ lpstruct32 = (LPVOID)STACKALLOC32( ulCount * uiSize32 );
+ if (lpstruct32 == NULL)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ }
+
+ WOWRELVDMPTR(vpstruct16);
+ }
+ }
+ }
+
+ if (SUCCEEDED(dwResult))
+ {
+ TO_STACK32(pti, ulCount, ULONG);
+ TO_STACK32(pti, lpstruct32, LPVOID);
+ TO_STACK32(pti, lpfetched32, ULONG FAR *);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP1632(pti);
+ }
+
+ if ( SUCCEEDED(dwResult) )
+ {
+ if ( vpstruct16 != 0 )
+ {
+ // Some apps (MsWorks3 is one) return S_FALSE and do not return
+ // the number of elements retrieved. The only thing we can
+ // do is ignore the enumeration since we don't know how many
+ // were actually set. Of course, we can't ignore all enumerations
+ // when the return is S_FALSE so we only handle the case
+ // where S_FALSE was returned on a enumeration of one element,
+ // in which we can be sure there isn't any valid data
+ if (dwResult == (DWORD)S_FALSE && ulCount == 1)
+ {
+ ulFetched32 = 0;
+ }
+
+ //
+ // Iterate through all of the structures, converting them
+ // into 16-bit
+ //
+ fError = FALSE;
+ ulIterate = 0;
+ vpstruct16Iterate = vpstruct16;
+ lpstruct32Iterate = lpstruct32;
+
+ while ( ulIterate < ulFetched32 )
+ {
+ //
+ // Callback to the callback function to do any specific
+ // processing
+ //
+ sc = (*pfnCallback)( pti, lpstruct32Iterate,
+ vpstruct16Iterate );
+
+ if ( FAILED(sc) )
+ {
+ fError = TRUE;
+ dwResult = sc;
+ }
+
+ vpstruct16Iterate = (VPVOID)((DWORD)vpstruct16Iterate +
+ uiSize16);
+ lpstruct32Iterate = (LPVOID)((DWORD)lpstruct32Iterate +
+ uiSize32);
+
+ ulIterate++;
+ }
+
+ if ( fError )
+ {
+ //
+ // Cleanup all these guys
+ //
+ ulIterate = 0;
+ vpstruct16Iterate = vpstruct16;
+ lpstruct32Iterate = lpstruct32;
+
+ while ( ulIterate <= ulFetched32 )
+ {
+ (*pfnCleanup)( pti, lpstruct32Iterate, vpstruct16Iterate );
+ vpstruct16Iterate = (VPVOID)((DWORD)vpstruct16Iterate +
+ uiSize16);
+ lpstruct32Iterate = (LPVOID)((DWORD)lpstruct32Iterate +
+ uiSize32);
+
+ ulIterate++;
+ }
+ }
+ }
+ }
+
+ if (FAILED(dwResult) && lp16 != NULL)
+ {
+ memset(lp16, 0, ulCount*uiSize16);
+ }
+
+ //
+ // Free up any space we've allocated
+ //
+ if (lpstruct32 != NULL)
+ {
+ if ( ulCount > MAX_ALLOCA_STRUCT )
+ {
+ CoTaskMemFree( lpstruct32 );
+ }
+ else
+ {
+ STACKFREE32(lpstruct32, ulCount*uiSize32);
+ }
+ }
+
+ if ( vpfetched16 != 0 )
+ {
+ lpfetched16 = FIXVDMPTR( vpfetched16, ULONG);
+ *lpfetched16 = ulFetched32;
+ RELVDMPTR(vpfetched16);
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_STRING_1632, public
+//
+// Synopsis: Prepares the LPOLESTR for the copy back into 16-bit address
+// space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_STRING_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ VPSTR vpstr;
+ VPSTR UNALIGNED *pvpstr16;
+ SCODE sc;
+
+ vpstr = 0;
+ sc = ConvertTaskString3216(pti, *(LPOLESTR *)lp32, NULL, 0,
+ &vpstr);
+
+ pvpstr16 = FIXVDMPTR(vp16, VPSTR);
+ *pvpstr16 = vpstr;
+ RELVDMPTR(vp16);
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_STRING_1632, public
+//
+// Synopsis: Cleans up the any STRINGs returned (either to 16-bit or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_STRING_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ VPSTR UNALIGNED *lpvpstr16;
+ VPSTR vpstr16;
+
+ lpvpstr16 = FIXVDMPTR( vp16, VPSTR );
+ vpstr16 = *lpvpstr16;
+ RELVDMPTR(vp16);
+
+ if ( vpstr16 != 0 )
+ {
+ TaskFree16( vpstr16 );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_STRING_1632, public
+//
+// Synopsis: Thunks IEnumSTRING::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_STRING_1632(THUNKINFO *pti)
+{
+ return General_Enum_1632(pti,
+ sizeof(LPOLESTR),
+ sizeof(VPSTR),
+ Callback_STRING_1632,
+ Cleanup_STRING_1632 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_UNKNOWN_1632, public
+//
+// Synopsis: Prepares the UNKNOWN structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_UNKNOWN_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ VPVOID vpunknown16;
+ SCODE sc = S_OK;
+
+ vpunknown16 =
+ pti->pThkMgr->FindProxy1632(NULL, *(LPUNKNOWN *)lp32,
+ INDEX_IIDIDX(THI_IUnknown), NULL);
+ if (vpunknown16 == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+
+ *FIXVDMPTR( vp16, VPVOID ) = vpunknown16;
+ RELVDMPTR(vp16);
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_UNKNOWN_1632, public
+//
+// Synopsis: Cleans up the any UNKNOWNs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_UNKNOWN_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ LPUNKNOWN lpunknown32;
+ VPVOID vpunknown16;
+
+ vpunknown16 = *FIXVDMPTR( vp16, VPVOID );
+ RELVDMPTR(vp16);
+ lpunknown32 = *(LPUNKNOWN *)lp32;
+
+ // BUGBUG - What is the proper cleanup for IEnum<Interface>?
+ // Should the objects be released or only the proxies we
+ // created?
+ if (vpunknown16 != 0)
+ {
+ pti->pThkMgr->FreeProxy1632( lpunknown32 );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_UNKNOWN_1632, public
+//
+// Synopsis: Thunks IEnumUNKNOWN::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_UNKNOWN_1632(THUNKINFO *pti)
+{
+ return General_Enum_1632(pti,
+ sizeof(LPUNKNOWN),
+ sizeof(LPUNKNOWN),
+ Callback_UNKNOWN_1632,
+ Cleanup_UNKNOWN_1632 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_STATSTG_1632, public
+//
+// Synopsis: Prepares the STATSTG structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_STATSTG_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ (FIXVDMPTR(vp16, STATSTG))->pwcsName = NULL;
+ RELVDMPTR(vp16);
+ return ConvertStatStg3216(pti, (STATSTG *)lp32, vp16,
+ NULL, 0);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_STATSTG_1632, public
+//
+// Synopsis: Cleans up the any STATSTGs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_STATSTG_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ STATSTG UNALIGNED *lpstatstg16;
+ VPVOID vpstr;
+
+ lpstatstg16 = FIXVDMPTR( vp16, STATSTG );
+ vpstr = (VPVOID)lpstatstg16->pwcsName;
+ RELVDMPTR(vp16);
+
+ if ( vpstr != 0)
+ {
+ TaskFree16( vpstr );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_STATSTG_1632, public
+//
+// Synopsis: Thunks IEnumSTATSTG::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_STATSTG_1632(THUNKINFO *pti)
+{
+ return General_Enum_1632(pti,
+ sizeof(STATSTG),
+ sizeof(STATSTG),
+ Callback_STATSTG_1632,
+ Cleanup_STATSTG_1632 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_FORMATETC_1632, public
+//
+// Synopsis: Prepares the FORMATETC structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_FORMATETC_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ (FIXVDMPTR(vp16, FORMATETC16))->ptd = NULL;
+ RELVDMPTR(vp16);
+ return ConvertFetc3216(pti, (FORMATETC *)lp32, vp16, TRUE);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_FORMATETC_1632, public
+//
+// Synopsis: Cleans up the any FORMATETCs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_FORMATETC_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ FORMATETC16 UNALIGNED *lpformatetc16;
+ VPVOID vptd;
+
+ lpformatetc16 = FIXVDMPTR( vp16, FORMATETC16 );
+ vptd = lpformatetc16->ptd;
+ RELVDMPTR(vp16);
+
+ if (vptd != 0)
+ {
+ TaskFree16(vptd);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_FORMATETC_1632, public
+//
+// Synopsis: Thunks IEnumFORMATETC::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_FORMATETC_1632(THUNKINFO *pti)
+{
+ return General_Enum_1632(pti,
+ sizeof(FORMATETC),
+ sizeof(FORMATETC16),
+ Callback_FORMATETC_1632,
+ Cleanup_FORMATETC_1632 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_STATDATA_1632, public
+//
+// Synopsis: Prepares the STATDATA structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+SCODE Callback_STATDATA_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ SCODE sc;
+ LPSTATDATA lpstatdata32;
+ STATDATA16 UNALIGNED *lpstatdata16;
+ VPVOID vpadv16;
+
+ sc = S_OK;
+
+ lpstatdata32 = (LPSTATDATA)lp32;
+
+ if (lpstatdata32->pAdvSink != NULL)
+ {
+ // We don't know whether it's an AdviseSink or
+ // an AdviseSink2, so pass AdviseSink2 since it's
+ // a superset of AdviseSink and will work for both
+
+ vpadv16 = pti->pThkMgr->FindProxy1632(NULL, lpstatdata32->pAdvSink,
+ INDEX_IIDIDX(THI_IAdviseSink2),
+ NULL);
+ if (vpadv16 == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ vpadv16 = 0;
+ }
+
+ lpstatdata16 = FIXVDMPTR( vp16, STATDATA16 );
+ lpstatdata16->formatetc.ptd = NULL;
+ if (SUCCEEDED(sc))
+ {
+ // If this fails the AdviseSink proxy will be cleaned up in
+ // the cleanup function later
+
+ sc = ConvertFetc3216(pti,
+ &lpstatdata32->formatetc,
+ vp16+FIELD_OFFSET(STATDATA16, formatetc), TRUE);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ lpstatdata16->advf = lpstatdata32->advf;
+ lpstatdata16->pAdvSink = vpadv16;
+ lpstatdata16->dwConnection = lpstatdata32->dwConnection;
+ }
+
+ RELVDMPTR(vp16);
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_STATDATA_1632, public
+//
+// Synopsis: Cleans up the any STATDATAs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_STATDATA_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ STATDATA *lpstatdata32;
+ STATDATA16 UNALIGNED *lpstatdata16;
+ LPADVISESINK lpadv32;
+ VPVOID vptd;
+
+ lpstatdata32 = (STATDATA FAR *)lp32;
+ lpadv32 = lpstatdata32->pAdvSink;
+
+ lpstatdata16 = FIXVDMPTR( vp16, STATDATA16 );
+ vptd = lpstatdata16->formatetc.ptd;
+ RELVDMPTR(vp16);
+
+ if ( lpstatdata16->pAdvSink != NULL )
+ {
+ // BUGBUG - What is the proper cleanup for interfaces?
+ // Should the objects be released or only the proxies we
+ // created?
+ pti->pThkMgr->FreeProxy1632(lpstatdata32->pAdvSink);
+ }
+
+ if (vptd != 0)
+ {
+ TaskFree16(vptd);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_STATDATA_1632, public
+//
+// Synopsis: Thunks IEnumSTATDATA::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_STATDATA_1632(THUNKINFO *pti)
+{
+ return General_Enum_1632(pti,
+ sizeof(STATDATA),
+ sizeof(STATDATA16),
+ Callback_STATDATA_1632,
+ Cleanup_STATDATA_1632 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_MONIKER_1632, public
+//
+// Synopsis: Prepares the MONIKER structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_MONIKER_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ VPVOID vpmoniker16;
+ SCODE sc = S_OK;
+
+ vpmoniker16 = pti->pThkMgr->FindProxy1632(NULL, *(LPMONIKER *)lp32,
+ INDEX_IIDIDX(THI_IMoniker),
+ NULL);
+ if (vpmoniker16 == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+
+ *FIXVDMPTR(vp16, VPVOID) = vpmoniker16;
+ RELVDMPTR(vp16);
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_MONIKER_1632, public
+//
+// Synopsis: Cleans up the any MONIKERs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_MONIKER_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ LPMONIKER lpmoniker32;
+ VPVOID vpmoniker16;
+
+ vpmoniker16 = *FIXVDMPTR( vp16, VPVOID );
+ RELVDMPTR(vp16);
+ lpmoniker32 = *(LPMONIKER *)lp32;
+
+ // BUGBUG - What is the proper cleanup for IEnum<Interface>?
+ // Should the objects be released or only the proxies we
+ // created?
+ if (vpmoniker16 != NULL)
+ {
+ pti->pThkMgr->FreeProxy1632( lpmoniker32 );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_MONIKER_1632, public
+//
+// Synopsis: Thunks IEnumMONIKER::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_MONIKER_1632(THUNKINFO *pti)
+{
+ return General_Enum_1632(pti,
+ sizeof(LPMONIKER),
+ sizeof(LPMONIKER),
+ Callback_MONIKER_1632,
+ Cleanup_MONIKER_1632 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_OLEVERB_1632, public
+//
+// Synopsis: Prepares the OLEVERB structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_OLEVERB_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ SCODE sc;
+ OLEVERB *lpoleverb32;
+ OLEVERB UNALIGNED *lpoleverb16;
+ VPSTR vpstr;
+
+ lpoleverb32 = (LPOLEVERB)lp32;
+ vpstr = 0;
+ sc = ConvertTaskString3216(pti, lpoleverb32->lpszVerbName, NULL, 0,
+ &vpstr);
+ lpoleverb16 = FIXVDMPTR(vp16, OLEVERB);
+ lpoleverb16->lpszVerbName = (LPOLESTR)vpstr;
+ if (SUCCEEDED(sc))
+ {
+ lpoleverb16->lVerb = lpoleverb32->lVerb;
+ lpoleverb16->fuFlags = lpoleverb32->fuFlags;
+ lpoleverb16->grfAttribs = lpoleverb32->grfAttribs;
+ }
+ RELVDMPTR(vp16);
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_OLEVERB_1632, public
+//
+// Synopsis: Cleans up the any OLEVERBs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit returned structure
+// [lp16] - Pointer to 16-bit output structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_OLEVERB_1632( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ OLEVERB UNALIGNED *lpoleverb16;
+ VPVOID vpstr;
+
+ lpoleverb16 = FIXVDMPTR( vp16, OLEVERB );
+ vpstr = (VPVOID)lpoleverb16->lpszVerbName;
+ RELVDMPTR(vp16);
+
+ if ( vpstr != 0 )
+ {
+ TaskFree16( vpstr );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_OLEVERB_1632, public
+//
+// Synopsis: Thunks IEnumOLEVERB::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_OLEVERB_1632(THUNKINFO *pti)
+{
+ return General_Enum_1632(pti,
+ sizeof(OLEVERB),
+ sizeof(OLEVERB),
+ Callback_OLEVERB_1632,
+ Cleanup_OLEVERB_1632 );
+}
+
+#define THOP_EFN(x) Thop_Enum_ ## x ## _1632
+
+DWORD (*CONST aThopEnumFunctions1632[])(THUNKINFO *) =
+{
+ THOP_EFN(STRING), // STRING
+ THOP_EFN(UNKNOWN), // UNKNOWN
+ THOP_EFN(STATSTG), // STATSTG
+ THOP_EFN(FORMATETC), // FORMATETC
+ THOP_EFN(STATDATA), // STATDATA
+ THOP_EFN(MONIKER), // MONIKER
+ THOP_EFN(OLEVERB), // OLEVERB
+};
+
+
diff --git a/private/ole32/olethunk/olethk32/thop32.cxx b/private/ole32/olethunk/olethk32/thop32.cxx
new file mode 100644
index 000000000..869dd75f3
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thop32.cxx
@@ -0,0 +1,3959 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thop32.cxx
+//
+// Contents: Thop implementations for 32->16
+//
+// History: 22-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <ole2.h>
+#include <string.h>
+#include <valid.h>
+#include "olethk32.hxx"
+#include "struct16.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Function: EXECUTE_THOP3216, public
+//
+// Synopsis: Debugging version of thop dispatch routine
+//
+// Arguments: [pti] - Thunking info
+//
+// Returns: Appropriate status
+//
+// History: 24-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+DWORD EXECUTE_THOP3216(THUNKINFO *pti)
+{
+ thkDebugOut((DEB_THOPS, "ExThop3216: %s (0x%02X), s16 %p, s32 %p\n",
+ ThopName(*pti->pThop), *pti->pThop, pti->s16.pbCurrent,
+ pti->s32.pbCurrent));
+ thkAssert((*pti->pThop & THOP_OPMASK) < THOP_LASTOP);
+ return (*aThopFunctions3216[*((pti)->pThop) & THOP_OPMASK])(pti);
+}
+#endif
+
+#if DBG == 1
+DWORD EXECUTE_ENUMTHOP3216(THUNKINFO *pti)
+{
+ thkDebugOut((DEB_THOPS, "ExEnumThop3216: %s (0x%02X), s16 %p, s32 %p\n",
+ EnumThopName(*pti->pThop), *pti->pThop, pti->s16.pbCurrent,
+ pti->s32.pbCurrent));
+ return (*aThopEnumFunctions3216[*(pti)->pThop])(pti);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: FixedThopHandler, public
+//
+// Synopsis: Generic function which handles the high-level details
+// of thop execution for thops that operate on known-size
+// data
+//
+// Arguments: [pti] - Thunking state information
+// [thop] - Thop being executed
+// [cb16] - 16-bit size
+// [pfn1632] - 16->32 conversion routine
+// [cb32] - 32-bit size
+// [pfn3216] - 32->16 conversion routine
+//
+// Returns: Appropriate status code
+//
+// History: 05-Apr-94 DrewB Created
+//
+// Notes: Automatically increments pThop
+//
+//----------------------------------------------------------------------------
+
+DWORD FixedThopHandler3216(THUNKINFO *pti,
+ THOP thop,
+ UINT cb16,
+ FIXEDHANDLERROUTINE pfn1632,
+ UINT cb32,
+ FIXEDHANDLERROUTINE pfn3216)
+{
+ DWORD dwResult;
+ VPVOID vp16;
+ BYTE *pb16;
+ BYTE *pb32;
+
+ if ((thop & (THOP_IN | THOP_OUT)) != 0)
+ {
+ vp16 = 0;
+
+ GET_STACK32(pti, pb32, BYTE *);
+ if ( pb32 != 0 )
+ {
+ if ((thop & THOP_IN) != 0)
+ {
+ if (IsBadReadPtr(pb32, cb32))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+ }
+ if ((thop & THOP_OUT) != 0)
+ {
+ if (IsBadWritePtr(pb32, cb32))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+ }
+
+ vp16 = STACKALLOC16(cb16);
+ if (vp16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+ else if ((thop & THOP_IN) != 0)
+ {
+ pb16 = (BYTE *)WOWFIXVDMPTR(vp16, cb16);
+ (pfn3216)(pb32, pb16, cb32, cb16);
+ WOWRELVDMPTR(vp16);
+ }
+ }
+
+ TO_STACK16(pti, vp16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if ((thop & THOP_OUT) != 0 && pb32 != NULL)
+ {
+ if (SUCCEEDED(dwResult))
+ {
+ pb16 = (BYTE *)WOWFIXVDMPTR(vp16, cb16);
+ (pfn1632)(pb16, pb32, cb16, cb32);
+ WOWRELVDMPTR(vp16);
+ }
+ else if ((thop & THOP_IN) == 0)
+ {
+ // Zero out-only parameters on failure
+ memset(pb32, 0, cb32);
+ }
+ }
+
+ if (vp16 != 0)
+ {
+ STACKFREE16(vp16, cb16);
+ }
+ }
+ else
+ {
+ (pfn3216)(PTR_STACK32(&pti->s32), PTR_STACK16(&pti->s16, cb16),
+ cb32, cb16);
+
+ SKIP_STACK16(&pti->s16, cb16);
+ SKIP_STACK32(&pti->s32, cb32);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+ }
+
+ return dwResult;
+}
+
+//-----------------------------------------------------------------------------
+//
+// Handler-based thunks
+//
+// These thunks use the fixed-size generic thop handler to do their work
+//
+//-----------------------------------------------------------------------------
+
+// Handle straight copy
+DWORD Thop_Copy_3216(THUNKINFO *pti)
+{
+ THOP thopSize;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_COPY);
+
+ thopSize = *++pti->pThop;
+ return FixedThopHandler3216(pti,
+ *(pti->pThop-1),
+ thopSize, FhCopyMemory,
+ thopSize, FhCopyMemory);
+}
+
+DWORD Thop_ShortToLong_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SHORTLONG);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(SHORT), FhShortToLong,
+ sizeof(LONG), FhLongToShort);
+}
+
+DWORD Thop_WordToDword_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_WORDDWORD);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(WORD), FhWordToDword,
+ sizeof(DWORD), FhDwordToWord);
+}
+
+DWORD Thop_GdiHandle_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HGDI);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhGdiHandle1632,
+ sizeof(HANDLE), FhGdiHandle3216);
+}
+
+DWORD Thop_UserHandle_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HUSER);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhUserHandle1632,
+ sizeof(HANDLE), FhUserHandle3216);
+}
+
+DWORD Thop_HACCEL_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HACCEL);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhHaccel1632,
+ sizeof(HANDLE), FhHaccel3216);
+}
+
+DWORD Thop_HTASK_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HTASK);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(HAND16), FhHtask1632,
+ sizeof(HANDLE), FhHtask3216);
+}
+
+DWORD Thop_HRESULT_3216( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_HRESULT);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(HRESULT), FhHresult1632,
+ sizeof(HRESULT), FhHresult3216);
+}
+
+DWORD Thop_NULL_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_NULL);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(void *), FhNull,
+ sizeof(void *), FhNull);
+}
+
+DWORD Thop_RECT_3216( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RECT);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(RECT16), FhRect1632,
+ sizeof(RECT), FhRect3216);
+}
+
+DWORD Thop_BINDOPTS_3216( THUNKINFO *pti )
+{
+ LPBIND_OPTS pbo;
+ UINT cb;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_BINDOPTS);
+
+ PEEK_STACK32(pti, pbo, LPBIND_OPTS);
+ if (!IsBadReadPtr(pbo, sizeof(LPBIND_OPTS)))
+ {
+ cb = pbo->cbStruct;
+ }
+ else
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ cb, FhCopyMemory,
+ cb, FhCopyMemory);
+}
+
+DWORD Thop_SIZE_3216( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SIZE);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(SIZE16), FhSize1632,
+ sizeof(SIZE), FhSize3216);
+}
+
+DWORD Thop_MSG_3216( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_MSG);
+
+ return FixedThopHandler3216(pti,
+ *pti->pThop,
+ sizeof(MSG16), FhMsg1632,
+ sizeof(MSG), FhMsg3216);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_ERROR_3216, public
+//
+// Synopsis: Any Thop type which should just fail with an error
+// should go be directed here.
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_ERROR_3216 ( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ERROR);
+
+ thkAssert( FALSE && "Hey we hit an ERROR Thop in 32->16" );
+
+ return (DWORD)E_UNEXPECTED;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThunkInString3216, public
+//
+// Synopsis: Converts an in param string or filename
+//
+// Arguments: [pti] - Thunk state information
+// [fFile] - Filename or plain string
+// [cchMax] - Maximum length allowed or zero
+//
+// Returns: Appropriate status code
+//
+// History: 24-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD ThunkInString3216(THUNKINFO *pti,
+ BOOL fFile,
+ UINT cchMax)
+{
+ DWORD dwResult;
+ LPOLESTR lpstr32;
+ VPSTR vpstr16;
+ UINT uiSize;
+ LPOLESTR lpstrConv;
+ LPOLESTR lpstrShort;
+
+ dwResult = (DWORD)S_OK;
+
+ lpstrShort = NULL;
+
+ GET_STACK32(pti, lpstr32, LPOLESTR);
+ lpstrConv = lpstr32;
+
+ vpstr16 = 0;
+ if (lpstr32 != NULL)
+ {
+ if (IsBadStringPtrW(lpstr32, CCHMAXSTRING))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ if (fFile)
+ {
+ DWORD cchNeeded, cchShort;
+
+ // Special case zero-length paths since the length returns from
+ // GetShortPathName become ambiguous when zero characters are
+ // processed
+ cchNeeded = lstrlenW(lpstr32);
+ if (cchNeeded > 0)
+ {
+ cchNeeded = GetShortPathName(lpstr32, NULL, 0);
+ }
+
+ // If we can't convert, simply pass through the name we're given
+ if (cchNeeded > 0)
+ {
+ lpstrShort = (LPOLESTR)CoTaskMemAlloc(cchNeeded*sizeof(WCHAR));
+ if (lpstrShort == NULL)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ cchShort = GetShortPathName(lpstr32, lpstrShort,
+ cchNeeded);
+ if (cchShort == 0 || cchShort > cchNeeded)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ else
+ {
+ lpstrConv = lpstrShort;
+ }
+ }
+ }
+
+ if (SUCCEEDED(dwResult))
+ {
+ uiSize = lstrlenW( lpstrConv ) + 1;
+
+ vpstr16 = STACKALLOC16(uiSize*2);
+ if (vpstr16 == 0)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ else
+ {
+ char *psz;
+
+ dwResult = Convert_LPOLESTR_to_VPSTR(lpstrConv, vpstr16,
+ uiSize, uiSize*2);
+
+ // If a maximum length was given, truncate the converted
+ // string if necessary
+ if (SUCCEEDED(dwResult) && cchMax > 0 && cchMax < uiSize)
+ {
+ psz = (char *)WOWFIXVDMPTR(vpstr16, 0);
+ psz[cchMax] = 0;
+ WOWRELVDMPTR(vpstr16);
+ }
+ }
+ }
+ }
+
+ if (SUCCEEDED(dwResult))
+ {
+#if DBG == 1
+ thkDebugOut((DEB_ARGS, "In3216 LPSTR %p -> %p '%s'\n",
+ lpstr32, vpstr16,
+ vpstr16 != 0 ? WOWFIXVDMPTR(vpstr16, 0) : "<null>"));
+ if (vpstr16 != 0)
+ {
+ WOWRELVDMPTR(vpstr16);
+ }
+#endif
+
+ TO_STACK16(pti, vpstr16, VPSTR);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+ }
+
+ if (vpstr16 != 0)
+ {
+ STACKFREE16(vpstr16, uiSize*2);
+ }
+
+ if (lpstrShort != NULL)
+ {
+ CoTaskMemFree(lpstrShort);
+ }
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_LPSTR_3216, public
+//
+// Synopsis: Converts 32-bit LPOLESTR to 16-bit LPSTR pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_LPSTR_3216( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LPSTR);
+ //
+ // We have only input LPSTRs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_IN &&
+ "LPSTR must be input only!" );
+
+ return ThunkInString3216(pti, FALSE, 0);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertTaskString1632, public
+//
+// Synopsis: Converts a task-memory string
+//
+// Arguments: [pti] - Thunk info
+// [vpstr16] - String
+// [posPreAlloc] - Preallocated string or NULL
+// [cchPreAlloc] - Preallocated size or zero
+// [ppos32] - String
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pti]
+// [ppos32]
+//
+// History: 14-May-94 DrewB Created
+//
+// Notes: Frees preallocation if successful and:
+// Name is too large or
+// Name is NULL
+//
+// Always frees source string if non-zero
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertTaskString1632(THUNKINFO *pti,
+ VPSTR vpstr16,
+ LPOLESTR posPreAlloc,
+ UINT cchPreAlloc,
+ LPOLESTR *ppos32)
+{
+ LPOLESTR pos32;
+
+ if (vpstr16 == 0)
+ {
+ pos32 = NULL;
+ }
+ else
+ {
+ pos32 = Convert_VPSTR_to_LPOLESTR(pti, vpstr16, posPreAlloc,
+ cchPreAlloc);
+
+ TaskFree16(vpstr16);
+
+ if (pos32 == NULL)
+ {
+ return pti->scResult;
+ }
+ }
+
+ // If there was a preallocated string we didn't use,
+ // free it
+ if (posPreAlloc != NULL && posPreAlloc != pos32)
+ {
+ TaskFree32(posPreAlloc);
+ }
+
+ *ppos32 = pos32;
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThunkOutString3216, public
+//
+// Synopsis: Converts an out param string
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD ThunkOutString3216(THUNKINFO *pti)
+{
+ DWORD dwResult;
+ LPOLESTR *lplpstr32;
+ VPVOID vpvpstr16;
+ VPSTR UNALIGNED *lpvpstr16;
+ LPOLESTR lpstr32;
+
+ GET_STACK32(pti, lplpstr32, LPOLESTR FAR *);
+
+ if ( lplpstr32 == NULL )
+ {
+ vpvpstr16 = 0;
+ }
+ else
+ {
+ if (IsBadWritePtr(lplpstr32, sizeof(LPOLESTR)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpvpstr16 = STACKALLOC16(sizeof(VPSTR));
+ if (vpvpstr16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ lpvpstr16 = FIXVDMPTR(vpvpstr16, VPSTR);
+ *lpvpstr16 = 0;
+ RELVDMPTR(vpvpstr16);
+
+ lpstr32 = (LPOLESTR)TaskMalloc32(CBSTRINGPREALLOC);
+ if (lpstr32 == NULL)
+ {
+ STACKFREE16(vpvpstr16, sizeof(VPSTR));
+ return (DWORD)E_OUTOFMEMORY;
+ }
+ }
+
+ TO_STACK16(pti, vpvpstr16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (lplpstr32 != NULL)
+ {
+ if (SUCCEEDED(dwResult))
+ {
+ lpvpstr16 = FIXVDMPTR(vpvpstr16, VPSTR);
+ if (lpvpstr16 == NULL)
+ {
+ dwResult = (DWORD)E_INVALIDARG;
+ }
+ else
+ {
+ SCODE sc;
+
+ sc = ConvertTaskString1632(pti, *lpvpstr16, lpstr32,
+ CWCSTRINGPREALLOC, &lpstr32);
+ if (FAILED(sc))
+ {
+ dwResult = sc;
+ }
+
+ RELVDMPTR(vpvpstr16);
+ }
+ }
+
+ if (FAILED(dwResult))
+ {
+ TaskFree32(lpstr32);
+
+ *lplpstr32 = NULL;
+ }
+ else
+ {
+ *lplpstr32 = lpstr32;
+ }
+
+ thkDebugOut((DEB_ARGS, "Out3216 LPLPSTR: %p -> %p, '%ws'\n",
+ *lpvpstr16, lpstr32, lpstr32));
+ }
+ else
+ {
+ thkDebugOut((DEB_ARGS, "Out3216 LPLPSTR NULL\n"));
+ }
+
+ if (vpvpstr16 != 0)
+ {
+ STACKFREE16(vpvpstr16, sizeof(VPSTR));
+ }
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_LPLPSTR_3216, public
+//
+// Synopsis: Converts 16-bit LPSTR to 32-bit LPSTR pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 26-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_LPLPSTR_3216( THUNKINFO *pti )
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LPLPSTR);
+ //
+ // We don't have anything but unmodified LPLPSTRs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == 0 &&
+ "LPLPSTR must be unmodified only!" );
+
+ return ThunkOutString3216(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_BUFFER_3216, public
+//
+// Synopsis: Converts 32-bit block of memory to 16-bit block of memory
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 25-Feb-94 BobDay Created
+//
+// Notes: WARNING! WARNING! WARNING! For an out parameter this expects
+// three parameters on the stack in the following format and order:
+// VOID * pointer to buffer
+// DWORD count of bytes in buffer
+// DWORD * count of bytes returned in the buffer
+//
+//----------------------------------------------------------------------------
+
+#define WATCH_VALUE 0xfef1f0
+
+DWORD Thop_BUFFER_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+ LPVOID lp32;
+ VPVOID vp16;
+ LPVOID lp16;
+ DWORD dwCount;
+ VPVOID vp16CountOut;
+ LPVOID pvCountOut32;
+ DWORD * pdwCountOut32;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_BUFFER);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ //
+ // Buffers can only be in or out
+ //
+ thkAssert( (fThopInput || fThopOutput) &&
+ (fThopInput != fThopOutput) &&
+ "BUFFER must be in or out only!" );
+
+ GET_STACK32(pti, lp32, LPVOID);
+ GET_STACK32(pti, dwCount, DWORD);
+
+ if (fThopOutput)
+ {
+ GET_STACK32(pti, pvCountOut32, LPVOID);
+ pdwCountOut32 = (DWORD *) pvCountOut32;
+ }
+
+ if ( lp32 == NULL )
+ {
+ vp16 = 0;
+ }
+ else if (dwCount == 0)
+ {
+ // If the count is zero then we can pass any valid 16-bit
+ // pointer
+
+#if DBG == 1
+ // In debug, make sure that no data is written back to the
+ // memory we pass on
+ vp16 = STACKALLOC16(sizeof(DWORD));
+
+ if ( vp16 == 0 )
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ *FIXVDMPTR(vp16, DWORD) = WATCH_VALUE;
+ RELVDMPTR(vp16);
+#else
+ vp16 = gdata16Data.atfnProxy1632Vtbl;
+#endif
+ }
+ else
+ {
+ if ((fThopInput && IsBadReadPtr(lp32, dwCount)) ||
+ (fThopOutput && IsBadWritePtr(lp32, dwCount)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vp16 = (VPVOID)WgtAllocLock( GMEM_MOVEABLE, dwCount, NULL );
+ if ( vp16 == 0 )
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ if ( fThopInput )
+ {
+ lp16 = (LPVOID)WOWFIXVDMPTR(vp16, dwCount);
+ memcpy( lp16, lp32, dwCount );
+ WOWRELVDMPTR(vp16);
+ }
+ }
+
+ if (fThopOutput)
+ {
+ // We always allocate storage so we can guarantee that we
+ // only copy the correct number of bytes.
+ vp16CountOut = STACKALLOC16(sizeof(DWORD));
+
+ if (vp16CountOut == 0)
+ {
+ return (DWORD) E_OUTOFMEMORY;
+ }
+ }
+
+ thkDebugOut((DEB_ARGS, "3216 BUFFER: %p -> %p, %u\n",
+ lp32, vp16, dwCount));
+
+ TO_STACK16(pti, vp16, VPVOID );
+ TO_STACK16(pti, dwCount, DWORD );
+
+ if (fThopOutput)
+ {
+ TO_STACK16(pti, vp16CountOut, VPVOID );
+ }
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if ( SUCCEEDED(dwResult) && fThopOutput )
+ {
+ // Count of bytes to copy into the output buffer
+ DWORD dwCountOut;
+
+ // Get the output data count
+ DWORD UNALIGNED *pdw16 = (DWORD UNALIGNED *)
+ WOWFIXVDMPTR(vp16CountOut, sizeof(DWORD));
+
+ // Save count to return to 32 bit caller.
+ dwCountOut = *pdw16;
+ if (pdwCountOut32)
+ {
+ // Note: this parameter can be a NULL pointer
+ *pdwCountOut32 = dwCountOut;
+ }
+
+ WOWRELVDMPTR(vp16CountOut);
+
+ // Copy data into output buffer if necessary.
+ if (dwCountOut > 0)
+ {
+ lp16 = (LPVOID) WOWFIXVDMPTR( vp16, dwCountOut );
+ memcpy( lp32, lp16, dwCountOut );
+ WOWRELVDMPTR(vp16);
+ }
+ }
+
+#if DBG == 1
+ if (vp16 != 0 && dwCount == 0)
+ {
+ thkAssert(*FIXVDMPTR(vp16, DWORD) == WATCH_VALUE &&
+ (RELVDMPTR(vp16), TRUE));
+ STACKFREE16(vp16, sizeof(DWORD));
+ }
+#endif
+
+ //
+ // Now free the buffers
+ //
+ if ( vp16 != 0 && dwCount > 0 )
+ {
+ WgtUnlockFree( vp16 );
+ }
+
+ if (fThopOutput && (vp16CountOut != 0))
+ {
+ STACKFREE16(vp16CountOut, sizeof(DWORD));
+ }
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_SNB_3216, public
+//
+// Synopsis: Converts 32-bit SNB to 16-bit SNB pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_SNB_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+
+ SNB snbSrc32; // Ptr to 32 bit Source SNB.
+ LPOLESTR FAR *lplpsTabSrc32; // Ptr into 32 bit Source ptr table.
+ LPOLESTR lpstr32; // Ptr into a Source Unicode data block.
+
+ VPVOID snbDest16s; // Seg:Ptr to 16 bit Destination SNB.
+ VPSTR UNALIGNED FAR *lpvpsTabDest16f; // Flat Ptr into 16 bit Dest ptr table.
+ char UNALIGNED *lpstrDest16f; // Flat Ptr into 16 bit Dest data block.
+ VPVOID lpstrDest16s; // Seg:Ptr into 16 bit Dest data block.
+
+ UINT cPointers; // Count of number of string pointers.
+ UINT cbStrings; // Count of number of bytes in data table.
+ UINT cLength;
+ UINT cChars;
+ UINT cbAlloc;
+ UINT i;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SNB);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ //
+ // We don't have anything but unmodified SNBs
+ //
+ thkAssert( !fThopInput && !fThopOutput && "SNB must be unmodified only!" );
+
+ GET_STACK32(pti, snbSrc32, LPOLESTR FAR *);
+
+ if ( snbSrc32 == NULL )
+ {
+ snbDest16s = 0;
+ }
+ else
+ {
+ //
+ // Count the strings in the 32-bit snb
+ //
+ lplpsTabSrc32 = snbSrc32;
+
+ cPointers = 0;
+ cbStrings = 0;
+ do
+ {
+ cPointers++;
+ if (IsBadReadPtr(lplpsTabSrc32, sizeof(LPOLESTR)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ lpstr32 = *lplpsTabSrc32++;
+
+ if ( lpstr32 == NULL )
+ {
+ break;
+ }
+
+ if (IsBadStringPtrW(lpstr32, CCHMAXSTRING))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ cbStrings += lstrlenW(lpstr32)+1;
+ }
+ while ( TRUE );
+
+ //
+ // Allocate a table for the 16-bit snb
+ // cPointers is a count of pointers plus the NULL pointer at the end.
+ //
+ cbAlloc = cPointers*sizeof(VPSTR)+cbStrings;
+ snbDest16s = (VPVOID)STACKALLOC16(cbAlloc);
+ if (snbDest16s == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ //
+ // Set up the pointers to the destination table and string block.
+ // This gets a flat pointer to the pointer table, a both flat and
+ // segmented pointers to the data block.
+ //
+ lpvpsTabDest16f = (VPSTR UNALIGNED FAR *)WOWFIXVDMPTR( snbDest16s, cbAlloc );
+ lpstrDest16f = (char UNALIGNED *)
+ ((BYTE UNALIGNED *)lpvpsTabDest16f+cPointers*sizeof(VPSTR));
+ lpstrDest16s = (VPVOID)((DWORD)snbDest16s+cPointers*sizeof(VPSTR));
+
+ //
+ // Now convert the strings
+ //
+ cPointers -= 1;
+ lplpsTabSrc32 = snbSrc32;
+ for(i=0; i<cPointers; i++)
+ {
+ lpstr32 = *lplpsTabSrc32++;
+
+ thkAssert( lpstr32 != NULL && "Loop is processing end of snb\n" );
+
+ cLength = lstrlenW( lpstr32 ) + 1;
+
+ cChars = WideCharToMultiByte( AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0, lpstr32, cLength,
+ lpstrDest16f, cbStrings, NULL, NULL );
+
+ if ( cChars == 0 && cLength != 0 )
+ {
+ WOWRELVDMPTR(snbDest16s);
+ STACKFREE16(snbDest16s, cbAlloc);
+ return (DWORD)E_UNEXPECTED;
+ }
+
+ //
+ // Assign the Segmented pointer into the pointer table.
+ //
+ *lpvpsTabDest16f++ = lpstrDest16s;
+
+ //
+ // Advance both the flat and segmented data pointers.
+ //
+ lpstrDest16f += cChars;
+ lpstrDest16s = (VPVOID)((DWORD)lpstrDest16s + cChars);
+
+ //
+ // As we advance the Dest pointer the size of the remaining
+ // space in the buffer decreases.
+ //
+ cbStrings -= cChars;
+ }
+
+ // Terminate SNB
+ *lpvpsTabDest16f = NULL;
+
+ thkAssert( *lplpsTabSrc32 == NULL &&
+ "Loop is out of sync with count\n" );
+
+ WOWRELVDMPTR(snbDest16s);
+ }
+
+ thkDebugOut((DEB_ARGS, "In3216 SNB: %p -> %p\n", snbSrc32, snbDest16s));
+
+ TO_STACK16(pti, snbDest16s, VPVOID );
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ //
+ // Free SNB data if necessary
+ //
+ if ( snbDest16s != 0 )
+ {
+ STACKFREE16( snbDest16s, cbAlloc );
+ }
+
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThunkInterface3216, private
+//
+// Synopsis: Handles 32->16 interface thunking for THOP_IFACE and
+// THOP_IFACEGEN
+//
+// Arguments: [pti] - Thunking state information
+// [iidx] - Interface IID or index
+// [thop] - Thop being executed
+// [vpvOuter] - Controlling unknown or NULL
+//
+// Returns: Appropriate status code
+//
+// History: 01-Mar-94 DrewB Created
+//
+// Notes: Assumes pti->pThop is adjusted by caller
+//
+//----------------------------------------------------------------------------
+
+DWORD ThunkInterface3216(THUNKINFO *pti,
+ IIDIDX iidx,
+ THOP thop,
+ VPVOID vpvOuter)
+{
+ DWORD dwResult;
+ void *pv;
+ VPVOID vpvOutParam;
+ VPVOID vpvThis16In, vpvThis16Out;
+ IUnknown *punkThis32;
+ IUnknown *punkIn;
+ THUNK3216OBJ *ptoPreAlloc = NULL;
+
+ dwResult = (DWORD)S_OK;
+
+ vpvOutParam = 0;
+ vpvThis16In = 0;
+
+ // Retrieve in or out interface pointer
+ GET_STACK32(pti, pv, void *);
+
+ // Out takes precedence over in for determining indirection depth
+
+ if ((thop & THOP_OUT) != 0 && pv != NULL)
+ {
+ if (IsBadReadPtr(pv, sizeof(void *)) ||
+ IsBadWritePtr(pv, sizeof(void *)))
+ {
+ thkDebugOut((DEB_WARN, "WARNING: failing - bad pointer %p\n", pv));
+ return (DWORD)E_INVALIDARG;
+ }
+ else
+ {
+ punkIn = *(IUnknown **)pv;
+ }
+ }
+ else
+ {
+ punkIn = (IUnknown *)pv;
+ }
+
+ if ((thop & THOP_IN) != 0)
+ {
+ if (punkIn == NULL)
+ {
+ vpvThis16In = 0;
+ }
+ else
+ {
+ if (!IsValidInterface(punkIn))
+ {
+ dwResult = (DWORD)E_INVALIDARG;
+ thkDebugOut((DEB_WARN, "WARNING: failing - "
+ "invalid interface %p\n", punkIn));
+ }
+ else
+ {
+ thkAssert(IIDIDX_IS_IID(iidx) ||
+ (IIDIDX_INDEX(iidx) >= 0 &&
+ IIDIDX_INDEX(iidx) < THI_COUNT));
+
+ // If the Interface is [In,Out] then we need to build a
+ // proxy with a "real" reference, rather than the
+ // "local" ref that is normally built for interfaces
+ // going [in]). Normaly only [out] parameters
+ // (which are build when the call is returning) have
+ // "real" references.
+ // To build a proxy with a "real" reference we trick
+ // "FindProxy1632" into believing it is building an
+ // [out] parameter.
+ THKSTATE thkstateSaved = pti->pThkMgr->GetThkState();
+
+ if ((thop & THOP_INOUT) == THOP_INOUT)
+ {
+ pti->pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT16);
+ }
+
+ vpvThis16In = pti->pThkMgr->FindProxy1632(NULL, punkIn, iidx,
+ NULL);
+ pti->pThkMgr->SetThkState(thkstateSaved);
+
+ if (vpvThis16In == 0)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ thkDebugOut((DEB_WARN, "WARNING: failing - "
+ "Can't create proxy for %p\n", punkIn));
+ }
+ }
+ }
+
+ thkDebugOut((DEB_ARGS, "In3216 %s %p -> %p\n",
+ IidIdxString(iidx), punkIn, vpvThis16In));
+ }
+
+ if ((thop & THOP_OUT) != 0 && SUCCEEDED(dwResult) && pv != NULL)
+ {
+ thkAssert(IIDIDX_IS_IID(iidx) ||
+ (IIDIDX_INDEX(iidx) >= 0 &&
+ IIDIDX_INDEX(iidx) < THI_COUNT));
+
+ // Preallocate a proxy for the out parameter
+ if ((ptoPreAlloc = pti->pThkMgr->CanGetNewProxy3216(iidx)) == NULL)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ thkDebugOut((DEB_WARN, "WARNING: failing - "
+ "Cannot allocate proxy\n"));
+ }
+ else
+ {
+ vpvOutParam = STACKALLOC16(sizeof(VPVOID));
+ if (vpvOutParam == 0)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ else
+ {
+ *FIXVDMPTR(vpvOutParam, VPVOID) = vpvThis16In;
+ RELVDMPTR(vpvOutParam);
+ TO_STACK16(pti, vpvOutParam, VPVOID);
+ }
+ }
+ }
+ else
+ {
+ TO_STACK16(pti, vpvThis16In, VPVOID);
+ }
+
+ if (SUCCEEDED((SCODE)dwResult))
+ {
+ // Assumes pThop is already adjusted
+ dwResult = EXECUTE_THOP3216(pti);
+ }
+
+ if (vpvThis16In != 0)
+ {
+ // Note that if the routine called keeps the proxy around
+ // it should AddRef it so this won't really remove the object
+ pti->pThkMgr->FreeProxy1632(punkIn);
+
+ if ((thop & THOP_OPMASK) == THOP_IFACECLEAN)
+ {
+ // IRpcStubBuffer::DebugServerQueryInterface returns an
+ // interface non-addref'ed
+ // IRpcStubBuffer::DebugServerRelease cleans up a returned
+ // pointer from QI, so for it we have to clean up the proxy
+ // from QI
+
+ // We're assuming that punkIn is actually a proxy
+ pti->pThkMgr->ReleaseUnreferencedProxy3216((THUNK3216OBJ *)punkIn);
+ }
+ }
+
+ if ((thop & THOP_OUT) != 0 && pv != NULL)
+ {
+ punkThis32 = NULL;
+
+ if (SUCCEEDED((SCODE)dwResult))
+ {
+ vpvThis16Out = *FIXVDMPTR(vpvOutParam, VPVOID);
+ RELVDMPTR(vpvOutParam);
+
+ // BUGBUG - No easy way to check interface validity
+ // Requires a 16-bit transition
+
+ if (vpvThis16Out != 0)
+ {
+ // Get a 32-bit proxy object for the 16-bit object
+ if (vpvOuter != 0)
+ {
+ punkThis32 =
+ pti->pThkMgr->FindAggregate3216(ptoPreAlloc, vpvOuter,
+ vpvThis16Out, iidx);
+ }
+ else
+ {
+ punkThis32 =
+ pti->pThkMgr->FindProxy3216(ptoPreAlloc,
+ vpvThis16Out, iidx,
+ NULL);
+ }
+ if (punkThis32 == NULL)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ }
+ }
+ else if (ptoPreAlloc != NULL)
+ {
+ // Return our preallocated proxy because we don't need it
+ pti->pThkMgr->FreeNewProxy3216(ptoPreAlloc, iidx);
+ }
+
+ // Set the out param
+ *(void **)pv = (void *)punkThis32;
+
+ thkDebugOut((DEB_ARGS, "Out3216 %s %p -> %p\n",
+ IidIdxString(iidx), vpvThis16Out, punkThis32));
+ }
+
+ if (vpvOutParam != 0)
+ {
+ STACKFREE16(vpvOutParam, sizeof(VPVOID));
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_IFACEGEN_3216, public
+//
+// Synopsis: Thunks riid,ppv pairs from 16->32
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_IFACEGEN_3216(THUNKINFO *pti)
+{
+ IIDIDX iidx;
+ THOP thop, thopOp, thopWeakOffset;
+ VPVOID vpvOuter;
+ IID const *piid;
+
+ thop = *pti->pThop++;
+ thopOp = thop & THOP_OPMASK;
+
+ thkAssert(thopOp == THOP_IFACEGEN ||
+ thopOp == THOP_IFACEGENOWNER);
+
+ // The current thop byte indicates how many bytes to look
+ // back in the stack to find the IID which identifies the
+ // interface being returned
+ INDEX_STACK32(pti, piid, IID const *, *pti->pThop);
+
+#if DBG == 1
+ if (!IsValidIid(*piid))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+#endif
+
+ pti->pThop++;
+
+ iidx = IidToIidIdx(*piid);
+ vpvOuter = 0;
+ if (thopOp == THOP_IFACEGENOWNER)
+ {
+ thopWeakOffset = *pti->pThop++;
+ INDEX_STACK16(pti, vpvOuter, VPVOID, thopWeakOffset, sizeof(DWORD));
+ }
+
+ return ThunkInterface3216(pti, iidx, thop, vpvOuter);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_OIFI_3216, public
+//
+// Synopsis: Convert OLEINPLACEFRAMEINFO
+//
+// Arguments: [pti] - Thunking state information
+//
+// Returns: Appropriate status code
+//
+// History: 26-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_OIFI_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ VPVOID vpoifi16;
+ OIFI16 UNALIGNED *poifi16;
+ OLEINPLACEFRAMEINFO *poifi32;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_OIFI);
+ thkAssert((*pti->pThop & THOP_IOMASK) == THOP_OUT);
+
+ // OIFIs are out-only parameters for their contents
+ // However, cb is in/out, so we need to copy cb on the way in
+ // Furthermore, cb may not be set to a valid value, in which
+ // case the documentation mentions that it should be assumed
+ // that this is an OLE 2.0 OIFI
+ // This thop simply ignores cb on the way in and always sets
+ // it to the OLE 2.0 size
+ // Since we're out-only, this always works since the number of
+ // fields we thunk is the size of the structure that we give out
+ // If OLEINPLACEFRAMEINFO is extended, this thop will break
+
+ // Assert that OLEINPLACEFRAMEINFO is what we expect it to be
+ thkAssert(sizeof(OLEINPLACEFRAMEINFO) == 20);
+
+ GET_STACK32(pti, poifi32, OLEINPLACEFRAMEINFO *);
+
+ vpoifi16 = 0;
+ if (poifi32 != NULL)
+ {
+ if (IsBadWritePtr(poifi32, sizeof(OLEINPLACEFRAMEINFO)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpoifi16 = STACKALLOC16(sizeof(OIFI16));
+ if (vpoifi16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ // OIFI's may be an out only parameters but if the "cb" field is
+ // "in" RPC doesn't slice up structs, so the whole thing is "in"
+ // as well. We are Thoping here but if we want this to match
+ // the RPC sematics then we need to copy all the fields.
+
+ poifi16 = FIXVDMPTR(vpoifi16, OIFI16);
+
+ poifi16->cb = sizeof(OIFI16);
+ poifi16->fMDIApp = (WORD)poifi32->fMDIApp;
+ poifi16->hwndFrame = HWND_16(poifi32->hwndFrame);
+ poifi16->cAccelEntries =
+ ClampULongToUShort(poifi32->cAccelEntries);
+
+ if (poifi32->haccel == NULL)
+ {
+ poifi16->haccel = NULL;
+ }
+ else
+ {
+ // WOW will clean up any dangling accelerator tables when
+ // tasks die
+ poifi16->haccel = HACCEL_16(poifi32->haccel);
+ if (poifi16->haccel == NULL)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ }
+
+ RELVDMPTR(vpoifi16);
+ }
+
+ TO_STACK16(pti, vpoifi16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (vpoifi16 != NULL)
+ {
+ poifi16 = FIXVDMPTR(vpoifi16, OIFI16);
+
+ if (SUCCEEDED(dwResult))
+ {
+ poifi32->cb = sizeof(OLEINPLACEFRAMEINFO);
+ poifi32->fMDIApp = (BOOL)poifi16->fMDIApp;
+ poifi32->hwndFrame = HWND_32(poifi16->hwndFrame);
+ poifi32->cAccelEntries = (UINT)poifi16->cAccelEntries;
+
+ if (poifi16->haccel == NULL)
+ {
+ poifi32->haccel = NULL;
+ }
+ else
+ {
+ // WOW will clean up any dangling accelerator tables when
+ // tasks die
+
+ // Check that the haccel is valid. We don't need to lock
+ // the pointer. We just want some means of validating it.
+ // HACCEL_32 faults in krnl386 if the handle is bad.
+
+ if(NULL != WOWGlobalLock16(poifi16->haccel))
+ {
+ poifi32->haccel = HACCEL_32(poifi16->haccel);
+ WOWGlobalUnlock16(poifi16->haccel);
+ }
+ else
+ {
+ poifi32->haccel = NULL;
+ }
+
+ if (poifi32->haccel == NULL)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ }
+
+#if DBG == 1
+ if (SUCCEEDED(dwResult))
+ {
+ thkDebugOut((DEB_ARGS, "Out3216 OIFI: "
+ "%p {%d, %d, 0x%04X, 0x%04X, %d} -> "
+ "%p {%d, %d, 0x%p, 0x%p, %d}\n",
+ vpoifi16, poifi16->cb, (BOOL)poifi16->fMDIApp,
+ (DWORD)poifi16->hwndFrame, (DWORD)poifi16->haccel,
+ poifi16->cAccelEntries,
+ poifi32, poifi32->cb, poifi32->fMDIApp,
+ poifi32->hwndFrame, poifi32->haccel,
+ poifi32->cAccelEntries));
+ }
+#endif
+ }
+
+ RELVDMPTR(vpoifi16);
+
+ if (FAILED(dwResult))
+ {
+ memset(poifi32, 0, sizeof(OLEINPLACEFRAMEINFO));
+ }
+
+ STACKFREE16(vpoifi16, sizeof(OIFI16));
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_STGMEDIUM_3216, public
+//
+// Synopsis: Converts 32-bit STGMEDIUM to 16-bit STGMEDIUM returned
+// structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_STGMEDIUM_3216(THUNKINFO *pti)
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+ VPVOID vpstgmedium16;
+ STGMEDIUM *lpstgmedium32;
+ DWORD dwSize;
+ SCODE sc;
+ BOOL fReleaseParam;
+ BOOL fTransferOwnership;
+ FORMATETC *pfe;
+ THOP thopFeOffset;
+ DWORD vpIStream = 0;
+ STGMEDIUM UNALIGNED *psm16;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_STGMEDIUM);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ //
+ // We currently don't have any unmodified or inout thops for STGMEDIUMs
+ //
+ thkAssert( (fThopInput || fThopOutput) &&
+ (fThopInput != fThopOutput) &&
+ "STGMEDIUM must be input or output only" );
+
+ // +2 thop byte indicates whether there's a FORMATETC to look at
+ // or not
+ // We need to reference this now before the stack is modified
+ // by argument recovery
+ thopFeOffset = *(pti->pThop+2);
+ if (thopFeOffset > 0)
+ {
+ INDEX_STACK32(pti, pfe, FORMATETC *, thopFeOffset);
+ }
+ else
+ {
+ pfe = NULL;
+ }
+
+ GET_STACK32(pti, lpstgmedium32, STGMEDIUM FAR *);
+
+ // Next thop byte indicates whether there's an ownership transfer
+ // argument or not
+ pti->pThop++;
+ fReleaseParam = (BOOL)*pti->pThop++;
+
+ if (fReleaseParam)
+ {
+ GET_STACK32(pti, fTransferOwnership, BOOL);
+ }
+ else
+ {
+ fTransferOwnership = FALSE;
+ }
+
+ // Skip FORMATETC offset thop
+ pti->pThop++;
+
+ vpstgmedium16 = 0;
+
+ if ( lpstgmedium32 != NULL )
+ {
+ if ((fThopInput && IsBadReadPtr(lpstgmedium32, sizeof(STGMEDIUM))) ||
+ (fThopOutput && IsBadWritePtr(lpstgmedium32, sizeof(STGMEDIUM))))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpstgmedium16 = STACKALLOC16(sizeof(STGMEDIUM));
+ if (vpstgmedium16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ if ( fThopInput )
+ {
+ sc = ConvertStgMed3216(pti, lpstgmedium32, vpstgmedium16,
+ pfe, fTransferOwnership, &dwSize);
+ if (SUCCEEDED(sc))
+ {
+ // Apparently if you pass TYMED_NULL into GetDataHere
+ // it's supposed to work like GetData, so switch input-only
+ // TYMED_NULLs to output
+ if (lpstgmedium32->tymed == TYMED_NULL &&
+ !fTransferOwnership)
+ {
+ fThopInput = FALSE;
+ fThopOutput = TRUE;
+ }
+ else if (lpstgmedium32->tymed == TYMED_ISTREAM)
+ {
+ //
+ // Excel has a bug in its Clipboard data object that when
+ // GetDataHere is done providing a IStream interface, it
+ // will create its own stream and pounce on the pointer
+ // being passed in. So, if the thing is input, and the
+ // TYMED is ISTREAM we need to stash away the original
+ // 16-bit stream pointer for use later.
+ //
+ psm16 = FIXVDMPTR(vpstgmedium16, STGMEDIUM);
+ vpIStream = (DWORD)psm16->pstm;
+ RELVDMPTR(vpstgmedium16);
+ }
+ }
+ else
+ {
+ STACKFREE16(vpstgmedium16, sizeof(STGMEDIUM));
+ return (DWORD)sc;
+ }
+
+ }
+ else
+ {
+ if( !((TlsThkGetAppCompatFlags() & OACF_CORELTRASHMEM) &&
+ lpstgmedium32->tymed == 0x66666666 ))
+ {
+
+ // Even though this is an out parameter, some apps
+ // (Graph 5 is one) check its values and depend on it
+ // being zeroed out
+
+ // However, if we are in CorelDraw *and* we're being
+ // called by wGetMonikerAndClassFromObject (tymed set to
+ // all 6's), then we do not want to set the tymed to zero.
+ // Corel5 relies on the memory being trashed in order to
+ // prevent paste-link-to-yourself.
+
+ memset(FIXVDMPTR(vpstgmedium16, STGMEDIUM), 0,
+ sizeof(STGMEDIUM));
+ RELVDMPTR(vpstgmedium16);
+ }
+
+ }
+ }
+
+ TO_STACK16(pti, vpstgmedium16, VPVOID);
+
+ if (fReleaseParam)
+ {
+ TO_STACK16(pti, (SHORT)fTransferOwnership, SHORT);
+ }
+
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (lpstgmedium32 != NULL)
+ {
+ if (fThopInput)
+ {
+
+ if (SUCCEEDED(dwResult) &&
+ (lpstgmedium32->tymed == TYMED_ISTREAM) &&
+ (vpIStream != 0))
+ {
+ //
+ // To continue our Excel Clipboard GetDataHere hack, if the
+ // TYMED was ISTREAM, and the medium was input (as it is now)
+ // then we need to detect the case where the IStream pointer
+ // changed. If it did change, then we have a special function
+ // in the 16-bit world that will copy the contents of the
+ // 'new' stream into 'our' stream, and release the 'new'
+ // stream. This should make the clipboard work properly.
+ //
+ psm16 = FIXVDMPTR(vpstgmedium16, STGMEDIUM);
+ if( (psm16->tymed == TYMED_ISTREAM) &&
+ (vpIStream != (DWORD)psm16->pstm))
+ {
+ BYTE b32Args[WCB16_MAX_CBARGS];
+ *(DWORD *)&b32Args[0] = vpIStream;
+ *(DWORD *)&b32Args[sizeof(DWORD)] = (DWORD)psm16->pstm;
+
+ RELVDMPTR(vpstgmedium16);
+
+ if( !CallbackTo16Ex(
+ (DWORD)gdata16Data.fnStgMediumStreamHandler16,
+ WCB16_PASCAL,
+ 2*sizeof(DWORD),
+ b32Args,
+ &dwResult) )
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+
+ }
+ else
+ {
+ //
+ // Two possibilites
+ // The stream pointers are the same. Good news
+ // The tymed was changed. Bad news. There isn't anything
+ // we can safely do with the different tymed, so ignore
+ // the whole thing.
+ //
+
+ RELVDMPTR(vpstgmedium16);
+ }
+ }
+
+
+ if (!fTransferOwnership || FAILED(dwResult))
+ {
+ sc = CleanStgMed16(pti, vpstgmedium16, lpstgmedium32,
+ dwSize, TRUE, pfe);
+ if (FAILED(sc))
+ {
+ dwResult = (DWORD)sc;
+ }
+ }
+ else if (SUCCEEDED(dwResult))
+ {
+
+ if (lpstgmedium32->pUnkForRelease == NULL)
+ {
+ sc = CleanStgMed32(pti, lpstgmedium32, vpstgmedium16,
+ 0, FALSE, pfe);
+ thkAssert(SUCCEEDED(sc));
+ }
+ }
+ }
+ else
+ {
+ thkAssert(fThopOutput);
+
+ if (SUCCEEDED(dwResult))
+ {
+ sc = ConvertStgMed1632(pti, vpstgmedium16, lpstgmedium32,
+ pfe, FALSE, &dwSize);
+ if (FAILED(sc))
+ {
+ dwResult = (DWORD)sc;
+ CallbackTo16(gdata16Data.fnReleaseStgMedium16,
+ vpstgmedium16);
+ }
+ else if (lpstgmedium32->pUnkForRelease == NULL)
+ {
+ sc = CleanStgMed16(pti, vpstgmedium16, lpstgmedium32,
+ dwSize, FALSE, pfe);
+ thkAssert(SUCCEEDED(sc));
+ }
+ }
+
+ if (FAILED(dwResult))
+ {
+ memset(lpstgmedium32, 0, sizeof(STGMEDIUM));
+ }
+ }
+ }
+
+ if (vpstgmedium16 != 0)
+ {
+ STACKFREE16(vpstgmedium16, sizeof(STGMEDIUM));
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertStatStg1632, public
+//
+// Synopsis: Converts a STATSTG
+//
+// Arguments: [pti] - Thunk info
+// [vpss16] - STATSTG
+// [pss32] - STATSTG
+// [posPreAlloc] - Preallocated string memory or NULL
+// [cchPreAlloc] - Amount preallocated
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pss32]
+//
+// History: 14-May-94 DrewB Created
+//
+// Notes: Assumes input STATSTG memory is valid
+// Assumes task memory for the string
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertStatStg1632(THUNKINFO *pti,
+ VPVOID vpss16,
+ STATSTG *pss32,
+ LPOLESTR posPreAlloc,
+ UINT cchPreAlloc)
+{
+ STATSTG UNALIGNED *pss16;
+ SCODE sc;
+ LPOLESTR pos32;
+ VPSTR vpstr;
+
+ pss16 = FIXVDMPTR(vpss16, STATSTG);
+ vpstr = (VPSTR)pss16->pwcsName;
+ RELVDMPTR(vpss16);
+
+ sc = ConvertTaskString1632(pti, vpstr,
+ posPreAlloc, cchPreAlloc,
+ &pos32);
+
+ if (SUCCEEDED(sc))
+ {
+ pss16 = FIXVDMPTR(vpss16, STATSTG);
+ memcpy(pss32, pss16, sizeof(STATSTG));
+ pss32->pwcsName = pos32;
+ RELVDMPTR(vpss16);
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_STATSTG_3216, public
+//
+// Synopsis: Converts 32-bit STATSTG to 16-bit STATSTG returned structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_STATSTG_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ STATSTG *lpstatstg32;
+ VPVOID vpstatstg16;
+ LPOLESTR lpstr32;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_STATSTG);
+
+ //
+ // We currently don't have any input thops for STATSTGs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_OUT &&
+ "STATSTG must be output only" );
+
+ GET_STACK32(pti, lpstatstg32, STATSTG FAR *);
+
+ if (IsBadWritePtr(lpstatstg32, sizeof(STATSTG)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpstatstg16 = STACKALLOC16(sizeof(STATSTG));
+ if (vpstatstg16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ lpstr32 = (LPOLESTR)TaskMalloc32(CBSTRINGPREALLOC);
+ if (lpstr32 == NULL)
+ {
+ STACKFREE16(vpstatstg16, sizeof(STATSTG));
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ TO_STACK16(pti, vpstatstg16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (SUCCEEDED(dwResult))
+ {
+ SCODE sc;
+
+ sc = ConvertStatStg1632(pti, vpstatstg16, lpstatstg32,
+ lpstr32, CWCSTRINGPREALLOC);
+ if (FAILED(sc))
+ {
+ dwResult = sc;
+ }
+ }
+
+ if (FAILED(dwResult))
+ {
+ TaskFree32(lpstr32);
+
+ memset(lpstatstg32, 0, sizeof(STATSTG));
+ }
+
+ STACKFREE16(vpstatstg16, sizeof(STATSTG));
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_DVTARGETDEVICE_3216, public
+//
+// Synopsis: Converts 16-bit DVTARGETDEVICE to 32-bit DVTARGETDEVICE
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_DVTARGETDEVICE_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ UINT uiSize;
+ DVTARGETDEVICE FAR *lpdv32;
+ VPVOID vpdv16;
+ SCODE sc;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_DVTARGETDEVICE);
+
+ //
+ // We currently don't have any output thops for DVTARGETDEVICEs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == THOP_IN &&
+ "DVTARGETDEVICE must be input only" );
+
+ //
+ // Processing for a DVTARGETDEVICE FAR * as input
+ //
+ GET_STACK32(pti, lpdv32, DVTARGETDEVICE FAR *);
+
+ vpdv16 = 0;
+
+ if ( lpdv32 != NULL )
+ {
+ sc = ConvertDvtd3216(pti, lpdv32, ArStack16, FrStack16, &vpdv16,
+ &uiSize);
+ if (FAILED(sc))
+ {
+ return (DWORD)sc;
+ }
+ }
+
+ TO_STACK16(pti, vpdv16, VPVOID);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if ( lpdv32 != NULL )
+ {
+ FrStack16((void *)vpdv16, uiSize);
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_FORMATETC_3216, public
+//
+// Synopsis: Converts 16-bit FORMATETC to 32-bit FORMATETC and back
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_FORMATETC_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ BOOL fThopInput;
+ BOOL fThopOutput;
+ VPVOID vpformatetc16;
+ FORMATETC16 UNALIGNED *lpformatetc16;
+ LPFORMATETC lpformatetc32;
+ VPVOID vpdv16;
+ SCODE sc;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_FORMATETC);
+
+ fThopInput = IS_THOP_IN(pti);
+ fThopOutput = IS_THOP_OUT(pti);
+
+ vpdv16 = 0;
+
+ //
+ // We have only input or output thops
+ //
+ thkAssert( (fThopInput || fThopOutput) &&
+ (fThopInput != fThopOutput) &&
+ "formatetc must be input or output only" );
+
+ GET_STACK32(pti, lpformatetc32, LPFORMATETC);
+
+ if ( lpformatetc32 == NULL )
+ {
+ vpformatetc16 = 0;
+ }
+ else
+ {
+ if ((fThopInput && IsBadReadPtr(lpformatetc32, sizeof(LPFORMATETC))) ||
+ (fThopOutput && IsBadWritePtr(lpformatetc32, sizeof(LPFORMATETC))))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpformatetc16 = STACKALLOC16(sizeof(FORMATETC16));
+ if (vpformatetc16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ if ( fThopInput )
+ {
+ sc = ConvertFetc3216(pti, lpformatetc32, vpformatetc16, FALSE);
+ if (FAILED(sc))
+ {
+ STACKFREE16(vpformatetc16, sizeof(FORMATETC16));
+ return (DWORD)sc;
+ }
+ }
+ else
+ {
+ thkAssert( fThopOutput );
+
+ //
+ // The below memset is needed at least for the DATA_S_SAMEFORMATETC
+ // case. This allows it to be cleaned up because all its pointers
+ // will be null.
+ //
+ lpformatetc16 = FIXVDMPTR(vpformatetc16, FORMATETC16);
+ memset(lpformatetc16, 0, sizeof(FORMATETC16) );
+ RELVDMPTR(vpformatetc16);
+ }
+ }
+
+ TO_STACK16(pti, vpformatetc16, VPVOID);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (fThopInput && vpformatetc16 != 0)
+ {
+ VPVOID vptd;
+
+ lpformatetc16 = FIXVDMPTR(vpformatetc16, FORMATETC16);
+ vptd = (VPVOID)lpformatetc16->ptd;
+ RELVDMPTR(vpformatetc16);
+
+ if (vptd != 0)
+ {
+ TaskFree16(vptd);
+ }
+ }
+
+ if ( fThopOutput && lpformatetc32 != NULL)
+ {
+ if (SUCCEEDED(dwResult))
+ {
+ sc = ConvertFetc1632(pti, vpformatetc16, lpformatetc32, TRUE);
+ if (FAILED(sc))
+ {
+ dwResult = sc;
+ }
+ }
+
+ if (FAILED(dwResult))
+ {
+ memset(lpformatetc32, 0, sizeof(FORMATETC));
+ }
+ }
+
+ if (vpformatetc16 != 0)
+ {
+ STACKFREE16(vpformatetc16, sizeof(FORMATETC16));
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_LOGPALETTE_3216, public
+//
+// Synopsis: Converts 16-bit LOGPALLETE to 32-bit LOGPALETTE
+// and converts 32-bit LOGPALETTE returned to 16-bit structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_LOGPALETTE_3216 ( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ UINT uiSize;
+ LPLOGPALETTE lplogpal32;
+ VPVOID vplogpal16;
+ LOGPALETTE UNALIGNED *lplogpal16;
+ LPLOGPALETTE *lplplogpal32;
+ VPVOID vpvplogpal16;
+ VPVOID UNALIGNED *lpvplogpal16;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_LOGPALETTE);
+
+ //
+ // It must be either an input or output LOGPALETTE
+ //
+ thkAssert( ((*pti->pThop & THOP_IOMASK) == THOP_IN ||
+ (*pti->pThop & THOP_IOMASK) == THOP_OUT) &&
+ "Hey, LOGPALETTE can't be input and output!" );
+
+ if ( (*pti->pThop & THOP_IN) != 0 )
+ {
+ //
+ // Processing for a LPLOGPALETTE as input
+ //
+ GET_STACK32(pti, lplogpal32, LPLOGPALETTE);
+
+ if ( lplogpal32 == NULL )
+ {
+ vplogpal16 = 0;
+ }
+ else
+ {
+ if (IsBadReadPtr(lplogpal32, sizeof(LOGPALETTE)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ uiSize = CBPALETTE(lplogpal32->palNumEntries);
+
+ if (IsBadReadPtr(lplogpal32, uiSize))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vplogpal16 = STACKALLOC16(uiSize);
+ if (vplogpal16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ lplogpal16 = (LOGPALETTE UNALIGNED *)
+ WOWFIXVDMPTR( vplogpal16, uiSize );
+
+ memcpy( lplogpal16, lplogpal32, uiSize );
+
+ WOWRELVDMPTR(vplogpal16);
+ }
+
+ TO_STACK16(pti, vplogpal16, VPVOID);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if ( vplogpal16 != 0 )
+ {
+ STACKFREE16(vplogpal16, uiSize);
+ }
+ }
+ else
+ {
+ //
+ // Processing for LPLPLOGPALETTE as output
+ //
+ thkAssert((*pti->pThop & THOP_OUT) != 0);
+
+ GET_STACK32(pti, lplplogpal32, LPLOGPALETTE FAR *);
+ if (IsBadWritePtr(lplplogpal32, sizeof(LPLOGPALETTE)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpvplogpal16 = (VPVOID)STACKALLOC16(sizeof(LPLOGPALETTE));
+ if (vpvplogpal16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ lplogpal32 = (LPLOGPALETTE)TaskMalloc32(CBPALETTE(NPALETTEPREALLOC));
+ if (lplogpal32 == NULL)
+ {
+ STACKFREE16(vpvplogpal16, sizeof(LPLOGPALETTE));
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ //
+ // We DO need to zero out the pointer on the way in.
+ //
+ *FIXVDMPTR(vpvplogpal16, LPLOGPALETTE) = 0;
+ RELVDMPTR(vpvplogpal16);
+
+ TO_STACK16(pti, vpvplogpal16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (SUCCEEDED(dwResult))
+ {
+ lpvplogpal16 = FIXVDMPTR( vpvplogpal16, VPVOID);
+ vplogpal16 = *lpvplogpal16;
+ RELVDMPTR(vpvplogpal16);
+
+ if ( vplogpal16 == 0 )
+ {
+ TaskFree32(lplogpal32);
+ lplogpal32 = NULL;
+ }
+ else
+ {
+ lplogpal16 = FIXVDMPTR( vplogpal16, LOGPALETTE );
+
+ //
+ // Copy the returned LOGPALETTE into 16-bit memory
+ //
+ uiSize = CBPALETTE(lplogpal16->palNumEntries);
+ if (uiSize > CBPALETTE(NPALETTEPREALLOC))
+ {
+ TaskFree32(lplogpal32);
+
+ lplogpal32 = (LPLOGPALETTE)TaskMalloc32(uiSize);
+ if ( lplogpal32 == NULL )
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ }
+
+ if (lplogpal32 != NULL)
+ {
+ memcpy( lplogpal32, lplogpal16, uiSize );
+ }
+
+ RELVDMPTR(vplogpal16);
+
+ TaskFree16( vplogpal16 );
+ }
+ }
+ else
+ {
+ TaskFree32(lplogpal32);
+ lplogpal32 = NULL;
+ }
+
+ //
+ // Update the value pointed to by the parameter on the 16-bit stack
+ //
+ *lplplogpal32 = lplogpal32;
+
+ if (vpvplogpal16 != 0)
+ {
+ STACKFREE16(vpvplogpal16, sizeof(LPLOGPALETTE));
+ }
+ }
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_CRGIID_3216, public
+//
+// Synopsis: Converts 32-bit CRGIID to 16-bit CRGIID structure
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_CRGIID_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ DWORD dwCount;
+ VPVOID vpiid16;
+ IID UNALIGNED *lpiid16;
+ IID *lpiid32;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CRGIID);
+
+ //
+ // We currently don't have any output thops for CRGIIDs
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == 0 &&
+ "CRGIID must be unmodified only" );
+
+ GET_STACK32(pti, dwCount, DWORD);
+ GET_STACK32(pti, lpiid32, IID FAR *);
+
+ if ( lpiid32 == NULL )
+ {
+ vpiid16 = 0;
+ }
+ else
+ {
+ if (IsBadReadPtr(lpiid32, dwCount*sizeof(IID)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpiid16 = STACKALLOC16( dwCount * sizeof(IID) );
+ if (vpiid16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ lpiid16 = (IID UNALIGNED *)
+ WOWFIXVDMPTR( vpiid16, dwCount*sizeof(IID) );
+
+ memcpy( lpiid16, lpiid32, dwCount*sizeof(IID) );
+
+ WOWRELVDMPTR(vpiid16);
+ }
+
+ TO_STACK16(pti, dwCount, DWORD);
+ TO_STACK16(pti, vpiid16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if ( vpiid16 != 0 )
+ {
+ STACKFREE16( vpiid16, dwCount * sizeof(IID) );
+ }
+ return( dwResult );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_INTERFACEINFO_3216, public
+//
+// Synopsis: Converts an INTERFACEINFO
+//
+// Arguments: [pti] - Thunking state information
+//
+// Returns: Appropriate status code
+//
+// History: 19-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_INTERFACEINFO_3216(THUNKINFO *pti)
+{
+ INTERFACEINFO *pii32;
+ INTERFACEINFO16 UNALIGNED *pii16;
+ VPVOID vpii16;
+ DWORD dwResult;
+ VPVOID vpunk16;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_INTERFACEINFO);
+ thkAssert((*pti->pThop & THOP_INOUT) == THOP_IN);
+
+ vpunk16 = 0;
+
+ GET_STACK32(pti, pii32, INTERFACEINFO *);
+ if (pii32 == NULL)
+ {
+ vpii16 = 0;
+ }
+ else
+ {
+ if (IsBadReadPtr(pii32, sizeof(INTERFACEINFO)))
+ {
+ return (DWORD)E_INVALIDARG;
+ }
+
+ vpii16 = STACKALLOC16(sizeof(INTERFACEINFO16));
+ if (vpii16 == 0)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ if (pii32->pUnk != NULL)
+ {
+ vpunk16 = pti->pThkMgr->FindProxy1632(NULL, pii32->pUnk,
+ INDEX_IIDIDX(THI_IUnknown),
+ NULL);
+ if (vpunk16 == 0)
+ {
+ STACKFREE16(vpii16, sizeof(INTERFACEINFO16));
+ return (DWORD)E_OUTOFMEMORY;
+ }
+ }
+
+ pii16 = FIXVDMPTR(vpii16, INTERFACEINFO16);
+ pii16->pUnk = vpunk16;
+ pii16->iid = pii32->iid;
+ pii16->wMethod = pii32->wMethod;
+
+ thkDebugOut((DEB_ARGS,
+ "In3216 INTERFACEINFO: %p -> %p {%p (%p), %s, %u}\n",
+ pii32, vpii16, pii16->pUnk, pii32->pUnk,
+ IidOrInterfaceString(&pii16->iid), pii16->wMethod));
+
+ RELVDMPTR(vpii16);
+ }
+
+ TO_STACK16(pti, vpii16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (vpunk16 != 0)
+ {
+ pti->pThkMgr->FreeProxy1632(pii32->pUnk);
+ }
+
+ if (vpii16 != 0)
+ {
+ STACKFREE16(vpii16, sizeof(INTERFACEINFO16));
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_RETURNTYPE_3216, public
+//
+// Synopsis: Thunks the return value of a call
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-94 DrewB Created
+//
+// Notes: This thunk assumes that the return value will always fit
+// in 32 bits and that the thops for it are only one thop
+// long. This fits the existing APIs and methods
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_RETURNTYPE_3216(THUNKINFO *pti)
+{
+ THOP thops[2];
+ DWORD dwResult;
+ THUNK3216OBJ *ptoPreAlloc = NULL;
+ IIDIDX iidx;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RETURNTYPE);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ pti->fResultThunked = TRUE;
+
+ pti->pThop++;
+
+ // Remember return type thop
+ thops[0] = *pti->pThop++;
+ if ((thops[0] & THOP_OPMASK) == THOP_COPY ||
+ (thops[0] & THOP_OPMASK) == THOP_IFACE ||
+ (thops[0] & THOP_OPMASK) == THOP_ALIAS32)
+ {
+ thops[1] = *pti->pThop++;
+ }
+
+ // Preallocate any necessary resources
+ switch(thops[0])
+ {
+ case THOP_IFACE | THOP_IN:
+ iidx = INDEX_IIDIDX(thops[1]);
+ if ((ptoPreAlloc = pti->pThkMgr->CanGetNewProxy3216(iidx)) == NULL)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+ break;
+ }
+
+ dwResult = EXECUTE_THOP3216(pti);
+
+ // Now that we have the return value thunk it from 16->32
+
+ switch(thops[0])
+ {
+ case THOP_COPY:
+ // Only handle DWORD copies
+ thkAssert(thops[1] == sizeof(DWORD));
+ break;
+
+ case THOP_SHORTLONG:
+ // For boolean results, not necessary to clamp
+ dwResult = (DWORD)(LONG)*(SHORT *)&dwResult;
+ break;
+
+ case THOP_IFACE | THOP_IN:
+ if (dwResult != 0)
+ {
+ // BUGBUG - What if another thop failed and returned an HRESULT?
+ // This will break
+ dwResult =
+ (DWORD)pti->pThkMgr->FindProxy3216(ptoPreAlloc, dwResult,
+ iidx, NULL);
+ thkAssert(dwResult != 0);
+
+ thkDebugOut((DEB_ARGS, "Ret3216 %s %p\n",
+ inInterfaceNames[thops[1]].pszInterface,
+ dwResult));
+ }
+ else
+ {
+ pti->pThkMgr->FreeNewProxy3216(ptoPreAlloc, iidx);
+ }
+ break;
+
+ default:
+ thkAssert(!"Unhandled 3216 return type");
+ break;
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_IFACE_3216, public
+//
+// Synopsis: Thunks a known interface pointer
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_IFACE_3216(THUNKINFO *pti)
+{
+ IIDIDX iidx;
+ THOP thop, thopOp, thopWeakOffset;
+ VPVOID vpvOuter;
+
+ thop = *pti->pThop++;
+ thopOp = thop & THOP_OPMASK;
+
+ thkAssert( thopOp == THOP_IFACE
+ || thopOp == THOP_IFACEOWNER
+ || thopOp == THOP_IFACECLEAN);
+
+ iidx = INDEX_IIDIDX(*pti->pThop++);
+ // There's a bit of a special case here in that IMalloc is
+ // not thunked so it doesn't have a real index but it's used
+ // in thop strings so it has a fake index to function as a placeholder
+ // The fake index is THI_COUNT so allow that in the assert
+ thkAssert(IIDIDX_INDEX(iidx) >= 0 && IIDIDX_INDEX(iidx) <= THI_COUNT);
+
+ vpvOuter = 0;
+ if (thopOp == THOP_IFACEOWNER)
+ {
+ // For cases where the controlling unknown is known,
+ // index back on the stack and find the 32-bit unknown
+ // pointer to use
+ thopWeakOffset = *pti->pThop++;
+
+ INDEX_STACK16(pti, vpvOuter, VPVOID, thopWeakOffset, sizeof(DWORD));
+
+ }
+
+ return ThunkInterface3216(pti, iidx, thop, vpvOuter);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_ALIAS32_3216, public
+//
+// Synopsis: Handles 16-bit aliases to 32-bit quantities
+//
+// Arguments: [pti] - Thunking state information
+//
+// Returns: Appropriate status code
+//
+// History: 27-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_ALIAS32_3216(THUNKINFO *pti)
+{
+ ALIAS alias;
+ DWORD dwValue;
+ THOP thopAction;
+ BOOL fTemporary = FALSE;
+ DWORD dwResult;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ALIAS32);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ pti->pThop++;
+
+ GET_STACK32(pti, dwValue, DWORD);
+
+ // Second byte indicates how the alias should be handled
+ thopAction = *pti->pThop++;
+
+ if (dwValue != 0)
+ {
+ switch(thopAction)
+ {
+ case ALIAS_RESOLVE:
+ alias = gAliases32.ValueAlias(dwValue);
+
+ // There may be cases where there is no existing alias
+ // for a value (for example, remoted SetMenu calls where
+ // the HOLEMENU is a temporary RPC object)
+ // so create a temporary one
+ if (alias == INVALID_ALIAS)
+ {
+ alias = gAliases32.AddValue(dwValue);
+ if (alias == INVALID_ALIAS)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ fTemporary = TRUE;
+ }
+ break;
+
+ default:
+ thkAssert(!"Default hit in Thop_ALIAS32_3216");
+ break;
+ }
+ }
+ else
+ {
+ alias = 0;
+ }
+
+ thkDebugOut((DEB_ARGS, "In3216 ALIAS32: 0x%08lX -> 0x%04X\n",
+ dwValue, alias));
+
+ TO_STACK16(pti, alias, ALIAS);
+
+ dwResult = EXECUTE_THOP3216(pti);
+
+ if (fTemporary)
+ {
+ gAliases32.RemoveAlias(alias);
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_RPCOLEMESSAGE_3216, public
+//
+// Synopsis: Converts 32-bit RPCOLEMESSAGE to 16-bit RPCOLEMESSAGE
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-94 JohannP Created
+//
+//----------------------------------------------------------------------------
+DWORD Thop_RPCOLEMESSAGE_3216( THUNKINFO *pti )
+{
+ DWORD dwResult;
+ PRPCOLEMESSAGE prom32;
+ VPVOID vprom16;
+ RPCOLEMESSAGE UNALIGNED *prom16;
+ VPVOID vpvBuffer16;
+ LPVOID lp16;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_RPCOLEMESSAGE);
+
+ //
+ // We currently have only IN/OUT RPCOLEMESSAGE
+ //
+ thkAssert( (*pti->pThop & THOP_IOMASK) == (THOP_IN | THOP_OUT) &&
+ "RPCOLEMESSAGE must be input/output only" );
+
+ vprom16 = 0;
+ vpvBuffer16 = 0;
+
+ //
+ // Processing for a RPCOLEMESSAGE FAR * as input/output
+ //
+ GET_STACK32(pti, prom32, RPCOLEMESSAGE *);
+ if ( prom32 != 0 )
+ {
+ // Copy over the input RPCOLEMESSAGE structure
+
+ vprom16 = STACKALLOC16(sizeof(RPCOLEMESSAGE));
+ if (vprom16 == NULL)
+ {
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ prom16 = FIXVDMPTR(vprom16, RPCOLEMESSAGE);
+ *prom16 = *prom32;
+ ROM_THUNK_FIELD(prom16) = (void *)prom32;
+ RELVDMPTR(vprom16);
+
+ // If there's a buffer, copy it
+ if (prom32->cbBuffer != 0)
+ {
+ vpvBuffer16 = TaskMalloc16(prom32->cbBuffer);
+ if (vpvBuffer16 == NULL)
+ {
+ STACKFREE16(vprom16, sizeof(RPCOLEMESSAGE));
+ return (DWORD)E_OUTOFMEMORY;
+ }
+
+ prom16 = FIXVDMPTR(vprom16, RPCOLEMESSAGE);
+ prom16->Buffer = (LPVOID) vpvBuffer16;
+ lp16 = (LPVOID)WOWFIXVDMPTR(vpvBuffer16, prom32->cbBuffer);
+ memcpy( lp16, prom32->Buffer, prom32->cbBuffer );
+ WOWRELVDMPTR(vpvBuffer16);
+ RELVDMPTR(vprom16);
+ }
+ }
+
+ TO_STACK16(pti, vprom16, VPVOID);
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+
+ prom16 = (PRPCOLEMESSAGE)FIXVDMPTR(vprom16, RPCOLEMESSAGE);
+ if (prom16 == NULL)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ else
+ {
+ VPVOID vpvBuffer;
+
+ vpvBuffer = (VPVOID)prom16->Buffer;
+ RELVDMPTR(vprom16);
+
+ if (SUCCEEDED(dwResult))
+ {
+ if ( prom32->Buffer != NULL )
+ {
+ lp16 = (LPVOID)WOWFIXVDMPTR(vpvBuffer, prom16->cbBuffer);
+ if (lp16 == NULL)
+ {
+ dwResult = (DWORD)E_UNEXPECTED;
+ }
+ else
+ {
+ memcpy( prom32->Buffer, lp16, prom16->cbBuffer );
+
+ WOWRELVDMPTR(vpvBuffer);
+ }
+ }
+ }
+
+ if ( vpvBuffer16 != 0 )
+ {
+ // We'd better have a buffer at this point
+ thkAssert( vpvBuffer != 0);
+
+ // Free up the buffer that we've been dealing with
+ TaskFree16(vpvBuffer);
+ }
+ }
+
+ if ( vprom16 != 0 )
+ {
+ STACKFREE16(vprom16, sizeof(RPCOLEMESSAGE));
+ }
+
+ return dwResult;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_ENUM_3216, public
+//
+// Synopsis: Thunks Enum::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is the start of a 2-byte thop. The next thop
+// byte references a function in the enumerator table, rather
+// than the standard thop table.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_ENUM_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_ENUM);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ //
+ // Get then next thop byte and execute it as a Enum thop
+ //
+ pti->pThop++;
+ return EXECUTE_ENUMTHOP3216(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CallbackProcessing_3216, public
+//
+// Synopsis: Thunks IOleObject::Draw pfnContinue & DWORD parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 3-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+typedef struct tagCallbackControl
+{
+ DWORD dwContinue;
+ LPVOID lpfn32;
+} CALLBACKCONTROL;
+
+
+STDAPI_(BOOL) CallbackProcessing_3216( DWORD dwContinue, DWORD dw1, DWORD dw2 )
+{
+ BOOL fResult;
+ CALLBACKCONTROL *lpcbc;
+ BOOL (*lpfn32)(DWORD);
+
+ lpcbc = (CALLBACKCONTROL *)dwContinue;
+
+ lpfn32 = (BOOL (*)(DWORD))lpcbc->lpfn32;
+
+ fResult = (*lpfn32)(lpcbc->dwContinue);
+
+ if ( fResult ) // This maps DWORD sized BOOLs into WORD sized BOOLs
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_CALLBACK_3216, public
+//
+// Synopsis: Thunks IOleObject::Draw pfnContinue & DWORD parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 3-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_CALLBACK_3216(THUNKINFO *pti)
+{
+ LPVOID lpfn32;
+ DWORD dwContinue;
+ CALLBACKCONTROL cbc;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CALLBACK);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ GET_STACK32(pti, lpfn32, LPVOID);
+ GET_STACK32(pti, dwContinue, DWORD);
+
+ if ( lpfn32 == 0 )
+ {
+ TO_STACK16(pti, NULL, VPVOID);
+ TO_STACK16(pti, dwContinue, DWORD);
+ }
+ else
+ {
+ cbc.lpfn32 = lpfn32;
+ cbc.dwContinue = dwContinue;
+
+ TO_STACK16(pti, gdata16Data.fnCallbackHandler, DWORD);
+ TO_STACK16(pti, (DWORD)&cbc, DWORD);
+ }
+
+ pti->pThop++;
+ return EXECUTE_THOP3216(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_CLSCONTEXT_3216, public
+//
+// Synopsis: Converts a class context flags DWORD
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 29-Jun-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_CLSCONTEXT_3216(THUNKINFO *pti)
+{
+ DWORD dwClsContext;
+
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_CLSCONTEXT);
+ thkAssert((*pti->pThop & THOP_IOMASK) == 0);
+
+ // When passing a 32-bit class context to 16-bits nothing
+ // nothing special needs to be done
+
+ GET_STACK32(pti, dwClsContext, DWORD);
+ TO_STACK16(pti, dwClsContext, DWORD);
+
+ pti->pThop++;
+ return EXECUTE_THOP3216(pti);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_FILENAME_3216, public
+//
+// Synopsis: Converts a filename string
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 24-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_FILENAME_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_FILENAME);
+
+ // Can be in or out only
+ thkAssert((*pti->pThop & THOP_IOMASK) == THOP_IN ||
+ (*pti->pThop & THOP_IOMASK) == THOP_OUT);
+
+ if ((*pti->pThop & THOP_IN) != 0)
+ {
+ // Convert filenames going from 32->16 to short filenames
+ // to avoid any possible problems with non-8.3 names.
+
+ return ThunkInString3216(pti, TRUE, 0);
+ }
+ else
+ {
+ thkAssert((*pti->pThop & THOP_OUT) != 0);
+
+ // No special processing is necessary for filenames going
+ // from 16->32 since it isn't possible for 16-bit code to
+ // generate a filename which can't be handled in 32-bits
+
+ return ThunkOutString3216(pti);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_SIZEDSTRING_3216, public
+//
+// Synopsis: Converts strings which cannot exceed a given length
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 02-Sep-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_SIZEDSTRING_3216(THUNKINFO *pti)
+{
+ thkAssert((*pti->pThop & THOP_OPMASK) == THOP_SIZEDSTRING);
+ thkAssert((*pti->pThop & THOP_IOMASK) == THOP_IN);
+
+ // Advance once to account for the length byte
+ // ThunkInString will advance again
+ pti->pThop++;
+ return ThunkInString3216(pti, FALSE, *pti->pThop);
+}
+
+#define THOP_FN(x) Thop_ ## x ## _3216
+
+DWORD (* CONST aThopFunctions3216[])(THUNKINFO *) =
+{
+
+ // x = Implemented
+ // ? = Mysteriously not needed
+ // = Left to do
+ //
+ // ^
+ // |
+ // +===+
+ // |
+ // v
+ //
+ ThunkCall3216, // x Terminating THOP
+ Thop_ShortToLong_3216, // x SHORTLONG
+ Thop_WordToDword_3216, // x WORDDWORD
+ Thop_Copy_3216, // x COPY
+ THOP_FN(LPSTR), // x LPSTR
+ THOP_FN(LPLPSTR), // x LPLPSTR
+ THOP_FN(BUFFER), // x BUFFER
+ Thop_UserHandle_3216, // x HUSER
+ Thop_GdiHandle_3216, // x HGDI
+ THOP_FN(SIZE), // x SIZE
+ THOP_FN(RECT), // x RECT
+ THOP_FN(MSG), // x MSG
+ THOP_FN(HRESULT), // x HRESULT
+ THOP_FN(STATSTG), // x STATSTG
+ THOP_FN(DVTARGETDEVICE), // x DVTARGETDEVICE
+ THOP_FN(STGMEDIUM), // x STGMEDIUM
+ THOP_FN(FORMATETC), // x FORMATETC
+ THOP_FN(HACCEL), // x HACCEL
+ THOP_FN(OIFI), // x OLEINPLACEFRAMEINFO
+ THOP_FN(BINDOPTS), // x BIND_OPTS
+ THOP_FN(LOGPALETTE), // x LOGPALETTE
+ THOP_FN(SNB), // x SNB
+ THOP_FN(CRGIID), // x CRGIID
+ Thop_ERROR_3216, // x OLESTREAM (only 16-bit)
+ THOP_FN(HTASK), // x HTASK
+ THOP_FN(INTERFACEINFO), // x INTERFACEINFO
+ THOP_FN(IFACE), // x IFACE
+ THOP_FN(IFACE), // x IFACEOWNER
+ THOP_FN(IFACE), // x IFACENOADDREF
+ THOP_FN(IFACE), // x IFACECLEAN
+ THOP_FN(IFACEGEN), // x IFACEGEN
+ THOP_FN(IFACEGEN), // x IFACEGENOWNER
+ Thop_ERROR_3216, // x ROUTINE_INDEX
+ THOP_FN(RETURNTYPE), // x RETURN_TYPE
+ THOP_FN(NULL), // x NULL
+ Thop_ERROR_3216, // x ERROR
+ THOP_FN(ENUM), // x ENUM
+ THOP_FN(CALLBACK), // x CALLBACK
+ THOP_FN(RPCOLEMESSAGE), // x RPCOLEMESSAGE
+ THOP_FN(ALIAS32), // x ALIAS32
+ THOP_FN(CLSCONTEXT), // x CLSCONTEXT
+ THOP_FN(FILENAME), // x FILENAME
+ THOP_FN(SIZEDSTRING), // x SIZEDSTRING
+};
+
+//+---------------------------------------------------------------------------
+//
+// Function: General_Enum_3216, private
+//
+// Synopsis: Thunking for standard OLE enumerator interface ::Next member
+// function.
+//
+// Arguments: [pti] - Thunk state information
+// [uiSize32] - 32-bit information size
+// [uiSize16] - 16-bit information size
+// [pfnCallback] - Data thunking callback
+// [pfnCleanup] - Thunking cleanup
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This handler is called from many IXXXEnum::Next handlers thop
+// thunks to do the standard sorts of "buffer of structures"
+// processing.
+//
+//----------------------------------------------------------------------------
+#define MAX_ALLOCA_STRUCT 5 // 16-bit stacks are precious
+
+DWORD General_Enum_3216(
+ THUNKINFO *pti,
+ UINT uiSize32,
+ UINT uiSize16,
+ SCODE (*pfnCallback)( THUNKINFO *, LPVOID, VPVOID),
+ void (*pfnCleanup)( THUNKINFO *, LPVOID, VPVOID) )
+{
+ DWORD dwResult;
+ ULONG ulCount;
+ VPVOID vpstruct16;
+ VPVOID vpfetched16;
+ LPVOID lpstruct32;
+ LPVOID lpstruct32Iterate;
+ VPVOID vpstruct16Iterate;
+ ULONG *lpfetched32;
+ ULONG UNALIGNED *lpfetched16;
+ ULONG ulFetched16;
+ ULONG ulIterate;
+ BOOL fError;
+ SCODE sc;
+ LPVOID pvArg32;
+
+ dwResult = (DWORD)S_OK;
+
+ GET_STACK32(pti, ulCount, ULONG );
+ GET_STACK32(pti, lpstruct32, LPVOID );
+ GET_STACK32(pti, lpfetched32, ULONG FAR *);
+
+ vpfetched16 = STACKALLOC16(sizeof(ULONG));
+ if (vpfetched16 == 0)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ else
+ {
+ // Zero this out so that we don't have a random value sitting
+ // underneath
+ // when bad apps like 16-bit MsWorks don't return the number of items
+ // in the returned enumeration.
+
+ lpfetched16 = FIXVDMPTR(vpfetched16, ULONG);
+ *lpfetched16 = 0;
+ RELVDMPTR(vpfetched16);
+ }
+
+ pvArg32 = NULL;
+ vpstruct16 = 0;
+
+ if ( lpstruct32 != NULL )
+ {
+ if ( ulCount == 0 )
+ {
+ dwResult = (DWORD)E_INVALIDARG;
+ }
+ else
+ {
+ if (IsBadWritePtr(lpstruct32, ulCount*uiSize32))
+ {
+ dwResult = (DWORD)E_INVALIDARG;
+ }
+ else
+ {
+ pvArg32 = lpstruct32;
+
+ if ( ulCount > MAX_ALLOCA_STRUCT )
+ {
+ vpstruct16 = WgtAllocLock( GMEM_MOVEABLE,
+ ulCount * uiSize16,
+ NULL );
+ }
+ else
+ {
+ vpstruct16 = STACKALLOC16( ulCount * uiSize16 );
+ }
+
+ if (vpstruct16 == 0)
+ {
+ dwResult = (DWORD)E_OUTOFMEMORY;
+ }
+ }
+ }
+ }
+
+ if (SUCCEEDED(dwResult))
+ {
+ TO_STACK16(pti, ulCount, ULONG);
+ TO_STACK16(pti, vpstruct16, VPVOID);
+ TO_STACK16(pti, vpfetched16, VPVOID);
+
+ pti->pThop++;
+ dwResult = EXECUTE_THOP3216(pti);
+ }
+
+ if ( SUCCEEDED(dwResult) )
+ {
+ lpfetched16 = FIXVDMPTR( vpfetched16, ULONG);
+ ulFetched16 = *lpfetched16;
+ RELVDMPTR(vpfetched16);
+
+ if ( lpstruct32 != NULL )
+ {
+ // Some apps (MsWorks3 is one) return S_FALSE and do not return
+ // the number of elements retrieved. The only thing we can
+ // do is ignore the enumeration since we don't know how many
+ // were actually set. Of course, we can't ignore all enumerations
+ // when the return is S_FALSE so we only handle the case
+ // where S_FALSE was returned on a enumeration of one element,
+ // in which we can be sure there isn't any valid data
+ if (dwResult == (DWORD)S_FALSE && ulCount == 1)
+ {
+ ulFetched16 = 0;
+ }
+
+ //
+ // Iterate through all of the structures, converting them
+ // into 16-bit
+ //
+ fError = FALSE;
+ ulIterate = 0;
+ vpstruct16Iterate = vpstruct16;
+ lpstruct32Iterate = lpstruct32;
+
+ while ( ulIterate < ulFetched16 )
+ {
+ //
+ // Callback to the callback function to do any specific
+ // processing
+ //
+ sc = (*pfnCallback)( pti, lpstruct32Iterate,
+ vpstruct16Iterate );
+
+ if ( FAILED(sc) )
+ {
+ fError = TRUE;
+ dwResult = sc;
+ }
+
+ vpstruct16Iterate = (VPVOID)((DWORD)vpstruct16Iterate +
+ uiSize16);
+ lpstruct32Iterate = (LPVOID)((DWORD)lpstruct32Iterate +
+ uiSize32);
+
+ ulIterate++;
+ }
+
+ if ( fError )
+ {
+ //
+ // Cleanup all these guys
+ //
+ ulIterate = 0;
+ vpstruct16Iterate = vpstruct16;
+ lpstruct32Iterate = lpstruct32;
+
+ while ( ulIterate <= ulFetched16 )
+ {
+ (*pfnCleanup)( pti, lpstruct32Iterate, vpstruct16Iterate );
+ vpstruct16Iterate = (VPVOID)((DWORD)vpstruct16Iterate +
+ uiSize16);
+ lpstruct32Iterate = (LPVOID)((DWORD)lpstruct32Iterate +
+ uiSize32);
+
+ ulIterate++;
+ }
+ }
+ }
+ }
+
+ if (FAILED(dwResult) && pvArg32 != NULL)
+ {
+ memset(pvArg32, 0, ulCount*uiSize32);
+ }
+
+ if ( lpfetched32 != NULL )
+ {
+ *lpfetched32 = ulFetched16;
+ }
+
+ //
+ // Free up any space we've allocated
+ //
+ if (vpstruct16 != 0)
+ {
+ if ( ulCount > MAX_ALLOCA_STRUCT )
+ {
+ WgtUnlockFree( vpstruct16 );
+ }
+ else
+ {
+ STACKFREE16( vpstruct16, ulCount * uiSize16 );
+ }
+ }
+
+ if (vpfetched16 != 0)
+ {
+ STACKFREE16(vpfetched16, sizeof(ULONG));
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_STRING_3216, public
+//
+// Synopsis: Prepares the LPOLESTR for the copy back into 16-bit address
+// space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_STRING_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ VPSTR vpstr;
+
+ *(LPOLESTR *)lp32 = NULL;
+ vpstr = *FIXVDMPTR(vp16, VPSTR);
+ RELVDMPTR(vp16);
+ return ConvertTaskString1632(pti, vpstr, NULL, 0, (LPOLESTR *)lp32);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_STRING_3216, public
+//
+// Synopsis: Cleans up the any STRINGs returned (either to 16-bit or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_STRING_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ LPOLESTR lpstr32;
+
+ lpstr32 = *(LPOLESTR *)lp32;
+ if ( lpstr32 != NULL )
+ {
+ TaskFree32( lpstr32 );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_STRING_3216, public
+//
+// Synopsis: Thunks IEnumSTRING::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_STRING_3216(THUNKINFO *pti)
+{
+ return General_Enum_3216(pti,
+ sizeof(LPOLESTR),
+ sizeof(VPSTR),
+ Callback_STRING_3216,
+ Cleanup_STRING_3216 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_UNKNOWN_3216, public
+//
+// Synopsis: Prepares the UNKNOWN structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_UNKNOWN_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ SCODE sc = S_OK;
+ VPVOID vpunknown16;
+ IUnknown *punkThis32;
+
+ vpunknown16 = *FIXVDMPTR( vp16, VPVOID );
+ RELVDMPTR(vp16);
+
+ punkThis32 = pti->pThkMgr->FindProxy3216(NULL, vpunknown16,
+ INDEX_IIDIDX(THI_IUnknown),
+ NULL);
+ if (punkThis32 == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+
+ *(LPUNKNOWN *)lp32 = (LPUNKNOWN)punkThis32;
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_UNKNOWN_3216, public
+//
+// Synopsis: Cleans up the any UNKNOWNs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_UNKNOWN_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ LPUNKNOWN lpunknown32;
+ VPVOID vpv;
+
+ lpunknown32 = *(LPUNKNOWN *)lp32;
+
+ // BUGBUG - What is the proper cleanup for IEnum<Interface>?
+ // Should the objects be released or only the proxies we
+ // created?
+ if (lpunknown32 != NULL)
+ {
+ vpv = *FIXVDMPTR(vp16, VPVOID);
+ RELVDMPTR(vp16);
+ pti->pThkMgr->FreeProxy3216(vpv);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_UNKNOWN_3216, public
+//
+// Synopsis: Thunks IEnumUNKNOWN::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_UNKNOWN_3216(THUNKINFO *pti)
+{
+ return General_Enum_3216(pti,
+ sizeof(LPUNKNOWN),
+ sizeof(LPUNKNOWN),
+ Callback_UNKNOWN_3216,
+ Cleanup_UNKNOWN_3216 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_STATSTG_3216, public
+//
+// Synopsis: Prepares the STATSTG structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_STATSTG_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ ((STATSTG *)lp32)->pwcsName = NULL;
+ return ConvertStatStg1632(pti, vp16, (STATSTG *)lp32,
+ NULL, 0);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_STATSTG_3216, public
+//
+// Synopsis: Cleans up the any STATSTGs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_STATSTG_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ STATSTG FAR *lpstatstg32;
+
+ lpstatstg32 = (STATSTG FAR *)lp32;
+
+ if ( lpstatstg32->pwcsName != NULL )
+ {
+ TaskFree32( lpstatstg32->pwcsName );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_STATSTG_3216, public
+//
+// Synopsis: Thunks IEnumSTATSTG::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_STATSTG_3216(THUNKINFO *pti)
+{
+ return General_Enum_3216(pti,
+ sizeof(STATSTG),
+ sizeof(STATSTG),
+ Callback_STATSTG_3216,
+ Cleanup_STATSTG_3216 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_FORMATETC_3216, public
+//
+// Synopsis: Prepares the FORMATETC structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_FORMATETC_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ ((FORMATETC *)lp32)->ptd = NULL;
+ return ConvertFetc1632(pti, vp16, (FORMATETC *)lp32, TRUE);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_FORMATETC_3216, public
+//
+// Synopsis: Cleans up the any FORMATETCs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_FORMATETC_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ FORMATETC FAR *lpformatetc32;
+
+ lpformatetc32 = (FORMATETC FAR *)lp32;
+
+ if ( lpformatetc32->ptd != NULL )
+ {
+ TaskFree32( lpformatetc32->ptd );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_FORMATETC_3216, public
+//
+// Synopsis: Thunks IEnumFORMATETC::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_FORMATETC_3216(THUNKINFO *pti)
+{
+ return General_Enum_3216(pti,
+ sizeof(FORMATETC),
+ sizeof(FORMATETC16),
+ Callback_FORMATETC_3216,
+ Cleanup_FORMATETC_3216 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_STATDATA_3216, public
+//
+// Synopsis: Prepares the STATDATA structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+SCODE Callback_STATDATA_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ SCODE sc;
+ LPSTATDATA lpstatdata32;
+ STATDATA16 UNALIGNED *lpstatdata16;
+ LPADVISESINK lpadv32;
+ VPVOID vpadv16;
+ IUnknown *punkThis32;
+
+ sc = S_OK;
+
+ lpstatdata32 = (LPSTATDATA)lp32;
+
+ lpstatdata16 = FIXVDMPTR( vp16, STATDATA16 );
+ vpadv16 = lpstatdata16->pAdvSink;
+ RELVDMPTR(vp16);
+
+ if ( vpadv16 != 0)
+ {
+ // We don't know whether it's an AdviseSink or
+ // an AdviseSink2, so pass AdviseSink2 since it's
+ // a superset of AdviseSink and will work for both
+
+ punkThis32 =
+ pti->pThkMgr->FindProxy3216(NULL, vpadv16,
+ INDEX_IIDIDX(THI_IAdviseSink2),
+ NULL);
+ if (punkThis32 == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+
+ lpadv32 = (LPADVISESINK)punkThis32;
+ }
+ else
+ {
+ lpadv32 = NULL;
+ }
+
+ lpstatdata32->formatetc.ptd = NULL;
+ if (SUCCEEDED(sc))
+ {
+ // If this fails the AdviseSink proxy will be cleaned up in
+ // the cleanup function later
+
+ sc = ConvertFetc1632(pti,
+ vp16+FIELD_OFFSET(STATDATA16, formatetc),
+ &lpstatdata32->formatetc, TRUE);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ lpstatdata16 = FIXVDMPTR( vp16, STATDATA16 );
+ lpstatdata32->advf = lpstatdata16->advf;
+ lpstatdata32->pAdvSink = lpadv32;
+ lpstatdata32->dwConnection = lpstatdata16->dwConnection;
+ RELVDMPTR(vp16);
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_STATDATA_3216, public
+//
+// Synopsis: Cleans up the any STATDATAs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_STATDATA_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ STATDATA FAR *lpstatdata32;
+ VPVOID vpvSink;
+
+ lpstatdata32 = (STATDATA FAR *)lp32;
+
+ if ( lpstatdata32->formatetc.ptd != NULL )
+ {
+ TaskFree32( lpstatdata32->formatetc.ptd );
+ }
+
+ if ( lpstatdata32->pAdvSink != NULL )
+ {
+ // BUGBUG - What is the proper cleanup for interfaces?
+ // Should the objects be released or only the proxies we
+ // created?
+ vpvSink = (FIXVDMPTR( vp16, STATDATA16 ))->pAdvSink;
+ RELVDMPTR(vp16);
+
+ pti->pThkMgr->FreeProxy3216(vpvSink);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_STATDATA_3216, public
+//
+// Synopsis: Thunks IEnumSTATDATA::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_STATDATA_3216(THUNKINFO *pti)
+{
+ return General_Enum_3216(pti,
+ sizeof(STATDATA),
+ sizeof(STATDATA16),
+ Callback_STATDATA_3216,
+ Cleanup_STATDATA_3216 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_MONIKER_3216, public
+//
+// Synopsis: Prepares the MONIKER structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_MONIKER_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ VPVOID vpmoniker16;
+ IUnknown *punkThis32;
+ SCODE sc = S_OK;
+
+ vpmoniker16 = *FIXVDMPTR( vp16, VPVOID );
+ RELVDMPTR(vp16);
+
+ punkThis32 = pti->pThkMgr->FindProxy3216(NULL, vpmoniker16,
+ INDEX_IIDIDX(THI_IMoniker),
+ NULL);
+ if (punkThis32 == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+
+ *(LPMONIKER *)lp32 = (LPMONIKER)punkThis32;
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_MONIKER_3216, public
+//
+// Synopsis: Cleans up the any MONIKERs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_MONIKER_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ LPMONIKER lpmoniker32;
+ VPVOID vpv;
+
+ lpmoniker32 = *(LPMONIKER *)lp32;
+
+ // BUGBUG - What is the proper cleanup for IEnum<Interface>?
+ // Should the objects be released or only the proxies we
+ // created?
+ if (lpmoniker32 != NULL)
+ {
+ vpv = *FIXVDMPTR(vp16, VPVOID);
+ RELVDMPTR(vp16);
+ pti->pThkMgr->FreeProxy3216(vpv);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_MONIKER_3216, public
+//
+// Synopsis: Thunks IEnumMONIKER::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_MONIKER_3216(THUNKINFO *pti)
+{
+ return General_Enum_3216(pti,
+ sizeof(LPMONIKER),
+ sizeof(LPMONIKER),
+ Callback_MONIKER_3216,
+ Cleanup_MONIKER_3216 );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Callback_OLEVERB_3216, public
+//
+// Synopsis: Prepares the OLEVERB structure for the copy back into 16-bit
+// address space.
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: SCODE indicating success/failure
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Callback_OLEVERB_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ SCODE sc;
+ OLEVERB *lpoleverb32;
+ OLEVERB UNALIGNED *lpoleverb16;
+ VPSTR vpstr;
+
+ lpoleverb32 = (LPOLEVERB)lp32;
+
+ lpoleverb16 = FIXVDMPTR(vp16, OLEVERB);
+ vpstr = (VPSTR)lpoleverb16->lpszVerbName;
+ RELVDMPTR(vp16);
+
+ lpoleverb32->lpszVerbName = NULL;
+ sc = ConvertTaskString1632(pti, vpstr, NULL, 0,
+ &lpoleverb32->lpszVerbName);
+ if (SUCCEEDED(sc))
+ {
+ lpoleverb16 = FIXVDMPTR(vp16, OLEVERB);
+ lpoleverb32->lVerb = lpoleverb16->lVerb;
+ lpoleverb32->fuFlags = lpoleverb16->fuFlags;
+ lpoleverb32->grfAttribs = lpoleverb16->grfAttribs;
+ RELVDMPTR(vp16);
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Cleanup_OLEVERB_3216, public
+//
+// Synopsis: Cleans up the any OLEVERBs returned (either to 16-bit
+// or 32-bit)
+//
+// Arguments: [pti] - Thunking state information
+// [lp32] - Pointer to 32-bit output structure
+// [lp16] - Pointer to 16-bit returned structure
+//
+// Returns: nothing, should NEVER fail
+//
+// History: 1-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+void Cleanup_OLEVERB_3216( THUNKINFO *pti, LPVOID lp32, VPVOID vp16 )
+{
+ OLEVERB FAR *lpoleverb32;
+
+ lpoleverb32 = (LPOLEVERB)lp32;
+
+ if ( lpoleverb32->lpszVerbName != NULL )
+ {
+ TaskFree32( lpoleverb32->lpszVerbName );
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Thop_Enum_OLEVERB_3216, public
+//
+// Synopsis: Thunks IEnumOLEVERB::Next parameters
+//
+// Arguments: [pti] - Thunk state information
+//
+// Returns: Appropriate status code
+//
+// History: 1-Mar-94 BobDay Created
+//
+// Notes: This thunk is 2nd part of a 2-byte thop.
+//
+//----------------------------------------------------------------------------
+
+DWORD Thop_Enum_OLEVERB_3216(THUNKINFO *pti)
+{
+ return General_Enum_3216(pti,
+ sizeof(OLEVERB),
+ sizeof(OLEVERB),
+ Callback_OLEVERB_3216,
+ Cleanup_OLEVERB_3216 );
+}
+
+#define THOP_EFN(x) Thop_Enum_ ## x ## _3216
+
+DWORD (*CONST aThopEnumFunctions3216[])(THUNKINFO *) =
+{
+ THOP_EFN(STRING), // STRING
+ THOP_EFN(UNKNOWN), // UNKNOWN
+ THOP_EFN(STATSTG), // STATSTG
+ THOP_EFN(FORMATETC), // FORMATETC
+ THOP_EFN(STATDATA), // STATDATA
+ THOP_EFN(MONIKER), // MONIKER
+ THOP_EFN(OLEVERB), // OLEVERB
+};
+
+
diff --git a/private/ole32/olethunk/olethk32/thopapi.hxx b/private/ole32/olethunk/olethk32/thopapi.hxx
new file mode 100644
index 000000000..f4bcf22d4
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thopapi.hxx
@@ -0,0 +1,37 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thopapi.hxx
+//
+// Contents: API thops header
+//
+// History: 22-Feb-94 DrewB Created
+//
+// Notes: This file declares generated tables found in
+// thtblapi.cxx
+//
+//----------------------------------------------------------------------------
+
+#ifndef __THOPAPI_HXX__
+#define __THOPAPI_HXX__
+
+// These are declared extern "C" because there was a bug in the
+// PPC compiler (aug '95) where the const related decorations on
+// the global data symbols was not done consistantly. By using
+// extern "C" the bug is simply avoided.
+
+extern "C" THOP CONST * CONST apthopsApiThops[];
+extern VTBLFN CONST apfnApiFunctions[];
+
+// These two routines aren't in the public headers but are needed
+// in vtblapi.cxx
+STDAPI ReadOleStg
+ (LPSTORAGE pstg, DWORD FAR* pdwFlags, DWORD FAR* pdwOptUpdate,
+ DWORD FAR* pdwReserved, LPMONIKER FAR* ppmk, LPSTREAM FAR* ppstmOut);
+STDAPI WriteOleStg
+ (LPSTORAGE pstg, IOleObject FAR* pOleObj,
+ DWORD dwReserved, LPSTREAM FAR* ppstmOut);
+
+#endif // #ifndef __THOPAPI_HXX__
diff --git a/private/ole32/olethunk/olethk32/thopiint.cxx b/private/ole32/olethunk/olethk32/thopiint.cxx
new file mode 100644
index 000000000..f979594cf
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thopiint.cxx
@@ -0,0 +1,83 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thopiint.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include "thopsint.cxx"
+#include "thtblint.cxx"
+#include "vtblifn.cxx"
+#include "vtblint.cxx"
+#include "fntomthd.cxx"
+
+THOPI CONST athopiInterfaceThopis[] =
+{
+ apthopsIUnknown, 3, tfnIUnknown, NULL
+, apthopsIClassFactory, 5, tfnIClassFactory, ftmIClassFactory
+, apthopsIMarshal, 9, tfnIMarshal, ftmIMarshal
+, apthopsIStdMarshalInfo, 4, tfnIStdMarshalInfo, ftmIStdMarshalInfo
+, apthopsIMessageFilter, 6, tfnIMessageFilter, ftmIMessageFilter
+, apthopsIExternalConnection, 5, tfnIExternalConnection, ftmIExternalConnection
+, apthopsIEnumString, 7, tfnIEnumString, ftmIEnumString
+, apthopsIEnumUnknown, 7, tfnIEnumUnknown, ftmIEnumUnknown
+, apthopsIEnumSTATSTG, 7, tfnIEnumSTATSTG, ftmIEnumSTATSTG
+, apthopsILockBytes, 10, tfnILockBytes, ftmILockBytes
+, apthopsIStream, 14, tfnIStream, ftmIStream
+, apthopsIStorage, 18, tfnIStorage, ftmIStorage
+, apthopsIRootStorage, 4, tfnIRootStorage, ftmIRootStorage
+, apthopsIEnumFORMATETC, 7, tfnIEnumFORMATETC, ftmIEnumFORMATETC
+, apthopsIEnumSTATDATA, 7, tfnIEnumSTATDATA, ftmIEnumSTATDATA
+, apthopsIDataObject, 12, tfnIDataObject, ftmIDataObject
+, apthopsIViewObject, 9, tfnIViewObject, ftmIViewObject
+, apthopsIViewObject2, 10, tfnIViewObject2, ftmIViewObject2
+, apthopsIAdviseSink, 8, tfnIAdviseSink, ftmIAdviseSink
+, apthopsIAdviseSink2, 9, tfnIAdviseSink2, ftmIAdviseSink2
+, apthopsIDataAdviseHolder, 7, tfnIDataAdviseHolder, ftmIDataAdviseHolder
+, apthopsIOleCache, 8, tfnIOleCache, ftmIOleCache
+, apthopsIOleCache2, 10, tfnIOleCache2, ftmIOleCache2
+, apthopsIOleCacheControl, 5, tfnIOleCacheControl, ftmIOleCacheControl
+, apthopsIDropTarget, 7, tfnIDropTarget, ftmIDropTarget
+, apthopsIDropSource, 5, tfnIDropSource, ftmIDropSource
+, apthopsIPersist, 4, tfnIPersist, ftmIPersist
+, apthopsIPersistStorage, 10, tfnIPersistStorage, ftmIPersistStorage
+, apthopsIPersistStream, 8, tfnIPersistStream, ftmIPersistStream
+, apthopsIPersistFile, 9, tfnIPersistFile, ftmIPersistFile
+, apthopsIBindCtx, 13, tfnIBindCtx, ftmIBindCtx
+, apthopsIMoniker, 23, tfnIMoniker, ftmIMoniker
+, apthopsIRunningObjectTable, 10, tfnIRunningObjectTable, ftmIRunningObjectTable
+, apthopsIEnumMoniker, 7, tfnIEnumMoniker, ftmIEnumMoniker
+, apthopsIEnumOLEVERB, 7, tfnIEnumOLEVERB, ftmIEnumOLEVERB
+, apthopsIOleObject, 24, tfnIOleObject, ftmIOleObject
+, apthopsIOleClientSite, 9, tfnIOleClientSite, ftmIOleClientSite
+, apthopsIRunnableObject, 8, tfnIRunnableObject, ftmIRunnableObject
+, apthopsIParseDisplayName, 4, tfnIParseDisplayName, ftmIParseDisplayName
+, apthopsIOleContainer, 6, tfnIOleContainer, ftmIOleContainer
+, apthopsIOleItemContainer, 9, tfnIOleItemContainer, ftmIOleItemContainer
+, apthopsIOleAdviseHolder, 9, tfnIOleAdviseHolder, ftmIOleAdviseHolder
+, apthopsIOleLink, 14, tfnIOleLink, ftmIOleLink
+, apthopsIOleWindow, 5, tfnIOleWindow, ftmIOleWindow
+, apthopsIOleInPlaceObject, 9, tfnIOleInPlaceObject, ftmIOleInPlaceObject
+, apthopsIOleInPlaceActiveObject, 10, tfnIOleInPlaceActiveObject, ftmIOleInPlaceActiveObject
+, apthopsIOleInPlaceUIWindow, 9, tfnIOleInPlaceUIWindow, ftmIOleInPlaceUIWindow
+, apthopsIOleInPlaceFrame, 15, tfnIOleInPlaceFrame, ftmIOleInPlaceFrame
+, apthopsIOleInPlaceSite, 15, tfnIOleInPlaceSite, ftmIOleInPlaceSite
+, apthopsIRpcChannelBuffer, 8, tfnIRpcChannelBuffer, ftmIRpcChannelBuffer
+, apthopsIRpcProxyBuffer, 5, tfnIRpcProxyBuffer, ftmIRpcProxyBuffer
+, apthopsIRpcStubBuffer, 10, tfnIRpcStubBuffer, ftmIRpcStubBuffer
+, apthopsIPSFactoryBuffer, 5, tfnIPSFactoryBuffer, ftmIPSFactoryBuffer
+, apthopsIRpcChannel, 7, tfnIRpcChannel, ftmIRpcChannel
+, apthopsIRpcProxy, 5, tfnIRpcProxy, ftmIRpcProxy
+, apthopsIRpcStub, 8, tfnIRpcStub, ftmIRpcStub
+, apthopsIPSFactory, 5, tfnIPSFactory, ftmIPSFactory
+};
diff --git a/private/ole32/olethunk/olethk32/thopint.hxx b/private/ole32/olethunk/olethk32/thopint.hxx
new file mode 100644
index 000000000..5d5eea987
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thopint.hxx
@@ -0,0 +1,39 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thopint.hxx
+//
+// Contents: Interface thops header file
+//
+// History: 22-Feb-94 DrewB Created
+//
+// Notes: This file declares generated tables found in
+// thtblint.cxx
+//
+//----------------------------------------------------------------------------
+
+#ifndef __THOPINT_HXX__
+#define __THOPINT_HXX__
+
+typedef DWORD (*THUNK3216FN)(THUNK3216OBJ *ptoThis);
+
+typedef struct tagTHOPI
+{
+ THOP CONST * CONST * ppThops;
+ UINT uiSize;
+ THUNK3216FN CONST * pt3216fn;
+ BYTE CONST * pftm;
+} THOPI;
+
+typedef struct tagIIDTOTHI
+{
+ IID CONST * piid;
+ int iThi;
+} IIDTOTHI;
+
+extern THOPI CONST athopiInterfaceThopis[];
+extern IIDTOTHI CONST aittIidToThi[];
+
+#endif // #ifndef __THOPINT_HXX__
diff --git a/private/ole32/olethunk/olethk32/thopsapi.cxx b/private/ole32/olethunk/olethk32/thopsapi.cxx
new file mode 100644
index 000000000..5493fb3d9
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thopsapi.cxx
@@ -0,0 +1,427 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thopsapi.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+THOP CONST thopsCoInitialize[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMalloc, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCoUninitialize[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 6
+};
+THOP CONST thopsCoGetClassObject[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_CLSCONTEXT, THOP_NULL | THOP_IN, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsCoRegisterClassObject[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_CLSCONTEXT, THOP_COPY, 4, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsCoRevokeClassObject[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCoMarshalInterface[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_IN, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsCoUnmarshalInterface[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsCoReleaseMarshalData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCoDisconnectObject[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCoLockObjectExternal[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_SHORTLONG, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsCoGetStandardMarshal[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IMarshal, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsCoIsHandlerConnected[] =
+{
+ THOP_RETURNTYPE, THOP_SHORTLONG, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCoFreeAllLibraries[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 6
+};
+THOP CONST thopsCoFreeUnusedLibraries[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 6
+};
+THOP CONST thopsCoCreateInstance[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_CLSCONTEXT, THOP_COPY | THOP_IN, 16, THOP_IFACEGENOWNER | THOP_OUT, 4, 12, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsCLSIDFromString[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCoIsOle1Class[] =
+{
+ THOP_RETURNTYPE, THOP_SHORTLONG, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsProgIDFromCLSID[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_LPLPSTR, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCLSIDFromProgID[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCoCreateGuid[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCoFileTimeToDosDateTime[] =
+{
+ THOP_RETURNTYPE, THOP_SHORTLONG, THOP_COPY | THOP_IN, 8, THOP_WORDDWORD | THOP_OUT, THOP_WORDDWORD | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsCoDosDateTimeToFileTime[] =
+{
+ THOP_RETURNTYPE, THOP_SHORTLONG, THOP_WORDDWORD, THOP_WORDDWORD, THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 8
+};
+THOP CONST thopsCoFileTimeNow[] =
+{
+ THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCoRegisterMessageFilter[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMessageFilter, THOP_IFACE | THOP_OUT, THI_IMessageFilter, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCoGetTreatAsClass[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCoTreatAsClass[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsDllGetClassObject[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsStgCreateDocfile[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsStgCreateDocfileOnILockBytes[] =
+{
+ THOP_IFACE | THOP_IN, THI_ILockBytes, THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsStgOpenStorage[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY, 4, THOP_SNB, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsStgOpenStorageOnILockBytes[] =
+{
+ THOP_IFACE | THOP_IN, THI_ILockBytes, THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY, 4, THOP_SNB, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsStgIsStorageFile[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsStgIsStorageILockBytes[] =
+{
+ THOP_IFACE | THOP_IN, THI_ILockBytes, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsStgSetTimes[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY | THOP_IN, 8, THOP_COPY | THOP_IN, 8, THOP_COPY | THOP_IN, 8, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsCreateDataAdviseHolder[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IDataAdviseHolder, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCreateDataCache[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_IN, 16, THOP_IFACEGENOWNER | THOP_OUT, 4, 12, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsBindMoniker[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY, 4, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsMkParseDisplayName[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsMonikerRelativePathTo[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsMonikerCommonPrefixWith[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsCreateBindCtx[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IBindCtx, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCreateGenericComposite[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsGetClassFile[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCreateFileMoniker[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsCreateItemMoniker[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsCreateAntiMoniker[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsCreatePointerMoniker[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsGetRunningObjectTable[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IRunningObjectTable, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsReadClassStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsWriteClassStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsReadClassStm[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsWriteClassStm[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsWriteFmtUserTypeStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_WORDDWORD, THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 19
+};
+THOP CONST thopsReadFmtUserTypeStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_WORDDWORD | THOP_OUT, THOP_LPLPSTR, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsOleInitialize[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMalloc, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleUninitialize[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 6
+};
+THOP CONST thopsOleQueryLinkFromData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleQueryCreateFromData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleCreate[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_FORMATETC | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACEGEN | THOP_OUT, 20, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsOleCreateFromData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_FORMATETC | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACEGEN | THOP_OUT, 20, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsOleCreateLinkFromData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_FORMATETC | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACEGEN | THOP_OUT, 20, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsOleCreateStaticFromData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_FORMATETC | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACEGEN | THOP_OUT, 20, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsOleCreateLink[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_FORMATETC | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACEGEN | THOP_OUT, 20, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsOleCreateLinkToFile[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_FORMATETC | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACEGEN | THOP_OUT, 20, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsOleCreateFromFile[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_LPSTR | THOP_IN, THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_FORMATETC | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACEGEN | THOP_OUT, 20, THOP_END,
+ THOP_ROUTINEINDEX, 20
+};
+THOP CONST thopsOleLoad[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_IFACEGEN | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsOleSave[] =
+{
+ THOP_IFACE | THOP_IN, THI_IPersistStorage, THOP_IFACE | THOP_IN, THI_IStorage, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsOleLoadFromStream[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsOleSaveToStream[] =
+{
+ THOP_IFACE | THOP_IN, THI_IPersistStream, THOP_IFACE | THOP_IN, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsOleSetContainedObject[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsOleNoteObjectVisible[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsRegisterDragDrop[] =
+{
+ THOP_HUSER, THOP_IFACE | THOP_IN, THI_IDropTarget, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsRevokeDragDrop[] =
+{
+ THOP_HUSER, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsDoDragDrop[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_IFACE | THOP_IN, THI_IDropSource, THOP_COPY, 4, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsOleSetClipboard[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleGetClipboard[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleFlushClipboard[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 6
+};
+THOP CONST thopsOleIsCurrentClipboard[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleCreateMenuDescriptor[] =
+{
+ THOP_RETURNTYPE, THOP_ALIAS32, ALIAS_CREATE, THOP_HUSER, THOP_COPY | THOP_IN, 24, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsOleSetMenuDescriptor[] =
+{
+ THOP_ALIAS32, ALIAS_RESOLVE, THOP_HUSER, THOP_HUSER, THOP_IFACE | THOP_IN, THI_IOleInPlaceFrame, THOP_IFACE | THOP_IN, THI_IOleInPlaceActiveObject, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsOleDestroyMenuDescriptor[] =
+{
+ THOP_ALIAS32, ALIAS_REMOVE, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleDraw[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY, 4, THOP_HGDI, THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsOleRun[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleIsRunning[] =
+{
+ THOP_RETURNTYPE, THOP_SHORTLONG, THOP_IFACE | THOP_IN, THI_IOleObject, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleLockRunning[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_SHORTLONG, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsCreateOleAdviseHolder[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IOleAdviseHolder, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsOleCreateDefaultHandler[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY | THOP_IN, 16, THOP_IFACEGENOWNER | THOP_OUT, 4, 8, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsOleCreateEmbeddingHelper[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IClassFactory, THOP_COPY | THOP_IN, 16, THOP_IFACEGENOWNER | THOP_OUT, 4, 16, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsOleRegGetUserType[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_LPLPSTR, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsOleRegGetMiscStatus[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsOleRegEnumFormatEtc[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IEnumFORMATETC, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsOleRegEnumVerbs[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_OUT, THI_IEnumOLEVERB, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsOleConvertIStorageToOLESTREAM[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_OLESTREAM | THOP_INOUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsOleConvertOLESTREAMToIStorage[] =
+{
+ THOP_OLESTREAM | THOP_INOUT, THOP_IFACE | THOP_IN, THI_IStorage, THOP_DVTARGETDEVICE | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsOleConvertIStorageToOLESTREAMEx[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_WORDDWORD, THOP_COPY, 4, THOP_COPY, 4, THOP_COPY, 4, THOP_STGMEDIUM | THOP_IN, 0, 0, THOP_OLESTREAM | THOP_INOUT, THOP_END, THOP_ROUTINEINDEX, 21
+};
+THOP CONST thopsOleConvertOLESTREAMToIStorageEx[] =
+{
+ THOP_OLESTREAM | THOP_INOUT, THOP_IFACE | THOP_IN, THI_IStorage, THOP_WORDDWORD | THOP_OUT, THOP_COPY | THOP_OUT, 4, THOP_COPY | THOP_OUT, 4, THOP_COPY | THOP_OUT, 4, THOP_STGMEDIUM | THOP_IN, 0, 0, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsOleDoAutoConvert[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsOleGetAutoConvert[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsOleSetAutoConvert[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsGetConvertStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsSetConvertStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsReadOleStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY | THOP_OUT, 4, THOP_COPY | THOP_OUT, 4, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsWriteOleStg[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_IFACE | THOP_IN, THI_IOleObject, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 2
+};
diff --git a/private/ole32/olethunk/olethk32/thopsint.cxx b/private/ole32/olethunk/olethk32/thopsint.cxx
new file mode 100644
index 000000000..9b0a06cf1
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thopsint.cxx
@@ -0,0 +1,1313 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thopsint.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+THOP CONST thopsIClassFactory_CreateInstance[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY | THOP_IN, 16, THOP_IFACEGENOWNER | THOP_OUT, 4, 8, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIClassFactory_LockServer[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMarshal_GetUnmarshalClass[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_IN, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY, 4, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIMarshal_GetMarshalSizeMax[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_IN, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY, 4, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIMarshal_MarshalInterface[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_IN, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIMarshal_UnmarshalInterface[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIMarshal_ReleaseMarshalData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMarshal_DisconnectObject[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIStdMarshalInfo_GetClassForHandler[] =
+{
+ THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIMessageFilter_HandleInComingCall[] =
+{
+ THOP_RETURNTYPE, THOP_COPY, 4, THOP_COPY, 4, THOP_HTASK, THOP_COPY, 4, THOP_INTERFACEINFO | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIMessageFilter_RetryRejectedCall[] =
+{
+ THOP_RETURNTYPE, THOP_COPY, 4, THOP_HTASK, THOP_COPY, 4, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIMessageFilter_MessagePending[] =
+{
+ THOP_RETURNTYPE, THOP_COPY, 4, THOP_HTASK, THOP_COPY, 4, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIExternalConnection_AddConnection[] =
+{
+ THOP_RETURNTYPE, THOP_COPY, 4, THOP_COPY, 4, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIExternalConnection_ReleaseConnection[] =
+{
+ THOP_RETURNTYPE, THOP_COPY, 4, THOP_COPY, 4, THOP_COPY, 4, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumString_Next[] =
+{
+ THOP_ENUM, THE_IEnumString, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumString_Skip[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumString_Reset[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIEnumString_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumString, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumUnknown_Next[] =
+{
+ THOP_ENUM, THE_IEnumUnknown, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumUnknown_Skip[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumUnknown_Reset[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIEnumUnknown_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumSTATSTG_Next[] =
+{
+ THOP_ENUM, THE_IEnumSTATSTG, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumSTATSTG_Skip[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumSTATSTG_Reset[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIEnumSTATSTG_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATSTG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+
+// Note: THOP_BUFFER | THOP_OUT takes care of the size of the input buffer
+// and the size of the output buffer.
+THOP CONST thopsILockBytes_ReadAt[] =
+{
+ THOP_COPY, 8, THOP_BUFFER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 9
+};
+THOP CONST thopsILockBytes_WriteAt[] =
+{
+ THOP_COPY, 8, THOP_BUFFER | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 9
+};
+THOP CONST thopsILockBytes_Flush[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsILockBytes_SetSize[] =
+{
+ THOP_COPY, 8, THOP_END, THOP_ROUTINEINDEX, 10
+};
+THOP CONST thopsILockBytes_LockRegion[] =
+{
+ THOP_COPY, 8, THOP_COPY, 8, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 11
+};
+THOP CONST thopsILockBytes_UnlockRegion[] =
+{
+ THOP_COPY, 8, THOP_COPY, 8, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 11
+};
+THOP CONST thopsILockBytes_Stat[] =
+{
+ THOP_STATSTG | THOP_OUT, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+
+// Note: THOP_BUFFER | THOP_OUT takes care of the size of the input buffer
+// and the size of the output buffer.
+THOP CONST thopsIStream_Read[] =
+{
+ THOP_BUFFER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 2
+};
+
+THOP CONST thopsIStream_Write[] =
+{
+ THOP_BUFFER | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIStream_Seek[] =
+{
+ THOP_COPY, 8, THOP_COPY, 4, THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 12
+};
+THOP CONST thopsIStream_SetSize[] =
+{
+ THOP_COPY, 8, THOP_END, THOP_ROUTINEINDEX, 10
+};
+THOP CONST thopsIStream_CopyTo[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY, 8, THOP_COPY | THOP_OUT, 8, THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 13
+};
+THOP CONST thopsIStream_Commit[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIStream_Revert[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIStream_LockRegion[] =
+{
+ THOP_COPY, 8, THOP_COPY, 8, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 11
+};
+THOP CONST thopsIStream_UnlockRegion[] =
+{
+ THOP_COPY, 8, THOP_COPY, 8, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 11
+};
+THOP CONST thopsIStream_Stat[] =
+{
+ THOP_STATSTG | THOP_OUT, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIStream_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIStorage_CreateStream[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY, 4, THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIStorage_OpenStream[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_NULL | THOP_IN, THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIStorage_CreateStorage[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY, 4, THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIStorage_OpenStorage[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_IN, THI_IStorage, THOP_COPY, 4, THOP_SNB, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIStorage_CopyTo[] =
+{
+ THOP_CRGIID, THOP_SNB, THOP_IFACE | THOP_IN, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIStorage_MoveElementTo[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_IN, THI_IStorage, THOP_LPSTR | THOP_IN, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIStorage_Commit[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIStorage_Revert[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIStorage_EnumElements[] =
+{
+ THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IEnumSTATSTG, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIStorage_DestroyElement[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIStorage_RenameElement[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIStorage_SetElementTimes[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY | THOP_IN, 8, THOP_COPY | THOP_IN, 8, THOP_COPY | THOP_IN, 8, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIStorage_SetClass[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIStorage_SetStateBits[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIStorage_Stat[] =
+{
+ THOP_STATSTG | THOP_OUT, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRootStorage_SwitchToFile[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumFORMATETC_Next[] =
+{
+ THOP_ENUM, THE_IEnumFORMATETC, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumFORMATETC_Skip[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumFORMATETC_Reset[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIEnumFORMATETC_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumFORMATETC, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumSTATDATA_Next[] =
+{
+ THOP_ENUM, THE_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumSTATDATA_Skip[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumSTATDATA_Reset[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIEnumSTATDATA_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIDataObject_GetData[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_STGMEDIUM | THOP_OUT, 0, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIDataObject_GetDataHere[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_STGMEDIUM | THOP_IN, 0, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIDataObject_QueryGetData[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIDataObject_GetCanonicalFormatEtc[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_FORMATETC | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIDataObject_SetData[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_STGMEDIUM | THOP_IN, 1, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIDataObject_EnumFormatEtc[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IEnumFORMATETC, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIDataObject_DAdvise[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IAdviseSink, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIDataObject_DUnadvise[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIDataObject_EnumDAdvise[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIViewObject_Draw[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_DVTARGETDEVICE | THOP_IN, THOP_HGDI, THOP_HGDI, THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_IN, 16, THOP_CALLBACK, THOP_END, THOP_ROUTINEINDEX, 14
+};
+THOP CONST thopsIViewObject_GetColorSet[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_DVTARGETDEVICE | THOP_IN, THOP_HGDI, THOP_LOGPALETTE | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIViewObject_Freeze[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIViewObject_Unfreeze[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIViewObject_SetAdvise[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IAdviseSink, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIViewObject_GetAdvise[] =
+{
+ THOP_COPY | THOP_OUT, 4, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IAdviseSink, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIViewObject2_Draw[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_DVTARGETDEVICE | THOP_IN, THOP_HGDI, THOP_HGDI, THOP_COPY | THOP_IN, 16, THOP_COPY | THOP_IN, 16, THOP_CALLBACK, THOP_END, THOP_ROUTINEINDEX, 14
+};
+THOP CONST thopsIViewObject2_GetColorSet[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_DVTARGETDEVICE | THOP_IN, THOP_HGDI, THOP_LOGPALETTE | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIViewObject2_Freeze[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIViewObject2_Unfreeze[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIViewObject2_SetAdvise[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IAdviseSink, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIViewObject2_GetAdvise[] =
+{
+ THOP_COPY | THOP_OUT, 4, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IAdviseSink, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIViewObject2_GetExtent[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_DVTARGETDEVICE | THOP_IN, THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIAdviseSink_OnDataChange[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_STGMEDIUM | THOP_IN, 0, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIAdviseSink_OnViewChange[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIAdviseSink_OnRename[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIAdviseSink_OnSave[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIAdviseSink_OnClose[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIAdviseSink2_OnDataChange[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_STGMEDIUM | THOP_IN, 0, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIAdviseSink2_OnViewChange[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIAdviseSink2_OnRename[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIAdviseSink2_OnSave[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIAdviseSink2_OnClose[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIAdviseSink2_OnLinkSrcChange[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIDataAdviseHolder_Advise[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_FORMATETC | THOP_IN, THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IAdviseSink, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIDataAdviseHolder_Unadvise[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIDataAdviseHolder_EnumAdvise[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIDataAdviseHolder_SendOnDataChange[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_COPY, 4, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleCache_Cache[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_COPY, 4, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleCache_Uncache[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCache_EnumCache[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCache_InitCache[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCache_SetData[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_STGMEDIUM | THOP_IN, 1, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleCache2_Cache[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_COPY, 4, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleCache2_Uncache[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCache2_EnumCache[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCache2_InitCache[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCache2_SetData[] =
+{
+ THOP_FORMATETC | THOP_IN, THOP_STGMEDIUM | THOP_IN, 1, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleCache2_UpdateCache[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleCache2_DiscardCache[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCacheControl_OnRun[] =
+{
+ THOP_IFACENOADDREF | THOP_IN, THI_IDataObject, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleCacheControl_OnStop[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIDropTarget_DragEnter[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_COPY, 4, THOP_COPY, 8, THOP_COPY | THOP_INOUT, 4, THOP_END, THOP_ROUTINEINDEX, 15
+};
+THOP CONST thopsIDropTarget_DragOver[] =
+{
+ THOP_COPY, 4, THOP_COPY, 8, THOP_COPY | THOP_INOUT, 4, THOP_END, THOP_ROUTINEINDEX, 16
+};
+THOP CONST thopsIDropTarget_DragLeave[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIDropTarget_Drop[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_COPY, 4, THOP_COPY, 8, THOP_COPY | THOP_INOUT, 4, THOP_END, THOP_ROUTINEINDEX, 15
+};
+THOP CONST thopsIDropSource_QueryContinueDrag[] =
+{
+ THOP_SHORTLONG, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIDropSource_GiveFeedback[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersist_GetClassID[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistStorage_GetClassID[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistStorage_IsDirty[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIPersistStorage_InitNew[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistStorage_Load[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistStorage_Save[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIPersistStorage_SaveCompleted[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStorage, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistStorage_HandsOffStorage[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIPersistStream_GetClassID[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistStream_IsDirty[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIPersistStream_Load[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistStream_Save[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIPersistStream_GetSizeMax[] =
+{
+ THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistFile_GetClassID[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistFile_IsDirty[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIPersistFile_Load[] =
+{
+ THOP_FILENAME | THOP_IN, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIPersistFile_Save[] =
+{
+ THOP_FILENAME | THOP_IN, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIPersistFile_SaveCompleted[] =
+{
+ THOP_FILENAME | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPersistFile_GetCurFile[] =
+{
+ THOP_FILENAME | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIBindCtx_RegisterObjectBound[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIBindCtx_RevokeObjectBound[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIBindCtx_ReleaseBoundObjects[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIBindCtx_SetBindOptions[] =
+{
+ THOP_BINDOPTS | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIBindCtx_GetBindOptions[] =
+{
+ THOP_BINDOPTS | THOP_INOUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIBindCtx_GetRunningObjectTable[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IRunningObjectTable, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIBindCtx_RegisterObjectParam[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIBindCtx_GetObjectParam[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_OUT, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIBindCtx_EnumObjectParam[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumString, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIBindCtx_RevokeObjectParam[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMoniker_GetClassID[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMoniker_IsDirty[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIMoniker_Load[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMoniker_Save[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIMoniker_GetSizeMax[] =
+{
+ THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMoniker_BindToObject[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIMoniker_BindToStorage[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIMoniker_Reduce[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_COPY, 4, THOP_IFACE | THOP_INOUT, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIMoniker_ComposeWith[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_SHORTLONG, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIMoniker_Enum[] =
+{
+ THOP_SHORTLONG, THOP_IFACE | THOP_OUT, THI_IEnumMoniker, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIMoniker_IsEqual[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMoniker_Hash[] =
+{
+ THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMoniker_IsRunning[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIMoniker_GetTimeOfLastChange[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIMoniker_Inverse[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIMoniker_CommonPrefixWith[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIMoniker_RelativePathTo[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIMoniker_GetDisplayName[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_LPLPSTR, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIMoniker_ParseDisplayName[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIMoniker_IsSystemMoniker[] =
+{
+ THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRunningObjectTable_Register[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIRunningObjectTable_Revoke[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRunningObjectTable_IsRunning[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRunningObjectTable_GetObject[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_IFACE | THOP_OUT, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRunningObjectTable_NoteChangeTime[] =
+{
+ THOP_COPY, 4, THOP_COPY | THOP_IN, 8, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRunningObjectTable_GetTimeOfLastChange[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRunningObjectTable_EnumRunning[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumMoniker_Next[] =
+{
+ THOP_ENUM, THE_IEnumMoniker, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumMoniker_Skip[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumMoniker_Reset[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIEnumMoniker_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumOLEVERB_Next[] =
+{
+ THOP_ENUM, THE_IEnumOLEVERB, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIEnumOLEVERB_Skip[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIEnumOLEVERB_Reset[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIEnumOLEVERB_Clone[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumOLEVERB, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleObject_SetClientSite[] =
+{
+ THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleObject_GetClientSite[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IOleClientSite, THOP_END, THOP_ROUTINEINDEX, 3
+};
+/*
+ The eighty character limit was arrived at by trial and error
+ with ClipArt Gallery. It faults at 90 characters.
+ */
+THOP CONST thopsIOleObject_SetHostNames[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_SIZEDSTRING | THOP_IN, 80, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_Close[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleObject_SetMoniker[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_GetMoniker[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleObject_InitFromData[] =
+{
+ THOP_IFACE | THOP_IN, THI_IDataObject, THOP_SHORTLONG, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleObject_GetClipboardData[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IDataObject, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_DoVerb[] =
+{
+ THOP_COPY, 4, THOP_MSG | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleClientSite, THOP_COPY, 4, THOP_HUSER, THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIOleObject_EnumVerbs[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumOLEVERB, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleObject_Update[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleObject_IsUpToDate[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleObject_GetUserClassID[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleObject_GetUserType[] =
+{
+ THOP_COPY, 4, THOP_LPLPSTR, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_SetExtent[] =
+{
+ THOP_COPY, 4, THOP_COPY | THOP_IN, 8, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_GetExtent[] =
+{
+ THOP_COPY, 4, THOP_COPY | THOP_OUT, 8, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_Advise[] =
+{
+ THOP_IFACE | THOP_IN, THI_IAdviseSink, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_Unadvise[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleObject_EnumAdvise[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleObject_GetMiscStatus[] =
+{
+ THOP_COPY, 4, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleObject_SetColorScheme[] =
+{
+ THOP_LOGPALETTE | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleClientSite_SaveObject[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleClientSite_GetMoniker[] =
+{
+ THOP_COPY, 4, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleClientSite_GetContainer[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IOleContainer, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleClientSite_ShowObject[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleClientSite_OnShowWindow[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleClientSite_RequestNewObjectLayout[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRunnableObject_GetRunningClass[] =
+{
+ THOP_COPY | THOP_OUT, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRunnableObject_Run[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRunnableObject_IsRunning[] =
+{
+ THOP_RETURNTYPE, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRunnableObject_LockRunning[] =
+{
+ THOP_SHORTLONG, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRunnableObject_SetContainedObject[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIParseDisplayName_ParseDisplayName[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIOleContainer_ParseDisplayName[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIOleContainer_EnumObjects[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IEnumUnknown, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleContainer_LockContainer[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleItemContainer_ParseDisplayName[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_LPSTR | THOP_IN, THOP_COPY | THOP_OUT, 4, THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIOleItemContainer_EnumObjects[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IEnumUnknown, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleItemContainer_LockContainer[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleItemContainer_GetObject[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIOleItemContainer_GetObjectStorage[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_COPY | THOP_IN, 16, THOP_IFACEGEN | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIOleItemContainer_IsRunning[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleAdviseHolder_Advise[] =
+{
+ THOP_IFACE | THOP_IN, THI_IAdviseSink, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleAdviseHolder_Unadvise[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleAdviseHolder_EnumAdvise[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IEnumSTATDATA, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleAdviseHolder_SendOnRename[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleAdviseHolder_SendOnSave[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleAdviseHolder_SendOnClose[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleLink_SetUpdateOptions[] =
+{
+ THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleLink_GetUpdateOptions[] =
+{
+ THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleLink_SetSourceMoniker[] =
+{
+ THOP_IFACE | THOP_IN, THI_IMoniker, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleLink_GetSourceMoniker[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IMoniker, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleLink_SetSourceDisplayName[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleLink_GetSourceDisplayName[] =
+{
+ THOP_LPLPSTR, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleLink_BindToSource[] =
+{
+ THOP_COPY, 4, THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleLink_BindIfRunning[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleLink_GetBoundSource[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleLink_UnbindSource[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleLink_Update[] =
+{
+ THOP_IFACE | THOP_IN, THI_IBindCtx, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleWindow_GetWindow[] =
+{
+ THOP_HUSER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleWindow_ContextSensitiveHelp[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceObject_GetWindow[] =
+{
+ THOP_HUSER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceObject_ContextSensitiveHelp[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceObject_InPlaceDeactivate[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceObject_UIDeactivate[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceObject_SetObjectRects[] =
+{
+ THOP_RECT | THOP_IN, THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleInPlaceObject_ReactivateAndUndo[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceActiveObject_GetWindow[] =
+{
+ THOP_HUSER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceActiveObject_ContextSensitiveHelp[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceActiveObject_TranslateAccelerator[] =
+{
+ THOP_MSG | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceActiveObject_OnFrameWindowActivate[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceActiveObject_OnDocWindowActivate[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceActiveObject_ResizeBorder[] =
+{
+ THOP_RECT | THOP_IN, THOP_IFACE | THOP_IN, THI_IOleInPlaceFrame, THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleInPlaceActiveObject_EnableModeless[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceUIWindow_GetWindow[] =
+{
+ THOP_HUSER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceUIWindow_ContextSensitiveHelp[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceUIWindow_GetBorder[] =
+{
+ THOP_RECT | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceUIWindow_RequestBorderSpace[] =
+{
+ THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceUIWindow_SetBorderSpace[] =
+{
+ THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceUIWindow_SetActiveObject[] =
+{
+ THOP_IFACE | THOP_IN, THI_IOleInPlaceActiveObject, THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleInPlaceFrame_GetWindow[] =
+{
+ THOP_HUSER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_ContextSensitiveHelp[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_GetBorder[] =
+{
+ THOP_RECT | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_RequestBorderSpace[] =
+{
+ THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_SetBorderSpace[] =
+{
+ THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_SetActiveObject[] =
+{
+ THOP_IFACE | THOP_IN, THI_IOleInPlaceActiveObject, THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleInPlaceFrame_InsertMenus[] =
+{
+ THOP_HUSER, THOP_COPY | THOP_INOUT, 24, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIOleInPlaceFrame_SetMenu[] =
+{
+ THOP_HUSER, THOP_ALIAS32, ALIAS_RESOLVE, THOP_HUSER, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIOleInPlaceFrame_RemoveMenus[] =
+{
+ THOP_HUSER, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_SetStatusText[] =
+{
+ THOP_LPSTR | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_EnableModeless[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceFrame_TranslateAccelerator[] =
+{
+ THOP_MSG | THOP_IN, THOP_WORDDWORD, THOP_END, THOP_ROUTINEINDEX, 17
+};
+THOP CONST thopsIOleInPlaceSite_GetWindow[] =
+{
+ THOP_HUSER | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceSite_ContextSensitiveHelp[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceSite_CanInPlaceActivate[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceSite_OnInPlaceActivate[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceSite_OnUIActivate[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceSite_GetWindowContext[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IOleInPlaceFrame, THOP_IFACE | THOP_OUT, THI_IOleInPlaceUIWindow, THOP_RECT | THOP_OUT, THOP_RECT | THOP_OUT, THOP_OIFI | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIOleInPlaceSite_Scroll[] =
+{
+ THOP_SIZE, THOP_END, THOP_ROUTINEINDEX, 18
+};
+THOP CONST thopsIOleInPlaceSite_OnUIDeactivate[] =
+{
+ THOP_SHORTLONG, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIOleInPlaceSite_OnInPlaceDeactivate[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceSite_DiscardUndoState[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceSite_DeactivateAndUndo[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIOleInPlaceSite_OnPosRectChange[] =
+{
+ THOP_RECT | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcChannelBuffer_GetBuffer[] =
+{
+ THOP_RPCOLEMESSAGE | THOP_INOUT, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRpcChannelBuffer_SendReceive[] =
+{
+ THOP_RPCOLEMESSAGE | THOP_INOUT, THOP_COPY | THOP_OUT, 4, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRpcChannelBuffer_FreeBuffer[] =
+{
+ THOP_RPCOLEMESSAGE | THOP_INOUT, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcChannelBuffer_GetDestCtx[] =
+{
+ THOP_COPY | THOP_OUT, 4, THOP_NULL | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRpcChannelBuffer_IsConnected[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRpcProxyBuffer_Connect[] =
+{
+ THOP_IFACE | THOP_IN, THI_IRpcChannelBuffer, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcProxyBuffer_Disconnect[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRpcStubBuffer_Connect[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcStubBuffer_Disconnect[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRpcStubBuffer_Invoke[] =
+{
+ THOP_RPCOLEMESSAGE | THOP_INOUT, THOP_IFACE | THOP_IN, THI_IRpcChannelBuffer, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRpcStubBuffer_IsIIDSupported[] =
+{
+ THOP_RETURNTYPE, THOP_IFACE | THOP_IN, THI_IRpcStubBuffer, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcStubBuffer_CountRefs[] =
+{
+ THOP_RETURNTYPE, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRpcStubBuffer_DebugServerQueryInterface[] =
+{
+ THOP_IFACE | THOP_OUT, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcStubBuffer_DebugServerRelease[] =
+{
+ THOP_IFACECLEAN | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIPSFactoryBuffer_CreateProxy[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY | THOP_IN, 16, THOP_IFACEOWNER | THOP_OUT, THI_IRpcProxyBuffer, 8, THOP_IFACEGENOWNER | THOP_OUT, 8, 12, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIPSFactoryBuffer_CreateStub[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_IFACEOWNER | THOP_OUT, THI_IRpcStubBuffer, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
+THOP CONST thopsIRpcChannel_GetStream[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_SHORTLONG, THOP_SHORTLONG, THOP_SHORTLONG, THOP_COPY, 4, THOP_IFACE | THOP_OUT, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 4
+};
+THOP CONST thopsIRpcChannel_Call[] =
+{
+ THOP_IFACE | THOP_IN, THI_IStream, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcChannel_GetDestCtx[] =
+{
+ THOP_COPY | THOP_OUT, 4, THOP_NULL | THOP_OUT, THOP_END, THOP_ROUTINEINDEX, 0
+};
+THOP CONST thopsIRpcChannel_IsConnected[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRpcProxy_Connect[] =
+{
+ THOP_IFACE | THOP_IN, THI_IRpcChannel, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcProxy_Disconnect[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRpcStub_Connect[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcStub_Disconnect[] =
+{
+ THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIRpcStub_Invoke[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_SHORTLONG, THOP_IFACE | THOP_IN, THI_IStream, THOP_COPY, 4, THOP_NULL | THOP_IN, THOP_END, THOP_ROUTINEINDEX, 7
+};
+THOP CONST thopsIRpcStub_IsIIDSupported[] =
+{
+ THOP_RETURNTYPE, THOP_SHORTLONG, THOP_COPY | THOP_IN, 16, THOP_END, THOP_ROUTINEINDEX, 3
+};
+THOP CONST thopsIRpcStub_CountRefs[] =
+{
+ THOP_RETURNTYPE, THOP_COPY, 4, THOP_END, THOP_ROUTINEINDEX, 1
+};
+THOP CONST thopsIPSFactory_CreateProxy[] =
+{
+ THOP_IFACE | THOP_IN, THI_IUnknown, THOP_COPY | THOP_IN, 16, THOP_IFACEOWNER | THOP_OUT, THI_IRpcProxy, 8, THOP_IFACEGENOWNER | THOP_OUT, 8, 12, THOP_END, THOP_ROUTINEINDEX, 5
+};
+THOP CONST thopsIPSFactory_CreateStub[] =
+{
+ THOP_COPY | THOP_IN, 16, THOP_IFACE | THOP_IN, THI_IUnknown, THOP_IFACEOWNER | THOP_OUT, THI_IRpcStub, 4, THOP_END, THOP_ROUTINEINDEX, 2
+};
diff --git a/private/ole32/olethunk/olethk32/thoputil.cxx b/private/ole32/olethunk/olethk32/thoputil.cxx
new file mode 100644
index 000000000..da4f424b6
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thoputil.cxx
@@ -0,0 +1,4547 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thoputil.cxx
+//
+// Contents: Utility routines for thunking
+//
+// History: 01-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <stdio.h>
+#include <limits.h>
+
+#include <vdmdbg.h>
+#include <valid.h>
+
+//
+// Chicago doesn't support the NT ExpLdr API, use the new Chicago
+// WOWGetDescriptor that copies the LDT info to a provided buffer.
+//
+#if defined(_CHICAGO_)
+extern "C" WOWGetDescriptor(VPVOID, VDMLDT_ENTRY *);
+#else
+extern "C" DECLSPEC_IMPORT VDMLDT_ENTRY *ExpLdt;
+#endif
+
+#include "struct16.hxx"
+
+#define CF_INVALID ((CLIPFORMAT)0)
+
+#define OBJDESC_CF(cf) \
+ ((cf) == g_cfObjectDescriptor || (cf) == g_cfLinkSourceDescriptor)
+
+// Alias manager for THOP_ALIAS32
+CAliases gAliases32;
+
+//+---------------------------------------------------------------------------
+//
+// Function: IidToIidIdx, public
+//
+// Synopsis: Looks up an interface index by IID
+// If it's not found, it returns the IID pointer
+//
+// Arguments: [riid] - IID
+//
+// Returns: Index or IID
+//
+// History: 23-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+IIDIDX IidToIidIdx(REFIID riid)
+{
+ int idx;
+
+ for (idx = 0; idx < THI_COUNT; idx++)
+ {
+ if (IsEqualIID(riid, *aittIidToThi[idx].piid))
+ {
+ return INDEX_IIDIDX(aittIidToThi[idx].iThi);
+ }
+ }
+
+ return IID_IIDIDX(&riid);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TaskMalloc32, public
+//
+// Synopsis: Task allocation for 32-bits
+//
+// History: 01-Mar-94 DrewB Created
+//
+// Notes: Temporary until CoTaskMemAlloc is hooked up
+//
+//----------------------------------------------------------------------------
+
+#ifndef COTASK_DEFINED
+LPVOID TaskMalloc32(DWORD cb)
+{
+ IMalloc *pm;
+ LPVOID pv;
+
+ if (FAILED(GetScode(CoGetMalloc(MEMCTX_TASK, &pm))))
+ {
+ return NULL;
+ }
+ else
+ {
+ pv = pm->Alloc(cb);
+ pm->Release();
+ }
+ return pv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TaskFree32, public
+//
+// Synopsis: Task free for 32-bits
+//
+// History: 01-Mar-94 DrewB Created
+//
+// Notes: Temporary until CoTaskMemAlloc is hooked up
+//
+//----------------------------------------------------------------------------
+
+void TaskFree32(LPVOID pv)
+{
+ IMalloc *pm;
+
+ if (FAILED(GetScode(CoGetMalloc(MEMCTX_TASK, &pm))))
+ {
+ thkAssert(!"CoGetMalloc failed");
+ }
+ else
+ {
+ pm->Free(pv);
+ pm->Release();
+ }
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: TaskMalloc16, public
+//
+// Synopsis: Allocates 16-bit task memory
+//
+// Arguments: [uiSize] - Amount of memory to allocate
+//
+// Returns: VPVOID for memory allocated
+//
+// History: 01-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+DWORD TaskMalloc16( UINT uiSize )
+{
+ return CallbackTo16(gdata16Data.fnTaskAlloc, uiSize);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TaskFree16, public
+//
+// Synopsis: Frees 16-bit task memory
+//
+// Arguments: [vpvoid] - VPVOID of allocated memory
+//
+// History: 01-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void TaskFree16( DWORD vpvoid )
+{
+ CallbackTo16(gdata16Data.fnTaskFree, vpvoid);
+}
+
+// List of 16/32 HRESULT mappings for mapping functions
+struct SHrMapping
+{
+ HRESULT hr16;
+ HRESULT hr32;
+};
+
+// Since we're including 32-bit headers in this code we can use
+// the defines for the 32-bit values but we must specify the
+// 16-bit values explicitly
+static SHrMapping hmMappings[] =
+{
+ 0x80000001, E_NOTIMPL,
+ 0x80000002, E_OUTOFMEMORY,
+ 0x80000003, E_INVALIDARG,
+ 0x80000004, E_NOINTERFACE,
+ 0x80000005, E_POINTER,
+ 0x80000006, E_HANDLE,
+ 0x80000007, E_ABORT,
+ 0x80000008, E_FAIL,
+ 0x80000009, E_ACCESSDENIED
+};
+#define NMAPPINGS (sizeof(hmMappings)/sizeof(hmMappings[0]))
+
+#define HR16_ERROR 0x80000000
+#define HR16_MAP_FIRST 1
+#define HR16_MAP_LAST 9
+
+//+---------------------------------------------------------------------------
+//
+// Function: TransformHRESULT_1632, public
+//
+// Synopsis: Translates a 16-bit hresult into a 32-bit hresult
+//
+// Arguments: [hresult] - 16-bit hresult to transform
+//
+// History: 15-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(DWORD) TransformHRESULT_1632( DWORD hresult )
+{
+ ULONG ulIndex;
+
+ // We only map error codes
+ if (hresult & HR16_ERROR)
+ {
+ // The 16-bit HRESULTs to be mapped are known quantities
+ // whose values are sequential, so we can map directly from
+ // the value to an array index
+
+ ulIndex = hresult & ~HR16_ERROR;
+ if (ulIndex >= HR16_MAP_FIRST && ulIndex <= HR16_MAP_LAST)
+ {
+ // Known value, index array to find 32-bit HRESULT
+ return hmMappings[ulIndex-HR16_MAP_FIRST].hr32;
+ }
+ }
+
+ // No mapping found, so return the original
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TransformHRESULT_3216, public
+//
+// Synopsis: Translates a 32-bit hresult into a 16-bit hresult
+//
+// Arguments: [hresult] - 32-bit hresult to transform
+//
+// History: 15-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(DWORD) TransformHRESULT_3216( DWORD hresult )
+{
+ int i;
+ SHrMapping *phm;
+
+ // We don't know the true values of 32-bit HRESULTs since we're
+ // using the defines and they may change, so we have to look up
+ // the hard way
+
+ phm = hmMappings;
+ for (i = 0; i < NMAPPINGS; i++)
+ {
+ if (phm->hr32 == (HRESULT)hresult)
+ {
+ return phm->hr16;
+ }
+
+ phm++;
+ }
+
+ // No mapping found, so return the original
+ return hresult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: RecordStackState, public debug
+//
+// Synopsis: Records the current state of the stack
+//
+// Arguments: [psr] - Storage space for information
+//
+// Modifies: [psr]
+//
+// History: 28-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+void RecordStackState16(SStackRecord *psr)
+{
+ CStackAllocator *psa;
+
+ psa = TlsThkGetStack16();
+ psa->RecordState(psr);
+}
+
+void RecordStackState32(SStackRecord *psr)
+{
+ CStackAllocator *psa;
+
+ psa = TlsThkGetStack32();
+ psa->RecordState(psr);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: CheckStackState, public debug
+//
+// Synopsis: Checks recorded information about the stack against its
+// current state
+//
+// Arguments: [psr] - Recorded information
+//
+// History: 28-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+void CheckStackState16(SStackRecord *psr)
+{
+ CStackAllocator *psa;
+
+ psa = TlsThkGetStack16();
+ psa->CheckState(psr);
+}
+
+void CheckStackState32(SStackRecord *psr)
+{
+ CStackAllocator *psa;
+
+ psa = TlsThkGetStack32();
+ psa->CheckState(psr);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: Convert_VPSTR_to_LPOLESTR
+//
+// Synopsis: Converts 16-bit VPSTR to 32-bit LPOLESTR pointer
+//
+// Arguments: [vpstr] - VPSTR
+// [lpOleStr] - OLESTR
+// [uiSizeInPlace] - Amount of data available in [lpOleStr]
+// for in-place conversion (in characters, not bytes)
+// including nul
+//
+// Returns: Pointer to LPOLESTR with data
+//
+// History: 24-Feb-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+LPOLESTR Convert_VPSTR_to_LPOLESTR(
+ THUNKINFO *pti,
+ VPSTR vpstr,
+ LPOLESTR lpOleStr,
+ UINT uiSizeInPlace
+)
+{
+ LPSTR lpstr;
+ UINT uiSize;
+ LPOLESTR lpOleStrResult;
+ UINT cChars;
+
+ // We shouldn't be calling here for null strings
+ thkAssert( vpstr != NULL );
+
+ lpstr = GetStringPtr16(pti, vpstr, CCHMAXSTRING, &uiSize);
+ if ( lpstr == NULL )
+ {
+ //
+ // GetStringPtr will have filled in the pti->scResult
+ //
+ return( NULL );
+ }
+
+ // The string has to have at least one character in it
+ // because it must be null-terminated to be valid
+ thkAssert(uiSize > 0);
+
+ lpOleStrResult = lpOleStr;
+
+ if ( uiSize > uiSizeInPlace )
+ {
+ lpOleStrResult = (LPOLESTR)TaskMalloc32(uiSize*sizeof(OLECHAR));
+ if (lpOleStrResult == NULL)
+ {
+ pti->scResult = E_OUTOFMEMORY;
+ return NULL;
+ }
+ }
+
+ cChars = MultiByteToWideChar( AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0,
+ lpstr,
+ uiSize,
+ lpOleStrResult,
+ uiSize );
+
+ WOWRELVDMPTR(vpstr);
+
+ if ( cChars == 0 )
+ {
+ if (lpOleStrResult != lpOleStr)
+ {
+ TaskFree32(lpOleStrResult);
+ }
+
+ pti->scResult = E_UNEXPECTED;
+ return( NULL );
+ }
+ else
+ {
+ return( lpOleStrResult );
+ }
+}
+//+---------------------------------------------------------------------------
+//
+// Function: Convert_LPOLESTR_to_VPSTR
+//
+// Synopsis: Converts 32-bit LPOLESTR to 16-bit VPSTR pointer
+//
+// Arguments: [lpOleStr] - OLESTR
+// [vpstr] - VPSTR
+// [uiSize32] - Length of OLESTR in characters (not bytes)
+// including nul
+// [uiSize16] - Byte length of buffer referred to by VPSTR
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-94 BobDay Created
+//
+// Notes: Always converts in place
+//
+//----------------------------------------------------------------------------
+
+SCODE Convert_LPOLESTR_to_VPSTR(
+ LPCOLESTR lpOleStr,
+ VPSTR vpstr,
+ UINT uiSize32,
+ UINT uiSize16
+)
+{
+ LPSTR lpstr;
+ UINT cChars;
+ SCODE sc;
+
+ sc = S_OK;
+
+ lpstr = (LPSTR)WOWFIXVDMPTR(vpstr, uiSize16);
+
+ cChars = WideCharToMultiByte( AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0,
+ lpOleStr,
+ uiSize32,
+ lpstr,
+ uiSize16,
+ NULL,
+ NULL );
+
+ if ( cChars == 0 && uiSize32 != 0 )
+ {
+ sc = E_UNEXPECTED;
+ }
+
+ WOWRELVDMPTR(vpstr);
+
+ return sc;
+}
+#ifdef _CHICAGO_
+//+---------------------------------------------------------------------------
+//
+// Function: Convert_LPSTR_to_VPSTR
+//
+// Synopsis: Converts 32-bit LPSTR to 16-bit VPSTR pointer
+//
+// Arguments: [lpOleStr] - LPSTR
+// [vpstr] - VPSTR
+// [uiSize32] - Length of LPSTR in bytes including nul
+// [uiSize16] - Byte length of buffer referred to by VPSTR
+//
+// Returns: Appropriate status code
+//
+// History: 10-21-95 KevinRo Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE Convert_LPSTR_to_VPSTR(
+ LPCSTR lpOleStr,
+ VPSTR vpstr,
+ UINT uiSize32,
+ UINT uiSize16
+)
+{
+ LPSTR lpstr;
+
+ lpstr = (LPSTR)WOWFIXVDMPTR(vpstr, uiSize16);
+
+ memcpy(lpstr,lpOleStr,uiSize32);
+
+ WOWRELVDMPTR(vpstr);
+
+ return S_OK;
+}
+#endif // _CHICAGO_
+
+// Selector bit constants
+#define SEL_TI 0x0004
+#define SEL_RPL 0x0003
+#define SEL_INDEX 0xfff8
+
+#define IS_LDT_SELECTOR(sel) (((sel) & SEL_TI) == SEL_TI)
+
+// LDT bit constants
+#define LTYPE_APP 0x0010
+#define LTYPE_CODE 0x0008
+#define LTYPE_CREAD 0x0002
+#define LTYPE_DDOWN 0x0004
+#define LTYPE_DWRITE 0x0002
+
+// Pointer access types, or'able
+// Defined to be the same as thop in/out so that no translation
+// is necessary for checks on thop memory access
+#define PACC_READ THOP_IN
+#define PACC_WRITE THOP_OUT
+#define PACC_CODE 1 // Special for CODE PTRs
+
+// Information about a VDM pointer
+typedef struct _VPTRDESC
+{
+ BYTE *pbFlat;
+ DWORD dwLengthLeft;
+} VPTRDESC;
+
+// VDM memory is always zero-based on Win95
+#ifndef _CHICAGO_
+DWORD dwBaseVDMMemory = 0xFFFFFFFF;
+#else
+#define dwBaseVDMMemory 0
+#endif
+
+// Extended success returns from GetPtr16Description
+#define S_GDTENTRY MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 1)
+#define S_SYSLDTENTRY MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 2)
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetPtr16Description, public
+//
+// Synopsis: Validates access for a VDM pointer and returns
+// information about it
+// Also forces not-present segments into memory by
+// touching them
+//
+// Arguments: [vp] - VDM pointer
+// [grfAccess] - Desired access
+// [dwSize] - Desired size of access, must be >= 1
+// [pvpd] - VPTRDESC out
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pvpd]
+//
+// History: 26-Apr-94 DrewB Created
+//
+// Notes: Returns fixed memory
+//
+//----------------------------------------------------------------------------
+
+SCODE GetPtr16Description(VPVOID vp,
+ WORD grfAccess,
+ DWORD dwSize,
+ VPTRDESC *pvpd)
+{
+ VDMLDT_ENTRY *vle;
+#if defined(_CHICAGO_)
+ VDMLDT_ENTRY LdtEntry;
+#endif
+ WORD wSel;
+ WORD wOff;
+ DWORD dwLength;
+
+ thkAssert(vp != 0);
+ thkAssert(dwSize > 0);
+ thkAssert(grfAccess != 0);
+
+ wSel = (WORD)(vp >> 16);
+ wOff = (WORD)(vp & 0xffff);
+
+ pvpd->dwLengthLeft = 0xffff-wOff+1; // Default length remaining
+
+ if (!IS_LDT_SELECTOR(wSel))
+ {
+ // According to the WOW developers, the only GDT selector
+ // is for the BIOS data area so we should never see one
+
+ thkDebugOut((DEB_ERROR, "GDT selector: 0x%04X\n", wSel));
+
+ // Handle it just in case
+ pvpd->pbFlat = (BYTE *)WOWFIXVDMPTR(vp, dwSize);
+
+ return S_GDTENTRY;
+ }
+
+#if defined(_CHICAGO_)
+ vle = &LdtEntry;
+ if (!WOWGetDescriptor(vp, vle))
+ {
+ return E_INVALIDARG;
+ }
+#else
+ vle = (VDMLDT_ENTRY *)((BYTE *)(ExpLdt)+(wSel & SEL_INDEX));
+#endif
+
+ if ((vle->HighWord.Bits.Type & LTYPE_APP) == 0)
+ {
+ // According to the WOW developers, they don't use
+ // system segments so we should never see one
+
+ thkDebugOut((DEB_ERROR, "System descriptor: 0x%04X\n", wSel));
+
+ // Handle it just in case
+ pvpd->pbFlat = (BYTE *)WOWFIXVDMPTR(vp, dwSize);
+
+ return S_SYSLDTENTRY;
+ }
+
+ // Do as much up-front validation as possible
+ // Since the segment may not be present, we are restricted to
+ // only checking the access permissions
+
+ if (vle->HighWord.Bits.Type & LTYPE_CODE)
+ {
+ // Validate access for code segments
+ // Code segments are never writable
+
+ if (((grfAccess & PACC_READ) &&
+ (vle->HighWord.Bits.Type & LTYPE_CREAD) == 0) ||
+ (grfAccess & PACC_WRITE))
+ {
+ return E_INVALIDARG;
+ }
+ }
+ else
+ {
+ // Validate access for data segments
+ // Data segments are always readable never executable
+
+ if (((grfAccess & PACC_WRITE) &&
+ (vle->HighWord.Bits.Type & LTYPE_DWRITE) == 0) ||
+ (grfAccess & PACC_CODE))
+ {
+ return E_INVALIDARG;
+ }
+ }
+
+ // Bring in segment if it's not present
+ if (!vle->HighWord.Bits.Pres)
+ {
+ // We've validated access permissions and segments must
+ // always be at least one byte long so it's safe to
+ // touch the first byte to bring it in
+
+ // On Win95, this will call GlobalFix on the pointer
+ // to ensure that it stays in memory
+ WOWCallback16(gdata16Data.fnTouchPointer16, vp);
+
+#if defined(_CHICAGO_)
+ // Since we only copy the descriptor, recopy it now.
+ WOWGetDescriptor(vp, vle);
+#endif
+
+ thkAssert(vle->HighWord.Bits.Pres);
+ }
+#ifdef _CHICAGO_
+ else
+ {
+ // Lock the LDT entry (as best as we can) by fixing it
+ // This prevents global blocks from being relocated during
+ // heap compaction
+ WOWGetVDMPointerFix(vp, dwSize, TRUE);
+ }
+#endif
+
+
+ dwLength = ((DWORD)vle->LimitLow |
+ ((DWORD)vle->HighWord.Bits.LimitHi << 16))+1;
+ if (vle->HighWord.Bits.Granularity)
+ {
+ // 4K granularity
+ dwLength <<= 12;
+ }
+
+ if ((vle->HighWord.Bits.Type & LTYPE_CODE) ||
+ (vle->HighWord.Bits.Type & LTYPE_DDOWN) == 0)
+ {
+ // Validate length for code and normal data segments
+
+ if (wOff+dwSize > dwLength)
+ {
+ WOWRELVDMPTR(vp);
+ return E_INVALIDARG;
+ }
+
+ pvpd->dwLengthLeft = dwLength-wOff;
+ }
+ else
+ {
+ // Expand-down segment
+
+ if (wOff < dwLength)
+ {
+ WOWRELVDMPTR(vp);
+ return E_INVALIDARG;
+ }
+
+ // Check for wraparound
+
+ if (vle->HighWord.Bits.Granularity)
+ {
+ // BUGBUG - Compiler - This should be +1, but
+ // the compiler generates a warning about an overflow
+ // in constant arithmetic
+ pvpd->dwLengthLeft = 0xffffffff-wOff;
+ }
+
+ if (dwSize > pvpd->dwLengthLeft)
+ {
+ WOWRELVDMPTR(vp);
+ return E_INVALIDARG;
+ }
+ }
+
+ // VDM memory is always zero-based on Win95
+#ifndef _CHICAGO_
+ if ( dwBaseVDMMemory == 0xFFFFFFFF )
+ {
+ dwBaseVDMMemory = (DWORD)WOWGetVDMPointer(0, 0, FALSE);
+ }
+#endif
+
+ // Translate the pointer even on Win95 because forcing the segment
+ // present may have changed its address
+ pvpd->pbFlat = (BYTE *)(dwBaseVDMMemory +
+ wOff +
+ ( (DWORD)vle->BaseLow |
+ ( (DWORD)vle->HighWord.Bytes.BaseMid << 16) |
+ ( (DWORD)vle->HighWord.Bytes.BaseHi << 24) ) );
+
+#if DBG == 1
+ if (pvpd->pbFlat != WOWGetVDMPointer(vp, dwSize, TRUE))
+ {
+ thkDebugOut((DEB_ERROR, "GetPtr16Description: "
+ "%p computed, %p system\n",
+ pvpd->pbFlat, WOWGetVDMPointer(vp, dwSize, TRUE)));
+ }
+#endif
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetReadPtr16
+//
+// Synopsis: Validates a 16-bit pointer for reading and converts it into
+// a flat 32 pointer.
+//
+// Arguments: [pti] - THUNKINFO * for updating error code
+// [vp] - 16-bit pointer to validate/convert
+// [dwSize] - Length to validate
+//
+// Returns: Appropriate status code
+//
+// History: 22-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+VOID *
+GetReadPtr16(
+ THUNKINFO *pti,
+ VPVOID vp,
+ DWORD dwSize )
+{
+ VPTRDESC vpd;
+ SCODE sc;
+
+ sc = GetPtr16Description(vp, PACC_READ, dwSize, &vpd);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ return NULL;
+ }
+ else
+ {
+ return vpd.pbFlat;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetWritePtr16
+//
+// Synopsis: Validates a 16-bit pointer for writing and converts it into
+// a flat 32 pointer.
+//
+// Arguments: [pti] - THUNKINFO * for updating error code
+// [vp] - 16-bit pointer to validate/convert
+// [dwSize] - Length to validate
+//
+// Returns: Appropriate status code
+//
+// History: 22-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+VOID *
+GetWritePtr16(
+ THUNKINFO *pti,
+ VPVOID vp,
+ DWORD dwSize )
+{
+ VPTRDESC vpd;
+ SCODE sc;
+
+ sc = GetPtr16Description(vp, PACC_WRITE, dwSize, &vpd);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ return NULL;
+ }
+ else
+ {
+ return vpd.pbFlat;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetCodePtr16
+//
+// Synopsis: Validates a 16-bit pointer for execution and converts it
+// into a flat 32 pointer.
+//
+// Arguments: [pti] - THUNKINFO * for updating error code
+// [vp] - 16-bit pointer to validate/convert
+// [dwSize] - Length to validate
+//
+// Returns: Appropriate status code
+//
+// History: 22-Jul-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+VOID *
+GetCodePtr16(
+ THUNKINFO *pti,
+ VPVOID vp,
+ DWORD dwSize )
+{
+ VPTRDESC vpd;
+ SCODE sc;
+
+ sc = GetPtr16Description(vp, PACC_CODE, dwSize, &vpd);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ return NULL;
+ }
+ else
+ {
+ return vpd.pbFlat;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetReadWritePtr16
+//
+// Synopsis: Validates a 16-bit pointer for reading and writing and
+// converts it into a flat 32 pointer.
+//
+// Arguments: [pti] - THUNKINFO * for updating error code
+// [vp] - 16-bit pointer to validate/convert
+// [dwSize] - Length to validate
+//
+// Returns: Appropriate status code
+//
+// History: 22-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+VOID *
+GetReadWritePtr16(
+ THUNKINFO *pti,
+ VPVOID vp,
+ DWORD dwSize )
+{
+ VPTRDESC vpd;
+ SCODE sc;
+
+ sc = GetPtr16Description(vp, PACC_READ | PACC_WRITE, dwSize, &vpd);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ return NULL;
+ }
+ else
+ {
+ return vpd.pbFlat;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetStringPtr16
+//
+// Synopsis: Validates a 16-bit pointer to a string for reading and
+// converts it (the pointer) into a flat 32 pointer. It also
+// returns the length, since it has to compute it anyway.
+//
+// Arguments: [pti] - THUNKINFO * for updating error code
+// [vp] - 16-bit pointer to validate/convert
+// [cchMax] - Maximum legal length
+// [lpSize] - Place to return length
+//
+// Returns: Appropriate status code
+//
+// History: 22-Mar-94 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+CHAR *
+GetStringPtr16(
+ THUNKINFO *pti,
+ VPSTR vp,
+ UINT cchMax,
+ PUINT lpSize )
+{
+ VPTRDESC vpd;
+ SCODE sc;
+
+ // Check the first byte to ensure read access to the segment
+ sc = GetPtr16Description(vp, PACC_READ, 1, &vpd);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ return NULL;
+ }
+ else
+ {
+ UINT cchLen;
+ BYTE *pb;
+ BOOL fMbLead;
+
+ pb = vpd.pbFlat;
+
+ if (pb == NULL)
+ {
+ goto Exit;
+ }
+
+
+ // Restrict zero-termination search to cchMax characters
+ // or valid remaining memory
+ // Since we specified one in GetPtr16Description, dwLengthLeft
+ // is one off here
+ cchMax = min(cchMax, vpd.dwLengthLeft+1);
+
+ cchLen = 0;
+ fMbLead = FALSE;
+ while (cchMax > 0)
+ {
+ cchLen++;
+
+ if (*pb == 0 && !fMbLead)
+ {
+ break;
+ }
+ else
+ {
+ fMbLead = (BOOL)g_abLeadTable[*pb++];
+ cchMax--;
+ }
+ }
+
+ if (cchMax > 0)
+ {
+ *lpSize = cchLen;
+ return (LPSTR)vpd.pbFlat;
+ }
+
+Exit:
+ {
+ pti->scResult = E_INVALIDARG;
+ WOWRELVDMPTR(vp);
+ return NULL;
+ }
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ValidatePtr16, public
+//
+// Synopsis: Calls an appropriate validation routine for 16-bit
+// memory based on in/out status
+//
+// Arguments: [pti] - Thunk info, can be NULL for no validation
+// [vp16] - 16-bit pointer
+// [dwSize] - Size
+// [thopInOut] - In/out type
+//
+// Returns: Pointer or NULL
+//
+// Modifies: [pti]->scResult for errors
+//
+// History: 24-Apr-94 DrewB Created
+//
+// Notes: 0 - No validation
+// THOP_IN - Read validation
+// THOP_OUT - Write validation
+// THOP_INOUT - Read/write validation
+//
+//----------------------------------------------------------------------------
+
+VOID *
+ValidatePtr16(THUNKINFO *pti,
+ VPVOID vp16,
+ DWORD dwSize,
+ THOP thopInOut)
+{
+ VPTRDESC vpd;
+ SCODE sc;
+
+ thopInOut &= THOP_INOUT;
+ if (thopInOut != 0)
+ {
+ sc = GetPtr16Description(vp16, thopInOut, dwSize, &vpd);
+ if (FAILED(sc))
+ {
+ pti->scResult = sc;
+ return NULL;
+ }
+ else
+ {
+ return vpd.pbFlat;
+ }
+ }
+ else
+ {
+ return WOWFIXVDMPTR(vp16, dwSize);
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: IsValidInterface16, public
+//
+// Synopsis: Validates that a provided 16-bit interface is really valid
+// (uses the same validation technique as 16-bit OLE 2.01)
+//
+// Arguments: [pti] - Thunk info, can be NULL for no validation
+// [vp16] - 16-bit pointer
+//
+// Returns: BOOL - true for valid, false for invalid
+//
+// Modifies: [pti]->scResult for errors
+//
+// History: 22-Jul-92 BobDay Created
+//
+//----------------------------------------------------------------------------
+
+BOOL IsValidInterface16( THUNKINFO *pti, VPVOID vp )
+{
+ VPVOID UNALIGNED *pvpv;
+ VPVOID vpvtbl;
+ VPVOID vpfn;
+ LPVOID lpfn;
+
+ //
+ // Make sure we can read the vtbl pointer from the object.
+ //
+ pvpv = (VPVOID FAR *)GetReadPtr16(pti, vp, sizeof(VPVOID));
+ if ( pvpv == NULL )
+ {
+ thkDebugOut((DEB_WARN, "IsValidInterface16: "
+ "Interface ptr invalid %p\n", vp));
+ return FALSE;
+ }
+
+ vpvtbl = *pvpv; // Read the vtbl ptr
+
+ WOWRELVDMPTR(vp);
+
+ // Make sure we can read the first entry from the vtbl (QI)
+
+ pvpv = (VPVOID FAR *)GetReadPtr16(pti, vpvtbl, sizeof(VPVOID));
+ if ( pvpv == NULL )
+ {
+ thkDebugOut((DEB_WARN, "Vtbl ptr invalid %p:%p\n", vp, vpvtbl));
+ return FALSE;
+ }
+
+ vpfn = *pvpv; // Get the QI Function
+
+ WOWRELVDMPTR(vpvtbl);
+
+ if ( vpfn == 0 )
+ {
+ thkDebugOut((DEB_WARN, "QI function NULL %p:%p\n", vp, vpvtbl));
+ pti->scResult = E_INVALIDARG;
+ return FALSE;
+ }
+
+ // Why it has to be 9 bytes long, I have no idea.
+ // This check was taken from valid.cpp in
+ // \src\ole2\dll\src\debug the 16-bit ole2.01
+ // sources...
+ lpfn = (LPVOID)GetCodePtr16(pti, vpfn, 9);
+
+ WOWRELVDMPTR(vpfn);
+
+ if ( lpfn == NULL )
+ {
+ thkDebugOut((DEB_WARN, "QI function ptr invalid %p:%p:%p\n",
+ vp,vpvtbl,vpfn));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GuidString, debug public
+//
+// Synopsis: Converts a guid to a string
+//
+// Arguments: [pguid] - GUID
+//
+// Returns: Pointer to string
+//
+// History: 08-Mar-94 DrewB Created
+//
+// Notes: Uses a static buffer
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+
+#pragma pack(1)
+struct SplitGuid
+{
+ DWORD dw1;
+ WORD w1;
+ WORD w2;
+ BYTE b[8];
+};
+#pragma pack()
+
+char *GuidString(GUID const *pguid)
+{
+ static char ach[39];
+ SplitGuid *psg = (SplitGuid *)pguid;
+
+ wsprintfA(ach, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
+ psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
+ return ach;
+}
+
+#endif
+
+#if DBG == 1
+ char *apszThopNames[] =
+{
+ "THOP_END",
+ "THOP_SHORTLONG",
+ "THOP_WORDDWORD",
+ "THOP_COPY",
+ "THOP_LPSTR",
+ "THOP_LPLPSTR",
+ "THOP_BUFFER",
+ "THOP_HUSER",
+ "THOP_HGDI",
+ "THOP_SIZE",
+ "THOP_RECT",
+ "THOP_MSG",
+ "THOP_HRESULT",
+ "THOP_STATSTG",
+ "THOP_DVTARGETDEVICE",
+ "THOP_STGMEDIUM",
+ "THOP_FORMATETC",
+ "THOP_HACCEL",
+ "THOP_OIFI",
+ "THOP_BINDOPTS",
+ "THOP_LOGPALETTE",
+ "THOP_SNB",
+ "THOP_CRGIID",
+ "THOP_OLESTREAM",
+ "THOP_HTASK",
+ "THOP_INTERFACEINFO",
+ "THOP_IFACE",
+ "THOP_IFACEOWNER",
+ "THOP_IFACENOADDREF",
+ "THOP_IFACECLEAN",
+ "THOP_IFACEGEN",
+ "THOP_IFACEGENOWNER",
+ "THOP_ROUTINEINDEX",
+ "THOP_RETURNTYPE",
+ "THOP_NULL",
+ "THOP_ERROR",
+ "THOP_ENUM",
+ "THOP_CALLBACK",
+ "THOP_RPCOLEMESSAGE",
+ "THOP_ALIAS32",
+ "THOP_CLSCONTEXT",
+ "THOP_FILENAME",
+ "THOP_SIZEDSTRING"
+};
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: ThopName, debug public
+//
+// Synopsis: Returns the string name of a thop
+//
+// Arguments: [thop] - Thop
+//
+// Returns: Pointer to string
+//
+// History: 11-Mar-94 DrewB Created
+//
+// Notes: Uses a static buffer
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+char *ThopName(THOP thop)
+{
+ static char achString[80];
+ char *psz;
+
+ thkAssert((thop & THOP_OPMASK) < THOP_LASTOP);
+ thkAssert(THOP_LASTOP ==
+ (sizeof(apszThopNames)/sizeof(apszThopNames[0])));
+
+ strcpy(achString, apszThopNames[thop & THOP_OPMASK]);
+
+ psz = achString+strlen(achString);
+ if (thop & THOP_IN)
+ {
+ strcpy(psz, " | THOP_IN");
+ psz += strlen(psz);
+ }
+ if (thop & THOP_OUT)
+ {
+ strcpy(psz, " | THOP_OUT");
+ }
+
+ return achString;
+}
+#endif
+
+#if DBG == 1
+ char *apszEnumThopNames[] =
+{
+ "STRING",
+ "UNKNOWN",
+ "STATSTG",
+ "FORMATETC",
+ "STATDATA",
+ "MONIKER",
+ "OLEVERB"
+};
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: EnumThopName, debug public
+//
+// Synopsis: Returns the string name of an enum thop
+//
+// Arguments: [thopEnum] - Thop
+//
+// Returns: Pointer to string
+//
+// History: 11-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+char *EnumThopName(THOP thopEnum)
+{
+ thkAssert(thopEnum <
+ (sizeof(apszEnumThopNames)/sizeof(apszEnumThopNames[0])));
+ return apszEnumThopNames[thopEnum];
+}
+#endif
+
+#if DBG == 1
+// Maintain current thunking invocation nesting level
+int _iThunkNestingLevel = 1;
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: NestingSpaces, debug public
+//
+// Synopsis: Spaces for each nesting level
+//
+// History: 22-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+
+#define NESTING_SPACES 32
+#define SPACES_PER_LEVEL 2
+
+static char achSpaces[NESTING_SPACES+1] = " ";
+
+void NestingSpaces(char *psz)
+{
+ int iSpaces, i;
+
+ iSpaces = _iThunkNestingLevel*SPACES_PER_LEVEL;
+
+ while (iSpaces > 0)
+ {
+ i = min(iSpaces, NESTING_SPACES);
+ memcpy(psz, achSpaces, i);
+ psz += i;
+ *psz = 0;
+ iSpaces -= i;
+ }
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: NestingLevelString, debug public
+//
+// Synopsis: Provides a string describing the nesting level
+//
+// History: 22-Mar-94 DrewB Created
+//
+// Notes: Uses a static buffer
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+char *NestingLevelString(void)
+{
+ static char ach[256];
+ char *psz;
+
+ if ((thkInfoLevel & DEB_NESTING) == 0)
+ {
+ return "";
+ }
+
+ wsprintfA(ach, "%2d:", _iThunkNestingLevel);
+ psz = ach+strlen(ach);
+
+ if (sizeof(ach)/SPACES_PER_LEVEL <= _iThunkNestingLevel)
+ {
+ strcpy(psz, "...");
+ }
+ else
+ {
+ NestingSpaces(psz);
+ }
+ return ach;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: IidOrInterfaceString, debug public
+//
+// Synopsis: Returns the interface name for known interfaces or
+// the IID string itself
+//
+// Arguments: [piid] - IID
+//
+// Returns: char *
+//
+// History: 18-Jun-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+char *IidOrInterfaceString(IID const *piid)
+{
+ return IidIdxString(IidToIidIdx(*piid));
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: IidIdxString, debug public
+//
+// Synopsis: Returns the interface name for known interfaces or
+// the IID string itself
+//
+// Arguments: [iidx] - IID or index
+//
+// Returns: char *
+//
+// History: 07-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+char *IidIdxString(IIDIDX iidx)
+{
+ if (IIDIDX_IS_IID(iidx))
+ {
+ return GuidString(IIDIDX_IID(iidx));
+ }
+ else if (IIDIDX_INDEX(iidx) == THI_COUNT)
+ {
+ // Special case here because of IMalloc's unusual unthunked-
+ // but-indexed existence
+ return "IMalloc";
+ }
+ else
+ {
+ return inInterfaceNames[IIDIDX_INDEX(iidx)].pszInterface;
+ }
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: Handler routines, public
+//
+// Synopsis: Generic conversion routines for the generic thop handler
+//
+// Arguments: [pbFrom] - Data to convert from
+// [pbTo] - Buffer to convert into
+// [cbFrom] - Size of source data
+// [cbTo] - Size of destination data
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+//+---------------------------------------------------------------------------
+//
+// Function: FhCopyMemory, public
+//
+// Synopsis: Handler routine for memory copies
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhCopyMemory(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == cbTo);
+
+ memcpy(pbTo, pbFrom, cbFrom);
+
+#if DBG == 1
+ if (cbFrom == sizeof(DWORD))
+ {
+ thkDebugOut((DEB_ARGS, "Arg DWORD: 0x%08lX\n",
+ *(DWORD UNALIGNED *)pbFrom));
+ }
+ else if (cbFrom == sizeof(LARGE_INTEGER))
+ {
+ thkDebugOut((DEB_ARGS, "Arg 8 byte: 0x%08lX:%08lX\n",
+ *(DWORD UNALIGNED *)(pbFrom+1*sizeof(DWORD)),
+ *(DWORD UNALIGNED *)(pbFrom+0*sizeof(DWORD))));
+ }
+ else if (cbFrom == sizeof(GUID))
+ {
+ thkDebugOut((DEB_ARGS, "Arg 16 byte: 0x%08lX:%08lX:%08lX:%08lX\n",
+ *(DWORD UNALIGNED *)(pbFrom+3*sizeof(DWORD)),
+ *(DWORD UNALIGNED *)(pbFrom+2*sizeof(DWORD)),
+ *(DWORD UNALIGNED *)(pbFrom+1*sizeof(DWORD)),
+ *(DWORD UNALIGNED *)(pbFrom+0*sizeof(DWORD))));
+ }
+ else
+ {
+ thkDebugOut((DEB_ARGS, "Arg %d byte copy\n", cbFrom));
+ }
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: FhShortToLong, FhLongToShort, public
+//
+// Synopsis: Signed int conversion
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhShortToLong(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(SHORT));
+ thkAssert(cbTo == sizeof(LONG));
+
+ *(LONG UNALIGNED *)pbTo = (LONG)*(SHORT UNALIGNED *)pbFrom;
+
+ thkDebugOut((DEB_ARGS, "ShToLo %d -> %d\n",
+ *(SHORT UNALIGNED *)pbFrom, *(LONG UNALIGNED *)pbTo));
+}
+
+void FhLongToShort(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(LONG));
+ thkAssert(cbTo == sizeof(SHORT));
+
+ // Not used in situations where clamping is meaningful
+ *(SHORT UNALIGNED *)pbTo = (SHORT)*(LONG UNALIGNED *)pbFrom;
+
+ thkDebugOut((DEB_ARGS, "LoToSh %d -> %d\n",
+ *(LONG UNALIGNED *)pbFrom, *(SHORT UNALIGNED *)pbTo));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: FhWordToDword, FhDwordToWord, public
+//
+// Synopsis: Handler routine for memory copies
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhWordToDword(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(WORD));
+ thkAssert(cbTo == sizeof(DWORD));
+
+ *(DWORD UNALIGNED *)pbTo = (DWORD)*(WORD UNALIGNED *)pbFrom;
+
+ thkDebugOut((DEB_ARGS, "WoToDw 0x%04lX -> 0x%08lX\n",
+ *(WORD UNALIGNED *)pbFrom, *(DWORD UNALIGNED *)pbTo));
+}
+
+void FhDwordToWord(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(DWORD));
+ thkAssert(cbTo == sizeof(WORD));
+
+ // Not used in situations where clamping is meaningful
+ *(WORD UNALIGNED *)pbTo = (WORD)*(DWORD UNALIGNED *)pbFrom;
+
+ thkDebugOut((DEB_ARGS, "DwToWo 0x%08lX -> 0x%04lX\n",
+ *(DWORD UNALIGNED *)pbFrom, *(WORD UNALIGNED *)pbTo));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Handle routines, public
+//
+// Synopsis: Handler routine for Windows handles
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhGdiHandle1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HAND16));
+ thkAssert(cbTo == sizeof(HANDLE));
+
+ *(HBITMAP *)pbTo = HBITMAP_32(*(HBITMAP16 UNALIGNED *)pbFrom);
+
+ thkDebugOut((DEB_ARGS, "1632 HGdi: 0x%04lX -> 0x%p\n",
+ *(HAND16 UNALIGNED *)pbFrom, *(HANDLE *)pbTo));
+}
+
+void FhGdiHandle3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HANDLE));
+ thkAssert(cbTo == sizeof(HAND16));
+
+ *(HAND16 UNALIGNED *)pbTo = HBITMAP_16(*(HANDLE *)pbFrom);
+
+ thkDebugOut((DEB_ARGS, "3216 HGdi: 0x%p -> 0x%04lX\n",
+ *(HANDLE *)pbFrom, *(HAND16 UNALIGNED *)pbTo));
+}
+
+void FhUserHandle1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HAND16));
+ thkAssert(cbTo == sizeof(HANDLE));
+
+ // Even though the constant is WOW_TYPE_FULLHWND, it
+ // works for any user handle
+
+ *(HANDLE *)pbTo = WOWHandle32(*(HAND16 UNALIGNED *)pbFrom,
+ WOW_TYPE_FULLHWND);
+
+ thkDebugOut((DEB_ARGS, "1632 HUser: 0x%04lX -> 0x%p\n",
+ *(HAND16 UNALIGNED *)pbFrom, *(HANDLE *)pbTo));
+}
+
+void FhUserHandle3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HANDLE));
+ thkAssert(cbTo == sizeof(HAND16));
+
+ *(HAND16 UNALIGNED *)pbTo = HWND_16(*(HANDLE *)pbFrom);
+
+ thkDebugOut((DEB_ARGS, "3216 HUser: 0x%p -> 0x%04lX\n",
+ *(HANDLE *)pbFrom, *(HAND16 UNALIGNED *)pbTo));
+}
+
+void FhHaccel1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HAND16));
+ thkAssert(cbTo == sizeof(HANDLE));
+
+ *(HANDLE *)pbTo = HACCEL_32(*(HAND16 UNALIGNED *)pbFrom);
+
+ thkDebugOut((DEB_ARGS, "1632 HACCEL: 0x%04lX -> 0x%p\n",
+ *(HAND16 UNALIGNED *)pbFrom, *(HANDLE *)pbTo));
+}
+
+void FhHaccel3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HANDLE));
+ thkAssert(cbTo == sizeof(HAND16));
+
+ *(HAND16 UNALIGNED *)pbTo = HACCEL_16(*(HANDLE *)pbFrom);
+
+ thkDebugOut((DEB_ARGS, "3216 HACCEL: 0x%p -> 0x%04lX\n",
+ *(HANDLE *)pbFrom, *(HAND16 UNALIGNED *)pbTo));
+}
+
+void FhHtask1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ HAND16 h16;
+ DWORD h32;
+ thkAssert(cbFrom == sizeof(HAND16));
+ thkAssert(cbTo == sizeof(HANDLE));
+
+ h16 = *(HAND16 UNALIGNED *)pbFrom;
+ if ( h16 == 0 )
+ {
+ h32 = 0;
+ }
+ else
+ {
+ h32 = HTASK_32(h16);
+ }
+ *(DWORD *)pbTo = h32;
+
+ thkDebugOut((DEB_ARGS, "1632 HTASK: 0x%04lX -> 0x%p\n", h16, h32));
+}
+
+void FhHtask3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ HAND16 h16;
+ HANDLE h32;
+
+ thkAssert(cbFrom == sizeof(HANDLE));
+ thkAssert(cbTo == sizeof(HAND16));
+
+ h32 = *(HANDLE *)pbFrom;
+ if ( h32 == NULL )
+ {
+ h16 = 0;
+ }
+ else
+ {
+ h16 = HTASK_16(h32);
+ }
+ *(HAND16 UNALIGNED *)pbTo = h16;
+
+ thkDebugOut((DEB_ARGS, "3216 HTASK: 0x%p -> 0x%04lX\n",h32, h16));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: HRESULT routines, public
+//
+// Synopsis: Handler routine for HRESULTs
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhHresult1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HRESULT));
+ thkAssert(cbTo == sizeof(HRESULT));
+
+ *(HRESULT *)pbTo = TransformHRESULT_1632(*(HRESULT UNALIGNED *)pbFrom);
+
+ thkDebugOut((DEB_ARGS, "1632 HRESULT: 0x%08lX -> 0x%08lX\n",
+ *(HRESULT UNALIGNED *)pbFrom, *(HRESULT *)pbTo));
+}
+
+void FhHresult3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(HRESULT));
+ thkAssert(cbTo == sizeof(HRESULT));
+
+ *(HRESULT UNALIGNED *)pbTo = TransformHRESULT_3216(*(HRESULT *)pbFrom);
+
+ thkDebugOut((DEB_ARGS, "3216 HRESULT: 0x%08lX -> 0x%08lX\n",
+ *(HRESULT *)pbFrom, *(HRESULT UNALIGNED *)pbTo));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: NULL routines, public
+//
+// Synopsis: Handler routine for NULL
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhNull(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ thkAssert(cbFrom == sizeof(void *));
+ thkAssert(cbTo == sizeof(void *));
+
+ thkDebugOut((DEB_WARN, "FhNull: %p NULL value not NULL\n", pbFrom));
+ *(void UNALIGNED **)pbTo = NULL;
+
+ thkDebugOut((DEB_ARGS, "Arg NULL\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Rect routines, public
+//
+// Synopsis: Handler routines for RECT
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhRect1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ RECT *pr32;
+ RECT16 UNALIGNED * pr16;
+
+ thkAssert(cbFrom == sizeof(RECT16));
+ thkAssert(cbTo == sizeof(RECT));
+
+ pr16 = (RECT16 UNALIGNED *)pbFrom;
+ pr32 = (RECT *)pbTo;
+
+ pr32->left = (LONG)pr16->left; // Sign extend
+ pr32->top = (LONG)pr16->top; // Sign extend
+ pr32->right = (LONG)pr16->right; // Sign extend
+ pr32->bottom = (LONG)pr16->bottom; // Sign extend
+
+ thkDebugOut((DEB_ARGS, "1632 RECT: {%d, %d, %d, %d}\n",
+ pr32->left, pr32->top, pr32->right, pr32->bottom));
+}
+
+void FhRect3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ RECT *pr32;
+ RECT16 UNALIGNED *pr16;
+
+ thkAssert(cbFrom == sizeof(RECT));
+ thkAssert(cbTo == sizeof(RECT16));
+
+ pr32 = (RECT *)pbFrom;
+ pr16 = (RECT16 UNALIGNED *)pbTo;
+
+ pr16->left = ClampLongToShort(pr32->left);
+ pr16->top = ClampLongToShort(pr32->top);
+ pr16->right = ClampLongToShort(pr32->right);
+ pr16->bottom = ClampLongToShort(pr32->bottom);
+
+ thkDebugOut((DEB_ARGS, "3216 RECT: {%d, %d, %d, %d}\n",
+ pr32->left, pr32->top, pr32->right, pr32->bottom));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Size routines, public
+//
+// Synopsis: Handler routines for SIZE
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhSize1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ SIZE16 UNALIGNED *psize16;
+ SIZE *psize32;
+
+ thkAssert(cbFrom == sizeof(SIZE16));
+ thkAssert(cbTo == sizeof(SIZE));
+
+ psize16 = (SIZE16 UNALIGNED *)pbFrom;
+ psize32 = (SIZE *)pbTo;
+
+ psize32->cx = (LONG)psize16->cx;
+ psize32->cy = (LONG)psize16->cy;
+
+ thkDebugOut((DEB_ARGS, "1632 SIZE: {%d, %d}\n",
+ psize32->cx, psize32->cy));
+}
+
+void FhSize3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ SIZE16 UNALIGNED *psize16;
+ SIZE *psize32;
+
+ thkAssert(cbFrom == sizeof(SIZE));
+ thkAssert(cbTo == sizeof(SIZE16));
+
+ psize32 = (SIZE *)pbFrom;
+ psize16 = (SIZE16 UNALIGNED *)pbTo;
+
+ psize16->cx = ClampLongToShort(psize32->cx);
+ psize16->cy = ClampLongToShort(psize32->cy);
+
+ thkDebugOut((DEB_ARGS, "3216 SIZE: {%d, %d}\n",
+ psize32->cx, psize32->cy));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Message routines, public
+//
+// Synopsis: Handler routines for MSG
+//
+// History: 05-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void FhMsg1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ MSG16 UNALIGNED *pmsg16;
+ MSG *pmsg32;
+
+ thkAssert(cbFrom == sizeof(MSG16));
+ thkAssert(cbTo == sizeof(MSG));
+
+ pmsg16 = (MSG16 UNALIGNED *)pbFrom;
+ pmsg32 = (MSG *)pbTo;
+
+ pmsg32->hwnd = HWND_32(pmsg16->hwnd);
+ pmsg32->message = (UINT)pmsg16->message;
+ pmsg32->wParam = (WPARAM)pmsg16->wParam; // Should we sign extend?
+ pmsg32->lParam = (LPARAM)pmsg16->lParam;
+ pmsg32->time = pmsg16->time;
+ pmsg32->pt.x = (LONG)(SHORT)LOWORD(pmsg16->pt); // Sign extend
+ pmsg32->pt.y = (LONG)(SHORT)HIWORD(pmsg16->pt); // Sign extend
+
+ thkDebugOut((DEB_ARGS, "1632 MSG: {0x%p, %d, 0x%08lX, 0x%08lX, "
+ "0x%08lX, {%d, %d}}\n",
+ pmsg32->hwnd, pmsg32->message, pmsg32->wParam,
+ pmsg32->lParam, pmsg32->time, pmsg32->pt.x,
+ pmsg32->pt.y));
+}
+
+void FhMsg3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo)
+{
+ MSG16 UNALIGNED *pmsg16;
+ MSG *pmsg32;
+
+ thkAssert(cbFrom == sizeof(MSG));
+ thkAssert(cbTo == sizeof(MSG16));
+
+ pmsg32 = (MSG *)pbFrom;
+ pmsg16 = (MSG16 UNALIGNED *)pbTo;
+
+ pmsg16->hwnd = HWND_16(pmsg32->hwnd);
+ pmsg16->message = (WORD)pmsg32->message;
+ pmsg16->wParam = (WORD)pmsg32->wParam; // Sign truncate
+ pmsg16->lParam = (LONG)pmsg32->lParam;
+ pmsg16->time = pmsg32->time;
+ pmsg16->pt = MAKELONG(ClampLongToShort(pmsg32->pt.x),
+ ClampLongToShort(pmsg32->pt.y));
+
+ thkDebugOut((DEB_ARGS, "3216 MSG: {0x%p, %d, 0x%08lX, 0x%08lX, "
+ "0x%08lX, {%d, %d}}\n",
+ pmsg32->hwnd, pmsg32->message, pmsg32->wParam,
+ pmsg32->lParam, pmsg32->time, pmsg32->pt.x,
+ pmsg32->pt.y));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ALLOCROUTINE, public
+//
+// Synopsis: A routine which allocates memory
+//
+// Arguments: [cb] - Amount to allocate
+//
+// Returns: Pointer to memory
+//
+// History: 19-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+//+---------------------------------------------------------------------------
+//
+// Function: FREEROUTINE, public
+//
+// Synopsis: A routine which frees memory
+//
+// Arguments: [pv] - Memory to free
+// [cb] - Size of memory to free
+//
+// History: 19-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void *ArTask16(UINT cb)
+{
+ return (void *)TaskMalloc16(cb);
+}
+
+void FrTask16(void *pv, UINT cb)
+{
+ TaskFree16((VPVOID)pv);
+}
+
+void *ArTask32(UINT cb)
+{
+ return TaskMalloc32(cb);
+}
+
+void FrTask32(void *pv, UINT cb)
+{
+ TaskFree32(pv);
+}
+
+void *ArStack16(UINT cb)
+{
+ return (void *)STACKALLOC16(cb);
+}
+
+void FrStack16(void *pv, UINT cb)
+{
+ STACKFREE16((VPVOID)pv, cb);
+}
+
+void *ArStack32(UINT cb)
+{
+ // Can't use STACKALLOC32 on NT since it may be _alloca which wouldn't
+ // live beyond this routine
+#ifdef _CHICAGO_
+ return STACKALLOC32(cb);
+#else
+ return (void *)LocalAlloc(LMEM_FIXED, cb);
+#endif
+}
+
+void FrStack32(void *pv, UINT cb)
+{
+#ifdef _CHICAGO_
+ STACKFREE32(pv, cb);
+#else
+ LocalFree(pv);
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertDvtd1632, private
+//
+// Synopsis: Converts a DVTARGETDEVICE from 16 to 32-bits
+//
+// Arguments: [pti] - Thunking state information
+// [vpdvtd16] - Source
+// [pfnAlloc] - ALLOCROUTINE
+// [pfnFree] - FREEROUTINE
+// [ppdvtd32] - Destination
+// [pcbSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdvtd32]
+// [pcbSize]
+//
+// History: 18-Apr-94 DrewB Created
+//
+// Notes: [pfnAlloc/Free] must deal with 32-bit memory
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertDvtd1632(THUNKINFO *pti,
+ VPVOID vpdvtd16,
+ ALLOCROUTINE pfnAlloc,
+ FREEROUTINE pfnFree,
+ DVTARGETDEVICE **ppdvtd32,
+ UINT *pcbSize)
+{
+ DVTARGETDEVICE UNALIGNED *pdvtd16;
+ DVTARGETDEVICE *pdvtd32;
+ DVTDINFO dvtdi;
+
+ pdvtd16 = (DVTARGETDEVICE UNALIGNED *)GetReadPtr16(pti, vpdvtd16,
+ sizeof(DVTARGETDEVICE));
+ if (pdvtd16 == NULL)
+ {
+ return pti->scResult;
+ }
+
+ pdvtd16 = (DVTARGETDEVICE UNALIGNED *)GetReadPtr16(pti, vpdvtd16,
+ pdvtd16->tdSize);
+
+ WOWRELVDMPTR(vpdvtd16);
+
+ if (pdvtd16 == NULL)
+ {
+ return pti->scResult;
+ }
+
+ pti->scResult = UtGetDvtd16Info( pdvtd16, &dvtdi );
+
+ if ( FAILED(pti->scResult) )
+ {
+ WOWRELVDMPTR(vpdvtd16);
+ return pti->scResult;
+ }
+
+ pdvtd32 = (DVTARGETDEVICE *)pfnAlloc(dvtdi.cbConvertSize);
+ if (pdvtd32 == NULL)
+ {
+ WOWRELVDMPTR(vpdvtd16);
+ return E_OUTOFMEMORY;
+ }
+
+ pti->scResult = UtConvertDvtd16toDvtd32( pdvtd16, &dvtdi, pdvtd32 );
+
+ WOWRELVDMPTR(vpdvtd16);
+
+ if ( FAILED(pti->scResult) )
+ {
+ pfnFree(pdvtd32, dvtdi.cbConvertSize);
+ return pti->scResult;
+ }
+
+ *ppdvtd32 = pdvtd32;
+ *pcbSize = dvtdi.cbConvertSize;
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertDvtd3216, private
+//
+// Synopsis: Converts a DVTARGETDEVICE from 32 to 16-bits
+//
+// Arguments: [pti] - Thunking state information
+// [pdvtd32] - Source
+// [pfnAlloc] - Allocator
+// [pfnFree] - Freer
+// [ppvdvtd16] - Destination
+// [pcbSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvdvtd16]
+// [pcbSize]
+//
+// History: 18-Apr-94 DrewB Created
+//
+// Notes: [pfnAlloc/Free] must deal with 16-bit memory
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertDvtd3216(THUNKINFO *pti,
+ DVTARGETDEVICE *pdvtd32,
+ ALLOCROUTINE pfnAlloc,
+ FREEROUTINE pfnFree,
+ VPVOID *ppvdvtd16,
+ UINT *pcbSize)
+{
+ DVTARGETDEVICE UNALIGNED *pdvtd16;
+ VPVOID vpdvtd16;
+ DVTDINFO dvtdi;
+
+ if (IsBadReadPtr(pdvtd32, sizeof(DVTARGETDEVICE)) ||
+ IsBadReadPtr(pdvtd32, pdvtd32->tdSize))
+ {
+ return E_INVALIDARG;
+ }
+
+ pti->scResult = UtGetDvtd32Info( pdvtd32, &dvtdi );
+
+ if ( FAILED(pti->scResult) )
+ {
+ return pti->scResult;
+ }
+
+ vpdvtd16 = (VPVOID)pfnAlloc(dvtdi.cbConvertSize);
+ if (vpdvtd16 == 0)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ pdvtd16 = (DVTARGETDEVICE UNALIGNED *)WOWFIXVDMPTR(vpdvtd16,
+ dvtdi.cbConvertSize);
+
+ pti->scResult = UtConvertDvtd32toDvtd16( pdvtd32, &dvtdi, pdvtd16 );
+
+ WOWRELVDMPTR(vpdvtd16);
+
+ if ( FAILED(pti->scResult) )
+ {
+ pfnFree((void *)vpdvtd16, dvtdi.cbConvertSize);
+ return pti->scResult;
+ }
+
+ *ppvdvtd16 = vpdvtd16;
+ *pcbSize = dvtdi.cbConvertSize;
+
+ return S_OK;
+}
+
+#if !defined(_CHICAGO_)
+
+SCODE ConvertHDrop1632(HMEM16 hg16, HGLOBAL* phg32)
+{
+ SCODE sc = S_OK;
+
+ *phg32 = CopyDropFilesFrom16(hg16);
+ if (!*phg32)
+ sc = E_INVALIDARG;
+
+ return sc;
+}
+
+
+SCODE ConvertHDrop3216(HGLOBAL hg32, HMEM16* phg16)
+{
+ SCODE sc = S_OK;
+
+ *phg16 = CopyDropFilesFrom32(hg32);
+ if (!*phg16)
+ sc = E_INVALIDARG;
+
+ return sc;
+}
+
+#endif
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertHGlobal1632, public
+//
+// Synopsis: Creates a 32-bit HGLOBAL for a 16-bit HGLOBAL
+//
+// Arguments: [pti] - Thunk info, can be NULL for no validation
+// [hg16] - 16-bit HGLOBAL
+// [thopInOut] - Validation type
+// [phg32] - 32-bit HGLOBAL in/out
+// [pdwSize] - Size in/out
+//
+// Returns: Appropriate status code
+//
+// Modifies: [phg32]
+// [pdwSize]
+//
+// History: 24-Apr-94 DrewB Created
+//
+// Notes: If [phg32] is non-NULL on entry, [pdwSize] must be set
+// appropriately also
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertHGlobal1632(THUNKINFO *pti,
+ HMEM16 hg16,
+ THOP thopInOut,
+ HGLOBAL *phg32,
+ DWORD *pdwSize)
+{
+ SCODE sc;
+ VPVOID vpdata16;
+ LPVOID lpdata16;
+ LPVOID lpdata32;
+ HGLOBAL hg32;
+ DWORD dwSize;
+ BOOL fOwn;
+
+ sc = S_OK;
+
+ vpdata16 = WOWGlobalLockSize16( hg16, &dwSize );
+ if ( vpdata16 == 0 )
+ {
+ sc = E_INVALIDARG;
+ }
+ else
+ {
+ if (*phg32 != 0 && *pdwSize == dwSize)
+ {
+ hg32 = *phg32;
+ fOwn = FALSE;
+ }
+ else
+ {
+ hg32 = GlobalAlloc( GMEM_MOVEABLE, dwSize );
+ fOwn = TRUE;
+ }
+
+ if ( hg32 == 0 )
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ lpdata32 = GlobalLock( hg32 );
+
+ lpdata16 = (LPVOID)ValidatePtr16(pti, vpdata16, dwSize, thopInOut);
+ if ( lpdata16 != NULL )
+ {
+ memcpy( lpdata32, lpdata16, dwSize );
+ WOWRELVDMPTR(vpdata16);
+ }
+ else
+ {
+ sc = pti->scResult;
+ }
+
+ GlobalUnlock(hg32);
+
+ if (FAILED(sc) && fOwn)
+ {
+ GlobalFree(hg32);
+ }
+ }
+
+ WOWGlobalUnlock16( hg16 );
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ if (*phg32 != 0 && hg32 != *phg32)
+ {
+ GlobalFree(*phg32);
+ }
+
+ *phg32 = hg32;
+ *pdwSize = dwSize;
+
+ thkDebugOut((DEB_ARGS, "1632 HGLOBAL: 0x%04X -> 0x%p, %u\n",
+ hg16, hg32, dwSize));
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertHGlobal3216, public
+//
+// Synopsis: Creates a 16-bit HGLOBAL for a 32-bit HGLOBAL
+//
+// Arguments: [pti] - Thunk info, can be NULL for no validation
+// [hg32] - 32-bit HGLOBAL
+// [thopInOut] - Validation type
+// [phg16] - 16-bit HGLOBAL in/out
+// [pdwSize] - Size in/out
+//
+// Returns: Appropriate status code
+//
+// Modifies: [phg16]
+// [pdwSize]
+//
+// History: 24-Apr-94 DrewB Created
+//
+// Notes: If [phg16] is non-NULL on entry, [pdwSize] must be set
+// appropriately also
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertHGlobal3216(THUNKINFO *pti,
+ HGLOBAL hg32,
+ THOP thopInOut,
+ HMEM16 *phg16,
+ DWORD *pdwSize)
+{
+ SCODE sc;
+ VPVOID vpdata16;
+ LPVOID lpdata16;
+ LPVOID lpdata32;
+ HMEM16 hg16;
+ DWORD dwSize;
+ BOOL fOwn;
+
+ sc = S_OK;
+
+ dwSize = GlobalSize(hg32);
+ if (dwSize == 0)
+ {
+ sc = E_INVALIDARG;
+ }
+ else
+ {
+ lpdata32 = GlobalLock(hg32);
+
+ if (*phg16 != 0 && *pdwSize == dwSize)
+ {
+ hg16 = *phg16;
+ vpdata16 = WOWGlobalLock16(hg16);
+ fOwn = FALSE;
+ }
+ else
+ {
+ vpdata16 = WOWGlobalAllocLock16(GMEM_MOVEABLE | GMEM_DDESHARE,
+ dwSize, &hg16);
+ fOwn = TRUE;
+ }
+
+ if (vpdata16 == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ lpdata16 = (LPVOID)WOWFIXVDMPTR( vpdata16, dwSize );
+ if ( lpdata16 == NULL )
+ {
+ sc = E_UNEXPECTED;
+ }
+ else
+ {
+ memcpy( lpdata16, lpdata32, dwSize );
+
+ WOWRELVDMPTR(vpdata16);
+ }
+
+ WOWGlobalUnlock16( hg16 );
+
+ if (FAILED(sc) && fOwn)
+ {
+ WOWGlobalFree16(hg16);
+ }
+ }
+
+ GlobalUnlock(hg32);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ if (*phg16 != 0 && hg16 != *phg16)
+ {
+ WOWGlobalFree16(*phg16);
+ }
+
+ *phg16 = hg16;
+ *pdwSize = dwSize;
+
+ thkDebugOut((DEB_ARGS, "3216 HGLOBAL: 0x%p -> 0x%04X, %u\n",
+ hg32, hg16, dwSize));
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertMfPict1632, public
+//
+// Synopsis: Converts a 16-bit METAFILEPICT to 32-bit
+//
+// Arguments: [pti] - Thunk info
+// [hg16] - 16-bit HGLOBAL containing METAFILEPICT
+// [phg32] - 32-bit HGLOBAL return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [phg32]
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+ SCODE ConvertMfPict1632(THUNKINFO *pti,
+ HMEM16 hg16,
+ HGLOBAL *phg32)
+{
+ SCODE sc;
+ VPVOID vpmfp16;
+ METAFILEPICT16 UNALIGNED *pmfp16;
+ METAFILEPICT *pmfp32;
+ HGLOBAL hg32;
+ DWORD dwSize;
+#if DBG == 1
+ BOOL fSaveToFile = FALSE;
+#endif
+
+ thkDebugOut((DEB_ITRACE, "In ConvertMfPict1632(%p, 0x%04X, %p)\n",
+ pti, hg16, phg32));
+
+ *phg32 = 0;
+ sc = S_OK;
+
+ vpmfp16 = WOWGlobalLockSize16( hg16, &dwSize );
+ if ( vpmfp16 == 0 || dwSize < sizeof(METAFILEPICT16))
+ {
+ sc = E_INVALIDARG;
+ }
+ else
+ {
+ hg32 = GlobalAlloc( GMEM_MOVEABLE, sizeof(METAFILEPICT) );
+ if ( hg32 == 0 )
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ pmfp32 = (METAFILEPICT *)GlobalLock( hg32 );
+
+ pmfp16 = (METAFILEPICT16 UNALIGNED *)GetReadPtr16(pti, vpmfp16,
+ dwSize);
+ if ( pmfp16 != NULL )
+ {
+ pmfp32->mm = (LONG)pmfp16->mm;
+ pmfp32->xExt = (LONG)pmfp16->xExt;
+ pmfp32->yExt = (LONG)pmfp16->yExt;
+
+ pmfp32->hMF = HMETAFILE_32(pmfp16->hMF);
+
+ thkDebugOut((DEB_ARGS, "1632 METAFILEPICT: "
+ "{%d, %d, %d, 0x%p} -> {%d, %d, %d, 0x%4x}\n",
+ pmfp16->mm, pmfp16->xExt, pmfp16->yExt, pmfp16->hMF,
+ pmfp32->mm, pmfp32->xExt, pmfp32->yExt, pmfp32->hMF));
+
+ WOWRELVDMPTR(vpmfp16);
+
+#if DBG == 1
+ if (fSaveToFile)
+ {
+ HMETAFILE hmf;
+
+ hmf = CopyMetaFile(pmfp32->hMF, __TEXT("thkmf.wmf"));
+ if (hmf != NULL)
+ {
+ DeleteMetaFile(hmf);
+ }
+ }
+#endif
+ }
+ else
+ {
+ sc = pti->scResult;
+ }
+
+ GlobalUnlock(hg32);
+
+ if (FAILED(sc))
+ {
+ GlobalFree(hg32);
+ }
+ }
+
+ WOWGlobalUnlock16( hg16 );
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ *phg32 = hg32;
+ }
+
+ thkDebugOut((DEB_ITRACE, "Out ConvertMfPict1632 => 0x%08lX, 0x%p\n",
+ sc, *phg32));
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertMfPict3216, public
+//
+// Synopsis: Converts a 32-bit METAFILEPICT to 16-bit
+//
+// Arguments: [pti] - Thunk info
+// [hg32] - 32-bit HGLOBAL containing METAFILEPICT
+// [phg16] - 16-bit HGLOBAL return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [phg16]
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+ SCODE ConvertMfPict3216(THUNKINFO *pti,
+ HGLOBAL hg32,
+ HMEM16 *phg16)
+{
+ SCODE sc;
+ VPVOID vpmfp16;
+ METAFILEPICT16 UNALIGNED *pmfp16;
+ METAFILEPICT *pmfp32;
+ DWORD dwSize;
+ HMEM16 hg16;
+#if DBG == 1
+ BOOL fSaveToFile = FALSE;
+#endif
+
+ thkDebugOut((DEB_ITRACE, "In ConvertMfPict3216(%p, 0x%p, %p)\n",
+ pti, hg32, phg16));
+
+ *phg16 = 0;
+ sc = S_OK;
+
+ dwSize = GlobalSize(hg32);
+ pmfp32 = (METAFILEPICT *)GlobalLock(hg32);
+ if (dwSize == 0 || dwSize < sizeof(METAFILEPICT) || pmfp32 == NULL)
+ {
+ sc = E_INVALIDARG;
+ }
+ else
+ {
+ vpmfp16 = WOWGlobalAllocLock16(GMEM_MOVEABLE | GMEM_DDESHARE,
+ sizeof(METAFILEPICT16), &hg16);
+ if (vpmfp16 == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ pmfp16 = FIXVDMPTR(vpmfp16, METAFILEPICT16);
+ if ( pmfp16 != NULL )
+ {
+ pmfp16->mm = (SHORT)pmfp32->mm;
+ pmfp16->xExt = ClampLongToShort(pmfp32->xExt);
+ pmfp16->yExt = ClampLongToShort(pmfp32->yExt);
+ pmfp16->hMF = HMETAFILE_16(pmfp32->hMF);
+
+ thkDebugOut((DEB_ARGS, "3216 METAFILEPICT: "
+ "{%d, %d, %d, 0x%p} -> {%d, %d, %d, 0x%4x}\n",
+ pmfp32->mm, pmfp32->xExt, pmfp32->yExt, pmfp32->hMF,
+ pmfp16->mm, pmfp16->xExt, pmfp16->yExt, pmfp16->hMF));
+
+ RELVDMPTR(vpmfp16);
+
+#if DBG == 1
+ if (fSaveToFile)
+ {
+ HMETAFILE hmf;
+
+ hmf = CopyMetaFile(pmfp32->hMF, __TEXT("thkmf.wmf"));
+ if (hmf != NULL)
+ {
+ DeleteMetaFile(hmf);
+ }
+ }
+#endif
+ }
+ else
+ {
+ sc = E_UNEXPECTED;
+ }
+
+ WOWGlobalUnlock16(hg16);
+
+ if (FAILED(sc))
+ {
+ WOWGlobalFree16(hg16);
+ }
+ }
+
+ GlobalUnlock(hg32);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ *phg16 = hg16;
+ }
+
+ thkDebugOut((DEB_ITRACE, "Out ConvertMfPict3216 => 0x%08lX, 0x%04X\n",
+ sc, *phg16));
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertObjDesc1632, public
+//
+// Synopsis: Converts an OBJECTDESCRIPTOR structure
+//
+// Arguments: [pti] - THUNKINFO
+// [hg16] - HGLOBAL containing structure
+// [phg32] - Output HGLOBAL
+//
+// Returns: Appropriate status code
+//
+// Modifies: [phg32]
+//
+// History: 04-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertObjDesc1632(THUNKINFO *pti,
+ HMEM16 hg16,
+ HGLOBAL *phg32)
+{
+ SCODE sc;
+ VPVOID vp16;
+ HGLOBAL hg32;
+ DWORD dwSize;
+ OBJECTDESCRIPTOR UNALIGNED *pod16;
+ OBJECTDESCRIPTOR *pod32;
+ char *pszFutn, *pszSoc;
+ UINT cchFutn, cchSoc;
+ UINT cbOffset;
+
+ sc = S_OK;
+
+ vp16 = WOWGlobalLock16(hg16);
+ if ( vp16 == 0 )
+ {
+ return E_INVALIDARG;
+ }
+
+ pszFutn = NULL;
+ pszSoc = NULL;
+
+ pod16 = (OBJECTDESCRIPTOR UNALIGNED *)
+ GetReadPtr16(pti, vp16, sizeof(OBJECTDESCRIPTOR));
+ if (pod16 == NULL)
+ {
+ sc = pti->scResult;
+ goto EH_Unlock;
+ }
+
+ dwSize = sizeof(OBJECTDESCRIPTOR);
+
+ if (pod16->dwFullUserTypeName > 0)
+ {
+ pszFutn = (char *)GetStringPtr16(pti, vp16+pod16->dwFullUserTypeName,
+ CCHMAXSTRING, &cchFutn);
+ if (pszFutn == NULL)
+ {
+ sc = pti->scResult;
+ goto EH_Unlock;
+ }
+
+ dwSize += cchFutn*sizeof(WCHAR);
+ }
+
+ if (pod16->dwSrcOfCopy > 0)
+ {
+ pszSoc = (char *)GetStringPtr16(pti, vp16+pod16->dwSrcOfCopy,
+ CCHMAXSTRING, &cchSoc);
+ if (pszSoc == NULL)
+ {
+ sc = pti->scResult;
+ goto EH_Unlock;
+ }
+
+ dwSize += cchSoc*sizeof(WCHAR);
+ }
+
+ hg32 = GlobalAlloc(GMEM_MOVEABLE, dwSize);
+ if ( hg32 == 0 )
+ {
+ sc = E_OUTOFMEMORY;
+ goto EH_Unlock;
+ }
+
+ pod32 = (OBJECTDESCRIPTOR *)GlobalLock(hg32);
+ memcpy(pod32, pod16, sizeof(OBJECTDESCRIPTOR));
+ pod32->cbSize = dwSize;
+
+ cbOffset = sizeof(OBJECTDESCRIPTOR);
+
+ if (pod16->dwFullUserTypeName > 0)
+ {
+ if (MultiByteToWideChar(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0, pszFutn, cchFutn,
+ (WCHAR *)((BYTE *)pod32+cbOffset),
+ cchFutn) == 0)
+ {
+ sc = E_UNEXPECTED;
+ goto EH_Free;
+ }
+
+ pod32->dwFullUserTypeName = cbOffset;
+ cbOffset += cchFutn*sizeof(WCHAR);
+ }
+
+ if (pod16->dwSrcOfCopy > 0)
+ {
+ if (MultiByteToWideChar(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0, pszSoc, cchSoc,
+ (WCHAR *)((BYTE *)pod32+cbOffset),
+ cchSoc) == 0)
+ {
+ sc = E_UNEXPECTED;
+ goto EH_Free;
+ }
+
+ pod32->dwSrcOfCopy = cbOffset;
+ cbOffset += cchFutn*sizeof(WCHAR);
+ }
+
+#if DBG == 1
+ WCHAR *pwcsFutn, *pwcsSoc;
+ if (pod32->dwFullUserTypeName > 0)
+ {
+ pwcsFutn = (WCHAR *)((BYTE *)pod32+pod32->dwFullUserTypeName);
+ }
+ else
+ {
+ pwcsFutn = NULL;
+ }
+ if (pod32->dwSrcOfCopy > 0)
+ {
+ pwcsSoc = (WCHAR *)((BYTE *)pod32+pod32->dwSrcOfCopy);
+ }
+ else
+ {
+ pwcsSoc = NULL;
+ }
+ thkDebugOut((DEB_ARGS, "1632 OBJECTDESCRIPTOR: "
+ "{%d, ..., \"%ws\" (%s), \"%ws\" (%s)} %p -> %p\n",
+ pod32->cbSize, pwcsFutn, pszFutn, pwcsSoc, pszSoc,
+ vp16, pod32));
+#endif
+
+ GlobalUnlock(hg32);
+
+ *phg32 = hg32;
+
+ EH_Unlock:
+ if (pszFutn != NULL)
+ {
+ WOWRELVDMPTR(vp16+pod16->dwFullUserTypeName);
+ }
+ if (pszSoc != NULL)
+ {
+ WOWRELVDMPTR(vp16+pod16->dwSrcOfCopy);
+ }
+ if (pod16 != NULL)
+ {
+ WOWRELVDMPTR(vp16);
+ }
+
+ WOWGlobalUnlock16(hg16);
+
+ return sc;
+
+ EH_Free:
+ GlobalUnlock(hg32);
+ GlobalFree(hg32);
+ goto EH_Unlock;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertObjDesc3216, public
+//
+// Synopsis: Converts an OBJECTDESCRIPTOR structure
+//
+// Arguments: [pti] - THUNKINFO
+// [hg32] - HGLOBAL containing structure
+// [phg16] - Output HGLOBAL
+//
+// Returns: Appropriate status code
+//
+// Modifies: [phg16]
+//
+// History: 04-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertObjDesc3216(THUNKINFO *pti,
+ HGLOBAL hg32,
+ HMEM16 *phg16)
+{
+ SCODE sc;
+ VPVOID vp16;
+ HMEM16 hg16;
+ DWORD dwSize;
+ OBJECTDESCRIPTOR UNALIGNED *pod16;
+ OBJECTDESCRIPTOR *pod32;
+ WCHAR *pwcsFutn, *pwcsSoc;
+ UINT cchFutn, cchSoc;
+ UINT cbOffset;
+
+ sc = S_OK;
+
+ pod32 = (OBJECTDESCRIPTOR *)GlobalLock(hg32);
+ if ( pod32 == 0 )
+ {
+ return E_INVALIDARG;
+ }
+
+ if (IsBadReadPtr(pod32, sizeof(OBJECTDESCRIPTOR)))
+ {
+ sc = E_INVALIDARG;
+ goto EH_Unlock;
+ }
+
+ dwSize = sizeof(OBJECTDESCRIPTOR);
+
+ pwcsFutn = NULL;
+ if (pod32->dwFullUserTypeName > 0)
+ {
+ pwcsFutn = (WCHAR *)((BYTE *)pod32+pod32->dwFullUserTypeName);
+ if (IsBadStringPtrW(pwcsFutn, CCHMAXSTRING))
+ {
+ sc = E_INVALIDARG;
+ goto EH_Unlock;
+ }
+
+ cchFutn = lstrlenW(pwcsFutn)+1;
+ dwSize += cchFutn*2;
+ }
+
+ pwcsSoc = NULL;
+ if (pod32->dwSrcOfCopy > 0)
+ {
+ pwcsSoc = (WCHAR *)((BYTE *)pod32+pod32->dwSrcOfCopy);
+ if (IsBadStringPtrW(pwcsSoc, CCHMAXSTRING))
+ {
+ sc = E_INVALIDARG;
+ goto EH_Unlock;
+ }
+
+ cchSoc = lstrlenW(pwcsSoc)+1;
+ dwSize += cchSoc*2;
+ }
+
+ vp16 = WOWGlobalAllocLock16(GMEM_MOVEABLE, dwSize, &hg16);
+ if ( vp16 == 0 )
+ {
+ sc = E_OUTOFMEMORY;
+ goto EH_Unlock;
+ }
+
+ pod16 = FIXVDMPTR(vp16, OBJECTDESCRIPTOR);
+ memcpy(pod16, pod32, sizeof(OBJECTDESCRIPTOR));
+ pod16->cbSize = dwSize;
+
+ cbOffset = sizeof(OBJECTDESCRIPTOR);
+
+ if (pod32->dwFullUserTypeName > 0)
+ {
+ if (WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0, pwcsFutn, cchFutn,
+ (char *)pod16+cbOffset, 2 * cchFutn,
+ NULL, NULL) == 0)
+ {
+ sc = E_UNEXPECTED;
+ goto EH_Free;
+ }
+
+ pod16->dwFullUserTypeName = cbOffset;
+ cbOffset += cchFutn*2;
+ }
+
+ if (pod32->dwSrcOfCopy > 0)
+ {
+ if (WideCharToMultiByte(AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0, pwcsSoc, cchSoc,
+ (char *)pod16+cbOffset, 2 * cchSoc,
+ NULL, NULL) == 0)
+ {
+ sc = E_UNEXPECTED;
+ goto EH_Free;
+ }
+
+ pod16->dwSrcOfCopy = cbOffset;
+ cbOffset += cchFutn*2;
+ }
+
+#if DBG == 1
+ char *pszFutn, *pszSoc;
+ if (pod16->dwFullUserTypeName > 0)
+ {
+ pszFutn = (char *)((BYTE *)pod16+pod16->dwFullUserTypeName);
+ }
+ else
+ {
+ pszFutn = NULL;
+ }
+ if (pod16->dwSrcOfCopy > 0)
+ {
+ pszSoc = (char *)((BYTE *)pod16+pod16->dwSrcOfCopy);
+ }
+ else
+ {
+ pszSoc = NULL;
+ }
+ thkDebugOut((DEB_ARGS, "3216 OBJECTDESCRIPTOR: "
+ "{%d, ..., \"%s\" (%ws), \"%s\" (%ws)} %p -> %p\n",
+ pod16->cbSize, pszFutn, pwcsFutn, pszSoc, pwcsSoc,
+ pod32, vp16));
+#endif
+
+ RELVDMPTR(vp16);
+
+ WOWGlobalUnlock16(hg16);
+
+ *phg16 = hg16;
+
+ EH_Unlock:
+ GlobalUnlock(hg32);
+
+ return sc;
+
+ EH_Free:
+ WOWGlobalUnlockFree16(vp16);
+ goto EH_Unlock;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSm32ReleaseHandler (srh)
+//
+// Purpose: Provides punkForRelease for 16->32 STGMEDIUM conversion
+//
+// Interface: IUnknown
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CSm32ReleaseHandler : public IUnknown
+{
+public:
+ CSm32ReleaseHandler(void)
+ {
+ _punkForRelease = NULL;
+ }
+ ~CSm32ReleaseHandler(void)
+ {
+ // Clean up proxy if it hasn't already been released
+ if (_punkForRelease)
+ {
+ _pThkMgr->FreeProxy3216((VPVOID)_sm16.pUnkForRelease);
+ }
+ }
+
+ void Init(CThkMgr *pThkMgr,
+ STGMEDIUM UNALIGNED *psm16,
+ STGMEDIUM *psm32,
+ IUnknown *punkForRelease,
+ CLIPFORMAT cfFormat)
+ {
+ // Unfortunately, the MIPS compiler is not smart enough
+ // to do the right thing if we just declare psm16 as UNALIGNED -- it
+ // doesn't recognize that each member of the structure is also
+ // unaligned when it does the structure copy. So...to make
+ // sure we don't generate an alignment fault, we just copy each
+ // member of the structure directly.
+
+ _sm16.tymed = psm16->tymed;
+ _sm16.hGlobal = psm16->hGlobal;
+ _sm16.pUnkForRelease = psm16->pUnkForRelease;
+ _sm32 = *psm32;
+ _punkForRelease = punkForRelease;
+ _cReferences = 1;
+ _cfFormat = cfFormat;
+ _pThkMgr = pThkMgr;
+ }
+
+ STDMETHOD(QueryInterface)(REFIID riid, void **ppv)
+ {
+ if ( IsEqualIID(riid,IID_IUnknown) )
+ {
+ *ppv = this;
+ AddRef();
+ return NOERROR;
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+ STDMETHOD_(ULONG, AddRef)(void)
+ {
+ return InterlockedIncrement(&_cReferences);
+ }
+ STDMETHOD_(ULONG, Release)(void);
+
+private:
+ STGMEDIUM _sm16;
+ STGMEDIUM _sm32;
+ IUnknown *_punkForRelease;
+ CLIPFORMAT _cfFormat;
+ CThkMgr *_pThkMgr;
+
+public:
+ LONG _cReferences;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSm32ReleaseHandler::Release, public
+//
+// Synopsis: Frees resources for the 32-bit copy and then
+// passes the ReleaseStgMedium on to 16-bits
+//
+// Returns: Ref count
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CSm32ReleaseHandler::Release(void)
+{
+ STGMEDIUM UNALIGNED *psm16;
+ STGMEDIUM *psm32;
+ LONG lRet;
+ SCODE sc;
+ DWORD dwSize;
+
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet != 0)
+ {
+ return lRet;
+ }
+
+ psm16 = &_sm16;
+ psm32 = &_sm32;
+
+ switch(psm32->tymed)
+ {
+ case TYMED_HGLOBAL:
+ // BUGBUG - Assumption that OBJECTDESCRIPTOR does not need copyback
+ if (!OBJDESC_CF(_cfFormat))
+ {
+ // BUGBUG - Do we ever need to do this?
+ // Is it valid to rely on the contents of the HGLOBAL
+ // at release time?
+
+ // BUGBUG - Is this the right time to copy back?
+
+ Assert(NULL != psm32->hGlobal);
+
+ WOWGlobalLockSize16((HMEM16)psm16->hGlobal, &dwSize);
+ WOWGlobalUnlock16((HMEM16)psm16->hGlobal);
+
+ sc = ConvertHGlobal3216(NULL, psm32->hGlobal, 0,
+ (HMEM16 *)&psm16->hGlobal, &dwSize);
+ // BUGBUG - What happens on errors?
+ thkAssert(SUCCEEDED(sc));
+ }
+
+ GlobalFree(psm32->hGlobal);
+ psm32->hGlobal = NULL;
+ break;
+
+ case TYMED_MFPICT:
+// Chicago uses the same GDI handles for both 32bit and 16bit worlds.
+// Don't delete the handle after a copy since Chicago doesn't actually
+// copy the handle.
+#if !defined(_CHICAGO_)
+ METAFILEPICT *pmfp32;
+
+ pmfp32 = (METAFILEPICT *)GlobalLock(psm32->hGlobal);
+ DeleteMetaFile(pmfp32->hMF);
+ GlobalUnlock(psm32->hGlobal);
+#endif
+ GlobalFree(psm32->hGlobal);
+ break;
+
+ case TYMED_FILE:
+ // 32-bit handled by ReleaseStgMedium
+ // Clean up 16-bit ourselves
+#ifdef SM_FREE_16BIT_FILENAME
+ // BUGBUG - 16-bit OLE did not free the filename, so we can't
+ // either. This may lead to memory leaks, but there's not
+ // really anything we can do about it
+ TaskFree16((VPVOID)psm16->lpszFileName);
+#endif
+ break;
+
+ case TYMED_ISTREAM:
+ case TYMED_ISTORAGE:
+ // Handled by ReleaseStgMedium and thunked to 16-bits if necessary
+ break;
+
+ case TYMED_GDI:
+ case TYMED_NULL:
+ // Nothing to release
+ break;
+
+ default:
+ thkAssert(!"Unknown tymed in CSm32ReleaseHandler::Release");
+ break;
+ }
+
+ // Call 16-bit Release through proxy
+ ((IUnknown *)_punkForRelease)->Release();
+ _punkForRelease = NULL;
+
+ // Clean up this
+ delete this;
+
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSm16ReleaseHandler::Init, public
+//
+// Synopsis: Initialize class
+//
+// Arguments: [psm32] - 32-bit STGMEDIUM
+// [psm16] - 16-bit STGMEDIUM
+// [vpvUnkForRelease] - Object for punkForRelease
+// [cfFormat] - Clipboard format associated with STGMEDIUM
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CSm16ReleaseHandler::Init(IUnknown *pThkMgr,
+ STGMEDIUM *psm32,
+ STGMEDIUM UNALIGNED *psm16,
+ VPVOID vpvUnkForRelease,
+ CLIPFORMAT cfFormat)
+{
+ _avpfnVtbl = gdata16Data.avpfnSm16ReleaseHandlerVtbl;
+ _sm32 = *psm32;
+
+ // Unfortunately, the MIPS compiler is not smart enough
+ // to do the right thing if we just (ony) declare psm16 as UNALIGNED,
+ // it doesn't recognize that each member of the structure is also
+ // unaligned when it does the structure copy. So...to make
+ // sure we don't generate an alignment fault, we just copy each
+ // member of the structure directly.
+
+ _sm16.tymed = psm16->tymed;
+ _sm16.hGlobal = psm16->hGlobal;
+ _sm16.pUnkForRelease = psm16->pUnkForRelease;
+
+ _vpvUnkForRelease = vpvUnkForRelease;
+ _cReferences = 1;
+ _cfFormat = cfFormat;
+ _pUnkThkMgr = pThkMgr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSm16ReleaseHandler::Uninit, public
+//
+// Synopsis: Uninitialize class
+//
+// History: 25-Apr-94 DrewB Created
+//
+// Notes: For cleanup without use only; do not call after
+// the release handler has actually executed Release
+//
+//----------------------------------------------------------------------------
+
+void CSm16ReleaseHandler::Uninit(void)
+{
+ ((CThkMgr *)_pUnkThkMgr)->FreeProxy1632(_sm32.pUnkForRelease);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CSm16ReleaseHandler_Release32, public
+//
+// Synopsis: Handles 32-bit portion of cleaning up STGMEDIUMs for
+// punkForRelease
+//
+// Arguments: [psrh] - this
+// [dw1]
+// [dw2]
+//
+// Returns: punkForRelease->Release()
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(DWORD) CSm16ReleaseHandler_Release32(CSm16ReleaseHandler *psrh,
+ DWORD dw1,
+ DWORD dw2)
+{
+ STGMEDIUM UNALIGNED *psm16;
+ STGMEDIUM *psm32;
+ DWORD dwSize;
+ SCODE sc;
+
+ psm16 = &psrh->_sm16;
+ psm32 = &psrh->_sm32;
+ switch(psm32->tymed)
+ {
+ case TYMED_FILE:
+ // 16-bit code cleaned up the 16-bit name,
+ // now clean up the 32-bit name
+ TaskFree32(psm32->lpszFileName);
+ break;
+
+ case TYMED_HGLOBAL:
+ // BUGBUG - Assumption that OBJECTDESCRIPTOR does not need copyback
+ if (!OBJDESC_CF(psrh->_cfFormat))
+ {
+ // BUGBUG - Do we ever need to do this?
+ // Copy data back and free global memory
+
+ dwSize = GlobalSize(psm32->hGlobal);
+
+ sc = ConvertHGlobal1632(NULL, (HMEM16)psm16->hGlobal, 0,
+ &psm32->hGlobal, &dwSize);
+ // BUGBUG - What happens on errors?
+ thkAssert(SUCCEEDED(sc));
+ }
+
+ WOWGlobalFree16((HMEM16)psm16->hGlobal);
+ break;
+
+ case TYMED_MFPICT:
+ // Untouched in this case
+ break;
+
+ case TYMED_ISTREAM:
+ case TYMED_ISTORAGE:
+ // Handled by ReleaseStgMedium and thunked to 32-bits if necessary
+ break;
+
+ case TYMED_GDI:
+ case TYMED_NULL:
+ // Nothing to release
+ break;
+
+ default:
+ thkAssert(!"Unknown tymed in ReleaseStgMedium32");
+ break;
+ }
+
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertStgMed1632, public
+//
+// Synopsis: Converts a 16-bit STGMEDIUM to 32-bits
+//
+// Arguments: [pti] - Thunk info
+// [vpsm16] - VDM pointer to 16-bit STGMEDIUM
+// [psm32] - 32-bit STGMEDIUM to fill in
+// [pfe] - FORMATETC paired with STGMEDIUM or NULL
+// [pdwSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pdwSize]
+//
+// History: 24-Apr-94 DrewB Created
+//
+// Notes: [pdwSize] is only set for TYMED_HGLOBAL
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertStgMed1632(THUNKINFO *pti,
+ VPVOID vpsm16,
+ STGMEDIUM *psm32,
+ FORMATETC *pfe,
+ BOOL fPassingOwnershipIn,
+ DWORD *pdwSize)
+{
+ SCODE sc;
+ STGMEDIUM UNALIGNED *psm16;
+ CSm32ReleaseHandler *psrh;
+ IUnknown *punkForRelease;
+ VPVOID vpvUnk;
+ HMEM16 hmem16;
+ HGDIOBJ hGDI = NULL;
+ THKSTATE thkstateSaved;
+
+ psm16 = (STGMEDIUM UNALIGNED *)
+ GetReadPtr16(pti, vpsm16, sizeof(STGMEDIUM));
+ if (psm16 == NULL)
+ {
+ return pti->scResult;
+ }
+
+ sc = S_OK;
+
+ psm32->tymed = psm16->tymed;
+
+ vpvUnk = (VPVOID)psm16->pUnkForRelease;
+ WOWRELVDMPTR(vpsm16);
+
+ if (vpvUnk != 0)
+ {
+ // If the storageMedium includes a pUnk and we are passing
+ // ownership via an [in] parameter. Then we need to build
+ // a proxy with a "real" (rather than "local") reference.
+ // Here we trick "FindProxy3216" into believing it
+ // is building an [out] parameter
+ thkstateSaved = pti->pThkMgr->GetThkState();
+ if(fPassingOwnershipIn)
+ {
+ pti->pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT32);
+ }
+
+ punkForRelease = pti->pThkMgr->FindProxy3216(NULL,
+ vpvUnk,
+ INDEX_IIDIDX(THI_IUnknown),
+ NULL);
+ pti->pThkMgr->SetThkState(thkstateSaved);
+
+ if (punkForRelease == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ psrh = new CSm32ReleaseHandler;
+ if (psrh == NULL)
+ {
+ pti->pThkMgr->FreeProxy3216(vpvUnk);
+ return E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ psrh = NULL;
+ }
+ psm32->pUnkForRelease = psrh;
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+
+ // Word 6 insists on treating BITMAPs as HGLOBALS, which is bogus.
+ // If this is the case, just patch the tymed to the correct value
+
+ if (pfe != NULL)
+ {
+ if( (pfe->cfFormat == CF_BITMAP || pfe->cfFormat == CF_PALETTE ) &&
+ psm16->tymed == TYMED_HGLOBAL )
+ {
+ DWORD dw = TlsThkGetAppCompatFlags();
+
+ // if we are in Word 6, then hack the tymed so we thunk the
+ // bitmaps as GDI objects
+
+ if( (dw & OACF_USEGDI ) )
+ {
+ DWORD dwType;
+
+ hGDI = HBITMAP_32((HBITMAP16)psm16->hBitmap);
+
+ // make sure HGDI is either a bitmap or palette
+
+ dwType = GetObjectType(hGDI);
+ if( (pfe->cfFormat == CF_BITMAP && dwType == OBJ_BITMAP) ||
+ (pfe->cfFormat == CF_PALETTE && dwType == OBJ_PAL) )
+ {
+ psm16->tymed = TYMED_GDI;
+ }
+ else
+ {
+ thkDebugOut((DEB_WARN,
+ "WARNING! invalid bitmap or palette!\n"));
+ hGDI = NULL;
+ }
+ }
+ else
+ {
+ thkDebugOut((DEB_WARN, "WARNING! App trying to transfer a "
+ "bitmap or palette on an HGLOBAL\n"));
+ }
+ }
+ }
+
+ switch( psm16->tymed )
+ {
+ case TYMED_HGLOBAL:
+ hmem16 = (HMEM16)psm16->hGlobal;
+ RELVDMPTR(vpsm16);
+
+ if (pfe && OBJDESC_CF(pfe->cfFormat))
+ {
+ sc = ConvertObjDesc1632(pti, hmem16, &psm32->hGlobal);
+ }
+#if !defined(_CHICAGO_)
+
+ else if (pfe && pfe->cfFormat == CF_HDROP)
+ {
+ // fix for mapi forms
+ // thunk CF_HDROP passed as HGLOBAL format
+ sc = ConvertHDrop1632(hmem16, &psm32->hGlobal);
+ }
+
+#endif
+ else
+ {
+ psm32->hGlobal = 0;
+ sc = ConvertHGlobal1632(pti, hmem16, THOP_INOUT,
+ &psm32->hGlobal, pdwSize);
+ }
+ break;
+
+ case TYMED_MFPICT:
+ hmem16 = (HMEM16)psm16->hGlobal;
+ RELVDMPTR(vpsm16);
+
+ sc = ConvertMfPict1632(pti, hmem16, &psm32->hGlobal);
+ break;
+
+ case TYMED_FILE:
+ psm32->lpszFileName =
+ Convert_VPSTR_to_LPOLESTR( pti,
+ (VPVOID)psm16->lpszFileName,
+ NULL, 0 );
+ if (psm32->lpszFileName == NULL)
+ {
+ sc = pti->scResult;
+ }
+ else
+ {
+#if DBG == 1
+ thkDebugOut((DEB_ARGS, "1632 TYMED_FILE: '%ws' (%s)\n",
+ psm32->lpszFileName,
+ WOWFIXVDMPTR((VPVOID)psm16->lpszFileName, 0)));
+ WOWRELVDMPTR((VPVOID)psm16->lpszFileName);
+#endif
+ }
+ RELVDMPTR(vpsm16);
+ break;
+
+ case TYMED_ISTREAM:
+ vpvUnk = (VPVOID)psm16->pstm;
+ RELVDMPTR(vpsm16);
+
+ psm32->pstm =
+ (LPSTREAM)pti->pThkMgr->FindProxy3216(NULL, vpvUnk,
+ INDEX_IIDIDX(THI_IStream),
+ NULL);
+ if (psm32->pstm == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ thkDebugOut((DEB_ARGS, "1632 TYMED_ISTREAM: %p -> %p\n",
+ vpvUnk, psm32->pstm));
+ }
+ break;
+
+ case TYMED_ISTORAGE:
+ vpvUnk = (VPVOID)psm16->pstm;
+ RELVDMPTR(vpsm16);
+
+ psm32->pstg =
+ (LPSTORAGE)pti->pThkMgr->FindProxy3216(NULL, vpvUnk,
+ INDEX_IIDIDX(THI_IStorage),
+ NULL);
+ if (psm32->pstg == NULL)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ thkDebugOut((DEB_ARGS, "1632 TYMED_ISTORAGE: %p -> %p\n",
+ vpvUnk, psm32->pstg));
+ }
+ break;
+
+ case TYMED_GDI:
+ // if we're in Word6, then we may have already converted the bitmap
+ // or palette handle
+ if( hGDI == NULL )
+ {
+ psm32->hBitmap = HBITMAP_32((HBITMAP16)psm16->hBitmap);
+ }
+ else
+ {
+ psm32->hBitmap = (HBITMAP)hGDI;
+ }
+
+ thkDebugOut((DEB_ARGS, "1632 TYMED_GDI: 0x%04X -> 0x%p\n",
+ psm16->hBitmap, psm32->hBitmap));
+ RELVDMPTR(vpsm16);
+ break;
+
+ case TYMED_NULL:
+ RELVDMPTR(vpsm16);
+ break;
+
+ default:
+ RELVDMPTR(vpsm16);
+ sc = E_INVALIDARG;
+ break;
+ }
+
+ if (FAILED(sc))
+ {
+ delete psrh;
+ }
+ else
+ {
+ if (psrh)
+ {
+ CLIPFORMAT cf;
+
+ if (pfe)
+ {
+ cf = pfe->cfFormat;
+ }
+ else
+ {
+ cf = CF_INVALID;
+ }
+ psrh->Init(pti->pThkMgr, FIXVDMPTR(vpsm16, STGMEDIUM), psm32,
+ punkForRelease, cf);
+ RELVDMPTR(vpsm16);
+ }
+
+#if DBG == 1
+ if (pfe)
+ {
+ thkDebugOut((DEB_ARGS, "1632 STGMEDIUM FORMATETC %p {%d}\n",
+ pfe, pfe->cfFormat));
+ }
+ thkDebugOut((DEB_ARGS, "1632 STGMEDIUM: %p {%d, %p, ...} -> "
+ "%p {%d, %p, ...}\n", vpsm16, psm16->tymed,
+ psm16->pUnkForRelease, psm32, psm32->tymed,
+ psm32->pUnkForRelease));
+#endif
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CleanStgMed32, public
+//
+// Synopsis: Cleans up a 32-bit STGMEDIUM
+//
+// Arguments: [pti] - Thunk info
+// [psm32] - STGMEDIUM to clean
+// [vpsm16] - Source STGMEDIUM if thunk
+// [dwSize] - Source size if thunk
+// [fIsThunk] - STGMEDIUM was generated by thunking
+// [pfe] - FORMATETC or NULL
+//
+// Returns: Appropriate status code
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CleanStgMed32(THUNKINFO *pti,
+ STGMEDIUM *psm32,
+ VPVOID vpsm16,
+ DWORD dwSize,
+ BOOL fIsThunk,
+ FORMATETC *pfe)
+{
+ SCODE sc;
+ STGMEDIUM UNALIGNED *psm16;
+ HMEM16 hmem16;
+ VPVOID vpvUnk;
+ BOOL bNoRefs=TRUE;
+
+ thkDebugOut((DEB_ITRACE, "In CleanStgMed32(%p, %p, %p, %u, %d, %p)\n",
+ pti, psm32, vpsm16, dwSize, fIsThunk, pfe));
+
+ sc = S_OK;
+
+ if (fIsThunk && (NULL!=psm32->pUnkForRelease) )
+ {
+ CSm32ReleaseHandler* psm32rh = (CSm32ReleaseHandler*)psm32->pUnkForRelease;
+
+ // When the StgMed is a Thunk and we have a pUnkForRelease:
+ //
+ // Only the remote end is expected to call the last Release() of
+ // the ReleaseHandler. We normally have the last reference here
+ // so just "delete" the ReleaseHandler and release everything.
+ //
+ // But... in the Async OnDataChange() if the remote call hasn't
+ // completed yet the system will be holding a reference so we need to
+ // release our reference but not free any non-reference counted objects
+ // below. Sm32ReleaseHandler->Release() will be called when the
+ // remote side call completes and Release() is called on the
+ // pUnkForRelease. And that will clean up.
+
+ if(1 == psm32rh->_cReferences)
+ {
+ delete psm32rh;
+ bNoRefs = TRUE;
+ }
+ else
+ {
+ psm32rh->Release();
+ bNoRefs = FALSE;
+ }
+ psm32->pUnkForRelease = NULL;
+ }
+
+ switch( psm32->tymed )
+ {
+ case TYMED_HGLOBAL:
+ if (bNoRefs)
+ {
+ if (fIsThunk &&
+ (pfe == NULL || !OBJDESC_CF(pfe->cfFormat)))
+ {
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ hmem16 = (HMEM16)psm16->hGlobal;
+ RELVDMPTR(vpsm16);
+
+ Assert(NULL != psm32->hGlobal);
+
+ sc = ConvertHGlobal3216(pti, psm32->hGlobal, 0,
+ &hmem16, &dwSize);
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->hGlobal = (HGLOBAL)hmem16;
+ RELVDMPTR(vpsm16);
+ }
+
+ GlobalFree( psm32->hGlobal );
+ psm32->hGlobal = NULL;
+ }
+ break;
+
+ case TYMED_MFPICT:
+ if (bNoRefs)
+ {
+
+// Chicago uses the same GDI handles for both 32bit and 16bit worlds.
+// Don't delete the handle after a copy since Chicago doesn't actually
+// copy the handle.
+#if !defined(_CHICAGO_)
+ // Can't modify an MFPICT
+
+ METAFILEPICT *pmfp32;
+
+ pmfp32 = (METAFILEPICT *)GlobalLock(psm32->hGlobal);
+ DeleteMetaFile(pmfp32->hMF);
+ GlobalUnlock(psm32->hGlobal);
+#endif
+ GlobalFree(psm32->hGlobal);
+ }
+ break;
+
+ case TYMED_FILE:
+ if (bNoRefs)
+ {
+ Convert_VPSTR_to_LPOLESTR_free( NULL, psm32->lpszFileName );
+ }
+ break;
+
+ case TYMED_ISTREAM:
+ if (fIsThunk)
+ {
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ vpvUnk = (VPVOID)psm16->pstm;
+ RELVDMPTR(vpsm16);
+
+ pti->pThkMgr->FreeProxy3216(vpvUnk);
+ }
+ break;
+
+ case TYMED_ISTORAGE:
+ if (fIsThunk)
+ {
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ vpvUnk = (VPVOID)psm16->pstg;
+ RELVDMPTR(vpsm16);
+
+ pti->pThkMgr->FreeProxy3216(vpvUnk);
+ }
+ break;
+
+ case TYMED_GDI:
+ //
+ // No unthunking needed
+ //
+ break;
+
+ case TYMED_NULL:
+ break;
+
+ default:
+ // Ignore, this case is handled on input
+ thkAssert(!"STGMEDIUM with invalid tymed");
+ break;
+ }
+
+ thkDebugOut((DEB_ITRACE, "Out CleanStgMed32 => 0x%08lX\n", sc));
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertStgMed3216, public
+//
+// Synopsis: Converts a 32-bit STGMEDIUM to 16-bits
+//
+// Arguments: [pti] - Thunk info
+// [psm32] - 32-bit STGMEDIUM
+// [vpsm16] - VDM pointer to 16-bit STGMEDIUM
+// [pfe] - FORMATETC paired with STGMEDIUM or NULL
+// [pdwSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pdwSize]
+//
+// History: 24-Apr-94 DrewB Created
+//
+// Notes: [pdwSize] is only set for TYMED_HGLOBAL
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertStgMed3216(THUNKINFO *pti,
+ STGMEDIUM *psm32,
+ VPVOID vpsm16,
+ FORMATETC *pfe,
+ BOOL fPassingOwnershipIn,
+ DWORD *pdwSize)
+{
+ SCODE sc;
+ STGMEDIUM UNALIGNED *psm16;
+ VPVOID vpsrh;
+ VPSTR vpstr;
+ UINT uiSize;
+ VPVOID vpvUnkForRelease;
+ VPVOID vpvUnk;
+ HMEM16 hmem16;
+ THKSTATE thkstateSaved;
+
+ sc = S_OK;
+
+ if (psm32->pUnkForRelease != NULL)
+ {
+ // If the storageMedium includes a pUnk and we are passing
+ // ownership via an [in] parameter. Then we need to build
+ // a proxy with a "real" (rather than "local") reference.
+ // Here we trick "FindProxy1632" into believing it
+ // is building an [out] parameter
+ thkstateSaved = pti->pThkMgr->GetThkState();
+ if(fPassingOwnershipIn)
+ pti->pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT16);
+
+ vpvUnkForRelease = pti->pThkMgr->FindProxy1632(NULL,
+ psm32->pUnkForRelease,
+ INDEX_IIDIDX(THI_IUnknown),
+ NULL);
+ pti->pThkMgr->SetThkState(thkstateSaved);
+
+ if (vpvUnkForRelease == 0)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ vpsrh = WOWGlobalAllocLock16(GMEM_MOVEABLE,
+ sizeof(CSm16ReleaseHandler),
+ NULL);
+ if (vpsrh == 0)
+ {
+ pti->pThkMgr->FreeProxy1632(psm32->pUnkForRelease);
+ return E_OUTOFMEMORY;
+ }
+ }
+ else
+ {
+ vpsrh = 0;
+ }
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->tymed = psm32->tymed;
+ psm16->pUnkForRelease = (IUnknown *)vpsrh;
+ RELVDMPTR(vpsm16);
+
+ switch( psm32->tymed )
+ {
+ case TYMED_HGLOBAL:
+ if (pfe && OBJDESC_CF(pfe->cfFormat))
+ {
+ sc = ConvertObjDesc3216(pti, psm32->hGlobal, &hmem16);
+ }
+#if !defined(_CHICAGO_)
+
+ else if (pfe && pfe->cfFormat == CF_HDROP)
+ {
+ // fix for mapi forms
+ sc = ConvertHDrop3216(psm32->hGlobal, &hmem16);
+ }
+
+#endif
+ else
+ {
+ hmem16 = 0;
+ sc = ConvertHGlobal3216(pti, psm32->hGlobal, THOP_INOUT,
+ &hmem16, pdwSize);
+ }
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->hGlobal = (HGLOBAL)hmem16;
+ RELVDMPTR(vpsm16);
+ break;
+
+ case TYMED_MFPICT:
+ sc = ConvertMfPict3216(pti, psm32->hGlobal, &hmem16);
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->hGlobal = (HGLOBAL)hmem16;
+ RELVDMPTR(vpsm16);
+ break;
+
+ case TYMED_FILE:
+ uiSize = lstrlenW(psm32->lpszFileName) + 1;
+ vpstr = TaskMalloc16( uiSize*2 );
+ if ( vpstr == NULL )
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ sc = Convert_LPOLESTR_to_VPSTR( psm32->lpszFileName,
+ vpstr, uiSize, uiSize*2 );
+ if (FAILED(sc))
+ {
+ TaskFree16(vpstr);
+ }
+ else
+ {
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->lpszFileName = (LPOLESTR)vpstr;
+ RELVDMPTR(vpsm16);
+
+#if DBG == 1
+ thkDebugOut((DEB_ARGS, "3216 TYMED_FILE: '%s' (%ws)\n",
+ WOWFIXVDMPTR(vpstr, 0),
+ psm32->lpszFileName));
+ WOWRELVDMPTR(vpstr);
+#endif
+ }
+ }
+ break;
+
+ case TYMED_ISTREAM:
+ vpvUnk = pti->pThkMgr->FindProxy1632(NULL, psm32->pstm,
+ INDEX_IIDIDX(THI_IStream),
+ NULL);
+ if (vpvUnk == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ thkDebugOut((DEB_ARGS, "3216 TYMED_ISTREAM: %p -> %p\n",
+ psm32->pstm, vpvUnk));
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->pstm = (IStream *)vpvUnk;
+ RELVDMPTR(vpsm16);
+ }
+ break;
+
+ case TYMED_ISTORAGE:
+ vpvUnk = pti->pThkMgr->FindProxy1632(NULL, psm32->pstg,
+ INDEX_IIDIDX(THI_IStorage),
+ NULL);
+ if (vpvUnk == 0)
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ else
+ {
+ thkDebugOut((DEB_ARGS, "3216 TYMED_ISTORAGE: %p -> %p\n",
+ psm32->pstg, vpvUnk));
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->pstg = (IStorage *)vpvUnk;
+ RELVDMPTR(vpsm16);
+ }
+ break;
+
+ case TYMED_GDI:
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ psm16->hBitmap = (HBITMAP)HBITMAP_16(psm32->hBitmap);
+ thkDebugOut((DEB_ARGS, "3216 TYMED_GDI: 0x%p -> 0x%04X\n",
+ psm32->hBitmap, psm16->hBitmap));
+ RELVDMPTR(vpsm16);
+ break;
+
+ case TYMED_NULL:
+ break;
+
+ default:
+ sc = E_INVALIDARG;
+ break;
+ }
+
+ if (FAILED(sc))
+ {
+ if (vpsrh != 0)
+ {
+ pti->pThkMgr->FreeProxy1632(psm32->pUnkForRelease);
+ WOWGlobalUnlockFree16(vpsrh);
+ }
+ }
+ else
+ {
+ if (vpsrh != 0)
+ {
+ CSm16ReleaseHandler UNALIGNED *psrh;
+ CLIPFORMAT cf;
+
+ if (pfe)
+ {
+ cf = pfe->cfFormat;
+ }
+ else
+ {
+ cf = CF_INVALID;
+ }
+ psrh = FIXVDMPTR(vpsrh, CSm16ReleaseHandler);
+ psrh->Init(pti->pThkMgr, psm32, FIXVDMPTR(vpsm16, STGMEDIUM),
+ vpvUnkForRelease, cf);
+ RELVDMPTR(vpsrh);
+ RELVDMPTR(vpsm16);
+ }
+
+#if DBG == 1
+ if (pfe)
+ {
+ thkDebugOut((DEB_ARGS, "3216 STGMEDIUM FORMATETC %p {%d}\n",
+ pfe, pfe->cfFormat));
+ }
+ thkDebugOut((DEB_ARGS, "3216 STGMEDIUM: %p {%d, %p, ...} -> "
+ "%p {%d, %p, ...}\n", psm32, psm32->tymed,
+ psm32->pUnkForRelease, vpsm16, psm16->tymed,
+ psm16->pUnkForRelease));
+#endif
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CleanStgMed16, public
+//
+// Synopsis: Frees up resources in a 16-bit STGMEDIUM
+//
+// Arguments: [pti] - Thunk info
+// [vpsm16] - STGMEDIUM to clean
+// [psm32] - Source STGMEDIUM if thunk
+// [dwSize] - Source size for thunked HGLOBAL
+// [fIsThunk] - If the STGMEDIUM is a result of thunking
+// [pfe] - FORMATETC or NULL
+//
+// Returns: Appropriate status code
+//
+// History: 24-Apr-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CleanStgMed16(THUNKINFO *pti,
+ VPVOID vpsm16,
+ STGMEDIUM *psm32,
+ DWORD dwSize,
+ BOOL fIsThunk,
+ FORMATETC *pfe)
+{
+ SCODE sc;
+ STGMEDIUM UNALIGNED *psm16;
+ VPVOID vpvUnk;
+ HMEM16 hmem16;
+
+ thkDebugOut((DEB_ITRACE, "In CleanStgMed16(%p, %p, %p, %u, %d, %p)\n",
+ pti, vpsm16, psm32, dwSize, fIsThunk, pfe));
+
+ sc = S_OK;
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ vpvUnk = (VPVOID)psm16->pUnkForRelease;
+ RELVDMPTR(vpsm16);
+
+ if (fIsThunk && vpvUnk != 0)
+ {
+ CSm16ReleaseHandler UNALIGNED *psrh;
+
+ psrh = FIXVDMPTR(vpvUnk, CSm16ReleaseHandler);
+ psrh->Uninit();
+ RELVDMPTR(vpvUnk);
+ WOWGlobalUnlockFree16(vpvUnk);
+ }
+
+ psm16 = FIXVDMPTR(vpsm16, STGMEDIUM);
+ switch( psm16->tymed )
+ {
+ case TYMED_HGLOBAL:
+ hmem16 = (HMEM16)psm16->hGlobal;
+ RELVDMPTR(vpsm16);
+
+ if (fIsThunk &&
+ (pfe == NULL || !OBJDESC_CF(pfe->cfFormat)))
+ {
+ sc = ConvertHGlobal1632(pti, hmem16, 0,
+ &psm32->hGlobal, &dwSize);
+ }
+
+ WOWGlobalFree16( hmem16 );
+ break;
+
+ case TYMED_MFPICT:
+ hmem16 = (HMEM16)psm16->hGlobal;
+ RELVDMPTR(vpsm16);
+
+ // Can't modify an MFPICT
+
+// Chicago uses the same GDI handles for both 32bit and 16bit worlds.
+// Don't delete the handle after a copy since Chicago doesn't actually
+// copy the handle.
+#if !defined(_CHICAGO_)
+ VPVOID vpvmfp16;
+ METAFILEPICT16 *pmfp16;
+ HMEM16 hmf16;
+
+ vpvmfp16 = WOWGlobalLock16(hmem16);
+ pmfp16 = FIXVDMPTR(vpvmfp16, METAFILEPICT16);
+ hmf16 = pmfp16->hMF;
+ RELVDMPTR(vpvmfp16);
+
+ // Relies on the fact that a 16-bit metafile is an HGLOBAL
+ WOWGlobalFree16(hmf16);
+
+ WOWGlobalUnlockFree16(vpvmfp16);
+#else
+ WOWGlobalFree16(hmem16);
+#endif
+ break;
+
+ case TYMED_FILE:
+ vpvUnk = (VPVOID)psm16->lpszFileName;
+ RELVDMPTR(vpsm16);
+
+ TaskFree16(vpvUnk);
+ break;
+
+ case TYMED_ISTREAM:
+ RELVDMPTR(vpsm16);
+
+ if (fIsThunk)
+ {
+ pti->pThkMgr->FreeProxy1632(psm32->pstm);
+ }
+ break;
+
+ case TYMED_ISTORAGE:
+ RELVDMPTR(vpsm16);
+
+ if (fIsThunk)
+ {
+ pti->pThkMgr->FreeProxy1632(psm32->pstg);
+ }
+ break;
+
+ case TYMED_GDI:
+ RELVDMPTR(vpsm16);
+
+ //
+ // No unthunking needed
+ //
+ break;
+
+ case TYMED_NULL:
+ RELVDMPTR(vpsm16);
+
+ break;
+
+ default:
+ // Ignore, this case is handled on input
+ thkAssert(!"CleanStgMed16 with invalid tymed");
+ break;
+ }
+
+ thkDebugOut((DEB_ITRACE, "Out CleanStgMed16 => 0x%08lX\n", sc));
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertFetc1632, public
+//
+// Synopsis: Converts a FORMATETC
+//
+// Arguments: [pti] - Thunk info
+// [vpfe16] - FORMATETC
+// [pfe32] - FORMATETC
+// [fFree] - Free resources as converting
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pfe32]
+//
+// History: 14-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertFetc1632(THUNKINFO *pti,
+ VPVOID vpfe16,
+ FORMATETC *pfe32,
+ BOOL fFree)
+{
+ FORMATETC16 UNALIGNED *pfe16;
+ VPVOID vpdv16;
+ DVTARGETDEVICE *pdv32;
+ UINT cbSize;
+ SCODE sc;
+
+ pfe16 = FIXVDMPTR(vpfe16, FORMATETC16);
+ vpdv16 = (VPVOID)pfe16->ptd;
+ RELVDMPTR(vpfe16);
+
+ if ( vpdv16 == 0 )
+ {
+ pdv32 = NULL;
+ }
+ else
+ {
+ sc = ConvertDvtd1632(pti, vpdv16, ArTask32, FrTask32,
+ &pdv32, &cbSize);
+
+ if (fFree)
+ {
+ TaskFree16(vpdv16);
+ }
+
+ if (FAILED(sc))
+ {
+ return sc;
+ }
+ }
+
+ pfe16 = FIXVDMPTR(vpfe16, FORMATETC16);
+ pfe32->cfFormat = pfe16->cfFormat;
+ pfe32->ptd = pdv32;
+ pfe32->dwAspect = pfe16->dwAspect;
+ pfe32->lindex = pfe16->lindex;
+ pfe32->tymed = pfe16->tymed;
+
+ thkDebugOut((DEB_ARGS, "1632 FORMATETC: "
+ "%p -> %p {%d, %p (%p), %u, %u, 0x%X}\n",
+ vpfe16, pfe32,
+ pfe32->cfFormat,
+ pfe32->ptd, vpdv16,
+ pfe32->dwAspect,
+ pfe32->lindex,
+ pfe32->tymed));
+
+ RELVDMPTR(vpfe16);
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertFetc3216, public
+//
+// Synopsis: Converts a FORMATETC
+//
+// Arguments: [pti] - Thunk info
+// [pfe32] - FORMATETC
+// [vpfe16] - FORMATETC
+// [fFree] - Free resources as converting
+//
+// Returns: Appropriate status code
+//
+// Modifies: [vpfe16]
+//
+// History: 14-May-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE ConvertFetc3216(THUNKINFO *pti,
+ FORMATETC *pfe32,
+ VPVOID vpfe16,
+ BOOL fFree)
+{
+ FORMATETC16 UNALIGNED *pfe16;
+ DVTARGETDEVICE *pdv32;
+ SCODE sc;
+ VPVOID vpdv16;
+ UINT cbSize;
+
+ pdv32 = pfe32->ptd;
+ if (pdv32 != NULL)
+ {
+ sc = ConvertDvtd3216(pti, pdv32, ArTask16, FrTask16,
+ &vpdv16, &cbSize);
+
+ if (fFree)
+ {
+ TaskFree32(pdv32);
+ }
+
+ if (FAILED(sc))
+ {
+ return sc;
+ }
+ }
+ else
+ {
+ vpdv16 = 0;
+ }
+
+ pfe16 = FIXVDMPTR(vpfe16, FORMATETC16);
+ pfe16->cfFormat = pfe32->cfFormat;
+ pfe16->ptd = vpdv16;
+ pfe16->dwAspect = pfe32->dwAspect;
+ pfe16->lindex = pfe32->lindex;
+ pfe16->tymed = pfe32->tymed;
+
+ thkDebugOut((DEB_ARGS, "3216 FORMATETC: "
+ "%p -> %p {%d, %p (%p), %u, %u, 0x%X}\n",
+ pfe32, vpfe16,
+ pfe16->cfFormat,
+ vpdv16, pdv32,
+ pfe16->dwAspect,
+ pfe16->lindex,
+ pfe16->tymed));
+
+ RELVDMPTR(vpfe16);
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DebugValidateProxy1632, debug public
+//
+// Synopsis: Validates a 16->32 proxy pointer and its memory
+//
+// Arguments: [vpvProxy] - Proxy
+//
+// History: 07-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+void DebugValidateProxy1632(VPVOID vpvProxy)
+{
+ THUNK1632OBJ UNALIGNED *pto;
+ THUNKINFO ti;
+
+ thkAssert(vpvProxy != 0 && "Invalid proxy pointer");
+
+ pto = (THUNK1632OBJ UNALIGNED *)
+ GetReadWritePtr16(&ti, vpvProxy, sizeof(THUNK1632OBJ));
+ thkAssert(pto != NULL && "Invalid proxy pointer");
+
+ thkAssert(pto->dwSignature == PSIG1632 && "Dead or invalid proxy!");
+
+ thkAssert(pto->cRefLocal >= 0 && "Invalid proxy refcount");
+ thkAssert(pto->cRefLocal >= pto->cRef && "Invalid proxy refcount");
+
+ if (!IsValidInterface(pto->punkThis32))
+ {
+ thkDebugOut((DEB_ERROR, "1632 %p: Invalid proxied object %p\n",
+ vpvProxy, pto->punkThis32));
+ }
+
+ WOWRELVDMPTR(vpvProxy);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: DebugValidateProxy3216, debug public
+//
+// Synopsis: Validates a 32->16 proxy pointer and its memory
+//
+// Arguments: [pto] - Proxy
+//
+// History: 07-Jul-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+void DebugValidateProxy3216(THUNK3216OBJ *pto)
+{
+ THUNKINFO ti;
+
+ thkAssert(pto != 0 && "Invalid proxy pointer");
+
+ thkAssert(!IsBadReadPtr(pto, sizeof(THUNK3216OBJ)) &&
+ !IsBadWritePtr(pto, sizeof(THUNK3216OBJ)) &&
+ "Invalid proxy pointer");
+
+ thkAssert(pto->dwSignature == PSIG3216 && "Dead or invalid proxy!");
+
+ thkAssert(pto->cRefLocal >= 0 && "Invalid proxy refcount");
+ thkAssert(pto->cRefLocal >= pto->cRef && "Invalid proxy refcount");
+
+ if (!IsValidInterface16(&ti, pto->vpvThis16))
+ {
+ thkDebugOut((DEB_ERROR, "3216 %p: Invalid proxied object %p\n",
+ pto, pto->vpvThis16));
+ }
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: ClampLongToShort, public
+//
+// Synopsis: Restricts a long value to a short value by clamping
+//
+// Arguments: [l] - Long
+//
+// Returns: Short
+//
+// History: 16-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SHORT ClampLongToShort(LONG l)
+{
+ SHORT s;
+
+ if (l < SHRT_MIN)
+ {
+ s = SHRT_MIN;
+ thkDebugOut((DEB_WARN, "ClampLongToShort: %ld -> %d\n", l, s));
+ }
+ else if (l > SHRT_MAX)
+ {
+ s = SHRT_MAX;
+ thkDebugOut((DEB_WARN, "ClampLongToShort: %ld -> %d\n", l, s));
+ }
+ else
+ {
+ s = (SHORT)l;
+ }
+
+ return s;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ClampULongToUShort, public
+//
+// Synopsis: Restricts an unsigned long value to an unsigned short value
+// by clamping
+//
+// Arguments: [ul] - Long
+//
+// Returns: UShort
+//
+// History: 16-Aug-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+USHORT ClampULongToUShort(ULONG ul)
+{
+ USHORT us;
+
+ if (ul > USHRT_MAX)
+ {
+ us = USHRT_MAX;
+ thkDebugOut((DEB_WARN, "ClampULongToUShort: %ld -> %d\n", ul, us));
+ }
+ else
+ {
+ us = (USHORT)ul;
+ }
+
+ return us;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ConvertObjDescriptor
+//
+// Synopsis: Exported API called by WOW to convert ObjectDescriptors to
+// the indicated format.
+//
+//
+// Arguments: [hMem] -- Handle to the ObjectDescriptor to convert.
+// [flag] -- Flag indicating which direction the convertion
+// should take place. Valid values are:
+// CFOLE_UNICODE_TO_ANSI.
+// CFOLE_ANSI_TO_UNICODE.
+//
+// Returns: HGLOBAL to the converted ObjectDescriptor,
+// or NULL on failure.
+//
+// History: 8-16-94 terryru Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDAPI_(HGLOBAL) ConvertObjDescriptor( HANDLE hMem, UINT flag )
+{
+
+ const UINT CFOLE_UNICODE_TO_ANSI = 0;
+ const UINT CFOLE_ANSI_TO_UNICODE = 1;
+
+ THUNKINFO ti;
+ HGLOBAL hMem32;
+ HMEM16 hMem16;
+
+ switch ( flag )
+ {
+ case CFOLE_UNICODE_TO_ANSI:
+ if( FAILED( ConvertObjDesc3216( &ti, (HGLOBAL) hMem, &hMem16 )))
+ {
+ return (HGLOBAL) NULL;
+ }
+ else
+ {
+ return (HGLOBAL) hMem16;
+ }
+ break;
+
+ case CFOLE_ANSI_TO_UNICODE:
+ if( FAILED( ConvertObjDesc1632( &ti, (HMEM16) hMem, &hMem32 )))
+ {
+ return (HGLOBAL) NULL;
+ }
+ else
+ {
+ return (HGLOBAL) hMem32;
+ }
+ break;
+
+ default:
+ thkAssert(!"ConvertObjDescriptor, Invalid flag");
+ break;
+ }
+ return (HGLOBAL) NULL;
+}
+
+#if defined(_CHICAGO_)
+
+//
+// BUGBUGCHICAGO
+//
+// A hack so everyone can build Chicago OLE until I write the thunking
+// library later this week.
+//
+
+#define ERR ((char*) -1)
+
+#if DBG==1
+int UnicodeToAnsi(LPSTR sz, LPCWSTR pwsz, LONG cb)
+{
+ int ret;
+
+ ret = WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, pwsz, -1, sz, cb, NULL, NULL);
+
+ thkAssert(ret != 0 && "Lost characters in thk Unicode->Ansi conversion");
+ if (ret == 0)
+ {
+ DebugBreak();
+ }
+
+ return ret;
+}
+#else
+#define UnicodeToAnsi(sz,pwsz,cb) WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, pwsz, -1, sz, cb, NULL, NULL)
+#endif
+
+
+#if DBG==1
+int AnsiToUnicode(LPWSTR pwsz, LPCSTR sz, LONG cb)
+{
+ int ret;
+
+ ret = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, sz, -1, pwsz, cb);
+
+ thkAssert(ret != 0 && "Lost characters in thk Ansi->Unicode conversion");
+ if (ret == 0)
+ {
+ DebugBreak();
+ }
+
+ return ret;
+}
+#else
+#define AnsiToUnicode(pwsz,sz,cb) MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, sz, -1, pwsz, cb)
+#endif
+
+
+
+extern "C"
+DWORD
+WINAPI
+GetShortPathNameX(
+ LPCWSTR lpszFullPath,
+ LPWSTR lpszShortPath,
+ DWORD cchBuffer
+ )
+{
+ #ifdef DEBUG_OUTPUT
+ OutputDebugString("GetShortPathName\n");
+ #endif
+
+ CHAR szFullPath[MAX_PATH];
+ CHAR szShortBuffer[MAX_PATH];
+ DWORD ret;
+
+
+ UnicodeToAnsi(szFullPath, lpszFullPath, sizeof(szFullPath));
+
+ if (lpszShortPath == NULL)
+ {
+ ret = GetShortPathNameA(szFullPath, NULL, cchBuffer);
+ }
+ else
+ {
+ ret = GetShortPathNameA(szFullPath, szShortBuffer,
+ sizeof(szShortBuffer));
+
+ thkAssert(ret != cchBuffer &&
+ "GetShortPathName - Output buffer too short");
+ //
+ // Don't convert the buffer if the
+ // call to GetShortPathNameA() failed.
+ //
+ if(0 != ret)
+ {
+ //
+ // Only convert the actual data, not the whole buffer.
+ //
+ if (cchBuffer > ret + 1)
+ cchBuffer = ret + 1;
+
+ AnsiToUnicode(lpszShortPath, szShortBuffer, cchBuffer);
+ }
+ }
+
+ return ret;
+}
+
+#endif // _CHICAGO_
+
diff --git a/private/ole32/olethunk/olethk32/thoputil.hxx b/private/ole32/olethunk/olethk32/thoputil.hxx
new file mode 100644
index 000000000..f13fe7f09
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thoputil.hxx
@@ -0,0 +1,216 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thoputil.hxx
+//
+// Contents: Thunk routine utilities
+//
+// History: 01-Mar-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __THOPUTIL_HXX__
+#define __THOPUTIL_HXX__
+
+// Alias manager for THOP_ALIAS32
+extern CAliases gAliases32;
+
+IIDIDX IidToIidIdx(REFIID riid);
+
+#ifdef COTASK_DEFINED
+#define TaskMalloc32 CoTaskMemAlloc
+#define TaskFree32 CoTaskMemFree
+#else
+LPVOID TaskMalloc32(DWORD cb);
+void TaskFree32(LPVOID pv);
+#endif
+
+DWORD TaskMalloc16( UINT uiSize );
+void TaskFree16( DWORD vpvoid );
+
+LPOLESTR Convert_VPSTR_to_LPOLESTR(THUNKINFO *pti,
+ VPSTR vpstr,
+ LPOLESTR lpOleStr,
+ UINT uiSizeInPlace);
+//
+// Simple macro to free up any string allocated in the conversion process
+//
+#define Convert_VPSTR_to_LPOLESTR_free( lpOleStr, lpOleStrUsed ) \
+ (((lpOleStr) == (lpOleStrUsed)) ? 0 : \
+ (lpOleStrUsed == NULL) ? 0 : TaskFree32(lpOleStrUsed))
+
+SCODE Convert_LPOLESTR_to_VPSTR(LPCOLESTR lpOleStr,
+ VPSTR vpstr,
+ UINT uiSize32,
+ UINT uiSize16);
+
+#ifdef _CHICAGO_
+// This is only really used on Chicago
+SCODE Convert_LPSTR_to_VPSTR(LPCSTR lpOleStr,
+ VPSTR vpstr,
+ UINT uiSize32,
+ UINT uiSize16);
+#endif
+
+STDAPI_(DWORD) TransformHRESULT_1632( DWORD hresult );
+STDAPI_(DWORD) TransformHRESULT_3216( DWORD hresult );
+
+SHORT ClampLongToShort(LONG l);
+USHORT ClampULongToUShort(ULONG l);
+
+VOID * GetReadPtr16( THUNKINFO *pti, VPVOID vp16, DWORD dwSize );
+VOID * GetWritePtr16( THUNKINFO *pti, VPVOID vp16, DWORD dwSize );
+VOID * GetCodePtr16( THUNKINFO *pti, VPVOID vp16, DWORD dwSize );
+VOID * GetReadWritePtr16( THUNKINFO *pti, VPVOID vp16, DWORD dwSize );
+CHAR * GetStringPtr16( THUNKINFO *pti, VPVOID vp16, UINT cchMax,
+ PUINT lpuiSize );
+VOID * ValidatePtr16(THUNKINFO *pti, VPVOID vp16, DWORD dwSize,
+ THOP thopInOut);
+BOOL IsValidInterface16( THUNKINFO *pti, VPVOID vp );
+
+SCODE ConvertHGlobal1632(THUNKINFO *pti,
+ HMEM16 hg16,
+ THOP thopInOut,
+ HGLOBAL *phg32,
+ DWORD *pdwSize);
+SCODE ConvertHGlobal3216(THUNKINFO *pti,
+ HGLOBAL hg32,
+ THOP thopInOut,
+ HMEM16 *phg16,
+ DWORD *pdwSize);
+SCODE ConvertStgMed1632(THUNKINFO *pti,
+ VPVOID vpsm16,
+ STGMEDIUM *psm32,
+ FORMATETC *pfe,
+ BOOL fPassingOwnershipIn,
+ DWORD *pdwSize);
+SCODE CleanStgMed32(THUNKINFO *pti,
+ STGMEDIUM *psm32,
+ VPVOID vpsm16,
+ DWORD dwSize,
+ BOOL fIsThunk,
+ FORMATETC *pfe);
+SCODE ConvertStgMed3216(THUNKINFO *pti,
+ STGMEDIUM *psm32,
+ VPVOID vpsm16,
+ FORMATETC *pfe,
+ BOOL fPassingOwnershipIn,
+ DWORD *pdwSize);
+SCODE CleanStgMed16(THUNKINFO *pti,
+ VPVOID vpsm16,
+ STGMEDIUM *psm32,
+ DWORD dwSize,
+ BOOL fIsThunk,
+ FORMATETC *pfe);
+SCODE ConvertFetc1632(THUNKINFO *pti,
+ VPVOID vpfe16,
+ FORMATETC *pfe32,
+ BOOL fFree);
+SCODE ConvertFetc3216(THUNKINFO *pti,
+ FORMATETC *pfe32,
+ VPVOID vpfe16,
+ BOOL fFree);
+
+#if DBG == 1
+
+char *ThopName(THOP thop);
+char *EnumThopName(THOP thopEnum);
+char *GuidString(GUID const *pguid);
+char *IidOrInterfaceString(IID const *piid);
+char *IidIdxString(IIDIDX iidx);
+
+void DebugValidateProxy1632(VPVOID vpvProxy);
+void DebugValidateProxy3216(THUNK3216OBJ *ptoProxy);
+
+#else
+
+#define DebugValidateProxy1632(p)
+#define DebugValidateProxy3216(p)
+
+#endif
+
+#define StackAlloc16(cb) \
+ ((VPVOID)TlsThkGetStack16()->Alloc(cb))
+#define StackFree16(vpv, cb) \
+ TlsThkGetStack16()->Free((DWORD)vpv, cb)
+#define StackAlloc32(cb) \
+ ((LPVOID)TlsThkGetStack32()->Alloc(cb))
+#define StackFree32(pv, cb) \
+ TlsThkGetStack32()->Free((DWORD)pv, cb)
+
+#define STACKALLOC16(x) StackAlloc16(x)
+#define STACKFREE16(x,y) StackFree16(x, y)
+
+#ifdef _CHICAGO_
+#define STACKALLOC32(x) StackAlloc32(x)
+#define STACKFREE32(x, y) StackFree32(x, y)
+#else
+#define STACKALLOC32(x) (DWORD)_alloca(x)
+#define STACKFREE32(x, y)
+#endif
+
+#if DBG == 1
+void RecordStackState16(SStackRecord *psr);
+void CheckStackState16(SStackRecord *psr);
+
+void RecordStackState32(SStackRecord *psr);
+void CheckStackState32(SStackRecord *psr);
+#endif
+
+typedef void *(*ALLOCROUTINE)(UINT cb);
+typedef void (*FREEROUTINE)(void *pv, UINT cb);
+
+void *ArTask16(UINT cb);
+void FrTask16(void *pv, UINT cb);
+
+void *ArTask32(UINT cb);
+void FrTask32(void *pv, UINT cb);
+
+void *ArStack16(UINT cb);
+void FrStack16(void *pv, UINT cb);
+
+void *ArStack32(UINT cb);
+void FrStack32(void *pv, UINT cb);
+
+SCODE ConvertDvtd1632(THUNKINFO *pti,
+ VPVOID vpdvtd16,
+ ALLOCROUTINE pfnAlloc,
+ FREEROUTINE pfnFree,
+ DVTARGETDEVICE **ppdvtd32,
+ UINT *pcbSize);
+SCODE ConvertDvtd3216(THUNKINFO *pti,
+ DVTARGETDEVICE *pdvtd32,
+ ALLOCROUTINE pfnAlloc,
+ FREEROUTINE pfnFree,
+ VPVOID *ppvdvtd16,
+ UINT *pcbSize);
+
+typedef void (*FIXEDHANDLERROUTINE)(BYTE *pbFrom, BYTE *pbTo,
+ UINT cbFrom, UINT cbTo);
+
+void FhCopyMemory(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhShortToLong(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhLongToShort(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhWordToDword(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhDwordToWord(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhGdiHandle1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhGdiHandle3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhUserHandle1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhUserHandle3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhHaccel1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhHaccel3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhHtask1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhHtask3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhHresult1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhHresult3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhNull(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhRect1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhRect3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhSize1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhSize3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhMsg1632(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+void FhMsg3216(BYTE *pbFrom, BYTE *pbTo, UINT cbFrom, UINT cbTo);
+
+#endif // #ifndef __THOPUTIL_HXX__
diff --git a/private/ole32/olethunk/olethk32/thtblapi.cxx b/private/ole32/olethunk/olethk32/thtblapi.cxx
new file mode 100644
index 000000000..3bc046a0d
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thtblapi.cxx
@@ -0,0 +1,125 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thtblapi.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include "thopsapi.cxx"
+
+THOP CONST * CONST apthopsApiThops[] =
+{
+ thopsCoInitialize
+, thopsCoUninitialize
+, thopsCoGetClassObject
+, thopsCoRegisterClassObject
+, thopsCoRevokeClassObject
+, thopsCoMarshalInterface
+, thopsCoUnmarshalInterface
+, thopsCoReleaseMarshalData
+, thopsCoDisconnectObject
+, thopsCoLockObjectExternal
+, thopsCoGetStandardMarshal
+, thopsCoIsHandlerConnected
+, thopsCoFreeAllLibraries
+, thopsCoFreeUnusedLibraries
+, thopsCoCreateInstance
+, thopsCLSIDFromString
+, thopsCoIsOle1Class
+, thopsProgIDFromCLSID
+, thopsCLSIDFromProgID
+, thopsCoCreateGuid
+, thopsCoFileTimeToDosDateTime
+, thopsCoDosDateTimeToFileTime
+, thopsCoFileTimeNow
+, thopsCoRegisterMessageFilter
+, thopsCoGetTreatAsClass
+, thopsCoTreatAsClass
+, thopsDllGetClassObject
+, thopsStgCreateDocfile
+, thopsStgCreateDocfileOnILockBytes
+, thopsStgOpenStorage
+, thopsStgOpenStorageOnILockBytes
+, thopsStgIsStorageFile
+, thopsStgIsStorageILockBytes
+, thopsStgSetTimes
+, thopsCreateDataAdviseHolder
+, thopsCreateDataCache
+, thopsBindMoniker
+, thopsMkParseDisplayName
+, thopsMonikerRelativePathTo
+, thopsMonikerCommonPrefixWith
+, thopsCreateBindCtx
+, thopsCreateGenericComposite
+, thopsGetClassFile
+, thopsCreateFileMoniker
+, thopsCreateItemMoniker
+, thopsCreateAntiMoniker
+, thopsCreatePointerMoniker
+, thopsGetRunningObjectTable
+, thopsReadClassStg
+, thopsWriteClassStg
+, thopsReadClassStm
+, thopsWriteClassStm
+, thopsWriteFmtUserTypeStg
+, thopsReadFmtUserTypeStg
+, thopsOleInitialize
+, thopsOleUninitialize
+, thopsOleQueryLinkFromData
+, thopsOleQueryCreateFromData
+, thopsOleCreate
+, thopsOleCreateFromData
+, thopsOleCreateLinkFromData
+, thopsOleCreateStaticFromData
+, thopsOleCreateLink
+, thopsOleCreateLinkToFile
+, thopsOleCreateFromFile
+, thopsOleLoad
+, thopsOleSave
+, thopsOleLoadFromStream
+, thopsOleSaveToStream
+, thopsOleSetContainedObject
+, thopsOleNoteObjectVisible
+, thopsRegisterDragDrop
+, thopsRevokeDragDrop
+, thopsDoDragDrop
+, thopsOleSetClipboard
+, thopsOleGetClipboard
+, thopsOleFlushClipboard
+, thopsOleIsCurrentClipboard
+, thopsOleCreateMenuDescriptor
+, thopsOleSetMenuDescriptor
+, thopsOleDestroyMenuDescriptor
+, thopsOleDraw
+, thopsOleRun
+, thopsOleIsRunning
+, thopsOleLockRunning
+, thopsCreateOleAdviseHolder
+, thopsOleCreateDefaultHandler
+, thopsOleCreateEmbeddingHelper
+, thopsOleRegGetUserType
+, thopsOleRegGetMiscStatus
+, thopsOleRegEnumFormatEtc
+, thopsOleRegEnumVerbs
+, thopsOleConvertIStorageToOLESTREAM
+, thopsOleConvertOLESTREAMToIStorage
+, thopsOleConvertIStorageToOLESTREAMEx
+, thopsOleConvertOLESTREAMToIStorageEx
+, thopsOleDoAutoConvert
+, thopsOleGetAutoConvert
+, thopsOleSetAutoConvert
+, thopsGetConvertStg
+, thopsSetConvertStg
+, thopsReadOleStg
+, thopsWriteOleStg
+};
diff --git a/private/ole32/olethunk/olethk32/thtblint.cxx b/private/ole32/olethunk/olethk32/thtblint.cxx
new file mode 100644
index 000000000..dcd0e89dc
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/thtblint.cxx
@@ -0,0 +1,508 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thtblint.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+THOP CONST * CONST apthopsIUnknown[] =
+{
+ NULL
+};
+THOP CONST * CONST apthopsIClassFactory[] =
+{
+ thopsIClassFactory_CreateInstance
+, thopsIClassFactory_LockServer
+};
+THOP CONST * CONST apthopsIMarshal[] =
+{
+ thopsIMarshal_GetUnmarshalClass
+, thopsIMarshal_GetMarshalSizeMax
+, thopsIMarshal_MarshalInterface
+, thopsIMarshal_UnmarshalInterface
+, thopsIMarshal_ReleaseMarshalData
+, thopsIMarshal_DisconnectObject
+};
+THOP CONST * CONST apthopsIStdMarshalInfo[] =
+{
+ thopsIStdMarshalInfo_GetClassForHandler
+};
+THOP CONST * CONST apthopsIMessageFilter[] =
+{
+ thopsIMessageFilter_HandleInComingCall
+, thopsIMessageFilter_RetryRejectedCall
+, thopsIMessageFilter_MessagePending
+};
+THOP CONST * CONST apthopsIExternalConnection[] =
+{
+ thopsIExternalConnection_AddConnection
+, thopsIExternalConnection_ReleaseConnection
+};
+THOP CONST * CONST apthopsIEnumString[] =
+{
+ thopsIEnumString_Next
+, thopsIEnumString_Skip
+, thopsIEnumString_Reset
+, thopsIEnumString_Clone
+};
+THOP CONST * CONST apthopsIEnumUnknown[] =
+{
+ thopsIEnumUnknown_Next
+, thopsIEnumUnknown_Skip
+, thopsIEnumUnknown_Reset
+, thopsIEnumUnknown_Clone
+};
+THOP CONST * CONST apthopsIEnumSTATSTG[] =
+{
+ thopsIEnumSTATSTG_Next
+, thopsIEnumSTATSTG_Skip
+, thopsIEnumSTATSTG_Reset
+, thopsIEnumSTATSTG_Clone
+};
+THOP CONST * CONST apthopsILockBytes[] =
+{
+ thopsILockBytes_ReadAt
+, thopsILockBytes_WriteAt
+, thopsILockBytes_Flush
+, thopsILockBytes_SetSize
+, thopsILockBytes_LockRegion
+, thopsILockBytes_UnlockRegion
+, thopsILockBytes_Stat
+};
+THOP CONST * CONST apthopsIStream[] =
+{
+ thopsIStream_Read
+, thopsIStream_Write
+, thopsIStream_Seek
+, thopsIStream_SetSize
+, thopsIStream_CopyTo
+, thopsIStream_Commit
+, thopsIStream_Revert
+, thopsIStream_LockRegion
+, thopsIStream_UnlockRegion
+, thopsIStream_Stat
+, thopsIStream_Clone
+};
+THOP CONST * CONST apthopsIStorage[] =
+{
+ thopsIStorage_CreateStream
+, thopsIStorage_OpenStream
+, thopsIStorage_CreateStorage
+, thopsIStorage_OpenStorage
+, thopsIStorage_CopyTo
+, thopsIStorage_MoveElementTo
+, thopsIStorage_Commit
+, thopsIStorage_Revert
+, thopsIStorage_EnumElements
+, thopsIStorage_DestroyElement
+, thopsIStorage_RenameElement
+, thopsIStorage_SetElementTimes
+, thopsIStorage_SetClass
+, thopsIStorage_SetStateBits
+, thopsIStorage_Stat
+};
+THOP CONST * CONST apthopsIRootStorage[] =
+{
+ thopsIRootStorage_SwitchToFile
+};
+THOP CONST * CONST apthopsIEnumFORMATETC[] =
+{
+ thopsIEnumFORMATETC_Next
+, thopsIEnumFORMATETC_Skip
+, thopsIEnumFORMATETC_Reset
+, thopsIEnumFORMATETC_Clone
+};
+THOP CONST * CONST apthopsIEnumSTATDATA[] =
+{
+ thopsIEnumSTATDATA_Next
+, thopsIEnumSTATDATA_Skip
+, thopsIEnumSTATDATA_Reset
+, thopsIEnumSTATDATA_Clone
+};
+THOP CONST * CONST apthopsIDataObject[] =
+{
+ thopsIDataObject_GetData
+, thopsIDataObject_GetDataHere
+, thopsIDataObject_QueryGetData
+, thopsIDataObject_GetCanonicalFormatEtc
+, thopsIDataObject_SetData
+, thopsIDataObject_EnumFormatEtc
+, thopsIDataObject_DAdvise
+, thopsIDataObject_DUnadvise
+, thopsIDataObject_EnumDAdvise
+};
+THOP CONST * CONST apthopsIViewObject[] =
+{
+ thopsIViewObject_Draw
+, thopsIViewObject_GetColorSet
+, thopsIViewObject_Freeze
+, thopsIViewObject_Unfreeze
+, thopsIViewObject_SetAdvise
+, thopsIViewObject_GetAdvise
+};
+THOP CONST * CONST apthopsIViewObject2[] =
+{
+ thopsIViewObject2_Draw
+, thopsIViewObject2_GetColorSet
+, thopsIViewObject2_Freeze
+, thopsIViewObject2_Unfreeze
+, thopsIViewObject2_SetAdvise
+, thopsIViewObject2_GetAdvise
+, thopsIViewObject2_GetExtent
+};
+THOP CONST * CONST apthopsIAdviseSink[] =
+{
+ thopsIAdviseSink_OnDataChange
+, thopsIAdviseSink_OnViewChange
+, thopsIAdviseSink_OnRename
+, thopsIAdviseSink_OnSave
+, thopsIAdviseSink_OnClose
+};
+THOP CONST * CONST apthopsIAdviseSink2[] =
+{
+ thopsIAdviseSink2_OnDataChange
+, thopsIAdviseSink2_OnViewChange
+, thopsIAdviseSink2_OnRename
+, thopsIAdviseSink2_OnSave
+, thopsIAdviseSink2_OnClose
+, thopsIAdviseSink2_OnLinkSrcChange
+};
+THOP CONST * CONST apthopsIDataAdviseHolder[] =
+{
+ thopsIDataAdviseHolder_Advise
+, thopsIDataAdviseHolder_Unadvise
+, thopsIDataAdviseHolder_EnumAdvise
+, thopsIDataAdviseHolder_SendOnDataChange
+};
+THOP CONST * CONST apthopsIOleCache[] =
+{
+ thopsIOleCache_Cache
+, thopsIOleCache_Uncache
+, thopsIOleCache_EnumCache
+, thopsIOleCache_InitCache
+, thopsIOleCache_SetData
+};
+THOP CONST * CONST apthopsIOleCache2[] =
+{
+ thopsIOleCache2_Cache
+, thopsIOleCache2_Uncache
+, thopsIOleCache2_EnumCache
+, thopsIOleCache2_InitCache
+, thopsIOleCache2_SetData
+, thopsIOleCache2_UpdateCache
+, thopsIOleCache2_DiscardCache
+};
+THOP CONST * CONST apthopsIOleCacheControl[] =
+{
+ thopsIOleCacheControl_OnRun
+, thopsIOleCacheControl_OnStop
+};
+THOP CONST * CONST apthopsIDropTarget[] =
+{
+ thopsIDropTarget_DragEnter
+, thopsIDropTarget_DragOver
+, thopsIDropTarget_DragLeave
+, thopsIDropTarget_Drop
+};
+THOP CONST * CONST apthopsIDropSource[] =
+{
+ thopsIDropSource_QueryContinueDrag
+, thopsIDropSource_GiveFeedback
+};
+THOP CONST * CONST apthopsIPersist[] =
+{
+ thopsIPersist_GetClassID
+};
+THOP CONST * CONST apthopsIPersistStorage[] =
+{
+ thopsIPersistStorage_GetClassID
+, thopsIPersistStorage_IsDirty
+, thopsIPersistStorage_InitNew
+, thopsIPersistStorage_Load
+, thopsIPersistStorage_Save
+, thopsIPersistStorage_SaveCompleted
+, thopsIPersistStorage_HandsOffStorage
+};
+THOP CONST * CONST apthopsIPersistStream[] =
+{
+ thopsIPersistStream_GetClassID
+, thopsIPersistStream_IsDirty
+, thopsIPersistStream_Load
+, thopsIPersistStream_Save
+, thopsIPersistStream_GetSizeMax
+};
+THOP CONST * CONST apthopsIPersistFile[] =
+{
+ thopsIPersistFile_GetClassID
+, thopsIPersistFile_IsDirty
+, thopsIPersistFile_Load
+, thopsIPersistFile_Save
+, thopsIPersistFile_SaveCompleted
+, thopsIPersistFile_GetCurFile
+};
+THOP CONST * CONST apthopsIBindCtx[] =
+{
+ thopsIBindCtx_RegisterObjectBound
+, thopsIBindCtx_RevokeObjectBound
+, thopsIBindCtx_ReleaseBoundObjects
+, thopsIBindCtx_SetBindOptions
+, thopsIBindCtx_GetBindOptions
+, thopsIBindCtx_GetRunningObjectTable
+, thopsIBindCtx_RegisterObjectParam
+, thopsIBindCtx_GetObjectParam
+, thopsIBindCtx_EnumObjectParam
+, thopsIBindCtx_RevokeObjectParam
+};
+THOP CONST * CONST apthopsIMoniker[] =
+{
+ thopsIMoniker_GetClassID
+, thopsIMoniker_IsDirty
+, thopsIMoniker_Load
+, thopsIMoniker_Save
+, thopsIMoniker_GetSizeMax
+, thopsIMoniker_BindToObject
+, thopsIMoniker_BindToStorage
+, thopsIMoniker_Reduce
+, thopsIMoniker_ComposeWith
+, thopsIMoniker_Enum
+, thopsIMoniker_IsEqual
+, thopsIMoniker_Hash
+, thopsIMoniker_IsRunning
+, thopsIMoniker_GetTimeOfLastChange
+, thopsIMoniker_Inverse
+, thopsIMoniker_CommonPrefixWith
+, thopsIMoniker_RelativePathTo
+, thopsIMoniker_GetDisplayName
+, thopsIMoniker_ParseDisplayName
+, thopsIMoniker_IsSystemMoniker
+};
+THOP CONST * CONST apthopsIRunningObjectTable[] =
+{
+ thopsIRunningObjectTable_Register
+, thopsIRunningObjectTable_Revoke
+, thopsIRunningObjectTable_IsRunning
+, thopsIRunningObjectTable_GetObject
+, thopsIRunningObjectTable_NoteChangeTime
+, thopsIRunningObjectTable_GetTimeOfLastChange
+, thopsIRunningObjectTable_EnumRunning
+};
+THOP CONST * CONST apthopsIEnumMoniker[] =
+{
+ thopsIEnumMoniker_Next
+, thopsIEnumMoniker_Skip
+, thopsIEnumMoniker_Reset
+, thopsIEnumMoniker_Clone
+};
+THOP CONST * CONST apthopsIEnumOLEVERB[] =
+{
+ thopsIEnumOLEVERB_Next
+, thopsIEnumOLEVERB_Skip
+, thopsIEnumOLEVERB_Reset
+, thopsIEnumOLEVERB_Clone
+};
+THOP CONST * CONST apthopsIOleObject[] =
+{
+ thopsIOleObject_SetClientSite
+, thopsIOleObject_GetClientSite
+, thopsIOleObject_SetHostNames
+, thopsIOleObject_Close
+, thopsIOleObject_SetMoniker
+, thopsIOleObject_GetMoniker
+, thopsIOleObject_InitFromData
+, thopsIOleObject_GetClipboardData
+, thopsIOleObject_DoVerb
+, thopsIOleObject_EnumVerbs
+, thopsIOleObject_Update
+, thopsIOleObject_IsUpToDate
+, thopsIOleObject_GetUserClassID
+, thopsIOleObject_GetUserType
+, thopsIOleObject_SetExtent
+, thopsIOleObject_GetExtent
+, thopsIOleObject_Advise
+, thopsIOleObject_Unadvise
+, thopsIOleObject_EnumAdvise
+, thopsIOleObject_GetMiscStatus
+, thopsIOleObject_SetColorScheme
+};
+THOP CONST * CONST apthopsIOleClientSite[] =
+{
+ thopsIOleClientSite_SaveObject
+, thopsIOleClientSite_GetMoniker
+, thopsIOleClientSite_GetContainer
+, thopsIOleClientSite_ShowObject
+, thopsIOleClientSite_OnShowWindow
+, thopsIOleClientSite_RequestNewObjectLayout
+};
+THOP CONST * CONST apthopsIRunnableObject[] =
+{
+ thopsIRunnableObject_GetRunningClass
+, thopsIRunnableObject_Run
+, thopsIRunnableObject_IsRunning
+, thopsIRunnableObject_LockRunning
+, thopsIRunnableObject_SetContainedObject
+};
+THOP CONST * CONST apthopsIParseDisplayName[] =
+{
+ thopsIParseDisplayName_ParseDisplayName
+};
+THOP CONST * CONST apthopsIOleContainer[] =
+{
+ thopsIOleContainer_ParseDisplayName
+, thopsIOleContainer_EnumObjects
+, thopsIOleContainer_LockContainer
+};
+THOP CONST * CONST apthopsIOleItemContainer[] =
+{
+ thopsIOleItemContainer_ParseDisplayName
+, thopsIOleItemContainer_EnumObjects
+, thopsIOleItemContainer_LockContainer
+, thopsIOleItemContainer_GetObject
+, thopsIOleItemContainer_GetObjectStorage
+, thopsIOleItemContainer_IsRunning
+};
+THOP CONST * CONST apthopsIOleAdviseHolder[] =
+{
+ thopsIOleAdviseHolder_Advise
+, thopsIOleAdviseHolder_Unadvise
+, thopsIOleAdviseHolder_EnumAdvise
+, thopsIOleAdviseHolder_SendOnRename
+, thopsIOleAdviseHolder_SendOnSave
+, thopsIOleAdviseHolder_SendOnClose
+};
+THOP CONST * CONST apthopsIOleLink[] =
+{
+ thopsIOleLink_SetUpdateOptions
+, thopsIOleLink_GetUpdateOptions
+, thopsIOleLink_SetSourceMoniker
+, thopsIOleLink_GetSourceMoniker
+, thopsIOleLink_SetSourceDisplayName
+, thopsIOleLink_GetSourceDisplayName
+, thopsIOleLink_BindToSource
+, thopsIOleLink_BindIfRunning
+, thopsIOleLink_GetBoundSource
+, thopsIOleLink_UnbindSource
+, thopsIOleLink_Update
+};
+THOP CONST * CONST apthopsIOleWindow[] =
+{
+ thopsIOleWindow_GetWindow
+, thopsIOleWindow_ContextSensitiveHelp
+};
+THOP CONST * CONST apthopsIOleInPlaceObject[] =
+{
+ thopsIOleInPlaceObject_GetWindow
+, thopsIOleInPlaceObject_ContextSensitiveHelp
+, thopsIOleInPlaceObject_InPlaceDeactivate
+, thopsIOleInPlaceObject_UIDeactivate
+, thopsIOleInPlaceObject_SetObjectRects
+, thopsIOleInPlaceObject_ReactivateAndUndo
+};
+THOP CONST * CONST apthopsIOleInPlaceActiveObject[] =
+{
+ thopsIOleInPlaceActiveObject_GetWindow
+, thopsIOleInPlaceActiveObject_ContextSensitiveHelp
+, thopsIOleInPlaceActiveObject_TranslateAccelerator
+, thopsIOleInPlaceActiveObject_OnFrameWindowActivate
+, thopsIOleInPlaceActiveObject_OnDocWindowActivate
+, thopsIOleInPlaceActiveObject_ResizeBorder
+, thopsIOleInPlaceActiveObject_EnableModeless
+};
+THOP CONST * CONST apthopsIOleInPlaceUIWindow[] =
+{
+ thopsIOleInPlaceUIWindow_GetWindow
+, thopsIOleInPlaceUIWindow_ContextSensitiveHelp
+, thopsIOleInPlaceUIWindow_GetBorder
+, thopsIOleInPlaceUIWindow_RequestBorderSpace
+, thopsIOleInPlaceUIWindow_SetBorderSpace
+, thopsIOleInPlaceUIWindow_SetActiveObject
+};
+THOP CONST * CONST apthopsIOleInPlaceFrame[] =
+{
+ thopsIOleInPlaceFrame_GetWindow
+, thopsIOleInPlaceFrame_ContextSensitiveHelp
+, thopsIOleInPlaceFrame_GetBorder
+, thopsIOleInPlaceFrame_RequestBorderSpace
+, thopsIOleInPlaceFrame_SetBorderSpace
+, thopsIOleInPlaceFrame_SetActiveObject
+, thopsIOleInPlaceFrame_InsertMenus
+, thopsIOleInPlaceFrame_SetMenu
+, thopsIOleInPlaceFrame_RemoveMenus
+, thopsIOleInPlaceFrame_SetStatusText
+, thopsIOleInPlaceFrame_EnableModeless
+, thopsIOleInPlaceFrame_TranslateAccelerator
+};
+THOP CONST * CONST apthopsIOleInPlaceSite[] =
+{
+ thopsIOleInPlaceSite_GetWindow
+, thopsIOleInPlaceSite_ContextSensitiveHelp
+, thopsIOleInPlaceSite_CanInPlaceActivate
+, thopsIOleInPlaceSite_OnInPlaceActivate
+, thopsIOleInPlaceSite_OnUIActivate
+, thopsIOleInPlaceSite_GetWindowContext
+, thopsIOleInPlaceSite_Scroll
+, thopsIOleInPlaceSite_OnUIDeactivate
+, thopsIOleInPlaceSite_OnInPlaceDeactivate
+, thopsIOleInPlaceSite_DiscardUndoState
+, thopsIOleInPlaceSite_DeactivateAndUndo
+, thopsIOleInPlaceSite_OnPosRectChange
+};
+THOP CONST * CONST apthopsIRpcChannelBuffer[] =
+{
+ thopsIRpcChannelBuffer_GetBuffer
+, thopsIRpcChannelBuffer_SendReceive
+, thopsIRpcChannelBuffer_FreeBuffer
+, thopsIRpcChannelBuffer_GetDestCtx
+, thopsIRpcChannelBuffer_IsConnected
+};
+THOP CONST * CONST apthopsIRpcProxyBuffer[] =
+{
+ thopsIRpcProxyBuffer_Connect
+, thopsIRpcProxyBuffer_Disconnect
+};
+THOP CONST * CONST apthopsIRpcStubBuffer[] =
+{
+ thopsIRpcStubBuffer_Connect
+, thopsIRpcStubBuffer_Disconnect
+, thopsIRpcStubBuffer_Invoke
+, thopsIRpcStubBuffer_IsIIDSupported
+, thopsIRpcStubBuffer_CountRefs
+, thopsIRpcStubBuffer_DebugServerQueryInterface
+, thopsIRpcStubBuffer_DebugServerRelease
+};
+THOP CONST * CONST apthopsIPSFactoryBuffer[] =
+{
+ thopsIPSFactoryBuffer_CreateProxy
+, thopsIPSFactoryBuffer_CreateStub
+};
+THOP CONST * CONST apthopsIRpcChannel[] =
+{
+ thopsIRpcChannel_GetStream
+, thopsIRpcChannel_Call
+, thopsIRpcChannel_GetDestCtx
+, thopsIRpcChannel_IsConnected
+};
+THOP CONST * CONST apthopsIRpcProxy[] =
+{
+ thopsIRpcProxy_Connect
+, thopsIRpcProxy_Disconnect
+};
+THOP CONST * CONST apthopsIRpcStub[] =
+{
+ thopsIRpcStub_Connect
+, thopsIRpcStub_Disconnect
+, thopsIRpcStub_Invoke
+, thopsIRpcStub_IsIIDSupported
+, thopsIRpcStub_CountRefs
+};
+THOP CONST * CONST apthopsIPSFactory[] =
+{
+ thopsIPSFactory_CreateProxy
+, thopsIPSFactory_CreateStub
+};
diff --git a/private/ole32/olethunk/olethk32/tlsthk.cxx b/private/ole32/olethunk/olethk32/tlsthk.cxx
new file mode 100644
index 000000000..628710327
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/tlsthk.cxx
@@ -0,0 +1,171 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: tlsthk.cxx
+//
+// Contents: Utility routines for logical thread data
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+#include "headers.cxx"
+#pragma hdrstop
+
+#define UNINITIALIZED_INDEX (0xffffffff)
+
+DWORD dwTlsThkIndex = UNINITIALIZED_INDEX;
+
+//+---------------------------------------------------------------------------
+//
+// Function: TlsThkGetData
+//
+// Synopsis: returns pointer to thread data
+//
+// Returns: pointer to threaddata
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+PThreadData TlsThkGetData(void)
+{
+ if (dwTlsThkIndex == UNINITIALIZED_INDEX)
+ {
+ thkDebugOut((DEB_WARN, "WARNING: TLS slot used when uninitialized\n"));
+ }
+
+ PThreadData pThreaddata = (PThreadData) TlsGetValue(dwTlsThkIndex);
+
+ return pThreaddata;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: TlsThkAlloc
+//
+// Synopsis: allocates a slot for thread data
+//
+// Returns: BOOL
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+BOOL TlsThkAlloc(void)
+{
+ thkDebugOut((DEB_THUNKMGR, "In TlsThkAlloc\n"));
+
+ // We must be uninitialized to call this routine
+ thkAssert(dwTlsThkIndex == UNINITIALIZED_INDEX);
+
+ dwTlsThkIndex = TlsAlloc();
+ if (dwTlsThkIndex == UNINITIALIZED_INDEX)
+ {
+ return FALSE;
+ }
+
+ thkDebugOut((DEB_THUNKMGR, "Out TlsThkAlloc\n"));
+ return TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TlsThkInitialize
+//
+// Synopsis: allocates thread data and initialize slot
+//
+// Returns: Appropriate status code
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+HRESULT TlsThkInitialize(void)
+{
+ PThreadData pThreaddata;
+
+ thkDebugOut((DEB_THUNKMGR, "In TlsThkInitialize\n"));
+
+ thkAssert(dwTlsThkIndex != UNINITIALIZED_INDEX &&
+ "Tls slot not allocated.");
+
+ // We must be uninitialized to call this routine
+ thkAssert(TlsGetValue(dwTlsThkIndex) == 0);
+
+ pThreaddata = (PThreadData) LocalAlloc(LPTR, sizeof (ThreadData));
+ if(pThreaddata != NULL)
+ {
+ // Force construction since we allocated with LocalAlloc
+ pThreaddata->sa16.CStackAllocator::
+ CStackAllocator(&mmodel16Owned, 1024, 2);
+ pThreaddata->sa32.CStackAllocator::
+ CStackAllocator(&mmodel32, 8192, 8);
+
+ pThreaddata->pCThkMgr = 0;
+ pThreaddata->dwAppCompatFlags = 0;
+
+ TlsSetValue(dwTlsThkIndex, pThreaddata);
+ }
+
+ thkDebugOut((DEB_THUNKMGR, "Out TlsThkInitialize\n"));
+
+ return (pThreaddata != NULL) ? NOERROR : E_OUTOFMEMORY;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TlsThkUninitialize
+//
+// Synopsis: frees thread data and set it to NULL
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void TlsThkUninitialize(void)
+{
+ thkDebugOut((DEB_TLSTHK, "In TlsThkUninitialize\n"));
+
+ // Asserts if data is NULL
+ PThreadData pThreaddata = TlsThkGetData();
+
+ // BUGBUG - We should assert that the things in the ThreadData
+ // are freed up
+
+ if (pThreaddata != NULL)
+ {
+ // Stack allocators are cleaned up elsewhere
+ // because they require special treatment
+
+ if (pThreaddata->pDelayedRegs != NULL)
+ {
+ delete pThreaddata->pDelayedRegs;
+ }
+ LocalFree(pThreaddata);
+ }
+
+ TlsSetValue(dwTlsThkIndex, NULL);
+
+ thkDebugOut((DEB_TLSTHK, "Out TlsThkUninitialize\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: TlsThkFree
+//
+// Synopsis: frees slot
+//
+// History: 5-18-94 JohannP (Johann Posch) Created
+//
+//----------------------------------------------------------------------------
+void TlsThkFree(void)
+{
+ thkAssert(dwTlsThkIndex != UNINITIALIZED_INDEX);
+
+ TlsFree( dwTlsThkIndex );
+
+ // We must set this to an invalid value so any further uses of the
+ // TLS slot will return NULL
+ dwTlsThkIndex = UNINITIALIZED_INDEX;
+}
diff --git a/private/ole32/olethunk/olethk32/tlsthk.hxx b/private/ole32/olethunk/olethk32/tlsthk.hxx
new file mode 100644
index 000000000..c2411133d
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/tlsthk.hxx
@@ -0,0 +1,85 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: TLSTHK.hxx
+//
+// Contents: Thunk routine utilities for tls
+//
+// History: 05-May-94 JohannP Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __TLSTHK_HXX__
+#define __TLSTHK_HXX__
+
+//
+// The following structures are used by CoRegisterClassObjectDelayed
+//
+typedef struct tagDelayedRegistration
+{
+ CLSID _clsid;
+ DWORD _dwRealKey;
+ LPUNKNOWN _punk;
+ DWORD _dwClsContext;
+ DWORD _flags;
+} DelayRegistration;
+
+#define MAX_DELAYED_REGISTRATIONS 8
+
+typedef struct tagDelayedRegistrationTable
+{
+ tagDelayedRegistrationTable()
+ {
+ memset(&_Entries,0,sizeof(_Entries));
+ }
+ DelayRegistration _Entries[MAX_DELAYED_REGISTRATIONS];
+} DelayedRegistrationTable;
+
+//
+// This is the per thread thunk manager state
+//
+
+typedef struct tagThreadData
+{
+ tagThreadData(DWORD cbBlock16,
+ DWORD cbAlign16,
+ DWORD cbBlock32,
+ DWORD cbAlign32)
+ : sa16(&mmodel16Owned, cbBlock16, cbAlign16),
+ sa32(&mmodel32, cbBlock32, cbAlign32),pDelayedRegs(NULL)
+ {
+ }
+
+ CStackAllocator sa16;
+ CStackAllocator sa32;
+ CThkMgr *pCThkMgr;
+ DWORD dwAppCompatFlags;
+ DelayedRegistrationTable *pDelayedRegs;
+} ThreadData, *PThreadData;
+
+HRESULT TlsThkInitialize();
+void TlsThkUninitialize();
+
+BOOL TlsThkAlloc();
+void TlsThkFree();
+
+#if DBG == 1
+PThreadData TlsThkGetData(void);
+#else
+extern DWORD dwTlsThkIndex;
+#define TlsThkGetData() ((PThreadData)TlsGetValue(dwTlsThkIndex))
+#endif
+
+#define TlsThkGetStack16() (&TlsThkGetData()->sa16)
+#define TlsThkGetStack32() (&TlsThkGetData()->sa32)
+
+#define TlsThkGetThkMgr() (TlsThkGetData()->pCThkMgr)
+#define TlsThkSetThkMgr(ptm) ((TlsThkGetData()->pCThkMgr) = (ptm))
+
+#define TlsThkGetAppCompatFlags() (TlsThkGetData()->dwAppCompatFlags)
+#define TlsThkSetAppCompatFlags(dw) \
+ ((TlsThkGetData()->dwAppCompatFlags) = (dw))
+
+#endif // #ifndef __TLSTHK_HXX__
diff --git a/private/ole32/olethunk/olethk32/vtblapi.cxx b/private/ole32/olethunk/olethk32/vtblapi.cxx
new file mode 100644
index 000000000..12f7ea492
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/vtblapi.cxx
@@ -0,0 +1,123 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: vtblapi.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+VTBLFN CONST apfnApiFunctions[] =
+{
+ (VTBLFN)CoInitializeNot
+, (VTBLFN)CoUninitialize
+, (VTBLFN)CoGetClassObject
+, (VTBLFN)CoRegisterClassObjectNot
+, (VTBLFN)CoRevokeClassObjectNot
+, (VTBLFN)CoMarshalInterface
+, (VTBLFN)CoUnmarshalInterface
+, (VTBLFN)CoReleaseMarshalData
+, (VTBLFN)CoDisconnectObject
+, (VTBLFN)CoLockObjectExternal
+, (VTBLFN)CoGetStandardMarshal
+, (VTBLFN)CoIsHandlerConnected
+, (VTBLFN)CoFreeAllLibraries
+, (VTBLFN)CoFreeUnusedLibraries
+, (VTBLFN)CoCreateInstance
+, (VTBLFN)CLSIDFromString
+, (VTBLFN)CoIsOle1Class
+, (VTBLFN)ProgIDFromCLSID
+, (VTBLFN)CLSIDFromProgID
+, (VTBLFN)CoCreateGuid
+, (VTBLFN)CoFileTimeToDosDateTime
+, (VTBLFN)CoDosDateTimeToFileTime
+, (VTBLFN)CoFileTimeNow
+, (VTBLFN)CoRegisterMessageFilter
+, (VTBLFN)CoGetTreatAsClass
+, (VTBLFN)CoTreatAsClass
+, (VTBLFN)DllGetClassObjectWOW
+, (VTBLFN)StgCreateDocfile
+, (VTBLFN)StgCreateDocfileOnILockBytes
+, (VTBLFN)StgOpenStorage
+, (VTBLFN)StgOpenStorageOnILockBytes
+, (VTBLFN)StgIsStorageFile
+, (VTBLFN)StgIsStorageILockBytes
+, (VTBLFN)StgSetTimes
+, (VTBLFN)CreateDataAdviseHolder
+, (VTBLFN)CreateDataCache
+, (VTBLFN)BindMoniker
+, (VTBLFN)MkParseDisplayName
+, (VTBLFN)MonikerRelativePathTo
+, (VTBLFN)MonikerCommonPrefixWith
+, (VTBLFN)CreateBindCtx
+, (VTBLFN)CreateGenericComposite
+, (VTBLFN)GetClassFile
+, (VTBLFN)CreateFileMoniker
+, (VTBLFN)CreateItemMoniker
+, (VTBLFN)CreateAntiMoniker
+, (VTBLFN)CreatePointerMoniker
+, (VTBLFN)GetRunningObjectTable
+, (VTBLFN)ReadClassStg
+, (VTBLFN)WriteClassStg
+, (VTBLFN)ReadClassStm
+, (VTBLFN)WriteClassStm
+, (VTBLFN)WriteFmtUserTypeStg
+, (VTBLFN)ReadFmtUserTypeStg
+, (VTBLFN)OleInitializeNot
+, (VTBLFN)OleUninitialize
+, (VTBLFN)OleQueryLinkFromData
+, (VTBLFN)OleQueryCreateFromData
+, (VTBLFN)OleCreate
+, (VTBLFN)OleCreateFromData
+, (VTBLFN)OleCreateLinkFromData
+, (VTBLFN)OleCreateStaticFromData
+, (VTBLFN)OleCreateLink
+, (VTBLFN)OleCreateLinkToFile
+, (VTBLFN)OleCreateFromFile
+, (VTBLFN)OleLoad
+, (VTBLFN)OleSave
+, (VTBLFN)OleLoadFromStream
+, (VTBLFN)OleSaveToStream
+, (VTBLFN)OleSetContainedObject
+, (VTBLFN)OleNoteObjectVisible
+, (VTBLFN)RegisterDragDrop
+, (VTBLFN)RevokeDragDrop
+, (VTBLFN)DoDragDrop
+, (VTBLFN)OleSetClipboard
+, (VTBLFN)OleGetClipboard
+, (VTBLFN)OleFlushClipboard
+, (VTBLFN)OleIsCurrentClipboard
+, (VTBLFN)OleCreateMenuDescriptor
+, (VTBLFN)OleSetMenuDescriptor
+, (VTBLFN)OleDestroyMenuDescriptor
+, (VTBLFN)OleDraw
+, (VTBLFN)OleRun
+, (VTBLFN)OleIsRunning
+, (VTBLFN)OleLockRunning
+, (VTBLFN)CreateOleAdviseHolder
+, (VTBLFN)OleCreateDefaultHandler
+, (VTBLFN)OleCreateEmbeddingHelper
+, (VTBLFN)OleRegGetUserTypeNot
+, (VTBLFN)OleRegGetMiscStatus
+, (VTBLFN)OleRegEnumFormatEtc
+, (VTBLFN)OleRegEnumVerbs
+, (VTBLFN)OleConvertIStorageToOLESTREAM
+, (VTBLFN)OleConvertOLESTREAMToIStorage
+, (VTBLFN)OleConvertIStorageToOLESTREAMEx
+, (VTBLFN)OleConvertOLESTREAMToIStorageEx
+, (VTBLFN)OleDoAutoConvert
+, (VTBLFN)OleGetAutoConvert
+, (VTBLFN)OleSetAutoConvert
+, (VTBLFN)GetConvertStg
+, (VTBLFN)SetConvertStg
+, (VTBLFN)ReadOleStg
+, (VTBLFN)WriteOleStg
+};
diff --git a/private/ole32/olethunk/olethk32/vtblifn.cxx b/private/ole32/olethunk/olethk32/vtblifn.cxx
new file mode 100644
index 000000000..b6fb85ea4
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/vtblifn.cxx
@@ -0,0 +1,766 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: vtblifn.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+DWORD ThunkMethod3216_48(
+ THUNK3216OBJ *ptoThis32
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[4];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[48];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_47(
+ THUNK3216OBJ *ptoThis32
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[4];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[47];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_46(
+ THUNK3216OBJ *ptoThis32
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[4];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[46];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_45(
+ THUNK3216OBJ *ptoThis32,
+ SIZEL Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(SIZEL *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[45];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_44(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ WORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(WORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[44];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_43(
+ THUNK3216OBJ *ptoThis32
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[4];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[43];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_42(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[42];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_41(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[41];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_40(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[40];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_39(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[39];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_38(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[38];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_37(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[16];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[37];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_36(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[36];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_35(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[35];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_34(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[34];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_33(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ SIZEL Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(SIZEL *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+20) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[33];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_32(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ SIZEL Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[20];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(SIZEL *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+16) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[32];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_31(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ SIZEL Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(SIZEL *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+20) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[31];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_30(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[16];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[30];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_29(
+ THUNK3216OBJ *ptoThis32
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[4];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[29];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_28(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4,
+ DWORD Arg5,
+ DWORD Arg6,
+ DWORD Arg7,
+ DWORD Arg8,
+ DWORD Arg9,
+ DWORD Arg10
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[44];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ *(DWORD *)(bArgs+20) = Arg5;
+ *(DWORD *)(bArgs+24) = Arg6;
+ *(DWORD *)(bArgs+28) = Arg7;
+ *(DWORD *)(bArgs+32) = Arg8;
+ *(DWORD *)(bArgs+36) = Arg9;
+ *(DWORD *)(bArgs+40) = Arg10;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[28];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_27(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[27];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_26(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[26];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_25(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[25];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_24(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[20];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[24];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_23(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[20];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[23];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_22(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[20];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[22];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_21(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4,
+ DWORD Arg5
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ *(DWORD *)(bArgs+20) = Arg5;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[21];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_20(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4,
+ DWORD Arg5
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ *(DWORD *)(bArgs+20) = Arg5;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[20];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_19(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4,
+ DWORD Arg5
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ *(DWORD *)(bArgs+20) = Arg5;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[19];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_18(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ ULARGE_INTEGER Arg2,
+ DWORD Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+16) = Arg3;
+ *(DWORD *)(bArgs+20) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[18];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_17(
+ THUNK3216OBJ *ptoThis32,
+ ULARGE_INTEGER Arg1,
+ DWORD Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[20];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+12) = Arg2;
+ *(DWORD *)(bArgs+16) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[17];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_16(
+ THUNK3216OBJ *ptoThis32,
+ ULARGE_INTEGER Arg1,
+ ULARGE_INTEGER Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+4) = Arg1;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+12) = Arg2;
+ *(DWORD *)(bArgs+20) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[16];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_15(
+ THUNK3216OBJ *ptoThis32,
+ ULARGE_INTEGER Arg1,
+ ULARGE_INTEGER Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+4) = Arg1;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+12) = Arg2;
+ *(DWORD *)(bArgs+20) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[15];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_14(
+ THUNK3216OBJ *ptoThis32,
+ ULARGE_INTEGER Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[14];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_13(
+ THUNK3216OBJ *ptoThis32,
+ ULARGE_INTEGER Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+12) = Arg2;
+ *(DWORD *)(bArgs+16) = Arg3;
+ *(DWORD *)(bArgs+20) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[13];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_12(
+ THUNK3216OBJ *ptoThis32,
+ ULARGE_INTEGER Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[24];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(ULARGE_INTEGER UNALIGNED *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+12) = Arg2;
+ *(DWORD *)(bArgs+16) = Arg3;
+ *(DWORD *)(bArgs+20) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[12];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_11(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[16];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[11];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_10(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[20];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[10];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_9(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4,
+ DWORD Arg5,
+ DWORD Arg6
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[28];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ *(DWORD *)(bArgs+20) = Arg5;
+ *(DWORD *)(bArgs+24) = Arg6;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[9];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_8(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4,
+ DWORD Arg5,
+ DWORD Arg6
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[28];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ *(DWORD *)(bArgs+20) = Arg5;
+ *(DWORD *)(bArgs+24) = Arg6;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[8];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_7(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3,
+ DWORD Arg4,
+ DWORD Arg5,
+ DWORD Arg6
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[28];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ *(DWORD *)(bArgs+16) = Arg4;
+ *(DWORD *)(bArgs+20) = Arg5;
+ *(DWORD *)(bArgs+24) = Arg6;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[7];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_6(
+ THUNK3216OBJ *ptoThis32
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[4];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[6];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_5(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[5];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_4(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[4];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_3(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[3];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_2(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[12];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[2];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_1(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[8];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[1];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
+DWORD ThunkMethod3216_0(
+ THUNK3216OBJ *ptoThis32,
+ DWORD Arg1,
+ DWORD Arg2,
+ DWORD Arg3
+ )
+{
+ DWORD dwMethod;
+ BYTE bArgs[16];
+ *(VPVOID *)bArgs = (DWORD)ptoThis32;
+ *(DWORD *)(bArgs+4) = Arg1;
+ *(DWORD *)(bArgs+8) = Arg2;
+ *(DWORD *)(bArgs+12) = Arg3;
+ dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)].pftm[0];
+ return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), dwMethod, bArgs);
+}
diff --git a/private/ole32/olethunk/olethk32/vtblint.cxx b/private/ole32/olethunk/olethk32/vtblint.cxx
new file mode 100644
index 000000000..cd1e9b62b
--- /dev/null
+++ b/private/ole32/olethunk/olethk32/vtblint.cxx
@@ -0,0 +1,678 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: vtblint.cxx
+//
+// Notes: This file is automatically generated
+// Do not modify by hand
+//
+// History: Fri May 27 10:39:02 1994 Generated
+//
+//----------------------------------------------------------------------------
+
+THUNK3216FN CONST tfnIUnknown[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+};
+THUNK3216FN CONST tfnIClassFactory[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_0
+, (THUNK3216FN)ThunkMethod3216_1
+};
+THUNK3216FN CONST tfnIMarshal[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_7
+, (THUNK3216FN)ThunkMethod3216_8
+, (THUNK3216FN)ThunkMethod3216_9
+, (THUNK3216FN)ThunkMethod3216_0
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIStdMarshalInfo[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_0
+};
+THUNK3216FN CONST tfnIMessageFilter[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_10
+, (THUNK3216FN)ThunkMethod3216_0
+, (THUNK3216FN)ThunkMethod3216_11
+};
+THUNK3216FN CONST tfnIExternalConnection[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_2
+, (THUNK3216FN)ThunkMethod3216_11
+};
+THUNK3216FN CONST tfnIEnumString[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIEnumUnknown[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIEnumSTATSTG[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnILockBytes[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_12
+, (THUNK3216FN)ThunkMethod3216_13
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_14
+, (THUNK3216FN)ThunkMethod3216_15
+, (THUNK3216FN)ThunkMethod3216_16
+, (THUNK3216FN)ThunkMethod3216_2
+};
+THUNK3216FN CONST tfnIStream[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_0
+, (THUNK3216FN)ThunkMethod3216_17
+, (THUNK3216FN)ThunkMethod3216_14
+, (THUNK3216FN)ThunkMethod3216_18
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_16
+, (THUNK3216FN)ThunkMethod3216_15
+, (THUNK3216FN)ThunkMethod3216_2
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIStorage[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_19
+, (THUNK3216FN)ThunkMethod3216_20
+, (THUNK3216FN)ThunkMethod3216_21
+, (THUNK3216FN)ThunkMethod3216_9
+, (THUNK3216FN)ThunkMethod3216_10
+, (THUNK3216FN)ThunkMethod3216_22
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_23
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_2
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_25
+, (THUNK3216FN)ThunkMethod3216_26
+};
+THUNK3216FN CONST tfnIRootStorage[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_5
+};
+THUNK3216FN CONST tfnIEnumFORMATETC[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIEnumSTATDATA[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIDataObject[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_25
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_2
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_3
+};
+THUNK3216FN CONST tfnIViewObject[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_28
+, (THUNK3216FN)ThunkMethod3216_9
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_0
+};
+THUNK3216FN CONST tfnIViewObject2[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_28
+, (THUNK3216FN)ThunkMethod3216_9
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_0
+, (THUNK3216FN)ThunkMethod3216_23
+};
+THUNK3216FN CONST tfnIAdviseSink[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_29
+};
+THUNK3216FN CONST tfnIAdviseSink2[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIDataAdviseHolder[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_21
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_11
+};
+THUNK3216FN CONST tfnIOleCache[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_0
+};
+THUNK3216FN CONST tfnIOleCache2[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_0
+, (THUNK3216FN)ThunkMethod3216_30
+, (THUNK3216FN)ThunkMethod3216_1
+};
+THUNK3216FN CONST tfnIOleCacheControl[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_29
+};
+THUNK3216FN CONST tfnIDropTarget[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_31
+, (THUNK3216FN)ThunkMethod3216_32
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_33
+};
+THUNK3216FN CONST tfnIDropSource[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_5
+};
+THUNK3216FN CONST tfnIPersist[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_5
+};
+THUNK3216FN CONST tfnIPersistStorage[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_1
+, (THUNK3216FN)ThunkMethod3216_6
+};
+THUNK3216FN CONST tfnIPersistStream[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_3
+};
+THUNK3216FN CONST tfnIPersistFile[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_3
+};
+THUNK3216FN CONST tfnIBindCtx[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_1
+, (THUNK3216FN)ThunkMethod3216_34
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_36
+};
+THUNK3216FN CONST tfnIMoniker[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_34
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_23
+, (THUNK3216FN)ThunkMethod3216_22
+, (THUNK3216FN)ThunkMethod3216_30
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_11
+, (THUNK3216FN)ThunkMethod3216_0
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_25
+, (THUNK3216FN)ThunkMethod3216_2
+, (THUNK3216FN)ThunkMethod3216_37
+, (THUNK3216FN)ThunkMethod3216_21
+, (THUNK3216FN)ThunkMethod3216_1
+};
+THUNK3216FN CONST tfnIRunningObjectTable[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_25
+, (THUNK3216FN)ThunkMethod3216_34
+};
+THUNK3216FN CONST tfnIEnumMoniker[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_37
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_35
+};
+THUNK3216FN CONST tfnIEnumOLEVERB[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_37
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_35
+};
+THUNK3216FN CONST tfnIOleObject[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_27
+, (THUNK3216FN)ThunkMethod3216_34
+, (THUNK3216FN)ThunkMethod3216_26
+, (THUNK3216FN)ThunkMethod3216_37
+, (THUNK3216FN)ThunkMethod3216_30
+, (THUNK3216FN)ThunkMethod3216_25
+, (THUNK3216FN)ThunkMethod3216_9
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_2
+, (THUNK3216FN)ThunkMethod3216_38
+, (THUNK3216FN)ThunkMethod3216_39
+, (THUNK3216FN)ThunkMethod3216_40
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_1
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_42
+};
+THUNK3216FN CONST tfnIOleClientSite[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_37
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_43
+};
+THUNK3216FN CONST tfnIRunnableObject[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_43
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_35
+};
+THUNK3216FN CONST tfnIParseDisplayName[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_24
+};
+THUNK3216FN CONST tfnIOleContainer[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_42
+};
+THUNK3216FN CONST tfnIOleItemContainer[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_21
+, (THUNK3216FN)ThunkMethod3216_23
+, (THUNK3216FN)ThunkMethod3216_36
+};
+THUNK3216FN CONST tfnIOleAdviseHolder[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_43
+, (THUNK3216FN)ThunkMethod3216_29
+};
+THUNK3216FN CONST tfnIOleLink[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_34
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_40
+, (THUNK3216FN)ThunkMethod3216_43
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_3
+};
+THUNK3216FN CONST tfnIOleWindow[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+};
+THUNK3216FN CONST tfnIOleInPlaceObject[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_43
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_6
+};
+THUNK3216FN CONST tfnIOleInPlaceActiveObject[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_34
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_37
+, (THUNK3216FN)ThunkMethod3216_4
+};
+THUNK3216FN CONST tfnIOleInPlaceUIWindow[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_34
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_41
+};
+THUNK3216FN CONST tfnIOleInPlaceFrame[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_34
+, (THUNK3216FN)ThunkMethod3216_5
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_40
+, (THUNK3216FN)ThunkMethod3216_37
+, (THUNK3216FN)ThunkMethod3216_4
+, (THUNK3216FN)ThunkMethod3216_3
+, (THUNK3216FN)ThunkMethod3216_1
+, (THUNK3216FN)ThunkMethod3216_44
+};
+THUNK3216FN CONST tfnIOleInPlaceSite[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_43
+, (THUNK3216FN)ThunkMethod3216_29
+, (THUNK3216FN)ThunkMethod3216_6
+, (THUNK3216FN)ThunkMethod3216_21
+, (THUNK3216FN)ThunkMethod3216_45
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_46
+, (THUNK3216FN)ThunkMethod3216_47
+, (THUNK3216FN)ThunkMethod3216_48
+, (THUNK3216FN)ThunkMethod3216_34
+};
+THUNK3216FN CONST tfnIRpcChannelBuffer[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_40
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_39
+, (THUNK3216FN)ThunkMethod3216_48
+};
+THUNK3216FN CONST tfnIRpcProxyBuffer[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_48
+};
+THUNK3216FN CONST tfnIRpcStubBuffer[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_48
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_47
+, (THUNK3216FN)ThunkMethod3216_35
+, (THUNK3216FN)ThunkMethod3216_34
+};
+THUNK3216FN CONST tfnIPSFactoryBuffer[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_37
+};
+THUNK3216FN CONST tfnIRpcChannel[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_9
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_41
+, (THUNK3216FN)ThunkMethod3216_48
+};
+THUNK3216FN CONST tfnIRpcProxy[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_48
+};
+THUNK3216FN CONST tfnIRpcStub[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_42
+, (THUNK3216FN)ThunkMethod3216_48
+, (THUNK3216FN)ThunkMethod3216_21
+, (THUNK3216FN)ThunkMethod3216_36
+, (THUNK3216FN)ThunkMethod3216_47
+};
+THUNK3216FN CONST tfnIPSFactory[] =
+{
+ (THUNK3216FN)QueryInterfaceProxy3216
+, (THUNK3216FN)AddRefProxy3216
+, (THUNK3216FN)ReleaseProxy3216
+, (THUNK3216FN)ThunkMethod3216_24
+, (THUNK3216FN)ThunkMethod3216_37
+};
diff --git a/private/ole32/olethunk/thc/readme.txt b/private/ole32/olethunk/thc/readme.txt
new file mode 100644
index 000000000..8fbe5705c
--- /dev/null
+++ b/private/ole32/olethunk/thc/readme.txt
@@ -0,0 +1,34 @@
+This tool is out of date!
+
+This directory contains the stuff that generated some of the source files
+found in olethk32. It was originaly used to generate the thopping strings
+and stubs and then abandon.
+
+I found this source when I needed to make some systematic changes to
+the thopping tables and stubs. (first "const" and later "unalined").
+I dusted it off and brought it mostly up to date. But there are still
+problems with "thopsint.cxx".
+
+This directory is not part of the "build". It is build by hand when
+the tool is needed. The build process is not automatic, please read
+the instructions for each directory. The original owner prefered the
+old Cairo build process that is no longer supported.
+
+thc\
+ This contains the generator program itself. It uses YACC and FLEX
+ (which I have checked into that directory). Run nmake -f makefil0
+ before running "build" to process the yacc/flex part of the build.
+ NT build doesn't support these tools.
+
+thpp\
+ This contains the OLE header files that the THC.EXE program processes
+ into the Thunking tables. First all the headers are PreProcessed into
+ on big "main.i". Run nmake -f makefile0 to build "main.i"
+
+thsplit\
+ Obsolete.
+
+To generate the source files for olethk32 run "thc main" and 17
+output source files will be deposited in the current directory.
+ -- Sept '95 (again Feb '96)
+
diff --git a/private/ole32/olethunk/thc/thc/depend.mk b/private/ole32/olethunk/thc/thc/depend.mk
new file mode 100644
index 000000000..d81e93b54
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/depend.mk
@@ -0,0 +1,32 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\main.obj $(OBJDIR)\main.lst: .\main.c $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h .\main.h .\type.h
+
+$(OBJDIR)\gen.obj $(OBJDIR)\gen.lst: .\gen.c $(CRTINC)\ctype.h \
+ $(CRTINC)\stdio.h .\gen.h .\special.h .\main.h .\type.h
+
+$(OBJDIR)\grammar.obj $(OBJDIR)\grammar.lst: .\grammar.c $(CRTINC)\malloc.h \
+ $(CRTINC)\string.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h .\op.h \
+ .\gen.h .\main.h .\type.h
+
+$(OBJDIR)\lexer.obj $(OBJDIR)\lexer.lst: .\lexer.c $(CRTINC)\io.h \
+ $(CRTINC)\stddef.h $(CRTINC)\ctype.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\grammar.h .\main.h .\type.h
+
+$(OBJDIR)\type.obj $(OBJDIR)\type.lst: .\type.c $(CRTINC)\malloc.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h .\main.h \
+ .\type.h
+
+$(OBJDIR)\special.obj $(OBJDIR)\special.lst: .\special.c $(CRTINC)\ctype.h \
+ $(CRTINC)\stdio.h .\gen.h .\main.h .\special.h .\type.h
+
+$(OBJDIR)\op.obj $(OBJDIR)\op.lst: .\op.c $(CRTINC)\stdio.h .\main.h \
+ .\op.h
+
diff --git a/private/ole32/olethunk/thc/thc/filelist.mk b/private/ole32/olethunk/thc/thc/filelist.mk
new file mode 100644
index 000000000..fedad6f1c
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/filelist.mk
@@ -0,0 +1,20 @@
+TARGET = thc.exe
+
+CFILES = \
+ .\main.c\
+ .\lexer.c\
+ .\grammar.c\
+ .\type.c\
+ .\op.c\
+ .\gen.c\
+ .\special.c
+
+CFLAGS = -D__STDC__
+
+YACCFILES = .\grammar.y
+
+DEPENDFILES = $(DEPENDFILES) .\grammar.h .\grammar.c .\lexer.c
+
+CLEANFILES = $(CLEANFILES) .\lexer.c
+
+NO_WINMAIN = 1
diff --git a/private/ole32/olethunk/thc/thc/gen.c b/private/ole32/olethunk/thc/thc/gen.c
new file mode 100644
index 000000000..b40389940
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/gen.c
@@ -0,0 +1,1785 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "type.h"
+#include "main.h"
+#include "gen.h"
+#include "special.h"
+
+typedef struct _FileSection
+{
+ char *file;
+ int is_cxx;
+ FILE *fp;
+} FileSection;
+
+FileSection sections[] =
+{
+ /* The following files are all #included into a single file so
+ only the master file (thopiint) gets cxx decoration */
+ "thopiint.cxx", TRUE, NULL,
+ "thopsint.cxx", FALSE, NULL,
+ "thtblint.cxx", FALSE, NULL,
+ "vtblint.cxx", FALSE, NULL,
+ "vtblifn.cxx", FALSE, NULL,
+ "fntomthd.cxx", FALSE, NULL,
+
+ "tc1632.cxx", TRUE, NULL,
+ "thi.hxx", FALSE, NULL,
+ "apilist.hxx", FALSE, NULL,
+
+ /* thopsapi is combined with thtblapi so don't generate
+ cxx code for it */
+ "thtblapi.cxx", TRUE, NULL,
+ "thopsapi.cxx", FALSE, NULL,
+
+ "vtblapi.cxx", TRUE, NULL,
+ "iidtothi.cxx", TRUE, NULL,
+ "the.hxx", FALSE, NULL,
+ "dbgapi.cxx", TRUE, NULL,
+
+ /* These two files are a group */
+ "dbgint.cxx", FALSE, NULL,
+ "dbgitbl.cxx", TRUE, NULL
+};
+
+static FILE *cur_section;
+
+void SecOut(char *fmt, ...)
+{
+ va_list args;
+
+ if (cur_section == NULL)
+ {
+ return;
+ }
+
+ va_start(args, fmt);
+ vfprintf(cur_section, fmt, args);
+ va_end(args);
+}
+
+void Section(int sec)
+{
+ if (cur_section == NULL)
+ {
+ cur_section = sections[sec].fp;
+ }
+ else
+ {
+ if (cur_section != sections[sec].fp)
+ {
+ LexError("Attempt to use section %d when other section open\n",
+ sec);
+ cur_section = sections[sec].fp;
+ }
+ else
+ {
+ cur_section = NULL;
+ }
+ }
+}
+
+void OpenSection(int sec)
+{
+ sections[sec].fp = fopen(sections[sec].file, "w");
+ if (sections[sec].fp == NULL)
+ {
+ perror(sections[sec].file);
+ exit(1);
+ }
+}
+
+void CloseSection(int sec)
+{
+ fclose(sections[sec].fp);
+}
+
+void tGenType(char *name, Type *t, int postpone_name)
+{
+ if (t == NULL)
+ {
+ LexError("untyped %s", name);
+ return;
+ }
+
+ for (;;)
+ {
+ if (t->base == NULL || t->kind == TYK_TYPEDEF)
+ {
+ switch(t->kind)
+ {
+ case TYK_STRUCT:
+ case TYK_UNION:
+ case TYK_CLASS:
+ case TYK_ENUM:
+ SecOut("%s ", TypeKindNames[t->kind]);
+ break;
+ }
+ if (t->name)
+ SecOut("%s", t->name);
+ else
+ SecOut("<anonymous>");
+ if (!postpone_name)
+ SecOut(" %s", name);
+ break;
+ }
+ else
+ {
+ switch(t->kind)
+ {
+ case TYK_QUALIFIER:
+ if (t->flags & TYF_UNSIGNED)
+ SecOut("unsigned ");
+ if (t->flags & TYF_CONST)
+ SecOut("const ");
+ if (t->flags & TYF_IN)
+ SecOut("__in ");
+ if (t->flags & TYF_OUT)
+ SecOut("__out ");
+ break;
+ case TYK_POINTER:
+ tGenType(name, t->base, TRUE);
+ SecOut(" *");
+ if (!postpone_name)
+ SecOut("%s", name);
+ t = NULL;
+ break;
+ case TYK_ARRAY:
+ tGenType(name, t->base, FALSE);
+ SecOut("[%d]", t->u.array.len);
+ t = NULL;
+ break;
+ case TYK_FUNCTION:
+ tGenType(NULL, t->base, TRUE);
+ SecOut(" (*%s)(...)", name);
+ t = NULL;
+ break;
+
+ default:
+ LexError("<Unhandled non-base type>");
+ t = NULL;
+ break;
+ }
+
+ if (t == NULL)
+ break;
+ else
+ t = t->base;
+ }
+ }
+}
+
+void tGenMember(char *name_prefix, Member *m)
+{
+ char nm[128], *mnm;
+
+ if (m->name)
+ mnm = m->name;
+ else
+ mnm = "<unnamed>";
+ if (name_prefix)
+ sprintf(nm, "%s%s", name_prefix, mnm);
+ else
+ strcpy(nm, mnm);
+
+ tGenType(nm, m->type, FALSE);
+}
+
+void tGenParamList(Member *params)
+{
+ SecOut("(");
+ if (params->type && params->type->kind == TYK_BASE &&
+ !strcmp(params->type->name, "void"))
+ {
+ SecOut("void");
+ }
+ else
+ {
+ while (params)
+ {
+ tGenMember(NULL, params);
+ params = params->next;
+ if (params)
+ SecOut(", ");
+ }
+ }
+ SecOut(");\n");
+}
+
+#define is_id_char(c) (isalnum(c) || (c) == '_')
+
+int EqStructure(char *structure, char *match)
+{
+ char enclosing = 0;
+
+ for (;;)
+ {
+ if (*structure == 0 || *match == 0)
+ return *structure == *match;
+
+ switch(*match)
+ {
+ case '?':
+ if (enclosing == 0)
+ return TRUE;
+
+ while (*structure != enclosing && is_id_char(*structure))
+ structure++;
+
+ if (*structure != enclosing)
+ {
+ LexError("Improperly formed structure string");
+ return FALSE;
+ }
+
+ if (*++match != enclosing)
+ LexError("Improperly formed match string");
+ enclosing = 0;
+ break;
+
+ case '<':
+ enclosing = '>';
+ goto must_match;
+ case '/':
+ enclosing = '/';
+ goto must_match;
+ case '[':
+ enclosing = ']';
+ goto must_match;
+ case '\'':
+ enclosing = '\'';
+ goto must_match;
+ case '{':
+ enclosing = '}';
+ goto must_match;
+ case '(':
+ enclosing = ')';
+ goto must_match;
+
+ default:
+ must_match:
+ if (*structure != *match)
+ return FALSE;
+ break;
+ }
+ structure++;
+ match++;
+ }
+}
+
+void Nothing(char *structure, char *arg)
+{
+}
+
+void PrintArg(char *structure, char *arg)
+{
+ SecOut("%s", arg);
+}
+
+void ClassIn(char *structure, char *arg)
+{
+ structure += 2;
+ structure[strlen(structure)-1] = 0;
+ SecOut("THOP_IFACE | THOP_IN, THI_%s", structure);
+}
+
+void ClassOut(char *structure, char *arg)
+{
+ structure += 3;
+ structure[strlen(structure)-1] = 0;
+ SecOut("THOP_IFACE | THOP_OUT, THI_%s", structure);
+}
+
+void StructureError(char *structure, char *arg)
+{
+ LexError("<ERROR - StructureError called>\n");
+}
+
+typedef struct _ToThop
+{
+ char *structure;
+ ParamDesc desc;
+ void (*fn)(char *structure, char *arg);
+ char *arg;
+ int review;
+} ToThop;
+
+ToThop to_thops[] =
+{
+ "<HRESULT>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_HRESULT",
+ FALSE,
+
+ "u<long>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY, 4",
+ FALSE,
+
+ "<long>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY, 4",
+ FALSE,
+
+ "*<long>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_OUT, 4",
+ FALSE,
+
+ "<int>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_SHORTLONG",
+ FALSE,
+
+ "*<int>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_SHORTLONG | THOP_OUT",
+ FALSE,
+
+ "u<int>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_WORDDWORD",
+ FALSE,
+
+ "*/?/",
+ SIGF_SCALAR, 4,
+ ClassIn, "",
+ FALSE,
+
+ "**/?/",
+ SIGF_SCALAR, 4,
+ ClassOut, "",
+ FALSE,
+
+ "<void>",
+ SIGF_NONE, 0,
+ Nothing, "",
+ FALSE,
+
+ "*u<long>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_OUT, 4",
+ FALSE,
+
+ "*<WCHAR>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_LPSTR | THOP_IN",
+ FALSE,
+
+ "*<char>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_LPSTR | THOP_IN",
+ FALSE,
+
+ "<REFGUID>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_IN, 16",
+ FALSE,
+
+ "<REFCLSID>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_IN, 16",
+ FALSE,
+
+ "<REFIID>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_IN, 16",
+ FALSE,
+
+ "*<HRESULT>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_HRESULT | THOP_OUT",
+ FALSE,
+
+ "<HANDLE>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_HANDLE",
+ FALSE,
+
+ "<HINSTANCE>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_HINST",
+ FALSE,
+
+ "<HDC>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_HGDI",
+ FALSE,
+
+ "<HWND>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_HUSER",
+ FALSE,
+
+ "*<HWND>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_HUSER | THOP_OUT",
+ FALSE,
+
+ "<HMENU>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_HUSER",
+ FALSE,
+
+ "<HOLEMENU>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_ALIAS32, ALIAS_RESOLVE",
+ FALSE,
+
+ "<HACCEL>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_HACCEL",
+ FALSE,
+
+ "<HGLOBAL>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_HGLOBAL",
+ FALSE,
+
+ "*<HGLOBAL>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_HGLOBAL | THOP_OUT",
+ FALSE,
+
+ "<HICON>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_HGDI",
+ FALSE,
+
+ "<HTASK>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_HTASK",
+ FALSE,
+
+ "**<WCHAR>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_LPLPSTR",
+ FALSE,
+
+ "**<char>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_LPLPSTR",
+ FALSE,
+
+ "u<short>",
+ SIGF_SCALAR, 2,
+ PrintArg, "THOP_WORDDWORD",
+ FALSE,
+
+ "*u<short>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_WORDDWORD | THOP_OUT",
+ FALSE,
+
+ "{tagULARGE_INTEGER}",
+ SIGF_SCALAR|SIGF_UNALIGNED, 8,
+ PrintArg, "THOP_COPY, 8",
+ FALSE,
+
+ "{_ULARGE_INTEGER}",
+ SIGF_SCALAR|SIGF_UNALIGNED, 8,
+ PrintArg, "THOP_COPY, 8",
+ FALSE,
+
+ "{tagLARGE_INTEGER}",
+ SIGF_SCALAR|SIGF_UNALIGNED, 8,
+ PrintArg, "THOP_COPY, 8",
+ FALSE,
+
+ "{_LARGE_INTEGER}",
+ SIGF_SCALAR|SIGF_UNALIGNED, 8,
+ PrintArg, "THOP_COPY, 8",
+ FALSE,
+
+ "*{tagULARGE_INTEGER}",
+ SIGF_SCALAR|SIGF_UNALIGNED, 4,
+ PrintArg, "THOP_COPY | THOP_OUT, 8",
+ FALSE,
+
+ "*{_ULARGE_INTEGER}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_OUT, 8",
+ FALSE,
+
+ "*{tagLOGPALETTE}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_LOGPALETTE | THOP_IN",
+ FALSE,
+
+ "**{tagLOGPALETTE}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_LOGPALETTE | THOP_OUT",
+ FALSE,
+
+ "{tagPOINTL}",
+ SIGF_NONE, 8,
+ PrintArg, "THOP_COPY, 8",
+ FALSE,
+
+ "{tagSIZEL}",
+ SIGF_NONE, 8,
+ PrintArg, "THOP_COPY, 8",
+ FALSE,
+
+ "{tagSIZE}",
+ SIGF_NONE, 8,
+ PrintArg, "THOP_SIZE",
+ FALSE,
+
+ "*{GUID}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_OUT, 16",
+ FALSE,
+
+ "*{tagSTATSTG}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_STATSTG | THOP_OUT",
+ FALSE,
+
+ "<SNB>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_SNB",
+ FALSE,
+
+ "*{tagDVTARGETDEVICE}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_DVTARGETDEVICE | THOP_IN",
+ FALSE,
+
+ "*{tagMSG}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_MSG | THOP_IN",
+ FALSE,
+
+ "*{tagINTERFACEINFO}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_INTERFACEINFO | THOP_IN",
+ FALSE,
+
+ /* An OLESTREAM must always be filled out so it's always inout */
+ "*{_OLESTREAM}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_OLESTREAM | THOP_INOUT",
+ FALSE,
+
+ /* RPCOLEMESSAGE seems to always be inout */
+ "*{tagRPCOLEMESSAGE}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_RPCOLEMESSAGE | THOP_INOUT",
+ FALSE,
+
+ "i*{tagRECT}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_RECT | THOP_IN",
+ FALSE,
+
+ "i*{tagBIND_OPTS}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_BINDOPTS | THOP_IN",
+ FALSE,
+
+ "i*{tagRECTL}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_IN, 16",
+ FALSE,
+
+ "i*{tagSTGMEDIUM}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_STGMEDIUM | THOP_IN, 0, 0",
+ FALSE,
+
+ "i*{tagFORMATETC}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_FORMATETC | THOP_IN",
+ FALSE,
+
+ "i*{tagOIFI}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_OIFI | THOP_IN",
+ FALSE,
+
+ "i*{tagFILETIME}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_IN, 8",
+ FALSE,
+
+ "i*{tagSIZEL}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_IN, 8",
+ FALSE,
+
+ "i*{tagOleMenuGroupWidths}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_IN, 24",
+ FALSE,
+
+ "o*{tagRECT}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_RECT | THOP_OUT",
+ FALSE,
+
+ "o*{tagRECTL}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_OUT, 16",
+ FALSE,
+
+ "o*{tagSTGMEDIUM}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_STGMEDIUM | THOP_OUT, 0, 0",
+ FALSE,
+
+ "o*{tagFORMATETC}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_FORMATETC | THOP_OUT",
+ FALSE,
+
+ "o*{tagOIFI}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_OIFI | THOP_OUT",
+ FALSE,
+
+ "o*{tagFILETIME}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_OUT, 8",
+ FALSE,
+
+ "o*{tagSIZEL}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_OUT, 8",
+ FALSE,
+
+ "o*{tagBIND_OPTS}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_BINDOPTS | THOP_OUT",
+ FALSE,
+
+ "io*{tagOleMenuGroupWidths}",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_INOUT, 24",
+ FALSE,
+
+ "io*u<long>",
+ SIGF_SCALAR, 4,
+ PrintArg, "THOP_COPY | THOP_INOUT, 4",
+ FALSE,
+
+ /* The following can't be used as structural elements but
+ are needed for size computations */
+ "*<void>",
+ SIGF_SCALAR, 4,
+ StructureError, NULL,
+ TRUE,
+
+ "**<void>",
+ SIGF_SCALAR, 4,
+ StructureError, NULL,
+ TRUE,
+
+ "(pfn)",
+ SIGF_SCALAR, 4,
+ StructureError, NULL,
+ TRUE,
+
+ "*{tagSTATDATA}",
+ SIGF_SCALAR, 4,
+ StructureError, NULL,
+ TRUE,
+
+ "*{tagOLEVERB}",
+ SIGF_SCALAR, 4,
+ StructureError, NULL,
+ TRUE
+};
+#define TO_THOPS (sizeof(to_thops)/sizeof(to_thops[0]))
+
+static int needs_review;
+
+void sGenToThops(char *structure, int generic)
+{
+ int i;
+
+ for (i = 0; i < TO_THOPS; i++)
+ if (EqStructure(structure, to_thops[i].structure))
+ {
+ if (generic)
+ needs_review |= to_thops[i].review;
+ to_thops[i].fn(structure, to_thops[i].arg);
+ return;
+ }
+ LexError("<BUGBUG untranslatable '%s'>", structure);
+}
+
+static void TypeStructure(Type *t, char *structure)
+{
+ char *p;
+
+ if (t == NULL)
+ {
+ LexError("TypeStructure: No type\n");
+ return;
+ }
+
+ p = structure;
+ while (t)
+ {
+ switch(t->kind)
+ {
+ case TYK_BASE:
+ sprintf(p, "<%s>", t->name);
+ p += strlen(p);
+ t = NULL;
+ break;
+ case TYK_TYPEDEF:
+ t = t->base;
+ break;
+ case TYK_QUALIFIER:
+ if (t->flags & TYF_UNSIGNED)
+ *p++ = 'u';
+ if (t->flags & TYF_IN)
+ *p++ = 'i';
+ if (t->flags & TYF_OUT)
+ *p++ = 'o';
+ t = t->base;
+ break;
+ case TYK_POINTER:
+ *p++ = '*';
+ t = t->base;
+ break;
+ case TYK_ARRAY:
+ LexError("<BUGBUG - unhandled array>\n");
+ t = t->base;
+ break;
+ case TYK_STRUCT:
+ sprintf(p, "{%s}", t->name);
+ p += strlen(p);
+ t = NULL;
+ break;
+ case TYK_UNION:
+ sprintf(p, "[%s]", t->name);
+ p += strlen(p);
+ t = NULL;
+ break;
+ case TYK_CLASS:
+ sprintf(p, "/%s/", t->name);
+ p += strlen(p);
+ t = NULL;
+ break;
+ case TYK_ENUM:
+ sprintf(p, "'%s'", t->name);
+ p += strlen(p);
+ t = NULL;
+ break;
+ case TYK_FUNCTION:
+ sprintf(p, "(pfn)", t->name);
+ p += strlen(p);
+ t = NULL;
+ break;
+
+ default:
+ LexError("TypeStructure: Unknown type kind %d\n", t->kind);
+ break;
+ }
+ }
+ *p = 0;
+}
+
+void sGenType(Type *t, int generic)
+{
+ char s[80];
+
+ TypeStructure(t, s);
+ sGenToThops(s, generic);
+}
+
+static int NoParams(Member *params)
+{
+ if (params == NULL ||
+ (params->type && params->type->name &&
+ (!strcmp(params->type->name, "void") ||
+ !strcmp(params->type->name, "VOID"))))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+Member *sGenParamList(Member *params, int generic, int number)
+{
+ if (!NoParams(params))
+ {
+ while (params && number != 0)
+ {
+ sGenType(params->type, generic);
+ params = params->next;
+ SecOut(", ");
+ if (number > 0)
+ number--;
+ }
+ }
+ return params;
+}
+
+int method_count;
+
+void sStartRoutine(char *class, Member *routine)
+{
+ needs_review = FALSE;
+
+ if (class == NULL)
+ {
+ Section(API_THOPS_SECTION);
+ }
+ else
+ {
+ Section(IFACE_THOP_TABLE_SECTION);
+ /* method_count has already been incremented */
+ if (method_count > FIRST_METHOD)
+ SecOut(",");
+ SecOut(" thops%s_%s\n", class, routine->name);
+ Section(IFACE_THOP_TABLE_SECTION);
+ Section(IFACE_THOPS_SECTION);
+ }
+
+ SecOut("THOP CONST thops");
+ if (class)
+ SecOut("%s_", class);
+ SecOut("%s[] =\n{\n ", routine->name);
+
+ if (routine->type &&
+ (routine->type->name == NULL ||
+ (strcmp(routine->type->name, "HRESULT") != 0 &&
+ strcmp(routine->type->name, "void") != 0)))
+ {
+ SecOut("THOP_RETURNTYPE, ");
+ sGenType(routine->type, TRUE);
+ SecOut(", ");
+ }
+}
+
+void sEndRoutine(char *class, Member *routine,
+ RoutineSignature *sig)
+{
+ SecOut("THOP_END");
+ SecOut(", THOP_ROUTINEINDEX, %d", sig->index[INDEX_TYPE_GLOBAL]);
+ SecOut("\n};\n");
+
+ if (class == NULL)
+ Section(API_THOPS_SECTION);
+ else
+ Section(IFACE_THOPS_SECTION);
+
+ if (needs_review)
+ SecOut("/* ** BUGBUG - REVIEW ** */\n");
+}
+
+static void StructureDesc(char *str, ParamDesc *desc)
+{
+ int i;
+
+ for (i = 0; i < TO_THOPS; i++)
+ {
+ if (EqStructure(str, to_thops[i].structure))
+ {
+ *desc = to_thops[i].desc;
+ return;
+ }
+ }
+
+ LexError("<BUGBUG - No match for '%s'\n", str);
+}
+
+static void MemberDesc(Member *m, ParamDesc *desc)
+{
+ char str[80];
+
+ TypeStructure(m->type, str);
+ StructureDesc(str, desc);
+}
+
+static int max_params = 0;
+
+static RoutineSignature *sig_types = NULL;
+static int sig_index = 0;
+static RoutineSignature *sig_ord_types[MAX_METHODS];
+static int sig_ord_index = 0;
+static RoutineSignature *sig_uaglobal_types = NULL;
+static int sig_uaglobal_index = 0;
+static RoutineSignature *per_class_sigs;
+static int per_class_index = 0;
+
+static int method_ua_index[MAX_METHODS];
+
+static void ComputeSignature(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ int i;
+ Member *p;
+
+ i = 0;
+ if (class != NULL)
+ {
+ /* Account for this pointer */
+ StructureDesc("*<void>", &sig->params[i++]);
+ }
+
+ if (!NoParams(params))
+ {
+ for (p = params; p; p = p->next)
+ {
+ MemberDesc(p, &sig->params[i++]);
+ if (sig->params[i-1].size == 0)
+ {
+ LexError("param %d in %s:%s is zero\n", i, class,
+ routine->name);
+ }
+
+ if (i > MAX_PARAMS)
+ {
+ LexError("Too many parameters %d\n", i);
+ exit(1);
+ }
+ }
+ }
+
+ if (i > max_params)
+ max_params = i;
+ sig->nparams = i;
+}
+
+static int SignaturesMatch(RoutineSignature *a, RoutineSignature *b)
+{
+ int i;
+
+ if (a->nparams == b->nparams)
+ {
+ for (i = 0; i < a->nparams; i++)
+ {
+ if (a->params[i].flags != b->params[i].flags ||
+ a->params[i].size != b->params[i].size)
+ {
+ break;
+ }
+ }
+
+ if (i == a->nparams)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static RoutineSignature *RememberSignature(RoutineSignature *sig,
+ RoutineSignature **list,
+ int *index_base,
+ int index_type,
+ int n)
+{
+ RoutineSignature *s;
+
+ for (s = *list; s; s = s->next)
+ if (SignaturesMatch(sig, s) && --n == 0)
+ break;
+
+ if (s == NULL)
+ {
+ sig->index[index_type] = (*index_base)++;
+ s = (RoutineSignature *)PanicMalloc(sizeof(RoutineSignature));
+ *s = *sig;
+ s->next = *list;
+ *list = s;
+ }
+ else
+ {
+ sig->index[index_type] = s->index[index_type];
+ }
+ return s;
+}
+
+void sGenRoutine(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ int i;
+ RoutineSignature *s;
+
+ ComputeSignature(class, routine, params, sig);
+ RememberSignature(sig, &sig_types, &sig_index, INDEX_TYPE_GLOBAL, 1);
+
+ if (class != NULL)
+ {
+ /* method_count has already been incremented so subtract one here */
+ RememberSignature(sig, &sig_ord_types[method_count-1], &sig_ord_index,
+ INDEX_TYPE_SIGORD, 1);
+
+ /* Ignore QueryInterface, AddRef and Release */
+ if (method_count > STD_METHODS)
+ {
+ per_class_index = 0;
+ s = RememberSignature(sig, &per_class_sigs, &per_class_index,
+ INDEX_TYPE_PER_CLASS, 1);
+ s->index[INDEX_TYPE_PER_CLASS]++;
+
+ /* Look up a signature in the unambiguous global list which has
+ a matching ambiguity count */
+ s = RememberSignature(sig, &sig_uaglobal_types,
+ &sig_uaglobal_index,
+ INDEX_TYPE_UAGLOBAL,
+ s->index[INDEX_TYPE_PER_CLASS]);
+ method_ua_index[method_count-1] = s->index[INDEX_TYPE_UAGLOBAL];
+ }
+ }
+
+ for (i = 0; i < SpecialCaseCount(); i++)
+ {
+ if (class == NULL || special_cases[i].class == NULL)
+ {
+ if (class != special_cases[i].class)
+ continue;
+ }
+ else if (!EqStructure(class, special_cases[i].class))
+ {
+ continue;
+ }
+
+ if (!EqStructure(routine->name, special_cases[i].routine))
+ continue;
+
+ special_cases[i].fn(class, routine, params, sig);
+ break;
+ }
+
+ if (i == SpecialCaseCount())
+ {
+ sStartRoutine(class, routine);
+ sGenParamList(params, TRUE, GEN_ALL);
+ sEndRoutine(class, routine, sig);
+ }
+}
+
+int not_thunked;
+
+static char *names_not_thunked[] =
+{
+ "IMalloc",
+ "DllCanUnloadNow",
+ "PropagateResult",
+ "CoGetMalloc",
+ "CoGetCurrentProcess",
+ "CoBuildVersion",
+ "CoMarshalHresult",
+ "CoUnmarshalHresult",
+ "IsEqualGUID",
+ "StringFromCLSID",
+ "StringFromIID",
+ "IIDFromString",
+ "StringFromGUID2",
+ "OleGetMalloc",
+ "OleBuildVersion",
+ "CoCreateStandardMalloc",
+ "CoLoadLibrary",
+ "CoFreeLibrary",
+ "ReleaseStgMedium",
+ "OleGetIconOfFile",
+ "OleGetIconOfClass",
+ "OleMetafilePictFromIconAndLabel",
+ "GetHGlobalFromILockBytes",
+ "CreateILockBytesOnHGlobal",
+ "GetHGlobalFromStream",
+ "CreateStreamOnHGlobal",
+ "OleDuplicateData",
+ "OleTranslateAccelerator",
+ "IsAccelerator",
+ "CoGetState",
+ "CoSetState"
+};
+#define NNOT_THUNKED (sizeof(names_not_thunked)/sizeof(names_not_thunked[0]))
+
+static int NotThunked(char *class)
+{
+ int i;
+
+ for (i = 0; i < NNOT_THUNKED; i++)
+ if (!strcmp(names_not_thunked[i], class))
+ return TRUE;
+ return FALSE;
+}
+
+int api_index = 0;
+
+void GenApi(Member *api, Member *params)
+{
+ RoutineSignature sig;
+
+ if (!NotThunked(api->name))
+ {
+ tGenMember(NULL, api);
+ tGenParamList(params);
+
+ Section(API_THOP_TABLE_SECTION);
+ if (api_index > 0)
+ SecOut(",");
+ SecOut(" thops%s\n", api->name);
+ Section(API_THOP_TABLE_SECTION);
+
+ Section(API_VTBL_SECTION);
+ if (api_index > 0)
+ SecOut(",");
+
+ /* Special case for some calls because the thunking
+ code needs special initialization */
+ if (!strcmp(api->name, "CoInitialize") ||
+ !strcmp(api->name, "OleInitialize") ||
+ !strcmp(api->name, "CoRegisterClassObject") ||
+ !strcmp(api->name, "CoRevokeClassObject") ||
+ !strcmp(api->name, "OleRegGetUserType") )
+ {
+ SecOut(" (VTBLFN)%sNot\n", api->name);
+ }
+ else if (!strcmp(api->name, "DllGetClassObject"))
+ {
+ SecOut(" (VTBLFN)%sWOW\n", api->name);
+ }
+ else
+ {
+ SecOut(" (VTBLFN)%s\n", api->name);
+ }
+ Section(API_VTBL_SECTION);
+
+ Section(API_DEBUG_SECTION);
+ if (api_index > 0)
+ SecOut(",");
+ SecOut(" \"%s\"\n", api->name);
+ Section(API_DEBUG_SECTION);
+
+ Section(API_LIST_SECTION);
+ SecOut("#define THK_API_%s %d\n", api->name, api_index++);
+ Section(API_LIST_SECTION);
+
+ sGenRoutine(NULL, api, params, &sig);
+ }
+
+ FreeMember(api);
+ FreeMemberList(params);
+}
+
+void GenMethod(char *class, Member *method, Member *params)
+{
+ char str[80];
+ RoutineSignature sig;
+
+ method_count++;
+ if (method_count > MAX_METHODS)
+ {
+ LexError("Too many methods on %s, %d\n", class, method_count);
+ exit(1);
+ }
+
+ sprintf(str, "%s::", class);
+
+ tGenMember(str, method);
+ tGenParamList(params);
+
+ sGenRoutine(class, method, params, &sig);
+
+ if (!not_thunked)
+ {
+ Section(VTABLE_SECTION);
+ if (method_count > 1)
+ SecOut(",");
+
+ /* QueryInterface, AddRef and Release are handled specially */
+ if (!strcmp(method->name, "QueryInterface") ||
+ !strcmp(method->name, "AddRef") ||
+ !strcmp(method->name, "Release"))
+ {
+ SecOut(" (THUNK3216FN)%sProxy3216\n", method->name);
+ }
+ else
+ {
+ SecOut(" (THUNK3216FN)ThunkMethod3216_%d\n",
+ sig.index[INDEX_TYPE_UAGLOBAL]);
+ }
+ Section(VTABLE_SECTION);
+
+ Section(IFACE_DEBUG_SECTION);
+ if (method_count > 1)
+ SecOut(",");
+ SecOut(" \"%s\"\n", method->name);
+ Section(IFACE_DEBUG_SECTION);
+ }
+
+ FreeMember(method);
+ FreeMemberList(params);
+}
+
+static int interface_index = 0;
+static int max_methods = 0;
+static int total_methods = 0;
+
+void StartClass(char *class)
+{
+ not_thunked = NotThunked(class);
+ if (not_thunked)
+ {
+ Section(THI_SECTION);
+ /* Unthunked but present interfaces are given an index
+ of THI_COUNT to guarantee that they're not valid yet
+ still keep a consecutive index set */
+ SecOut("#define THI_%s THI_COUNT\n", class);
+ Section(THI_SECTION);
+ }
+ else
+ {
+ Section(THI_SECTION);
+ SecOut("#define THI_%s %d\n", class, interface_index++);
+ Section(THI_SECTION);
+
+ Section(IID_TO_THI_SECTION);
+ if (interface_index > 1)
+ SecOut(",");
+ SecOut(" &IID_%s, THI_%s\n", class, class);
+ Section(IID_TO_THI_SECTION);
+
+ Section(VTABLE_SECTION);
+ SecOut("THUNK3216FN CONST tfn%s[] =\n", class);
+ SecOut("{\n");
+ Section(VTABLE_SECTION);
+
+ Section(IFACE_DEBUG_SECTION);
+ SecOut("char *apsz%sNames[] =\n", class);
+ SecOut("{\n");
+ Section(IFACE_DEBUG_SECTION);
+
+ Section(IFACE_THOP_TABLE_SECTION);
+ SecOut("THOP CONST * CONST apthops%s[] =\n", class);
+ SecOut("{\n");
+ Section(IFACE_THOP_TABLE_SECTION);
+ }
+
+ method_count = 0;
+ per_class_sigs = NULL;
+
+ memset(method_ua_index, 0xff, sizeof(method_ua_index));
+}
+
+void EndClass(char *class)
+{
+ RoutineSignature *s;
+ int i, j;
+
+ if (!not_thunked)
+ {
+ Section(VTABLE_SECTION);
+ SecOut("};\n");
+ Section(VTABLE_SECTION);
+
+ Section(IFACE_DEBUG_SECTION);
+ SecOut("};\n");
+ Section(IFACE_DEBUG_SECTION);
+
+ Section(IFACE_DEBUG_TABLE_SECTION);
+ if (interface_index > 1)
+ SecOut(",");
+ SecOut(" \"%s\", apsz%sNames\n", class, class);
+ Section(IFACE_DEBUG_TABLE_SECTION);
+
+ Section(IFACE_THOP_TABLE_SECTION);
+ if (method_count <= STD_METHODS)
+ {
+ SecOut(" NULL\n");
+ }
+ SecOut("};\n");
+ Section(IFACE_THOP_TABLE_SECTION);
+
+ Section(THOPI_SECTION);
+ if (interface_index > 1)
+ SecOut(",");
+ SecOut(" apthops%s", class);
+ SecOut(", %d, tfn%s, ", method_count, class);
+ if (method_count > STD_METHODS)
+ SecOut("ftm%s\n", class);
+ else
+ SecOut("NULL\n");
+ Section(THOPI_SECTION);
+
+ if (method_count > STD_METHODS)
+ {
+ Section(IFACE_3216_FN_TO_METHOD_SECTION);
+ SecOut("BYTE CONST ftm%s[] =\n", class);
+ SecOut("{\n");
+ for (i = 0; i < sig_uaglobal_index; i++)
+ {
+ for (j = 0; j < MAX_METHODS; j++)
+ if (method_ua_index[j] == i)
+ break;
+
+ if (j == MAX_METHODS)
+ j = 0;
+
+ if (i > 0)
+ SecOut(",\n");
+ SecOut(" %d", j);
+ }
+ SecOut("\n};\n");
+ Section(IFACE_3216_FN_TO_METHOD_SECTION);
+ }
+
+ if (method_count > max_methods)
+ max_methods = method_count;
+
+ total_methods += method_count;
+ }
+
+ while (per_class_sigs)
+ {
+ s = per_class_sigs->next;
+ free(per_class_sigs);
+ per_class_sigs = s;
+ }
+}
+
+static void CairoFilePrologue(char *fn, char *gen, int is_cxx)
+{
+ SecOut("//+-------------------------------------------------------"
+ "--------------------\n");
+ SecOut("//\n");
+ SecOut("// Microsoft Windows\n");
+ SecOut("// Copyright (C) Microsoft Corporation, 1992 - 1994.\n");
+ SecOut("//\n");
+ SecOut("// File:\t%s\n", fn);
+ SecOut("//\n");
+ SecOut("// Notes: This file is automatically generated\n");
+ SecOut("//\t\tDo not modify by hand\n");
+ SecOut("//\n");
+ //SecOut("// History:\t%s\tGenerated\n", gen);
+ SecOut("// History:\tFri May 27 10:39:02 1994\tGenerated\n", gen);
+ SecOut("//\n");
+ SecOut("//--------------------------------------------------------"
+ "--------------------\n");
+ SecOut("\n");
+
+ if (is_cxx)
+ {
+ SecOut("#include <headers.cxx>\n");
+ SecOut("#pragma hdrstop\n");
+ SecOut("\n");
+ }
+}
+
+void StartGen(void)
+{
+ int i;
+ char tms[80];
+ time_t tm;
+
+ tm = time(NULL);
+ strcpy(tms, ctime(&tm));
+ tms[strlen(tms)-1] = 0;
+ for (i = 0; i < NSECTIONS; i++)
+ {
+ OpenSection(i);
+ Section(i);
+ CairoFilePrologue(sections[i].file, tms, sections[i].is_cxx);
+ Section(i);
+ }
+
+ Section(THOPI_SECTION);
+ SecOut("#include \"%s\"\n", sections[IFACE_THOPS_SECTION].file);
+ SecOut("#include \"%s\"\n", sections[IFACE_THOP_TABLE_SECTION].file);
+ SecOut("#include \"%s\"\n", sections[VTABLE_IMP_SECTION].file);
+ SecOut("#include \"%s\"\n", sections[VTABLE_SECTION].file);
+ SecOut("#include \"%s\"\n",
+ sections[IFACE_3216_FN_TO_METHOD_SECTION].file);
+ SecOut("\n");
+ SecOut("THOPI CONST athopiInterfaceThopis[] =\n");
+ SecOut("{\n");
+ Section(THOPI_SECTION);
+
+ Section(API_THOP_TABLE_SECTION);
+ SecOut("#include \"%s\"\n", sections[API_THOPS_SECTION].file);
+ SecOut("\n");
+ SecOut("THOP CONST * CONST apthopsApiThops[] =\n");
+ SecOut("{\n");
+ Section(API_THOP_TABLE_SECTION);
+
+ Section(API_VTBL_SECTION);
+ SecOut("VTBLFN CONST apfnApiFunctions[] =\n");
+ SecOut("{\n");
+ Section(API_VTBL_SECTION);
+
+ Section(IID_TO_THI_SECTION);
+ SecOut("#include <coguid.h>\n");
+ SecOut("#include <oleguid.h>\n");
+ SecOut("IIDTOTHI CONST aittIidToThi[] =\n");
+ SecOut("{\n");
+ Section(IID_TO_THI_SECTION);
+
+ Section(API_DEBUG_SECTION);
+ SecOut("#if DBG == 1\n\n");
+ SecOut("char *apszApiNames[] =\n");
+ SecOut("{\n");
+ Section(API_DEBUG_SECTION);
+
+ Section(IFACE_DEBUG_SECTION);
+ SecOut("#if DBG == 1\n\n");
+ Section(IFACE_DEBUG_SECTION);
+
+ Section(IFACE_DEBUG_TABLE_SECTION);
+ SecOut("#include \"%s\"\n", sections[IFACE_DEBUG_SECTION].file);
+ SecOut("#if DBG == 1\n\n");
+ SecOut("INTERFACENAMES inInterfaceNames[] =\n");
+ SecOut("{\n");
+ Section(IFACE_DEBUG_TABLE_SECTION);
+}
+
+typedef struct _FullParamSizeInfo
+{
+ char *scalar_type, *struct_type;
+ int byte4_size;
+} FullParamSizeInfo;
+
+typedef struct _ParamSizeInfo
+{
+ char *type;
+ int byte4_size;
+} ParamSizeInfo;
+
+static FullParamSizeInfo arg_type_conv[] =
+{
+ NULL, NULL, 0,
+ "BYTE", NULL, 4,
+ "WORD", NULL, 4,
+ NULL, NULL, 0,
+ "DWORD", NULL, 4,
+ NULL, NULL, 0,
+ NULL, NULL, 0,
+ NULL, NULL, 0,
+ "ULARGE_INTEGER", "SIZEL", 8
+};
+#define ARG_TYPE_CONVS (sizeof(arg_type_conv)/sizeof(arg_type_conv[0]))
+
+static ParamSizeInfo *GetParamSizeInfo(ParamDesc *desc)
+{
+ static ParamSizeInfo info;
+ FullParamSizeInfo *finfo;
+
+ if (desc->size < 0 || desc->size >= ARG_TYPE_CONVS)
+ {
+ LexError("Invalid parameter description\n");
+ exit(1);
+ }
+
+ finfo = &arg_type_conv[desc->size];
+ if (finfo->byte4_size == 0)
+ {
+ LexError("Parameter description has unhandled size\n");
+ exit(1);
+ }
+
+ info.byte4_size = finfo->byte4_size;
+ if (desc->flags & SIGF_SCALAR)
+ {
+ info.type = finfo->scalar_type;
+ }
+ else
+ {
+ info.type = finfo->struct_type;
+ }
+ return &info;
+}
+
+static char *AlignmentPrefix(ParamDesc *desc)
+{
+ if(desc->flags & SIGF_UNALIGNED)
+ return "UNALIGNED";
+ else
+ return "";
+}
+
+void EndGen(void)
+{
+ RoutineSignature *s;
+ int i, j, sc, dws, dwi;
+ ParamSizeInfo *sinfo;
+
+ printf("APIs = %d\n", api_index);
+ printf("Interfaces = %d\n", interface_index);
+ printf("Methods = %d\n", total_methods);
+ printf("Maximum number of methods on an interface = %d\n", max_methods);
+ printf("Maximum number of parameters in a signature = %d\n", max_params);
+ printf("Distinct signatures = %d\n", sig_index);
+ printf("Distinct signature-ordinal pairs = %d\n", sig_ord_index);
+ printf("Per-class unambiguous signatures = %d\n", sig_uaglobal_index);
+
+ sc = 0;
+#ifdef SHOW_SIGNATURES
+ printf("\nSignatures:\n");
+ for (s = sig_types; s; s = s->next)
+ {
+ printf("%d params:", s->nparams);
+ for (i = 0; i < s->nparams; i++)
+ {
+ printf(" %X:%d", s->params[i].flags, s->params[i].size);
+ }
+ putchar('\n');
+ sc++;
+ }
+#endif
+
+ Section(THOPI_SECTION);
+ SecOut("};\n");
+ Section(THOPI_SECTION);
+
+ Section(API_THOP_TABLE_SECTION);
+ SecOut("};\n");
+ Section(API_THOP_TABLE_SECTION);
+
+ Section(API_VTBL_SECTION);
+ SecOut("};\n");
+ Section(API_VTBL_SECTION);
+
+ Section(API_LIST_SECTION);
+ SecOut("#define THK_API_COUNT %d\n", api_index);
+ Section(API_LIST_SECTION);
+
+ Section(THI_SECTION);
+ SecOut("#define THI_COUNT %d\n", interface_index);
+ Section(THI_SECTION);
+
+ Section(IID_TO_THI_SECTION);
+ SecOut("};\n");
+ Section(IID_TO_THI_SECTION);
+
+ Section(API_DEBUG_SECTION);
+ SecOut("};\n");
+ SecOut("\n#endif // DBG\n");
+ Section(API_DEBUG_SECTION);
+
+ Section(IFACE_DEBUG_SECTION);
+ SecOut("\n#endif // DBG\n");
+ Section(IFACE_DEBUG_SECTION);
+
+ Section(IFACE_DEBUG_TABLE_SECTION);
+ SecOut("};\n");
+ SecOut("\n#endif // DBG\n");
+ Section(IFACE_DEBUG_TABLE_SECTION);
+
+ Section(VTABLE_IMP_SECTION);
+
+#ifdef STD_METHOD_IMPL
+ SecOut("DWORD ThunkQueryInterface3216(THUNK3216OBJ *pto,\n");
+ SecOut(" DWORD dwArg1,\n");
+ SecOut(" DWORD dwArg2)\n");
+ SecOut("{\n");
+ SecOut(" DWORD dwStack32[3];\n");
+ SecOut(" dwStack32[0] = (DWORD)pto;\n");
+ SecOut(" dwStack32[1] = dwArg1;\n");
+ SecOut(" dwStack32[2] = dwArg2;\n");
+ SecOut(" return InvokeOn16(pto->oid, 0, dwStack32);\n");
+ SecOut("}\n");
+
+ SecOut("DWORD ThunkAddRef3216(THUNK3216OBJ *pto)\n");
+ SecOut("{\n");
+ SecOut(" DWORD dwStack32[1];\n");
+ SecOut(" InterlockedIncrement(&pto->cReferences);\n");
+ SecOut(" dwStack32[0] = (DWORD)pto;\n");
+ SecOut(" return InvokeOn16(pto->oid, 1, dwStack32);\n");
+ SecOut("}\n");
+
+ SecOut("DWORD ThunkRelease3216(THUNK3216OBJ *pto)\n");
+ SecOut("{\n");
+ SecOut(" LONG lRet;\n");
+ SecOut(" DWORD dwResult;\n");
+ SecOut(" DWORD dwStack32[1];\n");
+ SecOut(" lRet = InterlockedDecrement(&pto->cReferences);\n");
+ SecOut(" dwStack32[0] = (DWORD)pto;\n");
+ SecOut(" dwResult = InvokeOn16(pto->oid, 2, dwStack32);\n");
+ SecOut(" if (lRet == 0)\n");
+ SecOut(" DestroyProxy3216(pto);\n");
+ SecOut(" return dwResult;\n");
+ SecOut("}\n");
+#endif
+
+#ifdef SIGORD_METHODS
+ for (i = 0; i < MAX_METHODS; i++)
+ {
+ for (s = sig_ord_types[i]; s; s = s->next)
+ {
+ SecOut("DWORD ThunkMethod3216_%d(\n", s->index[INDEX_TYPE_SIGORD]);
+
+ /* We know that these are all methods so we can always declare
+ the this pointer */
+ SecOut(" THUNK3216OBJ *ptoThis32");
+ dws = sizeof(unsigned long);
+ if (s->nparams > 1)
+ {
+ for (j = 1; j < s->nparams; j++)
+ {
+ sinfo = GetParamSizeInfo(&s->params[j]);
+
+ SecOut(",\n %s Arg%d", sinfo->type, j);
+ dws += sinfo->byte4_size;
+ }
+ }
+ SecOut("\n )\n");
+
+ SecOut("{\n");
+ SecOut(" BYTE bArgs[%d];\n", dws);
+
+ /* Put this pointer on stack */
+ SecOut(" *(VPVOID *)bArgs = (DWORD)ptoThis32;\n");
+ dwi = sizeof(unsigned long);
+
+ for (j = 1; j < s->nparams; j++)
+ {
+ sinfo = GetParamSizeInfo(&s->params[j]);
+
+ SecOut(" *(%s %s *)(bArgs+%d) = Arg%d;\n",
+ sinfo->type,
+ AlignmentPrefix(&s->params[j]),
+ dwi,
+ j);
+ dwi += sinfo->byte4_size;
+ }
+
+ SecOut(" return InvokeOn16(ptoThis32->oid, %d, bArgs);\n", i);
+ SecOut("}\n");
+ }
+ }
+#else
+ for (s = sig_uaglobal_types; s; s = s->next)
+ {
+ SecOut("DWORD ThunkMethod3216_%d(\n", s->index[INDEX_TYPE_UAGLOBAL]);
+
+ /* We know that these are all methods so we can always declare
+ the this pointer */
+ SecOut(" THUNK3216OBJ *ptoThis32");
+ dws = sizeof(unsigned long);
+ if (s->nparams > 1)
+ {
+ for (j = 1; j < s->nparams; j++)
+ {
+ sinfo = GetParamSizeInfo(&s->params[j]);
+
+ SecOut(",\n %s Arg%d", sinfo->type, j);
+ dws += sinfo->byte4_size;
+ }
+ }
+ SecOut("\n )\n");
+
+ SecOut("{\n");
+ SecOut(" DWORD dwMethod;\n");
+ SecOut(" BYTE bArgs[%d];\n", dws);
+
+ /* Put this pointer on stack */
+ SecOut(" *(VPVOID *)bArgs = (DWORD)ptoThis32;\n");
+ dwi = sizeof(unsigned long);
+
+ for (j = 1; j < s->nparams; j++)
+ {
+ sinfo = GetParamSizeInfo(&s->params[j]);
+
+ SecOut(" *(%s %s *)(bArgs+%d) = Arg%d;\n",
+ sinfo->type,
+ AlignmentPrefix(&s->params[j]),
+ dwi,
+ j);
+ dwi += sinfo->byte4_size;
+ }
+
+ SecOut(" dwMethod = athopiInterfaceThopis[IIDIDX_INDEX(ptoThis32->iidx)]."
+ "pftm[%d];\n", s->index[INDEX_TYPE_UAGLOBAL]);
+ SecOut(" return InvokeOn16(IIDIDX_INDEX(ptoThis32->iidx), "
+ "dwMethod, bArgs);\n");
+ SecOut("}\n");
+ }
+#endif
+ Section(VTABLE_IMP_SECTION);
+
+ Section(SWITCH_SECTION);
+ SecOut("DWORD ThunkCall1632(THUNKINFO *pti)\n");
+ SecOut("{\n");
+ SecOut(" DWORD dwReturn;\n");
+ SecOut(" thkAssert(pti->pvfn != NULL);\n");
+ SecOut(" thkAssert(*pti->pThop == THOP_END);\n");
+ SecOut(" pti->pThop++;\n");
+ SecOut(" thkAssert(*pti->pThop == THOP_ROUTINEINDEX);\n");
+ SecOut(" pti->pThop++;\n");
+ SecOut(" if (FAILED(pti->scResult))\n");
+ SecOut(" {\n");
+ SecOut(" return (DWORD)pti->scResult;\n");
+ SecOut(" }\n");
+ SecOut(" pti->pThkMgr->SetThkState(THKSTATE_NOCALL);\n");
+ SecOut(" switch(*pti->pThop)\n");
+ SecOut(" {\n");
+
+ for (i = 0; i < sig_index; i++)
+ {
+ for (s = sig_types; s; s = s->next)
+ if (s->index[INDEX_TYPE_GLOBAL] == i)
+ break;
+
+ SecOut(" case %d:\n", i);
+ SecOut(" dwReturn = (*(DWORD (__stdcall *)(");
+
+ for (j = 0; j < s->nparams; j++)
+ {
+ sinfo = GetParamSizeInfo(&s->params[j]);
+
+ SecOut("\n %s", sinfo->type);
+ if (j < s->nparams-1)
+ {
+ SecOut(",");
+ }
+ }
+
+ SecOut("))pti->pvfn)(\n");
+
+ dwi = 0;
+ for (j = 0; j < s->nparams; j++)
+ {
+ sinfo = GetParamSizeInfo(&s->params[j]);
+
+ SecOut(" *(%s %s *)(pti->s32.pbStart+%d)",
+ sinfo->type,
+ AlignmentPrefix(&s->params[j]),
+ dwi);
+ if (j < s->nparams-1)
+ {
+ SecOut(",\n");
+ }
+ else
+ {
+ SecOut("\n");
+ }
+ dwi += sinfo->byte4_size;
+ }
+ SecOut(" );\n");
+ SecOut(" break;\n");
+ }
+ SecOut(" }\n");
+
+ SecOut("#if DBG == 1\n");
+ SecOut(" if ( !pti->fResultThunked && FAILED(dwReturn) )\n");
+ SecOut(" {\n");
+ SecOut(" thkDebugOut((DEB_FAILURES,\n");
+ SecOut(" \"ThunkCall1632 pvfn = %%08lX "
+ "Probably failed hr = %%08lX\\n\",\n");
+ SecOut(" pti->pvfn, dwReturn));\n");
+ SecOut(" }\n");
+ SecOut("#endif\n");
+
+ SecOut(" pti->pThkMgr->SetThkState(THKSTATE_INVOKETHKOUT32);\n");
+ SecOut(" return dwReturn;\n");
+ SecOut("}\n");
+ Section(SWITCH_SECTION);
+
+ for (i = 0; i < NSECTIONS; i++)
+ {
+ CloseSection(i);
+ }
+}
diff --git a/private/ole32/olethunk/thc/thc/gen.h b/private/ole32/olethunk/thc/thc/gen.h
new file mode 100644
index 000000000..7bb0ca485
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/gen.h
@@ -0,0 +1,86 @@
+#ifndef __GEN_H__
+#define __GEN_H__
+
+#define MAX_PARAMS 15
+#define MAX_METHODS 32
+
+#define INDEX_TYPE_GLOBAL 0
+#define INDEX_TYPE_SIGORD 1
+#define INDEX_TYPE_UAGLOBAL 2
+#define INDEX_TYPE_PER_CLASS 3
+#define INDEX_TYPE_COUNT 4
+
+#define SIGF_NONE 0
+#define SIGF_SCALAR 1
+#define SIGF_UNALIGNED 2
+
+typedef struct _ParamDesc
+{
+ int flags;
+ size_t size;
+} ParamDesc;
+
+typedef struct _RoutineSignature
+{
+ int nparams;
+ ParamDesc params[MAX_PARAMS];
+ struct _RoutineSignature *next;
+ int index[INDEX_TYPE_COUNT];
+} RoutineSignature;
+
+void StartGen(void);
+void EndGen(void);
+
+void GenApi(Member *api, Member *params);
+void GenMethod(char *class, Member *method, Member *params);
+void StartClass(char *class);
+void EndClass(char *class);
+
+#define GEN_ALL (-1)
+
+void sStartRoutine(char *class, Member *routine);
+void sEndRoutine(char *class, Member *routine,
+ RoutineSignature *sig);
+Member *sGenParamList(Member *params, int generic, int number);
+void sGenType(Type *t, int generic);
+
+#define THOPI_SECTION 0
+#define IFACE_THOPS_SECTION 1
+#define IFACE_THOP_TABLE_SECTION 2
+#define VTABLE_SECTION 3
+#define VTABLE_IMP_SECTION 4
+#define IFACE_3216_FN_TO_METHOD_SECTION 5
+#define SWITCH_SECTION 6
+#define THI_SECTION 7
+#define API_LIST_SECTION 8
+#define API_THOP_TABLE_SECTION 9
+#define API_THOPS_SECTION 10
+#define API_VTBL_SECTION 11
+#define IID_TO_THI_SECTION 12
+#define ENUM_INDEX_SECTION 13
+#define API_DEBUG_SECTION 14
+#define IFACE_DEBUG_SECTION 15
+#define IFACE_DEBUG_TABLE_SECTION 16
+#define NSECTIONS 17
+
+void Section(int sec);
+void SecOut(char *fmt, ...);
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+extern int not_thunked;
+
+/* Count of methods present on all interfaces, currently the set from
+ IUnknown */
+#define STD_METHODS 3
+
+#ifdef THUNK_IUNKNOWN
+#define FIRST_METHOD 1
+#else
+#define FIRST_METHOD (STD_METHODS+1)
+#endif
+
+#endif
diff --git a/private/ole32/olethunk/thc/thc/grammar.y b/private/ole32/olethunk/thc/thc/grammar.y
new file mode 100644
index 000000000..b6d99121b
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/grammar.y
@@ -0,0 +1,338 @@
+%{
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <malloc.h>
+
+#include "main.h"
+#include "type.h"
+#include "op.h"
+#include "gen.h"
+
+#define yyerror LexError
+
+extern FILE *yyin;
+
+int yylex(void);
+
+char *cur_class;
+char *GetCurrentClass(void)
+{
+ return cur_class;
+}
+
+void SetCurrentClass(char *name)
+{
+ cur_class = name;
+}
+%}
+
+%union
+{
+ char *text;
+ Type *ty;
+ int i;
+ Member *member;
+};
+
+%Token TkCdecl
+%token TkChar
+%token TkClass
+%token TkConst
+%token TkEllipsis
+%token TkEnum
+%token TkExport
+%token TkExtern
+%token TkHuge
+%token TkId
+%token TkIn
+%token TkInt
+%token TkLeftShift
+%token TkOut
+%token TkPascal
+%token TkPrivate
+%token TkPublic
+%token TkRegister
+%token TkSigned
+%token TkSizeof
+%token TkStdcall
+%token TkString
+%token TkStruct
+%token TkTypedef
+%token TkUnion
+%token TkUnsigned
+%token TkVirtual
+%token TkVoid
+%token TkVolatile
+
+%type <text> TkChar TkId TkString
+
+%type <ty> decl type_name qualifier qualifier_list
+%type <ty> aggregate_specifier enum_specifier
+
+%type <i> TkInt aggregate constant_expr prefix_operator binary_operator
+
+%type <member> decl_follower
+%type <member> member member_list member_id_list typedef_id_list
+%type <member> parameter_list parameters parameter
+
+%%
+
+file:
+ item_list
+ |
+;
+
+item_list:
+ item
+ | item_list item
+;
+
+item:
+ declaration
+;
+
+declaration:
+ typedef_specifier
+ | api_specifier
+ | class_specifier
+ | ';'
+;
+
+typedef_specifier:
+ TkTypedef decl typedef_id_list ';'
+ { Typedef($3, $2); }
+;
+
+api_specifier:
+ TkExtern api_body
+;
+
+api_body:
+ decl decl_follower parameter_list ';'
+ { GenApi(ApplyMemberType($2, $1), $3); }
+;
+
+type_name:
+ TkId
+ { $$ = FindTypeErr($1); free($1); }
+ | TkVoid
+ { $$ = FindType("void"); }
+;
+
+decl:
+ qualifier_list type_name
+ { $$ = ApplyQualifiers($1, $2); }
+ | type_name
+ { $$ = $1; }
+ | aggregate_specifier
+ { $$ = $1; }
+ | enum_specifier
+ { $$ = $1; }
+;
+
+qualifier_list:
+ qualifier
+ { $$ = $1; }
+ | qualifier_list qualifier
+ { $$ = ApplyQualifiers($1, $2); }
+;
+
+qualifier:
+ TkSigned
+ { $$ = NULL; }
+ | TkUnsigned
+ { $$ = NewQualifiedType(NULL, TYF_UNSIGNED, NULL); }
+ | TkConst
+ { $$ = NewQualifiedType(NULL, TYF_CONST, NULL); }
+ | TkIn
+ { $$ = NewQualifiedType(NULL, TYF_IN, NULL); }
+ | TkOut
+ { $$ = NewQualifiedType(NULL, TYF_OUT, NULL); }
+ | TkVolatile
+ { $$ = NULL; }
+ | TkStdcall
+ { $$ = NULL; }
+ | TkCdecl
+ { $$ = NULL; }
+ | TkExport
+ { $$ = NULL; }
+ | TkPascal
+ { $$ = NULL; }
+ | TkHuge
+ { $$ = NULL; }
+ | '*'
+ { $$ = NewPointerType(TYF_NONE, NULL); }
+;
+
+aggregate_specifier:
+ aggregate TkId '{' member_list '}'
+ { $$ = NewAggregateType($2, $4, $1); }
+ | aggregate '{' member_list '}'
+ { $$ = NewAggregateType(NULL, $3, $1); }
+ | aggregate TkId
+ {
+ Type *t;
+
+ t = FindType($2);
+ if (t == NULL)
+ {
+ t = NewAggregateType($2, NULL, $1);
+ }
+ else
+ {
+ if (t->kind != $1)
+ LexError("'%s' is not a %s",
+ $2, TypeKindNames[$1]);
+ free($2);
+ }
+ $$ = t;
+ }
+;
+
+aggregate:
+ TkStruct
+ { $$ = TYK_STRUCT; }
+ | TkUnion
+ { $$ = TYK_UNION; }
+ | TkClass
+ { $$ = TYK_CLASS; }
+;
+
+member_list:
+ member
+ { $$ = $1; }
+ | member_list member
+ { $$ = AppendMember($1, $2); }
+;
+
+member:
+ decl member_id_list ';'
+ { $$ = ApplyMemberType($2, $1); }
+;
+
+member_id_list:
+ decl_follower
+ { $$ = $1; }
+ | member_id_list ',' decl_follower
+ { $$ = AppendMember($1, $3); }
+;
+
+enum_specifier:
+ TkEnum TkId '{' enum_literal_list '}'
+ { $$ = NewEnumType($2); }
+ | TkEnum '{' enum_literal_list '}'
+ { $$ = NewEnumType(NULL); }
+;
+
+enum_literal_list:
+ literal
+ | literal ',' enum_literal_list
+ | literal ','
+;
+
+literal:
+ TkId
+ { free($1); }
+ | TkId '=' constant_expr
+ { free($1); }
+;
+
+decl_follower:
+ TkId
+ { $$ = NewMember($1, NULL); }
+ | qualifier_list TkId
+ { $$ = NewMember($2, $1); }
+ | '(' decl_follower ')' parameter_list
+ { $2->type = NewFunctionType(NULL); $$ = $2; }
+ | TkId '[' constant_expr ']'
+ { $$ = NewMember($1, NewArrayType(NULL, $3, NULL)); }
+;
+
+typedef_id_list:
+ decl_follower
+ { $$ = $1; }
+ | typedef_id_list ',' decl_follower
+ { $$ = AppendMember($1, $3); }
+;
+
+parameter_list:
+ '(' parameters ')'
+ { $$ = $2; }
+;
+
+parameters:
+ parameter
+ { $$ = $1; }
+ | parameters ',' parameter
+ { $$ = AppendMember($1, $3); }
+;
+
+parameter:
+ decl decl_follower
+ { $$ = ApplyMemberType($2, $1); }
+ | decl qualifier_list
+ { $$ = ApplyMemberType(NewMember(NULL, $2), $1); }
+ | decl
+ { $$ = NewMember(NULL, $1); }
+;
+
+constant_expr:
+ prefix_operator TkInt
+ { $$ = PrefixOp($1, $2); }
+ | TkInt binary_operator TkInt
+ { $$ = BinaryOp($1, $2, $3); }
+ | TkInt
+ { $$ = $1; }
+;
+
+prefix_operator:
+ '-'
+ { $$ = OP_UNARY_MINUS; }
+;
+
+binary_operator:
+ TkLeftShift
+ { $$ = OP_LEFT_SHIFT; }
+;
+
+class_specifier:
+ TkClass TkId
+ { SetCurrentClass($2);
+ AddType(NewClassType($2, NULL));
+ StartClass($2); }
+ inheritance '{' class_body '}' ';'
+ { EndClass($2); }
+;
+
+inheritance:
+ ':' inherit_list
+ |
+;
+
+inherit_list:
+ inherit
+ | inherit_list ',' inherit
+;
+
+inherit:
+ pub_or_priv TkId
+ { free($2); }
+;
+
+pub_or_priv:
+ TkPublic
+ | TkPrivate
+;
+
+class_body:
+ method
+ | class_body method
+;
+
+method:
+ TkVirtual decl decl_follower parameter_list '=' TkInt ';'
+ { GenMethod(GetCurrentClass(), ApplyMemberType($3, $2), $4); }
+;
+
+%%
diff --git a/private/ole32/olethunk/thc/thc/lexer.l b/private/ole32/olethunk/thc/thc/lexer.l
new file mode 100644
index 000000000..0d703b687
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/lexer.l
@@ -0,0 +1,104 @@
+%{
+//
+// undefine YY_CHAR and redefine it as char
+// (it is unsigned char for 8-bit scanners and the c++ compiler
+// does not let assignments from unsigned char to char EVEN with
+// the -J switch (WHICH MUST BE USED!).
+//
+#undef YY_CHAR
+#define YY_CHAR char
+
+#define yywrap() (1)
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define fileno _fileno
+
+#include "type.h"
+#include "main.h"
+#include "grammar.h"
+
+void SetFileFromDirective(char *dir)
+{
+ int ln;
+ char *s;
+
+ s = dir;
+ while (*s != ' ')
+ s++;
+ s++;
+ sscanf(s, "%d", &ln);
+ while (*s != ' ')
+ s++;
+ s++;
+
+ SetFile(ln-1, s);
+}
+%}
+
+%%
+
+"__cdecl" { return TkCdecl; }
+"_cdecl" { return TkCdecl; }
+"class" { return TkClass; }
+"const" { return TkConst; }
+"enum" { return TkEnum; }
+"__export" { return TkExport; }
+"extern" { return TkExtern; }
+"__huge" { return TkHuge; }
+"__in" { return TkIn; }
+"__out" { return TkOut; }
+"__pascal" { return TkPascal; }
+"private" { return TkPrivate; }
+"public" { return TkPublic; }
+"register" { return TkRegister; }
+"signed" { return TkSigned; }
+"sizeof" { return TkSizeof; }
+"__stdcall" { return TkStdcall; }
+"_stdcall" { return TkStdcall; }
+"struct" { return TkStruct; }
+"typedef" { return TkTypedef; }
+"union" { return TkUnion; }
+"unsigned" { return TkUnsigned; }
+"virtual" { return TkVirtual; }
+"void" { return TkVoid; }
+"volatile" { return TkVolatile; }
+
+[:{}(),;\[\]=*-] { return yytext[0]; }
+
+"<<" { return TkLeftShift; }
+
+"..." { return TkEllipsis; }
+
+\"[^\"]*\" { yylval.text = _strdup(yytext);
+ return TkString; }
+
+[0-9]+ { sscanf(yytext, "%d", &yylval.i);
+ return TkInt; }
+
+0x[0-9a-fA-F]+ { sscanf(yytext, "%x", &yylval.i);
+ return TkInt; }
+
+'.' { yylval.text = _strdup(yytext);
+ return TkChar; }
+
+[a-zA-Z_][a-zA-Z_0-9]* { yylval.text = _strdup(yytext);
+#if 0
+ printf("Id: %s\n", yylval.text);
+#endif
+ return TkId; }
+
+#[ \t]*"line"[^\n]*/\n { SetFileFromDirective(yytext); }
+
+#[ \t]*"pragma"[^\n]*/\n { }
+
+[ \t\v\f\r] { }
+
+[\n] { yyline++; }
+
+. { LexError("Unexpected character '%c' (%d)\n",
+ yytext[0], yytext[0]); }
+
+%%
diff --git a/private/ole32/olethunk/thc/thc/main.c b/private/ole32/olethunk/thc/thc/main.c
new file mode 100644
index 000000000..597562a7a
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/main.c
@@ -0,0 +1,66 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "main.h"
+#include "type.h"
+#include "gen.h"
+
+extern FILE *yyin;
+
+int yyline;
+char yyfile[256];
+
+int yyparse(void);
+
+void SetFile(int line, char *file)
+{
+ yyline = line;
+ strcpy(yyfile, file);
+}
+
+void LexError(char *fmt, ...)
+{
+ va_list args;
+
+ fprintf(stderr, "Error: %s(%d): ", yyfile, yyline);
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fputc('\n', stderr);
+}
+
+extern int yydebug;
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ char fn[256];
+
+ if (argc < 2)
+ {
+ printf("Usage: %s file\n", argv[0]);
+ exit(1);
+ }
+
+ sprintf(fn, "%s.i", argv[1]);
+ fclose(stdin);
+ yyin = fopen(fn, "r");
+ if (yyin == NULL)
+ {
+ perror(fn);
+ exit(1);
+ }
+
+ SetFile(1, fn);
+ InitTypes();
+ StartGen();
+
+ yyparse();
+
+ if (yyin != stdin)
+ fclose(yyin);
+
+ EndGen();
+ UninitTypes();
+}
diff --git a/private/ole32/olethunk/thc/thc/main.h b/private/ole32/olethunk/thc/thc/main.h
new file mode 100644
index 000000000..e93f7956b
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/main.h
@@ -0,0 +1,9 @@
+#ifndef __MAIN_H__
+#define __MAIN_H__
+
+extern int yyline;
+
+void LexError(char *fmt, ...);
+void SetFile(int line, char *file);
+
+#endif
diff --git a/private/ole32/olethunk/thc/thc/makefil0 b/private/ole32/olethunk/thc/thc/makefil0
new file mode 100644
index 000000000..2c217ded2
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/makefil0
@@ -0,0 +1,14 @@
+GENFILES = grammar.h grammar.c grammar.i lexer.c
+YACC=yacc.exe
+FLEX=flex.exe
+
+all: $(GENFILES)
+
+clean:
+ del $(GENFILES)
+
+lexer.c: lexer.l
+ $(FLEX) -t lexer.l > lexer.c
+
+grammar.c grammar.h: grammar.y
+ $(YACC) -hi grammar.y
diff --git a/private/ole32/olethunk/thc/thc/makefile b/private/ole32/olethunk/thc/thc/makefile
new file mode 100644
index 000000000..734e18727
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the subcomponents of NTOS.
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/olethunk/thc/thc/myypars.c b/private/ole32/olethunk/thc/thc/myypars.c
new file mode 100644
index 000000000..5dbcdc5b0
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/myypars.c
@@ -0,0 +1,164 @@
+# define YYFLAG -1000
+# define YYERROR goto yyerrlab
+# define YYACCEPT return(0)
+# define YYABORT return(1)
+
+/* parser for yacc output */
+
+int yydebug = 0; /* 1 for debugging */
+YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */
+int yychar = -1; /* current input token number */
+int yynerrs = 0; /* number of errors */
+short yyerrflag = 0; /* error recovery flag */
+
+yyparse()
+ {
+
+ short yys[YYMAXDEPTH];
+ short yyj, yym;
+ register YYSTYPE *yypvt;
+ register short yystate, *yyps, yyn;
+ register YYSTYPE *yypv;
+ register short *yyxi;
+
+ yystate = 0;
+ yychar = -1;
+ yynerrs = 0;
+ yyerrflag = 0;
+ yyps= &yys[-1];
+ yypv= &yyv[-1];
+
+yystack: /* put a state and value onto the stack */
+
+ if( yydebug )
+ printf( "depth %3d, state %3d, char 0%o\n",
+ yyps-yys+1, yystate, yychar );
+ if( ++yyps> &yys[YYMAXDEPTH] )
+ {
+ yyerror( "yacc stack overflow" );
+ return(1);
+ }
+ *yyps = yystate;
+ ++yypv;
+#ifdef YACC_UNION
+ yyunion(yypv, &yyval);
+#else
+ *yypv = yyval;
+#endif
+yynewstate:
+
+ yyn = yypact[yystate];
+
+ if( yyn<= YYFLAG ) goto yydefault; /* simple state */
+
+ if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0;
+ if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault;
+
+ if( yychk[ yyn=yyact[ yyn ] ] == yychar )
+ {
+ /* valid shift */
+ yychar = -1;
+#ifdef YACC_UNION
+ yyunion(&yyval, &yylval);
+#else
+ yyval = yylval;
+#endif
+ yystate = yyn;
+ if( yyerrflag > 0 ) --yyerrflag;
+ goto yystack;
+ }
+yydefault:
+ /* default state action */
+
+ if( (yyn=yydef[yystate]) == -2 )
+ {
+ if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0;
+ /* look through exception table */
+
+ for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */
+
+ for(yyxi+=2; *yyxi >= 0; yyxi+=2)
+ {
+ if( *yyxi == yychar ) break;
+ }
+ if( (yyn = yyxi[1]) < 0 ) return(0); /* accept */
+ }
+
+ if( yyn == 0 )
+ {
+ /* error */
+ /* error ... attempt to resume parsing */
+
+ switch( yyerrflag )
+ {
+
+ case 0: /* brand new error */
+
+ yyerror( "syntax error" );
+yyerrlab:
+ ++yynerrs;
+
+ case 1:
+ case 2: /* incompletely recovered error ... try again */
+
+ yyerrflag = 3;
+
+ /* find a state where "error" is a legal shift action */
+
+ while ( yyps >= yys )
+ {
+ yyn = yypact[*yyps] + YYERRCODE;
+ if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE )
+ {
+ yystate = yyact[yyn]; /* simulate a shift of "error" */
+ goto yystack;
+ }
+ yyn = yypact[*yyps];
+
+ /* the current yyps has no shift onn "error", pop stack */
+
+ if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] );
+ --yyps;
+ --yypv;
+ }
+
+ /* there is no state on the stack with an error shift ... abort */
+
+yyabort:
+ return(1);
+
+
+ case 3: /* no shift yet; clobber input char */
+ if( yydebug ) printf( "error recovery discards char %d\n", yychar );
+
+ if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */
+ yychar = -1;
+ goto yynewstate; /* try again in the same state */
+
+ }
+
+ }
+
+ /* reduction by production yyn */
+
+ if( yydebug ) printf("reduce %d\n",yyn);
+ yyps -= yyr2[yyn];
+ yypvt = yypv;
+ yypv -= yyr2[yyn];
+#ifdef YACC_UNION
+ yyunion(&yyval, &yypv[1]);
+#else
+ yyval = yypv[1];
+#endif
+ yym=yyn;
+ /* consult goto table to find next state */
+ yyn = yyr1[yyn];
+ yyj = yypgo[yyn] + *yyps + 1;
+ if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]];
+ switch(yym)
+ {
+ $A
+ }
+ goto yystack; /* stack new state and value */
+
+ }
diff --git a/private/ole32/olethunk/thc/thc/op.c b/private/ole32/olethunk/thc/thc/op.c
new file mode 100644
index 000000000..1816ac91b
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/op.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+
+#include "op.h"
+#include "main.h"
+
+int PrefixOp(int op, int val)
+{
+ switch(op)
+ {
+ case OP_UNARY_MINUS:
+ return -val;
+ }
+ LexError("Unknown prefix operator");
+ return 0;
+}
+
+int BinaryOp(int left, int op, int right)
+{
+ switch(op)
+ {
+ case OP_LEFT_SHIFT:
+ return left << right;
+ }
+ LexError("Unknown binary operator");
+ return 0;
+}
diff --git a/private/ole32/olethunk/thc/thc/op.h b/private/ole32/olethunk/thc/thc/op.h
new file mode 100644
index 000000000..161b6300c
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/op.h
@@ -0,0 +1,10 @@
+#ifndef __OP_H__
+#define __OP_H__
+
+#define OP_UNARY_MINUS 0
+#define OP_LEFT_SHIFT 1
+
+int PrefixOp(int op, int val);
+int BinaryOp(int left, int op, int right);
+
+#endif
diff --git a/private/ole32/olethunk/thc/thc/skeleton.flx b/private/ole32/olethunk/thc/thc/skeleton.flx
new file mode 100644
index 000000000..7827d37c1
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/skeleton.flx
@@ -0,0 +1,852 @@
+/* A lexical scanner generated by flex */
+
+/* scanner skeleton version:
+ * $Header: /usr/fsys/odin/a/vern/flex/RCS/flex.skel,v 2.16 90/08/03 14:09:36 vern Exp $
+ */
+
+#define FLEX_SCANNER
+
+#include <stdio.h>
+#include <io.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+// #include <osfcn.h> BUGBUG: raymondm: what is this file?
+
+/* use prototypes in function declarations */
+#define YY_USE_PROTOS
+
+/* the "const" storage-class-modifier is valid */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#ifdef __STDC__
+
+#ifdef __GNUC__
+#include <stddef.h>
+void *malloc( size_t );
+void free( void* );
+#else
+#include <stdlib.h>
+#endif /* __GNUC__ */
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+
+#ifdef __TURBOC__
+#define YY_USE_CONST
+#endif
+
+
+#ifndef YY_USE_CONST
+#define const
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+/* we can't get here if it's an ANSI C compiler, or a C++ compiler,
+ * so it's got to be a K&R compiler, and therefore there's no standard
+ * place from which to include these definitions
+ */
+//char *malloc();
+//int free();
+//int read();
+//#define read _read
+
+#endif
+
+
+/* amount of stuff to slurp up with each read */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* returned upon end-of-file */
+#define YY_END_TOK 0
+
+/* copy whatever the last rule matched to the standard output */
+
+/* cast to (char *) is because for 8-bit chars, yytext is (unsigned char *) */
+/* this used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite()
+ */
+#define ECHO (void) fwrite( (char *) yytext, yyleng, 1, yyout )
+
+/* gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+ // BUGBUG: raymondm replaced read(,(char*),) with _read(,(void*),)
+ // BUGBUG: removed "flex" from error message
+#define YY_INPUT(buf,result,max_size) \
+ if ( (result = _read( fileno(yyin), (void *) buf, max_size )) < 0 ) \
+ YY_FATAL_ERROR( "read() in lex scanner failed" );
+#define YY_NULL 0
+
+/* no semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#define yyterminate() return ( YY_NULL )
+
+/* report a fatal error */
+
+/* The funky do-while is used to turn this macro definition into
+ * a single C statement (which needs a semi-colon terminator).
+ * This avoids problems with code like:
+ *
+ * if ( something_happens )
+ * YY_FATAL_ERROR( "oops, the something happened" );
+ * else
+ * everything_okay();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the YY_FATAL_ERROR() call.
+ */
+
+#define YY_FATAL_ERROR(msg) \
+ do \
+ { \
+ (void) fputs( msg, stderr ); \
+ (void) putc( '\n', stderr ); \
+ exit( 1 ); \
+ } \
+ while ( 0 )
+
+/* default yywrap function - always treat EOF as an EOF */
+
+/* enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* action number for EOF rule of a given start state */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* special action meaning "start processing a new file" */
+#define YY_NEW_FILE \
+ do \
+ { \
+ yy_init_buffer( yy_current_buffer, yyin ); \
+ yy_load_buffer_state(); \
+ } \
+ while ( 0 )
+
+/* default declaration of generated scanner - a define so the user can
+ * easily add parameters
+ */
+#define YY_DECL int yylex YY_PROTO(( void ))
+
+/* code executed at the end of each rule */
+#define YY_BREAK break;
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE (YY_READ_BUF_SIZE * 2) /* size of default input buffer */
+#endif
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+%% section 1 definitions go here
+
+#ifndef yywrap
+#define yywrap() 1
+#endif
+
+
+/* done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext
+ */
+#define YY_DO_BEFORE_ACTION \
+ yytext = yy_bp; \
+%% code to fiddle yytext and yyleng for yymore() goes here
+ yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yy_c_buf_p = yy_cp;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* return all but the first 'n' matched characters back to the input stream */
+#define yyless(n) \
+ do \
+ { \
+ /* undo effects of setting up yytext */ \
+ *yy_cp = yy_hold_char; \
+ yy_c_buf_p = yy_cp = yy_bp + n; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yytext )
+
+
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ YY_CHAR *yy_ch_buf; /* input buffer */
+ YY_CHAR *yy_buf_pos; /* current position in input buffer */
+
+ /* size of input buffer in bytes, not including room for EOB characters*/
+ int yy_buf_size;
+
+ /* number of characters read into yy_ch_buf, not including EOB characters */
+ int yy_n_chars;
+
+ int yy_eof_status; /* whether we've seen an EOF on this buffer */
+#define EOF_NOT_SEEN 0
+ /* "pending" happens when the EOF has been seen but there's still
+ * some text process
+ */
+#define EOF_PENDING 1
+#define EOF_DONE 2
+ };
+
+static YY_BUFFER_STATE yy_current_buffer;
+
+/* we provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state"
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed */
+static YY_CHAR yy_hold_char;
+
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+
+
+
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+#ifndef YY_USER_INIT
+#define YY_USER_INIT
+#endif
+
+extern YY_CHAR *yytext;
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+YY_CHAR *yytext;
+int yyleng;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+%% data tables for the DFA go here
+
+/* these variables are all declared out here so that section 3 code can
+ * manipulate them
+ */
+/* points to current character in buffer */
+static YY_CHAR *yy_c_buf_p = (YY_CHAR *) 0;
+static int yy_init = 1; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yyunput YY_PROTO(( YY_CHAR c, YY_CHAR *buf_ptr ));
+void yyrestart YY_PROTO(( FILE *input_file ));
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+
+#define yy_new_buffer yy_create_buffer
+
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+
+YY_DECL
+ {
+ register yy_state_type yy_current_state;
+ register YY_CHAR *yy_cp, *yy_bp;
+ register int yy_act;
+
+%% user's declarations go here
+
+ if ( yy_init )
+ {
+ YY_USER_INIT;
+
+ if ( ! yy_start )
+ yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( yy_current_buffer )
+ yy_init_buffer( yy_current_buffer, yyin );
+ else
+ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+ yy_load_buffer_state();
+
+ yy_init = 0;
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+%% yymore()-related code goes here
+ yy_cp = yy_c_buf_p;
+
+ /* support of yytext */
+ *yy_cp = yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of the
+ * current run.
+ */
+ yy_bp = yy_cp;
+
+%% code to set up and find next match goes here
+
+yy_find_action:
+%% code to find the action number goes here
+
+ YY_DO_BEFORE_ACTION;
+ YY_USER_ACTION;
+
+do_action: /* this label is used only to access EOF actions */
+
+%% debug code goes here
+
+ switch ( yy_act )
+ {
+%% actions go here
+
+ case YY_END_OF_BUFFER:
+ {
+ /* amount of text matched not including the EOB char */
+ int yy_amount_of_matched_text = yy_cp - yytext - 1;
+
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yy_hold_char;
+
+ /* note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the end-
+ * of-buffer state). Contrast this with the test in yyinput().
+ */
+ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ /* this was really a NUL */
+ {
+ yy_state_type yy_next_state;
+
+ yy_c_buf_p = yytext + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ /* okay, we're now positioned to make the
+ * NUL transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we
+ * don't want to build jamming into it because
+ * then it will run more slowly)
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = yytext + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* consume the NUL */
+ yy_cp = ++yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+%% code to do backtracking for compressed tables and set up yy_cp goes here
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yy_did_buffer_switch_on_eof = 0;
+
+ if ( yywrap() )
+ {
+ /* note: because we've taken care in
+ * yy_get_next_buffer() to have set up yytext,
+ * we can now set up yy_c_buf_p so that if some
+ * total hoser (like flex itself) wants
+ * to call the scanner after we return the
+ * YY_NULL, it'll still work - another YY_NULL
+ * will get returned.
+ */
+ yy_c_buf_p = yytext + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF((yy_start - 1) / 2);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ }
+ break;
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yy_c_buf_p =
+ &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+ yy_current_state = yy_get_previous_state();
+
+ yy_cp = yy_c_buf_p;
+ yy_bp = yytext + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+#ifdef FLEX_DEBUG
+ printf( "action # %d\n", yy_act );
+#endif
+ // BUGBUG: raymondm: removed flex from error message
+ YY_FATAL_ERROR(
+ "fatal lex scanner internal error--no action found" );
+ }
+ }
+ // BUGBUG: raymondm: removed flex from error message
+ YY_FATAL_ERROR(
+ "fatal lex scanner internal error--no token returned");
+ // BUGBUG: added dummy return to quiet the CXX compile
+ return(0);
+ }
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * synopsis
+ * int yy_get_next_buffer();
+ *
+ * returns a code representing an action
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+
+ {
+ register YY_CHAR *dest = yy_current_buffer->yy_ch_buf;
+ register YY_CHAR *source = yytext - 1; /* copy prev. char, too */
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ /* try to read more data */
+
+ /* first move last chars to start of buffer */
+ number_to_move = yy_c_buf_p - yytext;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( yy_current_buffer->yy_eof_status != EOF_NOT_SEEN )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ else if ( num_to_read <= 0 )
+ YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" );
+
+ /* read in more data */
+ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+ yy_n_chars, num_to_read );
+ }
+
+ if ( yy_n_chars == 0 )
+ {
+ if ( number_to_move == 1 )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yy_current_buffer->yy_eof_status = EOF_DONE;
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ yy_current_buffer->yy_eof_status = EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yy_n_chars += number_to_move;
+ yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ /* yytext begins at the second character in yy_ch_buf; the first
+ * character is the one which preceded it before reading in the latest
+ * buffer; it needs to be kept around in case it's a newline, so
+ * yy_get_previous_state() will have with '^' rules active
+ */
+
+ yytext = &yy_current_buffer->yy_ch_buf[1];
+
+ return ( ret_val );
+ }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached
+ *
+ * synopsis
+ * yy_state_type yy_get_previous_state();
+ */
+
+static yy_state_type yy_get_previous_state()
+
+ {
+ register yy_state_type yy_current_state;
+ register YY_CHAR *yy_cp;
+
+%% code to get the start state into yy_current_state goes here
+
+ for ( yy_cp = yytext + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+ {
+%% code to find the next state goes here
+ }
+
+ return ( yy_current_state );
+ }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( register yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+register yy_state_type yy_current_state;
+#endif
+
+ {
+ register int yy_is_jam;
+%% code to find the next state, and perhaps do backtracking, goes here
+
+ return ( yy_is_jam ? 0 : yy_current_state );
+ }
+
+
+#ifdef YY_USE_PROTOS
+static void yyunput( YY_CHAR c, register YY_CHAR *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+YY_CHAR c;
+register YY_CHAR *yy_bp;
+#endif
+
+ {
+ register YY_CHAR *yy_cp = yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yy_hold_char;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ register int number_to_move = yy_n_chars + 2; /* +2 for EOB chars */
+ register YY_CHAR *dest =
+ &yy_current_buffer->yy_ch_buf[yy_current_buffer->yy_buf_size + 2];
+ register YY_CHAR *source =
+ &yy_current_buffer->yy_ch_buf[number_to_move];
+
+ while ( source > yy_current_buffer->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += dest - source;
+ yy_bp += dest - source;
+ yy_n_chars = yy_current_buffer->yy_buf_size;
+
+ if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ if ( yy_cp > yy_bp && yy_cp[-1] == '\n' )
+ yy_cp[-2] = '\n';
+
+ *--yy_cp = c;
+
+ /* note: the formal parameter *must* be called "yy_bp" for this
+ * macro to now work correctly
+ */
+ YY_DO_BEFORE_ACTION; /* set up yytext again */
+ }
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+
+ {
+ int c;
+ YY_CHAR *yy_cp = yy_c_buf_p;
+
+ *yy_cp = yy_hold_char;
+
+ if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+ /* this was really a NUL */
+ *yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ yytext = yy_c_buf_p;
+ ++yy_c_buf_p;
+
+ switch ( yy_get_next_buffer() )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap() )
+ {
+ yy_c_buf_p = yytext + YY_MORE_ADJ;
+ return ( EOF );
+ }
+
+ YY_NEW_FILE;
+
+#ifdef __cplusplus
+ return ( yyinput() );
+#else
+ return ( input() );
+#endif
+ }
+ break;
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yy_c_buf_p = yytext + YY_MORE_ADJ;
+ break;
+
+ case EOB_ACT_LAST_MATCH:
+#ifdef __cplusplus
+ YY_FATAL_ERROR( "unexpected last match in yyinput()" );
+#else
+ YY_FATAL_ERROR( "unexpected last match in input()" );
+#endif
+ }
+ }
+ }
+
+ c = *yy_c_buf_p;
+ yy_hold_char = *++yy_c_buf_p;
+
+ return ( c );
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+
+ {
+ yy_init_buffer( yy_current_buffer, input_file );
+ yy_load_buffer_state();
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+
+ {
+ if ( yy_current_buffer == new_buffer )
+ return;
+
+ if ( yy_current_buffer )
+ {
+ /* flush out information for old buffer */
+ *yy_c_buf_p = yy_hold_char;
+ yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+ yy_current_buffer->yy_n_chars = yy_n_chars;
+ }
+
+ yy_current_buffer = new_buffer;
+ yy_load_buffer_state();
+
+ /* we don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yy_did_buffer_switch_on_eof = 1;
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+
+ {
+ yy_n_chars = yy_current_buffer->yy_n_chars;
+ yytext = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+ yyin = yy_current_buffer->yy_input_file;
+ yy_hold_char = *yy_c_buf_p;
+ }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+
+ {
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) malloc( sizeof( struct yy_buffer_state ) );
+
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (YY_CHAR *) malloc( (unsigned) (b->yy_buf_size + 2) );
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ yy_init_buffer( b, file );
+
+ return ( b );
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+ {
+ if ( b == yy_current_buffer )
+ yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+ free( (char *) b->yy_ch_buf );
+ free( (char *) b );
+ }
+
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+ {
+ b->yy_input_file = file;
+
+ /* we put in the '\n' and start reading from [1] so that an
+ * initial match-at-newline will be true.
+ */
+
+ b->yy_ch_buf[0] = '\n';
+ b->yy_n_chars = 1;
+
+ /* we always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[2] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[1];
+
+ b->yy_eof_status = EOF_NOT_SEEN;
+ }
+ \ No newline at end of file
diff --git a/private/ole32/olethunk/thc/thc/sources b/private/ole32/olethunk/thc/thc/sources
new file mode 100644
index 000000000..32fa73bf0
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/sources
@@ -0,0 +1,75 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+Author:
+
+ Brian Chapman (BChapman) July 10th 1995.
+
+!ENDIF
+
+MAJORCOMP = cairole
+MINORCOMP = perform
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= thc
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= PROGRAM
+
+# INCLUDES= $(BASEDIR)\private\ole32\h;..\..\common
+# INCLUDES= $(INCLUDES);$(BASEDIR)\private\oleutest\balls\oleprx32\daytona
+# INCLUDES= $(INCLUDES);$(BASEDIR)\private\ole32\common\daytona;..
+# INCLUDES= $(INCLUDES);..\..\ole32\tests
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DFLAT \
+ -DWIN32=100 \
+ -D_NT1X_=100 \
+ -DUNICODE \
+ -D_UNICODE \
+ -DNOEXCEPTIONS \
+ -DCAIROLE_DOWNLEVEL
+
+#BLDCRT= 1
+
+SOURCES= \
+ gen.c \
+ grammar.c \
+ lexer.c \
+ main.c \
+ op.c \
+ special.c \
+ type.c
+
+
+UMTYPE= console
+UMENTRY= main
diff --git a/private/ole32/olethunk/thc/thc/special.c b/private/ole32/olethunk/thc/thc/special.c
new file mode 100644
index 000000000..3d861e525
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/special.c
@@ -0,0 +1,1283 @@
+#include <stdio.h>
+#include <ctype.h>
+
+#include "type.h"
+#include "main.h"
+#include "gen.h"
+#include "special.h"
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#define ALL_CLASSES "Std"
+
+extern int api_index;
+extern int method_count;
+
+void sBuiltIn(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ /* Thop string is built in */
+ if (!not_thunked)
+ {
+ if (class == NULL)
+ {
+ Section(API_THOP_TABLE_SECTION);
+ if (api_index > 1)
+ SecOut(",");
+ SecOut(" thops%s\n", routine->name);
+ Section(API_THOP_TABLE_SECTION);
+ }
+ else
+ {
+ Section(IFACE_THOP_TABLE_SECTION);
+ if (method_count > FIRST_METHOD)
+ SecOut(",");
+ SecOut(" thops" ALL_CLASSES "_%s\n", routine->name);
+ Section(IFACE_THOP_TABLE_SECTION);
+ }
+ }
+}
+
+// Only generate these once even though they exist on every interface
+
+#ifdef THUNK_IUNKNOWN
+void sQueryInterface(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ static int gen = FALSE;
+
+ if (!not_thunked)
+ {
+ if (!gen)
+ {
+ sStartRoutine(ALL_CLASSES, routine);
+
+ // This thop string should never be used
+ SecOut("THOP_ERROR, ");
+
+ sEndRoutine(ALL_CLASSES, routine, sig);
+ gen = TRUE;
+ }
+ else
+ {
+ sBuiltIn(ALL_CLASSES, routine, params, sig);
+ }
+ }
+}
+
+void sAddRef(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ static int gen = FALSE;
+
+ if (!not_thunked)
+ {
+ if (!gen)
+ {
+ sStartRoutine(ALL_CLASSES, routine);
+
+ // This thop string should never be used
+ SecOut("THOP_ERROR, ");
+
+ sEndRoutine(ALL_CLASSES, routine, sig);
+ gen = TRUE;
+ }
+ else
+ {
+ sBuiltIn(ALL_CLASSES, routine, params, sig);
+ }
+ }
+}
+
+void sRelease(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ static int gen = FALSE;
+
+ if (!not_thunked)
+ {
+ if (!gen)
+ {
+ sStartRoutine(ALL_CLASSES, routine);
+
+ // This thop string should never be used
+ SecOut("THOP_ERROR, ");
+
+ sEndRoutine(ALL_CLASSES, routine, sig);
+ gen = TRUE;
+ }
+ else
+ {
+ sBuiltIn(ALL_CLASSES, routine, params, sig);
+ }
+ }
+}
+#else
+void sQueryInterface(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ // Not thunked
+}
+
+void sAddRef(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ // Not thunked
+}
+
+void sRelease(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ // Not thunked
+}
+#endif
+
+static int enum_index = 0;
+
+void sIEnum_Next(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ Section(ENUM_INDEX_SECTION);
+ SecOut("#define THE_%s %d\n", class, enum_index++);
+ Section(ENUM_INDEX_SECTION);
+
+ sStartRoutine(class, routine);
+ SecOut("THOP_ENUM, THE_%s, ", class);
+ sEndRoutine(class, routine, sig);
+}
+
+void sIClassFactory_CreateInstance(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* LPUNKNOWN */
+ sGenType(params->type, FALSE);
+ params = params->next;
+ SecOut(", ");
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+
+ /* Interface return */
+ SecOut(", THOP_IFACEGENOWNER | THOP_OUT, %d, %d, ",
+ sizeof(void *), 2*sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIMalloc_All(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+}
+
+void sIMarshal_GetUnmarshalClass(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Interface in */
+ SecOut(", THOP_IFACEGEN | THOP_IN, %d, ", sizeof(void *));
+ params = params->next;
+
+ /* dwContext */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* pvContext is reserved NULL */
+ SecOut(", THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIMarshal_GetMarshalSizeMax(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Interface in */
+ SecOut(", THOP_IFACEGEN | THOP_IN, %d, ", sizeof(void *));
+ params = params->next;
+
+ /* dwContext */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* pvContext is reserved NULL */
+ SecOut(", THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIMarshal_MarshalInterface(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* LPSTREAM */
+ sGenType(params->type, FALSE);
+ params = params->next;
+ SecOut(", ");
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Interface in */
+ SecOut(", THOP_IFACEGEN | THOP_IN, %d, ", sizeof(void *));
+ params = params->next;
+
+ /* dwContext */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* pvContext is reserved NULL */
+ SecOut(", THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIMarshal_UnmarshalInterface(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* LPSTREAM */
+ sGenType(params->type, FALSE);
+ params = params->next;
+ SecOut(", ");
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+
+ /* Interface out */
+ SecOut(", THOP_IFACEGEN | THOP_OUT, %d, ", sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIStdMarshalInfo_GetClassForHandler(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* dwContext */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* pvContext is reserved NULL */
+ SecOut(", THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sCoGetClassObject(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* REFCLSID */
+ params = sGenParamList(params, FALSE, 1);
+
+ /* dwClsContext */
+ SecOut("THOP_CLSCONTEXT, ");
+ params = params->next;
+
+ /* pvReserved */
+ SecOut("THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Interface out */
+ SecOut(", THOP_IFACEGEN | THOP_OUT, %d, ", sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sCoRegisterClassObject(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* dwClsContext */
+ SecOut("THOP_CLSCONTEXT, ");
+ params = params->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sCoMarshalInterface(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* LPSTREAM */
+ sGenType(params->type, FALSE);
+ params = params->next;
+ SecOut(", ");
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Interface in */
+ SecOut(", THOP_IFACEGEN | THOP_IN, %d, ", sizeof(void *));
+ params = params->next;
+
+ /* dwContext */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* pvContext is reserved NULL */
+ SecOut(", THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sCoUnmarshalInterface(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* LPSTREAM */
+ sGenType(params->type, FALSE);
+ params = params->next;
+ SecOut(", ");
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+
+ /* Interface out */
+ SecOut(", THOP_IFACEGEN | THOP_OUT, %d, ", sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sCoCreateInstance(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* Class context */
+ SecOut("THOP_CLSCONTEXT, ");
+ params = params->next;
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Interface out */
+ SecOut(", THOP_IFACEGENOWNER | THOP_OUT, %d, %d, ",
+ sizeof(void *), 3*sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sDllGetClassObject(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* REFCLSID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+ SecOut(", ");
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+
+ /* Interface out */
+ SecOut(", THOP_IFACEGEN | THOP_OUT, %d, ", sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sCoGetStandardMarshal(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* riid, punk, dwDestContext */
+ params = sGenParamList(params, FALSE, 3);
+
+ /* pvContext is reserved NULL */
+ SecOut("THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sILockBytes_ReadAt(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* ULARGE_INTEGER */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Skip pv and size */
+ SecOut(", THOP_BUFFER | THOP_OUT, ");
+ params = params->next->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sILockBytes_WriteAt(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* ULARGE_INTEGER */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Buffer */
+ SecOut(", THOP_BUFFER | THOP_IN, ");
+ params = params->next->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIStream_Read(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Skip pv and size */
+ SecOut("THOP_BUFFER | THOP_OUT, ");
+ params = params->next->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIStream_Write(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Buffer */
+ SecOut("THOP_BUFFER | THOP_IN, ");
+ params = params->next->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIStorage_CopyTo(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* iidExclude array */
+ SecOut("THOP_CRGIID, ");
+ params = params->next->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sCreateDataCache(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Out interface */
+ SecOut(", THOP_IFACEGENOWNER | THOP_OUT, %d, %d, ",
+ sizeof(void *), 3*sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIMoniker_BindToObject(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Out interface */
+ SecOut(", THOP_IFACEGEN | THOP_OUT, %d, ", sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIMoniker_BindToStorage(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Out interface */
+ SecOut(", THOP_IFACEGEN | THOP_OUT, %d, ", sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sBindMoniker(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Out interface */
+ SecOut(", THOP_IFACEGEN | THOP_OUT, %d, ", sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIOleItemContainer_GetObject(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Three normal */
+ params = sGenParamList(params, FALSE, 3);
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Out interface */
+ SecOut(", THOP_IFACEGEN | THOP_OUT, %d, ", sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIOleItemContainer_GetObjectStorage(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Out interface */
+ SecOut(", THOP_IFACEGEN | THOP_OUT, %d, ", sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sOleCreate(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Six normal */
+ params = sGenParamList(params, FALSE, 6);
+
+ /* Out interface referring to second param */
+ SecOut("THOP_IFACEGEN | THOP_OUT, %d, ", 5*sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sOleCreateFromData(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Six normal */
+ params = sGenParamList(params, FALSE, 6);
+
+ /* Out interface referring to second param */
+ SecOut("THOP_IFACEGEN | THOP_OUT, %d, ", 5*sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sOleCreateLinkFromData(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Six normal */
+ params = sGenParamList(params, FALSE, 6);
+
+ /* Out interface referring to second param */
+ SecOut("THOP_IFACEGEN | THOP_OUT, %d, ", 5*sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sOleCreateLinkToFile(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Six normal */
+ params = sGenParamList(params, FALSE, 6);
+
+ /* Out interface referring to second param */
+ SecOut("THOP_IFACEGEN | THOP_OUT, %d, ", 5*sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sOleCreateStaticFromData(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Six normal */
+ params = sGenParamList(params, FALSE, 6);
+
+ /* Out interface referring to second param */
+ SecOut("THOP_IFACEGEN | THOP_OUT, %d, ", 5*sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sOleCreateLink(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Six normal */
+ params = sGenParamList(params, FALSE, 6);
+
+ /* Out interface referring to second param */
+ SecOut("THOP_IFACEGEN | THOP_OUT, %d, ", 5*sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sOleCreateFromFile(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Seven normal */
+ params = sGenParamList(params, FALSE, 7);
+
+ /* Out interface referring to third param */
+ SecOut("THOP_IFACEGEN | THOP_OUT, %d, ", 5*sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sOleLoad(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Three normal */
+ params = sGenParamList(params, FALSE, 3);
+
+ /* Out interface referring to second param */
+ SecOut("THOP_IFACEGEN | THOP_OUT, %d, ", 2*sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sOleLoadFromStream(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* One normal */
+ params = sGenParamList(params, FALSE, 1);
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Out interface */
+ SecOut(", THOP_IFACEGEN | THOP_OUT, %d, ", sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sOleCreateDefaultHandler(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Out interface */
+ SecOut(", THOP_IFACEGENOWNER | THOP_OUT, %d, %d, ",
+ sizeof(void *), 2*sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sOleCreateEmbeddingHelper(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Four normal */
+ params = sGenParamList(params, FALSE, 4);
+
+ /* REFIID */
+ sGenType(params->type, FALSE);
+ params = params->next;
+
+ /* Out interface */
+ SecOut(", THOP_IFACEGENOWNER | THOP_OUT, %d, %d, ",
+ sizeof(void *), 4*sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sStringFromGUID2(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+ SecOut("THOP_ERROR /* BUGBUG - LPWSTR is out param */, ");
+ sEndRoutine(class, routine, sig);
+}
+
+void sIViewObject_Draw(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* pvAspect */
+ SecOut("THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* Five normal */
+ params = sGenParamList(params, FALSE, 5);
+
+ /* pfnContinue and dwContinue */
+ SecOut("THOP_CALLBACK, ");
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIViewObject_GetColorSet(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* pvAspect */
+ SecOut("THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIViewObject_Freeze(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* pvAspect */
+ SecOut("THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIViewObject2_Draw(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* pvAspect */
+ SecOut("THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* Five normal */
+ params = sGenParamList(params, FALSE, 5);
+
+ /* pfnContinue and dwContinue */
+ SecOut("THOP_CALLBACK, ");
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIViewObject2_GetColorSet(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* pvAspect */
+ SecOut("THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIViewObject2_Freeze(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* pvAspect */
+ SecOut("THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIStorage_OpenStream(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* One normal */
+ params = sGenParamList(params, FALSE, 1);
+
+ /* reserved1 */
+ SecOut("THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIStorage_EnumElements(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* One normal */
+ params = sGenParamList(params, FALSE, 1);
+
+ /* reserved2 */
+ SecOut("THOP_NULL | THOP_IN, ");
+ params = params->next;
+
+ /* Continue normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIOleCache2_UpdateCache(char *class, Member *routine, Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* pReserved */
+ SecOut("THOP_NULL | THOP_IN, ");
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIMoniker_Reduce(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* ppmkToLeft, In/out IMoniker */
+ SecOut("THOP_IFACE | THOP_INOUT, THI_IMoniker, ");
+ params = params->next;
+
+ /* Finish normally */
+ sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIRpcChannelOrBuffer_GetDestCtx(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* One normal */
+ params = sGenParamList(params, FALSE, 1);
+
+ /* ppvDestContext should always return NULL */
+ SecOut("THOP_NULL | THOP_OUT, ");
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIRpcStubBuffer_DebugServerRelease(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* We need to do special hacking to clean up our proxies for
+ DebugServerQueryInterface and Release */
+ SecOut("THOP_IFACECLEAN | THOP_IN, THI_IUnknown, ");
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIPSFactoryOrBuffer_CreateProxy(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* Proxy is aggregated */
+ SecOut("THOP_IFACEOWNER | THOP_OUT, THI_%s, %d, ",
+ params->type->base->base->name,
+ 2*sizeof(void *));
+
+ /* ppv returns an aggregated interface */
+ SecOut("THOP_IFACEGENOWNER | THOP_OUT, %d, %d, ",
+ 2*sizeof(void *), 3*sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIPSFactoryOrBuffer_CreateStub(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* Stub is aggregated */
+ SecOut("THOP_IFACEOWNER | THOP_OUT, THI_%s, %d, ",
+ params->type->base->base->name, sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIRpcStub_Invoke(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Four normal */
+ params = sGenParamList(params, FALSE, 4);
+
+ /* pvDestContext should always be NULL */
+ SecOut("THOP_NULL | THOP_IN, ");
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sCoDosDateTimeToFileTime(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Two normal */
+ params = sGenParamList(params, FALSE, 2);
+
+ /* out FILETIME */
+ SecOut("THOP_COPY | THOP_OUT, 8, ");
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sStgMedSetData(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* One normal */
+ params = sGenParamList(params, FALSE, 1);
+
+ /* In STGMEDIUM with possible ownership transfer indicated
+ by following BOOL and FORMATETC as previous parameter */
+ SecOut("THOP_STGMEDIUM | THOP_IN, 1, %d, ", sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIDataObject_GetData(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* One normal */
+ params = sGenParamList(params, FALSE, 1);
+
+ /* Out STGMEDIUM
+ Without ownership transfer
+ With FORMATETC as previous parameter */
+ SecOut("THOP_STGMEDIUM | THOP_OUT, 0, %d, ", sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIDataObject_GetDataHere(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* One normal */
+ params = sGenParamList(params, FALSE, 1);
+
+ /* In STGMEDIUM
+ Without ownership transfer
+ With FORMATETC as previous parameter */
+ SecOut("THOP_STGMEDIUM | THOP_IN, 0, %d, ", sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sIAdviseSinks_OnDataChange(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* One normal */
+ params = sGenParamList(params, FALSE, 1);
+
+ /* In STGMEDIUM
+ Without ownership transfer
+ With FORMATETC as previous parameter */
+ SecOut("THOP_STGMEDIUM | THOP_IN, 0, %d, ", sizeof(void *));
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sOleCreateMenuDescriptor(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ Type *t;
+
+ /* Avoid generating a return type */
+ t = routine->type;
+ routine->type = NULL;
+ sStartRoutine(class, routine);
+ routine->type = t;
+
+ /* Generate return type by hand */
+ SecOut("THOP_RETURNTYPE, THOP_ALIAS32, ALIAS_CREATE, ");
+
+ /* Finish normally */
+ params = sGenParamList(params, FALSE, GEN_ALL);
+
+ sEndRoutine(class, routine, sig);
+}
+
+void sOleDestroyMenuDescriptor(char *class, Member *routine,
+ Member *params,
+ RoutineSignature *sig)
+{
+ sStartRoutine(class, routine);
+
+ /* Destroy alias */
+ SecOut("THOP_ALIAS32, ALIAS_REMOVE, ");
+
+ sEndRoutine(class, routine, sig);
+}
+
+SpecialCase special_cases[] =
+{
+ "?", "QueryInterface", sQueryInterface,
+ "?", "AddRef", sAddRef,
+ "?", "Release", sRelease,
+ "IEnum?", "Next", sIEnum_Next,
+ "IClassFactory", "CreateInstance", sIClassFactory_CreateInstance,
+ "IMalloc", "?", sIMalloc_All,
+ "IMarshal", "GetUnmarshalClass", sIMarshal_GetUnmarshalClass,
+ "IMarshal", "GetMarshalSizeMax", sIMarshal_GetMarshalSizeMax,
+ "IMarshal", "MarshalInterface", sIMarshal_MarshalInterface,
+ "IMarshal", "UnmarshalInterface", sIMarshal_UnmarshalInterface,
+ "IStdMarshalInfo", "GetClassForHandler",
+ sIStdMarshalInfo_GetClassForHandler,
+ NULL, "CoGetClassObject", sCoGetClassObject,
+ NULL, "CoRegisterClassObject", sCoRegisterClassObject,
+ NULL, "CoMarshalInterface", sCoMarshalInterface,
+ NULL, "CoUnmarshalInterface", sCoUnmarshalInterface,
+ NULL, "CoCreateInstance", sCoCreateInstance,
+ NULL, "DllGetClassObject", sDllGetClassObject,
+ NULL, "CoGetStandardMarshal", sCoGetStandardMarshal,
+ "ILockBytes", "ReadAt", sILockBytes_ReadAt,
+ "ILockBytes", "WriteAt", sILockBytes_WriteAt,
+ "IStream", "Read", sIStream_Read,
+ "IStream", "Write", sIStream_Write,
+ "IStorage", "CopyTo", sIStorage_CopyTo,
+ NULL, "CreateDataCache", sCreateDataCache,
+ "IMoniker", "BindToObject", sIMoniker_BindToObject,
+ "IMoniker", "BindToStorage", sIMoniker_BindToStorage,
+ NULL, "BindMoniker", sBindMoniker,
+ "IOleItemContainer", "GetObject", sIOleItemContainer_GetObject,
+ "IOleItemContainer", "GetObjectStorage",
+ sIOleItemContainer_GetObjectStorage,
+ NULL, "OleCreate", sOleCreate,
+ NULL, "OleCreateFromData", sOleCreateFromData,
+ NULL, "OleCreateLinkFromData", sOleCreateLinkFromData,
+ NULL, "OleCreateStaticFromData", sOleCreateStaticFromData,
+ NULL, "OleCreateLink", sOleCreateLink,
+ NULL, "OleCreateLinkToFile", sOleCreateLinkToFile,
+ NULL, "OleCreateFromFile", sOleCreateFromFile,
+ NULL, "OleLoad", sOleLoad,
+ NULL, "OleLoadFromStream", sOleLoadFromStream,
+ NULL, "OleCreateDefaultHandler", sOleCreateDefaultHandler,
+ NULL, "OleCreateEmbeddingHelper", sOleCreateEmbeddingHelper,
+ NULL, "StringFromGUID2", sStringFromGUID2,
+ "IViewObject", "Draw", sIViewObject_Draw,
+ "IViewObject", "GetColorSet", sIViewObject_GetColorSet,
+ "IViewObject", "Freeze", sIViewObject_Freeze,
+ "IViewObject2", "Draw", sIViewObject2_Draw,
+ "IViewObject2", "GetColorSet", sIViewObject2_GetColorSet,
+ "IViewObject2", "Freeze", sIViewObject2_Freeze,
+ "IStorage", "OpenStream", sIStorage_OpenStream,
+ "IStorage", "EnumElements", sIStorage_EnumElements,
+ "IOleCache2", "UpdateCache", sIOleCache2_UpdateCache,
+ "IMoniker", "Reduce", sIMoniker_Reduce,
+ "IRpcChannelBuffer", "GetDestCtx", sIRpcChannelOrBuffer_GetDestCtx,
+ "IRpcChannel", "GetDestCtx", sIRpcChannelOrBuffer_GetDestCtx,
+ "IRpcStubBuffer", "DebugServerRelease", sIRpcStubBuffer_DebugServerRelease,
+ "IPSFactoryBuffer", "CreateProxy", sIPSFactoryOrBuffer_CreateProxy,
+ "IPSFactory", "CreateProxy", sIPSFactoryOrBuffer_CreateProxy,
+ "IPSFactoryBuffer", "CreateStub", sIPSFactoryOrBuffer_CreateStub,
+ "IPSFactory", "CreateStub", sIPSFactoryOrBuffer_CreateStub,
+ "IRpcStub", "Invoke", sIRpcStub_Invoke,
+ "IDataObject", "SetData", sStgMedSetData,
+ "IOleCache", "SetData", sStgMedSetData,
+ "IOleCache2", "SetData", sStgMedSetData,
+ "IDataObject", "GetData", sIDataObject_GetData,
+ "IDataObject", "GetDataHere", sIDataObject_GetDataHere,
+ "IAdviseSink", "OnDataChange", sIAdviseSinks_OnDataChange,
+ "IAdviseSink2", "OnDataChange", sIAdviseSinks_OnDataChange,
+ NULL, "OleCreateMenuDescriptor", sOleCreateMenuDescriptor,
+ NULL, "OleDestroyMenuDescriptor", sOleDestroyMenuDescriptor
+};
+#define SPECIAL_CASES (sizeof(special_cases)/sizeof(special_cases[0]))
+
+int SpecialCaseCount(void)
+{
+ return SPECIAL_CASES;
+}
diff --git a/private/ole32/olethunk/thc/thc/special.h b/private/ole32/olethunk/thc/thc/special.h
new file mode 100644
index 000000000..224cdf9fc
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/special.h
@@ -0,0 +1,16 @@
+#ifndef __SPECIAL_H__
+#define __SPECIAL_H__
+
+typedef struct _SpecialCase
+{
+ char *class;
+ char *routine;
+ void (*fn)(char *class, Member *routine, Member *params,
+ RoutineSignature *sig);
+} SpecialCase;
+
+extern SpecialCase special_cases[];
+
+int SpecialCaseCount(void);
+
+#endif
diff --git a/private/ole32/olethunk/thc/thc/split.cmd b/private/ole32/olethunk/thc/thc/split.cmd
new file mode 100644
index 000000000..f6d0ac175
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/split.cmd
@@ -0,0 +1,51 @@
+@echo off
+setlocal
+
+if .%1 == . goto Usage
+
+del thopiint.cxx
+del thopsint.cxx
+del thtblint.cxx
+del vtblint.cxx
+del vtblifn.cxx
+del fntomthd.cxx
+del tc1632.cxx
+del apilist.hxx
+del thopsapi.cxx
+del thtblapi.cxx
+del vtblapi.cxx
+del thi.hxx
+del iidtothi.cxx
+del the.hxx
+del dbgapi.cxx
+del dbgint.cxx
+del dbgitbl.cxx
+
+..\thsplit\obji1d\thsplit %1
+
+copy apilist.hxx ..\..\h
+
+set dest=..\..\olethk32
+copy thopiint.cxx %dest%
+copy thopsint.cxx %dest%
+copy thtblint.cxx %dest%
+copy vtblint.cxx %dest%
+copy vtblifn.cxx %dest%
+copy fntomthd.cxx %dest%
+copy tc1632.cxx %dest%
+copy thopsapi.cxx %dest%
+copy thtblapi.cxx %dest%
+copy vtblapi.cxx %dest%
+copy thi.hxx %dest%
+copy iidtothi.cxx %dest%
+copy the.hxx %dest%
+copy dbgapi.cxx %dest%
+copy dbgint.cxx %dest%
+copy dbgitbl.cxx %dest%
+
+goto End
+
+:Usage
+echo Usage: %0 input
+
+:End
diff --git a/private/ole32/olethunk/thc/thc/type.c b/private/ole32/olethunk/thc/thc/type.c
new file mode 100644
index 000000000..94cb84b30
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/type.c
@@ -0,0 +1,347 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+
+#include "main.h"
+#include "type.h"
+
+char *TypeKindNames[] =
+{
+ "basic type",
+ "typedef",
+ "qualifier",
+ "pointer",
+ "array",
+ "struct",
+ "union",
+ "class",
+ "enum",
+ "function"
+};
+
+Type *types;
+
+void *PanicMalloc(size_t bytes)
+{
+ void *p;
+
+ p = (void *)malloc(bytes);
+ if (p == NULL)
+ {
+ printf("Out of memory\n");
+ exit(1);
+ }
+ return p;
+}
+
+static char *base_types[] =
+{
+ "void", "char", "short", "int", "long", "float", "double"
+};
+#define BASE_TYPES (sizeof(base_types)/sizeof(base_types[0]))
+
+static char *extended_types[] =
+{
+ "HANDLE", "HICON", "HWND", "HMENU", "HINSTANCE", "HGLOBAL",
+ "HDC", "HACCEL", "HRESULT", "WPARAM", "LPARAM", "WCHAR",
+ "REFIID", "REFGUID", "REFCLSID", "HOLEMENU", "SNB", "HTASK"
+};
+#define EXTENDED_TYPES (sizeof(extended_types)/sizeof(extended_types[0]))
+
+void InitTypes(void)
+{
+ int i;
+
+ for (i = 0; i < BASE_TYPES; i++)
+ AddType(NewBaseType(base_types[i]));
+
+ /* New types for the thops interpreter */
+ for (i = 0; i < EXTENDED_TYPES; i++)
+ AddType(NewBaseType(extended_types[i]));
+}
+
+void UninitTypes(void)
+{
+ while (types)
+ {
+ FreeType(types);
+ }
+}
+
+void AddType(Type *t)
+{
+ t->next = types;
+ t->prev = NULL;
+ if (t->next)
+ t->next->prev = t;
+ types = t;
+}
+
+void UnlinkType(Type *t)
+{
+ if (t->prev != NULL)
+ t->prev->next = t->next;
+ else
+ types = t->next;
+ if (t->next != NULL)
+ t->next->prev = t->prev;
+}
+
+Type *NewType(char *name, Type *base, int flags, int kind)
+{
+ Type *t;
+
+ t = (Type *)PanicMalloc(sizeof(Type));
+ t->name = name;
+ t->base = base;
+ ReferenceType(t->base);
+ t->flags = flags;
+ t->kind = kind;
+ t->ref = 1;
+ return t;
+}
+
+Type *NewBaseType(char *name)
+{
+ return NewType(name, NULL, TYF_NONE, TYK_BASE);
+}
+
+Type *NewQualifiedType(char *name, int flags, Type *base)
+{
+ return NewType(name, base, flags, TYK_QUALIFIER);
+}
+
+Type *NewTypedefType(char *name, Type *base)
+{
+ return NewType(name, base, TYF_NONE, TYK_TYPEDEF);
+}
+
+Type *NewPointerType(char *name, Type *base)
+{
+ return NewType(name, base, TYF_NONE, TYK_POINTER);
+}
+
+Type *NewArrayType(char *name, int len, Type *base)
+{
+ Type *t;
+
+ t = NewType(name, base, TYF_NONE, TYK_ARRAY);
+ t->u.array.len = len;
+ return t;
+}
+
+Type *NewStructType(char *name, Member *members)
+{
+ Type *t;
+
+ t = NewType(name, NULL, TYF_NONE, TYK_STRUCT);
+ t->u.agg.members = members;
+ return t;
+}
+
+Type *NewUnionType(char *name, Member *members)
+{
+ Type *t;
+
+ t = NewType(name, NULL, TYF_NONE, TYK_UNION);
+ t->u.agg.members = members;
+ return t;
+}
+
+Type *NewClassType(char *name, Member *members)
+{
+ Type *t;
+
+ t = NewType(name, NULL, TYF_NONE, TYK_CLASS);
+ t->u.agg.members = members;
+ return t;
+}
+
+Type *NewAggregateType(char *name, Member *members, int kind)
+{
+ Type *t;
+
+ t = NewType(name, NULL, TYF_NONE, kind);
+ t->u.agg.members = members;
+ return t;
+}
+
+Type *NewEnumType(char *name)
+{
+ return NewType(name, NULL, TYF_NONE, TYK_ENUM);
+}
+
+Type *NewFunctionType(char *name)
+{
+ return NewType(name, NULL, TYF_NONE, TYK_FUNCTION);
+}
+
+void FreeType(Type *t)
+{
+ if (t->name)
+ free(t->name);
+ DereferenceType(t->base);
+
+ switch(t->kind)
+ {
+ case TYK_STRUCT:
+ case TYK_UNION:
+ case TYK_CLASS:
+ FreeMemberList(t->u.agg.members);
+ break;
+ }
+
+ UnlinkType(t);
+
+ free(t);
+}
+
+void ReferenceType(Type *t)
+{
+ if (t)
+ {
+ t->ref++;
+ }
+}
+
+void DereferenceType(Type *t)
+{
+ if (t)
+ {
+ t->ref--;
+ if (t->ref == 0)
+ FreeType(t);
+ }
+}
+
+Type *FindType(char *name)
+{
+ Type *t;
+
+ for (t = types; t; t = t->next)
+ {
+ if (!strcmp(t->name, name))
+ return t;
+ }
+ return NULL;
+}
+
+Type *FindTypeErr(char *name)
+{
+ Type *t;
+
+ t = FindType(name);
+ if (t == NULL)
+ LexError("Unknown type: '%s'", name);
+ return t;
+}
+
+Type *ApplyQualifiers(Type *qual, Type *base)
+{
+ Type *t;
+
+ if (qual == NULL)
+ return base;
+ if (base == NULL)
+ return qual;
+
+ t = qual;
+ while (t->base != NULL)
+ {
+ t = t->base;
+ }
+ t->base = base;
+ ReferenceType(base);
+ return qual;
+}
+
+Member *NewMember(char *name, Type *t)
+{
+ Member *m;
+
+ m = (Member *)PanicMalloc(sizeof(Member));
+ m->name = name;
+ m->type = t;
+ m->next = NULL;
+ return m;
+}
+
+Member *AppendMember(Member *list, Member *m)
+{
+ Member *t;
+
+ if (list == NULL)
+ return m;
+
+ t = list;
+ while (t->next)
+ {
+ t = t->next;
+ }
+
+ t->next = m;
+ return list;
+}
+
+Member *ApplyMemberType(Member *list, Type *t)
+{
+ Member *m;
+
+ for (m = list; m; m = m->next)
+ if (m->type)
+ m->type = ApplyQualifiers(m->type, t);
+ else
+ m->type = t;
+ return list;
+}
+
+void FreeMember(Member *m)
+{
+ free(m->name);
+ free(m);
+}
+
+void FreeMemberList(Member *list)
+{
+ Member *m;
+
+ while (list)
+ {
+ m = list->next;
+ FreeMember(list);
+ list = m;
+ }
+}
+
+void Typedef(Member *td_names, Type *decl)
+{
+ Member *m, *t;
+
+
+ m = ApplyMemberType(td_names, decl);
+ while (m)
+ {
+ t = m->next;
+ if (FindType(m->name))
+ {
+ int i;
+
+ for (i = 0; i < EXTENDED_TYPES; i++)
+ if (!strcmp(m->name, extended_types[i]))
+ break;
+#ifdef REDEF_ERROR
+ if (i == EXTENDED_TYPES)
+ LexError("'%s' redefinition ignored", m->name);
+#endif
+ FreeMember(m);
+ }
+ else
+ {
+ AddType(NewTypedefType(m->name, m->type));
+ /* Can't use FreeMember since we want to keep the name */
+ free(m);
+ }
+ m = t;
+ }
+}
diff --git a/private/ole32/olethunk/thc/thc/type.h b/private/ole32/olethunk/thc/thc/type.h
new file mode 100644
index 000000000..8ca01e4b0
--- /dev/null
+++ b/private/ole32/olethunk/thc/thc/type.h
@@ -0,0 +1,97 @@
+#ifndef __TYPE_H__
+#define __TYPE_H__
+
+#define TYF_NONE 0
+#define TYF_UNSIGNED 1
+#define TYF_CONST 2
+#define TYF_IN 4
+#define TYF_OUT 8
+
+#define TYK_BASE 0
+#define TYK_TYPEDEF 1
+#define TYK_QUALIFIER 2
+#define TYK_POINTER 3
+#define TYK_ARRAY 4
+#define TYK_STRUCT 5
+#define TYK_UNION 6
+#define TYK_CLASS 7
+#define TYK_ENUM 8
+#define TYK_FUNCTION 9
+
+struct _Type;
+typedef struct _Type Type;
+
+typedef struct _ArrayType
+{
+ int len;
+} ArrayType;
+
+typedef struct _Member
+{
+ char *name;
+ Type *type;
+ struct _Member *next;
+} Member;
+
+typedef struct _Aggregate
+{
+ Member *members;
+} Aggregate;
+
+struct _Type
+{
+ char *name;
+ struct _Type *base;
+ int flags;
+ int kind;
+ int ref;
+
+ union
+ {
+ ArrayType array;
+ Aggregate agg;
+ } u;
+
+ struct _Type *next;
+ struct _Type *prev;
+};
+
+extern char *TypeKindNames[];
+
+void *PanicMalloc(size_t bytes);
+
+void InitTypes(void);
+void UninitTypes(void);
+
+Type *NewBaseType(char *name);
+Type *NewQualifiedType(char *name, int flags, Type *base);
+Type *NewTypedefType(char *name, Type *base);
+Type *NewPointerType(char *name, Type *base);
+Type *NewArrayType(char *name, int len, Type *base);
+Type *NewStructType(char *name, Member *members);
+Type *NewUnionType(char *name, Member *members);
+Type *NewClassType(char *name, Member *members);
+Type *NewAggregateType(char *name, Member *members, int kind);
+Type *NewEnumType(char *name);
+Type *NewFunctionType(char *name);
+
+void FreeType(Type *t);
+
+void ReferenceType(Type *t);
+void DereferenceType(Type *t);
+
+void AddType(Type *t);
+Type *FindType(char *name);
+Type *FindTypeErr(char *name);
+
+Type *ApplyQualifiers(Type *qual, Type *base);
+
+Member *NewMember(char *name, Type *t);
+Member *AppendMember(Member *list, Member *m);
+Member *ApplyMemberType(Member *list, Type *t);
+void FreeMember(Member *m);
+void FreeMemberList(Member *list);
+
+void Typedef(Member *td_names, Type *decl);
+
+#endif
diff --git a/private/ole32/olethunk/thc/thpp/cobjps.h b/private/ole32/olethunk/thc/thpp/cobjps.h
new file mode 100644
index 000000000..ff0359005
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/cobjps.h
@@ -0,0 +1,69 @@
+/*****************************************************************************\
+* *
+* cobjps.h - Definitions for writing standard proxies and stubs *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+#if !defined( _COBJPS_H_ )
+#define _COBJPS_H_
+
+
+/****** IRpcChannel Interface ***********************************************/
+
+interface IRpcChannel : IUnknown
+{
+ STDMETHOD(GetStream)(REFIID iid, int iMethod, BOOL fSend,
+ BOOL fNoWait, DWORD size, IStream FAR* FAR* ppIStream) = 0;
+ STDMETHOD(Call)(IStream FAR* pIStream) = 0;
+ STDMETHOD(GetDestCtx)(DWORD FAR* lpdwDestCtx, LPVOID FAR* lplpvDestCtx) = 0;
+ STDMETHOD(IsConnected)(void) = 0;
+};
+
+
+/****** IRpcProxy Interface *************************************************/
+
+// IRpcProxy is an interface implemented by proxy objects. A proxy object has
+// exactly the same interfaces as the real object in addition to IRpcProxy.
+//
+
+interface IRpcProxy : IUnknown
+{
+ STDMETHOD(Connect)(IRpcChannel FAR* pRpcChannel) = 0;
+ STDMETHOD_(void, Disconnect)(void) = 0;
+};
+
+
+/****** IRpcStub Interface **************************************************/
+
+// IRpcStub is an interface implemented by stub objects.
+//
+
+interface IRpcStub : IUnknown
+{
+ STDMETHOD(Connect)(IUnknown FAR* pUnk) = 0;
+ STDMETHOD_(void, Disconnect)(void) = 0;
+ STDMETHOD(Invoke)(REFIID iid, int iMethod, IStream FAR* pIStream,
+ DWORD dwDestCtx, LPVOID lpvDestCtx) = 0;
+ STDMETHOD_(BOOL, IsIIDSupported)(REFIID iid) = 0;
+ STDMETHOD_(ULONG, CountRefs)(void) = 0;
+};
+
+
+/****** IPSFactory Interface ************************************************/
+
+// IPSFactory - creates proxies and stubs
+//
+
+interface IPSFactory : IUnknown
+{
+ STDMETHOD(CreateProxy)(IUnknown FAR* pUnkOuter, REFIID riid,
+ IRpcProxy FAR* FAR* ppProxy, void FAR* FAR* ppv) = 0;
+ STDMETHOD(CreateStub)(REFIID riid, IUnknown FAR* pUnkServer,
+ IRpcStub FAR* FAR* ppStub) = 0;
+};
+
+#endif // _COBJPS_H_
diff --git a/private/ole32/olethunk/thc/thpp/coguid.h b/private/ole32/olethunk/thc/thpp/coguid.h
new file mode 100644
index 000000000..049884168
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/coguid.h
@@ -0,0 +1,65 @@
+/*****************************************************************************\
+* *
+* coguid.h - Master definition of GUIDs for compobj.dll *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+/* this file is the master definition of all GUIDs for the component object
+ model and is included in compobj.h. Some GUIDs for moinkers and storage
+ appear here as well. All of these GUIDs are OLE GUIDs only in the sense
+ that part of the GUID range owned by OLE was used to define them.
+
+ NOTE: The second byte of all of these GUIDs is 0.
+*/
+
+
+DEFINE_GUID(GUID_NULL, 0L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+DEFINE_OLEGUID(IID_IUnknown, 0x00000000L, 0, 0);
+DEFINE_OLEGUID(IID_IClassFactory, 0x00000001L, 0, 0);
+DEFINE_OLEGUID(IID_IMalloc, 0x00000002L, 0, 0);
+DEFINE_OLEGUID(IID_IMarshal, 0x00000003L, 0, 0);
+
+/* RPC related interfaces */
+DEFINE_OLEGUID(IID_IRpcChannel, 0x00000004L, 0, 0);
+DEFINE_OLEGUID(IID_IRpcStub, 0x00000005L, 0, 0);
+DEFINE_OLEGUID(IID_IStubManager, 0x00000006L, 0, 0);
+DEFINE_OLEGUID(IID_IRpcProxy, 0x00000007L, 0, 0);
+DEFINE_OLEGUID(IID_IProxyManager, 0x00000008L, 0, 0);
+DEFINE_OLEGUID(IID_IPSFactory, 0x00000009L, 0, 0);
+
+/* storage related interfaces */
+DEFINE_OLEGUID(IID_ILockBytes, 0x0000000aL, 0, 0);
+DEFINE_OLEGUID(IID_IStorage, 0x0000000bL, 0, 0);
+DEFINE_OLEGUID(IID_IStream, 0x0000000cL, 0, 0);
+DEFINE_OLEGUID(IID_IEnumSTATSTG, 0x0000000dL, 0, 0);
+
+/* moniker related interfaces */
+DEFINE_OLEGUID(IID_IBindCtx, 0x0000000eL, 0, 0);
+DEFINE_OLEGUID(IID_IMoniker, 0x0000000fL, 0, 0);
+DEFINE_OLEGUID(IID_IRunningObjectTable, 0x00000010L, 0, 0);
+DEFINE_OLEGUID(IID_IInternalMoniker, 0x00000011L, 0, 0);
+
+/* storage related interfaces */
+DEFINE_OLEGUID(IID_IRootStorage, 0x00000012L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved1, 0x00000013L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved2, 0x00000014L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved3, 0x00000015L, 0, 0);
+
+/* concurrency releated interfaces */
+DEFINE_OLEGUID(IID_IMessageFilter, 0x00000016L, 0, 0);
+
+/* CLSID of standard marshaler */
+DEFINE_OLEGUID(CLSID_StdMarshal, 0x00000017L, 0, 0);
+
+/* interface on server for getting info for std marshaler */
+DEFINE_OLEGUID(IID_IStdMarshalInfo, 0x00000018L, 0, 0);
+
+/* interface to inform object of number of external connections */
+DEFINE_OLEGUID(IID_IExternalConnection, 0x00000019L, 0, 0);
+
+/* NOTE: LSB 0x1a through 0xff are reserved for future use */
diff --git a/private/ole32/olethunk/thc/thpp/compobj.h b/private/ole32/olethunk/thc/thpp/compobj.h
new file mode 100644
index 000000000..f42b556bf
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/compobj.h
@@ -0,0 +1,971 @@
+/*****************************************************************************\
+* *
+* compobj.h - Component object model definitions *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#if !defined( _COMPOBJ_H_ )
+#define _COMPOBJ_H_
+
+/****** Linkage Definitions *************************************************/
+
+/*
+ * These are macros for declaring methods/functions. They exist so that
+ * control over the use of keywords (CDECL, PASCAL, __export,
+ * extern "C") resides in one place, and because this is the least
+ * intrusive way of writing function declarations that do not have
+ * to be modified in order to port to the Mac.
+ *
+ * The macros without the trailing underscore are for functions/methods
+ * which a return value of type HRESULT; this is by far the most common
+ * case in OLE. The macros with a trailing underscore take a return
+ * type as a parameter.
+ *
+ * WARNING: STDAPI is hard coded into the LPFNGETCLASSOBJECT typedef below.
+ */
+
+#ifdef __cplusplus
+ #define EXTERN_C extern "C"
+#else
+ #define EXTERN_C extern
+#endif
+
+#ifdef _MAC
+#define STDMETHODCALLTYPE
+#define STDAPICALLTYPE pascal
+
+#define STDAPI EXTERN_C STDAPICALLTYPE HRESULT
+#define STDAPI_(type) EXTERN_C STDAPICALLTYPE type
+
+#else // !_MAC
+
+#ifdef WIN32
+#define STDMETHODCALLTYPE __export __cdecl
+#define STDAPICALLTYPE __export __stdcall
+
+#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE
+#define STDAPI_(type) EXTERN_C type STDAPICALLTYPE
+
+#else
+#define STDMETHODCALLTYPE __export FAR CDECL
+#define STDAPICALLTYPE __export FAR PASCAL
+
+#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE
+#define STDAPI_(type) EXTERN_C type STDAPICALLTYPE
+
+#endif
+
+#endif //!_MAC
+
+#define STDMETHODIMP HRESULT STDMETHODCALLTYPE
+#define STDMETHODIMP_(type) type STDMETHODCALLTYPE
+
+
+/****** Interface Declaration ***********************************************/
+
+/*
+ * These are macros for declaring interfaces. They exist so that
+ * a single definition of the interface is simulataneously a proper
+ * declaration of the interface structures (C++ abstract classes)
+ * for both C and C++.
+ *
+ * DECLARE_INTERFACE(iface) is used to declare an interface that does
+ * not derive from a base interface.
+ * DECLARE_INTERFACE_(iface, baseiface) is used to declare an interface
+ * that does derive from a base interface.
+ *
+ * By default if the source file has a .c extension the C version of
+ * the interface declaratations will be expanded; if it has a .cpp
+ * extension the C++ version will be expanded. if you want to force
+ * the C version expansion even though the source file has a .cpp
+ * extension, then define the macro "CINTERFACE".
+ * eg. cl -DCINTERFACE file.cpp
+ *
+ * Example Interface declaration:
+ *
+ * #undef INTERFACE
+ * #define INTERFACE IClassFactory
+ *
+ * DECLARE_INTERFACE_(IClassFactory, IUnknown)
+ * {
+ * // *** IUnknown methods ***
+ * STDMETHOD(QueryInterface) (THIS_
+ * REFIID riid,
+ * LPVOID FAR* ppvObj) PURE;
+ * STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ * STDMETHOD_(ULONG,Release) (THIS) PURE;
+ *
+ * // *** IClassFactory methods ***
+ * STDMETHOD(CreateInstance) (THIS_
+ * LPUNKNOWN pUnkOuter,
+ * REFIID riid,
+ * LPVOID FAR* ppvObject) PURE;
+ * };
+ *
+ * Example C++ expansion:
+ *
+ * struct FAR IClassFactory : public IUnknown
+ * {
+ * virtual HRESULT STDMETHODCALLTYPE QueryInterface(
+ * IID FAR& riid,
+ * LPVOID FAR* ppvObj) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE AddRef(void) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE Release(void) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE CreateInstance(
+ * LPUNKNOWN pUnkOuter,
+ * IID FAR& riid,
+ * LPVOID FAR* ppvObject) = 0;
+ * };
+ *
+ * NOTE: Our documentation says '#define interface class' but we use
+ * 'struct' instead of 'class' to keep a lot of 'public:' lines
+ * out of the interfaces. The 'FAR' forces the 'this' pointers to
+ * be far, which is what we need.
+ *
+ * Example C expansion:
+ *
+ * typedef struct IClassFactory
+ * {
+ * const struct IClassFactoryVtbl FAR* lpVtbl;
+ * } IClassFactory;
+ *
+ * typedef struct IClassFactoryVtbl IClassFactoryVtbl;
+ *
+ * struct IClassFactoryVtbl
+ * {
+ * HRESULT (STDMETHODCALLTYPE * QueryInterface) (
+ * IClassFactory FAR* This,
+ * IID FAR* riid,
+ * LPVOID FAR* ppvObj) ;
+ * HRESULT (STDMETHODCALLTYPE * AddRef) (IClassFactory FAR* This) ;
+ * HRESULT (STDMETHODCALLTYPE * Release) (IClassFactory FAR* This) ;
+ * HRESULT (STDMETHODCALLTYPE * CreateInstance) (
+ * IClassFactory FAR* This,
+ * LPUNKNOWN pUnkOuter,
+ * IID FAR* riid,
+ * LPVOID FAR* ppvObject);
+ * HRESULT (STDMETHODCALLTYPE * LockServer) (
+ * IClassFactory FAR* This,
+ * BOOL fLock);
+ * };
+ */
+
+
+
+
+/****** Additional basic types **********************************************/
+
+
+#ifndef FARSTRUCT
+#ifdef __cplusplus
+#define FARSTRUCT FAR
+#else
+#define FARSTRUCT
+#endif // __cplusplus
+#endif // FARSTRUCT
+
+
+#ifndef WINAPI /* If not included with 3.1 headers... */
+
+#ifdef WIN32
+#define FAR
+#define PASCAL __stdcall
+#define CDECL
+#else
+#define FAR _far
+#define PASCAL _pascal
+#define CDECL _cdecl
+#endif
+
+#define VOID void
+#define WINAPI FAR PASCAL
+#define CALLBACK FAR PASCAL
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+typedef int BOOL;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned int UINT;
+
+typedef long LONG;
+typedef unsigned long DWORD;
+
+
+typedef UINT WPARAM;
+typedef LONG LPARAM;
+typedef LONG LRESULT;
+
+typedef unsigned int HANDLE;
+#define DECLARE_HANDLE(name) typedef UINT name
+
+DECLARE_HANDLE(HMODULE);
+DECLARE_HANDLE(HINSTANCE);
+DECLARE_HANDLE(HLOCAL);
+DECLARE_HANDLE(HGLOBAL);
+DECLARE_HANDLE(HDC);
+DECLARE_HANDLE(HRGN);
+DECLARE_HANDLE(HWND);
+DECLARE_HANDLE(HMENU);
+DECLARE_HANDLE(HACCEL);
+DECLARE_HANDLE(HTASK);
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+typedef void FAR * LPVOID;
+typedef WORD FAR * LPWORD;
+typedef DWORD FAR * LPDWORD;
+typedef char FAR* LPSTR;
+typedef const char FAR* LPCSTR;
+typedef void FAR* LPLOGPALETTE;
+typedef void FAR* LPMSG;
+//typedef struct tagMSG FAR *LPMSG;
+
+typedef HANDLE FAR *LPHANDLE;
+typedef struct tagRECT FAR *LPRECT;
+
+typedef struct FARSTRUCT tagSIZE
+{
+ int cx;
+ int cy;
+} SIZE;
+typedef SIZE* PSIZE;
+
+
+#endif /* WINAPI */
+
+
+typedef short SHORT;
+typedef unsigned short USHORT;
+typedef DWORD ULONG;
+
+
+#ifndef HUGEP
+#ifdef WIN32
+#define HUGEP
+#else
+#define HUGEP __huge
+#endif // WIN32
+#endif // HUGEP
+
+typedef WORD WCHAR;
+
+#ifndef WIN32
+typedef struct FARSTRUCT _LARGE_INTEGER {
+ DWORD LowPart;
+ LONG HighPart;
+} LARGE_INTEGER, *PLARGE_INTEGER;
+#endif
+#define LISet32(li, v) ((li).HighPart = ((LONG)(v)) < 0 ? -1 : 0, (li).LowPart = (v))
+
+#ifndef WIN32
+typedef struct FARSTRUCT _ULARGE_INTEGER {
+ DWORD LowPart;
+ DWORD HighPart;
+} ULARGE_INTEGER, *PULARGE_INTEGER;
+#endif
+#define ULISet32(li, v) ((li).HighPart = 0, (li).LowPart = (v))
+
+#ifndef _WINDOWS_
+#ifndef _FILETIME_
+#define _FILETIME_
+typedef struct FARSTRUCT tagFILETIME
+{
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+} FILETIME;
+#endif
+#endif
+
+#ifdef WIN32
+#define HTASK DWORD
+#endif
+
+#include "scode.h"
+
+
+
+// *********************** Compobj errors **********************************
+
+#define CO_E_NOTINITIALIZED (CO_E_FIRST + 0x0)
+// CoInitialize has not been called and must be
+
+#define CO_E_ALREADYINITIALIZED (CO_E_FIRST + 0x1)
+// CoInitialize has already been called and cannot be called again (temporary)
+
+#define CO_E_CANTDETERMINECLASS (CO_E_FIRST + 0x2)
+// can't determine clsid (e.g., extension not in reg.dat)
+
+#define CO_E_CLASSSTRING (CO_E_FIRST + 0x3)
+// the string form of the clsid is invalid (including ole1 classes)
+
+#define CO_E_IIDSTRING (CO_E_FIRST + 0x4)
+// the string form of the iid is invalid
+
+#define CO_E_APPNOTFOUND (CO_E_FIRST + 0x5)
+// application not found
+
+#define CO_E_APPSINGLEUSE (CO_E_FIRST + 0x6)
+// application cannot be run more than once
+
+#define CO_E_ERRORINAPP (CO_E_FIRST + 0x7)
+// some error in the app program file
+
+#define CO_E_DLLNOTFOUND (CO_E_FIRST + 0x8)
+// dll not found
+
+#define CO_E_ERRORINDLL (CO_E_FIRST + 0x9)
+// some error in the dll file
+
+#define CO_E_WRONGOSFORAPP (CO_E_FIRST + 0xa)
+// app written for other version of OS or other OS altogether
+
+#define CO_E_OBJNOTREG (CO_E_FIRST + 0xb)
+// object is not registered
+
+#define CO_E_OBJISREG (CO_E_FIRST + 0xc)
+// object is already registered
+
+#define CO_E_OBJNOTCONNECTED (CO_E_FIRST + 0xd)
+// handler is not connected to server
+
+#define CO_E_APPDIDNTREG (CO_E_FIRST + 0xe)
+// app was launched, but didn't registered a class factory
+
+
+// ********************* ClassObject errors ********************************
+
+#define CLASS_E_NOAGGREGATION (CLASSFACTORY_E_FIRST + 0x0)
+// class does not support aggregation (or class object is remote)
+
+#define CLASS_E_CLASSNOTAVAILABLE (CLASSFACTORY_E_FIRST + 0x1)
+// dll doesn't support that class (returned from DllGetClassObject)
+
+
+// *********************** Reg.dat errors **********************************
+
+#define REGDB_E_READREGDB (REGDB_E_FIRST + 0x0)
+// some error reading the registration database
+
+#define REGDB_E_WRITEREGDB (REGDB_E_FIRST + 0x1)
+// some error reading the registration database
+
+#define REGDB_E_KEYMISSING (REGDB_E_FIRST + 0x2)
+// some error reading the registration database
+
+#define REGDB_E_INVALIDVALUE (REGDB_E_FIRST + 0x3)
+// some error reading the registration database
+
+#define REGDB_E_CLASSNOTREG (REGDB_E_FIRST + 0x4)
+// some error reading the registration database
+
+#define REGDB_E_IIDNOTREG (REGDB_E_FIRST + 0x5)
+// some error reading the registration database
+
+
+// *************************** RPC errors **********************************
+
+#define RPC_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_RPC, 0x000)
+
+// call was rejected by callee, either by MF::HandleIncomingCall or
+#define RPC_E_CALL_REJECTED (RPC_E_FIRST + 0x1)
+
+// call was canceld by call - returned by MessagePending
+// this code only occurs if MessagePending return cancel
+#define RPC_E_CALL_CANCELED (RPC_E_FIRST + 0x2)
+
+// the caller is dispatching an intertask SendMessage call and
+// can NOT call out via PostMessage
+#define RPC_E_CANTPOST_INSENDCALL (RPC_E_FIRST + 0x3)
+
+// the caller is dispatching an asynchronus call can NOT
+// make an outgoing call on behalf of this call
+#define RPC_E_CANTCALLOUT_INASYNCCALL (RPC_E_FIRST + 0x4)
+
+// the caller is not in a state where an outgoing call can be made
+// this is the case if the caller has an outstandig call and
+// another incoming call was excepted by HIC; now the caller is
+// not allowed to call out again
+#define RPC_E_CANTCALLOUT_INEXTERNALCALL (RPC_E_FIRST + 0x5)
+
+// the connection terminated or is in a bogus state
+// and can not be used any more. Other connections
+// are still valid.
+#define RPC_E_CONNECTION_TERMINATED (RPC_E_FIRST + 0x6)
+
+// the callee (server [not server application]) is not available
+// and disappeared; all connections are invalid
+#define RPC_E_SERVER_DIED (RPC_E_FIRST + 0x7)
+
+// the caller (client ) disappeared while the callee (server) was
+// processing a call
+#define RPC_E_CLIENT_DIED (RPC_E_FIRST + 0x8)
+
+// the date paket with the marshalled parameter data is
+// incorrect
+#define RPC_E_INVALID_DATAPACKET (RPC_E_FIRST + 0x9)
+
+// the call was not transmitted properly; the message queue
+// was full and was not emptied after yielding
+#define RPC_E_CANTTRANSMIT_CALL (RPC_E_FIRST + 0xa)
+
+// the client (caller) can not marshall the parameter data
+// or unmarshall the return data - low memory etc.
+#define RPC_E_CLIENT_CANTMARSHAL_DATA (RPC_E_FIRST + 0xb)
+#define RPC_E_CLIENT_CANTUNMARSHAL_DATA (RPC_E_FIRST + 0xc)
+
+// the server (caller) can not unmarshall the parameter data
+// or marshall the return data - low memory
+#define RPC_E_SERVER_CANTMARSHAL_DATA (RPC_E_FIRST + 0xd)
+#define RPC_E_SERVER_CANTUNMARSHAL_DATA (RPC_E_FIRST + 0xe)
+
+// received data are invalid; can be server or
+// client data
+#define RPC_E_INVALID_DATA (RPC_E_FIRST + 0xf)
+
+// a particular parameter is invalid and can not be un/marshalled
+#define RPC_E_INVALID_PARAMETER (RPC_E_FIRST + 0x10)
+
+// DDE conversation - no second outgoing call on same channel
+#define RPC_E_CANTCALLOUT_AGAIN (RPC_E_FIRST + 0x11)
+
+// a internal error occured
+#define RPC_E_UNEXPECTED (RPC_E_FIRST + 0xFFFF)
+
+
+/****** Globally Unique Ids *************************************************/
+
+#ifdef __cplusplus
+
+struct FAR GUID
+{
+ DWORD Data1;
+ WORD Data2;
+ WORD Data3;
+ BYTE Data4[8];
+
+ BOOL operator==(const GUID& iidOther) const
+
+#ifdef WIN32
+ { return !memcmp(&Data1,&iidOther.Data1,sizeof(GUID)); }
+#else
+ { return !_fmemcmp(&Data1,&iidOther.Data1,sizeof(GUID)); }
+#endif
+ BOOL operator!=(const GUID& iidOther) const
+ { return !((*this) == iidOther); }
+};
+
+#else
+typedef struct GUID
+{
+ DWORD Data1;
+ WORD Data2;
+ WORD Data3;
+ BYTE Data4[8];
+} GUID;
+#endif
+
+typedef GUID FAR* LPGUID;
+
+
+// macros to define byte pattern for a GUID.
+// Example: DEFINE_GUID(GUID_XXX, a, b, c, ...);
+//
+// Each dll/exe must initialize the GUIDs once. This is done in one of
+// two ways. If you are not using precompiled headers for the file(s) which
+// initializes the GUIDs, define INITGUID before including compobj.h. This
+// is how OLE builds the initialized versions of the GUIDs which are included
+// in compobj.dll.
+//
+// The alternative (which some versions of the compiler don't handle properly;
+// they wind up with the initialized GUIDs in a data, not a text segment),
+// is to use a precompiled version of compobj.h and then include initguid.h
+// after compobj.h followed by one or more of the guid defintion files.
+
+
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID CDECL FAR name
+
+#ifdef INITGUID
+#include "initguid.h"
+#endif
+
+#define DEFINE_OLEGUID(name, l, w1, w2) \
+ DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)
+
+
+// Interface ID are just a kind of GUID
+typedef GUID IID;
+typedef IID FAR* LPIID;
+#define IID_NULL GUID_NULL
+#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2)
+
+
+// Class ID are just a kind of GUID
+typedef GUID CLSID;
+typedef CLSID FAR* LPCLSID;
+#define CLSID_NULL GUID_NULL
+#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2)
+
+
+
+#ifndef INITGUID
+#include "coguid.h"
+#endif
+
+/****** Other value types ***************************************************/
+
+// memory context values; passed to CoGetMalloc
+typedef enum tagMEMCTX
+{
+ MEMCTX_TASK = 1, // task (private) memory
+ MEMCTX_SHARED = 2, // shared memory (between processes)
+#ifdef _MAC
+ MEMCTX_MACSYSTEM = 3, // on the mac, the system heap
+#endif
+
+ // these are mostly for internal use...
+ MEMCTX_UNKNOWN = -1, // unknown context (when asked about it)
+ MEMCTX_SAME = -2, // same context (as some other pointer)
+} MEMCTX;
+
+
+
+// class context: used to determine what scope and kind of class object to use
+// NOTE: this is a bitwise enum
+typedef enum tagCLSCTX
+{
+ CLSCTX_INPROC_SERVER = 1, // server dll (runs in same process as caller)
+ CLSCTX_INPROC_HANDLER = 2, // handler dll (runs in same process as caller)
+ CLSCTX_LOCAL_SERVER = 4 // server exe (runs on same machine; diff proc)
+} CLSCTX;
+
+#define CLSCTX_ALL (CLSCTX_INPROC_SERVER| \
+ CLSCTX_INPROC_HANDLER| \
+ CLSCTX_LOCAL_SERVER)
+
+#define CLSCTX_INPROC (CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER)
+
+#define CLSCTX_SERVER (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER)
+
+
+// class registration flags; passed to CoRegisterClassObject
+typedef enum tagREGCLS
+{
+ REGCLS_SINGLEUSE = 0, // class object only generates one instance
+ REGCLS_MULTIPLEUSE = 1, // same class object genereates multiple inst.
+ // and local automatically goes into inproc tbl.
+ REGCLS_MULTI_SEPARATE = 2, // multiple use, but separate control over each
+ // context.
+
+ // NOTE: CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE is the same as
+ // (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER), REGCLS_MULTI_SEPARATE, but
+ // not the same as CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE.
+} REGCLS;
+
+
+// interface marshaling definitions
+#define MARSHALINTERFACE_MIN 40 // minimum number of bytes for interface marshl
+
+// marshaling flags; passed to CoMarshalInterface
+typedef enum tagMSHLFLAGS
+{
+ MSHLFLAGS_NORMAL = 0, // normal marshaling via proxy/stub
+ MSHLFLAGS_TABLESTRONG = 1, // keep object alive; must explicitly release
+ MSHLFLAGS_TABLEWEAK = 2 // doesn't hold object alive; still must release
+} MSHLFLAGS;
+
+// marshal context: determines the destination context of the marshal operation
+typedef enum tagMSHCTX
+{
+ MSHCTX_LOCAL = 0, // unmarshal context is local (eg.shared memory)
+ MSHCTX_NOSHAREDMEM = 1, // unmarshal context has no shared memory access
+} MSHCTX;
+
+
+// call type used by IMessageFilter::HandleIncommingMessage
+typedef enum tagCALLTYPE
+{
+ CALLTYPE_TOPLEVEL = 1, // toplevel call - no outgoing call
+ CALLTYPE_NESTED = 2, // callback on behalf of previous outgoing call - should always handle
+ CALLTYPE_ASYNC = 3, // aysnchronous call - can NOT be rejected
+ CALLTYPE_TOPLEVEL_CALLPENDING = 4, // new toplevel call with new LID
+ CALLTYPE_ASYNC_CALLPENDING = 5 // async call - can NOT be rejected
+} CALLTYPE;
+
+typedef struct tagINTERFACEINFO
+{
+ interface IUnknown FAR *pUnk; // the pointer to the object
+ IID iid; // interface id
+ WORD wMethod; // interface methode
+} INTERFACEINFO, FAR * LPINTERFACEINFO;
+
+// status of server call - returned by IMessageFilter::HandleIncommingCall
+// and passed to IMessageFilter::RetryRejectedCall
+typedef enum tagSERVERCALL
+{
+ SERVERCALL_ISHANDLED = 0,
+ SERVERCALL_REJECTED = 1,
+ SERVERCALL_RETRYLATER = 2
+} SERVERCALL;
+
+
+// Pending type indicates the level of nesting
+typedef enum tagPENDINGTYPE
+{
+ PENDINGTYPE_TOPLEVEL = 1, // toplevel call
+ PENDINGTYPE_NESTED = 2, // nested call
+} PENDINGTYPE;
+
+// return values of MessagePending
+typedef enum tagPENDINGMSG
+{
+ PENDINGMSG_CANCELCALL = 0, // cancel the outgoing call
+ PENDINGMSG_WAITNOPROCESS = 1, // wait for the return and don't dispatch the message
+ PENDINGMSG_WAITDEFPROCESS = 2 // wait and dispatch the message
+
+} PENDINGMSG;
+
+
+// bit flags for IExternalConnection
+typedef enum tagEXTCONN
+{
+ EXTCONN_STRONG = 0x0001 // strong connection
+} EXTCONN;
+
+
+/****** IUnknown Interface **************************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IUnknown
+
+DECLARE_INTERFACE(IUnknown)
+{
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+};
+
+typedef IUnknown FAR* LPUNKNOWN;
+
+
+/****** Class Factory Interface *******************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IClassFactory
+
+DECLARE_INTERFACE_(IClassFactory, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IClassFactory methods ***
+ STDMETHOD(CreateInstance) (THIS_ LPUNKNOWN pUnkOuter,
+ REFIID riid,
+ LPVOID FAR* ppvObject) PURE;
+ STDMETHOD(LockServer) (THIS_ BOOL fLock) PURE;
+
+};
+typedef IClassFactory FAR* LPCLASSFACTORY;
+
+
+/****** Memory Allocation Interface ***************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IMalloc
+
+DECLARE_INTERFACE_(IMalloc, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IMalloc methods ***
+ STDMETHOD_(void FAR*, Alloc) (THIS_ ULONG cb) PURE;
+ STDMETHOD_(void FAR*, Realloc) (THIS_ void FAR* pv, ULONG cb) PURE;
+ STDMETHOD_(void, Free) (THIS_ void FAR* pv) PURE;
+ STDMETHOD_(ULONG, GetSize) (THIS_ void FAR* pv) PURE;
+ STDMETHOD_(int, DidAlloc) (THIS_ void FAR* pv) PURE;
+ STDMETHOD_(void, HeapMinimize) (THIS) PURE;
+};
+typedef IMalloc FAR* LPMALLOC;
+
+
+/****** IMarshal Interface ************************************************/
+
+// forward declaration for IStream; must include storage.h later to use
+#ifdef __cplusplus
+interface IStream;
+#else
+typedef interface IStream IStream;
+#endif
+typedef IStream FAR* LPSTREAM;
+
+
+#undef INTERFACE
+#define INTERFACE IMarshal
+
+DECLARE_INTERFACE_(IMarshal, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IMarshal methods ***
+ STDMETHOD(GetUnmarshalClass)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid) PURE;
+ STDMETHOD(GetMarshalSizeMax)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize) PURE;
+ STDMETHOD(MarshalInterface)(THIS_ LPSTREAM pStm, REFIID riid,
+ LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags) PURE;
+ STDMETHOD(UnmarshalInterface)(THIS_ LPSTREAM pStm, REFIID riid,
+ LPVOID FAR* ppv) PURE;
+ STDMETHOD(ReleaseMarshalData)(THIS_ LPSTREAM pStm) PURE;
+ STDMETHOD(DisconnectObject)(THIS_ DWORD dwReserved) PURE;
+};
+typedef IMarshal FAR* LPMARSHAL;
+
+
+#undef INTERFACE
+#define INTERFACE IStdMarshalInfo
+
+DECLARE_INTERFACE_(IStdMarshalInfo, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IStdMarshalInfo methods ***
+ STDMETHOD(GetClassForHandler)(THIS_ DWORD dwDestContext,
+ LPVOID pvDestContext, LPCLSID pClsid) PURE;
+};
+typedef IStdMarshalInfo FAR* LPSTDMARSHALINFO;
+
+
+/****** Message Filter Interface *******************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IMessageFilter
+
+DECLARE_INTERFACE_(IMessageFilter, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IMessageFilter methods ***
+ STDMETHOD_(DWORD, HandleInComingCall) (THIS_ DWORD dwCallType,
+ HTASK htaskCaller, DWORD dwTickCount,
+ LPINTERFACEINFO pii) PURE;
+ STDMETHOD_(DWORD, RetryRejectedCall) (THIS_
+ HTASK htaskCallee, DWORD dwTickCount,
+ DWORD dwRejectType ) PURE;
+ STDMETHOD_(DWORD, MessagePending) (THIS_
+ HTASK htaskCallee, DWORD dwTickCount,
+ DWORD dwPendingType ) PURE;
+};
+typedef IMessageFilter FAR* LPMESSAGEFILTER;
+
+
+/****** External Connection Information ***********************************/
+
+#undef INTERFACE
+#define INTERFACE IExternalConnection
+
+DECLARE_INTERFACE_(IExternalConnection, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IExternalConnection methods ***
+ STDMETHOD_(DWORD, AddConnection) (THIS_ DWORD extconn, DWORD reserved) PURE;
+ STDMETHOD_(DWORD, ReleaseConnection) (THIS_ DWORD extconn, DWORD reserved, BOOL fLastReleaseCloses) PURE;
+};
+typedef IExternalConnection FAR* LPEXTERNALCONNECTION;
+
+
+/****** Enumerator Interfaces *********************************************/
+
+/*
+ * Since we don't use parametrized types, we put in explicit declarations
+ * of the enumerators we need.
+ */
+
+
+#undef INTERFACE
+#define INTERFACE IEnumString
+
+DECLARE_INTERFACE_(IEnumString, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumString methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt,
+ LPSTR FAR* rgelt,
+ ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumString FAR* FAR* ppenm) PURE;
+};
+typedef IEnumString FAR* LPENUMSTRING;
+
+
+#undef INTERFACE
+#define INTERFACE IEnumUnknown
+
+DECLARE_INTERFACE_(IEnumUnknown, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumUnknown methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, LPUNKNOWN FAR* rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumUnknown FAR* FAR* ppenm) PURE;
+};
+typedef IEnumUnknown FAR* LPENUMUNKNOWN;
+
+
+/****** STD Object API Prototypes *****************************************/
+
+STDAPI_(DWORD) CoBuildVersion( VOID );
+
+/* init/uninit */
+
+STDAPI CoInitialize(LPMALLOC pMalloc);
+STDAPI_(void) CoUninitialize(void);
+STDAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC FAR* ppMalloc);
+STDAPI_(DWORD) CoGetCurrentProcess(void);
+STDAPI CoCreateStandardMalloc(DWORD memctx, IMalloc FAR* FAR* ppMalloc);
+
+
+/* register/revoke/get class objects */
+
+STDAPI CoGetClassObject(REFCLSID rclsid, DWORD dwClsContext, LPVOID pvReserved,
+ REFIID riid, LPVOID FAR* ppv);
+STDAPI CoRegisterClassObject(REFCLSID rclsid, LPUNKNOWN pUnk,
+ DWORD dwClsContext, DWORD flags, LPDWORD lpdwRegister);
+STDAPI CoRevokeClassObject(DWORD dwRegister);
+
+
+/* marshaling interface pointers */
+
+STDAPI CoMarshalInterface(LPSTREAM pStm, REFIID riid, LPUNKNOWN pUnk,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags);
+STDAPI CoUnmarshalInterface(LPSTREAM pStm, REFIID riid, LPVOID FAR* ppv);
+STDAPI CoMarshalHresult(LPSTREAM pstm, HRESULT hresult);
+STDAPI CoUnmarshalHresult(LPSTREAM pstm, HRESULT FAR * phresult);
+STDAPI CoReleaseMarshalData(LPSTREAM pStm);
+STDAPI CoDisconnectObject(LPUNKNOWN pUnk, DWORD dwReserved);
+STDAPI CoLockObjectExternal(LPUNKNOWN pUnk, BOOL fLock, BOOL fLastUnlockReleases);
+STDAPI CoGetStandardMarshal(REFIID riid, LPUNKNOWN pUnk,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags,
+ LPMARSHAL FAR* ppMarshal);
+
+STDAPI_(BOOL) CoIsHandlerConnected(LPUNKNOWN pUnk);
+
+/* dll loading helpers; keeps track of ref counts and unloads all on exit */
+
+STDAPI_(HINSTANCE) CoLoadLibrary(LPSTR lpszLibName, BOOL bAutoFree);
+STDAPI_(void) CoFreeLibrary(HINSTANCE hInst);
+STDAPI_(void) CoFreeAllLibraries(void);
+STDAPI_(void) CoFreeUnusedLibraries(void);
+
+
+/* helper for creating instances */
+
+STDAPI CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
+ DWORD dwClsContext, REFIID riid, LPVOID FAR* ppv);
+
+
+/* other helpers */
+STDAPI_(BOOL) IsEqualGUID(REFGUID rguid1, REFGUID rguid2);
+STDAPI StringFromCLSID(REFCLSID rclsid, LPSTR FAR* lplpsz);
+STDAPI CLSIDFromString(LPSTR lpsz, LPCLSID pclsid);
+STDAPI StringFromIID(REFIID rclsid, LPSTR FAR* lplpsz);
+STDAPI IIDFromString(LPSTR lpsz, LPIID lpiid);
+STDAPI_(BOOL) CoIsOle1Class(REFCLSID rclsid);
+STDAPI ProgIDFromCLSID (REFCLSID clsid, LPSTR FAR* lplpszProgID);
+STDAPI CLSIDFromProgID (LPCSTR lpszProgID, LPCLSID lpclsid);
+STDAPI_(int) StringFromGUID2(REFGUID rguid, LPSTR lpsz, int cbMax);
+
+STDAPI CoCreateGuid(GUID FAR *pguid);
+
+STDAPI_(BOOL) CoFileTimeToDosDateTime(
+ FILETIME __in FAR* lpFileTime, LPWORD lpDosDate, LPWORD lpDosTime);
+STDAPI_(BOOL) CoDosDateTimeToFileTime(
+ WORD nDosDate, WORD nDosTime, FILETIME __out FAR* lpFileTime);
+STDAPI CoFileTimeNow( FILETIME __out FAR* lpFileTime );
+
+
+STDAPI CoRegisterMessageFilter( LPMESSAGEFILTER lpMessageFilter,
+ LPMESSAGEFILTER FAR* lplpMessageFilter );
+
+
+/* TreatAs APIS */
+
+STDAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID pClsidNew);
+STDAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew);
+
+
+/* the server dlls must define their DllGetClassObject and DllCanUnloadNow
+ * to match these; the typedefs are located here to ensure all are changed at
+ * the same time.
+ */
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID FAR* ppv);
+#ifdef _MAC
+typedef STDAPICALLTYPE HRESULT (FAR* LPFNGETCLASSOBJECT) (REFCLSID, REFIID, LPVOID FAR*);
+#else
+typedef HRESULT (STDAPICALLTYPE FAR* LPFNGETCLASSOBJECT) (REFCLSID, REFIID, LPVOID FAR*);
+#endif
+
+
+STDAPI DllCanUnloadNow(void);
+#ifdef _MAC
+typedef STDAPICALLTYPE HRESULT (FAR* LPFNCANUNLOADNOW)(void);
+#else
+typedef HRESULT (STDAPICALLTYPE FAR* LPFNCANUNLOADNOW)(void);
+#endif
+
+
+/****** Debugging Helpers *************************************************/
+
+#ifdef _DEBUG
+// writes to the debug port and displays a message box
+STDAPI FnAssert(LPSTR lpstrExpr, LPSTR lpstrMsg, LPSTR lpstrFileName, UINT iLine);
+#endif // _DEBUG
+
+#endif // _COMPOBJ_H_
diff --git a/private/ole32/olethunk/thc/thpp/config.h b/private/ole32/olethunk/thc/thpp/config.h
new file mode 100644
index 000000000..cb25e420b
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/config.h
@@ -0,0 +1,106 @@
+/* Additional base types which the THOPS interpreter understands:
+ HANDLE
+ HWND
+ HMENU
+ HINSTANCE
+ HICON
+ HGLOBAL
+ HDC
+ HACCEL
+ HOLEMENU
+ HTASK
+ HRESULT
+ WPARAM
+ LPARAM
+ WCHAR
+ SNB
+ */
+
+/* Always compile for Win16 */
+#undef WIN32
+
+#define WINAPI
+#define FAR
+#define CDECL
+#define CALLBACK
+#define NONAMELESSUNION
+#define INITGUID
+#define _INC_STRING
+#define PASCAL __pascal
+
+#define DECLARE_HANDLE(type)
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+typedef void *LPVOID;
+typedef int BOOL;
+typedef DWORD *LPDWORD;
+typedef WCHAR *LPWSTR;
+typedef WCHAR const *LPCWSTR;
+typedef void VOID;
+typedef unsigned int UINT;
+typedef long LONG;
+typedef WORD *LPWORD;
+typedef char *LPSTR;
+typedef char const *LPCSTR;
+
+/* This isn't called point to ensure that there are no legal uses of
+ POINT in the headers */
+typedef struct _INT_POINT
+{
+ int x;
+ int y;
+} INT_POINT;
+
+typedef struct tagRECT
+{
+ int top;
+ int left;
+ int right;
+ int bottom;
+} RECT, *LPRECT;
+
+typedef struct tagSIZE
+{
+ int x;
+ int y;
+} SIZE, *LPSIZE;
+
+typedef struct tagMSG
+{
+ HWND hwnd;
+ UINT message;
+ WPARAM wParam;
+ LPARAM lParam;
+ DWORD time;
+ INT_POINT pt;
+} MSG, *LPMSG;
+
+typedef struct tagPALETTEENTRY
+{
+ BYTE peRed;
+ BYTE peGreen;
+ BYTE peBlue;
+ BYTE peFlags;
+} PALETTEENTRY, *LPPALETTEENTRY;
+
+typedef struct tagLOGPALETTE
+{
+ WORD palVersion;
+ WORD palNumEntries;
+ PALETTEENTRY palPalEntry[1];
+} LOGPALETTE, *LPLOGPALETTE;
+
+/* To compile with this you must first delete this section from
+ compobj.h */
+#define interface class
+#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method
+#define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method
+#define PURE = 0
+#define THIS_
+#define THIS void
+#define DECLARE_INTERFACE(iface) interface iface
+#define DECLARE_INTERFACE_(iface, baseiface) interface iface : public baseiface
+
+/* You must also delete the section defining REF* */
diff --git a/private/ole32/olethunk/thc/thpp/depend.mk b/private/ole32/olethunk/thc/thpp/depend.mk
new file mode 100644
index 000000000..520e8d686
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/depend.mk
@@ -0,0 +1,11 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\main.obj $(OBJDIR)\main.lst: .\main.c \
+ .\coguid.h .\compobj.h .\initguid.h .\scode.h .\storage.h
+
diff --git a/private/ole32/olethunk/thc/thpp/dvobj.h b/private/ole32/olethunk/thc/thpp/dvobj.h
new file mode 100644
index 000000000..2fd844acd
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/dvobj.h
@@ -0,0 +1,480 @@
+/*****************************************************************************\
+* *
+* dvobj.h - Data/View object definitions *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+#if !defined( _DVOBJ_H_ )
+#define _DVOBJ_H_
+
+/****** DV value types ******************************************************/
+
+// forward type declarations
+#if defined(__cplusplus)
+interface IStorage;
+interface IStream;
+interface IAdviseSink;
+interface IMoniker;
+#else
+typedef interface IStorage IStorage;
+typedef interface IStream IStream;
+typedef interface IAdviseSink IAdviseSink;
+typedef interface IMoniker IMoniker;
+#endif
+
+typedef IStorage FAR* LPSTORAGE;
+typedef IStream FAR* LPSTREAM;
+typedef IAdviseSink FAR* LPADVISESINK;
+typedef IMoniker FAR* LPMONIKER;
+
+
+#if !defined(_MAC)
+typedef WORD CLIPFORMAT;
+#else
+typedef unsigned long CLIPFORMAT; // ResType
+#endif
+typedef CLIPFORMAT FAR* LPCLIPFORMAT;
+
+
+// Data/View aspect; specifies the desired aspect of the object when
+// drawing or getting data.
+typedef enum tagDVASPECT
+{
+ DVASPECT_CONTENT = 1,
+ DVASPECT_THUMBNAIL = 2,
+ DVASPECT_ICON = 4,
+ DVASPECT_DOCPRINT = 8
+} DVASPECT;
+
+
+// Data/View target device; determines the device for drawing or gettting data
+typedef struct FARSTRUCT tagDVTARGETDEVICE
+{
+ DWORD tdSize;
+ WORD tdDriverNameOffset;
+ WORD tdDeviceNameOffset;
+ WORD tdPortNameOffset;
+ WORD tdExtDevmodeOffset;
+ BYTE tdData[1];
+} DVTARGETDEVICE;
+
+
+// Format, etc.; completely specifices the kind of data desired, including tymed
+typedef struct FARSTRUCT tagFORMATETC
+{
+ CLIPFORMAT cfFormat;
+ DVTARGETDEVICE FAR* ptd;
+ DWORD dwAspect;
+ LONG lindex;
+ DWORD tymed;
+} FORMATETC, FAR* LPFORMATETC;
+
+
+// TYpes of storage MEDiums; determines how data is stored or passed around
+typedef enum tagTYMED
+{
+ TYMED_HGLOBAL = 1,
+ TYMED_FILE = 2,
+ TYMED_ISTREAM = 4,
+ TYMED_ISTORAGE = 8,
+ TYMED_GDI = 16,
+ TYMED_MFPICT = 32,
+ TYMED_NULL = 0
+} TYMED;
+
+
+// DATA format DIRection
+typedef enum tagDATADIR
+{
+ DATADIR_GET = 1,
+ DATADIR_SET = 2,
+} DATADIR;
+
+
+// SToraGe MEDIUM; a block of data on a particular medium
+typedef struct FARSTRUCT tagSTGMEDIUM
+{
+ DWORD tymed;
+ union
+ {
+ HANDLE hGlobal;
+ LPSTR lpszFileName;
+ IStream FAR* pstm;
+ IStorage FAR* pstg;
+ }
+#ifdef NONAMELESSUNION
+ u // add a tag when name less unions not supported
+#endif
+ ;
+ IUnknown FAR* pUnkForRelease;
+} STGMEDIUM, FAR* LPSTGMEDIUM;
+
+
+// Advise Flags
+typedef enum tagADVF
+{
+ ADVF_NODATA = 1,
+ ADVF_PRIMEFIRST = 2,
+ ADVF_ONLYONCE = 4,
+ ADVF_DATAONSTOP = 64,
+ ADVFCACHE_NOHANDLER = 8,
+ ADVFCACHE_FORCEBUILTIN = 16,
+ ADVFCACHE_ONSAVE = 32
+} ADVF;
+
+
+// Stats for data; used by several enumerations and by at least one
+// implementation of IDataAdviseHolder; if a field is not used, it
+// will be NULL.
+typedef struct FARSTRUCT tagSTATDATA
+{ // field used by:
+ FORMATETC formatetc; // EnumAdvise, EnumData (cache), EnumFormats
+ DWORD advf; // EnumAdvise, EnumData (cache)
+ IAdviseSink FAR* pAdvSink; // EnumAdvise
+ DWORD dwConnection; // EnumAdvise
+} STATDATA;
+
+typedef STATDATA FAR* LPSTATDATA;
+
+
+
+/****** DV Interfaces ***************************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IEnumFORMATETC
+
+DECLARE_INTERFACE_(IEnumFORMATETC, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumFORMATETC methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, FORMATETC __out FAR * rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumFORMATETC FAR* FAR* ppenum) PURE;
+};
+typedef IEnumFORMATETC FAR* LPENUMFORMATETC;
+
+
+#undef INTERFACE
+#define INTERFACE IEnumSTATDATA
+
+DECLARE_INTERFACE_(IEnumSTATDATA, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG, Release) (THIS) PURE;
+
+ // *** IEnumSTATDATA methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, STATDATA FAR * rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumSTATDATA FAR* FAR* ppenum) PURE;
+};
+typedef IEnumSTATDATA FAR* LPENUMSTATDATA;
+
+
+
+#undef INTERFACE
+#define INTERFACE IDataObject
+
+#define DATA_E_FORMATETC DV_E_FORMATETC
+#define DATA_S_SAMEFORMATETC (DATA_S_FIRST + 0)
+
+DECLARE_INTERFACE_(IDataObject, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG, Release) (THIS) PURE;
+
+ // *** IDataObject methods ***
+ STDMETHOD(GetData) (THIS_ __in LPFORMATETC pformatetcIn,
+ __out LPSTGMEDIUM pmedium ) PURE;
+ STDMETHOD(GetDataHere) (THIS_ __in LPFORMATETC pformatetc,
+ __in LPSTGMEDIUM pmedium ) PURE;
+ STDMETHOD(QueryGetData) (THIS_ __in LPFORMATETC pformatetc ) PURE;
+ STDMETHOD(GetCanonicalFormatEtc) (THIS_ __in LPFORMATETC pformatetc,
+ __out LPFORMATETC pformatetcOut) PURE;
+ STDMETHOD(SetData) (THIS_ __in LPFORMATETC pformatetc, STGMEDIUM __in FAR * pmedium,
+ BOOL fRelease) PURE;
+ STDMETHOD(EnumFormatEtc) (THIS_ DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenumFormatEtc) PURE;
+
+ STDMETHOD(DAdvise) (THIS_ FORMATETC __in FAR* pFormatetc, DWORD advf,
+ LPADVISESINK pAdvSink, DWORD FAR* pdwConnection) PURE;
+ STDMETHOD(DUnadvise) (THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumDAdvise) (THIS_ LPENUMSTATDATA FAR* ppenumAdvise) PURE;
+};
+typedef IDataObject FAR* LPDATAOBJECT;
+
+
+
+#undef INTERFACE
+#define INTERFACE IViewObject
+
+#define VIEW_E_DRAW (VIEW_E_FIRST)
+#define E_DRAW VIEW_E_DRAW
+
+#define VIEW_S_ALREADY_FROZEN (VIEW_S_FIRST)
+
+DECLARE_INTERFACE_(IViewObject, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IViewObject methods ***
+ STDMETHOD(Draw) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev,
+ HDC hdcDraw,
+ __in LPCRECTL lprcBounds,
+ __in LPCRECTL lprcWBounds,
+ BOOL (CALLBACK * pfnContinue) (DWORD),
+ DWORD dwContinue) PURE;
+
+ STDMETHOD(GetColorSet) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev,
+ LPLOGPALETTE FAR* ppColorSet) PURE;
+
+ STDMETHOD(Freeze)(THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect,
+ DWORD FAR* pdwFreeze) PURE;
+ STDMETHOD(Unfreeze) (THIS_ DWORD dwFreeze) PURE;
+ STDMETHOD(SetAdvise) (THIS_ DWORD aspects, DWORD advf,
+ LPADVISESINK pAdvSink) PURE;
+ STDMETHOD(GetAdvise) (THIS_ DWORD FAR* pAspects, DWORD FAR* pAdvf,
+ LPADVISESINK FAR* ppAdvSink) PURE;
+};
+typedef IViewObject FAR* LPVIEWOBJECT;
+
+
+#undef INTERFACE
+#define INTERFACE IViewObject2
+
+DECLARE_INTERFACE_(IViewObject2, IViewObject)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IViewObject methods ***
+ STDMETHOD(Draw) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev,
+ HDC hdcDraw,
+ __in LPCRECTL lprcBounds,
+ __in LPCRECTL lprcWBounds,
+ BOOL (CALLBACK * pfnContinue) (DWORD),
+ DWORD dwContinue) PURE;
+
+ STDMETHOD(GetColorSet) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev,
+ LPLOGPALETTE FAR* ppColorSet) PURE;
+
+ STDMETHOD(Freeze)(THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect,
+ DWORD FAR* pdwFreeze) PURE;
+ STDMETHOD(Unfreeze) (THIS_ DWORD dwFreeze) PURE;
+ STDMETHOD(SetAdvise) (THIS_ DWORD aspects, DWORD advf,
+ LPADVISESINK pAdvSink) PURE;
+ STDMETHOD(GetAdvise) (THIS_ DWORD FAR* pAspects, DWORD FAR* pAdvf,
+ LPADVISESINK FAR* ppAdvSink) PURE;
+
+ // *** IViewObject2 methods ***
+ STDMETHOD(GetExtent) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ DVTARGETDEVICE FAR * ptd, __out LPSIZEL lpsizel) PURE;
+
+};
+typedef IViewObject2 FAR* LPVIEWOBJECT2;
+
+
+#undef INTERFACE
+#define INTERFACE IAdviseSink
+
+DECLARE_INTERFACE_(IAdviseSink, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IAdviseSink methods ***
+ STDMETHOD_(void,OnDataChange)(THIS_ FORMATETC FAR __in * pFormatetc,
+ STGMEDIUM FAR __in * pStgmed) PURE;
+ STDMETHOD_(void,OnViewChange)(THIS_ DWORD dwAspect, LONG lindex) PURE;
+ STDMETHOD_(void,OnRename)(THIS_ LPMONIKER pmk) PURE;
+ STDMETHOD_(void,OnSave)(THIS) PURE;
+ STDMETHOD_(void,OnClose)(THIS) PURE;
+};
+typedef IAdviseSink FAR* LPADVISESINK;
+
+
+
+#undef INTERFACE
+#define INTERFACE IAdviseSink2
+
+DECLARE_INTERFACE_(IAdviseSink2, IAdviseSink)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IAdviseSink methods ***
+ STDMETHOD_(void,OnDataChange)(THIS_ FORMATETC FAR __in * pFormatetc,
+ STGMEDIUM FAR __in * pStgmed) PURE;
+ STDMETHOD_(void,OnViewChange)(THIS_ DWORD dwAspect, LONG lindex) PURE;
+ STDMETHOD_(void,OnRename)(THIS_ LPMONIKER pmk) PURE;
+ STDMETHOD_(void,OnSave)(THIS) PURE;
+ STDMETHOD_(void,OnClose)(THIS) PURE;
+
+ // *** IAdviseSink2 methods ***
+ STDMETHOD_(void,OnLinkSrcChange)(THIS_ LPMONIKER pmk) PURE;
+};
+typedef IAdviseSink2 FAR* LPADVISESINK2;
+
+
+
+#undef INTERFACE
+#define INTERFACE IDataAdviseHolder
+
+DECLARE_INTERFACE_(IDataAdviseHolder, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IDataAdviseHolder methods ***
+ STDMETHOD(Advise)(THIS_ LPDATAOBJECT pDataObject, FORMATETC FAR __in * pFetc,
+ DWORD advf, LPADVISESINK pAdvise, DWORD FAR* pdwConnection) PURE;
+ STDMETHOD(Unadvise)(THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumAdvise)(THIS_ LPENUMSTATDATA FAR* ppenumAdvise) PURE;
+
+ STDMETHOD(SendOnDataChange)(THIS_ LPDATAOBJECT pDataObject, DWORD dwReserved, DWORD advf) PURE;
+};
+typedef IDataAdviseHolder FAR* LPDATAADVISEHOLDER;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleCache
+
+#define CACHE_E_NOCACHE_UPDATED (CACHE_E_FIRST)
+
+#define CACHE_S_FORMATETC_NOTSUPPORTED (CACHE_S_FIRST)
+#define CACHE_S_SAMECACHE (CACHE_S_FIRST+1)
+#define CACHE_S_SOMECACHES_NOTUPDATED (CACHE_S_FIRST+2)
+
+
+DECLARE_INTERFACE_(IOleCache, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleCache methods ***
+ STDMETHOD(Cache) (THIS_ __in LPFORMATETC lpFormatetc, DWORD advf, LPDWORD lpdwConnection) PURE;
+ STDMETHOD(Uncache) (THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumCache) (THIS_ LPENUMSTATDATA FAR* ppenumStatData) PURE;
+ STDMETHOD(InitCache) (THIS_ LPDATAOBJECT pDataObject) PURE;
+ STDMETHOD(SetData) (THIS_ __in LPFORMATETC pformatetc, STGMEDIUM FAR __in * pmedium,
+ BOOL fRelease) PURE;
+};
+typedef IOleCache FAR* LPOLECACHE;
+
+
+
+// Cache update Flags
+
+#define UPDFCACHE_NODATACACHE 0x00000001
+#define UPDFCACHE_ONSAVECACHE 0x00000002
+#define UPDFCACHE_ONSTOPCACHE 0x00000004
+#define UPDFCACHE_NORMALCACHE 0x00000008
+#define UPDFCACHE_IFBLANK 0x00000010
+#define UPDFCACHE_ONLYIFBLANK 0x80000000
+
+#define UPDFCACHE_IFBLANKORONSAVECACHE (UPDFCACHE_IFBLANK | UPDFCACHE_ONSAVECACHE )
+#define UPDFCACHE_ALL (~UPDFCACHE_ONLYIFBLANK)
+#define UPDFCACHE_ALLBUTNODATACACHE (UPDFCACHE_ALL & ~UPDFCACHE_NODATACACHE)
+
+
+// IOleCache2::DiscardCache options
+typedef enum tagDISCARDCACHE
+{
+ DISCARDCACHE_SAVEIFDIRTY = 0, // Save all dirty cache before discarding
+ DISCARDCACHE_NOSAVE = 1 // Don't save dirty caches before
+ // discarding
+} DISCARDCACHE;
+
+
+#undef INTERFACE
+#define INTERFACE IOleCache2
+
+DECLARE_INTERFACE_(IOleCache2, IOleCache)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG, Release) (THIS) PURE;
+
+ // *** IOleCache methods ***
+ STDMETHOD(Cache) (THIS_ __in LPFORMATETC lpFormatetc, DWORD advf, LPDWORD lpdwConnection) PURE;
+ STDMETHOD(Uncache) (THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumCache) (THIS_ LPENUMSTATDATA FAR* ppenumStatData) PURE;
+ STDMETHOD(InitCache) (THIS_ LPDATAOBJECT pDataObject) PURE;
+ STDMETHOD(SetData) (THIS_ __in LPFORMATETC pformatetc, STGMEDIUM FAR __in * pmedium,
+ BOOL fRelease) PURE;
+
+ // *** IOleCache2 methods ***
+ STDMETHOD(UpdateCache) (THIS_ LPDATAOBJECT pDataObject, DWORD grfUpdf,
+ LPVOID pReserved) PURE;
+ STDMETHOD(DiscardCache) (THIS_ DWORD dwDiscardOptions) PURE;
+
+};
+typedef IOleCache2 FAR* LPOLECACHE2;
+
+
+#undef INTERFACE
+#define INTERFACE IOleCacheControl
+
+DECLARE_INTERFACE_(IOleCacheControl, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG, Release) (THIS) PURE;
+
+ // *** IDataObject methods ***
+ STDMETHOD(OnRun) (THIS_ LPDATAOBJECT pDataObject) PURE;
+ STDMETHOD(OnStop) (THIS) PURE;
+};
+typedef IOleCacheControl FAR* LPOLECACHECONTROL;
+
+
+
+/****** DV APIs ***********************************************************/
+
+
+STDAPI CreateDataAdviseHolder(LPDATAADVISEHOLDER FAR* ppDAHolder);
+
+STDAPI CreateDataCache(LPUNKNOWN pUnkOuter, REFCLSID rclsid,
+ REFIID iid, LPVOID FAR* ppv);
+
+#endif // _DVOBJ_H_
diff --git a/private/ole32/olethunk/thc/thpp/extens.h b/private/ole32/olethunk/thc/thpp/extens.h
new file mode 100644
index 000000000..6b57ceea6
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/extens.h
@@ -0,0 +1,202 @@
+typedef unsigned long RPCOLEDATAREP;
+
+typedef enum tagRPCFLG
+ {
+ RPCFLG_ASYNCHRONOUS = 1073741824,
+ RPCFLG_INPUT_SYNCHRONOUS = 536870912
+ }
+RPCFLG;
+
+typedef struct tagRPCOLEMESSAGE
+ {
+ void *reserved1;
+ RPCOLEDATAREP dataRepresentation;
+ void *Buffer;
+ ULONG cbBuffer;
+ ULONG iMethod;
+ DWORD reserved2[5];
+ ULONG rpcFlags;
+ }
+RPCOLEMESSAGE;
+
+typedef RPCOLEMESSAGE *PRPCOLEMESSAGE;
+
+interface IRpcChannelBuffer : public IUnknown
+{
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBuffer
+ (
+ RPCOLEMESSAGE *pMessage,
+ REFIID riid
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SendReceive
+ (
+ RPCOLEMESSAGE *pMessage,
+ ULONG *pStatus
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FreeBuffer
+ (
+ RPCOLEMESSAGE *pMessage
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDestCtx
+ (
+ DWORD *pdwDestContext,
+ void **ppvDestContext
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsConnected
+ (
+ void
+ ) = 0;
+};
+
+interface IRpcProxyBuffer : public IUnknown
+{
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ virtual HRESULT STDMETHODCALLTYPE Connect
+ (
+ IRpcChannelBuffer *pRpcChannelBuffer
+ ) = 0;
+
+ virtual void STDMETHODCALLTYPE Disconnect
+ (
+ void
+ ) = 0;
+
+};
+
+interface IRpcStubBuffer : public IUnknown
+{
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ virtual HRESULT STDMETHODCALLTYPE Connect
+ (
+ IUnknown *pUnkServer
+ ) = 0;
+
+ virtual void STDMETHODCALLTYPE Disconnect
+ (
+ void
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Invoke
+ (
+ RPCOLEMESSAGE *_prpcmsg,
+ IRpcChannelBuffer *_pRpcChannelBuffer
+ ) = 0;
+
+ virtual IRpcStubBuffer FAR *STDMETHODCALLTYPE IsIIDSupported
+ (
+ REFIID riid
+ ) = 0;
+
+ virtual ULONG STDMETHODCALLTYPE CountRefs
+ (
+ void
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DebugServerQueryInterface
+ (
+ IUnknown **ppunk
+ ) = 0;
+
+ virtual void STDMETHODCALLTYPE DebugServerRelease
+ (
+ void *pv
+ ) = 0;
+
+};
+
+interface IPSFactoryBuffer : public IUnknown
+{
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateProxy
+ (
+ IUnknown *pUnkOuter,
+ REFIID riid,
+ IRpcProxyBuffer **ppProxy,
+ void **ppv
+ ) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateStub
+ (
+ REFIID riid,
+ IUnknown *pUnkServer,
+ IRpcStubBuffer **ppStub
+ ) = 0;
+};
+
+interface IRpcChannel : public IUnknown
+{
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ STDMETHOD(GetStream)(REFIID iid, int iMethod, BOOL fSend,
+ BOOL fNoWait, DWORD size, IStream FAR* FAR* ppIStream) = 0;
+ STDMETHOD(Call)(IStream FAR* pIStream) = 0;
+ STDMETHOD(GetDestCtx)(DWORD FAR* lpdwDestCtx, LPVOID FAR* lplpvDestCtx) = 0;
+ STDMETHOD(IsConnected)(void) = 0;
+};
+
+
+interface IRpcProxy : public IUnknown
+{
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ STDMETHOD(Connect)(IRpcChannel FAR* pRpcChannel) = 0;
+ STDMETHOD_(void, Disconnect)(void) = 0;
+};
+
+
+interface IRpcStub : public IUnknown
+{
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ STDMETHOD(Connect)(IUnknown FAR* pUnk) = 0;
+ STDMETHOD_(void, Disconnect)(void) = 0;
+ STDMETHOD(Invoke)(REFIID iid, int iMethod, IStream FAR* pIStream,
+ DWORD dwDestCtx, LPVOID lpvDestCtx) = 0;
+ STDMETHOD_(BOOL, IsIIDSupported)(REFIID iid) = 0;
+ STDMETHOD_(ULONG, CountRefs)(void) = 0;
+};
+
+interface IPSFactory : public IUnknown
+{
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ STDMETHOD(CreateProxy)(IUnknown FAR* pUnkOuter, REFIID riid,
+ IRpcProxy FAR* FAR* ppProxy, void FAR* FAR* ppv) = 0;
+ STDMETHOD(CreateStub)(REFIID riid, IUnknown FAR* pUnkServer,
+ IRpcStub FAR* FAR* ppStub) = 0;
+};
+
+STDAPI ReadOleStg
+ (LPSTORAGE pstg, DWORD FAR* pdwFlags, DWORD FAR* pdwOptUpdate,
+ DWORD FAR* pdwReserved, LPMONIKER FAR* ppmk, LPSTREAM FAR* ppstmOut);
+STDAPI WriteOleStg
+ (LPSTORAGE pstg, IOleObject FAR* pOleObj,
+ DWORD dwReserved, LPSTREAM FAR* ppstmOut);
+
+STDAPI CoGetState(IUnknown FAR * FAR *ppunk);
+STDAPI CoSetState(IUnknown FAR *punk);
diff --git a/private/ole32/olethunk/thc/thpp/filelist.mk b/private/ole32/olethunk/thc/thpp/filelist.mk
new file mode 100644
index 000000000..82c0cd5d8
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/filelist.mk
@@ -0,0 +1,4 @@
+TARGET = thpp.lib
+CFILES = .\main.c
+CFLAGS = -P
+NO_WINMAIN = 1
diff --git a/private/ole32/olethunk/thc/thpp/initguid.h b/private/ole32/olethunk/thc/thpp/initguid.h
new file mode 100644
index 000000000..e7406e3c2
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/initguid.h
@@ -0,0 +1,38 @@
+/*****************************************************************************\
+* *
+* initguid.h - Definitions for controlling GUID initialization *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+// Include after compobj.h to enable GUID initialization. This
+// must be done once per exe/dll.
+//
+// After this file, include one or more of the GUID definition files.
+//
+// NOTE: ole2.lib contains references to all GUIDs defined by OLE.
+
+#ifndef DEFINE_GUID
+#pragma error "initguid: must include compobj.h first."
+#endif
+
+#undef DEFINE_GUID
+
+#ifdef _MAC
+#define __based(a)
+#endif
+
+#ifdef WIN32
+#define __based(a)
+#endif
+
+#ifdef __TURBOC__
+#define __based(a)
+#endif
+
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID CDECL __based(__segname("_CODE")) name \
+ = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
diff --git a/private/ole32/olethunk/thc/thpp/main.c b/private/ole32/olethunk/thc/thpp/main.c
new file mode 100644
index 000000000..1ad7b14ed
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/main.c
@@ -0,0 +1,5 @@
+#include "config.h"
+#include "compobj.h"
+#include "storage.h"
+#include "ole2.h"
+#include "extens.h"
diff --git a/private/ole32/olethunk/thc/thpp/makefile b/private/ole32/olethunk/thc/thpp/makefile
new file mode 100644
index 000000000..4645aad87
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/makefile
@@ -0,0 +1,2 @@
+main.i: main.c coguid.h compobj.h initguid.h scode.h storage.h
+ cl -P -I. -I/nt/public/sdk/inc/crt main.c
diff --git a/private/ole32/olethunk/thc/thpp/moniker.h b/private/ole32/olethunk/thc/thpp/moniker.h
new file mode 100644
index 000000000..3f1af6071
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/moniker.h
@@ -0,0 +1,248 @@
+/*****************************************************************************\
+* *
+* moniker.h - Moniker and related interfaces and APIs *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#if !defined( _MONIKER_H_ )
+#define _MONIKER_H_
+
+#define MK_E_CONNECTMANUALLY MK_E_FIRST
+#define MK_E_EXCEEDEDDEADLINE (MK_E_FIRST + 1)
+#define MK_E_NEEDGENERIC (MK_E_FIRST + 2)
+#define MK_E_UNAVAILABLE (MK_E_FIRST + 3)
+#define MK_E_SYNTAX (MK_E_FIRST + 4)
+#define MK_E_NOOBJECT (MK_E_FIRST + 5)
+#define MK_E_INVALIDEXTENSION (MK_E_FIRST + 6)
+#define MK_E_INTERMEDIATEINTERFACENOTSUPPORTED (MK_E_FIRST + 7)
+#define MK_E_NOTBINDABLE (MK_E_FIRST + 8)
+#define MK_E_NOTBOUND (MK_E_FIRST + 9)
+ // called IBindCtx->RevokeObjectBound for an
+ // object which was not bound
+#define MK_E_CANTOPENFILE (MK_E_FIRST + 10)
+#define MK_E_MUSTBOTHERUSER (MK_E_FIRST + 11)
+#define MK_E_NOINVERSE (MK_E_FIRST + 12)
+#define MK_E_NOSTORAGE (MK_E_FIRST + 13)
+#define MK_E_NOPREFIX (MK_E_FIRST + 14)
+
+
+// reserved MK_S_FIRST
+// reserved (MK_S_FIRST + 1)
+#define MK_S_REDUCED_TO_SELF (MK_S_FIRST + 2)
+// reserved (MK_S_FIRST + 3)
+#define MK_S_ME (MK_S_FIRST + 4)
+#define MK_S_HIM (MK_S_FIRST + 5)
+#define MK_S_US (MK_S_FIRST + 6)
+#define MK_S_MONIKERALREADYREGISTERED (MK_S_FIRST + 7)
+
+
+// bind options; variable sized
+typedef struct FARSTRUCT tagBIND_OPTS
+{
+ DWORD cbStruct; // sizeof(BIND_OPTS)
+ DWORD grfFlags;
+ DWORD grfMode;
+ DWORD dwTickCountDeadline;
+} BIND_OPTS, FAR* LPBIND_OPTS;
+
+
+// bind flags; controls binding; stored in bind options above
+typedef enum
+{
+ BIND_MAYBOTHERUSER = 1,
+ BIND_JUSTTESTEXISTENCE = 2
+} BIND_FLAGS;
+
+
+// system moniker types; returned from IsSystemMoniker.
+typedef enum tagMKSYS
+{
+ MKSYS_NONE = 0,
+ MKSYS_GENERICCOMPOSITE = 1,
+ MKSYS_FILEMONIKER = 2,
+ MKSYS_ANTIMONIKER = 3,
+ MKSYS_ITEMMONIKER = 4,
+ MKSYS_POINTERMONIKER = 5
+}MKSYS;
+
+
+// bit wise enum to control how much reduction takes place.
+typedef enum tagMKREDUCE
+{
+ MKRREDUCE_ONE = 3<<16,
+ MKRREDUCE_TOUSER = 2<<16,
+ MKRREDUCE_THROUGHUSER = 1<<16,
+ MKRREDUCE_ALL = 0
+} MKRREDUCE;
+
+
+#if defined(__cplusplus)
+interface IEnumMoniker;
+interface IRunningObjectTable;
+#else
+typedef interface IEnumMoniker IEnumMoniker;
+typedef interface IRunningObjectTable IRunningObjectTable;
+#endif
+
+typedef IEnumMoniker FAR* LPENUMMONIKER;
+typedef IRunningObjectTable FAR* LPRUNNINGOBJECTTABLE;
+
+
+
+#undef INTERFACE
+#define INTERFACE IBindCtx
+
+DECLARE_INTERFACE_(IBindCtx, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IBindCtx methods ***
+ STDMETHOD(RegisterObjectBound) (THIS_ LPUNKNOWN punk) PURE;
+ STDMETHOD(RevokeObjectBound) (THIS_ LPUNKNOWN punk) PURE;
+ STDMETHOD(ReleaseBoundObjects) (THIS) PURE;
+
+ STDMETHOD(SetBindOptions) (THIS_ __in LPBIND_OPTS pbindopts) PURE;
+ STDMETHOD(GetBindOptions) (THIS_ __out LPBIND_OPTS pbindopts) PURE;
+ STDMETHOD(GetRunningObjectTable) (THIS_ LPRUNNINGOBJECTTABLE FAR*
+ pprot) PURE;
+ STDMETHOD(RegisterObjectParam) (THIS_ LPSTR lpszKey, LPUNKNOWN punk) PURE;
+ STDMETHOD(GetObjectParam) (THIS_ LPSTR lpszKey, LPUNKNOWN FAR* ppunk) PURE;
+ STDMETHOD(EnumObjectParam) (THIS_ LPENUMSTRING FAR* ppenum) PURE;
+ STDMETHOD(RevokeObjectParam) (THIS_ LPSTR lpszKey) PURE;
+};
+typedef IBindCtx FAR* LPBC;
+typedef IBindCtx FAR* LPBINDCTX;
+
+
+
+#undef INTERFACE
+#define INTERFACE IMoniker
+
+DECLARE_INTERFACE_(IMoniker, IPersistStream)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+
+ // *** IPersistStream methods ***
+ STDMETHOD(IsDirty) (THIS) PURE;
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm) PURE;
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty) PURE;
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR * pcbSize) PURE;
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID FAR* ppvResult) PURE;
+ STDMETHOD(BindToStorage) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD(Reduce) (THIS_ LPBC pbc, DWORD dwReduceHowFar, LPMONIKER FAR*
+ ppmkToLeft, LPMONIKER FAR * ppmkReduced) PURE;
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNotGeneric,
+ LPMONIKER FAR* ppmkComposite) PURE;
+ STDMETHOD(Enum) (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker)
+ PURE;
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker) PURE;
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash) PURE;
+ STDMETHOD(IsRunning) (THIS_ LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+ pmkNewlyRunning) PURE;
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR __out * pfiletime) PURE;
+ STDMETHOD(Inverse) (THIS_ LPMONIKER FAR* ppmk) PURE;
+ STDMETHOD(CommonPrefixWith) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix) PURE;
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath) PURE;
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPSTR FAR* lplpszDisplayName) PURE;
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut) PURE;
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys) PURE;
+};
+typedef IMoniker FAR* LPMONIKER;
+
+
+// IRunningObjectTable::Register flags
+#define ROTFLAGS_REGISTRATIONKEEPSALIVE 1
+
+#undef INTERFACE
+#define INTERFACE IRunningObjectTable
+
+DECLARE_INTERFACE_(IRunningObjectTable, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IRunningObjectTable methods ***
+ STDMETHOD(Register) (THIS_ DWORD grfFlags, LPUNKNOWN punkObject,
+ LPMONIKER pmkObjectName, DWORD FAR * pdwRegister) PURE;
+ STDMETHOD(Revoke) (THIS_ DWORD dwRegister) PURE;
+ STDMETHOD(IsRunning) (THIS_ LPMONIKER pmkObjectName) PURE;
+ STDMETHOD(GetObject) (THIS_ LPMONIKER pmkObjectName,
+ LPUNKNOWN FAR* ppunkObject) PURE;
+ STDMETHOD(NoteChangeTime) (THIS_ DWORD dwRegister, FILETIME FAR __in * pfiletime) PURE;
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPMONIKER pmkObjectName, FILETIME FAR __out * pfiletime) PURE;
+ STDMETHOD(EnumRunning) (THIS_ LPENUMMONIKER FAR * ppenumMoniker ) PURE;
+};
+typedef IRunningObjectTable FAR* LPRUNNINGOBJECTTABLE;
+
+
+
+#undef INTERFACE
+#define INTERFACE IEnumMoniker
+
+DECLARE_INTERFACE_(IEnumMoniker, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumOleDataObject methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, LPMONIKER FAR* rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumMoniker FAR* FAR* ppenm) PURE;
+};
+typedef IEnumMoniker FAR* LPENUMMONIKER;
+
+
+
+
+STDAPI BindMoniker(LPMONIKER pmk, DWORD grfOpt, REFIID iidResult, LPVOID FAR* ppvResult);
+STDAPI MkParseDisplayName(LPBC pbc, LPSTR szUserName,
+ ULONG FAR * pchEaten, LPMONIKER FAR * ppmk);
+STDAPI MonikerRelativePathTo(LPMONIKER pmkSrc, LPMONIKER pmkDest, LPMONIKER
+ FAR* ppmkRelPath, BOOL fCalledFromMethod);
+STDAPI MonikerCommonPrefixWith(LPMONIKER pmkThis, LPMONIKER pmkOther,
+ LPMONIKER FAR* ppmkCommon);
+STDAPI CreateBindCtx(DWORD reserved, LPBC FAR* ppbc);
+STDAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest,
+ LPMONIKER FAR* ppmkComposite);
+STDAPI GetClassFile (LPCSTR szFilename, CLSID FAR* pclsid);
+
+STDAPI CreateFileMoniker(LPSTR lpszPathName, LPMONIKER FAR* ppmk);
+STDAPI CreateItemMoniker(LPSTR lpszDelim, LPSTR lpszItem,
+ LPMONIKER FAR* ppmk);
+STDAPI CreateAntiMoniker(LPMONIKER FAR* ppmk);
+STDAPI CreatePointerMoniker(LPUNKNOWN punk, LPMONIKER FAR* ppmk);
+
+STDAPI GetRunningObjectTable( DWORD reserved, LPRUNNINGOBJECTTABLE FAR* pprot);
+
+
+#endif // _MONIKER_H_
diff --git a/private/ole32/olethunk/thc/thpp/ole1cls.h b/private/ole32/olethunk/thc/thpp/ole1cls.h
new file mode 100644
index 000000000..eeae62ba4
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/ole1cls.h
@@ -0,0 +1,141 @@
+/*****************************************************************************\
+* *
+* ole1cls.h - Master definition of GUIDs for OLE1 classes *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+/* This file is the master definition of all GUIDs for OLE1 classes.
+
+ All such GUIDs are of the form:
+
+ 0003xxxx-0000-0000-C000-000000000046
+
+ The last parameter to DEFINE_OLE1GUID is the old 1.0 class name,
+ i.e., its key in the registration database.
+
+ Do not remove or change GUIDs.
+
+ Do not add anything to this file except comments and DEFINE_OLE1GUID macros.
+*/
+
+#ifndef DEFINE_OLE1GUID
+#define DEFINE_OLE1GUID(a,b,c,d,e) DEFINE_OLEGUID (a,b,c,d)
+#endif
+
+DEFINE_OLE1GUID(CLSID_ExcelWorksheet, 0x00030000, 0, 0, "ExcelWorksheet");
+DEFINE_OLE1GUID(CLSID_ExcelChart, 0x00030001, 0, 0, "ExcelChart");
+DEFINE_OLE1GUID(CLSID_ExcelMacrosheet, 0x00030002, 0, 0, "ExcelMacrosheet");
+DEFINE_OLE1GUID(CLSID_WordDocument, 0x00030003, 0, 0, "WordDocument");
+DEFINE_OLE1GUID(CLSID_MSPowerPoint, 0x00030004, 0, 0, "MSPowerPoint");
+DEFINE_OLE1GUID(CLSID_MSPowerPointSho, 0x00030005, 0, 0, "MSPowerPointSho");
+DEFINE_OLE1GUID(CLSID_MSGraph, 0x00030006, 0, 0, "MSGraph");
+DEFINE_OLE1GUID(CLSID_MSDraw, 0x00030007, 0, 0, "MSDraw");
+DEFINE_OLE1GUID(CLSID_Note_It, 0x00030008, 0, 0, "Note-It");
+DEFINE_OLE1GUID(CLSID_WordArt, 0x00030009, 0, 0, "WordArt");
+DEFINE_OLE1GUID(CLSID_PBrush, 0x0003000a, 0, 0, "PBrush");
+DEFINE_OLE1GUID(CLSID_Equation, 0x0003000b, 0, 0, "Equation");
+DEFINE_OLE1GUID(CLSID_Package, 0x0003000c, 0, 0, "Package");
+DEFINE_OLE1GUID(CLSID_SoundRec, 0x0003000d, 0, 0, "SoundRec");
+DEFINE_OLE1GUID(CLSID_MPlayer, 0x0003000e, 0, 0, "MPlayer");
+
+/* test apps */
+DEFINE_OLE1GUID(CLSID_ServerDemo, 0x0003000f, 0, 0, "ServerDemo");
+DEFINE_OLE1GUID(CLSID_Srtest, 0x00030010, 0, 0, "Srtest");
+DEFINE_OLE1GUID(CLSID_SrtInv, 0x00030011, 0, 0, "SrtInv");
+DEFINE_OLE1GUID(CLSID_OleDemo, 0x00030012, 0, 0, "OleDemo");
+
+/* External ISVs */
+// Coromandel / Dorai Swamy / 718-793-7963
+DEFINE_OLE1GUID(CLSID_CoromandelIntegra, 0x00030013, 0, 0, "CoromandelIntegra");
+DEFINE_OLE1GUID(CLSID_CoromandelObjServer,0x00030014, 0, 0, "CoromandelObjServer");
+
+// 3-d Visions Corp / Peter Hirsch / 310-325-1339
+DEFINE_OLE1GUID(CLSID_StanfordGraphics, 0x00030015, 0, 0, "StanfordGraphics");
+
+// Deltapoint / Nigel Hearne / 408-648-4000
+DEFINE_OLE1GUID(CLSID_DGraphCHART, 0x00030016, 0, 0, "DGraphCHART");
+DEFINE_OLE1GUID(CLSID_DGraphDATA, 0x00030017, 0, 0, "DGraphDATA");
+
+// Corel / Richard V. Woodend / 613-728-8200 x1153
+DEFINE_OLE1GUID(CLSID_PhotoPaint, 0x00030018, 0, 0, "PhotoPaint");
+DEFINE_OLE1GUID(CLSID_CShow, 0x00030019, 0, 0, "CShow");
+DEFINE_OLE1GUID(CLSID_CorelChart, 0x0003001a, 0, 0, "CorelChart");
+DEFINE_OLE1GUID(CLSID_CDraw, 0x0003001b, 0, 0, "CDraw");
+
+// Inset Systems / Mark Skiba / 203-740-2400
+DEFINE_OLE1GUID(CLSID_HJWIN1_0, 0x0003001c, 0, 0, "HJWIN1.0");
+
+// Mark V Systems / Mark McGraw / 818-995-7671
+DEFINE_OLE1GUID(CLSID_ObjMakerOLE, 0x0003001d, 0, 0, "ObjMakerOLE");
+
+// IdentiTech / Mike Gilger / 407-951-9503
+DEFINE_OLE1GUID(CLSID_FYI, 0x0003001e, 0, 0, "FYI");
+DEFINE_OLE1GUID(CLSID_FYIView, 0x0003001f, 0, 0, "FYIView");
+
+// Inventa Corporation / Balaji Varadarajan / 408-987-0220
+DEFINE_OLE1GUID(CLSID_Stickynote, 0x00030020, 0, 0, "Stickynote");
+
+// ShapeWare Corp. / Lori Pearce / 206-467-6723
+DEFINE_OLE1GUID(CLSID_ShapewareVISIO10, 0x00030021, 0, 0, "ShapewareVISIO10");
+DEFINE_OLE1GUID(CLSID_ImportServer, 0x00030022, 0, 0, "ImportServer");
+
+
+// test app SrTest
+DEFINE_OLE1GUID(CLSID_SrvrTest, 0x00030023, 0, 0, "SrvrTest");
+
+// Special clsid for when a 1.0 client pastes an embedded object
+// that is a link.
+// **This CLSID is obsolete. Do not reuse number.
+//DEFINE_OLE1GUID(CLSID_10EmbedObj, 0x00030024, 0, 0, "OLE2_Embedded_Link");
+
+// test app ClTest. Doesn't really work as a server but is in reg db
+DEFINE_OLE1GUID(CLSID_ClTest, 0x00030025, 0, 0, "Cltest");
+
+// Microsoft ClipArt Gallery Sherry Larsen-Holmes
+DEFINE_OLE1GUID(CLSID_MS_ClipArt_Gallery,0x00030026, 0, 0, "MS_ClipArt_Gallery");
+
+// Microsoft Project Cory Reina
+DEFINE_OLE1GUID(CLSID_MSProject, 0x00030027, 0, 0, "MSProject");
+
+// Microsoft Works Chart
+DEFINE_OLE1GUID(CLSID_MSWorksChart, 0x00030028, 0, 0, "MSWorksChart");
+
+// Microsoft Works Spreadsheet
+DEFINE_OLE1GUID(CLSID_MSWorksSpreadsheet,0x00030029, 0, 0, "MSWorksSpreadsheet");
+
+// AFX apps - Dean McCrory
+DEFINE_OLE1GUID(CLSID_MinSvr, 0x0003002A, 0, 0, "MinSvr");
+DEFINE_OLE1GUID(CLSID_HierarchyList, 0x0003002B, 0, 0, "HierarchyList");
+DEFINE_OLE1GUID(CLSID_BibRef, 0x0003002C, 0, 0, "BibRef");
+DEFINE_OLE1GUID(CLSID_MinSvrMI, 0x0003002D, 0, 0, "MinSvrMI");
+DEFINE_OLE1GUID(CLSID_TestServ, 0x0003002E, 0, 0, "TestServ");
+
+// Ami Pro
+DEFINE_OLE1GUID(CLSID_AmiProDocument, 0x0003002F, 0, 0, "AmiProDocument");
+
+// WordPerfect Presentations For Windows
+DEFINE_OLE1GUID(CLSID_WPGraphics, 0x00030030, 0, 0, "WPGraphics");
+DEFINE_OLE1GUID(CLSID_WPCharts, 0x00030031, 0, 0, "WPCharts");
+
+
+// MicroGrafx Charisma
+DEFINE_OLE1GUID(CLSID_Charisma, 0x00030032, 0, 0, "Charisma");
+DEFINE_OLE1GUID(CLSID_Charisma_30, 0x00030033, 0, 0, "Charisma_30");
+DEFINE_OLE1GUID(CLSID_CharPres_30, 0x00030034, 0, 0, "CharPres_30");
+
+// MicroGrafx Draw
+DEFINE_OLE1GUID(CLSID_Draw, 0x00030035, 0, 0, "Draw");
+
+// MicroGrafx Designer
+DEFINE_OLE1GUID(CLSID_Designer_40, 0x00030036, 0, 0, "Designer_40");
+
+
+#undef DEFINE_OLE1GUID
+
+/* as we discover OLE 1 servers we will add them to the end of this list;
+ there is room for 64K of them!
+*/
diff --git a/private/ole32/olethunk/thc/thpp/ole2.h b/private/ole32/olethunk/thc/thpp/ole2.h
new file mode 100644
index 000000000..1126479d0
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/ole2.h
@@ -0,0 +1,1336 @@
+/*****************************************************************************\
+* *
+* ole2.h - Main OLE2 header; includes all subcomponents *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#if !defined( _OLE2_H_ )
+#define _OLE2_H_
+
+#ifndef RC_INVOKED
+#pragma warning(disable:4001)
+#endif /* RC_INVOKED */
+
+#include <string.h>
+
+/****** Standard Object Definitions *****************************************/
+
+#include <compobj.h>
+
+
+// *************** FACILITY_ITF scodes common to all interfaces ************
+//
+// By convention, OLE interfaces divide the FACILITY_ITF range of errors
+// into nonoverlapping subranges. If an interface returns a FACILITY_ITF
+// scode, it must be from the range associated with that interface or from
+// the shared range: OLE_E_FIRST...OLE_E_LAST.
+//
+
+// error codes
+
+#define OLE_E_OLEVERB (OLE_E_FIRST)
+// invalid OLEVERB structure
+
+#define OLE_E_ADVF (OLE_E_FIRST+1)
+// invalid advise flags
+
+#define OLE_E_ENUM_NOMORE (OLE_E_FIRST+2)
+// you can't enuemrate any more, because the associated data is missing
+
+#define OLE_E_ADVISENOTSUPPORTED (OLE_E_FIRST+3)
+// this implementation doesn't take advises
+
+#define OLE_E_NOCONNECTION (OLE_E_FIRST+4)
+// there is no connection for this connection id
+
+#define OLE_E_NOTRUNNING (OLE_E_FIRST+5)
+// need run the object to perform this operation
+
+#define OLE_E_NOCACHE (OLE_E_FIRST+6)
+// there is no cache to operate on
+
+#define OLE_E_BLANK (OLE_E_FIRST+7)
+// Uninitialized object
+
+#define OLE_E_CLASSDIFF (OLE_E_FIRST+8)
+// linked object's source class has changed
+
+#define OLE_E_CANT_GETMONIKER (OLE_E_FIRST+9)
+// not able to get the moniker of the object
+
+#define OLE_E_CANT_BINDTOSOURCE (OLE_E_FIRST+10)
+// not able to bind to the source
+
+#define OLE_E_STATIC (OLE_E_FIRST+11)
+// object is static, operation not allowed
+
+#define OLE_E_PROMPTSAVECANCELLED (OLE_E_FIRST+12)
+// user cancelled out of save dialog
+
+#define OLE_E_INVALIDRECT (OLE_E_FIRST+13)
+// invalid rectangle
+
+#define OLE_E_WRONGCOMPOBJ (OLE_E_FIRST+14)
+// compobj.dll is too old for the ole2.dll initialized
+
+#define OLE_E_INVALIDHWND (OLE_E_FIRST+15)
+// invalid window handle
+
+#define OLE_E_NOT_INPLACEACTIVE (OLE_E_FIRST+16)
+// object is not in any of the inplace active states
+
+#define OLE_E_CANTCONVERT (OLE_E_FIRST+17)
+// not able to convert the object
+
+#define OLE_E_NOSTORAGE (OLE_E_FIRST+18)
+// not able to perform the operation because object is not given storage yet.
+
+
+#define DVGEN_E_FIRST (OLE_E_FIRST+100)
+
+#define DV_E_FORMATETC (DVGEN_E_FIRST)
+// invalid FORMATETC structure
+
+#define DV_E_DVTARGETDEVICE (DVGEN_E_FIRST+1)
+// invalid DVTARGETDEVICE structure
+
+#define DV_E_STGMEDIUM (DVGEN_E_FIRST+2)
+// invalid STDGMEDIUM structure
+
+#define DV_E_STATDATA (DVGEN_E_FIRST+3)
+// invalid STATDATA structure
+
+#define DV_E_LINDEX (DVGEN_E_FIRST+4)
+// invalid lindex
+
+#define DV_E_TYMED (DVGEN_E_FIRST+5)
+// invalid tymed
+
+#define DV_E_CLIPFORMAT (DVGEN_E_FIRST+6)
+// invalid clipboard format
+
+#define DV_E_DVASPECT (DVGEN_E_FIRST+7)
+// invalid aspect(s)
+
+#define DV_E_DVTARGETDEVICE_SIZE (DVGEN_E_FIRST+8)
+// tdSize paramter of the DVTARGETDEVICE structure is invalid
+
+#define DV_E_NOIVIEWOBJECT (DVGEN_E_FIRST+9)
+// object doesn't support IViewObject interface
+
+
+// Success codes
+
+#define OLE_S_USEREG (OLE_S_FIRST)
+// use the reg database to provide the requested info
+
+#define OLE_S_STATIC (OLE_S_FIRST+1)
+// success, but static
+
+#define OLE_S_MAC_CLIPFORMAT (OLE_S_FIRST+2)
+// macintosh clipboard format
+
+//*************************** Interface or API specific scodes *************
+
+// Errors for OleConvertOLESTREAMToIStorage and OleConvertIStorageToOLESTREAM
+
+// OLESTREAM Get method failed
+#define CONVERT10_E_OLESTREAM_GET (CONVERT10_E_FIRST + 0)
+
+// OLESTREAM Put method failed
+#define CONVERT10_E_OLESTREAM_PUT (CONVERT10_E_FIRST + 1)
+
+// Contents of the OLESTREAM not in correct format
+#define CONVERT10_E_OLESTREAM_FMT (CONVERT10_E_FIRST + 2)
+
+// There was in an error in a Windows GDI call while converting the bitmap
+// to a DIB.
+#define CONVERT10_E_OLESTREAM_BITMAP_TO_DIB (CONVERT10_E_FIRST + 3)
+
+// Contents of the IStorage not in correct format
+#define CONVERT10_E_STG_FMT (CONVERT10_E_FIRST + 4)
+
+// Contents of IStorage is missing one of the standard streams ("\1CompObj",
+// "\1Ole", "\2OlePres000"). This may be the storage for a DLL object, or a
+// class that does not use the def handler.
+#define CONVERT10_E_STG_NO_STD_STREAM (CONVERT10_E_FIRST + 5)
+
+// There was in an error in a Windows GDI call while converting the DIB
+// to a bitmap.
+#define CONVERT10_E_STG_DIB_TO_BITMAP (CONVERT10_E_FIRST + 6)
+
+
+// Returned by either API, this scode indicates that the original object
+// had no presentation, therefore the converted object does not either.
+#define CONVERT10_S_NO_PRESENTATION (CONVERT10_S_FIRST + 0)
+
+
+// Errors for Clipboard functions
+
+// OpenClipboard Failed
+#define CLIPBRD_E_CANT_OPEN (CLIPBRD_E_FIRST + 0)
+
+// EmptyClipboard Failed
+#define CLIPBRD_E_CANT_EMPTY (CLIPBRD_E_FIRST + 1)
+
+// SetClipboard Failed
+#define CLIPBRD_E_CANT_SET (CLIPBRD_E_FIRST + 2)
+
+// Data on clipboard is invalid
+#define CLIPBRD_E_BAD_DATA (CLIPBRD_E_FIRST + 3)
+
+// CloseClipboard Failed
+#define CLIPBRD_E_CANT_CLOSE (CLIPBRD_E_FIRST + 4)
+
+
+/****** OLE value types *****************************************************/
+
+/* rendering options */
+typedef enum tagOLERENDER
+{
+ OLERENDER_NONE = 0,
+ OLERENDER_DRAW = 1,
+ OLERENDER_FORMAT = 2,
+ OLERENDER_ASIS = 3
+} OLERENDER;
+typedef OLERENDER FAR* LPOLERENDER;
+
+// OLE verb; returned by IEnumOLEVERB
+typedef struct FARSTRUCT tagOLEVERB
+{
+ LONG lVerb;
+ LPSTR lpszVerbName;
+ DWORD fuFlags;
+ DWORD grfAttribs;
+} OLEVERB, FAR* LPOLEVERB;
+
+
+// Bitwise verb attributes used in OLEVERB.grfAttribs
+typedef enum tagOLEVERBATTRIB // bitwise
+{
+ OLEVERBATTRIB_NEVERDIRTIES = 1,
+ OLEVERBATTRIB_ONCONTAINERMENU = 2
+} OLEVERBATTRIB;
+
+
+// IOleObject::GetUserType optons; determines which form of the string to use
+typedef enum tagUSERCLASSTYPE
+{
+ USERCLASSTYPE_FULL = 1,
+ USERCLASSTYPE_SHORT= 2,
+ USERCLASSTYPE_APPNAME= 3,
+} USERCLASSTYPE;
+
+
+// bits returned from IOleObject::GetMistStatus
+typedef enum tagOLEMISC // bitwise
+{
+ OLEMISC_RECOMPOSEONRESIZE = 1,
+ OLEMISC_ONLYICONIC = 2,
+ OLEMISC_INSERTNOTREPLACE = 4,
+ OLEMISC_STATIC = 8,
+ OLEMISC_CANTLINKINSIDE = 16,
+ OLEMISC_CANLINKBYOLE1 = 32,
+ OLEMISC_ISLINKOBJECT = 64,
+ OLEMISC_INSIDEOUT = 128,
+ OLEMISC_ACTIVATEWHENVISIBLE = 256,
+ OLEMISC_RENDERINGISDEVICEINDEPENDENT = 512
+} OLEMISC;
+
+
+// IOleObject::Close options
+typedef enum tagOLECLOSE
+{
+ OLECLOSE_SAVEIFDIRTY = 0,
+ OLECLOSE_NOSAVE = 1,
+ OLECLOSE_PROMPTSAVE = 2
+} OLECLOSE;
+
+
+// IOleObject::GetMoniker and IOleClientSite::GetMoniker options; determines
+// if and how monikers should be assigned.
+typedef enum tagOLEGETMONIKER
+{
+ OLEGETMONIKER_ONLYIFTHERE=1,
+ OLEGETMONIKER_FORCEASSIGN=2,
+ OLEGETMONIKER_UNASSIGN=3,
+ OLEGETMONIKER_TEMPFORUSER=4
+} OLEGETMONIKER;
+
+
+// IOleObject::GetMoniker, IOleObject::SetMoniker and
+// IOleClientSite::GetMoniker options; determines which moniker to use
+typedef enum tagOLEWHICHMK
+{
+ OLEWHICHMK_CONTAINER=1,
+ OLEWHICHMK_OBJREL=2,
+ OLEWHICHMK_OBJFULL=3
+} OLEWHICHMK;
+
+
+#ifdef WIN32
+#define LPSIZEL PSIZEL
+#else
+typedef struct FARSTRUCT tagSIZEL
+{
+ long cx;
+ long cy;
+} SIZEL, FAR* LPSIZEL;
+#endif
+
+
+#ifdef WIN32
+#define LPRECTL PRECTL
+#else
+typedef struct FARSTRUCT tagRECTL
+{
+ long left;
+ long top;
+ long right;
+ long bottom;
+} RECTL, FAR* LPRECTL;
+
+typedef struct FARSTRUCT tagPOINTL {
+ LONG x;
+ LONG y;
+} POINTL;
+
+#endif
+
+
+#ifndef LPCRECT
+typedef const RECT FAR* LPCRECT;
+#endif
+
+#ifndef LPCRECTL
+typedef const RECTL FAR* LPCRECTL;
+#endif
+
+
+// for OleCreateEmbeddingHelper flags; roles in low word; options in high word
+#define EMBDHLP_INPROC_HANDLER 0x0000L // role is handler; implementation is
+ // default handler; pCF can be NULL
+#define EMBDHLP_INPROC_SERVER 0x0001L // role is server; pCF can't be NULL
+
+#define EMBDHLP_CREATENOW 0x00000000L // create using pCF immediately; if pCF
+ // is NULL, uses std remoting handler
+#define EMBDHLP_DELAYCREATE 0x00010000L // delayed create; must supply pCF
+
+
+// NOTE: OleCreateEmbeddingHelper(clsid, pUnkOuter,
+// EMBDHLP_INPROC_HANDLER | EMBDHLP_CREATENOW, NULL, riid, lplpObj)
+// is the same as OleCreateDefaultHandler(clsid, pUnkOuter, riid, lplpObj);
+// i.e., the embedding helper is the default handler in various roles.
+
+
+/***** OLE 1.0 OLESTREAM declarations *************************************/
+
+typedef struct _OLESTREAM FAR* LPOLESTREAM;
+
+typedef struct _OLESTREAMVTBL
+{
+ DWORD (CALLBACK* Get)(LPOLESTREAM, void FAR*, DWORD);
+ DWORD (CALLBACK* Put)(LPOLESTREAM, const void FAR*, DWORD);
+} OLESTREAMVTBL;
+typedef OLESTREAMVTBL FAR* LPOLESTREAMVTBL;
+
+typedef struct _OLESTREAM
+{
+ LPOLESTREAMVTBL lpstbl;
+} OLESTREAM;
+
+
+/****** Clipboard Data structures *****************************************/
+
+typedef struct tagOBJECTDESCRIPTOR
+{
+ ULONG cbSize; // Size of structure in bytes
+ CLSID clsid; // CLSID of data being transferred
+ DWORD dwDrawAspect; // Display aspect of the object
+ // normally DVASPECT_CONTENT or ICON.
+ // dwDrawAspect will be 0 (which is NOT
+ // DVASPECT_CONTENT) if the copier or
+ // dragsource didn't draw the object to
+ // begin with.
+ SIZEL sizel; // size of the object in HIMETRIC
+ // sizel is opt.: will be (0,0) for apps
+ // which don't draw the object being
+ // transferred
+ POINTL pointl; // Offset in HIMETRIC units from the
+ // upper-left corner of the obj where the
+ // mouse went down for the drag.
+ // NOTE: y coordinates increase downward.
+ // x coordinates increase to right
+ // pointl is opt.; it is only meaningful
+ // if object is transfered via drag/drop.
+ // (0, 0) if mouse position is unspecified
+ // (eg. when obj transfered via clipboard)
+ DWORD dwStatus; // Misc. status flags for object. Flags are
+ // defined by OLEMISC enum. these flags
+ // are as would be returned
+ // by IOleObject::GetMiscStatus.
+ DWORD dwFullUserTypeName; // Offset from beginning of structure to
+ // null-terminated string that specifies
+ // Full User Type Name of the object.
+ // 0 indicates string not present.
+ DWORD dwSrcOfCopy; // Offset from beginning of structure to
+ // null-terminated string that specifies
+ // source of the transfer.
+ // dwSrcOfCOpy is normally implemented as
+ // the display name of the temp-for-user
+ // moniker which identifies the source of
+ // the data.
+ // 0 indicates string not present.
+ // NOTE: moniker assignment is NOT forced.
+ // see IOleObject::GetMoniker(
+ // OLEGETMONIKER_TEMPFORUSER)
+
+ /* variable sized string data may appear here */
+
+} OBJECTDESCRIPTOR, *POBJECTDESCRIPTOR, FAR *LPOBJECTDESCRIPTOR,
+ LINKSRCDESCRIPTOR, *PLINKSRCDESCRIPTOR, FAR *LPLINKSRCDESCRIPTOR;
+
+
+
+/* verbs */
+#define OLEIVERB_PRIMARY (0L)
+#define OLEIVERB_SHOW (-1L)
+#define OLEIVERB_OPEN (-2L)
+#define OLEIVERB_HIDE (-3L)
+#define OLEIVERB_UIACTIVATE (-4L)
+#define OLEIVERB_INPLACEACTIVATE (-5L)
+#define OLEIVERB_DISCARDUNDOSTATE (-6L)
+
+
+// forward type declarations
+#if defined(__cplusplus)
+interface IOleClientSite;
+interface IOleContainer;
+interface IOleObject;
+#else
+typedef interface IOleClientSite IOleClientSite;
+typedef interface IOleContainer IOleContainer;
+typedef interface IOleObject IOleObject;
+#endif
+
+typedef IOleObject FAR* LPOLEOBJECT;
+typedef IOleClientSite FAR* LPOLECLIENTSITE;
+typedef IOleContainer FAR* LPOLECONTAINER;
+
+
+/****** OLE GUIDs *********************************************************/
+
+#ifndef INITGUID
+#include "oleguid.h"
+#endif
+
+
+/****** Other Major Interfaces ********************************************/
+
+#include <dvobj.h>
+
+#include <storage.h>
+
+
+
+/****** IDrop??? Interfaces ********************************************/
+
+#define MK_ALT 0x0020
+
+
+#define DROPEFFECT_NONE 0
+#define DROPEFFECT_COPY 1
+#define DROPEFFECT_MOVE 2
+#define DROPEFFECT_LINK 4
+#define DROPEFFECT_SCROLL 0x80000000
+
+// default inset-width of the hot zone, in pixels
+// typical use: GetProfileInt("windows","DragScrollInset",DD_DEFSCROLLINSET)
+#define DD_DEFSCROLLINSET 11
+
+// default delay before scrolling, in milliseconds
+// typical use: GetProfileInt("windows","DragScrollDelay",DD_DEFSCROLLDELAY)
+#define DD_DEFSCROLLDELAY 50
+
+// default scroll interval, in milliseconds
+// typical use: GetProfileInt("windows","DragScrollInterval",
+// DD_DEFSCROLLINTERVAL)
+#define DD_DEFSCROLLINTERVAL 50
+
+// default delay before dragging should start, in milliseconds
+// typical use: GetProfileInt("windows", "DragDelay", DD_DEFDRAGDELAY)
+#define DD_DEFDRAGDELAY 200
+
+// default minimum distance (radius) before dragging should start, in pixels
+// typical use: GetProfileInt("windows", "DragMinDist", DD_DEFDRAGMINDIST)
+#define DD_DEFDRAGMINDIST 2
+
+
+
+/* Dragdrop specific error codes */
+
+#define DRAGDROP_E_NOTREGISTERED (DRAGDROP_E_FIRST)
+// trying to revoke a drop target that has not been registered
+
+#define DRAGDROP_E_ALREADYREGISTERED (DRAGDROP_E_FIRST+1)
+// this window has already been registered as a drop target
+
+#define DRAGDROP_E_INVALIDHWND (DRAGDROP_E_FIRST+2)
+// invalid HWND
+
+
+#define DRAGDROP_S_DROP (DRAGDROP_S_FIRST + 0)
+// successful drop took place
+
+#define DRAGDROP_S_CANCEL (DRAGDROP_S_FIRST + 1)
+// drag-drop operation canceled
+
+#define DRAGDROP_S_USEDEFAULTCURSORS (DRAGDROP_S_FIRST + 2)
+// use the default cursor
+
+
+#undef INTERFACE
+#define INTERFACE IDropTarget
+
+DECLARE_INTERFACE_(IDropTarget, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IDropTarget methods ***
+ STDMETHOD(DragEnter) (THIS_ LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, __in __out LPDWORD pdwEffect) PURE;
+ STDMETHOD(DragOver) (THIS_ DWORD grfKeyState, POINTL pt, __in __out LPDWORD pdwEffect) PURE;
+ STDMETHOD(DragLeave) (THIS) PURE;
+ STDMETHOD(Drop) (THIS_ LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, __in __out LPDWORD pdwEffect) PURE;
+};
+typedef IDropTarget FAR* LPDROPTARGET;
+
+
+
+#undef INTERFACE
+#define INTERFACE IDropSource
+
+DECLARE_INTERFACE_(IDropSource, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IDropSource methods ***
+ STDMETHOD(QueryContinueDrag) (THIS_ BOOL fEscapePressed, DWORD grfKeyState) PURE;
+ STDMETHOD(GiveFeedback) (THIS_ DWORD dwEffect) PURE;
+};
+typedef IDropSource FAR* LPDROPSOURCE;
+
+
+
+/****** IPersist??? Interfaces ********************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IPersist
+
+DECLARE_INTERFACE_(IPersist, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+};
+typedef IPersist FAR* LPPERSIST;
+
+
+
+#undef INTERFACE
+#define INTERFACE IPersistStorage
+
+DECLARE_INTERFACE_(IPersistStorage, IPersist)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+
+ // *** IPersistStorage methods ***
+ STDMETHOD(IsDirty) (THIS) PURE;
+ STDMETHOD(InitNew) (THIS_ LPSTORAGE pStg) PURE;
+ STDMETHOD(Load) (THIS_ LPSTORAGE pStg) PURE;
+ STDMETHOD(Save) (THIS_ LPSTORAGE pStgSave, BOOL fSameAsLoad) PURE;
+ STDMETHOD(SaveCompleted) (THIS_ LPSTORAGE pStgNew) PURE;
+ STDMETHOD(HandsOffStorage) (THIS) PURE;
+};
+typedef IPersistStorage FAR* LPPERSISTSTORAGE;
+
+
+
+#undef INTERFACE
+#define INTERFACE IPersistStream
+
+DECLARE_INTERFACE_(IPersistStream, IPersist)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+
+ // *** IPersistStream methods ***
+ STDMETHOD(IsDirty) (THIS) PURE;
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm) PURE;
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty) PURE;
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR* pcbSize) PURE;
+};
+typedef IPersistStream FAR* LPPERSISTSTREAM;
+
+
+
+#undef INTERFACE
+#define INTERFACE IPersistFile
+
+DECLARE_INTERFACE_(IPersistFile, IPersist)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+
+ // *** IPersistFile methods ***
+ STDMETHOD(IsDirty) (THIS) PURE;
+ STDMETHOD(Load) (THIS_ LPCSTR lpszFileName, DWORD grfMode) PURE;
+ STDMETHOD(Save) (THIS_ LPCSTR lpszFileName, BOOL fRemember) PURE;
+ STDMETHOD(SaveCompleted) (THIS_ LPCSTR lpszFileName) PURE;
+ STDMETHOD(GetCurFile) (THIS_ LPSTR FAR* lplpszFileName) PURE;
+};
+typedef IPersistFile FAR* LPPERSISTFILE;
+
+
+/****** Moniker Object Interfaces ******************************************/
+
+#include <moniker.h>
+
+
+/****** OLE Object Interfaces ******************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IEnumOLEVERB
+
+DECLARE_INTERFACE_(IEnumOLEVERB, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumOLEVERB methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, LPOLEVERB rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumOLEVERB FAR* FAR* ppenm) PURE;
+};
+typedef IEnumOLEVERB FAR* LPENUMOLEVERB;
+
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleObject
+
+#define OLEOBJ_E_NOVERBS (OLEOBJ_E_FIRST + 0)
+
+#define OLEOBJ_E_INVALIDVERB (OLEOBJ_E_FIRST + 1)
+
+#define OLEOBJ_S_INVALIDVERB (OLEOBJ_S_FIRST + 0)
+
+#define OLEOBJ_S_CANNOT_DOVERB_NOW (OLEOBJ_S_FIRST + 1)
+// verb number is valid but verb cannot be done now, for instance
+// hiding a link or hiding a visible OLE 1.0 server
+
+#define OLEOBJ_S_INVALIDHWND (OLEOBJ_S_FIRST + 2)
+// invalid hwnd passed
+
+
+DECLARE_INTERFACE_(IOleObject, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleObject methods ***
+ STDMETHOD(SetClientSite) (THIS_ LPOLECLIENTSITE pClientSite) PURE;
+ STDMETHOD(GetClientSite) (THIS_ LPOLECLIENTSITE FAR* ppClientSite) PURE;
+ STDMETHOD(SetHostNames) (THIS_ LPCSTR szContainerApp, LPCSTR szContainerObj) PURE;
+ STDMETHOD(Close) (THIS_ DWORD dwSaveOption) PURE;
+ STDMETHOD(SetMoniker) (THIS_ DWORD dwWhichMoniker, LPMONIKER pmk) PURE;
+ STDMETHOD(GetMoniker) (THIS_ DWORD dwAssign, DWORD dwWhichMoniker,
+ LPMONIKER FAR* ppmk) PURE;
+ STDMETHOD(InitFromData) (THIS_ LPDATAOBJECT pDataObject,
+ BOOL fCreation,
+ DWORD dwReserved) PURE;
+ STDMETHOD(GetClipboardData) (THIS_ DWORD dwReserved,
+ LPDATAOBJECT FAR* ppDataObject) PURE;
+ STDMETHOD(DoVerb) (THIS_ LONG iVerb,
+ LPMSG lpmsg,
+ LPOLECLIENTSITE pActiveSite,
+ LONG lindex,
+ HWND hwndParent,
+ __in LPCRECT lprcPosRect) PURE;
+ STDMETHOD(EnumVerbs) (THIS_ LPENUMOLEVERB FAR* ppenumOleVerb) PURE;
+ STDMETHOD(Update) (THIS) PURE;
+ STDMETHOD(IsUpToDate) (THIS) PURE;
+ STDMETHOD(GetUserClassID) (THIS_ CLSID FAR* pClsid) PURE;
+ STDMETHOD(GetUserType) (THIS_ DWORD dwFormOfType, LPSTR FAR* pszUserType) PURE;
+ STDMETHOD(SetExtent) (THIS_ DWORD dwDrawAspect, __in LPSIZEL lpsizel) PURE;
+ STDMETHOD(GetExtent) (THIS_ DWORD dwDrawAspect, __out LPSIZEL lpsizel) PURE;
+
+ STDMETHOD(Advise)(THIS_ LPADVISESINK pAdvSink, DWORD FAR* pdwConnection) PURE;
+ STDMETHOD(Unadvise)(THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumAdvise) (THIS_ LPENUMSTATDATA FAR* ppenumAdvise) PURE;
+ STDMETHOD(GetMiscStatus) (THIS_ DWORD dwAspect, DWORD FAR* pdwStatus) PURE;
+ STDMETHOD(SetColorScheme) (THIS_ LPLOGPALETTE lpLogpal) PURE;
+};
+typedef IOleObject FAR* LPOLEOBJECT;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleClientSite
+
+DECLARE_INTERFACE_(IOleClientSite, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleClientSite methods ***
+ STDMETHOD(SaveObject) (THIS) PURE;
+ STDMETHOD(GetMoniker) (THIS_ DWORD dwAssign, DWORD dwWhichMoniker,
+ LPMONIKER FAR* ppmk) PURE;
+ STDMETHOD(GetContainer) (THIS_ LPOLECONTAINER FAR* ppContainer) PURE;
+ STDMETHOD(ShowObject) (THIS) PURE;
+ STDMETHOD(OnShowWindow) (THIS_ BOOL fShow) PURE;
+ STDMETHOD(RequestNewObjectLayout) (THIS) PURE;
+};
+typedef IOleClientSite FAR* LPOLECLIENTSITE;
+
+
+/****** OLE Runnable Object Interface **********************************/
+
+#undef INTERFACE
+#define INTERFACE IRunnableObject
+
+DECLARE_INTERFACE_(IRunnableObject, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IRunnableObject methods ***
+ STDMETHOD(GetRunningClass) (THIS_ LPCLSID lpClsid) PURE;
+ STDMETHOD(Run) (THIS_ LPBINDCTX pbc) PURE;
+ STDMETHOD_(BOOL, IsRunning) (THIS) PURE;
+ STDMETHOD(LockRunning)(THIS_ BOOL fLock, BOOL fLastUnlockCloses) PURE;
+ STDMETHOD(SetContainedObject)(THIS_ BOOL fContained) PURE;
+};
+typedef IRunnableObject FAR* LPRUNNABLEOBJECT;
+
+
+/****** OLE Container Interfaces ***************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IParseDisplayName
+
+DECLARE_INTERFACE_(IParseDisplayName, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IParseDisplayName method ***
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPSTR lpszDisplayName,
+ ULONG FAR* pchEaten, LPMONIKER FAR* ppmkOut) PURE;
+};
+typedef IParseDisplayName FAR* LPPARSEDISPLAYNAME;
+
+
+#undef INTERFACE
+#define INTERFACE IOleContainer
+
+DECLARE_INTERFACE_(IOleContainer, IParseDisplayName)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IParseDisplayName method ***
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPSTR lpszDisplayName,
+ ULONG FAR* pchEaten, LPMONIKER FAR* ppmkOut) PURE;
+
+ // *** IOleContainer methods ***
+ STDMETHOD(EnumObjects) ( DWORD grfFlags, LPENUMUNKNOWN FAR* ppenumUnknown) PURE;
+ STDMETHOD(LockContainer) (THIS_ BOOL fLock) PURE;
+};
+typedef IOleContainer FAR* LPOLECONTAINER;
+
+
+typedef enum tagBINDSPEED
+{
+ BINDSPEED_INDEFINITE = 1,
+ BINDSPEED_MODERATE = 2,
+ BINDSPEED_IMMEDIATE = 3
+} BINDSPEED;
+
+typedef enum tagOLECONTF
+{
+ OLECONTF_EMBEDDINGS = 1,
+ OLECONTF_LINKS = 2,
+ OLECONTF_OTHERS = 4,
+ OLECONTF_ONLYUSER = 8,
+ OLECONTF_ONLYIFRUNNING = 16
+} OLECONTF;
+
+
+#undef INTERFACE
+#define INTERFACE IOleItemContainer
+
+DECLARE_INTERFACE_(IOleItemContainer, IOleContainer)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IParseDisplayName method ***
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPSTR lpszDisplayName,
+ ULONG FAR* pchEaten, LPMONIKER FAR* ppmkOut) PURE;
+
+ // *** IOleContainer methods ***
+ STDMETHOD(EnumObjects) (THIS_ DWORD grfFlags, LPENUMUNKNOWN FAR* ppenumUnknown) PURE;
+ STDMETHOD(LockContainer) (THIS_ BOOL fLock) PURE;
+
+ // *** IOleItemContainer methods ***
+ STDMETHOD(GetObject) (THIS_ LPSTR lpszItem, DWORD dwSpeedNeeded,
+ LPBINDCTX pbc, REFIID riid, LPVOID FAR* ppvObject) PURE;
+ STDMETHOD(GetObjectStorage) (THIS_ LPSTR lpszItem, LPBINDCTX pbc,
+ REFIID riid, LPVOID FAR* ppvStorage) PURE;
+ STDMETHOD(IsRunning) (THIS_ LPSTR lpszItem) PURE;
+};
+typedef IOleItemContainer FAR* LPOLEITEMCONTAINER;
+
+
+/****** OLE Advise Holder Interface ***************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IOleAdviseHolder
+
+DECLARE_INTERFACE_(IOleAdviseHolder, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleAdviseHolder methods ***
+ STDMETHOD(Advise)(THIS_ LPADVISESINK pAdvise, DWORD FAR* pdwConnection) PURE;
+ STDMETHOD(Unadvise)(THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumAdvise)(THIS_ LPENUMSTATDATA FAR* ppenumAdvise) PURE;
+
+ STDMETHOD(SendOnRename)(THIS_ LPMONIKER pmk) PURE;
+ STDMETHOD(SendOnSave)(THIS) PURE;
+ STDMETHOD(SendOnClose)(THIS) PURE;
+};
+typedef IOleAdviseHolder FAR* LPOLEADVISEHOLDER;
+
+
+/****** OLE Link Interface ************************************************/
+
+/* Link update options */
+typedef enum tagOLEUPDATE
+{
+ OLEUPDATE_ALWAYS=1,
+ OLEUPDATE_ONCALL=3
+} OLEUPDATE;
+typedef OLEUPDATE FAR* LPOLEUPDATE;
+
+
+// for IOleLink::BindToSource
+typedef enum tagOLELINKBIND
+{
+ OLELINKBIND_EVENIFCLASSDIFF = 1,
+} OLELINKBIND;
+
+
+#undef INTERFACE
+#define INTERFACE IOleLink
+
+DECLARE_INTERFACE_(IOleLink, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleLink methods ***
+ STDMETHOD(SetUpdateOptions) (THIS_ DWORD dwUpdateOpt) PURE;
+ STDMETHOD(GetUpdateOptions) (THIS_ LPDWORD pdwUpdateOpt) PURE;
+ STDMETHOD(SetSourceMoniker) (THIS_ LPMONIKER pmk, REFCLSID rclsid) PURE;
+ STDMETHOD(GetSourceMoniker) (THIS_ LPMONIKER FAR* ppmk) PURE;
+ STDMETHOD(SetSourceDisplayName) (THIS_ LPCSTR lpszDisplayName) PURE;
+ STDMETHOD(GetSourceDisplayName) (THIS_ LPSTR FAR* lplpszDisplayName) PURE;
+ STDMETHOD(BindToSource) (THIS_ DWORD bindflags, LPBINDCTX pbc) PURE;
+ STDMETHOD(BindIfRunning) (THIS) PURE;
+ STDMETHOD(GetBoundSource) (THIS_ LPUNKNOWN FAR* ppUnk) PURE;
+ STDMETHOD(UnbindSource) (THIS) PURE;
+ STDMETHOD(Update) (THIS_ LPBINDCTX pbc) PURE;
+};
+typedef IOleLink FAR* LPOLELINK;
+
+
+/****** OLE InPlace Editing Interfaces ************************************/
+
+#ifdef _MAC
+typedef Handle HOLEMENU;
+typedef long SIZE;
+typedef long HACCEL;
+#else
+DECLARE_HANDLE(HOLEMENU);
+#endif
+
+typedef struct FARSTRUCT tagOIFI // OleInPlaceFrameInfo
+{
+ UINT cb;
+ BOOL fMDIApp;
+ HWND hwndFrame;
+ HACCEL haccel;
+ int cAccelEntries;
+} OLEINPLACEFRAMEINFO, FAR* LPOLEINPLACEFRAMEINFO;
+
+
+typedef struct FARSTRUCT tagOleMenuGroupWidths
+{
+ LONG width[6];
+} OLEMENUGROUPWIDTHS, FAR* LPOLEMENUGROUPWIDTHS;
+
+typedef RECT BORDERWIDTHS;
+typedef LPRECT LPBORDERWIDTHS;
+typedef LPCRECT LPCBORDERWIDTHS;
+
+/* Inplace editing specific error codes */
+
+#define INPLACE_E_NOTUNDOABLE (INPLACE_E_FIRST)
+// undo is not avaiable
+
+#define INPLACE_E_NOTOOLSPACE (INPLACE_E_FIRST+1)
+// Space for tools is not available
+
+#define INPLACE_S_TRUNCATED (INPLACE_S_FIRST)
+// Message is too long, some of it had to be truncated before displaying
+
+//misc definitions
+#define INPLACE_DEFBORDERWIDTH 4
+
+// forward type declarations
+#if defined(__cplusplus)
+interface IOleInPlaceUIWindow;
+#else
+typedef interface IOleInPlaceUIWindow IOleInPlaceUIWindow;
+#endif
+
+typedef IOleInPlaceUIWindow FAR* LPOLEINPLACEUIWINDOW;
+
+
+#undef INTERFACE
+#define INTERFACE IOleWindow
+
+DECLARE_INTERFACE_(IOleWindow, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+};
+
+typedef IOleWindow FAR* LPOLEWINDOW;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceObject
+
+DECLARE_INTERFACE_(IOleInPlaceObject, IOleWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceObject methods ***
+ STDMETHOD(InPlaceDeactivate) (THIS) PURE;
+ STDMETHOD(UIDeactivate) (THIS) PURE;
+ STDMETHOD(SetObjectRects) (THIS_ __in LPCRECT lprcPosRect,
+ __in LPCRECT lprcClipRect) PURE;
+ STDMETHOD(ReactivateAndUndo) (THIS) PURE;
+};
+typedef IOleInPlaceObject FAR* LPOLEINPLACEOBJECT;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceActiveObject
+
+DECLARE_INTERFACE_(IOleInPlaceActiveObject, IOleWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceActiveObject methods ***
+ STDMETHOD(TranslateAccelerator) (THIS_ LPMSG lpmsg) PURE;
+ STDMETHOD(OnFrameWindowActivate) (THIS_ BOOL fActivate) PURE;
+ STDMETHOD(OnDocWindowActivate) (THIS_ BOOL fActivate) PURE;
+ STDMETHOD(ResizeBorder) (THIS_ __in LPCRECT lprectBorder, LPOLEINPLACEUIWINDOW lpUIWindow, BOOL fFrameWindow) PURE;
+ STDMETHOD(EnableModeless) (THIS_ BOOL fEnable) PURE;
+};
+typedef IOleInPlaceActiveObject FAR* LPOLEINPLACEACTIVEOBJECT;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceUIWindow
+
+DECLARE_INTERFACE_(IOleInPlaceUIWindow, IOleWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceUIWindow methods ***
+ STDMETHOD(GetBorder) (THIS_ __out LPRECT lprectBorder) PURE;
+ STDMETHOD(RequestBorderSpace) (THIS_ __in LPCBORDERWIDTHS lpborderwidths) PURE;
+ STDMETHOD(SetBorderSpace) (THIS_ __in LPCBORDERWIDTHS lpborderwidths) PURE;
+ STDMETHOD(SetActiveObject) (THIS_ LPOLEINPLACEACTIVEOBJECT lpActiveObject,
+ LPCSTR lpszObjName) PURE;
+};
+typedef IOleInPlaceUIWindow FAR* LPOLEINPLACEUIWINDOW;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceFrame
+
+DECLARE_INTERFACE_(IOleInPlaceFrame, IOleInPlaceUIWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceUIWindow methods ***
+ STDMETHOD(GetBorder) (THIS_ __out LPRECT lprectBorder) PURE;
+ STDMETHOD(RequestBorderSpace) (THIS_ __in LPCBORDERWIDTHS lpborderwidths) PURE;
+ STDMETHOD(SetBorderSpace) (THIS_ __in LPCBORDERWIDTHS lpborderwidths) PURE;
+ STDMETHOD(SetActiveObject) (THIS_ LPOLEINPLACEACTIVEOBJECT lpActiveObject,
+ LPCSTR lpszObjName) PURE;
+
+
+ // *** IOleInPlaceFrame methods ***
+ STDMETHOD(InsertMenus) (THIS_ HMENU hmenuShared, __in __out LPOLEMENUGROUPWIDTHS lpMenuWidths) PURE;
+ STDMETHOD(SetMenu) (THIS_ HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) PURE;
+ STDMETHOD(RemoveMenus) (THIS_ HMENU hmenuShared) PURE;
+ STDMETHOD(SetStatusText) (THIS_ LPCSTR lpszStatusText) PURE;
+ STDMETHOD(EnableModeless) (THIS_ BOOL fEnable) PURE;
+ STDMETHOD(TranslateAccelerator) (THIS_ LPMSG lpmsg, WORD wID) PURE;
+};
+typedef IOleInPlaceFrame FAR* LPOLEINPLACEFRAME;
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceSite
+
+DECLARE_INTERFACE_(IOleInPlaceSite, IOleWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceSite methods ***
+ STDMETHOD(CanInPlaceActivate) (THIS) PURE;
+ STDMETHOD(OnInPlaceActivate) (THIS) PURE;
+ STDMETHOD(OnUIActivate) (THIS) PURE;
+ STDMETHOD(GetWindowContext) (THIS_ LPOLEINPLACEFRAME FAR* lplpFrame,
+ LPOLEINPLACEUIWINDOW FAR* lplpDoc,
+ __out LPRECT lprcPosRect,
+ __out LPRECT lprcClipRect,
+ __out LPOLEINPLACEFRAMEINFO lpFrameInfo) PURE;
+ STDMETHOD(Scroll) (THIS_ SIZE scrollExtent) PURE;
+ STDMETHOD(OnUIDeactivate) (THIS_ BOOL fUndoable) PURE;
+ STDMETHOD(OnInPlaceDeactivate) (THIS) PURE;
+ STDMETHOD(DiscardUndoState) (THIS) PURE;
+ STDMETHOD(DeactivateAndUndo) (THIS) PURE;
+ STDMETHOD(OnPosRectChange) (THIS_ __in LPCRECT lprcPosRect) PURE;
+};
+typedef IOleInPlaceSite FAR* LPOLEINPLACESITE;
+
+
+
+/****** OLE API Prototypes ************************************************/
+
+STDAPI_(DWORD) OleBuildVersion( VOID );
+
+/* helper functions */
+STDAPI ReadClassStg(LPSTORAGE pStg, CLSID FAR* pclsid);
+STDAPI WriteClassStg(LPSTORAGE pStg, REFCLSID rclsid);
+STDAPI ReadClassStm(LPSTREAM pStm, CLSID FAR* pclsid);
+STDAPI WriteClassStm(LPSTREAM pStm, REFCLSID rclsid);
+STDAPI WriteFmtUserTypeStg (LPSTORAGE pstg, CLIPFORMAT cf, LPSTR lpszUserType);
+STDAPI ReadFmtUserTypeStg (LPSTORAGE pstg, CLIPFORMAT FAR* pcf, LPSTR FAR* lplpszUserType);
+
+
+/* init/term */
+
+STDAPI OleInitialize(LPMALLOC pMalloc);
+STDAPI_(void) OleUninitialize(void);
+
+
+/* APIs to query whether (Embedded/Linked) object can be created from
+ the data object */
+
+STDAPI OleQueryLinkFromData(LPDATAOBJECT pSrcDataObject);
+STDAPI OleQueryCreateFromData(LPDATAOBJECT pSrcDataObject);
+
+
+/* Object creation APIs */
+
+STDAPI OleCreate(REFCLSID rclsid, REFIID riid, DWORD renderopt,
+ __in LPFORMATETC pFormatEtc, LPOLECLIENTSITE pClientSite,
+ LPSTORAGE pStg, LPVOID FAR* ppvObj);
+
+STDAPI OleCreateFromData(LPDATAOBJECT pSrcDataObj, REFIID riid,
+ DWORD renderopt, __in LPFORMATETC pFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
+ LPVOID FAR* ppvObj);
+
+STDAPI OleCreateLinkFromData(LPDATAOBJECT pSrcDataObj, REFIID riid,
+ DWORD renderopt, __in LPFORMATETC pFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
+ LPVOID FAR* ppvObj);
+
+STDAPI OleCreateStaticFromData(LPDATAOBJECT pSrcDataObj, REFIID iid,
+ DWORD renderopt, __in LPFORMATETC pFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
+ LPVOID FAR* ppvObj);
+
+
+STDAPI OleCreateLink(LPMONIKER pmkLinkSrc, REFIID riid,
+ DWORD renderopt, __in LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg, LPVOID FAR* ppvObj);
+
+STDAPI OleCreateLinkToFile(LPCSTR lpszFileName, REFIID riid,
+ DWORD renderopt, __in LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg, LPVOID FAR* ppvObj);
+
+STDAPI OleCreateFromFile(REFCLSID rclsid, LPCSTR lpszFileName, REFIID riid,
+ DWORD renderopt, __in LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg, LPVOID FAR* ppvObj);
+
+STDAPI OleLoad(LPSTORAGE pStg, REFIID riid, LPOLECLIENTSITE pClientSite,
+ LPVOID FAR* ppvObj);
+
+STDAPI OleSave(LPPERSISTSTORAGE pPS, LPSTORAGE pStg, BOOL fSameAsLoad);
+
+STDAPI OleLoadFromStream( LPSTREAM pStm, REFIID iidInterface, LPVOID FAR* ppvObj);
+STDAPI OleSaveToStream( LPPERSISTSTREAM pPStm, LPSTREAM pStm );
+
+
+STDAPI OleSetContainedObject(LPUNKNOWN pUnknown, BOOL fContained);
+STDAPI OleNoteObjectVisible(LPUNKNOWN pUnknown, BOOL fVisible);
+
+
+/* Drag/Drop APIs */
+
+STDAPI RegisterDragDrop(HWND hwnd, LPDROPTARGET pDropTarget);
+STDAPI RevokeDragDrop(HWND hwnd);
+STDAPI DoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
+ DWORD dwOKEffects, LPDWORD pdwEffect);
+
+/* Clipboard APIs */
+
+STDAPI OleSetClipboard(LPDATAOBJECT pDataObj);
+STDAPI OleGetClipboard(LPDATAOBJECT FAR* ppDataObj);
+STDAPI OleFlushClipboard(void);
+STDAPI OleIsCurrentClipboard(LPDATAOBJECT pDataObj);
+
+
+/* InPlace Editing APIs */
+
+STDAPI_(HOLEMENU) OleCreateMenuDescriptor (HMENU hmenuCombined,
+ __in LPOLEMENUGROUPWIDTHS lpMenuWidths);
+STDAPI OleSetMenuDescriptor (HOLEMENU holemenu, HWND hwndFrame,
+ HWND hwndActiveObject,
+ LPOLEINPLACEFRAME lpFrame,
+ LPOLEINPLACEACTIVEOBJECT lpActiveObj);
+STDAPI OleDestroyMenuDescriptor (HOLEMENU holemenu);
+
+STDAPI OleTranslateAccelerator (LPOLEINPLACEFRAME lpFrame,
+ LPOLEINPLACEFRAMEINFO lpFrameInfo, LPMSG lpmsg);
+
+
+/* Helper APIs */
+STDAPI_(HANDLE) OleDuplicateData (HANDLE hSrc, CLIPFORMAT cfFormat,
+ UINT uiFlags);
+
+STDAPI OleDraw (LPUNKNOWN pUnknown, DWORD dwAspect, HDC hdcDraw,
+ __in LPCRECT lprcBounds);
+
+STDAPI OleRun(LPUNKNOWN pUnknown);
+STDAPI_(BOOL) OleIsRunning(LPOLEOBJECT pObject);
+STDAPI OleLockRunning(LPUNKNOWN pUnknown, BOOL fLock, BOOL fLastUnlockCloses);
+
+STDAPI_(void) ReleaseStgMedium(LPSTGMEDIUM);
+STDAPI CreateOleAdviseHolder(LPOLEADVISEHOLDER FAR* ppOAHolder);
+
+STDAPI OleCreateDefaultHandler(REFCLSID clsid, LPUNKNOWN pUnkOuter,
+ REFIID riid, LPVOID FAR* lplpObj);
+
+STDAPI OleCreateEmbeddingHelper(REFCLSID clsid, LPUNKNOWN pUnkOuter,
+ DWORD flags, LPCLASSFACTORY pCF,
+ REFIID riid, LPVOID FAR* lplpObj);
+
+STDAPI_(BOOL) IsAccelerator(HACCEL hAccel, int cAccelEntries, LPMSG lpMsg,
+ WORD FAR* lpwCmd);
+
+
+/* Icon extraction Helper APIs */
+
+STDAPI_(HGLOBAL) OleGetIconOfFile(LPSTR lpszPath, BOOL fUseFileAsLabel);
+
+STDAPI_(HGLOBAL) OleGetIconOfClass(REFCLSID rclsid, LPSTR lpszLabel,
+ BOOL fUseTypeAsLabel);
+
+STDAPI_(HGLOBAL) OleMetafilePictFromIconAndLabel(HICON hIcon, LPSTR lpszLabel,
+ LPSTR lpszSourceFile, UINT iIconIndex);
+
+
+
+/* Registration Database Helper APIs */
+
+STDAPI OleRegGetUserType (REFCLSID clsid, DWORD dwFormOfType,
+ LPSTR FAR* pszUserType);
+
+STDAPI OleRegGetMiscStatus (REFCLSID clsid, DWORD dwAspect,
+ DWORD FAR* pdwStatus);
+
+STDAPI OleRegEnumFormatEtc (REFCLSID clsid, DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenum);
+
+STDAPI OleRegEnumVerbs (REFCLSID clsid, LPENUMOLEVERB FAR* ppenum);
+
+
+
+/* OLE 1.0 conversion APIS */
+
+STDAPI OleConvertIStorageToOLESTREAM
+ (LPSTORAGE pstg,
+ LPOLESTREAM polestm);
+
+STDAPI OleConvertOLESTREAMToIStorage
+ (LPOLESTREAM polestm,
+ LPSTORAGE pstg,
+ const DVTARGETDEVICE FAR* ptd);
+
+STDAPI OleConvertIStorageToOLESTREAMEx
+ (LPSTORAGE pstg,
+ // Presentation data to OLESTREAM
+ CLIPFORMAT cfFormat, // format
+ LONG lWidth, // width
+ LONG lHeight, // height
+ DWORD dwSize, // size in bytes
+ __in LPSTGMEDIUM pmedium, // bits
+ LPOLESTREAM polestm);
+
+STDAPI OleConvertOLESTREAMToIStorageEx
+ (LPOLESTREAM polestm,
+ LPSTORAGE pstg,
+ // Presentation data from OLESTREAM
+ CLIPFORMAT FAR* pcfFormat, // format
+ LONG FAR* plwWidth, // width
+ LONG FAR* plHeight, // height
+ DWORD FAR* pdwSize, // size in bytes
+ __in LPSTGMEDIUM pmedium); // bits
+
+
+
+/* Storage Utility APIs */
+STDAPI GetHGlobalFromILockBytes (LPLOCKBYTES plkbyt, HGLOBAL FAR* phglobal);
+STDAPI CreateILockBytesOnHGlobal (HGLOBAL hGlobal, BOOL fDeleteOnRelease,
+ LPLOCKBYTES FAR* pplkbyt);
+
+STDAPI GetHGlobalFromStream (LPSTREAM pstm, HGLOBAL FAR* phglobal);
+STDAPI CreateStreamOnHGlobal (HGLOBAL hGlobal, BOOL fDeleteOnRelease,
+ LPSTREAM FAR* ppstm);
+
+
+/* ConvertTo APIS */
+
+STDAPI OleDoAutoConvert(LPSTORAGE pStg, LPCLSID pClsidNew);
+STDAPI OleGetAutoConvert(REFCLSID clsidOld, LPCLSID pClsidNew);
+STDAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew);
+STDAPI GetConvertStg(LPSTORAGE pStg);
+STDAPI SetConvertStg(LPSTORAGE pStg, BOOL fConvert);
+
+
+#endif // _OLE2_H_
diff --git a/private/ole32/olethunk/thc/thpp/ole2dbg.h b/private/ole32/olethunk/thc/thpp/ole2dbg.h
new file mode 100644
index 000000000..34fbf8384
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/ole2dbg.h
@@ -0,0 +1,19 @@
+/*
+ ole2dbg.h: This header file contains the function declarations for the publicly
+ exported debugging interfaces.
+
+ Include *after* standard OLE2 includes.
+
+ Copyright (c) 1992-1993, Microsoft Corp. All rights reserved.
+*/
+
+#ifndef __OLE2DBG_H
+#define __OLE2DBG_H
+
+STDAPI_(void) DbgDumpObject( IUnknown FAR * pUnk, DWORD dwReserved);
+STDAPI_(void) DbgDumpExternalObject( IUnknown FAR * pUnk, DWORD dwReserved );
+
+STDAPI_(BOOL) DbgIsObjectValid( IUnknown FAR * pUnk );
+STDAPI_(void) DbgDumpClassName( IUnknown FAR * pUnk );
+
+#endif
diff --git a/private/ole32/olethunk/thc/thpp/ole2ver.h b/private/ole32/olethunk/thc/thpp/ole2ver.h
new file mode 100644
index 000000000..5cbde9a99
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/ole2ver.h
@@ -0,0 +1,5 @@
+#define rmj 0
+#define rmm 23
+#define rup 639
+#define szVerName ""
+#define szVerUser "Y-OLEBLD"
diff --git a/private/ole32/olethunk/thc/thpp/oleguid.h b/private/ole32/olethunk/thc/thpp/oleguid.h
new file mode 100644
index 000000000..723fa50d7
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/oleguid.h
@@ -0,0 +1,80 @@
+/*****************************************************************************\
+* *
+* oleguid.h - Master definition of GUIDs for ole2.dll *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+/* this file is the master definition of all public GUIDs specific to OLE
+ and is included in ole2.h.
+
+ NOTE: The second least significant byte of all of these GUIDs is 1.
+*/
+
+
+DEFINE_OLEGUID(IID_IEnumUnknown, 0x00000100, 0, 0);
+DEFINE_OLEGUID(IID_IEnumString, 0x00000101, 0, 0);
+DEFINE_OLEGUID(IID_IEnumMoniker, 0x00000102, 0, 0);
+DEFINE_OLEGUID(IID_IEnumFORMATETC, 0x00000103, 0, 0);
+DEFINE_OLEGUID(IID_IEnumOLEVERB, 0x00000104, 0, 0);
+DEFINE_OLEGUID(IID_IEnumSTATDATA, 0x00000105, 0, 0);
+
+DEFINE_OLEGUID(IID_IEnumGeneric, 0x00000106, 0, 0);
+DEFINE_OLEGUID(IID_IEnumHolder, 0x00000107, 0, 0);
+DEFINE_OLEGUID(IID_IEnumCallback, 0x00000108, 0, 0);
+
+DEFINE_OLEGUID(IID_IPersistStream, 0x00000109, 0, 0);
+DEFINE_OLEGUID(IID_IPersistStorage, 0x0000010a, 0, 0);
+DEFINE_OLEGUID(IID_IPersistFile, 0x0000010b, 0, 0);
+DEFINE_OLEGUID(IID_IPersist, 0x0000010c, 0, 0);
+
+DEFINE_OLEGUID(IID_IViewObject, 0x0000010d, 0, 0);
+DEFINE_OLEGUID(IID_IDataObject, 0x0000010e, 0, 0);
+DEFINE_OLEGUID(IID_IAdviseSink, 0x0000010f, 0, 0);
+DEFINE_OLEGUID(IID_IDataAdviseHolder, 0x00000110, 0, 0);
+DEFINE_OLEGUID(IID_IOleAdviseHolder, 0x00000111, 0, 0);
+
+DEFINE_OLEGUID(IID_IOleObject, 0x00000112, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceObject, 0x00000113, 0, 0);
+DEFINE_OLEGUID(IID_IOleWindow, 0x00000114, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceUIWindow, 0x00000115, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceFrame, 0x00000116, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceActiveObject, 0x00000117, 0, 0);
+
+DEFINE_OLEGUID(IID_IOleClientSite, 0x00000118, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceSite, 0x00000119, 0, 0);
+
+DEFINE_OLEGUID(IID_IParseDisplayName, 0x0000011a, 0, 0);
+DEFINE_OLEGUID(IID_IOleContainer, 0x0000011b, 0, 0);
+DEFINE_OLEGUID(IID_IOleItemContainer, 0x0000011c, 0, 0);
+
+DEFINE_OLEGUID(IID_IOleLink, 0x0000011d, 0, 0);
+DEFINE_OLEGUID(IID_IOleCache, 0x0000011e, 0, 0);
+DEFINE_OLEGUID(IID_IOleManager, 0x0000011f, 0, 0); // unused
+DEFINE_OLEGUID(IID_IOlePresObj, 0x00000120, 0, 0);
+
+DEFINE_OLEGUID(IID_IDropSource, 0x00000121, 0, 0);
+DEFINE_OLEGUID(IID_IDropTarget, 0x00000122, 0, 0);
+
+DEFINE_OLEGUID(IID_IDebug, 0x00000123, 0, 0);
+DEFINE_OLEGUID(IID_IDebugStream, 0x00000124, 0, 0);
+
+DEFINE_OLEGUID(IID_IAdviseSink2, 0x00000125, 0, 0);
+
+DEFINE_OLEGUID(IID_IRunnableObject, 0x00000126, 0, 0);
+
+DEFINE_OLEGUID(IID_IViewObject2, 0x00000127, 0, 0);
+DEFINE_OLEGUID(IID_IOleCache2, 0x00000128, 0, 0);
+DEFINE_OLEGUID(IID_IOleCacheControl, 0x00000129, 0, 0);
+
+/* NOTE: LSB values 0x27 through 0xff are reserved */
+
+
+/* GUIDs defined in OLE's private range */
+DEFINE_OLEGUID(CLSID_Picture_Metafile, 0x00000315, 0, 0);
+DEFINE_OLEGUID(CLSID_Picture_Dib, 0x00000316, 0, 0);
+
+
diff --git a/private/ole32/olethunk/thc/thpp/scode.h b/private/ole32/olethunk/thc/thpp/scode.h
new file mode 100644
index 000000000..cbfb2751c
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/scode.h
@@ -0,0 +1,283 @@
+/*****************************************************************************\
+* *
+* scode.h - Defines standard status code services. *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#ifndef __SCODE_H__
+#define __SCODE_H__
+
+//
+// SCODE
+//
+
+typedef long SCODE;
+typedef SCODE *PSCODE;
+typedef void FAR * HRESULT;
+#define NOERROR 0
+
+//
+// Status values are 32 bit values layed out as follows:
+//
+// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-+---------------------+-------+-------------------------------+
+// |S| Context | Facil | Code |
+// +-+---------------------+-------+-------------------------------+
+//
+// where
+//
+// S - is the severity code
+//
+// 0 - Success
+// 1 - Error
+//
+// Context - context info
+//
+// Facility - is the facility code
+//
+// Code - is the facility's status code
+//
+
+//
+// Severity values
+//
+
+#define SEVERITY_SUCCESS 0
+#define SEVERITY_ERROR 1
+
+
+
+#define SUCCEEDED(Status) ((SCODE)(Status) >= 0)
+
+#define FAILED(Status) ((SCODE)(Status)<0)
+
+
+//
+// Return the code
+//
+
+#define SCODE_CODE(sc) ((sc) & 0xFFFF)
+
+//
+// Return the facility
+//
+
+#define SCODE_FACILITY(sc) (((sc) >> 16) & 0x1fff)
+
+//
+// Return the severity
+//
+
+#define SCODE_SEVERITY(sc) (((sc) >> 31) & 0x1)
+
+//
+// Create an SCODE value from component pieces
+//
+
+#define MAKE_SCODE(sev,fac,code) \
+ ((SCODE) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
+
+
+
+// --------------------- Functions ---------------------------------------
+
+#define GetScode(hr) ((SCODE)(hr) & 0x800FFFFF)
+#define ResultFromScode(sc) ((HRESULT)((SCODE)(sc) & 0x800FFFFF))
+
+STDAPI PropagateResult(HRESULT hrPrev, SCODE scNew);
+
+
+// -------------------------- Facility definitions -------------------------
+
+#define FACILITY_NULL 0x0000 // generally useful errors ([SE]_*)
+#define FACILITY_RPC 0x0001 // remote procedure call errors (RPC_E_*)
+#define FACILITY_DISPATCH 0x0002 // late binding dispatch errors
+#define FACILITY_STORAGE 0x0003 // storage errors (STG_E_*)
+#define FACILITY_ITF 0x0004 // interface-specific errors
+
+
+
+#define S_OK 0L
+#define S_FALSE MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 1)
+
+
+
+// --------------------- FACILITY_NULL errors ------------------------------
+
+#define E_UNEXPECTED MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 0xffff)
+ // relatively catastrophic failure
+
+#define E_NOTIMPL MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 1)
+ // not implemented
+
+#define E_OUTOFMEMORY MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 2)
+ // ran out of memory
+
+#define E_INVALIDARG MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 3)
+ // one or more arguments are invalid
+
+#define E_NOINTERFACE MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 4)
+ // no such interface supported
+
+
+#define E_POINTER MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 5)
+ // invalid pointer
+
+#define E_HANDLE MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 6)
+ // invalid handle
+
+#define E_ABORT MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 7)
+ // operation aborted
+
+#define E_FAIL MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 8)
+ // unspecified error
+
+
+#define E_ACCESSDENIED MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 9)
+ // general access denied error
+
+
+// ----------------- FACILITY_ITF errors used by OLE ---------------------
+//
+// By convention, OLE interfaces divide the FACILITY_ITF range of errors
+// into nonoverlapping subranges. If an OLE interface returns a FACILITY_ITF
+// scode, it must be from the range associated with that interface or from
+// the shared range: OLE_E_FIRST...OLE_E_LAST.
+//
+// The ranges, their associated interfaces, and the header file that defines
+// the actual scodes are given below.
+//
+
+// Generic OLE errors that may be returned by many interfaces
+#define OLE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0000)
+#define OLE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x00FF)
+#define OLE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0000)
+#define OLE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x00FF)
+// interfaces: all
+// file: ole2.h
+
+
+#define DRAGDROP_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0100)
+#define DRAGDROP_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x010F)
+#define DRAGDROP_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0100)
+#define DRAGDROP_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x010F)
+// interfaces: IDropSource, IDropTarget
+// file: ole2.h
+
+#define CLASSFACTORY_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0110)
+#define CLASSFACTORY_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x011F)
+#define CLASSFACTORY_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0110)
+#define CLASSFACTORY_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x011F)
+// interfaces: IClassFactory
+// file:
+
+#define MARSHAL_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0120)
+#define MARSHAL_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x012F)
+#define MARSHAL_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0120)
+#define MARSHAL_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x012F)
+// interfaces: IMarshal, IStdMarshalInfo, marshal APIs
+// file:
+
+#define DATA_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0130)
+#define DATA_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x013F)
+#define DATA_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0130)
+#define DATA_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x013F)
+// interfaces: IDataObject
+// file: dvobj.h
+
+#define VIEW_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0140)
+#define VIEW_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x014F)
+#define VIEW_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0140)
+#define VIEW_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x014F)
+// interfaces: IViewObject
+// file: dvobj.h
+
+#define REGDB_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0150)
+#define REGDB_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x015F)
+#define REGDB_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0150)
+#define REGDB_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x015F)
+// API: reg.dat manipulation
+// file:
+
+
+// range 160 - 16F reserved
+
+#define CACHE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0170)
+#define CACHE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x017F)
+#define CACHE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0170)
+#define CACHE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x017F)
+// interfaces: IOleCache
+// file:
+
+#define OLEOBJ_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0180)
+#define OLEOBJ_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x018F)
+#define OLEOBJ_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0180)
+#define OLEOBJ_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x018F)
+// interfaces: IOleObject
+// file:
+
+#define CLIENTSITE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0190)
+#define CLIENTSITE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x019F)
+#define CLIENTSITE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0190)
+#define CLIENTSITE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x019F)
+// interfaces: IOleClientSite
+// file:
+
+#define INPLACE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01A0)
+#define INPLACE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01AF)
+#define INPLACE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01A0)
+#define INPLACE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01AF)
+// interfaces: IOleWindow, IOleInPlaceObject, IOleInPlaceActiveObject,
+// IOleInPlaceUIWindow, IOleInPlaceFrame, IOleInPlaceSite
+// file:
+
+#define ENUM_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01B0)
+#define ENUM_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01BF)
+#define ENUM_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01B0)
+#define ENUM_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01BF)
+// interfaces: IEnum*
+// file:
+
+#define CONVERT10_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01C0)
+#define CONVERT10_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01CF)
+#define CONVERT10_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01C0)
+#define CONVERT10_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01CF)
+// API: OleConvertOLESTREAMToIStorage, OleConvertIStorageToOLESTREAM
+// file:
+
+
+#define CLIPBRD_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01D0)
+#define CLIPBRD_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01DF)
+#define CLIPBRD_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01D0)
+#define CLIPBRD_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01DF)
+// interfaces: OleSetClipboard, OleGetClipboard, OleFlushClipboard
+// file: ole2.h
+
+#define MK_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01E0)
+#define MK_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01EF)
+#define MK_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01E0)
+#define MK_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01EF)
+// interfaces: IMoniker, IBindCtx, IRunningObjectTable, IParseDisplayName,
+// IOleContainer, IOleItemContainer, IOleLink
+// file: moniker.h
+
+
+#define CO_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01F0)
+#define CO_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01FF)
+#define CO_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01F0)
+#define CO_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01FF)
+// all Co* API
+// file: compobj.h
+
+
+// range 200 - ffff for new error codes
+
+
+
+#endif // ifndef __SCODE_H__
diff --git a/private/ole32/olethunk/thc/thpp/storage.h b/private/ole32/olethunk/thc/thpp/storage.h
new file mode 100644
index 000000000..777db3732
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/storage.h
@@ -0,0 +1,457 @@
+/*****************************************************************************\
+* *
+* storage.h - Definitions for the strutured storage system
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#if !defined( _STORAGE_H_ )
+#define _STORAGE_H_
+
+
+#include <compobj.h>
+
+
+/****** Storage Error Codes *************************************************/
+
+/* DOS-based error codes */
+#define STG_E_INVALIDFUNCTION \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x01)
+
+#define STG_E_FILENOTFOUND \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x02)
+
+#define STG_E_PATHNOTFOUND \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x03)
+
+#define STG_E_TOOMANYOPENFILES \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x04)
+
+#define STG_E_ACCESSDENIED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x05)
+
+#define STG_E_INVALIDHANDLE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x06)
+
+#define STG_E_INSUFFICIENTMEMORY \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x08)
+
+#define STG_E_INVALIDPOINTER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x09)
+
+#define STG_E_NOMOREFILES \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x12)
+
+#define STG_E_DISKISWRITEPROTECTED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x13)
+
+#define STG_E_SEEKERROR \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x19)
+
+#define STG_E_WRITEFAULT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x1d)
+
+#define STG_E_READFAULT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x1e)
+
+#define STG_E_SHAREVIOLATION \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x20)
+
+#define STG_E_LOCKVIOLATION \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x21)
+
+#define STG_E_FILEALREADYEXISTS \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x50)
+
+#define STG_E_INVALIDPARAMETER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x57)
+
+#define STG_E_MEDIUMFULL \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x70)
+
+#define STG_E_ABNORMALAPIEXIT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfa)
+
+#define STG_E_INVALIDHEADER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfb)
+
+#define STG_E_INVALIDNAME \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfc)
+
+#define STG_E_UNKNOWN \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfd)
+
+#define STG_E_UNIMPLEMENTEDFUNCTION\
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfe)
+
+#define STG_E_INVALIDFLAG \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xff)
+
+/* Standard storage error codes */
+#define STG_E_INUSE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x100)
+
+#define STG_E_NOTCURRENT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x101)
+
+#define STG_E_REVERTED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x102)
+
+#define STG_E_CANTSAVE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x103)
+
+#define STG_E_OLDFORMAT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x104)
+
+#define STG_E_OLDDLL \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x105)
+
+#define STG_E_SHAREREQUIRED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x106)
+
+#define STG_E_NOTFILEBASEDSTORAGE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x107)
+
+#define STG_E_EXTANTMARSHALLINGS \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x108)
+
+/* Information returns */
+#define STG_S_CONVERTED \
+ MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_STORAGE, 0x200)
+
+/****** Storage types *******************************************************/
+
+#if defined(_M_I286)
+typedef char TCHAR;
+#ifndef HUGEP
+#define HUGEP _huge
+#endif
+#else
+typedef char TCHAR;
+#ifndef HUGEP
+#define HUGEP
+#endif
+#endif
+
+#define CWCSTORAGENAME 32
+
+/* Storage instantiation modes */
+#define STGM_DIRECT 0x00000000L
+#define STGM_TRANSACTED 0x00010000L
+
+#define STGM_READ 0x00000000L
+#define STGM_WRITE 0x00000001L
+#define STGM_READWRITE 0x00000002L
+
+#define STGM_SHARE_DENY_NONE 0x00000040L
+#define STGM_SHARE_DENY_READ 0x00000030L
+#define STGM_SHARE_DENY_WRITE 0x00000020L
+#define STGM_SHARE_EXCLUSIVE 0x00000010L
+
+#define STGM_PRIORITY 0x00040000L
+#define STGM_DELETEONRELEASE 0x04000000L
+
+#define STGM_CREATE 0x00001000L
+#define STGM_CONVERT 0x00020000L
+#define STGM_FAILIFTHERE 0x00000000L
+
+/* Storage commit types */
+typedef enum tagSTGC
+{
+ STGC_DEFAULT = 0,
+ STGC_OVERWRITE = 1,
+ STGC_ONLYIFCURRENT = 2,
+ STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4
+} STGC;
+
+/* Stream name block definitions */
+typedef char FAR * FAR *SNB;
+
+
+#ifndef _WINDOWS_
+#ifndef _FILETIME_
+#define _FILETIME_
+typedef struct FARSTRUCT tagFILETIME
+{
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+} FILETIME;
+#endif
+#endif
+
+
+/* Storage stat buffer */
+
+typedef struct FARSTRUCT tagSTATSTG
+{
+ char FAR* pwcsName;
+ DWORD type;
+ ULARGE_INTEGER cbSize;
+ FILETIME mtime;
+ FILETIME ctime;
+ FILETIME atime;
+ DWORD grfMode;
+ DWORD grfLocksSupported;
+ CLSID clsid;
+ DWORD grfStateBits;
+ DWORD reserved;
+} STATSTG;
+
+
+/* Storage element types */
+typedef enum tagSTGTY
+{
+ STGTY_STORAGE = 1,
+ STGTY_STREAM = 2,
+ STGTY_LOCKBYTES = 3,
+ STGTY_PROPERTY = 4
+} STGTY;
+
+typedef enum tagSTREAM_SEEK
+{
+ STREAM_SEEK_SET = 0,
+ STREAM_SEEK_CUR = 1,
+ STREAM_SEEK_END = 2
+} STREAM_SEEK;
+
+typedef enum tagLOCKTYPE
+{
+ LOCK_WRITE = 1,
+ LOCK_EXCLUSIVE = 2,
+ LOCK_ONLYONCE = 4
+} LOCKTYPE;
+
+typedef enum tagSTGMOVE
+{
+ STGMOVE_MOVE = 0,
+ STGMOVE_COPY = 1
+} STGMOVE;
+
+typedef enum tagSTATFLAG
+{
+ STATFLAG_DEFAULT = 0,
+ STATFLAG_NONAME = 1
+} STATFLAG;
+
+
+/****** Storage Enumerators *************************************************/
+
+#undef INTERFACE
+#define INTERFACE IEnumSTATSTG
+
+DECLARE_INTERFACE_(IEnumSTATSTG, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IENUMSTATSTG methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, STATSTG FAR * rgelt, ULONG FAR *pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumSTATSTG FAR *FAR *ppenm) PURE;
+};
+
+typedef IEnumSTATSTG FAR* LPENUMSTATSTG;
+
+
+
+/****** ILockBytes Interface ************************************************/
+
+#undef INTERFACE
+#define INTERFACE ILockBytes
+
+DECLARE_INTERFACE_(ILockBytes, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** ILockBytes methods ***
+ STDMETHOD(ReadAt) (THIS_ ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbRead) PURE;
+ STDMETHOD(WriteAt) (THIS_ ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten) PURE;
+ STDMETHOD(Flush) (THIS) PURE;
+ STDMETHOD(SetSize) (THIS_ ULARGE_INTEGER cb) PURE;
+ STDMETHOD(LockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(UnlockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+};
+
+typedef ILockBytes FAR* LPLOCKBYTES;
+
+
+
+/****** IStream Interface ***************************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IStream
+
+DECLARE_INTERFACE_(IStream, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IStream methods ***
+ STDMETHOD(Read) (THIS_ VOID HUGEP *pv,
+ ULONG cb, ULONG FAR *pcbRead) PURE;
+ STDMETHOD(Write) (THIS_ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten) PURE;
+ STDMETHOD(Seek) (THIS_ LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER FAR *plibNewPosition) PURE;
+ STDMETHOD(SetSize) (THIS_ ULARGE_INTEGER libNewSize) PURE;
+ STDMETHOD(CopyTo) (THIS_ IStream FAR *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER FAR *pcbRead,
+ ULARGE_INTEGER FAR *pcbWritten) PURE;
+ STDMETHOD(Commit) (THIS_ DWORD grfCommitFlags) PURE;
+ STDMETHOD(Revert) (THIS) PURE;
+ STDMETHOD(LockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(UnlockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+ STDMETHOD(Clone)(THIS_ IStream FAR * FAR *ppstm) PURE;
+};
+
+typedef IStream FAR* LPSTREAM;
+
+
+
+/****** IStorage Interface **************************************************/
+
+#undef INTERFACE
+#define INTERFACE IStorage
+
+DECLARE_INTERFACE_(IStorage, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IStorage methods ***
+ STDMETHOD(CreateStream) (THIS_ const char FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream FAR *FAR *ppstm) PURE;
+ STDMETHOD(OpenStream) (THIS_ const char FAR* pwcsName,
+ void FAR *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream FAR *FAR *ppstm) PURE;
+ STDMETHOD(CreateStorage) (THIS_ const char FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStorage FAR *FAR *ppstg) PURE;
+ STDMETHOD(OpenStorage) (THIS_ const char FAR* pwcsName,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR *FAR *ppstg) PURE;
+ STDMETHOD(CopyTo) (THIS_ DWORD ciidExclude,
+ IID const FAR *rgiidExclude,
+ SNB snbExclude,
+ IStorage FAR *pstgDest) PURE;
+ STDMETHOD(MoveElementTo) (THIS_ char const FAR* lpszName,
+ IStorage FAR *pstgDest,
+ char const FAR* lpszNewName,
+ DWORD grfFlags) PURE;
+ STDMETHOD(Commit) (THIS_ DWORD grfCommitFlags) PURE;
+ STDMETHOD(Revert) (THIS) PURE;
+ STDMETHOD(EnumElements) (THIS_ DWORD reserved1,
+ void FAR *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG FAR *FAR *ppenm) PURE;
+ STDMETHOD(DestroyElement) (THIS_ const char FAR* pwcsName) PURE;
+ STDMETHOD(RenameElement) (THIS_ const char FAR* pwcsOldName,
+ const char FAR* pwcsNewName) PURE;
+ STDMETHOD(SetElementTimes) (THIS_ const char FAR *lpszName,
+ FILETIME __in const FAR *pctime,
+ FILETIME __in const FAR *patime,
+ FILETIME __in const FAR *pmtime) PURE;
+ STDMETHOD(SetClass) (THIS_ REFCLSID clsid) PURE;
+ STDMETHOD(SetStateBits) (THIS_ DWORD grfStateBits, DWORD grfMask) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+};
+
+typedef IStorage FAR* LPSTORAGE;
+
+
+
+/****** IRootStorage Interface **********************************************/
+
+#undef INTERFACE
+#define INTERFACE IRootStorage
+
+DECLARE_INTERFACE_(IRootStorage, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IRootStorage methods ***
+ STDMETHOD(SwitchToFile) (THIS_ LPSTR lpstrFile) PURE;
+};
+
+typedef IRootStorage FAR* LPROOTSTORAGE;
+
+
+
+/****** Storage API Prototypes ********************************************/
+
+STDAPI StgCreateDocfile(const char FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgCreateDocfileOnILockBytes(ILockBytes FAR *plkbyt,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgOpenStorage(const char FAR* pwcsName,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgOpenStorageOnILockBytes(ILockBytes FAR *plkbyt,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgIsStorageFile(const char FAR* pwcsName);
+STDAPI StgIsStorageILockBytes(ILockBytes FAR* plkbyt);
+
+STDAPI StgSetTimes(char const FAR* lpszName,
+ FILETIME __in const FAR* pctime,
+ FILETIME __in const FAR* patime,
+ FILETIME __in const FAR* pmtime);
+
+#endif
diff --git a/private/ole32/olethunk/thc/thpp/valid.h b/private/ole32/olethunk/thc/thpp/valid.h
new file mode 100644
index 000000000..0c25dc733
--- /dev/null
+++ b/private/ole32/olethunk/thc/thpp/valid.h
@@ -0,0 +1,72 @@
+#define IsValidPtrIn(pv,cb) (!IsBadReadPtr ((pv),(cb)))
+#define IsValidPtrOut(pv,cb) (!IsBadWritePtr((pv),(cb)))
+
+STDAPI_(BOOL) IsValidInterface( void FAR* pv );
+STDAPI_(BOOL) IsValidIid( REFIID riid );
+
+
+#ifdef _DEBUG
+
+//** POINTER IN validation macros:
+#define VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid in ptr", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTRIN( pv, TYPE, retval ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid in ptr", _szAssertFile, __LINE__), retval)
+#define VOID_VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) {\
+ FnAssert(#pv,"Invalid in ptr", _szAssertFile, __LINE__); return; }
+
+//** POINTER OUT validation macros:
+#define VDATEPTROUT( pv, TYPE ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid out ptr", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTROUT( pv, TYPE, retval ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid out ptr", _szAssertFile, __LINE__), retval)
+
+//** INTERFACE validation macro:
+#define GEN_VDATEIFACE( pv, retval ) if (!IsValidInterface(pv)) \
+ return (FnAssert(#pv,"Invalid interface", _szAssertFile, __LINE__), retval)
+#define VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return (FnAssert(#pv,"Invalid interface", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define VOID_VDATEIFACE( pv ) if (!IsValidInterface(pv)) {\
+ FnAssert(#pv,"Invalid interface", _szAssertFile, __LINE__); return; }
+
+//** INTERFACE ID validation macro:
+#define VDATEIID( iid ) if (!IsValidIid( iid )) \
+ return (FnAssert(#iid,"Invalid iid", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEIID( iid, retval ) if (!IsValidIid( iid )) {\
+ FnAssert(#iid,"Invalid iid", _szAssertFile, __LINE__); return retval; }
+#else
+
+
+
+// --assertless macros for non-debug case
+//** POINTER IN validation macros:
+#define VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTRIN( pv, TYPE, retval ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (retval)
+#define VOID_VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) {\
+ return; }
+
+//** POINTER OUT validation macros:
+#define VDATEPTROUT( pv, TYPE ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (ResultFromScode(E_INVALIDARG))
+
+#define GEN_VDATEPTROUT( pv, TYPE, retval ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (retval)
+
+//** INTERFACE validation macro:
+#define VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return (ResultFromScode(E_INVALIDARG))
+#define VOID_VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return;
+#define GEN_VDATEIFACE( pv, retval ) if (!IsValidInterface(pv)) \
+ return (retval)
+
+//** INTERFACE ID validation macro:
+#define VDATEIID( iid ) if (!IsValidIid( iid )) \
+ return (ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEIID( iid, retval ) if (!IsValidIid( iid )) \
+ return retval;
+
+#endif
+
diff --git a/private/ole32/olethunk/thc/thsplit/depend.mk b/private/ole32/olethunk/thc/thsplit/depend.mk
new file mode 100644
index 000000000..c6ff4b7ed
--- /dev/null
+++ b/private/ole32/olethunk/thc/thsplit/depend.mk
@@ -0,0 +1,11 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\thsplit.obj $(OBJDIR)\thsplit.lst: .\thsplit.c $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h
+
diff --git a/private/ole32/olethunk/thc/thsplit/filelist.mk b/private/ole32/olethunk/thc/thsplit/filelist.mk
new file mode 100644
index 000000000..fb057685e
--- /dev/null
+++ b/private/ole32/olethunk/thc/thsplit/filelist.mk
@@ -0,0 +1,10 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1994 **
+#********************************************************************
+
+TARGET = thsplit.exe
+
+CFILES = .\thsplit.c
+
+NO_WINMAIN = 1
diff --git a/private/ole32/olethunk/thc/thsplit/makefile b/private/ole32/olethunk/thc/thsplit/makefile
new file mode 100644
index 000000000..ab55746a6
--- /dev/null
+++ b/private/ole32/olethunk/thc/thsplit/makefile
@@ -0,0 +1,9 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1994 **
+#********************************************************************
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include $(DEPENDFILE)
diff --git a/private/ole32/olethunk/thc/thsplit/thsplit.c b/private/ole32/olethunk/thc/thsplit/thsplit.c
new file mode 100644
index 000000000..02434c323
--- /dev/null
+++ b/private/ole32/olethunk/thc/thsplit/thsplit.c
@@ -0,0 +1,92 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: thsplit.c
+//
+// Contents: File splitter tool for the thunk tool
+//
+// History: 22-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ FILE *in, *out;
+ char line[256];
+ char ofile[32], nfile[32], *n, *l;
+
+ if (argc != 2)
+ {
+ printf("Usage: %s multifile\n", argv[0]);
+ exit(1);
+ }
+
+ in = fopen(argv[1], "r");
+ if (in == NULL)
+ {
+ perror(argv[1]);
+ exit(1);
+ }
+
+ out = NULL;
+ for (;;)
+ {
+ if (fgets(line, 256, in) == NULL)
+ break;
+
+ if (strncmp(line, "|- ", 3) == 0)
+ {
+ n = nfile;
+ l = line+3;
+ while (*l != ' ')
+ *n++ = *l++;
+ *n = 0;
+
+ if (out != NULL && strcmp(nfile, ofile) != 0)
+ {
+ printf("Section '%s' started while section '%s' was active\n",
+ nfile, ofile);
+ fclose(out);
+ out = NULL;
+ }
+
+ if (out == NULL)
+ {
+ out = fopen(nfile, "a");
+ if (out == NULL)
+ {
+ perror(nfile);
+ exit(1);
+ }
+
+ strcpy(ofile, nfile);
+ }
+ else
+ {
+ fclose(out);
+ out = NULL;
+ }
+ }
+ else
+ {
+ if (out)
+ {
+ fprintf(out, "%s", line);
+ }
+ }
+ }
+
+ if (out != NULL)
+ {
+ printf("Unterminated section '%s'\n", ofile);
+ fclose(out);
+ }
+
+ fclose(in);
+}
diff --git a/private/ole32/olethunk/tools/clschk/classchk.cxx b/private/ole32/olethunk/tools/clschk/classchk.cxx
new file mode 100644
index 000000000..54be227aa
--- /dev/null
+++ b/private/ole32/olethunk/tools/clschk/classchk.cxx
@@ -0,0 +1,1114 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: classchk.cxx
+//
+// Classchk is a program for verifying that the contents of the registry are
+// OKY-DOKY as far as OLE is concerned.
+//
+// In general, we verify that all CLSID's are of the correct length, all string
+// parameters are NULL terminated.
+//
+// There are several phases of checking.
+//
+// 1) Checking that PROGID entries that have CLSID sections match.
+// 2) Checking that PROGID entries have correct and existing protocol entries
+// 3) Checking that PROGID entries
+//
+// History: 5-31-95 kevinro Created
+//
+//----------------------------------------------------------------------------
+
+#include <windows.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "classchk.h"
+
+//
+// The following registry values are used quite a few times in this program.
+// These global variables keep us from needing to open them constantly.
+//
+
+HKEY hkey_clsid = 0;
+
+DWORD g_VerbosityLevel = VERB_LEVEL_WARN | VERB_LEVEL_ERROR;
+
+#define StrICmp(x,y) (CompareString(LOCALE_USER_DEFAULT,NORM_IGNORECASE,x,-1,y,-1) - 2)
+//+---------------------------------------------------------------------------
+//
+// Function: ReadRegistryString
+//
+// Synopsis: Reads a string from the registry
+//
+// Effects:
+//
+// This function reads in a string from the registry, and does some basic
+// consistency checking on it, such as verifying the length and NULL
+// terminatation.
+//
+//
+// Arguments: [hkeyRoot] --
+// [pszSubKeyName] --
+// [pszValueName] --
+// [pszValue] --
+// [pcbValue] --
+//
+// Returns: ERROR_SUCCESS Everything peachy
+// ERROR_FILE_NOT_FOUND Couldn't read entry from registry
+// CLASSCHK_SOMETHINGODD Something about the string is wrong
+// (other) Return value from registry
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-31-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD ReadRegistryString( HKEY hkeyRoot, LPSTR pszSubKeyName, LPSTR pszValueName, LPSTR pszValue, PULONG pcbValue)
+{
+ LONG lRetValue;
+ DWORD dwType;
+ DWORD dwReturn = ERROR_SUCCESS;
+ HKEY hkey = hkeyRoot;
+
+ if(pszSubKeyName != NULL)
+ {
+ lRetValue = RegOpenKeyEx(hkeyRoot,
+ pszSubKeyName,
+ NULL,
+ KEY_READ,
+ &hkey);
+
+ //
+ // It is common to see keys that don't exist. Let the caller decide if it is
+ // important or not.
+ //
+ if(lRetValue != ERROR_SUCCESS)
+ {
+ VERBOSITY(VERB_LEVEL_TRACE,printf("Unable to open subkey %s to read value %s\n",pszSubKeyName,pszValueName););
+ return lRetValue;
+ }
+ }
+
+ lRetValue = RegQueryValueEx(hkey,
+ pszValueName,
+ NULL, // Must be NULL according to spec
+ &dwType,
+ (BYTE *)pszValue,
+ pcbValue);
+ if(hkeyRoot != hkey)
+ {
+ //
+ // Always close the new subkey if we opened it
+ //
+ RegCloseKey(hkey);
+ }
+
+ switch(lRetValue)
+ {
+ case ERROR_SUCCESS:
+ //
+ // Read the value, everything A-OK
+ //
+ break;
+ case ERROR_MORE_DATA:
+ VERBOSITY(VERB_LEVEL_WARN,printf("The value '%s' is larger than expected. May be a problem\n",pszValueName);)
+ return lRetValue;
+ break;
+
+ case ERROR_FILE_NOT_FOUND:
+ //
+ // This may be expected, so don't report any errors. Let the caller handle that
+ //
+ return lRetValue;
+ default:
+ VERBOSITY(VERB_LEVEL_WARN,printf("RegQueryValueEx() for '%s' returned unexpected error 0x%x\n",pszValueName,lRetValue);)
+ return lRetValue;
+ }
+
+ //
+ // We expect this type to be REG_SZ. If it isn't, complain
+ //
+ if(dwType != REG_SZ)
+ {
+ VERBOSITY(VERB_LEVEL_WARN,printf("The value for '%s' is type 0x%x, was expecting REG_SZ (0x%x)\n",pszValueName,dwType,REG_SZ);)
+ dwReturn = CLASSCHK_SOMETHINGODD;
+ }
+
+ //
+ // We expect the value to be NULL terminated
+ //
+ if(pszValue[(*pcbValue)-1] != 0)
+ {
+
+ VERBOSITY(VERB_LEVEL_WARN,printf("The value for '%s' may not be NULL terminated.\n",pszValueName);)
+ }
+
+ //
+ // We expect strlen to be the same as the length returned (which includes the NULL)
+ //
+ if((strlen(pszValue) + 1) != *pcbValue)
+ {
+ VERBOSITY(VERB_LEVEL_WARN,printf("The string value for '%s' may not have the correct length\n",pszValueName);)
+ if(dwType == REG_SZ)
+ {
+ VERBOSITY(VERB_LEVEL_WARN,printf("The string value is '%s'\n",pszValue);)
+ }
+ dwReturn = CLASSCHK_SOMETHINGODD;
+ }
+
+ return dwReturn;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: AllHexDigits
+//
+// Synopsis: Verify that all of the digits specified are hexidecimal
+//
+// Effects:
+//
+// Arguments: [pszString] -- String to check
+// [chString] -- Number of characters
+//
+// Requires:
+//
+// Returns: TRUE All hex digits
+// FALSE Not all hex digits
+//
+// History: 5-31-95 kevinro Created
+//----------------------------------------------------------------------------
+BOOL AllHexDigits(LPSTR pszString, ULONG chString)
+{
+ while(chString--)
+ {
+ if(!isxdigit(pszString[chString]))
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CheckForValidGuid
+//
+// Synopsis: Given a string, determine if the string is a GUID
+//
+// Arguments: [pszValue] -- String to check
+//
+// History: 5-31-95 kevinro Created
+//
+//----------------------------------------------------------------------------
+DWORD CheckForValidGuid(LPSTR pszValue)
+{
+ DWORD dwResult = 0;
+ if((strlen(pszValue) != 38) || (pszValue[0] != '{') || (pszValue[37] != '}'))
+ {
+ dwResult = CLASSCHK_SOMETHINGODD;
+ }
+ else
+ {
+ // Check the internals of the GUID.
+ if(!AllHexDigits(&pszValue[1],8) ||
+ pszValue[9] != '-' ||
+ !AllHexDigits(&pszValue[10],4) ||
+ pszValue[14] != '-' ||
+ !AllHexDigits(&pszValue[15],4) ||
+ pszValue[19] != '-' ||
+ !AllHexDigits(&pszValue[20],4) ||
+ pszValue[24] != '-' ||
+ !AllHexDigits(&pszValue[25],12) )
+ {
+ dwResult = CLASSCHK_SOMETHINGODD;
+ }
+ }
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReadRegistryGuid
+//
+// Synopsis: Read a GUID from the registry, and check to see if it is valid.
+//
+// Arguments: [hkey] -- Key to start from
+// [pszSubKeyName] -- Subkey relative to hkey (NULL if hkey)
+// [pszValueName] -- Value name (NULL if default value)
+// [pszValue] -- Pointer to return buffer
+// [pcbValue] -- Size of return buffer in characters
+//
+// Returns: ERROR_SUCCESS Read and verified GUID
+// (other) Something is wrong
+// ERROR_FILE_NOT_FOUND Key didn't exist
+// CLASSCHK_SOMETHINGODD Read key, but something is wrong with it.
+//
+// History: 5-31-95 kevinro Created
+//
+//----------------------------------------------------------------------------
+DWORD ReadRegistryGuid( HKEY hkey, LPSTR pszSubKeyName, LPSTR pszValueName, LPSTR pszValue, PULONG pcbValue)
+{
+ DWORD dwResult;
+ //
+ // First, just read the value from the registry.
+ //
+ dwResult = ReadRegistryString(hkey, pszSubKeyName, pszValueName, pszValue, pcbValue);
+
+ if(dwResult == ERROR_SUCCESS)
+ {
+ //
+ // Do some additional basic checking, such as the length being correct, and the
+ // GUID correctly formed.
+ //
+ dwResult = CheckForValidGuid(pszValue);
+ if(dwResult != ERROR_SUCCESS)
+ {
+ VERBOSITY(VERB_LEVEL_ERROR,printf("*** Malformed GUID '%s' ***\n",pszValue);)
+ }
+
+ }
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReadRegistryFile
+//
+// Synopsis: Read a registry entry which is supposed to be a file,
+// and determine if the file exists
+//
+// Arguments: [hkey] -- Key to start from
+// [pszSubKeyName] -- Subkey relative to hkey (NULL if hkey)
+// [pszValueName] -- Value name (NULL if default value)
+// [pszValue] -- Pointer to return buffer
+// [pcbValue] -- Size of return buffer in characters
+//
+// Returns: ERROR_SUCCESS Read and verified
+// (other) Something is wrong
+// ERROR_FILE_NOT_FOUND Key didn't exist
+// CLASSCHK_SOMETHINGODD Read key, but something is wrong with it.
+//
+// History: 5-31-95 kevinro Created
+//
+//----------------------------------------------------------------------------
+
+ReadRegistryFile(HKEY hkey, LPSTR pszSubKeyName, LPSTR pszValueName, LPSTR pszValue, PULONG pcbValue)
+{
+ DWORD dwResult;
+ //
+ // First, just read the value from the registry.
+ //
+ dwResult = ReadRegistryString(hkey, pszSubKeyName, pszValueName, pszValue, pcbValue);
+
+ if (dwResult == ERROR_SUCCESS)
+ {
+ char achFoundPath[MAX_PATH];
+ char *pszFileNamePart;
+ //
+ // Some apps append a switch at the end.
+ // If there is a switch, terminate the path at that point
+ //
+ if(pszFileNamePart = strchr(pszValue,'/'))
+ {
+ *pszFileNamePart = 0;
+ }
+ else if(pszFileNamePart = strchr(pszValue,'-'))
+ {
+ //
+ // Some applications also use the '-' character
+ // as a switch delimiter. If this character is in
+ // the string, and the previous character is a space,
+ // then assume it is a delimiter. This isn't foolproof,
+ // but it should work most of the time.
+ //
+ if(pszFileNamePart[-1] == ' ')
+ {
+ *pszFileNamePart = 0;
+ }
+ }
+
+ if(SearchPath(NULL,pszValue,NULL,MAX_PATH,achFoundPath,&pszFileNamePart) == 0)
+ {
+ //
+ // Didn't find the name in the path.
+ //
+ VERBOSITY(VERB_LEVEL_ERROR,printf("*** Could not find path '%s' ***\n",pszValue));
+ dwResult = CLASSCHK_SOMETHINGODD;
+
+ }
+ else
+ {
+ VERBOSITY(VERB_LEVEL_TRACE,printf("Found path %s (%s)\n",achFoundPath,pszValue));
+ }
+
+ }
+
+ return dwResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CheckProgID
+//
+// Synopsis:
+//
+// Given a PROGID entry, do some checking to insure the entry is sane. Of the things to check,
+// we should check to insure the name string is readable. If there is a CLSID entry, we should
+// check to see if it has a CLSID in it.
+//
+//
+// Arguments: [pszProgID] -- PROGID string to check
+//
+// History: 5-31-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD CheckProgID(LPSTR pszProgID)
+{
+
+ LONG lRetValue = 0;
+ char achValue[MAX_PATH];
+ DWORD cbValue;
+ DWORD dwRetValue;
+ HKEY progidKey = NULL;
+
+
+ lRetValue = RegOpenKeyEx(HKEY_CLASSES_ROOT,
+ pszProgID,
+ NULL,
+ KEY_READ,
+ &progidKey);
+
+ if(lRetValue == ERROR_SUCCESS)
+ {
+ cbValue = MAX_PATH;
+
+ //
+ // Read the default key value for the PROGID. Normally, this should be the name of the class name
+ // or program name that would be shown.
+ //
+ dwRetValue = ReadRegistryString(progidKey,NULL,NULL,achValue,&cbValue);
+
+ if(dwRetValue == CLASSCHK_SOMETHINGODD)
+ {
+ VERBOSITY(VERB_LEVEL_WHINE,printf("HKEY_CLASSES_ROOT\\%s found odd description '%s'\n",pszProgID,achValue);)
+ }
+
+ cbValue = MAX_PATH;
+
+ dwRetValue = ReadRegistryGuid(progidKey,"CLSID",NULL,achValue,&cbValue);
+
+ switch(dwRetValue)
+ {
+ case ERROR_SUCCESS:
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ // Not all of these entries will have a CLSID section
+ break;
+ default:
+ VERBOSITY(VERB_LEVEL_ERROR,
+ printf("*** Possible invalid CLSID in HKEY_CLASSES_ROOT\\%s\\CLSID\n",pszProgID);)
+ }
+
+ if(dwRetValue == ERROR_SUCCESS)
+ {
+ char achValue2[MAX_PATH];
+ DWORD cbValue2 = MAX_PATH;
+ //
+ // We appear to have a valid CLSID. Check for existence of the CLSID. We are actually only
+ // interested in it being found or not.
+ //
+ dwRetValue = ReadRegistryString(hkey_clsid,achValue,NULL,achValue2,&cbValue2);
+ if(dwRetValue == ERROR_FILE_NOT_FOUND)
+ {
+ VERBOSITY(VERB_LEVEL_ERROR,printf("ProgID %s has CLSID %s. Unable to find HKEY_CLASSES_ROOT\\CLSID\\%s\n",pszProgID,achValue,achValue);)
+ }
+ }
+
+ //
+ // Check to see if there is an OLE 1.0 section that specifies protocol\stdfileediting\server
+ //
+ cbValue = MAX_PATH;
+ dwRetValue = ReadRegistryFile(progidKey,"protocol\\stdfileediting\\server",NULL,achValue,&cbValue);
+ if(dwRetValue == CLASSCHK_SOMETHINGODD)
+ {
+ VERBOSITY(VERB_LEVEL_ERROR,printf("HKEY_CLASSES_ROOT\\%s\\Protocol\\StdFileEditing\\server may have invalid entry\n",pszProgID);)
+ }
+
+ }
+ else
+ {
+ VERBOSITY(VERB_LEVEL_WARN,printf("Unable to open HKEY_CLASSES_ROOT\\%s\n",pszProgID);)
+ }
+
+ if(progidKey != NULL)
+ {
+ RegCloseKey(progidKey);
+ }
+
+ return 0;
+}
+
+
+
+//
+// Given an extention (ie something that starts with a '.'), determine if the mapping to PROGID is correct
+//
+DWORD CheckExtentionToProgID(LPSTR pszExtention)
+{
+
+ LONG lRetValue = 0;
+ char achValue[MAX_PATH];
+ DWORD cbValue;
+ DWORD dwRetValue;
+ HKEY subKey = NULL;
+ HKEY progidKey = NULL;
+
+
+ lRetValue = RegOpenKeyEx(HKEY_CLASSES_ROOT,
+ pszExtention,
+ NULL,
+ KEY_READ,
+ &subKey);
+
+ if(lRetValue == ERROR_SUCCESS)
+ {
+ cbValue = MAX_PATH;
+
+ //
+ // Read the default key value for the extention. Normally, this should point to a
+ // PROGID.
+ //
+ dwRetValue = ReadRegistryString(subKey,NULL,NULL,achValue,&cbValue);
+ VERBOSITY(VERB_LEVEL_TRACE,printf("HKEY_CLASSES_ROOT\\%s = %s\n",pszExtention,achValue);)
+
+ if(dwRetValue == CLASSCHK_SOMETHINGODD)
+ {
+ VERBOSITY(VERB_LEVEL_WARN,printf("Reading HKEY_CLASSES_ROOT\\%s found something odd\n",pszExtention);)
+ }
+
+ //
+ // If it is an extension, the value should be a PROGID.Take a look to see if it is.
+ //
+ lRetValue = RegOpenKeyEx(HKEY_CLASSES_ROOT,
+ achValue,
+ NULL,
+ KEY_READ,
+ &progidKey);
+ //
+ // It should have been there. If it wasn't, then report a strangeness
+ //
+
+ switch(lRetValue)
+ {
+ case ERROR_SUCCESS:
+ //
+ // The PROGID actually existed. We will verify its contents later.
+ //
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ //
+ // The PROGID doesn't exist. This could be a potential problem in the registry. Report it.
+ //
+ VERBOSITY(VERB_LEVEL_ERROR,
+ printf("HKEY_CLASSES_ROOT\\%s **** PROGID '%s' didn't exist ***\n*** Check Registry ***\n",
+ pszExtention,
+ achValue);)
+ break;
+ default:
+ VERBOSITY(VERB_LEVEL_WARN,printf("Unexpected error opening HKEY_CLASSES_ROOT\\%s (error 0x%x)\n",achValue,lRetValue);)
+
+ }
+
+
+ }
+ else
+ {
+ VERBOSITY(VERB_LEVEL_WARN,printf("Unable to open HKEY_CLASSES_ROOT\\%s\n",pszExtention);)
+ }
+
+
+ if(subKey != NULL) RegCloseKey(subKey);
+ if(progidKey != NULL) RegCloseKey(progidKey);
+
+
+ return 0;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CheckOLE1CLSID
+//
+// Synopsis: CheckOLE1CLSID looks at CLSID's that are typically OLE 1.0.
+// This includes checking for AutoConvert, checking the PROGID,
+// and checking that the Ole1Class key exists.
+//
+// Arguments: [pszCLSID] -- Name of OLE 1.0 CLASSID to check
+//
+// History: 5-31-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD CheckOLE1CLSID(LPSTR pszCLSID)
+{
+ LONG lRetValue = 0;
+ char achValue[MAX_PATH];
+ DWORD cbValue;
+ DWORD dwRetValue;
+ HKEY subKey = NULL;
+ BOOL fFoundAServer = FALSE;
+ char achValue2[MAX_PATH];
+ DWORD cbValue2 = MAX_PATH;
+
+ lRetValue = RegOpenKeyEx(hkey_clsid,pszCLSID,NULL,KEY_READ,&subKey);
+
+ if(lRetValue != ERROR_SUCCESS)
+ {
+ VERBOSITY(VERB_LEVEL_ERROR,printf("Unable to open HKEY_CLASSES_ROOT\\CLSID\\%s error 0x%x\n",pszCLSID,lRetValue);)
+ return CLASSCHK_SOMETHINGODD;
+ }
+
+ //
+ // Check to insure that there is an Ole1Class entry
+ //
+
+ cbValue = MAX_PATH;
+ dwRetValue = ReadRegistryString(subKey,"Ole1Class",NULL,achValue,&cbValue);
+ switch(dwRetValue)
+ {
+ case ERROR_FILE_NOT_FOUND:
+ VERBOSITY(VERB_LEVEL_WARN,printf("HKEY_CLASSES_ROOT\\CLSID\\%s is missing its Ole1Class key\n",pszCLSID);)
+ break;
+ case CLASSCHK_SOMETHINGODD:
+ VERBOSITY(VERB_LEVEL_WARN,printf("HKEY_CLASSES_ROOT\\CLSID\\%s\\Ole1Class key is odd\n",pszCLSID);)
+
+ }
+
+ //
+ // Quite often, there will be a AutoConvertTo key, which is supposed to be a GUID
+ //
+ cbValue = MAX_PATH;
+ dwRetValue = ReadRegistryGuid(subKey,"AutoConvertTo",NULL,achValue,&cbValue);
+ switch(dwRetValue)
+ {
+ case ERROR_SUCCESS:
+ //
+ // The CLSID should normally point to another class, such as the 2.0 version. Check to
+ // insure the CLSID exists
+ //
+ dwRetValue = ReadRegistryString(hkey_clsid,achValue,NULL,achValue2,&cbValue2);
+ if(dwRetValue != ERROR_SUCCESS)
+ {
+ VERBOSITY(VERB_LEVEL_WARN,printf("HKEY_CLASSES_ROOT\\CLSID\\%s\\AutoConvertTo key is odd\n",pszCLSID);)
+ switch(dwRetValue)
+ {
+ case ERROR_FILE_NOT_FOUND:
+
+ VERBOSITY(VERB_LEVEL_WARN,printf("HKEY_CLASSES_ROOT\\CLSID\\%s doesn't appear to exist\n",achValue);)
+ break;
+ }
+ }
+
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ //
+ // This entry isn't required. If it doesn't exist, no big deal.
+ //
+ break;
+ case CLASSCHK_SOMETHINGODD:
+ VERBOSITY(VERB_LEVEL_WARN,printf("HKEY_CLASSES_ROOT\\CLSID\\%s\\AutoConvertTo key is odd\n",pszCLSID);)
+ break;
+
+ }
+
+ //
+ // It would be abnormal to find a missing PROGID key
+ //
+ cbValue = MAX_PATH;
+ dwRetValue = ReadRegistryString(subKey,"ProgID",NULL,achValue,&cbValue);
+ switch(dwRetValue)
+ {
+ case ERROR_SUCCESS:
+ //
+ // The PROGID should normally point to a valid PROGID
+ //
+ cbValue2 = MAX_PATH;
+ dwRetValue = ReadRegistryString(HKEY_CLASSES_ROOT,achValue,NULL,achValue2,&cbValue2);
+ if(dwRetValue != ERROR_SUCCESS)
+ {
+ VERBOSITY(VERB_LEVEL_ERROR,printf("HKEY_CLASSES_ROOT\\CLSID\\%s\\PROGID key is odd\n",pszCLSID);)
+ switch(dwRetValue)
+ {
+ case ERROR_FILE_NOT_FOUND:
+
+ VERBOSITY(VERB_LEVEL_ERROR,printf("HKEY_CLASSES_ROOT\\%s doesn't appear to exist\n",achValue);)
+ break;
+ }
+ }
+
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ //
+ // This entry is required.
+ //
+ VERBOSITY(VERB_LEVEL_ERROR,printf("HKEY_CLASSES_ROOT\\CLSID\\%s\\PROGID key is missing\n",pszCLSID);)
+
+ break;
+ case CLASSCHK_SOMETHINGODD:
+ VERBOSITY(VERB_LEVEL_WARN,printf("HKEY_CLASSES_ROOT\\CLSID\\%s\\Ole1Class key is odd\n",pszCLSID);)
+
+ }
+
+ return dwRetValue;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CheckForDLL
+//
+// Synopsis: Given a CLSID, its hkey, and the name of the DLL value,
+// determine if the DLL exists as a file, and if the threading
+// model value is appropriate.
+//
+// Arguments: [pszCLSID] -- Name of the CLSID (for debug output)
+// [hkeyCLSID] -- HKEY for the clsid
+// [pszDLLKey] -- Name of the subkey to check for
+//
+// Requires:
+//
+// Returns:
+//
+// Signals:
+//
+// Modifies:
+//
+// Algorithm:
+//
+// History: 5-31-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD CheckForDLL(LPSTR pszCLSID, HKEY hkeyCLSID, LPSTR pszDLLKey)
+{
+ LONG lRetValue = 0;
+ char achValue[MAX_PATH];
+ DWORD cbValue;
+ DWORD dwRetValue;
+ char achThreadModel[MAX_PATH];
+ DWORD cbThreadModel = MAX_PATH;
+ //
+ // The DLL name should be in
+ //
+ cbValue = MAX_PATH;
+ dwRetValue = ReadRegistryFile(hkeyCLSID,pszDLLKey,NULL,achValue,&cbValue);
+
+ switch(dwRetValue)
+ {
+ case ERROR_FILE_NOT_FOUND:
+ //
+ // The registry key didn't exist. Thats normally OK.
+ //
+ return dwRetValue;
+ case CLASSCHK_SOMETHINGODD:
+ VERBOSITY(VERB_LEVEL_WARN,printf("HKEY_CLASSES_ROOT\\CLSID\\%s\\%s key is odd\n",pszCLSID,pszDLLKey);)
+ return dwRetValue;
+ }
+
+ //
+ // If the DLL exists, check to see if the ThreadingModelKey is valid
+ //
+ dwRetValue = ReadRegistryString(hkeyCLSID,pszDLLKey,"ThreadingModel",achThreadModel,&cbThreadModel);
+ switch(dwRetValue)
+ {
+ case ERROR_FILE_NOT_FOUND:
+ //
+ // The registry key didn't exist. Thats normally OK.
+ //
+ return ERROR_SUCCESS;
+ case CLASSCHK_SOMETHINGODD:
+ VERBOSITY(VERB_LEVEL_WARN,printf("HKEY_CLASSES_ROOT\\CLSID\\%s\\%s\\ThreadingModel value is odd\n",pszCLSID,pszDLLKey);)
+ return dwRetValue;
+ }
+
+ //
+ // Check to insure the threading model is something we understand
+ //
+ if( StrICmp( achThreadModel, "Apartment") &&
+ StrICmp( achThreadModel, "Both") &&
+ StrICmp( achThreadModel, "Free"))
+ {
+ VERBOSITY(VERB_LEVEL_WARN,printf("HKEY_CLASSES_ROOT\\CLSID\\%s\\%s\\ThreadingModel value is %s\n",pszCLSID,pszDLLKey,achThreadModel);)
+ VERBOSITY(VERB_LEVEL_WARN,printf("Expected 'Apartment','Both', or 'Free'");)
+ return CLASSCHK_SOMETHINGODD;
+ }
+ return ERROR_SUCCESS;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CheckCLSIDEntry
+//
+// Synopsis: Given the name of a CLSID entry, verify that the entry is
+// valid by looking for the 'usual' key information, and
+// cross checking it against things that we assert should be
+// true.
+// Effects:
+//
+// Arguments: [pszCLSID] -- CLSID in a string form. Used to open key
+//
+// History: 5-31-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD CheckCLSIDEntry(LPSTR pszCLSID)
+{
+ LONG lRetValue = 0;
+ char achValue[MAX_PATH];
+ DWORD cbValue;
+ char achPROGID[MAX_PATH];
+ DWORD cbPROGID = MAX_PATH;
+ char achPROGIDPath[MAX_PATH];
+ DWORD cbPROGIDPath = MAX_PATH;
+ char achPROGIDValue[MAX_PATH];
+ DWORD cbPROGIDValue = MAX_PATH;
+
+ LPSTR pszLocalServer = "LocalServer32";
+ DWORD dwRetValue;
+ HKEY subKey = NULL;
+ BOOL fFoundAServer = FALSE;
+
+ lRetValue = RegOpenKeyEx(hkey_clsid,
+ pszCLSID,
+ NULL,
+ KEY_READ,
+ &subKey);
+
+ if(lRetValue != ERROR_SUCCESS)
+ {
+ VERBOSITY(VERB_LEVEL_ERROR,printf("Unable to open HKEY_CLASSES_ROOT\\CLSID\\%s error 0x%x\n",pszCLSID,lRetValue);)
+ return CLASSCHK_SOMETHINGODD;
+ }
+
+ //
+ // Basic sanity check: Is the description string a valid string
+ //
+ cbValue = MAX_PATH;
+ dwRetValue = ReadRegistryString(subKey,NULL,NULL,achValue,&cbValue);
+ if(dwRetValue != ERROR_SUCCESS)
+ {
+ VERBOSITY(VERB_LEVEL_WHINE,printf("HKEY_CLASSES_ROOT\\CLSID\\%s has odd description string\n",pszCLSID);)
+ }
+
+ //
+ // A CLSID entry typically has several values. Least of which is supposed to be one or more of the following:
+ // InprocHandler
+ // InprocServer
+ // LocalServer
+ // InprocHandler32
+ // InprocServer32
+ // LocalServer32
+ //
+ // It may also have an optional PROGID entry, which we can use to verify that that the LocalServer and
+ // the protocol\StdFileEditing\server entries match.
+ //
+ // Another couple of things to watch for include checking the Inproc entries for ThreadingModel,
+ //
+ // Yet another thing to look at is the value of the CLSID itself. If the first 4 digits are 0003 or 0004, then
+ // the CLSID is for an OLE 1.0 class, and we need to do a seperate check
+ //
+ if((strncmp(&pszCLSID[1],"0003",4) == 0) || (strncmp(&pszCLSID[1],"0004",4) == 0) )
+ {
+ //
+ // In theory, this is supposed to be an OLE1CLASS. Check it seperately
+ //
+ RegCloseKey(subKey);
+ return CheckOLE1CLSID(pszCLSID);
+ }
+
+ dwRetValue = CheckForDLL(pszCLSID, subKey, "InprocHandler");
+ dwRetValue = CheckForDLL(pszCLSID, subKey, "InprocHandler32");
+
+ dwRetValue = CheckForDLL(pszCLSID, subKey, "InprocServer");
+ if(dwRetValue != ERROR_FILE_NOT_FOUND) fFoundAServer++;
+
+ dwRetValue = CheckForDLL(pszCLSID, subKey, "InprocServer32");
+ if(dwRetValue != ERROR_FILE_NOT_FOUND) fFoundAServer++;
+
+ //
+ // First, check for LocalServer32. If that doesn't exist, then try for
+ // LocalServer.
+ //
+
+ cbValue = MAX_PATH;
+ dwRetValue = ReadRegistryFile(subKey,pszLocalServer,NULL,achValue,&cbValue);
+ if(dwRetValue == ERROR_FILE_NOT_FOUND)
+ {
+ cbValue = MAX_PATH;
+ pszLocalServer = "LocalServer";
+ dwRetValue = ReadRegistryFile(subKey,pszLocalServer,NULL,achValue,&cbValue);
+ if(dwRetValue == CLASSCHK_SOMETHINGODD)
+ {
+ VERBOSITY(VERB_LEVEL_WARN,printf("HKEY_CLASSES_ROOT\\CLSID\\%s\\LocalServer32 is odd\n",pszCLSID);)
+
+ }
+ }
+ else if(dwRetValue == CLASSCHK_SOMETHINGODD)
+ {
+ VERBOSITY(VERB_LEVEL_WARN,printf("HKEY_CLASSES_ROOT\\CLSID\\%s\\%s is odd\n",pszCLSID,pszLocalServer);)
+
+ }
+
+ if(dwRetValue == ERROR_SUCCESS)
+ {
+ fFoundAServer++;
+ //
+ // We have a valid LocalServer. Lets get the PROGID's version of the local server, and compare the
+ // two. They should compare.
+ //
+ dwRetValue = ReadRegistryString(subKey,"PROGID",NULL,achPROGID,&cbPROGID);
+ switch(dwRetValue)
+ {
+ case ERROR_FILE_NOT_FOUND:
+ //
+ // Most CLSID's should indeed have a PROGID, but it isn't 100% required.
+ //
+ VERBOSITY(VERB_LEVEL_WHINE,printf("HKEY_CLASSES_ROOT\\CLSID\\%s missing a PROGID entry\n",pszCLSID);)
+ break;
+ case CLASSCHK_SOMETHINGODD:
+ VERBOSITY(VERB_LEVEL_WARN,printf("HKEY_CLASSES_ROOT\\CLSID\\%s PROGID entry is odd\n",pszCLSID);)
+ break;
+ default:
+ sprintf(achPROGIDPath,"%s\\protocol\\stdfileediting\\server",achPROGID);
+ dwRetValue = ReadRegistryFile(HKEY_CLASSES_ROOT,achPROGIDPath,NULL,achPROGIDValue,&cbPROGIDValue);
+ //
+ // The only thing we are interested in checking is if the two strings compare.
+ //
+ if(dwRetValue == ERROR_SUCCESS)
+ {
+ if(StrICmp(achPROGIDValue,achValue) != 0)
+ {
+ VERBOSITY(VERB_LEVEL_ERROR,printf("HKEY_CLASSES_ROOT\\CLSID\\%s is inconsistent with its PROGID\n",pszCLSID);)
+ VERBOSITY(VERB_LEVEL_ERROR,printf("HKEY_CLASSES_ROOT\\%s = '%s'\n",achPROGIDPath,achPROGIDValue);)
+ VERBOSITY(VERB_LEVEL_ERROR,printf("HKEY_CLASSES_ROOT\\CLSID\\%s\\%s = '%s'\n",pszCLSID,pszLocalServer,achValue);)
+
+ }
+ }
+ }
+ }
+
+ if(!fFoundAServer)
+ {
+ VERBOSITY(VERB_LEVEL_ERROR,printf("*** Unable to find a valid server for HKEY_CLASSES_ROOT\\CLSID\\%s ***\n",pszCLSID);)
+ }
+
+ RegCloseKey(subKey);
+
+ return dwRetValue;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: EnumerateClsidRoot
+//
+// Synopsis: Enumerate and check each entry in the CLSID section
+//
+// History: 5-31-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD EnumerateClsidRoot()
+{
+ LONG lRetValue = 0;
+ DWORD iSubKey = 0;
+ char achKeyName[MAX_PATH];
+ DWORD cbKeyName;
+ FILETIME filetime;
+
+ while(1)
+ {
+ cbKeyName = MAX_PATH;
+
+ lRetValue = RegEnumKeyEx(hkey_clsid,
+ iSubKey,
+ achKeyName,
+ &cbKeyName,
+ NULL,
+ NULL,
+ NULL,
+ &filetime);
+
+ if(lRetValue == ERROR_NO_MORE_ITEMS)
+ {
+ // End of enumeration
+ break;
+ }
+
+ if(lRetValue != ERROR_SUCCESS)
+ {
+ VERBOSITY(VERB_LEVEL_ERROR,printf("EnumerateClsidRoot:RegEnumKeyEx returned %x\n",lRetValue);)
+ return CLASSCHK_ERROR;
+ }
+
+ //
+ // Each of the sub keys enumerated here is expected to be a GUID. If it isn't a GUID, then it
+ // might be some other random garbage that we don't care about.
+ //
+
+ if(CheckForValidGuid(achKeyName) == ERROR_SUCCESS)
+ {
+ CheckCLSIDEntry(achKeyName);
+ }
+
+ iSubKey++;
+ }
+
+ return 0;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: EnumerateClassesRoot
+//
+// Synopsis: Enumerate the root of HKEY_CLASSES, and check each entry
+// based on what we think it should be.
+//
+// History: 5-31-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+DWORD EnumerateClassesRoot()
+{
+ LONG lRetValue = 0;
+ DWORD iSubKey = 0;
+ char achKeyName[MAX_PATH];
+ DWORD cbKeyName;
+ FILETIME filetime;
+
+ while(1)
+ {
+ cbKeyName = MAX_PATH;
+ lRetValue = RegEnumKeyEx(HKEY_CLASSES_ROOT,
+ iSubKey,
+ achKeyName,
+ &cbKeyName,
+ NULL,
+ NULL,
+ NULL,
+ &filetime);
+
+ if(lRetValue == ERROR_NO_MORE_ITEMS)
+ {
+ // End of enumeration
+ break;
+ }
+
+ if(lRetValue != ERROR_SUCCESS)
+ {
+ VERBOSITY(VERB_LEVEL_ERROR,printf("EnumerateClassesRoot:RegEnumKeyEx returned %x\n",lRetValue);)
+ return CLASSCHK_ERROR;
+ }
+
+ //
+ // We expect to find two basic things at the HKEY_CLASSES_ROOT level.
+ // First are extention mappings, second are PROGID's. There is also
+ // the special cases of CLSID, Interface, and FileType, which are
+ // checked differently
+ //
+
+ if(StrICmp(achKeyName,"CLSID") == 0)
+ {
+ // The CLSID section is done later
+ }
+ else if(StrICmp(achKeyName,"Interface") == 0)
+ {
+ // The interface section is done later
+ }
+ else if(StrICmp(achKeyName,"FileType") == 0)
+ {
+ // The FileType entry is done later
+ }
+ else if(achKeyName[0] == '.')
+ {
+ // File extentions start with dots.
+ // Call the Check Extention function here
+ CheckExtentionToProgID(achKeyName);
+ }
+ else
+ {
+ // Assume it may be a PROGID. Call the PROGID function here.
+
+ CheckProgID(achKeyName);
+ }
+
+
+ iSubKey++;
+ }
+
+ return 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: main
+//
+// Synopsis: Main entry point for program. Does what main entry points
+// usually do.
+//
+// Arguments: [argc] --
+// [argv] --
+//
+// History: 5-31-95 kevinro Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+int _cdecl main(int argc, char *argv[])
+{
+ LONG lRetValue = 0;
+
+ //
+ // HKEY_CLASSES_ROOT is often used.
+ //
+ lRetValue = RegOpenKeyEx(HKEY_CLASSES_ROOT,
+ "CLSID",
+ NULL,
+ KEY_READ,
+ &hkey_clsid);
+
+ if(lRetValue != ERROR_SUCCESS)
+ {
+ printf("Couldn't open HKEY_CLASSES_ROOT\\CLSID\n");
+ return(1);
+ }
+
+ //
+ // Enumerate different parts of the registry, reporting
+ // errors as we go.
+ //
+ EnumerateClassesRoot();
+ EnumerateClsidRoot();
+
+ RegCloseKey(hkey_clsid);
+ return 0;
+
+}
diff --git a/private/ole32/olethunk/tools/clschk/classchk.h b/private/ole32/olethunk/tools/clschk/classchk.h
new file mode 100644
index 000000000..45b82f3d3
--- /dev/null
+++ b/private/ole32/olethunk/tools/clschk/classchk.h
@@ -0,0 +1,21 @@
+//
+// classchk.h
+//
+
+#define CLASSCHK_SOMETHINGODD 0x12340001
+
+// Some unknown error has occured
+#define CLASSCHK_ERROR 0x1234FFFF
+
+
+#define VERB_LEVEL_ERROR 0x01
+#define VERB_LEVEL_WARN 0x02
+#define VERB_LEVEL_WHINE 0x04
+#define VERB_LEVEL_TRACE 0x10
+#define VERB_LEVEL_ITRACE 0x20
+#define VERB_LEVEL_IWARN 0x40
+#define VERB_LEVEL_IERRROR 0x80
+
+extern DWORD g_VerbosityLevel;
+
+#define VERBOSITY( level, x) if( level & g_VerbosityLevel ) x
diff --git a/private/ole32/olethunk/tools/clschk/makefile b/private/ole32/olethunk/tools/clschk/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ole32/olethunk/tools/clschk/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/olethunk/tools/clschk/sources b/private/ole32/olethunk/tools/clschk/sources
new file mode 100644
index 000000000..5c7453acf
--- /dev/null
+++ b/private/ole32/olethunk/tools/clschk/sources
@@ -0,0 +1,25 @@
+MAJORCOMP=olethunk
+MINORCOMP=classchk
+
+TARGETPATH=obj
+TARGETNAME=classchk
+TARGETTYPE=PROGRAM
+
+SOURCES= classchk.cxx
+
+UMTYPE=console
+
+UMAPPL=classchk
+UMLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\crtdll.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib
+
+
+
+USE_CRTDLL=1
+
diff --git a/private/ole32/olethunk/tools/infolvl/infolvl.cxx b/private/ole32/olethunk/tools/infolvl/infolvl.cxx
new file mode 100644
index 000000000..bd9bd79ed
--- /dev/null
+++ b/private/ole32/olethunk/tools/infolvl/infolvl.cxx
@@ -0,0 +1,159 @@
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+typedef struct _InfoLevelRecord
+{
+ char *pszInfoLevel;
+ char *pszSectionName;
+ char *pszDescription;
+} InfoLevelRecord;
+
+InfoLevelRecord ilrArray[] =
+{
+ { "cairole", "Cairole Infolevels","Compobj layer" },
+ { "DD", "Cairole Infolevels","Drag & Drop" },
+ { "heap", "Cairole Infolevels","Heap trace output" },
+ { "hk", "Cairole Infolevels","Hook layer" },
+ { "intr","Cairole Infolevels","1.0/2.0 interop layer" },
+ { "le", "Cairole Infolevels", "Linking and embedding" },
+ { "mnk", "Cairole Infolevels", "Moniker tracing" },
+ { "msf", "Cairole Infolevels", "Upper layer storage" },
+ { "ol", "Cairole Infolevels", "Lower layer storage" },
+ { "ref", "Cairole Infolevels", "CSafeRef class (Cairo)" },
+ { "scm", "Cairole Infolevels", "OLE service" },
+ { "Stack", "Cairole Infolevels", "Stack switching (Win95)" },
+ { "StackOn", "Cairole Infolevels", "Stack switching enable (boolean,Win95)" },
+ { "prop", "Cairole Infolevels", "Storage property interfaces" },
+ { "api", "Cairole Infolevels","CompApi trace" },
+ { "breakoninit", "Olethk32","Break on initialization (boolean)" },
+ { "InfoLevel", "Olethk32","16/32 thunk layer (32-bit side)" },
+ { "ole2", "Olethk16","16/32 thunk layer: ole2.dll" },
+ { "stg", "Olethk16","16/32 thunk layer: storage.dll" },
+ { "comp", "Olethk16","16/32 thunk layer: compobj.dll" },
+ { NULL, NULL }
+};
+
+typedef struct _AttrRecord
+{
+ char *pszAttr;
+ char *pszSectionName;
+ char *pszDescription;
+} AttrRecord;
+
+AttrRecord arArray[] =
+{
+ { "DebugScreen", "Cairole Infolevels","Debugger Screen (Yes|No)" },
+ { "LogFile", "Cairole Infolevels","LogFile (\"<name>\"|\"\")" },
+ { NULL, NULL}
+};
+
+char * LookupILSection (char * pszInfoLevel)
+{
+ InfoLevelRecord *pr;
+ for ( pr = ilrArray ; pr->pszInfoLevel != NULL ; pr++)
+ {
+ if (_stricmp(pr->pszInfoLevel,pszInfoLevel) == 0)
+ {
+ break;
+ }
+
+ }
+ return pr->pszSectionName;
+}
+
+void DumpInfoLevelRecords()
+{
+ InfoLevelRecord *pr;
+
+ printf("%20s %-12s Currently\n","Section Name","Name");
+
+ for ( pr = ilrArray ; pr->pszInfoLevel != NULL ; pr++)
+ {
+ printf("%20s %-12s (%08x) %s\n",
+ pr->pszSectionName,
+ pr->pszInfoLevel,
+ GetProfileInt(pr->pszSectionName,pr->pszInfoLevel,0),
+ pr->pszDescription);
+
+ }
+
+}
+
+char * LookupASection (char * pszAttr)
+{
+ AttrRecord *pr;
+ for ( pr = arArray ; pr->pszAttr != NULL ; pr++)
+ {
+ if (stricmp(pr->pszAttr,pszAttr) == 0)
+ {
+ break;
+ }
+
+ }
+ return pr->pszSectionName;
+}
+
+void DumpAttrRecords()
+{
+ AttrRecord *pr;
+ char buffer[256];
+
+ printf("%20s %-12s Currently\n","Section Name","Name");
+
+ for ( pr = arArray ; pr->pszAttr != NULL ; pr++)
+ {
+ GetProfileString(pr->pszSectionName,pr->pszAttr, "", buffer, sizeof(buffer));
+ printf("%20s %-12s (%s) %s\n",
+ pr->pszSectionName,
+ pr->pszAttr,
+ buffer,
+ pr->pszDescription);
+
+ }
+
+}
+
+void Usage(char *pszProgName)
+{
+ printf("Usage:\n\t%s <infolevel name> 0x<hexvalue>\tOR\n\t%s <attribute> <value>\n", pszProgName, pszProgName);
+ printf("\nKnown infolevels are as follows\n\n");
+ DumpInfoLevelRecords();
+ printf("\nKnown attributes are as follows\n\n");
+ DumpAttrRecords();
+}
+
+void _cdecl main(int argc, char *argv[])
+{
+ //
+ // The command line specifies the infolevel, followed by the
+ // value. There are a known set of infolevels.
+ //
+ //
+ if (argc != 3)
+ {
+ Usage(argv[0]);
+ return;
+ }
+
+ char *pszSectionName = LookupILSection(argv[1]);
+
+ if (pszSectionName == NULL)
+ {
+ pszSectionName = LookupASection(argv[1]);
+ }
+
+ if (pszSectionName == NULL)
+ {
+ printf("Don't recognize %s as an infolevel or attribute\n",argv[1]);
+ Usage(argv[0]);
+ return;
+ }
+
+ if(!WriteProfileString(pszSectionName,argv[1],argv[2]))
+ {
+ printf("Error: WriteProfileString returns false\n");
+ printf("GetLastError returns %x\n",GetLastError());
+ }
+}
diff --git a/private/ole32/olethunk/tools/infolvl/makefile b/private/ole32/olethunk/tools/infolvl/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ole32/olethunk/tools/infolvl/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/olethunk/tools/infolvl/sources b/private/ole32/olethunk/tools/infolvl/sources
new file mode 100644
index 000000000..1e48ee2d8
--- /dev/null
+++ b/private/ole32/olethunk/tools/infolvl/sources
@@ -0,0 +1,12 @@
+MAJORCOMP=olethunk
+MINORCOMP=infolvl
+
+TARGETPATH=obj
+TARGETNAME=infolvl
+TARGETTYPE=PROGRAM
+
+SOURCES= infolvl.cxx
+
+UMTYPE=console
+
+UMAPPL=infolvl
diff --git a/private/ole32/olethunk/tools/rotdump/makefile b/private/ole32/olethunk/tools/rotdump/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ole32/olethunk/tools/rotdump/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/olethunk/tools/rotdump/rotdump.cxx b/private/ole32/olethunk/tools/rotdump/rotdump.cxx
new file mode 100644
index 000000000..6d5c2f5f3
--- /dev/null
+++ b/private/ole32/olethunk/tools/rotdump/rotdump.cxx
@@ -0,0 +1,126 @@
+
+#include <windows.h>
+#include <ole2.h>
+#include <stdio.h>
+
+void _cdecl main(int argc, char *argv[])
+{
+ IRunningObjectTable *prot = NULL;
+ HRESULT hr;
+ IBindCtx *pbc = NULL;
+ IEnumMoniker * penumMoniker = NULL;
+ IMoniker *alpMonikers[100];
+ DWORD dwReturned;
+ DWORD dwTotalCount = 0;
+ BOOL fFlushROT = FALSE;
+
+
+
+ hr = CoInitialize(NULL);
+
+ if (FAILED(hr))
+ {
+ printf("CoInitialize fails %x\n",hr);
+ exit(-1);
+ }
+
+ if ((argc == 2) && strcmp(argv[1],"-f"))
+ {
+ printf("Valid flags are -f for flush\n");
+ goto exitNow;
+ }
+
+ if( argc == 2)
+ {
+ fFlushROT = TRUE;
+ printf("Flushing ROT as we go!\n");
+ }
+
+ hr = GetRunningObjectTable(0,&prot);
+ if (FAILED(hr))
+ {
+ printf("Get ROT failed! %x\n",hr);
+ goto exitNow;
+ }
+
+ hr = prot->EnumRunning(&penumMoniker);
+ if (FAILED(hr))
+ {
+ printf("Enum ROT has failed %x\n",hr);
+ goto exitNow;
+ }
+
+ hr = CreateBindCtx(0,&pbc);
+ if(FAILED(hr))
+ {
+ printf("CreateBindContext returned %x\n",hr);
+ goto exitNow;
+ }
+
+ do
+ {
+ hr = penumMoniker->Next(100,alpMonikers,&dwReturned);
+ if(FAILED(hr))
+ {
+ printf("penumMoniker->Next failed %x\n",hr);
+ goto exitNow;
+ }
+
+ for (DWORD i = 0 ; i < dwReturned ; i++)
+ {
+ LPWSTR pwcName;
+
+ if(alpMonikers[i] == NULL) continue;
+
+ hr = alpMonikers[i]->GetDisplayName(pbc,NULL,&pwcName);
+
+ if(FAILED(hr))
+ {
+ printf("** MONIKER %x RETURNED ERRORCODE %x",i,hr);
+ }
+ else
+ {
+ printf("%S",pwcName);
+ CoTaskMemFree(pwcName);
+ }
+ if(fFlushROT)
+ {
+ IUnknown *punk;
+ hr = prot->GetObject(alpMonikers[i],&punk);
+ if(FAILED(hr))
+ {
+ printf(" Flushed (hr=0x%x)",hr);
+ }
+ else
+ {
+ printf(" Connected. Releasing connection");
+
+ }
+ }
+ printf("\n");
+ alpMonikers[i]->Release();
+
+ }
+ dwTotalCount += dwReturned;
+ } while(dwReturned == 100);
+
+ printf("** Total number of entries is %u\n",dwTotalCount);
+
+exitNow:
+ if(prot != NULL)
+ {
+ prot->Release();
+ }
+ if(penumMoniker != NULL)
+ {
+ penumMoniker->Release();
+ }
+ if(pbc != NULL)
+ {
+ pbc->Release();
+ }
+
+ CoUninitialize();
+
+
+}
diff --git a/private/ole32/olethunk/tools/rotdump/sources b/private/ole32/olethunk/tools/rotdump/sources
new file mode 100644
index 000000000..e3955867a
--- /dev/null
+++ b/private/ole32/olethunk/tools/rotdump/sources
@@ -0,0 +1,24 @@
+MAJORCOMP=olethunk
+MINORCOMP=rotdump
+
+TARGETPATH=obj
+TARGETNAME=rotdump
+TARGETTYPE=PROGRAM
+
+SOURCES= rotdump.cxx
+
+UMTYPE=console
+
+UMAPPL=rotdump
+UMLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\crtdll.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib
+
+USE_CRTDLL=1
+
+
diff --git a/private/ole32/olethunk/tools/upknown/makefile b/private/ole32/olethunk/tools/upknown/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ole32/olethunk/tools/upknown/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/olethunk/tools/upknown/sources b/private/ole32/olethunk/tools/upknown/sources
new file mode 100644
index 000000000..2732f07a1
--- /dev/null
+++ b/private/ole32/olethunk/tools/upknown/sources
@@ -0,0 +1,12 @@
+MAJORCOMP=olethunk
+MINORCOMP=upknown
+
+TARGETPATH=obj
+TARGETNAME=upknown
+TARGETTYPE=PROGRAM
+
+SOURCES=
+
+UMTYPE=console
+
+UMAPPL=upknown
diff --git a/private/ole32/olethunk/tools/upknown/upknown.c b/private/ole32/olethunk/tools/upknown/upknown.c
new file mode 100644
index 000000000..fc9d39138
--- /dev/null
+++ b/private/ole32/olethunk/tools/upknown/upknown.c
@@ -0,0 +1,179 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: UPKNOWN.C
+//
+// Contents: This tool will add the three OLE2 DLL's to the known list
+// for wow.
+//----------------------------------------------------------------------------
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void FindAndDelete(
+ char *psz,
+ char *pszDeleteString
+)
+{
+ char *substr;
+ char temp[1024];
+ char *pstr;
+
+ if ( psz == NULL )
+ {
+ return;
+ }
+
+ while ( TRUE ) {
+ substr = strstr(psz,pszDeleteString);
+ if ( substr == NULL ) {
+ break;
+ }
+
+ pstr = substr;
+ if ((substr > psz) && (substr[-1] == ' '))
+ {
+ substr--;
+ }
+
+ *substr=0;
+ strcat(psz,pstr+strlen(pszDeleteString));
+ }
+
+}
+void FindOrAdd(
+ char *psz,
+ char *pszAddition
+) {
+ char *substr;
+ char temp[1024];
+ char ch;
+
+ strcpy(temp," ");
+ strcat(temp,pszAddition);
+
+ substr = psz;
+ while ( TRUE ) {
+ substr = strstr(substr,temp);
+ if ( substr == NULL ) {
+ break;
+ }
+ ch = *(substr+strlen(temp));
+
+ if ( ch = ' ' || ch == '\0' ) {
+ break;
+ }
+ }
+
+ if ( substr == NULL )
+ {
+ strcat( psz, temp );
+ }
+}
+
+
+int _cdecl main(
+ int argc,
+ char *argv[]
+) {
+ HKEY WowKey;
+ long l;
+ DWORD dwRegValueType;
+ CHAR sz[2048];
+ ULONG ulSize;
+
+ l = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\WOW",
+ 0,
+ KEY_QUERY_VALUE | KEY_SET_VALUE,
+ &WowKey );
+
+ if ( l != 0 ) {
+ printf("Failed to open HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\WOW\n");
+ printf("Do you have administrator privleges?\n");
+ exit(1);
+ }
+
+ ulSize = sizeof(sz);
+
+ l = RegQueryValueEx( WowKey,
+ "KnownDLLs",
+ NULL,
+ &dwRegValueType,
+ sz,
+ &ulSize );
+
+ if ( l != ERROR_SUCCESS )
+ {
+ printf("Failed reading [WOWKEY]\\KnownDLLs\n");
+ printf("Do you have administrator privleges?\n");
+ exit(1);
+ }
+
+ if ( dwRegValueType != REG_SZ ) {
+ printf("Internal error, [WOWKEY]\\KnownDLLs is not a REG_SZ (string)\n");
+ exit(1);
+ }
+
+ printf("\nKey was: \"%s\"\n\n", sz );
+
+ switch (argc)
+ {
+ case 1:
+ FindOrAdd( sz, "compobj.dll" );
+ FindOrAdd( sz, "storage.dll" );
+ FindOrAdd( sz, "ole2.dll" );
+ FindOrAdd( sz, "ole2disp.dll" );
+ FindOrAdd( sz, "typelib.dll" );
+ FindOrAdd( sz, "ole2nls.dll" );
+ break;
+ case 2:
+ if( (strcmp(argv[1],"-r") == 0) ||
+ (strcmp(argv[1],"/r") == 0))
+ {
+ FindAndDelete( sz, "compobj.dll" );
+ FindAndDelete( sz, "storage.dll" );
+ FindAndDelete( sz, "ole2.dll" );
+ FindAndDelete( sz, "ole2disp.dll" );
+ FindAndDelete( sz, "typelib.dll" );
+ FindAndDelete( sz, "ole2nls.dll" );
+ }
+ else
+ {
+ printf("Unknown parameters\n");
+ exit(1);
+ }
+
+ break;
+ default:
+ printf("Too many parameters\n");
+ exit(1);
+
+ }
+
+
+ printf("Key is now: \"%s\"\n\n", sz );
+
+ ulSize = strlen( sz );
+
+ l = RegSetValueEx( WowKey,
+ "KnownDLLs",
+ 0,
+ dwRegValueType,
+ sz,
+ ulSize+1 );
+
+ if ( l != ERROR_SUCCESS ) {
+ printf("Error setting value (l=%ld,0x%08lX)\n",l,l);
+ printf("Do you have administrator privleges?\n");
+ exit(1);
+ }
+
+
+ l = RegCloseKey( WowKey );
+
+ return(0);
+}
diff --git a/private/ole32/olethunk/tools/zapknown/makefile b/private/ole32/olethunk/tools/zapknown/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ole32/olethunk/tools/zapknown/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/olethunk/tools/zapknown/sources b/private/ole32/olethunk/tools/zapknown/sources
new file mode 100644
index 000000000..bbc598f3f
--- /dev/null
+++ b/private/ole32/olethunk/tools/zapknown/sources
@@ -0,0 +1,12 @@
+MAJORCOMP=olethunk
+MINORCOMP=zapknown
+
+TARGETPATH=obj
+TARGETNAME=zapknown
+TARGETTYPE=PROGRAM
+
+SOURCES=
+
+UMTYPE=console
+
+UMAPPL=zapknown
diff --git a/private/ole32/olethunk/tools/zapknown/zapknown.c b/private/ole32/olethunk/tools/zapknown/zapknown.c
new file mode 100644
index 000000000..558cf5a65
--- /dev/null
+++ b/private/ole32/olethunk/tools/zapknown/zapknown.c
@@ -0,0 +1,62 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ZAPKNOWN.C
+//
+// Contents: This tool will remove the OLE KnownDLL's entries from the
+// registry.
+//----------------------------------------------------------------------------
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void ZapEntry(HKEY hKnownKey,char *pszEntry)
+{
+ long l;
+
+ l = RegDeleteValue(hKnownKey,pszEntry);
+ if (l == ERROR_FILE_NOT_FOUND)
+ {
+ printf("FYI: %s isn't in the KnownDLL list (no problem)\n",pszEntry);
+ } else if(l != ERROR_SUCCESS)
+ {
+ printf("Warning: Could not delete %s (error 0x%x)\n",pszEntry,l);
+ }
+}
+int _cdecl main(
+ int argc,
+ char *argv[]
+) {
+ HKEY hKnownKey;
+ long l;
+ DWORD dwRegValueType;
+ CHAR sz[2048];
+ ULONG ulSize;
+
+ l = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\KnownDLLs",
+ 0,
+ KEY_QUERY_VALUE | KEY_SET_VALUE,
+ &hKnownKey );
+
+ if ( l != 0 ) {
+ printf("Failed to open HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\KnownDLLs\n");
+ printf("Do you have administrator privleges?\n");
+ exit(1);
+ }
+
+ //
+ // Delete OLE32.DLL, OLETHK32.DLL, OLEPRX32.DLL, and OLECNV32.DLL
+ //
+ ZapEntry(hKnownKey,"OLE32");
+ ZapEntry(hKnownKey,"OLEAUT32");
+ ZapEntry(hKnownKey,"OLETHK32");
+ ZapEntry(hKnownKey,"OLECNV32");
+
+ l = RegCloseKey( hKnownKey );
+
+ return(0);
+}
diff --git a/private/ole32/olethunk/utest/simple/makefile b/private/ole32/olethunk/utest/simple/makefile
new file mode 100644
index 000000000..190f6df6d
--- /dev/null
+++ b/private/ole32/olethunk/utest/simple/makefile
@@ -0,0 +1,121 @@
+# simple Thunk DLL makefile
+#
+# Copyright (c) 1991, Microsoft Corporation
+#
+# History:
+#
+# 18-Feb-1994 BobDay Adapted from MVDM\WOW16\GDI\MAKEFILE
+#
+
+!IFDEF USEBUILD
+
+# If using BUILD.EXE, edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2.
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+!ELSE
+
+.SUFFIXES:
+.SUFFIXES: .c .cxx .asm .h .inc .obj .lst .sys .exe .com .map .sym .def .lib .rc .res
+
+
+!ifdef INCLUDE
+INCS =
+!else
+INCS = -I..\..\ole16\inc -I$(BASEDIR)\public\sdk\inc
+!endif
+
+# work around stupid bug in RC 3.1 that doesn't allow rcpp.err to be
+# in a directory that is greater than 128 chars down the path, even if
+# rc 3.1 is running as an OS/2 app.
+PATH = ..\..\ole16\tools;$(PATH)
+
+DEFINES = -DWOW
+
+AOBJ = -Mx -t $(DEFINES) $(INCS)
+
+CW16 = -G2sw -GA -Asnw -DWIN16 $(DEFINES) $(INCS)
+
+LINK = /map /align:16
+
+!if "$(NTDEBUG)"!="" && "$(NTDEBUG)"!="retail"
+!if "$(NTDEBUGTYPE)"=="windbg"
+AOBJ = $(AOBJ) -Zi
+CW16 = $(CW16) /Odi /Zip
+LINK = $(LINK) /CO
+!else
+AOBJ = $(AOBJ) -Zd
+CW16 = $(CW16) /Odi /Zd
+LINK = $(LINK) /LI
+!endif
+!else
+CW16 = $(CW16) /Os /Zp
+!endif
+
+W16LIBS = ..\..\ole16\lib\slibcew.lib ..\..\ole16\lib\libw.lib ..\..\ole16\compobj\compobj.lib
+
+
+.asm.obj:
+ masm $(AOBJ) $*;
+
+.asm.lst:
+ masm $(AOBJ) -l $*,nul,$*.lst;
+
+
+.c.obj:
+ cl16 -c -nologo $(CW16) $*.c
+
+.c.lst:
+ cl16 -c -nologo $(CW16) -Fonul -Fc$*.lst $*.c
+
+.cxx.obj:
+ cl16 -c -nologo $(CW16) $*.cxx
+
+.cxx.lst:
+ cl16 -c -nologo $(CW16) -Fonul -Fc$*.lst $*.cxx
+
+
+.def.lib:
+ implib $*.lib $*.def
+
+.map.sym:
+ mapsym $*
+
+.rc.res:
+ rc16 -r $(INCS) -fo $@ $*.rc
+
+all: simple.exe simple.sym
+ binplace simple.exe
+ binplace simple.sym
+ binplace simple.map
+
+cleanup:
+ if exist *.lrf del *.lrf
+ if exist *.obj del *.obj
+ if exist *.exe del *.exe
+ if exist *.map del *.map
+ if exist *.sym del *.sym
+ if exist *.res del *.res
+
+clean: cleanup
+
+simple.obj: simple.c simple.h
+
+simple.lrf: makefile
+ echo simple.obj >simple.lrf
+ echo simple.exe >>simple.lrf
+ echo simple $(LINK)>>simple.lrf
+ echo /NOD $(W16LIBS) /nod >>simple.lrf
+ echo simple;>>simple.lrf
+
+simple.res: $*.rc simple.h
+
+simple.exe simple.map: simple.obj simple.lrf \
+ simple.def simple.res
+ link16 @simple.lrf;
+ rc16 -t simple.res simple.exe
+
+
+!ENDIF
diff --git a/private/ole32/olethunk/utest/simple/simple.c b/private/ole32/olethunk/utest/simple/simple.c
new file mode 100644
index 000000000..9cfc78849
--- /dev/null
+++ b/private/ole32/olethunk/utest/simple/simple.c
@@ -0,0 +1,202 @@
+
+#include <windows.h>
+#include <ole2.h>
+#include "simple.h"
+
+HANDLE hInst; /* current instance */
+
+int PASCAL WinMain(
+ HANDLE hInstance,
+ HANDLE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nCmdShow
+) {
+ MSG msg;
+ HDC hdc;
+
+ if (!hPrevInstance) /* Other instances of app running? */
+ if (!InitApplication(hInstance)) /* Initialize shared things */
+ return (FALSE); /* Exits if unable to initialize */
+
+ /* Perform initializations that apply to a specific instance */
+
+ if (!InitInstance(hInstance, nCmdShow))
+ return (FALSE);
+
+ /* Acquire and dispatch messages until a WM_QUIT message is received. */
+ while ( GetMessage(&msg, NULL, 0,0) ) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+}
+
+
+BOOL InitApplication(hInstance)
+HANDLE hInstance;
+{
+ WNDCLASS wc;
+
+ wc.style = CS_OWNDC; /* Class style(s). */
+ wc.lpfnWndProc = MainWndProc; /* Function to retrieve messages for */
+ /* windows of this class. */
+ wc.cbClsExtra = 0; /* No per-class extra data. */
+ wc.cbWndExtra = 0; /* No per-window extra data. */
+ wc.hInstance = hInstance; /* Application that owns the class. */
+ wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
+ wc.lpszMenuName = "SimpleMenu"; /* Name of menu resource in .RC file. */
+ wc.lpszClassName = "SimpleClass"; /* Name used in call to CreateWindow. */
+
+ /* Register the window class and return success/failure code. */
+
+ return (RegisterClass(&wc));
+
+}
+
+BOOL InitInstance(hInstance, nCmdShow)
+ HANDLE hInstance; /* Current instance identifier. */
+ int nCmdShow; /* Param for first ShowWindow() call. */
+{
+ HWND hWnd; /* Main window handle. */
+ HWND hWndX;
+ OFSTRUCT ofFileData;
+ HANDLE hLogFile;
+ HDC hDC;
+ int i;
+ SIZE size;
+ int length;
+ BOOL f;
+
+ hInst = hInstance;
+
+ /* Create a main window for this application instance. */
+
+ hWnd = CreateWindow(
+ "SimpleClass", /* See RegisterClass() call. */
+ "OLE 2.0 Simple Thunk Testing", /* Text for window title bar. */
+ WS_OVERLAPPEDWINDOW, /* Window style. */
+ 280, /* Default horizontal position. */
+ 50, /* Default vertical position. */
+ CW_USEDEFAULT, /* Default width. */
+ CW_USEDEFAULT, /* Default height. */
+ NULL, /* Overlapped windows have no parent. */
+ NULL, /* Use the window class menu. */
+ hInstance, /* This instance owns this window. */
+ NULL /* Pointer not needed. */
+ );
+
+ /* If window could not be created, return "failure" */
+
+ if (!hWnd)
+ return (FALSE);
+
+ ShowWindow(hWnd, nCmdShow); /* Show the window */
+ UpdateWindow(hWnd); /* Sends WM_PAINT message */
+
+ return (TRUE); /* Returns the value from PostQuitMessage */
+
+}
+
+void LogResult( LPSTR message, HRESULT hr )
+{
+ char text[256];
+
+ if ( hr ) {
+ wsprintf(text,"%s:%08lX\n",message,hr);
+ OutputDebugString(text);
+ }
+}
+
+
+LONG FAR PASCAL MainWndProc(hWnd, message, wParam, lParam)
+HWND hWnd; /* window handle */
+UINT message; /* type of message */
+WPARAM wParam; /* additional information */
+LONG lParam; /* additional information */
+{
+ FARPROC lpProcAbout; /* pointer to the "About" function */
+ PAINTSTRUCT ps;
+ long rc;
+ int i;
+ HRESULT hr;
+
+ switch (message) {
+ case WM_COMMAND: /* message: command from application menu */
+ switch( wParam ) {
+ case IDM_ABOUT:
+ lpProcAbout = MakeProcInstance(About, hInst);
+
+ DialogBox(hInst, /* current instance */
+ "AboutBox", /* resource to use */
+ hWnd, /* parent handle */
+ lpProcAbout); /* About() instance address */
+
+ FreeProcInstance(lpProcAbout);
+ break; /* Lets Windows process it */
+ default:
+ { char text[100];
+ HDC hdc;
+ static int position = 0;
+ position += 20;
+ wsprintf(text,"Cmd = %04X",wParam);
+ hdc = GetDC( hWnd );
+ TextOut(hdc,100,position,text,lstrlen(text));
+ ReleaseDC( hWnd, hdc );
+ }
+ return (DefWindowProc(hWnd, message, wParam, lParam));
+ case IDM_COINIT:
+ hr = CoInitialize(NULL);
+ LogResult( "CoInitialize", hr );
+
+ break;
+ }
+ break;
+
+ case WM_DESTROY: /* message: window being destroyed */
+
+ PostQuitMessage(0);
+ break;
+
+ case WM_PAINT:
+ {
+ PAINTSTRUCT ps;
+ HDC hDC;
+ char text[100];
+
+ hDC = BeginPaint( hWnd, &ps );
+
+
+ EndPaint( hWnd, &ps );
+ }
+ break;
+
+ default: /* Passes it on if unproccessed */
+ rc = DefWindowProc(hWnd, message, wParam, lParam);
+ return( rc );
+ }
+ return (NULL);
+}
+
+
+BOOL FAR PASCAL About(hDlg, message, wParam, lParam)
+HWND hDlg; /* window handle of the dialog box */
+UINT message; /* type of message */
+WPARAM wParam; /* message-specific information */
+LONG lParam;
+{
+
+ switch (message) {
+ case WM_INITDIALOG: /* message: initialize dialog box */
+ return (TRUE);
+
+ case WM_COMMAND: /* message: received a command */
+ if (wParam == IDOK /* "OK" box selected? */
+ || wParam == IDCANCEL) { /* System menu close command? */
+ EndDialog(hDlg, TRUE); /* Exits the dialog box */
+ return (TRUE);
+ }
+ break;
+ }
+ return (FALSE); /* Didn't process a message */
+}
diff --git a/private/ole32/olethunk/utest/simple/simple.def b/private/ole32/olethunk/utest/simple/simple.def
new file mode 100644
index 000000000..96a4a587d
--- /dev/null
+++ b/private/ole32/olethunk/utest/simple/simple.def
@@ -0,0 +1,28 @@
+; module-definition file for generic -- used by LINK.EXE
+
+NAME Simple ; application's module name
+
+DESCRIPTION 'Sample Microsoft Windows Application'
+
+EXETYPE WINDOWS ; required for all Windows applications
+
+STUB 'WINSTUB.EXE' ; Generates error message if application
+ ; is run without Windows
+
+;CODE can be moved in memory and discarded/reloaded
+CODE PRELOAD MOVEABLE DISCARDABLE
+
+;DATA must be MULTIPLE if program can be invoked more than once
+DATA PRELOAD MOVEABLE MULTIPLE
+
+
+HEAPSIZE 1024
+STACKSIZE 5120 ; recommended minimum for Windows applications
+
+
+; All functions that will be called by any Windows routine
+; MUST be exported.
+
+EXPORTS
+ MainWndProc @1 ; name of window processing function
+ About @2 ; name of "About" processing function
diff --git a/private/ole32/olethunk/utest/simple/simple.h b/private/ole32/olethunk/utest/simple/simple.h
new file mode 100644
index 000000000..787616760
--- /dev/null
+++ b/private/ole32/olethunk/utest/simple/simple.h
@@ -0,0 +1,8 @@
+#define IDM_ABOUT 200
+#define IDM_COINIT 101
+
+int PASCAL WinMain(HANDLE, HANDLE, LPSTR, int);
+BOOL InitApplication(HANDLE);
+BOOL InitInstance(HANDLE, int);
+LONG FAR PASCAL MainWndProc(HWND, UINT, WPARAM, LONG);
+BOOL FAR PASCAL About(HWND, UINT, WPARAM, LONG);
diff --git a/private/ole32/olethunk/utest/simple/simple.rc b/private/ole32/olethunk/utest/simple/simple.rc
new file mode 100644
index 000000000..40aa006ad
--- /dev/null
+++ b/private/ole32/olethunk/utest/simple/simple.rc
@@ -0,0 +1,21 @@
+#include <windows.h>
+#include "simple.h"
+
+SimpleMenu MENU
+BEGIN
+ POPUP "&Tests"
+ BEGIN
+ MENUITEM "&CoInitialize", IDM_COINIT
+ MENUITEM "&About", IDM_ABOUT
+ END
+END
+
+AboutBox DIALOG 22, 17, 144, 75
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU | DS_NOIDLEMSG
+CAPTION "About Simple"
+BEGIN
+ CTEXT "Microsoft Windows" -1, 0, 5, 144, 8
+ CTEXT "OLE 2.0 Simple Thunk Test", -1, 0, 14, 144, 8
+ CTEXT "Version 3.0" -1, 0, 34, 144, 8
+ DEFPUSHBUTTON "OK" IDOK, 53, 59, 32, 14, WS_GROUP
+END
diff --git a/private/ole32/oleui/clspsht.cpp b/private/ole32/oleui/clspsht.cpp
new file mode 100644
index 000000000..45e184029
--- /dev/null
+++ b/private/ole32/oleui/clspsht.cpp
@@ -0,0 +1,1081 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: clspsht.cpp
+//
+// Contents: Implements class CClsidPropertySheet
+//
+// Classes:
+//
+// Methods: CClsidPropertySheet::CClsidPropertySheet
+// CClsidPropertySheet::~CClsidPropertySheet
+// CClsidPropertySheet::InitData
+// CClsidPropertySheet::OnNcCreate
+// CClsidPropertySheet::ValidateAndUpdate
+// CClsidPropertySheet::OnCommand
+// CClsidPropertySheet::LookAtCLSIDs
+// CClsidPropertySheet::ChangeCLSIDInfo
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+#include "stdafx.h"
+#include "afxtempl.h"
+#include "resource.h"
+#include "clspsht.h"
+#include "datapkt.h"
+extern "C"
+{
+#include <getuser.h>
+}
+#include "util.h"
+#include "newsrvr.h"
+#include "datapkt.h"
+#include "virtreg.h"
+
+extern "C"
+{
+#include <sedapi.h>
+#include <ntlsa.h>
+}
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char BASED_CODE THIS_FILE[] = __FILE__;
+#endif
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CClsidPropertySheet
+
+IMPLEMENT_DYNAMIC(CClsidPropertySheet, CPropertySheet)
+
+CClsidPropertySheet::CClsidPropertySheet(CWnd* pParentWnd)
+ : CPropertySheet(IDS_PROPSHT_CAPTION1, pParentWnd)
+{
+}
+
+CClsidPropertySheet::~CClsidPropertySheet()
+{
+}
+
+BEGIN_MESSAGE_MAP(CClsidPropertySheet, CPropertySheet)
+ //{{AFX_MSG_MAP(CClsidPropertySheet)
+ ON_WM_NCCREATE()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+CClsidPropertySheet::InitData(
+ CString szAppName,
+ HKEY hkAppID,
+ HKEY * rghkCLSID,
+ unsigned cCLSIDs)
+{
+ m_szAppName = szAppName;
+ m_hkAppID = hkAppID;
+ m_rghkCLSID = rghkCLSID;
+ m_cCLSIDs = cCLSIDs;
+
+ // Save the appid key, the table of clsid keys and the application
+ // title globally so the property pages can access them
+ // it
+ g_hAppid = hkAppID;
+ g_rghkCLSID = rghkCLSID;
+ g_cCLSIDs = cCLSIDs;
+ g_szAppTitle = (TCHAR *) LPCTSTR(szAppName);
+
+ m_Page2.m_fRemote = FALSE;
+ m_Page4.m_fService = FALSE;
+ m_Page2.m_fCanBeLocal = FALSE;
+ m_Page2.m_fLocal = FALSE;
+ m_Page1.m_fSurrogate = FALSE;
+
+ if (!LookAtCLSIDs())
+ {
+ return FALSE;
+ }
+
+ TCHAR szBuffer[MAX_PATH];
+ DWORD dwSize;
+ long lErr;
+
+ dwSize = sizeof(szBuffer);
+ lErr = RegQueryValueEx(
+ m_hkAppID,
+ TEXT("LocalService"),
+ NULL,
+ NULL,
+ (BYTE *)szBuffer,
+ &dwSize);
+ if (lErr == ERROR_SUCCESS)
+ {
+ m_Page1.m_szServerPath = szBuffer;
+ m_Page4.m_fService = TRUE;
+ m_Page2.m_fCanBeLocal = TRUE;
+ m_Page2.m_fLocal = TRUE;
+ }
+ else
+ {
+ dwSize = sizeof(szBuffer);
+ lErr = RegQueryValueEx(
+ m_hkAppID,
+ TEXT("_LocalService"),
+ NULL,
+ NULL,
+ (BYTE *)szBuffer,
+ &dwSize);
+ if (lErr == ERROR_SUCCESS)
+ {
+ m_Page1.m_szServerPath = szBuffer;
+ m_Page4.m_fService = TRUE;
+ m_Page2.m_fCanBeLocal = TRUE;
+ }
+ }
+
+ dwSize = sizeof(szBuffer);
+
+ if (!m_Page2.m_fLocal)
+ {
+ lErr = RegQueryValueEx(
+ m_hkAppID,
+ TEXT("DllSurrogate"),
+ NULL,
+ NULL,
+ (BYTE *)szBuffer,
+ &dwSize);
+ if (lErr == ERROR_SUCCESS)
+ {
+ if (szBuffer[0])
+ m_Page1.m_szServerPath = szBuffer;
+ else
+ m_Page1.m_szServerPath.LoadString(IDS_DEFAULT);
+ m_Page1.m_fSurrogate = TRUE;
+ }
+
+ }
+ dwSize = sizeof(szBuffer);
+
+ lErr = RegQueryValueEx(
+ m_hkAppID,
+ TEXT("RemoteServerName"),
+ NULL,
+ NULL,
+ (BYTE *)szBuffer,
+ &dwSize);
+ if (lErr == ERROR_SUCCESS)
+ {
+ m_Page1.m_szComputerName = szBuffer;
+ m_Page2.m_szComputerName = szBuffer;
+ m_Page2.m_fRemote = TRUE;
+ }
+
+ m_Page2.m_fAtStorage = FALSE;
+ dwSize = sizeof(szBuffer);
+ lErr = RegQueryValueEx(
+ m_hkAppID,
+ TEXT("ActivateAtStorage"),
+ NULL,
+ NULL,
+ (BYTE *)szBuffer,
+ &dwSize);
+ if (lErr == ERROR_SUCCESS)
+ {
+ if (szBuffer[0] == L'Y' || szBuffer[0] == L'y')
+ {
+// m_Page2.m_fRemote = TRUE;
+ m_Page2.m_fAtStorage = TRUE;
+ }
+ }
+
+ dwSize = sizeof(szBuffer);
+ lErr = RegQueryValueEx(
+ m_hkAppID,
+ TEXT("RunAs"),
+ NULL,
+ NULL,
+ (BYTE *)szBuffer,
+ &dwSize);
+ if (lErr == ERROR_SUCCESS)
+ {
+ // If the RunAs name is empty, jam in something
+ if (szBuffer[0] == TEXT('\0'))
+ {
+ _tcscpy(szBuffer, TEXT("<domain>\\<user>"));
+ }
+
+ if (0 == _tcscmp(szBuffer, TEXT("Interactive User")))
+ {
+ m_Page4.m_iIdentity = 0;
+ }
+ else
+ {
+ m_Page4.m_iIdentity = 2;
+ m_Page4.m_szUserName = szBuffer;
+
+ // Extract password from the Lsa private database
+ g_util.RetrieveUserPassword(g_szAppid , m_Page4.m_szPassword);
+ m_Page4.m_szConfirmPassword = m_Page4.m_szPassword;
+ }
+ }
+ else
+ {
+ if (m_Page4.m_fService)
+ {
+ m_Page4.m_iIdentity = 3;
+ }
+ else
+ {
+ m_Page4.m_iIdentity = 1;
+ }
+ }
+
+ m_Page1.m_szServerName = m_szAppName;
+
+ if (!m_Page1.m_fSurrogate)
+ {
+ if (m_Page2.m_fCanBeLocal)
+ {
+ if (m_Page4.m_fService)
+ m_Page1.m_iServerType = SERVICE;
+ else
+ m_Page1.m_iServerType = LOCALEXE;
+ if (m_Page2.m_fRemote)
+ m_Page1.m_iServerType += 3;
+ }
+ else
+ m_Page1.m_iServerType = PURE_REMOTE;
+ }
+ else
+ {
+ m_Page1.m_iServerType = SURROGATE;
+ }
+
+
+ // Set the title
+ SetTitle((const TCHAR *) m_szAppName, PSH_PROPTITLE);
+ m_Page1.m_szServerName = m_szAppName;
+
+ // TODO: If there are running instances, then make IDC_RUNNING,
+ // IDC_LIST2, IDC_BUTTON1, IDC_BUTTON2, and IDC_BUTTON3 visible
+ // and fill in IDC_LIST2 on page 1.
+
+ m_Page2.m_pPage1 = &m_Page1;
+
+
+ // Fetch RunAs key, LaunchPermission, AccessPermission and
+ // ConfigurationPermission
+ int err;
+ DWORD dwType;
+ BYTE bValue[16];
+ BYTE *pbValue = NULL;
+ ULONG ulSize = 1;
+
+ m_Page3.m_iAccess = 0;
+ m_Page3.m_iLaunch = 0;
+ m_Page3.m_iConfig = 0;
+
+ // "AccessPermission"
+ // Note: We always expect to get ERROR_MORE_DATA
+ err = RegQueryValueEx(g_hAppid, TEXT("AccessPermission"), 0,
+ &dwType, bValue, &ulSize);
+ if (err == ERROR_MORE_DATA)
+ {
+ pbValue = new BYTE[ulSize];
+ if (pbValue == NULL)
+ {
+ return FALSE;
+ }
+ err = RegQueryValueEx(g_hAppid, TEXT("AccessPermission"), 0,
+ &dwType, pbValue, &ulSize);
+ }
+
+ if (err == ERROR_SUCCESS && g_util.CheckForValidSD((SECURITY_DESCRIPTOR *)pbValue))
+ {
+ m_Page3.m_iAccess = 1;
+ g_virtreg.NewRegSingleACL(g_hAppid,
+ NULL,
+ TEXT("AccessPermission"),
+ (SECURITY_DESCRIPTOR *) pbValue,
+ TRUE, // Already in self-relative form
+ &m_Page3.m_iAccessIndex);
+ CDataPacket &cdb = g_virtreg.GetAt(m_Page3.m_iAccessIndex);
+ cdb.fDirty = FALSE;
+ }
+ delete pbValue;
+ pbValue = NULL;
+
+ // "LaunchPermission"
+ // Note: We always expect to get ERROR_MORE_DATA
+ ulSize = 1;
+ pbValue = NULL;
+ err = RegQueryValueEx(g_hAppid, TEXT("LaunchPermission"), 0,
+ &dwType, bValue, &ulSize);
+ if (err == ERROR_MORE_DATA)
+ {
+ pbValue = new BYTE[ulSize];
+ if (pbValue == NULL)
+ {
+ return FALSE;
+ }
+ err = RegQueryValueEx(g_hAppid, TEXT("LaunchPermission"), 0,
+ &dwType, pbValue, &ulSize);
+ }
+
+ if (err == ERROR_SUCCESS && g_util.CheckForValidSD((SECURITY_DESCRIPTOR *)pbValue))
+ {
+ m_Page3.m_iLaunch = 1;
+ g_virtreg.NewRegSingleACL(g_hAppid,
+ NULL,
+ TEXT("LaunchPermission"),
+ (SECURITY_DESCRIPTOR *) pbValue,
+ TRUE, // Already in self-relative form
+ &m_Page3.m_iLaunchIndex);
+ CDataPacket &cdb = g_virtreg.GetAt(m_Page3.m_iLaunchIndex);
+ cdb.fDirty = FALSE;
+ }
+ delete pbValue;
+ pbValue = NULL;
+
+
+ // "ConfigurationPermission"
+
+ // Fetch the security descriptor on this AppID
+ // Note: We always expect to get ERROR_INSUFFICIENT_BUFFER
+ ulSize = 1;
+ err = RegGetKeySecurity(g_hAppid,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ pbValue,
+ &ulSize);
+ if (err == ERROR_INSUFFICIENT_BUFFER)
+ {
+ pbValue = new BYTE[ulSize];
+ if (pbValue == NULL)
+ {
+ return FALSE;
+ }
+ err = RegGetKeySecurity(g_hAppid,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ pbValue,
+ &ulSize);
+ }
+
+ // Fetch the current security descriptor on HKEY_CLASSES_ROOT
+ // Note: We always expect to get ERROR_INSUFFICIENT_BUFFER
+ BYTE *pbValue2 = NULL;
+
+ ulSize = 1;
+ pbValue2 = NULL;
+ err = RegGetKeySecurity(HKEY_CLASSES_ROOT,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ pbValue2,
+ &ulSize);
+ if (err == ERROR_INSUFFICIENT_BUFFER)
+ {
+ pbValue2 = new BYTE[ulSize];
+ if (pbValue2 == NULL)
+ {
+ return FALSE;
+ }
+ err = RegGetKeySecurity(HKEY_CLASSES_ROOT,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ pbValue2,
+ &ulSize);
+ }
+
+ // Now compare them. If they differ then this AppId uses custom
+ // configuration permissions
+
+ if (err == ERROR_SUCCESS && g_util.CheckForValidSD((SECURITY_DESCRIPTOR *)pbValue))
+ {
+ if (!g_util.CompareSDs((PSrSecurityDescriptor) pbValue,
+ (PSrSecurityDescriptor) pbValue2))
+ {
+ err = g_virtreg.NewRegKeyACL(g_hAppid,
+ rghkCLSID,
+ cCLSIDs,
+ g_szAppTitle,
+ (SECURITY_DESCRIPTOR *) pbValue,
+ (SECURITY_DESCRIPTOR *) pbValue,
+ TRUE,
+ &m_Page3.m_iConfigurationIndex);
+ CDataPacket &cdb = g_virtreg.GetAt(m_Page3.m_iConfigurationIndex);
+ cdb.fDirty = FALSE;
+ m_Page3.m_iConfig = 1;
+ }
+ }
+ delete pbValue;
+ delete pbValue2;
+
+
+ // Add all of the property pages here. Note that
+ // the order that they appear in here will be
+ // the order they appear in on screen. By default,
+ // the first page of the set is the active one.
+ // One way to make a different property page the
+ // active one is to call SetActivePage().
+
+ AddPage(&m_Page1);
+ if (m_Page1.m_iServerType != SURROGATE)
+ {
+ AddPage(&m_Page2);
+ }
+ if (m_Page2.m_fCanBeLocal || m_Page1.m_fSurrogate)
+ {
+ AddPage(&m_Page3);
+ AddPage(&m_Page4);
+ }
+ return TRUE;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CClsidPropertySheet message handlers
+
+
+BOOL CClsidPropertySheet::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (!CPropertySheet::OnNcCreate(lpCreateStruct))
+ return FALSE;
+
+ ModifyStyleEx(0, WS_EX_CONTEXTHELP);
+
+ return TRUE;
+}
+
+BOOL CClsidPropertySheet::ValidateAndUpdate(void)
+{
+ // Call update data on all initialized pages
+ // to make sure that their private member variables are correct.
+ long lErr;
+
+ BOOL fReturn = UpdateData(TRUE);
+ if (fReturn && m_Page1.m_hWnd)
+ fReturn = m_Page1.UpdateData(TRUE);
+ if (fReturn && m_Page2.m_hWnd)
+ fReturn = m_Page2.UpdateData(TRUE);
+ if (fReturn && m_Page3.m_hWnd)
+ fReturn = m_Page3.UpdateData(TRUE);
+ if (fReturn && m_Page4.m_hWnd)
+ fReturn = m_Page4.UpdateData(TRUE);
+
+ if (m_Page4.m_iIdentity == 2)
+ {
+ // Check that the username is not blank
+ if (_tcslen(m_Page4.m_szUserName) == 0)
+ {
+ CString szTemp;
+ szTemp.LoadString(IDS_BLANKUSERNAME);
+ MessageBox(szTemp);
+ return FALSE;
+ }
+
+/*
+ // Check that the password is not blank
+ if (_tcslen(m_Page4.m_szPassword) == 0)
+ {
+ CString szTemp;
+ szTemp.LoadString(IDS_BLANKPASSWORD);
+ MessageBox(szTemp);
+ return FALSE;
+ }
+*/
+
+ // Check that the password has been confirmed
+ if (m_Page4.m_szPassword != m_Page4.m_szConfirmPassword)
+ {
+ CString szTemp;
+ szTemp.LoadString(IDS_NOMATCH);
+ MessageBox(szTemp);
+ fReturn = FALSE;
+ }
+ CString szUserName;
+ CString szDomain;
+ int iSplitPoint = m_Page4.m_szUserName.ReverseFind('\\');
+ if (iSplitPoint < 0)
+ {
+ DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
+ TCHAR *szNewDomain;
+
+ // user didn't specify a domain
+ szNewDomain = new TCHAR[MAX_COMPUTERNAME_LENGTH + 1];
+ if (szNewDomain == NULL)
+ {
+ return FALSE;
+ }
+ if (!GetComputerName(szNewDomain, &dwSize))
+ {
+ g_util.PostErrorMessage();
+ return FALSE;
+ }
+ szDomain = szNewDomain;
+ delete szNewDomain;
+ szUserName = m_Page4.m_szUserName;
+ m_Page4.m_szUserName = szDomain + "\\" + szUserName;
+ }
+ else
+ {
+ // user did specify a domain
+ szDomain = m_Page4.m_szUserName.Left(iSplitPoint);
+ szUserName = m_Page4.m_szUserName.Mid(iSplitPoint + 1);
+ }
+
+
+ // Validate the domain and user name
+ BOOL fOk = FALSE;
+ BYTE sid[256];
+ DWORD cbSid = 256;
+ TCHAR szAcctDomain[MAX_PATH];
+ DWORD cbAcctDomain = MAX_PATH * sizeof(TCHAR);
+ SID_NAME_USE acctType;
+
+ fOk = LookupAccountName(NULL,
+ (TCHAR *) ((LPCTSTR) szUserName),
+ sid,
+ &cbSid,
+ szAcctDomain,
+ &cbAcctDomain,
+ &acctType);
+
+ // if successful, then validate domain name and account type
+ if (fOk)
+ {
+ fOk = (_tcsicmp((TCHAR *) ((LPCTSTR) szDomain), szAcctDomain) == 0
+ &&
+ acctType == SidTypeUser);
+
+ // If still unsuccessful, then try to match the domain against
+ // this computer's name
+ if (!fOk)
+ {
+ TCHAR szThisComputer[MAX_COMPUTERNAME_LENGTH + 1];
+ DWORD dwSize;
+
+ if (GetComputerName(szThisComputer, &dwSize))
+ {
+ fOk = (_tcsicmp((TCHAR *) ((LPCTSTR) szThisComputer),
+ szAcctDomain) == 0
+ &&
+ acctType == SidTypeUser);
+ }
+ }
+ }
+
+ if (!fOk)
+ {
+ CString szTemp;
+ szTemp.LoadString(IDS_NOACCOUNT);
+ MessageBox(szTemp);
+ return FALSE;
+ }
+
+
+ // Write the RunAs password to the Lsa private database
+ // (Note: We do this even if it's a service since QueryServiceConfig
+ // doesn't return the password, though we can use ChangeServiceConfig
+ // to set the password in the service database.)
+ if (!g_util.StoreUserPassword(g_szAppid, m_Page4.m_szPassword))
+ {
+ g_util.PostErrorMessage();
+ }
+
+ // Add rights to this user's account for "SeBatchLogonRight"
+ int err;
+
+ if (err = g_util.SetAccountRights((LPCTSTR) szUserName,
+ SE_BATCH_LOGON_NAME)
+ != ERROR_SUCCESS)
+ {
+ g_util.PostErrorMessage(err);
+ }
+
+ }
+
+ // Check that remote servers are valid connectable machines
+ if (m_Page2.m_fRemote)
+ {
+ if (!g_util.VerifyRemoteMachine((TCHAR *) LPCTSTR(m_Page2.m_szComputerName)))
+ {
+ fReturn = FALSE;
+ }
+ }
+
+
+ if (!fReturn)
+ {
+ return FALSE;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////
+ // Persist Location property page data
+ if (m_Page2.m_fAtStorage)
+ {
+ lErr = RegSetValueEx(
+ m_hkAppID,
+ TEXT("ActivateAtStorage"),
+ 0,
+ REG_SZ,
+ (BYTE *)TEXT("Y"),
+ sizeof(TCHAR) * 2);
+ }
+ else
+ {
+ lErr = RegDeleteValue(
+ m_hkAppID,
+ TEXT("ActivateAtStorage"));
+ }
+
+
+ if (m_Page2.m_fRemote)
+ {
+ lErr = RegSetValueEx(
+ m_hkAppID,
+ TEXT("RemoteServerName"),
+ 0,
+ REG_SZ,
+ (BYTE *)(LPCTSTR)m_Page2.m_szComputerName,
+ (1 + m_Page2.m_szComputerName.GetLength()) * sizeof(TCHAR));
+ }
+ else
+ {
+ lErr = RegDeleteValue(
+ m_hkAppID,
+ TEXT("RemoteServerName"));
+ }
+
+
+ ////////////////////////////////////////////////////////////////////
+ // Persist Security property page data
+
+ // Access permissions
+ // Use default access permissions
+ if (m_Page3.m_iAccess == 0)
+ {
+ // Delete the local AccessPermission named value to force this
+ // AppID to use the default global named value DefaultAccessPermission
+ lErr = RegDeleteValue(m_hkAppID, TEXT("AccessPermission"));
+ }
+
+ // Use per AppID access permissions
+ else
+ {
+ // If the user edited security, then persist that now
+ if (m_Page3.m_iAccessIndex >= 0)
+ {
+ lErr = g_virtreg.Apply(m_Page3.m_iAccessIndex);
+ g_virtreg.Remove(m_Page3.m_iAccessIndex);
+ m_Page3.m_iAccessIndex = -1;
+ }
+ }
+
+ // Launch permissions
+ // Use default Launch permissions
+ if (m_Page3.m_iLaunch == 0)
+ {
+ // Delete the local LaunchPermission named value to force this
+ // AppID to use the default global named value DefaultLaunchPermission
+ lErr = RegDeleteValue(m_hkAppID, TEXT("LaunchPermission"));
+ }
+
+ // Use per AppID Launch permissions
+ else
+ {
+ // If the user edited security, then persist that now
+ if (m_Page3.m_iLaunchIndex >= 0)
+ {
+ lErr = g_virtreg.Apply(m_Page3.m_iLaunchIndex);
+ g_virtreg.Remove(m_Page3.m_iLaunchIndex);
+ m_Page3.m_iLaunchIndex = -1;
+ }
+ }
+
+ // Configuration permissions
+ // Only meaningful on a per AppID basis
+ // If the user edited configuration security, then persist that now
+ if (m_Page3.m_iConfigurationIndex >= 0)
+ {
+ lErr = g_virtreg.Apply(m_Page3.m_iConfigurationIndex);
+ g_virtreg.Remove(m_Page3.m_iConfigurationIndex);
+ m_Page3.m_iConfigurationIndex = -1;
+ }
+
+
+
+ ////////////////////////////////////////////////////////////////////
+ // Persist Identity property page data
+ switch (m_Page4.m_iIdentity)
+ {
+ case 0:
+ {
+ CString szTemp;
+ szTemp = TEXT("Interactive User");
+ lErr = RegSetValueEx(
+ m_hkAppID,
+ TEXT("RunAs"),
+ 0,
+ REG_SZ,
+ (BYTE *)(LPCTSTR)szTemp,
+ (1 + szTemp.GetLength()) * sizeof(TCHAR));
+ break;
+ }
+
+ case 1:
+ case 3:
+ lErr = RegDeleteValue(m_hkAppID,
+ TEXT("RunAs"));
+ break;
+
+ case 2:
+ lErr = RegSetValueEx(m_hkAppID,
+ TEXT("RunAs"),
+ 0,
+ REG_SZ,
+ (BYTE *)(LPCTSTR)m_Page4.m_szUserName,
+ (1 + m_Page4.m_szUserName.GetLength()) *
+ sizeof(TCHAR));
+ break;
+ }
+
+ if (m_Page4.m_fService)
+ {
+ if (m_Page2.m_fLocal)
+ {
+ BOOL fOk;
+
+ // Write the LocalService value to the registry
+ lErr = RegSetValueEx(
+ m_hkAppID,
+ TEXT("LocalService"),
+ 0,
+ REG_SZ,
+ (BYTE *)(LPCTSTR)m_Page1.m_szServerPath,
+ (1 + m_Page1.m_szServerPath.GetLength()) * sizeof (TCHAR));
+ lErr = RegDeleteValue(
+ m_hkAppID,
+ TEXT("_LocalService"));
+
+ // Persist information to the service manager database
+ if (m_Page4.m_iIdentity == 3)
+ {
+ fOk = g_util.ChangeService((LPCTSTR) m_Page1.m_szServerPath,
+ TEXT("LocalSystem"),
+ TEXT(""),
+ (LPCTSTR) m_Page1.m_szServerName);
+ }
+ else
+ {
+ fOk = g_util.ChangeService((LPCTSTR) m_Page1.m_szServerPath,
+ (LPCTSTR) m_Page4.m_szUserName,
+ (LPCTSTR) m_Page4.m_szPassword,
+ (LPCTSTR) m_Page1.m_szServerName);
+ }
+ if (!fOk)
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ lErr = RegSetValueEx(
+ m_hkAppID,
+ TEXT("_LocalService"),
+ 0,
+ REG_SZ,
+ (BYTE *)(LPCTSTR)m_Page1.m_szServerPath,
+ (1 + m_Page1.m_szServerPath.GetLength()) * sizeof (TCHAR));
+ lErr = RegDeleteValue(
+ m_hkAppID,
+ TEXT("LocalService"));
+ }
+ }
+
+ return ChangeCLSIDInfo(m_Page2.m_fLocal);
+}
+
+BOOL CClsidPropertySheet::OnCommand(WPARAM wParam, LPARAM lParam)
+{
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ case ID_APPLY_NOW:
+ if (!ValidateAndUpdate())
+ return TRUE;
+ break;
+ }
+ return CPropertySheet::OnCommand(wParam, lParam);
+}
+
+BOOL CClsidPropertySheet::LookAtCLSIDs(void)
+{
+ BOOL fFoundLocalServer = FALSE;
+ TCHAR szBuffer[MAX_PATH];
+ DWORD dwSize;
+ HKEY hKey;
+ long lErr;
+
+ unsigned n = 0;
+ while (n < m_cCLSIDs && !fFoundLocalServer)
+ {
+ lErr = RegOpenKeyEx(
+ m_rghkCLSID[n],
+ TEXT("LocalServer32"),
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ if (lErr == ERROR_SUCCESS)
+ {
+ dwSize = sizeof(szBuffer);
+ lErr = RegQueryValueEx(
+ hKey,
+ TEXT(""),
+ NULL,
+ NULL,
+ (BYTE *)szBuffer,
+ &dwSize);
+ if (lErr == ERROR_SUCCESS)
+ {
+ m_Page1.m_szServerPath = szBuffer;
+ m_Page2.m_fLocal = TRUE;
+ m_Page2.m_fCanBeLocal = TRUE;
+ fFoundLocalServer = TRUE;
+ }
+ RegCloseKey(hKey);
+ }
+
+
+ if (!fFoundLocalServer)
+ {
+ lErr = RegOpenKeyEx(
+ m_rghkCLSID[n],
+ TEXT("LocalServer"),
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ if (lErr == ERROR_SUCCESS)
+ {
+ dwSize = sizeof(szBuffer);
+ lErr = RegQueryValueEx(
+ hKey,
+ TEXT(""),
+ NULL,
+ NULL,
+ (BYTE *)szBuffer,
+ &dwSize);
+ if (lErr == ERROR_SUCCESS)
+ {
+ m_Page1.m_szServerPath = szBuffer;
+ m_Page2.m_fLocal = TRUE;
+ m_Page2.m_fCanBeLocal = TRUE;
+ fFoundLocalServer = TRUE;
+ }
+ RegCloseKey(hKey);
+ }
+ }
+
+ if (!fFoundLocalServer)
+ {
+ lErr = RegOpenKeyEx(
+ m_rghkCLSID[n],
+ TEXT("_LocalServer32"),
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ if (lErr == ERROR_SUCCESS)
+ {
+ dwSize = sizeof(szBuffer);
+ lErr = RegQueryValueEx(
+ hKey,
+ TEXT(""),
+ NULL,
+ NULL,
+ (BYTE *)szBuffer,
+ &dwSize);
+ if (lErr == ERROR_SUCCESS)
+ {
+ m_Page1.m_szServerPath = szBuffer;
+ m_Page2.m_fCanBeLocal = TRUE;
+ fFoundLocalServer = TRUE;
+ }
+ RegCloseKey(hKey);
+ }
+ }
+
+ if (!fFoundLocalServer)
+ {
+ lErr = RegOpenKeyEx(
+ m_rghkCLSID[n],
+ TEXT("_LocalServer"),
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ if (lErr == ERROR_SUCCESS)
+ {
+ dwSize = sizeof(szBuffer);
+ lErr = RegQueryValueEx(
+ hKey,
+ TEXT(""),
+ NULL,
+ NULL,
+ (BYTE *)szBuffer,
+ &dwSize);
+ if (lErr == ERROR_SUCCESS)
+ {
+ m_Page1.m_szServerPath = szBuffer;
+ m_Page2.m_fCanBeLocal = TRUE;
+ fFoundLocalServer = TRUE;
+ }
+ RegCloseKey(hKey);
+ }
+ }
+
+ n++;
+ }
+ return TRUE;
+}
+
+
+
+
+BOOL CClsidPropertySheet::ChangeCLSIDInfo(BOOL fLocal)
+{
+ TCHAR szBuffer[MAX_PATH];
+ CString szOld;
+ CString szNew;
+ CString szOld16;
+ CString szNew16;
+ DWORD dwSize;
+ HKEY hKey;
+ long lErr;
+
+ if (fLocal)
+ {
+ szOld = TEXT("_LocalServer32");
+ szNew = TEXT("LocalServer32");
+ szOld16 = TEXT("_LocalServer");
+ szNew16 = TEXT("LocalServer");
+ }
+ else
+ {
+ szOld = TEXT("LocalServer32");
+ szNew = TEXT("_LocalServer32");
+ szOld16 = TEXT("LocalServer");
+ szNew16 = TEXT("_LocalServer");
+ }
+
+ unsigned n = 0;
+ while (n < m_cCLSIDs)
+ {
+ // First do 32 servers
+ lErr = RegOpenKeyEx(
+ m_rghkCLSID[n],
+ szOld,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ if (lErr == ERROR_SUCCESS)
+ {
+ dwSize = sizeof(szBuffer);
+ lErr = RegQueryValueEx(
+ hKey,
+ TEXT(""),
+ NULL,
+ NULL,
+ (BYTE *)szBuffer,
+ &dwSize);
+ if (lErr == ERROR_SUCCESS)
+ {
+ HKEY hKeyNew;
+ DWORD dwDisp;
+
+ lErr = RegCreateKeyEx(
+ m_rghkCLSID[n],
+ szNew,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL,
+ &hKeyNew,
+ &dwDisp);
+ if (lErr == ERROR_SUCCESS)
+ {
+ lErr = RegSetValueEx(
+ hKeyNew,
+ TEXT(""),
+ NULL,
+ REG_SZ,
+ (BYTE *)szBuffer,
+ dwSize);
+ RegCloseKey(hKeyNew);
+ }
+ }
+ RegCloseKey(hKey);
+ lErr = RegDeleteKey(m_rghkCLSID[n], szOld);
+ }
+
+
+ // Then do 16 servers
+ lErr = RegOpenKeyEx(
+ m_rghkCLSID[n],
+ szOld16,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey);
+ if (lErr == ERROR_SUCCESS)
+ {
+ dwSize = sizeof(szBuffer);
+ lErr = RegQueryValueEx(
+ hKey,
+ TEXT(""),
+ NULL,
+ NULL,
+ (BYTE *)szBuffer,
+ &dwSize);
+ if (lErr == ERROR_SUCCESS)
+ {
+ HKEY hKeyNew;
+ DWORD dwDisp;
+
+ lErr = RegCreateKeyEx(
+ m_rghkCLSID[n],
+ szNew16,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL,
+ &hKeyNew,
+ &dwDisp);
+ if (lErr == ERROR_SUCCESS)
+ {
+ lErr = RegSetValueEx(
+ hKeyNew,
+ TEXT(""),
+ NULL,
+ REG_SZ,
+ (BYTE *)szBuffer,
+ dwSize);
+ RegCloseKey(hKeyNew);
+ }
+ }
+ RegCloseKey(hKey);
+ lErr = RegDeleteKey(m_rghkCLSID[n], szOld16);
+ }
+
+ n++;
+ }
+ return TRUE;
+}
+
diff --git a/private/ole32/oleui/clspsht.h b/private/ole32/oleui/clspsht.h
new file mode 100644
index 000000000..fd69df2ba
--- /dev/null
+++ b/private/ole32/oleui/clspsht.h
@@ -0,0 +1,75 @@
+// ClsPSht.h : header file
+//
+// This class defines custom modal property sheet
+// CClsidPropertySheet.
+
+#ifndef __CLSPSHT_H__
+#define __CLSPSHT_H__
+
+#include "LocPPg.h"
+
+#define INPROC 0
+#define LOCALEXE 1
+#define SERVICE 2
+#define PURE_REMOTE 3
+#define REMOTE_LOCALEXE 4
+#define REMOTE_SERVICE 5
+#define SURROGATE 6
+
+/////////////////////////////////////////////////////////////////////////////
+// CClsidPropertySheet
+
+class CClsidPropertySheet : public CPropertySheet
+{
+ DECLARE_DYNAMIC(CClsidPropertySheet)
+
+// Construction
+public:
+ CClsidPropertySheet(CWnd* pParentWnd = NULL);
+ BOOL InitData(
+ CString szAppName,
+ HKEY hkAppID,
+ HKEY * rghkCLSID,
+ unsigned cCLSIDs);
+
+// Attributes
+public:
+ CGeneralPropertyPage m_Page1;
+ CLocationPropertyPage m_Page2;
+ CSecurityPropertyPage m_Page3;
+ CIdentityPropertyPage m_Page4;
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CClsidPropertySheet)
+ protected:
+ virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ CString m_szAppName;
+ HKEY m_hkAppID;
+ HKEY * m_rghkCLSID;
+ unsigned m_cCLSIDs;
+
+ BOOL ValidateAndUpdate(void);
+ BOOL ChangeCLSIDInfo(BOOL fLocal);
+ BOOL LookAtCLSIDs(void);
+
+ virtual ~CClsidPropertySheet();
+
+// Generated message map functions
+protected:
+ //{{AFX_MSG(CClsidPropertySheet)
+ afx_msg BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // __CLSPSHT_H__
diff --git a/private/ole32/oleui/cnfgdlg.h b/private/ole32/oleui/cnfgdlg.h
new file mode 100644
index 000000000..6e21a998e
--- /dev/null
+++ b/private/ole32/oleui/cnfgdlg.h
@@ -0,0 +1,38 @@
+// CnfgDlg.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// COlecnfgDlg dialog
+
+class COlecnfgDlg : public CDialog
+{
+// Construction
+public:
+ void OnProperties();
+ COlecnfgDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(COlecnfgDlg)
+ enum { IDD = IDD_OLECNFG_DIALOG };
+ // NOTE: the ClassWizard will add data members here
+ //}}AFX_DATA
+
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(COlecnfgDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ HICON m_hIcon;
+
+ // Generated message map functions
+ //{{AFX_MSG(COlecnfgDlg)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
+ afx_msg void OnPaint();
+ afx_msg HCURSOR OnQueryDragIcon();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
diff --git a/private/ole32/oleui/cnfgpsht.cpp b/private/ole32/oleui/cnfgpsht.cpp
new file mode 100644
index 000000000..7350496a8
--- /dev/null
+++ b/private/ole32/oleui/cnfgpsht.cpp
@@ -0,0 +1,159 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: cnfgpsht.cpp
+//
+// Contents: Implements class COlecnfgPropertySheet
+//
+// Classes:
+//
+// Methods: COlecnfgPropertySheet::COlecnfgPropertySheet
+// COlecnfgPropertySheet::~COlecnfgPropertySheet
+// COlecnfgPropertySheet::DoModal
+// COlecnfgPropertySheet::Create
+// COlecnfgPropertySheet::OnNcCreate
+// COlecnfgPropertySheet::OnCommand
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+#include "stdafx.h"
+#include "afxtempl.h"
+#include "resource.h"
+#include "cstrings.h"
+#include "creg.h"
+#include "types.h"
+#include "datapkt.h"
+extern "C"
+{
+#include <getuser.h>
+}
+#include "util.h"
+#include "virtreg.h"
+#include "CnfgPSht.h"
+
+
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char BASED_CODE THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// COlecnfgPropertySheet
+
+IMPLEMENT_DYNAMIC(COlecnfgPropertySheet, CPropertySheet)
+
+COlecnfgPropertySheet::COlecnfgPropertySheet(CWnd* pWndParent)
+ : CPropertySheet(IDS_PROPSHT_CAPTION, pWndParent)
+{
+ // Set the title
+ CString sTitle;
+ sTitle.LoadString(IDS_PSMAIN_TITLE);
+ SetTitle(sTitle, PSH_PROPTITLE);
+
+ // Add all of the property pages here. Note that
+ // the order that they appear in here will be
+ // the order they appear in on screen. By default,
+ // the first page of the set is the active one.
+ // One way to make a different property page the
+ // active one is to call SetActivePage().
+
+ // Disable property sheet help button
+ m_psh.dwFlags &= ~PSH_HASHELP;
+ m_Page1.m_psp.dwFlags &= ~PSH_HASHELP;
+ m_Page2.m_psp.dwFlags &= ~PSH_HASHELP;
+ m_Page3.m_psp.dwFlags &= ~PSH_HASHELP;
+
+ AddPage(&m_Page1);
+ AddPage(&m_Page2);
+ AddPage(&m_Page3);
+}
+
+COlecnfgPropertySheet::~COlecnfgPropertySheet()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(COlecnfgPropertySheet, CPropertySheet)
+ //{{AFX_MSG_MAP(COlecnfgPropertySheet)
+ ON_WM_NCCREATE()
+// ON_COMMAND(ID_HELP, CWnd::OnHelp)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// COlecnfgPropertySheet message handlers
+
+
+
+int COlecnfgPropertySheet::DoModal()
+{
+ // TODO: Add your specialized code here and/or call the base class
+
+ return CPropertySheet::DoModal();
+}
+
+BOOL COlecnfgPropertySheet::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
+{
+ // TODO: Add your specialized code here and/or call the base class
+
+ return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
+}
+
+BOOL COlecnfgPropertySheet::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
+{
+ if (!CPropertySheet::OnNcCreate(lpCreateStruct))
+ return FALSE;
+
+ // Enable context help
+ ModifyStyleEx(0, WS_EX_CONTEXTHELP);
+
+ return TRUE;
+}
+
+BOOL COlecnfgPropertySheet::OnCommand(WPARAM wParam, LPARAM lParam)
+{
+ // TODO: Add your specialized code here and/or call the base class
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ case ID_APPLY_NOW:
+ g_virtreg.ApplyAll();
+
+ // Check whether the user changed something that requires a reboot
+ if (g_fReboot)
+ {
+ g_util.UpdateDCOMInfo();
+
+ // With the above interface to the SCM we don't have to ask the
+ // user whether to reboot. However, I'll keep the code for
+ // posterity.
+/*
+ CString sCaption;
+ CString sMessage;
+
+ sCaption.LoadString(IDS_SYSTEMMESSAGE);
+ sMessage.LoadString(IDS_REBOOT);
+ if (MessageBox(sMessage, sCaption, MB_YESNO) == IDYES)
+ {
+ if (g_util.AdjustPrivilege(SE_SHUTDOWN_NAME))
+ {
+ // Now reboot
+ ExitWindowsEx(EWX_REBOOT, 0);
+ }
+ }
+*/
+ }
+
+ break;
+
+ }
+ return CPropertySheet::OnCommand(wParam, lParam);
+}
+
diff --git a/private/ole32/oleui/cnfgpsht.h b/private/ole32/oleui/cnfgpsht.h
new file mode 100644
index 000000000..c0417cd17
--- /dev/null
+++ b/private/ole32/oleui/cnfgpsht.h
@@ -0,0 +1,69 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: cnfgpsht.h
+//
+// Contents: Defines class COlecnfgPropertySheet
+//
+// Classes:
+//
+// Methods:
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+#ifndef __CNFGPSHT_H__
+#define __CNFGPSHT_H__
+
+#include "SrvPPg.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// COlecnfgPropertySheet
+
+class COlecnfgPropertySheet : public CPropertySheet
+{
+ DECLARE_DYNAMIC(COlecnfgPropertySheet)
+
+// Construction
+public:
+ COlecnfgPropertySheet(CWnd* pParentWnd = NULL);
+
+// Attributes
+public:
+ CServersPropertyPage m_Page1;
+ CMachinePropertyPage m_Page2;
+ CDefaultSecurityPropertyPage m_Page3;
+
+
+// Operations
+public:
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(COlecnfgPropertySheet)
+ public:
+ virtual int DoModal();
+ virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
+ protected:
+ virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
+ //}}AFX_VIRTUAL
+
+// Implementation
+public:
+ virtual ~COlecnfgPropertySheet();
+
+// Generated message map functions
+protected:
+ //{{AFX_MSG(COlecnfgPropertySheet)
+ afx_msg BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // __CNFGPSHT_H__
diff --git a/private/ole32/oleui/creg.cpp b/private/ole32/oleui/creg.cpp
new file mode 100644
index 000000000..6a825d32c
--- /dev/null
+++ b/private/ole32/oleui/creg.cpp
@@ -0,0 +1,550 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: creg.cpp
+//
+// Contents: Implements class CRegistry to wrap registry access
+//
+// Classes:
+//
+// Methods: CRegistry::CRegistry
+// CRegistry::~CRegistry
+// CRegistry::Init
+// CRegistry::InitGetItem
+// CRegistry::GetNextItem
+// CRegistry::GetItem
+// CRegistry::FindItem
+// CRegistry::FindAppid
+// CRegistry::AppendIndex
+// CRegistry::GetNumItems
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+
+#include "stdafx.h"
+#include "resource.h"
+#include "types.h"
+#include "cstrings.h"
+#include "creg.h"
+
+
+
+
+CRegistry::CRegistry(void)
+{
+ m_applications.RemoveAll();
+}
+
+
+CRegistry::~CRegistry(void)
+{
+}
+
+
+
+
+// Access and store all application names and associated appid's
+BOOL CRegistry::Init(void)
+{
+ int err;
+ HKEY hKey;
+ DWORD dwSubKey;
+ TCHAR szKeyName[MAX_PATH];
+ TCHAR szItem[MAX_PATH];
+ TCHAR szTitle[MAX_PATH];
+ TCHAR szAppid[MAX_PATH];
+ TCHAR szBuffer[MAX_PATH];
+ LONG lSize;
+ DWORD dwType;
+ DWORD dwDisposition;
+
+ // Cleanup any previous run
+ m_applications.RemoveAll();
+
+
+ // First enumerate HKEY_CLASSES_ROOT\CLSID picking up all .exe
+
+ // Open HKEY_CLASSES_ROOT\CLSID
+ if (RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, KEY_ALL_ACCESS,
+ &hKey) != ERROR_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ // Enumerate the CLSID subkeys
+ dwSubKey = 0;
+ while (RegEnumKey(hKey, dwSubKey, szKeyName, MAX_PATH * sizeof(TCHAR))
+ == ERROR_SUCCESS)
+ {
+ HKEY hKey2;
+ SRVTYPE srvType;
+
+ // Prepare for next key
+ dwSubKey++;
+
+ // Open this key
+ if (RegOpenKeyEx(hKey, szKeyName, 0, KEY_ALL_ACCESS,
+ &hKey2) == ERROR_SUCCESS)
+ {
+ // Check for subkeys "LocalServer32", "_LocalServer32",
+ // "LocalServer", and "_LocalServer"
+ lSize = MAX_PATH * sizeof(TCHAR);
+ err = RegQueryValue(hKey2, TEXT("LocalServer32"), szItem,
+ &lSize);
+ srvType = LOCALSERVER32;
+
+ if (err != ERROR_SUCCESS)
+ {
+ lSize = MAX_PATH * sizeof(TCHAR);
+ err = RegQueryValue(hKey2, TEXT("_LocalServer32"), szItem,
+ &lSize);
+ srvType = _LOCALSERVER32;
+ }
+
+ if (err != ERROR_SUCCESS)
+ {
+ lSize = MAX_PATH * sizeof(TCHAR);
+ err = RegQueryValue(hKey2, TEXT("LocalServer"), szItem,
+ &lSize);
+ srvType = LOCALSERVER;
+ }
+
+ if (err != ERROR_SUCCESS)
+ {
+ lSize = MAX_PATH * sizeof(TCHAR);
+ err = RegQueryValue(hKey2, TEXT("_LocalServer"), szItem,
+ &lSize);
+ srvType = _LOCALSERVER;
+ }
+
+ if (err != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey2);
+ continue;
+ }
+
+ // Strip off any command line parameters -
+ // it's the executale path that determines an item. Because
+ // of quotes, embedded spaces, etc. we scan for ".exe"
+ int k = 0;
+
+ while (szItem[k])
+ {
+ if (szItem[k] == TEXT('.') &&
+ szItem[k + 1] && (szItem[k + 1] == TEXT('e') ||
+ szItem[k + 1] == TEXT('E')) &&
+ szItem[k + 2] && (szItem[k + 2] == TEXT('x') ||
+ szItem[k + 2] == TEXT('X')) &&
+ szItem[k + 3] && (szItem[k + 3] == TEXT('e') ||
+ szItem[k + 3] == TEXT('E')))
+ {
+ break;
+ }
+
+ k++;
+ }
+
+ // Just continue if we don't have an .exe path
+ if (!szItem[k])
+ {
+ RegCloseKey(hKey2);
+ continue;
+ }
+
+ // Increment to the nominal end of the path
+ k += 4;
+
+ // In case the entire path is surrounded by quotes
+ if (szItem[k] == TEXT('"'))
+ {
+ k++;
+ }
+ szItem[k] = TEXT('\0');
+
+ // Read the AppID for this clsid (if any)
+ BOOL fUseThisClsid = FALSE;
+
+ lSize = MAX_PATH * sizeof(TCHAR);
+ if (RegQueryValueEx(hKey2, TEXT("AppID"), NULL, &dwType,
+ (UCHAR *) szAppid, (ULONG *) &lSize)
+ != ERROR_SUCCESS)
+ {
+ // Use this clsid as the appid
+ fUseThisClsid = TRUE;
+ }
+
+ // If this is a 16-bit server without an existing AppId
+ // named value then skip it
+ if ((srvType == LOCALSERVER || srvType == _LOCALSERVER) &&
+ fUseThisClsid == TRUE)
+ {
+ RegCloseKey(hKey2);
+ continue;
+ }
+
+ // Read the title for the item
+ BOOL fNoTitle = FALSE;
+
+ lSize = MAX_PATH * sizeof(TCHAR);
+ if (RegQueryValueEx(hKey2, NULL, NULL, &dwType,
+ (UCHAR *) szTitle, (ULONG *) &lSize)
+ != ERROR_SUCCESS)
+ {
+ fNoTitle = TRUE;
+ }
+ else if (szTitle[0] == TEXT('\0'))
+ {
+ fNoTitle = TRUE;
+ }
+
+ // If both the item (the executable path) and the title
+ // (the unnamed value on the CLSID) are empty, then skip
+ // this entry
+ if (szItem[0] == TEXT('\0') &&
+ (fNoTitle || szTitle[0] == TEXT('\0')))
+ {
+ RegCloseKey(hKey2);
+ continue;
+ }
+
+ // Check whether we already have this item in the table - we
+ // search differently depending on whether this clsid already
+ // has an associated appid
+ SItem *pItem;
+
+ if (fUseThisClsid)
+ {
+ pItem = FindItem(szItem);
+ }
+ else
+ {
+ pItem = FindAppid(szAppid);
+ }
+
+ if (pItem == NULL)
+ {
+ // Create a new item
+ pItem = m_applications.PutItem(szItem[0] ? szItem : szKeyName,
+ fNoTitle ? szKeyName : szTitle,
+ fUseThisClsid ? szKeyName : szAppid);
+ if (pItem == NULL)
+ {
+ RegCloseKey(hKey2);
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+
+ // Note whether the clsid had an appid named value
+ pItem->fHasAppid = !fUseThisClsid;
+ }
+
+ // Write the AppId for this class if it doesn't exist
+ lSize = MAX_PATH * sizeof(TCHAR);
+ if (RegQueryValueEx(hKey2, TEXT("AppID"), 0, &dwType,
+ (BYTE *) szBuffer, (ULONG *) &lSize)
+ != ERROR_SUCCESS)
+ {
+ if (RegSetValueEx(hKey2, TEXT("AppID"), 0, REG_SZ,
+ (const BYTE *) pItem->szAppid,
+ (_tcslen(pItem->szAppid) + 1) * sizeof(TCHAR))
+ != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey2);
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+ }
+
+ // Now add this clsid to the table of clsid's for this .exe
+ if (!m_applications.AddClsid(pItem, szKeyName))
+ {
+ RegCloseKey(hKey2);
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+
+ // Close the key
+ RegCloseKey(hKey2);
+ }
+ } // End of the enumeration over HKEY_CLASSES_ROOT\CLSID
+
+ // Close the key on HKEY_CLASSES_ROOT\CLSID
+ RegCloseKey(hKey);
+
+
+
+ // Create or open the key "HKEY_CLASSES_ROOT\AppID"
+ if (RegCreateKeyEx(HKEY_CLASSES_ROOT, TEXT("AppID"), 0, NULL,
+ REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey,
+ &dwDisposition) != ERROR_SUCCESS)
+ {
+ return FALSE;
+ }
+
+ // Enumerate keys under HKEY_CLASSES_ROOT\AppID
+ dwSubKey = 0;
+ while (RegEnumKey(hKey, dwSubKey, szKeyName, MAX_PATH * sizeof(TCHAR))
+ == ERROR_SUCCESS)
+ {
+ // Prepare for next key
+ dwSubKey++;
+
+ // Only look at entries having an AppId format
+ if (!(szKeyName[0] == TEXT('{') &&
+ _tcslen(szKeyName) == GUIDSTR_MAX &&
+ szKeyName[37] == TEXT('}')))
+ {
+ continue;
+ }
+
+ // Check if this appid is already in the table
+ SItem *pItem = FindAppid(szKeyName);
+
+ // If not create an item entry so it can be displayed in the UI
+ if (pItem == NULL)
+ {
+ TCHAR szTitle[MAX_PATH];
+ long lSize = MAX_PATH * sizeof(TCHAR);
+
+ // Read its unnamed value as the title
+ err = RegQueryValue(hKey, szKeyName, szTitle, &lSize);
+
+ // Store this item
+ pItem = m_applications.PutItem(NULL,
+ szTitle[0] ? szTitle : szKeyName,
+ szKeyName);
+ if (pItem == NULL)
+ {
+ return FALSE;
+ }
+ }
+
+ // Mark it so we don't rewrite it to HKEY_CLASSES_ROOT\AppID
+ pItem->fMarked = TRUE;
+ } // End enumeration of HKEY_CLASSES_ROOT\AppID
+
+
+
+ // Enumerate through the table of items, writing to HKEY_CLASSES_ROOT\AppID
+ // any items that are not marked
+ SItem *pItem;
+
+ m_applications.InitGetNext();
+ for (pItem = GetNextItem(); pItem; pItem = GetNextItem())
+ {
+ HKEY hKey2;
+
+ // If this item has an AppID but is unmarked, then ask the user
+ // whether he really wants to create the AppID
+ if (!pItem->fMarked && pItem->fHasAppid)
+ {
+ CString szMessage;
+ CString szDCOM_;
+ CString szNULL;
+ TCHAR szText[MAX_PATH*2];
+ TCHAR *szParms[3];
+
+ szMessage.LoadString(IDS_CLSID_);
+ szDCOM_.LoadString(IDS_DCOM_Configuration_Warning);
+ szNULL.LoadString(IDS_NULL);
+
+ szParms[0] = pItem->ppszClsids[0];
+ szParms[1] = pItem->szItem ? pItem->szItem
+ : (TCHAR *) ((LPCTSTR) szNULL);
+ szParms[2] = pItem->szTitle ? pItem->szTitle
+ : (TCHAR *) ((LPCTSTR) szNULL);
+
+ FormatMessage(FORMAT_MESSAGE_FROM_STRING |
+ FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ (TCHAR *) ((LPCTSTR) szMessage),
+ 0,
+ 0,
+ szText,
+ MAX_PATH*2 * sizeof(TCHAR),
+ (va_list *) szParms);
+
+ if (MessageBox(GetForegroundWindow(),
+ szText,
+ (TCHAR *) ((LPCTSTR) szDCOM_),
+ MB_YESNO) == IDNO)
+ {
+ pItem->fMarked = TRUE;
+ pItem->fDontDisplay = TRUE;
+ }
+ }
+
+ // If this item is not marked then, then create an appid key for
+ // it under HKEY_CLASSES_ROOT\AppID and, separately, write the
+ // .exe name under HKEY_CLASSES_ROOT\AppID
+ if (!pItem->fMarked)
+ {
+ if (RegCreateKey(hKey, pItem->szAppid, &hKey2) != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+
+ // Write the item title as the unnamed value
+ if (pItem->szTitle)
+ {
+ RegSetValueEx(hKey2, NULL, 0, REG_SZ,
+ (BYTE *) pItem->szTitle,
+ (_tcslen(pItem->szTitle) + 1) * sizeof(TCHAR));
+ }
+
+ // Close it
+ RegCloseKey(hKey2);
+
+ // Write the .exe name if it's not empty
+ if (pItem->szItem && pItem->szItem[0])
+ {
+ TCHAR szExe[MAX_PATH];
+
+ // Extract the .exe name
+ for (int k = _tcslen(pItem->szItem);
+ k > 0 && pItem->szItem[k] != TEXT('\\');
+ k--)
+ {
+ }
+ if (pItem->szItem[k] == TEXT('\\'))
+ {
+ k++;
+ }
+ _tcscpy(szExe, &pItem->szItem[k]);
+
+ // Write the .exe name as a key
+ if (RegCreateKey(hKey, szExe, &hKey2) != ERROR_SUCCESS)
+ {
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+
+ // Now write the associated AppId as a named value
+ RegSetValueEx(hKey2, TEXT("AppId"), 0, REG_SZ,
+ (BYTE *) pItem->szAppid,
+ (_tcslen(pItem->szAppid) + 1) * sizeof(TCHAR));
+
+ RegCloseKey(hKey2);
+ }
+ }
+ }
+
+ // Close the key on HKEY_CLASSES_ROOT\AppID
+ RegCloseKey(hKey);
+
+
+ // We display applications by their titles (e.g. "Microsoft Word 6.0")
+ // which have to be unique because we're going to uniquely associate
+ // an entry in the list box with the index of its associated SItem
+ // structure. So here we make sure all the titles are unique.
+ DWORD cbItems = m_applications.GetNumItems();
+
+ // Compare all non-empty titles of the same length. If they are
+ // not unique, then append "(<index>)" to make them unique
+ for (DWORD k = 0; k < cbItems; k++)
+ {
+ DWORD dwIndex = 1;
+ SItem *pItem = m_applications.GetItem(k);
+
+ if (pItem->cbTitle > 0 && !pItem->fChecked)
+ {
+ for (DWORD j = k + 1; j < cbItems; j++)
+ {
+ SItem *pItem2 = m_applications.GetItem(j);
+
+ if (!pItem2->fChecked &&
+ pItem->cbTitle == pItem2->cbTitle)
+ {
+ if (_tcscmp(pItem->szTitle, pItem2->szTitle) == 0)
+ {
+ if (dwIndex == 1)
+ {
+ AppendIndex(pItem, 1);
+ dwIndex++;
+ }
+ AppendIndex(pItem2, dwIndex++);
+ pItem2->fChecked = TRUE;
+ }
+ }
+ }
+ }
+ }
+
+
+ // Prepare for the UI enumerating item entries
+ m_applications.InitGetNext();
+
+ return TRUE;
+}
+
+
+
+
+
+BOOL CRegistry::InitGetItem(void)
+{
+ return m_applications.InitGetNext();
+}
+
+
+
+
+// Enumerate the next application name
+SItem *CRegistry::GetNextItem(void)
+{
+ return m_applications.GetNextItem();
+}
+
+
+
+
+// Get a specific item
+SItem *CRegistry::GetItem(DWORD dwItem)
+{
+ return m_applications.GetItem(dwItem);
+}
+
+
+
+SItem *CRegistry::FindItem(TCHAR *szItem)
+{
+ return m_applications.FindItem(szItem);
+}
+
+
+
+SItem *CRegistry::FindAppid(TCHAR *szAppid)
+{
+ return m_applications.FindAppid(szAppid);
+}
+
+
+
+
+void CRegistry::AppendIndex(SItem *pItem, DWORD dwIndex)
+{
+ TCHAR *pszTmp;
+
+ pszTmp = new TCHAR[pItem->cbTitle + 1 + 1 + 2 + 1 + 1];
+
+#ifdef _UNICODE
+ wsprintf(pszTmp, L"%ws (%d)\0", pItem->szTitle, dwIndex);
+#else
+ wsprintf(pszTmp, "%s (%d)\0", pItem->szTitle, dwIndex);
+#endif
+
+ delete pItem->szTitle;
+ pItem->szTitle = pszTmp;
+}
+
+
+
+DWORD CRegistry::GetNumItems(void)
+{
+ return m_applications.GetNumItems();
+}
diff --git a/private/ole32/oleui/creg.h b/private/ole32/oleui/creg.h
new file mode 100644
index 000000000..99b02a94d
--- /dev/null
+++ b/private/ole32/oleui/creg.h
@@ -0,0 +1,51 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: creg.h
+//
+// Contents: Defines class CRegistry to wrap registry access
+//
+// Classes:
+//
+// Methods:
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+typedef enum {_LOCALSERVER, LOCALSERVER, _LOCALSERVER32, LOCALSERVER32,
+ LOCALSERVICE, REMOTESERVER} SRVTYPE;
+
+
+// Wraps registry access
+
+class CRegistry
+{
+ public:
+
+ CRegistry(void);
+
+ ~CRegistry(void);
+
+ BOOL Init(void);
+
+ BOOL InitGetItem(void);
+
+ SItem *GetNextItem(void);
+
+ SItem *GetItem(DWORD dwItem);
+
+ SItem *FindItem(TCHAR *szItem);
+
+ SItem *FindAppid(TCHAR *szAppid);
+
+ void AppendIndex(SItem *pItem, DWORD dwIndex);
+
+ DWORD GetNumItems(void);
+
+ private:
+
+ CStrings m_applications;
+};
diff --git a/private/ole32/oleui/cstrings.cpp b/private/ole32/oleui/cstrings.cpp
new file mode 100644
index 000000000..c8df66f06
--- /dev/null
+++ b/private/ole32/oleui/cstrings.cpp
@@ -0,0 +1,311 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: cstrings.cpp
+//
+// Contents: Implements the class CStrings to manage a dynamically
+// expandable array of string pairs which may be enumerated
+//
+// Classes:
+//
+// Methods: CStrings::CStrings
+// CStrings::~CStrings
+// CStrings::PutItem
+// CStrings::FindItem
+// CStrings::FindAppid
+// CStrings::AddClsid
+// CStrings::InitGetNext
+// CStrings::GetNextItem
+// CStrings::GetItem
+// CStrings::GetNumItems
+// CStrings::RemoveItem
+// CStrings::RemoveAll
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+
+#include "stdafx.h"
+#include "types.h"
+#include "cstrings.h"
+
+
+CStrings::CStrings(void)
+{
+ _psItems = NULL;
+ _dwCount = 0;
+ _dwSize = 0;
+ _dwGetCount = 0;
+}
+
+
+
+
+CStrings::~CStrings(void)
+{
+ RemoveAll();
+ delete _psItems;
+}
+
+
+
+
+// Store a string pair, expanding the array if necessary
+SItem *CStrings::PutItem(TCHAR *szString, TCHAR *szTitle, TCHAR *szAppid)
+{
+ // Expand the array of items if necessary
+ if (_dwCount == _dwSize)
+ {
+ SItem *psTemp = new SItem[_dwSize + INCREMENT_SIZE];
+
+ if (psTemp == NULL)
+ {
+ return NULL;
+ }
+ else
+ {
+ memcpy(psTemp, _psItems, _dwSize * sizeof(SItem *));
+ _dwSize += INCREMENT_SIZE;
+ delete _psItems;
+ _psItems = psTemp;
+ }
+ }
+
+ // Store the item name
+ if (szString)
+ {
+ _psItems[_dwCount].szItem = new TCHAR[_tcslen(szString) + 1];
+ if (_psItems[_dwCount].szItem == NULL)
+ {
+ return NULL;
+ }
+ _tcscpy(_psItems[_dwCount].szItem, szString);
+ }
+ else
+ {
+ _psItems[_dwCount].szItem = NULL;
+ }
+
+ // Store the item title
+ if (szTitle)
+ {
+ _psItems[_dwCount].szTitle = new TCHAR[_tcslen(szTitle) + 1];
+ if (_psItems[_dwCount].szTitle == NULL)
+ {
+ return NULL;
+ }
+ _tcscpy(_psItems[_dwCount].szTitle, szTitle);
+ _psItems[_dwCount].cbTitle = _tcslen(szTitle);
+ }
+ else
+ {
+ _psItems[_dwCount].szTitle = NULL;
+ _psItems[_dwCount].cbTitle = 0;
+ }
+
+ // Store the item's AppID
+ if (szAppid)
+ {
+ _psItems[_dwCount].szAppid = new TCHAR[_tcslen(szAppid) + 1];
+ if (_psItems[_dwCount].szAppid == NULL)
+ {
+ return NULL;
+ }
+ _tcscpy(_psItems[_dwCount].szAppid, szAppid);
+ }
+ else
+ {
+ _psItems[_dwCount].szAppid = NULL;
+ }
+
+ // Initialize the rest of the item
+ _psItems[_dwCount].ulClsidTbl = 0;
+ _psItems[_dwCount].ulClsids = 0;
+ _psItems[_dwCount].ppszClsids = NULL;
+ _psItems[_dwCount].fMarked = FALSE;
+ _psItems[_dwCount].fChecked = FALSE;
+ _psItems[_dwCount].fHasAppid = FALSE;
+ _psItems[_dwCount].fDontDisplay = FALSE;
+
+
+ // Increment the item count
+ _dwCount++;
+
+ return &_psItems[_dwCount - 1];
+}
+
+
+
+SItem *CStrings::FindItem(TCHAR *szItem)
+{
+ for (DWORD dwItem = 0; dwItem < _dwCount; dwItem++)
+ {
+ if (_psItems[dwItem].szItem &&
+ _tcscmp(_psItems[dwItem].szItem, szItem) == 0)
+ {
+ return &_psItems[dwItem];
+ }
+ }
+
+ return NULL;
+}
+
+
+
+SItem *CStrings::FindAppid(TCHAR *szAppid)
+{
+ for (DWORD dwItem = 0; dwItem < _dwCount; dwItem++)
+ {
+ if (_psItems[dwItem].szItem &&
+ _tcscmp(_psItems[dwItem].szAppid, szAppid) == 0)
+ {
+ return &_psItems[dwItem];
+ }
+ }
+
+ return NULL;
+}
+
+
+
+BOOL CStrings::AddClsid(SItem *pItem, TCHAR *szClsid)
+{
+ // Create or expand the clsid table if necessary
+ if (pItem->ulClsids == pItem->ulClsidTbl)
+ {
+ TCHAR **ppTmp = new TCHAR *[pItem->ulClsidTbl + 8];
+ if (ppTmp == NULL)
+ {
+ return FALSE;
+ }
+ if (pItem->ppszClsids)
+ {
+ memcpy(ppTmp,
+ pItem->ppszClsids,
+ pItem->ulClsids * sizeof(TCHAR *));
+ delete pItem->ppszClsids;
+ }
+ pItem->ppszClsids = ppTmp;
+ pItem->ulClsidTbl += 8;
+ }
+
+ // Add the new clsid
+ TCHAR *pszTmp = new TCHAR[GUIDSTR_MAX + 1];
+ if (pszTmp == NULL)
+ {
+ return FALSE;
+ }
+ _tcscpy(pszTmp, szClsid);
+ pItem->ppszClsids[pItem->ulClsids++] = pszTmp;
+
+ return TRUE;
+}
+
+
+
+// Prepare to enumerate the array
+DWORD CStrings::InitGetNext(void)
+{
+ _dwGetCount = 0;
+ return _dwCount;
+}
+
+
+
+
+// Return the first string in the next eumerated item
+SItem *CStrings::GetNextItem(void)
+{
+ if (_dwGetCount < _dwCount)
+ {
+ return &_psItems[_dwGetCount++];
+ }
+ else
+ {
+ _dwGetCount = 0;
+ return NULL;
+ }
+}
+
+
+
+
+// Return the first string in the next eumerated item
+SItem *CStrings::GetItem(DWORD dwItem)
+{
+ if (dwItem < _dwCount)
+ {
+ return &_psItems[dwItem];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
+
+
+// Return the total number of items
+DWORD CStrings::GetNumItems(void)
+{
+ return _dwCount;
+}
+
+
+
+
+
+// Given an item index, remove it
+BOOL CStrings::RemoveItem(DWORD dwItem)
+{
+ if (dwItem < _dwCount)
+ {
+ delete _psItems[dwItem].szItem;
+ _psItems[dwItem].szItem = NULL;
+
+ delete _psItems[dwItem].szTitle;
+ _psItems[dwItem].szTitle = NULL;
+
+ delete _psItems[dwItem].szAppid;
+ _psItems[dwItem].szAppid = NULL;
+
+ for (UINT k = 0; k < _psItems[dwItem].ulClsids; k++)
+ {
+ delete _psItems[dwItem].ppszClsids[k];
+ }
+ _psItems[dwItem].ulClsids = 0;
+ _psItems[dwItem].ulClsidTbl = 0;
+ delete _psItems[dwItem].ppszClsids;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+
+
+// Remove the array of items
+BOOL CStrings::RemoveAll(void)
+{
+ for (DWORD dwItem = 0; dwItem < _dwCount; dwItem++)
+ {
+ RemoveItem(dwItem);
+ }
+ _dwCount = 0;
+
+ if (_psItems)
+ {
+ delete _psItems;
+ }
+ _psItems = NULL;
+ _dwSize = 0;
+
+ return TRUE;
+}
diff --git a/private/ole32/oleui/cstrings.h b/private/ole32/oleui/cstrings.h
new file mode 100644
index 000000000..c6d448e59
--- /dev/null
+++ b/private/ole32/oleui/cstrings.h
@@ -0,0 +1,67 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: cstrings.h
+//
+// Contents: Defines the class CStrings to manage a dynamically
+// expandable array of string pairs which may be enumerated
+//
+// Classes:
+//
+// Methods:
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+const DWORD INCREMENT_SIZE = 1024;
+
+
+typedef struct
+{
+ TCHAR *szItem;
+ TCHAR *szTitle;
+ DWORD cbTitle;
+ TCHAR *szAppid;
+ ULONG fMarked:1;
+ ULONG fChecked:1;
+ ULONG fHasAppid:1;
+ ULONG fDontDisplay:1;
+ UINT ulClsids;
+ UINT ulClsidTbl;
+ TCHAR **ppszClsids;
+} SItem;
+
+
+class CStrings
+{
+ public:
+
+ CStrings(void);
+ ~CStrings(void);
+ SItem *PutItem(TCHAR *szString, TCHAR *szTitle, TCHAR *szAppid);
+ SItem *FindItem(TCHAR *szItem);
+ SItem *FindAppid(TCHAR *szAppid);
+ BOOL AddClsid(SItem *pItem, TCHAR *szClsid);
+ DWORD InitGetNext(void);
+ SItem *GetNextItem(void);
+ SItem *GetItem(DWORD dwItem);
+ DWORD GetNumItems(void);
+ BOOL RemoveItem(DWORD dwItem);
+ BOOL RemoveAll(void);
+
+
+ private:
+
+ SItem *_psItems;
+ DWORD _dwCount;
+ DWORD _dwSize;
+ DWORD _dwGetCount;
+};
+
+
+
+
diff --git a/private/ole32/oleui/datapkt.cpp b/private/ole32/oleui/datapkt.cpp
new file mode 100644
index 000000000..0dab30566
--- /dev/null
+++ b/private/ole32/oleui/datapkt.cpp
@@ -0,0 +1,343 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: datapkt.cpp
+//
+// Contents: Implements the class CDataPacket to manages diverse data
+// packets needing to be written to various databases
+//
+// Classes:
+//
+// Methods: CDataPacket::CDataPacket (x 7)
+// CDataPacket::~CDataPacket
+// CDataPacket::ChgSzValue
+// CDataPacket::ChgDwordValue
+// CDataPacket::ChgACL
+// CDataPacket::ChgPassword
+// CDataPacket::ChgSrvIdentity
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+
+#include "stdafx.h"
+#include "assert.h"
+#include "datapkt.h"
+extern "C"
+{
+#include <getuser.h>
+}
+#include "util.h"
+
+
+
+CDataPacket::CDataPacket(void)
+{
+ tagType = Empty;
+}
+
+
+
+CDataPacket::CDataPacket(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ TCHAR *szValue)
+{
+ tagType = NamedValueSz;
+ pkt.nvsz.hRoot = hRoot;
+ pkt.nvsz.szKeyPath = new TCHAR[_tcslen(szKeyPath) + 1];
+ _tcscpy(pkt.nvsz.szKeyPath, szKeyPath);
+ pkt.nvsz.szValueName = new TCHAR[_tcslen(szValueName) + 1];
+ _tcscpy(pkt.nvsz.szValueName, szValueName);
+ pkt.nvsz.szValue = (TCHAR *) new TCHAR[_tcslen(szValue) + 1];
+ _tcscpy(pkt.nvsz.szValue, szValue);
+ fDirty = TRUE;
+ fDelete = FALSE;
+}
+
+
+
+CDataPacket::CDataPacket(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ DWORD dwValue)
+{
+ tagType = NamedValueDword;
+ pkt.nvsz.hRoot = hRoot;
+ pkt.nvsz.szKeyPath = new TCHAR[_tcslen(szKeyPath) + 1];
+ _tcscpy(pkt.nvsz.szKeyPath, szKeyPath);
+ pkt.nvdw.szValueName = new TCHAR[_tcslen(szValueName) + 1];
+ _tcscpy(pkt.nvdw.szValueName, szValueName);
+ pkt.nvdw.dwValue = dwValue;
+ fDirty = TRUE;
+ fDelete = FALSE;
+}
+
+
+
+CDataPacket::CDataPacket(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ SECURITY_DESCRIPTOR *pSec,
+ BOOL fSelfRelative)
+{
+ int err;
+ ULONG cbLen;
+ SECURITY_DESCRIPTOR *pSD;
+
+ tagType = SingleACL;
+ pkt.acl.hRoot = hRoot;
+
+ if (szKeyPath)
+ {
+ pkt.acl.szKeyPath = new TCHAR[_tcslen(szKeyPath) + 1];
+ _tcscpy(pkt.acl.szKeyPath, szKeyPath);
+ }
+ else
+ {
+ pkt.acl.szKeyPath = NULL;
+ }
+
+ pkt.acl.szValueName = new TCHAR[_tcslen(szValueName) + 1];
+ _tcscpy(pkt.acl.szValueName, szValueName);
+
+ // Get the security descriptor into self relative form so we
+ // can cache it
+
+ // Force first call to fail so we can get the real size needed
+ if (!fSelfRelative)
+ {
+ cbLen = 1;
+ if (!MakeSelfRelativeSD(pSec, NULL, &cbLen))
+ {
+ err = GetLastError();
+ }
+
+ // Now really do it
+ pSD = (SECURITY_DESCRIPTOR *) new BYTE[cbLen];
+ if (!MakeSelfRelativeSD(pSec, pSD, &cbLen))
+ {
+ err = GetLastError();
+ }
+ pkt.acl.pSec = pSD;
+ }
+ else
+ {
+ // The security descriptor is aready in self relative form
+ // as it was read directly from the registry. However, we still
+ // have to copy the it.
+ g_util.CopySD(pSec, &pkt.acl.pSec);
+ }
+
+
+ fDirty = TRUE;
+ fDelete = FALSE;
+}
+
+
+
+CDataPacket::CDataPacket(HKEY hKey,
+ HKEY *phClsids,
+ unsigned cClsids,
+ TCHAR *szTitle,
+ SECURITY_DESCRIPTOR *pSecOrig,
+ SECURITY_DESCRIPTOR *pSec,
+ BOOL fSelfRelative)
+{
+ ULONG cbLen;
+ SECURITY_DESCRIPTOR *pSD;
+
+ tagType = RegKeyACL;
+ pkt.racl.hKey = hKey;
+ pkt.racl.phClsids = phClsids;
+ pkt.racl.cClsids = cClsids;
+ pkt.racl.szTitle = szTitle;
+
+ // Get the new security descriptor into self relative form so we
+ // can cache it (if we have to)
+ if (!fSelfRelative)
+ {
+ // Force first call to fail so we can get the real size needed
+ cbLen = 1;
+ MakeSelfRelativeSD(pSec, NULL, &cbLen);
+
+ // Now really do it
+ pSD = (SECURITY_DESCRIPTOR *) new BYTE[cbLen];
+ MakeSelfRelativeSD(pSec, pSD, &cbLen);
+ pkt.racl.pSec = pSD;
+ }
+ else
+ {
+ g_util.CopySD(pSec, &pkt.racl.pSec);
+ }
+
+ // The original security descriptor is aready in self relative form
+ // as it was read directly from the registry. (The edited SD from the
+ // ACL editor is in absolute form.) However, we still have to copy the
+ // original SD.
+ g_util.CopySD(pSecOrig, &pkt.racl.pSecOrig);
+
+ fDirty = TRUE;
+ fDelete = FALSE;
+}
+
+
+
+CDataPacket::CDataPacket(TCHAR *szPassword,
+ CLSID appid)
+{
+ tagType = Password;
+ pkt.pw.szPassword = new TCHAR[_tcslen(szPassword) + 1];
+ _tcscpy(pkt.pw.szPassword, szPassword);
+ pkt.pw.appid = appid;
+ fDirty = TRUE;
+ fDelete = FALSE;
+}
+
+
+
+CDataPacket::CDataPacket(TCHAR *szServiceName,
+ TCHAR *szIdentity)
+{
+ tagType = ServiceIdentity;
+ pkt.si.szServiceName = new TCHAR[_tcslen(szServiceName) + 1];
+ _tcscpy(pkt.si.szServiceName, szServiceName);
+ pkt.si.szIdentity = new TCHAR[_tcslen(szIdentity) + 1];
+ _tcscpy(pkt.si.szIdentity, szIdentity);
+ fDirty = TRUE;
+ fDelete = FALSE;
+}
+
+
+
+
+CDataPacket::~CDataPacket()
+{
+ switch (tagType)
+ {
+ case NamedValueSz:
+ delete pkt.nvsz.szValueName;
+ delete pkt.nvsz.szValue;
+ break;
+
+ case NamedValueDword:
+ delete pkt.nvdw.szValueName;
+ break;
+
+ case SingleACL:
+ delete pkt.acl.pSec;
+ break;
+
+ case RegKeyACL:
+ delete pkt.acl.pSec;
+ break;
+
+ case Password:
+ delete pkt.pw.szPassword;
+ break;
+
+ case ServiceIdentity:
+ delete pkt.si.szServiceName;
+ delete pkt.si.szIdentity;
+ break;
+ }
+}
+
+
+
+void CDataPacket::ChgSzValue(TCHAR *szValue)
+{
+ assert(tagType == NamedValueSz);
+ delete pkt.nvsz.szValueName;
+ pkt.nvsz.szValue = new TCHAR[_tcslen(szValue) + 1];
+ _tcscpy(pkt.nvsz.szValue, szValue);
+}
+
+
+void CDataPacket::ChgDwordValue(DWORD dwValue)
+{
+ assert(tagType == NamedValueDword);
+ pkt.nvdw.dwValue = dwValue;
+}
+
+
+
+void CDataPacket::ChgACL(SECURITY_DESCRIPTOR *pSec, BOOL fSelfRelative)
+{
+ ULONG cbLen;
+ SECURITY_DESCRIPTOR *pSD;
+
+ assert(tagType == SingleACL || tagType == RegKeyACL);
+
+ // Remove the previous security descriptor
+ if (tagType == SingleACL)
+ {
+ delete pkt.acl.pSec;
+ pkt.acl.pSec = NULL;
+ }
+ else
+ {
+ delete pkt.racl.pSec;
+ pkt.racl.pSec = NULL;
+ }
+
+ // Put into self relative form (if necessary)
+ if (!fSelfRelative)
+ {
+ cbLen = 1;
+ MakeSelfRelativeSD(pSec, NULL, &cbLen);
+
+ // Now really do it
+ pSD = (SECURITY_DESCRIPTOR *) new BYTE[cbLen];
+ MakeSelfRelativeSD(pSec, pSD, &cbLen);
+
+ // Store it
+ if (tagType == SingleACL)
+ {
+ pkt.acl.pSec = pSD;
+ }
+ else
+ {
+ pkt.racl.pSec = pSD;
+ }
+ }
+ else
+ {
+ if (tagType == SingleACL)
+ {
+ g_util.CopySD(pSec, &pkt.acl.pSec);
+ }
+ else
+ {
+ g_util.CopySD(pSec, &pkt.racl.pSec);
+ }
+ }
+}
+
+
+
+void CDataPacket::ChgPassword(TCHAR *szPassword)
+{
+ assert(tagType == Password);
+ delete pkt.pw.szPassword;
+ pkt.pw.szPassword = new TCHAR[_tcslen(szPassword) + 1];
+ _tcscpy(pkt.pw.szPassword, szPassword);
+}
+
+
+
+void CDataPacket::ChgSrvIdentity(TCHAR *szIdentity)
+{
+ assert(tagType == ServiceIdentity);
+ delete pkt.si.szIdentity;
+ pkt.si.szIdentity = new TCHAR[_tcslen(szIdentity) + 1];
+ _tcscpy(pkt.si.szIdentity, szIdentity);
+}
+
+
+
+
diff --git a/private/ole32/oleui/datapkt.h b/private/ole32/oleui/datapkt.h
new file mode 100644
index 000000000..a6feb52eb
--- /dev/null
+++ b/private/ole32/oleui/datapkt.h
@@ -0,0 +1,141 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: datapkt.h
+//
+// Contents: Defines the class CDataPacket to manages diverse data
+// packets needing to be written to various databases
+//
+// Classes:
+//
+// Methods:
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+#ifndef _DATAPKT_H_
+#define _DATAPKT_H_
+
+typedef enum tagPACKETTYPE {Empty, NamedValueSz, NamedValueDword, SingleACL,
+ RegKeyACL, Password, ServiceIdentity} PACKETTYPE;
+
+typedef struct
+{
+ HKEY hRoot;
+ TCHAR *szKeyPath;
+ TCHAR *szValueName;
+ TCHAR *szValue;
+} SNamedValueSz, *PNamedValueSz;
+
+typedef struct
+{
+ HKEY hRoot;
+ TCHAR *szKeyPath;
+ TCHAR *szValueName;
+ DWORD dwValue;
+} SNamedValueDword, *PNamedValueDword;
+
+typedef struct
+{
+ HKEY hRoot;
+ TCHAR *szKeyPath;
+ TCHAR *szValueName;
+ SECURITY_DESCRIPTOR *pSec;
+} SSingleACL, *PSingleACL;
+
+
+typedef struct
+{
+ HKEY hKey;
+ HKEY *phClsids;
+ unsigned cClsids;
+ TCHAR *szTitle;
+ SECURITY_DESCRIPTOR *pSec;
+ SECURITY_DESCRIPTOR *pSecOrig;
+} SRegKeyACL, *PRegKeyACL;
+
+
+typedef struct
+{
+ TCHAR *szPassword;
+ CLSID appid;
+} SPassword, *PPassword;
+
+
+typedef struct
+{
+ TCHAR *szServiceName;
+ TCHAR *szIdentity;
+} SServiceIdentity, *PServiceIdentity;
+
+
+class CDataPacket
+{
+ public:
+ CDataPacket(void);
+
+ CDataPacket(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ TCHAR *szValue);
+
+ CDataPacket(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ DWORD dwValue);
+
+ CDataPacket(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ SECURITY_DESCRIPTOR *pSec,
+ BOOL fSelfRelative);
+
+ CDataPacket(HKEY hKey,
+ HKEY *phClsids,
+ unsigned cClsids,
+ TCHAR *szTitle,
+ SECURITY_DESCRIPTOR *pSecOrig,
+ SECURITY_DESCRIPTOR *pSec,
+ BOOL fSelfRelative);
+
+ CDataPacket(TCHAR *szPassword,
+ CLSID apid);
+
+ CDataPacket(TCHAR *szServiceName,
+ TCHAR *szIdentity);
+
+ CDataPacket(PACKETTYPE pktType,
+ HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName);
+
+ void ChgSzValue(TCHAR *szValue);
+
+ void ChgDwordValue(DWORD dwValue);
+
+ void ChgACL(SECURITY_DESCRIPTOR *pSec, BOOL fSelfRelative);
+
+ void ChgPassword(TCHAR *szPassword);
+
+ void ChgSrvIdentity(TCHAR *szIdentity);
+
+
+ PACKETTYPE tagType;
+ BOOL fDirty;
+ BOOL fDelete;
+ union
+ {
+ SNamedValueSz nvsz;
+ SNamedValueDword nvdw;
+ SSingleACL acl;
+ SRegKeyACL racl;
+ SPassword pw;
+ SServiceIdentity si;
+ } pkt;
+};
+
+#endif // _DATAPKT_H_
diff --git a/private/ole32/oleui/daytona/makefile b/private/ole32/oleui/daytona/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ole32/oleui/daytona/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/oleui/daytona/sources b/private/ole32/oleui/daytona/sources
new file mode 100644
index 000000000..583d93dc8
--- /dev/null
+++ b/private/ole32/oleui/daytona/sources
@@ -0,0 +1,101 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1989
+
+
+Revision History:
+
+!ENDIF
+
+#
+# The TARGETNAME variable is defined by the developer. It is the name of
+# the target (component) that is being built by this makefile. It
+# should NOT include any path or file extension information.
+#
+
+TARGETNAME=dcomcnfg
+
+#
+# The TARGETPATH and TARGETTYPE varialbes are defined by the developer.
+# The first specifies where the target is to be build. The second specifies
+# the type of target (either PROGRAM, DYNLINK or LIBRARY)
+#
+
+TARGETPATH=obj
+TARGETTYPE=LIBRARY
+
+UMTYPE=windows
+UMAPPL=dcomcnfg
+UMRES=obj\*\dcomcnfg.res
+
+#
+# The INCLUDES variable specifies any include paths that are specific to
+# this source directory. Separate multiple directory paths with single
+# semicolons. Relative path specifications are okay.
+#
+
+INCLUDES=.;..\;..\..\..\inc
+
+#
+# The SOURCES variable is defined by the developer. It is a list of all the
+# source files for this component. Each source file should be on a separate
+# line using the line continuation character. This will minimize merge
+# conflicts if two developers adding source files to the same component.
+#
+
+USE_MFCUNICODE=1
+# C_DEFINES=-DUNICODE -D_UNICODE
+
+PRECOMPILED_INCLUDE=..\stdafx.h
+PRECOMPILED_CXX=1
+
+SOURCES=\
+ ..\clspsht.cpp \
+ ..\cnfgpsht.cpp \
+ ..\creg.cpp \
+ ..\cstrings.cpp \
+ ..\locppg.cpp \
+ ..\srvppg.cpp \
+ ..\newsrvr.cpp \
+ ..\util.cpp \
+ ..\virtreg.cpp \
+ ..\datapkt.cpp \
+ ..\dcomcnfg.cpp \
+ ..\dcomcnfg.rc
+
+
+# C_DEFINES=-DUNICODE
+
+UMLIBS=\
+ obj\*\dcomcnfg.lib \
+ ..\..\com\class\daytona\obj\*\scm_c.obj \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \
+ $(BASEDIR)\public\sdk\lib\*\comCtl32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\acledit.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\netui2.lib \
+ $(BASEDIR)\public\sdk\lib\*\mpr.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntlanui.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib
+
diff --git a/private/ole32/oleui/dcomcnfg.cpp b/private/ole32/oleui/dcomcnfg.cpp
new file mode 100644
index 000000000..ece03fbbd
--- /dev/null
+++ b/private/ole32/oleui/dcomcnfg.cpp
@@ -0,0 +1,20 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: dcomcnfg.cpp
+//
+// Contents: Simply wraps the true top level source program olecnfg.cpp
+//
+// Classes:
+//
+// Functions:
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+#include "stdafx.h"
+
+#include "olecnfg.cpp"
diff --git a/private/ole32/oleui/dcomcnfg.rc b/private/ole32/oleui/dcomcnfg.rc
new file mode 100644
index 000000000..3419aa99d
--- /dev/null
+++ b/private/ole32/oleui/dcomcnfg.rc
@@ -0,0 +1,4 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "olecnfg.rc"
+
diff --git a/private/ole32/oleui/dirs b/private/ole32/oleui/dirs
new file mode 100644
index 000000000..db113c7ff
--- /dev/null
+++ b/private/ole32/oleui/dirs
@@ -0,0 +1,36 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Donna Liu (DonnaLi) 19-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ daytona
diff --git a/private/ole32/oleui/locppg.cpp b/private/ole32/oleui/locppg.cpp
new file mode 100644
index 000000000..f4ed40461
--- /dev/null
+++ b/private/ole32/oleui/locppg.cpp
@@ -0,0 +1,706 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: locppg.cpp
+//
+// Contents: Implements the classes CGeneralPropertyPage,
+// CLocationPropertyPage, CSecurityPropertyPage and
+// CIdentityPropertyPage which manage the four property
+// pages per AppId.
+//
+// Classes:
+//
+// Methods: CGeneralPropertyPage::CGeneralPropertyPage
+// CGeneralPropertyPage::~CGeneralPropertyPage
+// CGeneralPropertyPage::DoDataExchange
+// CLocationPropertyPage::CLocationPropertyPage
+// CLocationPropertyPage::~CLocationPropertyPage
+// CLocationPropertyPage::DoDataExchange
+// CLocationPropertyPage::OnBrowse
+// CLocationPropertyPage::OnRunRemote
+// CLocationPropertyPage::UpdateControls
+// CLocationPropertyPage::OnSetActive
+// CLocationPropertyPage::OnChange
+// CSecurityPropertyPage::CSecurityPropertyPage
+// CSecurityPropertyPage::~CSecurityPropertyPage
+// CSecurityPropertyPage::DoDataExchange
+// CSecurityPropertyPage::OnDefaultAccess
+// CSecurityPropertyPage::OnCustomAccess
+// CSecurityPropertyPage::OnDefaultLaunch
+// CSecurityPropertyPage::OnCustomLaunch
+// CSecurityPropertyPage::OnDefaultConfig
+// CSecurityPropertyPage::OnCustomConfig
+// CSecurityPropertyPage::OnEditAccess
+// CSecurityPropertyPage::OnEditLaunch
+// CSecurityPropertyPage::OnEditConfig
+// CIdentityPropertyPage::CIdentityPropertyPage
+// CIdentityPropertyPage::~CIdentityPropertyPage
+// CIdentityPropertyPage::DoDataExchange
+// CIdentityPropertyPage::OnBrowse
+// CIdentityPropertyPage::OnChange
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+#include "stdafx.h"
+#include "afxtempl.h"
+#include "assert.h"
+#include "resource.h"
+#include "LocPPg.h"
+#include "clspsht.h"
+#include "datapkt.h"
+extern "C"
+{
+#include <getuser.h>
+}
+#include "util.h"
+#include "virtreg.h"
+#include "ntlsa.h"
+
+
+
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char BASED_CODE THIS_FILE[] = __FILE__;
+#endif
+
+IMPLEMENT_DYNCREATE(CGeneralPropertyPage, CPropertyPage)
+IMPLEMENT_DYNCREATE(CLocationPropertyPage, CPropertyPage)
+IMPLEMENT_DYNCREATE(CSecurityPropertyPage, CPropertyPage)
+IMPLEMENT_DYNCREATE(CIdentityPropertyPage, CPropertyPage)
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CGeneralPropertyPage property page
+
+CGeneralPropertyPage::CGeneralPropertyPage() : CPropertyPage(CGeneralPropertyPage::IDD)
+{
+ //{{AFX_DATA_INIT(CGeneralPropertyPage)
+ m_szServerName = _T("");
+ m_szServerPath = _T("");
+ m_szServerType = _T("");
+ m_szPathTitle = _T("");
+ m_szComputerName = _T("");
+ //}}AFX_DATA_INIT
+}
+
+CGeneralPropertyPage::~CGeneralPropertyPage()
+{
+}
+
+void CGeneralPropertyPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+
+ switch (m_iServerType)
+ {
+ case INPROC:
+ case LOCALEXE:
+ m_szPathTitle.LoadString(IDS_PATH);
+ GetDlgItem(IDC_PATHTITLE)->ShowWindow(SW_SHOW);
+ GetDlgItem(IDC_MACHINETITLE)->ShowWindow(SW_HIDE);
+ GetDlgItem(IDC_SERVERPATH)->ShowWindow(SW_SHOW);
+ GetDlgItem(IDC_MACHINE)->ShowWindow(SW_HIDE);
+ break;
+ case SERVICE:
+ m_szPathTitle.LoadString(IDS_SERVICENAME);
+ GetDlgItem(IDC_PATHTITLE)->ShowWindow(SW_SHOW);
+ GetDlgItem(IDC_MACHINETITLE)->ShowWindow(SW_HIDE);
+ GetDlgItem(IDC_SERVERPATH)->ShowWindow(SW_SHOW);
+ GetDlgItem(IDC_MACHINE)->ShowWindow(SW_HIDE);
+ break;
+ case PURE_REMOTE:
+ GetDlgItem(IDC_PATHTITLE)->ShowWindow(SW_HIDE);
+ GetDlgItem(IDC_MACHINETITLE)->ShowWindow(SW_SHOW);
+ GetDlgItem(IDC_SERVERPATH)->ShowWindow(SW_HIDE);
+ GetDlgItem(IDC_MACHINE)->ShowWindow(SW_SHOW);
+ break;
+ case REMOTE_LOCALEXE:
+ m_szPathTitle.LoadString(IDS_PATH);
+ GetDlgItem(IDC_PATHTITLE)->ShowWindow(SW_SHOW);
+ GetDlgItem(IDC_MACHINETITLE)->ShowWindow(SW_SHOW);
+ GetDlgItem(IDC_SERVERPATH)->ShowWindow(SW_SHOW);
+ GetDlgItem(IDC_MACHINE)->ShowWindow(SW_SHOW);
+ break;
+ case REMOTE_SERVICE:
+ m_szPathTitle.LoadString(IDS_SERVICENAME);
+ GetDlgItem(IDC_PATHTITLE)->ShowWindow(SW_SHOW);
+ GetDlgItem(IDC_MACHINETITLE)->ShowWindow(SW_SHOW);
+ GetDlgItem(IDC_SERVERPATH)->ShowWindow(SW_SHOW);
+ GetDlgItem(IDC_MACHINE)->ShowWindow(SW_SHOW);
+ break;
+ case SURROGATE:
+ m_szPathTitle.LoadString(IDS_PATH);
+ GetDlgItem(IDC_PATHTITLE)->ShowWindow(SW_SHOW);
+ GetDlgItem(IDC_MACHINETITLE)->ShowWindow(SW_HIDE);
+ GetDlgItem(IDC_SERVERPATH)->ShowWindow(SW_SHOW);
+ GetDlgItem(IDC_MACHINE)->ShowWindow(SW_HIDE);
+ break;
+ }
+ m_szServerType.LoadString(IDS_SERVERTYPE0+m_iServerType);
+
+ //{{AFX_DATA_MAP(CGeneralPropertyPage)
+ DDX_Text(pDX, IDC_SERVERNAME, m_szServerName);
+ DDX_Text(pDX, IDC_SERVERPATH, m_szServerPath);
+ DDX_Text(pDX, IDC_SERVERTYPE, m_szServerType);
+ DDX_Text(pDX, IDC_PATHTITLE, m_szPathTitle);
+ DDX_Text(pDX, IDC_MACHINE, m_szComputerName);
+ //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CGeneralPropertyPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CGeneralPropertyPage)
+ // NOTE: the ClassWizard will add message map macros here
+ ON_WM_HELPINFO()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CLocationPropertyPage property page
+
+CLocationPropertyPage::CLocationPropertyPage() : CPropertyPage(CLocationPropertyPage::IDD)
+{
+ //{{AFX_DATA_INIT(CLocationPropertyPage)
+ m_szComputerName = _T("");
+ m_fAtStorage = FALSE;
+ m_fLocal = FALSE;
+ m_fRemote = FALSE;
+ m_iInitial = 2;
+ //}}AFX_DATA_INIT
+}
+
+CLocationPropertyPage::~CLocationPropertyPage()
+{
+}
+
+void CLocationPropertyPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CLocationPropertyPage)
+ DDX_Text(pDX, IDC_EDIT1, m_szComputerName);
+ DDV_MaxChars(pDX, m_szComputerName, 256);
+ DDX_Check(pDX, IDC_CHECK1, m_fAtStorage);
+ DDX_Check(pDX, IDC_CHECK2, m_fLocal);
+ DDX_Check(pDX, IDC_CHECK3, m_fRemote);
+ //}}AFX_DATA_MAP
+ if (m_fRemote)
+ {
+ pDX->PrepareEditCtrl(IDC_EDIT1);
+ if (m_szComputerName.GetLength() == 0 && m_iInitial == 0)
+ {
+ CString szTemp;
+ szTemp.LoadString(IDS_INVALIDSERVER);
+ MessageBox(szTemp);
+ pDX->Fail();
+ }
+ }
+
+ if (m_fAtStorage)
+ {
+ m_pPage1->m_szComputerName.LoadString(IDS_ATSTORAGE);
+ }
+ else
+ m_pPage1->m_szComputerName = m_szComputerName;
+
+ switch(m_pPage1->m_iServerType)
+ {
+ case LOCALEXE:
+ case SERVICE:
+ if (m_fAtStorage || m_fRemote)
+ m_pPage1->m_iServerType += 3;
+ break;
+ case REMOTE_LOCALEXE:
+ case REMOTE_SERVICE:
+ if (!(m_fAtStorage || m_fRemote))
+ m_pPage1->m_iServerType -= 3;
+ break;
+ }
+
+ if (m_iInitial)
+ {
+ m_iInitial--;
+ }
+}
+
+BEGIN_MESSAGE_MAP(CLocationPropertyPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CLocationPropertyPage)
+ ON_BN_CLICKED(IDC_BUTTON1, OnBrowse)
+ ON_BN_CLICKED(IDC_CHECK3, OnRunRemote)
+ ON_EN_CHANGE(IDC_EDIT1, OnChange)
+ ON_BN_CLICKED(IDC_CHECK1, OnChange)
+ ON_BN_CLICKED(IDC_CHECK2, OnChange)
+ ON_WM_HELPINFO()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+void CLocationPropertyPage::OnBrowse()
+{
+ TCHAR szMachine[MAX_PATH];
+
+ if (g_util.InvokeMachineBrowser(szMachine))
+ {
+ // Strip off "\\"
+ GetDlgItem(IDC_EDIT1)->SetWindowText(&szMachine[2]);
+ SetModified(TRUE);
+ }
+}
+
+void CLocationPropertyPage::OnRunRemote()
+{
+ SetModified(TRUE);
+ UpdateControls();
+}
+
+void CLocationPropertyPage::UpdateControls()
+{
+ BOOL fChecked = IsDlgButtonChecked(IDC_CHECK3);
+ GetDlgItem(IDC_EDIT1)->EnableWindow(fChecked);
+
+// Leave this browse button disabled until after SUR Beta 2
+ GetDlgItem(IDC_BUTTON1)->EnableWindow(fChecked);
+}
+
+BOOL CLocationPropertyPage::OnSetActive()
+{
+ if (!m_fCanBeLocal)
+ GetDlgItem(IDC_CHECK2)->EnableWindow(FALSE);
+ UpdateControls();
+ return CPropertyPage::OnSetActive();
+}
+
+void CLocationPropertyPage::OnChange()
+{
+ SetModified(TRUE);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CSecurityPropertyPage property page
+
+CSecurityPropertyPage::CSecurityPropertyPage() : CPropertyPage(CSecurityPropertyPage::IDD)
+{
+ //{{AFX_DATA_INIT(CSecurityPropertyPage)
+ m_iAccess = -1;
+ m_iLaunch = -1;
+ m_iConfig = -1;
+ m_iAccessIndex = -1;
+ m_iLaunchIndex = -1;
+ m_iConfigurationIndex = -1;
+ //}}AFX_DATA_INIT
+}
+
+CSecurityPropertyPage::~CSecurityPropertyPage()
+{
+}
+
+void CSecurityPropertyPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CSecurityPropertyPage)
+ DDX_Radio(pDX, IDC_RADIO1, m_iAccess);
+ DDX_Radio(pDX, IDC_RADIO3, m_iLaunch);
+ DDX_Radio(pDX, IDC_RADIO5, m_iConfig);
+ //}}AFX_DATA_MAP
+ GetDlgItem(IDC_BUTTON1)->EnableWindow(1 == m_iAccess);
+ GetDlgItem(IDC_BUTTON2)->EnableWindow(1 == m_iLaunch);
+ GetDlgItem(IDC_BUTTON3)->EnableWindow(1 == m_iConfig);
+}
+
+BEGIN_MESSAGE_MAP(CSecurityPropertyPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CSecurityPropertyPage)
+ ON_BN_CLICKED(IDC_RADIO1, OnDefaultAccess)
+ ON_BN_CLICKED(IDC_RADIO2, OnCustomAccess)
+ ON_BN_CLICKED(IDC_RADIO3, OnDefaultLaunch)
+ ON_BN_CLICKED(IDC_RADIO4, OnCustomLaunch)
+ ON_BN_CLICKED(IDC_RADIO5, OnDefaultConfig)
+ ON_BN_CLICKED(IDC_RADIO6, OnCustomConfig)
+ ON_BN_CLICKED(IDC_BUTTON1, OnEditAccess)
+ ON_BN_CLICKED(IDC_BUTTON2, OnEditLaunch)
+ ON_BN_CLICKED(IDC_BUTTON3, OnEditConfig)
+ ON_WM_HELPINFO()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+void CSecurityPropertyPage::OnDefaultAccess()
+{
+ // Disable the edit access permissions window
+ UpdateData(TRUE);
+
+ // If there is an SD here then mark it for delete
+ if (m_iAccessIndex != -1)
+ {
+ CDataPacket &cdp = g_virtreg.GetAt(m_iAccessIndex);
+ cdp.fDelete = TRUE;
+ SetModified(TRUE);
+ }
+}
+
+void CSecurityPropertyPage::OnCustomAccess()
+{
+ UpdateData(TRUE);
+
+ // If there is an SD here then unmark it for delete
+ if (m_iAccessIndex != -1)
+ {
+ CDataPacket &cdp = g_virtreg.GetAt(m_iAccessIndex);
+ cdp.fDelete = FALSE;
+ SetModified(TRUE);
+ }
+}
+
+void CSecurityPropertyPage::OnDefaultLaunch()
+{
+ UpdateData(TRUE);
+
+ // If there is an SD here then mark it for delete
+ if (m_iLaunchIndex != -1)
+ {
+ CDataPacket &cdp = g_virtreg.GetAt(m_iLaunchIndex);
+ cdp.fDelete = TRUE;
+ SetModified(TRUE);
+ }
+}
+
+void CSecurityPropertyPage::OnCustomLaunch()
+{
+ UpdateData(TRUE);
+
+ // If there is an SD here then unmark it for delete
+ if (m_iLaunchIndex != -1)
+ {
+ CDataPacket &cdp = g_virtreg.GetAt(m_iLaunchIndex);
+ cdp.fDelete = FALSE;
+ }
+}
+
+void CSecurityPropertyPage::OnDefaultConfig()
+{
+ int err;
+ ULONG ulSize = 1;
+ BYTE *pbValue = NULL;
+
+ // Read the security descriptor for HKEY_CLASSES_ROOT
+ // Note: We always expect to get ERROR_INSUFFICIENT_BUFFER
+ err = RegGetKeySecurity(HKEY_CLASSES_ROOT,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ pbValue,
+ &ulSize);
+ if (err == ERROR_INSUFFICIENT_BUFFER)
+ {
+ pbValue = new BYTE[ulSize];
+ if (pbValue == NULL)
+ {
+ return;
+ }
+ err = RegGetKeySecurity(HKEY_CLASSES_ROOT,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ pbValue,
+ &ulSize);
+ }
+ // Change the custom security back to the default, if there is a custom
+ // security descriptor, but just in the virtual registry -
+ // in case the user cancels
+ if (m_iConfigurationIndex != -1)
+ {
+ CDataPacket &cdb = g_virtreg.GetAt(m_iConfigurationIndex);
+ cdb.ChgACL((SECURITY_DESCRIPTOR *) pbValue, TRUE);
+ cdb.fDirty = TRUE;
+ }
+ delete pbValue;
+
+ UpdateData(TRUE);
+ SetModified(TRUE);
+}
+
+
+
+void CSecurityPropertyPage::OnCustomConfig()
+{
+ // If a security descriptor already exists, then the user was here
+ // before, then selected default configuration. So just copy the
+ // original as the extant custom configuration
+ if (m_iConfigurationIndex != -1)
+ {
+ CDataPacket &cdb = g_virtreg.GetAt(m_iConfigurationIndex);
+ cdb.ChgACL(cdb.pkt.racl.pSecOrig, TRUE);
+ }
+
+ UpdateData(TRUE);
+ SetModified(TRUE);
+}
+
+
+
+void CSecurityPropertyPage::OnEditAccess()
+{
+ int err;
+ CString szAccess;
+
+ szAccess.LoadString(IDS_Access);
+
+ // Invoke the ACL editor
+ err = g_util.ACLEditor(m_hWnd,
+ g_hAppid,
+ NULL,
+ TEXT("AccessPermission"),
+ &m_iAccessIndex,
+ SingleACL,
+ (TCHAR *) ((LPCTSTR) szAccess));
+
+ // Enable the Apply button
+ if (err == ERROR_SUCCESS)
+ {
+ SetModified(TRUE);
+ }
+}
+
+void CSecurityPropertyPage::OnEditLaunch()
+{
+ int err;
+ CString szLaunch;
+
+ szLaunch.LoadString(IDS_Launch);
+
+ // Invoke the ACL editor
+ err = g_util.ACLEditor(m_hWnd,
+ g_hAppid,
+ NULL,
+ TEXT("LaunchPermission"),
+ &m_iLaunchIndex,
+ SingleACL,
+ (TCHAR *) ((LPCTSTR) szLaunch));
+
+ // Enable the Apply button
+ if (err == ERROR_SUCCESS)
+ {
+ SetModified(TRUE);
+ }
+}
+
+void CSecurityPropertyPage::OnEditConfig()
+{
+ int err = ERROR_SUCCESS;
+
+ // Invoke the ACL editor
+ err = g_util.ACLEditor2(m_hWnd,
+ g_hAppid,
+ g_rghkCLSID,
+ g_cCLSIDs,
+ g_szAppTitle,
+ &m_iConfigurationIndex,
+ RegKeyACL);
+
+ // Enable the Apply button
+ if (err == ERROR_SUCCESS)
+ {
+ SetModified(TRUE);
+ }
+ else if (err == ERROR_ACCESS_DENIED)
+ {
+ g_util.CkForAccessDenied(ERROR_ACCESS_DENIED);
+ }
+ else if (err != IDCANCEL)
+ {
+ g_util.PostErrorMessage();
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CIdentityPropertyPage property page
+
+CIdentityPropertyPage::CIdentityPropertyPage() : CPropertyPage(CIdentityPropertyPage::IDD)
+{
+ //{{AFX_DATA_INIT(CIdentityPropertyPage)
+ m_szUserName = _T("");
+ m_szPassword = _T("");
+ m_szConfirmPassword = _T("");
+ m_iIdentity = -1;
+ //}}AFX_DATA_INIT
+}
+
+CIdentityPropertyPage::~CIdentityPropertyPage()
+{
+}
+
+void CIdentityPropertyPage::DoDataExchange(CDataExchange* pDX)
+{
+ // If server is not a service, disable IDC_RADIO4 on page4.
+ if (m_fService)
+ {
+ GetDlgItem(IDC_RADIO1)->EnableWindow(FALSE);
+ GetDlgItem(IDC_RADIO2)->EnableWindow(FALSE);
+ }
+ else
+ {
+ GetDlgItem(IDC_RADIO4)->EnableWindow(FALSE);
+ }
+
+ CPropertyPage::DoDataExchange(pDX);
+
+ //{{AFX_DATA_MAP(CIdentityPropertyPage)
+ DDX_Text(pDX, IDC_EDIT1, m_szUserName);
+ DDV_MaxChars(pDX, m_szUserName, 128);
+ DDX_Text(pDX, IDC_EDIT2, m_szPassword);
+ DDV_MaxChars(pDX, m_szPassword, 128);
+ DDX_Text(pDX, IDC_EDIT3, m_szConfirmPassword);
+ DDV_MaxChars(pDX, m_szConfirmPassword, 128);
+ DDX_Radio(pDX, IDC_RADIO1, m_iIdentity);
+ //}}AFX_DATA_MAP
+
+ GetDlgItem(IDC_EDIT1)->EnableWindow(2 == m_iIdentity);
+ GetDlgItem(IDC_STATIC1)->EnableWindow(2 == m_iIdentity);
+ GetDlgItem(IDC_EDIT2)->EnableWindow(2 == m_iIdentity);
+ GetDlgItem(IDC_STATIC2)->EnableWindow(2 == m_iIdentity);
+ GetDlgItem(IDC_EDIT3)->EnableWindow(2 == m_iIdentity);
+ GetDlgItem(IDC_STATIC3)->EnableWindow(2 == m_iIdentity);
+ GetDlgItem(IDC_BUTTON1)->EnableWindow(2 == m_iIdentity);
+
+
+}
+
+BEGIN_MESSAGE_MAP(CIdentityPropertyPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CIdentityPropertyPage)
+ ON_EN_CHANGE(IDC_EDIT1, OnChange)
+ ON_BN_CLICKED(IDC_BUTTON1, OnBrowse)
+ ON_EN_CHANGE(IDC_EDIT2, OnChange)
+ ON_EN_CHANGE(IDC_EDIT3, OnChange)
+ ON_BN_CLICKED(IDC_RADIO1, OnChange)
+ ON_BN_CLICKED(IDC_RADIO2, OnChange)
+ ON_BN_CLICKED(IDC_RADIO3, OnChange)
+ ON_BN_CLICKED(IDC_RADIO4, OnChange)
+ ON_WM_HELPINFO()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+void CIdentityPropertyPage::OnBrowse()
+{
+ TCHAR szUser[128];
+
+ if (g_util.InvokeUserBrowser(m_hWnd, szUser))
+ {
+ GetDlgItem(IDC_EDIT1)->SetWindowText(szUser);
+ SetModified(TRUE);
+ }
+}
+
+void CIdentityPropertyPage::OnChange()
+{
+ // TODO: Add your control notification handler code here
+ UpdateData(TRUE);
+ SetModified(TRUE);
+}
+
+
+
+
+
+
+
+BOOL CGeneralPropertyPage::OnHelpInfo(HELPINFO* pHelpInfo)
+{
+ // TODO: Add your message handler code here and/or call default
+
+ if(-1 != pHelpInfo->iCtrlId)
+ {
+ WORD hiWord = 0x8000 | CGeneralPropertyPage::IDD;
+ WORD loWord = pHelpInfo->iCtrlId;
+ DWORD dwLong = MAKELONG(loWord,hiWord);
+
+ WinHelp(dwLong, HELP_CONTEXTPOPUP);
+ return TRUE;
+ }
+
+ else
+ {
+ return CPropertyPage::OnHelpInfo(pHelpInfo);
+ }
+}
+
+
+
+
+
+
+
+BOOL CLocationPropertyPage::OnHelpInfo(HELPINFO* pHelpInfo)
+{
+ // TODO: Add your message handler code here and/or call default
+
+ if(-1 != pHelpInfo->iCtrlId)
+ {
+ WORD hiWord = 0x8000 | CLocationPropertyPage::IDD;
+ WORD loWord = pHelpInfo->iCtrlId;
+ DWORD dwLong = MAKELONG(loWord,hiWord);
+
+ WinHelp(dwLong, HELP_CONTEXTPOPUP);
+ return TRUE;
+ }
+
+ else
+ {
+ return CPropertyPage::OnHelpInfo(pHelpInfo);
+ }
+}
+
+
+
+
+
+
+
+BOOL CSecurityPropertyPage::OnHelpInfo(HELPINFO* pHelpInfo)
+{
+ // TODO: Add your message handler code here and/or call default
+
+ if(-1 != pHelpInfo->iCtrlId)
+ {
+ WORD hiWord = 0x8000 | CSecurityPropertyPage::IDD;
+ WORD loWord = pHelpInfo->iCtrlId;
+ DWORD dwLong = MAKELONG(loWord,hiWord);
+
+ WinHelp(dwLong, HELP_CONTEXTPOPUP);
+ return TRUE;
+ }
+
+ else
+ {
+ return CPropertyPage::OnHelpInfo(pHelpInfo);
+ }
+}
+
+
+
+
+
+
+
+BOOL CIdentityPropertyPage::OnHelpInfo(HELPINFO* pHelpInfo)
+{
+ // TODO: Add your message handler code here and/or call default
+
+ if(-1 != pHelpInfo->iCtrlId)
+ {
+ WORD hiWord = 0x8000 | CIdentityPropertyPage::IDD;
+ WORD loWord = pHelpInfo->iCtrlId;
+ DWORD dwLong = MAKELONG(loWord,hiWord);
+
+ WinHelp(dwLong, HELP_CONTEXTPOPUP);
+ return TRUE;
+ }
+
+ else
+ {
+ return CPropertyPage::OnHelpInfo(pHelpInfo);
+ }
+}
diff --git a/private/ole32/oleui/locppg.h b/private/ole32/oleui/locppg.h
new file mode 100644
index 000000000..6cbfac8c9
--- /dev/null
+++ b/private/ole32/oleui/locppg.h
@@ -0,0 +1,212 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: locppg.h
+//
+// Contents: Defines the classes CGeneralPropertyPage,
+// CLocationPropertyPage, CSecurityPropertyPage and
+// CIdentityPropertyPage which manage the four property
+// pages per AppId.
+//
+// Classes:
+//
+// Methods:
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+#ifndef __LOCPPG_H__
+#define __LOCPPG_H__
+
+/////////////////////////////////////////////////////////////////////////////
+// CGeneralPropertyPage dialog
+
+class CGeneralPropertyPage : public CPropertyPage
+{
+ DECLARE_DYNCREATE(CGeneralPropertyPage)
+
+// Construction
+public:
+ CGeneralPropertyPage();
+ ~CGeneralPropertyPage();
+
+// Dialog Data
+ //{{AFX_DATA(CGeneralPropertyPage)
+ enum { IDD = IDD_PROPPAGE5 };
+ CString m_szServerName;
+ CString m_szServerPath;
+ CString m_szServerType;
+ CString m_szPathTitle;
+ CString m_szComputerName;
+ //}}AFX_DATA
+
+ int m_iServerType;
+ BOOL m_fSurrogate;
+
+// Overrides
+ // ClassWizard generate virtual function overrides
+ //{{AFX_VIRTUAL(CGeneralPropertyPage)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CGeneralPropertyPage)
+ // NOTE: the ClassWizard will add member functions here
+ afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CLocationPropertyPage dialog
+
+class CLocationPropertyPage : public CPropertyPage
+{
+ DECLARE_DYNCREATE(CLocationPropertyPage)
+
+// Construction
+public:
+ CLocationPropertyPage();
+ ~CLocationPropertyPage();
+
+// Dialog Data
+ //{{AFX_DATA(CLocationPropertyPage)
+ enum { IDD = IDD_PROPPAGE11 };
+ CString m_szComputerName;
+ BOOL m_fAtStorage;
+ BOOL m_fLocal;
+ BOOL m_fRemote;
+ int m_iInitial;
+ //}}AFX_DATA
+
+ BOOL m_fCanBeLocal;
+ CGeneralPropertyPage * m_pPage1;
+
+// Overrides
+ // ClassWizard generate virtual function overrides
+ //{{AFX_VIRTUAL(CLocationPropertyPage)
+ public:
+ virtual BOOL OnSetActive();
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CLocationPropertyPage)
+ afx_msg void OnBrowse();
+ afx_msg void OnRunRemote();
+ afx_msg void OnChange();
+ afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+ void UpdateControls();
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CSecurityPropertyPage dialog
+
+class CSecurityPropertyPage : public CPropertyPage
+{
+ DECLARE_DYNCREATE(CSecurityPropertyPage)
+
+// Construction
+public:
+ CSecurityPropertyPage();
+ ~CSecurityPropertyPage();
+
+// Dialog Data
+ //{{AFX_DATA(CSecurityPropertyPage)
+ enum { IDD = IDD_PROPPAGE21 };
+ int m_iAccess;
+ int m_iLaunch;
+ int m_iConfig;
+ int m_iAccessIndex;
+ int m_iLaunchIndex;
+ int m_iConfigurationIndex;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generate virtual function overrides
+ //{{AFX_VIRTUAL(CSecurityPropertyPage)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CSecurityPropertyPage)
+ afx_msg void OnDefaultAccess();
+ afx_msg void OnCustomAccess();
+ afx_msg void OnDefaultLaunch();
+ afx_msg void OnCustomLaunch();
+ afx_msg void OnDefaultConfig();
+ afx_msg void OnCustomConfig();
+ afx_msg void OnEditAccess();
+ afx_msg void OnEditLaunch();
+ afx_msg void OnEditConfig();
+ afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CIdentityPropertyPage dialog
+
+class CIdentityPropertyPage : public CPropertyPage
+{
+ DECLARE_DYNCREATE(CIdentityPropertyPage)
+
+// Construction
+public:
+ CIdentityPropertyPage();
+ ~CIdentityPropertyPage();
+
+// Dialog Data
+ //{{AFX_DATA(CIdentityPropertyPage)
+ enum { IDD = IDD_PROPPAGE3 };
+ CString m_szUserName;
+ CString m_szPassword;
+ CString m_szConfirmPassword;
+ int m_iIdentity;
+ //}}AFX_DATA
+
+ int m_fService;
+
+// Overrides
+ // ClassWizard generate virtual function overrides
+ //{{AFX_VIRTUAL(CIdentityPropertyPage)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CIdentityPropertyPage)
+ afx_msg void OnChange();
+ afx_msg void OnBrowse();
+ afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+};
+
+
+
+#endif // __LOCPPG_H__
diff --git a/private/ole32/oleui/newsrvr.cpp b/private/ole32/oleui/newsrvr.cpp
new file mode 100644
index 000000000..779dda612
--- /dev/null
+++ b/private/ole32/oleui/newsrvr.cpp
@@ -0,0 +1,81 @@
+//+---------------------------------u------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: newsrvr.cpp
+//
+// Contents: Implements the new server dialog
+//
+// Classes:
+//
+// Methods: CNewServer::CNewServer
+// CNewServer::~CNewServer
+// CNewServer::DoDataExchange
+// CNewServer::OnLocal
+// CNewServer::OnRemote
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+#include "stdafx.h"
+#include "olecnfg.h"
+#include "newsrvr.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CNewServer dialog
+
+
+CNewServer::CNewServer(CWnd* pParent /*=NULL*/)
+ : CDialog(CNewServer::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CNewServer)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+}
+
+
+void CNewServer::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CNewServer)
+ // NOTE: the ClassWizard will add DDX and DDV calls here
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CNewServer, CDialog)
+ //{{AFX_MSG_MAP(CNewServer)
+ ON_BN_CLICKED(IDC_RADIO1, OnLocal)
+ ON_BN_CLICKED(IDC_RADIO2, OnRemote)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CNewServer message handlers
+
+void CNewServer::OnLocal()
+{
+ // TODO: Add your control notification handler code here
+ GetDlgItem(IDC_EDIT2)->EnableWindow(TRUE);
+ GetDlgItem(IDC_BUTTON1)->EnableWindow(TRUE);
+ GetDlgItem(IDC_EDIT3)->EnableWindow(FALSE);
+ GetDlgItem(IDC_BUTTON2)->EnableWindow(FALSE);
+}
+
+void CNewServer::OnRemote()
+{
+ // TODO: Add your control notification handler code here
+ GetDlgItem(IDC_EDIT3)->EnableWindow(TRUE);
+ GetDlgItem(IDC_BUTTON2)->EnableWindow(TRUE);
+ GetDlgItem(IDC_EDIT2)->EnableWindow(FALSE);
+ GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
+}
diff --git a/private/ole32/oleui/newsrvr.h b/private/ole32/oleui/newsrvr.h
new file mode 100644
index 000000000..28eca2b88
--- /dev/null
+++ b/private/ole32/oleui/newsrvr.h
@@ -0,0 +1,55 @@
+//+---------------------------------u------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: newsrvr.h
+//
+// Contents: Defines the class CNewServer for the new server dialog
+//
+// Classes:
+//
+// Methods:
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CNewServer dialog
+#ifndef _NEWSRVR_H_
+#define _NEWSRVR_H_
+
+class CNewServer : public CDialog
+{
+// Construction
+public:
+ CNewServer(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CNewServer)
+ enum { IDD = IDD_DIALOG1 };
+ // NOTE: the ClassWizard will add data members here
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CNewServer)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+ // Generated message map functions
+ //{{AFX_MSG(CNewServer)
+ afx_msg void OnLocal();
+ afx_msg void OnRemote();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+#endif //_NEWSRVR_H_
diff --git a/private/ole32/oleui/olecnfg.cpp b/private/ole32/oleui/olecnfg.cpp
new file mode 100644
index 000000000..406ee3ecc
--- /dev/null
+++ b/private/ole32/oleui/olecnfg.cpp
@@ -0,0 +1,117 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: olecnfg.cpp
+//
+// Contents: Implements the class COlecnfgApp - the top level class
+// for dcomcnfg.exe
+//
+// Classes:
+//
+// Methods: COlecnfgApp::COlecnfgApp
+// COlecnfgApp::InitInstance
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+#include "stdafx.h"
+#include "afxtempl.h"
+#include "olecnfg.h"
+#include "CStrings.h"
+#include "CReg.h"
+#include "types.h"
+#include "datapkt.h"
+#include "virtreg.h"
+#include "CnfgPSht.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// COlecnfgApp
+
+BEGIN_MESSAGE_MAP(COlecnfgApp, CWinApp)
+ //{{AFX_MSG_MAP(COlecnfgApp)
+ // NOTE - the ClassWizard will add and remove mapping macros here.
+ // DO NOT EDIT what you see in these blocks of generated code!
+ ON_COMMAND(ID_CONTEXT_HELP, CWinApp::OnContextHelp)
+ //}}AFX_MSG
+
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// COlecnfgApp construction
+
+COlecnfgApp::COlecnfgApp()
+{
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only COlecnfgApp object
+
+COlecnfgApp theApp;
+
+/////////////////////////////////////////////////////////////////////////////
+// COlecnfgApp initialization
+
+BOOL COlecnfgApp::InitInstance()
+{
+ // Standard initialization
+ // If you are not using these features and wish to reduce the size
+ // of your final executable, you should remove from the following
+ // the specific initialization routines you do not need.
+
+#ifdef _AFXDLL
+ Enable3dControls(); // Call this when using MFC in a shared DLL
+#else
+ Enable3dControlsStatic(); // Call this when linking to MFC statically
+#endif
+
+ // This tool really so only be run by administrators. We check this
+ // by trying to get KEY_ALL_ACCESS rights to
+ // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLE
+ HKEY hKey;
+
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\OLE"),
+ 0, KEY_ALL_ACCESS, &hKey)
+ != ERROR_SUCCESS)
+ {
+ CString sCaption;
+ CString sMessage;
+
+ sCaption.LoadString(IDS_SYSTEMMESSAGE);
+ sMessage.LoadString(IDS_ADMINSONLY);
+ MessageBox(NULL, sMessage, sCaption, MB_OK);
+ return FALSE;
+ }
+
+ // The main body of oleui
+ COlecnfgPropertySheet psht;
+ m_pMainWnd = &psht;
+ int nResponse = psht.DoModal();
+ if (nResponse == IDOK)
+ {
+ g_virtreg.Ok(0);
+ }
+ else if (nResponse == IDCANCEL)
+ {
+ g_virtreg.Cancel(0);
+ }
+
+ // Remove the virtual registry
+ g_virtreg.RemoveAll();
+
+ // Since the dialog has been closed, return FALSE so that we exit the
+ // application, rather than start the application's message pump.
+ return FALSE;
+}
+
diff --git a/private/ole32/oleui/olecnfg.h b/private/ole32/oleui/olecnfg.h
new file mode 100644
index 000000000..679f5cdf0
--- /dev/null
+++ b/private/ole32/oleui/olecnfg.h
@@ -0,0 +1,53 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: olecnfg.h
+//
+// Contents: Implements the class COlecnfgApp - the top level class
+// for dcomcnfg.exe
+//
+// Classes:
+//
+// Methods:
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+#ifndef __AFXWIN_H__
+ #error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h" // main symbols
+
+/////////////////////////////////////////////////////////////////////////////
+// COlecnfgApp:
+// See olecnfg.cpp for the implementation of this class
+//
+
+class COlecnfgApp : public CWinApp
+{
+public:
+ COlecnfgApp();
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(COlecnfgApp)
+ public:
+ virtual BOOL InitInstance();
+ //}}AFX_VIRTUAL
+
+// Implementation
+
+ //{{AFX_MSG(COlecnfgApp)
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/private/ole32/oleui/olecnfg.hlp b/private/ole32/oleui/olecnfg.hlp
new file mode 100644
index 000000000..fffa071be
--- /dev/null
+++ b/private/ole32/oleui/olecnfg.hlp
Binary files differ
diff --git a/private/ole32/oleui/olecnfg.hpj b/private/ole32/oleui/olecnfg.hpj
new file mode 100644
index 000000000..38a686e0d
--- /dev/null
+++ b/private/ole32/oleui/olecnfg.hpj
@@ -0,0 +1,56 @@
+; This file is maintained by HCW. Do not modify this file directly.
+
+[OPTIONS]
+HCW=0
+LCID=0x409 0x0 0x0 ;English (United States)
+REPORT=Yes
+HLP=.\olecnfg.hlp
+
+[FILES]
+.\olecnfg.rtf
+
+[MAP]
+IDH_ACCESSPERMISSIONBTN=0x806c03e8 ; Access permission edit button
+IDH_ATBITSCHECK=0x806b03ee ; Actiavte AtBits checkbox
+IDH_CONFIGURATIONPERMISSIONBTN=0x806c03f3 ; Configuration permission edit button
+IDH_DEFAULTACCESSRADIO=0x806c03ec ; Default access permission radio button
+IDH_DEFAULTAUTHLEVEL=0x80690401 ; Default authentication level combo
+IDH_DEFAULTCONFIGURATIONRADIO=0x806c0408 ; Default configuration permission radio button
+IDH_DEFAULTIMPERLEVEL=0x80690402 ; Default impersonation level combo
+IDH_DEFAULTLAUNCHRADIO=0x806c03f7 ; Default launch permission radio button
+IDH_EDITACCESSRADIO=0x806c03ed ; Edit access permissions radio button.
+IDH_EDITCONFIGURATIONRADIO=0x806c0409 ; Edit configuration permissions radio button.
+IDH_EDITDEFAULTACCESSSECURITY=0x806e03e8 ; Default Access Security Edit Button
+IDH_EDITDEFAULTCONFIGURATIONSECURITY=0x806e03f3 ; Default configuration security edit button
+IDH_EDITDEFAULTLAUNCHSECURITY=0x806e03f1 ; Default launch security edit button
+IDH_EDITLAUNCHRADIO=0x806c0403 ; Edit launch permissions radio button
+IDH_ENABLEDCOMCK=0x806903ee ; Enable DCOM checkbox
+IDH_INTERACTIVEUSERRADIO=0x806d03ec ; Interactive user radio button
+IDH_LAUNCHINGUSERRADIO=0x806d03ed ; Launching user radio button
+IDH_LAUNCHPERMISSIONBTN=0x806c03f1 ; Launch permission edit button
+IDH_PAUSEBTN=0x806f03f3 ; Pause service button
+IDH_PROPERTIESBUTTON=0x806803e8 ; Properties button on initial property page
+IDH_PROPPAGE1=131176 ; First property page of first property sheet.
+IDH_REFTRACKING=0x806903ef ; Additional reference tracking checkbox
+IDH_REMOTEBROWSEBTN=0x806b03e8 ; Remote machine browse button.
+IDH_REMOTEBROWSEBTN=0x806b03f1 ; Remote machine browse button
+IDH_REMOTEMACHINE=0x806f0412 ; Remote machine text
+IDH_RUNASBROWSEBTN=0x806d03e8 ; RunAs browse button
+IDH_RUNASCONFIRMEDIT=0x806d0400 ; RunAs confirm password edit box
+IDH_RUNASPASSWORDEDIT=0x806d03ff ; RunAs password edit box
+IDH_RUNASUSEREDIT=0x806d03f2 ; RunAs user editr box
+IDH_RUNASUSERRADIO=0x806d03f7 ; This user radio button
+IDH_RUNLOCALLYCK=0x806b03ef ; Run server on local machine
+IDH_RUNNINGINSTANCES=0x806f03fb ; Running instances list box
+IDH_RUNREMOTECK=0x806b03f0 ; Remote activation checkbox
+IDH_RUNREMOTEEDIT=0x806b03f2 ; Remote machine edit box
+IDH_SERVERLISTBOX=0x806803eb ; The list of servers on the initial property page
+IDH_SERVERNAME=0x806f040d ; Server name text
+IDH_SERVERPATH=0x806f0410 ; Server executable path text
+IDH_SERVERTYPE=0x806f040f ; Type of server text
+IDH_STARTBTN=0x806f03f1 ; Start service button
+IDH_SYSTEMACCOUNTRADIO=0x806d0403 ; System account radio button
+IDH_TERMINATEBTN=0x806f03e8 ; Terinate server button
+
+[WINDOWS]
+Base="Distributed COM Configuration Help",(519,85,379,276),20484,(r14876671),(r12632256),f3
diff --git a/private/ole32/oleui/olecnfg.ico b/private/ole32/oleui/olecnfg.ico
new file mode 100644
index 000000000..a6d5e65fa
--- /dev/null
+++ b/private/ole32/oleui/olecnfg.ico
Binary files differ
diff --git a/private/ole32/oleui/olecnfg.mak b/private/ole32/oleui/olecnfg.mak
new file mode 100644
index 000000000..6d7871538
--- /dev/null
+++ b/private/ole32/oleui/olecnfg.mak
@@ -0,0 +1,1983 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+# TARGTYPE "Win32 (MIPS) Application" 0x0501
+
+!IF "$(CFG)" == ""
+CFG=olecnfg - Win32 MIPS Debug
+!MESSAGE No configuration specified. Defaulting to olecnfg - Win32 MIPS Debug.
+!ENDIF
+
+!IF "$(CFG)" != "olecnfg - Win32 Release" && "$(CFG)" !=\
+ "olecnfg - Win32 Debug" && "$(CFG)" != "olecnfg - Win32 MIPS Release" &&\
+ "$(CFG)" != "olecnfg - Win32 MIPS Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "olecnfg.mak" CFG="olecnfg - Win32 MIPS Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "olecnfg - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "olecnfg - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "olecnfg - Win32 MIPS Release" (based on "Win32 (MIPS) Application")
+!MESSAGE "olecnfg - Win32 MIPS Debug" (based on "Win32 (MIPS) Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "olecnfg - Win32 Debug"
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+# PROP BASE Use_MFC 5
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "$(OUTDIR)\olecnfg.exe" "$(OUTDIR)\olecnfg.bsc"
+
+CLEAN :
+ -@erase ".\Release\olecnfg.bsc"
+ -@erase ".\Release\locppg.sbr"
+ -@erase ".\Release\datapkt.sbr"
+ -@erase ".\Release\virtreg.sbr"
+ -@erase ".\Release\util.sbr"
+ -@erase ".\Release\clspsht.sbr"
+ -@erase ".\Release\newsrvr.sbr"
+ -@erase ".\Release\olecnfg.sbr"
+ -@erase ".\Release\cnfgpsht.sbr"
+ -@erase ".\Release\creg.sbr"
+ -@erase ".\Release\StdAfx.sbr"
+ -@erase ".\Release\cstrings.sbr"
+ -@erase ".\Release\srvppg.sbr"
+ -@erase ".\Release\olecnfg.exe"
+ -@erase ".\Release\StdAfx.obj"
+ -@erase ".\Release\cstrings.obj"
+ -@erase ".\Release\srvppg.obj"
+ -@erase ".\Release\locppg.obj"
+ -@erase ".\Release\datapkt.obj"
+ -@erase ".\Release\virtreg.obj"
+ -@erase ".\Release\util.obj"
+ -@erase ".\Release\clspsht.obj"
+ -@erase ".\Release\newsrvr.obj"
+ -@erase ".\Release\olecnfg.obj"
+ -@erase ".\Release\cnfgpsht.obj"
+ -@erase ".\Release\creg.obj"
+ -@erase ".\Release\olecnfg.res"
+ -@erase ".\Release\olecnfg.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_AFXDLL" /D "UNICODE" /D "_UNICODE" /D "_X86_" /FR /YX"stdafx.h" /c
+CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\
+ "_AFXDLL" /D "UNICODE" /D "_UNICODE" /D "_X86_" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/olecnfg.pch" /YX"stdafx.h" /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\Release/
+CPP_SBRS=.\Release/
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/olecnfg.res" /d "NDEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/olecnfg.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)/locppg.sbr" \
+ "$(INTDIR)/datapkt.sbr" \
+ "$(INTDIR)/virtreg.sbr" \
+ "$(INTDIR)/util.sbr" \
+ "$(INTDIR)/clspsht.sbr" \
+ "$(INTDIR)/newsrvr.sbr" \
+ "$(INTDIR)/olecnfg.sbr" \
+ "$(INTDIR)/cnfgpsht.sbr" \
+ "$(INTDIR)/creg.sbr" \
+ "$(INTDIR)/StdAfx.sbr" \
+ "$(INTDIR)/cstrings.sbr" \
+ "$(INTDIR)/srvppg.sbr"
+
+"$(OUTDIR)\olecnfg.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:I386
+# ADD LINK32 ntdll.lib acledit.lib advapi32.lib netui2.lib mpr.lib ntlanui.lib rpcrt4.lib ..\com\class\daytona\obj\i386\scm_c.obj /nologo /entry:"wWinMainCRTStartup" /subsystem:windows /debug /machine:I386
+# SUBTRACT LINK32 /verbose
+LINK32_FLAGS=ntdll.lib acledit.lib advapi32.lib netui2.lib mpr.lib ntlanui.lib\
+ rpcrt4.lib ..\com\class\daytona\obj\i386\scm_c.obj /nologo\
+ /entry:"wWinMainCRTStartup" /subsystem:windows /incremental:no\
+ /pdb:"$(OUTDIR)/olecnfg.pdb" /debug /machine:I386 /out:"$(OUTDIR)/olecnfg.exe"
+LINK32_OBJS= \
+ "$(INTDIR)/StdAfx.obj" \
+ "$(INTDIR)/cstrings.obj" \
+ "$(INTDIR)/srvppg.obj" \
+ "$(INTDIR)/locppg.obj" \
+ "$(INTDIR)/datapkt.obj" \
+ "$(INTDIR)/virtreg.obj" \
+ "$(INTDIR)/util.obj" \
+ "$(INTDIR)/clspsht.obj" \
+ "$(INTDIR)/newsrvr.obj" \
+ "$(INTDIR)/olecnfg.obj" \
+ "$(INTDIR)/cnfgpsht.obj" \
+ "$(INTDIR)/creg.obj" \
+ "$(INTDIR)/olecnfg.res"
+
+"$(OUTDIR)\olecnfg.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+# PROP BASE Use_MFC 5
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 6
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+OUTDIR=.\Debug
+INTDIR=.\Debug
+
+ALL : "$(OUTDIR)\olecnfg.exe" "$(OUTDIR)\olecnfg.pch" "$(OUTDIR)\olecnfg.bsc"
+
+CLEAN :
+ -@erase ".\Debug\vc40.pdb"
+ -@erase ".\Debug\vc40.idb"
+ -@erase ".\Debug\olecnfg.pch"
+ -@erase ".\Debug\olecnfg.bsc"
+ -@erase ".\Debug\StdAfx.sbr"
+ -@erase ".\Debug\virtreg.sbr"
+ -@erase ".\Debug\cstrings.sbr"
+ -@erase ".\Debug\srvppg.sbr"
+ -@erase ".\Debug\clspsht.sbr"
+ -@erase ".\Debug\util.sbr"
+ -@erase ".\Debug\datapkt.sbr"
+ -@erase ".\Debug\creg.sbr"
+ -@erase ".\Debug\newsrvr.sbr"
+ -@erase ".\Debug\olecnfg.sbr"
+ -@erase ".\Debug\cnfgpsht.sbr"
+ -@erase ".\Debug\locppg.sbr"
+ -@erase ".\Debug\olecnfg.exe"
+ -@erase ".\Debug\creg.obj"
+ -@erase ".\Debug\newsrvr.obj"
+ -@erase ".\Debug\olecnfg.obj"
+ -@erase ".\Debug\cnfgpsht.obj"
+ -@erase ".\Debug\locppg.obj"
+ -@erase ".\Debug\StdAfx.obj"
+ -@erase ".\Debug\virtreg.obj"
+ -@erase ".\Debug\cstrings.obj"
+ -@erase ".\Debug\srvppg.obj"
+ -@erase ".\Debug\clspsht.obj"
+ -@erase ".\Debug\util.obj"
+ -@erase ".\Debug\datapkt.obj"
+ -@erase ".\Debug\olecnfg.res"
+ -@erase ".\Debug\olecnfg.ilk"
+ -@erase ".\Debug\olecnfg.pdb"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /c
+# ADD CPP /MDd /W3 /Gm /GX /Zi /Od /Gf /Gy /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_AFXDLL" /D "UNICODE" /D "_UNICODE" /D "_X86_" /FR /YX"stdafx.h" /GZ /c
+CPP_PROJ=/MDd /W3 /Gm /GX /Zi /Od /Gf /Gy /D "_DEBUG" /D "WIN32" /D "_WINDOWS"\
+ /D "_AFXDLL" /D "UNICODE" /D "_UNICODE" /D "_X86_" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/olecnfg.pch" /YX"stdafx.h" /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /GZ /c\
+
+CPP_OBJS=.\Debug/
+CPP_SBRS=.\Debug/
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /win32
+# ADD MTL /nologo /D "_DEBUG" /win32
+MTL_PROJ=/nologo /D "_DEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/olecnfg.res" /d "_DEBUG" /d "_AFXDLL"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/olecnfg.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)/StdAfx.sbr" \
+ "$(INTDIR)/virtreg.sbr" \
+ "$(INTDIR)/cstrings.sbr" \
+ "$(INTDIR)/srvppg.sbr" \
+ "$(INTDIR)/clspsht.sbr" \
+ "$(INTDIR)/util.sbr" \
+ "$(INTDIR)/datapkt.sbr" \
+ "$(INTDIR)/creg.sbr" \
+ "$(INTDIR)/newsrvr.sbr" \
+ "$(INTDIR)/olecnfg.sbr" \
+ "$(INTDIR)/cnfgpsht.sbr" \
+ "$(INTDIR)/locppg.sbr"
+
+"$(OUTDIR)\olecnfg.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386
+# ADD LINK32 ntdll.lib acledit.lib advapi32.lib netui2.lib mpr.lib ntlanui.lib rpcrt4.lib ..\com\class\daytona\obj\i386\scm_c.obj /entry:"wWinMainCRTStartup" /subsystem:windows /debug /machine:I386
+# SUBTRACT LINK32 /nologo /verbose
+LINK32_FLAGS=ntdll.lib acledit.lib advapi32.lib netui2.lib mpr.lib ntlanui.lib\
+ rpcrt4.lib ..\com\class\daytona\obj\i386\scm_c.obj /entry:"wWinMainCRTStartup"\
+ /subsystem:windows /incremental:yes /pdb:"$(OUTDIR)/olecnfg.pdb" /debug\
+ /machine:I386 /out:"$(OUTDIR)/olecnfg.exe"
+LINK32_OBJS= \
+ "$(INTDIR)/creg.obj" \
+ "$(INTDIR)/newsrvr.obj" \
+ "$(INTDIR)/olecnfg.obj" \
+ "$(INTDIR)/cnfgpsht.obj" \
+ "$(INTDIR)/locppg.obj" \
+ "$(INTDIR)/StdAfx.obj" \
+ "$(INTDIR)/virtreg.obj" \
+ "$(INTDIR)/cstrings.obj" \
+ "$(INTDIR)/srvppg.obj" \
+ "$(INTDIR)/clspsht.obj" \
+ "$(INTDIR)/util.obj" \
+ "$(INTDIR)/datapkt.obj" \
+ "$(INTDIR)/olecnfg.res"
+
+"$(OUTDIR)\olecnfg.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+# PROP BASE Use_MFC 5
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 5
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+OUTDIR=.\Release
+INTDIR=.\Release
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+ALL : "$(OUTDIR)\olecnfg.exe"
+
+CLEAN :
+ -@erase ".\Release\olecnfg.exe"
+ -@erase ".\Release\clspsht.obj"
+ -@erase ".\Release\locppg.obj"
+ -@erase ".\Release\srvppg.obj"
+ -@erase ".\Release\olecnfg.obj"
+ -@erase ".\Release\creg.obj"
+ -@erase ".\Release\cnfgpsht.obj"
+ -@erase ".\Release\StdAfx.obj"
+ -@erase ".\Release\cstrings.obj"
+ -@erase ".\Release\olecnfg.res"
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mips
+# ADD MTL /nologo /D "NDEBUG" /mips
+MTL_PROJ=/nologo /D "NDEBUG" /mips
+CPP=cl.exe
+# ADD BASE CPP /nologo /MT /Gt0 /QMOb2000 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /c
+# ADD CPP /nologo /MT /Gt0 /QMOb2000 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /c
+CPP_PROJ=/nologo /MT /Gt0 /QMOb2000 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D\
+ "_WINDOWS" /D "_MBCS" /Fp"$(INTDIR)/olecnfg.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\Release/
+CPP_SBRS=
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/olecnfg.res" /d "NDEBUG"
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /machine:MIPS
+# ADD LINK32 /nologo /subsystem:windows /machine:MIPS
+LINK32_FLAGS=/nologo /subsystem:windows /incremental:no\
+ /pdb:"$(OUTDIR)/olecnfg.pdb" /machine:MIPS /out:"$(OUTDIR)/olecnfg.exe"
+LINK32_OBJS= \
+ "$(INTDIR)/clspsht.obj" \
+ "$(INTDIR)/locppg.obj" \
+ "$(INTDIR)/srvppg.obj" \
+ "$(INTDIR)/olecnfg.obj" \
+ "$(INTDIR)/creg.obj" \
+ "$(INTDIR)/cnfgpsht.obj" \
+ "$(INTDIR)/StdAfx.obj" \
+ "$(INTDIR)/cstrings.obj" \
+ "$(INTDIR)/olecnfg.res"
+
+"$(OUTDIR)\olecnfg.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/olecnfg.bsc"
+BSC32_SBRS=
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+# PROP BASE Use_MFC 5
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 5
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+OUTDIR=.\Debug
+INTDIR=.\Debug
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+ALL : "$(OUTDIR)\olecnfg.exe"
+
+CLEAN :
+ -@erase ".\Debug\vc40.pdb"
+ -@erase ".\Debug\olecnfg.exe"
+ -@erase ".\Debug\olecnfg.obj"
+ -@erase ".\Debug\StdAfx.obj"
+ -@erase ".\Debug\locppg.obj"
+ -@erase ".\Debug\creg.obj"
+ -@erase ".\Debug\cnfgpsht.obj"
+ -@erase ".\Debug\srvppg.obj"
+ -@erase ".\Debug\clspsht.obj"
+ -@erase ".\Debug\cstrings.obj"
+ -@erase ".\Debug\olecnfg.res"
+ -@erase ".\Debug\olecnfg.ilk"
+ -@erase ".\Debug\olecnfg.pdb"
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mips
+# ADD MTL /nologo /D "_DEBUG" /mips
+MTL_PROJ=/nologo /D "_DEBUG" /mips
+CPP=cl.exe
+# ADD BASE CPP /nologo /MTd /Gt0 /QMOb2000 /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /c
+# ADD CPP /nologo /MTd /Gt0 /QMOb2000 /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /c
+CPP_PROJ=/nologo /MTd /Gt0 /QMOb2000 /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D\
+ "_WINDOWS" /D "_MBCS" /Fp"$(INTDIR)/olecnfg.pch" /YX /Fo"$(INTDIR)/"\
+ /Fd"$(INTDIR)/" /c
+CPP_OBJS=.\Debug/
+CPP_SBRS=
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/olecnfg.res" /d "_DEBUG"
+LINK32=link.exe
+# ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:MIPS
+# SUBTRACT BASE LINK32 /incremental:no
+# ADD LINK32 /nologo /subsystem:windows /debug /machine:MIPS
+# SUBTRACT LINK32 /incremental:no
+LINK32_FLAGS=/nologo /subsystem:windows /incremental:yes\
+ /pdb:"$(OUTDIR)/olecnfg.pdb" /debug /machine:MIPS /out:"$(OUTDIR)/olecnfg.exe"
+LINK32_OBJS= \
+ "$(INTDIR)/olecnfg.obj" \
+ "$(INTDIR)/StdAfx.obj" \
+ "$(INTDIR)/locppg.obj" \
+ "$(INTDIR)/creg.obj" \
+ "$(INTDIR)/cnfgpsht.obj" \
+ "$(INTDIR)/srvppg.obj" \
+ "$(INTDIR)/clspsht.obj" \
+ "$(INTDIR)/cstrings.obj" \
+ "$(INTDIR)/olecnfg.res"
+
+"$(OUTDIR)\olecnfg.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/olecnfg.bsc"
+BSC32_SBRS=
+
+!ENDIF
+
+################################################################################
+# Begin Target
+
+# Name "olecnfg - Win32 Release"
+# Name "olecnfg - Win32 Debug"
+# Name "olecnfg - Win32 MIPS Release"
+# Name "olecnfg - Win32 MIPS Debug"
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\olecnfg.cpp
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+DEP_CPP_OLECN=\
+ ".\stdafx.h"\
+ ".\olecnfg.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+ ".\types.h"\
+ ".\datapkt.h"\
+ ".\virtreg.h"\
+ ".\cnfgpsht.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ ".\srvppg.h"\
+
+
+"$(INTDIR)\olecnfg.obj" : $(SOURCE) $(DEP_CPP_OLECN) "$(INTDIR)"
+
+"$(INTDIR)\olecnfg.sbr" : $(SOURCE) $(DEP_CPP_OLECN) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+DEP_CPP_OLECN=\
+ ".\stdafx.h"\
+ ".\olecnfg.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+ ".\types.h"\
+ ".\datapkt.h"\
+ ".\virtreg.h"\
+ ".\cnfgpsht.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ ".\srvppg.h"\
+
+
+"$(INTDIR)\olecnfg.obj" : $(SOURCE) $(DEP_CPP_OLECN) "$(INTDIR)"
+
+"$(INTDIR)\olecnfg.sbr" : $(SOURCE) $(DEP_CPP_OLECN) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+DEP_CPP_OLECN=\
+ ".\stdafx.h"\
+ ".\olecnfg.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+ ".\cnfgpsht.h"\
+ ".\srvppg.h"\
+
+
+"$(INTDIR)\olecnfg.obj" : $(SOURCE) $(DEP_CPP_OLECN) "$(INTDIR)"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+DEP_CPP_OLECN=\
+ ".\stdafx.h"\
+ ".\olecnfg.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+ ".\cnfgpsht.h"\
+ ".\srvppg.h"\
+
+
+"$(INTDIR)\olecnfg.obj" : $(SOURCE) $(DEP_CPP_OLECN) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+DEP_CPP_STDAF=\
+ ".\stdafx.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\cfg.h"\
+
+
+BuildCmds= \
+ $(CPP) /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\
+ "_AFXDLL" /D "UNICODE" /D "_UNICODE" /D "_X86_" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/olecnfg.pch" /YX"stdafx.h" /Fo"$(INTDIR)/" /c $(SOURCE) \
+
+
+"$(INTDIR)\StdAfx.obj" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)"
+ $(BuildCmds)
+
+"$(INTDIR)\StdAfx.sbr" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)"
+ $(BuildCmds)
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+DEP_CPP_STDAF=\
+ ".\stdafx.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+
+# ADD CPP /Yc"stdafx.h"
+
+BuildCmds= \
+ $(CPP) /MDd /W3 /Gm /GX /Zi /Od /Gf /Gy /D "_DEBUG" /D "WIN32" /D "_WINDOWS"\
+ /D "_AFXDLL" /D "UNICODE" /D "_UNICODE" /D "_X86_" /FR"$(INTDIR)/"\
+ /Fp"$(INTDIR)/olecnfg.pch" /Yc"stdafx.h" /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /GZ /c\
+ $(SOURCE) \
+
+
+"$(INTDIR)\StdAfx.obj" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)"
+ $(BuildCmds)
+
+"$(INTDIR)\StdAfx.sbr" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)"
+ $(BuildCmds)
+
+"$(INTDIR)\olecnfg.pch" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)"
+ $(BuildCmds)
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+DEP_CPP_STDAF=\
+ ".\stdafx.h"\
+
+
+"$(INTDIR)\StdAfx.obj" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+DEP_CPP_STDAF=\
+ ".\stdafx.h"\
+
+
+"$(INTDIR)\StdAfx.obj" : $(SOURCE) $(DEP_CPP_STDAF) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\olecnfg.rc
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+DEP_RSC_OLECNF=\
+ ".\olecnfg.ico"\
+ ".\res\olecnfg.rc2"\
+
+
+"$(INTDIR)\olecnfg.res" : $(SOURCE) $(DEP_RSC_OLECNF) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+DEP_RSC_OLECNF=\
+ ".\olecnfg.ico"\
+ ".\res\olecnfg.rc2"\
+
+
+"$(INTDIR)\olecnfg.res" : $(SOURCE) $(DEP_RSC_OLECNF) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+DEP_RSC_OLECNF=\
+ ".\res\olecnfg.ico"\
+ ".\res\olecnfg.rc2"\
+
+
+"$(INTDIR)\olecnfg.res" : $(SOURCE) $(DEP_RSC_OLECNF) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)/olecnfg.res" /d "NDEBUG" $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+DEP_RSC_OLECNF=\
+ ".\res\olecnfg.ico"\
+ ".\res\olecnfg.rc2"\
+
+
+"$(INTDIR)\olecnfg.res" : $(SOURCE) $(DEP_RSC_OLECNF) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)/olecnfg.res" /d "_DEBUG" $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cnfgpsht.cpp
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+DEP_CPP_CNFGP=\
+ ".\stdafx.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+ ".\types.h"\
+ ".\datapkt.h"\
+ {$(INCLUDE)}"\getuser.h"\
+ ".\util.h"\
+ ".\virtreg.h"\
+ ".\cnfgpsht.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ ".\srvppg.h"\
+
+
+"$(INTDIR)\cnfgpsht.obj" : $(SOURCE) $(DEP_CPP_CNFGP) "$(INTDIR)"
+
+"$(INTDIR)\cnfgpsht.sbr" : $(SOURCE) $(DEP_CPP_CNFGP) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+DEP_CPP_CNFGP=\
+ ".\stdafx.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+ ".\types.h"\
+ ".\datapkt.h"\
+ {$(INCLUDE)}"\getuser.h"\
+ ".\util.h"\
+ ".\virtreg.h"\
+ ".\cnfgpsht.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ ".\srvppg.h"\
+
+
+"$(INTDIR)\cnfgpsht.obj" : $(SOURCE) $(DEP_CPP_CNFGP) "$(INTDIR)"
+
+"$(INTDIR)\cnfgpsht.sbr" : $(SOURCE) $(DEP_CPP_CNFGP) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+DEP_CPP_CNFGP=\
+ ".\stdafx.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+ ".\cnfgpsht.h"\
+ ".\srvppg.h"\
+
+
+"$(INTDIR)\cnfgpsht.obj" : $(SOURCE) $(DEP_CPP_CNFGP) "$(INTDIR)"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+DEP_CPP_CNFGP=\
+ ".\stdafx.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+ ".\cnfgpsht.h"\
+ ".\srvppg.h"\
+
+
+"$(INTDIR)\cnfgpsht.obj" : $(SOURCE) $(DEP_CPP_CNFGP) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\srvppg.cpp
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+DEP_CPP_SRVPP=\
+ ".\stdafx.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+ ".\types.h"\
+ ".\srvppg.h"\
+ ".\clspsht.h"\
+ ".\newsrvr.h"\
+ ".\datapkt.h"\
+ {$(INCLUDE)}"\getuser.h"\
+ ".\util.h"\
+ ".\virtreg.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ ".\locppg.h"\
+
+
+"$(INTDIR)\srvppg.obj" : $(SOURCE) $(DEP_CPP_SRVPP) "$(INTDIR)"
+
+"$(INTDIR)\srvppg.sbr" : $(SOURCE) $(DEP_CPP_SRVPP) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+DEP_CPP_SRVPP=\
+ ".\stdafx.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+ ".\types.h"\
+ ".\srvppg.h"\
+ ".\clspsht.h"\
+ ".\newsrvr.h"\
+ ".\datapkt.h"\
+ {$(INCLUDE)}"\getuser.h"\
+ ".\util.h"\
+ ".\virtreg.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ ".\locppg.h"\
+
+
+"$(INTDIR)\srvppg.obj" : $(SOURCE) $(DEP_CPP_SRVPP) "$(INTDIR)"
+
+"$(INTDIR)\srvppg.sbr" : $(SOURCE) $(DEP_CPP_SRVPP) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+DEP_CPP_SRVPP=\
+ ".\stdafx.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+ ".\srvppg.h"\
+ ".\clspsht.h"\
+ ".\locppg.h"\
+
+
+"$(INTDIR)\srvppg.obj" : $(SOURCE) $(DEP_CPP_SRVPP) "$(INTDIR)"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+DEP_CPP_SRVPP=\
+ ".\stdafx.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+ ".\srvppg.h"\
+ ".\clspsht.h"\
+ ".\locppg.h"\
+
+
+"$(INTDIR)\srvppg.obj" : $(SOURCE) $(DEP_CPP_SRVPP) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\clspsht.cpp
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+DEP_CPP_CLSPS=\
+ ".\stdafx.h"\
+ ".\clspsht.h"\
+ ".\datapkt.h"\
+ {$(INCLUDE)}"\getuser.h"\
+ ".\util.h"\
+ ".\newsrvr.h"\
+ ".\virtreg.h"\
+ {$(INCLUDE)}"\sedapi.h"\
+ {$(INCLUDE)}"\ntlsa.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ ".\locppg.h"\
+
+
+"$(INTDIR)\clspsht.obj" : $(SOURCE) $(DEP_CPP_CLSPS) "$(INTDIR)"
+
+"$(INTDIR)\clspsht.sbr" : $(SOURCE) $(DEP_CPP_CLSPS) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+DEP_CPP_CLSPS=\
+ ".\stdafx.h"\
+ ".\clspsht.h"\
+ ".\datapkt.h"\
+ {$(INCLUDE)}"\getuser.h"\
+ ".\util.h"\
+ ".\newsrvr.h"\
+ ".\virtreg.h"\
+ {$(INCLUDE)}"\sedapi.h"\
+ {$(INCLUDE)}"\ntlsa.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ ".\locppg.h"\
+
+
+"$(INTDIR)\clspsht.obj" : $(SOURCE) $(DEP_CPP_CLSPS) "$(INTDIR)"
+
+"$(INTDIR)\clspsht.sbr" : $(SOURCE) $(DEP_CPP_CLSPS) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+DEP_CPP_CLSPS=\
+ ".\stdafx.h"\
+ ".\clspsht.h"\
+ ".\locppg.h"\
+
+
+"$(INTDIR)\clspsht.obj" : $(SOURCE) $(DEP_CPP_CLSPS) "$(INTDIR)"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+DEP_CPP_CLSPS=\
+ ".\stdafx.h"\
+ ".\clspsht.h"\
+ ".\locppg.h"\
+
+
+"$(INTDIR)\clspsht.obj" : $(SOURCE) $(DEP_CPP_CLSPS) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\locppg.cpp
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+DEP_CPP_LOCPP=\
+ ".\stdafx.h"\
+ ".\locppg.h"\
+ ".\clspsht.h"\
+ ".\datapkt.h"\
+ {$(INCLUDE)}"\getuser.h"\
+ ".\util.h"\
+ ".\virtreg.h"\
+ {$(INCLUDE)}"\ntlsa.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\cfg.h"\
+
+
+"$(INTDIR)\locppg.obj" : $(SOURCE) $(DEP_CPP_LOCPP) "$(INTDIR)"
+
+"$(INTDIR)\locppg.sbr" : $(SOURCE) $(DEP_CPP_LOCPP) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+DEP_CPP_LOCPP=\
+ ".\stdafx.h"\
+ ".\locppg.h"\
+ ".\clspsht.h"\
+ ".\datapkt.h"\
+ {$(INCLUDE)}"\getuser.h"\
+ ".\util.h"\
+ ".\virtreg.h"\
+ {$(INCLUDE)}"\ntlsa.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+
+
+"$(INTDIR)\locppg.obj" : $(SOURCE) $(DEP_CPP_LOCPP) "$(INTDIR)"
+
+"$(INTDIR)\locppg.sbr" : $(SOURCE) $(DEP_CPP_LOCPP) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+DEP_CPP_LOCPP=\
+ ".\stdafx.h"\
+ ".\locppg.h"\
+
+
+"$(INTDIR)\locppg.obj" : $(SOURCE) $(DEP_CPP_LOCPP) "$(INTDIR)"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+DEP_CPP_LOCPP=\
+ ".\stdafx.h"\
+ ".\locppg.h"\
+
+
+"$(INTDIR)\locppg.obj" : $(SOURCE) $(DEP_CPP_LOCPP) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\creg.cpp
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+DEP_CPP_CREG_=\
+ ".\stdafx.h"\
+ ".\types.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\cfg.h"\
+
+
+"$(INTDIR)\creg.obj" : $(SOURCE) $(DEP_CPP_CREG_) "$(INTDIR)"
+
+"$(INTDIR)\creg.sbr" : $(SOURCE) $(DEP_CPP_CREG_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+DEP_CPP_CREG_=\
+ ".\stdafx.h"\
+ ".\types.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+
+NODEP_CPP_CREG_=\
+ ".\szItem"\
+ ".\m_applications"\
+ ".\TRUE"\
+
+
+"$(INTDIR)\creg.obj" : $(SOURCE) $(DEP_CPP_CREG_) "$(INTDIR)"
+
+"$(INTDIR)\creg.sbr" : $(SOURCE) $(DEP_CPP_CREG_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+DEP_CPP_CREG_=\
+ ".\stdafx.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+
+
+"$(INTDIR)\creg.obj" : $(SOURCE) $(DEP_CPP_CREG_) "$(INTDIR)"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+DEP_CPP_CREG_=\
+ ".\stdafx.h"\
+ ".\cstrings.h"\
+ ".\creg.h"\
+
+
+"$(INTDIR)\creg.obj" : $(SOURCE) $(DEP_CPP_CREG_) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\cstrings.cpp
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+DEP_CPP_CSTRI=\
+ ".\stdafx.h"\
+ ".\types.h"\
+ ".\cstrings.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\cfg.h"\
+
+
+"$(INTDIR)\cstrings.obj" : $(SOURCE) $(DEP_CPP_CSTRI) "$(INTDIR)"
+
+"$(INTDIR)\cstrings.sbr" : $(SOURCE) $(DEP_CPP_CSTRI) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+DEP_CPP_CSTRI=\
+ ".\stdafx.h"\
+ ".\types.h"\
+ ".\cstrings.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+
+
+"$(INTDIR)\cstrings.obj" : $(SOURCE) $(DEP_CPP_CSTRI) "$(INTDIR)"
+
+"$(INTDIR)\cstrings.sbr" : $(SOURCE) $(DEP_CPP_CSTRI) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+DEP_CPP_CSTRI=\
+ ".\stdafx.h"\
+ ".\cstrings.h"\
+
+
+"$(INTDIR)\cstrings.obj" : $(SOURCE) $(DEP_CPP_CSTRI) "$(INTDIR)"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+DEP_CPP_CSTRI=\
+ ".\stdafx.h"\
+ ".\cstrings.h"\
+
+
+"$(INTDIR)\cstrings.obj" : $(SOURCE) $(DEP_CPP_CSTRI) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\newsrvr.cpp
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+DEP_CPP_NEWSR=\
+ ".\stdafx.h"\
+ ".\olecnfg.h"\
+ ".\newsrvr.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\cfg.h"\
+
+
+"$(INTDIR)\newsrvr.obj" : $(SOURCE) $(DEP_CPP_NEWSR) "$(INTDIR)"
+
+"$(INTDIR)\newsrvr.sbr" : $(SOURCE) $(DEP_CPP_NEWSR) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+DEP_CPP_NEWSR=\
+ ".\stdafx.h"\
+ ".\olecnfg.h"\
+ ".\newsrvr.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+
+
+"$(INTDIR)\newsrvr.obj" : $(SOURCE) $(DEP_CPP_NEWSR) "$(INTDIR)"
+
+"$(INTDIR)\newsrvr.sbr" : $(SOURCE) $(DEP_CPP_NEWSR) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\types.h
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\virtreg.cpp
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+DEP_CPP_VIRTR=\
+ ".\stdafx.h"\
+ {$(INCLUDE)}"\ntlsa.h"\
+ ".\types.h"\
+ ".\datapkt.h"\
+ {$(INCLUDE)}"\getuser.h"\
+ ".\util.h"\
+ ".\virtreg.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\cfg.h"\
+
+
+"$(INTDIR)\virtreg.obj" : $(SOURCE) $(DEP_CPP_VIRTR) "$(INTDIR)"
+
+"$(INTDIR)\virtreg.sbr" : $(SOURCE) $(DEP_CPP_VIRTR) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+DEP_CPP_VIRTR=\
+ ".\stdafx.h"\
+ {$(INCLUDE)}"\ntlsa.h"\
+ ".\types.h"\
+ ".\datapkt.h"\
+ {$(INCLUDE)}"\getuser.h"\
+ ".\util.h"\
+ ".\virtreg.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+
+
+"$(INTDIR)\virtreg.obj" : $(SOURCE) $(DEP_CPP_VIRTR) "$(INTDIR)"
+
+"$(INTDIR)\virtreg.sbr" : $(SOURCE) $(DEP_CPP_VIRTR) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\util.cpp
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+DEP_CPP_UTIL_=\
+ ".\stdafx.h"\
+ ".\types.h"\
+ ".\datapkt.h"\
+ ".\clspsht.h"\
+ {$(INCLUDE)}"\getuser.h"\
+ ".\util.h"\
+ ".\virtreg.h"\
+ {$(INCLUDE)}"\ntlsa.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\sedapi.h"\
+ {$(INCLUDE)}"\uiexport.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ ".\locppg.h"\
+
+
+"$(INTDIR)\util.obj" : $(SOURCE) $(DEP_CPP_UTIL_) "$(INTDIR)"
+
+"$(INTDIR)\util.sbr" : $(SOURCE) $(DEP_CPP_UTIL_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+DEP_CPP_UTIL_=\
+ ".\stdafx.h"\
+ ".\types.h"\
+ ".\datapkt.h"\
+ ".\clspsht.h"\
+ {$(INCLUDE)}"\getuser.h"\
+ ".\util.h"\
+ ".\virtreg.h"\
+ {$(INCLUDE)}"\ntlsa.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\sedapi.h"\
+ {$(INCLUDE)}"\uiexport.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ ".\locppg.h"\
+
+
+"$(INTDIR)\util.obj" : $(SOURCE) $(DEP_CPP_UTIL_) "$(INTDIR)"
+
+"$(INTDIR)\util.sbr" : $(SOURCE) $(DEP_CPP_UTIL_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=\nt\public\sdk\inc\ntrtl.h
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\datapkt.cpp
+
+!IF "$(CFG)" == "olecnfg - Win32 Release"
+
+DEP_CPP_DATAP=\
+ ".\stdafx.h"\
+ ".\datapkt.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\cfg.h"\
+
+
+"$(INTDIR)\datapkt.obj" : $(SOURCE) $(DEP_CPP_DATAP) "$(INTDIR)"
+
+"$(INTDIR)\datapkt.sbr" : $(SOURCE) $(DEP_CPP_DATAP) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 Debug"
+
+DEP_CPP_DATAP=\
+ ".\stdafx.h"\
+ ".\datapkt.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ ".\..\..\..\public\sdk\inc\nti386.h"\
+ ".\..\..\..\public\sdk\inc\ntmips.h"\
+ ".\..\..\..\public\sdk\inc\ntalpha.h"\
+ ".\..\..\..\public\sdk\inc\ntppc.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ ".\..\..\..\public\sdk\inc\mipsinst.h"\
+ ".\..\..\..\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+
+
+"$(INTDIR)\datapkt.obj" : $(SOURCE) $(DEP_CPP_DATAP) "$(INTDIR)"
+
+"$(INTDIR)\datapkt.sbr" : $(SOURCE) $(DEP_CPP_DATAP) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Release"
+
+!ELSEIF "$(CFG)" == "olecnfg - Win32 MIPS Debug"
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
+################################################################################
diff --git a/private/ole32/oleui/olecnfg.rc b/private/ole32/oleui/olecnfg.rc
new file mode 100644
index 000000000..9cf085c88
--- /dev/null
+++ b/private/ole32/oleui/olecnfg.rc
@@ -0,0 +1,564 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif\r\n"
+ "#include ""res\\olecnfg.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#endif\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON1 ICON DISCARDABLE "olecnfg.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OLECNFG_DIALOG DIALOGEX 0, 0, 319, 266
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "olecnfg"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,131,245,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,193,245,50,14
+ PUSHBUTTON "Help",IDC_BUTTON1,254,245,47,14
+END
+
+IDD_PROPPAGE1 DIALOG DISCARDABLE 0, 0, 252, 218
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Applications"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "App&lications:",IDC_STATIC,7,18,91,10
+ LTEXT "Status:",IDC_STATIC,177,18,60,10,NOT WS_VISIBLE
+ LISTBOX IDC_LIST1,7,28,238,160,LBS_SORT | WS_VSCROLL |
+ WS_TABSTOP
+ PUSHBUTTON "&Properties...",IDC_BUTTON1,7,194,71,14,WS_DISABLED
+END
+
+IDD_PROPPAGE2 DIALOG DISCARDABLE 0, 0, 252, 218
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Default Properties"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CONTROL "&Enable Distributed COM on this computer",IDC_CHECK1,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,7,169,17
+ GROUPBOX "Default Distributed COM communication properties",
+ IDC_STATIC,8,30,236,180
+ LTEXT "The Authentication Level specifies security at the packet level.",
+ IDC_STATIC,18,52,210,11
+ LTEXT "Default A&uthentication Level:",IDC_STATIC,18,67,157,8
+ COMBOBOX IDC_COMBO1,18,78,153,78,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_DISABLED | WS_VSCROLL | WS_TABSTOP
+ LTEXT "The Impersonation Level specifies whether applications can determine who is calling them, and whether the application can do operations using the client's identity.",
+ IDC_STATIC,18,111,212,30
+ LTEXT "Default &Impersonation Level:",IDC_STATIC,18,144,158,8
+ COMBOBOX IDC_COMBO2,18,155,153,48,CBS_DROPDOWNLIST | CBS_SORT |
+ WS_DISABLED | WS_VSCROLL | WS_TABSTOP
+ CONTROL "&Provide additional security for reference tracking",
+ IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_DISABLED |
+ WS_TABSTOP,18,185,214,20
+END
+
+IDD_PROPPAGE11 DIALOG DISCARDABLE 0, 0, 252, 218
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Location"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CONTROL "Run application on the computer where the data is &located",
+ IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,55,
+ 230,18
+ CONTROL "Run application on this &computer",IDC_CHECK2,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,7,76,230,19
+ CONTROL "Run application on the &following computer:",IDC_CHECK3,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,8,98,228,21
+ EDITTEXT IDC_EDIT1,7,119,174,15,ES_AUTOHSCROLL | WS_DISABLED
+ LTEXT "The following settings allow DCOM to locate the correct computer for this application. If you make more than one selection, then DCOM uses the first applicable one. Client applications may override your selections.",
+ IDC_STATIC,7,7,238,35
+ PUSHBUTTON "&Browse...",IDC_BUTTON1,185,119,59,14
+END
+
+IDD_PROPPAGE5 DIALOG DISCARDABLE 0, 0, 252, 218
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "General"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "General properties of this DCOM application",IDC_STATIC,
+ 7,6,238,97
+ GROUPBOX "&Running instances",IDC_RUNNING,7,111,238,99,NOT
+ WS_VISIBLE
+ LTEXT "<Server name>",IDC_SERVERNAME,89,25,149,8
+ LTEXT "Application type:",IDC_APPTYPE,18,43,62,8
+ LTEXT "<Server type>",IDC_SERVERTYPE,89,43,151,8
+ LTEXT "Local path:",IDC_PATHTITLE,18,58,37,8
+ LTEXT "<Server path>",IDC_SERVERPATH,18,69,219,8
+ LTEXT "Remote computer:",IDC_MACHINETITLE,18,83,62,8,NOT
+ WS_VISIBLE
+ LTEXT "<machine>",IDC_MACHINE,89,83,151,8
+ LISTBOX IDC_LIST2,19,119,157,79,LBS_SORT | LBS_NOINTEGRALHEIGHT |
+ NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "&Terminate",IDC_BUTTON1,185,119,52,14,NOT WS_VISIBLE |
+ WS_DISABLED
+ PUSHBUTTON "&Start",IDC_BUTTON2,185,137,52,14,NOT WS_VISIBLE |
+ WS_DISABLED
+ PUSHBUTTON "&Pause",IDC_BUTTON3,185,155,52,14,NOT WS_VISIBLE |
+ WS_DISABLED
+ LTEXT "Application name:",IDC_APPNAME,15,26,67,12
+END
+
+IDD_PROPPAGE21 DIALOG DISCARDABLE 0, 0, 252, 218
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Security"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX " ",IDC_STATIC,7,20,
+ 238,50
+ GROUPBOX " ",IDC_STATIC,7,89,
+ 238,50
+ GROUPBOX " ",IDC_STATIC,
+ 7,160,238,50
+ LTEXT "You may edit who can access this application.",
+ IDC_STATIC,15,34,146,14
+ LTEXT "You may edit who can launch this application.",
+ IDC_STATIC,15,103,149,9
+ LTEXT "You may edit who can change the configuration information for this application.",
+ IDC_STATIC,15,171,220,17
+ CONTROL "Use default acc&ess permissions",IDC_RADIO1,"Button",
+ BS_AUTORADIOBUTTON | WS_GROUP,14,7,117,11
+ CONTROL "Use custom access permissions",IDC_RADIO2,"Button",
+ BS_AUTORADIOBUTTON,14,20,120,10
+ PUSHBUTTON "Edit...",IDC_BUTTON1,166,47,70,14,WS_DISABLED
+ CONTROL "Use default &launch permissions",IDC_RADIO3,"Button",
+ BS_AUTORADIOBUTTON | WS_GROUP,14,77,124,8
+ CONTROL "Use custom launch permissions",IDC_RADIO4,"Button",
+ BS_AUTORADIOBUTTON,14,90,119,10
+ PUSHBUTTON "Edit...",IDC_BUTTON2,168,117,70,14,WS_DISABLED
+ CONTROL "Use default &configuration permissions",IDC_RADIO5,
+ "Button",BS_AUTORADIOBUTTON | WS_GROUP,14,147,172,10
+ CONTROL "Use custom configuration permissions",IDC_RADIO6,
+ "Button",BS_AUTORADIOBUTTON,14,160,134,10
+ PUSHBUTTON "Edit...",IDC_BUTTON3,168,187,70,14,WS_DISABLED
+END
+
+IDD_PROPPAGE3 DIALOG DISCARDABLE 0, 0, 252, 218
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Identity"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CONTROL "The &interactive user",IDC_RADIO1,"Button",
+ BS_AUTORADIOBUTTON | WS_GROUP,6,30,223,16
+ CONTROL "The &launching user",IDC_RADIO2,"Button",
+ BS_AUTORADIOBUTTON,6,49,205,16
+ CONTROL "This &user:",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,6,
+ 69,216,17
+ CONTROL "The &System Account (services only)",IDC_RADIO4,
+ "Button",BS_AUTORADIOBUTTON,6,161,174,14
+ LTEXT "Us&er:",IDC_STATIC1,17,90,40,12
+ EDITTEXT IDC_EDIT1,92,87,90,16,ES_AUTOHSCROLL | WS_DISABLED
+ LTEXT "&Password:",IDC_STATIC2,17,113,44,12
+ EDITTEXT IDC_EDIT2,92,108,90,16,ES_PASSWORD | ES_AUTOHSCROLL |
+ WS_DISABLED
+ LTEXT "C&onfirm Password:",IDC_STATIC3,17,135,62,12
+ EDITTEXT IDC_EDIT3,92,130,90,16,ES_PASSWORD | ES_AUTOHSCROLL |
+ WS_DISABLED
+ PUSHBUTTON "&Browse...",IDC_BUTTON1,188,87,56,14
+ LTEXT "Which user account do you want to use to run this application?",
+ IDC_STATIC,7,9,227,22
+END
+
+IDD_PROPPAGE4 DIALOG DISCARDABLE 0, 0, 252, 218
+STYLE WS_CHILD | WS_DISABLED | WS_CAPTION
+CAPTION "Default Security"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Default Acc&ess Permissions",IDC_STATIC,5,4,238,65
+ LTEXT "You may edit who is allowed to access applications that do not provide their own settings",
+ IDC_STATIC,14,17,218,17
+ PUSHBUTTON "Edit Default...",IDC_BUTTON1,163,45,70,14
+ GROUPBOX "Default &Launch Permissions",IDC_STATIC,5,75,238,65
+ LTEXT "You may edit who is allowed to launch applications that do not provide their own settings.",
+ IDC_STATIC,14,88,218,18
+ PUSHBUTTON "Edit Default...",IDC_BUTTON2,163,116,70,14
+ GROUPBOX "Default &Configuration Permissions",IDC_STATIC,5,145,
+ 238,65
+ LTEXT "You may edit the list of users that are allowed to modify OLE class configuration information. This includes installing new OLE servers and adjusting the configuration of existing OLE servers.",
+ IDC_STATIC,14,157,218,27
+ PUSHBUTTON "Edit Default...",IDC_BUTTON3,163,187,70,14
+END
+
+IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 252, 209
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Add New Application"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "&Name:",IDC_STATIC,14,19,27,15
+ EDITTEXT IDC_EDIT1,44,17,201,14,ES_AUTOHSCROLL
+ GROUPBOX "Application Location",IDC_STATIC,7,47,238,132
+ CONTROL "Application on &this computer",IDC_RADIO1,"Button",
+ BS_AUTORADIOBUTTON,16,61,166,11
+ CONTROL "Application on &another computer",IDC_RADIO2,"Button",
+ BS_AUTORADIOBUTTON,16,121,141,15
+ LTEXT "Path:",IDC_STATIC,27,77,109,9
+ EDITTEXT IDC_EDIT2,26,87,148,14,ES_AUTOHSCROLL
+ PUSHBUTTON "Browse...",IDC_BUTTON1,180,87,55,14
+ LTEXT "Computer name:",IDC_STATIC,27,138,105,10
+ EDITTEXT IDC_EDIT3,26,149,148,14,ES_AUTOHSCROLL | WS_DISABLED
+ PUSHBUTTON "Browse...",IDC_BUTTON2,180,148,55,14
+ DEFPUSHBUTTON "OK",IDOK,138,187,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,195,187,50,14
+END
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+//VS_VERSION_INFO VERSIONINFO
+// FILEVERSION 1,0,0,1
+// PRODUCTVERSION 1,0,0,1
+// FILEFLAGSMASK 0x3fL
+//#ifdef _DEBUG
+// FILEFLAGS 0x1L
+//#else
+// FILEFLAGS 0x0L
+//#endif
+// FILEOS 0x4L
+// FILETYPE 0x1L
+// FILESUBTYPE 0x0L
+//BEGIN
+// BLOCK "StringFileInfo"
+// BEGIN
+// BLOCK "040904b0"
+// BEGIN
+// VALUE "CompanyName", "\0"
+// VALUE "FileDescription", "OLE Configuration UI\0"
+// VALUE "FileVersion", "1, 0, 0, 1\0"
+// VALUE "InternalName", "OLEUI\0"
+// VALUE "LegalCopyright", "Copyright (c) 1996\0"
+// VALUE "OriginalFilename", "OLEUI.EXE\0"
+// VALUE "ProductName", "OLE Configuration Application\0"
+// VALUE "ProductVersion", "1, 0, 0, 1\0"
+// END
+// END
+// BLOCK "VarFileInfo"
+// BEGIN
+// VALUE "Translation", 0x409, 1200
+// END
+//END
+
+// The following conforms to Windows NT version resources
+#include <winver.h>
+#include <ntverp.h>
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Distributed COM Configuration"
+#define VER_INTERNALNAME_STR "dcomcnfg.exe"
+#define VER_ORIGINALFILENAME_STR "dcomcnfg.exe"
+#include <common.ver>
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_OLECNFG_DIALOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 312
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 259
+ END
+
+ IDD_PROPPAGE1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 245
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 210
+ END
+
+ IDD_PROPPAGE2, DIALOG
+ BEGIN
+ LEFTMARGIN, 8
+ RIGHTMARGIN, 244
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 210
+ END
+
+ IDD_PROPPAGE11, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 245
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 210
+ END
+
+ IDD_PROPPAGE5, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 245
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 210
+ END
+
+ IDD_PROPPAGE21, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 245
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 210
+ END
+
+ IDD_PROPPAGE3, DIALOG
+ BEGIN
+ LEFTMARGIN, 6
+ RIGHTMARGIN, 244
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 210
+ END
+
+ IDD_PROPPAGE4, DIALOG
+ BEGIN
+ LEFTMARGIN, 5
+ RIGHTMARGIN, 249
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 210
+ END
+
+ IDD_DIALOG1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 245
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 201
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE
+BEGIN
+ VK_F1, ID_CONTEXT_HELP, VIRTKEY, SHIFT, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_ABOUTBOX "&About olecnfg..."
+ IDS_PROPSHT_CAPTION "Property Sheet"
+ IDS_PROPSHT_CAPTION1 "Property Sheet"
+ IDS_PSMAIN_TITLE "Distributed COM Configuration"
+ IDS_DEFAULT "Default"
+ IDS_NONE "(None)"
+ IDS_CONNECT "Connect"
+ IDS_CALL "Call"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_PACKET "Packet"
+ IDS_PACKETINTEGRITY "Packet Integrity"
+ IDS_PACKETPRIVACY "Packet Privacy"
+ IDS_ANONYMOUS "Anonymous"
+ IDS_IDENTIFY "Identify"
+ IDS_IMPERSONATE "Impersonate"
+ IDS_DELEGATE "Delegate"
+ IDS_ACCESSDENIED "You have been denied access to some resource."
+ IDS_SYSTEMMESSAGE "DCOM Configuration"
+ IDS_NA "n/a"
+ IDS_SERVERTYPE0 "in-process server"
+ IDS_SERVERTYPE1 "local server"
+ IDS_SERVERTYPE2 "local service"
+ IDS_SERVERTYPE3 "remote server"
+ IDS_SERVERTYPE4 "remote or local server"
+ IDS_SERVERTYPE5 "remote server or local service"
+ IDS_SERVERTYPE6 "DLL surrogate"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_SERVICENAME "Service name:"
+ IDS_PATH "Local path:"
+ IDS_ATSTORAGE "where data is located"
+ IDS_NOMATCH "Password confirmation failed."
+ IDS_INVALIDSERVER "You must specify a valid machine name."
+ IDS_NOACCOUNT "An account for this domain and user could not be found. Check that this user has a valid user account in the specified domain."
+ IDS_ADMINSONLY "Only administrators are permitted to run this tool."
+ IDS_REBOOT "Changes have been applied but will not take effect until this machine is rebooted. Reboot now?"
+ IDS_BLANKUSERNAME "The RunAs user name cannot be blank."
+ IDS_BLANKPASSWORD "The RunAs password cannot be blank."
+ IDS_LocalService "LocalService"
+ IDS__LocalService "_LocalService"
+ IDS_RemoteServerName "RemoteServerName"
+ IDS_ActivateAtStorage "ActivateAtStorage"
+ IDS_RunAs "RunAs"
+ IDS_InteractiveUser "Interactive User"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_AccessPermission "AccessPermission"
+ IDS_LaunchPermission "LaunchPermission"
+ IDS_Y "Y"
+ IDS_LocalServer32 "LocalServer32"
+ IDS__LocalServer32 "_LocalServer32"
+ IDS_LocalServer "LocalServer"
+ IDS__LocalServer "_LocalServer"
+ IDS_CLSID "CLSID"
+ IDS_AppID "AppID"
+ IDS_NULL "NULL"
+ IDS_CLSID_ "The CLSID %1, item %2 and title %3 has the named value AppID, but is not recorded under \\\\HKEY_CLASSES_ROOT\\AppId. Do you wish to record it?"
+ IDS_DCOM_Configuration_Warning "DCOM Configuration Warning"
+ IDS_Access "Access"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_Launch "Launch"
+ IDS_Config "Config"
+ IDS_SOFTWARE_Microsoft_OLE "\\SOFTWARE\\Microsoft\\OLE"
+ IDS_Clsid2 "Clsid"
+ IDS_EnableDCOM "EnableDCOM"
+ IDS_LegacyAuthenticationLevel "LegacyAuthenticationLevel"
+ IDS_LegacyImpersonationLevel "LegacyImpersonationLevel"
+ IDS_LegacySecureReferences "LegacySecureReferences"
+ IDS_DefaultccessPermission "DefaultAccessPermssion"
+ IDS_DefaultLaunchPermission "DefaultLaunchPermission"
+ IDS_HKEY_CLASSES_ROOT "HKEY_CLASSES_ROOT"
+ IDS_Allow_ "Allow "
+ IDS_Deny_ "Deny "
+ IDS_Registry_value "Registry Value"
+ IDS_Browse_for_users "Browse for Users"
+ IDS_SCM_ "SCM:"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_The_security_ "The Security Descriptor contains an Access Control Entry (ACE) inappropriate to this context. If you continue it will be rewritten as an Allow ACE on the appropriate access mask. Do you wish to continue?"
+ IDS_backslash "\\"
+ IDS_Key_Read "Key Read"
+ IDS_Query_Value "Query Value"
+ IDS_Set_Value "Set Value"
+ IDS_Create_Subkey "Create Subkey"
+ IDS_Enumerate_Subkeys "Enumerate Subkeys"
+ IDS_Notify "Notify"
+ IDS_Create_Link "Create Link"
+ IDS_Delete "Delete"
+ IDS_Write_DAC "Write DAC"
+ IDS_Read_Control "Read Control"
+ IDS_Read "Read"
+ IDS_Full_Control "Full Control"
+ IDS_Special_AccessDotDotDot "Special Access..."
+ IDS_Registry_Key "Registry Key"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_Registry_Application "Registry Application"
+ IDS_Write_Owner "Write Owner"
+ IDS_BADSD "Found a Security Descriptor written in an unrecognized format. It will be ignored."
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif
+#include "res\olecnfg.rc2" // non-Microsoft Visual C++ edited resources
+#include "afxres.rc" // Standard components
+#endif
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/private/ole32/oleui/olecnfg.rtf b/private/ole32/oleui/olecnfg.rtf
new file mode 100644
index 000000000..bb55dbe95
--- /dev/null
+++ b/private/ole32/oleui/olecnfg.rtf
@@ -0,0 +1,73 @@
+{\rtf1\ansi \deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;
+\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{\widctlpar
+\f4\fs20 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}{\s15\widctlpar \f4\fs20 \sbasedon0\snext15 footnote text;}{\*\cs16 \additive\super \sbasedon10 footnote reference;}}{\info{\author Bruce Mansfield}{\creatim\yr1996\mo5\dy8\hr10\min55}
+{\version1}{\edmins678}{\nofpages0}{\nofwords0}{\nofchars0}{\vern49221}}\widowctrl\ftnbj\aenddoc\formshade \fet0\sectd \linex0\endnhere {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang
+{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang
+{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain
+\widctlpar \f4\fs20 {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_PROPPAGE1}} This is the initial property page of the top property sheet.
+\par \pard \widctlpar \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_PROPERTIESBUTTON}} The Properties... button invokes the property sheet for the currently selected application. The property sheet may also be invo
+ked by double clicking on the selected application.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_RUNASBROWSEBTN}} Rather than typing in the name of the user under whose identity this application is to run, this Browse...
+ button maybe used to browse for the approproate user. It may be used to scan for users on this and all connected domains.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_ATBITSCHECK}} This check box determines whether the application
+is to be run where the data for the object being invoked is located. This is commonly known as AtBits activation, because the application is launched on the machine where the bits of the data file are located.
+\par \pard \widctlpar \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_RUNREMOTECK}} Use this check box to force the application to be run on a remote machine. If this is checked then a valid m
+achine name must be entered into the associated edit box just below this check box. This can be done either manually or via the browse button.
+\par \pard \widctlpar \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_EDITDEFAULTACCESSSECURITY}} Default Access Permissions defines those groups and users who are permitted to access COM/DCOM applications runnning
+ on this machine. Using the Edit Default... button invokes the Access Control List Editor through which the user may add/remove/modify those users and groups who may access or are denied access to COM/DCOM applications running on this machine.
+\par \pard \widctlpar \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_SERVERLISTBOX}} This lists the COM servers registered on this machine. A list entry is the title for that server, or its AppID if the title is blank.
+
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_RUNLOCALLYCK}} Check this if the application is to run locally.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_RUNREMOTEEDIT}} Enter the name of the remote machine where the application is to run.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_ENABLEDCOMCK}} In order for Distributed COM to be enabled on this machine this box must be checked. If it is not checked then remote clients may not activate DCOM
+servers on this machine.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_REFTRACKING}} Check this box if additional security for reference tracking in legacy applications is desired. . This capability means DCOM will prevent malicous user
+s from releasing objects. However, it is quite expensive. The authentication level cannot be set to (None) if this is checked.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_DEFAULTAUTHLEVEL}} Use this combination box to select the default RPC authentication level for COM/DCOM calls.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_DEFAULTIMPERLEVEL}} Use this combination box to select the default RPC impersonation level for COM/DCOM calls.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_ACCESSPERMISSIONBTN}}
+Use this button to edit the list of users and groups who are either granted access permission to this application or who are denied access permission.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_LAUNCHPERMISSIONBTN}} Use this button to edit the list of users and groups who are either granted launch permission to this application or who are denied launch
+ permission.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_CONFIGURATIONPERMISSIONBTN}} Use this button to edit the list of users and groups who are allowed to read/modify registry configuration information for this applcation.
+ The Security Descriptor built by this edit session will get written to the AppID key for this application as well as each CLSID key, as well as all of its subkeys, for this application.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_DEFAULTACCESSRADIO}} Check this radio button if the list of users/groups allowed to access this application should be determined via the Default Access Permissions
+. If this radio button is not checked, then the user may use the edit button to the right to edit the list of users/groups permitted to access or are denied access to this application.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_DEFAULTLAUNCHRADIO}} Check this radio button if the list of users/groups allowed to launch this application should be determined via the Default Launch Permissions
+. If this radio button is not checked, then the user may use the edit button to the right to edit the list of users/groups permitted to launch or are denied launch of this application.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_DEFAULTCONFIGURATIONRADIO}} Check this radio button if the list of users/groups allowed to read/modify registry information for this application
+ should be determined by the Default Configuraton Permissions. If this radio button is not checked, then the user may use the edit button to the right to edit the list of users/groups permitted to read/modify registry information for this application.
+
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_INTERACTIVEUSERRADIO}} Check this radio button if the application is to run as the interactive user.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_LAUNCHINGUSERRADIO}} Check this radio button if the application is to run with the identify of the client; that is, with the security identity of the launching user.
+
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_RUNASUSERRADIO}} Select this radio button if the application is to be launched with the identity of the user specified below.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_SYSTEMACCOUNTRADIO}} Check this radio button if the application service is to be run as LocalSystem. This is only meaningful for a DCOM application which is
+ to be run as a Windows NT service. If the application is not a service, this radio button is disabled. Note that the application must already be registered in the Service Control Manager database.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_RUNASUSEREDIT}} Enter the domain and account name of the user under whose identity this application is to run. This should be entered in the form <domain>\\
+<user>. The domain may be any valid domain or the name of this machine. If <domain> is absent then it defaults to this machine.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_RUNASPASSWORDEDIT}} Enter the password of the user under whose identity this application is to run. It is permissible for the password to be blank; howeever, t
+his will work only if the domain account for the user also has a blank password.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_RUNASCONFIRMEDIT}} Re-enter the password of the user under whose identity this application is to run. This edit box is used simply to confirm
+the password. It is a safety feature.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_EDITDEFAULTLAUNCHSECURITY}} Default Launch Permissions defines those groups and users who are permitted to launch
+ COM/DCOM applications supported on this machine. Using the Edit Default... button invokes the Access Control List Editor through which the user may add/remove/modify those users and groups who may launch or are denied launch of COM/DCOM applications on
+ this machine.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_EDITDEFAULTCONFIGURATIONSECURITY}} Default Configuration Permissions defines those groups and users who are permitted to read/modify registry configuraton
+information for COM/DCM applications. Using the Edit Default... button invokes the Access Control List Editor through which the user may define which users and groups have what access to COM/DCOM registry information.
+ The Security Descriptor returned by the ACL editor is written to HKEY_CLASSES_ROOT and all of its subkeys.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_TERMINATEBTN}} Use this button to terminate the selected application in the above list box.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_STARTBTN}} Use this button to (re)start the selected service in the above list box.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_PAUSEBTN}} Use this button to pause the selected service in the above list box.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_REMOTEMACHINE}} If the application is to be run on a remote machine, this is the name of that remote machine.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_SERVERNAME}} The name of this application. This is the same as the unnamed value in the registry on the AppID key for this application.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_SERVERPATH}} This is the executable file path for this application.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_SERVERTYPE}} This is the type of this application. This will be either \ldblquote local server, \ldblquote local service\rdblquote or \ldblquote remote server
+\rdblquote .
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_RUNNINGINSTANCES}} This is a list of the instances of this application (server or service) currently running on this machine.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_EDITACCESSRADIO}} Enable this radio button in order to edit the access permissions for this application. Otherwise the Default Access Permissions will be used.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_EDITLAUNCHRADIO}} Enable this radio button in order to edit the launch permissions for this application. Otherwise the Default Launch Permissions will be used.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_EDITCONFIGURATIONRADIO}} Enable this radio button in order to edit the configuration permissions for this application. Otherwise the Default Configuration P
+ermissions will be used.
+\par \page {\cs16\super #{\footnote \pard\plain \s15\widctlpar \f4\fs20 {\cs16\super #} IDH_REMOTEBROWSEBTN}} You may use this button to browse for the name of the desired remote machine rather than typing it in.
+\par } \ No newline at end of file
diff --git a/private/ole32/oleui/oleui.cpp b/private/ole32/oleui/oleui.cpp
new file mode 100644
index 000000000..62ee92e2f
--- /dev/null
+++ b/private/ole32/oleui/oleui.cpp
@@ -0,0 +1,6 @@
+// olecnfg.cpp : Defines the class behaviors for the application.
+//
+
+#include "stdafx.h"
+
+#include "olecnfg.cpp"
diff --git a/private/ole32/oleui/oleui.rc b/private/ole32/oleui/oleui.rc
new file mode 100644
index 000000000..3419aa99d
--- /dev/null
+++ b/private/ole32/oleui/oleui.rc
@@ -0,0 +1,4 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "olecnfg.rc"
+
diff --git a/private/ole32/oleui/res/olecnfg.ico b/private/ole32/oleui/res/olecnfg.ico
new file mode 100644
index 000000000..7eef0bcbe
--- /dev/null
+++ b/private/ole32/oleui/res/olecnfg.ico
Binary files differ
diff --git a/private/ole32/oleui/res/olecnfg.rc2 b/private/ole32/oleui/res/olecnfg.rc2
new file mode 100644
index 000000000..7148c47fe
--- /dev/null
+++ b/private/ole32/oleui/res/olecnfg.rc2
@@ -0,0 +1,13 @@
+//
+// OLECNFG.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+ #error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/private/ole32/oleui/resource.h b/private/ole32/oleui/resource.h
new file mode 100644
index 000000000..617b1c74a
--- /dev/null
+++ b/private/ole32/oleui/resource.h
@@ -0,0 +1,154 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by olecnfg.rc
+//
+#define IDS_ABOUTBOX 101
+#define IDD_OLECNFG_DIALOG 102
+#define IDS_PROPSHT_CAPTION 103
+#define IDD_PROPPAGE1 104
+#define IDD_PROPPAGE2 105
+#define IDS_PROPSHT_CAPTION1 106
+#define IDD_PROPPAGE11 107
+#define IDS_PSMAIN_TITLE 107
+#define IDD_PROPPAGE21 108
+#define IDS_DEFAULT 108
+#define IDD_PROPPAGE3 109
+#define IDS_NONE 109
+#define IDD_PROPPAGE4 110
+#define IDS_CONNECT 110
+#define IDD_PROPPAGE5 111
+#define IDS_CALL 111
+#define IDS_PACKET 112
+#define IDS_PACKETINTEGRITY 113
+#define IDS_PACKETPRIVACY 114
+#define IDS_ANONYMOUS 115
+#define IDS_IDENTIFY 116
+#define IDS_IMPERSONATE 117
+#define IDS_DELEGATE 118
+#define IDS_ACCESSDENIED 119
+#define IDS_SYSTEMMESSAGE 120
+#define IDS_NA 121
+#define IDS_SERVERTYPE0 122
+#define IDS_SERVERTYPE1 123
+#define IDS_SERVERTYPE2 124
+#define IDS_SERVERTYPE3 125
+#define IDS_SERVERTYPE4 126
+#define IDS_SERVERTYPE5 127
+#define IDS_SERVERTYPE6 128
+#define IDR_MAINFRAME 129
+#define IDS_SERVICENAME 129
+#define IDD_DIALOG1 130
+#define IDS_PATH 130
+#define IDS_ATSTORAGE 131
+#define IDR_ACCELERATOR1 131
+#define IDS_NOMATCH 132
+#define IDS_INVALIDSERVER 133
+#define IDI_ICON1 133
+#define IDS_NOLOGON 134
+#define IDS_NOACCOUNT 134
+#define IDS_ADMINSONLY 135
+#define IDS_REBOOT 136
+#define IDS_BLANKUSERNAME 137
+#define IDS_BLANKPASSWORD 138
+#define IDS_LocalService 139
+#define IDS__LocalService 140
+#define IDS_RemoteServerName 141
+#define IDS_ActivateAtStorage 142
+#define IDS_RunAs 143
+#define IDS_InteractiveUser 144
+#define IDS_AccessPermission 145
+#define IDS_LaunchPermission 146
+#define IDS_Y 147
+#define IDS_LocalServer32 148
+#define IDS__LocalServer32 149
+#define IDS_LocalServer 150
+#define IDS__LocalServer 151
+#define IDS_CLSID 152
+#define IDS_AppID 153
+#define IDS_NULL 154
+#define IDS_The_CLSID_ 155
+#define IDS__item_ 156
+#define IDS_comma_and_title_ 157
+#define IDS__has_the_ 158
+#define IDS_CLSID_ 158
+#define IDS_DCOM_Configuration_Warning 159
+#define IDS_Access 160
+#define IDS_Launch 161
+#define IDS_Config 162
+#define IDS_SOFTWARE_Microsoft_OLE 163
+#define IDS_Clsid2 164
+#define IDS_EnableDCOM 165
+#define IDS_LegacyAuthenticationLevel 166
+#define IDS_LegacyImpersonationLevel 167
+#define IDS_LegacySecureReferences 168
+#define IDS_DefaultccessPermission 169
+#define IDS_DefaultLaunchPermission 170
+#define IDS_HKEY_CLASSES_ROOT 171
+#define IDS_Allow_ 172
+#define IDS_Deny 173
+#define IDS_Deny_ 173
+#define IDS_Registry_value 174
+#define IDS_Browse_for_users 175
+#define IDS_SCM_ 176
+#define IDS_The_security_ 177
+#define IDS_backslash 178
+#define IDS_Key_Read 179
+#define IDS_Query_Value 180
+#define IDS_Set_Value 181
+#define IDS_Create_Subkey 182
+#define IDS_Enumerate_Subkeys 183
+#define IDS_Notify 184
+#define IDS_Create_Link 185
+#define IDS_Delete 186
+#define IDS_Write_DAC 187
+#define IDS_Read_Control 188
+#define IDS_Read 189
+#define IDS_Full_Control 190
+#define IDS_Special_AccessDotDotDot 191
+#define IDS_Registry_Key 192
+#define IDS_Registry_Application 193
+#define IDS_Write_Owner 194
+#define IDS_BADSD 195
+#define IDC_BUTTON1 1000
+#define IDC_LIST1 1003
+#define IDC_RADIO1 1004
+#define IDC_RADIO2 1005
+#define IDC_CHECK1 1006
+#define IDC_CHECK2 1007
+#define IDC_CHECK3 1008
+#define IDC_BUTTON2 1009
+#define IDC_EDIT1 1010
+#define IDC_BUTTON3 1011
+#define IDC_RADIO3 1015
+#define IDC_LIST2 1019
+#define IDC_EDIT2 1023
+#define IDC_EDIT3 1024
+#define IDC_COMBO1 1025
+#define IDC_COMBO2 1026
+#define IDC_RADIO4 1027
+#define IDC_RADIO5 1032
+#define IDC_RADIO6 1033
+#define IDC_SERVERNAME 1037
+#define IDC_SERVERICON 1038
+#define IDC_SERVERTYPE 1039
+#define IDC_SERVERPATH 1040
+#define IDC_RUNNING 1041
+#define IDC_MACHINE 1042
+#define IDC_PATHTITLE 1043
+#define IDC_MACHINETITLE 1044
+#define IDC_STATIC1 1045
+#define IDC_STATIC2 1046
+#define IDC_STATIC3 1047
+#define IDC_APPTYPE 1048
+#define IDC_APPNAME 1049
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 133
+#define _APS_NEXT_COMMAND_VALUE 32771
+#define _APS_NEXT_CONTROL_VALUE 1050
+#define _APS_NEXT_SYMED_VALUE 111
+#endif
+#endif
diff --git a/private/ole32/oleui/srvppg.cpp b/private/ole32/oleui/srvppg.cpp
new file mode 100644
index 000000000..ac2c79816
--- /dev/null
+++ b/private/ole32/oleui/srvppg.cpp
@@ -0,0 +1,993 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: srvppg.cpp
+//
+// Contents: Implements the classes CServersPropertyPage,
+// CMachinePropertyPage and CDefaultSecurityPropertyPage to
+// manage the three property pages for top level info
+//
+// Classes:
+//
+// Methods: CServersPropertyPage::CServersPropertyPage
+// CServersPropertyPage::~CServersPropertyPage
+// CServersPropertyPage::OnProperties
+// CServersPropertyPage::DoDataExchange
+// CServersPropertyPage::OnServerProperties
+// CServersPropertyPage::OnInitDialog
+// CServersPropertyPage::FetchAndDisplayClasses
+// CServersPropertyPage::OnList1
+// CServersPropertyPage::OnDoubleclickedList1
+// CServersPropertyPage::OnButton2
+// CMachinePropertyPage::CMachinePropertyPage
+// CMachinePropertyPage::~CMachinePropertyPage
+// CMachinePropertyPage::DoDataExchange
+// CMachinePropertyPage::OnInitDialog
+// CMachinePropertyPage::OnCombo1
+// CMachinePropertyPage::OnCheck1
+// CMachinePropertyPage::OnCheck2
+// CMachinePropertyPage::OnEditchangeCombo1
+// CMachinePropertyPage::OnSelchangeCombo1
+// CMachinePropertyPage::OnEditchangeCombo2
+// CMachinePropertyPage::OnSelchangeCombo2
+// CDefaultSecurityPropertyPage::CDefaultSecurityPropertyPage
+// CDefaultSecurityPropertyPage::~CDefaultSecurityPropertyPage
+// CDefaultSecurityPropertyPage::DoDataExchange
+// CDefaultSecurityPropertyPage::OnInitDialog
+// CDefaultSecurityPropertyPage::OnButton1
+// CDefaultSecurityPropertyPage::OnButton2
+// CDefaultSecurityPropertyPage::OnButton3
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+#include "stdafx.h"
+#include "afxtempl.h"
+#include "assert.h"
+#include "resource.h"
+#include "CStrings.h"
+#include "CReg.h"
+#include "types.h"
+#include "SrvPPg.h"
+#include "ClsPSht.h"
+#include "newsrvr.h"
+#include "datapkt.h"
+extern "C"
+{
+#include <getuser.h>
+}
+#include "util.h"
+#include "virtreg.h"
+
+
+
+
+
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char BASED_CODE THIS_FILE[] = __FILE__;
+#endif
+
+IMPLEMENT_DYNCREATE(CDefaultSecurityPropertyPage, CPropertyPage)
+IMPLEMENT_DYNCREATE(CServersPropertyPage, CPropertyPage)
+IMPLEMENT_DYNCREATE(CMachinePropertyPage, CPropertyPage)
+
+
+// The globals used for communicating arguments between dialog classes
+CUtility g_util;
+CVirtualRegistry g_virtreg;
+HKEY g_hAppid;
+HKEY *g_rghkCLSID;
+unsigned g_cCLSIDs;
+TCHAR *g_szAppTitle;
+BOOL g_fReboot = FALSE;
+TCHAR *g_szAppid;
+
+/////////////////////////////////////////////////////////////////////////////
+// CServersPropertyPage property page
+
+CServersPropertyPage::CServersPropertyPage() : CPropertyPage(CServersPropertyPage::IDD)
+{
+ //{{AFX_DATA_INIT(CServersPropertyPage)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+
+ m_fApplications = TRUE;
+}
+
+CServersPropertyPage::~CServersPropertyPage()
+{
+}
+
+void CServersPropertyPage::OnProperties()
+{
+ CClsidPropertySheet propSheet;
+ SItem *pItem;
+ HKEY hKey;
+ HKEY *phClsids;
+ TCHAR szBuf[128];
+
+ // Get the selected item
+ pItem = m_registry.GetItem(m_classesLst.GetItemData(m_dwSelection));
+
+ // Save the AppID
+ g_szAppid = pItem->szAppid;
+
+ // Open the appid key
+ _tcscpy(szBuf, TEXT("AppId\\"));
+ _tcscat(szBuf, pItem->szAppid);
+ if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szBuf, 0, KEY_ALL_ACCESS, &hKey)
+ != ERROR_SUCCESS)
+ {
+ g_util.PostErrorMessage();
+ return;
+ }
+
+ // Open a key for each clsid associated with this appid
+ phClsids = new HKEY[pItem->ulClsids];
+ if (phClsids == NULL)
+ {
+ g_util.PostErrorMessage();
+ return;
+ }
+ for (UINT ul = 0; ul < pItem->ulClsids; ul++)
+ {
+ _tcscpy(szBuf, TEXT("ClsId\\"));
+ _tcscat(szBuf, pItem->ppszClsids[ul]);
+ if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szBuf, 0, KEY_ALL_ACCESS,
+ &phClsids[ul])
+ != ERROR_SUCCESS)
+ {
+ g_util.PostErrorMessage();
+ RegCloseKey(hKey);
+ for (UINT ul2 = 0; ul2 < ul; ul2++)
+ {
+ RegCloseKey(phClsids[ul2]);
+ }
+ delete phClsids;
+ return;
+ }
+
+ }
+
+ if (propSheet.InitData(m_szSelection, hKey, phClsids, pItem->ulClsids))
+ {
+ propSheet.DoModal();
+ }
+
+ // This is where you would retrieve information from the property
+ // sheet if propSheet.DoModal() returned IDOK. We aren't doing
+ // anything for simplicity.
+
+ // Close the registry keys we opened for the ClsidPropertySheet
+ RegCloseKey(hKey);
+ for (ul = 0; ul < pItem->ulClsids; ul++)
+ {
+ RegCloseKey(phClsids[ul]);
+ }
+ delete phClsids;
+}
+
+
+void CServersPropertyPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CServersPropertyPage)
+ DDX_Control(pDX, IDC_LIST1, m_classesLst);
+ //}}AFX_DATA_MAP
+
+ GotoDlgCtrl(GetDlgItem(IDC_BUTTON1));
+}
+
+
+BEGIN_MESSAGE_MAP(CServersPropertyPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CServersPropertyPage)
+ ON_BN_CLICKED(IDC_BUTTON1, OnServerProperties)
+ ON_LBN_SELCHANGE(IDC_LIST1, OnList1)
+ ON_LBN_DBLCLK(IDC_LIST1, OnDoubleclickedList1)
+ ON_BN_CLICKED(IDC_BUTTON2,OnButton2)
+ ON_WM_HELPINFO()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+
+
+void CServersPropertyPage::OnServerProperties()
+{
+ m_dwSelection = m_classesLst.GetCurSel();
+ m_classesLst.GetText(m_dwSelection, m_szSelection);
+ OnProperties();
+
+}
+
+BOOL CServersPropertyPage::OnInitDialog()
+{
+ // Disable property sheet help button
+// m_psp.dwFlags &= ~PSH_HASHELP;
+
+ CPropertyPage::OnInitDialog();
+
+ // Fetch and display the servers for the types specified
+ FetchAndDisplayClasses();
+
+
+ GotoDlgCtrl(GetDlgItem(IDC_BUTTON1));
+
+ // Invoke the work-around to fix WM_HELP problem on subclassed controls
+ g_util.FixHelp(this);
+
+ return FALSE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+
+void CServersPropertyPage::FetchAndDisplayClasses(void)
+{
+ // Collect applications
+ m_registry.Init();
+
+ // Clear the list box
+ m_classesLst.ResetContent();
+
+ // Store application names in the list box
+ SItem *pItem;
+
+ while (pItem = m_registry.GetNextItem())
+ {
+ if (!pItem->fDontDisplay)
+ {
+ if (pItem->szTitle)
+ {
+ m_classesLst.AddString(pItem->szTitle);
+ }
+ else if (pItem->szItem)
+ {
+ m_classesLst.AddString(pItem->szItem);
+ }
+ else
+ {
+ m_classesLst.AddString(pItem->szAppid);
+ }
+ }
+ }
+
+ // The list box sorted the items during the AddString's, so now we
+ // have to associate each item with its index in CRegistry
+ DWORD cbItems = m_registry.GetNumItems();
+
+ for (DWORD k = 0; k < cbItems; k++)
+ {
+ SItem *pItem = m_registry.GetItem(k);
+ int iLBItem;
+
+ if (!pItem->fDontDisplay)
+ {
+ if (pItem->szTitle)
+ {
+ iLBItem = m_classesLst.FindStringExact(-1, pItem->szTitle);
+ }
+ else if (pItem->szItem)
+ {
+ iLBItem = m_classesLst.FindStringExact(-1, pItem->szItem);
+ }
+ else
+ {
+ iLBItem = m_classesLst.FindStringExact(-1, pItem->szAppid);
+ }
+ m_classesLst.SetItemData(iLBItem, k);
+ }
+ }
+
+
+ // Select the first item
+ m_classesLst.SetCurSel(0);
+
+ OnList1();
+
+}
+
+
+
+void CServersPropertyPage::OnList1()
+{
+ m_dwSelection = m_classesLst.GetCurSel();
+ // enable or disable the properties button as necessary
+ GetDlgItem(IDC_BUTTON1)->EnableWindow(m_dwSelection != LB_ERR);
+ m_classesLst.GetText(m_dwSelection, m_szSelection);
+ GotoDlgCtrl(GetDlgItem(IDC_BUTTON1));
+}
+
+void CServersPropertyPage::OnDoubleclickedList1()
+{
+ m_dwSelection = m_classesLst.GetCurSel();
+ m_classesLst.GetText(m_dwSelection, m_szSelection);
+ OnProperties();
+}
+
+void CServersPropertyPage::OnButton2()
+{
+ CNewServer newServerDialog;
+
+ newServerDialog.DoModal();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CMachinePropertyPage property page
+
+CMachinePropertyPage::CMachinePropertyPage() : CPropertyPage(CMachinePropertyPage::IDD)
+{
+ //{{AFX_DATA_INIT(CMachinePropertyPage)
+ //}}AFX_DATA_INIT
+
+ m_fEnableDCOM = FALSE;
+ m_fEnableDCOMIndex = -1;
+ m_authLevel = Connect;
+ m_authLevelIndex = -1;
+ m_impersonateLevel = Identify;
+ m_impersonateLevelIndex = -1;
+ m_fLegacySecureReferences = FALSE;
+ m_fLegacySecureReferencesIndex = -1;
+}
+
+
+
+CMachinePropertyPage::~CMachinePropertyPage()
+{
+}
+
+
+
+void CMachinePropertyPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CMachinePropertyPage)
+ DDX_Control(pDX, IDC_CHECK2, m_legacySecureReferencesChk);
+ DDX_Control(pDX, IDC_CHECK1, m_EnableDCOMChk);
+ DDX_Control(pDX, IDC_COMBO2, m_impersonateLevelCBox);
+ DDX_Control(pDX, IDC_COMBO1, m_authLevelCBox);
+ //}}AFX_DATA_MAP
+}
+
+
+
+
+BEGIN_MESSAGE_MAP(CMachinePropertyPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CMachinePropertyPage)
+ ON_BN_CLICKED(IDC_COMBO1, OnCombo1)
+ ON_BN_CLICKED(IDC_CHECK1, OnCheck1)
+ ON_BN_CLICKED(IDC_CHECK2, OnCheck2)
+ ON_CBN_EDITCHANGE(IDC_COMBO1, OnEditchangeCombo1)
+ ON_CBN_EDITCHANGE(IDC_COMBO2, OnEditchangeCombo2)
+ ON_CBN_SELCHANGE(IDC_COMBO1, OnSelchangeCombo1)
+ ON_CBN_SELCHANGE(IDC_COMBO2, OnSelchangeCombo2)
+ ON_WM_HELPINFO()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+
+
+BOOL CMachinePropertyPage::OnInitDialog()
+{
+ int iIndex;
+
+ // Disable property sheet help button
+// m_psp.dwFlags &= ~PSH_HASHELP;
+
+ CPropertyPage::OnInitDialog();
+
+ // Populate the authentication combo boxe
+ CString sTemp;
+
+ m_authLevelCBox.ResetContent();
+
+ sTemp.LoadString(IDS_DEFAULT);
+ m_authLevelCBox.AddString(sTemp);
+
+ sTemp.LoadString(IDS_NONE);
+ m_authLevelCBox.AddString(sTemp);
+
+ sTemp.LoadString(IDS_CONNECT);
+ m_authLevelCBox.AddString(sTemp);
+
+ sTemp.LoadString(IDS_CALL);
+ m_authLevelCBox.AddString(sTemp);
+
+ sTemp.LoadString(IDS_PACKET);
+ m_authLevelCBox.AddString(sTemp);
+
+ sTemp.LoadString(IDS_PACKETINTEGRITY);
+ m_authLevelCBox.AddString(sTemp);
+
+ sTemp.LoadString(IDS_PACKETPRIVACY);
+ m_authLevelCBox.AddString(sTemp);
+
+ // Associate values with entries
+ sTemp.LoadString(IDS_DEFAULT);
+ iIndex = m_authLevelCBox.FindStringExact(-1, LPCTSTR(sTemp));
+ m_authLevelCBox.SetItemData(iIndex, Defaultx);
+
+ sTemp.LoadString(IDS_NONE);
+ iIndex = m_authLevelCBox.FindStringExact(-1, LPCTSTR(sTemp));
+ m_authLevelCBox.SetItemData(iIndex, None);
+
+ sTemp.LoadString(IDS_CONNECT);
+ iIndex = m_authLevelCBox.FindStringExact(-1, LPCTSTR(sTemp));
+ m_authLevelCBox.SetItemData(iIndex, Connect);
+
+ sTemp.LoadString(IDS_CALL);
+ iIndex = m_authLevelCBox.FindStringExact(-1, LPCTSTR(sTemp));
+ m_authLevelCBox.SetItemData(iIndex, Call);
+
+ sTemp.LoadString(IDS_PACKET);
+ iIndex = m_authLevelCBox.FindStringExact(-1, LPCTSTR(sTemp));
+ m_authLevelCBox.SetItemData(iIndex, Packet);
+
+ sTemp.LoadString(IDS_PACKETINTEGRITY);
+ iIndex = m_authLevelCBox.FindStringExact(-1, LPCTSTR(sTemp));
+ m_authLevelCBox.SetItemData(iIndex, PacketIntegrity);
+
+ sTemp.LoadString(IDS_PACKETPRIVACY);
+ iIndex = m_authLevelCBox.FindStringExact(-1, LPCTSTR(sTemp));
+ m_authLevelCBox.SetItemData(iIndex, PacketPrivacy);
+
+
+ // Populate the impersonation level combo box
+ m_impersonateLevelCBox.ResetContent();
+
+ sTemp.LoadString(IDS_ANONYMOUS);
+ m_impersonateLevelCBox.AddString(sTemp);
+
+ sTemp.LoadString(IDS_IDENTIFY);
+ m_impersonateLevelCBox.AddString(sTemp);
+
+ sTemp.LoadString(IDS_IMPERSONATE);
+ m_impersonateLevelCBox.AddString(sTemp);
+
+ sTemp.LoadString(IDS_DELEGATE);
+ m_impersonateLevelCBox.AddString(sTemp);
+
+ // Associate values with entries
+ sTemp.LoadString(IDS_ANONYMOUS);
+ iIndex = m_impersonateLevelCBox.FindStringExact(-1, LPCTSTR(sTemp));
+ m_impersonateLevelCBox.SetItemData(iIndex, Anonymous);
+
+ sTemp.LoadString(IDS_IDENTIFY);
+ iIndex = m_impersonateLevelCBox.FindStringExact(-1, LPCTSTR(sTemp));
+ m_impersonateLevelCBox.SetItemData(iIndex, Identify);
+
+ sTemp.LoadString(IDS_IMPERSONATE);
+ iIndex = m_impersonateLevelCBox.FindStringExact(-1, LPCTSTR(sTemp));
+ m_impersonateLevelCBox.SetItemData(iIndex, Impersonate);
+
+ sTemp.LoadString(IDS_DELEGATE);
+ iIndex = m_impersonateLevelCBox.FindStringExact(-1, LPCTSTR(sTemp));
+ m_impersonateLevelCBox.SetItemData(iIndex, Delegate);
+
+
+ // Set defaults
+ // EnableDCOM is unchecked initially
+ m_authLevelCBox.SetCurSel(Connect);
+ m_impersonateLevelCBox.SetCurSel(Identify);
+
+ // Attempt to read HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLE.EnableDCOM
+ int err;
+
+ err = g_virtreg.ReadRegSzNamedValue(HKEY_LOCAL_MACHINE,
+ TEXT("SOFTWARE\\Microsoft\\OLE"),
+ TEXT("EnableDCOM"),
+ &m_fEnableDCOMIndex);
+ if (err == ERROR_SUCCESS)
+ {
+ CDataPacket &cdp = g_virtreg.GetAt(m_fEnableDCOMIndex);
+
+
+ if (cdp.pkt.nvsz.szValue[0] == 'y' ||
+ cdp.pkt.nvsz.szValue[0] == 'Y')
+ {
+ m_fEnableDCOM = TRUE;
+ }
+ }
+ else if (err != ERROR_ACCESS_DENIED && err !=
+ ERROR_FILE_NOT_FOUND)
+ {
+ g_util.PostErrorMessage();
+ }
+
+ // Attempt to read HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLE.
+ // LegacyAuthenticationLevel
+ err = g_virtreg.ReadRegDwordNamedValue(HKEY_LOCAL_MACHINE,
+ TEXT("SOFTWARE\\Microsoft\\OLE"),
+ TEXT("LegacyAuthenticationLevel"),
+ &m_authLevelIndex);
+ if (err == ERROR_SUCCESS)
+ {
+ CDataPacket &cdp = g_virtreg.GetAt(m_authLevelIndex);
+
+ m_authLevel = (AUTHENTICATIONLEVEL) cdp.pkt.nvdw.dwValue;
+ }
+ else if (err != ERROR_ACCESS_DENIED && err !=
+ ERROR_FILE_NOT_FOUND)
+ {
+ g_util.PostErrorMessage();
+ }
+
+ // Attempt to read HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLE.
+ // LegacyImpersonationLevel
+ err = g_virtreg.ReadRegDwordNamedValue(HKEY_LOCAL_MACHINE,
+ TEXT("SOFTWARE\\Microsoft\\OLE"),
+ TEXT("LegacyImpersonationLevel"),
+ &m_impersonateLevelIndex);
+ if (err == ERROR_SUCCESS)
+ {
+ CDataPacket &cdp = g_virtreg.GetAt(m_impersonateLevelIndex);
+
+ m_impersonateLevel = (IMPERSONATIONLEVEL) cdp.pkt.nvdw.dwValue;
+ }
+ else if (err != ERROR_ACCESS_DENIED && err !=
+ ERROR_FILE_NOT_FOUND)
+ {
+ g_util.PostErrorMessage();
+ }
+
+ // Attempt to read HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLE.
+ // LegacySecureReferences
+ err = g_virtreg.ReadRegSzNamedValue(HKEY_LOCAL_MACHINE,
+ TEXT("SOFTWARE\\Microsoft\\OLE"),
+ TEXT("LegacySecureReferences"),
+ &m_fLegacySecureReferencesIndex );
+ if (err == ERROR_SUCCESS)
+ {
+ CDataPacket &cdp = g_virtreg.GetAt(m_fLegacySecureReferencesIndex);
+
+ if (cdp.pkt.nvsz.szValue[0] == _T('y') ||
+ cdp.pkt.nvsz.szValue[0] == _T('Y'))
+ {
+ m_fLegacySecureReferences = TRUE;
+ }
+ }
+ else if (err != ERROR_ACCESS_DENIED && err !=
+ ERROR_FILE_NOT_FOUND)
+ {
+ g_util.PostErrorMessage();
+ }
+
+
+ // Set the controls according to the current values
+
+ // EnableDCOM
+ if (m_fEnableDCOM)
+ {
+ m_EnableDCOMChk.SetCheck(1);
+ GetDlgItem(IDC_COMBO1)->EnableWindow(TRUE);
+ GetDlgItem(IDC_COMBO2)->EnableWindow(TRUE);
+ GetDlgItem(IDC_CHECK2)->EnableWindow(TRUE);
+ }
+ else
+ {
+ m_EnableDCOMChk.SetCheck(0);
+ }
+
+ // AuthenticationLevel
+ for (int k = 0; k < m_authLevelCBox.GetCount(); k++)
+ {
+ if (((AUTHENTICATIONLEVEL) m_authLevelCBox.GetItemData(k)) ==
+ m_authLevel)
+ {
+ m_authLevelCBox.SetCurSel(k);
+ break;
+ }
+ }
+
+ // ImpersonationLevel
+ for (k = 0; k < m_impersonateLevelCBox.GetCount(); k++)
+ {
+ if (((AUTHENTICATIONLEVEL) m_impersonateLevelCBox.GetItemData(k)) ==
+ m_impersonateLevel)
+ {
+ m_impersonateLevelCBox.SetCurSel(k);
+ break;
+ }
+ }
+
+ // LegacySecureReferences
+ if (m_fLegacySecureReferences)
+ {
+ m_legacySecureReferencesChk.SetCheck(1);
+ }
+ else
+ {
+ m_legacySecureReferencesChk.SetCheck(0);
+ }
+
+ // Invoke the work-around to fix WM_HELP problem on subclassed controls
+ g_util.FixHelp(this);
+
+ return TRUE; // return TRUE unless you set the focus to a control
+ // EXCEPTION: OCX Property Pages should return FALSE
+}
+
+
+
+
+void CMachinePropertyPage::OnCombo1()
+{
+ m_authLevelCBox.ShowDropDown(TRUE);
+
+}
+
+
+
+void CMachinePropertyPage::OnCheck1()
+{
+ // Flip the EnableDCOM flag
+ m_fEnableDCOM ^= 1;
+
+ // Disable or enable the other dialog controls:
+ GetDlgItem(IDC_COMBO1)->EnableWindow(m_fEnableDCOM);
+ GetDlgItem(IDC_COMBO2)->EnableWindow(m_fEnableDCOM);
+ GetDlgItem(IDC_CHECK2)->EnableWindow(m_fEnableDCOM);
+
+ // Virtually write it to the registry
+ if (m_fEnableDCOMIndex == -1)
+ {
+ g_virtreg.NewRegSzNamedValue(HKEY_LOCAL_MACHINE,
+ TEXT("SOFTWARE\\Microsoft\\OLE"),
+ TEXT("EnableDCOM"),
+ m_fEnableDCOM ? _T("Y") : _T("N"),
+ &m_fEnableDCOMIndex);
+ }
+
+ // Else simply update it in the virtual registry
+ else
+ {
+ g_virtreg.ChgRegSzNamedValue(m_fEnableDCOMIndex,
+ m_fEnableDCOM ? _T("Y") : _T("N"));
+ }
+
+ // This is a reboot event
+ g_fReboot = TRUE;
+
+ // Enable the Apply button
+ SetModified(TRUE);
+}
+
+
+
+void CMachinePropertyPage::OnCheck2()
+{
+
+ // Flip LegacySecureeferences flag
+ m_fLegacySecureReferences ^= 1;
+
+ // Virtually write it to the registry
+ if (m_fLegacySecureReferencesIndex == -1)
+ {
+ g_virtreg.NewRegSzNamedValue(HKEY_LOCAL_MACHINE,
+ TEXT("SOFTWARE\\Microsoft\\OLE"),
+ TEXT("LegacySecureReferences"),
+ m_fLegacySecureReferences ? _T("Y")
+ : _T("N"),
+ &m_fLegacySecureReferencesIndex);
+ }
+
+ // Else simply update it in the virtual registry
+ else
+ {
+ g_virtreg.ChgRegSzNamedValue(m_fLegacySecureReferencesIndex,
+ m_fLegacySecureReferences ? _T("Y") : _T("N"));
+ }
+
+ // This is a reboot event
+ g_fReboot = TRUE;
+
+ // Enable the Apply button
+ SetModified(TRUE);
+}
+
+
+
+void CMachinePropertyPage::OnEditchangeCombo1()
+{
+}
+
+
+void CMachinePropertyPage::OnSelchangeCombo1()
+{
+ int iSel;
+
+ // Get the new selection
+ iSel = m_authLevelCBox.GetCurSel();
+ m_authLevel = (AUTHENTICATIONLEVEL) m_authLevelCBox.GetItemData(iSel);
+
+ // Virtually write it to the registry
+ if (m_authLevelIndex == -1)
+ {
+ g_virtreg.NewRegDwordNamedValue(HKEY_LOCAL_MACHINE,
+ TEXT("SOFTWARE\\Microsoft\\OLE"),
+ TEXT("LegacyAuthenticationLevel"),
+ m_authLevel,
+ &m_authLevelIndex);
+ }
+ else
+ {
+ g_virtreg.ChgRegDwordNamedValue(m_authLevelIndex,
+ m_authLevel);
+ }
+
+ // This is a reboot event
+ g_fReboot = TRUE;
+
+ // Enable the Apply button
+ SetModified(TRUE);
+
+}
+
+
+
+void CMachinePropertyPage::OnEditchangeCombo2()
+{
+}
+
+
+
+
+
+void CMachinePropertyPage::OnSelchangeCombo2()
+{
+ int iSel;
+
+ // Get the new selection
+ iSel = m_impersonateLevelCBox.GetCurSel();
+ m_impersonateLevel =
+ (IMPERSONATIONLEVEL) m_impersonateLevelCBox.GetItemData(iSel);
+
+ // Virtually write it to the registry
+ if (m_impersonateLevelIndex == -1)
+ {
+ g_virtreg.NewRegDwordNamedValue(HKEY_LOCAL_MACHINE,
+ TEXT("SOFTWARE\\Microsoft\\OLE"),
+ TEXT("LegacyImpersonationLevel"),
+ m_impersonateLevel,
+ &m_impersonateLevelIndex);
+ }
+ else
+ {
+ g_virtreg.ChgRegDwordNamedValue(m_impersonateLevelIndex,
+ m_impersonateLevel);
+ }
+
+ // This is a reboot event
+ g_fReboot = TRUE;
+
+ // Enable the Apply button
+ SetModified(TRUE);
+}
+
+
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CDefaultSecurityPropertyPage property page
+
+CDefaultSecurityPropertyPage::CDefaultSecurityPropertyPage() : CPropertyPage(CDefaultSecurityPropertyPage::IDD)
+{
+ //{{AFX_DATA_INIT(CDefaultSecurityPropertyPage)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+
+ m_accessPermissionIndex = -1;
+ m_launchPermissionIndex = -1;
+ m_configurationPermissionIndex = -1;
+ m_fAccessChecked = FALSE;
+}
+
+
+
+CDefaultSecurityPropertyPage::~CDefaultSecurityPropertyPage()
+{
+}
+
+
+
+void CDefaultSecurityPropertyPage::DoDataExchange(CDataExchange* pDX)
+{
+ CPropertyPage::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CDefaultSecurityPropertyPage)
+ // NOTE: the ClassWizard will add DDX and DDV calls here
+ //}}AFX_DATA_MAP
+}
+
+
+BEGIN_MESSAGE_MAP(CDefaultSecurityPropertyPage, CPropertyPage)
+ //{{AFX_MSG_MAP(CDefaultSecurityPropertyPage)
+ ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
+ ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
+ ON_BN_CLICKED(IDC_BUTTON3, OnButton3)
+ ON_WM_HELPINFO()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+
+
+// Default access permissions
+BOOL CDefaultSecurityPropertyPage::OnInitDialog(void)
+{
+ BOOL fPostMsg = FALSE;
+
+ // Disable property sheet help button
+// m_psp.dwFlags &= ~PSH_HASHELP;
+
+ if (!m_fAccessChecked)
+ {
+
+ // Check whether we are denied access to
+ // HKEY_LOCAL_MACHINE
+ if (!g_util.CkAccessRights(HKEY_LOCAL_MACHINE, NULL))
+ {
+ GetDlgItem(IDC_BUTTON3)->EnableWindow(FALSE);
+ fPostMsg = TRUE;
+ }
+
+ // Post a message to the user
+ if (fPostMsg)
+ {
+ CString sMsg;
+ CString sCaption;
+
+ sMsg.LoadString(IDS_ACCESSDENIED);
+ sCaption.LoadString(IDS_SYSTEMMESSAGE);
+ MessageBox(sMsg, sCaption, MB_OK);
+ }
+ }
+
+ m_fAccessChecked = TRUE;
+ return TRUE;
+}
+
+
+
+// Default access permissions
+void CDefaultSecurityPropertyPage::OnButton1()
+{
+ int err;
+ CString szAccess;
+
+ szAccess.LoadString(IDS_Access);
+
+ // Invoke the ACL editor
+ err = g_util.ACLEditor(m_hWnd,
+ HKEY_LOCAL_MACHINE,
+ TEXT("SOFTWARE\\Microsoft\\OLE"),
+ TEXT("DefaultAccessPermission"),
+ &m_accessPermissionIndex,
+ SingleACL,
+ (TCHAR *) ((LPCTSTR) szAccess));
+
+ // Enable the Apply button
+ if (err == ERROR_SUCCESS)
+ {
+ // This is a reboot event
+ g_fReboot = TRUE;
+
+ SetModified(TRUE);
+ }
+}
+
+
+// Default launch permissions
+void CDefaultSecurityPropertyPage::OnButton2()
+{
+ int err;
+ CString szLaunch;
+
+ szLaunch.LoadString(IDS_Launch);
+
+ // Invoke the ACL editor
+ err = g_util.ACLEditor(m_hWnd,
+ HKEY_LOCAL_MACHINE,
+ TEXT("SOFTWARE\\Microsoft\\OLE"),
+ TEXT("DefaultLaunchPermission"),
+ &m_launchPermissionIndex,
+ SingleACL,
+ (TCHAR *) ((LPCTSTR) szLaunch));
+
+ // Enable the Apply button
+ if (err == ERROR_SUCCESS)
+ {
+ // This is a reboot event
+ g_fReboot = TRUE;
+
+ SetModified(TRUE);
+ }
+
+}
+
+
+// Default configuration permissions
+void CDefaultSecurityPropertyPage::OnButton3()
+{
+ int err;
+
+ err = g_util.ACLEditor2(m_hWnd,
+ HKEY_CLASSES_ROOT,
+ NULL,
+ 0,
+ NULL,
+ &m_configurationPermissionIndex,
+ RegKeyACL);
+
+ // Enable the Apply button
+ if (err == ERROR_SUCCESS)
+ {
+ SetModified(TRUE);
+ }
+}
+
+BOOL CDefaultSecurityPropertyPage::OnHelpInfo(HELPINFO* pHelpInfo)
+{
+ if(-1 != pHelpInfo->iCtrlId)
+ {
+ WORD hiWord = 0x8000 | CDefaultSecurityPropertyPage::IDD;
+ WORD loWord = pHelpInfo->iCtrlId;
+ DWORD dwLong = MAKELONG(loWord,hiWord);
+
+ WinHelp(dwLong, HELP_CONTEXTPOPUP);
+ return TRUE;
+ }
+
+ else
+ {
+ return CPropertyPage::OnHelpInfo(pHelpInfo);
+ }
+
+ return CPropertyPage::OnHelpInfo(pHelpInfo);
+}
+
+
+
+BOOL CMachinePropertyPage::OnHelpInfo(HELPINFO* pHelpInfo)
+{
+ if(-1 != pHelpInfo->iCtrlId)
+ {
+ WORD hiWord = 0x8000 | CMachinePropertyPage::IDD;
+ WORD loWord = pHelpInfo->iCtrlId;
+ DWORD dwLong = MAKELONG(loWord,hiWord);
+
+ WinHelp(dwLong, HELP_CONTEXTPOPUP);
+ return TRUE;
+ }
+
+ else
+ {
+ return CPropertyPage::OnHelpInfo(pHelpInfo);
+ }
+}
+
+
+
+BOOL CServersPropertyPage::OnHelpInfo(HELPINFO* pHelpInfo)
+{
+ if(-1 != pHelpInfo->iCtrlId)
+ {
+ WORD hiWord = 0x8000 | CServersPropertyPage::IDD;
+ WORD loWord = pHelpInfo->iCtrlId;
+ DWORD dwLong = MAKELONG(loWord,hiWord);
+
+ WinHelp(dwLong, HELP_CONTEXTPOPUP);
+ return TRUE;
+ }
+
+ else
+ {
+ return CPropertyPage::OnHelpInfo(pHelpInfo);
+ }
+}
diff --git a/private/ole32/oleui/srvppg.h b/private/ole32/oleui/srvppg.h
new file mode 100644
index 000000000..5ed4e50e3
--- /dev/null
+++ b/private/ole32/oleui/srvppg.h
@@ -0,0 +1,184 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: srvppg.h
+//
+// Contents: Defines the classes CServersPropertyPage,
+// CMachinePropertyPage and CDefaultSecurityPropertyPage to
+// manage the three property pages for top level info
+//
+// Classes:
+//
+// Methods:
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+#ifndef __SRVPPG_H__
+#define __SRVPPG_H__
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CServersPropertyPage dialog
+
+class CServersPropertyPage : public CPropertyPage
+{
+ DECLARE_DYNCREATE(CServersPropertyPage)
+
+// Construction
+public:
+ CServersPropertyPage();
+ ~CServersPropertyPage();
+void OnProperties();
+void FetchAndDisplayClasses();
+
+
+// Dialog Data
+ //{{AFX_DATA(CServersPropertyPage)
+ enum { IDD = IDD_PROPPAGE1 };
+ CListBox m_classesLst;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generate virtual function overrides
+ //{{AFX_VIRTUAL(CServersPropertyPage)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ virtual BOOL OnInitDialog();
+
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CServersPropertyPage)
+ afx_msg void OnServerProperties();
+ afx_msg void OnList1();
+ afx_msg void OnDoubleclickedList1();
+ afx_msg void OnButton2();
+ afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+private:
+ CRegistry m_registry;
+ BOOL m_fApplications;
+ DWORD m_dwSelection;
+ TCHAR m_szSelection[MAX_PATH];
+
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CMachinePropertyPage dialog
+
+class CMachinePropertyPage : public CPropertyPage
+{
+ DECLARE_DYNCREATE(CMachinePropertyPage)
+
+// Construction
+public:
+ CMachinePropertyPage();
+ ~CMachinePropertyPage();
+
+// Dialog Data
+ //{{AFX_DATA(CMachinePropertyPage)
+ enum { IDD = IDD_PROPPAGE2 };
+ CButton m_legacySecureReferencesChk;
+ CButton m_EnableDCOMChk;
+ CComboBox m_impersonateLevelCBox;
+ CComboBox m_authLevelCBox;
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generate virtual function overrides
+ //{{AFX_VIRTUAL(CMachinePropertyPage)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ virtual BOOL OnInitDialog();
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CMachinePropertyPage)
+ afx_msg void OnCombo1();
+ afx_msg void OnCheck1();
+ afx_msg void OnCheck2();
+ afx_msg void OnEditchangeCombo1();
+ afx_msg void OnEditchangeCombo2();
+ afx_msg void OnSelchangeCombo1();
+ afx_msg void OnSelchangeCombo2();
+ afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+private:
+ AUTHENTICATIONLEVEL m_authLevel;
+ int m_authLevelIndex;
+ IMPERSONATIONLEVEL m_impersonateLevel;
+ int m_impersonateLevelIndex;
+ BOOL m_fEnableDCOM;
+ int m_fEnableDCOMIndex;
+ BOOL m_fLegacySecureReferences;
+ int m_fLegacySecureReferencesIndex;
+
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+// CDefaultSecurityPropertyPage dialog
+
+class CDefaultSecurityPropertyPage : public CPropertyPage
+{
+ DECLARE_DYNCREATE(CDefaultSecurityPropertyPage)
+
+// Construction
+public:
+ CDefaultSecurityPropertyPage();
+ ~CDefaultSecurityPropertyPage();
+
+// Dialog Data
+ //{{AFX_DATA(CDefaultSecurityPropertyPage)
+ enum { IDD = IDD_PROPPAGE4 };
+ // NOTE - ClassWizard will add data members here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_DATA
+
+
+// Overrides
+ // ClassWizard generate virtual function overrides
+ //{{AFX_VIRTUAL(CDefaultSecurityPropertyPage)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ virtual BOOL OnInitDialog();
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ // Generated message map functions
+ //{{AFX_MSG(CDefaultSecurityPropertyPage)
+ afx_msg void OnButton1();
+ afx_msg void OnButton2();
+ afx_msg void OnButton3();
+ afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo);
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+private:
+ int m_accessPermissionIndex;
+ int m_launchPermissionIndex;
+ int m_configurationPermissionIndex;
+ BOOL m_fAccessChecked;
+};
+
+
+
+
+#endif // __SRVPPG_H__
diff --git a/private/ole32/oleui/stdafx.cpp b/private/ole32/oleui/stdafx.cpp
new file mode 100644
index 000000000..d94db1c6a
--- /dev/null
+++ b/private/ole32/oleui/stdafx.cpp
@@ -0,0 +1,7 @@
+// stdafx.cpp : source file that includes just the standard includes
+// olecnfg.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+
+#include "stdafx.h"
+
diff --git a/private/ole32/oleui/stdafx.h b/private/ole32/oleui/stdafx.h
new file mode 100644
index 000000000..260d4507e
--- /dev/null
+++ b/private/ole32/oleui/stdafx.h
@@ -0,0 +1,25 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+//#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+}
+
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows 95 Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+
+
+
diff --git a/private/ole32/oleui/types.h b/private/ole32/oleui/types.h
new file mode 100644
index 000000000..17723f683
--- /dev/null
+++ b/private/ole32/oleui/types.h
@@ -0,0 +1,45 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: types.h
+//
+// Contents: Defines a few generic types
+//
+// Classes:
+//
+// Methods:
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+// Note. These values are derived from rpcdce.h
+typedef enum tagAUTHENTICATIONLEVEL
+ {Defaultx=0, None=1, Connect=2, Call=3, Packet=4, PacketIntegrity=5,
+ PacketPrivacy=6} AUTHENTICATIONLEVEL;
+
+typedef enum tagIMPERSONATIONLEVEL
+ {Anonymous=1, Identify=2, Impersonate=3, Delegate=4} IMPERSONATIONLEVEL;
+
+
+#define GUIDSTR_MAX 38
+
+
+
+// These are help ID's for the "Help" button in the various dialogs
+// in the ACL editor
+#define IDH_REGISTRY_VALUE_PERMISSIONS 1
+#define IDH_ADD_USERS_AND_GROUPS 2
+#define IDH_LOCAL_GROUP_MEMBERSHIP 3
+#define IDH_GLOBAL_GROUP_MEMBERSHIP 4
+#define IDH_FIND_ACCOUNT1 5
+#define IDH_REGISTRY_APPLICATION_PERMISSIONS 6
+#define IDH_REGISTRY_KEY_PERMISSIONS 7
+#define IDH_SPECIAL_ACCESS_GLOBAL 8
+#define IDH_SPECIAL_ACCESS_PER_APPID 9
+#define IDH_SELECT_DOMAIN 10
+#define IDH_BROWSE_FOR_USERS 11
+#define IDH_FIND_ACCOUNT2 14 // == IDH_BROWSE_FOR_USERS + 3
diff --git a/private/ole32/oleui/util.cpp b/private/ole32/oleui/util.cpp
new file mode 100644
index 000000000..8637cd5dd
--- /dev/null
+++ b/private/ole32/oleui/util.cpp
@@ -0,0 +1,2085 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: util.cpp
+//
+// Contents: Implements the utility class CUtility
+//
+// Classes:
+//
+// Methods: CUtility::CkForAccessDenied
+// CUtility::CkAccessRights
+// CUtility::PostErrorMessage (x2)
+// CUtility::WriteRegSzNamedValue
+// CUtility::WriteRegDwordNamedValue
+// CUtility::WriteRegSingleACL
+// CUtility::WriteRegKeyACL
+// CUtility::WriteRegKeyACL2
+// CUtility::WriteLsaPassword
+// CUtility::DeleteRegKey
+// CUtility::DeleteRegValue
+// CUtility::WriteSrvIdentity
+// CUtility::ACLEditor
+// CUtility::ACLEditor2
+// CUtility::InvokeUserBrowser
+// CUtility::InvokeMachineBrowser
+// CUtility::StringFromGUID
+// CUtility::IsEqualGuid
+// CUtility::AdjustPrivilege
+// CUtility::VerifyRemoteMachine
+// CUtility::RetrieveUserPassword
+// CUtility::StoreUserPassword
+// CUtility::LookupProcessInfo
+// CUtility::MakeSecDesc
+// CUtility::CheckForValidSD
+// CUtility::CheckSDForCOM_RIGHTS_EXECUTE
+// CUtility::ChangeService
+// CUtility::UpdateDCOMInfo(void)
+// CUtility::FixHelp
+// CUtility::CopySD
+// CUtility::SetInheritanceFlags
+//
+// Functons: callBackFunc
+// ControlFixProc
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+#include "stdafx.h"
+#include "assert.h"
+#include "resource.h"
+#include "afxtempl.h"
+#include "types.h"
+#include "datapkt.h"
+#include "clspsht.h"
+
+extern "C"
+{
+#include <getuser.h>
+}
+
+#include "util.h"
+#include "virtreg.h"
+
+extern "C"
+{
+#include <ntlsa.h>
+#include <ntseapi.h>
+#include <sedapi.h>
+#include <winnetwk.h>
+#include <uiexport.h>
+#include <rpc.h>
+#include <rpcdce.h>
+}
+
+
+extern "C"
+{
+int _stdcall UpdateActivationSettings(HANDLE hRpc, RPC_STATUS *status);
+}
+
+
+static const BYTE GuidMap[] = { 3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-',
+ 8, 9, '-', 10, 11, 12, 13, 14, 15 };
+
+static const WCHAR wszDigits[] = L"0123456789ABCDEF";
+
+static const DWORD SIZEOF_SID = 44;
+
+// This leaves space for 2 access allowed ACEs in the ACL.
+const DWORD SIZEOF_ACL = sizeof(ACL) + 2 * sizeof(ACCESS_ALLOWED_ACE) +
+ 2 * SIZEOF_SID;
+
+static const DWORD SIZEOF_TOKEN_USER = sizeof(TOKEN_USER) + SIZEOF_SID;
+
+static const SID LOCAL_SYSTEM_SID = {SID_REVISION, 1, {0,0,0,0,0,5},
+ SECURITY_LOCAL_SYSTEM_RID };
+
+static const DWORD NUM_SEC_PKG = 8;
+
+
+
+
+// These are required for the method CUtility::UpdateDCOMInfo which invokes
+// an RPC proxy which expects the following
+
+
+extern "C" void * _stdcall MIDL_user_allocate(size_t size)
+{
+ return new BYTE[size];
+}
+
+
+extern "C" void _stdcall MIDL_user_free(void *p)
+{
+ delete p;
+}
+
+
+
+
+
+
+CUtility::CUtility(void)
+{
+ m_hRpc = NULL;
+}
+
+
+
+CUtility::~CUtility(void)
+{
+ if (m_hRpc != NULL)
+ {
+ RpcBindingFree(&m_hRpc);
+ }
+}
+
+
+
+void CUtility::CkForAccessDenied(int err)
+{
+ if (err == ERROR_ACCESS_DENIED)
+ {
+ CString sMsg;
+ CString sCaption;
+ sMsg.LoadString(IDS_ACCESSDENIED);
+ sCaption.LoadString(IDS_SYSTEMMESSAGE);
+ MessageBox(NULL, sMsg, sCaption, MB_OK);
+ }
+}
+
+
+
+BOOL CUtility::CkAccessRights(HKEY hRoot, TCHAR *szKeyPath)
+{
+ int err;
+ HKEY hKey;
+ BYTE aSid[256];
+ DWORD cbSid = 256;
+ PSECURITY_DESCRIPTOR pSid = (PSECURITY_DESCRIPTOR) aSid;
+ BOOL fFreePsid = FALSE;
+
+
+ // Open the specified key
+ err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey);
+
+ // The key may not exist
+ if (err == ERROR_FILE_NOT_FOUND)
+ {
+ return TRUE;
+ }
+
+ if (err == ERROR_SUCCESS)
+ {
+ // Fetch the security descriptor on this key
+ err = RegGetKeySecurity(hKey,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ (PSECURITY_DESCRIPTOR) aSid,
+ &cbSid);
+ if (err == ERROR_INSUFFICIENT_BUFFER)
+ {
+ pSid = (PSECURITY_DESCRIPTOR) malloc(cbSid);
+ if (pSid == NULL)
+ {
+ return FALSE;
+ }
+ fFreePsid = TRUE;
+ err = RegGetKeySecurity(hKey,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ (PSECURITY_DESCRIPTOR) pSid,
+ &cbSid);
+ }
+
+ // We've read the security descriptor - now try to write it
+ if (err == ERROR_SUCCESS)
+ {
+ err = RegSetKeySecurity(hKey,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ pSid);
+ }
+
+ if (hKey != hRoot)
+ {
+ RegCloseKey(hKey);
+ }
+ }
+
+ return err == ERROR_SUCCESS ? TRUE : FALSE;
+}
+
+
+
+
+
+
+void CUtility::PostErrorMessage(void)
+{
+ TCHAR szMessage[256];
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
+ 0, szMessage, sizeof( szMessage ), NULL);
+ CString sCaption;
+ sCaption.LoadString(IDS_SYSTEMMESSAGE);
+ MessageBox(NULL, szMessage, sCaption, MB_OK);
+}
+
+
+
+
+
+
+void CUtility::PostErrorMessage(int err)
+{
+ TCHAR szMessage[256];
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
+ 0, szMessage, sizeof( szMessage ), NULL);
+ CString sCaption;
+ sCaption.LoadString(IDS_SYSTEMMESSAGE);
+ MessageBox(NULL, szMessage, sCaption, MB_OK);
+}
+
+
+
+
+// Write a named string value to the registry
+int CUtility::WriteRegSzNamedValue(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ TCHAR *szVal,
+ DWORD dwSize)
+{
+ int err;
+ HKEY hKey;
+ ULONG lSize;
+
+ // Open the key
+ if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey)) != ERROR_SUCCESS)
+ {
+ return err;
+ }
+
+ // Attempt to write the named value
+ lSize = _tcslen(szVal) + 1;
+ if ((err = RegSetValueEx(hKey, szValueName, NULL, REG_SZ, (BYTE *) szVal,
+ lSize*sizeof(TCHAR) ))
+ != ERROR_SUCCESS)
+ {
+ if (hKey != hRoot)
+ {
+ RegCloseKey(hKey);
+ }
+ return err;
+ }
+
+ // Successful
+ if (hKey != hRoot)
+ {
+ RegCloseKey(hKey);
+ }
+ return ERROR_SUCCESS;
+}
+
+
+
+
+
+// Write a named DWORD value to the registry
+int CUtility::WriteRegDwordNamedValue(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ DWORD dwVal)
+{
+ int err;
+ HKEY hKey;
+
+ // Open the key
+ if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey))
+ != ERROR_SUCCESS)
+ {
+ return err;
+ }
+
+ // Attempt to write the named value
+ if (RegSetValueEx(hKey, szValueName, NULL, REG_DWORD, (BYTE *) &dwVal,
+ sizeof(DWORD))
+ != ERROR_SUCCESS)
+ {
+ if (hKey != hRoot)
+ {
+ RegCloseKey(hKey);
+ }
+ return GetLastError();
+ }
+
+ // Return the value
+ if (hKey != hRoot)
+ {
+ RegCloseKey(hKey);
+ }
+
+ return ERROR_SUCCESS;
+}
+
+
+
+// Write an ACL as a registry named value
+int CUtility::WriteRegSingleACL(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ PSECURITY_DESCRIPTOR pSec)
+{
+ int err;
+ HKEY hKey = hRoot;
+ PSrSecurityDescriptor pSrSec;
+ PSrAcl pDacl;
+
+ // Open the key unless the key path is NULL
+ if (szKeyPath)
+ {
+ if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey))
+ != ERROR_SUCCESS)
+ {
+ return err;
+ }
+ }
+
+ // If there are no ACE's and this is DefaultAccessPermission, then
+ // interpret this as activator access only which we indicate by
+ // removing the named value
+ pSrSec = (PSrSecurityDescriptor) pSec;
+ pDacl = (PSrAcl) (((BYTE *) pSec) + (pSrSec->Dacl));
+ if (_tcscmp(szValueName, TEXT("DefaultAccessPermission")) == 0 &&
+ pDacl->AceCount == 0)
+ {
+ RegDeleteValue(hKey, szValueName);
+ }
+
+ // Else write the ACL simply as a REG_SZ value
+ else
+ {
+ err = RegSetValueEx(hKey,
+ szValueName,
+ 0,
+ REG_BINARY,
+ (BYTE *) pSec,
+ RtlLengthSecurityDescriptor(pSec));
+ }
+
+ if (hKey != hRoot)
+ {
+ RegCloseKey(hKey);
+ }
+
+ return err;
+}
+
+
+
+// Write an ACL on a registry key
+int CUtility::WriteRegKeyACL(HKEY hKey,
+ HKEY *phClsids,
+ unsigned cClsids,
+ PSECURITY_DESCRIPTOR pSec,
+ PSECURITY_DESCRIPTOR pSecOrig)
+{
+ int err;
+
+ // The logic is somewhat different depending on whether we're starting
+ // with HKEY_CLASSES_ROOT or a specific AppID
+ if (hKey == HKEY_CLASSES_ROOT)
+ {
+ return WriteRegKeyACL2(hKey, hKey, pSec, pSecOrig);
+ }
+
+ // It's a specific AppID
+ else
+ {
+ // Write the security on the AppID key
+ if (err = RegSetKeySecurity(hKey,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ pSec) != ERROR_SUCCESS)
+ {
+ return err;
+ }
+
+ // Iterate over the CLSID's covered by this AppID and recursively
+ // write security on them and their subkeys
+ for (UINT k = 0; k < cClsids; k++)
+ {
+ if (err = WriteRegKeyACL2(phClsids[k], phClsids[k], pSec, pSecOrig)
+ != ERROR_SUCCESS)
+ {
+ return err;
+ }
+ }
+ }
+ return ERROR_SUCCESS;
+}
+
+
+
+// Write an ACL recursively on a registry key provided the current
+// security descriptor on the key is the same as the passed in
+// original security descriptor
+int CUtility::WriteRegKeyACL2(HKEY hRoot,
+ HKEY hKey,
+ PSECURITY_DESCRIPTOR pSec,
+ PSECURITY_DESCRIPTOR pSecOrig)
+{
+ BYTE aCurrSD[256];
+ DWORD cbCurrSD = 256;
+ PSECURITY_DESCRIPTOR pCurrSD = (PSECURITY_DESCRIPTOR) aCurrSD;
+ BOOL fFreePCurrSD = FALSE;
+ int err;
+ BOOL fProceed;
+
+ // Read the current security descriptor on this key
+ err = RegGetKeySecurity(hKey,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ aCurrSD,
+ &cbCurrSD);
+ if (err == ERROR_MORE_DATA || err == ERROR_INSUFFICIENT_BUFFER)
+ {
+ pCurrSD = (SECURITY_DESCRIPTOR *) new BYTE[cbCurrSD];
+ if (pCurrSD == NULL)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ fFreePCurrSD = TRUE;
+ }
+ else if (err != ERROR_SUCCESS)
+ {
+ return err;
+ }
+ if ((err = RegGetKeySecurity(hKey,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ pCurrSD,
+ &cbCurrSD)
+ != ERROR_SUCCESS))
+ {
+ if (fFreePCurrSD)
+ {
+ delete pCurrSD;
+ }
+ return err;
+ }
+
+ // Only proceed down this subtree if the current SD and the
+ // original SD are the same
+ fProceed = CompareSDs((PSrSecurityDescriptor) pCurrSD,
+ (PSrSecurityDescriptor) pSecOrig);
+
+ // We're done with the current security descriptor
+ if (fFreePCurrSD)
+ {
+ delete pCurrSD;
+ }
+
+ if (!fProceed)
+ {
+ if (hKey != hRoot)
+ {
+ RegCloseKey(hKey);
+ }
+ return ERROR_SUCCESS;
+ }
+
+ // Write the top level ACL
+ err = RegSetKeySecurity(hKey,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ pSec);
+
+ // Now enumerate the subkeys and write ACL's on them
+ DWORD iSubKey;
+ TCHAR szSubKeyName[128];
+ HKEY hKey2;
+
+ iSubKey = 0;
+
+ while (err == ERROR_SUCCESS)
+ {
+ // Enumerate the next key
+ err = RegEnumKey(hKey, iSubKey, szSubKeyName, 128);
+ if (err != ERROR_SUCCESS)
+ {
+ break;
+ }
+
+ // Prepare for the next key
+ iSubKey++;
+
+ // Open this subkey and recursively write the ACL on it and
+ // all of its subkeys
+ if (RegOpenKeyEx(hKey, szSubKeyName, 0, KEY_ALL_ACCESS, &hKey2)
+ == ERROR_SUCCESS)
+ {
+ err = WriteRegKeyACL2(hRoot, hKey2, pSec, pSecOrig);
+ }
+ }
+
+ if (hKey != hRoot)
+ {
+ RegCloseKey(hKey);
+ }
+ return err == ERROR_NO_MORE_ITEMS ? ERROR_SUCCESS : err;
+}
+
+
+
+
+// Write a user's password to the private LSA database
+int CUtility::WriteLsaPassword(CLSID appid, TCHAR *szPassword)
+{
+ return ERROR_SUCCESS;
+}
+
+
+
+int CUtility::DeleteRegKey(HKEY hRoot, TCHAR *szKeyPath)
+{
+ return RegDeleteKey(hRoot, szKeyPath);
+}
+
+
+
+int CUtility::DeleteRegValue(HKEY hRoot, TCHAR *szKeyPath, TCHAR *szValueName)
+{
+ int err;
+ HKEY hKey;
+
+ if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey)) == ERROR_SUCCESS)
+ {
+ err = RegDeleteValue(hKey, szValueName);
+ if (hRoot != hKey)
+ RegCloseKey(hKey);
+ }
+
+ return err;
+}
+
+
+
+// Change the identity under which a service runs
+int CUtility::WriteSrvIdentity(TCHAR *szService, TCHAR *szIdentity)
+{
+ return ERROR_SUCCESS;
+}
+
+
+
+
+
+DWORD __stdcall callBackFunc(HWND hwndParent,
+ HANDLE hInstance,
+ ULONG CallBackContext,
+ PSECURITY_DESCRIPTOR SecDesc,
+ PSECURITY_DESCRIPTOR SecDescNewObjects,
+ BOOLEAN ApplyToSubContainers,
+ BOOLEAN ApplyToSubObjects,
+ LPDWORD StatusReturn)
+{
+ int err = ERROR_SUCCESS;
+ PCallBackContext pCallBackContext = (PCallBackContext) CallBackContext;
+
+ // Set the inheritance flags on the new security descriptor
+ if (pCallBackContext->pktType == RegKeyACL)
+ {
+ g_util.SetInheritanceFlags((SECURITY_DESCRIPTOR *) SecDesc);
+ }
+
+ // Write the new or modified security descriptor
+ if (*pCallBackContext->pIndex == -1)
+ {
+ if (pCallBackContext->pktType == SingleACL)
+ {
+ err = g_virtreg.NewRegSingleACL(
+ pCallBackContext->info.single.hRoot,
+ pCallBackContext->info.single.szKeyPath,
+ pCallBackContext->info.single.szValueName,
+ (SECURITY_DESCRIPTOR *) SecDesc,
+ FALSE,
+ pCallBackContext->pIndex);
+ }
+ else
+ {
+ err = g_virtreg.NewRegKeyACL(
+ pCallBackContext->info.regKey.hKey,
+ pCallBackContext->info.regKey.phClsids,
+ pCallBackContext->info.regKey.cClsids,
+ pCallBackContext->info.regKey.szTitle,
+ pCallBackContext->origSD,
+ (SECURITY_DESCRIPTOR *) SecDesc,
+ FALSE,
+ pCallBackContext->pIndex);
+ }
+ }
+ else
+ {
+ g_virtreg.ChgRegACL(*pCallBackContext->pIndex,
+ (SECURITY_DESCRIPTOR *) SecDesc,
+ FALSE);
+ }
+
+ *StatusReturn = err;
+ return err;
+}
+
+
+
+
+
+// Invoke the ACL editor on the specified named value. This method
+// writes an ACL data packet to the virtual registry. This method is for
+// Access and Launch security only (pktType SingleACL).
+int CUtility::ACLEditor(HWND hWnd,
+ HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ int *pIndex,
+ PACKETTYPE pktType,
+ TCHAR *szPermType)
+{
+ int err;
+ HKEY hKey;
+ BYTE aSD[128];
+ DWORD cbSD = 128;
+ DWORD dwType;
+ SECURITY_DESCRIPTOR *pSD = (SECURITY_DESCRIPTOR *) aSD;
+ BOOL fFreePSD = FALSE;
+ SID *pSid;
+ TCHAR szAllow[32];
+ TCHAR szDeny[32];
+ CString szAllow_;
+ CString szDeny_;
+
+ szAllow_.LoadString(IDS_Allow_);
+ szDeny_.LoadString(IDS_Deny_);
+
+
+ // Build the allow and deny strings
+ _tcscpy(szAllow, (LPCTSTR) szAllow_);
+ _tcscat(szAllow, szPermType);
+ _tcscpy(szDeny, (LPCTSTR) szDeny_);
+ _tcscat(szDeny, szPermType);
+
+
+ // Fetch the current SD, either from the registry, by default if the
+ // named value doesn't exist or from the virtual registry
+ if (*pIndex == -1)
+ {
+ // Open the specified key
+ if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0,
+ KEY_ALL_ACCESS, &hKey))
+ != ERROR_SUCCESS)
+ {
+ return err;
+ }
+
+ // Attempt to read the specified named value
+ err = RegQueryValueEx(hKey, szValueName, 0, &dwType, (BYTE *) aSD,
+ &cbSD);
+
+ if (err == ERROR_MORE_DATA || err == ERROR_INSUFFICIENT_BUFFER)
+ {
+ pSD = (SECURITY_DESCRIPTOR *) new BYTE[cbSD];
+ if (pSD == NULL)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ fFreePSD = TRUE;
+ err = RegQueryValueEx(hKey, szValueName, 0, &dwType,
+ (BYTE *) pSD, &cbSD);
+ }
+ // The named valued doesn't exist. If this is
+ // \\HKEY_CLASSES_ROOT\...
+ // then use the default named value if it exists
+ else if (err != ERROR_SUCCESS)
+ {
+ if (hRoot != HKEY_LOCAL_MACHINE)
+ {
+ if (err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ TEXT("SOFTWARE\\Microsoft\\OLE"),
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey)
+ != ERROR_SUCCESS)
+ {
+ return err;
+ }
+
+ // Attempt to read the specified named value
+ TCHAR szDefault[32];
+
+ _tcscpy(szDefault, TEXT("Default"));
+ _tcscat(szDefault, szValueName);
+ err = RegQueryValueEx(hKey, szDefault, 0, &dwType,
+ (BYTE *) aSD, &cbSD);
+ if (err == ERROR_MORE_DATA)
+ {
+ pSD = (SECURITY_DESCRIPTOR *) new BYTE[cbSD];
+ if (pSD == NULL)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ fFreePSD = TRUE;
+ err = RegQueryValueEx(hKey, szDefault, 0, &dwType,
+ (BYTE *) pSD, &cbSD);
+ }
+ RegCloseKey(hKey);
+ }
+ }
+
+ // If still don't have an SD, then simply create one
+ if (err != ERROR_SUCCESS)
+ {
+ if (!g_util.LookupProcessInfo(&pSid, NULL))
+ {
+ return GetLastError();
+ }
+ if (!g_util.MakeSecDesc(pSid, &pSD))
+ {
+ delete pSid;
+ return GetLastError();
+ }
+ fFreePSD = TRUE;
+ }
+ }
+
+ // Fetch the most recently edited SD
+ else
+ {
+ CDataPacket &cdp = g_virtreg.GetAt(*pIndex);
+
+ pSD = cdp.pkt.acl.pSec;
+ }
+
+
+ // Initialize the callback context
+ m_sCallBackContext.pktType = pktType;
+ m_sCallBackContext.pIndex = pIndex;
+ m_sCallBackContext.origSD = pSD;
+ m_sCallBackContext.info.single.hRoot = hRoot;
+ m_sCallBackContext.info.single.szKeyPath = szKeyPath;
+ m_sCallBackContext.info.single.szValueName = szValueName;
+
+ // Invoke the ACL editor
+ DWORD dwStatus;
+ GENERIC_MAPPING genericMapping;
+ CString szObjectType;
+
+ szObjectType.LoadString(IDS_Registry_value);
+
+ SED_HELP_INFO helpInfo =
+ {
+ TEXT("dcomcnfg.hlp"),
+ {HC_MAIN_DLG,
+ HC_MAIN_DLG,
+ HC_MAIN_DLG,
+ HC_MAIN_DLG,
+ HC_MAIN_DLG,
+ HC_MAIN_DLG,
+ HC_MAIN_DLG}
+ };
+
+ SED_OBJECT_TYPE_DESCRIPTOR objTyp =
+ {1, // Revision
+ FALSE, // Is container?
+ FALSE, // Allow new object perms?
+ FALSE, // Specific to generic?
+ &genericMapping, // Generic mapping
+ NULL, // Generic mapping new
+ (TCHAR *) ((LPCTSTR) szObjectType), // Object type name
+ &helpInfo, // Help info
+ TEXT(""), // Ckbox title
+ TEXT(""), // Apply title
+ TEXT(""), //
+ NULL, // Special object access
+ NULL // New special object access
+ };
+
+ SED_APPLICATION_ACCESS appAccess[] =
+ {{SED_DESC_TYPE_RESOURCE, COM_RIGHTS_EXECUTE, 0, szAllow},
+ {SED_DESC_TYPE_RESOURCE, 0, 0, szDeny}};
+
+ SED_APPLICATION_ACCESSES appAccesses =
+ {2, // Count of access groups
+ appAccess, // Access array
+ szAllow // Default access name
+ };
+
+ // Intialize the help contexts
+ helpInfo.aulHelpContext[HC_MAIN_DLG] =
+ IDH_REGISTRY_VALUE_PERMISSIONS;
+ helpInfo.aulHelpContext[HC_SPECIAL_ACCESS_DLG] =
+ IDH_SPECIAL_ACCESS_GLOBAL;
+ helpInfo.aulHelpContext[HC_NEW_ITEM_SPECIAL_ACCESS_DLG] =
+ IDH_SPECIAL_ACCESS_GLOBAL;
+ helpInfo.aulHelpContext[HC_ADD_USER_DLG] =
+ IDH_ADD_USERS_AND_GROUPS;
+ helpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_LG_DLG] =
+ IDH_LOCAL_GROUP_MEMBERSHIP;
+ helpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_GG_DLG] =
+ IDH_GLOBAL_GROUP_MEMBERSHIP;
+ helpInfo.aulHelpContext[HC_ADD_USER_SEARCH_DLG] =
+ IDH_FIND_ACCOUNT1;
+
+ genericMapping.GenericRead = GENERIC_ALL;
+ genericMapping.GenericWrite = GENERIC_ALL;
+ genericMapping.GenericExecute = GENERIC_ALL;
+ genericMapping.GenericAll = GENERIC_ALL;
+
+ // If this is for Access or Launch permissons then check that the
+ // SD contains only allows and deny's for COM_RIGHTS_EXECUTE
+ if (!CheckSDForCOM_RIGHTS_EXECUTE(pSD))
+ {
+ return IDCANCEL;
+ }
+
+ if (!CheckForValidSD(pSD))
+ {
+ return IDCANCEL;
+ }
+ // Invoke the ACL editor
+ SedDiscretionaryAclEditor(hWnd, // Owner hWnd
+ GetModuleHandle(NULL), // Owner hInstance
+ NULL, // Server
+ &objTyp, // ObjectTyp,
+ &appAccesses, // Application accesses
+ szValueName, // Object name,
+ callBackFunc, // Callback function
+ (ULONG) &m_sCallBackContext, // Callback context
+ pSD, // Security descriptor,
+ FALSE, // Couldnt read Dacl,
+ FALSE, // Can't write Dacl,
+ &dwStatus, // SED status return,
+ 0); // Flags
+
+ // Check status return
+ if (dwStatus != ERROR_SUCCESS)
+ {
+// PostErrorMessage(dwStatus);
+ }
+
+ // We're done
+ if (fFreePSD)
+ {
+ delete pSD;
+ }
+
+ return dwStatus == 0 ? ERROR_SUCCESS : IDCANCEL;
+}
+
+
+
+
+
+// Invoke the ACL editor on the specified key. This method writes an ACL
+// data packet to the virtual registry. This method supports configuration
+// security only (pktType RegKeyACL).
+int CUtility::ACLEditor2(HWND hWnd,
+ HKEY hKey,
+ HKEY *phClsids,
+ unsigned cClsids,
+ TCHAR *szTitle,
+ int *pIndex,
+ PACKETTYPE pktType)
+{
+ int err;
+ BYTE aSD[128];
+ DWORD cbSD = 128;
+ SECURITY_DESCRIPTOR *pSD = (SECURITY_DESCRIPTOR *) aSD;
+ BOOL fFreePSD = FALSE;
+ TCHAR szKeyRead[32];
+ CString szKeyRead_;
+ TCHAR szHkeyClassesRoot[32];
+ CString szHkeyClassesRoot_;
+
+
+ // Initialize strings
+ szKeyRead_.LoadString(IDS_Key_Read);
+ _tcscpy(szKeyRead, (LPCTSTR) szKeyRead_);
+ szHkeyClassesRoot_.LoadString(IDS_HKEY_CLASSES_ROOT);
+ _tcscpy(szHkeyClassesRoot, (LPCTSTR) szHkeyClassesRoot_);
+
+ if (*pIndex == -1)
+ {
+ // Read the security descriptor on this key
+ err = RegGetKeySecurity(hKey,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ aSD,
+ &cbSD);
+ if (err == ERROR_MORE_DATA || err == ERROR_INSUFFICIENT_BUFFER)
+ {
+ pSD = (SECURITY_DESCRIPTOR *) new BYTE[cbSD];
+ if (pSD == NULL)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ fFreePSD = TRUE;
+ }
+ else if (err != ERROR_SUCCESS)
+ {
+ return err;
+ }
+ if ((err = RegGetKeySecurity(hKey,
+ OWNER_SECURITY_INFORMATION |
+ GROUP_SECURITY_INFORMATION |
+ DACL_SECURITY_INFORMATION,
+ pSD,
+ &cbSD)
+ != ERROR_SUCCESS))
+ {
+ if (fFreePSD)
+ {
+ delete pSD;
+ }
+ return err;
+ }
+ }
+
+ // Fetch the most recently edited SD
+ else
+ {
+ CDataPacket &cdp = g_virtreg.GetAt(*pIndex);
+
+ pSD = cdp.pkt.racl.pSec;
+ }
+
+
+ // Initialize the callback context
+ m_sCallBackContext.pktType = pktType;
+ m_sCallBackContext.pIndex = pIndex;
+ m_sCallBackContext.origSD = pSD;
+ m_sCallBackContext.info.regKey.hKey = hKey;
+ m_sCallBackContext.info.regKey.phClsids = phClsids;
+ m_sCallBackContext.info.regKey.cClsids = cClsids;
+ m_sCallBackContext.info.regKey.szTitle = szTitle;
+
+ // Invoke the ACL editor
+ DWORD dwStatus;
+ GENERIC_MAPPING genericMapping;
+
+ CString szObjectType;
+ szObjectType.LoadString(IDS_Registry_Key);
+ CString szQueryValue;
+ szQueryValue.LoadString(IDS_Query_Value);
+ CString szSetValue;
+ szSetValue.LoadString(IDS_Set_Value);
+ CString szCreateSubkeys;
+ szCreateSubkeys.LoadString(IDS_Create_Subkey);
+ CString szEnumerateSubkeys;
+ szEnumerateSubkeys.LoadString(IDS_Enumerate_Subkeys);
+ CString szNotify;
+ szNotify.LoadString(IDS_Notify);
+ CString szCreateLink;
+ szCreateLink.LoadString(IDS_Create_Link);
+ CString szDelete;
+ szDelete.LoadString(IDS_Delete);
+ CString szWriteDAC;
+ szWriteDAC.LoadString(IDS_Write_DAC);
+ CString szWriteOwner;
+ szWriteOwner.LoadString(IDS_Write_Owner);
+ CString szReadControl;
+ szReadControl.LoadString(IDS_Read_Control);
+ CString szRead;
+ szRead.LoadString(IDS_Read);
+ CString szFullControl;
+ szFullControl.LoadString(IDS_Full_Control);
+ CString szSpecialAccess;
+ szSpecialAccess.LoadString(IDS_Special_AccessDotDotDot);
+
+
+ SED_HELP_INFO helpInfo =
+ {
+ TEXT("dcomcnfg.hlp"),
+ {HC_MAIN_DLG,
+ HC_MAIN_DLG,
+ HC_MAIN_DLG,
+ HC_MAIN_DLG,
+ HC_MAIN_DLG,
+ HC_MAIN_DLG,
+ HC_MAIN_DLG}
+ };
+
+ SED_OBJECT_TYPE_DESCRIPTOR objTyp =
+ {SED_REVISION1, // Revision
+ FALSE, // Is container?
+ FALSE, // Allow new object perms?
+ FALSE, // Specific to generic?
+ &genericMapping, // Generic mapping
+ NULL, // Generic mapping new
+ (TCHAR *) ((LPCTSTR) szObjectType), // Object type name
+ &helpInfo, // Help info
+ TEXT(""), // Ckbox title
+ TEXT(""), // Apply title
+ TEXT(""), //
+ (TCHAR *) ((LPCTSTR) szSpecialAccess), // Special Access menu item
+ NULL // New special object access
+ };
+
+
+ SED_APPLICATION_ACCESS appAccess[] =
+ {
+ { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_QUERY_VALUE, 0,
+ (TCHAR *) ((LPCTSTR) szQueryValue) },
+ { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_SET_VALUE, 0,
+ (TCHAR *) ((LPCTSTR) szSetValue) },
+ { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_CREATE_SUB_KEY, 0,
+ (TCHAR *) ((LPCTSTR) szCreateSubkeys) },
+ { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_ENUMERATE_SUB_KEYS, 0,
+ (TCHAR *) ((LPCTSTR) szEnumerateSubkeys) },
+ { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_NOTIFY, 0,
+ (TCHAR *) ((LPCTSTR) szNotify) },
+ { SED_DESC_TYPE_RESOURCE_SPECIAL, KEY_CREATE_LINK, 0,
+ (TCHAR *) ((LPCTSTR) szCreateLink) },
+ { SED_DESC_TYPE_RESOURCE_SPECIAL, 0x00010000, /* DELETE, */ 0,
+ (TCHAR *) ((LPCTSTR) szDelete) },
+ { SED_DESC_TYPE_RESOURCE_SPECIAL, WRITE_DAC, 0,
+ (TCHAR *) ((LPCTSTR) szWriteDAC) },
+ { SED_DESC_TYPE_RESOURCE_SPECIAL, WRITE_OWNER, 0,
+ (TCHAR *) ((LPCTSTR) szWriteOwner) },
+ { SED_DESC_TYPE_RESOURCE_SPECIAL, READ_CONTROL, 0,
+ (TCHAR *) ((LPCTSTR) szReadControl) },
+ { SED_DESC_TYPE_RESOURCE, KEY_READ, 0,
+ (TCHAR *) ((LPCTSTR) szRead) },
+ { SED_DESC_TYPE_RESOURCE, GENERIC_ALL, /* KEY_ALL_ACCESS, */ 0,
+ (TCHAR *) ((LPCTSTR) szFullControl) }
+ };
+
+ SED_APPLICATION_ACCESSES appAccesses =
+ {12, // Count of access groups
+ appAccess, // Access array
+ szKeyRead // Default access name
+ };
+
+ // Intialize the help contexts
+ helpInfo.aulHelpContext[HC_MAIN_DLG] =
+ IDH_REGISTRY_KEY_PERMISSIONS;
+ if (hKey == HKEY_CLASSES_ROOT)
+ {
+ helpInfo.aulHelpContext[HC_SPECIAL_ACCESS_DLG] =
+ IDH_SPECIAL_ACCESS_GLOBAL;
+ helpInfo.aulHelpContext[HC_NEW_ITEM_SPECIAL_ACCESS_DLG] =
+ IDH_SPECIAL_ACCESS_GLOBAL;
+ }
+ else
+ {
+ helpInfo.aulHelpContext[HC_SPECIAL_ACCESS_DLG] =
+ IDH_SPECIAL_ACCESS_PER_APPID;
+ helpInfo.aulHelpContext[HC_NEW_ITEM_SPECIAL_ACCESS_DLG] =
+ IDH_SPECIAL_ACCESS_PER_APPID;
+ }
+
+ helpInfo.aulHelpContext[HC_ADD_USER_DLG] =
+ IDH_ADD_USERS_AND_GROUPS;
+ helpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_LG_DLG] =
+ IDH_LOCAL_GROUP_MEMBERSHIP;
+ helpInfo.aulHelpContext[HC_ADD_USER_MEMBERS_GG_DLG] =
+ IDH_GLOBAL_GROUP_MEMBERSHIP;
+ helpInfo.aulHelpContext[HC_ADD_USER_SEARCH_DLG] =
+ IDH_FIND_ACCOUNT1;
+
+ genericMapping.GenericRead = KEY_READ;
+ genericMapping.GenericWrite = KEY_WRITE;
+ genericMapping.GenericExecute = KEY_READ;
+ genericMapping.GenericAll = KEY_ALL_ACCESS;
+
+ if (!CheckForValidSD(pSD))
+ {
+ return IDCANCEL;
+ }
+
+ // Invoke the ACL editor
+ SedDiscretionaryAclEditor(hWnd, // Owner hWnd
+ GetModuleHandle(NULL), // Owner hInstance
+ NULL, // Server
+ &objTyp, // ObjectTyp,
+ &appAccesses, // Application accesses
+ szTitle ? szTitle : szHkeyClassesRoot,// Object name,
+ callBackFunc, // Callback function
+ (ULONG) &m_sCallBackContext, // Callback context
+ pSD, // Security descriptor,
+ FALSE, // Couldnt read Dacl,
+ FALSE, // Can't write Dacl,
+ &dwStatus, // SED status return,
+ 0); // Flags
+
+ // Check status return
+ if (dwStatus != ERROR_SUCCESS)
+ {
+// PostErrorMessage(dwStatus);
+ }
+
+ // We're done
+ if (fFreePSD)
+ {
+ delete pSD;
+ }
+
+ return dwStatus == 0 ? ERROR_SUCCESS : IDCANCEL;
+}
+
+
+
+
+BOOL CUtility::InvokeUserBrowser(HWND hWnd, TCHAR *szUser)
+{
+ BOOL fRet = FALSE;
+ HUSERBROW hUser;
+ USERBROWSER sUserBrowser;
+ SUserDetailsPlus sUserDetailsPlus;
+ ULONG ulSize = USER_DETAILS_BUFFER_SIZE;
+ CString szTitle;
+
+ szTitle.LoadString(IDS_Browse_for_users);
+
+ sUserBrowser.ulStructSize = sizeof(USERBROWSER);
+ sUserBrowser.fUserCancelled = FALSE;
+ sUserBrowser.fExpandNames = TRUE;
+ sUserBrowser.hwndOwner = hWnd;
+ sUserBrowser.pszTitle = (TCHAR *) ((LPCTSTR) szTitle);
+ sUserBrowser.pszInitialDomain = NULL;
+ sUserBrowser.Flags = USRBROWS_DONT_SHOW_COMPUTER |
+ USRBROWS_SINGLE_SELECT |
+ USRBROWS_INCL_ALL |
+ USRBROWS_SHOW_USERS;
+ sUserBrowser.ulHelpContext = IDH_BROWSE_FOR_USERS;
+ sUserBrowser.pszHelpFileName = TEXT("dcomcnfg.hlp");
+
+
+ hUser = OpenUserBrowser(&sUserBrowser);
+ if (hUser == NULL)
+ {
+ return FALSE;
+ }
+ else
+ {
+ CString szBackslash;
+
+ szBackslash.LoadString(IDS_backslash);
+
+ if (EnumUserBrowserSelection(hUser,
+ &sUserDetailsPlus.sUserDetails,
+ &ulSize))
+ {
+ _tcscpy(szUser, sUserDetailsPlus.sUserDetails.pszDomainName);
+ _tcscat(szUser, (LPCTSTR) szBackslash);
+ _tcscat(szUser, sUserDetailsPlus.sUserDetails.pszAccountName);
+ fRet = TRUE;
+ }
+ }
+
+ CloseUserBrowser(hUser);
+
+ return fRet;
+}
+
+
+
+
+
+
+
+BOOL CUtility::InvokeMachineBrowser(TCHAR *szMachine)
+{
+ ///////////////////////////////////////////////////
+ // If we end up not wanting to use I_SystemFocusDialog, then the code below
+ // is the start for fetching machine resources ourselves
+/*
+ DWORD dwErr;
+ NETRESOURCE aNetResource[1000];
+ HANDLE hNetwork;
+ DWORD dwEntries = 100;
+ DWORD dwBufSize = sizeof(aNetResource);
+
+ dwErr = WNetOpenEnum(RESOURCE_GLOBALNET,
+ RESOURCETYPE_ANY,
+ 0,
+ NULL,
+ &hNetwork);
+
+ if (dwErr == NO_ERROR)
+ {
+ dwEntries = 0xffffffff;
+ dwErr = WNetEnumResource(hNetwork,
+ &dwEntries,
+ aNetResource,
+ &dwBufSize);
+ }
+
+ WNetCloseEnum(hNetwork);
+
+ dwErr = WNetOpenEnum(RESOURCE_GLOBALNET,
+ RESOURCETYPE_ANY,
+ 0,
+ aNetResource,
+ &hNetwork);
+
+ if (dwErr == NO_ERROR)
+ {
+ dwEntries = 0xffffffff;
+ dwErr = WNetEnumResource(hNetwork,
+ &dwEntries,
+ &aNetResource[1],
+ &dwBufSize);
+ }
+
+
+ return dwErr == NO_ERROR ? TRUE : FALSE;
+*/
+///////////////////////////////////////////////////////
+
+
+
+
+ UINT err;
+ BOOL fOkPressed = FALSE;
+
+ err = I_SystemFocusDialog(GetForegroundWindow(),
+// FOCUSDLG_BROWSE_LOGON_DOMAIN |
+// FOCUSDLG_BROWSE_WKSTA_DOMAIN,
+ 0x30003,
+ szMachine,
+ 128,
+ &fOkPressed,
+ TEXT("dcomcnfg.hlp"),
+ IDH_SELECT_DOMAIN);
+
+ if (err == ERROR_SUCCESS && fOkPressed)
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+
+
+
+int CUtility::StringFromGUID(GUID &rguid, TCHAR *lpsz, int cbMax)
+{
+ int i;
+ LPWSTR p = lpsz;
+
+ const BYTE * pBytes = (const BYTE *) &rguid;
+
+ *p++ = L'{';
+
+ for (i = 0; i < sizeof(GuidMap); i++)
+ {
+ if (GuidMap[i] == '-')
+ {
+ *p++ = L'-';
+ }
+ else
+ {
+ *p++ = wszDigits[ (pBytes[GuidMap[i]] & 0xF0) >> 4 ];
+ *p++ = wszDigits[ (pBytes[GuidMap[i]] & 0x0F) ];
+ }
+ }
+ *p++ = L'}';
+ *p = L'\0';
+
+ return GUIDSTR_MAX;
+}
+
+
+
+
+BOOL CUtility::IsEqualGuid(GUID &guid1, GUID &guid2)
+{
+ return (
+ ((PLONG) &guid1)[0] == ((PLONG) &guid2)[0] &&
+ ((PLONG) &guid1)[1] == ((PLONG) &guid2)[1] &&
+ ((PLONG) &guid1)[2] == ((PLONG) &guid2)[2] &&
+ ((PLONG) &guid1)[3] == ((PLONG) &guid2)[3]);
+}
+
+
+
+BOOL CUtility::AdjustPrivilege(TCHAR *szPrivilege)
+{
+ HANDLE hProcessToken = 0;
+ BOOL bOK = FALSE;
+ TOKEN_PRIVILEGES privileges;
+
+ if( !OpenProcessToken( GetCurrentProcess(),
+ TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
+ &hProcessToken ) )
+ {
+ return FALSE;
+ }
+
+ privileges.PrivilegeCount = 1;
+ privileges.Privileges[ 0 ].Attributes = SE_PRIVILEGE_ENABLED;
+ if( !LookupPrivilegeValue(NULL, szPrivilege,
+ &privileges.Privileges[ 0 ].Luid ) )
+ {
+ return FALSE;
+ }
+
+ if( !AdjustTokenPrivileges( hProcessToken, FALSE,
+ &privileges,
+ 0L, NULL, NULL ) )
+ {
+ return FALSE;
+ }
+
+ if( hProcessToken )
+ {
+ CloseHandle( hProcessToken );
+ }
+
+ return TRUE;
+}
+
+
+
+BOOL CUtility::VerifyRemoteMachine(TCHAR *szRemoteMachine)
+{
+ NETRESOURCE sResource;
+ NETRESOURCE sResource2;
+ DWORD dwErr;
+ HANDLE hEnum;
+ DWORD cbEntries;
+ DWORD cbBfr;
+
+ // TODO: Get this function to work. Right now WNetEnumResource is
+ // screwing up the stack, causing an AV and anyway returns the error
+ // ERROR_NO_MORE_ITEMS which I don't understand.
+ //
+ // Also, it is not clear that we should verify the remote machine name.
+ // It may have different formats, e.g. IP address or a URL specification.
+ // It may not even be on an NT network. In any case it may be offline
+ // currently.
+ return TRUE;
+
+ sResource.dwScope = RESOURCE_GLOBALNET;
+ sResource.dwType = RESOURCETYPE_ANY;
+ sResource.dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;
+ sResource.dwUsage = RESOURCEUSAGE_CONTAINER;
+ sResource.lpLocalName = NULL;
+ sResource.lpRemoteName = szRemoteMachine;
+ sResource.lpComment = NULL;
+ sResource.lpProvider = NULL;
+
+
+
+ dwErr = WNetOpenEnum(RESOURCE_GLOBALNET,
+ RESOURCETYPE_ANY,
+ RESOURCEUSAGE_CONTAINER,
+ &sResource,
+ &hEnum);
+
+ if (dwErr == NO_ERROR)
+ {
+ cbEntries = 1;
+ cbBfr = sizeof(NETRESOURCE);
+ dwErr = WNetEnumResource(hEnum, &cbEntries, &sResource2, &cbBfr);
+ }
+
+ CloseHandle(hEnum);
+
+ return TRUE;
+
+}
+
+
+
+
+BOOL CUtility::RetrieveUserPassword(TCHAR *szAppid, CString &sPassword)
+{
+ LSA_OBJECT_ATTRIBUTES sObjAttributes;
+ HANDLE hPolicy = NULL;
+ LSA_UNICODE_STRING sKey;
+ PLSA_UNICODE_STRING psPassword;
+ TCHAR szKey[4 + GUIDSTR_MAX + 1];
+
+ // Formulate the access key
+ _tcscpy(szKey, TEXT("SCM:"));
+ _tcscat(szKey, szAppid);
+
+ // UNICODE_STRING length fields are in bytes and include the NULL
+ // terminator
+ sKey.Length = (_tcslen(szKey) + 1) * sizeof(TCHAR);
+ sKey.MaximumLength = (GUIDSTR_MAX + 5) * sizeof(TCHAR);
+ sKey.Buffer = szKey;
+
+ // Open the local security policy
+ InitializeObjectAttributes(&sObjAttributes, NULL, 0L, NULL, NULL);
+ if (!NT_SUCCESS(LsaOpenPolicy(NULL, &sObjAttributes,
+ POLICY_GET_PRIVATE_INFORMATION, &hPolicy)))
+ {
+ return FALSE;
+ }
+
+ // Read the user's password
+ if (!NT_SUCCESS(LsaRetrievePrivateData(hPolicy, &sKey, &psPassword)))
+ {
+ LsaClose(hPolicy);
+ return FALSE;
+ }
+
+ // Close the policy handle, we're done with it now.
+ LsaClose(hPolicy);
+
+ // Copy the password
+ sPassword = psPassword->Buffer;
+
+ return TRUE;
+}
+
+
+
+
+
+BOOL CUtility::StoreUserPassword(TCHAR *szAppid, CString &szPassword)
+{
+ LSA_OBJECT_ATTRIBUTES sObjAttributes;
+ HANDLE hPolicy = NULL;
+ LSA_UNICODE_STRING sKey;
+ LSA_UNICODE_STRING sPassword;
+ TCHAR szKey[4 + GUIDSTR_MAX + 1];
+
+ // Formulate the access key
+ _tcscpy(szKey, TEXT("SCM:"));
+ _tcscat(szKey, szAppid);
+
+ // UNICODE_STRING length fields are in bytes and include the NULL
+ // terminator
+ sKey.Length = (_tcslen(szKey) + 1) * sizeof(TCHAR);
+ sKey.MaximumLength = (GUIDSTR_MAX + 5) * sizeof(TCHAR);
+ sKey.Buffer = szKey;
+
+ // Make the password a UNICODE string
+ sPassword.Length = (_tcslen(LPCTSTR(szPassword)) + 1) * sizeof(TCHAR);
+ sPassword.Buffer = (TCHAR *) LPCTSTR(szPassword);
+ sPassword.MaximumLength = sPassword.Length;
+
+ // Open the local security policy
+ InitializeObjectAttributes(&sObjAttributes, NULL, 0L, NULL, NULL);
+ if (!NT_SUCCESS(LsaOpenPolicy(NULL, &sObjAttributes,
+ POLICY_CREATE_SECRET, &hPolicy)))
+ {
+ return FALSE;
+ }
+
+ // Store the user's password
+ if (!NT_SUCCESS(LsaStorePrivateData(hPolicy, &sKey, &sPassword)))
+ {
+ g_util.PostErrorMessage();
+ LsaClose(hPolicy);
+ return FALSE;
+ }
+
+ // Close the policy handle, we're done with it now.
+ LsaClose(hPolicy);
+
+ return TRUE;
+}
+
+
+
+
+
+
+BOOL CUtility::LookupProcessInfo(SID **ppSid, TCHAR **ppszPrincName)
+{
+ BYTE aMemory[SIZEOF_TOKEN_USER];
+ TOKEN_USER *pTokenUser = (TOKEN_USER *) &aMemory;
+ HANDLE hToken = NULL;
+ DWORD lIgnore;
+ DWORD lSidLen;
+ DWORD lNameLen = 0;
+ DWORD lDomainLen = 0;
+ TCHAR *pDomainName = NULL;
+ SID_NAME_USE sIgnore;
+
+ if (ppszPrincName != NULL)
+ *ppszPrincName = NULL;
+
+ // Open the process's token.
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
+ {
+ // Lookup SID of process token.
+ if (GetTokenInformation( hToken, TokenUser, pTokenUser,
+ sizeof(aMemory), &lIgnore ))
+ {
+ // Allocate memory to hold the SID.
+ lSidLen = GetLengthSid( pTokenUser->User.Sid );
+ *ppSid = (SID *) new BYTE[lSidLen];
+ if (*ppSid == NULL)
+ {
+ return FALSE;
+ }
+ memcpy(*ppSid, pTokenUser->User.Sid, lSidLen);
+
+ // Stop now if the caller doesn't want the user name.
+ if (ppszPrincName != NULL)
+ {
+ // Find out how much memory to allocate for the name.
+ LookupAccountSid(NULL, pTokenUser->User.Sid, NULL, &lNameLen,
+ NULL, &lDomainLen, NULL );
+ if (lNameLen != 0)
+ {
+ // Allocate memory for the user's name.
+ *ppszPrincName =
+ (TCHAR *) new BYTE[lNameLen*sizeof(TCHAR)];
+ if (ppszPrincName == NULL)
+ {
+ CloseHandle( hToken );
+ return FALSE;
+ }
+ pDomainName = (TCHAR *) new BYTE[lDomainLen*sizeof(TCHAR)];
+ if (pDomainName == NULL)
+ {
+ delete ppszPrincName;
+ CloseHandle( hToken );
+ return FALSE;
+ }
+
+ // Find the user's name.
+ if (!LookupAccountSid( NULL, pTokenUser->User.Sid,
+ *ppszPrincName, &lNameLen,
+ pDomainName,
+ &lDomainLen, &sIgnore))
+ {
+ delete ppszPrincName;
+ delete pDomainName;
+ CloseHandle( hToken );
+ return FALSE;
+ }
+ }
+ delete ppszPrincName;
+ delete pDomainName;
+ }
+ }
+ CloseHandle( hToken );
+ }
+
+ return TRUE;
+}
+
+
+
+
+
+
+BOOL CUtility::MakeSecDesc(SID *pSid, SECURITY_DESCRIPTOR **ppSD)
+{
+ ACL *pAcl;
+ DWORD lSidLen;
+ SID *pGroup;
+ SID *pOwner;
+
+ // In case we fail
+ *ppSD = NULL;
+
+ // Allocate the security descriptor.
+ lSidLen = GetLengthSid( pSid );
+ *ppSD = (SECURITY_DESCRIPTOR *) new BYTE[
+ sizeof(SECURITY_DESCRIPTOR) + 2*lSidLen + SIZEOF_ACL];
+ if (*ppSD == NULL)
+ {
+ return FALSE;
+ }
+ pGroup = (SID *) (*ppSD + 1);
+ pOwner = (SID *) (((BYTE *) pGroup) + lSidLen);
+ pAcl = (ACL *) (((BYTE *) pOwner) + lSidLen);
+
+ // Initialize a new security descriptor.
+ if (!InitializeSecurityDescriptor(*ppSD, SECURITY_DESCRIPTOR_REVISION))
+ {
+ delete *ppSD;
+ return FALSE;
+ }
+
+ // Initialize a new ACL.
+ if (!InitializeAcl(pAcl, SIZEOF_ACL, ACL_REVISION2))
+ {
+ delete *ppSD;
+ return FALSE;
+ }
+
+// Comment out this code because the only time we create a default SD is
+// when attempting to edit
+// \\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLE.DefaultAccessPermission
+// which we want to start with 0 ACE's
+/*
+ // Allow the current user access.
+ if (!AddAccessAllowedAce( pAcl, ACL_REVISION2, COM_RIGHTS_EXECUTE, pSid ))
+ {
+ delete *ppSD;
+ return FALSE;
+ }
+
+ // Allow local system access.
+ if (!AddAccessAllowedAce( pAcl, ACL_REVISION2, COM_RIGHTS_EXECUTE,
+ (void *) &LOCAL_SYSTEM_SID ))
+ {
+ delete *ppSD;
+ return FALSE;
+ }
+*/
+
+ // Add a new ACL to the security descriptor.
+ if (!SetSecurityDescriptorDacl( *ppSD, TRUE, pAcl, FALSE ))
+ {
+ delete *ppSD;
+ return FALSE;
+ }
+
+ // Set the group.
+ memcpy( pGroup, pSid, lSidLen );
+ if (!SetSecurityDescriptorGroup( *ppSD, pGroup, FALSE ))
+ {
+ delete *ppSD;
+ return FALSE;
+ }
+
+ // Set the owner.
+ memcpy( pOwner, pSid, lSidLen );
+ if (!SetSecurityDescriptorOwner( *ppSD, pOwner, FALSE ))
+ {
+ delete *ppSD;
+ return FALSE;
+ }
+
+ // Check the security descriptor.
+ assert(IsValidSecurityDescriptor(*ppSD));
+
+ return TRUE;
+}
+
+
+
+BOOL CUtility::CheckForValidSD(SECURITY_DESCRIPTOR *pSD)
+{
+ WORD dwType = *((WORD *)pSD);
+ if (dwType != 1)
+ {
+ CString sMsg, sCaption;
+ sMsg.LoadString(IDS_BADSD);
+ sCaption.LoadString(IDS_SYSTEMMESSAGE);
+ MessageBox(NULL, sMsg, sCaption, MB_OK);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL CUtility::CheckSDForCOM_RIGHTS_EXECUTE(SECURITY_DESCRIPTOR *pSD)
+{
+ PSrSecurityDescriptor pSrSD = (PSrSecurityDescriptor) pSD;
+ PSrAcl pDacl;
+ PSrAce pAce;
+ DWORD cbAces;
+
+ // Check whether the security descriptor is self-relative
+ if (pSrSD->Dacl > 0x1000)
+ {
+ pDacl = (PSrAcl) pSrSD->Dacl;
+
+ // Check for a deny ALL
+ if (pDacl == NULL)
+ {
+ return TRUE;
+ }
+ }
+ else
+ {
+ // First check for a deny ALL
+ if (pSrSD->Dacl == 0)
+ {
+ return TRUE;
+ }
+
+ pDacl = (PSrAcl) (((BYTE *) pSrSD) + (pSrSD->Dacl));
+ }
+
+ // Do over the ACE's
+ for (pAce = (PSrAce) (((BYTE *) pDacl) + sizeof(SSrAcl)),
+ cbAces = pDacl->AceCount;
+ cbAces;
+ pAce = (PSrAce) (((BYTE *) pAce) + pAce->AceSize),
+ cbAces--)
+ {
+ // Check that it is
+ // a) an allow on COM_RIGHTS_EXECUTE
+ // b) a deny on GENERIC_ALL,
+ // c) a deny on COM_RIGHTS_EXECUTE,
+ // d) a deny ALL (handled above if the DACL is NULL) or
+ // e) an allow everyone (handled implicitly if cbAces == 0)
+ if (!(((pAce->Type == 0 && pAce->AccessMask == COM_RIGHTS_EXECUTE)
+ ||
+ (pAce->Type == 1 && pAce->AccessMask == GENERIC_ALL)
+ ||
+ (pAce->Type == 1 && pAce->AccessMask == COM_RIGHTS_EXECUTE))))
+ {
+ CString szText;
+ CString szTitle;
+
+ szText.LoadString(IDS_The_security_);
+ szTitle.LoadString(IDS_DCOM_Configuration_Warning);
+
+ if (MessageBox(GetForegroundWindow(),
+ (LPCTSTR) szText,
+ (LPCTSTR) szTitle,
+ MB_YESNO) == IDYES)
+ {
+ pAce->Flags = 0;
+ pAce->Type = 0;
+ pAce->AccessMask = COM_RIGHTS_EXECUTE;
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+
+BOOL CUtility::ChangeService(const TCHAR *szService,
+ const TCHAR *szIdentity,
+ const TCHAR *szPassword,
+ const TCHAR *szDisplay)
+{
+ SC_HANDLE hSCManager;
+ SC_HANDLE hService;
+
+ // Open the service control manager
+ if (hSCManager = OpenSCManager(NULL, NULL, GENERIC_READ | GENERIC_WRITE))
+ {
+ // Try to open a handle to the requested service
+ if (!(hService = OpenService(hSCManager,
+ szService,
+ GENERIC_READ | GENERIC_WRITE)))
+ {
+ g_util.PostErrorMessage();
+ CloseServiceHandle(hSCManager);
+ return FALSE;
+ }
+
+ // Close the service manager's database
+ CloseServiceHandle(hSCManager);
+
+ // Change service identity parameters
+ if (ChangeServiceConfig(hService,
+ SERVICE_WIN32_OWN_PROCESS,
+ SERVICE_DEMAND_START,
+ SERVICE_NO_CHANGE,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ szIdentity,
+ szPassword,
+ szDisplay))
+ {
+
+ // Return success
+ CloseServiceHandle(hService);
+ return TRUE;
+ }
+ else
+ {
+ g_util.PostErrorMessage();
+ CloseServiceHandle(hService);
+ return FALSE;
+ }
+ }
+
+ else
+ {
+ g_util.PostErrorMessage();
+ return FALSE;
+ }
+
+}
+
+
+
+
+BOOL CUtility::UpdateDCOMInfo(void)
+{
+ RPC_STATUS status;
+ TCHAR *pszBindString;
+
+ // Get a binding handle to the SCM if we haven't yet
+ if (m_hRpc == NULL)
+ {
+ status = RpcStringBindingCompose(NULL,
+ TEXT("ncalrpc"),
+ NULL,
+ TEXT("epmapper"),
+ NULL,
+ &pszBindString);
+
+ if (status != RPC_S_OK)
+ {
+ return status;
+ }
+
+ status = RpcBindingFromStringBinding(pszBindString, &m_hRpc);
+ RpcStringFree(&pszBindString);
+
+ if (status != ERROR_SUCCESS)
+ {
+ return status;
+ }
+
+ }
+
+ // Call over to the SCM to get the global registry values read
+ // into memory
+ UpdateActivationSettings(m_hRpc, &status);
+ return status;
+}
+
+
+
+LRESULT CALLBACK ControlFixProc( HWND hwnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam);
+
+// This is a work-around because there is a bug in msdev 4.1: Cannot get
+// WM_HELP message processed by a control on which DDX_Control data exchange
+// is done because of subclassing problem. See msdn Q145865 for a discussion
+// plus work-around code.
+void CUtility::FixHelp(CWnd* pWnd)
+{
+ // search all child windows. If their window proc
+ // is AfxWndProc, then subclass with our window proc
+ CWnd* pWndChild = pWnd->GetWindow(GW_CHILD);
+ while(pWndChild != NULL)
+ {
+ if (GetWindowLong(pWndChild->GetSafeHwnd(),
+ GWL_WNDPROC) == (LONG)AfxWndProc)
+ {
+ SetWindowLong(pWndChild->GetSafeHwnd(), GWL_WNDPROC,
+ (LONG)ControlFixProc);
+ }
+ pWndChild = pWndChild->GetWindow(GW_HWNDNEXT);
+ }
+}
+
+
+
+LRESULT CALLBACK ControlFixProc(HWND hwnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam)
+{
+ if (uMsg == WM_HELP)
+ {
+ // bypass MFC's handler, message will be sent to parent
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+ }
+ return AfxWndProc(hwnd,uMsg,wParam,lParam);
+}
+
+
+
+
+// Compare two security descriptors in self-relative form to
+// determine if they're the same
+BOOL CUtility::CompareSDs(PSrSecurityDescriptor pSD1,
+ PSrSecurityDescriptor pSD2)
+{
+ PSID pSid1, pSid2;
+ PSrAcl pDacl1, pDacl2;
+ PSrAce pAce1, pAce2;
+ BYTE *p1, *p2;
+
+ // Compare the owners
+ pSid1 = (PSID) (((BYTE *) pSD1) + pSD1->Owner);
+ pSid2 = (PSID) (((BYTE *) pSD2) + pSD2->Owner);
+ if (!EqualSid(pSid1, pSid2))
+ {
+ return FALSE;
+ }
+
+ // Compare the groups
+ pSid1 = (PSID) (((BYTE *) pSD1) + pSD1->Group);
+ pSid2 = (PSID) (((BYTE *) pSD2) + pSD2->Group);
+ if (!EqualSid(pSid1, pSid2))
+ {
+ return FALSE;
+ }
+
+ // Compare the DACL's
+ pDacl1 = (PSrAcl) (((BYTE *) pSD1) + pSD1->Dacl);
+ pDacl2 = (PSrAcl) (((BYTE *) pSD2) + pSD2->Dacl);
+
+ // Check first that they are the same size and have the same
+ // number of ACE's
+ if (! (pDacl1->AclSize == pDacl2->AclSize &&
+ pDacl1->AceCount == pDacl2->AceCount))
+ {
+ return FALSE;
+ }
+
+ // Now compare the ACL ACE by ACE
+ pAce1 = (PSrAce) (((BYTE *) pDacl1) + sizeof(SSrAcl));
+ pAce2 = (PSrAce) (((BYTE *) pDacl2) + sizeof(SSrAcl));
+ for (int k = 0; k < pDacl1->AceCount; k++)
+ {
+ // Check the ACE headers
+ if (! (pAce1->Type == pAce2->Type &&
+ pAce1->AceSize == pAce2->AceSize &&
+ pAce1->AccessMask == pAce2->AccessMask))
+ {
+ return FALSE;
+ }
+
+ // Check the SID's
+ p1 = (BYTE *) (((BYTE *) pAce1) + sizeof(ACE_HEADER));
+ p2 = (BYTE *) (((BYTE *) pAce2) + sizeof(ACE_HEADER));
+ for (ULONG j = 0; j < pAce1->AceSize - sizeof(ACE_HEADER); j++)
+ {
+ if (p1[j] != p2[j])
+ {
+ return FALSE;
+ }
+ }
+
+ // Go to the next ACE
+ pAce1 = (PSrAce) (((BYTE *) pAce1) + pAce1->AceSize);
+ pAce2 = (PSrAce) (((BYTE *) pAce2) + pAce2->AceSize);
+ }
+
+ return TRUE;
+}
+
+
+
+
+
+int CUtility::SetAccountRights(const TCHAR *szUser, TCHAR *szPrivilege)
+{
+ int err;
+ LSA_HANDLE hPolicy;
+ LSA_OBJECT_ATTRIBUTES objAtt;
+ DWORD cbSid = 1;
+ TCHAR szDomain[MAX_PATH];
+ DWORD cbDomain = MAX_PATH * sizeof(TCHAR);
+ PSID pSid = NULL;
+ SID_NAME_USE snu;
+ LSA_UNICODE_STRING privStr;
+
+ // Get a policy handle
+ memset(&objAtt, 0, sizeof(LSA_OBJECT_ATTRIBUTES));
+ if (!NT_SUCCESS(LsaOpenPolicy(NULL,
+ &objAtt,
+ POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
+ &hPolicy)))
+ {
+ return GetLastError();
+ }
+
+ // Fetch the SID for the specified user
+ LookupAccountName(NULL, szUser, pSid, &cbSid, szDomain, &cbDomain, &snu);
+ if ((err = GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
+ {
+ LsaClose(hPolicy);
+ return err;
+ }
+ pSid = new BYTE[cbSid];
+ if (pSid == NULL)
+ {
+ LsaClose(hPolicy);
+ return ERROR_OUTOFMEMORY;
+ }
+ if (!LookupAccountName(NULL, szUser, pSid, &cbSid,
+ szDomain, &cbDomain, &snu))
+ {
+ LsaClose(hPolicy);
+ return GetLastError();
+ }
+
+ // Set the specified privilege on this account
+ privStr.Length = _tcslen(szPrivilege) * sizeof(TCHAR);
+ privStr.MaximumLength = privStr.Length + sizeof(TCHAR);
+ privStr.Buffer = szPrivilege;
+ if (!NT_SUCCESS(LsaAddAccountRights(hPolicy, pSid, &privStr, 1)))
+ {
+ LsaClose(hPolicy);
+ return GetLastError();
+ }
+
+ // We're done
+ delete pSid;
+ LsaClose(hPolicy);
+ return ERROR_SUCCESS;
+}
+
+
+
+
+
+// This method is included only because in the debug version when using
+// MFC they validate the C++ heap, whereas RtlCopySecurityDescriptor uses
+// the standard process heap, causing MFC to throw a breakpoint
+void CUtility::CopySD(SECURITY_DESCRIPTOR *pSrc, SECURITY_DESCRIPTOR **pDest)
+{
+ ULONG cbLen;
+ SECURITY_DESCRIPTOR *pSD;
+
+ cbLen = RtlLengthSecurityDescriptor(pSrc);
+ pSD = (SECURITY_DESCRIPTOR *) new BYTE[cbLen];
+ *pDest = pSD;
+ if (pSD)
+ {
+ memcpy(pSD, pSrc, cbLen);
+ }
+}
+
+
+
+
+// Set the inheritance flags on a security descriptor so keys created
+// under the key having this security descriptor will inherit all its
+// ACE's. We do this as a utility routine rather than via the ACL
+// editor because doing that adds check boxes and such to the ACL editor,
+// so it's cleaner this way.
+//
+// Note. The security descriptor is expected to be in absolute form
+void CUtility::SetInheritanceFlags(SECURITY_DESCRIPTOR *pSec)
+{
+ PSrAcl pAcl = (PSrAcl) pSec->Dacl;
+ PSrAce pAce;
+ int k;
+
+ // Do over the ACE's this DACL
+ for (k = pAcl->AceCount, pAce = (PSrAce) (((BYTE *) pAcl) + sizeof(SSrAcl));
+ k;
+ k--, pAce = (PSrAce) (((BYTE *) pAce) + pAce->AceSize))
+ {
+ pAce->Flags |= CONTAINER_INHERIT_ACE;
+ }
+}
diff --git a/private/ole32/oleui/util.h b/private/ole32/oleui/util.h
new file mode 100644
index 000000000..930244eb7
--- /dev/null
+++ b/private/ole32/oleui/util.h
@@ -0,0 +1,230 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: util.cpp
+//
+// Contents: Defnes the utility class CUtility
+//
+// Classes:
+//
+// Methods:
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+#ifndef _UTIL_H_
+#define _UTIL_H_
+
+
+#define COM_RIGHTS_EXECUTE 1
+
+
+typedef struct
+{
+ HKEY hRoot;
+ TCHAR *szKeyPath;
+ TCHAR *szValueName;
+} SSingleCallBack;
+
+
+
+typedef struct
+{
+ HKEY hKey;
+ HKEY *phClsids;
+ unsigned cClsids;
+ TCHAR *szTitle;
+} SRegKeyCallBack;
+
+
+
+typedef struct tagCallBackContext
+{
+ PACKETTYPE pktType;
+ int *pIndex;
+ SECURITY_DESCRIPTOR *origSD;
+ union
+ {
+ SSingleCallBack single;
+ SRegKeyCallBack regKey;
+ } info;
+} SCallBackContext, *PCallBackContext;
+
+
+
+typedef struct
+{
+ WORD Control;
+ BYTE Reserved1;
+ BYTE Revision;
+ DWORD Owner;
+ DWORD Group;
+ DWORD Sacl;
+ DWORD Dacl;
+} SSrSecurityDescriptor, *PSrSecurityDescriptor;
+
+
+
+typedef struct
+{
+ BYTE Revision;
+ BYTE Reserved1;
+ WORD AclSize;
+ WORD AceCount;
+ WORD Reserved2;
+} SSrAcl, *PSrAcl;
+
+
+
+typedef struct
+{
+ BYTE Type;
+ BYTE Flags;
+ WORD AceSize;
+ ULONG AccessMask;
+} SSrAce, *PSrAce;
+
+
+
+#define USER_DETAILS_BUFFER_SIZE 1024
+
+typedef struct tagUserDetailsPlus
+{
+ USERDETAILS sUserDetails;
+ BYTE bBuffer[USER_DETAILS_BUFFER_SIZE];
+} SUserDetailsPlus;
+
+
+
+
+class CUtility
+{
+public:
+ CUtility(void);
+
+ ~CUtility(void);
+
+ void PostErrorMessage(void);
+
+ void PostErrorMessage(int err);
+
+ void CkForAccessDenied(int err);
+
+ BOOL CkAccessRights(HKEY hRoot, TCHAR *szKeyPath);
+
+ int WriteRegSzNamedValue(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ TCHAR *szVal,
+ DWORD dwSize);
+
+ int WriteRegDwordNamedValue(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ DWORD dwVal);
+
+ int WriteRegSingleACL(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ PSECURITY_DESCRIPTOR pSec);
+
+ int WriteRegKeyACL(HKEY hKey,
+ HKEY *phClsids,
+ unsigned cClsids,
+ PSECURITY_DESCRIPTOR pSec,
+ PSECURITY_DESCRIPTOR pSecOrig);
+
+ int WriteRegKeyACL2(HKEY hRoot,
+ HKEY hKey,
+ PSECURITY_DESCRIPTOR pSec,
+ PSECURITY_DESCRIPTOR pSecOrig);
+
+ int WriteLsaPassword(CLSID appid,
+ TCHAR *szPassword);
+
+ int WriteSrvIdentity(TCHAR *szService,
+ TCHAR *szIdentity);
+
+ int DeleteRegKey(HKEY hRoot, TCHAR *szKeyPath);
+
+ int DeleteRegValue(HKEY hRoot, TCHAR *szKeyPath, TCHAR *szValueName);
+
+ int ACLEditor(HWND hWnd,
+ HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ int *nIndex,
+ PACKETTYPE pktType,
+ TCHAR *szPermType);
+
+ int ACLEditor2(HWND hWnd,
+ HKEY hKey,
+ HKEY *phClsids,
+ unsigned cClsids,
+ TCHAR *szTitle,
+ int *nIndex,
+ PACKETTYPE pktType);
+
+ BOOL InvokeUserBrowser(HWND hWnd, TCHAR *szUser);
+
+ BOOL InvokeMachineBrowser(TCHAR *szMachine);
+
+ int StringFromGUID(GUID &rguid, TCHAR *lpsz, int cbMax);
+
+ BOOL IsEqualGuid(GUID &guid1, GUID &guid2);
+
+ BOOL AdjustPrivilege(TCHAR *szPrivilege);
+
+ BOOL VerifyRemoteMachine(TCHAR *szRemoteMachine);
+
+ BOOL RetrieveUserPassword(TCHAR *szAppid, CString &sPassword);
+
+ BOOL StoreUserPassword(TCHAR *szAppid, CString &sPassword);
+
+ BOOL LookupProcessInfo(SID **ppSid, TCHAR **ppszPrincName);
+
+ BOOL MakeSecDesc(SID *pSid, SECURITY_DESCRIPTOR **ppSD);
+
+ BOOL ChangeService(const TCHAR *szService,
+ const TCHAR *szIdentity,
+ const TCHAR *szPassword,
+ const TCHAR *szDisplay);
+
+ int UpdateDCOMInfo(void);
+
+ void FixHelp(CWnd* pWnd);
+
+ BOOL CompareSDs(PSrSecurityDescriptor pSD1, PSrSecurityDescriptor pSD2);
+
+ int SetAccountRights(const TCHAR *szUser, TCHAR *szPrivilege);
+
+ void CopySD(SECURITY_DESCRIPTOR *pSrc, SECURITY_DESCRIPTOR **pDest);
+
+ void SetInheritanceFlags(SECURITY_DESCRIPTOR *pSec);
+
+ BOOL CheckForValidSD(SECURITY_DESCRIPTOR *pSD);
+
+ private:
+ BOOL CheckSDForCOM_RIGHTS_EXECUTE(SECURITY_DESCRIPTOR *pSD);
+
+ SCallBackContext m_sCallBackContext;
+ void *m_args[8];
+ HANDLE m_hRpc;
+
+};
+
+
+
+extern CUtility g_util;
+extern HKEY g_hAppid;
+extern HKEY *g_rghkCLSID;
+extern unsigned g_cCLSIDs;
+extern TCHAR *g_szAppTitle;
+extern BOOL g_fReboot;
+extern TCHAR *g_szAppid;
+
+#endif //_UTIL_H_
diff --git a/private/ole32/oleui/version.txt b/private/ole32/oleui/version.txt
new file mode 100644
index 000000000..54b0a4df5
--- /dev/null
+++ b/private/ole32/oleui/version.txt
@@ -0,0 +1,50 @@
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+//VS_VERSION_INFO VERSIONINFO
+// FILEVERSION 1,0,0,1
+// PRODUCTVERSION 1,0,0,1
+// FILEFLAGSMASK 0x3fL
+//#ifdef _DEBUG
+// FILEFLAGS 0x1L
+//#else
+// FILEFLAGS 0x0L
+//#endif
+// FILEOS 0x4L
+// FILETYPE 0x1L
+// FILESUBTYPE 0x0L
+//BEGIN
+// BLOCK "StringFileInfo"
+// BEGIN
+// BLOCK "040904b0"
+// BEGIN
+// VALUE "CompanyName", "\0"
+// VALUE "FileDescription", "OLE Configuration UI\0"
+// VALUE "FileVersion", "1, 0, 0, 1\0"
+// VALUE "InternalName", "OLEUI\0"
+// VALUE "LegalCopyright", "Copyright (c) 1996\0"
+// VALUE "OriginalFilename", "OLEUI.EXE\0"
+// VALUE "ProductName", "OLE Configuration Application\0"
+// VALUE "ProductVersion", "1, 0, 0, 1\0"
+// END
+// END
+// BLOCK "VarFileInfo"
+// BEGIN
+// VALUE "Translation", 0x409, 1200
+// END
+//END
+
+// The following conforms to Windows NT version resources
+#include <winver.h>
+#include <ntverp.h>
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Distributed COM Configuration"
+#define VER_INTERNALNAME_STR "dcomcnfg.exe"
+#define VER_ORIGINALFILENAME_STR "dcomcnfg.exe"
+#include <common.ver>
+
+#endif // !_MAC \ No newline at end of file
diff --git a/private/ole32/oleui/virtreg.cpp b/private/ole32/oleui/virtreg.cpp
new file mode 100644
index 000000000..9a32f0853
--- /dev/null
+++ b/private/ole32/oleui/virtreg.cpp
@@ -0,0 +1,783 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: virtreg.cpp
+//
+// Contents: Implements the class CVirtualRegistry which manages a
+// virtual registry
+//
+// Classes:
+//
+// Methods: CVirtualRegistry::CVirtualRegistry
+// CVirtualRegistry::~CVirtualRegistry
+// CVirtualRegistry::ReadRegSzNamedValue
+// CVirtualRegistry::NewRegSzNamedValue
+// CVirtualRegistry::ChgRegSzNamedValue
+// CVirtualRegistry::ReadRegDwordNamedValue
+// CVirtualRegistry::NewRegDwordNamedValue
+// CVirtualRegistry::ChgRegDwordNamedValue
+// CVirtualRegistry::NewRegSingleACL
+// CVirtualRegistry::ChgRegACL
+// CVirtualRegistry::NewRegKeyACL
+// CVirtualRegistry::ReadLsaPassword
+// CVirtualRegistry::NewLsaPassword
+// CVirtualRegistry::ChgLsaPassword
+// CVirtualRegistry::ReadSrvIdentity
+// CVirtualRegistry::NewSrvIdentity
+// CVirtualRegistry::ChgSrvIdentity
+// CVirtualRegistry::MarkForDeletion
+// CVirtualRegistry::GetAt
+// CVirtualRegistry::Remove
+// CVirtualRegistry::Cancel
+// CVirtualRegistry::Apply
+// CVirtualRegistry::ApplyAll
+// CVirtualRegistry::Ok
+// CVirtualRegistry::SearchForRegEntry
+// CVirtualRegistry::SearchForLsaEntry
+// CVirtualRegistry::SearchForSrvEntry
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+#include "stdafx.h"
+#include "afxtempl.h"
+#include "assert.h"
+extern "C"
+{
+#include "ntlsa.h"
+}
+#include "winsvc.h"
+#include "types.h"
+#include "datapkt.h"
+extern "C"
+{
+#include <getuser.h>
+}
+#include "util.h"
+#include "virtreg.h"
+
+
+
+
+CVirtualRegistry::CVirtualRegistry(void)
+{
+ m_pkts.SetSize(0, 8);
+}
+
+
+
+CVirtualRegistry::~CVirtualRegistry(void)
+{
+
+}
+
+
+
+
+// Read a named string value from the registry and cache it
+int CVirtualRegistry::ReadRegSzNamedValue(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ int *pIndex)
+{
+ int err;
+ HKEY hKey;
+ ULONG lSize;
+ DWORD dwType;
+ TCHAR *szVal = new TCHAR[MAX_PATH];
+
+ // Check if we already have an entry for this
+ *pIndex = SearchForRegEntry(hRoot, szKeyPath, szValueName);
+ if (*pIndex >= 0)
+ {
+ CDataPacket &cdp = GetAt(*pIndex);
+ if (cdp.fDelete)
+ {
+ *pIndex = -1;
+ delete szVal;
+ return ERROR_FILE_NOT_FOUND;
+ }
+ else
+ {
+ delete szVal;
+ return ERROR_SUCCESS;
+ }
+ }
+
+ // Open the referenced key
+ if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey)) != ERROR_SUCCESS)
+ {
+ g_util.CkForAccessDenied(err);
+ delete szVal;
+ return err;
+ }
+
+ // Attempt to read the named value
+ lSize = MAX_PATH * sizeof(TCHAR);
+ if ((err = RegQueryValueEx(hKey, szValueName, NULL, &dwType, (BYTE *) szVal,
+ &lSize))
+ != ERROR_SUCCESS)
+ {
+ g_util.CkForAccessDenied(err);
+ if (hKey != hRoot)
+ {
+ RegCloseKey(hKey);
+ }
+ delete szVal;
+ return err;
+ }
+
+ // Build a data packet
+ if (dwType == REG_SZ)
+ {
+ *pIndex = m_pkts.Add(CDataPacket(hRoot, szKeyPath,
+ szValueName, szVal));
+ CDataPacket &cdp = m_pkts.ElementAt(*pIndex);
+ cdp.fDirty = FALSE;
+ delete szVal;
+ return ERROR_SUCCESS;
+ }
+ else
+ {
+ delete szVal;
+ return ERROR_BAD_TOKEN_TYPE;
+ }
+}
+
+
+int CVirtualRegistry::NewRegSzNamedValue(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ TCHAR *szVal,
+ int *pIndex)
+{
+ // It may be in the virtual registry but marked for deletion
+ *pIndex = SearchForRegEntry(hRoot, szKeyPath, szValueName);
+ if (*pIndex >= 0)
+ {
+ CDataPacket &cdp = GetAt(*pIndex);
+ if (cdp.fDelete)
+ {
+ cdp.fDelete = FALSE;
+ }
+ delete cdp.pkt.nvsz.szValue;
+ cdp.pkt.nvsz.szValue = (TCHAR *) new TCHAR[_tcslen(szVal) + 1];
+ _tcscpy(cdp.pkt.nvsz.szValue, szVal);
+ return ERROR_SUCCESS;
+ }
+
+ // Build a data packet and add it
+ *pIndex = m_pkts.Add(CDataPacket(hRoot, szKeyPath,
+ szValueName, szVal));
+
+ return ERROR_SUCCESS;
+}
+
+
+
+void CVirtualRegistry::ChgRegSzNamedValue(int nIndex, TCHAR *szVal)
+{
+ CDataPacket &cdp = m_pkts.ElementAt(nIndex);
+
+ delete cdp.pkt.nvsz.szValue;
+ cdp.pkt.nvsz.szValue = new TCHAR[_tcslen(szVal) + 1];
+ _tcscpy(cdp.pkt.nvsz.szValue, szVal);
+ cdp.fDirty = TRUE;
+}
+
+
+
+// Read a named DWORD value from the registry
+int CVirtualRegistry::ReadRegDwordNamedValue(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ int *pIndex)
+{
+ int err;
+ HKEY hKey;
+ ULONG lSize;
+ DWORD dwType;
+ DWORD dwVal;
+
+ // Check if we already have an entry for this
+ *pIndex = SearchForRegEntry(hRoot, szKeyPath, szValueName);
+ if (*pIndex >= 0)
+ {
+ return ERROR_SUCCESS;
+ }
+
+ // Open the referenced key
+ if ((err = RegOpenKeyEx(hRoot, szKeyPath, 0, KEY_ALL_ACCESS, &hKey)) != ERROR_SUCCESS)
+ {
+ g_util.CkForAccessDenied(err);
+ return err;
+ }
+
+ // Attempt to read the named value
+ lSize = sizeof(DWORD);
+ if ((err = RegQueryValueEx(hKey, szValueName, NULL, &dwType, (BYTE *) &dwVal,
+ &lSize))
+ != ERROR_SUCCESS)
+ {
+ g_util.CkForAccessDenied(err);
+ if (hKey != hRoot)
+ {
+ RegCloseKey(hKey);
+ }
+ return err;
+ }
+
+ // Close the registry key
+ if (hKey != hRoot)
+ {
+ RegCloseKey(hKey);
+ }
+
+ // Build a data packet
+ if (dwType == REG_DWORD)
+ {
+ *pIndex = m_pkts.Add(CDataPacket(hRoot, szKeyPath,
+ szValueName, dwVal));
+ CDataPacket &cdp = m_pkts.ElementAt(*pIndex);
+ cdp.fDirty = FALSE;
+
+ return ERROR_SUCCESS;
+ }
+ else
+ {
+ return ERROR_BAD_TOKEN_TYPE;
+ }
+}
+
+
+
+int CVirtualRegistry::NewRegDwordNamedValue(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ DWORD dwVal,
+ int *pIndex)
+{
+ // It may be in the virtual registry but marked for deletion
+ *pIndex = SearchForRegEntry(hRoot, szKeyPath, szValueName);
+ if (*pIndex >= 0)
+ {
+ CDataPacket &cdp = GetAt(*pIndex);
+ if (cdp.fDelete)
+ {
+ cdp.fDelete = FALSE;
+ }
+ cdp.pkt.nvdw.dwValue = dwVal;
+ return ERROR_SUCCESS;
+ }
+
+ // Build a data packet and add it
+ *pIndex = m_pkts.Add(CDataPacket(hRoot, szKeyPath,
+ szValueName, dwVal));
+ return ERROR_SUCCESS;
+}
+
+
+void CVirtualRegistry::ChgRegDwordNamedValue(int nIndex, DWORD dwVal)
+{
+ CDataPacket &cdp = m_pkts.ElementAt(nIndex);
+
+ cdp.pkt.nvdw.dwValue = dwVal;
+ cdp.fDirty = TRUE;
+}
+
+
+int CVirtualRegistry::NewRegSingleACL(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ SECURITY_DESCRIPTOR *pacl,
+ BOOL fSelfRelative,
+ int *pIndex)
+{
+ // Build a data packet and add it
+ *pIndex = m_pkts.Add(CDataPacket(hRoot, szKeyPath, szValueName,
+ pacl, fSelfRelative));
+ return ERROR_SUCCESS;
+}
+
+
+void CVirtualRegistry::ChgRegACL(int nIndex,
+ SECURITY_DESCRIPTOR *pacl,
+ BOOL fSelfRelative)
+{
+ UINT cbSid = RtlLengthSid(pacl);
+ CDataPacket &cdp = m_pkts.ElementAt(nIndex);
+
+ cdp.ChgACL(pacl, fSelfRelative);
+ cdp.fDirty = TRUE;
+}
+
+
+
+int CVirtualRegistry::NewRegKeyACL(HKEY hKey,
+ HKEY *phClsids,
+ unsigned cClsids,
+ TCHAR *szTitle,
+ SECURITY_DESCRIPTOR *paclOrig,
+ SECURITY_DESCRIPTOR *pacl,
+ BOOL fSelfRelative,
+ int *pIndex)
+{
+ // Build a data packet and add it
+ *pIndex = m_pkts.Add(CDataPacket(hKey, phClsids, cClsids, szTitle,
+ paclOrig, pacl, fSelfRelative));
+ return ERROR_SUCCESS;
+}
+
+
+
+int CVirtualRegistry::ReadLsaPassword(CLSID &clsid,
+ int *pIndex)
+{
+ LSA_OBJECT_ATTRIBUTES sObjAttributes;
+ HANDLE hPolicy = NULL;
+ LSA_UNICODE_STRING sKey;
+ TCHAR szKey[GUIDSTR_MAX + 5];
+ PLSA_UNICODE_STRING psPassword;
+
+
+ // Check if we already have an entry fo this
+ *pIndex = SearchForLsaEntry(clsid);
+ if (*pIndex >= 0)
+ {
+ return ERROR_SUCCESS;
+ }
+
+ // Formulate the access key
+ lstrcpyW(szKey, L"SCM:");
+ g_util.StringFromGUID(clsid, &szKey[4], GUIDSTR_MAX);
+ szKey[GUIDSTR_MAX + 4] = L'\0';
+
+ // UNICODE_STRING length fields are in bytes and include the NULL
+ // terminator
+ sKey.Length = (lstrlenW(szKey) + 1) * sizeof(WCHAR);
+ sKey.MaximumLength = (GUIDSTR_MAX + 5) * sizeof(WCHAR);
+ sKey.Buffer = szKey;
+
+ // Open the local security policy
+ InitializeObjectAttributes(&sObjAttributes, NULL, 0L, NULL, NULL);
+ if (!NT_SUCCESS(LsaOpenPolicy(NULL, &sObjAttributes,
+ POLICY_GET_PRIVATE_INFORMATION, &hPolicy)))
+ {
+ return GetLastError();
+ }
+
+ // Read the user's password
+ if (!NT_SUCCESS(LsaRetrievePrivateData(hPolicy, &sKey, &psPassword)))
+ {
+ LsaClose(hPolicy);
+ return GetLastError();
+ }
+
+ // Close the policy handle, we're done with it now.
+ LsaClose(hPolicy);
+
+ // Build a data packet
+ *pIndex = m_pkts.Add(CDataPacket(psPassword->Buffer, clsid));
+ CDataPacket &cdp = m_pkts.ElementAt(*pIndex);
+ cdp.fDirty = FALSE;
+
+ return ERROR_SUCCESS;
+}
+
+
+
+int CVirtualRegistry::NewLsaPassword(CLSID &clsid,
+ TCHAR *szPassword,
+ int *pIndex)
+{
+ // Build a data packet and add it
+ *pIndex = m_pkts.Add(CDataPacket(szPassword, clsid));
+ return ERROR_SUCCESS;
+}
+
+
+
+void CVirtualRegistry::ChgLsaPassword(int nIndex,
+ TCHAR *szPassword)
+{
+ CDataPacket &cdp = m_pkts.ElementAt(nIndex);
+
+ delete cdp.pkt.pw.szPassword;
+ cdp.pkt.pw.szPassword = new TCHAR[_tcslen(szPassword) + 1];
+ _tcscpy(cdp.pkt.pw.szPassword, szPassword);
+ cdp.fDirty = TRUE;
+}
+
+
+
+int CVirtualRegistry::ReadSrvIdentity(TCHAR *szService,
+ int *pIndex)
+{
+ SC_HANDLE hSCManager;
+ SC_HANDLE hService;
+ QUERY_SERVICE_CONFIG sServiceQueryConfig;
+ DWORD dwSize;
+
+
+ // Check if we already have an entry fo this
+ *pIndex = SearchForSrvEntry(szService);
+ if (*pIndex >= 0)
+ {
+ return ERROR_SUCCESS;
+ }
+
+ // Open the service control manager
+ if (hSCManager = OpenSCManager(NULL, NULL, GENERIC_READ))
+ {
+ // Open a handle to the requested service
+ if (hService = OpenService(hSCManager, szService, GENERIC_READ))
+ {
+ // Close the service manager's database
+ CloseServiceHandle(hSCManager);
+
+ // Query the service
+ if (QueryServiceConfig(hService, &sServiceQueryConfig,
+ sizeof(SERVICE_QUERY_CONFIG), &dwSize))
+ {
+ // Build a data packet
+ *pIndex = m_pkts.Add(CDataPacket(szService,
+ sServiceQueryConfig.lpServiceStartName));
+ CDataPacket &cdp = m_pkts.ElementAt(*pIndex);
+ cdp.fDirty = FALSE;
+
+ // Return success
+ CloseServiceHandle(hSCManager);
+ CloseServiceHandle(hService);
+ return ERROR_SUCCESS;
+ }
+ }
+ CloseServiceHandle(hSCManager);
+ }
+
+ return GetLastError();
+}
+
+
+
+int CVirtualRegistry::NewSrvIdentity(TCHAR *szService,
+ TCHAR *szIdentity,
+ int *pIndex)
+{
+ // Build a data packet and add it
+ *pIndex = m_pkts.Add(CDataPacket(szService, szIdentity));
+ return ERROR_SUCCESS;
+}
+
+
+
+void CVirtualRegistry::ChgSrvIdentity(int nIndex,
+ TCHAR *szIdentity)
+{
+ CDataPacket &cdp = m_pkts.ElementAt(nIndex);
+
+ delete cdp.pkt.si.szIdentity;
+ cdp.pkt.si.szIdentity = new TCHAR[_tcslen(szIdentity) + 1];
+ _tcscpy(cdp.pkt.si.szIdentity, szIdentity);
+ cdp.fDirty = TRUE;
+}
+
+
+
+void CVirtualRegistry::MarkForDeletion(int nIndex)
+{
+ CDataPacket &cdp = GetAt(nIndex);
+ cdp.fDelete = TRUE;
+ cdp.fDirty = TRUE;
+}
+
+
+
+
+CDataPacket &CVirtualRegistry::GetAt(int nIndex)
+{
+ return m_pkts.ElementAt(nIndex);
+}
+
+
+
+
+void CVirtualRegistry::Remove(int nIndex)
+{
+ CDataPacket &cdb = GetAt(nIndex);
+
+ if (cdb.fDirty)
+ {
+ switch (cdb.tagType)
+ {
+ case NamedValueSz:
+ delete cdb.pkt.nvsz.szKeyPath;
+ delete cdb.pkt.nvsz.szValueName;
+ delete cdb.pkt.nvsz.szValue;
+ break;
+
+ case NamedValueDword:
+ delete cdb.pkt.nvdw.szKeyPath;
+ delete cdb.pkt.nvdw.szValueName;
+ break;
+
+ case SingleACL:
+ delete cdb.pkt.acl.szKeyPath;
+ delete cdb.pkt.acl.szValueName;
+ delete cdb.pkt.acl.pSec;
+ break;
+
+ case RegKeyACL:
+ delete cdb.pkt.racl.pSec;
+ break;
+
+ case Password:
+ delete cdb.pkt.pw.szPassword;
+ break;
+
+ case ServiceIdentity:
+ delete cdb.pkt.si.szServiceName;
+ delete cdb.pkt.si.szIdentity;
+ break;
+ }
+ }
+
+ m_pkts.SetAt(nIndex, CDataPacket());
+}
+
+
+
+
+void CVirtualRegistry::RemoveAll(void)
+{
+ int nSize = m_pkts.GetSize();
+ for (int k = 0; k < nSize; k++)
+ {
+ Remove(k);
+ }
+
+ m_pkts.RemoveAll();
+}
+
+
+
+
+void CVirtualRegistry::Cancel(int nIndex)
+{
+ int nSize = m_pkts.GetSize();
+
+ for (int k = nIndex; k < nSize; k++)
+ {
+ m_pkts.SetAt(nIndex, CDataPacket());
+ }
+}
+
+
+
+int CVirtualRegistry::Apply(int nIndex)
+{
+ int err = ERROR_SUCCESS;
+ int nSize = m_pkts.GetSize();
+ CDataPacket &cdp = m_pkts.ElementAt(nIndex);
+
+ if (cdp.fDirty)
+ {
+ switch (cdp.tagType)
+ {
+ case Empty:
+ break;
+
+ case NamedValueSz:
+ if (cdp.fDelete)
+ {
+ g_util.DeleteRegValue(cdp.pkt.nvsz.hRoot,
+ cdp.pkt.nvsz.szKeyPath,
+ cdp.pkt.nvsz.szValueName);
+ }
+ else
+ {
+ err = g_util.WriteRegSzNamedValue(cdp.pkt.nvsz.hRoot,
+ cdp.pkt.nvsz.szKeyPath,
+ cdp.pkt.nvsz.szValueName,
+ cdp.pkt.nvsz.szValue,
+ wcslen(cdp.pkt.nvsz.szValue) + 1);
+ }
+ break;
+
+ case NamedValueDword:
+ if (cdp.fDelete)
+ {
+ g_util.DeleteRegValue(cdp.pkt.nvdw.hRoot,
+ cdp.pkt.nvdw.szKeyPath,
+ cdp.pkt.nvdw.szValueName);
+ }
+ else
+ {
+ err = g_util.WriteRegDwordNamedValue(cdp.pkt.nvdw.hRoot,
+ cdp.pkt.nvdw.szKeyPath,
+ cdp.pkt.nvdw.szValueName,
+ cdp.pkt.nvdw.dwValue);
+ }
+ break;
+
+ case SingleACL:
+ if (cdp.fDelete)
+ {
+ HKEY hKey;
+
+ if (RegOpenKeyEx(cdp.pkt.acl.hRoot,
+ cdp.pkt.acl.szKeyPath,
+ 0,
+ KEY_ALL_ACCESS,
+ &hKey) == ERROR_SUCCESS)
+ {
+ RegDeleteValue(hKey, cdp.pkt.acl.szValueName);
+ RegCloseKey(hKey);
+ }
+ }
+ else
+ {
+ err = g_util.WriteRegSingleACL(cdp.pkt.acl.hRoot,
+ cdp.pkt.acl.szKeyPath,
+ cdp.pkt.acl.szValueName,
+ cdp.pkt.acl.pSec);
+ }
+ break;
+
+ case RegKeyACL:
+ err = g_util.WriteRegKeyACL(cdp.pkt.racl.hKey,
+ cdp.pkt.racl.phClsids,
+ cdp.pkt.racl.cClsids,
+ cdp.pkt.racl.pSec,
+ cdp.pkt.racl.pSecOrig);
+ break;
+
+ case Password:
+ err = g_util.WriteLsaPassword(cdp.pkt.pw.appid,
+ cdp.pkt.pw.szPassword);
+ break;
+
+ case ServiceIdentity:
+ err = g_util.WriteSrvIdentity(cdp.pkt.si.szServiceName,
+ cdp.pkt.si.szIdentity);
+ break;
+ }
+ }
+
+ // Cleanup work
+ if (err == ERROR_SUCCESS)
+ {
+ cdp.fDirty = FALSE;
+ }
+ else
+ {
+ if (err == ERROR_ACCESS_DENIED)
+ {
+ g_util.CkForAccessDenied(ERROR_ACCESS_DENIED);
+ }
+ else
+ {
+ g_util.PostErrorMessage();
+ }
+ }
+ return err;;
+}
+
+
+
+
+
+
+
+int CVirtualRegistry::ApplyAll(void)
+{
+ int nSize = m_pkts.GetSize();
+
+ // Persist all non-empty data packets
+ for (int k = 0; k < nSize; k++)
+ {
+ Apply(k);
+ }
+
+ return ERROR_SUCCESS;
+}
+
+
+
+
+int CVirtualRegistry::Ok(int nIndex)
+{
+ return 0;
+}
+
+
+
+
+int CVirtualRegistry::SearchForRegEntry(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName)
+{
+ int nSize = m_pkts.GetSize();
+
+ for (int k = 0; k < nSize; k++)
+ {
+ CDataPacket &cdp = GetAt(k);
+ if ((cdp.tagType == NamedValueSz &&
+ cdp.pkt.nvsz.hRoot == hRoot &&
+ (_tcscmp(cdp.pkt.nvsz.szKeyPath, szKeyPath) == 0) &&
+ (_tcscmp(cdp.pkt.nvsz.szValueName, szValueName) == 0)) ||
+ (cdp.tagType == NamedValueDword &&
+ cdp.pkt.nvdw.hRoot == hRoot &&
+ (_tcscmp(cdp.pkt.nvdw.szKeyPath, szKeyPath) == 0) &&
+ (_tcscmp(cdp.pkt.nvdw.szValueName, szValueName) == 0)))
+ {
+ return k;
+ }
+ }
+
+ return -1;
+}
+
+
+
+
+int CVirtualRegistry::SearchForLsaEntry(CLSID appid)
+{
+ int nSize = m_pkts.GetSize();
+
+ for (int k = 0; k < nSize; k++)
+ {
+ CDataPacket &cdp = GetAt(k);
+ if (cdp.tagType == Password &&
+ g_util.IsEqualGuid(cdp.pkt.pw.appid, appid))
+ {
+ return k;
+ }
+ }
+
+ return -1;
+}
+
+
+
+
+int CVirtualRegistry::SearchForSrvEntry(TCHAR *szServiceName)
+{
+ int nSize = m_pkts.GetSize();
+
+ for (int k = 0; k < nSize; k++)
+ {
+ CDataPacket &cdp = GetAt(k);
+ if (cdp.tagType == ServiceIdentity &&
+ (_tcscmp(cdp.pkt.si.szServiceName, szServiceName)))
+ {
+ return k;
+ }
+ }
+
+ return -1;
+}
+
diff --git a/private/ole32/oleui/virtreg.h b/private/ole32/oleui/virtreg.h
new file mode 100644
index 000000000..afde07262
--- /dev/null
+++ b/private/ole32/oleui/virtreg.h
@@ -0,0 +1,137 @@
+//+---------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993 - 1994.
+//
+// File: virtreg.h
+//
+// Contents: Defines the class CVirtualRegistry which manages a
+// virtual registry
+//
+// Classes:
+//
+// Methods:
+//
+// History: 23-Apr-96 BruceMa Created.
+//
+//----------------------------------------------------------------------
+
+
+
+#ifndef _VIRTREG_H_
+#define _VIRTREG_H_
+
+class CVirtualRegistry
+
+{
+ public:
+ CVirtualRegistry(void);
+ ~CVirtualRegistry(void);
+
+ int ReadRegSzNamedValue(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ int *pIndex);
+
+ int NewRegSzNamedValue(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ TCHAR *szVal,
+ int *pIndex);
+
+ void ChgRegSzNamedValue(int nIndex,
+ TCHAR *szVal);
+
+
+ int ReadRegDwordNamedValue(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ int *pIndex);
+
+ int NewRegDwordNamedValue(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ DWORD dwVal,
+ int *pIndex);
+
+ void ChgRegDwordNamedValue(int nIndex,
+ DWORD dwVal);
+
+
+ int NewRegSingleACL(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName,
+ SECURITY_DESCRIPTOR *pacl,
+ BOOL fSelfRelative,
+ int *pIndex);
+
+ void ChgRegACL(int nIndex,
+ SECURITY_DESCRIPTOR *pacl,
+ BOOL fSelfRelative);
+
+
+ int NewRegKeyACL(HKEY hKey,
+ HKEY *phClsids,
+ unsigned cClsids,
+ TCHAR *szTitle,
+ SECURITY_DESCRIPTOR *paclOrig,
+ SECURITY_DESCRIPTOR *pacl,
+ BOOL fSelfRelative,
+ int *pIndex);
+
+
+ int ReadLsaPassword(CLSID &clsid,
+ int *pIndex);
+
+ int NewLsaPassword(CLSID &clsid,
+ TCHAR *szPassword,
+ int *pIndex);
+
+ void ChgLsaPassword(int nIndex,
+ TCHAR *szPassword);
+
+
+ int ReadSrvIdentity(TCHAR *szService,
+ int *pIndex);
+
+ int NewSrvIdentity(TCHAR *szService,
+ TCHAR *szIdentity,
+ int *pIndex);
+
+ void ChgSrvIdentity(int nIndex,
+ TCHAR *szIdentity);
+
+ void MarkForDeletion(int nIndex);
+
+ CDataPacket &GetAt(int nIndex);
+
+ void Remove(int nIndex);
+
+ void RemoveAll(void);
+
+ void Cancel(int nIndex);
+
+ int Apply(int nIndex);
+
+ int ApplyAll(void);
+
+ int Ok(int nIndex);
+
+
+ private:
+ int SearchForRegEntry(HKEY hRoot,
+ TCHAR *szKeyPath,
+ TCHAR *szValueName);
+
+ int SearchForLsaEntry(CLSID appid);
+
+ int SearchForSrvEntry(TCHAR *szServiceName);
+
+ CArray<CDataPacket, CDataPacket> m_pkts;
+};
+
+
+
+extern CVirtualRegistry g_virtreg;
+
+#endif //_VIRTREG_H_
diff --git a/private/ole32/stdclass/dirs b/private/ole32/stdclass/dirs
new file mode 100644
index 000000000..4815844da
--- /dev/null
+++ b/private/ole32/stdclass/dirs
@@ -0,0 +1,4 @@
+DIRS=
+
+OPTIONAL_DIRS=
+
diff --git a/private/ole32/stdclass/stdclass.cxx b/private/ole32/stdclass/stdclass.cxx
new file mode 100644
index 000000000..3c6229a57
--- /dev/null
+++ b/private/ole32/stdclass/stdclass.cxx
@@ -0,0 +1,290 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: stdclass.cxx
+//
+// Contents: Implementation for standard base class for factory objects
+//
+// Classes: CStdClassFactory
+//
+// Functions: DllGetClassObject
+// DllCanUnloadNow
+//
+// History: 28-May-93 MikeSe Created
+// 2-Jul-93 ShannonC Split into CStdFactory and CStdClassFactory
+//
+//--------------------------------------------------------------------------
+
+#include <stdclass.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Global data
+//
+//--------------------------------------------------------------------------
+
+
+CStdClassFactory * CStdClassFactory::_gpcfFirst = NULL;
+ULONG CStdClassFactory::_gcDllRefs = 0;
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllGetClassObject
+//
+// Synopsis: Standard implementation of entrypoint required by binder.
+//
+// Arguments: [rclsid] -- class id to find
+// [riid] -- interface to return
+// [ppv] -- output pointer
+//
+// Returns: E_UNEXPECTED if class not found
+// Otherwise, whatever is returned by the class's QI
+//
+// Algorithm: Searches the linked list for the required class.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI DllGetClassObject (
+ REFCLSID rclsid,
+ REFIID riid,
+ LPVOID FAR* ppv )
+{
+ HRESULT hr;
+
+ // Note: this doesn't need to be reentrancy protected either
+ // as the linked list is fixed post-init.
+
+ CStdClassFactory * pcfTry = CStdClassFactory::_gpcfFirst;
+
+ while ( pcfTry != NULL &&
+ !IsEqualCLSID ( rclsid, pcfTry->_rcls ) )
+ {
+ pcfTry = pcfTry->_pcfNext;
+ }
+
+ if ( pcfTry != NULL )
+ {
+ // Note: QueryInterface is supposed (required) to do an AddRef
+ // so we don't need to directly.
+ hr = pcfTry->QueryInterface ( riid, ppv );
+ }
+ else
+ {
+ // BUGBUG: didn't find the class. What is the correct error code
+ // to return in such circumstances?
+ hr = E_UNEXPECTED;
+ *ppv = NULL;
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllCanUnloadNow
+//
+// Synopsis: Standard entrypoint required by binder
+//
+// Returns: S_OK if DLL reference count is zero
+// S_FALSE otherwise
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI DllCanUnloadNow ()
+{
+ // BUGBUG: I don't know how to code this in a multi-thread safe way
+ // probably because there isn't one.
+
+ return (CStdClassFactory::_gcDllRefs==0)? S_OK: S_FALSE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllAddRef
+//
+// Synopsis: Allows incrementing the DLL reference count without
+// AddRef'ing a specific class object.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(void) DllAddRef ()
+{
+ InterlockedIncrement ( (LONG*)&CStdClassFactory::_gcDllRefs );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllRelease
+//
+// Synopsis: Allows decrementing the DLL reference count without
+// Release'ing a specific class object.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+STDAPI_(void) DllRelease ()
+{
+ InterlockedDecrement ( (LONG*)&CStdClassFactory::_gcDllRefs );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CStdClassFactory::CStdClassFactory
+//
+// Synopsis: Constructor
+//
+// Effects: Initialises member variables
+// Adds object to global linked list.
+//
+// Arguments: [rcls] -- class id of derived class
+// [punk] -- controlling IUnknown of derived class
+//
+// Notes: Do not make this function inline, even though it appears
+// trivial, since it is necessary to force the static library
+// to be pulled in.
+//
+//--------------------------------------------------------------------------
+
+CStdClassFactory::CStdClassFactory (
+ REFCLSID rcls )
+ :_rcls(rcls),
+ _cRefs(1) // DaveStr - 11/3/94 - Ole32 requires (_cRefs >= 1)
+{
+ // Note: the following is not protected against reentrancy, since it
+ // is assumed to take place prior to LibMain/main/WinMain.
+
+ _pcfNext = _gpcfFirst;
+ _gpcfFirst = this;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CStdClassFactory::LockServer
+//
+// Synopsis: ???
+//
+// Derivation: IClassFactory
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CStdClassFactory::LockServer (
+ BOOL fLock )
+{
+ // BUGBUG: what to do?
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CStdClassFactory::CreateInstance, public
+//
+// Synopsis: Creates a new instance and returns the requested interface.
+// The returned object has a reference count of 1.
+//
+// Derivation: IClassFactory
+//
+// Note: Calls the pure virtual method _CreateInstance, which must
+// be implemented by subclasses.
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CStdClassFactory::CreateInstance (
+ IUnknown* punkOuter,
+ REFIID iidInterface,
+ void** ppv )
+{
+ return _CreateInstance ( punkOuter, iidInterface, ppv );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CStdClassFactory::QueryInterface, public
+//
+// Synopsis: Query for an interface on the class factory.
+//
+// Derivation: IUnknown
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CStdClassFactory::QueryInterface (
+ REFIID iid,
+ void * * ppv )
+{
+ HRESULT hr;
+
+ if ((IsEqualIID(iid, IID_IUnknown)) ||
+ (IsEqualIID(iid, IID_IClassFactory)))
+ {
+ *ppv = (IClassFactory*)this;
+ AddRef();
+ hr = S_OK;
+ }
+ else
+ {
+ // Make sure we null the return value in case of error
+ *ppv = NULL;
+ hr = _QueryInterface ( iid, ppv );
+ }
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CStdClassFactory::_QueryInterface, protected
+//
+// Synopsis: Default private QI, normally overridden in subclass
+//
+// Derivation: IUnknown
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CStdClassFactory::_QueryInterface (
+ REFIID iid,
+ void * * ppv )
+{
+ return E_NOINTERFACE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CStdClassFactory::AddRef, public
+//
+// Synopsis: Increment DLL and object reference counts
+//
+// Derivation: IUnknown
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CStdClassFactory::AddRef ()
+{
+ InterlockedIncrement ( (LONG*)&_gcDllRefs );
+ return (ULONG)InterlockedIncrement ( (LONG*)&_cRefs );
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CStdClassFactory::Release, public
+//
+// Synopsis: Decrement DLL and object reference counts
+//
+// Derivation: IUnknown
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CStdClassFactory::Release ()
+{
+ InterlockedDecrement ( (LONG*)&_gcDllRefs );
+ return (ULONG)InterlockedDecrement ( (LONG*)&_cRefs );
+}
+
+
diff --git a/private/ole32/stg/async/chicago.inc b/private/ole32/stg/async/chicago.inc
new file mode 100644
index 000000000..f3c21db2a
--- /dev/null
+++ b/private/ole32/stg/async/chicago.inc
@@ -0,0 +1,32 @@
+# This is the global include file for the daytona version of CairOLE.
+# It is included by all project sources files.
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DFLAT \
+ -DWIN32=200 \
+ -D_CHICAGO_=200 \
+ -DINC_OLE2 \
+ -DNOEXCEPTIONS \
+ -DCAIROLE_DOWNLEVEL \
+ -DSTRICT \
+ -DNEWPROPS \
+ $(TRACELOG)
+
+# DECLSPEC_IMPORT control (see objbase.h)
+!if "$(MINORCOMP)"=="com" || "$(MINORCOMP)"=="stg" || "$(MINORCOMP)"=="ole232"
+C_DEFINES= \
+ $(C_DEFINES) \
+ -D_OLE32_
+!endif
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+
+CHICAGO_PRODUCT=1
+
+NTLIBCPATH=$(_WINBASE)\Dev\Tools\Lego\Lib
+
+GPCH_BUILD=chicago
+
+NTLEGO=1
diff --git a/private/ole32/stg/async/cruntime.cxx b/private/ole32/stg/async/cruntime.cxx
new file mode 100644
index 000000000..9284cdf85
--- /dev/null
+++ b/private/ole32/stg/async/cruntime.cxx
@@ -0,0 +1,201 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: cruntime.cxx
+//
+// Contents: Implementation of Cruntimes that we need since we
+// can't use MSVCRT and WIn95 doesn't implement the lstr*W
+// versions. (well, it implements them but they are just stubs)
+//
+//
+// Functions: Laylstrcmp
+// Laylstrcpy
+// Laylstrcpyn
+// Laylstrlen
+// Laylstrcat
+//
+// History: 20-Jun-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+#pragma hdrstop
+#include <string.h>
+
+/***
+* Laylstrcmp - compare two wchar_t strings,
+* returning less than, equal to, or greater than
+*
+*Purpose:
+* wcscmp compares two wide-character strings and returns an integer
+* to indicate whether the first is less than the second, the two are
+* equal, or whether the first is greater than the second.
+*
+* Comparison is done wchar_t by wchar_t on an UNSIGNED basis, which is to
+* say that Null wchar_t(0) is less than any other character.
+*
+*Entry:
+* const wchar_t * src - string for left-hand side of comparison
+* const wchar_t * dst - string for right-hand side of comparison
+*
+*Exit:
+* returns -1 if src < dst
+* returns 0 if src == dst
+* returns +1 if src > dst
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int Laylstrcmp (
+ const wchar_t * src,
+ const wchar_t * dst
+ )
+{
+ int ret = 0 ;
+
+ while( ! (ret = (int)(*src - *dst)) && *dst)
+ ++src, ++dst;
+
+ if ( ret < 0 )
+ ret = -1 ;
+ else if ( ret > 0 )
+ ret = 1 ;
+
+ return( ret );
+}
+
+
+/***
+*wchar_t *Laylstrcat(dst, src) - concatenate (append) one wchar_t string to another
+*
+*Purpose:
+* Concatenates src onto the end of dest. Assumes enough
+* space in dest.
+*
+*Entry:
+* wchar_t *dst - wchar_t string to which "src" is to be appended
+* const wchar_t *src - wchar_t string to be appended to the end of "dst"
+*
+*Exit:
+* The address of "dst"
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * Laylstrcat (
+ wchar_t * dst,
+ const wchar_t * src
+ )
+{
+ wchar_t * cp = dst;
+
+ while( *cp )
+ cp++; /* find end of dst */
+
+ while( *cp++ = *src++ ) ; /* Copy src to end of dst */
+
+ return( dst ); /* return dst */
+
+}
+
+
+/***
+*wchar_t *Laylstrcpy(dst, src) - copy one wchar_t string over another
+*
+*Purpose:
+* Copies the wchar_t string src into the spot specified by
+* dest; assumes enough room.
+*
+*Entry:
+* wchar_t * dst - wchar_t string over which "src" is to be copied
+* const wchar_t * src - wchar_t string to be copied over "dst"
+*
+*Exit:
+* The address of "dst"
+*
+*Exceptions:
+*******************************************************************************/
+
+wchar_t * Laylstrcpy(wchar_t * dst, const wchar_t * src)
+{
+ wchar_t * cp = dst;
+
+ while( *cp++ = *src++ )
+ ; /* Copy src over dst */
+
+ return( dst );
+}
+
+
+/***
+*wchar_t *Laylstrcpyn(dest, source, count) - copy at most n wide characters
+*
+*Purpose:
+* Copies count characters from the source string to the
+* destination. If count is less than the length of source,
+* NO NULL CHARACTER is put onto the end of the copied string.
+* If count is greater than the length of sources, dest is padded
+* with null characters to length count (wide-characters).
+*
+*
+*Entry:
+* wchar_t *dest - pointer to destination
+* wchar_t *source - source string for copy
+* size_t count - max number of characters to copy
+*
+*Exit:
+* returns dest
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+wchar_t * Laylstrcpyn (
+ wchar_t * dest,
+ const wchar_t * source,
+ size_t count
+ )
+{
+ wchar_t *start = dest;
+
+ while (count && (*dest++ = *source++)) /* copy string */
+ count--;
+
+ if (count) /* pad out with zeroes */
+ while (--count)
+ *dest++ = L'\0';
+
+ return(start);
+}
+
+/***
+*Laylstrlen - return the length of a null-terminated wide-character string
+*
+*Purpose:
+* Finds the length in wchar_t's of the given string, not including
+* the final null wchar_t (wide-characters).
+*
+*Entry:
+* const wchar_t * wcs - string whose length is to be computed
+*
+*Exit:
+* length of the string "wcs", exclusive of the final null wchar_t
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t Laylstrlen (
+ const wchar_t * wcs
+ )
+{
+ const wchar_t *eos = wcs;
+
+ while( *eos++ ) ;
+
+ return( (size_t)(eos - wcs - 1) );
+}
diff --git a/private/ole32/stg/async/daytona.inc b/private/ole32/stg/async/daytona.inc
new file mode 100644
index 000000000..1e272906b
--- /dev/null
+++ b/private/ole32/stg/async/daytona.inc
@@ -0,0 +1,60 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ daytona.inc
+
+Abstract:
+
+ This file is included from all of the daytona sources files. It
+ is handy for doing things like turning off precompiled headers
+ to get around compiler bugs, and other such global activities.
+
+Notes:
+
+ We define _OLE32_ so that when building ole32.dll we don't have
+ DECLSPEC_IMPORT defined (see objbase.h)
+
+!ENDIF
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DNOEXCEPTIONS \
+ -DINC_OLE2 \
+ -DFLAT \
+ -DWIN32=100 \
+ -D_NT1X_=100 \
+ -DUNICODE \
+ -D_UNICODE \
+ -DCAIROLE_DOWNLEVEL \
+ -DDCOM \
+ -DMSWMSG \
+ -DDCOM_SECURITY \
+ -DNEWPROPS \
+ -D_TRACKLINK_=1 \
+ $(TRACELOG)
+
+# DECLSPEC_IMPORT control (see objbase.h)
+!if "$(MINORCOMP)"=="com" || "$(MINORCOMP)"=="stg" || "$(MINORCOMP)"=="ole232" || "$(MINORCOMP)"=="common"
+C_DEFINES= \
+ $(C_DEFINES) \
+ -D_OLE32_
+!endif
+
+
+BLDCRT= 1
+
+# For the Daytona build, we do not want statically linked compiler runtimes,
+# so leave this commented out.
+#
+# USE_LIBCMT= 1
+
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+NTLEGO=1
+
+GPCH_BUILD=daytona
+
diff --git a/private/ole32/stg/async/debug/assert.cxx b/private/ole32/stg/async/debug/assert.cxx
new file mode 100644
index 000000000..32497e051
--- /dev/null
+++ b/private/ole32/stg/async/debug/assert.cxx
@@ -0,0 +1,421 @@
+//+---------------------------------------------------------------------------
+// Copyright (C) 1991, Microsoft Corporation.
+//
+// File: assert.cxx
+//
+// Contents: Debugging output routines for idsmgr.dll
+//
+// Functions: Assert
+// PopUpError
+//
+// History: 23-Jul-91 KyleP Created.
+// 09-Oct-91 KevinRo Major changes and comments added
+// 18-Oct-91 vich moved debug print routines out
+// 10-Jun-92 BryanT Switched to w4crt.h instead of wchar.h
+// 30-Sep-93 KyleP DEVL obsolete
+//
+//----------------------------------------------------------------------------
+
+#pragma hdrstop
+
+//
+// This one file **always** uses debugging options
+//
+
+#if DBG == 1
+
+// needed for CT TOM assert events trapping
+#include <assert.hxx>
+
+#include <stdarg.h>
+#include <stdio.h>
+
+
+# include <dprintf.h> // w4printf, w4dprintf prototypes
+# include <debnot.h>
+# ifdef FLAT
+# include <sem.hxx>
+# include <dllsem.hxx>
+# endif // FLAT
+
+extern "C"
+{
+
+# ifdef FLAT
+# undef FAR
+# undef NEAR
+# else
+# define MessageBoxA MessageBox
+# endif
+
+# include <windows.h>
+}
+#ifdef _CHICAGO_
+//int WINAPI SSMessageBox(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption, UINT uType);
+#define SSMessageBox MessageBox
+#endif // _CHICAGO_
+
+
+extern BOOL gfService = FALSE;
+
+unsigned long Win4InfoLevel = DEF_INFOLEVEL;
+unsigned long Win4InfoMask = 0xffffffff;
+#ifdef _CAIRO_
+unsigned long Win4AssertLevel = ASSRT_MESSAGE | ASSRT_BREAK;
+#else
+unsigned long Win4AssertLevel = ASSRT_MESSAGE | ASSRT_BREAK | ASSRT_POPUP;
+#endif
+//+------------------------------------------------------------
+// Function: vdprintf
+//
+// Synopsis: Prints debug output using a pointer to the
+// variable information. Used primarily by the
+// xxDebugOut macros
+//
+// Arguements:
+// ulCompMask -- Component level mask used to determine
+// output ability
+// pszComp -- String const of component prefix.
+// ppszfmt -- Pointer to output format and data
+//
+//-------------------------------------------------------------
+
+//
+// This semaphore is *outside* vdprintf because the compiler isn't smart
+// enough to serialize access for construction if it's function-local and
+// protected by a guard variable.
+//
+// KyleP - 20 May, 1993
+//
+
+static CDLLStaticMutexSem mxs;
+
+STDAPI_(void) vdprintf(
+ unsigned long ulCompMask,
+ char const *pszComp,
+ char const *ppszfmt,
+ va_list pargs)
+{
+ if ((ulCompMask & DEB_FORCE) == DEB_FORCE ||
+ ((ulCompMask | Win4InfoLevel) & Win4InfoMask))
+ {
+#if defined( FLAT )
+ mxs.Request();
+ DWORD tid = GetCurrentThreadId();
+ DWORD pid = GetCurrentProcessId();
+ if ((Win4InfoLevel & (DEB_DBGOUT | DEB_STDOUT)) != DEB_STDOUT)
+#endif // FLAT
+ {
+ if (! (ulCompMask & DEB_NOCOMPNAME))
+ {
+#ifdef FLAT
+#if defined(_CHICAGO_)
+ //
+ // Hex Process/Thread ID's are better for Chicago since both
+ // are memory addresses.
+ //
+ w4dprintf( "%08x.%08x> ", pid, tid );
+#else
+ w4dprintf( "%d.%03d> ", pid, tid );
+#endif
+#endif // FLAT
+ w4dprintf("%s: ", pszComp);
+ }
+ w4vdprintf(ppszfmt, pargs);
+ }
+
+#if defined( FLAT )
+ if (Win4InfoLevel & DEB_STDOUT)
+ {
+ if (! (ulCompMask & DEB_NOCOMPNAME))
+ {
+ w4printf( "%03d> ", tid );
+ w4printf("%s: ", pszComp);
+ }
+ w4vprintf(ppszfmt, pargs);
+ }
+
+ mxs.Release();
+#endif // FLAT
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: _asdprintf
+//
+// Synopsis: Calls vdprintf to output a formatted message.
+//
+// History: 18-Oct-91 vich Created
+//
+//----------------------------------------------------------------------------
+inline void _CRTAPI1
+_asdprintf(
+ char const *pszfmt, ...)
+{
+ va_list va;
+ va_start(va, pszfmt);
+
+ vdprintf(DEB_FORCE, "Assert", pszfmt, va);
+
+ va_end(va);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: _Win4Assert, private
+//
+// Synopsis: Display assertion information
+//
+// Effects: Called when an assertion is hit.
+//
+// History: 12-Jul-91 AlexT Created.
+// 05-Sep-91 AlexT Catch Throws and Catches
+// 19-Oct-92 HoiV Added events for TOM
+//
+//----------------------------------------------------------------------------
+
+
+STDAPI_(void) Win4AssertEx(
+ char const * szFile,
+ int iLine,
+ char const * szMessage)
+{
+#if defined( FLAT )
+ //
+ // This code is for the CT Lab only. When running in the lab,
+ // all assert popups will be trapped and notifications will
+ // be sent to the manager. If running in the office (non-lab
+ // mode), the event CTTOMTrapAssertEvent will not exist and
+ // consequently, no event will be pulsed.
+ //
+
+ HANDLE hTrapAssertEvent,
+ hThreadStartEvent;
+
+ if (hTrapAssertEvent = OpenEvent(EVENT_ALL_ACCESS,
+ FALSE,
+ CAIRO_CT_TOM_TRAP_ASSERT_EVENT))
+ {
+ SetEvent(hTrapAssertEvent);
+
+ //
+ // This event is to allow TOM Manager time to perform
+ // a CallBack to the dispatcher.
+ //
+ if (hThreadStartEvent = OpenEvent(EVENT_ALL_ACCESS,
+ FALSE,
+ CAIRO_CT_TOM_THREAD_START_EVENT))
+ {
+ //
+ // Wait until it's ok to popup or until timed-out
+ //
+ WaitForSingleObject(hThreadStartEvent, TWO_MINUTES);
+ }
+ }
+#endif
+
+ if (Win4AssertLevel & ASSRT_MESSAGE)
+ {
+# ifdef FLAT
+ DWORD tid = GetCurrentThreadId();
+
+ _asdprintf("%s File: %s Line: %u, thread id %d\n",
+ szMessage, szFile, iLine, tid);
+# else // FLAT
+ _asdprintf("%s File: %s Line: %u\n", szMessage, szFile, iLine);
+# endif // FLAT
+ }
+
+ if (Win4AssertLevel & ASSRT_POPUP)
+ {
+ int id = PopUpError(szMessage,iLine,szFile);
+
+ if (id == IDCANCEL)
+ {
+#ifdef FLAT
+ DebugBreak();
+#else
+ _asm int 3;
+#endif
+ }
+ }
+ else if (Win4AssertLevel & ASSRT_BREAK)
+ {
+#ifdef FLAT
+ DebugBreak();
+#else
+ _asm int 3;
+#endif
+ }
+
+}
+
+
+//+------------------------------------------------------------
+// Function: SetWin4InfoLevel(unsigned long ulNewLevel)
+//
+// Synopsis: Sets the global info level for debugging output
+// Returns: Old info level
+//
+//-------------------------------------------------------------
+
+EXPORTIMP unsigned long APINOT
+SetWin4InfoLevel(
+ unsigned long ulNewLevel)
+{
+ unsigned long ul;
+
+ ul = Win4InfoLevel;
+ Win4InfoLevel = ulNewLevel;
+ return(ul);
+}
+
+
+//+------------------------------------------------------------
+// Function: _SetWin4InfoMask(unsigned long ulNewMask)
+//
+// Synopsis: Sets the global info mask for debugging output
+// Returns: Old info mask
+//
+//-------------------------------------------------------------
+
+EXPORTIMP unsigned long APINOT
+SetWin4InfoMask(
+ unsigned long ulNewMask)
+{
+ unsigned long ul;
+
+ ul = Win4InfoMask;
+ Win4InfoMask = ulNewMask;
+ return(ul);
+}
+
+
+//+------------------------------------------------------------
+// Function: _SetWin4AssertLevel(unsigned long ulNewLevel)
+//
+// Synopsis: Sets the global assert level for debugging output
+// Returns: Old assert level
+//
+//-------------------------------------------------------------
+
+EXPORTIMP unsigned long APINOT
+SetWin4AssertLevel(
+ unsigned long ulNewLevel)
+{
+ unsigned long ul;
+
+ ul = Win4AssertLevel;
+ Win4AssertLevel = ulNewLevel;
+ return(ul);
+}
+
+//+------------------------------------------------------------
+// Function: PopUpError
+//
+// Synopsis: Displays a dialog box using provided text,
+// and presents the user with the option to
+// continue or cancel.
+//
+// Arguments:
+// szMsg -- The string to display in main body of dialog
+// iLine -- Line number of file in error
+// szFile -- Filename of file in error
+//
+// Returns:
+// IDCANCEL -- User selected the CANCEL button
+// IDOK -- User selected the OK button
+//-------------------------------------------------------------
+
+STDAPI_(int) PopUpError(
+ char const *szMsg,
+ int iLine,
+ char const *szFile)
+{
+
+ int id;
+ static char szAssertCaption[128];
+ static char szModuleName[128];
+
+ DWORD tid = GetCurrentThreadId();
+ DWORD pid = GetCurrentProcessId();
+ char * pszModuleName;
+
+ if (GetModuleFileNameA(NULL, szModuleName, 128))
+ {
+ pszModuleName = strrchr(szModuleName, '\\');
+ if (!pszModuleName)
+ {
+ pszModuleName = szModuleName;
+ }
+ else
+ {
+ pszModuleName++;
+ }
+ }
+ else
+ {
+ pszModuleName = "Unknown";
+ }
+
+ wsprintfA(szAssertCaption,"Process: %s File: %s line %u, thread id %d.%d",
+ pszModuleName, szFile, iLine, pid, tid);
+
+
+ DWORD dwMessageFlags = MB_SETFOREGROUND | MB_TASKMODAL |
+ MB_ICONEXCLAMATION | MB_OKCANCEL;
+
+#ifndef _CHICAGO_
+ // Since this code is also used by SCM.EXE, we pass
+ // in the following flag which causes Service pop ups
+ // to appear on the desktop correctly
+
+ if (gfService)
+ {
+ dwMessageFlags |= MB_SERVICE_NOTIFICATION | MB_DEFAULT_DESKTOP_ONLY;
+ }
+
+ id = MessageBoxA(NULL,(char *) szMsg, (LPSTR) szAssertCaption,
+ dwMessageFlags);
+
+# ifdef _CAIRO_
+ // Other processes which are services also use this code, but they
+ // have no access to set gfService, so if the above failed with an
+ // access denied error (meaning no access to the default desktop)
+ // retry as a service popup. Also, remember that we are a service
+ // so we don't waste attempts later.
+ if ( !gfService && !id
+ && (GetLastError() == ERROR_ACCESS_DENIED) )
+ {
+ gfService = TRUE;
+ dwMessageFlags |= MB_SERVICE_NOTIFICATION | MB_DEFAULT_DESKTOP_ONLY;
+ id = MessageBoxA(NULL,(char *) szMsg, (LPSTR) szAssertCaption,
+ dwMessageFlags);
+ }
+# endif
+
+#else
+ id = SSMessageBox(NULL, (char *) szMsg, (LPSTR) szAssertCaption,
+ dwMessageFlags);
+
+#endif
+
+ // If id == 0, then an error occurred. There are two possibilities
+ // that can cause the error: Access Denied, which means that this
+ // process does not have access to the default desktop, and everything
+ // else (usually out of memory). Oh well.
+
+ return id;
+}
+
+
+#else
+
+int assertDontUseThisName(void)
+{
+ return 1;
+}
+
+#endif // DBG == 1
diff --git a/private/ole32/stg/async/debug/daytona/makefile b/private/ole32/stg/async/debug/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/async/debug/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/async/debug/daytona/sources b/private/ole32/stg/async/debug/daytona/sources
new file mode 100644
index 000000000..3fe01cb51
--- /dev/null
+++ b/private/ole32/stg/async/debug/daytona/sources
@@ -0,0 +1,68 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Philip Lafornara (PhilipLa) 19-Dec-1995
+
+!ENDIF
+
+
+MAJORCOMP = asyncstg
+MINORCOMP = debug
+
+!include ..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= debug
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..
+
+C_DEFINES= \
+ $(C_DEFINES)
+
+SOURCES= \
+ ..\assert.cxx \
+ ..\dprintf.c \
+ ..\eqguid.cxx \
+ ..\output.c \
+ ..\printf.c \
+ ..\sprintf.c
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+UMLIBS=
+
diff --git a/private/ole32/stg/async/debug/dirs b/private/ole32/stg/async/debug/dirs
new file mode 100644
index 000000000..f0d92a143
--- /dev/null
+++ b/private/ole32/stg/async/debug/dirs
@@ -0,0 +1,37 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Philip Lafornara (PhilipLa) 19-Dec-1995
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ daytona
diff --git a/private/ole32/stg/async/debug/dprintf.c b/private/ole32/stg/async/debug/dprintf.c
new file mode 100644
index 000000000..71acbcaeb
--- /dev/null
+++ b/private/ole32/stg/async/debug/dprintf.c
@@ -0,0 +1,15 @@
+/***
+*dprintf.c - print formatted to debug port
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4dprintf() - print formatted data to debug port
+* defines w4vdprintf() - print formatted output to debug port, get data
+* from an argument ptr instead of explicit args.
+*******************************************************************************/
+
+#include "dprintf.h" // function prototypes
+
+#define _W4DPRINTF_
+#include "printf.h"
diff --git a/private/ole32/stg/async/debug/dprintf.h b/private/ole32/stg/async/debug/dprintf.h
new file mode 100644
index 000000000..f4af83504
--- /dev/null
+++ b/private/ole32/stg/async/debug/dprintf.h
@@ -0,0 +1,33 @@
+//+---------------------------------------------------------------------------
+// Copyright (C) 1991, Microsoft Corporation.
+//
+// File: dprintf.h
+//
+// Contents: Debugging output routine function prototypes
+//
+// Functions: w4printf
+// w4vprintf
+// w4dprintf
+// w4vdprintf
+//
+// History: 18-Oct-91 vich Created
+//
+//----------------------------------------------------------------------------
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef WIN32
+int _cdecl w4printf(const char *format, ...);
+int _cdecl w4vprintf(const char *format, va_list arglist);
+#endif
+
+int _cdecl w4dprintf(const char *format, ...);
+int _cdecl w4vdprintf(const char *format, va_list arglist);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/private/ole32/stg/async/debug/eqguid.cxx b/private/ole32/stg/async/debug/eqguid.cxx
new file mode 100644
index 000000000..41223a16a
--- /dev/null
+++ b/private/ole32/stg/async/debug/eqguid.cxx
@@ -0,0 +1,54 @@
+
+#include <windows.h>
+#include <ole2.h>
+#include <stdlib.h>
+
+//+-------------------------------------------------------------------------
+//
+// Function: IsEqualGUID (public)
+//
+// Synopsis: compares two guids for equality
+//
+// Arguments: [guid1] - the first guid
+// [guid2] - the second guid to compare the first one with
+//
+// Returns: TRUE if equal, FALSE if not.
+//
+// Note:
+// Only reason we have this function is because we exported it originally
+// from OLE32.DLL and forgot to take it out when we made it an inline
+// function in objbase.h. Somebody out there may be relying on it being
+// available. Internally we must use wIsEqualGUID.
+//
+//--------------------------------------------------------------------------
+#undef IsEqualGUID // undo the #define in objbase.h
+extern "C" BOOL __stdcall IsEqualGUID(GUID &guid1, GUID &guid2)
+{
+ return (
+ ((PLONG) &guid1)[0] == ((PLONG) &guid2)[0] &&
+ ((PLONG) &guid1)[1] == ((PLONG) &guid2)[1] &&
+ ((PLONG) &guid1)[2] == ((PLONG) &guid2)[2] &&
+ ((PLONG) &guid1)[3] == ((PLONG) &guid2)[3]);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: wIsEqualGUID (internal)
+//
+// Synopsis: compares two guids for equality
+//
+// Arguments: [guid1] - the first guid
+// [guid2] - the second guid to compare the first one with
+//
+// Returns: TRUE if equal, FALSE if not.
+//
+//--------------------------------------------------------------------------
+
+BOOL __fastcall wIsEqualGUID(REFGUID guid1, REFGUID guid2)
+{
+ return (
+ ((PLONG) &guid1)[0] == ((PLONG) &guid2)[0] &&
+ ((PLONG) &guid1)[1] == ((PLONG) &guid2)[1] &&
+ ((PLONG) &guid1)[2] == ((PLONG) &guid2)[2] &&
+ ((PLONG) &guid1)[3] == ((PLONG) &guid2)[3]);
+}
diff --git a/private/ole32/stg/async/debug/output.c b/private/ole32/stg/async/debug/output.c
new file mode 100644
index 000000000..1b3d80bdf
--- /dev/null
+++ b/private/ole32/stg/async/debug/output.c
@@ -0,0 +1,964 @@
+/***
+*output.c - printf style output to a struct w4io
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the code that does all the work for the
+* printf family of functions. It should not be called directly, only
+* by the *printf functions. We don't make any assumtions about the
+* sizes of ints, longs, shorts, or long doubles, but if types do overlap, we
+* also try to be efficient. We do assume that pointers are the same size
+* as either ints or longs.
+*
+*Revision History:
+* 06-01-89 PHG Module created
+* 08-28-89 JCR Added cast to get rid of warning (no object changes)
+* 02-15-90 GJF Fixed copyright
+* 10-03-90 WHB Defined LOCAL(x) to "static x" for local procedures
+* 06-05-95 SVA Added support for printing GUIDs.
+*
+*******************************************************************************/
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <stdarg.h>
+#include "wchar.h"
+#include "w4io.h"
+
+
+/* this macro defines a function which is private and as fast as possible: */
+/* for example, in C 6.0, it might be static _fastcall <type>. */
+#define LOCAL(x) static x // 100390--WHB
+
+#define NOFLOATS // Win 4 doesn't need floating point
+
+/* int/long/short/pointer sizes */
+
+/* the following should be set depending on the sizes of various types */
+// FLAT or LARGE model is assumed
+#ifdef FLAT
+# define LONG_IS_INT 1 /* 1 means long is same size as int */
+# define SHORT_IS_INT 0 /* 1 means short is same size as int */
+# define PTR_IS_INT 1 /* 1 means ptr is same size as int */
+# define PTR_IS_LONG 0 /* 1 means ptr is same size as long */
+#else // LARGE model
+# define LONG_IS_INT 0 /* 1 means long is same size as int */
+# define SHORT_IS_INT 1 /* 1 means short is same size as int */
+# define PTR_IS_INT 0 /* 1 means ptr is same size as int */
+# define PTR_IS_LONG 1 /* 1 means ptr is same size as long */
+#endif
+#define LONGDOUBLE_IS_DOUBLE 0 /* 1 means long double is same as double */
+
+#if LONG_IS_INT
+ #define get_long_arg(x) (long)get_int_arg(x)
+#endif
+
+#if PTR_IS_INT
+ #define get_ptr_arg(x) (void *)get_int_arg(x)
+#elif PTR_IS_LONG
+ #define get_ptr_arg(x) (void *)get_long_arg(x)
+#else
+ #error Size of pointer must be same as size of int or long
+#endif
+
+#ifndef NOFLOATS
+/* These are "fake" double and long doubles to fool the compiler,
+ so we don't drag in floating point. */
+typedef struct {
+ char x[sizeof(double)];
+} DOUBLE;
+typedef struct {
+ char x[sizeof(long double)];
+} LONGDOUBLE;
+#endif
+
+
+/* CONSTANTS */
+
+//#define BUFFERSIZE CVTBUFSIZE /* buffer size for maximum double conv */
+#define BUFFERSIZE 20
+
+/* flag definitions */
+#define FL_SIGN 0x0001 /* put plus or minus in front */
+#define FL_SIGNSP 0x0002 /* put space or minus in front */
+#define FL_LEFT 0x0004 /* left justify */
+#define FL_LEADZERO 0x0008 /* pad with leading zeros */
+#define FL_LONG 0x0010 /* long value given */
+#define FL_SHORT 0x0020 /* short value given */
+#define FL_SIGNED 0x0040 /* signed data given */
+#define FL_ALTERNATE 0x0080 /* alternate form requested */
+#define FL_NEGATIVE 0x0100 /* value is negative */
+#define FL_FORCEOCTAL 0x0200 /* force leading '0' for octals */
+#define FL_LONGDOUBLE 0x0400 /* long double value given */
+#define FL_WIDE 0x0800 /* wide character/string given */
+
+/* state definitions */
+enum STATE {
+ ST_NORMAL, /* normal state; outputting literal chars */
+ ST_PERCENT, /* just read '%' */
+ ST_FLAG, /* just read flag character */
+ ST_WIDTH, /* just read width specifier */
+ ST_DOT, /* just read '.' */
+ ST_PRECIS, /* just read precision specifier */
+ ST_SIZE, /* just read size specifier */
+ ST_TYPE /* just read type specifier */
+};
+#define NUMSTATES (ST_TYPE + 1)
+
+/* character type values */
+enum CHARTYPE {
+ CH_OTHER, /* character with no special meaning */
+ CH_PERCENT, /* '%' */
+ CH_DOT, /* '.' */
+ CH_STAR, /* '*' */
+ CH_ZERO, /* '0' */
+ CH_DIGIT, /* '1'..'9' */
+ CH_FLAG, /* ' ', '+', '-', '#' */
+ CH_SIZE, /* 'h', 'l', 'L', 'N', 'F' */
+ CH_TYPE /* type specifying character */
+};
+
+/* static data (read only, since we are re-entrant) */
+char *nullstring = "(null)"; /* string to print on null ptr */
+
+/* The state table. This table is actually two tables combined into one. */
+/* The lower nybble of each byte gives the character class of any */
+/* character; while the uper nybble of the byte gives the next state */
+/* to enter. See the macros below the table for details. */
+/* */
+/* The table is generated by maketab.c -- use the maketab program to make */
+/* changes. */
+
+/* Brief description of the table, since I can't find maketab.c - t-stevan */
+/* Each entry in form 0xYZ. Here Z is a character class used in the macro */
+/* find_char_class defined below. The character classes are defined in the */
+/* CHARTYPE enum. For example, 'I' maps to CH_TYPE. To find a particular entry */
+/* Subtract the ASCI value for the space char from the character, and that is */
+/* the index to look up. The Y value is holds state transition information. */
+/* It is used in the macro find_next_state. */
+static char lookuptable[] = {
+ 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00,
+ 0x10, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x10,
+ 0x04, 0x45, 0x45, 0x45, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x35, 0x30, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x28, 0x38, 0x50, 0x58, 0x07, 0x08,
+ 0x00, 0x38, 0x30, 0x30, 0x57, 0x50, 0x07, 0x00,
+ 0x00, 0x20, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00,
+ 0x00, 0x70, 0x70, 0x78, 0x78, 0x78, 0x78, 0x08,
+ 0x07, 0x08, 0x00, 0x00, 0x07, 0x00, 0x08, 0x08,
+ 0x08, 0x00, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07,
+ 0x08
+};
+
+#define find_char_class(c) \
+ ((c) < ' ' || (c) > 'x' ? \
+ CH_OTHER \
+ : \
+ lookuptable[(c)-' '] & 0xF)
+
+#define find_next_state(class, state) \
+ (lookuptable[(class) * NUMSTATES + (state)] >> 4)
+
+#if !LONG_IS_INT
+LOCAL(long) get_long_arg(va_list *pargptr);
+#endif
+LOCAL(int) get_int_arg(va_list *pargptr);
+LOCAL(void) writestring(char *string,
+ int len,
+ struct w4io *f,
+ int *pcchwritten,
+ int fwide);
+
+#ifndef NOFLOATS
+/* extern float convert routines */
+typedef int (* PFI)();
+extern PFI _cfltcvt_tab[5];
+#define _cfltcvt(a,b,c,d,e) (*_cfltcvt_tab[0])(a,b,c,d,e)
+#define _cropzeros(a) (*_cfltcvt_tab[1])(a)
+#define _fassign(a,b,c) (*_cfltcvt_tab[2])(a,b,c)
+#define _forcdecpt(a) (*_cfltcvt_tab[3])(a)
+#define _positive(a) (*_cfltcvt_tab[4])(a)
+#define _cldcvt(a,b,c,d,e) (*_cfltcvt_tab[5])(a,b,c,d,e)
+#endif
+
+/* Defines for printing out GUIDs */
+#ifndef GUID_DEFINED
+#define GUID_DEFINED
+ /* size is 16 */
+typedef struct _GUID
+ {
+ unsigned long Data1;
+ unsigned short Data2;
+ unsigned short Data3;
+ unsigned char Data4[ 8 ];
+ } GUID;
+
+#endif // !GUID_DEFINED
+
+#ifndef _REFGUID_DEFINED
+#define _REFGUID_DEFINED
+#define REFGUID const GUID * const
+#endif // !_REFGUID_DEFINED
+
+/* This is actually one less than the normal GUIDSTR_MAX */
+/* Because we don't tag on a NULL byte */
+#define GUIDSTR_MAX (1+ 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 /* + 1 */)
+
+/* Make sure our buffer size is big enough to hold a GUID */
+#if BUFFERSIZE < GUIDSTR_MAX
+#undef BUFFERSIZE
+#define BUFFERSIZE GUIDSTR_MAX
+#endif
+
+/* Function used to write a GUID to a string */
+int StrFromGUID(REFGUID rguid, char * lpsz, int cbMax);
+
+/***
+*int w4iooutput(f, format, argptr)
+*
+*Purpose:
+* Output performs printf style output onto a stream. It is called by
+* printf/fprintf/sprintf/vprintf/vfprintf/vsprintf to so the dirty
+* work. In multi-thread situations, w4iooutput assumes that the given
+* stream is already locked.
+*
+* Algorithm:
+* The format string is parsed by using a finite state automaton
+* based on the current state and the current character read from
+* the format string. Thus, looping is on a per-character basis,
+* not a per conversion specifier basis. Once the format specififying
+* character is read, output is performed.
+*
+*Entry:
+* struct w4io *f - stream for output
+* char *format - printf style format string
+* va_list argptr - pointer to list of subsidiary arguments
+*
+*Exit:
+* Returns the number of characters written, or -1 if an output error
+* occurs.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _cdecl w4iooutput(struct w4io *f, const char *format, va_list argptr)
+{
+ int hexadd; /* offset to add to number to get 'a'..'f' */
+ char ch; /* character just read */
+ wchar_t wc; /* wide character temp */
+ wchar_t *pwc; /* wide character temp pointer */
+ int flags; /* flag word -- see #defines above for flag values */
+ enum STATE state; /* current state */
+ enum CHARTYPE chclass; /* class of current character */
+ int radix; /* current conversion radix */
+ int charsout; /* characters currently written so far, -1 = IO error */
+ int fldwidth; /* selected field with -- 0 means default */
+ int fwide;
+ int precision; /* selected precision -- -1 means default */
+ char prefix[2]; /* numeric prefix -- up to two characters */
+ int prefixlen; /* length of prefix -- 0 means no prefix */
+ int capexp; /* non-zero = 'E' exponent signifiet, zero = 'e' */
+ int no_output; /* non-zero = prodcue no output for this specifier */
+ char *text; /* pointer text to be printed, not zero terminated */
+ int textlen; /* length of the text to be printed */
+ char buffer[BUFFERSIZE]; /* buffer for conversions */
+
+ charsout = 0; /* no characters written yet */
+ state = ST_NORMAL; /* starting state */
+
+ /* main loop -- loop while format character exist and no I/O errors */
+ while ((ch = *format++) != '\0' && charsout >= 0) {
+ chclass = find_char_class(ch); /* find character class */
+ state = find_next_state(chclass, state); /* find next state */
+
+ /* execute code for each state */
+ switch (state) {
+
+ case ST_NORMAL:
+ /* normal state -- just write character */
+ f->writechar(ch, 1, f, &charsout);
+ break;
+
+ case ST_PERCENT:
+ /* set default value of conversion parameters */
+ prefixlen = fldwidth = no_output = capexp = 0;
+ flags = 0;
+ precision = -1;
+ fwide = 0;
+ break;
+
+ case ST_FLAG:
+ /* set flag based on which flag character */
+ switch (ch) {
+ case '-':
+ flags |= FL_LEFT; /* '-' => left justify */
+ break;
+ case '+':
+ flags |= FL_SIGN; /* '+' => force sign indicator */
+ break;
+ case ' ':
+ flags |= FL_SIGNSP; /* ' ' => force sign or space */
+ break;
+ case '#':
+ flags |= FL_ALTERNATE; /* '#' => alternate form */
+ break;
+ case '0':
+ flags |= FL_LEADZERO; /* '0' => pad with leading zeros */
+ break;
+ }
+ break;
+
+ case ST_WIDTH:
+ /* update width value */
+ if (ch == '*') {
+ /* get width from arg list */
+ fldwidth = get_int_arg(&argptr);
+ if (fldwidth < 0) {
+ /* ANSI says neg fld width means '-' flag and pos width */
+ flags |= FL_LEFT;
+ fldwidth = -fldwidth;
+ }
+ }
+ else {
+ /* add digit to current field width */
+ fldwidth = fldwidth * 10 + (ch - '0');
+ }
+ break;
+
+ case ST_DOT:
+ /* zero the precision, since dot with no number means 0
+ not default, according to ANSI */
+ precision = 0;
+ break;
+
+ case ST_PRECIS:
+ /* update precison value */
+ if (ch == '*') {
+ /* get precision from arg list */
+ precision = get_int_arg(&argptr);
+ if (precision < 0)
+ precision = -1; /* neg precision means default */
+ }
+ else {
+ /* add digit to current precision */
+ precision = precision * 10 + (ch - '0');
+ }
+ break;
+
+ case ST_SIZE:
+ /* just read a size specifier, set the flags based on it */
+ switch (ch) {
+#if !LONG_IS_INT
+ case 'l':
+ flags |= FL_LONG; /* 'l' => long int */
+ break;
+#endif
+
+#if !LONGDOUBLE_IS_DOUBLE
+ case 'L':
+ flags |= FL_LONGDOUBLE; /* 'L' => long double */
+ break;
+#endif
+
+#if !SHORT_IS_INT
+ case 'h':
+ flags |= FL_SHORT; /* 'h' => short int */
+ break;
+#endif
+ case 'w':
+ flags |= FL_WIDE; /* 'w' => wide character */
+ break;
+ case 't':
+#ifdef _UNICODE
+ flags |= FL_WIDE;
+#endif
+ break;
+
+ }
+ break;
+
+ case ST_TYPE:
+ /* we have finally read the actual type character, so we */
+ /* now format and "print" the output. We use a big switch */
+ /* statement that sets 'text' to point to the text that should */
+ /* be printed, and 'textlen' to the length of this text. */
+ /* Common code later on takes care of justifying it and */
+ /* other miscellaneous chores. Note that cases share code, */
+ /* in particular, all integer formatting is doen in one place. */
+ /* Look at those funky goto statements! */
+
+ switch (ch) {
+
+ case 'c': {
+ /* print a single character specified by int argument */
+ wc = (wchar_t) get_int_arg(&argptr); /* get char to print */
+ * (wchar_t *) buffer = wc;
+ text = buffer;
+ textlen = 1; /* print just a single character */
+ }
+ break;
+
+ case 'S': {
+ /* print a Counted String */
+
+ struct string {
+ short Length;
+ short MaximumLength;
+ char *Buffer;
+ } *pstr;
+
+ pstr = get_ptr_arg(&argptr);
+ if (pstr == NULL || pstr->Buffer == NULL) {
+ /* null ptr passed, use special string */
+ text = nullstring;
+ textlen = strlen(text);
+ flags &= ~FL_WIDE;
+ } else {
+ text = pstr->Buffer;
+ /* The length field is a count of bytes, not characters. */
+ if (flags & FL_WIDE)
+ textlen = pstr->Length / sizeof( wchar_t );
+ else
+ textlen = pstr->Length;
+ if (precision != -1)
+ textlen = min( textlen, precision );
+ }
+
+ }
+ break;
+
+ case 's': {
+ /* print a string -- */
+ /* ANSI rules on how much of string to print: */
+ /* all if precision is default, */
+ /* min(precision, length) if precision given. */
+ /* prints '(null)' if a null string is passed */
+
+ int i;
+ char *p; /* temps */
+
+ text = get_ptr_arg(&argptr);
+ if (text == NULL) {
+ /* null ptr passed, use special string */
+ text = nullstring;
+ flags &= ~FL_WIDE;
+ }
+
+ /* At this point it is tempting to use strlen(), but */
+ /* if a precision is specified, we're not allowed to */
+ /* scan past there, because there might be no null */
+ /* at all. Thus, we must do our own scan. */
+
+ i = (precision == -1) ? INT_MAX : precision;
+
+ /* scan for null upto i characters */
+ if (flags & FL_WIDE) {
+ pwc = (wchar_t *) text;
+ while (i-- && (wc = *pwc) && (wc & 0x00ff)) {
+ ++pwc;
+ if (wc & 0xff00) { // if high byte set,
+ break; // error will be indicated
+ }
+ }
+ textlen = pwc - (wchar_t *) text; /* length of string */
+ } else {
+ p = text;
+ while (i-- && *p) {
+ ++p;
+ }
+ textlen = p - text; /* length of the string */
+ }
+ }
+ break;
+
+ /* print a GUID */
+ case 'I':
+ {
+ void *p; /* temp */
+
+ p = get_ptr_arg(&argptr);
+
+ if (p == NULL)
+ {
+ /* null ptr passed, use special string */
+ text = nullstring;
+ textlen = strlen(nullstring);
+ }
+ else
+ {
+ textlen = StrFromGUID(p, buffer, BUFFERSIZE);
+ text = buffer;
+ }
+ }
+ break;
+
+ case 'n': {
+ /* write count of characters seen so far into */
+ /* short/int/long thru ptr read from args */
+
+ void *p; /* temp */
+
+ p = get_ptr_arg(&argptr);
+
+ /* store chars out into short/long/int depending on flags */
+#if !LONG_IS_INT
+ if (flags & FL_LONG)
+ *(long *)p = charsout;
+ else
+#endif
+
+#if !SHORT_IS_INT
+ if (flags & FL_SHORT)
+ *(short *)p = (short) charsout;
+ else
+#endif
+ *(int *)p = charsout;
+
+ no_output = 1; /* force no output */
+ }
+ break;
+
+#ifndef NOFLOATS
+ case 'E':
+ case 'G':
+ capexp = 1; /* capitalize exponent */
+ ch += 'a' - 'A'; /* convert format char to lower */
+ /* DROP THROUGH */
+ case 'e':
+ case 'f':
+ case 'g': {
+ /* floating point conversion -- we call cfltcvt routines */
+ /* to do the work for us. */
+ flags |= FL_SIGNED; /* floating point is signed conversion */
+ text = buffer; /* put result in buffer */
+ flags &= ~FL_WIDE; /* 8 bit string */
+
+ /* compute the precision value */
+ if (precision < 0)
+ precision = 6; /* default precision: 6 */
+ else if (precision == 0 && ch == 'g')
+ precision = 1; /* ANSI specified */
+
+#if !LONGDOUBLE_IS_DOUBLE
+ /* do the conversion */
+ if (flags & FL_LONGDOUBLE) {
+ _cldcvt(argptr, text, ch, precision, capexp);
+ va_arg(argptr, LONGDOUBLE);
+ }
+ else
+#endif
+ {
+ _cfltcvt(argptr, text, ch, precision, capexp);
+ va_arg(argptr, DOUBLE);
+ }
+
+ /* '#' and precision == 0 means force a decimal point */
+ if ((flags & FL_ALTERNATE) && precision == 0)
+ _forcdecpt(text);
+
+ /* 'g' format means crop zero unless '#' given */
+ if (ch == 'g' && !(flags & FL_ALTERNATE))
+ _cropzeros(text);
+
+ /* check if result was negative, save '-' for later */
+ /* and point to positive part (this is for '0' padding) */
+ if (*text == '-') {
+ flags |= FL_NEGATIVE;
+ ++text;
+ }
+
+ textlen = strlen(text); /* compute length of text */
+ }
+ break;
+#endif // NOFLOATS
+
+ case 'd':
+ case 'i':
+ /* signed decimal output */
+ flags |= FL_SIGNED;
+ radix = 10;
+ goto COMMON_INT;
+
+ case 'u':
+ radix = 10;
+ goto COMMON_INT;
+
+ case 'p':
+ /* write a pointer -- this is like an integer or long */
+ /* except we force precision to pad with zeros and */
+ /* output in big hex. */
+
+ precision = 2 * sizeof(void *); /* number of hex digits needed */
+#if !PTR_IS_INT
+ flags |= FL_LONG; /* assume we're converting a long */
+#endif
+ /* DROP THROUGH to hex formatting */
+
+ case 'C':
+ case 'X':
+ /* unsigned upper hex output */
+ hexadd = 'A' - '9' - 1; /* set hexadd for uppercase hex */
+ goto COMMON_HEX;
+
+ case 'x':
+ /* unsigned lower hex output */
+ hexadd = 'a' - '9' - 1; /* set hexadd for lowercase hex */
+ /* DROP THROUGH TO COMMON_HEX */
+
+ COMMON_HEX:
+ radix = 16;
+ if (flags & FL_ALTERNATE) {
+ /* alternate form means '0x' prefix */
+ prefix[0] = '0';
+ prefix[1] = (char)('x' - 'a' + '9' + 1 + hexadd); /* 'x' or 'X' */
+ prefixlen = 2;
+ }
+ goto COMMON_INT;
+
+ case 'o':
+ /* unsigned octal output */
+ radix = 8;
+ if (flags & FL_ALTERNATE) {
+ /* alternate form means force a leading 0 */
+ flags |= FL_FORCEOCTAL;
+ }
+ /* DROP THROUGH to COMMON_INT */
+
+ COMMON_INT: {
+ /* This is the general integer formatting routine. */
+ /* Basically, we get an argument, make it positive */
+ /* if necessary, and convert it according to the */
+ /* correct radix, setting text and textlen */
+ /* appropriately. */
+
+ unsigned long number; /* number to convert */
+ int digit; /* ascii value of digit */
+ long l; /* temp long value */
+
+ /* 1. read argument into l, sign extend as needed */
+#if !LONG_IS_INT
+ if (flags & FL_LONG)
+ l = get_long_arg(&argptr);
+ else
+#endif
+
+#if !SHORT_IS_INT
+ if (flags & FL_SHORT) {
+ if (flags & FL_SIGNED)
+ l = (short) get_int_arg(&argptr); /* sign extend */
+ else
+ l = (unsigned short) get_int_arg(&argptr); /* zero-extend*/
+ }
+ else
+#endif
+ {
+ if (flags & FL_SIGNED)
+ l = get_int_arg(&argptr); /* sign extend */
+ else
+ l = (unsigned int) get_int_arg(&argptr); /* zero-extend*/
+ }
+
+ /* 2. check for negative; copy into number */
+ if ( (flags & FL_SIGNED) && l < 0) {
+ number = -l;
+ flags |= FL_NEGATIVE; /* remember negative sign */
+ }
+ else {
+ number = l;
+ }
+
+ /* 3. check precision value for default; non-default */
+ /* turns off 0 flag, according to ANSI. */
+ if (precision < 0)
+ precision = 1; /* default precision */
+ else
+ flags &= ~FL_LEADZERO;
+
+ /* 4. Check if data is 0; if so, turn off hex prefix */
+ if (number == 0)
+ prefixlen = 0;
+
+ /* 5. Convert data to ASCII -- note if precision is zero */
+ /* and number is zero, we get no digits at all. */
+
+ text = &buffer[BUFFERSIZE-1]; // last digit at end of buffer
+ flags &= ~FL_WIDE; // 8 bit characters
+
+ while (precision-- > 0 || number != 0) {
+ digit = (int)(number % radix) + '0';
+ number /= radix; /* reduce number */
+ if (digit > '9') {
+ /* a hex digit, make it a letter */
+ digit += hexadd;
+ }
+ *text-- = (char)digit; /* store the digit */
+ }
+
+ textlen = (char *)&buffer[BUFFERSIZE-1] - text; /* compute length of number */
+ ++text; /* text points to first digit now */
+
+
+ /* 6. Force a leading zero if FORCEOCTAL flag set */
+ if ((flags & FL_FORCEOCTAL) && (text[0] != '0' || textlen == 0)) {
+ *--text = '0';
+ ++textlen; /* add a zero */
+ }
+ }
+ break;
+ }
+
+ /* At this point, we have done the specific conversion, and */
+ /* 'text' points to text to print; 'textlen' is length. Now we */
+ /* justify it, put on prefixes, leading zeros, and then */
+ /* print it. */
+
+ if (!no_output) {
+ int padding; /* amount of padding, negative means zero */
+
+ if (flags & FL_SIGNED) {
+ if (flags & FL_NEGATIVE) {
+ /* prefix is a '-' */
+ prefix[0] = '-';
+ prefixlen = 1;
+ }
+ else if (flags & FL_SIGN) {
+ /* prefix is '+' */
+ prefix[0] = '+';
+ prefixlen = 1;
+ }
+ else if (flags & FL_SIGNSP) {
+ /* prefix is ' ' */
+ prefix[0] = ' ';
+ prefixlen = 1;
+ }
+ }
+
+ /* calculate amount of padding -- might be negative, */
+ /* but this will just mean zero */
+ padding = fldwidth - textlen - prefixlen;
+
+ /* put out the padding, prefix, and text, in the correct order */
+
+ if (!(flags & (FL_LEFT | FL_LEADZERO))) {
+ /* pad on left with blanks */
+ f->writechar(' ', padding, f, &charsout);
+ }
+
+ /* write prefix */
+ writestring(prefix, prefixlen, f, &charsout, 0);
+
+ if ((flags & FL_LEADZERO) && !(flags & FL_LEFT)) {
+ /* write leading zeros */
+ f->writechar('0', padding, f, &charsout);
+ }
+
+ /* write text */
+ writestring(text, textlen, f, &charsout, flags & FL_WIDE);
+
+ if (flags & FL_LEFT) {
+ /* pad on right with blanks */
+ f->writechar(' ', padding, f, &charsout);
+ }
+
+ /* we're done! */
+ }
+ break;
+ }
+ }
+
+ return charsout; /* return value = number of characters written */
+}
+
+
+/***
+*int get_int_arg(va_list pargptr)
+*
+*Purpose:
+* Gets an int argument off the given argument list and updates *pargptr.
+*
+*Entry:
+* va_list pargptr - pointer to argument list; updated by function
+*
+*Exit:
+* Returns the integer argument read from the argument list.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+LOCAL(int) get_int_arg(va_list *pargptr)
+{
+ return va_arg(*pargptr, int);
+}
+
+/***
+*long get_long_arg(va_list pargptr)
+*
+*Purpose:
+* Gets an long argument off the given argument list and updates pargptr.
+*
+*Entry:
+* va_list pargptr - pointer to argument list; updated by function
+*
+*Exit:
+* Returns the long argument read from the argument list.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+#if !LONG_IS_INT
+LOCAL(long) get_long_arg(va_list *pargptr)
+{
+ return va_arg(*pargptr, long);
+}
+#endif
+
+
+
+/***
+*void writestring(char *string, int len, struct w4io *f, int *pcchwritten, int fwide)
+*
+*Purpose:
+* Writes a string of the given length to the given file. If no error occurs,
+* then *pcchwritten is incremented by len; otherwise, *pcchwritten is set
+* to -1. If len is negative, it is treated as zero.
+*
+*Entry:
+* char *string - string to write (NOT null-terminated)
+* int len - length of string
+* struct w4io *f - file to write to
+* int *pcchwritten - pointer to integer to update with total chars written
+* int fwide - wide character flag
+*
+*Exit:
+* No return value.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+LOCAL(void) writestring(
+ char *string,
+ int len,
+ struct w4io *f,
+ int *pcchwritten,
+ int fwide)
+{
+ wchar_t *pwc;
+
+ //printf("string: str=%.*s, len=%d, cch=%d, f=%d\n", len, string, len, *pcchwritten, fwide);
+ if (fwide) {
+ pwc = (wchar_t *) string;
+ while (len-- > 0) {
+ if (*pwc & 0xff00) {
+ f->writechar('^', 1, f, pcchwritten);
+ }
+ f->writechar((char) *pwc++, 1, f, pcchwritten);
+ }
+ } else {
+ while (len-- > 0) {
+ f->writechar(*string++, 1, f, pcchwritten);
+ }
+ }
+}
+
+
+const wchar_t a_wcDigits[] = L"0123456789ABCDEF";
+
+//+---------------------------------------------------------------------------
+//
+// Function: FormatHexNum
+//
+// Synopsis: Given a value, and a count of characters, translate
+// the value into a hex string. This is the ANSI version
+//
+// Arguments: [ulValue] -- Value to convert
+// [chChars] -- Number of characters to format
+// [pchStr] -- Pointer to output buffer
+//
+// Requires: pwcStr must be valid for chChars
+//
+// History: 5-31-95 t-stevan Copied and Modified for use in debug output function
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+void FormatHexNum( unsigned long ulValue, unsigned long chChars, char *pchStr)
+{
+ while(chChars--)
+ {
+ pchStr[chChars] = (char) a_wcDigits[ulValue & 0xF];
+ ulValue = ulValue >> 4;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: StrFromGUID (private)
+//
+// Synopsis: Converts a GUID into a string (duh!)
+//
+// Arguments: [rguid] - the guid to convert
+// [lpszy] - buffer to hold the results
+// [cbMax] - sizeof the buffer
+//
+// Returns: amount of data copied to lpsz if successful
+// 0 if buffer too small.
+//
+//--------------------------------------------------------------------------
+
+int StrFromGUID(REFGUID rguid, char * lpsz, int cbMax) // internal
+{
+ if (cbMax < GUIDSTR_MAX)
+ return 0;
+
+
+// Make the GUID into"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+
+ *lpsz++ = '{';
+ FormatHexNum( rguid->Data1, 8 , lpsz);
+ lpsz += 8;
+ *lpsz++ = '-';
+
+ FormatHexNum( rguid->Data2, 4 , lpsz);
+ lpsz += 4;
+ *lpsz++ = '-';
+
+ FormatHexNum( rguid->Data3, 4 , lpsz);
+ lpsz += 4;
+ *lpsz++ = '-';
+
+ FormatHexNum( rguid->Data4[0], 2 , lpsz);
+ lpsz += 2;
+ FormatHexNum( rguid->Data4[1], 2 , lpsz);
+ lpsz += 2;
+ *lpsz++ = '-';
+
+ FormatHexNum( rguid->Data4[2], 2 , lpsz);
+ lpsz += 2;
+ FormatHexNum( rguid->Data4[3], 2 , lpsz);
+ lpsz += 2;
+ FormatHexNum( rguid->Data4[4], 2 , lpsz);
+ lpsz += 2;
+ FormatHexNum( rguid->Data4[5], 2 , lpsz);
+ lpsz += 2;
+ FormatHexNum( rguid->Data4[6], 2 , lpsz);
+ lpsz += 2;
+ FormatHexNum( rguid->Data4[7], 2 , lpsz);
+ lpsz += 2;
+
+ *lpsz++ = '}';
+ /* We don't want to tag on a NULL char because we don't need to print one out *\
+ /* *lpsz = 0; */
+
+
+ return GUIDSTR_MAX;
+}
+
+
diff --git a/private/ole32/stg/async/debug/printf.c b/private/ole32/stg/async/debug/printf.c
new file mode 100644
index 000000000..9d6f6403e
--- /dev/null
+++ b/private/ole32/stg/async/debug/printf.c
@@ -0,0 +1,17 @@
+/***
+*printf.c - print formatted to stdout
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4printf() - print formatted data to stdout
+* defines w4vprintf() - print formatted output to stdout, get data
+* from an argument ptr instead of explicit args.
+*******************************************************************************/
+
+#ifdef FLAT
+#include "dprintf.h" // function prototypes
+
+#define _W4PRINTF_
+#include "printf.h"
+#endif
diff --git a/private/ole32/stg/async/debug/printf.h b/private/ole32/stg/async/debug/printf.h
new file mode 100644
index 000000000..2a03d6b64
--- /dev/null
+++ b/private/ole32/stg/async/debug/printf.h
@@ -0,0 +1,245 @@
+/***
+*printf.h - print formatted
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4*printf() - print formatted data
+* defines w4v*printf() - print formatted output, get data from an
+* argument ptr instead of explicit args.
+*
+*Revision History:
+* 09-02-83 RN original sprintf
+* 06-17-85 TC rewrote to use new varargs macros, and to be vsprintf
+* 04-13-87 JCR added const to declaration
+* 11-07-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-13-88 JCR Fake _iob entry is now static so that other routines
+* can assume _iob entries are in DGROUP.
+* 08-25-88 GJF Define MAXSTR to be INT_MAX (from LIMITS.H).
+* 06-06-89 JCR 386 mthread support
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 WIN32
+* model). Also fixed copyright and indents.
+* 02-16-90 GJF Fixed copyright
+*
+*******************************************************************************/
+
+#include <windows.h>
+#include <wchar.h>
+#include <stdarg.h>
+#include <limits.h>
+#include "w4io.h"
+
+#if defined(_W4PRINTF_)
+ static long fh;
+// extern long GetStdHandle(long);
+// extern void WriteFile(long fh, char *s, long cch, long * pcchret, long);
+# define _PRINTF_
+#elif defined(_W4DPRINTF_)
+# define _pwritechar _dwritechar
+# define _pflushbuf _dflushbuf
+# define w4printf w4dprintf
+# define w4vprintf w4vdprintf
+# define _PRINTF_
+#elif defined(_W4SPRINTF_)
+# define _pwritechar _swritechar
+# define w4printf w4sprintf
+# define w4vprintf w4vsprintf
+#elif defined(_W4WCSPRINTF_)
+# define _TCHAR_ wchar_t
+# define _PBUF_ pwcbuf
+# define _PSTART_ pwcstart
+# define w4printf w4wcsprintf
+# define w4vprintf w4vwcsprintf
+# define _pwritechar _wwritechar
+#else
+# error configuration problem
+#endif
+
+#ifndef _TCHAR_
+# define _TCHAR_ char
+# define _PBUF_ pchbuf
+# define _PSTART_ pchstart
+#endif
+
+
+#ifdef _PRINTF_
+# ifdef WIN32
+# undef OutputDebugString
+# define OutputDebugString OutputDebugStringA
+# else
+ extern void _pascal OutputDebugString(char *);
+# endif
+ int _cdecl _pflushbuf(struct w4io *f);
+# define SPR(a)
+# define MAXSTR 128
+#else
+# define SPR(a) a,
+# define MAXSTR INT_MAX
+#endif
+
+void _cdecl _pwritechar(int ch, int num, struct w4io *f, int *pcchwritten);
+int _cdecl w4vprintf(SPR(_TCHAR_ *string) const char *format, va_list arglist);
+
+
+/***
+*int w4printf(format, ...) - print formatted data
+*
+*Purpose:
+* Prints formatted data using the format string to
+* format data and getting as many arguments as called for
+* Sets up a w4io so file i/o operations can be used.
+* w4iooutput does the real work here
+*
+*Entry:
+* char *format - format string to control data format/number
+* of arguments followed by list of arguments, number and type
+* controlled by format string
+*
+*Exit:
+* returns number of characters written
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+int _cdecl
+w4printf(SPR(_TCHAR_ *string) const char *format, ...)
+/*
+ * 'PRINT', 'F'ormatted
+ */
+{
+ va_list arglist;
+
+ va_start(arglist, format);
+ return(w4vprintf(SPR(string) format, arglist));
+}
+
+
+/***
+*int w4vprintf(format, arglist) - print formatted data from arg ptr
+*
+*Purpose:
+* Prints formatted data, but gets data from an argument pointer.
+* Sets up a w4io so file i/o operations can be used, make string look
+* like a huge buffer to it, but _flsbuf will refuse to flush it if it
+* fills up. Appends '\0' to make it a true string.
+*
+* Multi-thread: (1) Since there is no stream, this routine must never try
+* to get the stream lock (i.e., there is no stream lock either). (2)
+* Also, since there is only one staticly allocated 'fake' iob, we must
+* lock/unlock to prevent collisions.
+*
+*Entry:
+* char *format - format string, describes format of data
+* va_list arglist - varargs argument pointer
+*
+*Exit:
+* returns number of characters written
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _cdecl
+w4vprintf(SPR(_TCHAR_ *string) const char *format, va_list arglist)
+/*
+ * 'V'ariable argument 'PRINT', 'F'ormatted
+ */
+{
+ struct w4io outfile;
+ register int retval;
+#ifdef _PRINTF_
+ char string[MAXSTR + 1]; // leave room for null termination
+#else
+ int dummy;
+#endif
+
+#ifdef _W4PRINTF_
+ long ldummy;
+
+ if (fh == 0 || fh == -1)
+ {
+ ldummy = -11; // C7 bug workaround
+ if ((fh = (long)GetStdHandle(ldummy)) == 0 || fh == -1)
+ {
+ OutputDebugString("GetStdHandle in " __FILE__ " failed\n");
+ return(-1);
+ }
+ }
+#endif
+
+ outfile._PBUF_ = outfile._PSTART_ = string;
+ outfile.cchleft = MAXSTR;
+ outfile.writechar = _pwritechar;
+
+ retval = w4iooutput(&outfile, format, arglist);
+
+#ifdef _PRINTF_
+ if (_pflushbuf(&outfile) == -1) {
+ return(-1);
+ }
+#else
+ _pwritechar('\0', 1, &outfile, &dummy);
+#endif
+ return(retval);
+}
+
+
+void _cdecl _pwritechar(int ch, int num, struct w4io *f, int *pcchwritten)
+{
+ //printf(" char: ch=%c, cnt=%d, cch=%d\n", ch, num, *pcchwritten);
+ while (num-- > 0) {
+#ifdef _PRINTF_
+ if (f->cchleft < 2 && _pflushbuf(f) == -1) {
+ *pcchwritten = -1;
+ return;
+ }
+#endif
+#ifdef _W4DPRINTF_
+# ifndef WIN32
+ if (ch == '\n')
+ {
+ *f->_PBUF_++ = '\r';
+ f->cchleft--;
+ (*pcchwritten)++;
+ }
+# endif
+#endif
+ *f->_PBUF_++ = (char) ch;
+ f->cchleft--;
+ (*pcchwritten)++;
+ }
+}
+
+
+#ifdef _PRINTF_
+int _cdecl _pflushbuf(struct w4io *f)
+{
+ int cch;
+
+ if (cch = (f->pchbuf - f->pchstart))
+ {
+#ifdef _W4DPRINTF_
+ *f->pchbuf = '\0'; // null terminate
+ OutputDebugString(f->pchstart);
+#else
+ long cchret;
+
+ //*f->pchbuf = '\0'; // null terminate
+ //printf("%d chars: \"%s\"\n", cch, f->pchstart);
+ WriteFile((HANDLE)fh, f->pchstart, cch, &cchret, 0);
+ if (cch != cchret)
+ {
+ OutputDebugString("WriteFile in " __FILE__ " failed\n");
+ return(-1);
+ }
+#endif
+ f->pchbuf -= cch; // reset pointer
+ f->cchleft += cch; // reset count
+ }
+ return(0);
+}
+#endif // _PRINTF_
diff --git a/private/ole32/stg/async/debug/sprintf.c b/private/ole32/stg/async/debug/sprintf.c
new file mode 100644
index 000000000..8fa23b0f4
--- /dev/null
+++ b/private/ole32/stg/async/debug/sprintf.c
@@ -0,0 +1,13 @@
+/***
+*sprintf.c - print formatted to string
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4sprintf() - print formatted data to string
+* defines w4vsprintf() - print formatted output to a string, get data
+* from an argument ptr instead of explicit args.
+*******************************************************************************/
+
+#define _W4SPRINTF_
+#include "printf.h"
diff --git a/private/ole32/stg/async/debug/w4io.h b/private/ole32/stg/async/debug/w4io.h
new file mode 100644
index 000000000..e88fd62b4
--- /dev/null
+++ b/private/ole32/stg/async/debug/w4io.h
@@ -0,0 +1,49 @@
+/***
+*w4io.h - fake FILE structure for Win 4 printf/sprintf/debug printf support
+*
+*/
+
+#if defined(M_I386) || defined(WIN32)
+# ifndef WIN32
+# define WIN32
+# endif
+#elif !defined(M_I86LM)
+# error Must be FLAT or LARGE model.
+#endif
+
+#ifndef NULL
+# define NULL 0
+#endif
+
+struct w4io
+{
+ union
+ {
+ struct
+ {
+ wchar_t *_pwcbuf; // wchar_t output buffer
+ wchar_t *_pwcstart;
+ } wc;
+ struct
+ {
+ char *_pchbuf; // char output buffer
+ char *_pchstart;
+ } ch;
+ } buf ;
+ unsigned int cchleft; // output buffer character count
+ void (_cdecl *writechar)(int ch,
+ int num,
+ struct w4io *f,
+ int *pcchwritten);
+};
+
+#define pwcbuf buf.wc._pwcbuf
+#define pwcstart buf.wc._pwcstart
+#define pchbuf buf.ch._pchbuf
+#define pchstart buf.ch._pchstart
+
+#define REG1 register
+#define REG2 register
+
+/* prototypes */
+int _cdecl w4iooutput(struct w4io *stream, const char *format, va_list argptr);
diff --git a/private/ole32/stg/async/debug/wsprintf.c b/private/ole32/stg/async/debug/wsprintf.c
new file mode 100644
index 000000000..83a74fb76
--- /dev/null
+++ b/private/ole32/stg/async/debug/wsprintf.c
@@ -0,0 +1,14 @@
+/***
+*sprintf.c - print formatted to string
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4wcsprintf() - print formatted data to wide character string
+* defines w4vwcsprintf() - print formatted output to a wide character
+* string, get data from argument ptr instead
+* of explicit args.
+*******************************************************************************/
+
+#define _W4WCSPRINTF_
+#include "printf.h"
diff --git a/private/ole32/stg/async/dfsetup/dfsetup.cxx b/private/ole32/stg/async/dfsetup/dfsetup.cxx
new file mode 100644
index 000000000..19b36c1d8
--- /dev/null
+++ b/private/ole32/stg/async/dfsetup/dfsetup.cxx
@@ -0,0 +1,40 @@
+#include "windows.h"
+
+_CRTAPI1 main(int argc, char **argv)
+{
+ char szSystemPath[_MAX_PATH];
+
+ char szFilename[_MAX_PATH];
+ char szCurPath[_MAX_PATH];
+
+ int len;
+ UINT dwFilename = _MAX_PATH;
+ DWORD dwstatus;
+
+ if (GetSystemDirectory(szSystemPath, _MAX_PATH) == 0)
+ {
+ return (dwstatus = GetLastError());
+ }
+
+
+ //Get the path to the install source directory
+ if ((len = GetModuleFileName(NULL, szCurPath, _MAX_PATH)) == 0)
+ {
+ return (dwstatus =GetLastError());
+ }
+
+ while (szCurPath[--len] != '\\')
+ continue;
+ szCurPath[len+1] = '\0';
+
+ // install the file to the system directory
+ dwstatus = VerInstallFile(0,"DFLAYOUT.DLL", "DFLAYOUT.DLL",
+ szCurPath, szSystemPath, szSystemPath,
+ szFilename, &dwFilename);
+
+
+ return dwstatus;
+
+
+}
+
diff --git a/private/ole32/stg/async/dfsetup/dfsetup.rc b/private/ole32/stg/async/dfsetup/dfsetup.rc
new file mode 100644
index 000000000..f7d656851
--- /dev/null
+++ b/private/ole32/stg/async/dfsetup/dfsetup.rc
@@ -0,0 +1,19 @@
+#include <windows.h>
+
+//
+// Version resources
+//
+#include <ntverp.h>
+#undef VER_PRODUCTNAME_STR
+#define VER_PRODUCTNAME_STR "Microsoft Docfile Layout Tool for OLE Setup\0"
+#define VER_COMMENT_STR "Microsoft Docfile Layout Tool for OLE Setup\0"
+#define VER_FILEDESCRIPTION_STR "Microsoft Docfile Layout Tool for OLE Setup\0"
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_INTERNALNAME_STR "DFSETUP.EXE"
+#define VER_ORIGINALFILENAME_STR "DFSETUP.EXE"
+#include <common.ver>
+
+
+
+
diff --git a/private/ole32/stg/async/dfsetup/makefile b/private/ole32/stg/async/dfsetup/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/async/dfsetup/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/async/dfsetup/sources b/private/ole32/stg/async/dfsetup/sources
new file mode 100644
index 000000000..408bc5835
--- /dev/null
+++ b/private/ole32/stg/async/dfsetup/sources
@@ -0,0 +1,108 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Susi Argo (SusiA) 16-Jul-96
+
+!ENDIF
+
+
+MAJORCOMP = dfsetup
+MINORCOMP = dfsetup
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= dfsetup
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= PROGRAM
+
+INCLUDES=
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DNOEXCEPTIONS \
+ -DINC_OLE2 \
+ -DFLAT \
+ -DWIN32=100 \
+ -D_NT1X_=100 \
+ -DCAIROLE_DOWNLEVEL \
+ -DDCOM \
+ -DMSWMSG \
+ -DDCOM_SECURITY \
+ -DNEWPROPS \
+ -D_TRACKLINK_=1 \
+ $(TRACELOG)
+
+#BLDCRT= 1
+#USE_LIBCMT=1
+
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+NTLEGO=1
+
+GPCH_BUILD=daytona
+
+
+
+PRECOMPILED_INCLUDE=
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
+
+SOURCES= \
+ dfsetup.rc \
+ dfsetup.cxx
+
+
+UMTYPE= console
+#UMENTRY=
+UMAPPL=
+UMTEST=
+
+LINKLIBS= \
+# $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+# $(BASEDIR)\public\sdk\lib\*\user32.lib \
+# $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+# $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+# $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+# $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \
+# $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\version.lib
+
+
+
+!include sources.inc
+
diff --git a/private/ole32/stg/async/dfsetup/sources.inc b/private/ole32/stg/async/dfsetup/sources.inc
new file mode 100644
index 000000000..9a091ed81
--- /dev/null
+++ b/private/ole32/stg/async/dfsetup/sources.inc
@@ -0,0 +1 @@
+SYNCHRONIZE_DRAIN=1
diff --git a/private/ole32/stg/async/dftool/dftool.cxx b/private/ole32/stg/async/dftool/dftool.cxx
new file mode 100644
index 000000000..5c3f3a55a
--- /dev/null
+++ b/private/ole32/stg/async/dftool/dftool.cxx
@@ -0,0 +1,51 @@
+#include "windows.h"
+
+_CRTAPI1 main(int argc, char **argv)
+{
+ char szSystemPath[_MAX_PATH];
+
+ char szFilename[_MAX_PATH];
+ char szCurPath[_MAX_PATH];
+
+ int len;
+ UINT dwFilename = _MAX_PATH;
+ DWORD dwstatus;
+
+ if (GetSystemDirectory(szSystemPath, _MAX_PATH) == 0)
+ {
+ return (dwstatus = GetLastError());
+ }
+
+
+ //Get the path to the install source directory
+ if ((len = GetModuleFileName(NULL, szCurPath, _MAX_PATH)) == 0)
+ {
+ return (dwstatus =GetLastError());
+ }
+
+ while (szCurPath[--len] != '\\')
+ continue;
+ szCurPath[len+1] = '\0';
+
+ // install the file to the system directory
+ dwstatus = VerInstallFile(0,"DFLAYOUT.DLL", "DFLAYOUT.DLL",
+ szCurPath, szSystemPath, szSystemPath,
+ szFilename, &dwFilename);
+ if (dwstatus)
+ {
+ return dwstatus;
+ }
+
+
+ // install the file to the system directory
+ dwFilename = _MAX_PATH;
+ dwstatus = VerInstallFile(0,"DFLAYOUT.EXE", "DFLAYOUT.EXE",
+ szCurPath, szSystemPath, szSystemPath,
+ szFilename, &dwFilename);
+
+
+ return dwstatus;
+
+
+}
+
diff --git a/private/ole32/stg/async/dftool/dftool.rc b/private/ole32/stg/async/dftool/dftool.rc
new file mode 100644
index 000000000..38f9c95a3
--- /dev/null
+++ b/private/ole32/stg/async/dftool/dftool.rc
@@ -0,0 +1,19 @@
+#include <windows.h>
+
+//
+// Version resources
+//
+#include <ntverp.h>
+#undef VER_PRODUCTNAME_STR
+#define VER_PRODUCTNAME_STR "Microsoft Docfile Layout User Tool for OLE Setup\0"
+#define VER_COMMENT_STR "Microsoft Docfile Layout User Tool for OLE Setup\0"
+#define VER_FILEDESCRIPTION_STR "Microsoft Docfile Layout User Tool for OLE Setup\0"
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_INTERNALNAME_STR "DFTOOL.EXE"
+#define VER_ORIGINALFILENAME_STR "DFTOOL.EXE"
+#include <common.ver>
+
+
+
+
diff --git a/private/ole32/stg/async/dftool/makefile b/private/ole32/stg/async/dftool/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/async/dftool/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/async/dftool/sources b/private/ole32/stg/async/dftool/sources
new file mode 100644
index 000000000..d2610fea1
--- /dev/null
+++ b/private/ole32/stg/async/dftool/sources
@@ -0,0 +1,108 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Susi Argo (SusiA) 16-Jul-96
+
+!ENDIF
+
+
+MAJORCOMP = dftool
+MINORCOMP = dftool
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= dftool
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= PROGRAM
+
+INCLUDES=
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DNOEXCEPTIONS \
+ -DINC_OLE2 \
+ -DFLAT \
+ -DWIN32=100 \
+ -D_NT1X_=100 \
+ -DCAIROLE_DOWNLEVEL \
+ -DDCOM \
+ -DMSWMSG \
+ -DDCOM_SECURITY \
+ -DNEWPROPS \
+ -D_TRACKLINK_=1 \
+ $(TRACELOG)
+
+#BLDCRT= 1
+#USE_LIBCMT=1
+
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+NTLEGO=1
+
+GPCH_BUILD=daytona
+
+
+
+PRECOMPILED_INCLUDE=
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
+
+SOURCES= \
+ dftool.rc \
+ dftool.cxx
+
+
+UMTYPE= console
+#UMENTRY=
+UMAPPL=
+UMTEST=
+
+LINKLIBS= \
+# $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+# $(BASEDIR)\public\sdk\lib\*\user32.lib \
+# $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+# $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+# $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+# $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \
+# $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\version.lib
+
+
+
+!include sources.inc
+
diff --git a/private/ole32/stg/async/dftool/sources.inc b/private/ole32/stg/async/dftool/sources.inc
new file mode 100644
index 000000000..9a091ed81
--- /dev/null
+++ b/private/ole32/stg/async/dftool/sources.inc
@@ -0,0 +1 @@
+SYNCHRONIZE_DRAIN=1
diff --git a/private/ole32/stg/async/dirs b/private/ole32/stg/async/dirs
new file mode 100644
index 000000000..522d1524b
--- /dev/null
+++ b/private/ole32/stg/async/dirs
@@ -0,0 +1,41 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Rick Sailor (Ricksa) 24-Jan-1994
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS= debug \
+ docfile \
+ layout \
+ layoutui \
+ dftool \
+ dfsetup
+
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS=test
diff --git a/private/ole32/stg/async/docfile/astg.hxx b/private/ole32/stg/async/docfile/astg.hxx
new file mode 100644
index 000000000..211a62f1f
--- /dev/null
+++ b/private/ole32/stg/async/docfile/astg.hxx
@@ -0,0 +1,83 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: astg.hxx
+//
+// Contents: Common header file for async docfiles
+//
+// Classes:
+//
+// Functions:
+//
+// History: 19-Dec-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ASTG_HXX__
+#define __ASTG_HXX__
+
+#if DBG == 1
+DECLARE_DEBUG(astg);
+#endif
+
+#if DBG == 1
+
+#define astgDebugOut(x) astgInlineDebugOut x
+#ifndef REF
+#define astgAssert(e) Win4Assert(e)
+#define astgVerify(e) Win4Assert(e)
+#else
+#include <assert.h>
+#define astgAssert(e) assert(e)
+#define astgVerify(e) assert(e)
+#endif //!REF
+
+#else
+
+#define astgDebugOut(x)
+#define astgAssert(e)
+#define astgVerify(e) (e)
+
+#endif
+
+#define astgErr(l, e) ErrJmp(astg, l, e, sc)
+#define astgChkTo(l, e) if (FAILED(sc = (e))) astgErr(l, sc) else 1
+#define astgHChkTo(l, e) if (FAILED(sc = GetScode(e))) astgErr(l, sc) else 1
+#define astgChk(e) astgChkTo(Err, e)
+#define astgHChk(e) astgHChkTo(Err, e)
+#define astgMemTo(l, e) if ((e) == NULL) astgErr(l, STG_E_INSUFFICIENTMEMORY) else 1
+#define astgMem(e) astgMemTo(Err, e)
+
+
+#if 0
+#define IsValidHugePtrIn(pv, n) (((pv) == NULL) || !IsBadHugeReadPtr(pv, n))
+#define IsValidHugePtrOut(pv, n) (!IsBadHugeWritePtr(pv, n))
+
+#define ValidateBuffer(pv, n) \
+ (((pv) == NULL || !IsValidPtrIn(pv, n)) ? STG_E_INVALIDPOINTER : S_OK)
+
+#define ValidatePtrBuffer(pv) \
+ ValidateBuffer(pv, sizeof(void *))
+
+#define ValidateHugeBuffer(pv, n) \
+ (((pv) == NULL || !IsValidHugePtrIn(pv, n)) ? STG_E_INVALIDPOINTER : S_OK)
+
+#define ValidateOutBuffer(pv, n) \
+ (!IsValidPtrOut(pv, n) ? STG_E_INVALIDPOINTER : S_OK)
+
+#define ValidateOutPtrBuffer(pv) \
+ ValidateOutBuffer(pv, sizeof(void *))
+
+#define ValidateHugeOutBuffer(pv, n) \
+ (!IsValidHugePtrOut(pv, n) ? STG_E_INVALIDPOINTER : S_OK)
+#endif
+
+#ifndef ASYNC
+#define UNTERMINATED 0
+#define TERMINATED_NORMAL 1
+#define TERMINATED_ABNORMAL 2
+#endif
+
+#endif // #ifndef __ASTG_HXX__
diff --git a/private/ole32/stg/async/docfile/astghead.cxx b/private/ole32/stg/async/docfile/astghead.cxx
new file mode 100644
index 000000000..5208cac88
--- /dev/null
+++ b/private/ole32/stg/async/docfile/astghead.cxx
@@ -0,0 +1,41 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1996 - 1996.
+//
+// File: astghead.cxx
+//
+// Contents: Precompiled header for async
+//
+// History: 28-Mar-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+}
+
+#include <windows.h>
+#include <ole2.h>
+#include <ocidl.h>
+
+#if defined(_CHICAGO_)
+#include <widewrap.h>
+#endif
+
+#include <debnot.h>
+#include <error.hxx>
+#include <except.hxx>
+#include <docfilep.hxx>
+#include <dfmsp.hxx>
+
+
+#include "astg.hxx"
+#include "asyncerr.hxx"
+
+#if defined (_CHICAGO_)
+#include <widewrap.h>
+#endif
diff --git a/private/ole32/stg/async/docfile/asyncapi.cxx b/private/ole32/stg/async/docfile/asyncapi.cxx
new file mode 100644
index 000000000..feeeddcfd
--- /dev/null
+++ b/private/ole32/stg/async/docfile/asyncapi.cxx
@@ -0,0 +1,331 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: asyncapi.cxx
+//
+// Contents: APIs for async docfiles
+//
+// Classes:
+//
+// Functions:
+//
+// History: 19-Dec-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "astghead.cxx"
+#pragma hdrstop
+
+#ifndef ASYNC
+#define USE_FILELKB
+#endif
+
+
+#include "asyncapi.hxx"
+#include "filllkb.hxx"
+#ifdef USE_FILELKB
+#include "filebyte.hxx"
+#endif
+
+#ifdef ASYNC
+#include <expdf.hxx>
+#endif
+
+
+#if DBG == 1
+DECLARE_INFOLEVEL(astg);
+#endif
+
+#ifdef ASYNC
+#ifdef COORD
+SCODE DfFromLB(CPerContext *ppc,
+ ILockBytes *plst,
+ DFLAGS df,
+ DWORD dwStartFlags,
+ SNBW snbExclude,
+ ITransaction *pTransaction,
+ CExposedDocFile **ppdfExp,
+ CLSID *pcid);
+#else
+SCODE DfFromLB(CPerContext *ppc,
+ ILockBytes *plst,
+ DFLAGS df,
+ DWORD dwStartFlags,
+ SNBW snbExclude,
+ CExposedDocFile **ppdfExp,
+ CLSID *pcid);
+#endif //COORD
+#endif //ASYNC
+
+
+STDAPI StgOpenAsyncDocfileOnIFillLockBytes(IFillLockBytes *pflb,
+ DWORD grfMode,
+ DWORD asyncFlags,
+ IStorage **ppstgOpen)
+{
+#ifdef ASYNC
+ SCODE sc;
+ ILockBytes *pilb;
+ IStorage *pstg;
+
+ sc = pflb->QueryInterface(IID_ILockBytes, (void **)&pilb);
+ if (FAILED(sc))
+ {
+ return sc;
+ }
+
+ //Next find out if we're opening on the docfile owned ILockBytes
+ // or on something custom. If it's docfile owned, then we can
+ // go directly to DfFromLB instead of using StgOpenStorageOnILockBytes
+ // which will avoid creating another shared heap.
+
+ IFileLockBytes *pfl;
+ if (SUCCEEDED(pflb->QueryInterface(IID_IFileLockBytes,
+ (void **)&pfl)))
+ {
+ pfl->Release();
+
+ CFileStream *pfst = (CFileStream *)pflb;
+ CPerContext *ppc = pfst->GetContextPointer();
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(ppc);
+#endif
+
+#ifdef COORD
+ astgChk(DfFromLB(ppc,
+ pfst,
+ ModeToDFlags(grfMode),
+ pfst->GetStartFlags(),
+ NULL,
+ NULL,
+ (CExposedDocFile **)&pstg,
+ NULL));
+#else
+ astgChk(DfFromLB(ppc,
+ pfst,
+ ModeToDFlags(grfMode),
+ pfst->GetStartFlags(),
+ NULL,
+ (CExposedDocFile **)&pstg,
+ NULL));
+#endif
+ //Note: Don't release the ILB reference we got from the QI
+ // above, since DfFromLB recorded that pointer but didn't
+ // AddRef it.
+ }
+ else
+ {
+ IFillLockBytes *pflb2;
+ if (SUCCEEDED(pilb->QueryInterface(IID_IDefaultFillLockBytes,
+ (void **)&pflb2)))
+ {
+ CFillLockBytes *pflbDefault = (CFillLockBytes *)pflb;
+ CPerContext *ppc;
+ pflb2->Release();
+ astgChk(StgOpenStorageOnILockBytes(pilb,
+ NULL,
+ grfMode,
+ NULL,
+ 0,
+ &pstg));
+ //Get PerContext pointer from pstg
+ ppc = ((CExposedDocFile *)pstg)->GetContext();
+ pflbDefault->SetContext(ppc);
+ }
+ else
+ {
+ astgChk(StgOpenStorageOnILockBytes(pilb,
+ NULL,
+ grfMode,
+ NULL,
+ 0,
+ &pstg));
+ }
+ pilb->Release();
+ }
+ astgChkTo(EH_stg, ((CExposedDocFile *)pstg)->InitConnection(NULL));
+ ((CExposedDocFile *)pstg)->SetAsyncFlags(asyncFlags);
+
+
+ *ppstgOpen = pstg;
+
+ return NOERROR;
+
+EH_stg:
+ pstg->Release();
+Err:
+ pilb->Release();
+ if (sc == STG_E_PENDINGCONTROL)
+ {
+ sc = E_PENDING;
+ }
+ return ResultFromScode(sc);
+#else
+ HRESULT hr;
+ ILockBytes *pilb;
+ IStorage *pstg;
+
+ hr = pflb->QueryInterface(IID_ILockBytes, (void **)&pilb);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = StgOpenStorageOnILockBytes(pilb,
+ NULL,
+ grfMode,
+ NULL,
+ 0,
+ &pstg);
+
+ pilb->Release();
+ if (FAILED(hr))
+ {
+ if (hr == STG_E_PENDINGCONTROL)
+ {
+ hr = E_PENDING;
+ }
+ return hr;
+ }
+
+ BOOL fDefault = FALSE;
+ IFillLockBytes *pflbDefault;
+ hr = pflb->QueryInterface(IID_IDefaultFillLockBytes,
+ (void **)&pflbDefault);
+ if (SUCCEEDED(hr))
+ {
+ fDefault = TRUE;
+ pflbDefault->Release();
+ }
+
+ *ppstgOpen = new CAsyncRootStorage(pstg, pflb, fDefault);
+ if (*ppstgOpen == NULL)
+ {
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+ else
+ {
+ ((CAsyncRootStorage *)(*ppstgOpen))->SetAsyncFlags(asyncFlags);
+ }
+
+ return NOERROR;
+#endif //ASYNC
+}
+
+STDAPI StgGetIFillLockBytesOnILockBytes( ILockBytes *pilb,
+ IFillLockBytes **ppflb)
+{
+ SCODE sc = S_OK;
+ CFillLockBytes *pflb = NULL;
+ pflb = new CFillLockBytes(pilb);
+ if (pflb == NULL)
+ {
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+ sc = pflb->Init();
+ if (FAILED(sc))
+ {
+ pflb->Release();
+ *ppflb = NULL;
+ return sc;
+ }
+
+ *ppflb = pflb;
+ return NOERROR;
+}
+
+
+STDAPI StgGetIFillLockBytesOnFile(OLECHAR const *pwcsName,
+ IFillLockBytes **ppflb)
+{
+#ifndef USE_FILELKB
+ SCODE sc;
+ IMalloc *pMalloc;
+ CFileStream *plst;
+ CFillLockBytes *pflb;
+ CPerContext *ppc;
+
+ DfInitSharedMemBase();
+ astgHChk(DfCreateSharedAllocator(&pMalloc));
+ astgMemTo(EH_Malloc, plst = new (pMalloc) CFileStream(pMalloc));
+ astgChkTo(EH_plst, plst->InitFlags(RSF_CREATE,
+ DF_DIRECT | DF_READ |
+ DF_WRITE | DF_DENYALL));
+ astgChkTo(EH_plst, plst->Init(pwcsName));
+
+ astgMemTo(EH_plstInit, ppc = new (pMalloc) CPerContext(pMalloc));
+ astgChkTo(EH_ppc, ppc->InitNewContext());
+ //We want 0 normal references on the per context, and one reference
+ // to the shared memory.
+ ppc->DecRef();
+ plst->SetContext(ppc);
+ plst->StartAsyncMode();
+ astgChkTo(EH_plstInit, ppc->InitNotificationEvent());
+
+ *ppflb = (IFillLockBytes *)plst;
+
+ return S_OK;
+
+EH_ppc:
+ delete ppc;
+EH_plstInit:
+ plst->Release();
+ goto EH_Malloc;
+EH_plst:
+ delete plst;
+EH_Malloc:
+ pMalloc->Release();
+Err:
+ return sc;
+#else
+ SCODE sc;
+ CFileLockBytes *pflb = NULL;
+ pflb = new CFileLockBytes;
+ if (pflb == NULL)
+ {
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+ sc = pflb->Init(pwcsName);
+ if (SUCCEEDED(sc))
+ {
+ sc = StgGetIFillLockBytesOnILockBytes(pflb, ppflb);
+ }
+ return sc;
+#endif // ASYNC
+}
+
+
+
+#if DBG == 1
+STDAPI StgGetDebugFileLockBytes(OLECHAR const *pwcsName, ILockBytes **ppilb)
+{
+#ifdef ASYNC
+ //BUGBUG: Implement
+ return STG_E_UNIMPLEMENTEDFUNCTION;
+#else
+ SCODE sc;
+ CFileLockBytes *pflb;
+
+ *ppilb = NULL;
+
+ pflb = new CFileLockBytes;
+ if (pflb == NULL)
+ {
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ sc = pflb->Init(pwcsName);
+ if (FAILED(sc))
+ {
+ delete pflb;
+ pflb = NULL;
+ }
+
+ *ppilb = pflb;
+
+ return sc;
+#endif // ASYNC
+}
+#endif
diff --git a/private/ole32/stg/async/docfile/asyncapi.hxx b/private/ole32/stg/async/docfile/asyncapi.hxx
new file mode 100644
index 000000000..73a3e12d8
--- /dev/null
+++ b/private/ole32/stg/async/docfile/asyncapi.hxx
@@ -0,0 +1,38 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: asyncapi.hxx
+//
+// Contents: API definitions for async storage
+//
+// Classes:
+//
+// Functions:
+//
+// History: 05-Jan-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ASYNCAPI_HXX__
+#define __ASYNCAPI_HXX__
+
+interface IFillLockBytes;
+
+STDAPI StgOpenAsyncDocfileOnIFillLockBytes( IFillLockBytes *pflb,
+ DWORD grfMode,
+ DWORD asyncFlags,
+ IStorage **ppstgOpen);
+
+STDAPI StgGetIFillLockBytesOnILockBytes( ILockBytes *pilb,
+ IFillLockBytes **ppflb);
+
+STDAPI StgGetIFillLockBytesOnFile(OLECHAR const *pwcsName,
+ IFillLockBytes **ppflb);
+
+#if DBG == 1
+STDAPI StgGetDebugFileLockBytes(OLECHAR const *pwcsName, ILockBytes **ppilb);
+#endif
+
+#endif // #ifndef __ASYNCAPI_HXX__
diff --git a/private/ole32/stg/async/docfile/asyncerr.hxx b/private/ole32/stg/async/docfile/asyncerr.hxx
new file mode 100644
index 000000000..ddf2d72e7
--- /dev/null
+++ b/private/ole32/stg/async/docfile/asyncerr.hxx
@@ -0,0 +1,26 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: asyncerr.hxx
+//
+// Contents: New error codes for async storage
+//
+// Classes:
+//
+// Functions:
+//
+// History: 03-Jan-96 PhilipLa Created
+//
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ASYNCERR_HXX__
+#define __ASYNCERR_HXX__
+
+#ifndef STG_E_PENDINGCONTROL
+#define STG_E_PENDINGCONTROL _HRESULT_TYPEDEF_(0x80030204L)
+#endif
+
+#endif // #ifndef __ASYNCERR_HXX__
diff --git a/private/ole32/stg/async/docfile/asyncstg.def b/private/ole32/stg/async/docfile/asyncstg.def
new file mode 100644
index 000000000..f60f648f3
--- /dev/null
+++ b/private/ole32/stg/async/docfile/asyncstg.def
@@ -0,0 +1,47 @@
+#if 0
+
+ Microsoft Windows
+ Copyright (C) Microsoft Corporation, 1992 - 1992.
+ All rights reserved.
+
+ This .def file is preprocessed by the compiler to create the version for
+ the current build in the appropriate subdir. Basically, whatever you
+ would have used in your code to control what is compiled when can be
+ used in this file for the same purpose. The following defines are in
+ use at the time this file was written:
+
+ FLAT - Used to indicate a NT/DOS7 build
+ i386 - Intel i386/i486 build
+ MIPS - MIPS R3000/R4000 build
+ ALPHA - DEC Alpha build
+ PPC - PowerPC build
+ DBG - Used to control Debug/Retail. Set to 1 if Debug,
+ 0 if Retail.
+ WIN31 - Win16 build
+ __OS2__ - OS/2 build (used by CT mostly)
+
+ If none of these are used, it is assumed the entire file can be used
+ for all builds.
+
+#endif
+
+LIBRARY asyncstg
+
+DESCRIPTION 'Microsoft (R) Component OLE 2.0 Base DLL 1.00'
+
+#if defined(_CHICAGO_)
+;
+; No security under Win95, take advantage of shared data segments.
+;
+SECTIONS
+ .sdata READ WRITE SHARED
+#endif
+
+EXPORTS
+
+ StgOpenAsyncDocfileOnIFillLockBytes
+ StgGetIFillLockBytesOnILockBytes
+ StgGetIFillLockBytesOnFile
+#if DBG == 1
+ StgGetDebugFileLockBytes
+#endif
diff --git a/private/ole32/stg/async/docfile/asyncver.h b/private/ole32/stg/async/docfile/asyncver.h
new file mode 100644
index 000000000..798ff8527
--- /dev/null
+++ b/private/ole32/stg/async/docfile/asyncver.h
@@ -0,0 +1,23 @@
+
+#ifdef RC_INVOKED
+
+#include <winver.h>
+
+#define VER_FILEVERSION_STR "0.0\0"
+#define VER_FILEVERSION 0,000,0000,0000
+
+#define VER_PRODUCTNAME_STR "Microsoft Asynchronous Storage for OLE\0"
+#define VER_COMPANYNAME_STR "Microsoft Corporation\0"
+#define VER_LEGALTRADEMARKS_STR "Microsoft\256 is a registered trademark of Microsoft Corporation. Windows NT(TM) is a trademark of Microsoft Corporation\0"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corp. 1992 - 1995\0"
+#define VER_PRODUCTVERSION_STR "0.0\0"
+#define VER_PRODUCTVERSION 0,0000,0000,0000
+#define VER_COMMENT_STR "Microsoft Asynchronous Storage for OLE\0"
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE 0
+#define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#define VER_FILEFLAGS 0L
+#define VER_FILEOS VOS_NT_WINDOWS32
+#define VER_FILEDESCRIPTION_STR "Microsoft Asynchronous Storage for OLE\0"
+
+#endif /* RC_INVOKED */
diff --git a/private/ole32/stg/async/docfile/daytona/makefile b/private/ole32/stg/async/docfile/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/async/docfile/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/async/docfile/daytona/makefile.inc b/private/ole32/stg/async/docfile/daytona/makefile.inc
new file mode 100644
index 000000000..6b0a97cf4
--- /dev/null
+++ b/private/ole32/stg/async/docfile/daytona/makefile.inc
@@ -0,0 +1,37 @@
+!ifndef MIDL
+MIDL = midl.exe
+!endif
+
+
+SDKINC=$(BASEDIR)\public\sdk\inc
+INCLUDES=$(SDKINC);$(INCLUDES)
+PASS0_HEADERDIR=$(SDKINC)
+PASS0_SOURCEDIR=obj
+
+MIDL_FLAGS= \
+ -Zp8 \
+ -I$(INCLUDES) \
+ -Oi2 \
+ -oldnames \
+ -char unsigned \
+ -error allocation \
+ -ms_ext -c_ext \
+ -DMIDL_PASS \
+ $(C_DEFINES) \
+ -cpp_cmd $(TARGET_CPP) \
+ -DMIDL_PASS $(C_DEFINES) -I$(INCLUDES)
+
+SSWITCH=-prefix sstub _
+
+obj\iconn.h: ..\iconn.idl
+ $(MIDL) $(MIDL_FLAGS) -header obj\iconn.h iconn.idl
+
+$(DOCFILEINC)\iconn.h: obj\iconn.h
+ copy obj\iconn.h $(DOCFILEINC)\iconn.h
+
+DEST_TREE=daytona
+
+allidl: obj\iconn.h
+
+clean:
+ -erase obj\iconn.h >NUL 2>NUL
diff --git a/private/ole32/stg/async/docfile/daytona/sources b/private/ole32/stg/async/docfile/daytona/sources
new file mode 100644
index 000000000..a574d25d4
--- /dev/null
+++ b/private/ole32/stg/async/docfile/daytona/sources
@@ -0,0 +1,78 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Philip Lafornara (PhilipLa) 19-Dec-1995
+
+!ENDIF
+
+
+MAJORCOMP = cairole
+MINORCOMP = stg
+
+!include ..\..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= asyncstg
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+DOCFILEINC=$(BASEDIR)\private\ole32\stg\h
+
+INCLUDES= ..;..\..\..\h;..\..\..\..\ih;..\..\..\..\com\inc;..\..\..\exp;..\..\..\props
+
+C_DEFINES= \
+ $(C_DEFINES)
+
+
+PRECOMPILED_INCLUDE= ..\astghead.cxx
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
+
+SOURCES= \
+ ..\asyncapi.cxx \
+ ..\filllkb.cxx \
+ ..\stgconn.cxx
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+
+NTTARGETFILE0=allidl \
+ $(DOCFILEINC)\iconn.h
+
+!include ..\sources.inc
+
diff --git a/private/ole32/stg/async/docfile/dirs b/private/ole32/stg/async/docfile/dirs
new file mode 100644
index 000000000..2677b40c1
--- /dev/null
+++ b/private/ole32/stg/async/docfile/dirs
@@ -0,0 +1,41 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Philip Lafornara (PhilipLa) 19-Dec-1995
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ daytona \
+ sweeper.day \
+ sweeper.chi
+
+
diff --git a/private/ole32/stg/async/docfile/filebyte.hxx b/private/ole32/stg/async/docfile/filebyte.hxx
new file mode 100644
index 000000000..63944fbc3
--- /dev/null
+++ b/private/ole32/stg/async/docfile/filebyte.hxx
@@ -0,0 +1,80 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: filebyte.hxx
+//
+// Contents: File ILockBytes class for async docfile
+//
+// Classes: CFileLockBytes
+//
+// Functions:
+//
+// History: 19-Dec-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FILEBYTE_HXX__
+#define __FILEBYTE_HXX__
+#define IID_IAsyncFileLockBytes IID_IDfReserved3
+
+//+---------------------------------------------------------------------------
+//
+// Class: CFileLockBytes
+//
+// Purpose:
+//
+// Interface:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+
+class CFileLockBytes: public ILockBytes
+{
+public:
+ CFileLockBytes();
+ ~CFileLockBytes();
+
+ SCODE Init(OLECHAR const *pwcsName);
+ ULONG FileDeleteRelease(void);
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+ // ILockBytes
+ STDMETHOD(ReadAt)(ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbRead);
+ STDMETHOD(WriteAt)(ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ STDMETHOD(Flush)(void);
+ STDMETHOD(SetSize)(ULARGE_INTEGER cb);
+ STDMETHOD(LockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+private:
+ LONG _cReferences;
+
+ CRITICAL_SECTION _cs;
+ HANDLE _h;
+
+ OLECHAR _acName[MAX_PATH + 1];
+};
+
+
+SCODE Win32ErrorToScode(DWORD dwErr);
+
+#endif // #ifndef __FILEBYTE_HXX__
diff --git a/private/ole32/stg/async/docfile/filelkb.cxx b/private/ole32/stg/async/docfile/filelkb.cxx
new file mode 100644
index 000000000..2e39da828
--- /dev/null
+++ b/private/ole32/stg/async/docfile/filelkb.cxx
@@ -0,0 +1,723 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: filelkb.cxx
+//
+// Contents: File ILockBytes implementation for async storage
+//
+// Classes:
+//
+// Functions:
+//
+// History: 19-Dec-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "astghead.cxx"
+#pragma hdrstop
+
+#include "filebyte.hxx"
+#include <valid.h>
+
+#define WIN32_SCODE(err) HRESULT_FROM_WIN32(err)
+#define LAST_STG_SCODE Win32ErrorToScode(GetLastError())
+
+#define boolChk(e) \
+ if (!(e)) astgErr(Err, LAST_STG_SCODE) else 1
+#define boolChkTo(l, e) \
+ if (!(e)) astgErr(l, LAST_STG_SCODE) else 1
+#define negChk(e) \
+ if ((e) == 0xffffffff) astgErr(Err, LAST_STG_SCODE) else 1
+#define negChkTo(l, e) \
+ if ((e) == 0xffffffff) astgErr(l, LAST_STG_SCODE) else 1
+
+
+class CSafeCriticalSection
+{
+public:
+ inline CSafeCriticalSection(CRITICAL_SECTION *pcs);
+ inline ~CSafeCriticalSection();
+private:
+ CRITICAL_SECTION *_pcs;
+};
+
+inline CSafeCriticalSection::CSafeCriticalSection(CRITICAL_SECTION *pcs)
+{
+ _pcs = pcs;
+ EnterCriticalSection(_pcs);
+}
+
+inline CSafeCriticalSection::~CSafeCriticalSection()
+{
+ LeaveCriticalSection(_pcs);
+#if DBG == 1
+ _pcs = NULL;
+#endif
+}
+
+#define TAKE_CS CSafeCriticalSection scs(&_cs);
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: Win32ErrorToScode, public
+//
+// Synopsis: Map a Win32 error into a corresponding scode, remapping
+// into Facility_Storage if appropriate.
+//
+// Arguments: [dwErr] -- Win32 error to map
+//
+// Returns: Appropriate scode
+//
+// History: 22-Sep-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+#ifdef SWEEPER
+SCODE Win32ErrorToScode(DWORD dwErr)
+{
+ astgAssert((dwErr != NO_ERROR) &&
+ "Win32ErrorToScode called on NO_ERROR");
+
+ SCODE sc = STG_E_UNKNOWN;
+
+ switch (dwErr)
+ {
+ case ERROR_INVALID_FUNCTION:
+ sc = STG_E_INVALIDFUNCTION;
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ sc = STG_E_FILENOTFOUND;
+ break;
+ case ERROR_PATH_NOT_FOUND:
+ sc = STG_E_PATHNOTFOUND;
+ break;
+ case ERROR_TOO_MANY_OPEN_FILES:
+ sc = STG_E_TOOMANYOPENFILES;
+ break;
+ case ERROR_ACCESS_DENIED:
+ case ERROR_NETWORK_ACCESS_DENIED:
+ sc = STG_E_ACCESSDENIED;
+ break;
+ case ERROR_INVALID_HANDLE:
+ sc = STG_E_INVALIDHANDLE;
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ sc = STG_E_INSUFFICIENTMEMORY;
+ break;
+ case ERROR_NO_MORE_FILES:
+ sc = STG_E_NOMOREFILES;
+ break;
+ case ERROR_WRITE_PROTECT:
+ sc = STG_E_DISKISWRITEPROTECTED;
+ break;
+ case ERROR_SEEK:
+ sc = STG_E_SEEKERROR;
+ break;
+ case ERROR_WRITE_FAULT:
+ sc = STG_E_WRITEFAULT;
+ break;
+ case ERROR_READ_FAULT:
+ sc = STG_E_READFAULT;
+ break;
+ case ERROR_SHARING_VIOLATION:
+ sc = STG_E_SHAREVIOLATION;
+ break;
+ case ERROR_LOCK_VIOLATION:
+ sc = STG_E_LOCKVIOLATION;
+ break;
+ case ERROR_HANDLE_DISK_FULL:
+ case ERROR_DISK_FULL:
+ sc = STG_E_MEDIUMFULL;
+ break;
+ case ERROR_FILE_EXISTS:
+ case ERROR_ALREADY_EXISTS:
+ sc = STG_E_FILEALREADYEXISTS;
+ break;
+ case ERROR_INVALID_PARAMETER:
+ sc = STG_E_INVALIDPARAMETER;
+ break;
+ case ERROR_INVALID_NAME:
+ case ERROR_BAD_PATHNAME:
+ case ERROR_FILENAME_EXCED_RANGE:
+ sc = STG_E_INVALIDNAME;
+ break;
+ case ERROR_INVALID_FLAGS:
+ sc = STG_E_INVALIDFLAG;
+ break;
+ default:
+ sc = WIN32_SCODE(dwErr);
+ break;
+ }
+
+ return sc;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileLockBytes::CFileLockBytes, public
+//
+// Synopsis: Default constructor
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+CFileLockBytes::CFileLockBytes(void)
+{
+ _cReferences = 1;
+ _h = INVALID_HANDLE_VALUE;
+ InitializeCriticalSection(&_cs);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileLockBytes::~CFileLockBytes, public
+//
+// Synopsis: Destructor
+//
+// Returns: Appropriate status code
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CFileLockBytes::~CFileLockBytes()
+{
+ if (_h != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(_h);
+ }
+ DeleteCriticalSection(&_cs);
+}
+//+---------------------------------------------------------------------------
+//
+// Member: CFileLockBytes::FileDeleteRelease, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// History: 13-Mar-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+ULONG CFileLockBytes::FileDeleteRelease(void)
+{
+ SCODE sc = S_OK;
+ LONG lRet;
+ astgDebugOut((DEB_ITRACE, "In CFileLockBytes::FileDeleteRelease:%p()\n", this));
+
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+ if (_h != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(_h);
+ _h = INVALID_HANDLE_VALUE;
+ #ifndef UNICODE
+ TCHAR atcPath[_MAX_PATH + 1];
+ UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ WideCharToMultiByte(uCodePage,
+ 0,
+ _acName,
+ -1,
+ atcPath,
+ _MAX_PATH + 1,
+ NULL,
+ NULL);
+
+
+ DeleteFileA(atcPath);
+#else
+ DeleteFile(_acName);
+#endif
+
+
+ }
+
+ delete this;
+ }
+ else if (lRet < 0)
+ {
+ lRet = 0;
+ }
+ astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::FileDeleteRelease\n"));
+ return lRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileLockBytes::Init, public
+//
+// Synopsis: Initialization function
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE CFileLockBytes::Init(OLECHAR const *pwcsName)
+{
+ astgDebugOut((DEB_ITRACE, "In CFileLockBytes::Init:%p()\n", this));
+
+#ifndef UNICODE
+ TCHAR atcPath[_MAX_PATH + 1];
+ UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ if (!WideCharToMultiByte(
+ uCodePage,
+ 0,
+ pwcsName,
+ -1,
+ atcPath,
+ _MAX_PATH + 1,
+ NULL,
+ NULL))
+ {
+ return STG_E_INVALIDNAME;
+ }
+
+ _h = CreateFileA(atcPath,
+ GENERIC_READ | GENERIC_WRITE, //Read-write
+ 0, // No sharing
+ NULL,
+ CREATE_NEW, //Create if necessary
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
+ NULL);
+#else
+ _h = CreateFile(pwcsName,
+ GENERIC_READ | GENERIC_WRITE, //Read-write
+ 0, // No sharing
+ NULL,
+ CREATE_NEW, //Create if necessary
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
+ NULL);
+#endif
+ if (_h == INVALID_HANDLE_VALUE)
+ {
+ return LAST_STG_SCODE;
+ }
+ lstrcpyW(_acName, pwcsName);
+
+ astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::Init\n"));
+ return S_OK;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CFileLockBytes::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 26-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CFileLockBytes::QueryInterface(REFIID iid, void **ppvObj)
+{
+ TAKE_CS;
+
+ SCODE sc;
+
+ astgDebugOut((DEB_ITRACE, "In CFileLockBytes::QueryInterface(?, %p)\n",
+ ppvObj));
+
+ astgChk(ValidateOutPtrBuffer(ppvObj));
+ *ppvObj = NULL;
+
+ sc = S_OK;
+ if (IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IUnknown *)this;
+ CFileLockBytes::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_ILockBytes))
+ {
+ *ppvObj = (ILockBytes *)this;
+ CFileLockBytes::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IAsyncFileLockBytes))
+ {
+ *ppvObj = (ILockBytes *)this;
+ CFileLockBytes::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::QueryInterface => %p\n",
+ ppvObj));
+
+Err:
+ return ResultFromScode(sc);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CFileLockBytes::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+// History: 16-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CFileLockBytes::AddRef(void)
+{
+ ULONG ulRet;
+
+ astgDebugOut((DEB_TRACE, "In CFileLockBytes::AddRef()\n"));
+
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+
+ astgDebugOut((DEB_TRACE, "Out CFileLockBytes::AddRef\n"));
+ return ulRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileLockBytes::Release, public
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CFileLockBytes::Release(void)
+{
+ LONG lRet;
+ astgDebugOut((DEB_ITRACE, "In CFileLockBytes::Release:%p()\n", this));
+
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ {
+ lRet = 0;
+ }
+ astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::Release\n"));
+ return lRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileLockBytes::ReadAt, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileLockBytes::ReadAt(ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbRead)
+{
+ TAKE_CS;
+
+ SCODE sc = S_OK;
+ astgDebugOut((DEB_ITRACE, "In CFileLockBytes::ReadAt:%p()\n", this));
+ ULONG ulLow = ulOffset.LowPart;
+ LONG lHigh = (LONG)ulOffset.HighPart;
+ negChk(SetFilePointer(_h,
+ ulLow,
+ &lHigh,
+ FILE_BEGIN));
+ boolChk(ReadFile(_h, pv, cb, pcbRead, NULL));
+
+ astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::ReadAt\n"));
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileLockBytes::WriteAt, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileLockBytes::WriteAt(ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ TAKE_CS;
+
+ SCODE sc = S_OK;
+ astgDebugOut((DEB_ITRACE, "In CFileLockBytes::WriteAt:%p()\n", this));
+
+ ULONG ulLow = ulOffset.LowPart;
+ LONG lHigh = (LONG)ulOffset.HighPart;
+ negChk(SetFilePointer(_h,
+ ulLow,
+ &lHigh,
+ FILE_BEGIN));
+ boolChk(WriteFile(_h, pv, cb, pcbWritten, NULL));
+
+ astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::WriteAt\n"));
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileLockBytes::Flush, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+//BUGBUG: Implement something here?
+STDMETHODIMP CFileLockBytes::Flush(void)
+{
+ TAKE_CS;
+
+ astgDebugOut((DEB_ITRACE, "In CFileLockBytes::Flush:%p()\n", this));
+ astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::Flush\n"));
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileLockBytes::SetSize, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileLockBytes::SetSize(ULARGE_INTEGER cb)
+{
+ TAKE_CS;
+
+ SCODE sc = S_OK;
+ astgDebugOut((DEB_ITRACE, "In CFileLockBytes::SetSize:%p()\n", this));
+ LONG lHigh = (LONG)cb.HighPart;
+ ULONG ulLow = cb.LowPart;
+
+ negChk(SetFilePointer(_h, ulLow, &lHigh, FILE_BEGIN));
+ boolChk(SetEndOfFile(_h));
+ astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::SetSize\n"));
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileLockBytes::LockRegion, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileLockBytes::LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ TAKE_CS;
+
+ SCODE sc = S_OK;
+ astgDebugOut((DEB_ITRACE, "In CFileLockBytes::LockRegion:%p()\n", this));
+ if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
+ {
+ return STG_E_INVALIDFUNCTION;
+ }
+
+ boolChk(LockFile(_h,
+ libOffset.LowPart,
+ libOffset.HighPart,
+ cb.LowPart,
+ cb.HighPart));
+
+ astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::LockRegion\n"));
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileLockBytes::UnlockRegion, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileLockBytes::UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ TAKE_CS;
+
+ SCODE sc = S_OK;
+ astgDebugOut((DEB_ITRACE, "In CFileLockBytes::UnlockRegion:%p()\n", this));
+ if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
+ {
+ return STG_E_INVALIDFUNCTION;
+ }
+
+ boolChk(UnlockFile(_h,
+ libOffset.LowPart,
+ libOffset.HighPart,
+ cb.LowPart,
+ cb.HighPart));
+
+ astgDebugOut((DEB_ITRACE, "Out CFileLockBytes::UnlockRegion\n"));
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFIleLockBytes::Stat, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileLockBytes::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ TAKE_CS;
+
+ SCODE sc;
+
+ astgDebugOut((DEB_ITRACE, "In CFIleLockBytes::Stat:%p()\n", this));
+
+ negChk(pstatstg->cbSize.LowPart =
+ GetFileSize(_h, &pstatstg->cbSize.HighPart));
+ boolChk(GetFileTime(_h, &pstatstg->ctime, &pstatstg->atime,
+ &pstatstg->mtime));
+ pstatstg->grfLocksSupported = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
+
+ pstatstg->type = STGTY_LOCKBYTES;
+ //BUGBUG: Set grfMode
+ //pstatstg->grfMode = DFlagsToMode(_pgfst->GetDFlags());
+ pstatstg->pwcsName = NULL;
+ if ((grfStatFlag & STATFLAG_NONAME) == 0)
+ {
+ pstatstg->pwcsName = (OLECHAR *)CoTaskMemAlloc(
+ (lstrlenW(_acName) + 1) * sizeof(OLECHAR));
+ if (pstatstg->pwcsName == NULL)
+ return STG_E_INSUFFICIENTMEMORY;
+ lstrcpyW(pstatstg->pwcsName, _acName);
+ }
+ sc = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "Out CFIleLockBytes::Stat\n"));
+ return NOERROR;
+
+Err:
+ return sc;
+}
diff --git a/private/ole32/stg/async/docfile/filllkb.cxx b/private/ole32/stg/async/docfile/filllkb.cxx
new file mode 100644
index 000000000..5881b3fc5
--- /dev/null
+++ b/private/ole32/stg/async/docfile/filllkb.cxx
@@ -0,0 +1,905 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: filllkb.cxx
+//
+// Contents: IFillLockBytes and ILockBytes wrapper for async docfiles
+//
+// Classes:
+//
+// Functions:
+//
+// History: 19-Dec-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "astghead.cxx"
+#pragma hdrstop
+
+#include "filllkb.hxx"
+#include <valid.h>
+#include "filebyte.hxx"
+
+
+#ifdef LKB_NOTIFY
+#define NOTIFY_SWEEPER \
+ SCODE sc2; \
+ if ((sc2 = _cpoint.Notify(E_PENDING, \
+ this, \
+ TRUE)) != S_OK) \
+ { \
+ return ResultFromScode(sc2); \
+ }
+#else
+#define NOTIFY_SWEEPER
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::CFillLockBytes, public
+//
+// Synopsis: Default constructor
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CFillLockBytes::CFillLockBytes(ILockBytes *pilb)
+{
+ _pilb = pilb;
+ _ulHighWater = 0;
+ _ulFailurePoint = 0;
+ _dwTerminate = UNTERMINATED;
+#ifdef ASYNC
+ _ppc = NULL;
+#else
+ _hNotifyEvent = INVALID_HANDLE_VALUE;
+#endif
+ InitializeCriticalSection(&_csThreadProtect);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::~CFillLockBytes, public
+//
+// Synopsis: Destructor
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CFillLockBytes::~CFillLockBytes()
+{
+ astgAssert(_pilb == NULL);
+#ifdef ASYNC
+#ifdef MULTIHEAP
+ if (_ppc)
+ {
+ CSafeMultiHeap smh(_ppc);
+ BOOL fLastRef = _ppc->LastRef();
+ _ppc->ReleaseSharedMem();
+ if (fLastRef)
+ g_smAllocator.Uninit();
+ }
+#endif
+#else
+ if (_hNotifyEvent != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(_hNotifyEvent);
+ }
+#endif
+ DeleteCriticalSection(&_csThreadProtect);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::Init, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 11-Jan-96 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE CFillLockBytes::Init(void)
+{
+ SCODE sc;
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::Init:%p()\n", this));
+#ifndef ASYNC
+ _hNotifyEvent = CreateEvent(NULL,
+ TRUE,
+ FALSE,
+ NULL);
+ if (_hNotifyEvent == NULL)
+ {
+ return Win32ErrorToScode(GetLastError());
+ }
+#endif
+
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::Init\n"));
+ return S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFillLockBytes::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 26-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+//BUGBUG: Delegate to wrapped ILockBytes? Probably not.
+STDMETHODIMP CFillLockBytes::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::QueryInterface(?, %p)\n",
+ ppvObj));
+
+ astgChk(ValidateOutPtrBuffer(ppvObj));
+ *ppvObj = NULL;
+
+ sc = S_OK;
+ if (IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (ILockBytes *)this;
+ CFillLockBytes::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_ILockBytes))
+ {
+ *ppvObj = (ILockBytes *)this;
+ CFillLockBytes::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IFillLockBytes))
+ {
+ *ppvObj = (IFillLockBytes *)this;
+ CFillLockBytes::AddRef();
+ }
+#ifdef ASYNC
+ else if (IsEqualIID(iid, IID_IFillInfo))
+ {
+ *ppvObj = (IFillInfo *)this;
+ CFillLockBytes::AddRef();
+ }
+#endif
+#ifdef LKB_NOTIFY
+ else if (IsEqualIID(iid, IID_IConnectionPointContainer))
+ {
+ *ppvObj = (IConnectionPointContainer *)this;
+ CFillLockBytes::AddRef();
+ }
+#endif
+ else if (IsEqualIID(iid, IID_IDefaultFillLockBytes))
+ {
+ *ppvObj = (IFillLockBytes *)this;
+ CFillLockBytes::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::QueryInterface => %p\n",
+ ppvObj));
+
+Err:
+ return ResultFromScode(sc);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CFillLockBytes::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+// History: 16-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CFillLockBytes::AddRef(void)
+{
+ return _pilb->AddRef();
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::Release, public
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CFillLockBytes::Release(void)
+{
+ LONG lRet;
+ if (_dwTerminate == TERMINATED_ABNORMAL)
+ {
+
+ ILockBytes *ptempilb;
+ IStorage *pstg;
+
+#ifndef ASYNC
+ if (SUCCEEDED(_pilb->QueryInterface(IID_IAsyncFileLockBytes,
+ (void **)&ptempilb)))
+ {
+ ptempilb->Release();
+ lRet = ((CFileLockBytes *)_pilb)->FileDeleteRelease();
+ }
+ else
+#endif
+ lRet = _pilb->Release();
+ }
+ else
+ lRet = _pilb->Release();
+
+ if (lRet == 0)
+ {
+ _pilb = NULL;
+ delete this;
+ }
+ return lRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::ReadAt, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::ReadAt(ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbRead)
+{
+ SCODE sc;
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::ReadAt:%p()\n", this));
+
+#ifdef LKB_NOTIFY
+ do
+ {
+#endif
+ if (_dwTerminate == TERMINATED_ABNORMAL)
+ {
+ sc = STG_E_INCOMPLETE;
+ }
+ else if ((_dwTerminate == TERMINATED_NORMAL) ||
+ (ULIGetLow(ulOffset) + cb <= _ulHighWater))
+ {
+ sc = _pilb->ReadAt(ulOffset, pv, cb, pcbRead);
+ }
+ else
+ {
+ *pcbRead = 0;
+ _ulFailurePoint = cb + ULIGetLow(ulOffset);
+ sc = E_PENDING;
+ NOTIFY_SWEEPER;
+ }
+#ifdef LKB_NOTIFY
+ } while (sc == E_PENDING);
+#endif
+
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::ReadAt\n"));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::WriteAt, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::WriteAt(ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ SCODE sc;
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::WriteAt:%p()\n", this));
+#ifdef LKB_NOTIFY
+ do
+ {
+#endif
+ if (_dwTerminate == TERMINATED_ABNORMAL)
+ {
+ sc = STG_E_INCOMPLETE;
+ }
+ else if ((_dwTerminate == TERMINATED_NORMAL) ||
+ (ULIGetLow(ulOffset) + cb <= _ulHighWater))
+ {
+ sc = _pilb->WriteAt(ulOffset, pv, cb, pcbWritten);
+ }
+ else
+ {
+ *pcbWritten = 0;
+ _ulFailurePoint = cb + ULIGetLow(ulOffset);
+ sc = E_PENDING;
+ NOTIFY_SWEEPER;
+ }
+#ifdef LKB_NOTIFY
+ } while (sc == E_PENDING);
+#endif
+
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::WriteAt\n"));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::Flush, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::Flush(void)
+{
+ SCODE sc;
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::Flush:%p()\n", this));
+ sc = _pilb->Flush();
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::Flush\n"));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::SetSize, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::SetSize(ULARGE_INTEGER cb)
+{
+ SCODE sc;
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::SetSize:%p()\n", this));
+#ifdef LKB_NOTIFY
+ do
+ {
+#endif
+ if (_dwTerminate == TERMINATED_ABNORMAL)
+ {
+ sc = STG_E_INCOMPLETE;
+ }
+ else if ((_dwTerminate == TERMINATED_NORMAL) ||
+ (ULIGetLow(cb) <= _ulHighWater))
+ {
+ sc = _pilb->SetSize(cb);
+ }
+ else
+ {
+ _ulFailurePoint = ULIGetLow(cb);
+ sc = E_PENDING;
+ NOTIFY_SWEEPER;
+ }
+#ifdef LKB_NOTIFY
+ } while (sc == E_PENDING);
+#endif
+
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::SetSize\n"));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::LockRegion, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ SCODE sc;
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::LockRegion:%p()\n", this));
+
+ sc = _pilb->LockRegion(libOffset, cb, dwLockType);
+
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::LockRegion\n"));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::UnlockRegion, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ SCODE sc;
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::UnlockRegion:%p()\n", this));
+ sc = _pilb->UnlockRegion(libOffset, cb, dwLockType);
+
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::UnlockRegion\n"));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::Stat, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::Stat:%p()\n", this));
+ if (_dwTerminate == TERMINATED_ABNORMAL)
+ {
+ sc = STG_E_INCOMPLETE;
+ }
+ else
+ {
+ sc = _pilb->Stat(pstatstg, grfStatFlag);
+ //BUGBUG: Do we need any post-processing here?
+ }
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::Stat\n"));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::FillAppend, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::FillAppend(void const *pv,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ SCODE sc;
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::FillAppend:%p()\n", this));
+ if (_dwTerminate != UNTERMINATED)
+ {
+ sc = STG_E_TERMINATED;
+ }
+ else
+ {
+ ULONG cbWritten;
+ ULARGE_INTEGER uli;
+ uli.QuadPart = _ulHighWater;
+ sc = _pilb->WriteAt(uli, pv, cb, &cbWritten);
+ _ulHighWater += cbWritten;
+ if (pcbWritten != NULL)
+ {
+ *pcbWritten = cbWritten;
+ }
+#ifdef ASYNC
+ if (_ppc)
+ {
+ HANDLE hEvent = _ppc->GetNotificationEvent();
+ if (!PulseEvent(hEvent))
+ {
+ sc = Win32ErrorToScode(GetLastError());
+ }
+ }
+#else
+ if (!PulseEvent(_hNotifyEvent))
+ {
+ sc = Win32ErrorToScode(GetLastError());
+ }
+#endif
+ }
+
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::FillAppend\n"));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::FillAt, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::FillAt(ULARGE_INTEGER ulOffset,
+ void const *pv,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ //BUGBUG: Implement
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::FillAt:%p()\n", this));
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::FillAt\n"));
+ return STG_E_UNIMPLEMENTEDFUNCTION;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::SetFillSize, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::SetFillSize(ULARGE_INTEGER ulSize)
+{
+ SCODE sc;
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::SetFillSize:%p()\n", this));
+ if (_dwTerminate == TERMINATED_ABNORMAL)
+ {
+ sc = STG_E_INCOMPLETE;
+ }
+ else
+ {
+ sc = _pilb->SetSize(ulSize);
+ }
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::SetFillSize\n"));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::Terminate, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::Terminate(BOOL bCanceled)
+{
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::Terminate:%p()\n", this));
+ _dwTerminate = (bCanceled) ? TERMINATED_ABNORMAL : TERMINATED_NORMAL;
+#ifdef ASYNC
+ if (_ppc)
+ {
+ HANDLE hEvent = _ppc->GetNotificationEvent();
+ if (!SetEvent(hEvent))
+ {
+ return Win32ErrorToScode(GetLastError());
+ }
+ }
+#else
+ if (!SetEvent(_hNotifyEvent))
+ {
+ return Win32ErrorToScode(GetLastError());
+ }
+#endif
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::Terminate\n"));
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::GetFailureInfo, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 11-Jan-96 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::GetFailureInfo(ULONG *pulWaterMark,
+ ULONG *pulFailurePoint)
+{
+ astgDebugOut((DEB_ITRACE,
+ "In CFillLockBytes::GetFailureInfo:%p()\n", this));
+ *pulWaterMark = _ulHighWater;
+ *pulFailurePoint = _ulFailurePoint;
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::GetFailureInfo\n"));
+ return S_OK;
+}
+
+#ifndef ASYNC
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::GetNotificationEvent, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 11-Jan-96 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+HANDLE CFillLockBytes::GetNotificationEvent(void)
+{
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::GetNotificationEvent:%p()\n", this));
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::GetNotificationEvent\n"));
+ return _hNotifyEvent;
+}
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::GetTerminationStatus, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 11-Jan-96 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::GetTerminationStatus(DWORD *pdwFlags)
+{
+ astgDebugOut((DEB_ITRACE,
+ "In CFillLockBytes::GetTerminationStatus:%p()\n", this));
+ *pdwFlags = _dwTerminate;
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::GetTerminationStatus\n"));
+ return S_OK;
+}
+
+
+
+SCODE CFillLockBytes::SetFailureInfo(ULONG ulWaterMark,
+ ULONG ulFailurePoint)
+{
+ astgDebugOut((DEB_ITRACE, "In CFillLockBytes::SetFailureInfo:%p()\n", this));
+ _ulHighWater =ulWaterMark;
+ _ulFailurePoint = ulFailurePoint ;
+ astgDebugOut((DEB_ITRACE, "Out CFillLockBytes::SetFailureInfo\n"));
+ return S_OK;
+}
+#if DBG==1
+void CFillLockBytes::PulseFillEvent()
+{
+#ifdef ASYNC
+ if (_ppc)
+ {
+ HANDLE hEvent = _ppc->GetNotificationEvent();
+ PulseEvent(hEvent);
+ }
+#else
+ PulseEvent(_hNotifyEvent);
+#endif
+}
+
+#endif
+
+
+#ifdef LKB_NOTIFY
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::EnumConnectionPoints, public
+//
+// Synopsis: Return enumerator on connection points
+//
+// Arguments: [ppEnum] -- Return pointer of enumerator
+//
+// Returns: Appropriate status code
+//
+// History: 28-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::EnumConnectionPoints(
+ IEnumConnectionPoints **ppEnum)
+{
+ astgDebugOut((DEB_ITRACE,
+ "In CFillLockBytes::EnumConnectionPoints:%p()\n",
+ this));
+ astgDebugOut((DEB_ITRACE,
+ "Out CFillLockBytes::EnumConnectionPoints\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFillLockBytes::FindConnectionPoint, public
+//
+// Synopsis: Return a connection point given an IID
+//
+// Arguments: [iid] -- IID to return connection point for
+// [ppCP] -- Return location for pointer
+//
+// Returns: Appropriate status code
+//
+// History: 28-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFillLockBytes::FindConnectionPoint(
+ REFIID iid,
+ IConnectionPoint **ppCP)
+{
+ astgDebugOut((DEB_ITRACE,
+ "In CFillLockBytes::FindConnectionPoint:%p()\n",
+ this));
+
+ CConnectionPoint *pcp;
+
+ if (IsEqualIID(iid, IID_IProgressNotify))
+ {
+ pcp = &_cpoint;
+ }
+ else
+ {
+ *ppCP = NULL;
+ return E_NOINTERFACE;
+ }
+
+ pcp->AddRef();
+ *ppCP = pcp;
+
+ astgDebugOut((DEB_ITRACE,
+ "Out CFillLockBytes::FindConnectionPoint\n"));
+ return S_OK;
+}
+#endif
+
+
diff --git a/private/ole32/stg/async/docfile/filllkb.hxx b/private/ole32/stg/async/docfile/filllkb.hxx
new file mode 100644
index 000000000..40fef8aea
--- /dev/null
+++ b/private/ole32/stg/async/docfile/filllkb.hxx
@@ -0,0 +1,162 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: filllkb.hxx
+//
+// Contents: CFillLockBytes class header
+//
+// Classes:
+//
+// Functions:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FILLLKB_HXX__
+#define __FILLLKB_HXX__
+
+
+#ifdef LKB_NOTIFY
+#include "stgwrap.hxx"
+#include "sinklist.hxx"
+#endif
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CFillLockBytes
+//
+// Purpose:
+//
+// Interface:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+class CFillLockBytes: public ILockBytes,
+ public IFillLockBytes
+#ifdef ASYNC
+ , public IFillInfo
+#endif
+#ifdef LKB_NOTIFY
+ , public IConnectionPointContainer
+#endif
+{
+public:
+ CFillLockBytes(ILockBytes *pilb);
+ ~CFillLockBytes();
+
+ SCODE Init(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+ // ILockBytes
+ STDMETHOD(ReadAt)(ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbRead);
+ STDMETHOD(WriteAt)(ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ STDMETHOD(Flush)(void);
+ STDMETHOD(SetSize)(ULARGE_INTEGER cb);
+ STDMETHOD(LockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+
+ //From IFillLockBytes
+ STDMETHOD(FillAppend)(void const *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ STDMETHOD(FillAt)(ULARGE_INTEGER ulOffset,
+ void const *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ STDMETHOD(SetFillSize)(ULARGE_INTEGER ulSize);
+ STDMETHOD(Terminate)(BOOL bCanceled);
+
+#ifdef LKB_NOTIFY
+ //From IConnectionPointContainer
+ STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum);
+ STDMETHOD(FindConnectionPoint)(REFIID iid, IConnectionPoint **ppCP);
+#endif
+
+ //From IFillInfo
+ STDMETHOD(GetFailureInfo)(ULONG *pulWaterMark, ULONG *pulFailurePoint);
+ STDMETHOD(GetTerminationStatus)(DWORD *pdwFlags);
+#ifndef ASYNC
+ HANDLE GetNotificationEvent(void);
+#endif
+
+#ifdef ASYNC
+ inline void SetContext(CPerContext *ppc);
+#endif
+
+ SCODE SetFailureInfo(ULONG ulWaterMark,ULONG ulFailurePoint);
+
+#if DBG==1
+ void PulseFillEvent(void);
+#endif
+
+ inline void TakeCriticalSection(void);
+ inline void ReleaseCriticalSection(void);
+
+private:
+ ILockBytes *_pilb;
+
+ ULONG _ulHighWater;
+ DWORD _dwTerminate;
+
+ ULONG _ulFailurePoint;
+
+#ifdef ASYNC
+ CPerContext *_ppc;
+#else
+ HANDLE _hNotifyEvent;
+#endif
+
+ CRITICAL_SECTION _csThreadProtect;
+
+#ifdef LKB_NOTIFY
+ CConnectionPoint _cpoint;
+#endif
+};
+
+inline void CFillLockBytes::TakeCriticalSection(void)
+{
+ EnterCriticalSection(&_csThreadProtect);
+}
+
+inline void CFillLockBytes::ReleaseCriticalSection(void)
+{
+ LeaveCriticalSection(&_csThreadProtect);
+}
+
+#ifdef ASYNC
+inline void CFillLockBytes::SetContext(CPerContext *ppc)
+{
+ _ppc = ppc;
+ _ppc->AddRefSharedMem();
+ if (_dwTerminate != UNTERMINATED)
+ {
+ SetEvent(_ppc->GetNotificationEvent());
+ }
+}
+#endif
+
+#endif // #ifndef __FILLLKB_HXX__
diff --git a/private/ole32/stg/async/docfile/iconn.idl b/private/ole32/stg/async/docfile/iconn.idl
new file mode 100644
index 000000000..556b12183
--- /dev/null
+++ b/private/ole32/stg/async/docfile/iconn.idl
@@ -0,0 +1,76 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: iconn.idl
+//
+// Contents: IDocfileAsyncConnectionPoint
+//
+// History: 03-Apr-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+
+[
+ object,
+ uuid(4a8df970-8d9a-11cf-8827-00aa00b569f5),
+ pointer_default(unique)
+]
+
+interface IDocfileAsyncConnectionPoint: IUnknown
+{
+#ifndef DO_NO_IMPORTS
+ import "objidl.idl";
+#endif
+
+ HRESULT AddConnection
+ (
+ [in] IProgressNotify *pSink,
+ [out] DWORD *pdwCookie
+ );
+
+ HRESULT RemoveConnection
+ (
+ [in] DWORD dwCookie
+ );
+
+ HRESULT NotifySinks
+ (
+ [in] ULONG ulProgressCurrent,
+ [in] ULONG ulProgressMaximum,
+ [in] BOOL fAccurate,
+ [in] SCODE sc
+ );
+
+ HRESULT GetParent
+ (
+ [out] IDocfileAsyncConnectionPoint ** ppParent
+ );
+}
+
+
+
+[
+ object,
+ uuid(de2eacd0-9c9d-11cf-882a-00aa00b569f5),
+ pointer_default(unique)
+]
+
+interface IFillInfo: IUnknown
+{
+#ifndef DO_NO_IMPORTS
+ import "unknwn.idl";
+#endif
+
+ HRESULT GetFailureInfo
+ (
+ [out] ULONG *pulWaterMark,
+ [out] ULONG *pulFailurePoint
+ );
+ HRESULT GetTerminationStatus
+ (
+ [out] DWORD *pdwFlags
+ );
+}
+
diff --git a/private/ole32/stg/async/docfile/sources.inc b/private/ole32/stg/async/docfile/sources.inc
new file mode 100644
index 000000000..9a091ed81
--- /dev/null
+++ b/private/ole32/stg/async/docfile/sources.inc
@@ -0,0 +1 @@
+SYNCHRONIZE_DRAIN=1
diff --git a/private/ole32/stg/async/docfile/stgconn.cxx b/private/ole32/stg/async/docfile/stgconn.cxx
new file mode 100644
index 000000000..8f6624c93
--- /dev/null
+++ b/private/ole32/stg/async/docfile/stgconn.cxx
@@ -0,0 +1,650 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: stgconn.cxx
+//
+// Contents: Connection points for Async Storage/Stream Wrappers
+//
+// Classes:
+//
+// Functions:
+//
+// History: 19-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+#include "astghead.cxx"
+#pragma hdrstop
+
+#include "stgwrap.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::CConnectionPoint, public
+//
+// Synopsis: Constructor
+//
+// Arguments:
+//
+// History: 28-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+CConnectionPoint::CConnectionPoint()
+{
+ astgDebugOut((DEB_ITRACE, "In CConnectionPoint::CConnectionPoint:%p()\n", this));
+ _cReferences = 1;
+ _dwCookie = 0;
+ _pSinkHead = NULL;
+ _pParentCP = NULL;
+
+ InitializeCriticalSection(&_csSinkList);
+ astgDebugOut((DEB_ITRACE, "Out CConnectionPoint::CConnectionPoint\n"));
+}
+
+
+CConnectionPoint::~CConnectionPoint()
+{
+ astgDebugOut((DEB_ITRACE, "In CConnectionPoint::~CConnectionPoint:%p()\n", this));
+ TakeCS();
+ if (_pParentCP)
+ _pParentCP->Release();
+
+ // clean up the advise list
+ CSinkList *psltemp = _pSinkHead;
+ CSinkList *pslprev = NULL;
+
+ while (psltemp)
+ {
+ pslprev = psltemp;
+ psltemp = psltemp->GetNext();
+ pslprev->GetProgressNotify()->Release();
+ delete pslprev;
+ }
+ ReleaseCS();
+ DeleteCriticalSection(&_csSinkList);
+
+ astgDebugOut((DEB_ITRACE, "Out CConnectionPoint::~CConnectionPoint\n"));
+}
+
+#ifndef ASYNC
+void CConnectionPoint::Init(IConnectionPointContainer *pCPC)
+{
+ _pCPC = pCPC;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::Notify, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 14-Jan-96 SusiA Created
+// 27-Feb-96 SusiA Moved from Async wrappers
+//
+//----------------------------------------------------------------------------
+SCODE CConnectionPoint::Notify(SCODE scFailure,
+ IFillLockBytes *piflb,
+ BOOL fDefaultLockBytes)
+{
+ SCODE sc = S_OK;
+ BOOL fAccurate = (scFailure == E_PENDING);
+ ULONG ulWaterMark;
+ ULONG ulFailurePoint;
+
+ HANDLE hNotifyEvent;
+
+ if (fDefaultLockBytes)
+ {
+ CFillLockBytes *pflb = (CFillLockBytes *)piflb;
+
+ pflb->GetFailureInfo(&ulWaterMark,
+ &ulFailurePoint);
+
+ pflb->ReleaseCriticalSection();
+
+ while (((sc = NotifySinks(ulWaterMark,
+ ulFailurePoint,
+ fAccurate,
+ STG_S_MONITORING)) == STG_S_BLOCK) ||
+ (sc == STG_S_MONITORING) ||
+ // S_OK is a synonym for STG_S_MONITORING
+ (sc == S_OK))
+ {
+ DWORD dwFlags;
+
+ // wait for an event to signal
+ hNotifyEvent = pflb->GetNotificationEvent();
+ WaitForSingleObject(hNotifyEvent, INFINITE);
+
+ pflb->GetTerminationStatus(&dwFlags);
+ // client terminated call?
+ if (dwFlags == TERMINATED_ABNORMAL)
+ return STG_E_INCOMPLETE;
+
+ // download is complete
+ else if (dwFlags == TERMINATED_NORMAL)
+ return S_OK;
+
+ else
+ {
+ //Note: Don't overwrite the failure point we recorded
+ // before, since it may have been changed by some
+ // other thread.
+
+ //Don't need to take the critical section here, since
+ //we don't care about the current failure point.
+ ULONG ulFailurePointCurrent;
+ pflb->GetFailureInfo(&ulWaterMark,
+ &ulFailurePointCurrent);
+
+ // all the data is available now
+ if (ulWaterMark >= ulFailurePoint)
+ {
+ // we won't care what the return value is, so send STG_S_BLOCK,
+ // and all sinks are will have fOwner == FALSE
+ NotifySinks(ulWaterMark, ulFailurePoint, fAccurate, STG_S_BLOCK);
+ break;
+ }
+ }
+
+ }
+ }
+
+ if ((sc == STG_S_RETRYNOW) || (sc == STG_S_BLOCK) || (sc == STG_S_MONITORING))
+ return S_OK;
+ else return sc;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::NotifySinks, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 23-Feb-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CConnectionPoint::NotifySinks(ULONG ulProgressCurrent,
+ ULONG ulProgressMaximum,
+ BOOL fAccurate,
+ SCODE sc)
+{
+
+ CSinkList *pslTemp;
+ TakeCS();
+
+
+ // closest node with a connection point that wants to determine
+ // behavior does
+ // priority first to last on this Connection Point, then the
+ // parent connection point.
+
+ pslTemp = GetHead();
+
+ while (((sc == S_OK) ||(sc == STG_S_MONITORING))
+ &&(pslTemp!=NULL))
+ {
+ sc = pslTemp->GetProgressNotify()
+ ->OnProgress(ulProgressCurrent, ulProgressMaximum, fAccurate, TRUE);
+ pslTemp = pslTemp->GetNext();
+ }
+
+ // notify the rest of the connections
+ while (pslTemp !=NULL)
+ {
+ pslTemp->GetProgressNotify()
+ ->OnProgress(ulProgressCurrent, ulProgressMaximum, fAccurate, FALSE);
+ pslTemp = pslTemp->GetNext();
+ }
+
+ //call parent storage advise list next
+ if (_pParentCP)
+ sc = _pParentCP->NotifySinks(ulProgressCurrent,
+ ulProgressMaximum,
+ fAccurate,
+ sc);
+
+ ReleaseCS();
+ return sc;
+
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::QueryInterface, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 01-Jan-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CConnectionPoint::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc = S_OK;
+ astgDebugOut((DEB_TRACE,
+ "In CConnectionPoint::QueryInterface:%p()\n",
+ this));
+
+ *ppvObj = NULL;
+
+ if ((IsEqualIID(iid, IID_IUnknown)) ||
+ (IsEqualIID(iid, IID_IDocfileAsyncConnectionPoint)))
+ {
+ *ppvObj = (IDocfileAsyncConnectionPoint *)this;
+ CConnectionPoint::AddRef();
+ }
+ else
+ {
+ return E_NOINTERFACE;
+ }
+
+ astgDebugOut((DEB_TRACE, "Out CConnectionPoint::QueryInterface\n"));
+ return ResultFromScode(sc);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::AddRef, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 29-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CConnectionPoint::AddRef(void)
+{
+ ULONG ulRet;
+ astgDebugOut((DEB_TRACE,
+ "In CConnectionPoint::AddRef:%p()\n",
+ this));
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+
+ astgDebugOut((DEB_TRACE, "Out CConnectionPoint::AddRef\n"));
+ return ulRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::Release, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 30-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CConnectionPoint::Release(void)
+{
+ LONG lRet;
+ astgDebugOut((DEB_TRACE,
+ "In CConnectionPoint::Release:%p()\n",
+ this));
+
+ astgAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ {
+ astgAssert((lRet > 0) && "Connection point released too many times.");
+ lRet = 0;
+
+ }
+ astgDebugOut((DEB_TRACE, "Out CConnectionPoint::Release\n"));
+ return (ULONG)lRet;
+}
+
+#ifndef ASYNC
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::GetConnectionInterface, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 30-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CConnectionPoint::GetConnectionInterface(IID *pIID)
+{
+ astgDebugOut((DEB_ITRACE,
+ "In CConnectionPoint::GetConnectionInterface:%p()\n",
+ this));
+
+
+ *pIID = IID_IProgressNotify;
+
+ astgDebugOut((DEB_ITRACE, "Out CConnectionPoint::GetConnectionInterface\n"));
+ return S_OK;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::GetConnectionPointContainer, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 30-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CConnectionPoint::GetConnectionPointContainer(
+ IConnectionPointContainer ** ppCPC)
+{
+ astgDebugOut((DEB_ITRACE,
+ "In CConnectionPoint::GetConnectionPointContainer:%p()\n",
+ this));
+
+ *ppCPC = _pCPC;
+ _pCPC->AddRef();
+
+ astgDebugOut((DEB_ITRACE,
+ "Out CConnectionPoint::GetConnectionPointContainer\n"));
+ return S_OK;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::Clone, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 26-Feb-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE CConnectionPoint::Clone( CConnectionPoint *pcp)
+{
+ SCODE sc = S_OK;
+ void *pv = NULL;
+
+ astgDebugOut((DEB_ITRACE,"In CConnectionPoint::Clone:%p()\n", this));
+
+ TakeCS();
+ pcp->TakeCS();
+
+ CSinkList *pslNew = NULL;
+ CSinkList *pslPrev = NULL;
+ CSinkList *pslOld = pcp->GetHead();
+
+
+
+ while (pslOld != NULL)
+ {
+ astgMem(pslNew = new CSinkList);
+
+ pslNew->SetNext(NULL);
+
+ if (pslPrev)
+ pslPrev->SetNext(pslNew);
+ else
+ _pSinkHead = pslNew;
+
+ pslPrev = pslNew;
+
+ pslNew->SetCookie(pslOld->GetCookie());
+
+ //Note: The QueryInterface will give us a reference to hold on to.
+ astgChk(pslOld->GetProgressNotify()->QueryInterface(IID_IProgressNotify, &pv));
+ pslNew->SetProgressNotify((IProgressNotify *)pv);
+
+ pslOld= pslOld->GetNext();
+ }
+
+ _dwCookie = pcp->GetCookie();
+
+ astgDebugOut((DEB_ITRACE,"Out CConnectionPoint::Clone\n"));
+
+Err:
+ while (_pSinkHead != NULL)
+ {
+ CSinkList *pSinkNext = _pSinkHead;
+ delete _pSinkHead;
+ _pSinkHead = pSinkNext;
+ }
+
+ pcp->ReleaseCS();
+ ReleaseCS();
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint:: Advise, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 29-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+#ifdef ASYNC
+STDMETHODIMP CConnectionPoint::AddConnection(IProgressNotify *pSink,
+ DWORD *pdwCookie)
+#else
+STDMETHODIMP CConnectionPoint::Advise(IUnknown *pUnkSink,
+ DWORD *pdwCookie)
+#endif
+{
+ SCODE sc = S_OK;
+ CSinkList *pslNew = NULL;
+ CSinkList *pslTemp = _pSinkHead;
+
+ astgDebugOut((DEB_ITRACE, "In CConnectionPoint::Advise:%p()\n", this));
+ TakeCS();
+
+ IProgressNotify *ppn;
+
+ astgMem(pslNew = new CSinkList);
+ *pdwCookie = ++_dwCookie;
+ pslNew->SetCookie(*pdwCookie);
+
+#ifdef ASYNC
+ pSink->AddRef();
+ pslNew->SetProgressNotify(pSink);
+#else
+ void *pv;
+ //Note: The QueryInterface will give us a reference to hold on to.
+ astgChk(pUnkSink->QueryInterface(IID_IProgressNotify, &pv));
+ pslNew->SetProgressNotify((IProgressNotify *)pv);
+#endif
+
+ //Add new node to end of list
+ if (pslTemp == NULL)
+ _pSinkHead = pslNew;
+ else
+ {
+ while(pslTemp->GetNext() != NULL)
+ pslTemp = pslTemp->GetNext();
+ pslTemp->SetNext(pslNew);
+ }
+ ReleaseCS();
+
+ astgDebugOut((DEB_ITRACE, "Out CConnectionPoint::Advise\n"));
+ return sc;
+Err:
+ ReleaseCS();
+ delete pslNew;
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::Unadvise, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 30-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef ASYNC
+STDMETHODIMP CConnectionPoint::RemoveConnection(DWORD dwCookie)
+#else
+STDMETHODIMP CConnectionPoint::Unadvise(DWORD dwCookie)
+#endif
+{
+ CSinkList *pslTemp;
+ CSinkList *pslPrev;
+ astgDebugOut((DEB_ITRACE, "In CConnectionPoint::Unadvise:%p()\n", this));
+
+ TakeCS();
+
+ pslTemp = _pSinkHead;
+ pslPrev = NULL;
+
+ while ((pslTemp != NULL) && (pslTemp->GetCookie() != dwCookie))
+ {
+ pslPrev = pslTemp;
+ pslTemp = pslTemp->GetNext();
+ }
+
+ if (pslTemp != NULL)
+ {
+ //Found the sink. Delete it from the list.
+ if (pslPrev != NULL)
+ {
+ pslPrev->SetNext(pslTemp->GetNext());
+ }
+ else
+ {
+ _pSinkHead = pslTemp->GetNext();
+ }
+ pslTemp->GetProgressNotify()->Release();
+
+ delete pslTemp;
+ }
+ else
+ { //Client passed in unknown cookie.
+ ReleaseCS();
+ return E_UNEXPECTED;
+ }
+ ReleaseCS();
+
+ astgDebugOut((DEB_ITRACE, "Out CConnectionPoint::Unadvise\n"));
+ return S_OK;
+}
+
+#ifndef ASYNC
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::EnumConnections, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 30-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CConnectionPoint::EnumConnections(
+ IEnumConnections **ppEnum)
+{
+ astgDebugOut((DEB_ITRACE, "In CConnectionPoint::EnumConnections:%p()\n", this));
+ astgDebugOut((DEB_ITRACE, "Out CConnectionPoint::EnumConnections\n"));
+ return E_NOTIMPL;
+}
+#endif
+
+#ifdef ASYNC
+STDMETHODIMP CConnectionPoint::GetParent(IDocfileAsyncConnectionPoint **ppdacp)
+{
+ *ppdacp = _pParentCP;
+ return S_OK;
+}
+#endif
diff --git a/private/ole32/stg/async/docfile/stgwrap.cxx b/private/ole32/stg/async/docfile/stgwrap.cxx
new file mode 100644
index 000000000..7122180c0
--- /dev/null
+++ b/private/ole32/stg/async/docfile/stgwrap.cxx
@@ -0,0 +1,1873 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: stgwrap.cxx
+//
+// Contents: IStorage/IStream wrappers for async docfile
+//
+// Classes:
+//
+// Functions:
+//
+// History: 19-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+#include "astghead.cxx"
+#pragma hdrstop
+
+#include "stgwrap.hxx"
+#include "asyncerr.hxx"
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::QueryInterface, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc = S_OK;
+ *ppvObj = NULL;
+
+ astgDebugOut((DEB_ITRACE,
+ "In CAsyncStorage::QueryInterface:%p()\n", this));
+
+ if (IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IStorage *)this;
+ }
+ else if (IsEqualIID(iid, IID_IStorage))
+ {
+ *ppvObj = (IStorage *)this;
+ }
+ else if (IsEqualIID(iid, IID_IConnectionPointContainer))
+ {
+ *ppvObj = (IConnectionPointContainer *)this;
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ AddRef();
+ }
+ astgDebugOut((DEB_ITRACE,
+ "Out CAsyncStorage::QueryInterface:%p()\n", this));
+ return sc;
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::AddRef, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CAsyncStorage::AddRef(void)
+{
+ ULONG ulRet;
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::AddRef:%p()\n", this));
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+ _pRealStg->AddRef();
+
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::AddRef\n"));
+ return ulRet;
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::Release, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CAsyncStorage::Release(void)
+{
+ LONG lRet;
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::Release:%p()\n", this));
+
+
+ lRet = InterlockedDecrement(&_cReferences);
+ _pRealStg->Release();
+
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ lRet = 0;
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::Release\n"));
+ return (ULONG)lRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::CreateStream, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::CreateStream(OLECHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ CAsyncStream *pwstm;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::CreateStream:%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStg->CreateStream(pwcsName,
+ grfMode,
+ reserved1,
+ reserved2,
+ ppstm));
+
+ if (SUCCEEDED(sc))
+ {
+ CAsyncStream *pwstm = new CAsyncStream(*ppstm,
+ _pflb,
+ _fDefaultLockBytes);
+ if (pwstm == NULL)
+ {
+ (*ppstm)->Release();
+ *ppstm = NULL;
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ *ppstm = (IStream *)pwstm;
+ if (_asyncFlags == ASYNC_MODE_COMPATIBILITY)
+ {
+ pwstm->GetCP()->SetParent(&_cpoint);
+ pwstm->SetAsyncFlags(_asyncFlags);
+ }
+ }
+ else *ppstm = NULL;
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::CreateStream:%p()\n", this));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::OpenStream, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::OpenStream(OLECHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ CAsyncStream *pwstm;
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::OpenStream:%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStg->OpenStream(pwcsName,
+ reserved1,
+ grfMode,
+ reserved2,
+ ppstm));
+
+ if (SUCCEEDED(sc))
+ {
+ CAsyncStream *pwstm = new CAsyncStream(*ppstm,
+ _pflb,
+ _fDefaultLockBytes);
+ if (pwstm == NULL)
+ {
+ (*ppstm)->Release();
+ *ppstm = NULL;
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ *ppstm = (IStream *)pwstm;
+ if (_asyncFlags == ASYNC_MODE_COMPATIBILITY)
+ {
+ pwstm->GetCP()->SetParent(&_cpoint);
+ pwstm->SetAsyncFlags(_asyncFlags);
+ }
+
+ }
+ else *ppstm = NULL;
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::OpenStream:%p()\n", this));
+ return ResultFromScode(sc);
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::CreateStorage, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::CreateStorage(OLECHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ LPSTGSECURITY reserved2,
+ IStorage **ppstg)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE,
+ "In CAsyncStorage::CreateStorage:%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStg->CreateStorage(pwcsName,
+ grfMode,
+ reserved1,
+ reserved2,
+ ppstg));
+
+ if (SUCCEEDED(sc))
+ {
+ CAsyncStorage *pwstg = new CAsyncStorage(*ppstg,
+ _pflb,
+ _fDefaultLockBytes);
+ if (pwstg == NULL)
+ {
+ (*ppstg)->Release();
+ *ppstg = NULL;
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ *ppstg = (IStorage *) pwstg;
+ if (_asyncFlags == ASYNC_MODE_COMPATIBILITY)
+ {
+ pwstg->GetCP()->SetParent(&_cpoint);
+ pwstg->SetAsyncFlags(_asyncFlags);
+ }
+
+ }
+ else *ppstg = NULL;
+
+ astgDebugOut((DEB_ITRACE,
+ "Out CAsyncStorage::CreateStorage:%p()\n", this));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::OpenStorage, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::OpenStorage(OLECHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::OpenStorage:%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStg->OpenStorage(pwcsName,
+ pstgPriority,
+ grfMode,
+ snbExclude,
+ reserved,
+ ppstg));
+
+ if (SUCCEEDED(sc))
+ {
+ CAsyncStorage *pwstg = new CAsyncStorage(*ppstg,
+ _pflb,
+ _fDefaultLockBytes);
+ if (pwstg == NULL)
+ {
+ (*ppstg)->Release();
+ *ppstg = NULL;
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ *ppstg = (IStorage *) pwstg;
+ if (_asyncFlags == ASYNC_MODE_COMPATIBILITY)
+ {
+ pwstg->GetCP()->SetParent(&_cpoint);
+ pwstg->SetAsyncFlags(_asyncFlags);
+ }
+ }
+ else *ppstg = NULL;
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::OpenStorage:%p()\n", this));
+ return ResultFromScode(sc);
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::CopyTo, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::CopyTo(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::CopyTo%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStg->CopyTo(ciidExclude,
+ rgiidExclude,
+ snbExclude,
+ pstgDest));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::CopyTo\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::MoveElementTo, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::MoveElementTo(OLECHAR const *lpszName,
+ IStorage *pstgDest,
+ OLECHAR const *lpszNewName,
+ DWORD grfFlags)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::MoveElementTo%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStg->MoveElementTo(lpszName,
+ pstgDest,
+ lpszNewName,
+ grfFlags));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::MoveElementTo\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::Commit, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::Commit(DWORD grfCommitFlags)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::Commit%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStg->Commit(grfCommitFlags));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::Commit\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::Revert, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::Revert(void)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::Revert%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStg->Revert());
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::Revert\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::EnumElements, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::EnumElements(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::EnumElements%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStg->EnumElements(reserved1,
+ reserved2,
+ reserved3,
+ ppenm));
+ if (SUCCEEDED(sc))
+ {
+ CAsyncEnum *pwenum = new CAsyncEnum(*ppenm, _pflb, _fDefaultLockBytes);
+ if (pwenum == NULL)
+ {
+ (*ppenm)->Release();
+ *ppenm = NULL;
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ *ppenm = (IEnumSTATSTG *)pwenum;
+ if (_asyncFlags == ASYNC_MODE_COMPATIBILITY)
+ {
+ pwenum->GetCP()->SetParent(&_cpoint);
+ pwenum->SetAsyncFlags(_asyncFlags);
+ }
+
+ }
+ else *ppenm = NULL;
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::EnumElements\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::DestroyElement, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::DestroyElement(OLECHAR const *pwcsName)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+ ULONG ulWaterMark;
+ ULONG ulFailurePoint;
+
+ HANDLE hNotifyEvent;
+ CSinkList *pslTemp;
+
+ astgDebugOut((DEB_ITRACE,
+ "In CAsyncStorage::DestroyElement%p()\n", this));
+
+#ifdef SWEEPER
+ pslTemp =_cpoint.GetHead();
+
+ //NOTE: No DO_PENDING_LOOP because of workaround
+ while (1)
+ {
+ if (_fDefaultLockBytes)
+ {
+ DWORD dwFlags;
+
+ ((CFillLockBytes *)_pflb)->GetTerminationStatus(&dwFlags);
+ // client terminated call?
+ if (dwFlags == TERMINATED_ABNORMAL)
+ return STG_E_INCOMPLETE;
+
+ // download is complete
+ else if (dwFlags == TERMINATED_NORMAL)
+ {
+ ((CFillLockBytes *)_pflb)->SetFailureInfo(ulWaterMark,
+ ulWaterMark);
+ break;
+ }
+ // wait for an event to signal
+ hNotifyEvent = ((CFillLockBytes *)_pflb)->GetNotificationEvent();
+ WaitForSingleObject(hNotifyEvent, INFINITE);
+
+ if (pslTemp != NULL)
+ {
+ ((CFillLockBytes *)_pflb)->GetFailureInfo(&ulWaterMark,
+ &ulFailurePoint);
+ pslTemp->GetProgressNotify()->OnProgress(ulWaterMark,
+ (ULONG) -1,
+ FALSE,
+ FALSE);
+ }
+ }
+ }
+
+ sc = _pRealStg->DestroyElement(pwcsName);
+#else
+ DO_PENDING_LOOP(_pRealStg->DestroyElement(pwcsName));
+#endif
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::DestroyElement\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::RenameElement, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::RenameElement(OLECHAR const *pwcsOldName,
+ OLECHAR const *pwcsNewName)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::RenameElement%p()\n", this));
+ DO_PENDING_LOOP(_pRealStg->RenameElement(pwcsOldName, pwcsNewName));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::RenameElement\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::SetElementTimes, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::SetElementTimes(const OLECHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE,
+ "In CAsyncStorage::SetElementTimes%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStg->SetElementTimes(lpszName,
+ pctime,
+ patime,
+ pmtime));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::SetElementTimes\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::SetClass, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::SetClass(REFCLSID clsid)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::SetClass%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStg->SetClass(clsid));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::SetClass\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::SetStateBits, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::SetStateBits%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStg->SetStateBits(grfStateBits, grfMask));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::SetStateBits\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::Stat, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::Stat%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStg->Stat(pstatstg, grfStatFlag));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::Stat\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::EnumConnectionPoints, public
+//
+// Synopsis: Return enumerator on connection points
+//
+// Arguments: [ppEnum] -- Return pointer of enumerator
+//
+// Returns: Appropriate status code
+//
+// History: 28-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::EnumConnectionPoints(
+ IEnumConnectionPoints **ppEnum)
+{
+ astgDebugOut((DEB_ITRACE,
+ "In CAsyncStorage::EnumConnectionPoints:%p()\n",
+ this));
+ astgDebugOut((DEB_ITRACE,
+ "Out CAsyncStorage::EnumConnectionPoints\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStorage::FindConnectionPoint, public
+//
+// Synopsis: Return a connection point given an IID
+//
+// Arguments: [iid] -- IID to return connection point for
+// [ppCP] -- Return location for pointer
+//
+// Returns: Appropriate status code
+//
+// History: 28-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStorage::FindConnectionPoint(
+ REFIID iid,
+ IConnectionPoint **ppCP)
+{
+ astgDebugOut((DEB_ITRACE,
+ "In CAsyncStorage::FindConnectionPoint:%p()\n",
+ this));
+
+ CConnectionPoint *pcp;
+
+ if (IsEqualIID(iid, IID_IProgressNotify))
+ {
+ pcp = &_cpoint;
+ }
+ else
+ {
+ *ppCP = NULL;
+ return E_NOINTERFACE;
+ }
+
+ pcp->AddRef();
+ *ppCP = pcp;
+
+ astgDebugOut((DEB_ITRACE,
+ "Out CAsyncStorage::FindConnectionPoint\n"));
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncRootStorage::QueryInterface, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncRootStorage::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc = S_OK;
+ *ppvObj = NULL;
+
+ astgDebugOut((DEB_ITRACE,
+ "In CAsyncRootStorage::QueryInterface:%p()\n",
+ this));
+ if (IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IStorage *)this;
+ }
+ else if (IsEqualIID(iid, IID_IStorage))
+ {
+ *ppvObj = (IStorage *)this;
+ }
+ else if (IsEqualIID(iid, IID_IRootStorage))
+ {
+ IRootStorage *prstg;
+ if (!SUCCEEDED(_pRealStg->QueryInterface(IID_IRootStorage,
+ (void **) &prstg)))
+ return E_NOINTERFACE;
+ prstg->Release();
+
+ *ppvObj = (IRootStorage *)this;
+ }
+ else if (IsEqualIID(iid, IID_IConnectionPointContainer))
+ {
+ *ppvObj = (IConnectionPointContainer *)this;
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ AddRef();
+ }
+ astgDebugOut((DEB_ITRACE,
+ "Out CAsyncRootStorage::QueryInterface:%p()\n",
+ this));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncRootStorage::AddRef, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CAsyncRootStorage::AddRef(void)
+{
+ ULONG ulRet;
+ astgDebugOut((DEB_ITRACE, "In CAsyncRootStorage::AddRef:%p()\n", this));
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+ _pRealStg->AddRef();
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncRootStorage::AddRef\n"));
+ return ulRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncRootStorage::Release, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CAsyncRootStorage::Release(void)
+{
+ LONG lRet;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncRootStorage::Release:%p()\n", this));
+ lRet = InterlockedDecrement(&_cReferences);
+ _pRealStg->Release();
+
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ lRet = 0;
+ astgDebugOut((DEB_ITRACE, "Out CAsyncRootStorage::Release\n"));
+ return (ULONG)lRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncRootStorage::SwitchToFile, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncRootStorage::SwitchToFile(OLECHAR *ptcsFile)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+ IRootStorage *prstg;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStorage::%p()\n", this));
+
+ astgVerify(SUCCEEDED(_pRealStg->QueryInterface(IID_IRootStorage,
+ (void **) &prstg)));
+
+ DO_PENDING_LOOP(prstg->SwitchToFile(ptcsFile));
+
+ prstg->Release();
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStorage::\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::QueryInterface, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStream::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc = S_OK;
+ *ppvObj = NULL;
+
+ astgDebugOut((DEB_ITRACE,
+ "In CAsyncStream::QueryInterface:%p()\n", this));
+ if (IsEqualIID(iid, IID_IUnknown))
+
+ {
+ *ppvObj = (IStream *)this;
+ }
+ else if (IsEqualIID(iid, IID_IStream))
+ {
+ *ppvObj = (IStream *)this;
+ }
+ else if (IsEqualIID(iid, IID_IConnectionPointContainer))
+ {
+ *ppvObj = (IConnectionPointContainer *)this;
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ AddRef();
+ }
+ astgDebugOut((DEB_ITRACE,
+ "Out CAsyncStream::QueryInterface:%p()\n", this));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::AddRef, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CAsyncStream::AddRef(void)
+{
+ ULONG ulRet;
+ astgDebugOut((DEB_ITRACE, "In CAsyncStream::AddRef:%p()\n", this));
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+ _pRealStm->AddRef();
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStream::AddRef\n"));
+ return ulRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::Release, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CAsyncStream::Release(void)
+{
+ LONG lRet;
+ astgDebugOut((DEB_ITRACE, "In CAsyncStream::Release:%p()\n", this));
+
+ lRet = InterlockedDecrement(&_cReferences);
+ _pRealStm->Release();
+
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ lRet = 0;
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStream::Release\n"));
+ return (ULONG)lRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::Read, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStream::Read(VOID HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbRead)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStream::Read:%p()\n", this));
+
+#ifdef SWEEPER
+ ULONG cbRead = 0;
+
+ DO_PENDING_LOOP_WITH_SEEK(_pRealStm->Read(pv, cb, &cbRead), pcbRead);
+
+ if (SUCCEEDED(sc))
+ {
+ _ulSeek = _ulSeek + cbRead;
+ }
+ else
+ {
+ cbRead = 0;
+ }
+
+ if (pcbRead)
+ *pcbRead = cbRead;
+#else
+ ULONG cbRead = 0;
+ do
+ {
+ TAKE_CRITICAL_SECTION;
+ sc = _pRealStm->Read(pv, cb, &cbRead);
+ astgAssert(cbRead <= cb);
+ if (cbRead != 0)
+ {
+ pv = (BYTE *)pv + cbRead;
+ cb -= cbRead;
+ }
+ if (!ISPENDINGERROR(sc))
+ {
+ RELEASE_CRITICAL_SECTION;
+ break;
+ }
+ else if ((sc2 = _cpoint.Notify(sc,
+ _pflb,
+ _fDefaultLockBytes)) != S_OK)
+ {
+ if (pcbRead)
+ *pcbRead = cbRead;
+ return ResultFromScode(sc2);
+ }
+ } while (TRUE);
+ if (pcbRead)
+ *pcbRead = cbRead;
+#endif
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStream::Read\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::Write, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStream::Write(VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStream::Write:%p()\n", this));
+
+#ifdef SWEEPER
+ ULONG cbWritten = 0;
+
+ DO_PENDING_LOOP_WITH_SEEK(_pRealStm->Write(pv, cb, &cbWritten),
+ pcbWritten);
+ if (SUCCEEDED(sc))
+ {
+ _ulSeek += cbWritten;
+ }
+ else
+ {
+ cbWritten = 0;
+ }
+ if (pcbWritten)
+ *pcbWritten = cbWritten;
+#else
+ ULONG cbWritten = 0;
+ do
+ {
+ TAKE_CRITICAL_SECTION;
+ sc = _pRealStm->Write(pv, cb, &cbWritten);
+ astgAssert(cbWritten <= cb);
+ if (cbWritten != 0)
+ {
+ pv = (BYTE *)pv + cbWritten;
+ cb -= cbWritten;
+ }
+ if (!ISPENDINGERROR(sc))
+ {
+ RELEASE_CRITICAL_SECTION;
+ break;
+ }
+ else if ((sc2 = _cpoint.Notify(sc,
+ _pflb,
+ _fDefaultLockBytes)) != S_OK)
+ {
+ if (pcbWritten)
+ *pcbWritten = cbWritten;
+ return ResultFromScode(sc2);
+ }
+ } while (TRUE);
+ if (pcbWritten)
+ *pcbWritten = cbWritten;
+#endif
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStream::Write\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::Seek, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStream::Seek(LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStream::Seek:%p()\n", this));
+
+#ifdef SWEEPER
+ ULARGE_INTEGER liNew;
+
+ DO_PENDING_LOOP_WITH_SEEK_AND_LI(_pRealStm->Seek(dlibMove,
+ dwOrigin,
+ &liNew),
+ plibNewPosition);
+ if (SUCCEEDED(sc))
+ {
+ _ulSeek = liNew.LowPart;
+ }
+ else
+ {
+ liNew.QuadPart = 0;
+ }
+
+ if (plibNewPosition)
+ *plibNewPosition = liNew;
+#else
+ DO_PENDING_LOOP(_pRealStm->Seek(dlibMove, dwOrigin, plibNewPosition));
+#endif
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStream::Seek\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::CopyTo, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStream::CopyTo(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStream::CopyTo:%p()\n", this));
+
+#ifdef SWEEPER
+ ULARGE_INTEGER cbRead;
+
+ DO_PENDING_LOOP_WITH_SEEK_AND_LI(_pRealStm->CopyTo(pstm,
+ cb,
+ &cbRead,
+ pcbWritten),
+ pcbRead);
+ if (SUCCEEDED(sc))
+ {
+ _ulSeek = _ulSeek + cbRead.LowPart;
+ }
+ else
+ {
+ cbRead.QuadPart = 0;
+ }
+
+ if (pcbRead)
+ *pcbRead = cbRead;
+#else
+ DO_PENDING_LOOP(_pRealStm->CopyTo(pstm, cb, pcbRead, pcbWritten));
+#endif
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStream::CopyTo\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::SetSize, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStream::SetSize(ULARGE_INTEGER cb)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStream::SetSize%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStm->SetSize(cb));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStream::SetSize\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::Commit, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CAsyncStream::Commit(DWORD grfCommitFlags)
+{
+
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStream::Commit%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStm->Commit(grfCommitFlags));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStream::Commit\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::Revert, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStream::Revert(void)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStream::Revert%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStm->Revert());
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStream::Revert\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::LockRegion, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStream::LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStream::LockRegion%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStm->LockRegion(libOffset, cb, dwLockType));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStream::LockRegion\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::UnlockRegion, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStream::UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStream::UnlockRegion%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStm->UnlockRegion(libOffset, cb, dwLockType));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStream::UnlockRegion\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::Stat, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStream::Stat%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStm->Stat(pstatstg, grfStatFlag));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStream::Stat\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::Clone, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStream::Clone(IStream **ppstm)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncStream::Clone:%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealStm->Clone(ppstm));
+
+ if (SUCCEEDED(sc))
+ {
+ CAsyncStream *pwstm = new CAsyncStream(*ppstm,
+ _pflb,
+ _fDefaultLockBytes);
+ if (pwstm == NULL)
+ {
+ (*ppstm)->Release();
+ *ppstm = NULL;
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+#ifdef SWEEPER
+ pwstm->_ulSeek = _ulSeek;
+#endif
+ *ppstm = (IStream *) pwstm;
+ if (_asyncFlags == ASYNC_MODE_COMPATIBILITY)
+ {
+ pwstm->GetCP()->SetParent(_cpoint.GetParent());
+ pwstm->SetAsyncFlags(_asyncFlags);
+ pwstm->GetCP()->Clone(&_cpoint);
+ }
+
+ }
+ else *ppstm = NULL;
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncStream::Clone\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::EnumConnectionPoints, public
+//
+// Synopsis: Return enumerator on connection points
+//
+// Arguments: [ppEnum] -- Return pointer of enumerator
+//
+// Returns: Appropriate status code
+//
+// History: 28-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStream::EnumConnectionPoints(IEnumConnectionPoints **ppEnum)
+{
+ astgDebugOut((DEB_ITRACE,
+ "In CAsyncStream::EnumConnectionPoints:%p()\n",
+ this));
+ astgDebugOut((DEB_ITRACE,
+ "Out CAsyncStream::EnumConnectionPoints\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncStream::FindConnectionPoint, public
+//
+// Synopsis: Return a connection point given an IID
+//
+// Arguments: [iid] -- IID to return connection point for
+// [ppCP] -- Return location for pointer
+//
+// Returns: Appropriate status code
+//
+// History: 28-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncStream::FindConnectionPoint(REFIID iid,
+ IConnectionPoint **ppCP)
+{
+ astgDebugOut((DEB_ITRACE,
+ "In CAsyncStream::FindConnectionPoint:%p()\n",
+ this));
+
+ CConnectionPoint *pcp;
+
+ if (IsEqualIID(iid, IID_IProgressNotify))
+ {
+ pcp = &_cpoint;
+ }
+ else
+ {
+ *ppCP = NULL;
+ return E_NOINTERFACE;
+ }
+
+ pcp->AddRef();
+ *ppCP = pcp;
+
+ astgDebugOut((DEB_ITRACE,
+ "Out CAsyncStream::FindConnectionPoint\n"));
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncEnum::QueryInterface, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncEnum::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc = S_OK;
+ *ppvObj = NULL;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncEnum::QueryInterface:%p()\n", this));
+ if (IsEqualIID(iid, IID_IUnknown))
+
+ {
+ *ppvObj = (IEnumSTATSTG *)this;
+ }
+ else if (IsEqualIID(iid, IID_IEnumSTATSTG))
+ {
+ *ppvObj = (IEnumSTATSTG *)this;
+ }
+ else if (IsEqualIID(iid, IID_IConnectionPointContainer))
+ {
+ *ppvObj = (IConnectionPointContainer *)this;
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ AddRef();
+ }
+ astgDebugOut((DEB_ITRACE, "Out CAsyncEnum::QueryInterface:%p()\n", this));
+ return sc;
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncEnum::AddRef, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CAsyncEnum::AddRef(void)
+{
+ ULONG ulRet;
+ astgDebugOut((DEB_ITRACE, "In CAsyncEnum::AddRef:%p()\n", this));
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+ _pRealEnum->AddRef();
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncEnum::AddRef\n"));
+ return ulRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncEnum::Release, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CAsyncEnum::Release(void)
+{
+ LONG lRet;
+ astgDebugOut((DEB_ITRACE, "In CAsyncEnum::Release:%p()\n", this));
+
+ lRet = InterlockedDecrement(&_cReferences);
+ _pRealEnum->Release();
+
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ lRet = 0;
+ astgDebugOut((DEB_ITRACE, "Out CAsyncEnum::Release\n"));
+ return (ULONG)lRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncEnum::EnumConnectionPoints, public
+//
+// Synopsis: Return enumerator on connection points
+//
+// Arguments: [ppEnum] -- Return pointer of enumerator
+//
+// Returns: Appropriate status code
+//
+// History: 28-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncEnum::EnumConnectionPoints(IEnumConnectionPoints **ppEnum)
+{
+ astgDebugOut((DEB_ITRACE,
+ "In CAsyncEnum::EnumConnectionPoints:%p()\n",
+ this));
+ astgDebugOut((DEB_ITRACE,
+ "Out CAsyncEnum::EnumConnectionPoints\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncEnum::FindConnectionPoint, public
+//
+// Synopsis: Return a connection point given an IID
+//
+// Arguments: [iid] -- IID to return connection point for
+// [ppCP] -- Return location for pointer
+//
+// Returns: Appropriate status code
+//
+// History: 28-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncEnum::FindConnectionPoint(REFIID iid,
+ IConnectionPoint **ppCP)
+{
+ astgDebugOut((DEB_ITRACE,
+ "In CAsyncEnum::FindConnectionPoint:%p()\n",
+ this));
+
+ CConnectionPoint *pcp;
+
+ if (IsEqualIID(iid, IID_IProgressNotify))
+ {
+ pcp = &_cpoint;
+ }
+ else
+ {
+ *ppCP = NULL;
+ return E_NOINTERFACE;
+ }
+
+ pcp->AddRef();
+ *ppCP = pcp;
+
+ astgDebugOut((DEB_ITRACE,
+ "Out CAsyncEnum::FindConnectionPoint\n"));
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncEnum::Next, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncEnum::Next(ULONG celt,
+ STATSTG FAR *rgelt,
+ ULONG *pceltFetched)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncEnum::Next:%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealEnum->Next(celt, rgelt, pceltFetched));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncEnum::Next\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncEnum::Skip, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncEnum::Skip(ULONG celt)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncEnum::Skip:%p()\n", this));
+ sc = _pRealEnum->Skip(celt);
+
+ DO_PENDING_LOOP(_pRealEnum->Skip(celt));
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncEnum::Skip\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncEnum::Reset, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncEnum::Reset(void)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncEnum::Reset:%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealEnum->Reset());
+
+ astgDebugOut((DEB_ITRACE, "Out CAsyncEnum::Reset\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncEnum::Clone, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncEnum::Clone(IEnumSTATSTG **ppenm)
+{
+ SCODE sc = S_OK;
+ SCODE sc2 = S_OK;
+
+ astgDebugOut((DEB_ITRACE, "In CAsyncEnum::Clone:%p()\n", this));
+
+ DO_PENDING_LOOP(_pRealEnum->Clone(ppenm));
+
+ if (SUCCEEDED(sc))
+ {
+ CAsyncEnum *pwenum = new CAsyncEnum(*ppenm, _pflb, _fDefaultLockBytes);
+ if (pwenum == NULL)
+ {
+ (*ppenm)->Release();
+ *ppenm = NULL;
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ *ppenm = (IEnumSTATSTG *) pwenum;
+ if (_asyncFlags == ASYNC_MODE_COMPATIBILITY)
+ {
+ pwenum->GetCP()->SetParent(_cpoint.GetParent());
+ pwenum->SetAsyncFlags(_asyncFlags);
+ pwenum->GetCP()->Clone(&_cpoint);
+ }
+ }
+ astgDebugOut((DEB_ITRACE, "Out CAsyncEnum::Clone\n"));
+ return ResultFromScode(sc);
+}
diff --git a/private/ole32/stg/async/docfile/stgwrap.hxx b/private/ole32/stg/async/docfile/stgwrap.hxx
new file mode 100644
index 000000000..af99d51e3
--- /dev/null
+++ b/private/ole32/stg/async/docfile/stgwrap.hxx
@@ -0,0 +1,465 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: stgwrap.hxx
+//
+// Contents: IStorage and IStream wrappers for async docfile
+//
+// Classes: CAsyncStorage
+// CAsyncRootStorage
+// CAsyncStream
+// CConnectionPoint
+//
+// Functions:
+//
+// History: 27-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ASYNCEXPDF_HXX__
+#define __ASYNCEXPDF_HXX__
+
+#include "sinklist.hxx"
+#include "filllkb.hxx"
+
+#ifndef ASYNC
+
+//BUGBUG: defined in dfmsp.hxx.
+typedef DWORD LPSTGSECURITY;
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CAsyncStorage
+//
+// Purpose: Wrap storage objects for Async Docfiles
+//
+// Interface:
+//
+// History: 28-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+class CAsyncStorage:
+ public IStorage,
+ public IConnectionPointContainer
+{
+public:
+ inline CAsyncStorage(IStorage *pstg, IFillLockBytes *pflb, BOOL fDefault);
+ inline ~CAsyncStorage(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+ // IStorage
+ STDMETHOD(CreateStream)(OLECHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(OpenStream)(OLECHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(CreateStorage)(OLECHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ LPSTGSECURITY reserved2,
+ IStorage **ppstg);
+ STDMETHOD(OpenStorage)(OLECHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg);
+ STDMETHOD(CopyTo)(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest);
+ STDMETHOD(MoveElementTo)(OLECHAR const *lpszName,
+ IStorage *pstgDest,
+ OLECHAR const *lpszNewName,
+ DWORD grfFlags);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(EnumElements)(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm);
+ STDMETHOD(DestroyElement)(OLECHAR const *pwcsName);
+ STDMETHOD(RenameElement)(OLECHAR const *pwcsOldName,
+ OLECHAR const *pwcsNewName);
+ STDMETHOD(SetElementTimes)(const OLECHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+ STDMETHOD(SetClass)(REFCLSID clsid);
+ STDMETHOD(SetStateBits)(DWORD grfStateBits, DWORD grfMask);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+
+ //From IConnectionPointContainer
+ STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum);
+ STDMETHOD(FindConnectionPoint)(REFIID iid, IConnectionPoint **ppCP);
+
+ inline void SetAsyncFlags(DWORD asyncFlags);
+ inline CConnectionPoint * GetCP(void);
+
+protected:
+ LONG _cReferences;
+ IStorage *_pRealStg;
+ IFillLockBytes *_pflb;
+ BOOL _fDefaultLockBytes;
+ CConnectionPoint _cpoint;
+DWORD _asyncFlags;
+};
+inline CConnectionPoint *CAsyncStorage::GetCP(void)
+{
+ return &_cpoint;
+}
+
+
+inline CAsyncStorage::CAsyncStorage(IStorage *pstg,
+ IFillLockBytes *pflb,
+ BOOL fDefault)
+{
+ _cReferences = 1;
+ _pRealStg = pstg;
+ _pflb = pflb;
+ _pflb->AddRef();
+ _fDefaultLockBytes = fDefault;
+ _asyncFlags = 0;
+}
+
+
+inline CAsyncStorage::~CAsyncStorage(void)
+{
+ _pflb->Release();
+}
+
+
+inline void CAsyncStorage::SetAsyncFlags(DWORD asyncFlags)
+{
+ _asyncFlags = asyncFlags;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Class: CAsyncRootStorage
+//
+// Purpose: Wrap Root Storage objects for Async Docfiles
+//
+// Interface:
+//
+// History: 28-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+class CAsyncRootStorage:
+ public IRootStorage,
+ public CAsyncStorage
+{
+public:
+ inline CAsyncRootStorage(IStorage *pstg,
+ IFillLockBytes *pflb,
+ BOOL fDefault);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+ // IRootStorage
+ STDMETHOD(SwitchToFile)(OLECHAR *ptcsFile);
+};
+
+inline CAsyncRootStorage::CAsyncRootStorage(IStorage *pstg,
+ IFillLockBytes *pflb,
+ BOOL fDefault)
+ :CAsyncStorage(pstg, pflb, fDefault)
+{
+}
+
+//+---------------------------------------------------------------------------
+//
+// Class: CAsyncStream
+//
+// Purpose: Wrap Stream objects for Async Docfiles
+//
+// Interface:
+//
+// History: 28-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+class CAsyncStream:
+ public IStream,
+ public IConnectionPointContainer
+{
+public:
+ inline CAsyncStream(IStream *pstm, IFillLockBytes *pflb, BOOL fDefault);
+ inline ~CAsyncStream(void);
+
+ // From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+
+ // From IStream
+ STDMETHOD(Read)(VOID HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbRead);
+ STDMETHOD(Write)(VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ STDMETHOD(Seek)(LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition);
+ STDMETHOD(SetSize)(ULARGE_INTEGER cb);
+ STDMETHOD(CopyTo)(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(LockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+ STDMETHOD(Clone)(IStream **ppstm);
+
+ //From IConnectionPointContainer
+ STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum);
+ STDMETHOD(FindConnectionPoint)(REFIID iid, IConnectionPoint **ppCP);
+
+ inline void SetAsyncFlags(DWORD asyncFlags);
+ inline CConnectionPoint * GetCP(void);
+
+private:
+ LONG _cReferences;
+ IStream *_pRealStm;
+ IFillLockBytes *_pflb;
+ BOOL _fDefaultLockBytes;
+ CConnectionPoint _cpoint;
+ DWORD _asyncFlags;
+
+#ifdef SWEEPER
+ //On platforms where OLE has not been fixed, we need to cache a
+ // seek pointer in the wrapper to get around a bug.
+ ULONG _ulSeek;
+#endif
+};
+
+inline CAsyncStream::CAsyncStream(IStream *pstm,
+ IFillLockBytes *pflb,
+ BOOL fDefault)
+{
+ _cReferences = 1;
+ _pRealStm = pstm;
+ _pflb = pflb;
+ _pflb->AddRef();
+ _fDefaultLockBytes = fDefault;
+ _asyncFlags = 0;
+#ifdef SWEEPER
+ _ulSeek = 0;
+#endif
+
+}
+inline CAsyncStream::~CAsyncStream(void)
+{
+ _pflb->Release();
+}
+
+
+inline CConnectionPoint *CAsyncStream::GetCP(void)
+{
+ return &_cpoint;
+}
+
+inline void CAsyncStream::SetAsyncFlags(DWORD asyncFlags)
+{
+ _asyncFlags = asyncFlags;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CAsyncEnumSTATSTG
+//
+// Purpose: Wrap EnumSTATSTG objects for Async Docfiles
+//
+// Interface:
+//
+// History: 28-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+class CAsyncEnum
+ : public IEnumSTATSTG,
+ public IConnectionPointContainer
+{
+public:
+ inline CAsyncEnum(IEnumSTATSTG *penum,
+ IFillLockBytes *pflb,
+ BOOL fDefault);
+ inline ~CAsyncEnum(void);
+
+ // From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // IEnumSTATSTG
+ STDMETHOD(Next)(ULONG celt, STATSTG FAR *rgelt, ULONG *pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(IEnumSTATSTG **ppenm);
+
+ //From IConnectionPointContainer
+ STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum);
+ STDMETHOD(FindConnectionPoint)(REFIID iid, IConnectionPoint **ppCP);
+
+ inline void SetAsyncFlags(DWORD asyncFlags);
+ inline CConnectionPoint * GetCP(void);
+
+private:
+
+ LONG _cReferences;
+ IEnumSTATSTG *_pRealEnum;
+ IFillLockBytes *_pflb;
+ BOOL _fDefaultLockBytes;
+ CConnectionPoint _cpoint;
+ DWORD _asyncFlags;
+
+};
+
+inline CAsyncEnum::CAsyncEnum(IEnumSTATSTG *penum,
+ IFillLockBytes *pflb,
+ BOOL fDefault)
+{
+ _cReferences = 1;
+ _pRealEnum = penum;
+ _pflb = pflb;
+ _pflb->AddRef();
+ _fDefaultLockBytes = fDefault;
+ _asyncFlags = 0;
+}
+
+inline CAsyncEnum::~CAsyncEnum(void)
+{
+ _pflb->Release();
+}
+
+inline CConnectionPoint *CAsyncEnum::GetCP(void)
+{
+ return &_cpoint;
+}
+
+inline void CAsyncEnum::SetAsyncFlags(DWORD asyncFlags)
+{
+ _asyncFlags = asyncFlags;
+}
+
+
+
+
+#define ISPENDINGERROR(x) ((x == E_PENDING) || (x == STG_E_PENDINGCONTROL))
+
+#define TAKE_CRITICAL_SECTION if (_fDefaultLockBytes) \
+ ((CFillLockBytes *)_pflb)->TakeCriticalSection()
+
+#define RELEASE_CRITICAL_SECTION if (_fDefaultLockBytes) \
+ ((CFillLockBytes *)_pflb)->ReleaseCriticalSection()
+
+
+//The following construct is used repeatedly in the wrapper code to
+// try a function, then perform notification if an E_PENDING error is
+// returned.
+#define DO_PENDING_LOOP(x) \
+do \
+{ \
+ TAKE_CRITICAL_SECTION; \
+ sc = x; \
+ if (!ISPENDINGERROR(sc)) \
+ { \
+ RELEASE_CRITICAL_SECTION; \
+ break; \
+ } \
+ else if ((sc2 = _cpoint.Notify(sc, \
+ _pflb, \
+ _fDefaultLockBytes)) != S_OK) \
+ { \
+ return ResultFromScode(sc2); \
+ } \
+} while (TRUE);
+
+
+
+
+#ifdef SWEEPER
+//A bug on Sweeper platforms makes it necessary to cache the seek pointer
+// in stream calls. This macro helps with that.
+#define DO_PENDING_LOOP_WITH_SEEK(x, y) \
+do \
+{ \
+ TAKE_CRITICAL_SECTION; \
+ LARGE_INTEGER li; \
+ li.QuadPart = _ulSeek; \
+ sc = _pRealStm->Seek(li, STREAM_SEEK_SET, NULL); \
+ if (SUCCEEDED(sc)) \
+ sc = x; \
+ if ((ISPENDINGERROR(sc)) && ((sc2 = _cpoint.Notify(sc, \
+ _pflb, \
+ _fDefaultLockBytes)) \
+ != S_OK)) \
+ { \
+ if (y) \
+ *y = 0; \
+ return ResultFromScode(sc2); \
+ } \
+ else if (!ISPENDINGERROR(sc)) \
+ RELEASE_CRITICAL_SECTION; \
+} while (ISPENDINGERROR(sc));
+
+
+#define DO_PENDING_LOOP_WITH_SEEK_AND_LI(x, y) \
+do \
+{ \
+ TAKE_CRITICAL_SECTION; \
+ LARGE_INTEGER li; \
+ li.QuadPart = _ulSeek; \
+ sc = _pRealStm->Seek(li, STREAM_SEEK_SET, NULL); \
+ if (SUCCEEDED(sc)) \
+ sc = x; \
+ if ((ISPENDINGERROR(sc)) && ((sc2 = _cpoint.Notify(sc, \
+ _pflb, \
+ _fDefaultLockBytes)) \
+ != S_OK)) \
+ { \
+ if (y) \
+ (*y).QuadPart = 0; \
+ return ResultFromScode(sc2); \
+ } \
+ else if (!ISPENDINGERROR(sc)) \
+ RELEASE_CRITICAL_SECTION; \
+} while (ISPENDINGERROR(sc));
+#endif
+#endif //!ASYNC
+
+#endif // #ifndef __ASYNCEXPDF_HXX__
diff --git a/private/ole32/stg/async/docfile/sweeper.chi/makefile b/private/ole32/stg/async/docfile/sweeper.chi/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/async/docfile/sweeper.chi/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/async/docfile/sweeper.chi/sources b/private/ole32/stg/async/docfile/sweeper.chi/sources
new file mode 100644
index 000000000..dcf975634
--- /dev/null
+++ b/private/ole32/stg/async/docfile/sweeper.chi/sources
@@ -0,0 +1,93 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Philip Lafornara (PhilipLa) 19-Dec-1995
+
+!ENDIF
+
+
+MAJORCOMP = asyncstg
+MINORCOMP = asyncstg
+
+!include ..\..\chicago.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= asyncstg
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= $(BASEDIR)\public\sdk\lib\chicago
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= DYNLINK
+
+DLLDEF= obj\$(TARGET_DIRECTORY)\asyncstg.def
+
+DLLENTRY= _DllMainCRTStartup
+
+DLLBASE= @$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,usermode
+
+INCLUDES= ..;..\..\h;..\..\idl\chicago\obj
+
+C_DEFINES= \
+ -DSWEEPER \
+ $(C_DEFINES)
+
+
+PRECOMPILED_INCLUDE= ..\astghead.cxx
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
+
+SOURCES= \
+ ..\asyncapi.cxx \
+ ..\filllkb.cxx \
+ ..\stgwrap.cxx \
+ ..\stgconn.cxx \
+ ..\filelkb.cxx \
+ ..\asyncstg.rc
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+
+LINKLIBS= \
+ $(BASEDIR)\public\sdk\lib\chicago\*\astguuid.lib \
+ ..\..\debug\chicago\obj\*\debug.lib \
+ $(BASEDIR)\public\sdk\lib\chicago\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\chicago\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\chicago\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\chicago\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\chicago\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\chicago\*\uuid.lib
+
+
+!include ..\sources.inc
+
diff --git a/private/ole32/stg/async/docfile/sweeper.day/makefile b/private/ole32/stg/async/docfile/sweeper.day/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/async/docfile/sweeper.day/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/async/docfile/sweeper.day/sources b/private/ole32/stg/async/docfile/sweeper.day/sources
new file mode 100644
index 000000000..aa7349229
--- /dev/null
+++ b/private/ole32/stg/async/docfile/sweeper.day/sources
@@ -0,0 +1,102 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Susi Argo (susia) 15-Feb-96
+
+!ENDIF
+
+
+MAJORCOMP = asyncstg
+MINORCOMP = asyncstg
+
+!include ..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= asyncstg
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= $(BASEDIR)\public\sdk\lib
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= DYNLINK
+
+DLLDEF= obj\$(TARGET_DIRECTORY)\asyncstg.def
+
+DLLENTRY= _DllMainCRTStartup
+
+DLLBASE= @$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,usermode
+
+INCLUDES= ..;..\..\h;..\..\idl\daytona\obj
+
+C_DEFINES= \
+ -DSWEEPER \
+ $(C_DEFINES)
+
+
+PRECOMPILED_INCLUDE= ..\astghead.cxx
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
+
+SOURCES= \
+ ..\asyncapi.cxx \
+ ..\filllkb.cxx \
+ ..\stgwrap.cxx \
+ ..\stgconn.cxx \
+ ..\filelkb.cxx \
+ ..\asyncstg.rc
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+
+LINKLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\astguuid.lib \
+ ..\..\debug\daytona\obj\*\debug.lib \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcndr.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcns4.lib \
+ $(BASEDIR)\public\sdk\lib\*\netapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\pwin32.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib \
+ $(BASEDIR)\public\sdk\lib\*\imagehlp.lib
+
+
+#NTTARGETFILE0=allidl
+
+!include ..\sources.inc
+
diff --git a/private/ole32/stg/async/h/error.hxx b/private/ole32/stg/async/h/error.hxx
new file mode 100644
index 000000000..b4e12052c
--- /dev/null
+++ b/private/ole32/stg/async/h/error.hxx
@@ -0,0 +1,33 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992
+//
+// File: error.hxx
+//
+// Contents: Error code handler routines
+//
+// History: 19-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __ERROR_HXX__
+#define __ERROR_HXX__
+
+#if DBG == 1
+#define ErrJmp(comp, label, errval, var) \
+{\
+ var = errval;\
+ comp##DebugOut((DEB_IERROR, "Error %lX at %s:%d\n",\
+ (unsigned long)var, __FILE__, __LINE__));\
+ goto label;\
+}
+#else
+#define ErrJmp(comp, label, errval, var) \
+{\
+ var = errval;\
+ goto label;\
+}
+#endif
+
+#endif // #ifndef __ERROR_HXX__
diff --git a/private/ole32/stg/async/h/valid.h b/private/ole32/stg/async/h/valid.h
new file mode 100644
index 000000000..011aa4eb0
--- /dev/null
+++ b/private/ole32/stg/async/h/valid.h
@@ -0,0 +1,188 @@
+
+#if DBG==1 && defined(WIN32) && !defined(_CHICAGO_)
+#define VDATEHEAP() if( !HeapValidate(GetProcessHeap(),0,0)){ DebugBreak();}
+#else
+#define VDATEHEAP()
+#endif // DBG==1 && defined(WIN32) && !defined(_CHICAGO_)
+
+#define IsValidPtrIn(pv,cb) ((pv == NULL) || !IsBadReadPtr ((pv),(cb)))
+#define IsValidPtrOut(pv,cb) (!IsBadWritePtr((pv),(cb)))
+
+STDAPI_(BOOL) IsValidInterface( void FAR* pv );
+
+
+#if DBG==1
+// for performance, do not do in retail builds
+STDAPI_(BOOL) IsValidIid( REFIID riid );
+#else
+#define IsValidIid(x) (TRUE)
+#endif
+
+#ifdef _DEBUG
+
+//** POINTER IN validation macros:
+#define VDATEPTRIN( pv, TYPE ) \
+ if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid in ptr", __FILE__, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTRIN( pv, TYPE, retval) \
+ if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid in ptr", __FILE__, __LINE__), retval)
+#define VOID_VDATEPTRIN( pv, TYPE ) \
+ if (!IsValidPtrIn( (pv), sizeof(TYPE))) {\
+ FnAssert(#pv,"Invalid in ptr", __FILE__, __LINE__); return; }
+
+//** POINTER IN validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define VDATEPTRIN_LABEL(pv, TYPE, label, retVar) \
+ if (!IsValidPtrIn((pv), sizeof(TYPE))) \
+ { retVar = (FnAssert(#pv, "Invalid in ptr", __FILE__, __LINE__), ResultFromScode(E_INVALIDARG)); \
+ goto label; }
+#define GEN_VDATEPTRIN_LABEL(pv, TYPE, retval, label, retVar) \
+ if (!IsValidPtrIn((pv), sizeof(TYPE))) \
+ { retVar = (FnAssert(#pv, "Invalid in ptr", __FILE__, __LINE__), retval); \
+ goto label; }
+#define VOID_VDATEPTRIN_LABEL(pv, TYPE, label) \
+ if (!IsValidPtrIn((pv), sizeof(TYPE))) \
+ { FnAssert(#pv, "Invalid in ptr", __FILE__, __LINE__); goto label; }
+
+//** POINTER OUT validation macros:
+#define VDATEPTROUT( pv, TYPE ) \
+ if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid out ptr", __FILE__, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTROUT( pv, TYPE, retval ) \
+ if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid out ptr", __FILE__, __LINE__), retval)
+
+//** POINTER OUT validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define VDATEPTROUT_LABEL( pv, TYPE, label, retVar ) \
+ if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ { retVar = (FnAssert(#pv,"Invalid out ptr", __FILE__, __LINE__),ResultFromScode(E_INVALIDARG)); \
+ goto label; }
+#define GEN_VDATEPTROUT_LABEL( pv, TYPE, retval, label, retVar ) \
+ if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ { retVar = (FnAssert(#pv,"Invalid out ptr", __FILE__, __LINE__),retval); \
+ goto label; }
+
+//** INTERFACE validation macro:
+#define GEN_VDATEIFACE( pv, retval ) \
+ if (!IsValidInterface(pv)) \
+ return (FnAssert(#pv,"Invalid interface", __FILE__, __LINE__), retval)
+#define VDATEIFACE( pv ) \
+ if (!IsValidInterface(pv)) \
+ return (FnAssert(#pv,"Invalid interface", __FILE__, __LINE__),ResultFromScode(E_INVALIDARG))
+#define VOID_VDATEIFACE( pv ) \
+ if (!IsValidInterface(pv)) {\
+ FnAssert(#pv,"Invalid interface", __FILE__, __LINE__); return; }
+
+//** INTERFACE validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define GEN_VDATEIFACE_LABEL( pv, retval, label, retVar ) \
+ if (!IsValidInterface(pv)) \
+ { retVar = (FnAssert(#pv,"Invalid interface", __FILE__, __LINE__),retval); \
+ goto label; }
+#define VDATEIFACE_LABEL( pv, label, retVar ) \
+ if (!IsValidInterface(pv)) \
+ { retVar = (FnAssert(#pv,"Invalid interface", __FILE__, __LINE__),ResultFromScode(E_INVALIDARG)); \
+ goto label; }
+#define VOID_VDATEIFACE_LABEL( pv, label ) \
+ if (!IsValidInterface(pv)) {\
+ FnAssert(#pv,"Invalid interface", __FILE__, __LINE__); goto label; }
+
+//** INTERFACE ID validation macro:
+// Only do this in debug build
+#define VDATEIID( iid ) if (!IsValidIid( iid )) \
+ return (FnAssert(#iid,"Invalid iid", __FILE__, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEIID( iid, retval ) if (!IsValidIid( iid )) {\
+ FnAssert(#iid,"Invalid iid", __FILE__, __LINE__); return retval; }
+
+//** INTERFACE ID validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define VDATEIID_LABEL( iid, label, retVar ) if (!IsValidIid( iid )) \
+ {retVar = (FnAssert(#iid,"Invalid iid", __FILE__, __LINE__),ResultFromScode(E_INVALIDARG)); \
+ goto label; }
+#define GEN_VDATEIID_LABEL( iid, retval, label, retVar ) if (!IsValidIid( iid )) {\
+ FnAssert(#iid,"Invalid iid", __FILE__, __LINE__); retVar = retval; goto label; }
+#else
+
+
+
+// --assertless macros for non-debug case
+//** POINTER IN validation macros:
+#define VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTRIN( pv, TYPE, retval ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (retval)
+#define VOID_VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) {\
+ return; }
+
+//** POINTER IN validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define VDATEPTRIN_LABEL(pv, TYPE, label, retVar) \
+ if (!IsValidPtrIn((pv), sizeof(TYPE))) \
+ { retVar = ResultFromScode(E_INVALIDARG); \
+ goto label; }
+#define GEN_VDATEPTRIN_LABEL(pv, TYPE, retval, label, retVar) \
+ if (!IsValidPtrIn((pv), sizeof(TYPE))) \
+ { retVar = retval; \
+ goto label; }
+#define VOID_VDATEPTRIN_LABEL(pv, TYPE, label) \
+ if (!IsValidPtrIn((pv), sizeof(TYPE))) \
+ { goto label; }
+
+//** POINTER OUT validation macros:
+#define VDATEPTROUT( pv, TYPE ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (ResultFromScode(E_INVALIDARG))
+
+#define GEN_VDATEPTROUT( pv, TYPE, retval ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (retval)
+
+//** POINTER OUT validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define VDATEPTROUT_LABEL( pv, TYPE, label, retVar ) \
+ if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ { retVar = ResultFromScode(E_INVALIDARG); \
+ goto label; }
+#define GEN_VDATEPTROUT_LABEL( pv, TYPE, retval, label, retVar ) \
+ if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ { retVar = retval; \
+ goto label; }
+
+//** INTERFACE validation macro:
+#define VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return (ResultFromScode(E_INVALIDARG))
+#define VOID_VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return;
+#define GEN_VDATEIFACE( pv, retval ) if (!IsValidInterface(pv)) \
+ return (retval)
+
+//** INTERFACE validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define GEN_VDATEIFACE_LABEL( pv, retval, label, retVar ) \
+ if (!IsValidInterface(pv)) \
+ { retVar = retval; \
+ goto label; }
+#define VDATEIFACE_LABEL( pv, label, retVar ) \
+ if (!IsValidInterface(pv)) \
+ { retVar = ResultFromScode(E_INVALIDARG); \
+ goto label; }
+#define VOID_VDATEIFACE_LABEL( pv, label ) \
+ if (!IsValidInterface(pv)) {\
+ goto label; }
+
+//** INTERFACE ID validation macro:
+// do not do in retail build. This code USED to call a bogus version of
+// IsValidIID that did no work. Now we are faster and no less stable than before.
+#define VDATEIID( iid ) ((void)0)
+#define GEN_VDATEIID( iid, retval ) ((void)0);
+
+//** INTERFACE ID validation macros for single entry/single exit functions
+//** uses a goto instead of return
+#define VDATEIID_LABEL( iid, label, retVar ) if (!IsValidIid( iid )) \
+ {retVar = ResultFromScode(E_INVALIDARG); \
+ goto label; }
+#define GEN_VDATEIID_LABEL( iid, retval, label, retVar ) if (!IsValidIid( iid )) {\
+ retVar = retval; goto label; }
+
+#endif
+
diff --git a/private/ole32/stg/async/idl/dirs b/private/ole32/stg/async/idl/dirs
new file mode 100644
index 000000000..f0d92a143
--- /dev/null
+++ b/private/ole32/stg/async/idl/dirs
@@ -0,0 +1,37 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Philip Lafornara (PhilipLa) 19-Dec-1995
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ daytona
diff --git a/private/ole32/stg/async/idl/ifill.idl b/private/ole32/stg/async/idl/ifill.idl
new file mode 100644
index 000000000..96cf0ee00
--- /dev/null
+++ b/private/ole32/stg/async/idl/ifill.idl
@@ -0,0 +1,50 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ifill.idl
+//
+// Contents: IFillLockBytes
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+
+[
+ local,
+ object,
+ uuid(99caf010-415e-11cf-8814-00aa00b569f5),
+ pointer_default(unique)
+]
+
+interface IFillLockBytes: IUnknown
+{
+ import "unknwn.idl";
+
+ HRESULT FillAppend
+ (
+ [in] void const *pv,
+ [in] ULONG cb,
+ [out] ULONG *pcbWritten
+ );
+
+ HRESULT FillAt
+ (
+ [in] ULARGE_INTEGER ulOffset,
+ [in] void const *pv,
+ [in] ULONG cb,
+ [out] ULONG *pcbWritten
+ );
+
+ HRESULT SetFillSize
+ (
+ [in] ULARGE_INTEGER ulSize
+ );
+
+ HRESULT Terminate
+ (
+ [in] BOOL bCanceled
+ );
+}
diff --git a/private/ole32/stg/async/idl/ilay.idl b/private/ole32/stg/async/idl/ilay.idl
new file mode 100644
index 000000000..d02efba44
--- /dev/null
+++ b/private/ole32/stg/async/idl/ilay.idl
@@ -0,0 +1,48 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: ilay.idl
+//
+// Contents: ILayoutStorage
+//
+// History: 14-Feb-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+[
+ local,
+ object,
+ uuid(0e6d4d90-6738-11cf-9608-00aa00680db4),
+ pointer_default(unique)
+]
+
+
+interface ILayoutStorage: IUnknown
+{
+ import "unknwn.idl";
+
+ typedef struct tagStorageLayout
+ { DWORD LayoutType;
+ OLECHAR *pwcsElementName;
+ LARGE_INTEGER cOffset;
+ LARGE_INTEGER cBytes;
+ } StorageLayout;
+
+
+ HRESULT __stdcall LayoutScript(
+ [in] StorageLayout *pStorageLayout,
+ [in] DWORD nEntries,
+ [in] DWORD glfInterleavedFlag);
+
+ HRESULT __stdcall BeginMonitor(void);
+
+ HRESULT __stdcall EndMonitor(void);
+
+ HRESULT __stdcall ReLayoutDocfile(
+ [in] OLECHAR *pwcsNewDfName);
+
+
+}
+
diff --git a/private/ole32/stg/async/idl/intfy.idl b/private/ole32/stg/async/idl/intfy.idl
new file mode 100644
index 000000000..ad34a68ce
--- /dev/null
+++ b/private/ole32/stg/async/idl/intfy.idl
@@ -0,0 +1,32 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: iprognot.idl
+//
+// Contents: IProgressNotify
+//
+// History: 28-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+
+[
+ local,
+ object,
+ uuid(a9d758a0-4617-11cf-95fc-00aa00680db4),
+ pointer_default(unique)
+]
+
+interface IProgressNotify: IUnknown
+{
+ import "unknwn.idl";
+
+ HRESULT OnProgress (
+ [in] DWORD dwProgressCurrent,
+ [in] DWORD dwProgressMaximum,
+ [in] BOOL fAccurate
+ );
+
+}
diff --git a/private/ole32/stg/async/idl/sources.inc b/private/ole32/stg/async/idl/sources.inc
new file mode 100644
index 000000000..9a091ed81
--- /dev/null
+++ b/private/ole32/stg/async/idl/sources.inc
@@ -0,0 +1 @@
+SYNCHRONIZE_DRAIN=1
diff --git a/private/ole32/stg/async/layout/layapi.cxx b/private/ole32/stg/async/layout/layapi.cxx
new file mode 100644
index 000000000..d55cb809a
--- /dev/null
+++ b/private/ole32/stg/async/layout/layapi.cxx
@@ -0,0 +1,86 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: layapi.cxx
+//
+// Contents: API for layout tool
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-Feb-96 PhilipLa Created
+// 21-Feb-96 SusiA New API, moved ReLayoutDocfile to method
+//
+//----------------------------------------------------------------------------
+
+#include "layouthd.cxx"
+#pragma hdrstop
+
+#include <header.hxx>
+
+#include "laylkb.hxx"
+#include "laywrap.hxx"
+
+#if DBG == 1
+DECLARE_INFOLEVEL(lay);
+#endif
+
+STDAPI StgOpenLayoutDocfile(OLECHAR const *pwcsDfName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage **ppstgOpen)
+{
+ SCODE sc;
+ CLayoutLockBytes *pllkb;
+ IStorage *pstg;
+
+ if ((reserved != 0) || (!ppstgOpen))
+ {
+ return STG_E_INVALIDPARAMETER;
+ }
+ if (!(pwcsDfName))
+ {
+ return STG_E_INVALIDNAME;
+ }
+
+ pllkb = new CLayoutLockBytes();
+ if (pllkb == NULL)
+ {
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ if (FAILED(sc = pllkb->Init(pwcsDfName, grfMode)))
+ {
+ pllkb->Release();
+ return sc;
+ }
+
+ sc = StgOpenStorageOnILockBytes(pllkb,
+ NULL,
+ grfMode,
+ NULL,
+ 0,
+ &pstg);
+
+ if (FAILED(sc))
+ {
+ pllkb->Release();
+ return sc;
+ }
+
+ *ppstgOpen = new CLayoutRootStorage(pstg, pllkb);
+ if (*ppstgOpen == NULL)
+ {
+ pstg->Release();
+ pllkb->Release();
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ pstg->Release();
+ pllkb->Release();
+ return sc;
+}
+
diff --git a/private/ole32/stg/async/layout/laylkb.cxx b/private/ole32/stg/async/layout/laylkb.cxx
new file mode 100644
index 000000000..129781eb1
--- /dev/null
+++ b/private/ole32/stg/async/layout/laylkb.cxx
@@ -0,0 +1,773 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: laylkb.cxx
+//
+// Contents: File ILockBytes implementation for layout storage
+//
+// Classes:
+//
+// Functions:
+//
+// History: 19-Feb-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+#include "layouthd.cxx"
+#pragma hdrstop
+
+#include "laylkb.hxx"
+#include <valid.h>
+
+
+class CSafeCriticalSection
+{
+public:
+ inline CSafeCriticalSection(CRITICAL_SECTION *pcs);
+ inline ~CSafeCriticalSection();
+private:
+ CRITICAL_SECTION *_pcs;
+};
+
+inline CSafeCriticalSection::CSafeCriticalSection(CRITICAL_SECTION *pcs)
+{
+ _pcs = pcs;
+ EnterCriticalSection(_pcs);
+}
+
+inline CSafeCriticalSection::~CSafeCriticalSection()
+{
+ LeaveCriticalSection(_pcs);
+#if DBG == 1
+ _pcs = NULL;
+#endif
+}
+
+#define TAKE_CS CSafeCriticalSection scs(&_cs);
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::CLayoutLockBytes, public
+//
+// Synopsis: Default constructor
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 20-Feb-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+CLayoutLockBytes::CLayoutLockBytes(void)
+{
+ _cReferences = 1;
+ _h = INVALID_HANDLE_VALUE;
+ _hScript = INVALID_HANDLE_VALUE;
+ _fLogging = FALSE;
+ _cbSectorShift = 0;
+ _atcScriptName[0] = TEXT('\0');
+ _awcName[0] = L'\0';
+ InitializeCriticalSection(&_cs);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::~CLayoutLockBytes, public
+//
+// Synopsis: Destructor
+//
+// Returns: Appropriate status code
+//
+// History: 20-Feb-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+CLayoutLockBytes::~CLayoutLockBytes()
+{
+ if (_h != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(_h);
+ _h = INVALID_HANDLE_VALUE;
+ }
+ if (_hScript != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(_hScript);
+ _hScript = INVALID_HANDLE_VALUE;
+ }
+
+ DeleteCriticalSection(&_cs);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::Init, public
+//
+// Synopsis: Initialization function
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// History: 20-Feb-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE CLayoutLockBytes::Init(OLECHAR const *pwcsName,
+ DWORD grfMode)
+{
+ SCODE sc = S_OK;
+ BYTE abHeader[sizeof(CMSFHeaderData)];
+ ULONG cbRead;
+
+ layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Init:%p()\n", this));
+
+ if (pwcsName == NULL)
+ return STG_E_INVALIDNAME;
+
+ _grfMode = grfMode;
+
+#ifndef UNICODE
+ TCHAR atcPath[MAX_PATH + 1];
+ UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ if (!WideCharToMultiByte(
+ uCodePage,
+ 0,
+ pwcsName,
+ -1,
+ atcPath,
+ MAX_PATH + 1,
+ NULL,
+ NULL))
+ {
+ return STG_E_INVALIDNAME;
+ }
+
+ _h = CreateFileA(atcPath,
+ GENERIC_READ | GENERIC_WRITE, //Read-write
+ 0, // No sharing
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
+ NULL);
+#else
+ _h = CreateFile(pwcsName,
+ GENERIC_READ | GENERIC_WRITE, //Read-write
+ 0, // No sharing
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
+ NULL);
+#endif
+
+ if (_h == INVALID_HANDLE_VALUE)
+ {
+ layErr(Err, Win32ErrorToScode(GetLastError()));
+ }
+
+ lstrcpyW(_awcName, pwcsName);
+
+ //Get the sector size
+ boolChk(ReadFile(_h, abHeader, sizeof(CMSFHeaderData), &cbRead, NULL));
+ if (cbRead != sizeof(CMSFHeaderData))
+ {
+ return STG_E_READFAULT;
+ }
+
+ _cbSectorShift = ((CMSFHeaderData *)abHeader)->_uSectorShift;
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Init\n"));
+
+Err:
+ return ResultFromScode(sc);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 26-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CLayoutLockBytes::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::QueryInterface(?, %p)\n",
+ ppvObj));
+
+ layChk(ValidateOutPtrBuffer(ppvObj));
+ *ppvObj = NULL;
+
+ sc = S_OK;
+ if (IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IUnknown *)this;
+ CLayoutLockBytes::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_ILockBytes))
+ {
+ *ppvObj = (ILockBytes *)this;
+ CLayoutLockBytes::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::QueryInterface => %p\n",
+ ppvObj));
+
+Err:
+ return ResultFromScode(sc);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+// History: 16-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CLayoutLockBytes::AddRef(void)
+{
+ ULONG ulRet;
+
+ layDebugOut((DEB_TRACE, "In CLayoutLockBytes::AddRef()\n"));
+
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+
+ layDebugOut((DEB_TRACE, "Out CLayoutLockBytes::AddRef\n"));
+ return ulRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::Release, public
+//
+// History: 20-Feb-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CLayoutLockBytes::Release(void)
+{
+ LONG lRet;
+ layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Release:%p()\n", this));
+
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ {
+ lRet = 0;
+ }
+ layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Release\n"));
+ return lRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::ReadAt, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 20-Feb-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutLockBytes::ReadAt(ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbRead)
+{
+ CSafeCriticalSection scs(&_cs);
+
+ SCODE sc = S_OK;
+ layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::ReadAt:%p()\n", this));
+
+ ULONG ulLow = ulOffset.LowPart;
+ LONG lHigh = (LONG)ulOffset.HighPart;
+
+ if ((_fLogging)&&(ulOffset.QuadPart >= sizeof(CMSFHeaderData)))
+ {
+ if (_hScript == INVALID_HANDLE_VALUE)
+ {
+ return STG_E_INVALIDHANDLE;
+ }
+
+ ULONG ulFirstSector = (ULONG) ((ulOffset.QuadPart -
+ sizeof(CMSFHeaderData))
+ >> _cbSectorShift);
+
+ ULONG ulLastSector = (ULONG) ((ulOffset.QuadPart + (cb - 1) -
+ sizeof(CMSFHeaderData))
+ >> _cbSectorShift);
+ ULONG ulSect;
+ ULONG cbScriptWritten;
+
+ for (ulSect = ulFirstSector; ulSect <= ulLastSector; ulSect++)
+ {
+
+ layAssert(_hScript !=INVALID_HANDLE_VALUE);
+
+ boolChk(WriteFile(_hScript,
+ (VOID *)&ulSect,
+ sizeof(ULONG),
+ &cbScriptWritten,
+ NULL));
+
+
+ if (cbScriptWritten != sizeof(ULONG))
+ {
+ return STG_E_WRITEFAULT;
+ }
+ }
+ }
+
+ negChk(SetFilePointer(_h,
+ ulLow,
+ &lHigh,
+ FILE_BEGIN));
+ boolChk(ReadFile(_h, pv, cb, pcbRead, NULL));
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::ReadAt\n"));
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::WriteAt, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 20-Feb-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutLockBytes::WriteAt(ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ CSafeCriticalSection scs(&_cs);
+
+ SCODE sc = S_OK;
+ layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::WriteAt:%p()\n", this));
+
+ ULONG ulLow = ulOffset.LowPart;
+ LONG lHigh = (LONG)ulOffset.HighPart;
+
+ if ((_fLogging)&&(ulOffset.QuadPart >= sizeof(CMSFHeaderData)))
+ {
+ if (_hScript == INVALID_HANDLE_VALUE)
+ {
+ return STG_E_INVALIDHANDLE;
+ }
+
+ ULONG ulFirstSector = (ULONG) ((ulOffset.QuadPart -
+ sizeof(CMSFHeaderData))
+ >> _cbSectorShift);
+ ULONG ulLastSector = (ULONG) ((ulOffset.QuadPart + (cb - 1) -
+ sizeof(CMSFHeaderData))
+ >> _cbSectorShift);
+ ULONG ulSect;
+ ULONG cbScriptWritten;
+
+ for (ulSect = ulFirstSector; ulSect <= ulLastSector; ulSect++)
+ {
+ boolChk(WriteFile(_hScript,
+ (VOID *)&ulSect,
+ sizeof(ULONG),
+ &cbScriptWritten,
+ NULL));
+ if (cbScriptWritten != sizeof(ULONG))
+ {
+ return STG_E_WRITEFAULT;
+ }
+ }
+ }
+
+ negChk(SetFilePointer(_h,
+ ulLow,
+ &lHigh,
+ FILE_BEGIN));
+ boolChk(WriteFile(_h, pv, cb, pcbWritten, NULL));
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::WriteAt\n"));
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::Flush, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 20-Feb-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutLockBytes::Flush(void)
+{
+ layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Flush:%p()\n", this));
+ layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Flush\n"));
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::SetSize, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 20-Feb-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutLockBytes::SetSize(ULARGE_INTEGER cb)
+{
+ CSafeCriticalSection scs(&_cs);
+
+ SCODE sc = S_OK;
+ layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::SetSize:%p()\n", this));
+ LONG lHigh = (LONG)cb.HighPart;
+ ULONG ulLow = cb.LowPart;
+
+ negChk(SetFilePointer(_h, ulLow, &lHigh, FILE_BEGIN));
+ boolChk(SetEndOfFile(_h));
+ layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::SetSize\n"));
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::LockRegion, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 20-Feb-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutLockBytes::LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ CSafeCriticalSection scs(&_cs);
+
+ SCODE sc = S_OK;
+ layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::LockRegion:%p()\n", this));
+ if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
+ {
+ return STG_E_INVALIDFUNCTION;
+ }
+
+ boolChk(LockFile(_h,
+ libOffset.LowPart,
+ libOffset.HighPart,
+ cb.LowPart,
+ cb.HighPart));
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::LockRegion\n"));
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::UnlockRegion, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 20-Feb-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutLockBytes::UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ CSafeCriticalSection scs(&_cs);
+
+ SCODE sc = S_OK;
+ layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::UnlockRegion:%p()\n", this));
+ if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
+ {
+ return STG_E_INVALIDFUNCTION;
+ }
+
+ boolChk(UnlockFile(_h,
+ libOffset.LowPart,
+ libOffset.HighPart,
+ cb.LowPart,
+ cb.HighPart));
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::UnlockRegion\n"));
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::Stat, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 20-Feb-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutLockBytes::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ CSafeCriticalSection scs(&_cs);
+
+ SCODE sc;
+
+ layDebugOut((DEB_ITRACE, "In CLayoutLockBytes::Stat:%p()\n", this));
+
+ negChk(pstatstg->cbSize.LowPart =
+ GetFileSize(_h, &pstatstg->cbSize.HighPart));
+ boolChk(GetFileTime(_h, &pstatstg->ctime, &pstatstg->atime,
+ &pstatstg->mtime));
+ pstatstg->grfLocksSupported = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
+
+ pstatstg->type = STGTY_LOCKBYTES;
+ pstatstg->grfMode = _grfMode;
+ pstatstg->pwcsName = NULL;
+ if ((grfStatFlag & STATFLAG_NONAME) == 0)
+ {
+ pstatstg->pwcsName = (OLECHAR *)CoTaskMemAlloc(
+ (lstrlenW(_awcName) + 1) * sizeof(OLECHAR));
+ if (pstatstg->pwcsName == NULL)
+ return STG_E_INSUFFICIENTMEMORY;
+ lstrcpyW(pstatstg->pwcsName, _awcName);
+ }
+ sc = S_OK;
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutLockBytes::Stat\n"));
+ return NOERROR;
+
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::StartLogging, public
+//
+// Returns: Appropriate status code
+//
+// Modifies: _fLogging
+//
+// History: 24-Feb-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE CLayoutLockBytes::StartLogging(void)
+{
+ CSafeCriticalSection scs(&_cs);
+
+ OLECHAR acTempPathName[MAX_PATH + 1];
+ SCODE sc = S_OK;
+
+ if (_fLogging)
+ {
+ return STG_E_INUSE; //logging already started!
+ }
+
+
+ if (_atcScriptName[0] != TEXT('\0'))
+ {
+ LONG dwDistanceToMoveHigh = 0;
+
+ //Script has already been started. Need to reopen it and seek
+ // to the end.
+#ifndef UNICODE
+ _hScript = CreateFileA
+#else
+ _hScript = CreateFile
+#endif
+ (_atcScriptName,
+ GENERIC_WRITE, //Read-write
+ 0, // No sharing
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
+ NULL);
+
+ if (_hScript == INVALID_HANDLE_VALUE)
+ {
+ return LAST_STG_SCODE;
+ }
+
+ negChk(SetFilePointer(_hScript, 0, &dwDistanceToMoveHigh, FILE_END));
+ }
+ else
+ {
+ TCHAR atcPath[MAX_PATH + 1];
+ //Generate the script name, then create it.
+
+ boolChk(GetTempPath(MAX_PATH, atcPath));
+ boolChk(GetTempFileName(atcPath, TEXT("SCR"), 0, _atcScriptName));
+
+ //GetTempFileName actually creates the file, so we open with
+ // OPEN_EXISTING
+#ifndef UNICODE
+ _hScript = CreateFileA
+#else
+ _hScript = CreateFile
+#endif
+ (_atcScriptName,
+ GENERIC_READ | GENERIC_WRITE, //Read-write
+ 0, // No sharing
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
+ NULL);
+
+ if (_hScript == INVALID_HANDLE_VALUE)
+ {
+ return LAST_STG_SCODE;
+ }
+ }
+
+ _fLogging = TRUE;
+
+Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::StopLogging, public
+//
+// Returns: Appropriate status code
+//
+// Modifies: _fLogging
+//
+// History: 24-Feb-96 SusiA Created
+//
+// Notes:
+//
+//-----------------------------------------------------------------------------
+SCODE CLayoutLockBytes::StopLogging(void)
+{
+ SCODE sc = S_OK;
+ CSafeCriticalSection scs(&_cs);
+
+ if (!_fLogging)
+ {
+ layAssert(FALSE && "StopLogging called when logging not yet started.");
+ return E_FAIL;
+ }
+
+ boolChk(CloseHandle(_hScript));
+ _hScript = INVALID_HANDLE_VALUE;
+ _fLogging = FALSE;
+
+Err:
+ return sc;
+}
diff --git a/private/ole32/stg/async/layout/laylkb.hxx b/private/ole32/stg/async/layout/laylkb.hxx
new file mode 100644
index 000000000..67ce87de7
--- /dev/null
+++ b/private/ole32/stg/async/layout/laylkb.hxx
@@ -0,0 +1,138 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: laylkb.hxx
+//
+// Contents: Layout ILockBytes class for layout docfile
+//
+// Classes: CLayoutLockBytes
+//
+// Functions:
+//
+// History: 19-Feb-96 SusiAa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __LAYOUTLKB_HXX__
+#define __LAYOUTLKB_HXX__
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CLayoutLockBytes
+//
+// Purpose:
+//
+// Interface:
+//
+// History: 21-Feb-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+class CLayoutLockBytes: public ILockBytes
+{
+public:
+ CLayoutLockBytes();
+ ~CLayoutLockBytes();
+
+ SCODE Init(OLECHAR const *pwcsName, DWORD grfMode);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+ // ILockBytes
+ STDMETHOD(ReadAt)(ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbRead);
+ STDMETHOD(WriteAt)(ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ STDMETHOD(Flush)(void);
+ STDMETHOD(SetSize)(ULARGE_INTEGER cb);
+ STDMETHOD(LockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+
+
+ inline HANDLE GetHandle(void);
+ inline TCHAR *GetScriptName(void);
+ inline void ClearScriptName(void);
+ SCODE StartLogging(void);
+ SCODE StopLogging(void);
+
+private:
+ LONG _cReferences;
+ BOOL _fLogging;
+ ULONG _cbSectorShift;
+ DWORD _grfMode;
+
+ TCHAR _atcScriptName[MAX_PATH + 1];
+ HANDLE _hScript;
+ OLECHAR _awcName[MAX_PATH + 1];
+ HANDLE _h;
+
+ CRITICAL_SECTION _cs;
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::GetHandle, public
+//
+// Synopsis: Return the file handle for this ILockBytes
+//
+// Arguments: None
+//
+// Returns: File Handle
+//
+// History: 20-Feb-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+inline HANDLE CLayoutLockBytes::GetHandle(void)
+{
+ return _h;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::GetScriptName, public
+//
+// Returns: Pointer to script name
+//
+// History: 24-Feb-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+inline TCHAR * CLayoutLockBytes::GetScriptName(void)
+{
+ return _atcScriptName;
+}
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutLockBytes::ClearScriptName, public
+//
+// Returns: Pointer to script name
+//
+// History: 24-Feb-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+inline void CLayoutLockBytes::ClearScriptName(void)
+{
+ _atcScriptName[0] = TEXT('\0');
+}
+
+
+#endif // #ifndef __FILELKB_HXX__
diff --git a/private/ole32/stg/async/layout/layout.cxx b/private/ole32/stg/async/layout/layout.cxx
new file mode 100644
index 000000000..622a18ea5
--- /dev/null
+++ b/private/ole32/stg/async/layout/layout.cxx
@@ -0,0 +1,1012 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: layout.cxx
+//
+// Contents: Code for the relayout tool
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-Feb-96 PhilipLa Created
+// 21-Feb-96 SusiA Put funtions on ILayoutStorage
+//
+//----------------------------------------------------------------------------
+
+#include "layouthd.cxx"
+#pragma hdrstop
+
+#include <dirfunc.hxx>
+#include "laylkb.hxx"
+#include "laywrap.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLayoutRootStorage::LayoutScript
+//
+// Synopsis: Construct an unprocessed script from an app provided script
+//
+// Arguments: [pStorageLayout] -- Pointer to storage layout array
+// [nEntries] -- Number of entries in the array
+// [grfInterleavedFlag] -- Specifies disposition of control
+// structures
+//
+// Returns: Appropriate status code
+//
+// History: 21-Feb-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::LayoutScript( StorageLayout *pStorageLayout,
+ DWORD nEntries,
+ DWORD glfInterleavedFlag)
+{
+
+ SCODE sc;
+
+ if ((LONG)nEntries < 0)
+ {
+ return E_INVALIDARG;
+ }
+
+ if ((LONG)nEntries == 0)
+ {
+ return S_OK;
+ }
+
+ if ((glfInterleavedFlag != STG_LAYOUT_INTERLEAVED) &&
+ (glfInterleavedFlag != STG_LAYOUT_SEQUENTIAL ) )
+ {
+ return STG_E_INVALIDFLAG;
+ }
+
+ if (IsBadWritePtr( pStorageLayout, nEntries * sizeof(StorageLayout)))
+ {
+ return STG_E_INVALIDPOINTER;
+ }
+
+ if (FAILED(sc = BeginMonitor()))
+ {
+ return sc;
+ }
+
+ if (FAILED(sc = ProcessLayout(pStorageLayout,
+ nEntries,
+ glfInterleavedFlag)))
+ {
+ //BUGBUG: what do we do if this EndMonitor fails?
+ EndMonitor();
+ return sc;
+ }
+
+ if (FAILED(sc = EndMonitor()))
+ {
+ return sc;
+ }
+
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLayoutRootStorage::BeginMonitor
+//
+// Synopsis: Begin monitoring the ILockBytes operations for recording a
+// script.
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+// History: 21-Feb-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::BeginMonitor(void)
+{
+ SCODE sc = S_OK;
+ sc = _pllkb->StartLogging();
+ return ResultFromScode(sc);
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLayoutRootStorage::EndMonitor
+//
+// Synopsis: Stop monitoring ILockBytes operations for script recording.
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+// History: 21-Feb-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::EndMonitor(void)
+{
+ SCODE sc = S_OK;
+ sc = _pllkb->StopLogging();
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLayoutRootStorage::ReLayoutDocfile
+//
+// Synopsis: Relayout the docfile into the new name specified.
+//
+// Arguments: [pwcsNewName] -- Name of destination file
+//
+// Returns: Appropriate status code
+//
+// History: 13-Feb-96 PhilipLa Created
+// 21-Feb-96 SusiA Made a method on ILayoutStorage
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::ReLayoutDocfile(OLECHAR *pwcsNewDfName)
+{
+ SCODE sc;
+
+#ifndef UNICODE
+ WCHAR awcScriptName[MAX_PATH + 1];
+ UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ if (!MultiByteToWideChar(
+ uCodePage,
+ 0,
+ _pllkb->GetScriptName(),
+ -1,
+ awcScriptName,
+ MAX_PATH + 1
+ ))
+ {
+ return STG_E_INVALIDNAME;
+ }
+ sc = StgLayoutDocfile(_pllkb->GetHandle(),
+ pwcsNewDfName,
+ awcScriptName);
+#else
+
+
+ sc = StgLayoutDocfile(_pllkb->GetHandle(),
+ pwcsNewDfName,
+ _pllkb->GetScriptName());
+#endif
+
+ if (FAILED(sc))
+ {
+ //Delete new file
+#ifdef UNICODE
+ DeleteFileW(pwcsNewDfName);
+#else
+ TCHAR atcPath[MAX_PATH + 1];
+ UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ //Note: Intentionally ignore an error if it happens here. We
+ // want to return the error from StgLayoutDocfile, not from
+ // the cleanup path.
+ WideCharToMultiByte(
+ uCodePage,
+ 0,
+ pwcsNewDfName,
+ -1,
+ atcPath,
+ _MAX_PATH + 1,
+ NULL,
+ NULL);
+ DeleteFileA(atcPath);
+#endif
+ }
+ else
+ {
+ //Delete Script File
+ DeleteFile(_pllkb->GetScriptName());
+ //Note: Intentionally ignore an error if it happens here. We
+ // want to return the error from StgLayoutDocfile, not from
+ // the cleanup path.
+ _pllkb->ClearScriptName();
+
+ }
+ return sc;
+}
+
+#if DBG == 1
+STDMETHODIMP CLayoutRootStorage::GetScript(TCHAR **ptcsScriptFileName)
+{
+
+ *ptcsScriptFileName = _pllkb->GetScriptName();
+ return S_OK;
+}
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLayoutRootStorage::ReLayoutDocfileOnILockBytes
+//
+// Synopsis: Relayout the docfile into a generic ILockBytes implementation.
+//
+// Arguments: [pILockBytes] -- destination relayout ILockBytes
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jun-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::ReLayoutDocfileOnILockBytes(ILockBytes *pILockBytes)
+{
+ return STG_E_UNIMPLEMENTEDFUNCTION;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgLayoutDocfile
+//
+// Synopsis: Given an old file and an unprocessed script, relayout the
+// docfile into the new name specified.
+//
+// Arguments: [hOld] -- Handle of source file
+// [pwcsNewDfName] -- Name of destination file
+// [pwcsScriptName] -- Name of unprocessed script file
+//
+// Returns: Appropriate status code
+//
+// History: 13-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE StgLayoutDocfile(HANDLE hOld,
+ OLECHAR const *pwcsNewDfName,
+ OLECHAR const *pwcsScriptName)
+{
+ SCODE sc = S_OK;
+ CMappedFile mfOld, mfNew, mfScript;
+ void *pvOld, *pvNew, *pvScript;
+ ULONG ulScriptSize;
+ ULONG csectScript, csectProcessed, csectFile;
+ ULONG cbSectorSize;
+ ULONG i;
+
+ SECT *psProcessedScript = NULL;
+ DWORD dwSize;
+
+ if (pwcsNewDfName == NULL)
+ return STG_E_INVALIDNAME;
+
+ layChkTo(EH_End, mfOld.InitFromHandle(hOld,
+ GENERIC_READ,
+ TRUE,
+ NULL));
+
+ layChkTo(EH_End, mfNew.Init(pwcsNewDfName,
+ mfOld.GetSize(),
+ GENERIC_READ | GENERIC_WRITE,
+ CREATE_ALWAYS,
+ NULL));
+
+
+ if ((pwcsScriptName !=NULL) &&
+ (pwcsScriptName[0] != TEXT('\0')) )
+ {
+ sc = mfScript.Init(pwcsScriptName,
+ 0,
+ GENERIC_READ,
+ OPEN_EXISTING,
+ NULL);
+ layChkTo(EH_End, sc);
+
+ if (sc == STG_S_FILEEMPTY)
+ {
+ pvScript = NULL;
+ }
+ else
+ {
+ pvScript = mfScript.GetBaseAddress();
+ }
+ }
+ else
+ {
+ pvScript = NULL;
+ }
+
+ pvOld = mfOld.GetBaseAddress();
+ pvNew = mfNew.GetBaseAddress();
+
+ //From this point on, we may get an exception while we're poking around
+ // in one of the memory maps. We need to handle this case and be able
+ // to properly return an error and clean up if it happens.
+
+ __try
+ {
+
+ //Figure out how many sectors are in the file
+ cbSectorSize = 1 << ((CMSFHeaderData *)pvOld)->_uSectorShift;
+ csectFile = (mfOld.GetSize() + cbSectorSize - 1 -
+ sizeof(CMSFHeaderData)) / cbSectorSize;
+
+ if (pvScript)
+ {
+ ulScriptSize = mfScript.GetSize();
+ }
+ else
+ {
+ ulScriptSize = 0;
+ }
+
+ csectProcessed = max(ulScriptSize / sizeof(SECT), csectFile);
+ layMem(psProcessedScript = new SECT[csectProcessed]);
+
+ for (i = 0; i < csectProcessed; i++)
+ {
+ psProcessedScript[i] = ENDOFCHAIN;
+ }
+
+ ULONG csectControl;
+ layChk(ProcessControl(psProcessedScript,
+ pvOld,
+ &csectControl));
+
+ layChk(ProcessScript(psProcessedScript,
+ (SECT *)pvScript,
+ csectFile,
+ ulScriptSize / sizeof(SECT),
+ csectControl,
+ &csectScript));
+
+ layAssert(csectScript == csectFile);
+
+ layChk(CopyData(pvNew,
+ pvOld,
+ psProcessedScript,
+ csectFile,
+ cbSectorSize));
+
+ layChk(RemapHeader(pvNew, psProcessedScript, csectFile));
+ layChk(RemapDIF(pvNew, psProcessedScript, csectFile, cbSectorSize));
+ layChk(RemapFat(pvNew,
+ pvOld,
+ psProcessedScript,
+ csectFile,
+ cbSectorSize));
+ layChk(RemapDirectory(pvNew,
+ psProcessedScript,
+ csectFile,
+ cbSectorSize));
+Err:
+ delete psProcessedScript;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ sc = LAST_STG_SCODE;
+ }
+
+EH_End:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetDIFSect
+//
+// Synopsis: Return a pointer to the appropriate sector in the DIF
+//
+// Arguments: [pvBase] -- Pointer to base address of memory mapped file
+// [iDIF] -- Index into DIF desired
+// [cbSectorSize] -- Size in bytes of sector
+//
+// Returns: Pointer to appropriate sector
+//
+// History: 13-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CFatSect * GetDIFSect(void *pvBase,
+ ULONG iDIF,
+ ULONG cbSectorSize,
+ SECT *psect)
+{
+ USHORT cSectPerFat = (USHORT)(cbSectorSize / sizeof(SECT));
+ SECT sectDif = ((CMSFHeaderData *)pvBase)->_sectDifStart;
+
+ for (ULONG i = 0; i < iDIF; i++)
+ {
+ CFatSect *pdif = (CFatSect *)((BYTE *)pvBase +
+ (sectDif * cbSectorSize) +
+ sizeof(CMSFHeaderData));
+ sectDif = pdif->GetSect(cSectPerFat - 1);
+ }
+
+ if (psect)
+ {
+ *psect = sectDif;
+ }
+ return (CFatSect *)((BYTE *)pvBase +
+ (sectDif * cbSectorSize) +
+ sizeof(CMSFHeaderData));
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetFatSect
+//
+// Synopsis: Return a pointer to the appropriate sector in the fat
+//
+// Arguments: [pvBase] -- Pointer to base address of memory mapped file
+// [iFat] -- Index into fat desired
+// [cbSectorSize] -- Size in bytes of sector
+//
+// Returns: Pointer to appropriate sector
+//
+// History: 13-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CFatSect *GetFatSect(void *pvBase,
+ ULONG iFat,
+ ULONG cbSectorSize,
+ SECT *psect)
+{
+ SECT sectFat;
+ BYTE *pbFat;
+
+ if (iFat < CSECTFAT)
+ {
+ //Fatsect can be found in header
+ sectFat = ((CMSFHeaderData *)pvBase)->_sectFat[iFat];
+ }
+ else
+ {
+ ULONG cFatPerDif = (cbSectorSize / sizeof(SECT)) - 1;
+ ULONG iDIF = (iFat - CSECTFAT) / cFatPerDif;
+ USHORT oDIF = (USHORT)((iFat - CSECTFAT) % cFatPerDif);
+ CFatSect *pDif = GetDIFSect(pvBase, iDIF, cbSectorSize, NULL);
+ sectFat = pDif->GetSect(oDIF);
+ }
+
+ pbFat = (BYTE *)pvBase + (sectFat * cbSectorSize) + sizeof(CMSFHeaderData);
+ if (psect)
+ {
+ *psect = sectFat;
+ }
+ return (CFatSect *)pbFat;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetNext
+//
+// Synopsis: Given a sector, return the next sector in the fat chain
+//
+// Arguments: [pvBase] -- Pointer to base address of memory mapped file
+// [sect] -- Sect desired
+// [cbSectorSize] -- Sector size in bytes
+//
+// Returns: Appropriate SECT value
+//
+// History: 13-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SECT GetNext(void *pvBase,
+ SECT sect,
+ ULONG cbSectorSize)
+{
+ ULONG csectPerFat = cbSectorSize / sizeof(SECT);
+ ULONG iFat = sect / csectPerFat;
+ USHORT oFat = (USHORT)(sect % csectPerFat);
+ CFatSect *pfs = GetFatSect(pvBase, iFat, cbSectorSize, NULL);
+
+ return pfs->GetSect(oFat);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ProcessControl, private
+//
+// Synopsis: Add control structures to processed script
+//
+// Arguments: [psProcessed] -- Pointer to processed script
+// [pvOld] -- Pointer to old file
+// [pcsectControl] -- Return location for total sectors processed
+//
+// Returns: Appropriate status code
+//
+// History: 05-Mar-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE ProcessControl(SECT *psProcessed,
+ void *pvOld,
+ ULONG *pcsectControl)
+{
+ SECT sectCurrent = 0;
+ CMSFHeaderData *phdr = (CMSFHeaderData *)pvOld;
+ ULONG csectDif, csectFat;
+ ULONG cbSectorSize;
+
+ csectDif = phdr->_csectDif;
+ csectFat = phdr->_csectFat;
+ cbSectorSize = 1 << phdr->_uSectorShift;
+
+ //We want the structures in the following order:
+ //1) Enough fat and DIFat sectors to hold themselves and all of the
+ // directory sectors.
+ //2) All of the directory sectors
+ //3) Everything else - the rest of the difat, the fat, and the minifat.
+
+ //First find out how big the directory is
+ SECT sectDir = phdr->_sectDirStart;
+ ULONG csectDir = 0;
+ while (sectDir != ENDOFCHAIN)
+ {
+ sectDir = GetNext(pvOld, sectDir, cbSectorSize);
+ csectDir++;
+ }
+
+ //Now compute the number of fat sectors we need to hold the directory
+ // plus the fat sectors themselves.
+ ULONG csectFatNeeded = 0;
+ ULONG csectDifNeeded = 0;
+ ULONG csectNeededLast = 0;
+ ULONG cfsSect = (cbSectorSize / sizeof(SECT));
+
+ do
+ {
+ csectNeededLast = csectFatNeeded;
+ csectFatNeeded = (csectFatNeeded + csectDifNeeded + csectDir +
+ cfsSect - 1) /
+ cfsSect;
+ if (csectFatNeeded > CSECTFAT)
+ {
+ csectDifNeeded = (csectFatNeeded - CSECTFAT + cfsSect - 2) /
+ (cfsSect - 1);
+ }
+ }
+ while (csectFatNeeded != csectNeededLast);
+
+ //Now we know how many DIF, Fat, and Directory sectors we need.
+ //Lay those out first.
+
+ //For those of you keeping score, the docfile will need to have exactly
+ // csectFatNeeded + csectDifNeeded sectors downloaded before it can
+ // be opened.
+ for (ULONG i = 0; i < csectDifNeeded; i++)
+ {
+ SECT sectDif;
+ GetDIFSect(pvOld, i, cbSectorSize, &sectDif);
+ psProcessed[sectDif] = sectCurrent++;
+ }
+
+ for (i = 0; i < csectFatNeeded; i++)
+ {
+ SECT sectFat;
+ GetFatSect(pvOld, i, cbSectorSize, &sectFat);
+ psProcessed[sectFat] = sectCurrent++;
+ }
+ sectDir = phdr->_sectDirStart;
+ for (i = 0; i < csectDir; i++)
+ {
+ layAssert(sectDir != ENDOFCHAIN);
+ psProcessed[sectDir] = sectCurrent++;
+ sectDir = GetNext(pvOld, sectDir, cbSectorSize);
+ }
+
+ //Now put down everything else
+ for (i = csectDifNeeded; i < csectDif; i++)
+ {
+ SECT sectDif;
+ GetDIFSect(pvOld, i, cbSectorSize, &sectDif);
+ psProcessed[sectDif] = sectCurrent++;
+ }
+ for (i = csectFatNeeded; i < csectFat; i++)
+ {
+ SECT sectFat;
+ GetFatSect(pvOld, i, cbSectorSize, &sectFat);
+ psProcessed[sectFat] = sectCurrent++;
+ }
+ //Finally minifat
+ SECT sectMiniFat = phdr->_sectMiniFatStart;
+ while (sectMiniFat != ENDOFCHAIN)
+ {
+ psProcessed[sectMiniFat] = sectCurrent++;
+ sectMiniFat = GetNext(pvOld, sectMiniFat, cbSectorSize);
+ }
+
+ *pcsectControl = sectCurrent;
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: ProcessScript
+//
+// Synopsis: Given a list of sectors in order, construct a mapping
+// of old sector->new sector
+//
+// Arguments: [psProcessed] -- Pointer to destination buffer
+// [psOriginal] -- Pointer to source script buffer
+// [csectFile] -- Count of sectors in file
+// [csectOriginal] -- Count of entries in original script
+// [pcsectProcessed] -- Return location for number of entries
+// in processed script
+//
+// Returns: Appropriate status code
+//
+// History: 13-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE ProcessScript(SECT *psProcessed,
+ SECT *psOriginal,
+ ULONG csectFile,
+ ULONG csectOriginal,
+ ULONG csectControl,
+ ULONG *pcsectProcessed)
+{
+ SCODE sc = S_OK;
+#if DBG == 1
+ ULONG csectProcessed = 0;
+#endif
+ ULONG cDuplicates = 0;
+ ULONG cUnlisted = 0;
+
+ for (ULONG i = 0; i < csectOriginal; i++)
+ {
+ SECT sectOld = psOriginal[i];
+
+ if (sectOld >= csectFile)
+ {
+ //Weird. We're past the range of the file.
+ //BUGBUG: Need a better error code.
+ return STG_E_UNKNOWN;
+ }
+
+#if DBG == 1
+ if (sectOld + 1> csectProcessed)
+ {
+ csectProcessed = sectOld + 1;
+ }
+#endif
+
+ if (psProcessed[sectOld] == ENDOFCHAIN)
+ {
+ psProcessed[sectOld] = i - cDuplicates + csectControl;
+ }
+ else
+ {
+ cDuplicates++;
+ }
+ }
+
+
+ //Fill in holes
+ for (i = 0; i < csectFile; i++)
+ {
+ if (psProcessed[i] == ENDOFCHAIN)
+ {
+ SECT sectNew = csectOriginal - cDuplicates + csectControl +
+ cUnlisted;
+ psProcessed[i] = sectNew;
+ cUnlisted++;
+#if DBG == 1
+ if (sectNew + 1> csectProcessed)
+ {
+ csectProcessed = sectNew + 1;
+ }
+#endif
+ }
+#if DBG == 1
+ //If we have control structures at the end of the file that are
+ // not in the script anywhere (which may happen particularly often
+ // on files produced with simple mode), we want to make sure to
+ // update the count on those. For retail builds, we don't really
+ // care about the count, so we can skip this.
+ else if (psProcessed[i] + 1 > csectProcessed)
+ {
+ csectProcessed = psProcessed[i] + 1;
+ }
+#endif
+ }
+
+#if DBG == 1
+ for (i = 0; i < csectProcessed; i++)
+ {
+ layDebugOut((DEB_IERROR, "Script[%lu] = %lx\n", i, psProcessed[i]));
+ }
+#endif
+
+#if DBG == 1
+ *pcsectProcessed = csectProcessed;
+#else
+ *pcsectProcessed = csectFile;
+#endif
+
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CopyData
+//
+// Synopsis: Given an old->new mapping, copy data from old mapping to
+// new mapping
+//
+// Arguments: [pvNew] -- Pointer to destination mapped file
+// [pvOld] -- Pointer to source mapped file
+// [psScript] -- Pointer to processed script
+// [csectFile] -- Count of sectors in the file
+// [cbSectorSize] -- Sector size in bytes
+//
+// Returns: Appropriate status code
+//
+// History: 13-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CopyData(void *pvNew,
+ void *pvOld,
+ SECT *psScript,
+ ULONG csectFile,
+ ULONG cbSectorSize)
+{
+ SCODE sc = S_OK;
+
+ for (ULONG i = 0; i < csectFile; i++)
+ {
+ BYTE *pbSrc = (BYTE *)pvOld + (i * cbSectorSize) +
+ sizeof(CMSFHeaderData);
+ BYTE *pbDest = (BYTE *)pvNew + (psScript[i] * cbSectorSize) +
+ sizeof(CMSFHeaderData);
+
+ CopyMemory(pbDest, pbSrc, cbSectorSize);
+ }
+ //Also the header.
+ CopyMemory(pvNew, pvOld, sizeof(CMSFHeaderData));
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: RemapHeader
+//
+// Synopsis: Remap the docfile header using a processed script
+//
+// Arguments: [pvNew] -- Pointer to base of memory mapped file
+// [psScript] -- Pointer to processed script
+// [csectFile] -- Count of sectors in file
+//
+// Returns: Appropriate status code
+//
+// History: 13-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE RemapHeader(void *pvNew, SECT *psScript, ULONG csectFile)
+{
+ CMSFHeaderData *ph = (CMSFHeaderData *)pvNew;
+ //Directory start will never be EOC
+ ph->_sectDirStart = psScript[ph->_sectDirStart];
+
+ if (ph->_sectMiniFatStart != ENDOFCHAIN)
+ ph->_sectMiniFatStart = psScript[ph->_sectMiniFatStart];
+
+ if (ph->_sectDifStart != ENDOFCHAIN)
+ ph->_sectDifStart = psScript[ph->_sectDifStart];
+
+ for (ULONG i = 0; i < CSECTFAT; i++)
+ {
+ if (ph->_sectFat[i] != FREESECT)
+ {
+ ph->_sectFat[i] = psScript[ph->_sectFat[i]];
+ }
+ }
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: RemapDIF
+//
+// Synopsis: Remap the DIF according to a processed script
+//
+// Arguments: [pvNew] -- Pointer to base of memory mapped file
+// [psScript] -- Pointer to processed script
+// [csectFile] -- Count of sectors in file
+// [cbSectorSize] -- Sector size in bytes
+//
+// Returns: Appropriate status code
+//
+// History: 13-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE RemapDIF(void *pvNew,
+ SECT *psScript,
+ ULONG csectFile,
+ ULONG cbSectorSize)
+{
+ CMSFHeaderData *ph = (CMSFHeaderData *)pvNew;
+ CFatSect *pfs = NULL;
+ USHORT csectPerDif = (USHORT)(cbSectorSize / sizeof(SECT));
+ SECT sectDif = ph->_sectDifStart;
+
+ for (ULONG i = 0; i < ph->_csectDif; i++)
+ {
+ BYTE *pbDif = (BYTE *)pvNew + (sectDif * cbSectorSize) +
+ sizeof(CMSFHeaderData);
+ pfs = (CFatSect *)pbDif;
+
+ for (USHORT j = 0; j < csectPerDif; j++)
+ {
+ SECT sectOld = pfs->GetSect(j);
+
+ if ((sectOld != FREESECT) &&
+ (sectOld != ENDOFCHAIN))
+ {
+ pfs->SetSect(j, psScript[sectOld]);
+ }
+ }
+
+ sectDif = pfs->GetNextFat(csectPerDif - 1);
+ }
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: RemapFat
+//
+// Synopsis: Remap the Fat according to a processed script and the original
+// file
+//
+// Arguments: [pvNew] -- Pointer to base of destination memory mapped file
+// [pvOld] -- Pointer to base of source memory mapped file
+// [psScript] -- Pointer to processed script
+// [csectFile] -- Count of sectors in file
+// [cbSectorSize] -- Sector size in bytes
+//
+// Returns: Appropriate status code
+//
+// History: 13-Feb-96 PhilipLa Created
+//
+// Notes: Since the processed script does not contain information
+// about individual fat chains, we need the old file in order
+// to construct the new fat.
+//
+//----------------------------------------------------------------------------
+
+SCODE RemapFat(void *pvNew,
+ void *pvOld,
+ SECT *psScript,
+ ULONG csectFile,
+ ULONG cbSectorSize)
+{
+ CFatSect *pfsNew;
+ CFatSect *pfsOld;
+ ULONG csectFat = ((CMSFHeaderData *)pvNew)->_csectFat;
+ USHORT csectPerFat = (USHORT)(cbSectorSize / sizeof(SECT));
+
+ for (ULONG i = 0; i < csectFat; i++)
+ {
+ pfsNew = GetFatSect(pvNew, i, cbSectorSize, NULL);
+ memset(pfsNew, 0xFF, cbSectorSize);
+ }
+
+ for (i = 0; i < csectFat; i++)
+ {
+ pfsOld = GetFatSect(pvOld, i, cbSectorSize, NULL);
+
+ for (USHORT j = 0; j < csectPerFat; j++)
+ {
+ if (i * csectPerFat + j >= csectFile)
+ {
+ //Sector outside of current file size - no remapping
+ //is necessary, and sector has already been marked
+ //as free above.
+ break;
+ }
+
+ SECT sectOld = pfsOld->GetSect(j);
+ SECT sectNew = psScript[i * csectPerFat + j];
+ ULONG iFatNew = sectNew / csectPerFat;
+ USHORT oFatNew = (USHORT)(sectNew % csectPerFat);
+
+ CFatSect *pfsNew = GetFatSect(pvNew, iFatNew, cbSectorSize, NULL);
+
+ if (sectOld > MAXREGSECT)
+ {
+ pfsNew->SetSect(oFatNew, sectOld);
+ }
+ else
+ {
+ //Need to map contents.
+ SECT sectMap = psScript[sectOld];
+ pfsNew->SetSect(oFatNew, sectMap);
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: RemapDirectory
+//
+// Synopsis: Remap a directory based on a processed script
+//
+// Arguments: [pvNew] -- Pointer to base of memory mapped file
+// [psScript] -- Pointer to processed script
+// [csectFile] -- Count of sectors in file
+// [cbSectorSize] -- Sector size in bytes
+//
+// Returns: Appropriate status code
+//
+// History: 13-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE RemapDirectory(void *pvNew,
+ SECT *psScript,
+ ULONG csectFile,
+ ULONG cbSectorSize)
+{
+ CMSFHeaderData *ph = (CMSFHeaderData *)pvNew;
+ CFatSect *pfs = NULL;
+ USHORT csectPerFat = (USHORT)(cbSectorSize / sizeof(SECT));
+ USHORT cEntryPerSect = (USHORT)(cbSectorSize / sizeof(CDirEntry));
+ SECT sectDir = ph->_sectDirStart;
+
+ while (sectDir != ENDOFCHAIN)
+ {
+ BYTE *pbDir = (BYTE *)pvNew + (sectDir * cbSectorSize) +
+ sizeof(CMSFHeaderData);
+ CDirSect *pds = (CDirSect *)pbDir;
+
+ for (USHORT i = 0; i < cEntryPerSect; i++)
+ {
+ CDirEntry *pde = pds->GetEntry(i);
+
+ if (STREAMLIKE(pde->GetFlags()))
+ {
+ SECT sectOld = pde->GetStart();
+ if ((pde->GetSize() >= ph->_ulMiniSectorCutoff) ||
+ (pde->GetFlags() == STGTY_ROOT))
+ {
+ if ((sectOld != ENDOFCHAIN) && (sectOld != FREESECT))
+ {
+ pde->SetStart(psScript[sectOld]);
+ }
+ }
+ }
+ }
+ sectDir = GetNext(pvNew, sectDir, cbSectorSize);
+ }
+
+ return S_OK;
+}
diff --git a/private/ole32/stg/async/layout/layout.def b/private/ole32/stg/async/layout/layout.def
new file mode 100644
index 000000000..bb35e1987
--- /dev/null
+++ b/private/ole32/stg/async/layout/layout.def
@@ -0,0 +1,45 @@
+#if 0
+
+ Microsoft Windows
+ Copyright (C) Microsoft Corporation, 1992 - 1992.
+ All rights reserved.
+
+ This .def file is preprocessed by the compiler to create the version for
+ the current build in the appropriate subdir. Basically, whatever you
+ would have used in your code to control what is compiled when can be
+ used in this file for the same purpose. The following defines are in
+ use at the time this file was written:
+
+ FLAT - Used to indicate a NT/DOS7 build
+ i386 - Intel i386/i486 build
+ MIPS - MIPS R3000/R4000 build
+ ALPHA - DEC Alpha build
+ PPC - PowerPC build
+ DBG - Used to control Debug/Retail. Set to 1 if Debug,
+ 0 if Retail.
+ WIN31 - Win16 build
+ __OS2__ - OS/2 build (used by CT mostly)
+
+ If none of these are used, it is assumed the entire file can be used
+ for all builds.
+
+#endif
+
+LIBRARY dflayout
+
+DESCRIPTION 'Microsoft (R) Docfile Layout Tool for OLE'
+
+#if defined(_CHICAGO_)
+;
+; No security under Win95, take advantage of shared data segments.
+;
+SECTIONS
+ .sdata READ WRITE SHARED
+#endif
+
+EXPORTS
+
+ StgOpenLayoutDocfile
+#if DBG == 1
+ StgLayoutDocfile
+#endif
diff --git a/private/ole32/stg/async/layout/layout.hxx b/private/ole32/stg/async/layout/layout.hxx
new file mode 100644
index 000000000..ef8c5c7aa
--- /dev/null
+++ b/private/ole32/stg/async/layout/layout.hxx
@@ -0,0 +1,53 @@
+
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: layout.hxx
+//
+// Contents: Common header file for layout tool
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-Feb-96 PhilipLa Created
+// 20-Feb-96 SusiA Added StgOpenLayoutDocfile
+// 20-Jun-96 SusiA Add Cruntime functions
+//
+//----------------------------------------------------------------------------
+
+#ifndef __LAYOUT_HXX__
+#define __LAYOUT_HXX__
+#ifdef SWEEPER
+
+HRESULT StgOpenLayoutDocfile(OLECHAR const *pwcsDfName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage **ppstgOpen);
+
+#endif
+
+
+int Laylstrcmp (
+ const wchar_t * src,
+ const wchar_t * dst);
+
+wchar_t * Laylstrcat (
+ wchar_t * dst,
+ const wchar_t * src );
+
+wchar_t * Laylstrcpy(
+ wchar_t * dst,
+ const wchar_t * src );
+
+wchar_t * Laylstrcpyn (
+ wchar_t * dest,
+ const wchar_t * source,
+ size_t count);
+
+size_t Laylstrlen (
+ const wchar_t * wcs);
+
+#endif // #ifndef __LAYOUT_HXX__
diff --git a/private/ole32/stg/async/layout/layout.rc b/private/ole32/stg/async/layout/layout.rc
new file mode 100644
index 000000000..bbc807835
--- /dev/null
+++ b/private/ole32/stg/async/layout/layout.rc
@@ -0,0 +1,19 @@
+#include <windows.h>
+
+//
+// Version resources
+//
+#include <ntverp.h>
+#undef VER_PRODUCTNAME_STR
+#define VER_PRODUCTNAME_STR "Microsoft Docfile Layout Tool for OLE\0"
+#define VER_COMMENT_STR "Microsoft Docfile Layout Tool for OLE\0"
+#define VER_FILEDESCRIPTION_STR "Microsoft Docfile Layout Tool for OLE\0"
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_INTERNALNAME_STR "DFLAYOUT.DLL"
+#define VER_ORIGINALFILENAME_STR "DFLAYOUT.DLL"
+#include <common.ver>
+
+
+
+
diff --git a/private/ole32/stg/async/layout/layouter.cxx b/private/ole32/stg/async/layout/layouter.cxx
new file mode 100644
index 000000000..46fd16fd5
--- /dev/null
+++ b/private/ole32/stg/async/layout/layouter.cxx
@@ -0,0 +1,116 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: layouter.cxx
+//
+// Contents: Error functions
+//
+// Classes:
+//
+// Functions:
+//
+// History: 21-Feb-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+#include "layouthd.cxx"
+#pragma hdrstop
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: Win32ErrorToScode, public
+//
+// Synopsis: Map a Win32 error into a corresponding scode, remapping
+// into Facility_Storage if appropriate.
+//
+// Arguments: [dwErr] -- Win32 error to map
+//
+// Returns: Appropriate scode
+//
+// History: 22-Sep-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Win32ErrorToScode(DWORD dwErr)
+{
+ layAssert((dwErr != NO_ERROR) &&
+ "Win32ErrorToScode called on NO_ERROR");
+
+ SCODE sc = STG_E_UNKNOWN;
+
+ switch (dwErr)
+ {
+ case ERROR_INVALID_FUNCTION:
+ sc = STG_E_INVALIDFUNCTION;
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ sc = STG_E_FILENOTFOUND;
+ break;
+ case ERROR_PATH_NOT_FOUND:
+ sc = STG_E_PATHNOTFOUND;
+ break;
+ case ERROR_TOO_MANY_OPEN_FILES:
+ sc = STG_E_TOOMANYOPENFILES;
+ break;
+ case ERROR_ACCESS_DENIED:
+ case ERROR_NETWORK_ACCESS_DENIED:
+ sc = STG_E_ACCESSDENIED;
+ break;
+ case ERROR_INVALID_HANDLE:
+ sc = STG_E_INVALIDHANDLE;
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ sc = STG_E_INSUFFICIENTMEMORY;
+ break;
+ case ERROR_NO_MORE_FILES:
+ sc = STG_E_NOMOREFILES;
+ break;
+ case ERROR_WRITE_PROTECT:
+ sc = STG_E_DISKISWRITEPROTECTED;
+ break;
+ case ERROR_SEEK:
+ sc = STG_E_SEEKERROR;
+ break;
+ case ERROR_WRITE_FAULT:
+ sc = STG_E_WRITEFAULT;
+ break;
+ case ERROR_READ_FAULT:
+ sc = STG_E_READFAULT;
+ break;
+ case ERROR_SHARING_VIOLATION:
+ sc = STG_E_SHAREVIOLATION;
+ break;
+ case ERROR_LOCK_VIOLATION:
+ sc = STG_E_LOCKVIOLATION;
+ break;
+ case ERROR_HANDLE_DISK_FULL:
+ case ERROR_DISK_FULL:
+ sc = STG_E_MEDIUMFULL;
+ break;
+ case ERROR_FILE_EXISTS:
+ case ERROR_ALREADY_EXISTS:
+ sc = STG_E_FILEALREADYEXISTS;
+ break;
+ case ERROR_INVALID_PARAMETER:
+ sc = STG_E_INVALIDPARAMETER;
+ break;
+ case ERROR_INVALID_NAME:
+ case ERROR_BAD_PATHNAME:
+ case ERROR_FILENAME_EXCED_RANGE:
+ sc = STG_E_INVALIDNAME;
+ break;
+ case ERROR_INVALID_FLAGS:
+ sc = STG_E_INVALIDFLAG;
+ break;
+ default:
+ sc = WIN32_SCODE(dwErr);
+ break;
+ }
+
+ return sc;
+}
+
diff --git a/private/ole32/stg/async/layout/layouter.hxx b/private/ole32/stg/async/layout/layouter.hxx
new file mode 100644
index 000000000..731f32b99
--- /dev/null
+++ b/private/ole32/stg/async/layout/layouter.hxx
@@ -0,0 +1,72 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: layouter.hxx
+//
+// Contents: Error codes for layout tool
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __LAYOUTER_HXX__
+#define __LAYOUTER_HXX__
+
+#ifndef STGTY_REPEAT
+#define STGTY_REPEAT 100
+#endif
+
+#ifndef STG_TOEND
+#define STG_TOEND -1
+#endif
+
+#ifndef STG_S_FILEEMPTY
+#define STG_S_FILEEMPTY _HRESULT_TYPEDEF_(0x00030204L)
+#endif
+
+#define WIN32_SCODE(err) HRESULT_FROM_WIN32(err)
+#define LAST_STG_SCODE Win32ErrorToScode(GetLastError())
+
+#if DBG == 1
+DECLARE_DEBUG(lay);
+
+#define layDebugOut(x) layInlineDebugOut x
+#define layAssert(e) Win4Assert(e)
+#define layVerify(e) Win4Assert(e)
+
+
+#else
+
+#define layDebugOut(x)
+#define layAssert(e)
+#define layVerify(e) (e)
+
+#endif
+
+#define layErr(l, e) ErrJmp(lay, l, e, sc)
+#define layChkTo(l, e) if (FAILED(sc = (e))) layErr(l, sc) else 1
+#define layHChkTo(l, e) if (FAILED(sc = GetScode(e))) layErr(l, sc) else 1
+#define layChk(e) layChkTo(Err, e)
+#define layHChk(e) layHChkTo(Err, e)
+#define layMemTo(l, e) if ((e) == NULL) layErr(l, STG_E_INSUFFICIENTMEMORY) else 1
+#define layMem(e) layMemTo(Err, e)
+
+#define boolChk(e) \
+ if (!(e)) layErr(Err, LAST_STG_SCODE) else 1
+#define boolChkTo(l, e) \
+ if (!(e)) layErr(l, LAST_STG_SCODE) else 1
+#define negChk(e) \
+ if ((e) == 0xffffffff) layErr(Err, LAST_STG_SCODE) else 1
+#define negChkTo(l, e) \
+ if ((e) == 0xffffffff) layErr(l, LAST_STG_SCODE) else 1
+
+
+
+
+#endif // #ifndef __LAYOUTER_HXX__
diff --git a/private/ole32/stg/async/layout/layouthd.cxx b/private/ole32/stg/async/layout/layouthd.cxx
new file mode 100644
index 000000000..224994081
--- /dev/null
+++ b/private/ole32/stg/async/layout/layouthd.cxx
@@ -0,0 +1,48 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: layouthd.cxx
+//
+// Contents: Precompiled header for docfile layout
+//
+// History: 13-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+}
+
+#include <windows.h>
+#include <ole2.h>
+#include <error.hxx>
+#include <debnot.h>
+
+#include <msf.hxx>
+
+#include "layout.hxx"
+#include "layouter.hxx"
+#include "mapfile.hxx"
+
+
+
+#include "layout.hxx"
+#include "layouter.hxx"
+#include "mapfile.hxx"
+
+// we have to implement these ourselves
+#undef lstrcmpW
+#define lstrcmpW Laylstrcmp
+#undef lstrcpyW
+#define lstrcpyW Laylstrcpy
+#undef lstrcpynW
+#define lstrcpynW Laylstrcpyn
+#undef lstrlenW
+#define lstrlenW Laylstrlen
+#undef lstrcatW
+#define lstrcatW Laylstrcat
diff --git a/private/ole32/stg/async/layout/layouthd.hxx b/private/ole32/stg/async/layout/layouthd.hxx
new file mode 100644
index 000000000..b10009c75
--- /dev/null
+++ b/private/ole32/stg/async/layout/layouthd.hxx
@@ -0,0 +1,20 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: layouthd.hxx
+//
+// Contents: Theis is so both layout and layoutu can share the cruntime source code
+// Classes:
+//
+// Functions:
+//
+// History: 20-Jun-96 SusiA Share Cruntime functions
+//
+//----------------------------------------------------------------------------
+#ifndef __LAYOUTHD_HXX__
+#define __LAYOUTHD_HXX__
+#include "layouthd.cxx"
+
+#endif // #ifndef __LAYOUTHD_HXX__
diff --git a/private/ole32/stg/async/layout/layscrpt.cxx b/private/ole32/stg/async/layout/layscrpt.cxx
new file mode 100644
index 000000000..84e878213
--- /dev/null
+++ b/private/ole32/stg/async/layout/layscrpt.cxx
@@ -0,0 +1,657 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: layscrpt.cxx
+//
+// Contents: Code for the LayoutScript method
+//
+//
+// History: 22-Apr-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+#include "layouthd.cxx"
+#pragma hdrstop
+
+#include <dirfunc.hxx>
+#include "layout.hxx"
+#include "laylkb.hxx"
+#include "laywrap.hxx"
+
+#define NULL_TERM L'\0'
+#define BACKSLASH L'\\'
+#define MAX_BUFFER 0x10000
+
+//#define UNIT_TEST
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLayoutRootStorage::FreeStmList
+//
+// Synopsis: Free the stream linked list
+//
+// Arguments: [pStmList] -- Pointer STREAMLIST node
+//
+//----------------------------------------------------------------------------
+
+void CLayoutRootStorage::FreeStmList( STREAMLIST *pStmList)
+{
+ STREAMLIST *ptmp = pStmList;
+
+ while (pStmList)
+ {
+ ptmp = pStmList->pnext;
+
+#ifdef UNIT_TEST
+ wprintf(L"STGTY_STREAM %ls\n", pStmList->pwcsStmName );
+#endif
+ CoTaskMemFree(pStmList->pwcsStmName);
+ pStmList->pStm->Release();
+ delete pStmList;
+
+ pStmList = ptmp;
+
+ }
+
+
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLayoutRootStorage::FreeStgList
+//
+// Synopsis: Free the storage linked list
+//
+// Arguments: [pStgList] -- Pointer STORAGELIST node
+//
+//----------------------------------------------------------------------------
+
+void CLayoutRootStorage::FreeStgList( STORAGELIST *pStgList)
+{
+ STORAGELIST *ptmp;
+
+ while (pStgList)
+ {
+ ptmp = pStgList->pnext;
+#ifdef UNIT_TEST
+ wprintf(L"STGTY_STORAGE %ls\n", pStgList->pwcsStgName );
+#endif
+
+ CoTaskMemFree(pStgList->pwcsStgName);
+ pStgList->pStg->Release();
+ delete pStgList;
+
+ pStgList = ptmp;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLayoutRootStorage::ProcessOpen
+//
+// Synopsis: Open the storage or stream
+//
+// Arguments: [pwcsElementPathName] -- full "path" name of element to open
+// [dwType] STGTY_STORAGE or STGTY_STREAM
+// [ppIstgStm] interface pointer to the opened Storage or Stream
+// [cOffset] offset of beginning of the read
+//
+// Returns: Appropriate status code
+//
+// History: 22-Apr-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CLayoutRootStorage::ProcessOpen(OLECHAR *pwcsElementPathName,
+ DWORD dwType,
+ void **ppIStgStm,
+ LARGE_INTEGER cOffset)
+{
+ SCODE sc = S_OK;
+
+ IStorage *pStgNew;
+ IStream *pStmNew;
+
+ IStorage *pStg = this;
+
+ STORAGELIST *pStgList;
+ STREAMLIST *pStmList;
+
+ OLECHAR *pwcsStg = pwcsElementPathName,
+ *pwcsTemp = pwcsElementPathName;
+
+ OLECHAR *pwcsBuffer;
+
+ if ( (!pwcsElementPathName) || (pwcsElementPathName[0] == NULL_TERM))
+ {
+ return STG_E_PATHNOTFOUND;
+ }
+
+ // process storage path
+ while (1)
+ {
+ while ((*pwcsTemp) && (*pwcsTemp != BACKSLASH))
+ {
+ pwcsTemp++;
+ }
+
+ pwcsBuffer = (OLECHAR *) CoTaskMemAlloc
+ ((pwcsTemp - pwcsElementPathName + 1) *
+ sizeof(OLECHAR) );
+
+ if (!pwcsBuffer)
+ {
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ lstrcpynW (pwcsBuffer,
+ pwcsElementPathName,
+ (pwcsTemp - pwcsElementPathName + 1));
+
+ pwcsBuffer[pwcsTemp - pwcsElementPathName] = NULL_TERM;
+
+ if (!(*pwcsTemp))
+ {
+ //we are at the end, now handle leaf Storage or stream
+ break;
+ }
+
+ pStgList = _pStgList;
+
+ // see if this storage is already in the list
+ while (pStgList)
+ {
+ if (!(lstrcmpW(pwcsBuffer, pStgList->pwcsStgName )))
+ {
+ break;
+ }
+
+ pStgList = pStgList->pnext;
+ }
+ if (pStgList)
+ {
+ pStgNew = pStgList->pStg;
+ CoTaskMemFree(pwcsBuffer);
+ }
+ else
+ {
+ sc = pStg->OpenStorage(pwcsBuffer+(pwcsStg-pwcsElementPathName),
+ NULL,
+ STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0,
+ &pStgNew);
+ if (FAILED(sc))
+ {
+ CoTaskMemFree(pwcsBuffer);
+ return sc;
+ }
+
+ // add the storage to the list
+ pStgList = _pStgList;
+
+ if (NULL == (_pStgList = new STORAGELIST))
+ {
+ CoTaskMemFree(pwcsBuffer);
+ pStgNew->Release();
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ _pStgList->pwcsStgName = pwcsBuffer;
+ _pStgList->pStg = pStgNew;
+ _pStgList->pnext = pStgList;
+
+ }
+
+ pStg = pStgNew;
+ pwcsStg = ++pwcsTemp;
+
+ }
+
+ //process leaf storage
+ if (dwType == STGTY_STORAGE)
+ {
+ sc = pStg->OpenStorage(pwcsBuffer+(pwcsStg-pwcsElementPathName),
+ NULL,
+ STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0,
+ &pStgNew);
+ if (FAILED(sc))
+ {
+ CoTaskMemFree(pwcsBuffer);
+ return sc;
+ }
+
+ // add the storage to the list
+ pStgList = _pStgList;
+
+ if (NULL == (_pStgList = new STORAGELIST))
+ {
+ CoTaskMemFree(pwcsBuffer);
+ pStgNew->Release();
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ _pStgList->pwcsStgName = pwcsBuffer;
+ _pStgList->pStg = pStgNew;
+ _pStgList->pnext = pStgList;
+
+ *ppIStgStm = (void *) pStgNew;
+ }
+ //process leaf stream
+ else
+ {
+ sc = pStg->OpenStream(pwcsBuffer+(pwcsStg-pwcsElementPathName),
+ NULL,
+ STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
+ 0,
+ &pStmNew);
+
+ if (FAILED(sc))
+ {
+ CoTaskMemFree(pwcsBuffer);
+ return sc;
+ }
+
+ pStmList = _pStmList;
+
+ if (NULL == (_pStmList = new STREAMLIST))
+ {
+ CoTaskMemFree(pwcsBuffer);
+ pStmNew->Release();
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ _pStmList->pwcsStmName = pwcsBuffer;
+ _pStmList->pStm = pStmNew;
+ _pStmList->fDone = FALSE;
+ _pStmList->cOffset = cOffset;
+ _pStmList->pnext = pStmList;
+
+ *ppIStgStm = (void *) pStmNew;
+ }
+
+ return sc;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLayoutRootStorage::ProcessItem
+//
+// Synopsis: Construct an unprocessed script from an app provided script
+//
+// Arguments: [pLayoutItem] -- Pointer to a StorageLayout element of the array
+// [fStmDone] -- indicate whether the stream finished reading
+//
+// Returns: Appropriate status code
+//
+// History: 22-Apr-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CLayoutRootStorage::ProcessItem( StorageLayout *pLayoutItem, BOOL *fStmDone )
+{
+ SCODE sc = S_OK;
+
+ STREAMLIST *pStmList = _pStmList;
+ STORAGELIST *pStgList = _pStgList;
+ IStorage *pStgNew;
+ IStream *pStmNew;
+
+ ULARGE_INTEGER libNewPosition;
+ ULONG cbRead;
+
+ BYTE abBuffer[MAX_BUFFER];
+ BYTE *pb = abBuffer;
+ BOOL fBigBuffer = FALSE;
+
+ *fStmDone = FALSE;
+
+ if ((pLayoutItem->cOffset.QuadPart < 0) || (pLayoutItem->cBytes.QuadPart < 0))
+ {
+ return STG_E_INVALIDPARAMETER;
+ }
+
+ switch (pLayoutItem->LayoutType)
+ {
+
+ case STGTY_STORAGE:
+
+#ifdef UNIT_TEST
+ wprintf(L"STGTY_STORAGE %ls %lu%lu %lu%lu\n",
+ pLayoutItem->pwcsElementName,
+ pLayoutItem->cOffset.HighPart,
+ pLayoutItem->cOffset.LowPart,
+ pLayoutItem->cBytes.HighPart,
+ pLayoutItem->cBytes.LowPart);
+#endif
+
+ while (pStgList)
+ {
+ if (!(lstrcmpW(pLayoutItem->pwcsElementName,
+ pStgList->pwcsStgName )))
+ {
+ break;
+ }
+
+ pStgList = pStgList->pnext;
+ }
+
+ // if storage was not found in the list, open the storage
+ // and add it to the list
+ if (!pStgList)
+ {
+ sc = ProcessOpen(pLayoutItem->pwcsElementName,
+ STGTY_STORAGE,
+ (void **)&pStgNew,
+ pLayoutItem->cOffset);
+
+ if (FAILED(sc))
+ {
+ // the application may try to open Storages
+ // that do not really exist in the compound file,
+ // and we will let them try.
+ if (sc == STG_E_FILENOTFOUND)
+ {
+ return S_OK;
+ }
+ else
+ {
+ return sc;
+ }
+ }
+
+ }
+
+ break;
+
+ case STGTY_STREAM:
+
+#ifdef UNIT_TEST
+ wprintf(L"STGTY_STREAM %ls %lu%lu %lu%lu\n",
+ pLayoutItem->pwcsElementName,
+ pLayoutItem->cOffset.HighPart,
+ pLayoutItem->cOffset.LowPart,
+ pLayoutItem->cBytes.HighPart,
+ pLayoutItem->cBytes.LowPart);
+#endif
+
+ while (pStmList)
+ {
+ if (!(lstrcmpW(pLayoutItem->pwcsElementName,
+ pStmList->pwcsStmName )))
+ {
+ pStmNew = pStmList->pStm;
+ break;
+ }
+ pStmList = pStmList->pnext;
+ }
+
+ // if stream was not found in the list, open the stream,
+ // and add it to the list
+ if (pStmList)
+ {
+ if( pStmList->fDone )
+ {
+ *fStmDone = TRUE;
+ return S_OK;
+ }
+ }
+ else
+ {
+
+ sc = ProcessOpen(pLayoutItem->pwcsElementName,
+ STGTY_STREAM,
+ (void **)&pStmNew,
+ pLayoutItem->cOffset);
+
+ if (FAILED(sc))
+ {
+ // the application may try to open Streams
+ // that do not really exist in the compound file,
+ // and we will let them try.
+ if (sc == STG_E_FILENOTFOUND)
+ {
+ return S_OK;
+ }
+ else
+ {
+ return sc;
+ }
+ }
+
+ pStmList = _pStmList;
+
+ }
+
+ // seek to the correct position
+
+ sc = pStmNew->Seek(
+ pStmList->cOffset,
+ STREAM_SEEK_SET,
+ &libNewPosition );
+
+ if (FAILED(sc))
+ {
+ return sc;
+ }
+
+ // read the stream and update the script information
+
+ if (pLayoutItem->cBytes.LowPart > MAX_BUFFER)
+ {
+ if (NULL == (pb = (BYTE *) CoTaskMemAlloc(pLayoutItem->cBytes.LowPart)) )
+ {
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+ fBigBuffer = TRUE;
+ }
+ sc = pStmNew->Read(pb,
+ pLayoutItem->cBytes.LowPart,
+ &cbRead);
+
+ if (fBigBuffer)
+ {
+ CoTaskMemFree(pb);
+ fBigBuffer = FALSE;
+ pb = abBuffer;
+
+ }
+
+ if (FAILED(sc))
+ {
+ return sc;
+ }
+ //we have reached the end of the stream, mark it as done
+ if (cbRead < pLayoutItem->cBytes.LowPart)
+ {
+ pStmList->fDone = TRUE;
+ }
+
+ pStmList->cOffset.QuadPart += cbRead;
+
+ break;
+
+
+ default:
+ // we just handle storages and stream types
+ return STG_E_INVALIDPARAMETER;
+
+ }
+
+ return sc;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLayoutRootStorage::ProcessRepeatLoop
+//
+// Synopsis: Construct an unprocessed script from an app provided script
+//
+// Arguments: [pStorageLayout] -- Pointer to storage layout array
+// [nEntries] -- Number of entries in the array
+// [nRepeatStart] -- address of index of start of repeat loop
+//
+// Returns: Appropriate status code
+//
+// History: 22-Apr-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+SCODE CLayoutRootStorage::ProcessRepeatLoop( StorageLayout *pStorageLayout,
+ DWORD nEntries,
+ int * nRepeatStart)
+{
+ SCODE sc = S_OK;
+
+ int i,
+ nLoopCount = 0,
+ nLoopTimes;
+
+ BOOL fDone = FALSE,
+ fUntilDone;
+
+
+ // Are we going to repeat until all streams are read to the end?
+ if ((nLoopTimes = (LONG) pStorageLayout[*nRepeatStart].cBytes.LowPart) != STG_TOEND)
+ fUntilDone = FALSE;
+ else
+ {
+ fUntilDone = TRUE;
+ nLoopTimes = 1;
+ }
+ // finished when all streams are completely read, or we have
+ // looped through the specified amount of times
+ while ((!fDone)&&(nLoopCount < nLoopTimes))
+ {
+ if (!fUntilDone)
+ nLoopCount ++;
+
+ i = *nRepeatStart;
+ fDone = TRUE;
+
+ // STGTY_REPEAT with 0 bytes indicates the end of this repeat block
+ while (!((pStorageLayout[++i].LayoutType == STGTY_REPEAT ) &&
+ (pStorageLayout[i].cBytes.QuadPart == 0)) )
+ {
+ if (i >= (LONG) nEntries)
+ {
+ return E_INVALIDARG;
+ }
+
+ // beginning of another repeat block
+ if (pStorageLayout[i].LayoutType == STGTY_REPEAT )
+ {
+ if ((pStorageLayout[i].pwcsElementName !=NULL) ||
+ (pStorageLayout[i].cOffset.QuadPart < 0) ||
+ (pStorageLayout[i].cBytes.QuadPart < 0) )
+ {
+ return STG_E_INVALIDPARAMETER;
+ }
+ layChk(ProcessRepeatLoop(pStorageLayout,
+ nEntries,
+ &i));
+ }
+
+ else
+ {
+ layChk(ProcessItem(&(pStorageLayout[i]), &fDone));
+
+ }
+ }
+ }
+ *nRepeatStart = i;
+
+Err:
+
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: CLayoutRootStorage::ProcessLayout
+//
+// Synopsis: Construct an unprocessed script from an app provided script
+//
+// Arguments: [pStorageLayout] -- Pointer to storage layout array
+// [nEntries] -- Number of entries in the array
+// [grfInterleavedFlag] -- Specifies disposition of control
+// structures
+//
+// Returns: Appropriate status code
+//
+// History: 22-Apr-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+
+SCODE CLayoutRootStorage::ProcessLayout( StorageLayout *pStorageLayout,
+ DWORD nEntries,
+ DWORD glfInterleavedFlag)
+{
+
+ SCODE sc = S_OK;
+ int i;
+ BOOL fUnused;
+
+
+ TCHAR *patcScriptName = _pllkb->GetScriptName();
+
+
+ for (i = 0; i < (LONG) nEntries; i++)
+ {
+
+ if (pStorageLayout[i].LayoutType == STGTY_REPEAT )
+ {
+
+ if (pStorageLayout[i].cBytes.QuadPart != 0)
+ {
+ if ((pStorageLayout[i].pwcsElementName !=NULL) ||
+ (pStorageLayout[i].cOffset.QuadPart < 0) ||
+ (pStorageLayout[i].cBytes.QuadPart < 0) )
+ {
+ return STG_E_INVALIDPARAMETER;
+ }
+ layChk(ProcessRepeatLoop(pStorageLayout,
+ nEntries,
+ &i));
+ }
+ else //end repeat block with no matching beginning
+ {
+ sc = E_INVALIDARG;
+ layChk(sc);
+
+ }
+
+
+ }
+ else // (pStorageLayout[i].LayoutType == STGTY_REPEAT )
+ {
+ layChk(ProcessItem(&(pStorageLayout[i]), &fUnused));
+ }
+ }
+
+
+
+
+Err:
+ if (_pStgList)
+ {
+ FreeStgList(_pStgList);
+ _pStgList = NULL;
+ }
+ if (_pStmList)
+ {
+ FreeStmList(_pStmList);
+ _pStmList = NULL;
+ }
+ return sc;
+
+}
diff --git a/private/ole32/stg/async/layout/laywrap.cxx b/private/ole32/stg/async/layout/laywrap.cxx
new file mode 100644
index 000000000..84388c6a8
--- /dev/null
+++ b/private/ole32/stg/async/layout/laywrap.cxx
@@ -0,0 +1,540 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: laywrap.cxx
+//
+// Contents: IStorage wrapper for layout docfile
+//
+// Classes:
+//
+// Functions:
+//
+// History: 14-Feb-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+#include "layouthd.cxx"
+#pragma hdrstop
+
+#include "laywrap.hxx"
+#include "layouter.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::QueryInterface, public
+//
+// History: 14-Feb-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc = S_OK;
+ *ppvObj = NULL;
+
+ layDebugOut((DEB_ITRACE,
+ "In CLayoutRootStorage::QueryInterface:%p()\n", this));
+
+ if (IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IStorage *)this;
+ }
+ else if (IsEqualIID(iid, IID_IStorage))
+ {
+ *ppvObj = (IStorage *)this;
+ }
+ else if (IsEqualIID(iid, IID_IRootStorage))
+ {
+ IRootStorage *prstg;
+ if (FAILED(_pRealStg->QueryInterface(IID_IRootStorage,
+ (void **) &prstg)))
+ {
+ return E_NOINTERFACE;
+ }
+
+ prstg->Release();
+
+ *ppvObj = (IRootStorage *)this;
+ }
+ else if (IsEqualIID(iid, IID_ILayoutStorage))
+ {
+ *ppvObj = (ILayoutStorage *)this;
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ AddRef();
+ }
+ layDebugOut((DEB_ITRACE,
+ "Out CLayoutRootStorage::QueryInterface:%p()\n", this));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::AddRef, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CLayoutRootStorage::AddRef(void)
+{
+ ULONG ulRet;
+ layDebugOut((DEB_ITRACE, "In CLayoutRootStorage::AddRef:%p()\n", this));
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+ layDebugOut((DEB_ITRACE, "Out CLayoutRootStorage::AddRef\n"));
+ return ulRet;
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::Release, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CLayoutRootStorage::Release(void)
+{
+ LONG lRet;
+ layDebugOut((DEB_ITRACE, "In CLayoutRootStorage::Release:%p()\n", this));
+
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ lRet = 0;
+ layDebugOut((DEB_ITRACE, "Out CLayoutRootStorage::Release\n"));
+ return (ULONG)lRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::CreateStream, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::CreateStream(OLECHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+
+ layDebugOut((DEB_ITRACE,
+ "In CLayoutRootStorage::CreateStream:%p()\n", this));
+
+ sc = _pRealStg->CreateStream(pwcsName,
+ grfMode,
+ reserved1,
+ reserved2,
+ ppstm);
+
+
+ layDebugOut((DEB_ITRACE,
+ "Out CLayoutRootStorage::CreateStream:%p()\n", this));
+
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::OpenStream, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::OpenStream(OLECHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc = S_OK;
+
+ layDebugOut((DEB_ITRACE,
+ "In CLayoutRootStorage::OpenStream:%p()\n", this));
+
+ sc = _pRealStg->OpenStream(pwcsName,
+ reserved1,
+ grfMode,
+ reserved2,
+ ppstm);
+
+ layDebugOut((DEB_ITRACE,
+ "Out CLayoutRootStorage::OpenStream:%p()\n", this));
+
+ return ResultFromScode(sc);
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::CreateStorage, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::CreateStorage(OLECHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ LPSTGSECURITY reserved2,
+ IStorage **ppstg)
+{
+ SCODE sc = S_OK;
+
+ layDebugOut((DEB_ITRACE,
+ "In CLayoutRootStorage::CreateStorage:%p()\n", this));
+
+ sc = _pRealStg->CreateStorage( pwcsName,
+ grfMode,
+ reserved1,
+ reserved2,
+ ppstg);
+
+ layDebugOut((DEB_ITRACE,
+ "Out CLayoutRootStorage::CreateStorage:%p()\n", this));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::OpenStorage, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::OpenStorage(OLECHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+{
+ SCODE sc = S_OK;
+
+ layDebugOut((DEB_ITRACE,
+ "In CLayoutRootStorage::OpenStorage:%p()\n", this));
+
+ sc = _pRealStg->OpenStorage(pwcsName,
+ pstgPriority,
+ grfMode,
+ snbExclude,
+ reserved,
+ ppstg);
+
+ layDebugOut((DEB_ITRACE,
+ "Out CLayoutRootStorage::OpenStorage:%p()\n", this));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::CopyTo, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::CopyTo(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest)
+{
+ SCODE sc = S_OK;
+
+ layDebugOut((DEB_ITRACE, "In CLayoutRootStorage::CopyTo%p()\n", this));
+
+ sc = _pRealStg->CopyTo(ciidExclude,
+ rgiidExclude,
+ snbExclude,
+ pstgDest);
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutRootStorage::CopyTo\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::MoveElementTo, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::MoveElementTo(OLECHAR const *lpszName,
+ IStorage *pstgDest,
+ OLECHAR const *lpszNewName,
+ DWORD grfFlags)
+{
+ SCODE sc = S_OK;
+
+ layDebugOut((DEB_ITRACE,
+ "In CLayoutRootStorage::MoveElementTo%p()\n", this));
+
+ sc = _pRealStg->MoveElementTo(lpszName,
+ pstgDest,
+ lpszNewName,
+ grfFlags) ;
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutRootStorage::MoveElementTo\n"));
+
+ return ResultFromScode(sc);
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::Commit, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::Commit(DWORD grfCommitFlags)
+{
+ SCODE sc = S_OK;
+
+ layDebugOut((DEB_ITRACE, "In CLayoutRootStorage::Commit%p()\n", this));
+
+ sc = _pRealStg->Commit(grfCommitFlags);
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutRootStorage::Commit\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::Revert, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::Revert(void)
+{
+ SCODE sc = S_OK;
+
+ layDebugOut((DEB_ITRACE, "In CLayoutRootStorage::Revert%p()\n", this));
+
+ sc = _pRealStg->Revert();
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutRootStorage::Revert\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::EnumElements, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::EnumElements(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm)
+{
+ SCODE sc = S_OK;
+
+ layDebugOut((DEB_ITRACE,
+ "In CLayoutRootStorage::EnumElements%p()\n", this));
+
+ sc = _pRealStg->EnumElements(reserved1,
+ reserved2,
+ reserved3,
+ ppenm);
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutRootStorage::EnumElements\n"));
+
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::DestroyElement, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::DestroyElement(OLECHAR const *pwcsName)
+{
+ SCODE sc = S_OK;
+
+ layDebugOut((DEB_ITRACE, "In CLayoutRootStorage::DestroyElement\n"));
+
+ sc = _pRealStg->DestroyElement(pwcsName);
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutRootStorage::DestroyElement\n"));
+
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::RenameElement, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::RenameElement(OLECHAR const *pwcsOldName,
+ OLECHAR const *pwcsNewName)
+{
+ SCODE sc = S_OK;
+
+ sc = _pRealStg->RenameElement(pwcsOldName, pwcsNewName);
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutRootStorage::RenameElement\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::SetElementTimes, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::SetElementTimes(const OLECHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ SCODE sc = S_OK;
+ layDebugOut((DEB_ITRACE, "In CLayoutRootStorage::SetElementTimes\n"));
+
+ sc = _pRealStg->SetElementTimes(lpszName,
+ pctime,
+ patime,
+ pmtime);
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutRootStorage::SetElementTimes\n"));
+
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::SetClass, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::SetClass(REFCLSID clsid)
+{
+ SCODE sc = S_OK;
+ layDebugOut((DEB_ITRACE, "In CLayoutRootStorage::SetClass\n"));
+
+ sc = _pRealStg->SetClass(clsid);
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutRootStorage::SetClass\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::SetStateBits, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::SetStateBits(DWORD grfStateBits,
+ DWORD grfMask)
+{
+ SCODE sc = S_OK;
+ layDebugOut((DEB_ITRACE, "In CLayoutRootStorage::SetStateBits\n"));
+
+ sc = _pRealStg->SetStateBits(grfStateBits, grfMask);
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutRootStorage::SetStateBits\n"));
+
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::Stat, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc = S_OK;
+
+ layDebugOut((DEB_ITRACE, "In CLayoutRootStorage::Stat%p()\n", this));
+
+ sc = _pRealStg->Stat( pstatstg, grfStatFlag);
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutRootStorage::Stat\n"));
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutRootStorage::SwitchToFile, public
+//
+// History: 01-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CLayoutRootStorage::SwitchToFile(OLECHAR *ptcsFile)
+{
+ SCODE sc = S_OK;
+ IRootStorage *prstg;
+
+ layDebugOut((DEB_ITRACE, "In CLayoutRootStorage::%p()\n", this));
+
+ layVerify(SUCCEEDED(_pRealStg->QueryInterface(IID_IRootStorage,
+ (void **) &prstg)));
+
+ sc = prstg->SwitchToFile(ptcsFile);
+
+ prstg->Release();
+
+ layDebugOut((DEB_ITRACE, "Out CLayoutRootStorage::\n"));
+ return ResultFromScode(sc);
+}
+
diff --git a/private/ole32/stg/async/layout/laywrap.hxx b/private/ole32/stg/async/layout/laywrap.hxx
new file mode 100644
index 000000000..b5a8ad0ba
--- /dev/null
+++ b/private/ole32/stg/async/layout/laywrap.hxx
@@ -0,0 +1,236 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: laywrap.hxx
+//
+// Contents: RootStorage wrapper for Layout docfile
+//
+// Classes: CLayoutRootStorage
+//
+// Functions:
+//
+// History: 13-Feb-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __LAYWRAP_HXX__
+#define __LAYWRAP_HXX__
+
+#include "laylkb.hxx"
+
+typedef struct tagSTORAGELIST
+{
+ OLECHAR *pwcsStgName;
+ IStorage *pStg;
+ struct tagSTORAGELIST *pnext;
+} STORAGELIST;
+
+typedef struct tagSTREAMLIST
+{
+ OLECHAR *pwcsStmName;
+ IStream *pStm;
+ BOOL fDone;
+ LARGE_INTEGER cOffset;
+ struct tagSTREAMLIST *pnext;
+} STREAMLIST;
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CLayoutRootStorage
+//
+// Purpose: Wrap root storage objects for Layout Docfiles
+//
+// Interface:
+//
+// History: 28-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+class CLayoutRootStorage:
+ public IStorage,
+ public IRootStorage,
+ public ILayoutStorage
+{
+public:
+ inline CLayoutRootStorage(IStorage *pstg, CLayoutLockBytes *pllkb);
+ inline ~CLayoutRootStorage(void);
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+ // IStorage
+ STDMETHOD(CreateStream)(OLECHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(OpenStream)(OLECHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(CreateStorage)(OLECHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ LPSTGSECURITY reserved2,
+ IStorage **ppstg);
+ STDMETHOD(OpenStorage)(OLECHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg);
+ STDMETHOD(CopyTo)(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest);
+ STDMETHOD(MoveElementTo)(OLECHAR const *lpszName,
+ IStorage *pstgDest,
+ OLECHAR const *lpszNewName,
+ DWORD grfFlags);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(EnumElements)(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm);
+ STDMETHOD(DestroyElement)(OLECHAR const *pwcsName);
+ STDMETHOD(RenameElement)(OLECHAR const *pwcsOldName,
+ OLECHAR const *pwcsNewName);
+ STDMETHOD(SetElementTimes)(const OLECHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+ STDMETHOD(SetClass)(REFCLSID clsid);
+ STDMETHOD(SetStateBits)(DWORD grfStateBits, DWORD grfMask);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+ // IRootStorage
+ STDMETHOD(SwitchToFile)(OLECHAR *ptcsFile);
+
+ //ILayoutStorage
+ STDMETHOD (LayoutScript)( StorageLayout *pStorageLayout,
+ DWORD nEntries,
+ DWORD glfInterleavedFlag);
+
+ STDMETHOD (BeginMonitor)(void);
+
+ STDMETHOD (EndMonitor)(void);
+
+ STDMETHOD (ReLayoutDocfile)(OLECHAR *pwcsNewDfName);
+
+ STDMETHOD (ReLayoutDocfileOnILockBytes)(ILockBytes *pILockBytes);
+
+#if (DBG==1)
+ STDMETHOD (GetScript)(TCHAR **pwcsScriptFileName);
+#endif
+
+private:
+ SCODE ProcessItem( StorageLayout *pLayoutItem, BOOL *fStmDone );
+
+ SCODE ProcessRepeatLoop( StorageLayout *pStorageLayout,
+ DWORD nEntries,
+ int * nRepeatStart);
+
+ SCODE ProcessLayout( StorageLayout *pStorageLayout,
+ DWORD nEntries,
+ DWORD glfInterleavedFlag);
+
+ SCODE ProcessOpen(OLECHAR *pwcsElementPathName,
+ DWORD dwType,
+ void **ppIStgStm,
+ LARGE_INTEGER cOffset);
+
+ void FreeStmList( STREAMLIST *pStmList);
+
+ void FreeStgList( STORAGELIST *pStgList);
+
+
+ LONG _cReferences;
+ IStorage *_pRealStg;
+ CLayoutLockBytes *_pllkb;
+
+ STORAGELIST *_pStgList;
+ STREAMLIST *_pStmList;
+
+};
+
+inline CLayoutRootStorage::CLayoutRootStorage(IStorage *pstg,
+ CLayoutLockBytes *pllkb)
+{
+ _cReferences = 1;
+ _pRealStg = pstg;
+ _pRealStg->AddRef();
+ _pllkb = pllkb;
+ _pllkb->AddRef();
+ _pStmList = NULL;
+ _pStgList = NULL;
+
+}
+
+inline CLayoutRootStorage::~CLayoutRootStorage(void)
+{
+ if (_pRealStg != NULL)
+ _pRealStg->Release();
+
+ if (_pllkb != NULL)
+ _pllkb->Release();
+
+ if (_pStmList != NULL)
+ FreeStmList(_pStmList);
+
+ if (_pStgList != NULL)
+ FreeStgList(_pStgList);
+
+}
+
+
+SCODE StgLayoutDocfile(HANDLE hOld,
+ OLECHAR const *pwcsNewDfName,
+ OLECHAR const *pwcsScriptName);
+
+
+SCODE ProcessControl(SECT *psProcessed,
+ void *pvOld,
+ ULONG *pcsectControl);
+
+SCODE ProcessScript(SECT *psProcessed,
+ SECT *psOriginal,
+ ULONG csectFile,
+ ULONG csectOriginal,
+ ULONG csectControl,
+ ULONG *pcsectProcessed);
+
+SCODE CopyData(void *pvNew,
+ void *pvOld,
+ SECT *psScript,
+ ULONG cSectFile,
+ ULONG cbSectorSize);
+
+SCODE RemapHeader(void *pvNew,
+ SECT *pScript,
+ ULONG csectFile);
+
+SCODE RemapDIF(void *pvNew,
+ SECT *pScript,
+ ULONG csectFile,
+ ULONG cbSectorSize);
+
+SCODE RemapFat(void *pvNew,
+ void *pvOld,
+ SECT *pScript,
+ ULONG csectFile,
+ ULONG cbSectorSize);
+
+SCODE RemapDirectory(void *pvNew,
+ SECT *pScript,
+ ULONG csectFile,
+ ULONG cbSectorSize);
+
+#endif // #ifndef __LAYWRAP_HXX__
diff --git a/private/ole32/stg/async/layout/makefile b/private/ole32/stg/async/layout/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/async/layout/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/async/layout/mapfile.cxx b/private/ole32/stg/async/layout/mapfile.cxx
new file mode 100644
index 000000000..4bcc2c6d8
--- /dev/null
+++ b/private/ole32/stg/async/layout/mapfile.cxx
@@ -0,0 +1,229 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: mapfile.cxx
+//
+// Contents: Mapped file class implementation
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "layouthd.cxx"
+#pragma hdrstop
+
+
+CMappedFile::~CMappedFile(void)
+{
+ if (_pbBase != NULL)
+ {
+ UnmapViewOfFile(_pbBase);
+ }
+ if (_hMapping != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(_hMapping);
+ }
+ if (_hFile != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(_hFile);
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMappedFile::InitFromHandle, public
+//
+// Synopsis: Initialize object based on file handle
+//
+// Arguments: [h] -- File handle
+// [fReadOnly] -- TRUE if mapping is to be read-only
+// [fDuplicate] -- TRUE if handle is to be duplicated
+// [pvDesiredBaseAddress] -- Desired address for mapping
+//
+// Returns: Appropriate status code
+//
+// History: 13-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CMappedFile::InitFromHandle(HANDLE h,
+ BOOL fReadOnly,
+ BOOL fDuplicate,
+ void *pvDesiredBaseAddress)
+{
+ SCODE sc = S_OK;
+
+ if (fDuplicate)
+ {
+ if (!DuplicateHandle(GetCurrentProcess(),
+ h,
+ GetCurrentProcess(),
+ &_hFile,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS))
+ {
+ layErr(Err, Win32ErrorToScode(GetLastError()));
+ }
+ }
+ else
+ {
+ _hFile = h;
+ }
+#ifndef UNICODE
+ _hMapping = CreateFileMappingA
+#else
+ _hMapping = CreateFileMapping
+#endif
+ (_hFile,
+ NULL, // No security
+ (fReadOnly) ? PAGE_READONLY : PAGE_READWRITE,
+ 0,
+ 0, //File size determines map size
+ NULL); // Unnamed
+
+ if (_hMapping == NULL)
+ {
+ layErr(Err, Win32ErrorToScode(GetLastError()));
+ }
+
+ //Mapping created OK, now map view
+ _pbBase = MapViewOfFileEx(_hMapping,
+ (fReadOnly) ? FILE_MAP_READ : FILE_MAP_WRITE,
+ 0,
+ 0,
+ 0,
+ pvDesiredBaseAddress);
+ if (_pbBase == NULL)
+ {
+ layErr(Err, Win32ErrorToScode(GetLastError()));
+ }
+
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMappedFile::Init, public
+//
+// Synopsis: Initialize based on a filename
+//
+// Arguments: [pwcsName] -- Filename for file
+// [dwSize] -- Desired size of file, 0 for no size change
+// [dwAccess] -- Access mode for file (see CreateFile)
+// [dwCreationDisposition] -- Creation for file (see CreateFile)
+// [pvDesiredBaseAddress] -- Desired base address for mapping
+//
+// Returns: Appropriate status code
+//
+// History: 13-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CMappedFile::Init(WCHAR const *pwcsName,
+ DWORD dwSize,
+ DWORD dwAccess,
+ DWORD dwCreationDisposition,
+ void *pvDesiredBaseAddress)
+{
+ SCODE sc;
+ BOOL fReadOnly = ((dwAccess & GENERIC_WRITE) == 0);
+
+ layAssert(!fReadOnly || (dwSize == 0));
+ if (pwcsName == NULL)
+ return STG_E_INVALIDNAME;
+
+#ifndef UNICODE
+ TCHAR atcPath[MAX_PATH + 1];
+ UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ if (!WideCharToMultiByte(
+ uCodePage,
+ 0,
+ pwcsName,
+ -1,
+ atcPath,
+ MAX_PATH + 1,
+ NULL,
+ NULL))
+ {
+ return STG_E_INVALIDNAME;
+ }
+
+ _hFile = CreateFileA(atcPath,
+ dwAccess,
+ 0, //No sharing
+ NULL, //No security
+ dwCreationDisposition,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL); // No template file
+#else
+ _hFile = CreateFile(pwcsName,
+ dwAccess,
+ 0, //No sharing
+ NULL, //No security
+ dwCreationDisposition,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL); // No template file
+#endif
+
+
+
+ if (_hFile == INVALID_HANDLE_VALUE)
+ {
+ layErr(Err, Win32ErrorToScode(GetLastError()));
+ }
+
+ if (dwSize != 0)
+ {
+ DWORD dw = SetFilePointer(_hFile,
+ dwSize,
+ NULL,
+ FILE_BEGIN);
+ if (dw == 0xFFFFFFFF)
+ {
+ layErr(Err, Win32ErrorToScode(GetLastError()));
+ }
+
+ if (!SetEndOfFile(_hFile))
+ {
+ layErr(Err, Win32ErrorToScode(GetLastError()));
+ }
+ }
+ else
+ {
+ DWORD dwFileSize;
+
+ dwFileSize = GetFileSize(_hFile, NULL);
+
+ if (dwFileSize == 0xFFFFFFFF)
+ {
+ layErr(Err, Win32ErrorToScode(GetLastError()));
+ }
+
+ if ( dwFileSize == 0 )
+ {
+ return STG_S_FILEEMPTY;
+ }
+
+ }
+ layChk(InitFromHandle(_hFile, fReadOnly, FALSE, pvDesiredBaseAddress));
+
+Err:
+ return sc;
+}
+
+
+
+
+
+
diff --git a/private/ole32/stg/async/layout/mapfile.hxx b/private/ole32/stg/async/layout/mapfile.hxx
new file mode 100644
index 000000000..058c5a237
--- /dev/null
+++ b/private/ole32/stg/async/layout/mapfile.hxx
@@ -0,0 +1,78 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: mapfile.hxx
+//
+// Contents: Mapped File class definition
+//
+// Classes:
+//
+// Functions:
+//
+// History: 12-Feb-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __MAPFILE_HXX__
+#define __MAPFILE_HXX__
+
+//+---------------------------------------------------------------------------
+//
+// Class: CMappedFile
+//
+// Purpose: Provides a wrapper over a file mapping
+//
+// Interface:
+//
+// History: 12-Feb-96 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+class CMappedFile
+{
+public:
+ inline CMappedFile();
+ ~CMappedFile();
+
+ SCODE Init(WCHAR const *pwcsFileName,
+ DWORD dwSize,
+ DWORD dwAccess,
+ DWORD dwCreationDisposition,
+ void *pbDesiredBaseAddress);
+ SCODE InitFromHandle(HANDLE h,
+ BOOL fReadOnly,
+ BOOL fDuplicate,
+ void *pbDesiredBaseAddress);
+
+ inline void * GetBaseAddress(void);
+ inline ULONG GetSize(void);
+
+private:
+ HANDLE _hFile;
+ HANDLE _hMapping;
+ void *_pbBase;
+};
+
+
+inline CMappedFile::CMappedFile(void)
+{
+ _hFile = _hMapping = INVALID_HANDLE_VALUE;
+ _pbBase = NULL;
+}
+
+inline void * CMappedFile::GetBaseAddress(void)
+{
+ return _pbBase;
+}
+
+inline ULONG CMappedFile::GetSize(void)
+{
+ layAssert(_hFile != INVALID_HANDLE_VALUE);
+ return GetFileSize(_hFile, NULL);
+}
+
+#endif // #ifndef __MAPFILE_HXX__
diff --git a/private/ole32/stg/async/layout/sources b/private/ole32/stg/async/layout/sources
new file mode 100644
index 000000000..c7024a9da
--- /dev/null
+++ b/private/ole32/stg/async/layout/sources
@@ -0,0 +1,113 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Philip Lafornara (PhilipLa) 19-Dec-1995
+
+!ENDIF
+
+
+MAJORCOMP = dflayout
+MINORCOMP = dflayout
+
+
+#BLDCRT= 1
+USE_LIBCMT=1
+
+
+MSC_WARNING_LEVEL=/W3 /WX /Oi
+
+NTLEGO=1
+
+GPCH_BUILD=daytona
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= dflayout
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= $(BASEDIR)\public\sdk\lib
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= DYNLINK
+
+DLLDEF= obj\$(TARGET_DIRECTORY)\layout.def
+
+DLLENTRY= _DllMainCRTStartup
+
+DLLBASE= @$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,usermode
+
+INCLUDES= ..\h;..\..\h;..\..\..\ih
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DNOEXCEPTIONS \
+ -DINC_OLE2 \
+ -DFLAT \
+ -DWIN32=100 \
+ -D_NT1X_=100 \
+ -DCAIROLE_DOWNLEVEL \
+ -D_TRACKLINK_=1 \
+ -D_OLE32_ \
+ $(TRACELOG)
+
+
+
+PRECOMPILED_INCLUDE=
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
+
+SOURCES= \
+ layapi.cxx \
+ layout.cxx \
+ mapfile.cxx \
+ layouter.cxx \
+ laylkb.cxx \
+ laywrap.cxx \
+ layscrpt.cxx \
+ ..\cruntime.cxx \
+ layout.rc
+
+UMTYPE= console
+UMTEST=
+
+TARGETLIBS= \
+ ..\debug\daytona\obj\*\debug.lib \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib
+
+#NTTARGETFILE0=allidl
+
+!include sources.inc
diff --git a/private/ole32/stg/async/layout/sources.inc b/private/ole32/stg/async/layout/sources.inc
new file mode 100644
index 000000000..9a091ed81
--- /dev/null
+++ b/private/ole32/stg/async/layout/sources.inc
@@ -0,0 +1 @@
+SYNCHRONIZE_DRAIN=1
diff --git a/private/ole32/stg/async/layout/test/daytona/makefile b/private/ole32/stg/async/layout/test/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/async/layout/test/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/async/layout/test/daytona/sources b/private/ole32/stg/async/layout/test/daytona/sources
new file mode 100644
index 000000000..d7087c5cf
--- /dev/null
+++ b/private/ole32/stg/async/layout/test/daytona/sources
@@ -0,0 +1,48 @@
+!IF 0
+
+Copyright (c) 1995 Microsoft Corporation
+
+!ENDIF
+
+MAJORCOMP= ole32
+MINORCOMP= stg
+TARGETNAME= laytest
+TARGETPATH= obj
+TARGETTYPE= PROGRAM
+
+INCLUDES=.;..;..\..;..\..\..\h
+
+BLDCRT= 1
+USE_CRTDLL= 1
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DFLAT \
+ -DUNICODE \
+ -D_UNICODE
+
+PRECOMPILED_INCLUDE= ..\pch.cxx
+
+
+SOURCES= \
+ ..\laytest.cxx\
+ ..\tutils.cxx
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+
+
+LINKLIBS= $(BASEDIR)\public\sdk\lib\*\dflayout.lib \
+ ..\..\..\debug\daytona\obj\*\debug.lib \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib
+
+
+
+
diff --git a/private/ole32/stg/async/layout/test/dirs b/private/ole32/stg/async/layout/test/dirs
new file mode 100644
index 000000000..e9c1f6749
--- /dev/null
+++ b/private/ole32/stg/async/layout/test/dirs
@@ -0,0 +1,22 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+DIRS=
+OPTIONAL_DIRS= daytona
diff --git a/private/ole32/stg/async/layout/test/laytest.cxx b/private/ole32/stg/async/layout/test/laytest.cxx
new file mode 100644
index 000000000..c4fe15126
--- /dev/null
+++ b/private/ole32/stg/async/layout/test/laytest.cxx
@@ -0,0 +1,282 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: laytest.cxx
+//
+// History: 15-May-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+#include "scripts.hxx"
+
+
+HRESULT StgLayoutDocfile(HANDLE hOld,
+ OLECHAR const *pwcsNewName,
+ OLECHAR const *pwcsScriptName);
+
+typedef ULONG SECT;
+
+
+#define FailMsg(MSG) {printf MSG; exit(1);}
+
+#define DoCmd(MSG, CODE, FAILMSG) \
+printf(MSG " => %s (0x%lX)\n", (sc = ResultFromScode(CODE), ScText(sc)), sc); \
+if (FAILED(sc)) {printf(FAILMSG "\n");}
+
+#define SHIFT(c,v) ( (c)--, (v)++)
+
+#include <assert.h>
+
+void BeginTest(void)
+{
+ HRESULT hr;
+
+ hr = CoInitialize(NULL);
+ Result(hr, "CoInitialize");
+}
+
+
+void EndTest(int rc)
+{
+ if (rc == 0)
+ printf("Test SUCCEEDED\n");
+ else
+ printf("Test FAILED\n");
+ CoUninitialize();
+ exit(rc);
+}
+
+void PrintStat(STATSTG *pstat, BOOL fEnum)
+{
+ printf("%s: '%ws'\n", pstat->type == STGTY_STORAGE ? "Storage" : "Stream",
+ pstat->pwcsName);
+ //printf("Type: %lu, %lu\n", pstat->type, pstat->dwStgFmt);
+ printf("Type: %lu, %lu\n", pstat->type);
+ if (!fEnum)
+ printf("Mode: %lX\n", pstat->grfMode);
+ if (pstat->type == STGTY_STREAM)
+ {
+ printf("Size: %lu:%lu\n", pstat->cbSize.HighPart,
+ pstat->cbSize.LowPart);
+ if (!fEnum)
+ printf("Locks: %lX\n", pstat->grfLocksSupported);
+ }
+ else
+ {
+ if (pstat->ctime.dwHighDateTime != 0 ||
+ pstat->ctime.dwLowDateTime != 0)
+ printf("Ctime: %s\n", FileTimeText(&pstat->ctime));
+ if (pstat->mtime.dwHighDateTime != 0 ||
+ pstat->mtime.dwLowDateTime != 0)
+ printf("Mtime: %s\n", FileTimeText(&pstat->mtime));
+ if (pstat->atime.dwHighDateTime != 0 ||
+ pstat->atime.dwLowDateTime != 0)
+ printf("Atime: %s\n", FileTimeText(&pstat->atime));
+ }
+ if (!fEnum)
+ printf("Clsid: %s\n", GuidText(&pstat->clsid));
+}
+void PrintStatInfo(STATSTG *pstat)
+{
+ PrintStat(pstat, TRUE);
+}
+
+#define OLDFILENAME L"StartDocfile.Doc"
+#define NEWFILENAME L"d:\\scratch\\NewD.doc"
+#define SCRIPTFILENAME L"Script"
+
+void t_layout(void)
+{
+ SCODE sc;
+ SECT *psect;
+ ULONG csect;
+ IStorage *pstgRoot;
+ IStream *pstm;
+ BYTE buffer[4096];
+
+ IStorage *pstgOld, *pstgNew;
+
+ HANDLE hFile = CreateFileW(OLDFILENAME,
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ sc = StgCreateDocfile(OLDFILENAME,
+ STGM_CREATE | STGM_DIRECT |
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0,
+ &pstgRoot);
+ Result(sc, "Create start docfile.");
+ sc = pstgRoot->Commit(STGC_DEFAULT);
+ Result(sc, "Commit start docfile.");
+
+ sc = pstgRoot->CreateStream(L"Foo",
+ STGM_DIRECT | STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE,
+ 0,
+ 0,
+ &pstm);
+ Result(sc, "CreateStream");
+ memset(buffer, 'P', 4096);
+ sc = pstm->Write(buffer, 4096, NULL);
+ Result(sc, "Write");
+ pstm->Release();
+ pstgRoot->Release();
+ csect = 9;
+ }
+ else
+ {
+ ULONG ulSize = GetFileSize(hFile, NULL);
+ //BUGBUG: Assumes sector size is 512
+ csect = ulSize / 512 - 2;
+ printf("Old file detected with %lu sectors\n", csect);
+ CloseHandle(hFile);
+ }
+
+
+ HANDLE hScript;
+ hScript = CreateFileW(SCRIPTFILENAME,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hScript == INVALID_HANDLE_VALUE)
+ {
+ Fail("CreateFile failed with %lu\n", GetLastError());
+ }
+
+ psect = new SECT[1];
+ psect[0] = csect;
+
+ DWORD dwBytesWritten;
+
+ if (!WriteFile(hScript,
+ psect,
+ 1 * sizeof(SECT),
+ &dwBytesWritten,
+ NULL))
+ {
+ Fail("WriteFile failed with %lu\n", GetLastError());
+ }
+ delete psect;
+ CloseHandle(hScript);
+
+ hFile = CreateFileW(OLDFILENAME,
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ sc = StgLayoutDocfile(hFile, NEWFILENAME, SCRIPTFILENAME);
+ Result(sc, "StgLayoutDocfile");
+
+ CloseHandle(hFile);
+
+ sc = StgOpenStorage(NEWFILENAME,
+ NULL,
+ STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0,
+ &pstgNew);
+ Result(sc, "Open new file");
+
+ sc = StgOpenStorage(OLDFILENAME,
+ NULL,
+ STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0,
+ &pstgOld);
+ Result(sc, "Open old file");
+
+ if (!CompareStorages(pstgOld, pstgNew))
+ {
+ Fail("Files did not compare identical\n");
+ }
+
+ pstgNew->Release();
+ pstgOld->Release();
+}
+
+#define DOCFILENAME L"d:\\nt\\private\\ole32\\stg\\async\\layout\\test\\test.doc"
+
+void t_script(void)
+{
+ SCODE sc;
+ IStorage *pstgRoot, *pstgNew, *pstgOld;
+ ILayoutStorage *pLayout;
+
+ int i;
+
+ BYTE buffer[4096];
+
+
+ sc = StgOpenLayoutDocfile(DOCFILENAME,
+ STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
+ 0,
+ &pstgRoot);
+ Result(sc, "StgOpenLayoutDocfile");
+
+
+ pstgRoot->QueryInterface(IID_ILayoutStorage,(void **) &pLayout);
+
+ for (i=0; i < NUMTESTS; i++)
+ {
+ sc = pLayout->LayoutScript(
+ arrWord[i].LayoutArray,
+ arrWord[i].nEntries,
+ STG_LAYOUT_SEQUENTIAL); // sequential (all up front) control structures
+
+ Result(sc, "LayoutScript");
+
+
+ }
+ // Write new compound file with desired layout
+ sc = pLayout->ReLayoutDocfile(NEWFILENAME);
+
+ Result(sc, "ReLayoutDocfile");
+
+ sc = StgOpenStorage(NEWFILENAME,
+ NULL,
+ STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0,
+ &pstgNew);
+ Result(sc, "Open new file");
+
+ if (!CompareStorages(pstgRoot, pstgNew))
+ {
+ Fail("Files did not compare identical\n");
+ }
+
+ pLayout->Release();
+ pstgNew->Release();
+ pstgRoot->Release();
+}
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ SCODE sc;
+ BeginTest();
+
+ //t_layout();
+
+ t_script();
+
+ EndTest(0);
+ exit(0);
+
+}
+
diff --git a/private/ole32/stg/async/layout/test/pch.cxx b/private/ole32/stg/async/layout/test/pch.cxx
new file mode 100644
index 000000000..7aced62e6
--- /dev/null
+++ b/private/ole32/stg/async/layout/test/pch.cxx
@@ -0,0 +1,25 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: pch.cxx
+//
+// History: 09-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include <windows.h>
+//#include <stgint.h>
+#include <objbase.h>
+
+#include <debnot.h>
+#include <error.hxx>
+
+#include "tutils.hxx"
+
diff --git a/private/ole32/stg/async/layout/test/scripts.hxx b/private/ole32/stg/async/layout/test/scripts.hxx
new file mode 100644
index 000000000..2dc27f57f
--- /dev/null
+++ b/private/ole32/stg/async/layout/test/scripts.hxx
@@ -0,0 +1,159 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: scripts.hxx
+//
+// History: 15-May-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+#define NUMTESTS 7
+
+StorageLayout arrWord0[] =
+{
+ // no repeat loop
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG) 0}, 2048 },
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)12800}, 2048},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)14848}, 346},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)12288}, 2048},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)10752}, 2048},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)10240}, 2048},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)7680}, 2048},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)9728}, 512},
+
+ { STGTY_STREAM, L"ObjectPool\\_823896884\\\x03PIC", {(LONGLONG) 0}, 76},
+ { STGTY_STORAGE, L"ObjectPool\\_823896884\\.PRINT", {(LONGLONG) 0}, {(LONGLONG) 0}},
+ { STGTY_STREAM, L"ObjectPool\\_823896884\\\x03META", {(LONGLONG) 0}, 101896},
+
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)2048}, 7*512},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)7168}, 3*512},
+
+ { STGTY_STREAM, L"ObjectPool\\_823617166\\\x03PIC", {(LONGLONG) 0}, 76},
+ { STGTY_STORAGE, L"ObjectPool\\_823617166\\.PRINT", {(LONGLONG) 0}, {(LONGLONG) 0}},
+
+ { STGTY_STREAM, L"ObjectPool\\_823620610\\\x03PIC", {(LONGLONG) 0}, 76},
+ { STGTY_STORAGE, L"ObjectPool\\_823620610\\.PRINT", {(LONGLONG) 0}, {(LONGLONG) 0}},
+
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)5632}, 2048}
+};
+
+StorageLayout arrWord1[] =
+{
+ // type name offset bytes
+ // one repeat loop
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)0}, 2048},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)12800}, 2048},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)14848}, 346},
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 4},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)12288}, 512},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)10752}, 512},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)10240}, 512},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)7680}, 512},
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 0},
+
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)9728}, 512}
+
+};
+
+StorageLayout arrWord2[] =
+{
+ // type name offset bytes
+ // nested repeat loop
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)0}, 2048},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)12800}, 2048},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)14848}, 346},
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 4},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)12288}, 512},
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 2},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)10752}, 256},
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 0},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)10240}, 512},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)7680}, 512},
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 0},
+
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)9728}, 512}
+
+};
+StorageLayout arrWord3[] =
+{
+ // type name offset bytes
+ // two repeat loops
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)0}, 2048},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)12800}, 2048},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)14848}, 346},
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 4},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)12288}, 512},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)10752}, 512},
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 0},
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 4},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)10240}, 512},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)7680}, 512},
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 0},
+
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)9728}, 512}
+
+};
+
+StorageLayout arrWord4[] =
+{
+ // 1 limited repeat loop with streams 3/4 streams running out
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 4},
+ { STGTY_STREAM, L"\x05SummaryInformation", {(LONGLONG) 0}, 100 }, //496
+ { STGTY_STREAM, L"\x01"L"CompObj", {(LONGLONG) 0}, 50}, // 106
+ { STGTY_STREAM, L"ObjectPool\\_823896884\\\x03PIC", {(LONGLONG) 0}, 76}, //76
+ { STGTY_STREAM, L"ObjectPool\\_823896884\\\x03META", {(LONGLONG) 0}, 101896}, //101896
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 0},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)9728}, 512} //15177
+
+};
+
+StorageLayout arrWord5[] =
+{
+ // 1 limited repeat loop with streams all streams running out
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 4},
+ { STGTY_STREAM, L"\x01"L"CompObj", {(LONGLONG) 0}, 50}, // 106
+ { STGTY_STREAM, L"\x05SummaryInformation", {(LONGLONG) 0}, 200 }, //496
+ { STGTY_STREAM, L"ObjectPool\\_823896884\\\x03PIC", {(LONGLONG) 0}, 76}, //76
+ { STGTY_STREAM, L"ObjectPool\\_823896884\\\x03META", {(LONGLONG) 0}, 101896}, //101896
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 0},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)9728}, 512} //15177
+
+};
+
+StorageLayout arrWord6[] =
+{
+ // 1 unlimited repeat loop
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, {STG_TOEND, 0} },
+ { STGTY_STREAM, L"\x01"L"CompObj", {(LONGLONG) 0}, 50}, // 106
+ { STGTY_STREAM, L"\x05SummaryInformation", {(LONGLONG) 0}, 100 }, //496
+ { STGTY_STREAM, L"ObjectPool\\_823896884\\\x03PIC", {(LONGLONG) 0}, 76}, //76
+ { STGTY_STREAM, L"ObjectPool\\_823896884\\\x03META", {(LONGLONG) 0}, 101896}, //101896
+ { STGTY_REPEAT, NULL, {(LONGLONG)0}, 0},
+ { STGTY_STREAM, L"WordDocument", {(LONGLONG)9728}, 512} //15177
+
+};
+
+
+typedef struct tagStorageLayoutArray
+{
+ StorageLayout *LayoutArray;
+ int nEntries;
+
+} STORAGELAYOUTARRAY;
+
+STORAGELAYOUTARRAY arrWord[] =
+{
+ { arrWord0, sizeof(arrWord0)/sizeof(arrWord0[0]) },
+ { arrWord1, sizeof(arrWord1)/sizeof(arrWord1[0]) },
+ { arrWord2, sizeof(arrWord2)/sizeof(arrWord2[0]) },
+ { arrWord3, sizeof(arrWord3)/sizeof(arrWord3[0]) },
+ { arrWord4, sizeof(arrWord4)/sizeof(arrWord4[0]) },
+ { arrWord5, sizeof(arrWord5)/sizeof(arrWord5[0]) },
+ { arrWord6, sizeof(arrWord6)/sizeof(arrWord6[0]) }
+
+};
+
+
+
diff --git a/private/ole32/stg/async/layout/test/test.doc b/private/ole32/stg/async/layout/test/test.doc
new file mode 100644
index 000000000..b56f64779
--- /dev/null
+++ b/private/ole32/stg/async/layout/test/test.doc
Binary files differ
diff --git a/private/ole32/stg/async/layout/test/tutils.cxx b/private/ole32/stg/async/layout/test/tutils.cxx
new file mode 100644
index 000000000..94fbfab4f
--- /dev/null
+++ b/private/ole32/stg/async/layout/test/tutils.cxx
@@ -0,0 +1,546 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tutils.cxx
+//
+// Contents: Generic utilities for tests
+//
+// History: 06-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+static BOOL fExitOnFail = TRUE;
+
+BOOL GetExitOnFail(void)
+{
+ return fExitOnFail;
+}
+
+void SetExitOnFail(BOOL set)
+{
+ fExitOnFail = set;
+}
+
+// Print out an error message and terminate
+void Fail(char *fmt, ...)
+{
+ va_list args;
+
+ args = va_start(args, fmt);
+ fprintf(stderr, "** Fatal error **: ");
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ EndTest(1);
+}
+
+typedef struct
+{
+ SCODE sc;
+ char *text;
+} StatusCodeText;
+
+static StatusCodeText scodes[] =
+{
+ S_OK, "S_OK",
+ S_FALSE, "S_FALSE",
+ STG_E_INVALIDFUNCTION, "STG_E_INVALIDFUNCTION",
+ STG_E_FILENOTFOUND, "STG_E_FILENOTFOUND",
+ STG_E_PATHNOTFOUND, "STG_E_PATHNOTFOUND",
+ STG_E_TOOMANYOPENFILES, "STG_E_TOOMANYOPENFILES",
+ STG_E_ACCESSDENIED, "STG_E_ACCESSDENIED",
+ STG_E_INVALIDHANDLE, "STG_E_INVALIDHANDLE",
+ STG_E_INSUFFICIENTMEMORY, "STG_E_INSUFFICIENTMEMORY",
+ STG_E_INVALIDPOINTER, "STG_E_INVALIDPOINTER",
+ STG_E_NOMOREFILES, "STG_E_NOMOREFILES",
+ STG_E_DISKISWRITEPROTECTED, "STG_E_DISKISWRITEPROTECTED",
+ STG_E_SEEKERROR, "STG_E_SEEKERROR",
+ STG_E_WRITEFAULT, "STG_E_WRITEFAULT",
+ STG_E_READFAULT, "STG_E_READFAULT",
+ STG_E_SHAREVIOLATION, "STG_E_SHAREVIOLATION",
+ STG_E_LOCKVIOLATION, "STG_E_LOCKVIOLATION",
+ STG_E_FILEALREADYEXISTS, "STG_E_FILEALREADYEXISTS",
+ STG_E_INVALIDPARAMETER, "STG_E_INVALIDPARAMETER",
+ STG_E_MEDIUMFULL, "STG_E_MEDIUMFULL",
+ STG_E_ABNORMALAPIEXIT, "STG_E_ABNORMALAPIEXIT",
+ STG_E_INVALIDHEADER, "STG_E_INVALIDHEADER",
+ STG_E_INVALIDNAME, "STG_E_INVALIDNAME",
+ STG_E_UNKNOWN, "STG_E_UNKNOWN",
+ STG_E_UNIMPLEMENTEDFUNCTION, "STG_E_UNIMPLEMENTEDFUNCTION",
+ STG_E_INVALIDFLAG, "STG_E_INVALIDFLAG",
+ STG_E_INUSE, "STG_E_INUSE",
+ STG_E_NOTCURRENT, "STG_E_NOTCURRENT",
+ STG_E_REVERTED, "STG_E_REVERTED",
+ STG_E_CANTSAVE, "STG_E_CANTSAVE",
+ STG_E_OLDFORMAT, "STG_E_OLDFORMAT",
+ STG_E_OLDDLL, "STG_E_OLDDLL",
+ STG_E_SHAREREQUIRED, "STG_E_SHAREREQUIRED",
+ STG_E_NOTFILEBASEDSTORAGE, "STG_E_NOTFILEBASEDSTORAGE",
+ STG_E_EXTANTMARSHALLINGS, "STG_E_EXTANTMARSHALLINGS",
+ STG_S_CONVERTED, "STG_S_CONVERTED"
+};
+#define NSCODETEXT (sizeof(scodes)/sizeof(scodes[0]))
+
+// Convert a status code to text
+char *ScText(SCODE sc)
+{
+ int i;
+
+ for (i = 0; i<NSCODETEXT; i++)
+ if (scodes[i].sc == sc)
+ return scodes[i].text;
+ return "<Unknown SCODE>";
+}
+
+// Output a call result and check for failure
+HRESULT Result(HRESULT hr, char *fmt, ...)
+{
+ SCODE sc;
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ sc = GetScode(hr);
+ printf(" - %s (0x%lX)\n", ScText(sc), sc);
+ if (FAILED(sc) && fExitOnFail)
+ Fail("Unexpected call failure\n");
+ return hr;
+}
+
+// Perform Result() when the expectation is failure
+HRESULT IllResult(HRESULT hr, char *fmt, ...)
+{
+ SCODE sc;
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ sc = GetScode(hr);
+ printf(" - %s (0x%lX)\n", ScText(sc), sc);
+ if (SUCCEEDED(sc) && fExitOnFail)
+ Fail("Unexpected call success\n");
+ return hr;
+}
+
+char *TcsText(TCHAR *ptcs)
+{
+ static char buf[256];
+
+ TTOA(ptcs, buf, 256);
+ return buf;
+}
+
+char *FileTimeText(FILETIME *pft)
+{
+ static char buf[80];
+ struct tm ctm;
+#ifndef FLAT
+ WORD dosdate, dostime;
+
+ if (CoFileTimeToDosDateTime(pft, &dosdate, &dostime))
+ {
+ ctm.tm_sec = (dostime & 31)*2;
+ ctm.tm_min = (dostime >> 5) & 63;
+ ctm.tm_hour = dostime >> 11;
+ ctm.tm_mday = dosdate & 31;
+ ctm.tm_mon = ((dosdate >> 5) & 15)-1;
+ ctm.tm_year = (dosdate >> 9)+80;
+ ctm.tm_wday = 0;
+#else
+ SYSTEMTIME st;
+
+ if (FileTimeToSystemTime(pft, &st))
+ {
+ ctm.tm_sec = st.wSecond;
+ ctm.tm_min = st.wMinute;
+ ctm.tm_hour = st.wHour;
+ ctm.tm_mday = st.wDay;
+ ctm.tm_mon = st.wMonth-1;
+ ctm.tm_year = st.wYear-1900;
+ ctm.tm_wday = st.wDayOfWeek;
+#endif
+ ctm.tm_yday = 0;
+ ctm.tm_isdst = 0;
+ strcpy(buf, asctime(&ctm));
+ buf[strlen(buf)-1] = 0;
+ }
+ else
+ sprintf(buf, "<FILETIME %08lX:%08lX>", pft->dwHighDateTime,
+ pft->dwLowDateTime);
+ return buf;
+}
+
+#pragma pack(1)
+struct SplitGuid
+{
+ DWORD dw1;
+ WORD w1;
+ WORD w2;
+ BYTE b[8];
+};
+#pragma pack()
+
+char *GuidText(GUID *pguid)
+{
+ static char buf[39];
+ SplitGuid *psg = (SplitGuid *)pguid;
+
+ sprintf(buf, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
+ psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
+ return buf;
+}
+
+#define CROW 16
+
+void BinText(ULONG cbSize, BYTE *pb)
+{
+ ULONG cb, i;
+
+ while (cbSize > 0)
+ {
+ cb = min(CROW, cbSize);
+ cbSize -= cb;
+ for (i = 0; i<cb; i++)
+ printf(" %02X", pb[i]);
+ for (i = cb; i<CROW; i++)
+ printf(" ");
+ printf(" '");
+ for (i = 0; i<cb; i++)
+ if (pb[i] >= 0x20 && pb[i] <= 0x7f)
+ putchar(pb[i]);
+ else
+ putchar('.');
+ pb += cb;
+ printf("'\n");
+ }
+}
+
+// BUGBUG - Remove for Cairole when they exist
+STDAPI CoMemAlloc(DWORD cbSize, void **ppv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc;
+
+ if (SUCCEEDED(GetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ *ppv = pMalloc->Alloc(cbSize);
+ pMalloc->Release();
+
+ if (*ppv == NULL)
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ }
+ else
+ *ppv = NULL;
+
+ return hr;
+}
+
+STDAPI CoMemFree(void *pv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc;
+
+ if (SUCCEEDED(GetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ pMalloc->Free(pv);
+ pMalloc->Release();
+ }
+
+ return hr;
+}
+
+TCHAR *TestFile(TCHAR *ptcsName, char *pszFile)
+{
+ char achFn[MAX_PATH];
+ char *dir, *file;
+ int len;
+
+ dir = getenv("DFDATA");
+ if (dir)
+ strcpy(achFn, dir);
+ else
+ strcpy(achFn, ".");
+ len = strlen(achFn);
+ if (achFn[len-1] != '\\')
+ achFn[len++] = '\\';
+
+ if (pszFile)
+ {
+ strcpy(achFn+len, pszFile);
+ }
+ else
+ {
+ file = getenv("DFFILE");
+ if (file)
+ strcpy(achFn+len, file);
+ else
+ strcpy(achFn+len, "TEST.DFL");
+ }
+
+ ATOT(achFn, ptcsName, MAX_PATH);
+ return ptcsName+len;
+}
+
+#if WIN32 == 300
+char *TestFormat(DWORD *pdwFmt, DWORD *pgrfMode)
+{
+ char *fmt;
+
+ fmt = getenv("STGFMT");
+ if (fmt == NULL || !strcmp(fmt, "doc"))
+ {
+ fmt = "document";
+ *pdwFmt = STGFMT_DOCUMENT;
+ }
+ else if (!strcmp(fmt, "file"))
+ {
+ fmt = "file";
+ *pdwFmt = STGFMT_FILE;
+ }
+ else
+ {
+ fmt = "directory";
+ *pdwFmt = STGFMT_DIRECTORY;
+ *pgrfMode &= ~STGM_CREATE;
+ }
+ return fmt;
+}
+#endif
+
+BOOL CompareStatStg(STATSTG *pstat1, STATSTG *pstat2)
+{
+ if (wcscmp(pstat1->pwcsName, pstat2->pwcsName) != 0)
+ {
+ printf("Names compared wrong: %ws and %ws\n",
+ pstat1->pwcsName, pstat2->pwcsName);
+ return FALSE;
+ }
+ if (pstat1->type != pstat2->type)
+ {
+ printf("Types compares wrong on %ws and %ws: %lu and %lu\n",
+ pstat1->pwcsName,
+ pstat2->pwcsName,
+ pstat2->type,
+ pstat2->type);
+
+ return FALSE;
+ }
+ if (!IsEqualIID(pstat1->clsid, pstat2->clsid))
+ {
+ printf("Class IDs for %ws and %ws compared bad\n",
+ pstat1->pwcsName,
+ pstat2->pwcsName);
+ return FALSE;
+ }
+ if (pstat1->type == STGTY_STREAM)
+ {
+ if ((pstat1->cbSize).QuadPart != (pstat2->cbSize).QuadPart)
+ {
+ printf("Sizes for %ws and %ws compared bad: %lu and %lu\n",
+ pstat1->pwcsName,
+ pstat2->pwcsName,
+ (pstat1->cbSize).LowPart,
+ (pstat2->cbSize).LowPart);
+
+ return FALSE;
+ }
+ }
+ //Also check statebits and timestamps?
+
+ return TRUE;
+}
+
+
+BOOL CompareStreams(IStream *pstm1, IStream *pstm2)
+{
+ const ULONG BUFSIZE = 4096;
+ BYTE buffer1[BUFSIZE];
+ BYTE buffer2[BUFSIZE];
+ ULONG cbRead1;
+ ULONG cbRead2;
+ STATSTG stat1;
+ STATSTG stat2;
+ LARGE_INTEGER li;
+ li.QuadPart = 0;
+
+ pstm1->Seek(li, STREAM_SEEK_SET, NULL);
+ pstm2->Seek(li, STREAM_SEEK_SET, NULL);
+
+ do
+ {
+ SCODE sc;
+ sc = pstm1->Read(buffer1, BUFSIZE, &cbRead1);
+ if (FAILED(sc))
+ {
+ printf("Read failed with %lx\n", sc);
+ return FALSE;
+ }
+ sc = pstm2->Read(buffer2, BUFSIZE, &cbRead2);
+ if (FAILED(sc))
+ {
+ printf("Read failed with %lx\n", sc);
+ return FALSE;
+ }
+ if ((cbRead1 != cbRead2) || (memcmp(buffer1, buffer2, cbRead1) != 0))
+ {
+ if (cbRead1 != cbRead2)
+ {
+ printf("Stream compare returned different bytes read: %lu and %lu\n",
+ cbRead1,
+ cbRead2);
+ }
+ else
+ {
+ printf("Data mismatch.\n");
+ }
+ return FALSE;
+ }
+ }
+ while (cbRead1 == BUFSIZE);
+
+ return TRUE;
+}
+
+
+BOOL CompareStorages(IStorage *pstg1, IStorage *pstg2)
+{
+ SCODE sc1, sc2, sc;
+ IStorage *pstgChild1, *pstgChild2;
+ IStream *pstmChild1, *pstmChild2;
+ IEnumSTATSTG *penum1, *penum2;
+ STATSTG stat1, stat2;
+
+ pstg1->EnumElements(0, 0, 0, &penum1);
+ pstg2->EnumElements(0, 0, 0, &penum2);
+
+ do
+ {
+ ULONG celtFetched1, celtFetched2;
+
+ sc1 = penum1->Next(1, &stat1, &celtFetched1);
+ if (FAILED(sc1))
+ {
+ printf("EnumElements 1 failed with %lx\n", sc1);
+ return FALSE;
+ }
+ sc2 = penum2->Next(1, &stat2, &celtFetched2);
+ if (FAILED(sc2) || (celtFetched1 != celtFetched2) || (sc1 != sc2))
+ {
+ if (FAILED(sc2))
+ {
+ printf("EnumElements 2 failed with %lx\n", sc2);
+ }
+ else
+ {
+ printf("Return code mismatch: %lx and %lx\n", sc1, sc2);
+ }
+ return FALSE;
+ }
+ if (celtFetched1 == 0)
+ {
+ //We're done.
+ return TRUE;
+ }
+
+ if (!CompareStatStg(&stat1, &stat2))
+ {
+ return FALSE;
+ }
+
+ //Items have compared OK so far. Now compare contents.
+ if (stat1.type == STGTY_STREAM)
+ {
+ sc = pstg1->OpenStream(stat1.pwcsName,
+ 0,
+ STGM_DIRECT |
+ STGM_READ | STGM_SHARE_EXCLUSIVE,
+ 0,
+ &pstmChild1);
+ if (FAILED(sc))
+ {
+ printf("OpenStream on pstg1 for %ws failed with %lx\n",
+ stat1.pwcsName,
+ sc);
+ return FALSE;
+ }
+ sc = pstg2->OpenStream(stat2.pwcsName,
+ 0,
+ STGM_DIRECT |
+ STGM_READ | STGM_SHARE_EXCLUSIVE,
+ 0,
+ &pstmChild2);
+ if (FAILED(sc))
+ {
+ printf("OpenStream on pstg2 for %ws failed with %lx\n",
+ stat2.pwcsName,
+ sc);
+ return FALSE;
+ }
+ if (!CompareStreams(pstmChild1, pstmChild2))
+ {
+ printf("Stream compare on %ws and %ws failed.\n",
+ stat1.pwcsName,
+ stat2.pwcsName);
+ return FALSE;
+ }
+ pstmChild1->Release();
+ pstmChild2->Release();
+ }
+ else
+ {
+ //Compare storages
+ sc = pstg1->OpenStorage(stat1.pwcsName,
+ NULL,
+ STGM_DIRECT | STGM_READ |
+ STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0,
+ &pstgChild1);
+ if (FAILED(sc))
+ {
+ printf("OpenStorage on pstg1 for %ws failed with %lx\n",
+ stat1.pwcsName,
+ sc);
+ return FALSE;
+ }
+
+ sc = pstg2->OpenStorage(stat2.pwcsName,
+ NULL,
+ STGM_DIRECT | STGM_READ |
+ STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0,
+ &pstgChild2);
+ if (FAILED(sc))
+ {
+ printf("OpenStorage on pstg2 for %ws failed with %lx\n",
+ stat2.pwcsName,
+ sc);
+ return FALSE;
+ }
+ if (!CompareStorages(pstgChild1, pstgChild2))
+ {
+ printf("CompareStorages failed for %ws and %ws\n",
+ stat1.pwcsName,
+ stat2.pwcsName);
+ return FALSE;
+ }
+ pstgChild1->Release();
+ pstgChild2->Release();
+ }
+
+ //printf("Object %ws compared OK.\n", stat1.pwcsName);
+ CoMemFree(stat1.pwcsName);
+ CoMemFree(stat2.pwcsName);
+
+ } while (sc1 != S_FALSE);
+
+ return TRUE;
+}
diff --git a/private/ole32/stg/async/layout/test/tutils.hxx b/private/ole32/stg/async/layout/test/tutils.hxx
new file mode 100644
index 000000000..4e05947a0
--- /dev/null
+++ b/private/ole32/stg/async/layout/test/tutils.hxx
@@ -0,0 +1,89 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tutils.hxx
+//
+// Contents: Generic test utilities
+//
+// History: 06-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __TUTILS_HXX__
+#define __TUTILS_HXX__
+
+#ifndef UNICODE
+#define tcscpy(d, s) strcpy(d, s)
+#define tcslen(s) strlen(s)
+#define TTEXT(s) s
+#define TFMT "%s"
+#define ATOT(a, t, max) strcpy(t, a)
+#define TTOA(t, a, max) strcpy(a, t)
+#define WTOT(w, t, max) wcstombs(t, w, max)
+#define TTOW(t, w, max) mbstowcs(w, t, max)
+#else
+#define tcscpy(d, s) wcscpy(d, s)
+#define tcslen(s) wcslen(s)
+#define TTEXT(s) L##s
+#define TFMT "%ws"
+#define ATOT(a, t, max) mbstowcs(t, a, max)
+#define TTOA(t, a, max) wcstombs(a, t, max)
+#define WTOT(w, t, max) wcscpy(t, w)
+#define TTOW(t, w, max) wcscpy(w, t)
+#endif
+#ifdef WIN32
+#define ATOX(a, t, max) mbstowcs(t, a, max)
+#define XTOA(t, a, max) wcstombs(a, t, max)
+#define WTOX(w, t, max) wcscpy(t, w)
+#define XTOW(t, w, max) wcscpy(w, t)
+#else
+#define ATOX(a, t, max) strcpy(t, a)
+#define XTOA(t, a, max) strcpy(a, t)
+#define WTOX(w, t, max) wcstombs(t, w, max)
+#define XTOW(t, w, max) mbstowcs(w, t, max)
+#endif
+
+#ifdef CINTERFACE
+#define Mthd(this, name) ((this)->lpVtbl->name)
+#define SELF(p) (p),
+#else
+#define Mthd(this, name) (this)->name
+#define SELF(p)
+#endif
+
+#if 0
+// BUGBUG - Remove for Cairole when they exist
+STDAPI CoMemAlloc(DWORD cBytes, void **ppv);
+STDAPI CoMemFree(void *pv);
+#endif
+
+BOOL GetExitOnFail(void);
+void SetExitOnFail(BOOL set);
+void Fail(char *fmt, ...);
+char *ScText(SCODE sc);
+HRESULT Result(HRESULT hr, char *fmt, ...);
+HRESULT IllResult(HRESULT hr, char *fmt, ...);
+char *TcsText(TCHAR *ptcs);
+char *FileTimeText(FILETIME *pft);
+char *GuidText(GUID *pguid);
+void BinText(ULONG cb, BYTE *pb);
+TCHAR *TestFile(TCHAR *ptcsName, char *pszFile);
+
+#if WIN32 == 300
+char *TestFormat(DWORD *pdwFmt, DWORD *pgrfMode);
+#endif
+
+void CreateTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName);
+void OpenTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName);
+
+// Defined by test, called by Fail
+void EndTest(int code);
+
+
+BOOL CompareStorages(IStorage *pstg1, IStorage *pstg2);
+
+#endif // #ifndef __TUTILS_HXX__
diff --git a/private/ole32/stg/async/layoutui/cklayout.cxx b/private/ole32/stg/async/layoutui/cklayout.cxx
new file mode 100644
index 000000000..a1c77ef0b
--- /dev/null
+++ b/private/ole32/stg/async/layoutui/cklayout.cxx
@@ -0,0 +1,333 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: layoutui.cxx
+//
+// Contents: debug UI implementation on Docfile Layout Tool
+//
+// Classes: CLayoutApp
+//
+// Functions:
+//
+// History: 07-Apr-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+#include "layoutui.hxx"
+
+#if DBG==1
+
+// BUGBUG - Remove for Cairole when they exist
+STDAPI CoMemAlloc(DWORD cbSize, void **ppv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc;
+
+ if (SUCCEEDED(GetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ *ppv = pMalloc->Alloc(cbSize);
+ pMalloc->Release();
+
+ if (*ppv == NULL)
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ }
+ else
+ *ppv = NULL;
+
+ return hr;
+}
+
+STDAPI CoMemFree(void *pv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc;
+
+ if (SUCCEEDED(GetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ pMalloc->Free(pv);
+ pMalloc->Release();
+ }
+
+ return hr;
+}
+
+
+BOOL CompareStatStg(STATSTG *pstat1, STATSTG *pstat2)
+{
+ if (Laylstrcmp(pstat1->pwcsName, pstat2->pwcsName) != 0)
+ {
+ return FALSE;
+ }
+ if (pstat1->type != pstat2->type)
+ {
+ return FALSE;
+ }
+ if (!IsEqualIID(pstat1->clsid, pstat2->clsid))
+ {
+ return FALSE;
+ }
+ if (pstat1->type == STGTY_STREAM)
+ {
+ if ((pstat1->cbSize).QuadPart != (pstat2->cbSize).QuadPart)
+ {
+ return FALSE;
+ }
+ }
+ //Also check statebits and timestamps?
+
+ return TRUE;
+}
+
+
+BOOL CompareStreams(IStream *pstm1, IStream *pstm2)
+{
+ const ULONG BUFSIZE = 4096;
+ BYTE buffer1[BUFSIZE];
+ BYTE buffer2[BUFSIZE];
+ ULONG cbRead1;
+ ULONG cbRead2;
+ STATSTG stat1;
+ STATSTG stat2;
+ LARGE_INTEGER li;
+ li.QuadPart = 0;
+
+ pstm1->Seek(li, STREAM_SEEK_SET, NULL);
+ pstm2->Seek(li, STREAM_SEEK_SET, NULL);
+
+ do
+ {
+ SCODE sc;
+ sc = pstm1->Read(buffer1, BUFSIZE, &cbRead1);
+ if (FAILED(sc))
+ {
+ return FALSE;
+ }
+ sc = pstm2->Read(buffer2, BUFSIZE, &cbRead2);
+ if (FAILED(sc))
+ {
+ return FALSE;
+ }
+ if ((cbRead1 != cbRead2) || (memcmp(buffer1, buffer2, cbRead1) != 0))
+ {
+ return FALSE;
+ }
+ }
+ while (cbRead1 == BUFSIZE);
+
+ return TRUE;
+}
+
+
+BOOL CompareStorages(IStorage *pstg1, IStorage *pstg2)
+{
+ SCODE sc1, sc2, sc;
+ HRESULT hr = TRUE;
+
+ IStorage *pstgChild1,
+ *pstgChild2;
+
+ IStream *pstmChild1,
+ *pstmChild2;
+
+ IEnumSTATSTG *penum1 = NULL,
+ *penum2 = NULL;
+ STATSTG stat1,
+ stat2;
+
+ pstg1->EnumElements(0, 0, 0, &penum1);
+
+ if (!penum1)
+ return FALSE;
+
+ pstg2->EnumElements(0, 0, 0, &penum2);
+
+ if (!penum2)
+ {
+ penum1->Release();
+ return FALSE;
+ }
+
+ do
+ {
+ ULONG celtFetched1, celtFetched2;
+
+ sc1 = penum1->Next(1, &stat1, &celtFetched1);
+ if (FAILED(sc1))
+ {
+ hr = FALSE;
+ goto Done;
+ }
+ sc2 = penum2->Next(1, &stat2, &celtFetched2);
+ if (FAILED(sc2) || (celtFetched1 != celtFetched2) || (sc1 != sc2))
+ {
+ hr = FALSE;
+ goto Done;
+ }
+ if (celtFetched1 == 0)
+ {
+ // we are done
+ hr = TRUE;
+ goto Done;
+
+ }
+
+ if (!CompareStatStg(&stat1, &stat2))
+ {
+ hr = FALSE;
+ goto Done;
+ }
+
+ //Items have compared OK so far. Now compare contents.
+ if (stat1.type == STGTY_STREAM)
+ {
+ sc = pstg1->OpenStream(stat1.pwcsName,
+ 0,
+ STGM_DIRECT |
+ STGM_READ | STGM_SHARE_EXCLUSIVE,
+ 0,
+ &pstmChild1);
+ if (FAILED(sc))
+ {
+ hr = FALSE;
+ goto Done;
+ }
+ sc = pstg2->OpenStream(stat2.pwcsName,
+ 0,
+ STGM_DIRECT |
+ STGM_READ | STGM_SHARE_EXCLUSIVE,
+ 0,
+ &pstmChild2);
+ if (FAILED(sc))
+ {
+ pstmChild1->Release();
+ hr = FALSE;
+ goto Done;
+ }
+ if (!CompareStreams(pstmChild1, pstmChild2))
+ {
+ pstmChild1->Release();
+ pstmChild2->Release();
+ hr = FALSE;
+ goto Done;
+ }
+ pstmChild1->Release();
+ pstmChild2->Release();
+ }
+ else
+ {
+ //Compare storages
+ sc = pstg1->OpenStorage(stat1.pwcsName,
+ NULL,
+ STGM_DIRECT | STGM_READ |
+ STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0,
+ &pstgChild1);
+ if (FAILED(sc))
+ {
+ hr = FALSE;
+ goto Done;
+ }
+
+ sc = pstg2->OpenStorage(stat2.pwcsName,
+ NULL,
+ STGM_DIRECT | STGM_READ |
+ STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0,
+ &pstgChild2);
+ if (FAILED(sc))
+ {
+ pstgChild1->Release();
+ hr = FALSE;
+ goto Done;
+ }
+ if (!CompareStorages(pstgChild1, pstgChild2))
+ {
+ pstgChild1->Release();
+ pstgChild2->Release();
+ hr = FALSE;
+ goto Done;
+ }
+ pstgChild1->Release();
+ pstgChild2->Release();
+ }
+
+ CoMemFree(stat1.pwcsName);
+ CoMemFree(stat2.pwcsName);
+
+ } while (sc1 != S_FALSE);
+
+
+Done:
+
+ penum1->Release();
+ penum2->Release();
+
+ return hr;
+
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::IdenticalFiles public
+//
+// Synopsis: Check two docfiles to ensure they are the same
+//
+// Returns: TRUE is the files are identical, FALSE is they are not
+//
+// History: 07-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+BOOL CLayoutApp::IdenticalFiles( TCHAR *patcFileOne,
+ TCHAR *patcFileTwo)
+{
+
+ SCODE sc;
+ IStorage *pstgOne,
+ *pstgTwo;
+ OLECHAR awcNewFileOne[MAX_PATH];
+ OLECHAR awcNewFileTwo[MAX_PATH];
+
+
+ sc = StgOpenStorage(TCharToOleChar(patcFileOne, awcNewFileOne, MAX_PATH),
+ NULL,
+ STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0,
+ &pstgOne);
+ if (FAILED(sc))
+ {
+ return FALSE;
+ }
+
+ sc = StgOpenStorage (TCharToOleChar(patcFileTwo, awcNewFileTwo, MAX_PATH),
+ NULL,
+ STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0,
+ &pstgTwo);
+ if (FAILED(sc))
+ {
+ pstgOne->Release();
+ return FALSE;
+ }
+
+
+ sc = CompareStorages(pstgOne, pstgTwo);
+
+ pstgOne->Release();
+ pstgTwo->Release();
+
+ if (sc)
+ return TRUE;
+ else
+ return FALSE;
+
+}
+
+#endif
diff --git a/private/ole32/stg/async/layoutui/daytona/makefile b/private/ole32/stg/async/layoutui/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/async/layoutui/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/async/layoutui/daytona/sources b/private/ole32/stg/async/layoutui/daytona/sources
new file mode 100644
index 000000000..b1774106e
--- /dev/null
+++ b/private/ole32/stg/async/layoutui/daytona/sources
@@ -0,0 +1,91 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Susi Argo (SusiA) 25-Mar-96
+
+!ENDIF
+
+
+MAJORCOMP = dflayui
+MINORCOMP = dflayui
+
+!include ..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= dflayout
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= PROGRAM
+
+INCLUDES= ..;..\..\h;..\..\..\h;..\..\..\..\ih
+
+C_DEFINES= \
+ $(C_DEFINES)
+
+
+PRECOMPILED_INCLUDE=
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
+
+SOURCES= \
+ ..\laymain.cxx \
+ ..\layoutui.cxx \
+ ..\olesite.cxx \
+ ..\cklayout.cxx \
+ ..\layoutui.rc
+
+
+UMTYPE= windows
+UMENTRY= winmain
+UMAPPL=
+UMTEST=
+
+LINKLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\dflayout.lib \
+ ..\..\debug\daytona\obj\*\debug.lib \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib
+
+
+!include ..\sources.inc
+
diff --git a/private/ole32/stg/async/layoutui/laymain.cxx b/private/ole32/stg/async/layoutui/laymain.cxx
new file mode 100644
index 000000000..a60adcd44
--- /dev/null
+++ b/private/ole32/stg/async/layoutui/laymain.cxx
@@ -0,0 +1,23 @@
+#include "layoutui.hxx"
+
+
+INT WINAPI WinMain(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine,
+ INT nCmdShow
+)
+{
+ CLayoutApp *pLayoutApp;
+
+ pLayoutApp = new CLayoutApp(hInstance);
+
+ if( !pLayoutApp )
+ return 0;
+
+ if( !pLayoutApp->InitApp() )
+ return 0;
+
+ return pLayoutApp->DoAppMessageLoop();
+}
+
diff --git a/private/ole32/stg/async/layoutui/layouthd.hxx b/private/ole32/stg/async/layoutui/layouthd.hxx
new file mode 100644
index 000000000..a8ab5df9f
--- /dev/null
+++ b/private/ole32/stg/async/layoutui/layouthd.hxx
@@ -0,0 +1,21 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: layouthd.hxx
+//
+// Contents: Theis is so both layout and layoutu can share the cruntime source code
+// Classes:
+//
+// Functions:
+//
+// History: 20-Jun-96 SusiA Share Cruntime functions
+//
+//----------------------------------------------------------------------------
+#ifndef __LAYOUTHD_HXX__
+#define __LAYOUTHD_HXX__
+
+// do nothing here for layoutui, to share the cruntime.cxx code
+
+#endif // #ifndef __LAYOUTHD_HXX__
diff --git a/private/ole32/stg/async/layoutui/layoutui.cxx b/private/ole32/stg/async/layoutui/layoutui.cxx
new file mode 100644
index 000000000..fd5842d91
--- /dev/null
+++ b/private/ole32/stg/async/layoutui/layoutui.cxx
@@ -0,0 +1,1351 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: layoutui.cxx
+//
+// Contents: UI implementation on Docfile Layout Tool
+//
+// Classes: CLayoutApp
+//
+// Functions:
+//
+// History: 23-Mar-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+#include "layoutui.hxx"
+
+// Constants for File Addition dialogs
+#define MAX_FILES_BUFFER 2048
+#define MAX_TITLE_LEN 256
+#define MAX_FILTER_LEN 256
+#define MAX_PREFIX_LEN 5
+
+#define WIDTH 500
+#define HEIGHT 300
+
+#define NULL_TERM TEXT('\0')
+#define BACKSLASH TEXT("\\")
+
+#define MALLOC(x) LocalAlloc( LMEM_FIXED , x );
+#define FREE(x) LocalFree( x );
+#define JumpOnFail(sc) if( FAILED(sc) ) goto Err;
+
+#ifdef UNICODE
+#define STRING_LEN(x) Laylstrlen(x)
+#define CopyString(dst, src) Laylstrcpy(dst, src)
+#define CatString(dst, src) Laylstrcat(dst, src)
+#else
+#define STRING_LEN(x) lstrlen(x)
+#define CopyString(dst, src) lstrcpy(dst, src)
+#define CatString(dst, src) lstrcat(dst, src)
+#endif
+
+// Since the LayoutDlgProc must be static for the Callback,
+// we need a way to reference the member variables inside of
+// LayoutDlgProc
+static CLayoutApp *pStaticThis;
+
+#ifdef STRICT
+static WNDPROC lpfnwpListBoxProc = NULL;
+static WNDPROC lpfnwpButtonProc = NULL;
+#define SUBCLASS_WNDPROC WNDPROC
+#else
+static FARPROC lpfnwpListBoxProc = NULL;
+static FARPROC lpfnwpButtonProc = NULL;
+#define SUBCLASS_WNDPROC FARPROC
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::CLayoutApp public
+//
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+
+CLayoutApp::CLayoutApp(HINSTANCE hInst)
+{
+ m_hInst = hInst;
+ m_hwndMain = hwndNil;
+
+ pStaticThis = this;
+ m_bOptimizing = FALSE;
+ m_bCancelled = FALSE;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::InitApp public
+//
+// Synopsis: Initialize the application
+//
+// Returns: TRUE is sucessful, FALSE is FAILED
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+BOOL CLayoutApp::InitApp(void)
+{
+
+ if( !InitWindow() )
+ {
+ DisplayMessage(NULL,
+ IDS_MAIN_WINDOW_FAIL,
+ IDS_MAIN_WINDOW_FAIL_TITLE,
+ MB_ICONSTOP);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::DoAppMessageLoop public
+//
+// Synopsis: Main window message loop
+//
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+
+INT CLayoutApp::DoAppMessageLoop(void)
+{
+ MSG msg;
+ HACCEL hAccel;
+
+ hAccel = LoadAccelerators( m_hInst, MAKEINTRESOURCE(IDR_ACCELERATOR1) );
+
+ while (GetMessage (&msg, NULL, 0, 0))
+ {
+ if (m_hwndMain == 0 || !IsDialogMessage (m_hwndMain, &msg))
+ {
+ TranslateMessage (&msg) ;
+ DispatchMessage (&msg) ;
+ }
+ }
+
+ return msg.wParam;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::InitWindow public
+//
+// Synopsis: Initialize the main window
+//
+// Returns: TRUE is sucessful, FALSE is FAILED
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+BOOL CLayoutApp::InitWindow (void)
+{
+ m_hwndMain = CreateDialog( m_hInst,
+ MAKEINTRESOURCE(IDD_MAIN),
+ NULL,
+ (DLGPROC)LayoutDlgProc);
+
+ if( m_hwndMain == NULL )
+ return FALSE;
+
+ EnableButtons();
+ DragAcceptFiles(m_hwndMain, TRUE);
+
+ return TRUE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::InitApp public
+//
+// Synopsis: Application Callback function
+//
+// Returns: TRUE is message was handled. FALSE otherwise
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+
+BOOL CALLBACK CLayoutApp::ListBoxWndProc(
+ HWND hWnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_SETCURSOR:
+ if( (HWND)wParam == pStaticThis->m_hwndMain )
+ SetCursor(LoadCursor(NULL, (pStaticThis->m_bCancelled ? IDC_WAIT : IDC_ARROW)));
+
+ return bMsgHandled;
+ }
+
+ return CallWindowProc(lpfnwpListBoxProc, hWnd, uMsg, wParam, lParam);
+}
+
+
+BOOL CALLBACK CLayoutApp::ButtonWndProc(
+ HWND hWnd,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_SETCURSOR:
+ if( (HWND)wParam == pStaticThis->m_hwndMain )
+ SetCursor(LoadCursor(NULL, (pStaticThis->m_bCancelled ? IDC_WAIT : IDC_ARROW)));
+
+ return bMsgHandled;
+ }
+
+ return CallWindowProc(lpfnwpButtonProc, hWnd, uMsg, wParam, lParam);
+}
+
+
+BOOL CALLBACK CLayoutApp::LayoutDlgProc(
+ HWND hDlg,
+ UINT uMsg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ SCODE sc = S_OK;
+ WORD wId = LOWORD((DWORD)wParam);
+ WORD wNotifyCode = HIWORD((DWORD)wParam);
+ DWORD thrdid;
+ static HANDLE hthread;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ pStaticThis->m_hwndBtnAdd = GetDlgItem( hDlg, IDC_BTN_ADD );
+ pStaticThis->m_hwndBtnRemove = GetDlgItem( hDlg, IDC_BTN_REMOVE );
+ pStaticThis->m_hwndBtnOptimize = GetDlgItem( hDlg, IDC_BTN_OPTIMIZE );
+ pStaticThis->m_hwndListFiles = GetDlgItem( hDlg, IDC_LIST_FILES );
+ pStaticThis->m_hwndStaticFiles = GetDlgItem( hDlg, IDC_STATIC_FILES );
+
+ lpfnwpListBoxProc = (SUBCLASS_WNDPROC)SetWindowLong(
+ pStaticThis->m_hwndListFiles,
+ GWL_WNDPROC,
+ (LONG)(WNDPROC)MakeProcInstance(
+ (FARPROC)ListBoxWndProc,
+ pStaticThis->m_hInst
+ )
+ );
+
+ lpfnwpButtonProc = (SUBCLASS_WNDPROC)SetWindowLong(
+ pStaticThis->m_hwndBtnAdd,
+ GWL_WNDPROC,
+ (LONG)(WNDPROC)MakeProcInstance(
+ (FARPROC)ButtonWndProc,
+ pStaticThis->m_hInst
+ )
+ );
+
+ lpfnwpButtonProc = (SUBCLASS_WNDPROC)SetWindowLong(
+ pStaticThis->m_hwndBtnRemove,
+ GWL_WNDPROC,
+ (LONG)(WNDPROC)MakeProcInstance(
+ (FARPROC)ButtonWndProc,
+ pStaticThis->m_hInst
+ )
+ );
+
+ lpfnwpButtonProc = (SUBCLASS_WNDPROC)SetWindowLong(
+ pStaticThis->m_hwndBtnOptimize,
+ GWL_WNDPROC,
+ (LONG)(WNDPROC)MakeProcInstance(
+ (FARPROC)ButtonWndProc,
+ pStaticThis->m_hInst
+ )
+ );
+
+ // resize dialog and center it on the screen
+ {
+ RECT rcScreen;
+ GetWindowRect(GetDesktopWindow(), &rcScreen);
+
+ SetWindowPos(
+ hDlg,
+ HWND_TOP,
+ (rcScreen.right - rcScreen.left - WIDTH) / 2,
+ (rcScreen.bottom - rcScreen.top - HEIGHT) / 2,
+ WIDTH,
+ HEIGHT,
+ SWP_SHOWWINDOW);
+ }
+ return TRUE;
+
+ case WM_SIZE:
+ pStaticThis->ReSizeWindow(lParam);
+ return bMsgHandled;
+
+ case WM_GETMINMAXINFO:
+ {
+ LPMINMAXINFO lpminmax = (LPMINMAXINFO) lParam;
+
+ lpminmax->ptMinTrackSize.x = gdxWndMin;
+ lpminmax->ptMinTrackSize.y = gdyWndMin;
+ }
+ return bMsgHandled;
+
+ case WM_CLOSE:
+ DestroyWindow(hDlg);
+ PostQuitMessage(0);
+ return bMsgHandled;
+
+ case WM_DROPFILES:
+ {
+ TCHAR atcFileName[MAX_PATH];
+ HDROP hdrop = (HDROP)wParam;
+ INT nFiles = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);
+ INT i;
+
+ for( i=0; i < nFiles; i++ )
+ {
+ if( DragQueryFile(hdrop, i, atcFileName, MAX_PATH) != 0 )
+ pStaticThis->AddFileToListBox(atcFileName);
+ }
+ DragFinish(hdrop);
+ pStaticThis->EnableButtons();
+ }
+ return bMsgHandled;
+
+ case WM_SETCURSOR:
+ if( (HWND)wParam == pStaticThis->m_hwndMain )
+ SetCursor(LoadCursor(NULL, (pStaticThis->m_bCancelled ? IDC_WAIT : IDC_ARROW)));
+
+ return bMsgHandled;
+
+ case WM_COMMAND:
+ switch( wId )
+ {
+ case IDC_BTN_ADD:
+ pStaticThis->AddFiles();
+ return bMsgHandled;
+
+ case IDC_BTN_REMOVE:
+ pStaticThis->RemoveFiles();
+ return bMsgHandled;
+
+ case IDC_BTN_OPTIMIZE:
+
+ if (pStaticThis->m_bOptimizing) //Cancel Button click
+ {
+ pStaticThis->m_bCancelled = TRUE;
+
+ //SetCursor(LoadCursor(NULL, IDC_WAIT));
+
+ return bMsgHandled;
+ }
+ else //Optimize Button Click
+ {
+
+ pStaticThis->m_bOptimizing = TRUE;
+ pStaticThis->SetActionButton( IDS_CANCEL );
+ hthread = CreateThread(NULL,0,
+ (LPTHREAD_START_ROUTINE) &(pStaticThis->OptimizeFiles),
+ NULL, 0, &thrdid);
+
+ return bMsgHandled;
+
+ }
+
+ case IDC_LIST_FILES:
+ switch( wNotifyCode )
+ {
+ case LBN_SELCHANGE:
+ pStaticThis->EnableButtons();
+ return bMsgHandled;
+
+ default:
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ break;
+
+ }
+
+ return bMsgNotHandled;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::ReSizeWindow public
+//
+// Synopsis: Handle resizing the main dialog
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+
+VOID CLayoutApp::ReSizeWindow (LPARAM lParam)
+{
+ int nW = LOWORD(lParam);
+ int nH = HIWORD(lParam);
+
+ int nBorder = 10;
+ int nButtonH = 25;
+ int nButtonW = 100;
+ int nStaticH = 15;
+
+ int nListY = nBorder + nStaticH;
+ int nListW = nW - 3 * nBorder - nButtonW;
+ int nListH = nH - nListY - nBorder;
+
+ int nButtonX = 2 * nBorder + nListW;
+
+ MoveWindow(m_hwndStaticFiles, nBorder, nBorder, nListW, nStaticH, TRUE);
+ MoveWindow(m_hwndListFiles , nBorder, nListY, nListW, nH - nButtonH - nBorder, TRUE);
+
+ MoveWindow(m_hwndBtnAdd , nButtonX, nListY, nButtonW, nButtonH, TRUE);
+ MoveWindow(m_hwndBtnRemove , nButtonX, nListY + 3 * nBorder, nButtonW, nButtonH, TRUE);
+ MoveWindow(m_hwndBtnOptimize, nButtonX, nListY + nListH - nButtonH, nButtonW, nButtonH, TRUE);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::AddFiles public
+//
+// Synopsis: Add and display selected files to the dialog window
+//
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+
+VOID CLayoutApp::AddFiles (void)
+{
+ TCHAR atcFile[MAX_FILES_BUFFER];
+ TCHAR atcTitle[MAX_TITLE_LEN];
+ TCHAR atcFilter[MAX_FILTER_LEN];
+
+
+ OPENFILENAME ofn;
+ FillMemory( (LPVOID)&ofn, sizeof(ofn), 0 );
+
+ ofn.lStructSize = sizeof( ofn );
+ ofn.hwndOwner = m_hwndMain;
+ ofn.hInstance = m_hInst;
+
+ FormFilterString( atcFilter, MAX_FILTER_LEN );
+ ofn.lpstrFilter = atcFilter;
+
+ ofn.lpstrCustomFilter = NULL;
+ ofn.nFilterIndex = 0;
+
+ *atcFile = NULL_TERM;
+ ofn.lpstrFile = atcFile;
+ ofn.nMaxFile = MAX_FILES_BUFFER;
+
+ ofn.lpstrFileTitle = NULL;
+ ofn.lpstrInitialDir = NULL;
+
+ LoadString( m_hInst, IDS_ADDFILES_TITLE, atcTitle, MAX_TITLE_LEN );
+ ofn.lpstrTitle = atcTitle;
+
+ ofn.Flags = OFN_ALLOWMULTISELECT |
+ OFN_HIDEREADONLY |
+ OFN_EXPLORER |
+ OFN_FILEMUSTEXIST |
+ OFN_PATHMUSTEXIST;
+
+ if( !GetOpenFileName( &ofn ) )
+ {
+ DWORD dw = CommDlgExtendedError();
+
+ if( dw == FNERR_BUFFERTOOSMALL )
+ DisplayMessage( m_hwndMain,
+ IDS_ADDFILES_BUFFERTOOSMALL,
+ IDS_ADDFILES_BUFFERTOOSMALL_TITLE,
+ 0);
+ return;
+ }
+
+ WriteFilesToList( atcFile );
+ EnableButtons();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::FormFilterString public
+//
+// Synopsis: Specifies which files (with which extension are to be displayed
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+VOID CLayoutApp::FormFilterString( TCHAR *patcFilter, INT nMaxLen )
+{
+ int nLen;
+ UINT uStrID;
+
+ //NOTE: the string resources must be in sequence
+ uStrID = IDS_FILTER_BEGIN+1;
+
+ // this is an internal function and so we aren't checking for
+ // enough room in the string buffer, patcFilter
+ while( uStrID != IDS_FILTER_END )
+ {
+ LoadString( m_hInst, uStrID++, patcFilter, nMaxLen );
+ nLen = STRING_LEN( patcFilter );
+ nMaxLen -= nLen + 1;
+ patcFilter += nLen;
+ *patcFilter++ = NULL_TERM;
+ }
+
+ *patcFilter = NULL_TERM;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::WriteFilesToList public
+//
+// Synopsis: Gets and writes the files, complete with path, to the File List
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+VOID CLayoutApp::WriteFilesToList( TCHAR *patcFilesList )
+{
+ TCHAR *patcDir;
+ TCHAR atcFile[MAX_PATH];
+ BOOL bOneFile = TRUE;
+
+ patcDir = patcFilesList;
+ while( *patcFilesList++ != NULL_TERM )
+ ;
+
+ while( *patcFilesList != NULL_TERM )
+ {
+ bOneFile = FALSE;
+ CopyString( atcFile, patcDir );
+ CatString( atcFile, BACKSLASH );
+ CatString( atcFile, patcFilesList );
+ AddFileToListBox( atcFile );
+ while( *patcFilesList++ != NULL_TERM )
+ ;
+ }
+
+ // if only one file was selected,
+ // the filename isn't separated by it's path,
+ // but is one complete filename
+ if( bOneFile )
+ AddFileToListBox( patcDir );
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::AddFileToListBox public
+//
+// Synopsis: displays the file to the dialog list box
+//
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+VOID CLayoutApp::AddFileToListBox( TCHAR *patcFile )
+{
+
+ // add the file iff the file is not already displayed
+ if (LB_ERR == SendMessage(m_hwndListFiles,
+ LB_FINDSTRING,
+ (WPARAM)0,
+ (LPARAM)(LPCTSTR)patcFile))
+ {
+ SendMessage(m_hwndListFiles,
+ LB_ADDSTRING,
+ (WPARAM)0,
+ (LPARAM)(LPCTSTR)patcFile);
+ }
+
+ SetListBoxExtent();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::RemoveFileFromListBox public
+//
+// Synopsis: remove the displayed the file from the dialog list box
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+VOID CLayoutApp::RemoveFileFromListBox( INT nIndex )
+{
+ SendMessage(m_hwndListFiles,
+ LB_DELETESTRING,
+ (WPARAM)nIndex,
+ (LPARAM)0);
+
+ SetListBoxExtent();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::SetListBoxExtent public
+//
+// Synopsis: Handles making a horizontal scroll bar if necessary
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+VOID CLayoutApp::SetListBoxExtent( void )
+{
+ INT i;
+ INT nExtent = 0;
+ INT nItems = SendMessage( m_hwndListFiles,
+ LB_GETCOUNT,
+ (WPARAM)0,
+ (LPARAM)0);
+ TCHAR atcFile[MAX_PATH];
+ HDC hdc = NULL;
+ SIZE size;
+
+
+ if( nItems == 0 )
+ goto lSetListBoxExtent_Exit;
+
+ if( (hdc = GetDC(m_hwndMain)) == NULL)
+ goto lSetListBoxExtent_Exit;
+
+ for( i=0; i < nItems; i++ )
+ {
+ SendMessage(m_hwndListFiles,
+ LB_GETTEXT,
+ (WPARAM)i,
+ (LPARAM)(LPCTSTR)atcFile);
+
+
+ GetTextExtentPoint32(
+ hdc,
+ atcFile,
+ STRING_LEN(atcFile),
+ &size);
+
+ nExtent = max(nExtent, (INT)size.cx);
+ }
+
+lSetListBoxExtent_Exit:
+
+ if( hdc )
+ ReleaseDC( m_hwndMain, hdc );
+
+ //BUGBUG: can scroll too far now? make it 0.8 * nExtent or so?
+ SendMessage(m_hwndListFiles,
+ LB_SETHORIZONTALEXTENT,
+ (WPARAM)nExtent,
+ (LPARAM)0);
+}
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::RemoveFiles public
+//
+// Synopsis: remove one or more files from displayed list
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+
+VOID CLayoutApp::RemoveFiles (void)
+{
+ INT i;
+ INT *pnSelItems;;
+ INT nSelItems = SendMessage( m_hwndListFiles,
+ LB_GETSELCOUNT,
+ (WPARAM)0,
+ (LPARAM)0);
+
+ if( nSelItems == 0 )
+ return;
+
+ pnSelItems = (LPINT) MALLOC( sizeof(INT)*nSelItems );
+
+ if( !pnSelItems )
+ return;
+
+ SendMessage(m_hwndListFiles,
+ LB_GETSELITEMS,
+ (WPARAM)nSelItems,
+ (LPARAM)(LPINT)pnSelItems);
+
+ // start from bottom of list to keep the indices correct
+ for( i=nSelItems; --i >= 0; )
+ RemoveFileFromListBox( pnSelItems[i] );
+
+ FREE( pnSelItems );
+
+ EnableButtons();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::DisplayMessage public
+//
+// Synopsis: message box general routine with no file names
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+INT CLayoutApp::DisplayMessage(HWND hWnd,
+ UINT uMessageID,
+ UINT uTitleID,
+ UINT uFlags)
+{
+ TCHAR atcMessage[MAX_PATH];
+ TCHAR atcTitle[MAX_PATH];
+
+ LoadString(m_hInst, uMessageID, atcMessage, MAX_PATH);
+ LoadString(m_hInst, uTitleID, atcTitle, MAX_PATH);
+
+ if( hWnd )
+ SetForegroundWindow(hWnd);
+
+ return MessageBox(hWnd, atcMessage, atcTitle, uFlags);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::DisplayMessageWithFileName public
+//
+// Synopsis: message box general routine with 1 file name
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+INT CLayoutApp::DisplayMessageWithFileName(HWND hWnd,
+ UINT uMessageIDBefore,
+ UINT uMessageIDAfter,
+ UINT uTitleID,
+ UINT uFlags,
+ TCHAR *patcFileName)
+{
+ TCHAR atcMessageBefore[MAX_PATH];
+ TCHAR atcMessageAfter[MAX_PATH];
+ TCHAR atcTitle[MAX_PATH];
+ TCHAR atcFileErrorMsg[MAX_PATH*2];
+
+
+ LoadString(m_hInst, uMessageIDBefore, atcMessageBefore, MAX_PATH);
+ LoadString(m_hInst, uMessageIDAfter, atcMessageAfter, MAX_PATH);
+ LoadString(m_hInst, uTitleID, atcTitle, MAX_PATH);
+
+ CopyString(atcFileErrorMsg, atcMessageBefore);
+ CatString(atcFileErrorMsg, patcFileName);
+ CatString(atcFileErrorMsg, atcMessageAfter);
+
+ if( hWnd )
+ SetForegroundWindow(hWnd);
+
+ return MessageBox(hWnd, atcFileErrorMsg, atcTitle, uFlags);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::DisplayMessageWithTwoFileNames public
+//
+// Synopsis: message box general routine with 2 file names
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+INT CLayoutApp::DisplayMessageWithTwoFileNames(HWND hWnd,
+ UINT uMessageID,
+ UINT uTitleID,
+ UINT uFlags,
+ TCHAR *patcFirstFileName,
+ TCHAR *patcLastFileName)
+{
+ TCHAR atcMessage[MAX_PATH];
+ TCHAR atcTitle[MAX_PATH];
+ TCHAR atcFileErrorMsg[MAX_PATH*2];
+
+
+ LoadString(m_hInst, uMessageID, atcMessage, MAX_PATH);
+ LoadString(m_hInst, uTitleID, atcTitle, MAX_PATH);
+
+ CopyString(atcFileErrorMsg, patcFirstFileName);
+ CatString(atcFileErrorMsg, atcMessage);
+ CatString(atcFileErrorMsg, patcLastFileName);
+
+ if( hWnd )
+ SetForegroundWindow(hWnd);
+
+ return MessageBox(hWnd, atcFileErrorMsg, atcTitle, uFlags);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::EnableButtons public
+//
+// Synopsis: Updates the buttons. Optimize turns to Cancel
+// during optimize function.
+// Remove is greyed if no files are displayed
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+VOID CLayoutApp::EnableButtons( BOOL bShowOptimizeBtn )
+{
+ INT nItems = SendMessage( m_hwndListFiles,
+ LB_GETCOUNT,
+ (WPARAM)0,
+ (LPARAM)0);
+ INT nSelItems = SendMessage( m_hwndListFiles,
+ LB_GETSELCOUNT,
+ (WPARAM)0,
+ (LPARAM)0);
+
+ EnableWindow( m_hwndBtnAdd, TRUE );
+ EnableWindow( m_hwndBtnRemove, nSelItems > 0 );
+ EnableWindow( m_hwndBtnOptimize, nItems > 0 && bShowOptimizeBtn );
+}
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::OptimizeFiles public
+//
+// Synopsis: Static function to call the optimizeFiles worker routine
+//
+// Returns: Appropriate status code
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+DWORD CLayoutApp::OptimizeFiles (void *args)
+{
+ SCODE sc;
+
+ sc = CoInitialize(NULL);
+
+ sc = pStaticThis->OptimizeFilesWorker();
+
+ CoUninitialize();
+
+ pStaticThis->HandleOptimizeReturnCode(sc);
+
+ pStaticThis->m_bCancelled = FALSE;
+
+ pStaticThis->SetActionButton( IDS_OPTIMIZE );
+ pStaticThis->m_bOptimizing = FALSE;
+
+ //SetCursor(LoadCursor(NULL, IDC_ARROW));
+
+ return 0;
+
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::OptimizeFilesWorker public
+//
+// Synopsis: Optimize all the displayed files. Make temp files,
+// optimize to temp file, then rename temp back to original file.
+//
+// Returns: Appropriate status code
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CLayoutApp::OptimizeFilesWorker (void)
+{
+ INT i, j;
+ SCODE sc = S_OK;
+ HRESULT hr;
+
+ TCHAR atcFileName[MAX_PATH];
+ TCHAR atcTempPath[MAX_PATH];
+ TCHAR atcTempFile[MAX_PATH];
+ TCHAR atcPrefix[MAX_PREFIX_LEN];
+ TCHAR **ppatcTempFiles = NULL;
+ INT *pintErrorFlag = NULL;
+ INT nItems = SendMessage( m_hwndListFiles,
+ LB_GETCOUNT,
+ (WPARAM)0,
+ (LPARAM)0 );
+
+ if( nItems == 0 )
+ return S_OK;
+
+ ppatcTempFiles = (TCHAR **) MALLOC( sizeof(TCHAR *) * nItems );
+ FillMemory( (LPVOID)ppatcTempFiles, sizeof(TCHAR *) * nItems, 0 );
+
+ if( !ppatcTempFiles )
+ return STG_E_INSUFFICIENTMEMORY;
+
+ pintErrorFlag = (INT *) MALLOC( sizeof(INT) * nItems );
+ FillMemory( (LPVOID)pintErrorFlag, sizeof(INT) * nItems, 0 );
+
+ if( !pintErrorFlag )
+ {
+ sc = STG_E_INSUFFICIENTMEMORY;
+ JumpOnFail(sc);
+ }
+
+
+ if( GetTempPath( MAX_PATH, atcTempPath ) == 0 )
+ {
+ sc = GetLastError();
+ JumpOnFail(sc);
+ }
+
+ LoadString( m_hInst, IDS_TEMPFILE_PREFIX, atcPrefix, MAX_PREFIX_LEN );
+
+ for( i=0; i < nItems; i++ )
+ {
+
+ // handle Cancel pressed and cleanup
+ if (m_bCancelled)
+ {
+ m_bCancelled = FALSE;
+
+ for( j=0; j < i ; j++ )
+ DeleteFile(ppatcTempFiles[j]);
+
+ sc = STG_E_NONEOPTIMIZED;
+ JumpOnFail(sc);
+ }
+
+ if( GetTempFileName( atcTempPath, atcPrefix, (UINT)0, atcTempFile ) == 0 )
+ {
+ sc = GetLastError();
+ JumpOnFail(sc);
+ }
+
+ ppatcTempFiles[i] =
+ (TCHAR *) MALLOC( (STRING_LEN(atcTempFile) + 1) * sizeof(TCHAR) );
+
+ if( !ppatcTempFiles[i] )
+ {
+ sc = STG_E_INSUFFICIENTMEMORY;
+ JumpOnFail(sc);
+ }
+
+ CopyString( ppatcTempFiles[i], atcTempFile );
+ }
+
+
+ for( i=0; i < nItems; i++ )
+ {
+ // handle Cancel pressed and cleanup
+ if (m_bCancelled)
+ {
+ m_bCancelled = FALSE;
+
+ for( j=i; j < nItems ; j++ )
+ {
+ DeleteFile(ppatcTempFiles[j]);
+ pintErrorFlag[j] = 1;
+ }
+ sc = STG_E_NONEOPTIMIZED;
+
+ for( j=nItems; --j >= 0; )
+ {
+ if (pintErrorFlag[j])
+ {
+ RemoveFileFromListBox(j);
+ }
+ else
+ {
+ sc = S_OK;
+ }
+
+ }
+ EnableButtons();
+ goto Err;
+ }
+
+ SendMessage( m_hwndListFiles,
+ LB_GETTEXT,
+ (WPARAM)i,
+ (LPARAM)(LPINT)atcFileName );
+
+ sc = DoOptimizeFile( atcFileName, ppatcTempFiles[i] );
+
+#if DBG==1
+ //check that files are identical here.
+ if ((SUCCEEDED(sc)) && (!IdenticalFiles( atcFileName, ppatcTempFiles[i])))
+ {
+ sc = STG_E_DOCFILECORRUPT;
+
+ }
+#endif
+
+ if (!SUCCEEDED(sc))
+ {
+ // This file could not be optimized. Display Error message
+ switch( sc )
+ {
+ // the file is read only
+ case STG_E_ACCESSDENIED:
+
+ DisplayMessageWithFileName(m_hwndMain,
+ IDS_FILE_BEFORE,
+ IDS_FILE_AFTER_READ_ONLY,
+ IDS_OPTIMIZE_FAILED_TITLE,
+ 0,
+ atcFileName);
+ break;
+
+ // the file is not in a legal docfile format.
+ case STG_E_FILEALREADYEXISTS:
+
+ DisplayMessageWithFileName(m_hwndMain,
+ IDS_FILE_BEFORE,
+ IDS_FILE_AFTER_NOTDOCFILE,
+ IDS_OPTIMIZE_FAILED_TITLE,
+ 0,
+ atcFileName);
+ break;
+
+ default:
+ DisplayMessageWithFileName(m_hwndMain,
+ IDS_FILE_BEFORE,
+ IDS_OPTIMIZE_ERROR,
+ IDS_OPTIMIZE_FAILED_TITLE,
+ 0,
+ atcFileName);
+ break;
+ }
+
+ pintErrorFlag[i] = 1;
+ DeleteFile( ppatcTempFiles[i] );
+ continue;
+ }
+
+
+ //remove the (unoptimized) original file
+ hr = DeleteFile( atcFileName );
+ if (!hr)
+ {
+ sc = GetLastError();
+
+ DisplayMessageWithFileName(m_hwndMain,
+ IDS_FILE_BEFORE,
+ IDS_DELETE_ERROR,
+ IDS_OPTIMIZE_FAILED_TITLE,
+ 0,
+ atcFileName);
+
+ DisplayMessageWithTwoFileNames(m_hwndMain,
+ IDS_RENAME_MESSAGE,
+ IDS_OPTIMIZE_FAILED_TITLE,
+ 0,
+ atcFileName,
+ ppatcTempFiles[i]);
+
+ SendMessage( m_hwndListFiles,
+ LB_DELETESTRING,
+ (WPARAM)i,
+ (LPARAM)0);
+
+ SendMessage( m_hwndListFiles,
+ LB_INSERTSTRING,
+ (WPARAM)i,
+ (LPARAM)(LPINT)ppatcTempFiles[i] );
+
+ continue;
+ }
+
+ // rename the optimized file to the original file name
+ hr = MoveFile( ppatcTempFiles[i], atcFileName );
+
+ if (!hr)
+ {
+ sc = GetLastError();
+
+ DisplayMessageWithFileName(m_hwndMain,
+ IDS_FILE_BEFORE,
+ IDS_RENAME_ERROR,
+ IDS_OPTIMIZE_FAILED_TITLE,
+ 0,
+ ppatcTempFiles[i]);
+
+ DisplayMessageWithTwoFileNames(m_hwndMain,
+ IDS_RENAME_MESSAGE,
+ IDS_OPTIMIZE_FAILED_TITLE,
+ 0,
+ atcFileName,
+ ppatcTempFiles[i]);
+
+ SendMessage( m_hwndListFiles,
+ LB_DELETESTRING,
+ (WPARAM)i,
+ (LPARAM)0);
+
+ SendMessage( m_hwndListFiles,
+ LB_INSERTSTRING,
+ (WPARAM)i,
+ (LPARAM)(LPINT)ppatcTempFiles[i] );
+
+ continue;
+ }
+
+ DeleteFile( ppatcTempFiles[i] );
+ }
+
+ // remove files from list box that could not be optimized
+ //bSuccess is set if at least one file was sucessfully optimized.
+ sc = STG_E_NONEOPTIMIZED;
+
+ for( i=nItems; --i >= 0; )
+ {
+ if (pintErrorFlag[i])
+ {
+ RemoveFileFromListBox(i);
+ }
+ else
+ {
+ sc = S_OK;
+ }
+
+ }
+ EnableButtons();
+Err:
+
+ if ( pintErrorFlag )
+ FREE( pintErrorFlag);
+
+ if( ppatcTempFiles )
+ {
+ for( i=0; i < nItems; i++ )
+ {
+ if( ppatcTempFiles[i] )
+ FREE( ppatcTempFiles[i] );
+ }
+
+ FREE( ppatcTempFiles );
+ }
+ return sc;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::DoOptimizeFile public
+//
+// Synopsis: Monitor and relayout docfile to temp file.
+//
+// Returns: Appropriate status code
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CLayoutApp::DoOptimizeFile( TCHAR *patcFileName, TCHAR *patcTempFile )
+{
+ IStorage *pStg = NULL;
+ ILayoutStorage *pLayoutStg = NULL;
+ IUnknown *punkApp = NULL;
+ IPersistStorage *pPersist = NULL;
+ IOleObject *pObj = NULL;
+ COleClientSite *pSite = NULL;
+ SCODE sc = S_OK;
+ STATSTG stat;
+ OLECHAR awcNewFileName[MAX_PATH];
+
+
+ sc = StgOpenLayoutDocfile
+ (TCharToOleChar(patcFileName, awcNewFileName, MAX_PATH),
+ STGM_DIRECT |
+ STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE,
+ NULL,
+ &pStg);
+
+
+ JumpOnFail(sc);
+
+ sc = pStg->QueryInterface( IID_ILayoutStorage, (void**) &pLayoutStg );
+ JumpOnFail(sc);
+ pStg->Release();
+
+ // begin monitoring
+ sc = pLayoutStg->BeginMonitor();
+ JumpOnFail(sc);
+
+ sc = pStg->Stat(&stat, STATFLAG_NONAME);
+ JumpOnFail(sc);
+
+ // open the application type of the input storage
+ sc = CoCreateInstance( stat.clsid,
+ NULL,
+ (CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER),
+ IID_IUnknown,
+ (void**) &punkApp );
+ JumpOnFail(sc);
+
+ // load the document through the IPersistStorage Interface
+ sc = punkApp->QueryInterface( IID_IPersistStorage, (void**) &pPersist );
+ JumpOnFail(sc);
+ punkApp->Release();
+
+
+ sc = pPersist->Load( pStg );
+ JumpOnFail(sc);
+
+ sc = punkApp->QueryInterface( IID_IOleObject, (void**) &pObj );
+ JumpOnFail(sc);
+ punkApp->Release();
+
+ // Open as a client
+ pSite = new COleClientSite;
+ pSite->m_patcFile = patcFileName;
+
+ sc = pObj->DoVerb(OLEIVERB_OPEN, NULL, (IOleClientSite*) pSite, 0, NULL, NULL);
+ JumpOnFail(sc);
+
+ pObj->Close( OLECLOSE_NOSAVE );
+
+ // end monitoring and relayout
+ if( pLayoutStg )
+ {
+ sc = pLayoutStg->EndMonitor();
+ JumpOnFail(sc);
+
+ sc = pLayoutStg->ReLayoutDocfile(
+ TCharToOleChar(patcTempFile, awcNewFileName, MAX_PATH) );
+ JumpOnFail(sc);
+ }
+
+Err:
+
+ if( pStg )
+ pStg->Release();
+
+ if( punkApp )
+ punkApp->Release();
+
+ if( pSite )
+ pSite->Release();
+
+ return sc;
+ }
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::HandleOptimizeReturnCode public
+//
+// Synopsis: message box general routine to display apprpriate message
+// based on the Optimize returned SCODE
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+
+VOID CLayoutApp::HandleOptimizeReturnCode( SCODE sc )
+{
+ switch( sc )
+ {
+ case S_OK:
+ DisplayMessage(m_hwndMain, IDS_OPTIMIZE_SUCCESS, IDS_OPTIMIZE_SUCCESS_TITLE, 0);
+ break;
+
+ case STG_E_FILENOTFOUND:
+ case STG_E_INSUFFICIENTMEMORY:
+ DisplayMessage(m_hwndMain, IDS_OPTIMIZE_OUTOFMEM, IDS_OPTIMIZE_OUTOFMEM_TITLE, 0);
+ break;
+
+ case STG_E_PATHNOTFOUND:
+ DisplayMessage(m_hwndMain, IDS_OPTIMIZE_NOPATH, IDS_OPTIMIZE_NOPATH_TITLE, 0);
+ break;
+ case STG_E_NONEOPTIMIZED:
+ // already displayed errors for why each file could not be optimized.
+ break;
+
+ default:
+ DisplayMessage(m_hwndMain, IDS_OPTIMIZE_FAILED, IDS_OPTIMIZE_FAILED_TITLE, 0);
+ break;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::TCharToOleChar public
+//
+// Synopsis: helper function for UNICODE/ANSI TCHAR to OLEchar conversion
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+
+OLECHAR *CLayoutApp::TCharToOleChar(TCHAR *patcSrc, OLECHAR *pawcDst, INT nDstLen)
+{
+#ifdef UNICODE
+
+ // this is already UNICODE
+ return patcSrc;
+
+#else
+
+ UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ *pawcDst = NULL_TERM;
+
+ // convert to UNICODE
+ MultiByteToWideChar(
+ uCodePage,
+ 0,
+ patcSrc,
+ -1,
+ pawcDst,
+ nDstLen-1 );
+
+ return pawcDst;
+
+#endif
+}
+//+---------------------------------------------------------------------------
+//
+// Member: CLayoutApp::SetActionButton public
+//
+// Synopsis: change the text of the button
+//
+// History: 03-April-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+
+VOID CLayoutApp::SetActionButton( UINT uID )
+{
+ TCHAR atcText[MAX_PATH];
+
+ LoadString( m_hInst, uID, atcText, MAX_PATH );
+
+ SetWindowText( m_hwndBtnOptimize, atcText );
+
+ UpdateWindow( m_hwndMain );
+}
diff --git a/private/ole32/stg/async/layoutui/layoutui.hxx b/private/ole32/stg/async/layoutui/layoutui.hxx
new file mode 100644
index 000000000..98119dd63
--- /dev/null
+++ b/private/ole32/stg/async/layoutui/layoutui.hxx
@@ -0,0 +1,183 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: layoutui.hxx
+//
+// Contents: Common header file Layout Tool UI
+//
+// Classes: CLayoutApp
+// COleClientSite
+//
+// History: 23-Mar-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+#ifndef __LAYOUTUI_HXX__
+#define __LAYOUTUI_HXX__
+
+
+#include <windows.h>
+#include <shellapi.h>
+#include <commdlg.h>
+#include <cderr.h>
+#include <winuser.h>
+
+#include "resource.h"
+
+#ifndef STG_E_NONEOPTIMIZED
+#define STG_E_NONEOPTIMIZED _HRESULT_TYPEDEF_(0x80030205L)
+#endif
+
+#define gdxWndMin 300;
+#define gdyWndMin 300;
+
+#define hwndNil NULL;
+#define hNil NULL;
+#define bMsgHandled 1
+#define bMsgNotHandled 0
+
+int Laylstrcmp (
+ const wchar_t * src,
+ const wchar_t * dst);
+
+wchar_t * Laylstrcat (
+ wchar_t * dst,
+ const wchar_t * src );
+
+wchar_t * Laylstrcpy(
+ wchar_t * dst,
+ const wchar_t * src );
+
+wchar_t * Laylstrcpyn (
+ wchar_t * dest,
+ const wchar_t * source,
+ size_t count);
+
+size_t Laylstrlen (
+ const wchar_t * wcs);
+
+
+class CLayoutApp
+{
+
+public:
+ CLayoutApp(HINSTANCE hInst);
+ BOOL InitApp(void);
+ INT DoAppMessageLoop(void);
+
+private:
+ HINSTANCE m_hInst;
+ HWND m_hwndMain;
+ HWND m_hwndBtnAdd;
+ HWND m_hwndBtnRemove;
+ HWND m_hwndBtnOptimize;
+ HWND m_hwndListFiles;
+ HWND m_hwndStaticFiles;
+ BOOL m_bOptimizing;
+ BOOL m_bCancelled;
+
+ static BOOL CALLBACK LayoutDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ static BOOL CALLBACK ListBoxWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ static BOOL CALLBACK ButtonWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ static DWORD OptimizeFiles (void *args);
+
+
+ BOOL InitWindow (void);
+
+ VOID ReSizeWindow( LPARAM lParam );
+ VOID AddFiles( void );
+ VOID RemoveFiles( void );
+ VOID EnableButtons( BOOL bShowOptimizeBtn = TRUE );
+ VOID FormFilterString( TCHAR *patcFilter, INT nMaxLen );
+ VOID WriteFilesToList( TCHAR *patc );
+ VOID AddFileToListBox( TCHAR *patcFile );
+ VOID RemoveFileFromListBox( INT nIndex );
+ VOID SetListBoxExtent( void );
+ VOID HandleOptimizeReturnCode( SCODE sc );
+ VOID SetActionButton( UINT uID );
+
+
+ INT DisplayMessage( HWND hWnd,
+ UINT uMessageID,
+ UINT uTitleID,
+ UINT uFlags );
+
+ INT DisplayMessageWithFileName(HWND hWnd,
+ UINT uMessageIDBefore,
+ UINT uMessageIDAfter,
+ UINT uTitleID,
+ UINT uFlags,
+ TCHAR *patcFileName);
+
+ INT CLayoutApp::DisplayMessageWithTwoFileNames(HWND hWnd,
+ UINT uMessageID,
+ UINT uTitleID,
+ UINT uFlags,
+ TCHAR *patcFirstFileName,
+ TCHAR *patcLastFileName);
+
+ SCODE OptimizeFilesWorker( void );
+ SCODE DoOptimizeFile( TCHAR *patcFileName, TCHAR *patcTempFile );
+
+ OLECHAR *TCharToOleChar(TCHAR *atcSrc, OLECHAR *awcDst, INT nDstLen);
+
+#if DBG==1
+
+ BOOL CLayoutApp::IdenticalFiles( TCHAR *patcFileOne,
+ TCHAR *patcFileTwo);
+#endif
+
+
+
+};
+
+
+
+
+
+class COleClientSite : public IOleClientSite
+{
+public:
+ TCHAR *m_patcFile;
+ inline COleClientSite(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID riid, void** ppObject);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+ //IOleClientSite
+ STDMETHOD (SaveObject)( void);
+
+ STDMETHOD (GetMoniker)(
+ /* [in] */ DWORD dwAssign,
+ /* [in] */ DWORD dwWhichMoniker,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk);
+
+ STDMETHOD (GetContainer)(
+ /* [out] */ IOleContainer __RPC_FAR *__RPC_FAR *ppContainer);
+
+ STDMETHOD (ShowObject)( void);
+
+ STDMETHOD (OnShowWindow)(
+ /* [in] */ BOOL fShow);
+
+ STDMETHOD (RequestNewObjectLayout)( void);
+private:
+ LONG _cReferences;
+
+
+};
+inline COleClientSite::COleClientSite(void)
+{
+ _cReferences = 1;
+}
+
+
+
+
+
+#endif // __LAYOUTUI_HXX__
+
+
diff --git a/private/ole32/stg/async/layoutui/layoutui.rc b/private/ole32/stg/async/layoutui/layoutui.rc
new file mode 100644
index 000000000..5885c8ceb
--- /dev/null
+++ b/private/ole32/stg/async/layoutui/layoutui.rc
@@ -0,0 +1,120 @@
+
+#include <windows.h>
+//
+// Version resources
+//
+#include <ntverp.h>
+#undef VER_PRODUCTNAME_STR
+#define VER_PRODUCTNAME_STR "Microsoft Compound File Layout User Tool for OLE\0"
+#define VER_COMMENT_STR "Microsoft Compound File User Tool for OLE\0"
+#define VER_FILEDESCRIPTION_STR "Microsoft Compound File Layout User Tool for OLE\0"
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_INTERNALNAME_STR "DFLAYOUT.EXE"
+#define VER_ORIGINALFILENAME_STR "DFLAYOUT.EXE"
+#include <common.ver>
+
+#include "resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_MAIN DIALOGEX 25, 25, 214, 161
+STYLE DS_SETFOREGROUND | DS_3DLOOK | WS_MINIMIZEBOX | WS_MAXIMIZEBOX |
+ WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
+CAPTION "Docfile Layout Tool"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Files to Optimize:",IDC_STATIC_FILES,6,4,64,8
+ LISTBOX IDC_LIST_FILES,6,14,133,141,LBS_SORT |
+ LBS_NOINTEGRALHEIGHT | LBS_EXTENDEDSEL |
+ LBS_DISABLENOSCROLL | WS_VSCROLL | WS_HSCROLL |
+ WS_TABSTOP,WS_EX_ACCEPTFILES
+ DEFPUSHBUTTON "&Add...",IDC_BTN_ADD,153,14,50,14,BS_CENTER
+ PUSHBUTTON "&Remove",IDC_BTN_REMOVE,153,33,50,14
+ PUSHBUTTON "&Optimize",IDC_BTN_OPTIMIZE,153,139,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE
+BEGIN
+ "A", IDC_BTN_ADD, VIRTKEY, CONTROL, NOINVERT
+ "O", IDC_BTN_OPTIMIZE, VIRTKEY, CONTROL, NOINVERT
+ "R", IDC_BTN_REMOVE, VIRTKEY, CONTROL, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_ADDFILES_TITLE "Add File to Optimize"
+ IDS_TEMPFILE_PREFIX "dfl"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_FILTER_BEGIN "FILTER_BEGIN"
+ IDS_ALL_FILES "All Files (*.*)"
+ IDS_ALL_FILES_EXT "*.*"
+ IDS_WORD_FILES "Word Files (*.doc)"
+ IDS_WORD_FILES_EXT "*.doc"
+ IDS_EXCEL_FILES "Excel Files (*.xls)"
+ IDS_EXCEL_FILES_EXT "*.xls"
+ IDS_PPT_FILES "Power Point Files (*.ppt)"
+ IDS_PPT_FILES_EXT "*.ppt"
+ IDS_PUB_FILES "Publisher Files (*.pub)"
+ IDS_PUB_FILES_EXT "*.pub"
+ IDS_FILTER_END "FILTER_END"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_MAIN_WINDOW_FAIL "Unable to create main window."
+ IDS_MAIN_WINDOW_FAIL_TITLE "Layout Tool Error"
+ IDS_ADDFILES_BUFFERTOOSMALL
+ "Buffer Too Small.\r\nPlease select fewer files at a time."
+ IDS_ADDFILES_BUFFERTOOSMALL_TITLE "Layout Tool Add Files Error"
+ IDS_OPTIMIZE_SUCCESS "These files have been successfully optimized."
+ IDS_OPTIMIZE_SUCCESS_TITLE "Compound File Layout Completed"
+ IDS_OPTIMIZE_OUTOFMEM "There is not enough memory to complete this operation."
+ IDS_OPTIMIZE_OUTOFMEM_TITLE "Out of Memory"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_OPTIMIZE_NOPATH "No temporary path was detected on your machine. Please ensure your temporary path is correctly registered with the system."
+ IDS_OPTIMIZE_NOPATH_TITLE "No Temporary Path Found"
+ IDS_ERROR_FILE_NOT_CREATED "A temporary file could not be created."
+ IDS_OPTIMIZE_FAILED "An unknown error has occurred."
+ IDS_OPTIMIZE_FAILED_TITLE "Layout Tool Error"
+ IDS_FILE_BEFORE "The file "
+ IDS_FILE_AFTER_NOTFOUND " could not be found."
+ IDS_FILE_AFTER_NOTDOCFILE " is not a valid Compound File."
+ IDS_FILE_AFTER_CORRUPT " is corrupt!"
+ IDS_FILE_AFTER_COMPLETE " has been successfully optimized."
+ IDS_FILE_AFTER_FILE_NOT_OPENED " could not be opened."
+ IDS_FILE_AFTER_READ_ONLY " has read only permissions."
+ IDS_OPTIMIZING_FILES "Optimizing files..."
+ IDS_RENAME_ERROR " could not be renamed."
+ IDS_RENAME_MESSAGE " has been optimized as "
+ IDS_DELETE_ERROR " could not be deleted."
+ IDS_OPTIMIZE_ERROR " could not be optimized."
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_OPTIMIZE "&Optimize"
+ IDS_CANCEL "Cancel"
+END
+
diff --git a/private/ole32/stg/async/layoutui/makefile b/private/ole32/stg/async/layoutui/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/async/layoutui/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/async/layoutui/olesite.cxx b/private/ole32/stg/async/layoutui/olesite.cxx
new file mode 100644
index 000000000..1567074b4
--- /dev/null
+++ b/private/ole32/stg/async/layoutui/olesite.cxx
@@ -0,0 +1,69 @@
+#include "layoutui.hxx"
+
+
+STDMETHODIMP COleClientSite::QueryInterface(REFIID riid, void** ppObject)
+{
+ if (riid==IID_IUnknown || riid==IID_IOleClientSite)
+ {
+ *ppObject=(IOleClientSite*) this;
+ AddRef();
+ }
+ else
+ {
+ return E_NOINTERFACE;
+ }
+ return NO_ERROR;
+}
+
+STDMETHODIMP_(ULONG) COleClientSite::AddRef()
+{
+ InterlockedIncrement( &_cReferences);
+ return _cReferences;
+}
+
+STDMETHODIMP_(ULONG) COleClientSite::Release()
+{
+ InterlockedDecrement(&_cReferences);
+ if (_cReferences == 0)
+ {
+ delete this;
+ }
+
+ return _cReferences;
+}
+
+STDMETHODIMP COleClientSite::SaveObject( void)
+{
+ return E_FAIL;
+}
+
+STDMETHODIMP COleClientSite::GetMoniker(
+ /* [in] */ DWORD dwAssign,
+ /* [in] */ DWORD dwWhichMoniker,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk)
+{
+ return S_OK;
+}
+
+STDMETHODIMP COleClientSite::GetContainer(
+ /* [out] */ IOleContainer __RPC_FAR *__RPC_FAR *ppContainer)
+{
+ *ppContainer=NULL;
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP COleClientSite::ShowObject( void)
+{
+ return S_OK;
+}
+
+STDMETHODIMP COleClientSite::OnShowWindow(
+ /* [in] */ BOOL fShow)
+{
+ return S_OK;
+}
+
+STDMETHODIMP COleClientSite::RequestNewObjectLayout( void)
+{
+ return E_NOTIMPL;
+}
diff --git a/private/ole32/stg/async/layoutui/resource.h b/private/ole32/stg/async/layoutui/resource.h
new file mode 100644
index 000000000..aec4bda5a
--- /dev/null
+++ b/private/ole32/stg/async/layoutui/resource.h
@@ -0,0 +1,63 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by layoutui.rc
+//
+#define IDS_ADDFILES_TITLE 20
+#define IDS_TEMPFILE_PREFIX 21
+#define IDS_FILTER_BEGIN 100
+#define IDD_MAIN 101
+#define IDS_ALL_FILES 101
+#define IDS_ALL_FILES_EXT 102
+#define IDS_WORD_FILES 103
+#define IDS_WORD_FILES_EXT 104
+#define IDS_EXCEL_FILES 105
+#define IDS_EXCEL_FILES_EXT 106
+#define IDS_PPT_FILES 107
+#define IDS_PPT_FILES_EXT 108
+#define IDS_PUB_FILES 109
+#define IDS_PUB_FILES_EXT 110
+#define IDS_FILTER_END 111
+#define IDR_ACCELERATOR1 133
+#define IDS_MAIN_WINDOW_FAIL 200
+#define IDC_BTN_ADD 201
+#define IDS_MAIN_WINDOW_FAIL_TITLE 201
+#define IDC_BTN_REMOVE 202
+#define IDS_ADDFILES_BUFFERTOOSMALL 202
+#define IDC_BTN_OPTIMIZE 203
+#define IDS_ADDFILES_BUFFERTOOSMALL_TITLE 203
+#define IDS_OPTIMIZE_SUCCESS 204
+#define IDS_OPTIMIZE_SUCCESS_TITLE 205
+#define IDS_OPTIMIZE_OUTOFMEM 206
+#define IDS_OPTIMIZE_OUTOFMEM_TITLE 207
+#define IDS_OPTIMIZE_NOPATH 208
+#define IDS_OPTIMIZE_NOPATH_TITLE 209
+#define IDS_ERROR_FILE_NOT_CREATED 210
+#define IDS_OPTIMIZE_FAILED 212
+#define IDS_OPTIMIZE_FAILED_TITLE 213
+#define IDS_FILE_BEFORE 214
+#define IDS_FILE_AFTER_NOTFOUND 215
+#define IDS_FILE_AFTER_NOTDOCFILE 216
+#define IDS_FILE_AFTER_CORRUPT 217
+#define IDS_FILE_AFTER_COMPLETE 218
+#define IDS_FILE_AFTER_FILE_NOT_OPENED 219
+#define IDS_OPTIMIZING_FILES 220
+#define IDS_RENAME_ERROR 221
+#define IDS_RENAME_MESSAGE 222
+#define IDS_DELETE_ERROR 223
+#define IDS_FILE_AFTER_READ_ONLY 224
+#define IDS_OPTIMIZE_ERROR 225
+#define IDS_OPTIMIZE 300
+#define IDC_LIST_FILES 301
+#define IDS_CANCEL 301
+#define IDC_STATIC_FILES 401
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 134
+#define _APS_NEXT_COMMAND_VALUE 40003
+#define _APS_NEXT_CONTROL_VALUE 1037
+#define _APS_NEXT_SYMED_VALUE 102
+#endif
+#endif
diff --git a/private/ole32/stg/async/layoutui/sources b/private/ole32/stg/async/layoutui/sources
new file mode 100644
index 000000000..c2de44f9e
--- /dev/null
+++ b/private/ole32/stg/async/layoutui/sources
@@ -0,0 +1,113 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Susi Argo (SusiA) 25-Mar-96
+
+!ENDIF
+
+
+MAJORCOMP = dflayui
+MINORCOMP = dflayui
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= dflayout
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= PROGRAM
+
+INCLUDES= ..\h;..\..\h;..\..\..\ih
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DNOEXCEPTIONS \
+ -DINC_OLE2 \
+ -DFLAT \
+ -DWIN32=100 \
+ -D_NT1X_=100 \
+ -DCAIROLE_DOWNLEVEL \
+ -DDCOM \
+ -DMSWMSG \
+ -DDCOM_SECURITY \
+ -DNEWPROPS \
+ -D_TRACKLINK_=1 \
+ $(TRACELOG)
+
+#BLDCRT= 1
+USE_LIBCMT=1
+
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+NTLEGO=1
+
+GPCH_BUILD=daytona
+
+
+
+PRECOMPILED_INCLUDE=
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
+
+SOURCES= \
+ laymain.cxx \
+ layoutui.cxx \
+ olesite.cxx \
+ cklayout.cxx \
+ ..\cruntime.cxx \
+ layoutui.rc
+
+
+UMTYPE= windows
+UMENTRY= winmain
+UMAPPL=
+UMTEST=
+
+LINKLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\dflayout.lib \
+ ..\debug\daytona\obj\*\debug.lib \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib
+
+
+!include sources.inc
+
diff --git a/private/ole32/stg/async/layoutui/sources.inc b/private/ole32/stg/async/layoutui/sources.inc
new file mode 100644
index 000000000..9a091ed81
--- /dev/null
+++ b/private/ole32/stg/async/layoutui/sources.inc
@@ -0,0 +1 @@
+SYNCHRONIZE_DRAIN=1
diff --git a/private/ole32/stg/async/test/astgtest.cxx b/private/ole32/stg/async/test/astgtest.cxx
new file mode 100644
index 000000000..514deb7ef
--- /dev/null
+++ b/private/ole32/stg/async/test/astgtest.cxx
@@ -0,0 +1,883 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofstest.cxx
+//
+// History: 30-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+#include "notify.hxx"
+
+#if DBG == 1
+DECLARE_INFOLEVEL(astg);
+#endif
+
+BYTE inbuf[4096];
+#define STREAMNAME L"MyStream"
+#define STGNAME L"EmbeddedStorage"
+#define STGNAME2 L"RenamedStorage"
+#define ROOTNAME "RootStorage"
+
+WCHAR pwcsRootName[1024];
+
+#define FailMsg(MSG) {printf MSG; exit(1);}
+
+#define DoCmd(MSG, CODE, FAILMSG) \
+printf(MSG " => %s (0x%lX)\n", (sc = ResultFromScode(CODE), ScText(sc)), sc); \
+if (FAILED(sc)) {printf(FAILMSG "\n");}
+
+#define SHIFT(c,v) ( (c)--, (v)++)
+
+#include <assert.h>
+
+void BeginTest(void)
+{
+ HRESULT hr;
+
+ hr = CoInitialize(NULL);
+ Result(hr, "CoInitialize");
+}
+
+
+void EndTest(int rc)
+{
+ if (rc == 0)
+ printf("Test SUCCEEDED\n");
+ else
+ printf("Test FAILED\n");
+ CoUninitialize();
+ exit(rc);
+}
+
+void PrintStat(STATSTG *pstat, BOOL fEnum)
+{
+ printf("%s: '%ws'\n", pstat->type == STGTY_STORAGE ? "Storage" : "Stream",
+ pstat->pwcsName);
+ //printf("Type: %lu, %lu\n", pstat->type, pstat->dwStgFmt);
+ printf("Type: %lu, %lu\n", pstat->type);
+ if (!fEnum)
+ printf("Mode: %lX\n", pstat->grfMode);
+ if (pstat->type == STGTY_STREAM)
+ {
+ printf("Size: %lu:%lu\n", pstat->cbSize.HighPart,
+ pstat->cbSize.LowPart);
+ if (!fEnum)
+ printf("Locks: %lX\n", pstat->grfLocksSupported);
+ }
+ else
+ {
+ if (pstat->ctime.dwHighDateTime != 0 ||
+ pstat->ctime.dwLowDateTime != 0)
+ printf("Ctime: %s\n", FileTimeText(&pstat->ctime));
+ if (pstat->mtime.dwHighDateTime != 0 ||
+ pstat->mtime.dwLowDateTime != 0)
+ printf("Mtime: %s\n", FileTimeText(&pstat->mtime));
+ if (pstat->atime.dwHighDateTime != 0 ||
+ pstat->atime.dwLowDateTime != 0)
+ printf("Atime: %s\n", FileTimeText(&pstat->atime));
+ }
+ if (!fEnum)
+ printf("Clsid: %s\n", GuidText(&pstat->clsid));
+}
+void PrintStatInfo(STATSTG *pstat)
+{
+ PrintStat(pstat, TRUE);
+}
+
+void t_filelkb(void)
+{
+#if DBG == 1
+ const WCHAR OLEFILELKBNAME[] = L"astgtest.dfl";
+ const TCHAR FILELKBNAME[] = TEXT("astgtest.dfl");
+ const int BLOCKSIZE = 4096;
+ const int NUMBLOCKS = 16;
+ BYTE buf[BLOCKSIZE];
+ SCODE sc;
+
+ HRESULT hr;
+ ILockBytes *pilb;
+
+#ifdef _CHICAGO_
+ if (!DeleteFileA(FILELKBNAME))
+#else
+ if (!DeleteFile(FILELKBNAME))
+#endif
+ DoCmd("Delete docfile", GetLastError(),
+ "Could not delete docfile.");
+
+
+
+ hr = StgGetDebugFileLockBytes(OLEFILELKBNAME, &pilb);
+ Result(hr, "StgGetDebugFileLockBytes");
+
+ //Test WriteAt
+ for (int i = 0; i < NUMBLOCKS; i++)
+ {
+ ULONG cbWritten;
+ ULARGE_INTEGER uli;
+ uli.QuadPart = (BLOCKSIZE * (NUMBLOCKS - i - 1));
+
+ memset(buf, i+'A', BLOCKSIZE);
+ hr = pilb->WriteAt(uli, buf, BLOCKSIZE, &cbWritten);
+ Result(hr, "ILockBytes::WriteAt");
+ if (cbWritten != BLOCKSIZE)
+ {
+ Fail("Incorrect byte count. Got %lu, expected %lu",
+ cbWritten,
+ BLOCKSIZE);
+ }
+ }
+
+ //Test ReadAt
+ for (i = 0; i < NUMBLOCKS; i++)
+ {
+ ULONG cbWritten;
+ ULARGE_INTEGER uli;
+ uli.QuadPart = BLOCKSIZE * i;
+
+ hr = pilb->ReadAt(uli, buf, BLOCKSIZE, &cbWritten);
+ Result(hr, "ILockBytes::ReadAt");
+ if (cbWritten != BLOCKSIZE)
+ {
+ Fail("Incorrect byte count. Got %lu, expected %lu",
+ cbWritten,
+ BLOCKSIZE);
+ }
+ //Check contents
+ BYTE buf2[BLOCKSIZE];
+ memset(buf2, (NUMBLOCKS - i - 1)+'A', BLOCKSIZE);
+ if (memcmp(buf, buf2, BLOCKSIZE))
+ {
+ Fail("Buffers compared incorrectly.");
+ }
+ }
+
+ //Test SetSize
+ {
+ const ULONG CHECKSIZE = 180000;
+ ULARGE_INTEGER uli;
+ uli.QuadPart = CHECKSIZE;
+ hr = pilb->SetSize(uli);
+ Result(hr, "SetSize");
+
+ //Verify size
+ STATSTG statstg;
+ hr = pilb->Stat(&statstg, STATFLAG_DEFAULT);
+ PrintStat(&statstg, FALSE);
+ Result(hr, "Stat");
+ if (statstg.cbSize.QuadPart != CHECKSIZE)
+ {
+ Fail("File size differs");
+ }
+ }
+
+ pilb->Release();
+#endif
+}
+
+void t_filllkb(void)
+{
+ HRESULT hr;
+ IFillLockBytes *pflb;
+ ILockBytes *pilb;
+
+ const WCHAR OLEFILLLKBNAME[] = L"fill.dfl";
+ const TCHAR FILLLKBNAME[] = TEXT("fill.dfl");
+ const int BLOCKSIZE = 4096;
+ const int NUMBLOCKS = 16;
+ BYTE buf[BLOCKSIZE];
+
+#ifdef _CHICAGO_
+ DeleteFileA(FILLLKBNAME);
+#else
+ DeleteFile(FILLLKBNAME);
+#endif
+
+
+ hr = StgGetIFillLockBytesOnFile(OLEFILLLKBNAME, &pflb);
+ Result(hr, "StgGetIFillLockBytesOnFile");
+
+ hr = pflb->QueryInterface(IID_ILockBytes, (void **)&pilb);
+ Result(hr, "QueryInterface for ILockBytes");
+
+ void *foo;
+ pflb->QueryInterface(IID_IFillLockBytes, (void **)&foo);
+ pflb->QueryInterface(IID_IProgressNotify, (void **)&foo);
+
+ {
+ //Test ReadAt - should fail
+ ULARGE_INTEGER uli;
+ ULONG cbWritten;
+ uli.QuadPart = 0;
+
+ hr = pilb->ReadAt(uli, buf, BLOCKSIZE, &cbWritten);
+ if (hr != E_PENDING)
+ {
+ Fail("Should have returned E_PENDING. Got %lx", hr);
+ }
+ }
+
+ {
+ //Test WriteAt - should fail
+ ULARGE_INTEGER uli;
+ ULONG cbWritten;
+ uli.QuadPart = 0;
+
+ hr = pilb->WriteAt(uli, buf, BLOCKSIZE, &cbWritten);
+ if (hr != E_PENDING)
+ {
+ Fail("Should have returned E_PENDING. Got %lx", hr);
+ }
+ }
+
+ {
+ ULONG cbWritten;
+ //Fill the first block.
+ memset(buf, 'A', BLOCKSIZE);
+
+ hr = pflb->FillAppend(buf, BLOCKSIZE, &cbWritten);
+ Result(hr, "FillAppend");
+ if (cbWritten != BLOCKSIZE)
+ {
+ Fail("Incorrect number of bytes written. Got %lu, requested %lu",
+ cbWritten,
+ BLOCKSIZE);
+ }
+ }
+
+ {
+ //Test ReadAt - should succeed
+ ULARGE_INTEGER uli;
+ ULONG cbRead;
+ uli.QuadPart = 0;
+
+ hr = pilb->ReadAt(uli, buf, BLOCKSIZE, &cbRead);
+ Result(hr, "ReadAt");
+ if (cbRead != BLOCKSIZE)
+ {
+ Fail("Incorrect bytes read. Got %lu, requested %lu",
+ cbRead,
+ BLOCKSIZE);
+ }
+
+ //Verify contents.
+ BYTE buf2[BLOCKSIZE];
+ memset(buf2, 'A', BLOCKSIZE);
+ if (memcmp(buf, buf2, BLOCKSIZE) != 0)
+ {
+ Fail("Buffer compare failed.");
+ }
+ }
+
+ {
+ //Test WriteAt
+ ULARGE_INTEGER uli;
+ ULONG cbWritten;
+ uli.QuadPart = 0;
+
+ memset(buf, 'B', BLOCKSIZE);
+ hr = pilb->WriteAt(uli, buf, BLOCKSIZE, &cbWritten);
+ Result(hr, "WriteAt");
+
+ if (cbWritten != BLOCKSIZE)
+ {
+ Fail("Incorrect number of bytes written. Got %lu, requested %lu",
+ cbWritten,
+ BLOCKSIZE);
+ }
+ }
+
+}
+//sanity check of IStorage/IStream code on async docfiles
+void t_asyncstg(void)
+{
+ IStorage *pdf = NULL;
+ IStorage *pdf2 = NULL;
+ IStream *pst = NULL;
+ IStorage *pstgRoot;
+ IStream *pstm;
+ IEnumSTATSTG *penm = NULL;
+
+ void *foo;
+ SCODE sc;
+ HRESULT hr;
+
+ ILockBytes *pilb;
+ IFillLockBytes *pflb;
+ CHAR *pszName = ROOTNAME;
+ const CHAR *test = "Async Docfile test string";
+ const WCHAR OLEFILLLKBNAME[] = L"async.dfl";
+ const TCHAR FILLLKBNAME[] = TEXT("async.dfl");
+ const int BLOCKSIZE = 4096;
+ const int NUMBLOCKS = 16;
+ BYTE buf[BLOCKSIZE];
+
+#ifdef _CHICAGO_
+ DeleteFileA(FILLLKBNAME);
+#else
+ DeleteFile(FILLLKBNAME);
+#endif
+
+ mbstowcs(pwcsRootName, pszName, 1024);
+
+ hr = StgGetIFillLockBytesOnFile(OLEFILLLKBNAME, &pflb);
+ Result(hr, "StgGetIFillLockBytesOnFile");
+
+ hr = pflb->QueryInterface(IID_ILockBytes, (void **)&pilb);
+ Result(hr, "QueryInterface for ILockBytes");
+
+ pflb->Terminate(FALSE);
+
+ // create a storage on the ILockBytes
+ hr = StgCreateDocfileOnILockBytes(pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstgRoot);
+ Result(hr, "StgCreateDocfileOnILockBytes");
+
+ hr = pstgRoot->Commit(0);
+ Result(hr, "Commit");
+ pstgRoot->Release();
+
+ //open the async stg
+ do
+ { sc = StgOpenAsyncDocfileOnIFillLockBytes(
+ pflb,
+ STGM_DIRECT| STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE,
+ NULL,
+ &pdf);
+
+ if (sc == E_PENDING)
+ Sleep(1000);
+
+ } while (sc == E_PENDING);
+
+
+
+ DoCmd("Create root", sc, "Unable to create root");
+
+ DoCmd("Create stream",pdf->CreateStream(STREAMNAME,
+ STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_CREATE,
+ 0,
+ 0,
+ &pst),"Unable to create stream");
+
+ ULONG ulBytes;
+
+ strcpy((char *)inbuf, test);
+
+ DoCmd("Write to stream", pst->Write(inbuf, strlen(test), &ulBytes),
+ "Unable to write");
+
+ if (ulBytes != strlen(test))
+ FailMsg(("Wrote %lu bytes, expected %lu\n", ulBytes, strlen(test)));
+
+ memset(inbuf, 0, strlen(test));
+
+ LARGE_INTEGER li;
+ LISet32(li, 0);
+
+ DoCmd("Seek", pst->Seek(li, STREAM_SEEK_SET, NULL),"Seek failed.");
+
+ DoCmd("Read", pst->Read(inbuf, strlen(test), &ulBytes), "Read failed.");
+
+ if (ulBytes != strlen(test))
+ FailMsg(("Read %lu, expected %lu\n", ulBytes, strlen(test)));
+
+ printf("String read was %s\n",inbuf);
+ if (strcmp((char *)inbuf, test))
+ FailMsg(("Strings are not identical\n"));
+
+ printf("Release stream = %lu\n",
+ pst->Release());
+ pst = NULL;
+
+ DoCmd("Open stream", pdf->OpenStream(STREAMNAME,
+ NULL,
+ STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE,
+ 0,
+ &pst),
+ "Could not open stream.");
+
+ memset(inbuf, 0, strlen(test));
+
+ LISet32(li, 0);
+
+ DoCmd("Seek", pst->Seek(li, STREAM_SEEK_SET, NULL), "Seek failed.");
+
+ DoCmd("Read", pst->Read(inbuf, strlen(test), &ulBytes),
+ "Read failed.");
+
+ if (ulBytes != strlen(test))
+ FailMsg(("Read %lu, expected %lu\n", ulBytes, strlen(test)));
+
+ printf("String read was %s\n",inbuf);
+ if (strcmp((char *)inbuf, test))
+ FailMsg(("Strings are not identical\n"));
+
+ printf("Release stream = %lu\n",
+ pst->Release());
+ pst = NULL;
+
+ DoCmd("Open storage", pdf->CreateStorage(STGNAME,
+ STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_FAILIFTHERE,
+ NULL,
+ NULL,
+ &pdf2),
+ "Unable to create internal storage");
+
+ DoCmd("SetClass", pdf2->SetClass(IID_IUnknown), "SetClass failed.");
+
+ STATSTG stat;
+
+ DoCmd("Embedding Stat()", pdf2->Stat(&stat, STATFLAG_DEFAULT),
+ "Stat failed.");
+ PrintStatInfo(&stat);
+
+ printf("Release internal storage = %lu\n", pdf2->Release());
+ pdf2 = NULL;
+
+ //Stat IStorage
+
+ DoCmd("Root storage Stat()", pdf->Stat(&stat, STATFLAG_DEFAULT),
+ "Stat failed.");
+ PrintStatInfo(&stat);
+
+ //Enumerate contents of root.
+
+ DoCmd("EnumElements()", pdf->EnumElements(0, NULL, 0, &penm),
+ "EnumElements failed.");
+
+ do
+ {
+ ULONG ulTemp;
+
+ DoCmd("Next()", penm->Next(1, &stat, &ulTemp),
+ "Next failed.");
+
+ if (SUCCEEDED(sc) && (sc != S_FALSE))
+ {
+ PrintStatInfo(&stat);
+ }
+ } while (sc == S_OK);
+ printf("\n\n");
+
+ //Rename the embedded storage
+ DoCmd("Rename storage", pdf->RenameElement(STGNAME, STGNAME2),
+ "Rename failed.");
+
+ //Rewind iterator
+ DoCmd("Reset",penm->Reset(),"Reset failed.");
+ do
+ {
+ ULONG ulTemp;
+
+ DoCmd("Next()", penm->Next(1, &stat, &ulTemp),
+ "Next failed.");
+
+ if (SUCCEEDED(sc) && (sc != S_FALSE))
+ {
+ PrintStatInfo(&stat);
+ }
+ } while (sc == S_OK);
+ printf("\n\n");
+
+ //Delete the embedded storage
+ DoCmd("Delete storage", pdf->DestroyElement(STGNAME2),
+ "Could not delete storage.");
+
+ //Rewind iterator
+ DoCmd("Reset",penm->Reset(),"Reset failed.");
+ do
+ {
+ ULONG ulTemp;
+
+ DoCmd("Next()", penm->Next(1, &stat, &ulTemp),
+ "Next failed.");
+ if (SUCCEEDED(sc) && (sc != S_FALSE))
+ {
+ PrintStatInfo(&stat);
+ }
+ } while (sc == S_OK);
+ printf("\n\n");
+
+ printf("Release enumerator = %lu\n",
+ penm->Release());
+ penm = NULL;
+
+
+ printf("Release root = %lu\n",
+ pdf->Release());
+
+ pdf = NULL;
+
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Class: CDebugFillLockBytes
+//
+// Purpose: exercise the Notify routine
+//
+// Interface:
+//
+// History: 11-Jan-96 Susia Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#define UNTERMINATED 0
+#define TERMINATED_NORMAL 1
+#define TERMINATED_ABNORMAL 2
+ULONG ulWaterMark;
+ULONG ulFailurePoint;
+
+
+CFillLockBytes *p_gflb;
+
+DWORD PulseNotification(void *args)
+{
+ DWORD casenum;
+ DWORD *caseptr;
+ caseptr = (DWORD *) args;
+ casenum = *caseptr;
+
+
+ switch( casenum )
+ {
+ case 1:
+ Sleep(100);
+ p_gflb->PulseFillEvent();
+ Sleep(100);
+ p_gflb->PulseFillEvent();
+ Sleep(100);
+ p_gflb->PulseFillEvent();
+ Sleep(100);
+ p_gflb->Terminate(FALSE);
+ break;
+ case 2:
+ Sleep(100);
+ p_gflb->PulseFillEvent();
+ Sleep(100);
+ p_gflb->PulseFillEvent();
+ Sleep(100);
+ p_gflb->PulseFillEvent();
+ Sleep(100);
+ p_gflb->Terminate(TRUE);
+ break;
+ case 3:
+ Sleep(100);
+ p_gflb->PulseFillEvent();
+ Sleep(100);
+ p_gflb->PulseFillEvent();
+ Sleep(100);
+ p_gflb->PulseFillEvent();
+ Sleep(100);
+ p_gflb->SetFailureInfo(10, 10);
+ p_gflb->PulseFillEvent();
+ break;
+ default :
+ break;
+
+ }
+ ExitThread(0);
+ return casenum;
+
+}
+
+void t_notify()
+{
+ CAsyncStorage *pstg;
+ CAsyncStream *pstm;
+ CAsyncEnum *penum;
+ CFillLockBytes *pflb;
+ ILockBytes *plkb = NULL;
+
+ DWORD casenum;
+ DWORD dwFlags;
+ DWORD thrdid;
+ DWORD term;
+ SCODE sc;
+ HRESULT hr;
+ HANDLE hthread;
+
+ pflb = new CFillLockBytes(plkb);
+ pflb->Init();
+ p_gflb = pflb;
+ pstg = new CAsyncStorage(NULL, pflb);
+
+ ulFailurePoint = 10;
+ ulWaterMark = 5;
+ pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
+
+ // case 1:first try with no connection point.
+ // Should block until TERMINATED event.
+ // _dwTerminated should be TERMINATED_NORMAL
+ // Notify should return S_OK
+ casenum = 1;
+
+ hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
+ (void *) &casenum,
+ 0, &thrdid);
+ sc = pstg->Notify();
+
+ DoCmd("Notify storage case 1 (normal termination)", sc , "Notify Failed");
+ pflb->GetTerminationStatus(&dwFlags);
+ if (dwFlags == TERMINATED_NORMAL)
+ sc = S_OK;
+ else sc = STG_E_TERMINATED;
+
+ DoCmd("Notify storage case 1 (normal termination)", sc, "Notify returned prematurely");
+
+
+ // stream notify
+ TerminateThread(hthread,0);
+ delete pflb;
+ pflb = new CFillLockBytes(plkb);
+ pflb->Init();
+ p_gflb = pflb;
+ pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
+ pstm = new CAsyncStream(NULL, pflb);
+
+ hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
+ (void *) &casenum,
+ 0, &thrdid);
+ sc = pstm->Notify();
+
+ DoCmd("Notify stream case 1 (normal termination)", sc , "Notify Failed");
+ pflb->GetTerminationStatus(&dwFlags);
+ if (dwFlags == TERMINATED_NORMAL)
+ sc = S_OK;
+ else sc = STG_E_TERMINATED;
+
+ DoCmd("Notify stream case 1 (normal termination)", sc, "Notify returned prematurely");
+
+ // enumerator notify
+ TerminateThread(hthread,0);
+ delete pflb;
+ pflb = new CFillLockBytes(plkb);
+ pflb->Init();
+ p_gflb = pflb;
+ pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
+ penum = new CAsyncEnum(NULL,pflb);
+
+ hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
+ (void *) &casenum,
+ 0, &thrdid);
+ sc = penum->Notify();
+
+ DoCmd("Notify enumSTATSTG case 1 (normal termination)", sc , "Notify Failed");
+ pflb->GetTerminationStatus(&dwFlags);
+ if (dwFlags == TERMINATED_NORMAL)
+ sc = S_OK;
+ else sc = STG_E_TERMINATED;
+
+ DoCmd("Notify enumSTATSTG case 1 (normal termination)", sc, "Notify returned prematurely");
+
+ //cleanup
+ TerminateThread(hthread,0);
+ delete pflb;
+ delete pstg;
+ delete pstm;
+ delete penum;
+
+ // case 2: try with no connection point.
+ // Should block until abnormal termination.
+ // _dwTerminated should be TERMINATED_ABNORMAL
+ // Notify should return STG_E_INCOMPLETE
+ casenum = 2;
+
+
+ pflb = new CFillLockBytes(plkb);
+ pflb->Init();
+ p_gflb = pflb;
+ pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
+ pstg = new CAsyncStorage(NULL, pflb);
+
+ hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
+ (void *) &casenum,
+ 0, &thrdid);
+ sc = pstg->Notify();
+ if (sc == STG_E_INCOMPLETE)
+ sc = S_OK;
+ else sc = STG_E_TERMINATED;
+
+ DoCmd("Notify storage case 2 (abnormal termination)", sc , "Notify Failed");
+ pflb->GetTerminationStatus(&dwFlags);
+ if (dwFlags == TERMINATED_ABNORMAL)
+ sc = S_OK;
+ else sc = STG_E_TERMINATED;
+
+ DoCmd("Notify storage case 2 (abnormal termination)", sc, "Notify returned prematurely");
+
+ // stream notify
+ TerminateThread(hthread,0);
+ delete pflb;
+ pflb = new CFillLockBytes(plkb);
+ pflb->Init();
+ p_gflb = pflb;
+ pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
+ pstm = new CAsyncStream(NULL, pflb);
+
+ hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
+ (void *) &casenum,
+ 0, &thrdid);
+ sc = pstm->Notify();
+
+ if (sc == STG_E_INCOMPLETE)
+ sc = S_OK;
+ else sc = STG_E_TERMINATED;
+
+ DoCmd("Notify stream case 2 (abnormal termination)", sc, "Notify Failed");
+ pflb->GetTerminationStatus(&dwFlags);
+ if (dwFlags == TERMINATED_ABNORMAL)
+ sc = S_OK;
+ else sc = STG_E_TERMINATED;
+
+ DoCmd("Notify stream case 2 (abnormal termination)", sc, "Notify returned prematurely");
+
+ // enumerator notify
+ TerminateThread(hthread,0);
+ delete pflb;
+ pflb = new CFillLockBytes(plkb);
+ pflb->Init();
+ p_gflb = pflb;
+ pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
+ penum = new CAsyncEnum(NULL,pflb);
+
+ hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
+ (void *) &casenum,
+ 0, &thrdid);
+ sc = penum->Notify();
+
+ if (sc == STG_E_INCOMPLETE)
+ sc = S_OK;
+ else sc = STG_E_TERMINATED;
+
+ DoCmd("Notify enumSTATSTG case 2 (abnormal termination)", sc , "Notify Failed");
+ pflb->GetTerminationStatus(&dwFlags);
+ if (dwFlags == TERMINATED_ABNORMAL)
+ sc = S_OK;
+ else sc = STG_E_TERMINATED;
+
+ DoCmd("Notify enumSTATSTG case 2 (abnormal termination)", sc, "Notify returned prematurely");
+
+
+ //cleanup:
+ TerminateThread(hthread,0);
+ delete pflb;
+ delete pstg;
+ delete pstm;
+ delete penum;
+
+ // case 3: Should block until file is completely downloaded
+ // (with watermark >= failurepoint)
+ // _dwTerminated should be UNTERMINATED
+ // Notify should return S_OK
+ casenum = 3;
+
+
+ pflb = new CFillLockBytes(plkb);
+ pflb->Init();
+ p_gflb = pflb;
+ pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
+ pstg = new CAsyncStorage(NULL, pflb);
+
+ hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
+ (void *) &casenum,
+ 0, &thrdid);
+ sc = pstg->Notify();
+
+ DoCmd("Notify storage case 3 (watermark reached end)", sc , "Notify Failed");
+ pflb->GetTerminationStatus(&dwFlags);
+ if (dwFlags == UNTERMINATED)
+ sc = S_OK;
+ else sc = STG_E_TERMINATED;
+
+ DoCmd("Notify storage case 3 (watermark reached end)", sc, "Notify returned prematurely");
+
+ // stream notify
+ TerminateThread(hthread,0);
+ delete pflb;
+ pflb = new CFillLockBytes(plkb);
+ pflb->Init();
+ p_gflb = pflb;
+ pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
+ pstm = new CAsyncStream(NULL, pflb);
+
+ hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
+ (void *) &casenum,
+ 0, &thrdid);
+ sc = pstm->Notify();
+
+ DoCmd("Notify stream case 3 (watermark reached end)", sc, "Notify Failed");
+ pflb->GetTerminationStatus(&dwFlags);
+ if (dwFlags == UNTERMINATED)
+ sc = S_OK;
+ else sc = STG_E_TERMINATED;
+
+ DoCmd("Notify stream case 3 (watermark reached end)", sc, "Notify returned prematurely");
+
+ // enumerator notify
+ TerminateThread(hthread,0);
+ delete pflb;
+ pflb = new CFillLockBytes(plkb);
+ pflb->Init();
+ p_gflb = pflb;
+ pflb->SetFailureInfo(ulWaterMark, ulFailurePoint);
+ penum = new CAsyncEnum(NULL,pflb);
+
+ hthread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) &PulseNotification,
+ (void *) &casenum,
+ 0, &thrdid);
+ sc = penum->Notify();
+
+ DoCmd("Notify enumSTATSTG case 3 (watermark reached end)", sc , "Notify Failed");
+ pflb->GetTerminationStatus(&dwFlags);
+ if (dwFlags == UNTERMINATED)
+ sc = S_OK;
+ else sc = STG_E_TERMINATED;
+
+ DoCmd("Notify enumSTATSTG case 3 (watermark reached end)", sc, "Notify returned prematurely");
+
+
+ //cleanup:
+ TerminateThread(hthread,0);
+ delete pflb;
+ delete pstg;
+ delete pstm;
+ delete penum;
+
+
+}
+
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ SCODE sc;
+ BeginTest();
+ t_filelkb();
+ t_filllkb();
+ t_asyncstg();
+ t_notify();
+
+
+ EndTest(0);
+ exit(0);
+
+}
+
diff --git a/private/ole32/stg/async/test/daytona/makefile b/private/ole32/stg/async/test/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/async/test/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/async/test/daytona/sources b/private/ole32/stg/async/test/daytona/sources
new file mode 100644
index 000000000..7473b2245
--- /dev/null
+++ b/private/ole32/stg/async/test/daytona/sources
@@ -0,0 +1,56 @@
+!IF 0
+
+Copyright (c) 1995 Microsoft Corporation
+
+!ENDIF
+
+MAJORCOMP= ole32
+MINORCOMP= stg
+TARGETNAME= astgtest
+TARGETPATH= obj
+TARGETTYPE= PROGRAM
+
+INCLUDES=.;..;..\..\docfile;..\..\h;..\..\idl\daytona\obj
+#.;..;..\..\..\h;..\..\..\common;..\..\..\..\ih
+
+BLDCRT= 1
+USE_CRTDLL= 1
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DFLAT \
+ -DUNICODE \
+ -D_UNICODE
+
+PRECOMPILED_INCLUDE= ..\pch.cxx
+
+
+SOURCES= \
+ ..\astgtest.cxx\
+ ..\tutils.cxx
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+
+
+LINKLIBS= $(BASEDIR)\public\sdk\lib\*\asyncstg.lib \
+ ..\..\debug\daytona\obj\*\debug.lib \
+ $(BASEDIR)\public\sdk\lib\*\astguuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcndr.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib \
+ $(BASEDIR)\public\sdk\lib\*\rpcns4.lib \
+ $(BASEDIR)\public\sdk\lib\*\netapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\pwin32.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib \
+ $(BASEDIR)\public\sdk\lib\*\imagehlp.lib
+
+
+
+
diff --git a/private/ole32/stg/async/test/dirs b/private/ole32/stg/async/test/dirs
new file mode 100644
index 000000000..00a0b6753
--- /dev/null
+++ b/private/ole32/stg/async/test/dirs
@@ -0,0 +1,24 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+DIRS=
+OPTIONAL_DIRS= daytona \
+ \
+
diff --git a/private/ole32/stg/async/test/notify.hxx b/private/ole32/stg/async/test/notify.hxx
new file mode 100644
index 000000000..30317e26a
--- /dev/null
+++ b/private/ole32/stg/async/test/notify.hxx
@@ -0,0 +1,119 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: notify.hxx
+//
+// Contents: Classes and error codes for testing the notifier
+//
+// Classes:
+//
+// Functions:
+//
+// History: 11-Jan-96 SusiA Created
+//
+//----------------------------------------------------------------------------
+#ifndef __DBGNOTIFY_HXX__
+#define __DBGNOTIFY_HXX__
+#include "stgwrap.cxx"
+#include "stgconn.cxx"
+#include "filllkb.cxx"
+#define WIN32_SCODE(err) HRESULT_FROM_WIN32(err)
+#define LAST_STG_SCODE Win32ErrorToScode(GetLastError())
+
+//+---------------------------------------------------------------------------
+//
+// Function: Win32ErrorToScode, public
+//
+// Synopsis: Map a Win32 error into a corresponding scode, remapping
+// into Facility_Storage if appropriate.
+//
+// Arguments: [dwErr] -- Win32 error to map
+//
+// Returns: Appropriate scode
+//
+// History: 22-Sep-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE Win32ErrorToScode(DWORD dwErr)
+{
+ astgAssert((dwErr != NO_ERROR) &&
+ "Win32ErrorToScode called on NO_ERROR");
+
+ SCODE sc = STG_E_UNKNOWN;
+
+ switch (dwErr)
+ {
+ case ERROR_INVALID_FUNCTION:
+ sc = STG_E_INVALIDFUNCTION;
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ sc = STG_E_FILENOTFOUND;
+ break;
+ case ERROR_PATH_NOT_FOUND:
+ sc = STG_E_PATHNOTFOUND;
+ break;
+ case ERROR_TOO_MANY_OPEN_FILES:
+ sc = STG_E_TOOMANYOPENFILES;
+ break;
+ case ERROR_ACCESS_DENIED:
+ case ERROR_NETWORK_ACCESS_DENIED:
+ sc = STG_E_ACCESSDENIED;
+ break;
+ case ERROR_INVALID_HANDLE:
+ sc = STG_E_INVALIDHANDLE;
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ sc = STG_E_INSUFFICIENTMEMORY;
+ break;
+ case ERROR_NO_MORE_FILES:
+ sc = STG_E_NOMOREFILES;
+ break;
+ case ERROR_WRITE_PROTECT:
+ sc = STG_E_DISKISWRITEPROTECTED;
+ break;
+ case ERROR_SEEK:
+ sc = STG_E_SEEKERROR;
+ break;
+ case ERROR_WRITE_FAULT:
+ sc = STG_E_WRITEFAULT;
+ break;
+ case ERROR_READ_FAULT:
+ sc = STG_E_READFAULT;
+ break;
+ case ERROR_SHARING_VIOLATION:
+ sc = STG_E_SHAREVIOLATION;
+ break;
+ case ERROR_LOCK_VIOLATION:
+ sc = STG_E_LOCKVIOLATION;
+ break;
+ case ERROR_HANDLE_DISK_FULL:
+ case ERROR_DISK_FULL:
+ sc = STG_E_MEDIUMFULL;
+ break;
+ case ERROR_FILE_EXISTS:
+ case ERROR_ALREADY_EXISTS:
+ sc = STG_E_FILEALREADYEXISTS;
+ break;
+ case ERROR_INVALID_PARAMETER:
+ sc = STG_E_INVALIDPARAMETER;
+ break;
+ case ERROR_INVALID_NAME:
+ case ERROR_BAD_PATHNAME:
+ case ERROR_FILENAME_EXCED_RANGE:
+ sc = STG_E_INVALIDNAME;
+ break;
+ case ERROR_INVALID_FLAGS:
+ sc = STG_E_INVALIDFLAG;
+ break;
+ default:
+ sc = WIN32_SCODE(dwErr);
+ break;
+ }
+
+ return sc;
+}
+
+#endif //__DBGNOTIFY_HXX__
diff --git a/private/ole32/stg/async/test/pch.cxx b/private/ole32/stg/async/test/pch.cxx
new file mode 100644
index 000000000..ac6aa8da5
--- /dev/null
+++ b/private/ole32/stg/async/test/pch.cxx
@@ -0,0 +1,26 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: pch.cxx
+//
+// History: 09-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include <windows.h>
+//#include <stgint.h>
+#include <objbase.h>
+
+#include <asyncapi.hxx>
+#include <asyncerr.hxx>
+#include <ifill.h>
+#include <intfy.h>
+#include "tutils.hxx"
+
diff --git a/private/ole32/stg/async/test/tutils.cxx b/private/ole32/stg/async/test/tutils.cxx
new file mode 100644
index 000000000..d77b7b31d
--- /dev/null
+++ b/private/ole32/stg/async/test/tutils.cxx
@@ -0,0 +1,316 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tutils.cxx
+//
+// Contents: Generic utilities for tests
+//
+// History: 06-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+static BOOL fExitOnFail = TRUE;
+
+BOOL GetExitOnFail(void)
+{
+ return fExitOnFail;
+}
+
+void SetExitOnFail(BOOL set)
+{
+ fExitOnFail = set;
+}
+
+// Print out an error message and terminate
+void Fail(char *fmt, ...)
+{
+ va_list args;
+
+ args = va_start(args, fmt);
+ fprintf(stderr, "** Fatal error **: ");
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ EndTest(1);
+}
+
+typedef struct
+{
+ SCODE sc;
+ char *text;
+} StatusCodeText;
+
+static StatusCodeText scodes[] =
+{
+ S_OK, "S_OK",
+ S_FALSE, "S_FALSE",
+ STG_E_INVALIDFUNCTION, "STG_E_INVALIDFUNCTION",
+ STG_E_FILENOTFOUND, "STG_E_FILENOTFOUND",
+ STG_E_PATHNOTFOUND, "STG_E_PATHNOTFOUND",
+ STG_E_TOOMANYOPENFILES, "STG_E_TOOMANYOPENFILES",
+ STG_E_ACCESSDENIED, "STG_E_ACCESSDENIED",
+ STG_E_INVALIDHANDLE, "STG_E_INVALIDHANDLE",
+ STG_E_INSUFFICIENTMEMORY, "STG_E_INSUFFICIENTMEMORY",
+ STG_E_INVALIDPOINTER, "STG_E_INVALIDPOINTER",
+ STG_E_NOMOREFILES, "STG_E_NOMOREFILES",
+ STG_E_DISKISWRITEPROTECTED, "STG_E_DISKISWRITEPROTECTED",
+ STG_E_SEEKERROR, "STG_E_SEEKERROR",
+ STG_E_WRITEFAULT, "STG_E_WRITEFAULT",
+ STG_E_READFAULT, "STG_E_READFAULT",
+ STG_E_SHAREVIOLATION, "STG_E_SHAREVIOLATION",
+ STG_E_LOCKVIOLATION, "STG_E_LOCKVIOLATION",
+ STG_E_FILEALREADYEXISTS, "STG_E_FILEALREADYEXISTS",
+ STG_E_INVALIDPARAMETER, "STG_E_INVALIDPARAMETER",
+ STG_E_MEDIUMFULL, "STG_E_MEDIUMFULL",
+ STG_E_ABNORMALAPIEXIT, "STG_E_ABNORMALAPIEXIT",
+ STG_E_INVALIDHEADER, "STG_E_INVALIDHEADER",
+ STG_E_INVALIDNAME, "STG_E_INVALIDNAME",
+ STG_E_UNKNOWN, "STG_E_UNKNOWN",
+ STG_E_UNIMPLEMENTEDFUNCTION, "STG_E_UNIMPLEMENTEDFUNCTION",
+ STG_E_INVALIDFLAG, "STG_E_INVALIDFLAG",
+ STG_E_INUSE, "STG_E_INUSE",
+ STG_E_NOTCURRENT, "STG_E_NOTCURRENT",
+ STG_E_REVERTED, "STG_E_REVERTED",
+ STG_E_CANTSAVE, "STG_E_CANTSAVE",
+ STG_E_OLDFORMAT, "STG_E_OLDFORMAT",
+ STG_E_OLDDLL, "STG_E_OLDDLL",
+ STG_E_SHAREREQUIRED, "STG_E_SHAREREQUIRED",
+ STG_E_NOTFILEBASEDSTORAGE, "STG_E_NOTFILEBASEDSTORAGE",
+ STG_E_EXTANTMARSHALLINGS, "STG_E_EXTANTMARSHALLINGS",
+ STG_S_CONVERTED, "STG_S_CONVERTED"
+};
+#define NSCODETEXT (sizeof(scodes)/sizeof(scodes[0]))
+
+// Convert a status code to text
+char *ScText(SCODE sc)
+{
+ int i;
+
+ for (i = 0; i<NSCODETEXT; i++)
+ if (scodes[i].sc == sc)
+ return scodes[i].text;
+ return "<Unknown SCODE>";
+}
+
+// Output a call result and check for failure
+HRESULT Result(HRESULT hr, char *fmt, ...)
+{
+ SCODE sc;
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ sc = GetScode(hr);
+ printf(" - %s (0x%lX)\n", ScText(sc), sc);
+ if (FAILED(sc) && fExitOnFail)
+ Fail("Unexpected call failure\n");
+ return hr;
+}
+
+// Perform Result() when the expectation is failure
+HRESULT IllResult(HRESULT hr, char *fmt, ...)
+{
+ SCODE sc;
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ sc = GetScode(hr);
+ printf(" - %s (0x%lX)\n", ScText(sc), sc);
+ if (SUCCEEDED(sc) && fExitOnFail)
+ Fail("Unexpected call success\n");
+ return hr;
+}
+
+char *TcsText(TCHAR *ptcs)
+{
+ static char buf[256];
+
+ TTOA(ptcs, buf, 256);
+ return buf;
+}
+
+char *FileTimeText(FILETIME *pft)
+{
+ static char buf[80];
+ struct tm ctm;
+#ifndef FLAT
+ WORD dosdate, dostime;
+
+ if (CoFileTimeToDosDateTime(pft, &dosdate, &dostime))
+ {
+ ctm.tm_sec = (dostime & 31)*2;
+ ctm.tm_min = (dostime >> 5) & 63;
+ ctm.tm_hour = dostime >> 11;
+ ctm.tm_mday = dosdate & 31;
+ ctm.tm_mon = ((dosdate >> 5) & 15)-1;
+ ctm.tm_year = (dosdate >> 9)+80;
+ ctm.tm_wday = 0;
+#else
+ SYSTEMTIME st;
+
+ if (FileTimeToSystemTime(pft, &st))
+ {
+ ctm.tm_sec = st.wSecond;
+ ctm.tm_min = st.wMinute;
+ ctm.tm_hour = st.wHour;
+ ctm.tm_mday = st.wDay;
+ ctm.tm_mon = st.wMonth-1;
+ ctm.tm_year = st.wYear-1900;
+ ctm.tm_wday = st.wDayOfWeek;
+#endif
+ ctm.tm_yday = 0;
+ ctm.tm_isdst = 0;
+ strcpy(buf, asctime(&ctm));
+ buf[strlen(buf)-1] = 0;
+ }
+ else
+ sprintf(buf, "<FILETIME %08lX:%08lX>", pft->dwHighDateTime,
+ pft->dwLowDateTime);
+ return buf;
+}
+
+#pragma pack(1)
+struct SplitGuid
+{
+ DWORD dw1;
+ WORD w1;
+ WORD w2;
+ BYTE b[8];
+};
+#pragma pack()
+
+char *GuidText(GUID *pguid)
+{
+ static char buf[39];
+ SplitGuid *psg = (SplitGuid *)pguid;
+
+ sprintf(buf, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
+ psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
+ return buf;
+}
+
+#define CROW 16
+
+void BinText(ULONG cbSize, BYTE *pb)
+{
+ ULONG cb, i;
+
+ while (cbSize > 0)
+ {
+ cb = min(CROW, cbSize);
+ cbSize -= cb;
+ for (i = 0; i<cb; i++)
+ printf(" %02X", pb[i]);
+ for (i = cb; i<CROW; i++)
+ printf(" ");
+ printf(" '");
+ for (i = 0; i<cb; i++)
+ if (pb[i] >= 0x20 && pb[i] <= 0x7f)
+ putchar(pb[i]);
+ else
+ putchar('.');
+ pb += cb;
+ printf("'\n");
+ }
+}
+
+// BUGBUG - Remove for Cairole when they exist
+STDAPI CoMemAlloc(DWORD cbSize, void **ppv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc;
+
+ if (SUCCEEDED(GetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ *ppv = pMalloc->Alloc(cbSize);
+ pMalloc->Release();
+
+ if (*ppv == NULL)
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ }
+ else
+ *ppv = NULL;
+
+ return hr;
+}
+
+STDAPI CoMemFree(void *pv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc;
+
+ if (SUCCEEDED(GetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ pMalloc->Free(pv);
+ pMalloc->Release();
+ }
+
+ return hr;
+}
+
+TCHAR *TestFile(TCHAR *ptcsName, char *pszFile)
+{
+ char achFn[MAX_PATH];
+ char *dir, *file;
+ int len;
+
+ dir = getenv("DFDATA");
+ if (dir)
+ strcpy(achFn, dir);
+ else
+ strcpy(achFn, ".");
+ len = strlen(achFn);
+ if (achFn[len-1] != '\\')
+ achFn[len++] = '\\';
+
+ if (pszFile)
+ {
+ strcpy(achFn+len, pszFile);
+ }
+ else
+ {
+ file = getenv("DFFILE");
+ if (file)
+ strcpy(achFn+len, file);
+ else
+ strcpy(achFn+len, "TEST.DFL");
+ }
+
+ ATOT(achFn, ptcsName, MAX_PATH);
+ return ptcsName+len;
+}
+
+#if WIN32 == 300
+char *TestFormat(DWORD *pdwFmt, DWORD *pgrfMode)
+{
+ char *fmt;
+
+ fmt = getenv("STGFMT");
+ if (fmt == NULL || !strcmp(fmt, "doc"))
+ {
+ fmt = "document";
+ *pdwFmt = STGFMT_DOCUMENT;
+ }
+ else if (!strcmp(fmt, "file"))
+ {
+ fmt = "file";
+ *pdwFmt = STGFMT_FILE;
+ }
+ else
+ {
+ fmt = "directory";
+ *pdwFmt = STGFMT_DIRECTORY;
+ *pgrfMode &= ~STGM_CREATE;
+ }
+ return fmt;
+}
+#endif
+
diff --git a/private/ole32/stg/async/test/tutils.hxx b/private/ole32/stg/async/test/tutils.hxx
new file mode 100644
index 000000000..b006da5f0
--- /dev/null
+++ b/private/ole32/stg/async/test/tutils.hxx
@@ -0,0 +1,84 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tutils.hxx
+//
+// Contents: Generic test utilities
+//
+// History: 06-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __TUTILS_HXX__
+#define __TUTILS_HXX__
+
+#ifndef UNICODE
+#define tcscpy(d, s) strcpy(d, s)
+#define tcslen(s) strlen(s)
+#define TTEXT(s) s
+#define TFMT "%s"
+#define ATOT(a, t, max) strcpy(t, a)
+#define TTOA(t, a, max) strcpy(a, t)
+#define WTOT(w, t, max) wcstombs(t, w, max)
+#define TTOW(t, w, max) mbstowcs(w, t, max)
+#else
+#define tcscpy(d, s) wcscpy(d, s)
+#define tcslen(s) wcslen(s)
+#define TTEXT(s) L##s
+#define TFMT "%ws"
+#define ATOT(a, t, max) mbstowcs(t, a, max)
+#define TTOA(t, a, max) wcstombs(a, t, max)
+#define WTOT(w, t, max) wcscpy(t, w)
+#define TTOW(t, w, max) wcscpy(w, t)
+#endif
+#ifdef WIN32
+#define ATOX(a, t, max) mbstowcs(t, a, max)
+#define XTOA(t, a, max) wcstombs(a, t, max)
+#define WTOX(w, t, max) wcscpy(t, w)
+#define XTOW(t, w, max) wcscpy(w, t)
+#else
+#define ATOX(a, t, max) strcpy(t, a)
+#define XTOA(t, a, max) strcpy(a, t)
+#define WTOX(w, t, max) wcstombs(t, w, max)
+#define XTOW(t, w, max) mbstowcs(w, t, max)
+#endif
+
+#ifdef CINTERFACE
+#define Mthd(this, name) ((this)->lpVtbl->name)
+#define SELF(p) (p),
+#else
+#define Mthd(this, name) (this)->name
+#define SELF(p)
+#endif
+
+// BUGBUG - Remove for Cairole when they exist
+STDAPI CoMemAlloc(DWORD cBytes, void **ppv);
+STDAPI CoMemFree(void *pv);
+
+BOOL GetExitOnFail(void);
+void SetExitOnFail(BOOL set);
+void Fail(char *fmt, ...);
+char *ScText(SCODE sc);
+HRESULT Result(HRESULT hr, char *fmt, ...);
+HRESULT IllResult(HRESULT hr, char *fmt, ...);
+char *TcsText(TCHAR *ptcs);
+char *FileTimeText(FILETIME *pft);
+char *GuidText(GUID *pguid);
+void BinText(ULONG cb, BYTE *pb);
+TCHAR *TestFile(TCHAR *ptcsName, char *pszFile);
+
+#if WIN32 == 300
+char *TestFormat(DWORD *pdwFmt, DWORD *pgrfMode);
+#endif
+
+void CreateTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName);
+void OpenTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName);
+
+// Defined by test, called by Fail
+void EndTest(int code);
+
+#endif // #ifndef __TUTILS_HXX__
diff --git a/private/ole32/stg/common/assert.cxx b/private/ole32/stg/common/assert.cxx
new file mode 100644
index 000000000..f6b0646d2
--- /dev/null
+++ b/private/ole32/stg/common/assert.cxx
@@ -0,0 +1,239 @@
+//+---------------------------------------------------------------------------
+// Copyright (C) 1991, Microsoft Corporation.
+//
+// File: assert.cxx
+//
+// Contents: Debugging output routines for idsmgr.dll
+//
+// Functions: _Assert
+// _PopUpError
+//
+// History: 23-Jul-91 KyleP Created.
+// 09-Oct-91 KevinRo Major changes and comments added
+// 18-Oct-91 vich moved debug print routines out
+// 10-Jun-92 BryanT Switched to w4crt.h instead of wchar.h
+//
+//----------------------------------------------------------------------------
+
+//
+// This one file **always** uses debugging options
+//
+
+#if DBG == 1
+
+#include <stdarg.h>
+
+# include <debnot.h>
+# include <dprintf.h> // w4printf, w4dprintf prototypes
+
+extern "C"
+{
+#include <windows.h>
+
+#ifndef WIN32
+#define MessageBoxA MessageBox
+#define wsprintfA wsprintf
+#endif
+}
+
+int APINOT _PopUpError(char const *szMsg,int iLine, char const *szFile);
+
+unsigned long Win4InfoLevel = DEF_INFOLEVEL;
+unsigned long Win4InfoMask = 0xffffffff;
+unsigned long Win4AssertLevel = ASSRT_MESSAGE | ASSRT_BREAK | ASSRT_POPUP;
+
+//+---------------------------------------------------------------------------
+//
+// Function: _asdprintf
+//
+// Synopsis: Calls vdprintf to output a formatted message.
+//
+// History: 18-Oct-91 vich Created
+//
+//----------------------------------------------------------------------------
+inline void _asdprintf(char const *pszfmt, ...)
+{
+ va_list va;
+ va_start(va, pszfmt);
+
+ vdprintf(DEB_FORCE, "Assert", pszfmt, va);
+
+ va_end(va);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: _Win4Assert, private
+//
+// Synopsis: Display assertion information
+//
+// Effects: Called when an assertion is hit.
+//
+// History: 12-Jul-91 AlexT Created.
+// 05-Sep-91 AlexT Catch Throws and Catches
+// 19-Oct-92 HoiV Added events for TOM
+//
+//----------------------------------------------------------------------------
+
+
+void APINOT _Win4Assert(char const * szFile, int iLine, char const * szMessage)
+{
+ if (Win4AssertLevel & ASSRT_MESSAGE)
+ {
+ _asdprintf("%s File: %s Line: %u\n", szMessage, szFile, iLine);
+ }
+
+ if (Win4AssertLevel & ASSRT_POPUP)
+ {
+ int id = _PopUpError(szMessage,iLine,szFile);
+
+ if (id == IDCANCEL)
+ {
+#ifndef FLAT
+ _asm int 3;
+#else
+ DebugBreak();
+#endif
+ }
+ }
+ else if (Win4AssertLevel & ASSRT_BREAK)
+ {
+#ifndef FLAT
+ _asm int 3;
+#else
+ DebugBreak();
+#endif
+ }
+}
+
+
+//+------------------------------------------------------------
+// Function: _SetWin4InfoLevel(unsigned long ulNewLevel)
+//
+// Synopsis: Sets the global info level for debugging output
+// Returns: Old info level
+//
+//-------------------------------------------------------------
+
+unsigned long APINOT _SetWin4InfoLevel(unsigned long ulNewLevel)
+{
+ unsigned long ul;
+
+ ul = Win4InfoLevel;
+ Win4InfoLevel = ulNewLevel;
+ return(ul);
+}
+
+
+//+------------------------------------------------------------
+// Function: _SetWin4InfoMask(unsigned long ulNewMask)
+//
+// Synopsis: Sets the global info mask for debugging output
+// Returns: Old info mask
+//
+//-------------------------------------------------------------
+
+unsigned long APINOT _SetWin4InfoMask(unsigned long ulNewMask)
+{
+ unsigned long ul;
+
+ ul = Win4InfoMask;
+ Win4InfoMask = ulNewMask;
+ return(ul);
+}
+
+
+//+------------------------------------------------------------
+// Function: _SetWin4AssertLevel(unsigned long ulNewLevel)
+//
+// Synopsis: Sets the global assert level for debugging output
+// Returns: Old assert level
+//
+//-------------------------------------------------------------
+
+unsigned long APINOT _SetWin4AssertLevel(unsigned long ulNewLevel)
+{
+ unsigned long ul;
+
+ ul = Win4AssertLevel;
+ Win4AssertLevel = ulNewLevel;
+ return(ul);
+}
+
+//+------------------------------------------------------------
+// Function: _PopUpError
+//
+// Synopsis: Displays a dialog box using provided text,
+// and presents the user with the option to
+// continue or cancel.
+//
+// Arguments:
+// szMsg -- The string to display in main body of dialog
+// iLine -- Line number of file in error
+// szFile -- Filename of file in error
+//
+// Returns:
+// IDCANCEL -- User selected the CANCEL button
+// IDOK -- User selected the OK button
+//-------------------------------------------------------------
+
+int APINOT _PopUpError(char const *szMsg,int iLine, char const *szFile)
+{
+
+ int id;
+ static char szAssertCaption[100];
+#ifdef WIN32
+#undef wsprintfA
+#undef MessageBoxA
+#endif
+ wsprintfA(szAssertCaption, "File: %s line %u", szFile,iLine);
+
+ id = MessageBoxA(NULL,
+ (char *) szMsg,
+ (LPSTR) szAssertCaption,
+ MB_TASKMODAL | MB_ICONEXCLAMATION | MB_OKCANCEL);
+ return id;
+}
+
+
+//+------------------------------------------------------------
+// Function: vdprintf
+//
+// Synopsis: Prints debug output using a pointer to the
+// variable information. Used primarily by the
+// xxDebugOut macros
+//
+// Arguements:
+// ulCompMask -- Component level mask used to determine
+// output ability
+// pszComp -- String const of component prefix.
+// ppszfmt -- Pointer to output format and data
+//
+//-------------------------------------------------------------
+
+void APINOT vdprintf(unsigned long ulCompMask,
+ char const *pszComp,
+ char const *ppszfmt,
+ va_list pargs)
+{
+ if ((ulCompMask & DEB_FORCE) == DEB_FORCE ||
+ ((ulCompMask | Win4InfoLevel) & Win4InfoMask))
+ {
+
+ {
+ if (! (ulCompMask & DEB_NOCOMPNAME))
+ {
+ w4dprintf("%s: ", pszComp);
+ }
+ w4vdprintf(ppszfmt, pargs);
+
+ // Chicago and Win32s debugging is usually through wdeb386
+ // which needs carriage returns
+#if WIN32 == 50 || WIN32 == 200
+ w4dprintf("\r");
+#endif
+ }
+ }
+}
+
+#endif // DBG == 1
diff --git a/private/ole32/stg/common/daytona/makefile b/private/ole32/stg/common/daytona/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ole32/stg/common/daytona/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/stg/common/daytona/sources b/private/ole32/stg/common/daytona/sources
new file mode 100644
index 000000000..4aceebf52
--- /dev/null
+++ b/private/ole32/stg/common/daytona/sources
@@ -0,0 +1,83 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= dfcommon
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES=..\..\..\ih;..\..\..\common\daytona;..\..\h;..
+
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+SOURCES= \
+ ..\assert.cxx \
+ ..\output.c \
+ ..\dprintf.c \
+ ..\sprintf.c
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+PRECOMPILED_INCLUDE=
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
diff --git a/private/ole32/stg/common/depend.mk1 b/private/ole32/stg/common/depend.mk1
new file mode 100644
index 000000000..8cf50747b
--- /dev/null
+++ b/private/ole32/stg/common/depend.mk1
@@ -0,0 +1,16 @@
+#
+# Source files
+#
+
+$(OBJDIR)\mem.obj $(OBJDIR)\mem.lst: .\mem.cxx $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\cguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\errors.h $(OLE2H)\hresult.h \
+ $(OLE2H)\memalloc.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\olescode.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\winnot.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winreg.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
diff --git a/private/ole32/stg/common/depend.mk3 b/private/ole32/stg/common/depend.mk3
new file mode 100644
index 000000000..b5ae9453b
--- /dev/null
+++ b/private/ole32/stg/common/depend.mk3
@@ -0,0 +1,65 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\assert.obj $(OBJDIR)\assert.lst: .\assert.cxx \
+ $(CAIROLE)\stg\common\dprintf.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winmm.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
+$(OBJDIR)\output.obj $(OBJDIR)\output.lst: .\output.c \
+ $(CAIROLE)\stg\h\wchar.h $(CRTINC)\limits.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\string.h .\w4io.h
+
+$(OBJDIR)\dprintf.obj $(OBJDIR)\dprintf.lst: .\dprintf.c $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\limits.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winmm.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\dprintf.h .\printf.h .\w4io.h
+
+$(OBJDIR)\sprintf.obj $(OBJDIR)\sprintf.lst: .\sprintf.c $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\limits.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winmm.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\printf.h .\w4io.h
+
diff --git a/private/ole32/stg/common/depend.mk9 b/private/ole32/stg/common/depend.mk9
new file mode 100644
index 000000000..6726427ce
--- /dev/null
+++ b/private/ole32/stg/common/depend.mk9
@@ -0,0 +1,24 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\assert.obj $(OBJDIR)\assert.lst: .\assert.cxx \
+ $(CAIROLE)\STG\common\dprintf.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\stdarg.h \
+ $(OSINC)\windows.h
+
+$(OBJDIR)\output.obj $(OBJDIR)\output.lst: .\output.c \
+ $(CAIROLE)\stg\h\wchar.h $(CRTINC)\limits.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\stdarg.h .\w4io.h
+
+$(OBJDIR)\dprintf.obj $(OBJDIR)\dprintf.lst: .\dprintf.c $(CRTINC)\limits.h \
+ $(CRTINC)\stdarg.h $(OSINC)\windows.h .\dprintf.h .\printf.h \
+ .\w4io.h
+
+$(OBJDIR)\sprintf.obj $(OBJDIR)\sprintf.lst: .\sprintf.c $(CRTINC)\limits.h \
+ $(CRTINC)\stdarg.h $(OSINC)\windows.h .\printf.h .\w4io.h
+
diff --git a/private/ole32/stg/common/dirs b/private/ole32/stg/common/dirs
new file mode 100644
index 000000000..2fa7576a0
--- /dev/null
+++ b/private/ole32/stg/common/dirs
@@ -0,0 +1,37 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ daytona
diff --git a/private/ole32/stg/common/dprintf.c b/private/ole32/stg/common/dprintf.c
new file mode 100644
index 000000000..88d6047a2
--- /dev/null
+++ b/private/ole32/stg/common/dprintf.c
@@ -0,0 +1,19 @@
+/***
+*dprintf.c - print formatted to debug port
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4dprintf() - print formatted data to debug port
+* defines w4vdprintf() - print formatted output to debug port, get data
+* from an argument ptr instead of explicit args.
+*******************************************************************************/
+
+#if DBG == 1
+
+#include "dprintf.h" // function prototypes
+
+#define _W4DPRINTF_
+#include "printf.h"
+
+#endif // DBG == 1
diff --git a/private/ole32/stg/common/dprintf.h b/private/ole32/stg/common/dprintf.h
new file mode 100644
index 000000000..f8c9563dc
--- /dev/null
+++ b/private/ole32/stg/common/dprintf.h
@@ -0,0 +1,28 @@
+//+---------------------------------------------------------------------------
+// Copyright (C) 1991, Microsoft Corporation.
+//
+// File: dprintf.h
+//
+// Contents: Debugging output routine function prototypes
+//
+// Functions: w4printf
+// w4vprintf
+// w4dprintf
+// w4vdprintf
+//
+// History: 18-Oct-91 vich Created
+//
+//----------------------------------------------------------------------------
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int _cdecl w4dprintf(const char *format, ...);
+int _cdecl w4vdprintf(const char *format, va_list arglist);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/private/ole32/stg/common/filelist.mk b/private/ole32/stg/common/filelist.mk
new file mode 100644
index 000000000..c4496f929
--- /dev/null
+++ b/private/ole32/stg/common/filelist.mk
@@ -0,0 +1,15 @@
+# Used only for non-Cairo builds
+!if "$(OPSYS)" == "NT"
+!error $(CAIROLE)\stg\common used for Cairo
+!endif
+
+MKNAME = dfcommon
+
+CXXFILES = \
+ .\assert.cxx
+
+CFILES = .\output.c \
+ .\dprintf.c \
+ .\sprintf.c
+
+!include $(CAIROLE)\stg\dfms.mk
diff --git a/private/ole32/stg/common/makefile b/private/ole32/stg/common/makefile
new file mode 100644
index 000000000..917a7c04a
--- /dev/null
+++ b/private/ole32/stg/common/makefile
@@ -0,0 +1,20 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1994 **
+#********************************************************************
+
+!ifdef NTMAKEENV
+
+all:
+ echo $(BUILDMSG)
+
+clean: all
+
+!else
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/stg/common/output.c b/private/ole32/stg/common/output.c
new file mode 100644
index 000000000..970d9d49f
--- /dev/null
+++ b/private/ole32/stg/common/output.c
@@ -0,0 +1,803 @@
+/***
+*output.c - printf style output to a struct w4io
+*
+* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the code that does all the work for the
+* printf family of functions. It should not be called directly, only
+* by the *printf functions. We don't make any assumtions about the
+* sizes of ints, longs, shorts, or long doubles, but if types do overlap, we
+* also try to be efficient. We do assume that pointers are the same size
+* as either ints or longs.
+*
+*Revision History:
+* 06-01-89 PHG Module created
+* 08-28-89 JCR Added cast to get rid of warning (no object changes)
+* 02-15-90 GJF Fixed copyright
+* 10-03-90 WHB Defined LOCAL(x) to "static x" for local procedures
+*
+*******************************************************************************/
+
+#if DBG == 1
+
+#include <limits.h>
+#include <string.h>
+#include <stdarg.h>
+#include "wchar.h"
+#include "w4io.h"
+
+
+/* this macro defines a function which is private and as fast as possible: */
+/* for example, in C 6.0, it might be static _fastcall <type>. */
+#define LOCAL(x) static x // 100390--WHB
+
+#define NOFLOATS // Win 4 doesn't need floating point
+
+/* int/long/short/pointer sizes */
+
+/* the following should be set depending on the sizes of various types */
+// FLAT or LARGE model is assumed
+#ifdef FLAT
+# define LONG_IS_INT 1 /* 1 means long is same size as int */
+# define SHORT_IS_INT 0 /* 1 means short is same size as int */
+# define PTR_IS_INT 1 /* 1 means ptr is same size as int */
+# define PTR_IS_LONG 0 /* 1 means ptr is same size as long */
+#else // LARGE model
+# define LONG_IS_INT 0 /* 1 means long is same size as int */
+# define SHORT_IS_INT 1 /* 1 means short is same size as int */
+# define PTR_IS_INT 0 /* 1 means ptr is same size as int */
+# define PTR_IS_LONG 1 /* 1 means ptr is same size as long */
+#endif
+#define LONGDOUBLE_IS_DOUBLE 0 /* 1 means long double is same as double */
+
+#if LONG_IS_INT
+ #define get_long_arg(x) (long)get_int_arg(x)
+#endif
+
+#if PTR_IS_INT
+ #define get_ptr_arg(x) (void *)get_int_arg(x)
+#elif PTR_IS_LONG
+ #define get_ptr_arg(x) (void *)get_long_arg(x)
+#else
+ #error Size of pointer must be same as size of int or long
+#endif
+
+#ifndef NOFLOATS
+/* These are "fake" double and long doubles to fool the compiler,
+ so we don't drag in floating point. */
+typedef struct {
+ char x[sizeof(double)];
+} DOUBLE;
+typedef struct {
+ char x[sizeof(long double)];
+} LONGDOUBLE;
+#endif
+
+
+/* CONSTANTS */
+
+//#define BUFFERSIZE CVTBUFSIZE /* buffer size for maximum double conv */
+#define BUFFERSIZE 20
+
+/* flag definitions */
+#define FL_SIGN 0x0001 /* put plus or minus in front */
+#define FL_SIGNSP 0x0002 /* put space or minus in front */
+#define FL_LEFT 0x0004 /* left justify */
+#define FL_LEADZERO 0x0008 /* pad with leading zeros */
+#define FL_LONG 0x0010 /* long value given */
+#define FL_SHORT 0x0020 /* short value given */
+#define FL_SIGNED 0x0040 /* signed data given */
+#define FL_ALTERNATE 0x0080 /* alternate form requested */
+#define FL_NEGATIVE 0x0100 /* value is negative */
+#define FL_FORCEOCTAL 0x0200 /* force leading '0' for octals */
+#define FL_LONGDOUBLE 0x0400 /* long double value given */
+#define FL_WIDE 0x0800 /* wide character/string given */
+
+/* state definitions */
+enum STATE {
+ ST_NORMAL, /* normal state; outputting literal chars */
+ ST_PERCENT, /* just read '%' */
+ ST_FLAG, /* just read flag character */
+ ST_WIDTH, /* just read width specifier */
+ ST_DOT, /* just read '.' */
+ ST_PRECIS, /* just read precision specifier */
+ ST_SIZE, /* just read size specifier */
+ ST_TYPE /* just read type specifier */
+};
+#define NUMSTATES (ST_TYPE + 1)
+
+/* character type values */
+enum CHARTYPE {
+ CH_OTHER, /* character with no special meaning */
+ CH_PERCENT, /* '%' */
+ CH_DOT, /* '.' */
+ CH_STAR, /* '*' */
+ CH_ZERO, /* '0' */
+ CH_DIGIT, /* '1'..'9' */
+ CH_FLAG, /* ' ', '+', '-', '#' */
+ CH_SIZE, /* 'h', 'l', 'L', 'N', 'F' */
+ CH_TYPE /* type specifying character */
+};
+
+/* static data (read only, since we are re-entrant) */
+char *nullstring = "(null)"; /* string to print on null ptr */
+
+/* The state table. This table is actually two tables combined into one. */
+/* The lower nybble of each byte gives the character class of any */
+/* character; while the uper nybble of the byte gives the next state */
+/* to enter. See the macros below the table for details. */
+/* */
+/* The table is generated by maketab.c -- use the maketab program to make */
+/* changes. */
+
+static char lookuptable[] = {
+ 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00,
+ 0x10, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x10,
+ 0x04, 0x45, 0x45, 0x45, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x35, 0x30, 0x00, 0x50, 0x00, 0x00, 0x00,
+ 0x00, 0x20, 0x28, 0x38, 0x50, 0x58, 0x07, 0x08,
+ 0x00, 0x30, 0x30, 0x30, 0x57, 0x50, 0x07, 0x00,
+ 0x00, 0x20, 0x20, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00,
+ 0x00, 0x70, 0x70, 0x78, 0x78, 0x78, 0x78, 0x08,
+ 0x07, 0x08, 0x00, 0x00, 0x07, 0x00, 0x08, 0x08,
+ 0x08, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x07,
+ 0x08
+};
+
+#define find_char_class(c) \
+ ((c) < ' ' || (c) > 'x' ? \
+ CH_OTHER \
+ : \
+ lookuptable[(c)-' '] & 0xF)
+
+#define find_next_state(class, state) \
+ (lookuptable[(class) * NUMSTATES + (state)] >> 4)
+
+#if !LONG_IS_INT
+LOCAL(long) get_long_arg(va_list *pargptr);
+#endif
+LOCAL(int) get_int_arg(va_list *pargptr);
+LOCAL(void) writestring(char *string,
+ int len,
+ struct w4io *f,
+ int *pcchwritten,
+ int fwide);
+
+#ifndef NOFLOATS
+/* extern float convert routines */
+typedef int (* PFI)();
+extern PFI _cfltcvt_tab[5];
+#define _cfltcvt(a,b,c,d,e) (*_cfltcvt_tab[0])(a,b,c,d,e)
+#define _cropzeros(a) (*_cfltcvt_tab[1])(a)
+#define _fassign(a,b,c) (*_cfltcvt_tab[2])(a,b,c)
+#define _forcdecpt(a) (*_cfltcvt_tab[3])(a)
+#define _positive(a) (*_cfltcvt_tab[4])(a)
+#define _cldcvt(a,b,c,d,e) (*_cfltcvt_tab[5])(a,b,c,d,e)
+#endif
+
+
+/***
+*int w4iooutput(f, format, argptr)
+*
+*Purpose:
+* Output performs printf style output onto a stream. It is called by
+* printf/fprintf/sprintf/vprintf/vfprintf/vsprintf to so the dirty
+* work. In multi-thread situations, w4iooutput assumes that the given
+* stream is already locked.
+*
+* Algorithm:
+* The format string is parsed by using a finite state automaton
+* based on the current state and the current character read from
+* the format string. Thus, looping is on a per-character basis,
+* not a per conversion specifier basis. Once the format specififying
+* character is read, output is performed.
+*
+*Entry:
+* struct w4io *f - stream for output
+* char *format - printf style format string
+* va_list argptr - pointer to list of subsidiary arguments
+*
+*Exit:
+* Returns the number of characters written, or -1 if an output error
+* occurs.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _cdecl w4iooutput(struct w4io *f, const char *format, va_list argptr)
+{
+ int hexadd; /* offset to add to number to get 'a'..'f' */
+ char ch; /* character just read */
+ wchar_t wc; /* wide character temp */
+ wchar_t *pwc; /* wide character temp pointer */
+ int flags; /* flag word -- see #defines above for flag values */
+ enum STATE state; /* current state */
+ enum CHARTYPE chclass; /* class of current character */
+ int radix; /* current conversion radix */
+ int charsout; /* characters currently written so far, -1 = IO error */
+ int fldwidth; /* selected field with -- 0 means default */
+ int fwide;
+ int precision; /* selected precision -- -1 means default */
+ char prefix[2]; /* numeric prefix -- up to two characters */
+ int prefixlen; /* length of prefix -- 0 means no prefix */
+ int capexp; /* non-zero = 'E' exponent signifiet, zero = 'e' */
+ int no_output; /* non-zero = prodcue no output for this specifier */
+ char *text; /* pointer text to be printed, not zero terminated */
+ int textlen; /* length of the text to be printed */
+ char buffer[BUFFERSIZE]; /* buffer for conversions */
+
+ charsout = 0; /* no characters written yet */
+ state = ST_NORMAL; /* starting state */
+
+ /* main loop -- loop while format character exist and no I/O errors */
+ while ((ch = *format++) != '\0' && charsout >= 0) {
+ chclass = find_char_class(ch); /* find character class */
+ state = find_next_state(chclass, state); /* find next state */
+
+ /* execute code for each state */
+ switch (state) {
+
+ case ST_NORMAL:
+ /* normal state -- just write character */
+ f->writechar(ch, 1, f, &charsout);
+ break;
+
+ case ST_PERCENT:
+ /* set default value of conversion parameters */
+ prefixlen = fldwidth = no_output = capexp = 0;
+ flags = 0;
+ precision = -1;
+ fwide = 0;
+ break;
+
+ case ST_FLAG:
+ /* set flag based on which flag character */
+ switch (ch) {
+ case '-':
+ flags |= FL_LEFT; /* '-' => left justify */
+ break;
+ case '+':
+ flags |= FL_SIGN; /* '+' => force sign indicator */
+ break;
+ case ' ':
+ flags |= FL_SIGNSP; /* ' ' => force sign or space */
+ break;
+ case '#':
+ flags |= FL_ALTERNATE; /* '#' => alternate form */
+ break;
+ case '0':
+ flags |= FL_LEADZERO; /* '0' => pad with leading zeros */
+ break;
+ }
+ break;
+
+ case ST_WIDTH:
+ /* update width value */
+ if (ch == '*') {
+ /* get width from arg list */
+ fldwidth = get_int_arg(&argptr);
+ if (fldwidth < 0) {
+ /* ANSI says neg fld width means '-' flag and pos width */
+ flags |= FL_LEFT;
+ fldwidth = -fldwidth;
+ }
+ }
+ else {
+ /* add digit to current field width */
+ fldwidth = fldwidth * 10 + (ch - '0');
+ }
+ break;
+
+ case ST_DOT:
+ /* zero the precision, since dot with no number means 0
+ not default, according to ANSI */
+ precision = 0;
+ break;
+
+ case ST_PRECIS:
+ /* update precison value */
+ if (ch == '*') {
+ /* get precision from arg list */
+ precision = get_int_arg(&argptr);
+ if (precision < 0)
+ precision = -1; /* neg precision means default */
+ }
+ else {
+ /* add digit to current precision */
+ precision = precision * 10 + (ch - '0');
+ }
+ break;
+
+ case ST_SIZE:
+ /* just read a size specifier, set the flags based on it */
+ switch (ch) {
+#if !LONG_IS_INT
+ case 'l':
+ flags |= FL_LONG; /* 'l' => long int */
+ break;
+#endif
+
+#if !LONGDOUBLE_IS_DOUBLE
+ case 'L':
+ flags |= FL_LONGDOUBLE; /* 'L' => long double */
+ break;
+#endif
+
+#if !SHORT_IS_INT
+ case 'h':
+ flags |= FL_SHORT; /* 'h' => short int */
+ break;
+#endif
+ case 'w':
+ flags |= FL_WIDE; /* 'w' => wide character */
+ break;
+ }
+ break;
+
+ case ST_TYPE:
+ /* we have finally read the actual type character, so we */
+ /* now format and "print" the output. We use a big switch */
+ /* statement that sets 'text' to point to the text that should */
+ /* be printed, and 'textlen' to the length of this text. */
+ /* Common code later on takes care of justifying it and */
+ /* other miscellaneous chores. Note that cases share code, */
+ /* in particular, all integer formatting is doen in one place. */
+ /* Look at those funky goto statements! */
+
+ switch (ch) {
+
+ case 'c': {
+ /* print a single character specified by int argument */
+ wc = (wchar_t) get_int_arg(&argptr); /* get char to print */
+ * (wchar_t *) buffer = wc;
+ text = buffer;
+ textlen = 1; /* print just a single character */
+ }
+ break;
+
+ case 'S': {
+ /* print a Counted String
+
+ int i;
+ char *p; /* temps */
+ struct string {
+ short Length;
+ short MaximumLength;
+ char *Buffer;
+ } *pstr;
+
+ pstr = get_ptr_arg(&argptr);
+ if (pstr == NULL || pstr->Buffer == NULL) {
+ /* null ptr passed, use special string */
+ text = nullstring;
+ textlen = strlen(text);
+ flags &= ~FL_WIDE;
+ } else {
+ text = pstr->Buffer;
+ textlen = pstr->Length;
+ }
+
+ }
+ break;
+
+ case 's': {
+ /* print a string -- */
+ /* ANSI rules on how much of string to print: */
+ /* all if precision is default, */
+ /* min(precision, length) if precision given. */
+ /* prints '(null)' if a null string is passed */
+
+ int i;
+ char *p; /* temps */
+
+ text = get_ptr_arg(&argptr);
+ if (text == NULL) {
+ /* null ptr passed, use special string */
+ text = nullstring;
+ flags &= ~FL_WIDE;
+ }
+
+ /* At this point it is tempting to use strlen(), but */
+ /* if a precision is specified, we're not allowed to */
+ /* scan past there, because there might be no null */
+ /* at all. Thus, we must do our own scan. */
+
+ i = (precision == -1) ? INT_MAX : precision;
+
+ /* scan for null upto i characters */
+ if (flags & FL_WIDE) {
+ pwc = (wchar_t *) text;
+ while (i-- && (wc = *pwc) && (wc & 0x00ff)) {
+ ++pwc;
+ if (wc & 0xff00) { // if high byte set,
+ break; // error will be indicated
+ }
+ }
+ textlen = pwc - (wchar_t *) text; /* length of string */
+ } else {
+ p = text;
+ while (i-- && *p) {
+ ++p;
+ }
+ textlen = p - text; /* length of the string */
+ }
+ }
+ break;
+
+ case 'n': {
+ /* write count of characters seen so far into */
+ /* short/int/long thru ptr read from args */
+
+ void *p; /* temp */
+
+ p = get_ptr_arg(&argptr);
+
+ /* store chars out into short/long/int depending on flags */
+#if !LONG_IS_INT
+ if (flags & FL_LONG)
+ *(long *)p = charsout;
+ else
+#endif
+
+#if !SHORT_IS_INT
+ if (flags & FL_SHORT)
+ *(short *)p = (short) charsout;
+ else
+#endif
+ *(int *)p = charsout;
+
+ no_output = 1; /* force no output */
+ }
+ break;
+
+
+#ifndef NOFLOATS
+ case 'E':
+ case 'G':
+ capexp = 1; /* capitalize exponent */
+ ch += 'a' - 'A'; /* convert format char to lower */
+ /* DROP THROUGH */
+ case 'e':
+ case 'f':
+ case 'g': {
+ /* floating point conversion -- we call cfltcvt routines */
+ /* to do the work for us. */
+ flags |= FL_SIGNED; /* floating point is signed conversion */
+ text = buffer; /* put result in buffer */
+ flags &= ~FL_WIDE; /* 8 bit string */
+
+ /* compute the precision value */
+ if (precision < 0)
+ precision = 6; /* default precision: 6 */
+ else if (precision == 0 && ch == 'g')
+ precision = 1; /* ANSI specified */
+
+#if !LONGDOUBLE_IS_DOUBLE
+ /* do the conversion */
+ if (flags & FL_LONGDOUBLE) {
+ _cldcvt(argptr, text, ch, precision, capexp);
+ va_arg(argptr, LONGDOUBLE);
+ }
+ else
+#endif
+ {
+ _cfltcvt(argptr, text, ch, precision, capexp);
+ va_arg(argptr, DOUBLE);
+ }
+
+ /* '#' and precision == 0 means force a decimal point */
+ if ((flags & FL_ALTERNATE) && precision == 0)
+ _forcdecpt(text);
+
+ /* 'g' format means crop zero unless '#' given */
+ if (ch == 'g' && !(flags & FL_ALTERNATE))
+ _cropzeros(text);
+
+ /* check if result was negative, save '-' for later */
+ /* and point to positive part (this is for '0' padding) */
+ if (*text == '-') {
+ flags |= FL_NEGATIVE;
+ ++text;
+ }
+
+ textlen = strlen(text); /* compute length of text */
+ }
+ break;
+#endif // NOFLOATS
+
+ case 'd':
+ case 'i':
+ /* signed decimal output */
+ flags |= FL_SIGNED;
+ radix = 10;
+ goto COMMON_INT;
+
+ case 'u':
+ radix = 10;
+ goto COMMON_INT;
+
+ case 'p':
+ /* write a pointer -- this is like an integer or long */
+ /* except we force precision to pad with zeros and */
+ /* output in big hex. */
+
+ precision = 2 * sizeof(void *); /* number of hex digits needed */
+#if !PTR_IS_INT
+ flags |= FL_LONG; /* assume we're converting a long */
+#endif
+ /* DROP THROUGH to hex formatting */
+
+ case 'C':
+ case 'X':
+ /* unsigned upper hex output */
+ hexadd = 'A' - '9' - 1; /* set hexadd for uppercase hex */
+ goto COMMON_HEX;
+
+ case 'x':
+ /* unsigned lower hex output */
+ hexadd = 'a' - '9' - 1; /* set hexadd for lowercase hex */
+ /* DROP THROUGH TO COMMON_HEX */
+
+ COMMON_HEX:
+ radix = 16;
+ if (flags & FL_ALTERNATE) {
+ /* alternate form means '0x' prefix */
+ prefix[0] = '0';
+ prefix[1] = (char)('x' - 'a' + '9' + 1 + hexadd); /* 'x' or 'X' */
+ prefixlen = 2;
+ }
+ goto COMMON_INT;
+
+ case 'o':
+ /* unsigned octal output */
+ radix = 8;
+ if (flags & FL_ALTERNATE) {
+ /* alternate form means force a leading 0 */
+ flags |= FL_FORCEOCTAL;
+ }
+ /* DROP THROUGH to COMMON_INT */
+
+ COMMON_INT: {
+ /* This is the general integer formatting routine. */
+ /* Basically, we get an argument, make it positive */
+ /* if necessary, and convert it according to the */
+ /* correct radix, setting text and textlen */
+ /* appropriately. */
+
+ unsigned long number; /* number to convert */
+ int digit; /* ascii value of digit */
+ long l; /* temp long value */
+
+ /* 1. read argument into l, sign extend as needed */
+#if !LONG_IS_INT
+ if (flags & FL_LONG)
+ l = get_long_arg(&argptr);
+ else
+#endif
+
+#if !SHORT_IS_INT
+ if (flags & FL_SHORT) {
+ if (flags & FL_SIGNED)
+ l = (short) get_int_arg(&argptr); /* sign extend */
+ else
+ l = (unsigned short) get_int_arg(&argptr); /* zero-extend*/
+ }
+ else
+#endif
+ {
+ if (flags & FL_SIGNED)
+ l = get_int_arg(&argptr); /* sign extend */
+ else
+ l = (unsigned int) get_int_arg(&argptr); /* zero-extend*/
+ }
+
+ /* 2. check for negative; copy into number */
+ if ( (flags & FL_SIGNED) && l < 0) {
+ number = -l;
+ flags |= FL_NEGATIVE; /* remember negative sign */
+ }
+ else {
+ number = l;
+ }
+
+ /* 3. check precision value for default; non-default */
+ /* turns off 0 flag, according to ANSI. */
+ if (precision < 0)
+ precision = 1; /* default precision */
+ else
+ flags &= ~FL_LEADZERO;
+
+ /* 4. Check if data is 0; if so, turn off hex prefix */
+ if (number == 0)
+ prefixlen = 0;
+
+ /* 5. Convert data to ASCII -- note if precision is zero */
+ /* and number is zero, we get no digits at all. */
+
+ text = &buffer[BUFFERSIZE-1]; // last digit at end of buffer
+ flags &= ~FL_WIDE; // 8 bit characters
+
+ while (precision-- > 0 || number != 0) {
+ digit = (int)(number % radix) + '0';
+ number /= radix; /* reduce number */
+ if (digit > '9') {
+ /* a hex digit, make it a letter */
+ digit += hexadd;
+ }
+ *text-- = (char)digit; /* store the digit */
+ }
+
+ textlen = (char *)&buffer[BUFFERSIZE-1] - text; /* compute length of number */
+ ++text; /* text points to first digit now */
+
+
+ /* 6. Force a leading zero if FORCEOCTAL flag set */
+ if ((flags & FL_FORCEOCTAL) && (text[0] != '0' || textlen == 0)) {
+ *--text = '0';
+ ++textlen; /* add a zero */
+ }
+ }
+ break;
+ }
+
+ /* At this point, we have done the specific conversion, and */
+ /* 'text' points to text to print; 'textlen' is length. Now we */
+ /* justify it, put on prefixes, leading zeros, and then */
+ /* print it. */
+
+ if (!no_output) {
+ int padding; /* amount of padding, negative means zero */
+
+ if (flags & FL_SIGNED) {
+ if (flags & FL_NEGATIVE) {
+ /* prefix is a '-' */
+ prefix[0] = '-';
+ prefixlen = 1;
+ }
+ else if (flags & FL_SIGN) {
+ /* prefix is '+' */
+ prefix[0] = '+';
+ prefixlen = 1;
+ }
+ else if (flags & FL_SIGNSP) {
+ /* prefix is ' ' */
+ prefix[0] = ' ';
+ prefixlen = 1;
+ }
+ }
+
+ /* calculate amount of padding -- might be negative, */
+ /* but this will just mean zero */
+ padding = fldwidth - textlen - prefixlen;
+
+ /* put out the padding, prefix, and text, in the correct order */
+
+ if (!(flags & (FL_LEFT | FL_LEADZERO))) {
+ /* pad on left with blanks */
+ f->writechar(' ', padding, f, &charsout);
+ }
+
+ /* write prefix */
+ writestring(prefix, prefixlen, f, &charsout, 0);
+
+ if ((flags & FL_LEADZERO) && !(flags & FL_LEFT)) {
+ /* write leading zeros */
+ f->writechar('0', padding, f, &charsout);
+ }
+
+ /* write text */
+ writestring(text, textlen, f, &charsout, flags & FL_WIDE);
+
+ if (flags & FL_LEFT) {
+ /* pad on right with blanks */
+ f->writechar(' ', padding, f, &charsout);
+ }
+
+ /* we're done! */
+ }
+ break;
+ }
+ }
+
+ return charsout; /* return value = number of characters written */
+}
+
+
+/***
+*int get_int_arg(va_list pargptr)
+*
+*Purpose:
+* Gets an int argument off the given argument list and updates *pargptr.
+*
+*Entry:
+* va_list pargptr - pointer to argument list; updated by function
+*
+*Exit:
+* Returns the integer argument read from the argument list.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+LOCAL(int) get_int_arg(va_list *pargptr)
+{
+ return va_arg(*pargptr, int);
+}
+
+/***
+*long get_long_arg(va_list pargptr)
+*
+*Purpose:
+* Gets an long argument off the given argument list and updates pargptr.
+*
+*Entry:
+* va_list pargptr - pointer to argument list; updated by function
+*
+*Exit:
+* Returns the long argument read from the argument list.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+#if !LONG_IS_INT
+LOCAL(long) get_long_arg(va_list *pargptr)
+{
+ return va_arg(*pargptr, long);
+}
+#endif
+
+
+
+/***
+*void writestring(char *string, int len, struct w4io *f, int *pcchwritten, int fwide)
+*
+*Purpose:
+* Writes a string of the given length to the given file. If no error occurs,
+* then *pcchwritten is incremented by len; otherwise, *pcchwritten is set
+* to -1. If len is negative, it is treated as zero.
+*
+*Entry:
+* char *string - string to write (NOT null-terminated)
+* int len - length of string
+* struct w4io *f - file to write to
+* int *pcchwritten - pointer to integer to update with total chars written
+* int fwide - wide character flag
+*
+*Exit:
+* No return value.
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+LOCAL(void) writestring(
+ char *string,
+ int len,
+ struct w4io *f,
+ int *pcchwritten,
+ int fwide)
+{
+ wchar_t *pwc;
+
+ //printf("string: str=%.*s, len=%d, cch=%d, f=%d\n", len, string, len, *pcchwritten, fwide);
+ if (fwide) {
+ pwc = (wchar_t *) string;
+ while (len-- > 0) {
+ if (*pwc & 0xff00) {
+ f->writechar('^', 1, f, pcchwritten);
+ }
+ f->writechar((char) *pwc++, 1, f, pcchwritten);
+ }
+ } else {
+ while (len-- > 0) {
+ f->writechar(*string++, 1, f, pcchwritten);
+ }
+ }
+}
+
+#endif // DBG == 1
diff --git a/private/ole32/stg/common/printf.h b/private/ole32/stg/common/printf.h
new file mode 100644
index 000000000..466fced2f
--- /dev/null
+++ b/private/ole32/stg/common/printf.h
@@ -0,0 +1,241 @@
+/***
+*printf.h - print formatted
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4*printf() - print formatted data
+* defines w4v*printf() - print formatted output, get data from an
+* argument ptr instead of explicit args.
+*
+*Revision History:
+* 09-02-83 RN original sprintf
+* 06-17-85 TC rewrote to use new varargs macros, and to be vsprintf
+* 04-13-87 JCR added const to declaration
+* 11-07-87 JCR Multi-thread support
+* 12-11-87 JCR Added "_LOAD_DS" to declaration
+* 05-27-88 PHG Merged DLL and normal versions
+* 06-13-88 JCR Fake _iob entry is now static so that other routines
+* can assume _iob entries are in DGROUP.
+* 08-25-88 GJF Define MAXSTR to be INT_MAX (from LIMITS.H).
+* 06-06-89 JCR 386 mthread support
+* 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
+* model). Also fixed copyright and indents.
+* 02-16-90 GJF Fixed copyright
+*
+*******************************************************************************/
+
+#include <stdarg.h>
+#include <limits.h>
+#include <windows.h>
+#include "w4io.h"
+
+#if defined(_W4PRINTF_)
+ static long fh;
+// extern long GetStdHandle(long);
+// extern void WriteFile(long fh, char *s, long cch, long * pcchret, long);
+# define _PRINTF_
+#elif defined(_W4DPRINTF_)
+# define _pwritechar _dwritechar
+# define _pflushbuf _dflushbuf
+# define w4printf w4dprintf
+# define w4vprintf w4vdprintf
+# define _PRINTF_
+#elif defined(_W4SPRINTF_)
+# define _pwritechar _swritechar
+# define w4printf w4sprintf
+# define w4vprintf w4vsprintf
+#elif defined(_W4WCSPRINTF_)
+# define _TCHAR_ wchar_t
+# define _PBUF_ pwcbuf
+# define _PSTART_ pwcstart
+# define w4printf w4wcsprintf
+# define w4vprintf w4vwcsprintf
+# define _pwritechar _wwritechar
+#else
+# error configuration problem
+#endif
+
+#ifndef _TCHAR_
+# define _TCHAR_ char
+# define _PBUF_ pchbuf
+# define _PSTART_ pchstart
+#endif
+
+
+#ifdef _PRINTF_
+# ifndef FLAT
+# define OutputDebugStringA OutputDebugString
+# endif
+ int _cdecl _pflushbuf(struct w4io *f);
+# define SPR(a)
+# define MAXSTR 128
+#else
+# define SPR(a) a,
+# define MAXSTR INT_MAX
+#endif
+
+void _cdecl _pwritechar(int ch, int num, struct w4io *f, int *pcchwritten);
+int _cdecl w4vprintf(SPR(_TCHAR_ *string) const char *format, va_list arglist);
+
+
+/***
+*int w4printf(format, ...) - print formatted data
+*
+*Purpose:
+* Prints formatted data using the format string to
+* format data and getting as many arguments as called for
+* Sets up a w4io so file i/o operations can be used.
+* w4iooutput does the real work here
+*
+*Entry:
+* char *format - format string to control data format/number
+* of arguments followed by list of arguments, number and type
+* controlled by format string
+*
+*Exit:
+* returns number of characters written
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+
+int _cdecl
+w4printf(SPR(_TCHAR_ *string) const char *format, ...)
+/*
+ * 'PRINT', 'F'ormatted
+ */
+{
+ va_list arglist;
+
+ va_start(arglist, format);
+ return(w4vprintf(SPR(string) format, arglist));
+}
+
+
+/***
+*int w4vprintf(format, arglist) - print formatted data from arg ptr
+*
+*Purpose:
+* Prints formatted data, but gets data from an argument pointer.
+* Sets up a w4io so file i/o operations can be used, make string look
+* like a huge buffer to it, but _flsbuf will refuse to flush it if it
+* fills up. Appends '\0' to make it a true string.
+*
+* Multi-thread: (1) Since there is no stream, this routine must never try
+* to get the stream lock (i.e., there is no stream lock either). (2)
+* Also, since there is only one staticly allocated 'fake' iob, we must
+* lock/unlock to prevent collisions.
+*
+*Entry:
+* char *format - format string, describes format of data
+* va_list arglist - varargs argument pointer
+*
+*Exit:
+* returns number of characters written
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _cdecl
+w4vprintf(SPR(_TCHAR_ *string) const char *format, va_list arglist)
+/*
+ * 'V'ariable argument 'PRINT', 'F'ormatted
+ */
+{
+ struct w4io outfile;
+ register int retval;
+#ifdef _PRINTF_
+ char string[MAXSTR + 1]; // leave room for null termination
+#else
+ int dummy;
+#endif
+
+#ifdef _W4PRINTF_
+ long ldummy;
+
+ if (fh == 0 || fh == -1)
+ {
+ ldummy = -11; // C7 bug workaround
+ if ((fh = (long)GetStdHandle(ldummy)) == 0 || fh == -1)
+ {
+ OutputDebugStringA("GetStdHandle in " __FILE__ " failed\n");
+ return(-1);
+ }
+ }
+#endif
+
+ outfile._PBUF_ = outfile._PSTART_ = string;
+ outfile.cchleft = MAXSTR;
+ outfile.writechar = _pwritechar;
+
+ retval = w4iooutput(&outfile, format, arglist);
+
+#ifdef _PRINTF_
+ if (_pflushbuf(&outfile) == -1) {
+ return(-1);
+ }
+#else
+ _pwritechar('\0', 1, &outfile, &dummy);
+#endif
+ return(retval);
+}
+
+
+void _cdecl _pwritechar(int ch, int num, struct w4io *f, int *pcchwritten)
+{
+ //printf(" char: ch=%c, cnt=%d, cch=%d\n", ch, num, *pcchwritten);
+ while (num-- > 0) {
+#ifdef _PRINTF_
+ if (f->cchleft < 2 && _pflushbuf(f) == -1) {
+ *pcchwritten = -1;
+ return;
+ }
+#endif
+#ifdef _W4DPRINTF_
+# ifndef FLAT
+ if (ch == '\n')
+ {
+ *f->_PBUF_++ = '\r';
+ f->cchleft--;
+ (*pcchwritten)++;
+ }
+# endif
+#endif
+ *f->_PBUF_++ = (char) ch;
+ f->cchleft--;
+ (*pcchwritten)++;
+ }
+}
+
+
+#ifdef _PRINTF_
+int _cdecl _pflushbuf(struct w4io *f)
+{
+ int cch;
+
+ if (cch = (f->pchbuf - f->pchstart))
+ {
+#ifdef _W4DPRINTF_
+ *f->pchbuf = '\0'; // null terminate
+ OutputDebugStringA(f->pchstart);
+#else
+ long cchret;
+
+ //*f->pchbuf = '\0'; // null terminate
+ //printf("%d chars: \"%s\"\n", cch, f->pchstart);
+ WriteFile((HANDLE)fh, f->pchstart, cch, &cchret, 0);
+ if (cch != cchret)
+ {
+ OutputDebugString("WriteFile in " __FILE__ " failed\n");
+ return(-1);
+ }
+#endif
+ f->pchbuf -= cch; // reset pointer
+ f->cchleft += cch; // reset count
+ }
+ return(0);
+}
+#endif // _PRINTF_
diff --git a/private/ole32/stg/common/sprintf.c b/private/ole32/stg/common/sprintf.c
new file mode 100644
index 000000000..c4d9dfcdf
--- /dev/null
+++ b/private/ole32/stg/common/sprintf.c
@@ -0,0 +1,17 @@
+/***
+*sprintf.c - print formatted to string
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines w4sprintf() - print formatted data to string
+* defines w4vsprintf() - print formatted output to a string, get data
+* from an argument ptr instead of explicit args.
+*******************************************************************************/
+
+#if DBG == 1
+
+#define _W4SPRINTF_
+#include "printf.h"
+
+#endif
diff --git a/private/ole32/stg/common/w4io.h b/private/ole32/stg/common/w4io.h
new file mode 100644
index 000000000..0613dc727
--- /dev/null
+++ b/private/ole32/stg/common/w4io.h
@@ -0,0 +1,54 @@
+/***
+*w4io.h - fake FILE structure for Win 4 printf/sprintf/debug printf support
+*
+*/
+
+#if defined(M_I386) || defined(FLAT)
+# ifndef FLAT
+# define FLAT
+# endif
+#elif !defined(M_I86LM)
+# error Must be FLAT or LARGE model.
+#endif
+
+#ifndef NULL
+# define NULL 0
+#endif
+
+#ifndef _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+struct w4io
+{
+ union
+ {
+ struct
+ {
+ wchar_t *_pwcbuf; // wchar_t output buffer
+ wchar_t *_pwcstart;
+ } wc;
+ struct
+ {
+ char *_pchbuf; // char output buffer
+ char *_pchstart;
+ } ch;
+ } buf ;
+ unsigned int cchleft; // output buffer character count
+ void (_cdecl *writechar)(int ch,
+ int num,
+ struct w4io *f,
+ int *pcchwritten);
+};
+
+#define pwcbuf buf.wc._pwcbuf
+#define pwcstart buf.wc._pwcstart
+#define pchbuf buf.ch._pchbuf
+#define pchstart buf.ch._pchstart
+
+#define REG1 register
+#define REG2 register
+
+/* prototypes */
+int _cdecl w4iooutput(struct w4io *stream, const char *format, va_list argptr);
diff --git a/private/ole32/stg/dflibs.mk b/private/ole32/stg/dflibs.mk
new file mode 100644
index 000000000..ad081ffbe
--- /dev/null
+++ b/private/ole32/stg/dflibs.mk
@@ -0,0 +1,38 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1993 **
+#********************************************************************
+
+!if "$(OPSYS)" == "NT"
+
+# Cairo
+
+LIBS = $(LIBS) $(COMMON)\src\ole\$(OBJDIR)\olecom.lib $(CAIROLIB)
+!else
+
+# Non-Cairo
+
+! if "$(BUILDTYPE)" == "DEBUG"
+LIBS = $(LIBS) $(CAIROLE)\stg\common\$(OBJDIR)\dfcommon.lib
+! endif
+
+! if "$(OPSYS)" == "NT1X"
+# NT 1.x
+LIBS = $(LIBS) $(CAIROLE)\ilib\$(OBJDIR)\compob32.lib \
+ $(CAIROLE)\ilib\$(OBJDIR)\ole232.lib
+! endif
+
+! if "$(OPSYS)" == "DOS" && "$(PLATFORM)" == "i386"
+# Chicago
+LIBS = $(LIBS) $(CAIROLE)\ilib\$(OBJDIR)\compob32.lib
+! endif
+
+! if "$(PLATFORM)" == "i286"
+# Win16
+LIBS = $(LIBS) \
+ $(CAIROLE)\stg\wclib\$(OBJDIR)\wclib.lib \
+ $(OLE2BIN)\compobj.lib \
+ $(OSLIBDIR)\toolhelp.lib \
+! endif
+
+!endif
diff --git a/private/ole32/stg/dfms.mk b/private/ole32/stg/dfms.mk
new file mode 100644
index 000000000..a8ab65b51
--- /dev/null
+++ b/private/ole32/stg/dfms.mk
@@ -0,0 +1,30 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1992 **
+#********************************************************************
+
+!include $(CAIROLE)\stg\setole2.mk
+
+TARGET = $(MKNAME).lib
+
+!if "$(PLATFORM)" == "i286"
+CFLAGS = $(CFLAGS) -GA -GEd -Aw -D_WINDLL
+!endif
+
+!if "$(BUILDTYPE)" == "DEBUG"
+!if "$(PLATFORM)" == "i286"
+CFLAGS = $(CFLAGS) -Gt8
+!endif
+#CFLAGS = $(CFLAGS) -DINDINST
+!endif
+
+# Properties on Cairo only
+!if "$(OPSYS)" == "NT"
+CFLAGS = $(CFLAGS) -DPROPS
+!endif
+
+CINC = -I$(OLE2H) $(CINC) -I$(CAIROLE)\stg\h
+
+INCLUDES_ROOTS = $(INCLUDES_ROOTS) -P$$(OLE2H)=$(OLE2H) -P$$(CAIROLE)=$(CAIROLE)
+
+MULTIDEPEND = MERGED
diff --git a/private/ole32/stg/dirs b/private/ole32/stg/dirs
new file mode 100644
index 000000000..a6c431bd7
--- /dev/null
+++ b/private/ole32/stg/dirs
@@ -0,0 +1,45 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS= \
+ async \
+ docfile \
+ exp \
+ fsstg \
+ msf \
+ ofsstg \
+ simp \
+ wclib \
+ props \
+ xact
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS=
diff --git a/private/ole32/stg/dll/daytona/makefile b/private/ole32/stg/dll/daytona/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ole32/stg/dll/daytona/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/stg/dll/daytona/makefile.inc b/private/ole32/stg/dll/daytona/makefile.inc
new file mode 100644
index 000000000..a49825ec8
--- /dev/null
+++ b/private/ole32/stg/dll/daytona/makefile.inc
@@ -0,0 +1 @@
+obj\$(TARGET_DIRECTORY)\storag32.def: storag32.src
diff --git a/private/ole32/stg/dll/daytona/sources b/private/ole32/stg/dll/daytona/sources
new file mode 100644
index 000000000..ab9b698a0
--- /dev/null
+++ b/private/ole32/stg/dll/daytona/sources
@@ -0,0 +1,85 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= storag32
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= $(BASEDIR)\public\sdk\lib
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= DYNLINK
+DLLDEF= obj\$(TARGET_DIRECTORY)\storag32.def
+DLLBASE=@$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,storag32
+
+
+SOURCES= ..\dummy.c
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+
+DLLENTRY= DllEntryPoint
+
+LINKLIBS= \
+ ..\..\common\daytona\obj\*\dfcommon.lib \
+ ..\..\docfile\daytona\obj\*\docfile.lib \
+ ..\..\exp\daytona\obj\*\exp.lib \
+ ..\..\msf\daytona\obj\*\msf.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib\
+ $(BASEDIR)\public\sdk\lib\*\user32.lib\
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib
+
+TARGETLIBS= $(BASEDIR)\public\sdk\lib\*\compob32.lib
+
+PRECOMPILED_INCLUDE=
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
+
+NTTARGETFILE0=$(DLLDEF)
diff --git a/private/ole32/stg/dll/daytona/storag32.src b/private/ole32/stg/dll/daytona/storag32.src
new file mode 100644
index 000000000..36d8d9870
--- /dev/null
+++ b/private/ole32/stg/dll/daytona/storag32.src
@@ -0,0 +1,115 @@
+;//+-------------------------------------------------------------------------
+;//
+;// Microsoft Windows
+;// Copyright (C) Microsoft Corporation, 1992 - 1993.
+;//
+;// File: storag32.def
+;//
+;// Contents: storag32.dll module definition file
+;//
+;// History: 23-Sep-92 DrewB Created from multiple def files
+;// 09-Oct-92 AlexT Added HEAPSIZE to 16-bit definitions
+;// 03-Feb-93 DrewB Changed docfile.def to storage.def
+;//
+;// Note: $(OLE)\storage.def is used for 16-bit builds
+;// $(CAIROLE)\ilib\storag32.def is used for non-Cairo 32-bit
+;// $(COMMON)\ilib\storag32.def is used for Cairo 32-bit builds
+;//
+;//--------------------------------------------------------------------------
+
+LIBRARY STORAG32
+DESCRIPTION 'Storage DLL'
+CODE DISCARDABLE LOADONCALL MOVABLE SHARED
+DATA LOADONCALL SINGLE MOVABLE
+
+EXPORTS
+
+#if defined (i386)
+
+ _StgCreateDocfile@16 @1
+ _StgCreateDocfileOnILockBytes@16 @2
+ _StgOpenStorage@24 @3
+ _StgOpenStorageOnILockBytes@24 @4
+ _StgIsStorageFile@4 @5
+ _StgIsStorageILockBytes@4 @6
+ _StgSetTimes@16 @7
+#ifdef _CAIRO_
+ _StgCreateStorage@20 @43
+ _StgCreateStorageOnHandle@16 @44
+ _StgOpenStorageOnHandle@12 @45
+ _StgIsStorage@8 @46
+
+ _FreeVariantArray@8 @50
+#endif
+
+ _DfUnMarshalInterface@16 @102
+ _DllGetClassObject@12 @103
+ DllGetClassObject=_DllGetClassObject@12
+
+#if DBG == 1
+ _DfDebug@8 @300
+ _DfSetResLimit@8 @310
+ _DfGetResLimit@4 @311
+ _DfGetMemAlloced@0 @302
+ _DfPrintAllocs@0 @303
+#endif
+
+#elif defined (_MIPS_)
+
+ StgCreateDocfile @1
+ StgCreateDocfileOnILockBytes @2
+ StgOpenStorage @3
+ StgOpenStorageOnILockBytes @4
+ StgIsStorageFile @5
+ StgIsStorageILockBytes @6
+ StgSetTimes @7
+#ifdef _CAIRO_
+ StgCreateStorage @43
+ StgCreateStorageOnHandle @44
+ StgOpenStorageOnHandle @45
+ StgIsStorage @46
+
+ FreeVariantArray @50
+#endif
+
+ DfUnMarshalInterface @102
+ DllGetClassObject @103
+
+#if DBG == 1
+ DfDebug @300
+ DfSetResLimit @310
+ DfGetResLimit @311
+ DfGetMemAlloced @302
+ DfPrintAllocs @303
+#endif
+
+#elif defined (_PPC_)
+
+ StgCreateDocfile @1
+ StgCreateDocfileOnILockBytes @2
+ StgOpenStorage @3
+ StgOpenStorageOnILockBytes @4
+ StgIsStorageFile @5
+ StgIsStorageILockBytes @6
+ StgSetTimes @7
+#ifdef _CAIRO_
+ StgCreateStorage @43
+ StgCreateStorageOnHandle @44
+ StgOpenStorageOnHandle @45
+ StgIsStorage @46
+
+ FreeVariantArray @50
+#endif
+
+ DfUnMarshalInterface @102
+ DllGetClassObject @103
+
+#if DBG == 1
+ DfDebug @300
+ DfSetResLimit @310
+ DfGetResLimit @311
+ DfGetMemAlloced @302
+ DfPrintAllocs @303
+#endif
+
+#endif // i386 - MIPS - PPC
diff --git a/private/ole32/stg/dll/dirs b/private/ole32/stg/dll/dirs
new file mode 100644
index 000000000..ddf44d103
--- /dev/null
+++ b/private/ole32/stg/dll/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/stg/dll/dummy.c b/private/ole32/stg/dll/dummy.c
new file mode 100644
index 000000000..2992dfeac
--- /dev/null
+++ b/private/ole32/stg/dll/dummy.c
@@ -0,0 +1,3 @@
+void __DummyRoutineUncalled__(void)
+{
+}
diff --git a/private/ole32/stg/docfile/cdocfile.cxx b/private/ole32/stg/docfile/cdocfile.cxx
new file mode 100644
index 000000000..f33f9f226
--- /dev/null
+++ b/private/ole32/stg/docfile/cdocfile.cxx
@@ -0,0 +1,574 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992
+//
+// File: cdocfile.cxx
+//
+// Contents: Implementation of CDocFile methods for DocFiles
+//
+// History: 11-Dec-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+#include <vectfunc.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: PBasicEntry::_dlBase, static private data
+//
+// Synopsis: luid allocation base
+//
+// History: 21-Oct-92 AlexT Created
+//
+// Notes: Some LUIDs are reserved so we start at LUID_BASE
+// rather than zero
+//
+//---------------------------------------------------------------
+
+#ifndef FLAT
+DFLUID PBasicEntry::_dlBase = LUID_BASE;
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::InitFromEntry, public
+//
+// Synopsis: Creation/Instantiation constructor for embeddings
+//
+// Arguments: [pstghParent] - Parent handle
+// [pdfn] - Name
+// [fCreate] - Create/Instantiate
+// [dwType] - Type of entry
+//
+// Returns: Appropriate status code
+//
+// History: 16-Dec-91 DrewB Created
+//
+// Algorithm: Create or get the entry from the multistream
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_InitFromEntry) // Dirdf_Init_TEXT
+#endif
+
+SCODE CDocFile::InitFromEntry(CStgHandle *pstghParent,
+ CDfName const *pdfn,
+ BOOL const fCreate)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::InitFromEntry(%p, %ws, %d)\n",
+ pstghParent, pdfn, fCreate));
+ if (fCreate)
+ sc = pstghParent->CreateEntry(pdfn, STGTY_STORAGE, &_stgh);
+ else
+ sc = pstghParent->GetEntry(pdfn, STGTY_STORAGE, &_stgh);
+
+ if (SUCCEEDED(sc))
+ AddRef();
+ olDebugOut((DEB_ITRACE, "Out CDocFile::InitFromEntry\n"));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::CreateDocFile, public
+//
+// Synopsis: Creates a DocFile object in a parent
+//
+// Arguments: [pdfn] - Name of DocFile
+// [df] - Transactioning flags
+// [dlSet] - LUID to set or DF_NOLUID
+// [dwType] - Type of entry
+// [ppdfDocFile] - DocFile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdfDocFile]
+//
+// History: 11-Dec-91 DrewB Created
+//
+// Algorithm: Allocate new docfile and init from given entry
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_CreateDocFile) // Dirdf_Create_TEXT
+#endif
+
+SCODE CDocFile::CreateDocFile(CDfName const *pdfn,
+ DFLAGS const df,
+ DFLUID dlSet,
+ PDocFile **ppdfDocFile)
+{
+ CDocFile *pdf;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::CreateDocFile:%p("
+ "%ws, %X, %lu, %p)\n", this, pdfn, df, dlSet,
+ ppdfDocFile));
+
+ UNREFERENCED_PARM(df);
+
+ if (dlSet == DF_NOLUID)
+ dlSet = CDocFile::GetNewLuid(_pdfb->GetMalloc());
+
+#ifndef REF
+ pdf = GetReservedDocfile(dlSet);
+ olAssert(pdf != NULL && aMsg("Reserved Docfile not found"));
+#else
+ olMem(pdf = new CDocFile(dlSet, _pilbBase));
+#endif //!REF
+
+ olChkTo(EH_pdf, pdf->InitFromEntry(&_stgh, pdfn, TRUE));
+
+ *ppdfDocFile = pdf;
+ olDebugOut((DEB_ITRACE, "Out CDocFile::CreateDocFile => %p\n",
+ *ppdfDocFile));
+ return S_OK;
+
+EH_pdf:
+#ifndef REF
+ pdf->ReturnToReserve(BP_TO_P(CDFBasis *,_pdfb));
+#else
+ delete pdf;
+EH_Err:
+#endif //!REF
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::GetDocFile, public
+//
+// Synopsis: Instantiates an existing docfile
+//
+// Arguments: [pdfn] - Name of stream
+// [df] - Transactioning flags
+// [dwType] - Type of entry
+// [ppdfDocFile] - Docfile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdfDocFile]
+//
+// History: 11-Dec-91 DrewB Created
+//
+// Algorithm: Allocate new docfile and init from given entry
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_GetDocFile) // Dirdf_Open_TEXT
+#endif
+
+SCODE CDocFile::GetDocFile(CDfName const *pdfn,
+ DFLAGS const df,
+ PDocFile **ppdfDocFile)
+{
+ CDocFile *pdf;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::GetDocFile:%p("
+ "%ws, %X, %p)\n", this, pdfn, df, ppdfDocFile));
+
+ UNREFERENCED_PARM(df);
+
+ DFLUID dl = CDocFile::GetNewLuid(_pdfb->GetMalloc());
+#ifndef REF
+ olMem(pdf = new (_pdfb->GetMalloc()) CDocFile(dl,
+ BP_TO_P(CDFBasis *, _pdfb)));
+#else
+ olMem(pdf = new CDocFile(dl, _pilbBase));
+#endif //!REF
+
+ olChkTo(EH_pdf, pdf->InitFromEntry(&_stgh, pdfn, FALSE));
+
+ *ppdfDocFile = pdf;
+ olDebugOut((DEB_ITRACE, "Out CDocFile::GetDocFile => %p\n",
+ *ppdfDocFile));
+ return S_OK;
+
+EH_pdf:
+ delete pdf;
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::Release, public
+//
+// Synopsis: Release resources for a DocFile
+//
+// History: 11-Dec-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_Release) // Dirdf_Release_TEXT
+#endif
+
+void CDocFile::Release(void)
+{
+ LONG lRet;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::Release()\n"));
+ olAssert(_cReferences > 0);
+
+ lRet = AtomicDec(&_cReferences);
+ if (lRet == 0)
+ delete this;
+ olDebugOut((DEB_ITRACE, "Out CDocFile::Release\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::RenameEntry, public
+//
+// Synopsis: Renames a child
+//
+// Arguments: [pdfnName] - Old name
+// [pdfnNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// History: 12-Dec-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_Rename) // Dirdf_Rename_TEXT
+#endif
+
+SCODE CDocFile::RenameEntry(CDfName const *pdfnName,
+ CDfName const *pdfnNewName)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::RenameEntry(%ws, %ws)\n",
+ pdfnName, pdfnNewName));
+ sc = _stgh.RenameEntry(pdfnName, pdfnNewName);
+ olDebugOut((DEB_ITRACE, "Out CDocFile::RenameEntry\n"));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::DestroyEntry, public
+//
+// Synopsis: Permanently destroys a child
+//
+// Arguments: [pdfnName] - Name of child
+// [fClean] - Ignored
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_Destroy) // Dirdf_Destroy_TEXT
+#endif
+
+SCODE CDocFile::DestroyEntry(CDfName const *pdfnName,
+ BOOL fClean)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::DestroyEntry:%p(%ws, %d)\n",
+ this, pdfnName, fClean));
+ UNREFERENCED_PARM(fClean);
+ sc = _stgh.DestroyEntry(pdfnName);
+ olDebugOut((DEB_ITRACE, "Out CDocFile::DestroyEntry\n"));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::IsEntry, public
+//
+// Synopsis: Determines whether the given object is a member
+// of the DocFile
+//
+// Arguments: [pdfnName] - Name
+// [peb] - Entry buffer to fill in
+//
+// Returns: Appropriate status code
+//
+// Modifies: [peb]
+//
+// History: 07-Nov-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_IsEntry) // Dirdf_TEXT
+#endif
+
+SCODE CDocFile::IsEntry(CDfName const *pdfnName,
+ SEntryBuffer *peb)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::IsEntry(%ws, %p)\n",
+ pdfnName, peb));
+ sc = _stgh.IsEntry(pdfnName, peb);
+ olDebugOut((DEB_ITRACE, "Out CDocFile::IsEntry => %lu, %lu, %lu\n",
+ sc, peb->luid, peb->dwType));
+ return sc;
+}
+
+#ifdef INDINST
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::Destroy, public
+//
+// Synopsis: Destroys the DocFile
+//
+// History: 12-Dec-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+void CDocFile::Destroy(void)
+{
+ olDebugOut((DEB_ITRACE, "In CDocFile::Destroy()\n"));
+ olAssert(_cReferences == 1);
+ olVerSucc(_stgh.DestroyEntry(NULL);
+ CDocFile::Release();
+ olDebugOut((DEB_ITRACE, "Out CDocFile::Destroy\n"));
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// History: 08-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_AddRef)
+#endif
+
+void CDocFile::AddRef(void)
+{
+ olDebugOut((DEB_ITRACE, "In CDocFile::AddRef()\n"));
+ AtomicInc(&_cReferences);
+ olDebugOut((DEB_ITRACE, "Out CDocFile::AddRef, %lu\n", _cReferences));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::GetTime, public
+//
+// Synopsis: Gets a time
+//
+// Arguments: [wt] - Which time
+// [ptm] - Time return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ptm]
+//
+// History: 31-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_GetTime)
+#endif
+
+SCODE CDocFile::GetTime(WHICHTIME wt, TIME_T *ptm)
+{
+ return _stgh.GetTime(wt, ptm);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::GetAllTimes, public
+//
+// Synopsis: Gets all time values
+//
+// Arguments: [patm] - Access Time
+// [pmtm] - Modification Time
+// [pctm] - Creation Time
+//
+// Returns: Appropriate status code
+//
+// Modifies: [patm]
+// [pmtm]
+// [pctm]
+//
+// History: 26-May-95 SusiA Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_GetAllTimes)
+#endif
+
+SCODE CDocFile::GetAllTimes(TIME_T *patm, TIME_T *pmtm, TIME_T *pctm)
+{
+ return _stgh.GetAllTimes(patm, pmtm, pctm);
+}
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::SetAllTimes, public
+//
+// Synopsis: Sets all time values
+//
+// Arguments: [atm] - Access Time
+// [mtm] - Modification Time
+// [ctm] - Creation Time
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 22-Nov-95 SusiA Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_SetAllTimes)
+#endif
+
+SCODE CDocFile::SetAllTimes(TIME_T atm, TIME_T mtm, TIME_T ctm)
+{
+ return _stgh.SetAllTimes(atm, mtm, ctm);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::SetTime, public
+//
+// Synopsis: Sets a time
+//
+// Arguments: [wt] - Which time
+// [tm] - New time
+//
+// Returns: Appropriate status code
+//
+// History: 31-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_SetTime)
+#endif
+
+SCODE CDocFile::SetTime(WHICHTIME wt, TIME_T tm)
+{
+ return _stgh.SetTime(wt, tm);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::GetClass, public
+//
+// Synopsis: Gets the class ID
+//
+// Arguments: [pclsid] - Class ID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pclsid]
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_GetClass)
+#endif
+
+SCODE CDocFile::GetClass(CLSID *pclsid)
+{
+ return _stgh.GetClass(pclsid);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::SetClass, public
+//
+// Synopsis: Sets the class ID
+//
+// Arguments: [clsid] - New class ID
+//
+// Returns: Appropriate status code
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_SetClass)
+#endif
+
+SCODE CDocFile::SetClass(REFCLSID clsid)
+{
+ return _stgh.SetClass(clsid);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::GetStateBits, public
+//
+// Synopsis: Gets the state bits
+//
+// Arguments: [pgrfStateBits] - State bits return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pgrfStateBits]
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_GetStateBits)
+#endif
+
+SCODE CDocFile::GetStateBits(DWORD *pgrfStateBits)
+{
+ return _stgh.GetStateBits(pgrfStateBits);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::SetStateBits, public
+//
+// Synopsis: Sets the state bits
+//
+// Arguments: [grfStateBits] - Bits to set
+// [grfMask] - Mask
+//
+// Returns: Appropriate status code
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_SetStateBits)
+#endif
+
+SCODE CDocFile::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ return _stgh.SetStateBits(grfStateBits, grfMask);
+}
+
+
diff --git a/private/ole32/stg/docfile/chinst.cxx b/private/ole32/stg/docfile/chinst.cxx
new file mode 100644
index 000000000..648d7d1fc
--- /dev/null
+++ b/private/ole32/stg/docfile/chinst.cxx
@@ -0,0 +1,266 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992
+//
+// File: chinst.cxx
+//
+// Contents: DocFile child instance management code
+//
+// History: 19-Nov-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+// Permissions checked in the less-restrictive rule
+#define TCANTSET DF_READ
+#define DCANTSET (DF_READ | DF_WRITE)
+#define CANTCLEAR (DF_DENYREAD | DF_DENYWRITE)
+
+//+--------------------------------------------------------------
+//
+// Method: CChildInstanceList::Add, private
+//
+// Synopsis: Registers an instance of a child
+//
+// Arguments: [prv] - Child
+//
+// History: 17-Oct-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CChildInstanceList_Add)
+#endif
+
+void CChildInstanceList::Add(PRevertable *prv)
+{
+ olDebugOut((DEB_ITRACE, "In CChildInstanceList::Add(%p)\n", prv));
+ prv->_prvNext = _prvHead;
+ _prvHead = P_TO_BP(CBasedRevertablePtr, prv);
+ olDebugOut((DEB_ITRACE, "Out CChildInstanceList::Add\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CChildInstanceList::FindByName, private
+//
+// Synopsis: Finds a child instance by name
+//
+// Arguments: [pdfn] - Name
+//
+// Returns: Pointer to instance or NULL
+//
+// History: 12-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CChildInstanceList_FindByName)
+#endif
+
+PRevertable *CChildInstanceList::FindByName(CDfName const *pdfn)
+{
+ PRevertable *prv;
+
+ olDebugOut((DEB_ITRACE, "In CChildInstanceList::FindByName:%p(%ws)\n",
+ this, pdfn->GetBuffer()));
+ for (prv = BP_TO_P(PRevertable *, _prvHead);
+ prv;
+ prv = BP_TO_P(PRevertable *, prv->_prvNext))
+ {
+ if (prv->_dfn.IsEqual(pdfn))
+ return prv;
+ }
+ olDebugOut((DEB_ITRACE, "Out CChildInstanceList::FindByName\n"));
+ return NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CChildInstanceList::FlushBufferedData, private
+//
+// Synopsis: Calls each child, instructing it to flush property data.
+//
+// Arguments: [recursionlevel] -- current level in hierachy below initial
+// entry point.
+//
+// Returns: SCODE
+//
+// History: 5-May-1995 BillMo Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef NEWPROPS
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CChildInstanceList_FindByName)
+#endif
+
+SCODE CChildInstanceList::FlushBufferedData(int recursionlevel)
+{
+ PRevertable *prv;
+ SCODE sc = S_OK;
+
+ olDebugOut((DEB_ITRACE, "In CChildInstanceList::FlushBufferedData:%p\n",
+ this));
+
+ for (prv = BP_TO_P(PRevertable *, _prvHead);
+ prv && sc == S_OK;
+ prv = BP_TO_P(PRevertable *, prv->_prvNext))
+ {
+ sc = prv->FlushBufferedData(recursionlevel + 1);
+ }
+ olDebugOut((DEB_ITRACE, "Out CChildInstanceList::FlushBufferedData\n"));
+ return sc;
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Method: CChildInstanceList::DeleteByName, private
+//
+// Synopsis: Removes an instance from the instance list
+// and reverts it
+//
+// Arguments: [pdfn] - Name or NULL
+//
+// History: 17-Oct-91 DrewB Created
+//
+// Notes: The entry does not have to exist
+// There can be multiple entries
+// If name is NULL, all entries match
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CChildInstanceList_DeleteByName)
+#endif
+
+void CChildInstanceList::DeleteByName(CDfName const *pdfn)
+{
+ CBasedRevertablePtr *pprv;
+
+ olDebugOut((DEB_ITRACE, "In CChildInstanceList::DeleteByName(%ws)\n",
+ pdfn->GetBuffer()));
+ for (pprv = &_prvHead; *pprv; )
+ if (NULL == pdfn || (*pprv)->_dfn.IsEqual(pdfn))
+ {
+ (*pprv)->RevertFromAbove();
+ *pprv = (*pprv)->_prvNext;
+ }
+ else
+ pprv = &(*pprv)->_prvNext;
+ olDebugOut((DEB_ITRACE, "Out CChildInstanceList::DeleteByName\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Method: CChildInstanceList::RemoveRv, private
+//
+// Synopsis: Removes a specific instance from the instance list
+//
+// Arguments: [prv] - Instance
+//
+// History: 17-Oct-91 DrewB Created
+//
+// Notes: The entry does not have to exist
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CChildInstanceList_RemoveRv)
+#endif
+
+void CChildInstanceList::RemoveRv(PRevertable *prvRv)
+{
+ CBasedRevertablePtr *prv;
+
+ olDebugOut((DEB_ITRACE, "In CChildInstanceList::RemoveRv(%p)\n", prvRv));
+ for (prv = &_prvHead; *prv; prv = &(*prv)->_prvNext)
+ if (*prv == prvRv)
+ {
+ *prv = (*prv)->_prvNext;
+ break;
+ }
+ olDebugOut((DEB_ITRACE, "Out CChildInstanceList::RemoveRv\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Method: CChildInstanceList::IsDenied, private
+//
+// Synopsis: Checks the parent instantiation list for a previous
+// instance of the given child with DENY flags on
+// Also determines whether child mode flags are
+// less restrictive than the parent's
+//
+// Arguments: [pdfn] - Instance name
+// [dfCheck] - Access modes to check for denial
+// [dfAgainst] - Access modes to check against
+//
+// Returns: Appropriate status code
+//
+// History: 17-Oct-91 DrewB Created
+// 28-Oct-92 AlexT Converted to names
+//
+// Notes: The instance doesn't have to be in the list.
+// If it isn't, it's not denied
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CChildInstanceList_IsDenied)
+#endif
+
+SCODE CChildInstanceList::IsDenied(CDfName const *pdfn,
+ DFLAGS const dfCheck,
+ DFLAGS const dfAgainst)
+{
+ PRevertable *prv;
+ SCODE sc = S_OK;
+
+ olDebugOut((DEB_ITRACE, "In CChildInstanceList::IsDenied("
+ "%p, %lX, %lX)\n", pdfn, dfCheck, dfAgainst));
+
+ olAssert(pdfn != NULL && aMsg("IsDenied, null name"));
+
+ // Check to see if permissions are less restrictive than
+ // parent permissions
+ // This checks to see that a child isn't specifying
+ // a permission that its parent doesn't
+ // For example, giving read permission when the parent
+ // doesn't
+ if ((~dfAgainst & dfCheck &
+ (P_TRANSACTED(dfAgainst) ? TCANTSET : DCANTSET)) ||
+ (dfAgainst & ~dfCheck & CANTCLEAR))
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+
+ // Check for DENY_*
+ olAssert((DF_DENYALL >> DF_DENIALSHIFT) == DF_READWRITE);
+ for (prv = BP_TO_P(PRevertable *, _prvHead);
+ prv != NULL; prv = prv->GetNext())
+ {
+ if (prv->_dfn.IsEqual(pdfn))
+ {
+ // Check for existing instance with DENY_* mode
+ if ((((prv->GetDFlags() & DF_DENYALL) >> DF_DENIALSHIFT) &
+ dfCheck) != 0 ||
+ // Check for instance with permission already given that
+ // new instance wants to deny
+ (((dfCheck & DF_DENYALL) >> DF_DENIALSHIFT) &
+ prv->GetDFlags()) != 0)
+ {
+ sc = STG_E_ACCESSDENIED;
+ break;
+ }
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out CChildInstanceList::IsDenied\n"));
+ // Fall through
+EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/docfile/daytona/makefile b/private/ole32/stg/docfile/daytona/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ole32/stg/docfile/daytona/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/stg/docfile/daytona/sources b/private/ole32/stg/docfile/daytona/sources
new file mode 100644
index 000000000..2a0ec2fb2
--- /dev/null
+++ b/private/ole32/stg/docfile/daytona/sources
@@ -0,0 +1,105 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= docfile
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES=..\..\..\ih;..\..\..\com\inc;..\..\..\common\daytona;..\..\h;..;..\..\..\..\types\new_ole;..\..\..\..\inc
+
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+SOURCES= \
+ ..\cdocfile.cxx\
+ ..\chinst.cxx\
+ ..\debug.cxx\
+ ..\dfbasis.cxx\
+ ..\dffuncs.cxx\
+ ..\dfiter.cxx\
+ ..\dfname.cxx\
+ ..\dfstream.cxx\
+ ..\dfxact.cxx\
+ ..\entry.cxx\
+ ..\freelist.cxx\
+ ..\funcs.cxx\
+ ..\mem.cxx\
+ ..\smalloc.cxx\
+ ..\pdffuncs.cxx\
+ ..\publicdf.cxx\
+ ..\rpubdf.cxx\
+ ..\tlsets.cxx\
+ ..\tset.cxx\
+ ..\ulist.cxx\
+ ..\wdffuncs.cxx\
+ ..\wdfiter.cxx\
+ ..\wdfstrm.cxx\
+ ..\wdfxact.cxx\
+ ..\wdocfile.cxx\
+ ..\fastlock.cxx
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+PRECOMPILED_INCLUDE= ..\dfhead.cxx
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
diff --git a/private/ole32/stg/docfile/debug.cxx b/private/ole32/stg/docfile/debug.cxx
new file mode 100644
index 000000000..3cc2b31f8
--- /dev/null
+++ b/private/ole32/stg/docfile/debug.cxx
@@ -0,0 +1,773 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992
+//
+// File: debug.cxx
+//
+// Contents: Debugging routines
+//
+// History: 07-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+#if DBG == 1
+#include <w4wchar.h>
+
+#include <stdarg.h>
+#include <dfdeb.hxx>
+#include <logfile.hxx>
+#include <df32.hxx>
+
+//+-------------------------------------------------------------
+//
+// Function: DfDebug, public
+//
+// Synopsis: Sets debugging level
+//
+//---------------------------------------------------------------
+
+DECLARE_INFOLEVEL(ol);
+
+#define LOGFILENAME L"logfile.txt"
+
+static CGlobalFileStream *_pgfstLogFiles = NULL;
+WCHAR gwcsLogFile[] = LOGFILENAME;
+
+STDAPI_(void) DfDebug(ULONG ulLevel, ULONG ulMSFLevel)
+{
+#if DBG == 1
+ olInfoLevel = ulLevel;
+ SetInfoLevel(ulMSFLevel);
+ _SetWin4InfoLevel(ulLevel | ulMSFLevel);
+
+ olDebugOut((DEB_ITRACE, "\n-- DfDebug(0x%lX, 0x%lX)\n",
+ ulLevel, ulMSFLevel));
+#endif
+}
+
+// NT and Cairo
+#ifdef WIN32
+#if 0
+// Throw Win32 error information
+#define THROW_LAST_ERROR() THROW_SC(LAST_SCODE)
+
+//+---------------------------------------------------------------------------
+//
+// Class: CDfGlobalMemory (dgm)
+//
+// Purpose: Create a fixed size chunk of globally shared memory
+//
+// Interface: See below
+//
+// History: 06-May-93 DrewB Created
+//
+// Notes: The init function is only called once when the shared
+// memory is first created.
+//
+// The end function is only called once when the last
+// reference to the global memory is released
+//
+// The reference count is added onto the global allocation
+// and kept at offset zero so the address returned to
+// client code is offset by sizeof(LONG)
+//
+//----------------------------------------------------------------------------
+
+typedef void (*DfGlobalMemoryFn)(void *);
+
+class CDfGlobalMemory
+{
+public:
+ CDfGlobalMemory(TCHAR const *ptcsName,
+ DWORD cbSize,
+ DfGlobalMemoryFn pfnInit,
+ DfGlobalMemoryFn pfnEnd);
+ ~CDfGlobalMemory(void);
+
+ inline void *GetAddress(void) const;
+
+private:
+ inline LONG *RefCount(void);
+
+ HANDLE _hMapping;
+ void *_pvMemory;
+ DfGlobalMemoryFn _pfnEnd;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDfGlobalMemory::GetAddress, public
+//
+// Synopsis: Returns the address of the shared memory
+//
+// History: 06-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void *CDfGlobalMemory::GetAddress(void) const
+{
+ return (void *)((LONG *)_pvMemory+1);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDfGlobalMemory::RefCount, private
+//
+// Synopsis: Returns a pointer to the reference count
+//
+// History: 07-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline LONG *CDfGlobalMemory::RefCount(void)
+{
+ return (LONG *)_pvMemory;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDfGlobalMemory::CDfGlobalMemory, public
+//
+// Synopsis: Creates a chunk of global memory
+//
+// Arguments: [ptcsName] - Name for sharing
+// [cbSize] - Size of chunk
+// [pfnInit] - Initialization function or NULL
+// [pfnEnd] - Shutdown function or NULL
+//
+// History: 06-May-93 DrewB Created
+//
+// Notes: Allowed to throw on failure; this is debug only code
+//
+//----------------------------------------------------------------------------
+
+CDfGlobalMemory::CDfGlobalMemory(TCHAR const *ptcsName,
+ DWORD cbSize,
+ DfGlobalMemoryFn pfnInit,
+ DfGlobalMemoryFn pfnEnd)
+{
+ BOOL fOpened;
+#if WIN32 == 100 || WIN32 > 200
+ CGlobalSecurity gs;
+ SCODE sc;
+
+ if (FAILED(sc = gs.Init()))
+ THROW_SC(sc);
+ _hMapping = CreateFileMapping((HANDLE)0xFFFFFFFF, gs, PAGE_READWRITE,
+ 0, cbSize+sizeof(LONG), (TCHAR *)ptcsName);
+#else
+ _hMapping = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE,
+ 0, cbSize+sizeof(LONG), (TCHAR *)ptcsName);
+#endif
+ if (_hMapping == NULL)
+ THROW_LAST_ERROR();
+
+ fOpened = GetLastError() == ERROR_ALREADY_EXISTS;
+
+ _pvMemory = MapViewOfFile(_hMapping, FILE_MAP_ALL_ACCESS,
+ 0, 0, 0);
+ if (_pvMemory == NULL)
+ {
+ CloseHandle(_hMapping);
+ THROW_LAST_ERROR();
+ }
+
+ if (pfnInit && !fOpened)
+ {
+ *(RefCount()) = 0;
+ pfnInit(GetAddress());
+ }
+
+ _pfnEnd = pfnEnd;
+ InterlockedIncrement(RefCount());
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDfGlobalMemory::~CDfGlobalMemory, public
+//
+// Synopsis: Releases resources for shared memory
+//
+// History: 06-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CDfGlobalMemory::~CDfGlobalMemory(void)
+{
+ if (InterlockedDecrement(RefCount()) == 0 && _pfnEnd)
+ _pfnEnd(GetAddress());
+
+ UnmapViewOfFile(_pvMemory);
+ CloseHandle(_hMapping);
+}
+#endif //0
+#endif // WIN32
+
+// Resource limits
+
+static LONG lResourceLimits[CDBRESOURCES] =
+{
+ 0x7fffffff, // DBR_MEMORY
+ 0x7fffffff, // DBR_XSCOMMITS
+ 0x0, // DBR_FAILCOUNT
+ 0x0, // DBR_FAILLIMIT
+ 0x0, // DBRQ_MEMORY_ALLOCATED
+ 0x0, // DBRI_ALLOC_LIST
+ 0x0, // DBRI_LOGFILE_LIST
+ 0x0 // DBRF_LOGGING
+};
+
+#define CBRESOURCES sizeof(lResourceLimits)
+
+#if 0
+
+static CStaticDfMutex _sdmtxResources(TSTR("DfResourceMutex"));
+
+static void ResInit(void *pvMemory)
+{
+ // Initialize limits
+ memcpy(pvMemory, lResourceLimits, CBRESOURCES);
+}
+
+static CDfGlobalMemory _dgmResourceLimits(TSTR("DfResourceMemory"),
+ CBRESOURCES,
+ ResInit,
+ NULL);
+
+#define RESLIMIT(n) \
+ (*((LONG *)_dgmResourceLimits.GetAddress()+(n)))
+
+#define TAKEMTX \
+ olVerSucc(_sdmtxResources.Take(INFINITE))
+#define RELEASEMTX \
+ _sdmtxResources.Release();
+
+#else
+
+#define RESLIMIT(n) lResourceLimits[n]
+#define TAKEMTX
+#define RELEASEMTX
+
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: DfSetResLimit, public
+//
+// Synopsis: Sets a resource limit
+//
+// History: 24-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(void) DfSetResLimit(UINT iRes, LONG lLimit)
+{
+ TAKEMTX;
+
+ RESLIMIT(iRes) = lLimit;
+
+ RELEASEMTX;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DfGetResLimit, public
+//
+// Synopsis: Gets a resource limit
+//
+// History: 24-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(LONG) DfGetResLimit(UINT iRes)
+{
+ // Doesn't need serialization
+ return RESLIMIT(iRes);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: HaveResource, private
+//
+// Synopsis: Checks to see if a resource limit is exceeded
+// and consumes resource if not
+//
+// History: 24-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+BOOL HaveResource(UINT iRes, LONG lRequest)
+{
+ if (RESLIMIT(iRes) >= lRequest)
+ {
+ TAKEMTX;
+
+ RESLIMIT(iRes) -= lRequest;
+
+ RELEASEMTX;
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ModifyResLimit, private
+//
+// Synopsis: Adds to a resource limit
+//
+// History: 24-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+LONG ModifyResLimit(UINT iRes, LONG lChange)
+{
+ LONG l;
+
+ TAKEMTX;
+
+ RESLIMIT(iRes) += lChange;
+ l = RESLIMIT(iRes);
+
+ RELEASEMTX;
+
+ return l;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SimulateFailure
+//
+// Synopsis: Check for simulated failure
+//
+// Effects: Tracks failure count
+//
+// Arguments: [failure] -- failure type
+//
+// Returns: TRUE if call should fail, FALSE if call should succeed
+//
+// Modifies: RESLIMIT(DBR_FAILCOUNT)
+//
+// Algorithm: Increment failure count, fail if count has succeeded
+// limit
+//
+// History: 21-Jan-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+BOOL SimulateFailure(DBFAILURE failure)
+{
+ LONG l;
+ BOOL fFail;
+
+ // We don't special case failure types, yet.
+
+ TAKEMTX;
+
+ RESLIMIT(DBR_FAILCOUNT)++;
+ l = RESLIMIT(DBR_FAILLIMIT);
+ fFail = RESLIMIT(DBR_FAILCOUNT) >= l;
+
+ RELEASEMTX;
+
+ if (l == 0)
+ {
+ // We're not simulating any failures; just tracking them
+ return(FALSE);
+ }
+
+ return fFail;
+}
+
+//+--------------------------------------------------------------
+//
+// Class: CChecksumBlock (cb)
+//
+// Purpose: Holds a memory block that is being checksummed
+//
+// Interface: See below
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+class CChecksumBlock
+{
+public:
+ CChecksumBlock(char *pszName,
+ void *pvAddr,
+ ULONG cBytes,
+ DWORD dwFlags,
+ CChecksumBlock *pcbNext,
+ CChecksumBlock *pcbPrev);
+ ~CChecksumBlock(void);
+
+ char *_pszName;
+ void *_pvAddr;
+ ULONG _cBytes;
+ DWORD _dwFlags;
+ CChecksumBlock *_pcbNext, *_pcbPrev;
+ ULONG _ulChecksum;
+};
+
+// Global list of checksummed blocks
+static CChecksumBlock *pcbChkBlocks = NULL;
+
+//+--------------------------------------------------------------
+//
+// Member: CChecksumBlock::CChecksumBlock, private
+//
+// Synopsis: Ctor
+//
+// Arguments: [pszName] - Block name
+// [pvAddr] - Starting addr
+// [cBytes] - Length
+// [dwFlags] - Type flags
+// [pcbNext] - Next checksum block
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CChecksumBlock::CChecksumBlock(char *pszName,
+ void *pvAddr,
+ ULONG cBytes,
+ DWORD dwFlags,
+ CChecksumBlock *pcbNext,
+ CChecksumBlock *pcbPrev)
+{
+ ULONG i;
+ char *pc;
+
+ olVerify(_pszName = new char[strlen(pszName)+1]);
+ strcpy(_pszName, pszName);
+ _pvAddr = pvAddr;
+ _cBytes = cBytes;
+ _dwFlags = dwFlags;
+ _pcbNext = pcbNext;
+ if (pcbNext)
+ pcbNext->_pcbPrev = this;
+ _pcbPrev = pcbPrev;
+ if (pcbPrev)
+ pcbPrev->_pcbNext = this;
+ _ulChecksum = 0;
+ pc = (char *)pvAddr;
+ for (i = 0; i<cBytes; i++)
+ _ulChecksum += *pc++;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CChecksumBlock::~CChecksumBlock, private
+//
+// Synopsis: Dtor
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CChecksumBlock::~CChecksumBlock(void)
+{
+ delete _pszName;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: DbgChkBlocks, private
+//
+// Synopsis: Verify checksums on all current blocks
+//
+// Arguments: [dwFlags] - Types of blocks to check
+// [pszFile] - File check was called from
+// [iLine] - Line in file
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+void DbgChkBlocks(DWORD dwFlags, char *pszFile, int iLine)
+{
+ CChecksumBlock *pcb;
+
+ for (pcb = pcbChkBlocks; pcb; pcb = pcb->_pcbNext)
+ if (pcb->_dwFlags & dwFlags)
+ {
+ ULONG i, ulSum = 0;
+ char *pc;
+
+ for (pc = (char *)pcb->_pvAddr, i = 0; i<pcb->_cBytes; i++)
+ ulSum += *pc++;
+ if (ulSum != pcb->_ulChecksum)
+ olDebugOut((DEB_ERROR, "* Bad checksum %s:%d '%s' %p:%lu *\n",
+ pszFile, iLine, pcb->_pszName,
+ pcb->_pvAddr, pcb->_cBytes));
+ else if (dwFlags & DBG_VERBOSE)
+ olDebugOut((DEB_ERROR, "* Checksum passed %s:%d"
+ " '%s' %p:%lu *\n",
+ pszFile, iLine, pcb->_pszName,
+ pcb->_pvAddr, pcb->_cBytes));
+ }
+}
+
+//+--------------------------------------------------------------
+//
+// Function: DbgAddChkBlock, private
+//
+// Synopsis: Adds a checksum block
+//
+// Arguments: [pszName] - Name of block
+// [pvAddr] - Starting addr
+// [cBytes] - Length
+// [dwFlags] - Type flags
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+void DbgAddChkBlock(char *pszName,
+ void *pvAddr,
+ ULONG cBytes,
+ DWORD dwFlags)
+{
+ CChecksumBlock *pcb;
+
+ olVerify(pcb = new CChecksumBlock(pszName, pvAddr, cBytes,
+ dwFlags, pcbChkBlocks, NULL));
+ pcbChkBlocks = pcb;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: DbgFreeChkBlock, private
+//
+// Synopsis: Removes a block from the list
+//
+// Arguments: [pvAddr] - Block's check address
+//
+// History: 10-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+void DbgFreeChkBlock(void *pvAddr)
+{
+ CChecksumBlock *pcb;
+
+ for (pcb = pcbChkBlocks; pcb; pcb = pcb->_pcbNext)
+ if (pcb->_pvAddr == pvAddr)
+ {
+ if (pcb->_pcbPrev)
+ pcb->_pcbPrev->_pcbNext = pcb->_pcbNext;
+ else
+ pcbChkBlocks = pcb->_pcbNext;
+ if (pcb->_pcbNext)
+ pcb->_pcbNext->_pcbPrev = pcb->_pcbPrev;
+ delete pcb;
+ return;
+ }
+}
+
+//+--------------------------------------------------------------
+//
+// Function: DbgFreeChkBlocks, private
+//
+// Synopsis: Frees all checksum blocks
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+void DbgFreeChkBlocks(void)
+{
+ CChecksumBlock *pcb;
+
+ while (pcbChkBlocks)
+ {
+ pcb = pcbChkBlocks->_pcbNext;
+ delete pcbChkBlocks;
+ pcbChkBlocks = pcb;
+ }
+}
+
+inline CGlobalFileStream *GetGlobalFileStream()
+{
+ return((CGlobalFileStream *)DfGetResLimit(DBRI_LOGFILE_LIST));
+}
+
+inline void SetGlobalFileStream(CGlobalFileStream *pgfst)
+{
+ DfSetResLimit(DBRI_LOGFILE_LIST, (LONG) pgfst);
+}
+
+#ifdef MULTIHEAP
+static CGlobalFileStream *g_pDebugLogGlobalFileStream = NULL;
+static CFileStream *g_pDebugLogFileStream = NULL;
+#endif
+
+
+SCODE GetLogFile(CFileStream **pfs)
+#ifdef MULTIHEAP
+{
+ // Do not use shared memory to write log files
+ SCODE sc = S_OK;
+
+ if (GetGlobalFileStream() == NULL)
+ {
+ g_pDebugLogGlobalFileStream = ::new CGlobalFileStream
+ (NULL, 0, LOGFILEDFFLAGS, LOGFILESTARTFLAGS);
+ SetGlobalFileStream (g_pDebugLogGlobalFileStream);
+
+ g_pDebugLogFileStream = ::new CFileStream (NULL);
+ }
+ g_pDebugLogFileStream->InitFromGlobal(GetGlobalFileStream());
+ *pfs = g_pDebugLogFileStream;
+ return sc;
+}
+#else
+{
+ SCODE sc = S_OK;
+ CFileStream *pfsLoop = NULL;
+
+ *pfs = NULL;
+
+ if (GetGlobalFileStream() == NULL)
+ {
+ IMalloc *pMalloc;
+
+#ifdef WIN32
+ olHChk(DfCreateSharedAllocator(&pMalloc));
+#else
+ olHChk(CoGetMalloc(MEMCTX_SHARED, &pMalloc));
+#endif
+ SetGlobalFileStream(new (pMalloc) CGlobalFileStream(pMalloc,
+ 0, LOGFILEDFFLAGS,
+ LOGFILESTARTFLAGS));
+ pMalloc->Release();
+ }
+
+ if (GetGlobalFileStream() != NULL)
+ {
+ pfsLoop = GetGlobalFileStream()->Find(GetCurrentContextId());
+
+ if (pfsLoop == NULL)
+ {
+ IMalloc *pMalloc;
+#ifdef WIN32
+ olHChk(DfCreateSharedAllocator(&pMalloc));
+#else
+ olHChk(CoGetMalloc(MEMCTX_SHARED, &pMalloc));
+#endif
+
+ pfsLoop = new (pMalloc) CFileStream(pMalloc);
+ pMalloc->Release();
+
+ if (pfsLoop != NULL)
+ pfsLoop->InitFromGlobal(GetGlobalFileStream());
+ }
+ }
+
+EH_Err:
+ *pfs = pfsLoop;
+ return sc;
+}
+#endif // MULIHEAP
+
+SCODE _FreeLogFile(void)
+{
+#ifdef MULTIHEAP
+ if (GetGlobalFileStream())
+ {
+ g_pDebugLogFileStream->RemoveFromGlobal();
+ memset (g_pDebugLogGlobalFileStream, 0, sizeof(CContextList));
+ SetGlobalFileStream (NULL);
+ ::delete g_pDebugLogFileStream;
+ ::delete g_pDebugLogGlobalFileStream;
+ }
+ return S_OK;
+#else
+ CFileStream *pfsLoop = NULL;
+
+ if (GetGlobalFileStream())
+ pfsLoop = GetGlobalFileStream()->Find(GetCurrentContextId());
+
+ if (pfsLoop != NULL)
+ {
+ pfsLoop->vRelease();
+ GetGlobalFileStream()->Release();
+ SetGlobalFileStream(NULL);
+ return S_OK;
+ }
+
+ return STG_E_UNKNOWN;
+#endif
+}
+
+long cLogNestings = 0;
+
+void OutputLogfileMessage(char const *format, ...)
+{
+ int length;
+ char achPreFormat[] = "PID[%lx] TID[%lx] ";
+ char achBuffer[256];
+ ULONG cbWritten;
+ CFileStream *pfs = NULL;
+ va_list arglist;
+ STATSTG stat;
+
+ if (cLogNestings > 0)
+ return;
+
+ TAKEMTX;
+ cLogNestings++;
+
+ va_start(arglist, format);
+
+ GetLogFile(&pfs);
+
+ if (NULL != pfs)
+ {
+ pfs->Init(gwcsLogFile);
+ pfs->Stat(&stat, STATFLAG_NONAME);
+
+ if (DfGetResLimit(DBRF_LOGGING) & DFLOG_PIDTID)
+ {
+ // Prepare prefix string
+ length = wsprintfA(achBuffer, "PID[%8lx] TID[%8lx] ",
+ GetCurrentProcessId(), GetCurrentThreadId());
+
+ // length does not include NULL terminator
+
+ pfs->WriteAt(stat.cbSize, achBuffer, length, &cbWritten);
+ stat.cbSize.LowPart += cbWritten;
+ }
+
+ // Write caller data to logfile
+#if WIN32 == 300
+ wsprintfA(achBuffer, format, arglist);
+#else
+ w4vsprintf(achBuffer, format, arglist);
+#endif
+
+ length = strlen(achBuffer);
+ for (int i = 0; i < length; i++)
+ {
+ if (((achBuffer[i] < 32) || (achBuffer[i] > 127)) &&
+ (achBuffer[i] != '\n') && (achBuffer[i] != '\t'))
+ {
+ achBuffer[i] = '.';
+ }
+ }
+
+ pfs->WriteAt(stat.cbSize, achBuffer, length, &cbWritten);
+ }
+
+ cLogNestings--;
+ RELEASEMTX;
+}
+
+#endif // DBG == 1
diff --git a/private/ole32/stg/docfile/depend.mk1 b/private/ole32/stg/docfile/depend.mk1
new file mode 100644
index 000000000..b8e8be4d4
--- /dev/null
+++ b/private/ole32/stg/docfile/depend.mk1
@@ -0,0 +1,1437 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\cdocfile.obj $(OBJDIR)\cdocfile.lst: .\cdocfile.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\chinst.obj $(OBJDIR)\chinst.lst: .\chinst.cxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\STG\docfile\segdf.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cdocfile.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\prspec.h $(OLE2H)\stream.h $(OLE2H)\varnt.h \
+ $(OLE2H)\wtypes.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\rpc.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\debug.obj $(OBJDIR)\debug.lst: .\debug.cxx \
+ $(CAIROLE)\stg\h\dfdeb.hxx $(CAIROLE)\STG\docfile\segdf.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cdocfile.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\wtypes.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\dfbasis.obj $(OBJDIR)\dfbasis.lst: .\dfbasis.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\wtypes.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\dffuncs.obj $(OBJDIR)\dffuncs.lst: .\dffuncs.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\dfiter.obj $(OBJDIR)\dfiter.lst: .\dfiter.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\dfname.obj $(OBJDIR)\dfname.lst: .\dfname.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\dfstream.obj $(OBJDIR)\dfstream.lst: .\dfstream.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\dfxact.obj $(OBJDIR)\dfxact.lst: .\dfxact.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\entry.obj $(OBJDIR)\entry.lst: .\entry.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\freelist.obj $(OBJDIR)\freelist.lst: .\freelist.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\funcs.obj $(OBJDIR)\funcs.lst: .\funcs.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\mem.obj $(OBJDIR)\mem.lst: .\mem.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfdeb.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dlink.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types16.h \
+ $(COMMON)\ih\win4p.h $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\dos.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\pdffuncs.obj $(OBJDIR)\pdffuncs.lst: .\pdffuncs.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\publicdf.obj $(OBJDIR)\publicdf.lst: .\publicdf.cxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\h\pbstream.hxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\time.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\rpubdf.obj $(OBJDIR)\rpubdf.lst: .\rpubdf.cxx \
+ $(CAIROLE)\stg\h\rpubdf.hxx $(CAIROLE)\STG\docfile\segdf.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cdocfile.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\sngprop.obj $(OBJDIR)\sngprop.lst: .\sngprop.cxx \
+ $(CAIROLE)\stg\h\props.hxx $(CAIROLE)\stg\h\sngprop.hxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pbstream.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\memalloc.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\tlsets.obj $(OBJDIR)\tlsets.lst: .\tlsets.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\tset.obj $(OBJDIR)\tset.lst: .\tset.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\ulist.obj $(OBJDIR)\ulist.lst: .\ulist.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\wdffuncs.obj $(OBJDIR)\wdffuncs.lst: .\wdffuncs.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\wdfiter.obj $(OBJDIR)\wdfiter.lst: .\wdfiter.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\wdfstrm.obj $(OBJDIR)\wdfstrm.lst: .\wdfstrm.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\wdfxact.obj $(OBJDIR)\wdfxact.lst: .\wdfxact.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfdeb.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\wdocfile.obj $(OBJDIR)\wdocfile.lst: .\wdocfile.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\dfhead.pxh $(PCHDIR)\$(OBJDIR)\dfhead.lst: \
+ $(CAIROLE)\stg\docfile\dfhead.cxx $(CAIROLE)\STG\docfile\segdf.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cdocfile.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+.\$(OBJDIR)\cdocfile.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\chinst.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\debug.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfbasis.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dffuncs.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfiter.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfname.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfstream.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfxact.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\entry.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\freelist.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\funcs.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\mem.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\pdffuncs.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\publicdf.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\rpubdf.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\sngprop.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\tlsets.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\tset.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\ulist.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdffuncs.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdfiter.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdfstrm.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdfxact.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdocfile.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/docfile/depend.mk3 b/private/ole32/stg/docfile/depend.mk3
new file mode 100644
index 000000000..22232ec3f
--- /dev/null
+++ b/private/ole32/stg/docfile/depend.mk3
@@ -0,0 +1,1177 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\cdocfile.obj $(OBJDIR)\cdocfile.lst: .\cdocfile.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\chinst.obj $(OBJDIR)\chinst.lst: .\chinst.cxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\scode.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winmm.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\debug.obj $(OBJDIR)\debug.lst: .\debug.cxx \
+ $(CAIROLE)\stg\h\dfdeb.hxx $(CAIROLE)\stg\docfile\segdf.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cdocfile.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\dfbasis.obj $(OBJDIR)\dfbasis.lst: .\dfbasis.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\dffuncs.obj $(OBJDIR)\dffuncs.lst: .\dffuncs.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\dfiter.obj $(OBJDIR)\dfiter.lst: .\dfiter.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\dfname.obj $(OBJDIR)\dfname.lst: .\dfname.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\dfstream.obj $(OBJDIR)\dfstream.lst: .\dfstream.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\dfxact.obj $(OBJDIR)\dfxact.lst: .\dfxact.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\entry.obj $(OBJDIR)\entry.lst: .\entry.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\freelist.obj $(OBJDIR)\freelist.lst: .\freelist.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\funcs.obj $(OBJDIR)\funcs.lst: .\funcs.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\mem.obj $(OBJDIR)\mem.lst: .\mem.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfdeb.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dlink.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types16.h \
+ $(COMMON)\ih\win4p.h $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\dos.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\pdffuncs.obj $(OBJDIR)\pdffuncs.lst: .\pdffuncs.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\publicdf.obj $(OBJDIR)\publicdf.lst: .\publicdf.cxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\h\pbstream.hxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\time.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winmm.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\rpubdf.obj $(OBJDIR)\rpubdf.lst: .\rpubdf.cxx \
+ $(CAIROLE)\stg\h\rpubdf.hxx $(CAIROLE)\stg\docfile\segdf.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cdocfile.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\tlsets.obj $(OBJDIR)\tlsets.lst: .\tlsets.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\tset.obj $(OBJDIR)\tset.lst: .\tset.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\ulist.obj $(OBJDIR)\ulist.lst: .\ulist.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\wdffuncs.obj $(OBJDIR)\wdffuncs.lst: .\wdffuncs.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\wdfiter.obj $(OBJDIR)\wdfiter.lst: .\wdfiter.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\wdfstrm.obj $(OBJDIR)\wdfstrm.lst: .\wdfstrm.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\wdfxact.obj $(OBJDIR)\wdfxact.lst: .\wdfxact.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfdeb.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+$(OBJDIR)\wdocfile.obj $(OBJDIR)\wdocfile.lst: .\wdocfile.cxx \
+ $(CAIROLE)\stg\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\dfhead.cxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\dfhead.pxh $(PCHDIR)\$(OBJDIR)\dfhead.lst: \
+ $(CAIROLE)\stg\docfile\dfhead.cxx $(CAIROLE)\stg\docfile\segdf.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cdocfile.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+.\$(OBJDIR)\cdocfile.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\chinst.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\debug.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfbasis.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dffuncs.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfiter.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfname.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfstream.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfxact.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\entry.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\freelist.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\funcs.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\mem.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\pdffuncs.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\publicdf.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\rpubdf.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\tlsets.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\tset.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\ulist.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdffuncs.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdfiter.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdfstrm.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdfxact.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdocfile.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/docfile/depend.mk9 b/private/ole32/stg/docfile/depend.mk9
new file mode 100644
index 000000000..2cd297863
--- /dev/null
+++ b/private/ole32/stg/docfile/depend.mk9
@@ -0,0 +1,896 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\cdocfile.obj $(OBJDIR)\cdocfile.lst: .\cdocfile.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\chinst.obj $(OBJDIR)\chinst.lst: .\chinst.cxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\STG\docfile\segdf.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cdocfile.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\scode.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\debug.obj $(OBJDIR)\debug.lst: .\debug.cxx \
+ $(CAIROLE)\stg\h\dfdeb.hxx $(CAIROLE)\STG\docfile\segdf.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cdocfile.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\dfbasis.obj $(OBJDIR)\dfbasis.lst: .\dfbasis.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\dffuncs.obj $(OBJDIR)\dffuncs.lst: .\dffuncs.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\dfiter.obj $(OBJDIR)\dfiter.lst: .\dfiter.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\dfname.obj $(OBJDIR)\dfname.lst: .\dfname.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\dfstream.obj $(OBJDIR)\dfstream.lst: .\dfstream.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\dfxact.obj $(OBJDIR)\dfxact.lst: .\dfxact.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\entry.obj $(OBJDIR)\entry.lst: .\entry.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\freelist.obj $(OBJDIR)\freelist.lst: .\freelist.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\funcs.obj $(OBJDIR)\funcs.lst: .\funcs.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\mem.obj $(OBJDIR)\mem.lst: .\mem.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfdeb.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dlink.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types16.h \
+ $(COMMON)\ih\win4p.h $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\dos.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\toolhelp.h $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\pdffuncs.obj $(OBJDIR)\pdffuncs.lst: .\pdffuncs.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\publicdf.obj $(OBJDIR)\publicdf.lst: .\publicdf.cxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\h\pbstream.hxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\time.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\rpubdf.obj $(OBJDIR)\rpubdf.lst: .\rpubdf.cxx \
+ $(CAIROLE)\stg\h\rpubdf.hxx $(CAIROLE)\STG\docfile\segdf.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cdocfile.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\tlsets.obj $(OBJDIR)\tlsets.lst: .\tlsets.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\tset.obj $(OBJDIR)\tset.lst: .\tset.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\ulist.obj $(OBJDIR)\ulist.lst: .\ulist.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\wdffuncs.obj $(OBJDIR)\wdffuncs.lst: .\wdffuncs.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\wdfiter.obj $(OBJDIR)\wdfiter.lst: .\wdfiter.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\wdfstrm.obj $(OBJDIR)\wdfstrm.lst: .\wdfstrm.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\wdfxact.obj $(OBJDIR)\wdfxact.lst: .\wdfxact.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfdeb.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\dfhead.cxx
+
+$(OBJDIR)\wdocfile.obj $(OBJDIR)\wdocfile.lst: .\wdocfile.cxx \
+ $(CAIROLE)\STG\docfile\segdf.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cdocfile.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dffuncs.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\ulist.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\h\wdocfile.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\dfhead.cxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\dfhead.pxh $(PCHDIR)\$(OBJDIR)\dfhead.lst: \
+ $(CAIROLE)\stg\docfile\dfhead.cxx $(CAIROLE)\STG\docfile\segdf.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cdocfile.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dffuncs.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\ulist.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\h\wdocfile.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h
+
+.\$(OBJDIR)\cdocfile.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\chinst.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\debug.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfbasis.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dffuncs.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfiter.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfname.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfstream.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\dfxact.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\entry.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\freelist.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\funcs.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\mem.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\pdffuncs.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\publicdf.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\rpubdf.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\tlsets.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\tset.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\ulist.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdffuncs.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdfiter.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdfstrm.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdfxact.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+.\$(OBJDIR)\wdocfile.obj : $(PCHDIR)\$(OBJDIR)\dfhead.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/docfile/dfbasis.cxx b/private/ole32/stg/docfile/dfbasis.cxx
new file mode 100644
index 000000000..171f05348
--- /dev/null
+++ b/private/ole32/stg/docfile/dfbasis.cxx
@@ -0,0 +1,67 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dfbasis.cxx
+//
+// Contents: Docfile basis implementation
+//
+// History: 28-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+#include <sstream.hxx>
+#include <ole.hxx>
+#include <entry.hxx>
+#include <smalloc.hxx>
+
+size_t CDFBasis::_aReserveSize[CDFB_CLASSCOUNT] =
+{
+ sizeof(CDocFile),
+ sizeof(CDirectStream),
+ sizeof(CWrappedDocFile),
+ sizeof(CTransactedStream)
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::Release, public
+//
+// Synopsis: Decrease reference count and free memory
+//
+// History: 02-Mar-92 DrewB Created
+// 24-Jul-95 SusiA Take mutex prior to delete
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDFBasis_vRelease)
+#endif
+
+void CDFBasis::vRelease(void)
+{
+ LONG lRet;
+
+ olDebugOut((DEB_ITRACE, "In CDFBasis::Release()\n"));
+ olAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+#if !defined(MULTIHEAP)
+ //take the mutex here instead of in the allocator.
+ g_smAllocator.GetMutex()->Take(DFM_TIMEOUT);
+#endif
+ delete this;
+#if !defined(MULTIHEAP)
+ g_smAllocator.GetMutex()->Release();
+#endif
+
+
+ }
+ olDebugOut((DEB_ITRACE, "Out CDFBasis::Release()\n"));
+}
diff --git a/private/ole32/stg/docfile/dffuncs.cxx b/private/ole32/stg/docfile/dffuncs.cxx
new file mode 100644
index 000000000..919a341bd
--- /dev/null
+++ b/private/ole32/stg/docfile/dffuncs.cxx
@@ -0,0 +1,228 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992
+//
+// File: dffuncs.cxx
+//
+// Contents: Private support functions for the DocFile code
+//
+// Methods: StartMS
+// DeleteContents
+//
+// History: 11-Dec-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+//+--------------------------------------------------------------
+//
+// Method: CDocFile::DeleteContents, public
+//
+// Synopsis: Deletes all entries in a DocFile recursing on entries
+// with children
+//
+// Returns: Appropriate status code
+//
+// History: 25-Sep-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_DeleteContents) // Dirdf_TEXT
+#endif
+
+SCODE CDocFile::DeleteContents(void)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::DeleteContents()\n"));
+ sc = _stgh.DestroyEntry(NULL);
+ olDebugOut((DEB_ITRACE, "Out CDocFile::DeleteContents\n"));
+ return sc;
+}
+
+#ifndef REF
+//+--------------------------------------------------------------
+//
+// Method: CDocFile::ApplyChanges, public
+//
+// Synopsis: Applies a list of updates to a docfile
+// Creates source entries in destination and links
+// them to child instances in the given TL
+//
+// Arguments: [ulChanged] - List of changes
+//
+// Returns: Appropriate status code
+//
+// History: 12-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_ApplyChanges) // Dirdf_Commit_TEXT
+#endif
+
+SCODE CDocFile::ApplyChanges(CUpdateList &ulChanged)
+{
+ SCODE sc = S_OK;
+ CUpdate *pud;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::ApplyChanges(%p)\n",
+ ulChanged.GetHead()));
+
+ for (pud = ulChanged.GetHead(); pud; pud = pud->GetNext())
+ {
+ if (pud->IsDelete())
+ olChk(DestroyEntry(pud->GetOriginalName(), FALSE));
+ else if (pud->IsRename())
+ olChk(RenameEntry(pud->GetOriginalName(),
+ pud->GetCurrentName()));
+ else
+ {
+ olAssert(pud->IsCreate());
+ olChk(CreateFromUpdate(pud, this, DF_WRITE));
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out CDocFile::ApplyChanges\n"));
+ // Fall through
+ EH_Err:
+ return sc;
+}
+#endif //!REF
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::CopyTo, public
+//
+// Synopsis: Copies the contents of one DocFile to another
+//
+// Arguments: [pdfTo] - Destination DocFile
+// [dwFlags] - Control flags
+// [snbExclude] - Partial instantiation list
+//
+// Returns: Appropriate status code
+//
+// History: 26-Sep-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_CopyTo) // Root_TEXT
+#endif
+
+SCODE CDocFile::CopyTo(CDocFile *pdfTo,
+ DWORD dwFlags,
+ SNBW snbExclude)
+{
+ CDfName dfnKey;
+ SIterBuffer ib;
+ PSStream *psstFrom, *psstTo;
+ CDocFile *pdfFromChild, *pdfToChild;
+ DFLUID dlLUID = DF_NOLUID;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::CopyTo:%p(%p, %lX, %p)\n", this,
+ pdfTo, dwFlags, snbExclude));
+ for (;;)
+ {
+ if (FAILED(FindGreaterEntry(&dfnKey, &ib, NULL)))
+ break;
+ dfnKey.Set(&ib.dfnName);
+
+ switch(REAL_STGTY(ib.type))
+ {
+ case STGTY_STORAGE:
+ // Embedded DocFile, create destination and recurse
+
+ olChkTo(EH_pwcsName, GetDocFile(&ib.dfnName, DF_READ, ib.type,
+ (PDocFile **)&pdfFromChild));
+ // Destination must be a direct docfile
+#ifndef REF
+ olChkTo(EH_Get, CDocFile::Reserve(1, BP_TO_P(CDFBasis *, _pdfb)));
+#endif //!REF
+ olChkTo(EH_Reserve, pdfTo->CreateDocFile(&ib.dfnName, DF_WRITE,
+ dlLUID, ib.type,
+ (PDocFile **)&pdfToChild));
+ if (dwFlags & CDF_EXACT)
+ pdfToChild->CopyTimesFrom(pdfFromChild);
+
+ CLSID clsid;
+ olChkTo(EH_Create, pdfFromChild->GetClass(&clsid));
+ olChkTo(EH_Create, pdfToChild->SetClass(clsid));
+
+ DWORD grfStateBits;
+ olChkTo(EH_Create, pdfFromChild->GetStateBits(&grfStateBits));
+ olChkTo(EH_Create, pdfToChild->SetStateBits(grfStateBits,
+ 0xffffffff));
+
+ if ((dwFlags & CDF_ENTRIESONLY) == 0 &&
+ !(snbExclude && NameInSNB(&ib.dfnName, snbExclude) ==
+ S_OK))
+ olChkTo(EH_Create,
+ pdfFromChild->CopyTo(pdfToChild, dwFlags, NULL));
+
+ pdfFromChild->Release();
+ pdfToChild->Release();
+ break;
+
+ case STGTY_STREAM:
+ olChkTo(EH_pwcsName, GetStream(&ib.dfnName, DF_READ,
+ ib.type, &psstFrom));
+ // Destination must be a direct docfile
+#ifndef REF
+ olChkTo(EH_Get,
+ CDirectStream::Reserve(1, BP_TO_P(CDFBasis *, _pdfb)));
+
+ olChkTo(EH_Reserve,
+ pdfTo->CreateStream(&ib.dfnName, DF_WRITE, dlLUID,
+ ib.type, &psstTo));
+#else
+ olChkTo(EH_Reserve,
+ pdfTo->CreateStream(&ib.dfnName, DF_WRITE, dlLUID,
+ &psstTo));
+#endif //!REF
+
+ if ((dwFlags & CDF_ENTRIESONLY) == 0 &&
+ !(snbExclude && NameInSNB(&ib.dfnName, snbExclude) ==
+ S_OK))
+ olChkTo(EH_Create, CopySStreamToSStream(psstFrom, psstTo));
+
+ psstFrom->Release();
+ psstTo->Release();
+ break;
+
+ default:
+ olAssert(!aMsg("Unknown entry type in CDocFile::CopyTo"));
+ break;
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out CDocFile::CopyTo\n"));
+ return S_OK;
+
+ EH_Create:
+ if (REAL_STGTY(ib.type))
+ pdfToChild->Release();
+ else
+ psstTo->Release();
+ olAssert(&ib.dfnName);
+ olVerSucc(pdfTo->DestroyEntry(&ib.dfnName, TRUE));
+ goto EH_Get;
+ EH_Reserve:
+#ifndef REF
+ if (REAL_STGTY(ib.type))
+ CDocFile::Unreserve(1, BP_TO_P(CDFBasis *, _pdfb));
+ else
+ CDirectStream::Unreserve(1, BP_TO_P(CDFBasis *, _pdfb));
+#endif //!REF
+ EH_Get:
+ if (REAL_STGTY(ib.type))
+ pdfFromChild->Release();
+ else
+ psstFrom->Release();
+ EH_pwcsName:
+ return sc;
+}
diff --git a/private/ole32/stg/docfile/dfhead.cxx b/private/ole32/stg/docfile/dfhead.cxx
new file mode 100644
index 000000000..7931a47e8
--- /dev/null
+++ b/private/ole32/stg/docfile/dfhead.cxx
@@ -0,0 +1,66 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dfhead.cxx
+//
+// Contents: Precompiled headers
+//
+// History: 26-Oct-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windef.h>
+}
+
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef REF
+#include <ole2.h>
+#else
+#include <ref.hxx>
+#endif //!REF
+
+#include <propset.h>
+
+#ifdef _CAIRO_
+# include <iofs.h>
+#else
+# include <propapi.h>
+#endif
+
+#if defined(_CHICAGO_)
+#include <widewrap.h>
+#endif
+
+#include <propstm.hxx>
+
+#include <msf.hxx>
+
+#include <olesem.hxx>
+#include <dfexcept.hxx>
+#include <docfilep.hxx>
+#include <publicdf.hxx>
+#include <psstream.hxx>
+#ifndef REF
+#include <wdocfile.hxx>
+#endif //!REF
+#include <dffuncs.hxx>
+#include <funcs.hxx>
+#ifndef REF
+#include <debug.hxx>
+#endif //!REF
+
+
+
+
+
diff --git a/private/ole32/stg/docfile/dfiter.cxx b/private/ole32/stg/docfile/dfiter.cxx
new file mode 100644
index 000000000..3a604e2e9
--- /dev/null
+++ b/private/ole32/stg/docfile/dfiter.cxx
@@ -0,0 +1,116 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: dfiter.cxx
+//
+// Contents: Implementations of CDocFile iterator methods
+//
+// History: 16-Dec-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::FindGreaterEntry, public
+//
+// Synopsis: Returns the next greater child
+//
+// Arguments: [pdfnKey] - Previous key
+// [pib] - Fast iterator buffer
+// [pstat] - Full iterator buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pib] or [pstat]
+//
+// History: 16-Apr-93 DrewB Created
+//
+// Notes: Either [pib] or [pstat] must be NULL
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_FindGreaterEntry) // Iterate_TEXT
+#endif
+
+SCODE CDocFile::FindGreaterEntry(CDfName const *pdfnKey,
+ SIterBuffer *pib,
+ STATSTGW *pstat)
+{
+ SID sid, sidChild;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::FindGreaterEntry:%p(%p, %p, %p)\n",
+ this, pdfnKey, pib, pstat));
+ olAssert((pib == NULL) != (pstat == NULL));
+
+ if (SUCCEEDED(sc = _stgh.GetMS()->GetChild(_stgh.GetSid(), &sidChild)))
+ {
+ if (sidChild == NOSTREAM)
+ {
+ sc = STG_E_NOMOREFILES;
+ }
+ else
+ {
+ if (SUCCEEDED(sc = _stgh.GetMS()->FindGreaterEntry(sidChild,
+ pdfnKey,
+ &sid)))
+ {
+ sc = _stgh.GetMS()->StatEntry(sid, pib, pstat);
+ }
+ }
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CDocFile::FindGreaterEntry\n"));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::StatEntry, public
+//
+// Synopsis: Gets information for a child
+//
+// Arguments: [pdfn] - Child name
+// [pib] - Short information
+// [pstat] - Full information
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pib] or [pstat]
+//
+// History: 16-Apr-93 DrewB Created
+//
+// Notes: Either [pib] or [pstat] must be NULL
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_StatEntry)
+#endif
+
+SCODE CDocFile::StatEntry(CDfName const *pdfn,
+ SIterBuffer *pib,
+ STATSTGW *pstat)
+{
+ SEntryBuffer eb;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::StatEntry:%p(%p, %p, %p)\n",
+ this, pdfn, pib, pstat));
+ olAssert((pib == NULL) != (pstat == NULL));
+
+ olChk(_stgh.GetMS()->IsEntry(_stgh.GetSid(), pdfn, &eb));
+ sc = _stgh.GetMS()->StatEntry(eb.sid, pib, pstat);
+
+ olDebugOut((DEB_ITRACE, "Out CDocFile::StatEntry\n"));
+ EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/docfile/dfname.cxx b/private/ole32/stg/docfile/dfname.cxx
new file mode 100644
index 000000000..b4a75c56c
--- /dev/null
+++ b/private/ole32/stg/docfile/dfname.cxx
@@ -0,0 +1,63 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dfname.cxx
+//
+// Contents: CDfName implementation
+//
+// History: 14-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDfName::IsEqual, public
+//
+// Synopsis: Compares two CDfNames
+//
+// Arguments: [pdfn] - Name to compare against
+//
+// Returns: TRUE/FALSE
+//
+// History: 11-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef FLAT
+BOOL CDfName::IsEqual(CDfName const *pdfn) const
+{
+ if (_cb != pdfn->_cb)
+ return FALSE;
+ return dfwcsnicmp((WCHAR *)_ab, (WCHAR *)pdfn->_ab, _cb) == 0;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDfName::CopyString, public
+//
+// Synopsis: Makes a proper copy of a name in a WCHAR string
+//
+// Arguments: [pwcs] - String
+//
+// History: 14-May-93 DrewB Created
+//
+// Notes: Uses leading characters to determine the format of
+// the name in the string
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDfName_CopyString)
+#endif
+
+void CDfName::CopyString(WCHAR const *pwcs)
+{
+ Set(pwcs);
+}
diff --git a/private/ole32/stg/docfile/dfstream.cxx b/private/ole32/stg/docfile/dfstream.cxx
new file mode 100644
index 000000000..1a40ca737
--- /dev/null
+++ b/private/ole32/stg/docfile/dfstream.cxx
@@ -0,0 +1,135 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: dfstream.cxx
+//
+// Contents: Implementations of CDocFile stream methods
+//
+// History: 18-Oct-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+//+--------------------------------------------------------------
+//
+// Method: CDocFile::CreateStream, public
+//
+// Synopsis: Creates a named stream in a DocFile
+//
+// Arguments: [pwcsName] - Name of the stream
+// [df] - Transactioning flags
+// [dlSet] - LUID to set or DF_NOLUID
+// [dwType] - Type of entry to be created
+// [ppsstStream] - Pointer to storage for the stream pointer
+//
+// Returns: Appropriate error code
+//
+// Modifies: [ppsstStream]
+//
+// History: 22-Aug-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_CreateStream) // Dirdf_Create_TEXT
+#endif
+
+SCODE CDocFile::CreateStream(CDfName const *pdfn,
+ DFLAGS const df,
+ DFLUID dlSet,
+ PSStream **ppsstStream)
+{
+ SCODE sc;
+ CDirectStream *pstm;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::CreateStream("
+ "%ws, %X, %lu, %p)\n",
+ pdfn, df, dlSet, ppsstStream));
+
+ UNREFERENCED_PARM(df);
+
+ if (dlSet == DF_NOLUID)
+ dlSet = CDirectStream::GetNewLuid(_pdfb->GetMalloc());
+#ifndef REF
+ pstm = new (BP_TO_P(CDFBasis *, _pdfb)) CDirectStream(dlSet);
+ olAssert(pstm != NULL && aMsg("Reserved stream unavailable"));
+#else
+ olMem(pstm = new CDirectStream(dlSet));
+#endif //!REF
+
+ olChkTo(EH_pstm, pstm->Init(&_stgh, pdfn, TRUE));
+
+ *ppsstStream = pstm;
+ olDebugOut((DEB_ITRACE, "Out CDocFile::CreateStream => %p\n",
+ *ppsstStream));
+ return S_OK;
+
+EH_pstm:
+#ifndef REF
+ pstm->ReturnToReserve(BP_TO_P(CDFBasis *, _pdfb));
+#else
+ delete pstm;
+EH_Err:
+#endif //!REF
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Method: CDocFile::GetStream, public
+//
+// Synopsis: Retrieves an existing stream from a DocFile
+//
+// Arguments: [pwcsName] - Name of the stream
+// [df] - Transactioning flags
+// [dwType] - Type of entry
+// [ppsstStream] - Pointer to storage for the stream pointer
+//
+// Returns: Appropriate error code
+//
+// Modifies: [ppsstStream]
+//
+// History: 22-Aug-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_GetStream) // Dirdf_Open_TEXT
+#endif
+
+SCODE CDocFile::GetStream(CDfName const *pdfn,
+ DFLAGS const df,
+ PSStream **ppsstStream)
+{
+ SCODE sc;
+ CDirectStream *pstm;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::GetStream(%ws, %X, %p)\n",
+ pdfn, df, ppsstStream));
+
+ UNREFERENCED_PARM(df);
+
+ DFLUID dl = CDirectStream::GetNewLuid(_pdfb->GetMalloc());
+#ifndef REF
+ olMem(pstm = new(_pdfb->GetMalloc()) CDirectStream(dl));
+#else
+ olMem(pstm = new CDirectStream(dl));
+#endif //!REF
+
+ olChkTo(EH_pstm, pstm->Init(&_stgh, pdfn, FALSE));
+
+ *ppsstStream = pstm;
+ olDebugOut((DEB_ITRACE, "Out CDocFile::GetStream => %p\n",
+ *ppsstStream));
+ return S_OK;
+
+EH_pstm:
+ delete pstm;
+EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/docfile/dfxact.cxx b/private/ole32/stg/docfile/dfxact.cxx
new file mode 100644
index 000000000..f0c750596
--- /dev/null
+++ b/private/ole32/stg/docfile/dfxact.cxx
@@ -0,0 +1,173 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dfxact.cxx
+//
+// Contents: CDocFile transactioning methods
+//
+// History: 22-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::BeginCommitFromChild, public
+//
+// Synopsis: Start two-phase commit, requested by child
+//
+// Arguments: [ulChanged] - Update list
+// [dwFlags] - Flags controlling commit
+// [pdfChild] - Child object
+//
+// Returns: Appropriate status code
+//
+// History: 04-Nov-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_BeginCommitFromChild) // Dirdf_Commit_TEXT
+#endif
+
+SCODE CDocFile::BeginCommitFromChild(CUpdateList &ulChanged,
+ DWORD const dwFlags,
+ CWrappedDocFile *pdfChild)
+{
+ SCODE sc;
+ TIME_T tm;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::BeginCommitFromChild:%p("
+ "%p, %lX, %p)\n", this, ulChanged.GetHead(), dwFlags,
+ pdfChild));
+ UNREFERENCED_PARM(dwFlags);
+
+ // Copy-on-write will back these changes out if they fail
+ if (pdfChild->GetDirty() & DIRTY_CREATETIME)
+ {
+ olVerSucc(pdfChild->GetTime(WT_CREATION, &tm));
+ olChk(SetTime(WT_CREATION, tm));
+ }
+ if (pdfChild->GetDirty() & DIRTY_MODIFYTIME)
+ {
+ olVerSucc(pdfChild->GetTime(WT_MODIFICATION, &tm));
+ olChk(SetTime(WT_MODIFICATION, tm));
+ }
+ if (pdfChild->GetDirty() & DIRTY_ACCESSTIME)
+ {
+ olVerSucc(pdfChild->GetTime(WT_ACCESS, &tm));
+ olChk(SetTime(WT_ACCESS, tm));
+ }
+ if (pdfChild->GetDirty() & DIRTY_CLASS)
+ {
+ CLSID clsid;
+
+ olVerSucc(pdfChild->GetClass(&clsid));
+ olChk(SetClass(clsid));
+ }
+ if (pdfChild->GetDirty() & DIRTY_STATEBITS)
+ {
+ DWORD grfStateBits;
+
+ olVerSucc(pdfChild->GetStateBits(&grfStateBits));
+ olChk(SetStateBits(grfStateBits, 0xffffffff));
+ }
+
+ _ulChangedHolder = ulChanged;
+ sc = ApplyChanges(ulChanged);
+
+ olDebugOut((DEB_ITRACE, "Out CDocFile::BeginCommitFromChild\n"));
+ EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::EndCommitFromChild
+//
+// Synopsis: Ends two-phase commit, requested by child
+//
+// Arguments: [df] - COMMIT/ABORT
+// [pdfChild] - Child object
+//
+// History: 07-Nov-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_EndCommitFromChild)
+#endif
+
+void CDocFile::EndCommitFromChild(DFLAGS const df,
+ CWrappedDocFile *pdfChild)
+{
+ CUpdate *pud;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::EndCommitFromChild:%p(%X, %p)\n",
+ this, df, pdfChild));
+
+ UNREFERENCED_PARM(pdfChild);
+
+ if (P_COMMIT(df))
+ {
+ // Finalize updates
+ for (pud = _ulChangedHolder.GetHead(); pud; pud = pud->GetNext())
+ if (pud->IsCreate())
+ // Remove reference to child's XSM so that list destruction
+ // won't free it
+ pud->SetXSM(NULL);
+ _ulChangedHolder.Empty();
+ }
+ else
+ {
+ for (pud = _ulChangedHolder.GetTail(); pud; pud = pud->GetPrev())
+ if (pud->IsCreate())
+ {
+ // We need to do two things:
+ //
+ // Break any SetBase links that might have been created
+ //
+ // Return newly created objects to the creators so
+ // that they can be returned to the preallocation
+ // pool
+
+ if ((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL)) ==
+ STGTY_STORAGE)
+ {
+ CWrappedDocFile *pwdf = (CWrappedDocFile *)pud->GetXSM();
+ CDocFile *pddf;
+
+ if ((pddf = (CDocFile *)pwdf->GetBase()) != NULL)
+ {
+ // AddRef so SetBase won't free memory
+ pddf->AddRef();
+ pwdf->SetBase(NULL);
+ ReturnDocFile(pddf);
+ }
+ }
+ else
+ {
+ CTransactedStream *pwstm = (CTransactedStream *)pud->
+ GetXSM();
+ CDirectStream *pdstm;
+
+ olAssert((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL))
+ == STGTY_STREAM);
+ if ((pdstm = (CDirectStream *)pwstm->GetBase()) != NULL)
+ {
+ // AddRef so SetBase won't free memory
+ pdstm->AddRef();
+ pwstm->SetBase(NULL);
+ ReturnStream(pdstm);
+ }
+ }
+ }
+ _ulChangedHolder.Unlink();
+ }
+ olDebugOut((DEB_ITRACE, "Out CDocFile::EndCommitFromChild\n"));
+}
diff --git a/private/ole32/stg/docfile/dirs b/private/ole32/stg/docfile/dirs
new file mode 100644
index 000000000..4c50c7cc4
--- /dev/null
+++ b/private/ole32/stg/docfile/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/stg/docfile/entry.cxx b/private/ole32/stg/docfile/entry.cxx
new file mode 100644
index 000000000..e59a8ffde
--- /dev/null
+++ b/private/ole32/stg/docfile/entry.cxx
@@ -0,0 +1,81 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: entry.cxx
+//
+// Contents: Entry implementations
+//
+// History: 29-Jul-92 DrewB Created
+// 10-Apr-95 HenryLee remove Sleep
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+#include <smalloc.hxx>
+
+#pragma hdrstop
+
+//+--------------------------------------------------------------
+//
+// Member: PTimeEntry::CopyTimesFrom, public
+//
+// Synopsis: Copies one entries times to another
+//
+// Arguments: [ptenFrom] - From
+//
+// Returns: Appropriate status code
+//
+// History: 29-Jul-92 DrewB Created
+// 26-May-95 SusiA Removed GetTime; Added GetAllTimes
+// 22-Nov-95 SusiA SetAllTimes at once
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_PTimeEntry_CopyTimesFrom)
+#endif
+
+SCODE PTimeEntry::CopyTimesFrom(PTimeEntry *ptenFrom)
+{
+ SCODE sc;
+ TIME_T atm; //Access time
+ TIME_T mtm; //Modification time
+ TIME_T ctm; //Creation time
+
+ olDebugOut((DEB_ITRACE, "In PTimeEntry::CopyTimesFrom(%p)\n",
+ ptenFrom));
+ olChk(ptenFrom->GetAllTimes(&atm, &mtm, &ctm));
+ olChk(SetAllTimes(atm, mtm, ctm));
+ olDebugOut((DEB_ITRACE, "Out PTimeEntry::CopyTimesFrom\n"));
+ // Fall through
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PBasicEntry::GetNewLuid, public
+//
+// Synopsis: Returns a new luid
+//
+// History: 21-Oct-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+#ifdef FLAT
+//We used to have a mutex here - it turns out that this is unnecessary,
+// since we're already holding the tree mutex. We get a performance
+// win by eliminating the mutex.
+//Using CSmAllocator mutex and took out Sleep()
+//static CStaticDfMutex _sdmtxLuids(TSTR("DfLuidsProtector"));
+
+DFLUID PBasicEntry::GetNewLuid(const IMalloc *pMalloc)
+{
+ DFLUID luid;
+
+ luid = ((CSmAllocator *)pMalloc)->IncrementLuid();
+ return luid;
+}
+#endif
diff --git a/private/ole32/stg/docfile/fastlock.cxx b/private/ole32/stg/docfile/fastlock.cxx
new file mode 100644
index 000000000..b6d61cdc8
--- /dev/null
+++ b/private/ole32/stg/docfile/fastlock.cxx
@@ -0,0 +1,436 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992
+//
+// File: fastlock.cxx
+//
+// Contents: Implementation of CDfMutex methods for DocFiles
+//
+// History: 26-Jul-94 DonnaLi Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+#pragma hdrstop
+
+#include <df32.hxx>
+
+#ifdef UNICODE
+#define GLOBAL_CS L"GlobalCsMutex"
+#else
+#define GLOBAL_CS "GlobalCsMutex"
+#endif
+
+//
+// This is the number of characters to skip over in the name
+// pased to CDfMutex::Init. The name consists of the string
+// OleDfRoot followed by the hex representation of a unique
+// number for each Docfile. We skip CHARS_TO_SKIP number of
+// characters in the name to produce a related and yet unique
+// name for the file mapping containing global state for the
+// critical section.
+//
+#define CHARS_TO_SKIP 3
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDfMutex::Init, public
+//
+// Synopsis: This routine creates and initializes the global
+// critical section if it does not already exist.
+// It then attaches to the global critical section.
+//
+// Arguments: [lpName] - Supplies the critical section name
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-94 DonnaLi Created
+//
+// Algorithm: Uses a mutex to serialize global critical section
+// creation and initialization
+// The name passed in is used to create or open the
+// semaphore embedded in the global critical section.
+// The name with the first CHARS_TO_SKIP characters
+// skipped is used to create or open the file mapping
+// containing global state of the critical section.
+// If a file mapping with that name already exists,
+// it is not reinitialized. The caller instead just
+// attaches to it.
+//
+//---------------------------------------------------------------
+
+SCODE
+CDfMutex::Init(
+ TCHAR * lpName
+ )
+{
+ HANDLE hGlobalMutex;
+ SCODE scResult = S_OK;
+ DWORD dwResult;
+ LPSECURITY_ATTRIBUTES lpsa = NULL;
+
+#if WIN32 == 100 || WIN32 > 200
+ CGlobalSecurity gs;
+ if (FAILED(scResult = gs.Init())) return scResult;
+#else
+ LPSECURITY_ATTRIBUTES gs = NULL;
+#endif
+
+ //
+ // Serialize all global critical section initialization
+ //
+
+ hGlobalMutex = CreateMutex(
+ gs, // LPSECURITY_ATTRIBUTES lpsa
+ TRUE, // BOOL fInitialOwner
+ GLOBAL_CS // LPCTSTR lpszMutexName
+ );
+
+ //
+ // If the mutex create/open failed, then bail
+ //
+
+ if ( !hGlobalMutex )
+ {
+ return LAST_SCODE;
+ }
+
+ if ( GetLastError() == ERROR_ALREADY_EXISTS )
+ {
+
+ //
+ // Since the mutex already existed, the request for ownership has
+ // no effect.
+ //
+ // wait for the mutex
+ //
+
+ if ( WaitForSingleObject (hGlobalMutex, INFINITE) == WAIT_FAILED )
+ {
+ scResult = LAST_SCODE;
+ CloseHandle (hGlobalMutex);
+ return scResult;
+ }
+ }
+
+ //
+ // We now own the global critical section creation mutex. Create/Open the
+ // named semaphore.
+ //
+
+ _hLockSemaphore = CreateSemaphore (
+ gs, // LPSECURITY_ATTRIBUTES lpsa
+ 0, // LONG cSemInitial
+ MAXLONG-1, // LONG cSemMax
+ lpName // LPCTSTR lpszSemName
+ );
+
+ //
+ // If the semaphore create/open failed, then bail
+ //
+
+ if ( !_hLockSemaphore )
+ {
+ scResult = LAST_SCODE;
+ }
+ else
+ {
+ //
+ // Create/open a shared file mapping object
+ // If we created it, we need to initialize the global structure.
+ // Otherwise just point to it.
+ // The global critical section creation mutex allows us to do
+ // this safely.
+ //
+
+ _hSharedMapping = CreateFileMappingT (
+ (HANDLE)0xffffffff, // HANDLE hFile
+ gs, // LPSECURITY_ATTRIBUTES lpsa
+ PAGE_READWRITE, // DWORD fdwProtect
+ 0, // DWORD dwMaximumSizeHigh
+ 1024, // DWORD dwMaximumSizeLow
+ lpName+CHARS_TO_SKIP// LPCTSTR lpszMapName
+ );
+
+ if ( !_hSharedMapping )
+ {
+ scResult = LAST_SCODE;
+ CloseHandle (_hLockSemaphore);
+ _hLockSemaphore = (HANDLE)NULL;
+ }
+ else
+ {
+ dwResult = GetLastError();
+
+ _pGlobalPortion = (PGLOBAL_SHARED_CRITICAL_SECTION)
+ MapViewOfFile (
+ _hSharedMapping, // HANDLE hMapObject
+ FILE_MAP_WRITE, // DWORD fdwAccess
+ 0, // DWORD dwOffsetHigh
+ 0, // DWORD dwOffsetLow
+ 0 // DWORD cbMap
+ );
+
+ if (!_pGlobalPortion)
+ {
+ scResult = LAST_SCODE;
+ CloseHandle (_hLockSemaphore);
+ _hLockSemaphore = (HANDLE)NULL;
+ CloseHandle (_hSharedMapping);
+ _hSharedMapping = (HANDLE)NULL;
+ }
+ else if (dwResult != ERROR_ALREADY_EXISTS )
+ {
+ //
+ // We created the file mapping, so initialize the
+ // global portion.
+ //
+
+ _pGlobalPortion->LockCount = -1;
+#ifdef SUPPORT_RECURSIVE_LOCK
+ _pGlobalPortion->RecursionCount = 0;
+ _pGlobalPortion->OwningThread = 0;
+#else
+#if DBG == 1
+ _pGlobalPortion->OwningThread = 0;
+#endif
+#endif
+ _pGlobalPortion->Reserved = 0;
+ }
+ }
+ }
+
+
+ ReleaseMutex (hGlobalMutex);
+ CloseHandle (hGlobalMutex);
+
+ return scResult;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDfMutex::~CDfMutex, public
+//
+// Synopsis: This routine detaches from an existing global
+// critical section.
+//
+// History: 26-Jul-94 DonnaLi Created
+//
+// Algorithm: Create or get the entry from the multistream
+//
+//---------------------------------------------------------------
+
+CDfMutex::~CDfMutex(
+ void
+ )
+{
+ //If we're holding the mutex, we need to get rid of it here.
+
+#ifdef SUPPORT_RECURSIVE_LOCK
+ if ((_pGlobalPortion) &&
+ (_pGlobalPortion->OwningThread == GetCurrentThreadId()))
+ {
+#else
+ if (_pGlobalPortion)
+ {
+#if DBG == 1
+ olAssert (_pGlobalPortion->OwningThread == 0 || _pGlobalPortion->OwningThread == GetCurrentThreadId());
+#endif
+#endif
+ Release();
+ }
+
+ if ( _pGlobalPortion )
+ {
+ UnmapViewOfFile (_pGlobalPortion);
+ }
+
+ if ( _hLockSemaphore )
+ {
+ CloseHandle (_hLockSemaphore);
+ }
+ if ( _hSharedMapping )
+ {
+ CloseHandle (_hSharedMapping);
+ }
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDfMutex::Take, public
+//
+// Synopsis: This routine enters the global critical section.
+//
+// Arguments: [dwTimeout] - Supplies the timeout
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-94 DonnaLi Created
+//
+// Algorithm: Enters the critical section if nobody owns it or
+// if the current thread already owns it.
+// Waits for the critical section otherwise.
+//
+//---------------------------------------------------------------
+
+SCODE
+CDfMutex::Take (
+ DWORD dwTimeout
+ )
+{
+ olAssert (_pGlobalPortion->LockCount >= -1);
+
+#ifdef SUPPORT_RECURSIVE_LOCK
+
+ olAssert (_pGlobalPortion->RecursionCount >= 0);
+
+ DWORD ThreadId;
+
+ ThreadId = GetCurrentThreadId();
+
+#endif
+
+ //
+ // Increment the lock variable. On the transition to 0, the caller
+ // becomes the absolute owner of the lock. Otherwise, the caller is
+ // either recursing, or is going to have to wait
+ //
+
+ if ( !InterlockedIncrement (&_pGlobalPortion->LockCount) )
+ {
+ //
+ // lock count went from -1 to 0, so the caller
+ // is the owner of the lock
+ //
+
+#ifdef SUPPORT_RECURSIVE_LOCK
+ _pGlobalPortion->RecursionCount = 1;
+ _pGlobalPortion->OwningThread = ThreadId;
+#else
+#if DBG == 1
+ _pGlobalPortion->OwningThread = GetCurrentThreadId();
+#endif
+#endif
+ return S_OK;
+ }
+ else
+ {
+#ifdef SUPPORT_RECURSIVE_LOCK
+ //
+ // If the caller is recursing, then increment the recursion count
+ //
+
+ if ( _pGlobalPortion->OwningThread == ThreadId )
+ {
+ _pGlobalPortion->RecursionCount++;
+ return S_OK;
+ }
+ else
+ {
+#else
+#if DBG == 1
+ olAssert (_pGlobalPortion->OwningThread != GetCurrentThreadId());
+#endif
+#endif
+ switch (WaitForSingleObject(
+ _hLockSemaphore,
+ dwTimeout
+ ))
+ {
+ case WAIT_OBJECT_0:
+ case WAIT_ABANDONED:
+#ifdef SUPPORT_RECURSIVE_LOCK
+ _pGlobalPortion->RecursionCount = 1;
+ _pGlobalPortion->OwningThread = ThreadId;
+#else
+#if DBG == 1
+ _pGlobalPortion->OwningThread = GetCurrentThreadId();
+#endif
+#endif
+ return S_OK;
+ case WAIT_TIMEOUT:
+ return STG_E_INUSE;
+ default:
+ return LAST_SCODE;
+ }
+#ifdef SUPPORT_RECURSIVE_LOCK
+ }
+#endif
+ }
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDfMutex::Release, public
+//
+// Synopsis: This routine leaves the global critical section
+//
+// History: 26-Jul-94 DonnaLi Created
+//
+// Algorithm: Leaves the critical section if this is the owning
+// thread.
+//
+//---------------------------------------------------------------
+
+VOID
+CDfMutex::Release(
+ void
+ )
+{
+#ifdef SUPPORT_RECURSIVE_LOCK
+ if ( _pGlobalPortion->OwningThread != GetCurrentThreadId() ) return;
+#else
+#if DBG == 1
+ olAssert (_pGlobalPortion->OwningThread == 0 || _pGlobalPortion->OwningThread == GetCurrentThreadId());
+#endif
+#endif
+
+ olAssert (_pGlobalPortion->LockCount >= -1);
+
+#ifdef SUPPORT_RECURSIVE_LOCK
+ olAssert (_pGlobalPortion->RecursionCount >= 0);
+
+ //
+ // decrement the recursion count. If it is still non-zero, then
+ // we are still the owner so don't do anything other than dec the lock
+ // count
+ //
+
+ if ( --_pGlobalPortion->RecursionCount )
+ {
+ InterlockedDecrement(&_pGlobalPortion->LockCount);
+ }
+ else
+ {
+ //
+ // We are really leaving, so give up ownership and decrement the
+ // lock count
+ //
+
+ _pGlobalPortion->OwningThread = 0;
+#else
+#if DBG == 1
+ _pGlobalPortion->OwningThread = 0;
+#endif
+#endif
+
+ //
+ // Check to see if there are other waiters. If so, then wake up a waiter
+ //
+
+ if ( InterlockedDecrement(&_pGlobalPortion->LockCount) >= 0 )
+ {
+ ReleaseSemaphore(
+ _hLockSemaphore, // HANDLE hSemaphore
+ 1, // LONG cReleaseCount
+ NULL // LPLONG lplPreviousCount
+ );
+ }
+#ifdef SUPPORT_RECURSIVE_LOCK
+ }
+#endif
+}
diff --git a/private/ole32/stg/docfile/filelist.mk b/private/ole32/stg/docfile/filelist.mk
new file mode 100644
index 000000000..649627ded
--- /dev/null
+++ b/private/ole32/stg/docfile/filelist.mk
@@ -0,0 +1,46 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1992 **
+#********************************************************************
+
+MKNAME = docfile
+!if "$(OLESEP)" != ""
+LIBS = $(CAIROLE)\stg\msf\$(OBJDIR)\msf.lib
+!endif
+
+#CFLAGS = $(CFLAGS) -Fc
+
+CXXFILES = \
+ .\cdocfile.cxx\
+ .\chinst.cxx\
+ .\debug.cxx\
+ .\dfbasis.cxx\
+ .\dffuncs.cxx\
+ .\dfiter.cxx\
+ .\dfname.cxx\
+ .\dfstream.cxx\
+ .\dfxact.cxx\
+ .\entry.cxx\
+ .\freelist.cxx\
+ .\funcs.cxx\
+ .\mem.cxx\
+ .\pdffuncs.cxx\
+ .\publicdf.cxx\
+ .\rpubdf.cxx\
+!if "$(OPSYS)" == "NT"
+ .\sngprop.cxx\
+!endif
+ .\tlsets.cxx\
+ .\tset.cxx\
+ .\ulist.cxx\
+ .\wdffuncs.cxx\
+ .\wdfiter.cxx\
+ .\wdfstrm.cxx\
+ .\wdfxact.cxx\
+ .\wdocfile.cxx
+
+!if "$(PLATFORM)" != "MAC"
+PXXFILE = .\dfhead.cxx
+!endif
+
+!include $(CAIROLE)\stg\dfms.mk
diff --git a/private/ole32/stg/docfile/freelist.cxx b/private/ole32/stg/docfile/freelist.cxx
new file mode 100644
index 000000000..21eda5ee0
--- /dev/null
+++ b/private/ole32/stg/docfile/freelist.cxx
@@ -0,0 +1,104 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: freelist.cxx
+//
+// Contents: CFreeList implementation
+//
+// History: 05-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+#include <freelist.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFreeList::Reserve, public
+//
+// Synopsis: Allocates memory for a given number of blocks
+//
+// Arguments: [pMalloc] - Allocator to use to allocate blocks
+// [cBlocks] - Number of blocks to allocate
+// [cbBlock] - Block size
+//
+// Returns: Appropriate status code
+//
+// History: 05-Nov-92 DrewB Created
+// 21-May-93 AlexT Add allocator
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFreeList_Reserve)
+#endif
+
+SCODE CFreeList::Reserve(IMalloc *pMalloc, UINT cBlocks, size_t cbBlock)
+{
+ SFreeBlock *pfb;
+ UINT i;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CFreeList::Reserve:%p(%lu, %u)\n",
+ this, cBlocks, cbBlock));
+ olAssert(cbBlock >= sizeof(SFreeBlock));
+ for (i = 0; i<cBlocks; i++)
+ {
+ olMem(pfb = (SFreeBlock *)
+ CMallocBased::operator new (cbBlock, pMalloc));
+ pfb->pfbNext = _pfbHead;
+ _pfbHead = P_TO_BP(CBasedFreeBlockPtr, pfb);
+ }
+ olDebugOut((DEB_ITRACE, "Out CFreeList::Reserve\n"));
+ return S_OK;
+
+ EH_Err:
+ SFreeBlock *pfbT;
+
+ for (; i>0; i--)
+ {
+ olAssert(_pfbHead != NULL);
+ pfbT = BP_TO_P(SFreeBlock *, _pfbHead->pfbNext);
+ delete (CMallocBased *) BP_TO_P(SFreeBlock *, _pfbHead);
+ _pfbHead = P_TO_BP(CBasedFreeBlockPtr, pfbT);
+ }
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFreeList::Unreserve, public
+//
+// Synopsis: Removes N blocks from the list
+//
+// Arguments: [cBlocks] - Number of blocks to free
+//
+// History: 05-Nov-92 DrewB Created
+// 21-May-93 AlexT Switch to CMallocBased
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFreeList_Unreserve)
+#endif
+
+void CFreeList::Unreserve(UINT cBlocks)
+{
+ SFreeBlock *pfbT;
+
+ olDebugOut((DEB_ITRACE, "In CFreeList::Unreserve:%p(%lu)\n",
+ this, cBlocks));
+ for (; cBlocks>0; cBlocks--)
+ {
+ olAssert(_pfbHead != NULL);
+ pfbT = BP_TO_P(SFreeBlock *, _pfbHead->pfbNext);
+ delete (CMallocBased *) BP_TO_P(SFreeBlock *, _pfbHead);
+ _pfbHead = P_TO_BP(CBasedFreeBlockPtr, pfbT);
+ }
+ olDebugOut((DEB_ITRACE, "Out CFreeList::Unreserve\n"));
+}
diff --git a/private/ole32/stg/docfile/funcs.cxx b/private/ole32/stg/docfile/funcs.cxx
new file mode 100644
index 000000000..c4b72d31c
--- /dev/null
+++ b/private/ole32/stg/docfile/funcs.cxx
@@ -0,0 +1,722 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: funcs.cxx
+//
+// Contents: Generic DocFile support functions
+//
+// Functions: ModeToTFlags
+// CheckName
+// VerifyPerms
+//
+// History: 22-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+#include <df32.hxx>
+
+
+//+--------------------------------------------------------------
+//
+// Function: ModeToDFlags, private
+//
+// Synopsis: Translates STGM flags to DF flags
+//
+// Arguments: [dwModeFlags]
+//
+// Returns: DF_*
+//
+// History: 04-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_ModeToDFlags)
+#endif
+
+DFLAGS ModeToDFlags(DWORD const dwModeFlags)
+{
+ DFLAGS df;
+
+ olDebugOut((DEB_ITRACE, "In ModeToDFlags(%lX)\n", dwModeFlags));
+ if ((dwModeFlags & STGM_TRANSACTED) == 0)
+ df = DF_DIRECT;
+ else
+ df = DF_TRANSACTED;
+ if ((dwModeFlags & STGM_TRANSACTED) &&
+ (dwModeFlags & STGM_PRIORITY) == 0 &&
+ (dwModeFlags & STGM_DENY) != STGM_SHARE_DENY_WRITE &&
+ (dwModeFlags & STGM_DENY) != STGM_SHARE_EXCLUSIVE)
+ df |= DF_INDEPENDENT;
+ switch(dwModeFlags & STGM_RDWR)
+ {
+ case STGM_READ:
+ df |= DF_READ;
+ break;
+ case STGM_WRITE:
+ df |= DF_WRITE;
+ break;
+ case STGM_READWRITE:
+ df |= DF_READWRITE;
+ break;
+ default:
+ olAssert(FALSE);
+ break;
+ }
+ switch(dwModeFlags & STGM_DENY)
+ {
+ case STGM_SHARE_DENY_READ:
+ df |= DF_DENYREAD;
+ break;
+ case STGM_SHARE_DENY_WRITE:
+ df |= DF_DENYWRITE;
+ break;
+ case STGM_SHARE_EXCLUSIVE:
+ df |= DF_DENYALL;
+ break;
+ // Default is deny none
+ }
+ if (dwModeFlags & STGM_PRIORITY)
+ df |= DF_PRIORITY;
+
+#ifdef USE_NOSNAPSHOT
+#ifdef USE_NOSNAPSHOT_ALWAYS
+ //This makes all transacted-writeable !deny-write instances no-snapshot,
+ // for testing.
+ if ((dwModeFlags & STGM_TRANSACTED) &&
+ !(df & DF_DENYWRITE) &&
+ (df & DF_WRITE))
+ {
+ df |= DF_NOSNAPSHOT;
+ df &= ~DF_INDEPENDENT;
+ }
+#else
+ if (dwModeFlags & STGM_NOSNAPSHOT)
+ {
+ df |= DF_NOSNAPSHOT;
+ df &= ~DF_INDEPENDENT;
+ }
+#endif //USE_NOSNAPSHOT_ALWAYS
+#endif //USE_NOSNAPSHOT
+
+#ifdef USE_NOSCRATCH
+#ifdef USE_NOSCRATCH_ALWAYS
+ //This makes everything NOSCRATCH, for testing.
+ if ((dwModeFlags & STGM_TRANSACTED) && (df & DF_WRITE))
+ df |= DF_NOSCRATCH;
+#else
+ if (dwModeFlags & STGM_NOSCRATCH)
+ df |= DF_NOSCRATCH;
+#endif
+#endif
+#if WIN32 == 300
+ if (dwModeFlags & STGM_EDIT_ACCESS_RIGHTS)
+ df |= DF_ACCESSCONTROL;
+#endif
+
+ olDebugOut((DEB_ITRACE, "Out ModeToDFlags => %lX\n", df));
+ return df;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: DFlagsToMode, private
+//
+// Synopsis: Converts the read/write/denials/transacted/priority
+// to STGM flags
+//
+// Arguments: [df] - DFlags
+//
+// Returns: STGM flags
+//
+// History: 24-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_DFlagsToMode)
+#endif
+
+DWORD DFlagsToMode(DFLAGS const df)
+{
+ DWORD dwMode;
+
+ olDebugOut((DEB_ITRACE, "In DFlagsToMode(%X)\n", df));
+ if (P_READ(df))
+ if (P_WRITE(df))
+ dwMode = STGM_READWRITE;
+ else
+ dwMode = STGM_READ;
+ else if (P_WRITE(df))
+ dwMode = STGM_WRITE;
+ // Must have either read or write, so no else
+
+ if (P_DENYREAD(df))
+ if (P_DENYWRITE(df))
+ dwMode |= STGM_SHARE_EXCLUSIVE;
+ else
+ dwMode |= STGM_SHARE_DENY_READ;
+ else if (P_DENYWRITE(df))
+ dwMode |= STGM_SHARE_DENY_WRITE;
+ else
+ dwMode |= STGM_SHARE_DENY_NONE;
+
+ if (P_TRANSACTED(df))
+ dwMode |= STGM_TRANSACTED;
+
+ if (P_PRIORITY(df))
+ dwMode |= STGM_PRIORITY;
+
+ if (P_NOSCRATCH(df))
+ dwMode |= STGM_NOSCRATCH;
+
+#ifdef USE_NOSNAPSHOT
+ if (P_NOSNAPSHOT(df))
+ dwMode |= STGM_NOSNAPSHOT;
+#endif
+
+ olDebugOut((DEB_ITRACE, "Out DFlagsToMode\n"));
+ return dwMode;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: VerifyPerms, private
+//
+// Synopsis: Checks flags to see if they are valid
+//
+// Arguments: [grfMode] - Permissions
+//
+// Returns: Appropriate status code
+//
+// History: 19-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_VerifyPerms)
+#endif
+
+SCODE VerifyPerms(DWORD grfMode)
+{
+ SCODE sc = S_OK;
+
+ olDebugOut((DEB_ITRACE, "In VerifyPerms(%lX)\n", grfMode));
+
+ // Check for valid flags
+ if ((grfMode & STGM_RDWR) > STGM_READWRITE ||
+ (grfMode & STGM_DENY) > STGM_SHARE_DENY_NONE ||
+ (grfMode & ~(STGM_RDWR | STGM_DENY | STGM_DIRECT | STGM_TRANSACTED |
+ STGM_PRIORITY | STGM_CREATE | STGM_CONVERT |
+#ifdef USE_NOSCRATCH
+ STGM_NOSCRATCH |
+#endif
+#ifdef USE_NOSNAPSHOT
+#ifndef DISABLE_NOSNAPSHOT
+ STGM_NOSNAPSHOT |
+#endif
+#endif
+#if WIN32 >= 300
+ STGM_EDIT_ACCESS_RIGHTS |
+#endif
+ STGM_FAILIFTHERE | STGM_DELETEONRELEASE)))
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+
+ // If priority is specified...
+ if (grfMode & STGM_PRIORITY)
+ {
+#ifndef REF
+ // Make sure no priority-denied permissions are specified
+ if ((grfMode & STGM_RDWR) == STGM_WRITE ||
+ (grfMode & STGM_RDWR) == STGM_READWRITE ||
+ (grfMode & STGM_TRANSACTED))
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+#else
+ return STG_E_INVALIDFUNCTION;
+#endif //!REF
+ }
+
+#ifdef REF
+ if (grfMode & STGM_TRANSACTED)
+ {
+ return STG_E_INVALIDFUNCTION;
+ }
+#endif //REF
+
+ // Check to make sure only one existence flag is specified
+ // FAILIFTHERE is zero so it can't be checked
+ if ((grfMode & (STGM_CREATE | STGM_CONVERT)) ==
+ (STGM_CREATE | STGM_CONVERT))
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+
+ // If not transacted and not priority, you can either be
+ // read-only deny write or read-write deny all
+ if ((grfMode & (STGM_TRANSACTED | STGM_PRIORITY)) == 0)
+ {
+ if ((grfMode & STGM_RDWR) == STGM_READ)
+ {
+ // we're asking for read-only access
+
+ if ((grfMode & STGM_DENY) != STGM_SHARE_EXCLUSIVE &&
+ (grfMode & STGM_DENY) != STGM_SHARE_DENY_WRITE)
+ {
+ // Can't allow others to have write access
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ }
+ }
+ else
+ {
+ // we're asking for write access
+
+ if ((grfMode & STGM_DENY) != STGM_SHARE_EXCLUSIVE)
+ {
+ // Can't allow others to have any access
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ }
+ }
+ }
+
+#ifdef USE_NOSCRATCH
+ if (grfMode & STGM_NOSCRATCH)
+ {
+ if (((grfMode & STGM_RDWR) == STGM_READ) ||
+ ((grfMode & STGM_TRANSACTED) == 0))
+ {
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ }
+ }
+#endif
+
+#ifdef USE_NOSNAPSHOT
+ if (grfMode & STGM_NOSNAPSHOT)
+ {
+ if (((grfMode & STGM_DENY) == STGM_SHARE_EXCLUSIVE) ||
+ ((grfMode & STGM_DENY) == STGM_SHARE_DENY_WRITE) ||
+ ((grfMode & STGM_TRANSACTED) == 0) ||
+ ((grfMode & STGM_NOSCRATCH) != 0) ||
+ ((grfMode & STGM_CREATE) != 0) ||
+ ((grfMode & STGM_CONVERT) != 0))
+ {
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ }
+ }
+#endif
+
+ olDebugOut((DEB_ITRACE, "Out VerifyPerms\n"));
+ // Fall through
+EH_Err:
+ return sc;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Function: CheckName, public
+//
+// Synopsis: Checks name for illegal characters and length
+//
+// Arguments: [pwcsName] - Name
+//
+// Returns: Appropriate status code
+//
+// History: 11-Feb-92 DrewB Created
+// 04-Dec-95 SusiA Optimized
+//
+//---------------------------------------------------------------
+
+#ifdef OLEWIDECHAR
+SCODE CheckName(WCHAR const *pwcsName)
+{
+ LPCWSTR pChar;
+
+ //Each character's position in the array is detrmined by its ascii numeric
+ //value. ":" is 58, so bit 58 of the array will be 1 if ":" is illegal.
+ //32bits per position in the array, so 58/32 is in Invalid[1].
+ //58%32 = 28th bit ( 0x04000000 ) in Invalid[1].
+
+ /* Invalid characters: : / ! \ */
+ static ULONG const Invalid[128/32] =
+ {0x00000000,0x04008002,0x10000000,0x00000000};
+
+ SCODE sc = STG_E_INVALIDNAME;
+ olDebugOut((DEB_ITRACE, "In CheckName(%ws)\n", pwcsName));
+
+ __try
+ {
+ for (pChar = (LPCWSTR)pwcsName;
+ pChar <= (LPCWSTR) &pwcsName[CWCMAXPATHCOMPLEN];
+ pChar++)
+ {
+ if (*pChar == L'\0')
+ {
+ sc = S_OK;
+ break; // Success
+ }
+
+ // Test to see if this is an invalid character
+ if (*pChar < 128 &&
+ // All values above 128 are valid
+ (Invalid[*pChar / 32] & (1 << (*pChar % 32))) != 0)
+ // check to see if this character's bit is set
+ {
+ break; // Failure: invalid Char
+ }
+ }
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CheckName\n"));
+ return sc;
+
+}
+#endif
+
+#ifdef EMPTYCOPYTO
+//+--------------------------------------------------------------
+//
+// Function: DeleteIStorageContents, public
+//
+// Synopsis: Deletes all entries in an IStorage
+//
+// Arguments: [pstg] - IStorage
+//
+// Returns: Appropriate status code
+//
+// History: 07-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_DeleteIStorageContents) // Expdf_CopyTo_TEXT
+#endif
+
+SCODE DeleteIStorageContents(IStorage *pstg)
+{
+ SCODE sc;
+ IEnumSTATSTG *penm;
+ IStorage *pstgTmp;
+ STATSTG sstg;
+
+ olDebugOut((DEB_ITRACE, "In DeleteIStorageContents(%p)\n", pstg));
+ olChk(pstg->EnumElements(0, NULL, 0, &penm));
+ for (;;)
+ {
+ olChkTo(EH_penm, penm->Next(1, &sstg, NULL));
+ if (S_FALSE == sc)
+ break;
+ if (REAL_STGTY(sstg.type))
+ {
+ // This entry is an embedded DocFile, recurse
+ olChkTo(EH_pwcsName, pstg->OpenStorage(sstg.pwcsName, NULL,
+ STGM_READ | STGM_WRITE |
+ STGM_DENY_READ | STGM_DENY_WRITE,
+ NULL, 0, &pstgTmp));
+ olChkTo(EH_OpenStorage, DeleteIStorageContents(pstgTmp));
+ olVerSucc(pstgTmp->Release());
+ }
+ olChkTo(EH_pwcsName, pstg->DestroyElement(sstg.pwcsName));
+ TaskMemFree(sstg.pwcsName);
+ }
+ olVerSucc(penm->Release());
+ olDebugOut((DEB_ITRACE, "Out DeleteIStorageContents\n"));
+ return S_OK;
+
+EH_OpenStorage:
+ olVerSucc(pstgTmp->Release());
+EH_pwcsName:
+ TaskMemFree(sstg.pwcsName);
+EH_penm:
+ olVerSucc(penm->Release());
+EH_Err:
+ return sc;
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Function: ValidateSNB, private
+//
+// Synopsis: Validates SNB memory
+//
+// Arguments: [snb] - SNB
+//
+// Returns: Appropriate status code
+//
+// History: 10-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_ValidateSNB) //
+#endif
+
+SCODE ValidateSNB(SNBW snb)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In ValidateSNB(%p)\n", snb));
+ for (;;)
+ {
+ olChk(ValidatePtrBuffer(snb));
+ if (*snb == NULL)
+ break;
+ olChk(ValidateNameW(*snb, CWCMAXPATHCOMPLEN));
+ snb++;
+ }
+ olDebugOut((DEB_ITRACE, "Out ValidateSNB\n"));
+ return S_OK;
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: CopySStreamToSStream
+//
+// Synopsis: Copies the contents of a stream to another stream
+//
+// Arguments: [psstFrom] - Stream to copy from
+// [psstTo] - Stream to copy to
+//
+// Returns: Appropriate status code
+//
+// History: 13-Sep-91 DrewB Created
+//
+// Notes: This function may fail due to out of memory. It
+// may not be used by callers who must not fail due
+// to out of memory.
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CopySStreamToSStream)
+#endif
+
+SCODE CopySStreamToSStream(PSStream *psstFrom, PSStream *psstTo)
+{
+ BYTE *pbBuffer = NULL;
+ SCODE sc;
+ ULONG cbRead, cbWritten, cbSize, cbPos;
+
+ // We're allowed to fail due to out of memory
+ olMem(pbBuffer = (BYTE *) DfMemAlloc(STREAMBUFFERSIZE));
+
+ // Set destination size for contiguity
+ psstFrom->GetSize(&cbSize);
+ olChk(psstTo->SetSize(cbSize));
+
+ // Copy between streams
+ cbPos = 0;
+ for (;;)
+ {
+ olChk(psstFrom->ReadAt(cbPos, pbBuffer, STREAMBUFFERSIZE,
+ (ULONG STACKBASED *)&cbRead));
+ if (cbRead == 0) // EOF
+ break;
+ olChk(psstTo->WriteAt(cbPos, pbBuffer, cbRead,
+ (ULONG STACKBASED *)&cbWritten));
+ if (cbRead != cbWritten)
+ olErr(EH_Err, STG_E_WRITEFAULT);
+ cbPos += cbWritten;
+ }
+
+EH_Err:
+ DfMemFree(pbBuffer);
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: dfwcsnicmp, public
+//
+// Synopsis: wide character string compare that interoperates with what
+// we did on 16-bit windows.
+//
+// Arguments: [wcsa] -- First string
+// [wcsb] -- Second string
+// [len] -- Length to compare to
+//
+// Returns: > 0 if wcsa > wcsb
+// < 0 if wcsa < wcsb
+// 0 is wcsa == wcsb
+//
+// History: 11-May-95 PhilipLa Created
+// 22-Nov-95 SusiA Optimize comparisons
+//
+// Notes: This function is necessary because on 16-bit windows our
+// wcsnicmp function converted everything to uppercase and
+// compared the strings, whereas the 32-bit runtimes convert
+// everything to lowercase and compare. This means that the
+// sort order is different for string containing [\]^_`
+//
+//----------------------------------------------------------------------------
+
+int dfwcsnicmp(const WCHAR *wcsa, const WCHAR *wcsb, size_t len)
+{
+ if (!len)
+ return 0;
+
+ while (--len && *wcsa &&
+ ( *wcsa == *wcsb ||
+ CharUpperW((LPWSTR)*wcsa) == CharUpperW((LPWSTR)*wcsb)))
+ {
+ wcsa++;
+ wcsb++;
+ }
+ return (int)CharUpperW((LPWSTR)*wcsa) - (int)CharUpperW((LPWSTR)*wcsb);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Function: NameInSNB, private
+//
+// Synopsis: Determines whether the given name is in the SNB
+//
+// Arguments: [dfn] - Name
+// [snb] - SNB
+//
+// Returns: S_OK or S_FALSE
+//
+// History: 19-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_NameInSNB)
+#endif
+
+SCODE NameInSNB(CDfName const *dfn, SNBW snb)
+{
+ SCODE sc = S_FALSE;
+
+ olDebugOut((DEB_ITRACE, "In NameInSNB(%ws, %p)\n", dfn, snb));
+ TRY
+ {
+ for (; *snb; snb++)
+ if ((lstrlenW(*snb)+1)*sizeof(WCHAR) == dfn->GetLength() &&
+#ifdef CASE_SENSITIVE
+ memcmp(dfn->GetBuffer(), *snb, dfn->GetLength()) == 0)
+#else
+ dfwcsnicmp((WCHAR *)dfn->GetBuffer(), (WCHAR *)*snb,
+ dfn->GetLength()/sizeof(WCHAR)) == 0)
+#endif
+ {
+ sc = S_OK;
+ break;
+ }
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out NameInSNB\n"));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Win32ErrorToScode, public
+//
+// Synopsis: Map a Win32 error into a corresponding scode, remapping
+// into Facility_Storage if appropriate.
+//
+// Arguments: [dwErr] -- Win32 error to map
+//
+// Returns: Appropriate scode
+//
+// History: 22-Sep-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef WIN32
+SCODE Win32ErrorToScode(DWORD dwErr)
+{
+ olAssert((dwErr != NO_ERROR) &&
+ aMsg("Win32ErrorToScode called on NO_ERROR"));
+
+ SCODE sc = STG_E_UNKNOWN;
+
+ switch (dwErr)
+ {
+ case ERROR_INVALID_FUNCTION:
+ sc = STG_E_INVALIDFUNCTION;
+ break;
+ case ERROR_FILE_NOT_FOUND:
+ sc = STG_E_FILENOTFOUND;
+ break;
+ case ERROR_PATH_NOT_FOUND:
+ sc = STG_E_PATHNOTFOUND;
+ break;
+ case ERROR_TOO_MANY_OPEN_FILES:
+ sc = STG_E_TOOMANYOPENFILES;
+ break;
+ case ERROR_ACCESS_DENIED:
+ case ERROR_NETWORK_ACCESS_DENIED:
+ sc = STG_E_ACCESSDENIED;
+ break;
+ case ERROR_INVALID_HANDLE:
+ sc = STG_E_INVALIDHANDLE;
+ break;
+ case ERROR_NOT_ENOUGH_MEMORY:
+ sc = STG_E_INSUFFICIENTMEMORY;
+ break;
+ case ERROR_NO_MORE_FILES:
+ sc = STG_E_NOMOREFILES;
+ break;
+ case ERROR_WRITE_PROTECT:
+ sc = STG_E_DISKISWRITEPROTECTED;
+ break;
+ case ERROR_SEEK:
+ sc = STG_E_SEEKERROR;
+ break;
+ case ERROR_WRITE_FAULT:
+ sc = STG_E_WRITEFAULT;
+ break;
+ case ERROR_READ_FAULT:
+ sc = STG_E_READFAULT;
+ break;
+ case ERROR_SHARING_VIOLATION:
+ sc = STG_E_SHAREVIOLATION;
+ break;
+ case ERROR_LOCK_VIOLATION:
+ sc = STG_E_LOCKVIOLATION;
+ break;
+ case ERROR_HANDLE_DISK_FULL:
+ case ERROR_DISK_FULL:
+ sc = STG_E_MEDIUMFULL;
+ break;
+ case ERROR_FILE_EXISTS:
+ case ERROR_ALREADY_EXISTS:
+ sc = STG_E_FILEALREADYEXISTS;
+ break;
+ case ERROR_INVALID_PARAMETER:
+ sc = STG_E_INVALIDPARAMETER;
+ break;
+ case ERROR_INVALID_NAME:
+ case ERROR_BAD_PATHNAME:
+ case ERROR_FILENAME_EXCED_RANGE:
+ sc = STG_E_INVALIDNAME;
+ break;
+ case ERROR_INVALID_FLAGS:
+ sc = STG_E_INVALIDFLAG;
+ break;
+ default:
+ sc = WIN32_SCODE(dwErr);
+ break;
+ }
+
+ return sc;
+}
+#endif
+
+
diff --git a/private/ole32/stg/docfile/makefile b/private/ole32/stg/docfile/makefile
new file mode 100644
index 000000000..e76de2f73
--- /dev/null
+++ b/private/ole32/stg/docfile/makefile
@@ -0,0 +1,20 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1994 **
+#********************************************************************
+
+!ifdef NTMAKEENV
+
+all:
+ echo $(BUILDMSG)
+
+clean:
+
+!else
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/stg/docfile/mem.cxx b/private/ole32/stg/docfile/mem.cxx
new file mode 100644
index 000000000..1df521e04
--- /dev/null
+++ b/private/ole32/stg/docfile/mem.cxx
@@ -0,0 +1,1133 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: Mem.CXX
+//
+// Contents: Memory tracking code
+//
+// Classes: CMemAlloc
+//
+// Functions: DfCreateSharedAllocator
+// DfPrintAllocs
+// DfGetMemAlloced
+//
+// History: 17-May-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+#if defined(WIN32)
+
+#include <smalloc.hxx>
+#include <olesem.hxx>
+
+// This global variable holds the base address of the shared memory region.
+// It is required by the based pointer stuff and is accessed directly.
+// Initialisation is a side effect of calling DfCreateSharedAllocator or
+// DfSyncSharedMemory (BUGBUG: or will be, when the based pointer stuff
+// is checked in).
+
+#ifdef MULTIHEAP
+//__declspec(thread) void *DFBASEPTR = NULL;
+#else
+void *DFBASEPTR = NULL;
+#endif
+
+#endif
+
+#if DBG == 1
+#include <dfdeb.hxx>
+
+#ifdef _M_I286
+#include <dos.h>
+#include <toolhelp.h>
+#endif
+
+#ifdef WIN32
+// Multithread protection for allocation list
+CStaticDfMutex _sdmtxAllocs(TSTR("DfAllocList"));
+
+#define TAKE_ALLOCS_MUTEX olVerSucc(_sdmtxAllocs.Take(INFINITE))
+#define RELEASE_ALLOCS_MUTEX _sdmtxAllocs.Release()
+#else
+#define TAKE_ALLOCS_MUTEX
+#define RELEASE_ALLOCS_MUTEX
+#endif
+
+#define GET_ALLOC_LIST_HEAD ((CMemAlloc *)DfGetResLimit(DBRI_ALLOC_LIST))
+#define SET_ALLOC_LIST_HEAD(pma) DfSetResLimit(DBRI_ALLOC_LIST, (LONG)(pma))
+
+#define DEB_MEMORY 0x01000000
+#define DEB_LEAKS 0x01100000
+
+const int NEWMEM = 0xDEDE;
+const int OLDMEM = 0xEDED;
+
+//+--------------------------------------------------------------
+//
+// Class: CMemAlloc (ma)
+//
+// Purpose: Tracks memory allocations
+//
+// Interface: See below
+//
+// History: 08-Jul-92 DrewB Created
+// 17-May-93 AlexT Add idContext
+//
+//---------------------------------------------------------------
+
+class CMemAlloc
+{
+public:
+ void *pvCaller;
+ ULONG cbSize;
+ void *pvMem;
+ ContextId idContext;
+ CMemAlloc *pmaPrev, *pmaNext;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Function: AddAlloc, private
+//
+// Synopsis: Puts an allocation into the allocation list
+//
+// Arguments: [pma] - Allocation descriptor
+// [pvCaller] - Allocator
+// [cbSize] - Real size
+// [pvMem] - Memory block
+// [cid] - Context ID
+//
+// History: 11-Jan-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+static void AddAlloc(CMemAlloc *pma, void *pvCaller, ULONG cbSize,
+ void *pvMem, ContextId cid)
+{
+ pma->pvCaller = pvCaller;
+ pma->cbSize = cbSize;
+ pma->pvMem = pvMem;
+ pma->idContext = cid;
+
+#ifdef MEMTRACK
+ TAKE_ALLOCS_MUTEX;
+
+ pma->pmaNext = GET_ALLOC_LIST_HEAD;
+ if (pma->pmaNext)
+ pma->pmaNext->pmaPrev = pma;
+ pma->pmaPrev = NULL;
+ olAssert(!IsBadReadPtr(pma, sizeof(CMemAlloc)));
+ SET_ALLOC_LIST_HEAD(pma);
+
+ RELEASE_ALLOCS_MUTEX;
+
+ ModifyResLimit(DBRQ_MEMORY_ALLOCATED, (LONG)cbSize);
+
+ olDebugOut((DEB_MEMORY, "%s alloced %p:%lu, total %ld\n",
+ cid != 0 ? "Task" : "Shrd",
+ pvMem, pma->cbSize, DfGetResLimit(DBRQ_MEMORY_ALLOCATED)));
+
+#endif
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: RemoveAlloc, private
+//
+// Synopsis: Takes an allocation out of the allocation list
+//
+// Arguments: [pma] - Allocation descriptor
+// [pvMem] - Real allocation
+// [cid] - Context ID
+//
+// History: 11-Jan-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+static void RemoveAlloc(CMemAlloc *pma, void *pvMem, ContextId cid)
+{
+#ifdef MEMTRACK
+ olAssert(pma->pvMem == pvMem && aMsg("Address mismatch"));
+ olAssert(pma->idContext == cid && aMsg("Context mismatch"));
+
+ TAKE_ALLOCS_MUTEX;
+
+ olAssert(pma->pmaNext == NULL ||
+ !IsBadReadPtr(pma->pmaNext, sizeof(CMemAlloc)));
+ olAssert(pma->pmaPrev == NULL ||
+ !IsBadReadPtr(pma->pmaPrev, sizeof(CMemAlloc)));
+ if (pma->pmaPrev)
+ {
+ pma->pmaPrev->pmaNext = pma->pmaNext;
+ }
+ else
+ {
+ SET_ALLOC_LIST_HEAD(pma->pmaNext);
+ }
+ if (pma->pmaNext)
+ {
+ pma->pmaNext->pmaPrev = pma->pmaPrev;
+ }
+
+ RELEASE_ALLOCS_MUTEX;
+
+ ModifyResLimit(DBR_MEMORY, (LONG)pma->cbSize);
+
+ ModifyResLimit(DBRQ_MEMORY_ALLOCATED, -(LONG)pma->cbSize);
+ olAssert(DfGetResLimit(DBRQ_MEMORY_ALLOCATED) >= 0);
+
+ olDebugOut((DEB_MEMORY, "%s freed %p:%lu, total %ld\n",
+ cid != 0 ? "Task" : "Shrd",
+ pma->pvMem, pma->cbSize,
+ DfGetResLimit(DBRQ_MEMORY_ALLOCATED)));
+#endif
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: DfGetMemAlloced, private
+//
+// Synopsis: Returns the amount of memory currently allocated
+//
+// History: 08-Jul-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI_(LONG) DfGetMemAlloced(void)
+{
+ return DfGetResLimit(DBRQ_MEMORY_ALLOCATED);
+}
+
+//+--------------------------------------------------------------
+//
+// Function: DfPrintAllocs, private
+//
+// Synopsis: Walks the allocation list and prints out their info
+//
+// History: 08-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDAPI_(void) DfPrintAllocs(void)
+{
+#ifdef MEMTRACK
+ CMemAlloc *pma;
+
+ olDebugOut((DEB_ITRACE, "In DfPrintAllocs()\n"));
+
+ TAKE_ALLOCS_MUTEX;
+
+ pma = GET_ALLOC_LIST_HEAD;
+ while (pma != NULL)
+ {
+#ifdef _M_I286
+ HGLOBAL hgbCode;
+ GLOBALENTRY ge;
+
+ hgbCode = LOWORD(GlobalHandle(_FP_SEG(pma->pvCaller)));
+ ge.dwSize = sizeof(ge);
+
+ if (hgbCode == 0 || !GlobalEntryHandle(&ge, hgbCode) ||
+ ge.wType != GT_CODE)
+ olDebugOut((DEB_LEAKS, "Alloc: %p alloc %p:%4lu bytes\n",
+ pma->pvCaller, pma->pvMem, pma->cbSize));
+ else
+ // The (unsigned short)(unsigned long) cast is necessary
+ // to avoid a compiler warning. We want the offset of
+ // the pointer which is an unsigned short. A direct
+ // cast results in a "segment lost" warning. Casting
+ // to unsigned long first avoids this unnecessary warning
+ olDebugOut((DEB_LEAKS,
+ "Alloc %s: %2X:%04X alloc %p:%4lu bytes\n",
+ pma->idContext ? "LOCAL" : "SHARED",
+ ge.wData, (unsigned short)(unsigned long)pma->pvCaller,
+ pma->pvMem, pma->cbSize));
+#else
+ olDebugOut((DEB_LEAKS, "Alloc %s: %p alloc %p:%4lu bytes\n",
+ pma->idContext ? "LOCAL" : "SHARED",
+ pma->pvCaller, pma->pvMem, pma->cbSize));
+#endif
+ pma = pma->pmaNext;
+ }
+
+ RELEASE_ALLOCS_MUTEX;
+
+ olDebugOut((DEB_ITRACE, "Out DfPrintAllocs\n"));
+#endif
+}
+
+#endif
+
+#ifdef MULTIHEAP
+
+CSmAllocator g_SmAllocator; // optimization for single threaded case
+CErrorSmAllocator g_ErrorSmAllocator;
+CSharedMemoryBlock g_smb; // optimize single threaded case
+ULONG g_ulHeapName = 0; // name of the above heap
+TEB * g_pteb = NtCurrentTeb();
+
+CSmAllocator& GetTlsSmAllocator()
+{
+ HRESULT hr;
+ COleTls otls(hr); // even for main thread, we need to initialize TLS
+ memAssert (SUCCEEDED(hr) && "Error initializing TLS");
+
+ if (g_pteb == NtCurrentTeb())
+ {
+ // return the static global allocator for main thread
+ // DoThreadSpecificCleanup does not deallocate this allocator
+ return g_SmAllocator;
+ }
+
+ if (otls->pSmAllocator == NULL)
+ {
+ if ((otls->pSmAllocator = new CSmAllocator()) == NULL)
+ otls->pSmAllocator = &g_ErrorSmAllocator;
+ // DoThreadSpecificCleanup will deallocate this when thread goes away
+ }
+ return *(otls->pSmAllocator);
+}
+
+//
+// This initialization used to be done in the global allocator
+// which is now a per thread allocator
+//
+class CResourceCriticalSection
+{
+public:
+ CResourceCriticalSection ()
+ {
+ InitializeCriticalSection(&g_csScratchBuffer);
+#ifdef COORD
+ InitializeCriticalSection(&g_csResourceList);
+#endif
+ }
+ ~CResourceCriticalSection ()
+ {
+ DeleteCriticalSection(&g_csScratchBuffer);
+#ifdef COORD
+ DeleteCriticalSection(&g_csResourceList);
+#endif
+ }
+};
+CResourceCriticalSection g_ResourceCriticalSection;
+
+#else
+CSmAllocator g_smAllocator;
+#endif // MULTIHEAP
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMallocBased::operator new, public
+//
+// Synopsis: Overridden allocator
+//
+// Effects: Allocates memory from given allocator
+//
+// Arguments: [size] -- byte count to allocate
+// [pMalloc] -- allocator
+//
+// Returns: memory block address
+//
+// Algorithm:
+//
+// History: 21-May-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMallocBased_new)
+#endif
+
+void *CMallocBased::operator new(size_t size, IMalloc * const pMalloc)
+
+{
+#ifndef WIN32
+ olAssert(DfGetResLimit(DBRQ_MEMORY_ALLOCATED) >= 0);
+#endif
+ olAssert(size > 0);
+
+#if DBG==1
+ if (SimulateFailure(DBF_MEMORY))
+ {
+ return(NULL);
+ }
+
+ if (!HaveResource(DBR_MEMORY, (LONG)size))
+ {
+ // Artificial limit exceeded so force failure
+ return NULL;
+ }
+#endif
+
+ void *pv = g_smAllocator.Alloc(
+#if DBG==1
+ sizeof(CMemAlloc) +
+#endif
+ size);
+
+ if (pv == NULL)
+ {
+#if DBG==1
+ ModifyResLimit(DBR_MEMORY, (LONG)size);
+#endif
+ return NULL;
+ }
+
+#if DBG==1
+ memset(pv, NEWMEM, sizeof(CMemAlloc) + size);
+#endif
+
+
+
+#if DBG==1
+ // Put debug info in buffer
+ // Note: This assumes CMemAlloc will end up properly aligned
+ CMemAlloc *pma = (CMemAlloc *) pv;
+ pv = (void *) ((CMemAlloc *) pv + 1);
+
+ AddAlloc(pma, *(((void **)&size)-1), size, pv, 0);
+#endif
+
+ return pv;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMallocBased::operator delete
+//
+// Synopsis: Overridden deallocator
+//
+// Effects: Frees memory block
+//
+// Arguments: [pv] -- memory block address
+//
+// Algorithm:
+//
+// History: 21-May-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMallocBased_delete)
+#endif
+
+void CMallocBased::operator delete(void *pv)
+
+{
+ if (pv == NULL)
+ return;
+
+#if DBG==1
+ // Assumes ma ends up properly aligned
+ CMemAlloc *pma = (CMemAlloc *) pv;
+ pma--;
+
+ RemoveAlloc(pma, pv, 0);
+
+ pv = (void *) pma;
+
+ memset(pv, OLDMEM, (size_t) pma->cbSize);
+#endif
+
+ g_smAllocator.Free(pv);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMallocBased::deleteNoMutex
+//
+// Synopsis: deallocator function without Mutex
+//
+// Effects: Frees memory block
+//
+// Arguments: [pv] -- memory block address
+// Algorithm:
+//
+// History: 19-Jul-95 SusiA Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMallocBased_deleteNoMutex)
+#endif
+
+void CMallocBased::deleteNoMutex(void *pv)
+
+{
+ if (pv == NULL)
+ return;
+
+#if DBG==1
+ // Assumes ma ends up properly aligned
+ CMemAlloc *pma = (CMemAlloc *) pv;
+ pma--;
+
+ RemoveAlloc(pma, pv, 0);
+
+ pv = (void *) pma;
+
+ memset(pv, OLDMEM, (size_t) pma->cbSize);
+#endif
+
+ g_smAllocator.FreeNoMutex(pv);
+
+}
+
+
+
+#if !defined(WIN32) && DBG==1
+
+//+-------------------------------------------------------------------------
+//
+// Class: CSharedMalloc
+//
+// Purpose: Track shared allocators
+//
+// Interface: IMalloc
+//
+// History: 28-May-93 AlexT Created
+//
+// Notes: This is only for builds that use CoCreateStandardMalloc
+// (which is non-WIN32 builds for now). We inherit from
+// CMallocBased to pick up memory tracking.
+//
+//--------------------------------------------------------------------------
+
+class CSharedMalloc : public IMalloc, public CMallocBased
+{
+public:
+ CSharedMalloc(IMalloc *pMalloc);
+
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ // *** IMalloc methods ***
+ STDMETHOD_(void FAR*, Alloc) (THIS_ ULONG cb);
+ STDMETHOD_(void FAR*, Realloc) (THIS_ void FAR* pv, ULONG cb);
+ STDMETHOD_(void, Free) (THIS_ void FAR* pv);
+ STDMETHOD_(ULONG, GetSize) (THIS_ void FAR* pv);
+ STDMETHOD_(int, DidAlloc) (THIS_ void FAR* pv);
+ STDMETHOD_(void, HeapMinimize) (THIS);
+
+private:
+ IMalloc * const _pMalloc;
+};
+
+CSharedMalloc::CSharedMalloc(IMalloc *pMalloc)
+: _pMalloc(pMalloc)
+{
+ _pMalloc->AddRef();
+}
+
+STDMETHODIMP CSharedMalloc::QueryInterface(THIS_ REFIID riid, LPVOID FAR* ppvObj)
+{
+ olAssert(!aMsg("CSharedMalloc::QueryInterface unsupported"));
+ return(ResultFromScode(E_UNEXPECTED));
+}
+
+STDMETHODIMP_(ULONG) CSharedMalloc::AddRef (THIS)
+{
+ return(_pMalloc->AddRef());
+}
+
+STDMETHODIMP_(ULONG) CSharedMalloc::Release (THIS)
+{
+ ULONG cRef = _pMalloc->Release();
+
+ if (cRef == 0)
+ delete this;
+
+ return (ULONG) cRef;
+}
+
+STDMETHODIMP_(void FAR*) CSharedMalloc::Alloc (THIS_ ULONG cb)
+{
+ return _pMalloc->Alloc(cb);
+}
+
+STDMETHODIMP_(void FAR*) CSharedMalloc::Realloc (THIS_ void FAR* pv, ULONG cb)
+{
+ olAssert(!aMsg("CSharedMalloc::Realloc unsupported"));
+ return(NULL);
+}
+
+STDMETHODIMP_(void) CSharedMalloc::Free (THIS_ void FAR* pv)
+{
+ _pMalloc->Free(pv);
+}
+
+STDMETHODIMP_(ULONG) CSharedMalloc::GetSize (THIS_ void FAR* pv)
+{
+ olAssert(!aMsg("CSharedMalloc::GetSize unsupported"));
+ return(0);
+}
+
+STDMETHODIMP_(int) CSharedMalloc::DidAlloc (THIS_ void FAR* pv)
+{
+ olAssert(!aMsg("CSharedMalloc::DidAlloc unsupported"));
+ return(TRUE);
+}
+
+STDMETHODIMP_(void) CSharedMalloc::HeapMinimize (THIS)
+{
+ olAssert(!aMsg("CSharedMalloc::HeapMinimize unsupported"));
+}
+
+#endif
+
+#if defined(WIN32)
+
+// -------------- Shared memory allocator stuff for Win32 ---------------
+
+
+
+typedef HRESULT InitSmFn ( IMalloc ** ppm );
+extern HRESULT NullInitSm ( IMalloc ** ppm );
+extern HRESULT InitSharedAllocator ( IMalloc ** ppm);
+#ifdef MULTIHEAP
+extern HRESULT InitMultipleSharedAllocator (IMalloc ** ppm );
+InitSmFn * DfCreateSharedAllocator = InitMultipleSharedAllocator;
+#else
+InitSmFn * DfCreateSharedAllocator = InitSharedAllocator;
+#endif
+
+#if !defined(MULTIHEAP)
+COleStaticMutexSem mxsInitSm;
+BOOL fInitialisedSm = FALSE;
+
+//+-------------------------------------------------------------------------
+//
+// Function: InitSharedAllocator
+//
+// Synopsis: Initialises the shared memory region for this process.
+//
+// Arguments: [ppm] -- return address for shared memory IMalloc*
+//
+// Returns: status code
+//
+// History: 27-May-94 MikeSe Created
+//
+// Notes: This routine is called indirectly through DfCreateSharedAllocator, in
+// such a way that in most circumstances it will be executed
+// exactly once per process. (Because we overwrite the contents
+// of DfCreateSharedAllocator if successful).
+//
+// However, in order to be multi-thread safe, we need a process
+// mutex to prevent execution of the initialisation code twice.
+//
+// Furthermore, since we are initialising system-wide state
+// (namely the shared memory region) we must provide cross-process
+// mutual exclusion over this activity.
+//
+//--------------------------------------------------------------------------
+
+HRESULT InitSharedAllocator (
+ IMalloc ** ppm )
+{
+ // multi-thread safety
+
+ mxsInitSm.Request();
+
+ HRESULT hr = S_OK;
+
+ if ( !fInitialisedSm )
+ {
+ // We need to do the initialisation. Obtain exclusion against
+ // other processes.
+
+ SECURITY_ATTRIBUTES secattr;
+ secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
+#ifndef _CHICAGO_
+ CWorldSecurityDescriptor wsd;
+ secattr.lpSecurityDescriptor = &wsd;
+#else
+ secattr.lpSecurityDescriptor = NULL;
+#endif // !_CHICAGO_
+ secattr.bInheritHandle = FALSE;
+
+ HANDLE hMutex = CreateMutex ( &secattr, FALSE, TEXT("OleDfSharedMemoryMutex"));
+ if ( hMutex != NULL )
+ {
+ WaitForSingleObject ( hMutex, INFINITE );
+ hr = g_smAllocator.Init ( DOCFILE_SM_NAME );
+ if ( SUCCEEDED(hr) )
+ {
+ *ppm = &g_smAllocator;
+ // Also set up base address
+#ifdef USEBASED
+ DFBASEPTR = g_smAllocator.GetBase();
+#endif
+ DfCreateSharedAllocator = NullInitSm;
+ fInitialisedSm = TRUE;
+ }
+ ReleaseMutex ( hMutex );
+ }
+ else
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ else // fInitialisedSm is TRUE
+ {
+ *ppm = &g_smAllocator;
+ }
+ mxsInitSm.Release();
+ return hr;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: NullInitSm
+//
+// Synopsis: Second and subsequent times handler for DfCreateSharedAllocator
+//
+// Effects: Simply returns pointer to g_smAllocator.
+//
+// Arguments: [ppm] -- return address for shared memory IMalloc*
+//
+// Returns: S_OK
+//
+// History: 27-May-94 MikeSe Created
+//
+// Notes: This function cannot be called unless we successfully
+// initialise the shared memory (because we do not overwrite
+// the contents of DfCreateSharedAllocator until then).
+//
+//--------------------------------------------------------------------------
+
+HRESULT NullInitSm (
+ IMalloc **ppm )
+{
+ *ppm = &g_smAllocator;
+ return S_OK;
+}
+#endif // !defined(MULTIHEAP)
+
+#ifdef MULTIHEAP
+//+-------------------------------------------------------------------------
+//
+// Function: InitMultipleSharedAllocator
+//
+// Synopsis: Initialises a shared memory region for this process.
+//
+// Arguments: [ppm] -- return address for shared memory IMalloc*
+//
+// Returns: status code
+//
+// History: 20-Nov-95 HenryLee Created
+//
+// Notes: This routine is called indirectly by DfCreateSharedAllocator
+// such a way that in most circumstances it will be executed
+// exactly once per docfile open.
+//
+//--------------------------------------------------------------------------
+
+HRESULT InitMultipleSharedAllocator (IMalloc ** ppm )
+{
+ HRESULT hr = S_OK;
+
+ CSmAllocator *pMalloc = &g_smAllocator;
+ *ppm = NULL;
+
+ if (DFBASEPTR == NULL) // allocate a new heap
+ {
+ LUID luid; // generate a unique name
+ if (AllocateLocallyUniqueId (&luid) == FALSE)
+ return HRESULT_FROM_WIN32(GetLastError());
+
+ // reset the allocator state to initialize it properly
+ pMalloc->SetState (NULL, NULL, NULL, NULL, 0);
+
+ hr = pMalloc->Init ( luid.LowPart, FALSE );
+ if ( SUCCEEDED(hr) )
+ {
+ *ppm = pMalloc;
+ DFBASEPTR = pMalloc->GetBase();
+ pMalloc->AddRef();
+ }
+ }
+ else // use an existing heap
+ *ppm = pMalloc;
+
+ return hr;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: DfSyncSharedMemory, public
+//
+// Synopsis: Sync up shared memory
+//
+// Returns: Appropriate status code
+//
+// History: 08-Apr-94 PhilipLa Created
+//
+// Notes: BUGBUG should play pointer game here too
+//
+//----------------------------------------------------------------------------
+
+#ifdef MULTIHEAP
+SCODE DfSyncSharedMemory(ULONG ulHeapName)
+#else
+SCODE DfSyncSharedMemory(void)
+#endif
+{
+ // make sure we have initialised
+ HRESULT hr = S_OK;
+
+#ifdef MULTIHEAP
+ CSmAllocator *pMalloc = &g_smAllocator;
+ if (ulHeapName != 0) // reopen a shared heap for unmarshaling
+ {
+ // reset the allocator state to initialize it properly
+ pMalloc->SetState (NULL, NULL, NULL, NULL, 0);
+
+ hr = pMalloc->Init ( ulHeapName, TRUE);
+ DFBASEPTR = pMalloc->GetBase();
+
+ }
+ else // try to create a new shared heap
+#else
+ if (!fInitialisedSm)
+#endif // MULTIHEAP
+ {
+ IMalloc * pm;
+ hr = DfCreateSharedAllocator ( &pm );
+ }
+ if ( SUCCEEDED(hr) )
+#ifdef MULTIHEAP
+ hr = pMalloc->Sync();
+#else
+ hr = g_smAllocator.Sync();
+#endif
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DfInitSharedMemBase, public
+//
+// Synopsis: Set up the base of shared memory
+//
+// History: 31-May-94 MikeSe Created
+//
+// Notes: BUGBUG this may go away
+//
+//----------------------------------------------------------------------------
+
+void DfInitSharedMemBase()
+{
+#ifdef MULTIHEAP
+ HRESULT hr;
+ COleTls otls(hr);
+ memAssert (SUCCEEDED(hr) && "Error initializing TLS");
+
+ DFBASEPTR = NULL; // this will force a heap to be allocated
+ // when DfCreateSharedAllocator is called
+#else
+ // make sure we have initialised. This is sufficient to ensure
+ // that DFBASEPTR is set up
+ if (!fInitialisedSm)
+ {
+ IMalloc * pm;
+ HRESULT hr = DfCreateSharedAllocator ( &pm );
+ }
+#endif
+}
+
+#elif DBG==1
+
+// Win16, debug only shared memory stuff
+
+//+-------------------------------------------------------------------------
+//
+// Function: DfCreateSharedAllocator
+//
+// Synopsis: Create shared memory tracking allocator
+//
+// Effects:
+//
+// Arguments: [ppm] -- place holder for returned IMalloc instance
+//
+// Returns: HRESULT
+//
+// Algorithm:
+//
+// History: 17-May-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT DfCreateSharedAllocator(IMalloc **ppm)
+{
+ SCODE sc;
+ IMalloc *pMallocNew, *pMallocShare;
+
+ olHChk(CoCreateStandardMalloc(MEMCTX_SHARED, &pMallocNew));
+ olHChkTo(EH_New, CoGetMalloc(MEMCTX_SHARED, &pMallocShare));
+ olMemTo(EH_Share, *ppm = new (pMallocShare) CSharedMalloc(pMallocNew));
+
+EH_Share:
+ pMallocShare->Release();
+EH_New:
+ pMallocNew->Release();
+EH_Err:
+ return(ResultFromScode(sc));
+}
+
+#endif
+
+// BUGBUG re-enable debug allocator with shared heap support
+#if DBG==1 && !defined(MULTIHEAP)
+
+//+-------------------------------------------------------------------------
+//
+// Method: CLocalAlloc::operator new, public
+//
+// Synopsis: Overloaded new operator to allocate objects from
+// task local space.
+//
+// Arguments: [size] -- Size of block to allocate
+//
+// Returns: Pointer to memory allocated.
+//
+// History: 17-Aug-92 PhilipLa Created.
+// 18-May-93 AlexT Switch to task IMalloc
+//
+//--------------------------------------------------------------------------
+
+void *CLocalAlloc::operator new(size_t size)
+{
+#ifndef WIN32
+ olAssert(DfGetResLimit(DBRQ_MEMORY_ALLOCATED) >= 0);
+#endif
+ olAssert(size > 0);
+
+ if (SimulateFailure(DBF_MEMORY))
+ {
+ return(NULL);
+ }
+
+ if (!HaveResource(DBR_MEMORY, (LONG)size))
+ {
+ // Artificial limit exceeded so force failure
+ return NULL;
+ }
+
+ void *pv = TaskMemAlloc(sizeof(CMemAlloc *) + size);
+
+ if (pv != NULL)
+ {
+ void * const pvOrig = pv;
+
+ memset(pv, NEWMEM, sizeof(CMemAlloc *) + size);
+
+ CMemAlloc *pma = NULL;
+
+ // Allocate tracking block (with shared memory)
+ IMalloc *pMalloc;
+
+#ifdef WIN32
+#ifdef MULTIHEAP
+ pMalloc = &g_smAllocator;
+#else
+ if ( FAILED(DfCreateSharedAllocator ( &pMalloc )) )
+ pMalloc = NULL;
+#endif // MULTIHEAP
+#else
+ if (FAILED(DfGetScode(CoGetMalloc(MEMCTX_SHARED, &pMalloc))))
+ pMalloc = NULL;
+#endif
+
+ if (pMalloc)
+ {
+ pma = (CMemAlloc *) pMalloc->Alloc(sizeof(CMemAlloc));
+ if (pma != NULL)
+ {
+ memset(pma, NEWMEM, sizeof(CMemAlloc));
+ CMemAlloc **ppma = (CMemAlloc **) pv;
+ pv = (void *) ((CMemAlloc **)pv + 1);
+ *ppma = pma;
+
+ AddAlloc(pma, *(((void **)&size)-1), size, pv,
+ GetCurrentContextId());
+ }
+
+ pMalloc->Release();
+ }
+
+ if (pma == NULL)
+ {
+ // Couldn't allocate tracking block - fail allocation
+ TaskMemFree(pvOrig);
+ pv = NULL;
+ }
+ }
+
+ if (pv == NULL)
+ {
+ ModifyResLimit(DBR_MEMORY, (LONG)size);
+ }
+
+ return(pv);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CLocalAlloc::operator delete, public
+//
+// Synopsis: Free memory from task local space
+//
+// Arguments: [pv] -- Pointer to memory to free
+//
+// History: 17-Aug-92 PhilipLa Created.
+// 18-May-93 AlexT Switch to task IMalloc
+//
+//--------------------------------------------------------------------------
+
+void CLocalAlloc::operator delete(void *pv)
+{
+ if (pv == NULL)
+ return;
+
+ CMemAlloc **ppma = (CMemAlloc **)pv;
+ ppma--;
+
+ CMemAlloc *pma = *ppma;
+
+ RemoveAlloc(pma, pv, GetCurrentContextId());
+
+ pv = (void *) ppma;
+ memset(pv, OLDMEM, (size_t) pma->cbSize);
+
+ // Free tracking block
+ IMalloc *pMalloc = NULL;
+
+#ifdef WIN32
+#ifdef MULTIHEAP
+ pMalloc = &g_smAllocator;
+#else
+ if ( FAILED(DfCreateSharedAllocator ( &pMalloc )) )
+ pMalloc = NULL;
+#endif // MULTIHEAP
+#else
+ if (FAILED(DfGetScode(CoGetMalloc(MEMCTX_SHARED, &pMalloc))))
+ pMalloc = NULL;
+#endif
+
+ if (pMalloc != NULL)
+ {
+ memset(pma, OLDMEM, sizeof(CMemAlloc));
+ pMalloc->Free(pma);
+ pMalloc->Release();
+ }
+ else
+ olAssert(!aMsg("Unable to get shared allocator\n"));
+
+ TaskMemFree(pv);
+}
+
+#endif // DBG==1 && !defined(MULTIHEAP)
+
+#if !defined(WIN32)
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_TaskMemAlloc)
+#endif
+
+void *TaskMemAlloc(ULONG ulcb)
+{
+ void FAR* pv = NULL;
+ IMalloc FAR* pMalloc;
+
+ if (SUCCEEDED(GetScode(CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ pv = pMalloc->Alloc(ulcb);
+ pMalloc->Release();
+ }
+
+ return(pv);
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_TaskMemFree)
+#endif
+
+void TaskMemFree(void *pv)
+{
+ IMalloc FAR* pMalloc;
+ if (SUCCEEDED(GetScode(CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ pMalloc->Free(pv);
+ pMalloc->Release();
+ }
+}
+
+#endif // !defined(WIN32)
+
+#if DBG == 1 && WIN32 == 0
+
+//+-------------------------------------------------------------------------
+//
+// Function: operator new
+//
+// Synopsis: Global new
+//
+// Effects: Asserts
+//
+// Arguments: [size] -- count of bytes
+//
+// History: 26-May-93 AlexT Created
+//
+// Notes: None of our code should use global new
+//
+//--------------------------------------------------------------------------
+
+void * _CRTAPI1 operator new(size_t size)
+{
+ olAssert(!aMsg("global new called"));
+ return(NULL);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: operator delete
+//
+// Synopsis: Global delete
+//
+// Effects: Asserts
+//
+// Arguments: [pv] -- memory address
+//
+// History: 26-May-93 AlexT Created
+//
+// Notes: None of our code should use global delete
+//
+//--------------------------------------------------------------------------
+
+void _CRTAPI1 operator delete(void *pv)
+{
+ olAssert(!aMsg("Global delete called"));
+}
+
+#endif // DBG == 1 && WIN32 == 0
diff --git a/private/ole32/stg/docfile/pdffuncs.cxx b/private/ole32/stg/docfile/pdffuncs.cxx
new file mode 100644
index 000000000..2ddb3431d
--- /dev/null
+++ b/private/ole32/stg/docfile/pdffuncs.cxx
@@ -0,0 +1,155 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: pdffuncs.cxx
+//
+// Contents: PDocFile static member functions
+//
+// History: 22-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+#ifndef REF
+#include <tstream.hxx>
+#endif //!REF
+
+#ifndef REF
+//+---------------------------------------------------------------------------
+//
+// Member: PDocFile::CreateFromUpdate, public
+//
+// Synopsis: Creates an object from an update list entry
+//
+// Arguments: [pud] - Update entry
+// [pdf] - Docfile
+// [df] - Permissions
+//
+// Returns: Appropriate status code
+//
+// History: 02-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_PDocFile_CreateFromUpdate) // Gendf_Commit_TEXT
+#endif
+
+SCODE PDocFile::CreateFromUpdate(CUpdate *pud,
+ PDocFile *pdf,
+ DFLAGS df)
+{
+ PDocFile *pdfChild;
+ PSStream *pstChild;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In PDocFile::CreateFromUpdate(%p, %p, %X)\n",
+ pud, pdf, df));
+ olAssert(pud->GetXSM() != NULL);
+ switch(pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL))
+ {
+ case STGTY_STORAGE:
+ olChk(pdf->CreateDocFile(pud->GetCurrentName(), df, pud->GetLUID(),
+ pud->GetFlags() & ULF_TYPEFLAGS, &pdfChild));
+ olChkTo(EH_Create,
+ ((CWrappedDocFile *)pud->GetXSM())->SetBase(pdfChild));
+ break;
+ case STGTY_STREAM:
+ olChk(pdf->CreateStream(pud->GetCurrentName(), df, pud->GetLUID(),
+ pud->GetFlags() & ULF_TYPEFLAGS, &pstChild));
+ olChkTo(EH_Create,
+ ((CTransactedStream *)pud->GetXSM())->SetBase(pstChild));
+ break;
+ default:
+ olAssert(FALSE && aMsg("Unknown type in update list entry"));
+ break;
+ }
+ olDebugOut((DEB_ITRACE, "Out PDocFile::CreateFromUpdate\n"));
+ return S_OK;
+
+ EH_Create:
+ if ((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL)) == STGTY_STORAGE)
+ pdfChild->Release();
+ else
+ {
+ olAssert((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL)) ==
+ STGTY_STREAM);
+ pstChild->Release();
+ }
+ olVerSucc(pdf->DestroyEntry(pud->GetCurrentName(), TRUE));
+ EH_Err:
+ return sc;
+}
+#endif //!REF
+
+//+--------------------------------------------------------------
+//
+// Member: PDocFile::ExcludeEntries, public
+//
+// Synopsis: Excludes the given entries
+//
+// Arguments: [snbExclude] - Entries to exclude
+//
+// Returns: Appropriate status code
+//
+// History: 26-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_PDocFile_ExcludeEntries) //
+#endif
+
+SCODE PDocFile::ExcludeEntries(PDocFile *pdf,
+ SNBW snbExclude)
+{
+ PSStream *psstChild;
+ PDocFile *pdfChild;
+ SCODE sc;
+ CDfName dfnKey;
+ SIterBuffer ib;
+
+ olDebugOut((DEB_ITRACE, "In PDocFile::ExcludeEntries(%p)\n",
+ snbExclude));
+ for (;;)
+ {
+ if (FAILED(pdf->FindGreaterEntry(&dfnKey, &ib, NULL)))
+ break;
+ dfnKey.Set(&ib.dfnName);
+
+ if (NameInSNB(&ib.dfnName, snbExclude) == S_OK)
+ {
+ switch(REAL_STGTY(ib.type))
+ {
+ case STGTY_STORAGE:
+ olChkTo(EH_pwcsName, pdf->GetDocFile(&ib.dfnName, DF_READ |
+ DF_WRITE, ib.type,
+ &pdfChild));
+ olChkTo(EH_Get, pdfChild->DeleteContents());
+ pdfChild->Release();
+ break;
+ case STGTY_STREAM:
+ olChkTo(EH_pwcsName, pdf->GetStream(&ib.dfnName, DF_WRITE,
+ ib.type, &psstChild));
+ olChkTo(EH_Get, psstChild->SetSize(0));
+ psstChild->Release();
+ break;
+ }
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out ExcludeEntries\n"));
+ return S_OK;
+
+EH_Get:
+ if (REAL_STGTY(ib.type))
+ pdfChild->Release();
+ else
+ psstChild->Release();
+EH_pwcsName:
+ return sc;
+}
diff --git a/private/ole32/stg/docfile/publicdf.cxx b/private/ole32/stg/docfile/publicdf.cxx
new file mode 100644
index 000000000..705c347ef
--- /dev/null
+++ b/private/ole32/stg/docfile/publicdf.cxx
@@ -0,0 +1,1976 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: publicdf.cxx
+//
+// Contents: Public DocFile implementation
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+#include <time.h>
+#include <pbstream.hxx>
+#ifndef REF
+#include <tstream.hxx>
+#endif //!REF
+#include <sstream.hxx>
+#include <lock.hxx>
+
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::CPubDocFile, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [pdfParent] - Parent PubDocFile
+// [pdf] - DocFile basis
+// [df] - Permissions
+// [luid] - LUID
+// [pdfb] - Basis
+// [pdfn] - name
+// [cTransactedDepth] - Number of transacted parents
+// [pmsBase] - Base multistream
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_CPubDocFile) // Pubdf_Init_TEXT
+#endif
+
+CPubDocFile::CPubDocFile(CPubDocFile *pdfParent,
+ PDocFile *pdf,
+ DFLAGS const df,
+ DFLUID luid,
+#ifndef REF
+ CDFBasis *pdfb,
+#else
+ ILockBytes *pilbBase,
+#endif //!REF
+ CDfName const *pdfn,
+#ifndef REF
+ UINT cTransactedDepth,
+#endif //!REF
+ CMStream *pmsBase)
+{
+#ifndef REF
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::CPubDocFile("
+ "%p, %p, %X, %lu, %p, %p, %lu, %p)\n",
+ pdfParent, pdf, df, luid, pdfb, pdfn, cTransactedDepth,
+ pmsBase));
+#else
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::CPubDocFile("
+ "%p, %p, %X, %lu, %p, %p, %p)\n",
+ pdfParent, pdf, df, luid, pilbBase, pdfn, pmsBase));
+#endif //!REF
+ _pdfParent = P_TO_BP(CBasedPubDocFilePtr, pdfParent);
+ _pdf = P_TO_BP(CBasedDocFilePtr, pdf);
+ _df = df;
+ _luid = luid;
+#ifndef REF
+ _pdfb = P_TO_BP(CBasedDFBasisPtr, pdfb);
+ _cTransactedDepth = cTransactedDepth;
+#else
+ _pilbBase = pilbBase;
+#endif //!REF
+
+ _wFlags = 0;
+ _pmsBase = P_TO_BP(CBasedMStreamPtr, pmsBase);
+
+ _cReferences = 1;
+ if (pdfn)
+ {
+ _dfn.Set(pdfn->GetLength(), pdfn->GetBuffer());
+ }
+ else
+ {
+ _dfn.Set((WORD)0, (BYTE *)NULL);
+ }
+
+ if (!IsRoot())
+ _pdfParent->AddChild(this);
+
+ _sig = CPUBDOCFILE_SIG;
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::CPubDocFile\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::~CPubDocFile, public
+//
+// Synopsis: Destructor
+//
+// History: 23-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_vdtor) // Pubdf_Shutdown_TEXT
+#endif
+
+void CPubDocFile::vdtor(void)
+{
+ olAssert(_cReferences == 0);
+
+ _sig = CPUBDOCFILE_SIGDEL;
+
+ if (SUCCEEDED(CheckReverted()))
+ {
+#ifndef REF
+ ChangeXs(DF_NOLUID, XSO_RELEASE);
+#endif //!REF
+ olAssert(!IsRoot());
+ _pdfParent->ReleaseChild(this);
+
+ _cilChildren.DeleteByName(NULL);
+
+ if (_pdf)
+ _pdf->Release();
+ }
+#ifdef HACK_COORD
+ if (P_COORD(_df))
+ {
+ _pdfParent->vRelease();
+ }
+#endif
+ delete this;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::Release, public
+//
+// Synopsis: Releases resources for a CPubDocFile
+//
+// Returns: Appropriate status code
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_vRelease) // Pubdf_Release_TEXT
+#endif
+
+void CPubDocFile::vRelease(void)
+{
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::Release()\n"));
+
+ olAssert(_cReferences > 0);
+
+ if (_pdf && !P_TRANSACTED(_df) && SUCCEEDED(CheckReverted()))
+ {
+ TIME_T tm;
+
+#ifndef REF
+#ifdef ACCESSTIME
+ olVerSucc(DfGetTOD(&tm));
+ olVerSucc(_pdf->SetTime(WT_ACCESS, tm));
+#endif
+#endif //!REF
+
+#ifdef NEWPROPS
+ olVerSucc(FlushBufferedData(0));
+#endif
+ if (IsDirty())
+ {
+ olVerSucc(DfGetTOD(&tm));
+ olVerSucc(_pdf->SetTime(WT_MODIFICATION, tm));
+ if (!IsRoot())
+ _pdfParent->SetDirty();
+ else
+ {
+ msfAssert(P_WRITE(_df) &&
+ aMsg("Dirty & Direct but no write access"));
+ }
+ SetClean();
+ }
+ if (IsRoot() && P_WRITE(_df))
+ {
+ SCODE sc;
+ sc = _pmsBase->Flush(0);
+#if DBG == 1
+ if (FAILED(sc))
+ {
+ olDebugOut((DEB_ERROR,
+ "ILockBytes::Flush() failed in release path "
+ "with error %lx\n", sc));
+ }
+#endif
+ }
+ }
+
+ vDecRef();
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::Release()\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Method: CPubDocFile::CopyLStreamToLStream, private static
+//
+// Synopsis: Copies the contents of a stream to another stream
+//
+// Arguments: [plstFrom] - Stream to copy from
+// [plstTo] - Stream to copy to
+//
+// Returns: Appropriate status code
+//
+// History: 13-Sep-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_CopyLStreamToLStream) // Root_TEXT
+#endif
+
+SCODE CPubDocFile::CopyLStreamToLStream(ILockBytes *plstFrom,
+ ILockBytes *plstTo)
+{
+ BYTE *pbBuffer;
+ USHORT cbBuffer;
+ SCODE sc;
+ ULONG cbRead, cbWritten;
+ ULARGE_INTEGER cbPos;
+ STATSTG stat;
+
+ GetSafeBuffer(CB_SMALLBUFFER, CB_LARGEBUFFER, &pbBuffer, &cbBuffer);
+ olAssert((pbBuffer != NULL) && aMsg("Couldn't get scratch buffer"));
+
+ // Set destination size for contiguity
+ olHChk(plstFrom->Stat(&stat, STATFLAG_NONAME));
+ olHChk(plstTo->SetSize(stat.cbSize));
+
+ // Copy between streams
+ ULISet32(cbPos, 0);
+ for (;;)
+ {
+ olHChk(plstFrom->ReadAt(cbPos, pbBuffer, cbBuffer, &cbRead));
+ if (cbRead == 0) // EOF
+ break;
+ olHChk(plstTo->WriteAt(cbPos, pbBuffer, cbRead, &cbWritten));
+ if (cbRead != cbWritten)
+ olErr(EH_Err, STG_E_WRITEFAULT);
+ olAssert(0xFFFFFFFF-ULIGetLow(cbPos) > cbWritten);
+ ULISetLow(cbPos, ULIGetLow(cbPos)+cbWritten);
+ }
+ // Fall through
+ EH_Err:
+ FreeBuffer(pbBuffer);
+ return sc;
+}
+
+#ifndef REF
+//+-------------------------------------------------------------------------
+//
+// Method: CPubDocFile::PrepareForOverwrite, private
+//
+// Synopsis: Make sure that there is enough space to do a commit
+// when the overwrite flag has been specified.
+//
+// Arguments: None.
+//
+// Returns: S_OK if call completed OK.
+//
+// History: 08-Jul-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_PrepareForOverwrite)
+#endif
+
+SCODE CPubDocFile::PrepareForOverwrite(void)
+{
+ SCODE sc;
+ ULONG ulSize;
+ ULARGE_INTEGER ulNewSize;
+
+ olChk(GetCommitSize(&ulSize));
+
+ ULISet32(ulNewSize, ulSize);
+
+ if (P_INDEPENDENT(_df))
+ {
+ STATSTG statOrig;
+
+ olHChk(_pdfb->GetOriginal()->Stat(&statOrig, STATFLAG_NONAME));
+ olAssert(ULIGetHigh(statOrig.cbSize) == 0);
+
+ if (ULIGetLow(ulNewSize) > ULIGetLow(statOrig.cbSize))
+ {
+ olHChk(_pdfb->GetOriginal()->SetSize(ulNewSize));
+ }
+ }
+
+ sc = DfGetScode(_pmsBase->GetILB()->SetSize(ulNewSize));
+ // Fall through
+ EH_Err:
+ olDebugOut((DEB_ITRACE,"Out CPubDocFile::PrepareForOverwrite() =>"
+ "%lu\n", sc));
+ return sc;
+}
+#endif //!REF
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::GetCommitSize, public
+//
+// Synopsis: Get the total size needed to commit the current docfile
+// with overwrite permissions.
+//
+// Arguments: [pulSize] -- Return location for size
+//
+// Returns: Appropriate status code
+//
+// Algorithm: For each Transaction Set Member call GetCommitInfo()
+// 1) If Tset member is a Docfile, then GetCommitInfo
+// returns number of deleted entries and number of
+// newly created entries.
+// 2) If Tset member is a stream, GetCommitInfo returns
+// current size and size of base.
+// Determine the number of DirSectors needed to handle
+// newly created entries.
+// Determine number of data sectors needed to hold new
+// stream info.
+// Determine number of fat sectors needed to hold new
+// data and dir sectors.
+// Determine number of DI Fat sectors needed to hold new
+// fat sectors.
+// Add size of new sectors to the current size of the
+// base and return that value.
+//
+// History: 15-Jun-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_GetCommitSize)
+#endif
+
+SCODE CPubDocFile::GetCommitSize(ULONG *pulSize)
+{
+ SCODE sc;
+ PTSetMember *ptsm;
+ ULONG cDirEntries = 0;
+ ULONG cNewSectors = 0;
+ ULONG cMiniSectors = 0;
+ ULONG cMiniFatSectors;
+ ULONG cFatSectors = 0;
+ ULONG cFatLast;
+ ULONG cDIFatSectors = 0;
+
+ olDebugOut((DEB_ITRACE,"In CPubDocFile::PrepareForOverwrite()\n"));
+ //Bytes per sector
+ ULONG cbSect = _pmsBase->GetSectorSize();
+
+ if (!(_wFlags & PF_PREPARED))
+ {
+ //DirEntries per sector
+ ULONG cdsSect = cbSect / sizeof(CDirEntry);
+
+ //Fat entries per sector
+ ULONG cfsSect = cbSect / sizeof(SECT);
+
+ //Minisectors per sector
+ ULONG cmsSect = cbSect / MINISECTORSIZE;
+
+ ULONG ulRet1, ulRet2;
+ for (ptsm = _tss.GetHead(); ptsm; ptsm = ptsm->GetNext())
+ {
+ ptsm->GetCommitInfo(&ulRet1, &ulRet2);
+ switch(REAL_STGTY(ptsm->ObjectType()))
+ {
+ case STGTY_STORAGE:
+ if (ulRet2 < ulRet1)
+ {
+ cDirEntries += (ulRet1 - ulRet2);
+ }
+ break;
+ case STGTY_STREAM:
+ //If new size is larger than old...
+ if (ulRet2 > ulRet1)
+ {
+ if (ulRet2 < MINISTREAMSIZE)
+ {
+ cMiniSectors += ((ulRet2 + MINISECTORSIZE - 1)
+ / MINISECTORSIZE) -
+ ((ulRet1 + MINISECTORSIZE - 1)
+ / MINISECTORSIZE);
+ }
+ else
+ {
+ ULONG csectOld = (ulRet1 + cbSect - 1) / cbSect;
+ ULONG csectNew = (ulRet2 + cbSect - 1) / cbSect;
+
+ cNewSectors += (csectNew - csectOld);
+ }
+ }
+ break;
+ default:
+ olAssert(!aMsg("Unknown pstm object type"));
+ break;
+ }
+ }
+
+ cNewSectors += (cDirEntries + cdsSect - 1) / cdsSect;
+ cMiniFatSectors = ((cMiniSectors + cfsSect - 1) / cfsSect);
+
+ cNewSectors += cMiniFatSectors + ((cMiniSectors + cmsSect -1) / cmsSect);
+
+ do
+ {
+ cFatLast = cFatSectors;
+
+ cFatSectors = (cNewSectors + cDIFatSectors + cFatSectors + cbSect - 1)
+ / cbSect;
+
+ cDIFatSectors = (cFatSectors + cfsSect - 1) / cfsSect;
+
+ }
+ while (cFatLast != cFatSectors);
+
+ cNewSectors += cFatSectors + cDIFatSectors;
+
+ }
+
+ STATSTG stat;
+ olHChk(_pmsBase->GetILB()->Stat(&stat, STATFLAG_NONAME));
+
+ *pulSize = ULIGetLow(stat.cbSize) + cNewSectors * cbSect;
+
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::Commit, public
+//
+// Synopsis: Commits transacted changes
+//
+// Arguments: [dwFlags] - DFC_*
+//
+// Returns: Appropriate status code
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_Commit) // Pubdf_Commit_TEXT
+#endif
+
+SCODE CPubDocFile::Commit(DWORD const dwFlags)
+{
+ SCODE sc;
+#ifndef COORD
+ TIME_T tm;
+#ifndef REF
+ PTSetMember *ptsm;
+ ULONG ulLock = 0;
+ DFSIGNATURE sigMSF;
+#endif //!REF
+
+ BOOL fFlush = FLUSH_CACHE(dwFlags);
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::Commit:%p(%lX)\n",
+ this, dwFlags));
+
+ olChk(CheckReverted());
+ if (!P_WRITE(_df))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ if (IsDirty())
+ {
+ olChk(DfGetTOD(&tm));
+ olChk(_pdf->SetTime(WT_MODIFICATION, tm));
+ }
+
+#ifdef USE_NOSNAPSHOT
+ if (P_NOSNAPSHOT(_df) && (dwFlags & STGC_OVERWRITE))
+ {
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ }
+#endif
+
+#ifndef REF
+#ifdef ACCESSTIME
+ olChk(DfGetTOD(&tm));
+ olChk(_pdf->SetTime(WT_ACCESS, tm));
+#endif
+#endif //!REF
+
+#ifdef NEWPROPS
+ olChk(FlushBufferedData(0));
+#endif
+
+#ifndef REF
+ if (!P_TRANSACTED(_df))
+ {
+#endif //!REF
+ if (IsDirty())
+ {
+ if (!IsRoot())
+ _pdfParent->SetDirty();
+ SetClean();
+ }
+
+ if (_cTransactedDepth == 0)
+ {
+ // Direct all the way
+ olChk(_pmsBase->Flush(fFlush));
+ }
+ return S_OK;
+#ifndef REF
+ }
+
+ olAssert(GetTransactedDepth() > 0 &&
+ aMsg("Transaction depth/flags conflict"));
+
+ if (GetTransactedDepth() == 1)
+ {
+ // A transacted depth of 1 means this is the lowest transacted
+ // level and committed changes will go into the real file,
+ // so do all the special contents protection and locking
+
+ if (_pdfb->GetOrigLockFlags() & LOCK_ONLYONCE)
+ olChk(WaitForAccess(_pdfb->GetOriginal(), DF_WRITE,
+ &ulLock));
+
+ olChkTo(EH_GetAccess, _pmsBase->BeginCopyOnWrite(dwFlags));
+
+ if (dwFlags & STGC_OVERWRITE)
+ {
+ olChkTo(EH_COW, PrepareForOverwrite());
+ }
+
+ if (P_INDEPENDENT(_df))
+ {
+ if (_sigMSF == DF_INVALIDSIGNATURE)
+ {
+ if ((dwFlags & STGC_ONLYIFCURRENT) &&
+ DllIsMultiStream(_pdfb->GetOriginal()) == S_OK)
+ olErr(EH_COW, STG_E_NOTCURRENT);
+ }
+ else
+ {
+ olChkTo(EH_COW, DllGetCommitSig(_pdfb->GetOriginal(),
+ &sigMSF));
+ if (dwFlags & STGC_ONLYIFCURRENT)
+ if (sigMSF != _sigMSF)
+ olErr(EH_COW, STG_E_NOTCURRENT);
+ }
+ }
+ }
+
+ for (ptsm = _tss.GetHead(); ptsm; ptsm = ptsm->GetNext())
+ if ((ptsm->GetFlags() & XSM_DELETED) == 0)
+ olChkTo(EH_NoCommit, ptsm->BeginCommit(dwFlags));
+
+ // 10/02/92 - To handle low disk space situations well, we
+ // preallocate the space we'll need to copy (when independent).
+
+ STATSTG statBase, statOrig;
+
+ if (P_INDEPENDENT(_df))
+ {
+ // With DELAYFLUSH we can't be sure of the size
+ // of the file until EndCopyOnWrite, but we do
+ // know that the file won't grow so this is safe
+
+ olHChkTo(EH_NoCommit, _pdfb->GetBase()->Stat(&statBase,
+ STATFLAG_NONAME));
+ olAssert(ULIGetHigh(statBase.cbSize) == 0);
+
+ olHChkTo(EH_NoCommit, _pdfb->GetOriginal()->Stat(&statOrig,
+ STATFLAG_NONAME));
+ olAssert(ULIGetHigh(statOrig.cbSize) == 0);
+
+ if (ULIGetLow(statBase.cbSize) > ULIGetLow(statOrig.cbSize))
+ {
+ olHChkTo(EH_NoCommit,
+ _pdfb->GetOriginal()->SetSize(statBase.cbSize));
+ }
+ }
+
+ //End of phase 1 of commit.
+
+ if (GetTransactedDepth() == 1)
+ {
+ olChkTo(EH_ResetSize,
+ _pmsBase->EndCopyOnWrite(dwFlags, DF_COMMIT));
+ }
+
+ // Move to end of list
+ for (ptsm = _tss.GetHead();
+ ptsm && ptsm->GetNext();
+ ptsm = ptsm->GetNext())
+ NULL;
+ // End commits in reverse
+ for (; ptsm; ptsm = ptsm->GetPrev())
+ ptsm->EndCommit(DF_COMMIT);
+
+ if (P_INDEPENDENT(_df))
+ {
+ // Not robust, but we made sure we had enough
+ // disk space by presetting the larger size
+ // There is no practical way of making this robust
+ // and we have never guaranteed behavior in the face
+ // of disk errors, so this is good enough
+
+ olVerSucc(CopyLStreamToLStream(_pdfb->GetBase(),
+ _pdfb->GetOriginal()));
+ olVerSucc(_pdfb->GetOriginal()->Flush());
+
+ if (_sigMSF == DF_INVALIDSIGNATURE)
+ {
+ olVerSucc(DllGetCommitSig(_pdfb->GetOriginal(), &_sigMSF));
+ }
+ else
+ {
+ _sigMSF = sigMSF+1;
+ olVerSucc(DllSetCommitSig(_pdfb->GetOriginal(), _sigMSF));
+ }
+ }
+
+ if (ulLock != 0)
+ ReleaseAccess(_pdfb->GetOriginal(), DF_WRITE, ulLock);
+
+ // Dirty all parents up to the next transacted storage
+ if (IsDirty())
+ {
+ if (!IsRoot())
+ _pdfParent->SetDirty();
+ SetClean();
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CTransactionLevel::Commit\n"));
+#if DBG == 1
+ VerifyXSMemberBases();
+#endif
+ _wFlags = (_wFlags & ~PF_PREPARED);
+
+ return S_OK;
+
+EH_ResetSize:
+ if (P_INDEPENDENT(_df) &&
+ (ULIGetLow(statBase.cbSize) > ULIGetLow(statOrig.cbSize)))
+ {
+ _pdfb->GetOriginal()->SetSize(statOrig.cbSize);
+ }
+EH_NoCommit:
+ // Move to end of list
+ for (ptsm = _tss.GetHead();
+ ptsm && ptsm->GetNext();
+ ptsm = ptsm->GetNext())
+ NULL;
+ // Abort commits in reverse
+ for (; ptsm; ptsm = ptsm->GetPrev())
+ ptsm->EndCommit(DF_ABORT);
+EH_COW:
+ if (GetTransactedDepth() == 1)
+ {
+ olVerSucc(_pmsBase->EndCopyOnWrite(dwFlags, DF_ABORT));
+ }
+EH_GetAccess:
+ if (ulLock != 0)
+ ReleaseAccess(_pdfb->GetOriginal(), DF_WRITE, ulLock);
+#endif //!REF
+EH_Err:
+ return sc;
+
+#else //COORD
+ ULONG ulLock = 0;
+ DFSIGNATURE sigMSF;
+ ULONG cbSizeBase;
+ ULONG cbSizeOrig;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::Commit:%p(%lX)\n",
+ this, dwFlags));
+
+ sc = CommitPhase1(dwFlags, &ulLock, &sigMSF, &cbSizeBase, &cbSizeOrig);
+
+ //Only do phase 2 if we're transacted and phase 1 succeeded.
+ if (P_TRANSACTED(_df) && SUCCEEDED(sc))
+ {
+ sc = CommitPhase2(dwFlags,
+ TRUE,
+ ulLock,
+ sigMSF,
+ cbSizeBase,
+ cbSizeOrig);
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::Commit -> %lX\n", sc));
+
+ return sc;
+#endif //!COORD
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::DestroyEntry, public
+//
+// Synopsis: Permanently deletes an element of a DocFile
+//
+// Arguments: [pdfnName] - Name of element
+// [fClean] - Whether this was invoked as cleanup or not
+//
+// Returns: Appropriate status code
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_DestroyEntry) // Pubdf_Destroy_TEXT
+#endif
+
+SCODE CPubDocFile::DestroyEntry(CDfName const *pdfnName,
+ BOOL fClean)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::DestroyEntry:%p(%ws, %d)\n",
+ this, pdfnName, fClean));
+ olChk(CheckReverted());
+ if (!P_TRANSACTED(_df) && !P_WRITE(_df))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ olChk(_pdf->DestroyEntry(pdfnName, fClean));
+ _cilChildren.DeleteByName(pdfnName);
+ SetDirty();
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::DestroyEntry\n"));
+ // Fall through
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::RenameEntry, public
+//
+// Synopsis: Renames an element of a DocFile
+//
+// Arguments: [pdfnName] - Current name
+// [pdfnNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// History: 20-Jan-92 DrewB Created
+// 28-Oct-92 AlexT Add names to XSM's
+// 09-Aug-93 AlexT Disallow renames of open children
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_RenameEntry) // Pubdf_Rename_TEXT
+#endif
+
+SCODE CPubDocFile::RenameEntry(CDfName const *pdfnName,
+ CDfName const *pdfnNewName)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::RenameEntry(%ws, %ws)\n",
+ pdfnName, pdfnNewName));
+ olChk(CheckReverted());
+ if (FAILED(_cilChildren.IsDenied(pdfnName, DF_WRITE | DF_DENYALL, _df)))
+ {
+ // Translate all denial errors to STG_E_ACCESSDENIED
+ sc = STG_E_ACCESSDENIED;
+ }
+ else
+ {
+ sc = _pdf->RenameEntry(pdfnName, pdfnNewName);
+
+ if (SUCCEEDED(sc))
+ {
+ SetDirty();
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::RenameEntry\n"));
+ // Fall through
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::CreateDocFile, public
+//
+// Synopsis: Creates an embedded DocFile
+//
+// Arguments: [pdfnName] - Name
+// [df] - Permissions
+// [ppdfDocFile] - New DocFile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdfDocFile]
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_CreateDocFile) // Pubdf_Create_TEXT
+#endif
+
+SCODE CPubDocFile::CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubDocFile **ppdfDocFile)
+{
+ PDocFile *pdf;
+ SCODE sc;
+#ifndef REF
+ CWrappedDocFile *pdfWrapped = NULL;
+#endif //!REF
+ SEntryBuffer eb;
+#ifndef REF
+ UINT cNewTDepth;
+#endif //!REF
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::CreateDocFile:%p("
+ "%ws, %X, %p)\n", this, pdfnName, df, ppdfDocFile));
+
+ olChk(CheckReverted());
+#ifndef REF
+ if (!P_TRANSACTED(_df) && !P_WRITE(_df))
+#else
+ if (!P_WRITE(_df))
+#endif //!REF
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ olChk(_cilChildren.IsDenied(pdfnName, df, _df));
+
+#ifndef REF
+ olChk(CDocFile::Reserve(1, BP_TO_P(CDFBasis *, _pdfb)));
+ cNewTDepth = _cTransactedDepth+(P_TRANSACTED(df) ? 1 : 0);
+ olChkTo(EH_DirectReserve,
+ CWrappedDocFile::Reserve(cNewTDepth, BP_TO_P(CDFBasis *, _pdfb)));
+#endif //!REF
+
+ olChkTo(EH_Reserve, _pdf->CreateDocFile(pdfnName, df, DF_NOLUID,
+ &pdf));
+
+ // As soon as we have a base we dirty ourself (in case
+ // we get an error later) so that we'll flush properly.
+ SetDirty();
+
+ eb.luid = pdf->GetLuid();
+ olAssert(eb.luid != DF_NOLUID && aMsg("DocFile id is DF_NOLUID!"));
+#ifndef REF
+ olMemTo(EH_pdf,
+ *ppdfDocFile = new (_pmsBase->GetMalloc())
+ CPubDocFile(this, pdf, df, eb.luid,
+ BP_TO_P(CDFBasis *, _pdfb),
+ pdfnName, cNewTDepth,
+ BP_TO_P(CMStream *, _pmsBase)));
+#else
+ olMemTo(EH_pdf,
+ *ppdfDocFile = new (_pmsBase->GetMalloc())
+ CPubDocFile(this, pdf, df, eb.luid,
+ _pilbBase, pdfnName, _pmsBase));
+#endif //!REF
+
+#ifndef REF
+ if (P_TRANSACTED(df))
+ {
+ pdfWrapped = new(BP_TO_P(CDFBasis *, _pdfb))
+ CWrappedDocFile(pdfnName, eb.luid, df,
+ BP_TO_P(CDFBasis *, _pdfb), *ppdfDocFile);
+ olAssert(pdfWrapped != NULL && aMsg("Reserved DocFile not found"));
+ olChkTo(EH_pdfWrapped,
+ pdfWrapped->Init(pdf));
+ (*ppdfDocFile)->AddXSMember(NULL, pdfWrapped, eb.luid);
+ (*ppdfDocFile)->SetDF(pdfWrapped);
+ }
+#endif //!REF
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::CreateDocFile\n"));
+ return S_OK;
+
+#ifndef REF
+ EH_pdfWrapped:
+ delete pdfWrapped;
+ (*ppdfDocFile)->vRelease();
+ goto EH_Destroy;
+#endif //!REF
+ EH_pdf:
+ pdf->Release();
+#ifndef REF
+ if (P_TRANSACTED(df))
+ CWrappedDocFile::Unreserve(1, BP_TO_P(CDFBasis *, _pdfb));
+ EH_Destroy:
+#endif //!REF
+ olVerSucc(_pdf->DestroyEntry(pdfnName, TRUE));
+ return sc;
+ EH_Reserve:
+#ifndef REF
+ CWrappedDocFile::Unreserve(cNewTDepth, BP_TO_P(CDFBasis *, _pdfb));
+ EH_DirectReserve:
+ CDocFile::Unreserve(1, BP_TO_P(CDFBasis *, _pdfb));
+#endif //!REF
+ EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::GetDocFile, public
+//
+// Synopsis: Gets an existing embedded DocFile
+//
+// Arguments: [pdfnName] - Name
+// [df] - Permissions
+// [ppdfDocFile] - DocFile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdfDocFile]
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_GetDocFile) // Pubdf_Open_TEXT
+#endif
+
+SCODE CPubDocFile::GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubDocFile **ppdfDocFile)
+{
+ PDocFile *pdf;
+ SCODE sc;
+#ifndef REF
+ CWrappedDocFile *pdfWrapped;
+#endif //!REF
+ SEntryBuffer eb;
+#ifndef REF
+ UINT cNewTDepth;
+#endif //!REF
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::GetDocFile:%p("
+ "%ws, %X, %p)\n",
+ this, pdfnName, df, ppdfDocFile));
+
+ olChk(CheckReverted());
+ if (!P_READ(_df))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ // Check to see if an instance with DENY_* exists
+ olChk(_cilChildren.IsDenied(pdfnName, df, _df));
+
+ olChk(_pdf->GetDocFile(pdfnName, df, &pdf));
+
+ eb.luid = pdf->GetLuid();
+ olAssert(eb.luid != DF_NOLUID && aMsg("DocFile id is DF_NOLUID!"));
+#ifndef REF
+ cNewTDepth = _cTransactedDepth+(P_TRANSACTED(df) ? 1 : 0);
+#endif //!REF
+#ifndef REF
+ olMemTo(EH_pdf,
+ *ppdfDocFile = new (_pmsBase->GetMalloc())
+ CPubDocFile(this, pdf, df, eb.luid,
+ BP_TO_P(CDFBasis *, _pdfb),
+ pdfnName, cNewTDepth,
+ BP_TO_P(CMStream *, _pmsBase)));
+#else
+ olMemTo(EH_pdf,
+ *ppdfDocFile = new (_pmsBase->GetMalloc())
+ CPubDocFile(this, pdf, df, eb.luid,
+ _pilbBase, pdfnName, _pmsBase));
+#endif //!REF
+
+#ifndef REF
+ if (P_TRANSACTED(df))
+ {
+ olMemTo(EH_ppdf, pdfWrapped = new(_pmsBase->GetMalloc())
+ CWrappedDocFile(pdfnName, eb.luid, df,
+ BP_TO_P(CDFBasis *, _pdfb), *ppdfDocFile));
+ olChkTo(EH_pdfWrapped,
+ pdfWrapped->Init(pdf));
+ (*ppdfDocFile)->AddXSMember(NULL, pdfWrapped, eb.luid);
+ (*ppdfDocFile)->SetDF(pdfWrapped);
+ }
+#endif //!REF
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::GetDocFile\n"));
+ return S_OK;
+
+#ifndef REF
+EH_pdfWrapped:
+ delete pdfWrapped;
+EH_ppdf:
+#endif //!REF
+ (*ppdfDocFile)->vRelease();
+ return sc;
+EH_pdf:
+ pdf->Release();
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::CreateStream, public
+//
+// Synopsis: Creates a stream
+//
+// Arguments: [pdfnName] - Name
+// [df] - Permissions
+// [ppdstStream] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdstStream]
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_CreateStream) // Pubdf_Create_TEXT
+#endif
+
+SCODE CPubDocFile::CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubStream **ppdstStream)
+{
+ PSStream *psst;
+ SCODE sc;
+ SEntryBuffer eb;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::CreateStream:%p("
+ "%ws, %X, %p)\n", this, pdfnName, df, ppdstStream));
+
+ olChk(CheckReverted());
+#ifndef REF
+ if (!P_TRANSACTED(_df) && !P_WRITE(_df))
+#else
+ if (!P_WRITE(_df))
+#endif //!REF
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ olChk(_cilChildren.IsDenied(pdfnName, df, _df));
+
+#ifndef REF
+ olChk(CDirectStream::Reserve(1, BP_TO_P(CDFBasis *, _pdfb)));
+ olChkTo(EH_DirectReserve,
+ CTransactedStream::Reserve(_cTransactedDepth,
+ BP_TO_P(CDFBasis *, _pdfb)));
+#endif //!REF
+ olChkTo(EH_Reserve,
+ _pdf->CreateStream(pdfnName, df, DF_NOLUID, &psst));
+
+ // As soon as we have a base we dirty ourself (in case
+ // we get an error later) so that we'll flush properly.
+ SetDirty();
+
+ eb.luid = psst->GetLuid();
+ olAssert(eb.luid != DF_NOLUID && aMsg("Stream id is DF_NOLUID!"));
+
+ olMemTo(EH_Create, *ppdstStream = new (_pmsBase->GetMalloc())
+ CPubStream(this, df, pdfnName));
+ (*ppdstStream)->Init(psst, eb.luid);
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::CreateStream\n"));
+ return S_OK;
+
+ EH_Create:
+ psst->Release();
+ olVerSucc(_pdf->DestroyEntry(pdfnName, TRUE));
+ return sc;
+ EH_Reserve:
+#ifndef REF
+ CTransactedStream::Unreserve(_cTransactedDepth,
+ BP_TO_P(CDFBasis *, _pdfb));
+ EH_DirectReserve:
+ CDirectStream::Unreserve(1, BP_TO_P(CDFBasis *, _pdfb));
+#endif //!REF
+ EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::GetStream, public
+//
+// Synopsis: Gets an existing stream
+//
+// Arguments: [pdfnName] - Name
+// [df] - Permissions
+// [ppdstStream] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdstStream]
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_GetStream) // Pubdf_Open_TEXT
+#endif
+
+SCODE CPubDocFile::GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubStream **ppdstStream)
+{
+ PSStream *psst;
+ SCODE sc;
+ SEntryBuffer eb;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::GetStream(%ws, %X, %p)\n",
+ pdfnName, df, ppdstStream));
+
+ olChk(CheckReverted());
+ if (!P_READ(_df))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ // Check permissions
+ olChk(_cilChildren.IsDenied(pdfnName, df, _df));
+
+ olChk(_pdf->GetStream(pdfnName, df, &psst));
+
+ eb.luid = psst->GetLuid();
+ olAssert(eb.luid != DF_NOLUID && aMsg("Stream id is DF_NOLUID!"));
+
+ olMemTo(EH_Get, *ppdstStream = new (_pmsBase->GetMalloc())
+ CPubStream(this, df, pdfnName));
+
+
+ (*ppdstStream)->Init(psst, eb.luid);
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::GetStream\n"));
+ return S_OK;
+
+EH_Get:
+ psst->Release();
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::Stat, public
+//
+// Synopsis: Fills in a stat buffer
+//
+// Arguments: [pstatstg] - Buffer
+// [grfStatFlag] - Stat flags
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 24-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_Stat) // Stat_TEXT
+#endif
+
+SCODE CPubDocFile::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::Stat(%p, %lu)\n",
+ pstatstg, grfStatFlag));
+ olAssert(SUCCEEDED(VerifyStatFlag(grfStatFlag)));
+ olChk(CheckReverted());
+
+ pstatstg->pwcsName = NULL;
+ if ((grfStatFlag & STATFLAG_NONAME) == 0)
+ {
+#ifdef COORD
+ if (P_COORD(_df))
+ {
+ olHChk(_pdfb->GetOriginal()->Stat((STATSTG *)pstatstg,
+ grfStatFlag));
+ }
+ else
+#endif
+ {
+ olMem(pstatstg->pwcsName =
+ (WCHAR *)TaskMemAlloc(_dfn.GetLength()));
+ memcpy(pstatstg->pwcsName, _dfn.GetBuffer(), _dfn.GetLength());
+ }
+ }
+
+ olChk(_pdf->GetTime(WT_CREATION, &pstatstg->ctime));
+ olChk(_pdf->GetTime(WT_MODIFICATION, &pstatstg->mtime));
+ pstatstg->atime.dwLowDateTime = pstatstg->atime.dwHighDateTime = 0;
+ olChk(_pdf->GetClass(&pstatstg->clsid));
+ olChk(_pdf->GetStateBits(&pstatstg->grfStateBits));
+ olAssert(!IsRoot());
+
+
+ pstatstg->grfMode = DFlagsToMode(_df);
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::Stat\n"));
+ // Fall through
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::RevertFromAbove, public
+//
+// Synopsis: Parent has asked for reversion
+//
+// History: 29-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_RevertFromAbove) // Pubdf_Revert_TEXT
+#endif
+
+void CPubDocFile::RevertFromAbove(void)
+{
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::RevertFromAbove:%p()\n", this));
+ _df |= DF_REVERTED;
+
+ _cilChildren.DeleteByName(NULL);
+
+#ifndef REF
+ ChangeXs(DF_NOLUID, XSO_RELEASE);
+#endif //!REF
+ _pdf->Release();
+ _pdf = NULL;
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::RevertFromAbove\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::FlushBufferedData, public
+//
+// Synopsis: Flush buffered data in any child streams.
+//
+// History: 5-May-1995 BillMo Created
+//
+//---------------------------------------------------------------
+
+#ifdef NEWPROPS
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_RevertFromAbove) // Pubdf_Revert_TEXT
+#endif
+
+SCODE CPubDocFile::FlushBufferedData(int recursionlevel)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::FlushBufferedData:%p()\n", this));
+
+ if ((recursionlevel == 0 && (_df & DF_TRANSACTED)) ||
+ (_df & DF_TRANSACTED) == 0)
+ {
+ sc = _cilChildren.FlushBufferedData(recursionlevel);
+ }
+ else
+ {
+ sc = S_OK;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::FlushBufferedData\n"));
+
+ return sc;
+}
+#endif
+
+#ifndef REF
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::ChangeXs, public
+//
+// Synopsis: Performs an operation on the XS
+//
+// Arguments: [luidTree] - LUID of tree or DF_NOLUID
+// [dwOp] - Operation
+//
+// History: 30-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_ChangeXs) //
+#endif
+
+void CPubDocFile::ChangeXs(DFLUID const luidTree,
+ DWORD const dwOp)
+{
+ olAssert((dwOp == XSO_RELEASE) || (dwOp == XSO_REVERT));
+
+ PTSetMember *ptsmNext, *ptsmCur, *ptsmPrev;
+
+ for (ptsmNext = _tss.GetHead(); ptsmNext; )
+ {
+ ptsmCur = ptsmNext;
+ ptsmNext = ptsmCur->GetNext();
+ olAssert ((ptsmCur->GetName() != ptsmCur->GetTree()));
+
+ if (luidTree == DF_NOLUID || ptsmCur->GetName() == luidTree)
+ {
+ switch(dwOp)
+ {
+ case XSO_RELEASE:
+ ptsmPrev = ptsmCur->GetPrev();
+ _tss.RemoveMember(ptsmCur);
+ ptsmCur->Release();
+ if (ptsmPrev == NULL)
+ ptsmNext = _tss.GetHead();
+ else
+ ptsmNext = ptsmPrev->GetNext();
+ break;
+ case XSO_REVERT:
+ ptsmCur->Revert();
+ // Revert might have changed the next pointer
+ ptsmNext = ptsmCur->GetNext();
+ break;
+ }
+ }
+ else if (luidTree != DF_NOLUID && luidTree == ptsmCur->GetTree())
+ {
+// This weirdness is necessary because ptsm will be
+// deleted by the call to ChangeXs. Since ptsm->GetNext()
+// could also be deleted, we would have no way to continue.
+// ptsm->GetPrev() will never be deleted by the call to
+// ChangeXs, since all children of a node appear _after_
+// that node in the list. Therefore, ptsm->GetPrev()->GetNext()
+// is the best place to resume the loop.
+
+ ptsmPrev = ptsmCur->GetPrev();
+
+ ChangeXs(ptsmCur->GetName(), dwOp);
+ if (ptsmPrev == NULL)
+ ptsmNext = _tss.GetHead();
+ else
+ ptsmNext = ptsmPrev->GetNext();
+ }
+ }
+
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::AddXSMember, public
+//
+// Synopsis: Adds an object to the XS
+//
+// Arguments: [ptsmRequestor] - Object requesting add or NULL if
+// first addition
+// [ptsmAdd] - Object to add
+// [luid] - LUID of object
+//
+// History: 29-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_AddXSMember)
+#endif
+
+void CPubDocFile::AddXSMember(PTSetMember *ptsmRequestor,
+ PTSetMember *ptsmAdd,
+ DFLUID luid)
+{
+ DFLUID luidTree;
+ ULONG ulLevel;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::AddXSMember:%p("
+ "%p, %p, %ld)\n", this, ptsmRequestor, ptsmAdd, luid));
+ if (ptsmRequestor == NULL)
+ {
+ // If we're starting the XS, this is a new TL and we have
+ // no tree
+ luidTree = DF_NOLUID;
+ ulLevel = 0;
+ }
+ else
+ {
+ // We're creating a subobject so it goes in the parent's tree
+ luidTree = ptsmRequestor->GetName();
+ ulLevel = ptsmRequestor->GetLevel()+1;
+ }
+ ptsmAdd->SetXsInfo(luidTree, luid, ulLevel);
+ InsertXSMember(ptsmAdd);
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::AddXSMember\n"));
+}
+
+#if DBG == 1
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::VerifyXSMemberBases,public
+//
+// Synopsis: Verify that all XS members have valid bases
+//
+// History: 15-Sep-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+void CPubDocFile::VerifyXSMemberBases()
+{
+ PTSetMember *ptsm;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::VerifyXSMemberBases\n"));
+ for (ptsm = _tss.GetHead(); ptsm; ptsm = ptsm->GetNext())
+ {
+ DWORD otype = REAL_STGTY(ptsm->ObjectType());
+ olAssert(otype == STGTY_STORAGE || otype == STGTY_STREAM);
+ if (otype == STGTY_STORAGE)
+ {
+ CWrappedDocFile *pdf = (CWrappedDocFile *) ptsm;
+ olAssert(pdf->GetBase() != NULL);
+ }
+ else
+ {
+ CTransactedStream *pstm = (CTransactedStream *) ptsm;
+ olAssert(pstm->GetBase() != NULL);
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::VerifyXSMemberBases\n"));
+}
+
+#endif
+#endif //!REF
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::SetElementTimes, public
+//
+// Synopsis: Sets the times for an element
+//
+// Arguments: [pdfnName] - Name
+// [pctime] - Create time
+// [patime] - Access time
+// [pmtime] - Modify time
+//
+// Returns: Appropriate status code
+//
+// History: 10-Nov-92 DrewB Created
+// 06-Sep-95 MikeHill Added call to CMStream::MaintainFLBModifyTimestamp().
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_SetElementTimes)
+#endif
+
+SCODE CPubDocFile::SetElementTimes(CDfName const *pdfnName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ SCODE sc;
+ PDocFile *pdf;
+#ifndef REF
+ PTSetMember *ptsm = NULL;
+#endif //!REF
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::SetElementTimes:%p("
+ "%ws, %p, %p, %p)\n", this, pdfnName, pctime,
+ patime, pmtime));
+ olChk(CheckReverted());
+ if (pdfnName != NULL)
+ {
+#ifndef REF
+ if ((!P_TRANSACTED(_df) && !P_WRITE(_df)) ||
+#else
+ if ((!P_WRITE(_df)) ||
+#endif //!REF
+ _cilChildren.FindByName(pdfnName) != NULL)
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+ }
+
+#ifndef REF
+ if (pdfnName == NULL)
+ {
+ //Set pdf to the transacted self object.
+ pdf = BP_TO_P(PDocFile *, _pdf);
+ }
+ else if ((ptsm = FindXSMember(pdfnName, _luid)) != NULL)
+ {
+ if (ptsm->ObjectType() != STGTY_STORAGE)
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+ pdf = (CWrappedDocFile *)ptsm;
+ }
+ else
+#endif //!REF
+
+ olChk(_pdf->GetDocFile(pdfnName, DF_WRITE, &pdf));
+
+
+ if (pctime)
+ {
+ olChkTo(EH_pdf, pdf->SetTime(WT_CREATION, *pctime));
+ }
+ if (pmtime)
+ {
+ olChkTo(EH_pdf, pdf->SetTime(WT_MODIFICATION, *pmtime));
+
+ // If we've explicitely set the modify timestamp on a root Storage,
+ // we must tell CMStream to maintain that timestamp manually from here on
+ // out.
+
+ if( IsRoot() // This is the root Storage
+ &&
+ ( !pdfnName ) // I.e., we're not setting a child's timestamp.
+ )
+ _pmsBase->MaintainFLBModifyTimestamp();
+ }
+ if (patime)
+ {
+ olChkTo(EH_pdf, pdf->SetTime(WT_ACCESS, *patime));
+ }
+
+ if (pdfnName != NULL)
+ SetDirty();
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::SetElementTimes\n"));
+ // Fall through
+ EH_pdf:
+#ifndef REF
+ if ((ptsm == NULL) && (pdfnName != NULL))
+#endif //!REF
+ pdf->Release();
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::SetClass, public
+//
+// Synopsis: Sets the class ID
+//
+// Arguments: [clsid] - Class ID
+//
+// Returns: Appropriate status code
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_SetClass)
+#endif
+
+SCODE CPubDocFile::SetClass(REFCLSID clsid)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::SetClass:%p(?)\n", this));
+ olChk(CheckReverted());
+#ifndef REF
+ if (!P_TRANSACTED(_df) && !P_WRITE(_df))
+#else
+ if (!P_WRITE(_df))
+#endif //!REF
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ sc = _pdf->SetClass(clsid);
+
+ SetDirty();
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::SetClass\n"));
+ // Fall through
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::SetStateBits, public
+//
+// Synopsis: Sets the state bits
+//
+// Arguments: [grfStateBits] - State bits
+// [grfMask] - Mask
+//
+// Returns: Appropriate status code
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_SetStateBits)
+#endif
+
+SCODE CPubDocFile::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::SetStateBits:%p(%lu, %lu)\n",
+ this, grfStateBits, grfMask));
+ olChk(CheckReverted());
+#ifndef REF
+ if (!P_TRANSACTED(_df) && !P_WRITE(_df))
+#else
+ if (!P_WRITE(_df))
+#endif //!REF
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ sc = _pdf->SetStateBits(grfStateBits, grfMask);
+
+ SetDirty();
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::SetStateBits\n"));
+ // Fall through
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::Validate, public static
+//
+// Synopsis: Validates a possibly invalid public docfile pointer
+//
+// Arguments: [pdf] - Memory to check
+//
+// Returns: Appropriate status code
+//
+// History: 26-Mar-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_Validate)
+#endif
+
+SCODE CPubDocFile::Validate(CPubDocFile *pdf)
+{
+ if (FAILED(ValidateBuffer(pdf, sizeof(CPubDocFile))) ||
+ pdf->_sig != CPUBDOCFILE_SIG)
+ {
+ return STG_E_INVALIDHANDLE;
+ }
+ return S_OK;
+}
+
+
+
+#ifdef COORD
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::CommitPhase1, public
+//
+// Synopsis: Do phase 1 of the commit sequence
+//
+// Arguments: [dwFlags] -- Commit flags
+//
+// Returns: Appropriate status code
+//
+// History: 07-Aug-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CPubDocFile::CommitPhase1(DWORD const dwFlags,
+ ULONG *pulLock,
+ DFSIGNATURE *psigMSF,
+ ULONG *pcbSizeBase,
+ ULONG *pcbSizeOrig)
+{
+ SCODE sc;
+ TIME_T tm;
+#ifndef REF
+ PTSetMember *ptsm;
+ ULONG ulLock = 0;
+ DFSIGNATURE sigMSF;
+#endif //!REF
+
+ BOOL fFlush = FLUSH_CACHE(dwFlags);
+
+ olChk(CheckReverted());
+ if (!P_WRITE(_df))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ if (IsDirty())
+ {
+ olChk(DfGetTOD(&tm));
+ olChk(_pdf->SetTime(WT_MODIFICATION, tm));
+ }
+
+
+#ifndef REF
+#ifdef ACCESSTIME
+ olChk(DfGetTOD(&tm));
+ olChk(_pdf->SetTime(WT_ACCESS, tm));
+#endif
+#endif //!REF
+
+#ifndef REF
+ if (!P_TRANSACTED(_df))
+ {
+#endif //!REF
+ if (IsDirty())
+ {
+ if (!IsRoot())
+ _pdfParent->SetDirty();
+ SetClean();
+ }
+
+ if (_cTransactedDepth == 0)
+ {
+ // Direct all the way
+ olChk(_pmsBase->Flush(fFlush));
+ }
+ return S_OK;
+#ifndef REF
+ }
+
+ olAssert(GetTransactedDepth() > 0 &&
+ aMsg("Transaction depth/flags conflict"));
+
+ if (GetTransactedDepth() == 1)
+ {
+ // A transacted depth of 1 means this is the lowest transacted
+ // level and committed changes will go into the real file,
+ // so do all the special contents protection and locking
+
+ olChk(_pmsBase->BeginCopyOnWrite(dwFlags));
+
+ if (dwFlags & STGC_OVERWRITE)
+ {
+ olChk(PrepareForOverwrite());
+ }
+
+ if (_pdfb->GetOrigLockFlags() & LOCK_ONLYONCE)
+ olChkTo(EH_COW, WaitForAccess(_pdfb->GetOriginal(), DF_WRITE,
+ &ulLock));
+
+ if (P_INDEPENDENT(_df))
+ {
+ if (_sigMSF == DF_INVALIDSIGNATURE)
+ {
+ if ((dwFlags & STGC_ONLYIFCURRENT) &&
+ DllIsMultiStream(_pdfb->GetOriginal()) == S_OK)
+ olErr(EH_GetAccess, STG_E_NOTCURRENT);
+ }
+ else
+ {
+ olChkTo(EH_GetAccess, DllGetCommitSig(_pdfb->GetOriginal(),
+ &sigMSF));
+ if (dwFlags & STGC_ONLYIFCURRENT)
+ if (sigMSF != _sigMSF)
+ olErr(EH_GetAccess, STG_E_NOTCURRENT);
+ }
+ }
+ }
+
+ for (ptsm = _tss.GetHead(); ptsm; ptsm = ptsm->GetNext())
+ if ((ptsm->GetFlags() & XSM_DELETED) == 0)
+ olChkTo(EH_NoCommit, ptsm->BeginCommit(dwFlags));
+
+ // 10/02/92 - To handle low disk space situations well, we
+ // preallocate the space we'll need to copy (when independent).
+
+ if (P_INDEPENDENT(_df))
+ {
+ STATSTG statBase, statOrig;
+
+ // With DELAYFLUSH we can't be sure of the size
+ // of the file until EndCopyOnWrite, but we do
+ // know that the file won't grow so this is safe
+
+ olHChkTo(EH_NoCommit, _pdfb->GetBase()->Stat(&statBase,
+ STATFLAG_NONAME));
+ olAssert(ULIGetHigh(statBase.cbSize) == 0);
+
+ olHChkTo(EH_NoCommit, _pdfb->GetOriginal()->Stat(&statOrig,
+ STATFLAG_NONAME));
+ olAssert(ULIGetHigh(statOrig.cbSize) == 0);
+
+ if (ULIGetLow(statBase.cbSize) > ULIGetLow(statOrig.cbSize))
+ {
+ olHChkTo(EH_NoCommit,
+ _pdfb->GetOriginal()->SetSize(statBase.cbSize));
+ }
+ *pcbSizeBase = ULIGetLow(statBase.cbSize);
+ *pcbSizeOrig = ULIGetLow(statOrig.cbSize);
+ }
+ *pulLock = ulLock;
+ *psigMSF = sigMSF;
+
+ //If this docfile is the root of a coordinated transaction, then mark
+ // its child as 'committing' so that the user can't write more data
+ // while this commit is in progress.
+ //BUGBUG: Do this.
+
+ return S_OK;
+
+EH_NoCommit:
+ // Move to end of list
+ for (ptsm = _tss.GetHead();
+ ptsm && ptsm->GetNext();
+ ptsm = ptsm->GetNext())
+ NULL;
+ // Abort commits in reverse
+ for (; ptsm; ptsm = ptsm->GetPrev())
+ ptsm->EndCommit(DF_ABORT);
+EH_GetAccess:
+ if (ulLock != 0)
+ ReleaseAccess(_pdfb->GetOriginal(), DF_WRITE, ulLock);
+EH_COW:
+ if (GetTransactedDepth() == 1)
+ {
+ olVerSucc(_pmsBase->EndCopyOnWrite(dwFlags, DF_ABORT));
+ }
+#endif //!REF
+EH_Err:
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::CommitPhase2, public
+//
+// Synopsis: Do phase 2 of commit
+//
+// Arguments: [dwFlags] -- Commit flags
+//
+// Returns: This can only fail if EndCopyOnWrite fails, which should
+// never happen (but can due to a hard disk error). We
+// include cleanup code just in case.
+//
+// History: 07-Aug-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CPubDocFile::CommitPhase2(DWORD const dwFlags,
+ BOOL fCommit,
+ ULONG ulLock,
+ DFSIGNATURE sigMSF,
+ ULONG cbSizeBase,
+ ULONG cbSizeOrig)
+{
+ SCODE sc;
+ PTSetMember *ptsm;
+
+ //The commit was aborted for some reason external to this particular
+ // docfile. We can handle this by calling directly to our cleanup
+ // code, which will abort and return success.
+ if (!fCommit)
+ {
+ sc = S_OK;
+ goto EH_Err;
+ }
+
+ if (GetTransactedDepth() == 1)
+ {
+ olChk(_pmsBase->EndCopyOnWrite(dwFlags, DF_COMMIT));
+ }
+
+ // Move to end of list
+ for (ptsm = _tss.GetHead();
+ ptsm && ptsm->GetNext();
+ ptsm = ptsm->GetNext())
+ NULL;
+ // End commits in reverse
+ for (; ptsm; ptsm = ptsm->GetPrev())
+ ptsm->EndCommit(DF_COMMIT);
+
+ if (P_INDEPENDENT(_df))
+ {
+ // Not robust, but we made sure we had enough
+ // disk space by presetting the larger size
+ // There is no practical way of making this robust
+ // and we have never guaranteed behavior in the face
+ // of disk errors, so this is good enough
+
+ olVerSucc(CopyLStreamToLStream(_pdfb->GetBase(),
+ _pdfb->GetOriginal()));
+ olVerSucc(_pdfb->GetOriginal()->Flush());
+
+ if (_sigMSF == DF_INVALIDSIGNATURE)
+ {
+ olVerSucc(DllGetCommitSig(_pdfb->GetOriginal(), &_sigMSF));
+ }
+ else
+ {
+ _sigMSF = sigMSF+1;
+ olVerSucc(DllSetCommitSig(_pdfb->GetOriginal(), _sigMSF));
+ }
+ }
+
+ if (ulLock != 0)
+ ReleaseAccess(_pdfb->GetOriginal(), DF_WRITE, ulLock);
+
+ // Dirty all parents up to the next transacted storage
+ if (IsDirty())
+ {
+ if (!IsRoot())
+ _pdfParent->SetDirty();
+ SetClean();
+ }
+
+#if DBG == 1
+ VerifyXSMemberBases();
+#endif
+ _wFlags = (_wFlags & ~PF_PREPARED);
+
+ //If this is the root of a coordinated transaction, mark its child
+ // as no longer 'committing', so the user can make more changes.
+ //BUGBUG: Do this.
+
+#ifdef HACK_COORD
+ if (P_COORD(_df))
+ {
+ return _pdfParent->Commit(dwFlags);
+ }
+#endif
+
+ return S_OK;
+
+EH_Err:
+ if (P_INDEPENDENT(_df) && (cbSizeBase > cbSizeOrig))
+ {
+ ULARGE_INTEGER uliSize;
+ ULISet32(uliSize, cbSizeOrig);
+
+ _pdfb->GetOriginal()->SetSize(uliSize);
+ }
+
+ // Move to end of list
+ for (ptsm = _tss.GetHead();
+ ptsm && ptsm->GetNext();
+ ptsm = ptsm->GetNext())
+ NULL;
+ // Abort commits in reverse
+ for (; ptsm; ptsm = ptsm->GetPrev())
+ ptsm->EndCommit(DF_ABORT);
+
+ if (ulLock != 0)
+ ReleaseAccess(_pdfb->GetOriginal(), DF_WRITE, ulLock);
+
+ if (GetTransactedDepth() == 1)
+ {
+ olVerSucc(_pmsBase->EndCopyOnWrite(dwFlags, DF_ABORT));
+ }
+
+ //If this is the root of a coordinated transaction, mark its child
+ // as no longer 'committing', so the user can make more changes.
+ //BUGBUG: Do this.
+
+ return sc;
+}
+
+#endif
diff --git a/private/ole32/stg/docfile/rpubdf.cxx b/private/ole32/stg/docfile/rpubdf.cxx
new file mode 100644
index 000000000..76915d822
--- /dev/null
+++ b/private/ole32/stg/docfile/rpubdf.cxx
@@ -0,0 +1,853 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: rpubdf.cxx
+//
+// Contents: CRootPubDocFile implementation
+//
+// History: 26-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+#include <header.hxx>
+#include <rpubdf.hxx>
+#include <lock.hxx>
+#ifndef REF
+#include <filelkb.hxx>
+#endif //!REF
+
+// Priority mode lock permissions
+#define PRIORITY_PERMS DF_READ
+
+//+--------------------------------------------------------------
+//
+// Member: CRootPubDocFile::CRootPubDocFile, public
+//
+// Synopsis: Ctor - Initializes empty object
+//
+// History: 30-Mar-92 DrewB Created
+// 05-Sep-5 MikeHill Init _timeModifyAtCommit.
+//
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CRootPubDocFile_CRootPubDocFile) // RPubdf_Init
+#endif
+
+CRootPubDocFile::CRootPubDocFile(IMalloc * const pMalloc) :
+ _pMalloc(pMalloc),
+#ifndef REF
+ CPubDocFile(NULL, NULL, 0, ROOT_LUID, NULL, NULL, 0, NULL)
+#else
+ CPubDocFile(NULL, NULL, 0, ROOT_LUID, NULL, NULL, NULL)
+#endif //!REF
+{
+ olDebugOut((DEB_ITRACE, "In CRootPubDocFile::CRootPubDocFile()\n"));
+
+#ifndef REF
+
+ _ulPriLock = 0;
+
+ // Default to an invalid value.
+ _timeModifyAtCommit.dwLowDateTime = _timeModifyAtCommit.dwHighDateTime = (DWORD) -1L;
+
+#endif //!REF
+
+ olDebugOut((DEB_ITRACE, "Out CRootPubDocFile::CRootPubDocFile\n"));
+}
+
+#ifndef REF
+//+--------------------------------------------------------------
+//
+// Member: CRootPubDocFile::InitInd, private
+//
+// Synopsis: Initializes independent root
+//
+// Arguments: [plstBase] - Base
+// [snbExclude] - Limited instantiation exclusions
+// [dwStartFlags] - Startup flags
+// [df] - Transactioning flags
+//
+// Returns: Appropriate status code
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CRootPubDocFile_InitInd)
+#endif
+
+SCODE CRootPubDocFile::InitInd(ILockBytes *plstBase,
+ SNBW snbExclude,
+ DWORD const dwStartFlags,
+ DFLAGS const df)
+{
+ CFileStream *pfstCopy;
+ ILockBytes *plkbCopy;
+ ULONG ulLock = 0;
+ CDocFile *pdfFrom, *pdfTo;
+ SCODE sc;
+ CMStream *pms;
+
+ olDebugOut((DEB_ITRACE, "In CRootPubDocFile::InitInd()\n"));
+
+ if ((sc = DllGetCommitSig(plstBase, &_sigMSF)) == STG_E_INVALIDHEADER ||
+ sc == STG_E_UNKNOWN)
+ {
+ _sigMSF = DF_INVALIDSIGNATURE;
+ }
+ else if (FAILED(sc))
+ {
+ olErr(EH_Err,sc);
+ }
+
+ olMem(pfstCopy = new (_pMalloc) CFileStream(_pMalloc));
+
+ olChkTo(EH_pfstCopy, pfstCopy->InitFlags(RSF_CREATE | RSF_DELETEONRELEASE,
+ DF_READWRITE));
+ olChkTo(EH_pfstCopy, pfstCopy->Init(NULL));
+
+ if (!P_PRIORITY(df) && (_pdfb->GetOrigLockFlags() & LOCK_ONLYONCE))
+ olChkTo(EH_pfstCopyInit, WaitForAccess(plstBase, DF_READ, &ulLock));
+ if (snbExclude)
+ {
+ plkbCopy = pfstCopy;
+ olChkTo(EH_GetAccess, DllMultiStreamFromStream(_pMalloc,
+ &pms, &plstBase,
+ dwStartFlags,
+ df));
+ olMemTo(EH_pmsFrom, pdfFrom = new (_pMalloc)
+ CDocFile(pms, SIDROOT, ROOT_LUID, BP_TO_P(CDFBasis *, _pdfb)));
+ pdfFrom->AddRef();
+ olChkTo(EH_pdfFrom, DllMultiStreamFromStream(_pMalloc,
+ &pms, &plkbCopy,
+ RSF_CREATE,
+ 0));
+ olMemTo(EH_pmsTo, pdfTo = new (_pMalloc)
+ CDocFile(pms, SIDROOT, ROOT_LUID, BP_TO_P(CDFBasis *, _pdfb)));
+ pdfTo->AddRef();
+ olChkTo(EH_pdfTo, pdfFrom->CopyTo(pdfTo, CDF_EXACT, snbExclude));
+ olChkTo(EH_pdfTo, pms->Flush(0));
+
+ pdfFrom->Release();
+ pdfTo->Release();
+ }
+ else if ((dwStartFlags & RSF_TRUNCATE) == 0)
+ olChkTo(EH_GetAccess, CopyLStreamToLStream(plstBase, pfstCopy));
+ if (!P_PRIORITY(df) && ulLock != 0)
+ ReleaseAccess(plstBase, DF_READ, ulLock);
+
+ _pdfb->SetBase(pfstCopy);
+ _pdfb->SetOriginal(plstBase);
+ olDebugOut((DEB_ITRACE, "Out CRootPubDocFile::InitInd\n"));
+ return S_OK;
+
+EH_pdfTo:
+ pdfTo->Release();
+ goto EH_pdfFrom;
+EH_pmsTo:
+ DllReleaseMultiStream(pms);
+EH_pdfFrom:
+ pdfFrom->Release();
+ goto EH_GetAccess;
+EH_pmsFrom:
+ DllReleaseMultiStream(pms);
+EH_GetAccess:
+ if (!P_PRIORITY(df) && ulLock != 0)
+ ReleaseAccess(plstBase, DF_READ, ulLock);
+EH_pfstCopyInit:
+EH_pfstCopy:
+ olVerSucc(pfstCopy->Release());
+EH_Err:
+ return sc;
+}
+#endif //!REF
+
+//+--------------------------------------------------------------
+//
+// Member: CRootPubDocFile::InitNotInd, private
+//
+// Synopsis: Dependent root initialization
+//
+// Arguments: [plstBase] - Base
+// [snbExclude] - Limited instantiation exclusions
+// [dwStartFlags] - Startup flags
+//
+// Returns: Appropriate status code
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CRootPubDocFile_InitNotInd)
+#endif
+
+#ifndef REF
+SCODE CRootPubDocFile::InitNotInd(ILockBytes *plstBase,
+#else
+SCODE CRootPubDocFile::Init(ILockBytes *plstBase,
+#endif //!REF
+ SNBW snbExclude,
+ DWORD const dwStartFlags,
+ DFLAGS const df)
+{
+ CDocFile *pdf;
+ SCODE sc;
+ CMStream *pms;
+
+ olDebugOut((DEB_ITRACE, "In CRootPubDocFile::InitNotInd()\n"));
+ if (snbExclude)
+ {
+ olChk(DllMultiStreamFromStream(_pMalloc,
+ &pms, &plstBase, dwStartFlags,
+ df));
+#ifndef REF
+ olMemTo(EH_pms, pdf = new(_pMalloc)
+ CDocFile(pms, SIDROOT, ROOT_LUID, BP_TO_P(CDFBasis *, _pdfb)));
+#else
+ olMemTo(EH_pms,
+ pdf = new CDocFile(pms, SIDROOT, ROOT_LUID, _pilbBase));
+#endif //!REF
+ pdf->AddRef();
+ olChkTo(EH_pdf, PDocFile::ExcludeEntries(pdf, snbExclude));
+ olChkTo(EH_pdf, pms->Flush(0));
+ pdf->Release();
+ }
+#ifndef REF
+ _pdfb->SetBase(plstBase);
+ plstBase->AddRef();
+ _pdfb->SetOriginal(plstBase);
+#else
+ _pilbBase = plstBase;
+#endif //!REF
+ olDebugOut((DEB_ITRACE, "Out CRootPubDocFile::InitNotInd\n"));
+ return S_OK;
+
+EH_pdf:
+ pdf->Release();
+EH_pms:
+ DllReleaseMultiStream(pms);
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CRootPubDocFile::InitRoot, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [plstBase] - Base LStream
+// [dwStartFlags] - How to start things
+// [df] - Transactioning flags
+// [snbExclude] - Parital instantiation list
+// [ppdfb] - Basis pointer return
+// [pulOpenLock] - Open lock index return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdfb]
+// [pulOpenLock]
+//
+// History: 09-Dec-91 DrewB Created
+// 09-Jun-92 PhilipLa Added conversion support
+// 05-Sep-95 MikeHill Initialize _timeModifyAtCommit.
+// Removed duplicate call to pdfWrapped->CopyTimesFrom
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CRootPubDocFile_InitRoot)
+#endif
+
+SCODE CRootPubDocFile::InitRoot(ILockBytes *plstBase,
+ DWORD const dwStartFlags,
+ DFLAGS const df,
+ SNBW snbExclude,
+#ifndef REF
+ CDFBasis **ppdfb,
+#endif //!REF
+ ULONG *pulOpenLock)
+{
+#ifndef REF
+ CWrappedDocFile *pdfWrapped;
+#endif //!REF
+ CDocFile *pdfBase;
+#ifndef REF
+ CFileStream *pfstScratch;
+ CMStream *pmsScratch;
+#endif //!REF
+ SCODE sc, scConv = S_OK;
+ STATSTG statstg;
+
+#ifndef REF
+ olDebugOut((DEB_ITRACE, "In CRootPubDocFile::InitRoot("
+ "%p, %lX, %lX, %p, %p)\n",
+ plstBase, dwStartFlags, df, snbExclude, ppdfb));
+#else
+ olDebugOut((DEB_ITRACE, "In CRootPubDocFile::InitRoot("
+ "%p, %lX, %lX, %p)\n",
+ plstBase, dwStartFlags, df, snbExclude));
+#endif //!REF
+
+ // Exclusion only works with a plain open
+ olAssert(snbExclude == NULL ||
+ (dwStartFlags & (RSF_CREATEFLAGS | RSF_CONVERT)) == 0);
+
+ // ILockBytes::Stat calls are very expensive; we avoid one here
+ // if possible
+
+ HRESULT hr;
+ IFileLockBytes *pfl;
+ if (SUCCEEDED(plstBase->QueryInterface(IID_IFileLockBytes,
+ (void**) &pfl)))
+ {
+ // This is our private ILockBytes implementation.
+
+ hr = pfl->GetLocksSupported(&statstg.grfLocksSupported);
+ pfl->Release();
+ }
+ else
+ hr = plstBase->Stat(&statstg, STATFLAG_NONAME);
+
+ olHChk(hr);
+
+ *pulOpenLock = 0;
+ if (statstg.grfLocksSupported & LOCK_ONLYONCE)
+ olChk(GetOpen(plstBase, df, TRUE, pulOpenLock));
+#ifndef REF
+ if (P_PRIORITY(df) && (statstg.grfLocksSupported & LOCK_ONLYONCE))
+ olChkTo(EH_GetOpen, GetAccess(plstBase, PRIORITY_PERMS, &_ulPriLock));
+
+ olMemTo(EH_GetPriority, *ppdfb = new (_pMalloc) CDFBasis(_pMalloc, df,
+ statstg.grfLocksSupported));
+ _pdfb = P_TO_BP(CBasedDFBasisPtr, *ppdfb);
+
+#endif //!REF
+
+#ifndef REF
+ if (P_INDEPENDENT(df))
+ olChkTo(EH_GetPriority, InitInd(plstBase, snbExclude, dwStartFlags,
+ df));
+ else
+ olChkTo(EH_GetPriority,
+ InitNotInd(plstBase, snbExclude, dwStartFlags, df));
+#else
+ olChkTo(EH_GetPriority,
+ Init(plstBase, snbExclude, dwStartFlags, df));
+#endif //!REF
+
+#ifndef REF
+ olMemTo(EH_SubInit, pfstScratch = new (_pMalloc) CFileStream(_pMalloc));
+ olChkTo(EH_pfstScratchInit, pfstScratch->InitFlags(RSF_CREATE |
+ RSF_DELETEONRELEASE,
+ DF_READWRITE));
+ _pdfb->SetDirty(pfstScratch);
+
+ CMStream *pms;
+ scConv = DllMultiStreamFromStream(_pMalloc,
+ &pms, _pdfb->GetPBase(),
+ dwStartFlags |
+ ((!P_INDEPENDENT(df) &&
+ P_TRANSACTED(df)) ? RSF_DELAY : 0),
+ df);
+#else
+ scConv = DllMultiStreamFromStream(_pMalloc,
+ &_pmsBase, &_pilbBase,
+ dwStartFlags,
+ df);
+#endif //!REF
+ _pmsBase = P_TO_BP(CBasedMStreamPtr, pms);
+
+ if (scConv == STG_E_INVALIDHEADER)
+ scConv = STG_E_FILEALREADYEXISTS;
+ olChkTo(EH_pfstScratchInit, scConv);
+
+#ifndef REF
+ olMemTo(EH_pmsBase, pdfBase = new (_pMalloc)
+ CDocFile(pms, SIDROOT, ROOT_LUID, BP_TO_P(CDFBasis *, _pdfb)));
+#else
+ olMemTo(EH_pmsBase, pdfBase = new (_pMalloc)
+ CDocFile(_pmsBase, SIDROOT, ROOT_LUID, _pilbBase));
+#endif //!REF
+
+ pdfBase->AddRef();
+
+#ifndef REF
+ if (P_TRANSACTED(df))
+ {
+ _cTransactedDepth = 1;
+ CDfName dfnNull; // auto-initialized to 0
+ WCHAR wcZero = 0;
+ dfnNull.Set(2, (BYTE*)&wcZero);
+
+ // 3/11/93 - Demand scratch when opening/creating transacted
+ olChkTo(EH_pdfBaseInit, _pdfb->GetDirty()->Init(NULL));
+
+ olMemTo(EH_pdfBaseInit, pdfWrapped = new(_pMalloc)
+ CWrappedDocFile(&dfnNull, pdfBase->GetLuid(), df,
+ BP_TO_P(CDFBasis *, _pdfb), this));
+ olChkTo(EH_pdfWrapped,
+ pdfWrapped->Init(pdfBase));
+ AddXSMember(NULL, pdfWrapped, pdfWrapped->GetLuid());
+ _pdf = P_TO_BP(CBasedDocFilePtr, (PDocFile *)pdfWrapped);
+
+ }
+ else
+#endif //!REF
+ _pdf = P_TO_BP(CBasedDocFilePtr, (PDocFile *)pdfBase);
+
+#ifndef REF
+#ifdef USE_NOSCRATCH
+
+ // For no-scratch transacted files, also save the Docfile's current modify
+ // time. This will be used on the Release (in vdtor).
+
+ if( P_NOSCRATCH( df ))
+ {
+ if( FAILED( _pmsBase->GetTime( SIDROOT, WT_MODIFICATION, &_timeModifyAtCommit )))
+ {
+ // Do not return an error, but record an error flag so that
+ // vdtor will not try to use it.
+
+ _timeModifyAtCommit.dwLowDateTime = _timeModifyAtCommit.dwHighDateTime = (DWORD) -1;
+ }
+ }
+
+
+ olChkTo(EH_pfstScratchInit,
+ DllGetScratchMultiStream(&pmsScratch,
+ (df & DF_NOSCRATCH),
+ (ILockBytes **)_pdfb->GetPDirty(),
+ pms));
+#else //USE_NOSCRATCH
+
+ olChkTo(EH_pfstScratchInit,
+ DllGetScratchMultiStream(&pmsScratch,
+ (ILockBytes **)_pdfb->GetPDirty(),
+ pms));
+#endif //USE_NOSCRATCH
+
+ _pdfb->SetScratch(pmsScratch);
+
+#ifdef USE_NOSCRATCH
+
+ if (df & DF_NOSCRATCH)
+ {
+ _pdfb->SetBaseMultiStream(pms);
+ olChkTo(EH_pfstScratchInit, pmsScratch->InitScratch(pms, TRUE));
+ _pmsBase->SetScratchMS(pmsScratch);
+ }
+ else
+ {
+ _pdfb->SetBaseMultiStream(NULL);
+ }
+#endif //USE_NOSCRATCH
+#endif //!REF
+
+
+ _df = df;
+
+#ifndef REF
+
+ // _pdfb->mxs is constructed automatically
+
+#endif //!REF
+
+ olDebugOut((DEB_ITRACE, "Out CRootPubDocFile::InitRoot\n"));
+ return scConv;
+
+#ifndef REF
+
+EH_pdfWrapped:
+ delete pdfWrapped;
+EH_pdfBaseInit:
+ pdfBase->Release();
+ goto EH_pfstScratchInit;
+#endif //!REF
+
+EH_pmsBase:
+ DllReleaseMultiStream(BP_TO_P(CMStream *, _pmsBase));
+
+EH_pfstScratchInit:
+#ifndef REF
+ olVerSucc(pfstScratch->Release());
+ _pdfb->SetDirty(NULL);
+EH_SubInit:
+ olVerSucc(_pdfb->GetBase()->Release());
+ _pdfb->SetBase(NULL);
+#else
+ olVerSucc(_pilbBase->Release());
+#endif //!REF
+EH_GetPriority:
+#ifndef REF
+ if (_ulPriLock > 0)
+ {
+ olAssert(P_PRIORITY(df) &&
+ (statstg.grfLocksSupported & LOCK_ONLYONCE));
+ ReleaseAccess(plstBase, PRIORITY_PERMS, _ulPriLock);
+ _ulPriLock = 0;
+ }
+#endif //!REF
+EH_GetOpen:
+ if (*pulOpenLock != 0)
+ {
+ olAssert(statstg.grfLocksSupported & LOCK_ONLYONCE);
+ ReleaseOpen(plstBase, df, *pulOpenLock);
+ *pulOpenLock = 0;
+ }
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CRootPubDocFile::~CRootPubDocFile, public
+//
+// Synopsis: dtor
+//
+// History: 09-Dec-91 DrewB Created
+// 05-Sep-95 MikeHill Revert time using _timeModifyAtCommit.
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CRootPubDocFile_vdtor) // RPubdf_Shutdown
+#endif
+
+void CRootPubDocFile::vdtor(void)
+{
+ olDebugOut((DEB_ITRACE, "In CRootPubDocFile::~CRootPubDocFile\n"));
+
+ olAssert(_cReferences == 0);
+
+
+#ifndef REF
+
+ // If this is a no-scratch transacted file, revert the Modify timestamp
+ // on the Docfile to that of the last commit.
+
+ if( P_NOSCRATCH( _df )
+ &&
+ ( _timeModifyAtCommit.dwLowDateTime != -1L ) // Don't use an invalid timestamp.
+ )
+ {
+ // We call SetFileLockBytesTime, rather than SetTime, so that
+ // the underlying Docfile's timestamp is changed, but the Storage's
+ // timestamp in the Directory is unchanged. If we changed the
+ // Directory, we would have to flush the Multi-Stream.
+
+ // An error here is ignored.
+
+ _pmsBase->SetFileLockBytesTime( WT_MODIFICATION, _timeModifyAtCommit );
+ }
+
+#endif // !REF
+
+ // We can't rely on CPubDocFile::~CPubDocFile to do this since
+ // we're using a virtual destructor
+ _sig = CPUBDOCFILE_SIGDEL;
+
+ if (SUCCEEDED(CheckReverted()))
+ {
+#ifndef REF
+ ChangeXs(DF_NOLUID, XSO_RELEASE);
+#endif //!REF
+ _cilChildren.DeleteByName(NULL);
+#ifndef REF
+ if (_ulPriLock > 0)
+ {
+ // Priority instantiation can't be independent
+ olAssert(!P_INDEPENDENT(_df));
+ ReleaseAccess(_pdfb->GetBase(), PRIORITY_PERMS, _ulPriLock);
+ }
+#endif //!REF
+
+ if (_pdf)
+ _pdf->Release();
+#ifndef REF
+ if (_pdfb)
+ _pdfb->vRelease();
+#else
+ if (_pilbBase)
+ _pilbBase->Release();
+#endif //!REF
+
+
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CRootPubDocFile::~CRootPubDocFile\n"));
+ delete this;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CRootPubDocFile::ReleaseLocks, public
+//
+// Synopsis: Release any locks using the given ILockBytes
+//
+// Arguments: [plkb] -- ILockBytes to use for release
+//
+// Returns: void
+//
+// History: 24-Jan-95 PhilipLa Created
+//
+// Notes: This is a cleanup function used to resolve the many
+// conflicts we get trying to release locks using an
+// ILockBytes in a basis that's already been released.
+//
+//----------------------------------------------------------------------------
+
+void CRootPubDocFile::ReleaseLocks(ILockBytes *plkb)
+{
+ olDebugOut((DEB_ITRACE, "In CRootPubDocFile::ReleaseLocks:%p()\n", this));
+ if (_ulPriLock > 0)
+ {
+ // Priority instantiation can't be independent
+ olAssert(!P_INDEPENDENT(_df));
+ ReleaseAccess(plkb, PRIORITY_PERMS, _ulPriLock);
+ _ulPriLock = 0;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CRootPubDocFile::ReleaseLocks\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CRootPubDocFile::Stat, public
+//
+// Synopsis: Fills in a stat buffer from the base LStream
+//
+// Arguments: [pstatstg] - Stat buffer
+// [grfStatFlag] - Stat flags
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 25-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CRootPubDocFile_Stat) // Stat_TEXT
+#endif
+
+SCODE CRootPubDocFile::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CRootPubDocFile::Stat(%p, %lu)\n",
+ pstatstg, grfStatFlag));
+ olChk(CheckReverted());
+#ifndef REF
+ olHChk(_pdfb->GetOriginal()->Stat((STATSTG *)pstatstg, grfStatFlag));
+#else
+ olHChk(_pilbBase->Stat((STATSTG *)pstatstg, grfStatFlag));
+#endif //!REF
+#ifndef OLEWIDECHAR
+ if (pstatstg->pwcsName)
+ {
+ WCHAR *pwcs;
+
+ olChkTo(EH_pwcsName,
+ DfAllocWC(strlen((char *)pstatstg->pwcsName)+1, &pwcs));
+ if (mbstowcs(pwcs, (char *)pstatstg->pwcsName,
+ strlen((char *)pstatstg->pwcsName)+1) == (size_t)-1)
+ {
+ TaskMemFree(pwcs);
+ olErr(EH_pwcsName, STG_E_INVALIDNAME);
+ }
+#ifndef REF
+ TaskMemFree(pstatstg->pwcsName);
+#else
+ delete[] pstatstg->pwcsName;
+#endif //!REF
+ pstatstg->pwcsName = pwcs;
+ }
+#endif
+ pstatstg->grfMode = DFlagsToMode(_df);
+ olChkTo(EH_pwcsName, _pdf->GetClass(&pstatstg->clsid));
+ olChkTo(EH_pwcsName, _pdf->GetStateBits(&pstatstg->grfStateBits));
+ olDebugOut((DEB_ITRACE, "Out CRootPubDocFile::Stat\n"));
+ return S_OK;
+
+EH_pwcsName:
+ if (pstatstg->pwcsName)
+#ifndef REF
+ TaskMemFree(pstatstg->pwcsName);
+#else
+ delete[] pstatstg->pwcsName;
+#endif //!REF
+EH_Err:
+ return sc;
+}
+
+#ifndef REF
+//+---------------------------------------------------------------------------
+//
+// Member: CRootPubDocFile::SwitchToFile, public
+//
+// Synopsis: Switches the underlying file in the base ILockBytes
+//
+// Arguments: [ptcsFile] - Filename
+// [plkb] - The ILockBytes to operate on
+// [pulOpenLock] - On entry, the current open lock
+// On exit, the new open lock
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pulOpenLock]
+//
+// History: 08-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CRootPubDocFile_SwitchToFile) // RPubdf_SwitchToFile
+#endif
+
+SCODE CRootPubDocFile::SwitchToFile(OLECHAR const *ptcsFile,
+ ILockBytes *plkb,
+ ULONG *pulOpenLock)
+{
+ IFileLockBytes *pfl;
+ SCODE sc;
+ BYTE *pbBuffer;
+ USHORT cbBuffer;
+
+ olDebugOut((DEB_ITRACE, "In CRootPubDocFile::SwitchToFile:%p("
+ "%s, %p, %p)\n", this, ptcsFile, plkb, pulOpenLock));
+
+ // If you're transacted, nothing can be dirty in the base
+ // If you're not dirty, there's no point in flushing
+ // This is also necessary to allow SwitchToFile with a read-only source
+ if (!P_TRANSACTED(_df) && IsDirty())
+ {
+ // Make sure pending changes are flushed
+ olChk(_pmsBase->Flush(0));
+
+ // Make sure ILockBytes contents are on disk
+ olHChk(plkb->Flush());
+ }
+
+ ULONG ulCommitSize;
+ olChk(GetCommitSize(&ulCommitSize));
+
+ // Check for FileLockBytes
+ olHChkTo(EH_NotFile, plkb->QueryInterface(IID_IFileLockBytes,
+ (void **)&pfl));
+
+ // Release old locks
+ if (*pulOpenLock)
+ ReleaseOpen(plkb, _df, *pulOpenLock);
+
+ // Ask ILockBytes to switch
+ GetSafeBuffer(CB_SMALLBUFFER, CB_LARGEBUFFER, &pbBuffer, &cbBuffer);
+ olAssert(pbBuffer != NULL);
+ sc = DfGetScode(pfl->SwitchToFile(
+ ptcsFile,
+ ulCommitSize,
+ cbBuffer,
+ pbBuffer));
+
+ pfl->Release();
+ FreeBuffer(pbBuffer);
+
+ //Record the fact that we have enough space for overwrite commit.
+ _wFlags = _wFlags | PF_PREPARED;
+
+
+ // Attempt to get new locks
+ // If SwitchToFile failed, the ILockBytes is the same so this will
+ // restore our open locks released above
+ // If SwitchToFile succeeded, the ILockBytes is working on the new file
+ // so this will get locks for that
+ if (*pulOpenLock)
+ {
+ ULONG ulLock;
+
+ // Don't propagate failures here since there's nothing
+ // that can be done
+ if (SUCCEEDED(GetOpen(plkb, _df, FALSE, &ulLock)))
+ *pulOpenLock = ulLock;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CRootPubDocFile::SwitchToFile\n"));
+EH_Err:
+ return sc;
+
+EH_NotFile:
+ return(STG_E_NOTFILEBASEDSTORAGE);
+}
+#endif //!REF
+
+
+
+#ifndef REF
+//+--------------------------------------------------------------
+//
+// Member: CRootPubDocFile::Commit, public
+//
+// Synopsis: Commits transacted changes
+//
+// Arguments: [dwFlags] - DFC_*
+//
+// Returns: Appropriate status code
+//
+// History: 29-Aug-95 MikeHill Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CRootPubDocFile_Commit)
+#endif
+
+SCODE CRootPubDocFile::Commit(DWORD const dwFlags)
+{
+
+ SCODE sc = STG_E_UNKNOWN;
+
+ // Execute the normal commit procedures for a CPubDocFile.
+
+ olChk( CPubDocFile::Commit( dwFlags ));
+
+#ifdef USE_NOSCRATCH
+
+ // For no-scratch transacted files, also save the Docfile's modify
+ // time. This will be used to restore the file's current time on a Release.
+
+ if( P_NOSCRATCH( _df ) && P_TRANSACTED( _df ))
+ {
+ if( FAILED( _pmsBase->GetTime( SIDROOT, WT_MODIFICATION, &_timeModifyAtCommit )))
+ {
+ // Do not return an error, but record an error flag so that
+ // the Release (vdtor) will not try to use it.
+
+ _timeModifyAtCommit.dwLowDateTime = _timeModifyAtCommit.dwHighDateTime = (DWORD) -1L;
+ }
+ }
+
+#endif // USE_NOSCRATCH
+
+ return NOERROR;
+
+EH_Err:
+
+ return sc;
+
+} // End - CRootPubDocFile::Commit
+
+#endif // !REF
+
+
diff --git a/private/ole32/stg/docfile/segdf.hxx b/private/ole32/stg/docfile/segdf.hxx
new file mode 100644
index 000000000..99e0d2574
--- /dev/null
+++ b/private/ole32/stg/docfile/segdf.hxx
@@ -0,0 +1,160 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: SegDF.HXX
+//
+// Contents: Segment defines for 16-bit builds
+//
+// History: 11-Jun-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __SEGDF_HXX__
+#define __SEGDF_HXX__
+
+#include <segh.hxx>
+
+#ifdef CODESEGMENTS
+
+// Code segment defines go here
+
+// Common code
+
+#define SEG_CChildInstanceList_DeleteByName "Common0_TEXT" // chinst
+#define SEG_CChildInstanceList_RemoveRv "Common0_TEXT" // chinst
+#define SEG_CDFBasis_vRelease "Common0_TEXT" // dfbasis
+#define SEG_CDocFile_Release "Common0_TEXT" // Dirdf_Release_TEXT // cdocfile
+#define SEG_CMallocBased_delete "Common0_TEXT" // mem
+#define SEG_CPubDocFile_ChangeXs "Common0_TEXT" // // publicdf
+#define SEG_CPubDocFile_vRelease "Common0_TEXT" // Pubdf_Release_TEXT // publicdf
+#define SEG_CRootPubDocFile_vdtor "Common0_TEXT" // RPubdf_Shutdown // rpubdf
+#define SEG_CTSSet_1CTSSet "Common0_TEXT" // inline? // tlsets
+#define SEG_CWrappedDocFile_SetInitialState "Common0_TEXT" // wdffuncs
+#define SEG_TaskMemFree "Common0_TEXT" // mem
+#define SEG_CRootPubDocFile_InitNotInd "Common0_TEXT" // rpubdf
+#define SEG_CRootPubDocFile_InitRoot "Common0_TEXT" // rpubdf
+
+#define SEG_CChildInstanceList_Add "Common1_TEXT" // chinst
+#define SEG_CChildInstanceList_IsDenied "Common0_TEXT" // chinst
+#define SEG_CDocFile_AddRef "Common1_TEXT" // cdocfile
+#define SEG_CDocFile_GetClass "Common3_TEXT" // cdocfile
+#define SEG_CDocFile_GetStateBits "Common1_TEXT" // cdocfile
+#define SEG_CDocFile_GetStream "Common1_TEXT" // Dirdf_Open_TEXT // dfstream
+#define SEG_CDocFile_GetTime "Common1_TEXT" // cdocfile
+
+#define SEG_CMallocBased_new "Common2_TEXT" // mem
+#define SEG_CPubDocFile_AddXSMember "Common2_TEXT" // publicdf
+#define SEG_CPubDocFile_CPubDocFile "Common2_TEXT" // Pubdf_Init_TEXT // publicdf
+#define SEG_CPubDocFile_GetStream "Common2_TEXT" // Pubdf_Open_TEXT // publicdf
+#define SEG_CRootPubDocFile_CRootPubDocFile "Common2_TEXT" // RPubdf_Init // rpubdf
+#define SEG_CRootPubDocFile_Stat "Common2_TEXT" // Stat_TEXT // rpubdf
+#define SEG_CTSSet_AddMember "Common2_TEXT" // tlsets
+#define SEG_CTSSet_FindName "Common2_TEXT" // tlsets
+#define SEG_CUpdateList_IsEntry "Common2_TEXT" // ulist
+#define SEG_CWrappedDocFile_AddRef "Common2_TEXT" // Wrapdf_TEXT // wdocfile
+#define SEG_CWrappedDocFile_CWrappedDocFile "Common2_TEXT" // Wrapdf_Init_TEXT // wdocfile
+#define SEG_CWrappedDocFile_Init "Common2_TEXT" // wdocfile
+#define SEG_CWrappedDocFile_SetTime "Common2_TEXT" // wdocfile
+#define SEG_DFlagsToMode "Common2_TEXT" // funcs
+#define SEG_ModeToDFlags "Common2_TEXT" // funcs
+#define SEG_PTimeEntry_CopyTimesFrom "Common2_TEXT" // entry
+#define SEG_TaskMemAlloc "Common2_TEXT" // mem
+#define SEG_VerifyPerms "Common2_TEXT" // funcs
+
+#define SEG_CDocFile_IsEntry "BootSave_TEXT" // Dirdf_TEXT // cdocfile
+#define SEG_CFreeList_Reserve "BootSave_TEXT" // freelist
+#define SEG_CPubDocFile_CreateDocFile "BootSave_TEXT" // Pubdf_Create_TEXT // publicdf
+#define SEG_CPubDocFile_CreateStream "BootSave_TEXT" // Pubdf_Create_TEXT // publicdf
+
+#define SEG_CUpdate_CUpdate "Boot_TEXT" // ulist
+#define SEG_CUpdateList_Add "Boot_TEXT" // ulist
+#define SEG_CUpdateList_Append "Boot_TEXT" // ulist
+#define SEG_CWrappedDocFile_CreateDocFile "Boot_TEXT" // Wrapdf_Create_TEXT // wdocfile
+#define SEG_CWrappedDocFile_CreateStream "Boot_TEXT" // Wrapdf_Create_TEXT // wdfstrm
+#define SEG_CWrappedDocFile_IsEntry "Boot_TEXT" // Wrapdf_TEXT // wdocfile
+
+#define SEG_CPubDocFile_vdtor "OpenSave0_TEXT" // Pubdf_Shutdown_TEXT // publicdf
+#define SEG_CTSSet_RemoveMember "OpenSave0_TEXT" // tlsets
+#define SEG_CUpdateList_Empty "OpenSave0_TEXT" // ulist
+#define SEG_CWrappedDocFile_Release "OpenSave0_TEXT" // Wrapdf_Release_TEXT // wdocfile
+#define SEG_CWrappedDocFile_Revert "OpenSave0_TEXT" // Wrapdf_Revert_TEXT // wdfxact
+#define SEG_CWrappedDocFile_1CWrappedDocFile "OpenSave0_TEXT" // Wrapdf_Shutdown_TEXT // wdocfile
+
+#define SEG_CDocFile_GetDocFile "OpenSave1_TEXT" // Dirdf_Open_TEXT // cdocfile
+#define SEG_CDocFile_InitFromEntry "OpenSave1_TEXT" // Dirdf_Init_TEXT // cdocfile
+#define SEG_CDocFile_SetTime "OpenSave1_TEXT" // cdocfile
+#define SEG_CPubDocFile_Commit "OpenSave1_TEXT" // Pubdf_Commit_TEXT // publicdf
+#define SEG_CPubDocFile_GetDocFile "OpenSave1_TEXT" // Pubdf_Open_TEXT // publicdf
+#define SEG_CWrappedDocFile_GetClass "OpenSave1_TEXT" // wdocfile
+#define SEG_CWrappedDocFile_GetDocFile "OpenSave1_TEXT" // Wrapdf_Open_TEXT // wdocfile
+#define SEG_CWrappedDocFile_GetStateBits "OpenSave1_TEXT" // wdocfile
+#define SEG_CWrappedDocFile_GetStream "OpenSave1_TEXT" // Wrapdf_Open_TEXT // wdfstrm
+
+#define SEG_CDocFile_ApplyChanges "Open_TEXT" // Dirdf_Commit_TEXT // dffuncs
+#define SEG_CDocFile_BeginCommitFromChild "Open_TEXT" // Dirdf_Commit_TEXT // dfxact
+#define SEG_CDocFile_EndCommitFromChild "Open_TEXT" // dfxact
+#define SEG_CFreeList_Unreserve "Open_TEXT" // freelist
+#define SEG_CPubDocFile_GetCommitSize "Open_TEXT" // publicdf
+#define SEG_CPubDocFile_PrepareForOverwrite "Open_TEXT" // publicdf
+#define SEG_CUpdate_1CUpdate "Open_TEXT" // inline? // ulist
+#define SEG_CWrappedDocFile_BeginCommit "Open_TEXT" // Wrapdf_Commit_TEXT // wdfxact
+#define SEG_CWrappedDocFile_EndCommit "Open_TEXT" // wdfxact
+#define SEG_CWrappedDocFile_GetCommitInfo "Open_TEXT" // Wrapdf_Overwrite_TEXT // wdfxact
+#define SEG_CWrappedDocFile_GetTime "Open_TEXT" // Wrapdf_TEXT // wdocfile
+#define SEG_CWrappedDocFile_RevertUpdate "Open_TEXT" // Wrapdf_Revert_TEXT // wdffuncs
+
+#define SEG_CDocFile_CreateDocFile "Save_TEXT" // Dirdf_Create_TEXT // cdocfile
+#define SEG_CDocFile_CreateStream "Save_TEXT" // Dirdf_Create_TEXT // dfstream
+#define SEG_CDocFile_SetClass "Save_TEXT" // cdocfile
+#define SEG_CPubDocFile_SetClass "Save_TEXT" // publicdf
+
+#define SEG_PDocFile_CreateFromUpdate "Commit_TEXT" // Gendf_Commit_TEXT // pdffuncs
+#define SEG_CDocFile_SetStateBits "Commit_TEXT" // cdocfile
+#define SEG_CWrappedDocFile_SetBase "Commit_TEXT" // Wrapdf_Commit_TEXT // wdfxact
+
+// Marshalling code
+
+#define SEG_CPubDocFile_Validate "Marshal_TEXT" // publicdf
+
+// Transactioning code
+
+#define SEG_PTSetMember_STAT "TransD_TEXT" // tset
+#define SEG_CUpdateList_Remove "TransD_TEXT" // ulist
+#define SEG_CUpdateList_FindBase "TransD_TEXT" // ulist
+#define SEG_CWrappedDocFile_BeginCommitFromChild "TransD_TEXT" // Wrapdf_Commit_TEXT // wdfxact
+#define SEG_CWrappedDocFile_EndCommitFromChild "TransD_TEXT" // wdfxact
+#define SEG_CWrappedDocFile_DestroyEntry "TransD_TEXT" // Wrapdf_Destroy_TEXT // wdocfile
+
+#define SEG_CPubDocFile_Stat "UnassignedD_TEXT" // Stat_TEXT // publicdf
+#define SEG_CWrappedDocFile_SetClass "UnassignedD_TEXT" // wdocfile
+#define SEG_CDocFile_Destroy "UnassignedD_TEXT" // Dirdf_Destroy_TEXT // cdocfile
+#define SEG_CDocFile_CopyTo "UnassignedD_TEXT" // Root_TEXT // dffuncs
+#define SEG_ValidateSNB "UnassignedD_TEXT" // // funcs
+#define SEG_CopySStreamToSStream "UnassignedD_TEXT" // funcs
+#define SEG_NameInSNB "UnassignedD_TEXT" // funcs
+#define SEG_PDocFile_ExcludeEntries "UnassignedD_TEXT" // // pdffuncs
+#define SEG_CPubDocFile_CopyLStreamToLStream "UnassignedD_TEXT" // Root_TEXT // publicdf
+#define SEG_CPubDocFile_DestroyEntry "UnassignedD_TEXT" // Pubdf_Destroy_TEXT // publicdf
+#define SEG_CRootPubDocFile_SwitchToFile "UnassignedD_TEXT" // RPubdf_SwitchToFile // rpubdf
+#define SEG_CPubDocFile_RevertFromAbove "UnassignedD_TEXT" // Pubdf_Revert_TEXT // publicdf
+#define SEG_CDocFile_Rename "UnassignedD_TEXT" // Dirdf_Rename_TEXT // cdocfile
+#define SEG_CChildInstanceList_FindByName "UnassignedD_TEXT" // chinst
+#define SEG_CDocFile_DeleteContents "UnassignedD_TEXT" // Dirdf_TEXT // dffuncs
+#define SEG_CDocFile_FindGreaterEntry "UnassignedD_TEXT" // Iterate_TEXT // dfiter
+#define SEG_CDocFile_StatEntry "UnassignedD_TEXT" // dfiter
+#define SEG_CDfName_CopyString "UnassignedD_TEXT" // dfname
+#define SEG_DeleteIStorageContents "UnassignedD_TEXT" // Expdf_CopyTo_TEXT // funcs
+#define SEG_CPubDocFile_RenameEntry "UnassignedD_TEXT" // Pubdf_Rename_TEXT // publicdf
+#define SEG_CPubDocFile_SetElementTimes "UnassignedD_TEXT" // publicdf
+#define SEG_CPubDocFile_SetStateBits "UnassignedD_TEXT" // publicdf
+#define SEG_CRootPubDocFile_InitInd "UnassignedD_TEXT" // rpubdf
+#define SEG_CWrappedDocFile_DeleteContents "UnassignedD_TEXT" // Wrapdf_TEXT inline? // wdffuncs
+#define SEG_CWrappedDocFile_FindGreaterEntry "UnassignedD_TEXT" // Iterate_TEXT // wdfiter
+#define SEG_CWrappedDocFile_StatEntry "UnassignedD_TEXT" // wdfiter
+#define SEG_CWrappedDocFile_RenameEntry "UnassignedD_TEXT" // Wrapdf_Rename_TEXT // wdocfile
+#define SEG_CWrappedDocFile_SetStateBits "UnassignedD_TEXT" // wdocfile
+
+#endif // CODESEGMENTS
+#endif // __SEGDF_HXX__
diff --git a/private/ole32/stg/docfile/smalloc.cxx b/private/ole32/stg/docfile/smalloc.cxx
new file mode 100644
index 000000000..dacb18eca
--- /dev/null
+++ b/private/ole32/stg/docfile/smalloc.cxx
@@ -0,0 +1,1184 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: smalloc.cxx
+//
+// Contents: Shared memory heap implementation
+//
+// Classes:
+//
+// Functions:
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+// 10-May-95 KentCe Defer Heap Destruction to the last
+// process detach.
+//
+//----------------------------------------------------------------------------
+
+#include <dfhead.cxx>
+#pragma hdrstop
+
+#include <smalloc.hxx>
+
+#ifdef NEWPROPS
+#define FULLIMPL
+#endif
+
+//
+// Take advantage of unique Win95 support of a shared heap.
+//
+#if defined(_CHICAGO_)
+
+#define HEAP_SHARED 0x04000000 // Secret feature of Win95 only.
+
+//
+// Locate the following in a shared data segment.
+//
+#pragma data_seg(".sdata")
+
+HANDLE gs_hSharedHeap = NULL; // hSharedHeap Handle for Win95.
+DFLUID gs_dfluid = LUID_BASE; // shared docfile global LUID
+
+#pragma data_seg()
+
+#define PRINTSTATS
+
+#else // defined(_CHICAGO_)
+
+#define DLL
+
+#define DEB_STATS 0x00010000
+#define DEB_PRINT 0x00020000
+
+#ifdef DLL
+
+#define PERCENT(a,b,c) (int)((((double)a + (double)b) / (double)c) * 100.0)
+
+#define PRINTSTATS \
+ memDebugOut((DEB_STATS, \
+ "Total size: %lu, Space: Free: %lu, Alloced: %lu"\
+ " Blocks: Free: %lu, Alloced: %lu"\
+ " Efficiency: %.2f%%\n",\
+ _cbSize,\
+ GetHeader()->_ulFreeBytes,\
+ GetHeader()->_ulAllocedBytes,\
+ GetHeader()->_ulFreeBlocks,\
+ GetHeader()->GetAllocedBlocks(),\
+ PERCENT(GetHeader()->_ulFreeBytes,\
+ GetHeader()->_ulAllocedBytes, _cbSize)));
+
+#else
+#define PRINTSTATS \
+ printf( \
+ "Total size: %lu, Free space: %lu, Alloced space: %lu"\
+ " Efficiency: %.2f%%\n",\
+ _cbSize,\
+ GetHeader()->_ulFreeBytes,\
+ GetHeader()->_ulAllocedBytes,\
+ ((double)(GetHeader()->_ulFreeBytes +\
+ GetHeader()->_ulAllocedBytes) / \
+ (double)_cbSize) * (double)100);
+#endif
+
+
+#if DBG == 1
+inline BOOL IsAligned(void *pv)
+{
+ return !((ULONG)pv & 7);
+}
+#else
+#define IsAligned(x) TRUE
+#endif
+
+
+#define SHAREDMEMBASE NULL
+
+#endif // !defined(_CHICAGO_)
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Init, public
+//
+// Synopsis: Initialize heap for use
+//
+// Arguments: [pszName] -- Name of shared memory heap to use
+//
+// Returns: Appropriate status code
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+//
+// Remarks: Review the class destructor if you change this code.
+//
+//----------------------------------------------------------------------------
+
+#if !defined(MULTIHEAP)
+SCODE CSmAllocator::Init(LPWSTR pszName)
+#else
+SCODE CSmAllocator::Init(ULONG ulHeapName, BOOL fUnmarshal)
+#endif
+{
+ SCODE sc = S_OK;
+
+#if !defined(MULTIHEAP)
+ // Initialize the mutex
+ sc = _dmtx.Init(TEXT("DocfileAllocatorMutex"));
+ if (FAILED(sc))
+ {
+ return sc;
+ }
+
+ sc = _dmtx.Take(DFM_TIMEOUT);
+ if (FAILED(sc))
+ {
+ return sc;
+ }
+#endif
+
+#if defined(_CHICAGO_)
+ //
+ // Create a new shared heap if this is the first time thru.
+ //
+ if (gs_hSharedHeap == NULL)
+ {
+ gs_hSharedHeap = HeapCreate(HEAP_SHARED, 0, 0);
+ }
+
+ //
+ // We keep a copy of the shared heap as a flag so the destructor logic
+ // does the right thing.
+ //
+ //
+ m_hSharedHeap = gs_hSharedHeap;
+
+#else
+ CSharedMemoryBlock *psmb = NULL;
+#ifdef MULTIHEAP
+ _cbSize = 0;
+ if (!fUnmarshal && this == &g_SmAllocator) // only for main thread
+ {
+ if (g_ulHeapName != 0) // the global shared memory block is active
+ {
+ _psmb = &g_smb; // needed for GetHeader
+ _pbBase = (BYTE *)(_psmb->GetBase()); // needed for GetHeader
+ if (_pbBase != NULL && GetHeader()->GetAllocedBlocks() == 0)
+ { // its' empty reuse it
+ psmb = _psmb;
+ _ulHeapName = g_ulHeapName;
+ memDebugOut ((DEB_ITRACE, "Out CSmAllocator::Init "
+ " reuse %x\n", g_ulHeapName));
+ return sc;
+ }
+ }
+ else
+ {
+ psmb = _psmb = &g_smb; // initialize g_smb
+ }
+ }
+
+ if (psmb == NULL)
+ {
+ psmb = _psmb = new CSharedMemoryBlock ();
+ if (psmb == NULL)
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ WCHAR pszName[DOCFILE_SM_NAMELEN];
+ wsprintf(pszName, L"DfSharedHeap%X", ulHeapName);
+#else
+ psmb = &_smb;
+#endif
+ // the SMB needs a few bytes for its own header. If we request
+ // a page sized allocation, those few header bytes will cause an
+ // extra page to be allocated, so to prevent that we subtract off
+ // the header space from our requests.
+
+ sc = psmb->Init(pszName,
+ DOCFILE_SM_SIZE - psmb->GetHdrSize(), // reserve size
+ INITIALHEAPSIZE - psmb->GetHdrSize(), // commit size
+ SHAREDMEMBASE, // base address
+ NULL, // security descriptor
+ TRUE); // create if doesn't exist
+
+ if (SUCCEEDED(sc))
+ {
+ _cbSize = psmb->GetSize();
+ _pbBase = (BYTE *)(psmb->GetBase());
+#ifdef MULTIHEAP
+ _ulHeapName = ulHeapName;
+#endif
+
+ if (psmb->Created())
+ {
+ CBlockHeader *pbh = (CBlockHeader *)
+ (_pbBase + sizeof(CHeapHeader));
+
+ memAssert(IsAligned(pbh));
+ pbh->SetFree();
+ pbh->SetSize(_cbSize - sizeof(CHeapHeader));
+ pbh->SetNext(0);
+
+ memAssert((BYTE *)pbh + pbh->GetSize() == _pbBase + _cbSize);
+ GetHeader()->SetFirstFree(GetOffset(pbh));
+ GetHeader()->SetCompacted();
+ GetHeader()->ResetAllocedBlocks();
+ GetHeader()->ResetLuid();
+
+#if DBG == 1
+ GetHeader()->_ulAllocedBytes = 0;
+ GetHeader()->_ulFreeBytes =
+ pbh->GetSize() - sizeof(CBlockPreHeader);
+ GetHeader()->_ulFreeBlocks = 1;
+#endif
+ }
+
+#ifdef MULTIHEAP
+ if (psmb == &g_smb)
+ g_ulHeapName = ulHeapName; // store global heap name
+#endif
+ PRINTSTATS;
+ }
+#endif
+
+#if defined(MULTIHEAP)
+ memDebugOut ((DEB_ITRACE, "Out CSmAllocator::Init sc=%x %x\n",
+ sc, ulHeapName));
+#else
+ _dmtx.Release();
+ memDebugOut ((DEB_ITRACE, "Out CSmAllocator::Init sc=%x\n",
+ sc));
+#endif
+
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::QueryInterface, public
+//
+// Synopsis: Standard QI
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CSmAllocator::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::QueryInterface:%p()\n", this));
+
+ if (IsEqualIID(iid, IID_IMalloc) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IMalloc *) this;
+ CSmAllocator::AddRef();
+ }
+ else
+ sc = E_NOINTERFACE;
+
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::QueryInterface\n"));
+
+ return ResultFromScode(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::AddRef, public
+//
+// Synopsis: Add reference
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CSmAllocator::AddRef(void)
+{
+#ifdef MULTIHEAP
+ return ++_cRefs;
+#else
+ return 1;
+#endif
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Release, public
+//
+// Synopsis: Release
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CSmAllocator::Release(void)
+{
+#ifdef MULTIHEAP
+ ULONG cRefs = --_cRefs;
+ if (cRefs <= 0)
+ delete this;
+ return cRefs;
+#else
+ return 0;
+#endif
+}
+
+#if !defined(_CHICAGO_)
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::FindBlock, private
+//
+// Synopsis: Find an appropriately sized block in the heap.
+//
+// Arguments: [cb] -- Size of block required
+//
+// Returns: Pointer to block, NULL on failure
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CBlockHeader * CSmAllocator::FindBlock(ULONG cb, CBlockHeader **ppbhPrev)
+{
+ CBlockHeader *pbhCurrent = GetAddress(GetHeader()->GetFirstFree());
+ *ppbhPrev = NULL;
+
+ while (pbhCurrent != NULL)
+ {
+ memAssert(IsAligned(pbhCurrent));
+
+ if ((pbhCurrent->GetSize() >= cb) && (pbhCurrent->IsFree()))
+ {
+ memAssert(pbhCurrent->GetSize() < _cbSize); //MULTIHEAP
+ memAssert((BYTE *)pbhCurrent >= _pbBase &&
+ (BYTE *)pbhCurrent < _pbBase + _cbSize); // MULTIHEAP
+ break;
+ }
+ else
+ {
+ memAssert (pbhCurrent->GetNext() <= _cbSize); // MULITHEAP
+ *ppbhPrev = pbhCurrent;
+ pbhCurrent = GetAddress(pbhCurrent->GetNext());
+ }
+ }
+ return pbhCurrent;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Reset, private
+//
+// Synopsis: Reset the heap to its original empty state.
+//
+// Returns: Appropriate status code
+//
+// History: 04-Apr-94 PhilipLa Created
+//
+// Notes: There is only one caller of this function. Hence it is
+// declared inline.
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CSmAllocator::Reset(void)
+{
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::Reset:%p()\n", this));
+#ifdef RESETOK
+#ifdef MULTIHEAP
+ CSharedMemoryBlock *psmb = _psmb;
+#else
+ CSharedMemoryBlock *psmb = &_smb;
+#endif
+ psmb->Reset();
+ _cbSize = psmb->GetSize();
+ _pbBase = (BYTE *)(psmb->GetBase());
+
+ CBlockHeader *pbh = (CBlockHeader *)
+ (_pbBase + sizeof(CHeapHeader));
+
+ pbh->SetFree();
+ pbh->SetSize(_cbSize - sizeof(CHeapHeader));
+ pbh->SetNext(0);
+
+ memAssert((BYTE *)pbh + pbh->GetSize() == _pbBase + _cbSize);
+ GetHeader()->SetFirstFree(GetOffset(pbh));
+ GetHeader()->SetCompacted();
+ GetHeader()->ResetAllocedBlocks();
+
+#if DBG == 1
+ GetHeader()->_ulAllocedBytes = 0;
+ GetHeader()->_ulFreeBytes =
+ pbh->GetSize() - sizeof(CBlockPreHeader);
+ GetHeader()->_ulFreeBlocks = 1;
+#endif
+
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::Reset\n"));
+#else
+ HeapMinimize();
+#endif
+ return S_OK;
+}
+
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Alloc, public
+//
+// Synopsis: Allocate memory
+//
+// Arguments: [cb] -- Number of bytes to allocate
+//
+// Returns: Pointer to block, NULL if failure
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(void *) CSmAllocator::Alloc (
+ ULONG cb )
+{
+ void *pv = NULL;
+
+#if !defined(_CHICAGO_)
+ CBlockHeader *pbh = NULL;
+ CBlockHeader *pbhPrev = NULL;
+ SCODE sc;
+#endif
+
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::Alloc:%p(%lu)\n", this, cb));
+
+#if defined(_CHICAGO_)
+
+ pv = HeapAlloc(m_hSharedHeap, 0, cb);
+
+#else // !defined(_CHICAGO_)
+#if !defined(MULTIHEAP)
+ CLockDfMutex lckdmtx(_dmtx);
+#endif
+
+ Sync();
+
+ //The block must be at least large enough to hold the standard
+ // header (size and free bit) and a pointer to the next block.
+ if (cb < sizeof(CBlockHeader) - sizeof(CBlockPreHeader))
+ {
+ cb = sizeof(CBlockHeader) - sizeof(CBlockPreHeader);
+ }
+
+ cb = cb + sizeof(CBlockPreHeader);
+
+ //Make cb 8 byte aligned.
+ if (cb & 7)
+ {
+ cb += (8 - (cb & 7));
+ }
+
+ memAssert((cb >= CBLOCKMIN) && "Undersized block requested.");
+ pbh = FindBlock(cb, &pbhPrev);
+
+ if (pbh == NULL)
+ {
+ if (!(GetHeader()->IsCompacted()))
+ {
+ //Do a heap merge and try to allocate again.
+ CSmAllocator::HeapMinimize();
+ pbh = FindBlock(cb, &pbhPrev);
+ }
+
+ if (pbh == NULL)
+ {
+#ifdef MULTIHEAP
+ CSharedMemoryBlock *psmb = _psmb;
+#else
+ CSharedMemoryBlock *psmb = &_smb;
+#endif
+#if DBG == 1
+ ULONG ulOldSize = psmb->GetSize();
+#endif
+ sc = psmb->Commit(_cbSize + max(cb, MINHEAPGROWTH));
+ if (SUCCEEDED(sc))
+ {
+ //Attach newly committed space to free list.
+ CBlockHeader *pbhNew = (CBlockHeader *)
+ (_pbBase + _cbSize);
+
+ _cbSize = psmb->GetSize();
+
+ memAssert((pbhPrev == NULL) || (pbhPrev->GetNext() == 0));
+ memAssert(_cbSize > ulOldSize);
+
+ if (pbhPrev != NULL)
+ {
+ pbhPrev->SetNext(GetOffset(pbhNew));
+ }
+ else
+ {
+ GetHeader()->SetFirstFree(GetOffset(pbhNew));
+ }
+
+ pbhNew->SetNext(0);
+ pbhNew->SetSize(max(cb, MINHEAPGROWTH));
+ pbhNew->SetFree();
+
+
+ memAssert((BYTE *)pbhNew + pbhNew->GetSize() ==
+ _pbBase + _cbSize);
+
+#if DBG == 1
+ GetHeader()->_ulFreeBytes +=
+ pbhNew->GetSize() - sizeof(CBlockPreHeader);
+ GetHeader()->_ulFreeBlocks += 1;
+#endif
+
+ pbh = pbhNew;
+ }
+ }
+ }
+
+ if (pbh != NULL)
+ {
+ //Allocate the found block.
+ if ((pbh->GetSize() > cb) &&
+ (pbh->GetSize() - cb > CBLOCKMIN))
+ {
+ //Split an existing block. No free list update required.
+
+ CBlockHeader *pbhNew =
+ (CBlockHeader *)((BYTE *)pbh + (pbh->GetSize() - cb));
+
+ pbhNew->SetSize(cb);
+ pbhNew->ResetFree();
+ pbhNew->SetNext(0);
+
+ pbh->SetSize(pbh->GetSize() - cb);
+#if DBG == 1
+ GetHeader()->_ulAllocedBytes += (cb - sizeof(CBlockPreHeader));
+ //The number of available free bytes decreases by the number
+ // of bytes allocated
+ GetHeader()->_ulFreeBytes -= cb;
+#endif
+ memAssert(IsAligned(pbhNew));
+ memAssert(IsAligned(pbh));
+
+ pbh = pbhNew;
+ }
+ else
+ {
+ //Use an entire block. Update free list appropriately.
+ memAssert(IsAligned(pbh));
+ pbh->ResetFree();
+ if (pbhPrev != NULL)
+ {
+ pbhPrev->SetNext(pbh->GetNext());;
+ }
+ else
+ {
+ GetHeader()->SetFirstFree(pbh->GetNext());
+ }
+#if DBG == 1
+ GetHeader()->_ulAllocedBytes += (cb - sizeof(CBlockPreHeader));
+ GetHeader()->_ulFreeBytes -= (cb - sizeof(CBlockPreHeader));
+ GetHeader()->_ulFreeBlocks--;
+#endif
+ pbh->SetNext(0);
+ }
+ }
+
+ if (pbh != NULL)
+ {
+ pv = (BYTE *)pbh + sizeof(CBlockPreHeader);
+ GetHeader()->IncrementAllocedBlocks();
+ }
+#endif // !defined(_CHICAGO_)
+
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::Alloc=> %p\n", pv));
+
+#if !defined(_CHICAGO_)
+ memAssert(IsAligned(pv));
+#endif // !defined(_CHICAGO_)
+
+ PRINTSTATS;
+
+#if DBG == 1
+ if (pv == NULL)
+ {
+#if defined(_CHICAGO_)
+ memDebugOut((DEB_ERROR,
+ "Failed allocation of %lu bytes.\n",
+ cb));
+#else // !defined(_CHICAGO_)
+ memDebugOut((DEB_ERROR,
+ "Failed allocation of %lu bytes. Heap size is %lu\n",
+ cb,
+ _cbSize));
+#endif // !defined(_CHICAGO_)
+ }
+#endif
+
+ return pv;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Realloc, public
+//
+// Synopsis: Resize the block given
+//
+// Arguments: [pv] -- Pointer to block to realloc
+// [cb] -- New size for block
+//
+// Returns: Pointer to new block, NULL if failure
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(void *) CSmAllocator::Realloc(
+ void *pv,
+ ULONG cb )
+{
+ void *pvNew = NULL;
+#ifdef FULLIMPL
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::Realloc:%p()\n", this));
+
+#if defined(_CHICAGO_)
+
+ pvNew = HeapReAlloc(m_hSharedHeap, 0, pv, cb);
+
+#else
+#if !defined(MULTIHEAP)
+ CLockDfMutex lckdmtx(_dmtx);
+#endif
+
+ if ((pv != NULL) && (cb == 0))
+ {
+ CSmAllocator::Free(pv);
+ return NULL;
+ }
+
+ pvNew = CSmAllocator::Alloc(cb);
+ if (pvNew != NULL && pv != NULL)
+ {
+ //Copy contents
+ memcpy(pvNew, pv, min(cb, CSmAllocator::GetSize(pv)));
+ CSmAllocator::Free(pv);
+ }
+#endif
+
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::Realloc\n"));
+#endif
+ PRINTSTATS;
+
+ return pvNew;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::DoFree, private
+//
+// Synopsis: Free a memory block
+//
+// Arguments: [pv] -- Pointer to block to free
+//
+// Returns: void
+//
+// History: 26-Jul-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+inline void CSmAllocator::DoFree(void *pv)
+{
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::DoFree:%p(%p)\n", this, pv));
+
+#if defined(_CHICAGO_)
+
+ if (pv != NULL)
+ {
+ HeapFree(m_hSharedHeap, 0, pv);
+ }
+
+#else
+
+ Sync();
+
+ if (pv != NULL)
+ {
+ CBlockHeader *pbh = (CBlockHeader *)
+ ((BYTE *)pv - sizeof(CBlockPreHeader));
+#ifdef MULTIHEAP
+ ULONG ulSize = pbh->GetSize(); // temporary to hold size for debug
+#endif
+
+ memAssert(IsAligned(pbh));
+ memAssert((BYTE*)pbh >= _pbBase &&
+ (BYTE*)pbh < _pbBase + _cbSize); // MULTIHEAP
+ pbh->SetFree();
+ pbh->SetNext(GetHeader()->GetFirstFree());
+
+ GetHeader()->SetFirstFree(GetOffset(pbh));
+ GetHeader()->ResetCompacted();
+ if (GetHeader()->DecrementAllocedBlocks() == 0)
+ {
+#ifdef MULTIHEAP
+ Uninit();
+#else
+
+ Reset();
+#endif
+ }
+
+#if DBG == 1
+ else
+ {
+ GetHeader()->_ulAllocedBytes -=
+ (pbh->GetSize() - sizeof(CBlockPreHeader));
+ GetHeader()->_ulFreeBytes +=
+ (pbh->GetSize() - sizeof(CBlockPreHeader));
+ GetHeader()->_ulFreeBlocks++;
+ }
+#endif
+#ifdef MULTIHEAP
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::DoFree. Freed %lu\n",
+ ulSize)); // don't access shared memory
+#else
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::DoFree. Freed %lu\n",
+ pbh->GetSize()));
+#endif
+ }
+#endif
+#if !defined(MULTIHEAP)
+ // the shared heap may have been unmapped, mustn't read it now
+ PRINTSTATS;
+#endif
+}
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Free, public
+//
+// Synopsis: Free a memory block
+//
+// Arguments: [pv] -- Pointer to block to free
+//
+// Returns: void
+//
+// History: 29-Mar-94 PhilipLa Created
+// 26-Jul-95 SusiA Moved bulk of work to DoFree to
+// share code between Free and
+// FreeNoMutex
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CSmAllocator::Free(void *pv)
+{
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::Free:%p(%p)\n", this, pv));
+
+#if !defined(_CHICAGO_)
+#if !defined(MULTIHEAP)
+ CLockDfMutex lckdmtx(_dmtx);
+#endif
+#endif
+ DoFree(pv);
+
+}
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::FreeNoMutex, public
+//
+// Synopsis: Free a memory block without first aquiring the mutex.
+// This function is equivalent to Free above, except that is does
+// not attempt to first aquire the mutex. It should be used OLNY
+// when the calling function guarantees to already have the mutex.
+//
+//
+// Arguments: [pv] -- Pointer to block to free
+//
+// Returns: void
+//
+// History: 19-Jul-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+void CSmAllocator::FreeNoMutex(void *pv)
+{
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::FreeNoMutex:%p(%p)\n", this, pv));
+
+#if !defined(_CHICAGO_)
+#if !defined(MULTIHEAP)
+ //ensure we already have the mutex
+ memAssert(_dmtx.HaveMutex());
+#endif
+#endif
+ DoFree(pv);
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::GetSize, public
+//
+// Synopsis: Return the size of the given block
+//
+// Arguments: [pv] -- Block to get size of
+//
+// Returns: Size of block pointer to by pv
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CSmAllocator::GetSize(void * pv)
+{
+#if !defined(_CHICAGO_)
+#if !defined(MULTIHEAP)
+ CLockDfMutex lckdmtx(_dmtx);
+#endif
+#endif
+
+ Sync();
+
+ ULONG ulSize = (ULONG)-1;
+#ifdef FULLIMPL
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::GetSize:%p()\n", this));
+ if (pv != NULL)
+ {
+#if defined(_CHICAGO_)
+ ulSize = HeapSize(m_hSharedHeap, 0, pv);
+#else
+ CBlockHeader *pbh;
+ pbh = (CBlockHeader *)((BYTE *)pv - sizeof(CBlockPreHeader));
+
+ ulSize = pbh->GetSize() - sizeof(CBlockPreHeader);
+#endif
+ }
+
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::GetSize\n"));
+#endif
+ return ulSize;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::DidAlloc, public
+//
+// Synopsis: Return '1' if this heap allocated pointer at pv
+//
+// Arguments: [pv] -- Pointer to block
+//
+// Returns: '1' == This heap allocated block.
+// '0' == This heap did not allocate block.
+// '-1' == Could not determine if this heap allocated block.
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(int) CSmAllocator::DidAlloc(void FAR * pv)
+{
+ int i = -1;
+#ifdef FULLIMPL
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::DidAlloc:%p()\n", this));
+#if defined(_CHICAGO_)
+ if (HeapValidate(m_hSharedHeap, 0, pv))
+ {
+ i = 1;
+ }
+ else
+ {
+ i = 0;
+ }
+#else // !defined(_CHICAGO_)
+#if !defined(MULTIHEAP)
+ CLockDfMutex lckdmtx(_dmtx);
+#endif
+
+ i = ((BYTE *)pv >= _pbBase) && ((BYTE *)pv <= (_pbBase + _cbSize));
+#endif // !defined(_CHICAGO_)
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::DidAlloc\n"));
+#endif
+ return i;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::HeapMinimize, public
+//
+// Synopsis: Minimize the heap
+//
+// Arguments: None.
+//
+// Returns: void.
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(void) CSmAllocator::HeapMinimize(void)
+{
+#if !defined(_CHICAGO_)
+#if !defined(MULTIHEAP)
+ CLockDfMutex lckdmtx(_dmtx);
+#endif
+#endif
+
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::HeapMinimize:%p()\n", this));
+
+ PRINTSTATS;
+
+#if defined(_CHICAGO_)
+
+ HeapCompact(m_hSharedHeap, 0);
+
+#else // !defined(_CHICAGO_)
+
+ CBlockHeader *pbhCurrent;
+ CBlockHeader *pbhLast = NULL;
+ BYTE *pbEnd = _pbBase + _cbSize;
+
+#if DBG == 1
+ PrintFreeBlocks();
+ GetHeader()->_ulAllocedBytes = 0;
+ GetHeader()->_ulFreeBytes = 0;
+ GetHeader()->_ulFreeBlocks = 0;
+#endif
+
+ pbhCurrent = (CBlockHeader *)(_pbBase + sizeof(CHeapHeader));
+
+ while ((BYTE *)pbhCurrent < pbEnd)
+ {
+ memAssert(IsAligned(pbhCurrent));
+ memAssert((pbhCurrent->GetSize != 0) &&
+ "Zero size block found.");
+ if (pbhCurrent->IsFree())
+ {
+ //Check last block. If adjacent, merge them. If not,
+ // update pbhNext.
+
+ if (pbhLast == NULL)
+ {
+ GetHeader()->SetFirstFree(GetOffset(pbhCurrent));
+#if DBG == 1
+ GetHeader()->_ulFreeBlocks = 1;
+#endif
+ }
+ else
+ {
+ if (pbhLast->GetSize() + GetOffset(pbhLast) ==
+ GetOffset(pbhCurrent))
+ {
+ //Merge the blocks.
+ pbhLast->SetSize(pbhLast->GetSize() +
+ pbhCurrent->GetSize());
+ pbhCurrent = pbhLast;
+ }
+ else
+ {
+#if DBG == 1
+ GetHeader()->_ulFreeBytes +=
+ (pbhLast->GetSize() - sizeof(CBlockPreHeader));
+ GetHeader()->_ulFreeBlocks++;
+#endif
+ pbhLast->SetNext(GetOffset(pbhCurrent));
+ }
+ }
+ pbhLast = pbhCurrent;
+ }
+#if DBG == 1
+ else
+ {
+ GetHeader()->_ulAllocedBytes +=
+ (pbhCurrent->GetSize() - sizeof(CBlockPreHeader));
+ }
+#endif
+ //Move to next block.
+ pbhCurrent =
+ (CBlockHeader *)((BYTE *)pbhCurrent + pbhCurrent->GetSize());
+ }
+
+ if (pbhLast != NULL)
+ {
+
+#if DBG == 1
+ GetHeader()->_ulFreeBytes +=
+ (pbhLast->GetSize() - sizeof(CBlockPreHeader));
+#endif
+ pbhLast->SetNext(0);
+ }
+ else
+ {
+ GetHeader()->SetFirstFree(0);
+ }
+
+ GetHeader()->SetCompacted();
+#if DBG == 1
+ PrintFreeBlocks();
+#endif
+
+#endif // !defined(_CHICAGO_)
+
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::HeapMinimize\n"));
+
+ PRINTSTATS;
+}
+
+#if !defined(_CHICAGO_)
+#if DBG == 1
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::PrintFreeBlocks, private
+//
+// Synopsis: Debug code to print sizes of free blocks
+//
+// History: 25-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+void CSmAllocator::PrintFreeBlocks(void)
+{
+ CBlockHeader *pbhCurrent = GetAddress(GetHeader()->GetFirstFree());
+
+ memDebugOut((DEB_PRINT, "There are %lu total free blocks\n",
+ GetHeader()->_ulFreeBlocks));
+
+ while (pbhCurrent != NULL)
+ {
+ memDebugOut((DEB_PRINT, "Free block %p has size %lu\n", pbhCurrent,
+ pbhCurrent->GetSize()));
+ pbhCurrent = GetAddress(pbhCurrent->GetNext());
+ }
+}
+#endif
+
+#ifdef MULTIHEAP
+#if DBG == 1
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::PrintAllocatedBlocks, private
+//
+// Synopsis: Debug code to find allocated block(s) that leaked
+//
+// History: 25-Nov-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+void CSmAllocator::PrintAllocatedBlocks(void)
+{
+ CBlockHeader *pbhCurrent;
+ CBlockHeader *pbhLast = NULL;
+ BYTE *pbEnd = _pbBase + _cbSize;
+ ULONG *pul;
+
+ pbhCurrent = (CBlockHeader *)(_pbBase + sizeof(CHeapHeader));
+
+ while ((BYTE *)pbhCurrent < pbEnd)
+ {
+ memAssert(IsAligned(pbhCurrent));
+ memAssert((pbhCurrent->GetSize != 0) && "Zero size block found.");
+ if (!pbhCurrent->IsFree())
+ {
+ pul = (ULONG *)((BYTE *)pbhCurrent + sizeof(CBlockHeader));
+ memDebugOut((DEB_PRINT, "PrintAllocatedBlocks %p %8x %8x\n",
+ pul, *pul, *(pul+1)));
+
+ }
+ pbhCurrent =
+ (CBlockHeader *)((BYTE *)pbhCurrent + pbhCurrent->GetSize());
+ }
+}
+#endif // DBG == 1
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::SetState
+//
+// Synopsis: replace thread local state by PerContext state
+//
+// History: 20-Nov-95 Henrylee Created
+//
+//----------------------------------------------------------------------------
+void CSmAllocator::SetState (CSharedMemoryBlock *psmb, BYTE * pbBase,
+ ULONG ulHeapName, CPerContext ** ppcPrev,
+ CPerContext *ppcOwner)
+{
+ olDebugOut((DEB_ITRACE, "In CSmAllocator::SetState(%p, %p, %lx, %p, %p) (this == %p)\n", psmb, pbBase, ulHeapName, ppcPrev, ppcOwner, this));
+ olDebugOut((DEB_ITRACE, "Current allocator owner == %p\n", _ppcOwner));
+
+ _psmb = psmb;
+ _pbBase = pbBase;
+ _cbSize = (_psmb) ? _psmb->GetSize() : 0;
+ _ulHeapName = ulHeapName;
+ DFBASEPTR = _pbBase;
+
+ if (ppcPrev != NULL)
+ *ppcPrev = _ppcOwner;
+ _ppcOwner = ppcOwner;
+
+ memAssert (g_smAllocator.GetBase() == DFBASEPTR);
+ olDebugOut((DEB_ITRACE, "Out CSmAllocator::SetState()\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::GetState
+//
+// Synopsis: retrive thread local allocator state into percontext
+//
+// History: 20-Nov-95 Henrylee Created
+//
+//----------------------------------------------------------------------------
+void CSmAllocator::GetState (CSharedMemoryBlock **ppsmb,
+ BYTE ** ppbBase, ULONG *pulHeapName)
+{
+ *ppsmb = _psmb;
+ *ppbBase = _pbBase;
+ *pulHeapName = _ulHeapName;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Uninit
+//
+// Synopsis: unmap the shared memory region
+//
+// History: 20-Nov-95 Henrylee Created
+//
+//----------------------------------------------------------------------------
+SCODE CSmAllocator::Uninit ()
+{
+ memDebugOut((DEB_ITRACE, "In CSmAllocator::Uninit\n"));
+ if (_psmb != NULL)
+ {
+ if (_psmb != &g_smb)
+ {
+ // This is last block in the heap, so we can close the heap
+ // now. There must be no shared heap accesses after this.
+ BOOL b = VirtualFree(_pbBase - sizeof(CSharedMemHeader),
+ 0, MEM_RELEASE);
+ delete _psmb;
+ }
+ else
+ {
+ Reset(); // for g_smb
+ }
+ _psmb = NULL;
+ }
+ _pbBase = NULL;
+ memDebugOut((DEB_ITRACE, "Out CSmAllocator::Uninit %x\n", _ulHeapName));
+
+ return S_OK;
+}
+#endif // MULTIHEAP
+
+#endif // !defined(_CHICAGO_)
diff --git a/private/ole32/stg/docfile/sngprop.cxx b/private/ole32/stg/docfile/sngprop.cxx
new file mode 100644
index 000000000..ffcf761e2
--- /dev/null
+++ b/private/ole32/stg/docfile/sngprop.cxx
@@ -0,0 +1,238 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: sngprop.cxx
+//
+// Contents: CSingleProperty implementation
+//
+// History: 13-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+#include <memalloc.h>
+#include <pbstream.hxx>
+#include <sngprop.hxx>
+#include <props.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSingleProp::Get, public
+//
+// Synopsis: Gets the value of a property
+//
+// Arguments: [pdfn] - Name
+// [pdpv] - Value to fill in
+// [pcbSize] - Data size return
+// [ppbBuffer] - Data return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pdpv]
+// [pcbSize]
+// [ppbBuffer]
+//
+// History: 13-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CSingleProp::Get(CDfName *pdfn,
+ DFPROPVAL *pdpv,
+ ULONG *pcbSize,
+ BYTE **ppbBuffer)
+{
+ CPubDocFile *pdf;
+ CPubStream *pstm;
+ SCODE sc;
+ ULONG cbRead;
+ ULONG ulOff = 0;
+ BYTE *pb;
+
+ olDebugOut((DEB_ITRACE, "In CSingleProp::Get:%p("
+ "%p, %p, %p, %p, %p)\n", this, pdfn, pdfn,
+ pdpv, pcbSize, ppbBuffer));
+ sc = _pstg->GetStream(pdfn, DF_READ | DF_DENYALL,
+ STGTY_PROPFLAG | STGTY_STREAM, &pstm);
+ if (sc == STG_E_FILENOTFOUND)
+ {
+ olChk(_pstg->GetDocFile(pdfn, DF_READ | DF_DENYALL,
+ STGTY_PROPFLAG | STGTY_STORAGE, &pdf));
+ sc = pdf->GetPropType(&pdpv->vt);
+ // If the property successfully opened as a storage then
+ // it can't have anything we can read so just close it and
+ // leave
+ pdf->CPubDocFile::vRelease();
+ return sc;
+ }
+ else if (FAILED(sc))
+ olErr(EH_Err, sc);
+ olChkTo(EH_pstm, pstm->GetPropType(&pdpv->vt));
+
+ if (pdpv->vt == VT_STREAM || pdpv->vt == VT_STREAMED_OBJECT)
+ {
+ // We don't want to touch the data in a stream-like object
+ // so just return
+ pstm->CPubStream::vRelease();
+ return sc;
+ }
+
+ olChkTo(EH_pstm, pstm->ReadAt(ulOff, pcbSize, sizeof(ULONG),
+ (ULONG STACKBASED *)&cbRead));
+ if (cbRead != sizeof(ULONG))
+ olErr(EH_pstm, STG_E_READFAULT);
+ ulOff += sizeof(ULONG);
+
+ *ppbBuffer = NULL;
+ if (VT_NOT_IN_VALUE(pdpv->vt))
+ {
+ olMemTo(EH_pstm, *ppbBuffer = (BYTE *)TaskMemAlloc(*pcbSize));
+ pb = *ppbBuffer;
+ }
+ else
+ pb = (BYTE *)&pdpv->iVal;
+ if (*pcbSize > 0)
+ {
+ olChkTo(EH_buffer, pstm->ReadAt(ulOff, pb, *pcbSize,
+ (ULONG STACKBASED *)&cbRead));
+ if (cbRead != *pcbSize)
+ olErr(EH_buffer, STG_E_READFAULT);
+ }
+ olDebugOut((DEB_ITRACE, "Out CSingleProp::Get\n"));
+ pstm->vRelease();
+ return S_OK;
+
+ EH_buffer:
+ TaskMemFree(*ppbBuffer);
+ EH_pstm:
+ pstm->vRelease();
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSingleProp::Set, public
+//
+// Synopsis: Sets the value of a property
+//
+// Arguments: [pdfn] - Name
+// [pdpv] - Property value
+// [cbSize] - Size of value
+// [pbBuffer] - Value
+//
+// Returns: Appropriate status code
+//
+// History: 13-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CSingleProp::Set(CDfName *pdfn,
+ DFPROPVAL *pdpv,
+ ULONG const cbSize,
+ BYTE *pbBuffer)
+{
+ CPubStream *pstm;
+ SCODE sc;
+ ULONG cbWritten;
+ BOOL fCreated = FALSE;
+ ULONG ulOff = 0;
+
+ olDebugOut((DEB_ITRACE, "In CSingleProp::Set:%p("
+ "%p, %p, %lu, %p)\n", this, pdfn, pdpv,
+ cbSize, pbBuffer));
+
+ // Check for existing stream property
+ sc = _pstg->GetStream(pdfn, DF_WRITE | DF_DENYALL,
+ STGTY_PROPFLAG | STGTY_STREAM, &pstm);
+ if (SUCCEEDED(sc))
+ {
+ // If it exists, truncate it so that new contents replace old
+ sc = pstm->SetSize(0);
+ if (FAILED(sc))
+ pstm->CPubStream::vRelease();
+ }
+ else if (sc == STG_E_FILENOTFOUND)
+ {
+ CPubDocFile *pstg;
+
+ // If no stream property was found, check for a storage property
+ sc = _pstg->GetDocFile(pdfn, DF_WRITE | DF_DENYALL,
+ STGTY_PROPFLAG | STGTY_STORAGE, &pstg);
+ if (SUCCEEDED(sc))
+ {
+ // If we found one, we have an error because we
+ // can't replace a storage with a stream
+ pstg->CPubDocFile::vRelease();
+ sc = STG_E_FILEALREADYEXISTS;
+ }
+ else if (sc == STG_E_FILENOTFOUND)
+ // If we didn't find anything, no property exists for the given
+ // name so we need to create one
+ sc = S_OK;
+ if (SUCCEEDED(sc))
+ {
+ // If no property exists, create one. Storage properties
+ // are created in WriteMultiple so we only need to create
+ // streams here
+ sc = _pstg->CreateStream(pdfn, DF_WRITE | DF_DENYALL,
+ STGTY_PROPFLAG | STGTY_STREAM, &pstm);
+ fCreated = TRUE;
+ }
+ }
+ // Check for any errors from the above procedure
+ olChk(sc);
+
+ olChkTo(EH_pstm, pstm->SetPropType(pdpv->vt));
+ olChkTo(EH_pstm, pstm->WriteAt(ulOff, (void *)&cbSize, sizeof(ULONG),
+ (ULONG STACKBASED *)&cbWritten));
+ if (cbWritten != sizeof(ULONG))
+ olErr(EH_pstm, STG_E_WRITEFAULT);
+ ulOff += sizeof(ULONG);
+ if (cbSize > 0)
+ {
+ olAssert(pbBuffer != NULL);
+ olChkTo(EH_pstm, pstm->WriteAt(ulOff, pbBuffer, cbSize,
+ (ULONG STACKBASED *)&cbWritten));
+ if (cbWritten != cbSize)
+ olErr(EH_pstm, STG_E_WRITEFAULT);
+ }
+ olDebugOut((DEB_ITRACE, "Out CSingleProp::Set\n"));
+ // Fall through
+ EH_pstm:
+ pstm->vRelease();
+ if (FAILED(sc) && fCreated)
+ olVerSucc(_pstg->DestroyEntry(pdfn, TRUE));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSingleProp::Exists, public
+//
+// Synopsis: Determines whether a given property exists or not
+//
+// Arguments: [pdfn] - Name
+//
+// Returns: Appropriate status code
+//
+// History: 12-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CSingleProp::Exists(CDfName *pdfn)
+{
+ SEntryBuffer eb;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CSingleProp::Exists:%p(%d:%ws)\n",
+ this, pdfn->GetLength(), pdfn->GetBuffer()));
+ sc = _pstg->IsEntry(pdfn, &eb);
+ olDebugOut((DEB_ITRACE, "Out CSingleProp::Exists => 0x%lX\n", sc));
+ return sc;
+}
diff --git a/private/ole32/stg/docfile/tests/based.cxx b/private/ole32/stg/docfile/tests/based.cxx
new file mode 100644
index 000000000..c3023ee0d
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/based.cxx
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#pragma hdrstop
+
+void *pvBase;
+#define BASE_BASED __based(pvBase)
+
+void BASE_BASED *Alloc(int size)
+{
+ ULONG ul;
+
+ ul = (ULONG)size;
+ return (void BASE_BASED *)ul;
+}
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ ULONG BASE_BASED *pul;
+
+ pvBase = 0;
+
+ pul = (ULONG BASE_BASED *)Alloc(sizeof(ULONG));
+ if (*pul != 0)
+ *pul = 0;
+}
diff --git a/private/ole32/stg/docfile/tests/casein.cxx b/private/ole32/stg/docfile/tests/casein.cxx
new file mode 100644
index 000000000..40601fad4
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/casein.cxx
@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tsupp.hxx"
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg, *pstgEm;
+ IStream *pst;
+ IEnumSTATSTG *penm;
+ STATSTG stat;
+
+ StartTest("casein");
+ CmdArgs(argc, argv);
+ printf("Create root docfile = %lX\n",
+ StgCreateDocfile(TEXT("TEST.DFL"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pstg));
+ printf("Create stream = %lX\n",
+ pstg->CreateStream(TEXT("TestSt"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pst));
+ printf("Create embedded docfile = %lX\n",
+ pstg->CreateStorage(TEXT("TEST"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstgEm));
+ printf("Commit embedded docfile = %lX\n",
+ pstgEm->Commit(0));
+ printf("Release embedded docfile = %lX\n",
+ pstgEm->Release());
+ printf("Commit stream = %lX\n",
+ pst->Commit(0));
+ printf("Release stream = %lX\n",
+ pst->Release());
+
+ printf("Open stream = %lX\n",
+ pstg->OpenStream(TEXT("tEsTst"), NULL, STMP(STGM_RW), 0, &pst));
+ if (pst == NULL)
+ {
+ printf("** ERROR: Unable to open stream\n");
+ exit(1);
+ }
+ printf("Open embedded docfile = %lX\n",
+ pstg->OpenStorage(TEXT("test"), NULL, STGP(STGM_RW),
+ NULL, 0, &pstgEm));
+ if (pstgEm == NULL)
+ {
+ printf("** ERROR: Unable to open embedded docfile\n");
+ exit(1);
+ }
+ printf("Release embedded docfile = %lX\n",
+ pstgEm->Release());
+ printf("Release root stream = %lX\n",
+ pst->Release());
+
+ printf("Get enumerator = %lX\n",
+ pstg->EnumElements(0, 0, 0, &penm));
+ printf("Next = %lX\n",
+ penm->Next(1, &stat, NULL));
+ if (!strcmp(stat.pwcsName, TEXT("TestSt")) &&
+ !strcmp(stat.pwcsName, TEXT("TEST")))
+ {
+ printf("** ERROR: Unknown name '%s'\n", stat.pwcsName);
+ exit(1);
+ }
+ MemFree(stat.pwcsName);
+ printf("Next = %lX\n",
+ penm->Next(1, &stat, NULL));
+ if (!strcmp(stat.pwcsName, TEXT("TestSt")) &&
+ !strcmp(stat.pwcsName, TEXT("TEST")))
+ {
+ printf("** ERROR: Unknown name '%s'\n", stat.pwcsName);
+ exit(1);
+ }
+ MemFree(stat.pwcsName);
+
+ printf("Release enumerator = %lX\n",
+ penm->Release());
+ printf("Release root docfile = %lX\n",
+ pstg->Release());
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/cmtovr.cxx b/private/ole32/stg/docfile/tests/cmtovr.cxx
new file mode 100644
index 000000000..0a9dcad29
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/cmtovr.cxx
@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+// #define CINTERFACE
+
+#include "tsupp.hxx"
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ ULONG cbWritten;
+ IStorage *pstg;
+ IStream *pstm;
+
+ StartTest("cmtovr");
+ CmdArgs(argc, argv);
+ printf("Create root docfile = %lX\n",
+ StgCreateDocfile(TEXT("test.dfl"), ROOTP(STGM_RW) | STGM_CREATE,
+ 0, &pstg));
+ printf("Create stream = %lX\n",
+ Mthd(pstg, CreateStream)(SELF(pstg)
+ TEXT("Stream"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, &pstm));
+ printf("Commit storage = %lX\n",
+ Mthd(pstg, Commit)(SELF(pstg) STGC_OVERWRITE));
+ printf("Release stream = %lX\n",
+ Mthd(pstm, Release)(SELF(pstm)));
+ printf("Release storage = %lX\n",
+ Mthd(pstg, Release)(SELF(pstg)));
+ printf("Open root docfile = %lX\n",
+ StgOpenStorage(TEXT("test.dfl"), NULL, ROOTP(STGM_RW), NULL, 0,
+ &pstg));
+ printf("Open stream = %lX\n",
+ Mthd(pstg, OpenStream)(SELF(pstg)
+ TEXT("Stream"), NULL, STMP(STGM_RW), 0,
+ &pstm));
+ printf("Write to stream = %lX\n",
+ Mthd(pstm, Write)(SELF(pstm) "FOO", 3, &cbWritten));
+ printf("Wrote %lu\n", cbWritten);
+ printf("Commit storage = %lX\n",
+ Mthd(pstg, Commit)(SELF(pstg) STGC_OVERWRITE));
+ printf("Release stream = %lX\n",
+ Mthd(pstm, Release)(SELF(pstm)));
+ printf("Release storage = %lX\n",
+ Mthd(pstg, Release)(SELF(pstg)));
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/copyto.cxx b/private/ole32/stg/docfile/tests/copyto.cxx
new file mode 100644
index 000000000..6ad9396bc
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/copyto.cxx
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tsupp.hxx"
+
+#define DATA "1234567890123456789012345678901234567890"
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg;
+ IStream *pst, *pstC;
+ char buf[256];
+ ULONG cbRead;
+
+ CmdArgs(argc, argv);
+ printf("Create root docfile = %lX\n",
+ StgCreateDocfile(TEXT("TEST.DFL"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pstg));
+ printf("Create root stream = %lX\n",
+ pstg->CreateStream(TEXT("TestSt"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, &pst));
+ printf("Clone root stream = %lX\n",
+ pst->Clone(&pstC));
+ printf("Write data into stream = %lX\n",
+ pst->Write(DATA, sizeof(DATA), NULL));
+ printf("Seek to 15 = %lX\n",
+ pst->Seek(15, STREAM_SEEK_SET, NULL));
+ printf("CopyTo 25 back = %lX\n",
+ pst->CopyTo(pstC, 25, NULL, NULL));
+ printf("Seek to 0 = %lx\n",
+ pst->Seek(0, STREAM_SEEK_SET, NULL));
+ printf("Read = %lX\n",
+ pst->Read(buf, sizeof(buf), &cbRead));
+ printf("Contents are %lu: '%s'\n", cbRead, buf);
+ printf("Seek to 5 = %lX\n",
+ pst->Seek(5, STREAM_SEEK_SET, NULL));
+ printf("Seek clone to 12 = %lX\n",
+ pstC->Seek(12, STREAM_SEEK_SET, NULL));
+ printf("CopyTo 13 forward = %lX\n",
+ pst->CopyTo(pstC, 13, NULL, NULL));
+ printf("Seek to 0 = %lx\n",
+ pst->Seek(0, STREAM_SEEK_SET, NULL));
+ printf("Read = %lX\n",
+ pst->Read(buf, sizeof(buf), &cbRead));
+ printf("Contents are %lu: '%s'\n", cbRead, buf);
+ printf("Release clone = %lX\n",
+ pstC->Release());
+ printf("Release root stream = %lX\n",
+ pst->Release());
+ printf("Release root docfile = %lX\n",
+ pstg->Release());
+}
diff --git a/private/ole32/stg/docfile/tests/cpy.cxx b/private/ole32/stg/docfile/tests/cpy.cxx
new file mode 100644
index 000000000..85a5ff144
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/cpy.cxx
@@ -0,0 +1,40 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "tsupp.hxx"
+
+#define ITERS 25
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ IStorage *pstgFrom, *pstgTo;
+ int i;
+ SCODE sc;
+
+ if (argc != 2)
+ {
+ printf("Usage: %s docfile\n", argv[0]);
+ exit(1);
+ }
+ sc = StgOpenStorage(argv[1], NULL, ROOTP(STGM_READ), NULL, 0, &pstgFrom);
+ if (FAILED(sc))
+ {
+ printf("Can't open %s, %lX\n", argv[1], sc);
+ exit(1);
+ }
+ for (i = 0; i<ITERS; i++)
+ {
+ printf("Iteration %d of %d\n", i+1, ITERS);
+ sc = StgCreateDocfile(TEXT("CPY.DFL"), ROOTP(STGM_WRITE) |
+ STGM_CREATE, 0, &pstgTo);
+ if (FAILED(sc))
+ {
+ printf("Can't open destination, %lX\n", sc);
+ exit(1);
+ }
+ sc = pstgFrom->CopyTo(pstgTo);
+ if (FAILED(sc))
+ printf("Copy failed with %lX\n", sc);
+ pstgTo->Release();
+ }
+ pstgFrom->Release();
+}
diff --git a/private/ole32/stg/docfile/tests/delonr.cxx b/private/ole32/stg/docfile/tests/delonr.cxx
new file mode 100644
index 000000000..1e5adfb94
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/delonr.cxx
@@ -0,0 +1,87 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: delonr.cxx
+//
+// Contents: STGM_DELETEONRELEASE test
+//
+// History: 22-Oct-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+// #define CINTERFACE
+
+TCHAR dfname[_MAX_PATH];
+char *dffile = NULL;
+
+void check_exist(void)
+{
+ char nm[_MAX_PATH];
+ OFSTRUCT of;
+
+ TTOA(dfname, nm, _MAX_PATH);
+ if (OpenFile(nm, &of, OF_EXIST) != HFILE_ERROR)
+ Fail("File exists\n");
+}
+
+void RunArgs(int argc, char *argv[])
+{
+ int i;
+
+ for (i = 1; i<argc; i++)
+ if (argv[i][0] == '-')
+ switch(argv[i][1])
+ {
+ case 'n':
+ dffile = argv[i]+2;
+ break;
+ }
+}
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg;
+
+ StartTest("delonr");
+ CmdArgs(argc, argv);
+ RunArgs(argc, argv);
+
+ CreateTestFile(dffile, ROOTP(STGM_RW) | STGM_CREATE | STGM_DELETEONRELEASE,
+ FALSE, &pstg, dfname);
+ Mthd(pstg, Release)(SELF(pstg));
+ check_exist();
+ CreateTestFile(dffile, ROOTP(STGM_RW) | STGM_CREATE | STGM_DELETEONRELEASE,
+ FALSE, &pstg, dfname);
+#ifndef WIN32
+ IStorage *pstg2;
+ IStream *pstm;
+ HRESULT hr;
+
+ hr = Mthd(pstg, CreateStream)(SELF(pstg) TEXT("test"), STMP(STGM_RW) |
+ STGM_DELETEONRELEASE, 0, 0, &pstm);
+ IllResult(hr, "CreateStream DOR");
+ hr = Mthd(pstg, OpenStream)(SELF(pstg) TEXT("test"), NULL,
+ STMP(STGM_RW) | STGM_DELETEONRELEASE,
+ 0, &pstm);
+ IllResult(hr, "OpenStream DOR");
+ hr = Mthd(pstg, CreateStorage)(SELF(pstg) TEXT("test"), STGP(STGM_RW) |
+ STGM_DELETEONRELEASE, 0, 0, &pstg2);
+ IllResult(hr, "CreateStorage DOR");
+ hr = Mthd(pstg, OpenStorage)(SELF(pstg) TEXT("test"), NULL,
+ STGP(STGM_RW) | STGM_DELETEONRELEASE,
+ NULL, 0, &pstg2);
+ IllResult(hr, "OpenStorage DOR");
+#endif
+ Mthd(pstg, Release)(SELF(pstg));
+ check_exist();
+
+ OpenTestFile(dffile, ROOTP(STGM_RW) | STGM_DELETEONRELEASE, TRUE,
+ &pstg, NULL);
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/depend.cxx b/private/ole32/stg/docfile/tests/depend.cxx
new file mode 100644
index 000000000..a65f36c9a
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/depend.cxx
@@ -0,0 +1,15 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: depend.cxx
+//
+// Contents: Dependency file
+//
+// History: 03-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
diff --git a/private/ole32/stg/docfile/tests/depend.mk1 b/private/ole32/stg/docfile/tests/depend.mk1
new file mode 100644
index 000000000..9fec64ca7
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/depend.mk1
@@ -0,0 +1,131 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\$(NAME).obj $(OBJDIR)\$(NAME).lst: .\$(NAME).cxx \
+ $(COMMON)\ih\Base32K.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\types.h $(COMMON)\ih\winnot.h \
+ $(COMMONINC)\baseole.h $(COMMONINC)\basetyps.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\idltyps.h \
+ $(COMMONINC)\itabls.h $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h \
+ $(COMMONINC)\prspec.h $(COMMONINC)\querys.h $(COMMONINC)\scode.h \
+ $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h $(COMMONINC)\valid.h \
+ $(COMMONINC)\varnt.h $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\time.h $(OLE)\docfile\tests\tutils.hxx \
+ $(OLE)\h\dfdeb.hxx $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx \
+ $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx $(OLE)\h\wchar.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\pch.cxx .\tsupp.hxx
+
+$(OBJDIR)\tutils.obj $(OBJDIR)\tutils.lst: .\tutils.cxx \
+ $(COMMON)\ih\Base32K.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\types.h $(COMMON)\ih\winnot.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\prspec.h $(COMMONINC)\varnt.h \
+ $(COMMONINC)\wtypes.h $(COMMONINC)\baseole.h $(COMMONINC)\basetyps.h \
+ $(COMMONINC)\cguid.h $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h \
+ $(COMMONINC)\dispatch.h $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h \
+ $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h $(COMMONINC)\ole2.h \
+ $(COMMONINC)\oletyp.h $(COMMONINC)\prspec.h $(COMMONINC)\querys.h \
+ $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h \
+ $(COMMONINC)\valid.h $(COMMONINC)\varnt.h $(COMMONINC)\winole.h \
+ $(COMMONINC)\wtypes.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(CRTINC)\time.h \
+ $(OLE)\docfile\tests\tutils.hxx $(OLE)\h\dfdeb.hxx $(OLE)\h\dfmem.hxx \
+ $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx \
+ $(OLE)\h\wchar.h $(OSINC)\rpc.h $(OSINC)\cderr.h $(OSINC)\commdlg.h \
+ $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\pch.cxx .\tsupp.hxx
+
+$(OBJDIR)\tsupp.obj $(OBJDIR)\tsupp.lst: .\tsupp.cxx \
+ $(COMMON)\ih\Base32K.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\types.h $(COMMON)\ih\winnot.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\wtypes.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\cguid.h $(COMMONINC)\cobjerr.h \
+ $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h $(COMMONINC)\disptype.h \
+ $(COMMONINC)\dsbase.h $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h \
+ $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\querys.h $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h \
+ $(COMMONINC)\stgprop.h $(COMMONINC)\valid.h $(COMMONINC)\varnt.h \
+ $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\time.h $(OLE)\docfile\tests\tutils.hxx \
+ $(OLE)\h\dfdeb.hxx $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx \
+ $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx $(OLE)\h\wchar.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\pch.cxx .\tsupp.hxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\pch.pxh $(PCHDIR)\$(OBJDIR)\pch.lst: \
+ $(OLE)\docfile\tests\pch.cxx $(COMMON)\ih\Base32K.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\baseole.h $(COMMONINC)\basetyps.h \
+ $(COMMONINC)\cguid.h $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h \
+ $(COMMONINC)\dispatch.h $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h \
+ $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h $(COMMONINC)\ole2.h \
+ $(COMMONINC)\oletyp.h $(COMMONINC)\prspec.h $(COMMONINC)\querys.h \
+ $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h \
+ $(COMMONINC)\valid.h $(COMMONINC)\varnt.h $(COMMONINC)\winole.h \
+ $(COMMONINC)\wtypes.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(CRTINC)\time.h \
+ $(OLE)\docfile\tests\tsupp.hxx $(OLE)\docfile\tests\tutils.hxx \
+ $(OLE)\h\dfdeb.hxx $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx \
+ $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx $(OLE)\h\wchar.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
+.\$(OBJDIR)\$(NAME).obj : $(PCHDIR)\$(OBJDIR)\pch.pxh
+.\$(OBJDIR)\tutils.obj : $(PCHDIR)\$(OBJDIR)\pch.pxh
+.\$(OBJDIR)\tsupp.obj : $(PCHDIR)\$(OBJDIR)\pch.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/docfile/tests/depend.mk3 b/private/ole32/stg/docfile/tests/depend.mk3
new file mode 100644
index 000000000..98fefa386
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/depend.mk3
@@ -0,0 +1,145 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\$(NAME).obj $(OBJDIR)\$(NAME).lst: .\$(NAME).cxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\time.h $(OLE)\docfile\tests\tutils.hxx \
+ $(OLE)\h\dfdeb.hxx $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx \
+ $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx $(OLE)\h\wchar.h .\pch.cxx \
+ .\tsupp.hxx d:\nt\public\sdk\inc\cderr.h \
+ d:\nt\public\sdk\inc\cobjerr.h d:\nt\public\sdk\inc\coguid.h \
+ d:\nt\public\sdk\inc\commdlg.h d:\nt\public\sdk\inc\compobj.h \
+ d:\nt\public\sdk\inc\dde.h d:\nt\public\sdk\inc\ddeml.h \
+ d:\nt\public\sdk\inc\dlgs.h d:\nt\public\sdk\inc\drivinit.h \
+ d:\nt\public\sdk\inc\dvobj.h d:\nt\public\sdk\inc\initguid.h \
+ d:\nt\public\sdk\inc\lzexpand.h d:\nt\public\sdk\inc\mmsystem.h \
+ d:\nt\public\sdk\inc\moniker.h d:\nt\public\sdk\inc\nb30.h \
+ d:\nt\public\sdk\inc\ole.h d:\nt\public\sdk\inc\ole2.h \
+ d:\nt\public\sdk\inc\oleguid.h d:\nt\public\sdk\inc\rpc.h \
+ d:\nt\public\sdk\inc\rpcdce.h d:\nt\public\sdk\inc\rpcdce2.h \
+ d:\nt\public\sdk\inc\rpcdcep.h d:\nt\public\sdk\inc\rpcferr.h \
+ d:\nt\public\sdk\inc\rpcnsi.h d:\nt\public\sdk\inc\rpcnterr.h \
+ d:\nt\public\sdk\inc\scode.h d:\nt\public\sdk\inc\shellapi.h \
+ d:\nt\public\sdk\inc\storage.h d:\nt\public\sdk\inc\valid.h \
+ d:\nt\public\sdk\inc\winbase.h d:\nt\public\sdk\inc\wincon.h \
+ d:\nt\public\sdk\inc\windef.h d:\nt\public\sdk\inc\windows.h \
+ d:\nt\public\sdk\inc\winerror.h d:\nt\public\sdk\inc\wingdi.h \
+ d:\nt\public\sdk\inc\winnetwk.h d:\nt\public\sdk\inc\winnls.h \
+ d:\nt\public\sdk\inc\winnt.h d:\nt\public\sdk\inc\winperf.h \
+ d:\nt\public\sdk\inc\winreg.h d:\nt\public\sdk\inc\winsock.h \
+ d:\nt\public\sdk\inc\winspool.h d:\nt\public\sdk\inc\winsvc.h \
+ d:\nt\public\sdk\inc\winuser.h d:\nt\public\sdk\inc\winver.h
+
+$(OBJDIR)\tutils.obj $(OBJDIR)\tutils.lst: .\tutils.cxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\time.h $(OLE)\docfile\tests\tutils.hxx \
+ $(OLE)\h\dfdeb.hxx $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx \
+ $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx $(OLE)\h\wchar.h .\pch.cxx \
+ .\tsupp.hxx d:\nt\public\sdk\inc\cderr.h \
+ d:\nt\public\sdk\inc\cobjerr.h d:\nt\public\sdk\inc\coguid.h \
+ d:\nt\public\sdk\inc\commdlg.h d:\nt\public\sdk\inc\compobj.h \
+ d:\nt\public\sdk\inc\dde.h d:\nt\public\sdk\inc\ddeml.h \
+ d:\nt\public\sdk\inc\dlgs.h d:\nt\public\sdk\inc\drivinit.h \
+ d:\nt\public\sdk\inc\dvobj.h d:\nt\public\sdk\inc\initguid.h \
+ d:\nt\public\sdk\inc\lzexpand.h d:\nt\public\sdk\inc\mmsystem.h \
+ d:\nt\public\sdk\inc\moniker.h d:\nt\public\sdk\inc\nb30.h \
+ d:\nt\public\sdk\inc\ole.h d:\nt\public\sdk\inc\ole2.h \
+ d:\nt\public\sdk\inc\oleguid.h d:\nt\public\sdk\inc\rpc.h \
+ d:\nt\public\sdk\inc\rpcdce.h d:\nt\public\sdk\inc\rpcdce2.h \
+ d:\nt\public\sdk\inc\rpcdcep.h d:\nt\public\sdk\inc\rpcferr.h \
+ d:\nt\public\sdk\inc\rpcnsi.h d:\nt\public\sdk\inc\rpcnterr.h \
+ d:\nt\public\sdk\inc\scode.h d:\nt\public\sdk\inc\shellapi.h \
+ d:\nt\public\sdk\inc\storage.h d:\nt\public\sdk\inc\valid.h \
+ d:\nt\public\sdk\inc\winbase.h d:\nt\public\sdk\inc\wincon.h \
+ d:\nt\public\sdk\inc\windef.h d:\nt\public\sdk\inc\windows.h \
+ d:\nt\public\sdk\inc\winerror.h d:\nt\public\sdk\inc\wingdi.h \
+ d:\nt\public\sdk\inc\winnetwk.h d:\nt\public\sdk\inc\winnls.h \
+ d:\nt\public\sdk\inc\winnt.h d:\nt\public\sdk\inc\winperf.h \
+ d:\nt\public\sdk\inc\winreg.h d:\nt\public\sdk\inc\winsock.h \
+ d:\nt\public\sdk\inc\winspool.h d:\nt\public\sdk\inc\winsvc.h \
+ d:\nt\public\sdk\inc\winuser.h d:\nt\public\sdk\inc\winver.h
+
+$(OBJDIR)\tsupp.obj $(OBJDIR)\tsupp.lst: .\tsupp.cxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(CRTINC)\time.h \
+ $(OLE)\docfile\tests\tutils.hxx $(OLE)\h\dfdeb.hxx $(OLE)\h\dfmem.hxx \
+ $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx \
+ $(OLE)\h\wchar.h .\pch.cxx .\tsupp.hxx d:\nt\public\sdk\inc\cderr.h \
+ d:\nt\public\sdk\inc\cobjerr.h d:\nt\public\sdk\inc\coguid.h \
+ d:\nt\public\sdk\inc\commdlg.h d:\nt\public\sdk\inc\compobj.h \
+ d:\nt\public\sdk\inc\dde.h d:\nt\public\sdk\inc\ddeml.h \
+ d:\nt\public\sdk\inc\dlgs.h d:\nt\public\sdk\inc\drivinit.h \
+ d:\nt\public\sdk\inc\dvobj.h d:\nt\public\sdk\inc\initguid.h \
+ d:\nt\public\sdk\inc\lzexpand.h d:\nt\public\sdk\inc\mmsystem.h \
+ d:\nt\public\sdk\inc\moniker.h d:\nt\public\sdk\inc\nb30.h \
+ d:\nt\public\sdk\inc\ole.h d:\nt\public\sdk\inc\ole2.h \
+ d:\nt\public\sdk\inc\oleguid.h d:\nt\public\sdk\inc\rpc.h \
+ d:\nt\public\sdk\inc\rpcdce.h d:\nt\public\sdk\inc\rpcdce2.h \
+ d:\nt\public\sdk\inc\rpcdcep.h d:\nt\public\sdk\inc\rpcferr.h \
+ d:\nt\public\sdk\inc\rpcnsi.h d:\nt\public\sdk\inc\rpcnterr.h \
+ d:\nt\public\sdk\inc\scode.h d:\nt\public\sdk\inc\shellapi.h \
+ d:\nt\public\sdk\inc\storage.h d:\nt\public\sdk\inc\valid.h \
+ d:\nt\public\sdk\inc\winbase.h d:\nt\public\sdk\inc\wincon.h \
+ d:\nt\public\sdk\inc\windef.h d:\nt\public\sdk\inc\windows.h \
+ d:\nt\public\sdk\inc\winerror.h d:\nt\public\sdk\inc\wingdi.h \
+ d:\nt\public\sdk\inc\winnetwk.h d:\nt\public\sdk\inc\winnls.h \
+ d:\nt\public\sdk\inc\winnt.h d:\nt\public\sdk\inc\winperf.h \
+ d:\nt\public\sdk\inc\winreg.h d:\nt\public\sdk\inc\winsock.h \
+ d:\nt\public\sdk\inc\winspool.h d:\nt\public\sdk\inc\winsvc.h \
+ d:\nt\public\sdk\inc\winuser.h d:\nt\public\sdk\inc\winver.h
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\pch.pxh $(PCHDIR)\$(OBJDIR)\pch.lst: \
+ $(OLE)\docfile\tests\pch.cxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\time.h $(OLE)\docfile\tests\tsupp.hxx \
+ $(OLE)\docfile\tests\tutils.hxx $(OLE)\h\dfdeb.hxx $(OLE)\h\dfmem.hxx \
+ $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx \
+ $(OLE)\h\wchar.h d:\nt\public\sdk\inc\cderr.h \
+ d:\nt\public\sdk\inc\cobjerr.h d:\nt\public\sdk\inc\coguid.h \
+ d:\nt\public\sdk\inc\commdlg.h d:\nt\public\sdk\inc\compobj.h \
+ d:\nt\public\sdk\inc\dde.h d:\nt\public\sdk\inc\ddeml.h \
+ d:\nt\public\sdk\inc\dlgs.h d:\nt\public\sdk\inc\drivinit.h \
+ d:\nt\public\sdk\inc\dvobj.h d:\nt\public\sdk\inc\initguid.h \
+ d:\nt\public\sdk\inc\lzexpand.h d:\nt\public\sdk\inc\mmsystem.h \
+ d:\nt\public\sdk\inc\moniker.h d:\nt\public\sdk\inc\nb30.h \
+ d:\nt\public\sdk\inc\ole.h d:\nt\public\sdk\inc\ole2.h \
+ d:\nt\public\sdk\inc\oleguid.h d:\nt\public\sdk\inc\rpc.h \
+ d:\nt\public\sdk\inc\rpcdce.h d:\nt\public\sdk\inc\rpcdce2.h \
+ d:\nt\public\sdk\inc\rpcdcep.h d:\nt\public\sdk\inc\rpcferr.h \
+ d:\nt\public\sdk\inc\rpcnsi.h d:\nt\public\sdk\inc\rpcnterr.h \
+ d:\nt\public\sdk\inc\scode.h d:\nt\public\sdk\inc\shellapi.h \
+ d:\nt\public\sdk\inc\storage.h d:\nt\public\sdk\inc\valid.h \
+ d:\nt\public\sdk\inc\winbase.h d:\nt\public\sdk\inc\wincon.h \
+ d:\nt\public\sdk\inc\windef.h d:\nt\public\sdk\inc\windows.h \
+ d:\nt\public\sdk\inc\winerror.h d:\nt\public\sdk\inc\wingdi.h \
+ d:\nt\public\sdk\inc\winnetwk.h d:\nt\public\sdk\inc\winnls.h \
+ d:\nt\public\sdk\inc\winnt.h d:\nt\public\sdk\inc\winperf.h \
+ d:\nt\public\sdk\inc\winreg.h d:\nt\public\sdk\inc\winsock.h \
+ d:\nt\public\sdk\inc\winspool.h d:\nt\public\sdk\inc\winsvc.h \
+ d:\nt\public\sdk\inc\winuser.h d:\nt\public\sdk\inc\winver.h
+
+.\$(OBJDIR)\$(NAME).obj : $(PCHDIR)\$(OBJDIR)\pch.pxh
+.\$(OBJDIR)\tutils.obj : $(PCHDIR)\$(OBJDIR)\pch.pxh
+.\$(OBJDIR)\tsupp.obj : $(PCHDIR)\$(OBJDIR)\pch.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/docfile/tests/depend.mk9 b/private/ole32/stg/docfile/tests/depend.mk9
new file mode 100644
index 000000000..70d4f1c96
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/depend.mk9
@@ -0,0 +1,56 @@
+#
+# Source files
+#
+
+$(OBJDIR)\$(NAME).obj $(OBJDIR)\$(NAME).lst: .\$(NAME).cxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(CRTINC)\time.h \
+ $(OLE)\h\dfdeb.hxx $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx \
+ $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx $(OLE)\h\wchar.h \
+ $(OLE)\ole2h\coguid.h $(OLE)\ole2h\compobj.h $(OLE)\ole2h\initguid.h \
+ $(OLE)\ole2h\scode.h $(OLE)\ole2h\storage.h $(OLE)\ole2h\valid.h \
+ $(OSINC)\windows.h .\pch.cxx .\tsupp.hxx .\tutils.hxx
+
+$(OBJDIR)\tutils.obj $(OBJDIR)\tutils.lst: .\tutils.cxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(CRTINC)\time.h \
+ $(OLE)\h\dfdeb.hxx $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx \
+ $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx $(OLE)\h\wchar.h \
+ $(OLE)\ole2h\coguid.h $(OLE)\ole2h\compobj.h $(OLE)\ole2h\initguid.h \
+ $(OLE)\ole2h\scode.h $(OLE)\ole2h\storage.h $(OLE)\ole2h\valid.h \
+ $(OSINC)\windows.h .\pch.cxx .\tsupp.hxx .\tutils.hxx
+
+$(OBJDIR)\tsupp.obj $(OBJDIR)\tsupp.lst: .\tsupp.cxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(CRTINC)\time.h \
+ $(OLE)\h\dfdeb.hxx $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx \
+ $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx $(OLE)\h\wchar.h \
+ $(OLE)\ole2h\coguid.h $(OLE)\ole2h\compobj.h $(OLE)\ole2h\initguid.h \
+ $(OLE)\ole2h\scode.h $(OLE)\ole2h\storage.h $(OLE)\ole2h\valid.h \
+ $(OSINC)\windows.h .\pch.cxx .\tsupp.hxx .\tutils.hxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(OBJDIR)\pch.pxx pch.lst: pch.cxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\memory.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\time.h $(OLE)\h\dfdeb.hxx \
+ $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx \
+ $(OLE)\h\ref.hxx $(OLE)\h\wchar.h $(OLE)\ole2h\coguid.h \
+ $(OLE)\ole2h\compobj.h $(OLE)\ole2h\initguid.h $(OLE)\ole2h\scode.h \
+ $(OLE)\ole2h\storage.h $(OLE)\ole2h\valid.h $(OSINC)\windows.h \
+ .\tutils.hxx tsupp.hxx
+
+.\$(OBJDIR)\$(NAME).obj : $(OBJDIR)\pch.pxx
+.\$(OBJDIR)\tutils.obj : $(OBJDIR)\pch.pxx
+.\$(OBJDIR)\tsupp.obj : $(OBJDIR)\pch.pxx
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/docfile/tests/dfgc.cxx b/private/ole32/stg/docfile/tests/dfgc.cxx
new file mode 100644
index 000000000..64e70a069
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/dfgc.cxx
@@ -0,0 +1,49 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dfgc.cxx
+//
+// Contents: Test DfGetClass
+//
+// History: 03-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg;
+ HRESULT hr;
+ CLSID clsid;
+ HANDLE h;
+ TCHAR tchName[_MAX_PATH];
+
+ StartTest("dfgc");
+ CmdArgs(argc, argv);
+
+ CreateTestFile(NULL, ROOTP(STGM_RW) | STGM_CREATE, FALSE, &pstg,
+ tchName);
+ hr = pstg->SetClass(IID_IStorage);
+ Result(hr, "SetClass");
+ hr = pstg->Commit(0);
+ Result(hr, "Commit");
+ pstg->Release();
+
+ h = CreateFile(tchName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ Fail("Unable to open '%s'\n", TcsText(tchName));
+
+ hr = DfGetClass(h, &clsid);
+ Result(hr, "DfGetClass");
+ if (!IsEqualIID(clsid, IID_IStorage))
+ Fail("DfGetClass returned class ID %s\n", GuidText(&clsid));
+
+ CloseHandle(h);
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/dftct.cxx b/private/ole32/stg/docfile/tests/dftct.cxx
new file mode 100644
index 000000000..21b736bc0
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/dftct.cxx
@@ -0,0 +1,412 @@
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dos.h>
+#include <direct.h>
+#include <io.h>
+#include <string.h>
+#ifdef FLAT
+#include <windows.h>
+#endif
+#include "tsupp.hxx"
+#include <dfmsp.hxx>
+#include <dfdeb.hxx>
+
+#define RPERMS ROOTP(STGM_RW)
+#define STGPERMS STGP(STGM_RW)
+#define STMPERMS STMP(STGM_RW)
+
+#define BUFFERSIZE 65535
+BYTE bBuffer[BUFFERSIZE];
+BYTE bCompare[BUFFERSIZE];
+
+#define WILD_CARD "\\*.*"
+#define FIND_ATTRS (_A_SUBDIR | _A_NORMAL | _A_RDONLY | _A_HIDDEN)
+
+void pexit(char *fmt, ...)
+{
+ va_list args;
+
+ args = va_start(args, fmt);
+ fprintf(stderr, "Fatal error: ");
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ exit(1);
+}
+
+void levspace(int lev)
+{
+ int i;
+
+ for (i = 0; i<lev; i++)
+ printf(" ");
+}
+
+void CopyFileToDFStream(char *pszPath,
+ IStorage *pdfParent, char *pszName,
+ int level)
+{
+ IStream *pst;
+ FILE *fp;
+ SCODE sc;
+ ULONG cbRead;
+ ULONG cbWritten;
+ TCHAR wcsName[NAMELEN];
+
+ fp = fopen(pszPath, "rb");
+ if (fp == NULL)
+ pexit("Cannot open file %s\n", pszPath);
+
+ WIDEN(pszName, wcsName);
+ sc = GetScode(pdfParent->CreateStream(wcsName, STMPERMS | STGM_FAILIFTHERE,
+ 0, 0, &pst));
+ levspace(level);
+ printf("%s = %lX, %p\n", pszName, sc, pst);
+ if (FAILED(sc))
+ pexit("Unable to create stream %s\n", pszPath);
+
+ for (;;)
+ {
+ cbRead = fread(bBuffer, 1, BUFFERSIZE, fp);
+ if (cbRead == 0)
+ if (feof(fp))
+ break;
+ else
+ pexit("fread %lu failed: %lu read\n", cbRead);
+ sc = GetScode(pst->Write(bBuffer, cbRead, &cbWritten));
+ if (FAILED(sc) || cbWritten != cbRead)
+ pexit("Write %lu failed: sc %lX, wrote %lu\n",
+ cbRead, sc, cbWritten);
+ }
+
+ fclose(fp);
+ pst->Release();
+}
+
+#ifdef FLAT
+typedef HANDLE FINDHANDLE;
+typedef WIN32_FIND_DATA FINDBUF;
+#define FBName(fb) (fb).cFileName
+#define FBAttr(fb) (fb).dwFileAttributes
+#define FBA_DIR FILE_ATTRIBUTE_DIRECTORY
+#define FindFirst(path, buf, fh) \
+ ((*(fh) = FindFirstFile(path, buf)) == INVALID_HANDLE_VALUE ? \
+ STG_E_NOMOREFILES : S_OK)
+#define FindNext(fh, buf) \
+ (FindNextFile(fh, buf) ? S_OK : STG_E_NOMOREFILES)
+// FindClose is defined for Win32
+#else
+typedef int FINDHANDLE;
+typedef struct find_t FINDBUF;
+#define FBName(fb) (fb).name
+#define FBAttr(fb) (fb).attrib
+#define FBA_DIR _A_SUBDIR
+#define FindFirst(path, buf, fh) \
+ (_dos_findfirst(path, FIND_ATTRS, buf) == 0 ? S_OK : STG_E_NOMOREFILES)
+#define FindNext(fh, buf) \
+ (_dos_findnext(buf) == 0 ? S_OK : STG_E_NOMOREFILES)
+#define FindClose(fh) fh
+#endif
+
+void CopyTreeToDocFile(char *pszPath,
+ IStorage *pdfParent, char *pszName,
+ int level)
+{
+ IStorage *pdf;
+ TCHAR wcsName[NAMELEN];
+ SCODE sc;
+ int iPathLen;
+ FINDHANDLE fh;
+ FINDBUF fnd;
+
+ WIDEN(pszName, wcsName);
+ if (pdfParent == NULL)
+ sc = GetScode(StgCreateDocfile(wcsName, RPERMS | STGM_FAILIFTHERE,
+ 0, &pdf));
+ else
+ sc = GetScode(pdfParent->CreateStorage(wcsName, STGPERMS |
+ STGM_FAILIFTHERE,
+ 0, 0, &pdf));
+ levspace(level);
+ printf("%s = %lX, %p\n", pszName, sc, pdf);
+ if (FAILED(sc))
+ pexit("Unable to create Docfile %s\n", pszName);
+
+ levspace(level);
+ printf("{\n");
+
+ iPathLen = strlen(pszPath);
+ pszPath[iPathLen] = '\\';
+ strcpy(pszPath+iPathLen+1, WILD_CARD);
+ sc = FindFirst(pszPath, &fnd, &fh);
+ while (SUCCEEDED(sc))
+ {
+ if (FBName(fnd)[0] == '.')
+ {
+ sc = FindNext(fh, &fnd);
+ continue;
+ }
+ strcpy(pszPath+iPathLen+1, FBName(fnd));
+ if (FBAttr(fnd) & FBA_DIR)
+ CopyTreeToDocFile(pszPath, pdf, FBName(fnd), level+1);
+ else
+ CopyFileToDFStream(pszPath, pdf, FBName(fnd), level+1);
+ sc = FindNext(fh, &fnd);
+ }
+ FindClose(fh);
+
+ pszPath[iPathLen] = 0;
+
+ levspace(level);
+ printf("}\n");
+
+ if (fVerbose)
+ {
+ printf("Contents before:\n");
+ c_list(pdf);
+ }
+ if (FAILED(sc = GetScode(pdf->Commit(0))))
+ pexit("Error %lX committing docfile %p\n", sc, pdf);
+ if (fVerbose)
+ {
+ printf("Contents after:\n");
+ c_list(pdf);
+ getchar();
+ }
+
+ pdf->Release();
+}
+
+void CopyDFStreamToFile(IStorage *pdfParent, TCHAR *pwcsName,
+ char *pszPath,
+ int level)
+{
+ IStream *pst;
+ FILE *fp;
+ ULONG cbRead;
+ ULONG cbWritten;
+ char szName[NAMELEN];
+ SCODE sc;
+
+ NARROW(pwcsName, szName);
+ sc = GetScode(pdfParent->OpenStream(pwcsName, NULL, STMPERMS, 0, &pst));
+ levspace(level);
+ printf("%s = %lX, %p\n", szName, sc, pst);
+ if (FAILED(sc))
+ pexit("Unable to open DF stream %s\n", pszPath);
+
+ fp = fopen(pszPath, "wb");
+ if (fp == NULL)
+ pexit("Cannot open file %s\n", pszPath);
+
+ for (;;)
+ {
+ sc = GetScode(pst->Read(bBuffer, BUFFERSIZE, &cbRead));
+ if (FAILED(sc))
+ pexit("Read %lu failed: sc %lX, read %lu\n", BUFFERSIZE,
+ sc, cbRead);
+ else if (cbRead == 0)
+ break;
+ cbWritten = fwrite(bBuffer, 1, (size_t)cbRead, fp);
+ if (cbRead != cbWritten || ferror(fp))
+ pexit("fwrite %lu failed, %lu written\n", cbRead, cbWritten);
+ }
+
+ pst->Release();
+ fclose(fp);
+ pdfParent->DestroyElement(pwcsName);
+}
+
+void CopyDocFileToTree(IStorage *pdfParent, TCHAR *pwcsName,
+ char *pszPath,
+ int level)
+{
+ IStorage *pdf;
+ IEnumSTATSTG *pdfi;
+ int iPathLen;
+ SCODE sc;
+ STATSTG sstg;
+ char szName[NAMELEN];
+
+ NARROW(pwcsName, szName);
+ if (pdfParent == NULL)
+ sc = GetScode(StgOpenStorage(pwcsName, NULL, RPERMS, NULL, 0, &pdf));
+ else
+ sc = GetScode(pdfParent->OpenStorage(pwcsName, NULL, STGPERMS, NULL,
+ 0, &pdf));
+ levspace(level);
+ printf("%s = %lX, %p\n", szName, sc, pdf);
+ if (pdf == NULL)
+ pexit("Unable to instantiate Docfile %s\n", szName);
+ levspace(level);
+ printf("{\n");
+
+ _mkdir(pszPath);
+ iPathLen = strlen(pszPath);
+ strcpy(pszPath+iPathLen, "\\");
+
+ pdf->EnumElements(0, NULL, 0, &pdfi);
+ if (pdfi == NULL)
+ pexit("Unable to obtain iterator for Docfile %s\n", pszPath);
+
+ for (;;)
+ {
+ if (GetScode(pdfi->Next(1, &sstg, NULL)) != S_OK)
+ break;
+
+ NARROW(sstg.pwcsName, pszPath+iPathLen+1);
+ if (sstg.type == STGTY_STORAGE)
+ CopyDocFileToTree(pdf, sstg.pwcsName, pszPath, level+1);
+ else
+ CopyDFStreamToFile(pdf, sstg.pwcsName, pszPath, level+1);
+ MemFree(sstg.pwcsName);
+ }
+ pdfi->Release();
+
+ pszPath[iPathLen] = 0;
+
+ levspace(level);
+ printf("}\n");
+ pdf->Release();
+
+ if (pdfParent != NULL)
+ pdfParent->DestroyElement(pwcsName);
+ else
+ _unlink(szName);
+}
+
+void CompareFiles(char *pszSrc, char *pszDest,
+ int level)
+{
+ FILE *fpSrc;
+ FILE *fpDest;
+ ULONG cbSrcRead;
+ ULONG cbDestRead;
+
+ levspace(level);
+ printf("%s\n", pszSrc);
+
+ fpSrc = fopen(pszSrc, "rb");
+ if (fpSrc == NULL)
+ pexit("Error opening source file %s\n", pszSrc);
+
+ fpDest = fopen(pszDest, "rb");
+ if (fpDest == NULL)
+ pexit("Error opening dest file %s\n", pszDest);
+
+ for (;;)
+ {
+ cbSrcRead = fread(bBuffer, 1, BUFFERSIZE, fpSrc);
+ if (cbSrcRead == 0)
+ if (feof(fpSrc))
+ break;
+ else
+ pexit("Error reading file %s\n", pszSrc);
+ cbDestRead = fread(bCompare, 1, (size_t)cbSrcRead, fpDest);
+ if (ferror(fpDest))
+ pexit("Error reading file %s\n", pszDest);
+ if (cbDestRead != cbSrcRead)
+ pexit("Read length mismatch: %lu vs. %lu\n",
+ cbSrcRead, cbDestRead);
+ if (memcmp(bBuffer, bCompare, (size_t)cbSrcRead))
+ pexit("Data mismatch\n");
+ }
+
+ fclose(fpSrc);
+ fclose(fpDest);
+ _unlink(pszDest);
+}
+
+void CompareDirectoryTrees(char *pszSrc, char *pszDest,
+ int level)
+{
+ SCODE sc;
+ int iSrcLen, iDestLen;
+ FINDHANDLE fh;
+ FINDBUF fnd;
+
+ levspace(level);
+ printf("%s\n", pszSrc);
+
+ iSrcLen = strlen(pszSrc);
+ pszSrc[iSrcLen] = '\\';
+ strcpy(pszSrc+iSrcLen+1, WILD_CARD);
+ iDestLen = strlen(pszDest);
+ pszDest[iDestLen] = '\\';
+
+ sc = FindFirst(pszSrc, &fnd, &fh);
+ while (sc == 0)
+ {
+ if (FBName(fnd)[0] == '.')
+ {
+ sc = FindNext(fh, &fnd);
+ continue;
+ }
+ strcpy(pszSrc+iSrcLen+1, FBName(fnd));
+ strcpy(pszDest+iDestLen+1, FBName(fnd));
+ if (FBAttr(fnd) & FBA_DIR)
+ CompareDirectoryTrees(pszSrc, pszDest, level+1);
+ else
+ CompareFiles(pszSrc, pszDest, level+1);
+ sc = FindNext(fh, &fnd);
+ }
+ FindClose(fh);
+
+ pszSrc[iSrcLen] = 0;
+ pszDest[iDestLen] = 0;
+ _rmdir(pszDest);
+}
+
+char szDocfile[NAMELEN] = "DFTCT.DFL";
+char szSrcPath[_MAX_PATH] = "C:\\TEST";
+char szDestPath[_MAX_PATH] = "C:\\DFTC";
+
+void RunArgs(int argc, char *argv[])
+{
+ int i;
+
+ for (i = 1; i<argc; i++)
+ if (argv[i][0] == '-')
+ switch(argv[i][1])
+ {
+ case 's':
+ strcpy(szSrcPath, argv[i]+2);
+ break;
+ case 'd':
+ strcpy(szDestPath, argv[i]+2);
+ break;
+ case 'n':
+ strcpy(szDocfile, argv[i]+2);
+ break;
+ }
+}
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ TCHAR wcsName[NAMELEN];
+
+ StartTest("dftct");
+ SetDebug(0x101, 0x101);
+ CmdArgs(argc, argv);
+ RunArgs(argc, argv);
+ _unlink(szDocfile);
+
+ if (fVerbose)
+ {
+ printf("Waiting...\n");
+ getchar();
+ }
+
+ printf(">> Copy %s into %s\n", szSrcPath, szDocfile);
+ CopyTreeToDocFile(szSrcPath, NULL, szDocfile, 0);
+
+ printf("\n>> Copy %s into %s\n", szDocfile, szDestPath);
+ WIDEN(szDocfile, wcsName);
+ CopyDocFileToTree(NULL, wcsName, szDestPath, 0);
+
+ printf("\n>> Compare src and dest\n");
+ CompareDirectoryTrees(szSrcPath, szDestPath, 0);
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/dfxact.cxx b/private/ole32/stg/docfile/tests/dfxact.cxx
new file mode 100644
index 000000000..030875585
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/dfxact.cxx
@@ -0,0 +1,77 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "tsupp.hxx"
+
+#define TEST_FN "test.dfl"
+#define LTEST_FN TEXT("test.dfl")
+#define MSG "This is a bucket o' bytes"
+#define MSG2 "This isn't a byte of chicken"
+
+void contents(char *pszWhat, IStorage *pdf)
+{
+ printf("Contents of %s:\n", pszWhat);
+ c_contents(pdf, 0, FALSE, TRUE);
+}
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pdf = NULL, *pdf2 = NULL;
+ IStream *pst = NULL, *pst2 = NULL;
+
+ _unlink(TEST_FN);
+ CmdArgs(argc, argv);
+ printf("Create root = %lu\n",
+ StgCreateDocfile(LTEST_FN, ROOTP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, &pdf));
+ if (pdf == NULL)
+ {
+ printf("Unable to create root DocFile\n");
+ exit(1);
+ }
+
+ printf("Create embed = %lu\n",
+ pdf->CreateStorage(TEXT("Embedding"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, &pdf2));
+ printf("Release embed = %lu\n",
+ pdf2->Release());
+ printf("Create stream = %lu\n",
+ pdf->CreateStream(TEXT("PublicStream"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, &pst));
+ printf("Release stream = %lu\n",
+ pst->Release());
+ contents("root", pdf);
+
+ printf("\nCommit root = %lu\n",
+ pdf->Commit(0));
+ printf("DestroyElement on embed = %lu\n",
+ pdf->DestroyElement(TEXT("Embedding")));
+ printf("RenameElement on stream = %lu\n",
+ pdf->RenameElement(TEXT("PublicStream"), TEXT("Stream")));
+ contents("root", pdf);
+
+ printf("\nRevert root = %lu\n",
+ pdf->Revert());
+ contents("root", pdf);
+
+ printf("\nDestroyElement on embed = %lu\n",
+ pdf->DestroyElement(TEXT("Embedding")));
+ contents("root", pdf);
+ printf("RenameElement on stream = %lu\n",
+ pdf->RenameElement(TEXT("PublicStream"), TEXT("Link")));
+ printf("Create embed = %lu\n",
+ pdf->CreateStorage(TEXT("PublicStream"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, &pdf2));
+ printf("Release embed = %lu\n",
+ pdf2->Release());
+ contents("root", pdf);
+ printf("Commit root = %lu\n",
+ pdf->Commit(0));
+ printf("Release root = %lu\n",
+ pdf->Release());
+
+ printf("Get root = %lu\n",
+ StgOpenStorage(LTEST_FN, NULL, ROOTP(STGM_RW), NULL, 0, &pdf));
+ contents("root", pdf);
+ printf("Release root = %lu\n",
+ pdf->Release());
+}
diff --git a/private/ole32/stg/docfile/tests/dnmwrite.cxx b/private/ole32/stg/docfile/tests/dnmwrite.cxx
new file mode 100644
index 000000000..64f1182a7
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/dnmwrite.cxx
@@ -0,0 +1,105 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dnmwrite.cxx
+//
+// Contents: Direct no-memory write test
+//
+// History: 19-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <malloc.h>
+#include "tsupp.hxx"
+
+#define BUFFERSIZE (5L*1024L)
+BYTE HUGE *pbBuffer;
+
+#define OUTPUTON (5L*1024L)
+
+#define LIMIT (4L*1024L*1024L)
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pdf;
+ IStream *pst;
+ ULONG cbWritten, cbTotal;
+
+ StartTest("dfnmwrite");
+ SetDebug(0x101, 0x101);
+ CmdArgs(argc, argv);
+ printf("Create root = %lX\n",
+ DfGetScode(StgCreateDocfile(NULL, STGM_RW | STGM_SHARE_DENY_WRITE |
+ STGM_CREATE | STGM_DELETEONRELEASE, 0,
+ &pdf)));
+ if (pdf == NULL)
+ {
+ printf("Unable to create root DocFile\n");
+ exit(1);
+ }
+ printf("Create stream = %lX\n",
+ DfGetScode(pdf->CreateStream(TEXT("Stream"), STGM_RW |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_FAILIFTHERE, 0, 0, &pst)));
+ if (pst == NULL)
+ {
+ printf("Unable to create stream\n");
+ exit(1);
+ }
+ pbBuffer = (BYTE HUGE *)_halloc(BUFFERSIZE, 1);
+ if (pbBuffer == NULL)
+ {
+ printf("Unable to allocate buffer\n");
+ exit(1);
+ }
+
+#if DBG == 1
+ printf("%lu bytes of memory in use\n", DfGetMemAlloced());
+ printf("Setting memory limit to zero\n");
+ DfSetMemLimit(0);
+#endif
+
+ cbTotal = 0;
+ for (;;)
+ {
+ SCODE sc;
+
+ sc = DfGetScode(pst->Write(pbBuffer, BUFFERSIZE, &cbWritten));
+ if (sc == STG_E_MEDIUMFULL ||
+ (SUCCEEDED(sc) && cbWritten != BUFFERSIZE))
+ {
+ printf("Disk is full, quitting\n");
+ break;
+ }
+ else if (FAILED(sc))
+ {
+ printf("Failed with %lX\n", sc);
+ exit(1);
+ }
+ cbTotal += cbWritten;
+ if ((cbTotal % OUTPUTON) == 0)
+ {
+ printf("Wrote %4luK (%lu)\n", cbTotal/1024, cbTotal);
+#if DBG == 1
+ printf("%lu bytes of memory in use\n", DfGetMemAlloced());
+#endif
+ }
+ if (cbTotal >= LIMIT)
+ {
+ printf("Limit hit, quitting\n");
+ break;
+ }
+ }
+
+ _hfree(pbBuffer);
+ printf("Release stream = %lu\n",
+ pst->Release());
+ printf("Release root = %lu\n",
+ pdf->Release());
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/drect.cxx b/private/ole32/stg/docfile/tests/drect.cxx
new file mode 100644
index 000000000..321e42c02
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/drect.cxx
@@ -0,0 +1,122 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "tsupp.hxx"
+
+#define TEST_FN "test.dfl"
+#define LTEST_FN TEXT("test.dfl")
+#define MSG "This is a bucket o' bytes"
+#define MSG2 "This isn't a byte of chicken"
+
+void contents(char *pszWhat, IStorage *pdf)
+{
+ printf("Contents of %s:\n", pszWhat);
+ c_contents(pdf, 0, FALSE, TRUE);
+}
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ IStorage *pdf = NULL, *pdf2 = NULL;
+ IStream *pst = NULL, *pst2 = NULL;
+ ULONG ulRet, ulStatus, ulPos;
+ char buf[80];
+
+ _unlink(TEST_FN);
+ CmdArgs(argc, argv);
+ printf("Create root = %lu\n",
+ StgCreateDocfile(LTEST_FN, ROOTP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, &pdf));
+ if (pdf == NULL)
+ {
+ printf("Unable to create root DocFile\n");
+ exit(1);
+ }
+ printf("Create root again = %lu\n",
+ StgCreateDocfile(LTEST_FN, ROOTP(STGM_RW) | STGM_FAILIFTHERE,
+ 0, &pdf2));
+
+ printf("\nCreateStream = %lu\n",
+ pdf->CreateStream(TEXT("PublicStream"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, &pst));
+ if (pst == NULL)
+ {
+ printf("Unable to create stream\n");
+ exit(1);
+ }
+ printf("Create stream again = %lu\n",
+ pdf->CreateStream(TEXT("PublicStream"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, &pst2));
+ printf("Get stream with bad perms = %lu\n",
+ pdf->OpenStream(TEXT("PublicStream"), NULL, STMP(STGM_RW) |
+ STGM_SHARE_DENY_READ, 0, &pst2));
+ ulStatus = pst->Write((BYTE *)MSG, sizeof(MSG), &ulRet);
+ printf("Write = %lu, ret is %lu\n", ulStatus, ulRet);
+ printf("Commit = %lu\n",
+ pst->Commit(0));
+ printf("Release = %lu\n",
+ pst->Release());
+ printf("GetStream = %lu\n",
+ pdf->OpenStream(TEXT("PublicStream"), NULL, STMP(STGM_RW),
+ 0, &pst));
+ printf("Seek = %lu\n",
+ pst->Seek(1, SEEK_SET, &ulPos));
+ ulStatus = pst->Read((BYTE *)buf, sizeof(MSG)-1, &ulRet);
+ printf("Read = %lu, ret is %lu\n", ulStatus, ulRet);
+ buf[ulRet] = 0;
+ printf("Buffer is '%s'\n", buf);
+ printf("Release stream = %lu\n",
+ pst->Release());
+
+ printf("\nCreateStream = %lu\n",
+ pdf->CreateStream(TEXT("..PrivateStream"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, &pst));
+ ulStatus = pst->Write((BYTE *)MSG2, sizeof(MSG2), &ulRet);
+ printf("Write = %lu, ret = %lu\n", ulStatus, ulRet);
+ printf("Seek = %lu\n",
+ pst->Seek(0, SEEK_SET, &ulPos));
+ ulStatus = pst->Read((BYTE *)buf, sizeof(MSG2), &ulRet);
+ printf("Read = %lu, ret is %lu\n", ulStatus, ulRet);
+ buf[ulRet] = 0;
+ printf("Buffer is '%s'\n", buf);
+ printf("Release stream = %lu\n",
+ pst->Release());
+
+ printf("\nCreate embed = %lu\n",
+ pdf->CreateStorage(TEXT("Embedding"), STGP(STGM_RW) |
+ STGM_SHARE_DENY_WRITE | STGM_FAILIFTHERE,
+ 0, &pdf2));
+ printf("\nCreate embed with bad perms = %lu\n",
+ pdf->CreateStorage(TEXT("Embedding"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, &pdf2));
+
+ printf("\nCreateStream in embed = %lu\n",
+ pdf2->CreateStream(TEXT("PublicSubStream"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, &pst));
+ contents("embed", pdf2);
+ printf("DestroyEntry on stream = %lu\n",
+ pdf2->DestroyElement(TEXT("PublicSubStream")));
+ ulStatus = pst->Read((BYTE *)buf, sizeof(MSG2), &ulRet);
+ printf("Read = %lu, ret is %lu\n", ulStatus, ulRet);
+ printf("Release stream = %lu\n",
+ pst->Release());
+ contents("embed", pdf2);
+ putchar('\n');
+
+ contents("root", pdf);
+
+ printf("\nDestroyElement on embed = %lu\n",
+ pdf->DestroyElement(TEXT("Embedding")));
+ printf("GetStream on embed = %lu\n",
+ pdf2->OpenStream(TEXT("AnyStream"), NULL, STMP(STGM_RW), 0, &pst));
+ printf("Release embed = %lu\n",
+ pdf2->Release());
+ contents("root", pdf);
+
+ printf("\nRelease root = %lu\n",
+ pdf->Release());
+
+ printf("\nGet root = %lu\n",
+ StgOpenStorage(LTEST_FN, NULL, ROOTP(STGM_RW), NULL, 0, &pdf));
+ contents("root", pdf);
+ printf("Release root = %lu\n",
+ pdf->Release());
+}
diff --git a/private/ole32/stg/docfile/tests/exe.def b/private/ole32/stg/docfile/tests/exe.def
new file mode 100644
index 000000000..9e7f8de22
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/exe.def
@@ -0,0 +1,19 @@
+#ifndef FLAT
+EXETYPE WINDOWS
+//STUB 'WINSTUB.EXE'
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 20000
+STACKSIZE 8000
+#else
+EXETYPE NT
+SUBSYSTEM WINDOWSCHAR
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 32768
+STACKSIZE 16384
+#endif
diff --git a/private/ole32/stg/docfile/tests/exe.mk b/private/ole32/stg/docfile/tests/exe.mk
new file mode 100644
index 000000000..29d79333a
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/exe.mk
@@ -0,0 +1,40 @@
+default: all
+
+!if "$(NAME)" == ""
+!error Must define NAME
+!endif
+
+!include $(OLE)\setole2.mk
+
+TARGET = $(NAME).exe
+NO_WINMAIN = 1
+DEFBASE = exe
+
+CXXFILES = .\$(NAME).cxx\
+ .\tutils.cxx\
+ .\tsupp.cxx
+
+PXXFILE = .\pch.cxx
+
+!if "$(PLATFORM)" == "i286"
+DFLIB = $(OLE)\$(OBJDIR)\storage.lib
+!else
+DFLIB = d:\nt\public\sdk\lib\i386\uuid.lib d:\nt\public\sdk\lib\i386\ole32.lib
+!endif
+
+# !include $(OLE)\dflibs.mk
+
+LIBS = $(LIBS) $(DFLIB) $(RTLIBEXEQ)
+
+CFLAGS = $(CFLAGS) -DUL64
+
+CINC = -I$(OLE2H) $(CINC) -I$(OLE)\h -Id:\nt\public\sdk\inc
+
+MULTIDEPEND = MERGED
+
+!if "$(OLETARGET)" != "\win40\ole\docfile\tests"
+EXECOPY = $(OLETARGET)\$(OBJDIR)
+!endif
+
+!include $(COMMON)\src\win40.mk
+!include $(DEPENDFILE)
diff --git a/private/ole32/stg/docfile/tests/failcmt.cxx b/private/ole32/stg/docfile/tests/failcmt.cxx
new file mode 100644
index 000000000..afbc17af2
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/failcmt.cxx
@@ -0,0 +1,172 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tsupp.hxx"
+
+#define LEVELS 3
+#define OBJECTS 6
+
+int new_level(IStorage *pstgParent, int level, TCHAR *ptcsName)
+{
+ IStorage *pstg;
+ IStream *pstmChild;
+ int i, rnd, nobjs = 0;
+ TCHAR name[CWCSTORAGENAME], name2[CWCSTORAGENAME];
+ TCHAR *ents[OBJECTS];
+
+ if (pstgParent == NULL)
+ {
+ printf("Create root docfile %s = ", ptcsName);
+ printf("%lX\n",
+ StgCreateDocfile(ptcsName, ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pstg));
+ }
+ else
+ {
+ printf("Create embedded docfile %s = ", ptcsName);
+ printf("%lX\n",
+ pstgParent->CreateStorage(ptcsName, STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstg));
+ }
+ if (pstg == NULL)
+ return 0;
+ nobjs++;
+
+ for (i = 0; i<OBJECTS; i++)
+ {
+ sprintf(name, "XObject%d-%d", level, i);
+ if ((rand()%100) < 20 && level>0)
+ {
+ name[0] = 'D';
+ nobjs += new_level(pstg, level-1, name);
+ }
+ else
+ {
+ name[0] = 'S';
+ printf("Create embedded stream %s = ", name);
+ printf("%lX\n",
+ pstg->CreateStream(name, STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstmChild));
+ if (pstmChild)
+ {
+ printf("Release stream %s = ", name);
+ printf("%lX\n", pstmChild->Release());
+ }
+ else
+ exit(1);
+ nobjs++;
+ }
+ ents[i] = _strdup(name);
+ }
+ for (i = 0; i<OBJECTS; i++)
+ {
+ rnd = rand()%100;
+ if (rnd<15)
+ {
+ printf("DestroyEntry %s = ", ents[i]);
+ printf("%lX\n",
+ pstg->DestroyElement(ents[i]));
+ free(ents[i]);
+ ents[i] = NULL;
+ nobjs--;
+ }
+ else if (rnd<30)
+ {
+ sprintf(name2, "XRename%d-%d", level, i);
+ name2[0] = ents[i][0];
+ printf("RenameEntry %s = ", ents[i]);
+ printf("%lX\n",
+ pstg->RenameElement(ents[i], name2));
+ free(ents[i]);
+ ents[i] = _strdup(name2);
+ }
+ }
+#if DBG == 1
+ // Disallow allocations
+ LONG lMemLimit;
+
+#if 0
+ // Root requires memory for copy-on-write
+ if (pstgParent)
+#endif
+
+ {
+ lMemLimit = DfGetResLimit(DBR_MEMORY);
+ DfSetResLimit(DBR_MEMORY, 0);
+ }
+
+ // Set commit to fail halfway through
+ DfSetResLimit(DBR_XSCOMMITS, nobjs/2);
+ printf("Commit level %d storage expecting failure after %d objects = ",
+ level, nobjs/2);
+ printf("%lX\n", pstg->Commit(0));
+ DfSetResLimit(DBR_XSCOMMITS, 0x7fffffff);
+#endif
+
+ printf("Commit level %d storage = ", level);
+ printf("%lX\n", pstg->Commit(0));
+
+#if DBG == 1
+#if 0
+ if (pstgParent)
+#endif
+ {
+ // Re-enable allocation
+ DfSetResLimit(DBR_MEMORY, lMemLimit);
+ }
+#endif
+
+ IEnumSTATSTG *penm;
+ STATSTG stat;
+
+ printf("Get enumerator on %s = ", ptcsName);
+ printf("%lX\n", pstg->EnumElements(0, 0, 0, &penm));
+ for (;;)
+ {
+ if (GetScode(penm->Next(1, &stat, NULL)) == S_FALSE)
+ break;
+ for (i = 0; i<OBJECTS; i++)
+ if (ents[i] && !strcmp(ents[i], stat.pwcsName))
+ {
+ if (stat.type != (ents[i][0] == 'D' ? STGTY_STORAGE :
+ STGTY_STREAM))
+ {
+ printf("**ERROR: Type mismatch for '%s'\n", ents[i]);
+ exit(1);
+ }
+ if (fVerbose)
+ printf("Verified '%s'\n", ents[i]);
+ free(ents[i]);
+ ents[i] = NULL;
+ break;
+ }
+ if (i >= OBJECTS)
+ {
+ printf("**ERROR: Extra element '%s'\n", stat.pwcsName);
+ exit(1);
+ }
+ MemFree(stat.pwcsName);
+ }
+ printf("Release enumerator = ");
+ printf("%lX\n", penm->Release());
+ for (i = 0; i<OBJECTS; i++)
+ if (ents[i] != NULL)
+ {
+ printf("**ERROR: Didn't find '%s' but should have\n", ents[i]);
+ exit(1);
+ }
+
+ printf("Release storage %s = ", ptcsName);
+ printf("%lX\n", pstg->Release());
+ return nobjs;
+}
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ StartTest("failcmt");
+ CmdArgs(argc, argv);
+
+ srand(1001);
+ new_level(NULL, LEVELS, TEXT("test.dfl"));
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/imultip.cxx b/private/ole32/stg/docfile/tests/imultip.cxx
new file mode 100644
index 000000000..b356f60b6
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/imultip.cxx
@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tsupp.hxx"
+#include <dfentry.hxx>
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ IStorage *pdf, *pdfEmbed, *pdfEmbed2, *pdfRoot;
+ IStream *pst, *pstEmbed;
+ BOOL fCreate = FALSE;
+ HRESULT hr;
+
+ StartTest("imultip");
+ if (argc == 1 || *argv[1] == 'c')
+ fCreate = TRUE;
+ CmdArgs(argc-1, argv+1);
+ if (fCreate)
+ {
+ hr = StgCreateDocfile(TEXT("test.dfl"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pdfRoot);
+ Result("Create root docfile", hr);
+ hr = pdfRoot->CreateStorage(TEXT("Embedding"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pdfEmbed);
+ Result("Create embedded storage", hr);
+ hr = pdfEmbed->CreateStorage(TEXT("Embedding2"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pdfEmbed2);
+ Result("Create second embedding", hr);
+ hr = pdfEmbed2->CreateStream(TEXT("PublicStream"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstEmbed);
+ Result("Create embedded stream", hr);
+ hr = StgCreateDocfile(TEXT("dup.dfl"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pdf);
+ Result("Create dup docfile", hr);
+ hr = pdf->CreateStream(TEXT("DupStream"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pst);
+ Result("Create dup stream", hr);
+ hr = CoMarshalInterface(pst, IID_IStorage, pdfRoot, 0, NULL,
+ MSHLFLAGS_NORMAL);
+ Result("CoMarshalInterface", hr);
+ hr = pst->Commit(0);
+ Result("Commit dup stream", hr);
+ pst->Release();
+ hr = pdf->Commit(0);
+ Result("Commit dup storage", hr);
+ pdf->Release();
+ pstEmbed->Release();
+ hr = pdfEmbed2->Commit(0);
+ Result("Commit embedding2", hr);
+ pdfEmbed2->Release();
+ hr = pdfEmbed->Commit(0);
+ Result("Commit embedding", hr);
+ pdfEmbed->Release();
+ printf("Release root storage - marshal data now invalid\n");
+ pdfRoot->Release();
+ printf("Waiting...\n");
+ getchar();
+ }
+ else
+ {
+ void *p;
+
+ // Break up the heap
+ p = malloc(16);
+ hr = StgOpenStorage(TEXT("dup.dfl"), NULL, ROOTP(STGM_RW),
+ NULL, 0, &pdf);
+ Result("Open dup docfile", hr);
+ hr = pdf->OpenStream(TEXT("DupStream"), NULL, STMP(STGM_RW),
+ 0, &pst);
+ Result("Open dup stream", hr);
+ hr = CoUnmarshalInterface(pst, IID_IStorage, (void **)&pdfRoot);
+ IllResult("CoUnmarshalInterface", hr);
+ pst->Release();
+ pdf->Release();
+ free(p);
+ }
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/itermod.cxx b/private/ole32/stg/docfile/tests/itermod.cxx
new file mode 100644
index 000000000..5838568a2
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/itermod.cxx
@@ -0,0 +1,135 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tsupp.hxx"
+
+#define NITEMS 10
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstgRoot, *pstg, *pstgO;
+ IStream *pstmO;
+ HRESULT hr;
+ int i;
+ STATSTG stat;
+ IEnumSTATSTG *penm;
+ char achName[CWCSTORAGENAME], achName2[CWCSTORAGENAME];
+ TCHAR atcName[CWCSTORAGENAME], atcName2[CWCSTORAGENAME];
+ IUnknown *punk;
+
+ StartTest("itermod");
+ CmdArgs(argc, argv);
+
+ hr = StgCreateDocfile(TEXT("TEST.DFL"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pstgRoot);
+ Result("Create root docfile", hr);
+ hr = pstgRoot->CreateStorage(TEXT("Test"), STGP(STGM_RW), 0, 0, &pstg);
+ Result("Create embedding", hr);
+
+ hr = pstg->EnumElements(0, 0, 0, &penm);
+ Result("Get enumerator", hr);
+
+ hr = penm->Next(1, &stat, NULL);
+ Result("Next on empty storage", hr);
+
+ printf("\n----- Create elements -----\n");
+ for (i = 0; i < NITEMS; i++)
+ {
+ sprintf(achName, "Obj%d", i);
+ ATOT(achName, atcName, CWCSTORAGENAME);
+ if (i & 1)
+ {
+ hr = pstg->CreateStorage(atcName, STGP(STGM_RW), 0, 0, &pstgO);
+ punk = pstgO;
+ }
+ else
+ {
+ hr = pstg->CreateStream(atcName, STMP(STGM_RW), 0, 0, &pstmO);
+ punk = pstmO;
+ }
+ printf("Create child '%s'", achName);
+ Result("", hr);
+ punk->Release();
+
+ if ((i % 3) == 0)
+ {
+ hr = penm->Reset();
+ Result("Reset", hr);
+ }
+ hr = penm->Next(1, &stat, NULL);
+ Result("Enumerate", hr);
+ if (GetScode(hr) != S_FALSE)
+ {
+ TTOA(stat.pwcsName, achName, CWCSTORAGENAME);
+ printf("Enumerator returned '%s'\n", achName);
+ MemFree(stat.pwcsName);
+ }
+ }
+
+ printf("\n----- Modify elements -----\n");
+ for (i = 0; i < NITEMS; i++)
+ {
+ if ((i % 3) == 0)
+ {
+ sprintf(achName, "Obj%d", i);
+ ATOT(achName, atcName, CWCSTORAGENAME);
+ if ((i % 6) == 0)
+ {
+ hr = pstg->DestroyElement(atcName);
+ printf("Destroy '%s'", achName);
+ Result("", hr);
+ }
+ else
+ {
+ sprintf(achName2, "Zbj%d", i);
+ ATOT(achName2, atcName2, CWCSTORAGENAME);
+ hr = pstg->RenameElement(atcName, atcName2);
+ printf("Rename '%s' to '%s'", achName, achName2);
+ Result("", hr);
+ }
+ }
+
+
+ if ((i % 5) == 0)
+ {
+ hr = pstg->Commit(0);
+ Result("Commit", hr);
+ }
+
+ if ((i % 4) == 0)
+ {
+ hr = penm->Reset();
+ Result("Reset", hr);
+ }
+ hr = penm->Next(1, &stat, NULL);
+ Result("Enumerate", hr);
+ if (GetScode(hr) != S_FALSE)
+ {
+ TTOA(stat.pwcsName, achName, CWCSTORAGENAME);
+ printf("Enumerator returned '%s'\n", achName);
+ MemFree(stat.pwcsName);
+ }
+ }
+
+ printf("\n----- Full enumeration -----\n");
+ hr = penm->Reset();
+ Result("Reset", hr);
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result("Enumerate", hr);
+ if (GetScode(hr) != S_FALSE)
+ {
+ TTOA(stat.pwcsName, achName, CWCSTORAGENAME);
+ printf("Enumerator returned '%s'\n", achName);
+ MemFree(stat.pwcsName);
+ }
+ else
+ break;
+ }
+
+ penm->Release();
+ pstg->Release();
+ pstgRoot->Release();
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/iterrev.cxx b/private/ole32/stg/docfile/tests/iterrev.cxx
new file mode 100644
index 000000000..ac11dd87b
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/iterrev.cxx
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+// #define CINTERFACE
+
+#include "tsupp.hxx"
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg;
+ IEnumSTATSTG *penm;
+ STATSTG sstg;
+
+ StartTest("iterrev");
+ CmdArgs(argc, argv);
+ printf("Create root docfile = %lX\n",
+ StgCreateDocfile(TEXT("test.dfl"), ROOTP(STGM_RW) | STGM_CREATE,
+ 0, &pstg));
+ printf("EnumElements = %lX\n",
+ Mthd(pstg, EnumElements)(SELF(pstg) 0, NULL, 0, &penm));
+ printf("Release root = %lX\n",
+ Mthd(pstg, Release)(SELF(pstg)));
+ printf("Next = %lX\n",
+ Mthd(penm, Next)(SELF(penm) 1, &sstg, NULL));
+ printf("Open root docfile = %lX\n",
+ StgOpenStorage(TEXT("test.dfl"), NULL, ROOTP(STGM_RW), NULL, 0,
+ &pstg));
+ printf("Release root = %lX\n",
+ Mthd(pstg, Release)(SELF(pstg)));
+ printf("Release enumerator = %lX\n",
+ Mthd(penm, Release)(SELF(penm)));
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/lk.cxx b/private/ole32/stg/docfile/tests/lk.cxx
new file mode 100644
index 000000000..0a66e337f
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/lk.cxx
@@ -0,0 +1,104 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <io.h>
+#include "tsupp.hxx"
+
+BOOL Lock(int fd, ULONG off, ULONG len)
+{
+ int iRt;
+
+ __asm
+ {
+ mov ax, 5C00H
+ mov bx, fd
+ mov cx, WORD PTR off+2
+ mov dx, WORD PTR off
+ mov si, WORD PTR len+2
+ mov di, WORD PTR len
+ mov iRt, 0
+ clc
+ int 21h
+ jnc grl_noerror
+ mov iRt, ax
+ grl_noerror:
+ }
+ if (iRt != 0)
+ return FALSE;
+ return TRUE;
+}
+
+BOOL Unlock(int fd, ULONG off, ULONG len)
+{
+ int iRt;
+
+ __asm
+ {
+ mov ax, 5C01H
+ mov bx, fd
+ mov cx, WORD PTR off+2
+ mov dx, WORD PTR off
+ mov si, WORD PTR len+2
+ mov di, WORD PTR len
+ mov iRt, 0
+ clc
+ int 21h
+ jnc rrl_noerror
+ mov iRt, ax
+ rrl_noerror:
+ }
+ if (iRt != 0)
+ return FALSE;
+ return TRUE;
+}
+
+#define NLOCKS 50
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ int fd;
+ char *fn;
+ int i;
+ BOOL fName;
+
+ StartTest("open");
+ CmdArgs(argc, argv);
+
+ for (i = 1; i < argc; i++)
+ if (*argv[i] != '-')
+ {
+ fn = argv[i];
+ fName = TRUE;
+ }
+
+ if (!fName)
+ {
+ printf("No filename specified\n");
+ exit(1);
+ }
+
+ fd = _open(fn, _O_RDONLY | _O_BINARY);
+ if (fd < 0)
+ {
+ printf("Can't open %s\n", fn);
+ exit(1);
+ }
+
+ for (i = 0; i < NLOCKS; i++)
+ {
+ printf("Locking %d\n", i);
+ if (!Lock(fd, (ULONG)i, 1))
+ {
+ printf("** Lock failed **\n", i);
+ break;
+ }
+ }
+ while (--i >= 0)
+ Unlock(fd, (ULONG)i, 1);
+
+ _close(fd);
+
+ EndTest(0);
+}
+
diff --git a/private/ole32/stg/docfile/tests/lkb.cxx b/private/ole32/stg/docfile/tests/lkb.cxx
new file mode 100644
index 000000000..dcbd65007
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/lkb.cxx
@@ -0,0 +1,647 @@
+#include <io.h>
+#include "tsupp.hxx"
+
+#ifndef FLAT
+typedef LONG LARGE_INTEGER;
+typedef ULONG ULARGE_INTEGER;
+#endif
+
+#define MAKE_ERR(c) \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, SCODE_CODE(c))
+
+interface CFileStream : public ILockBytes
+{
+public:
+ CFileStream(DWORD const grfMode, char *pszPath);
+ ~CFileStream(void);
+
+ // IUnknown
+ OLEMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ OLEMETHOD_(ULONG, AddRef)(void);
+ OLEMETHOD_(ULONG, Release)(void);
+
+ // New methods
+ OLEMETHOD(ReadAt)(ULARGE_INTEGER ulOffset,
+ VOID *pv,
+ ULONG cb,
+ ULONG *pcbRead);
+ OLEMETHOD(WriteAt)(ULARGE_INTEGER ulOffset,
+ VOID *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ OLEMETHOD(Flush)(void);
+ OLEMETHOD(GetSize)(ULARGE_INTEGER *pcb);
+ OLEMETHOD(SetSize)(ULARGE_INTEGER cb);
+ OLEMETHOD(LockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ OLEMETHOD(UnlockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ OLEMETHOD(Stat)(STATSTG *pstatstg);
+
+private:
+ int _fd;
+ LONG _cReferences;
+};
+
+SCODE CFileStream::Init(DWORD const grfMode, char *pszPath)
+{
+ char szPath[_MAX_PATH+1];
+ SCODE sc;
+ int iOpenMode;
+ OFSTRUCT of;
+ CFileStream *pfst;
+ BOOL fAddedAtom = FALSE;
+
+ // Open the file
+ if (!P_WRITE(_df))
+ iOpenMode = OF_READ;
+ else
+ iOpenMode = OF_READWRITE;
+ if (P_DENYWRITE(_df) && !P_WRITE(_df))
+ iOpenMode |= OF_SHARE_DENY_WRITE;
+ else
+ iOpenMode |= OF_SHARE_DENY_NONE;
+
+ _hFile = OpenFile(szPath, &of, iOpenMode);
+ if (_dwStartFlags & RSF_CREATE)
+ {
+ if (_hFile < 0)
+ _hFile = OpenFile(szPath, &of, iOpenMode | OF_CREATE);
+ else if ((_dwStartFlags & RSF_TRUNCATE) == 0)
+ olErr(EH_hFile, STG_E_FILEALREADYEXISTS);
+ if (_hFile < 0)
+ {
+ olErr(EH_atPath, MAKE_ERR(of.nErrCode));
+ }
+ else
+ {
+ olVerify(_lclose(_hFile) != HFILE_ERROR);
+ _hFile = OpenFile(szPath, &of, iOpenMode);
+ }
+ }
+ if (_hFile < 0)
+ olErr(EH_atPath, MAKE_ERR(of.nErrCode));
+ if (_dwStartFlags & RSF_TRUNCATE)
+ {
+ hfChkTo(EH_hFile, _llseek(_hFile, 0, STREAM_SEEK_SET));
+ hfChkTo(EH_hFile, _lwrite(_hFile, szPath, 0));
+ }
+
+ olFileStOut((DEB_ITRACE, "Out CFileStream::Init\n"));
+ return S_OK;
+
+EH_hFile:
+ olVerify(_lclose(_hFile) != HFILE_ERROR);
+ _hFile = INVALID_FH;
+EH_atPath:
+ if (fAddedAtom)
+ {
+ olVerify(GlobalDeleteAtom(_atPath) == 0);
+ _atPath = 0;
+ }
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::~CFileStream, public
+//
+// Synopsis: Destructor
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CFileStream::~CFileStream(void)
+{
+ char szPath[_MAX_PATH];
+ int iRt;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::~CFileStream()\n"));
+ olAssert(_cReferences == 0);
+ _sig = CFILESTREAM_SIGDEL;
+#ifndef NOPUBLIST
+ if (!_fCleanup)
+ {
+#endif
+ if (_hFile >= 0)
+ olVerify(_lclose(_hFile) != HFILE_ERROR);
+ if (_atPath != 0)
+ {
+ if ((_dwStartFlags & RSF_DELETEONRELEASE) &&
+ GetNext() == this && GetPrev() == this)
+ {
+ olVerify(GlobalGetAtomName(_atPath, szPath, _MAX_PATH) != 0);
+ // Delete file
+ __asm
+ {
+ mov iRt, 0
+ push ds
+ mov ax, ss
+ mov ds, ax
+ lea dx, szPath
+ mov ah, 041h
+ int 21h
+ pop ds
+ jnc del_succ
+ mov iRt, ax
+ del_succ:
+ }
+ olAssert(iRt == 0);
+ }
+ olVerify(GlobalDeleteAtom(_atPath) == 0);
+ }
+ if (GetPrev())
+ GetPrev()->SetNext(GetNext());
+ if (GetNext())
+ GetNext()->SetPrev(GetPrev());
+#ifndef NOPUBLIST
+ }
+#endif
+ olFileStOut((DEB_ITRACE, "Out CFileStream::~CFileStream\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::ReadAt, public
+//
+// Synopsis: Reads bytes at a specific point in a stream
+//
+// Arguments: [ulPosition] - Offset in file to read at
+// [pb] - Buffer
+// [cb] - Count of bytes to read
+// [pcbRead] - Return of bytes read
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+OLEMETHODIMP CFileStream::ReadAt(ULARGE_INTEGER ulPosition,
+ VOID *pb,
+ ULONG cb,
+ ULONG *pcbRead)
+{
+ SCODE sc;
+ ULONG cbRead = 0;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::ReadAt(%lu, %p, %lu, %p)\n",
+ ULIGetLow(ulPosition), pb, cb, pcbRead));
+ TRY
+ {
+ if (pcbRead)
+ {
+ olChk(ValidateBuffer(pcbRead, sizeof(ULONG)));
+ *pcbRead = 0;
+ }
+ olChk(ValidateBuffer(pb, cb));
+ olChk(Validate());
+ olChk(CheckHandle());
+ if (ULIGetHigh(ulPosition) != 0)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ hfChk(_llseek(_hFile, (LONG)ULIGetLow(ulPosition), STREAM_SEEK_SET));
+ negChk(cbRead = _hread(_hFile, (void HUGE *)pb, (long)cb));
+ if (pcbRead)
+ *pcbRead = cbRead;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olFileStOut((DEB_ITRACE, "Out CFileStream::ReadAt => %lu\n", cbRead));
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::WriteAt, public
+//
+// Synopsis: Writes bytes at a specific point in a stream
+//
+// Arguments: [ulPosition] - Offset in file
+// [pb] - Buffer
+// [cb] - Count of bytes to write
+// [pcbWritten] - Return of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbWritten]
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+OLEMETHODIMP CFileStream::WriteAt(ULARGE_INTEGER ulPosition,
+ VOID *pb,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ SCODE sc;
+ ULONG cbWritten = 0;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::WriteAt(%lu, %p, %lu, %p)\n",
+ ULIGetLow(ulPosition), pb, cb, pcbWritten));
+ TRY
+ {
+ if (pcbWritten)
+ {
+ olChk(ValidateBuffer(pcbWritten, sizeof(ULONG)));
+ *pcbWritten = 0;
+ }
+ olChk(ValidateBuffer(pb, cb));
+ olChk(Validate());
+ olChk(CheckHandle());
+ if (ULIGetHigh(ulPosition) != 0)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ if (cb == 0)
+ olErr(EH_Err, S_OK);
+ hfChk(_llseek(_hFile, (LONG)ULIGetLow(ulPosition), STREAM_SEEK_SET));
+ negChk(cbWritten = _hwrite(_hFile, (void HUGE *)pb, (long)cb));
+ // BUGBUG - This condition can also occur for invalid buffers
+ // We may need to do buffer validation before we know which
+ // error to return
+ if (cbWritten < cb)
+ olErr(EH_Err, STG_E_MEDIUMFULL);
+ if (pcbWritten)
+ *pcbWritten = cbWritten;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olFileStOut((DEB_ITRACE, "Out CFileStream::WriteAt => %lu\n",
+ cbWritten));
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::Flush, public
+//
+// Synopsis: Flushes buffers
+//
+// Returns: Appropriate status code
+//
+// History: 24-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+OLEMETHODIMP CFileStream::Flush(void)
+{
+ int iRt, fd;
+ SCODE sc;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::Flush()\n"));
+ TRY
+ {
+ olChk(Validate());
+ olChk(CheckHandle());
+ fd = _hFile;
+ // Commit file
+ __asm
+ {
+ mov iRt, 0
+ mov ah, 068h
+ mov bx, fd
+ int 21h
+ jnc flush_succ
+ mov iRt, ax
+ flush_succ:
+ }
+ if (iRt != 0)
+ olErr(EH_Err, MAKE_ERR(iRt));
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olFileStOut((DEB_ITRACE, "Out CFileStream::Flush\n"));
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::GetSize, public
+//
+// Synopsis: Returns the size of the LStream
+//
+// Arguments: [pulSize] - Return for size
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pulSize]
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+OLEMETHODIMP CFileStream::GetSize(ULARGE_INTEGER *pulSize)
+{
+ SCODE sc;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::GetSize(%p)\n", pulSize));
+ TRY
+ {
+ olChk(ValidateBuffer(pulSize, sizeof(ULARGE_INTEGER)));
+ ULISet32(*pulSize, 0);
+ olChk(Validate());
+ olChk(CheckHandle());
+ hfChk(ULISetLow(*pulSize, _llseek(_hFile, 0, STREAM_SEEK_END)));
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olFileStOut((DEB_ITRACE, "Out CFileStream::GetSize => %lu\n",
+ ULIGetLow(*pulSize)));
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::SetSize, public
+//
+// Synopsis: Sets the size of the LStream
+//
+// Arguments: [ulSize] - New size
+//
+// Returns: Appropriate status code
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+OLEMETHODIMP CFileStream::SetSize(ULARGE_INTEGER ulSize)
+{
+ SCODE sc;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::SetSize(%lu)\n",
+ ULIGetLow(ulSize)));
+ TRY
+ {
+ olChk(Validate());
+ olChk(CheckHandle());
+ if (ULIGetHigh(ulSize) != 0)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+
+ ULARGE_INTEGER ulCurrentSize;
+ hfChk(ULISetLow(ulCurrentSize, _llseek(_hFile, 0, STREAM_SEEK_END)));
+
+ if (ULIGetLow(ulSize) > ULIGetLow(ulCurrentSize))
+ {
+ ULONG cbWritten;
+ hfChk(_llseek(_hFile, (LONG)ULIGetLow(ulSize) - 1, STREAM_SEEK_SET));
+ hfChk(cbWritten = _lwrite(_hFile, &sc, 1));
+
+ if (cbWritten != 1)
+ olErr(EH_Err, STG_E_MEDIUMFULL);
+ }
+ else
+ {
+ hfChk(_llseek(_hFile, (LONG)ULIGetLow(ulSize), STREAM_SEEK_SET));
+ hfChk(_lwrite(_hFile, &sc, 0));
+ }
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olFileStOut((DEB_ITRACE, "Out CFileStream::SetSize\n"));
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::LockRegion, public
+//
+// Synopsis: Gets a lock on a portion of the LStream
+//
+// Arguments: [ulStartOffset] - Lock start
+// [cbLockLength] - Length
+// [dwLockType] - Exclusive/Read only
+//
+// Returns: Appropriate status code
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+OLEMETHODIMP CFileStream::LockRegion(ULARGE_INTEGER ulStartOffset,
+ ULARGE_INTEGER cbLockLength,
+ DWORD dwLockType)
+{
+ int iRt, fd;
+ SCODE sc;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::LockRegion(%lu, %lu, %lu)\n",
+ ULIGetLow(ulStartOffset), ULIGetLow(cbLockLength),
+ dwLockType));
+ TRY
+ {
+ olChk(Validate());
+ olChk(CheckHandle());
+ if (!VALID_LOCKTYPE(dwLockType))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ if (ULIGetHigh(ulStartOffset) != 0 || ULIGetHigh(cbLockLength) != 0)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ fd = _hFile;
+ __asm
+ {
+ mov ax, 5C00H
+ mov bx, fd
+ // Assumes low DWORD is first in ULARGE_INTEGER
+ mov cx, WORD PTR ulStartOffset+2
+ mov dx, WORD PTR ulStartOffset
+ mov si, WORD PTR cbLockLength+2
+ mov di, WORD PTR cbLockLength
+ mov iRt, 0
+ int 21h
+ jnc grl_noerror
+ mov iRt, ax
+ grl_noerror:
+ }
+ if (iRt != 0)
+ {
+ if (iRt == 1)
+ {
+ // INVALID_FUNCTION is impossible because the
+ // function is hardcoded. This means locking
+ // isn't supported
+ olErr(EH_Err, STG_E_SHAREREQUIRED);
+ }
+ else
+ olErr(EH_Err, MAKE_ERR(iRt));
+ }
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olFileStOut((DEB_ITRACE, "Out CFileStream::LockRegion\n"));
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::UnlockRegion, public
+//
+// Synopsis: Releases an existing lock
+//
+// Arguments: [ulStartOffset] - Lock start
+// [cbLockLength] - Length
+// [dwLockType] - Lock type
+//
+// Returns: Appropriate status code
+//
+// History: 20-Feb-92 DrewB Created
+//
+// Notes: Must match an existing lock exactly
+//
+//---------------------------------------------------------------
+
+OLEMETHODIMP CFileStream::UnlockRegion(ULARGE_INTEGER ulStartOffset,
+ ULARGE_INTEGER cbLockLength,
+ DWORD dwLockType)
+{
+ int iRt, fd;
+ SCODE sc;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::UnlockRegion(%lu, %lu)\n",
+ ULIGetLow(ulStartOffset), ULIGetLow(cbLockLength),
+ dwLockType));
+ TRY
+ {
+ olChk(Validate());
+ olChk(CheckHandle());
+ if (!VALID_LOCKTYPE(dwLockType))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ if (ULIGetHigh(ulStartOffset) != 0 || ULIGetHigh(cbLockLength) != 0)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ fd = _hFile;
+ __asm
+ {
+ mov ax, 5C01H
+ mov bx, fd
+ // Assumes low DWORD is first in ULARGE_INTEGER
+ mov cx, WORD PTR ulStartOffset+2
+ mov dx, WORD PTR ulStartOffset
+ mov si, WORD PTR cbLockLength+2
+ mov di, WORD PTR cbLockLength
+ mov iRt, 0
+ int 21h
+ jnc rrl_noerror
+ mov iRt, ax
+ rrl_noerror:
+ }
+ if (iRt != 0)
+ olErr(EH_Err, MAKE_ERR(iRt));
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olFileStOut((DEB_ITRACE, "Out CFileStream::UnlockRegion\n"));
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::Stat, public
+//
+// Synopsis: Fills in a stat buffer for this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 25-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+SCODE CFileStream::Stat(STATSTGW *pstatstg)
+{
+ int iRt, fd;
+ SCODE sc;
+ unsigned short tm, dt;
+ struct tm tmFile;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::Stat(%p)\n", pstatstg));
+ TRY
+ {
+ olChkTo(EH_RetSc, ValidateBuffer(pstatstg, sizeof(STATSTGW)));
+ olChk(Validate());
+ olChk(CheckHandle());
+ ULISetHigh(pstatstg->cbSize, 0);
+ hfChk(ULISetLow(pstatstg->cbSize,
+ _llseek(_hFile, 0, STREAM_SEEK_END)));
+ fd = _hFile;
+ // Retrieve file time
+ __asm
+ {
+ mov iRt, 0
+ mov bx, fd
+ mov ax, 05700h
+ int 21h
+ mov tm, cx
+ mov dt, dx
+ jnc time_succ
+ mov iRt, ax
+ time_succ:
+ }
+ if (iRt != 0)
+ olErr(EH_Err, MAKE_ERR(iRt));
+ tmFile.tm_sec = (tm&31)*2;
+ tmFile.tm_min = (tm>>5)&63;
+ tmFile.tm_hour = (tm>>11)&31;
+ tmFile.tm_mday = dt&31;
+ tmFile.tm_mon = ((dt>>5)&15)-1;
+ tmFile.tm_year = (dt>>9)+80;
+ pstatstg->atime.dwHighDateTime = pstatstg->mtime.dwHighDateTime =
+ pstatstg->ctime.dwHighDateTime = 0;
+ pstatstg->atime.dwLowDateTime = pstatstg->mtime.dwLowDateTime =
+ pstatstg->ctime.dwLowDateTime = (DWORD)mktime(&tmFile);
+ pstatstg->grfLocksSupported = LOCK_EXCLUSIVE_FLAG |
+ LOCK_ONLYONCE_FLAG;
+ pstatstg->type = STGTY_LOCKBYTES;
+ pstatstg->grfMode = DFlagsToMode(_df);
+ olChk(GetName(&pstatstg->pwcsName));
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olFileStOut((DEB_ITRACE, "Out CFileStream::Stat\n"));
+ return S_OK;
+
+EH_Err:
+ memset(pstatstg, 0, sizeof(STATSTGW));
+EH_RetSc:
+ return sc;
+}
diff --git a/private/ole32/stg/docfile/tests/marsrev.cxx b/private/ole32/stg/docfile/tests/marsrev.cxx
new file mode 100644
index 000000000..59e93b1cf
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/marsrev.cxx
@@ -0,0 +1,104 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tsupp.hxx"
+#include <dfentry.hxx>
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ IStorage *pdf, *pdfEmbed, *pdfEmbed2, *pdfRoot;
+ IStream *pst, *pstEmbed;
+ BOOL fCreate = FALSE;
+ STATSTG statstg;
+
+ StartTest("marsrev");
+ if (argc == 1 || *argv[1] == 'c')
+ fCreate = TRUE;
+ CmdArgs(argc-1, argv+1);
+ if (fCreate)
+ {
+ printf("Create root docfile = %lX\n",
+ StgCreateDocfile(TEXT("test.dfl"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pdfRoot));
+ printf("Create embedded storage = %lX\n",
+ pdfRoot->CreateStorage(TEXT("Embedding"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pdfEmbed));
+ printf("Create second embedding = %lX\n",
+ pdfEmbed->CreateStorage(TEXT("Embedding2"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pdfEmbed2));
+ printf("Create embedded stream = %lX\n",
+ pdfEmbed2->CreateStream(TEXT("PublicStream"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstEmbed));
+ printf("Create dup docfile = %lX\n",
+ StgCreateDocfile(TEXT("dup.dfl"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pdf));
+ printf("Create dup stream = %lX\n",
+ pdf->CreateStream(TEXT("DupStream"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pst));
+ printf("CoMarshalInterface = %lX\n",
+ CoMarshalInterface(pst, IID_IStorage, pdfEmbed, 0, NULL,
+ MSHLFLAGS_NORMAL));
+ printf("Commit dup stream = %lX\n",
+ pst->Commit(0));
+ printf("Release dup stream = %lX\n",
+ pst->Release());
+ printf("Commit dup storage = %lX\n",
+ pdf->Commit(0));
+ printf("Release dup storage = %lX\n",
+ pdf->Release());
+ printf("Release embedded stream = %lX\n",
+ pstEmbed->Release());
+ printf("Commit embedding2 = %lX\n",
+ pdfEmbed2->Commit(0));
+ printf("Release embedding2 = %lX\n",
+ pdfEmbed2->Release());
+ printf("Commit embedding = %lX\n",
+ pdfEmbed->Commit(0));
+
+ c_contents(pdfEmbed, 0, TRUE, TRUE);
+ printf("Waiting...\n");
+ getchar();
+
+ printf("Release root docfile = %lu\n",
+ pdfRoot->Release());
+ printf("Open root = %lX\n",
+ StgOpenStorage(TEXT("test.dfl"), NULL, ROOTP(STGM_RW),
+ NULL, 0, &pdfRoot));
+ printf("Release root docfile = %lu\n",
+ pdfRoot->Release());
+ printf("Stat embedding = %lX\n",
+ pdfEmbed->Stat(&statstg, STATFLAG_NONAME));
+ printf("Release embedding = %lX\n",
+ pdfEmbed->Release());
+ }
+ else
+ {
+ printf("Open dup docfile = %lX\n",
+ StgOpenStorage(TEXT("dup.dfl"), NULL, ROOTP(STGM_RW),
+ NULL, 0, &pdf));
+ printf("Open dup stream = %lX\n",
+ pdf->OpenStream(TEXT("DupStream"), NULL, STMP(STGM_RW),
+ 0, &pst));
+ printf("CoUnmarshalInterface = %lX\n",
+ CoUnmarshalInterface(pst, IID_IStorage, (void **)&pdfEmbed));
+ printf("Open second embedding = %lX\n",
+ pdfEmbed->OpenStorage(TEXT("Embedding2"), NULL, STGP(STGM_RW),
+ NULL, 0, &pdfEmbed2));
+ printf("Release first embedding = %lX\n",
+ pdfEmbed->Release());
+ printf("Open embedded stream = %lX\n",
+ pdfEmbed2->OpenStream(TEXT("PublicStream"), NULL, STMP(STGM_RW),
+ 0, &pstEmbed));
+ printf("Release embedded stream = %lX\n",
+ pstEmbed->Release());
+ printf("Release second embedding = %lX\n",
+ pdfEmbed2->Release());
+
+ printf("Waiting...\n");
+ getchar();
+ printf("Release dup stream = %lX\n",
+ pst->Release());
+ printf("Release dup storage = %lX\n",
+ pdf->Release());
+ }
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/memt.cxx b/private/ole32/stg/docfile/tests/memt.cxx
new file mode 100644
index 000000000..e4e155bbe
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/memt.cxx
@@ -0,0 +1,79 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: memt.cxx
+//
+// Contents: Basic memory leak check
+//
+// History: 03-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg, *pstgEm;
+ IStream *pstRt, *pstEm;
+ HRESULT hr;
+
+ StartTest("memt");
+ CmdArgs(argc, argv);
+
+ CreateTestFile(NULL, ROOTP(STGM_RW) | STGM_CREATE, FALSE, &pstg, NULL);
+ hr = pstg->CreateStream(TTEXT("TestSt"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstRt);
+ Result(hr, "Create root stream");
+ hr = pstg->CreateStorage(TTEXT("TEST"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstgEm);
+ Result(hr, "Create embedded docfile");
+ hr = pstgEm->CreateStream(TTEXT("TestEmSt"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstEm);
+ Result(hr, "Create embedded stream");
+
+#if DBG == 1
+ printf("Memory used = %ld\n", DfGetMemAlloced());
+#endif
+
+ hr = pstEm->Commit(0);
+ Result(hr, "Commit embedded stream");
+ pstEm->Release();
+
+ hr = pstgEm->Commit(0);
+ Result(hr, "Commit embedded docfile");
+ pstgEm->Release();
+
+ hr = pstRt->Commit(0);
+ Result(hr, "Commit root stream");
+ pstRt->Release();
+
+ hr = pstg->Commit(0);
+ Result(hr, "Commit root docfile");
+ pstg->Release();
+
+ CheckMemory();
+
+ OpenTestFile(NULL, ROOTP(STGM_RW), FALSE, &pstg, NULL);
+ hr = pstg->OpenStream(TTEXT("TestSt"), NULL, STMP(STGM_RW), 0, &pstRt);
+ Result(hr, "Open root stream");
+ hr = pstg->OpenStorage(TTEXT("TEST"), NULL, STGP(STGM_RW),
+ NULL, 0, &pstgEm);
+ Result(hr, "Open embedded docfile");
+ hr = pstgEm->OpenStream(TTEXT("TestEmSt"), NULL,
+ STMP(STGM_RW), 0, &pstEm);
+ Result(hr, "Open embedded stream");
+
+#if DBG == 1
+ printf("Memory used = %ld\n", DfGetMemAlloced());
+#endif
+
+ pstEm->Release();
+ pstgEm->Release();
+ pstRt->Release();
+ pstg->Release();
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/mthrd.cxx b/private/ole32/stg/docfile/tests/mthrd.cxx
new file mode 100644
index 000000000..61eeb6162
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/mthrd.cxx
@@ -0,0 +1,78 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: mthrd.cxx
+//
+// Contents: Multi-threaded access test
+//
+// History: 11-Oct-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+IStream *pstm;
+
+#define REPCOUNT 100
+#define BUF 256
+char buf[BUF];
+
+DWORD thread(void *arg)
+{
+ int rep;
+ HRESULT hr;
+ LARGE_INTEGER li;
+
+ li.LowPart = li.HighPart = 0;
+ for (rep = 0; rep < REPCOUNT; rep++)
+ {
+ hr = pstm->Seek(li, STREAM_SEEK_SET, NULL);
+ Result(hr, "Seek %lu", GetCurrentThreadId());
+ hr = pstm->Read(buf, BUF, NULL);
+ Result(hr, "Read %lu", GetCurrentThreadId());
+ }
+ return 0;
+}
+
+#define MAX_THREADS 10
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg;
+ HRESULT hr;
+ DWORD id;
+ HANDLE thrd[MAX_THREADS];
+ int i, nt;
+
+ StartTest("mthrd");
+ CmdArgs(argc, argv);
+
+ nt = 1;
+ for (i = 1; i < argc; i++)
+ if (!strcmp(argv[i], "-n"))
+ {
+ i++;
+ sscanf(argv[i], "%d", &nt);
+ }
+
+ CreateTestFile(NULL, ROOTP(STGM_RW) | STGM_CREATE, FALSE, &pstg, NULL);
+ hr = pstg->CreateStream(TSTR("test"), STMP(STGM_RW), 0, 0, &pstm);
+ Result(hr, "Create stream");
+ hr = pstm->Write(buf, BUF, NULL);
+ Result(hr, "Write");
+
+ for (i = 0; i < nt; i++)
+ thrd[i] = CreateThread(NULL, 0, thread, NULL, 0, &id);
+ thread(NULL);
+ WaitForMultipleObjects(nt, thrd, TRUE, INFINITE);
+ for (i = 0; i < nt; i++)
+ CloseHandle(thrd[i]);
+
+ pstm->Release();
+ pstg->Release();
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/multimod.cxx b/private/ole32/stg/docfile/tests/multimod.cxx
new file mode 100644
index 000000000..6ac67f432
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/multimod.cxx
@@ -0,0 +1,98 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tsupp.hxx"
+#include <dfentry.hxx>
+
+char buf[] = "This is a test";
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ IStorage *pdf, *pdfEmbed, *pdfEmbed2, *pdfRoot;
+ IStream *pst, *pstEmbed;
+ BOOL fCreate = FALSE;
+ ULONG cb;
+
+ StartTest("multimod");
+ if (argc == 1 || *argv[1] == 'c')
+ fCreate = TRUE;
+ CmdArgs(argc-1, argv+1);
+ if (fCreate)
+ {
+ printf("Create root docfile = %lX\n",
+ StgCreateDocfile(TEXT("test.dfl"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pdfRoot));
+ printf("Create embedded storage = %lX\n",
+ pdfRoot->CreateStorage(TEXT("Embedding"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pdfEmbed));
+ printf("Create second embedding = %lX\n",
+ pdfEmbed->CreateStorage(TEXT("Embedding2"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pdfEmbed2));
+ printf("Create embedded stream = %lX\n",
+ pdfEmbed2->CreateStream(TEXT("PublicStream"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstEmbed));
+ printf("Create dup docfile = %lX\n",
+ StgCreateDocfile(TEXT("dup.dfl"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pdf));
+ printf("Create dup stream = %lX\n",
+ pdf->CreateStream(TEXT("DupStream"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pst));
+ printf("CoMarshalInterface = %lX\n",
+ CoMarshalInterface(pst, IID_IStream, pstEmbed, 0, NULL,
+ MSHLFLAGS_NORMAL));
+ printf("Commit dup stream = %lX\n",
+ pst->Commit(0));
+ printf("Release dup stream = %lX\n",
+ pst->Release());
+ printf("Commit dup storage = %lX\n",
+ pdf->Commit(0));
+ printf("Release dup storage = %lX\n",
+ pdf->Release());
+ printf("Waiting...\n");
+ getchar();
+
+#ifdef DO_READ
+ LARGE_INTEGER ulOff;
+ LISet32(ulOff, 0);
+ printf("Seek to start = %lX\n",
+ pstEmbed->Seek(ulOff, STREAM_SEEK_SET, NULL));
+ printf("Read from embedded stream = %lX\n",
+ pstEmbed->Read(buf, sizeof(buf), &cb));
+ printf("Read %lu bytes, '%s'\n", cb, buf);
+#endif
+ printf("Write = %lX\n",
+ pstEmbed->Write(buf, sizeof(buf), NULL));
+
+ printf("Release embedded stream = %lX\n",
+ pstEmbed->Release());
+ printf("Commit embedding2 = %lX\n",
+ pdfEmbed2->Commit(0));
+ printf("Release embedding2 = %lX\n",
+ pdfEmbed2->Release());
+ printf("Commit embedding = %lX\n",
+ pdfEmbed->Commit(0));
+ printf("Release embedding = %lX\n",
+ pdfEmbed->Release());
+ printf("Release root docfile = %lu\n",
+ pdfRoot->Release());
+ }
+ else
+ {
+ printf("Open dup docfile = %lX\n",
+ StgOpenStorage(TEXT("dup.dfl"), NULL, ROOTP(STGM_RW),
+ NULL, 0, &pdf));
+ printf("Open dup stream = %lX\n",
+ pdf->OpenStream(TEXT("DupStream"), NULL, STMP(STGM_RW),
+ 0, &pst));
+ printf("CoUnmarshalInterface = %lX\n",
+ CoUnmarshalInterface(pst, IID_IStream, (void **)&pstEmbed));
+ printf("Write to stream = %lX\n",
+ pstEmbed->Write(buf, sizeof(buf), NULL));
+ printf("Release embedded stream = %lX\n",
+ pstEmbed->Release());
+ printf("Release dup stream = %lX\n",
+ pst->Release());
+ printf("Release dup storage = %lX\n",
+ pdf->Release());
+ }
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/multip.cxx b/private/ole32/stg/docfile/tests/multip.cxx
new file mode 100644
index 000000000..b5354e5ef
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/multip.cxx
@@ -0,0 +1,99 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: multip.cxx
+//
+// Contents: Multi-process marshalling test
+//
+// History: 13-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ IStorage *pdf, *pdfEmbed, *pdfEmbed2, *pdfRoot;
+ IStream *pst, *pstEmbed;
+ IMarshal *pmsh;
+ BOOL fCreate = FALSE;
+ STATSTG statstg;
+ HRESULT hr;
+ DWORD cb;
+
+ StartTest("multip");
+ if (argc == 1 || *argv[1] == 'c')
+ fCreate = TRUE;
+ CmdArgs(argc-1, argv+1);
+ if (fCreate)
+ {
+ CreateTestFile(NULL, ROOTP(STGM_RW) | STGM_CREATE, FALSE,
+ &pdfRoot, NULL);
+ hr = pdfRoot->CreateStorage(TEXT("Embedding"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pdfEmbed);
+ Result(hr, "Create embedded storage");
+ hr = pdfEmbed->CreateStorage(TEXT("Embedding2"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pdfEmbed2);
+ Result(hr, "Create second embedding");
+ hr = pdfEmbed2->CreateStream(TEXT("PublicStream"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstEmbed);
+ Result(hr, "Create embedded stream");
+ CreateTestFile("dup.dfl", ROOTP(STGM_RW) | STGM_CREATE,
+ FALSE, &pdf, NULL);
+ hr = pdf->CreateStream(TEXT("DupStream"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pst);
+ Result(hr, "Create dup stream");
+
+ hr = pdfRoot->QueryInterface(IID_IMarshal, (void **)&pmsh);
+ Result(hr, "QI to IMarshal");
+ hr = pmsh->GetMarshalSizeMax(IID_IStorage, NULL, 0, NULL,
+ MSHLFLAGS_NORMAL, &cb);
+ Result(hr, "GetMarshalSizeMax");
+ printf("Size is %lu\n", cb);
+ pmsh->Release();
+
+ hr = CoMarshalInterface(pst, IID_IStorage, pdfRoot, 0, NULL,
+ MSHLFLAGS_NORMAL);
+ Result(hr, "CoMarshalInterface");
+ hr = pst->Commit(0);
+ Result(hr, "Commit dup stream");
+ pst->Release();
+ hr = pdf->Commit(0);
+ Result(hr, "Commit dup storage");
+ pdf->Release();
+ pstEmbed->Release();
+ hr = pdfEmbed2->Commit(0);
+ Result(hr, "Commit embedding2");
+ pdfEmbed2->Release();
+ hr = pdfEmbed->Commit(0);
+ Result(hr, "Commit embedding");
+ pdfEmbed->Release();
+ c_contents(pdfRoot, 0, TRUE, TRUE);
+ // CheckMemory();
+ printf("Waiting...\n");
+ getchar();
+ }
+ else
+ {
+ OpenTestFile("dup.dfl", ROOTP(STGM_RW), FALSE, &pdf, NULL);
+ hr = pdf->OpenStream(TEXT("DupStream"), NULL, STMP(STGM_RW),
+ 0, &pst);
+ Result(hr, "Open dup stream");
+ hr = CoUnmarshalInterface(pst, IID_IStorage, (void **)&pdfRoot);
+ Result(hr, "CoUnmarshalInterface");
+ // CheckMemory();
+ printf("Waiting...\n");
+ getchar();
+ hr = pdfRoot->Stat(&statstg, 0);
+ Result(hr, "Stat root");
+ printstat(&statstg, TRUE);
+ c_contents(pdfRoot, 0, TRUE, TRUE);
+ pst->Release();
+ pdf->Release();
+ }
+ pdfRoot->Release();
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/nmake.cmd b/private/ole32/stg/docfile/tests/nmake.cmd
new file mode 100644
index 000000000..816e62cc2
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/nmake.cmd
@@ -0,0 +1,33 @@
+@set ORIGINAL_NAME=%NAME%
+@if .%NAME% == . set NAME=%1
+@if .%NAME% == . goto Usage
+@
+:loop
+@if %NAME% == depend set CMD_EXTRA=depend
+@if not %NAME% == depend set CMD_EXTRA=
+@nmake.exe /f exe.mk NAME=%NAME% %CMD_EXTRA%
+@if not errorlevel == 0 goto End
+@
+@if not %NAME% == depend goto Next
+@if %PLATFORM% == i286 set DEPEND_CHAR=9
+@if %OPSYS% == NT set DEPEND_CHAR=1
+@if %OPSYS% == NT1X set DEPEND_CHAR=3
+@if %OPSYS% == CHICAGO set DEPEND_CHAR=3
+@sed s/%NAME%/$(NAME)/g < depend.mk%DEPEND_CHAR% > depend.ne%DEPEND_CHAR%
+@copy depend.ne%DEPEND_CHAR% depend.mk%DEPEND_CHAR% 1>nul 2>nul
+@del depend.ne%DEPEND_CHAR%
+@set DEPEND_CHAR=
+@
+:Next
+@shift
+@if .%1 == . goto End
+@set NAME=%1
+@goto loop
+@
+:Usage
+@echo Usage: %0 [depend] [target...]
+@
+:End
+@set NAME=%ORIGINAL_NAME%
+@set ORIGINAL_NAME=
+@set CMD_EXTRA=
diff --git a/private/ole32/stg/docfile/tests/nomem.cxx b/private/ole32/stg/docfile/tests/nomem.cxx
new file mode 100644
index 000000000..5a9c4bb2e
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/nomem.cxx
@@ -0,0 +1,28 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: nomem.cxx
+//
+// Contents: Set memory use to zero
+//
+// History: 03-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ StartTest("nomem");
+ CmdArgs(argc, argv);
+
+ printf("Memory in use = %lu\n", DfGetResLimit(DBRQ_MEMORY_ALLOCATED));
+ DfSetResLimit(DBRQ_MEMORY_ALLOCATED, 0);
+ DfSetResLimit(DBRI_ALLOC_LIST, 0);
+ printf("Memory in use = %lu\n", DfGetResLimit(DBRQ_MEMORY_ALLOCATED));
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/nowrite.cxx b/private/ole32/stg/docfile/tests/nowrite.cxx
new file mode 100644
index 000000000..383abeee8
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/nowrite.cxx
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tsupp.hxx"
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg, *pstgE;
+ IStream *pstm;
+ SCODE sc;
+ HRESULT hr;
+
+ StartTest("nowrite");
+ CmdArgs(argc, argv);
+
+ hr = StgCreateDocfile(TEXT("TEST.DFL"), STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, &pstg);
+ Result("Create root docfile", hr);
+ hr = pstg->CreateStorage(TEXT("Test"), STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE, 0, 0, &pstgE);
+ Result("Create middle storage", hr);
+ pstgE->Release();
+ pstg->Release();
+
+ hr = StgOpenStorage(TEXT("TEST.DFL"), NULL, STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE,
+ NULL, 0, &pstg);
+ Result("Open root storage d/RW", hr);
+ hr = pstg->OpenStorage(TEXT("Test"), NULL, STGM_READ |
+ STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE,
+ NULL, 0, &pstgE);
+ Result("Open middle storage t/RO", hr);
+ hr = pstgE->CreateStream(TEXT("Test"), STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, 0, &pstm);
+ Result("Create stream RW", hr);
+ hr = pstm->Write("This is a test", 10, NULL);
+ Result("Write to stream", hr);
+ pstm->Release();
+ hr = pstgE->Commit(0);
+ IllResult("Commit middle storage", hr);
+ pstgE->Release();
+ pstg->Release();
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/oord.cxx b/private/ole32/stg/docfile/tests/oord.cxx
new file mode 100644
index 000000000..05dcc387b
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/oord.cxx
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "tsupp.hxx"
+
+char data[] = "This is some data";
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg;
+ IStream *pstm;
+ HRESULT hr;
+ int i;
+
+ StartTest("oord");
+ CmdArgs(argc, argv);
+
+ hr = StgCreateStorage(TTEXT("test.dfl"), ROOTP(STGM_RW) | STGM_CREATE,
+ STGFMT_DOCUMENT, NULL, &pstg);
+ Result(hr, "Create storage");
+
+ hr = pstg->CreateStream(TTEXT("TRAIL_DATA_STREAM"),
+ STMP(STGM_RW) | STGM_CREATE,
+ 0, 0, &pstm);
+ Result(hr, "Create stream");
+
+ for (i = 0; i < 64; i++)
+ {
+ hr = pstm->Write(data, sizeof(data), NULL);
+ Result(hr, "Write stream");
+ }
+
+ pstg->Release();
+ pstm->Release();
+
+ EndTest(0);
+}
+
diff --git a/private/ole32/stg/docfile/tests/open.cxx b/private/ole32/stg/docfile/tests/open.cxx
new file mode 100644
index 000000000..9d386206b
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/open.cxx
@@ -0,0 +1,82 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: open.cxx
+//
+// Contents: Basic StgOpenStorage scaffold
+//
+// History: 09-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+#define NOPENS 1
+#define BUFFER 1024
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg[NOPENS];
+ HRESULT hr;
+ int i;
+ BOOL fName = FALSE;
+ TCHAR atcPath[_MAX_PATH];
+ IStream *pstm;
+ ULONG cbRead;
+ BYTE bytes[BUFFER];
+ LARGE_INTEGER li;
+
+ SetHandleCount(128);
+
+ StartTest("open");
+ CmdArgs(argc, argv);
+
+ for (i = 1; i < argc; i++)
+ if (*argv[i] != '-')
+ {
+ ATOT(argv[i], atcPath, _MAX_PATH);
+ fName = TRUE;
+ }
+
+ if (!fName)
+ Fail("No filename specified\n");
+
+ /*
+ hr = StgIsStorageFile(atcPath);
+ Result(hr, "StgIsStorageFile");
+ */
+
+ hr = StgOpenStorage(atcPath, NULL, ROOTP(STGM_RW),
+ NULL, 0, &pstg[0]);
+ Result(hr, "Open storage");
+ pstg[0]->Release();
+ hr = StgOpenStorage(atcPath, NULL, ROOTP(STGM_RW),
+ NULL, 0, &pstg[0]);
+ Result(hr, "Open storage");
+ pstg[0]->Release();
+ EndTest(0);
+
+ hr = pstg[0]->OpenStream(TTEXT("WordDocument"), 0, STMP(STGM_RW), 0,
+ &pstm);
+ Result(hr, "Open stream");
+
+ li.HighPart = 0;
+ li.LowPart = 0;
+ pstm->Seek(li, STREAM_SEEK_SET, NULL);
+ for (;;)
+ {
+ hr = pstm->Read(bytes, BUFFER, &cbRead);
+ Result(hr, "Read");
+ if (cbRead == 0)
+ break;
+ }
+ pstm->Release();
+ for (i = 0; i < NOPENS; i++)
+ pstg[i]->Release();
+
+ EndTest(0);
+}
+
diff --git a/private/ole32/stg/docfile/tests/opentm.cxx b/private/ole32/stg/docfile/tests/opentm.cxx
new file mode 100644
index 000000000..59c0816b2
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/opentm.cxx
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tsupp.hxx"
+
+void main(int argc, char *argv[])
+{
+ IStorage *pstg;
+
+ StartTest("opentm");
+ CmdArgs(argc, argv);
+ printf("Create root docfile = %lX\n",
+ StgCreateDocfile(TEXT("TEST.DFL"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pstg));
+ printf("Release root = %lX\n",
+ pstg->Release());
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/oprop.cxx b/private/ole32/stg/docfile/tests/oprop.cxx
new file mode 100644
index 000000000..194d0ff51
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/oprop.cxx
@@ -0,0 +1,622 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: oprop.cxx
+//
+// Contents: OFS property test
+//
+// History: 03-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+struct PropDesc
+{
+ DFPROPTYPE dpt;
+ char *pszName;
+ BOOL fArray;
+ size_t size;
+};
+
+PropDesc props[] =
+{
+ VT_I2, "I2", TRUE, sizeof(short int),
+ VT_I4, "I4", TRUE, sizeof(long int),
+ VT_R4, "R4", TRUE, sizeof(float),
+ VT_R8, "R8", TRUE, sizeof(double),
+ VT_CY, "Currency", TRUE, sizeof(CY),
+ VT_DATE, "Date", TRUE, sizeof(DATE),
+ VT_BSTR, "Basic string", FALSE, sizeof(BSTR),
+ VT_BOOL, "BOOL", TRUE, sizeof(VARIANT_BOOL),
+ VT_I8, "I8", TRUE, sizeof(LARGE_INTEGER),
+ VT_LPSTR, "char string", TRUE, sizeof(LPSTR),
+ VT_BLOB, "BLOB", FALSE, sizeof(BLOB),
+ VT_LPWSTR, "WCHAR string", TRUE, sizeof(LPWSTR),
+ VT_FILETIME, "File time", TRUE, sizeof(FILETIME),
+ VT_UUID, "UUID", TRUE, sizeof(GUID)
+#ifdef FULL_PROPS
+ ,
+ VT_STREAM, "Stream", FALSE, sizeof(IStream *),
+ VT_STREAMED_OBJECT, "Streamed object", FALSE, sizeof(IStream *),
+ VT_STORAGE, "Storage", FALSE, sizeof(IStorage *),
+ VT_STORED_OBJECT, "Stored object", FALSE, sizeof(IStorage *)
+#endif
+};
+#define CPROPS (sizeof(props)/sizeof(props[0]))
+#define CTOTPROPS (2*CPROPS)
+
+#define ARRAY_SIZE 16
+
+struct _BSTR
+{
+ UINT len;
+ char str[80];
+};
+
+#define I2_VAL 0x8564
+#define I4_VAL 0xfef1f064
+#define R4_VAL 1.25
+#define R8_VAL 3.1415926535
+#define DATE_VAL 4.0
+#define F_VAL TRUE
+#define BSTR_STR "This is a BSTR"
+_BSTR BSTR_VAL = {sizeof(BSTR_STR)-1, BSTR_STR};
+#define LPSTR_VAL "This is an LPSTR"
+#define BLOB_VAL "This is binary data for a BLOB"
+#define LPWSTR_VAL L"This is an LPWSTR"
+#define STREAM_VAL "This is data for an IStream"
+LARGE_INTEGER I8_VAL = {0x12345678, 0x87654321};
+
+WCHAR wcsNames[CTOTPROPS][CWCSTORAGENAME];
+WCHAR *pwcsNames[CTOTPROPS];
+
+IStorage *pstgProp;
+IStream *pstmProp;
+
+int prop_index(DFPROPTYPE dpt)
+{
+ int i;
+
+ for (i = 0; i<CPROPS; i++)
+ if (dpt == props[i].dpt)
+ return i;
+ printf("** Unknown prop type 0x%X **\n", dpt);
+ return 0;
+}
+
+void MakeSingleVal(DFPROPTYPE dpt, void *pval)
+{
+ switch(dpt)
+ {
+ case VT_I2:
+ *(short int *)pval = (short int)I2_VAL;
+ break;
+ case VT_I4:
+ *(long int *)pval = I4_VAL;
+ break;
+ case VT_R4:
+ *(float *)pval = R4_VAL;
+ break;
+ case VT_R8:
+ *(double *)pval = R8_VAL;
+ break;
+ case VT_CY:
+ CY *pcy;
+ pcy = (CY *)pval;
+ pcy->Lo = 0x43215678;
+ pcy->Hi = 0x56784321;
+ break;
+ case VT_DATE:
+ *(DATE *)pval = DATE_VAL;
+ break;
+ case VT_BSTR:
+ *(BSTR *)pval = (BSTR)&BSTR_VAL.str;
+ break;
+ case VT_BOOL:
+ *(VARIANT_BOOL *)pval = F_VAL;
+ break;
+ case VT_I8:
+ *(LARGE_INTEGER *)pval = I8_VAL;
+ break;
+ case VT_LPSTR:
+ *(LPSTR *)pval = LPSTR_VAL;
+ break;
+ case VT_BLOB:
+ BLOB *pblob;
+ pblob = new BLOB;
+#ifndef ZERO_LENGTH_BLOB
+ pblob->cbSize = sizeof(BLOB_VAL);
+#else
+ pblob->cbSize = 0;
+#endif
+ pblob->pBlobData = (BYTE *)BLOB_VAL;
+ *(BLOB **)pval = pblob;
+ break;
+ case VT_LPWSTR:
+ *(LPWSTR *)pval = LPWSTR_VAL;
+ break;
+ case VT_FILETIME:
+ FILETIME *pstm;
+ pstm = (FILETIME *)pval;
+ pstm->dwLowDateTime = 0x11223344;
+ pstm->dwHighDateTime = 0x55667788;
+ break;
+ case VT_UUID:
+ *(GUID **)pval = (GUID *)&IID_IStorage;
+ break;
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ *(IStream **)pval = pstmProp;
+ break;
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ *(IStorage **)pval = pstgProp;
+ break;
+ default:
+ printf("** Unknown property type in MakeVal: %X\n", dpt);
+ break;
+ }
+}
+
+void MakeVal(DFPROPTYPE dpt, VARIANT *pval)
+{
+ int i;
+
+ pval->vt = dpt;
+ if (dpt & VT_VECTOR)
+ {
+ BYTE *pb;
+ int indx;
+
+ indx = prop_index(dpt & ~VT_VECTOR);
+ pval->pcai = new CAI;
+ pval->pcai->cElems = ARRAY_SIZE;
+ pb = new BYTE[props[indx].size*ARRAY_SIZE];
+ pval->pcai->pElems = (short int *)pb;
+ for (i = 0; i<ARRAY_SIZE; i++)
+ {
+ MakeSingleVal(dpt & ~VT_VECTOR, pb);
+ pb += props[indx].size;
+ }
+ }
+ else
+ MakeSingleVal(dpt, &pval->iVal);
+}
+
+void UnmakeVal(VARIANT *pval)
+{
+ if (pval->vt & VT_VECTOR)
+ {
+ delete pval->pcai->pElems;
+ delete pval->pcai;
+ }
+ else if (pval->vt == VT_BLOB)
+ delete pval->pblob;
+}
+
+void DispSingleVal(DFPROPTYPE dpt, void *pval)
+{
+ switch(dpt)
+ {
+ case VT_EMPTY:
+ printf("empty\n");
+ break;
+ case VT_NULL:
+ printf("null\n");
+ break;
+ case VT_I2:
+ printf("0x%04hX\n", *(short int *)pval);
+ break;
+ case VT_I4:
+ printf("0x%08lX\n", *(long int *)pval);
+ break;
+ case VT_R4:
+ printf("%f\n", *(float *)pval);
+ break;
+ case VT_R8:
+ printf("%lf\n", *(double *)pval);
+ break;
+ case VT_CY:
+ CY *pcy;
+ pcy = (CY *)pval;
+ printf("0x%08lX:0x%08lX\n", pcy->Hi, pcy->Lo);
+ break;
+ case VT_DATE:
+ printf("%lf\n", *(DATE *)pval);
+ break;
+ case VT_BSTR:
+ printf("string form: '%s'\n", *(BSTR *)pval);
+ printf("binary form: %lu bytes\n",
+ *(UINT *)((BYTE *)*(BSTR *)pval-sizeof(UINT)));
+ BinText(*(UINT *)((BYTE *)*(BSTR *)pval-sizeof(UINT)),
+ (BYTE *)*(BSTR *)pval);
+ break;
+ case VT_BOOL:
+ printf("%d\n", *(VARIANT_BOOL *)pval);
+ break;
+ case VT_I8:
+ LARGE_INTEGER *pli;
+ pli = (LARGE_INTEGER *)pval;
+ printf("0x%08lX:%08lX\n", pli->HighPart, pli->LowPart);
+ break;
+ case VT_LPSTR:
+ printf("'%s'\n", *(LPSTR *)pval);
+ break;
+ case VT_BLOB:
+ BLOB *pblob;
+ pblob = *(BLOB **)pval;
+ printf("%lu bytes\n", pblob->cbSize);
+ BinText(pblob->cbSize, pblob->pBlobData);
+ break;
+ case VT_LPWSTR:
+ #define BUFSIZE 256
+ char szVal[BUFSIZE];
+ wcstombs(szVal, *(LPWSTR *)pval, BUFSIZE);
+ printf("'%s'\n", szVal);
+ break;
+ case VT_FILETIME:
+ FILETIME *pstm;
+ pstm = (FILETIME *)pval;
+ printf("0x%08lX:0x%08lX\n", pstm->dwHighDateTime, pstm->dwLowDateTime);
+ break;
+ case VT_UUID:
+ printf("UUID: %s\n", GuidText(*(GUID **)pval));
+ break;
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ IStream *pistm;
+ pistm = *(IStream **)pval;
+ BYTE buf[2*sizeof(STREAM_VAL)];
+ ULONG cbRead;
+ pistm->Read(buf, 2*sizeof(STREAM_VAL), &cbRead);
+ printf("read %lu bytes\n", cbRead);
+ BinText(cbRead, buf);
+ break;
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ IStorage *pistg;
+ pistg = *(IStorage **)pval;
+ printf("contents:\n");
+ c_tree(pistg);
+ break;
+ default:
+ printf("** Unknown property type in DispVal: 0x%X\n", dpt);
+ break;
+ }
+}
+
+void DispVal(VARIANT *pdpv)
+{
+ ULONG i;
+ DFPROPTYPE dpt;
+
+ dpt = pdpv->vt & ~VT_VECTOR;
+ printf("%s val is ", props[prop_index(dpt)].pszName);
+ if (pdpv->vt & VT_VECTOR)
+ {
+ BYTE *pb = (BYTE *)pdpv->pcai->pElems;
+ int indx = prop_index(dpt);
+
+ printf("%lu element array:\n", pdpv->pcai->cElems);
+ for (i = 0; i<pdpv->pcai->cElems; i++)
+ {
+ printf(" %02d - ", i+1);
+ DispSingleVal(dpt, pb);
+ pb += props[indx].size;
+ }
+ }
+ else
+ DispSingleVal(dpt, &pdpv->iVal);
+}
+
+void test_props(IPropertyStorage *pprop)
+{
+ VARIANT val[CTOTPROPS], *pval;
+ PROPSPEC pspec[CTOTPROPS];
+ ULONG i, cProps;
+ WCHAR *pwcs, **ppwcs;
+ FILETIME dtm, ttl;
+ PROPID id[CTOTPROPS];
+ HRESULT hr;
+
+ // Set up property value data
+ pval = val;
+ pwcs = (WCHAR *)&wcsNames[0];
+ ppwcs = pwcsNames;
+ cProps = 0;
+ for (i = 0; i < CPROPS; i++)
+ {
+#if 1
+ pspec[cProps].ulKind = PRSPEC_LPWSTR;
+ pspec[cProps].lpwstr = pwcs;
+#else
+ pspec[cProps].ulKind = PRSPEC_DISPID;
+ pspec[cProps].dispid = i;
+#endif
+ mbstowcs(pwcs, props[i].pszName, CWCSTORAGENAME);
+ *ppwcs++ = pwcs;
+ pwcs += CWCSTORAGENAME;
+ MakeVal(props[i].dpt, pval++);
+ cProps++;
+#if 1
+ if (props[i].fArray)
+ {
+ pspec[cProps].ulKind = PRSPEC_LPWSTR;
+ pspec[cProps].lpwstr = pwcs;
+ pwcs[0] = L'#';
+ mbstowcs(pwcs+1, props[i].pszName, CWCSTORAGENAME);
+ *ppwcs++ = pwcs;
+ pwcs += CWCSTORAGENAME;
+ MakeVal(props[i].dpt | VT_VECTOR, pval++);
+ cProps++;
+ }
+#endif
+ }
+ printf("%lu properties\n", cProps);
+
+ // WriteMultiple for named properties
+ hr = pprop->WriteMultiple(cProps, pspec, id, val);
+ Result(hr, "WriteMultiple");
+ for (i = 0; i < cProps; i++)
+ {
+ printf("%2d propid is %lu\n", i, id[i]);
+ UnmakeVal(&val[i]);
+ }
+
+#if 1
+ // ReadMultiple for named properties
+ hr = pprop->ReadMultiple(cProps, pspec, &dtm, &ttl, id, &pval);
+ Result(hr, "ReadMultiple");
+ printf("dtm is %s\n", FileTimeText(&dtm));
+ printf("ttl is 0x%08lX:%08lX\n", ttl.dwHighDateTime, ttl.dwLowDateTime);
+ for (i = 0; i<cProps; i++)
+ {
+ printf("%2d propid is %lu\n", i, id[i]);
+ DispVal(&pval[i]);
+ }
+
+ hr = FreeVariantArray(cProps, pval);
+ Result(hr, "FreeVariantArray");
+#endif
+
+#if 0
+ // GetIDsOfNames
+ hr = pprop->GetIDsOfNames(cProps, pwcsNames, id);
+ Result(hr, "GetIDsOfNames");
+ for (i = 0; i < cProps; i++)
+ printf("%2d propid is %lu\n", i, id[i]);
+#endif
+
+#if 1
+ // Non-existent property
+ PROPSPEC pspecNot;
+ pspecNot.ulKind = PRSPEC_LPWSTR;
+ pspecNot.lpwstr = L"NotThere";
+ hr = pprop->ReadMultiple(1, &pspecNot, &dtm, &ttl, id, &pval);
+ Result(hr, "ReadMultiple on non-existent property");
+ for (i = 0; i<1; i++)
+ {
+ printf("%2d propid is %lu\n", i, id[i]);
+ DispVal(&pval[i]);
+ }
+ hr = FreeVariantArray(1, pval);
+ Result(hr, "FreeVariantArray");
+#endif
+
+#if 1
+ // Enumerator test
+ IEnumSTATPROPSTG *penm;
+ STATPROPSTG stat;
+ char szName[CWCSTORAGENAME];
+
+ hr = pprop->Enum(&penm);
+ Result(hr, "Enum");
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result(hr, "Next");
+ if (GetScode(hr) == S_FALSE)
+ break;
+ if (stat.lpwstrName)
+ {
+ wcstombs(szName, stat.lpwstrName, CWCSTORAGENAME);
+ CoMemFree(stat.lpwstrName);
+ printf("%s, ", szName);
+ }
+ printf("vt 0x%X, did %lu, pid %lu, size %lu\n", stat.vt, stat.dispid,
+ stat.propid, stat.cbSize);
+ }
+ printf("Release enumerator = %lu\n",
+ penm->Release());
+#endif
+
+#if 1
+ // DeleteMultiple
+ hr = pprop->DeleteMultiple(cProps, pspec);
+ Result(hr, "DeleteMultiple");
+ hr = pprop->Enum(&penm);
+ Result(hr, "Enum");
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result(hr, "Next");
+ if (GetScode(hr) == S_FALSE)
+ break;
+ if (stat.lpwstrName)
+ {
+ wcstombs(szName, stat.lpwstrName, CWCSTORAGENAME);
+ CoMemFree(stat.lpwstrName);
+ printf("%s, ", szName);
+ }
+ printf("vt 0x%X, did %lu, pid %lu, size %lu\n", stat.vt, stat.dispid,
+ stat.propid, stat.cbSize);
+ }
+ printf("Release enumerator = %lu\n",
+ penm->Release());
+#endif
+
+ // Get a propid
+ pspec[0].ulKind = PRSPEC_DISPID;
+ pspec[0].dispid = 2;
+ MakeVal(VT_I2, val);
+ cProps = 1;
+ hr = pprop->WriteMultiple(cProps, pspec, id, val);
+ Result(hr, "WriteMultiple");
+
+ // WriteMultiple with ids and names
+ pspec[0].ulKind = PRSPEC_DISPID;
+ pspec[0].dispid = 1;
+ MakeVal(VT_I2, val);
+ pspec[1].ulKind = PRSPEC_LPWSTR;
+ pspec[1].lpwstr = L"TestName";
+ MakeVal(VT_I4, val+1);
+ pspec[2].ulKind = PRSPEC_PROPID;
+ pspec[2].propid = id[0];
+ MakeVal(VT_I8, val+2);
+ cProps = 3;
+
+ hr = pprop->WriteMultiple(cProps, pspec, id, val);
+ Result(hr, "WriteMultiple");
+ for (i = 0; i < cProps; i++)
+ {
+ printf("%2d propid is %lu\n", i, id[i]);
+ UnmakeVal(&val[i]);
+ }
+
+ // ReadMultiple for ids and id for a named property
+ pspec[1].ulKind = PRSPEC_PROPID;
+ pspec[1].propid = id[1];
+ hr = pprop->ReadMultiple(cProps, pspec, &dtm, &ttl, id, &pval);
+ Result(hr, "ReadMultiple");
+ printf("dtm is %s\n", FileTimeText(&dtm));
+ printf("ttl is 0x%08lX:%08lX\n", ttl.dwHighDateTime, ttl.dwLowDateTime);
+ for (i = 0; i<cProps; i++)
+ {
+ printf("%2d propid is %lu\n", i, id[i]);
+ DispVal(&pval[i]);
+ }
+
+ hr = FreeVariantArray(cProps, pval);
+ Result(hr, "FreeVariantArray");
+}
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg, *pstgRoot;
+ IPropertySetStorage *ppset;
+ IPropertyStorage *pprop;
+ HRESULT hr;
+
+ StartTest("oprop");
+ CmdArgs(argc, argv);
+
+ CreateTestFile(NULL, ROOTP(STGM_RW) | STGM_CREATE, FALSE, &pstgRoot, NULL);
+
+ hr = pstgRoot->QueryInterface(IID_IPropertySetStorage,
+ (void **)&ppset);
+ Result(hr, "QI to IPropertySetStorage");
+ hr = ppset->Create(IID_IPropertySetStorage, STGP(STGM_RW), 0,
+ &pprop);
+ Result(hr, "Create propset");
+
+ hr = pstgRoot->Commit(0);
+ Result(hr, "Commit root");
+ pprop->Release();
+ ppset->Release();
+ pstgRoot->Release();
+ OpenTestFile(NULL, ROOTP(STGM_RW), FALSE, &pstgRoot, NULL);
+ hr = pstgRoot->QueryInterface(IID_IPropertySetStorage,
+ (void **)&ppset);
+ Result(hr, "QI to IPropertySetStorage");
+ hr = ppset->Open(IID_IPropertySetStorage, STGP(STGM_RW), &pprop);
+ Result(hr, "Open propset");
+
+#if 0
+ // BUGBUG - Should be in propset if possible
+ pstg = pstgRoot;
+ hr = pstg->CreateStorage(TEXT("Storage"), STGP(STGM_RW), 0, 0,
+ &pstgProp);
+ Result(hr, "Create embedding in propset");
+ hr = pstgProp->CreateStream(TEXT("Stream"), STMP(STGM_RW), 0, 0,
+ &pstmProp);
+ Result(hr, "Create stream in embedding");
+ hr = pstmProp->Write(STREAM_VAL, sizeof(STREAM_VAL), NULL);
+ Result(hr, "Write to stream");
+ LARGE_INTEGER lOff;
+ LISet32(lOff, 0);
+ hr = pstmProp->Seek(lOff, STREAM_SEEK_SET, NULL);
+ Result(hr, "Seek to zero");
+#endif
+
+ test_props(pprop);
+
+ printf("Release IPropertyStorage = %lu\n",
+ pprop->Release());
+#if 0
+ printf("Release stream = %lu\n",
+ pstmProp->Release());
+ printf("Release embedding = %lu\n",
+ pstgProp->Release());
+#endif
+#if 0
+ printf("Release cheat IStorage = %lu\n",
+ pstg->Release());
+#endif
+
+ hr = ppset->Open(IID_IPropertySetStorage, STGP(STGM_RW), &pprop);
+ Result(hr, "Open propset");
+ printf("Release IPropertyStorage = %lu\n",
+ pprop->Release());
+
+#if 1
+ IEnumSTATPROPSETSTG *penm;
+ STATPROPSETSTG stat;
+
+ hr = ppset->Enum(&penm);
+ Result(hr, "Enum");
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result(hr, "Next");
+ if (GetScode(hr) == S_FALSE)
+ break;
+ printf("IID: %s\n", GuidText(&stat.iid));
+ printf("ctime %s\n", FileTimeText(&stat.ctime));
+ printf("mtime %s\n", FileTimeText(&stat.mtime));
+ printf("atime %s\n", FileTimeText(&stat.atime));
+ }
+ printf("Release enumerator = %lu\n",
+ penm->Release());
+
+#if 0
+ hr = ppset->Delete(IID_IPropertySetStorage);
+ Result(hr, "Delete propset");
+ hr = ppset->Enum(&penm);
+ Result(hr, "Enum");
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result(hr, "Next");
+ if (GetScode(hr) == S_FALSE)
+ break;
+ printf("IID: %s\n", GuidText(&stat.iid));
+ printf("ctime %s\n", FileTimeText(&stat.ctime));
+ printf("mtime %s\n", FileTimeText(&stat.mtime));
+ printf("atime %s\n", FileTimeText(&stat.atime));
+ }
+ printf("Release enumerator = %lu\n",
+ penm->Release());
+#endif
+#endif
+
+ printf("Release IPropertySetStorage = %lu\n",
+ ppset->Release());
+ printf("Release root docfile = %lu\n",
+ pstgRoot->Release());
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/pch.cxx b/private/ole32/stg/docfile/tests/pch.cxx
new file mode 100644
index 000000000..96fc7deed
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/pch.cxx
@@ -0,0 +1,20 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: pch.cxx
+//
+// Contents: Precompiled header file
+//
+// History: 03-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+
+#include "tsupp.hxx"
diff --git a/private/ole32/stg/docfile/tests/pp.cxx b/private/ole32/stg/docfile/tests/pp.cxx
new file mode 100644
index 000000000..9d95935b4
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/pp.cxx
@@ -0,0 +1,54 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: pp.cxx
+//
+// Contents: PowerPoint commit failure repro
+//
+// History: 07-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstgRoot, *pstgObj;
+ IStream *pstm;
+ HRESULT hr;
+
+ StartTest("pp");
+ CmdArgs(argc, argv);
+
+ hr = StgCreateDocfile(NULL, 0x11022, 0, &pstgRoot);
+ Result(hr, "Create docfile");
+ hr = pstgRoot->CreateStream(TTEXT("PP40"), 0x1012, 0, 0, &pstm);
+ Result(hr, "Create PP40");
+ pstm->Release();
+ hr = pstgRoot->CreateStorage(TTEXT("Object1"), 0x10012, 0, 0, &pstgObj);
+ Result(hr, "Create Object1");
+ hr = pstgObj->CreateStream(TTEXT(".Ole"), 0x1011, 0, 0, &pstm);
+ Result(hr, "Create .Ole");
+ pstm->Release();
+ hr = pstgObj->CreateStream(TTEXT(".CompObj"), 0x1011, 0, 0, &pstm);
+ Result(hr, "Create .CompObj");
+ pstm->Release();
+ hr = pstgObj->CreateStream(TTEXT(".Ole10Native"), 0x1011, 0, 0, &pstm);
+ Result(hr, "Create .Ole10Native");
+ pstm->Release();
+ hr = pstgObj->Commit(0);
+ Result(hr, "Commit Object1");
+
+ DfSetResLimit(DBR_XSCOMMITS, 3);
+ hr = pstgRoot->Commit(0);
+ IllResult(hr, "Commit root");
+
+ pstgObj->Release();
+ pstgRoot->Release();
+
+ EndTest(0);
+}
+
diff --git a/private/ole32/stg/docfile/tests/priority.cxx b/private/ole32/stg/docfile/tests/priority.cxx
new file mode 100644
index 000000000..fca5da231
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/priority.cxx
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tsupp.hxx"
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstgNorm, *pstgPrior;
+ IStream *pstm;
+ SCODE sc;
+ HRESULT hr;
+
+ StartTest("priority");
+ CmdArgs(argc, argv);
+
+ hr = StgCreateDocfile(TEXT("TEST.DFL"), STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, &pstgNorm);
+ Result("Create root docfile", hr);
+ hr = pstgNorm->CreateStream(TEXT("Test"), STMP(STGM_RW), 0, 0, &pstm);
+ Result("Create stream", hr);
+ pstm->Release();
+ pstgNorm->Release();
+
+ hr = StgOpenStorage(TEXT("TEST.DFL"), NULL, STGM_READWRITE |
+ STGM_TRANSACTED | STGM_SHARE_DENY_WRITE,
+ NULL, 0, &pstgNorm);
+ Result("Open root storage T/R/W/DW", hr);
+ hr = StgOpenStorage(TEXT("TEST.DFL"), NULL, STGM_DIRECT | STGM_PRIORITY |
+ STGM_SHARE_DENY_NONE, NULL, 0, &pstgPrior);
+ Result("Open priority mode", hr);
+
+ hr = pstgPrior->OpenStream(TEXT("Test"), NULL, STMP(STGM_READ), 0, &pstm);
+ Result("Open stream from priority", hr);
+ pstm->Release();
+
+ hr = pstgNorm->OpenStream(TEXT("Test"), NULL, STMP(STGM_RW), 0, &pstm);
+ Result("Open stream from normal storage", hr);
+
+ hr = pstm->Write("Hello world", 4, NULL);
+ IllResult("Illegal write to stream", hr);
+
+ printf("Release priority\n");
+ pstgPrior->Release();
+
+ hr = pstm->Write("Hello world", 4, NULL);
+ Result("Write to stream", hr);
+
+ pstm->Release();
+ pstgNorm->Release();
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/prop.cxx b/private/ole32/stg/docfile/tests/prop.cxx
new file mode 100644
index 000000000..396008383
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/prop.cxx
@@ -0,0 +1,955 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: prop.cxx
+//
+// Contents: Non-OFS property test
+//
+// History: 03-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+struct PropDesc
+{
+ DFPROPTYPE dpt;
+ char *pszName;
+ BOOL fArray;
+ size_t size;
+};
+
+PropDesc props[] =
+{
+ VT_EMPTY, "Empty", FALSE, 0,
+ VT_I2, "I2", TRUE, sizeof(short int),
+ VT_I4, "I4", TRUE, sizeof(long int),
+ VT_R4, "R4", TRUE, sizeof(float),
+ VT_R8, "R8", TRUE, sizeof(double),
+ VT_CY, "Currency", TRUE, sizeof(CY),
+ VT_DATE, "Date", TRUE, sizeof(DATE),
+ VT_BSTR, "Basic string", TRUE, sizeof(BSTR),
+ VT_WBSTR, "Wide basic string", TRUE, sizeof(WBSTR),
+ VT_BOOL, "BOOL", TRUE, sizeof(VARIANT_BOOL),
+ VT_I8, "I8", TRUE, sizeof(LARGE_INTEGER),
+ VT_LPSTR, "char string", TRUE, sizeof(LPSTR),
+ VT_BLOB, "BLOB", FALSE, sizeof(BLOB),
+ VT_BLOB_OBJECT, "BLOB object", FALSE, sizeof(BLOB),
+ VT_LPWSTR, "WCHAR string", TRUE, sizeof(LPWSTR),
+ VT_FILETIME, "File time", TRUE, sizeof(FILETIME),
+ VT_UUID, "UUID", TRUE, sizeof(GUID),
+ VT_VARIANT, "Variant", TRUE, sizeof(VARIANT),
+ VT_STREAM, "Stream", FALSE, sizeof(IStream *),
+ VT_STREAMED_OBJECT, "Streamed object", FALSE, sizeof(IStream *),
+ VT_STORAGE, "Storage", FALSE, sizeof(IStorage *),
+ VT_STORED_OBJECT, "Stored object", FALSE, sizeof(IStorage *),
+ VT_CF, "Clipboard data", FALSE, sizeof(CLIPDATA)
+};
+#define CPROPS (sizeof(props)/sizeof(props[0]))
+#define CTOTPROPS (2*CPROPS)
+
+#define ARRAY_SIZE 16
+
+#define BSTR_PTR(pb) ((BYTE *)(pb)-sizeof(UINT))
+#define BSTR_LEN(pb) (*(UINT *)BSTR_PTR(pb)+sizeof(UINT)+1)
+#define WBSTR_PTR(pb) ((BYTE *)(pb)-sizeof(UINT))
+#define WBSTR_LEN(pb) (*(UINT *)WBSTR_PTR(pb)+sizeof(UINT)+sizeof(WCHAR))
+
+struct _BSTR
+{
+ UINT len;
+ char str[80];
+};
+
+struct _WBSTR
+{
+ UINT len;
+ WCHAR str[80];
+};
+
+#define I2_VAL ((short)0x8564)
+#define I4_VAL ((long)0xfef1f064)
+#define R4_VAL ((float)1.25)
+#define R8_VAL ((double)3.1415926535)
+#define DATE_VAL ((DATE)4.0)
+#define F_VAL ((VARIANT_BOOL)TRUE)
+#define BSTR_STR "This is a BSTR"
+_BSTR BSTR_STRUCT = {sizeof(BSTR_STR)-1, BSTR_STR};
+#define BSTR_VAL ((BSTR)(&BSTR_STRUCT.str))
+#define WBSTR_STR L"This is a WBSTR"
+_WBSTR WBSTR_STRUCT = {sizeof(WBSTR_STR)-sizeof(WCHAR), WBSTR_STR};
+#define WBSTR_VAL ((WBSTR)(&WBSTR_STRUCT.str))
+#define LPSTR_VAL "This is an LPSTR"
+#define BLOB_VAL "This is binary data for a BLOB"
+#define LPWSTR_VAL L"This is an LPWSTR"
+#define STREAM_VAL "This is data for an IStream"
+LARGE_INTEGER I8_VAL = {0x12345678, 0x87654321};
+#define CF_FMT ((ULONG)12345678)
+#define CF_VAL "This is binary data for VT_CF"
+#define VARIANT_VAL VT_R8
+CY CY_VAL = {0x43215678, 0x56784321};
+FILETIME FILETIME_VAL = {0x11223344, 0x55667788};
+#define UUID_VAL IID_IStorage
+
+WCHAR wcsNames[CTOTPROPS][CWCSTORAGENAME];
+WCHAR *pwcsNames[CTOTPROPS];
+
+IStorage *pstgProp;
+IStream *pstmProp;
+
+int prop_index(DFPROPTYPE dpt)
+{
+ int i;
+
+ for (i = 0; i<CPROPS; i++)
+ if (dpt == props[i].dpt)
+ return i;
+ printf("** Unknown prop type 0x%X **\n", dpt);
+ return 0;
+}
+
+void MakeVal(DFPROPTYPE dpt, VARIANT *pval);
+
+void MakeSingleVal(DFPROPTYPE dpt, void *pval)
+{
+ switch(dpt)
+ {
+ case VT_EMPTY:
+ break;
+ case VT_I2:
+ case VT_I2 | VT_VECTOR:
+ *(short int *)pval = (short int)I2_VAL;
+ break;
+ case VT_I4:
+ case VT_I4 | VT_VECTOR:
+ *(long int *)pval = I4_VAL;
+ break;
+ case VT_R4:
+ case VT_R4 | VT_VECTOR:
+ *(float *)pval = R4_VAL;
+ break;
+ case VT_R8:
+ case VT_R8 | VT_VECTOR:
+ *(double *)pval = R8_VAL;
+ break;
+ case VT_CY:
+ case VT_CY | VT_VECTOR:
+ CY *pcy;
+ pcy = (CY *)pval;
+ *pcy = CY_VAL;
+ break;
+ case VT_DATE:
+ case VT_DATE | VT_VECTOR:
+ *(DATE *)pval = DATE_VAL;
+ break;
+ case VT_BSTR:
+ case VT_BSTR | VT_VECTOR:
+ *(BSTR *)pval = BSTR_VAL;
+ break;
+ case VT_WBSTR:
+ case VT_WBSTR | VT_VECTOR:
+ *(WBSTR *)pval = WBSTR_VAL;
+ break;
+ case VT_BOOL:
+ case VT_BOOL | VT_VECTOR:
+ *(VARIANT_BOOL *)pval = F_VAL;
+ break;
+ case VT_I8:
+ case VT_I8 | VT_VECTOR:
+ *(LARGE_INTEGER *)pval = I8_VAL;
+ break;
+ case VT_LPSTR:
+ case VT_LPSTR | VT_VECTOR:
+ *(LPSTR *)pval = LPSTR_VAL;
+ break;
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ BLOB *pblob;
+ pblob = (BLOB *)pval;
+#ifndef ZERO_LENGTH_BLOB
+ pblob->cbSize = sizeof(BLOB_VAL);
+#else
+ pblob->cbSize = 0;
+#endif
+ pblob->pBlobData = (BYTE *)BLOB_VAL;
+ break;
+ case VT_LPWSTR:
+ case VT_LPWSTR | VT_VECTOR:
+ *(LPWSTR *)pval = LPWSTR_VAL;
+ break;
+ case VT_FILETIME:
+ case VT_FILETIME | VT_VECTOR:
+ FILETIME *pstm;
+ pstm = (FILETIME *)pval;
+ *pstm = FILETIME_VAL;
+ break;
+ case VT_UUID:
+ *(GUID **)pval = (GUID *)&UUID_VAL;
+ break;
+ case VT_UUID | VT_VECTOR:
+ memcpy(pval, &UUID_VAL, sizeof(GUID));
+ break;
+ case VT_VARIANT:
+ VARIANT *pvar;
+ pvar = new VARIANT;
+ MakeVal(VARIANT_VAL, pvar);
+ *(VARIANT **)pval = pvar;
+ break;
+ case VT_VARIANT | VT_VECTOR:
+ MakeVal(VARIANT_VAL | VT_VECTOR, (VARIANT *)pval);
+ break;
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ *(IStream **)pval = pstmProp;
+ break;
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ *(IStorage **)pval = pstgProp;
+ break;
+ case VT_CF:
+ CLIPDATA *pcd;
+ pcd = new CLIPDATA;
+ pcd->cbSize = sizeof(CF_VAL)+sizeof(ULONG);
+ pcd->ulClipFmt = CF_FMT;
+ pcd->pClipData = (BYTE *)CF_VAL;
+ *(CLIPDATA **)pval = pcd;
+ break;
+ default:
+ printf("** Unknown property type in MakeVal: %X\n", dpt);
+ break;
+ }
+}
+
+void MakeVal(DFPROPTYPE dpt, VARIANT *pval)
+{
+ int i;
+
+ pval->vt = dpt;
+ if (dpt & VT_VECTOR)
+ {
+ BYTE *pb;
+ int indx;
+
+ indx = prop_index(dpt & VT_TYPEMASK);
+ pval->cai.cElems = ARRAY_SIZE;
+ pb = new BYTE[props[indx].size*ARRAY_SIZE];
+ pval->cai.pElems = (short int *)pb;
+ for (i = 0; i < ARRAY_SIZE; i++)
+ {
+ MakeSingleVal(dpt, pb);
+ pb += props[indx].size;
+ }
+ }
+ else
+ MakeSingleVal(dpt, &pval->iVal);
+}
+
+void UnmakeVal(VARIANT *pval)
+{
+ if (pval->vt & VT_VECTOR)
+ {
+ if ((pval->vt & VT_TYPEMASK) == VT_VARIANT)
+ {
+ ULONG i;
+
+ for (i = 0; i < ARRAY_SIZE; i++)
+ UnmakeVal(pval->cavar.pElems+i);
+ }
+ delete pval->cai.pElems;
+ }
+ else if (pval->vt == VT_VARIANT)
+ {
+ UnmakeVal(pval->pvarVal);
+ delete pval->pvarVal;
+ }
+ else if (pval->vt == VT_CF)
+ delete pval->pClipData;
+}
+
+void DispVal(VARIANT *pdpv);
+
+void DispSingleVal(DFPROPTYPE dpt, void *pval)
+{
+ HRESULT hr;
+
+ switch(dpt)
+ {
+ case VT_ILLEGAL:
+ printf("illegal\n");
+ break;
+ case VT_EMPTY:
+ printf("empty\n");
+ break;
+ case VT_I2:
+ case VT_I2 | VT_VECTOR:
+ printf("0x%04hX\n", *(short int *)pval);
+ break;
+ case VT_I4:
+ case VT_I4 | VT_VECTOR:
+ printf("0x%08lX\n", *(long int *)pval);
+ break;
+ case VT_R4:
+ case VT_R4 | VT_VECTOR:
+ printf("%f\n", *(float *)pval);
+ break;
+ case VT_R8:
+ case VT_R8 | VT_VECTOR:
+ printf("%lf\n", *(double *)pval);
+ break;
+ case VT_CY:
+ case VT_CY | VT_VECTOR:
+ CY *pcy;
+ pcy = (CY *)pval;
+ printf("0x%08lX:0x%08lX\n", pcy->Hi, pcy->Lo);
+ break;
+ case VT_DATE:
+ case VT_DATE | VT_VECTOR:
+ printf("%lf\n", *(DATE *)pval);
+ break;
+ case VT_BSTR:
+ case VT_BSTR | VT_VECTOR:
+ BSTR bstr;
+ bstr = *(BSTR *)pval;
+ printf("string form: '%s'\n", bstr);
+ printf("binary form: %lu bytes\n", BSTR_LEN(bstr));
+ BinText(BSTR_LEN(bstr), BSTR_PTR(bstr));
+ break;
+ case VT_WBSTR:
+ case VT_WBSTR | VT_VECTOR:
+ char str[80];
+ WBSTR wbstr;
+ wbstr = *(WBSTR *)pval;
+ wcstombs(str, wbstr, 80);
+ printf("string form: '%s'\n", str);
+ printf("binary form: %lu bytes\n", WBSTR_LEN(wbstr));
+ BinText(WBSTR_LEN(wbstr), WBSTR_PTR(wbstr));
+ break;
+ case VT_BOOL:
+ case VT_BOOL | VT_VECTOR:
+ printf("%d\n", *(VARIANT_BOOL *)pval);
+ break;
+ case VT_I8:
+ case VT_I8 | VT_VECTOR:
+ LARGE_INTEGER *pli;
+ pli = (LARGE_INTEGER *)pval;
+ printf("0x%08lX:%08lX\n", pli->HighPart, pli->LowPart);
+ break;
+ case VT_LPSTR:
+ case VT_LPSTR | VT_VECTOR:
+ printf("'%s'\n", *(LPSTR *)pval);
+ break;
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ BLOB *pblob;
+ pblob = (BLOB *)pval;
+ printf("%lu bytes\n", pblob->cbSize);
+ BinText(pblob->cbSize, pblob->pBlobData);
+ break;
+ case VT_LPWSTR:
+ case VT_LPWSTR | VT_VECTOR:
+ #define BUFSIZE 256
+ char szVal[BUFSIZE];
+ wcstombs(szVal, *(LPWSTR *)pval, BUFSIZE);
+ printf("'%s'\n", szVal);
+ break;
+ case VT_FILETIME:
+ case VT_FILETIME | VT_VECTOR:
+ FILETIME *pstm;
+ pstm = (FILETIME *)pval;
+ printf("0x%08lX:0x%08lX\n", pstm->dwHighDateTime, pstm->dwLowDateTime);
+ break;
+ case VT_UUID:
+ printf("UUID: %s\n", GuidText(*(GUID **)pval));
+ break;
+ case VT_UUID | VT_VECTOR:
+ printf("UUID: %s\n", GuidText((GUID *)pval));
+ break;
+ case VT_VARIANT:
+ printf("VARIANT type 0x%X: ", (*(VARIANT **)pval)->vt);
+ DispVal(*(VARIANT **)pval);
+ break;
+ case VT_VARIANT | VT_VECTOR:
+ printf("VARIANT type 0x%X: ", ((VARIANT *)pval)->vt);
+ DispVal((VARIANT *)pval);
+ break;
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ IStream *pistm;
+ pistm = *(IStream **)pval;
+ BYTE buf[sizeof(STREAM_VAL)];
+ ULONG cbRead;
+ LARGE_INTEGER li;
+ li.HighPart = 0;
+ li.LowPart = 0;
+ hr = pistm->Seek(li, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr))
+ Result(hr, "DispVal stream seek");
+ hr = pistm->Read(buf, sizeof(STREAM_VAL), &cbRead);
+ if (FAILED(hr))
+ Result(hr, "DispVal stream read");
+ printf("read %lu bytes\n", cbRead);
+ BinText(cbRead, buf);
+ break;
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ IStorage *pistg;
+ pistg = *(IStorage **)pval;
+ printf("contents:\n");
+ c_tree(pistg);
+ break;
+ case VT_CF:
+ CLIPDATA *pcd;
+ pcd = *(CLIPDATA **)pval;
+ printf("%lu bytes, format %lu\n", pcd->cbSize, pcd->ulClipFmt);
+ BinText(pcd->cbSize-sizeof(ULONG), pcd->pClipData);
+ break;
+ default:
+ printf("** Unknown property type in DispVal: 0x%X\n", dpt);
+ break;
+ }
+}
+
+void DispVal(VARIANT *pdpv)
+{
+ ULONG i;
+ DFPROPTYPE dpt;
+
+ dpt = pdpv->vt & VT_TYPEMASK;
+ printf("%s val is ", props[prop_index(dpt)].pszName);
+ if (pdpv->vt & VT_VECTOR)
+ {
+ BYTE *pb = (BYTE *)pdpv->cai.pElems;
+ int indx = prop_index(dpt);
+
+ printf("%lu element array:\n", pdpv->cai.cElems);
+ for (i = 0; i < pdpv->cai.cElems; i++)
+ {
+ printf(" %02d - ", i+1);
+ DispSingleVal(pdpv->vt, pb);
+ pb += props[indx].size;
+ }
+ }
+ else
+ DispSingleVal(pdpv->vt, &pdpv->iVal);
+}
+
+void CheckVal(VARIANT *pdpv);
+
+void CheckSingleVal(DFPROPTYPE dpt, BYTE *pval)
+{
+ HRESULT hr;
+
+ switch(dpt)
+ {
+ case VT_EMPTY:
+ break;
+ case VT_I2:
+ case VT_I2 | VT_VECTOR:
+ if (*(short int *)pval != I2_VAL)
+ Fail("I2 val is %d rather than %d\n", *(short int *)pval,
+ I2_VAL);
+ break;
+ case VT_I4:
+ case VT_I4 | VT_VECTOR:
+ if (*(long int *)pval != I4_VAL)
+ Fail("I4 val is %d rather than %d\n", *(long int *)pval,
+ I4_VAL);
+ break;
+ case VT_R4:
+ case VT_R4 | VT_VECTOR:
+ if (*(float *)pval != R4_VAL)
+ Fail("R4 val is %f rather than %f\n", *(float *)pval,
+ R4_VAL);
+ break;
+ case VT_R8:
+ case VT_R8 | VT_VECTOR:
+ if (*(double *)pval != R8_VAL)
+ Fail("R8 val is %lf rather than %lf\n", *(double *)pval,
+ R8_VAL);
+ break;
+ case VT_CY:
+ case VT_CY | VT_VECTOR:
+ CY *pcy;
+ pcy = (CY *)pval;
+ if (memcmp(pcy, &CY_VAL, sizeof(CY)) != 0)
+ Fail("CY val is 0x%08lX:0x%08lX rather than 0x%08lX:0x%08lX\n",
+ pcy->Hi, pcy->Lo, CY_VAL.Hi, CY_VAL.Lo);
+ break;
+ case VT_DATE:
+ case VT_DATE | VT_VECTOR:
+ if (*(DATE *)pval != DATE_VAL)
+ Fail("DATE val is %lf rather than %lf\n", *(DATE *)pval,
+ DATE_VAL);
+ break;
+ case VT_BSTR:
+ case VT_BSTR | VT_VECTOR:
+ if (BSTR_LEN(*(BSTR *)pval) != BSTR_LEN(BSTR_VAL) ||
+ memcmp(BSTR_PTR(*(BSTR *)pval), BSTR_PTR(BSTR_VAL),
+ BSTR_LEN(BSTR_VAL)) != 0)
+ Fail("BSTR value doesn't match\n");
+ break;
+ case VT_WBSTR:
+ case VT_WBSTR | VT_VECTOR:
+ if (WBSTR_LEN(*(WBSTR *)pval) != WBSTR_LEN(WBSTR_VAL) ||
+ memcmp(WBSTR_PTR(*(WBSTR *)pval), WBSTR_PTR(WBSTR_VAL),
+ WBSTR_LEN(WBSTR_VAL)) != 0)
+ {
+ WBSTR wbstr;
+
+ DispSingleVal(VT_WBSTR, pval);
+ wbstr = WBSTR_VAL;
+ DispSingleVal(VT_WBSTR, &wbstr);
+ Fail("WBSTR value doesn't match\n");
+ }
+ break;
+ case VT_BOOL:
+ case VT_BOOL | VT_VECTOR:
+ if (*(VARIANT_BOOL *)pval != F_VAL)
+ Fail("BOOL val is %d rather than %d\n", *(VARIANT_BOOL *)pval,
+ F_VAL);
+ break;
+ case VT_I8:
+ case VT_I8 | VT_VECTOR:
+ LARGE_INTEGER *pli;
+ pli = (LARGE_INTEGER *)pval;
+ if (memcmp(pli, &I8_VAL, sizeof(LARGE_INTEGER)) != 0)
+ Fail("I8 val is 0x%08lX:0x%08lX rather than 0x%08lX:0x%08lX\n",
+ pli->HighPart, pli->LowPart, I8_VAL.HighPart,
+ I8_VAL.LowPart);
+ break;
+ case VT_LPSTR:
+ case VT_LPSTR | VT_VECTOR:
+ if (strcmp(*(LPSTR *)pval, LPSTR_VAL) != 0)
+ Fail("LPSTR val is '%s' rather than '%s'\n", *(LPSTR *)pval,
+ LPSTR_VAL);
+ break;
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ BLOB *pblob;
+ pblob = (BLOB *)pval;
+ if (pblob->cbSize != sizeof(BLOB_VAL) ||
+ memcmp(pblob->pBlobData, BLOB_VAL, sizeof(BLOB_VAL)) != 0)
+ Fail("BLOB val doesn't match\n");
+ break;
+ case VT_LPWSTR:
+ case VT_LPWSTR | VT_VECTOR:
+ if (wcscmp(*(LPWSTR *)pval, LPWSTR_VAL) != 0)
+ Fail("LPWSTR val doesn't match\n");
+ break;
+ case VT_FILETIME:
+ case VT_FILETIME | VT_VECTOR:
+ FILETIME *pstm;
+ pstm = (FILETIME *)pval;
+ if (memcmp(pstm, &FILETIME_VAL, sizeof(FILETIME)) != 0)
+ Fail("FILETIME val doesn't match\n");
+ break;
+ case VT_UUID:
+ if (memcmp(*(GUID **)pval, &UUID_VAL, sizeof(GUID)) != 0)
+ Fail("UUID val doesn't match\n");
+ break;
+ case VT_UUID | VT_VECTOR:
+ if (memcmp((GUID *)pval, &UUID_VAL, sizeof(GUID)) != 0)
+ Fail("UUID val doesn't match\n");
+ break;
+ case VT_VARIANT:
+ if ((*(VARIANT **)pval)->vt != VARIANT_VAL)
+ Fail("VARIANT type 0x%X doesn't match 0x%X\n",
+ (*(VARIANT **)pval)->vt, VARIANT_VAL);
+ CheckVal(*(VARIANT **)pval);
+ break;
+ case VT_VARIANT | VT_VECTOR:
+ if (((VARIANT *)pval)->vt != (VARIANT_VAL | VT_VECTOR))
+ Fail("VARIANT type 0x%X doesn't match 0x%X\n",
+ ((VARIANT *)pval)->vt, (VARIANT_VAL | VT_VECTOR));
+ CheckVal((VARIANT *)pval);
+ break;
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ IStream *pistm;
+ pistm = *(IStream **)pval;
+ BYTE buf[sizeof(STREAM_VAL)];
+ ULONG cbRead;
+ STATSTG stat;
+ LARGE_INTEGER li;
+ hr = pistm->Stat(&stat, STATFLAG_NONAME);
+ if (FAILED(hr))
+ Result(hr, "CheckVal stream stat");
+ if (stat.cbSize.HighPart != 0 ||
+ stat.cbSize.LowPart != sizeof(STREAM_VAL))
+ Fail("Stream size doesn't match\n");
+ li.HighPart = 0;
+ li.LowPart = 0;
+ hr = pistm->Seek(li, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr))
+ Result(hr, "CheckVal stream seek");
+ hr = pistm->Read(buf, sizeof(STREAM_VAL), &cbRead);
+ if (FAILED(hr))
+ Result(hr, "CheckVal stream read");
+ if (cbRead != sizeof(STREAM_VAL))
+ Fail("Read %d byte rather than %d\n", cbRead, sizeof(STREAM_VAL));
+ if (memcmp(buf, STREAM_VAL, sizeof(STREAM_VAL)) != 0)
+ Fail("Stream val doesn't match\n");
+ break;
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ IStorage *pistg;
+ pistg = *(IStorage **)pval;
+ // BUGBUG - A real pain to check
+ break;
+ case VT_CF:
+ CLIPDATA *pcd;
+ pcd = *(CLIPDATA **)pval;
+ if (pcd->cbSize-sizeof(ULONG) != sizeof(CF_VAL) ||
+ pcd->ulClipFmt != CF_FMT ||
+ memcmp(pcd->pClipData, CF_VAL, sizeof(CF_VAL)) != 0)
+ Fail("CF val doesn't match\n");
+ break;
+ default:
+ printf("** Unknown property type in CheckVal: 0x%X\n", dpt);
+ break;
+ }
+}
+
+void CheckVal(VARIANT *pdpv)
+{
+ ULONG i;
+
+ if (pdpv->vt & VT_VECTOR)
+ {
+ BYTE *pb = (BYTE *)pdpv->cai.pElems;
+ int indx = prop_index(pdpv->vt & VT_TYPEMASK);
+
+ if (pdpv->cai.cElems != ARRAY_SIZE)
+ Fail("%s array is size %d rather than %d\n", props[indx].pszName,
+ pdpv->cai.cElems, ARRAY_SIZE);
+ for (i = 0; i < pdpv->cai.cElems; i++)
+ {
+ CheckSingleVal(pdpv->vt, pb);
+ pb += props[indx].size;
+ }
+ }
+ else
+ CheckSingleVal(pdpv->vt, (BYTE *)&pdpv->iVal);
+}
+
+void test_props(IPropertyStorage *pprop)
+{
+ VARIANT val[CTOTPROPS], *pval;
+ PROPSPEC pspec[CTOTPROPS];
+ ULONG i, cProps;
+ WCHAR *pwcs, **ppwcs;
+ FILETIME dtm;
+ PROPID pid[CTOTPROPS];
+ HRESULT hr;
+ CStrList sl;
+ SStrEntry *pse;
+
+ // Set up property value data
+ pval = val;
+ pwcs = (WCHAR *)&wcsNames[0];
+ ppwcs = pwcsNames;
+ cProps = 0;
+ for (i = 0; i < CPROPS; i++)
+ {
+ pspec[cProps].ulKind = PRSPEC_LPWSTR;
+ pspec[cProps].lpwstr = pwcs;
+ mbstowcs(pwcs, props[i].pszName, CWCSTORAGENAME);
+ pse = sl.Add(pwcs);
+ pse->user.dw = props[i].dpt;
+ *ppwcs++ = pwcs;
+ pwcs += CWCSTORAGENAME;
+ MakeVal(props[i].dpt, pval++);
+ cProps++;
+ if (props[i].fArray)
+ {
+ pspec[cProps].ulKind = PRSPEC_LPWSTR;
+ pspec[cProps].lpwstr = pwcs;
+ pwcs[0] = L'#';
+ mbstowcs(pwcs+1, props[i].pszName, CWCSTORAGENAME);
+ pse = sl.Add(pwcs);
+ pse->user.dw = props[i].dpt | VT_VECTOR;
+ *ppwcs++ = pwcs;
+ pwcs += CWCSTORAGENAME;
+ MakeVal(props[i].dpt | VT_VECTOR, pval++);
+ cProps++;
+ }
+ }
+ printf("%lu properties\n", cProps);
+
+ // WriteMultiple for named properties
+ hr = pprop->WriteMultiple(cProps, pspec, pid, val);
+ Result(hr, "WriteMultiple");
+ for (i = 0; i < cProps; i++)
+ {
+ printf("%2d propid is %lu\n", i, pid[i]);
+ UnmakeVal(&val[i]);
+ }
+ hr = pprop->Commit(0);
+ Result(hr, "Commit");
+ hr = pprop->Revert();
+ Result(hr, "Revert");
+
+ // ReadMultiple for named properties
+ hr = pprop->ReadMultiple(cProps, pspec, &dtm, pid, val);
+ Result(hr, "ReadMultiple");
+ printf("dtm is %s\n", FileTimeText(&dtm));
+ for (i = 0; i<cProps; i++)
+ {
+ if (pid[i] == PROPID_UNKNOWN)
+ Fail("Property %d not found\n", i);
+ printf("%2d propid is %lu\n", i, pid[i]);
+ DispVal(&val[i]);
+ pse = sl.Find(pspec[i].lpwstr);
+ if (pse == NULL)
+ Fail("Unable to find written property '%s'\n", pspec[i].lpwstr);
+ if (pse->user.dw != val[i].vt)
+ Fail("Property '%s' is type %d rather than %d\n",
+ TcsText(pse->atc), val[i].vt, pse->user.dw);
+ CheckVal(&val[i]);
+ }
+
+ hr = FreeVariantArray(cProps, val);
+ Result(hr, "FreeVariantArray");
+
+#ifdef GET_IDS_OF_NAMES
+ // GetIDsOfNames
+ hr = pprop->GetIDsOfNames(cProps, pwcsNames, pid);
+ Result(hr, "GetIDsOfNames");
+ for (i = 0; i < cProps; i++)
+ printf("%2d propid is %lu\n", i, pid[i]);
+#endif
+
+ // Non-existent property
+ PROPSPEC pspecNot;
+ pspecNot.ulKind = PRSPEC_LPWSTR;
+ pspecNot.lpwstr = L"NotThere";
+ hr = pprop->ReadMultiple(1, &pspecNot, &dtm, pid, val);
+ Result(hr, "ReadMultiple on non-existent property");
+ DispVal(&val[0]);
+ if (val[0].vt != VT_ILLEGAL)
+ Fail("Nonexistent property returned a real value %d\n", val[0].vt);
+ if (pid[0] != PROPID_UNKNOWN)
+ Fail("Nonexistent property returned a real propid %lu\n", pid[0]);
+
+ // Enumerator test
+ IEnumSTATPROPSTG *penm;
+ STATPROPSTG stat;
+ char szName[CWCSTORAGENAME];
+
+ hr = pprop->Enum(&penm);
+ Result(hr, "Enum");
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result(hr, "Next");
+ if (GetScode(hr) == S_FALSE)
+ break;
+ if (stat.lpwstrName)
+ {
+ wcstombs(szName, stat.lpwstrName, CWCSTORAGENAME);
+ CoMemFree(stat.lpwstrName);
+ pse = sl.Find(stat.lpwstrName);
+ if (pse == NULL)
+ {
+ Fail("Enumerator returned unknown name '%s'\n", szName);
+ }
+ if (pse->user.dw != stat.vt)
+ Fail("Property '%s' is type %d rather than %d\n",
+ szName, val[i].vt, pse->user.dw);
+ sl.Remove(pse);
+ printf("%s, ", szName);
+ }
+ else
+ {
+ Fail("Enumerator returned unnamed property "
+ "dispid %lu, propid %lu\n",
+ stat.dispid, stat.propid);
+ }
+ printf("vt 0x%X, did %lu, pid %lu, size %lu\n", stat.vt, stat.dispid,
+ stat.propid, stat.cbSize);
+ }
+ printf("Release enumerator = %lu\n",
+ penm->Release());
+ if (sl.GetHead())
+ {
+ for (pse = sl.GetHead(); pse; pse = pse->pseNext)
+ printf("Enumerator didn't return '%s'\n", TcsText(pse->atc));
+ Fail("Missing elements in enumeration\n");
+ }
+
+ // DeleteMultiple
+ BOOL fPresent;
+ fPresent = FALSE;
+ hr = pprop->DeleteMultiple(cProps, pspec);
+ Result(hr, "DeleteMultiple");
+ hr = pprop->Enum(&penm);
+ Result(hr, "Enum");
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result(hr, "Next");
+ if (GetScode(hr) == S_FALSE)
+ break;
+ fPresent = TRUE;
+ wcstombs(szName, stat.lpwstrName, CWCSTORAGENAME);
+ CoMemFree(stat.lpwstrName);
+ printf("%s, vt 0x%X, did %lu, pid %lu, size %lu\n",
+ szName, stat.vt, stat.dispid, stat.propid, stat.cbSize);
+ }
+ printf("Release enumerator = %lu\n",
+ penm->Release());
+ if (fPresent)
+ Fail("Enumeration returned entries after DeleteMultiple\n");
+
+#ifdef GET_IDS_OF_NAMES
+ // GetIDsOfNames on deleted entries
+ hr = pprop->GetIDsOfNames(cProps, pwcsNames, did);
+ Result(hr, "GetIDsOfNames on deleted");
+ for (i = 0; i < cProps; i++)
+ printf("%2d dispid is %lu\n", i, did[i]);
+#endif
+
+ // WriteMultiple with ids and names
+ pspec[0].ulKind = PRSPEC_DISPID;
+ pspec[0].dispid = 1;
+ MakeVal(VT_I2, val);
+ pspec[1].ulKind = PRSPEC_LPWSTR;
+ pspec[1].lpwstr = L"TestName";
+ MakeVal(VT_I4, val+1);
+ pspec[2].ulKind = PRSPEC_PROPID;
+ // Hack
+ pspec[2].propid = PROPID_FIRST-1;
+ MakeVal(VT_I8, val+2);
+ cProps = 3;
+
+ hr = pprop->WriteMultiple(cProps, pspec, pid, val);
+ Result(hr, "WriteMultiple");
+ for (i = 0; i < cProps; i++)
+ {
+ printf("%2d propid is %lu\n", i, pid[i]);
+ UnmakeVal(&val[i]);
+ }
+
+ // ReadMultiple for ids and id for a named property
+ pspec[1].ulKind = PRSPEC_PROPID;
+ pspec[1].propid = pid[1];
+ hr = pprop->ReadMultiple(cProps, pspec, &dtm, pid, val);
+ Result(hr, "ReadMultiple");
+ printf("dtm is %s\n", FileTimeText(&dtm));
+ for (i = 0; i<cProps; i++)
+ {
+ printf("%2d propid is %lu\n", i, pid[i]);
+ DispVal(&val[i]);
+ CheckVal(&val[i]);
+ }
+
+ hr = FreeVariantArray(cProps, val);
+ Result(hr, "FreeVariantArray");
+}
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg, *pstgRoot;
+ IPropertySetStorage *ppset;
+ IPropertyStorage *pprop;
+ HRESULT hr;
+ STATPROPSETSTG stat;
+
+ StartTest("prop");
+ CmdArgs(argc, argv);
+
+ CreateTestFile(NULL, ROOTP(STGM_RW) | STGM_CREATE, FALSE, &pstgRoot, NULL);
+
+ hr = pstgRoot->QueryInterface(IID_IPropertySetStorage,
+ (void **)&ppset);
+ Result(hr, "QI to IPropertySetStorage");
+ hr = ppset->Create(IID_IPropertySetStorage, STGP(STGM_RW), &pprop);
+ Result(hr, "Create propset");
+
+ hr = pprop->QueryInterface(IID_IStorage, (void **)&pstg);
+ Result(hr, "Cheat QI to IStorage");
+ hr = pstg->CreateStorage(TEXT("Storage"), STGP(STGM_RW), 0, 0,
+ &pstgProp);
+ Result(hr, "Create embedding in propset");
+ hr = pstgProp->CreateStream(TEXT("Stream"), STMP(STGM_RW), 0, 0,
+ &pstmProp);
+ Result(hr, "Create stream in embedding");
+ hr = pstmProp->Write(STREAM_VAL, sizeof(STREAM_VAL), NULL);
+ Result(hr, "Write to stream");
+ LARGE_INTEGER lOff;
+ LISet32(lOff, 0);
+ hr = pstmProp->Seek(lOff, STREAM_SEEK_SET, NULL);
+ Result(hr, "Seek to zero");
+
+ hr = pprop->Stat(&stat);
+ Result(hr, "Stat propset");
+ if (!IsEqualIID(stat.iid, IID_IPropertySetStorage))
+ Fail("Property set Stat returned GUID %s\n", GuidText(&stat.iid));
+
+ printf("IID: %s\n", GuidText(&stat.iid));
+ printf("ctime %s\n", FileTimeText(&stat.ctime));
+ printf("mtime %s\n", FileTimeText(&stat.mtime));
+ printf("atime %s\n", FileTimeText(&stat.atime));
+
+ test_props(pprop);
+
+ printf("Release IPropertyStorage = %lu\n",
+ pprop->Release());
+ printf("Release stream = %lu\n",
+ pstmProp->Release());
+ printf("Release embedding = %lu\n",
+ pstgProp->Release());
+ printf("Release cheat IStorage = %lu\n",
+ pstg->Release());
+
+ hr = ppset->Open(IID_IPropertySetStorage, STGP(STGM_RW), &pprop);
+ Result(hr, "Open propset");
+ printf("Release IPropertyStorage = %lu\n",
+ pprop->Release());
+
+ IEnumSTATPROPSETSTG *penm;
+
+ hr = ppset->Enum(&penm);
+ Result(hr, "Enum");
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result(hr, "Next");
+ if (GetScode(hr) == S_FALSE)
+ break;
+ printf("IID: %s\n", GuidText(&stat.iid));
+ printf("ctime %s\n", FileTimeText(&stat.ctime));
+ printf("mtime %s\n", FileTimeText(&stat.mtime));
+ printf("atime %s\n", FileTimeText(&stat.atime));
+ }
+ printf("Release enumerator = %lu\n",
+ penm->Release());
+
+ hr = ppset->Delete(IID_IPropertySetStorage);
+ Result(hr, "Delete propset");
+ hr = ppset->Enum(&penm);
+ Result(hr, "Enum");
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result(hr, "Next");
+ if (GetScode(hr) == S_FALSE)
+ break;
+ printf("IID: %s\n", GuidText(&stat.iid));
+ printf("ctime %s\n", FileTimeText(&stat.ctime));
+ printf("mtime %s\n", FileTimeText(&stat.mtime));
+ printf("atime %s\n", FileTimeText(&stat.atime));
+ }
+ printf("Release enumerator = %lu\n",
+ penm->Release());
+
+ printf("Release IPropertySetStorage = %lu\n",
+ ppset->Release());
+ printf("Release root docfile = %lu\n",
+ pstgRoot->Release());
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/propcopy.cxx b/private/ole32/stg/docfile/tests/propcopy.cxx
new file mode 100644
index 000000000..c1ca095f9
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/propcopy.cxx
@@ -0,0 +1,180 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: propcopy.cxx
+//
+// Contents: OFS CopyTo property copying test
+//
+// History: 03-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+#define DIMA(ar) (sizeof(ar)/sizeof(ar[0]))
+
+const IID *piids[] =
+{
+ &IID_IPropertySetStorage,
+ &IID_IStorage,
+ &IID_IStream
+};
+#define NSETS DIMA(piids)
+
+struct
+{
+ VARTYPE vt;
+ WCHAR *name;
+ DISPID id;
+} props[] =
+{
+ VT_I4, L"i4", 0,
+ VT_LPSTR, L"lpstr", 0,
+ VT_I2, L"i2", 0,
+ VT_R8, NULL, 1024
+};
+#define NPROPS DIMA(props)
+
+PROPSPEC pspec[NPROPS];
+PROPID propid[NPROPS];
+VARIANT var[NPROPS];
+
+void write_props(IPropertySetStorage *ppset)
+{
+ IPropertyStorage *pprop;
+ int s, p;
+ HRESULT hr;
+
+ for (s = 0; s < NSETS; s++)
+ {
+ hr = ppset->Create(*piids[s], STGP(STGM_RW), 0, &pprop);
+ Result(hr, "Create propset %s", GuidText((GUID *)piids[s]));
+
+ for (p = 0; p < NPROPS; p++)
+ {
+ if (props[p].name)
+ {
+ pspec[p].ulKind = PRSPEC_LPWSTR;
+ pspec[p].lpwstr = props[p].name;
+ }
+ else
+ {
+ pspec[p].ulKind = PRSPEC_DISPID;
+ pspec[p].dispid = props[p].id;
+ }
+
+ VariantInit(&var[p]);
+ var[p].vt = props[p].vt;
+ switch(var[p].vt)
+ {
+ case VT_I2:
+ var[p].iVal = 5;
+ break;
+ case VT_I4:
+ var[p].lVal = 55;
+ break;
+ case VT_R8:
+ var[p].dblVal = 3.1415926535;
+ break;
+ case VT_LPSTR:
+ var[p].pszVal = "Hello";
+ break;
+ }
+ }
+ hr = pprop->WriteMultiple(NPROPS, pspec, propid, var);
+ Result(hr, "WriteMultiple");
+
+ pprop->Release();
+ }
+}
+
+void read_pset(IPropertySetStorage *ppset, IID *piid)
+{
+ IPropertyStorage *pprop;
+ IEnumSTATPROPSTG *penm;
+ STATPROPSTG stat;
+ HRESULT hr;
+
+ hr = ppset->Open(*piid, STGP(STGM_RW), &pprop);
+ Result(hr, "Open %s", GuidText(piid));
+ hr = pprop->Enum(&penm);
+ Result(hr, "Enum");
+
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result(hr, "Next");
+ if (GetScode(hr) == S_FALSE)
+ break;
+
+ wprintf(L"Property name '%s', dispid %d, type %d\n",
+ stat.lpwstrName, stat.dispid, stat.vt);
+ CoMemFree(stat.lpwstrName);
+ }
+ penm->Release();
+ pprop->Release();
+}
+
+void read_props(IPropertySetStorage *ppset)
+{
+ IEnumSTATPROPSETSTG *penm;
+ STATPROPSETSTG stat;
+ HRESULT hr;
+
+ hr = ppset->Enum(&penm);
+ Result(hr, "Enum");
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result(hr, "Next");
+ if (GetScode(hr) == S_FALSE)
+ break;
+ printf("IID: %s\n", GuidText(&stat.iid));
+ printf("ctime %s\n", FileTimeText(&stat.ctime));
+ printf("mtime %s\n", FileTimeText(&stat.mtime));
+ printf("atime %s\n", FileTimeText(&stat.atime));
+ read_pset(ppset, &stat.iid);
+ }
+ penm->Release();
+}
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstgRoot, *pstgDest;
+ IPropertySetStorage *ppset;
+ HRESULT hr;
+
+ StartTest("propcopy");
+ CmdArgs(argc, argv);
+
+ CreateTestFile("test1.dfl", ROOTP(STGM_RW) | STGM_CREATE, FALSE, &pstgRoot,
+ NULL);
+
+ hr = pstgRoot->QueryInterface(IID_IPropertySetStorage,
+ (void **)&ppset);
+ Result(hr, "QI to IPropertySetStorage");
+
+ write_props(ppset);
+ ppset->Release();
+
+ CreateTestFile("test2.dfl", ROOTP(STGM_RW) | STGM_CREATE, FALSE, &pstgDest,
+ NULL);
+
+ hr = pstgRoot->CopyTo(0, NULL, NULL, pstgDest);
+ Result(hr, "CopyTo");
+
+ hr = pstgDest->QueryInterface(IID_IPropertySetStorage,
+ (void **)&ppset);
+ Result(hr, "QI to IPropertySetStorage");
+
+ read_props(ppset);
+ ppset->Release();
+
+ pstgDest->Release();
+ pstgRoot->Release();
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/readtm.cxx b/private/ole32/stg/docfile/tests/readtm.cxx
new file mode 100644
index 000000000..c34439c3c
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/readtm.cxx
@@ -0,0 +1,241 @@
+#define TEST_READ 1
+#define TEST_WRITE 2
+
+char *test_type[] =
+{
+ "",
+ "read",
+ "write"
+};
+
+ULONG ulTest = TEST_READ;
+ULONG ulIter = 5, ulOps = 250, ulSize = 64L*1024L, ulBlock = 4096,
+ ulCtn = 1;
+int fMove = FALSE;
+
+#define MAXBUF 64000L
+char *buf;
+
+#define MAXCTN 64
+CTN ctn_stack[MAXCTN];
+
+void usage(void)
+{
+ printf("%s Version\n", BUILD_TYPE);
+ printf("Usage: readtm [options]\n");
+ printf("Options are:\n");
+ printf(" -? This list\n");
+ printf(" -t # Test number:\n");
+ printf(" %d - Reads, default\n", TEST_READ);
+ printf(" %d - Writes\n", TEST_WRITE);
+ printf(" -i # Number of averaging iterations (default = %lu)\n",
+ ulIter);
+ printf(" -o # Number of operations per iteration (default = %lu)\n",
+ ulOps);
+ printf(" -z # Number of operations per iteration by size "
+ "(default = %lu)\n", ulOps*ulBlock);
+ printf(" -s # Size of stream (default = %lu)\n", ulSize);
+ printf(" -b # Size of block (default = %lu, max = %ld)\n",
+ ulBlock, MAXBUF);
+ printf(" -c # Number of nested containers (default = %lu)\n", ulCtn);
+ printf(" -w Walk around stream\n");
+ printf(" -x Allow stream to grow\n");
+ printf(" -d Use direct mode\n");
+ exit(1);
+}
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ CTN ctn;
+ STM stm;
+ ULONG i, j, ulRet, ulPos;
+ ULONG ulDFDebug = 0x101, ulMSDebug = 0x101;
+ int dwTFlags = PM_TRANSACTED;
+ time_t start, duration, sum = 0;
+ int fNew = TRUE;
+ int fGrow = FALSE;
+
+ for (i = 1; (int)i<argc; i++)
+ if (argv[i][0] == '-')
+ switch(argv[i][1])
+ {
+ case '?':
+ usage();
+ break;
+ case 'b':
+ i++;
+ sscanf(argv[i], "%lu", &ulBlock);
+ break;
+ case 'c':
+ i++;
+ sscanf(argv[i], "%lu", &ulCtn);
+ break;
+ case 'd':
+ dwTFlags = PM_DIRECT;
+ break;
+ case 'D':
+ ulDFDebug = 0xffffffff;
+ break;
+ case 'i':
+ i++;
+ sscanf(argv[i], "%lu", &ulIter);
+ break;
+ case 'M':
+ ulMSDebug = 0xffffffff;
+ break;
+ case 'o':
+ i++;
+ sscanf(argv[i], "%lu", &ulOps);
+ break;
+ case 'p':
+ fNew = FALSE; // used for profiling
+ break;
+ case 's':
+ i++;
+ sscanf(argv[i], "%lu", &ulSize);
+ break;
+ case 't':
+ i++;
+ sscanf(argv[i], "%lu", &ulTest);
+ break;
+ case 'w':
+ fMove = TRUE;
+ break;
+ case 'x':
+ fGrow = TRUE;
+ break;
+ case 'z':
+ i++;
+ sscanf(argv[i], "%lu", &ulOps);
+ ulOps = ulOps/ulBlock+1;
+ break;
+ }
+
+ buf = (char *)malloc((size_t)ulBlock);
+ if (buf == NULL)
+ {
+ printf("Unable to allocate buffer\n");
+ exit(1);
+ }
+
+ printf("%s Version\n", BUILD_TYPE);
+#if DBG == 1
+ DfDebug(ulDFDebug, ulMSDebug);
+#endif
+
+ if (fNew)
+ {
+ _unlink("rtst.dfl");
+ ctn = NULL;
+ for (i = 0; i<ulCtn; i++)
+ {
+ ctn = open_ctn(ctn, STR(rtst.dfl), PM_CREATE | PM_RDWR | dwTFlags);
+ if (!VALID_CTN(ctn))
+ {
+ printf("Unable to create container %lu\n", i+1);
+ exit(1);
+ }
+ printf("Container %lu created\n", i+1);
+ ctn_stack[i] = ctn;
+ }
+
+ stm = open_stm(ctn, STR(Stream), PM_CREATE | PM_RDWR | PM_DIRECT);
+ if (!VALID_STM(stm))
+ {
+ printf("Unable to create stream\n");
+ exit(1);
+ }
+ printf("Stream created\n");
+
+ set_stm_size(stm, ulSize);
+ printf("Size set to %lu\n", ulSize);
+ commit_stm(stm);
+ printf("Stream committed\n");
+ release_stm(stm);
+ printf("Stream released\n");
+
+ for (i = ulCtn; i > 0; i--)
+ {
+ commit_ctn(ctn_stack[i-1]);
+ printf("Container %lu committed\n", i);
+ release_ctn(ctn_stack[i-1]);
+ printf("Container %lu released\n", i);
+ }
+ }
+
+ ctn = NULL;
+ for (i = 0; i<ulCtn; i++)
+ {
+ ctn = open_ctn(ctn, STR(rtst.dfl), PM_RDWR | dwTFlags);
+ if (!VALID_CTN(ctn))
+ {
+ printf("Unable to open container %lu\n", i+1);
+ exit(1);
+ }
+ printf("Container %lu opened\n", i+1);
+ ctn_stack[i] = ctn;
+ }
+
+ stm = open_stm(ctn, STR(Stream), PM_RDWR | PM_DIRECT);
+ if (!VALID_STM(stm))
+ {
+ printf("Unable to open stream\n");
+ exit(1);
+ }
+ printf("Stream opened\n");
+
+ for (j = 0; j<ulIter; j++)
+ {
+ ulPos = 0;
+ seek_stm(stm, 0);
+ start = time(&start);
+ for (i = 0; i<ulOps; i++)
+ {
+ if (!fMove)
+ seek_stm(stm, 0);
+ else if (!fGrow)
+ {
+ ulPos += ulBlock;
+ if (ulPos > ulSize)
+ {
+ seek_stm(stm, 0);
+ ulPos = ulBlock;
+ }
+ }
+ switch(ulTest)
+ {
+ case TEST_READ:
+ if ((ulRet = read_stm(stm, buf, ulBlock)) != ulBlock)
+ {
+ printf("Read %lu bytes instead of %lu\n", ulRet,
+ ulBlock);
+ i = ulOps;
+ }
+ break;
+ case TEST_WRITE:
+ if ((ulRet = write_stm(stm, buf, ulBlock)) != ulBlock)
+ {
+ printf("Wrote %lu bytes instead of %lu\n", ulRet,
+ ulBlock);
+ i = ulOps;
+ }
+ break;
+ }
+ }
+ duration = time(&duration)-start;
+ sum += duration;
+ printf("Iteration %lu of %lu, %lu %ss on %lu bytes:\n\t"
+ "%ld seconds, average %.3lf\n", j+1, ulIter, ulOps,
+ test_type[ulTest], ulBlock, duration, (double)sum/(j+1));
+ }
+
+ release_stm(stm);
+ printf("Stream released\n");
+
+ for (i = ulCtn; i > 0; i--)
+ {
+ release_ctn(ctn_stack[i-1]);
+ printf("Container %lu released\n", i);
+ }
+ free(buf);
+}
diff --git a/private/ole32/stg/docfile/tests/readtmd.cxx b/private/ole32/stg/docfile/tests/readtmd.cxx
new file mode 100644
index 000000000..4c646fd38
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/readtmd.cxx
@@ -0,0 +1,82 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <io.h>
+#include <fcntl.h>
+#include <sys\types.h>
+#include <sys\stat.h>
+
+#define TRUE 1
+#define FALSE 0
+
+typedef unsigned long ULONG;
+
+typedef int CTN;
+typedef int STM;
+
+#define BUILD_TYPE "DOS"
+
+#define STR(x) #x
+
+#define VALID_CTN(c) ((c) >= 0)
+#define VALID_STM(s) ((s) >= 0)
+
+#define PM_READ O_RDONLY
+#define PM_WRITE O_WRONLY
+#define PM_RDWR O_RDWR
+#define PM_CREATE (O_CREAT | O_TRUNC)
+#define PM_DIRECT 0
+#define PM_TRANSACTED 0
+
+CTN open_ctn(CTN ctnParent, char *psz, int iPerms)
+{
+ if (ctnParent != NULL)
+ return -1;
+ return NULL;
+}
+
+void release_ctn(CTN ctn)
+{
+}
+
+STM open_stm(CTN ctnParent, char *psz, int iPerms)
+{
+ if (ctnParent != NULL)
+ return -1;
+ return _open(psz, iPerms | O_BINARY, S_IREAD | S_IWRITE);
+}
+
+void release_stm(STM stm)
+{
+ _close(stm);
+}
+
+void set_stm_size(STM stm, ULONG ulLength)
+{
+ _chsize(stm, (long)ulLength);
+}
+
+ULONG read_stm(STM stm, void *buf, ULONG ulLength)
+{
+ return (ULONG)_read(stm, buf, (unsigned)ulLength);
+}
+
+void seek_stm(STM stm, ULONG ulPos)
+{
+ _lseek(stm, (long)ulPos, SEEK_SET);
+}
+
+ULONG write_stm(STM stm, void *buf, ULONG ulLength)
+{
+ return (ULONG)_write(stm, buf, (unsigned)ulLength);
+}
+
+void commit_ctn(CTN ctn)
+{
+}
+
+void commit_stm(STM stm)
+{
+}
+
+#include "readtm.cxx"
diff --git a/private/ole32/stg/docfile/tests/readtmm.cxx b/private/ole32/stg/docfile/tests/readtmm.cxx
new file mode 100644
index 000000000..3750aeccd
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/readtmm.cxx
@@ -0,0 +1,145 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <ole2.h>
+#include <wchar.h>
+#include <dfmsp.hxx>
+#include <dfdeb.hxx>
+
+typedef IStorage *CTN;
+typedef IStream *STM;
+
+#define BUILD_TYPE "Docfile"
+
+#ifdef UNICODE
+#define STR(x) L#x
+#else
+#define STR(x) #x
+#endif
+
+#define VALID_CTN(c) ((c) != NULL)
+#define VALID_STM(s) ((s) != NULL)
+
+#define PM_READ STGM_READ
+#define PM_WRITE STGM_WRITE
+#define PM_RDWR STGM_READWRITE
+#define PM_DIRECT STGM_DIRECT
+#define PM_TRANSACTED STGM_TRANSACTED
+#define PM_MASK (~PM_CREATE)
+#define PM_CREATE STGM_CREATE
+
+CTN open_ctn(CTN ctnParent, TCHAR *pwcs, DWORD dwPerms)
+{
+ CTN ctn;
+
+ if ((dwPerms & STGM_TRANSACTED) == 0)
+ dwPerms |= STGM_SHARE_DENY_WRITE;
+ if (ctnParent == NULL)
+ if (dwPerms & PM_CREATE)
+ {
+ if (StgCreateDocfile(pwcs, (dwPerms & PM_MASK) | STGM_CREATE,
+ 0, &ctn) != S_OK)
+ ctn = NULL;
+ }
+ else
+ {
+ if (StgOpenStorage(pwcs, NULL, dwPerms & PM_MASK, NULL,
+ 0, &ctn) != S_OK)
+ ctn = NULL;
+ }
+ else
+ {
+ dwPerms = (dwPerms & ~STGM_SHARE_DENY_WRITE) | STGM_SHARE_EXCLUSIVE;
+ if (dwPerms & PM_CREATE)
+ {
+ if (ctnParent->CreateStorage(pwcs, (dwPerms & PM_MASK) |
+ STGM_FAILIFTHERE,
+ 0, 0, &ctn) != S_OK)
+ ctn = NULL;
+ }
+ else
+ {
+ if (ctnParent->OpenStorage(pwcs, NULL, dwPerms & PM_MASK, NULL,
+ 0, &ctn) != S_OK)
+ ctn = NULL;
+ }
+ }
+ return ctn;
+}
+
+void release_ctn(CTN ctn)
+{
+ ctn->Release();
+}
+
+STM open_stm(CTN ctnParent, TCHAR *pwcs, DWORD dwPerms)
+{
+ STM stm;
+
+ if (ctnParent == NULL)
+ return NULL;
+ dwPerms |= STGM_SHARE_EXCLUSIVE;
+ if (dwPerms & PM_CREATE)
+ {
+ if (ctnParent->CreateStream(pwcs, (dwPerms & PM_MASK) |
+ STGM_FAILIFTHERE,
+ 0, 0, &stm) != S_OK)
+ stm = NULL;
+ }
+ else
+ {
+ if (ctnParent->OpenStream(pwcs, NULL, dwPerms & PM_MASK,
+ 0, &stm) != S_OK)
+ stm = NULL;
+ }
+ return stm;
+}
+
+void release_stm(STM stm)
+{
+ stm->Release();
+}
+
+void set_stm_size(STM stm, ULONG ulLength)
+{
+ ULARGE_INTEGER ulrge;
+
+ ULISet32(ulrge, ulLength);
+ stm->SetSize(ulrge);
+}
+
+ULONG read_stm(STM stm, void *buf, ULONG ulLength)
+{
+ ULONG ulRet;
+
+ stm->Read(buf, ulLength, &ulRet);
+ return ulRet;
+}
+
+void seek_stm(STM stm, ULONG ulPos)
+{
+ ULARGE_INTEGER ulRet;
+ LARGE_INTEGER ulrge;
+
+ LISet32(ulrge, ulPos);
+ stm->Seek(ulrge, SEEK_SET, &ulRet);
+}
+
+ULONG write_stm(STM stm, void *buf, ULONG ulLength)
+{
+ ULONG ulRet;
+
+ stm->Write(buf, ulLength, &ulRet);
+ return ulRet;
+}
+
+void commit_ctn(CTN ctn)
+{
+ ctn->Commit(0);
+}
+
+void commit_stm(STM stm)
+{
+}
+
+#include "readtm.cxx"
diff --git a/private/ole32/stg/docfile/tests/readtmw.cxx b/private/ole32/stg/docfile/tests/readtmw.cxx
new file mode 100644
index 000000000..3a5afc999
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/readtmw.cxx
@@ -0,0 +1,89 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <windows.h>
+
+typedef unsigned long ULONG;
+
+#ifdef FLAT
+typedef int HFILE;
+#define HFILE_ERROR -1
+#define READ OF_READ
+#define WRITE OF_WRITE
+#define READ_WRITE OF_READWRITE
+#endif
+
+typedef HFILE CTN;
+typedef HFILE STM;
+
+#define BUILD_TYPE "Windows"
+
+#define STR(x) #x
+
+#define VALID_CTN(c) ((c) != HFILE_ERROR)
+#define VALID_STM(s) ((s) != HFILE_ERROR)
+
+#define PM_READ READ
+#define PM_WRITE WRITE
+#define PM_RDWR READ_WRITE
+#define PM_MASK 0x3
+#define PM_CREATE 0x100
+#define PM_DIRECT 0
+#define PM_TRANSACTED 0
+
+CTN open_ctn(CTN ctnParent, char *psz, int iPerms)
+{
+ if (ctnParent != NULL)
+ return HFILE_ERROR;
+ return NULL;
+}
+
+void release_ctn(CTN ctn)
+{
+}
+
+STM open_stm(CTN ctnParent, char *psz, int iPerms)
+{
+ if (ctnParent != NULL)
+ return HFILE_ERROR;
+ if (iPerms & PM_CREATE)
+ return _lcreat(psz, 0);
+ else
+ return _lopen(psz, iPerms);
+}
+
+void release_stm(STM stm)
+{
+ _lclose(stm);
+}
+
+void set_stm_size(STM stm, ULONG ulLength)
+{
+ _llseek(stm, ulLength, SEEK_SET);
+ _lwrite(stm, NULL, 0);
+}
+
+ULONG read_stm(STM stm, void *buf, ULONG ulLength)
+{
+ return (ULONG)_lread(stm, (LPSTR)buf, (UINT)ulLength);
+}
+
+void seek_stm(STM stm, ULONG ulPos)
+{
+ _llseek(stm, (LONG)ulPos, SEEK_SET);
+}
+
+ULONG write_stm(STM stm, void *buf, ULONG ulLength)
+{
+ return (ULONG)_lwrite(stm, (LPSTR)buf, (UINT)ulLength);
+}
+
+void commit_ctn(CTN ctn)
+{
+}
+
+void commit_stm(STM stm)
+{
+}
+
+#include "readtm.cxx"
diff --git a/private/ole32/stg/docfile/tests/rest.cxx b/private/ole32/stg/docfile/tests/rest.cxx
new file mode 100644
index 000000000..8fcce442b
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/rest.cxx
@@ -0,0 +1,68 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tsupp.hxx"
+
+struct Permission
+{
+ char *name;
+ DWORD grf;
+};
+
+Permission pPerms[] =
+{
+ "STGM_READ", STGM_READ,
+ "STGM_WRITE", STGM_WRITE,
+ "STGM_READWRITE", STGM_READWRITE,
+ "STGM_TRANSACTED | STGM_READ", STGM_TRANSACTED | STGM_READ,
+ "STGM_TRANSACTED | STGM_WRITE", STGM_TRANSACTED | STGM_WRITE,
+ "STGM_TRANSACTED | STGM_READWRITE", STGM_TRANSACTED | STGM_READWRITE
+};
+#define NPERMS (sizeof(pPerms)/sizeof(pPerms[0]))
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstgRoot, *pstg;
+ HRESULT hr;
+ SCODE sc;
+ int i, j;
+
+ StartTest("rest");
+ CmdArgs(argc, argv);
+
+ hr = StgCreateDocfile(TEXT("TEST.DFL"), STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE | STGM_CREATE, 0, &pstgRoot);
+ Result("Create root docfile", hr);
+ hr = pstgRoot->CreateStorage(TEXT("Test"),
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0, 0, &pstg);
+ Result("Create embedding", hr);
+ pstg->Release();
+ pstgRoot->Release();
+
+ for (i = 0; i<NPERMS; i++)
+ {
+ hr = StgOpenStorage(TEXT("TEST.DFL"), NULL,
+ pPerms[i].grf | STGM_SHARE_EXCLUSIVE, NULL, 0,
+ &pstgRoot);
+ sc = GetScode(hr);
+ printf("Open root %s = %s (%lX)\n", pPerms[i].name,
+ ScText(sc), sc);
+ if (FAILED(sc))
+ continue;
+ for (j = 0; j<NPERMS; j++)
+ {
+ hr = pstgRoot->OpenStorage(TEXT("Test"), NULL,
+ pPerms[j].grf | STGM_SHARE_EXCLUSIVE,
+ NULL, 0, &pstg);
+ sc = GetScode(hr);
+ printf(" Open child %s = %s (%lX)\n", pPerms[j].name,
+ ScText(sc), sc);
+ if (FAILED(sc))
+ continue;
+ pstg->Release();
+ }
+ pstgRoot->Release();
+ }
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/reverted.cxx b/private/ole32/stg/docfile/tests/reverted.cxx
new file mode 100644
index 000000000..62b4e9f1b
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/reverted.cxx
@@ -0,0 +1,109 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tsupp.hxx"
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstgRoot, *pstg;
+ IStream *pstm, *pstm2;
+ IEnumSTATSTG *penm, *penm2;
+ HRESULT hr;
+ STATSTG stat;
+
+ StartTest("reverted");
+ CmdArgs(argc, argv);
+
+ hr = StgCreateDocfile(TEXT("TEST.DFL"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pstgRoot);
+ Result("Create root docfile", hr);
+ hr = pstgRoot->CreateStorage(TEXT("Test"), STGP(STGM_RW), 0, 0, &pstg);
+ Result("Create child docfile", hr);
+ hr = pstg->CreateStream(TEXT("Test"), STMP(STGM_RW), 0, 0, &pstm);
+ Result("Create stream", hr);
+ hr = pstg->EnumElements(0, 0, 0, &penm);
+ Result("Create enumerator", hr);
+
+ printf("Release root - all objects now reverted\n");
+ pstgRoot->Release();
+
+ printf("----- IStorage\n");
+ hr = pstg->QueryInterface(IID_IStorage, (void **)&pstgRoot);
+ IllResult("QueryInterface", hr);
+ hr = pstg->CreateStream(TEXT("Test"), STMP(STGM_RW), 0, 0, &pstm2);
+ IllResult("CreateStream", hr);
+ hr = pstg->OpenStream(TEXT("Test"), 0, STMP(STGM_RW), 0, &pstm2);
+ IllResult("OpenStream", hr);
+ hr = pstg->CreateStorage(TEXT("Test"), STGP(STGM_RW), 0, 0, &pstgRoot);
+ IllResult("CreateStorage", hr);
+ hr = pstg->OpenStorage(TEXT("Test"), NULL, STGP(STGM_RW), NULL, 0,
+ &pstgRoot);
+ IllResult("OpenStorage", hr);
+ hr = pstg->CopyTo(0, NULL, NULL, pstg);
+ IllResult("CopyTo", hr);
+ hr = pstg->MoveElementTo(TEXT("Test"), pstg, TEXT("Test"), STGMOVE_MOVE);
+ IllResult("MoveElementTo", hr);
+ hr = pstg->Commit(0);
+ IllResult("Commit", hr);
+ hr = pstg->Revert();
+ IllResult("Revert", hr);
+ hr = pstg->EnumElements(0, 0, 0, &penm2);
+ IllResult("EnumElements", hr);
+ hr = pstg->DestroyElement(TEXT("Test"));
+ IllResult("DestroyElement", hr);
+ hr = pstg->RenameElement(TEXT("Test"), TEXT("Test2"));
+ IllResult("RenameElement", hr);
+ hr = pstg->SetElementTimes(TEXT("Test"), NULL, NULL, NULL);
+ IllResult("SetElementTimes", hr);
+ hr = pstg->SetClass(IID_IStorage);
+ IllResult("SetClass", hr);
+ hr = pstg->SetStateBits(0, 0);
+ IllResult("SetStateBits", hr);
+ hr = pstg->Stat(&stat, 0);
+ IllResult("Stat", hr);
+ pstg->Release();
+
+ printf("----- IStream\n");
+ hr = pstm->QueryInterface(IID_IStream, (void **)&pstm2);
+ IllResult("QueryInterface", hr);
+ hr = pstm->Read(&stat, 1, NULL);
+ IllResult("Read", hr);
+ hr = pstm->Write(&stat, 1, NULL);
+ IllResult("Write", hr);
+ LARGE_INTEGER liSeek = {0, 0};
+ hr = pstm->Seek(liSeek, STREAM_SEEK_SET, NULL);
+ IllResult("Seek", hr);
+ ULARGE_INTEGER uliSize = {0, 0};
+ hr = pstm->SetSize(uliSize);
+ IllResult("SetSize", hr);
+ hr = pstm->CopyTo(pstm, uliSize, NULL, NULL);
+ IllResult("CopyTo", hr);
+ hr = pstm->Commit(0);
+ IllResult("Commit", hr);
+ hr = pstm->Revert();
+ IllResult("Revert", hr);
+ hr = pstm->LockRegion(uliSize, uliSize, LOCK_ONLYONCE);
+ IllResult("LockRegion", hr);
+ hr = pstm->UnlockRegion(uliSize, uliSize, LOCK_ONLYONCE);
+ IllResult("UnlockRegion", hr);
+ hr = pstm->Stat(&stat, 0);
+ IllResult("Stat", hr);
+ hr = pstm->Clone(&pstm2);
+ IllResult("Clone", hr);
+ pstm->Release();
+
+ printf("----- IEnumSTATSTG\n");
+ hr = penm->QueryInterface(IID_IEnumSTATSTG, (void **)&penm2);
+ IllResult("QueryInterface", hr);
+ hr = penm->Next(1, &stat, NULL);
+ IllResult("Next", hr);
+ hr = penm->Skip(1);
+ IllResult("Skip", hr);
+ hr = penm->Reset();
+ IllResult("Reset", hr);
+ hr = penm->Clone(&penm2);
+ IllResult("Clone", hr);
+
+ penm->Release();
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/ropen.cxx b/private/ole32/stg/docfile/tests/ropen.cxx
new file mode 100644
index 000000000..593222aba
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/ropen.cxx
@@ -0,0 +1,65 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ropen.cxx
+//
+// Contents: Remote open test
+//
+// History: 03-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+// BUGBUG - Need a header file
+STDAPI RemStgCreateStorage(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD dwStgFmt,
+ LPSECURITY_ATTRIBUTES pssSecurity,
+ IStorage **ppstg);
+STDAPI RemStgOpenStorage(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg);
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg;
+ HRESULT hr;
+ int i;
+ BOOL fName = FALSE;
+ TCHAR atcPath[_MAX_PATH];
+
+ SetHandleCount(128);
+
+ StartTest("open");
+ CmdArgs(argc, argv);
+
+ for (i = 1; i < argc; i++)
+ if (*argv[i] != '-')
+ {
+ ATOT(argv[i], atcPath, _MAX_PATH);
+ fName = TRUE;
+ }
+
+ if (!fName)
+ Fail("No filename specified\n");
+
+ hr = RemStgCreateStorage(atcPath, ROOTP(STGM_RW) | STGM_CREATE,
+ STGFMT_DOCUMENT, NULL, &pstg);
+ Result(hr, "Create storage %p", pstg);
+ printf("Ref count %lu\n", pstg->Release());
+
+ hr = RemStgOpenStorage(atcPath, NULL, STGM_TRANSACTED | STGM_READWRITE |
+ STGM_SHARE_DENY_NONE, NULL, 0, &pstg);
+ Result(hr, "Open storage %p", pstg);
+ printf("Ref count %lu\n", pstg->Release());
+
+ EndTest(0);
+}
+
diff --git a/private/ole32/stg/docfile/tests/safep.cxx b/private/ole32/stg/docfile/tests/safep.cxx
new file mode 100644
index 000000000..0dc0fd190
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/safep.cxx
@@ -0,0 +1,121 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: safep.cxx
+//
+// Contents: Safe pointer test
+//
+// History: 28-Oct-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+#include <memalloc.h>
+#include <safepnt.hxx>
+
+SAFE_INTERFACE_PTR(SafeIStorage, IStorage);
+SAFE_MEMALLOC_PTR(SafeMaPOINT, POINT);
+SAFE_MEMALLOC_MEMPTR(SafeMaMByte, BYTE);
+SAFE_COMEMALLOC_PTR(SafeCoPOINT, POINT);
+SAFE_COMEMALLOC_MEMPTR(SafeCoMByte, BYTE);
+SAFE_HEAP_PTR(SafeHPOINT, POINT);
+SAFE_HEAP_MEMPTR(SafeHMByte, BYTE);
+SAFE_WIN32_HANDLE(SafeW32Handle);
+SAFE_WIN32FIND_HANDLE(SafeW32FHandle);
+#ifdef NTHANDLE
+SAFE_NT_HANDLE(SafeNtHandle);
+#endif
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ HRESULT hr;
+
+ StartTest("safep");
+ CmdArgs(argc, argv);
+
+{
+ SafeIStorage pstg;
+
+ CreateTestFile(NULL, ROOTP(STGM_RW) | STGM_CREATE, FALSE, &pstg, NULL);
+}
+
+{
+ SafeMaPOINT pmapoint;
+
+ hr = MemAlloc(sizeof(POINT), (void **)&pmapoint);
+ Result(hr, "MemAlloc");
+}
+
+{
+ SafeMaMByte pmambyte;
+
+ hr = MemAlloc(64, (void **)&pmambyte);
+ Result(hr, "MemAlloc");
+}
+
+{
+ SafeCoPOINT pcopoint;
+
+ hr = CoMemAlloc(sizeof(POINT), (void **)&pcopoint);
+ Result(hr, "CoMemAlloc");
+}
+
+{
+ SafeCoMByte pcombyte;
+
+ hr = CoMemAlloc(64, (void **)&pcombyte);
+ Result(hr, "CoMemAlloc");
+}
+
+{
+ SafeHPOINT phpoint;
+
+ phpoint.Attach(new POINT);
+ if ((POINT *)phpoint == NULL)
+ Fail("new POINT failed\n");
+}
+
+{
+ SafeHMByte phmbyte;
+
+ phmbyte.Attach(new BYTE[64]);
+ if ((BYTE *)phmbyte == NULL)
+ Fail("new BYTE failed\n");
+}
+
+{
+ SafeW32Handle w32h;
+
+ if (!DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_INPUT_HANDLE),
+ GetCurrentProcess(), &w32h, 0, FALSE,
+ DUPLICATE_SAME_ACCESS))
+ Fail("Unable to dup handle, %lu\n", GetLastError());
+}
+
+{
+ SafeW32FHandle w32fh;
+ WIN32_FIND_DATA fd;
+
+ if (!FindFirstFile(L"*.*", &fd))
+ Fail("FindFirstFile failed with %lu\n", GetLastError());
+}
+
+#ifdef NTHANDLE
+{
+ SafeNtHandle nth;
+ NTSTATUS nts;
+
+ nts = NtDuplicateObject(NtCurrentProcess(), h, NtCurrentProcess(), &nth,
+ 0, 0, DUPLICATE_SAME_ATTRIBUTES |
+ DUPLICATE_SAME_ACCESS);
+ if (!NT_SUCCESS(nts))
+ Fail("NtDuplicateObject failed with 0x%lX\n", nts);
+}
+#endif
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/setdbg.cxx b/private/ole32/stg/docfile/tests/setdbg.cxx
new file mode 100644
index 000000000..92663e8bf
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/setdbg.cxx
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+#include "tsupp.hxx"
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ char ch[80];
+
+ StartTest("SetDbg");
+ CmdArgs(argc, argv);
+
+#ifdef _INC_WINDOWS
+ if (fVerbose)
+ printf("HTASK is %X\n", GetCurrentTask());
+#endif
+
+ for (;;)
+ {
+ printf("m to check memory, other to quit");
+ gets(ch);
+ if (ch[0] == 'm')
+ CheckMemory();
+ else
+ break;
+ }
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/settime.cxx b/private/ole32/stg/docfile/tests/settime.cxx
new file mode 100644
index 000000000..d1d93e7be
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/settime.cxx
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include "tsupp.hxx"
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg;
+ HRESULT hr;
+ FILETIME ftm;
+ time_t ctm;
+
+ StartTest("settime");
+ CmdArgs(argc, argv);
+
+ ctm = time(NULL);
+ printf("Create time is %s", ctime(&ctm));
+
+ hr = StgCreateDocfile(TEXT("TEST.DFL"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pstg);
+ Result("Create root docfile", hr);
+ pstg->Release();
+
+#ifdef FLAT
+ Sleep(5000);
+#endif
+
+ ctm = time(NULL);
+ printf("Set time is %s", ctime(&ctm));
+
+#ifdef FLAT
+ SYSTEMTIME stm;
+ GetSystemTime(&stm);
+ SystemTimeToFileTime(&stm, &ftm);
+ Sleep(5000);
+#else
+ ftm.dwLowDateTime = 0x7fffffff;
+ ftm.dwHighDateTime = 0x100;
+#endif
+
+ ctm = time(NULL);
+ printf("Current time is %s", ctime(&ctm));
+
+ hr = StgSetTimes(TEXT("TEST.DFL"), &ftm, &ftm, &ftm);
+ Result("StgSetTimes", hr);
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/size.cxx b/private/ole32/stg/docfile/tests/size.cxx
new file mode 100644
index 000000000..f17276e57
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/size.cxx
@@ -0,0 +1,57 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: size.cxx
+//
+// Contents: Create large docfiles
+//
+// History: 03-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+#define NSTREAMS 40
+#define STREAM_SIZE 1000000
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg;
+ HRESULT hr;
+ int i;
+ IStream *pstm;
+ char achName[CWCSTORAGENAME];
+ TCHAR atcName[CWCSTORAGENAME];
+ ULARGE_INTEGER uli;
+
+ StartTest("size");
+ CmdArgs(argc, argv);
+
+ hr = StgCreateDocfile(TSTR("test.dfl"), ROOTP(STGM_RW) | STGM_CREATE,
+ 0, &pstg);
+ Result(hr, "Create root");
+
+ uli.HighPart = 0;
+ uli.LowPart = STREAM_SIZE;
+ for (i = 0; i < NSTREAMS; i++)
+ {
+ sprintf(achName, "Stream%d", i);
+ printf("Creating stream %d\n", i);
+ ATOT(achName, atcName, CWCSTORAGENAME);
+ hr = pstg->CreateStream(atcName, STMP(STGM_RW), 0, 0, &pstm);
+ Result(hr, "Create stream %d", i);
+ hr = pstm->SetSize(uli);
+ Result(hr, "SetSize to %d", STREAM_SIZE);
+ pstm->Release();
+ }
+
+ hr = pstg->Commit(0);
+ Result(hr, "Commit");
+
+ pstg->Release();
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/smp.cxx b/private/ole32/stg/docfile/tests/smp.cxx
new file mode 100644
index 000000000..9ef1a9acf
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/smp.cxx
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tsupp.hxx"
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg;
+
+ StartTest("smp");
+ CmdArgs(argc, argv);
+ printf("Create root docfile = %lX\n",
+ StgCreateDocfile(TEXT("D:TEST.DFL"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pstg));
+ printf("Release root docfile = %lX\n",
+ pstg->Release());
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/stmdny.cxx b/private/ole32/stg/docfile/tests/stmdny.cxx
new file mode 100644
index 000000000..e59813c4b
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/stmdny.cxx
@@ -0,0 +1,46 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: stmdny.cxx
+//
+// Contents: Stream denials test
+//
+// History: 07-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg;
+ IStream *pstm1, *pstm2;
+ HRESULT hr;
+
+ StartTest("stmdny");
+ CmdArgs(argc, argv);
+
+ hr = StgCreateDocfile(TTEXT("test.dfl"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pstg);
+ Result(hr, "Create storage");
+
+ hr = pstg->CreateStream(TTEXT("Contents"), STMP(STGM_RW), 0, 0, &pstm1);
+ Result(hr, "Create stream");
+ hr = pstg->CreateStream(TTEXT("Contents"), STMP(STGM_RW), 0, 0, &pstm2);
+ IllResult(hr, "Create stream again");
+ pstm1->Release();
+
+ hr = pstg->OpenStream(TTEXT("Contents"), NULL, STMP(STGM_RW), 0, &pstm1);
+ Result(hr, "Open stream");
+ hr = pstg->OpenStream(TTEXT("Contents"), NULL, STMP(STGM_RW), 0, &pstm2);
+ IllResult(hr, "Open stream again");
+ pstm1->Release();
+
+ pstg->Release();
+
+ EndTest(0);
+}
+
diff --git a/private/ole32/stg/docfile/tests/switch.cxx b/private/ole32/stg/docfile/tests/switch.cxx
new file mode 100644
index 000000000..da76972a0
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/switch.cxx
@@ -0,0 +1,78 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tsupp.hxx"
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg, *pstgEm;
+ IStream *pstRt, *pstEm;
+ IRootStorage *prstg;
+
+ _unlink("TEST2.DFL");
+ StartTest("switch");
+ CmdArgs(argc, argv);
+ printf("Create root docfile = %lX\n",
+ StgCreateDocfile(TEXT("TEST.DFL"), ROOTP(STGM_RW) |
+ STGM_CREATE | STGM_DELETEONRELEASE, 0, &pstg));
+ printf("Create root stream = %lX\n",
+ pstg->CreateStream(TEXT("TestSt"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstRt));
+ printf("Create embedded docfile = %lX\n",
+ pstg->CreateStorage(TEXT("TEST"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstgEm));
+ printf("Create embedded stream = %lX\n",
+ pstgEm->CreateStream(TEXT("TestEmSt"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstEm));
+
+ printf("QueryInterface to IRootStorage = %lX\n",
+ pstg->QueryInterface(IID_IRootStorage, (void **)&prstg));
+ if (prstg == NULL)
+ exit(1);
+ printf("SwitchToFile = %lX\n",
+ prstg->SwitchToFile(TEXT("TEST2.DFL")));
+ printf("Release IRootStorage = %lX\n",
+ prstg->Release());
+
+ printf("Commit embedded stream = %lX\n",
+ pstEm->Commit(0));
+ printf("Release embedded stream = %lX\n",
+ pstEm->Release());
+ printf("Commit embedded docfile = %lX\n",
+ pstgEm->Commit(0));
+ printf("Release embedded docfile = %lX\n",
+ pstgEm->Release());
+ printf("Commit root stream = %lX\n",
+ pstRt->Commit(0));
+ printf("Release root stream = %lX\n",
+ pstRt->Release());
+ printf("Commit root docfile = %lX\n",
+ pstg->Commit(0));
+ printf("Release root docfile = %lX\n",
+ pstg->Release());
+
+ printf("Open root docfile = %lX\n",
+ StgOpenStorage(TEXT("TEST.DFL"), NULL, ROOTP(STGM_RW),
+ NULL, 0, &pstg));
+
+ printf("Open root docfile = %lX\n",
+ StgOpenStorage(TEXT("TEST2.DFL"), NULL, ROOTP(STGM_RW),
+ NULL, 0, &pstg));
+ printf("Open root stream = %lX\n",
+ pstg->OpenStream(TEXT("TestSt"), NULL, STMP(STGM_RW), 0, &pstRt));
+ printf("Open embedded docfile = %lX\n",
+ pstg->OpenStorage(TEXT("TEST"), NULL, STGP(STGM_RW),
+ NULL, 0, &pstgEm));
+ printf("Open embedded stream = %lX\n",
+ pstgEm->OpenStream(TEXT("TestEmSt"), NULL,
+ STMP(STGM_RW), 0, &pstEm));
+ printf("Release embedded stream = %lX\n",
+ pstEm->Release());
+ printf("Release embedded docfile = %lX\n",
+ pstgEm->Release());
+ printf("Release root stream = %lX\n",
+ pstRt->Release());
+ printf("Release root docfile = %lX\n",
+ pstg->Release());
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/timest.cxx b/private/ole32/stg/docfile/tests/timest.cxx
new file mode 100644
index 000000000..5f8cf5656
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/timest.cxx
@@ -0,0 +1,89 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include "tsupp.hxx"
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pstg, *pstgEm;
+ IStream *pstEm;
+ ULARGE_INTEGER ulSize;
+ STATSTG stat;
+
+ StartTest("timest");
+ CmdArgs(argc, argv);
+ printf("Create root docfile = %lX\n",
+ StgCreateDocfile(TEXT("TEST.DFL"), ROOTP(STGM_RW) |
+ STGM_CREATE, 0, &pstg));
+ printf("Create embedded docfile = %lX\n",
+ pstg->CreateStorage(TEXT("TEST"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstgEm));
+ printf("Create embedded stream = %lX\n",
+ pstgEm->CreateStream(TEXT("TestEmSt"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pstEm));
+ printf("Commit embedded stream = %lX\n",
+ pstEm->Commit(0));
+ printf("Release embedded stream = %lX\n",
+ pstEm->Release());
+ printf("Commit embedded docfile = %lX\n",
+ pstgEm->Commit(0));
+
+ printf("Stat embedded docfile = %lX\n",
+ pstgEm->Stat(&stat, STATFLAG_NONAME));
+ printf("Embedded docfile modify time = %s\n",
+ AscFileTime(&stat.mtime));
+
+ printf("Release embedded docfile = %lX\n",
+ pstgEm->Release());
+ printf("Commit root docfile = %lX\n",
+ pstg->Commit(0));
+ printf("Release root docfile = %lX\n",
+ pstg->Release());
+
+ int i;
+ time_t curtm;
+ curtm = time(NULL);
+ printf("Waiting five seconds from %s", ctime(&curtm));
+ while (time(NULL)-curtm < 5)
+ for (i = 0; i<25000; i++)
+ ;
+ curtm = time(NULL);
+ printf("Time is now %s", ctime(&curtm));
+
+ printf("Open root docfile = %lX\n",
+ StgOpenStorage(TEXT("TEST.DFL"), NULL, ROOTP(STGM_RW),
+ NULL, 0, &pstg));
+ printf("Open embedded docfile = %lX\n",
+ pstg->OpenStorage(TEXT("TEST"), NULL, STGP(STGM_RW),
+ NULL, 0, &pstgEm));
+ printf("Open embedded stream = %lX\n",
+ pstgEm->OpenStream(TEXT("TestEmSt"), NULL,
+ STMP(STGM_RW), 0, &pstEm));
+ ULISet32(ulSize, 64);
+ printf("SetSize embedded stream = %lX\n",
+ pstEm->SetSize(ulSize));
+
+ printf("Commit embedded stream = %lX\n",
+ pstEm->Commit(0));
+ printf("Release embedded stream = %lX\n",
+ pstEm->Release());
+
+ printf("Commit embedded docfile = %lX\n",
+ pstgEm->Commit(0));
+ printf("Stat embedded docfile = %lX\n",
+ pstgEm->Stat(&stat, STATFLAG_NONAME));
+ printf("Embedded docfile modify time = %s\n",
+ AscFileTime(&stat.mtime));
+ printf("Release embedded docfile = %lX\n",
+ pstgEm->Release());
+
+ printf("Commit root docfile = %lX\n",
+ pstg->Commit(0));
+ printf("Stat root docfile = %lX\n",
+ pstg->Stat(&stat, STATFLAG_NONAME));
+ printf("Root storage modify time = %s\n",
+ AscFileTime(&stat.mtime));
+ printf("Release root docfile = %lX\n",
+ pstg->Release());
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tests/tsupp.cxx b/private/ole32/stg/docfile/tests/tsupp.cxx
new file mode 100644
index 000000000..97bf02af0
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/tsupp.cxx
@@ -0,0 +1,253 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tsupp.cxx
+//
+// Contents: Test support routines
+//
+// History: 03-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+DWORD dwTransacted = STGM_DIRECT, dwRootDenyWrite = STGM_SHARE_EXCLUSIVE;
+BOOL fVerbose = FALSE;
+
+#define START_MEMORY_NOT_SET 0x7fffffff
+
+static LONG cbStartMemory = START_MEMORY_NOT_SET;
+
+static char *types[3] =
+{
+ "",
+ "storage",
+ "stream"
+};
+
+static char testname[256];
+
+void StartTest(char *test)
+{
+ SCODE sc;
+
+ strcpy(testname, test);
+#if WIN32 == 300
+ if (FAILED(sc = GetScode(CoInitializeEx(NULL, COINIT_MULTITHREADED))))
+#else
+ if (FAILED(sc = GetScode(CoInitialize(NULL))))
+#endif
+ {
+ fprintf(stderr, "CoInitialize failed with sc = %lX\n", sc);
+ exit(1);
+ }
+#if DBG == 1
+ cbStartMemory = DfGetMemAlloced();
+#endif
+}
+
+void EndTest(int code)
+{
+ if (code == 0)
+ CheckMemory();
+ CoUninitialize();
+ if (code == 0)
+ printf("%s SUCCEEDED\n", testname);
+ else
+ printf("%s FAILED\n", testname);
+ exit(code);
+}
+
+void printstat(STATSTG *psstg, BOOL verbose)
+{
+ char szName[NAMELEN];
+#ifndef WIN32
+ time_t tm;
+#endif
+
+ TTOA(psstg->pwcsName, szName, CWCSTORAGENAME);
+ if (verbose)
+ {
+ printf("%s:%s =>\n", szName, types[psstg->type]);
+ if (psstg->grfMode != 0)
+ printf(" Mode: 0x%lX\n", psstg->grfMode);
+ if (psstg->type == STGTY_STREAM)
+ {
+ printf(" Size: %lu:%lu\n", ULIGetHigh(psstg->cbSize),
+ ULIGetLow(psstg->cbSize));
+ if (psstg->grfLocksSupported & LOCK_WRITE)
+ printf(" Supports write locks\n");
+ if (psstg->grfLocksSupported & LOCK_EXCLUSIVE)
+ printf(" Supports exclusive locks\n");
+ if (psstg->grfLocksSupported & LOCK_ONLYONCE)
+ printf(" Supports only-once locking\n");
+ }
+ else
+ {
+#ifndef WIN32
+ tm = psstg->ctime.dwLowDateTime;
+ if (tm != 0)
+ printf(" Created : %s", ctime(&tm));
+ tm = psstg->mtime.dwLowDateTime;
+ if (tm != 0)
+ printf(" Modified: %s", ctime(&tm));
+ tm = psstg->atime.dwLowDateTime;
+ if (tm != 0)
+ printf(" Accessed: %s", ctime(&tm));
+#else
+ printf(" Created : %s\n", FileTimeText(&psstg->ctime));
+ printf(" Modified: %s\n", FileTimeText(&psstg->mtime));
+ printf(" Accessed: %s\n", FileTimeText(&psstg->atime));
+#endif
+ printf(" Class ID: %s\n", GuidText(&psstg->clsid));
+ printf(" State bits: 0x%lX\n", psstg->grfStateBits);
+ }
+ }
+ else
+ printf("%s:%lu\n", szName, psstg->type);
+}
+
+void c_contents(IStorage *pdf, int level, BOOL recurse, BOOL verbose)
+{
+ IEnumSTATSTG *pdfi;
+ ULONG ulRet;
+ IStorage *pdfChild;
+ int i;
+ STATSTG sstg;
+ SCODE sc;
+
+ if (FAILED(sc = GetScode(pdf->EnumElements(0, NULL, 0, &pdfi))))
+ {
+ printf("Unable to create iterator, error %lX\n", sc);
+ return;
+ }
+ for (;;)
+ {
+ ulRet = GetScode(pdfi->Next(1, &sstg, NULL));
+ if (ulRet != S_OK)
+ break;
+ if (!verbose)
+ for (i = 0; i<level; i++)
+ putchar(' ');
+ printstat(&sstg, verbose);
+ if (sstg.type == STGTY_STORAGE && recurse)
+ {
+ if (SUCCEEDED(sc = GetScode(pdf->OpenStorage(sstg.pwcsName, NULL,
+ STGP(STGM_READ),
+ NULL, 0, &pdfChild))))
+ {
+ c_contents(pdfChild, level+2, recurse, verbose);
+ pdfChild->Release();
+ }
+ else
+ printf("Unable to recurse, error %lX\n", sc);
+ }
+ CoMemFree(sstg.pwcsName);
+ }
+ pdfi->Release();
+}
+
+static void GetDbgValues(char *psz, DWORD *pdwDf, DWORD *pdwMs)
+{
+ switch(psz[0])
+ {
+ case 'a':
+ *pdwDf = 0xfdffffdf;
+ *pdwMs = 0xfdffffdf;
+ break;
+ case 'd':
+ *pdwDf = 0xfdffffdf;
+ *pdwMs = 0x101;
+ break;
+ case 'G':
+ *pdwDf = 0x02000000;
+ *pdwMs = 0;
+ break;
+ case 'i':
+ *pdwDf = 0x101;
+ *pdwMs = 0x101;
+ break;
+ case 'm':
+ *pdwDf = 0x101;
+ *pdwMs = 0xfdffff2f;
+ break;
+ case 'M':
+ *pdwDf = 0x01100000;
+ *pdwMs = 0;
+ break;
+ case 'L':
+ *pdwDf = 0x00100000;
+ *pdwMs = 0;
+ break;
+ case ':':
+ sscanf(psz+1, "%lx,%lx", pdwDf, pdwMs);
+ break;
+ default:
+ *pdwDf = 0;
+ *pdwMs = 0;
+ break;
+ }
+}
+
+void CmdArgs(int argc, char *argv[])
+{
+ int i;
+ ULONG dbD = 0, dbM = 0, dbtD, dbtM;
+
+ for (i = 1; i<argc; i++)
+ if (*argv[i] == '-')
+ switch(argv[i][1])
+ {
+ case 't':
+ dwTransacted = STGM_TRANSACTED;
+ dwRootDenyWrite = STGM_SHARE_DENY_NONE;
+ break;
+ case 'w':
+ dwTransacted = STGM_TRANSACTED;
+ dwRootDenyWrite = STGM_SHARE_DENY_WRITE;
+ break;
+ case 'v':
+ fVerbose = TRUE;
+ break;
+ case 'y':
+ GetDbgValues(argv[i]+2, &dbD, &dbM);
+ SetDebug(dbD, dbM);
+ break;
+ case 'Y':
+ GetDbgValues(argv[i]+2, &dbtD, &dbtM);
+ dbD |= dbtD;
+ dbM |= dbtM;
+ SetDebug(dbD, dbM);
+ break;
+ }
+ if (dwTransacted == STGM_TRANSACTED)
+ printf(" Transacted");
+ else
+ printf(" Direct");
+ if (dwRootDenyWrite == STGM_SHARE_DENY_WRITE ||
+ dwRootDenyWrite == STGM_SHARE_EXCLUSIVE)
+ printf(" Dependent");
+ else
+ printf(" Independent");
+ if (fVerbose)
+ printf(" Verbose");
+ putchar('\n');
+}
+
+#if DBG == 1
+void CheckMemory(void)
+{
+ if (fVerbose ||
+ (cbStartMemory == START_MEMORY_NOT_SET && DfGetMemAlloced() != 0) ||
+ (DfGetMemAlloced() != cbStartMemory))
+ {
+ DfPrintAllocs();
+ Fail("%s: memory start = %ld, memory held = %ld, change = %ld\n",
+ testname, cbStartMemory, DfGetMemAlloced(),
+ DfGetMemAlloced()-cbStartMemory);
+ }
+}
+#endif
diff --git a/private/ole32/stg/docfile/tests/tsupp.hxx b/private/ole32/stg/docfile/tests/tsupp.hxx
new file mode 100644
index 000000000..3796e025a
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/tsupp.hxx
@@ -0,0 +1,41 @@
+#include <windows.h>
+#include <memory.h>
+#if WIN32 != 300
+#include <compobj.h>
+#include <storage.h>
+#endif
+#include <wchar.h>
+#include <dfdeb.hxx>
+#include <dfmsp.hxx>
+#include <dfentry.hxx>
+#include <tutils.hxx>
+
+#if DBG == 1
+#define SetDebug(d, m) DfDebug(d, m)
+void CheckMemory(void);
+#else
+#define SetDebug(d, m)
+#define CheckMemory()
+#endif
+
+#define NAMELEN CWCSTORAGENAME
+
+#define STGM_RW STGM_READWRITE
+#define STGM_DRDW STGM_SHARE_EXCLUSIVE
+
+#define ROOTP(p) ((p) | dwTransacted | dwRootDenyWrite)
+#define STGP(p) ((p) | dwTransacted | STGM_DRDW)
+#define STMP(p) ((p) | STGM_DRDW)
+
+void printstat(STATSTG *psstg, BOOL verbose);
+void c_contents(IStorage *pdf, int level, BOOL recurse, BOOL verbose);
+void CmdArgs(int argc, char *argv[]);
+
+void StartTest(char *test);
+void EndTest(int code);
+
+#define c_list(pdf) c_contents(pdf, 0, FALSE, FALSE)
+#define c_tree(pdf) c_contents(pdf, 0, TRUE, FALSE)
+
+extern DWORD dwTransacted, dwRootDenyWrite;
+extern BOOL fVerbose;
diff --git a/private/ole32/stg/docfile/tests/tutils.cxx b/private/ole32/stg/docfile/tests/tutils.cxx
new file mode 100644
index 000000000..794d80b2a
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/tutils.cxx
@@ -0,0 +1,485 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tutils.cxx
+//
+// Contents: Generic utilities for tests
+//
+// History: 06-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+static BOOL fExitOnFail = TRUE;
+
+BOOL GetExitOnFail(void)
+{
+ return fExitOnFail;
+}
+
+void SetExitOnFail(BOOL set)
+{
+ fExitOnFail = set;
+}
+
+// Print out an error message and terminate
+void Fail(char *fmt, ...)
+{
+ va_list args;
+
+ args = va_start(args, fmt);
+ fprintf(stderr, "** Fatal error **: ");
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ EndTest(1);
+}
+
+typedef struct
+{
+ SCODE sc;
+ char *text;
+} StatusCodeText;
+
+static StatusCodeText scodes[] =
+{
+ S_OK, "S_OK",
+ S_FALSE, "S_FALSE",
+ STG_E_INVALIDFUNCTION, "STG_E_INVALIDFUNCTION",
+ STG_E_FILENOTFOUND, "STG_E_FILENOTFOUND",
+ STG_E_PATHNOTFOUND, "STG_E_PATHNOTFOUND",
+ STG_E_TOOMANYOPENFILES, "STG_E_TOOMANYOPENFILES",
+ STG_E_ACCESSDENIED, "STG_E_ACCESSDENIED",
+ STG_E_INVALIDHANDLE, "STG_E_INVALIDHANDLE",
+ STG_E_INSUFFICIENTMEMORY, "STG_E_INSUFFICIENTMEMORY",
+ STG_E_INVALIDPOINTER, "STG_E_INVALIDPOINTER",
+ STG_E_NOMOREFILES, "STG_E_NOMOREFILES",
+ STG_E_DISKISWRITEPROTECTED, "STG_E_DISKISWRITEPROTECTED",
+ STG_E_SEEKERROR, "STG_E_SEEKERROR",
+ STG_E_WRITEFAULT, "STG_E_WRITEFAULT",
+ STG_E_READFAULT, "STG_E_READFAULT",
+ STG_E_SHAREVIOLATION, "STG_E_SHAREVIOLATION",
+ STG_E_LOCKVIOLATION, "STG_E_LOCKVIOLATION",
+ STG_E_FILEALREADYEXISTS, "STG_E_FILEALREADYEXISTS",
+ STG_E_INVALIDPARAMETER, "STG_E_INVALIDPARAMETER",
+ STG_E_MEDIUMFULL, "STG_E_MEDIUMFULL",
+ STG_E_ABNORMALAPIEXIT, "STG_E_ABNORMALAPIEXIT",
+ STG_E_INVALIDHEADER, "STG_E_INVALIDHEADER",
+ STG_E_INVALIDNAME, "STG_E_INVALIDNAME",
+ STG_E_UNKNOWN, "STG_E_UNKNOWN",
+ STG_E_UNIMPLEMENTEDFUNCTION, "STG_E_UNIMPLEMENTEDFUNCTION",
+ STG_E_INVALIDFLAG, "STG_E_INVALIDFLAG",
+ STG_E_INUSE, "STG_E_INUSE",
+ STG_E_NOTCURRENT, "STG_E_NOTCURRENT",
+ STG_E_REVERTED, "STG_E_REVERTED",
+ STG_E_CANTSAVE, "STG_E_CANTSAVE",
+ STG_E_OLDFORMAT, "STG_E_OLDFORMAT",
+ STG_E_OLDDLL, "STG_E_OLDDLL",
+ STG_E_SHAREREQUIRED, "STG_E_SHAREREQUIRED",
+ STG_E_NOTFILEBASEDSTORAGE, "STG_E_NOTFILEBASEDSTORAGE",
+ STG_E_EXTANTMARSHALLINGS, "STG_E_EXTANTMARSHALLINGS",
+ STG_S_CONVERTED, "STG_S_CONVERTED"
+};
+#define NSCODETEXT (sizeof(scodes)/sizeof(scodes[0]))
+
+// Convert a status code to text
+char *ScText(SCODE sc)
+{
+ int i;
+
+ for (i = 0; i<NSCODETEXT; i++)
+ if (scodes[i].sc == sc)
+ return scodes[i].text;
+ return "<Unknown SCODE>";
+}
+
+// Output a call result and check for failure
+HRESULT Result(HRESULT hr, char *fmt, ...)
+{
+ SCODE sc;
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ sc = GetScode(hr);
+ printf(" - %s (0x%lX)\n", ScText(sc), sc);
+ if (FAILED(sc) && fExitOnFail)
+ Fail("Unexpected call failure\n");
+ return hr;
+}
+
+// Perform Result() when the expectation is failure
+HRESULT IllResult(HRESULT hr, char *fmt, ...)
+{
+ SCODE sc;
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ sc = GetScode(hr);
+ printf(" - %s (0x%lX)\n", ScText(sc), sc);
+ if (SUCCEEDED(sc) && fExitOnFail)
+ Fail("Unexpected call success\n");
+ return hr;
+}
+
+char *TcsText(TCHAR *ptcs)
+{
+ static char buf[256];
+
+ TTOA(ptcs, buf, 256);
+ return buf;
+}
+
+char *FileTimeText(FILETIME *pft)
+{
+ static char buf[80];
+ struct tm ctm;
+#ifndef FLAT
+ WORD dosdate, dostime;
+
+ if (CoFileTimeToDosDateTime(pft, &dosdate, &dostime))
+ {
+ ctm.tm_sec = (dostime & 31)*2;
+ ctm.tm_min = (dostime >> 5) & 63;
+ ctm.tm_hour = dostime >> 11;
+ ctm.tm_mday = dosdate & 31;
+ ctm.tm_mon = ((dosdate >> 5) & 15)-1;
+ ctm.tm_year = (dosdate >> 9)+80;
+ ctm.tm_wday = 0;
+#else
+ SYSTEMTIME st;
+
+ if (FileTimeToSystemTime(pft, &st))
+ {
+ ctm.tm_sec = st.wSecond;
+ ctm.tm_min = st.wMinute;
+ ctm.tm_hour = st.wHour;
+ ctm.tm_mday = st.wDay;
+ ctm.tm_mon = st.wMonth-1;
+ ctm.tm_year = st.wYear-1900;
+ ctm.tm_wday = st.wDayOfWeek;
+#endif
+ ctm.tm_yday = 0;
+ ctm.tm_isdst = 0;
+ strcpy(buf, asctime(&ctm));
+ buf[strlen(buf)-1] = 0;
+ }
+ else
+ sprintf(buf, "<FILETIME %08lX:%08lX>", pft->dwHighDateTime,
+ pft->dwLowDateTime);
+ return buf;
+}
+
+#pragma pack(1)
+struct SplitGuid
+{
+ DWORD dw1;
+ WORD w1;
+ WORD w2;
+ BYTE b[8];
+};
+#pragma pack()
+
+char *GuidText(GUID *pguid)
+{
+ static char buf[39];
+ SplitGuid *psg = (SplitGuid *)pguid;
+
+ sprintf(buf, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
+ psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
+ return buf;
+}
+
+#define CROW 16
+
+void BinText(ULONG cbSize, BYTE *pb)
+{
+ ULONG cb, i;
+
+ while (cbSize > 0)
+ {
+ cb = min(CROW, cbSize);
+ cbSize -= cb;
+ for (i = 0; i<cb; i++)
+ printf(" %02X", pb[i]);
+ for (i = cb; i<CROW; i++)
+ printf(" ");
+ printf(" '");
+ for (i = 0; i<cb; i++)
+ if (pb[i] >= 0x20 && pb[i] <= 0x7f)
+ putchar(pb[i]);
+ else
+ putchar('.');
+ pb += cb;
+ printf("'\n");
+ }
+}
+
+// BUGBUG - Remove for Cairole when they exist
+STDAPI CoMemAlloc(DWORD cbSize, void **ppv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc;
+
+ if (SUCCEEDED(GetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ *ppv = pMalloc->Alloc(cbSize);
+ pMalloc->Release();
+
+ if (*ppv == NULL)
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ }
+ else
+ *ppv = NULL;
+
+ return hr;
+}
+
+STDAPI CoMemFree(void *pv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc;
+
+ if (SUCCEEDED(GetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ pMalloc->Free(pv);
+ pMalloc->Release();
+ }
+
+ return hr;
+}
+
+TCHAR *TestFile(TCHAR *ptcsName, char *pszFile)
+{
+ char achFn[MAX_PATH];
+ char *dir, *file;
+ int len;
+
+ dir = getenv("DFDATA");
+ if (dir)
+ strcpy(achFn, dir);
+ else
+ strcpy(achFn, ".");
+ len = strlen(achFn);
+ if (achFn[len-1] != '\\')
+ achFn[len++] = '\\';
+
+ if (pszFile)
+ {
+ strcpy(achFn+len, pszFile);
+ }
+ else
+ {
+ file = getenv("DFFILE");
+ if (file)
+ strcpy(achFn+len, file);
+ else
+ strcpy(achFn+len, "TEST.DFL");
+ }
+
+ ATOT(achFn, ptcsName, MAX_PATH);
+ return ptcsName+len;
+}
+
+#if WIN32 == 300
+char *TestFormat(DWORD *pdwFmt, DWORD *pgrfMode)
+{
+ char *fmt;
+
+ fmt = getenv("STGFMT");
+ if (fmt == NULL || !strcmp(fmt, "doc"))
+ {
+ fmt = "document";
+ *pdwFmt = STGFMT_DOCUMENT;
+ }
+ else if (!strcmp(fmt, "file"))
+ {
+ fmt = "file";
+ *pdwFmt = STGFMT_FILE;
+ }
+ else
+ {
+ fmt = "directory";
+ *pdwFmt = STGFMT_DIRECTORY;
+ *pgrfMode &= ~STGM_CREATE;
+ }
+ return fmt;
+}
+#endif
+
+void CreateTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName)
+{
+ HRESULT hr;
+ TCHAR atcFile[MAX_PATH];
+ char *fmt;
+
+ if (ptcsName == NULL)
+ ptcsName = atcFile;
+ TestFile(ptcsName, pszFile);
+#if WIN32 == 300
+ DWORD dwStgFmt;
+
+ fmt = TestFormat(&dwStgFmt, &grfMode);
+ hr = StgCreateStorage(ptcsName, grfMode, dwStgFmt, 0, ppstg);
+#else
+ hr = StgCreateDocfile(ptcsName, grfMode, 0, ppstg);
+ fmt = "docfile";
+#endif
+ if (fFail)
+ IllResult(hr, "Create %s %s", fmt, TcsText(ptcsName));
+ else
+ Result(hr, "Create %s %s", fmt, TcsText(ptcsName));
+}
+
+void OpenTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName)
+{
+ HRESULT hr;
+ TCHAR atcFile[MAX_PATH];
+
+ if (ptcsName == NULL)
+ ptcsName = atcFile;
+ TestFile(ptcsName, pszFile);
+ hr = StgOpenStorage(ptcsName, NULL, grfMode, NULL, 0, ppstg);
+ if (fFail)
+ IllResult(hr, "Open storage %s", TcsText(ptcsName));
+ else
+ Result(hr, "Open storage %s", TcsText(ptcsName));
+}
+//+--------------------------------------------------------------
+//
+// Member: CStrList::CStrList, public
+//
+// Synopsis: Ctor
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CStrList::CStrList(void)
+{
+ _pseHead = NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::~CStrList, public
+//
+// Synopsis: Dtor
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CStrList::~CStrList(void)
+{
+ Empty();
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::Add, public
+//
+// Synopsis: Adds a string to the list
+//
+// Arguments: [ptcs] - String
+//
+// Returns: Pointer to entry or NULL
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+SStrEntry *CStrList::Add(TCHAR *ptcs)
+{
+ SStrEntry *pse;
+
+ // One char of string already counted in sizeof
+ pse = (SStrEntry *)new char[sizeof(SStrEntry)+tcslen(ptcs)*sizeof(TCHAR)];
+ if (pse == NULL)
+ return NULL;
+ pse->pseNext = _pseHead;
+ pse->psePrev = NULL;
+ if (_pseHead)
+ _pseHead->psePrev = pse;
+ _pseHead = pse;
+ tcscpy(pse->atc, ptcs);
+ return pse;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::Remove, public
+//
+// Synopsis: Removes an entry from the list
+//
+// Arguments: [pse] - Entry
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+void CStrList::Remove(SStrEntry *pse)
+{
+ if (pse->psePrev)
+ pse->psePrev->pseNext = pse->pseNext;
+ else
+ _pseHead = pse->pseNext;
+ if (pse->pseNext)
+ pse->pseNext->psePrev = pse->psePrev;
+ delete pse;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::Find, public
+//
+// Synopsis: Attempts to find a string in the list
+//
+// Arguments: [ptcs] - String
+//
+// Returns: Entry or NULL
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+SStrEntry *CStrList::Find(TCHAR *ptcs)
+{
+ SStrEntry *pse;
+
+ for (pse = _pseHead; pse; pse = pse->pseNext)
+ if (!tcscmp(ptcs, pse->atc))
+ return pse;
+ return NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::Empty, public
+//
+// Synopsis: Frees all elements in list
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+void CStrList::Empty(void)
+{
+ SStrEntry *pse;
+
+ while (_pseHead)
+ {
+ pse = _pseHead->pseNext;
+ delete _pseHead;
+ _pseHead = pse;
+ }
+}
diff --git a/private/ole32/stg/docfile/tests/tutils.hxx b/private/ole32/stg/docfile/tests/tutils.hxx
new file mode 100644
index 000000000..1fd9992c2
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/tutils.hxx
@@ -0,0 +1,124 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tutils.hxx
+//
+// Contents: Generic test utilities
+//
+// History: 06-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __TUTILS_HXX__
+#define __TUTILS_HXX__
+
+#ifndef UNICODE
+#define tcscpy(d, s) strcpy(d, s)
+#define tcslen(s) strlen(s)
+#define tcscmp(s1, s2) strcmp(s1, s2)
+#define TTEXT(s) s
+#define TFMT "%s"
+#define ATOT(a, t, max) strcpy(t, a)
+#define TTOA(t, a, max) strcpy(a, t)
+#define WTOT(w, t, max) wcstombs(t, w, max)
+#define TTOW(t, w, max) mbstowcs(w, t, max)
+#else
+#define tcscpy(d, s) wcscpy(d, s)
+#define tcslen(s) wcslen(s)
+#define tcscmp(s1, s2) wcscmp(s1, s2)
+#define TTEXT(s) L##s
+#define TFMT "%ws"
+#define ATOT(a, t, max) mbstowcs(t, a, max)
+#define TTOA(t, a, max) wcstombs(a, t, max)
+#define WTOT(w, t, max) wcscpy(t, w)
+#define TTOW(t, w, max) wcscpy(w, t)
+#endif
+#ifdef WIN32
+#define ATOX(a, t, max) mbstowcs(t, a, max)
+#define XTOA(t, a, max) wcstombs(a, t, max)
+#define WTOX(w, t, max) wcscpy(t, w)
+#define XTOW(t, w, max) wcscpy(w, t)
+#else
+#define ATOX(a, t, max) strcpy(t, a)
+#define XTOA(t, a, max) strcpy(a, t)
+#define WTOX(w, t, max) wcstombs(t, w, max)
+#define XTOW(t, w, max) mbstowcs(w, t, max)
+#endif
+
+#ifdef CINTERFACE
+#define Mthd(this, name) ((this)->lpVtbl->name)
+#define SELF(p) (p),
+#else
+#define Mthd(this, name) (this)->name
+#define SELF(p)
+#endif
+
+// BUGBUG - Remove for Cairole when they exist
+STDAPI CoMemAlloc(DWORD cBytes, void **ppv);
+STDAPI CoMemFree(void *pv);
+
+BOOL GetExitOnFail(void);
+void SetExitOnFail(BOOL set);
+void Fail(char *fmt, ...);
+char *ScText(SCODE sc);
+HRESULT Result(HRESULT hr, char *fmt, ...);
+HRESULT IllResult(HRESULT hr, char *fmt, ...);
+char *TcsText(TCHAR *ptcs);
+char *FileTimeText(FILETIME *pft);
+char *GuidText(GUID *pguid);
+void BinText(ULONG cb, BYTE *pb);
+TCHAR *TestFile(TCHAR *ptcsName, char *pszFile);
+
+#if WIN32 == 300
+char *TestFormat(DWORD *pdwFmt, DWORD *pgrfMode);
+#endif
+
+void CreateTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName);
+void OpenTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName);
+
+// Defined by test, called by Fail
+void EndTest(int code);
+
+//+---------------------------------------------------------------------------
+//
+// Class: CStrList (sl)
+//
+// Purpose: Maintains a list of strings
+//
+// History: 30-Nov-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+struct SStrEntry
+{
+ SStrEntry *pseNext, *psePrev;
+ union
+ {
+ void *pv;
+ unsigned long dw;
+ } user;
+ TCHAR atc[1]; // Actually contains the whole string
+};
+
+class CStrList
+{
+public:
+ CStrList(void);
+ ~CStrList(void);
+
+ SStrEntry *Add(TCHAR *ptcs);
+ void Remove(SStrEntry *pse);
+ SStrEntry *Find(TCHAR *ptcs);
+ void Empty(void);
+
+ SStrEntry *GetHead(void) { return _pseHead; }
+
+private:
+ SStrEntry *_pseHead;
+};
+
+#endif // #ifndef __TUTILS_HXX__
diff --git a/private/ole32/stg/docfile/tests/xact.cxx b/private/ole32/stg/docfile/tests/xact.cxx
new file mode 100644
index 000000000..0072ef454
--- /dev/null
+++ b/private/ole32/stg/docfile/tests/xact.cxx
@@ -0,0 +1,147 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include "tsupp.hxx"
+
+#define TEST_FN "test.dfl"
+#define LTEST_FN TEXT("test.dfl")
+#define MSG "This is a bucket o' bytes"
+#define MSG2 "This isn't a byte of chicken"
+
+void contents(char *pszWhat, IStorage *pdf)
+{
+ printf("Contents of %s:\n", pszWhat);
+ c_contents(pdf, 0, FALSE, TRUE);
+}
+
+#define SBLK 1024
+#define SBLKS 8
+#define SSIZE (SBLK*SBLKS)
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pdf = NULL, *pdf2 = NULL;
+ IStream *pst = NULL, *pst2 = NULL;
+ STATSTG sstg;
+
+ _unlink(TEST_FN);
+ if (fVerbose)
+ getchar();
+ StartTest("xact");
+ SetDebug(0x101, 0x101);
+ CmdArgs(argc, argv);
+ printf("Create root = %lX\n",
+ StgCreateDocfile(LTEST_FN, ROOTP(STGM_RW) | STGM_FAILIFTHERE,
+ 0, &pdf));
+ if (pdf == NULL)
+ {
+ printf("Unable to create root DocFile\n");
+ exit(1);
+ }
+ printf("Stat root = %lX\n",
+ pdf->Stat(&sstg, 0));
+ printstat(&sstg, TRUE);
+ MemFree(sstg.pwcsName);
+
+ // SetDebug(0xffffffff, 0);
+ printf("Create embed = %lX\n",
+ pdf->CreateStorage(TEXT("Embedding"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pdf2));
+ printf("Stat embed = %lX\n",
+ pdf2->Stat(&sstg, 0));
+ printstat(&sstg, TRUE);
+ MemFree(sstg.pwcsName);
+ // SetDebug(0, 0);
+ printf("Create stream = %lX\n",
+ pdf->CreateStream(TEXT("PublicStream"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pst));
+ printf("Stat stream = %lX\n",
+ pst->Stat(&sstg, 0));
+ printstat(&sstg, TRUE);
+ MemFree(sstg.pwcsName);
+ printf("Release stream = %lX\n",
+ pst->Release());
+ contents("root", pdf);
+
+ printf("Create embedded stream = %lX\n",
+ pdf2->CreateStream(TEXT("Stream"), STMP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pst2));
+#ifdef TESTSTREAM
+ int i;
+ char buf[SBLK+1];
+ ULONG ulStatus, ulRet, ulPos;
+
+ for (i = 0; i<SBLK/4; i++)
+ sprintf(buf+i*4, "%4d", i);
+ printf("SetSize = %lX\n",
+ pst2->SetSize(SSIZE));
+ for (i = 0; i<SBLKS; i++)
+ {
+ ulPos = (ULONG)(rand()%(SSIZE-SBLK));
+ printf("Seek = %lX\n",
+ pst2->Seek(ulPos, SEEK_SET, &ulPos));
+ ulStatus = pst2->Write(buf, SBLK, &ulRet);
+ printf("Write = %lX, ret is %lu\n", ulStatus, ulRet);
+ }
+#endif
+ printf("Stat embedded stream = %lX\n",
+ pst2->Stat(&sstg, 0));
+ printstat(&sstg, TRUE);
+ MemFree(sstg.pwcsName);
+ printf("Release embedded stream = %lX\n",
+ pst2->Release());
+
+ // SetDebug(0xffffffff, 0);
+ printf("Commit embed = %lX\n",
+ pdf2->Commit(0));
+ printf("Release embed = %lX\n",
+ pdf2->Release());
+ printf("\nCommit root = %lX\n",
+ pdf->Commit(0));
+ printf("DestroyEntry on embed = %lX\n",
+ pdf->DestroyElement(TEXT("Embedding")));
+ printf("RenameEntry on stream = %lX\n",
+ pdf->RenameElement(TEXT("PublicStream"), TEXT("Stream")));
+ contents("root", pdf);
+
+ printf("\nRevert root = %lX\n",
+ pdf->Revert());
+ contents("root", pdf);
+
+ printf("\nDestroyEntry on embed = %lX\n",
+ pdf->DestroyElement(TEXT("Embedding")));
+ contents("root", pdf);
+ // SetDebug(0xffffffff, 0);
+ printf("RenameEntry on stream = %lX\n",
+ pdf->RenameElement(TEXT("PublicStream"), TEXT("Link")));
+ // SetDebug(0xffffffff, 0);
+ printf("Create embed = %lX\n",
+ pdf->CreateStorage(TEXT("PublicStream"), STGP(STGM_RW) |
+ STGM_FAILIFTHERE, 0, 0, &pdf2));
+ // SetDebug(0, 0);
+ printf("Stat embed = %lX\n",
+ pdf2->Stat(&sstg, 0));
+ printstat(&sstg, TRUE);
+ MemFree(sstg.pwcsName);
+ printf("Release embed = %lX\n",
+ pdf2->Release());
+ // SetDebug(0xffffffff, 0);
+ contents("root", pdf);
+ // SetDebug(0, 0);
+ printf("Commit root = %lX\n",
+ pdf->Commit(0));
+ printf("Release root = %lX\n",
+ pdf->Release());
+
+ printf("Get root = %lX\n",
+ StgOpenStorage(LTEST_FN, NULL, ROOTP(STGM_READ),
+ NULL, 0, &pdf));
+ contents("root", pdf);
+ printf("Stat root = %lX\n",
+ pdf->Stat(&sstg, 0));
+ printstat(&sstg, TRUE);
+ MemFree(sstg.pwcsName);
+ printf("Release root = %lX\n",
+ pdf->Release());
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/docfile/tlsets.cxx b/private/ole32/stg/docfile/tlsets.cxx
new file mode 100644
index 000000000..8c5ab9bc7
--- /dev/null
+++ b/private/ole32/stg/docfile/tlsets.cxx
@@ -0,0 +1,165 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: tlsets.cxx
+//
+// Contents: Transaction level set manager implementation
+//
+// History: 20-Jan-1992 PhilipL Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+//+--------------------------------------------------------------
+//
+// Member: CTSSet::~CTSSet, public
+//
+// Synopsis: destructor
+//
+// History: 22-Jan-1992 Philipl Created
+// 08-Apr-1992 DrewB Rewritten
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTSSet_1CTSSet) // inline?
+#endif
+
+CTSSet::~CTSSet()
+{
+ // Last element should be TS, but we can't check this
+ // so allow one last element to exist, assuming it will
+ // be the TS
+ olAssert(_ptsmHead == NULL ||
+ _ptsmHead->GetNext() == NULL);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTSSet::FindName, public
+//
+// Synopsis: Return the element in the TS with the given name
+//
+// Arguments: [pdfn] - name
+// [ulLevel] - level
+//
+// Returns: Matching element or NULL
+//
+// History: 22-Jan-1992 Philipl Created
+// 08-Apr-1992 DrewB Rewritten
+// 28-Oct-1992 AlexT Convert to name
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTSSet_FindName)
+#endif
+
+PTSetMember *CTSSet::FindName(CDfName const *pdfn, DFLUID dlTree)
+{
+ PTSetMember *ptsm;
+
+ olDebugOut((DEB_ITRACE, "In CTSSet::FindName(%p)\n", pdfn));
+ olAssert(pdfn != NULL && aMsg("Can't search for Null name"));
+
+ for (ptsm = BP_TO_P(PTSetMember *, _ptsmHead);
+ ptsm; ptsm = ptsm->GetNext())
+ {
+ if (ptsm->GetDfName()->IsEqual(pdfn) && ptsm->GetTree() == dlTree)
+ break;
+ }
+ olDebugOut((DEB_ITRACE, "Out CTSSet::FindName => %p\n", ptsm));
+ return ptsm;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTSSet::AddMember, public
+//
+// Synopsis: Add the member to the correct position in the list
+//
+// Arguments: [ptsmAdd] - Element to add
+//
+// History: 22-Jan-1992 Philipl Created
+// 08-Apr-1992 DrewB Rewritten
+//
+// Notes: This function inserts the provided element into the
+// list in its correct sorted position.
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTSSet_AddMember)
+#endif
+
+void CTSSet::AddMember(PTSetMember *ptsmAdd)
+{
+ PTSetMember *ptsm, *ptsmPrev;
+
+ olDebugOut((DEB_ITRACE, "In CTSSet::AddMember(%p)\n", ptsmAdd));
+ for (ptsm = BP_TO_P(PTSetMember *, _ptsmHead), ptsmPrev = NULL;
+ ptsm;
+ ptsmPrev = ptsm, ptsm = ptsm->GetNext())
+ if (ptsm->GetLevel() >= ptsmAdd->GetLevel())
+ break;
+ if (ptsm == NULL)
+ if (ptsmPrev == NULL)
+ // Empty list
+ _ptsmHead = P_TO_BP(CBasedTSetMemberPtr, ptsmAdd);
+ else
+ {
+ // Nothing with a higher level, add to end of list
+ ptsmPrev->SetNext(ptsmAdd);
+ ptsmAdd->SetPrev(ptsmPrev);
+ }
+ else
+ {
+ // Add before element with higher level
+ ptsmAdd->SetNext(ptsm);
+ ptsmAdd->SetPrev(ptsm->GetPrev());
+ if (ptsm->GetPrev())
+ ptsm->GetPrev()->SetNext(ptsmAdd);
+ else
+ _ptsmHead = P_TO_BP(CBasedTSetMemberPtr, ptsmAdd);
+ ptsm->SetPrev(ptsmAdd);
+ }
+ olDebugOut((DEB_ITRACE, "Out CTSSet::AddMember\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTSSet::RemoveMember, public
+//
+// Synopsis: Removes the member from the list
+//
+// Arguments: [ptsmRemove] - Element to remove
+//
+// History: 22-Jan-1992 Philipl Created
+// 08-Apr-1992 DrewB Rewritten
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTSSet_RemoveMember)
+#endif
+
+void CTSSet::RemoveMember(PTSetMember *ptsmRemove)
+{
+ olDebugOut((DEB_ITRACE, "In CTSSet::RemoveMember(%p)\n", ptsmRemove));
+ PTSetMember *ptsmNext = ptsmRemove->GetNext();
+
+ if (ptsmRemove->GetPrev())
+ ptsmRemove->GetPrev()->SetNext(ptsmNext);
+ else
+ _ptsmHead = P_TO_BP(CBasedTSetMemberPtr, ptsmNext);
+ if (ptsmRemove->GetNext())
+ ptsmRemove->GetNext()->SetPrev(ptsmRemove->GetPrev());
+ ptsmRemove->SetNext(NULL);
+ ptsmRemove->SetPrev(NULL);
+ olDebugOut((DEB_ITRACE, "Out CTSSet::RemoveMember\n"));
+}
diff --git a/private/ole32/stg/docfile/tset.cxx b/private/ole32/stg/docfile/tset.cxx
new file mode 100644
index 000000000..b8c0f3528
--- /dev/null
+++ b/private/ole32/stg/docfile/tset.cxx
@@ -0,0 +1,91 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tset.cxx
+//
+// Contents: PTSetMember methods
+//
+// History: 16-Apr-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "dfhead.cxx"
+
+#pragma hdrstop
+
+//+---------------------------------------------------------------------------
+//
+// Member: PTSetMember::Stat, public
+//
+// Synopsis: Fills in a STATSTG for the XSM
+//
+// Arguments: [pstat] - Buffer to fill in
+// [dwFlags] - STATFLAG_*
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstat]
+//
+// History: 12-Apr-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_PTSetMember_STAT)
+#endif
+
+SCODE PTSetMember::Stat(STATSTGW *pstat, DWORD dwFlags)
+{
+ CWrappedDocFile *pwdf;
+ CTransactedStream *ptstm;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In PTSetMember::Stat:%p(%p, %lX)\n",
+ this, pstat, dwFlags));
+
+ pstat->type = ObjectType();
+
+ if ((pstat->type & STGTY_REAL) == STGTY_STORAGE)
+ {
+ PTimeEntry *pen;
+
+ pwdf = (CWrappedDocFile *)this;
+ pen = pwdf;
+ olChk(pen->GetTime(WT_CREATION, &pstat->ctime));
+ olChk(pen->GetTime(WT_ACCESS, &pstat->atime));
+ olChk(pen->GetTime(WT_MODIFICATION, &pstat->mtime));
+
+ olChk(pwdf->GetClass(&pstat->clsid));
+ olChk(pwdf->GetStateBits(&pstat->grfStateBits));
+
+ ULISet32(pstat->cbSize, 0);
+ }
+ else
+ {
+ ULONG cbSize;
+
+ ptstm = (CTransactedStream *)this;
+ ptstm->GetSize(&cbSize);
+ ULISet32(pstat->cbSize, cbSize);
+ }
+
+ if ((dwFlags & STATFLAG_NONAME) == 0)
+ {
+ olMem(pstat->pwcsName =
+ (WCHAR *)TaskMemAlloc(_dfnName.GetLength()));
+ memcpy(pstat->pwcsName, _dfnName.GetBuffer(), _dfnName.GetLength());
+ }
+ else
+ {
+ pstat->pwcsName = NULL;
+ }
+
+ sc = S_OK;
+
+ olDebugOut((DEB_ITRACE, "Out PTSetMember::Stat\n"));
+ // Fall through
+ EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/docfile/ulist.cxx b/private/ole32/stg/docfile/ulist.cxx
new file mode 100644
index 000000000..4b17c2f52
--- /dev/null
+++ b/private/ole32/stg/docfile/ulist.cxx
@@ -0,0 +1,397 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: ulist.cxx
+//
+// Contents: CUpdateList implementation and support routines
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::CUpdate, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [pdfnCurrentName] - Current name pointer
+// [pdfnOriginalName] - Original name pointer
+// [dlLUID] - LUID
+// [dwFlags] - Flags
+// [ptsm] - Entry object
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CUpdate_CUpdate)
+#endif
+
+CUpdate::CUpdate(CDfName const *pdfnCurrent,
+ CDfName const *pdfnOriginal,
+ DFLUID dlLUID,
+ DWORD dwFlags,
+ PTSetMember *ptsm)
+{
+ SetCurrentName(pdfnCurrent);
+ SetOriginalName(pdfnOriginal);
+ _dl = dlLUID;
+ _dwFlags = dwFlags;
+ _ptsm = P_TO_BP(CBasedTSetMemberPtr, ptsm);
+ _pudNext = _pudPrev = NULL;
+ if (_ptsm)
+ _ptsm->AddRef();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CUpdate::~CUpdate, public
+//
+// Synopsis: Destructor
+//
+// History: 05-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CUpdate_1CUpdate) // inline?
+#endif
+
+CUpdate::~CUpdate(void)
+{
+ if (_ptsm)
+ _ptsm->Release();
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdateList::Add, public
+//
+// Synopsis: Adds an element to an update list
+//
+// Arguments: [pdfnCurrent] - Current name
+// [pdfnOriginal] - Original name
+// [dlLUID] - LUID
+// [dwFlags] - Flags
+// [ptsm] - Entry object
+//
+// Returns: The new element or NULL
+//
+// History: 15-Jan-92 DrewB Created
+//
+// Notes: Caller must handle NULL
+// Entries must be added in the list in the order of
+// Add calls
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CUpdateList_Add)
+#endif
+
+CUpdate *CUpdateList::Add(IMalloc * const pMalloc,
+ CDfName const *pdfnCurrent,
+ CDfName const *pdfnOriginal,
+ DFLUID dlLUID,
+ DWORD dwFlags,
+ PTSetMember *ptsm)
+{
+ CUpdate *pudNew;
+
+ olDebugOut((DEB_ITRACE, "In CUpdateList::Add:%p("
+ "%ws, %ws, %ld, %lX, %p)\n", this, pdfnCurrent->GetBuffer(),
+ pdfnOriginal->GetBuffer(), dlLUID, dwFlags, ptsm));
+
+ olAssert((dlLUID != DF_NOLUID || pdfnOriginal != NULL) &&
+ aMsg("Create update luid can't be DF_NOLUID"));
+
+ pudNew = new (pMalloc) CUpdate(pdfnCurrent, pdfnOriginal, dlLUID,
+ dwFlags, ptsm);
+ if (pudNew)
+ {
+ Append(pudNew);
+ }
+ olDebugOut((DEB_ITRACE, "Out CUpdateList::Add => %p\n", pudNew));
+ return pudNew;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CUpdateList::Append, public
+//
+// Synopsis: Appends an update to the list
+//
+// Arguments: [pud] - Update
+//
+// History: 25-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CUpdateList_Append)
+#endif
+
+void CUpdateList::Append(CUpdate *pud)
+{
+ olDebugOut((DEB_ITRACE, "In CUpdateList::Append:%p(%p)\n", this, pud));
+ if (_pudTail)
+ _pudTail->SetNext(pud);
+ else
+ _pudHead = P_TO_BP(CBasedUpdatePtr, pud);
+ pud->SetPrev(BP_TO_P(CUpdate *, _pudTail));
+ pud->SetNext(NULL);
+ _pudTail = P_TO_BP(CBasedUpdatePtr, pud);
+ olDebugOut((DEB_ITRACE, "Out CUpdateList::Append\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CUpdateList::Remove, public
+//
+// Synopsis: Removes an element from the list
+//
+// Arguments: [pud] - Element to remove
+//
+// History: 25-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CUpdateList_Remove)
+#endif
+
+void CUpdateList::Remove(CUpdate *pud)
+{
+ olDebugOut((DEB_ITRACE, "In CUpdateList::Remove:%p(%p)\n", this, pud));
+ olAssert(pud != NULL);
+ CUpdate *pudNext = pud->GetNext();
+ CUpdate *pudPrev = pud->GetPrev();
+
+ if (pud->GetNext())
+ pudNext->SetPrev(pudPrev);
+ if (pud->GetPrev())
+ pudPrev->SetNext(pudNext);
+ if (pud == _pudHead)
+ _pudHead = P_TO_BP(CBasedUpdatePtr, pudNext);
+ if (pud == _pudTail)
+ _pudTail = P_TO_BP(CBasedUpdatePtr, pudPrev);
+ pud->SetNext(NULL);
+ pud->SetPrev(NULL);
+ olDebugOut((DEB_ITRACE, "Out CUpdateList::Remove\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdateList::Empty, public
+//
+// Synopsis: Frees all elements in an update list
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CUpdateList_Empty)
+#endif
+
+void CUpdateList::Empty(void)
+{
+ CUpdate *pudTmp;
+
+ olDebugOut((DEB_ITRACE, "In CUpdateList::Empty()\n"));
+ while (_pudHead)
+ {
+ pudTmp = _pudHead->GetNext();
+ delete BP_TO_P(CUpdate *, _pudHead);
+ _pudHead = P_TO_BP(CBasedUpdatePtr, pudTmp);
+ }
+ _pudTail = NULL;
+ olDebugOut((DEB_ITRACE, "Out CUpdateList::Empty\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CUpdateList::IsEntry, public
+//
+// Synopsis: Checks the update list to see if the given name represents
+// and existing entry in the list
+//
+// Arguments: [pdfn] - Name
+// [ppud] - Update entry return or NULL
+//
+// Returns: UIE_CURRENT - Found as a current name
+// UIE_ORIGINAL - Found as an original name
+// UIE_NOTFOUND
+//
+// Modifies: [ppud]
+//
+// History: 02-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CUpdateList_IsEntry)
+#endif
+
+UlIsEntry CUpdateList::IsEntry(CDfName const *pdfn, CUpdate **ppud)
+{
+ CUpdate *pud;
+ UlIsEntry ret = UIE_NOTFOUND;
+
+ olDebugOut((DEB_ITRACE, "In CUpdateList::IsEntry:%p(%ws, %p)\n", this,
+ pdfn->GetBuffer(), ppud));
+ olAssert(pdfn != NULL && pdfn->GetLength() > 0);
+ for (pud = BP_TO_P(CUpdate *, _pudTail); pud; pud = pud->GetPrev())
+ {
+ if (pdfn->IsEqual(pud->GetCurrentName()))
+ {
+ ret = UIE_CURRENT;
+ break;
+ }
+ else if (pdfn->IsEqual(pud->GetOriginalName()))
+ {
+ ret = UIE_ORIGINAL;
+ break;
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out CUpdateList::IsEntry\n"));
+ if (ppud)
+ *ppud = pud;
+ return ret;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CUpdateList::Concat, public
+//
+// Synopsis: Concatenates an update list onto the end of this one
+//
+// Arguments: [ul] - List to concatenate
+//
+// History: 02-Nov-92 DrewB Created
+//
+// Notes: [ul]'s head may be modified
+//
+//+---------------------------------------------------------------------------
+
+#ifdef FUTURECODE
+void CUpdateList::Concat(CUpdateList &ul)
+{
+ olDebugOut((DEB_ITRACE, "In CUpdateList::Concat:%p(ul)\n", this));
+ if (_pudTail)
+ {
+ _pudTail->SetNext(ul.GetHead());
+ if (ul.GetHead())
+ {
+ ul.GetHead()->SetPrev(_pudTail);
+ olAssert(ul.GetTail() != NULL);
+ _pudTail = ul.GetTail();
+ }
+ }
+ else
+ {
+ olAssert(_pudHead == NULL);
+ _pudHead = ul.GetHead();
+ _pudTail = ul.GetTail();
+ }
+ olDebugOut((DEB_ITRACE, "Out CUpdateList::Concat\n"));
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CUpdateList::Exists, public static
+//
+// Synopsis: Traverses an update list from a particular point
+// and determines whether a given name exists or
+// is renamed
+//
+// Arguments: [pud] - Update to look from
+// [ppdfn] - Name in/out
+// [fRename] - Perform renames or quit
+//
+// Returns: TRUE if exists
+// FALSE if deleted
+//
+// History: 03-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef FUTURECODE
+BOOL CUpdateList::Exists(CUpdate *pud,
+ CDfName **ppdfn,
+ BOOL fRename)
+{
+ for (; pud; pud = pud->GetNext())
+ {
+ if (pud->IsRename() &&
+ (*ppdfn)->IsEqual(pud->GetOriginalName()))
+ {
+ if (fRename)
+ *ppdfn = pud->GetCurrentName();
+ else
+ return FALSE;
+ }
+ else if (pud->IsDelete() &&
+ (*ppdfn)->IsEqual(pud->GetOriginalName()))
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CUpdateList::FindBase, public static
+//
+// Synopsis: Searches backwards in an update list for the creation of
+// a particular object, applying renames if necessary
+//
+// Arguments: [pud] - Update to start from
+// [ppdfn] - Name in/out
+//
+// Returns: Pointer to update entry for creation or NULL if
+// no creation entry. [ppdfn] is changed to point to
+// the base name.
+//
+// Modifies: [ppdfn]
+//
+// History: 16-Apr-93 DrewB Created
+//
+// Notes: Does not kill the search on deletions; primarily
+// intended to be used with names that represent existing
+// entries, although it will work on any name
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CUpdateList_FindBase)
+#endif
+
+CUpdate *CUpdateList::FindBase(CUpdate *pud, CDfName const **ppdfn)
+{
+ for (; pud; pud = pud->GetPrev())
+ {
+ if (pud->IsRename() &&
+ (*ppdfn)->IsEqual(pud->GetCurrentName()))
+ {
+ *ppdfn = pud->GetOriginalName();
+ }
+ else if (pud->IsCreate() &&
+ (*ppdfn)->IsEqual(pud->GetCurrentName()))
+ {
+ return pud;
+ }
+ }
+ return NULL;
+}
diff --git a/private/ole32/stg/docfile/wdffuncs.cxx b/private/ole32/stg/docfile/wdffuncs.cxx
new file mode 100644
index 000000000..d07ab11a6
--- /dev/null
+++ b/private/ole32/stg/docfile/wdffuncs.cxx
@@ -0,0 +1,173 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: wdffuncs.cxx
+//
+// Contents: CWrappedDocFile support methods
+//
+// History: 22-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::DeleteContents, public
+//
+// Synopsis: Destroys the contents of a docfile
+//
+// Returns: Appropriate status code
+//
+// History: 24-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_DeleteContents) // Wrapdf_TEXT inline?
+#endif
+
+SCODE CWrappedDocFile::DeleteContents(void)
+{
+#ifdef WRAPPED_DELETE_CONTENTS
+ PDocFileIterator *pdfi;
+ SCODE sc;
+ SIterBuffer ib;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::DeleteContents:%p()\n",
+ this));
+ _ulChanged.Empty();
+ olChk(GetIterator(&pdfi));
+ for (;;)
+ {
+ if (FAILED(pdfi->BufferGetNext(&ib)))
+ break;
+ olChkTo(EH_pdfi, DestroyEntry(&ib.dfnName, FALSE));
+ }
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::DeleteContents\n"));
+ // Fall through
+EH_pdfi:
+ pdfi->Release();
+EH_Err:
+ return sc;
+#else
+ olAssert(!aMsg("CWrappedDocFile::DeleteContents called"));
+ return STG_E_UNIMPLEMENTEDFUNCTION;
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::SetInitialState, private
+//
+// Synopsis: Sets inital values from a base or defaults
+//
+// Arguments: [pdfBase] - Base object or NULL
+//
+// Returns: Appropriate status code
+//
+// History: 11-Nov-92 DrewB Created
+// 05-Sep-95 MikeHill Clear the time bits after CopyTimesFrom(base)
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_SetInitialState)
+#endif
+
+SCODE CWrappedDocFile::SetInitialState(PDocFile *pdfBase)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::SetInitialState:%p(%p)\n",
+ this, pdfBase));
+ if (pdfBase == NULL)
+ {
+ TIME_T tm;
+
+ olChk(DfGetTOD(&tm));
+ _tten.SetTime(WT_CREATION, tm);
+ _tten.SetTime(WT_MODIFICATION, tm);
+ _tten.SetTime(WT_ACCESS, tm);
+ _clsid = CLSID_NULL;
+ _grfStateBits = 0;
+ }
+ else
+ {
+ olChk(CopyTimesFrom(pdfBase));
+
+ // There's no need for the time bits to be dirty; they don't need
+ // to be written to the base because they were just read from the base.
+
+ _fDirty &= ~(BOOL)( DIRTY_CREATETIME | DIRTY_MODIFYTIME | DIRTY_ACCESSTIME );
+
+ olChk(pdfBase->GetClass(&_clsid));
+ olChk(pdfBase->GetStateBits(&_grfStateBits));
+ }
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::SetInitialState\n"));
+ // Fall through
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::RevertUpdate, private
+//
+// Synopsis: Reverses an update list entry's effect
+//
+// Arguments: [pud] - Update entry
+//
+// Returns: Appropriate status code
+//
+// History: 25-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_RevertUpdate) // Wrapdf_Revert_TEXT
+#endif
+
+void CWrappedDocFile::RevertUpdate(CUpdate *pud)
+{
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::RevertUpdate:%p(%p)\n",
+ this, pud));
+ if (pud->IsCreate())
+ {
+ CDFBasis *pdfb = BP_TO_P(CDFBasis *, _pdfb);
+
+ olAssert(pud->GetLUID() != DF_NOLUID);
+ _ppubdf->DestroyChild(pud->GetLUID());
+ if ((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL)) == STGTY_STORAGE)
+ {
+ CDocFile::Unreserve(1, pdfb);
+ CWrappedDocFile::Unreserve(_ppubdf->GetTransactedDepth()-1,
+ pdfb);
+ }
+ else
+ {
+ CDirectStream::Unreserve(1, pdfb);
+ CTransactedStream::Unreserve(_ppubdf->GetTransactedDepth()-1,
+ pdfb);
+ }
+ }
+ else if (pud->IsRename())
+ {
+ // Roll back renames
+ olAssert(_ppubdf->FindXSMember(pud->GetOriginalName(),
+ GetName()) == NULL &&
+ aMsg("Revert rename precondition"));
+
+ _ppubdf->RenameChild(pud->GetCurrentName(), GetName(),
+ pud->GetOriginalName());
+
+ olAssert(_ppubdf->FindXSMember(pud->GetCurrentName(),
+ GetName()) == NULL &&
+ aMsg("Revert rename postcondition"));
+ }
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::RevertUpdate\n"));
+}
diff --git a/private/ole32/stg/docfile/wdfiter.cxx b/private/ole32/stg/docfile/wdfiter.cxx
new file mode 100644
index 000000000..2e3178c37
--- /dev/null
+++ b/private/ole32/stg/docfile/wdfiter.cxx
@@ -0,0 +1,289 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: wdfiter.cxx
+//
+// Contents: CWrappedDocFile iterator methods
+//
+// History: 22-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::FindGreaterEntry, public
+//
+// Synopsis: Returns the next greater child
+//
+// Arguments: [pdfnKey] - Previous key
+// [pib] - Fast iterator buffer
+// [pstat] - Full iterator buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pib] or [pstat]
+//
+// History: 16-Apr-93 DrewB Created
+//
+// Notes: Either [pib] or [pstat] must be NULL
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_FindGreaterEntry) // Iterate_TEXT
+#endif
+
+SCODE CWrappedDocFile::FindGreaterEntry(CDfName const *pdfnKey,
+ SIterBuffer *pib,
+ STATSTGW *pstat)
+{
+ SCODE sc;
+ CDfName *pdfnGreater, *pdfn;
+ CUpdate *pud, *pudGreater;
+ BOOL fFilled = FALSE;
+ WCHAR *pwcsName;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::FindGreaterEntry:%p("
+ "%p, %p, %p)\n", this, pdfnKey, pib, pstat));
+ olAssert(pib == NULL || pstat == NULL);
+
+ // Find the update entry that has the next greater name than the key
+ pudGreater = NULL;
+ for (pud = _ulChanged.GetHead(); pud; pud = pud->GetNext())
+ {
+ if (pud->IsCreate() || pud->IsRename())
+ {
+ pdfn = pud->GetCurrentName();
+ if (_ulChanged.IsEntry(pdfn, NULL) == UIE_CURRENT &&
+ CDirectory::NameCompare(pdfn, pdfnKey) > 0 &&
+ (pudGreater == NULL ||
+ CDirectory::NameCompare(pdfn,
+ pudGreater->GetCurrentName()) < 0))
+ {
+ pudGreater = pud;
+ pdfnGreater = pdfn;
+ }
+ }
+ }
+
+ // Request the next greater name from the base
+ if (_pdfBase != NULL)
+ {
+ CDfName dfnKey;
+
+ // Loop until we either get a valid name or we run out
+ dfnKey.Set(pdfnKey);
+ for (;;)
+ {
+ if (FAILED(sc = _pdfBase->FindGreaterEntry(&dfnKey, pib, pstat)))
+ {
+ if (sc != STG_E_NOMOREFILES)
+ {
+ olErr(EH_Err, sc);
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (pib)
+ dfnKey.Set(&pib->dfnName);
+ else
+ {
+ olAssert(pstat != NULL);
+ dfnKey.CopyString(pstat->pwcsName);
+ }
+
+ // Filter this name against the update list
+ pdfn = &dfnKey;
+ if (_ulChanged.IsEntry(pdfn, NULL) == UIE_ORIGINAL)
+ {
+ if (pstat)
+ TaskMemFree(pstat->pwcsName);
+ continue;
+ }
+
+ // If this name is less than the update list name, use
+ // the stat entry
+ if (pudGreater == NULL ||
+ CDirectory::NameCompare(pdfn,
+ pudGreater->GetCurrentName()) < 0)
+ {
+ PTSetMember *ptsm;
+
+ fFilled = TRUE;
+
+ if (pstat && (ptsm = _ppubdf->FindXSMember(pdfn, GetName())))
+ {
+ pwcsName = pstat->pwcsName;
+ // We want to keep the name already in pstat but pick
+ // up any new times on the XSM
+ olChkTo(EH_name, ptsm->Stat(pstat, STATFLAG_NONAME));
+ pstat->pwcsName = pwcsName;
+ }
+
+ // No need to check for renames because Exists would
+ // have failed if there was a rename
+ }
+ else if (pstat)
+ {
+ TaskMemFree(pstat->pwcsName);
+ }
+
+ // Found a valid name, so stop looping
+ break;
+ }
+ }
+
+ if (!fFilled)
+ {
+ if (pudGreater == NULL)
+ {
+ sc = STG_E_NOMOREFILES;
+ }
+ else
+ {
+ if (pstat)
+ {
+ if (pudGreater->IsCreate())
+ {
+ olChk(pudGreater->GetXSM()->Stat(pstat, 0));
+ }
+ else
+ {
+ olAssert(pudGreater->IsRename());
+ olChk(StatEntry(pudGreater->GetCurrentName(), pib, pstat));
+ }
+ }
+ else
+ {
+ olAssert(pib != NULL);
+ pib->dfnName.Set(pudGreater->GetCurrentName());
+ pib->type = pudGreater->GetFlags() & ULF_TYPEFLAGS;
+ }
+ sc = S_OK;
+ }
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::FindGreaterEntry\n"));
+ EH_Err:
+ return sc;
+
+ EH_name:
+ if (pstat)
+ TaskMemFree(pwcsName);
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::StatEntry, public
+//
+// Synopsis: Gets information for a child
+//
+// Arguments: [pdfn] - Child name
+// [pib] - Short information
+// [pstat] - Full information
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pib] or [pstat]
+//
+// History: 16-Apr-93 DrewB Created
+//
+// Notes: Either [pib] or [pstat] must be NULL
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_StatEntry)
+#endif
+
+SCODE CWrappedDocFile::StatEntry(CDfName const *pdfn,
+ SIterBuffer *pib,
+ STATSTGW *pstat)
+{
+ CUpdate *pud;
+ UlIsEntry uie;
+ SCODE sc = S_FALSE;
+ CDfName const *pdfnBase = pdfn;
+ BOOL fResult = FALSE;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::StatEntry:%p(%p, %p, %p)\n",
+ this, pdfn, pib, pstat));
+ olAssert((pib != NULL) != (pstat != NULL));
+
+ // Attempt to find the name in the update list
+ uie = _ulChanged.IsEntry(pdfn, &pud);
+ if (uie == UIE_ORIGINAL)
+ {
+ // Name has been renamed or deleted
+ sc = STG_E_FILENOTFOUND;
+ fResult = TRUE;
+ }
+ else if (uie == UIE_CURRENT)
+ {
+ if (pib)
+ {
+ pib->dfnName.Set(pud->GetCurrentName());
+ pib->type = pud->GetFlags() & ULF_TYPEFLAGS;
+ fResult = TRUE;
+ sc = S_OK;
+ }
+ else
+ {
+
+ olAssert(pstat != NULL);
+
+ // Find whether the given name came from a create entry
+ // or resolve the name to the base name
+ pud = CUpdateList::FindBase(pud, &pdfnBase);
+ if (pud != NULL)
+ {
+ // Stat creation update entry
+ olChk(pud->GetXSM()->Stat(pstat, 0));
+ fResult = TRUE;
+ }
+ // else the update entry is a rename of an object in the base
+ // and FindBase changed pdfnBase to the base name
+ }
+ }
+
+ olAssert(fResult || sc == S_FALSE);
+
+ if (!fResult)
+ {
+ // Haven't found the entry so try the base
+ if (_pdfBase)
+ {
+ olChk(_pdfBase->StatEntry(pdfnBase, pib, pstat));
+
+ // Check to see if we need to return a renamed name
+ if (!pdfn->IsEqual(pdfnBase))
+ {
+ if (pib)
+ pib->dfnName.Set(pdfn);
+ else
+ {
+ TaskMemFree(pstat->pwcsName);
+ olMem(pstat->pwcsName =
+ (WCHAR *)TaskMemAlloc(pdfn->GetLength()));
+ memcpy(pstat->pwcsName, pdfn->GetBuffer(),
+ pdfn->GetLength());
+ }
+ }
+ }
+ else
+ sc = STG_E_FILENOTFOUND;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::StatEntry\n"));
+ EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/docfile/wdfstrm.cxx b/private/ole32/stg/docfile/wdfstrm.cxx
new file mode 100644
index 000000000..69d487f66
--- /dev/null
+++ b/private/ole32/stg/docfile/wdfstrm.cxx
@@ -0,0 +1,189 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: wdfstrm.cxx
+//
+// Contents: CWrappedDocFile stream methods
+//
+// History: 22-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+#include <tstream.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::CreateStream, public
+//
+// Synopsis: Creates a wrapped stream
+//
+// Arguments: [pdfnName] - Name
+// [df] - Transactioning flags
+// [dlSet] - LUID to set or DF_NOLUID
+// [pppstStream] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pppstStream]
+//
+// History: 09-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_CreateStream) // Wrapdf_Create_TEXT
+#endif
+
+SCODE CWrappedDocFile::CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID dlSet,
+ PSStream **ppsstStream)
+{
+ SEntryBuffer eb;
+ SCODE sc;
+ CTransactedStream *pstWrapped;
+ CUpdate *pud = NULL;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::CreateStream("
+ "%ws, %X, %lu, %p)\n", pdfnName, df, dlSet,
+ ppsstStream));
+
+ if (SUCCEEDED(IsEntry(pdfnName, &eb)))
+ olErr(EH_Err, STG_E_FILEALREADYEXISTS);
+
+ olAssert(P_TRANSACTED(_df));
+
+ if (dlSet == DF_NOLUID)
+ dlSet = CTransactedStream::GetNewLuid(_pdfb->GetMalloc());
+ pstWrapped = GetReservedStream(pdfnName, dlSet, _df);
+ if (!P_NOUPDATE(df))
+ {
+ olMemTo(EH_pstWrapped,
+ (pud = _ulChanged.Add(_pdfb->GetMalloc(),
+ pdfnName, NULL, dlSet,
+ STGTY_STREAM, pstWrapped)));
+ }
+ olChkTo(EH_pud, pstWrapped->Init(NULL));
+ _ppubdf->AddXSMember(this, pstWrapped, dlSet);
+ *ppsstStream = pstWrapped;
+
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::CreateStream => %p\n",
+ *ppsstStream));
+ return S_OK;
+
+ EH_pud:
+ if (pud)
+ _ulChanged.Delete(pud);
+ EH_pstWrapped:
+ pstWrapped->ReturnToReserve(BP_TO_P(CDFBasis *, _pdfb));
+ EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::GetStream, public
+//
+// Synopsis: Instantiates a wrapped stream
+//
+// Arguments: [pdfnName] - Name
+// [df] - Permissions
+// [pppstStream] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pppstStream]
+//
+// History: 09-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_GetStream) // Wrapdf_Open_TEXT
+#endif
+
+SCODE CWrappedDocFile::GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ PSStream **ppsstStream)
+{
+ PSStream *psstNew;
+ PTSetMember *ptsm;
+ CTransactedStream *pstWrapped;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::GetStream("
+ "%ws, %X, %p)\n", pdfnName, df, ppsstStream));
+
+ olAssert(P_TRANSACTED(_df));
+
+ // Look for this name in this level transaction set
+
+ if ((ptsm = _ppubdf->FindXSMember(pdfnName, GetName())) != NULL)
+ {
+ if (ptsm->ObjectType() != STGTY_STREAM)
+ olErr(EH_Err, STG_E_FILENOTFOUND);
+ ptsm->AddRef();
+ *ppsstStream = (CTransactedStream *)ptsm;
+ }
+ else if (_pdfBase == NULL ||
+ _ulChanged.IsEntry(pdfnName, NULL) == UIE_ORIGINAL)
+ {
+ // named entry has been renamed or deleted
+ // (we can't have a rename or delete without a base)
+
+ olErr(EH_Err, STG_E_FILENOTFOUND);
+ }
+ else
+ {
+ // We didn't find it here, so we need to ask our parent
+ // Find the right name to ask of the parent
+
+ CDfName const *pdfnRealName = pdfnName;
+ CUpdate *pud;
+
+ if (_ulChanged.IsEntry(pdfnName, &pud) == UIE_CURRENT &&
+ pud->IsRename())
+ {
+ pdfnRealName = pud->GetCurrentName();
+ // We don't have to worry about picking up creates
+ // because any create would have an XSM that would
+ // be detected above
+ olVerify(_ulChanged.FindBase(pud, &pdfnRealName) == NULL);
+ }
+
+ olAssert(_pdfBase != NULL);
+ olChk(_pdfBase->GetStream(pdfnRealName, df, &psstNew));
+ olAssert(psstNew->GetLuid() != DF_NOLUID &&
+ aMsg("Stream id is DF_NOLUID!"));
+
+#ifdef USE_NOSCRATCH
+ olMemTo(EH_Get, pstWrapped = new(_pdfb->GetMalloc())
+ CTransactedStream(pdfnName, psstNew->GetLuid(), _df,
+ _pdfb->GetBaseMultiStream(),
+ _pdfb->GetScratch()));
+#else
+ olMemTo(EH_Get, pstWrapped = new(_pdfb->GetMalloc())
+ CTransactedStream(pdfnName, psstNew->GetLuid(), _df,
+ _pdfb->GetScratch()));
+#endif
+ olChkTo(EH_pstWrapped, pstWrapped->Init(psstNew));
+ *ppsstStream = pstWrapped;
+ _ppubdf->AddXSMember(this, pstWrapped, pstWrapped->GetLuid());
+ }
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::GetStream => %p\n",
+ *ppsstStream));
+ return S_OK;
+
+EH_pstWrapped:
+ delete pstWrapped;
+EH_Get:
+ psstNew->Release();
+EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/docfile/wdfxact.cxx b/private/ole32/stg/docfile/wdfxact.cxx
new file mode 100644
index 000000000..e5768b6e4
--- /dev/null
+++ b/private/ole32/stg/docfile/wdfxact.cxx
@@ -0,0 +1,589 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: wdfxact.cxx
+//
+// Contents: CWrappedDocFile transactioning methods
+//
+// History: 22-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+#include <sstream.hxx>
+#include <tstream.hxx>
+#include <dfdeb.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::BeginCommit, public
+//
+// Synopsis: Allocates commit resources for two-phase commit
+//
+// Arguments: [dwFlags] - Flags
+//
+// Returns: Appropriate status code
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_BeginCommit) // Wrapdf_Commit_TEXT
+#endif
+
+SCODE CWrappedDocFile::BeginCommit(DWORD const dwFlags)
+{
+ SCODE sc;
+#ifdef INDINST
+ DFSIGNATURE sigNew;
+#endif
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::BeginCommit(%lX)\n",
+ dwFlags));
+
+ olAssert(_pdfBase != NULL);
+ olAssert(P_TRANSACTED(_df));
+
+#if DBG == 1
+ if (!HaveResource(DBR_XSCOMMITS, 1))
+ olErr(EH_Err, STG_E_ABNORMALAPIEXIT);
+#endif
+
+ _fBeginCommit = TRUE;
+#ifdef INDINST
+ _ppubdf->GetNewSignature(&sigNew);
+ olChk(_pdfBase->BeginCommitFromChild(_ulChanged, NULL,
+ _sigBase, sigNew, dwFlags, _ppubdf));
+ // INDINST - Ownership of dirty and changed?
+ if (P_INDEPENDENT(_df) && _pdfParent)
+ olChkTo(EH_Begin,
+ _pdfParent->BeginCommitFromChild(_ulChanged,
+ _pdfBase, _sigBase, sigNew,
+ dwFlags, _ppubdf));
+ _sigBaseOld = _sigBase;
+ _sigCombinedOld = _sigCombined;
+ _sigBase = _sigCombined = sigNew;
+#else
+ olChk(_pdfBase->BeginCommitFromChild(_ulChanged, dwFlags, this));
+#endif
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::BeginCommit\n"));
+ return S_OK;
+
+#ifdef INDINST
+EH_Begin:
+ _pdfBase->EndCommitFromChild(DF_ABORT);
+#endif
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::EndCommit, public
+//
+// Synopsis: Performs actual commit/abort for two-phase commit
+//
+// Arguments: [df] - COMMIT/ABORT
+//
+// Returns: Appropriate status code
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_EndCommit)
+#endif
+
+void CWrappedDocFile::EndCommit(DFLAGS const df)
+{
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::EndCommit(%X)\n",
+ df));
+
+ olAssert(P_TRANSACTED(_df));
+
+ if (!_fBeginCommit)
+ return;
+ _fBeginCommit = FALSE;
+
+#if DBG == 1
+ if (P_COMMIT(df))
+ ModifyResLimit(DBR_XSCOMMITS, 1);
+#endif
+
+ _pdfBase->EndCommitFromChild(df, this);
+#ifdef INDINST
+ if (P_INDEPENDENT(_df) && _pdfParent)
+ olVerSucc(_pdfParent->EndCommitFromChild(df));
+#endif
+
+ if (P_COMMIT(df))
+ {
+ // These are nulled because the memory should be gone
+ _ulChanged.Unlink();
+ SetClean();
+ }
+ else
+ {
+#ifdef INDINST
+ _sigBase = _sigBaseOld;
+ _sigCombined = _sigCombinedOld;
+#endif
+ }
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::EndCommit\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::Revert, public
+//
+// Synopsis: Transaction level has requested revert
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_Revert) // Wrapdf_Revert_TEXT
+#endif
+
+void CWrappedDocFile::Revert(void)
+{
+ CUpdate *pud;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile %p::Revert()\n", this));
+ for (pud = _ulChanged.GetTail(); pud; pud = pud->GetPrev())
+ RevertUpdate(pud);
+ _ulChanged.Empty();
+ olVerSucc(SetInitialState(BP_TO_P(PDocFile *, _pdfBase)));
+ SetClean();
+
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::Revert\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::BeginCommitFromChild, public
+//
+// Synopsis: Start two-phase commit, requested by child
+//
+// Arguments: [ulChanged] - Change list
+// [dwFlags] - Flags controlling commit
+// [pdfChild] - Child object
+//
+// Returns: Appropriate status code
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_BeginCommitFromChild) // Wrapdf_Commit_TEXT
+#endif
+
+SCODE CWrappedDocFile::BeginCommitFromChild(CUpdateList &ulChanged,
+ DWORD const dwFlags,
+ CWrappedDocFile *pdfChild)
+{
+ CUpdate *pud, *pudNext;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::BeginCommitFromChild:%p("
+ "%p, %lX, %p)\n", this, ulChanged.GetHead(), dwFlags,
+ pdfChild));
+
+ UNREFERENCED_PARM(pdfChild);
+
+ olAssert(P_TRANSACTED(_df));
+ olAssert(_tssDeletedHolder.GetHead() == NULL);
+
+ _ulChangedHolder = ulChanged;
+ _ulChangedOld = _ulChanged;
+
+ for (pud = ulChanged.GetHead(); pud; pud = pudNext)
+ {
+ if (pud->IsRename())
+ _ppubdf->RenameChild(pud->GetOriginalName(), GetName(),
+ pud->GetCurrentName());
+ else if (pud->IsDelete())
+ {
+ PTSetMember *ptsm;
+ if ((ptsm = _ppubdf->FindXSMember(pud->GetOriginalName(),
+ GetName())) != NULL)
+ {
+ olAssert(ptsm->GetName() != DF_NOLUID &&
+ aMsg("Can't destroy NOLUID XSM"));
+ // Take a reference because RemoveXSMember
+ // will call Release
+ ptsm->AddRef();
+ _ppubdf->RemoveXSMember(ptsm);
+ _tssDeletedHolder.AddMember(ptsm);
+ }
+ }
+ else
+ if (pud->IsCreate())
+ olVerSucc(CreateFromUpdate(pud, this,
+ DF_WRITE | DF_NOUPDATE |
+ DF_TRANSACTED));
+ pudNext = pud->GetNext();
+ _ulChanged.Append(pud);
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::BeginCommitFromChild\n"));
+ return S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::EndCommitFromChild
+//
+// Synopsis: Ends two-phase commit, requested by child
+//
+// Arguments: [df] - COMMIT/ABORT
+// [pdfChild] - Child object
+//
+// Returns: Appropriate status code
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_EndCommitFromChild)
+#endif
+
+void CWrappedDocFile::EndCommitFromChild(DFLAGS const df,
+ CWrappedDocFile *pdfChild)
+{
+ PTSetMember *ptsm;
+ CUpdate *pud;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::EndCommitFromChild:%p("
+ "%X, %p)\n", this, df, pdfChild));
+
+ olAssert(P_TRANSACTED(_df));
+
+ if (!P_COMMIT(df))
+ {
+ // Restore our update list
+ _ulChanged = _ulChangedOld;
+
+ // Unconcat _ulChanged and ulChanged
+ if (_ulChanged.GetTail())
+ _ulChanged.GetTail()->SetNext(NULL);
+ if (_ulChangedHolder.GetHead())
+ _ulChangedHolder.GetHead()->SetPrev(NULL);
+
+ // Back out updates
+ for (pud = _ulChangedHolder.GetTail(); pud; pud = pud->GetPrev())
+ if (pud->IsCreate())
+ {
+ // We need to do two things:
+ //
+ // Break any SetBase links that might have been created
+ //
+ // Return newly created objects to the creators so
+ // that they can be returned to the preallocation
+ // pool
+
+ if ((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL)) ==
+ STGTY_STORAGE)
+ {
+ CWrappedDocFile *pwdf = (CWrappedDocFile *)pud->GetXSM();
+ CWrappedDocFile *pwdfBase;
+
+ if ((pwdfBase = (CWrappedDocFile *)pwdf->GetBase()) !=
+ NULL)
+ {
+ // Increase ref count because SetBase will release
+ pwdfBase->AddRef();
+ pwdf->SetBase(NULL);
+ ReturnDocFile(pwdfBase);
+ }
+ }
+ else
+ {
+ CTransactedStream *ptstm = (CTransactedStream *)pud->
+ GetXSM();
+ CTransactedStream *ptstmBase;
+
+ olAssert((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL))
+ == STGTY_STREAM);
+ if ((ptstmBase = (CTransactedStream *)ptstm->GetBase()) !=
+ NULL)
+ {
+ // Increase ref count because SetBase will release
+ ptstmBase->AddRef();
+ ptstm->SetBase(NULL);
+ ReturnStream(ptstmBase);
+ }
+ }
+ }
+ else if (pud->IsDelete())
+ {
+ // We use GetName() as the tree because we know that
+ // only immediate children can show up in delete records
+ if ((ptsm = _tssDeletedHolder.FindName(pud->GetOriginalName(),
+ GetName())) != NULL)
+ {
+ _tssDeletedHolder.RemoveMember(ptsm);
+ _ppubdf->InsertXSMember(ptsm);
+ // Release the reference we took in BeginCommitFromChild
+ // because InsertXSMember takes a reference
+ ptsm->Release();
+ }
+ }
+ else if (pud->IsRename())
+ {
+ // Roll back renames
+ olAssert(_ppubdf->FindXSMember(pud->GetOriginalName(),
+ GetName()) == NULL &&
+ aMsg("Abort commit rename precondition"));
+
+ _ppubdf->RenameChild(pud->GetCurrentName(), GetName(),
+ pud->GetOriginalName());
+
+ olAssert(_ppubdf->FindXSMember(pud->GetCurrentName(),
+ GetName()) == NULL &&
+ aMsg("Abort commit rename postcondition"));
+ }
+ }
+ else
+ {
+ // Finalize creations
+ for (pud = _ulChangedHolder.GetHead(); pud; pud = pud->GetNext())
+ if (pud->IsCreate())
+ {
+ // Since the object pointed to by GetBase is at our level,
+ // we know it is transacted so we can safely cast to
+ // PTSetMember
+ if ((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL)) ==
+ STGTY_STORAGE)
+ {
+ ptsm = (CWrappedDocFile *)
+ ((CWrappedDocFile *)pud->GetXSM())->GetBase();
+ }
+ else
+ {
+ olAssert((pud->GetFlags() & (ULF_TYPEFLAGS & STGTY_REAL))
+ == STGTY_STREAM);
+ ptsm = (CTransactedStream *)
+ ((CTransactedStream *)pud->GetXSM())->GetBase();
+ }
+ pud->SetXSM(ptsm);
+ }
+
+ // Finalize deletions
+ while (ptsm = _tssDeletedHolder.GetHead())
+ {
+ olAssert(ptsm->GetName() != DF_NOLUID &&
+ aMsg("Can't destroy NOLUID XSM"));
+ _ppubdf->DestroyChild(ptsm->GetName());
+ _tssDeletedHolder.RemoveMember(ptsm);
+ ptsm->Release();
+ }
+
+ // Pick up state information
+ TIME_T tm;
+
+ if (pdfChild->GetDirty() & DIRTY_CREATETIME)
+ {
+ olVerSucc(pdfChild->GetTime(WT_CREATION, &tm));
+ olVerSucc(SetTime(WT_CREATION, tm));
+ }
+ if (pdfChild->GetDirty() & DIRTY_MODIFYTIME)
+ {
+ olVerSucc(pdfChild->GetTime(WT_MODIFICATION, &tm));
+ olVerSucc(SetTime(WT_MODIFICATION, tm));
+ }
+ if (pdfChild->GetDirty() & DIRTY_ACCESSTIME)
+ {
+ olVerSucc(pdfChild->GetTime(WT_ACCESS, &tm));
+ olVerSucc(SetTime(WT_ACCESS, tm));
+ }
+ if (pdfChild->GetDirty() & DIRTY_CLASS)
+ {
+ CLSID cls;
+
+ olVerSucc(pdfChild->GetClass(&cls));
+ olVerSucc(SetClass(cls));
+ }
+ if (pdfChild->GetDirty() & DIRTY_STATEBITS)
+ {
+ DWORD dwState;
+
+ olVerSucc(pdfChild->GetStateBits(&dwState));
+ olVerSucc(SetStateBits(dwState, 0xffffffff));
+ }
+ }
+
+ // Forget temporary commit lists
+ _ulChangedOld.Unlink();
+ _ulChangedHolder.Unlink();
+
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::EndCommitFromChild\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::GetSignature, public
+//
+// Synopsis: Returns signature
+//
+// Returns: Appropriate status code
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef INDINST
+void CWrappedDocFile::GetSignature(DFSIGNATURE *psig)
+{
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::GetSignature()\n"));
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::GetSignature => %ld\n",
+ _sigCombined));
+ *psig = _sigCombined;
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::SetSignature, public
+//
+// Synopsis: Sets the signature
+//
+// Arguments: [sig] - Signature
+//
+// Returns: Appropriate status code
+//
+// History: 04-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef INDINST
+void CWrappedDocFile::SetSignature(DFSIGNATURE sig)
+{
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::SetSignature(%ld)\n", sig));
+ _sigCombined = sig;
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::SetSignature\n"));
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::SetBase, public
+//
+// Synopsis: Sets Base pointer
+//
+// Arguments: [pdf] - New base
+//
+// Returns: Appropriate status code
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_SetBase) // Wrapdf_Commit_TEXT
+#endif
+
+SCODE CWrappedDocFile::SetBase(PDocFile *pdf)
+{
+ SCODE sc = S_OK;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::SetBase(%p)\n", pdf));
+ olAssert(_pdfBase == NULL || pdf == NULL);
+ if (_pdfBase)
+ _pdfBase->Release();
+ if (pdf)
+ {
+ olChk(pdf->CopyTimesFrom(this));
+ olChk(pdf->SetClass(_clsid));
+ olChk(pdf->SetStateBits(_grfStateBits, 0xffffffff));
+ }
+ _pdfBase = P_TO_BP(CBasedDocFilePtr, pdf);
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::SetBase\n"));
+ // Fall through
+ EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::CopySelf, public
+//
+// Synopsis: Duplicates this object
+//
+// Arguments: [ptsm] - New object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [*pstm] holds pointer to new object if successful
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef INDINST
+SCODE CWrappedDocFile::CopySelf(PTSetMember **pptsm)
+{
+ CDocFile *pdfCopy;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::CopySelf()\n"));
+ olChk(_ppubdf->GetScratchDocFile(&pdfCopy));
+ olChkTo(EH_pdfCopy,
+ CopyDocFileToDocFile(this, pdfCopy, TRUE, FALSE, TRUE, NULL));
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::CopySelf => %p\n",
+ pdfCopy));
+ *pptsm = pdfCopy;
+ return S_OK;
+
+EH_pdfCopy:
+ pdfCopy->Destroy();
+EH_Err:
+ return sc;
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::GetCommitInfo, public
+//
+// Synopsis: Returns space accounting information for commits
+//
+// Arguments: [pulRet1] - Return for number of new entries
+// [pulRet2] - Return for number of deleted entries
+//
+// Modifies: [pulRet1]
+// [pulRet2]
+//
+// History: 07-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_GetCommitInfo) // Wrapdf_Overwrite_TEXT
+#endif
+
+void CWrappedDocFile::GetCommitInfo(ULONG *pulRet1, ULONG *pulRet2)
+{
+ CUpdate *pud;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::GetCommitInfo(%p, %p)\n",
+ pulRet1, pulRet2));
+ *pulRet1 = 0;
+ *pulRet2 = 0;
+ for (pud = _ulChanged.GetHead(); pud; pud = pud->GetNext())
+ if (pud->IsCreate())
+ *pulRet1++;
+ else if (pud->IsDelete())
+ *pulRet2++;
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::GetCommitInfo => %lu, %lu\n",
+ *pulRet1, *pulRet2));
+}
diff --git a/private/ole32/stg/docfile/wdocfile.cxx b/private/ole32/stg/docfile/wdocfile.cxx
new file mode 100644
index 000000000..064af1160
--- /dev/null
+++ b/private/ole32/stg/docfile/wdocfile.cxx
@@ -0,0 +1,781 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: wdocfile.cxx
+//
+// Contents: Implementation of CWrappedDocFile methods for DocFiles
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+#pragma hdrstop
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::CWrappedDocFile, public
+//
+// Synopsis: Empty object constructor
+//
+// Arguments: [pdfn] - Name
+// [dl] - LUID
+// [df] - Transactioning flags
+// [dwType] - Type of object
+// [pdfb] - Basis
+// [ppubdf] - Public docfile
+//
+// History: 30-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_CWrappedDocFile) // Wrapdf_Init_TEXT
+#endif
+
+CWrappedDocFile::CWrappedDocFile(CDfName const *pdfn,
+ DFLUID dl,
+ DFLAGS const df,
+ CDFBasis *pdfb,
+ CPubDocFile *ppubdf)
+ : PTSetMember(pdfn, STGTY_STORAGE),
+ PDocFile(dl),
+ _pdfb(P_TO_BP(CBasedDFBasisPtr, pdfb))
+{
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::CWrappedDocFile:%p("
+ "%ws, %lu, %X, %p, %p)\n", this, pdfn->GetBuffer(),
+ dl, df, pdfb, ppubdf));
+
+ _df = df;
+ _fBeginCommit = FALSE;
+ _cReferences = 0;
+ _pdfParent = NULL;
+ _ppubdf = P_TO_BP(CBasedPubDocFilePtr, ppubdf);
+ _fDirty = 0;
+ _pdfBase = NULL;
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::CWrappedDocFile\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::Init, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [pdfBase] - Base DocFile
+//
+// Returns: Appropriate status code
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_Init)
+#endif
+
+SCODE CWrappedDocFile::Init(PDocFile *pdfBase)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::CWrappedDocFile:%p(%p)\n",
+ this, pdfBase));
+
+ olChk(SetInitialState(pdfBase));
+ _pdfBase = P_TO_BP(CBasedDocFilePtr, pdfBase);
+ AddRef();
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::CWrappedDocFile\n"));
+ // Fall through
+EH_Err:
+ return sc;
+}
+
+
+#ifdef COORD
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::InitPub, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [ppubdf] - Enclosing CPubDocFile
+//
+// Returns: Appropriate status code
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_Init)
+#endif
+
+SCODE CWrappedDocFile::InitPub(CPubDocFile *ppubdf)
+{
+ _ppubdf = P_TO_BP(CBasedPubDocFilePtr, ppubdf);
+ return S_OK;
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::~CWrappedDocFile, public
+//
+// Synopsis: Destructor
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_1CWrappedDocFile) // Wrapdf_Shutdown_TEXT
+#endif
+
+CWrappedDocFile::~CWrappedDocFile(void)
+{
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::~CWrappedDocFile()\n"));
+ olAssert(_cReferences == 0);
+#ifdef INDINST
+ if (P_INDEPENDENT(_df))
+ ((CDocFile *)_pdfBase)->Destroy();
+ else
+#endif
+ if (_pdfBase)
+ _pdfBase->Release();
+ // We don't want SetInitialState in Revert to actually refer to the
+ // base because this object is dying and we shouldn't communicate
+ // with out base except for the above Release
+ _pdfBase = NULL;
+ CWrappedDocFile::Revert();
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::~CWrappedDocFile\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::CreateDocFile, public
+//
+// Synopsis: Creates an embedded DocFile
+//
+// Arguments: [pdfnName] - Name of DocFile
+// [df] - Transactioning flags
+// [dlSet] - LUID to set or DF_NOLUID
+// [dwType] - Type of entry
+// [ppdfDocFile] - DocFile pointer return
+//
+// Returns: Appropriate error code
+//
+// Modifies: [*ppdfDocFile] holds DocFile pointer if successful
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_CreateDocFile) // Wrapdf_Create_TEXT
+#endif
+
+SCODE CWrappedDocFile::CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID dlSet,
+ PDocFile **ppdfDocFile)
+{
+ CWrappedDocFile *pdfWrapped;
+ SEntryBuffer eb;
+ SCODE sc;
+ CUpdate *pud = NULL;
+ CDFBasis *pdfb = BP_TO_P(CDFBasis *, _pdfb);
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::CreateDocFile:%p("
+ "%ws, %X, %lu, %p, %p)\n", this, pdfnName, df, dlSet,
+ ppdfDocFile));
+
+ if (SUCCEEDED(IsEntry(pdfnName, &eb)))
+ olErr(EH_Err, STG_E_FILEALREADYEXISTS);
+
+ olAssert(P_TRANSACTED(_df));
+
+ if (dlSet == DF_NOLUID)
+ dlSet = CWrappedDocFile::GetNewLuid(_pdfb->GetMalloc());
+
+ pdfWrapped = new (pdfb)
+ CWrappedDocFile(pdfnName, dlSet, _df,
+ pdfb, BP_TO_P(CPubDocFile *, _ppubdf));
+ olAssert(pdfWrapped != NULL && aMsg("Reserved DocFile not found"));
+
+ if (!P_NOUPDATE(df))
+ {
+ olMemTo(EH_pdfWrapped,
+ (pud = _ulChanged.Add(pdfb->GetMalloc(),
+ pdfnName, NULL, dlSet,
+ STGTY_STORAGE, pdfWrapped)));
+ }
+ olChkTo(EH_pud, pdfWrapped->Init(NULL));
+ _ppubdf->AddXSMember(this, pdfWrapped, dlSet);
+ *ppdfDocFile = pdfWrapped;
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::CreateDocFile => %p\n",
+ *ppdfDocFile));
+ return S_OK;
+
+ EH_pud:
+ if (pud)
+ _ulChanged.Delete(pud);
+ EH_pdfWrapped:
+ pdfWrapped->ReturnToReserve(pdfb);
+ EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::GetDocFile, public
+//
+// Synopsis: Instantiates or converts an existing stream to a
+// DocFile
+//
+// Arguments: [pdfnName] - Name of stream
+// [df] - Transactioning flags
+// [dwType] - Type of entry
+// [ppdfDocFile] - Pointer to return new object
+//
+// Returns: Appropriate error code
+//
+// Modifies: [*ppdfDocFile] holds DocFile pointer if successful
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_GetDocFile) // Wrapdf_Open_TEXT
+#endif
+
+SCODE CWrappedDocFile::GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ PDocFile **ppdfDocFile)
+{
+ PDocFile *pdfNew;
+ PTSetMember *ptsm;
+ CWrappedDocFile *pdfWrapped;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::GetDocFile:%p("
+ "%ws, %X, %p)\n", this, pdfnName, df, ppdfDocFile));
+
+ olAssert(P_TRANSACTED(_df));
+
+ // Look for this name in this level transaction set
+
+ if ((ptsm = _ppubdf->FindXSMember(pdfnName, GetName())) != NULL)
+ {
+ if (ptsm->ObjectType() != STGTY_STORAGE)
+ olErr(EH_Err, STG_E_FILENOTFOUND);
+
+ ptsm->AddRef();
+ *ppdfDocFile = (CWrappedDocFile *)ptsm;
+ }
+ else if (_pdfBase == NULL ||
+ _ulChanged.IsEntry(pdfnName, NULL) == UIE_ORIGINAL)
+ {
+ // named entry has been renamed or deleted
+ // (we can't have a rename or delete without a base)
+
+ olErr(EH_Err, STG_E_FILENOTFOUND);
+ }
+ else
+ {
+ CDfName const *pdfnRealName = pdfnName;
+ CUpdate *pud;
+
+ if (_ulChanged.IsEntry(pdfnName, &pud) == UIE_CURRENT &&
+ pud->IsRename())
+ {
+ pdfnRealName = pud->GetCurrentName();
+ // We don't have to worry about picking up creates
+ // because any create would have an XSM that would
+ // be detected above
+ olVerify(_ulChanged.FindBase(pud, &pdfnRealName) == NULL);
+ }
+
+ olAssert(_pdfBase != NULL);
+ olChk(_pdfBase->GetDocFile(pdfnRealName, df, &pdfNew));
+ olAssert(pdfNew->GetLuid() != DF_NOLUID &&
+ aMsg("Docfile id is DF_NOLUID!"));
+
+ CDFBasis *pdfb;
+ pdfb = BP_TO_P(CDFBasis *, _pdfb);
+
+ olMemTo(EH_Get, pdfWrapped = new(pdfb->GetMalloc())
+ CWrappedDocFile(pdfnName, pdfNew->GetLuid(),
+ _df, pdfb, BP_TO_P(CPubDocFile *, _ppubdf)));
+ olChkTo(EH_pdfWrapped, pdfWrapped->Init(pdfNew));
+ _ppubdf->AddXSMember(this, pdfWrapped, pdfWrapped->GetLuid());
+ *ppdfDocFile = pdfWrapped;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::GetDocFile => %p\n",
+ *ppdfDocFile));
+ return S_OK;
+
+EH_pdfWrapped:
+ delete pdfWrapped;
+EH_Get:
+ pdfNew->Release();
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::IsEntry, public
+//
+// Synopsis: Determines whether the given object is in the DocFile
+// or not
+//
+// Arguments: [pdfnName] - Object name
+// [peb] - Entry buffer to fill in
+//
+// Returns: Appropriate error code
+//
+// Modifies: [peb]
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_IsEntry) // Wrapdf_TEXT
+#endif
+
+SCODE CWrappedDocFile::IsEntry(CDfName const *pdfnName,
+ SEntryBuffer *peb)
+{
+ CUpdate *pud;
+ SCODE sc = S_OK;
+ UlIsEntry uie;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::IsEntry(%ws, %p)\n",
+ pdfnName, peb));
+
+ // Look in XSM's (for open/created things)
+
+ PTSetMember *ptsm;
+ if ((ptsm = _ppubdf->FindXSMember(pdfnName, GetName())) != NULL)
+ {
+ peb->luid = ptsm->GetName();
+ peb->dwType = ptsm->ObjectType();
+ }
+ else
+ {
+ uie = _ulChanged.IsEntry(pdfnName, &pud);
+ if (uie == UIE_CURRENT)
+ {
+ peb->luid = pud->GetLUID();
+ peb->dwType = pud->GetFlags() & ULF_TYPEFLAGS;
+ }
+ else if (uie == UIE_ORIGINAL || _pdfBase == NULL)
+ {
+ sc = STG_E_FILENOTFOUND;
+ }
+ else
+ {
+ sc = _pdfBase->IsEntry(pdfnName, peb);
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::IsEntry => %lu, %lu, %lu\n",
+ sc, peb->luid, peb->dwType));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::RenameEntry, public
+//
+// Synopsis: Renames an element of the DocFile
+//
+// Arguments: [pdfnName] - Current name
+// [pdfnNewName] - New name
+//
+// Returns: Appropriate error code
+//
+// History: 09-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_RenameEntry) // Wrapdf_Rename_TEXT
+#endif
+
+SCODE CWrappedDocFile::RenameEntry(CDfName const *pdfnName,
+ CDfName const *pdfnNewName)
+{
+ SCODE sc;
+ SEntryBuffer eb;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::RenameEntry(%ws, %ws)\n",
+ pdfnName, pdfnNewName));
+
+ olAssert(P_TRANSACTED(_df));
+
+ if (SUCCEEDED(sc = IsEntry(pdfnNewName, &eb)))
+ olErr(EH_Err, STG_E_ACCESSDENIED)
+ else if (sc != STG_E_FILENOTFOUND)
+ olErr(EH_Err, sc);
+
+ olChk(IsEntry(pdfnName, &eb));
+ olMem(_ulChanged.Add(_pdfb->GetMalloc(),
+ pdfnNewName, pdfnName, eb.luid, eb.dwType, NULL));
+
+ _ppubdf->RenameChild(pdfnName, GetName(), pdfnNewName);
+
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::RenameEntry\n"));
+ return S_OK;
+
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::DestroyEntry, public
+//
+// Synopsis: Permanently destroys a child
+//
+// Arguments: [pdfnName] - Name
+// [fClean] - If true, remove create entry from update list
+// rather than appending a delete update entry
+//
+// Returns: Appropriate error code
+//
+// History: 09-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_DestroyEntry) // Wrapdf_Destroy_TEXT
+#endif
+
+SCODE CWrappedDocFile::DestroyEntry(CDfName const *pdfnName,
+ BOOL fClean)
+{
+ SCODE sc;
+ SEntryBuffer eb;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::DestroyEntry:%p(%ws, %d)\n",
+ this, pdfnName, fClean));
+
+ olAssert(P_TRANSACTED(_df));
+
+ if (fClean)
+ {
+ CUpdate *pud;
+ UlIsEntry uie;
+
+ uie = _ulChanged.IsEntry(pdfnName, &pud);
+ olAssert(uie == UIE_CURRENT);
+ RevertUpdate(pud);
+ _ulChanged.Delete(pud);
+ }
+ else
+ {
+ PTSetMember *ptsm;
+
+ olChk(IsEntry(pdfnName, &eb));
+ olMem(_ulChanged.Add(_pdfb->GetMalloc(),
+ NULL, pdfnName, eb.luid, eb.dwType, NULL));
+
+ if ((ptsm = _ppubdf->FindXSMember(pdfnName, GetName())) != NULL)
+ {
+ olAssert(ptsm->GetName() != DF_NOLUID &&
+ aMsg("Can't destroy NOLUID XSM"));
+ _ppubdf->DestroyChild(ptsm->GetName());
+ }
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::DestroyEntry\n"));
+ return S_OK;
+
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+// History: 08-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_AddRef) // Wrapdf_TEXT
+#endif
+
+void CWrappedDocFile::AddRef(void)
+{
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile %p::AddRef()\n", this));
+ AtomicInc(&_cReferences);
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::AddRef, %lu\n",
+ _cReferences));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::Release, public
+//
+// Synopsis: TL requests resource release for a child
+//
+// Returns: Appropriate status code
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_Release) // Wrapdf_Release_TEXT
+#endif
+
+void CWrappedDocFile::Release(void)
+{
+ LONG lRet;
+
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::Release()\n"));
+ olAssert(_cReferences > 0);
+ lRet = AtomicDec(&_cReferences);
+ if (lRet == 0)
+ delete this;
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::Release\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::GetTime, public
+//
+// Synopsis: Gets a time
+//
+// Arguments: [wt] - Which time
+// [ptm] - Time return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ptm]
+//
+// History: 31-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_GetTime) // Wrapdf_TEXT
+#endif
+
+SCODE CWrappedDocFile::GetTime(WHICHTIME wt, TIME_T *ptm)
+{
+ _tten.GetTime(wt, ptm);
+ return S_OK;
+}
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::GetAllTimes, public
+//
+// Synopsis: Gets all times
+//
+// Arguments: [patm] - Access Time
+// [pmtm] - Modification Time
+// [pctm] - Creation Time
+//
+// Returns: Appropriate status code
+//
+// Modifies: [atm], [mtm], [ctm]
+//
+// History: 26-May-95 SusiA Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_GetAllTimes) // Wrapdf_TEXT
+#endif
+
+SCODE CWrappedDocFile::GetAllTimes(TIME_T *patm, TIME_T *pmtm, TIME_T *pctm)
+{
+ _tten.GetAllTimes(patm, pmtm, pctm);
+ return S_OK;
+}
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::SetAllTimes, public
+//
+// Synopsis: Sets all time values
+//
+// Arguments: [atm] - Access Time
+// [mtm] - Modification Time
+// [ctm] - Creation Time
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 22-Nov-95 SusiA Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_SetAllTimes)
+#endif
+
+SCODE CWrappedDocFile::SetAllTimes(TIME_T atm, TIME_T mtm, TIME_T ctm)
+{
+ SetDirty((1 << WT_CREATION) | (1 << WT_MODIFICATION) |(1 << WT_ACCESS));
+ _tten.SetAllTimes(atm, mtm, ctm);
+ return S_OK;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::SetTime, public
+//
+// Synopsis: Sets a time
+//
+// Arguments: [wt] - Which time
+// [tm] - New time
+//
+// Returns: Appropriate status code
+//
+// History: 31-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_SetTime)
+#endif
+
+SCODE CWrappedDocFile::SetTime(WHICHTIME wt, TIME_T tm)
+{
+ olAssert((1 << WT_CREATION) == DIRTY_CREATETIME);
+ olAssert((1 << WT_MODIFICATION) == DIRTY_MODIFYTIME);
+ olAssert((1 << WT_ACCESS) == DIRTY_ACCESSTIME);
+ SetDirty(1 << wt);
+ _tten.SetTime(wt, tm);
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::GetClass, public
+//
+// Synopsis: Gets the class ID
+//
+// Arguments: [pclsid] - Class ID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pclsid]
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_GetClass)
+#endif
+
+SCODE CWrappedDocFile::GetClass(CLSID *pclsid)
+{
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::GetClass:%p(%p)\n",
+ this, pclsid));
+ *pclsid = _clsid;
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::GetClass\n"));
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::SetClass, public
+//
+// Synopsis: Sets the class ID
+//
+// Arguments: [clsid] - New class ID
+//
+// Returns: Appropriate status code
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_SetClass)
+#endif
+
+SCODE CWrappedDocFile::SetClass(REFCLSID clsid)
+{
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::SetClass:%p(?)\n", this));
+ _clsid = clsid;
+ SetDirty(DIRTY_CLASS);
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::SetClass\n"));
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::GetStateBits, public
+//
+// Synopsis: Gets the state bits
+//
+// Arguments: [pgrfStateBits] - State bits return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pgrfStateBits]
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_GetStateBits)
+#endif
+
+SCODE CWrappedDocFile::GetStateBits(DWORD *pgrfStateBits)
+{
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::GetStateBits:%p(%p)\n",
+ this, pgrfStateBits));
+ *pgrfStateBits = _grfStateBits;
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::GetStateBits\n"));
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::SetStateBits, public
+//
+// Synopsis: Sets the state bits
+//
+// Arguments: [grfStateBits] - Bits to set
+// [grfMask] - Mask
+//
+// Returns: Appropriate status code
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_SetStateBits)
+#endif
+
+SCODE CWrappedDocFile::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::SetStateBits:%p("
+ "%lu, %lu)\n", this, grfStateBits, grfMask));
+ _grfStateBits = (_grfStateBits & ~grfMask) | (grfStateBits & grfMask);
+ SetDirty(DIRTY_STATEBITS);
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::SetStateBits\n"));
+ return S_OK;
+}
+
diff --git a/private/ole32/stg/drt/daytona/makefile b/private/ole32/stg/drt/daytona/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ole32/stg/drt/daytona/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/stg/drt/daytona/sources b/private/ole32/stg/drt/daytona/sources
new file mode 100644
index 000000000..c2cb3af4f
--- /dev/null
+++ b/private/ole32/stg/drt/daytona/sources
@@ -0,0 +1,92 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= stgdrt
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= PROGRAM
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES=..\..\..\h;..\..\..\ih;..\..\..\common\daytona;..\..\h;..
+
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+SOURCES= \
+ ..\drt.cxx\
+ ..\tests.cxx\
+ ..\illeg.cxx\
+ ..\util.cxx\
+ ..\wrap.cxx\
+ ..\strlist.cxx\
+ ..\drtguid.cxx\
+ ..\ilb.cxx
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+UMLIBS= \
+ ..\..\common\daytona\obj\*\dfcommon.lib\
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib\
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib\
+ $(BASEDIR)\public\sdk\lib\*\user32.lib\
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib
+
+PRECOMPILED_INCLUDE= ..\headers.cxx
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
diff --git a/private/ole32/stg/drt/depend.mk1 b/private/ole32/stg/drt/depend.mk1
new file mode 100644
index 000000000..9d25f1992
--- /dev/null
+++ b/private/ole32/stg/drt/depend.mk1
@@ -0,0 +1,82 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\drt.obj $(OBJDIR)\drt.lst: .\drt.cxx .\illeg.hxx .\tests.hxx
+
+$(OBJDIR)\tests.obj $(OBJDIR)\tests.lst: .\tests.cxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\ctype.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE)\h\dfmem.hxx \
+ $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx \
+ $(OLE)\h\wchar.h $(OLE2H)\disptype.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\valid.h $(OSINC)\windef.h $(OSINC)\winnt.h .\ilb.hxx \
+ .\tests.hxx
+
+$(OBJDIR)\ilb.obj $(OBJDIR)\ilb.lst: .\ilb.cxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\memory.h \
+ $(CRTINC)\ctype.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE)\drt\ilb.hxx \
+ $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx \
+ $(OLE)\h\ref.hxx $(OLE)\h\wchar.h $(OLE2H)\disptype.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\valid.h $(OSINC)\windef.h \
+ $(OSINC)\winnt.h
+
+$(OBJDIR)\strlist.obj $(OBJDIR)\strlist.lst: .\strlist.cxx \
+ $(CRTINC)\string.h
+
+$(OBJDIR)\illeg.obj $(OBJDIR)\illeg.lst: .\illeg.cxx $(CRTINC)\fcntl.h \
+ $(CRTINC)\io.h $(CRTINC)\sys\stat.h $(CRTINC)\sys\types.h .\illeg.hxx
+
+$(OBJDIR)\util.obj $(OBJDIR)\util.lst: .\util.cxx $(CRTINC)\direct.h \
+ $(CRTINC)\io.h $(CRTINC)\stdarg.h $(OLE)\h\dfdeb.hxx
+
+$(OBJDIR)\wrap.obj $(OBJDIR)\wrap.lst: .\wrap.cxx $(OLE)\h\dfentry.hxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\headers.pxh $(PCHDIR)\$(OBJDIR)\headers.lst: \
+ $(OLE)\drt\headers.cxx $(COMMON)\ih\Base32K.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE)\drt\drt.hxx \
+ $(OLE)\drt\strlist.hxx $(OLE)\drt\util.hxx $(OLE)\drt\wrap.hxx \
+ $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx \
+ $(OLE)\h\ref.hxx $(OLE)\h\wchar.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h \
+ $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h $(OLE2H)\disptype.h \
+ $(OLE2H)\dsbase.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prspec.h $(OLE2H)\querys.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
+.\$(OBJDIR)\drt.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\tests.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\illeg.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\util.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\wrap.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\strlist.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\ilb.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/drt/depend.mk3 b/private/ole32/stg/drt/depend.mk3
new file mode 100644
index 000000000..eaf3195b3
--- /dev/null
+++ b/private/ole32/stg/drt/depend.mk3
@@ -0,0 +1,102 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\drt.obj $(OBJDIR)\drt.lst: .\drt.cxx .\illeg.hxx .\tests.hxx
+
+$(OBJDIR)\tests.obj $(OBJDIR)\tests.lst: .\tests.cxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\ctype.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE)\h\dfmem.hxx \
+ $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx \
+ $(OLE)\h\wchar.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windef.h $(OSINC)\winnt.h .\ilb.hxx \
+ .\tests.hxx
+
+$(OBJDIR)\ilb.obj $(OBJDIR)\ilb.lst: .\ilb.cxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\memory.h \
+ $(CRTINC)\ctype.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE)\drt\ilb.hxx \
+ $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx \
+ $(OLE)\h\ref.hxx $(OLE)\h\wchar.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windef.h \
+ $(OSINC)\winnt.h
+
+$(OBJDIR)\drtguid.obj $(OBJDIR)\drtguid.lst: .\drtguid.cxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\excpt.h $(CRTINC)\ctype.h $(CRTINC)\memory.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE)\drt\drt.hxx $(OLE)\drt\strlist.hxx \
+ $(OLE)\drt\util.hxx $(OLE)\drt\wrap.hxx $(OLE)\h\dfmem.hxx \
+ $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx \
+ $(OLE)\h\wchar.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h \
+ $(OSINC)\windef.h $(OSINC)\winnt.h .\headers.cxx
+
+$(OBJDIR)\strlist.obj $(OBJDIR)\strlist.lst: .\strlist.cxx \
+ $(CRTINC)\string.h
+
+$(OBJDIR)\illeg.obj $(OBJDIR)\illeg.lst: .\illeg.cxx $(CRTINC)\fcntl.h \
+ $(CRTINC)\io.h $(CRTINC)\sys\stat.h $(CRTINC)\sys\types.h .\illeg.hxx
+
+$(OBJDIR)\util.obj $(OBJDIR)\util.lst: .\util.cxx $(CRTINC)\direct.h \
+ $(CRTINC)\io.h $(CRTINC)\stdarg.h $(OLE)\h\dfdeb.hxx
+
+$(OBJDIR)\wrap.obj $(OBJDIR)\wrap.lst: .\wrap.cxx $(OLE)\h\dfentry.hxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\headers.pxh $(PCHDIR)\$(OBJDIR)\headers.lst: \
+ $(OLE)\drt\headers.cxx $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE)\drt\drt.hxx \
+ $(OLE)\drt\strlist.hxx $(OLE)\drt\util.hxx $(OLE)\drt\wrap.hxx \
+ $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx \
+ $(OLE)\h\ref.hxx $(OLE)\h\wchar.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h
+
+.\$(OBJDIR)\drt.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\tests.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\illeg.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\util.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\wrap.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\strlist.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\drtguid.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\ilb.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/drt/depend.mk9 b/private/ole32/stg/drt/depend.mk9
new file mode 100644
index 000000000..66b028f12
--- /dev/null
+++ b/private/ole32/stg/drt/depend.mk9
@@ -0,0 +1,64 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\drt.obj $(OBJDIR)\drt.lst: .\drt.cxx .\illeg.hxx .\tests.hxx
+
+$(OBJDIR)\tests.obj $(OBJDIR)\tests.lst: .\tests.cxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx \
+ $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx $(OLE)\h\wchar.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h .\ilb.hxx \
+ .\tests.hxx
+
+$(OBJDIR)\ilb.obj $(OBJDIR)\ilb.lst: .\ilb.cxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\memory.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx \
+ $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx $(OLE)\h\wchar.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h .\ilb.hxx
+
+$(OBJDIR)\strlist.obj $(OBJDIR)\strlist.lst: .\strlist.cxx \
+ $(CRTINC)\string.h
+
+$(OBJDIR)\illeg.obj $(OBJDIR)\illeg.lst: .\illeg.cxx $(CRTINC)\fcntl.h \
+ $(CRTINC)\io.h $(CRTINC)\sys\stat.h $(CRTINC)\sys\types.h .\illeg.hxx
+
+$(OBJDIR)\util.obj $(OBJDIR)\util.lst: .\util.cxx $(CRTINC)\direct.h \
+ $(CRTINC)\io.h $(CRTINC)\stdarg.h $(OLE)\h\dfdeb.hxx
+
+$(OBJDIR)\wrap.obj $(OBJDIR)\wrap.lst: .\wrap.cxx $(OLE)\h\dfentry.hxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\headers.pxh $(PCHDIR)\$(OBJDIR)\headers.lst: \
+ $(OLE)\drt\headers.cxx $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\winnot.h $(CRTINC)\memory.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx \
+ $(OLE)\h\ref.hxx $(OLE)\h\wchar.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\drt.hxx \
+ .\strlist.hxx .\util.hxx .\wrap.hxx
+
+.\$(OBJDIR)\drt.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\tests.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\illeg.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\util.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\wrap.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\strlist.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\ilb.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/drt/dirs b/private/ole32/stg/drt/dirs
new file mode 100644
index 000000000..4c50c7cc4
--- /dev/null
+++ b/private/ole32/stg/drt/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/stg/drt/drt.cxx b/private/ole32/stg/drt/drt.cxx
new file mode 100644
index 000000000..f5b3a3805
--- /dev/null
+++ b/private/ole32/stg/drt/drt.cxx
@@ -0,0 +1,291 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: drt.cxx
+//
+// Contents: DRT main routine
+//
+// History: 22-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include "tests.hxx"
+#include "illeg.hxx"
+
+// Test flags and type
+typedef ULONG FLAGS;
+
+#define TF_NONE 0x00000000
+
+// Suppression flags
+#define TF_SUPPRESS 0x0000FFFF
+#define TFS_ILLEGITIMATE 0x00000001
+#define TFS_16BIT 0x00000002
+
+// Enabling flags
+#define TF_ENABLE 0xFFFF0000
+#define TFE_DIRECT 0x00010000
+#define TFE_TRANSACTED 0x00020000
+#define TFE_INDEPENDENT 0x00040000
+#define TFE_ANY (TFE_DIRECT | TFE_TRANSACTED | TFE_INDEPENDENT)
+
+// Pointer to a test function
+typedef void (*TestFn)(void);
+
+static struct
+{
+ char *pszName;
+ char *pszDesc;
+ TestFn tfn;
+ FLAGS flags;
+} tests[] =
+{
+ "Create", "Creation",
+ t_create, TFE_ANY,
+ "Open", "Opening",
+ t_open, TFE_ANY,
+ "AddRef", "AddRef/Release",
+ t_addref, TFE_ANY,
+ "TModify", "Transacted modify/Commit/Revert",
+ t_tmodify, TFE_TRANSACTED | TFE_INDEPENDENT,
+ "DModify", "Direct modifications",
+ t_dmodify, TFE_DIRECT,
+ "Stat", "Stat",
+ t_stat, TFE_ANY,
+ "Stream", "Stream operations",
+ t_stream, TFE_ANY,
+ "Enum", "Enumerator operations",
+ t_enum, TFE_ANY,
+ "StgCopyTo", "IStorage::CopyTo",
+ t_stgcopyto, TFE_ANY,
+ "MoveCopy", "IStorage::MoveElementTo",
+ t_movecopy, TFE_ANY,
+ "Marshal", "IMarshal operations",
+ t_marshal, TFE_ANY
+#if WIN32 == 200
+ // No marshalling on Chicago
+ | TFS_16BIT
+#endif
+ ,
+ "ILockBytes", "ILockBytes usage",
+ t_ilb, TFE_ANY,
+ "StgMisc", "Miscellaneous Stg functions",
+ t_stgmisc, TFE_ANY,
+
+ "IllStg", "Illegitimate IStorage calls",
+ i_storage, TFE_ANY | TFS_ILLEGITIMATE,
+ "IllStm", "Illegitimate IStream calls",
+ i_stream, TFE_ANY | TFS_ILLEGITIMATE,
+ "IllEnum", "Illegitimate enumerator calls",
+ i_enum, TFE_ANY | TFS_ILLEGITIMATE
+};
+#define NTESTS (sizeof(tests)/sizeof(tests[0]))
+
+DWORD dwTransacted = 0;
+DWORD dwRootDenyWrite = STGM_SHARE_DENY_WRITE;
+BOOL fVerbose = FALSE;
+OLECHAR atcDrtDocfile[_MAX_PATH];
+
+static BOOL fRun[NTESTS];
+#ifdef FLAT
+static FLAGS flTests = TF_NONE;
+#else
+static FLAGS flTests = TF_NONE | TFS_16BIT;
+#endif
+
+static void Initialize(void)
+{
+ SCODE sc;
+
+ SetData();
+#if WIN32 == 300
+ if (FAILED(sc = DfGetScode(CoInitializeEx(NULL, COINIT_MULTITHREADED))))
+ error(EXIT_UNKNOWN,
+ "CoInitializeEx failed with sc = 0x%lX\n", sc);
+#else
+ if (FAILED(sc = DfGetScode(CoInitialize(NULL))))
+ error(EXIT_UNKNOWN,
+ "CoInitialize failed with sc = 0x%lX\n", sc);
+#endif
+}
+
+static void Uninitialize(void)
+{
+ UnsetData();
+ CoUninitialize();
+}
+
+static int FindTest(char *pszName)
+{
+ int i, cchName;
+
+ cchName = strlen(pszName);
+ for (i = 0; i<NTESTS; i++)
+ if (!_strnicmp(pszName, tests[i].pszName, cchName))
+ return i;
+ return -1;
+}
+
+static void RunTests(void)
+{
+ int i;
+
+ for (i = 0; i<NTESTS; i++)
+ // For a test to run:
+ // 1) fRun[test] must be TRUE
+ // 2) No suppression flags can be set that are not set in flTests
+ // 3) At least one enabling flag must be set that is set in flTests
+ if (fRun[i] &&
+ (tests[i].flags & ~flTests & TF_SUPPRESS) == 0 &&
+ (tests[i].flags & flTests & TF_ENABLE) != 0)
+ {
+ out("\n----- Test #%2d - %s -----\n", i+1, tests[i].pszDesc);
+ tests[i].tfn();
+ CheckMemory();
+ CleanData();
+ }
+}
+
+static void Usage(void)
+{
+ int i;
+
+ printf("Usage: drt [options]\n");
+ printf("Options are:\n");
+ printf(" -h - This message\n");
+ printf(" -d - Suppress direct tests\n");
+ printf(" -t - Suppress transacted tests\n");
+ printf(" -w - Suppress independent tests\n");
+ printf(" -i - Enable illegitimate tests\n");
+ printf(" -v - Display test output\n");
+ printf(" -y<kind> - Control debug output (a, d, m, i, M, L)\n");
+ printf(" -#[+|-]<number> - Turn test <number> on (+) or off (-)\n");
+ printf(" No number means all\n");
+ printf(" -n[+|-]<prefix> - Turn test <prefix> on or off\n");
+ printf(" -N<file> - Set file to use for tests\n");
+ printf("Prefix can be any prefix of:\n");
+ for (i = 0; i<NTESTS; i++)
+ printf(" %s\n", tests[i].pszName);
+ exit(1);
+}
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ int i, iTest;
+ BOOL fDirect = TRUE, fTrans = TRUE, fIndep = TRUE;
+
+ SetDebug(0x101, 0x101);
+ for (i = 0; i<NTESTS; i++)
+ fRun[i] = TRUE;
+ ATOOLE("drt.dfl", atcDrtDocfile, _MAX_PATH);
+ while (--argc>0)
+ {
+ if (**++argv == '-')
+ {
+ switch(argv[0][1])
+ {
+ case '#':
+ if (sscanf(argv[0]+3, "%d", &iTest) != 1)
+ iTest = -1;
+ else
+ iTest--;
+ for (i = 0; i<NTESTS; i++)
+ if (iTest == -1 || iTest == i)
+ fRun[i] = argv[0][2] == '+';
+ break;
+ case 'd':
+ fDirect = FALSE;
+ break;
+ case 'i':
+ flTests |= TFS_ILLEGITIMATE;
+ break;
+ case 'n':
+ iTest = FindTest(argv[0]+3);
+ if (iTest >= 0)
+ fRun[iTest] = argv[0][2] == '+';
+ break;
+ case 'N':
+ ATOOLE(argv[0]+2, atcDrtDocfile, _MAX_PATH);
+ break;
+ case 't':
+ fTrans = FALSE;
+ break;
+ case 'v':
+ fVerbose = TRUE;
+ break;
+ case 'w':
+ fIndep = FALSE;
+ break;
+ case 'y':
+ switch(argv[0][2])
+ {
+ case 'a':
+ SetDebug(0xffffffff, 0xffffffff);
+ break;
+ case 'd':
+ SetDebug(0xffffffff, 0x101);
+ break;
+ case 'm':
+ SetDebug(0x101, 0xffffffff);
+ break;
+ case 'i':
+ SetDebug(0x101, 0x101);
+ break;
+ case 'M':
+ SetDebug(0x01100000, 0);
+ break;
+ case 'L':
+ SetDebug(0x00100000, 0);
+ break;
+ }
+ break;
+ case 'h':
+ default:
+ Usage();
+ }
+ }
+ else
+ Usage();
+ }
+
+ Initialize();
+
+ if (fDirect)
+ {
+ out("\n---------- Direct ----------\n");
+ dwTransacted = 0;
+ dwRootDenyWrite = STGM_SHARE_EXCLUSIVE;
+ flTests |= TFE_DIRECT;
+ RunTests();
+ flTests &= ~TFE_DIRECT;
+ }
+
+ if (fTrans)
+ {
+ out("\n---------- Transacted ----------\n");
+ dwTransacted = STGM_TRANSACTED;
+ dwRootDenyWrite = STGM_SHARE_DENY_WRITE;
+ flTests |= TFE_TRANSACTED;
+ RunTests();
+ flTests &= ~TFE_TRANSACTED;
+ }
+
+ if (fIndep)
+ {
+ out("\n---------- Independent ----------\n");
+ dwTransacted = STGM_TRANSACTED;
+ dwRootDenyWrite = STGM_SHARE_DENY_NONE;
+ flTests |= TFE_INDEPENDENT;
+ RunTests();
+ flTests &= ~TFE_INDEPENDENT;
+ }
+
+ printf("Docfile DRT - PASSED\n");
+
+ Uninitialize();
+}
diff --git a/private/ole32/stg/drt/drt.def b/private/ole32/stg/drt/drt.def
new file mode 100644
index 000000000..97b2c0aa5
--- /dev/null
+++ b/private/ole32/stg/drt/drt.def
@@ -0,0 +1,19 @@
+#ifndef FLAT
+EXETYPE WINDOWS
+//STUB 'WINSTUB.EXE'
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 16384
+STACKSIZE 8192
+#else
+EXETYPE NT
+SUBSYSTEM WINDOWSCHAR
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 16384
+STACKSIZE 8192
+#endif
diff --git a/private/ole32/stg/drt/drt.hxx b/private/ole32/stg/drt/drt.hxx
new file mode 100644
index 000000000..2a3bcee4c
--- /dev/null
+++ b/private/ole32/stg/drt/drt.hxx
@@ -0,0 +1,103 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: drt.hxx
+//
+// Contents: DRT header
+//
+// History: 22-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __DRT_HXX__
+#define __DRT_HXX__
+
+#include <dfmsp.hxx>
+
+// Exit codes
+#define EXIT_BADSC 1
+#define EXIT_OOM 2
+#define EXIT_UNKNOWN 3
+
+#define STR(x) OLESTR(x)
+
+#ifdef UNICODE
+#ifndef ATOT
+#define ATOT(psz, ptcs, max) mbstowcs(ptcs, psz, max)
+#endif
+#ifndef TTOA
+#define TTOA(ptcs, psz, max) wcstombs(psz, ptcs, max)
+#endif
+#else
+#ifndef ATOT
+#define ATOT(psz, ptcs) strcpy(ptcs, psz)
+#endif
+#ifndef TTOA
+#define TTOA(ptcs, psz) strcpy(psz, ptcs)
+#endif
+#endif
+
+#ifdef OLEWIDECHAR
+
+//typedef WCHAR TCHAR;
+
+#ifndef ATOOLE
+#define ATOOLE(psz, ptcs, max) mbstowcs(ptcs, psz, max)
+#endif
+#ifndef OLETOA
+i#define OLETOA(ptcs, psz, max) wcstombs(psz, ptcs, max)
+#endif
+
+#ifndef olecscmp
+#define olecscmp wcscmp
+#endif
+#ifndef olecscpy
+#define olecscpy wcscpy
+#endif
+#ifndef olecslen
+#define olecslen wcslen
+#endif
+#ifndef olecsprintf
+#define olecsprintf swprintf
+#endif
+
+#else
+
+typedef char TCHAR;
+
+#ifndef ATOOLE
+#define ATOOLE(psz, ptcs) strcpy(ptcs, psz)
+#endif
+#ifndef OLETOA
+#define OLETOA(ptcs, psz) strcpy(psz, ptcs)
+#endif
+
+#ifndef olecscmp
+#define olecscmp strcmp
+#endif
+#ifndef olecscpy
+#define olecscpy strcpy
+#endif
+#ifndef olecslen
+#define olecslen strlen
+#endif
+#ifndef olecsprintf
+#define olecsprintf sprintf
+#endif
+
+#endif
+
+#define DRTDF atcDrtDocfile
+#define MARSHALDF STR("dup.dfl")
+
+#define ROOTP(x) ((x) | dwTransacted | dwRootDenyWrite)
+#define STGP(x) ((x) | dwTransacted | STGM_SHARE_EXCLUSIVE)
+#define STMP(x) ((x) | STGM_SHARE_EXCLUSIVE)
+
+extern DWORD dwTransacted, dwRootDenyWrite;
+extern BOOL fVerbose;
+extern OLECHAR atcDrtDocfile[];
+
+#endif // #ifndef __DRT_HXX__
diff --git a/private/ole32/stg/drt/drtguid.cxx b/private/ole32/stg/drt/drtguid.cxx
new file mode 100644
index 000000000..8e3f3f966
--- /dev/null
+++ b/private/ole32/stg/drt/drtguid.cxx
@@ -0,0 +1,25 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: drtguid.cxx
+//
+// Contents: Define GUIDs needed by the DRT
+//
+// History: 04-Nov-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <initguid.h>
+
+#if WIN32 == 100 || WIN32 == 200
+DEFINE_GUID(GUID_NULL, 0L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+DEFINE_OLEGUID(IID_ILockBytes, 0x0000000aL, 0, 0);
+DEFINE_OLEGUID(IID_IStorage, 0x0000000bL, 0, 0);
+DEFINE_OLEGUID(IID_IStream, 0x0000000cL, 0, 0);
+#endif
diff --git a/private/ole32/stg/drt/filelist.mk b/private/ole32/stg/drt/filelist.mk
new file mode 100644
index 000000000..837d3b938
--- /dev/null
+++ b/private/ole32/stg/drt/filelist.mk
@@ -0,0 +1,101 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+#
+# Set up include directories and roots for includes.exe
+#
+
+CINC = -I$(OLE2H) $(CINC) -I$(OLE)\h
+INCLUDES_ROOTS = -P$$(OLE2H)=$(OLE2H) -P$$(OLE)=$(OLE)
+
+#
+# Default OLE2 paths
+#
+
+!include $(OLE)\setole2.mk
+
+#
+# Defining NO_WINMAIN suppresses linking with astartw.obj
+#
+
+NO_WINMAIN = 1
+
+#
+# Copy built exes to this directory
+#
+
+!ifdef OLETARGET
+EXECOPY = $(OLETARGET)\$(OBJDIR)
+!endif
+
+#
+# Define libraries
+#
+
+!if "$(PLATFORM)" == "i286"
+DFLIB = $(OLE)\$(OBJDIR)\storage.lib
+!else if "$(PLATFORM)" == "NT"
+# Cairo
+DFLIB = $(COMMON)\ilib\$(OBJDIR)\storag32.lib
+!else
+DFLIB = $(CAIROLE)\ilib\$(OBJDIR)\storag32.lib
+!endif
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = stgdrt.exe
+TARGET_DESCRIPTION = "STORAGE.DLL Developer Regression Test"
+RELEASE =
+
+#
+# C compiler flags
+#
+
+CFLAGS = $(CFLAGS) -DUL64
+
+!if "$(PLATFORM)" == "i286"
+CFLAGS = $(CFLAGS) -GEd -GA
+!endif
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES = \
+ .\drt.cxx\
+ .\tests.cxx\
+ .\illeg.cxx\
+ .\util.cxx\
+ .\wrap.cxx\
+ .\strlist.cxx\
+!if ("$(PLATFORM)" == "i386" && "$(OPSYS)" == "DOS") || \
+ "$(OPSYS)" == "NT1X"
+ .\drtguid.cxx\
+!endif
+ .\ilb.cxx
+
+!if "$(PLATFORM)" != "MAC"
+PXXFILE = .\headers.cxx
+!endif
+
+#
+# Libraries and other object files to link.
+#
+
+!include $(OLE)\dflibs.mk
+
+LIBS = $(DFLIB) $(LIBS) $(RTLIBEXEQ)
+
+#
+# Set MULTIDEPEND to support multiple build targets
+#
+
+MULTIDEPEND = MERGED
diff --git a/private/ole32/stg/drt/headers.cxx b/private/ole32/stg/drt/headers.cxx
new file mode 100644
index 000000000..9cef4689f
--- /dev/null
+++ b/private/ole32/stg/drt/headers.cxx
@@ -0,0 +1,35 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: headers.cxx
+//
+// Contents: Precompiled headers
+//
+// History: 05-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#if defined(WIN32) && WIN32 != 300
+// 32-bit non-Cairo hack - windows.h includes ole.h which is incompatible
+// with ole2.h, as well as rpc.h which is incompatible with compobj.h
+#define _INC_OLE
+#define __RPC_H__
+#endif
+
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <windows.h>
+#if WIN32 != 300
+#include <storage.h>
+#endif
+
+#include <debnot.h>
+
+#include <drt.hxx>
+#include <wrap.hxx>
+#include <util.hxx>
+#include <strlist.hxx>
diff --git a/private/ole32/stg/drt/ilb.cxx b/private/ole32/stg/drt/ilb.cxx
new file mode 100644
index 000000000..805009f81
--- /dev/null
+++ b/private/ole32/stg/drt/ilb.cxx
@@ -0,0 +1,422 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: ilbmem.cx
+//
+// Contents: ILockBytes memory implementation
+//
+// Classes: CMapBytes
+//
+// History: 06-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <memory.h>
+#include <ilb.hxx>
+
+#if DBG == 1
+
+DECLARE_INFOLEVEL(ol);
+
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapBytes::CMapBytes, public
+//
+// Synopsis: constructor
+//
+// Effects: initialize member variables
+//
+// Derivation: ILockBytes
+//
+// History: 06-Nov-92 AlexT Created
+//
+// Notes: Returns a fully initialized CMapBytes (ref count == 1)
+//
+//--------------------------------------------------------------------------
+
+CMapBytes::CMapBytes(void)
+{
+ _ulSize = 0;
+ _pv = 0;
+
+ _ulRef = 1;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapBytes::QueryInterface, public
+//
+// Arguments: [riid] - interface id
+// [ppvObj] - place holder for interface
+//
+// Returns: Always fails
+//
+// Derivation: ILockBytes
+//
+// History: 06-Nov-92 AlexT Created
+//
+// Notes: Not used in tests
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMapBytes::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
+{
+ *ppvObj = NULL;
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapBytes::AddRef, public
+//
+// Synopsis: add reference
+//
+// Returns: post reference count
+//
+// Derivation: ILockBytes
+//
+// History: 06-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CMapBytes::AddRef(void)
+{
+ AtomicInc(&_ulRef);
+ return(_ulRef);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapBytes::Release, public
+//
+// Synopsis: release reference
+//
+// Effects: deletes object when reference count reaches zero
+//
+// Returns: post reference count
+//
+// Derivation: ILockBytes
+//
+// History: 06-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CMapBytes::Release(void)
+{
+ AtomicDec(&_ulRef);
+
+ if (_ulRef > 0)
+ return(_ulRef);
+
+ free(_pv);
+
+ delete this;
+
+ return(0);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapBytes::ReadAt
+//
+// Synopsis: Reads bytes from memory
+//
+// Arguments: [ulOffset] - byte offset
+// [pv] - input buffer
+// [cb] - count of bytes to read
+// [pcbRead] - count of bytes read
+//
+// Returns: SCODE
+//
+// Modifies: pv, pcbRead
+//
+// Derivation: ILockBytes
+//
+// History: 30-Oct-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMapBytes::ReadAt(ULARGE_INTEGER uliOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbRead)
+{
+ olAssert(ULIGetHigh(uliOffset) == 0);
+
+ ULONG ulOffset = ULIGetLow(uliOffset);
+ if (ulOffset >= _ulSize)
+ {
+ // truncate read
+ cb = 0;
+ }
+ else if (cb > (_ulSize - ulOffset))
+ {
+ // truncate range that exceeds size
+ cb = _ulSize - ulOffset;
+ }
+
+ memcpy(pv, (void*)(((BYTE*)_pv) + ulOffset), (size_t) cb);
+ *pcbRead = cb;
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapBytes::WriteAt, public
+//
+// Synopsis: Writes bytes to memory
+//
+// Effects: May change memory size
+//
+// Arguments: [uliOffset] - byte offset
+// [pv] - output buffer
+// [cb] - count of bytes to write
+// [pcbWritten] - count of bytes written
+//
+// Returns: SCODE
+//
+// Modifies: pcbWritten
+//
+// Derivation: ILockBytes
+//
+// History: 06-Nov-92 AlexT Created
+//
+// Notes: This implementation doesn't write partial buffers.
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMapBytes::WriteAt(ULARGE_INTEGER uliOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten)
+{
+ olAssert(ULIGetHigh(uliOffset) == 0);
+
+ ULONG ulOffset = ULIGetLow(uliOffset);
+ HRESULT hr;
+
+ if (ulOffset + cb > _ulSize)
+ {
+ // increase memory buffer to accomodate write
+
+ ULARGE_INTEGER uliSize;
+
+ ULISetHigh(uliSize, 0);
+ ULISetLow(uliSize, ulOffset + cb);
+ hr = SetSize(uliSize);
+
+ if (FAILED(DfGetScode(hr)))
+ {
+ // don't bother writing partial buffers
+
+ *pcbWritten = 0;
+ return hr;
+ }
+ }
+
+ memcpy((void *)(((BYTE*)_pv) + ulOffset), pv, (size_t) cb);
+ *pcbWritten = cb;
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapBytes::Flush, public
+//
+// Synopsis: flushes memory - not appropriate for this implementation
+//
+// Effects: none
+//
+// Returns: SUCCESS_SUCCESS
+//
+// Derivation: ILockBytes
+//
+// History: 06-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMapBytes::Flush(void)
+{
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapBytes::GetSize, public
+//
+// Synopsis: gets memory buffer size
+//
+// Arguments: [pcb] - size place holder
+//
+// Returns: SUCCESS_SUCCESS
+//
+// Modifies: pcb
+//
+// Derivation: ILockBytes
+//
+// History: 06-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMapBytes::GetSize(ULARGE_INTEGER FAR *pcb)
+{
+ ULISetHigh(*pcb, 0);
+ ULISetLow(*pcb, _ulSize);
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapBytes::SetSize, public
+//
+// Synopsis: sets memory buffer size
+//
+// Effects: may change buffer size
+//
+// Arguments: [ulicb] - new memory size
+//
+// Returns: SCODE
+//
+// Derivation: ILockBytes
+//
+// Algorithm: realloc the buffer
+//
+// History: 06-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMapBytes::SetSize(ULARGE_INTEGER ulicb)
+{
+ olAssert(ULIGetHigh(ulicb) == 0);
+
+ ULONG cb = ULIGetLow(ulicb);
+
+ if (cb == _ulSize)
+ return NOERROR;
+
+ void *pv = realloc(_pv, (size_t) cb);
+
+ if ((cb > 0) && (pv == NULL))
+ {
+ // Unable to allocate memory
+ // Leave current memory and size alone
+
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ _pv = pv;
+ _ulSize = cb;
+
+ return NOERROR;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapBytes::LockRegion, public
+//
+// Synopsis: not supported (intentionally)
+//
+// Effects: asserts if called
+//
+// Arguments: [libOffset] - lock range offset
+// [cb] - lock range size
+// [dwLockType] - lock type
+//
+// Returns: STG_E_INVALIDFUNCTION
+//
+// Derivation: ILockBytes
+//
+// History: 06-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMapBytes::LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ olAssert(0 && "Can't lock CMapBytes");
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapBytes::UnLockRegion, public
+//
+// Synopsis: not supported (intentionally)
+//
+// Effects: asserts if called
+//
+// Arguments: [libOffset] - lock range offset
+// [cb] - lock range size
+// [dwLockType] - lock type
+//
+// Returns: STG_E_INVALIDFUNCTION
+//
+// Derivation: ILockBytes
+//
+// History: 06-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMapBytes::UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ olAssert(0 && "Can't unlock CMapBytes");
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMapBytes::Stat, public
+//
+// Synopsis: Provide instance information
+//
+// Arguments: [pstatstg] - status buffer
+// [grfStatFlag] - status flags
+//
+// Returns: SCODE
+//
+// Modifies: pstatstg
+//
+// Derivation: ILockBytes
+//
+// History: 06-Nov-92 AlexT Created
+//
+// Notes: No time stamps
+//
+//--------------------------------------------------------------------------
+
+STDMETHODIMP CMapBytes::Stat(STATSTG FAR *pstatstg, DWORD grfStatFlag)
+{
+ memset(pstatstg, 0, sizeof(STATSTG));
+
+ if ((grfStatFlag & STATFLAG_NONAME) == 0)
+ {
+ static char const abName[] = "Memory";
+
+ HRESULT hr;
+
+ if (FAILED(DfGetScode(hr = drtMemAlloc(sizeof(abName),
+ (void **) &pstatstg->pwcsName))))
+ return hr;
+
+ memcpy(pstatstg->pwcsName, abName, sizeof(abName));
+ }
+
+ pstatstg->type = STGTY_LOCKBYTES;
+
+ ULISetHigh(pstatstg->cbSize, 0);
+ ULISetLow(pstatstg->cbSize, _ulSize);
+
+ pstatstg->grfMode = STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE;
+
+ return NOERROR;
+}
diff --git a/private/ole32/stg/drt/ilb.hxx b/private/ole32/stg/drt/ilb.hxx
new file mode 100644
index 000000000..c04580c6d
--- /dev/null
+++ b/private/ole32/stg/drt/ilb.hxx
@@ -0,0 +1,69 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: ilbmem.hxx
+//
+// Contents: ILockBytes memory implementation
+//
+// Classes: CMapBytes
+//
+// History: 30-Oct-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __ILB_HXX__
+
+#include <dfmsp.hxx> // Pick up UL64 support
+
+#if DBG == 1
+
+DECLARE_DEBUG(ol);
+
+#define olDebugOut(parms) olInlineDebugOut parms
+#define olAssert(exp) Win4Assert(exp)
+
+#else // DBG != 1
+
+#define olDebugOut(parms)
+#define olAssert(exp)
+
+#endif // DBG == 1
+
+class CMapBytes : public ILockBytes
+{
+public:
+ CMapBytes(void);
+
+ STDMETHOD(QueryInterface) (REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (void);
+ STDMETHOD_(ULONG,Release) (void);
+
+ STDMETHOD(ReadAt) (ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbRead);
+ STDMETHOD(WriteAt) (ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten);
+ STDMETHOD(Flush) (void);
+ STDMETHOD(GetSize) (ULARGE_INTEGER FAR *pcb);
+ STDMETHOD(SetSize) (ULARGE_INTEGER cb);
+ STDMETHOD(LockRegion) (ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion) (ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+
+ STDMETHOD(Stat) (STATSTG FAR *pstatstg, DWORD grfStatFlag);
+
+private:
+ LONG _ulRef; // reference count
+ ULONG _ulSize; // memory map size
+ void FAR *_pv; // memory map
+};
+
+#endif // #ifndef __ILB_HXX__
diff --git a/private/ole32/stg/drt/illeg.cxx b/private/ole32/stg/drt/illeg.cxx
new file mode 100644
index 000000000..44768ef12
--- /dev/null
+++ b/private/ole32/stg/drt/illeg.cxx
@@ -0,0 +1,145 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: illeg.cxx
+//
+// Contents: Illegitimate tests
+//
+// History: 17-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <io.h>
+#include <fcntl.h>
+#include <sys\types.h>
+#include <sys\stat.h>
+
+#include "illeg.hxx"
+
+void i_storage(void)
+{
+ WStorage *pwstg;
+ IStorage *pstg, *pstg2;
+ IStream *pstm;
+
+ IllResult("StgCreateDocfile with NULL ppstg",
+ StgCreateDocfile(NULL, 0, 0, NULL));
+ IllResult("StgCreateDocfile with non-zero reserved",
+ StgCreateDocfile(NULL, 0, 1, &pstg));
+ IllResult("StgCreateDocfile with illegal permissions",
+ StgCreateDocfile(NULL, 0, 0, &pstg));
+
+ int fd;
+ fd = _creat(OlecsOut(DRTDF), _S_IREAD);
+ if (fd<0)
+ error(EXIT_BADSC, "Unable to create file '%s'\n", OlecsOut(DRTDF));
+ _close(fd);
+ IllResult("StgCreateDocfile with STGM_WRITE over read-only file",
+ StgCreateDocfile(DRTDF, ROOTP(STGM_READWRITE), 0, &pstg));
+ _chmod(OlecsOut(DRTDF), _S_IREAD | _S_IWRITE);
+
+ IllResult("StgOpenStorage with NULL ppstg",
+ StgOpenStorage(NULL, NULL, 0, NULL, 0, NULL));
+ IllResult("StgOpenStorage with NULL name",
+ StgOpenStorage(NULL, NULL, 0, NULL, 0, &pstg));
+ IllResult("StgOpenStorage with illegal permissions",
+ StgOpenStorage(DRTDF, NULL, 0xffffffff, NULL, 0, &pstg));
+ IllResult("StgOpenStorage with non-zero reserved",
+ StgOpenStorage(DRTDF, NULL, ROOTP(STGM_READWRITE), NULL,
+ 1, &pstg));
+#if WIN32 != 300
+ // This will work on Cairo because it will open a file storage
+ IllResult("StgOpenStorage on non-docfile",
+ StgOpenStorage(DRTDF, NULL, ROOTP(STGM_READWRITE), NULL,
+ 0, &pstg));
+#endif
+
+ WStgCreateDocfile(DRTDF, ROOTP(STGM_READWRITE) | STGM_CREATE, 0, &pwstg);
+ pstg = pwstg->GetI();
+ IllResult("OpenStream that doesn't exist",
+ pstg->OpenStream(STR("NoName"), 0, STMP(STGM_READWRITE),
+ 0, &pstm));
+ IllResult("OpenStorage that doesn't exist",
+ pstg->OpenStorage(STR("NoName"), NULL, STGP(STGM_READWRITE),
+ NULL, 0, &pstg2));
+ pwstg->Unwrap();
+}
+
+#define STREAMSIZE 128
+
+void i_stream(void)
+{
+ WStorage *pwstg;
+ WStream *pwstm;
+ IStream *pstm;
+ BYTE bBuffer[STREAMSIZE];
+ ULONG cbRead;
+ LARGE_INTEGER liSeek;
+ ULARGE_INTEGER uliPos;
+ ULARGE_INTEGER uliSize;
+ ULARGE_INTEGER cb;
+
+ WStgCreateDocfile(DRTDF, ROOTP(STGM_READWRITE), 0, &pwstg);
+ pwstg->CreateStream(STR("Stream"), STMP(STGM_READ), 0, 0, &pwstm);
+ pstm = pwstm->GetI();
+
+ IllResult("Read with NULL buffer",
+ pstm->Read(NULL, STREAMSIZE, NULL));
+ fExitOnFail = FALSE;
+ pwstm->Read(bBuffer, STREAMSIZE, &cbRead);
+ fExitOnFail = TRUE;
+ if (cbRead != 0)
+ error(EXIT_BADSC, "Read %lu bytes on zero-length stream\n", cbRead);
+
+ IllResult("Write with NULL buffer",
+ pstm->Write(NULL, STREAMSIZE, NULL));
+ IllResult("Write on read-only stream",
+ pstm->Write(bBuffer, STREAMSIZE, NULL));
+
+ LISet32(liSeek, 0);
+ IllResult("Seek with invalid origin",
+ pstm->Seek(liSeek, (DWORD)(~STREAM_SEEK_SET), NULL));
+ LISet32(liSeek, (ULONG)-1);
+ IllResult("Seek before beginning",
+ pstm->Seek(liSeek, STREAM_SEEK_CUR, NULL));
+
+ ULISet32(uliSize, STREAMSIZE);
+ IllResult("SetSize on read-only stream",
+ pstm->SetSize(uliSize));
+
+ ULISet32(uliPos, 0);
+ ULISet32(cb, STREAMSIZE);
+ IllResult("LockRegion attempt",
+ pstm->LockRegion(uliPos, cb, LOCK_ONLYONCE));
+ IllResult("UnlockRegion attempt",
+ pstm->UnlockRegion(uliPos, cb, LOCK_ONLYONCE));
+
+ pwstm->Unwrap();
+ pwstg->Unwrap();
+}
+
+void i_enum(void)
+{
+ WStorage *pwstg;
+ IStorage *pstg;
+ IEnumSTATSTG *penm;
+
+ WStgCreateDocfile(DRTDF, ROOTP(STGM_READWRITE), 0, &pwstg);
+ pstg = pwstg->GetI();
+
+ IllResult("EnumElements with NULL ppenm",
+ pstg->EnumElements(0, NULL, 0, NULL));
+ IllResult("EnumElements with non-zero reserved1",
+ pstg->EnumElements(1, NULL, 0, &penm));
+ IllResult("EnumElements with non-zero reserved2",
+ pstg->EnumElements(0, (void *)1, 0, &penm));
+ IllResult("EnumElements with non-zero reserved3",
+ pstg->EnumElements(0, NULL, 1, &penm));
+
+ pwstg->Unwrap();
+}
diff --git a/private/ole32/stg/drt/illeg.hxx b/private/ole32/stg/drt/illeg.hxx
new file mode 100644
index 000000000..615560b84
--- /dev/null
+++ b/private/ole32/stg/drt/illeg.hxx
@@ -0,0 +1,21 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: illeg.hxx
+//
+// Contents: Illegitimate tests header
+//
+// History: 17-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ILLEG_HXX__
+#define __ILLEG_HXX__
+
+void i_storage(void);
+void i_stream(void);
+void i_enum(void);
+
+#endif // #ifndef __ILLEG_HXX__
diff --git a/private/ole32/stg/drt/makefile b/private/ole32/stg/drt/makefile
new file mode 100644
index 000000000..917a7c04a
--- /dev/null
+++ b/private/ole32/stg/drt/makefile
@@ -0,0 +1,20 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1994 **
+#********************************************************************
+
+!ifdef NTMAKEENV
+
+all:
+ echo $(BUILDMSG)
+
+clean: all
+
+!else
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/stg/drt/strlist.cxx b/private/ole32/stg/drt/strlist.cxx
new file mode 100644
index 000000000..3afc14d9c
--- /dev/null
+++ b/private/ole32/stg/drt/strlist.cxx
@@ -0,0 +1,148 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: strlist.cxx
+//
+// Contents: CStrList implementation
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <string.h>
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::CStrList, public
+//
+// Synopsis: Ctor
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CStrList::CStrList(void)
+{
+ _pseHead = NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::~CStrList, public
+//
+// Synopsis: Dtor
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CStrList::~CStrList(void)
+{
+ Empty();
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::Add, public
+//
+// Synopsis: Adds a string to the list
+//
+// Arguments: [ptcs] - String
+//
+// Returns: Pointer to entry or NULL
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+SStrEntry *CStrList::Add(OLECHAR *ptcs)
+{
+ SStrEntry *pse;
+
+ // One char of string already counted in sizeof
+ pse = (SStrEntry *)new
+ char[sizeof(SStrEntry)+olecslen(ptcs)*sizeof(OLECHAR)];
+ if (pse == NULL)
+ return NULL;
+ pse->pseNext = _pseHead;
+ pse->psePrev = NULL;
+ if (_pseHead)
+ _pseHead->psePrev = pse;
+ _pseHead = pse;
+ olecscpy(pse->atc, ptcs);
+ return pse;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::Remove, public
+//
+// Synopsis: Removes an entry from the list
+//
+// Arguments: [pse] - Entry
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+void CStrList::Remove(SStrEntry *pse)
+{
+ if (pse->psePrev)
+ pse->psePrev->pseNext = pse->pseNext;
+ else
+ _pseHead = pse->pseNext;
+ if (pse->pseNext)
+ pse->pseNext->psePrev = pse->psePrev;
+ delete pse;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::Find, public
+//
+// Synopsis: Attempts to find a string in the list
+//
+// Arguments: [ptcs] - String
+//
+// Returns: Entry or NULL
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+SStrEntry *CStrList::Find(OLECHAR *ptcs)
+{
+ SStrEntry *pse;
+
+ for (pse = _pseHead; pse; pse = pse->pseNext)
+ if (!olecscmp(ptcs, pse->atc))
+ return pse;
+ return NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::Empty, public
+//
+// Synopsis: Frees all elements in list
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+void CStrList::Empty(void)
+{
+ SStrEntry *pse;
+
+ while (_pseHead)
+ {
+ pse = _pseHead->pseNext;
+ delete _pseHead;
+ _pseHead = pse;
+ }
+}
diff --git a/private/ole32/stg/drt/strlist.hxx b/private/ole32/stg/drt/strlist.hxx
new file mode 100644
index 000000000..4e0824be6
--- /dev/null
+++ b/private/ole32/stg/drt/strlist.hxx
@@ -0,0 +1,49 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: strlist.hxx
+//
+// Contents: CStrList header
+//
+// Classes: CStrList
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __STRLIST_HXX__
+#define __STRLIST_HXX__
+
+#include <drt.hxx>
+
+struct SStrEntry
+{
+ SStrEntry *pseNext, *psePrev;
+ union
+ {
+ void *pv;
+ unsigned long dw;
+ } user;
+ OLECHAR atc[1]; // Actually contains the whole string
+};
+
+class CStrList
+{
+public:
+ CStrList(void);
+ ~CStrList(void);
+
+ SStrEntry *Add(OLECHAR *ptcs);
+ void Remove(SStrEntry *pse);
+ SStrEntry *Find(OLECHAR *ptcs);
+ void Empty(void);
+
+ SStrEntry *GetHead(void) { return _pseHead; }
+
+private:
+ SStrEntry *_pseHead;
+};
+
+#endif // #ifndef __STRLIST_HXX__
diff --git a/private/ole32/stg/drt/tests.cxx b/private/ole32/stg/drt/tests.cxx
new file mode 100644
index 000000000..882c80f31
--- /dev/null
+++ b/private/ole32/stg/drt/tests.cxx
@@ -0,0 +1,793 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: tests.cxx
+//
+// Contents: DRT tests
+//
+// History: 23-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include "tests.hxx"
+#include "ilb.hxx"
+
+void t_create(void)
+{
+ WStorage *pstgRoot, *pstgChild, *pstgChild2;
+ WStream *pstm;
+
+ WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE,
+ 0, &pstgRoot);
+ pstgRoot->CreateStorage(STR("Child"), STGP(WSTG_READWRITE), 0, 0,
+ &pstgChild);
+ pstgChild->CreateStorage(STR("Child2"), STGP(WSTG_READWRITE), 0, 0,
+ &pstgChild2);
+ pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0,
+ &pstm);
+ pstm->Unwrap();
+ pstgChild2->Commit(0);
+ pstgChild2->Unwrap();
+ pstgChild->Commit(0);
+ pstgChild->Unwrap();
+ VerifyStructure(pstgRoot->GetI(), "dChild(dChild2(sStream))");
+ pstgRoot->Unwrap();
+}
+
+void t_open(void)
+{
+ WStorage *pstgRoot, *pstgChild, *pstgChild2;
+ WStream *pstm;
+
+ WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE,
+ 0, &pstgRoot);
+ CreateStructure(pstgRoot->GetI(), "dChild(dChild2(sStream))");
+ pstgRoot->Commit(0);
+ pstgRoot->Unwrap();
+
+ WStgOpenStorage(DRTDF, NULL, ROOTP(WSTG_READWRITE), NULL,
+ 0, &pstgRoot);
+ pstgRoot->OpenStorage(STR("Child"), NULL, STGP(WSTG_READWRITE), NULL, 0,
+ &pstgChild);
+ pstgChild->OpenStorage(STR("Child2"), NULL, STGP(WSTG_READWRITE), NULL, 0,
+ &pstgChild2);
+ pstgChild2->OpenStream(STR("Stream"), NULL, STMP(WSTG_READWRITE), 0,
+ &pstm);
+ pstm->Unwrap();
+ pstgChild2->Unwrap();
+ pstgChild->Unwrap();
+ pstgRoot->Unwrap();
+}
+
+void t_addref(void)
+{
+ WStorage *pstg;
+ WStream *pstm;
+ ULONG ul;
+
+ WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE,
+ 0, &pstg);
+ pstg->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
+#ifndef FLAT
+ if ((ul = pstm->AddRef()) != 2)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+ if ((ul = pstm->Release()) != 1)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+ pstm->Unwrap();
+ if ((ul = pstg->AddRef()) != 2)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+ if ((ul = pstg->Release()) != 1)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+#else
+ if ((ul = pstm->AddRef()) <= 0)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+ if ((ul = pstm->Release()) <= 0)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+ pstm->Unwrap();
+ if ((ul = pstg->AddRef()) <= 0)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+ if ((ul = pstg->Release()) <= 0)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+#endif
+ pstg->Unwrap();
+}
+
+void t_tmodify(void)
+{
+ WStorage *pstgRoot, *pstgChild, *pstgChild2;
+ WStream *pstm;
+
+ // This test must use transacted mode to reproduce the
+ // expected behavior
+ ForceTransacted();
+
+ WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE,
+ 0, &pstgRoot);
+ pstgRoot->CreateStorage(STR("Child"), STGP(WSTG_READWRITE), 0,
+ 0, &pstgChild);
+ pstgChild->CreateStorage(STR("Child2"), STGP(WSTG_READWRITE), 0,
+ 0, &pstgChild2);
+ pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
+ pstm->Unwrap();
+ pstgChild2->Commit(0);
+ VerifyStructure(pstgChild2->GetI(), "sStream");
+
+ // Test renaming a closed stream
+ pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream"));
+ VerifyStructure(pstgChild2->GetI(), "sRenamedStream");
+
+ // Test rename reversion
+ pstgChild2->Revert();
+ VerifyStructure(pstgChild2->GetI(), "sStream");
+
+ // Test destruction of closed object
+ pstgChild2->DestroyElement(STR("Stream"));
+ pstgChild2->Commit(0);
+
+ // Test create of previously deleted object
+ pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
+ pstgChild2->Commit(0);
+ VerifyStructure(pstgChild2->GetI(), "sStream");
+
+#if 0
+ // 08/11/93 - Renaming open children no longer allowed
+ // Test renaming an open stream
+ pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream"));
+ VerifyStructure(pstgChild2->GetI(), "sRenamedStream");
+#endif
+
+ pstgChild2->Revert();
+ VerifyStructure(pstgChild2->GetI(), "sStream");
+ pstgChild2->DestroyElement(STR("Stream"));
+ pstgChild2->Commit(0);
+ pstm->Unwrap();
+
+ pstgChild2->Unwrap();
+ VerifyStructure(pstgChild->GetI(), "dChild2()");
+
+ // Test rename of storage
+ pstgChild->RenameElement(STR("Child2"), STR("RenamedChild"));
+ pstgChild->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0,
+ &pstm);
+ pstm->Unwrap();
+ pstgChild->DestroyElement(STR("Stream"));
+ pstgChild->Commit(0);
+
+ // Test SetElementTimes
+ FILETIME tm;
+ STATSTG stat;
+
+ tm.dwLowDateTime = 0x12345678;
+ tm.dwHighDateTime = 0x9abcdef0;
+
+ // Set when element not open
+ pstgChild->SetElementTimes(STR("RenamedChild"), &tm, NULL, NULL);
+ pstgChild->SetElementTimes(STR("RenamedChild"), NULL, &tm, NULL);
+ pstgChild->SetElementTimes(STR("RenamedChild"), NULL, NULL, &tm);
+
+ pstgChild->OpenStorage(STR("RenamedChild"), NULL, STGP(WSTG_READWRITE),
+ NULL, 0, &pstgChild2);
+ pstgChild2->Stat(&stat, STATFLAG_NONAME);
+ if (!IsEqualTime(stat.ctime, tm) ||
+ !IsEqualTime(stat.mtime, tm))
+ error(EXIT_BADSC, "Times don't match those set by SetElementTimes\n");
+
+ // Test SetClass and SetStateBits
+ pstgChild2->SetClass(IID_IStorage);
+ pstgChild2->SetStateBits(0xff00ff00, 0xffffffff);
+ pstgChild2->SetStateBits(0x00880088, 0xeeeeeeee);
+ pstgChild2->Stat(&stat, STATFLAG_NONAME);
+ if (!IsEqualCLSID(stat.clsid, IID_IStorage))
+ error(EXIT_BADSC, "Class ID set to %s\n", GuidText(&stat.clsid));
+ if (stat.grfStateBits != 0x11881188)
+ error(EXIT_BADSC, "State bits set improperly: has %lX vs. %lX\n",
+ stat.grfStateBits, 0x11881188);
+ pstgChild2->Revert();
+ pstgChild2->Stat(&stat, STATFLAG_NONAME);
+ if (!IsEqualCLSID(stat.clsid, CLSID_NULL))
+ error(EXIT_BADSC, "Class ID reverted to %s\n", GuidText(&stat.clsid));
+ if (stat.grfStateBits != 0)
+ error(EXIT_BADSC, "State bits reverted improperly: has %lX vs. %lX\n",
+ stat.grfStateBits, 0);
+ pstgChild2->Unwrap();
+
+ pstgChild->Unwrap();
+ VerifyStructure(pstgRoot->GetI(), "dChild(dRenamedChild())");
+ pstgRoot->Revert();
+ VerifyStructure(pstgRoot->GetI(), "");
+ pstgRoot->Commit(0);
+ VerifyStructure(pstgRoot->GetI(), "");
+ pstgRoot->Unwrap();
+ Unforce();
+}
+
+void t_dmodify(void)
+{
+ WStorage *pstgRoot, *pstgChild, *pstgChild2;
+ WStream *pstm;
+ ULONG cbSize1, cbSize2;
+
+ // This test must use direct mode to reproduce the
+ // expected behavior
+ ForceDirect();
+
+ WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE,
+ 0, &pstgRoot);
+ pstgRoot->CreateStorage(STR("Child"), STGP(WSTG_READWRITE), 0,
+ 0, &pstgChild);
+ pstgChild->CreateStorage(STR("Child2"), STGP(WSTG_READWRITE), 0,
+ 0, &pstgChild2);
+ pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
+ pstm->Unwrap();
+ VerifyStructure(pstgChild2->GetI(), "sStream");
+
+ // Test renaming a closed stream
+ pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream"));
+ VerifyStructure(pstgChild2->GetI(), "sRenamedStream");
+
+ // Test destroying a stream
+ pstgChild2->DestroyElement(STR("RenamedStream"));
+
+#if 0
+ // 08/11/93 - Renaming open child no longer allowed
+ // Test renaming an open stream
+ pstgChild2->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
+ VerifyStructure(pstgChild2->GetI(), "sStream");
+ pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream"));
+ VerifyStructure(pstgChild2->GetI(), "sRenamedStream");
+ pstgChild2->DestroyElement(STR("RenamedStream"));
+ pstm->Unwrap();
+#endif
+
+ pstgChild2->Unwrap();
+ VerifyStructure(pstgChild->GetI(), "dChild2()");
+
+ // Test renaming a storage
+ pstgChild->RenameElement(STR("Child2"), STR("RenamedChild"));
+ pstgChild->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0,
+ &pstm);
+ pstm->Unwrap();
+ pstgChild->DestroyElement(STR("Stream"));
+
+ // Test SetElementTimes
+ FILETIME tm;
+ STATSTG stat;
+
+ tm.dwLowDateTime = 0x12345678;
+ tm.dwHighDateTime = 0x9abcdef0;
+
+ // Set when element not open
+ pstgChild->SetElementTimes(STR("RenamedChild"), &tm, NULL, NULL);
+ pstgChild->SetElementTimes(STR("RenamedChild"), NULL, &tm, NULL);
+ pstgChild->SetElementTimes(STR("RenamedChild"), NULL, NULL, &tm);
+
+ pstgChild->OpenStorage(STR("RenamedChild"), NULL, STMP(WSTG_READWRITE),
+ NULL, 0, &pstgChild2);
+ pstgChild2->Stat(&stat, STATFLAG_NONAME);
+ if (!IsEqualTime(stat.ctime, tm) ||
+ !IsEqualTime(stat.mtime, tm))
+ error(EXIT_BADSC, "Times don't match those set by SetElementTimes\n");
+
+ // Test SetClass and SetStateBits
+ pstgChild2->SetClass(IID_IStorage);
+ pstgChild2->SetStateBits(0xff00ff00, 0xffffffff);
+ pstgChild2->SetStateBits(0x00880088, 0xeeeeeeee);
+ pstgChild2->Stat(&stat, STATFLAG_NONAME);
+ if (!IsEqualCLSID(stat.clsid, IID_IStorage))
+ error(EXIT_BADSC, "Class ID set improperly\n");
+ if (stat.grfStateBits != 0x11881188)
+ error(EXIT_BADSC, "State bits set improperly: has %lX vs. %lX\n",
+ stat.grfStateBits, 0x11881188);
+ pstgChild2->Unwrap();
+
+ pstgChild->Unwrap();
+ VerifyStructure(pstgRoot->GetI(), "dChild(dRenamedChild())");
+ pstgRoot->Revert();
+ VerifyStructure(pstgRoot->GetI(), "dChild(dRenamedChild())");
+ pstgRoot->Commit(0);
+ VerifyStructure(pstgRoot->GetI(), "dChild(dRenamedChild())");
+ pstgRoot->DestroyElement(STR("Child"));
+ VerifyStructure(pstgRoot->GetI(), "");
+
+ // Verify that space is reclaimed after modifications
+ pstgRoot->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
+ pstm->SetSize(65536);
+ pstm->Unwrap();
+ cbSize1 = Length(DRTDF);
+ pstgRoot->DestroyElement(STR("Stream"));
+ pstgRoot->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
+ pstm->SetSize(65536);
+ pstm->Unwrap();
+ cbSize2 = Length(DRTDF);
+ if (cbSize1 != cbSize2)
+ error(EXIT_BADSC, "Space is not being reclaimed, original %lu, "
+ "now %lu\n", cbSize1, cbSize2);
+
+ pstgRoot->Unwrap();
+
+ WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE |
+ WSTG_DELETEONRELEASE, 0, &pstgRoot);
+
+ // removal cases
+ // 1) no right child
+
+ CreateStructure(pstgRoot->GetI(), "d64,d32");
+ VerifyStructure(pstgRoot->GetI(), "d64,d32");
+ pstgRoot->DestroyElement(STR("64"));
+ VerifyStructure(pstgRoot->GetI(), "d32");
+
+ // 2) right child has no left child
+
+ CreateStructure(pstgRoot->GetI(), "d64");
+ VerifyStructure(pstgRoot->GetI(), "d32,d64");
+ pstgRoot->DestroyElement(STR("32"));
+ VerifyStructure(pstgRoot->GetI(), "d64");
+
+ // 3) right child has left child
+
+ CreateStructure(pstgRoot->GetI(), "d96,d80");
+ VerifyStructure(pstgRoot->GetI(), "d64,d80,d96");
+ pstgRoot->DestroyElement(STR("64"));
+ VerifyStructure(pstgRoot->GetI(), "d80,d96");
+
+ // 4) right child's left child has children
+
+ CreateStructure(pstgRoot->GetI(), "d88,d84,d92");
+ VerifyStructure(pstgRoot->GetI(), "d80,d84,d88,d92,d96");
+ pstgRoot->DestroyElement(STR("80"));
+ VerifyStructure(pstgRoot->GetI(), "d84,d88,d92,d96");
+
+ pstgRoot->Unwrap();
+
+ Unforce();
+}
+
+void t_stat(void)
+{
+ WStorage *pstgRoot, *pstgChild;
+ WStream *pstm;
+ STATSTG stat;
+
+ WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE,
+ 0, &pstgRoot);
+ pstgRoot->CreateStorage(STR("Child"), STGP(WSTG_READWRITE), 0, 0,
+ &pstgChild);
+ pstgChild->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
+
+ pstm->Stat(&stat, 0);
+ VerifyStat(&stat, STR("Stream"), STGTY_STREAM, STMP(WSTG_READWRITE));
+ drtMemFree(stat.pwcsName);
+
+ pstm->Stat(&stat, STATFLAG_NONAME);
+ VerifyStat(&stat, NULL, STGTY_STREAM, STMP(WSTG_READWRITE));
+
+ pstm->Unwrap();
+
+ pstgChild->Stat(&stat, 0);
+ VerifyStat(&stat, STR("Child"), STGTY_STORAGE, STGP(WSTG_READWRITE));
+ drtMemFree(stat.pwcsName);
+
+ pstgChild->Stat(&stat, STATFLAG_NONAME);
+ VerifyStat(&stat, NULL, STGTY_STORAGE, STGP(WSTG_READWRITE));
+
+ pstgChild->Unwrap();
+
+ pstgRoot->Stat(&stat, 0);
+ OLECHAR atcFullPath[_MAX_PATH];
+ GetFullPath(DRTDF, atcFullPath);
+ VerifyStat(&stat, atcFullPath, STGTY_STORAGE, ROOTP(WSTG_READWRITE));
+ drtMemFree(stat.pwcsName);
+
+ pstgRoot->Stat(&stat, STATFLAG_NONAME);
+ VerifyStat(&stat, NULL, STGTY_STORAGE, ROOTP(WSTG_READWRITE));
+
+ pstgRoot->Unwrap();
+}
+
+static char NUMBERS[] = "12345678901234567890123456789012345678901234567890";
+
+void t_stream(void)
+{
+ WStorage *pstg;
+ WStream *pstm, *pstmC;
+ char buf[sizeof(NUMBERS)*2];
+ ULONG cb, ulPos;
+
+ WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE, 0, &pstg);
+ pstg->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
+ pstm->Write(NUMBERS, sizeof(NUMBERS), &cb);
+ pstm->Commit(0);
+ pstm->Seek(0, WSTM_SEEK_SET, &ulPos);
+ if (ulPos != 0)
+ error(EXIT_BADSC, "Incorrect seek, ptr is %lu\n", ulPos);
+ pstm->Read(buf, sizeof(NUMBERS), &cb);
+ if (strcmp(buf, NUMBERS))
+ error(EXIT_BADSC, "Incorrect stream contents\n");
+ pstm->SetSize(sizeof(NUMBERS)/2);
+ pstm->Seek(0, WSTM_SEEK_SET, NULL);
+ fExitOnFail = FALSE;
+ pstm->Read(buf, sizeof(NUMBERS), &cb);
+ fExitOnFail = TRUE;
+ if (cb != sizeof(NUMBERS)/2)
+ error(EXIT_BADSC, "SetSize failed to size stream properly\n");
+ if (memcmp(buf, NUMBERS, sizeof(NUMBERS)/2))
+ error(EXIT_BADSC, "SetSize corrupted contents\n");
+ pstm->Clone(&pstmC);
+ pstm->Seek(0, WSTM_SEEK_SET, NULL);
+ pstm->CopyTo(pstmC, sizeof(NUMBERS)/2, NULL, NULL);
+ pstm->Seek(0, WSTM_SEEK_SET, NULL);
+ pstm->CopyTo(pstmC, sizeof(NUMBERS)&~1, NULL, NULL);
+ pstm->Seek(0, WSTM_SEEK_SET, NULL);
+ pstm->Read(buf, (sizeof(NUMBERS)&~1)*2, &cb);
+ if (memcmp(buf, NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+sizeof(NUMBERS)/2, NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+(sizeof(NUMBERS)&~1), NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+3*(sizeof(NUMBERS)/2), NUMBERS, sizeof(NUMBERS)/2))
+ error(EXIT_BADSC, "Stream contents incorrect\n");
+ pstmC->Unwrap();
+ pstm->Unwrap();
+ pstg->Unwrap();
+}
+
+// Number of entries for enumeration test
+#define ENUMENTRIES 10
+
+// Flag indicating a name has already shown up in enumeration,
+// must not conflict with STGTY_*
+#define ENTRY_SEEN 0x100
+
+// Check the validity of an enumeration element
+static void elt_check(STATSTG *pstat, CStrList *psl)
+{
+ SStrEntry *pse;
+
+ pse = psl->Find(pstat->pwcsName);
+ if (pse == NULL)
+ error(EXIT_BADSC, "Spurious element '%s'\n", pstat->pwcsName);
+ else if ((pse->user.dw & ~ENTRY_SEEN) != pstat->type)
+ error(EXIT_BADSC, "Element '%s' has wrong type - "
+ "has %lX vs. %lX\n", pstat->pwcsName, pstat->type,
+ pse->user.dw & ~ENTRY_SEEN);
+ else if (pse->user.dw & ENTRY_SEEN)
+ error(EXIT_BADSC, "Element '%s' has already been seen\n",
+ pstat->pwcsName);
+ pse->user.dw |= ENTRY_SEEN;
+}
+
+// Do final validity checks for enumeration
+static void enum_list_check(CStrList *psl)
+{
+ SStrEntry *pse;
+
+ for (pse = psl->GetHead(); pse; pse = pse->pseNext)
+ {
+ if ((pse->user.dw & ENTRY_SEEN) == 0)
+ error(EXIT_BADSC, "Element '%s' not found\n", pse->atc);
+ pse->user.dw &= ~ENTRY_SEEN;
+ }
+}
+
+void t_enum(void)
+{
+ int i;
+ OLECHAR atcName[CWCSTORAGENAME];
+ WStorage *pstg, *pstg2;
+ WStream *pstm;
+ SStrEntry *pse;
+ CStrList sl;
+
+ // Create some entries to enumerate
+ WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE, 0, &pstg);
+ for (i = 0; i<ENUMENTRIES; i++)
+ {
+ olecsprintf(atcName, STR("Name%d"), rand());
+ pse = sl.Add(atcName);
+ if (rand()%100 < 50)
+ {
+ pse->user.dw = STGTY_STORAGE;
+ pstg->CreateStorage(atcName, STGP(WSTG_READWRITE), 0, 0, &pstg2);
+ pstg2->Unwrap();
+ }
+ else
+ {
+ pse->user.dw = STGTY_STREAM;
+ pstg->CreateStream(atcName, STMP(WSTG_READWRITE), 0, 0, &pstm);
+ pstm->Unwrap();
+ }
+ }
+
+ WEnumSTATSTG *penm;
+ STATSTG stat[2*ENUMENTRIES];
+ SCODE sc;
+
+ // Test plain, single element enumeration
+ pstg->EnumElements(0, NULL, 0, &penm);
+ for (;;)
+ {
+ sc = DfGetScode(penm->Next(1, stat, NULL));
+ if (sc == S_FALSE)
+ break;
+ elt_check(stat, &sl);
+ drtMemFree(stat->pwcsName);
+
+ }
+ enum_list_check(&sl);
+
+ ULONG cFound;
+
+ // Test rewind and multiple element enumeration with too many elements
+ penm->Reset();
+ sc = DfGetScode(penm->Next(ENUMENTRIES*2, stat, &cFound));
+ if (sc != S_FALSE)
+ error(EXIT_BADSC, "Enumerator returned %s (%lX) instead of "
+ "S_FALSE\n", ScText(sc), sc);
+ if (cFound != ENUMENTRIES)
+ error(EXIT_BADSC, "Enumerator found %lu entries instead of "
+ "%d entries\n", cFound, ENUMENTRIES);
+ for (; cFound > 0; cFound--)
+ {
+ elt_check(&stat[cFound-1], &sl);
+ drtMemFree(stat[cFound-1].pwcsName);
+ }
+ enum_list_check(&sl);
+
+ // Test skip and multiple enumeration with exact number of elements
+ penm->Reset();
+ penm->Skip(ENUMENTRIES/2);
+ sc = DfGetScode(penm->Next(ENUMENTRIES-ENUMENTRIES/2, stat, &cFound));
+ if (sc != S_OK)
+ error(EXIT_BADSC, "Enumerator returned %s (%lX) instead of "
+ "S_OK\n", ScText(sc), sc);
+ if (cFound != ENUMENTRIES-ENUMENTRIES/2)
+ error(EXIT_BADSC, "Enumerator found %lu entries instead of "
+ "%d entries\n", cFound, ENUMENTRIES-ENUMENTRIES/2);
+ for (; cFound > 0; cFound--)
+ {
+ elt_check(&stat[cFound-1], &sl);
+ drtMemFree(stat[cFound-1].pwcsName);
+ }
+ sc = DfGetScode(penm->Next(1, stat, NULL));
+ if (sc != S_FALSE)
+ error(EXIT_BADSC, "Enumerator returned %s (%lX) instead of "
+ "S_FALSE\n", ScText(sc), sc);
+
+ penm->Unwrap();
+ pstg->Unwrap();
+}
+
+#define SCT_CLASSID IID_ILockBytes
+#define SCT_STATEBITS 0xfef1f0f0
+
+void t_stgcopyto(void)
+{
+ WStorage *pstgFrom, *pstgTo;
+ STATSTG statFrom, statTo;
+
+ WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE |
+ WSTG_DELETEONRELEASE, 0, &pstgFrom);
+ pstgFrom->Stat(&statFrom, 0);
+
+ // Set some interesting values to make sure they're copied
+ pstgFrom->SetClass(SCT_CLASSID);
+ pstgFrom->SetStateBits(SCT_STATEBITS, 0xffffffff);
+
+ WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE |
+ WSTG_DELETEONRELEASE, 0, &pstgTo);
+ CreateStructure(pstgFrom->GetI(), "dA(dB(dC(sA,sB,sC),sCs),sBs),sAs");
+ CreateStructure(pstgTo->GetI(), "dA(dY(sZ),sBs)");
+
+ pstgFrom->CopyTo(0, NULL, NULL, pstgTo);
+
+ VerifyStructure(pstgTo->GetI(),
+ "dA(dB(dC(sA,sB,sC),sCs),dY(sZ),sBs),sAs");
+ pstgTo->Stat(&statTo, 0);
+ if (!IsEqualCLSID(statTo.clsid, SCT_CLASSID))
+ error(EXIT_BADSC, "Class ID mismatch after copy\n");
+ if (statTo.grfStateBits != SCT_STATEBITS)
+ error(EXIT_BADSC, "State bits mismatch: has %lX vs. %lX\n",
+ statTo.grfStateBits, SCT_STATEBITS);
+
+ pstgFrom->Unwrap();
+ pstgTo->Unwrap();
+ if (Exists(statFrom.pwcsName))
+ error(EXIT_BADSC, "Storage '%s' not deleted\n", statFrom.pwcsName);
+ drtMemFree(statFrom.pwcsName);
+ if (Exists(statTo.pwcsName))
+ error(EXIT_BADSC, "Storage '%s' not deleted\n", statTo.pwcsName);
+ drtMemFree(statTo.pwcsName);
+}
+
+#define MARSHAL_STM STR("Marshal")
+
+static void do_marshal(WStorage *pstg, WStream *pstm)
+{
+ WStorage *pstgMarshal;
+ WStream *pstmMarshal;
+
+ WStgCreateDocfile(MARSHALDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE,
+ 0, &pstgMarshal);
+ pstgMarshal->CreateStream(MARSHAL_STM, STMP(WSTG_READWRITE), 0, 0,
+ &pstmMarshal);
+ WCoMarshalInterface(pstmMarshal, IID_IStorage, pstg->GetI(), 0, NULL,
+ MSHLFLAGS_NORMAL);
+ WCoMarshalInterface(pstmMarshal, IID_IStream, pstm->GetI(), 0, NULL,
+ MSHLFLAGS_NORMAL);
+ pstmMarshal->Unwrap();
+ pstgMarshal->Commit(0);
+ pstgMarshal->Unwrap();
+}
+
+static char STREAM_DATA[] = "This is data to be written";
+
+static void do_unmarshal(WStorage **ppstg, WStream **ppstm)
+{
+ IStorage *pistg;
+ WStorage *pstgMarshal;
+ WStream *pstmMarshal;
+ IStream *pistm;
+
+ WStgOpenStorage(MARSHALDF, NULL, ROOTP(WSTG_READWRITE), NULL, 0,
+ &pstgMarshal);
+ pstgMarshal->OpenStream(MARSHAL_STM, NULL, STMP(WSTG_READWRITE), 0,
+ &pstmMarshal);
+ WCoUnmarshalInterface(pstmMarshal, IID_IStorage, (void **)&pistg);
+ *ppstg = WStorage::Wrap(pistg);
+ WCoUnmarshalInterface(pstmMarshal, IID_IStream, (void **)&pistm);
+ *ppstm = WStream::Wrap(pistm);
+ pstmMarshal->Unwrap();
+ pstgMarshal->Unwrap();
+}
+
+void t_marshal(void)
+{
+ WStorage *pstg, *pstgM;
+ WStream *pstm, *pstmM;
+ ULONG cbRead, cbWritten;
+ char buf[sizeof(STREAM_DATA)];
+
+ WStgCreateDocfile(DRTDF, ROOTP(WSTG_READWRITE) | WSTG_CREATE |
+ WSTG_DELETEONRELEASE, 0, &pstg);
+ pstg->CreateStream(STR("Stream"), STMP(WSTG_READWRITE), 0, 0, &pstm);
+ pstm->Write(STREAM_DATA, sizeof(STREAM_DATA), &cbWritten);
+ CreateStructure(pstg->GetI(), "dChild(dChild(sStream))");
+
+ do_marshal(pstg, pstm);
+ do_unmarshal(&pstgM, &pstmM);
+ pstm->Unwrap();
+ pstg->Unwrap();
+
+ pstmM->Seek(0, WSTM_SEEK_SET, NULL);
+ pstmM->Read(buf, sizeof(STREAM_DATA), &cbRead);
+ if (strcmp(buf, STREAM_DATA))
+ error(EXIT_BADSC, "Stream data mismatch\n");
+ pstmM->Unwrap();
+
+ VerifyStructure(pstgM->GetI(), "dChild(dChild(sStream)),sStream");
+ pstgM->Unwrap();
+}
+
+void t_stgmisc(void)
+{
+ WStorage *pstg;
+ SCODE sc;
+ STATSTG stat;
+
+ // Can't make this call in transacted mode because we want
+ // the storage signature to make it into the file right away
+ WStgCreateDocfile(DRTDF, WSTG_READWRITE | WSTG_CREATE |
+ WSTG_SHARE_EXCLUSIVE, 0, &pstg);
+ sc = DfGetScode(WStgIsStorageFile(DRTDF));
+ if (sc == S_FALSE)
+ error(EXIT_BADSC, "Open file - Should be a storage object\n");
+ pstg->Unwrap();
+ sc = DfGetScode(WStgIsStorageFile(DRTDF));
+ if (sc == S_FALSE)
+ error(EXIT_BADSC, "Closed file - Should be a storage object\n");
+ WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE |
+ WSTG_DELETEONRELEASE, 0, &pstg);
+ pstg->Stat(&stat, 0);
+ if (!Exists(stat.pwcsName))
+ error(EXIT_BADSC, "Storage '%s' not created\n", stat.pwcsName);
+ pstg->Unwrap();
+ if (Exists(stat.pwcsName))
+ error(EXIT_BADSC, "Storage '%s' not deleted on release\n",
+ stat.pwcsName);
+ drtMemFree(stat.pwcsName);
+}
+
+void t_ilb(void)
+{
+ WStorage *pstg;
+ SCODE sc;
+ // create an ILockBytes
+
+ ILockBytes *pilb = new CMapBytes();
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ WStgCreateDocfileOnILockBytes(pilb,
+ WSTG_READWRITE |
+ WSTG_CREATE |
+ WSTG_SHARE_EXCLUSIVE,
+ 0, &pstg);
+
+ // verify the ILockBytes
+
+ sc = DfGetScode(WStgIsStorageILockBytes(pilb));
+ if (sc == S_FALSE)
+ error(EXIT_BADSC, "Open ILockBytes - Should be a storage object\n");
+
+ // release the storage
+
+ pstg->Unwrap();
+
+ // verify the ILockBytes
+
+ sc = DfGetScode(WStgIsStorageILockBytes(pilb));
+
+ if (sc == S_FALSE)
+ error(EXIT_BADSC, "Released ILockBytes - Should be a storage object\n");
+
+ // open the ILockBytes
+
+ WStgOpenStorageOnILockBytes(pilb, NULL, ROOTP(WSTG_READWRITE),
+ NULL, 0, &pstg);
+
+
+ // release the storage
+
+ pstg->Unwrap();
+
+ // release the ILockBytes
+
+ pilb->Release();
+}
+
+void t_movecopy(void)
+{
+ WStorage *pstgFrom, *pstgTo;
+ STATSTG statFrom, statTo;
+
+ // create a source
+ WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE |
+ WSTG_DELETEONRELEASE, 0, &pstgFrom);
+ pstgFrom->Stat(&statFrom, 0);
+
+ // create a destination
+ WStgCreateDocfile(NULL, ROOTP(WSTG_READWRITE) | WSTG_CREATE |
+ WSTG_DELETEONRELEASE, 0, &pstgTo);
+ pstgTo->Stat(&statTo, 0);
+
+ // populate source
+ CreateStructure(pstgFrom->GetI(), "dA(dB(dC(sA,sB,sC),sCs),sBs),sAs");
+
+ // move a storage
+ pstgFrom->MoveElementTo(STR("A"), pstgTo, STR("M"), STGMOVE_MOVE);
+ VerifyStructure(pstgFrom->GetI(),
+ "sAs");
+ VerifyStructure(pstgTo->GetI(),
+ "dM(dB(dC(sA,sB,sC),sCs),sBs)");
+
+ // copy a stream
+ pstgFrom->MoveElementTo(STR("As"), pstgTo, STR("Bs"), STGMOVE_COPY);
+ VerifyStructure(pstgFrom->GetI(),
+ "sAs");
+ VerifyStructure(pstgTo->GetI(),
+ "dM(dB(dC(sA,sB,sC),sCs),sBs),sBs");
+
+ pstgFrom->Unwrap();
+ pstgTo->Unwrap();
+ if (Exists(statFrom.pwcsName))
+ error(EXIT_BADSC, "Storage '%s' not deleted\n", statFrom.pwcsName);
+ drtMemFree(statFrom.pwcsName);
+ if (Exists(statTo.pwcsName))
+ error(EXIT_BADSC, "Storage '%s' not deleted\n", statTo.pwcsName);
+ drtMemFree(statTo.pwcsName);
+}
diff --git a/private/ole32/stg/drt/tests.hxx b/private/ole32/stg/drt/tests.hxx
new file mode 100644
index 000000000..ad9176cda
--- /dev/null
+++ b/private/ole32/stg/drt/tests.hxx
@@ -0,0 +1,31 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: tests.hxx
+//
+// Contents: DRT tests header
+//
+// History: 23-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __TESTS_HXX__
+#define __TESTS_HXX__
+
+void t_create(void);
+void t_open(void);
+void t_addref(void);
+void t_tmodify(void);
+void t_dmodify(void);
+void t_stat(void);
+void t_stream(void);
+void t_enum(void);
+void t_stgcopyto(void);
+void t_marshal(void);
+void t_stgmisc(void);
+void t_ilb(void);
+void t_movecopy(void);
+
+#endif // #ifndef __TESTS_HXX__
diff --git a/private/ole32/stg/drt/util.cxx b/private/ole32/stg/drt/util.cxx
new file mode 100644
index 000000000..0feca7fb0
--- /dev/null
+++ b/private/ole32/stg/drt/util.cxx
@@ -0,0 +1,517 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: util.cxx
+//
+// Contents: DRT support routines
+//
+// History: 22-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <stdarg.h>
+#include <direct.h>
+#include <io.h>
+
+#if DBG == 1
+#include <dfdeb.hxx>
+#endif
+
+#define DEFAULT_DATA_DIR "."
+
+BOOL fExitOnFail = TRUE;
+
+char szOrigDir[_MAX_PATH] = ".";
+
+// Preserve the current directory and change
+// directory into the data directory
+void SetData(void)
+{
+ char *pszDataDir;
+
+ _getcwd(szOrigDir, _MAX_PATH);
+ pszDataDir = getenv("DRTDATA");
+ if (pszDataDir == NULL)
+ pszDataDir = DEFAULT_DATA_DIR;
+ _chdir(pszDataDir);
+}
+
+// Clean up the data directory
+void CleanData(void)
+{
+ _unlink(OlecsOut(DRTDF));
+ _unlink(OlecsOut(MARSHALDF));
+}
+
+// Restore the original directory
+void UnsetData(void)
+{
+ _chdir(szOrigDir);
+}
+
+// Output a message if fVerbose is true
+void out(char *fmt, ...)
+{
+ va_list args;
+
+ if (fVerbose)
+ {
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ }
+}
+
+// Print out an error message and terminate the DRT
+void error(int code, char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+#if !defined(FLAT) || defined(FPRINTF_WORKS)
+ fprintf(stderr, "** Fatal error **: ");
+ vfprintf(stderr, fmt, args);
+#else
+ printf("** Fatal error **: ");
+ vprintf(fmt, args);
+#endif
+ va_end(args);
+ CleanData();
+ UnsetData();
+ exit(code);
+}
+
+// Converts a TCHAR string to a char pointer in a temporary buffer
+// This implementation treats the conversion buffer as a circular
+// buffer so more than one string can be held (depending on the size
+// of the strings)
+
+#define BUFSIZE 1024
+
+char *OlecsOut(OLECHAR const *ptcs)
+{
+#ifdef OLEWIDECHAR
+ static char szBuffer[BUFSIZE];
+ static char *pszBuf = szBuffer;
+ char *pszTmp;
+
+ if (ptcs == NULL)
+ return NULL;
+ if (wcslen(ptcs) >= (size_t)(BUFSIZE-(pszBuf-szBuffer)))
+ pszBuf = szBuffer;
+ wcstombs(pszBuf, ptcs, BUFSIZE);
+ szBuffer[BUFSIZE-1] = 0;
+ pszTmp = pszBuf;
+ pszBuf += strlen(pszBuf)+1;
+ return pszTmp;
+#else
+ return (char *)ptcs;
+#endif
+}
+
+typedef struct
+{
+ SCODE sc;
+ char *text;
+} StatusCodeText;
+
+static StatusCodeText scodes[] =
+{
+ S_OK, "S_OK",
+ S_FALSE, "S_FALSE",
+ STG_E_INVALIDFUNCTION, "STG_E_INVALIDFUNCTION",
+ STG_E_FILENOTFOUND, "STG_E_FILENOTFOUND",
+ STG_E_PATHNOTFOUND, "STG_E_PATHNOTFOUND",
+ STG_E_TOOMANYOPENFILES, "STG_E_TOOMANYOPENFILES",
+ STG_E_ACCESSDENIED, "STG_E_ACCESSDENIED",
+ STG_E_INVALIDHANDLE, "STG_E_INVALIDHANDLE",
+ STG_E_INSUFFICIENTMEMORY, "STG_E_INSUFFICIENTMEMORY",
+ STG_E_INVALIDPOINTER, "STG_E_INVALIDPOINTER",
+ STG_E_NOMOREFILES, "STG_E_NOMOREFILES",
+ STG_E_DISKISWRITEPROTECTED, "STG_E_DISKISWRITEPROTECTED",
+ STG_E_SEEKERROR, "STG_E_SEEKERROR",
+ STG_E_WRITEFAULT, "STG_E_WRITEFAULT",
+ STG_E_READFAULT, "STG_E_READFAULT",
+ STG_E_SHAREVIOLATION, "STG_E_SHAREVIOLATION",
+ STG_E_LOCKVIOLATION, "STG_E_LOCKVIOLATION",
+ STG_E_FILEALREADYEXISTS, "STG_E_FILEALREADYEXISTS",
+ STG_E_INVALIDPARAMETER, "STG_E_INVALIDPARAMETER",
+ STG_E_MEDIUMFULL, "STG_E_MEDIUMFULL",
+ STG_E_ABNORMALAPIEXIT, "STG_E_ABNORMALAPIEXIT",
+ STG_E_INVALIDHEADER, "STG_E_INVALIDHEADER",
+ STG_E_INVALIDNAME, "STG_E_INVALIDNAME",
+ STG_E_UNKNOWN, "STG_E_UNKNOWN",
+ STG_E_UNIMPLEMENTEDFUNCTION, "STG_E_UNIMPLEMENTEDFUNCTION",
+ STG_E_INVALIDFLAG, "STG_E_INVALIDFLAG",
+ STG_E_INUSE, "STG_E_INUSE",
+ STG_E_NOTCURRENT, "STG_E_NOTCURRENT",
+ STG_E_REVERTED, "STG_E_REVERTED",
+ STG_E_CANTSAVE, "STG_E_CANTSAVE",
+ STG_E_OLDFORMAT, "STG_E_OLDFORMAT",
+ STG_E_OLDDLL, "STG_E_OLDDLL",
+ STG_E_SHAREREQUIRED, "STG_E_SHAREREQUIRED",
+ STG_E_NOTFILEBASEDSTORAGE, "STG_E_NOTFILEBASEDSTORAGE",
+ STG_E_EXTANTMARSHALLINGS, "STG_E_EXTANTMARSHALLINGS",
+ STG_S_CONVERTED, "STG_S_CONVERTED"
+};
+#define NSCODETEXT (sizeof(scodes)/sizeof(scodes[0]))
+
+// Convert a status code to text
+char *ScText(SCODE sc)
+{
+ int i;
+
+ for (i = 0; i<NSCODETEXT; i++)
+ if (scodes[i].sc == sc)
+ return scodes[i].text;
+ return "?";
+}
+
+// Output a call result and check for failure
+HRESULT Result(HRESULT hr)
+{
+ SCODE sc;
+
+ sc = DfGetScode(hr);
+ out(" - %s (0x%lX)\n", ScText(sc), sc);
+ if (FAILED(sc) && fExitOnFail)
+ error(EXIT_BADSC, "Unexpected call failure\n");
+ return hr;
+}
+
+// Perform Result() when the expectation is failure
+HRESULT IllResult(char *pszText, HRESULT hr)
+{
+ SCODE sc;
+
+ sc = DfGetScode(hr);
+ out("%s - %s (0x%lX)\n", pszText, ScText(sc), sc);
+ if (SUCCEEDED(sc) && fExitOnFail)
+ error(EXIT_BADSC, "Unexpected call success\n");
+ return hr;
+}
+
+// DEBUG - Check for memory leaks
+void CheckMemory(void)
+{
+#if DBG == 1
+ if (fVerbose || DfGetMemAlloced() != 0)
+ {
+ out("Memory held: %lu bytes\n", DfGetMemAlloced());
+ if (DfGetMemAlloced() != 0)
+ {
+ DfPrintAllocs();
+ error(EXIT_BADSC, "Memory leak\n");
+ }
+ }
+#endif
+}
+
+// DEBUG - Set the debugging level
+void SetDebug(ULONG ulDf, ULONG ulMsf)
+{
+#if DBG == 1
+ DfDebug(ulDf, ulMsf);
+#endif
+}
+
+// Check whether a given storage has a certain
+// structure or not
+// Structure is given as a string with elements:
+// <Type><Name><Options>[,...]
+// Type - d for docfile and s for stream
+// Name - Characters up to a '(' or ','
+// Options - For a docfile, you can specify a recursive check
+// in parentheses
+//
+// Example: dDocfile(sStream,dDocfile)
+char *VerifyStructure(IStorage *pstg, char *pszStructure)
+{
+ char szName[CWCSTORAGENAME], *psz;
+ IStorage *pstgChild;
+ char chType;
+ SCODE sc;
+ CStrList sl;
+ SStrEntry *pse;
+ IEnumSTATSTG *penm;
+ STATSTG stat;
+ OLECHAR atcName[CWCSTORAGENAME];
+
+ if (FAILED(sc = DfGetScode(pstg->EnumElements(0, NULL, 0, &penm))))
+ error(EXIT_BADSC, "VerifyStructure: Unable to create enumerator - "
+ "%s (0x%lX)\n", ScText(sc), sc);
+ for (;;)
+ {
+ sc = DfGetScode(penm->Next(1, &stat, NULL));
+ if (sc == S_FALSE)
+ break;
+ else if (FAILED(sc))
+ error(EXIT_BADSC, "VerifyStructure: Unable to enumerate - "
+ "%s (0x%lX)\n", ScText(sc), sc);
+ pse = sl.Add(stat.pwcsName);
+ if (pse == NULL)
+ error(EXIT_OOM, "VerifyStructure: Unable to allocate string\n");
+ pse->user.dw = stat.type;
+ drtMemFree(stat.pwcsName);
+ }
+ penm->Release();
+ while (*pszStructure && *pszStructure != ')')
+ {
+ chType = *pszStructure++;
+ psz = szName;
+ while (*pszStructure && *pszStructure != '(' &&
+ *pszStructure != ')' && *pszStructure != ',')
+ *psz++ = *pszStructure++;
+ *psz = 0;
+ ATOOLE(szName, atcName, CWCSTORAGENAME);
+ pse = sl.Find(atcName);
+ if (pse == NULL)
+ error(EXIT_BADSC, "VerifyStructure: '%s' not found\n", szName);
+ switch(chType)
+ {
+ case 'd':
+ if (pse->user.dw != STGTY_STORAGE)
+ error(EXIT_BADSC, "VerifyStructure: '%s' is not a storage\n",
+ szName);
+ sc = DfGetScode(pstg->OpenStorage(atcName, NULL,
+ STGP(STGM_READWRITE), NULL,
+ 0, &pstgChild));
+ if (FAILED(sc))
+ error(EXIT_BADSC, "VerifyStructure: can't open storage "
+ "'%s' - %s\n", szName, ScText(sc));
+ if (*pszStructure == '(')
+ pszStructure = VerifyStructure(pstgChild, pszStructure+1)+1;
+ pstgChild->Release();
+ break;
+ case 's':
+ if (pse->user.dw != STGTY_STREAM)
+ error(EXIT_BADSC, "VerifyStructure: '%s' is not a stream\n",
+ szName);
+ break;
+ }
+ sl.Remove(pse);
+ if (*pszStructure == ',')
+ pszStructure++;
+ }
+ for (pse = sl.GetHead(); pse; pse = pse->pseNext)
+ error(EXIT_BADSC, "VerifyStructure: additional member '%s'\n",
+ OlecsOut(pse->atc));
+ return pszStructure;
+}
+
+// Creates a structure using the same syntax
+// as VerifyStructure
+char *CreateStructure(IStorage *pstg, char *pszStructure)
+{
+ char szName[CWCSTORAGENAME], *psz;
+ IStorage *pstgChild;
+ IStream *pstmChild;
+ char chType;
+ SCODE sc;
+ OLECHAR atcName[CWCSTORAGENAME];
+
+ while (*pszStructure && *pszStructure != ')')
+ {
+ chType = *pszStructure++;
+ psz = szName;
+ while (*pszStructure && *pszStructure != '(' &&
+ *pszStructure != ')' && *pszStructure != ',')
+ *psz++ = *pszStructure++;
+ *psz = 0;
+ ATOOLE(szName, atcName, CWCSTORAGENAME);
+ switch(chType)
+ {
+ case 'd':
+ sc = DfGetScode(pstg->CreateStorage(atcName, STGP(STGM_READWRITE),
+ 0, 0, &pstgChild));
+ if (FAILED(sc))
+ error(EXIT_BADSC, "CreateStructure: can't create storage "
+ "'%s' - %s\n", szName, ScText(sc));
+ if (*pszStructure == '(')
+ pszStructure = CreateStructure(pstgChild, pszStructure+1)+1;
+ pstgChild->Release();
+ break;
+ case 's':
+ sc = DfGetScode(pstg->CreateStream(atcName, STMP(STGM_READWRITE),
+ 0, 0, &pstmChild));
+ if (FAILED(sc))
+ error(EXIT_BADSC, "CreateStructure: can't create stream "
+ "'%s' - %s\n", szName, ScText(sc));
+ pstmChild->Release();
+ break;
+ }
+ if (*pszStructure == ',')
+ pszStructure++;
+ }
+ pstg->Commit(0);
+ return pszStructure;
+}
+
+// Verifies the fields of a STATSTG
+void VerifyStat(STATSTG *pstat, OLECHAR *ptcsName, DWORD type, DWORD grfMode)
+{
+ if (ptcsName == NULL)
+ {
+ if (pstat->pwcsName != NULL)
+ error(EXIT_BADSC, "Stat name should be NULL - is %p\n",
+ pstat->pwcsName);
+ }
+ else if (olecscmp(pstat->pwcsName, ptcsName))
+ error(EXIT_BADSC, "Stat name mismatch - has '%s' vs. '%s'\n",
+ OlecsOut(pstat->pwcsName), OlecsOut(ptcsName));
+ if (pstat->type != type)
+ error(EXIT_BADSC, "Stat type mismatch - has %lu vs. %lu\n",
+ pstat->type, type);
+ if (pstat->grfMode != grfMode)
+ error(EXIT_BADSC, "Stat mode mismatch - has 0x%lX vs. 0x%lX\n",
+ pstat->grfMode, grfMode);
+}
+
+// Checks on a file's existence
+BOOL Exists(OLECHAR *file)
+{
+ OFSTRUCT of;
+
+#ifndef OLEWIDECHAR
+ return OpenFile(file, &of, OF_EXIST | OF_SHARE_DENY_NONE) !=
+ HFILE_ERROR ? TRUE : FALSE;
+#else
+ char szName[_MAX_PATH];
+ wcstombs(szName, file, _MAX_PATH);
+ return OpenFile(szName, &of, OF_EXIST | OF_SHARE_DENY_NONE) !=
+ HFILE_ERROR ? TRUE : FALSE;
+#endif
+}
+
+// Gets a file's length
+ULONG Length(OLECHAR *file)
+{
+ OFSTRUCT of;
+ ULONG cb;
+ int hf;
+
+#ifndef OLEWIDECHAR
+ hf = OpenFile(file, &of, OF_READ | OF_SHARE_DENY_NONE);
+#else
+ char szName[_MAX_PATH];
+ wcstombs(szName, file, _MAX_PATH);
+ hf = OpenFile(szName, &of, OF_READ | OF_SHARE_DENY_NONE);
+#endif
+ if (hf == HFILE_ERROR)
+ error(EXIT_BADSC, "Length: Unable to open '%s'\n", OlecsOut(file));
+ cb = (ULONG)_llseek(hf, 0, SEEK_END);
+ if (cb == (ULONG)HFILE_ERROR)
+ error(EXIT_BADSC, "Length: Unable to get length for '%s'\n",
+ OlecsOut(file));
+ _lclose(hf);
+ return cb;
+}
+
+// Original mode when a new mode is forced
+// Used by ForceDirect, ForceTransacted and Unforce
+static DWORD dwTransOld;
+static DWORD dwRDWOld;
+
+// Forces direct mode to be active
+// Note: this uses a static variable so it can\'t be nested
+void ForceDirect(void)
+{
+ dwTransOld = dwTransacted;
+ dwTransacted = STGM_DIRECT;
+ dwRDWOld = dwRootDenyWrite;
+ dwRootDenyWrite = STGM_SHARE_EXCLUSIVE;
+}
+
+// Forces transacted mode similarly to ForceDirect
+void ForceTransacted(void)
+{
+ dwTransOld = dwTransacted;
+ dwRDWOld = dwRootDenyWrite;
+ dwTransacted = STGM_TRANSACTED;
+}
+
+// Returns to the original mode after a ForceDirect or ForceTransacted
+void Unforce(void)
+{
+ dwTransacted = dwTransOld;
+ dwRootDenyWrite = dwRDWOld;
+}
+
+// Equality for FILETIME
+BOOL IsEqualTime(FILETIME ttTime, FILETIME ttCheck)
+{
+ return ttTime.dwLowDateTime == ttCheck.dwLowDateTime &&
+ ttTime.dwHighDateTime == ttCheck.dwHighDateTime;
+}
+
+// Get a fully qualified path for a file name
+void GetFullPath(OLECHAR *file, OLECHAR *path)
+{
+#ifndef UNICODE
+ char buf[_MAX_PATH];
+ OFSTRUCT of;
+
+ OLETOA(file, buf, _MAX_PATH);
+ OpenFile(buf, &of, OF_PARSE);
+ ATOOLE((char *)of.szPathName, path, _MAX_PATH);
+#else
+ OLECHAR *ptcsFile;
+
+ GetFullPathName(file, _MAX_PATH, path, &ptcsFile);
+#endif
+}
+
+// Memory helper functions
+
+HRESULT drtMemAlloc(ULONG ulcb, void **ppv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc = NULL;
+
+ if (SUCCEEDED(DfGetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ *ppv = pMalloc->Alloc(ulcb);
+ pMalloc->Release();
+
+ if (*ppv == NULL)
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+
+ return hr;
+}
+
+void drtMemFree(void *pv)
+{
+ IMalloc FAR* pMalloc;
+ if (SUCCEEDED(GetScode(CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ pMalloc->Free(pv);
+ pMalloc->Release();
+ }
+}
+
+#pragma pack(1)
+struct SplitGuid
+{
+ DWORD dw1;
+ WORD w1;
+ WORD w2;
+ BYTE b[8];
+};
+#pragma pack()
+
+char *GuidText(GUID const *pguid)
+{
+ static char buf[39];
+ SplitGuid *psg = (SplitGuid *)pguid;
+
+ sprintf(buf, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
+ psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
+ return buf;
+}
diff --git a/private/ole32/stg/drt/util.hxx b/private/ole32/stg/drt/util.hxx
new file mode 100644
index 000000000..32c562cc0
--- /dev/null
+++ b/private/ole32/stg/drt/util.hxx
@@ -0,0 +1,44 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: util.hxx
+//
+// Contents: DRT support functions
+//
+// History: 22-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __UTIL_HXX__
+#define __UTIL_HXX__
+
+extern BOOL fExitOnFail;
+
+void SetData(void);
+void CleanData(void);
+void UnsetData(void);
+void out(char *fmt, ...);
+void error(int code, char *fmt, ...);
+char *OlecsOut(OLECHAR const *ptcs);
+char *ScText(SCODE sc);
+HRESULT Result(HRESULT hr);
+HRESULT IllResult(char *pszText, HRESULT hr);
+void CheckMemory(void);
+void SetDebug(ULONG ulDf, ULONG ulMsf);
+char *VerifyStructure(IStorage *pstg, char *pszStructure);
+char *CreateStructure(IStorage *pstg, char *pszStructure);
+void VerifyStat(STATSTG *pstat, OLECHAR *ptcsName, DWORD type, DWORD grfMode);
+BOOL Exists(OLECHAR *file);
+ULONG Length(OLECHAR *file);
+void ForceDirect(void);
+void ForceTransacted(void);
+void Unforce(void);
+BOOL IsEqualTime(FILETIME ttTime, FILETIME ttCheck);
+void GetFullPath(OLECHAR *file, OLECHAR *path);
+HRESULT drtMemAlloc(ULONG ulcb, void **ppv);
+void drtMemFree(void *pv);
+char *GuidText(GUID const *pguid);
+
+#endif // #ifndef __UTIL_HXX__
diff --git a/private/ole32/stg/drt/wrap.cxx b/private/ole32/stg/drt/wrap.cxx
new file mode 100644
index 000000000..2c3e4622b
--- /dev/null
+++ b/private/ole32/stg/drt/wrap.cxx
@@ -0,0 +1,684 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: wrap.cxx
+//
+// Contents: Wrapper implementations
+//
+// History: 22-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <dfentry.hxx>
+
+// Retrieve interface pointer for possibly NULL objects
+#define SAFEI(obj) ((obj) ? (obj)->GetI() : NULL)
+
+//+--------------------------------------------------------------
+//
+// IStorage wrappers
+//
+// History: 23-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+WStorage *WStorage::Wrap(IStorage *pistg)
+{
+ WStorage *wstg;
+
+ wstg = new WStorage(pistg);
+ if (wstg == NULL)
+ error(EXIT_OOM, "Unable to wrap IStorage\n");
+ return wstg;
+}
+
+WStorage::WStorage(IStorage *pstg)
+{
+ // Note: takes ownership of pstg
+ _pstg = pstg;
+}
+
+WStorage::~WStorage(void)
+{
+ if (_pstg)
+ Release();
+}
+
+void WStorage::Unwrap(void)
+{
+ delete this;
+}
+
+HRESULT WStorage::QueryInterface(REFIID riid, void **ppvObj)
+{
+ out("IStorage %p::QueryInterface(riid, %p)", _pstg, ppvObj);
+ return Result(_pstg->QueryInterface(riid, ppvObj));
+}
+
+ULONG WStorage::AddRef(void)
+{
+ ULONG ul;
+
+ ul = _pstg->AddRef();
+ out("IStorage %p::AddRef() - %lu\n", _pstg, ul);
+ return ul;
+}
+
+ULONG WStorage::Release(void)
+{
+ ULONG ul;
+
+ ul = _pstg->Release();
+ out("IStorage %p::Release() - %lu\n", _pstg, ul);
+ if (ul == 0)
+ _pstg = NULL;
+ return ul;
+}
+
+HRESULT WStorage::CreateStream(const OLECHAR * pwcsName,
+ const DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ WStream **ppstm)
+{
+ HRESULT hr;
+ IStream *pistm;
+
+ out("IStorage %p::CreateStream(%s, 0x%lX, %lu, %lu, %p)", _pstg,
+ OlecsOut(pwcsName), grfMode, reserved1, reserved2, ppstm);
+ hr = Result(_pstg->CreateStream(pwcsName, grfMode, reserved1,
+ reserved2, &pistm));
+ *ppstm = WStream::Wrap(pistm);
+ return hr;
+}
+
+HRESULT WStorage::OpenStream(const OLECHAR * pwcsName,
+ void *reserved1,
+ const DWORD grfMode,
+ DWORD reserved2,
+ WStream **ppstm)
+{
+ HRESULT hr;
+ IStream *pistm;
+
+ out("IStorage %p::OpenStream(%s, %p, 0x%lX, %lu, %p)", _pstg,
+ OlecsOut(pwcsName), reserved1, grfMode, reserved2, ppstm);
+ hr = Result(_pstg->OpenStream(pwcsName, reserved1, grfMode,
+ reserved2, &pistm));
+ *ppstm = WStream::Wrap(pistm);
+ return hr;
+}
+
+HRESULT WStorage::CreateStorage(const OLECHAR * pwcsName,
+ const DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ WStorage **ppstg)
+{
+ HRESULT hr;
+ IStorage *pistg;
+
+ out("IStorage %p::CreateStorage(%s, 0x%lX, %lu, %lu, %p)", _pstg,
+ OlecsOut(pwcsName), grfMode, reserved1, reserved2, ppstg);
+ hr = Result(_pstg->CreateStorage(pwcsName, grfMode, reserved1,
+ (LPSTGSECURITY)reserved2, &pistg));
+ *ppstg = WStorage::Wrap(pistg);
+ return hr;
+}
+
+HRESULT WStorage::OpenStorage(const OLECHAR * pwcsName,
+ WStorage *pstgPriority,
+ const DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ WStorage **ppstg)
+{
+ HRESULT hr;
+ IStorage *pistg;
+
+ out("IStorage %p::OpenStorage(%s, %p, 0x%lX, %p, %lu, %p)", _pstg,
+ OlecsOut(pwcsName), SAFEI(pstgPriority), grfMode,
+ snbExclude, reserved, ppstg);
+ hr = Result(_pstg->OpenStorage(pwcsName, SAFEI(pstgPriority),
+ grfMode, snbExclude,
+ reserved, &pistg));
+ *ppstg = WStorage::Wrap(pistg);
+ return hr;
+}
+
+HRESULT WStorage::CopyTo(DWORD ciidExclude,
+ IID *rgiidExclude,
+ SNB snbExclude,
+ WStorage *pstgDest)
+{
+ out("IStorage %p::CopyTo(%lu, %p, %p, %p)", _pstg, ciidExclude,
+ rgiidExclude, snbExclude, pstgDest->GetI());
+ return Result(_pstg->CopyTo(ciidExclude, rgiidExclude, snbExclude,
+ pstgDest->GetI()));
+}
+
+HRESULT WStorage::MoveElementTo(OLECHAR const FAR* lpszName,
+ WStorage FAR *pstgDest,
+ OLECHAR const FAR* lpszNewName,
+ DWORD grfFlags)
+{
+ out("IStorage %p::MoveElementTo(%p, %p, %p, %lu)", _pstg, lpszName,
+ pstgDest->GetI(), lpszNewName, grfFlags);
+ return Result(_pstg->MoveElementTo(lpszName, pstgDest->GetI(),
+ lpszNewName, grfFlags));
+}
+
+HRESULT WStorage::Commit(const DWORD grfCommitFlags)
+{
+ out("IStorage %p::Commit(0x%lX)", _pstg, grfCommitFlags);
+ return Result(_pstg->Commit(grfCommitFlags));
+}
+
+HRESULT WStorage::Revert(void)
+{
+ out("IStorage %p::Revert()", _pstg);
+ return Result(_pstg->Revert());
+}
+
+HRESULT WStorage::EnumElements(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ WEnumSTATSTG **ppenm)
+{
+ HRESULT hr;
+ IEnumSTATSTG *pienm;
+
+ out("IStorage %p::EnumElements(%lu, %p, %lu, %p)", _pstg,
+ reserved1, reserved2, reserved3, ppenm);
+ hr = Result(_pstg->EnumElements(reserved1, reserved2, reserved3, &pienm));
+ *ppenm = WEnumSTATSTG::Wrap(pienm);
+ return hr;
+}
+
+HRESULT WStorage::DestroyElement(const OLECHAR * pwcsName)
+{
+ out("IStorage %p::DestroyElement(%s)", _pstg, OlecsOut(pwcsName));
+ return Result(_pstg->DestroyElement(pwcsName));
+}
+
+HRESULT WStorage::RenameElement(const OLECHAR * pwcsOldName,
+ const OLECHAR * pwcsNewName)
+{
+ out("IStorage %p::RenameElement(%s, %s)", _pstg, OlecsOut(pwcsOldName),
+ OlecsOut(pwcsNewName));
+ return Result(_pstg->RenameElement(pwcsOldName, pwcsNewName));
+}
+
+HRESULT WStorage::SetElementTimes(const OLECHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ out("IStorage %p::SetElementTimes(%s, %p, %p, %p)", _pstg,
+ OlecsOut(lpszName), pctime, patime, pmtime);
+ return Result(_pstg->SetElementTimes(lpszName, pctime, patime, pmtime));
+}
+
+HRESULT WStorage::SetClass(REFCLSID clsid)
+{
+ out("IStorage %p::SetClass(%s)", _pstg, GuidText(&clsid));
+ return Result(_pstg->SetClass(clsid));
+}
+
+HRESULT WStorage::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ out("IStorage %p::SetStateBits(0x%lX, 0x%lX)", _pstg, grfStateBits,
+ grfMask);
+ return Result(_pstg->SetStateBits(grfStateBits, grfMask));
+}
+
+HRESULT WStorage::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ out("IStorage %p::Stat(%p, %lu)", _pstg, pstatstg, grfStatFlag);
+ return Result(_pstg->Stat(pstatstg, grfStatFlag));
+}
+
+//+--------------------------------------------------------------
+//
+// IStream wrappers
+//
+// History: 23-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+WStream *WStream::Wrap(IStream *pistm)
+{
+ WStream *wstm;
+
+ wstm = new WStream(pistm);
+ if (wstm == NULL)
+ error(EXIT_OOM, "Unable to wrap IStream\n");
+ return wstm;
+}
+
+WStream::WStream(IStream *pstm)
+{
+ // Note: takes ownership of pstm
+ _pstm = pstm;
+}
+
+WStream::~WStream(void)
+{
+ if (_pstm)
+ Release();
+}
+
+void WStream::Unwrap(void)
+{
+ delete this;
+}
+
+HRESULT WStream::QueryInterface(REFIID riid, void **ppvObj)
+{
+ out("IStream %p::QueryInterface(riid, %p)", _pstm, ppvObj);
+ return Result(_pstm->QueryInterface(riid, ppvObj));
+}
+
+ULONG WStream::AddRef(void)
+{
+ ULONG ul;
+
+ ul = _pstm->AddRef();
+ out("IStream %p::AddRef() - %lu\n", _pstm, ul);
+ return ul;
+}
+
+ULONG WStream::Release(void)
+{
+ ULONG ul;
+
+ ul = _pstm->Release();
+ out("IStream %p::Release() - %lu\n", _pstm, ul);
+ if (ul == 0)
+ _pstm = NULL;
+ return ul;
+}
+
+HRESULT WStream::Read(VOID *pv, ULONG cb, ULONG *pcbRead)
+{
+ HRESULT hr;
+
+ out("IStream %p::Read(%p, %lu, %p)", _pstm, pv, cb, pcbRead);
+ hr = _pstm->Read(pv, cb, pcbRead);
+ if (pcbRead)
+ out(" - %lu bytes", *pcbRead);
+ Result(hr);
+ if (pcbRead && *pcbRead != cb && fExitOnFail)
+ error(EXIT_BADSC, "Couldn't read data\n");
+ return hr;
+}
+
+HRESULT WStream::Write(VOID *pv, ULONG cb, ULONG *pcbWritten)
+{
+ HRESULT hr;
+
+ out("IStream %p::Write(%p, %lu, %p)", _pstm, pv, cb, pcbWritten);
+ hr = _pstm->Write(pv, cb, pcbWritten);
+ if (pcbWritten)
+ out(" - %lu bytes", *pcbWritten);
+ Result(hr);
+ if (pcbWritten && *pcbWritten != cb && fExitOnFail)
+ error(EXIT_BADSC, "Couldn't write data\n");
+ return hr;
+}
+
+HRESULT WStream::Seek(LONG dlibMove,
+ DWORD dwOrigin,
+ ULONG *plibNewPosition)
+{
+ HRESULT hr;
+ LARGE_INTEGER dlib;
+ ULARGE_INTEGER plib;
+
+ out("IStream %p::Seek(%ld, %lu, %p)", _pstm, dlibMove, dwOrigin,
+ plibNewPosition);
+ LISet32(dlib, dlibMove);
+ hr = _pstm->Seek(dlib, dwOrigin, &plib);
+ if (plibNewPosition)
+ {
+ *plibNewPosition = ULIGetLow(plib);
+ out(" - ptr %lu", *plibNewPosition);
+ }
+ return Result(hr);
+}
+
+HRESULT WStream::SetSize(ULONG libNewSize)
+{
+ ULARGE_INTEGER lib;
+
+ out("IStream %p::SetSize(%lu)", _pstm, libNewSize);
+ ULISet32(lib, libNewSize);
+ return Result(_pstm->SetSize(lib));
+}
+
+HRESULT WStream::Commit(const DWORD dwFlags)
+{
+ out("IStream %p:Commit(%lu)", _pstm, dwFlags);
+ return Result(_pstm->Commit(dwFlags));
+}
+
+HRESULT WStream::CopyTo(WStream *pstm,
+ ULONG cb,
+ ULONG *pcbRead,
+ ULONG *pcbWritten)
+{
+ ULARGE_INTEGER lcb, pcbr, pcbw;
+ HRESULT hr;
+
+ out("IStream %p::CopyTo(%p, %lu, %p, %p)", _pstm, pstm->GetI(), cb,
+ pcbRead, pcbWritten);
+ ULISet32(lcb, cb);
+ hr = Result(_pstm->CopyTo(pstm->GetI(), lcb, &pcbr, &pcbw));
+ if (pcbRead)
+ *pcbRead = ULIGetLow(pcbr);
+ if (pcbWritten)
+ *pcbWritten = ULIGetLow(pcbw);
+ return hr;
+}
+
+HRESULT WStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ out("IStream %p::Stat(%p, %lu)", _pstm, pstatstg, grfStatFlag);
+ return Result(_pstm->Stat(pstatstg, grfStatFlag));
+}
+
+HRESULT WStream::Clone(WStream * *ppstm)
+{
+ HRESULT hr;
+ IStream *pistm;
+
+ out("IStream %p::Clone(%p)", _pstm, ppstm);
+ hr = Result(_pstm->Clone(&pistm));
+ *ppstm = WStream::Wrap(pistm);
+ return hr;
+}
+
+//+--------------------------------------------------------------
+//
+// IEnumSTATSTG wrappers
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+WEnumSTATSTG *WEnumSTATSTG::Wrap(IEnumSTATSTG *pienm)
+{
+ WEnumSTATSTG *wenm;
+
+ wenm = new WEnumSTATSTG(pienm);
+ if (wenm == NULL)
+ error(EXIT_OOM, "Unable to wrap IEnumSTATSTG\n");
+ return wenm;
+}
+
+WEnumSTATSTG::WEnumSTATSTG(IEnumSTATSTG *penm)
+{
+ // Note: takes ownership of penm
+ _penm = penm;
+}
+
+WEnumSTATSTG::~WEnumSTATSTG(void)
+{
+ if (_penm)
+ Release();
+}
+
+void WEnumSTATSTG::Unwrap(void)
+{
+ delete this;
+}
+
+HRESULT WEnumSTATSTG::QueryInterface(REFIID riid, void **ppvObj)
+{
+ out("IEnumSTATSTG %p::QueryInterface(riid, %p)", _penm, ppvObj);
+ return Result(_penm->QueryInterface(riid, ppvObj));
+}
+
+ULONG WEnumSTATSTG::AddRef(void)
+{
+ ULONG ul;
+
+ ul = _penm->AddRef();
+ out("IEnumSTATSTG %p::AddRef() - %lu\n", _penm, ul);
+ return ul;
+}
+
+ULONG WEnumSTATSTG::Release(void)
+{
+ ULONG ul;
+
+ ul = _penm->Release();
+ out("IEnumSTATSTG %p::Release() - %lu\n", _penm, ul);
+ if (ul == 0)
+ _penm = NULL;
+ return ul;
+}
+
+HRESULT WEnumSTATSTG::Next(ULONG celt, STATSTG rgelt[], ULONG *pceltFetched)
+{
+ out("IEnumSTATSTG %p::Next(%lu, rgelt, %p)", _penm, celt, pceltFetched);
+ return Result(_penm->Next(celt, rgelt, pceltFetched));
+}
+
+HRESULT WEnumSTATSTG::Skip(ULONG celt)
+{
+ out("IEnumSTATSTG %p::Skip(%lu)", _penm, celt);
+ return Result(_penm->Skip(celt));
+}
+
+HRESULT WEnumSTATSTG::Reset(void)
+{
+ out("IEnumSTATSTG %p::Reset()", _penm);
+ return Result(_penm->Reset());
+}
+
+HRESULT WEnumSTATSTG::Clone(WEnumSTATSTG **ppenm)
+{
+ HRESULT hr;
+ IEnumSTATSTG *pienm;
+
+ out("IEnumSTATSTG %p::Clone(%p)", _penm, ppenm);
+ hr = Result(_penm->Clone(&pienm));
+ *ppenm = WEnumSTATSTG::Wrap(pienm);
+ return hr;
+}
+
+//+--------------------------------------------------------------
+//
+// IMarshal wrappers
+//
+// History: 23-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+WMarshal *WMarshal::Wrap(IMarshal *pimsh)
+{
+ WMarshal *wmsh;
+
+ wmsh = new WMarshal(pimsh);
+ if (wmsh == NULL)
+ error(EXIT_OOM, "Unable to wrap IMarshal\n");
+ return wmsh;
+}
+
+WMarshal::WMarshal(IMarshal *pmsh)
+{
+ // Note: takes ownership of pmsh
+ _pmsh = pmsh;
+}
+
+WMarshal::~WMarshal(void)
+{
+ if (_pmsh)
+ Release();
+}
+
+void WMarshal::Unwrap(void)
+{
+ delete this;
+}
+
+HRESULT WMarshal::QueryInterface(REFIID riid, void **ppvObj)
+{
+ out("IMarshal %p::QueryInterface(riid, %p)", _pmsh, ppvObj);
+ return Result(_pmsh->QueryInterface(riid, ppvObj));
+}
+
+ULONG WMarshal::AddRef(void)
+{
+ ULONG ul;
+
+ ul = _pmsh->AddRef();
+ out("IMarshal %p::AddRef() - %lu\n", _pmsh, ul);
+ return ul;
+}
+
+ULONG WMarshal::Release(void)
+{
+ ULONG ul;
+
+ ul = _pmsh->Release();
+ out("IMarshal %p::Release() - %lu\n", _pmsh, ul);
+ if (ul == 0)
+ _pmsh = NULL;
+ return ul;
+}
+
+HRESULT WMarshal::MarshalInterface(WStream * pStm,
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ out("IMarshal %p::MarshalInterface(%p, riid, %p, %lu, %lu, %lu)",
+ _pmsh, pStm->GetI(), pv, dwDestContext, pvDestContext, mshlflags);
+ return Result(_pmsh->MarshalInterface(pStm->GetI(), riid, pv,
+ dwDestContext,
+ pvDestContext,
+ mshlflags));
+}
+
+//+--------------------------------------------------------------
+//
+// Root level wrappers
+//
+// History: 23-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+HRESULT WStgCreateDocfile(const OLECHAR * pwcsName,
+ const DWORD grfMode,
+ DWORD reserved,
+ WStorage * *ppstgOpen)
+{
+ HRESULT hr;
+ IStorage *pistg;
+
+ out("StgCreateDocfile(%s, 0x%lX, %lu, %p)", OlecsOut(pwcsName), grfMode,
+ reserved, ppstgOpen);
+ hr = Result(StgCreateDocfile(pwcsName, grfMode,
+ reserved, &pistg));
+
+ *ppstgOpen = WStorage::Wrap(pistg);
+ return hr;
+}
+
+HRESULT WStgCreateDocfileOnILockBytes(ILockBytes *plkbyt,
+ const DWORD grfMode,
+ DWORD reserved,
+ WStorage * *ppstgOpen)
+{
+ HRESULT hr;
+ IStorage *pistg;
+
+ out("StgCreateDocfileOnILockBytes(%p, 0x%lX, %lu, %p)",
+ plkbyt, grfMode, reserved, ppstgOpen);
+ hr = Result(StgCreateDocfileOnILockBytes(plkbyt, grfMode,
+ reserved, &pistg));
+ *ppstgOpen = WStorage::Wrap(pistg);
+ return hr;
+}
+
+HRESULT WStgOpenStorage(const OLECHAR * pwcsName,
+ WStorage *pstgPriority,
+ const DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ WStorage * *ppstgOpen)
+{
+ HRESULT hr;
+ IStorage *pistg;
+
+ out("StgOpenStorage(%s, %p, 0x%lX, %p, %lu, %p)", OlecsOut(pwcsName),
+ SAFEI(pstgPriority), grfMode, snbExclude, reserved, ppstgOpen);
+ hr = Result(StgOpenStorage(pwcsName, SAFEI(pstgPriority), grfMode,
+ snbExclude,
+ reserved, &pistg));
+
+ *ppstgOpen = WStorage::Wrap(pistg);
+ return hr;
+}
+
+HRESULT WStgOpenStorageOnILockBytes(ILockBytes *plkbyt,
+ WStorage *pstgPriority,
+ const DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ WStorage * *ppstgOpen)
+{
+ HRESULT hr;
+ IStorage *pistg;
+
+ out("StgOpenStorageOnILockBytes(%p, %p, 0x%lX, %p, %lu, %p)",
+ plkbyt, SAFEI(pstgPriority), grfMode, snbExclude, reserved,
+ ppstgOpen);
+ hr = Result(StgOpenStorageOnILockBytes(plkbyt, SAFEI(pstgPriority),
+ grfMode, snbExclude, reserved,
+ &pistg));
+ *ppstgOpen = WStorage::Wrap(pistg);
+ return hr;
+}
+
+HRESULT WStgIsStorageFile(const OLECHAR * pwcsName)
+{
+ out("StgIsStorageFile(%s)", OlecsOut(pwcsName));
+ return Result(StgIsStorageFile(pwcsName));
+}
+
+HRESULT WStgIsStorageILockBytes(ILockBytes * plkbyt)
+{
+ out("StgIsStorageILockBytes(%p)", plkbyt);
+ return Result(StgIsStorageILockBytes(plkbyt));
+}
+
+HRESULT WCoMarshalInterface(WStream *pStm,
+ REFIID iid,
+ IUnknown *pUnk,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ out("CoMarshalInterface(%p, iid, %p, %lu, %p, %lX)", pStm->GetI(),
+ pUnk, dwDestContext, pvDestContext, mshlflags);
+ return Result(CoMarshalInterface(pStm->GetI(), iid, pUnk, dwDestContext,
+ pvDestContext, mshlflags));
+}
+
+HRESULT WCoUnmarshalInterface(WStream *pStm,
+ REFIID riid,
+ LPVOID *ppv)
+{
+ out("CoUnmarshalInterface(%p, iid, %p)", pStm->GetI(), ppv);
+ return Result(CoUnmarshalInterface(pStm->GetI(), riid, ppv));
+}
diff --git a/private/ole32/stg/drt/wrap.hxx b/private/ole32/stg/drt/wrap.hxx
new file mode 100644
index 000000000..487fa44b8
--- /dev/null
+++ b/private/ole32/stg/drt/wrap.hxx
@@ -0,0 +1,377 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: wrap.hxx
+//
+// Contents: Interface wrappers for test
+//
+// Classes: WStorage, WStream, WLockBytes, WEnmSTATSTG
+//
+// History: 22-Sep-92 DrewB Created
+//
+// Notes: These wrappers function in legitimate cases only,
+// they are not intended for testing illegitimate
+// calls.
+// QueryInterface does not return wrapped objects.
+//
+//---------------------------------------------------------------
+
+#ifndef __WRAP_HXX__
+#define __WRAP_HXX__
+
+/* Storage instantiation modes */
+#define WSTG_DIRECT 0x00000000L
+#define WSTG_TRANSACTED 0x00010000L
+
+#define WSTG_READ 0x00000000L
+#define WSTG_WRITE 0x00000001L
+#define WSTG_READWRITE 0x00000002L
+
+#define WSTG_SHARE_DENY_NONE 0x00000040L
+#define WSTG_SHARE_DENY_READ 0x00000030L
+#define WSTG_SHARE_DENY_WRITE 0x00000020L
+#define WSTG_SHARE_EXCLUSIVE 0x00000010L
+
+#define WSTG_PRIORITY 0x00040000L
+#define WSTG_DELETEONRELEASE 0x04000000L
+
+#define WSTG_CREATE 0x00001000L
+#define WSTG_CONVERT 0x00020000L
+#define WSTG_FAILIFTHERE 0x00000000L
+
+/* Storage commit types */
+typedef enum
+{
+ WSTGC_OVERWRITE = 1,
+ WSTGC_ONLYIFCURRENT = 2
+} WSTGC;
+
+typedef enum
+{
+ WSTM_SEEK_SET = 0,
+ WSTM_SEEK_CUR = 1,
+ WSTM_SEEK_END = 2
+} WSTMS;
+
+typedef enum
+{
+ WLOCK_WRITE = 1,
+ WLOCK_EXCLUSIVE = 2,
+ WLOCK_ONLYONCE = 3
+} WLOCKTYPE;
+
+//+--------------------------------------------------------------
+//
+// Class: WUnknown
+//
+// Purpose: Replacement for IUnknown
+//
+// History: 22-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+interface WUnknown
+{
+public:
+ virtual HRESULT QueryInterface(REFIID riid, LPVOID * ppvObj) = 0;
+ virtual ULONG AddRef(void) = 0;
+ virtual ULONG Release(void) = 0;
+};
+
+//+--------------------------------------------------------------
+//
+// Class: WEnumSTATSTG
+//
+// Purpose: Wrapper for IEnumSTATSTG
+//
+// History: 22-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+interface WEnumSTATSTG : public WUnknown
+{
+public:
+ WEnumSTATSTG(IEnumSTATSTG *penm);
+ ~WEnumSTATSTG(void);
+
+ IEnumSTATSTG *GetI(void) { return _penm; }
+ static WEnumSTATSTG *Wrap(IEnumSTATSTG *penm);
+ void Unwrap(void);
+
+ virtual HRESULT QueryInterface(REFIID riid, LPVOID * ppvObj);
+ virtual ULONG AddRef(void);
+ virtual ULONG Release(void);
+
+ HRESULT Next(ULONG celt, STATSTG rgelt[], ULONG *pceltFetched);
+ HRESULT Skip(ULONG celt);
+ HRESULT Reset(void);
+ HRESULT Clone(WEnumSTATSTG **ppenm);
+
+private:
+ IEnumSTATSTG *_penm;
+};
+
+//+--------------------------------------------------------------
+//
+// Class: WLockBytes
+//
+// Purpose: Wrapper for ILockBytes
+//
+// History: 22-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+interface WLockBytes : public WUnknown
+{
+public:
+ WLockBytes(ILockBytes *plkb);
+ ~WLockBytes(void);
+
+ ILockBytes *GetI(void) { return _plkb; }
+ static WLockBytes Wrap(ILockBytes *plkb);
+ void Unwrap(void);
+
+ virtual HRESULT QueryInterface(REFIID riid, LPVOID * ppvObj);
+ virtual ULONG AddRef(void);
+ virtual ULONG Release(void);
+
+ HRESULT ReadAt(ULONG ulOffset,
+ VOID *pv,
+ ULONG cb,
+ ULONG *pcbRead);
+ HRESULT WriteAt(ULONG ulOffset,
+ VOID *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ HRESULT Flush(void);
+ HRESULT GetSize(ULONG *pcb);
+ HRESULT SetSize(ULONG cb);
+ HRESULT LockRegion(ULONG libOffset,
+ ULONG cb,
+ DWORD dwLockType);
+ HRESULT UnlockRegion(ULONG libOffset,
+ ULONG cb,
+ DWORD dwLockType);
+ HRESULT Stat(STATSTG *pstatstg, DWORD grfStatFlag);
+
+private:
+ ILockBytes *_plkb;
+};
+
+//+--------------------------------------------------------------
+//
+// Class: WMarshal
+//
+// Purpose: Wrapper for IMarshal
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+interface WStream;
+
+interface WMarshal : public WUnknown
+{
+public:
+ WMarshal(IMarshal *pmsh);
+ ~WMarshal(void);
+
+ IMarshal *GetI(void) { return _pmsh; }
+ static WMarshal *Wrap(IMarshal *pmsh);
+ void Unwrap(void);
+
+ virtual HRESULT QueryInterface(REFIID riid, LPVOID * ppvObj);
+ virtual ULONG AddRef(void);
+ virtual ULONG Release(void);
+
+ HRESULT GetUnmarshalClass(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ CLSID * pCid);
+ HRESULT GetMarshalSizeMax(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ DWORD * pSize);
+ HRESULT MarshalInterface(WStream * pStm,
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags);
+ HRESULT UnmarshalInterface(WStream * pStm,
+ REFIID riid,
+ LPVOID * ppv);
+ HRESULT ReleaseMarshalData(WStream * pStm);
+ HRESULT DisconnectObject(DWORD dwReserved);
+
+private:
+ IMarshal *_pmsh;
+};
+
+//+--------------------------------------------------------------
+//
+// Class: WStream
+//
+// Purpose: Wrapper for IStream
+//
+// History: 22-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+interface WStream : public WUnknown
+{
+public:
+ WStream(IStream *pstm);
+ ~WStream(void);
+
+ IStream *GetI(void) { return _pstm; }
+ static WStream *Wrap(IStream *pstm);
+ void Unwrap(void);
+
+ virtual HRESULT QueryInterface(REFIID riid, LPVOID * ppvObj);
+ virtual ULONG AddRef(void);
+ virtual ULONG Release(void);
+
+ HRESULT Read(VOID *pv, ULONG cb, ULONG *pcbRead);
+ HRESULT Write(VOID *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ HRESULT Seek(LONG dlibMove,
+ DWORD dwOrigin,
+ ULONG *plibNewPosition);
+ HRESULT SetSize(ULONG libNewSize);
+ HRESULT CopyTo(WStream *pstm,
+ ULONG cb,
+ ULONG *pcbRead,
+ ULONG *pcbWritten);
+ HRESULT Commit(const DWORD grfCommitFlags);
+ HRESULT Revert(void);
+ HRESULT LockRegion(ULONG libOffset,
+ ULONG cb,
+ const DWORD dwLockType);
+ HRESULT UnlockRegion(ULONG libOffset,
+ ULONG cb,
+ const DWORD dwLockType);
+ HRESULT Stat(STATSTG *pstatstg, DWORD grfStatFlag);
+ HRESULT Clone(WStream * *ppstm);
+
+private:
+ IStream *_pstm;
+};
+
+//+--------------------------------------------------------------
+//
+// Class: WStorage
+//
+// Purpose: Wrapper for IStorage
+//
+// History: 22-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+interface WStorage : public WUnknown
+{
+public:
+ WStorage(IStorage *pstg);
+ ~WStorage(void);
+
+ IStorage *GetI(void) { return _pstg; }
+ static WStorage *Wrap(IStorage *pstg);
+ void Unwrap(void);
+
+ virtual HRESULT QueryInterface(REFIID riid, LPVOID * ppvObj);
+ virtual ULONG AddRef(void);
+ virtual ULONG Release(void);
+
+ HRESULT CreateStream(const OLECHAR * pwcsName,
+ const DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ WStream **ppstm);
+ HRESULT OpenStream(const OLECHAR * pwcsName,
+ void *reserved1,
+ const DWORD grfMode,
+ DWORD reserved2,
+ WStream **ppstm);
+ HRESULT CreateStorage(const OLECHAR * pwcsName,
+ const DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ WStorage **ppstg);
+ HRESULT OpenStorage(const OLECHAR * pwcsName,
+ WStorage *pstgPriority,
+ const DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ WStorage **ppstg);
+ HRESULT CopyTo(DWORD ciidExclude,
+ IID *rgiidExclude,
+ SNB snbExclude,
+ WStorage *pstgDest);
+ HRESULT MoveElementTo(OLECHAR const FAR* lpszName,
+ WStorage FAR *pstgDest,
+ OLECHAR const FAR* lpszNewName,
+ DWORD grfFlags);
+ HRESULT Commit(const DWORD grfCommitFlags);
+ HRESULT Revert(void);
+ HRESULT EnumElements(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ WEnumSTATSTG **ppenm);
+ HRESULT DestroyElement(const OLECHAR * pwcsName);
+ HRESULT RenameElement(const OLECHAR * pwcsOldName,
+ const OLECHAR * pwcsNewName);
+ HRESULT SetElementTimes(const OLECHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+ HRESULT SetClass(REFCLSID clsid);
+ HRESULT SetStateBits(DWORD grfStateBits, DWORD grfMask);
+ HRESULT Stat(STATSTG *pstatstg, DWORD grfStatFlag);
+
+private:
+ IStorage *_pstg;
+};
+
+/****** Storage API Prototypes ********************************************/
+
+HRESULT WStgCreateDocfile(const OLECHAR * pwcsName,
+ const DWORD grfMode,
+ DWORD reserved,
+ WStorage * *ppstgOpen);
+HRESULT WStgCreateDocfileOnILockBytes(ILockBytes *plkbyt,
+ const DWORD grfMode,
+ DWORD reserved,
+ WStorage * *ppstgOpen);
+HRESULT WStgOpenStorage(const OLECHAR * pwcsName,
+ WStorage *pstgPriority,
+ const DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ WStorage * *ppstgOpen);
+HRESULT WStgOpenStorageOnILockBytes(ILockBytes *plkbyt,
+ WStorage *pstgPriority,
+ const DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ WStorage * *ppstgOpen);
+HRESULT WStgIsStorageFile(const OLECHAR * pwcsName);
+HRESULT WStgIsStorageILockBytes(ILockBytes * plkbyt);
+
+HRESULT WCoMarshalInterface(WStream *pStm,
+ REFIID iid,
+ IUnknown *pUnk,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags);
+HRESULT WCoUnmarshalInterface(WStream *pStm,
+ REFIID riid,
+ LPVOID *ppv);
+
+#endif // #ifndef __WRAP_HXX__
diff --git a/private/ole32/stg/exp/ascii.cxx b/private/ole32/stg/exp/ascii.cxx
new file mode 100644
index 000000000..4ad3730ad
--- /dev/null
+++ b/private/ole32/stg/exp/ascii.cxx
@@ -0,0 +1,795 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: ascii.cxx
+//
+// Contents: char to WCHAR conversion layer
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <expdf.hxx>
+#include <expiter.hxx>
+#include <expst.hxx>
+#include <ascii.hxx>
+
+// If OLEWIDECHAR is defined, none of this is necessary
+#ifndef OLEWIDECHAR
+
+//+--------------------------------------------------------------
+//
+// Function: ValidateSNBA, private
+//
+// Synopsis: Validates a char SNB
+//
+// Arguments: [snb] - SNB
+//
+// Returns: Appropriate status code
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_ValidateSNBA)
+#endif
+
+static SCODE ValidateSNBA(SNB snb)
+{
+ SCODE sc;
+
+ for (;;)
+ {
+ olChk(ValidatePtrBuffer(snb));
+ if (*snb == NULL)
+ break;
+ olChk(ValidateNameA(*snb, CBMAXPATHCOMPLEN));
+ snb++;
+ }
+ return S_OK;
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: SNBToSNBW, private
+//
+// Synopsis: Converts a char SNB to a WCHAR SNB
+//
+// Arguments: [snbIn] - char SNB
+// [psnbwOut] - WCHAR SNB return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [psnbwOut]
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_SNBToSNBW)
+#endif
+
+static SCODE SNBToSNBW(SNB snbIn, SNBW *psnbwOut)
+{
+ ULONG cbStrings = 0;
+ SNB snb;
+ ULONG cItems = 0;
+ SNBW snbw, snbwOut;
+ WCHAR *pwcs;
+ BYTE *pb;
+ SCODE sc;
+
+ for (snb = snbIn; *snb; snb++, cItems++)
+ cbStrings += (strlen(*snb)+1)*sizeof(WCHAR);
+ cItems++;
+
+ olMem(pb = (BYTE *) DfMemAlloc(cbStrings+sizeof(WCHAR *)*cItems));
+
+ snbwOut = (SNBW)pb;
+ pwcs = (WCHAR *)(pb+sizeof(WCHAR *)*cItems);
+ for (snb = snbIn, snbw = snbwOut; *snb; snb++, snbw++)
+ {
+ *snbw = pwcs;
+ if (mbstowcs(*snbw, *snb, strlen(*snb)+1) == (size_t)-1)
+ olErr(EH_pb, STG_E_INVALIDNAME);
+ pwcs += wcslen(*snbw)+1;
+ }
+ *snbw = NULL;
+ *psnbwOut = snbwOut;
+ return S_OK;
+
+ EH_pb:
+ DfMemFree(pb);
+ EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: FreeSNBW, private
+//
+// Synopsis: Free an SNBW
+//
+// Arguments: [snbw] - WCHAR SNB
+//
+// History: 26-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline static void FreeSNBW(SNBW snbw)
+{
+ DfMemFree(snbw);
+}
+
+//+--------------------------------------------------------------
+//
+// Function: CheckAName, public
+//
+// Synopsis: Checks name for illegal characters and length
+//
+// Arguments: [pwcsName] - Name
+//
+// Returns: Appropriate status code
+//
+// History: 11-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CheckAName)
+#endif
+
+#define INVALIDCHARS "\\/:!"
+
+SCODE CheckAName(char const *pwcsName)
+{
+ SCODE sc;
+ olDebugOut((DEB_ITRACE, "In CheckAName(%s)\n", pwcsName));
+ if (FAILED(sc = ValidateNameA(pwcsName, CBMAXPATHCOMPLEN)))
+ return sc;
+ // >= is used because the max len includes the null terminator
+ if (strlen(pwcsName) >= CWCMAXPATHCOMPLEN)
+ return STG_E_INVALIDNAME;
+ for (; *pwcsName; pwcsName = AnsiNext(pwcsName))
+ if (*pwcsName == '\\' || *pwcsName == '/' || *pwcsName == ':' ||
+ *pwcsName == '!')
+ return STG_E_INVALIDNAME;
+ olDebugOut((DEB_ITRACE, "Out CheckAName\n"));
+ return S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::Next, public
+//
+// Synopsis: char version
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CEI_NextA)
+#endif
+
+STDMETHODIMP CExposedIterator::Next(ULONG celt,
+ STATSTG FAR *rgelt,
+ ULONG *pceltFetched)
+{
+ SCODE sc;
+ ULONG i;
+ ULONG cnt;
+ CDfName dfnInitial;
+ char achName[CWCSTORAGENAME];
+
+ olAssert(sizeof(STATSTG) == sizeof(STATSTGW));
+
+ if (pceltFetched)
+ {
+ olChk(ValidateBuffer(pceltFetched, sizeof(ULONG)));
+ *pceltFetched = 0;
+ }
+ if (pceltFetched == NULL && celt > 1)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olAssert(0xffffUL/sizeof(STATSTGW) >= celt);
+ olChkTo(EH_Err, ValidateOutBuffer(rgelt,
+ (size_t)(sizeof(STATSTGW)*celt)));
+ memset(rgelt, 0, (size_t)(sizeof(STATSTGW)*celt));
+
+ cnt = 0;
+ dfnInitial.Set(&_dfnKey);
+ sc = S_OK;
+ while (cnt < celt)
+ {
+ sc = Next(1, (STATSTGW *)&rgelt[cnt], NULL);
+ if (sc == S_FALSE)
+ break;
+ else if (FAILED(sc))
+ olErr(EH_rgelt, sc);
+
+ // Skip untranslatable names
+ if (wcstombs(achName, (WCHAR *)rgelt[cnt].pwcsName,
+ CWCSTORAGENAME) == (size_t)-1)
+ {
+ TaskMemFree(rgelt[cnt].pwcsName);
+ }
+ else
+ {
+ strcpy(rgelt[cnt].pwcsName, achName);
+ cnt++;
+ }
+ }
+ if (pceltFetched)
+ *pceltFetched = cnt;
+
+ EH_Err:
+ return ResultFromScode(sc);
+
+ EH_rgelt:
+ _dfnKey.Set(&dfnInitial);
+ for (i = 0; i < cnt; i++)
+ TaskMemFree(rgelt[i].pwcsName);
+ memset(rgelt, 0, (size_t)(sizeof(STATSTGW)*celt));
+ goto EH_Err;
+}
+
+#ifndef REF
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::Stat, public
+//
+// Synopsis: char version
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_StatA)
+#endif
+
+STDMETHODIMP CFileStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+ char achName[_MAX_PATH];
+
+ olAssert(sizeof(STATSTG) == sizeof(STATSTGW));
+
+ olChk(sc = Stat((STATSTGW *)pstatstg, grfStatFlag));
+ if (pstatstg->pwcsName)
+ if (wcstombs(achName, (WCHAR *)pstatstg->pwcsName,
+ _MAX_PATH) == (size_t)-1)
+ {
+ TaskMemFree(pstatstg->pwcsName);
+ sc = STG_E_INVALIDNAME;
+ }
+ else
+ {
+ strcpy(pstatstg->pwcsName, achName);
+ }
+EH_Err:
+ return ResultFromScode(sc);
+}
+#endif //!REF
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Stat, public
+//
+// Synopsis: char version
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CES_StatA)
+#endif
+
+STDMETHODIMP CExposedStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+ char achName[CWCSTORAGENAME];
+
+ olAssert(sizeof(STATSTG) == sizeof(STATSTGW));
+
+ olChk(sc = Stat((STATSTGW *)pstatstg, grfStatFlag));
+ if (pstatstg->pwcsName)
+ if (wcstombs(achName, (WCHAR *)pstatstg->pwcsName,
+ CWCSTORAGENAME) == (size_t)-1)
+ {
+ TaskMemFree(pstatstg->pwcsName);
+ sc = STG_E_INVALIDNAME;
+ }
+ else
+ {
+ strcpy(pstatstg->pwcsName, achName);
+ }
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::Stat, public
+//
+// Synopsis: char version
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CED_StatA)
+#endif
+
+STDMETHODIMP CExposedDocFile::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+ char achName[_MAX_PATH];
+
+ olAssert(sizeof(STATSTG) == sizeof(STATSTGW));
+
+ olChk(sc = Stat((STATSTGW *)pstatstg, grfStatFlag));
+ if (pstatstg->pwcsName)
+ if (wcstombs(achName, (WCHAR *)pstatstg->pwcsName,
+ _MAX_PATH) == (size_t)-1)
+ {
+ TaskMemFree(pstatstg->pwcsName);
+ sc = STG_E_INVALIDNAME;
+ }
+ else
+ {
+ strcpy(pstatstg->pwcsName, achName);
+ }
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CreateStream, public
+//
+// Synopsis: char version
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CED_CreateStreamA)
+#endif
+
+STDMETHODIMP CExposedDocFile::CreateStream(char const *pszName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+ WCHAR wcsName[CWCSTORAGENAME];
+
+ olChk(ValidateOutPtrBuffer(ppstm));
+ *ppstm = NULL;
+ olChk(CheckAName(pszName));
+ if (mbstowcs(wcsName, pszName, CWCSTORAGENAME) == (size_t)-1)
+ olErr(EH_Err, STG_E_INVALIDNAME);
+ sc = CreateStream(wcsName, grfMode, reserved1, reserved2, ppstm);
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::OpenStream, public
+//
+// Synopsis: char version
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CED_OpenStreamA)
+#endif
+
+STDMETHODIMP CExposedDocFile::OpenStream(char const *pszName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+ WCHAR wcsName[CWCSTORAGENAME];
+
+ olChk(ValidateOutPtrBuffer(ppstm));
+ *ppstm = NULL;
+ olChk(CheckAName(pszName));
+ if (mbstowcs(wcsName, pszName, CWCSTORAGENAME) == (size_t)-1)
+ olErr(EH_Err, STG_E_INVALIDNAME);
+ sc = OpenStream(wcsName, reserved1, grfMode, reserved2, ppstm);
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CreateStorage, public
+//
+// Synopsis: char version
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CED_CreateStorageA)
+#endif
+
+STDMETHODIMP CExposedDocFile::CreateStorage(char const *pszName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ WCHAR wcsName[CWCSTORAGENAME];
+
+ olChk(ValidateOutPtrBuffer(ppstg));
+ *ppstg = NULL;
+ olChk(CheckAName(pszName));
+ if (mbstowcs(wcsName, pszName, CWCSTORAGENAME) == (size_t)-1)
+ olErr(EH_Err, STG_E_INVALIDNAME);
+ sc = CreateStorage(wcsName, grfMode, reserved1, reserved2, ppstg);
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::OpenStorage, public
+//
+// Synopsis: char version
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CED_OpenStorageA)
+#endif
+
+STDMETHODIMP CExposedDocFile::OpenStorage(char const *pszName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+{
+ SNBW snbw;
+ SCODE sc;
+ WCHAR wcsName[CWCSTORAGENAME];
+
+ olChk(ValidateOutPtrBuffer(ppstg));
+ *ppstg = NULL;
+ olChk(CheckAName(pszName));
+ if (mbstowcs(wcsName, pszName, CWCSTORAGENAME) == (size_t)-1)
+ olErr(EH_Err, STG_E_INVALIDNAME);
+ if (snbExclude)
+ {
+#ifdef INTERNAL_EXCLUSION_ALLOWED
+ olChk(ValidateSNBA(snbExclude));
+ olChk(SNBToSNBW(snbExclude, &snbw));
+#else
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+#endif
+ }
+ else
+ snbw = NULL;
+ sc = OpenStorage(wcsName, pstgPriority, grfMode, snbw,
+ reserved, ppstg);
+ FreeSNBW(snbw);
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::DestroyElement, public
+//
+// Synopsis: char version
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CED_DestroyElementA)
+#endif
+
+STDMETHODIMP CExposedDocFile::DestroyElement(char const *pszName)
+{
+ SCODE sc;
+ WCHAR wcsName[CWCSTORAGENAME];
+
+ olChk(CheckAName(pszName));
+ if (mbstowcs(wcsName, pszName, CWCSTORAGENAME) == (size_t)-1)
+ olErr(EH_Err, STG_E_INVALIDNAME);
+ sc = DestroyElement(wcsName);
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::RenameElement, public
+//
+// Synopsis: char version
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CED_RenameElementA)
+#endif
+
+STDMETHODIMP CExposedDocFile::RenameElement(char const *pszOldName,
+ char const *pszNewName)
+{
+ SCODE sc;
+ WCHAR wcsOldName[CWCSTORAGENAME], wcsNewName[CWCSTORAGENAME];
+
+ olChk(CheckAName(pszOldName));
+ olChk(CheckAName(pszNewName));
+ if (mbstowcs(wcsOldName, pszOldName, CWCSTORAGENAME) == (size_t)-1)
+ olErr(EH_Err, STG_E_INVALIDNAME);
+ if (mbstowcs(wcsNewName, pszNewName, CWCSTORAGENAME) == (size_t)-1)
+ olErr(EH_Err, STG_E_INVALIDNAME);
+ sc = RenameElement(wcsOldName, wcsNewName);
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CopyTo, public
+//
+// Synopsis: ANSI version
+//
+// History: 29-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CED_CopyToA)
+#endif
+
+STDMETHODIMP CExposedDocFile::CopyTo(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest)
+{
+ SNBW snbw;
+ SCODE sc;
+
+ if (snbExclude)
+ {
+ olChk(ValidateSNBA(snbExclude));
+ olChk(SNBToSNBW(snbExclude, &snbw));
+ }
+ else
+ snbw = NULL;
+ sc = CopyTo(ciidExclude, rgiidExclude, snbw, pstgDest);
+ FreeSNBW(snbw);
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::MoveElementTo, public
+//
+// Synopsis: ANSI version
+//
+// History: 05-Oct-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CED_MoveElementToA)
+#endif
+
+STDMETHODIMP CExposedDocFile::MoveElementTo(TCHAR const *lpszName,
+ IStorage *pstgDest,
+ TCHAR const *lpszNewName,
+ DWORD grfFlags)
+{
+ SCODE sc;
+ WCHAR wcsName[CWCSTORAGENAME];
+
+ olChk(CheckAName(lpszName));
+ if (mbstowcs(wcsName, lpszName, CWCSTORAGENAME) == (size_t)-1)
+ olErr(EH_Err, STG_E_INVALIDNAME);
+ sc = MoveElementTo(wcsName, pstgDest, lpszNewName, grfFlags);
+
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::SetElementTimes, public
+//
+// Synopsis: ANSI version
+//
+// History: 05-Oct-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CED_SetElementTimesA)
+#endif
+
+STDMETHODIMP CExposedDocFile::SetElementTimes(TCHAR const *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ SCODE sc;
+ WCHAR wcsName[CWCSTORAGENAME];
+
+ olChk(CheckAName(lpszName));
+ if (mbstowcs(wcsName, lpszName, CWCSTORAGENAME) == (size_t)-1)
+ olErr(EH_Err, STG_E_INVALIDNAME);
+ sc = SetElementTimes(wcsName, pctime, patime, pmtime);
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Function: StgCreateDocfile, public
+//
+// Synopsis: char version
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_StgCreateDocfileA)
+#endif
+
+STDAPI StgCreateDocfile(char const *pszName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage **ppstgOpen)
+{
+#ifndef REF
+ SCODE sc;
+ WCHAR wcsBuffer[_MAX_PATH], *pwcs;
+
+ olChk(ValidatePtrBuffer(ppstgOpen));
+ *ppstgOpen = NULL;
+ if (pszName)
+ {
+ olChk(ValidateNameA(pszName, _MAX_PATH));
+ if (mbstowcs(wcsBuffer, pszName, _MAX_PATH) == (size_t)-1)
+ olErr(EH_Err, STG_E_INVALIDNAME);
+ pwcs = wcsBuffer;
+ }
+ else
+ pwcs = NULL;
+ sc = StgCreateDocfileW(pwcs, grfMode, reserved, ppstgOpen);
+EH_Err:
+ return ResultFromScode(sc);
+#else
+ return ResultFromScode(STG_E_UNIMPLEMENTEDFUNCTION);
+#endif //!REF
+}
+
+#ifndef REF
+//+--------------------------------------------------------------
+//
+// Function: OpenStorage, public
+//
+// Synopsis: char version
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_OpenStorageA)
+#endif
+
+SCODE OpenStorage(char const *pszName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstgOpen,
+ CLSID *pcid)
+{
+ SNBW snbw;
+ SCODE sc;
+ WCHAR wcsBuffer[_MAX_PATH];
+
+ olChk(ValidatePtrBuffer(ppstgOpen));
+ *ppstgOpen = NULL;
+ olChk(ValidateNameA(pszName, _MAX_PATH));
+ if (mbstowcs(wcsBuffer, pszName, _MAX_PATH) == (size_t)-1)
+ olErr(EH_Err, STG_E_INVALIDNAME);
+ if (snbExclude)
+ {
+ olChk(ValidateSNBA(snbExclude));
+ olChk(SNBToSNBW(snbExclude, &snbw));
+ }
+ else
+ snbw = NULL;
+ sc = OpenStorageW(wcsBuffer, pstgPriority, grfMode, snbw,
+ reserved, ppstgOpen, pcid);
+ FreeSNBW(snbw);
+EH_Err:
+ return sc;
+}
+#endif //!REF
+
+//+--------------------------------------------------------------
+//
+// Function: OpenStorageOnILockBytes, public
+//
+// Synopsis: char version
+//
+// History: 11-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_OpenStorageOnILockBytesA)
+#endif
+
+SCODE OpenStorageOnILockBytes(ILockBytes *plkbyt,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstgOpen,
+ CLSID *pcid)
+{
+ SNBW snbw;
+ SCODE sc;
+
+ olChk(ValidatePtrBuffer(ppstgOpen));
+ *ppstgOpen = NULL;
+ if (snbExclude)
+ {
+ olChk(ValidateSNBA(snbExclude));
+ olChk(SNBToSNBW(snbExclude, &snbw));
+ }
+ else
+ snbw = NULL;
+ sc = OpenStorageOnILockBytesW(plkbyt, pstgPriority, grfMode,
+ snbw, reserved, ppstgOpen, pcid);
+ FreeSNBW(snbw);
+EH_Err:
+ return sc;
+}
+
+#endif // #ifndef OLEWIDECHAR
diff --git a/private/ole32/stg/exp/ascii.hxx b/private/ole32/stg/exp/ascii.hxx
new file mode 100644
index 000000000..72eb59337
--- /dev/null
+++ b/private/ole32/stg/exp/ascii.hxx
@@ -0,0 +1,40 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: ascii.hxx
+//
+// Contents: WCHAR header for ASCII layer
+//
+// History: 23-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __ASCII_HXX__
+#define __ASCII_HXX__
+
+#ifndef OLEWIDECHAR
+#ifndef REF
+SCODE StgCreateDocfileW(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage **ppstgOpen);
+SCODE OpenStorageW(WCHAR const *pszName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNBW snbExclude,
+ DWORD reserved,
+ IStorage **ppstgOpen,
+ CLSID *pcid);
+#endif //!REF
+SCODE OpenStorageOnILockBytesW(ILockBytes *plkbyt,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNBW snbExclude,
+ DWORD reserved,
+ IStorage **ppstgOpen,
+ CLSID *pcid);
+#endif
+
+#endif // #ifndef __ASCII_HXX__
diff --git a/private/ole32/stg/exp/astgconn.cxx b/private/ole32/stg/exp/astgconn.cxx
new file mode 100644
index 000000000..39b02f3e6
--- /dev/null
+++ b/private/ole32/stg/exp/astgconn.cxx
@@ -0,0 +1,606 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1996 - 1996.
+//
+// File: astgconn.cxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 03-Apr-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "exphead.cxx"
+#pragma hdrstop
+
+#include "astgconn.hxx"
+#include <filllkb.hxx>
+#include <asyncerr.hxx>
+
+
+SCODE CAsyncConnection::Init(IConnectionPointContainer *pCPC,
+ CAsyncConnection *pacParent)
+{
+ SCODE sc = S_OK;
+ CConnectionPoint *pcpoint;
+ olAssert(_pdacp == NULL);
+
+ if (pacParent)
+ _dwAsyncFlags = pacParent->_dwAsyncFlags;
+
+ olMem(pcpoint = new CConnectionPoint());
+ if ((pacParent) && (_dwAsyncFlags & ASYNC_MODE_COMPATIBILITY))
+ {
+ pcpoint->SetParent(pacParent->_pdacp);
+ }
+ else
+ {
+ pcpoint->SetParent(NULL);
+ }
+
+ _pCPC = pCPC;
+ _pdacp = pcpoint;
+EH_Err:
+ return sc;
+}
+
+
+SCODE CAsyncConnection::InitClone(IConnectionPointContainer *pCPC,
+ CAsyncConnection *pac)
+{
+ SCODE sc = S_OK;
+ CConnectionPoint *pcpoint;
+ olAssert(pac != NULL);
+
+ _dwAsyncFlags = pac->_dwAsyncFlags;
+
+ olMem(pcpoint = new CConnectionPoint());
+ if (_dwAsyncFlags & ASYNC_MODE_COMPATIBILITY)
+ {
+ IDocfileAsyncConnectionPoint *pdacp;
+ if (FAILED(sc = pac->_pdacp->GetParent(&pdacp)))
+ {
+ delete pcpoint;
+ return sc;
+ }
+ pcpoint->SetParent(pdacp);
+ }
+ else
+ {
+ pcpoint->SetParent(NULL);
+ }
+
+ _pCPC = pCPC;
+ _pdacp = pcpoint;
+EH_Err:
+ return sc;
+}
+
+SCODE CAsyncConnection::InitMarshal(IConnectionPointContainer *pCPC,
+ DWORD dwAsyncFlags,
+ IDocfileAsyncConnectionPoint *pdacp)
+{
+ SCODE sc = S_OK;
+ _dwAsyncFlags = dwAsyncFlags;
+
+ _pCPC = pCPC;
+ _pdacp = pdacp;
+ if (_pdacp)
+ _pdacp->AddRef();
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncConnection::~CAsyncConnection, public
+//
+// Synopsis: Destructor
+//
+// Returns: Appropriate status code
+//
+// History: 03-Apr-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CAsyncConnection::~CAsyncConnection()
+{
+ olDebugOut((DEB_ITRACE,
+ "In CAsyncConnection::~CAsyncConnection:%p()\n", this));
+ //Note: _pdacp must be released outside of the tree mutex, which
+ // means we need to extract the pointer and release it elsewhere.
+#if 0
+ if (_pdacp != NULL)
+ {
+ _pdacp->Release();
+ }
+#endif
+ olDebugOut((DEB_ITRACE,
+ "Out CAsyncConnection::~CAsyncConnection\n"));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncConnection::QueryInterface, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 01-Jan-96 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncConnection::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc = S_OK;
+ olDebugOut((DEB_TRACE,
+ "In CAsyncConnection::QueryInterface:%p()\n",
+ this));
+
+ *ppvObj = NULL;
+
+ if ((IsEqualIID(iid, IID_IUnknown)) ||
+ (IsEqualIID(iid, IID_IConnectionPoint)))
+ {
+ *ppvObj = (IConnectionPoint *)this;
+ CAsyncConnection::AddRef();
+ }
+ else
+ {
+ return E_NOINTERFACE;
+ }
+
+ olDebugOut((DEB_TRACE, "Out CAsyncConnection::QueryInterface\n"));
+ return ResultFromScode(sc);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncConnection::AddRef, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 29-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CAsyncConnection::AddRef(void)
+{
+ ULONG ulRet;
+ olDebugOut((DEB_TRACE,
+ "In CAsyncConnection::AddRef:%p()\n",
+ this));
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+
+ olDebugOut((DEB_TRACE, "Out CAsyncConnection::AddRef\n"));
+ return ulRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncConnection::Release, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 30-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CAsyncConnection::Release(void)
+{
+ LONG lRet;
+ olDebugOut((DEB_TRACE,
+ "In CAsyncConnection::Release:%p()\n",
+ this));
+
+ olAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ {
+ olAssert((lRet > 0) && "Connection point released too many times.");
+ lRet = 0;
+
+ }
+ olDebugOut((DEB_TRACE, "Out CAsyncConnection::Release\n"));
+ return (ULONG)lRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncConnection::Notify, public
+//
+// Synopsis:
+//
+// Returns: Appropriate status code
+//
+// History: 14-Jan-96 SusiA Created
+// 27-Feb-96 SusiA Moved from Async wrappers
+//
+//----------------------------------------------------------------------------
+SCODE CAsyncConnection::Notify(SCODE scFailure,
+ ILockBytes *pilb,
+ CPerContext *ppc,
+ CSafeSem *pss)
+{
+ SCODE sc = S_OK;
+ BOOL fAccurate = (scFailure == E_PENDING);
+ IFillInfo *pfi = ppc->GetFillInfo();
+ ULONG ulWaterMark;
+ ULONG ulFailurePoint;
+
+ HANDLE hNotifyEvent;
+
+ if (pfi != NULL)
+ {
+ pfi->GetFailureInfo(&ulWaterMark,
+ &ulFailurePoint);
+
+ pss->Release();
+
+ while (((sc = _pdacp->NotifySinks(ulWaterMark,
+ ulFailurePoint,
+ fAccurate,
+ STG_S_MONITORING)) == STG_S_BLOCK) ||
+ (sc == STG_S_MONITORING) ||
+ // S_OK is a synonym for STG_S_MONITORING
+ (sc == S_OK))
+ {
+ DWORD dwFlags;
+
+ // wait for an event to signal
+ hNotifyEvent = ppc->GetNotificationEvent();
+ WaitForSingleObject(hNotifyEvent, INFINITE);
+
+ pfi->GetTerminationStatus(&dwFlags);
+ // client terminated call?
+ if (dwFlags == TERMINATED_ABNORMAL)
+ {
+ return STG_E_INCOMPLETE;
+ }
+ // download is complete
+ else if (dwFlags == TERMINATED_NORMAL)
+ {
+ return S_OK;
+ }
+ else
+ {
+ //Note: Don't overwrite the failure point we recorded
+ // before, since it may have been changed by some
+ // other thread.
+
+ //Don't need to take the critical section here, since
+ //we don't care about the current failure point.
+ ULONG ulFailurePointCurrent;
+ pfi->GetFailureInfo(&ulWaterMark,
+ &ulFailurePointCurrent);
+
+ // all the data is available now
+ if (ulWaterMark >= ulFailurePoint)
+ {
+ //We don't care what the return value is, so send
+ //STG_S_BLOCK and all sinks will have fOwner == FALSE
+ _pdacp->NotifySinks(ulWaterMark,
+ ulFailurePoint,
+ fAccurate,
+ STG_S_BLOCK);
+ break;
+ }
+ }
+ }
+ }
+
+ if ((sc == STG_S_RETRYNOW) ||
+ (sc == STG_S_BLOCK) ||
+ (sc == STG_S_MONITORING))
+ {
+ return S_OK;
+ }
+ else return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncConnection::GetConnectionInterface, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 30-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncConnection::GetConnectionInterface(IID *pIID)
+{
+ olDebugOut((DEB_ITRACE,
+ "In CAsyncConnection::GetConnectionInterface:%p()\n",
+ this));
+
+
+ *pIID = IID_IProgressNotify;
+
+ olDebugOut((DEB_ITRACE, "Out CAsyncConnection::GetConnectionInterface\n"));
+ return S_OK;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncConnection::GetConnectionPointContainer, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 30-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncConnection::GetConnectionPointContainer(
+ IConnectionPointContainer ** ppCPC)
+{
+ olDebugOut((DEB_ITRACE,
+ "In CAsyncConnection::GetConnectionPointContainer:%p()\n",
+ this));
+
+ *ppCPC = _pCPC;
+ _pCPC->AddRef();
+
+ olDebugOut((DEB_ITRACE,
+ "Out CAsyncConnection::GetConnectionPointContainer\n"));
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncConnection::EnumConnections, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 30-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncConnection::EnumConnections(
+ IEnumConnections **ppEnum)
+{
+ olDebugOut((DEB_ITRACE, "In CAsyncConnection::EnumConnections:%p()\n", this));
+ olDebugOut((DEB_ITRACE, "Out CAsyncConnection::EnumConnections\n"));
+ return E_NOTIMPL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncConnection:: Advise, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 29-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncConnection::Advise(IUnknown *pUnkSink,
+ DWORD *pdwCookie)
+{
+ SCODE sc;
+ IProgressNotify *ppnSink;
+
+ olDebugOut((DEB_ITRACE, "In CAsyncConnection::Advise:%p()\n", this));
+
+ olChk(pUnkSink->QueryInterface(IID_IProgressNotify, (void **)&ppnSink));
+ sc = _pdacp->AddConnection(ppnSink, pdwCookie);
+ ppnSink->Release();
+
+ olDebugOut((DEB_ITRACE, "Out CAsyncConnection::Advise\n"));
+EH_Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncConnection::Unadvise, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 30-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncConnection::Unadvise(DWORD dwCookie)
+{
+ SCODE sc;
+ olDebugOut((DEB_ITRACE, "In CAsyncConnection::Unadvise:%p()\n", this));
+ sc = _pdacp->RemoveConnection(dwCookie);
+ olDebugOut((DEB_ITRACE, "Out CAsyncConnection::Unadvise\n"));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncConnectionContainer::EnumConnectionPoints, public
+//
+// Synopsis: Return enumerator on connection points
+//
+// Arguments: [ppEnum] -- Return pointer of enumerator
+//
+// Returns: Appropriate status code
+//
+// History: 28-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncConnectionContainer::EnumConnectionPoints(
+ IEnumConnectionPoints **ppEnum)
+{
+ olDebugOut((DEB_ITRACE,
+ "In CAsyncConnectionContainer::EnumConnectionPoints:%p()\n",
+ this));
+ olDebugOut((DEB_ITRACE,
+ "Out CAsyncConnectionContainer::EnumConnectionPoints\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncConnectionContainer::FindConnectionPoint, public
+//
+// Synopsis: Return a connection point given an IID
+//
+// Arguments: [iid] -- IID to return connection point for
+// [ppCP] -- Return location for pointer
+//
+// Returns: Appropriate status code
+//
+// History: 28-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CAsyncConnectionContainer::FindConnectionPoint(
+ REFIID iid,
+ IConnectionPoint **ppCP)
+{
+ olDebugOut((DEB_ITRACE,
+ "In CAsyncConnectionContainer::FindConnectionPoint:%p()\n",
+ this));
+
+ CAsyncConnection *pcp;
+
+ if (IsEqualIID(iid, IID_IProgressNotify))
+ {
+ pcp = &_cpoint;
+ }
+ else
+ {
+ *ppCP = NULL;
+ return E_NOINTERFACE;
+ }
+
+ pcp->AddRef();
+ *ppCP = pcp;
+
+ olDebugOut((DEB_ITRACE,
+ "Out CAsyncConnectionContainer::FindConnectionPoint\n"));
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncConnectionContainer::InitConnection, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// History: 10-Apr-96 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE CAsyncConnectionContainer::InitConnection(CAsyncConnection *pacParent)
+{
+ return _cpoint.Init(this, pacParent);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAsyncConnectionContainer::InitClone, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// History: 10-Apr-96 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE CAsyncConnectionContainer::InitClone(CAsyncConnection *pac)
+{
+ return _cpoint.InitClone(this, pac);
+}
diff --git a/private/ole32/stg/exp/astgconn.hxx b/private/ole32/stg/exp/astgconn.hxx
new file mode 100644
index 000000000..75dae5792
--- /dev/null
+++ b/private/ole32/stg/exp/astgconn.hxx
@@ -0,0 +1,181 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1996 - 1996.
+//
+// File: astgconn.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 28-Mar-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ASTGCONN_HXX__
+#define __ASTGCONN_HXX__
+
+
+#ifdef ASYNC
+#include <sinklist.hxx>
+#endif
+
+#include <ocidl.h>
+
+interface IDocfileAsyncConnectionPoint;
+
+//+---------------------------------------------------------------------------
+//
+// Class: CAsyncConnection
+//
+// Purpose: Provide connection point for objects operating in async
+// docfile.
+//
+// History: 28-Mar-96 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+class CAsyncConnection: public IConnectionPoint
+{
+public:
+ inline CAsyncConnection();
+ SCODE Init(IConnectionPointContainer *pCPC,
+ CAsyncConnection *pacParent);
+ SCODE InitClone(IConnectionPointContainer *pCPC,
+ CAsyncConnection *pac);
+ SCODE InitMarshal(IConnectionPointContainer *pCPC,
+ DWORD dwAsyncFlags,
+ IDocfileAsyncConnectionPoint *pdacp);
+ ~CAsyncConnection();
+
+ //From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ //From IConnectionPoint
+ STDMETHOD(GetConnectionInterface)(IID *pIID);
+ STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer ** ppCPC);
+ STDMETHOD(Advise)(IUnknown *pUnkSink, DWORD *pdwCookie);
+ STDMETHOD(Unadvise)(DWORD dwCookie);
+ STDMETHOD(EnumConnections)(IEnumConnections **ppEnum);
+
+
+ SCODE Init(void);
+ SCODE Notify(SCODE scFailure,
+ ILockBytes *pilb,
+ CPerContext *ppc,
+ CSafeSem *pss);
+
+ inline BOOL IsInitialized(void) const;
+ inline IDocfileAsyncConnectionPoint * GetMarshalPoint(void);
+ inline void SetAsyncFlags(DWORD dwAsyncFlags);
+ inline DWORD GetAsyncFlags(void) const;
+
+private:
+ IConnectionPointContainer *_pCPC;
+ IDocfileAsyncConnectionPoint *_pdacp;
+ DWORD _dwAsyncFlags;
+ LONG _cReferences;
+};
+
+
+inline CAsyncConnection::CAsyncConnection()
+{
+ _pCPC = NULL;
+ _cReferences = 1;
+ _pdacp = NULL;
+ _dwAsyncFlags = 0;
+}
+
+inline void CAsyncConnection::SetAsyncFlags(DWORD dwAsyncFlags)
+{
+ _dwAsyncFlags = dwAsyncFlags;
+}
+
+inline DWORD CAsyncConnection::GetAsyncFlags(void) const
+{
+ return _dwAsyncFlags;
+}
+
+inline BOOL CAsyncConnection::IsInitialized(void) const
+{
+ return (_pdacp != NULL);
+}
+
+inline IDocfileAsyncConnectionPoint * CAsyncConnection::GetMarshalPoint(void)
+{
+ return _pdacp;
+}
+
+
+class CAsyncConnectionContainer: public IConnectionPointContainer
+{
+public:
+ SCODE InitConnection(CAsyncConnection *pacParent);
+ SCODE InitClone(CAsyncConnection *pac);
+ SCODE InitMarshal(IDocfileAsyncConnectionPoint *pdacp);
+
+ inline void SetAsyncFlags(DWORD dwAsyncFlags);
+
+ //From IConnectionPointContainer
+ STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum);
+ STDMETHOD(FindConnectionPoint)(REFIID iid, IConnectionPoint **ppCP);
+
+protected:
+ inline IDocfileAsyncConnectionPoint * GetMarshalPoint(void);
+
+ CAsyncConnection _cpoint;
+};
+
+inline void CAsyncConnectionContainer::SetAsyncFlags(DWORD dwAsyncFlags)
+{
+ _cpoint.SetAsyncFlags(dwAsyncFlags);
+}
+
+
+inline IDocfileAsyncConnectionPoint *
+ CAsyncConnectionContainer::GetMarshalPoint(void)
+{
+ return _cpoint.GetMarshalPoint();
+}
+
+
+
+#ifdef ASYNC
+#define BEGIN_PENDING_LOOP \
+ do \
+ {
+
+//Note: There is a return in this macro. Cleanup needs to be done
+// before the macro is used.
+#define END_PENDING_LOOP \
+ if (!ISPENDINGERROR(sc)) \
+ { \
+ break; \
+ } \
+ else \
+ { \
+ SCODE sc2; \
+ sc2 = _cpoint.Notify(sc, \
+ _ppc->GetBase(), \
+ _ppc, \
+ &_ss); \
+ if (sc2 != S_OK) \
+ { \
+ return ResultFromScode(sc2); \
+ } \
+ } \
+ } while (TRUE);
+#else
+#define BEGIN_PENDING_LOOP
+#define END_PENDING_LOOP
+#endif
+
+
+#endif // #ifndef __ASTGCONN_HXX__
diff --git a/private/ole32/stg/exp/cntxlist.cxx b/private/ole32/stg/exp/cntxlist.cxx
new file mode 100644
index 000000000..ecfb6565c
--- /dev/null
+++ b/private/ole32/stg/exp/cntxlist.cxx
@@ -0,0 +1,111 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: cntxlist.cxx
+//
+// Contents: CContextList implementation
+//
+// History: 26-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <cntxlist.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Member: CContextList::_Find, public
+//
+// Synopsis: Looks through the list for a matching context
+//
+// Arguments: [ctxid] - Context to look for
+//
+// Returns: Pointer to object or NULL
+//
+// History: 26-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CContextList_Find)
+#endif
+
+CContext *CContextList::_Find(ContextId ctxid)
+{
+ CBasedContextPtr pctx;
+
+ olDebugOut((DEB_ITRACE, "In CContextList::_Find:%p(%lu)\n", this,
+ (ULONG)ctxid));
+ for (pctx = _pctxHead; pctx; pctx = pctx->pctxNext)
+ if (pctx->ctxid != INVALID_CONTEXT_ID &&
+ pctx->ctxid == ctxid)
+ break;
+ olDebugOut((DEB_ITRACE, "Out CContextList::_Find\n"));
+ return BP_TO_P(CContext *, pctx);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CContextList::Add, public
+//
+// Synopsis: Adds a context to the list
+//
+// Arguments: [pctx] - Context
+//
+// History: 26-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CContextList_Add)
+#endif
+
+void CContextList::Add(CContext *pctx)
+{
+ olDebugOut((DEB_ITRACE, "In CContextList::Add:%p(%p)\n", this, pctx));
+ pctx->pctxNext = _pctxHead;
+ pctx->ctxid = GetCurrentContextId();
+ _pctxHead = P_TO_BP(CBasedContextPtr, pctx);
+ olDebugOut((DEB_ITRACE, "Out CContextList::Add\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CContextList::Remove, public
+//
+// Synopsis: Removes a context from the list
+//
+// Arguments: [pctx] - Context
+//
+// History: 26-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CContextList_Remove)
+#endif
+
+void CContextList::Remove(CContext *pctx)
+{
+ CBasedContextPtr *ppctx;
+#if DBG == 1
+ BOOL fFound = FALSE;
+#endif
+
+ olDebugOut((DEB_ITRACE, "In CContextList::Remove:%p(%p)\n", this, pctx));
+ for (ppctx = &_pctxHead; *ppctx; ppctx = &(*ppctx)->pctxNext)
+ if (*ppctx == pctx)
+ {
+#if DBG == 1
+ fFound = TRUE;
+#endif
+ *ppctx = pctx->pctxNext;
+ break;
+ }
+ olAssert(fFound == TRUE);
+ olDebugOut((DEB_ITRACE, "Out CContextList::Remove\n"));
+}
diff --git a/private/ole32/stg/exp/context.cxx b/private/ole32/stg/exp/context.cxx
new file mode 100644
index 000000000..07eeb21cd
--- /dev/null
+++ b/private/ole32/stg/exp/context.cxx
@@ -0,0 +1,153 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: context.cxx
+//
+// Contents: CPerContext implementation
+//
+// History: 14-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <lock.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: CPerContext::~CPerContext, public
+//
+// Synopsis: Releases internal objects
+//
+// History: 14-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPerContext_1CPerContext)
+#endif
+
+CPerContext::~CPerContext(void)
+{
+#ifndef ASYNC
+ //In the ASYNC case, the Close() happens in the Release method.
+ if (_plkbBase != NULL)
+ Close();
+#endif
+ if (_pgc)
+ {
+ _pgc->Remove(this);
+ _pgc->Release();
+ }
+
+#ifdef ASYNC
+ if (_hNotificationEvent != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(_hNotificationEvent);
+ _hNotificationEvent = INVALID_HANDLE_VALUE;
+ }
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPerContext::Close, public
+//
+// Synopsis: Closes the ILockBytes for this context
+//
+// History: 09-Apr-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPerContext_Close)
+#endif
+
+void CPerContext::Close(void)
+{
+ if (_ulOpenLock && _pgc)
+ ReleaseOpen(_plkbOriginal, _pgc->GetOpenLockFlags(), _ulOpenLock);
+ _plkbBase->Release();
+ _pfstDirty->Release();
+ _plkbOriginal->Release();
+ _plkbBase = NULL;
+ _pfstDirty = NULL;
+ _plkbOriginal = NULL;
+#ifdef ASYNC
+ if (_pfi != NULL)
+ {
+ _pfi->Release();
+ _pfi = NULL;
+ }
+#endif
+}
+
+#ifdef MULTIHEAP
+//+--------------------------------------------------------------
+//
+// Method: CSafeMultiHeap::CSafeMultiHeap
+//
+// Purpose: allows restoration of heap with methods calling "delete this"
+//
+// History: 29-Nov-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+CSafeMultiHeap::CSafeMultiHeap(CPerContext *ppc)
+{
+ _pSmAllocator = &g_smAllocator;
+ ppc->SetAllocatorState (&_ppcPrev, _pSmAllocator);
+}
+
+//+--------------------------------------------------------------
+//
+// Method: CSafeMultiHeap::~CSafeMultiHeap
+//
+// Purpose: allows restoration of heap with methods calling "delete this"
+//
+// History: 29-Nov-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+CSafeMultiHeap::~CSafeMultiHeap()
+{
+ if (_ppcPrev != NULL)
+ _ppcPrev->SetAllocatorState(NULL, _pSmAllocator);
+ else
+ _pSmAllocator->SetState(NULL, NULL, 0, NULL, NULL);
+}
+#endif // MULTIHEAP
+
+#ifdef ASYNC
+//+---------------------------------------------------------------------------
+//
+// Member: CPerContext::InitNotificationEvent, public
+//
+// Returns: Appropriate status code
+//
+// History: 17-Apr-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CPerContext::InitNotificationEvent(void)
+{
+ TCHAR atcEventName[CONTEXT_MUTEX_NAME_LENGTH];
+
+ olAssert(_pgc != NULL);
+
+ _pgc->GetEventName(atcEventName);
+ _hNotificationEvent = CreateEventT(NULL, //No security
+ TRUE,
+ FALSE,
+ atcEventName);
+ if (_hNotificationEvent == NULL)
+ {
+ _hNotificationEvent = INVALID_HANDLE_VALUE;
+ return Win32ErrorToScode(GetLastError());
+ }
+ return S_OK;
+}
+#endif
diff --git a/private/ole32/stg/exp/daytona/makefile b/private/ole32/stg/exp/daytona/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ole32/stg/exp/daytona/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/stg/exp/daytona/sources b/private/ole32/stg/exp/daytona/sources
new file mode 100644
index 000000000..ca19a0443
--- /dev/null
+++ b/private/ole32/stg/exp/daytona/sources
@@ -0,0 +1,98 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= exp
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES=..\..\..\ih;..\..\..\common\daytona;..\..\h;..;..\..\props;..\..\..\com\inc;..\..\..\..\inc;..\..\async\docfile
+
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+SOURCES= \
+ ..\dfguid.cxx \
+ ..\docfile.cxx \
+ ..\filest.cxx \
+ ..\filest32.cxx \
+ ..\time32.cxx \
+ ..\context.cxx \
+ ..\cntxlist.cxx \
+ ..\lock.cxx \
+ ..\marshl.cxx \
+ ..\dfunmfct.cxx \
+ ..\seekptr.cxx \
+ ..\expst.cxx \
+ ..\peiter.cxx \
+ ..\expiter.cxx \
+ ..\expdf.cxx \
+ ..\ptrcache.cxx \
+ ..\storage.cxx \
+ ..\mrshlist.cxx \
+ ..\astgconn.cxx
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+PRECOMPILED_INCLUDE= ..\exphead.cxx
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
diff --git a/private/ole32/stg/exp/depend.mk1 b/private/ole32/stg/exp/depend.mk1
new file mode 100644
index 000000000..4c6b67f61
--- /dev/null
+++ b/private/ole32/stg/exp/depend.mk1
@@ -0,0 +1,1312 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\docfile.obj $(OBJDIR)\docfile.lst: .\docfile.cxx \
+ $(CAIROLE)\STG\exp\ascii.hxx $(CAIROLE)\STG\exp\expdf.hxx \
+ $(CAIROLE)\STG\exp\expst.hxx $(CAIROLE)\STG\exp\nmidmap.hxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfentry.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\rpubdf.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sngprop.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\dfunmfct.obj $(OBJDIR)\dfunmfct.lst: .\dfunmfct.cxx \
+ $(CAIROLE)\STG\exp\dfunmfct.hxx $(CAIROLE)\STG\exp\marshl.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfentry.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\basetyps.h $(OLE2H)\prspec.h \
+ $(OLE2H)\stream.h $(OLE2H)\varnt.h $(OLE2H)\wtypes.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\rpc.h $(OSINC)\cderr.h $(OSINC)\commdlg.h \
+ $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\cntxlist.obj $(OBJDIR)\cntxlist.lst: .\cntxlist.cxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\types.h $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\wtypes.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\context.obj $(OBJDIR)\context.lst: .\context.cxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\basetyps.h $(OLE2H)\wtypes.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\ascii.obj $(OBJDIR)\ascii.lst: .\ascii.cxx \
+ $(CAIROLE)\STG\exp\expiter.hxx $(CAIROLE)\STG\exp\peiter.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\STG\exp\ascii.hxx \
+ $(CAIROLE)\STG\exp\expdf.hxx $(CAIROLE)\STG\exp\expst.hxx \
+ $(CAIROLE)\STG\exp\nmidmap.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sngprop.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\filest.obj $(OBJDIR)\filest.lst: .\filest.cxx \
+ $(CAIROLE)\STG\exp\marshl.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\expdf.obj $(OBJDIR)\expdf.lst: .\expdf.cxx \
+ $(CAIROLE)\stg\h\pbstream.hxx $(CAIROLE)\STG\exp\expdf.hxx \
+ $(CAIROLE)\STG\exp\expiter.hxx $(CAIROLE)\STG\exp\expst.hxx \
+ $(CAIROLE)\STG\exp\marshl.hxx $(CAIROLE)\STG\exp\nmidmap.hxx \
+ $(CAIROLE)\STG\exp\peiter.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\rpubdf.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sngprop.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\expprop.obj $(OBJDIR)\expprop.lst: .\expprop.cxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\props.hxx \
+ $(CAIROLE)\STG\exp\nmidmap.hxx $(CAIROLE)\STG\exp\peiter.hxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pbstream.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sngprop.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\memalloc.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\expdf.hxx \
+ .\exphead.cxx .\exppiter.hxx .\expst.hxx
+
+$(OBJDIR)\exppsi.obj $(OBJDIR)\exppsi.lst: .\exppsi.cxx \
+ $(CAIROLE)\STG\exp\exppsi.hxx $(CAIROLE)\STG\exp\peiter.hxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\exppiter.obj $(OBJDIR)\exppiter.lst: .\exppiter.cxx \
+ $(CAIROLE)\STG\exp\expdf.hxx $(CAIROLE)\STG\exp\exppiter.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\STG\exp\nmidmap.hxx $(CAIROLE)\STG\exp\peiter.hxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sngprop.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\memalloc.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oletyp.h $(OLE2H)\prsist.h $(OLE2H)\prspec.h \
+ $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h \
+ $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h $(OLE2H)\storag.h \
+ $(OLE2H)\stream.h $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h \
+ $(OLE2H)\winole.h $(OLE2H)\wtypes.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\exppset.obj $(OBJDIR)\exppset.lst: .\exppset.cxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\STG\exp\nmidmap.hxx $(CAIROLE)\STG\exp\peiter.hxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\h\logfile.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sngprop.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\expdf.hxx \
+ .\exphead.cxx .\exppsi.hxx .\expst.hxx
+
+$(OBJDIR)\expiter.obj $(OBJDIR)\expiter.lst: .\expiter.cxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\STG\exp\expiter.hxx \
+ $(CAIROLE)\STG\exp\peiter.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\expst.obj $(OBJDIR)\expst.lst: .\expst.cxx \
+ $(CAIROLE)\STG\exp\expst.hxx $(CAIROLE)\STG\exp\seekptr.hxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\h\logfile.hxx \
+ $(CAIROLE)\STG\exp\marshl.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pbstream.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\filest32.obj $(OBJDIR)\filest32.lst: .\filest32.cxx \
+ $(CAIROLE)\STG\exp\marshl.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\time.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\time32.obj $(OBJDIR)\time32.lst: .\time32.cxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\storage.obj $(OBJDIR)\storage.lst: .\storage.cxx \
+ $(CAIROLE)\stg\h\dfentry.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\logfile.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\dos.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\dsyserr.h $(OLE2H)\issperr.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\ptrcache.obj $(OBJDIR)\ptrcache.lst: .\ptrcache.cxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\ptrcache.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\logfile.obj $(OBJDIR)\logfile.lst: .\logfile.cxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\nmidmap.obj $(OBJDIR)\nmidmap.lst: .\nmidmap.cxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx \
+ .\nmidmap.hxx
+
+$(OBJDIR)\props.obj $(OBJDIR)\props.lst: .\props.cxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\props.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\memalloc.h $(OLE2H)\monikr.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h $(OLE2H)\prspec.h \
+ $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h \
+ $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h $(OLE2H)\storag.h \
+ $(OLE2H)\stream.h $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h \
+ $(OLE2H)\winole.h $(OLE2H)\wtypes.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\peiter.obj $(OBJDIR)\peiter.lst: .\peiter.cxx \
+ $(CAIROLE)\STG\exp\peiter.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\seekptr.obj $(OBJDIR)\seekptr.lst: .\seekptr.cxx \
+ $(CAIROLE)\STG\exp\seekptr.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\marshl.obj $(OBJDIR)\marshl.lst: .\marshl.cxx \
+ $(CAIROLE)\STG\exp\expdf.hxx $(CAIROLE)\STG\exp\nmidmap.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\STG\exp\expst.hxx \
+ $(CAIROLE)\STG\exp\marshl.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pbstream.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sngprop.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\lock.obj $(OBJDIR)\lock.lst: .\lock.cxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\exphead.pxh $(PCHDIR)\$(OBJDIR)\exphead.lst: \
+ $(CAIROLE)\stg\exp\exphead.cxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h
+
+.\$(OBJDIR)\docfile.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\ascii.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\filest.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\filest32.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\time32.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\context.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\cntxlist.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\lock.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\marshl.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\dfunmfct.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\seekptr.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\expst.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\peiter.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\expiter.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\props.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\exppset.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\exppiter.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\exppsi.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\expprop.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\nmidmap.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\expdf.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\logfile.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\ptrcache.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\storage.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/exp/depend.mk3 b/private/ole32/stg/exp/depend.mk3
new file mode 100644
index 000000000..d02fc6a88
--- /dev/null
+++ b/private/ole32/stg/exp/depend.mk3
@@ -0,0 +1,904 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\docfile.obj $(OBJDIR)\docfile.lst: .\docfile.cxx \
+ $(CAIROLE)\stg\exp\ascii.hxx $(CAIROLE)\stg\exp\expdf.hxx \
+ $(CAIROLE)\stg\exp\expst.hxx $(CAIROLE)\stg\exp\nmidmap.hxx \
+ $(CAIROLE)\stg\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfentry.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\rpubdf.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sngprop.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\dllentry.obj $(OBJDIR)\dllentry.lst: .\dllentry.c \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h
+
+$(OBJDIR)\dfunmfct.obj $(OBJDIR)\dfunmfct.lst: .\dfunmfct.cxx \
+ $(CAIROLE)\stg\exp\dfunmfct.hxx $(CAIROLE)\stg\exp\marshl.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfentry.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\scode.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\cntxlist.obj $(OBJDIR)\cntxlist.lst: .\cntxlist.cxx \
+ $(CAIROLE)\stg\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\context.obj $(OBJDIR)\context.lst: .\context.cxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\dfguid.obj $(OBJDIR)\dfguid.lst: .\dfguid.cxx \
+ $(CAIROLE)\stg\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\initguid.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\ascii.obj $(OBJDIR)\ascii.lst: .\ascii.cxx \
+ $(CAIROLE)\stg\exp\expiter.hxx $(CAIROLE)\stg\exp\peiter.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\exp\ascii.hxx \
+ $(CAIROLE)\stg\exp\expdf.hxx $(CAIROLE)\stg\exp\expst.hxx \
+ $(CAIROLE)\stg\exp\nmidmap.hxx $(CAIROLE)\stg\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sngprop.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\filest.obj $(OBJDIR)\filest.lst: .\filest.cxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\exp\marshl.hxx \
+ $(CAIROLE)\stg\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\expdf.obj $(OBJDIR)\expdf.lst: .\expdf.cxx \
+ $(CAIROLE)\stg\exp\expiter.hxx $(CAIROLE)\stg\h\pbstream.hxx \
+ $(CAIROLE)\stg\exp\expdf.hxx $(CAIROLE)\stg\exp\expst.hxx \
+ $(CAIROLE)\stg\exp\marshl.hxx $(CAIROLE)\stg\exp\nmidmap.hxx \
+ $(CAIROLE)\stg\exp\peiter.hxx $(CAIROLE)\stg\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\rpubdf.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sngprop.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\expiter.obj $(OBJDIR)\expiter.lst: .\expiter.cxx \
+ $(CAIROLE)\stg\exp\expiter.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\exp\peiter.hxx $(CAIROLE)\stg\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\expst.obj $(OBJDIR)\expst.lst: .\expst.cxx \
+ $(CAIROLE)\stg\exp\seekptr.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\exp\expst.hxx $(CAIROLE)\stg\exp\marshl.hxx \
+ $(CAIROLE)\stg\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\h\logfile.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pbstream.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\filest32.obj $(OBJDIR)\filest32.lst: .\filest32.cxx \
+ $(CAIROLE)\stg\exp\marshl.hxx $(CAIROLE)\stg\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\time.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\time32.obj $(OBJDIR)\time32.lst: .\time32.cxx \
+ $(CAIROLE)\stg\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\storage.obj $(OBJDIR)\storage.lst: .\storage.cxx \
+ $(CAIROLE)\stg\h\dfentry.hxx $(CAIROLE)\stg\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\logfile.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\dos.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\ptrcache.obj $(OBJDIR)\ptrcache.lst: .\ptrcache.cxx \
+ $(CAIROLE)\stg\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\ptrcache.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\logfile.obj $(OBJDIR)\logfile.lst: .\logfile.cxx \
+ $(CAIROLE)\stg\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\peiter.obj $(OBJDIR)\peiter.lst: .\peiter.cxx \
+ $(CAIROLE)\stg\exp\peiter.hxx $(CAIROLE)\stg\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\seekptr.obj $(OBJDIR)\seekptr.lst: .\seekptr.cxx \
+ $(CAIROLE)\stg\exp\seekptr.hxx $(CAIROLE)\stg\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\marshl.obj $(OBJDIR)\marshl.lst: .\marshl.cxx \
+ $(CAIROLE)\stg\exp\expdf.hxx $(CAIROLE)\stg\exp\expst.hxx \
+ $(CAIROLE)\stg\exp\marshl.hxx $(CAIROLE)\stg\exp\nmidmap.hxx \
+ $(CAIROLE)\stg\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\h\logfile.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pbstream.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sngprop.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+$(OBJDIR)\lock.obj $(OBJDIR)\lock.lst: .\lock.cxx \
+ $(CAIROLE)\stg\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\exphead.cxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\exphead.pxh $(PCHDIR)\$(OBJDIR)\exphead.lst: \
+ $(CAIROLE)\stg\exp\exphead.cxx $(CAIROLE)\stg\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
+.\$(OBJDIR)\docfile.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\ascii.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\dfguid.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\filest.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\filest32.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\time32.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\context.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\cntxlist.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\lock.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\marshl.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\dfunmfct.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\seekptr.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\expst.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\peiter.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\expiter.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\expdf.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\logfile.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\ptrcache.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\storage.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/exp/depend.mk9 b/private/ole32/stg/exp/depend.mk9
new file mode 100644
index 000000000..8e7bfcc3a
--- /dev/null
+++ b/private/ole32/stg/exp/depend.mk9
@@ -0,0 +1,652 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\docfile.obj $(OBJDIR)\docfile.lst: .\docfile.cxx \
+ $(CAIROLE)\STG\exp\ascii.hxx $(CAIROLE)\STG\exp\expdf.hxx \
+ $(CAIROLE)\STG\exp\expst.hxx $(CAIROLE)\STG\exp\nmidmap.hxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfentry.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\rpubdf.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sngprop.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\dfunmfct.obj $(OBJDIR)\dfunmfct.lst: .\dfunmfct.cxx \
+ $(CAIROLE)\STG\exp\dfunmfct.hxx $(CAIROLE)\STG\exp\marshl.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfentry.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\scode.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\cntxlist.obj $(OBJDIR)\cntxlist.lst: .\cntxlist.cxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\context.obj $(OBJDIR)\context.lst: .\context.cxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\dfguid.obj $(OBJDIR)\dfguid.lst: .\dfguid.cxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\initguid.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\ascii.obj $(OBJDIR)\ascii.lst: .\ascii.cxx \
+ $(CAIROLE)\STG\exp\expiter.hxx $(CAIROLE)\STG\exp\peiter.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\STG\exp\ascii.hxx \
+ $(CAIROLE)\STG\exp\expdf.hxx $(CAIROLE)\STG\exp\expst.hxx \
+ $(CAIROLE)\STG\exp\nmidmap.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sngprop.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\filest.obj $(OBJDIR)\filest.lst: .\filest.cxx \
+ $(CAIROLE)\STG\exp\marshl.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\expdf.obj $(OBJDIR)\expdf.lst: .\expdf.cxx \
+ $(CAIROLE)\stg\h\pbstream.hxx $(CAIROLE)\STG\exp\expdf.hxx \
+ $(CAIROLE)\STG\exp\expiter.hxx $(CAIROLE)\STG\exp\expst.hxx \
+ $(CAIROLE)\STG\exp\marshl.hxx $(CAIROLE)\STG\exp\nmidmap.hxx \
+ $(CAIROLE)\STG\exp\peiter.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\rpubdf.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sngprop.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\expiter.obj $(OBJDIR)\expiter.lst: .\expiter.cxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ptrcache.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\STG\exp\expiter.hxx $(CAIROLE)\STG\exp\peiter.hxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\expst.obj $(OBJDIR)\expst.lst: .\expst.cxx \
+ $(CAIROLE)\STG\exp\seekptr.hxx $(CAIROLE)\STG\exp\expst.hxx \
+ $(CAIROLE)\STG\exp\marshl.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\lock.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pbstream.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\filest16.obj $(OBJDIR)\filest16.lst: .\filest16.cxx \
+ $(CAIROLE)\STG\exp\time16.hxx $(CAIROLE)\stg\h\dfdeb.hxx \
+ $(CAIROLE)\STG\exp\marshl.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\logfile.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\dos.h \
+ $(CRTINC)\fcntl.h $(CRTINC)\io.h $(CRTINC)\share.h \
+ $(CRTINC)\sys\stat.h $(CRTINC)\sys\types.h $(CRTINC)\time.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\time16.obj $(OBJDIR)\time16.lst: .\time16.cxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\STG\exp\time16.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\dos.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(CRTINC)\time.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\storage.obj $(OBJDIR)\storage.lst: .\storage.cxx \
+ $(CAIROLE)\stg\h\dfentry.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\logfile.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tlsets.hxx $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\dos.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\ptrcache.obj $(OBJDIR)\ptrcache.lst: .\ptrcache.cxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pdocfile.hxx \
+ $(CAIROLE)\stg\h\ptrcache.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\logfile.obj $(OBJDIR)\logfile.lst: .\logfile.cxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\peiter.obj $(OBJDIR)\peiter.lst: .\peiter.cxx \
+ $(CAIROLE)\STG\exp\peiter.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\seekptr.obj $(OBJDIR)\seekptr.lst: .\seekptr.cxx \
+ $(CAIROLE)\STG\exp\seekptr.hxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\marshl.obj $(OBJDIR)\marshl.lst: .\marshl.cxx \
+ $(CAIROLE)\STG\exp\expdf.hxx $(CAIROLE)\STG\exp\expst.hxx \
+ $(CAIROLE)\STG\exp\marshl.hxx $(CAIROLE)\STG\exp\nmidmap.hxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\h\logfile.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\pbstream.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\publicdf.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sngprop.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+$(OBJDIR)\lock.obj $(OBJDIR)\lock.lst: .\lock.cxx \
+ $(CAIROLE)\STG\exp\segexp.hxx $(CAIROLE)\stg\h\chinst.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\debug.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\lock.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\exphead.cxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\exphead.pxh $(PCHDIR)\$(OBJDIR)\exphead.lst: \
+ $(CAIROLE)\stg\exp\exphead.cxx $(CAIROLE)\STG\exp\segexp.hxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\debug.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\revert.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\safepnt.hxx \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h
+
+.\$(OBJDIR)\docfile.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\ascii.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\dfguid.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\filest.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\filest16.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\time16.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\context.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\cntxlist.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\lock.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\marshl.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\dfunmfct.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\seekptr.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\expst.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\peiter.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\expiter.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\expdf.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\logfile.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\ptrcache.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+.\$(OBJDIR)\storage.obj : $(PCHDIR)\$(OBJDIR)\exphead.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/exp/dfguid.cxx b/private/ole32/stg/exp/dfguid.cxx
new file mode 100644
index 000000000..35b1611cb
--- /dev/null
+++ b/private/ole32/stg/exp/dfguid.cxx
@@ -0,0 +1,24 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dfguid.cxx
+//
+// Contents: GUID definitions for useful GUIDS
+//
+// History: 16-Aug-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <initguid.h>
+
+#ifdef CODESEGMENTS
+#pragma code_seg("Marshal_TEXT")
+#endif
+
+DEFINE_OLEGUID(CLSID_DfMarshal, 0x0000030b, 0, 0);
+
diff --git a/private/ole32/stg/exp/dfunmfct.cxx b/private/ole32/stg/exp/dfunmfct.cxx
new file mode 100644
index 000000000..4b3d1808c
--- /dev/null
+++ b/private/ole32/stg/exp/dfunmfct.cxx
@@ -0,0 +1,570 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dfunmfct.cxx
+//
+// Contents: Implementation of CDocfileUnmarshalFactory
+//
+// History: 25-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <dfunmfct.hxx>
+#include <marshl.hxx>
+#include <logfile.hxx>
+#include <expdf.hxx>
+#include <expst.hxx>
+#if WIN32 >= 300
+#include <omarshal.hxx>
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::new, public
+//
+// Synopsis: Overloaded allocator
+//
+// Returns: Memory block for CDocfileUnmarshalFactory instance
+//
+// History: 25-Jun-93 AlexT Created
+//
+// Notes: We only need one instance of CDocfileUnmarshalFactory.
+// We use a static memory block for that instance (so we
+// can share it). We don't use a static object because
+// we want to avoid the static construction call when this
+// library is loaded.
+//
+//---------------------------------------------------------------
+
+BYTE abCDocfileUnmarshalFactory[sizeof(CDocfileUnmarshalFactory)];
+
+inline void *CDocfileUnmarshalFactory::operator new(size_t size)
+{
+ olAssert(size == sizeof(CDocfileUnmarshalFactory) &&
+ aMsg("Class size mismatch"));
+
+ return(abCDocfileUnmarshalFactory);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::delete, public
+//
+// Synopsis: Overloaded deallocator
+//
+// History: 25-Jun-93 AlexT Created
+//
+// Notes: Should never be called
+//
+//---------------------------------------------------------------
+
+void CDocfileUnmarshalFactory::operator delete(void *pv)
+{
+ olAssert(!aMsg("CDocfileUnmarshalFactory::operator delete called!"));
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_DllGetClassObject) // Marshal_TEXT
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: DllGetClassObject, public
+//
+// Synopsis: Returns class factory objects for CLSID_DfMarshal
+//
+// Arguments: [clsid] - Class ID of object to get
+// [riid] - IID of interface to get
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 26-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+#ifdef WIN32
+HRESULT Storage32DllGetClassObject(REFCLSID clsid, REFIID riid, void **ppv)
+#else
+STDAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void FAR* FAR* ppv)
+#endif // WIN32
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In DllGetClassObject(clsid, riid, %p)\n", ppv));
+ TRY
+ {
+ olChk(ValidatePtrBuffer(ppv));
+ *ppv = NULL;
+ olChk(ValidateIid(riid));
+#if WIN32 >= 300
+ if (IsEqualCLSID(clsid, CLSID_NtHandleMarshal))
+ {
+ if (!IsEqualIID(riid, IID_IUnknown) &&
+ !IsEqualIID(riid, IID_IClassFactory))
+ olErr(EH_Err, E_NOINTERFACE);
+ *ppv = (IClassFactory *) &sCNtHandleUnmarshalFactory;
+ }
+ else
+ {
+#endif
+ if (!IsEqualCLSID(clsid, CLSID_DfMarshal))
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if (!IsEqualIID(riid, IID_IUnknown) &&
+ !IsEqualIID(riid, IID_IClassFactory))
+ olErr(EH_Err, E_NOINTERFACE);
+ // Multiple inits don't hurt
+ *ppv = (IClassFactory *)new CDocfileUnmarshalFactory;
+ olAssert(*ppv != NULL && aMsg("new CDocfileUnmarshalFactory failed!"));
+#if WIN32 >= 300
+ }
+#endif
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_TRACE, "Out DllGetClassObject => %p\n", *ppv));
+ EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+// History: 25-Jan-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDUF_AddRef)
+#endif
+
+STDMETHODIMP_(ULONG) CDocfileUnmarshalFactory::AddRef(void)
+{
+ LONG lRet;
+
+ olLog(("%p::In CDocfileUnmarshalFactory::AddRef()\n", this));
+ olDebugOut((DEB_TRACE, "In CDocfileUnmarshalFactory::AddRef:%p()\n",
+ this));
+ lRet = _AddRef();
+ olDebugOut((DEB_TRACE, "Out CDocfileUnmarshalFactory::AddRef => %ld\n",
+ lRet));
+ olLog(("%p::Out CDocfileUnmarshalFactory::AddRef(). ret == %ld\n",
+ this, lRet));
+ return lRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::Release, public
+//
+// Synopsis: Releases resources
+//
+// Returns: Appropriate status code
+//
+// History: 25-Jan-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDUF_Release)
+#endif
+
+STDMETHODIMP_(ULONG) CDocfileUnmarshalFactory::Release(void)
+{
+ LONG lRet;
+
+ olLog(("%p::In CDocfileUnmarshalFactory::Release()\n", this));
+ olDebugOut((DEB_TRACE, "In CDocfileUnmarshalFactory::Release:%p()\n",
+ this));
+ lRet = 0;
+ olDebugOut((DEB_TRACE, "Out CDocfileUnmarshalFactory::Release => %ld\n",
+ lRet));
+ olLog(("%p::Out CDocfileUnmarshalFactory::Release(). ret == %ld\n",
+ this, lRet));
+ return lRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 25-Jan-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDUF_QueryInterface)
+#endif
+
+STDMETHODIMP CDocfileUnmarshalFactory::QueryInterface(REFIID riid,
+ void **ppv)
+{
+ SCODE sc;
+
+ olLog(("%p::In CDocfileUnmarshalFactory::QueryInterface(riid, %p)\n",
+ this, ppv));
+ olDebugOut((DEB_TRACE, "In CDocfileUnmarshalFactory::QueryInterface:%p("
+ "riid, %p)\n", this, ppv));
+ TRY
+ {
+ olChk(Validate());
+ olChk(ValidateOutPtrBuffer(ppv));
+ *ppv = NULL;
+ olChk(ValidateIid(riid));
+ if (IsEqualIID(riid, IID_IClassFactory) ||
+ IsEqualIID(riid, IID_IUnknown))
+ {
+ _AddRef();
+ *ppv = (IClassFactory *)this;
+ }
+ else if (IsEqualIID(riid, IID_IMarshal))
+ {
+ _AddRef();
+ *ppv = (IMarshal *)this;
+ }
+ else
+ olErr(EH_Err, E_NOINTERFACE);
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_TRACE, "Out CDocfileUnmarshalFactory::QueryInterface => "
+ "%p\n", *ppv));
+EH_Err:
+ olLog(("%p::Out CDocfileUnmarshalFactory::QueryInterface(). "
+ "*ppv == %p, ret == 0x%lX\n", this, *ppv, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::GetUnmarshalClass, public
+//
+// Synopsis: Returns the class ID
+//
+// Arguments: [riid] - IID of object
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+// [pcid] - CLSID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcid]
+//
+// History: 25-Jan-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDUF_GetUnmarshalClass)
+#endif
+
+STDMETHODIMP CDocfileUnmarshalFactory::GetUnmarshalClass(REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pcid)
+{
+ olLog(("%p::INVALID CALL TO CDocfileUnmarshalFactory::GetUnmarshalClass("
+ "riid, %p, %lu, %p, %lu, %p)\n", this, pv, dwDestContext,
+ pvDestContext, mshlflags, pcid));
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::GetMarshalSizeMax, public
+//
+// Synopsis: Returns the size needed for the marshal buffer
+//
+// Arguments: [iid] - IID of object being marshaled
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+// [pcbSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbSize]
+//
+// History: 25-Jan-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDUF_GetMarshalSizeMax)
+#endif
+
+STDMETHODIMP CDocfileUnmarshalFactory::GetMarshalSizeMax(REFIID iid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pcbSize)
+{
+ olLog(("%p::INVALID CALL TO CDocfileUnmarshalFactory::GetMarshalSizeMax("
+ "riid, %p, %lu, %p, %lu, %p)\n",
+ this, pv, dwDestContext, pvDestContext, mshlflags, pcbSize));
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::MarshalInterface, public
+//
+// Synopsis: Marshals a given object
+//
+// Arguments: [pstStm] - Stream to write marshal data into
+// [iid] - Interface to marshal
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+//
+// Returns: Appropriate status code
+//
+// History: 25-Jan-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDUF_MarshalInterface)
+#endif
+
+STDMETHODIMP CDocfileUnmarshalFactory::MarshalInterface(IStream *pstStm,
+ REFIID iid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ olLog(("%p::INVALID CALL TO CDocfileUnmarshalFactory::MarshalInterface("
+ "%p, riid, %p, %lu, %p, %lu). Context == %lX\n",
+ this, pstStm, pv, dwDestContext, pvDestContext, mshlflags,
+ (ULONG)GetCurrentContextId()));
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::UnmarshalInterface, public
+//
+// Synopsis: Calls through to DfUnmarshalInterface
+//
+// Arguments: [pstStm] - Marshal stream
+// [riid] - IID of object to unmarshal
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 25-Jan-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDUF_UnmarshalInterface)
+#endif
+
+STDMETHODIMP CDocfileUnmarshalFactory::UnmarshalInterface(IStream *pstStm,
+ REFIID iid,
+ void **ppv)
+{
+ return DfUnMarshalInterface(pstStm, iid, TRUE, ppv);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::ReleaseMarshalData, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [pstStm] -
+//
+// Returns: Appropriate status code
+//
+// History: 18-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDUF_ReleaseMarshalData)
+#endif
+
+#ifdef WIN32
+STDMETHODIMP CDocfileUnmarshalFactory::ReleaseMarshalData(IStream *pstStm)
+{
+ SCODE sc;
+ IID iid;
+ DWORD mshlflags;
+
+ olLog(("%p::In CDocfileUnmarshalFactory::ReleaseMarshalData(%p)\n",
+ this, pstStm));
+
+ olChk(SkipStdMarshal(pstStm, &iid, &mshlflags));
+ if (IsEqualIID(iid, IID_ILockBytes))
+ {
+ sc = CFileStream::StaticReleaseMarshalData(pstStm, mshlflags);
+ }
+ else if (IsEqualIID(iid, IID_IStorage))
+ {
+ sc = CExposedDocFile::StaticReleaseMarshalData(pstStm, mshlflags);
+ }
+ else if (IsEqualIID(iid, IID_IStream))
+ {
+ sc = CExposedStream::StaticReleaseMarshalData(pstStm, mshlflags);
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ olLog(("%p::Out CDocfileUnmarshalFactory::ReleaseMarshalData, sc == %lX\n",
+ this, sc));
+ EH_Err:
+ return ResultFromScode(sc);
+}
+#else
+STDMETHODIMP CDocfileUnmarshalFactory::ReleaseMarshalData(IStream *pstStm)
+{
+ olLog(("%p::Stb CDocfileUnmarshalFactory::ReleaseMarshalData(%p)\n",
+ this, pstStm));
+ return NOERROR;
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::DisconnectObject, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [dwRevserved] -
+//
+// Returns: Appropriate status code
+//
+// History: 18-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDUF_DisconnectObject)
+#endif
+
+STDMETHODIMP CDocfileUnmarshalFactory::DisconnectObject(DWORD dwReserved)
+{
+ olLog(("%p::Stb CDocfileUnmarshalFactory::DisconnectObject(%lu)\n",
+ this, dwReserved));
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::CreateInstance, public
+//
+// Synopsis: Creates an instance of the docfile IMarshal unmarshaller
+//
+// Arguments: [pUnkOuter] -
+// [riid] - IID of object to create
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 25-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDUF_CreateInstance)
+#endif
+
+STDMETHODIMP CDocfileUnmarshalFactory::CreateInstance(IUnknown *pUnkOuter,
+ REFIID riid,
+ LPVOID *ppv)
+{
+ SCODE sc;
+
+ olLog(("%p::In CDocfileUnmarshalFactory::CreateInstance(%p, riid, %p)\n",
+ this, pUnkOuter, ppv));
+ olDebugOut((DEB_TRACE, "In CDocfileUnmarshalFactory::CreateInstance:%p("
+ "%p, riid, %p)\n", this, pUnkOuter, ppv));
+ TRY
+ {
+ olChk(Validate());
+ olChk(ValidatePtrBuffer(ppv));
+ *ppv = NULL;
+ olChk(ValidateIid(riid));
+ if (pUnkOuter != NULL || !IsEqualIID(riid, IID_IMarshal))
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ _AddRef();
+ *ppv = (IMarshal *)this;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_TRACE, "Out CDocfileUnmarshalFactory::CreateInstance => "
+ "%p\n", ppv));
+ EH_Err:
+ olLog(("%p::Out CDocfileUnmarshalFactory::CreateInstance(). "
+ "*ppv == %p, ret == 0x%lX\n", this, *ppv, sc));
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::LockServer, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [fLock] -
+//
+// Returns: Appropriate status code
+//
+// History: 25-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDUF_LockServer)
+#endif
+
+STDMETHODIMP CDocfileUnmarshalFactory::LockServer(BOOL fLock)
+{
+ olLog(("%p::Stb CDocfileUnmarshalFactory::LockServer(%d)\n",
+ this, fLock));
+ return NOERROR;
+}
diff --git a/private/ole32/stg/exp/dfunmfct.hxx b/private/ole32/stg/exp/dfunmfct.hxx
new file mode 100644
index 000000000..9843a80dc
--- /dev/null
+++ b/private/ole32/stg/exp/dfunmfct.hxx
@@ -0,0 +1,155 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dfunmfct.hxx
+//
+// Contents: OLE2 unmarshalling support for docfiles
+//
+// Classes: CDocfileUnmarshalFactory
+//
+// History: 25-Jan-93 DrewB Created
+//
+// Notes: Adapted from OLE2 dfmarshl.h and defcf.cpp
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DFUNMFCT_HXX__
+#define __DFUNMFCT_HXX__
+
+#include <dfentry.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: CDocfileUnmarshalFactory (dfuf)
+//
+// Purpose: Implements OLE2 unmarshalling support
+//
+// Interface: See below
+//
+// History: 25-Jan-93 DrewB Created
+//
+// Notes: This class is intended to be used statically
+// rather than dynamically with initialization being
+// deferred past construction to avoid unnecessary
+// initialization of static objects.
+// Init should be called to initialize in place of
+// a constructor.
+//
+//----------------------------------------------------------------------------
+
+#ifndef FLAT
+// C700 - C7 doesn't like long interface+method names
+#define CDocfileUnmarshalFactory CDFUF
+#endif
+
+class CDocfileUnmarshalFactory : public IMarshal, public IClassFactory
+{
+public:
+ inline void *operator new(size_t size);
+ inline void operator delete(void *pv);
+
+ inline CDocfileUnmarshalFactory(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // IMarshal
+ STDMETHOD(GetUnmarshalClass)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID *ppv);
+ STDMETHOD(ReleaseMarshalData)(IStream *pStm);
+ STDMETHOD(DisconnectObject)(DWORD dwReserved);
+
+ // IClassFactory
+ STDMETHOD(CreateInstance)(IUnknown *pUnkOuter,
+ REFIID riid,
+ LPVOID *ppunkObject);
+ STDMETHOD(LockServer)(BOOL fLock);
+
+ // New methods
+ inline SCODE Validate(void) const;
+
+private:
+ inline LONG _AddRef(void);
+
+ ULONG _sig;
+};
+
+#define CDOCFILEUNMARSHALFACTORY_SIG LONGSIG('D', 'F', 'U', 'F')
+#define CDOCFILEUNMARSHALFACTORY_SIGDEL LONGSIG('D', 'f', 'U', 'f')
+
+//+--------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::Validate, public
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 25-Jan-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CDocfileUnmarshalFactory::Validate(void) const
+{
+ return (this == NULL || _sig != CDOCFILEUNMARSHALFACTORY_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::AddRef, private
+//
+// Synopsis: Increments the ref count
+//
+// History: 27-Jan-93 DrewB Created
+//
+// Notes: Currently does nothing because we don't maintain a ref count
+// This is present to make switching to a ref counted
+// implementation easy
+//
+//----------------------------------------------------------------------------
+
+inline LONG CDocfileUnmarshalFactory::_AddRef(void)
+{
+ return 1;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileUnmarshalFactory::CDocfileUnmarshalFactory, public
+//
+// Synopsis: Constructor
+//
+// History: 27-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline CDocfileUnmarshalFactory::CDocfileUnmarshalFactory(void)
+{
+ _sig = CDOCFILEUNMARSHALFACTORY_SIG;
+}
+
+#endif // #ifndef __DFUNMFCT_HXX__
diff --git a/private/ole32/stg/exp/dirs b/private/ole32/stg/exp/dirs
new file mode 100644
index 000000000..ddf44d103
--- /dev/null
+++ b/private/ole32/stg/exp/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/stg/exp/dllentry.c b/private/ole32/stg/exp/dllentry.c
new file mode 100644
index 000000000..8ed416eee
--- /dev/null
+++ b/private/ole32/stg/exp/dllentry.c
@@ -0,0 +1,59 @@
+#include <stdlib.h>
+#include <windows.h>
+
+BOOL WINAPI _CRT_INIT (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
+
+#ifdef HAS_LIBMAIN
+BOOL _CRTAPI1 LibMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
+#else
+#define LibMain(h, d, l) TRUE
+#endif
+
+#if WIN32 == 50
+BOOL fWin32s = FALSE;
+extern void DfDebug(ULONG, ULONG);
+#endif
+
+int _CRTAPI1 atexit(void (_CRTAPI1 *pfn)(void))
+{
+ // Do nothing
+ return 0;
+}
+
+BOOL __stdcall DllEntryPoint (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
+{
+ BOOL fRc;
+// char msg[80];
+#if WIN32 == 50
+ DWORD dwVer;
+#endif
+
+ switch(dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+// DebugBreak();
+#if DBG == 1 && WIN32 == 50
+ dwVer = GetVersion();
+ if (dwVer & 0x80000000)
+ {
+ ULONG uOLevel;
+
+ fWin32s = TRUE;
+ uOLevel = (ULONG)GetPrivateProfileIntA("Win32sDbg", "docfile",
+ 0, "system.ini");
+ DfDebug(uOLevel, uOLevel);
+ }
+#endif
+ break;
+ }
+ if (fRc = _CRT_INIT(hDll, dwReason, lpReserved))
+ fRc = LibMain(hDll, dwReason, lpReserved);
+ switch(dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+// wsprintfA(msg, "Storag32 returning %d on attach\r\n", fRc);
+// OutputDebugStringA(msg);
+ break;
+ }
+ return fRc;
+}
diff --git a/private/ole32/stg/exp/docfile.cxx b/private/ole32/stg/exp/docfile.cxx
new file mode 100644
index 000000000..73d00809a
--- /dev/null
+++ b/private/ole32/stg/exp/docfile.cxx
@@ -0,0 +1,1141 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: docfile.c
+//
+// Contents: DocFile root functions (Stg* functions)
+//
+// History: 10-Dec-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <rpubdf.hxx>
+#include <expdf.hxx>
+#include <expst.hxx>
+#include <dfentry.hxx>
+#include <logfile.hxx>
+#include <dirfunc.hxx>
+#include <wdocfile.hxx>
+
+#include <ole2sp.h>
+#include <ole2com.h>
+#include <hkole32.h>
+
+#ifdef COORD
+#include <resource.hxx>
+#endif
+
+#ifdef _MAC
+#include <ole2sp.h>
+#endif
+
+//+--------------------------------------------------------------
+//
+// Function: DfFromLB, private
+//
+// Synopsis: Starts a root Docfile on an ILockBytes
+//
+// Arguments: [plst] - LStream to start on
+// [df] - Permissions
+// [dwStartFlags] - Startup flags
+// [snbExclude] - Partial instantiation list
+// [ppdfExp] - DocFile return
+// [pcid] - Class ID return for opens
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdfExp]
+// [pcid]
+//
+// History: 19-Mar-92 DrewB Created
+// 18-May-93 AlexT Added pMalloc
+//
+// Algorithm: Create and initialize a root transaction level
+// Create and initialize a public docfile
+// Create and initialize an exposed docfile
+//
+//---------------------------------------------------------------
+
+
+#ifdef COORD
+SCODE DfFromLB(CPerContext *ppc,
+ ILockBytes *plst,
+ DFLAGS df,
+ DWORD dwStartFlags,
+ SNBW snbExclude,
+ ITransaction *pTransaction,
+ CExposedDocFile **ppdfExp,
+ CLSID *pcid)
+#else
+SCODE DfFromLB(CPerContext *ppc,
+ ILockBytes *plst,
+ DFLAGS df,
+ DWORD dwStartFlags,
+ SNBW snbExclude,
+ CExposedDocFile **ppdfExp,
+ CLSID *pcid)
+#endif //COORD
+{
+ SCODE sc, scConv;
+ CRootPubDocFile *prpdf;
+
+#ifdef COORD
+ CPubDocFile *ppubdf;
+ CPubDocFile *ppubReturn;
+ CWrappedDocFile *pwdf;
+ CDocfileResource *pdfr = NULL;
+#endif
+
+ CDFBasis *pdfb;
+ ULONG ulOpenLock;
+ IMalloc *pMalloc = ppc->GetMalloc();
+
+ ppc->AddRef();
+
+ olDebugOut((DEB_ITRACE, "In DfFromLB(%p, %p, %X, %lX, %p, %p, %p)\n",
+ pMalloc, plst, df, dwStartFlags, snbExclude, ppdfExp, pcid));
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_ILockBytes,(IUnknown **)&plst);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IMalloc,(IUnknown **)&pMalloc);
+
+ //Take the mutex in the CPerContext, in case there is an IFillLockBytes
+ // trying to write data while we're trying to open.
+ CSafeSem _ss(ppc);
+ olChk(_ss.Take());
+
+ // For NT 1.0 we must ensure that the DLL is at the proper base
+ // address since we'll have vtable pointers in shared memory and
+ // they must work from every process that accesses them
+ // 16-bit and Chicago have global shared memory
+ // In later version of NT we'll either be in the kernel or a system DLL
+ // with a guaranteed base address
+#if WIN32 == 100
+ olChk(DfCheckBaseAddress());
+#endif
+
+#ifdef CHECKCID
+ ULONG cbRead;
+ olChk(plst->ReadAt(CBCLSIDOFFSET, pcid, sizeof(CLSID), &cbRead));
+ if (cbRead != sizeof(CLSID))
+ olErr(EH_Err, STG_E_INVALIDHEADER);
+ if (!REFCLSIDEQ(*pcid, DOCFILE_CLASSID))
+ olErr(EH_Err, STG_E_INVALIDHEADER);
+#endif
+
+#ifdef COORD
+
+ if (pTransaction != NULL)
+ {
+ //If we've passed in an ITransaction pointer, it indicates that we
+ // want to open or create this docfile as part of a coordinated
+ // transaction. First, we need to find out if there's a docfile
+ // resource manager for that transaction currently existing in
+ // this process.
+ //First, check if we're opening transacted. If we aren't, then we're
+ // not going to allow this docfile to participate in the
+ // transaction.
+ // BUGBUG: Do we really need this restriction?
+
+ if (!P_TRANSACTED(df))
+ {
+ //Is this the right error?
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ }
+ XACTTRANSINFO xti;
+ olChk(pTransaction->GetTransactionInfo(&xti));
+
+ EnterCriticalSection(&g_csResourceList);
+ CDocfileResource *pdfrTemp = g_dfrHead.GetNext();
+
+ while (pdfrTemp != NULL)
+ {
+ if (IsEqualBOID(pdfrTemp->GetUOW(), xti.uow))
+ {
+ //Direct hit.
+ pdfr = pdfrTemp;
+ break;
+ }
+ pdfrTemp = pdfrTemp->GetNext();
+ }
+
+ if (pdfr == NULL)
+ {
+ ITransactionCoordinator *ptc;
+ //If there isn't, we need to create one.
+
+ olChkTo(EH_cs, pTransaction->QueryInterface(
+ IID_ITransactionCoordinator,
+ (void **)&ptc));
+
+ pdfr = new CDocfileResource;
+ if (pdfr == NULL)
+ {
+ ptc->Release();
+ olErr(EH_cs, STG_E_INSUFFICIENTMEMORY);
+ }
+ sc = pdfr->Enlist(ptc);
+ ptc->Release();
+ if (FAILED(sc))
+ {
+ pdfr->Release();;
+ olErr(EH_cs, sc);
+ }
+
+ //Add to list.
+ pdfr->SetNext(g_dfrHead.GetNext());
+ if (g_dfrHead.GetNext() != NULL)
+ g_dfrHead.GetNext()->SetPrev(pdfr);
+ g_dfrHead.SetNext(pdfr);
+ pdfr->SetPrev(&g_dfrHead);
+ }
+ else
+ {
+ //We'll release this reference below.
+ pdfr->AddRef();
+ }
+ LeaveCriticalSection(&g_csResourceList);
+ }
+#endif
+
+ // Make root
+ olMem(prpdf = new (pMalloc) CRootPubDocFile(pMalloc));
+ olChkTo(EH_prpdf, scConv = prpdf->InitRoot(plst, dwStartFlags, df,
+ snbExclude, &pdfb,
+ &ulOpenLock));
+
+#ifdef COORD
+#ifdef HACK_COORD
+ if (P_TRANSACTED(df))
+#else
+ if (pTransaction != NULL)
+#endif
+ {
+ //Set up a fake transaction level at the root. A pointer to
+ // this will be held by the resource manager. The storage pointer
+ // that is passed back to the caller will be a pointer to the
+ // transaction level (non-root) below it. This will allow the
+ // client to write and commit as many times as desired without
+ // the changes ever actually hitting the file.
+
+ CDfName dfnNull; // auto-initialized to 0
+ WCHAR wcZero = 0;
+ dfnNull.Set(2, (BYTE *)&wcZero);
+
+ olMemTo(EH_prpdfInit, pwdf = new (pMalloc) CWrappedDocFile(
+ &dfnNull,
+ ROOT_LUID,
+ (df & ~DF_INDEPENDENT),
+ pdfb,
+ NULL));
+
+ olChkTo(EH_pwdf, pwdf->Init(prpdf->GetDF()));
+ prpdf->GetDF()->AddRef();
+
+ olMemTo(EH_pwdfInit, ppubdf = new (pMalloc) CPubDocFile(
+ prpdf,
+ pwdf,
+ (df | DF_COORD) & ~DF_INDEPENDENT,
+ ROOT_LUID,
+ pdfb,
+ &dfnNull,
+ 2,
+ pdfb->GetBaseMultiStream()));
+
+ olChkTo(EH_ppubdf, pwdf->InitPub(ppubdf));
+ ppubdf->AddXSMember(NULL, pwdf, ROOT_LUID);
+
+ ppubReturn = ppubdf;
+ }
+ else
+ {
+ ppubReturn = prpdf;
+ }
+#endif //COORD
+
+
+ ppc->SetILBInfo(pdfb->GetBase(),
+ pdfb->GetDirty(),
+ pdfb->GetOriginal(),
+ ulOpenLock);
+ ppc->SetLockInfo(ulOpenLock != 0, df);
+ // Make exposed
+
+#ifdef COORD
+ //We don't need to AddRef ppc since it starts with a refcount of 1.
+ olMemTo(EH_ppcInit,
+ *ppdfExp = new (pMalloc) CExposedDocFile(
+ ppubReturn,
+ pdfb,
+ ppc,
+ TRUE));
+
+ if (pTransaction != NULL)
+ {
+ CExposedDocFile *pexpdf;
+
+ olMemTo(EH_ppcInit, pexpdf = new (pMalloc) CExposedDocFile(
+ prpdf,
+ pdfb,
+ ppc,
+ TRUE));
+ ppc->AddRef();
+
+ sc = pdfr->Join(pexpdf);
+ if (FAILED(sc))
+ {
+ pexpdf->Release();
+ olErr(EH_ppcInit, sc);
+ }
+ pdfr->Release();
+ }
+#else
+ olMemTo(EH_ppcInit,
+ *ppdfExp = new (pMalloc) CExposedDocFile(
+ prpdf,
+ pdfb,
+ ppc,
+ TRUE));
+#endif //COORD
+
+
+ olDebugOut((DEB_ITRACE, "Out DfFromLB => %p\n", *ppdfExp));
+ return scConv;
+
+ EH_ppcInit:
+ // The context will release this but we want to keep it around
+ // so take a reference
+ pdfb->GetOriginal()->AddRef();
+ pdfb->GetBase()->AddRef();
+ pdfb->GetDirty()->AddRef();
+ if (ulOpenLock > 0 && ppc->GetGlobal() == NULL)
+ {
+ // The global context doesn't exist, so we need to release
+ // the open lock explicitly.
+
+ ReleaseOpen(pdfb->GetOriginal(), df, ulOpenLock);
+ }
+
+ // The open lock has now been released (either explicitly or by ppc)
+ ulOpenLock = 0;
+#ifdef COORD
+EH_ppubdf:
+ if (pTransaction != NULL)
+ {
+ ppubdf->vRelease();
+ }
+EH_pwdfInit:
+ if (pTransaction != NULL)
+ {
+ prpdf->GetDF()->Release();
+ }
+EH_pwdf:
+ if (pTransaction != NULL)
+ {
+ pwdf->Release();
+ }
+ EH_prpdfInit:
+#endif //COORD
+ pdfb->GetDirty()->Release();
+ pdfb->GetBase()->Release();
+ if (ulOpenLock > 0)
+ ReleaseOpen(pdfb->GetOriginal(), df, ulOpenLock);
+
+ pdfb->SetDirty(NULL);
+ pdfb->SetBase(NULL);
+
+ EH_prpdf:
+ prpdf->ReleaseLocks(plst);
+ prpdf->vRelease();
+#ifdef COORD
+ if ((pTransaction != NULL) && (pdfr != NULL))
+ {
+ pdfr->Release();
+ }
+ goto EH_Err;
+ EH_cs:
+ LeaveCriticalSection(&g_csResourceList);
+#endif
+
+ EH_Err:
+ ppc->Release();
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: DfFromName, private
+//
+// Synopsis: Starts a root DocFile from a base name
+//
+// Arguments: [pwcsName] - Name
+// [df] - Permissions
+// [dwStartFlags] - Startup flags
+// [snbExclude] - Partial instantiation list
+// [ppdfExp] - Docfile return
+// [pcid] - Class ID return for opens
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdfExp]
+// [pcid]
+//
+// History: 19-Mar-92 DrewB Created
+// 18-May-93 AlexT Add per file allocator
+//
+// Notes: [pwcsName] is treated as unsafe memory
+//
+//---------------------------------------------------------------
+
+
+// This set of root startup flags is handled by the multistream
+// and doesn't need to be set for filestreams
+#define RSF_MSF (RSF_CONVERT | RSF_TRUNCATE)
+
+#ifdef COORD
+SCODE DfFromName(WCHAR const *pwcsName,
+ DFLAGS df,
+ DWORD dwStartFlags,
+ SNBW snbExclude,
+ ITransaction *pTransaction,
+ CExposedDocFile **ppdfExp,
+ CLSID *pcid)
+#else
+SCODE DfFromName(WCHAR const *pwcsName,
+ DFLAGS df,
+ DWORD dwStartFlags,
+ SNBW snbExclude,
+ CExposedDocFile **ppdfExp,
+ CLSID *pcid)
+#endif
+{
+ IMalloc *pMalloc;
+ CFileStream *plst;
+ CPerContext *ppc;
+ SCODE sc;
+ BOOL fCreated;
+
+ olDebugOut((DEB_ITRACE, "In DfFromName(%ws, %lX, %lX, %p, %p, %p)\n",
+ pwcsName, df, dwStartFlags, snbExclude, ppdfExp, pcid));
+
+ olHChk(DfCreateSharedAllocator(&pMalloc));
+
+ // Start an ILockBytes from the named file
+ olMemTo(EH_Malloc, plst = new (pMalloc) CFileStream(pMalloc));
+ olChkTo(EH_plst, plst->InitFlags(dwStartFlags & ~RSF_MSF, df));
+ sc = plst->Init(pwcsName);
+ fCreated = SUCCEEDED(sc) &&
+ ((dwStartFlags & RSF_CREATE) || pwcsName == NULL);
+ if (sc == STG_E_FILEALREADYEXISTS && (dwStartFlags & RSF_MSF))
+ {
+ plst->SetStartFlags(dwStartFlags & ~(RSF_MSF | RSF_CREATE));
+ sc = plst->Init(pwcsName);
+ }
+ olChkTo(EH_plst, sc);
+
+
+ //Create the per context
+ olMemTo(EH_plstInit, ppc = new (pMalloc) CPerContext(pMalloc));
+ olChkTo(EH_ppc, ppc->InitNewContext());
+
+ {
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(ppc);
+#endif
+
+ // Start up the docfile
+#ifdef COORD
+ sc = DfFromLB(ppc, plst, df, dwStartFlags,
+ snbExclude, pTransaction,
+ ppdfExp, pcid);
+#else
+ sc = DfFromLB(ppc, plst, df, dwStartFlags,
+ snbExclude, ppdfExp, pcid);
+#endif //COORD
+
+ //Either DfFromLB has AddRef'ed the per context or it has failed.
+ //Either way we want to release our reference here.
+ ppc->Release();
+ if (FAILED(sc))
+ {
+ if (fCreated || ((dwStartFlags & RSF_CREATE) && !P_TRANSACTED(df)))
+ plst->Delete();
+ plst->Release();
+ }
+ }
+ pMalloc->Release();
+
+ olDebugOut((DEB_ITRACE, "Out DfFromName => %p\n", *ppdfExp));
+ return sc;
+EH_ppc:
+ delete ppc;
+EH_plstInit:
+ if (fCreated || ((dwStartFlags & RSF_CREATE) && !P_TRANSACTED(df)))
+ plst->Delete();
+EH_plst:
+ plst->Release();
+EH_Malloc:
+ pMalloc->Release();
+EH_Err:
+ return sc;
+}
+
+// This function is renamed in Cairo, for which StgCreateDocfile
+// is a simple wrapper over DfCreateDocfile -- see ..\fsstg\api.cxx
+#if !defined(REF)
+
+
+//+--------------------------------------------------------------
+//
+// Function: StgCreateDocfile, public
+//
+// Synopsis: Creates a root Docfile on a file
+//
+// Arguments: [pwcsName] - Filename
+// [grfMode] - Permissions
+// [reserved]
+// [ppstgOpen] - Docfile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstgOpen]
+//
+// History: 14-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDAPI DfCreateDocfile (WCHAR const *pwcsName,
+#ifdef COORD
+ ITransaction *pTransaction,
+#else
+ void *pTransaction,
+#endif
+ DWORD grfMode,
+#if WIN32 == 300
+ LPSECURITY_ATTRIBUTES reserved,
+#else
+ LPSTGSECURITY reserved,
+#endif
+ IStorage **ppstgOpen)
+{
+ SafeCExposedDocFile pdfExp;
+ SCODE sc;
+ DFLAGS df;
+
+ OLETRACEIN((API_StgCreateDocfile,
+ PARAMFMT("pwcsName= %ws, grfMode= %x, reserved=%p, ppstgOpen= %p"),
+ pwcsName, grfMode, reserved, ppstgOpen));
+
+ olLog(("--------::In StgCreateDocFile(%ws, %lX, %lu, %p)\n",
+ pwcsName, grfMode, reserved, ppstgOpen));
+ olDebugOut((DEB_TRACE, "In StgCreateDocfile(%ws, %lX, %lu, %p)\n",
+ pwcsName, grfMode, reserved, ppstgOpen));
+
+ olAssert(sizeof(LPSTGSECURITY) == sizeof(DWORD));
+
+ olChkTo(EH_BadPtr, ValidatePtrBuffer(ppstgOpen));
+ *ppstgOpen = NULL;
+ if (pwcsName)
+ olChk(ValidateNameW(pwcsName, _MAX_PATH));
+ if (reserved != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+
+ if (grfMode & STGM_SIMPLE)
+ {
+ if (pTransaction != NULL)
+ {
+ //BUGBUG: Is this the right error code?
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ }
+ sc = DfCreateSimpDocfile(pwcsName, grfMode, 0, ppstgOpen);
+ goto EH_Err;
+ }
+
+ olChk(VerifyPerms(grfMode));
+ if ((grfMode & STGM_RDWR) == STGM_READ ||
+ (grfMode & (STGM_DELETEONRELEASE | STGM_CONVERT)) ==
+ (STGM_DELETEONRELEASE | STGM_CONVERT))
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ df = ModeToDFlags(grfMode);
+ if ((grfMode & (STGM_TRANSACTED | STGM_CONVERT)) ==
+ (STGM_TRANSACTED | STGM_CONVERT))
+ df |= DF_INDEPENDENT;
+
+ DfInitSharedMemBase();
+#ifdef COORD
+ olChk(sc = DfFromName(pwcsName, df,
+ RSF_CREATE |
+ ((grfMode & STGM_CREATE) ? RSF_TRUNCATE : 0) |
+ ((grfMode & STGM_CONVERT) ? RSF_CONVERT : 0) |
+ ((grfMode & STGM_DELETEONRELEASE) ?
+ RSF_DELETEONRELEASE : 0),
+ NULL, pTransaction, &pdfExp, NULL));
+#else
+ olChk(sc = DfFromName(pwcsName, df,
+ RSF_CREATE |
+ ((grfMode & STGM_CREATE) ? RSF_TRUNCATE : 0) |
+ ((grfMode & STGM_CONVERT) ? RSF_CONVERT : 0) |
+ ((grfMode & STGM_DELETEONRELEASE) ?
+ RSF_DELETEONRELEASE : 0),
+ NULL, &pdfExp, NULL));
+#endif //COORD
+
+ TRANSFER_INTERFACE(pdfExp, IStorage, ppstgOpen);
+ CALLHOOKOBJECTCREATE(_OLERETURN(sc),CLSID_NULL,IID_IStorage,
+ (IUnknown **)ppstgOpen);
+
+EH_Err:
+ olDebugOut((DEB_TRACE, "Out StgCreateDocfile => %p, ret == %lx\n",
+ *ppstgOpen, sc));
+ olLog(("--------::Out StgCreateDocFile(). *ppstgOpen == %p, ret == %lx\n",
+ *ppstgOpen, sc));
+
+ OLETRACEOUT(( API_StgCreateDocfile, _OLERETURN(sc)));
+
+EH_BadPtr:
+ FreeLogFile();
+ return _OLERETURN(sc);
+}
+
+#if WIN32 < 300
+_OLEAPIDECL _OLEAPI(StgCreateDocfile)(WCHAR const *pwcsName,
+ DWORD grfMode,
+ LPSTGSECURITY reserved,
+ IStorage **ppstgOpen)
+{
+ return DfCreateDocfile(pwcsName, NULL, grfMode, reserved, ppstgOpen);
+}
+#endif
+
+
+#endif //!REF && !_CAIRO_
+
+//+--------------------------------------------------------------
+//
+// Function: StgCreateDocfileOnILockBytes, public
+//
+// Synopsis: Creates a root Docfile on an lstream
+//
+// Arguments: [plkbyt] - LStream
+// [grfMode] - Permissions
+// [reserved] - Unused
+// [ppstgOpen] - Docfile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstgOpen]
+//
+// History: 14-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDAPI StgCreateDocfileOnILockBytes(ILockBytes *plkbyt,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage **ppstgOpen)
+{
+ IMalloc *pMalloc;
+ CPerContext *ppc;
+ SafeCExposedDocFile pdfExp;
+ SCODE sc;
+ DFLAGS df;
+#ifdef MULTIHEAP
+ CPerContext pcSharedMemory (NULL);
+#endif
+
+ OLETRACEIN((API_StgCreateDocfileOnILockBytes,
+ PARAMFMT("plkbyt= %p, grfMode= %x, reserved= %ud, ppstgOpen= %p"),
+ plkbyt, grfMode, reserved, ppstgOpen));
+
+ olLog(("--------::In StgCreateDocFileOnILockBytes(%p, %lX, %lu, %p)\n",
+ plkbyt, grfMode, reserved, ppstgOpen));
+ olDebugOut((DEB_TRACE, "In StgCreateDocfileOnILockBytes("
+ "%p, %lX, %lu, %p)\n",
+ plkbyt, grfMode, reserved, ppstgOpen));
+
+ olChk(ValidatePtrBuffer(ppstgOpen));
+ *ppstgOpen = NULL;
+ olChk(ValidateInterface(plkbyt, IID_ILockBytes));
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_ILockBytes,(IUnknown **)&plkbyt);
+
+ if (reserved != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if ((grfMode & (STGM_CREATE | STGM_CONVERT)) == 0)
+ olErr(EH_Err, STG_E_FILEALREADYEXISTS);
+ olChk(VerifyPerms(grfMode));
+ if (grfMode & STGM_DELETEONRELEASE)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ df = ModeToDFlags(grfMode);
+ if ((grfMode & (STGM_TRANSACTED | STGM_CONVERT)) ==
+ (STGM_TRANSACTED | STGM_CONVERT))
+ df |= DF_INDEPENDENT;
+
+ DfInitSharedMemBase();
+ olHChk(DfCreateSharedAllocator(&pMalloc));
+#ifdef MULTIHEAP
+ // Because a custom ILockbytes can call back into storage code,
+ // possibly using another shared heap, we need a temporary
+ // owner until the real CPerContext is allocated
+ // new stack frame for CSafeMultiHeap constructor/destructor
+ {
+ pcSharedMemory.GetThreadAllocatorState();
+ CSafeMultiHeap smh(&pcSharedMemory);
+#endif
+
+ //Create the per context
+ olMem(ppc = new (pMalloc) CPerContext(pMalloc));
+ olChkTo(EH_ppc, ppc->InitNewContext());
+
+#ifdef COORD
+ sc = DfFromLB(ppc, plkbyt, df,
+ RSF_CREATE |
+ ((grfMode & STGM_CREATE) ? RSF_TRUNCATE : 0) |
+ ((grfMode & STGM_CONVERT) ? RSF_CONVERT : 0),
+ NULL, NULL, &pdfExp, NULL);
+#else
+ sc = DfFromLB(ppc, plkbyt, df,
+ RSF_CREATE |
+ ((grfMode & STGM_CREATE) ? RSF_TRUNCATE : 0) |
+ ((grfMode & STGM_CONVERT) ? RSF_CONVERT : 0),
+ NULL, &pdfExp, NULL);
+#endif //COORD
+
+ pMalloc->Release();
+
+ //Either DfFromLB has AddRef'ed the per context or it has failed.
+ //Either way we want to release our reference here.
+ ppc->Release();
+
+ olChkTo(EH_Truncate, sc);
+
+ TRANSFER_INTERFACE(pdfExp, IStorage, ppstgOpen);
+ CALLHOOKOBJECTCREATE(ResultFromScode(sc),CLSID_NULL,IID_IStorage,
+ (IUnknown **)ppstgOpen);
+
+ // Success; since we hold on to the ILockBytes interface,
+ // we must take a reference to it.
+ plkbyt->AddRef();
+
+ olDebugOut((DEB_TRACE, "Out StgCreateDocfileOnILockBytes => %p\n",
+ *ppstgOpen));
+#ifdef MULTIHEAP
+ }
+#endif
+ EH_Err:
+ OLETRACEOUT((API_StgCreateDocfileOnILockBytes, ResultFromScode(sc)));
+
+ olLog(("--------::Out StgCreateDocFileOnILockBytes(). "
+ "*ppstgOpen == %p, ret == %lx\n", *ppstgOpen, sc));
+ FreeLogFile();
+ return ResultFromScode(sc);
+
+ EH_ppc:
+ delete ppc;
+ goto EH_Err;
+
+ EH_Truncate:
+ if ((grfMode & STGM_CREATE) && (grfMode & STGM_TRANSACTED) == 0)
+ {
+ ULARGE_INTEGER ulSize;
+
+ ULISet32(ulSize, 0);
+ olHVerSucc(plkbyt->SetSize(ulSize));
+ }
+ goto EH_Err;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: OpenStorage, public
+//
+// Synopsis: Instantiates a root Docfile from a file,
+// converting if necessary
+//
+// Arguments: [pwcsName] - Name
+// [pstgPriority] - Priority mode reopen IStorage
+// [grfMode] - Permissions
+// [snbExclude] - Exclusions for priority reopen
+// [reserved]
+// [ppstgOpen] - Docfile return
+// [pcid] - Class ID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstgOpen]
+// [pcid]
+//
+// History: 14-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+SCODE _OLEAPI(OpenStorage)(WCHAR const *pwcsName,
+#ifdef COORD
+ ITransaction *pTransaction,
+#else
+ void *pTransaction,
+#endif
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNBW snbExclude,
+#if WIN32 == 300
+ LPSECURITY_ATTRIBUTES reserved,
+#else
+ LPSTGSECURITY reserved,
+#endif
+ IStorage **ppstgOpen,
+ CLSID *pcid)
+{
+ SafeCExposedDocFile pdfExp;
+ SCODE sc;
+ WCHAR awcName[_MAX_PATH];
+
+ olLog(("--------::In OpenStorage(%ws, %p, %lX, %p, %lu, %p, %p)\n",
+ pwcsName, pstgPriority, grfMode, snbExclude, reserved, ppstgOpen,
+ pcid));
+ olDebugOut((DEB_TRACE, "In OpenStorage("
+ "%ws, %p, %lX, %p, %lu, %p, %p)\n", pwcsName, pstgPriority,
+ grfMode, snbExclude, reserved, ppstgOpen, pcid));
+
+ olAssert(sizeof(LPSTGSECURITY) == sizeof(DWORD));
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pstgPriority);
+
+ olChk(ValidatePtrBuffer(ppstgOpen));
+ *ppstgOpen = NULL;
+ if (pstgPriority == NULL)
+ {
+ olChk(ValidateNameW(pwcsName, _MAX_PATH));
+ lstrcpyW(awcName, pwcsName);
+ }
+ if (pstgPriority)
+ {
+ STATSTG stat;
+
+ olChk(ValidateInterface(pstgPriority, IID_IStorage));
+ olHChk(pstgPriority->Stat(&stat, 0));
+ lstrcpyW(awcName, stat.pwcsName);
+ TaskMemFree(stat.pwcsName);
+ }
+ olChk(VerifyPerms(grfMode));
+ if (grfMode & (STGM_CREATE | STGM_CONVERT))
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ if (snbExclude)
+ {
+ if ((grfMode & STGM_RDWR) != STGM_READWRITE)
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+ olChk(ValidateSNB(snbExclude));
+ }
+ if (reserved != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if (grfMode & STGM_DELETEONRELEASE)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ if (pstgPriority)
+ olChk(pstgPriority->Release());
+
+ DfInitSharedMemBase();
+#ifdef COORD
+ olChk(DfFromName(awcName, ModeToDFlags(grfMode), RSF_OPEN |
+ ((grfMode & STGM_DELETEONRELEASE) ?
+ RSF_DELETEONRELEASE : 0),
+ snbExclude, pTransaction, &pdfExp, pcid));
+#else
+ olChk(DfFromName(awcName, ModeToDFlags(grfMode), RSF_OPEN |
+ ((grfMode & STGM_DELETEONRELEASE) ?
+ RSF_DELETEONRELEASE : 0),
+ snbExclude, &pdfExp, pcid));
+#endif //COORD
+
+ TRANSFER_INTERFACE(pdfExp, IStorage, ppstgOpen);
+ CALLHOOKOBJECTCREATE(ResultFromScode(sc),CLSID_NULL,IID_IStorage,
+ (IUnknown **)ppstgOpen);
+
+ olDebugOut((DEB_TRACE, "Out OpenStorage => %p\n", *ppstgOpen));
+EH_Err:
+ olLog(("--------::Out OpenStorage(). *ppstgOpen == %p, ret == %lx\n",
+ *ppstgOpen, sc));
+ FreeLogFile();
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: OpenStorageOnILockBytes, public
+//
+// Synopsis: Instantiates a root Docfile from an LStream,
+// converting if necessary
+//
+// Arguments: [plkbyt] - Source LStream
+// [pstgPriority] - For priority reopens
+// [grfMode] - Permissions
+// [snbExclude] - For priority reopens
+// [reserved]
+// [ppstgOpen] - Docfile return
+// [pcid] - Class ID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstgOpen]
+// [pcid]
+//
+// History: 14-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+SCODE _OLEAPI(OpenStorageOnILockBytes)(ILockBytes *plkbyt,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNBW snbExclude,
+ DWORD reserved,
+ IStorage **ppstgOpen,
+ CLSID *pcid)
+{
+ IMalloc *pMalloc;
+ CPerContext *ppc;
+ SCODE sc;
+ SafeCExposedDocFile pdfExp;
+#ifdef MULTIHEAP
+ CPerContext pcSharedMemory(NULL);
+#endif
+
+ olLog(("--------::In OpenStorageOnILockBytes("
+ "%p, %p, %lX, %p, %lu, %p, %p)\n",
+ plkbyt, pstgPriority, grfMode, snbExclude, reserved, ppstgOpen,
+ pcid));
+ olDebugOut((DEB_TRACE, "In OpenStorageOnILockBytes("
+ "%p, %p, %lX, %p, %lu, %p, %p)\n", plkbyt, pstgPriority,
+ grfMode, snbExclude, reserved, ppstgOpen, pcid));
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_ILockBytes,(IUnknown **)&plkbyt);
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pstgPriority);
+
+ olChk(ValidatePtrBuffer(ppstgOpen));
+ *ppstgOpen = NULL;
+ olChk(ValidateInterface(plkbyt, IID_ILockBytes));
+ if (pstgPriority)
+ olChk(ValidateInterface(pstgPriority, IID_IStorage));
+ olChk(VerifyPerms(grfMode));
+ if (grfMode & (STGM_CREATE | STGM_CONVERT))
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ if (grfMode & STGM_DELETEONRELEASE)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ if (snbExclude)
+ {
+ if ((grfMode & STGM_RDWR) != STGM_READWRITE)
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+ olChk(ValidateSNB(snbExclude));
+ }
+ if (reserved != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if (pstgPriority)
+ olChk(pstgPriority->Release());
+
+ IFileLockBytes *pfl;
+ if (SUCCEEDED(plkbyt->QueryInterface(IID_IFileLockBytes,
+ (void **)&pfl)) &&
+ ((CFileStream *)plkbyt)->GetContextPointer() != NULL)
+ {
+ //Someone passed us the ILockBytes we gave them from
+ //StgGetIFillLockBytesOnFile. It already contains a
+ //context pointer, so reuse that rather than creating
+ //a whole new shared heap.
+ pfl->Release();
+ CFileStream *pfst = (CFileStream *)plkbyt;
+ CPerContext *ppc = pfst->GetContextPointer();
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(ppc);
+#endif
+#ifdef COORD
+ olChk(DfFromLB(ppc,
+ pfst,
+ ModeToDFlags(grfMode),
+ pfst->GetStartFlags(),
+ NULL,
+ NULL,
+ &pdfExp,
+ NULL));
+#else
+ olChk(DfFromLB(ppc,
+ pfst,
+ ModeToDFlags(grfMode),
+ pfst->GetStartFlags(),
+ NULL,
+ &pdfExp,
+ NULL));
+#endif
+ }
+ else
+ {
+ DfInitSharedMemBase();
+ olHChk(DfCreateSharedAllocator(&pMalloc));
+#ifdef MULTIHEAP
+ // Because a custom ILockbytes can call back into storage code,
+ // possibly using another shared heap, we need a temporary
+ // owner until the real CPerContext is allocated
+ // new stack frame for CSafeMultiHeap constructor/destructor
+ {
+ pcSharedMemory.GetThreadAllocatorState();
+ CSafeMultiHeap smh(&pcSharedMemory);
+#endif
+
+ //Create the per context
+ olMem(ppc = new (pMalloc) CPerContext(pMalloc));
+ sc = ppc->InitNewContext();
+ if (FAILED(sc))
+ {
+ delete ppc;
+ olErr(EH_Err, sc);
+ }
+
+#ifdef COORD
+ sc = DfFromLB(ppc,
+ plkbyt, ModeToDFlags(grfMode), RSF_OPEN, snbExclude,
+ NULL, &pdfExp, pcid);
+#else
+ sc = DfFromLB(ppc,
+ plkbyt, ModeToDFlags(grfMode), RSF_OPEN, snbExclude,
+ &pdfExp, pcid);
+#endif //COORD
+
+ pMalloc->Release();
+
+ //Either DfFromLB has AddRef'ed the per context or it has failed.
+ //Either way we want to release our reference here.
+ ppc->Release();
+ olChk(sc);
+#ifdef MULTIHEAP
+ }
+#endif
+ }
+
+ TRANSFER_INTERFACE(pdfExp, IStorage, ppstgOpen);
+ CALLHOOKOBJECTCREATE(ResultFromScode(sc),CLSID_NULL,IID_IStorage,
+ (IUnknown **)ppstgOpen);
+
+ // Success; since we hold on to the ILockBytes interface,
+ // we must take a reference to it.
+ plkbyt->AddRef();
+
+ olDebugOut((DEB_TRACE, "Out OpenStorageOnILockBytes => %p\n",
+ *ppstgOpen));
+
+EH_Err:
+ olLog(("--------::Out OpenStorageOnILockBytes(). "
+ "*ppstgOpen == %p, ret == %lx\n", *ppstgOpen, sc));
+ FreeLogFile();
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DfGetClass, public
+//
+// Synopsis: Retrieves the class ID of the root entry of a docfile
+//
+// Arguments: [hFile] - Docfile file handle
+// [pclsid] - Class ID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pclsid]
+//
+// History: 09-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI DfGetClass(HANDLE hFile,
+ CLSID *pclsid)
+{
+ SCODE sc;
+ DWORD dwCb;
+ IMalloc *pMalloc;
+ CFileStream *pfst;
+ ULARGE_INTEGER uliOffset;
+ ULONG ulOpenLock, ulAccessLock;
+ BYTE bBuffer[sizeof(CMSFHeader)];
+ CMSFHeader *pmsh;
+ CDirEntry *pde;
+
+ olDebugOut((DEB_ITRACE, "In DfGetClass(%p, %p)\n", hFile, pclsid));
+
+ olAssert(sizeof(bBuffer) >= sizeof(CMSFHeader));
+ pmsh = (CMSFHeader *)bBuffer;
+
+ olAssert(sizeof(bBuffer) >= sizeof(CDirEntry));
+ pde = (CDirEntry *)bBuffer;
+
+ if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) != 0)
+ {
+ olErr(EH_Err, LAST_STG_SCODE);
+ }
+ if (!ReadFile(hFile, pmsh->GetData(), sizeof(CMSFHeaderData), &dwCb, NULL))
+ {
+ olErr(EH_Err, LAST_STG_SCODE);
+ }
+ if (dwCb != sizeof(CMSFHeaderData))
+ {
+ olErr(EH_Err, STG_E_INVALIDHEADER);
+ }
+ olChk(pmsh->Validate());
+
+ // Now we know it's a docfile
+
+ DfInitSharedMemBase();
+ olHChk(DfCreateSharedAllocator(&pMalloc));
+ olMemTo(EH_pMalloc, pfst = new (pMalloc) CFileStream(pMalloc));
+ olChkTo(EH_pfst, pfst->InitFlags(0, 0));
+ olChkTo(EH_pfst, pfst->InitFromHandle(hFile));
+
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStream,(IUnknown **)&pfst);
+
+ // Take open and access locks to ensure that we're cooperating
+ // with real opens
+
+ olChkTo(EH_pfst, GetOpen(pfst, DF_READ, TRUE, &ulOpenLock));
+ olChkTo(EH_open, GetAccess(pfst, DF_READ, &ulAccessLock));
+
+ uliOffset.HighPart = 0;
+ uliOffset.LowPart = (pmsh->GetDirStart() << pmsh->GetSectorShift())+
+ HEADERSIZE;
+
+ // The root directory entry is always the first directory entry
+ // in the first directory sector
+
+ // Ideally, we could read just the class ID directly into
+ // pclsid. In practice, all the important things are declared
+ // private or protected so it's easier to read the whole entry
+
+ olChkTo(EH_access, GetScode(pfst->ReadAt(uliOffset, pde,
+ sizeof(CDirEntry), &dwCb)));
+ if (dwCb != sizeof(CDirEntry))
+ {
+ sc = STG_E_READFAULT;
+ }
+ else
+ {
+ sc = S_OK;
+ }
+
+ *pclsid = pde->GetClassId();
+
+ olDebugOut((DEB_ITRACE, "Out DfGetClass\n"));
+ EH_access:
+ ReleaseAccess(pfst, DF_READ, ulAccessLock);
+ EH_open:
+ ReleaseOpen(pfst, DF_READ, ulOpenLock);
+ EH_pfst:
+ pfst->Release();
+ EH_pMalloc:
+ pMalloc->Release();
+ EH_Err:
+ return ResultFromScode(sc);
+}
+
diff --git a/private/ole32/stg/exp/expdf.cxx b/private/ole32/stg/exp/expdf.cxx
new file mode 100644
index 000000000..8b9802feb
--- /dev/null
+++ b/private/ole32/stg/exp/expdf.cxx
@@ -0,0 +1,3079 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: expdf.cxx
+//
+// Contents: Exposed DocFile implementation
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <expdf.hxx>
+#include <expst.hxx>
+#include <expiter.hxx>
+#include <pbstream.hxx>
+#include <lock.hxx>
+#include <marshl.hxx>
+#include <logfile.hxx>
+#include <rpubdf.hxx>
+
+#include <olepfn.hxx>
+
+#include <ole2sp.h>
+#include <ole2com.h>
+
+#if WIN32 == 300
+IMPLEMENT_UNWIND(CSafeAccess);
+IMPLEMENT_UNWIND(CSafeSem);
+#endif
+
+// Check for proper single-instance flags
+#define NOT_SINGLE(md) (((md) & STGM_DENY) != STGM_SHARE_EXCLUSIVE)
+
+#define EnforceSingle(mode) (NOT_SINGLE(mode) ? STG_E_INVALIDFUNCTION : S_OK)
+
+extern WCHAR const wcsContents[];
+
+
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CExposedDocFile, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [pdf] - Public DocFile
+// [pdfb] - DocFile basis
+// [ppc] - Context
+// [fOwnContext] - Whether this object owns the context
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+CExposedDocFile::CExposedDocFile(CPubDocFile *pdf,
+ CDFBasis *pdfb,
+ CPerContext *ppc,
+ BOOL fOwnContext)
+#ifdef NEWPROPS
+#pragma warning(disable: 4355)
+ : CDocFilePropertySetStorage(this, this)
+#pragma warning(default: 4355)
+#endif
+{
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::CExposedDocFile("
+ "%p, %p, %p, %u)\n", pdf, pdfb, ppc, fOwnContext));
+ _ppc = ppc;
+ _fOwnContext = fOwnContext;
+ _pdf = P_TO_BP(CBasedPubDocFilePtr, pdf);
+ _pdfb = P_TO_BP(CBasedDFBasisPtr, pdfb);
+ _pdfb->vAddRef();
+ _cReferences = 1;
+ _sig = CEXPOSEDDOCFILE_SIG;
+#if WIN32 >= 300
+ _pIAC = NULL;
+#endif
+ //
+ // CoQueryReleaseObject needs to have the address of the exposed docfiles
+ // query interface routine.
+ //
+ if (adwQueryInterfaceTable[QI_TABLE_CExposedDocFile] == 0)
+ {
+ adwQueryInterfaceTable[QI_TABLE_CExposedDocFile] =
+ **(DWORD **)((IStorage *)this);
+ }
+
+#ifdef COORD
+ _ulLock = _cbSizeBase = _cbSizeOrig = 0;
+ _sigMSF = 0;
+#endif
+
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::CExposedDocFile\n"));
+}
+
+
+SCODE CExposedDocFile::InitMarshal(DWORD dwAsyncFlags,
+ IDocfileAsyncConnectionPoint *pdacp)
+{
+ return _cpoint.InitMarshal(this, dwAsyncFlags, pdacp);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::~CExposedDocFile, public
+//
+// Synopsis: Destructor
+//
+// History: 23-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+CExposedDocFile::~CExposedDocFile(void)
+{
+ BOOL fClose = FALSE;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::~CExposedDocFile\n"));
+ olAssert(_cReferences == 0);
+
+ //In order to call into the tree, we need to take the mutex.
+ //The mutex may get deleted in _ppc->Release(), so we can't
+ //release it here. The mutex actually gets released in
+ //CPerContext::Release() or in the CPerContext destructor.
+
+ //If _ppc is NULL, we're partially constructed and don't need to
+ //worry.
+ SCODE sc;
+
+#if WIN32 >= 300
+ if (_pIAC != NULL)
+ {
+ _pIAC->Release();
+ _pIAC = NULL;
+ }
+#endif
+
+#if !defined(MULTIHEAP)
+ // TakeSem and ReleaseSem are moved to the Release Method
+ // so that the deallocation for this object is protected
+ if (_ppc)
+ {
+ sc = TakeSem();
+ SetWriteAccess();
+ olAssert(SUCCEEDED(sc));
+ }
+#ifdef ASYNC
+ IDocfileAsyncConnectionPoint *pdacp = _cpoint.GetMarshalPoint();
+#endif
+#endif //MULTIHEAP
+
+ if (_pdf)
+ {
+ // If we're the last reference on a root object
+ // we close the context because all children will become
+ // reverted so it is no longer necessary
+ if (_pdf->GetRefCount() == 1 && _pdf->IsRoot())
+ fClose = TRUE;
+
+ _pdf->CPubDocFile::vRelease();
+ }
+ if (_pdfb)
+ _pdfb->CDFBasis::vRelease();
+#if !defined(MULTIHEAP)
+ if (_fOwnContext && _ppc)
+ {
+ if (fClose)
+ _ppc->Close();
+ _ppc->Release();
+ }
+ else if (_ppc)
+ {
+ ReleaseSem(sc);
+ }
+#ifdef ASYNC
+ //Mutex has been released, so we can release the connection point
+ // without fear of deadlock.
+ if (pdacp != NULL)
+ pdacp->Release();
+#endif
+#endif // MULTIHEAP
+
+
+ _sig = CEXPOSEDDOCFILE_SIGDEL;
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::~CExposedDocFile\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::Release, public
+//
+// Synopsis: Releases resources for a CExposedDocFile
+//
+// Returns: Appropriate status code
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP_(ULONG) CExposedDocFile::Release(void)
+{
+ LONG lRet;
+
+ olLog(("%p::In CExposedDocFile::Release()\n", this));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::Release()\n"));
+
+ if (FAILED(Validate()))
+ return 0;
+ olAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+ CPerContext *ppc = _ppc;
+ BOOL fOwnContext = _fOwnContext;
+ SCODE sc = S_OK;
+
+ if (_ppc)
+ {
+ sc = TakeSem();
+ SetWriteAccess();
+ olAssert(SUCCEEDED(sc));
+ }
+#ifdef ASYNC
+ IDocfileAsyncConnectionPoint *pdacp = _cpoint.GetMarshalPoint();
+#endif
+ BOOL fClose = (_pdf) && (_pdf->GetRefCount()==1) && _pdf->IsRoot();
+#endif //MULTIHEAP
+ delete this;
+#ifdef MULTIHEAP
+ if (fOwnContext && ppc)
+ {
+ BOOL fLastRef = ppc->LastRef();
+ if (fClose)
+ ppc->Close();
+ ppc->Release();
+ if (fLastRef)
+ g_smAllocator.Uninit();
+ }
+ else if (ppc)
+ {
+ if (SUCCEEDED(sc)) ppc->UntakeSem();
+ }
+#ifdef ASYNC
+ //Mutex has been released, so we can release the connection point
+ // without fear of deadlock.
+ if (pdacp != NULL)
+ pdacp->Release();
+#endif
+#endif
+ }
+ else if (lRet < 0)
+ lRet = 0;
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::Release()\n"));
+ olLog(("%p::Out CExposedDocFile::Release(). ret == %lu\n", this, lRet));
+ FreeLogFile();
+ return (ULONG)lRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CheckCopyTo, private
+//
+// Synopsis: Checks for CopyTo legality
+//
+// Returns: Appropriate status code
+//
+// History: 07-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CExposedDocFile::CheckCopyTo(void)
+{
+ return _pdfb->GetCopyBase() != NULL &&
+ _pdf->IsAtOrAbove(_pdfb->GetCopyBase()) ?
+ STG_E_ACCESSDENIED : S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::ConvertInternalStream, private
+//
+// Synopsis: Converts an internal stream to a storage
+//
+// Arguments: [pwcsName] - Name
+// [pdfExp] - Destination docfile
+//
+// Returns: Appropriate status code
+//
+// History: 23-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+static WCHAR const wcsIllegalName[] = {'\\', '\0'};
+
+SCODE CExposedDocFile::ConvertInternalStream(CExposedDocFile *pdfExp)
+{
+ CPubStream *pstFrom, *pstTo;
+ SCODE sc;
+ CDfName const dfnIllegal(wcsIllegalName);
+ CDfName const dfnContents(wcsContents);
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::ConvertInternalStream(%p)\n",
+ pdfExp));
+ olChk(_pdf->GetStream(&dfnIllegal, DF_READWRITE | DF_DENYALL, &pstFrom));
+ olChkTo(EH_pstFrom, pdfExp->GetPub()->CreateStream(&dfnContents,
+ DF_WRITE | DF_DENYALL,
+ &pstTo));
+ olChkTo(EH_pstTo, CopySStreamToSStream(pstFrom->GetSt(),
+ pstTo->GetSt()));
+ olChkTo(EH_pstTo, _pdf->DestroyEntry(&dfnIllegal, FALSE));
+ sc = S_OK;
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::ConvertInternalStream\n"));
+ // Fall through
+EH_pstTo:
+ pstTo->CPubStream::vRelease();
+EH_pstFrom:
+ pstFrom->CPubStream::vRelease();
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::CreateEntry, private
+//
+// Synopsis: Creates elements, used in CreateStream, CreateStorage.
+//
+// Arguments: [pdfn] - Name
+// [dwType] - Entry type
+// [grfMode] - Access mode
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 18-Dec-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+
+SCODE CExposedDocFile::CreateEntry(CDfName const *pdfn,
+ DWORD dwType,
+ DWORD grfMode,
+ void **ppv)
+{
+ SCODE sc;
+ SEntryBuffer eb;
+ BOOL fRenamed = FALSE;
+ CPubStream *pst;
+ CExposedStream *pstExp;
+ CPubDocFile *pdf;
+ CExposedDocFile *pdfExp;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::CreateEntry:%p("
+ "%p, %lX, %lX, %p)\n", this, pdfn, dwType, grfMode, ppv));
+ olChk(EnforceSingle(grfMode));
+
+ if (grfMode & STGM_NOSNAPSHOT)
+ {
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ }
+
+ // 3/11/93 - Demand scratch when opening/creating transacted
+ if ((grfMode & STGM_TRANSACTED) == STGM_TRANSACTED)
+ {
+ olChk(_ppc->GetDirty()->Init(NULL));
+ }
+
+ if (grfMode & (STGM_CREATE | STGM_CONVERT))
+ {
+ if (FAILED(sc = _pdf->IsEntry(pdfn, &eb)))
+ {
+ if (sc != STG_E_FILENOTFOUND)
+ olErr(EH_Err, sc);
+ }
+ else if (eb.dwType == dwType && (grfMode & STGM_CREATE))
+ olChk(_pdf->DestroyEntry(pdfn, FALSE));
+ else if (eb.dwType == STGTY_STREAM && (grfMode & STGM_CONVERT) &&
+ dwType == STGTY_STORAGE)
+ {
+ CDfName const dfnIllegal(wcsIllegalName);
+
+ olChk(_pdf->RenameEntry(pdfn, &dfnIllegal));
+ fRenamed = TRUE;
+ }
+ else
+ olErr(EH_Err, STG_E_FILEALREADYEXISTS);
+ }
+ if (REAL_STGTY(dwType) == STGTY_STREAM)
+ {
+ olChk(_pdf->CreateStream(pdfn, ModeToDFlags(grfMode), &pst));
+ olMemTo(EH_pst, pstExp = new (_pdfb->GetMalloc()) CExposedStream);
+ olChkTo(EH_pstExp, pstExp->Init(pst, BP_TO_P(CDFBasis *, _pdfb),
+ _ppc, TRUE, NULL));
+ _ppc->AddRef();
+#ifdef ASYNC
+ if (_cpoint.IsInitialized())
+ {
+ olChkTo(EH_connSt, pstExp->InitConnection(&_cpoint));
+ }
+#endif
+ *ppv = pstExp;
+ }
+ else
+ {
+ olAssert(REAL_STGTY(dwType) == STGTY_STORAGE);
+ olChk(_pdf->CreateDocFile(pdfn, ModeToDFlags(grfMode), &pdf));
+ olMemTo(EH_pdf, pdfExp = new (_pdfb->GetMalloc())
+ CExposedDocFile(pdf, BP_TO_P(CDFBasis *, _pdfb), _ppc, TRUE));
+ _ppc->AddRef();
+ if (_cpoint.IsInitialized())
+ {
+ olChkTo(EH_pdfExpInit, pdfExp->InitConnection(&_cpoint));
+ }
+
+ // If we've renamed the original stream for conversion, convert
+ if (fRenamed)
+ {
+ olChkTo(EH_pdfExpInit, ConvertInternalStream(pdfExp));
+ sc = STG_S_CONVERTED;
+ }
+
+ *ppv = pdfExp;
+ }
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::CreateEntry\n"));
+ return sc;
+
+ EH_connSt:
+ pstExp->Release();
+ goto EH_Del;
+
+ EH_pstExp:
+ delete pstExp;
+ EH_pst:
+ pst->CPubStream::vRelease();
+ goto EH_Del;
+
+ EH_pdfExpInit:
+ pdfExp->Release();
+ goto EH_Del;
+ EH_pdf:
+ pdf->CPubDocFile::vRelease();
+ // Fall through
+ EH_Del:
+ olVerSucc(_pdf->DestroyEntry(pdfn, TRUE));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::OpenEntry, private
+//
+// Synopsis: Opens elements, used in OpenStream, OpenStorage.
+//
+// Arguments: [pdfn] - Name
+// [dwType] - Entry type
+// [grfMode] - Access mode
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 18-Dec-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+
+SCODE CExposedDocFile::OpenEntry(CDfName const *pdfn,
+ DWORD dwType,
+ DWORD grfMode,
+ void **ppv)
+{
+ SCODE sc;
+ CPubDocFile *pdf;
+ CExposedDocFile *pdfExp;
+ CPubStream *pst;
+ CExposedStream *pstExp;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::OpenEntry:%p("
+ "%p, %lX, %lX, %p)\n", this, pdfn, dwType, grfMode, ppv));
+ olChk(EnforceSingle(grfMode));
+
+ // 3/11/93 - Demand scratch when opening/creating transacted
+ if ((grfMode & STGM_TRANSACTED) == STGM_TRANSACTED)
+ {
+ olChk(_ppc->GetDirty()->Init(NULL));
+ }
+
+ if (REAL_STGTY(dwType) == STGTY_STREAM)
+ {
+ olChk(_pdf->GetStream(pdfn, ModeToDFlags(grfMode), &pst));
+ olMemTo(EH_pst, pstExp = new (_pdfb->GetMalloc()) CExposedStream);
+ olChkTo(EH_pstExp, pstExp->Init(pst, BP_TO_P(CDFBasis *, _pdfb),
+ _ppc, TRUE, NULL));
+ _ppc->AddRef();
+ if (_cpoint.IsInitialized())
+ {
+ olChkTo(EH_connSt, pstExp->InitConnection(&_cpoint));
+ }
+
+ *ppv = pstExp;
+ }
+ else
+ {
+ olAssert(REAL_STGTY(dwType) == STGTY_STORAGE);
+ olChk(_pdf->GetDocFile(pdfn, ModeToDFlags(grfMode), &pdf));
+ olMemTo(EH_pdf, pdfExp = new (_pdfb->GetMalloc())
+ CExposedDocFile(pdf, BP_TO_P(CDFBasis *, _pdfb), _ppc, TRUE));
+ _ppc->AddRef();
+ if (_cpoint.IsInitialized())
+ {
+ olChkTo(EH_connDf, pdfExp->InitConnection(&_cpoint));
+ }
+
+ *ppv = pdfExp;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::OpenEntry\n"));
+ return S_OK;
+ EH_connSt:
+ pstExp->Release();
+ return sc;
+
+ EH_pstExp:
+ delete pstExp;
+ // Fall through to clean up CPubStream
+ EH_pst:
+ pst->CPubStream::vRelease();
+ return sc;
+
+EH_connDf:
+ pdfExp->Release();
+ return sc;
+
+ EH_pdf:
+ pdf->CPubDocFile::vRelease();
+ // Fall through
+ EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CreateStream, public
+//
+// Synopsis: Creates a stream
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [reserved1]
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+_OLESTDMETHODIMP CExposedDocFile::CreateStream(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ SafeCExposedStream pestm;
+ CDfName dfn;
+
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::CreateStream("
+ "%ws, %lX, %lu, %lu, %p)\n", pwcsName, grfMode, reserved1,
+ reserved2, ppstm));
+ olLog(("%p::In CExposedDocFile::CreateStream(%ws, %lX, %lu, %lu, %p)\n",
+ this, pwcsName, grfMode, reserved1, reserved2, ppstm));
+
+ olChk(ValidateOutPtrBuffer(ppstm));
+ *ppstm = NULL;
+ olChk(CheckName(pwcsName));
+ if (reserved1 != 0 || reserved2 != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(VerifyPerms(grfMode));
+ if (grfMode & (STGM_CONVERT | STGM_TRANSACTED | STGM_PRIORITY |
+ STGM_DELETEONRELEASE))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ olChk(Validate());
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ olChk(CheckCopyTo());
+ SafeWriteAccess();
+
+ dfn.Set(pwcsName);
+ sc = CreateEntry(&dfn, STGTY_STREAM, grfMode, (void **)&pestm);
+ END_PENDING_LOOP;
+
+ if (SUCCEEDED(sc))
+ TRANSFER_INTERFACE(pestm, IStream, ppstm);
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::CreateStream => %p\n",
+ *ppstm));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::CreateStream(). "
+ "*ppstm == %p, ret == %lx\n", this, *ppstm, sc));
+ return _OLERETURN(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::OpenStream, public
+//
+// Synopsis: Opens an existing stream
+//
+// Arguments: [pwcsName] - Name
+// [reserved1]
+// [grfMode] - Permissions
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+_OLESTDMETHODIMP CExposedDocFile::OpenStream(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ SafeCExposedStream pestm;
+ CDfName dfn;
+
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::OpenStream("
+ "%ws, %p, %lX, %lu, %p)\n", pwcsName, reserved1,
+ grfMode, reserved2, ppstm));
+ olLog(("%p::In CExposedDocFile::OpenStream(%ws, %lu %lX, %lu, %p)\n",
+ this, pwcsName, reserved1, grfMode, reserved2, ppstm));
+
+ olChk(ValidateOutPtrBuffer(ppstm));
+ *ppstm = NULL;
+ olChk(CheckName(pwcsName));
+ if (reserved1 != NULL || reserved2 != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(VerifyPerms(grfMode));
+ if (grfMode & (STGM_CREATE | STGM_CONVERT))
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ if (grfMode & (STGM_TRANSACTED | STGM_PRIORITY |
+ STGM_DELETEONRELEASE))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ olChk(Validate());
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeReadAccess();
+
+ dfn.Set(pwcsName);
+ sc = OpenEntry(&dfn, STGTY_STREAM, grfMode, (void **)&pestm);
+ END_PENDING_LOOP;
+
+ if (SUCCEEDED(sc))
+ TRANSFER_INTERFACE(pestm, IStream, ppstm);
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::OpenStream => %p\n",
+ *ppstm));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::OpenStream(). "
+ "*ppstm == %p, ret == %lx\n", this, *ppstm, sc));
+ return _OLERETURN(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CreateStorage, public
+//
+// Synopsis: Creates an embedded DocFile
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [reserved1]
+// [reserved2]
+// [ppstg] - New DocFile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+_OLESTDMETHODIMP CExposedDocFile::CreateStorage(
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ LPSTGSECURITY reserved2,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ SafeCExposedDocFile pedf;
+ CDfName dfn;
+
+ olLog(("%p::In CExposedDocFile::CreateStorage(%ws, %lX, %lu, %lu, %p)\n",
+ this, pwcsName, grfMode, reserved1, reserved2, ppstg));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::CreateStorage:%p("
+ "%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode,
+ reserved1, reserved2, ppstg));
+
+ olChk(ValidateOutPtrBuffer(ppstg));
+ *ppstg = NULL;
+ olChk(CheckName(pwcsName));
+ if (reserved1 != 0 || reserved2 != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(VerifyPerms(grfMode));
+ if (grfMode & (STGM_PRIORITY | STGM_DELETEONRELEASE))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ olChk(Validate());
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ olChk(CheckCopyTo());
+ SafeWriteAccess();
+
+ dfn.Set(pwcsName);
+ sc = CreateEntry(&dfn, STGTY_STORAGE, grfMode, (void **)&pedf);
+ END_PENDING_LOOP;
+
+ if (SUCCEEDED(sc))
+ TRANSFER_INTERFACE(pedf, IStorage, ppstg);
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::CreateStorage => %p\n",
+ *ppstg));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::CreateStorage(). "
+ "*ppstg == %p, ret == %lX\n", this, *ppstg, sc));
+ return _OLERETURN(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::OpenStorage, public
+//
+// Synopsis: Gets an existing embedded DocFile
+//
+// Arguments: [pwcsName] - Name
+// [pstgPriority] - Priority reopens
+// [grfMode] - Permissions
+// [snbExclude] - Priority reopens
+// [reserved]
+// [ppstg] - DocFile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+_OLESTDMETHODIMP CExposedDocFile::OpenStorage(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNBW snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ SafeCExposedDocFile pdfExp;
+ CDfName dfn;
+
+ olLog(("%p::In CExposedDocFile::OpenStorage(%ws, %p, %lX, %p, %lu, %p)\n",
+ this, pwcsName, pstgPriority, grfMode, snbExclude, reserved,
+ ppstg));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::OpenStorage:%p("
+ "%ws, %p, %lX, %p, %lu, %p)\n", this, pwcsName, pstgPriority,
+ grfMode, snbExclude, reserved, ppstg));
+
+ olChk(ValidateOutPtrBuffer(ppstg));
+ *ppstg = NULL;
+ olChk(CheckName(pwcsName));
+ if (reserved != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(VerifyPerms(grfMode));
+ if (grfMode & (STGM_CREATE | STGM_CONVERT))
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ if (pstgPriority != NULL ||
+ (grfMode & (STGM_PRIORITY | STGM_DELETEONRELEASE)))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ olChk(Validate());
+ if (snbExclude != NULL)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeReadAccess();
+
+ dfn.Set(pwcsName);
+ sc = OpenEntry(&dfn, STGTY_STORAGE, grfMode, (void **)&pdfExp);
+ END_PENDING_LOOP;
+
+ if (SUCCEEDED(sc))
+ {
+ TRANSFER_INTERFACE(pdfExp, IStorage, ppstg);
+ }
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::OpenStorage => %p\n",
+ *ppstg));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::OpenStorage(). "
+ "*ppstg == %p, ret == %lX\n", this, *ppstg, sc));
+ return _OLERETURN(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::MakeCopyFlags, public
+//
+// Synopsis: Translates IID array into bit fields
+//
+// Arguments: [ciidExclude] - Count of IIDs
+// [rgiidExclude] - IIDs not to copy
+//
+// Returns: Appropriate status code
+//
+// History: 23-Dec-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+
+DWORD CExposedDocFile::MakeCopyFlags(DWORD ciidExclude,
+ IID const *rgiidExclude)
+{
+ DWORD dwCopyFlags;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::MakeCopyFlags(%lu, %p)\n",
+ ciidExclude, rgiidExclude));
+ // Copy everything by default
+ dwCopyFlags = COPY_ALL;
+ for (; ciidExclude > 0; ciidExclude--, rgiidExclude++)
+ if (IsEqualIID(*rgiidExclude, IID_IStorage))
+ dwCopyFlags &= ~COPY_STORAGES;
+ else if (IsEqualIID(*rgiidExclude, IID_IStream))
+ dwCopyFlags &= ~COPY_STREAMS;
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::MakeCopyFlags\n"));
+ return dwCopyFlags;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CopyTo, public
+//
+// Synopsis: Makes a copy of a DocFile
+//
+// Arguments: [ciidExclude] - Length of rgiid array
+// [rgiidExclude] - Array of IIDs to exclude
+// [snbExclude] - Names to exclude
+// [pstgDest] - Parent of copy
+//
+// Returns: Appropriate status code
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+_OLESTDMETHODIMP CExposedDocFile::CopyTo(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNBW snbExclude,
+ IStorage *pstgDest)
+{
+ SCODE sc;
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ SAFE_SEM;
+ DWORD i;
+
+
+
+ olLog(("%p::In CExposedDocFile::CopyTo(%lu, %p, %p, %p)\n",
+ this, ciidExclude, rgiidExclude, snbExclude, pstgDest));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::CopyTo(%lu, %p, %p, %p)\n",
+ ciidExclude, rgiidExclude, snbExclude, pstgDest));
+
+ olChk(ValidateInterface(pstgDest, IID_IStorage));
+ if (rgiidExclude)
+ {
+ olAssert(sizeof(IID)*ciidExclude <= 0xffffUL);
+ olChk(ValidateBuffer(rgiidExclude,
+ (size_t)(sizeof(IID)*ciidExclude)));
+ for (i = 0; i<ciidExclude; i++)
+ olChk(ValidateIid(rgiidExclude[i]));
+ }
+ if (snbExclude)
+ olChk(ValidateSNB(snbExclude));
+ olChk(Validate());
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ olChk(_pdf->CheckReverted());
+
+ // BUGBUG - DeleteContents should really be a method on IStorage
+ // so that we can call pstgDest->DeleteContents() rather than
+ // having to give our own implementation.
+
+ olAssert(_pdfb->GetCopyBase() == NULL);
+ _pdfb->SetCopyBase(BP_TO_P(CPubDocFile *, _pdf));
+
+ // Flush all descendant property set buffers so that their
+ // underlying Streams (which are about to be copied) are
+ // up to date.
+
+ SetWriteAccess();
+ olChkTo(EH_Loop, _pdf->FlushBufferedData(0));
+ ClearWriteAccess();
+
+ // Perform the copy.
+
+ sc = CopyDocFileToIStorage(_pdf->GetDF(), pstgDest, snbExclude,
+ MakeCopyFlags(ciidExclude, rgiidExclude));
+EH_Loop:
+ _pdfb->SetCopyBase(NULL);
+ END_PENDING_LOOP;
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::CopyTo\n"));
+EH_Err:
+ _pdfb->SetCopyBase(NULL);
+ olLog(("%p::Out ExposedDocFile::CopyTo(). ret == %lX\n", this, sc));
+ return _OLERETURN(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::Commit, public
+//
+// Synopsis: Commits transacted changes
+//
+// Arguments: [dwFlags] - DFC_*
+//
+// Returns: Appropriate status code
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::Commit(DWORD dwFlags)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+
+ olLog(("%p::In CExposedDocFile::Commit(%lX)\n",this, dwFlags));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::Commit(%lX)\n", dwFlags));
+
+ olChk(VerifyCommitFlags(dwFlags));
+ olChk(Validate());
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeWriteAccess();
+
+ olChkTo(EH_Loop, _pdf->Commit(dwFlags));
+
+#if WIN32 >= 300
+ if (SUCCEEDED(sc) && _pIAC != NULL)
+ sc = _pIAC->CommitAccessRights(0);
+#endif
+
+EH_Loop:
+ END_PENDING_LOOP;
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::Commit\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::Commit(). ret == %lx\n",this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::Revert, public
+//
+// Synopsis: Reverts transacted changes
+//
+// Returns: Appropriate status code
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::Revert(void)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+
+ olLog(("%p::In CExposedDocFile::Revert()\n", this));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::Revert\n"));
+
+ olChk(Validate());
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeWriteAccess();
+
+ olChkTo(EH_Loop, _pdf->Revert());
+
+#if WIN32 >= 300
+ if (SUCCEEDED(sc) && _pIAC != NULL)
+ sc = _pIAC->RevertAccessRights();
+#endif
+EH_Loop:
+ END_PENDING_LOOP;
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::Revert\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::Revert(). ret == %lx\n", this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::EnumElements, public
+//
+// Synopsis: Starts an iterator
+//
+// Arguments: [reserved1]
+// [reserved2]
+// [reserved3]
+// [ppenm] - Enumerator return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::EnumElements(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ SafeCExposedIterator pdiExp;
+ CDfName dfnTmp;
+
+ olLog(("%p::In CExposedDocFile::EnumElements(%lu, %p, %lu, %p)\n",
+ this, reserved1, reserved2, reserved3, ppenm));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::EnumElements(%p)\n",
+ ppenm));
+
+ olChk(ValidateOutPtrBuffer(ppenm));
+ *ppenm = NULL;
+
+ if (
+ reserved1 != 0 ||
+ reserved2 != NULL || reserved3 != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(Validate());
+
+ //ASYNC Note: It doesn't appear that there's any way that this
+ // function can fail with STG_E_PENDING, so we don't need a pending
+ // loop here.
+ olChk(TakeSafeSem());
+ if (!P_READ(_pdf->GetDFlags()))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+ olChk(_pdf->CheckReverted());
+ SafeReadAccess();
+
+ pdiExp.Attach(new CExposedIterator(BP_TO_P(CPubDocFile *, _pdf),
+ &dfnTmp,
+ BP_TO_P(CDFBasis *, _pdfb),
+ _ppc, TRUE));
+ olMem((CExposedIterator *)pdiExp);
+ _ppc->AddRef();
+#ifdef ASYNC
+ if (_cpoint.IsInitialized())
+ {
+ olChkTo(EH_Exp, pdiExp->InitConnection(&_cpoint));
+ }
+#endif
+ TRANSFER_INTERFACE(pdiExp, IEnumSTATSTG, ppenm);
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::EnumElements => %p\n",
+ *ppenm));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::EnumElements(). ret == %lx\n",this, sc));
+ return ResultFromScode(sc);
+EH_Exp:
+ pdiExp->Release();
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::DestroyElement, public
+//
+// Synopsis: Permanently deletes an element of a DocFile
+//
+// Arguments: [pwcsName] - Name of element
+//
+// Returns: Appropriate status code
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+_OLESTDMETHODIMP CExposedDocFile::DestroyElement(WCHAR const *pwcsName)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ CDfName dfn;
+
+ olLog(("%p::In CExposedDocFile::DestroyElement(%ws)\n", this, pwcsName));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::DestroyElement(%ws)\n",
+ pwcsName));
+
+ olChk(Validate());
+ olChk(CheckName(pwcsName));
+ dfn.Set(pwcsName);
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeWriteAccess();
+
+ sc = _pdf->DestroyEntry(&dfn, FALSE);
+ END_PENDING_LOOP;
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::DestroyElement\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::DestroyElement(). ret == %lx\n",
+ this, sc));
+ return _OLERETURN(sc);
+}
+
+_OLESTDMETHODIMP CExposedDocFile::MoveElementTo(WCHAR const *pwcsName,
+ IStorage *pstgParent,
+ OLECHAR const *ptcsNewName,
+ DWORD grfFlags)
+{
+ SCODE sc;
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ olLog(("%p::In CExposedDocFile::MoveElementTo("
+ "%ws, %p, " OLEFMT ", %lu)\n",
+ this, pwcsName, pstgParent, ptcsNewName, grfFlags));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::MoveElementTo("
+ "%ws, %p, " OLEFMT ", %lu)\n",
+ pwcsName, pstgParent, ptcsNewName, grfFlags));
+
+ olChk(Validate());
+ olChk(CheckName(pwcsName));
+ olChk(VerifyMoveFlags(grfFlags));
+
+#ifdef ASYNC
+ //ASYNC Note: We don't use the normal pending loop macros here because
+ // we have no safe sem and need to pass a NULL.
+ do
+ {
+#endif
+ sc = MoveElementWorker(pwcsName,
+ pstgParent,
+ ptcsNewName,
+ grfFlags);
+#ifdef ASYNC
+ if (!ISPENDINGERROR(sc))
+ {
+ break;
+ }
+ else
+ {
+ SCODE sc2;
+ sc2 = _cpoint.Notify(sc,
+ _ppc->GetBase(),
+ _ppc,
+ NULL);
+ if (sc2 != S_OK)
+ {
+ return ResultFromScode(sc2);
+ }
+ }
+ } while (TRUE);
+#endif
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::MoveElementTo(). ret == %lx\n",
+ this, sc));
+ return _OLERETURN(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::MoveElementTo, public
+//
+// Synopsis: Move an element of a DocFile to an IStorage
+//
+// Arguments: [pwcsName] - Current name
+// [ptcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// Algorithm: Open source as storage or stream (whatever works)
+// Create appropriate destination
+// Copy source to destination
+// Set create time of destination equal to create time of source
+// If appropriate, delete source
+//
+// History: 10-Nov-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+
+SCODE CExposedDocFile::MoveElementWorker(WCHAR const *pwcsName,
+ IStorage *pstgParent,
+ OLECHAR const *ptcsNewName,
+ DWORD grfFlags)
+{
+ IUnknown *punksrc = NULL;
+ SCODE sc;
+ IUnknown *punkdst;
+ IStorage *pstgsrc;
+ STATSTG statstg;
+
+ // Determine source type
+ sc = GetScode(OpenStorage(pwcsName, NULL,
+ STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
+ NULL, NULL, &pstgsrc));
+ if (SUCCEEDED(sc))
+ {
+ HRESULT hr;
+
+ // It's a storage
+ punksrc = pstgsrc;
+
+ IStorage *pstgdst;
+ olHChkTo(EH_UnkSrc, pstgsrc->Stat(&statstg, STATFLAG_NONAME));
+
+ hr = pstgParent->CreateStorage(ptcsNewName,
+ STGM_DIRECT | STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE | STGM_FAILIFTHERE,
+ 0, 0, &pstgdst);
+ if (DfGetScode(hr) == STG_E_FILEALREADYEXISTS &&
+ grfFlags == STGMOVE_COPY)
+ {
+ //If we're opening an existing thing for merging, we need
+ // read and write permissions so we can traverse the tree.
+ hr = pstgParent->OpenStorage(ptcsNewName, NULL,
+ STGM_DIRECT | STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE, NULL,
+ 0, &pstgdst);
+ }
+ olHChkTo(EH_UnkSrc, hr);
+
+ punkdst = pstgdst;
+
+ sc = DfGetScode(pstgsrc->CopyTo(0, NULL, NULL, pstgdst));
+ }
+ else if (sc == STG_E_FILENOTFOUND)
+ {
+ // Try opening it as a stream
+
+ IStream *pstmsrc, *pstmdst;
+ olHChk(OpenStream(pwcsName, NULL,
+ STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
+ NULL, &pstmsrc));
+
+ // It's a stream
+ punksrc = pstmsrc;
+
+ olHChkTo(EH_UnkSrc, pstmsrc->Stat(&statstg, STATFLAG_NONAME));
+
+ olHChkTo(EH_UnkSrc,
+ pstgParent->CreateStream(ptcsNewName,
+ STGM_DIRECT | STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE |
+ (grfFlags == STGMOVE_MOVE ?
+ STGM_FAILIFTHERE :
+ STGM_CREATE),
+ 0, 0, &pstmdst));
+
+ punkdst = pstmdst;
+
+ ULARGE_INTEGER cb;
+ ULISetLow (cb, 0xffffffff);
+ ULISetHigh(cb, 0xffffffff);
+ sc = DfGetScode(pstmsrc->CopyTo(pstmdst, cb, NULL, NULL));
+ }
+ else
+ olChk(sc);
+
+ punkdst->Release();
+
+ if (SUCCEEDED(sc))
+ {
+ // Make destination create time match source create time
+ // Note that we don't really care if this call succeeded.
+
+ pstgParent->SetElementTimes(ptcsNewName, &statstg.ctime,
+ NULL, NULL);
+
+ if ((grfFlags & STGMOVE_COPY) == STGMOVE_MOVE)
+ olVerify(SUCCEEDED(DestroyElement(pwcsName)));
+ }
+ else
+ {
+ // The copy/move failed, so get rid of the partial result.
+ pstgParent->DestroyElement(ptcsNewName);
+ }
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::MoveElementTo\n"));
+ // Fall through
+EH_UnkSrc:
+ if (punksrc)
+ punksrc->Release();
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::RenameElement, public
+//
+// Synopsis: Renames an element of a DocFile
+//
+// Arguments: [pwcsName] - Current name
+// [pwcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+_OLESTDMETHODIMP CExposedDocFile::RenameElement(WCHAR const *pwcsName,
+ WCHAR const *pwcsNewName)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ CDfName dfnOld, dfnNew;
+
+ olLog(("%p::In CExposedDocFile::RenameElement(%ws, %ws)\n",
+ this, pwcsName, pwcsNewName));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::RenameElement(%ws, %ws)\n",
+ pwcsName, pwcsNewName));
+
+ olChk(Validate());
+ olChk(CheckName(pwcsName));
+ olChk(CheckName(pwcsNewName));
+ dfnOld.Set(pwcsName);
+ dfnNew.Set(pwcsNewName);
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeWriteAccess();
+
+ sc = _pdf->RenameEntry(&dfnOld, &dfnNew);
+ END_PENDING_LOOP;
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::RenameElement\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::RenameElement(). ret == %lx\n",
+ this, sc));
+ return _OLERETURN(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::SetElementTimes, public
+//
+// Synopsis: Sets element time stamps
+//
+// Arguments: [pwcsName] - Name
+// [pctime] - create time
+// [patime] - access time
+// [pmtime] - modify time
+//
+// Returns: Appropriate status code
+//
+// History: 05-Oct-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+
+_OLESTDMETHODIMP CExposedDocFile::SetElementTimes(WCHAR const *pwcsName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ CDfName dfn;
+ CDfName *pdfn = NULL;
+ FILETIME ctime, atime, mtime;
+
+ olLog(("%p::In CExposedDocFile::SetElementTimes(%ws, %p, %p, %p)\n",
+ this, pwcsName, pctime, patime, pmtime));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::SetElementTimes:%p("
+ "%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime));
+
+ olChk(Validate());
+ if (pwcsName != NULL)
+ {
+ olChk(CheckName(pwcsName));
+ }
+ // Probe arguments and make local copies if necessary
+ if (pctime)
+ {
+ ValidateBuffer(pctime, sizeof(FILETIME));
+ ctime = *pctime;
+ pctime = &ctime;
+ }
+ if (patime)
+ {
+ ValidateBuffer(patime, sizeof(FILETIME));
+ atime = *patime;
+ patime = &atime;
+ }
+ if (pmtime)
+ {
+ ValidateBuffer(pmtime, sizeof(FILETIME));
+ mtime = *pmtime;
+ pmtime = &mtime;
+ }
+
+ if (pwcsName != NULL)
+ {
+ dfn.Set(pwcsName);
+ pdfn = &dfn;
+ }
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeWriteAccess();
+
+ sc = _pdf->SetElementTimes(pdfn, pctime, patime, pmtime);
+ END_PENDING_LOOP;
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::SetElementTimes\n"));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::SetElementTimes(). ret == %lx\n",
+ this, sc));
+ return _OLERETURN(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::SetClass, public
+//
+// Synopsis: Sets storage class
+//
+// Arguments: [clsid] - class id
+//
+// Returns: Appropriate status code
+//
+// History: 05-Oct-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::SetClass(REFCLSID rclsid)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ CLSID clsid;
+
+ olLog(("%p::In CExposedDocFile::SetClass(?)\n", this));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::SetClass:%p(?)\n", this));
+
+ olChk(Validate());
+ olChk(ValidateBuffer(&rclsid, sizeof(CLSID)));
+ clsid = rclsid;
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeWriteAccess();
+
+ sc = _pdf->SetClass(clsid);
+ END_PENDING_LOOP;
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::SetClass\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::SetClass(). ret == %lx\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::SetStateBits, public
+//
+// Synopsis: Sets state bits
+//
+// Arguments: [grfStateBits] - state bits
+// [grfMask] - state bits mask
+//
+// Returns: Appropriate status code
+//
+// History: 05-Oct-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+
+ olLog(("%p::In CExposedDocFile::SetStateBits(%lu, %lu)\n", this,
+ grfStateBits, grfMask));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::SetStateBits:%p("
+ "%lu, %lu)\n", this, grfStateBits, grfMask));
+
+ olChk(Validate());
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeWriteAccess();
+
+ sc = _pdf->SetStateBits(grfStateBits, grfMask);
+ END_PENDING_LOOP;
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::SetStateBits\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::SetStateBits(). ret == %lx\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::Stat, public
+//
+// Synopsis: Fills in a buffer of information about this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 24-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+_OLESTDMETHODIMP CExposedDocFile::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ SAFE_SEM;
+ SAFE_ACCESS;
+ SCODE sc;
+ STATSTGW stat;
+
+ olLog(("%p::In CExposedDocFile::Stat(%p)\n", this, pstatstg));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::Stat(%p)\n", pstatstg));
+
+ olChkTo(EH_RetSc, ValidateOutBuffer(pstatstg, sizeof(STATSTGW)));
+ olChk(VerifyStatFlag(grfStatFlag));
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeReadAccess();
+
+ sc = _pdf->Stat(&stat, grfStatFlag);
+ END_PENDING_LOOP;
+
+ if (SUCCEEDED(sc))
+ {
+ TRY
+ {
+ *pstatstg = stat;
+ pstatstg->type = STGTY_STORAGE;
+ ULISet32(pstatstg->cbSize, 0);
+ pstatstg->grfLocksSupported = 0;
+ pstatstg->STATSTG_dwStgFmt = 0;
+ }
+ CATCH(CException, e)
+ {
+ UNREFERENCED_PARM(e);
+ if (stat.pwcsName)
+ TaskMemFree(stat.pwcsName);
+ }
+ END_CATCH
+ }
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::Stat\n"));
+EH_Err:
+EH_RetSc:
+ olLog(("%p::Out CExposedDocFile::Stat(). *pstatstg == %p ret == %lx\n",
+ this, *pstatstg, sc));
+ return _OLERETURN(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+// History: 16-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP_(ULONG) CExposedDocFile::AddRef(void)
+{
+ ULONG ulRet;
+
+ olLog(("%p::In CExposedDocFile::AddRef()\n", this));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::AddRef()\n"));
+
+ if (FAILED(Validate()))
+ return 0;
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::AddRef\n"));
+ olLog(("%p::Out CExposedDocFile::AddRef(). ret == %lu\n", this, ulRet));
+ return ulRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 26-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ olLog(("%p::In CExposedDocFile::QueryInterface(?, %p)\n",
+ this, ppvObj));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::QueryInterface(?, %p)\n",
+ ppvObj));
+
+ olChk(ValidateOutPtrBuffer(ppvObj));
+ *ppvObj = NULL;
+ olChk(ValidateIid(iid));
+ olChk(Validate());
+ olChk(_pdf->CheckReverted());
+
+ sc = S_OK;
+ if (IsEqualIID(iid, IID_IStorage) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IStorage *)this;
+ CExposedDocFile::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IMarshal))
+ {
+ if (P_PRIORITY(_pdf->GetDFlags()) && _pdf->IsRoot())
+ olErr(EH_Err, E_NOINTERFACE);
+
+ //If the ILockBytes we'd need to marshal doesn't support IMarshal
+ // then we want to do standard marshalling on the storage, mostly
+ // to prevent deadlock problems but also because you'll get better
+ // performance. So check, then do the right thing.
+
+ IMarshal *pim;
+ ILockBytes *plkb;
+ plkb = _ppc->GetOriginal();
+ if (plkb == NULL)
+ {
+ plkb = _ppc->GetBase();
+ }
+
+ sc = plkb->QueryInterface(IID_IMarshal, (void **)&pim);
+ if (FAILED(sc))
+ {
+ olErr(EH_Err, E_NOINTERFACE);
+ }
+ pim->Release();
+
+ *ppvObj = (IMarshal *)this;
+ CExposedDocFile::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IRootStorage))
+ {
+#ifdef COORD
+ if ((!_pdf->IsRoot()) && (!_pdf->IsCoord()))
+#else
+ if (!_pdf->IsRoot())
+#endif
+ olErr(EH_Err, E_NOINTERFACE);
+ *ppvObj = (IRootStorage *)this;
+ CExposedDocFile::AddRef();
+ }
+#ifdef NEWPROPS
+ else if (IsEqualIID(iid, IID_IPropertySetStorage))
+ {
+ *ppvObj = (IPropertySetStorage *)this;
+ CExposedDocFile::AddRef();
+ }
+#endif
+#ifdef ASYNC
+ else if (IsEqualIID(iid, IID_IConnectionPointContainer) &&
+ _cpoint.IsInitialized())
+ {
+ *ppvObj = (IConnectionPointContainer *)this;
+ CExposedDocFile::AddRef();
+ }
+#endif
+#if WIN32 >= 300
+ else if (_pdf->IsRoot() && IsEqualIID(iid, IID_IAccessControl))
+ {
+ ILockBytes *piLB = _pdf->GetBaseMS()->GetILB();
+ olAssert((piLB != NULL));
+ SCODE scode = S_OK;
+ if (_pIAC == NULL) // use existing _pIAC if available
+ scode = piLB->QueryInterface(IID_IAccessControl,(void **)&_pIAC);
+ if (SUCCEEDED(scode))
+ {
+ *ppvObj = (IAccessControl *)this;
+ CExposedDocFile::AddRef();
+ }
+ else sc = E_NOINTERFACE;
+ }
+#endif
+ else
+ sc = E_NOINTERFACE;
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::QueryInterface => %p\n",
+ ppvObj));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::QueryInterface(). "
+ "*ppvObj == %p ret == %lx\n", this, *ppvObj, sc));
+ return ResultFromScode(sc);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Method: CExposedDocFile::CopySStreamToIStream, private
+//
+// Synopsis: Copies a PSStream to an IStream
+//
+// Arguments: [psstFrom] - SStream
+// [pstTo] - IStream
+//
+// Returns: Appropriate status code
+//
+// History: 07-May-92 DrewB Created
+// 26-Jun-92 AlexT Moved to CExposedDocFile
+// so we can call SetReadAccess
+//
+//---------------------------------------------------------------
+
+
+SCODE CExposedDocFile::CopySStreamToIStream(PSStream *psstFrom,
+ IStream *pstTo)
+{
+ BYTE *pbBuffer;
+ SCODE sc;
+ ULONG cbRead, cbWritten, cbPos, cbSizeLow;
+ ULARGE_INTEGER cbSize;
+
+ // This is part of CopyTo and therefore we are allowed to
+ // fail with out-of-memory
+ olMem(pbBuffer = (BYTE *) DfMemAlloc(STREAMBUFFERSIZE));
+
+ // Set destination size for contiguity
+ SetReadAccess();
+ psstFrom->GetSize(&cbSizeLow);
+ ClearReadAccess();
+
+ ULISet32(cbSize, cbSizeLow);
+ // Don't need to SetReadAccess here because pstTo is an IStream
+ olHChk(pstTo->SetSize(cbSize));
+ // Copy between streams
+ cbPos = 0;
+ for (;;)
+ {
+ SetReadAccess();
+ olChk(psstFrom->ReadAt(cbPos, pbBuffer, STREAMBUFFERSIZE,
+ (ULONG STACKBASED *)&cbRead));
+ ClearReadAccess();
+ if (cbRead == 0) // EOF
+ break;
+
+ // Don't need to SetReadAccess here because pstTo is an IStream
+ olHChk(pstTo->Write(pbBuffer, cbRead, &cbWritten));
+ if (cbRead != cbWritten)
+ olErr(EH_Err, STG_E_WRITEFAULT);
+ cbPos += cbWritten;
+ }
+ sc = S_OK;
+
+EH_Err:
+ DfMemFree(pbBuffer);
+ return sc;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Method: CExposedDocFile::CopyDocFileToIStorage, private
+//
+// Synopsis: Copies a docfile's contents to an IStorage
+//
+// Arguments: [pdfFrom] - From
+// [pstgTo] - To
+// [snbExclude] - Names to not copy
+// [dwCopyFlags] - Bitwise flags for types of objects to copy
+//
+// Returns: Appropriate status code
+//
+// History: 07-May-92 DrewB Created
+// 26-Jun-92 AlexT Moved to CExposedDocFile
+// so we can call SetReadAccess
+//
+//---------------------------------------------------------------
+
+
+// Variables used by CopyDocFileToIStorage that we
+// want to allocate dynamically rather than eating stack space
+struct SCopyVars : public CLocalAlloc
+{
+ PSStream *psstFrom;
+ IStream *pstTo;
+ PDocFile *pdfFromChild;
+ IStorage *pstgToChild;
+ DWORD grfStateBits;
+ CLSID clsid;
+ CDfName dfnKey;
+ SIterBuffer ib;
+ OLECHAR atcName[CWCSTORAGENAME];
+};
+
+SCODE CExposedDocFile::CopyDocFileToIStorage(PDocFile *pdfFrom,
+ IStorage *pstgTo,
+ SNBW snbExclude,
+ DWORD dwCopyFlags)
+{
+ SCODE sc;
+ SCopyVars *pcv = NULL;
+
+ olDebugOut((DEB_ITRACE, "In CopyDocFileToIStorage:%p(%p, %p, %p, %lX)\n",
+ this, pdfFrom, pstgTo, snbExclude, dwCopyFlags));
+
+ // Allocate variables dynamically to conserve stack space since
+ // this is a recursive call
+ olMem(pcv = new SCopyVars);
+
+#ifndef REF
+ SetReadAccess();
+#endif //!REF
+ sc = pdfFrom->GetClass(&pcv->clsid);
+#ifndef REF
+ ClearReadAccess();
+#endif //!REF
+ olChk(sc);
+
+ // Assume STG_E_INVALIDFUNCTION means that the destination storage
+ // doesn't support class IDs
+ sc = GetScode(pstgTo->SetClass(pcv->clsid));
+ if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
+ olErr(EH_Err, sc);
+
+#ifndef REF
+ SetReadAccess();
+#endif //!REF
+ sc = pdfFrom->GetStateBits(&pcv->grfStateBits);
+#ifndef REF
+ ClearReadAccess();
+#endif //!REF
+ olChk(sc);
+
+ sc = GetScode(pstgTo->SetStateBits(pcv->grfStateBits, 0xffffffff));
+ if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
+ olErr(EH_Err, sc);
+
+ for (;;)
+ {
+#ifndef REF
+ SetReadAccess();
+#endif //!REF
+ sc = pdfFrom->FindGreaterEntry(&pcv->dfnKey, &pcv->ib, NULL);
+#ifndef REF
+ ClearReadAccess();
+#endif //!REF
+
+ if (sc == STG_E_NOMOREFILES)
+ break;
+ else if (FAILED(sc))
+ olErr(EH_pdfi, sc);
+ pcv->dfnKey.Set(&pcv->ib.dfnName);
+
+ if (snbExclude && NameInSNB(&pcv->ib.dfnName, snbExclude) == S_OK)
+ continue;
+
+ if ((pcv->ib.type == STGTY_STORAGE &&
+ (dwCopyFlags & COPY_STORAGES) == 0) ||
+ (pcv->ib.type == STGTY_STREAM &&
+ (dwCopyFlags & COPY_STREAMS) == 0))
+ continue;
+
+ switch(pcv->ib.type)
+ {
+ case STGTY_STORAGE:
+ // Embedded DocFile, create destination and recurse
+
+#ifndef REF
+ SetReadAccess();
+#endif //!REF
+ sc = pdfFrom->GetDocFile(&pcv->ib.dfnName, DF_READ,
+ pcv->ib.type, &pcv->pdfFromChild);
+#ifndef REF
+ ClearReadAccess();
+#endif //!REF
+ olChkTo(EH_pdfi, sc);
+ // Not optimally efficient, but reduces #ifdef's
+ lstrcpyW(pcv->atcName, (WCHAR *)pcv->ib.dfnName.GetBuffer());
+
+ // Don't need to SetReadAccess here because pstgTo is an IStorage.
+
+#ifdef MULTIHEAP
+ {
+ CSafeMultiHeap smh(_ppc);
+ // if pstgTo is an IStorage proxy, then returned IStorage
+ // can be custom marshaled and allocator state is lost
+#endif
+ sc = DfGetScode(pstgTo->CreateStorage(pcv->atcName, STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_FAILIFTHERE,
+ 0, 0, &pcv->pstgToChild));
+
+ if (sc == STG_E_FILEALREADYEXISTS)
+ //We need read and write permissions so we can traverse
+ // the destination IStorage
+ olHChkTo(EH_Get, pstgTo->OpenStorage(pcv->atcName, NULL,
+ STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE,
+ NULL, 0,
+ &pcv->pstgToChild));
+ else if (FAILED(sc))
+ olErr(EH_Get, sc);
+#ifdef MULTIHEAP
+ }
+#endif
+ olChkTo(EH_Create,
+ CopyDocFileToIStorage(pcv->pdfFromChild, pcv->pstgToChild,
+ NULL, dwCopyFlags));
+ pcv->pdfFromChild->Release();
+ pcv->pstgToChild->Release();
+ break;
+
+ case STGTY_STREAM:
+#ifndef REF
+ SetReadAccess();
+#endif //!REF
+ sc = pdfFrom->GetStream(&pcv->ib.dfnName, DF_READ,
+ pcv->ib.type, &pcv->psstFrom);
+#ifndef REF
+ ClearReadAccess();
+#endif //!REF
+ olChkTo(EH_pdfi, sc);
+ // Not optimally efficient, but reduces #ifdef's
+ lstrcpyW(pcv->atcName, (WCHAR *)pcv->ib.dfnName.GetBuffer());
+
+ // Don't need to SetReadAccess here because pstgTo is an IStorage.
+
+#ifdef MULTIHEAP
+ {
+ CSafeMultiHeap smh(_ppc);
+ // if pstgTo is an IStorage proxy, then returned IStream
+ // can be custom marshaled and allocator state is lost
+#endif
+ olHChkTo(EH_Get,
+ pstgTo->CreateStream(pcv->atcName, STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_CREATE,
+ 0, 0, &pcv->pstTo));
+#ifdef MULTIHEAP
+ }
+#endif
+ olChkTo(EH_Create,
+ CopySStreamToIStream(pcv->psstFrom, pcv->pstTo));
+ pcv->psstFrom->Release();
+ pcv->pstTo->Release();
+ break;
+
+ default:
+ olAssert(!aMsg("Unknown type in CopyDocFileToIStorage"));
+ break;
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out CopyDocFileToIStorage\n"));
+ sc = S_OK;
+
+ EH_pdfi:
+ EH_Err:
+ delete pcv;
+ return sc;
+
+ EH_Create:
+ if (pcv->ib.type == STGTY_STORAGE)
+ pcv->pstgToChild->Release();
+ else
+ pcv->pstTo->Release();
+ olVerSucc(pstgTo->DestroyElement(pcv->atcName));
+ EH_Get:
+ if (pcv->ib.type == STGTY_STORAGE)
+ pcv->pdfFromChild->Release();
+ else
+ pcv->psstFrom->Release();
+ goto EH_Err;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::Unmarshal, public
+//
+// Synopsis: Creates a duplicate DocFile from parts
+//
+// Arguments: [pstm] - Marshal stream
+// [ppv] - Object return
+// [mshlflags] - Marshal flags
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 26-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+SCODE CExposedDocFile::Unmarshal(IStream *pstm,
+ void **ppv,
+ DWORD mshlflags)
+{
+ SCODE sc;
+ CDfMutex mtx;
+ CPerContext *ppc;
+ CPubDocFile *pdf;
+ CGlobalContext *pgc;
+ CDFBasis *pdfb;
+ CExposedDocFile *pedf;
+#ifdef ASYNC
+ DWORD dwAsyncFlags;
+ IDocfileAsyncConnectionPoint *pdacp;
+#endif
+#ifdef POINTER_IDENTITY
+ CMarshalList *pml;
+#endif
+ BOOL fRoot;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::Unmarshal(%p, %p)\n",
+ pstm, ppv));
+
+#ifdef MULTIHEAP
+ void *pvBaseOld;
+ void *pvBaseNew;
+ ContextId cntxid;
+ CPerContext pcSharedMemory (NULL); // bootstrap object
+#endif
+
+#if WIN32 == 100
+ olChk(DfCheckBaseAddress());
+#endif
+
+#ifdef MULTIHEAP
+ olChk(UnmarshalSharedMemory(pstm, mshlflags, &pcSharedMemory, &cntxid));
+ pvBaseOld = DFBASEPTR;
+#endif
+#ifdef POINTER_IDENTITY
+ olChkTo(EH_mem, UnmarshalPointer(pstm, (void **) &pedf));
+#endif
+ olChkTo(EH_mem, UnmarshalPointer(pstm, (void **)&pdf));
+ olChkTo(EH_mem, CPubDocFile::Validate(pdf));
+ olChkTo(EH_pdf, UnmarshalPointer(pstm, (void **)&pdfb));
+ olChkTo(EH_pdfb, UnmarshalPointer(pstm, (void **)&pgc));
+
+ //So far, nothing has called into the tree so we don't really need
+ // to be holding the tree mutex. The UnmarshalContext call does
+ // call into the tree, though, so we need to make sure this is
+ // threadsafe. We'll do this my getting the mutex name from the
+ // CGlobalContext, then creating a new CDfMutex object. While
+ // this is obviously not optimal, since it's possible we could
+ // reuse an existing CDfMutex, the reuse strategy isn't threadsafe
+ // since we can't do a lookup without the possibility of the thing
+ // we're looking for being released by another thread.
+ TCHAR atcMutexName[CONTEXT_MUTEX_NAME_LENGTH];
+ pgc->GetMutexName(atcMutexName);
+ olChkTo(EH_pgc, mtx.Init(atcMutexName));
+ olChkTo(EH_pgc, mtx.Take(INFINITE));
+
+ //At this point we're holding the mutex.
+
+#ifdef MULTIHEAP
+#ifdef ASYNC
+ olChkTo(EH_mtx, UnmarshalContext(pstm,
+ pgc,
+ &ppc,
+ mshlflags,
+ TRUE,
+ P_INDEPENDENT(pdf->GetDFlags()),
+ cntxid,
+ pdf->IsRoot()));
+#else
+ olChkTo(EH_mtx, UnmarshalContext(pstm,
+ pgc,
+ &ppc,
+ mshlflags,
+ P_INDEPENDENT(pdf->GetDFlags()),
+ cntxid,
+ pdf->IsRoot()));
+#endif
+ if ((pvBaseNew = DFBASEPTR) != pvBaseOld)
+ {
+ pdf = (CPubDocFile*) ((UINT)pdf - (UINT)pvBaseOld + (UINT)pvBaseNew);
+ pedf = (CExposedDocFile*) ((UINT)pedf-(UINT)pvBaseOld+(UINT)pvBaseNew);
+ pdfb = (CDFBasis*) ((UINT)pdfb - (UINT)pvBaseOld + (UINT)pvBaseNew);
+ }
+#else
+#ifdef ASYNC
+ olChkTo(EH_mtx, UnmarshalContext(pstm,
+ pgc,
+ &ppc,
+ mshlflags,
+ TRUE,
+ P_INDEPENDENT(pdf->GetDFlags()),
+ pdf->IsRoot()));
+#else
+ olChkTo(EH_mtx, UnmarshalContext(pstm,
+ pgc,
+ &ppc,
+ mshlflags,
+ P_INDEPENDENT(pdf->GetDFlags()),
+ pdf->IsRoot()));
+#endif //ASYNC
+#endif
+
+#ifdef ASYNC
+ olChkTo(EH_mtx, UnmarshalConnection(pstm,
+ &dwAsyncFlags,
+ &pdacp,
+ mshlflags));
+#endif
+#ifdef POINTER_IDENTITY
+ olAssert (pedf != NULL);
+ pml = (CMarshalList *) pedf;
+
+ // Warning: these checks must remain valid across processes
+ if (SUCCEEDED(pedf->Validate()) && pedf->GetPub() == pdf)
+ {
+ pedf = (CExposedDocFile *) pml->FindMarshal(GetCurrentContextId());
+ }
+ else
+ {
+ pml = NULL;
+ pedf = NULL;
+ }
+
+ // exposed object is not found or has been deleted
+ if (pedf == NULL)
+ {
+#endif
+ olMemTo(EH_ppc, pedf = new (pdfb->GetMalloc())
+ CExposedDocFile(pdf, pdfb, ppc, TRUE));
+ olChkTo(EH_exp, pedf->InitMarshal(dwAsyncFlags, pdacp));
+ //InitMarshal adds a reference.
+ if (pdacp)
+ pdacp->Release();
+#ifdef POINTER_IDENTITY
+ if (pml) pml->AddMarshal(pedf);
+ }
+ else
+ {
+ pdfb->SetAccess(ppc);
+ pedf->AddRef(); // reuse this object
+ pdf->vRelease(); // reuse public layer object
+ ppc->Release(); // reuse percontext
+ }
+#endif
+
+#ifdef DCOM
+ if (mshlflags == MSHLFLAGS_NORMAL)
+ {
+ // an AddRef was done by MarshalInterface AND the CExposedDocfile ctor,
+ // so Release one of those references here.
+ pdfb->vRelease();
+
+ // was AddRef'd by MarshalInterface but was only needed to find the
+ // ppc so we can Release it here.
+ pgc->Release();
+
+ }
+ else
+#endif
+ {
+ // unmarshal from TABLE, add our own references.
+ pdf->vAddRef();
+ }
+
+ fRoot = pdf->IsRoot();
+ *ppv = (void *)pedf;
+#ifdef MULTIHEAP
+ if (pvBaseOld != pvBaseNew)
+ {
+ pcSharedMemory.SetThreadAllocatorState(NULL);
+ g_smAllocator.Uninit(); // delete the extra mapping
+ }
+ g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL);
+#endif
+
+ mtx.Release();
+
+#ifdef MULTIHEAP
+ if (mshlflags == MSHLFLAGS_NORMAL && fRoot)
+ {
+ // release tree mutex first to prevent deadlock
+ sc = CoReleaseMarshalData (pstm); // ignore error, COM will cleanup
+ }
+#endif
+
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::Unmarshal => %p\n", *ppv));
+ return S_OK;
+ EH_exp:
+ pedf->Release();
+ goto EH_Err;
+ EH_ppc:
+ ppc->Release();
+ EH_mtx:
+ mtx.Release();
+#ifdef DCOM
+ EH_pgc:
+ if (mshlflags == MSHLFLAGS_NORMAL)
+ pgc->Release();
+ EH_pdfb:
+ if (mshlflags == MSHLFLAGS_NORMAL)
+ pdfb->vRelease();
+ EH_pdf:
+ if (mshlflags == MSHLFLAGS_NORMAL)
+ pdf->vRelease();
+#else
+ EH_pgc:
+ EH_pdfb:
+ EH_pdf:
+#endif
+ EH_mem:
+EH_Err:
+#ifdef MULTIHEAP
+ pcSharedMemory.SetThreadAllocatorState(NULL);
+ g_smAllocator.Uninit(); // delete the file mapping in error case
+ g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL);
+#endif
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::GetUnmarshalClass, public
+//
+// Synopsis: Returns the class ID
+//
+// Arguments: [riid] - IID of object
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+// [pcid] - CLSID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcid]
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::GetUnmarshalClass(REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pcid)
+{
+ SCODE sc;
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ olLog(("%p::In CExposedDocFile::GetUnmarshalClass("
+ "riid, %p, %lu, %p, %lu, %p)\n",
+ this, pv, dwDestContext, pvDestContext, mshlflags, pcid));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::GetUnmarshalClass:%p("
+ "riid, %p, %lu, %p, %lu, %p)\n", this,
+ pv, dwDestContext, pvDestContext, mshlflags, pcid));
+
+ UNREFERENCED_PARM(pv);
+ UNREFERENCED_PARM(mshlflags);
+
+ olChk(ValidateOutBuffer(pcid, sizeof(CLSID)));
+ memset(pcid, 0, sizeof(CLSID));
+ olChk(ValidateIid(riid));
+ olChk(Validate());
+ olChk(_pdf->CheckReverted());
+
+#if !defined(DCOM)
+ if (((dwDestContext != MSHCTX_LOCAL) &&
+ (dwDestContext != MSHCTX_INPROC)) ||
+ pvDestContext != NULL)
+#else
+ if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
+ {
+ IMarshal *pmsh;
+
+ if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
+ dwDestContext, pvDestContext,
+ mshlflags, &pmsh)))
+ {
+ sc = GetScode(pmsh->GetUnmarshalClass(riid, pv, dwDestContext,
+ pvDestContext, mshlflags,
+ pcid));
+ pmsh->Release();
+ }
+ }
+ else if (pvDestContext != NULL)
+#endif
+ {
+ sc = STG_E_INVALIDPARAMETER;
+ }
+ else
+ {
+ *pcid = CLSID_DfMarshal;
+ }
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::GetUnmarshalClass\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::GetUnmarshalClass(). ret = %lx\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::GetMarshalSizeMax, public
+//
+// Synopsis: Returns the size needed for the marshal buffer
+//
+// Arguments: [riid] - IID of object being marshaled
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+// [pcbSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbSize]
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::GetMarshalSizeMax(REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pcbSize)
+{
+ SCODE sc;
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ UNREFERENCED_PARM(pv);
+ olLog(("%p::In CExposedDocFile::GetMarshalSizeMax("
+ "riid, %p, %lu, %p, %lu, %p)\n",
+ this, pv, dwDestContext, pvDestContext, mshlflags, pcbSize));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::GetMarshalSizeMax:%p("
+ "riid, %p, %lu, %p, %lu, %p)\n", this,
+ pv, dwDestContext, pvDestContext, mshlflags, pcbSize));
+
+ olChk(Validate());
+ olChk(_pdf->CheckReverted());
+
+#if !defined(DCOM)
+ if (((dwDestContext != MSHCTX_LOCAL) &&
+ (dwDestContext != MSHCTX_INPROC)) ||
+ pvDestContext != NULL)
+#else
+ if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
+ {
+ IMarshal *pmsh;
+
+ if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
+ dwDestContext, pvDestContext,
+ mshlflags, &pmsh)))
+ {
+ sc = GetScode(pmsh->GetMarshalSizeMax(riid, pv, dwDestContext,
+ pvDestContext, mshlflags,
+ pcbSize));
+ pmsh->Release();
+ }
+ }
+ else if (pvDestContext != NULL)
+#endif
+ {
+ sc = STG_E_INVALIDPARAMETER;
+ }
+ else
+ {
+ sc = GetStdMarshalSize(riid,
+ IID_IStorage,
+ dwDestContext,
+ pvDestContext,
+ mshlflags, pcbSize,
+ sizeof(CPubDocFile *)+sizeof(CDFBasis *),
+#ifdef ASYNC
+ &_cpoint,
+ TRUE,
+#endif
+ _ppc, P_INDEPENDENT(_pdf->GetDFlags()));
+
+#ifdef MULTIHEAP
+ if (_pdf->IsRoot())
+ {
+ DWORD cbSize = 0;
+ IMarshal *pmsh;
+
+ if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
+ dwDestContext, pvDestContext,
+ mshlflags, &pmsh)))
+ {
+ sc = GetScode(pmsh->GetMarshalSizeMax(riid, pv, dwDestContext,
+ pvDestContext, mshlflags,
+ &cbSize));
+ pmsh->Release();
+ *pcbSize += cbSize;
+ }
+ }
+#endif
+ }
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::GetMarshalSizeMax\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::GetMarshalSizeMax()."
+ "*pcbSize == %lu, ret == %lx\n", this, *pcbSize, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::MarshalInterface, public
+//
+// Synopsis: Marshals a given object
+//
+// Arguments: [pstStm] - Stream to write marshal data into
+// [riid] - Interface to marshal
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+//
+// Returns: Appropriate status code
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::MarshalInterface(IStream *pstStm,
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ SCODE sc;
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ olLog(("%p::In CExposedDocFile::MarshalInterface("
+ "%p, riid, %p, %lu, %p, %lu). Context == %lX\n",
+ this, pstStm, pv, dwDestContext,
+ pvDestContext, mshlflags,(ULONG)GetCurrentContextId()));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::MarshalInterface:%p("
+ "%p, riid, %p, %lu, %p, %lu)\n", this, pstStm, pv,
+ dwDestContext, pvDestContext, mshlflags));
+
+ UNREFERENCED_PARM(pv);
+
+ olChk(Validate());
+ olChk(_pdf->CheckReverted());
+
+#if !defined(DCOM)
+ if (((dwDestContext != MSHCTX_LOCAL) &&
+ (dwDestContext != MSHCTX_INPROC)) ||
+ pvDestContext != NULL)
+#else
+ if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
+ {
+ IMarshal *pmsh;
+
+ if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
+ dwDestContext, pvDestContext,
+ mshlflags, &pmsh)))
+ {
+ sc = GetScode(pmsh->MarshalInterface(pstStm, riid, pv,
+ dwDestContext, pvDestContext,
+ mshlflags));
+ pmsh->Release();
+ }
+ }
+ else if (pvDestContext != NULL)
+#endif
+ {
+ sc = STG_E_INVALIDPARAMETER;
+ }
+ else
+ {
+ olChk(StartMarshal(pstStm, riid, IID_IStorage, mshlflags));
+
+#ifdef MULTIHEAP
+ olChk(MarshalSharedMemory(pstStm, _ppc));
+#endif
+#ifdef POINTER_IDENTITY
+ olChk(MarshalPointer(pstStm, (CExposedDocFile*) GetNextMarshal()));
+#endif
+ olChk(MarshalPointer(pstStm, BP_TO_P(CPubDocFile *, _pdf)));
+ olChk(MarshalPointer(pstStm, BP_TO_P(CDFBasis *, _pdfb)));
+#ifdef ASYNC
+ olChk(MarshalContext(pstStm,
+ _ppc,
+ dwDestContext,
+ pvDestContext,
+ mshlflags,
+ TRUE,
+ P_INDEPENDENT(_pdf->GetDFlags())));
+
+ sc = MarshalConnection(pstStm,
+ &_cpoint,
+ dwDestContext,
+ pvDestContext,
+ mshlflags);
+#else
+ olChk(MarshalContext(pstStm,
+ _ppc,
+ dwDestContext,
+ pvDestContext,
+ mshlflags,
+ P_INDEPENDENT(_pdf->GetDFlags())));
+#endif
+
+#ifdef MULTIHEAP
+ if (_pdf->IsRoot())
+ {
+ IMarshal *pmsh;
+ if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
+ dwDestContext, pvDestContext,
+ mshlflags, &pmsh)))
+ {
+ sc = GetScode(pmsh->MarshalInterface(pstStm, riid, pv,
+ dwDestContext, pvDestContext,
+ mshlflags));
+ pmsh->Release();
+ }
+ }
+#endif
+
+ if (SUCCEEDED(sc) && mshlflags != MSHLFLAGS_TABLEWEAK)
+ {
+ _pdf->vAddRef();
+ _pdfb->vAddRef();
+ }
+ }
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::MarshalInterface\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::MarshalInterface(). ret == %lx\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::UnmarshalInterface, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [pstStm] -
+// [riid] -
+// [ppvObj] -
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::UnmarshalInterface(IStream *pstStm,
+ REFIID riid,
+ void **ppvObj)
+{
+ olLog(("%p::INVALID CALL TO CExposedDocFile::UnmarshalInterface()\n",
+ this));
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::StaticReleaseMarshalData, public static
+//
+// Synopsis: Releases any references held in marshal data
+//
+// Arguments: [pstStm] - Marshal data stream
+//
+// Returns: Appropriate status code
+//
+// History: 02-Feb-94 DrewB Created
+//
+// Notes: Assumes standard marshal header has already been read
+//
+//---------------------------------------------------------------
+
+
+SCODE CExposedDocFile::StaticReleaseMarshalData(IStream *pstStm,
+ DWORD mshlflags)
+{
+ SCODE sc;
+ CPubDocFile *pdf;
+ CDFBasis *pdfb;
+#ifdef POINTER_IDENTITY
+ CExposedDocFile *pedf;
+#endif
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::StaticReleaseMarshalData:("
+ "%p, %lX)\n", pstStm, mshlflags));
+
+#ifdef MULTIHEAP
+ ContextId cntxid;
+ CPerContext pcSharedMemory (NULL); // bootstrap object
+ olChk(UnmarshalSharedMemory(pstStm, mshlflags, &pcSharedMemory, &cntxid));
+#endif
+#ifdef POINTER_IDENTITY
+ olChk(UnmarshalPointer(pstStm, (void **) &pedf));
+#endif
+ olChk(UnmarshalPointer(pstStm, (void **)&pdf));
+ olChk(UnmarshalPointer(pstStm, (void **)&pdfb));
+#ifdef ASYNC
+ olChk(ReleaseContext(pstStm, TRUE,
+ P_INDEPENDENT(pdf->GetDFlags()),
+ mshlflags));
+ olChk(ReleaseConnection(pstStm, mshlflags));
+#else
+ olChk(ReleaseContext(pstStm, P_INDEPENDENT(pdf->GetDFlags()), mshlflags));
+#endif
+
+ if (mshlflags != MSHLFLAGS_TABLEWEAK)
+ {
+ // Use DecRef rather than release because Release could cause
+ // a flush. We may not have any ILockBytes around to support
+ // a flush at this point
+ pdf->vDecRef();
+
+ pdfb->vRelease();
+ }
+
+#ifdef MULTIHEAP
+ if (SUCCEEDED(sc) && pdf->IsRoot())
+ {
+ sc = CoReleaseMarshalData (pstStm);
+ }
+#endif
+
+ olDebugOut((DEB_ITRACE,
+ "Out CExposedDocFile::StaticReleaseMarshalData\n"));
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::ReleaseMarshalData, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [pstStm] -
+//
+// Returns: Appropriate status code
+//
+// History: 18-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::ReleaseMarshalData(IStream *pstStm)
+{
+ SCODE sc;
+ DWORD mshlflags;
+ IID iid;
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ olLog(("%p::In CExposedDocFile::ReleaseMarshalData(%p)\n", this, pstStm));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::ReleaseMarshalData:%p(%p)\n",
+ this, pstStm));
+
+ olChk(Validate());
+ olChk(_pdf->CheckReverted());
+ olChk(SkipStdMarshal(pstStm, &iid, &mshlflags));
+ olAssert(IsEqualIID(iid, IID_IStorage));
+ sc = StaticReleaseMarshalData(pstStm, mshlflags);
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::ReleaseMarshalData\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::ReleaseMarshalData(). ret == %lx\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::DisconnectObject, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [dwRevserved] -
+//
+// Returns: Appropriate status code
+//
+// History: 18-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::DisconnectObject(DWORD dwReserved)
+{
+ olLog(("%p::INVALID CALL TO CExposedDocFile::DisconnectObject()\n",
+ this));
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::SwitchToFile, public
+//
+// Synopsis: Switches the underlying file to another file
+//
+// Arguments: [ptcsFile] - New file name
+//
+// Returns: Appropriate status code
+//
+// History: 08-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+
+// BUGBUG copy over IAccessControl information
+STDMETHODIMP CExposedDocFile::SwitchToFile(OLECHAR *ptcsFile)
+{
+
+ ULONG ulOpenLock;
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+
+ olLog(("%p::In CExposedDocFile::SwitchToFile(" OLEFMT ")\n",
+ this, ptcsFile));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::SwitchToFile:"
+ "%p(" OLEFMT ")\n",
+ this, ptcsFile));
+
+ olChk(ValidateNameW(ptcsFile, _MAX_PATH));
+ olChk(Validate());
+
+ olChk(TakeSafeSem());
+ olChk(_pdf->CheckReverted());
+#ifdef COORD
+ olAssert(_pdf->IsRoot() || _pdf->IsCoord());
+#else
+ olAssert(_pdf->IsRoot());
+#endif
+
+ SafeReadAccess();
+
+ ulOpenLock = _ppc->GetOpenLock();
+#ifdef COORD
+ sc = _pdf->GetRoot()->SwitchToFile(ptcsFile,
+ _ppc->GetOriginal(),
+ &ulOpenLock);
+#else
+ sc = ((CRootPubDocFile *)(CPubDocFile*)_pdf)->SwitchToFile(ptcsFile,
+ _ppc->GetOriginal(),
+ &ulOpenLock);
+#endif
+
+ _ppc->SetOpenLock(ulOpenLock);
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::SwitchToFile\n"));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::SwitchToFile(). ret == %lx\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+
+#if WIN32 >= 300
+ // IAccessControl methods
+STDMETHODIMP CExposedDocFile::GrantAccessRights(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[])
+{
+ olAssert((_pIAC != NULL));
+ return _pIAC->GrantAccessRights(cCount, pAccessRequestList);
+}
+
+STDMETHODIMP CExposedDocFile::SetAccessRights(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[])
+{
+ olAssert((_pIAC != NULL));
+ return _pIAC->SetAccessRights(cCount, pAccessRequestList);
+}
+
+STDMETHODIMP CExposedDocFile::ReplaceAllAccessRights(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[])
+{
+ olAssert((_pIAC != NULL));
+ return _pIAC->ReplaceAllAccessRights(cCount, pAccessRequestList);
+}
+
+STDMETHODIMP CExposedDocFile::DenyAccessRights(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[])
+{
+ olAssert((_pIAC != NULL));
+ return _pIAC->DenyAccessRights(cCount, pAccessRequestList);
+}
+
+STDMETHODIMP CExposedDocFile::RevokeExplicitAccessRights(ULONG cCount,
+ TRUSTEE pTrustee[])
+{
+ olAssert((_pIAC != NULL));
+ return _pIAC->RevokeExplicitAccessRights(cCount, pTrustee);
+}
+
+STDMETHODIMP CExposedDocFile::IsAccessPermitted(TRUSTEE *pTrustee,
+ DWORD grfAccessPermissions)
+{
+ olAssert((_pIAC != NULL));
+ return _pIAC->IsAccessPermitted(pTrustee, grfAccessPermissions);
+}
+
+STDMETHODIMP CExposedDocFile::GetEffectiveAccessRights(TRUSTEE *pTrustee,
+ DWORD *pgrfAccessPermissions )
+{
+ olAssert((_pIAC != NULL));
+ return _pIAC->GetEffectiveAccessRights(pTrustee, pgrfAccessPermissions);
+}
+
+STDMETHODIMP CExposedDocFile::GetExplicitAccessRights(ULONG *pcCount,
+ PEXPLICIT_ACCESS *pExplicitAccessList)
+{
+ olAssert((_pIAC != NULL));
+ return _pIAC->GetExplicitAccessRights(pcCount, pExplicitAccessList);
+}
+
+STDMETHODIMP CExposedDocFile::CommitAccessRights(DWORD grfCommitFlags)
+{
+ olAssert((_pIAC != NULL));
+ return _pIAC->CommitAccessRights(grfCommitFlags);
+}
+
+STDMETHODIMP CExposedDocFile::RevertAccessRights()
+{
+ olAssert((_pIAC != NULL));
+ return _pIAC->RevertAccessRights();
+}
+
+
+
+#endif // if WIN32 >= 300
+
+
+#ifdef COORD
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::CommitPhase1, public
+//
+// Synopsis: Do phase 1 of an exposed two phase commit
+//
+// Arguments: [grfCommitFlags] -- Commit flags
+//
+// Returns: Appropriate status code
+//
+// History: 08-Aug-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CExposedDocFile::CommitPhase1(DWORD grfCommitFlags)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+
+ olChk(VerifyCommitFlags(grfCommitFlags));
+ olChk(Validate());
+
+ olChk(TakeSafeSem());
+ SafeWriteAccess();
+
+ sc = _pdf->CommitPhase1(grfCommitFlags,
+ &_ulLock,
+ &_sigMSF,
+ &_cbSizeBase,
+ &_cbSizeOrig);
+EH_Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::CommitPhase2, public
+//
+// Synopsis: Do phase 2 of an exposed two phase commit
+//
+// Arguments: [grfCommitFlags] -- Commit flags
+// [fCommit] -- TRUE if transaction is to commit, FALSE if abort
+//
+// Returns: Appropriate status code
+//
+// History: 08-Aug-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CExposedDocFile::CommitPhase2(DWORD grfCommitFlags,
+ BOOL fCommit)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+
+ olChk(Validate());
+
+ olChk(TakeSafeSem());
+ SafeWriteAccess();
+
+ sc = _pdf->CommitPhase2(grfCommitFlags,
+ fCommit,
+ _ulLock,
+ _sigMSF,
+ _cbSizeBase,
+ _cbSizeOrig);
+
+ _ulLock = _cbSizeBase = _cbSizeOrig = 0;
+ _sigMSF = 0;
+EH_Err:
+ return sc;
+}
+#endif //COORD
+
+
+#ifdef NEWPROPS
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::GetStorage, public IPrivateStorage
+//
+// Synopsis: Returns the IStorage for this object.
+//
+// Notes: This member is called by CPropertyStorage.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(IStorage *)
+CExposedDocFile::GetStorage(VOID)
+{
+ return this;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::Lock, public IPrivateStorage
+//
+// Synopsis: Acquires the semaphore associated with the docfile.
+//
+// Notes: This member is called by CPropertyStorage.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP
+CExposedDocFile::Lock(DWORD dwTimeout)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ TakeSem();
+ SetDifferentBasisAccess(_pdfb, _ppc);
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::Unlock, public IPrivateStorage
+//
+// Synopsis: Releases the semaphore associated with the docfile.
+//
+// Notes: This member is called by CPropertyStorage.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(VOID)
+CExposedDocFile::Unlock(VOID)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ ClearBasisAccess(_pdfb);
+ ReleaseSem(S_OK);
+}
+#endif
+
diff --git a/private/ole32/stg/exp/expdf.hxx b/private/ole32/stg/exp/expdf.hxx
new file mode 100644
index 000000000..86ff3647d
--- /dev/null
+++ b/private/ole32/stg/exp/expdf.hxx
@@ -0,0 +1,306 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: expdf.hxx
+//
+// Contents: Exposed DocFile header
+//
+// Classes: CExposedDocFile
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __EXPDF_HXX__
+#define __EXPDF_HXX__
+
+#include <except.hxx>
+#include <dfmsp.hxx>
+#include <dfbasis.hxx>
+#include <psstream.hxx>
+#include <debug.hxx>
+#include <stgprops.hxx>
+#include <safedecl.hxx>
+#include <psetstg.hxx>
+#include "dfmem.hxx"
+#include <mrshlist.hxx>
+
+#ifdef ASYNC
+#include "astgconn.hxx"
+#endif
+
+// CopyDocFileToIStorage flags
+#define COPY_STORAGES 1
+#define COPY_STREAMS 2
+#define COPY_ALL (COPY_STORAGES | COPY_STREAMS)
+
+class CPubDocFile;
+class PDocFile;
+class CPerContext;
+
+//+--------------------------------------------------------------
+//
+// Class: CExposedDocFile (df)
+//
+// Purpose: Exposed DocFile class
+//
+// Interface: See IStorage
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+interface CExposedDocFile
+ :
+ public IStorage,
+#ifdef NEWPROPS
+ public CDocFilePropertySetStorage,
+#endif
+ public IRootStorage,
+ public IMarshal,
+#if WIN32 >= 300
+ public IAccessControl,
+#endif
+ public CMallocBased
+#ifdef NEWPROPS
+ , public IPrivateStorage
+#endif
+#ifdef POINTER_IDENTITY
+ , public CMarshalList
+#endif
+#ifdef ASYNC
+ , public CAsyncConnectionContainer
+#endif
+{
+public:
+ CExposedDocFile(CPubDocFile *pdf,
+ CDFBasis *pdfb,
+ CPerContext *ppc,
+ BOOL fOwnContext);
+#ifdef ASYNC
+ SCODE InitMarshal(DWORD dwAsyncFlags,
+ IDocfileAsyncConnectionPoint *pdacp);
+#endif
+
+ ~CExposedDocFile(void);
+
+ // From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // IMarshal
+ STDMETHOD(GetUnmarshalClass)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID *ppv);
+ static SCODE StaticReleaseMarshalData(IStream *pstStm,
+ DWORD mshlflags);
+ STDMETHOD(ReleaseMarshalData)(IStream *pStm);
+ STDMETHOD(DisconnectObject)(DWORD dwReserved);
+
+ // IStorage
+ STDMETHOD(CreateStream)(OLECHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(OpenStream)(OLECHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(CreateStorage)(OLECHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ LPSTGSECURITY reserved2,
+ IStorage **ppstg);
+ STDMETHOD(OpenStorage)(OLECHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg);
+ STDMETHOD(CopyTo)(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest);
+ STDMETHOD(MoveElementTo)(OLECHAR const *lpszName,
+ IStorage *pstgDest,
+ OLECHAR const *lpszNewName,
+ DWORD grfFlags);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(EnumElements)(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm);
+ STDMETHOD(DestroyElement)(OLECHAR const *pwcsName);
+ STDMETHOD(RenameElement)(OLECHAR const *pwcsOldName,
+ OLECHAR const *pwcsNewName);
+ STDMETHOD(SetElementTimes)(const OLECHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+ STDMETHOD(SetClass)(REFCLSID clsid);
+ STDMETHOD(SetStateBits)(DWORD grfStateBits, DWORD grfMask);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+
+
+ // IRootStorage
+ STDMETHOD(SwitchToFile)(OLECHAR *ptcsFile);
+
+#ifdef NEWPROPS
+ // IPrivateStorage
+ STDMETHOD_(IStorage *,GetStorage)(VOID);
+ STDMETHOD(Lock)(DWORD dwTime);
+ STDMETHOD_(VOID, Unlock)(VOID);
+#endif
+
+ // New methods
+ inline SCODE Validate(void) const;
+ inline CPubDocFile *GetPub(void) const;
+ inline CPerContext *GetContext(void) const;
+
+ static SCODE Unmarshal(IStream *pstm,
+ void **ppv,
+ DWORD mshlflags);
+#if WIN32 >= 300
+ // IAccessControl
+ STDMETHOD(GrantAccessRights)(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[]);
+ STDMETHOD(SetAccessRights)(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[]);
+ STDMETHOD(ReplaceAllAccessRights)(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[]);
+ STDMETHOD(DenyAccessRights)(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[]);
+ STDMETHOD(RevokeExplicitAccessRights)(ULONG cCount,
+ TRUSTEE Trustee[]);
+ STDMETHOD(IsAccessPermitted)(TRUSTEE *Trustee,
+ DWORD grfAccessPermissions);
+ STDMETHOD(GetEffectiveAccessRights)(TRUSTEE *Trustee,
+ DWORD *pgrfAccessPermissions );
+ STDMETHOD(GetExplicitAccessRights)(ULONG *pcCount,
+ PEXPLICIT_ACCESS *pExplicitAccessList);
+
+ STDMETHOD(CommitAccessRights)(DWORD grfCommitFlags);
+ STDMETHOD(RevertAccessRights)();
+#endif // if WIN32 >= 300
+
+#ifdef COORD
+ SCODE CommitPhase1(DWORD grfCommitFlags);
+ SCODE CommitPhase2(DWORD grfCommitFlags, BOOL fCommit);
+#endif
+
+private:
+ SCODE CreateEntry(CDfName const *pdfn,
+ DWORD dwType,
+ DWORD grfMode,
+ void **ppv);
+ SCODE OpenEntry(CDfName const *pdfn,
+ DWORD dwType,
+ DWORD grfMode,
+ void **ppv);
+ SCODE MoveElementWorker(WCHAR const *pwcsName,
+ IStorage *pstgParent,
+ OLECHAR const *ptcsNewName,
+ DWORD grfFlags);
+ static DWORD MakeCopyFlags(DWORD ciidExclude,
+ IID const *rgiidExclude);
+ SCODE CopyDocFileToIStorage(PDocFile *pdfFrom,
+ IStorage *pstgTo,
+ SNBW snbExclude,
+ DWORD dwCopyFlags);
+ SCODE CopySStreamToIStream(PSStream *psstFrom, IStream *pstTo);
+ SCODE ConvertInternalStream(CExposedDocFile *pdfExp);
+ inline SCODE CheckCopyTo(void);
+
+ CBasedPubDocFilePtr _pdf;
+ CBasedDFBasisPtr _pdfb;
+ CPerContext *_ppc;
+ BOOL _fOwnContext;
+ ULONG _sig;
+ LONG _cReferences;
+#if WIN32 >= 300
+ IAccessControl *_pIAC;
+#endif // WIN32 >= 300
+
+#ifdef COORD
+ //These are holder values for an exposed two-phase commit.
+ ULONG _ulLock;
+ DFSIGNATURE _sigMSF;
+ ULONG _cbSizeBase;
+ ULONG _cbSizeOrig;
+#endif
+};
+
+SAFE_INTERFACE_PTR(SafeCExposedDocFile, CExposedDocFile);
+
+#define CEXPOSEDDOCFILE_SIG LONGSIG('E', 'D', 'F', 'L')
+#define CEXPOSEDDOCFILE_SIGDEL LONGSIG('E', 'd', 'F', 'l')
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::Validate, public
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CExposedDocFile::Validate(void) const
+{
+ olChkBlocks((DBG_FAST));
+ return (this == NULL || _sig != CEXPOSEDDOCFILE_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::GetPub, public
+//
+// Synopsis: Returns the public
+//
+// History: 26-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CPubDocFile *CExposedDocFile::GetPub(void) const
+{
+#ifdef MULTIHEAP
+ // The tree mutex must be taken before calling this routine
+ // CSafeMultiHeap smh(_ppc); // optimzation
+#endif
+ return BP_TO_P(CPubDocFile *, _pdf);
+}
+
+inline CPerContext * CExposedDocFile::GetContext(void) const
+{
+ return _ppc;
+}
+
+#endif
diff --git a/private/ole32/stg/exp/exphead.cxx b/private/ole32/stg/exp/exphead.cxx
new file mode 100644
index 000000000..621b3aa0c
--- /dev/null
+++ b/private/ole32/stg/exp/exphead.cxx
@@ -0,0 +1,59 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: exphead.cxx
+//
+// Contents: Precompiled headers
+//
+// History: 26-Oct-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windef.h>
+}
+
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef REF
+#include <windows.h>
+#include <ole2.h>
+#else
+#include <ref.hxx>
+#endif //!REF
+
+#include <propset.h>
+#include <propapi.h>
+#include <propstm.hxx>
+#include <stgprops.hxx>
+
+#if defined(_CHICAGO_)
+#include <widewrap.h>
+#endif
+
+#include <safedecl.hxx>
+#include <dfexcept.hxx>
+
+#include <docfilep.hxx>
+
+#include <msf.hxx>
+
+#include <publicdf.hxx>
+#ifndef REF
+#include <debug.hxx>
+#include <dfmem.hxx>
+#endif //!REF
+#include <funcs.hxx>
+#ifdef ASYNC
+#include <async.hxx>
+#endif
+
diff --git a/private/ole32/stg/exp/expiter.cxx b/private/ole32/stg/exp/expiter.cxx
new file mode 100644
index 000000000..3543a9cea
--- /dev/null
+++ b/private/ole32/stg/exp/expiter.cxx
@@ -0,0 +1,494 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: expiter.cxx
+//
+// Contents: CExposedIterator implementation
+//
+// History: 12-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <expiter.hxx>
+#include <sstream.hxx>
+#include <ptrcache.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::CExposedIterator, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [ppdf] - Public docfile
+// [pdfnKey] - Initial key
+// [pdfb] - DocFile basis
+// [ppc] - Context
+// [fOwnContext] - Whether this object owns the context
+//
+// History: 12-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+CExposedIterator::CExposedIterator(CPubDocFile *ppdf,
+ CDfName *pdfnKey,
+ CDFBasis *pdfb,
+ CPerContext *ppc,
+ BOOL fOwnContext)
+{
+ olDebugOut((DEB_ITRACE, "In CExposedIterator::CExposedIterator("
+ "%p, %d:%s, %p, %p, %u)\n", ppdf, pdfnKey->GetLength(),
+ pdfnKey->GetBuffer(), pdfb, ppc, fOwnContext));
+ _ppc = ppc;
+ _fOwnContext = fOwnContext;
+ _ppdf = P_TO_BP(CBasedPubDocFilePtr, ppdf);
+ _ppdf->vAddRef();
+ _dfnKey.Set(pdfnKey);
+ _pdfb = P_TO_BP(CBasedDFBasisPtr, pdfb);
+ _pdfb->vAddRef();
+ _cReferences = 1;
+ _sig = CEXPOSEDITER_SIG;
+ olDebugOut((DEB_ITRACE, "Out CExposedIterator::CExposedIterator\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::~CExposedIterator, public
+//
+// Synopsis: Destructor
+//
+// History: 22-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+CExposedIterator::~CExposedIterator(void)
+{
+ olDebugOut((DEB_ITRACE, "In CExposedIterator::~CExposedIterator\n"));
+ _sig = CEXPOSEDITER_SIGDEL;
+
+ //In order to call into the tree, we need to take the mutex.
+ //The mutex may get deleted in _ppc->Release(), so we can't
+ //release it here. The mutex actually gets released in
+ //CPerContext::Release() or in the CPerContext destructor.
+ SCODE sc;
+
+#if !defined(MULTIHEAP)
+ // TakeSem and ReleaseSem are moved to the Release Method
+ // so that the deallocation for this object is protected
+ if (_ppc)
+ {
+ sc = TakeSem();
+ SetWriteAccess();
+ olAssert(SUCCEEDED(sc));
+ }
+#ifdef ASYNC
+ IDocfileAsyncConnectionPoint *pdacp = _cpoint.GetMarshalPoint();
+#endif
+#endif //MULTIHEAP
+
+ olAssert(_cReferences == 0);
+ if (_ppdf)
+ _ppdf->CPubDocFile::vRelease();
+ if (_pdfb)
+ _pdfb->CDFBasis::vRelease();
+#if !defined(MULTIHEAP)
+ if (_fOwnContext && _ppc)
+ {
+ _ppc->Release();
+ }
+ else if (_ppc)
+ {
+ ReleaseSem(sc);
+ }
+#ifdef ASYNC
+ //Mutex has been released, so we can release the connection point
+ // without fear of deadlock.
+ if (pdacp != NULL)
+ pdacp->Release;
+#endif
+#endif // MULTIHEAP
+ olDebugOut((DEB_ITRACE, "Out CExposedIterator::~CExposedIterator\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::Next, public
+//
+// Synopsis: Gets N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+// [rgelt] - Array for element return
+// [pceltFetched] - If non-NULL, contains the number of
+// elements fetched
+//
+// Returns: Appropriate status code
+//
+// Modifies: [rgelt]
+// [pceltFetched]
+//
+// History: 16-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+_OLESTDMETHODIMP CExposedIterator::Next(ULONG celt,
+ STATSTGW FAR *rgelt,
+ ULONG *pceltFetched)
+{
+ SAFE_SEM;
+ SAFE_ACCESS;
+ SCODE sc;
+ STATSTGW *pelt = rgelt;
+ ULONG celtDone;
+ CDfName dfnInitial;
+ CPtrCache pc;
+ STATSTGW stat;
+
+ olDebugOut((DEB_TRACE, "In CExposedIterator::Next(%lu, %p, %p)\n",
+ celt, rgelt, pceltFetched));
+
+ if (pceltFetched)
+ {
+ olChkTo(EH_RetSc, ValidateOutBuffer(pceltFetched, sizeof(ULONG)));
+ *pceltFetched = 0;
+ }
+ else if (celt > 1)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChkTo(EH_RetSc, ValidateOutBuffer(rgelt,
+ (size_t)(sizeof(STATSTGW)*celt)));
+ memset(rgelt, 0, (size_t)(sizeof(STATSTGW)*celt));
+ olChk(Validate());
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SetReadAccess();
+
+ olChk(_ppdf->CheckReverted());
+
+ // Preserve initial key to reset on failure
+ dfnInitial.Set(&_dfnKey);
+
+ TRY
+ {
+ for (; pelt<rgelt+celt; pelt++)
+ {
+ sc = _ppdf->FindGreaterEntry(&_dfnKey, NULL, &stat, FALSE);
+ if (FAILED(sc))
+ {
+ if (sc == STG_E_NOMOREFILES)
+ sc = S_FALSE;
+ break;
+ }
+
+ if (FAILED(sc = pc.Add(stat.pwcsName)))
+ {
+ TaskMemFree(stat.pwcsName);
+ break;
+ }
+
+ _dfnKey.Set(stat.pwcsName);
+
+ stat.grfMode = 0;
+ stat.grfLocksSupported = 0;
+ stat.STATSTG_dwStgFmt = 0;
+
+ *pelt = stat;
+ }
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ END_PENDING_LOOP;
+
+ // Can't move this down because dfnInitial isn't set for all EH_Err cases
+ if (FAILED(sc))
+ _dfnKey.Set(&dfnInitial);
+
+ olDebugOut((DEB_TRACE, "Out CExposedIterator::Next => %lX\n", sc));
+EH_Err:
+ celtDone = pelt-rgelt;
+ if (FAILED(sc))
+ {
+ void *pv;
+
+ pc.StartEnum();
+ while (pc.Next(&pv))
+ TaskMemFree(pv);
+
+ }
+ else if (pceltFetched)
+ // May fault but that's acceptable
+ *pceltFetched = celtDone;
+EH_RetSc:
+ return _OLERETURN(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::Skip, public
+//
+// Synopsis: Skips N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+//
+// Returns: Appropriate status code
+//
+// History: 16-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedIterator::Skip(ULONG celt)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In CExposedIterator::Skip(%lu)\n", celt));
+
+ if (SUCCEEDED(sc = Validate()))
+ sc = hSkip(celt, FALSE);
+
+ olDebugOut((DEB_TRACE, "Out CExposedIterator::Skip\n"));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::Reset, public
+//
+// Synopsis: Rewinds the iterator
+//
+// Returns: Appropriate status code
+//
+// History: 22-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedIterator::Reset(void)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In CExposedIterator::Reset()\n"));
+
+ if (SUCCEEDED(sc = Validate()))
+ sc = hReset();
+
+ olDebugOut((DEB_TRACE, "Out CExposedIterator::Reset\n"));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::Clone, public
+//
+// Synopsis: Clones this iterator
+//
+// Arguments: [ppenm] - Clone return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 26-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedIterator::Clone(IEnumSTATSTG **ppenm)
+{
+ SCODE sc, scSem = STG_E_INUSE;
+ SafeCExposedIterator piExp;
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ olDebugOut((DEB_TRACE, "In CExposedIterator::Clone(%p)\n", ppenm));
+
+ olChk(ValidateOutPtrBuffer(ppenm));
+ *ppenm = NULL;
+ olChk(Validate());
+ olChk(scSem = TakeSem());
+ if (!SUCCEEDED(sc = _ppdf->CheckReverted()))
+ {
+ ReleaseSem(scSem);
+ olChk(sc);
+ }
+ SetReadAccess();
+
+ piExp.Attach(new CExposedIterator(BP_TO_P(CPubDocFile *, _ppdf),
+ &_dfnKey,
+ BP_TO_P(CDFBasis *, _pdfb),
+ _ppc,
+ TRUE));
+ if ((CExposedIterator *)piExp == NULL)
+ sc = STG_E_INSUFFICIENTMEMORY;
+
+ ClearReadAccess();
+ ReleaseSem(scSem);
+
+ if (SUCCEEDED(sc))
+ {
+ _ppc->AddRef();
+ TRANSFER_INTERFACE(piExp, IEnumSTATSTG, ppenm);
+ }
+
+ if (_cpoint.IsInitialized())
+ {
+ olChkTo(EH_init, piExp->InitClone(&_cpoint));
+ }
+
+ olDebugOut((DEB_TRACE, "Out CExposedIterator::Clone => %p\n",
+ *ppenm));
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+EH_init:
+ piExp->Release();
+ goto EH_Err;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::Release, public
+//
+// Synopsis: Releases resources for the iterator
+//
+// Returns: Appropriate status code
+//
+// History: 22-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP_(ULONG) CExposedIterator::Release(void)
+{
+ LONG lRet;
+
+ olDebugOut((DEB_TRACE, "In CExposedIterator::Release()\n"));
+
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+ CPerContext *ppc = _ppc;
+ BOOL fOwnContext = _fOwnContext;
+ SCODE sc = S_OK;
+#endif
+ if (FAILED(Validate()))
+ return 0;
+ if ((lRet = hRelease()) == 0)
+#ifdef MULTIHEAP
+ {
+ if (_ppc)
+ {
+ sc = TakeSem();
+ SetWriteAccess();
+ olAssert(SUCCEEDED(sc));
+ }
+#ifdef ASYNC
+ IDocfileAsyncConnectionPoint *pdacp = _cpoint.GetMarshalPoint();
+#endif
+#endif //MULTIHEAP
+ delete this;
+#ifdef MULTIHEAP
+ if (fOwnContext && ppc)
+ {
+ BOOL fLastRef = ppc->LastRef();
+ ppc->Release();
+ if (fLastRef)
+ g_smAllocator.Uninit();
+ }
+ else if (ppc)
+ {
+ if (SUCCEEDED(sc)) ppc->UntakeSem();
+ }
+#ifdef ASYNC
+ //Mutex has been released, so we can release the connection point
+ // without fear of deadlock.
+ if (pdacp != NULL)
+ pdacp->Release();
+#endif
+ }
+#endif
+
+ olDebugOut((DEB_TRACE, "Out CExposedIterator::Release\n"));
+ return lRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+// History: 16-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP_(ULONG) CExposedIterator::AddRef(void)
+{
+ ULONG ulRet;
+
+ olDebugOut((DEB_TRACE, "In CExposedIterator::AddRef()\n"));
+
+ if (FAILED(Validate()))
+ return 0;
+ ulRet = hAddRef();
+
+ olDebugOut((DEB_TRACE, "Out CExposedIterator::AddRef\n"));
+ return ulRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 26-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedIterator::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In CExposedIterator::QueryInterface(?, %p)\n",
+ ppvObj));
+
+ if (SUCCEEDED(sc = Validate()))
+ sc = hQueryInterface(iid,
+ IID_IEnumSTATSTG,
+ (IEnumSTATSTG *)this,
+ ppvObj);
+#ifdef ASYNC
+ if (FAILED(sc) &&
+ IsEqualIID(iid, IID_IConnectionPointContainer) &&
+ _cpoint.IsInitialized())
+ {
+ *ppvObj = (IConnectionPointContainer *)this;
+ CExposedIterator::AddRef();
+ }
+#endif
+
+ olDebugOut((DEB_TRACE, "Out CExposedIterator::QueryInterface => %p\n",
+ ppvObj));
+ return ResultFromScode(sc);
+}
diff --git a/private/ole32/stg/exp/expiter.hxx b/private/ole32/stg/exp/expiter.hxx
new file mode 100644
index 000000000..41d20ac4d
--- /dev/null
+++ b/private/ole32/stg/exp/expiter.hxx
@@ -0,0 +1,92 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: expiter.hxx
+//
+// Contents: CExposedIterator header file
+//
+// Classes: CExposedIterator
+//
+// History: 12-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __EXPITER_HXX__
+#define __EXPITER_HXX__
+
+#include <dfmsp.hxx>
+#include <lock.hxx>
+#include <dfbasis.hxx>
+#include <peiter.hxx>
+#include <astgconn.hxx>
+
+class CDFBasis;
+class CDirectStream;
+
+//+--------------------------------------------------------------
+//
+// Class: CExposedIterator (ei)
+//
+// Purpose: Iterator for wrapped DocFiles
+//
+// Interface: See below
+//
+// History: 12-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+interface CExposedIterator
+ : public IEnumSTATSTG, public PExposedIterator
+#ifdef ASYNC
+, public CAsyncConnectionContainer
+#endif
+{
+public:
+ CExposedIterator(CPubDocFile *ppdf,
+ CDfName *pdfnKey,
+ CDFBasis *pdfb,
+ CPerContext *ppc,
+ BOOL fOwnContext);
+ ~CExposedIterator(void);
+
+ // From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // New methods
+ STDMETHOD(Next)(ULONG celt, STATSTG FAR *rgelt, ULONG *pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(IEnumSTATSTG **ppenm);
+
+ inline SCODE Validate(void) const;
+};
+
+SAFE_INTERFACE_PTR(SafeCExposedIterator, CExposedIterator);
+
+// DocFileIter signatures
+#define CEXPOSEDITER_SIG LONGSIG('E', 'D', 'F', 'I')
+#define CEXPOSEDITER_SIGDEL LONGSIG('E', 'd', 'F', 'i')
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::Validate, public
+//
+// Synopsis: Validates the signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE if the signature doesn't match
+//
+// History: 12-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CExposedIterator::Validate(void) const
+{
+ return (this == NULL || _sig != CEXPOSEDITER_SIG) ? STG_E_INVALIDHANDLE :
+ S_OK;
+}
+
+#endif
diff --git a/private/ole32/stg/exp/exppiter.cxx b/private/ole32/stg/exp/exppiter.cxx
new file mode 100644
index 000000000..7a62e7217
--- /dev/null
+++ b/private/ole32/stg/exp/exppiter.cxx
@@ -0,0 +1,432 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: exppiter.cxx
+//
+// Contents: CExposedPropertyIter implementation
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <expdf.hxx>
+#include <exppiter.hxx>
+#include <ptrcache.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropertyIter::CExposedPropertyIter, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [pedf] - Property storage being enumerated,
+// for name -> id mapping
+// [ppdf] - Public docfile
+// [pdfnKey] - Initial key
+// [pdfb] - DocFile basis
+// [ppc] - Context
+// [fOwnContext] - Whether this object owns the context
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CExposedPropertyIter::CExposedPropertyIter(CExposedDocFile *pedf,
+ CPubDocFile *ppdf,
+ CDfName *pdfnKey,
+ CDFBasis *pdfb,
+ CPerContext *ppc,
+ BOOL fOwnContext)
+{
+ olDebugOut((DEB_ITRACE, "In CExposedPropertyIter::"
+ "CExposedPropertyIter:%p(%p, %p, %d:%s, %p, %p, %u)\n", this,
+ pedf, ppdf, pdfnKey->GetLength(),
+ pdfnKey->GetBuffer(), pdfb, ppc, fOwnContext));
+ _ppc = ppc;
+ _fOwnContext = fOwnContext;
+ _pedf = pedf;
+ _ppdf = P_TO_BP(CBasedPubDocFilePtr, ppdf);
+ _ppdf->vAddRef();
+ _dfnKey.Set(pdfnKey);
+ _pdfb = P_TO_BP(CBasedDFBasisPtr, pdfb);
+ _pdfb->vAddRef();
+ _cReferences = 1;
+ _sig = CEXPOSEDPROPERTYITER_SIG;
+ olDebugOut((DEB_ITRACE,
+ "Out CExposedPropertyIter::CExposedPropertyIter\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropertyIter::~CExposedPropertyIter, public
+//
+// Synopsis: Destructor
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CExposedPropertyIter::~CExposedPropertyIter(void)
+{
+ olDebugOut((DEB_ITRACE,
+ "In CExposedPropertyIter::~CExposedPropertyIter\n"));
+ _sig = CEXPOSEDPROPERTYITER_SIGDEL;
+ olAssert(_cReferences == 0);
+ if (_ppdf)
+ _ppdf->CPubDocFile::vRelease();
+ if (_pdfb)
+ _pdfb->CDFBasis::vRelease();
+ if (_fOwnContext && _ppc)
+ _ppc->Release();
+ olDebugOut((DEB_ITRACE,
+ "Out CExposedPropertyIter::~CExposedPropertyIter\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropertyIter::Next, public
+//
+// Synopsis: Gets N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+// [rgelt] - Array for element return
+// [pceltFetched] - If non-NULL, contains the number of
+// elements fetched
+//
+// Returns: Appropriate status code
+//
+// Modifies: [rgelt]
+// [pceltFetched]
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+_OLESTDMETHODIMP CExposedPropertyIter::Next(ULONG celt,
+ STATPROPSTG FAR *rgelt,
+ ULONG *pceltFetched)
+{
+ SAFE_SEM;
+ SAFE_ACCESS;
+ SCODE sc;
+ STATSTGW sstg;
+ STATPROPSTG *pelt = rgelt;
+ ULONG celtDone;
+ CDfName dfnInitial;
+ CPtrCache pc;
+ WCHAR *pwc;
+
+ olDebugOut((DEB_TRACE, "In CExposedPropertyIter::Next(%lu, %p, %p)\n",
+ celt, rgelt, pceltFetched));
+
+ if (pceltFetched)
+ {
+ olChkTo(EH_RetSc, ValidateOutBuffer(pceltFetched, sizeof(ULONG)));
+ *pceltFetched = 0;
+ }
+ else if (celt > 1)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olAssert(0xffffUL/sizeof(STATPROPSTG) >= celt);
+ olChkTo(EH_RetSc,
+ ValidateOutBuffer(rgelt, (size_t)(sizeof(STATPROPSTG)*celt)));
+ memset(rgelt, 0, (size_t)(sizeof(STATPROPSTG)*celt));
+ olChk(Validate());
+ olChk(_ppdf->CheckReverted());
+
+ olChk(TakeSafeSem());
+ SafeReadAccess();
+
+ // Preserve initial key
+ dfnInitial.Set(&_dfnKey);
+
+ TRY
+ {
+ for (; pelt<rgelt+celt; pelt++)
+ {
+ sc = _ppdf->FindGreaterEntry(&_dfnKey, NULL, &sstg, TRUE);
+ if (FAILED(sc))
+ {
+ if (sc == STG_E_NOMOREFILES)
+ sc = S_FALSE;
+ break;
+ }
+
+ _dfnKey.CopyString(sstg.pwcsName);
+ pwc = (WCHAR *)_dfnKey.GetBuffer();
+
+ // We need to copy the STATSTG fields into our
+ // STATPROPSTG
+ if (pwc[0] == PROPBYTE_WCHAR)
+ {
+ // Byte buffer name
+
+ TaskMemFree(sstg.pwcsName);
+
+ pelt->lpwstrName = NULL;
+ if (pwc[1] == PROPID_WCHAR)
+ {
+ // DISPID or PROPID
+ pelt->propid = *(DISPID *)(pwc+2);
+
+ // Fixed properties have DISPID == PROPID
+ if (pelt->propid < DISPID_MAX_FIXED)
+ pelt->dispid = pelt->propid;
+ }
+ else
+ {
+ // Property set, ignore
+ pelt--;
+ continue;
+ }
+ }
+ else
+ {
+ PROPSPEC pspec;
+
+ if (FAILED(sc = pc.Add(sstg.pwcsName)))
+ {
+ TaskMemFree(sstg.pwcsName);
+ break;
+ }
+
+ // Normal name, copy over prefix
+ memmove(sstg.pwcsName, sstg.pwcsName+1,
+ wcslen(sstg.pwcsName)*sizeof(WCHAR));
+ pelt->lpwstrName = sstg.pwcsName;
+ pelt->dispid = DISPID_UNKNOWN;
+ pspec.ulKind = PRSPEC_LPWSTR;
+ pspec.lpwstr = sstg.pwcsName;
+ sc = _pedf->GetSpecId(&pspec, &pelt->propid, TRUE);
+ if (FAILED(sc))
+ {
+ TaskMemFree(sstg.pwcsName);
+ break;
+ }
+ }
+ olAssert(sstg.cbSize.HighPart == 0);
+ pelt->cbSize = sstg.cbSize.LowPart;
+ pelt->vt = (VARTYPE)sstg.grfMode;
+ }
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+
+ // Can't move this down because dfnInitial isn't set for all EH_Err cases
+ if (FAILED(sc))
+ _dfnKey.Set(&dfnInitial);
+
+ olDebugOut((DEB_TRACE, "Out CExposedPropertyIter::Next => %lX\n", sc));
+EH_Err:
+ celtDone = pelt-rgelt;
+ if (FAILED(sc))
+ {
+ void *pv;
+
+ pc.StartEnum();
+ while (pc.Next(&pv))
+ TaskMemFree(pv);
+
+#ifndef WIN32
+ memset(rgelt, 0, (size_t)(sizeof(STATPROPSTG)*celt));
+#endif
+ }
+ else if (pceltFetched)
+ // Can fault but that's acceptable
+ *pceltFetched = celtDone;
+EH_RetSc:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropertyIter::Skip, public
+//
+// Synopsis: Skips N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+//
+// Returns: Appropriate status code
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedPropertyIter::Skip(ULONG celt)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In CExposedPropertyIter::Skip(%lu)\n", celt));
+
+ if (SUCCEEDED(sc = Validate()))
+ sc = hSkip(celt, TRUE);
+
+ olDebugOut((DEB_TRACE, "Out CExposedPropertyIter::Skip\n"));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropertyIter::Reset, public
+//
+// Synopsis: Rewinds the iterator
+//
+// Returns: Appropriate status code
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedPropertyIter::Reset(void)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In CExposedPropertyIter::Reset()\n"));
+
+ if (SUCCEEDED(sc = Validate()))
+ sc = hReset();
+
+ olDebugOut((DEB_TRACE, "Out CExposedPropertyIter::Reset\n"));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropertyIter::Clone, public
+//
+// Synopsis: Clones this iterator
+//
+// Arguments: [ppenm] - Clone return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedPropertyIter::Clone(IEnumSTATPROPSTG **ppenm)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ SafeCExposedPropertyIter pepi;
+
+ olDebugOut((DEB_TRACE, "In CExposedPropertyIter::Clone(%p)\n", ppenm));
+
+ olChk(ValidateOutPtrBuffer(ppenm));
+ *ppenm = NULL;
+ olChk(Validate());
+ olChk(_ppdf->CheckReverted());
+
+ olChk(TakeSafeSem());
+ SafeReadAccess();
+
+ pepi.Attach(new CExposedPropertyIter(_pedf, BP_TO_P(CPubDocFile *, _ppdf),
+ &_dfnKey,
+ BP_TO_P(CDFBasis *, _pdfb),
+ _ppc, TRUE));
+ olMem((CExposedPropertyIter *)pepi);
+ TRANSFER_INTERFACE(pepi, IEnumSTATPROPSTG, ppenm);
+ _ppc->AddRef();
+
+ olDebugOut((DEB_TRACE, "Out CExposedPropertyIter::Clone => %p\n",
+ *ppenm));
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropertyIter::Release, public
+//
+// Synopsis: Releases resources for the iterator
+//
+// Returns: Appropriate status code
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CExposedPropertyIter::Release(void)
+{
+ LONG lRet;
+
+ olDebugOut((DEB_TRACE, "In CExposedPropertyIter::Release()\n"));
+
+ if (FAILED(Validate()))
+ return 0;
+ if ((lRet = hRelease()) == 0)
+ delete this;
+
+ olDebugOut((DEB_TRACE, "Out CExposedPropertyIter::Release\n"));
+ return lRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropertyIter::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CExposedPropertyIter::AddRef(void)
+{
+ ULONG ulRet;
+
+ olDebugOut((DEB_TRACE, "In CExposedPropertyIter::AddRef()\n"));
+
+ if (FAILED(Validate()))
+ return 0;
+ ulRet = hAddRef();
+
+ olDebugOut((DEB_TRACE, "Out CExposedPropertyIter::AddRef\n"));
+ return ulRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropertyIter::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedPropertyIter::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE,
+ "In CExposedPropertyIter::QueryInterface(riid, %p)\n",
+ ppvObj));
+
+ if (SUCCEEDED(sc = Validate()))
+ sc = hQueryInterface(iid, IID_IEnumSTATPROPSTG, this, ppvObj);
+
+ olDebugOut((DEB_TRACE, "Out CExposedPropertyIter::QueryInterface => %p\n",
+ ppvObj));
+ return ResultFromScode(sc);
+}
diff --git a/private/ole32/stg/exp/exppiter.hxx b/private/ole32/stg/exp/exppiter.hxx
new file mode 100644
index 000000000..d75e37cf5
--- /dev/null
+++ b/private/ole32/stg/exp/exppiter.hxx
@@ -0,0 +1,92 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: exppiter.hxx
+//
+// Contents: Exposed property iterator header
+//
+// Classes: CExposedPropertyIter
+//
+// History: 21-Dec-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __EXPPITER_HXX__
+#define __EXPPITER_HXX__
+
+#include <dfmsp.hxx>
+#include <lock.hxx>
+#include <dfbasis.hxx>
+#include <peiter.hxx>
+
+class CDFBasis;
+interface CExposedDocFile;
+
+//+---------------------------------------------------------------------------
+//
+// Class: CExposedPropertyIter (epi)
+//
+// Purpose: Exposed portion of the property iterator
+//
+// Interface: See below
+//
+// History: 21-Dec-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+interface CExposedPropertyIter
+ : public IEnumSTATPROPSTG, public PExposedIterator
+{
+public:
+ CExposedPropertyIter(CExposedDocFile *pedf,
+ CPubDocFile *ppdf,
+ CDfName *pdfnKey,
+ CDFBasis *pdfb,
+ CPerContext *ppc,
+ BOOL fOwnContext);
+ ~CExposedPropertyIter(void);
+
+ // From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // New methods
+ STDMETHOD(Next)(ULONG celt, STATPROPSTG FAR *rgelt, ULONG *pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(IEnumSTATPROPSTG **ppenm);
+
+ inline SCODE Validate(void) const;
+
+private:
+ CExposedDocFile *_pedf;
+};
+
+SAFE_INTERFACE_PTR(SafeCExposedPropertyIter, CExposedPropertyIter);
+
+// DocFileIter signatures
+#define CEXPOSEDPROPERTYITER_SIG LONGSIG('E', 'P', 'R', 'I')
+#define CEXPOSEDPROPERTYITER_SIGDEL LONGSIG('E', 'p', 'R', 'i')
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropertyIter::Validate, public
+//
+// Synopsis: Validates the signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE if the signature doesn't match
+//
+// History: 12-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CExposedPropertyIter::Validate(void) const
+{
+ return (this == NULL || _sig != CEXPOSEDPROPERTYITER_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+#endif // #ifndef __EXPPITER_HXX__
diff --git a/private/ole32/stg/exp/expprop.cxx b/private/ole32/stg/exp/expprop.cxx
new file mode 100644
index 000000000..045203adf
--- /dev/null
+++ b/private/ole32/stg/exp/expprop.cxx
@@ -0,0 +1,1542 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: expprop.cxx
+//
+// Contents: Exposed property implementation
+//
+// History: 14-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <memalloc.h>
+#include <pbstream.hxx>
+#include "props.hxx"
+#include "expdf.hxx"
+#include "expst.hxx"
+#include "exppiter.hxx"
+#include "logfile.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Method: CExposedDocFile::ValidatePropSpecs, private
+//
+// Synopsis: Checks an array of PROPSPEC for validity
+//
+// Arguments: [cpspec] - Count
+// [rgpspec] - Specs
+//
+// Returns: Appropriate status code
+//
+// History: 11-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CExposedDocFile::ValidatePropSpecs(ULONG cpspec, PROPSPEC rgpspec[])
+{
+ ULONG i;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In ValidatePropSpecs(%lu, %p)\n",
+ cpspec, rgpspec));
+ olChk(ValidateBuffer(rgpspec, sizeof(PROPSPEC)*cpspec));
+ for (i = 0; i < cpspec; i++)
+ {
+ olChk(ValidatePropSpecKind(rgpspec[i].ulKind));
+ switch(rgpspec[i].ulKind)
+ {
+ case PRSPEC_LPWSTR:
+ olChk(CheckPropertyName(rgpspec[i].lpwstr));
+ break;
+
+ case PRSPEC_DISPID:
+ if (rgpspec[i].dispid < 0 || rgpspec[i].dispid > DISPID_MAX_FIXED)
+ {
+ olErr(EH_Err, STG_E_INVALIDNAME);
+ }
+ break;
+
+ case PRSPEC_PROPID:
+ break;
+
+ default:
+ olAssert(!aMsg("ValidatePropSpecs default hit"));
+ break;
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out ValidatePropSpecs\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::SpecToDfName, private
+//
+// Synopsis: Creates a CDfName for a PROPSPEC
+//
+// Returns: Appropriate status code
+//
+// Arguments: [ppspec] - Spec
+// [pdfn] - DfName
+//
+// History: 11-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CExposedDocFile::SpecToDfName(PROPSPEC *ppspec, CDfName *pdfn)
+{
+ olDebugOut((DEB_ITRACE, "In SpecToDfName(%p, %p)\n", ppspec, pdfn));
+ switch(ppspec->ulKind)
+ {
+ case PRSPEC_DISPID:
+ pdfn->IdName(ppspec->dispid);
+ break;
+
+ case PRSPEC_PROPID:
+ if (ppspec->propid >= INITIAL_PROPID)
+ {
+ LPWSTR lpwstr;
+
+ // Mapped name
+ lpwstr = _nim.NameFromId(ppspec->propid);
+ if (lpwstr == NULL)
+ return STG_E_FILENOTFOUND;
+ pdfn->PropName(lpwstr);
+ }
+ else
+ {
+ pdfn->IdName((DISPID)ppspec->propid);
+ }
+ break;
+
+ case PRSPEC_LPWSTR:
+ pdfn->PropName(ppspec->lpwstr);
+ break;
+
+ default:
+ olAssert(!aMsg("SpecToDfName default hit"));
+ break;
+ }
+ olDebugOut((DEB_ITRACE, "Out SpecToDfName\n"));
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::GetSpecId, public
+//
+// Synopsis: Gets the propid for a PROPSPEC
+//
+// Arguments: [ppspec] - PROPSPEC
+// [ppropid] - Propid return
+// [fAlloc] - Allocate new ids
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppropid]
+//
+// History: 12-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CExposedDocFile::GetSpecId(PROPSPEC *ppspec,
+ PROPID *ppropid,
+ BOOL fAlloc)
+{
+ SCODE sc = S_OK;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::GetSpecId:%p(%p, %p, %d)\n",
+ this, ppspec, ppropid, fAlloc));
+ switch(ppspec->ulKind)
+ {
+ case PRSPEC_DISPID:
+ *ppropid = (PROPID)ppspec->dispid;
+ break;
+
+ case PRSPEC_PROPID:
+ *ppropid = ppspec->propid;
+ break;
+
+ case PRSPEC_LPWSTR:
+ if ((*ppropid = _nim.IdFromName(ppspec->lpwstr)) == PROPID_UNKNOWN)
+ {
+ if (fAlloc)
+ {
+ *ppropid = _propid;
+ if (_nim.Add(ppspec->lpwstr, *ppropid) == NULL)
+ sc = STG_E_INSUFFICIENTMEMORY;
+ else
+ _propid++;
+ }
+ else
+ sc = STG_E_FILENOTFOUND;
+ }
+ break;
+
+ default:
+ olAssert(!aMsg("GetSpecId default hit"));
+ break;
+ }
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::GetSpecId\n"));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::BufferToPropValue, private
+//
+// Synopsis: Fills in a property value from a buffer
+//
+// Arguments: [ppb] - Buffer start in, buffer end out
+// [pdpv] - Property value
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppb]
+//
+// History: 14-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#define GET_SIMPLE_VAL(type) \
+ memcpy(&pdpv->iVal, pb, sizeof(type)); \
+ pb += sizeof(type)
+
+#define GET_SIMPLE_VECTOR(type) \
+ if (pdpv->cai.pElems = (short *)TaskMemAlloc(sizeof(type)*ulCnt)) \
+ { \
+ memcpy(pdpv->cai.pElems, pb, sizeof(type)*ulCnt); \
+ pb += sizeof(type)*ulCnt; \
+ } \
+ else \
+ { \
+ sc = STG_E_INSUFFICIENTMEMORY; \
+ }
+
+SCODE CExposedDocFile::BufferToPropValue(BYTE **ppb,
+ DFPROPVAL *pdpv)
+{
+ SCODE sc = S_OK;
+ ULONG i, ulCnt, cb;
+ BYTE *pb;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::BufferToPropValue:%p("
+ "%p, %p)\n", this, ppb, pdpv));
+
+ pb = *ppb;
+ if (pdpv->vt & VT_VECTOR)
+ {
+ ulCnt = *(ULONG UNALIGNED *)pb;
+ pb += sizeof(ULONG);
+ pdpv->cai.cElems = ulCnt;
+ }
+
+ switch(pdpv->vt)
+ {
+ case VT_EMPTY:
+ break;
+
+ case VT_I2:
+ GET_SIMPLE_VAL(short);
+ break;
+ case VT_I2 | VT_VECTOR:
+ GET_SIMPLE_VECTOR(short);
+ break;
+
+ case VT_I4:
+ GET_SIMPLE_VAL(long);
+ break;
+ case VT_I4 | VT_VECTOR:
+ GET_SIMPLE_VECTOR(long);
+ break;
+
+ case VT_R4:
+ GET_SIMPLE_VAL(float);
+ break;
+ case VT_R4 | VT_VECTOR:
+ GET_SIMPLE_VECTOR(float);
+ break;
+
+ case VT_R8:
+ GET_SIMPLE_VAL(double);
+ break;
+ case VT_R8 | VT_VECTOR:
+ GET_SIMPLE_VECTOR(double);
+ break;
+
+ case VT_CY:
+ GET_SIMPLE_VAL(CY);
+ break;
+ case VT_CY | VT_VECTOR:
+ GET_SIMPLE_VECTOR(CY);
+ break;
+
+ case VT_DATE:
+ GET_SIMPLE_VAL(DATE);
+ break;
+ case VT_DATE | VT_VECTOR:
+ GET_SIMPLE_VECTOR(DATE);
+ break;
+
+ case VT_BSTR:
+ pb += BSTR_LLEN;
+ ulCnt = BSTR_TLEN(pb);
+ olMem(pdpv->bstrVal = (BSTR)TaskMemAlloc(ulCnt));
+ memcpy(pdpv->bstrVal, BSTR_PTR(pb), ulCnt);
+ pdpv->bstrVal = (BSTR)((BYTE *)pdpv->bstrVal+BSTR_LLEN);
+ pb += ulCnt-BSTR_LLEN;
+ break;
+ case VT_BSTR | VT_VECTOR:
+ olMem(pdpv->cabstr.pElems =
+ (BSTR *)TaskMemAlloc(sizeof(BSTR)*ulCnt));
+ for (i = 0; i < ulCnt; i++)
+ {
+ pb += BSTR_LLEN;
+ cb = BSTR_TLEN(pb);
+ pdpv->cabstr.pElems[i] = (BSTR)TaskMemAlloc(cb);
+ if (pdpv->cabstr.pElems[i] == NULL)
+ break;
+ memcpy(pdpv->cabstr.pElems[i], BSTR_PTR(pb), cb);
+ pdpv->cabstr.pElems[i] =
+ (BSTR)((BYTE *)pdpv->cabstr.pElems[i]+BSTR_LLEN);
+ pb += cb-BSTR_LLEN;
+ }
+
+ if (i != ulCnt)
+ {
+ while (i > 0)
+ {
+ i--;
+ TaskMemFree(pdpv->cabstr.pElems[i]);
+ }
+ TaskMemFree(pdpv->cabstr.pElems);
+ sc = STG_E_INSUFFICIENTMEMORY;
+ }
+ break;
+#ifdef OLDPROPS
+ case VT_WBSTR:
+ pb += WBSTR_LLEN;
+ ulCnt = WBSTR_TLEN(pb);
+ pdpv->wbstrVal = (WBSTR)TaskMemAlloc(ulCnt);
+ memcpy(pdpv->wbstrVal, WBSTR_PTR(pb), ulCnt);
+ pdpv->wbstrVal = (WBSTR)((BYTE *)pdpv->wbstrVal+WBSTR_LLEN);
+ pb += ulCnt-WBSTR_LLEN;
+ break;
+ case VT_WBSTR | VT_VECTOR:
+ olMem(pdpv->cawbstr.pElems =
+ (WBSTR *)TaskMemAlloc(sizeof(WBSTR)*ulCnt));
+ for (i = 0; i < ulCnt; i++)
+ {
+ pb += WBSTR_LLEN;
+ cb = WBSTR_TLEN(pb);
+ pdpv->cawbstr.pElems[i] = (WBSTR)TaskMemAlloc(cb);
+ if (pdpv->cawbstr.pElems[i] == NULL)
+ break;
+ memcpy(pdpv->cawbstr.pElems[i], WBSTR_PTR(pb), cb);
+ pdpv->cawbstr.pElems[i] =
+ (WBSTR)((BYTE *)pdpv->cawbstr.pElems[i]+WBSTR_LLEN);
+ pb += cb-WBSTR_LLEN;
+ }
+
+ if (i != ulCnt)
+ {
+ while (i > 0)
+ {
+ i--;
+ TaskMemFree(pdpv->cawbstr.pElems[i]);
+ }
+ TaskMemFree(pdpv->cawbstr.pElems);
+ sc = STG_E_INSUFFICIENTMEMORY;
+ }
+ break;
+#endif
+ case VT_LPSTR:
+ ulCnt = strlen((char *)pb)+1;
+ olMem(pdpv->pszVal = (char *)TaskMemAlloc(ulCnt));
+ memcpy(pdpv->pszVal, pb, ulCnt);
+ pb += ulCnt;
+ break;
+ case VT_LPSTR | VT_VECTOR:
+ olMem(pdpv->calpstr.pElems =
+ (LPSTR *)TaskMemAlloc(sizeof(LPSTR)*ulCnt));
+ for (i = 0; i < ulCnt; i++)
+ {
+ cb = strlen((char *)pb)+1;
+ pdpv->calpstr.pElems[i] = (LPSTR)TaskMemAlloc(cb);
+ if (pdpv->calpstr.pElems[i] == NULL)
+ break;
+ memcpy(pdpv->calpstr.pElems[i], pb, cb);
+ pb += cb;
+ }
+
+ if (i != ulCnt)
+ {
+ while (i > 0)
+ {
+ i--;
+ TaskMemFree(pdpv->calpstr.pElems[i]);
+ }
+ TaskMemFree(pdpv->calpstr.pElems);
+ sc = STG_E_INSUFFICIENTMEMORY;
+ }
+ break;
+
+ case VT_BOOL:
+ GET_SIMPLE_VAL(VARIANT_BOOL);
+ break;
+ case VT_BOOL | VT_VECTOR:
+ GET_SIMPLE_VECTOR(VARIANT_BOOL);
+ break;
+
+ case VT_I8:
+ GET_SIMPLE_VAL(LARGE_INTEGER);
+ break;
+ case VT_I8 | VT_VECTOR:
+ GET_SIMPLE_VECTOR(LARGE_INTEGER);
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ ulCnt = *(ULONG UNALIGNED *)pb;
+ pb += sizeof(ULONG);
+ olMem(pdpv->blob.pBlobData = (BYTE *)TaskMemAlloc(ulCnt));
+ pdpv->blob.cbSize = ulCnt;
+ memcpy(pdpv->blob.pBlobData, pb, ulCnt);
+ pb += ulCnt;
+ break;
+
+ case VT_LPWSTR:
+ ulCnt = (wcslen((WCHAR *)pb)+1)*sizeof(WCHAR);
+ olMem(pdpv->pwszVal = (WCHAR *)TaskMemAlloc(ulCnt));
+ memcpy(pdpv->pwszVal, pb, ulCnt);
+ pb += ulCnt;
+ break;
+ case VT_LPWSTR | VT_VECTOR:
+ olMem(pdpv->calpwstr.pElems =
+ (LPWSTR *)TaskMemAlloc(sizeof(LPWSTR)*ulCnt));
+ for (i = 0; i < ulCnt; i++)
+ {
+ cb = (wcslen((WCHAR *)pb)+1)*sizeof(WCHAR);
+ pdpv->calpwstr.pElems[i] = (LPWSTR)TaskMemAlloc(cb);
+ if (pdpv->calpwstr.pElems[i] == NULL)
+ break;
+ memcpy(pdpv->calpwstr.pElems[i], pb, cb);
+ pb += cb;
+ }
+
+ if (i != ulCnt)
+ {
+ while (i > 0)
+ {
+ i--;
+ TaskMemFree(pdpv->calpwstr.pElems[i]);
+ }
+ TaskMemFree(pdpv->calpwstr.pElems);
+ sc = STG_E_INSUFFICIENTMEMORY;
+ }
+ break;
+
+ case VT_FILETIME:
+ GET_SIMPLE_VAL(FILETIME);
+ break;
+ case VT_FILETIME | VT_VECTOR:
+ GET_SIMPLE_VECTOR(FILETIME);
+ break;
+
+ case VT_UUID:
+ olMem(pdpv->puuid = (GUID *)TaskMemAlloc(sizeof(GUID)));
+ memcpy(pdpv->puuid, pb, sizeof(GUID));
+ pb += sizeof(GUID);
+ break;
+ case VT_UUID | VT_VECTOR:
+ GET_SIMPLE_VECTOR(GUID);
+ break;
+
+ case VT_VARIANT:
+ olMem(pdpv->pvarVal = (DFPROPVAL *)TaskMemAlloc(sizeof(DFPROPVAL)));
+ VariantInit(pdpv->pvarVal);
+ pdpv->pvarVal->vt = *(VARTYPE UNALIGNED *)pb;
+ pb += sizeof(VARTYPE);
+ if (FAILED(sc = BufferToPropValue(&pb, pdpv->pvarVal)))
+ {
+ TaskMemFree(pdpv->pvarVal);
+ }
+ break;
+ case VT_VARIANT | VT_VECTOR:
+ olMem(pdpv->cavar.pElems =
+ (DFPROPVAL *)TaskMemAlloc(sizeof(DFPROPVAL)*ulCnt));
+ for (i = 0; i < ulCnt; i++)
+ {
+ VariantInit(pdpv->cavar.pElems+i);
+ pdpv->cavar.pElems[i].vt = *(VARTYPE UNALIGNED *)pb;
+ pb += sizeof(VARTYPE);
+ if (FAILED(sc = BufferToPropValue(&pb, pdpv->cavar.pElems+i)))
+ {
+ if (i > 0)
+ olHVerSucc(FreeVariantArray(i, pdpv->cavar.pElems));
+ TaskMemFree(pdpv->cavar.pElems);
+ break;
+ }
+ }
+ break;
+
+ case VT_CF:
+ ulCnt = *(ULONG UNALIGNED *)pb;
+ pb += sizeof(ULONG);
+ olMem(pdpv->pClipData = (CLIPDATA *)TaskMemAlloc(sizeof(CLIPDATA)));
+ if (pdpv->pClipData->pClipData = (BYTE *)TaskMemAlloc(ulCnt))
+ {
+ pdpv->pClipData->cbSize = ulCnt+sizeof(ULONG);
+ pdpv->pClipData->ulClipFmt = *(ULONG UNALIGNED *)pb;
+ pb += sizeof(ULONG);
+ memcpy(pdpv->pClipData->pClipData, pb, ulCnt);
+ pb += ulCnt;
+ }
+ else
+ {
+ TaskMemFree(pdpv->pClipData);
+ sc = STG_E_INSUFFICIENTMEMORY;
+ }
+ break;
+
+ default:
+ olAssert(!aMsg("Unknown property type in BufferToPropValue"));
+ sc = STG_E_INVALIDFUNCTION;
+ break;
+ }
+
+ *ppb = pb;
+
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::BufferToPropValue\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::PropValueToBuffer, private
+//
+// Synopsis: Puts a property value into a buffer
+//
+// Arguments: [pdpv] - Property value
+// [pcb] - Size return
+// [pb] - Buffer to serialize into or NULL
+//
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcb]
+//
+// History: 14-Oct-92 DrewB Created
+//
+// Notes: Responsible for checking validity of data before use
+// If [pb] is NULL then only the size is computed
+//
+//----------------------------------------------------------------------------
+
+#define SET_SIMPLE_VAL(type) \
+ *pcb = sizeof(type); \
+ if (pb) \
+ memcpy(pb, &pdpv->iVal, sizeof(type))
+
+#define SET_SIMPLE_VECTOR(type) \
+ *pcb = sizeof(type)*pdpv->cai.cElems; \
+ if (pb) \
+ { \
+ olChk(ValidateBuffer(pdpv->cai.pElems, *pcb)); \
+ *(ULONG UNALIGNED *)pb = pdpv->cai.cElems; \
+ pb += sizeof(ULONG); \
+ memcpy(pb, pdpv->cai.pElems, *pcb); \
+ } \
+ *pcb += sizeof(ULONG)
+
+SCODE CExposedDocFile::PropValueToBuffer(DFPROPVAL *pdpv,
+ ULONG *pcb,
+ BYTE *pb)
+{
+ SCODE sc = S_OK;
+ char **plpstr, *pch;
+ BSTR *pbstr;
+#ifdef OLPROPS
+ WBSTR *pwbstr;
+#endif
+ WCHAR **plpwstr, *pwch;
+ ULONG i;
+ ULONG ulCnt = 0;
+ ULONG cbRecurse;
+ DFPROPVAL *pdpvA;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::PropValueToBuffer:%p("
+ "%p, %p, %p)\n", this, pdpv, pcb, pb));
+
+ olChk(ValidatePropType(pdpv->vt));
+
+ // Make zero-length arrays illegal
+ if ((pdpv->vt & VT_VECTOR) && pdpv->cai.cElems == 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+
+ switch(pdpv->vt)
+ {
+ case VT_EMPTY:
+ *pcb = 0;
+ break;
+
+ case VT_I2:
+ SET_SIMPLE_VAL(short);
+ break;
+ case VT_I2 | VT_VECTOR:
+ SET_SIMPLE_VECTOR(short);
+ break;
+
+ case VT_I4:
+ SET_SIMPLE_VAL(long);
+ break;
+ case VT_I4 | VT_VECTOR:
+ SET_SIMPLE_VECTOR(long);
+ break;
+
+ case VT_R4:
+ SET_SIMPLE_VAL(float);
+ break;
+ case VT_R4 | VT_VECTOR:
+ SET_SIMPLE_VECTOR(float);
+ break;
+
+ case VT_R8:
+ SET_SIMPLE_VAL(double);
+ break;
+ case VT_R8 | VT_VECTOR:
+ SET_SIMPLE_VECTOR(double);
+ break;
+
+ case VT_CY:
+ SET_SIMPLE_VAL(CY);
+ break;
+ case VT_CY | VT_VECTOR:
+ SET_SIMPLE_VECTOR(CY);
+ break;
+
+ case VT_DATE:
+ SET_SIMPLE_VAL(DATE);
+ break;
+ case VT_DATE | VT_VECTOR:
+ SET_SIMPLE_VECTOR(DATE);
+ break;
+
+ case VT_BSTR:
+ olChk(ValidateBuffer(BSTR_PTR(pdpv->bstrVal), BSTR_LLEN));
+ *pcb = BSTR_TLEN(pdpv->bstrVal);
+ if (pb)
+ {
+ olChk(ValidateBuffer(BSTR_PTR(pdpv->bstrVal), *pcb));
+ memcpy(pb, BSTR_PTR(pdpv->bstrVal), *pcb);
+ }
+ break;
+ case VT_BSTR | VT_VECTOR:
+ ulCnt = pdpv->cabstr.cElems;
+ *pcb = sizeof(ULONG);
+ pbstr = pdpv->cabstr.pElems;
+ olChk(ValidateBuffer(pbstr, ulCnt*sizeof(BSTR)));
+ for (i = 0; i < ulCnt; i++)
+ {
+ ULONG cb;
+
+ olChk(ValidateBuffer(BSTR_PTR(*pbstr), BSTR_LLEN));
+ cb = BSTR_TLEN(*pbstr);
+ *pcb += cb;
+ pbstr++;
+ }
+ if (pb)
+ {
+ *(ULONG UNALIGNED *)pb = ulCnt;
+ pb += sizeof(ULONG);
+ pbstr = pdpv->cabstr.pElems;
+ for (i = 0; i < ulCnt; i++)
+ {
+ olChk(ValidateBuffer(*pbstr, BSTR_BLEN(*pbstr)));
+ memcpy(pb, BSTR_PTR(*pbstr), BSTR_TLEN(*pbstr));
+ pb += BSTR_TLEN(*pbstr);
+ pbstr++;
+ }
+ }
+ break;
+#ifdef OLDPROPS
+ case VT_WBSTR:
+ olChk(ValidateBuffer(WBSTR_PTR(pdpv->wbstrVal), WBSTR_LLEN));
+ *pcb = WBSTR_TLEN(pdpv->wbstrVal);
+ if (pb)
+ {
+ olChk(ValidateBuffer(WBSTR_PTR(pdpv->wbstrVal), *pcb));
+ memcpy(pb, WBSTR_PTR(pdpv->wbstrVal), *pcb);
+ }
+ break;
+ case VT_WBSTR | VT_VECTOR:
+ ulCnt = pdpv->cawbstr.cElems;
+ *pcb = sizeof(ULONG);
+ pwbstr = pdpv->cawbstr.pElems;
+ olChk(ValidateBuffer(pwbstr, ulCnt*sizeof(WBSTR)));
+ for (i = 0; i < ulCnt; i++)
+ {
+ ULONG cb;
+
+ olChk(ValidateBuffer(WBSTR_PTR(*pwbstr), WBSTR_LLEN));
+ cb = WBSTR_TLEN(*pwbstr);
+ *pcb += cb;
+ pwbstr++;
+ }
+ if (pb)
+ {
+ *(ULONG UNALIGNED *)pb = ulCnt;
+ pb += sizeof(ULONG);
+ pwbstr = pdpv->cawbstr.pElems;
+ for (i = 0; i < ulCnt; i++)
+ {
+ olChk(ValidateBuffer(*pwbstr, WBSTR_BLEN(*pwbstr)));
+ memcpy(pb, WBSTR_PTR(*pwbstr), WBSTR_TLEN(*pwbstr));
+ pb += WBSTR_TLEN(*pwbstr);
+ pwbstr++;
+ }
+ }
+ break;
+#endif
+ case VT_LPSTR:
+ olChk(ValidateSz(pdpv->pszVal, 0xffffffff));
+ *pcb = strlen(pdpv->pszVal)+1;
+ if (pb)
+ memcpy(pb, pdpv->pszVal, *pcb);
+ break;
+ case VT_LPSTR | VT_VECTOR:
+ ulCnt = pdpv->calpstr.cElems;
+ *pcb = sizeof(ULONG);
+ plpstr = pdpv->calpstr.pElems;
+ olChk(ValidateBuffer(plpstr, ulCnt*sizeof(LPSTR)));
+ for (i = 0; i < ulCnt; i++)
+ {
+ ULONG cb;
+
+ olChk(ValidateSz(*plpstr, 0xffffffff));
+ cb = strlen(*plpstr)+1;
+ *pcb += cb;
+ plpstr++;
+ }
+ if (pb)
+ {
+ *(ULONG UNALIGNED *)pb = ulCnt;
+ pb += sizeof(ULONG);
+ pch = (char *)pb;
+ plpstr = pdpv->calpstr.pElems;
+ for (i = 0; i < ulCnt; i++)
+ {
+ strcpy(pch, *plpstr);
+ pch += strlen(*plpstr)+1;
+ plpstr++;
+ }
+ }
+ break;
+
+ case VT_BOOL:
+ SET_SIMPLE_VAL(VARIANT_BOOL);
+ break;
+ case VT_BOOL | VT_VECTOR:
+ SET_SIMPLE_VECTOR(VARIANT_BOOL);
+ break;
+
+ case VT_I8:
+ SET_SIMPLE_VAL(LARGE_INTEGER);
+ break;
+ case VT_I8 | VT_VECTOR:
+ SET_SIMPLE_VECTOR(LARGE_INTEGER);
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ *pcb = pdpv->blob.cbSize+sizeof(ULONG);
+ if (pb)
+ {
+ *(ULONG UNALIGNED *)pb = pdpv->blob.cbSize;
+ pb += sizeof(ULONG);
+ memcpy(pb, pdpv->blob.pBlobData, pdpv->blob.cbSize);
+ }
+ break;
+
+ case VT_LPWSTR:
+ olChk(ValidateWcs(pdpv->pwszVal, 0xffffffff));
+ *pcb = (wcslen(pdpv->pwszVal)+1)*sizeof(WCHAR);
+ if (pb)
+ memcpy(pb, pdpv->pwszVal, *pcb);
+ break;
+ case VT_LPWSTR | VT_VECTOR:
+ ulCnt = pdpv->calpwstr.cElems;
+ *pcb = sizeof(ULONG);
+ plpwstr = pdpv->calpwstr.pElems;
+ olChk(ValidateBuffer(plpwstr, ulCnt*sizeof(LPWSTR)));
+ for (i = 0; i < ulCnt; i++)
+ {
+ ULONG cb;
+
+ olChk(ValidateWcs(*plpwstr, 0xffffffff));
+ cb = (wcslen(*plpwstr)+1)*sizeof(WCHAR);
+ *pcb += cb;
+ plpwstr++;
+ }
+ if (pb)
+ {
+ *(ULONG UNALIGNED *)pb = ulCnt;
+ pb += sizeof(ULONG);
+ pwch = (WCHAR *)pb;
+ plpwstr = pdpv->calpwstr.pElems;
+ for (i = 0; i < ulCnt; i++)
+ {
+ wcscpy(pwch, *plpwstr);
+ pwch += wcslen(*plpwstr)+1;
+ plpwstr++;
+ }
+ }
+ break;
+
+ case VT_FILETIME:
+ SET_SIMPLE_VAL(FILETIME);
+ break;
+ case VT_FILETIME | VT_VECTOR:
+ SET_SIMPLE_VECTOR(FILETIME);
+ break;
+
+ case VT_UUID:
+ *pcb = sizeof(GUID);
+ if (pb)
+ {
+ olChk(ValidateBuffer(pdpv->puuid, sizeof(GUID)));
+ memcpy(pb, pdpv->puuid, sizeof(GUID));
+ }
+ break;
+ case VT_UUID | VT_VECTOR:
+ SET_SIMPLE_VECTOR(GUID);
+ break;
+
+ case VT_VARIANT:
+ olChk(ValidateBuffer(pdpv->pvarVal, sizeof(DFPROPVAL)));
+ if (pb)
+ {
+ *(VARTYPE UNALIGNED *)pb = pdpv->pvarVal->vt;
+ pb += sizeof(VARTYPE);
+ }
+ olChk(PropValueToBuffer(pdpv->pvarVal, &cbRecurse, pb));
+ *pcb = sizeof(VARTYPE)+cbRecurse;
+ break;
+ case VT_VARIANT | VT_VECTOR:
+ ulCnt = pdpv->cavar.cElems;
+ *pcb = sizeof(ULONG);
+ pdpvA = pdpv->cavar.pElems;
+ olChk(ValidateBuffer(pdpvA, ulCnt*sizeof(DFPROPVAL)));
+ if (pb)
+ {
+ *(ULONG UNALIGNED *)pb = ulCnt;
+ pb += sizeof(ULONG);
+ }
+ for (i = 0; i<ulCnt; i++)
+ {
+ if (pb)
+ {
+ *(VARTYPE UNALIGNED *)pb = pdpvA->vt;
+ pb += sizeof(VARTYPE);
+ }
+ olChk(PropValueToBuffer(pdpvA, &cbRecurse, pb));
+ *pcb += sizeof(VARTYPE)+cbRecurse;
+ if (pb)
+ pb += cbRecurse;
+ pdpvA++;
+ }
+ break;
+
+ case VT_CF:
+ olChk(ValidateBuffer(pdpv->pClipData, sizeof(CLIPDATA)));
+ *pcb = pdpv->pClipData->cbSize+sizeof(ULONG);
+ if (pb)
+ {
+ olChk(ValidateBuffer(pdpv->pClipData->pClipData,
+ pdpv->pClipData->cbSize-sizeof(ULONG)));
+ *(ULONG UNALIGNED *)pb = pdpv->pClipData->cbSize-sizeof(ULONG);
+ pb += sizeof(ULONG);
+ *(ULONG UNALIGNED *)pb = pdpv->pClipData->ulClipFmt;
+ pb += sizeof(ULONG);
+ memcpy(pb, pdpv->pClipData->pClipData,
+ pdpv->pClipData->cbSize-sizeof(ULONG));
+ }
+ break;
+
+ default:
+ olAssert(!aMsg("Unknown property type in PropValueToBuffer"));
+ sc = STG_E_INVALIDFUNCTION;
+ break;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::PropValueToBuffer\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::CreateProp, private
+//
+// Synopsis: Creates a property entry
+//
+// Arguments: [pdfn] - Name
+// [grfMode] - Access mode
+// [dpt] - Property type
+// [riid] - Type of desired object
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 12-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CExposedDocFile::CreateProp(CDfName const *pdfn,
+ DWORD grfMode,
+ DFPROPTYPE dpt,
+ REFIID riid,
+ void **ppv)
+{
+ SCODE sc;
+ CExposedDocFile *pedf;
+ CExposedStream *pest;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::CreateProp:%p("
+ "%p, %lX, %X, riid, %p)\n", this, pdfn, grfMode,
+ dpt, ppv));
+ if (IsEqualIID(riid, IID_IStorage))
+ {
+ olChk(CreateEntry(pdfn, STGTY_STORAGE | STGTY_PROPFLAG,
+ grfMode, (void **)&pedf));
+ olChkTo(EH_pedf,
+ pedf->GetPub()->SetPropType(dpt));
+ olChkTo(EH_pedf, pedf->GetPub()->Commit(0));
+ *ppv = pedf;
+ }
+ else if (IsEqualIID(riid, IID_IStream))
+ {
+ olChk(CreateEntry(pdfn, STGTY_STREAM | STGTY_PROPFLAG,
+ grfMode, (void **)&pest));
+ olChkTo(EH_pest,
+ pest->GetPub()->SetPropType(dpt));
+ *ppv = pest;
+ }
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::CreateProp\n"));
+ EH_Err:
+ return sc;
+
+ EH_pedf:
+ pedf->Release();
+ olVerSucc(_pdf->DestroyEntry(pdfn, TRUE));
+ goto EH_Err;
+
+ EH_pest:
+ pest->Release();
+ olVerSucc(_pdf->DestroyEntry(pdfn, TRUE));
+ goto EH_Err;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::OpenProp, private
+//
+// Synopsis: Opens a property entry
+//
+// Arguments: [pdfn] - Name
+// [grfMode] - Access mode
+// [dpt] - Property type
+// [riid] - Type of desired object
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 12-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CExposedDocFile::OpenProp(CDfName const *pdfn,
+ DWORD grfMode,
+ DFPROPTYPE dpt,
+ REFIID riid,
+ void **ppv)
+{
+ SCODE sc;
+ CExposedDocFile *pedf;
+ CExposedStream *pest;
+ DFPROPTYPE dptEnt;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::OpenProp:%p("
+ "%p, %lX, %X, riid, %p)\n", this, pdfn, grfMode,
+ dpt, ppv));
+ if (IsEqualIID(riid, IID_IStorage))
+ {
+ olChk(OpenEntry(pdfn, STGTY_STORAGE | STGTY_PROPFLAG,
+ grfMode, (void **)&pedf));
+ olChkTo(EH_pedf, pedf->GetPub()->GetPropType(&dptEnt));
+ if (dptEnt != dpt)
+ olErr(EH_pedf, STG_E_FILENOTFOUND);
+ *ppv = pedf;
+ }
+ else if (IsEqualIID(riid, IID_IStream))
+ {
+ olChk(OpenEntry(pdfn, STGTY_STREAM | STGTY_PROPFLAG,
+ grfMode, (void **)&pest));
+ olChkTo(EH_pest, pest->GetPub()->GetPropType(&dptEnt));
+ if (dptEnt != dpt)
+ olErr(EH_pest, STG_E_FILENOTFOUND);
+ *ppv = pest;
+ }
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::OpenProp\n"));
+ EH_Err:
+ return sc;
+
+ EH_pedf:
+ pedf->Release();
+ goto EH_Err;
+
+ EH_pest:
+ pest->Release();
+ goto EH_Err;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::ReadMultiple, public
+//
+// Synopsis: Gets property values
+//
+// Arguments: [cpspec] - Count of properties
+// [rgpspec] - Property names
+// [pftmModified] - Modify time or NULL
+// [rgpropid] - Id return or NULL
+// [rgdpv] - Value array to fill in
+//
+// Returns: Appropriate status code
+//
+// Modifies: [rgpropid]
+//
+// History: 13-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::ReadMultiple(ULONG cpspec,
+ PROPSPEC rgpspec[],
+ FILETIME *pftmModified,
+ PROPID rgpropid[],
+ DFPROPVAL rgdpv[])
+{
+ SCODE sc = S_OK;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ ULONG cb;
+ CDfName dfn;
+ DFPROPVAL *pdpv;
+ DWORD grfMode;
+ ULONG i;
+ BYTE *pb;
+
+ olLog(("%p::In CExposedDocFile::ReadMultiple(%lu, %p, %p, %p, %p)\n",
+ this, cpspec, rgpspec, pftmModified, rgpropid, rgdpv));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::ReadMultiple:%p("
+ "%lu, %p, %p, %p, %p)\n", this, cpspec, rgpspec,
+ pftmModified, rgpropid, rgdpv));
+
+ if (pftmModified)
+ {
+ olChk(ValidateOutBuffer(pftmModified, sizeof(FILETIME)));
+ memset(pftmModified, 0, sizeof(FILETIME));
+ }
+ if (rgpropid)
+ {
+ olChk(ValidateOutBuffer(rgpropid, sizeof(PROPID)*cpspec));
+ memset(rgpropid, 0, sizeof(PROPID)*cpspec);
+ }
+ olChk(ValidateOutBuffer(rgdpv, sizeof(DFPROPVAL)*cpspec));
+ for (i = 0; i < cpspec; i++)
+ {
+ // BUGBUG - VariantClear doesn't handle all of the supported
+ // property types
+ // olChk(VariantClear(&rgdpv[i]));
+ VariantInit(&rgdpv[i]);
+ }
+ olChk(ValidatePropSpecs(cpspec, rgpspec));
+ olChk(Validate());
+ olChk(_pdf->CheckReverted());
+
+ olChk(TakeSafeSem());
+ SafeReadAccess();
+
+ if (pftmModified)
+ {
+ FILETIME ft;
+
+ // Retrieve modification time
+ olChk(_pdf->GetDF()->GetTime(WT_MODIFICATION, &ft));
+ *pftmModified = ft;
+ }
+
+ // Compute child activation mode from propset mode
+ grfMode = (DFlagsToMode(_pdf->GetDFlags()) &
+ (STGM_READ | STGM_WRITE | STGM_READWRITE |
+ STGM_TRANSACTED)) | STGM_SHARE_EXCLUSIVE;
+
+ pdpv = rgdpv;
+
+ for (i = 0; i < cpspec; i++)
+ {
+ // The docfile can't take advantage of this optimization
+ // so just skip indeterminate requests
+ if (rgpspec[i].ulKind == PRSPEC_PROPID &&
+ rgpspec[i].propid == PROPID_UNKNOWN)
+ {
+ if (rgpropid)
+ rgpropid[i] = PROPID_UNKNOWN;
+ pdpv++;
+ continue;
+ }
+
+ olChkTo(EH_Next, SpecToDfName(&rgpspec[i], &dfn));
+ olChkTo(EH_Next, _sp.Get(&dfn, pdpv, &cb, &pb));
+
+ switch(pdpv->vt)
+ {
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ olChkTo(EH_Next,
+ OpenProp(&dfn, grfMode & ~STGM_TRANSACTED, pdpv->vt,
+ IID_IStream, (void **)&pdpv->pIStream));
+ break;
+
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ olChkTo(EH_Next,
+ OpenProp(&dfn, grfMode, pdpv->vt, IID_IStorage,
+ (void **)&pdpv->pIStorage));
+ break;
+
+ default:
+ if (pb != NULL)
+ {
+ BYTE *pbTmp = pb;
+
+ sc = BufferToPropValue(&pbTmp, pdpv);
+ TaskMemFree(pb);
+ olChkTo(EH_Next, sc);
+ }
+ break;
+ }
+
+ if (rgpropid)
+ sc = GetSpecId(&rgpspec[i], &rgpropid[i], TRUE);
+
+ EH_Next:
+ if (FAILED(sc))
+ {
+ if (sc == STG_E_FILENOTFOUND)
+ {
+ pdpv->vt = VT_ILLEGAL;
+ if (rgpropid)
+ rgpropid[i] = PROPID_UNKNOWN;
+ }
+ else
+ olErr(EH_Clear, sc);
+ }
+
+ pdpv++;
+ }
+
+ sc = S_OK;
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::ReadMultiple\n"));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::ReadMultiple(). sc == %lX\n",
+ this, sc));
+ return ResultFromScode(sc);
+
+ EH_Clear:
+ if (i > 0)
+ olHVerSucc(FreeVariantArray(i, rgdpv));
+ if (rgpropid)
+ memset(rgpropid, 0, sizeof(PROPID)*cpspec);
+ goto EH_Err;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::WriteMultiple, public
+//
+// Synopsis: Sets property values
+//
+// Arguments: [cpspec] - Count of properties
+// [rgpspec] - Property names
+// [rgpropid] - Property id return
+// [rgdpv] - Value array
+//
+// Returns: Appropriate status code
+//
+// Modifies: [rgpropid]
+//
+// History: 13-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::WriteMultiple(ULONG cpspec,
+ PROPSPEC rgpspec[],
+ PROPID rgpropid[],
+ DFPROPVAL rgdpv[])
+{
+ SCODE sc = S_OK;
+ CDfName dfn;
+ SAFE_SEM;
+ ULONG cb;
+ BYTE *pb;
+ ULONG i;
+ DFPROPVAL *pdpv;
+
+ olLog(("%p::In CExposedDocFile::WriteMultiple(%lu, %p, %p, %p)\n",
+ this, cpspec, rgpspec, rgpropid, rgdpv));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::WriteMultiple:%p("
+ "%lu, %p, %p, %p)\n", this, cpspec, rgpspec, rgpropid, rgdpv));
+
+ olChk(ValidatePropSpecs(cpspec, rgpspec));
+ if (rgpropid)
+ {
+ olChk(ValidateBuffer(rgpropid, sizeof(PROPID)*cpspec));
+ memset(rgpropid, 0, sizeof(PROPID)*cpspec);
+ }
+ olChk(ValidateBuffer(rgdpv, sizeof(DFPROPVAL)*cpspec));
+ olChk(Validate());
+ olChk(_pdf->CheckReverted());
+
+ olChk(TakeSafeSem());
+ SetWriteAccess();
+ pdpv = rgdpv;
+
+ for (i = 0; i < cpspec; i++)
+ {
+ olChkTo(EH_Clear, SpecToDfName(&rgpspec[i], &dfn));
+ switch(pdpv->vt)
+ {
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ CExposedStream *pest;
+ ULARGE_INTEGER cbCopy;
+ LARGE_INTEGER liZero;
+
+ olChkTo(EH_Clear,
+ ValidateInterface(pdpv->pIStream, IID_IStream));
+ olChkTo(EH_Clear,
+ CreateProp(&dfn, STGM_WRITE | STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE, pdpv->vt,
+ IID_IStream, (void **)&pest));
+ ULISet32(cbCopy, 0xffffffff);
+ ClearWriteAccess();
+ LISet32(liZero, 0);
+ sc = pdpv->pIStream->Seek(liZero, STREAM_SEEK_SET, NULL);
+ if (SUCCEEDED(sc))
+ sc = pdpv->pIStream->CopyTo(pest, cbCopy, NULL, NULL);
+ pest->Release();
+ olChkTo(EH_Clear, sc);
+ SetWriteAccess();
+ break;
+
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ CExposedDocFile *pedf;
+
+ olChkTo(EH_Clear, ValidateInterface(pdpv->pIStorage,
+ IID_IStorage));
+ olChkTo(EH_Clear,
+ CreateProp(&dfn, STGM_WRITE | STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE, pdpv->vt,
+ IID_IStorage, (void **)&pedf));
+ ClearWriteAccess();
+ sc = pdpv->pIStorage->CopyTo(0, NULL, NULL, pedf);
+ pedf->Release();
+ olChkTo(EH_Clear, sc);
+ SetWriteAccess();
+ break;
+
+ default:
+ olChkTo(EH_Clear, PropValueToBuffer(pdpv, &cb, NULL));
+ if (cb > 0)
+ {
+ olMemTo(EH_Clear, pb = (BYTE *)TaskMemAlloc(cb));
+ olChkTo(EH_pb, PropValueToBuffer(pdpv, &cb, pb));
+ }
+ else
+ pb = NULL;
+ sc = _sp.Set(&dfn, pdpv, cb, pb);
+ if (pb)
+ TaskMemFree(pb);
+ olChkTo(EH_Clear, sc);
+ break;
+ }
+
+ if (rgpropid)
+ olChkTo(EH_Clear, GetSpecId(&rgpspec[i], &rgpropid[i], TRUE));
+
+ pdpv++;
+ }
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::WriteMultiple\n"));
+ EH_Err:
+ ClearWriteAccess();
+ olLog(("%p::Out CExposedDocFile::WriteMultiple(). sc == %lX\n",
+ this, sc));
+ return ResultFromScode(sc);
+
+ EH_pb:
+ TaskMemFree(pb);
+ EH_Clear:
+ if (rgpropid)
+ memset(rgpropid, 0, sizeof(PROPID)*cpspec);
+ goto EH_Err;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::GetIDsOfNames, public
+//
+// Synopsis: Maps property names to ids
+//
+// Arguments: [clpwstr] - Count of names
+// [rglpwstr] - Names
+// [rgpropid] - Id return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [rgpropid]
+//
+// History: 12-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef GET_IDS_OF_NAMES
+SCODE CExposedDocFile::GetIDsOfNames(ULONG clpwstr,
+ LPWSTR rglpwstr[],
+ PROPID rgpropid[])
+{
+ ULONG i;
+ SCODE sc, scSem = STG_E_INUSE, scSingle;
+ CDfName dfn;
+
+ olLog(("%p::In CExposedDocFile::GetIDsOfNames(%lu, %p, %p)\n",
+ this, clpwstr, rglpwstr, rgpropid));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::GetIDsOfNames:%p("
+ "%lu, %p, %p)\n", this, clpwstr, rglpwstr, rgpropid));
+ TRY
+ {
+ olChk(ValidateBuffer(rglpwstr, sizeof(WCHAR *)*clpwstr));
+ for (i = 0; i < clpwstr; i++)
+ olChk(CheckPropertyName(rglpwstr[i]));
+ olChk(ValidateOutBuffer(rgpropid, sizeof(PROPID)*clpwstr));
+ memset(rgpropid, 0, sizeof(PROPID)*clpwstr);
+ olChk(Validate());
+
+ PROPSPEC pspec;
+
+ olChk(scSem = SetReadAccess());
+ pspec.fPropid = FALSE;
+ sc = S_OK;
+ for (i = 0; i < clpwstr; i++)
+ {
+ pspec.lpwstrName = rglpwstr[i];
+
+ // Can't fail for names
+ olVerSucc(SpecToDfName(&pspec, &dfn));
+
+ // Does any such property exist?
+ scSingle = _sp.Exists(&dfn);
+ if (scSingle == STG_E_FILENOTFOUND)
+ rgpropid[i] = PROPID_UNKNOWN;
+ else if (FAILED(sc))
+ sc = scSingle;
+ else
+ {
+ // It exists, so there's either a mapping for it or
+ // we should make one
+ scSingle = GetSpecId(&pspec, &rgpropid[i], TRUE);
+ if (FAILED(scSingle))
+ sc = scSingle;
+ }
+ }
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::GetIDsOfNames\n"));
+ EH_Err:
+ ClearReadAccess(scSem);
+ olLog(("%p::Out CExposedDocFile::GetIDsOfNames(). sc == %lX\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::DeleteMultiple, public
+//
+// Synopsis: Deletes properties
+//
+// Arguments: [cpspec] - Count of names
+// [rgpspec] - Names
+//
+// Returns: Appropriate status code
+//
+// History: 13-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::DeleteMultiple(ULONG cpspec,
+ PROPSPEC rgpspec[])
+{
+ SCODE scFinal = S_OK, sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ CDfName dfn;
+ ULONG i;
+
+ olLog(("%p::In CExposedDocFile::DeleteMultiple(%lu, %p)\n",
+ this, cpspec, rgpspec));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::DeleteMultiple:%p("
+ "%lu, %p)\n", this, cpspec, rgpspec));
+
+ olChk(ValidatePropSpecs(cpspec, rgpspec));
+ olChk(Validate());
+ olChk(_pdf->CheckReverted());
+
+ olChk(TakeSafeSem());
+ SafeWriteAccess();
+
+ for (i = 0; i < cpspec; i++)
+ {
+ sc = SpecToDfName(&rgpspec[i], &dfn);
+ if (SUCCEEDED(sc))
+ sc = _pdf->DestroyEntry(&dfn, FALSE);
+ if (FAILED(sc) && sc != STG_E_FILENOTFOUND)
+ scFinal = sc;
+ }
+ sc = scFinal;
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::DeleteMultiple\n"));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::DeleteMultiple(). sc == %lX\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::Enum, public
+//
+// Synopsis: Create a property enumerator
+//
+// Arguments: [ppenm] - Enumerator return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 17-Dec-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::Enum(IEnumSTATPROPSTG **ppenm)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ SafeCExposedPropertyIter pepi;
+ CDfName dfnTmp;
+
+ olLog(("%p::In CExposedDocFile::Enum(%p)\n", this, ppenm));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::Enum:%p(%p)\n",
+ this, ppenm));
+
+ olChk(ValidateOutPtrBuffer(ppenm));
+ *ppenm = NULL;
+ olChk(Validate());
+ olChk(_pdf->CheckReverted());
+
+ olChk(TakeSafeSem());
+ SafeReadAccess();
+
+ pepi.Attach(new CExposedPropertyIter(this, BP_TO_P(CPubDocFile *, _pdf),
+ &dfnTmp, BP_TO_P(CDFBasis *, _pdfb),
+ _ppc, FALSE));
+ olMem((CExposedPropertyIter *)pepi);
+ TRANSFER_INTERFACE(pepi, IEnumSTATPROPSTG, ppenm);
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::Enum\n"));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::Enum(). sc == %lX\n", this, sc));
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::Stat, public
+//
+// Synopsis: Returns information about this property set
+//
+// Arguments: [pstat] - Stat structure to fill in
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstat]
+//
+// History: 30-Nov-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::Stat(STATPROPSETSTG *pstat)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ FILETIME ft;
+ CDfName *pdfn;
+
+ olLog(("%p::In CExposedDocFile::Stat(%p)\n",
+ this, pstat));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::Stat:%p(%p)\n",
+ this, pstat));
+
+ olChk(ValidateBuffer(pstat, sizeof(STATPROPSETSTG)));
+ memset(pstat, 0, sizeof(STATPROPSETSTG));
+ olChk(Validate());
+ olChk(_pdf->CheckReverted());
+
+ olChk(TakeSafeSem());
+ SafeReadAccess();
+
+ pdfn = _pdf->GetName();
+ olAssert(pdfn->GetLength() == CBPROPSETNAME);
+ memcpy(&pstat->iid, pdfn->GetBuffer()+2*sizeof(WCHAR), sizeof(IID));
+ olChk(_pdf->GetDF()->GetTime(WT_CREATION, &ft));
+ pstat->ctime = ft;
+ olChk(_pdf->GetDF()->GetTime(WT_MODIFICATION, &ft));
+ pstat->mtime = ft;
+ olChk(_pdf->GetDF()->GetTime(WT_ACCESS, &ft));
+ pstat->atime = ft;
+
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::Stat\n"));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::Stat(). sc == %lX\n", this, sc));
+ return sc;
+}
diff --git a/private/ole32/stg/exp/exppset.cxx b/private/ole32/stg/exp/exppset.cxx
new file mode 100644
index 000000000..c134a8bff
--- /dev/null
+++ b/private/ole32/stg/exp/exppset.cxx
@@ -0,0 +1,233 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: exppset.cxx
+//
+// Contents: IPropertySetStorage implementation
+//
+// History: 11-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include "exppsi.hxx"
+#include "expdf.hxx"
+#include "expst.hxx"
+#include "logfile.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::Create, public
+//
+// Synopsis: Creates a property set
+//
+// Arguments: [riid] - Name
+// [grfMode] - Access mode
+// [ppprstg] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppprstg]
+//
+// History: 17-Dec-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::Create(REFIID riid,
+ DWORD grfMode,
+ IPropertyStorage **ppprstg)
+{
+ SCODE sc;
+ SAFE_SEM;
+ CDfName dfn;
+ SafeIStorage pstg;
+
+ olLog(("%p::In CExposedDocFile::Create(riid, 0x%lX, %p)\n",
+ this, grfMode, ppprstg));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::Create:%p("
+ "riid, %lX, %p)\n", this, grfMode, ppprstg));
+
+ olChk(ValidateOutPtrBuffer(ppprstg));
+ *ppprstg = NULL;
+ olChk(ValidateBuffer(&riid, sizeof(IID)));
+ olChk(Validate());
+ olChk(VerifyPerms(grfMode));
+ if ((grfMode & (STGM_PRIORITY | STGM_DELETEONRELEASE |
+ STGM_CONVERT)))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+
+ dfn.IidName(riid);
+
+ olChk(TakeSafeSem());
+
+ SetWriteAccess();
+ sc = CreateEntry(&dfn, STGTY_STORAGE | STGTY_PROPFLAG,
+ grfMode, (void **)&pstg);
+ ClearWriteAccess();
+ if (SUCCEEDED(sc))
+ {
+ sc = pstg->QueryInterface(IID_IPropertyStorage, (void **)ppprstg);
+ if (FAILED(sc))
+ {
+ pstg.Set(NULL);
+ SetWriteAccess();
+ olVerSucc(_pdf->DestroyEntry(&dfn, TRUE));
+ ClearWriteAccess();
+ }
+ }
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::Create\n"));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::Create(). *ppprstg == %p, sc == %lX\n",
+ this, *ppprstg, sc));
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::Open, public
+//
+// Synopsis: Opens a property set
+//
+// Arguments: [riid] - Name
+// [grfMode] - Access mode
+// [ppprstg] - Interface pointer return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppprstg]
+//
+// History: 13-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::Open(REFIID riid,
+ DWORD grfMode,
+ IPropertyStorage **ppprstg)
+{
+ SCODE sc;
+ SAFE_SEM;
+ CDfName dfn;
+ SafeIStorage pstg;
+
+ olLog(("%p::In CExposedDocFile::Open(riid, %lX, %p)\n",
+ this, grfMode, ppprstg));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::Open:%p("
+ "riid, %lX, %p)\n", this, grfMode, ppprstg));
+
+ olChk(ValidateOutPtrBuffer(ppprstg));
+ *ppprstg = NULL;
+ olChk(ValidateBuffer(&riid, sizeof(IID)));
+ olChk(Validate());
+ olChk(VerifyPerms(grfMode));
+ if ((grfMode & (STGM_PRIORITY | STGM_DELETEONRELEASE |
+ STGM_CONVERT)))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+
+ dfn.IidName(riid);
+
+ olChk(TakeSafeSem());
+
+ SetReadAccess();
+ sc = OpenEntry(&dfn, STGTY_STORAGE | STGTY_PROPFLAG, grfMode,
+ (void **)&pstg);
+ ClearReadAccess();
+ if (SUCCEEDED(sc))
+ {
+ sc = pstg->QueryInterface(IID_IPropertyStorage, (void **)ppprstg);
+ }
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::Open\n"));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::Open(). *ppprstg == %p, sc == %lX\n",
+ this, *ppprstg, sc));
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::Delete, public
+//
+// Synopsis: Deletes a property set
+//
+// Arguments: [riid] - Name
+//
+// Returns: Appropriate status code
+//
+// History: 13-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::Delete(REFIID riid)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ CDfName dfn;
+
+ olLog(("%p::In CExposedDocFile::Delete(riid)\n", this));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::Delete:%p(riid)\n", this));
+
+ olChk(ValidateBuffer(&riid, sizeof(IID)));
+ olChk(Validate());
+
+ dfn.IidName(riid);
+ olChk(TakeSafeSem());
+ SafeWriteAccess();
+ sc = _pdf->DestroyEntry(&dfn, FALSE);
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::Delete\n"));
+ EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::Enum, public
+//
+// Synopsis: Create a property set enumerator
+//
+// Arguments: [ppenm] - Enumerator return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 17-Dec-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::Enum(IEnumSTATPROPSETSTG **ppenm)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ SafeCExposedPropSetIter pepi;
+ CDfName dfnTmp;
+
+ olLog(("%p::In CExposedDocFile::EnumPS(%p)\n", this, ppenm));
+ olDebugOut((DEB_TRACE, "In CExposedDocFile::EnumPS:%p(%p)\n",
+ this, ppenm));
+
+ olChk(ValidateOutPtrBuffer(ppenm));
+ *ppenm = NULL;
+ olChk(Validate());
+
+ olChk(TakeSafeSem());
+ SafeReadAccess();
+
+ pepi.Attach(new CExposedPropSetIter(BP_TO_P(CPubDocFile *, _pdf), &dfnTmp,
+ BP_TO_P(CDFBasis *, _pdfb),
+ _ppc, FALSE));
+ olMem((CExposedPropSetIter *)pepi);
+ TRANSFER_INTERFACE(pepi, IEnumSTATPROPSETSTG, ppenm);
+
+ olDebugOut((DEB_TRACE, "Out CExposedDocFile::EnumPS\n"));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::EnumPS(). sc == %lX\n", sc));
+ return ResultFromScode(sc);
+}
diff --git a/private/ole32/stg/exp/exppsi.cxx b/private/ole32/stg/exp/exppsi.cxx
new file mode 100644
index 000000000..452881a09
--- /dev/null
+++ b/private/ole32/stg/exp/exppsi.cxx
@@ -0,0 +1,382 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: exppsi.cxx
+//
+// Contents: CExposedPropSetIter implementation
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <exppsi.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropSetIter::CExposedPropSetIter, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [ppdf] - Public docfile
+// [pdfnKey] - Initial key
+// [pdfb] - DocFile basis
+// [ppc] - Context
+// [fOwnContext] - Whether this object owns the context
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CExposedPropSetIter::CExposedPropSetIter(CPubDocFile *ppdf,
+ CDfName *pdfnKey,
+ CDFBasis *pdfb,
+ CPerContext *ppc,
+ BOOL fOwnContext)
+{
+ olDebugOut((DEB_ITRACE, "In CExposedPropSetIter::CExposedPropSetIter("
+ "%p, %d:%s, %p, %p, %u)\n", ppdf, pdfnKey->GetLength(),
+ pdfnKey->GetBuffer(), pdfb, ppc, fOwnContext));
+ _ppc = ppc;
+ _fOwnContext = fOwnContext;
+ _ppdf = P_TO_BP(CBasedPubDocFilePtr, ppdf);
+ _ppdf->vAddRef();
+ _dfnKey.Set(pdfnKey);
+ _pdfb = P_TO_BP(CBasedDFBasisPtr, pdfb);
+ _pdfb->vAddRef();
+ _cReferences = 1;
+ _sig = CEXPOSEDPROPSETITER_SIG;
+ olDebugOut((DEB_ITRACE,
+ "Out CExposedPropSetIter::CExposedPropSetIter\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropSetIter::~CExposedPropSetIter, public
+//
+// Synopsis: Destructor
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CExposedPropSetIter::~CExposedPropSetIter(void)
+{
+ olDebugOut((DEB_ITRACE,
+ "In CExposedPropSetIter::~CExposedPropSetIter\n"));
+ _sig = CEXPOSEDPROPSETITER_SIGDEL;
+ olAssert(_cReferences == 0);
+ if (_ppdf)
+ _ppdf->CPubDocFile::vRelease();
+ if (_pdfb)
+ _pdfb->CDFBasis::vRelease();
+ if (_fOwnContext && _ppc)
+ _ppc->Release();
+ olDebugOut((DEB_ITRACE,
+ "Out CExposedPropSetIter::~CExposedPropSetIter\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropSetIter::Next, public
+//
+// Synopsis: Gets N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+// [rgelt] - Array for element return
+// [pceltFetched] - If non-NULL, contains the number of
+// elements fetched
+//
+// Returns: Appropriate status code
+//
+// Modifies: [rgelt]
+// [pceltFetched]
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+_OLESTDMETHODIMP CExposedPropSetIter::Next(ULONG celt,
+ STATPROPSETSTG FAR *rgelt,
+ ULONG *pceltFetched)
+{
+ SCODE scSem = STG_E_INUSE;
+ SCODE sc;
+ STATSTGW sstg;
+ STATPROPSETSTG *pelt = rgelt;
+ ULONG celtDone;
+ WCHAR *pwc;
+ CDfName dfnInitial;
+
+ olDebugOut((DEB_TRACE, "In CExposedPropSetIter::Next(%lu, %p, %p)\n",
+ celt, rgelt, pceltFetched));
+
+ if (pceltFetched)
+ {
+ olChkTo(EH_RetSc, ValidateOutBuffer(pceltFetched, sizeof(ULONG)));
+ *pceltFetched = 0;
+ }
+ else if (celt > 1)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olAssert(0xffffUL/sizeof(STATPROPSTG) >= celt);
+ olChkTo(EH_RetSc,
+ ValidateOutBuffer(rgelt, (size_t)(sizeof(STATPROPSTG)*celt)));
+ memset(rgelt, 0, (size_t)(sizeof(STATPROPSTG)*celt));
+ olChk(Validate());
+ olChk(_ppdf->CheckReverted());
+
+ olChk(scSem = TakeSem());
+ SetReadAccess();
+
+ dfnInitial.Set(&_dfnKey);
+
+ TRY
+ {
+ for (; pelt<rgelt+celt; pelt++)
+ {
+ sc = _ppdf->FindGreaterEntry(&_dfnKey, NULL, &sstg, TRUE);
+ if (FAILED(sc))
+ {
+ if (sc == STG_E_NOMOREFILES)
+ sc = S_FALSE;
+ break;
+ }
+ _dfnKey.CopyString(sstg.pwcsName);
+ pwc = (WCHAR *)_dfnKey.GetBuffer();
+ TaskMemFree(sstg.pwcsName);
+
+ // We need to copy the STATSTG fields into our
+ // STATPROPSETSTG
+ if (pwc[0] == PROPBYTE_WCHAR &&
+ pwc[1] == PROPSET_WCHAR)
+ {
+ memcpy(&pelt->iid, pwc+2, sizeof(IID));
+ pelt->mtime = sstg.mtime;
+ pelt->atime = sstg.atime;
+ pelt->ctime = sstg.ctime;
+ }
+ else
+ {
+ // Not a property set name, ignore
+ pelt--;
+ }
+ }
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+
+ olDebugOut((DEB_TRACE, "Out CExposedPropSetIter::Next => %lX\n", sc));
+EH_Err:
+ ClearReadAccess();
+ ReleaseSem(scSem);
+ celtDone = pelt-rgelt;
+ if (FAILED(sc))
+#ifndef WIN32
+ memset(rgelt, 0, (size_t)(sizeof(STATPROPSTG)*celt));
+#else
+ NULL;
+#endif
+ else if (pceltFetched)
+ *pceltFetched = celtDone;
+EH_RetSc:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropSetIter::Skip, public
+//
+// Synopsis: Skips N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+//
+// Returns: Appropriate status code
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedPropSetIter::Skip(ULONG celt)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In CExposedPropSetIter::Skip(%lu)\n", celt));
+
+ if (SUCCEEDED(Validate()))
+ sc = hSkip(celt, TRUE);
+
+ olDebugOut((DEB_TRACE, "Out CExposedPropSetIter::Skip\n"));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropSetIter::Reset, public
+//
+// Synopsis: Rewinds the iterator
+//
+// Returns: Appropriate status code
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedPropSetIter::Reset(void)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In CExposedPropSetIter::Reset()\n"));
+
+ if (SUCCEEDED(Validate()))
+ sc = hReset();
+
+ olDebugOut((DEB_TRACE, "Out CExposedPropSetIter::Reset\n"));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropSetIter::Clone, public
+//
+// Synopsis: Clones this iterator
+//
+// Arguments: [ppenm] - Clone return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedPropSetIter::Clone(IEnumSTATPROPSETSTG **ppenm)
+{
+ SCODE sc, scSem = STG_E_INUSE;
+ SafeCExposedPropSetIter pepi;
+
+ olDebugOut((DEB_TRACE, "In CExposedPropSetIter::Clone(%p)\n", ppenm));
+
+ olChk(ValidateOutPtrBuffer(ppenm));
+ *ppenm = NULL;
+ olChk(Validate());
+ olChk(_ppdf->CheckReverted());
+
+ olChk(scSem = TakeSem());
+ SetReadAccess();
+
+ pepi.Attach(new CExposedPropSetIter(BP_TO_P(CPubDocFile *, _ppdf),
+ &_dfnKey, BP_TO_P(CDFBasis *, _pdfb),
+ _ppc,
+ TRUE));
+ if ((CExposedPropSetIter *)pepi == NULL)
+ sc = STG_E_INSUFFICIENTMEMORY;
+
+ ClearReadAccess();
+ ReleaseSem(scSem);
+
+ if (SUCCEEDED(sc))
+ {
+ TRANSFER_INTERFACE(pepi, IEnumSTATPROPSETSTG, ppenm);
+ _ppc->AddRef();
+ }
+
+ olDebugOut((DEB_TRACE, "Out CExposedPropSetIter::Clone => %p\n",
+ *ppenm));
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropSetIter::Release, public
+//
+// Synopsis: Releases resources for the iterator
+//
+// Returns: Appropriate status code
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CExposedPropSetIter::Release(void)
+{
+ LONG lRet;
+
+ olDebugOut((DEB_TRACE, "In CExposedPropSetIter::Release()\n"));
+
+ if (FAILED(Validate()))
+ return 0;
+ if ((lRet = hRelease()) == 0)
+ delete this;
+
+ olDebugOut((DEB_TRACE, "Out CExposedPropSetIter::Release\n"));
+ return lRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropSetIter::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CExposedPropSetIter::AddRef(void)
+{
+ ULONG ulRet;
+
+ olDebugOut((DEB_TRACE, "In CExposedPropSetIter::AddRef()\n"));
+
+ if (FAILED(Validate()))
+ return 0;
+ ulRet = hAddRef();
+
+ olDebugOut((DEB_TRACE, "Out CExposedPropSetIter::AddRef\n"));
+ return ulRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropSetIter::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedPropSetIter::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE,
+ "In CExposedPropSetIter::QueryInterface(riid, %p)\n",
+ ppvObj));
+
+ if (SUCCEEDED(Validate()))
+ sc = hQueryInterface(iid, IID_IEnumSTATPROPSETSTG, this, ppvObj);
+
+ olDebugOut((DEB_TRACE, "Out CExposedPropSetIter::QueryInterface => %p\n",
+ ppvObj));
+ return ResultFromScode(sc);
+}
diff --git a/private/ole32/stg/exp/exppsi.hxx b/private/ole32/stg/exp/exppsi.hxx
new file mode 100644
index 000000000..01f21748f
--- /dev/null
+++ b/private/ole32/stg/exp/exppsi.hxx
@@ -0,0 +1,89 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: exppsi.hxx
+//
+// Contents: Exposed property set iterator header
+//
+// Classes: CExposedPropSetIter
+//
+// History: 21-Dec-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __EXPPSI_HXX__
+#define __EXPPSI_HXX__
+
+#include <dfmsp.hxx>
+#include <lock.hxx>
+#include <dfbasis.hxx>
+#include <peiter.hxx>
+
+class CDFBasis;
+
+//+---------------------------------------------------------------------------
+//
+// Class: CExposedPropSetIter (epi)
+//
+// Purpose: Exposed portion of the PropSet iterator
+//
+// Interface: See below
+//
+// History: 21-Dec-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+interface CExposedPropSetIter
+ : public IEnumSTATPROPSETSTG, public PExposedIterator
+{
+public:
+ CExposedPropSetIter(CPubDocFile *ppdf,
+ CDfName *pdfnKey,
+ CDFBasis *pdfb,
+ CPerContext *ppc,
+ BOOL fOwnContext);
+ ~CExposedPropSetIter(void);
+
+ // From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // New methods
+ STDMETHOD(Next)(ULONG celt,
+ STATPROPSETSTG FAR *rgelt,
+ ULONG *pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(IEnumSTATPROPSETSTG **ppenm);
+
+ inline SCODE Validate(void) const;
+};
+
+SAFE_INTERFACE_PTR(SafeCExposedPropSetIter, CExposedPropSetIter);
+
+// DocFileIter signatures
+#define CEXPOSEDPROPSETITER_SIG LONGSIG('E', 'P', 'S', 'I')
+#define CEXPOSEDPROPSETITER_SIGDEL LONGSIG('E', 'p', 'S', 'i')
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedPropSetIter::Validate, public
+//
+// Synopsis: Validates the signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE if the signature doesn't match
+//
+// History: 12-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CExposedPropSetIter::Validate(void) const
+{
+ return (this == NULL || _sig != CEXPOSEDPROPSETITER_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+#endif // #ifndef __EXPPSI_HXX__
diff --git a/private/ole32/stg/exp/expst.cxx b/private/ole32/stg/exp/expst.cxx
new file mode 100644
index 000000000..48d1d84ac
--- /dev/null
+++ b/private/ole32/stg/exp/expst.cxx
@@ -0,0 +1,2300 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) 1992, Microsoft Corporation.
+//
+// File: expst.cxx
+//
+// Contents: CExposedStream code
+//
+// History: 28-Feb-92 PhilipLa Created.
+// 20-Jun-96 MikeHill Fixed the PropSet version of
+// Lock to check the result of TakeSem.
+// 1-Jul-96 MikeHill - Removed Win32 SEH from PropSet code.
+// - Receive NTPROP in propset Open method.
+//
+//--------------------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <pbstream.hxx>
+#include <expst.hxx>
+#include <lock.hxx>
+#include <seekptr.hxx>
+#include <marshl.hxx>
+#include <logfile.hxx>
+
+// Maximum stream size supported by exposed streams
+// This is MAX_ULONG with one subtracted so that
+// the seek pointer has a spot to sit even at the
+// end of the stream
+#define CBMAXSTREAM 0xfffffffeUL
+// Maximum seek pointer value
+#define CBMAXSEEK (CBMAXSTREAM+1)
+
+#if DBG
+DWORD MyGetLastError()
+{
+ return GetLastError();
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::CExposedStream, public
+//
+// Synopsis: Empty object constructor
+//
+// History: 30-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+
+CExposedStream::CExposedStream(void)
+{
+ olDebugOut((DEB_ITRACE, "In CExposedStream::CExposedStream()\n"));
+ _pdfb = NULL;
+ _ppc = NULL;
+ _fOwnContext = FALSE;
+ _cReferences = 0;
+ _psp = NULL;
+ _pst = NULL;
+#ifdef NEWPROPS
+ _pmapstm = NULL;
+#endif
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::CExposedStream\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Init, public
+//
+// Synopsis: Base constructor
+//
+// Arguments: [pst] - Public stream
+// [pdfb] - DocFile basis
+// [ppc] - Context
+// [fOwnContext] - Whether this object owns the context
+// [psp] - Seek pointer or NULL for new seek pointer
+//
+// Returns: Appropriate status code
+//
+// History: 28-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+SCODE CExposedStream::Init(CPubStream *pst,
+ CDFBasis *pdfb,
+ CPerContext *ppc,
+ BOOL fOwnContext,
+ CSeekPointer *psp)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CExposedStream::Init("
+ "%p, %p, %p, %u, %p)\n",
+ pst, pdfb, ppc, fOwnContext, psp));
+
+#ifdef NEWPROPS
+ CMappedStream *pmsT = &(pst->GetMappedStream());
+ _pmapstm = P_TO_BP(CBasedMappedStreamPtr, pmsT);
+#endif
+
+ if (psp == NULL)
+ {
+ CSeekPointer *pspTemp;
+ olMem(pspTemp = new (pdfb->GetMalloc()) CSeekPointer(0));
+ _psp = P_TO_BP(CBasedSeekPointerPtr, pspTemp);
+ }
+ else
+ _psp = P_TO_BP(CBasedSeekPointerPtr, psp);
+ _ppc = ppc;
+ _fOwnContext = fOwnContext;
+ _pst = P_TO_BP(CBasedPubStreamPtr, pst);
+ _pdfb = P_TO_BP(CBasedDFBasisPtr, pdfb);
+ _pdfb->vAddRef();
+ _cReferences = 1;
+ _sig = CEXPOSEDSTREAM_SIG;
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::Init\n"));
+ return S_OK;
+
+EH_Err:
+ return sc;
+}
+
+SCODE CExposedStream::InitMarshal(CPubStream *pst,
+ CDFBasis *pdfb,
+ CPerContext *ppc,
+ DWORD dwAsyncFlags,
+ IDocfileAsyncConnectionPoint *pdacp,
+ BOOL fOwnContext,
+ CSeekPointer *psp)
+{
+ SCODE sc;
+ sc = CExposedStream::Init(pst,
+ pdfb,
+ ppc,
+ fOwnContext,
+ psp);
+ if (SUCCEEDED(sc))
+ {
+ sc = _cpoint.InitMarshal(this, dwAsyncFlags, pdacp);
+ }
+ return sc;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::~CExposedStream, public
+//
+// Synopsis: Destructor
+//
+// Returns: Appropriate status code
+//
+// History: 28-Feb-92 DrewB Created from pbstream source
+//
+//---------------------------------------------------------------
+
+
+CExposedStream::~CExposedStream(void)
+{
+ olDebugOut((DEB_ITRACE, "In CExposedStream::~CExposedStream\n"));
+ olAssert(_cReferences == 0);
+ _sig = CEXPOSEDSTREAM_SIGDEL;
+
+ //In order to call into the tree, we need to take the mutex.
+ //The mutex may get deleted in _ppc->Release(), so we can't
+ //release it here. The mutex actually gets released in
+ //CPerContext::Release() or in the CPerContext destructor.
+ SCODE sc;
+
+#if !defined(MULTIHEAP)
+ // TakeSem and ReleaseSem are moved to the Release Method
+ // so that the deallocation for this object is protected
+ if (_ppc)
+ {
+ sc = TakeSem();
+ SetWriteAccess();
+ olAssert(SUCCEEDED(sc));
+ }
+
+#ifdef ASYNC
+ IDocfileAsyncConnectionPoint *pdacp = _cpoint.GetMarshalPoint();
+#endif
+#endif //MULTIHEAP
+
+
+ if (_pst)
+ _pst->CPubStream::vRelease();
+ if (_psp)
+ _psp->CSeekPointer::vRelease();
+ if (_pdfb)
+ _pdfb->CDFBasis::vRelease();
+#if !defined(MULTIHEAP)
+ if (_fOwnContext && _ppc)
+ {
+ _ppc->Release();
+ }
+ else if (_ppc)
+ {
+ ReleaseSem(sc);
+ }
+#ifdef ASYNC
+ //Mutex has been released, so we can release the connection point
+ // without fear of deadlock.
+ if (pdacp != NULL)
+ pdacp->Release();
+#endif
+#endif // MULTIHEAP
+
+
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::~CExposedStream\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Read, public
+//
+// Synopsis: Read from a stream
+//
+// Arguments: [pb] - Buffer
+// [cb] - Count of bytes to read
+// [pcbRead] - Return number of bytes read
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+//
+// History: 28-Feb-92 DrewB Created from pbstream source
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedStream::Read(VOID HUGEP *pb, ULONG cb, ULONG *pcbRead)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ ULONG cbRead = 0;
+
+ olLog(("%p::In CExposedStream::Read(%p, %lu, %p)\n",
+ this, pb, cb, pcbRead));
+ olDebugOut((DEB_TRACE, "In CExposedStream::Read(%p, %lu, %p)\n",
+ pb, cb, pcbRead));
+
+ if (pcbRead)
+ {
+ olChkTo(EH_BadPtr, ValidateOutBuffer(pcbRead, sizeof(ULONG)));
+ }
+
+ olChk(ValidateHugeOutBuffer(pb, cb));
+ olChk(Validate());
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeReadAccess();
+ sc = _pst->ReadAt(_psp->GetPos(), pb, cb, (ULONG STACKBASED *)&cbRead);
+ olAssert(CBMAXSEEK-_psp->GetPos() >= cbRead);
+ _psp->SetPos(_psp->GetPos()+cbRead);
+ pb = (BYTE *)pb + cbRead;
+ cb -= cbRead;
+ END_PENDING_LOOP;
+
+ olDebugOut((DEB_TRACE, "Out CExposedStream::Read => %lu\n", cbRead));
+
+EH_Err:
+ if (pcbRead)
+ {
+ // May fault and leave stream seek pointer changed
+ // This is acceptable
+ *pcbRead = cbRead;
+ olLog(("%p::Out CExposedStream::Read(). *pcbRead == %lu, ret = %lx\n",
+ this, *pcbRead, sc));
+ }
+ else
+ {
+ olLog(("%p::Out CExposedStream::Read(). ret == %lx\n", this, sc));
+ }
+
+EH_BadPtr:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Write, public
+//
+// Synopsis: Write to a stream
+//
+// Arguments: [pb] - Buffer
+// [cb] - Count of bytes to write
+// [pcbWritten] - Return of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbWritten]
+//
+// History: 28-Feb-92 DrewB Created from pbstream source
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::Write(
+ VOID const HUGEP *pb,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ ULONG cbWritten = 0;
+
+ olLog(("%p::In CExposedStream::Write(%p, %lu, %p)\n",
+ this, pb, cb, pcbWritten));
+ olDebugOut((DEB_TRACE, "In CExposedStream::Write(%p, %lu, %p)\n",
+ pb, cb, pcbWritten));
+
+ if (pcbWritten)
+ {
+ olChkTo(EH_BadPtr, ValidateOutBuffer(pcbWritten, sizeof(ULONG)));
+ }
+ olChk(ValidateHugeBuffer(pb, cb));
+ olChk(Validate());
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeWriteAccess();
+ sc = _pst->WriteAt(_psp->GetPos(), pb, cb,
+ (ULONG STACKBASED *)&cbWritten);
+ olAssert(CBMAXSEEK-_psp->GetPos() >= cbWritten);
+ _psp->SetPos(_psp->GetPos()+cbWritten);
+ pb = (BYTE *)pb + cbWritten;
+ cb -= cbWritten;
+ END_PENDING_LOOP;
+
+ olDebugOut((DEB_TRACE, "Out CExposedStream::Write => %lu\n",
+ cbWritten));
+EH_Err:
+ if (pcbWritten)
+ {
+ // May fault but that's acceptable
+ *pcbWritten = cbWritten;
+ olLog(("%p::Out CExposedStream::Write(). "
+ "*pcbWritten == %lu, ret = %lx\n",
+ this, *pcbWritten, sc));
+ }
+ else
+ {
+ olLog(("%p::Out CExposedStream::Write(). ret == %lx\n", this, sc));
+ }
+
+EH_BadPtr:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Seek, public
+//
+// Synopsis: Seek to a point in a stream
+//
+// Arguments: [dlibMove] - Offset to move by
+// [dwOrigin] - SEEK_SET, SEEK_CUR, SEEK_END
+// [plibNewPosition] - Return of new offset
+//
+// Returns: Appropriate status code
+//
+// Modifies: [plibNewPosition]
+//
+// History: 28-Feb-92 DrewB Created from pbstream source
+//
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::Seek(LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ LONG lMove;
+ ULARGE_INTEGER ulPos;
+
+ olLog(("%p::In CExposedStream::Seek(%ld, %lu, %p)\n",
+ this, LIGetLow(dlibMove), dwOrigin, plibNewPosition));
+ olDebugOut((DEB_TRACE, "In CExposedStream::Seek(%ld, %lu, %p)\n",
+ LIGetLow(dlibMove), dwOrigin, plibNewPosition));
+
+ if (plibNewPosition)
+ {
+ olChk(ValidateOutBuffer(plibNewPosition, sizeof(ULARGE_INTEGER)));
+ ULISet32(*plibNewPosition, 0);
+ }
+ if (dwOrigin != STREAM_SEEK_SET && dwOrigin != STREAM_SEEK_CUR &&
+ dwOrigin != STREAM_SEEK_END)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+
+ // Truncate dlibMove to 32 bits
+ if (dwOrigin == STREAM_SEEK_SET)
+ {
+ // Make sure we don't seek too far
+ if (LIGetHigh(dlibMove) != 0)
+ LISet32(dlibMove, 0xffffffff);
+ }
+ else
+ {
+ // High dword must be zero for positive values or -1 for
+ // negative values
+ // Additionally, for negative values, the low dword can't
+ // exceed -0x80000000 because the 32nd bit is the sign
+ // bit
+ if (LIGetHigh(dlibMove) > 0 ||
+ (LIGetHigh(dlibMove) == 0 &&
+ LIGetLow(dlibMove) >= 0x80000000))
+ LISet32(dlibMove, 0x7fffffff);
+ else if (LIGetHigh(dlibMove) < -1 ||
+ (LIGetHigh(dlibMove) == -1 &&
+ LIGetLow(dlibMove) <= 0x7fffffff))
+ LISet32(dlibMove, 0x80000000);
+ }
+
+ lMove = (LONG)LIGetLow(dlibMove);
+ olChk(Validate());
+
+ //ASYNC Note: We probably don't need this pending loop in Seek
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ olChk(_pst->CheckReverted());
+ SafeReadAccess();
+
+ ULISet32(ulPos, _psp->GetPos());
+ switch(dwOrigin)
+ {
+ case STREAM_SEEK_SET:
+ ULISetLow(ulPos, (ULONG)lMove);
+ break;
+
+ case STREAM_SEEK_END:
+ ULONG cbSize;
+ olChk(_pst->GetSize(&cbSize));
+ if (lMove < 0)
+ {
+ if ((ULONG)(-lMove) > cbSize)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ }
+ else if ((ULONG)lMove > CBMAXSEEK-cbSize)
+ lMove = (LONG)(CBMAXSEEK-cbSize);
+ ULISetLow(ulPos, cbSize+lMove);
+ break;
+
+ case STREAM_SEEK_CUR:
+ if (lMove < 0)
+ {
+ if ((ULONG)(-lMove) > _psp->GetPos())
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ }
+ else if ((ULONG)lMove > CBMAXSEEK-_psp->GetPos())
+ lMove = (LONG)(CBMAXSEEK-_psp->GetPos());
+ ULISetLow(ulPos, _psp->GetPos()+lMove);
+ break;
+ }
+ _psp->SetPos(ULIGetLow(ulPos));
+
+ if (plibNewPosition)
+ // May fault but that's acceptable
+ *plibNewPosition = ulPos;
+ END_PENDING_LOOP;
+
+ olDebugOut((DEB_TRACE, "Out CExposedStream::Seek => %lu\n",
+ ULIGetLow(ulPos)));
+EH_Err:
+ olLog(("%p::Out CExposedStream::Seek(). ulPos == %lu, ret == %lx\n",
+ this, ULIGetLow(ulPos), sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::SetSize, public
+//
+// Synopsis: Sets the size of a stream
+//
+// Arguments: [ulNewSize] - New size
+//
+// Returns: Appropriate status code
+//
+// History: 28-Feb-92 DrewB Created from pbstream source
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::SetSize(ULARGE_INTEGER ulNewSize)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+
+ olLog(("%p::In CExposedStream::SetSize(%lu)\n",
+ this, ULIGetLow(ulNewSize)));
+ olDebugOut((DEB_TRACE, "In CExposedStream::SetSize(%lu)\n",
+ ULIGetLow(ulNewSize)));
+
+ if (ULIGetHigh(ulNewSize) != 0)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ olChk(Validate());
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeWriteAccess();
+ sc = _pst->SetSize(ULIGetLow(ulNewSize));
+ END_PENDING_LOOP;
+
+ olDebugOut((DEB_TRACE, "Out CExposedStream::SetSize\n"));
+EH_Err:
+ olLog(("%p::Out CExposedStream::SetSize(). ret == %lx\n", this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::CopyTo, public
+//
+// Synopsis: Copies information from one stream to another
+//
+// Arguments: [pstm] - Destination
+// [cb] - Number of bytes to copy
+// [pcbRead] - Return number of bytes read
+// [pcbWritten] - Return number of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+// [pcbWritten]
+//
+// History: 25-Mar-92 DrewB Created
+// 12-Jan-93 AlexT Rewritten without recursion
+//
+// Notes: We do our best to handle overlap correctly. This allows
+// CopyTo to be used to insert and remove space within a
+// stream.
+//
+// In the error case, we make no gurantees as to the
+// validity of pcbRead, pcbWritten, or either stream's
+// seek position.
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedStream::CopyTo(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten)
+{
+ SCODE sc;
+
+ olLog(("%p::In CExposedStream::CopyTo(%p, %lu, %p, %p)\n",
+ this, pstm, ULIGetLow(cb), pcbRead, pcbWritten));
+ olDebugOut((DEB_TRACE, "In CExposedStream::CopyTo("
+ "%p, %lu, %p, %p)\n", pstm, ULIGetLow(cb),
+ pcbRead, pcbWritten));
+ if (pcbRead)
+ {
+ olChk(ValidateOutBuffer(pcbRead, sizeof(ULARGE_INTEGER)));
+ ULISet32(*pcbRead, 0);
+ }
+ if (pcbWritten)
+ {
+ olChk(ValidateOutBuffer(pcbWritten, sizeof(ULARGE_INTEGER)));
+ ULISet32(*pcbWritten, 0);
+ }
+
+ // We don't touch the out parameters during the actual work so we
+ // don't expect any faults until the end
+
+ olChk(ValidateInterface(pstm, IID_IStream));
+ olChk(Validate());
+
+ do
+ {
+ sc = CopyToWorker(pstm, cb, pcbRead, pcbWritten);
+ if (!ISPENDINGERROR(sc))
+ {
+ break;
+ }
+ else
+ {
+ SCODE sc2;
+ sc2 = _cpoint.Notify(sc,
+ _ppc->GetBase(),
+ _ppc,
+ NULL);
+ if (sc2 != S_OK)
+ {
+ return ResultFromScode(sc2);
+ }
+ }
+ } while (TRUE);
+
+ olDebugOut((DEB_TRACE, "Out CExposedStream::CopyTo => %lu, %lu\n",
+ pcbRead ? ULIGetLow(*pcbRead) : 0,
+ pcbWritten ? ULIGetLow(*pcbWritten) : 0));
+EH_Err:
+ return sc;
+}
+
+SCODE CExposedStream::CopyToWorker(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ SCODE sc;
+ ULONG ulCopySize;
+ ULONG ulSrcSize;
+ ULONG ulSrcOrig;
+ ULARGE_INTEGER uliDestOrig;
+ LARGE_INTEGER liDestPos;
+ BYTE *pb = NULL;
+ BOOL fOverlap;
+ ULONG ulBytesCopied = 0;
+
+ // Bound the size of the copy
+ // 1. The maximum we can copy is 0xffffffff
+ if (ULIGetHigh(cb) == 0)
+ ulCopySize = ULIGetLow(cb);
+ else
+ ulCopySize = 0xffffffff;
+
+ // 2. We can only copy what's available in the source stream
+ SetReadAccess();
+ sc = _pst->GetSize(&ulSrcSize);
+ ClearReadAccess();
+ olChk(sc);
+
+ ulSrcOrig = _psp->GetPos();
+ if (ulSrcSize < ulSrcOrig)
+ {
+ // Nothing in source to copy
+ ulCopySize = 0;
+ }
+ else if ((ulSrcSize - ulSrcOrig) < ulCopySize)
+ {
+ // Shrink ulCopySize to fit bytes in source
+ ulCopySize = ulSrcSize - ulSrcOrig;
+ }
+
+ // 3. We can only copy what will fit in the destination
+ LISet32(liDestPos, 0);
+ olHChk(pstm->Seek(liDestPos, STREAM_SEEK_CUR, &uliDestOrig));
+ olAssert(ULIGetHigh(uliDestOrig) == 0);
+
+ if (ulCopySize > CBMAXSEEK - ULIGetLow(uliDestOrig))
+ ulCopySize = CBMAXSEEK - ULIGetLow(uliDestOrig);
+
+ // We are allowed to fail here with out-of-memory
+ olMem(pb = (BYTE *) DfMemAlloc(STREAMBUFFERSIZE));
+
+ // Since we have no reliable way to determine if the source and
+ // destination represent the same stream, we assume they
+ // do and always handle overlap.
+
+ fOverlap = (ULIGetLow(uliDestOrig) > ulSrcOrig &&
+ ULIGetLow(uliDestOrig) < ulSrcOrig + ulCopySize);
+
+ ULONG ulSrcCopyOffset;
+ ULONG ulDstCopyOffset;
+ if (fOverlap)
+ {
+ // We're going to copy back to front, so determine the
+ // stream end positions
+ ulSrcCopyOffset = ulSrcOrig + ulCopySize;
+
+ // uliDestOrig is the destination starting offset
+ ulDstCopyOffset = ULIGetLow(uliDestOrig) + ulCopySize;
+ }
+
+ while (ulCopySize > 0)
+ {
+ // We can only copy up to STREAMBUFFERSIZE bytes at a time
+ ULONG cbPart = min(ulCopySize, STREAMBUFFERSIZE);
+
+ if (fOverlap)
+ {
+ // We're copying back to front so we need to seek to
+ // set up the streams correctly
+
+ ulSrcCopyOffset -= cbPart;
+ ulDstCopyOffset -= cbPart;
+
+ // Set source stream position
+ _psp->SetPos(ulSrcCopyOffset);
+
+ // Set destination stream position
+ LISet32(liDestPos, ulDstCopyOffset);
+ olHChk(pstm->Seek(liDestPos, STREAM_SEEK_SET, NULL));
+ }
+
+ ULONG ulRead;
+ olHChk(Read(pb, cbPart, &ulRead));
+ if (cbPart != ulRead)
+ {
+ // There was no error, but we were unable to read cbPart
+ // bytes. Something's wrong (the underlying ILockBytes?)
+ // but we can't control it; just return an error.
+ olErr(EH_Err, STG_E_READFAULT);
+ }
+
+ ULONG ulWritten;
+ olHChk(pstm->Write(pb, cbPart, &ulWritten));
+ if (cbPart != ulWritten)
+ {
+ // There was no error, but we were unable to write
+ // ulWritten bytes. We can't trust the pstm
+ // implementation, so all we can do here is return
+ // an error.
+ olErr(EH_Err, STG_E_WRITEFAULT);
+ }
+
+ olAssert(ulCopySize >= cbPart);
+ ulCopySize -= cbPart;
+ ulBytesCopied += cbPart;
+ }
+
+ if (fOverlap)
+ {
+ // Set the seek pointers to the correct location
+ _psp->SetPos(ulSrcOrig + ulBytesCopied);
+
+ LISet32(liDestPos, ULIGetLow(uliDestOrig) + ulBytesCopied);
+ olHChk(pstm->Seek(liDestPos, STREAM_SEEK_SET, NULL));
+ }
+
+ // Fall through
+
+EH_Err:
+ DfMemFree(pb);
+
+ // We can fault here, but that's acceptable
+ if (pcbRead)
+ ULISet32(*pcbRead, ulBytesCopied);
+ if (pcbWritten)
+ ULISet32(*pcbWritten, ulBytesCopied);
+
+ olLog(("%p::Out CExposedStream::CopyTo(). "
+ "cbRead == %lu, cbWritten == %lu, ret == %lx\n",
+ this, pcbRead ? ULIGetLow(*pcbRead) : 0,
+ pcbWritten ? ULIGetLow(*pcbWritten) : 0, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Release, public
+//
+// Synopsis: Releases a stream
+//
+// Returns: Appropriate status code
+//
+// History: 28-Feb-92 DrewB Created from pbstream source
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP_(ULONG) CExposedStream::Release(void)
+{
+ LONG lRet;
+
+ olLog(("%p::In CExposedStream::Release()\n", this));
+ olDebugOut((DEB_TRACE, "In CExposedStream::Release()\n"));
+
+ if (FAILED(Validate()))
+ return 0;
+ olAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+ CPerContext *ppc = _ppc;
+ BOOL fOwnContext = _fOwnContext;
+ SCODE sc = S_OK;
+ if (_ppc)
+ {
+ sc = TakeSem();
+ SetWriteAccess();
+ olAssert(SUCCEEDED(sc));
+ }
+#ifdef ASYNC
+ IDocfileAsyncConnectionPoint *pdacp = _cpoint.GetMarshalPoint();
+#endif
+#endif //MULTIHEAP
+ delete this;
+#ifdef MULTIHEAP
+ if (fOwnContext && ppc)
+ {
+ BOOL fLastRef = ppc->LastRef();
+ ppc->Release();
+ if (fLastRef)
+ g_smAllocator.Uninit();
+ }
+ else if (ppc)
+ {
+ if (SUCCEEDED(sc)) ppc->UntakeSem();
+ }
+#ifdef ASYNC
+ //Mutex has been released, so we can release the connection point
+ // without fear of deadlock.
+ if (pdacp != NULL)
+ pdacp->Release();
+#endif
+#endif
+ }
+ else if (lRet < 0)
+ lRet = 0;
+
+ olDebugOut((DEB_TRACE, "Out CExposedStream::Release\n"));
+ olLog(("%p::Out CExposedStream::Release(). ret == %lu\n", this, lRet));
+ FreeLogFile();
+ return lRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Stat, public
+//
+// Synopsis: Fills in a buffer of information about this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 24-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+_OLESTDMETHODIMP CExposedStream::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+ STATSTGW stat;
+
+ olLog(("%p::In CExposedStream::Stat(%p)\n", this, pstatstg));
+ olDebugOut((DEB_TRACE, "In CExposedStream::Stat(%p)\n",
+ pstatstg));
+
+ olChkTo(EH_RetSc, ValidateOutBuffer(pstatstg, sizeof(STATSTGW)));
+ olChk(VerifyStatFlag(grfStatFlag));
+ olChk(Validate());
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeReadAccess();
+
+ sc = _pst->Stat(&stat, grfStatFlag);
+ END_PENDING_LOOP;
+
+ if (SUCCEEDED(sc))
+ {
+ TRY
+ {
+ *pstatstg = stat;
+ pstatstg->type = STGTY_STREAM;
+ pstatstg->grfLocksSupported = 0;
+ pstatstg->STATSTG_dwStgFmt = 0;
+ pstatstg->ctime.dwLowDateTime = pstatstg->ctime.dwHighDateTime = 0;
+ pstatstg->mtime.dwLowDateTime = pstatstg->mtime.dwHighDateTime = 0;
+ pstatstg->atime.dwLowDateTime = pstatstg->atime.dwHighDateTime = 0;
+ }
+ CATCH(CException, e)
+ {
+ UNREFERENCED_PARM(e);
+ if (stat.pwcsName)
+ TaskMemFree(stat.pwcsName);
+ sc = STG_E_INVALIDPOINTER;
+ }
+ END_CATCH
+ }
+ olDebugOut((DEB_TRACE, "Out CExposedStream::Stat\n"));
+ // Fall through
+
+EH_Err:
+EH_RetSc:
+ olLog(("%p::Out CExposedStream::Stat(). ret == %lx\n",
+ this, sc));
+ return _OLERETURN(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Clone, public
+//
+// Synopsis: Clones a stream
+//
+// Returns: Appropriate status code
+//
+// History: 28-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::Clone(IStream **ppstm)
+{
+ SafeCExposedStream pst;
+ CSeekPointer *psp;
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+
+ olLog(("%p::In CExposedStream::Clone(%p)\n", this, ppstm));
+ olDebugOut((DEB_TRACE, "In CExposedStream::Clone(%p)\n", ppstm));
+
+ olChk(ValidateOutPtrBuffer(ppstm));
+ *ppstm = NULL;
+ olChk(Validate());
+ olChk(TakeSafeSem());
+ olChk(_pst->CheckReverted());
+ SafeReadAccess();
+ olMem(psp = new (_pdfb->GetMalloc()) CSeekPointer(_psp->GetPos()));
+ pst.Attach(new (_pdfb->GetMalloc()) CExposedStream);
+ olMemTo(EH_psp, (CExposedStream *)pst);
+ olChkTo(EH_pst, pst->Init(BP_TO_P(CPubStream *, _pst),
+ BP_TO_P(CDFBasis *, _pdfb),
+ _ppc, TRUE, psp));
+
+ _ppc->AddRef();
+ _pst->vAddRef();
+#ifdef ASYNC
+ if (_cpoint.IsInitialized())
+ {
+ olChkTo(EH_pstInit, pst->InitClone(&_cpoint));
+ }
+#endif
+ TRANSFER_INTERFACE(pst, IStream, ppstm);
+
+ olDebugOut((DEB_TRACE, "Out CExposedStream::Clone => %p\n", *ppstm));
+
+ EH_Err:
+ olLog(("%p::Out CExposedStream::Clone(). *ppstm == %p, ret == %lx\n",
+ this, *ppstm, sc));
+ return ResultFromScode(sc);
+EH_pstInit:
+ pst->Release();
+ goto EH_Err;
+EH_pst:
+ delete pst;
+EH_psp:
+ psp->vRelease();
+ goto EH_Err;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+// History: 16-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP_(ULONG) CExposedStream::AddRef(void)
+{
+ ULONG ulRet;
+
+ olLog(("%p::In CExposedStream::AddRef()\n", this));
+ olDebugOut((DEB_TRACE, "In CExposedStream::AddRef()\n"));
+
+ if (FAILED(Validate()))
+ return 0;
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+
+ olDebugOut((DEB_TRACE, "Out CExposedStream::AddRef\n"));
+ olLog(("%p::Out CExposedStream::AddRef(). ret == %lu\n", this, ulRet));
+ return ulRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::LockRegion, public
+//
+// Synopsis: Nonfunctional
+//
+// Returns: Appropriate status code
+//
+// History: 16-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ olDebugOut((DEB_TRACE, "In CExposedStream::LockRegion("
+ "%lu, %lu\n", ULIGetLow(cb), dwLockType));
+ olDebugOut((DEB_TRACE, "Out CExposedStream::LockRegion\n"));
+ olLog(("%p::INVALID CALL TO CExposedStream::LockRegion()\n"));
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::UnlockRegion, public
+//
+// Synopsis: Nonfunctional
+//
+// Returns: Appropriate status code
+//
+// History: 16-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ olDebugOut((DEB_TRACE, "In CExposedStream::UnlockRegion(%lu, %lu)\n",
+ ULIGetLow(cb), dwLockType));
+ olDebugOut((DEB_TRACE, "Out CExposedStream::UnlockRegion\n"));
+ olLog(("%p::INVALID CALL TO CExposedStream::UnlockRegion()\n"));
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Commit, public
+//
+// Synopsis: No-op in current implementation
+//
+// Returns: Appropriate status code
+//
+// History: 16-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::Commit(DWORD grfCommitFlags)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+
+ olDebugOut((DEB_TRACE, "In CExposedStream::Commit(%lu)\n",
+ grfCommitFlags));
+ olLog(("%p::In CExposedStream::Commit(%lx)\n", this, grfCommitFlags));
+
+ olChk(Validate());
+
+ BEGIN_PENDING_LOOP;
+ olChk(TakeSafeSem());
+ SafeWriteAccess();
+
+ sc = _pst->Commit(grfCommitFlags);
+ END_PENDING_LOOP;
+
+ olDebugOut((DEB_TRACE, "Out CExposedStream::Commit\n"));
+EH_Err:
+ olLog(("%p::Out CExposedStream::Commit(). ret == %lx\n", this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Revert, public
+//
+// Synopsis: No-op in current implementation
+//
+// Returns: Appropriate status code
+//
+// History: 16-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::Revert(void)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In CExposedStream::Revert()\n"));
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ //ASYNC Note: Don't need pending loop here.
+ sc = _pst->CheckReverted();
+ olDebugOut((DEB_TRACE, "Out CExposedStream::Revert\n"));
+ olLog(("%p::In CExposedStream::Revert()\n", this));
+ olLog(("%p::Out CExposedStream::Revert(). ret == %lx", this, sc));
+
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 26-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ olLog(("%p::In CExposedStream::QueryInterface(?, %p)\n",
+ this, ppvObj));
+ olDebugOut((DEB_TRACE, "In CExposedStream::QueryInterface(?, %p)\n",
+ ppvObj));
+
+ olChk(ValidateOutPtrBuffer(ppvObj));
+ *ppvObj = NULL;
+ olChk(ValidateIid(iid));
+ olChk(Validate());
+ olChk(_pst->CheckReverted());
+
+ sc = S_OK;
+ if (IsEqualIID(iid, IID_IStream) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IStream *)this;
+ AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IMarshal))
+ {
+ //If the ILockBytes we'd need to marshal doesn't support IMarshal
+ // then we want to do standard marshalling on the stream, mostly
+ // to prevent deadlock problems but also because you'll get better
+ // performance. So check, then do the right thing.
+
+ IMarshal *pim;
+ ILockBytes *plkb;
+ plkb = _ppc->GetOriginal();
+ if (plkb == NULL)
+ {
+ plkb = _ppc->GetBase();
+ }
+
+ sc = plkb->QueryInterface(IID_IMarshal, (void **)&pim);
+ if (FAILED(sc))
+ {
+ olErr(EH_Err, E_NOINTERFACE);
+ }
+ pim->Release();
+
+ *ppvObj = (IMarshal *)this;
+ AddRef();
+ }
+#ifdef ASYNC
+ else if (IsEqualIID(iid, IID_IConnectionPointContainer) &&
+ _cpoint.IsInitialized())
+ {
+ *ppvObj = (IConnectionPointContainer *)this;
+ CExposedStream::AddRef();
+ }
+#endif
+
+ else
+ sc = E_NOINTERFACE;
+
+ olDebugOut((DEB_TRACE, "Out CExposedStream::QueryInterface => %p\n",
+ ppvObj));
+EH_Err:
+ olLog(("%p::Out CExposedStream::QueryInterface(). "
+ "*ppvObj == %p, ret == %lx\n", this, *ppvObj, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Unmarshal, public
+//
+// Synopsis: Creates a duplicate stream from parts
+//
+// Arguments: [pstm] - Marshal stream
+// [ppv] - Object return
+// [mshlflags] - Marshal flags
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 26-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+SCODE CExposedStream::Unmarshal(IStream *pstm,
+ void **ppv,
+ DWORD mshlflags)
+{
+ SCODE sc;
+ CDfMutex mtx;
+ CPerContext *ppc;
+ CPubStream *pst;
+ CDFBasis *pdfb;
+ CGlobalContext *pgc;
+ CExposedStream *pest;
+ CSeekPointer *psp;
+#ifdef ASYNC
+ DWORD dwAsyncFlags;
+ IDocfileAsyncConnectionPoint *pdacp;
+#endif
+#ifdef POINTER_IDENTITY
+ CMarshalList *pml;
+#endif
+
+ olDebugOut((DEB_ITRACE, "In CExposedStream::Unmarshal(%p, %p, %lu)\n",
+ pstm, ppv, mshlflags));
+
+#ifdef MULTIHEAP
+ void *pvBaseOld;
+ void *pvBaseNew;
+ ContextId cntxid;
+ CPerContext pcSharedMemory (NULL); // bootstrap object
+#endif
+
+#if WIN32 == 100
+ olChk(DfCheckBaseAddress());
+#endif
+
+#ifdef MULTIHEAP
+ olChk(UnmarshalSharedMemory(pstm, mshlflags, &pcSharedMemory, &cntxid));
+ pvBaseOld = DFBASEPTR;
+#endif
+#ifdef POINTER_IDENTITY
+ olChkTo(EH_mem, UnmarshalPointer(pstm, (void **)&pest));
+#endif
+ olChkTo(EH_mem, UnmarshalPointer(pstm, (void **)&pst));
+ olChkTo(EH_mem, ValidateBuffer(pst, sizeof(CPubStream)));
+ olChkTo(EH_pst, UnmarshalPointer(pstm, (void **)&pdfb));
+ olChkTo(EH_pdfb, UnmarshalPointer(pstm, (void **)&psp));
+ olChkTo(EH_psp, UnmarshalPointer(pstm, (void **)&pgc));
+
+ //So far, nothing has called into the tree so we don't really need
+ // to be holding the tree mutex. The UnmarshalContext call does
+ // call into the tree, though, so we need to make sure this is
+ // threadsafe. We'll do this my getting the mutex name from the
+ // CGlobalContext, then creating a new CDfMutex object. While
+ // this is obviously not optimal, since it's possible we could
+ // reuse an existing CDfMutex, the reuse strategy isn't threadsafe
+ // since we can't do a lookup without the possibility of the thing
+ // we're looking for being released by another thread.
+ TCHAR atcMutexName[CONTEXT_MUTEX_NAME_LENGTH];
+ pgc->GetMutexName(atcMutexName);
+ olChkTo(EH_pgc, mtx.Init(atcMutexName));
+ olChkTo(EH_pgc, mtx.Take(INFINITE));
+
+ //At this point we're holding the mutex.
+#ifdef MULTIHEAP
+#ifdef ASYNC
+ olChkTo(EH_mtx, UnmarshalContext(pstm,
+ pgc,
+ &ppc,
+ mshlflags,
+ TRUE,
+ FALSE,
+ cntxid,
+ FALSE));
+#else
+ olChkTo(EH_mtx, UnmarshalContext(pstm,
+ pgc,
+ &ppc,
+ mshlflags,
+ FALSE,
+ cntxid,
+ FALSE));
+#endif
+ if ((pvBaseNew = DFBASEPTR) != pvBaseOld)
+ {
+ pst = (CPubStream*) ((UINT)pst - (UINT)pvBaseOld + (UINT)pvBaseNew);
+ pest = (CExposedStream*) ((UINT)pest-(UINT)pvBaseOld+(UINT)pvBaseNew);
+ pdfb = (CDFBasis*) ((UINT)pdfb - (UINT)pvBaseOld + (UINT)pvBaseNew);
+ psp = (CSeekPointer*) ((UINT)psp - (UINT)pvBaseOld + (UINT)pvBaseNew);
+ }
+#else
+#ifdef ASYNC
+ olChkTo(EH_mtx, UnmarshalContext(pstm,
+ pgc,
+ &ppc,
+ mshlflags,
+ TRUE,
+ FALSE,
+ FALSE));
+#else
+ olChkTo(EH_mtx, UnmarshalContext(pstm,
+ pgc,
+ &ppc,
+ mshlflags,
+ FALSE,
+ FALSE));
+#endif //ASYNC
+#endif
+#ifdef ASYNC
+ olChkTo(EH_ppc, UnmarshalConnection(pstm,
+ &dwAsyncFlags,
+ &pdacp,
+ mshlflags));
+#endif
+
+#ifdef POINTER_IDENTITY
+ olAssert (pest != NULL);
+ pml = (CMarshalList *) pest;
+
+ // Warning: these checks must remain valid across processes
+ if (SUCCEEDED(pest->Validate()) && pest->GetPub() == pst)
+ {
+ pest = (CExposedStream *) pml->FindMarshal(GetCurrentContextId());
+ }
+ else
+ {
+ pml = NULL;
+ pest = NULL;
+ }
+
+ if (pest == NULL)
+ {
+#endif
+ olMemTo(EH_ppc, pest = new (pdfb->GetMalloc()) CExposedStream);
+#ifdef ASYNC
+ olChkTo(EH_pest, pest->InitMarshal(pst,
+ pdfb,
+ ppc,
+ dwAsyncFlags,
+ pdacp,
+ TRUE,
+ psp));
+ //InitMarshal adds a reference on pdacp.
+ if (pdacp)
+ pdacp->Release();
+#else
+ olChkTo(EH_pest, pest->Init(pst, pdfb, ppc, TRUE, psp));
+#endif
+#ifdef POINTER_IDENTITY
+ if (pml) pml->AddMarshal(pest);
+ }
+ else
+ {
+ pdfb->SetAccess(ppc);
+ pest->AddRef(); // reuse this object
+ pst->vRelease(); // reuse public layer object
+ ppc->Release(); // reuse percontext
+ }
+#endif
+
+#ifdef DCOM
+ if (mshlflags == MSHLFLAGS_NORMAL)
+ {
+ // this was AddRef'd by the marshaler AND by CExposedStream::Init.
+ // we release one of those references now.
+ pdfb->vRelease();
+
+ // was AddRef'd by MarshalInterface but was only needed to find the
+ // ppc so we can Release it here.
+ pgc->Release();
+ }
+ else
+#endif
+ {
+ // unmarshaling from TABLE, add our own references.
+ pst->vAddRef();
+ psp->vAddRef();
+ }
+
+ *ppv = pest;
+#ifdef MULTIHEAP
+ if (pvBaseOld != pvBaseNew)
+ {
+ pcSharedMemory.SetThreadAllocatorState(NULL);
+ g_smAllocator.Uninit(); // delete the extra mapping
+ }
+ g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL);
+#endif
+
+ mtx.Release();
+
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::Unmarshal => %p\n", *ppv));
+ return S_OK;
+
+ EH_pest:
+ delete pest;
+ EH_ppc:
+ ppc->Release();
+ EH_mtx:
+ mtx.Release();
+#ifdef DCOM
+ EH_pgc:
+ if (mshlflags == MSHLFLAGS_NORMAL)
+ pgc->Release();
+ EH_psp:
+ if (mshlflags == MSHLFLAGS_NORMAL)
+ psp->vRelease();
+ EH_pdfb:
+ if (mshlflags == MSHLFLAGS_NORMAL)
+ pdfb->vRelease();
+ EH_pst:
+ if (mshlflags == MSHLFLAGS_NORMAL)
+ pst->vRelease();
+#else
+ EH_pgc:
+ EH_psp:
+ EH_pdfb:
+ EH_pst:
+#endif
+EH_mem:
+#ifdef MULTIHEAP
+ EH_Err:
+ pcSharedMemory.SetThreadAllocatorState(NULL);
+ g_smAllocator.Uninit(); // delete the file mapping in error case
+ g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL);
+#endif
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::GetUnmarshalClass, public
+//
+// Synopsis: Returns the class ID
+//
+// Arguments: [riid] - IID of object
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+// [pcid] - CLSID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcid]
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::GetUnmarshalClass(REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pcid)
+{
+ SCODE sc;
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ olLog(("%p::In CExposedStream::GetUnmarshalClass("
+ "riid, %p, %lu, %p, %lu, %p)\n",
+ this, pv, dwDestContext, pvDestContext, mshlflags, pcid));
+ olDebugOut((DEB_TRACE, "In CExposedStream::GetUnmarshalClass:%p("
+ "riid, %p, %lu, %p, %lu, %p)\n", this, pv, dwDestContext,
+ pvDestContext, mshlflags, pcid));
+
+ UNREFERENCED_PARM(pv);
+ UNREFERENCED_PARM(mshlflags);
+
+ olChk(ValidateOutBuffer(pcid, sizeof(CLSID)));
+ memset(pcid, 0, sizeof(CLSID));
+ olChk(ValidateIid(riid));
+ olChk(Validate());
+ olChk(_pst->CheckReverted());
+
+#if !defined(DCOM)
+ if (((dwDestContext != MSHCTX_LOCAL) &&
+ (dwDestContext != MSHCTX_INPROC)) ||
+ pvDestContext != NULL)
+#else
+ if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
+ {
+ IMarshal *pmsh;
+
+ if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
+ dwDestContext, pvDestContext,
+ mshlflags, &pmsh)))
+ {
+ sc = GetScode(pmsh->GetUnmarshalClass(riid, pv, dwDestContext,
+ pvDestContext, mshlflags,
+ pcid));
+ pmsh->Release();
+ }
+ }
+ else if (pvDestContext != NULL)
+#endif
+ {
+ sc = STG_E_INVALIDPARAMETER;
+ }
+ else
+ {
+ *pcid = CLSID_DfMarshal;
+ }
+
+ olDebugOut((DEB_TRACE, "Out CExposedStream::GetUnmarshalClass\n"));
+EH_Err:
+ olLog(("%p::Out CExposedStream::GetUnmarshalClass(). ret == %lx\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::GetMarshalSizeMax, public
+//
+// Synopsis: Returns the size needed for the marshal buffer
+//
+// Arguments: [riid] - IID of object being marshaled
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Marshal flags
+// [pcbSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbSize]
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::GetMarshalSizeMax(REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pcbSize)
+{
+ SCODE sc;
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ UNREFERENCED_PARM(pv);
+ olLog(("%p::In CExposedStream::GetMarshalSizeMax("
+ "riid, %p, %lu, %p, %lu, %p)\n",
+ this, pv, dwDestContext, pvDestContext, mshlflags, pcbSize));
+ olDebugOut((DEB_TRACE, "In CExposedStream::GetMarshalSizeMax:%p("
+ "riid, %p, %lu, %p, %lu, %p)\n", this, pv, dwDestContext,
+ pvDestContext, mshlflags, pcbSize));
+
+ olChk(Validate());
+ olChk(_pst->CheckReverted());
+
+#if !defined(DCOM)
+ if (((dwDestContext != MSHCTX_LOCAL) &&
+ (dwDestContext != MSHCTX_INPROC)) ||
+ pvDestContext != NULL)
+#else
+ if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
+ {
+ IMarshal *pmsh;
+
+ if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
+ dwDestContext, pvDestContext,
+ mshlflags, &pmsh)))
+ {
+ sc = GetScode(pmsh->GetMarshalSizeMax(riid, pv, dwDestContext,
+ pvDestContext, mshlflags,
+ pcbSize));
+ pmsh->Release();
+ }
+ }
+ else if (pvDestContext != NULL)
+#endif
+ {
+ sc = STG_E_INVALIDPARAMETER;
+ }
+ else
+ {
+ sc = GetStdMarshalSize(riid, IID_IStream, dwDestContext, pvDestContext,
+ mshlflags, pcbSize,
+ sizeof(CPubStream *)+sizeof(CDFBasis *)+
+ sizeof(CSeekPointer *),
+#ifdef ASYNC
+ &_cpoint,
+ TRUE,
+#endif
+ _ppc, FALSE);
+ }
+
+ olDebugOut((DEB_TRACE, "Out CExposedStream::GetMarshalSizeMax\n"));
+EH_Err:
+ olLog(("%p::Out CExposedStream::GetMarshalSizeMax(). *pcbSize == %lu, "
+ "ret == %lx\n", this, *pcbSize, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::MarshalInterface, public
+//
+// Synopsis: Marshals a given object
+//
+// Arguments: [pstStm] - Stream to write marshal data into
+// [riid] - Interface to marshal
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Marshal flags
+//
+// Returns: Appropriate status code
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::MarshalInterface(IStream *pstStm,
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ SCODE sc;
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ olLog(("%p::In CExposedStream::MarshalInterface("
+ "%p, riid, %p, %lu, %p, %lu). Context == %lX\n",
+ this, pstStm, pv, dwDestContext, pvDestContext,
+ mshlflags, (ULONG)GetCurrentContextId()));
+ olDebugOut((DEB_TRACE, "In CExposedStream::MarshalInterface:%p("
+ "%p, riid, %p, %lu, %p, %lu)\n", this, pstStm, pv,
+ dwDestContext, pvDestContext, mshlflags));
+
+ UNREFERENCED_PARM(pv);
+
+ olChk(Validate());
+ olChk(_pst->CheckReverted());
+
+#if !defined(DCOM)
+ if (((dwDestContext != MSHCTX_LOCAL) &&
+ (dwDestContext != MSHCTX_INPROC)) ||
+ pvDestContext != NULL)
+#else
+ if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
+ {
+ IMarshal *pmsh;
+
+ if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
+ dwDestContext, pvDestContext,
+ mshlflags, &pmsh)))
+ {
+ sc = GetScode(pmsh->MarshalInterface(pstStm, riid, pv,
+ dwDestContext, pvDestContext,
+ mshlflags));
+ pmsh->Release();
+ }
+ }
+ else if (pvDestContext != NULL)
+#endif
+ {
+ sc = STG_E_INVALIDPARAMETER;
+ }
+ else
+ {
+ olChk(StartMarshal(pstStm, riid, IID_IStream, mshlflags));
+#ifdef MULTIHEAP
+ olChk(MarshalSharedMemory(pstStm, _ppc));
+#endif
+#ifdef POINTER_IDENTITY
+ olChk(MarshalPointer(pstStm, (CExposedStream*) GetNextMarshal()));
+#endif
+ olChk(MarshalPointer(pstStm, BP_TO_P(CPubStream *, _pst)));
+ olChk(MarshalPointer(pstStm, BP_TO_P(CDFBasis *, _pdfb)));
+ olChk(MarshalPointer(pstStm, BP_TO_P(CSeekPointer *, _psp)));
+#ifdef ASYNC
+ olChk(MarshalContext(pstStm,
+ _ppc,
+ dwDestContext,
+ pvDestContext,
+ mshlflags,
+ TRUE,
+ FALSE));
+#else
+ olChk(MarshalContext(pstStm,
+ _ppc,
+ dwDestContext,
+ pvDestContext,
+ mshlflags,
+ FALSE));
+#endif
+
+#ifdef ASYNC
+ olChk(MarshalConnection(pstStm,
+ &_cpoint,
+ dwDestContext,
+ pvDestContext,
+ mshlflags));
+#endif
+ if (mshlflags != MSHLFLAGS_TABLEWEAK)
+ {
+ _pst->vAddRef();
+ _pdfb->vAddRef();
+ _psp->vAddRef();
+ }
+ }
+
+ olDebugOut((DEB_TRACE, "Out CExposedStream::MarshalInterface\n"));
+EH_Err:
+ olLog(("%p::Out CExposedStream::MarshalInterface(). ret == %lx\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::UnmarshalInterface, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [pstStm] -
+// [riid] -
+// [ppvObj] -
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::UnmarshalInterface(IStream *pstStm,
+ REFIID riid,
+ void **ppvObj)
+{
+ olLog(("%p::INVALID CALL TO CExposedStream::UnmarshalInterface()\n"));
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::StaticReleaseMarshalData, public static
+//
+// Synopsis: Releases any references held in marshal data
+//
+// Arguments: [pstStm] - Marshal data stream
+//
+// Returns: Appropriate status code
+//
+// History: 02-Feb-94 DrewB Created
+//
+// Notes: Assumes standard marshal header has already been read
+//
+//---------------------------------------------------------------
+
+
+SCODE CExposedStream::StaticReleaseMarshalData(IStream *pstStm,
+ DWORD mshlflags)
+{
+ SCODE sc;
+ CPubStream *pst;
+ CDFBasis *pdfb;
+ CSeekPointer *psp;
+#ifdef POINTER_IDENTITY
+ CExposedStream *pest;
+#endif
+
+ olDebugOut((DEB_ITRACE, "In CExposedStream::StaticReleaseMarshalData:("
+ "%p, %lX)\n", pstStm, mshlflags));
+
+#ifdef MULTIHEAP
+ ContextId cntxid;
+ CPerContext pcSharedMemory (NULL); // bootstrap object
+ olChk(UnmarshalSharedMemory(pstStm, mshlflags, &pcSharedMemory, &cntxid));
+#endif
+#ifdef POINTER_IDENTITY
+ olChk(UnmarshalPointer(pstStm, (void **) &pest));
+#endif
+ olChk(UnmarshalPointer(pstStm, (void **)&pst));
+ olChk(UnmarshalPointer(pstStm, (void **)&pdfb));
+ olChk(UnmarshalPointer(pstStm, (void **)&psp));
+#ifdef ASYNC
+ olChk(ReleaseContext(pstStm, TRUE, FALSE, mshlflags));
+ olChk(ReleaseConnection(pstStm, mshlflags));
+#else
+ olChk(ReleaseContext(pstStm, FALSE, mshlflags));
+#endif
+
+ if (mshlflags != MSHLFLAGS_TABLEWEAK)
+ {
+ pst->vRelease();
+ pdfb->vRelease();
+ psp->vRelease();
+ }
+
+ olDebugOut((DEB_ITRACE,
+ "Out CExposedStream::StaticReleaseMarshalData\n"));
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::ReleaseMarshalData, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [pstStm] - Stream
+//
+// Returns: Appropriate status code
+//
+// History: 18-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::ReleaseMarshalData(IStream *pstStm)
+{
+ SCODE sc;
+ DWORD mshlflags;
+ IID iid;
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ olLog(("%p::In CExposedStream::ReleaseMarshalData(%p)\n", this, pstStm));
+ olDebugOut((DEB_TRACE, "In CExposedStream::ReleaseMarshalData:%p(%p)\n",
+ this, pstStm));
+
+ olChk(Validate());
+ olChk(_pst->CheckReverted());
+ olChk(SkipStdMarshal(pstStm, &iid, &mshlflags));
+ olAssert(IsEqualIID(iid, IID_IStream));
+ sc = StaticReleaseMarshalData(pstStm, mshlflags);
+
+ olDebugOut((DEB_TRACE, "Out CExposedStream::ReleaseMarshalData\n"));
+EH_Err:
+ olLog(("%p::Out CExposedStream::ReleaseMarshalData(). ret == %lx\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::DisconnectObject, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [dwRevserved] -
+//
+// Returns: Appropriate status code
+//
+// History: 18-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::DisconnectObject(DWORD dwReserved)
+{
+ olLog(("%p::INVALID CALL TO CExposedStream::DisconnectObject()\n"));
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+#ifdef NEWPROPS
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::Open
+//
+// Synopsis: Opens mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes: Gets the size of the underlying stream and reads it
+// into memory so that it can be "mapped."
+//
+//--------------------------------------------------------------------
+
+VOID CExposedStream::Open(IN VOID *powner, LONG *phr)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ GetMappedStream().Open(powner, phr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::Close
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes: Does nothing because the object may be mapped in
+// another process.
+//
+//--------------------------------------------------------------------
+
+VOID CExposedStream::Close(OUT LONG *phr)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ GetMappedStream().Close(phr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::ReOpen
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes: Combined open and map.
+//
+//--------------------------------------------------------------------
+
+VOID CExposedStream::ReOpen(IN OUT VOID **ppv, OUT LONG *phr)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ GetMappedStream().ReOpen(ppv,phr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::Quiesce
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes: Meaningless for docfile mapped stream.
+//
+//--------------------------------------------------------------------
+
+VOID CExposedStream::Quiesce(VOID)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ GetMappedStream().Quiesce();
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::Map
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes: Return the address of the "mapping" buffer.
+//
+//--------------------------------------------------------------------
+
+VOID CExposedStream::Map(BOOLEAN fCreate, VOID **ppv)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ GetMappedStream().Map(fCreate, ppv);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::Unmap
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes: Unmapping is merely zeroing the pointer. We don't
+// flush because that's done explicitly by the
+// CPropertyStorage class.
+//
+//
+//--------------------------------------------------------------------
+
+VOID CExposedStream::Unmap(BOOLEAN fFlush, VOID **pv)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ GetMappedStream().Unmap(fFlush, pv);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::Flush
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+// Flush the memory property set to disk and commit it.
+//
+// Signals: HRESULT from IStream methods.
+//
+// Notes: Calls the shared memory buffer to do the actual flush
+// because that code path is shared with the "FlushBufferedData"
+// call for IStorage::Commit.
+//
+//--------------------------------------------------------------------
+
+VOID CExposedStream::Flush(OUT LONG *phr)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ GetMappedStream().Flush(phr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::GetSize
+//
+// Synopsis: Returns size of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//--------------------------------------------------------------------
+
+ULONG CExposedStream::GetSize(OUT LONG *phr)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ return GetMappedStream().GetSize(phr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::SetSize
+//
+// Synopsis: Sets size of "map." Called by
+// NtCreatePropertySet et al.
+//
+// Arguments: [cb] -- requested size.
+// [fPersistent] -- FALSE if expanding in-memory read-only image
+// [ppv] -- new mapped address.
+//
+// Signals: Not enough disk space.
+//
+// Notes: In a low memory situation we may not be able to
+// get the requested amount of memory. In this
+// case we must fall back on disk storage as the
+// actual map.
+//
+//--------------------------------------------------------------------
+
+VOID CExposedStream::SetSize(ULONG cb, BOOLEAN fPersistent, VOID **ppv, OUT LONG *phr)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ GetMappedStream().SetSize(cb, fPersistent, ppv, phr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::Lock
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+NTSTATUS CExposedStream::Lock(BOOLEAN fExclusive)
+{
+ SCODE sc;
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ if( SUCCEEDED( sc = TakeSem() ))
+ {
+ SetDifferentBasisAccess(_pdfb, _ppc);
+ return GetMappedStream().Lock(fExclusive);
+ }
+ else
+ {
+ olDebugOut((DEB_IERROR, "Couldn't take CExposedStream::Lock(%lx)\n", sc));
+ return (STATUS_LOCK_NOT_GRANTED);
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::Unlock
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+NTSTATUS CExposedStream::Unlock(VOID)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ NTSTATUS Status = GetMappedStream().Unlock();
+ ClearBasisAccess(_pdfb);
+ ReleaseSem(S_OK);
+ return Status;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::QueryTimeStamps
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+VOID CExposedStream::QueryTimeStamps(STATPROPSETSTG *pspss, BOOLEAN fNonSimple) const
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ GetMappedStream().QueryTimeStamps(pspss, fNonSimple);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::QueryModifyTime
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+BOOLEAN CExposedStream::QueryModifyTime(OUT LONGLONG *pll) const
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ return(GetMappedStream().QueryModifyTime(pll));
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::QuerySecurity
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+BOOLEAN CExposedStream::QuerySecurity(OUT ULONG *pul) const
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ return(GetMappedStream().QuerySecurity(pul));
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::IsWriteable
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+BOOLEAN CExposedStream::IsWriteable() const
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ return GetConstMappedStream().IsWriteable();
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::SetChangePending
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+#if DBGPROP
+BOOLEAN CExposedStream::SetChangePending(BOOLEAN f)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ return GetMappedStream().SetChangePending(f);
+}
+#endif
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::IsNtMappedStream
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+#if DBGPROP
+BOOLEAN CExposedStream::IsNtMappedStream(VOID) const
+{
+ return FALSE;
+}
+#endif
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::GetParentHandle
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+HANDLE CExposedStream::GetHandle(VOID) const
+{
+ return INVALID_HANDLE_VALUE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::SetModified
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+VOID CExposedStream::SetModified(VOID)
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ GetMappedStream().SetModified();
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CExposedStream::IsModified
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+BOOLEAN CExposedStream::IsModified(VOID) const
+{
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+
+ //return ((class CExposedStream*const)this)->GetMappedStream().IsModified();
+ return GetConstMappedStream().IsModified();
+}
+
+#endif
+
diff --git a/private/ole32/stg/exp/expst.hxx b/private/ole32/stg/exp/expst.hxx
new file mode 100644
index 000000000..b16f91404
--- /dev/null
+++ b/private/ole32/stg/exp/expst.hxx
@@ -0,0 +1,251 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: expst.hxx
+//
+// Contents: CExposedStream definition
+//
+// Classes: CExposedStream
+//
+// Functions:
+//
+// History: 28-Feb-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __EXPST_HXX__
+#define __EXPST_HXX__
+
+#include <dfmsp.hxx>
+#include <debug.hxx>
+#include "lock.hxx"
+#include <dfmem.hxx>
+
+#include <pbstream.hxx>
+#include <mrshlist.hxx>
+#include <astgconn.hxx>
+
+
+class CPubStream;
+class CPubMappedStream;
+
+class CDFBasis;
+interface ILockBytes;
+class CSeekPointer;
+SAFE_DFBASED_PTR(CBasedSeekPointerPtr, CSeekPointer);
+
+//+--------------------------------------------------------------
+//
+// Class: CExposedStream (est)
+//
+// Purpose: Public stream interface
+//
+// Interface: See below
+//
+// History: 28-Feb-92 PhilipLa Created.
+//
+//---------------------------------------------------------------
+
+
+interface CExposedStream: public IStream, public IMarshal, public CMallocBased
+#ifdef NEWPROPS
+, public CMappedStream
+#endif
+#ifdef POINTER_IDENTITY
+, public CMarshalList
+#endif
+#ifdef ASYNC
+, public CAsyncConnectionContainer
+#endif
+{
+public:
+ CExposedStream(void);
+ SCODE Init(CPubStream *pst,
+ CDFBasis *pdfb,
+ CPerContext *ppc,
+ BOOL fOwnContext,
+ CSeekPointer *psp);
+#ifdef ASYNC
+ SCODE InitMarshal(CPubStream *pst,
+ CDFBasis *pdfb,
+ CPerContext *ppc,
+ DWORD dwAsyncFlags,
+ IDocfileAsyncConnectionPoint *pdacp,
+ BOOL fOwnContext,
+ CSeekPointer *psp);
+#endif
+
+ ~CExposedStream(void);
+
+ // From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // IMarshal
+ STDMETHOD(GetUnmarshalClass)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID *ppv);
+ static SCODE StaticReleaseMarshalData(IStream *pstStm,
+ DWORD mshlflags);
+ STDMETHOD(ReleaseMarshalData)(IStream *pStm);
+ STDMETHOD(DisconnectObject)(DWORD dwReserved);
+
+ // New methods
+ STDMETHOD(Read)(VOID HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbRead);
+ STDMETHOD(Write)(VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ STDMETHOD(Seek)(LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition);
+ STDMETHOD(SetSize)(ULARGE_INTEGER cb);
+ STDMETHOD(CopyTo)(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(LockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+ STDMETHOD(Clone)(IStream **ppstm);
+
+ // CMappedStream methods
+#ifdef NEWPROPS
+ VOID Open(IN VOID *powner, OUT LONG *phr);
+ VOID Close(OUT LONG *phr);
+ VOID ReOpen(IN OUT VOID **ppv, OUT LONG *phr);
+ VOID Quiesce(VOID);
+ VOID Map(BOOLEAN fCreate, VOID **ppv);
+ VOID Unmap(BOOLEAN fFlush, VOID **pv);
+ VOID Flush(LONG *phr);
+ ULONG GetSize(LONG *phr);
+ VOID SetSize(ULONG cb, BOOLEAN fPersistent, VOID **ppv, LONG *phr);
+ NTSTATUS Lock(IN BOOLEAN fExclusive);
+ NTSTATUS Unlock(VOID);
+ VOID QueryTimeStamps(STATPROPSETSTG *pspss, BOOLEAN fNonSimple) const;
+ BOOLEAN QueryModifyTime(OUT LONGLONG *pll) const;
+ BOOLEAN QuerySecurity(OUT ULONG *pul) const;
+
+ BOOLEAN IsWriteable(VOID) const;
+ BOOLEAN IsModified(VOID) const;
+ VOID SetModified(VOID);
+ HANDLE GetHandle(VOID) const;
+#if DBGPROP
+ BOOLEAN SetChangePending(BOOLEAN fChangePending);
+ BOOLEAN IsNtMappedStream(VOID) const;
+#endif
+
+ inline CMappedStream & GetMappedStream(void) const;
+ inline const CMappedStream & GetConstMappedStream(void) const;
+#endif
+
+ inline SCODE Validate(void) const;
+ inline CPubStream *GetPub(void) const;
+
+ static SCODE Unmarshal(IStream *pstm,
+ void **ppv,
+ DWORD mshlflags);
+
+private:
+ SCODE CopyToWorker(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten);
+
+ CBasedPubStreamPtr _pst;
+ CBasedDFBasisPtr _pdfb;
+ CPerContext *_ppc;
+ BOOL _fOwnContext;
+ ULONG _sig;
+ LONG _cReferences;
+ CBasedSeekPointerPtr _psp;
+#ifdef NEWPROPS
+ CBasedMappedStreamPtr _pmapstm;
+#endif
+};
+
+SAFE_INTERFACE_PTR(SafeCExposedStream, CExposedStream);
+
+#define CEXPOSEDSTREAM_SIG LONGSIG('E', 'X', 'S', 'T')
+#define CEXPOSEDSTREAM_SIGDEL LONGSIG('E', 'x', 'S', 't')
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Validate, public
+//
+// Synopsis: Validates the object signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for bad signatures
+//
+// History: 17-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CExposedStream::Validate(void) const
+{
+ olChkBlocks((DBG_FAST));
+ return (this == NULL || _sig != CEXPOSEDSTREAM_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::GetPub, public
+//
+// Synopsis: Returns the public
+//
+// History: 28-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+inline CPubStream *CExposedStream::GetPub(void) const
+{
+#ifdef MULTIHEAP
+ // The tree mutex must be taken before calling this routine
+ // CSafeMultiHeap smh(_ppc); // optimization
+#endif
+ return BP_TO_P(CPubStream *, _pst);
+}
+
+#ifdef NEWPROPS
+inline CMappedStream & CExposedStream::GetMappedStream(void) const
+{
+ CMappedStream * p = BP_TO_P(CMappedStream *, _pmapstm);
+ return *p;
+}
+
+inline const CMappedStream & CExposedStream::GetConstMappedStream(void) const
+{
+ CMappedStream * p = BP_TO_P(CMappedStream *, _pmapstm);
+ return *p;
+}
+#endif
+
+#endif // #ifndef __EXPST_HXX__
diff --git a/private/ole32/stg/exp/filelist.mk b/private/ole32/stg/exp/filelist.mk
new file mode 100644
index 000000000..45ed73dca
--- /dev/null
+++ b/private/ole32/stg/exp/filelist.mk
@@ -0,0 +1,53 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1992 **
+#********************************************************************
+
+MKNAME = exp
+
+CXXFILES = \
+ .\docfile.cxx\
+ .\ascii.cxx\
+!if "$(OPSYS)" != "NT" # Not necessary for Cairo
+ .\dfguid.cxx\
+!endif
+ .\filest.cxx\
+!if "$(PLATFORM)" != "i286"
+ .\filest32.cxx\
+ .\time32.cxx\
+!else
+ .\filest16.cxx\
+ .\time16.cxx\
+!endif
+ .\context.cxx\
+ .\cntxlist.cxx\
+ .\lock.cxx\
+ .\marshl.cxx\
+ .\dfunmfct.cxx\
+ .\seekptr.cxx\
+ .\expst.cxx\
+ .\peiter.cxx\
+ .\expiter.cxx\
+!if "$(OPSYS)" == "NT" # Cairo only
+ .\props.cxx\
+ .\exppset.cxx\
+ .\exppiter.cxx\
+ .\exppsi.cxx\
+ .\expprop.cxx\
+ .\nmidmap.cxx\
+!endif
+ .\expdf.cxx\
+ .\logfile.cxx\
+ .\ptrcache.cxx\
+ .\storage.cxx
+
+!if "$(PLATFORM)" != "i286" && "$(OPSYS)" != "NT"
+# Non-Cairo 32-bit platforms need DLL initialization code
+CFILES = .\dllentry.c
+!endif
+
+!if "$(PLATFORM)" != "MAC"
+PXXFILE = .\exphead.cxx
+!endif
+
+!include $(CAIROLE)\stg\dfms.mk
diff --git a/private/ole32/stg/exp/filest.cxx b/private/ole32/stg/exp/filest.cxx
new file mode 100644
index 000000000..4a61c96f2
--- /dev/null
+++ b/private/ole32/stg/exp/filest.cxx
@@ -0,0 +1,954 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: filest.cxx
+//
+// Contents: Generic 16/32 filestream code
+//
+// History: 20-Nov-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <marshl.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::CFileStream, public
+//
+// Synopsis: Empty object constructor
+//
+// History: 26-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_CFS)
+#endif
+
+CFileStream::CFileStream(IMalloc * const pMalloc)
+ : _pMalloc(pMalloc)
+{
+ _cReferences = 1;
+ _hFile = INVALID_FH;
+ _hReserved = INVALID_FH;
+ _pgfst = NULL;
+ _grfLocal = 0;
+ _sig = CFILESTREAM_SIG;
+
+#if WIN32 == 100 || WIN32 > 200
+ _hMapObject = NULL;
+ _pbBaseAddr = NULL;
+ _cbFileSize = 0;
+#endif
+
+#ifdef WIN32
+ _ulLowPos = 0xffffffff;
+#if DBG == 1
+ _ulSeeks = 0;
+ _ulRealSeeks = 0;
+#endif
+#endif
+#ifdef ASYNC
+ _ppc = NULL;
+#endif
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::InitFlags, public
+//
+// Synopsis: Constructor for flags only
+//
+// Arguments: [dwStartFlags] - Startup flags
+// [df] - Permissions
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_InitFlags)
+#endif
+
+SCODE CFileStream::InitFlags(DWORD dwStartFlags,
+ DFLAGS df)
+{
+ SCODE sc = S_OK;
+ CGlobalFileStream *pgfstTemp;
+
+ olMem(pgfstTemp = new (_pMalloc) CGlobalFileStream(_pMalloc,
+ NULL, df, dwStartFlags));
+ _pgfst = P_TO_BP(CBasedGlobalFileStreamPtr, pgfstTemp);
+ _pgfst->Add(this);
+ // Fall through
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::InitFromGlobal, public
+//
+// Synopsis: Initializes a filestream with a global filestream
+//
+// Arguments: [pgfst] - Global object
+//
+// History: 26-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_InitFromGlobal)
+#endif
+
+void CFileStream::InitFromGlobal(CGlobalFileStream *pgfst)
+{
+ _pgfst = P_TO_BP(CBasedGlobalFileStreamPtr, pgfst);
+ _pgfst->AddRef();
+ _pgfst->Add(this);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::vRelease, public
+//
+// Synopsis: PubList support
+//
+// History: 19-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_vRelease)
+#endif
+
+ULONG CFileStream::vRelease(void)
+{
+ LONG lRet;
+ olDebugOut((DEB_ITRACE, "In CFileStream::vRelease:%p()\n", this));
+ olAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+#ifdef ASYNC
+ if (_ppc != NULL)
+ {
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ SCODE sc;
+ sc = TakeSem();
+ olAssert(SUCCEEDED(sc));
+ CPerContext *ppc = _ppc;
+
+ _ppc = NULL;
+ delete this;
+
+#ifdef MULTIHEAP
+ BOOL fLastRef = ppc->LastRef();
+#endif
+ ppc->ReleaseSharedMem();
+#ifdef MULTIHEAP
+ if (fLastRef)
+ g_smAllocator.Uninit();
+#endif
+ }
+ else
+#endif
+ delete this;
+ }
+ return (ULONG)lRet;
+ olDebugOut((DEB_ITRACE, "Out CFileStream::vRelease\n"));
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::Release, public
+//
+// Synopsis: Releases resources for an LStream
+//
+// Returns: Appropriate status code
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_Release)
+#endif
+
+STDMETHODIMP_(ULONG) CFileStream::Release(void)
+{
+ ULONG ulRet;
+
+ olDebugOut((DEB_ITRACE, "In CFileStream::Release()\n"));
+
+#ifdef CFS_SECURE
+ if (FAILED(Validate()) || _cReferences < 1)
+ return 0;
+#else
+ olAssert(_cReferences >= 1);
+#endif
+
+ ulRet = CFileStream::vRelease();
+
+ olDebugOut((DEB_ITRACE, "Out CFileStream::Release\n"));
+ return ulRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::AddRef, public
+//
+// Synopsis: Increases the ref count
+//
+// History: 27-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_AddRef)
+#endif
+
+STDMETHODIMP_(ULONG) CFileStream::AddRef(void)
+{
+ ULONG ulRet;
+
+ olDebugOut((DEB_ITRACE, "In CFileStream::AddRef()\n"));
+
+#ifdef CFS_SECURE
+ if (FAILED(Validate()))
+ return 0;
+#endif
+
+ CFileStream::vAddRef();
+ ulRet = _cReferences;
+
+ olDebugOut((DEB_ITRACE, "Out CFileStream::AddRef, %ld\n", _cReferences));
+ return ulRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::GetName, public
+//
+// Synopsis: Returns the internal path
+//
+// Arguments: [ppwcsName] - Name pointer return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppwcsName]
+//
+// History: 24-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_GetName)
+#endif
+
+SCODE CFileStream::GetName(WCHAR **ppwcsName)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CFileStream::GetName(%p)\n",
+ ppwcsName));
+ olAssert(_pgfst->HasName());
+ olChk(DfAllocWC(lstrlenW(_pgfst->GetName())+1, ppwcsName));
+ lstrcpyW(*ppwcsName, _pgfst->GetName());
+
+ olDebugOut((DEB_ITRACE, "Out CFileStream::GetName => %ws\n",
+ *ppwcsName));
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 26-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_QueryInterface)
+#endif
+
+STDMETHODIMP CFileStream::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CFileStream::QueryInterface(?, %p)\n",
+ ppvObj));
+
+#ifdef CFS_SECURE
+ olChk(ValidateOutPtrBuffer(ppvObj));
+ *ppvObj = NULL;
+ olChk(ValidateIid(iid));
+ olChk(Validate());
+#endif
+
+ sc = S_OK;
+ if (IsEqualIID(iid, IID_IFileLockBytes) ||
+ IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IFileLockBytes *)this;
+ CFileStream::vAddRef();
+ }
+ else if (IsEqualIID(iid, IID_ILockBytes))
+ {
+ *ppvObj = (ILockBytes *)this;
+ CFileStream::vAddRef();
+ }
+ else if (IsEqualIID(iid, IID_IMarshal))
+ {
+ *ppvObj = (IMarshal *)this;
+ CFileStream::vAddRef();
+ }
+#ifdef ASYNC
+ else if (IsEqualIID(iid, IID_IFillLockBytes))
+ {
+ *ppvObj = (IFillLockBytes *)this;
+ CFileStream::vAddRef();
+ }
+ else if (IsEqualIID(iid, IID_IFillInfo))
+ {
+ *ppvObj = (IFillInfo *)this;
+ CFileStream::vAddRef();
+ }
+#endif
+#if WIN32 >= 300
+ else if (IsEqualIID(iid, IID_IAccessControl))
+ {
+ DWORD grfMode = 0;
+ if (_pgfst->GetDFlags() & DF_TRANSACTED)
+ grfMode |= STGM_TRANSACTED;
+ if (_pgfst->GetDFlags() & DF_ACCESSCONTROL)
+ grfMode |= STGM_EDIT_ACCESS_RIGHTS;
+
+ // check if underlying file system supports security
+ if (SUCCEEDED(sc = InitAccessControl(_hFile, grfMode, TRUE, NULL)))
+ {
+ *ppvObj = (IAccessControl *) this;
+ CFileStream::vAddRef();
+ }
+ else sc = E_NOINTERFACE;
+ }
+#endif
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CFileStream::QueryInterface => %p\n",
+ ppvObj));
+#ifdef CFS_SECURE
+EH_Err:
+#endif
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::Unmarshal, public
+//
+// Synopsis: Creates a duplicate FileStream
+//
+// Arguments: [ptsm] - Marshal stream
+// [ppv] - New filestream return
+// [mshlflags] - Marshal flags
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 14-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_Unmarshal) // Marshal_Text
+#endif
+
+SCODE CFileStream::Unmarshal(IStream *pstm,
+ void **ppv,
+ DWORD mshlflags)
+{
+ SCODE sc;
+ WCHAR wcsPath[_MAX_PATH];
+ CFileStream *pfst;
+ CGlobalFileStream *pgfst;
+
+ olDebugOut((DEB_ITRACE, "In CFileStream::Unmarshal(%p, %p, %lu)\n",
+ pstm, ppv, mshlflags));
+
+#ifdef ASYNC
+ CPerContext pcSharedMemory(NULL);
+ CGlobalContext *pgc;
+ CPerContext *ppc;
+ ContextId cntxid;
+ CDfMutex mtx;
+
+ BOOL fIsAsync;
+ ULONG cbRead;
+ olChk(pstm->Read(&fIsAsync, sizeof(BOOL), &cbRead));
+ if (cbRead != sizeof(BOOL))
+ {
+ olErr(EH_Err, STG_E_READFAULT);
+ }
+
+
+ if (fIsAsync)
+ {
+#ifdef MULTIHEAP
+ olChk(UnmarshalSharedMemory(pstm,
+ mshlflags,
+ &pcSharedMemory,
+ &cntxid));
+#endif
+ olChkTo(EH_mem, UnmarshalPointer(pstm, (void **)&pgc));
+ TCHAR atcMutexName[CONTEXT_MUTEX_NAME_LENGTH];
+ pgc->GetMutexName(atcMutexName);
+ olChkTo(EH_pgc, mtx.Init(atcMutexName));
+ olChkTo(EH_pgc, mtx.Take(INFINITE));
+#ifdef MULTIHEAP
+ olChkTo(EH_mtx, UnmarshalContext(pstm,
+ pgc,
+ &ppc,
+ mshlflags,
+ FALSE,
+ FALSE,
+ cntxid,
+ FALSE));
+#else
+ olChkTo(EH_mtx, UnmarshalContext(pstm,
+ pgc,
+ &ppc,
+ mshlflags,
+ FALSE,
+ FALSE,
+ FALSE));
+#endif
+ olChkTo(EH_ppc, UnmarshalPointer(pstm, (void **)&pgfst));
+
+ pfst = pgfst->Find(GetCurrentContextId());
+ if (pfst)
+ {
+ pfst->AddRef();
+ // Demand scratch: If this is a scratch ILockBytes,
+ // it may need to be initialized, since a transacted
+ // storage above this object may have been opened
+ // after a direct root mode storage was marshaled
+ if (pgfst->HasName())
+ {
+ olChkTo(EH_pfst, pfst->InitUnmarshal(NULL));
+ }
+#ifdef DCOM
+ if (mshlflags == MSHLFLAGS_NORMAL)
+ {
+ pgc->Release();
+ }
+#endif
+ ppc->Release();
+ }
+ else
+ {
+ olMemTo(EH_pgfst,
+ pfst = new (pgfst->GetMalloc())
+ CFileStream(pgfst->GetMalloc()));
+ pfst->InitFromGlobal(pgfst);
+
+ if (pgfst->HasName())
+ {
+ lstrcpyW(wcsPath, pgfst->GetName());
+ olChkTo(EH_pfst, pfst->InitUnmarshal(wcsPath));
+ }
+ pfst->SetContext(ppc);
+
+ //We only need a reference on the shared mem portion of
+ // the per context, not the whole thing.
+ ppc->DecRef();
+#ifdef DCOM
+ if (mshlflags == MSHLFLAGS_NORMAL)
+ {
+ pgc->Release();
+ }
+#endif
+ }
+
+ mtx.Release();
+ }
+ else
+ {
+#endif
+
+ olChk(UnmarshalPointer(pstm, (void **)&pgfst));
+ pfst = pgfst->Find(GetCurrentContextId());
+ if (pfst)
+ {
+ pfst->AddRef();
+ // Demand scratch: If this is a scratch ILockBytes,
+ // it may need to be initialized, since a transacted
+ // storage above this object may have been opened
+ // after a direct mode root storage was marshaled
+ if (pgfst->HasName())
+ {
+ olChkTo(EH_pfst, pfst->InitUnmarshal(NULL));
+ }
+ }
+ else
+ {
+ olMemTo(EH_pgfst,
+ pfst = new (pgfst->GetMalloc())
+ CFileStream(pgfst->GetMalloc()));
+ pfst->InitFromGlobal(pgfst);
+
+ if (pgfst->HasName())
+ {
+ lstrcpyW(wcsPath, pgfst->GetName());
+ olChkTo(EH_pfst, pfst->InitUnmarshal(wcsPath));
+ }
+ }
+#ifdef ASYNC
+ }
+#endif
+ *ppv = (void *)pfst;
+
+ olDebugOut((DEB_ITRACE, "Out CFileStream::Unmarshal => %p\n", *ppv));
+
+ EH_pfst:
+ if (FAILED(sc))
+ pfst->Release();
+ EH_pgfst:
+#ifdef DCOM
+ if (mshlflags == MSHLFLAGS_NORMAL)
+ pgfst->Release();
+#endif
+#ifdef ASYNC
+ return sc;
+EH_ppc:
+ ppc->Release();
+EH_mtx:
+ mtx.Release();
+EH_pgc:
+ if (mshlflags == MSHLFLAGS_NORMAL)
+ {
+ pgc->Release();
+ }
+EH_mem:
+ //BUGBUG: Should we really be doing this?
+#ifdef MULTIHEAP
+ pcSharedMemory.SetThreadAllocatorState(NULL);
+ g_smAllocator.Uninit(); // delete the file mapping in error case
+ g_smAllocator.SetState(NULL, NULL, 0, NULL, NULL);
+#endif
+#endif //ASYNC
+ EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::GetUnmarshalClass, public
+//
+// Synopsis: Returns the class ID
+//
+// Arguments: [riid] - IID of object
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+// [pcid] - CLSID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcid]
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_GetUnmarshalClass)
+#endif
+
+STDMETHODIMP CFileStream::GetUnmarshalClass(REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pcid)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CFileStream::GetUnmarshalClass("
+ "riid, %p, %lu, %p, %lu, %p)\n", pv, dwDestContext,
+ pvDestContext, mshlflags, pcid));
+
+ UNREFERENCED_PARM(pv);
+ UNREFERENCED_PARM(mshlflags);
+
+#ifdef CFS_SECURE
+ olChk(ValidateOutBuffer(pcid, sizeof(CLSID)));
+ memset(pcid, 0, sizeof(CLSID));
+ olChk(ValidateIid(riid));
+ if (dwDestContext != 0 || pvDestContext != NULL)
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ olChk(Validate());
+#endif
+
+ *pcid = CLSID_DfMarshal;
+ sc = S_OK;
+
+ olDebugOut((DEB_ITRACE, "Out CFileStream::GetUnmarshalClass\n"));
+#ifdef CFS_SECURE
+EH_Err:
+#endif
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::GetMarshalSizeMax, public
+//
+// Synopsis: Returns the size needed for the marshal buffer
+//
+// Arguments: [iid] - IID of object being marshaled
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Marshal flags
+// [pcbSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbSize]
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_GetMarshalSizeMax)
+#endif
+
+STDMETHODIMP CFileStream::GetMarshalSizeMax(REFIID iid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pcbSize)
+{
+ SCODE sc;
+
+ UNREFERENCED_PARM(pv);
+ olChk(Validate());
+ sc = GetStdMarshalSize(iid, IID_ILockBytes, dwDestContext, pvDestContext,
+ mshlflags, pcbSize, sizeof(CFileStream *),
+#ifdef ASYNC
+ NULL,
+ FALSE,
+ _ppc,
+#else
+ NULL,
+#endif
+ FALSE);
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::MarshalInterface, public
+//
+// Synopsis: Marshals a given object
+//
+// Arguments: [pstStm] - Stream to write marshal data into
+// [iid] - Interface to marshal
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Marshal flags
+//
+// Returns: Appropriate status code
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_MarshalInterface)
+#endif
+
+STDMETHODIMP CFileStream::MarshalInterface(IStream *pstStm,
+ REFIID iid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ SCODE sc;
+#ifdef ASYNC
+ BOOL fIsAsync = (_ppc != NULL);
+#endif
+
+ olDebugOut((DEB_ITRACE, "In CFileStream::MarshalInterface("
+ "%p, iid, %p, %lu, %p, %lu)\n", pstStm, pv, dwDestContext,
+ pvDestContext, mshlflags));
+
+ UNREFERENCED_PARM(pv);
+
+#ifdef CFS_SECURE
+ if (dwDestContext != 0 || pvDestContext != NULL)
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ olChk(Validate());
+#endif
+
+#if WIN32 == 100 || WIN32 > 200
+ TurnOffMapping();
+#endif
+
+ olChk(StartMarshal(pstStm, iid, IID_ILockBytes, mshlflags));
+#ifdef ASYNC
+ ULONG cbWritten;
+ olHChk(pstStm->Write(&fIsAsync, sizeof(BOOL), &cbWritten));
+ if (cbWritten != sizeof(BOOL))
+ {
+ olErr(EH_Err, STG_E_WRITEFAULT);
+ }
+ if (fIsAsync)
+ {
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+ olChk(MarshalSharedMemory(pstStm, _ppc));
+#endif
+ olChk(MarshalContext(pstStm,
+ _ppc,
+ dwDestContext,
+ pvDestContext,
+ mshlflags,
+ FALSE,
+ FALSE));
+ olChk(MarshalPointer(pstStm, BP_TO_P(CGlobalFileStream *, _pgfst)));
+
+#ifdef WIN32
+ if (mshlflags != MSHLFLAGS_TABLEWEAK)
+ _pgfst->AddRef();
+#endif
+ }
+ else
+#endif
+ {
+ olChk(MarshalPointer(pstStm, BP_TO_P(CGlobalFileStream *, _pgfst)));
+
+#ifdef WIN32
+ if (mshlflags != MSHLFLAGS_TABLEWEAK)
+ _pgfst->AddRef();
+#endif
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CFileStream::MarshalInterface\n"));
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::UnmarshalInterface, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [pstStm] -
+// [iid] -
+// [ppvObj] -
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_UnmarshalInterface)
+#endif
+
+STDMETHODIMP CFileStream::UnmarshalInterface(IStream *pstStm,
+ REFIID iid,
+ void **ppvObj)
+{
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::StaticReleaseMarshalData, public static
+//
+// Synopsis: Releases any references held in marshal data
+//
+// Arguments: [pstStm] - Marshal data stream
+//
+// Returns: Appropriate status code
+//
+// History: 02-Feb-94 DrewB Created
+//
+// Notes: Assumes standard marshal header has already been read
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_ReleaseMarshalData)
+#endif
+
+#ifdef WIN32
+SCODE CFileStream::StaticReleaseMarshalData(IStream *pstStm,
+ DWORD mshlflags)
+{
+ SCODE sc;
+ CGlobalFileStream *pgfst;
+
+ olDebugOut((DEB_ITRACE, "In CFileStream::StaticReleaseMarshalData:("
+ "%p, %lX)\n", pstStm, mshlflags));
+#ifdef ASYNC
+ BOOL fIsAsync;
+ ULONG cbRead;
+ olChk(pstStm->Read(&fIsAsync, sizeof(BOOL), &cbRead));
+ if (cbRead != sizeof(BOOL))
+ {
+ olErr(EH_Err, STG_E_READFAULT);
+ }
+
+ if (fIsAsync)
+ {
+#ifdef MULTIHEAP
+ ContextId cntxid;
+ CPerContext pcSharedMemory(NULL); // bootstrap object
+ olChk(UnmarshalSharedMemory(pstStm,
+ mshlflags,
+ &pcSharedMemory,
+ &cntxid));
+#endif
+ olChk(ReleaseContext(pstStm, FALSE, FALSE, mshlflags));
+ }
+#endif
+ olChk(UnmarshalPointer(pstStm, (void **)&pgfst));
+ if (mshlflags != MSHLFLAGS_TABLEWEAK)
+ pgfst->Release();
+
+ olDebugOut((DEB_ITRACE, "Out CFileStream::StaticReleaseMarshalData\n"));
+EH_Err:
+ return sc;
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::ReleaseMarshalData, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [pstStm] -
+//
+// Returns: Appropriate status code
+//
+// History: 18-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_ReleaseMarshalData)
+#endif
+
+#ifdef WIN32
+STDMETHODIMP CFileStream::ReleaseMarshalData(IStream *pstStm)
+{
+ SCODE sc;
+ DWORD mshlflags;
+ IID iid;
+
+ olDebugOut((DEB_ITRACE, "In CFileStream::ReleaseMarshalData:%p(%p)\n",
+ this, pstStm));
+
+#ifdef CFS_SECURE
+ olChk(Validate());
+#endif
+
+ olChk(SkipStdMarshal(pstStm, &iid, &mshlflags));
+ olAssert(IsEqualIID(iid, IID_ILockBytes));
+ sc = StaticReleaseMarshalData(pstStm, mshlflags);
+
+ olDebugOut((DEB_ITRACE, "Out CFileStream::ReleaseMarshalData\n"));
+EH_Err:
+ return ResultFromScode(sc);
+}
+#else
+STDMETHODIMP CFileStream::ReleaseMarshalData(IStream *pstStm)
+{
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::DisconnectObject, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [dwReserved] -
+//
+// Returns: Appropriate status code
+//
+// History: 18-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_DisconnectObject) // invalid
+#endif
+
+STDMETHODIMP CFileStream::DisconnectObject(DWORD dwReserved)
+{
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::GetLocksSupported, public
+//
+// Synopsis: Return lock capabilities
+//
+// Arguments: [pdwLockFlags] -- place holder for lock flags
+//
+// Returns: Appropriate status code
+//
+// History: 12-Jul-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_GetLocksSupported)
+#endif
+
+STDMETHODIMP CFileStream::GetLocksSupported(DWORD *pdwLockFlags)
+{
+ *pdwLockFlags = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
+ return(ResultFromScode(S_OK));
+}
diff --git a/private/ole32/stg/exp/filest16.cxx b/private/ole32/stg/exp/filest16.cxx
new file mode 100644
index 000000000..f415c858c
--- /dev/null
+++ b/private/ole32/stg/exp/filest16.cxx
@@ -0,0 +1,1732 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: filest.cxx
+//
+// Contents: x86 DOS FAT LStream implementation
+//
+// History: 20-Nov-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <fcntl.h>
+#include <sys\types.h>
+#include <sys\stat.h>
+#include <share.h>
+#include <dos.h>
+#include <io.h>
+
+#include <marshl.hxx>
+#include <time16.hxx>
+#include <dfdeb.hxx>
+
+// #define CFSLOG // Use to log file operations
+#include <logfile.hxx>
+
+#define DEBOUT_FILEST
+
+#ifdef DEBOUT_FILEST
+#define olFileStOut(x) olDebugOut(x)
+#else
+#define olFileStOut(x)
+#endif
+
+#define hfChk(e) if ((e) == HFILE_ERROR) olErr(EH_Err, STG_E_UNKNOWN) else 1
+#define hfChkTo(l, e) \
+ if ((e) == HFILE_ERROR) olErr(l, STG_E_UNKNOWN) else 1
+#define negChk(e) if ((e) == (ULONG)-1) olErr(EH_Err, STG_E_UNKNOWN) else 1
+#define negChkTo(l, e) \
+ if ((e) == (ULONG)-1) olErr(l, STG_E_UNKNOWN) else 1
+
+// Number of characters in a volume name (non-null terminated)
+#define CCH_VOLUME 11
+
+//+---------------------------------------------------------------------------
+//
+// Function: DosDup, private
+//
+// Synopsis: Duplicates a DOS file handle
+//
+// Arguments: [fh] - Existing handle
+//
+// Returns: New handle or INVALID_FH
+//
+// History: 22-Feb-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_DosDup)
+#endif
+
+int DosDup(int fh)
+{
+ int nfh;
+
+ __asm
+ {
+ mov nfh, INVALID_FH
+ mov bx, fh
+ mov ah, 45h
+ clc
+ int 21h
+ jc dup_fail
+ mov nfh, ax
+ dup_fail:
+ }
+ return nfh;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DosGetSectorSize, private
+//
+// Synopsis: Retrieve the sector size for a disk
+//
+// Arguments: [fh] - File handle of file on disk
+// [pcbSector] - Sector size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbSector]
+//
+// History: 27-Feb-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_DosGetSectorSize)
+#endif
+
+SCODE DosGetSectorSize(int fh, WORD *pcbSector)
+{
+ int iDrive, iRt;
+ SCODE sc = S_OK;
+
+ olAssert(fh >= 0);
+
+ // Get drive number from file handle
+ __asm
+ {
+ mov bx, fh
+ mov ax, 4400h
+ mov iRt, 0
+ clc
+ int 21h
+ mov iDrive, dx
+ jnc drive_succ
+ mov iRt, ax
+ drive_succ:
+ }
+ if (iRt != 0)
+ olErr(EH_Err, STG_SCODE(iRt));
+
+ iDrive = (iDrive & 0x3f)+1;
+
+ // Get sector size
+ __asm
+ {
+ mov ah, 36h
+ mov dl, BYTE PTR iDrive
+ int 21h
+ mov iRt, cx
+ cmp ax, 0ffffh
+ jne secsize_succ
+ mov iRt, 0
+ secsize_succ:
+ }
+ if (iRt == 0)
+ sc = STG_E_READFAULT;
+ else
+ *pcbSector = iRt;
+
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DosGetVolumeInfo, private
+//
+// Synopsis: Gets the volume info for a file handle
+//
+// Arguments: [fh] - File handle
+// [cbSector] - Size of a sector on disk
+// [pchVolume] - Name return
+// [pdwId] - Volume Id return (if proper version)
+// [fCheck] - Whether this is for init for for check
+//
+// Returns: Appropriate status code
+//
+// History: 24-Feb-93 DrewB Created
+// 27-Jan-94 PhilipLa Changed boot sector code
+// to work on DOS 3
+//
+// Note: Please refer to the MS-DOS Programmer's Reference for
+// an explanation of where this information comes from
+// and what all the ugly assembly does.
+//
+// fCheck controls whether this function considers certain
+// types of failure fatal or not. The volume ID check
+// requires a sector-sized buffer which is dynamically
+// allocated. If you are initializing you want this
+// function to fail if it can't get the memory and you
+// don't if you're just checking. In the checking,
+// no-memory case pdwId is *untouched*. This means
+// that you can set *pdwId to your cached ID and call
+// this function for checking. If it couldn't get
+// memory, your ID is unchanged so a comparison will
+// show equality, which what you generally want.
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_DosGetVolumeInfo)
+#endif
+
+SCODE DosGetVolumeInfo(int fh, WORD cbSector,
+ char *pchVolume, DWORD *pdwId, BOOL fCheck)
+{
+ SCODE sc = S_OK;
+ int iRt, iDrive;
+ BYTE extFCB[44] = {0xff, 0, 0, 0, 0, 0, _A_VOLID, 0,
+ '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?'};
+ BYTE dta[64];
+
+ olAssert(fh >= 0);
+
+ // Get drive number from file handle
+ __asm
+ {
+ mov bx, fh
+ mov ax, 4400h
+ mov iRt, 0
+ clc
+ int 21h
+ mov iDrive, dx
+ jnc drive_succ
+ mov iRt, ax
+ drive_succ:
+ }
+ if (iRt != 0)
+ olErr(EH_Err, STG_SCODE(iRt));
+
+ iDrive = iDrive & 0x3f;
+ extFCB[7] = iDrive+1;
+
+ // Try to get a volume label
+ __asm
+ {
+ //Preserve registers
+ push ds
+ push es
+
+ //Save address of current DTA on stack
+ mov ah, 2fh
+ int 21h
+ push es
+ push bx
+
+ //Set DTA to point to our buffer
+ mov ax, ss
+ mov ds, ax
+ lea dx, dta
+ mov ah, 1ah
+ int 21h
+
+ //Read volume info
+ lea dx, extFCB
+ mov ah, 11h
+ mov iRt, 0
+ clc
+ int 21h
+
+ //Set up error return
+ xor ah,ah
+ mov iRt, ax
+
+ //Restore original DTA
+ pop dx
+ pop ds
+ mov ah, 1ah
+ int 21h
+
+ //Restore registers
+ pop es
+ pop ds
+ }
+ if (iRt == 0)
+ memcpy(pchVolume, dta+8, CCH_VOLUME);
+ else
+ memset(pchVolume, 0, CCH_VOLUME);
+
+ // Try to get a volume ID
+ BYTE *pbSector;
+
+ //NOTE: Allocate twice the amount we think we need to get around
+ // a DOS/J bug. Bleah.
+ pbSector = (BYTE *) DfMemAlloc(cbSector * 2);
+ if (pbSector != NULL)
+ {
+ // Default ID return
+ *pdwId = 0;
+
+ *(WORD *)pbSector = 0;
+ pbSector[0x26] = 0;
+ __asm
+ {
+ //Set return code
+ mov iRt, 0
+
+ //Save everything that might need saving
+ push bp
+ push si
+ push di
+ push ds
+
+ //Make the call:
+ // CX == Number of sectors to read
+ // DX == Logical sector to read
+ // DS:BX == Buffer to read into
+ // AL == Drive number
+ mov cx, 01h
+ mov dx, 00h
+ mov ax, WORD PTR pbSector + 2
+ mov ds, ax
+ mov bx, WORD PTR pbSector
+ mov al, BYTE PTR iDrive
+ clc
+ int 25h
+
+ //int 25h leaves garbage on the stack - get rid of it.
+ add sp,2
+
+ //Restore everything we saved before
+ pop ds
+ pop di
+ pop si
+ pop bp
+
+ jnc volid_succ
+ mov iRt, 1
+ volid_succ:
+ }
+
+ if (iRt == 0)
+ {
+ // We read the sector successfully, now check
+ // and see if we understand it
+ if (pbSector[0] == 0xe9 ||
+ (pbSector[0] == 0xeb && pbSector[2] == 0x90) &&
+ pbSector[0x26] == 0x29)
+ *pdwId = *(DWORD *)(pbSector+0x27);
+ }
+ else
+ // Bad sector read
+ sc = STG_E_READFAULT;
+ DfMemFree(pbSector);
+ }
+ else if (!fCheck)
+ sc = STG_E_INSUFFICIENTMEMORY;
+
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::CheckIdentity, private
+//
+// Synopsis: Attempts to verify that the open file handle
+// refers to the same file
+//
+// Returns: Appropriate status code
+//
+// Algorithm: If tick count < delta then succeeded.
+// Otherwise, DosGetVolumeInfo.
+// If volume is different or volume ID
+// is different, fail. If both are the same, then
+// try _access on the file. If access succeeds
+// succeed.
+//
+// History: 24-Feb-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_CheckIdentity)
+#endif
+
+// Set delta in milliseconds
+#define TICK_DELTA 2000
+
+SCODE CFileStream::CheckIdentity(void)
+{
+ char achVolume[CCH_VOLUME];
+ DWORD dwVolId;
+ SCODE sc = S_OK;
+ DWORD dwTicks;
+
+ dwTicks = GetTickCount();
+ if (dwTicks >= _dwTicks && (dwTicks-_dwTicks) <= TICK_DELTA)
+ return S_OK;
+
+ dwVolId = _dwVolId;
+ olChk(DosGetVolumeInfo(_hFile, _cbSector, achVolume, &dwVolId, TRUE));
+
+ sc = STG_E_INVALIDHANDLE;
+ if (memcmp(_achVolume, achVolume, CCH_VOLUME) == 0 && _dwVolId == dwVolId)
+ {
+ char achOemName[_MAX_PATH];
+
+ AnsiToOem(_pgfst->GetName(), achOemName);
+ if (_access(achOemName, 0) == 0)
+ sc = S_OK;
+ }
+
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetWinTempFile, private
+//
+// Synopsis: Attempts to create a temporary file in the Windows directory
+//
+// Arguments: [pszPrefix] - Prefix of temp file
+// [pszPath] - Path return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pszPath]
+//
+// History: 29-Jul-93 DrewB Created
+//
+// Notes: Actually creates the file if succesful
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_GetWinTempFile)
+#endif
+
+// Number of retries before failure
+#define CTRIES 10
+
+SCODE GetWinTempFile(char *pszPrefix, char *pszPath)
+{
+ UINT uiRc;
+ int cch;
+ SCODE sc;
+ HFILE hf;
+ WORD wRnd;
+ int cTry;
+
+ uiRc = GetWindowsDirectory(pszPath, _MAX_PATH);
+ if (uiRc == 0 || uiRc > _MAX_PATH)
+ olErr(EH_Err, STG_E_UNKNOWN);
+
+ // Make sure it ends with a backslash
+ cch = strlen(pszPath);
+ if (*AnsiPrev(pszPath, pszPath+cch) != '\\')
+ {
+ pszPath[cch++] = '\\';
+ pszPath[cch] = 0;
+ }
+
+ // Generate a "random" value from the current time
+ wRnd = (WORD)(GetTickCount() & 0xffff);
+
+ cTry = 0;
+ sc = STG_E_TOOMANYOPENFILES;
+ while (cTry < CTRIES)
+ {
+ sprintf(pszPath+cch, "~%s%04x.tmp", pszPrefix, wRnd);
+
+ // Check for a previously existing file
+ // If nothing exists, see if we can create it
+ if (_access(pszPath, 0) != 0 &&
+ (hf = _lcreat(pszPath, 0)) != HFILE_ERROR)
+ {
+ _lclose(hf);
+ sc = S_OK;
+ break;
+ }
+
+ cTry++;
+
+ // Jumble the number before trying again
+ wRnd ^= (WORD)((GetTickCount() & 0xffff)+cTry);
+ }
+
+EH_Err:
+#if DBG == 1
+ if (FAILED(sc))
+ olDebugOut((DEB_IERROR,"GetWinTempFile returned %lx\n",sc));
+#endif
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::Init, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [pwcsPath] - Path, NULL creates a temporary name
+//
+// Returns: Appropriate status code
+//
+// History: 20-Feb-92 DrewB Created
+//
+// Notes: This Init function does more than the usual init
+// function. Rather than construct an invalid object,
+// this also can construct a fully or partially
+// constructed object. For fully constructed objects,
+// nothing is done other than return. In all other cases,
+// as much construction is done as is necessary. This
+// allows us to do lazy construction of filestream by
+// simply calling Init on a filestream that we want
+// lazily constructed. An initial new'ed filestream
+// will be fully constructed and later Init's will
+// do nothing.
+//
+// [pwcsPath] may be unsafe memory but since this is 16-bit
+// it has already been validated
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_Init) // CFS_Init
+#endif
+
+SCODE CFileStream::Init(WCHAR const *pwcsPath)
+{
+ char szPath[_MAX_PATH+1];
+ SCODE sc;
+ int iOpenMode;
+ OFSTRUCT of;
+ DWORD dwStartFlags;
+ BOOL fSetName = FALSE;
+ BOOL fCreated = FALSE;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::Init(%ws)\n", pwcsPath));
+
+ // If we've already been constructed, leave
+ if (_hFile != INVALID_FH)
+ return S_OK;
+
+ // If we don't have a name, get one
+ if (!_pgfst->HasName())
+ {
+ // File hasn't been opened yet, so use the start flags
+ dwStartFlags = _pgfst->GetStartFlags();
+
+ if (pwcsPath == NULL)
+ {
+ char szOemPath[_MAX_PATH+1];
+ HFILE hf;
+
+ // Can't truncate since for temporary files we will
+ // always be creating
+ olAssert((dwStartFlags & RSF_TRUNCATE) == 0);
+
+ GetTempFileName(0, "DFT", 0, szOemPath);
+ if ((hf = _lcreat(szOemPath, 0)) != HFILE_ERROR)
+ {
+ _lclose(hf);
+ }
+ else
+ {
+ olChk(GetWinTempFile("DFT", szOemPath));
+ }
+ OemToAnsi(szOemPath, szPath);
+
+ // We created the temp file, so we just want to open it
+ dwStartFlags = (dwStartFlags & ~RSF_CREATE) | RSF_OPEN;
+ }
+ else
+ {
+ if (wcstombs(szPath, pwcsPath, _MAX_PATH) == (size_t)-1)
+ olErr(EH_Err, STG_E_INVALIDNAME);
+ }
+ _pgfst->SetName(szPath);
+ fSetName = TRUE;
+ }
+ else
+ {
+ // Use the name somebody else gave us
+ strcpy(szPath, _pgfst->GetName());
+
+ // File has already been started, so just open it
+ dwStartFlags = (_pgfst->GetStartFlags() & ~RSF_CREATEFLAGS) | RSF_OPEN;
+ }
+
+ // Open the file
+ if (!P_WRITE(_pgfst->GetDFlags()))
+ iOpenMode = OF_READ;
+ else
+ iOpenMode = OF_READWRITE;
+ if (P_DENYWRITE(_pgfst->GetDFlags()) && !P_WRITE(_pgfst->GetDFlags()))
+ iOpenMode |= OF_SHARE_DENY_WRITE;
+ else
+ iOpenMode |= OF_SHARE_DENY_NONE;
+
+ // Make sure we're not attempting to create/truncate a read-only thing
+ olAssert(iOpenMode != OF_READ ||
+ !(dwStartFlags & (RSF_CREATE | RSF_TRUNCATE)));
+
+ _hFile = OpenFile(szPath, &of, iOpenMode);
+ if (dwStartFlags & RSF_CREATE)
+ {
+ if (_hFile < 0)
+ _hFile = OpenFile(szPath, &of, iOpenMode | OF_CREATE);
+ else if (((dwStartFlags & RSF_TRUNCATE) == 0) &&
+ ((dwStartFlags & RSF_OPENCREATE) == 0))
+ olErr(EH_hFile, STG_E_FILEALREADYEXISTS);
+ if (_hFile < 0)
+ {
+ olErr(EH_Path, STG_SCODE(of.nErrCode));
+ }
+ else
+ {
+ olVerify(_lclose(_hFile) != HFILE_ERROR);
+ _hFile = OpenFile(szPath, &of, iOpenMode);
+ fCreated = TRUE;
+ }
+ }
+ if (_hFile < 0)
+ olErr(EH_Path, STG_SCODE(of.nErrCode));
+
+ //Check to see if this name is a device - if it is, return
+ // STG_E_INVALIDNAME
+
+ if (pwcsPath != NULL)
+ {
+ //We only need to check if the user passed in the name.
+ int iRetval;
+ int fd = _hFile;
+ __asm
+ {
+ mov ax, 4400h
+ mov bx, fd
+ int 21h
+ mov iRetval, dx
+ }
+ if (iRetval & 0x80)
+ {
+ //We are a device, so we couldn't have created this
+ // handle. Reset fCreated so we don't try to delete
+ // the device name in the cleanup path.
+ fCreated = FALSE;
+ olErr(EH_hFile, STG_E_INVALIDNAME);
+ }
+ }
+
+
+ // Set name to fully qualified path return in OFSTRUCT
+ // This removes any current-directory dependencies in the name
+ if (fSetName)
+ OemToAnsi(of.szPathName, _pgfst->GetName());
+
+ if (dwStartFlags & RSF_TRUNCATE)
+ {
+ hfChkTo(EH_hFile, _llseek(_hFile, 0, STREAM_SEEK_SET));
+ hfChkTo(EH_hFile, _lwrite(_hFile, szPath, 0));
+ }
+
+ _fFixedDisk = of.fFixedDisk;
+ if (!_fFixedDisk)
+ {
+ // These errors are not critical errors - if either of
+ // the following calls fail, we just turn off the floppy
+ // checking.
+
+ sc = DosGetSectorSize(_hFile, &_cbSector);
+ if (SUCCEEDED(sc))
+ {
+ sc = DosGetVolumeInfo(
+ _hFile,
+ _cbSector,
+ _achVolume,
+ &_dwVolId,
+ FALSE);
+ }
+
+ if (FAILED(sc))
+ {
+ _fFixedDisk = TRUE;
+ }
+
+ }
+
+ if (!_fFixedDisk)
+ _dwTicks = GetTickCount();
+
+ olFileStOut((DEB_ITRACE, "Out CFileStream::Init\n"));
+ return S_OK;
+
+ EH_hFile:
+ olVerify(_lclose(_hFile) != HFILE_ERROR);
+ _hFile = INVALID_FH;
+ if (fCreated)
+ OpenFile(szPath, &of, OF_DELETE);
+ EH_Path:
+ if (fSetName)
+ _pgfst->SetName(NULL);
+ EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::~CFileStream, public
+//
+// Synopsis: Destructor
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_1CFS) // CFS_Shutdown
+#endif
+
+CFileStream::~CFileStream(void)
+{
+#ifdef FULL_CHECK_IDENTITY
+ SCODE scIdentity;
+#endif
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::~CFileStream()\n"));
+ olAssert(_cReferences == 0);
+ _sig = CFILESTREAM_SIGDEL;
+
+#ifdef FULL_CHECK_IDENTITY
+ if (_fFixedDisk || _hFile == INVALID_FH ||
+ SUCCEEDED(scIdentity = CheckIdentity()))
+ {
+#endif
+ if (_hFile >= 0)
+ olVerify(_lclose(_hFile) != HFILE_ERROR);
+ if (_hReserved >= 0)
+ olVerify(_lclose(_hReserved) != HFILE_ERROR);
+#ifdef FULL_CHECK_IDENTITY
+ }
+#endif
+ if (_pgfst)
+ {
+ _pgfst->Remove(this);
+ if (_pgfst->HasName())
+ {
+ if (_pgfst->GetRefCount() == 1)
+ {
+ if ((_pgfst->GetStartFlags() & RSF_DELETEONRELEASE)
+#ifdef FULL_CHECK_IDENTITY
+ && (_fFixedDisk || _hFile == INVALID_FH ||
+ SUCCEEDED(scIdentity))
+#endif
+ )
+ {
+ OFSTRUCT of;
+
+ // This is allowed to fail if somebody else has
+ // the file open
+ OpenFile(_pgfst->GetName(), &of, OF_DELETE);
+ }
+ }
+ }
+ _pgfst->Release();
+ }
+
+ olFileStOut((DEB_ITRACE, "Out CFileStream::~CFileStream\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::ReadAt, public
+//
+// Synopsis: Reads bytes at a specific point in a stream
+//
+// Arguments: [ulPosition] - Offset in file to read at
+// [pb] - Buffer
+// [cb] - Count of bytes to read
+// [pcbRead] - Return of bytes read
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_ReadAt) //
+#endif
+
+STDMETHODIMP CFileStream::ReadAt(ULARGE_INTEGER ulPosition,
+ VOID HUGEP *pb,
+ ULONG cb,
+ ULONG *pcbRead)
+{
+ SCODE sc;
+ ULONG cbRead = 0;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::ReadAt(%lu, %p, %lu, %p)\n",
+ ULIGetLow(ulPosition), pb, cb, pcbRead));
+#ifdef CFS_SECURE
+ TRY
+ {
+ if (pcbRead)
+ {
+ olChk(ValidateOutBuffer(pcbRead, sizeof(ULONG)));
+#endif
+ *pcbRead = 0;
+#ifdef CFS_SECURE
+ }
+ olChk(ValidateHugeOutBuffer(pb, cb));
+ olChk(Validate());
+ olChk(CheckHandle());
+#else
+ olAssert(_hFile != INVALID_FH);
+#endif
+ if (!_fFixedDisk)
+ olChk(CheckIdentity());
+ olAssert(ULIGetHigh(ulPosition) == 0);
+ hfChk(_llseek(_hFile, (LONG)ULIGetLow(ulPosition), STREAM_SEEK_SET));
+ negChk(cbRead = _hread(_hFile, pb, (long)cb));
+ if (pcbRead)
+ *pcbRead = cbRead;
+#ifdef CFS_SECURE
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+#else
+ sc = S_OK;
+#endif
+ if (!_fFixedDisk)
+ _dwTicks = GetTickCount();
+ olFileStOut((DEB_ITRACE, "Out CFileStream::ReadAt => %lu\n", cbRead));
+EH_Err:
+
+#ifdef CFSLOG
+ olLog(("%p CFS::ReadAt(%ld, %ld), cbRead = %ld, sc = %lx\n",
+ this, ULIGetLow(ulPosition), cb, cbRead, sc));
+#endif
+
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::WriteAt, public
+//
+// Synopsis: Writes bytes at a specific point in a stream
+//
+// Arguments: [ulPosition] - Offset in file
+// [pb] - Buffer
+// [cb] - Count of bytes to write
+// [pcbWritten] - Return of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbWritten]
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_WriteAt)
+#endif
+
+STDMETHODIMP CFileStream::WriteAt(ULARGE_INTEGER ulPosition,
+ VOID const HUGEP *pb,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ SCODE sc;
+ ULONG cbWritten = 0;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::WriteAt(%lu, %p, %lu, %p)\n",
+ ULIGetLow(ulPosition), pb, cb, pcbWritten));
+#ifdef CFS_SECURE
+ TRY
+ {
+ if (pcbWritten)
+ {
+ olChk(ValidateOutBuffer(pcbWritten, sizeof(ULONG)));
+#endif
+ *pcbWritten = 0;
+#ifdef CFS_SECURE
+ }
+ olChk(ValidateHugeBuffer(pb, cb));
+ olChk(Validate());
+ olChk(CheckHandle());
+#else
+ olAssert(_hFile != INVALID_FH);
+#endif
+#if DBG == 1
+ ULONG ulCurrentSize;
+
+ hfChk(ulCurrentSize = _llseek(_hFile, 0, STREAM_SEEK_END));
+
+ if ((ULIGetLow(ulPosition) + cb) > ulCurrentSize)
+ {
+ if (SimulateFailure(DBF_DISKFULL))
+ {
+ olErr(EH_Err, STG_E_MEDIUMFULL);
+ }
+ }
+#endif
+ if (!_fFixedDisk)
+ olChk(CheckIdentity());
+
+ olAssert(ULIGetHigh(ulPosition) == 0);
+ if (cb == 0)
+ olErr(EH_Err, S_OK);
+ hfChk(_llseek(_hFile, (LONG)ULIGetLow(ulPosition), STREAM_SEEK_SET));
+ negChk(cbWritten = _hwrite(_hFile, pb, (long)cb));
+ if (cbWritten < cb)
+ olErr(EH_Err, STG_E_MEDIUMFULL);
+ if (pcbWritten)
+ *pcbWritten = cbWritten;
+#ifdef CFS_SECURE
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+#else
+ sc = S_OK;
+#endif
+ if (!_fFixedDisk)
+ _dwTicks = GetTickCount();
+ olFileStOut((DEB_ITRACE, "Out CFileStream::WriteAt => %lu\n",
+ cbWritten));
+EH_Err:
+#ifdef CFSLOG
+ olLog(("%p CFS::WriteAt(%ld, %ld), cbWritten = %ld, sc = %lx\n",
+ this, ULIGetLow(ulPosition), cb, cbWritten, sc));
+#endif
+
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::FlushCache, public
+//
+// Synopsis: Flushes buffers
+//
+// Returns: Appropriate status code
+//
+// History: 24-Mar-92 DrewB Created
+// 12-Feb-93 AlexT Flush -> FlushCache
+//
+// Notes: Flush as thoroughly as possible
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_FlushCache)
+#endif
+
+STDMETHODIMP CFileStream::FlushCache(void)
+{
+ int iRt, fd;
+ unsigned int uiVer;
+ SCODE sc;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::FlushCache()\n"));
+#ifdef CFS_SECURE
+ TRY
+ {
+ olChk(Validate());
+ olChk(CheckHandle());
+#else
+ olAssert(_hFile != INVALID_FH);
+#endif
+ if (!_fFixedDisk)
+ olChk(CheckIdentity());
+ __asm
+ {
+ mov ax, 3000h
+ clc
+ int 21h
+ xchg al, ah
+ mov uiVer, ax
+ }
+ if (uiVer >= 0x31E)
+ {
+ // Function 68h is only supported on DOS 3.3 and later
+ fd = _hFile;
+ // Commit file
+ __asm
+ {
+ mov iRt, 0
+ mov ah, 068h
+ mov bx, fd
+ clc // DOS doesn't properly clear this
+ int 21h
+ jnc flush_succ
+ mov iRt, ax
+ flush_succ:
+ }
+ if (iRt != 0)
+ olErr(EH_Err, STG_SCODE(iRt));
+ }
+ else
+ {
+ if (_hReserved == INVALID_FH)
+ {
+ // We try to pick up a handle here in two cases:
+ // a) We tried to reserve one before and failed
+ // b) We're not supposed to have a reserve handle
+
+ _hReserved = DosDup(_hFile);
+ if (_hReserved == INVALID_FH)
+ olErr(EH_Err, STG_E_TOOMANYOPENFILES);
+ }
+
+ olVerify(_lclose(_hReserved) != HFILE_ERROR);
+
+ if (_grfLocal & LFF_RESERVE_HANDLE)
+ {
+ // Reacquire a reserve handle (doesn't matter if we fail)
+ _hReserved = DosDup(_hFile);
+ }
+ else
+ _hReserved = INVALID_FH;
+
+ }
+#ifdef CFS_SECURE
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+#else
+ sc = S_OK;
+#endif
+ if (!_fFixedDisk)
+ _dwTicks = GetTickCount();
+ olFileStOut((DEB_ITRACE, "Out CFileStream::FlushCache\n"));
+EH_Err:
+#ifdef CFSLOG
+ olLog(("%p CFS::FlushCache() sc = %lx\n",
+ this, sc));
+#endif
+
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::Flush, public
+//
+// Synopsis: Flushes buffers
+//
+// Returns: Appropriate status code
+//
+// History: 24-Mar-92 DrewB Created
+// 12-Feb-93 AlexT Use dup/close
+//
+// Notes: We flush DOS (but not any disk cache)
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_Flush)
+#endif
+
+STDMETHODIMP CFileStream::Flush(void)
+{
+ BOOL fhrValid = FALSE;
+ HRESULT hr;
+ SCODE sc = S_OK;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::Flush()\n"));
+#ifdef CFS_SECURE
+ TRY
+ {
+
+ olChk(Validate());
+ olChk(CheckHandle());
+#else
+ olAssert(_hFile != INVALID_FH);
+#endif
+ if (!_fFixedDisk)
+ olChk(CheckIdentity());
+ if (_hReserved == INVALID_FH)
+ {
+ // We try to pick up a handle here in two cases:
+ // a) We tried to reserve one before and failed
+ // b) We're not supposed to have a reserve handle
+
+ _hReserved = DosDup(_hFile);
+ if (_hReserved == INVALID_FH)
+ {
+ // We couldn't dup; flush everything (to be safe)
+ hr = FlushCache();
+ fhrValid = TRUE;
+ }
+ }
+ if (_hReserved != INVALID_FH)
+ {
+ // Close the dup'd handle, flushing changes out of DOS
+ olVerify(_lclose(_hReserved) != HFILE_ERROR);
+
+ if (_grfLocal & LFF_RESERVE_HANDLE)
+ {
+ // Reacquire a reserve handle (doesn't matter if we fail)
+ _hReserved = DosDup(_hFile);
+ }
+ else
+ _hReserved = INVALID_FH;
+
+ }
+#ifdef CFS_SECURE
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+#endif
+
+ if (!_fFixedDisk)
+ _dwTicks = GetTickCount();
+ olFileStOut((DEB_ITRACE, "Out CFileStream::Flush\n"));
+ if (!fhrValid)
+ hr = ResultFromScode(sc);
+EH_Err:
+#ifdef CFSLOG
+ olLog(("%p CFS::Flush() sc = %lx\n", this, sc));
+#endif
+
+ return hr;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::SetSize, public
+//
+// Synopsis: Sets the size of the LStream
+//
+// Arguments: [ulSize] - New size
+//
+// Returns: Appropriate status code
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_SetSize)
+#endif
+
+STDMETHODIMP CFileStream::SetSize(ULARGE_INTEGER ulSize)
+{
+ SCODE sc;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::SetSize(%lu)\n",
+ ULIGetLow(ulSize)));
+#ifdef CFS_SECURE
+ TRY
+ {
+ olChk(Validate());
+ olChk(CheckHandle());
+#else
+ olAssert(_hFile != INVALID_FH);
+#endif
+ if (!_fFixedDisk)
+ olChk(CheckIdentity());
+ olAssert(ULIGetHigh(ulSize) == 0);
+
+ ULARGE_INTEGER ulCurrentSize;
+ hfChk(ULISetLow(ulCurrentSize, _llseek(_hFile, 0, STREAM_SEEK_END)));
+
+ hfChk(_llseek(_hFile, (LONG)ULIGetLow(ulSize), STREAM_SEEK_SET));
+ hfChk(_lwrite(_hFile, &sc, 0));
+
+ if (ULIGetLow(ulSize) > ULIGetLow(ulCurrentSize))
+ {
+ // Make sure we didn't run out of disk space
+ LONG lNewSize;
+
+ hfChk(lNewSize = _llseek(_hFile, 0, STREAM_SEEK_END));
+ if (lNewSize < (LONG)ULIGetLow(ulSize)
+#if DBG == 1
+ || SimulateFailure(DBF_DISKFULL)
+#endif
+ )
+ {
+ // we were unable to allocate enough space;
+ // reset to ulCurrentSize (to conserve space) if possible
+
+ if (_llseek(_hFile, (LONG)ULIGetLow(ulCurrentSize),
+ STREAM_SEEK_SET) ==
+ (LONG)ULIGetLow(ulCurrentSize))
+ {
+ _lwrite(_hFile, &sc, 0);
+ }
+ olErr(EH_Err, STG_E_MEDIUMFULL);
+ }
+ }
+#ifdef CFS_SECURE
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+#else
+ sc = S_OK;
+#endif
+ if (!_fFixedDisk)
+ _dwTicks = GetTickCount();
+ olFileStOut((DEB_ITRACE, "Out CFileStream::SetSize\n"));
+EH_Err:
+#ifdef CFSLOG
+ olLog(("%p CFS::SetSize(%ld) sc = %lx\n",
+ this, ULIGetLow(ulSize), sc));
+#endif
+
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::LockRegion, public
+//
+// Synopsis: Gets a lock on a portion of the LStream
+//
+// Arguments: [ulStartOffset] - Lock start
+// [cbLockLength] - Length
+// [dwLockType] - Exclusive/Read only
+//
+// Returns: Appropriate status code
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_LockRegion)
+#endif
+
+STDMETHODIMP CFileStream::LockRegion(ULARGE_INTEGER ulStartOffset,
+ ULARGE_INTEGER cbLockLength,
+ DWORD dwLockType)
+{
+ int iRt, fd;
+ SCODE sc;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::LockRegion(%lu, %lu, %lu)\n",
+ ULIGetLow(ulStartOffset), ULIGetLow(cbLockLength),
+ dwLockType));
+#ifdef CFS_SECURE
+ TRY
+ {
+ olChk(Validate());
+ olChk(CheckHandle());
+ if (!VALID_LOCKTYPE(dwLockType))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+#else
+ olAssert(_hFile != INVALID_FH);
+#endif
+ if (!_fFixedDisk)
+ olChk(CheckIdentity());
+ olAssert(ULIGetHigh(ulStartOffset) == 0);
+ olAssert(ULIGetHigh(cbLockLength) == 0);
+ fd = _hFile;
+ __asm
+ {
+ mov ax, 5C00H
+ mov bx, fd
+ // Assumes low DWORD is first in ULARGE_INTEGER
+ mov cx, WORD PTR ulStartOffset+2
+ mov dx, WORD PTR ulStartOffset
+ mov si, WORD PTR cbLockLength+2
+ mov di, WORD PTR cbLockLength
+ mov iRt, 0
+ clc
+ int 21h
+ jnc grl_noerror
+ mov iRt, ax
+ grl_noerror:
+ }
+ if (iRt != 0)
+ {
+ if (iRt == 1)
+ {
+ // INVALID_FUNCTION is impossible because the
+ // function is hardcoded. This means locking
+ // isn't supported
+ olErr(EH_Err, STG_E_SHAREREQUIRED);
+ }
+ else
+ olErr(EH_Err, STG_SCODE(iRt));
+ }
+#ifdef CFS_SECURE
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+#else
+ sc = S_OK;
+#endif
+ if (!_fFixedDisk)
+ _dwTicks = GetTickCount();
+ olFileStOut((DEB_ITRACE, "Out CFileStream::LockRegion\n"));
+EH_Err:
+#ifdef CFSLOG
+ olLog(("%p CFS::LockRegion(%lx, %lx) sc = %lx\n",
+ this, ULIGetLow(ulStartOffset), ULIGetLow(cbLockLength), sc));
+#endif
+
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::UnlockRegion, public
+//
+// Synopsis: Releases an existing lock
+//
+// Arguments: [ulStartOffset] - Lock start
+// [cbLockLength] - Length
+// [dwLockType] - Lock type
+//
+// Returns: Appropriate status code
+//
+// History: 20-Feb-92 DrewB Created
+//
+// Notes: Must match an existing lock exactly
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_UnlockRegion)
+#endif
+
+STDMETHODIMP CFileStream::UnlockRegion(ULARGE_INTEGER ulStartOffset,
+ ULARGE_INTEGER cbLockLength,
+ DWORD dwLockType)
+{
+ int iRt, fd;
+ SCODE sc;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::UnlockRegion(%lu, %lu)\n",
+ ULIGetLow(ulStartOffset), ULIGetLow(cbLockLength),
+ dwLockType));
+#ifdef CFS_SECURE
+ TRY
+ {
+ olChk(Validate());
+ olChk(CheckHandle());
+ if (!VALID_LOCKTYPE(dwLockType))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+#else
+ olAssert(_hFile != INVALID_FH);
+#endif
+#ifdef FULL_CHECK_IDENTITY
+ if (!_fFixedDisk)
+ olChk(CheckIdentity());
+#endif
+ olAssert(ULIGetHigh(ulStartOffset) == 0);
+ olAssert(ULIGetHigh(cbLockLength) == 0);
+ fd = _hFile;
+ __asm
+ {
+ mov ax, 5C01H
+ mov bx, fd
+ // Assumes low DWORD is first in ULARGE_INTEGER
+ mov cx, WORD PTR ulStartOffset+2
+ mov dx, WORD PTR ulStartOffset
+ mov si, WORD PTR cbLockLength+2
+ mov di, WORD PTR cbLockLength
+ mov iRt, 0
+ clc
+ int 21h
+ jnc rrl_noerror
+ mov iRt, ax
+ rrl_noerror:
+ }
+ if (iRt != 0)
+ olErr(EH_Err, STG_SCODE(iRt));
+#ifdef CFS_SECURE
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+#else
+ sc = S_OK;
+#endif
+#ifdef FULL_CHECK_IDENTITY
+ if (!_fFixedDisk)
+ _dwTicks = GetTickCount();
+#endif
+ olFileStOut((DEB_ITRACE, "Out CFileStream::UnlockRegion\n"));
+EH_Err:
+#ifdef CFSLOG
+ olLog(("%p CFS::UnlockRegion(%lx, %lx) sc = %lx\n",
+ this, ULIGetLow(ulStartOffset), ULIGetLow(cbLockLength), sc));
+#endif
+
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::Stat, public
+//
+// Synopsis: Fills in a stat buffer for this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 25-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_Stat) // Stat_TEXT
+#endif
+
+_OLESTDMETHODIMP CFileStream::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ int iRt, fd;
+ SCODE sc;
+ WORD tm, dt;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::Stat(%p)\n", pstatstg));
+
+#ifdef CFSLOG
+ olLog(("%p CFS::Stat(%ld)\n", this, grfStatFlag));
+#endif
+
+#ifdef CFS_SECURE
+ TRY
+ {
+ olChkTo(EH_RetSc, ValidateOutBuffer(pstatstg, sizeof(STATSTGW)));
+ olAssert(SUCCEEDED(VerifyStatFlag(grfStatFlag)));
+ olChk(Validate());
+ olChk(CheckHandle());
+#else
+ olAssert(_hFile != INVALID_FH);
+#endif
+ if (!_fFixedDisk)
+ olChk(CheckIdentity());
+ ULISetHigh(pstatstg->cbSize, 0);
+ hfChk(ULISetLow(pstatstg->cbSize,
+ _llseek(_hFile, 0, STREAM_SEEK_END)));
+ fd = _hFile;
+ // Retrieve file time
+ __asm
+ {
+ mov iRt, 0
+ mov bx, fd
+ mov ax, 05700h
+ clc
+ int 21h
+ mov tm, cx
+ mov dt, dx
+ jnc time_succ
+ mov iRt, ax
+ time_succ:
+ }
+ if (iRt != 0)
+ olErr(EH_Err, STG_SCODE(iRt));
+
+ if (!CoDosDateTimeToFileTime(dt, tm, &pstatstg->mtime))
+ olErr(EH_Err, STG_E_UNKNOWN);
+ pstatstg->ctime.dwLowDateTime = pstatstg->ctime.dwHighDateTime = 0;
+ pstatstg->atime.dwLowDateTime = pstatstg->atime.dwHighDateTime = 0;
+
+ olHVerSucc(GetLocksSupported(&pstatstg->grfLocksSupported));
+ pstatstg->type = STGTY_LOCKBYTES;
+ pstatstg->grfMode = DFlagsToMode(_pgfst->GetDFlags());
+ pstatstg->pwcsName = NULL;
+ if ((grfStatFlag & STATFLAG_NONAME) == 0)
+ {
+ olChk(GetName(&pstatstg->pwcsName));
+ }
+#ifdef CFS_SECURE
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+#else
+ sc = S_OK;
+#endif
+ if (!_fFixedDisk)
+ _dwTicks = GetTickCount();
+ olFileStOut((DEB_ITRACE, "Out CFileStream::Stat\n"));
+ return NOERROR;
+
+EH_Err:
+#ifdef CFS_SECURE
+ memset(pstatstg, 0, sizeof(STATSTGW));
+EH_RetSc:
+#endif
+ _OLERETURN(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::SwitchToFile, public
+//
+// Synopsis: Changes the file this filestream uses
+//
+// Arguments: [ptcsFile] - File name
+// [ulCommitSize] -- Size needed to do overwrite commit
+// [cbBuffer] - Buffer size
+// [pvBuffer] - Buffer for file copying
+//
+// Returns: Appropriate status code
+//
+// History: 08-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_SwitchToFile) // CFS_SwitchToFile
+#endif
+
+STDMETHODIMP CFileStream::SwitchToFile(TCHAR const *ptcsFile,
+ ULONG ulCommitSize,
+ ULONG cbBuffer,
+ void *pvBuffer)
+{
+ SCODE sc;
+ UINT cbRead, cbWritten;
+ HFILE hOldFile;
+ TCHAR atcOldName[_MAX_PATH];
+ WCHAR wcsFile[_MAX_PATH];
+ DWORD dwOldStartFlags;
+ OFSTRUCT of;
+
+ olDebugOut((DEB_ITRACE, "In CFileStream::SwitchToFile:%p(%s, %lu, %p)\n",
+ this, ptcsFile, cbBuffer, pvBuffer));
+
+#ifdef CFS_SECURE
+ olChk(Validate());
+ olChk(CheckHandle());
+#else
+ olAssert(_hFile != INVALID_FH);
+#endif
+ if (!_fFixedDisk)
+ olChk(CheckIdentity());
+
+ // Check for marshals
+ if (_pgfst->GetRefCount() != 1)
+ olErr(EH_Err, STG_E_EXTANTMARSHALLINGS);
+
+ // Seek to beginning
+ hfChk(_llseek(_hFile, 0, STREAM_SEEK_SET));
+
+ // Preserve old file information
+ tcscpy(atcOldName, _pgfst->GetName());
+ hOldFile = _hFile;
+ dwOldStartFlags = _pgfst->GetStartFlags();
+
+ // Set file information to prepare for new Init
+ _pgfst->SetName(NULL);
+ _hFile = INVALID_FH;
+ _pgfst->SetStartFlags((dwOldStartFlags & ~(RSF_CREATEFLAGS |
+ RSF_CONVERT |
+ RSF_DELETEONRELEASE |
+ RSF_OPEN)) |
+ RSF_CREATE);
+
+ // Release reserved file handle so it can be consumed
+ if (_hReserved >= 0)
+ {
+ olVerify(_lclose(_hReserved) != HFILE_ERROR);
+ _hReserved = INVALID_FH;
+ }
+
+ // Attempt to create new file
+ if (mbstowcs(wcsFile, ptcsFile, _MAX_PATH) == (size_t)-1)
+ olErr(EH_ReplaceOld, STG_E_INVALIDNAME);
+ olChkTo(EH_ReplaceOld, Init(wcsFile));
+
+ ULARGE_INTEGER ulNewSize;
+ ULISet32(ulNewSize, ulCommitSize);
+
+ // SetSize to minimum commit size
+ olHChkTo(EH_NewFile, SetSize(ulNewSize));
+ // SetSize changes the file pointer, so move it back to the beginning
+ hfChkTo(EH_NewFile, _llseek(_hFile, 0, STREAM_SEEK_SET));
+
+ // Copy file contents
+ for (;;)
+ {
+ negChkTo(EH_NewFile,
+ cbRead = _lread(hOldFile, pvBuffer, (UINT)cbBuffer));
+ if (cbRead == 0)
+ // EOF
+ break;
+ negChkTo(EH_NewFile,
+ cbWritten = _lwrite(_hFile, pvBuffer, cbRead));
+ if (cbWritten != cbRead)
+ olErr(EH_NewFile, STG_E_WRITEFAULT);
+ }
+
+ olVerify(_lclose(hOldFile) != HFILE_ERROR);
+ if (dwOldStartFlags & RSF_DELETEONRELEASE)
+ {
+ // This is allowed to fail if somebody else has
+ // the file open
+ OpenFile(atcOldName, &of, OF_DELETE);
+ }
+
+ if (_grfLocal & LFF_RESERVE_HANDLE)
+ {
+ // Nothing we can do about errors here
+ _hReserved = DosDup(_hFile);
+ }
+
+ if (!_fFixedDisk)
+ _dwTicks = GetTickCount();
+
+ olDebugOut((DEB_ITRACE, "Out CFileStream::SwitchToFile\n"));
+ return NOERROR;
+
+ EH_NewFile:
+ olVerify(_lclose(_hFile) != HFILE_ERROR);
+ olVerify(OpenFile(_pgfst->GetName(), &of, OF_DELETE) != HFILE_ERROR);
+ EH_ReplaceOld:
+ _pgfst->SetName(atcOldName);
+ _hFile = hOldFile;
+ _pgfst->SetStartFlags(dwOldStartFlags);
+ if (_grfLocal & LFF_RESERVE_HANDLE)
+ // Nothing we can do about errors here
+ _hReserved = DosDup(_hFile);
+ EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::Delete, public
+//
+// Synopsis: Closes and deletes the file, errors ignored
+//
+// Returns: Appropriate status code
+//
+// History: 09-Feb-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_Delete) // CFS_Shutdown
+#endif
+
+void CFileStream::Delete(void)
+{
+ OFSTRUCT of;
+
+ olDebugOut((DEB_ITRACE, "In CFileStream::Delete:%p()\n", this));
+ if (_hFile >= 0)
+ _lclose(_hFile);
+ _hFile = INVALID_FH;
+ if (_hReserved >= 0)
+ _lclose(_hReserved);
+ _hReserved = INVALID_FH;
+ OpenFile(_pgfst->GetName(), &of, OF_DELETE);
+ olDebugOut((DEB_ITRACE, "Out CFileStream::Delete\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::ReserveHandle, public
+//
+// Synopsis: Reserves a backup file handle for handle-required operations
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jul-93 DrewB Created
+//
+// Notes: May be called with a handle already reserved
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_ReserveHandle) // CFS_ReserveHandle
+#endif
+
+STDMETHODIMP CFileStream::ReserveHandle(void)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CFileStream::ReserveHandle:%p()\n", this));
+ if (_hReserved == INVALID_FH &&
+ (_hReserved = DosDup(_hFile)) == INVALID_FH)
+ {
+ sc = STG_E_TOOMANYOPENFILES;
+ }
+ else
+ {
+ sc = S_OK;
+ _grfLocal |= LFF_RESERVE_HANDLE;
+ }
+ olDebugOut((DEB_ITRACE, "Out CFileStream::ReserveHandle => %lX\n", sc));
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::GetSize, public
+//
+// Synopsis: Return the size of the stream
+//
+// Returns: Appropriate status code
+//
+// History: 12-Jul-93 AlexT Created
+//
+// Notes: This is a separate method from Stat as an optimization
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFS_GetSize) // CFS_ReserveHandle
+#endif
+
+STDMETHODIMP CFileStream::GetSize(ULARGE_INTEGER *puliSize)
+{
+ SCODE sc = S_OK;
+
+ ULISetHigh(*puliSize, 0);
+ hfChk(ULISetLow(*puliSize, _llseek(_hFile, 0, STREAM_SEEK_END)));
+
+EH_Err:
+ return(ResultFromScode(sc));
+}
diff --git a/private/ole32/stg/exp/filest32.cxx b/private/ole32/stg/exp/filest32.cxx
new file mode 100644
index 000000000..faeb9648c
--- /dev/null
+++ b/private/ole32/stg/exp/filest32.cxx
@@ -0,0 +1,1918 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: filest32.cxx
+//
+// Contents: Win32 LStream implementation
+//
+// History: 12-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <time.h>
+#include <marshl.hxx>
+#include <df32.hxx>
+#include <logfile.hxx>
+#include <dfdeb.hxx>
+
+
+#if WIN32 != 200
+#define USE_OVERLAPPED
+#endif
+
+
+#define DEBOUT_FILEST
+
+#ifdef DEBOUT_FILEST
+#define olFileStOut(x) olDebugOut(x)
+#else
+#define olFileStOut(x)
+#endif
+
+#define DEB_FILEST 0x8000
+#define DEB_SEEK 0x2000
+
+#define boolChk(e) \
+if (!(e)) olErr(EH_Err, LAST_STG_SCODE) else 1
+#define boolChkTo(l, e) \
+if (!(e)) olErr(l, LAST_STG_SCODE) else 1
+#define negChk(e) \
+if ((e) == 0xffffffff) olErr(EH_Err, LAST_STG_SCODE) else 1
+#define negChkTo(l, e) \
+if ((e) == 0xffffffff) olErr(l, LAST_STG_SCODE) else 1
+
+
+#if DBG == 1
+void CFileStream::CheckSeekPointer(void)
+{
+ LONG lHighChk;
+ ULONG ulLowChk;
+
+ lHighChk = 0;
+
+ if (_hFile != INVALID_FH)
+ {
+ ulLowChk = SetFilePointer(_hFile, 0, &lHighChk, FILE_CURRENT);
+
+ olDebugOut((DEB_SEEK, "%lx: Seek pointer on handle %lx == %lu\n",
+ this,
+ _hFile,
+ ulLowChk));
+
+ if (ulLowChk == 0xFFFFFFFF)
+ {
+ //An error of some sort occurred.
+
+ olDebugOut((DEB_ERROR, "SetFilePointer call failed with %lu\n",
+ GetLastError()));
+ }
+ else if ((ulLowChk != _ulLowPos) && (_ulLowPos != 0xFFFFFFFF))
+ {
+ olDebugOut((DEB_ERROR,"Seek pointer mismatch."
+ " Cached = %lu, Real = %lu, Last Checked = %lu\n",
+ _ulLowPos,
+ ulLowChk,
+ _ulLastFilePos));
+ olAssert((ulLowChk == _ulLowPos) || (_ulLowPos == 0xFFFFFFFF));
+ }
+
+ _ulLastFilePos = ulLowChk;
+ }
+}
+#define CheckSeek() CheckSeekPointer()
+#else
+#define CheckSeek()
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::InitWorker, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [pwcsPath] -- Path
+// [fCheck] -- If TRUE, check in read-only, deny-read case
+// to make sure there is not reader. If FALSE,
+// don't check. FALSE is used for unmarshalling.
+//
+// Returns: Appropriate status code
+//
+// History: 20-Feb-92 DrewB Created
+//
+// Notes: This Init function does more than the usual init
+// function. Rather than construct an invalid object,
+// this also can construct a fully or partially
+// constructed object. For fully constructed objects,
+// nothing is done other than return. In all other cases,
+// as much construction is done as is necessary. This
+// allows us to do lazy construction of filestream by
+// simply calling Init on a filestream that we want
+// lazily constructed. An initial new'ed filestream
+// will be fully constructed and later Init's will
+// do nothing.
+//
+// [pwcsPath] may be unsafe memory so we must be careful
+// not to propagate faults
+//
+//---------------------------------------------------------------
+
+SCODE CFileStream::InitWorker(WCHAR const *pwcsPath, BOOL fCheck)
+{
+ TCHAR atcPath[_MAX_PATH+1], *ptcsFile;
+ TCHAR atcTmpPath[_MAX_PATH+1];
+ DWORD dwTickCount;
+ SCODE sc;
+ DWORD dwCreation, dwAccess, dwShare;
+ BOOL fSetName = FALSE;
+ DWORD dwStartFlags;
+
+ olFileStOut((DEB_FILEST, "In CFileStream::Init(%ws)\n", pwcsPath));
+
+ _ulLowPos = 0xFFFFFFFF;
+#if DBG == 1
+ _ulSeeks = 0;
+ _ulRealSeeks = 0;
+ _ulLastFilePos = 0xFFFFFFFF;
+#endif
+
+ // If we've already been constructed, leave
+ if (_hFile != INVALID_FH)
+ return S_OK;
+
+ // If we don't have a name, get one
+ if (!_pgfst->HasName())
+ {
+ // File hasn't been opened yet, so use the start flags
+ dwStartFlags = _pgfst->GetStartFlags();
+
+ if (pwcsPath == NULL)
+ {
+ BOOL fWinDir = FALSE;
+
+ // Can't truncate since for temporary files we will
+ // always be creating
+ olAssert((dwStartFlags & RSF_TRUNCATE) == 0);
+
+ if (GetTempPath(_MAX_PATH, atcTmpPath) == 0)
+ {
+ if (GetWindowsDirectory(atcTmpPath, _MAX_PATH) == 0)
+ olErr(EH_Err, LAST_STG_SCODE);
+ fWinDir = TRUE;
+ }
+
+ dwTickCount = GetTickCount();
+
+ if (GetTempFileName(atcTmpPath, TSTR("~DFT"),
+ dwTickCount, atcPath) == 0)
+ {
+ if (fWinDir)
+ {
+ olErr(EH_Err, LAST_STG_SCODE);
+ }
+ if (GetWindowsDirectory(atcTmpPath, _MAX_PATH) == 0)
+ olErr(EH_Err, LAST_STG_SCODE);
+ if (GetTempFileName(atcTmpPath, TSTR("~DFT"),
+ dwTickCount, atcPath) == 0)
+ olErr(EH_Err, LAST_STG_SCODE);
+ }
+
+ // GetTempFileName created a file so we just want to open it
+ // dwStartFlags = (dwStartFlags & ~RSF_CREATE) | RSF_OPEN;
+ }
+ else
+ {
+ TRY
+ {
+#ifndef UNICODE
+ UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ if (!WideCharToMultiByte(
+ uCodePage,
+ 0,
+ pwcsPath,
+ -1,
+ atcPath,
+ _MAX_PATH + 1,
+ NULL,
+ NULL))
+ olErr(EH_Err, STG_E_INVALIDNAME);
+#else
+ lstrcpyW(atcPath, pwcsPath);
+#endif
+ }
+ CATCH(CException, e)
+ {
+ UNREFERENCED_PARM(e);
+ olErr(EH_Err, STG_E_INVALIDPOINTER);
+ }
+ END_CATCH
+ }
+// _pgfst->SetName(pwcsPath);
+// fSetName = TRUE;
+ }
+ else
+ {
+ // Use the name somebody else gave us
+#ifndef UNICODE
+ UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ if (!WideCharToMultiByte(
+ uCodePage,
+ 0,
+ _pgfst->GetName(),
+ -1,
+ atcPath,
+ _MAX_PATH + 1,
+ NULL,
+ NULL))
+ olErr(EH_Err, STG_E_INVALIDNAME);
+#else
+ lstrcpyW(atcPath, _pgfst->GetName());
+#endif
+
+ // File has already been started, so just open it
+ dwStartFlags = (_pgfst->GetStartFlags() & ~RSF_CREATEFLAGS) | RSF_OPEN;
+ }
+
+ if (dwStartFlags & RSF_OPENCREATE)
+ {
+ // This is used for our internal logging
+ dwCreation = OPEN_ALWAYS;
+ }
+ else if (dwStartFlags & RSF_CREATE)
+ {
+ if (dwStartFlags & RSF_TRUNCATE)
+ dwCreation = CREATE_ALWAYS;
+ else
+ dwCreation = CREATE_NEW;
+ }
+ else
+ {
+ if (dwStartFlags & RSF_TRUNCATE)
+ dwCreation = TRUNCATE_EXISTING;
+ else
+ dwCreation = OPEN_EXISTING;
+ }
+
+ if (!P_WRITE(_pgfst->GetDFlags()))
+ dwAccess = GENERIC_READ;
+ else
+ dwAccess = GENERIC_READ | GENERIC_WRITE;
+ if (P_DENYWRITE(_pgfst->GetDFlags()) && !P_WRITE(_pgfst->GetDFlags()))
+ dwShare = FILE_SHARE_READ;
+ else
+ dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE;
+#if WIN32 == 300
+ if (_pgfst->GetDFlags() & DF_ACCESSCONTROL)
+ dwAccess |= WRITE_DAC | READ_CONTROL;
+#endif
+
+ // Make sure we're not attempting to create/truncate a read-only thing
+ olAssert(dwAccess != GENERIC_READ ||
+ !(dwStartFlags & (RSF_CREATE | RSF_TRUNCATE)));
+
+ //If we're opening with deny-read, we need to let the
+ // file system tell us if there are any other readers, to
+ // avoid our no-lock trick for the read-only deny-write case.
+ //Yes, this is ugly.
+ //Yes, it also has a race condition in which two people can
+ // get read access while specifying SHARE_DENY_READ.
+
+ if (fCheck &&
+ !P_WRITE(_pgfst->GetDFlags()) && P_DENYREAD(_pgfst->GetDFlags()))
+ {
+ //We open read-only, share exclusive. If this fails, there
+ // is already another accessor, so we bail.
+ //
+ //If we are unmarshalling, we don't do this check because we
+ // know there is already another reader, i.e. the original
+ // open.
+ _hFile = CreateFileT(atcPath, GENERIC_READ, 0, NULL,
+ dwCreation, FILE_ATTRIBUTE_NORMAL |
+ FILE_FLAG_RANDOM_ACCESS, NULL);
+
+ if (_hFile == INVALID_HANDLE_VALUE)
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ olErr(EH_Path, STG_E_FILEALREADYEXISTS)
+ else
+ olErr(EH_Path, LAST_STG_SCODE);
+
+ CloseHandle(_hFile);
+ }
+
+ DWORD dwLastError;
+
+ _hFile = CreateFileT(atcPath, dwAccess, dwShare, NULL,
+ dwCreation, FILE_ATTRIBUTE_NORMAL |
+ FILE_FLAG_RANDOM_ACCESS, NULL);
+ if (_hFile == INVALID_HANDLE_VALUE)
+ if ((dwLastError = GetLastError()) == ERROR_ALREADY_EXISTS ||
+ dwLastError == ERROR_FILE_EXISTS)
+ {
+ if (!_pgfst->HasName() && pwcsPath == NULL)
+ {
+ while (1)
+ {
+ if (GetTempFileName(atcTmpPath, TSTR("~DFT"),
+ ++dwTickCount, atcPath) == 0)
+ olErr(EH_Path, LAST_STG_SCODE);
+ _hFile = CreateFileT(atcPath, dwAccess, dwShare, NULL,
+ dwCreation, FILE_ATTRIBUTE_NORMAL |
+ FILE_FLAG_RANDOM_ACCESS, NULL);
+ if (_hFile != INVALID_HANDLE_VALUE) break;
+ if ((dwLastError = GetLastError()) != ERROR_ALREADY_EXISTS &&
+ dwLastError != ERROR_FILE_EXISTS)
+ olErr(EH_Path, dwLastError);
+ }
+ }
+ else
+ olErr(EH_Path, STG_E_FILEALREADYEXISTS)
+ }
+ else
+ olErr(EH_Path, STG_SCODE(dwLastError));
+
+ //At this point the file handle is valid, so let's look at the
+ //seek pointer and see what it is.
+ CheckSeek();
+
+ // Set name to fully qualified path to avoid current-directory
+ // dependencies
+ if (!_pgfst->HasName())
+ {
+#ifndef UNICODE
+ TCHAR atcFullPath[_MAX_PATH+1];
+
+ if (GetFullPathNameA(atcPath, _MAX_PATH, atcFullPath, &ptcsFile) == 0)
+ olErr(EH_File, LAST_STG_SCODE);
+
+ //Now convert it to Unicode and store.
+ if (!MultiByteToWideChar(
+ AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0,
+ atcFullPath,
+ -1,
+ _pgfst->GetName(),
+ MAX_PATH + 1))
+ olErr(EH_File, STG_E_INVALIDNAME);
+#else
+ if (GetFullPathNameW(atcPath, _MAX_PATH,
+ _pgfst->GetName(), &ptcsFile) == 0)
+ olErr(EH_File, LAST_STG_SCODE);
+#endif
+ fSetName = TRUE;
+ }
+
+ CheckSeek();
+ olDebugOut((DEB_IWARN, "CFileStream %p handle %p thread %lX\n",
+ this, _hFile, GetCurrentThreadId()));
+
+ olFileStOut((DEB_FILEST, "Out CFileStream::Init\n"));
+
+#if WIN32 == 100 || WIN32 > 200
+
+ if (fCheck && !(_pgfst->GetDFlags() & DF_WRITE) &&
+ (_cbFileSize = GetFileSize (_hFile, NULL)))
+ {
+ //
+ // create a nameless file mapping object, with a maximum
+ // size equal to the current size of the file identified
+ // by _hFile
+ //
+
+ _hMapObject = CreateFileMappingT (
+ _hFile, // handle of file to map
+ NULL, // optional security attributes
+#ifndef TAKE_HINT
+ PAGE_READONLY, // protection for mapping object
+#else
+ ((_pgfst->GetDFlags() & DF_WRITE) ? PAGE_READWRITE : PAGE_READONLY),
+#endif
+ 0, // high order 32 bits of object size
+ 0, // low order 32 bits of object size
+ NULL // name of file mapping object
+ );
+
+ if (_hMapObject == NULL) return S_OK;
+
+ //
+ // map the entire file into the address space, counting
+ // on the system to handle it in the most efficient way
+ //
+
+ _pbBaseAddr = (LPBYTE) MapViewOfFile (
+ _hMapObject, // file-mapping object to map into address space
+#ifndef TAKE_HINT
+ FILE_MAP_READ, // access mode
+#else
+ ((_pgfst->GetDFlags() & DF_WRITE) ? FILE_MAP_WRITE : FILE_MAP_READ),
+#endif
+ 0, // high-order 32 bits of file offset
+ 0, // low-order 32 bits of file offset
+ 0 // number of bytes to map
+ );
+
+ if (_pbBaseAddr == NULL)
+ {
+ CloseHandle (_hMapObject);
+ _hMapObject = NULL;
+ }
+ }
+
+#endif
+
+ return S_OK;
+
+EH_File:
+ olVerify(CloseHandle(_hFile));
+ _hFile = INVALID_FH;
+ if (dwCreation == CREATE_NEW || dwCreation == CREATE_ALWAYS)
+ DeleteFileT(atcPath);
+EH_Path:
+ if (fSetName)
+ _pgfst->SetName(NULL);
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::InitFromHandle, public
+//
+// Synopsis: Creates a filestream by duping an existing handle
+//
+// Arguments: [h] - Handle
+//
+// Returns: Appropriate status code
+//
+// History: 09-Feb-94 DrewB Created
+//
+// Notes: Intended only for creating a temporary ILockBytes on a file;
+// does not create a true CFileStream; there is no
+// global filestream, no access flags, etc.
+//
+//----------------------------------------------------------------------------
+
+SCODE CFileStream::InitFromHandle(HANDLE h)
+{
+ SCODE sc;
+
+ olFileStOut((DEB_FILEST, "In CFileStream::InitFromHandle:%p(%p)\n",
+ this, h));
+
+ if (!DuplicateHandle(GetCurrentProcess(), h, GetCurrentProcess(), &_hFile,
+ 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ sc = LAST_STG_SCODE;
+ }
+ else
+ {
+ sc = S_OK;
+ }
+
+ _ulLowPos = SetFilePointer(_hFile, 0, NULL, FILE_CURRENT);
+#if DBG == 1
+ _ulSeeks = 1;
+ _ulRealSeeks = 1;
+ _ulLastFilePos = _ulLowPos;
+#endif
+
+ olFileStOut((DEB_FILEST, "Out CFileStream::InitFromHandle\n"));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::~CFileStream, public
+//
+// Synopsis: Destructor
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CFileStream::~CFileStream(void)
+{
+ olFileStOut((DEB_FILEST, "In CFileStream::~CFileStream()\n"));
+ olAssert(_cReferences == 0);
+ _sig = CFILESTREAM_SIGDEL;
+
+ CheckSeek();
+
+ if (_hFile != INVALID_FH)
+ {
+ olDebugOut((DEB_IWARN, "~CFileStream %p handle %p thread %lX\n",
+ this, _hFile, GetCurrentThreadId()));
+ olVerify(CloseHandle(_hFile));
+#ifdef ASYNC
+ if ((_pgfst) &&
+ (_pgfst->GetTerminationStatus() == TERMINATED_ABNORMAL))
+ {
+ WCHAR *pwcName;
+ SCODE sc = GetName(&pwcName);
+ if (SUCCEEDED(sc))
+ {
+#ifndef UNICODE
+ TCHAR atcPath[_MAX_PATH + 1];
+ UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ WideCharToMultiByte(uCodePage,
+ 0,
+ pwcName,
+ -1,
+ atcPath,
+ _MAX_PATH + 1,
+ NULL,
+ NULL);
+
+
+ DeleteFileA(atcPath);
+#else
+ DeleteFile(pwcName);
+#endif
+ }
+ }
+#endif //ASYNC
+ }
+ if (_hReserved != INVALID_FH)
+ {
+ olDebugOut((DEB_IWARN, "~CFileStream reserved %p"
+ "handle %p thread %lX\n",
+ this, _hReserved, GetCurrentThreadId()));
+ olVerify(CloseHandle(_hReserved));
+ _hReserved = INVALID_FH;
+ }
+
+#if WIN32 == 100 || WIN32 > 200
+
+ TurnOffMapping();
+
+#endif
+
+ if (_pgfst)
+ {
+ _pgfst->Remove(this);
+ if (_pgfst->HasName())
+ {
+ if (_pgfst->GetRefCount() == 1)
+ {
+ // Delete zero length files also. A zero length file
+ // is not a valid docfile so don't leave them around
+ if (_pgfst->GetStartFlags() & RSF_DELETEONRELEASE)
+ {
+ // This is allowed to fail if somebody
+ // else has the file open
+ DeleteFileX(_pgfst->GetName());
+ }
+ }
+ }
+ _pgfst->Release();
+ }
+ olDebugOut((DEB_ITRACE,
+ "Number of seeks: %lu\nNumber of actual seeks:"
+ "%lu\nSavings: %lu\n",
+ _ulSeeks, _ulRealSeeks, _ulSeeks-_ulRealSeeks));
+
+ olFileStOut((DEB_FILEST, "Out CFileStream::~CFileStream\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::ReadAt, public
+//
+// Synopsis: Reads bytes at a specific point in a stream
+//
+// Arguments: [ulPosition] - Offset in file to read at
+// [pb] - Buffer
+// [cb] - Count of bytes to read
+// [pcbRead] - Return of bytes read
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CFileStream::ReadAt(ULARGE_INTEGER ulPosition,
+ VOID *pb,
+ ULONG cb,
+ ULONG *pcbRead)
+{
+ SCODE sc;
+ LONG lHigh = ULIGetHigh(ulPosition);
+ ULONG ulLow = ULIGetLow(ulPosition);
+
+#ifdef ASYNC
+ olAssert((_ppc == NULL) || (_ppc->HaveMutex()));
+#endif
+ olAssert(lHigh == 0 &&
+ aMsg("High dword other than zero passed to filestream."));
+
+ olFileStOut((DEB_FILEST, "In CFileStream::ReadAt("
+ "%lu:%lu, %p, %lu, %p)\n", ULIGetHigh(ulPosition),
+ ULIGetLow(ulPosition), pb, cb, pcbRead));
+
+ CheckSeek();
+#ifdef CFS_SECURE
+ if (pcbRead)
+ {
+ olChk(ValidateOutBuffer(pcbRead, sizeof(ULONG)));
+ *pcbRead = 0;
+ }
+ olChk(ValidateHugeOutBuffer(pb, cb));
+ olChk(Validate());
+ olChk(CheckHandle());
+#else
+ olAssert(_hFile != INVALID_FH);
+ *pcbRead = 0;
+#endif
+
+#ifdef ASYNC
+ DWORD dwTerminate;
+ dwTerminate = _pgfst->GetTerminationStatus();
+ if (dwTerminate == TERMINATED_ABNORMAL)
+ {
+ sc = STG_E_INCOMPLETE;
+ }
+ else if ((dwTerminate == TERMINATED_NORMAL) ||
+ (ulLow + cb <= _pgfst->GetHighWaterMark()))
+ {
+#endif
+#if WIN32 == 100 || WIN32 > 200
+
+ if (_pbBaseAddr)
+ {
+ sc = S_OK;
+ if (ulLow < _cbFileSize)
+ {
+ *pcbRead = _cbFileSize - ulLow;
+ if (cb < *pcbRead) *pcbRead = cb;
+ __try
+ {
+ memcpy (pb, _pbBaseAddr+ulLow, *pcbRead);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ sc = STG_E_READFAULT;
+ }
+ }
+ else
+ {
+ *pcbRead = 0;
+ }
+ olFileStOut((DEB_ITRACE, "Out CFileStream::ReadAt => %lu\n", *pcbRead));
+ return sc;
+ }
+
+#endif
+
+#if DBG == 1
+ _ulSeeks++;
+#endif
+
+
+#ifndef USE_OVERLAPPED
+ if (_ulLowPos != ulLow)
+ {
+ negChk(SetFilePointer(_hFile, ulLow, &lHigh,
+ FILE_BEGIN));
+ _ulLowPos = ulLow;
+ CheckSeek();
+ olLowLog(("STGIO - Seek : %8x at %8x\n", _hFile, ulLow));
+#if DBG == 1
+ _ulRealSeeks++;
+#endif
+ }
+
+ boolChk(ReadFile(_hFile, pb, cb, pcbRead, NULL));
+
+#else // ifndef USE_OVERLAPPED
+ if (_ulLowPos != ulLow)
+ {
+ OVERLAPPED Overlapped;
+ Overlapped.Offset = ulLow;
+ Overlapped.OffsetHigh = 0;
+ Overlapped.hEvent = NULL;
+
+ if (!ReadFile(_hFile, pb, cb, pcbRead, &Overlapped))
+ //Check Error return value for FILE_ERROR_EOF
+ {
+ if (GetLastError() != ERROR_HANDLE_EOF)
+ olErr(EH_Err, LAST_STG_SCODE);
+ }
+ }
+ else
+ {
+ boolChk(ReadFile(_hFile, pb, cb, pcbRead, NULL));
+ }
+
+#endif
+ _ulLowPos = ulLow + *pcbRead;
+ sc = S_OK;
+#ifdef ASYNC
+ }
+ else
+ {
+ *pcbRead = 0;
+ _pgfst->SetFailurePoint(cb + ulLow);
+ sc = E_PENDING;
+ }
+#endif
+
+ olLowLog(("STGIO - Read : %8x at %8x, %8d, %8d <--\n", _hFile, ulLow, cb, *pcbRead));
+
+ olFileStOut((DEB_FILEST, "Out CFileStream::ReadAt => %lu\n", *pcbRead));
+EH_Err:
+ CheckSeek();
+ return ResultFromScode(sc);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::WriteAt, public
+//
+// Synopsis: Writes bytes at a specific point in a stream
+//
+// Arguments: [ulPosition] - Offset in file
+// [pb] - Buffer
+// [cb] - Count of bytes to write
+// [pcbWritten] - Return of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbWritten]
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+STDMETHODIMP CFileStream::WriteAt(ULARGE_INTEGER ulPosition,
+ VOID const *pb,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ SCODE sc;
+ LONG lHigh = ULIGetHigh(ulPosition);
+ ULONG ulLow = ULIGetLow(ulPosition);
+
+#ifdef ASYNC
+ olAssert((_ppc == NULL) || (_ppc->HaveMutex()));
+#endif
+ olAssert(lHigh == 0 &&
+ aMsg("High dword other than zero passed to filestream."));
+
+
+ olFileStOut((DEB_FILEST, "In CFileStream::WriteAt:%p("
+ "%lu:%lu, %p, %lu, %p)\n", this, ULIGetHigh(ulPosition),
+ ULIGetLow(ulPosition), pb, cb, pcbWritten));
+
+#ifdef ASYNC
+ DWORD dwTerminate;
+ dwTerminate = _pgfst->GetTerminationStatus();
+ if (dwTerminate == TERMINATED_ABNORMAL)
+ {
+ sc = STG_E_INCOMPLETE;
+ }
+ else if ((dwTerminate == TERMINATED_NORMAL) ||
+ (ulLow + cb <= _pgfst->GetHighWaterMark()))
+ {
+#endif
+ sc = WriteAtWorker(ulPosition, pb, cb, pcbWritten);
+#ifdef ASYNC
+ }
+ else
+ {
+ *pcbWritten = 0;
+ _pgfst->SetFailurePoint(cb + ulLow);
+ sc = E_PENDING;
+ }
+#endif
+
+ olFileStOut((DEB_FILEST, "Out CFileStream::WriteAt => %lu\n",
+ *pcbWritten));
+ return sc;
+}
+
+
+SCODE CFileStream::WriteAtWorker(ULARGE_INTEGER ulPosition,
+ VOID const *pb,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ SCODE sc;
+ LONG lHigh = ULIGetHigh(ulPosition);
+ ULONG ulLow = ULIGetLow(ulPosition);
+
+ olAssert(lHigh == 0 &&
+ aMsg("High dword other than zero passed to filestream."));
+
+ CheckSeek();
+#ifdef CFS_SECURE
+ if (pcbWritten)
+ {
+ olChk(ValidateOutBuffer(pcbWritten, sizeof(ULONG)));
+ *pcbWritten = 0;
+ }
+ olChk(ValidateHugeBuffer(pb, cb));
+ olChk(Validate());
+ olChk(CheckHandle());
+#else
+ olAssert(_hFile != INVALID_FH);
+ *pcbWritten = 0;
+#endif
+
+#if DBG == 1
+ ULONG ulCurrentSize;
+
+ ulCurrentSize = GetFileSize(_hFile, NULL);
+ if ((ULIGetLow(ulPosition) + cb) > ulCurrentSize)
+ {
+ if (SimulateFailure(DBF_DISKFULL))
+ {
+ olErr(EH_Err, STG_E_MEDIUMFULL);
+ }
+ }
+#endif
+
+#if WIN32 == 100 || WIN32 > 200
+
+ TurnOffMapping();
+
+#endif
+
+#ifdef TAKE_HINT
+
+ if (_pbBaseAddr != NULL)
+ {
+ if ((ulLow + cb) > _cbFileSize)
+ {
+ olVerify(UnmapViewOfFile(_pbBaseAddr));
+ _pbBaseAddr = NULL;
+ }
+ else
+ {
+ __try
+ {
+ memcpy (_pbBaseAddr+ulLow, pb, cb);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ return STG_E_WRITEFAULT;
+ }
+ *pcbWritten = cb;
+ return S_OK;
+ }
+
+ if (_hMapObject != NULL)
+ {
+ olVerify(CloseHandle(_hMapObject));
+ _hMapObject = NULL;
+ }
+ }
+
+#endif
+
+#if DBG == 1
+ _ulSeeks++;
+#endif
+
+#ifndef USE_OVERLAPPED
+ if (_ulLowPos != ulLow)
+ {
+
+ negChk(SetFilePointer(_hFile, ulLow, &lHigh,
+ FILE_BEGIN));
+ _ulLowPos = ulLow;
+ CheckSeek();
+ olLowLog(("STGIO - Seek : %8x at %8x\n", _hFile, ulLow));
+#if DBG == 1
+ _ulRealSeeks++;
+#endif
+ }
+ boolChk(WriteFile(_hFile, pb, cb, pcbWritten, NULL));
+#else // ifndef USE_OVERLAPPED
+ if (_ulLowPos != ulLow)
+ {
+ OVERLAPPED Overlapped;
+ Overlapped.Offset = ulLow;
+ Overlapped.OffsetHigh = 0;
+ Overlapped.hEvent = NULL;
+ boolChk(WriteFile(_hFile, pb, cb, pcbWritten,&Overlapped));
+ }
+ else
+ {
+ boolChk(WriteFile(_hFile, pb, cb, pcbWritten, NULL));
+ }
+
+#endif
+ _ulLowPos = ulLow + *pcbWritten;
+
+ olLowLog(("STGIO - Write: %8x at %8x, %8d, %8d -->\n", _hFile, ulLow, cb, *pcbWritten));
+
+ sc = S_OK;
+
+EH_Err:
+ CheckSeek();
+ return ResultFromScode(sc);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::Flush, public
+//
+// Synopsis: Flushes buffers
+//
+// Returns: Appropriate status code
+//
+// History: 24-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CFileStream::Flush(void)
+{
+ CheckSeek();
+
+#if WIN32 == 200
+ SCODE sc = S_OK;
+
+ if (_hReserved == INVALID_FH)
+ {
+ if (!DuplicateHandle(GetCurrentProcess(), _hFile, GetCurrentProcess(),
+ &_hReserved, 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ //We couldn't get a handle, so flush everything just to be
+ //safe.
+ sc = FlushCache();
+ }
+ else
+ {
+ olAssert(_hReserved != INVALID_FH);
+ olVerify(CloseHandle(_hReserved));
+ _hReserved = INVALID_FH;
+ }
+ }
+ else
+ {
+ //In this case, we already have a duplicate of the file handle
+ // reserved, so close it, then reopen it again.
+ olVerify(CloseHandle(_hReserved));
+ _hReserved = INVALID_FH;
+ }
+
+ if ((_hReserved == INVALID_FH) && (_grfLocal & LFF_RESERVE_HANDLE))
+ {
+ //Reacquire reserved handle.
+ //If this fails there isn't anything we can do about it. We'll
+ // try to reacquire the handle later when we really need it.
+ DuplicateHandle(GetCurrentProcess(), _hFile, GetCurrentProcess(),
+ &_hReserved, 0, FALSE, DUPLICATE_SAME_ACCESS);
+ }
+
+ return ResultFromScode(sc);
+#else
+ //On NT, the file system does the right thing, we think.
+ return S_OK;
+#endif
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::FlushCache, public
+//
+// Synopsis: Flushes buffers
+//
+// Returns: Appropriate status code
+//
+// History: 12-Feb-93 AlexT Created
+//
+// Notes:
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CFileStream::FlushCache(void)
+{
+ SCODE sc;
+
+ olFileStOut((DEB_FILEST, "In CFileStream::Flush()\n"));
+ CheckSeek();
+#ifdef CFS_SECURE
+ olChk(Validate());
+ olChk(CheckHandle());
+#else
+ olAssert(_hFile != INVALID_FH);
+#endif
+
+ boolChk(FlushFileBuffers(_hFile));
+ sc = S_OK;
+
+ olFileStOut((DEB_FILEST, "Out CFileStream::Flush\n"));
+EH_Err:
+ CheckSeek();
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::SetSize, public
+//
+// Synopsis: Sets the size of the LStream
+//
+// Arguments: [ulSize] - New size
+//
+// Returns: Appropriate status code
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CFileStream::SetSize(ULARGE_INTEGER ulSize)
+{
+ SCODE sc;
+#ifdef ASYNC
+ olAssert((_ppc == NULL) || (_ppc->HaveMutex()));
+#endif
+
+#ifdef ASYNC
+ LONG lHigh = ULIGetHigh(ulSize);
+ ULONG ulLow = ULIGetLow(ulSize);
+
+ DWORD dwTerminate;
+ dwTerminate = _pgfst->GetTerminationStatus();
+ if (dwTerminate == TERMINATED_ABNORMAL)
+ {
+ sc = STG_E_INCOMPLETE;
+ }
+ else if ((dwTerminate == TERMINATED_NORMAL) ||
+ (ulLow <= _pgfst->GetHighWaterMark()))
+ {
+#endif
+ sc = SetSizeWorker(ulSize);
+#ifdef ASYNC
+ }
+ else
+ {
+ _pgfst->SetFailurePoint(ulLow);
+ sc = E_PENDING;
+ }
+#endif
+ return sc;
+}
+
+
+
+SCODE CFileStream::SetSizeWorker(ULARGE_INTEGER ulSize)
+{
+ SCODE sc;
+ LONG lHigh = ULIGetHigh(ulSize);
+ ULONG ulLow = ULIGetLow(ulSize);
+
+ olAssert(lHigh == 0 &&
+ aMsg("High dword other than zero passed to filestream."));
+
+
+
+ olFileStOut((DEB_FILEST, "In CFileStream::SetSize:%p(%lu:%lu)\n",
+ this, ULIGetHigh(ulSize), ULIGetLow(ulSize)));
+
+ CheckSeek();
+#ifdef CFS_SECURE
+ olChk(Validate());
+ olChk(CheckHandle());
+#else
+ olAssert(_hFile != INVALID_FH);
+#endif
+
+#if WIN32 == 100 || WIN32 > 200
+
+ TurnOffMapping();
+
+#endif
+
+#if DBG == 1
+ ULONG ulCurrentSize;
+
+ ulCurrentSize = GetFileSize(_hFile, NULL);
+ if (ulCurrentSize < ulLow)
+ {
+ if (SimulateFailure(DBF_DISKFULL))
+ {
+ olErr(EH_Err, STG_E_MEDIUMFULL);
+ }
+ }
+#endif
+
+#if DBG == 1
+ _ulSeeks++;
+#endif
+
+
+ if (_ulLowPos != ulLow)
+ {
+ negChk(SetFilePointer(_hFile, ulLow, &lHigh,
+ FILE_BEGIN));
+ _ulLowPos = ulLow;
+ CheckSeek();
+
+#if DBG == 1
+ _ulRealSeeks++;
+#endif
+ }
+ boolChk(SetEndOfFile(_hFile));
+
+ sc = S_OK;
+
+ olFileStOut((DEB_FILEST, "Out CFileStream::SetSize\n"));
+EH_Err:
+ CheckSeek();
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::LockRegion, public
+//
+// Synopsis: Gets a lock on a portion of the LStream
+//
+// Arguments: [ulStartOffset] - Lock start
+// [cbLockLength] - Length
+// [dwLockType] - Exclusive/Read only
+//
+// Returns: Appropriate status code
+//
+// History: 20-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CFileStream::LockRegion(ULARGE_INTEGER ulStartOffset,
+ ULARGE_INTEGER cbLockLength,
+ DWORD dwLockType)
+{
+ SCODE sc;
+
+ olFileStOut((DEB_FILEST, "In CFileStream::LockRegion("
+ "%lu:%lu, %lu:%lu, %lu)\n", ULIGetHigh(ulStartOffset),
+ ULIGetLow(ulStartOffset), ULIGetHigh(cbLockLength),
+ ULIGetLow(cbLockLength), dwLockType));
+ CheckSeek();
+#ifdef CFS_SECURE
+ olChk(Validate());
+ olChk(CheckHandle());
+ if (!VALID_LOCKTYPE(dwLockType))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+#else
+ olAssert(_hFile != INVALID_FH);
+#endif
+
+ boolChk(LockFile(_hFile, ULIGetLow(ulStartOffset),
+ ULIGetHigh(ulStartOffset), ULIGetLow(cbLockLength),
+ ULIGetHigh(cbLockLength)));
+
+ sc = S_OK;
+
+ olFileStOut((DEB_FILEST, "Out CFileStream::LockRegion\n"));
+EH_Err:
+ CheckSeek();
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::UnlockRegion, public
+//
+// Synopsis: Releases an existing lock
+//
+// Arguments: [ulStartOffset] - Lock start
+// [cbLockLength] - Length
+// [dwLockType] - Lock type
+//
+// Returns: Appropriate status code
+//
+// History: 20-Feb-92 DrewB Created
+//
+// Notes: Must match an existing lock exactly
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CFileStream::UnlockRegion(ULARGE_INTEGER ulStartOffset,
+ ULARGE_INTEGER cbLockLength,
+ DWORD dwLockType)
+{
+ SCODE sc;
+
+ olFileStOut((DEB_FILEST, "In CFileStream::UnlockRegion("
+ "%lu:%lu, %lu:%lu, %lu)\n", ULIGetHigh(ulStartOffset),
+ ULIGetLow(ulStartOffset), ULIGetHigh(cbLockLength),
+ ULIGetLow(cbLockLength), dwLockType));
+
+ CheckSeek();
+#ifdef CFS_SECURE
+ olChk(Validate());
+ olChk(CheckHandle());
+ if (!VALID_LOCKTYPE(dwLockType))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ if (dwLockType != LOCK_EXCLUSIVE && dwLockType != LOCK_ONLYONCE)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+#else
+ olAssert(_hFile != INVALID_FH);
+#endif
+
+ boolChk(UnlockFile(_hFile, ULIGetLow(ulStartOffset),
+ ULIGetHigh(ulStartOffset),
+ ULIGetLow(cbLockLength),
+ ULIGetHigh(cbLockLength)));
+
+ sc = S_OK;
+
+ olFileStOut((DEB_FILEST, "Out CFileStream::UnlockRegion\n"));
+EH_Err:
+ CheckSeek();
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Function: FileTimeToTimeT, private
+//
+// Synopsis: Converts a FILETIME to a TIME_T
+//
+// Arguments: [pft] - FILETIME
+//
+// Returns: TIME_T
+//
+// History: 12-May-92 DrewB Created
+//
+//+--------------------------------------------------------------
+
+#ifdef NOFILETIME
+TIME_T FileTimeToTimeT(LPFILETIME pft)
+{
+ WORD dt, tm;
+ struct tm tmFile;
+
+ olVerify(FileTimeToDosDateTime(pft, &dt, &tm));
+ tmFile.tm_sec = (tm&31)*2;
+ tmFile.tm_min = (tm>>5)&63;
+ tmFile.tm_hour = (tm>>11)&31;
+ tmFile.tm_mday = dt&31;
+ tmFile.tm_mon = ((dt>>5)&15)-1;
+ tmFile.tm_year = (dt>>9)+80;
+ return (TIME_T)mktime(&tmFile);
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::Stat, public
+//
+// Synopsis: Fills in a stat buffer for this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 25-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+_OLESTDMETHODIMP CFileStream::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+
+ olFileStOut((DEB_FILEST, "In CFileStream::Stat(%p)\n", pstatstg));
+
+ CheckSeek();
+#ifdef CFS_SECURE
+ olChkTo(EH_RetSc, ValidateOutBuffer(pstatstg, sizeof(STATSTGW)));
+ olChk(VerifyStatFlag(grfStatFlag));
+ olChk(Validate());
+ olChk(CheckHandle());
+#else
+ olAssert(_hFile != INVALID_FH);
+#endif
+
+ negChk(pstatstg->cbSize.LowPart =
+ GetFileSize(_hFile, &pstatstg->cbSize.HighPart));
+#ifdef NOFILETIME
+ FILETIME ftCreation, ftAccess, ftWrite;
+ boolChk(GetFileTime(_hFile, &ftCreation, &ftAccess, &ftWrite));
+ if (ftCreation.dwLowDateTime == 0 && ftCreation.dwHighDateTime == 0)
+ ftCreation = ftWrite;
+ if (ftAccess.dwLowDateTime == 0 && ftAccess.dwHighDateTime == 0)
+ ftAccess = ftWrite;
+ pstatstg->ctime = FileTimeToTimeT(&ftCreation);
+ pstatstg->atime = FileTimeToTimeT(&ftAccess);
+ pstatstg->mtime = FileTimeToTimeT(&ftWrite);
+#else
+ boolChk(GetFileTime(_hFile, &pstatstg->ctime, &pstatstg->atime,
+ &pstatstg->mtime));
+#endif
+ olHVerSucc(GetLocksSupported(&pstatstg->grfLocksSupported));
+ pstatstg->type = STGTY_LOCKBYTES;
+ pstatstg->grfMode = DFlagsToMode(_pgfst->GetDFlags());
+ pstatstg->pwcsName = NULL;
+ if ((grfStatFlag & STATFLAG_NONAME) == 0)
+ {
+ olChk(GetName(&pstatstg->pwcsName));
+ }
+ sc = S_OK;
+ CheckSeek();
+
+ olFileStOut((DEB_FILEST, "Out CFileStream::Stat\n"));
+ return NOERROR;
+
+EH_Err:
+#ifdef CFS_SECURE
+ memset(pstatstg, 0, sizeof(STATSTGW));
+EH_RetSc:
+#endif
+ CheckSeek();
+#ifndef OLEWIDECHAR
+ return sc;
+#else
+ return ResultFromScode(sc);
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::SwitchToFile, public
+//
+// Synopsis: Changes the file this filestream uses
+//
+// Arguments: [ptcsFile] - File name
+// [ulCommitSize] -- Size needed to do overwrite commit
+// [cbBuffer] - Buffer size
+// [pvBuffer] - Buffer for file copying
+//
+// Returns: Appropriate status code
+//
+// History: 08-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStream::SwitchToFile(OLECHAR const *ptcsFile,
+ ULONG ulCommitSize,
+ ULONG cbBuffer,
+ void *pvBuffer)
+{
+ SCODE sc;
+ DWORD cbRead, cbWritten;
+ FILEH hOldFile;
+ WCHAR awcOldName[_MAX_PATH];
+ WCHAR wcsFile[_MAX_PATH];
+ DWORD dwOldStartFlags;
+
+#ifdef ASYNC
+ olAssert((_ppc == NULL) || (_ppc->HaveMutex()));
+#endif
+
+ olFileStOut((DEB_FILEST, "In CFileStream::SwitchToFile:%p(%s, %lu, %p)\n",
+ this, ptcsFile, cbBuffer, pvBuffer));
+
+ // Check for marshals
+ if (_pgfst->GetRefCount() != 1)
+ olErr(EH_Err, STG_E_EXTANTMARSHALLINGS);
+
+ CheckSeek();
+ // Seek to beginning
+ negChk(SetFilePointer(_hFile, 0, NULL, FILE_BEGIN));
+#if DBG == 1
+ _ulSeeks++;
+ _ulRealSeeks++;
+#endif
+
+#if WIN32 == 100 || WIN32 > 200
+
+ TurnOffMapping();
+
+#endif
+
+ _ulLowPos = 0;
+
+ // Preserve old file information
+ lstrcpyW(awcOldName, _pgfst->GetName());
+ hOldFile = _hFile;
+ dwOldStartFlags = _pgfst->GetStartFlags();
+
+ // Set file information to prepare for new Init
+ _pgfst->SetName(NULL);
+ _hFile = INVALID_FH;
+ _pgfst->SetStartFlags((dwOldStartFlags & ~(RSF_CREATEFLAGS |
+ RSF_CONVERT |
+ RSF_DELETEONRELEASE |
+ RSF_OPEN)) |
+ RSF_CREATE);
+
+ // Release reserved file handle so it can be consumed
+ if (_hReserved != INVALID_FH)
+ {
+ olVerify(CloseHandle(_hReserved));
+ _hReserved = INVALID_FH;
+ }
+
+ // Attempt to create new file
+ TRY
+ {
+#ifndef OLEWIDECHAR
+ if (mbstowcs(wcsFile, ptcsFile, _MAX_PATH) == (size_t)-1)
+ olErr(EH_ReplaceOld, STG_E_INVALIDNAME);
+#else
+ lstrcpyW(wcsFile, ptcsFile);
+#endif
+ }
+ CATCH(CException, e)
+ {
+ UNREFERENCED_PARM(e);
+ olErr(EH_ReplaceOld, STG_E_INVALIDPOINTER);
+ }
+ END_CATCH
+ olChkTo(EH_ReplaceOld, Init(wcsFile));
+
+ ULARGE_INTEGER ulNewSize;
+ ULISet32(ulNewSize, ulCommitSize);
+
+ // SetSize to minimum commit size
+ olHChkTo(EH_NewFile, SetSize(ulNewSize));
+ // SetSize changes the file pointer, so move it back to the beginning
+ negChkTo(EH_NewFile, SetFilePointer(_hFile, 0, NULL, FILE_BEGIN));
+#if DBG == 1
+ _ulSeeks++;
+ _ulRealSeeks++;
+#endif
+
+ _ulLowPos = 0;
+
+ // Copy file contents
+ for (;;)
+ {
+ boolChkTo(EH_NewFile,
+ ReadFile(hOldFile, pvBuffer, (UINT)cbBuffer, &cbRead, NULL));
+ if (cbRead == 0)
+ // EOF
+ break;
+ boolChkTo(EH_NewFile,
+ WriteFile(_hFile, pvBuffer, cbRead, &cbWritten, NULL));
+ if (cbWritten != cbRead)
+ olErr(EH_NewFile, STG_E_WRITEFAULT);
+ }
+
+ olVerify(CloseHandle(hOldFile));
+ if (dwOldStartFlags & RSF_DELETEONRELEASE)
+ {
+ // This is allowed to fail if somebody else has
+ // the file open
+ DeleteFileX(awcOldName);
+ }
+
+
+ olDebugOut((DEB_ITRACE, "Out CFileStream::SwitchToFile\n"));
+ _ulLowPos = SetFilePointer(_hFile, 0, NULL, FILE_CURRENT);
+#if DBG == 1
+ _ulSeeks++;
+ _ulRealSeeks++;
+#endif
+ CheckSeek();
+ return S_OK;
+
+EH_NewFile:
+ olVerify(CloseHandle(_hFile));
+ olVerify(DeleteFileX(_pgfst->GetName()));
+EH_ReplaceOld:
+ _pgfst->SetName(awcOldName);
+ _hFile = hOldFile;
+ _pgfst->SetStartFlags(dwOldStartFlags);
+
+EH_Err:
+ _ulLowPos = SetFilePointer(_hFile, 0, NULL, FILE_CURRENT);
+#if DBG == 1
+ _ulSeeks++;
+ _ulRealSeeks++;
+#endif
+ CheckSeek();
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::Delete, public
+//
+// Synopsis: Closes and deletes the file, errors ignored
+//
+// Returns: Appropriate status code
+//
+// History: 09-Feb-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+void CFileStream::Delete(void)
+{
+ olDebugOut((DEB_ITRACE, "In CFileStream::Delete:%p()\n", this));
+ if (_hFile != INVALID_FH)
+ CloseHandle(_hFile);
+ _hFile = INVALID_FH;
+ if (_hReserved != INVALID_FH)
+ CloseHandle(_hReserved);
+ _hReserved = INVALID_FH;
+ DeleteFileX(_pgfst->GetName());
+ olDebugOut((DEB_ITRACE, "Out CFileStream::Delete\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::ReserveHandle, public
+//
+// Synopsis: Reserves a backup file handle for handle-required operations
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jul-93 DrewB Created
+//
+// Notes: May be called with a handle already reserved
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStream::ReserveHandle(void)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CFileStream::ReserveHandle:%p()\n", this));
+ if (_hReserved == INVALID_FH &&
+ !DuplicateHandle(GetCurrentProcess(), _hFile, GetCurrentProcess(),
+ &_hReserved, 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ sc = LAST_STG_SCODE;
+ }
+ else
+ {
+ olDebugOut((DEB_IWARN, "CFileStream reserved %p"
+ "handle %p thread %lX\n",
+ this, _hReserved, GetCurrentThreadId()));
+ sc = S_OK;
+ _grfLocal |= LFF_RESERVE_HANDLE;
+ }
+ olDebugOut((DEB_ITRACE, "Out CFileStream::ReserveHandle => %lX\n", sc));
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::GetSize, public
+//
+// Synopsis: Return the size of the stream
+//
+// Returns: Appropriate status code
+//
+// History: 12-Jul-93 AlexT Created
+//
+// Notes: This is a separate method from Stat as an optimization
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStream::GetSize(ULARGE_INTEGER *puliSize)
+{
+ SCODE sc = S_OK;
+ CheckSeek();
+ negChk(puliSize->LowPart = GetFileSize(_hFile, &puliSize->HighPart));
+
+EH_Err:
+ CheckSeek();
+ return(ResultFromScode(sc));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::SetTime, public
+//
+// Synopsis: Set the times on the ILockbytes
+//
+// Arguments: [tt] -- Which time to set
+// [nt] -- New time stamp
+//
+// Returns: Appropriate status code
+//
+// History: 24-Mar-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CFileStream::SetTime(WHICHTIME tt,
+ TIME_T nt)
+{
+ olFileStOut((DEB_FILEST, "In CFileStream::SetTime()\n"));
+
+ SCODE sc = S_OK;
+
+ FILETIME *pctime = NULL, *patime = NULL, *pmtime = NULL;
+ CheckSeek();
+
+ if (tt == WT_CREATION)
+ {
+ pctime = &nt;
+ }
+ else if (tt == WT_MODIFICATION)
+ {
+ pmtime = &nt;
+ }
+ else
+ {
+ patime = &nt;
+ }
+
+ boolChk(SetFileTime(_hFile,
+ pctime,
+ patime,
+ pmtime));
+
+EH_Err:
+ olFileStOut((DEB_FILEST, "Out CFileStream::SetSize() => %lx\n", sc));
+ CheckSeek();
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::SetAllTimes, public
+//
+// Synopsis: Set the times on the ILockbytes
+//
+// Arguments: [atm] Access time
+// [mtm] Modification time
+// [ctm] Creation time
+//
+// Returns: Appropriate status code
+//
+// History: 24-Nov-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CFileStream::SetAllTimes( TIME_T atm,
+ TIME_T mtm,
+ TIME_T ctm)
+{
+ olFileStOut((DEB_FILEST, "In CFileStream::SetAllTimes()\n"));
+
+ SCODE sc = S_OK;
+
+ CheckSeek();
+
+ boolChk(SetFileTime(_hFile, &ctm, &atm, &mtm));
+
+EH_Err:
+ olFileStOut((DEB_FILEST, "Out CFileStream::SetAllTimes() => %lx\n", sc));
+ CheckSeek();
+ return sc;
+}
+
+
+#ifndef UNICODE
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::DeleteFileUnicode, private
+//
+// Synopsis: Delete a unicode filename for non-unicode platforms.
+//
+// Arguments: [lpFileName] -- Name of file to delete
+//
+// Returns: Return code from DeleteFileA
+//
+// History: 18-May-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+BOOL CFileStream::DeleteFileUnicode(LPCWSTR lpFileName)
+{
+ BOOL f;
+
+ TCHAR atcPath[MAX_PATH + 1];
+
+ UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ f = WideCharToMultiByte(
+ uCodePage,
+ 0,
+ lpFileName,
+ -1,
+ atcPath,
+ _MAX_PATH + 1,
+ NULL,
+ NULL);
+ if (!f)
+ return f;
+
+ return DeleteFileT(atcPath);
+}
+#endif //!UNICODE
+
+
+
+#ifdef ASYNC
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::FillAppend, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStream::FillAppend(void const *pv,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ SCODE sc;
+ SAFE_SEM;
+ HANDLE hEvent;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::FillAppend:%p()\n", this));
+ olChk(TakeSafeSem());
+ if (_pgfst->GetTerminationStatus() != UNTERMINATED)
+ {
+ sc = STG_E_TERMINATED;
+ }
+ else
+ {
+ ULONG cbWritten;
+ ULONG ulHighWater = _pgfst->GetHighWaterMark();
+ ULARGE_INTEGER uli;
+ uli.QuadPart = ulHighWater;
+ sc = CFileStream::WriteAtWorker(uli, pv, cb, &cbWritten);
+ _pgfst->SetHighWaterMark(ulHighWater + cbWritten);
+ if (pcbWritten != NULL)
+ {
+ *pcbWritten = cbWritten;
+ }
+
+ hEvent = _ppc->GetNotificationEvent();
+ if (!PulseEvent(hEvent))
+ {
+ sc = Win32ErrorToScode(GetLastError());
+ }
+ }
+
+ olFileStOut((DEB_ITRACE, "Out CFileStream::FillAppend\n"));
+EH_Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::FillAt, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStream::FillAt(ULARGE_INTEGER ulOffset,
+ void const *pv,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ //BUGBUG: Implement
+ //BUGBUG: Thread protect
+ olFileStOut((DEB_ITRACE, "In CFileStream::FillAt:%p()\n", this));
+ olFileStOut((DEB_ITRACE, "Out CFileStream::FillAt\n"));
+ return STG_E_UNIMPLEMENTEDFUNCTION;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::SetFillSize, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStream::SetFillSize(ULARGE_INTEGER ulSize)
+{
+ SCODE sc;
+ SAFE_SEM;
+
+ olFileStOut((DEB_ITRACE,
+ "In CFileStream::SetFillSize:%p()\n", this));
+
+ olChk(TakeSafeSem());
+ if (_pgfst->GetTerminationStatus() == TERMINATED_ABNORMAL)
+ {
+ sc = STG_E_INCOMPLETE;
+ }
+ else
+ {
+ sc = SetSizeWorker(ulSize);
+ }
+ olFileStOut((DEB_ITRACE, "Out CFileStream::SetFillSize\n"));
+EH_Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::Terminate, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 28-Dec-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStream::Terminate(BOOL bCanceled)
+{
+ SCODE sc;
+ SAFE_SEM;
+ HANDLE hEvent;
+
+ olFileStOut((DEB_ITRACE, "In CFileStream::Terminate:%p()\n", this));
+
+ olChk(TakeSafeSem());
+ _pgfst->SetTerminationStatus((bCanceled) ?
+ TERMINATED_ABNORMAL :
+ TERMINATED_NORMAL);
+
+ hEvent = _ppc->GetNotificationEvent();
+
+ if ((hEvent != INVALID_HANDLE_VALUE) && (!SetEvent(hEvent)))
+ {
+ return Win32ErrorToScode(GetLastError());
+ }
+
+ olFileStOut((DEB_ITRACE, "Out CFileStream::Terminate\n"));
+EH_Err:
+ return sc;
+}
+
+void CFileStream::StartAsyncMode(void)
+{
+ //Note: No semaphore here - this must be called before the ILockBytes
+ // is returned to an app.
+ _pgfst->SetTerminationStatus(UNTERMINATED);
+}
+
+STDMETHODIMP CFileStream::GetFailureInfo(ULONG *pulWaterMark,
+ ULONG *pulFailurePoint)
+{
+ SAFE_SEM;
+ TakeSafeSem();
+ *pulWaterMark = _pgfst->GetHighWaterMark();
+ *pulFailurePoint = _pgfst->GetFailurePoint();
+ return S_OK;
+}
+
+STDMETHODIMP CFileStream::GetTerminationStatus(DWORD *pdwFlags)
+{
+ SAFE_SEM;
+ TakeSafeSem();
+ *pdwFlags = _pgfst->GetTerminationStatus();
+ return S_OK;
+}
+
+#endif //ASYNC
diff --git a/private/ole32/stg/exp/lock.cxx b/private/ole32/stg/exp/lock.cxx
new file mode 100644
index 000000000..b21591e0a
--- /dev/null
+++ b/private/ole32/stg/exp/lock.cxx
@@ -0,0 +1,776 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: lock.cxx
+//
+// Contents: Remote exclusion stuff for docfile
+//
+// Functions: GetAccess
+// ReleaseAccess
+// GetOpen
+// ReleaseOpen
+//
+// History: 09-Mar-92 PhilipLa Created.
+// 20-Jul-93 DrewB Added dual locking for Mac
+// compatibility
+//
+//--------------------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <header.hxx>
+#include <lock.hxx>
+
+// Offset to next lock group from a particular group
+#define OLOCKGROUP 1
+
+// The docfile originally locked at 0xffffff00
+// It turned out that the Mac can only lock to 0x7fffffff,
+// so for compatibility reasons it was decided that the
+// docfile would lock at both places. Thus, we have one routine
+// that locks with a mask for the offset so that we can
+// selectively suppress the high bit
+// Since lock indices fit easily within 16 bits, the two
+// lock indices are now combined into the existing ULONG
+// value to preserve compatibility with other code. This
+// implies that lock indices from these routines must be
+// handled opaquely since they are no longer simple numbers
+
+// 09/23/1993 - Further change:
+// To avoid a Netware 2.2 problem we are offsetting the lock regions
+// so that they differ by more than just the high bit. The high
+// lock region was moved to 0xffffff80, moving the low region to
+// 0x7fffff80. The 0x80 was then taken out of the high mask so that
+// the net is no change for high locks and the low locks moved up by 0x80
+
+// Masks for separate lock locations
+#define MASK_LOW 0x7fffffff
+#ifndef _MAC
+#define MASK_HIGH 0xffffff7f
+#endif
+
+//In a specific open case (Read-only, deny-write), we don't need to
+//take locks.
+#define P_NOLOCK(df) (!P_WRITE(df) && P_READ(df) && \
+ P_DENYWRITE(df) && !P_DENYREAD(df))
+
+//+--------------------------------------------------------------
+//
+// Function: GetAccessWithMask, private
+//
+// Synopsis: Takes appropriate access locks on an LStream,
+// masking the offset with the given mask
+//
+// Arguments: [plst] - LStream
+// [df] - Permissions needed
+// [ulMask] - Mask
+// [poReturn] - Index of lock taken
+//
+// Returns: Appropriate status code
+//
+// Modifies: [poReturn]
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_GetAccessWithMask)
+#endif
+
+static SCODE GetAccessWithMask(ILockBytes *plst,
+ DFLAGS df,
+ ULONG ulMask,
+ ULONG *poReturn)
+{
+ SCODE sc;
+ ULARGE_INTEGER ulOffset, cbLength;
+
+ olDebugOut((DEB_ITRACE, "In GetAccessWithMask(%p, %X, %lX, %p)\n",
+ plst, df, ulMask, poReturn));
+ olAssert((df & ~(DF_READ | DF_WRITE)) == 0 && P_READ(df) != P_WRITE(df));
+ *poReturn = NOLOCK;
+ ULISet32(ulOffset, OACCESS & ulMask);
+ if (P_READ(df))
+ {
+ ULISet32(cbLength, 1);
+ olHChk(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ for (USHORT i = 0; i < CREADLOCKS; i++)
+ {
+ ULISetLow(ulOffset, (OREADLOCK+i) & ulMask);
+ sc = DfGetScode(plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ if (SUCCEEDED(sc))
+ {
+ *poReturn = i+1;
+ break;
+ }
+ }
+ ULISetLow(ulOffset, OACCESS & ulMask);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ if (i == CREADLOCKS)
+ olErr(EH_Err, STG_E_TOOMANYOPENFILES);
+ }
+ else
+ {
+ olAssert((OACCESS + 1 == OREADLOCK) && aMsg("Bad lock dependency"));
+ ULISet32(cbLength, 1 + CREADLOCKS);
+ olChk(DfGetScode(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE)));
+ *poReturn = 0xFFFF;
+ }
+ olDebugOut((DEB_ITRACE, "Out GetAccessWithMask => %lu\n", *poReturn));
+ olAssert(*poReturn != NOLOCK);
+ return S_OK;
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: ReleaseAccessWithMask, private
+//
+// Synopsis: Releases an access lock at the given offset
+//
+// Arguments: [plst] - LStream that is locked
+// [df] - Permission to release
+// [offset] - Offset of locks taken
+// [ulMask] - Mask
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_ReleaseAccessWithMask)
+#endif
+
+static void ReleaseAccessWithMask(ILockBytes *plst,
+ DFLAGS df,
+ ULONG offset,
+ ULONG ulMask)
+{
+ ULARGE_INTEGER ulOffset, cbLength;
+
+ olDebugOut((DEB_ITRACE, "In ReleaseAccessWithMask(%p, %lX, %lu, %lX)\n",
+ plst, df, offset, ulMask));
+ olAssert((df & ~(DF_READ | DF_WRITE)) == 0 && P_READ(df) != P_WRITE(df));
+ if (offset == NOLOCK)
+ return;
+ if (P_READ(df))
+ {
+ ULISet32(ulOffset, (offset+OREADLOCK-1) & ulMask);
+ ULISet32(cbLength, 1);
+ olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))) &&
+ aMsg("Non-fatal (Removable media?)"));
+ }
+ else
+ {
+ olAssert((OACCESS + 1 == OREADLOCK) && aMsg("Bad lock dependency"));
+ ULISet32(ulOffset, OACCESS & ulMask);
+ ULISet32(cbLength, 1 + CREADLOCKS);
+ olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))) &&
+ aMsg("Non-fatal (Removable media?)"));
+ }
+ olDebugOut((DEB_ITRACE, "Out ReleaseAccessWithMask\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Function: GetAccess, public
+//
+// Synopsis: Takes appropriate access locks on an LStream
+//
+// Arguments: [plst] - LStream
+// [df] - Permissions needed
+// [poReturn] - Index of lock taken
+//
+// Returns: Appropriate status code
+//
+// Modifies: [poReturn]
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_GetAccess)
+#endif
+
+SCODE GetAccess(ILockBytes *plst,
+ DFLAGS df,
+ ULONG *poReturn)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In GetAccess(%p, %X, %p)\n",
+ plst, df, poReturn));
+
+ // Make sure our lock region hasn't overflowed 32 bits
+ olAssert(OLOCKREGIONEND > OACCESS);
+
+ // If we aren't locking high, this dual lock business is unnecessary
+ olAssert(OACCESS & 0x80000000);
+
+ olChk(GetAccessWithMask(plst, df, MASK_LOW, poReturn));
+ olAssert(*poReturn < 0x10000);
+#ifndef _MAC
+#ifdef _LOCK_HIGH
+ ULONG ulIndex;
+ olChkTo(EH_Low, GetAccessWithMask(plst, df, MASK_HIGH, &ulIndex));
+ olAssert(ulIndex < 0x10000);
+ *poReturn |= ulIndex << 16;
+#endif
+#endif
+
+ olDebugOut((DEB_ITRACE, "Out GetAccess => %lu\n", *poReturn));
+ return S_OK;
+
+#ifndef _MAC
+#ifdef _LOCK_HIGH
+ EH_Low:
+ ReleaseAccessWithMask(plst, df, *poReturn, MASK_LOW);
+#endif
+#endif
+ EH_Err:
+ *poReturn = NOLOCK;
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: ReleaseAccess, public
+//
+// Synopsis: Releases access locks
+//
+// Arguments: [plst] - LStream that is locked
+// [df] - Permission to release
+// [offset] - Offset of locks taken
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_ReleaseAccess)
+#endif
+
+void ReleaseAccess(ILockBytes *plst, DFLAGS df, ULONG offset)
+{
+ olDebugOut((DEB_ITRACE, "In ReleaseAccess(%p, %lX, %lu)\n",
+ plst, df, offset));
+
+ ReleaseAccessWithMask(plst, df, offset & 0xffff, MASK_LOW);
+#ifndef _MAC
+#ifdef _LOCK_HIGH
+ ReleaseAccessWithMask(plst, df, offset >> 16, MASK_HIGH);
+#endif
+#endif
+
+ olDebugOut((DEB_ITRACE, "Out ReleaseAccess\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Function: GetOpenWithMask, private
+//
+// Synopsis: Gets locks on an LStream during opening, masking the offset
+//
+// Arguments: [plst] - LStream
+// [df] - Permissions to take
+// [fCheck] - Whether to check for existing locks or not
+// [ulMask] - Mask
+// [puReturn] - Index of lock taken
+//
+// Returns: Appropriate status code
+//
+// Modifies: [puReturn]
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_GetOpenWithMask)
+#endif
+
+static SCODE GetOpenWithMask(ILockBytes *plst,
+ DFLAGS df,
+ BOOL fCheck,
+ ULONG ulMask,
+ ULONG *puReturn)
+{
+ SCODE sc;
+ ULONG i;
+ ULARGE_INTEGER ulOffset, cbLength;
+
+ olDebugOut((DEB_ITRACE, "In GetOpenWithMask(%p, %lX, %d, %lX, %p)\n",
+ plst, df, fCheck, ulMask, puReturn));
+ *puReturn = NOLOCK;
+
+ ULISet32(ulOffset, OUPDATE & ulMask);
+ ULISet32(cbLength, 1);
+ olHChk(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ if (fCheck)
+ {
+ ULISetLow(cbLength, COPENLOCKS);
+ if (P_DENYREAD(df))
+ {
+ ULISetLow(ulOffset, OOPENREADLOCK & ulMask);
+ olHChkTo(EH_UnlockUpdate, plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+#ifndef USE_NOSNAPSHOT
+ if (P_DENYWRITE(df))
+#else
+ if (P_DENYWRITE(df) || P_NOSNAPSHOT(df))
+#endif
+ {
+ ULISetLow(ulOffset, OOPENWRITELOCK & ulMask);
+ sc = plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE);
+ if (SUCCEEDED(sc))
+ {
+ olHVerSucc(plst->UnlockRegion(ulOffset,
+ cbLength,
+ LOCK_ONLYONCE));
+ }
+#ifdef USE_NOSNAPSHOT
+ else if (P_NOSNAPSHOT(df))
+ {
+ //There is an existing writer. In order for this
+ //open to succeed, there must also be a lock in the
+ //no-snapshot region. Otherwise we have a case where
+ //a normal open proceeded a no-snapshot open attempt,
+ //and mixing modes is not allowed.
+ ULISetLow(ulOffset, OOPENNOSNAPSHOTLOCK & ulMask);
+ sc = plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE);
+ if (SUCCEEDED(sc))
+ {
+ //There was no no-snapshot lock. No mixing modes,
+ //so fail here.
+ olHVerSucc(plst->UnlockRegion(ulOffset,
+ cbLength,
+ LOCK_ONLYONCE));
+ olErr(EH_UnlockUpdate, STG_E_LOCKVIOLATION);
+ }
+ }
+#endif
+ else
+ {
+ olErr(EH_UnlockUpdate, sc);
+ }
+ }
+ if (P_READ(df))
+ {
+ ULISetLow(ulOffset, OOPENDENYREADLOCK & ulMask);
+ olHChkTo(EH_UnlockUpdate, plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+ if (P_WRITE(df))
+ {
+ ULISetLow(ulOffset, OOPENDENYWRITELOCK & ulMask);
+#ifndef USE_NOSNAPSHOT
+ olHChkTo(EH_UnlockUpdate, plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+#else
+ sc = plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE);
+ if (P_NOSNAPSHOT(df) && (sc == STG_E_LOCKVIOLATION))
+ {
+ //The deny-write lock may be the fake holder we use for
+ //no-snapshot mode. Check then no-snapshot region - if
+ //there is a lock there too, then this succeeds, otherwise
+ //the deny-write lock is real and we must fail the call.
+ ULISetLow(ulOffset, OOPENNOSNAPSHOTLOCK & ulMask);
+ sc = plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE);
+ if (sc != STG_E_LOCKVIOLATION)
+ {
+ if (SUCCEEDED(sc))
+ {
+ olHVerSucc(plst->UnlockRegion(ulOffset,
+ cbLength,
+ LOCK_ONLYONCE));
+ olErr(EH_UnlockUpdate, STG_E_LOCKVIOLATION);
+ }
+ else
+ {
+ olErr(EH_UnlockUpdate, sc);
+ }
+ }
+ }
+ else
+ {
+ olHChkTo(EH_UnlockUpdate, sc);
+ olHVerSucc(plst->UnlockRegion(ulOffset,
+ cbLength,
+ LOCK_ONLYONCE));
+ }
+#endif
+ }
+ }
+
+ //If we are read-only and deny-write, and we are on our
+ // ILockBytes, we don't need to lock and can rely on the FS
+ // to handle the access control.
+ if (P_NOLOCK(df))
+ {
+ //QueryInterface to see if this ILockBytes is ours
+
+ IFileLockBytes *pfl;
+ if (SUCCEEDED(plst->QueryInterface(IID_IFileLockBytes,
+ (void **) &pfl)))
+ {
+ pfl->Release();
+
+ ULISetLow(ulOffset, OUPDATE & ulMask);
+ ULISetLow(cbLength, 1);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+
+ *puReturn = NOLOCK;
+ return S_OK;
+ }
+ }
+
+
+ ULISetLow(cbLength, 1);
+ for (i = 0; i < COPENLOCKS; i = i + OLOCKGROUP)
+ {
+ ULISetLow(ulOffset, (OOPENREADLOCK+i) & ulMask);
+ olHChkTo(EH_Loop, plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ ULISetLow(ulOffset, (OOPENWRITELOCK+i) & ulMask);
+ olHChkTo(EH_UnlockR, plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ ULISetLow(ulOffset, (OOPENDENYREADLOCK+i) & ulMask);
+ olHChkTo(EH_UnlockW, plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ ULISetLow(ulOffset, (OOPENDENYWRITELOCK+i) & ulMask);
+#ifdef USE_NOSNAPSHOT
+ olHChkTo(EH_UnlockDR, plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ if (P_NOSNAPSHOT(df))
+ {
+ //Note that in the non no-snapshot case we don't need to
+ //grab this lock, unlike the others where we must grab all
+ //four to make sure we have a valid slot. This is because
+ //a no-snapshot open will always have a corresponding
+ //deny-write lock in the same slot.
+ ULISetLow(ulOffset, (OOPENNOSNAPSHOTLOCK+i) & ulMask);
+ if (SUCCEEDED(DfGetScode(plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))))
+ {
+ break;
+ }
+ //Unlock the deny-write lock, then all the rest.
+ ULISetLow(ulOffset, (OOPENDENYWRITELOCK + i));
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+ else
+ {
+ //We're not no-snapshot, and we've gotten all our locks
+ // successfully, so bail.
+ break;
+ }
+ EH_UnlockDR:
+#else
+ if (SUCCEEDED(DfGetScode(plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))))
+ break;
+#endif //USE_NOSNAPSHOT
+ ULISetLow(ulOffset, (OOPENDENYREADLOCK+i) & ulMask);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ EH_UnlockW:
+ ULISetLow(ulOffset, (OOPENWRITELOCK+i) & ulMask);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ EH_UnlockR:
+ ULISetLow(ulOffset, (OOPENREADLOCK+i) & ulMask);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ EH_Loop:
+ ;
+ }
+ if (i >= COPENLOCKS)
+ olErr(EH_UnlockUpdate, STG_E_TOOMANYOPENFILES);
+ if (!P_READ(df))
+ {
+ ULISetLow(ulOffset, (OOPENREADLOCK+i) & ulMask);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+ if (!P_WRITE(df))
+ {
+ ULISetLow(ulOffset, (OOPENWRITELOCK+i) & ulMask);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+ if (!P_DENYREAD(df))
+ {
+ ULISetLow(ulOffset, (OOPENDENYREADLOCK+i) & ulMask);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+#ifdef USE_NOSNAPSHOT
+ if (!P_DENYWRITE(df) && !P_NOSNAPSHOT(df))
+#else
+ if (!P_DENYWRITE(df))
+#endif
+ {
+ ULISetLow(ulOffset, (OOPENDENYWRITELOCK+i) & ulMask);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+ ULISetLow(ulOffset, OUPDATE & ulMask);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+
+ // 0 <= i < COPENLOCKS, but 0 is the invalid value, so increment
+ // on the way out
+ *puReturn = i + 1;
+ olAssert(*puReturn != NOLOCK);
+
+ olDebugOut((DEB_ITRACE, "Out GetOpenWithMask => %lu\n", *puReturn));
+ return S_OK;
+EH_UnlockUpdate:
+ ULISetLow(ulOffset, OUPDATE & ulMask);
+ ULISetLow(cbLength, 1);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: ReleaseOpenWithMask, private
+//
+// Synopsis: Releases opening locks with offset masking
+//
+// Arguments: [plst] - LStream
+// [df] - Locks taken
+// [offset] - Index of locks
+// [ulMask] - Mask
+//
+// Requires: offset != NOLOCK
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_ReleaseOpenWithMask)
+#endif
+
+static void ReleaseOpenWithMask(ILockBytes *plst,
+ DFLAGS df,
+ ULONG offset,
+ ULONG ulMask)
+{
+ ULARGE_INTEGER ulOffset, cbLength;
+
+ olDebugOut((DEB_ITRACE, "In ReleaseOpenWithMask(%p, %lX, %lu, %lX)\n",
+ plst, df, offset, ulMask));
+
+ olAssert(offset != NOLOCK);
+
+ // we incremented at the end of GetOpen, so we decrement here
+ // to restore the proper lock index
+ offset--;
+
+ ULISetHigh(ulOffset, 0);
+ ULISet32(cbLength, 1);
+ if (P_READ(df))
+ {
+ ULISetLow(ulOffset, (OOPENREADLOCK+offset) & ulMask);
+ olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))) &&
+ aMsg("Non-fatal (Removable media?)"));
+ }
+ if (P_WRITE(df))
+ {
+ ULISetLow(ulOffset, (OOPENWRITELOCK+offset) & ulMask);
+ olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))) &&
+ aMsg("Non-fatal (Removable media?)"));
+ }
+ if (P_DENYREAD(df))
+ {
+ ULISetLow(ulOffset, (OOPENDENYREADLOCK+offset) & ulMask);
+ olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))) &&
+ aMsg("Non-fatal (Removable media?)"));
+ }
+#ifdef USE_NOSNAPSHOT
+ if (P_DENYWRITE(df) || P_NOSNAPSHOT(df))
+#else
+ if (P_DENYWRITE(df))
+#endif
+ {
+ ULISetLow(ulOffset, (OOPENDENYWRITELOCK+offset) & ulMask);
+ olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))) &&
+ aMsg("Non-fatal (Removable media?)"));
+ }
+#ifdef USE_NOSNAPSHOT
+ if (P_NOSNAPSHOT(df))
+ {
+ ULISetLow(ulOffset, (OOPENNOSNAPSHOTLOCK+offset) & ulMask);
+ olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))) &&
+ aMsg("Non-fatal (Removable media?)"));
+ }
+#endif
+
+ olDebugOut((DEB_ITRACE, "Out ReleaseOpenWithMask\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Function: GetOpen, public
+//
+// Synopsis: Gets locks on an LStream during opening
+//
+// Arguments: [plst] - LStream
+// [df] - Permissions to take
+// [fCheck] - Whether to check for existing locks or not
+// [puReturn] - Index of lock taken
+//
+// Returns: Appropriate status code
+//
+// Modifies: [puReturn]
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_GetOpen)
+#endif
+
+SCODE GetOpen(ILockBytes *plst,
+ DFLAGS df,
+ BOOL fCheck,
+ ULONG *puReturn)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In GetOpen(%p, %lX, %d, %p)\n",
+ plst, df, fCheck, puReturn));
+
+ // Make sure our lock region hasn't overflowed 32 bits
+ olAssert(OLOCKREGIONEND > OACCESS);
+
+ // If we're not locking high, the dual locks are unnecessary
+ olAssert(OACCESS & 0x80000000);
+
+ olChk(GetOpenWithMask(plst, df, fCheck, MASK_LOW, puReturn));
+ olAssert(*puReturn < 0x10000);
+#ifndef _MAC
+#ifdef _LOCK_HIGH
+ ULONG ulIndex;
+ olChkTo(EH_Low, GetOpenWithMask(plst, df, fCheck, MASK_HIGH, &ulIndex));
+ olAssert(ulIndex < 0x10000);
+ *puReturn |= ulIndex << 16;
+#endif
+#endif
+
+ olDebugOut((DEB_ITRACE, "Out GetOpen => %lu\n", *puReturn));
+ return S_OK;
+
+#ifndef _MAC
+#ifdef _LOCK_HIGH
+ EH_Low:
+ ReleaseOpenWithMask(plst, df, *puReturn, MASK_LOW);
+#endif
+#endif
+ EH_Err:
+ *puReturn = NOLOCK;
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: ReleaseOpen, public
+//
+// Synopsis: Releases opening locks
+//
+// Arguments: [plst] - LStream
+// [df] - Locks taken
+// [offset] - Index of locks
+//
+// Requires: offset != NOLOCK
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_ReleaseOpen)
+#endif
+
+void ReleaseOpen(ILockBytes *plst, DFLAGS df, ULONG offset)
+{
+ olDebugOut((DEB_ITRACE, "In ReleaseOpen(%p, %lX, %lu)\n",
+ plst, df, offset));
+
+ if (offset != NOLOCK)
+ {
+ ReleaseOpenWithMask(plst, df, offset & 0xffff, MASK_LOW);
+#ifndef _MAC
+#ifdef _LOCK_HIGH
+ ReleaseOpenWithMask(plst, df, offset >> 16, MASK_HIGH);
+#endif
+#endif
+ }
+ olDebugOut((DEB_ITRACE, "Out ReleaseOpen\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: WaitForAccess, public, 32-bit only
+//
+// Synopsis: Attempts to get access locks, retrying if necessary
+// using exponential backoff
+//
+// Arguments: [plst] - ILockBytes
+// [df] - Access desired
+// [poReturn] - Lock index return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [poReturn]
+//
+// History: 23-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef WIN32
+#define WAITACCESS_INITIAL 100
+#define WAITACCESS_TIMEOUT 100000
+
+SCODE WaitForAccess(ILockBytes *plst,
+ DFLAGS df,
+ ULONG *poReturn)
+{
+ SCODE sc;
+ DWORD dwWait;
+
+ olDebugOut((DEB_ITRACE, "In WaitForAccess(%p, %X, %p)\n",
+ plst, df, poReturn));
+
+ dwWait = WAITACCESS_INITIAL;
+ for (;;)
+ {
+ sc = GetAccess(plst, df, poReturn);
+ if (sc != STG_E_LOCKVIOLATION ||
+ dwWait >= WAITACCESS_TIMEOUT
+ )
+ break;
+
+ Sleep(dwWait);
+ dwWait *= 2;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out WaitForAccess => 0x%lX, %lu\n",
+ sc, poReturn));
+ return sc;
+}
+#endif
diff --git a/private/ole32/stg/exp/makefile b/private/ole32/stg/exp/makefile
new file mode 100644
index 000000000..917a7c04a
--- /dev/null
+++ b/private/ole32/stg/exp/makefile
@@ -0,0 +1,20 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1994 **
+#********************************************************************
+
+!ifdef NTMAKEENV
+
+all:
+ echo $(BUILDMSG)
+
+clean: all
+
+!else
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/stg/exp/marshl.cxx b/private/ole32/stg/exp/marshl.cxx
new file mode 100644
index 000000000..d23735934
--- /dev/null
+++ b/private/ole32/stg/exp/marshl.cxx
@@ -0,0 +1,1111 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: marshl.cxx
+//
+// Contents: Marshal/Unmarshal implementation
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <expdf.hxx>
+#include <expst.hxx>
+#include <pbstream.hxx>
+#include <marshl.hxx>
+#include <logfile.hxx>
+
+// Standard marshal data is an IID plus a DWORD
+#define CBSTDMARSHALSIZE (sizeof(IID)+sizeof(DWORD))
+
+#ifndef DCOM
+STDAPI CoUnmarshalInterfaceEx(IStream *pStm,
+ REFIID riid,
+ void **ppv,
+ BOOL fNormalDoesRelease);
+#endif
+
+
+inline SCODE VerifyIid(REFIID iid, REFIID iidObj)
+{
+ if ((IsEqualIID(iid, IID_IUnknown) || (IsEqualIID(iid, iidObj))))
+ {
+ return S_OK;
+ }
+
+ if (IsEqualIID(iidObj, IID_ILockBytes))
+ {
+ if (IsEqualIID(iid, IID_IFillLockBytes))
+ {
+ return S_OK;
+ }
+ }
+
+ if (IsEqualIID(iidObj, IID_IStorage))
+ {
+ if (IsEqualIID(iid, IID_IPropertySetStorage))
+ {
+ return S_OK;
+ }
+ }
+
+ return STG_E_INVALIDPARAMETER;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: DfUnMarshalInterface, public
+//
+// Synopsis: Unmarshals marshaled data
+//
+// Arguments: [pstStm] - Stream to read data from
+// [iid] - Interface to unmarshal
+// [fFirst] - First time unmarshalling
+// [ppvObj] - Interface return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_DfUnMarshalInterface) // Marshal_TEXT
+#endif
+
+STDAPI DfUnMarshalInterface(IStream *pstStm,
+ REFIID iid,
+ BOOL fFirst,
+ void **ppvObj)
+{
+ SCODE sc;
+ ULONG cbRead;
+ IID iidSt;
+ DWORD mshlflags;
+ SafeIUnknown punk;
+
+ olLog(("--------::In DfUnMarshalInterface(%p, iid, %d, %p). "
+ "Context == %lX\n", pstStm, fFirst, ppvObj,
+ (ULONG)GetCurrentContextId()));
+ olDebugOut((DEB_TRACE, "In DfUnMarshalInterface("
+ "%p, ?, %d, %p)\n", pstStm, fFirst, ppvObj));
+
+ olChk(ValidateOutPtrBuffer(ppvObj));
+ *ppvObj = NULL;
+ olChk(ValidateInterface(pstStm, IID_IStream));
+ olChk(ValidateIid(iid));
+ if (!fFirst)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+
+ olHChk(pstStm->Read(&iidSt, sizeof(iidSt), &cbRead));
+ if (cbRead != sizeof(iidSt))
+ olErr(EH_Err, STG_E_READFAULT);
+ olHChk(pstStm->Read(&mshlflags, sizeof(mshlflags), &cbRead));
+ if (cbRead != sizeof(mshlflags))
+ olErr(EH_Err, STG_E_READFAULT);
+ olChk(VerifyIid(iid, iidSt));
+
+#if !defined(MULTIHEAP)
+ olChk(DfSyncSharedMemory());
+ DfInitSharedMemBase();
+#endif
+ if (IsEqualIID(iidSt, IID_ILockBytes))
+ sc = CFileStream::Unmarshal(pstStm, (void **)&punk, mshlflags);
+ else if (IsEqualIID(iidSt, IID_IStream))
+ sc = CExposedStream::Unmarshal(pstStm, (void **)&punk, mshlflags);
+ else if (IsEqualIID(iidSt, IID_IStorage))
+ sc = CExposedDocFile::Unmarshal(pstStm, (void **)&punk, mshlflags);
+ else
+ sc = E_NOINTERFACE;
+
+ if (SUCCEEDED(sc))
+ {
+ if (!IsEqualIID(iid, iidSt))
+ {
+ sc = punk->QueryInterface(iid, ppvObj);
+ }
+ else
+ {
+ TRANSFER_INTERFACE(punk, IUnknown, ppvObj);
+#if DBG
+ void *pvCheck;
+ olAssert( S_OK == ((IUnknown*)*ppvObj)->QueryInterface(iidSt, &pvCheck));
+ olAssert( pvCheck == *ppvObj );
+ ((IUnknown*)pvCheck)->Release();
+#endif
+ }
+ }
+
+ olDebugOut((DEB_TRACE, "Out DfUnMarshalInterface => %p\n",
+ *ppvObj));
+EH_Err:
+ olLog(("--------::Out DfUnMarshalInterface(). "
+ "*ppvObj == %p, ret == %lX\n", *ppvObj, sc));
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetCoMarshalSize, private
+//
+// Synopsis: Gets the marshal size for an interface marshalled using
+// CoMarshalInterface
+//
+// Arguments: [riid] - Interface id
+// [punk] - Interface pointer
+// [pv] - Context info
+// [dwDestContext] - Destination context
+// [pvDestContext] - Destination context
+// [mshlflags] - Marshal flags
+// [pcb] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcb]
+//
+// Algorithm: CoMarshalInterface is guaranteed to add no more than
+// MARSHALINTERFACE_MIN bytes of overhead to a marshal
+// Also, the standard marshaller takes no more than that
+// So if the given object supports IMarshal, the return
+// is IMarshal::GetMarshalSizeMax+MARSHALINTERFACE_MIN,
+// otherwise it is just MARSHALINTERFACE_MIN
+//
+// History: 03-Aug-93 DrewB Created
+//
+// Notes: On 32-bit platforms, we can use CoGetMarshalSizeMax
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_GetCoMarshalSize)
+#endif
+
+#ifndef WIN32
+static SCODE GetCoMarshalSize(REFIID riid,
+ IUnknown *punk,
+ void *pv,
+ DWORD dwDestContext,
+ void *pvDestContext,
+ DWORD mshlflags,
+ DWORD *pcb)
+{
+ IMarshal *pmsh;
+ SCODE sc;
+ DWORD cb;
+
+ olDebugOut((DEB_ITRACE, "In GetCoMarshalSize("
+ "riid, %p, %p, %lu, %p, %lu, %p)\n", pv, punk, dwDestContext,
+ pvDestContext, mshlflags, pcb));
+
+ sc = DfGetScode(punk->QueryInterface(IID_IMarshal, (void **)&pmsh));
+ if (sc == E_NOINTERFACE)
+ {
+ *pcb = MARSHALINTERFACE_MIN;
+ sc = S_OK;
+ }
+ else if (SUCCEEDED(sc))
+ {
+ sc = DfGetScode(pmsh->GetMarshalSizeMax(riid, pv, dwDestContext,
+ pvDestContext, mshlflags,
+ &cb));
+ if (SUCCEEDED(sc))
+ *pcb = MARSHALINTERFACE_MIN+cb;
+ pmsh->Release();
+ }
+
+ olDebugOut((DEB_ITRACE, "Out GetCoMarshalSize => %lu, 0x%lX\n",
+ *pcb, sc));
+ return sc;
+}
+#else
+#define GetCoMarshalSize(riid, punk, pv, dwDestContext, pvDestContext,\
+ mshlflags, pcb) \
+ GetScode(CoGetMarshalSizeMax(pcb, riid, punk, dwDestContext, \
+ pvDestContext, mshlflags))
+#endif
+
+//+--------------------------------------------------------------
+//
+// Function: GetStdMarshalSize, public
+//
+// Synopsis: Returns the size needed for a standard marshal buffer
+//
+// Arguments: [iid] - Requested marshal IID
+// [iidObj] - IID of object being marshalled
+// [dwDestContext] - Destination context
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Marshal flags
+// [pcbSize] - Size return
+// [cbSize] - Object private size
+// [ppc] - Context to marshal or NULL
+// [fMarshalOriginal] - Marshal original in context
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbSize]
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_GetStdMarshalSize)
+#endif
+
+SCODE GetStdMarshalSize(REFIID iid,
+ REFIID iidObj,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ DWORD *pcbSize,
+ DWORD cbSize,
+#ifdef ASYNC
+ CAsyncConnection *pcpoint,
+ BOOL fMarshalILBs,
+#endif
+ CPerContext *ppc,
+ BOOL const fMarshalOriginal)
+{
+ DWORD cbLBSize;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In GetStdMarshalSize("
+ "iid, iidObj, %lu, %p, %lu, %p, %lu, %p, %d)\n",
+ dwDestContext, pvDestContext, mshlflags, pcbSize, cbSize, ppc,
+ fMarshalOriginal));
+
+ olChk(ValidateOutBuffer(pcbSize, sizeof(DWORD)));
+ *pcbSize = 0;
+ olChk(ValidateIid(iid));
+ olChk(VerifyIid(iid, iidObj));
+
+ if (((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
+ || pvDestContext != NULL)
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+
+ *pcbSize = CBSTDMARSHALSIZE+cbSize;
+#ifdef MULTIHEAP
+ *pcbSize += sizeof(ULONG)+sizeof(ContextId)+sizeof(CPerContext*);
+#endif
+#ifdef POINTER_IDENTITY
+ *pcbSize += sizeof(CMarshalList*);
+#endif
+#ifdef ASYNC
+ if ((ppc) && fMarshalILBs)
+#else
+ if (ppc)
+#endif
+ {
+ *pcbSize += sizeof(CGlobalContext *);
+ olChk(GetCoMarshalSize(IID_ILockBytes,
+ (ILockBytes *)ppc->GetBase(),
+ NULL, dwDestContext, pvDestContext,
+ mshlflags, &cbLBSize));
+ *pcbSize += cbLBSize;
+ olChk(GetCoMarshalSize(IID_ILockBytes,
+ (ILockBytes *)ppc->GetDirty(),
+ NULL, dwDestContext, pvDestContext,
+ mshlflags, &cbLBSize));
+ *pcbSize += cbLBSize;
+ if (fMarshalOriginal)
+ {
+ olChk(GetCoMarshalSize(IID_ILockBytes,
+ (ILockBytes *)ppc->GetOriginal(),
+ NULL, dwDestContext, pvDestContext,
+ mshlflags, &cbLBSize));
+ *pcbSize += cbLBSize;
+ }
+ }
+#ifdef ASYNC
+ //BOOL determines whether we have a connection to marshal or not
+ *pcbSize += sizeof(BOOL);
+ if ((pcpoint) && (pcpoint->GetMarshalPoint() != NULL))
+ {
+ ULONG cbConnectSize;
+ //Async flags
+ *pcbSize += sizeof(DWORD);
+ olChk(GetCoMarshalSize(IID_IDocfileAsyncConnectionPoint,
+ pcpoint->GetMarshalPoint(),
+ NULL, dwDestContext, pvDestContext,
+ mshlflags, &cbConnectSize));
+ *pcbSize += cbConnectSize;
+ }
+#endif
+
+ olDebugOut((DEB_ITRACE, "Out GetStdMarshalSize\n"));
+ EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: StartMarshal, public
+//
+// Synopsis: Writes standard marshal header
+//
+// Arguments: [pstStm] - Stream to write marshal data into
+// [iid] - Interface to marshal
+// [iidObj] - Object being marshalled
+// [mshlflags] - Marshal flags
+//
+// Returns: Appropriate status code
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_StartMarshal)
+#endif
+
+SCODE StartMarshal(IStream *pstStm,
+ REFIID iid,
+ REFIID iidObj,
+ DWORD mshlflags)
+{
+ SCODE sc;
+ ULONG cbWritten;
+
+ olDebugOut((DEB_ITRACE, "In StartMarshal(%p, iid, iidObj, %lu)\n",
+ pstStm, mshlflags));
+
+ olChk(ValidateInterface(pstStm, IID_IStream));
+ olChk(ValidateIid(iid));
+ olChk(VerifyIid(iid, iidObj));
+ olHChk(pstStm->Write((void *)&iidObj, sizeof(iidObj), &cbWritten));
+ if (cbWritten != sizeof(iidObj))
+ olErr(EH_Err, STG_E_WRITEFAULT);
+ olHChk(pstStm->Write((void *)&mshlflags, sizeof(mshlflags), &cbWritten));
+ if (cbWritten != sizeof(mshlflags))
+ olErr(EH_Err, STG_E_WRITEFAULT);
+
+ olDebugOut((DEB_ITRACE, "Out StartMarshal\n"));
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SkipStdMarshal, public
+//
+// Synopsis: Skips over the standard marshal data
+//
+// Arguments: [pstm] - Marshal stream
+// [piid] - IID return
+// [pmshlflags] - Return marshal flags
+//
+// Returns: Appropriate status code
+//
+// Modifies: [piid]
+// [pmshlflags]
+//
+// History: 20-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_SkipStdMarshal)
+#endif
+
+#ifdef WIN32
+SCODE SkipStdMarshal(IStream *pstm, IID *piid, DWORD *pmshlflags)
+{
+ SCODE sc;
+ ULONG cbRead;
+
+ olDebugOut((DEB_ITRACE, "In SkipStdMarshal(%p, %p, %p)\n", pstm,
+ piid, pmshlflags));
+
+ olHChk(pstm->Read(piid, sizeof(IID), &cbRead));
+ if (cbRead != sizeof(IID))
+ olErr(EH_Err, STG_E_READFAULT);
+ olHChk(pstm->Read(pmshlflags, sizeof(DWORD), &cbRead));
+ if (cbRead != sizeof(DWORD))
+ olErr(EH_Err, STG_E_READFAULT);
+
+ olDebugOut((DEB_ITRACE, "Out SkipStdMarshal => %lX\n", sc));
+ EH_Err:
+ return sc;
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Function: MarshalPointer, public
+//
+// Synopsis: Marshals a pointer
+//
+// Arguments: [pstm] - Marshal stream
+// [pv] - Pointer
+//
+// Returns: Appropriate status code
+//
+// History: 20-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_MarshalPointer)
+#endif
+
+SCODE MarshalPointer(IStream *pstm, void *pv)
+{
+ SCODE sc;
+ ULONG cbWritten;
+
+ olDebugOut((DEB_ITRACE, "In MarshalPointer(%p, %p)\n", pstm, pv));
+
+#ifdef USEBASED
+ pv = (void *)((ULONG)pv-(ULONG)DFBASEPTR);
+#endif
+
+ sc = DfGetScode(pstm->Write(&pv, sizeof(pv), &cbWritten));
+ if (SUCCEEDED(sc) && cbWritten != sizeof(pv))
+ sc = STG_E_WRITEFAULT;
+
+ olDebugOut((DEB_ITRACE, "Out MarshalPointer\n"));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: MarshalContext, public
+//
+// Synopsis: Marshals a context
+//
+// Arguments: [pstm] - Marshal stream
+// [ppc] - Context
+// [dwDestContext] - Destination context
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Marshal flags
+// [fMarshalOriginal] - Marshal original or not
+//
+// Returns: Appropriate status code
+//
+// History: 20-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_MarshalContext)
+#endif
+
+SCODE MarshalContext(IStream *pstm,
+ CPerContext *ppc,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+#ifdef ASYNC
+ BOOL const fMarshalILBs,
+#endif
+ BOOL const fMarshalOriginal)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In MarshalContext(%p, %p, %lu, %p, %lu, %d)\n",
+ pstm, ppc, dwDestContext, pvDestContext, mshlflags,
+ fMarshalOriginal));
+
+ olChk(MarshalPointer(pstm, ppc->GetGlobal()));
+
+#ifdef ASYNC
+ if (fMarshalILBs)
+#endif
+ {
+ olHChk(CoMarshalInterface(pstm, IID_ILockBytes, ppc->GetBase(),
+ dwDestContext, pvDestContext, mshlflags));
+ olHChk(CoMarshalInterface(pstm, IID_ILockBytes,
+ (ILockBytes *)ppc->GetDirty(),
+ dwDestContext, pvDestContext, mshlflags));
+ if (fMarshalOriginal)
+ olHChk(CoMarshalInterface(pstm, IID_ILockBytes, ppc->GetOriginal(),
+ dwDestContext, pvDestContext, mshlflags));
+ }
+
+#ifdef WIN32
+ if (mshlflags != MSHLFLAGS_TABLEWEAK)
+ ppc->GetGlobal()->AddRef();
+#endif
+
+ olDebugOut((DEB_ITRACE, "Out MarshalContext\n"));
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: UnmarshalPointer, public
+//
+// Synopsis: Unmarshals a pointer
+//
+// Arguments: [pstm] - Marshal stream
+// [ppv] - Pointer return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 20-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_UnmarshalPointer)
+#endif
+
+SCODE UnmarshalPointer(IStream *pstm,
+ void **ppv)
+{
+ SCODE sc;
+ ULONG cbRead;
+
+ olDebugOut((DEB_ITRACE, "In UnmarshalPointer(%p, %p)\n", pstm, ppv));
+
+ sc = DfGetScode(pstm->Read(ppv, sizeof(*ppv), &cbRead));
+ if (SUCCEEDED(sc) && cbRead != sizeof(*ppv))
+ sc = STG_E_READFAULT;
+
+#ifdef USEBASED
+ *ppv = (void *)((ULONG)*ppv+(ULONG)DFBASEPTR);
+#endif
+
+ olDebugOut((DEB_ITRACE, "Out UnmarshalPointer => %p\n", *ppv));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: UnmarshalContext, public
+//
+// Synopsis: Unmarshals a context
+//
+// Arguments: [pstm] - Marshal stream
+// [pppc] - Context return
+// [fUnmarshalOriginal] - Marshalled original exists or not
+// [fIsRoot] - Root unmarshal or not
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pppc]
+//
+// History: 20-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_UnmarshalContext)
+#endif
+
+SCODE UnmarshalContext(IStream *pstm,
+ CGlobalContext *pgc,
+ CPerContext **pppc,
+ DWORD mshlflags,
+#ifdef ASYNC
+ BOOL const fUnmarshalILBs,
+#endif
+ BOOL const fUnmarshalOriginal,
+#ifdef MULTIHEAP
+ ContextId cntxid,
+#endif
+ BOOL const fIsRoot)
+{
+ BOOL fNewContext;
+ ILockBytes *plkbBase = NULL;
+ CFileStream *pfstDirty = NULL;
+ ILockBytes *plkbOriginal = NULL;
+ SCODE sc, sc2;
+ CPerContext *ppc;
+ ULONG ulOpenLock = 0;
+
+ olDebugOut((DEB_ITRACE, "In UnmarshalContext(%p, %p, %lu, %d, %d)\n",
+ pstm, pppc, mshlflags, fUnmarshalOriginal, fIsRoot));
+
+ ppc = pgc->Find(GetCurrentContextId());
+ fNewContext = (ppc == NULL);
+
+#ifdef MULTIHEAP
+ // when marshaling to the same process, use the same heap
+ // when marshaling to a different process, check the context list
+ // if there is a matching percontext, use that heap
+
+ if (GetCurrentContextId() != cntxid && ppc != NULL)
+ {
+ ppc->SetThreadAllocatorState(NULL); // set new base
+
+ // Whenever we unmarshal into a different process, we create
+ // a new mapping (of the same heap),
+ // even if a mapping of the same heap may already exist in
+ // the same process. For pointer identity, it is essential
+ // that we find and use the existing heap.
+ // process A ---marshal---> process B ---marshal----> process A
+ // The "final" unmarshaled exposed object in process A should
+ // match the original pointer used when the exposed object
+ // was originally marshaled. To do this, we check the global
+ // context list, and if there's a percontext match, we use
+ // its allocator and heap mapping (and don't create a new one).
+ // However, to actually search the global context list (it
+ // lives in shared memory), we need a temporary mapping until
+ // a matching percontext can be found and reused.
+ // If not, then a new percontext is allocated and the temporary
+ // mapping becomes "permanent" for the lifetime of the new percontext.
+ }
+#endif
+ //BUGBUG: Fix error path
+ if (fNewContext)
+ {
+ olMemTo(EH_Open,
+ ppc = new (pgc->GetMalloc()) CPerContext(pgc->GetMalloc()));
+ olChkTo(EH_ppc, ppc->InitFromGlobal(pgc));
+ }
+
+#ifdef MULTIHEAP
+ // take the ownership of the heap away from the temporary
+ ppc->SetAllocatorState (NULL, &g_smAllocator);
+
+ //ppc from above may have used incorrect base (base of temporary heap).
+ // Since we're returning and storing an unbased pointer, we need to get
+ // the real absolute pointer here. At this point, ppc will always be in
+ // the context list, so we don't need to worry about a NULL return.
+ ppc = pgc->Find(GetCurrentContextId());
+
+ olAssert(ppc != NULL);
+#endif
+
+#ifdef ASYNC
+ if (fUnmarshalILBs)
+ {
+#endif
+#ifdef DCOM
+ // attempt to unmarshal all the interfaces first. this makes cleanup
+ // easier.
+ sc = CoUnmarshalInterface(pstm, IID_ILockBytes, (void **)&plkbBase);
+ sc2 = CoUnmarshalInterface(pstm, IID_ILockBytes, (void **)&pfstDirty);
+
+ sc = (SUCCEEDED(sc)) ? sc2 : sc; // sc = first failure code (if any)
+
+ if (fUnmarshalOriginal)
+ {
+ sc2 = CoUnmarshalInterface(pstm, IID_ILockBytes,
+ (void **)&plkbOriginal);
+ sc = (SUCCEEDED(sc)) ? sc2 : sc; // sc = first failure code (if any)
+ }
+
+ // cleanup if any failure so far
+ olChkTo(EH_plkbOriginal, sc);
+
+ if (ppc->GetBase() != NULL)
+ {
+ // already have context, just release the things we unmarshaled.
+ plkbBase->Release();
+ plkbBase = NULL;
+ }
+
+ if (ppc->GetDirty() != NULL)
+ {
+ pfstDirty->Release();
+ pfstDirty = NULL;
+ }
+
+ if ((plkbOriginal) && (ppc->GetOriginal() != NULL))
+ {
+ plkbOriginal->Release();
+ plkbOriginal = NULL;
+ }
+ else if ((NULL == plkbOriginal) && plkbBase)
+ {
+ plkbBase->AddRef();
+ plkbOriginal = plkbBase;
+ }
+ olAssert (plkbOriginal != NULL || ppc->GetOriginal() != NULL);
+#else
+ olHChkTo(EH_pgc,
+ CoUnmarshalInterfaceEx(pstm, IID_ILockBytes, (void **)&plkbBase,
+ FALSE /*fNormalDoesRelease*/));
+ if (ppc->GetBase() != NULL)
+ {
+ plkbBase->Release();
+ plkbBase = NULL;
+ }
+ olHChkTo(EH_plkbBase,
+ CoUnmarshalInterfaceEx(pstm, IID_ILockBytes, (void **)&pfstDirty,
+ FALSE /*fNormalDoesRelease*/));
+ if (ppc->GetDirty() != NULL)
+ {
+ pfstDirty->Release();
+ pfstDirty = NULL;
+ }
+ if (fUnmarshalOriginal)
+ {
+ olHChkTo(EH_pfstDirty,
+ CoUnmarshalInterfaceEx(pstm, IID_ILockBytes,
+ (void **)&plkbOriginal,
+ FALSE /*fNormalDoesRelease*/));
+ if (ppc->GetOriginal() != NULL)
+ {
+ plkbOriginal->Release();
+ plkbOriginal = NULL;
+ }
+ }
+ else if (fNewContext || (ppc->GetOriginal() == NULL))
+ {
+ plkbBase->AddRef();
+ plkbOriginal = plkbBase;
+ }
+ else
+ {
+ plkbOriginal = NULL;
+ }
+#endif
+
+ // Make sure there is a reserved handle if this is a root
+ // file-based lockbytes
+ if (fIsRoot)
+ {
+ IFileLockBytes *pflkb;
+
+ if (SUCCEEDED(DfGetScode((plkbOriginal ? plkbOriginal :
+ ppc->GetOriginal())->
+ QueryInterface(IID_IFileLockBytes,
+ (void **)&pflkb))))
+ {
+ sc = DfGetScode(pflkb->ReserveHandle());
+ pflkb->Release();
+ olChkTo(EH_plkbOriginal, sc);
+ }
+ }
+#ifdef ASYNC
+ }
+#endif
+
+ if (fNewContext)
+ {
+ olAssert(plkbOriginal != NULL);
+
+ // Take open locks if necessary
+ if (fIsRoot && pgc->TakeLock())
+ {
+ olChkTo(EH_plkbOriginal,
+ GetOpen(plkbOriginal, pgc->GetOpenLockFlags(),
+ FALSE, &ulOpenLock));
+ }
+
+ ppc->SetILBInfo(plkbBase, pfstDirty, plkbOriginal, ulOpenLock);
+ }
+ else
+ {
+ if (ppc->GetBase() == NULL)
+ {
+ //Fill in the ILB fields
+ ppc->SetILBInfo(plkbBase, pfstDirty, plkbOriginal, ulOpenLock);
+ }
+ ppc->AddRef();
+
+ }
+
+ *pppc = ppc;
+
+ olDebugOut((DEB_ITRACE, "Out UnmarshalContext => %p\n", *pppc));
+ return S_OK;
+
+ EH_ppc:
+ // Preserve plkbOriginal so the lock is released even after the
+ // context releases things;
+ plkbOriginal->AddRef();
+ ppc->Release();
+ pfstDirty = NULL;
+ plkbBase = NULL;
+ EH_Open:
+ if (ulOpenLock != 0)
+ {
+ olAssert(plkbOriginal != NULL);
+ ReleaseOpen(plkbOriginal, pgc->GetOpenLockFlags(), ulOpenLock);
+ }
+ EH_plkbOriginal:
+ if (plkbOriginal)
+ plkbOriginal->Release();
+#ifdef DCOM
+ // compiler complains about unreferenced lables
+ if (pfstDirty)
+ pfstDirty->Release();
+ if (plkbBase)
+ plkbBase->Release();
+#else
+ EH_pfstDirty:
+ if (pfstDirty)
+ pfstDirty->Release();
+ EH_plkbBase:
+ if (plkbBase)
+ plkbBase->Release();
+ EH_pgc:
+#endif
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReleaseContext, public
+//
+// Synopsis: Releases references for a context's marshal data
+//
+// Arguments: [pstm] - Marshal stream
+// [fHasOriginal] - Original is marshalled
+// [mshlflags] - Marshal flags
+//
+// Returns: Appropriate status code
+//
+// History: 20-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_ReleaseContext)
+#endif
+
+#ifdef WIN32
+SCODE ReleaseContext(IStream *pstm,
+#ifdef ASYNC
+ BOOL const fUnmarshalILBs,
+#endif
+ BOOL const fHasOriginal,
+ DWORD mshlflags)
+{
+ CGlobalContext *pgc;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In ReleaseContext(%p, %d, %lu)\n", pstm,
+ fHasOriginal, mshlflags));
+
+ olChk(UnmarshalPointer(pstm, (void **)&pgc));
+ if (fUnmarshalILBs)
+ {
+ olHChk(CoReleaseMarshalData(pstm));
+ olHChk(CoReleaseMarshalData(pstm));
+ if (fHasOriginal)
+ olHChk(CoReleaseMarshalData(pstm));
+ }
+
+ if (mshlflags != MSHLFLAGS_TABLEWEAK)
+ pgc->Release();
+
+ olDebugOut((DEB_ITRACE, "Out ReleaseContext\n"));
+ EH_Err:
+ return sc;
+}
+#endif
+
+#ifdef MULTIHEAP
+//+---------------------------------------------------------------------------
+//
+// Function: MarshalSharedMemory, public
+//
+// Synopsis: marshals the shared memory context
+//
+// Arguments: [pstm] - Marshal stream
+// [ppc] - per context structure
+//
+// Returns: Appropriate status code
+//
+// History: 02-Dec-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+SCODE MarshalSharedMemory (IStream *pstStm, CPerContext *ppc)
+{
+ SCODE sc = S_OK;
+ ULONG cbWritten;
+ ULONG ulHeapName;
+ ContextId cntxid = GetCurrentContextId();
+
+ ulHeapName = g_smAllocator.GetHeapName();
+ olHChk(pstStm->Write((void*) &ulHeapName, sizeof(ulHeapName), &cbWritten));
+ if (cbWritten != sizeof(ulHeapName))
+ olErr(EH_Err, STG_E_WRITEFAULT);
+ olHChk(pstStm->Write((void*) &cntxid, sizeof(cntxid), &cbWritten));
+ if (cbWritten != sizeof(cntxid))
+ olErr(EH_Err, STG_E_WRITEFAULT);
+ olHChk(pstStm->Write((void*) &ppc, sizeof(ppc), &cbWritten));
+ if (cbWritten != sizeof(ppc))
+ olErr(EH_Err, STG_E_WRITEFAULT);
+
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: UnMarshalSharedMemory, public
+//
+// Synopsis: Unmarshals the shared memory context
+//
+// Arguments: [pstm] - Marshal stream
+//
+// Returns: Appropriate status code
+//
+// History: 02-Dec-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+SCODE UnmarshalSharedMemory (IStream *pstStm, DWORD mshlflags,
+ CPerContext *ppcOwner, ContextId *pcntxid)
+{
+ SCODE sc = S_OK;
+ ULONG cbRead;
+ ULONG ulHeapName;
+ ContextId cntxid;
+ CPerContext *ppc;
+
+ olHChk(pstStm->Read(&ulHeapName, sizeof(ulHeapName), &cbRead));
+ if (cbRead != sizeof(ulHeapName))
+ olErr(EH_Err, STG_E_READFAULT);
+ olHChk(pstStm->Read(&cntxid, sizeof(cntxid), &cbRead));
+ if (cbRead != sizeof(cntxid))
+ olErr(EH_Err, STG_E_READFAULT);
+ olHChk(pstStm->Read(&ppc, sizeof(ppc), &cbRead));
+ if (cbRead != sizeof(ppc))
+ olErr(EH_Err, STG_E_READFAULT);
+
+ *pcntxid = cntxid;
+ if (GetCurrentContextId() == cntxid)
+ {
+ // marshaling to the same process, reuse the per context and heap
+ // in the case of marshaling to another thread
+ // the per context takes ownership of the thread's allocator
+ ppc->SetThreadAllocatorState(NULL);
+ }
+ else
+ {
+ // marshaling to another process on the same machine
+ // if the name of heap is different that current one, open it
+ if (g_smAllocator.GetHeapName() != ulHeapName)
+ {
+ DfInitSharedMemBase();
+ olChk(DfSyncSharedMemory(ulHeapName));
+ }
+
+ // Because the unmarshaling code calls IStream::Read,
+ // possibly using another shared heap, we need a temporary
+ // owner until the real CPerContext is unmarshaled
+ ppcOwner->GetThreadAllocatorState();
+ ppcOwner->SetThreadAllocatorState(NULL);
+ }
+EH_Err:
+ return sc;
+}
+#endif
+
+
+#ifdef ASYNC
+SCODE MarshalConnection(IStream *pstm,
+ CAsyncConnection *pcpoint,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ SCODE sc;
+ ULONG cbWritten;
+ IDocfileAsyncConnectionPoint *pdacp = pcpoint->GetMarshalPoint();
+ BOOL fIsInitialized = (pdacp != NULL);
+
+ //Write out the pointer.
+ olHChk(pstm->Write(&fIsInitialized,
+ sizeof(BOOL),
+ &cbWritten));
+ if (cbWritten != sizeof(BOOL))
+ {
+ olErr(EH_Err, STG_E_READFAULT);
+ }
+
+ if (fIsInitialized)
+ {
+ //If the pointer was NULL, we don't need to worry about actually
+ //marshalling anything, and we can detect this in the unmarshal
+ //path. If it wasn't NULL, we need to store some additional
+ //information: The async flags and the actual connection point,
+ //which will be standard marshalled.
+ DWORD dwAsyncFlags = pcpoint->GetAsyncFlags();
+
+ olChk(pstm->Write(&dwAsyncFlags, sizeof(DWORD), &cbWritten));
+ if (cbWritten != sizeof(DWORD))
+ {
+ olErr(EH_Err, STG_E_WRITEFAULT);
+ }
+
+ //Finally, standard marshal the connection point itself.
+ olHChk(CoMarshalInterface(pstm,
+ IID_IDocfileAsyncConnectionPoint,
+ pdacp,
+ dwDestContext,
+ pvDestContext,
+ mshlflags));
+ }
+EH_Err:
+ return sc;
+}
+
+SCODE UnmarshalConnection(IStream *pstm,
+ DWORD *pdwAsyncFlags,
+ IDocfileAsyncConnectionPoint **ppdacp,
+ DWORD mshlflags)
+{
+ SCODE sc;
+ BOOL fIsInitialized;
+ ULONG cbRead;
+
+ *ppdacp = NULL;
+ *pdwAsyncFlags = 0;
+
+ olHChk(pstm->Read(&fIsInitialized, sizeof(BOOL), &cbRead));
+ if (cbRead != sizeof(BOOL))
+ {
+ olErr(EH_Err, STG_E_READFAULT);
+ }
+
+ if (fIsInitialized)
+ {
+ olChk(pstm->Read(pdwAsyncFlags, sizeof(DWORD), &cbRead));
+ if (cbRead != sizeof(DWORD))
+ {
+ olErr(EH_Err, STG_E_READFAULT);
+ }
+ sc = CoUnmarshalInterface(pstm,
+ IID_IDocfileAsyncConnectionPoint,
+ (void **)ppdacp);
+ }
+EH_Err:
+ return sc;
+}
+
+SCODE ReleaseConnection(IStream *pstm, DWORD mshlflags)
+{
+ SCODE sc;
+ ULONG cbRead;
+ BOOL fIsInitialized;
+ DWORD dwAsyncFlags;
+
+ olHChk(pstm->Read(&fIsInitialized, sizeof(BOOL), &cbRead));
+ if (cbRead != sizeof(BOOL))
+ {
+ olErr(EH_Err, STG_E_READFAULT);
+ }
+ if (fIsInitialized)
+ {
+ olChk(pstm->Read(&dwAsyncFlags, sizeof(DWORD), &cbRead));
+ if (cbRead != sizeof(DWORD))
+ {
+ olErr(EH_Err, STG_E_READFAULT);
+ }
+ olHChk(CoReleaseMarshalData(pstm));
+ }
+
+ EH_Err:
+ return sc;
+}
+
+#endif
diff --git a/private/ole32/stg/exp/marshl.hxx b/private/ole32/stg/exp/marshl.hxx
new file mode 100644
index 000000000..221ebd66d
--- /dev/null
+++ b/private/ole32/stg/exp/marshl.hxx
@@ -0,0 +1,107 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: marshl.hxx
+//
+// Contents: Marshal/Unmarshal header
+//
+// History: 04-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __MARSHL_HXX__
+#define __MARSHL_HXX__
+
+#include <dfmsp.hxx>
+
+// BUGBUG - This should go somewhere official
+DEFINE_OLEGUID(CLSID_DfMarshal, 0x0000030b, 0, 0);
+
+class CPerContext;
+#ifdef ASYNC
+class CAsyncConnection;
+interface IDocfileAsyncConnectionPoint;
+#endif
+
+
+SCODE GetStdMarshalSize(REFIID iid,
+ REFIID iidObj,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ DWORD *pcbSize,
+ DWORD cbSize,
+#ifdef ASYNC
+ CAsyncConnection *pcpoint,
+ BOOL fMarshalILBs,
+#endif
+ CPerContext *ppc,
+ BOOL const fMarshalOriginal);
+SCODE StartMarshal(IStream *pstStm,
+ REFIID iid,
+ REFIID iidObj,
+ DWORD mshlflags);
+SCODE MarshalPointer(IStream *pstm,
+ void *pv);
+SCODE MarshalContext(IStream *pstm,
+ CPerContext *ppc,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+#ifdef ASYNC
+ BOOL const fMarshalILBs,
+#endif
+ BOOL const fMarshalOriginal);
+
+#ifdef ASYNC
+SCODE MarshalConnection(IStream *pstm,
+ CAsyncConnection *pcpoint,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags);
+#endif
+
+SCODE UnmarshalPointer(IStream *pstm,
+ void **ppv);
+SCODE UnmarshalContext(IStream *pstm,
+ CGlobalContext *pgc,
+ CPerContext **pppc,
+ DWORD mshlflags,
+#ifdef ASYNC
+ BOOL const fUnmarshalILBs,
+#endif
+ BOOL const fUnmarshalOriginal,
+#ifdef MULTIHEAP
+ ContextId cntxid,
+#endif
+ BOOL const fIsRoot);
+
+#ifdef ASYNC
+SCODE UnmarshalConnection(IStream *pstm,
+ DWORD *pdwAsyncFlags,
+ IDocfileAsyncConnectionPoint **ppdacp,
+ DWORD mshlflags);
+#endif
+
+SCODE SkipStdMarshal(IStream *pstStm, IID *piid, DWORD *pmshlflags);
+SCODE ReleaseContext(IStream *pstm,
+#ifdef ASYNC
+ BOOL const fUnmarshalILBs,
+#endif
+ BOOL const fHasOriginal,
+ DWORD mshlflags);
+
+#ifdef ASYNC
+SCODE ReleaseConnection(IStream *pstm,
+ DWORD mshlflags);
+#endif
+
+#ifdef MULTIHEAP
+SCODE UnmarshalSharedMemory (IStream *pstStm, DWORD mshlflags,
+ CPerContext *ppcOwner, ContextId *pcntxid);
+SCODE MarshalSharedMemory (IStream *ptm, CPerContext *ppc);
+#endif
+
+#endif // #ifndef __MARSHL_HXX__
diff --git a/private/ole32/stg/exp/mrshlist.cxx b/private/ole32/stg/exp/mrshlist.cxx
new file mode 100644
index 000000000..8bf23fe93
--- /dev/null
+++ b/private/ole32/stg/exp/mrshlist.cxx
@@ -0,0 +1,117 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: mrshlist.cxx
+//
+// Contents: CMarshalList implementation
+//
+// History: 16-Mar-96 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <mrshlist.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMarshalList::FindMarshal, public
+//
+// Synopsis: Looks through the list for a matching context
+//
+// Arguments: [ctxid] - Context to look for
+//
+// Returns: Pointer to object or NULL
+//
+// History: 16-Mar-96 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+CMarshalList *CMarshalList::FindMarshal (ContextId ctxid) const
+{
+ CMarshalList *pmlResult = NULL;
+
+ olDebugOut((DEB_ITRACE, "In CMarshalList::Find:%p(%lu)Marshal\n", this,
+ (ULONG)ctxid));
+ olAssert (ctxid != INVALID_CONTEXT_ID);
+ if (GetContextId() == ctxid)
+ pmlResult = (CMarshalList *) this; // cast away const
+ else
+ {
+ olAssert (GetNextMarshal() != NULL);
+ CMarshalList *pml;
+ for (pml = GetNextMarshal(); pml != this; pml = pml->GetNextMarshal())
+ if (pml->GetContextId() != INVALID_CONTEXT_ID &&
+ pml->GetContextId() == ctxid)
+ {
+ pmlResult = pml;
+ break;
+ }
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CMarshalList::FindMarshal %p\n", pmlResult));
+ return pmlResult;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMarshalList::AddMarshal, public
+//
+// Synopsis: Adds a context to the list
+//
+// Arguments: [pml] - another marshaling of the same storage/stream
+//
+// History: 16-Mar-96 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+void CMarshalList::AddMarshal (CMarshalList *pml)
+{
+ olDebugOut((DEB_ITRACE, "In CMarshalList::AddMarshal:%p(%p)\n",this,pml));
+ olAssert (pml != NULL);
+ olAssert (GetNextMarshal() != NULL);
+ pml->SetNextMarshal(GetNextMarshal());
+ SetNextMarshal(pml);
+ olDebugOut((DEB_ITRACE, "Out CMarshalList::AddMarshal\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMarshalList::RemoveMarshal, public
+//
+// Synopsis: Removes a context from the list
+//
+// Arguments: [pctx] - Context
+//
+// History: 16-Mar-96 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+void CMarshalList::RemoveMarshal(CMarshalList *pml)
+{
+ olDebugOut((DEB_ITRACE, "In CMarshalList::RemoveMarshal:%p(%p)\n",
+ this,pml));
+ if (GetNextMarshal() != NULL && GetNextMarshal() != this)
+ {
+ CMarshalList *pmlNext;
+#if DBG == 1
+ BOOL fFound = FALSE;
+#endif
+ for (pmlNext = GetNextMarshal(); pmlNext != this;
+ pmlNext = pmlNext->GetNextMarshal())
+ if (pmlNext->GetNextMarshal() == pml)
+ {
+#if DBG == 1
+ fFound = TRUE;
+#endif
+ pmlNext->SetNextMarshal(pml->GetNextMarshal());
+ pml->SetNextMarshal(NULL);
+ break;
+ }
+ olAssert(fFound == TRUE);
+ }
+ olDebugOut((DEB_ITRACE, "Out CMarshalList::RemoveMarshal\n"));
+}
diff --git a/private/ole32/stg/exp/mrshlist.hxx b/private/ole32/stg/exp/mrshlist.hxx
new file mode 100644
index 000000000..488b4ceca
--- /dev/null
+++ b/private/ole32/stg/exp/mrshlist.hxx
@@ -0,0 +1,148 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: mrshlist.hxx
+//
+// Contents: CMarshalList header
+//
+// Classes: CMarshalList
+//
+// History: 16-Mar-96 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __MRSHLIST_HXX__
+#define __MRSHLIST_HXX__
+
+#define POINTER_IDENTITY
+class CMarshalList; // forward declaration for SAFE macro
+SAFE_DFBASED_PTR(CBasedMarshalListPtr, CMarshalList);
+
+//+---------------------------------------------------------------------------
+//
+// Class: CMarshalList (ml)
+//
+// Purpose: Maintains a list of marshaled exposed objects that
+// represent the same storage or stream
+//
+// Interface: See below
+//
+// Notes: This class is intended to solve the "pointer identity"
+// problem. When an IStorage or IStream is passed as an
+// [in, out] RPC parameter, two marshal/unmarshalings occur,
+// one for the [in] side, and a reverse marshaling for
+// the [out] side. The previous algorithm always allocated
+// a new exposed object for every unmarshaling, so the
+// pointer going into an [in,out] call isn't the same
+// as the pointer returned from the call.
+//
+// This algorithm links the exposed objects together, each
+// link keyed by the ContextId (ProcessId). When unmarshaling,
+// this list is checked for a valid exposed object that
+// can be reused. If not, then a new exposed object
+// is allocated and inserted into the linked list.
+// Instances of this class must live in shared memory
+// in order for the list to traverse across processes
+//
+// History: 26-Mar-96 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+class CMarshalList
+{
+protected:
+ inline CMarshalList ();
+ inline ~CMarshalList ();
+
+public:
+ inline CMarshalList * GetNextMarshal () const;
+ inline void SetNextMarshal (CMarshalList *pml);
+ inline ContextId GetContextId () const;
+ CMarshalList * FindMarshal (ContextId ctxid) const;
+ void AddMarshal (CMarshalList *pml);
+ void RemoveMarshal (CMarshalList *pml);
+
+private:
+ CBasedMarshalListPtr _pmlNext;
+ ContextId _cntxid;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMarshalList::CMarshalList, public
+//
+// Synopsis: Constructor
+//
+// History: 17-Mar-96 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+inline CMarshalList::CMarshalList ()
+{
+ _pmlNext = P_TO_BP(CBasedMarshalListPtr, this);
+ _cntxid = GetCurrentContextId();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMarshalList::~CMarshalList, public
+//
+// Synopsis: Destructor
+//
+// History: 17-Mar-96 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+inline CMarshalList::~CMarshalList ()
+{
+ RemoveMarshal(this);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMarshalList::GetNext, public
+//
+// Synopsis: Returns the next element of the list
+//
+// History: 17-Mar-96 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+inline CMarshalList *CMarshalList::GetNextMarshal () const
+{
+ return BP_TO_P(CMarshalList *, _pmlNext);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMarshalList::SetNext, public
+//
+// Synopsis: Assigns the next element of the list
+//
+// History: 17-Mar-96 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMarshalList::SetNextMarshal (CMarshalList *pml)
+{
+ _pmlNext = P_TO_BP(CBasedMarshalListPtr, pml);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMarshalList::GetContextId, public
+//
+// Synopsis: Returns the context id of the current element
+//
+// History: 17-Mar-96 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+inline ContextId CMarshalList::GetContextId () const
+{
+ return _cntxid;
+}
+
+#endif // #ifndef __MRSHLIST_HXX__
diff --git a/private/ole32/stg/exp/nmidmap.cxx b/private/ole32/stg/exp/nmidmap.cxx
new file mode 100644
index 000000000..f6a1438f0
--- /dev/null
+++ b/private/ole32/stg/exp/nmidmap.cxx
@@ -0,0 +1,164 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: nmidmap.cxx
+//
+// Contents: CNameIdMap implementation
+//
+// History: 11-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include "nmidmap.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNameIdMap::~CNameIdMap, public
+//
+// Synopsis: Destroys map
+//
+// History: 11-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CNameIdMap::~CNameIdMap(void)
+{
+ while (_pniHead)
+ {
+ SNameId *pni = _pniHead->pniNext;
+
+ DfMemFree(_pniHead->lpwstr);
+ DfMemFree(_pniHead);
+ _pniHead = pni;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNameIdMap::Add, public
+//
+// Synopsis: Adds a mapping
+//
+// Arguments: [lpwstr] - Name
+// [id] - Id
+//
+// Returns: Pointer to mapping or NULL for failure
+//
+// History: 11-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SNameId *CNameIdMap::Add(LPWSTR lpwstr, PROPID id)
+{
+ SNameId *pni;
+
+ pni = (SNameId *)DfMemAlloc(sizeof(SNameId));
+ if (pni == NULL)
+ return NULL;
+ pni->lpwstr = (WCHAR *)DfMemAlloc((wcslen(lpwstr)+1)*sizeof(WCHAR));
+ if (pni->lpwstr == NULL)
+ {
+ DfMemFree(pni);
+ return NULL;
+ }
+ wcscpy(pni->lpwstr, lpwstr);
+ pni->id = id;
+ pni->pniNext = _pniHead;
+ _pniHead = pni;
+ return pni;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNameIdMap::RemoveByName, public
+//
+// Synopsis: Removes an entry found by name
+//
+// Arguments: [lpwstr] - Name
+//
+// History: 12-Jul-93 DrewB Created
+//
+// Notes: Entry doesn't have to exist
+//
+//----------------------------------------------------------------------------
+
+#ifdef REMOVE_NEEDED
+void CNameIdMap::RemoveByName(LPWSTR lpwstr)
+{
+ SNameId *pni, **ppniPrevPtr;
+
+ pni = FindMapping(lpwstr, PROPID_UNKNOWN, &ppniPrevPtr);
+ if (pni)
+ Remove(ppniPrevPtr, pni);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNameIdMap::RemoveById, private
+//
+// Synopsis: Removes an entry found by id
+//
+// Arguments: [id] - ID
+//
+// Returns: Appropriate status code
+//
+// History: 12-Jul-93 DrewB Created
+//
+// Notes: Entry doesn't have to exist
+//
+//----------------------------------------------------------------------------
+
+#ifdef REMOVE_NEEDED
+void CNameIdMap::RemoveById(PROPID id)
+{
+ SNameId *pni, **ppniPrevPtr;
+
+ pni = FindMapping(NULL, id, &ppniPrevPtr);
+ if (pni)
+ Remove(ppniPrevPtr, pni);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNameIdMap::FindMapping, private
+//
+// Synopsis: Finds a mapping by name or id
+//
+// Arguments: [lpwstr] - LPWSTR or NULL
+// [id] - ID or PROPID_UNKNOWN
+// [pppniPrevPtr] - Returns pointer to previous list element's
+// reference to found element, can be NULL
+//
+// Returns: Pointer to mapping or NULL
+//
+// Modifies: [pppniPrevPtr] if non-NULL
+//
+// History: 12-Jul-93 DrewB Created
+//
+// Notes: Depends on PROPID_UNKNOWN not being present in the list
+//
+//----------------------------------------------------------------------------
+
+SNameId *CNameIdMap::FindMapping(LPWSTR lpwstr,
+ PROPID id,
+ SNameId ***pppniPrevPtr)
+{
+ SNameId **ppni;
+
+ for (ppni = &_pniHead; *ppni; ppni = &(*ppni)->pniNext)
+ if ((lpwstr && _wcsicmp(lpwstr, (*ppni)->lpwstr) == 0) ||
+ id == (*ppni)->id)
+ {
+ if (pppniPrevPtr)
+ *pppniPrevPtr = ppni;
+ return *ppni;
+ }
+ return NULL;
+}
diff --git a/private/ole32/stg/exp/nmidmap.hxx b/private/ole32/stg/exp/nmidmap.hxx
new file mode 100644
index 000000000..6312f8942
--- /dev/null
+++ b/private/ole32/stg/exp/nmidmap.hxx
@@ -0,0 +1,150 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: nmidmap.hxx
+//
+// Contents: CNameIdMap header
+//
+// Classes: CNameIdMap
+//
+// History: 11-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __NMIDMAP_HXX__
+#define __NMIDMAP_HXX__
+
+#include <ole2.h>
+
+//+---------------------------------------------------------------------------
+//
+// Structure: SNameId (ni)
+//
+// Purpose: Holds a name/id pair
+//
+// History: 11-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+struct SNameId
+{
+ LPWSTR lpwstr;
+ PROPID id;
+ SNameId *pniNext;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Class: CNameIdMap (nim)
+//
+// Purpose: Keeps track of a mapping between a name and an id
+//
+// Interface: See below
+//
+// History: 11-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CNameIdMap
+{
+public:
+ inline CNameIdMap(void);
+ ~CNameIdMap(void);
+
+ SNameId *Add(LPWSTR lpwstr, PROPID id);
+ inline LPWSTR NameFromId(PROPID id);
+ inline PROPID IdFromName(LPWSTR lpwstr);
+ void RemoveByName(LPWSTR lpwstr);
+ void RemoveById(PROPID id);
+
+private:
+ SNameId *FindMapping(LPWSTR lpwstr, PROPID id, SNameId ***pppniPrevPtr);
+ void Remove(SNameId **ppniPrevPtr, SNameId *pni);
+
+ SNameId *_pniHead;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNameIdMap::CNameIdMap, public
+//
+// Synopsis: Initializes a map
+//
+// History: 11-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline CNameIdMap::CNameIdMap(void)
+{
+ _pniHead = NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNameIdMap::NameFromId, public
+//
+// Synopsis: Maps an id to a name
+//
+// Arguments: [id] - Id
+//
+// Returns: Name or NULL
+//
+// History: 11-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline LPWSTR CNameIdMap::NameFromId(PROPID id)
+{
+ SNameId *pni;
+
+ pni = FindMapping(NULL, id, NULL);
+ return pni ? pni->lpwstr : NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNameIdMap::IdFromName, public
+//
+// Synopsis: Maps a name to an id
+//
+// Arguments: [lpwstr] - Name
+//
+// Returns: Id or PROPID_UNKNOWN
+//
+// History: 11-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline PROPID CNameIdMap::IdFromName(LPWSTR lpwstr)
+{
+ SNameId *pni;
+
+ pni = FindMapping(lpwstr, PROPID_UNKNOWN, NULL);
+ return pni ? pni->id : PROPID_UNKNOWN;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNameIdMap::Remove, private
+//
+// Synopsis: Unlinks a mapping from the list
+//
+// Arguments: [ppniPrevPtr] - Previous pointer to element to remove
+// [pni] - Element to remove
+//
+// History: 12-Jul-93 DrewB Created
+//
+// Notes: Frees memory
+//
+//----------------------------------------------------------------------------
+
+inline void CNameIdMap::Remove(SNameId **ppniPrevPtr, SNameId *pni)
+{
+ *ppniPrevPtr = pni->pniNext;
+ DfMemFree(pni->lpwstr);
+ DfMemFree(pni);
+}
+
+#endif // #ifndef __NMIDMAP_HXX__
diff --git a/private/ole32/stg/exp/peiter.cxx b/private/ole32/stg/exp/peiter.cxx
new file mode 100644
index 000000000..dcdfa7b9e
--- /dev/null
+++ b/private/ole32/stg/exp/peiter.cxx
@@ -0,0 +1,171 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: peiter.cxx
+//
+// Contents: Implementation of PExposedIterator
+//
+// History: 18-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <peiter.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Member: PExposedIterator::hSkip, public
+//
+// Synopsis: Enumerator skip helper function
+//
+// History: 18-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_PExposedIterator_hSkip)
+#endif
+
+SCODE PExposedIterator::hSkip(ULONG celt, BOOL fProps)
+{
+ SCODE sc;
+#ifndef REF
+ SAFE_SEM;
+ SAFE_ACCESS;
+#endif //!REF
+ SIterBuffer ib;
+
+ olDebugOut((DEB_ITRACE, "In PExposedIterator::hSkip:%p(%lu, %d)\n",
+ this, celt, fProps));
+#ifndef REF
+ olChk(TakeSafeSem());
+ olChk(_ppdf->CheckReverted());
+ SafeReadAccess();
+#endif //!REF
+ for (; celt>0; celt--)
+ {
+ sc = _ppdf->FindGreaterEntry(&_dfnKey, &ib, NULL, fProps);
+ if (FAILED(sc))
+ {
+ if (sc == STG_E_NOMOREFILES)
+ sc = S_FALSE;
+ break;
+ }
+ _dfnKey.Set(&ib.dfnName);
+ }
+ olDebugOut((DEB_ITRACE, "Out PExposedIterator::hSkip\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: PExposedIterator::hRelease, public
+//
+// Synopsis: Release helper
+//
+// History: 18-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_PExposedIterator_hRelease)
+#endif
+
+LONG PExposedIterator::hRelease(void)
+{
+ LONG lRet;
+
+ olDebugOut((DEB_ITRACE, "In PExposedIterator::hRelease:%p()\n", this));
+
+ olAssert(_cReferences > 0);
+
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet < 0)
+ {
+ lRet = 0;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out PExposedIterator::hRelease => %lu\n", lRet));
+ return lRet;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: PExposedIterator::hQueryInterface, public
+//
+// Synopsis: QueryInterface helper
+//
+// History: 18-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_PExposedIterator_hQueryInterface)
+#endif
+
+SCODE PExposedIterator::hQueryInterface(REFIID iid,
+ REFIID riidSelf,
+ IUnknown *punkSelf,
+ void **ppv)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In PExposedIterator::hQueryInterface:%p("
+ "riid, riidSelf, %p, %p)\n", this, punkSelf, ppv));
+
+#ifdef MULTIHEAP
+ CSafeMultiHeap smh(_ppc);
+#endif
+ olChk(ValidateOutPtrBuffer(ppv));
+ *ppv = NULL;
+ olChk(_ppdf->CheckReverted());
+ olChk(ValidateIid(iid));
+
+ if (IsEqualIID(iid, riidSelf) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppv = punkSelf;
+ hAddRef();
+ sc = S_OK;
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out PExposedIterator::hQueryInterface\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: PExposedIterator::hReset, public
+//
+// Synopsis: Reset help
+//
+// History: 18-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE PExposedIterator::hReset(void)
+{
+ SCODE sc;
+ SAFE_SEM;
+ SAFE_ACCESS;
+
+ olDebugOut((DEB_ITRACE, "In PExposedIterator::hReset:%p()\n", this));
+
+ olChk(TakeSafeSem());
+ SafeReadAccess();
+
+ _dfnKey.Set((WORD)0, (BYTE *)NULL);
+ sc = _ppdf->CheckReverted();
+ olDebugOut((DEB_ITRACE, "Out PExposedIterator::hReset\n"));
+EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/exp/peiter.hxx b/private/ole32/stg/exp/peiter.hxx
new file mode 100644
index 000000000..df2541fb2
--- /dev/null
+++ b/private/ole32/stg/exp/peiter.hxx
@@ -0,0 +1,73 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: peiter.hxx
+//
+// Contents: PExposedIterator class
+//
+// Classes: PExposedIterator
+//
+// History: 18-Jan-93 DrewB Created
+//
+// Notes: PExposedIterator is a partial exposed iterator
+// implementation used by CExposedIterator.
+//
+//----------------------------------------------------------------------------
+
+#ifndef __PEITER_HXX__
+#define __PEITER_HXX__
+
+#ifndef REF
+#include <dfmem.hxx>
+
+#ifndef REF
+interface PExposedIterator : public CLocalAlloc
+#else
+interface PExposedIterator
+#endif //!REF
+{
+public:
+ SCODE hSkip(ULONG celt, BOOL fProps);
+ SCODE hReset(void);
+ inline LONG hAddRef(void);
+ LONG hRelease(void);
+ SCODE hQueryInterface(REFIID iid,
+ REFIID riidSelf,
+ IUnknown *punkSelf,
+ void **ppv);
+
+protected:
+
+ CBasedPubDocFilePtr _ppdf;
+ CDfName _dfnKey;
+#ifndef REF
+ CBasedDFBasisPtr _pdfb;
+ CPerContext *_ppc;
+ BOOL _fOwnContext;
+#endif //!REF
+ LONG _cReferences;
+ ULONG _sig;
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: PExposedIterator::hAddRef, public
+//
+// Synopsis: AddRef helper
+//
+// History: 18-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+LONG PExposedIterator::hAddRef(void)
+{
+ olDebugOut((DEB_ITRACE, "In PExposedIterator::hAddRef:%p()\n", this));
+ InterlockedIncrement(&_cReferences);
+ olDebugOut((DEB_ITRACE, "Out PExposedIterator::hAddRef\n"));
+ return _cReferences;
+}
+#endif //!REF
+#endif // #ifndef __PEITER_HXX__
diff --git a/private/ole32/stg/exp/props.cxx b/private/ole32/stg/exp/props.cxx
new file mode 100644
index 000000000..f81050a19
--- /dev/null
+++ b/private/ole32/stg/exp/props.cxx
@@ -0,0 +1,225 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: props.cxx
+//
+// Contents: Property code shared between OFS and docfile
+//
+// Functions: ValidatePropType
+//
+// History: 14-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <memalloc.h>
+#include "props.hxx"
+#include "logfile.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Function: ValidatePropType, public
+//
+// Synopsis: Checks the given proptype for legality
+//
+// Arguments: [dpt] - Property type
+//
+// Returns: Appropriate status code
+//
+// History: 23-Dec-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE ValidatePropType(DFPROPTYPE dpt)
+{
+ olDebugOut((DEB_ITRACE, "In ValidatePropType(%X)\n", dpt));
+ if (dpt == VT_EMPTY ||
+ dpt == VT_I2 ||
+ dpt == (VT_I2 | VT_VECTOR) ||
+ dpt == VT_I4 ||
+ dpt == (VT_I4 | VT_VECTOR) ||
+ dpt == VT_R4 ||
+ dpt == (VT_R4 | VT_VECTOR) ||
+ dpt == VT_R8 ||
+ dpt == (VT_R8 | VT_VECTOR) ||
+ dpt == VT_CY ||
+ dpt == (VT_CY | VT_VECTOR) ||
+ dpt == VT_DATE ||
+ dpt == (VT_DATE | VT_VECTOR) ||
+ dpt == VT_BSTR ||
+ dpt == (VT_BSTR | VT_VECTOR) ||
+#ifdef OLDPROPS
+ dpt == VT_WBSTR ||
+ dpt == (VT_WBSTR | VT_VECTOR) ||
+#endif
+ dpt == VT_BOOL ||
+ dpt == (VT_BOOL | VT_VECTOR) ||
+ dpt == VT_I8 ||
+ dpt == (VT_I8 | VT_VECTOR) ||
+ dpt == VT_LPSTR ||
+ dpt == (VT_LPSTR | VT_VECTOR) ||
+ dpt == VT_BLOB ||
+ dpt == VT_BLOB_OBJECT ||
+ dpt == VT_LPWSTR ||
+ dpt == (VT_LPWSTR | VT_VECTOR) ||
+ dpt == VT_FILETIME ||
+ dpt == (VT_FILETIME | VT_VECTOR) ||
+ dpt == VT_UUID ||
+ dpt == (VT_UUID | VT_VECTOR) ||
+ dpt == VT_VARIANT ||
+ dpt == (VT_VARIANT | VT_VECTOR) ||
+ dpt == VT_STREAM ||
+ dpt == VT_STREAMED_OBJECT ||
+ dpt == VT_STORAGE ||
+ dpt == VT_STORED_OBJECT ||
+ dpt == VT_CF)
+ return S_OK;
+ olDebugOut((DEB_ITRACE, "Out ValidatePropType\n"));
+ return STG_E_INVALIDPARAMETER;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: FreeVariantArray, public
+//
+// Synopsis: Frees a value array returned from ReadMultiple
+//
+// Arguments: [cval] - Number of elements
+// [rgdpv] - Array
+//
+// Returns: Appropriate status code
+//
+// History: 18-Dec-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI FreeVariantArray(DWORD cval, DFPROPVAL rgdpv[])
+{
+ SCODE sc;
+ DFPROPVAL *pdpv;
+ ULONG i;
+
+ olLog(("--------::In FreeVariantArray(%lu, %p)\n", cval, rgdpv));
+ olDebugOut((DEB_ITRACE, "In FreeVariantArray(%lu, %p)\n",
+ cval, rgdpv));
+
+ // BUGBUG - This should just call VariantClear when that works
+ // properly
+
+ olChk(ValidateBuffer(rgdpv, sizeof(DFPROPVAL)*cval));
+ pdpv = rgdpv;
+ for (; cval > 0; cval--, pdpv++)
+ {
+ switch(pdpv->vt)
+ {
+ case VT_EMPTY:
+ case VT_I2:
+ case VT_I4:
+ case VT_R4:
+ case VT_R8:
+ case VT_CY:
+ case VT_DATE:
+ case VT_BOOL:
+ case VT_I8:
+ case VT_FILETIME:
+ break;
+
+ case VT_I2 | VT_VECTOR:
+ case VT_I4 | VT_VECTOR:
+ case VT_R4 | VT_VECTOR:
+ case VT_R8 | VT_VECTOR:
+ case VT_CY | VT_VECTOR:
+ case VT_DATE | VT_VECTOR:
+ case VT_BOOL | VT_VECTOR:
+ case VT_I8 | VT_VECTOR:
+ case VT_FILETIME | VT_VECTOR:
+ case VT_UUID | VT_VECTOR:
+ break;
+
+ case VT_BSTR:
+ TaskMemFree(BSTR_PTR(pdpv->bstrVal));
+ break;
+ case VT_BSTR | VT_VECTOR:
+ for (i = 0; i < pdpv->cabstr.cElems; i++)
+ TaskMemFree(BSTR_PTR(pdpv->cabstr.pElems[i]));
+ break;
+#ifdef OLDPROPS
+ case VT_WBSTR:
+ TaskMemFree(WBSTR_PTR(pdpv->wbstrVal));
+ break;
+ case VT_WBSTR | VT_VECTOR:
+ for (i = 0; i < pdpv->cawbstr.cElems; i++)
+ TaskMemFree(WBSTR_PTR(pdpv->cawbstr.pElems[i]));
+ break;
+#endif
+ case VT_LPSTR:
+ TaskMemFree(pdpv->pszVal);
+ break;
+ case VT_LPSTR | VT_VECTOR:
+ for (i = 0; i < pdpv->calpstr.cElems; i++)
+ TaskMemFree(pdpv->calpstr.pElems[i]);
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ TaskMemFree(pdpv->blob.pBlobData);
+ break;
+
+ case VT_LPWSTR:
+ TaskMemFree(pdpv->pwszVal);
+ break;
+ case VT_LPWSTR | VT_VECTOR:
+ for (i = 0; i < pdpv->calpwstr.cElems; i++)
+ TaskMemFree(pdpv->calpwstr.pElems[i]);
+ break;
+
+ case VT_UUID:
+ TaskMemFree(pdpv->puuid);
+ break;
+
+ case VT_VARIANT:
+ olHVerSucc(FreeVariantArray(1, pdpv->pvarVal));
+ TaskMemFree(pdpv->pvarVal);
+ break;
+ case VT_VARIANT | VT_VECTOR:
+ olHVerSucc(FreeVariantArray(pdpv->cavar.cElems,
+ pdpv->cavar.pElems));
+ break;
+
+ case VT_CF:
+ TaskMemFree(pdpv->pClipData->pClipData);
+ TaskMemFree(pdpv->pClipData);
+ break;
+
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ if (pdpv->pIStorage)
+ pdpv->pIStorage->Release();
+ break;
+
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ if (pdpv->pIStream)
+ pdpv->pIStream->Release();
+ break;
+
+ default:
+ olAssert(!aMsg("Unknown property type in FreeVariantArray"));
+ break;
+ }
+
+ if (pdpv->vt & VT_VECTOR)
+ {
+ TaskMemFree(pdpv->cai.pElems);
+ }
+ }
+
+ olDebugOut((DEB_ITRACE, "Out FreeVariantArray\n"));
+ EH_Err:
+ olLog(("--------::Out FreeVariantArray(). sc == %lX\n", sc));
+ return ResultFromScode(sc);
+}
diff --git a/private/ole32/stg/exp/ptrcache.cxx b/private/ole32/stg/exp/ptrcache.cxx
new file mode 100644
index 000000000..dddb1f287
--- /dev/null
+++ b/private/ole32/stg/exp/ptrcache.cxx
@@ -0,0 +1,94 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ptrcache.cxx
+//
+// Contents: CPtrCache implementation
+//
+// History: 26-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "exphead.cxx"
+#pragma hdrstop
+
+#include <ptrcache.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPtrCache::~CPtrCache, public
+//
+// Synopsis: Destructor
+//
+// History: 26-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CPtrCache::~CPtrCache(void)
+{
+ CPtrBlock *pb;
+
+ Win4Assert(_pbHead != NULL);
+ while (_pbHead != &_pbFirst)
+ {
+ pb = _pbHead->Next();
+ delete _pbHead;
+ _pbHead = pb;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPtrCache::Add, public
+//
+// Synopsis: Adds a pointer to the cache
+//
+// Arguments: [pv] - Pointer
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CPtrCache::Add(void *pv)
+{
+ CPtrBlock *pb;
+
+ Win4Assert(_pbHead != NULL);
+ if (_pbHead->Full())
+ {
+ pb = new CPtrBlock(_pbHead);
+ if (pb == NULL)
+ return E_OUTOFMEMORY;
+ _pbHead = pb;
+ }
+ _pbHead->Add(pv);
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPtrCache::Next, public
+//
+// Synopsis: Returns the next element in the enumeration
+//
+// Arguments: [ppv] - Pointer return
+//
+// Returns: TRUE/FALSE
+//
+// History: 26-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+BOOL CPtrCache::Next(void **ppv)
+{
+ if (_pbEnum && _iEnum >= _pbEnum->Count())
+ _pbEnum = _pbEnum->Next();
+ if (_pbEnum == NULL)
+ return FALSE;
+ *ppv = _pbEnum->Nth(_iEnum++);
+ return TRUE;
+}
diff --git a/private/ole32/stg/exp/resource.cxx b/private/ole32/stg/exp/resource.cxx
new file mode 100644
index 000000000..fbde8f55e
--- /dev/null
+++ b/private/ole32/stg/exp/resource.cxx
@@ -0,0 +1,669 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: resource.cxx
+//
+// Contents: Transacted Resource Manager implementation
+//
+// Classes:
+//
+// Functions:
+//
+// History: 03-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "exphead.cxx"
+#pragma hdrstop
+
+#include "resource.hxx"
+
+#ifdef COORD
+
+CRITICAL_SECTION g_csResourceList;
+CDocfileResource g_dfrHead(TRUE);
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::CDocfileResource, public
+//
+// Synopsis: Default constructor
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CDocfileResource::CDocfileResource(BOOL fStatic)
+ :_fStatic(fStatic)
+{
+ _cReferences = 1;
+ _pte = NULL;
+ _pedlHead = NULL;
+ _pdrPrev = _pdrNext = NULL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::~CDocfileResource, public
+//
+// Synopsis: Destructor
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CDocfileResource::~CDocfileResource()
+{
+ //If we're the static object, we're just a placeholder, and
+ // the fact that we're being deleted means the whole process
+ // is going away. We don't need to do any of this cleanup for
+ // that case, and since we can't guarantee that the critical section
+ // is still valid, we don't want to.
+ if (!_fStatic)
+ {
+ if (_pte != NULL)
+ {
+ _pte->Release();
+ }
+ //Remove from list.
+
+ EnterCriticalSection(&g_csResourceList);
+ if (_pdrPrev != NULL)
+ {
+ _pdrPrev->SetNext(_pdrNext);
+ }
+ if (_pdrNext != NULL)
+ {
+ _pdrNext->SetPrev(_pdrPrev);
+ }
+ LeaveCriticalSection(&g_csResourceList);
+
+ //Release all exposed objects.
+ SExpDocfileList *pedl = _pedlHead;
+ while (pedl != NULL)
+ {
+ SExpDocfileList *pedlTemp = pedl->pedlNext;
+ pedl->pexp->Release();
+ delete pedl;
+ pedl = pedlTemp;
+ }
+ }
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::Init, public
+//
+// Synopsis: Initialize instance
+//
+// Arguments: [pte] -- Pointer to transaction enlistment for this
+// resource
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CDocfileResource::Init(ITransactionEnlistment *pte)
+{
+ olDebugOut((DEB_ITRACE, "In CDocfileResource::Init:%p()\n", this));
+
+ _pte = pte;
+
+ olDebugOut((DEB_ITRACE, "Out CDocfileResource::Init\n"));
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::QueryInterface, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDocfileResource::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc = S_OK;
+
+ olDebugOut((DEB_ITRACE,
+ "In CDocfileResource::QueryInterface:%p()\n",
+ this));
+
+ *ppvObj = NULL;
+
+ if ((IsEqualIID(iid, IID_IUnknown)) ||
+ (IsEqualIID(iid, IID_ITransactionResource)) ||
+ (IsEqualIID(iid, IID_ITransactionResourceManagement)))
+ {
+ *ppvObj = (ITransactionResource *)this;
+ }
+ else if (IsEqualIID(iid, IID_ITransactionResourceRecover))
+ {
+ *ppvObj = (ITransactionResourceRecover *)this;
+ }
+ else if (IsEqualIID(iid, IID_ITransactionResourceAsync))
+ {
+ *ppvObj = (ITransactionResourceAsync *)this;
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ CDocfileResource::AddRef();
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CDocfileResource::QueryInterface\n"));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::AddRef, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDocfileResource::AddRef(void)
+{
+ ULONG ulRet;
+ olDebugOut((DEB_ITRACE, "In CDocfileResource::AddRef:%p()\n", this));
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+
+ olDebugOut((DEB_ITRACE, "Out CDocfileResource::AddRef\n"));
+ return ulRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::Release, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CDocfileResource::Release(void)
+{
+ LONG lRet;
+ olDebugOut((DEB_ITRACE, "In CDocfileResource::Release:%p()\n", this));
+
+ olAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ lRet = 0;
+ olDebugOut((DEB_ITRACE, "Out CDocfileResource::Release\n"));
+ return (ULONG)lRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::Prepare, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDocfileResource::Prepare(BOOL fRetaining,
+ DWORD grfRM,
+ BOOL fSinglePhase,
+ IMoniker **ppmk,
+ BOID **ppboidReason)
+{
+ //BUGBUG: Return moniker
+ SCODE sc = S_OK;
+ olDebugOut((DEB_ITRACE, "In CDocfileResource::Prepare:%p()\n", this));
+
+ SExpDocfileList *pedlTemp = _pedlHead;
+
+ //Note: There is no difference for us between a retaining prepare and
+ // a non-retaining prepare. The coordinator will defect us after
+ // a non-retaining commit, which will trigger all the appropriate
+ // cleanup. Pretty convenient.
+ STGC stgc = (grfRM & XACTRM_OPTIMISTICLASTWINS) ? STGC_DEFAULT :
+ STGC_ONLYIFCURRENT;
+
+ while (pedlTemp != NULL)
+ {
+ sc = pedlTemp->pexp->CommitPhase1(stgc);
+
+ if (FAILED(sc))
+ {
+ SExpDocfileList *pedlTemp2 = _pedlHead;
+ while (pedlTemp2 != pedlTemp)
+ {
+ pedlTemp2->pexp->CommitPhase2(stgc, FALSE);
+ pedlTemp2 = pedlTemp2->pedlNext;
+ }
+ return sc;
+ }
+ pedlTemp = pedlTemp->pedlNext;
+ }
+
+ if (fSinglePhase)
+ {
+ //BUGBUG: Waiting on spec question from Bob about what to do
+ // for the case where both fRetaining and fSinglePhase are true.
+ // How do we get the new UOW in that case?
+ olAssert(!fRetaining);
+ sc = Commit(grfRM, NULL);
+ }
+ olDebugOut((DEB_ITRACE, "Out CDocfileResource::Prepare\n"));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::Commit, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDocfileResource::Commit(DWORD grfRM, XACTUOW *pNewUOW)
+{
+ SCODE sc = S_OK;
+
+ olDebugOut((DEB_ITRACE, "In CDocfileResource::Commit:%p()\n", this));
+
+ SExpDocfileList *pedlTemp = _pedlHead;
+
+ STGC stgc = (grfRM & XACTRM_OPTIMISTICLASTWINS) ? STGC_DEFAULT :
+ STGC_ONLYIFCURRENT;
+
+ while (pedlTemp != NULL)
+ {
+ sc = pedlTemp->pexp->CommitPhase2(stgc, TRUE);
+
+ if (FAILED(sc))
+ {
+ //Augh, panic.
+ return sc;
+ }
+ pedlTemp = pedlTemp->pedlNext;
+ }
+
+ if (pNewUOW != NULL)
+ {
+ _xti.uow = *pNewUOW;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CDocfileResource::Commit\n"));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::Abort, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDocfileResource::Abort(
+ BOID *pboidReason,
+ BOOL fRetaining,
+ XACTUOW *pNewUOW)
+{
+ SCODE sc = S_OK;
+
+ olDebugOut((DEB_ITRACE, "In CDocfileResource::Abort:%p()\n", this));
+
+ SExpDocfileList *pedlTemp = _pedlHead;
+
+ if (fRetaining)
+ {
+#ifdef RETAINING_ABORT
+ //We need to do some special stuff to make the pub docfiles
+ //stay valid
+ if (pNewUOW != NULL)
+ {
+ _xti.uow;
+ }
+#else
+ return XACT_E_CANTRETAIN;
+#endif
+ }
+
+ while (pedlTemp != NULL)
+ {
+ sc = pedlTemp->pexp->Revert();
+
+ if (FAILED(sc))
+ {
+ //Augh, panic.
+ return sc;
+ }
+ pedlTemp = pedlTemp->pedlNext;
+ }
+
+
+ olDebugOut((DEB_ITRACE, "Out CDocfileResource::Abort\n"));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::GetMoniker, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDocfileResource::GetMoniker(IMoniker **ppmk)
+{
+ olDebugOut((DEB_ITRACE, "In CDocfileResource::GetMoniker:%p()\n", this));
+ olDebugOut((DEB_ITRACE, "Out CDocfileResource::GetMoniker\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::ReEnlist, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDocfileResource::ReEnlist(ITransactionCoordinator *pEnlistment,
+ XACTUOW *pUOWCur)
+{
+ olDebugOut((DEB_ITRACE, "In CDocfileResource::ReEnlist:%p()\n", this));
+ olDebugOut((DEB_ITRACE, "Out CDocfileResource::ReEnlist\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::PrepareRequest, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDocfileResource::PrepareRequest(BOOL fRetaining,
+ DWORD grfRM,
+ BOOL fWantMoniker,
+ BOOL fSinglePhase)
+{
+ olDebugOut((DEB_ITRACE, "In CDocfileResource::PrepareRequest:%p()\n", this));
+ olDebugOut((DEB_ITRACE, "Out CDocfileResource::PrepareRequest\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::CommitRequest, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDocfileResource::CommitRequest(DWORD grfRM, XACTUOW *pNewUOW)
+{
+ olDebugOut((DEB_ITRACE,
+ "In CDocfileResource::CommitRequest:%p()\n",
+ this));
+
+ olDebugOut((DEB_ITRACE, "Out CDocfileResource::CommitRequest\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::AbortRequest, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDocfileResource::AbortRequest(BOID *pboidReason,
+ BOOL fRetaining,
+ XACTUOW *pNewUOW)
+{
+ olDebugOut((DEB_ITRACE, "In CDocfileResource::AbortRequest:%p()\n", this));
+ olDebugOut((DEB_ITRACE, "Out CDocfileResource::AbortRequest\n"));
+ return E_NOTIMPL;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::Defect, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 08-Aug-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDocfileResource::Defect(BOOL fInformCoordinator)
+{
+ olDebugOut((DEB_ITRACE, "In CDocfileResource::Defect:%p()\n", this));
+ if (!fInformCoordinator)
+ {
+ CDocfileResource::Release();
+ return S_OK;
+ }
+
+ SCODE sc = _pte->Defect();
+ if (SUCCEEDED(sc) || (sc == XACT_E_NOTRANSACTION))
+ {
+ CDocfileResource::Release();
+ return S_OK;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out CDocfileResource::Defect\n"));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::Enlist, public
+//
+// Synopsis: Enlist resource in the given transaction coordinator.
+//
+// Arguments: [ptc] -- Pointer to ITransactionCoordinator to enlist in
+//
+// Returns: Appropriate status code
+//
+// History: 08-Aug-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CDocfileResource::Enlist(ITransactionCoordinator *ptc)
+{
+ SCODE sc;
+ DWORD grfTCRMENLIST;
+
+ sc = ptc->Enlist((ITransactionResource *)this,
+ XACTRMTC_CANBEACTIVE,
+ NULL,
+ &_xti,
+ &grfTCRMENLIST,
+ &_pte);
+
+ _pte->AddRef();
+ //BUGBUG: Need to check grfTCRMENLIST
+ //BUGBUG: Need to check ISOLEVEL??
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocfileResource::Join, public
+//
+// Synopsis: Join an exposed docfile to a resource manager.
+//
+// Arguments: [ped] -- Pointer to exposed docfile
+//
+// Returns: Appropriate status code
+//
+// History: 08-Aug-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CDocfileResource::Join(CExposedDocFile *ped)
+{
+ SCODE sc;
+ olDebugOut((DEB_ITRACE, "In CDocfileResource::Join:%p()\n", this));
+ SExpDocfileList *pedl;
+
+ olMem(pedl = new SExpDocfileList);
+ pedl->pexp = ped;
+
+ pedl->pedlNext = _pedlHead;
+ _pedlHead = pedl;
+
+ olDebugOut((DEB_ITRACE, "Out CDocfileResource::Join\n"));
+
+EH_Err:
+ return sc;
+}
+
+#endif //COORD
diff --git a/private/ole32/stg/exp/resource.hxx b/private/ole32/stg/exp/resource.hxx
new file mode 100644
index 000000000..b4c619d62
--- /dev/null
+++ b/private/ole32/stg/exp/resource.hxx
@@ -0,0 +1,145 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: resource.hxx
+//
+// Contents: Transacted resource manager header file
+//
+// Classes:
+//
+// Functions:
+//
+// History: 03-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __RESOURCE_HXX__
+#define __RESOURCE_HXX__
+
+#include <msf.hxx>
+
+#ifdef COORD
+#include <oledb.h>
+#include <dfrlist.hxx>
+#include <expdf.hxx>
+
+struct SExpDocfileList
+{
+ CExposedDocFile *pexp;
+ SExpDocfileList *pedlNext;
+};
+
+
+//ITransactionResourceManagement is brought in by ITransactionResource
+class CDocfileResource:
+ public ITransactionResource,
+ public ITransactionResourceRecover,
+ public ITransactionResourceAsync
+{
+public:
+
+ CDocfileResource(BOOL fStatic = FALSE);
+ ~CDocfileResource();
+
+ SCODE Init(ITransactionEnlistment *pte);
+
+ //From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ //From ITransactionResourceManagement
+ STDMETHOD(Defect)(BOOL fInformCoordinator);
+
+ //From ITransactionResource
+ STDMETHOD(Prepare)(BOOL fRetaining,
+ DWORD grfRM,
+ BOOL fSinglePhase,
+ IMoniker **ppmk,
+ BOID **ppboidReason);
+ STDMETHOD(Commit)(DWORD grfRM, XACTUOW *pNewUOW);
+ STDMETHOD(Abort)(BOID *pboidReason, BOOL fRetaining, XACTUOW *pNewUOW);
+
+ //From ITransactionResourceRecover
+ STDMETHOD(GetMoniker)(IMoniker **ppmk);
+ STDMETHOD(ReEnlist)(ITransactionCoordinator *pEnlistment,
+ XACTUOW *pUOWCur);
+
+ //From ITransactionResourceAsync
+ STDMETHOD(PrepareRequest)(BOOL fRetaining,
+ DWORD grfRM,
+ BOOL fWantMoniker,
+ BOOL fSinglePhase);
+ STDMETHOD(CommitRequest)(DWORD grfRM, XACTUOW *pNewUOW);
+ STDMETHOD(AbortRequest)(BOID *pboidReason,
+ BOOL fRetaining,
+ XACTUOW *pNewUOW);
+
+ SCODE Enlist(ITransactionCoordinator *ptc);
+ SCODE Join(CExposedDocFile *ped);
+// SCODE Leave(CExposedDocfile *ped);
+
+ inline CDocfileResource * GetNext(void);
+ inline CDocfileResource * GetPrev(void);
+
+ inline void SetNext(CDocfileResource *pdrNext);
+ inline void SetPrev(CDocfileResource *pdrPrev);
+
+ inline XACTUOW GetUOW(void);
+
+private:
+ LONG _cReferences;
+ const BOOL _fStatic;
+
+ ITransactionEnlistment *_pte;
+ XACTTRANSINFO _xti;
+
+ SExpDocfileList *_pedlHead;
+
+ //We also will maintain a list of these things.
+ CDocfileResource *_pdrPrev;
+ CDocfileResource *_pdrNext;
+};
+
+
+inline CDocfileResource * CDocfileResource::GetNext(void)
+{
+ return _pdrNext;
+}
+
+inline CDocfileResource * CDocfileResource::GetPrev(void)
+{
+ return _pdrPrev;
+}
+
+inline void CDocfileResource::SetNext(CDocfileResource *pdrNext)
+{
+ _pdrNext = pdrNext;
+}
+
+inline void CDocfileResource::SetPrev(CDocfileResource *pdrPrev)
+{
+ _pdrPrev = pdrPrev;
+}
+
+inline XACTUOW CDocfileResource::GetUOW(void)
+{
+ return _xti.uow;
+}
+
+//Use a static object for the head of the list, to simplify adding and
+// deleting members.
+extern CDocfileResource g_dfrHead;
+
+//BUGBUG: This should really be defined someplace globally.
+#ifndef IsEqualBOID
+inline BOOL IsEqualBOID(BOID rboid1, BOID rboid2)
+{
+ return !memcmp(&rboid1, &rboid2, sizeof(BOID));
+}
+#endif
+
+#endif //COORD
+#endif // #ifndef __RESOURCE_HXX__
diff --git a/private/ole32/stg/exp/seekptr.cxx b/private/ole32/stg/exp/seekptr.cxx
new file mode 100644
index 000000000..decad8d20
--- /dev/null
+++ b/private/ole32/stg/exp/seekptr.cxx
@@ -0,0 +1,43 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: seekptr.cxx
+//
+// Contents: Seek pointer non-inline implementation
+//
+// History: 11-Aug-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <seekptr.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: CSeekPointer::Release, public
+//
+// Synopsis: Decrements _cReferences and delete's on noref
+//
+// History: 30-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CSeekPointer_vRelease)
+#endif
+
+void CSeekPointer::vRelease(void)
+{
+ LONG lRet;
+
+ olDebugOut((DEB_ITRACE, "In CSeekPointer::Release()\n"));
+ olAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ delete this;
+ olDebugOut((DEB_ITRACE, "Out CSeekPointer::Release()\n"));
+}
+
diff --git a/private/ole32/stg/exp/seekptr.hxx b/private/ole32/stg/exp/seekptr.hxx
new file mode 100644
index 000000000..513434450
--- /dev/null
+++ b/private/ole32/stg/exp/seekptr.hxx
@@ -0,0 +1,127 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: seekptr.hxx
+//
+// Contents: CSeekPointer header
+//
+// Classes: CSeekPointer
+//
+// History: 30-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __SEEKPTR_HXX__
+#define __SEEKPTR_HXX__
+
+
+//+--------------------------------------------------------------
+//
+// Class: CSeekPointer
+//
+// Purpose: Contains a seek pointer to share between exposed
+// streams
+//
+// Interface: See below.
+//
+// History: 30-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+class CSeekPointer : public CMallocBased
+{
+public:
+ inline CSeekPointer(ULONG ulPos);
+ inline ~CSeekPointer(void);
+
+ inline ULONG GetPos(void) const;
+ inline void SetPos(ULONG ulPos);
+ inline void vAddRef(void);
+ void vRelease(void);
+
+private:
+ ULONG _ulPos;
+ LONG _cReferences;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CSeekPointer::CSeekPointer, public
+//
+// Synopsis: Ctor
+//
+// Arguments: [ulPos] - Initial position
+//
+// History: 30-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CSeekPointer::CSeekPointer(ULONG ulPos)
+{
+ _ulPos = ulPos;
+ _cReferences = 1;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSeekPointer::~CSeekPointer, public
+//
+// Synopsis: Dtor
+//
+// History: 30-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CSeekPointer::~CSeekPointer(void)
+{
+ olAssert(_cReferences == 0);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSeekPointer::GetPos, public
+//
+// Synopsis: Returns _ulPos
+//
+// History: 30-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline ULONG CSeekPointer::GetPos(void) const
+{
+ return _ulPos;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSeekPointer::SetPos, public
+//
+// Synopsis: Assigns _ulPos
+//
+// History: 30-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CSeekPointer::SetPos(ULONG ulPos)
+{
+ _ulPos = ulPos;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSeekPointer::AddRef, public
+//
+// Synopsis: Increments _cReferences
+//
+// History: 30-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CSeekPointer::vAddRef(void)
+{
+ InterlockedIncrement(&_cReferences);
+}
+
+#endif // #ifndef __SEEKPTR_HXX__
diff --git a/private/ole32/stg/exp/segexp.hxx b/private/ole32/stg/exp/segexp.hxx
new file mode 100644
index 000000000..a144b7d31
--- /dev/null
+++ b/private/ole32/stg/exp/segexp.hxx
@@ -0,0 +1,218 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: SegEXP.HXX
+//
+// Contents: Segment defines for 16-bit builds
+//
+// History: 11-Jun-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __SEGEXP_HXX__
+#define __SEGEXP_HXX__
+
+#include <segh.hxx>
+
+#ifdef CODESEGMENTS
+
+// Code segment defines go here
+
+// Common code
+
+#define SEG_CContextList_Remove "Common0_TEXT" // cntxlist
+#define SEG_CED_1CED "Common0_TEXT" // Expdf_Shutdown // expdf
+#define SEG_CED_Release "Common0_TEXT" // Expdf_Release // expdf
+#define SEG_CES_1CES "Common0_TEXT" // Expst_Shutdown_TEXT // expst
+#define SEG_CES_Release "Common0_TEXT" // Expst_Release_TEXT // expst
+#define SEG_CFS_1CFS "Common0_TEXT" // CFS_Shutdown // filest16
+#define SEG_CFS_Release "Common0_TEXT" // filest
+#define SEG_CFS_UnlockRegion "Common0_TEXT" // filest16
+#define SEG_CFS_vRelease "Common0_TEXT" // filest
+#define SEG_CPerContext_1CPerContext "Common0_TEXT" // context
+#define SEG_CPerContext_Close "Common0_TEXT" // context
+#define SEG_CSeekPointer_vRelease "Common0_TEXT" // seekptr
+#define SEG_DfGetTOD "Common0_TEXT" // time16
+#define SEG_ReleaseOpen "Common0_TEXT" // lock
+#define SEG_ReleaseOpenWithMask "Common0_TEXT" // lock
+#define SEG_DfFromLB "Common0_TEXT" // Root_Text // docfile
+#define SEG_DfFromName "Common0_TEXT" // docfile
+#define SEG_StgIsStorageFile "Common3_TEXT" // storage
+
+#define SEG_CContextList_Add "Common1_TEXT" // cntxlist
+#define SEG_CED_AddRef "Common1_TEXT" // // expdf
+#define SEG_CED_CED "Common1_TEXT" // Expdf_Init // expdf
+#define SEG_CED_OpenEntry "Common1_TEXT" // Expdf_Open // expdf
+#define SEG_CED_OpenStreamA "Common1_TEXT" // ascii
+#define SEG_CED_OpenStream "Common1_TEXT" // Expdf_Open // expdf
+#define SEG_CED_StatA "Common0_TEXT" // ascii
+#define SEG_CED_Stat "Common1_TEXT" // Stat_TEXT // expdf
+#define SEG_CES_CES "Common1_TEXT" // Expst_Init_TEXT // expst
+#define SEG_CES_Init "Common1_TEXT" // expst
+#define SEG_CES_Read "Common1_TEXT" // Expst_Read_TEXT // expst
+#define SEG_CES_Seek "Common1_TEXT" // // expst
+#define SEG_CFS_AddRef "Common1_TEXT" // filest
+#define SEG_CFS_CFS "Common1_TEXT" // filest
+#define SEG_CFS_Flush "Common1_TEXT" // filest16
+#define SEG_CFS_GetLocksSupported "Common1_TEXT" // filest
+#define SEG_CFS_GetSize "Common1_TEXT" // filest16
+#define SEG_CFS_Init "Common1_TEXT" // CFS_Init // filest16
+#define SEG_CFS_InitFlags "Common1_TEXT" // filest
+#define SEG_CFS_LockRegion "Common1_TEXT" // filest16
+#define SEG_CFS_QueryInterface "Common1_TEXT" // filest
+#define SEG_CFS_ReadAt "Common1_TEXT" // // filest16
+#define SEG_CFS_ReserveHandle "Common1_TEXT" // CFS_ReserveHandle // filest16
+#define SEG_CFS_SetSize "Common1_TEXT" // filest16
+#define SEG_CFS_StatA "Common1_TEXT" // ascii
+#define SEG_CFS_Stat "Common1_TEXT" // Stat_TEXT // filest16
+#define SEG_CFS_WriteAt "Common1_TEXT" // filest16
+
+#define SEG_CheckAName "Common2_TEXT" // ascii
+#define SEG_CheckSignature "Common2_TEXT" // storage
+#define SEG_DosDup "Common2_TEXT" // filest16
+#define SEG_GetOpen "Common2_TEXT" // lock
+#define SEG_GetOpenWithMask "Common2_TEXT" // lock
+#define SEG_OpenStorageA "Common2_TEXT" // ascii
+#define SEG_OpenStorage "Common2_TEXT" // Root_Open_Text // docfile
+#define SEG_StgOpenStorage "Common2_TEXT" // storage
+
+#define SEG_CED_CreateEntry "BootSave_TEXT" // expdf
+#define SEG_CED_CreateStorageA "BootSave_TEXT" // ascii
+#define SEG_CED_CreateStorage "BootSave_TEXT" // Expdf_Create // expdf
+#define SEG_CED_CreateStreamA "BootSave_TEXT" // ascii
+#define SEG_CED_CreateStream "BootSave_TEXT" // Expdf_Create // expdf
+#define SEG_StgCreateDocfileA "BootSave_TEXT" // ascii
+#define SEG_StgCreateDocfile "BootSave_TEXT" // Root_Create_Text // docfile
+
+#define SEG_OpenStorageOnILockBytesA "Boot_TEXT" // ascii
+#define SEG_OpenStorageOnILockBytes "Boot_TEXT" // docfile
+#define SEG_StgOpenStorageOnILockBytes "Boot_TEXT" // storage
+
+#define SEG_StgSetTimes "OpenSave0_TEXT" // storage
+
+#define SEG_CED_Commit "OpenSave1_TEXT" // Expdf_Commit // expdf
+#define SEG_CED_OpenStorageA "OpenSave1_TEXT" // ascii
+#define SEG_CED_OpenStorage "OpenSave1_TEXT" // Expdf_Open // expdf
+#define SEG_CES_Write "OpenSave1_TEXT" // Expst_Write_TEXT // expst
+
+#define SEG_CES_StatA "Open_TEXT" // ascii
+#define SEG_CES_Stat "Open_TEXT" // Stat_TEXT // expst
+#define SEG_GetAccess "Open_TEXT" // lock
+#define SEG_GetAccessWithMask "Open_TEXT" // lock
+#define SEG_ReleaseAccess "Open_TEXT" // lock
+#define SEG_ReleaseAccessWithMask "Open_TEXT" // lock
+#define SEG_DosGetSectorSize "Open_TEXT" // filest16
+#define SEG_DosGetVolumeInfo "Open_TEXT" // filest16
+#define SEG_CFS_CheckIdentity "Open_TEXT" // filest16
+
+#define SEG_CED_SetClass "Save_TEXT" // expdf
+#define SEG_CFS_FlushCache "Save_TEXT" // filest16
+
+// Marshalling code
+
+#define SEG_CDUF_Release "Marshal_TEXT" // dfunmfct
+#define SEG_MarshalPointer "Marshal_TEXT" // marshl
+#define SEG_UnmarshalPointer "Marshal_TEXT" // marshl
+#define SEG_CContextList_Find "Marshal_TEXT" // cntxlist
+#define SEG_CDUF_CreateInstance "Marshal_TEXT" // dfunmfct
+#define SEG_CDUF_QueryInterface "Marshal_TEXT" // dfunmfct
+#define SEG_CDUF_ReleaseMarshalData "Marshal_TEXT" // dfunmfct
+#define SEG_CDUF_UnmarshalInterface "Marshal_TEXT" // dfunmfct
+#define SEG_DfUnMarshalInterface "Marshal_TEXT" // Marshal_TEXT // marshl
+#define SEG_StartMarshal "Marshal_TEXT" // marshl
+#define SEG_CFS_GetUnmarshalClass "Marshal_TEXT" // filest
+#define SEG_CFS_MarshalInterface "Marshal_TEXT" // filest
+#define SEG_CFS_Unmarshal "Marshal_TEXT" // Marshal_Text // filest
+#define SEG_CED_GetUnmarshalClass "Marshal_TEXT" // expdf
+#define SEG_CED_MarshalInterface "Marshal_TEXT" // expdf
+#define SEG_CED_QueryInterface "Marshal_TEXT" // expdf
+#define SEG_CED_Unmarshal "Marshal_TEXT" // Marshal_TEXT // expdf
+#define SEG_DllGetClassObject "Marshal_TEXT" // Marshal_TEXT // dfunmfct
+#define SEG_MarshalContext "Marshal_TEXT" // marshl
+#define SEG_UnmarshalContext "Marshal_TEXT" // marshl
+#define SEG_CFS_InitFromGlobal "Marshal_TEXT" // filest
+#define SEG_GetCoMarshalSize "Marshal_TEXT" // marshl
+#define SEG_GetStdMarshalSize "Marshal_TEXT" // marshl
+#define SEG_SkipStdMarshal "Marshal_TEXT" // marshl
+#define SEG_CED_GetMarshalSizeMax "Marshal_TEXT" // expdf
+
+// Less commonly used
+
+#define SEG_CES_SetSize "RareE_TEXT" // expst
+#define SEG_CFS_SwitchToFile "RareE_TEXT" // CFS_SwitchToFile // filest16
+#define SEG_CED_SwitchToFile "RareE_TEXT" // Expdf_SwitchToFile // expdf
+#define SEG_CES_Clone "RareE_TEXT" // // expst
+#define SEG_CES_CopyTo "RareE_TEXT" // Expst_CopyTo_TEXT // expst
+#define SEG_CED_Revert "RareE_TEXT" // Expdf_Revert // expdf
+#define SEG_CED_DestroyElement "RareE_TEXT" // Expdf_Destroy // expdf
+#define SEG_CED_CopySStreamToIStream "RareE_TEXT" // Expdf_CopyTo // expdf
+#define SEG_CED_CopyDocFileToIStorage "RareE_TEXT" // expdf
+#define SEG_CED_CopyToA "RareE_TEXT" // ascii
+#define SEG_CED_CheckCopyTo "RareE_TEXT" // // expdf
+#define SEG_CED_MakeCopyFlags "RareE_TEXT" // Expdf_CopyTo // expdf
+#define SEG_ValidateSNBA "RareE_TEXT" // ascii
+#define SEG_SNBToSNBW "RareE_TEXT" // ascii
+#define SEG_CES_AddRef "RareE_TEXT" // expst
+#define SEG_StgCreateDocfileOnILockBytes "RareE_TEXT" // docfile
+#define SEG_StgIsStorageILockBytes "RareE_TEXT" // storage
+
+// Unassigned
+
+#define SEG_CEI_NextA "UnassignedE_TEXT" // ascii
+#define SEG_CED_RenameElementA "UnassignedE_TEXT" // ascii
+#define SEG_CED_MoveElementToA "UnassignedE_TEXT" // ascii
+#define SEG_CED_SetElementTimesA "UnassignedE_TEXT" // ascii
+#define SEG_CDUF_AddRef "UnassignedE_TEXT" // dfunmfct
+#define SEG_CDUF_GetUnmarshalClass "UnassignedE_TEXT" // dfunmfct
+#define SEG_CDUF_GetMarshalSizeMax "UnassignedE_TEXT" // dfunmfct
+#define SEG_CDUF_MarshalInterface "UnassignedE_TEXT" // dfunmfct
+#define SEG_CDUF_DisconnectObject "UnassignedE_TEXT" // dfunmfct
+#define SEG_CDUF_LockServer "UnassignedE_TEXT" // dfunmfct
+#define SEG_CED_ConvertInternalStream "UnassignedE_TEXT" // Expdf_Create // expdf
+#define SEG_CED_EnumElements "UnassignedE_TEXT" // Expdf_Iterate // expdf
+#define SEG_CED_MoveElementTo "UnassignedE_TEXT" // Expdf_MoveTo // expdf
+#define SEG_CED_RenameElement "UnassignedE_TEXT" // Expdf_Rename // expdf
+#define SEG_CED_SetElementTimes "UnassignedE_TEXT" // // expdf
+#define SEG_CED_SetStateBits "UnassignedE_TEXT" // expdf
+#define SEG_CED_UnmarshalInterface "UnassignedE_TEXT" // expdf
+#define SEG_CED_ReleaseMarshalData "UnassignedE_TEXT" // expdf
+#define SEG_CED_DisconnectObject "UnassignedE_TEXT" // invalid // expdf
+#define SEG_CEI_CEI "UnassignedE_TEXT" // expiter
+#define SEG_CEI_Clone "UnassignedE_TEXT" // expiter
+#define SEG_CEI_1CEI "UnassignedE_TEXT" // expiter
+#define SEG_CEI_Next "UnassignedE_TEXT" // expiter
+#define SEG_CEI_Skip "UnassignedE_TEXT" // expiter
+#define SEG_CEI_Reset "UnassignedE_TEXT" // expiter
+#define SEG_CEI_Release "UnassignedE_TEXT" // expiter
+#define SEG_CEI_AddRef "UnassignedE_TEXT" // expiter
+#define SEG_CEI_QueryInterface "UnassignedE_TEXT" // expiter
+#define SEG_CES_LockRegion "UnassignedE_TEXT" // expst
+#define SEG_CES_UnlockRegion "UnassignedE_TEXT" // expst
+#define SEG_CES_Revert "UnassignedE_TEXT" // Expst_Revert_TEXT // expst
+#define SEG_CES_QueryInterface "UnassignedE_TEXT" // // expst
+#define SEG_CES_Unmarshal "UnassignedE_TEXT" // Marshal_TEXT // expst
+#define SEG_CES_GetUnmarshalClass "UnassignedE_TEXT" // expst
+#define SEG_CES_GetMarshalSizeMax "UnassignedE_TEXT" // expst
+#define SEG_CES_MarshalInterface "UnassignedE_TEXT" // expst
+#define SEG_CES_UnmarshalInterface "UnassignedE_TEXT" // unused // expst
+#define SEG_CES_ReleaseMarshalData "UnassignedE_TEXT" // unused // expst
+#define SEG_CES_DisconnectObject "UnassignedE_TEXT" // unused // expst
+#define SEG_CFS_GetMarshalSizeMax "UnassignedE_TEXT" // filest
+#define SEG_CFS_UnmarshalInterface "UnassignedE_TEXT" // filest
+#define SEG_CFS_ReleaseMarshalData "UnassignedE_TEXT" // filest
+#define SEG_CFS_DisconnectObject "UnassignedE_TEXT" // invalid // filest
+#define SEG_PExposedIterator_hSkip "UnassignedE_TEXT" // peiter
+#define SEG_PExposedIterator_hRelease "UnassignedE_TEXT" // peiter
+#define SEG_PExposedIterator_hQueryInterface "UnassignedE_TEXT" // peiter
+#define SEG_CFS_GetWinTempFile "UnassignedE_TEXT" // filest16
+#define SEG_CFS_Delete "UnassignedE_TEXT" // CFS_Shutdown // filest16
+#define SEG_ReleaseContext "UnassignedE_TEXT" // marshl
+#define SEG_CES_Commit "UnassignedE_TEXT" // Expst_Commit_TEXT // expst
+#define SEG_CED_DestroyElementA "UnassignedE_TEXT" // ascii
+#define SEG_CED_CopyTo "UnassignedE_TEXT" // expdf
+#define SEG_CFS_GetName "UnassignedE_TEXT" // filest
+
+#endif // CODESEGMENTS
+#endif // __SEGEXP_HXX__
diff --git a/private/ole32/stg/exp/storage.cxx b/private/ole32/stg/exp/storage.cxx
new file mode 100644
index 000000000..a34e3bedd
--- /dev/null
+++ b/private/ole32/stg/exp/storage.cxx
@@ -0,0 +1,611 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: storage.cxx
+//
+// Contents: Contains generic storage APIs
+//
+// History: 05-Oct-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <dfentry.hxx>
+#include <storagep.h>
+#include <logfile.hxx>
+#include <df32.hxx>
+#ifdef COORD
+#include <oledb.h>
+#endif //COORD
+
+#ifndef REF
+#ifndef FLAT
+#include <dos.h>
+#endif
+#endif //!REF
+#include <trace.hxx>
+
+#include <ole2sp.h>
+#include <ole2com.h>
+
+//+--------------------------------------------------------------
+//
+// Function: StgOpenStorage, public
+//
+// Synopsis: Instantiates a root storage from a file
+// by binding to the appropriate implementation
+// and starting things up
+//
+// Arguments: [pwcsName] - Name
+// [pstgPriority] - Priority mode reopen IStorage
+// [grfMode] - Permissions
+// [snbExclude] - Exclusions for priority reopen
+// [reserved]
+// [ppstgOpen] - Docfile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstgOpen]
+//
+// History: 05-Oct-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_StgOpenStorage)
+#endif
+STDAPI DfOpenDocfile(OLECHAR const *pwcsName,
+#ifdef COORD
+ ITransaction *pTransaction,
+#else
+ void *pTransaction,
+#endif
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+#if WIN32 == 300
+ LPSECURITY_ATTRIBUTES reserved,
+#else
+ LPSTGSECURITY reserved,
+#endif
+ IStorage **ppstgOpen)
+{
+#ifndef REF
+ CLSID cid;
+ HRESULT hr;
+ OLETRACEIN((API_StgOpenStorage,
+ PARAMFMT("pstgPriority= %p, grfMode= %x, snbExclude= %p, reserved= %p, ppStgOpen= %p"),
+ pstgPriority, grfMode,snbExclude, reserved, ppstgOpen));
+
+ hr = ResultFromScode(OpenStorage(pwcsName,
+ pTransaction,
+ pstgPriority, grfMode,
+ snbExclude, reserved, ppstgOpen, &cid));
+
+
+ OLETRACEOUT((API_StgOpenStorage, hr));
+
+ return hr;
+#else
+ return ResultFromScode(STG_E_UNIMPLEMENTEDFUNCTION);
+#endif //!REF
+}
+
+//On Cairo and later, StgOpenStorage is defined elsewhere and calls
+// through to DfOpenDocfile above.
+#if WIN32 < 300
+STDAPI StgOpenStorage(OLECHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ LPSTGSECURITY reserved,
+ IStorage **ppstgOpen)
+{
+ return DfOpenDocfile(pwcsName, NULL, pstgPriority, grfMode,
+ snbExclude, reserved, ppstgOpen);
+}
+#endif //WIN32 != 300
+
+
+//+--------------------------------------------------------------
+//
+// Function: StgOpenStorageOnILockBytes, public
+//
+// Synopsis: Instantiates a root storage from an ILockBytes
+// by binding to the appropriate implementation
+// and starting things up
+//
+// Arguments: [plkbyt] - Source ILockBytes
+// [pstgPriority] - For priority reopens
+// [grfMode] - Permissions
+// [snbExclude] - For priority reopens
+// [reserved]
+// [ppstgOpen] - Docfile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstgOpen]
+//
+// History: 05-Oct-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_StgOpenStorageOnILockBytes)
+#endif
+
+STDAPI StgOpenStorageOnILockBytes(ILockBytes *plkbyt,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstgOpen)
+{
+ CLSID cid;
+
+ OLETRACEIN((API_StgOpenStorageOnILockBytes,
+ PARAMFMT("pstgPriority= %p, grfMode= %x, snbExclude= %p, reserved= %ud, ppstgOpen= %p"),
+ pstgPriority, grfMode, snbExclude, reserved, ppstgOpen));
+
+ HRESULT hr;
+
+ hr = ResultFromScode(OpenStorageOnILockBytes(plkbyt, pstgPriority,
+ grfMode, snbExclude, reserved,
+ ppstgOpen, &cid));
+
+ OLETRACEOUT((API_StgOpenStorageOnILockBytes, hr));
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CheckSignature, private
+//
+// Synopsis: Checks the given memory against known signatures
+//
+// Arguments: [pb] - Pointer to memory to check
+//
+// Returns: S_OK - Current signature
+// S_FALSE - Beta 2 signature, but still successful
+// Appropriate status code
+//
+// History: 23-Jul-93 DrewB Created from header.cxx code
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CheckSignature)
+#endif
+
+#ifndef REF
+//Identifier for first bytes of Beta 1 Docfiles
+const BYTE SIGSTG_B1[] = {0xd0, 0xcf, 0x11, 0xe0, 0x0e, 0x11, 0xfc, 0x0d};
+const USHORT CBSIGSTG_B1 = sizeof(SIGSTG_B1);
+#endif //!REF
+
+//Identifier for first bytes of Beta 2 Docfiles
+const BYTE SIGSTG_B2[] = {0x0e, 0x11, 0xfc, 0x0d, 0xd0, 0xcf, 0x11, 0xe0};
+const BYTE CBSIGSTG_B2 = sizeof(SIGSTG_B2);
+
+SCODE CheckSignature(BYTE *pb)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CheckSignature(%p)\n", pb));
+
+ // Check for ship Docfile signature first
+ if (memcmp(pb, SIGSTG, CBSIGSTG) == 0)
+ sc = S_OK;
+
+ // Check for Beta 2 Docfile signature
+ else if (memcmp(pb, SIGSTG_B2, CBSIGSTG_B2) == 0)
+ sc = S_FALSE;
+
+#ifndef REF
+ // Check for Beta 1 Docfile signature
+ else if (memcmp(pb, SIGSTG_B1, CBSIGSTG_B1) == 0)
+ sc = STG_E_OLDFORMAT;
+#endif //!REF
+
+ else
+ sc = STG_E_INVALIDHEADER;
+
+ olDebugOut((DEB_ITRACE, "Out CheckSignature => %lX\n", sc));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: StgIsStorageFile, public
+//
+// Synopsis: Determines whether the named file is a storage or not
+//
+// Arguments: [pwcsName] - Filename
+//
+// Returns: S_OK, S_FALSE or error codes
+//
+// History: 05-Oct-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_StgIsStorageFile)
+#endif
+
+// The CAIRO version of this function must handle OFS
+// native storage. See stg\fsstg\api.cxx
+#if WIN32 < 300
+STDAPI StgIsStorageFile(OLECHAR const *pwcsName)
+{
+#ifndef REF
+#ifndef WIN32
+ HFILE hf;
+ UINT cbRead;
+ OFSTRUCT of;
+#else
+ HANDLE hf;
+ DWORD cbRead;
+#endif // !WIN32
+ SStorageFile stgfile;
+ SCODE sc;
+
+ olLog(("--------::In StgIsStorageFile(" OLEFMT ")\n", pwcsName));
+
+ TRY
+ {
+#ifndef OLEWIDECHAR
+ if (FAILED(sc = ValidateNameA(pwcsName, _MAX_PATH)))
+#else
+ if (FAILED(sc = ValidateNameW(pwcsName, _MAX_PATH)))
+#endif
+ return ResultFromScode(sc);
+
+#ifndef WIN32
+
+ hf = OpenFile(pwcsName, &of, OF_READ | OF_SHARE_DENY_NONE);
+ if (hf == HFILE_ERROR)
+ return ResultFromScode(STG_SCODE(of.nErrCode));
+
+ //Check to see if this name is a device - if it is, return
+ // STG_E_INVALIDNAME
+
+ int iRetval;
+ int fd = hf;
+ __asm
+ {
+ mov ax, 4400h
+ mov bx, fd
+ int 21h
+ mov iRetval, dx
+ }
+ if (iRetval & 0x80)
+ {
+ sc = STG_E_INVALIDNAME;
+ }
+ else
+ {
+ cbRead = _lread(hf, &stgfile, sizeof(stgfile));
+
+ if (cbRead == sizeof(stgfile) &&
+ SUCCEEDED(CheckSignature(stgfile.abSig)))
+ {
+ sc = S_OK;
+ }
+ else
+ {
+ sc = S_FALSE;
+ }
+ }
+ _lclose(hf);
+
+#else
+
+ // use WIN32 APIs
+
+#if !defined(UNICODE)
+
+ // Chicago - call ANSI CreateFile
+
+ char szName[_MAX_PATH + 1];
+
+ if (!WideCharToMultiByte(
+ AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0,
+ pwcsName,
+ -1,
+ szName,
+ _MAX_PATH + 1,
+ NULL,
+ NULL))
+ return ResultFromScode(STG_E_INVALIDNAME);
+
+ hf = CreateFileA (
+ szName,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+#else
+
+ hf = CreateFile (
+ pwcsName,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+#endif // !defined(UNICODE)
+
+ if (hf == INVALID_HANDLE_VALUE)
+ return ResultFromScode(STG_SCODE(GetLastError()));
+
+ if (ReadFile(hf, &stgfile, sizeof(stgfile), &cbRead, NULL) &&
+ SUCCEEDED(CheckSignature(stgfile.abSig)))
+ {
+ sc = S_OK;
+ }
+ else
+ {
+ sc = S_FALSE;
+ }
+ CloseHandle (hf);
+
+#endif // !WIN32
+
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+
+ olLog(("--------::Out StgIsStorageFile(). ret == %lx\n", sc));
+
+ return(ResultFromScode(sc));
+#else
+ return ResultFromScode(STG_E_UNIMPLEMENTEDFUNCTION);
+#endif //!REF
+}
+#endif // WIN32 == 300
+
+//+--------------------------------------------------------------
+//
+// Function: StgIsStorageILockBytes, public
+//
+// Synopsis: Determines whether the ILockBytes is a storage or not
+//
+// Arguments: [plkbyt] - The ILockBytes
+//
+// Returns: S_OK, S_FALSE or error codes
+//
+// History: 05-Oct-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_StgIsStorageILockBytes)
+#endif
+
+STDAPI StgIsStorageILockBytes(ILockBytes *plkbyt)
+{
+ OLETRACEIN((API_StgIsStorageILockBytes, PARAMFMT("plkbyt= %p"), plkbyt));
+
+ HRESULT hr;
+ SCODE sc;
+ SStorageFile stgfile;
+ ULONG cbRead;
+ ULARGE_INTEGER ulOffset;
+
+ TRY
+ {
+ if (FAILED(sc = ValidateInterface(plkbyt, IID_ILockBytes)))
+ {
+ hr = ResultFromScode(sc);
+ goto errRtn;
+ }
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_ILockBytes,(IUnknown **)&plkbyt);
+ ULISet32(ulOffset, 0);
+ hr = plkbyt->ReadAt(ulOffset, &stgfile, sizeof(stgfile), &cbRead);
+ if (FAILED(GetScode(hr)))
+ {
+ goto errRtn;
+ }
+ }
+ CATCH(CException, e)
+ {
+ hr = ResultFromScode(e.GetErrorCode());
+ goto errRtn;
+ }
+ END_CATCH
+
+ if (cbRead == sizeof(stgfile))
+ {
+ if ((memcmp((void *)stgfile.abSig, SIGSTG, CBSIGSTG) == 0) ||
+ (memcmp((void *)stgfile.abSig, SIGSTG_B2, CBSIGSTG_B2) == 0))
+ {
+ hr = ResultFromScode(S_OK);
+ goto errRtn;
+ }
+ }
+
+ hr = ResultFromScode(S_FALSE);
+
+errRtn:
+ OLETRACEOUT((API_StgIsStorageILockBytes, hr));
+
+ return hr;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: StgSetTimes
+//
+// Synopsis: Sets file time stamps
+//
+// Arguments: [lpszName] - Name
+// [pctime] - create time
+// [patime] - access time
+// [pmtime] - modify time
+//
+// Returns: Appropriate status code
+//
+// History: 05-Oct-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_StgSetTimes)
+#endif
+
+// This has a completely different implementation in Cairo
+#if WIN32 != 300
+STDAPI StgSetTimes(OLECHAR const *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+#ifndef REF
+#ifndef FLAT
+ SCODE sc;
+ WORD dosdate, dostime;
+ HFILE hf;
+ OFSTRUCT of;
+ WORD wErr;
+
+ TRY
+ {
+#ifndef OLEWIDECHAR
+ sc = ValidateNameA(lpszName, _MAX_PATH);
+#else
+ sc = ValidateNameW(lpszName, _MAX_PATH);
+#endif //OLEWIDECHAR
+ // Cast is necessary since the headers use const inconsistently
+ if (SUCCEEDED(sc) &&
+ !CoFileTimeToDosDateTime((FILETIME *)pmtime, &dosdate, &dostime))
+ sc = STG_E_UNKNOWN;
+#ifdef OLEWIDECHAR
+ char achName[_MAX_PATH];
+ if (SUCCEEDED(sc))
+ {
+ if (wcstombs(achName, lpszName, _MAX_PATH) == (size_t)-1)
+ sc = STG_E_INVALIDNAME;
+ }
+#endif //OLEWIDECHAR
+ if (SUCCEEDED(sc))
+ {
+#ifndef OLEWIDECHAR
+ hf = OpenFile(lpszName, &of, OF_WRITE | OF_SHARE_DENY_NONE);
+#else
+ hf = OpenFile(achName, &of, OF_WRITE | OF_SHARE_DENY_NONE);
+#endif //OLEWIDECHAR
+ if (hf == HFILE_ERROR)
+ sc = STG_SCODE(of.nErrCode);
+ else
+ {
+ //Check to see if this name is a device - if it is, return
+ // STG_E_INVALIDNAME
+
+ int iRetval;
+ int fd = hf;
+ __asm
+ {
+ mov ax, 4400h
+ mov bx, fd
+ int 21h
+ mov iRetval, dx
+ }
+ if (iRetval & 0x80)
+ {
+ sc = STG_E_INVALIDNAME;
+ }
+ else
+ {
+ wErr = _dos_setftime(hf, dosdate, dostime);
+ if (wErr != 0)
+ sc = STG_SCODE(wErr);
+ }
+ _lclose(hf);
+ }
+ }
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ return ResultFromScode(sc);
+
+#else //FLAT
+
+ SCODE sc;
+ HANDLE hFile;
+
+ TRY
+ {
+#ifndef OLEWIDECHAR
+ sc = ValidateNameA(lpszName, _MAX_PATH);
+#else
+ sc = ValidateNameW(lpszName, _MAX_PATH);
+#endif
+ if (SUCCEEDED(sc))
+ {
+#if !defined(UNICODE) && defined(OLEWIDECHAR)
+ //Chicago - call ANSI CreateFile
+ char szName[_MAX_PATH];
+
+ if (!WideCharToMultiByte(
+ AreFileApisANSI() ? CP_ACP : CP_OEMCP,
+ 0,
+ lpszName,
+ -1,
+ szName,
+ _MAX_PATH,
+ NULL,
+ NULL))
+ return ResultFromScode(STG_E_INVALIDNAME);
+ hFile = CreateFileA(szName, GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+#else
+ hFile = CreateFile(lpszName, GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ NULL);
+#endif
+ if (hFile == INVALID_HANDLE_VALUE)
+ sc = LAST_STG_SCODE;
+ else
+ {
+ if (!SetFileTime(hFile, (FILETIME *)pctime, (FILETIME *)patime,
+ (FILETIME *)pmtime))
+ sc = LAST_STG_SCODE;
+ CloseHandle(hFile);
+ }
+ }
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ return ResultFromScode(sc);
+#endif
+#else
+ return ResultFromScode(STG_E_UNIMPLEMENTEDFUNCTION);
+#endif //!REF
+}
+#endif // !Cairo
+
diff --git a/private/ole32/stg/exp/time16.cxx b/private/ole32/stg/exp/time16.cxx
new file mode 100644
index 000000000..faa212e78
--- /dev/null
+++ b/private/ole32/stg/exp/time16.cxx
@@ -0,0 +1,58 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: Time16.CXX
+//
+// Contents: Time conversion routines (16-bit only)
+//
+// Functions: DfGetTOD
+//
+// History: 13-Nov-92 AlexT Created
+//
+// Notes: These functions come from NT - time.c
+//
+//--------------------------------------------------------------------------
+#include <exphead.cxx>
+#pragma hdrstop
+
+#include <time16.hxx>
+#include <dos.h>
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_DfGetTOD)
+#endif
+
+SCODE DfGetTOD(TIME_T *pft)
+{
+#ifndef REF
+ SCODE sc;
+ WORD packedtime, packeddate;
+ struct _dosdate_t dosdate;
+ struct _dostime_t dostime;
+
+ _dos_gettime(&dostime);
+ packedtime = (dostime.second/2) | (dostime.minute<<5) | (dostime.hour<<11);
+ _dos_getdate(&dosdate);
+ packeddate = dosdate.day | (dosdate.month<<5) | ((dosdate.year-1980)<<9);
+
+ BOOL b = CoDosDateTimeToFileTime(packeddate, packedtime, pft);
+
+ if (b)
+ {
+ sc = S_OK;
+ }
+ else
+ {
+ olAssert(!aMsg("Unable to convert time"));
+ sc = E_UNEXPECTED;
+ }
+
+ return(sc);
+#else
+ //REFBUG: A time of day function needs to be provided for any port of this
+ // code.
+ return S_OK;
+#endif //!REF
+}
diff --git a/private/ole32/stg/exp/time16.hxx b/private/ole32/stg/exp/time16.hxx
new file mode 100644
index 000000000..49f3c89ee
--- /dev/null
+++ b/private/ole32/stg/exp/time16.hxx
@@ -0,0 +1,21 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: time16.hxx
+//
+// Contents: DocFile Time support (16-bit only)
+//
+// History: 13-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __TIME16_HXX__
+#define __TIME16_HXX__
+
+#include <time.h>
+
+BOOL tmToFileTime(struct tm *ptm, FILETIME *pft);
+
+#endif
diff --git a/private/ole32/stg/exp/time32.cxx b/private/ole32/stg/exp/time32.cxx
new file mode 100644
index 000000000..42e2c784a
--- /dev/null
+++ b/private/ole32/stg/exp/time32.cxx
@@ -0,0 +1,40 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: Time32.CXX, 32-bit only
+//
+// Contents: time routine
+//
+// Functions: DfGetTOD
+//
+// History: 13-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+#include <exphead.cxx>
+#pragma hdrstop
+
+SCODE DfGetTOD(TIME_T *pft)
+{
+ SCODE sc;
+
+ SYSTEMTIME SystemTime;
+
+ GetSystemTime(&SystemTime);
+
+ olAssert(sizeof(TIME_T) == sizeof(FILETIME));
+ BOOL b = SystemTimeToFileTime(&SystemTime, pft);
+
+ if (b)
+ {
+ sc = S_OK;
+ }
+ else
+ {
+ olAssert(!aMsg("Unable to convert time"));
+ sc = E_FAIL;
+ }
+
+ return(sc);
+}
diff --git a/private/ole32/stg/fsstg/accstg.cxx b/private/ole32/stg/fsstg/accstg.cxx
new file mode 100644
index 000000000..b47d8e578
--- /dev/null
+++ b/private/ole32/stg/fsstg/accstg.cxx
@@ -0,0 +1,1051 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995.
+//
+// File: accstg.cxx
+//
+// Contents: IAccessControl for files implementation
+//
+// History: 00-Mar-95 DaveMont Created
+// 25-May-95 HenryLee Modified
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <aclapi.h>
+#include <accstg.hxx>
+#include <ctype.h>
+
+#define AccAlloc(x) LocalAlloc(LMEM_FIXED, x)
+#ifndef AccFree
+#define AccFree(x) LocalFree(x)
+#endif
+//+-------------------------------------------------------------------
+//
+// Member: CAccessControl::~CAccessControl
+//
+// Synopsis: Delete the object and set the deletion signature.
+//
+//--------------------------------------------------------------------
+
+CAccessControl::~CAccessControl()
+{
+ if (m_grfMode & STGM_EDIT_ACCESS_RIGHTS)
+ {
+ if ((m_grfMode & STGM_TRANSACTED) == 0) // directmode only
+ CommitAccessRights(0);
+ if (m_pdacl)
+ AccFree(m_pdacl);
+ if (m_pdaclCommitted)
+ AccFree(m_pdaclCommitted);
+
+ CAccessControl *pAC = m_pACChild;
+ while (pAC != NULL)
+ {
+ CAccessControl *pACNext = pAC->m_pACNext;
+ pAC->m_pACParent = NULL; // mark parent as dead
+ pAC->Release(); // release the child
+ pAC = pACNext; // next child
+
+ }
+ if (m_pACParent != NULL) // if parent is still alive
+ m_pACParent->RemoveChild (this); // remove from parent's list
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CAccessControl::InitAccessControl
+//
+// Synopsis: Initialize the generic access control object.
+//
+// Arguments: [handle] File system handle
+// [grfMode] Specifies transacted or direct mode
+// [fGetDacl] Reads the DACL into memory
+// [pACParent] parent for nested transactions
+//
+// Notes: The passed handle is saved to manipulate security
+// descriptors.
+//
+//--------------------------------------------------------------------
+
+HRESULT CAccessControl::InitAccessControl (HANDLE handle,
+ DWORD grfMode,
+ BOOL fGetDacl,
+ CAccessControl *pACParent)
+{
+ SCODE sc = S_OK;
+
+ m_handle = handle;
+ m_pdacl = NULL;
+ m_grfMode = grfMode & (~DF_REVERTED); // clear reverted bit
+
+ if (m_grfMode & STGM_EDIT_ACCESS_RIGHTS)
+ {
+ if ((pACParent != NULL) && (m_grfMode & STGM_TRANSACTED))
+ {
+ pACParent->InsertChild(this);
+ AddRef(); // hold on to child for nested commits
+ // released in parent's destructor
+ }
+ sc = InitializeCAcl (fGetDacl);
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAccessControl::GrantAccessRights, public
+//
+// Synopsis: grants the access requests to the current state of
+// access control for the object. The access control
+// will only be saved on the object if it is committed.
+//
+// Arguments: [cCount] - number of access requests in list
+// [pAccessRequestList] - list of access requests
+//
+// Returns: Appropriate status code
+//
+// Modifies: none
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CAccessControl::GrantAccessRights(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[])
+{
+ ssDebugOut((DEB_TRACE, "In CAccessControl::GrantAccessRights(%d, %x)\n",
+ cCount, pAccessRequestList));
+
+ SCODE sc = ApplyAccessRights(GRANT_ACCESS,
+ cCount,
+ pAccessRequestList,
+ &m_pdacl,
+ FALSE);
+
+ ssDebugOut((DEB_TRACE, "Out CAccessControl::GrantAccessRights => (%d)\n",
+ sc));
+
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAccessControl::SetAccessRights, public
+//
+// Synopsis: sets the access requests to the current state of
+// access control for the object. The access control
+// will only be saved on the object if it is committed.
+//
+// Arguments: [cCount] - number of access requests in list
+// [pAccessRequestList] - list of access requests
+//
+// Returns: Appropriate status code
+//
+// Modifies: none
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CAccessControl::SetAccessRights(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[])
+{
+ ssDebugOut((DEB_TRACE, "In CAccessControl::SetAccessRights(%d, %x)\n",
+ cCount, pAccessRequestList));
+
+ SCODE sc = ApplyAccessRights(SET_ACCESS,
+ cCount,
+ pAccessRequestList,
+ &m_pdacl,
+ FALSE);
+
+ ssDebugOut((DEB_TRACE, "Out CAccessControl::SetAccessRights => (%d)\n",
+ sc));
+
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAccessControl::ReplaceAllAccessRights, public
+//
+// Synopsis: replaces all the access requests on the current state of
+// access control for the object. The access control
+// will only be saved on the object if it is committed.
+//
+// Arguments: [cCount] - number of access requests in list
+// [pAccessRequestList] - list of access requests
+//
+// Returns: Appropriate status code
+//
+// Modifies: none
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CAccessControl::ReplaceAllAccessRights(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[])
+{
+ ssDebugOut((DEB_TRACE,"In CAccessControl::ReplaceAllAccessRights(%d, %x)\n",
+ cCount, pAccessRequestList));
+
+ SCODE sc = ApplyAccessRights(SET_ACCESS,
+ cCount,
+ pAccessRequestList,
+ &m_pdacl,
+ TRUE);
+
+ ssDebugOut((DEB_TRACE,"Out CAccessControl::ReplaceAllAccessRights =>(%d)\n",
+ sc));
+
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAccessControl::DenyAccessRights, public
+//
+// Synopsis: denies the access requests on the current state of
+// access control for the object. The access control
+// will only be saved on the object if it is committed.
+//
+// Arguments: [cCount] - number of access requests in list
+// [pAccessRequestList] - list of access requests
+//
+// Returns: Appropriate status code
+//
+// Modifies: none
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CAccessControl::DenyAccessRights(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[])
+{
+ ssDebugOut((DEB_TRACE, "In CAccessControl::DenyAccessRights(%d, %x)\n",
+ cCount, pAccessRequestList));
+
+ SCODE sc = ApplyAccessRights(DENY_ACCESS,
+ cCount,
+ pAccessRequestList,
+ &m_pdacl,
+ FALSE);
+
+ ssDebugOut((DEB_TRACE,"Out CAccessControl::DenyAccessRights => (%d)\n",
+ sc));
+
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAccessControl::RevokeExplicitAccessRights, public
+//
+// Synopsis: revokes access control for the trustees from the current
+// state of access control for the object. The access control
+// will only be saved on the object if it is committed.
+//
+// Arguments: [cCount] - number of trustees in list
+// [Trustee] - list of trustees
+//
+// Returns: Appropriate status code
+//
+// Modifies: none
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CAccessControl::RevokeExplicitAccessRights(ULONG cCount,
+ TRUSTEE Trustee[])
+{
+ ACCESS_REQUEST *par;
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CAccessControl::RevokeExplicitAccessRights"
+ "(%d, %x)\n", cCount, Trustee));
+
+ if ((par = (ACCESS_REQUEST *)AccAlloc(cCount * sizeof(ACCESS_REQUEST))))
+ {
+ for (ULONG idx = 0; idx < cCount; idx++)
+ {
+ par[idx].grfAccessPermissions = 0;
+ par[idx].Trustee = Trustee[idx];
+ // Trustee name pointer is copied here
+ }
+ sc = ApplyAccessRights(REVOKE_ACCESS,
+ cCount,
+ par,
+ &m_pdacl,
+ FALSE);
+
+ AccFree(par);
+ }
+ else
+ sc = STG_E_INSUFFICIENTMEMORY;
+
+ ssDebugOut((DEB_TRACE,"Out CAccessControl::RevokeExplicitAccessRights => "
+ "(%d)\n", sc));
+
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAccessControl::IsAccessPermitted, public
+//
+// Synopsis: determines if the trustee has the requested access permissions
+// on the object
+//
+// Arguments: [Trustee] - Trustee name
+// [grfAccessPermissions] - the requested permissions
+//
+// Returns: Appropriate status code
+// S_OK == Access permitted, S_FALSE == Access denied
+//
+// Modifies:
+//
+// Notes: does not check access given by privileges
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CAccessControl::IsAccessPermitted(TRUSTEE *pTrustee,
+ DWORD grfAccessPermissions)
+
+{
+ SCODE sc = S_OK;
+ DWORD dwPermitted;
+
+ ssDebugOut((DEB_TRACE, "In CAccessControl::IsAccessPermitted"
+ "(%d, %x)\n", grfAccessPermissions, pTrustee));
+
+ if (m_grfMode & DF_REVERTED)
+ sc = STG_E_REVERTED;
+
+ if (pTrustee == NULL || pTrustee->ptstrName == NULL)
+ {
+ sc = STG_E_INVALIDPARAMETER;
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ if (S_OK == (sc = GetEffectiveAccessRights(pTrustee,&dwPermitted)))
+ {
+ if (grfAccessPermissions == (grfAccessPermissions & dwPermitted))
+ sc = S_OK;
+ else
+ sc = S_FALSE;
+ }
+ }
+ ssDebugOut((DEB_TRACE,"Out CAccessControl::IsAccessPermitted => "
+ "(%d)\n", sc));
+
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAccessControl::GetEffectiveAccessRights, public
+//
+// Synopsis: returns the effective access rights for the specified trustee
+// on the object
+//
+// Arguments: [Trustee] - Trustee name
+// [pgrfAccessPermissions] - effective access rights returned
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pgrfAccessPermissions]
+//
+// Notes: does not check access given by privileges
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CAccessControl::GetEffectiveAccessRights(TRUSTEE *pTrustee,
+ DWORD *pgrfAccessPermissions)
+{
+ SCODE sc = S_OK;
+
+ ssDebugOut((DEB_TRACE, "In CAccessControl::GetEffectiveAccessRights"
+ "(%x, %x)\n", pgrfAccessPermissions, pTrustee));
+
+ if (m_grfMode & DF_REVERTED)
+ sc = STG_E_REVERTED;
+
+ if (pTrustee == NULL || pTrustee->ptstrName == NULL)
+ {
+ sc = STG_E_INVALIDPARAMETER;
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ if (S_OK == (sc = InitializeCAcl(TRUE)))
+ {
+ //
+ // lookup group ownerships
+ //
+ DWORD accessmask;
+ DWORD winerror;
+
+ if (NO_ERROR == (winerror = GetEffectiveRightsFromAcl(m_pdacl,
+ pTrustee,
+ &accessmask)))
+ {
+ *pgrfAccessPermissions = NTAccessMaskToProvAccessRights(
+ SE_FILE_OBJECT,
+ FALSE, //bugbug, iscontainer
+ accessmask);
+ } else
+ {
+ sc = WIN32_SCODE(winerror);
+ }
+ }
+ }
+ ssDebugOut((DEB_TRACE,"Out CAccessControl::GetEffectiveAccessRights => "
+ "(%d)\n", sc));
+
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAccessControl::GetExplicitAccessRights, public
+//
+// Synopsis: retrieves the DACL information
+//
+// Arguments: [pcCount] - number of ExplicitAccess entries
+// [pExplicitAccessList] - list of Trustees and their perms
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcCount, pExplicitAccessList]
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CAccessControl::GetExplicitAccessRights(ULONG *pcCount,
+ PEXPLICIT_ACCESS *pExplicitAccessList)
+{
+ SCODE sc = S_OK;
+
+ ssDebugOut((DEB_TRACE, "In CAccessControl::GetExplicitAccessRights"
+ "(%x, %x)\n", pcCount, pExplicitAccessList));
+
+ if (m_grfMode & DF_REVERTED)
+ sc = STG_E_REVERTED;
+
+ if (SUCCEEDED(sc))
+ {
+ if (S_OK == (sc = InitializeCAcl(TRUE)))
+ {
+ EXPLICIT_ACCESS *pExplicitAccess;
+ DWORD winerror;
+
+ if (NO_ERROR == (winerror = GetExplicitEntriesFromAcl(m_pdacl,
+ pcCount,
+ &pExplicitAccess)))
+ {
+ sc = Win32ExplicitAccessToExplicitAccess(*pcCount,
+ pExplicitAccess,
+ pExplicitAccessList);
+ AccFree(pExplicitAccess);
+ } else
+ {
+ sc = WIN32_SCODE(winerror);
+ }
+ }
+
+ }
+ ssDebugOut((DEB_TRACE,"Out CAccessControl::GetExplicitAccessRights => "
+ "(%d)\n", sc));
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAccessControl::Commit, public
+//
+// Synopsis: Writes access control changes to disk
+//
+// Arguments: [grfCommitFlags] - future commit flags
+//
+// Returns: Appropriate status code
+//
+// Modifies: []
+//
+// Notes: In transacted mode, save the committed state for nested transactions
+// In direct mode, save to disk by calling CommitFromAbove
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CAccessControl::CommitAccessRights(DWORD grfCommitFlags)
+{
+ SCODE sc = S_OK;
+ if (grfCommitFlags != 0)
+ ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+ if (m_grfMode & DF_REVERTED)
+ ssErr (EH_Err, STG_E_REVERTED);
+
+ if ((m_grfMode & STGM_TRANSACTED) && m_pdacl != NULL)
+ {
+ // save the last commited state
+ if (m_pdaclCommitted != NULL)
+ AccFree (m_pdaclCommitted);
+ if ((m_pdaclCommitted = (ACL *) AccAlloc (m_pdacl->AclSize)) == 0)
+ ssErr (EH_Err, E_OUTOFMEMORY);
+ memcpy (m_pdaclCommitted, m_pdacl, m_pdacl->AclSize);
+ }
+
+ if (m_pACParent != NULL) // save only if at root level
+ ssErr (EH_Err, S_OK); // for non-root, get out
+
+ ssChk(CommitFromAbove()); // root level commit, walk the tree
+
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CAccessControl::RevertAccessRights, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies: []
+//
+// Notes: Files only support the contents stream
+//
+//----------------------------------------------------------------------------
+STDMETHODIMP CAccessControl::RevertAccessRights()
+{
+ SCODE sc = S_OK;
+ if ((m_grfMode & STGM_TRANSACTED))
+ {
+ if (m_pdacl)
+ {
+ AccFree(m_pdacl);
+ m_pdacl = NULL;
+ m_isdirty = FALSE;
+ }
+ if (m_pdaclCommitted)
+ {
+ m_pdacl = m_pdaclCommitted; // transfer the last committed state
+ m_pdaclCommitted = NULL; // to the current state
+ }
+ }
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: AccessRequestToExplicitAccess, private
+//
+// Synopsis: converts a list of access requests into access entries
+//
+// Arguments: IN [ObjectType] - the type of the object (eg.file,printer,etc.)
+// IN [AccessMode] - the mode to apply access rights
+// IN [cCountOfAccessRequests] - count of the access requests
+// IN [pListOfAccessRequests] - the list of acccess requests
+// OUT [pListOfExplicitAccess] - the list of acccess entries
+//
+// Returns: Appropriate status code
+//
+// Modifies: []
+//
+// Notes: Files only support the contents stream
+//
+//----------------------------------------------------------------------------
+HRESULT CAccessControl::AccessRequestToExplicitAccess(
+ IN ACCESS_MODE AccessMode,
+ IN FILEDIR fd,
+ IN ACCESS_REQUEST *pListOfAccessRequests,
+ IN ULONG cCountOfAccessRequests,
+ OUT PEXPLICIT_ACCESS *pListOfExplicitAccess)
+{
+ SCODE status = ERROR_SUCCESS;
+
+ //
+ // if no requests, no entries
+ //
+ if (cCountOfAccessRequests > 0)
+ {
+ //
+ // allocate space for the access entries (passed to SetEntriesInAcl)
+ // note that we could just modify the mask in each entry, but then we
+ // would be modifying one of the callers in parameters.
+ //
+ if (NULL != (*pListOfExplicitAccess = (PEXPLICIT_ACCESS)
+ AccAlloc(cCountOfAccessRequests * sizeof(EXPLICIT_ACCESS))))
+ {
+ for (ULONG idx = 0; idx < cCountOfAccessRequests; idx++)
+ {
+ //
+ // set the access mode (same for all entries in this case
+ // set the inheritance
+ //
+ (*pListOfExplicitAccess)[idx].grfAccessMode = AccessMode;
+ if (fd == FD_DIR)
+ {
+ //
+ // bugbug, perhaps it might be better to make two aces
+ // (as the security editor does, since files and directories
+ // use different access masks)
+ //
+ (*pListOfExplicitAccess)[idx].grfInheritance =
+ OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
+ } else
+ {
+ //
+ // no inheritance for files (and docfiles, etc.)
+ //
+ (*pListOfExplicitAccess)[idx].grfInheritance = NO_INHERITANCE;
+ }
+ //
+ // copy the trustee
+ //
+ (*pListOfExplicitAccess)[idx].Trustee =
+ pListOfAccessRequests[idx].Trustee;
+ //
+ // if impersonating, don't convert the mask as it may be
+ // object specific (in which case the object must make sure
+ // that the filesystem does not attempt to access check against
+ // it) To be specific, a server may want to define its own object
+ // specific permissions. In which case it puts an ACE at the front
+ // of the ACL that gives the server exclusive access to the file.
+ // The remaining ACEs are impersonate ACEs. When the server gets
+ // a client call on the object, the server opens the object. Then
+ // it impersonates and calls accesscheck on the object, using its
+ // own object specific permissions.
+ //
+ if (GetMultipleTrusteeOperation(&((*pListOfExplicitAccess)[idx].
+ Trustee)) == TRUSTEE_IS_IMPERSONATE)
+ {
+ //
+ // we don't copy the multiple trustee pointed to by the
+ // trustee
+ //
+ (*pListOfExplicitAccess)[idx].grfAccessPermissions =
+ pListOfAccessRequests[idx].grfAccessPermissions;
+ } else if (AccessMode != REVOKE_ACCESS)
+ {
+ //
+ // as long as not revoking access, make sure the input
+ // access mask is valid by checking the conversion
+ // to an NT mask for zero
+ //
+ if (0 == ((*pListOfExplicitAccess)[idx].grfAccessPermissions =
+ ProvAccessRightsToNTAccessMask(SE_FILE_OBJECT,
+ pListOfAccessRequests[idx].grfAccessPermissions)))
+ {
+ status = E_INVALIDARG;
+ AccFree(*pListOfExplicitAccess);
+ break;
+ }
+ //
+ // always add read_control and synchronize for allows since
+ // they overlap for all access requests.
+ //
+ if (AccessMode != DENY_ACCESS)
+ {
+ ((*pListOfExplicitAccess)[idx].grfAccessPermissions) |=
+ (READ_CONTROL | SYNCHRONIZE);
+ }
+ }
+ }
+ } else
+ {
+ status = STG_E_INSUFFICIENTMEMORY;
+ }
+ }
+ else
+ {
+ status = STG_E_INVALIDPARAMETER;
+ }
+
+ return(status);
+}
+//+---------------------------------------------------------------------------
+//
+// Function: Win32ExplicitAccessToExplicitAccess, private
+//
+// Synopsis: converts a list of win32 explicit accesses into explicit accesses
+//
+// Arguments: IN [cCountOfExplicitAccess] - count of the access requests
+// IN [pListOfExplicitAccess] - the list of access requests
+// OUT [pListOfExplicitAccess] - the returned list of explicit access
+//
+// Returns: Appropriate status code
+//
+// Modifies: []
+//
+// Notes: Files only support the contents stream
+//
+//----------------------------------------------------------------------------
+HRESULT CAccessControl::Win32ExplicitAccessToExplicitAccess(
+ IN ULONG cCountOfExplicitAccess,
+ IN PEXPLICIT_ACCESS pListOfWin32ExplicitAccess,
+ OUT PEXPLICIT_ACCESS *pListOfExplicitAccesses)
+{
+ SCODE status = S_OK;
+
+ if (cCountOfExplicitAccess > 0)
+ {
+ //
+ // allocate space for the returned explicit accesses
+ //
+ if (NULL != (*pListOfExplicitAccesses = (EXPLICIT_ACCESS *)
+ CoTaskMemAlloc(cCountOfExplicitAccess * sizeof(EXPLICIT_ACCESS))))
+ {
+ for (ULONG idx = 0; idx < cCountOfExplicitAccess; idx++)
+ {
+ PEXPLICIT_ACCESS pea = &(*pListOfExplicitAccesses)[idx];
+ PEXPLICIT_ACCESS pWin32ea = &pListOfWin32ExplicitAccess[idx];
+
+ pea->grfAccessMode = pWin32ea->grfAccessMode;
+ pea->grfInheritance = pWin32ea->grfInheritance;
+ pea->Trustee = pWin32ea->Trustee;
+ //
+ // if it is an impersonate access request don't convert the mask
+ //
+ if (TRUSTEE_IS_IMPERSONATE == GetMultipleTrusteeOperation(&(pea->Trustee)))
+ {
+ pea->grfAccessPermissions = pWin32ea->grfAccessPermissions;
+ //
+ // allocate and fill the multiple trustee, fortunately this
+ // is only used for impersonate ACEs
+ //
+ if (NULL != (pea->Trustee.pMultipleTrustee = (PTRUSTEE)CoTaskMemAlloc(
+ sizeof(TRUSTEE))))
+ {
+ //
+ // copy the impersonate trustee
+ //
+ *(pea->Trustee.pMultipleTrustee) =
+ *(pWin32ea->Trustee.pMultipleTrustee);
+ //
+ // allocate space for the impersonate trustee name
+ //
+ if (pea->Trustee.pMultipleTrustee->ptstrName = (WCHAR *)
+ CoTaskMemAlloc((lstrlenW(pWin32ea->Trustee.pMultipleTrustee->ptstrName)+1)
+ *sizeof(WCHAR)))
+ {
+ //
+ // copy the name
+ //
+ lstrcpyW (pea->Trustee.pMultipleTrustee->ptstrName,
+ pWin32ea->Trustee.pMultipleTrustee->ptstrName);
+ } else
+ {
+ status = STG_E_INSUFFICIENTMEMORY;
+ //
+ // cleanup allocations
+ //
+ FreeStgExplicitAccessList(idx, *pListOfExplicitAccesses);
+ break;
+ }
+ } else
+ {
+ status = STG_E_INSUFFICIENTMEMORY;
+ //
+ // cleanup allocations
+ //
+ FreeStgExplicitAccessList(idx, *pListOfExplicitAccesses);
+ break;
+ }
+ } else
+ {
+ pea->grfAccessPermissions =
+ NTAccessMaskToProvAccessRights(SE_FILE_OBJECT,
+ FALSE, //bugbug iscontainer
+ pWin32ea->grfAccessPermissions);
+ }
+ if (pea->Trustee.ptstrName = (WCHAR *)
+ CoTaskMemAlloc((lstrlenW(pWin32ea->Trustee.ptstrName)+1)
+ *sizeof(WCHAR)))
+ {
+ lstrcpyW (pea->Trustee.ptstrName,
+ pWin32ea->Trustee.ptstrName);
+ } else
+ {
+ status = STG_E_INSUFFICIENTMEMORY;
+ //
+ // cleanup allocations
+ //
+ FreeStgExplicitAccessList(idx, *pListOfExplicitAccesses);
+ break;
+ }
+ }
+ } else
+ {
+ status = STG_E_INSUFFICIENTMEMORY;
+ }
+ }
+
+ return(status);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: InitializeCAcl, private
+//
+// Synopsis:
+//
+// Arguments: [fGetDacl] - controls whether DACL is read in
+//
+// Returns: Appropriate status code
+//
+// Modifies: []
+//
+// Notes: DACL is read only when pdacl is NULL
+//
+//----------------------------------------------------------------------------
+HRESULT CAccessControl::InitializeCAcl(BOOL fGetDacl)
+{
+ SCODE sc = S_OK;
+
+
+ PSECURITY_DESCRIPTOR psd;
+ PACL pdacl;
+
+ if (m_pdacl == NULL && fGetDacl)
+ {
+ DWORD dwStatus;
+ if (S_OK == (dwStatus = GetSecurityInfo(m_handle,
+ SE_FILE_OBJECT,
+ DACL_SECURITY_INFORMATION,
+ NULL,
+ NULL,
+ &pdacl,
+ NULL,
+ &psd)))
+ {
+ if (NULL != (m_pdacl = (PACL) LocalAlloc(LMEM_FIXED, pdacl->AclSize)))
+ {
+ RtlCopyMemory(m_pdacl, pdacl, pdacl->AclSize);
+ } else
+ {
+ sc = E_OUTOFMEMORY;
+ }
+ AccFree(psd);
+ } else
+ {
+ sc = WIN32_SCODE(dwStatus);
+ }
+ }
+
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ApplyAccessRights, private
+//
+// Synopsis:
+//
+// Arguments: [eAccessMode] - grant/deny/set/revoke/replaceall
+// [cCount] - number of access requests
+// [pAccessRequestList] - list of requests
+// [pca] - the output CAcl class
+// [pdacl] - the output ACL
+// [fReplaceAll] - deletes old ACL before REPLACE_ALL_ACCESS
+//
+// Returns: Appropriate status code
+//
+// Modifies: []
+//
+//----------------------------------------------------------------------------
+HRESULT CAccessControl::ApplyAccessRights(ACCESS_MODE eAccessMode,
+ ULONG cCount,
+ ACCESS_REQUEST *pAccessRequestList,
+ PACL *pdacl,
+ BOOL fReplaceAll)
+
+{
+ SCODE status;
+ EXPLICIT_ACCESS *pea;
+ const BOOL bParanoid = FALSE;
+ //
+ // initialize the class and get the ACL if this is the first time
+ // When replacing all, there's no need to read the DACL
+ //
+ if (m_grfMode & DF_REVERTED)
+ return STG_E_REVERTED;
+
+ //
+ // if not replacing all, get the DACL
+ //
+ if (S_OK == (status = InitializeCAcl(!fReplaceAll)))
+ {
+ //
+ // convert the access request into something the
+ // acl management code understands
+ //
+ if (S_OK == (status = AccessRequestToExplicitAccess(eAccessMode,
+ FD_FILE,
+ pAccessRequestList,
+ cCount,
+ &pea)))
+ {
+ //
+ // if all the access entries are being replaced, delete
+ // the acl
+ //
+ if (fReplaceAll)
+ {
+ AccFree(*pdacl);
+ *pdacl = NULL;
+ }
+ ACL *pNewAcl;
+ DWORD winerror;
+ //
+ // set the access rights into the dacl
+ //
+ if (NO_ERROR == (winerror = SetEntriesInAcl(cCount, pea, *pdacl, &pNewAcl)))
+ {
+ //
+ // free the old dacl, make the new one the current one
+ //
+ if (*pdacl != NULL)
+ AccFree(*pdacl);
+ *pdacl = pNewAcl;
+ m_isdirty = TRUE;
+ if (bParanoid && // save every operation to disk
+ ((m_grfMode & STGM_TRANSACTED) == 0)) // directmode
+ {
+ status = CommitAccessRights(0);
+ }
+ } else
+ {
+ status = WIN32_SCODE(winerror);
+ }
+ AccFree(pea);
+ }
+ }
+ return(status);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CommitFromAbove, private
+//
+// Synopsis:
+//
+// Arguments: [none] -
+//
+// Returns: Appropriate status code
+//
+// Notes: In direct mode, commit the ACL to disk
+// In transacted mode, commit the children and write the
+// "last committed" version to disk.
+//
+//----------------------------------------------------------------------------
+HRESULT CAccessControl::CommitFromAbove ()
+{
+ SCODE sc = S_OK;
+
+ // we have a nested transaction parent, commit the children
+ for (CAccessControl *pAC = m_pACChild; pAC; pAC = pAC->m_pACNext)
+ {
+ ssChk(pAC->CommitFromAbove());
+ }
+
+ if (m_grfMode & STGM_TRANSACTED) // save the last committed ACL
+ {
+ DWORD winerror;
+
+ if (NO_ERROR == (winerror = SetSecurityInfo(m_handle,
+ SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
+ NULL, NULL, m_pdaclCommitted, NULL)))
+ {
+ if (m_pdaclCommitted)
+ {
+ AccFree (m_pdaclCommitted);
+ m_pdaclCommitted = NULL;
+ }
+ } else
+ {
+ sc = WIN32_SCODE(winerror);
+ }
+ }
+ else // direct mode, save current state
+ {
+ if (m_isdirty)
+ {
+ DWORD winerror;
+
+ if (NO_ERROR == (winerror = SetSecurityInfo(m_handle,
+ SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
+ NULL, NULL, m_pdacl, NULL)))
+ {
+ //if (m_pdacl)
+ //{
+ // AccFree(m_pdacl);
+ // m_pdacl = NULL;
+ //}
+ m_isdirty = FALSE;
+ } else
+ {
+ sc = WIN32_SCODE(winerror);
+ }
+ }
+
+ }
+EH_Err:
+ return ssResult(sc);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CAccessControl::InsertChild
+//
+// Synopsis: insert into child list for nested transactions
+//
+// Arguments: [pACChild] child object
+//
+// Notes: does not detect duplicates
+//
+//+-------------------------------------------------------------------
+HRESULT CAccessControl::InsertChild (CAccessControl *pACChild)
+{
+ ssAssert (pACChild != NULL);
+ // BUGBUG lock this
+ pACChild->m_pACNext = m_pACChild;
+ pACChild->m_pACParent = this;
+ m_pACChild = pACChild;
+ // BUGBUG unlock this
+
+ return ssResult(S_OK);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CAccessControl::RemoveChild
+//
+// Synopsis: removes a child list from nested transactions
+//
+// Arguments: [pACChild] child object
+//
+// Notes: does not remove/detect duplicates
+//
+//+-------------------------------------------------------------------
+HRESULT CAccessControl::RemoveChild (CAccessControl *pACChild)
+{
+ SCODE sc = S_OK;
+ ssAssert (pACChild != NULL);
+ if (m_pACChild == pACChild) // remove from front of list
+ {
+ // BUGBUG lock this
+ m_pACChild = pACChild->m_pACNext;
+ pACChild->m_pACNext = NULL;
+ // BUGBUG unlock this
+ }
+ else
+ {
+ for (CAccessControl *pAC = m_pACChild; pAC; pAC = pAC->m_pACNext)
+ {
+ if (pAC->m_pACNext == pACChild)
+ {
+ // BUGBUG lock pAC
+ pAC->m_pACNext = pACChild->m_pACNext;
+ pACChild->m_pACNext = NULL;
+ // BUGBUG unlock pAC
+ break;
+ }
+ }
+ }
+ return ssResult(S_OK);
+}
diff --git a/private/ole32/stg/fsstg/api.cxx b/private/ole32/stg/fsstg/api.cxx
new file mode 100644
index 000000000..2616341ac
--- /dev/null
+++ b/private/ole32/stg/fsstg/api.cxx
@@ -0,0 +1,835 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: api.cxx
+//
+// Contents: API entry points
+//
+// History: 30-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <storagep.h>
+#include <filstm.hxx>
+#include <stgutil.hxx>
+#include <dfentry.hxx>
+
+#include <ole2sp.h>
+#include <ole2com.h>
+
+#if DBG == 1
+DECLARE_INFOLEVEL(ss);
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: CoMemAlloc, public
+//
+// Synopsis: BUGBUG - Stub function
+//
+// History: 23-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI CoMemAlloc(DWORD cbSize, void **ppv)
+{
+ HRESULT hr;
+
+ *ppv = CoTaskMemAlloc ( cbSize );
+ if ( *ppv == NULL )
+ hr = E_OUTOFMEMORY;
+ else
+ hr = S_OK;
+
+ return hr;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgCreateStorage, public
+// StgCreateDocfile, public
+//
+// Synopsis: Creates a storage for the given path
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Mode
+// [dwStgFmt] - Type
+// [pssSecurity] - Security
+// [ppstg] - Storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 14-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI StgCreateDocfile (
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage **ppstg )
+{
+ return StgCreateStorage ( pwcsName, grfMode, STGFMT_DOCUMENT, NULL, ppstg );
+}
+
+STDAPI StgCreateStorage(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD dwStgFmt,
+ LPSECURITY_ATTRIBUTES pssSecurity,
+ IStorage **ppstg)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In StgCreateStorage(%ws, %lX, %lu, %p, %p)\n",
+ pwcsName, grfMode, dwStgFmt, pssSecurity, ppstg));
+
+ // pssSecurity occupies what was previously a DWORD reserved
+ // argument, so make sure things haven't grown and thrown off
+ // the stack frame
+ ssAssert(sizeof(LPSTGSECURITY) == sizeof(DWORD));
+
+ ssChk(VerifyStgFmt(dwStgFmt));
+
+ if (pwcsName == NULL)
+ {
+ WCHAR awcTmpPath[_MAX_PATH], awcPath[_MAX_PATH];
+ BOOL fWinDir = FALSE;
+
+ // Temporary directories are not supported
+ if (dwStgFmt == STGFMT_DIRECTORY)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+
+ if (GetTempPath(_MAX_PATH, awcTmpPath) == 0)
+ {
+ if (GetWindowsDirectory(awcTmpPath, _MAX_PATH) == 0)
+ ssErr(EH_Err, LAST_STG_SCODE);
+ fWinDir = TRUE;
+ }
+ if (GetTempFileName(awcTmpPath, TSTR("~DFT"), 0, awcPath) == 0)
+ {
+ if (fWinDir)
+ {
+ ssErr(EH_Err, LAST_STG_SCODE);
+ }
+ if (GetWindowsDirectory(awcTmpPath, _MAX_PATH) == 0)
+ ssErr(EH_Err, LAST_STG_SCODE);
+ if (GetTempFileName(awcTmpPath, TSTR("DFT"), 0, awcPath) == 0)
+ ssErr(EH_Err, LAST_STG_SCODE);
+ }
+ return StgCreateStorage(awcPath, grfMode | STGM_CREATE, dwStgFmt,
+ pssSecurity, ppstg);
+ }
+
+ sc = RefersToOfsVolume(pwcsName, CO_CREATE);
+ if (sc == S_OK)
+ {
+#ifdef TRANSACT_OLE
+ if (grfMode & STGM_TRANSACTED)
+ grfMode &= ~STGM_TRANSACTED;
+#endif
+ sc = OfsCreateStorageType(NULL, pwcsName, NULL, grfMode, dwStgFmt,
+ pssSecurity, TRUE, ppstg);
+ }
+ else if (sc == S_FALSE)
+ sc = CreateStorageType(NULL, pwcsName, NULL, grfMode, dwStgFmt,
+ pssSecurity, ppstg);
+
+ ssDebugOut((DEB_TRACE, "Out StgCreateStorage => %p, %lX\n",
+ *ppstg, sc));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgOpenStorage, public
+//
+// Synopsis: Opens a storage
+//
+// Arguments: [pwcsName] - Name
+// [pstgPriority] - Priority mode prior open
+// [grfMode] - Mode
+// [snbExclude] - Exclusions
+// [reserved]
+// [ppstg] - Storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 14-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI StgOpenStorage(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In StgOpenStorage(%ws, %p, %lX, %p, %p, %p)\n",
+ pwcsName, pstgPriority, grfMode, snbExclude, reserved,
+ ppstg));
+ CALLHOOKOBJECT(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)&pstgPriority);
+
+ if (grfMode & (STGM_CREATE | STGM_CONVERT | STGM_DELETEONRELEASE))
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+ if (pwcsName == NULL)
+ ssErr(EH_Err, STG_E_INVALIDNAME);
+ if (reserved != 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+
+ sc = CheckFsAndOpenAnyStorage(NULL, pwcsName, pstgPriority, grfMode,
+ snbExclude, TRUE, ppstg);
+ CALLHOOKOBJECTCREATE(ssResult(sc),CLSID_NULL,IID_IStream,
+ (IUnknown **)ppstg);
+
+ ssDebugOut((DEB_TRACE, "Out StgOpenStorage => %p\n", *ppstg));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgCreateStorageOnHandle, public
+//
+// Synopsis: Creates a storage on the given handle
+//
+// Arguments: [h] - Handle
+// [grfMode] - Mode of handle
+// [dwStgFmt] - Desired storage type
+// [ppstg] - Storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 20-Oct-93 DrewB Created
+//
+// Notes: This function does any work necessary to establish a freshly
+// created handle as a storage of the appropriate type
+// It must check to see that the handle type is correct for
+// the storage type and then do any appropriate storage-specific
+// initialization.
+//
+//----------------------------------------------------------------------------
+
+SCODE StgCreateStorageOnHandle(HANDLE h,
+ DWORD grfMode,
+ DWORD dwStgFmt,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ STATSTG stat;
+ FILEDIR fd;
+ HANDLE hDup = NULL;
+ NTSTATUS nts;
+
+ ssDebugOut((DEB_ITRACE, "In StgCreateStorageOnHandle(%p, %lX, %lu, %p)\n",
+ h, grfMode, dwStgFmt, ppstg));
+
+ if (grfMode & (STGM_CREATE | STGM_CONVERT | STGM_DELETEONRELEASE |
+ STGM_PRIORITY))
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+
+ // BUGBUG - Can't identify summary catalogs or OFS compound files
+#ifdef TRANSACT_OLE
+ if (grfMode & STGM_TRANSACTED) // BUGBUG remove when supported
+ grfMode &= ~STGM_TRANSACTED;
+#endif
+
+ ssChk(DupNtHandle(h, &hDup));
+ ssChk(StatNtHandle(hDup, STATFLAG_NONAME, 0, &stat, NULL, NULL, &fd));
+ ssChk(HandleRefersToOfsVolume(hDup));
+
+ // BUGBUG: [mikese] This is all screwed up. StatNtHandle does not do the
+ // right detection for OFS. I have disabled these tests because they
+ // are no good and because in any case the only caller is replication
+ // which gets it right!
+#if 0
+ switch(dwStgFmt)
+ {
+ case STGFMT_DOCUMENT:
+ // BUGBUG - OFS document must have a handle type of compound file?
+ if (fd != FD_STORAGE)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+ break;
+
+ case STGFMT_CATALOG:
+ // ?
+ break;
+
+ case STGFMT_FILE:
+ if (fd != FD_FILE)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+ break;
+
+ case STGFMT_DIRECTORY:
+ if (fd != FD_DIR)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+ break;
+ }
+#endif
+
+ if (sc == S_OK)
+ {
+ sc = OfsCreateStorageType(NULL, NULL, hDup, grfMode, dwStgFmt,
+ NULL, TRUE, ppstg);
+ }
+ else if (sc == S_FALSE)
+ {
+ sc = CreateStorageType(NULL, NULL, &hDup, grfMode, dwStgFmt,
+ NULL, ppstg);
+ }
+ CALLHOOKOBJECTCREATE(ssResult(sc),CLSID_NULL,IID_IStorage,
+ (IUnknown **)ppstg);
+
+ ssDebugOut((DEB_ITRACE, "Out StgCreateStorageOnHandle => %lX, %p\n",
+ sc, *ppstg));
+ EH_Err:
+ // If the create is successful, the storage object owns the handle
+ // If not successful, then we clean up and close the handle
+ if (hDup != NULL && !SUCCEEDED(sc))
+ if (!NT_SUCCESS(nts = NtClose(hDup)))
+ ssDebugOut((DEB_ITRACE,
+ "StgCreateStorageOnHandle NtClose(%lx)\n", nts));
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgOpenStorageOnHandle, public
+//
+// Synopsis: Starts an IStorage on a handle
+//
+// Arguments: [h] - Handle
+// [grfMode] - Handle permissions
+// [ppstg] - Storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 15-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI StgOpenStorageOnHandle(HANDLE h,
+ DWORD grfMode,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ STATSTG stat;
+ FILEDIR fd;
+ DWORD dwStgFmt;
+ HANDLE hDup = NULL;
+ NTSTATUS nts;
+
+ ssDebugOut((DEB_TRACE, "In StgStorageFromHandle(%p, %lX, %p)\n",
+ h, grfMode, ppstg));
+
+ if (grfMode & (STGM_CREATE | STGM_CONVERT | STGM_DELETEONRELEASE |
+ STGM_PRIORITY))
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+
+ // BUGBUG - Can't identify summary catalogs
+#ifdef TRANSACT_OLE
+ if (grfMode & STGM_TRANSACTED) // BUGBUG remove when supported
+ grfMode &= ~STGM_TRANSACTED;
+#endif
+
+ ssChk(DupNtHandle(h, &hDup));
+ ssChk(StatNtHandle(hDup, STATFLAG_NONAME, 0, &stat, NULL, NULL, &fd));
+ ssChk(DetermineHandleStgType(hDup, fd, &dwStgFmt));
+ sc = HandleRefersToOfsVolume(hDup);
+ if (sc == S_OK)
+ {
+ sc = OfsOpenAnyStorage(NULL, NULL, &hDup, dwStgFmt, NULL, grfMode,
+ NULL, TRUE, ppstg);
+ }
+ else if (sc == S_FALSE)
+ {
+ sc = OpenAnyStorage(NULL, NULL, &hDup, dwStgFmt, NULL, grfMode,
+ NULL, ppstg);
+
+ if (SUCCEEDED(sc) && dwStgFmt == STGFMT_DOCUMENT)
+ hDup = NULL; // already closed by docfile
+ }
+ ssDebugOut((DEB_TRACE, "Out StgStorageFromHandle => %lX, %p\n",
+ sc, *ppstg));
+ EH_Err:
+ // If the open is successful, the storage object owns the handle
+ // If not successful, then we clean up and close the handle
+ if (hDup != NULL && !SUCCEEDED(sc))
+ if (!NT_SUCCESS(nts = NtClose(hDup)))
+ ssDebugOut((DEB_ITRACE,
+ "StgOpenStorageOnHandle NtClose(%lx)\n", nts));
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgIsStorage, public
+//
+// Synopsis: Determines storage type of object
+//
+// Arguments: [pwcsName] - Name
+// [pdwStgFmt] - Storage type return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pdwStgFmt]
+//
+// History: 15-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI StgIsStorage(WCHAR const *pwcsName,
+ DWORD *pdwStgFmt)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In StgIsStorage(%ws, %p)\n",
+ pwcsName, pdwStgFmt));
+
+ sc = DetermineStgType(NULL, pwcsName, STGM_READ, pdwStgFmt, NULL);
+
+ ssDebugOut((DEB_TRACE, "Out StgIsStorage => %lX, %lu\n", sc, *pdwStgFmt));
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgIsStorageFile, public
+//
+// Synopsis: Determines if the named object is detectably a Docfile or
+// OFS structured file
+//
+// Arguments: [pwcsName] - Name
+//
+// Returns: S_OK if the name points to an OFS structured file
+// S_OK if the name points to a DocFile
+// S_FALSE if the name points to a single stream file that is not a docfile
+// other SC based upon return codes.
+//
+// Modifies: [pdwStgFmt]
+//
+// History: 15-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI StgIsStorageFile (WCHAR const *pwcsName)
+{
+ SCODE sc;
+ DWORD StorageFormat;
+ ssDebugOut((DEB_TRACE, "In StgIsStorageFile(%ws)\n",
+ pwcsName));
+
+ sc = StgIsStorage (pwcsName, &StorageFormat);
+ if (sc == S_OK)
+ {
+ sc = StorageFormat == STGFMT_DOCUMENT ? S_OK : S_FALSE;
+ }
+
+ ssDebugOut((DEB_TRACE, "Out StgIsStorageFile => %lX\n", sc));
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Function: StgSetTimes
+//
+// Synopsis: Sets storage time stamps
+//
+// Arguments: [pwcsName] - Name
+// [pctime] - create time
+// [patime] - access time
+// [pmtime] - modify time
+//
+// Returns: Appropriate status code
+//
+// History: 22-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDAPI StgSetTimes(WCHAR const *pwcsName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ SCODE sc;
+ SafeNtHandle h;
+
+ ssDebugOut((DEB_TRACE, "In StgSetTimes(%ws, %p, %p, %p)\n",
+ pwcsName, pctime, patime, pmtime));
+
+ ssChk(GetFileOrDirHandle(NULL, pwcsName, STGM_WRITE, &h, NULL,NULL,NULL));
+ sc = SetTimes(h, pctime, patime, pmtime);
+
+ ssDebugOut((DEB_TRACE, "Out StgSetTimes => %lX\n", sc));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DfIsDocfile, public
+//
+// Synopsis: Determines whether a file is a docfile or not
+//
+// Arguments: [h] - Handle of file
+//
+// Returns: Appropriate status code
+//
+// History: 12-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI DfIsDocfile(HANDLE h)
+{
+ IO_STATUS_BLOCK iosb;
+ BYTE bSig[CBSIGSTG];
+ NTSTATUS nts;
+ LARGE_INTEGER liZero;
+ SCODE sc;
+
+ liZero.HighPart = liZero.LowPart = 0;
+ if (!NT_SUCCESS(nts = NtReadFile(h, NULL, NULL, NULL, &iosb, bSig,
+ CBSIGSTG, &liZero, NULL)))
+ {
+ if (nts == STATUS_END_OF_FILE)
+ return ssResult(S_FALSE);
+ else if (nts == STATUS_INVALID_DEVICE_REQUEST)
+ return ssResult(S_FALSE);
+ else
+ return ssResult(NtStatusToScode(nts));
+ }
+ if (iosb.Information != CBSIGSTG)
+ return ssResult(S_FALSE);
+
+ sc = CheckSignature(bSig);
+ if (SUCCEEDED(sc))
+ {
+ // Fold all success codes into S_OK
+ sc = S_OK;
+ }
+ else if (sc == STG_E_INVALIDHEADER)
+ {
+ // First eight bytes aren't a signature we recognize,
+ // so it's not a docfile and not an error
+ sc = S_FALSE;
+ }
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgCreateStorageEx, public
+//
+// Synopsis: Creates an IDirectory or IStorage
+//
+// Arguments: [pwcsName] - pathname of file
+// [pStgCreate] - creation information
+// [pStgOpen] - mode, format
+// [riid] - GUID of interface pointer to return
+// [ppObjectOpen] - interface pointer to return
+//
+// Returns: Appropriate status code
+//
+// History: 12-Jul-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI TempStgCreateStorageEx (const WCHAR* pwcsName,
+ STGCREATE * pStgCreate,
+ STGOPEN * pStgOpen,
+ REFIID riid,
+ BOOL fRestricted,
+ void ** ppObjectOpen)
+{
+ SCODE sc = S_OK;
+ SCODE scOfs = STG_E_INVALIDFLAG; // true, false, invalid
+ ssDebugOut((DEB_TRACE, "In StgCreateStorageEx(%ws, %p, %p, %p, %p)\n",
+ pwcsName, pStgCreate, pStgOpen, riid, ppObjectOpen));
+
+ if (pStgCreate == NULL || pStgOpen == NULL || ppObjectOpen == NULL)
+ ssErr (EH_Err, STG_E_INVALIDPOINTER);
+ if (pwcsName)
+ ssChk (ValidateNameW (pwcsName, _MAX_PATH));
+
+
+ *ppObjectOpen = NULL;
+
+ if (pStgOpen->stgfmt==STGFMT_STORAGE ||
+ pStgOpen->stgfmt==STGFMT_DOCUMENT ||
+ pStgOpen->stgfmt==STGFMT_DOCFILE ||
+ pStgOpen->stgfmt==STGFMT_CATALOG )
+ {
+ sc = InitStorage (NULL, pwcsName, NULL,
+ CO_CREATE, pStgOpen, pStgCreate,
+ NULL, &scOfs, fRestricted, riid, ppObjectOpen);
+ }
+ else if (pStgOpen->stgfmt==STGFMT_DIRECTORY ||
+ pStgOpen->stgfmt==STGFMT_JUNCTION)
+ {
+ ssChk(InitDirectory (NULL, pwcsName, NULL,
+ CO_CREATE, pStgOpen, pStgCreate,
+ scOfs, riid, ppObjectOpen));
+ }
+ else if (pStgOpen->stgfmt==STGFMT_FILE)
+ {
+ CNtFileStream *pfs = new CNtFileStream();
+ ssMem((CNtFileStream *)pfs);
+
+ ssChk(pfs->InitFromPath (NULL, pwcsName, pStgOpen->grfMode,
+ pStgCreate->grfAttrs, CO_CREATE, NULL));
+ sc = pfs->QueryInterface(riid, ppObjectOpen);
+ // success case, undo QI AddRef
+ pfs->Release(); // failure case, destroy obj
+ }
+ else ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+EH_Err:
+ ssDebugOut((DEB_TRACE, "Out StgCreateStorageEx => %lX\n", sc));
+ CALLHOOKOBJECTCREATE(ssResult(sc),CLSID_NULL,riid,
+ (IUnknown **)&ppObjectOpen);
+ return ssResult(sc);
+}
+
+STDAPI StgCreateStorageEx (const WCHAR *pwcsName,
+ STGCREATE * pStgCreate,
+ STGOPEN * pStgOpen,
+ REFIID riid,
+ void ** ppObjectOpen)
+{
+ return TempStgCreateStorageEx (pwcsName, pStgCreate, pStgOpen, riid,
+ FALSE, ppObjectOpen);
+}
+
+STDAPI DsysStgCreateStorageEx (const WCHAR *pwcsName,
+ STGCREATE * pStgCreate,
+ STGOPEN * pStgOpen,
+ REFIID riid,
+ void ** ppObjectOpen)
+{
+ return TempStgCreateStorageEx (pwcsName, pStgCreate, pStgOpen, riid,
+ TRUE, ppObjectOpen);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgOpenStorageEx
+//
+// Synopsis: Open storages/directories as IDirectory or IStorage
+//
+// Arguments: [pwcsName] - pathanme of the file
+// [pStgCreate] - creation information
+// [pStgOpen] - mode, format
+// [riid] - GUID of interface pointer to return
+// [ppObjectOpen] - interface pointer to return
+// Returns: Appropriate status code
+//
+// History: 12-Jul-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+STDAPI TempStgOpenStorageEx (const WCHAR *pwcsName,
+ STGOPEN * pStgOpen,
+ REFIID riid,
+ STGFMT * pStgfmt,
+ BOOL fRestricted,
+ void ** ppObjectOpen)
+{
+ SCODE sc = S_OK;
+ DWORD dwStgfmt;
+ SCODE scOfs = STG_E_INVALIDFLAG;
+ HANDLE h = NULL;
+ ssDebugOut((DEB_TRACE, "In StgOpenStorageEx(%ws, %p, %p, %p, %p)\n",
+ pwcsName, pStgOpen, riid, pStgfmt, ppObjectOpen));
+
+ if (pwcsName == NULL)
+ ssErr(EH_Err, STG_E_INVALIDPOINTER) // macro has a '}' no ';' needed
+ else
+ ssChk (ValidateNameW (pwcsName, _MAX_PATH));
+ if (pStgOpen == NULL || ppObjectOpen == NULL)
+ ssErr (EH_Err, STG_E_INVALIDPOINTER);
+
+ *ppObjectOpen = NULL;
+ dwStgfmt = pStgOpen->stgfmt;
+
+ if (dwStgfmt==STGFMT_ANY)
+ {
+ HANDLE h;
+#ifdef TRANSACT_OLE
+ const DWORD grfMode2 = (fRestricted ? pStgOpen->grfMode :
+ pStgOpen->grfMode & ~STGM_TRANSACTED);
+#else
+ const DWORD grfMode2 = pStgOpen->grfMode;
+#endif
+ ssChk(DetermineStgType(NULL,pwcsName,grfMode2,&dwStgfmt,&h));
+ scOfs = HandleRefersToOfsVolume(h);
+ if (scOfs == S_OK && dwStgfmt==STGFMT_DOCUMENT && S_OK==DfIsDocfile(h))
+ dwStgfmt = STGFMT_DOCFILE;
+ if (h != NULL)
+ NTSTATUS nts = NtClose (h);
+ pStgOpen->stgfmt = (STGFMT) dwStgfmt;// BUGBUG changing input parameter
+ }
+
+ if (dwStgfmt == STGFMT_STORAGE ||
+ dwStgfmt == STGFMT_DOCUMENT ||
+ dwStgfmt == STGFMT_DOCFILE ||
+ dwStgfmt == STGFMT_CATALOG )
+ {
+ // Priority mode not supported, snbExclude not supported
+ STGFMT stgfmtTemp = (STGFMT) dwStgfmt;
+ sc = InitStorage (NULL, pwcsName, NULL,
+ CO_OPEN, pStgOpen, NULL,
+ NULL, &scOfs, fRestricted, riid, ppObjectOpen);
+
+ if (pStgfmt != NULL)
+ *pStgfmt = stgfmtTemp;
+ }
+ else if (dwStgfmt==STGFMT_DIRECTORY || dwStgfmt==STGFMT_JUNCTION)
+ {
+ ssChk(InitDirectory (NULL, pwcsName, NULL,
+ CO_OPEN, pStgOpen, NULL,
+ scOfs, riid, ppObjectOpen));
+ if (pStgfmt != NULL) *pStgfmt = (STGFMT) dwStgfmt;
+ }
+ else if (dwStgfmt==STGFMT_FILE)
+ {
+ CNtFileStream *pfs = new CNtFileStream();
+ ssMem((CNtFileStream *)pfs);
+
+ ssChk(pfs->InitFromPath(NULL, pwcsName, pStgOpen->grfMode,
+ 0, CO_OPEN,NULL));
+ if (SUCCEEDED(sc = pfs->QueryInterface(riid, ppObjectOpen)))
+ {
+ if (pStgfmt != NULL)
+ *pStgfmt = STGFMT_FILE;
+ } // success case, undo QI AddRef
+ pfs->Release(); // failure case, destroy obj
+ }
+ else ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+EH_Err:
+ ssDebugOut((DEB_TRACE, "Out StgOpenStorageEx => %lX\n", sc));
+ CALLHOOKOBJECTCREATE(ssResult(sc),CLSID_NULL,riid,
+ (IUnknown **)&ppObjectOpen);
+ return ssResult(sc);
+}
+
+STDAPI StgOpenStorageEx (const WCHAR *pwcsName,
+ STGOPEN * pStgOpen,
+ REFIID riid,
+ STGFMT * pStgfmt,
+ void ** ppObjectOpen)
+{
+ return TempStgOpenStorageEx (pwcsName, pStgOpen, riid, pStgfmt,
+ FALSE, ppObjectOpen);
+
+}
+
+STDAPI DsysStgOpenStorageEx (const WCHAR *pwcsName,
+ STGOPEN * pStgOpen,
+ REFIID riid,
+ STGFMT * pStgfmt,
+ void ** ppObjectOpen)
+{
+ return TempStgOpenStorageEx (pwcsName, pStgOpen, riid, pStgfmt,
+ TRUE, ppObjectOpen);
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StgGetClassFile
+//
+// Synopsis: retrieves a classid from a storage or directory
+//
+// Arguments: [hParent] = handle of parent object
+// [pwcsName] - pathanme of the file
+// [pclsid] - output class id
+// [hFile] - output file handle
+// Returns: Appropriate status code
+//
+// History: 12-Jul-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+STDAPI StgGetClassFile (HANDLE hParent,
+ const WCHAR *pwcsName,
+ LPCLSID pclsid,
+ HANDLE *hFile)
+{
+ SCODE sc = S_OK;
+ FILEDIR fd;
+ HANDLE h = NULL;
+ BOOL fOfs = TRUE;
+
+ ssDebugOut((DEB_ITRACE, "In StgGetClassFile (%lX, %ws, %lX)\n",
+ hParent, pwcsName, pclsid));
+ ssAssert (pclsid != NULL);
+ *pclsid = CLSID_NULL;
+ *hFile = INVALID_HANDLE_VALUE;
+
+ ssChk(GetFileOrDirHandle(hParent, pwcsName,
+ STGM_READ | STGM_DIRECT, &h, pclsid, &fOfs, &fd));
+ if (!fOfs)
+ {
+ if ((fd == FD_STORAGE) || (fd == FD_FILE && S_OK==DfIsDocfile(h)))
+ {
+ ssChk(DfGetClass(h, pclsid));
+ }
+ else if (fd == FD_DIR)
+ {
+ HANDLE hHidden = NULL;
+ IO_STATUS_BLOCK iosb;
+ if (SUCCEEDED( GetNtHandle (h, CLSID_FILENAME,
+ STGM_READ, 0, CO_OPEN, FD_FILE, NULL, &hHidden)))
+ {
+ NTSTATUS nts = NtReadFile (hHidden, NULL, NULL, NULL, &iosb,
+ (void *)pclsid, sizeof(*pclsid), NULL, NULL);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode (nts);
+ if (hHidden != NULL)
+ nts = NtClose(hHidden);
+ if (iosb.Information < sizeof(*pclsid))
+ sc = STG_E_READFAULT;
+ }
+ // if we can't open the classid file for a dir, assume CLSID_NULL
+ // we return S_OK, skip the pattern, and try extension matching
+ // this is compatible behavior with OFS directories
+ }
+ }
+ else
+ {
+ if (fd == FD_FILE) // support downlevel docfiles on OFS
+ {
+ if (S_OK==DfIsDocfile(h))
+ {
+ ssChk(DfGetClass(h, pclsid));
+ }
+ else // BUGBUG OFS returns a default classid
+ *pclsid = CLSID_NULL; // for files, should be CLSID_NULL
+ }
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out StgGetClassFile => %lX\n", sc));
+EH_Err:
+ if (h != NULL) // for the FD_FILE case,
+ { // GetClassFileEx will close handle
+ if (fd == FD_FILE)
+ *hFile = h; // handle for CoGetClassPattern
+ else
+ NtClose(h);
+ }
+
+ return ssResult(sc);
+}
diff --git a/private/ole32/stg/fsstg/daytona/makefile b/private/ole32/stg/fsstg/daytona/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ole32/stg/fsstg/daytona/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/stg/fsstg/daytona/sources b/private/ole32/stg/fsstg/daytona/sources
new file mode 100644
index 000000000..be78ad3d2
--- /dev/null
+++ b/private/ole32/stg/fsstg/daytona/sources
@@ -0,0 +1,58 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+
+!include ..\..\..\daytona.inc
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= fsstg
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+INCLUDES= ..\..\h;..\..\..\ih;..
+
+SOURCES= ..\ntsupp.cxx
+
+UMTYPE= console
+
+PRECOMPILED_INCLUDE= ..\headers.cxx
+
diff --git a/private/ole32/stg/fsstg/depend.mk b/private/ole32/stg/fsstg/depend.mk
new file mode 100644
index 000000000..06b54be7e
--- /dev/null
+++ b/private/ole32/stg/fsstg/depend.mk
@@ -0,0 +1,741 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\dirstg.obj $(OBJDIR)\dirstg.lst: .\dirstg.cxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ntenm.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\stgutil.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\eprstg.h $(COMMONINC)\epsstg.h \
+ $(COMMONINC)\estatd.h $(COMMONINC)\estats.h $(COMMONINC)\estrng.h \
+ $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h \
+ $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h \
+ $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h $(COMMONINC)\prstg.h \
+ $(COMMONINC)\psstg.h $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h \
+ $(COMMONINC)\rot.h $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h \
+ $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h $(COMMONINC)\stream.h \
+ $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h $(COMMONINC)\varnt.h \
+ $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\limits.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\devioctl.h $(OSINC)\dlgs.h \
+ $(OSINC)\lint.hxx $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h \
+ $(OSINC)\mipsinst.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h \
+ $(OSINC)\ntalpha.h $(OSINC)\ntconfig.h $(OSINC)\ntdef.h \
+ $(OSINC)\ntelfapi.h $(OSINC)\ntexapi.h $(OSINC)\nti386.h \
+ $(OSINC)\ntimage.h $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h \
+ $(OSINC)\ntkeapi.h $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h \
+ $(OSINC)\ntmips.h $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h \
+ $(OSINC)\ntobapi.h $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h \
+ $(OSINC)\ntrtl.h $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h \
+ $(OSINC)\nturtl.h $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\dirstg.hxx .\dsenm.hxx \
+ .\filstg.hxx .\headers.cxx
+
+$(OBJDIR)\api.obj $(OBJDIR)\api.lst: .\api.cxx $(CAIROLE)\stg\h\filstm.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ntsupp.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ptrcache.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\stgutil.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\basetyps.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\stream.h $(COMMONINC)\varnt.h $(COMMONINC)\wtypes.h \
+ $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h $(COMMONINC)\basetyps.h \
+ $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h $(COMMONINC)\cobjerr.h \
+ $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h $(COMMONINC)\disptype.h \
+ $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h $(COMMONINC)\emonkr.h \
+ $(COMMONINC)\estatd.h $(COMMONINC)\estats.h $(COMMONINC)\estrng.h \
+ $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h \
+ $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h \
+ $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h $(COMMONINC)\pstrm.h \
+ $(COMMONINC)\querys.h $(COMMONINC)\rot.h $(COMMONINC)\scode.h \
+ $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h \
+ $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h \
+ $(COMMONINC)\varnt.h $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h \
+ $(CRTINC)\limits.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OSINC)\lintfunc.hxx \
+ $(OSINC)\ntrtl.h $(OSINC)\rpc.h $(OSINC)\cderr.h $(OSINC)\commdlg.h \
+ $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\devioctl.h $(OSINC)\dlgs.h \
+ $(OSINC)\lint.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntseapi.h \
+ $(OSINC)\ntstatus.h $(OSINC)\nturtl.h $(OSINC)\ntxcapi.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\filstg.hxx \
+ .\headers.cxx .\dirstg.hxx
+
+$(OBJDIR)\dsenm.obj $(OBJDIR)\dsenm.lst: .\dsenm.cxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ntenm.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\types.h $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\basetyps.h $(COMMONINC)\wtypes.h \
+ $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h $(COMMONINC)\basetyps.h \
+ $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h $(COMMONINC)\cobjerr.h \
+ $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h $(COMMONINC)\disptype.h \
+ $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h $(COMMONINC)\emonkr.h \
+ $(COMMONINC)\estatd.h $(COMMONINC)\estats.h $(COMMONINC)\estrng.h \
+ $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h \
+ $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h \
+ $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h $(COMMONINC)\pstrm.h \
+ $(COMMONINC)\querys.h $(COMMONINC)\rot.h $(COMMONINC)\scode.h \
+ $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h \
+ $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h \
+ $(COMMONINC)\varnt.h $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\limits.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\filstg.hxx .\headers.cxx .\dirstg.hxx \
+ .\dsenm.hxx
+
+$(OBJDIR)\filstg.obj $(OBJDIR)\filstg.lst: .\filstg.cxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\filstm.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\stgutil.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\basetyps.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\estats.h $(COMMONINC)\prspec.h $(COMMONINC)\stream.h \
+ $(COMMONINC)\wtypes.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\eprstg.h $(COMMONINC)\epsstg.h \
+ $(COMMONINC)\estatd.h $(COMMONINC)\estats.h $(COMMONINC)\estrng.h \
+ $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h \
+ $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h \
+ $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h $(COMMONINC)\prstg.h \
+ $(COMMONINC)\psstg.h $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h \
+ $(COMMONINC)\rot.h $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h \
+ $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h $(COMMONINC)\stream.h \
+ $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h $(COMMONINC)\varnt.h \
+ $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h $(CRTINC)\excpt.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\limits.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OSINC)\rpc.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\filstg.hxx .\fsenm.hxx .\headers.cxx \
+ .\dirstg.hxx
+
+$(OBJDIR)\fsenm.obj $(OBJDIR)\fsenm.lst: .\fsenm.cxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ntsupp.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ptrcache.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\stgstm.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h $(COMMONINC)\estats.h \
+ $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h \
+ $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h \
+ $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h $(COMMONINC)\rot.h \
+ $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h \
+ $(COMMONINC)\storag.h $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h \
+ $(COMMONINC)\valid.h $(COMMONINC)\varnt.h $(COMMONINC)\winole.h \
+ $(COMMONINC)\wtypes.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\limits.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\filstg.hxx .\headers.cxx .\dirstg.hxx \
+ .\fsenm.hxx
+
+$(OBJDIR)\filstm.obj $(OBJDIR)\filstm.lst: .\filstm.cxx \
+ $(CAIROLE)\stg\h\filstm.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h $(COMMONINC)\estats.h \
+ $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h \
+ $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h \
+ $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h $(COMMONINC)\rot.h \
+ $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h \
+ $(COMMONINC)\storag.h $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h \
+ $(COMMONINC)\valid.h $(COMMONINC)\varnt.h $(COMMONINC)\winole.h \
+ $(COMMONINC)\wtypes.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\limits.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\filstg.hxx .\headers.cxx .\dirstg.hxx
+
+$(OBJDIR)\ntsupp.obj $(OBJDIR)\ntsupp.lst: .\ntsupp.cxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ntsupp.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ptrcache.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\stgstm.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\iofs.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\iofsprop.h $(COMMONINC)\prspec.h $(COMMONINC)\rot.h \
+ $(COMMONINC)\stream.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h $(COMMONINC)\estats.h \
+ $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h \
+ $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h \
+ $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h $(COMMONINC)\rot.h \
+ $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h \
+ $(COMMONINC)\storag.h $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h \
+ $(COMMONINC)\valid.h $(COMMONINC)\varnt.h $(COMMONINC)\winole.h \
+ $(COMMONINC)\wtypes.h $(CRTINC)\excpt.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\limits.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OSINC)\rpc.h $(OSINC)\winerror.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\filstg.hxx .\headers.cxx .\dirstg.hxx
+
+$(OBJDIR)\ntlkb.obj $(OBJDIR)\ntlkb.lst: .\ntlkb.cxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\ntlkb.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ntsupp.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ptrcache.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h $(COMMONINC)\estats.h \
+ $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h \
+ $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h \
+ $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h $(COMMONINC)\rot.h \
+ $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h \
+ $(COMMONINC)\storag.h $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h \
+ $(COMMONINC)\valid.h $(COMMONINC)\varnt.h $(COMMONINC)\winole.h \
+ $(COMMONINC)\wtypes.h $(CRTINC)\limits.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OSINC)\lintfunc.hxx $(OSINC)\ntrtl.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h $(OSINC)\ntconfig.h \
+ $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h $(OSINC)\ntexapi.h \
+ $(OSINC)\nti386.h $(OSINC)\ntimage.h $(OSINC)\ntioapi.h \
+ $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h $(OSINC)\ntldr.h \
+ $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h $(OSINC)\ntmmapi.h \
+ $(OSINC)\ntnls.h $(OSINC)\ntobapi.h $(OSINC)\ntpsapi.h \
+ $(OSINC)\ntregapi.h $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h \
+ $(OSINC)\nturtl.h $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\filstg.hxx .\headers.cxx \
+ .\dirstg.hxx
+
+$(OBJDIR)\ntenm.obj $(OBJDIR)\ntenm.lst: .\ntenm.cxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\ntenm.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h $(COMMONINC)\estats.h \
+ $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h \
+ $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h \
+ $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h $(COMMONINC)\rot.h \
+ $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h \
+ $(COMMONINC)\storag.h $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h \
+ $(COMMONINC)\valid.h $(COMMONINC)\varnt.h $(COMMONINC)\winole.h \
+ $(COMMONINC)\wtypes.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\limits.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\filstg.hxx .\headers.cxx .\dirstg.hxx
+
+$(OBJDIR)\stgsupp.obj $(OBJDIR)\stgsupp.lst: .\stgsupp.cxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ntlkb.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\stgutil.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h $(COMMONINC)\estats.h \
+ $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h \
+ $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h \
+ $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h $(COMMONINC)\rot.h \
+ $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h \
+ $(COMMONINC)\storag.h $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h \
+ $(COMMONINC)\valid.h $(COMMONINC)\varnt.h $(COMMONINC)\winole.h \
+ $(COMMONINC)\wtypes.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\limits.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\filstg.hxx .\headers.cxx .\dirstg.hxx
+
+$(OBJDIR)\stgutil.obj $(OBJDIR)\stgutil.lst: .\stgutil.cxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\ntenm.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\stgutil.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\dsyserr.h $(COMMONINC)\issperr.h \
+ $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h $(COMMONINC)\basetyps.h \
+ $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h $(COMMONINC)\cobjerr.h \
+ $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h $(COMMONINC)\disptype.h \
+ $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h $(COMMONINC)\emonkr.h \
+ $(COMMONINC)\estatd.h $(COMMONINC)\estats.h $(COMMONINC)\estrng.h \
+ $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h \
+ $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h \
+ $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h $(COMMONINC)\pstrm.h \
+ $(COMMONINC)\querys.h $(COMMONINC)\rot.h $(COMMONINC)\scode.h \
+ $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h \
+ $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h \
+ $(COMMONINC)\varnt.h $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\limits.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\filstg.hxx .\headers.cxx .\dirstg.hxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\headers.pxh $(PCHDIR)\$(OBJDIR)\headers.lst: \
+ $(CAIROLE)\stg\fsstg\headers.cxx $(CAIROLE)\stg\fsstg\dirstg.hxx \
+ $(CAIROLE)\stg\fsstg\filstg.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h $(COMMONINC)\estats.h \
+ $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h \
+ $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h \
+ $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h $(COMMONINC)\rot.h \
+ $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h \
+ $(COMMONINC)\storag.h $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h \
+ $(COMMONINC)\valid.h $(COMMONINC)\varnt.h $(COMMONINC)\winole.h \
+ $(COMMONINC)\wtypes.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\limits.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
+.\$(OBJDIR)\dirstg.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\dsenm.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\filstg.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\fsenm.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\filstm.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\api.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\ntsupp.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\ntenm.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\ntlkb.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\stgsupp.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\stgutil.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/fsstg/dirs b/private/ole32/stg/fsstg/dirs
new file mode 100644
index 000000000..f10ca67a3
--- /dev/null
+++ b/private/ole32/stg/fsstg/dirs
@@ -0,0 +1,36 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+
diff --git a/private/ole32/stg/fsstg/dirstg.cxx b/private/ole32/stg/fsstg/dirstg.cxx
new file mode 100644
index 000000000..66c9a641e
--- /dev/null
+++ b/private/ole32/stg/fsstg/dirstg.cxx
@@ -0,0 +1,868 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dirstg.cxx
+//
+// Contents: IStorage for directories implementation
+//
+// History: 24-Jun-93 DrewB Created
+//
+// Notes: This code is for non-OFS filesystems
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <stgutil.hxx>
+#include "dsenm.hxx"
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CDirStorage::QueryInterface:%p(riid, %p)\n",
+ this, ppvObj));
+ if (!IsValidIid(iid))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+ if (IsEqualIID(iid, IID_IStorage) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IStorage *)this;
+ CDirStorage::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IPropertySetStorage))
+ {
+ // BUGBUG - Need storage property set
+ sc = E_NOINTERFACE;
+ *ppvObj = NULL;
+ }
+ else if (IsEqualIID(iid, IID_INativeFileSystem))
+ {
+ *ppvObj = (INativeFileSystem *)this;
+ CDirStorage::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppvObj = NULL;
+ }
+ ssDebugOut((DEB_TRACE, "Out CDirStorage::QueryInterface => %p\n",
+ *ppvObj));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::CDirStorage, public
+//
+// Synopsis: Empty object construction
+//
+// History: 30-Jun-93 DrewB Created
+// 24-Mar-95 HenryLee Save drive letter to correct Stat prob
+//
+//----------------------------------------------------------------------------
+
+CDirStorage::CDirStorage(void)
+{
+ ssDebugOut((DEB_ITRACE, "In CDirStorage::CDirStorage:%p()\n", this));
+ _sig = 0;
+ _wcDrive = L'\0';
+ ssDebugOut((DEB_ITRACE, "Out CDirStorage::CDirStorage\n"));
+ ENLIST_TRACKING(CDirStorage);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::InitFromHandle, public
+//
+// Synopsis: From-handle constructor
+//
+// Arguments: [h] - Handle of directory
+// [grfMode] - Mode of handle
+//
+// Returns: Appropriate status code
+//
+// History: 29-Jun-93 DrewB Created
+// 24-Mar-95 HenryLee Save drive letter to correct Stat prob
+//
+// Notes: Takes a new reference on the handle
+//
+//----------------------------------------------------------------------------
+
+SCODE CDirStorage::InitFromHandle(HANDLE h,
+ WCHAR const *pwcsName,
+ DWORD grfMode)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CDirStorage::InitFromHandle:%p(%p, %lX)\n",
+ this, h, grfMode));
+
+ ssChk(ValidateMode(grfMode));
+ _h = h;
+ ssAssert(_h != NULL);
+ _grfMode = grfMode;
+ _sig = CDIRSTORAGE_SIG;
+ _wcDrive = GetDriveLetter (pwcsName);
+
+ ssDebugOut((DEB_ITRACE, "Out CDirStorage::InitFromHandle\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::InitFromPath, public
+//
+// Synopsis: From-path constructor
+//
+// Arguments: [hParent] - Handle of parent directory
+// [pwcsName] - Name of directory
+// [grfMode] - Mode
+// [fCreate] - Create or open
+// [pssSecurity] - Security
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+// 24-Mar-95 HenryLee Save drive letter to correct Stat prob
+//
+//----------------------------------------------------------------------------
+
+SCODE CDirStorage::InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSECURITY_ATTRIBUTES pssSecurity)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CDirStorage::InitFromPath:%p("
+ "%p, %ws, %lX, %d, %p)\n", this, hParent, pwcsName, grfMode,
+ co, pssSecurity));
+
+ ssChk(ValidateMode(grfMode));
+ ssChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co, FD_DIR,
+ pssSecurity, &_h));
+
+ _grfMode = grfMode;
+ _sig = CDIRSTORAGE_SIG;
+ _wcDrive = GetDriveLetter (pwcsName);
+
+ ssDebugOut((DEB_ITRACE, "Out CDirStorage::InitFromPath\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::~CDirStorage, public
+//
+// Synopsis: Destructor
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CDirStorage::~CDirStorage(void)
+{
+ ssDebugOut((DEB_ITRACE, "In CDirStorage::~CDirStorage()\n"));
+
+ _sig = CDIRSTORAGE_SIGDEL;
+
+ if ((HANDLE)_h != NULL && (_grfMode & STGM_DELETEONRELEASE))
+ ssVerSucc(DestroyTree(NULL, NULL, _h, FD_DIR));
+
+ ssDebugOut((DEB_ITRACE, "Out CDirStorage::~CDirStorage\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::CreateStream, public
+//
+// Synopsis: Creates a stream
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [reserved1]
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::CreateStream(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ ssDebugOut((DEB_TRACE, "Stb CDirStorage::CreateStream:%p("
+ "%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode,
+ reserved1, reserved2, ppstm));
+ return ssResult(STG_E_INVALIDFUNCTION);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::OpenStream, public
+//
+// Synopsis: Opens an existing stream
+//
+// Arguments: [pwcsName] - Name
+// [reserved1]
+// [grfMode] - Permissions
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::OpenStream(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ ssDebugOut((DEB_TRACE, "Stb CDirStorage::OpenStream:%p("
+ "%ws, %p, %lX, %lu, %p)\n", this, pwcsName, reserved1,
+ grfMode, reserved2, ppstm));
+ return ssResult(STG_E_FILENOTFOUND);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::CreateStorage, public
+//
+// Synopsis: Creates a child storage
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [dwStgFmt] - Type of storage to create
+// [pssSecurity] - Security
+// [ppstg] - New storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::CreateStorage (
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD dwStgFmt,
+ LPSTGSECURITY pssSecurity,
+ IStorage **ppstg )
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CDirStorage::CreateStorage:%p("
+ "%ws, %lX, %lu, %p, %p)\n", this, pwcsName, grfMode,
+ dwStgFmt, pssSecurity, ppstg));
+
+ ssChk(Validate());
+ ssChk(VerifyStgFmt(dwStgFmt));
+ ssAssert(_h != NULL);
+ sc = CreateStorageType(_h, pwcsName, NULL, grfMode, dwStgFmt,
+ (LPSECURITY_ATTRIBUTES)pssSecurity, ppstg);
+
+ ssDebugOut((DEB_TRACE, "Out CDirStorage::CreateStorage => %p\n", *ppstg));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::OpenStorage, public
+//
+// Synopsis: Gets an existing child storage
+//
+// Arguments: [pwcsName] - Name
+// [pstgPriority] - Priority reopens
+// [grfMode] - Permissions
+// [snbExclude] - Priority reopens
+// [reserved]
+// [ppstg] - Storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::OpenStorage(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CDirStorage::OpenStorage:%p("
+ "%ws, %p, %lX, %p, %lu, %p)\n", this, pwcsName, pstgPriority,
+ grfMode, snbExclude, reserved, ppstg));
+
+ ssChk(Validate());
+ if (pstgPriority != NULL || snbExclude != NULL ||
+ reserved != 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if (grfMode & (STGM_CREATE | STGM_CONVERT))
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+
+ ssAssert(_h != NULL);
+ sc = OpenAnyStorage(_h, pwcsName, NULL, 0, pstgPriority, grfMode,
+ snbExclude, ppstg);
+
+ ssDebugOut((DEB_TRACE, "Out CDirStorage::OpenStorage => %p\n", *ppstg));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::CopyTo, public
+//
+// Synopsis: Makes a copy of a storage
+//
+// Arguments: [ciidExclude] - Length of rgiid array
+// [rgiidExclude] - Array of IIDs to exclude
+// [snbExclude] - Names to exclude
+// [pstgDest] - Parent of copy
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+// Notes: BUGBUG - This function operates recursively and so
+// is bounded by stack space
+// It could also be optimized to recognize special cases
+// of copying (like treating a docfile as a file)
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::CopyTo(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest)
+{
+ SCODE sc, scFinal;
+ STATSTG stat, statFrom, statTo;
+ WCHAR pwcsName[MAXIMUM_FILENAME_LENGTH];
+ FILEDIR fd;
+ ULONG i;
+ CNtEnum nte;
+ CDfName dfn;
+
+ ssDebugOut((DEB_TRACE, "In CDirStorage::CopyTo:%p(%lu, %p, %p, %p)\n",
+ this, ciidExclude, rgiidExclude, snbExclude, pstgDest));
+
+ ssChk(Validate());
+ if (!IsValidInterface(pstgDest))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+
+ // Check IID exclusions. A directory storage can only contain
+ // substorages so if IID_IStorage is excluded we are done
+ for (i = 0; i < ciidExclude; i++)
+ if (IsEqualIID(rgiidExclude[i], IID_IStorage))
+ ssErr(EH_Err, S_OK);
+
+ // Copy class ID and state bits if the destination supports them
+ ssChk(Stat(&stat, STATFLAG_NONAME));
+ sc = GetScode(pstgDest->SetClass(stat.clsid));
+ if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
+ ssErr(EH_Err, sc);
+ sc = GetScode(pstgDest->SetStateBits(stat.grfStateBits, 0xffffffff));
+ if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
+ ssErr(EH_Err, sc);
+
+ scFinal = S_OK;
+ ssAssert(_h != NULL);
+ ssChk(nte.InitFromHandle(_h, TRUE));
+ for (;;)
+ {
+ sc = nte.Next(&stat, pwcsName, NTE_BUFFERNAME, &fd);
+ if (sc == S_FALSE)
+ break;
+ else if (FAILED(sc))
+ ssErr(EH_Err, sc);
+
+ // Ignore . and ..
+ if (!lstrcmpW(pwcsName, L".") || !lstrcmpW(pwcsName, L".."))
+ continue;
+
+ dfn.Set(pwcsName);
+ if (snbExclude == NULL || !NameInSNB(&dfn, snbExclude))
+ {
+ SafeIStorage pstgFrom, pstgTo;
+
+ ssHChkTo(EH_Next, OpenStorage(pwcsName, NULL, STGM_READ |
+ STGM_SHARE_EXCLUSIVE,
+ NULL, NULL, &pstgFrom));
+ ssHChkTo(EH_Next, pstgFrom->Stat(&statFrom, STATFLAG_NONAME));
+ sc = GetScode(pstgDest->CreateStorage(pwcsName, STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE,
+ statFrom.STATSTG_dwStgFmt,
+ NULL,
+ &pstgTo));
+ if (FAILED(sc))
+ {
+ if (sc == STG_E_FILEALREADYEXISTS)
+ {
+ // Try to open rather than creating
+ sc = GetScode(pstgDest->OpenStorage(pwcsName, NULL,
+ STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE,
+ NULL, NULL, &pstgTo));
+ if (SUCCEEDED(sc))
+ {
+ sc = GetScode(pstgTo->Stat(&statTo, STATFLAG_NONAME));
+ if ( FAILED(sc) ||
+ statTo.STATSTG_dwStgFmt != statFrom.STATSTG_dwStgFmt)
+ {
+ sc = STG_E_INVALIDFUNCTION;
+ }
+ }
+ }
+ }
+
+ if (SUCCEEDED(sc))
+ sc = pstgFrom->CopyTo(0, NULL, NULL, pstgTo);
+
+ EH_Next:
+ if (FAILED(sc))
+ scFinal = sc;
+ }
+ }
+ sc = scFinal;
+
+ ssDebugOut((DEB_TRACE, "Out CDirStorage::CopyTo\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::MoveElementTo, public
+//
+// Synopsis: Move an element of a storage to another storage
+//
+// Arguments: [pwcsName] - Current name
+// [ptcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// Algorithm: Open source as storage or stream (whatever works)
+// Create appropriate destination
+// Copy source to destination
+// Set create time of destination equal to create time of source
+// If appropriate, delete source
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::MoveElementTo(WCHAR const *pwcsName,
+ IStorage *pstgParent,
+ WCHAR const *ptcsNewName,
+ DWORD grfFlags)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CDirStorage::MoveElementTo:%p("
+ "%ws, %p, %ws, %lu)\n", this, pwcsName, pstgParent,
+ ptcsNewName, grfFlags));
+
+ ssChk(Validate());
+ ssChk(VerifyMoveFlags(grfFlags));
+
+ sc = GenericMoveElement(this, pwcsName, pstgParent, ptcsNewName, grfFlags);
+
+ ssDebugOut((DEB_TRACE, "Out CDirStorage::MoveElementTo => %lX\n", sc));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::Commit, public
+//
+// Synopsis: Commits transacted changes
+//
+// Arguments: [dwFlags] - DFC_*
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::Commit(DWORD dwFlags)
+{
+ ssDebugOut((DEB_TRACE, "Stb CDirStorage::Commit:%p(%lX)\n",
+ this, dwFlags));
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::Revert, public
+//
+// Synopsis: Reverts transacted changes
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::Revert(void)
+{
+ ssDebugOut((DEB_TRACE, "Stb CDirStorage::Revert:%p()\n", this));
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::EnumElements, public
+//
+// Synopsis: Starts an iterator
+//
+// Arguments: [reserved1]
+// [reserved2]
+// [reserved3]
+// [ppenm] - Enumerator return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::EnumElements(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm)
+{
+ SCODE sc;
+ SafeCDirEnum pde;
+
+ ssDebugOut((DEB_TRACE, "In CDirStorage::EnumElements:%p("
+ "%lu, %p, %lu, %p)\n", this, reserved1, reserved2,
+ reserved3, ppenm));
+
+ if (reserved1 != 0 || reserved2 != NULL || reserved3 != 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+
+ pde.Attach(new CDirEnum());
+ ssMem((CDirEnum *)pde);
+ ssAssert(_h != NULL);
+ ssChk(pde->InitFromHandle(_h));
+ TRANSFER_INTERFACE(pde, IEnumSTATSTG, ppenm);
+
+ ssDebugOut((DEB_TRACE, "Out CDirStorage::EnumElements => %p\n",
+ *ppenm));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::DestroyElement, public
+//
+// Synopsis: Permanently deletes an element of a storage
+//
+// Arguments: [pwcsName] - Name of element
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::DestroyElement(WCHAR const *pwcsName)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CDirStorage::DestroyElement:%p(%ws)\n",
+ this, pwcsName));
+
+ if (SUCCEEDED(sc = Validate()))
+ {
+ ssAssert(_h != NULL);
+ sc = DestroyTree(_h, pwcsName, NULL, FD_FILE);
+ }
+
+ ssDebugOut((DEB_TRACE, "Out CDirStorage::DestroyElement\n"));
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::RenameElement, public
+//
+// Synopsis: Renames an element of a storage
+//
+// Arguments: [pwcsName] - Current name
+// [pwcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::RenameElement(WCHAR const *pwcsName,
+ WCHAR const *pwcsNewName)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CDirStorage::RenameElement:%p(%ws, %ws)\n",
+ this, pwcsName, pwcsNewName));
+
+ ssChk(Validate());
+ // pwcsName is checked by GetFileOrDirHandle
+ ssChk(CheckFdName(pwcsNewName));
+
+ ssAssert(_h != NULL);
+ sc = RenameChild(_h, pwcsName, pwcsNewName);
+
+ ssDebugOut((DEB_TRACE, "Out CDirStorage::RenameElement\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::SetElementTimes, public
+//
+// Synopsis: Sets element time stamps
+//
+// Arguments: [pwcsName] - Name
+// [pctime] - Create time
+// [patime] - Access time
+// [pmtime] - Modify time
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::SetElementTimes(WCHAR const *pwcsName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ SCODE sc;
+ SafeNtHandle h;
+
+ ssDebugOut((DEB_TRACE, "In CDirStorage::SetElementTimes:%p("
+ "%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime));
+
+ ssChk(Validate());
+
+ ssAssert(_h != NULL);
+ ssChk(GetFileOrDirHandle(_h, pwcsName, STGM_WRITE, &h, NULL, NULL, NULL));
+ sc = SetTimes(h, pctime, patime, pmtime);
+
+ ssDebugOut((DEB_TRACE, "Out CDirStorage::SetElementTimes\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::SetClass, public
+//
+// Synopsis: Sets storage class
+//
+// Arguments: [clsid] - class id
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::SetClass(REFCLSID clsid)
+{
+ ssDebugOut((DEB_TRACE, "In CDirStorage::SetClass:%p(clsid)\n", this));
+ ssDebugOut((DEB_TRACE, "Out CDirStorage::SetClass:%p(clsid)\n", this));
+ return ssResult(STG_E_INVALIDFUNCTION);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::SetStateBits, public
+//
+// Synopsis: Sets state bits
+//
+// Arguments: [grfStateBits] - state bits
+// [grfMask] - state bits mask
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ ssDebugOut((DEB_TRACE, "In CDirStorage::SetStateBits:%p("
+ "%lu, %lu)\n", this, grfStateBits, grfMask));
+ ssDebugOut((DEB_TRACE, "Out CDirStorage::SetStateBits\n"));
+ return ssResult(STG_E_INVALIDFUNCTION);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::Stat, public
+//
+// Synopsis: Fills in a buffer of information about this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+ STATSTG stat;
+ FILEDIR fd;
+
+ ssDebugOut((DEB_TRACE, "In CDirStorage::Stat:%p(%p, %lX)\n",
+ this, pstatstg, grfStatFlag));
+
+ ssChk(VerifyStatFlag(grfStatFlag));
+ ssChk(Validate());
+
+ __try
+ {
+ ssAssert(_h != NULL);
+ sc = StatNtHandle(_h, grfStatFlag, 0, &stat, NULL, NULL, &fd);
+ if (SUCCEEDED(sc))
+ {
+ SetDriveLetter (stat.pwcsName, _wcDrive);
+ if (SUCCEEDED(sc))
+ {
+ stat.clsid = CLSID_NULL;
+
+ ssAssert(fd == FD_DIR);
+ stat.grfMode = _grfMode;
+ stat.cbSize.HighPart = stat.cbSize.LowPart = 0;
+ stat.STATSTG_dwStgFmt = STGFMT_DIRECTORY;
+ *pstatstg = stat;
+ }
+ else if (stat.pwcsName)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (stat.pwcsName)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ sc = HRESULT_FROM_NT(GetExceptionCode());
+ }
+
+ ssDebugOut((DEB_TRACE, "Out CDirStorage::Stat\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::ValidateMode, private
+//
+// Synopsis: Checks for legal access modes
+//
+// Arguments: [grfMode] - Mode
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CDirStorage::ValidateMode(DWORD grfMode)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CDirStorage::ValidateMode:%p(0x%lX)\n",
+ this, grfMode));
+ // BUGBUG - Can we simply ignore priority mode?
+ if (grfMode & (STGM_TRANSACTED | STGM_CREATE | STGM_CONVERT))
+ sc = STG_E_INVALIDFLAG;
+ else
+ sc = S_OK;
+ ssDebugOut((DEB_ITRACE, "Out CDirStorage::ValidateMode => 0x%lX\n", sc));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirStorage::GetHandle, private
+//
+// Synopsis: Get the handle backing this Storage.
+//
+// History: 10-May-94 BillMo Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirStorage::GetHandle(HANDLE *ph)
+{
+ SCODE sc;
+
+ ssChk(Validate());
+
+ *ph = _h;
+
+EH_Err:
+ return(ssResult(sc));
+}
diff --git a/private/ole32/stg/fsstg/dirstg.hxx b/private/ole32/stg/fsstg/dirstg.hxx
new file mode 100644
index 000000000..3f4895e1f
--- /dev/null
+++ b/private/ole32/stg/fsstg/dirstg.hxx
@@ -0,0 +1,138 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dirstg.hxx
+//
+// Contents: CDirStorage header
+//
+// Classes: CDirStorage
+//
+// History: 24-Jun-93 DrewB Created
+//
+// Notes: Non-OFS
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DIRSTG_HXX__
+#define __DIRSTG_HXX__
+
+#include <otrack.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: CDirStorage (ds)
+//
+// Purpose: Implements IStorage for a directory
+//
+// Interface: See below
+//
+// History: 24-Jun-93 DrewB Created
+// 26-Mar-95 HenryLee added drive letter for Stat problem
+//
+//----------------------------------------------------------------------------
+
+interface CDirStorage
+ : INHERIT_TRACKING,
+ public IStorage,
+ public INativeFileSystem
+{
+public:
+ CDirStorage(void);
+ SCODE InitFromHandle(HANDLE h, WCHAR const *pwcsName, DWORD grfMode);
+ SCODE InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSECURITY_ATTRIBUTES pssSecurity);
+ ~CDirStorage(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // IStorage
+ STDMETHOD(CreateStream)(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(OpenStream)(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(CreateStorage)(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD stgType,
+ LPSTGSECURITY pssSecurity,
+ IStorage **ppstg);
+ STDMETHOD(OpenStorage)(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg);
+ STDMETHOD(CopyTo)(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest);
+ STDMETHOD(MoveElementTo)(WCHAR const *lpszName,
+ IStorage *pstgDest,
+ WCHAR const *lpszNewName,
+ DWORD grfFlags);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(EnumElements)(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm);
+ STDMETHOD(DestroyElement)(WCHAR const *pwcsName);
+ STDMETHOD(RenameElement)(WCHAR const *pwcsOldName,
+ WCHAR const *pwcsNewName);
+ STDMETHOD(SetElementTimes)(const WCHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+ STDMETHOD(SetClass)(REFCLSID clsid);
+ STDMETHOD(SetStateBits)(DWORD grfStateBits, DWORD grfMask);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+
+ // INativeFileSystem
+ STDMETHOD(GetHandle(HANDLE *ph));
+
+private:
+ inline SCODE Validate(void) const;
+ SCODE ValidateMode(DWORD grfMode);
+
+ ULONG _sig;
+ NuSafeNtHandle _h;
+ DWORD _grfMode;
+ WCHAR _wcDrive;
+};
+
+SAFE_INTERFACE_PTR(SafeCDirStorage, CDirStorage);
+
+#define CDIRSTORAGE_SIG LONGSIG('D', 'S', 'T', 'G')
+#define CDIRSTORAGE_SIGDEL LONGSIG('D', 's', 'T', 'g')
+
+//+--------------------------------------------------------------
+//
+// Member: CDirStorage::Validate, private
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 24-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CDirStorage::Validate(void) const
+{
+ return (this == NULL || _sig != CDIRSTORAGE_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+#endif // #ifndef __DIRSTG_HXX__
diff --git a/private/ole32/stg/fsstg/dsenm.cxx b/private/ole32/stg/fsstg/dsenm.cxx
new file mode 100644
index 000000000..86ed705aa
--- /dev/null
+++ b/private/ole32/stg/fsstg/dsenm.cxx
@@ -0,0 +1,264 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dsenm.cxx
+//
+// Contents: CDirEnum implementation
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include "dsenm.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirEnum::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CDirEnum::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CDirEnum::QueryInterface:%p(riid, %p)\n",
+ this, ppvObj));
+ if (!IsValidIid(iid))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+ if (IsEqualIID(iid, IID_IEnumSTATSTG) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IEnumSTATSTG *)this;
+ CDirEnum::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppvObj = NULL;
+ }
+ ssDebugOut((DEB_TRACE, "Out CDirEnum::QueryInterface => %p\n",
+ *ppvObj));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirEnum::CDirEnum, public
+//
+// Synopsis: Constructor
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CDirEnum::CDirEnum(void)
+ : _nte(FALSE)
+{
+ ssDebugOut((DEB_ITRACE, "In CDirEnum::CDirEnum:%p()\n", this));
+ _sig = 0;
+ ssDebugOut((DEB_ITRACE, "Out CDirEnum::CDirEnum\n"));
+ ENLIST_TRACKING(CDirEnum);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirEnum::~CDirEnum, public
+//
+// Synopsis: Destructor
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CDirEnum::~CDirEnum(void)
+{
+ ssDebugOut((DEB_ITRACE, "In CDirEnum::~CDirEnum:%p()\n", this));
+ _sig = CDIRENUM_SIGDEL;
+ ssDebugOut((DEB_ITRACE, "Out CDirEnum::~CDirEnum\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDirEnum::Next, public
+//
+// Synopsis: Gets N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+// [rgelt] - Array for element return
+// [pceltFetched] - If non-NULL, contains the number of
+// elements fetched
+//
+// Returns: Appropriate status code
+//
+// Modifies: [rgelt]
+// [pceltFetched]
+//
+// History: 09-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CDirEnum::Next(ULONG celt,
+ STATSTG *rgelt,
+ ULONG *pceltFetched)
+{
+ SCODE sc;
+ STATSTG *pelt = rgelt, stat;
+ ULONG celtDone;
+ FILEDIR fd;
+ CPtrCache pc;
+ WCHAR *pwcs;
+
+ ssDebugOut((DEB_TRACE, "In CDirEnum::Next:%p(%lu, %p, %p)\n",
+ this, celt, rgelt, pceltFetched));
+
+ if (pceltFetched == NULL && celt > 1)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+
+ __try
+ {
+ for (celtDone = 0; pelt<rgelt+celt; pelt++, celtDone++)
+ {
+ sc = _nte.Next(&stat, NULL, NTE_STATNAME, &fd);
+ if (FAILED(sc) || sc == S_FALSE)
+ break;
+ if (FAILED(sc = pc.Add(stat.pwcsName)))
+ break;
+ *pelt = stat;
+ }
+
+ if (SUCCEEDED(sc) && pceltFetched)
+ *pceltFetched = celtDone;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ pc.StartEnum();
+ while (pc.Next((void **)&pwcs))
+ ssHVerSucc(CoMemFree(pwcs));
+ sc = HRESULT_FROM_NT(GetExceptionCode());
+ }
+
+ ssDebugOut((DEB_TRACE, "Out CDirEnum::Next => 0x%lX\n", sc));
+EH_Err:
+ if (FAILED(sc))
+ {
+ pc.StartEnum();
+ while (pc.Next((void **)&pwcs))
+ ssHVerSucc(CoMemFree(pwcs));
+ }
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDirEnum::Skip, public
+//
+// Synopsis: Skips N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CDirEnum::Skip(ULONG celt)
+{
+ SCODE sc;
+ STATSTG stat;
+ FILEDIR fd;
+
+ ssDebugOut((DEB_TRACE, "In CDirEnum::Skip:%p(%lu)\n", this, celt));
+
+ ssChk(Validate());
+
+ while (celt > 0)
+ {
+ sc = _nte.Next(&stat, NULL, NTE_NONAME, &fd);
+ if (FAILED(sc) || sc == S_FALSE)
+ break;
+ }
+
+ ssDebugOut((DEB_TRACE, "Out CDirEnum::Skip\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDirEnum::Reset, public
+//
+// Synopsis: Rewinds the iterator
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CDirEnum::Reset(void)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CDirEnum::Reset:%p()\n", this));
+
+ ssChk(Validate());
+ _nte.Reset();
+
+ ssDebugOut((DEB_TRACE, "Out CDirEnum::Reset\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDirEnum::Clone, public
+//
+// Synopsis: Clones this iterator
+//
+// Arguments: [ppenm] - Clone return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 09-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CDirEnum::Clone(IEnumSTATSTG **ppenm)
+{
+ SCODE sc;
+ SafeCDirEnum pde;
+
+ ssDebugOut((DEB_TRACE, "In CDirEnum::Clone:%p(%p)\n", this, ppenm));
+
+ ssChk(Validate());
+
+ pde.Attach(new CDirEnum());
+ ssMem((CDirEnum *)pde);
+ ssChk(pde->InitFromHandle(_nte.GetHandle()));
+ TRANSFER_INTERFACE(pde, IEnumSTATSTG, ppenm);
+
+ ssDebugOut((DEB_TRACE, "Out CDirEnum::Clone => %p\n", *ppenm));
+EH_Err:
+ return ssResult(sc);
+}
diff --git a/private/ole32/stg/fsstg/dsenm.hxx b/private/ole32/stg/fsstg/dsenm.hxx
new file mode 100644
index 000000000..4596d8119
--- /dev/null
+++ b/private/ole32/stg/fsstg/dsenm.hxx
@@ -0,0 +1,110 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dsenm.hxx
+//
+// Contents: Directory storage enumerator
+//
+// Classes: CDirEnum
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DSENM_HXX__
+#define __DSENM_HXX__
+
+#include <otrack.hxx>
+#include <ntenm.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: CDirEnum (de)
+//
+// Purpose: Directory storage enumerator
+//
+// Interface: IEnumSTATSTG
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CDirEnum
+ : INHERIT_TRACKING,
+ public IEnumSTATSTG
+{
+public:
+ CDirEnum(void);
+ inline SCODE InitFromHandle(HANDLE h);
+ ~CDirEnum(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // IEnumSTATSTG
+ STDMETHOD(Next)(ULONG celt, STATSTG FAR *rgelt, ULONG *pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(IEnumSTATSTG **ppenm);
+
+private:
+ inline SCODE Validate(void) const;
+
+ ULONG _sig;
+ CNtEnum _nte;
+};
+
+SAFE_INTERFACE_PTR(SafeCDirEnum, CDirEnum);
+
+#define CDIRENUM_SIG LONGSIG('D', 'E', 'N', 'M')
+#define CDIRENUM_SIGDEL LONGSIG('D', 'e', 'N', 'm')
+
+//+--------------------------------------------------------------
+//
+// Member: CDirEnum::Validate, private
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 09-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CDirEnum::Validate(void) const
+{
+ return (this == NULL || _sig != CDIRENUM_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirEnum::InitFromHandle, public
+//
+// Synopsis: Initializes from a handle
+//
+// Arguments: [h] - Handle
+//
+// Returns: Throws exceptions on failure
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CDirEnum::InitFromHandle(HANDLE h)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CDirEnum::InitFromHandle:%p(%p)\n",
+ this, h));
+ sc = _nte.InitFromHandle(h, TRUE);
+ if (SUCCEEDED(sc))
+ _sig = CDIRENUM_SIG;
+ ssDebugOut((DEB_ITRACE, "Out CDirEnum::InitFromHandle => %lX\n", sc));
+ return sc;
+}
+
+#endif // #ifndef __DSENM_HXX__
diff --git a/private/ole32/stg/fsstg/filelist.mk b/private/ole32/stg/fsstg/filelist.mk
new file mode 100644
index 000000000..a98bb2cef
--- /dev/null
+++ b/private/ole32/stg/fsstg/filelist.mk
@@ -0,0 +1,26 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1993.
+# All rights reserved.
+#
+############################################################################
+
+
+TARGET = fsstg.lib
+
+PXXFILE = .\headers.cxx
+
+CXXFILES = .\dirstg.cxx\
+ .\dsenm.cxx\
+ .\filstg.cxx\
+ .\fsenm.cxx\
+ .\filstm.cxx\
+ .\api.cxx\
+ .\ntsupp.cxx\
+ .\ntenm.cxx\
+ .\ntlkb.cxx\
+ .\stgsupp.cxx\
+ .\stgutil.cxx
+
+CINC = $(CINC) -I$(CAIROLE)\stg\h
diff --git a/private/ole32/stg/fsstg/filstg.cxx b/private/ole32/stg/fsstg/filstg.cxx
new file mode 100644
index 000000000..2ac8ee5ba
--- /dev/null
+++ b/private/ole32/stg/fsstg/filstg.cxx
@@ -0,0 +1,1083 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: filstg.cxx
+//
+// Contents: IStorage for files implementation
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <ctype.h>
+#include <stgutil.hxx>
+#include <filstm.hxx>
+#include "fsenm.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CFileStorage::QueryInterface:%p(riid, %p)\n",
+ this, ppvObj));
+ if (!IsValidIid(iid))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+ if (IsEqualIID(iid, IID_IStorage) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IStorage *)this;
+ CFileStorage::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IPropertySetStorage))
+ {
+ // BUGBUG - Need storage property set
+ *ppvObj = NULL;
+ sc = STG_E_UNIMPLEMENTEDFUNCTION;
+ }
+ else if (IsEqualIID(iid, IID_INativeFileSystem))
+ {
+ *ppvObj = (INativeFileSystem *)this;
+ CFileStorage::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppvObj = NULL;
+ }
+ ssDebugOut((DEB_TRACE, "Out CFileStorage::QueryInterface => %p\n",
+ *ppvObj));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::CFileStorage, public
+//
+// Synopsis: Empty object constructor
+//
+// History: 30-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CFileStorage::CFileStorage(void)
+{
+ ssDebugOut((DEB_ITRACE, "In CFileStorage::CFileStorage:%p()\n", this));
+ _sig = 0;
+ ssDebugOut((DEB_ITRACE, "Out CFileStorage::CFileStorage\n"));
+ ENLIST_TRACKING(CFileStorage);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::InitFromPath, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [hParent] - Handle of parent directory
+// [pwcsName] - Name of directory
+// [grfMode] - Mode
+// [co] - Create or open
+// [pssSecurity] - Security
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CFileStorage::InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSECURITY_ATTRIBUTES pssSecurity)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CFileStorage::InitFromPath:%p("
+ "%p, %ws, %lX, %d, %p)\n", this, hParent, pwcsName,
+ grfMode, co, pssSecurity));
+
+ ssChk(ValidateMode(grfMode));
+ ssChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co,
+ FD_FILE, pssSecurity, &_h));
+
+ _grfMode = grfMode;
+ _sig = CFILESTORAGE_SIG;
+
+ ssDebugOut((DEB_ITRACE, "Out CFileStorage::InitFromPath\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::InitFromHandle, public
+//
+// Synopsis: Initialize from a handle
+//
+// Arguments: [h] - Handle
+// [grfMode] - Mode
+//
+// Returns: Appropriate status code
+//
+// History: 14-Jul-93 DrewB Created
+//
+// Notes: Takes a new reference on the handle
+//
+//----------------------------------------------------------------------------
+
+SCODE CFileStorage::InitFromHandle(HANDLE h, DWORD grfMode)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CFileStorage::InitFromHandle:%p(%p, %lX)\n",
+ this, h, grfMode));
+
+ ssChk(ValidateMode(grfMode));
+ _h = h;
+ ssAssert(_h != NULL);
+ _grfMode = grfMode;
+ _sig = CFILESTORAGE_SIG;
+
+ ssDebugOut((DEB_ITRACE, "Out CFileStorage::InitFromHandle\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::~CFileStorage, public
+//
+// Synopsis: Destructor
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CFileStorage::~CFileStorage(void)
+{
+ ssDebugOut((DEB_ITRACE, "In CFileStorage::~CFileStorage()\n"));
+ _sig = CFILESTORAGE_SIGDEL;
+ ssDebugOut((DEB_ITRACE, "Out CFileStorage::~CFileStorage\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::CreateStream, public
+//
+// Synopsis: Creates a stream
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [reserved1]
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+// History: 28-Jun-93 DrewB Created
+//
+// Notes: Files only support the contents stream
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::CreateStream(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+ SafeCNtFileStream pfs;
+
+ ssDebugOut((DEB_TRACE, "In CFileStorage::CreateStream:%p("
+ "%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode,
+ reserved1, reserved2, ppstm));
+
+ ssChk(Validate());
+ if (lstrcmpiW(pwcsName, CONTENTS_STREAM) != 0)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+ // Contents always exist so fail if FAILIFTHERE
+ if ((grfMode & (STGM_CREATE | STGM_CONVERT)) == 0)
+ ssErr(EH_Err, STG_E_FILEALREADYEXISTS);
+ if (reserved1 != 0 || reserved2 != 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+
+ pfs.Attach(new CNtFileStream());
+ ssMem((CNtFileStream *)pfs);
+ ssAssert(_h != NULL);
+ ssChk(pfs->InitFromHandle(_h, grfMode, CO_CREATE, NULL));
+ TRANSFER_INTERFACE(pfs, IStream, ppstm);
+
+ ssDebugOut((DEB_TRACE, "Out CFileStorage::CreateStream => %p\n", *ppstm));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::OpenStream, public
+//
+// Synopsis: Opens an existing stream
+//
+// Arguments: [pwcsName] - Name
+// [reserved1]
+// [grfMode] - Permissions
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::OpenStream(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+ SafeCNtFileStream pfs;
+
+ ssDebugOut((DEB_TRACE, "In CFileStorage::OpenStream:%p("
+ "%ws, %p, %lX, %lu, %p)\n", this, pwcsName, reserved1,
+ grfMode, reserved2, ppstm));
+
+ ssChk(Validate());
+ if (lstrcmpiW(pwcsName, CONTENTS_STREAM) != 0)
+ ssErr(EH_Err, STG_E_FILENOTFOUND);
+ if (reserved1 != 0 || reserved2 != 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if (grfMode & (STGM_CREATE | STGM_CONVERT))
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+
+ pfs.Attach(new CNtFileStream());
+ ssMem((CNtFileStream *)pfs);
+ ssAssert(_h != NULL);
+ ssChk(pfs->InitFromHandle(_h, grfMode, CO_OPEN, NULL));
+ TRANSFER_INTERFACE(pfs, IStream, ppstm);
+
+ ssDebugOut((DEB_TRACE, "Out CFileStorage::OpenStream => %p\n", *ppstm));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::CreateStorage, public
+//
+// Synopsis: Creates a child storage
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [stgType] - Type of storage to create
+// [pssSecurity] - Security
+// [ppstg] - New storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::CreateStorage (
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD stgType,
+ LPSTGSECURITY pssSecurity,
+ IStorage **ppstg)
+{
+ ssDebugOut((DEB_TRACE, "Stb CFileStorage::CreateStorage:%p("
+ "%ws, %lX, %lu, %p, %p)\n", this, pwcsName, grfMode,
+ stgType, (LPSTGSECURITY)pssSecurity, ppstg));
+ return ssResult(STG_E_INVALIDFUNCTION);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::OpenStorage, public
+//
+// Synopsis: Gets an existing child storage
+//
+// Arguments: [pwcsName] - Name
+// [pstgPriority] - Priority reopens
+// [grfMode] - Permissions
+// [snbExclude] - Priority reopens
+// [pssSecurity] - Security
+// [ppstg] - Storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::OpenStorage(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+{
+ ssDebugOut((DEB_TRACE, "Stb CFileStorage::OpenStorage:%p("
+ "%ws, %p, %lX, %p, %p, %p)\n", this, pwcsName, pstgPriority,
+ grfMode, snbExclude, reserved, ppstg));
+ return ssResult(STG_E_FILENOTFOUND);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::CopyTo, public
+//
+// Synopsis: Makes a copy of a storage
+//
+// Arguments: [ciidExclude] - Length of rgiid array
+// [rgiidExclude] - Array of IIDs to exclude
+// [snbExclude] - Names to exclude
+// [pstgDest] - Parent of copy
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::CopyTo(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest)
+{
+ SCODE sc;
+ SafeIStream pstm;
+ ULARGE_INTEGER cb;
+ ULONG i;
+ CDfName dfn;
+ SafeCNtFileStream pfs;
+ STATSTG stat;
+
+ ssDebugOut((DEB_TRACE, "In CFileStorage::CopyTo:%p(%lu, %p, %p, %p)\n",
+ this, ciidExclude, rgiidExclude, snbExclude, pstgDest));
+
+ ssChk(Validate());
+
+ // Copy class ID and state bits if the destination supports them
+ ssChk(Stat(&stat, STATFLAG_NONAME));
+ sc = GetScode(pstgDest->SetClass(stat.clsid));
+ if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
+ ssErr(EH_Err, sc);
+ sc = GetScode(pstgDest->SetStateBits(stat.grfStateBits, 0xffffffff));
+ if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
+ ssErr(EH_Err, sc);
+
+ // Check exclusions
+ dfn.Set(CONTENTS_STREAM);
+ if (snbExclude != NULL && NameInSNB(&dfn, snbExclude))
+ ssErr(EH_Err, S_OK);
+ for (i = 0; i < ciidExclude; i++)
+ if (IsEqualIID(rgiidExclude[i], IID_IStream))
+ ssErr(EH_Err, S_OK);
+
+ // CONTENTS_STREAM is the only thing contained by a file
+ // storage, so copy it
+
+ pfs.Attach(new CNtFileStream());
+ ssMem((CNtFileStream *)pfs);
+ ssAssert(_h != NULL);
+ ssChk(pfs->InitFromHandle(_h, STGM_DIRECT | STGM_READ |
+ STGM_SHARE_DENY_NONE, CO_OPEN, NULL));
+
+ ssChk(GetScode(pstgDest->CreateStream(CONTENTS_STREAM, STGM_DIRECT |
+ STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_CREATE,
+ 0, NULL, &pstm)));
+ cb.LowPart = cb.HighPart = 0xffffffff;
+ sc = GetScode(pfs->CopyTo(pstm, cb, NULL, NULL));
+
+ ssDebugOut((DEB_TRACE, "Out CFileStorage::CopyTo\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::MoveElementTo, public
+//
+// Synopsis: Move an element of a storage to another storage
+//
+// Arguments: [pwcsName] - Current name
+// [ptcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// Algorithm: Open source as storage or stream (whatever works)
+// Create appropriate destination
+// Copy source to destination
+// Set create time of destination equal to create time of source
+// If appropriate, delete source
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::MoveElementTo(WCHAR const *pwcsName,
+ IStorage *pstgParent,
+ WCHAR const *ptcsNewName,
+ DWORD grfFlags)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CFileStorage::MoveElementTo:%p("
+ "%ws, %p, %ws, %lu)\n", this, pwcsName, pstgParent,
+ ptcsNewName, grfFlags));
+
+ ssChk(Validate());
+ ssChk(VerifyMoveFlags(grfFlags));
+
+ sc = GenericMoveElement(this, pwcsName, pstgParent, ptcsNewName, grfFlags);
+
+ ssDebugOut((DEB_TRACE, "Out CFileStorage::MoveElementTo => %lX\n", sc));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::Commit, public
+//
+// Synopsis: Commits transacted changes
+//
+// Arguments: [dwFlags] - DFC_*
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::Commit(DWORD dwFlags)
+{
+ NTSTATUS nts;
+ SCODE sc;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_TRACE, "In CFileStorage::Commit:%p(%lX)\n",
+ this, dwFlags));
+
+ ssChk(VerifyCommitFlags(dwFlags));
+ ssChk(Validate());
+
+ ssAssert(_h != NULL);
+ nts = NtFlushBuffersFile(_h, &iosb);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_TRACE, "Out CFileStorage::Commit => %lX\n", sc));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::Revert, public
+//
+// Synopsis: Reverts transacted changes
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::Revert(void)
+{
+ ssDebugOut((DEB_TRACE, "Stb CFileStorage::Revert:%p()\n", this));
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::EnumElements, public
+//
+// Synopsis: Starts an iterator
+//
+// Arguments: [reserved1]
+// [reserved2]
+// [reserved3]
+// [ppenm] - Enumerator return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::EnumElements(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm)
+{
+ SCODE sc;
+ SafeCFileEnum pfe;
+
+ ssDebugOut((DEB_TRACE, "In CFileStorage::EnumElements:%p("
+ "%lu, %p, %lu, %p)\n", this, reserved1, reserved2,
+ reserved3, ppenm));
+
+ if (reserved1 != 0 || reserved2 != NULL || reserved3 != 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+
+ pfe.Attach(new CFileEnum());
+ ssMem((CFileEnum *)pfe);
+ ssAssert(_h != NULL);
+ ssChk(pfe->InitFromHandle(_h, FALSE));
+ TRANSFER_INTERFACE(pfe, IEnumSTATSTG, ppenm);
+
+ ssDebugOut((DEB_TRACE, "Out CFileStorage::EnumElements => %p\n",
+ *ppenm));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::DestroyElement, public
+//
+// Synopsis: Permanently deletes an element of a storage
+//
+// Arguments: [pwcsName] - Name of element
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::DestroyElement(WCHAR const *pwcsName)
+{
+ ssDebugOut((DEB_TRACE, "Stb CFileStorage::DestroyElement:%p(%ws)\n",
+ this, pwcsName));
+ if (lstrcmpiW(pwcsName, CONTENTS_STREAM) == 0)
+ return ssResult(STG_E_INVALIDFUNCTION);
+ else
+ return ssResult(STG_E_FILENOTFOUND);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::RenameElement, public
+//
+// Synopsis: Renames an element of a storage
+//
+// Arguments: [pwcsName] - Current name
+// [pwcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::RenameElement(WCHAR const *pwcsName,
+ WCHAR const *pwcsNewName)
+{
+ ssDebugOut((DEB_TRACE, "Stb CFileStorage::RenameElement:%p(%ws, %ws)\n",
+ this, pwcsName, pwcsNewName));
+ if (lstrcmpiW(pwcsName, CONTENTS_STREAM) == 0)
+ {
+ if (lstrcmpiW(pwcsNewName, CONTENTS_STREAM) == 0)
+ return ssResult(STG_E_ACCESSDENIED);
+ else
+ return ssResult(STG_E_INVALIDFUNCTION);
+ }
+ else
+ return ssResult(STG_E_FILENOTFOUND);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::SetElementTimes, public
+//
+// Synopsis: Sets element time stamps
+//
+// Arguments: [pwcsName] - Name
+// [pctime] - Create time
+// [patime] - Access time
+// [pmtime] - Modify time
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::SetElementTimes(WCHAR const *pwcsName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ ssDebugOut((DEB_TRACE, "Stb CFileStorage::SetElementTimes:%p("
+ "%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime));
+ if (lstrcmpiW(pwcsName, CONTENTS_STREAM) == 0)
+ return ssResult(STG_E_INVALIDFUNCTION);
+ else
+ return ssResult(STG_E_FILENOTFOUND);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::SetClass, public
+//
+// Synopsis: Sets storage class
+//
+// Arguments: [clsid] - class id
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::SetClass(REFCLSID clsid)
+{
+ ssDebugOut((DEB_TRACE, "Stb CFileStorage::SetClass:%p(clsid)\n", this));
+ return ssResult(STG_E_INVALIDFUNCTION);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::SetStateBits, public
+//
+// Synopsis: Sets state bits
+//
+// Arguments: [grfStateBits] - state bits
+// [grfMask] - state bits mask
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ ssDebugOut((DEB_TRACE, "Stb CFileStorage::SetStateBits:%p("
+ "%lu, %lu)\n", this, grfStateBits, grfMask));
+ return ssResult(STG_E_INVALIDFUNCTION);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StrToLong, private
+//
+// Synopsis: Converts a string to a long value
+//
+// Arguments: [pwcs] - String
+//
+// Returns: LONG
+//
+// History: 27-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+static LONG StrToLong(WCHAR *pwcs)
+{
+ LONG l = 0;
+
+ while (*pwcs >= L'0' && *pwcs <= L'9')
+ {
+ l = l*10+(int)*pwcs-(int)L'0';
+ pwcs++;
+ }
+ return l;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Matches, private
+//
+// Synopsis: Determines if a file signature matches the given pattern
+//
+// Arguments: [h] - File handle
+// [pwcsBuf] - Pattern
+// [cb] - Size of pattern
+//
+// Returns: Appropriate status code
+//
+// History: 27-Jul-93 DrewB Created from moniker code
+//
+//----------------------------------------------------------------------------
+
+static SCODE Matches(HANDLE h, WCHAR *pwcsBuf, ULONG cb)
+{
+ // Parse <offset>,<cb>,<mask>,<pattern>
+ WCHAR *pwcs = pwcsBuf;
+ WCHAR *pwcsMask, *pwcsPattern;
+ int nOffset;
+ WORD wCb;
+ WORD wCtr;
+ BYTE bMask;
+ BYTE bPattern;
+ SafeBytePtr pbFileContents;
+ IO_STATUS_BLOCK iosb;
+ FILE_POSITION_INFORMATION fpi;
+ NTSTATUS nts;
+ LARGE_INTEGER liOriginalPos;
+ SCODE sc = S_FALSE;
+
+ PUSHORT pCharTypes = _alloca (sizeof (USHORT) * cb);
+ if (pCharTypes == NULL || !GetStringTypeW (CT_CTYPE1, pwcs, cb, pCharTypes)) {
+ goto EH_Err;
+
+ nOffset = (WORD)StrToLong(pwcs);
+ while (*pwcs && *pwcs != L',')
+ pwcs++;
+ ssAssert(*pwcs == L',');
+ pwcs++;
+
+ wCb = (WORD)StrToLong(pwcs);
+ ssAssert(wCb > 0);
+ while (*pwcs && *pwcs != L',')
+ pwcs++;
+ ssAssert(*pwcs == L',');
+ pwcs++;
+
+ while (pCharTypes[pwcs - pwcsBuf] & C1_SPACE)
+ pwcs++;
+
+ // pwcsMask points to the beginning of the mask
+ pwcsMask = pwcs;
+ pwcsPattern = pwcsMask;
+ while (*pwcsPattern && *pwcsPattern != L',')
+ pwcsPattern++;
+ ssAssert(*pwcsPattern == L',');
+ pwcsPattern++;
+ while (pCharTypes[pwcsPattern - pwcsBuf] & C1_SPACE)
+ pwcsPattern++;
+
+ pbFileContents.Attach(new BYTE[wCb]);
+ ssMem((BYTE *)pbFileContents);
+
+ // Remember the current file position
+ nts = NtQueryInformationFile(h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+ liOriginalPos = fpi.CurrentByteOffset;
+
+ // We seek to zero if necessary since we may have read from the file before
+ if (nOffset >= 0)
+ {
+ fpi.CurrentByteOffset.LowPart = (ULONG)nOffset;
+ fpi.CurrentByteOffset.HighPart = 0;
+ nts = NtSetInformationFile(h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Seek, NtStatusToScode(nts));
+ }
+ else if (nOffset < 0)
+ {
+ fpi.CurrentByteOffset.HighPart = -1;
+ fpi.CurrentByteOffset.LowPart = (ULONG)nOffset;
+ fpi.CurrentByteOffset.QuadPart =
+ fpi.CurrentByteOffset.QuadPart + liOriginalPos.QuadPart;
+ nts = NtSetInformationFile(h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Seek, NtStatusToScode(nts));
+ }
+
+ nts = NtReadFile(h, NULL, NULL, NULL, &iosb, pbFileContents, wCb,
+ NULL, NULL);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Seek, NtStatusToScode(nts));
+
+ if (wCb == iosb.Information)
+ {
+ for (wCtr = 0; wCtr < wCb; wCtr++)
+ {
+ // Get the mask byte, 0xFF is the default
+ bMask = 0xFF;
+ if (pCharTypes[pwcsMask - pwcsBuf] & C1_XDIGIT)
+ {
+ bMask = pCharTypes[pwcsMask - pwcsBuf] & C1_DIGIT ? *pwcsMask - L'0' :
+ (WCHAR)CharUpperW((LPWSTR)*pwcsMask) - L'A' + 10;
+ pwcsMask++;
+ if (pCharTypes[pwcsMask - pwcsBuf] & C1_XDIGIT)
+ {
+ bMask *= 16;
+ bMask += pCharTypes[pwcsMask - pwcsBuf] & C1_DIGIT ? *pwcsMask - L'0' :
+ (WCHAR)CharUpperW((LPWSTR)*pwcsMask) - L'A' + 10;
+ pwcsMask++;
+ }
+ }
+ // Get the pattern byte
+ ssAssert(pCharTypes[pwcsPattern - pwcsBuf] & C1_XDIGIT);
+ bPattern = pCharTypes[pwcsPattern - pwcsBuf] & C1_DIGIT ? *pwcsPattern - L'0' :
+ (WCHAR)CharUpperW((LPWSTR)*pwcsPattern) - L'A' + 10;
+ pwcsPattern++;
+ ssAssert(pCharTypes[pwcsPattern - pwcsBuf] & C1_XDIGIT);
+ bPattern *= 16;
+ bPattern += pCharTypes[pwcsPattern - pwcsBuf] & C1_DIGIT ? *pwcsPattern - L'0' :
+ (WCHAR)CharUpperW((LPWSTR)*pwcsPattern) - L'A' + 10;
+ pwcsPattern++;
+
+ if ((BYTE)(*((BYTE *)pbFileContents + wCtr) & bMask) != bPattern)
+ ssErr(EH_Seek, S_FALSE);
+ }
+ sc = S_OK;
+ }
+
+ EH_Seek:
+ // Can't do anything about failure
+ fpi.CurrentByteOffset = liOriginalPos;
+ NtSetInformationFile(h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoesMatchPattern, private
+//
+// Synopsis: Determines whether the given file matches its registry pattern
+//
+// Arguments: [h] - File handle
+// [pclsid] - CLSID return if successful
+//
+// Returns: Appropriate status code
+//
+// History: 27-Jul-93 DrewB Created from moniker code
+//
+//----------------------------------------------------------------------------
+
+#define CB_DEF_BUFF 80
+#define CB_DEF_NUM 10
+#define CB_DEF_PATTERN 1024
+
+SAFE_HEAP_MEMPTR(SafeWcharPtr, WCHAR);
+
+static SCODE DoesMatchPattern(HANDLE h, CLSID *pclsid)
+{
+ DWORD dwIndexClsid;
+ DWORD dwIndexPattern;
+ HKEY hkFileType;
+ HKEY hkClsid;
+ DWORD cbBuff = CB_DEF_BUFF;
+ DWORD cbNum = CB_DEF_NUM;
+ DWORD cbPattern = CB_DEF_PATTERN;
+ ULONG cb;
+ SafeWcharPtr pwcsBuff;
+ SafeWcharPtr pwcsPattern;
+ SafeWcharPtr pwcsNum;
+ SCODE sc = S_FALSE;
+
+ pwcsBuff.Attach(new TCHAR[CB_DEF_BUFF]);
+ ssMem((WCHAR *)pwcsBuff);
+ pwcsPattern.Attach(new TCHAR[CB_DEF_PATTERN]);
+ ssMem((WCHAR *)pwcsPattern);
+ pwcsNum.Attach(new TCHAR[CB_DEF_NUM]);
+ ssMem((WCHAR *)pwcsNum);
+
+ if (RegOpenKey(HKEY_CLASSES_ROOT, L"FileType", &hkFileType) ==
+ ERROR_SUCCESS)
+ {
+ for (dwIndexClsid = 0;
+ sc == S_FALSE &&
+ RegEnumKey(hkFileType, dwIndexClsid, pwcsBuff, cbBuff) ==
+ ERROR_SUCCESS;
+ ++dwIndexClsid)
+ {
+ if (RegOpenKey(hkFileType, pwcsBuff, &hkClsid) == ERROR_SUCCESS)
+ {
+ for (dwIndexPattern = 0;
+ RegEnumKey(hkClsid, dwIndexPattern, pwcsNum, cbNum) ==
+ ERROR_SUCCESS;
+ ++dwIndexPattern)
+ {
+ cb = cbPattern;
+ if (RegQueryValue(hkClsid, pwcsNum, pwcsPattern,
+ (LONG *)&cb) == ERROR_SUCCESS)
+ {
+ sc = Matches(h, pwcsPattern, cbPattern);
+ if (sc == S_OK)
+ CLSIDFromString(pwcsBuff, pclsid);
+ if (sc != S_FALSE)
+ break;
+ }
+ }
+ RegCloseKey(hkClsid);
+ }
+ }
+ RegCloseKey(hkFileType);
+ }
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::Stat, public
+//
+// Synopsis: Fills in a buffer of information about this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+ STATSTG stat;
+ FILEDIR fd;
+ CLSID clsid;
+ WCHAR awcName[MAX_PATH];
+
+ ssDebugOut((DEB_TRACE, "In CFileStorage::Stat:%p(%p, %lX)\n",
+ this, pstatstg, grfStatFlag));
+
+ ssChk(VerifyStatFlag(grfStatFlag));
+ ssChk(Validate());
+
+ __try
+ {
+ ssAssert(_h != NULL);
+ sc = StatNtHandle(_h, grfStatFlag, 0, &stat, awcName, NULL, &fd);
+ if (SUCCEEDED(sc))
+ {
+ // Attempt to get a CLSID for this file
+ sc = DoesMatchPattern(_h, &clsid);
+ if (sc == S_FALSE)
+ {
+ WCHAR *pwcsExt;
+
+ // No pattern matched, so look up the class by extension
+ pwcsExt = FindExt(awcName);
+ if (pwcsExt != NULL && wCoGetClassExt(pwcsExt, &clsid) == 0)
+ sc = S_OK;
+ }
+ if (sc == S_OK)
+ stat.clsid = clsid;
+ if (SUCCEEDED(sc))
+ {
+ stat.grfMode = _grfMode;
+ stat.cbSize.HighPart = stat.cbSize.LowPart = 0;
+ stat.STATSTG_dwStgFmt = STGFMT_FILE;
+ *pstatstg = stat;
+ sc = S_OK;
+ }
+ else if (stat.pwcsName)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (stat.pwcsName)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ sc = HRESULT_FROM_NT(GetExceptionCode());
+ }
+
+ ssDebugOut((DEB_TRACE, "Out CFileStorage::Stat\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::ValidateMode, private
+//
+// Synopsis: Validates a grfMode
+//
+// Arguments: [grfMode] - Mode
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CFileStorage::ValidateMode(DWORD grfMode)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CFileStorage::ValidateMode:%p(0x%lX)\n",
+ this, grfMode));
+ // BUGBUG - Can we simply ignore priority mode?
+ if (grfMode & (STGM_TRANSACTED | STGM_CONVERT))
+ sc = STG_E_INVALIDFLAG;
+ else
+ sc = S_OK;
+ ssDebugOut((DEB_ITRACE, "Out CFileStorage::ValidateMode => 0x%lX\n", sc));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStorage::GetHandle, private
+//
+// Synopsis: Get the handle backing this Storage.
+//
+// History: 10-May-94 BillMo Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileStorage::GetHandle(HANDLE *ph)
+{
+ SCODE sc;
+
+ ssChk(Validate());
+
+ *ph = _h;
+
+EH_Err:
+ return(ssResult(sc));
+}
diff --git a/private/ole32/stg/fsstg/filstg.hxx b/private/ole32/stg/fsstg/filstg.hxx
new file mode 100644
index 000000000..18410d6f2
--- /dev/null
+++ b/private/ole32/stg/fsstg/filstg.hxx
@@ -0,0 +1,136 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: filstg.hxx
+//
+// Contents: CFileStorage header
+//
+// Classes: CFileStorage
+//
+// History: 28-Jun-93 DrewB Created
+//
+// Notes: Non-OFS
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FILSTG_HXX__
+#define __FILSTG_HXX__
+
+#include <otrack.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: CFileStorage (fs)
+//
+// Purpose: Implements IStorage for a file
+//
+// Interface: See below
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+interface CFileStorage
+ : INHERIT_TRACKING,
+ public IStorage,
+ public INativeFileSystem
+{
+public:
+ CFileStorage(void);
+ SCODE InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSECURITY_ATTRIBUTES pssSecurity);
+ SCODE InitFromHandle(HANDLE h, DWORD grfMode);
+ ~CFileStorage(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // IStorage
+ STDMETHOD(CreateStream)(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(OpenStream)(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(CreateStorage)(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD stgType,
+ LPSTGSECURITY pssSecurity,
+ IStorage **ppstg);
+ STDMETHOD(OpenStorage)(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg);
+ STDMETHOD(CopyTo)(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest);
+ STDMETHOD(MoveElementTo)(WCHAR const *lpszName,
+ IStorage *pstgDest,
+ WCHAR const *lpszNewName,
+ DWORD grfFlags);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(EnumElements)(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm);
+ STDMETHOD(DestroyElement)(WCHAR const *pwcsName);
+ STDMETHOD(RenameElement)(WCHAR const *pwcsOldName,
+ WCHAR const *pwcsNewName);
+ STDMETHOD(SetElementTimes)(const WCHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+ STDMETHOD(SetClass)(REFCLSID clsid);
+ STDMETHOD(SetStateBits)(DWORD grfStateBits, DWORD grfMask);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+
+ // INativeFileSystem
+ STDMETHOD(GetHandle(HANDLE *ph));
+
+private:
+ inline SCODE Validate(void) const;
+ SCODE ValidateMode(DWORD grfMode);
+
+ ULONG _sig;
+ NuSafeNtHandle _h;
+ DWORD _grfMode;
+};
+
+SAFE_INTERFACE_PTR(SafeCFileStorage, CFileStorage);
+
+#define CFILESTORAGE_SIG LONGSIG('F', 'S', 'T', 'G')
+#define CFILESTORAGE_SIGDEL LONGSIG('F', 's', 'T', 'g')
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStorage::Validate, private
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 28-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CFileStorage::Validate(void) const
+{
+ return (this == NULL || _sig != CFILESTORAGE_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+#endif // #ifndef __FILSTG_HXX__
diff --git a/private/ole32/stg/fsstg/filstm.cxx b/private/ole32/stg/fsstg/filstm.cxx
new file mode 100644
index 000000000..c04ca7ed9
--- /dev/null
+++ b/private/ole32/stg/fsstg/filstm.cxx
@@ -0,0 +1,965 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: filstm.cxx
+//
+// Contents: CNtFileStream implementation
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include "filstm.hxx"
+
+#define ValidateLockType(lt) \
+ ((lt) == LOCK_EXCLUSIVE || (lt) == LOCK_ONLYONCE)
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CNtFileStream::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CNtFileStream::QueryInterface:%p(riid, %p)\n",
+ this, ppvObj));
+ if (!IsValidIid(iid))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+ if (IsEqualIID(iid, IID_IStream) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IStream *)this;
+ CNtFileStream::AddRef();
+ }
+ else if(IsEqualIID(iid, IID_IOverlappedStream))
+ {
+ *ppvObj = (IOverlappedStream *) this;
+ CNtFileStream::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppvObj = NULL;
+ }
+ ssDebugOut((DEB_TRACE, "Out CNtFileStream::QueryInterface => %p\n",
+ *ppvObj));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::CNtFileStream, public
+//
+// Synopsis: Empty object constructor
+//
+// History: 30-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CNtFileStream::CNtFileStream(void)
+{
+ ssDebugOut((DEB_ITRACE, "In CNtFileStream::CNtFileStream:%p()\n", this));
+ _sig = 0;
+ ssDebugOut((DEB_ITRACE, "Out CNtFileStream::CNtFileStream\n"));
+ ENLIST_TRACKING(CNtFileStream);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::InitCommon, private
+//
+// Synopsis: Common initialization code
+//
+// Arguments: [co] - For detecting creation flags
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CNtFileStream::InitCommon(CREATEOPEN co)
+{
+ NTSTATUS nts;
+ SCODE sc;
+ IO_STATUS_BLOCK iosb;
+ FILE_POSITION_INFORMATION fpi;
+ FILE_END_OF_FILE_INFORMATION feofi;
+
+ ssDebugOut((DEB_ITRACE, "In CNtFileStream::InitCommon:%p(%d)\n",
+ this, co));
+
+ // If we're supposed to be creating, truncate
+ // STGM_CREATE must have been passed since FAILIFTHERE always will fail
+ if (co == CO_CREATE)
+ {
+ feofi.EndOfFile.LowPart = 0;
+ feofi.EndOfFile.HighPart = 0;
+ nts = NtSetInformationFile(_h, &iosb, &feofi,
+ sizeof(FILE_END_OF_FILE_INFORMATION),
+ FileEndOfFileInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+ }
+
+ // Make sure the file pointer is at zero
+ fpi.CurrentByteOffset.LowPart = 0;
+ fpi.CurrentByteOffset.HighPart = 0;
+ nts = NtSetInformationFile(_h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_ITRACE, "Out CNtFileStream::InitCommon\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::InitFromHandle, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [h] - Handle to duplicate
+// [grfMode] - Mode of handle
+//
+// Returns: Appropriate status code
+//
+// History: 08-Jul-93 DrewB Created
+//
+// Notes: Takes a new reference on the given handle
+//
+//----------------------------------------------------------------------------
+
+SCODE CNtFileStream::InitFromHandle(HANDLE h,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSTGSECURITY pssSecurity)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CNtFileStream::InitFromHandle:%p("
+ "%p, %lX, %d, %p)\n", this, h, grfMode, co, pssSecurity));
+
+ ssChk(ValidateMode(grfMode));
+ if (pssSecurity != NULL)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(ReopenNtHandle(h, grfMode, FD_FILE, &_h));
+
+ ssAssert(co != CO_CREATE || (grfMode & STGM_CREATE));
+ ssChk(InitCommon(co));
+
+ _grfMode = grfMode;
+ _sig = CNTFILESTREAM_SIG;
+
+ ssDebugOut((DEB_ITRACE, "Out CNtFileStream::InitFromHandle\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::InitFromPath, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [h] - Handle to duplicate
+// [grfMode] - Mode of handle
+//
+// Returns: Appropriate status code
+//
+// History: 08-Jul-95 HenryLee Created
+//
+// Notes: Takes a new reference on the given handle
+//
+//----------------------------------------------------------------------------
+
+SCODE CNtFileStream::InitFromPath(HANDLE hParent,
+ const WCHAR *pwcsName,
+ DWORD grfMode,
+ DWORD grfAttr,
+ CREATEOPEN co,
+ LPSTGSECURITY pssSecurity)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CNtFileStream::InitFromPath:%p("
+ "%p, %lX, %ws, %d, %p)\n", this, hParent, pwcsName,
+ grfMode, co, pssSecurity));
+
+ ssChk(ValidateMode(grfMode));
+ if (pssSecurity != NULL)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(GetNtHandle(hParent, pwcsName, grfMode, grfAttr, co, FD_FILE,
+ (LPSECURITY_ATTRIBUTES) pssSecurity,&_h));
+
+ //ssAssert(co != CO_CREATE || (grfMode & STGM_CREATE));
+ ssChk(InitCommon(co));
+
+ _grfMode = grfMode;
+ _sig = CNTFILESTREAM_SIG;
+
+ ssDebugOut((DEB_ITRACE, "Out CNtFileStream::InitFromPath\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::InitClone, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [h] - Handle to duplicate
+// [grfMode] - Mode of handle
+//
+// Returns: Appropriate status code
+//
+// History: 08-Jul-93 DrewB Created
+//
+// Notes: Takes a new reference on the given handle
+//
+//----------------------------------------------------------------------------
+
+SCODE CNtFileStream::InitClone(HANDLE h, DWORD grfMode)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CNtFileStream::InitClone:%p(%p, %lX)\n",
+ this, h, grfMode));
+
+ ssChk(ValidateMode(grfMode));
+ ssChk(DupNtHandle(h, &_h));
+
+ _grfMode = grfMode;
+ _sig = CNTFILESTREAM_SIG;
+
+ ssDebugOut((DEB_ITRACE, "Out CNtFileStream::InitClone\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::~CNtFileStream, public
+//
+// Synopsis: Destructor
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CNtFileStream::~CNtFileStream(void)
+{
+ ssDebugOut((DEB_ITRACE, "In CNtFileStream::~CNtFileStream:%p()\n", this));
+ _sig = CNTFILESTREAM_SIGDEL;
+ ssDebugOut((DEB_ITRACE, "Out CNtFileStream::~CNtFileStream\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::Read, public
+//
+// Synopsis: Read from a stream
+//
+// Arguments: [pb] - Buffer
+// [cb] - Count of bytes to read
+// [pcbRead] - Return number of bytes read
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CNtFileStream::Read(VOID *pb, ULONG cb, ULONG *pcbRead)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_TRACE, "In CNtFileStream::Read:%p(%p, %lu, %p)\n",
+ this, pb, cb, pcbRead));
+
+ sc = S_OK;
+ ssChk(Validate());
+
+ ssAssert(_h != NULL);
+ nts = NtReadFile(_h, NULL, NULL, NULL, &iosb, pb, cb, NULL, NULL);
+ if (!NT_SUCCESS(nts))
+ {
+ if (nts != STATUS_END_OF_FILE)
+ sc = NtStatusToScode(nts);
+ else
+ iosb.Information = 0;
+ }
+ if (pcbRead)
+ {
+ if (SUCCEEDED(sc))
+ *pcbRead = iosb.Information;
+ else
+ *pcbRead = 0;
+ }
+
+ ssDebugOut((DEB_TRACE, "Out CNtFileStream::Read => %lu\n",
+ iosb.Information));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::Write, public
+//
+// Synopsis: Write to a stream
+//
+// Arguments: [pb] - Buffer
+// [cb] - Count of bytes to write
+// [pcbWritten] - Return of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbWritten]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CNtFileStream::Write(VOID const *pb,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_TRACE, "In CNtFileStream::Write:%p(%p, %lu, %p)\n",
+ this, pb, cb, pcbWritten));
+
+ sc = S_OK;
+ ssChk(Validate());
+
+ ssAssert(_h != NULL);
+ nts = NtWriteFile(_h, NULL, NULL, NULL, &iosb, (void *)pb, cb,
+ NULL, NULL);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ if (pcbWritten)
+ {
+ if (SUCCEEDED(sc))
+ *pcbWritten = iosb.Information;
+ else
+ *pcbWritten = 0;
+ }
+
+ ssDebugOut((DEB_TRACE, "Out CNtFileStream::Write => %lu\n",
+ iosb.Information));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::Seek, public
+//
+// Synopsis: Seek to a point in a stream
+//
+// Arguments: [dlibMove] - Offset to move by
+// [dwOrigin] - SEEK_SET, SEEK_CUR, SEEK_END
+// [plibNewPosition] - Return of new offset
+//
+// Returns: Appropriate status code
+//
+// Modifies: [plibNewPosition]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CNtFileStream::Seek(LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+ FILE_POSITION_INFORMATION fpi;
+ FILE_STANDARD_INFORMATION fsi;
+
+ ssDebugOut((DEB_TRACE, "In CNtFileStream::Seek:%p(%ld:%ld, %lu, %p)\n",
+ this, dlibMove.HighPart, dlibMove.LowPart, dwOrigin,
+ plibNewPosition));
+
+ if (dwOrigin != STREAM_SEEK_SET && dwOrigin != STREAM_SEEK_CUR &&
+ dwOrigin != STREAM_SEEK_END)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+
+ ssAssert(_h != NULL);
+ switch(dwOrigin)
+ {
+ case STREAM_SEEK_SET:
+ fpi.CurrentByteOffset.LowPart = dlibMove.LowPart;
+ fpi.CurrentByteOffset.HighPart = dlibMove.HighPart;
+ break;
+
+ case STREAM_SEEK_CUR:
+ nts = NtQueryInformationFile(_h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+
+ // Check for seek before beginning and overflow
+ if (dlibMove.HighPart < 0)
+ {
+ if ((-dlibMove.QuadPart) > fpi.CurrentByteOffset.QuadPart)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+ }
+ else if (!((fpi.CurrentByteOffset.QuadPart + dlibMove.QuadPart) >=
+ fpi.CurrentByteOffset.QuadPart))
+ {
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+ }
+
+ fpi.CurrentByteOffset.QuadPart =
+ fpi.CurrentByteOffset.QuadPart + dlibMove.QuadPart;
+ break;
+
+ case STREAM_SEEK_END:
+ nts = NtQueryInformationFile(_h, &iosb, &fsi,
+ sizeof(FILE_STANDARD_INFORMATION),
+ FileStandardInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+
+ // Check for seek before beginning and overflow
+ if (dlibMove.HighPart < 0)
+ {
+ if ((-dlibMove.QuadPart) > fsi.EndOfFile.QuadPart)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+ }
+ else if (!((fsi.EndOfFile.QuadPart + dlibMove.QuadPart) >=
+ fsi.EndOfFile.QuadPart))
+ {
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+ }
+
+ fpi.CurrentByteOffset.QuadPart =
+ fsi.EndOfFile.QuadPart + dlibMove.QuadPart;
+ break;
+ }
+
+ sc = S_OK;
+ nts = NtSetInformationFile(_h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else if (plibNewPosition)
+ *plibNewPosition = *(ULARGE_INTEGER *)&fpi.CurrentByteOffset;
+
+ ssDebugOut((DEB_TRACE, "Out CNtFileStream::Seek => %lu:%lu\n",
+ fpi.CurrentByteOffset.HighPart,
+ fpi.CurrentByteOffset.LowPart));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::SetSize, public
+//
+// Synopsis: Sets the size of a stream
+//
+// Arguments: [ulNewSize] - New size
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CNtFileStream::SetSize(ULARGE_INTEGER ulNewSize)
+{
+ SCODE sc;
+ IO_STATUS_BLOCK iosb;
+ FILE_END_OF_FILE_INFORMATION feofi;
+ NTSTATUS nts;
+
+ ssDebugOut((DEB_TRACE, "In CNtFileStream::SetSize:%p(%lu:%lu)\n",
+ this, ulNewSize.HighPart, ulNewSize.LowPart));
+
+ sc = S_OK;
+ ssChk(Validate());
+
+ feofi.EndOfFile.LowPart = ulNewSize.LowPart;
+ feofi.EndOfFile.HighPart = (ULONG)ulNewSize.HighPart;
+ ssAssert(_h != NULL);
+ nts = NtSetInformationFile(_h, &iosb, &feofi,
+ sizeof(FILE_END_OF_FILE_INFORMATION),
+ FileEndOfFileInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+
+ ssDebugOut((DEB_TRACE, "Out CNtFileStream::SetSize\n"));
+
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::CopyTo, public
+//
+// Synopsis: Copies information from one stream to another
+//
+// Arguments: [pstm] - Destination
+// [cb] - Number of bytes to copy
+// [pcbRead] - Return number of bytes read
+// [pcbWritten] - Return number of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+// [pcbWritten]
+//
+// History: 28-Jun-93 DrewB Created
+//
+// Notes: We do our best to handle overlap correctly. This allows
+// CopyTo to be used to insert and remove space within a
+// stream.
+//
+// In the error case, we make no gurantees as to the
+// validity of pcbRead, pcbWritten, or either stream's
+// seek position.
+//
+//----------------------------------------------------------------------------
+
+#define CBBUFFER 8192
+
+STDMETHODIMP CNtFileStream::CopyTo(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten)
+{
+ SCODE sc;
+ LARGE_INTEGER cbRead = {0, 0}, cbWritten = {0, 0}, cbDone;
+ LARGE_INTEGER liPosFrom, liPosTo, liTmp;
+ LARGE_INTEGER liZero = {0, 0};
+ LARGE_INTEGER liStep;
+ LARGE_INTEGER licb;
+ BOOL fForward;
+ ULONG ulcbDone, cbDo;
+ SafeBytePtr pbBuffer;
+
+ ssDebugOut((DEB_TRACE, "In CNtFileStream::CopyTo:%p("
+ "%p, %lu:%lu, %p, %p)\n",
+ this, pstm, cb.HighPart, cb.LowPart, pcbRead, pcbWritten));
+
+ // BUGBUG - Possible 63-bit overflow problems?
+
+ if (!IsValidInterface(pstm))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ sc = S_OK;
+ ssChk(Validate());
+
+ if (cb.HighPart >= 0x80000000)
+ cb.HighPart = 0x7fffffff;
+ licb = *(LARGE_INTEGER *)&cb;
+
+ pbBuffer.Attach(new BYTE[CBBUFFER]);
+ ssMem((BYTE *)pbBuffer);
+
+ ssHChk(Seek(liZero, STREAM_SEEK_CUR, (ULARGE_INTEGER *)&liPosFrom));
+ ssHChk(pstm->Seek(liZero, STREAM_SEEK_CUR,
+ (ULARGE_INTEGER *)&liPosTo));
+
+ // Determine which direction to copy to avoid overlap problems
+ if (!(liPosFrom.QuadPart >= liPosTo.QuadPart) &&
+ (licb.QuadPart > liStep.QuadPart))
+ {
+ liStep.HighPart = -1;
+ liStep.LowPart = (ULONG)(-CBBUFFER);
+ fForward = FALSE;
+
+ // Seek to the end of the copy area plus one step
+ // so that we're in place for the loop seek backwards
+ liTmp.QuadPart = liPosFrom.QuadPart + licb.QuadPart;
+ liTmp.QuadPart = liTmp.QuadPart - liStep.QuadPart;
+ ssHChk(Seek(liTmp, STREAM_SEEK_SET, NULL));
+ liTmp.QuadPart = liPosTo.QuadPart + licb.QuadPart;
+ liTmp.QuadPart = liTmp.QuadPart - liStep.QuadPart;
+ ssHChk(pstm->Seek(liTmp, STREAM_SEEK_SET, NULL));
+
+ // We seek backwards by twice the step size, once
+ // to back up beyond the step we just read and once
+ // more to back up to a fresh step worth of data
+ ssAssert(CBBUFFER <= 0x3fffffff);
+ liStep.LowPart *= 2;
+ }
+ else
+ {
+ liStep.HighPart = 0;
+ liStep.LowPart = CBBUFFER;
+ fForward = TRUE;
+ }
+
+ cbDone.HighPart = 0;
+ for (;;)
+ {
+ if (licb.HighPart == 0 && licb.LowPart < CBBUFFER)
+ cbDo = licb.LowPart;
+ else
+ cbDo = CBBUFFER;
+
+ if (!fForward)
+ {
+ // If we're doing the last fragment make sure we don't overshoot
+ // when backing up
+ if (cbDo < CBBUFFER)
+ {
+ liStep.LowPart /= 2;
+ liStep.LowPart -= CBBUFFER-(LONG)cbDo;
+ }
+
+ // Seek backwards to fresh data
+ ssHChkTo(EH_End, Seek(liStep, STREAM_SEEK_CUR, NULL));
+ ssHChkTo(EH_End, pstm->Seek(liStep, STREAM_SEEK_CUR, NULL));
+ }
+
+ ssHChkTo(EH_End, Read(pbBuffer, cbDo, &cbDone.LowPart));
+ if (cbDone.LowPart == 0)
+ break;
+ cbRead.QuadPart = cbRead.QuadPart + cbDone.QuadPart;
+ ssHChkTo(EH_End, pstm->Write(pbBuffer, cbDone.LowPart,
+ &ulcbDone));
+ if (ulcbDone != cbDone.LowPart)
+ ssErr(EH_End, STG_E_WRITEFAULT);
+ cbWritten.QuadPart = cbWritten.QuadPart + cbDone.QuadPart;
+
+ licb.QuadPart = licb.QuadPart - cbDone.QuadPart;
+ if (licb.HighPart < 0 ||
+ (licb.HighPart == 0 && licb.LowPart == 0))
+ break;
+ }
+
+ EH_End:
+ if (pcbRead)
+ *(LARGE_INTEGER *)pcbRead = cbRead;
+ if (pcbWritten)
+ *(LARGE_INTEGER *)pcbWritten = cbWritten;
+
+ ssDebugOut((DEB_TRACE, "Out CNtFileStream::CopyTo => %lu:%lu, %lu:%lu\n",
+ cbRead.HighPart, cbRead.LowPart, cbWritten.HighPart,
+ cbWritten.LowPart));
+ // Fall through
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::Commit, public
+//
+// Synopsis: Commits transacted changes
+//
+// Arguments: [grfCommitFlags] - Flags
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CNtFileStream::Commit(DWORD grfCommitFlags)
+{
+ NTSTATUS nts;
+ SCODE sc;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_TRACE, "In CNtFileStream::Commit:%p(%lX)\n",
+ this, grfCommitFlags));
+
+ ssChk(VerifyCommitFlags(grfCommitFlags));
+ ssChk(Validate());
+
+ ssAssert(_h != NULL);
+ nts = NtFlushBuffersFile(_h, &iosb);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_TRACE, "Out CNtFileStream::Commit => %lX\n", sc));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::Revert, public
+//
+// Synopsis: Reverts transacted changes
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CNtFileStream::Revert(void)
+{
+ ssDebugOut((DEB_TRACE, "Stb CNtFileStream::Revert()\n"));
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::LockRegion, public
+//
+// Synopsis: Locks a portion of the stream
+//
+// Arguments: [libOffset] - Offset to lock at
+// [cb] - Length of lock
+// [dwLockType] - LockType
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CNtFileStream::LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_TRACE, "In CNtFileStream::LockRegion:%p("
+ "%lu:%lu, %lu:%lu, %lu)\n", this, libOffset.HighPart,
+ libOffset.LowPart, cb.HighPart, cb.LowPart, dwLockType));
+
+ sc = S_OK;
+ ssChk(Validate());
+ ssChk(ValidateLockType(dwLockType));
+
+ ssAssert(_h != NULL);
+ nts = NtLockFile(_h, NULL, NULL, NULL, &iosb, (PLARGE_INTEGER)&libOffset,
+ (PLARGE_INTEGER)&cb, 0, TRUE, TRUE);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_TRACE, "Out CNtFileStream::LockRegion\n"));
+
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::UnlockRegion, public
+//
+// Synopsis: Unlocks a locked region
+//
+// Arguments: [libOffset] - Offset to lock at
+// [cb] - Length of lock
+// [dwLockType] - LockType
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CNtFileStream::UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_TRACE, "In CNtFileStream::UnlockRegion:%p("
+ "%lu:%lu, %lu:%lu, %lu)\n", this, libOffset.HighPart,
+ libOffset.LowPart, cb.HighPart, cb.LowPart, dwLockType));
+
+ sc = S_OK;
+ ssChk(Validate());
+ ssChk(ValidateLockType(dwLockType));
+
+ ssAssert(_h != NULL);
+ nts = NtUnlockFile(_h, &iosb, (PLARGE_INTEGER)&libOffset,
+ (PLARGE_INTEGER)&cb, 0);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_TRACE, "Out CNtFileStream::UnlockRegion\n"));
+
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::Stat, public
+//
+// Synopsis: Fills in a buffer of information about this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CNtFileStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+ STATSTG stat;
+ FILEDIR fd;
+
+ ssDebugOut((DEB_TRACE, "In CNtFileStream::Stat:%p(%p, %lX)\n",
+ this, pstatstg, grfStatFlag));
+
+ ssChk(VerifyStatFlag(grfStatFlag));
+ ssChk(Validate());
+
+ __try
+ {
+ // \CONTENTS must be appended to name
+ ssAssert(_h != NULL);
+ sc = StatNtHandle(_h, grfStatFlag,
+ sizeof(CONTENTS_STREAM)+sizeof(WCHAR), &stat,
+ NULL, NULL, &fd);
+ if (SUCCEEDED(sc))
+ {
+ if (stat.pwcsName)
+ {
+ WCHAR *pwcs;
+
+ pwcs = stat.pwcsName+lstrlenW(stat.pwcsName);
+ *pwcs++ = L'\\';
+ lstrcpyW(pwcs, CONTENTS_STREAM);
+ }
+ stat.grfMode = _grfMode;
+ stat.type = STGTY_STREAM;
+ stat.mtime.dwLowDateTime = stat.mtime.dwHighDateTime = 0;
+ stat.atime.dwLowDateTime = stat.atime.dwHighDateTime = 0;
+ stat.ctime.dwLowDateTime = stat.ctime.dwHighDateTime = 0;
+ stat.grfLocksSupported = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
+ *pstatstg = stat;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (stat.pwcsName)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ sc = HRESULT_FROM_NT(GetExceptionCode());
+ }
+
+ ssDebugOut((DEB_TRACE, "Out CNtFileStream::Stat\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::Clone, public
+//
+// Synopsis: Clones a stream
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CNtFileStream::Clone(IStream **ppstm)
+{
+ SCODE sc;
+ SafeCNtFileStream pfs;
+
+ ssDebugOut((DEB_TRACE, "In CNtFileStream::Clone:%p(%p)\n",
+ this, ppstm));
+
+ sc = S_OK;
+ ssChk(Validate());
+
+ pfs.Attach(new CNtFileStream());
+ ssMem((CNtFileStream *)pfs);
+ ssAssert(_h != NULL);
+ ssChk(pfs->InitClone(_h, _grfMode));
+ TRANSFER_INTERFACE(pfs, IStream, ppstm);
+
+ ssDebugOut((DEB_TRACE, "Out CNtFileStream::Clone => %p\n", *ppstm));
+
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtFileStream::ValidateMode, private
+//
+// Synopsis: Validates a mode
+//
+// Arguments: [grfMode] - Mode
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jul-93 DrewB Created
+//
+// Notes: Streams allow any sharing permissions but ignore all of them
+//
+//----------------------------------------------------------------------------
+
+SCODE CNtFileStream::ValidateMode(DWORD grfMode)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CNtFileStream::ValidateMode:%p(0x%lX)\n",
+ this, grfMode));
+ if ((grfMode & (STGM_TRANSACTED | STGM_PRIORITY | STGM_DELETEONRELEASE |
+ STGM_CONVERT)))
+ sc = STG_E_INVALIDFLAG;
+ else
+ sc = S_OK;
+ ssDebugOut((DEB_ITRACE, "Out CNtFileStream::ValidateMode => 0x%lX\n"));
+ return sc;
+}
diff --git a/private/ole32/stg/fsstg/fsenm.cxx b/private/ole32/stg/fsstg/fsenm.cxx
new file mode 100644
index 000000000..d24846fc2
--- /dev/null
+++ b/private/ole32/stg/fsstg/fsenm.cxx
@@ -0,0 +1,326 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: fsenm.cxx
+//
+// Contents: File storage enumerator
+//
+// History: 21-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include "fsenm.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileEnum::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 21-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CFileEnum::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CFileEnum::QueryInterface:%p(riid, %p)\n",
+ this, ppvObj));
+ if (!IsValidIid(iid))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+ if (IsEqualIID(iid, IID_IEnumSTATSTG) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IEnumSTATSTG *)this;
+ CFileEnum::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppvObj = NULL;
+ }
+ ssDebugOut((DEB_TRACE, "Out CFileEnum::QueryInterface => %p\n",
+ *ppvObj));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileEnum::CFileEnum, public
+//
+// Synopsis: Constructor
+//
+// History: 21-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CFileEnum::CFileEnum(void)
+{
+ ssDebugOut((DEB_ITRACE, "In CFileEnum::CFileEnum:%p()\n", this));
+ _sig = 0;
+ ssDebugOut((DEB_ITRACE, "Out CFileEnum::CFileEnum\n"));
+ ENLIST_TRACKING(CFileEnum);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileEnum::InitFromHandle, public
+//
+// Synopsis: Initializes from the given information
+//
+// Arguments: [h] - Handle
+// [fDone] - Done status
+//
+// Returns: Appropriate status code
+//
+// History: 21-Jul-93 DrewB Created
+//
+// Notes: Takes a new reference on the handle
+//
+//----------------------------------------------------------------------------
+
+SCODE CFileEnum::InitFromHandle(HANDLE h, BOOL fDone)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CFileEnum::InitFromHandle:%p(%p, %d)\n",
+ this, h, fDone));
+
+ ssChk(DupNtHandle(h, &_h));
+
+ _fDone = fDone;
+ _sig = CFILEENUM_SIG;
+
+ ssDebugOut((DEB_ITRACE, "Out CFileEnum::InitFromHandle\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileEnum::~CFileEnum, public
+//
+// Synopsis: Destructor
+//
+// History: 21-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CFileEnum::~CFileEnum(void)
+{
+ ssDebugOut((DEB_ITRACE, "In CFileEnum::~CFileEnum:%p()\n", this));
+ _sig = CFILEENUM_SIGDEL;
+ ssDebugOut((DEB_ITRACE, "Out CFileEnum::~CFileEnum\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileEnum::Next, public
+//
+// Synopsis: Gets N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+// [rgelt] - Array for element return
+// [pceltFetched] - If non-NULL, contains the number of
+// elements fetched
+//
+// Returns: Appropriate status code
+//
+// Modifies: [rgelt]
+// [pceltFetched]
+//
+// History: 21-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CFileEnum::Next(ULONG celt,
+ STATSTG *rgelt,
+ ULONG *pceltFetched)
+{
+ SCODE sc;
+ STATSTG stat;
+ FILE_STANDARD_INFORMATION fi;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_TRACE, "In CFileEnum::Next:%p(%lu, %p, %p)\n",
+ this, celt, rgelt, pceltFetched));
+
+ if (pceltFetched == NULL && celt > 1)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+
+ ssAssert(_h != NULL);
+ __try
+ {
+ if (celt == 0)
+ {
+ if (pceltFetched)
+ *pceltFetched = 0;
+ ssErr(EH_Err, S_OK);
+ }
+
+ stat.pwcsName = NULL;
+ if (!_fDone)
+ {
+ nts = NtQueryInformationFile(_h, &iosb, &fi,
+ sizeof(FILE_STANDARD_INFORMATION),
+ FileStandardInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+
+ ssChk(CoMemAlloc(sizeof(CONTENTS_STREAM),
+ (void **)&stat.pwcsName));
+ lstrcpyW(stat.pwcsName, CONTENTS_STREAM);
+
+ stat.type = STGTY_STREAM;
+ stat.cbSize = *(ULARGE_INTEGER *)&fi.EndOfFile;
+ stat.mtime.dwLowDateTime = stat.mtime.dwHighDateTime = 0;
+ stat.atime.dwLowDateTime = stat.atime.dwHighDateTime = 0;
+ stat.ctime.dwLowDateTime = stat.ctime.dwHighDateTime = 0;
+ stat.grfMode = 0;
+ stat.grfLocksSupported = 0;
+ stat.clsid = CLSID_NULL;
+ stat.grfStateBits = 0;
+ stat.STATSTG_dwStgFmt = STGFMT_DOCUMENT;
+
+ rgelt[0] = stat;
+ if (pceltFetched)
+ *pceltFetched = 1;
+
+ _fDone = TRUE;
+
+ if (celt > 1)
+ sc = S_FALSE;
+ else
+ sc = S_OK;
+ }
+ else
+ {
+ if (pceltFetched)
+ *pceltFetched = 0;
+ sc = S_FALSE;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (stat.pwcsName)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ sc = HRESULT_FROM_NT(GetExceptionCode());
+ }
+
+ ssDebugOut((DEB_TRACE, "Out CFileEnum::Next => 0x%lX\n", sc));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileEnum::Skip, public
+//
+// Synopsis: Skips N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+//
+// Returns: Appropriate status code
+//
+// History: 21-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CFileEnum::Skip(ULONG celt)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CFileEnum::Skip:%p(%lu)\n", this, celt));
+
+ ssChk(Validate());
+
+ if (celt > 0)
+ {
+ if (_fDone)
+ sc = S_FALSE;
+ else
+ _fDone = TRUE;
+ }
+
+ ssDebugOut((DEB_TRACE, "Out CFileEnum::Skip\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileEnum::Reset, public
+//
+// Synopsis: Rewinds the iterator
+//
+// Returns: Appropriate status code
+//
+// History: 21-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CFileEnum::Reset(void)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CFileEnum::Reset:%p()\n", this));
+
+ ssChk(Validate());
+ _fDone = FALSE;
+
+ ssDebugOut((DEB_TRACE, "Out CFileEnum::Reset\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileEnum::Clone, public
+//
+// Synopsis: Clones this iterator
+//
+// Arguments: [ppenm] - Clone return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 21-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CFileEnum::Clone(IEnumSTATSTG **ppenm)
+{
+ SCODE sc;
+ SafeCFileEnum pfe;
+
+ ssDebugOut((DEB_TRACE, "In CFileEnum::Clone:%p(%p)\n", this, ppenm));
+
+ ssChk(Validate());
+
+ pfe.Attach(new CFileEnum());
+ ssMem((CFileEnum *)pfe);
+ ssAssert(_h != NULL);
+ ssChk(pfe->InitFromHandle(_h, _fDone));
+ TRANSFER_INTERFACE(pfe, IEnumSTATSTG, ppenm);
+
+ ssDebugOut((DEB_TRACE, "Out CFileEnum::Clone => %p\n", *ppenm));
+EH_Err:
+ return ssResult(sc);
+}
diff --git a/private/ole32/stg/fsstg/fsenm.hxx b/private/ole32/stg/fsstg/fsenm.hxx
new file mode 100644
index 000000000..f5589b9c4
--- /dev/null
+++ b/private/ole32/stg/fsstg/fsenm.hxx
@@ -0,0 +1,83 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: fsenm.hxx
+//
+// Contents: File storage enumerator
+//
+// Classes: CFileEnum
+//
+// History: 21-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FSENM_HXX__
+#define __FSENM_HXX__
+
+#include <otrack.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: CFileEnum (fe)
+//
+// Purpose: File storage enumerator
+//
+// Interface: IEnumSTATSTG
+//
+// History: 21-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CFileEnum
+ : INHERIT_TRACKING,
+ public IEnumSTATSTG
+{
+public:
+ CFileEnum(void);
+ SCODE InitFromHandle(HANDLE h, BOOL fDone);
+ ~CFileEnum(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // IEnumSTATSTG
+ STDMETHOD(Next)(ULONG celt, STATSTG FAR *rgelt, ULONG *pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(IEnumSTATSTG **ppenm);
+
+private:
+ inline SCODE Validate(void) const;
+
+ ULONG _sig;
+ NuSafeNtHandle _h;
+ BOOL _fDone;
+};
+
+SAFE_INTERFACE_PTR(SafeCFileEnum, CFileEnum);
+
+#define CFILEENUM_SIG LONGSIG('F', 'E', 'N', 'M')
+#define CFILEENUM_SIGDEL LONGSIG('F', 'e', 'N', 'm')
+
+//+--------------------------------------------------------------
+//
+// Member: CFileEnum::Validate, private
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 21-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CFileEnum::Validate(void) const
+{
+ return (this == NULL || _sig != CFILEENUM_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+#endif // #ifndef __FSENM_HXX__
diff --git a/private/ole32/stg/fsstg/headers.cxx b/private/ole32/stg/fsstg/headers.cxx
new file mode 100644
index 000000000..b0b83d455
--- /dev/null
+++ b/private/ole32/stg/fsstg/headers.cxx
@@ -0,0 +1,44 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: headers.cxx
+//
+// Contents: Precompiled header file
+//
+// History: 02-Nov-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+}
+
+#if WIN32 != 300
+#include <compobj.h>
+#include <storage.h>
+#endif
+#ifdef _CAIRO_
+#define _CAIROSTG_
+#include <oleext.h>
+#endif
+#include <stgint.h>
+#include <valid.h>
+#include <debnot.h>
+
+#include <dfexcept.hxx>
+#include <dfmsp.hxx>
+#include <funcs.hxx>
+#include <docfilep.hxx>
+#include <safedecl.hxx>
+
+#include <infs.hxx>
+#include "stgstm.hxx"
+#include "ntsupp.hxx"
+#include "dirstg.hxx"
+#include "filstg.hxx"
+#include "ptrcache.hxx"
diff --git a/private/ole32/stg/fsstg/makefile b/private/ole32/stg/fsstg/makefile
new file mode 100644
index 000000000..b38db237d
--- /dev/null
+++ b/private/ole32/stg/fsstg/makefile
@@ -0,0 +1,23 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1994.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+all:
+ echo $(BUILDMSG)
+
+clean: all
+
+!else
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/stg/fsstg/ntenm.cxx b/private/ole32/stg/fsstg/ntenm.cxx
new file mode 100644
index 000000000..8667640d9
--- /dev/null
+++ b/private/ole32/stg/fsstg/ntenm.cxx
@@ -0,0 +1,424 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ntenm.cxx
+//
+// Contents: NT handle enumerator
+//
+// History: 12-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include "ntenm.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtEnum::InitFromHandle, public
+//
+// Synopsis: Initialize from a handle
+//
+// Arguments: [h] - Handle
+// [fReset] - Initial reset status
+//
+// Returns: Appropriate status code
+//
+// History: 12-Jul-93 DrewB Created
+//
+// Notes: Takes a new reference on the handle
+//
+//----------------------------------------------------------------------------
+
+SCODE CNtEnum::InitFromHandle(HANDLE h, BOOL fReset)
+{
+ SCODE sc = S_OK;
+ BOOL fClone = TRUE; // BUGBUG should be a parameter
+
+ ssDebugOut((DEB_ITRACE, "In CNtEnum::InitFromHandle:%p(%p, %d)\n",
+ this, h, fReset));
+
+ if (!fClone)
+ ssChk(DupNtHandle(h, &_h));
+ else
+ {
+ NTSTATUS nts; // if this is cloned enumerator
+ IO_STATUS_BLOCK iosb; // reopen handle to get new cursor
+ OBJECT_ATTRIBUTES oa;
+ UNICODE_STRING us = {0, 0, NULL};
+ DWORD accessMask = GENERIC_READ | DELETE | SYNCHRONIZE;
+ DWORD shareAccess = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
+
+ InitializeObjectAttributes(&oa, &us, OBJ_CASE_INSENSITIVE, h, NULL);
+ if (!NT_SUCCESS(nts=NtOpenFile (&_h, accessMask, &oa, &iosb,
+ shareAccess, FILE_SYNCHRONOUS_IO_NONALERT)))
+ {
+ // BUGBUG it's probably not safe to dup the handle, since
+ // base storage object may do a CopyTo or DestroyTree
+ // but we need to create enumerators with share_exclusive handles
+ if (nts == STATUS_SHARING_VIOLATION || // local error
+ nts == STATUS_ACCESS_DENIED || // local error
+ nts == STATUS_OBJECT_TYPE_MISMATCH) // dfs error
+ sc = DupNtHandle(h, &_h);
+ else
+ {
+ ssDebugOut((DEB_ERROR,"CNtEnum pseudo-DUP open failed %x\n",nts));
+ sc = NtStatusToScode (nts);
+
+ }
+ }
+ }
+ ssAssert (fReset);
+ _nes = NES_RESET_PENDING;
+EH_Err:
+ ssDebugOut((DEB_ITRACE, "Out CNtEnum::InitFromHandle\n"));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtEnum::Next, public
+//
+// Synopsis: Retrieves the next enumeration entry
+//
+// Arguments: [pstat] - STATSTG to fill in
+// [pwcsName] - Name buffer or NULL
+// [dwNte] - NTE flag controlling name return
+// [pfd] - Dir/file flag return
+//
+// Returns: Appropriate status code
+//
+// BUGBUG: This call should retrieve the storage type from the info class
+// in order to set the PFD field.
+//
+// Note: Nt supports enumeration of storages/streams through two
+// different calls. We maintain a state flag that indicates which
+// of the two different API we are using.
+//
+// Worse, enumeration of children occurs through an enumerator
+// while enumeration of streams through a get-all call. This
+// latter call requires allocating a big buffer and hoping it's
+// big enough to handle the data.
+//
+// Modifies: [pstat]
+// [pwcsName]
+// [pfDir]
+//
+// History: 12-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CNtEnum::Next(STATSTG *pstat, WCHAR *pwcsName, DWORD dwNte, FILEDIR *pfd)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+ FILE_DIRECTORY_INFORMATION *pfdi;
+ ULONG cbFdi;
+ WCHAR *pwcs;
+ UNICODE_STRING us, *pus;
+ BOOL fDotOrDotDot;
+
+ ssDebugOut((DEB_ITRACE, "In CNtEnum::Next:%p(%p, %p, %lu, %p)\n",
+ this, pwcsName, dwNte, pfd));
+
+ cbFdi = sizeof(FILE_DIRECTORY_INFORMATION)+
+ MAXIMUM_FILENAME_LENGTH*sizeof(WCHAR);
+ ssMem(pfdi = (FILE_DIRECTORY_INFORMATION *)new BYTE[cbFdi]);
+
+ // Set up match string to force enumeration from beginning.
+ if (_nes == NES_RESET_PENDING)
+ {
+ pus = &us;
+
+ //
+ // The asterisk below is needed so the redirector won't
+ // return STATUS_INVALID_HANDLE after the first call (it
+ // optimizes the single shot query because it thinks
+ // OFS is not enumerating multiple files.)
+ //
+
+ RtlInitUnicodeString (pus, _fIsStorage ? L"\1*" : L"*");
+ }
+ else
+ pus = NULL;
+
+ do
+ {
+ // Retrieve next single content of directory
+ nts = NtQueryDirectoryFile(_h, NULL, NULL, NULL, &iosb, pfdi, cbFdi,
+ FileDirectoryInformation, TRUE,
+ _nes == NES_RESET_PENDING ? pus : NULL,
+ _nes == NES_RESET_PENDING);
+
+ if (nts == STATUS_NO_MORE_FILES || nts == STATUS_NO_SUCH_FILE)
+ {
+ sc = S_FALSE;
+ break;
+ }
+
+ if (!NT_SUCCESS (nts))
+ {
+ sc = NtStatusToScode (nts);
+ break;
+ }
+
+ sc = S_OK;
+
+ _nes = NES_ENUM_DIR;
+
+ fDotOrDotDot =
+ (pfdi->FileNameLength == 2 && pfdi->FileName[0] == L'.') ||
+ (pfdi->FileNameLength == 4 && pfdi->FileName[0] == L'.' && pfdi->FileName[1] == L'.');
+
+ if (!fDotOrDotDot)
+ {
+
+ pstat->pwcsName = NULL;
+ if (dwNte == NTE_STATNAME)
+ {
+ ssChkTo(EH_pdfi,
+ GetScode(CoMemAlloc(pfdi->FileNameLength+sizeof(WCHAR),
+ (void **)&pstat->pwcsName)));
+ pwcs = pstat->pwcsName;
+ }
+ else if (dwNte == NTE_BUFFERNAME)
+ {
+ ssAssert(pwcsName != NULL);
+ pwcs = pwcsName;
+ }
+ else
+ {
+ ssAssert(dwNte == NTE_NONAME);
+ pwcs = NULL;
+ }
+ if (pwcs)
+ {
+ memcpy(pwcs, pfdi->FileName, pfdi->FileNameLength);
+ *(WCHAR *)((BYTE *)pwcs+pfdi->FileNameLength) = 0;
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ pstat->type =
+ (pfdi->FileAttributes & ~FILE_ATTRIBUTE_PROPERTY_SET) == 0?
+ STGTY_STREAM : STGTY_STORAGE;
+ LARGE_INTEGER_TO_FILETIME(&pfdi->LastWriteTime, &pstat->mtime);
+ LARGE_INTEGER_TO_FILETIME(&pfdi->CreationTime, &pstat->ctime);
+ LARGE_INTEGER_TO_FILETIME(&pfdi->LastAccessTime, &pstat->atime);
+ pstat->grfMode = 0;
+ pstat->grfLocksSupported = 0;
+ pstat->clsid = CLSID_NULL; // BUGBUG: BillMo, RAID# 13804, should return real clsid
+ // from file system.
+ pstat->grfStateBits = 0;
+
+ if (pfdi->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ pstat->STATSTG_dwStgFmt = STGFMT_DIRECTORY;
+ *pfd = FD_DIR;
+ pstat->cbSize.HighPart = pstat->cbSize.LowPart = 0;
+ }
+ else
+ {
+ pstat->STATSTG_dwStgFmt = STGFMT_DOCUMENT;
+ if ((pfdi->FileAttributes & ~FILE_ATTRIBUTE_PROPERTY_SET) == 0)
+ {
+ *pfd = FD_STREAM;
+ pstat->cbSize.HighPart = pfdi->EndOfFile.HighPart;
+ pstat->cbSize.LowPart = pfdi->EndOfFile.LowPart;
+ }
+ else
+ {
+ *pfd = FD_STORAGE;
+ pstat->cbSize.HighPart = pstat->cbSize.LowPart = 0;
+ }
+ }
+ }
+ }
+ } while (fDotOrDotDot);
+
+ ssDebugOut((DEB_ITRACE, "Out CNtEnum::Next\n"));
+
+ EH_pdfi:
+ delete pfdi;
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtEnum::NextOfs, public
+//
+// Synopsis: Retrieves the next enumeration entry
+//
+// Arguments: [pstat] - STATSTG to fill in
+// [pwcsName] - Name buffer or NULL
+// [dwNte] - NTE flag controlling name return
+// [pfd] - Dir/file flag return
+//
+// Returns: Appropriate status code
+//
+// BUGBUG: This call should retrieve the storage type from the info class
+// in order to set the PFD field.
+//
+// Note: Identical to Next,but return OLE info from OFS
+// Can be optimized to use C++ templates
+//
+// Modifies: [pstat]
+// [pwcsName]
+// [pfDir]
+//
+// History: 18-Jul-1995 HenryLee created
+//
+//----------------------------------------------------------------------------
+
+SCODE CNtEnum::NextOfs(STATSTG *pstat,WCHAR *pwcsName,DWORD dwNte,FILEDIR *pfd)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+ FILE_OLE_DIR_INFORMATION *pfdi;
+ ULONG cbFdi;
+ WCHAR *pwcs;
+ UNICODE_STRING us, *pus;
+ BOOL fDotOrDotDot;
+
+ ssDebugOut((DEB_ITRACE, "In CNtEnum::NextOfs:%p(%p, %p, %lu, %p)\n",
+ this, pwcsName, dwNte, pfd));
+
+ cbFdi = sizeof(FILE_OLE_DIR_INFORMATION)+
+ MAXIMUM_FILENAME_LENGTH*sizeof(WCHAR);
+ ssMem(pfdi = (FILE_OLE_DIR_INFORMATION *)new BYTE[cbFdi]);
+
+ // Set up match string to force enumeration from beginning.
+ if (_nes == NES_RESET_PENDING)
+ {
+ pus = &us;
+
+ //
+ // The asterisk below is needed so the redirector won't
+ // return STATUS_INVALID_HANDLE after the first call (it
+ // optimizes the single shot query because it thinks
+ // OFS is not enumerating multiple files.)
+ //
+
+ RtlInitUnicodeString (pus, _fIsStorage ? L"\1*" : L"*");
+ }
+ else
+ pus = NULL;
+
+ do
+ {
+ // Retrieve next single content of directory
+
+ nts = NtQueryDirectoryFile(_h, NULL, NULL, NULL, &iosb, pfdi, cbFdi,
+ FileOleDirectoryInformation, TRUE,
+ _nes == NES_RESET_PENDING ? pus : NULL,
+ _nes == NES_RESET_PENDING);
+
+ if (nts == STATUS_NO_MORE_FILES || nts == STATUS_NO_SUCH_FILE)
+ {
+ sc = S_FALSE;
+ break;
+ }
+
+ if (!NT_SUCCESS (nts))
+ {
+ sc = NtStatusToScode (nts);
+ break;
+ }
+
+ sc = S_OK;
+
+ _nes = NES_ENUM_DIR;
+
+ fDotOrDotDot =
+ (pfdi->FileNameLength == 2 && pfdi->FileName[0] == L'.') ||
+ (pfdi->FileNameLength == 4 && pfdi->FileName[0] == L'.' && pfdi->FileName[1] == L'.');
+
+ if (!fDotOrDotDot)
+ {
+
+ pstat->pwcsName = NULL;
+ if (dwNte == NTE_STATNAME)
+ {
+ ssChkTo(EH_pdfi,
+ GetScode(CoMemAlloc(pfdi->FileNameLength+sizeof(WCHAR),
+ (void **)&pstat->pwcsName)));
+ pwcs = pstat->pwcsName;
+ }
+ else if (dwNte == NTE_BUFFERNAME)
+ {
+ ssAssert(pwcsName != NULL);
+ pwcs = pwcsName;
+ }
+ else
+ {
+ ssAssert(dwNte == NTE_NONAME);
+ pwcs = NULL;
+ }
+ if (pwcs)
+ {
+ memcpy(pwcs, pfdi->FileName, pfdi->FileNameLength);
+ *(WCHAR *)((BYTE *)pwcs+pfdi->FileNameLength) = 0;
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ pstat->type = STGTY_STORAGE;
+ LARGE_INTEGER_TO_FILETIME(&pfdi->LastWriteTime, &pstat->mtime);
+ LARGE_INTEGER_TO_FILETIME(&pfdi->CreationTime, &pstat->ctime);
+ LARGE_INTEGER_TO_FILETIME(&pfdi->LastAccessTime, &pstat->atime);
+ pstat->grfMode = 0;
+ pstat->grfLocksSupported = 0;
+ pstat->clsid = pfdi->OleClassId;
+ pstat->grfStateBits = pfdi->OleStateBits;
+ pstat->cbSize.HighPart = pstat->cbSize.LowPart = 0;
+
+ if (pfdi->StorageType == StorageTypeDirectory)
+ {
+ pstat->STATSTG_dwStgFmt = STGFMT_DIRECTORY;
+ *pfd = FD_DIR;
+ }
+ else if (pfdi->StorageType == StorageTypeJunctionPoint)
+ {
+ pstat->STATSTG_dwStgFmt = STGFMT_JUNCTION;
+ *pfd = FD_JUNCTION;
+ }
+ else
+ {
+ pstat->STATSTG_dwStgFmt = STGFMT_DOCUMENT;
+ if (pfdi->StorageType == StorageTypeStream)
+ {
+ if ((pfdi->FileAttributes &
+ FILE_ATTRIBUTE_PROPERTY_SET) == 0)
+ {
+ ssAssert(pfdi->FileAttributes == 0);
+ pstat->mtime.dwHighDateTime = pstat->mtime.dwLowDateTime = 0;
+ }
+ pstat->ctime.dwHighDateTime = pstat->ctime.dwLowDateTime = 0;
+ pstat->atime.dwHighDateTime = pstat->atime.dwLowDateTime = 0;
+ *pfd = FD_STREAM;
+ pstat->cbSize.QuadPart = pfdi->EndOfFile.QuadPart;
+ pstat->type = STGTY_STREAM;
+ }
+ else
+ {
+ *pfd = FD_STORAGE;
+ }
+ }
+ }
+ }
+ } while (fDotOrDotDot);
+
+ ssDebugOut((DEB_ITRACE, "Out CNtEnum::NextOfs\n"));
+
+ EH_pdfi:
+ delete pfdi;
+ EH_Err:
+ return sc;
+}
+
diff --git a/private/ole32/stg/fsstg/ntlkb.cxx b/private/ole32/stg/fsstg/ntlkb.cxx
new file mode 100644
index 000000000..8c9c57a74
--- /dev/null
+++ b/private/ole32/stg/fsstg/ntlkb.cxx
@@ -0,0 +1,496 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ntlkb.cxx
+//
+// Contents: ILockBytes for an NT handle
+//
+// History: 17-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <ntlkb.hxx>
+#include <stgutil.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtLockBytes::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 17-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CNtLockBytes::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CNtLockBytes::QueryInterface:%p(riid, %p)\n",
+ this, ppvObj));
+ if (!IsValidIid(iid))
+ sc = STG_E_INVALIDPARAMETER;
+ else if (IsEqualIID(iid, IID_ILockBytes) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (ILockBytes *)this;
+ CNtLockBytes::AddRef();
+ sc = S_OK;
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppvObj = NULL;
+ }
+ ssDebugOut((DEB_TRACE, "Out CNtLockBytes::QueryInterface => %p\n",
+ *ppvObj));
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtLockBytes::CNtLockBytes, public
+//
+// Synopsis: Constructor
+//
+// History: 17-Aug-93 DrewB Created
+// 24-Mar-95 HenryLee Save drive letter for Stat problem
+//
+//----------------------------------------------------------------------------
+
+CNtLockBytes::CNtLockBytes(BOOL fOfs)
+{
+ ssDebugOut((DEB_ITRACE, "In CNtLockBytes::CNtLockBytes:%p()\n", this));
+ _fOfs = fOfs;
+ _wcDrive = L'\0';
+ ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::CNtLockBytes\n"));
+ ENLIST_TRACKING(CNtLockBytes);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtLockBytes::InitFromPath, public
+//
+// Synopsis: Constructs from the given path
+//
+// Arguments: [hParent] - Parent handle
+// [pwcsName] - Path
+// [grfMode] - Mode
+// [co] - Create or open
+// [pssSecurity] - Security
+//
+// Returns: Appropriate status code
+//
+// History: 17-Aug-93 DrewB Created
+// 24-Mar-95 HenryLee Save drive letter for Stat problem
+//
+//----------------------------------------------------------------------------
+
+SCODE CNtLockBytes::InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSECURITY_ATTRIBUTES pssSecurity)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CNtLockBytes::InitFromPath:%p("
+ "%p, %ws, %lX, %d, %p)\n", this, hParent, pwcsName,
+ grfMode, co, pssSecurity));
+
+ ssChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co,
+ FD_FILE, pssSecurity, &_h));
+ _grfMode = grfMode;
+ _wcDrive = GetDriveLetter (pwcsName);
+
+ ssDebugOut((DEB_IWARN, "CNtLockBytes::InitFromPath %p"
+ "handle %p thread %lX\n",
+ this, (HANDLE)_h, GetCurrentThreadId()));
+
+ ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::InitFromPath\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtLockBytes::InitFromHandle, public
+//
+// Synopsis: Initialization by handle
+//
+// Arguments: [h] - Handle
+// [grfMode] - Mode
+//
+// Returns: Appropriate status code
+//
+// History: 21-Sep-93 DrewB Created
+// 24-Mar-95 HenryLee Save drive letter for Stat problem
+//
+// Notes: Takes a new reference on the handle
+//
+//----------------------------------------------------------------------------
+
+SCODE CNtLockBytes::InitFromHandle(HANDLE h,
+ WCHAR const *pwcsName,
+ DWORD grfMode)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CNtLockBytes::InitFromHandle:%p(%p, %lX)\n",
+ this, h, grfMode));
+
+
+ ssChk(DupNtHandle(h, &_h));
+
+ _grfMode = grfMode;
+ _wcDrive = GetDriveLetter (pwcsName);
+
+ ssDebugOut((DEB_IWARN, "CNtLockBytes::InitFromHandle %p"
+ "handle %p thread %lX\n",
+ this, (HANDLE)_h, GetCurrentThreadId()));
+
+ ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::InitFromHandle\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtLockBytes::~CNtLockBytes, public debugging
+//
+// Synopsis: Stub for placing shutdown debug messages
+//
+// History: 01-Oct-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if DBG == 1
+CNtLockBytes::~CNtLockBytes(void)
+{
+ ssDebugOut((DEB_IWARN, "~CNtLockBytes %p handle %p thread %lX\n",
+ this, (HANDLE)_h, GetCurrentThreadId()));
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CNtLockBytes::ReadAt, public
+//
+// Synopsis: Reads bytes at a specific point in a stream
+//
+// Arguments: [ulPosition] - Offset in file to read at
+// [pb] - Buffer
+// [cb] - Count of bytes to read
+// [pcbRead] - Return of bytes read
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+//
+// History: 17-Aug-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtLockBytes::ReadAt(ULARGE_INTEGER ulPosition,
+ VOID *pb,
+ ULONG cb,
+ ULONG *pcbRead)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_ITRACE, "In CNtLockBytes::ReadAt:%p("
+ "%lu:%lu, %p, %lu, %p)\n", this, ulPosition.HighPart,
+ ulPosition.LowPart, pb, cb, pcbRead));
+
+ sc = S_OK;
+ ssAssert(_h != NULL);
+ nts = NtReadFile(_h, NULL, NULL, NULL, &iosb, pb, cb,
+ (LARGE_INTEGER *)&ulPosition, NULL);
+ if (!NT_SUCCESS(nts))
+ {
+ if (nts != STATUS_END_OF_FILE)
+ sc = NtStatusToScode(nts);
+ else
+ iosb.Information = 0;
+ }
+ if (pcbRead)
+ {
+ if (SUCCEEDED(sc))
+ *pcbRead = iosb.Information;
+ else
+ *pcbRead = 0;
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::ReadAt => %lu\n", *pcbRead));
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtLockBytes::WriteAt, public
+//
+// Synopsis: Writes bytes at a specific point in a stream
+//
+// Arguments: [ulPosition] - Offset in file
+// [pb] - Buffer
+// [cb] - Count of bytes to write
+// [pcbWritten] - Return of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbWritten]
+//
+// History: 17-Aug-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtLockBytes::WriteAt(ULARGE_INTEGER ulPosition,
+ VOID const *pb,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_ITRACE, "In CNtLockBytes::WriteAt:%p("
+ "%lu:%lu, %p, %lu, %p)\n", this, ulPosition.HighPart,
+ ulPosition.LowPart, pb, cb, pcbWritten));
+
+ sc = S_OK;
+ ssAssert(_h != NULL);
+ nts = NtWriteFile(_h, NULL, NULL, NULL, &iosb, (void *)pb, cb,
+ (LARGE_INTEGER *)&ulPosition, NULL);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ if (pcbWritten)
+ {
+ if (SUCCEEDED(sc))
+ *pcbWritten = iosb.Information;
+ else
+ *pcbWritten = 0;
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::WriteAt => %lu\n",
+ *pcbWritten));
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtLockBytes::Flush, public
+//
+// Synopsis: Flushes buffers
+//
+// Returns: Appropriate status code
+//
+// History: 24-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtLockBytes::Flush(void)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_ITRACE, "In CNtLockBytes::Flush:%p()\n", this));
+
+ ssAssert(_h != NULL);
+ nts = NtFlushBuffersFile(_h, &iosb);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::Flush => %lX\n", sc));
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtLockBytes::SetSize, public
+//
+// Synopsis: Sets the size of the LStream
+//
+// Arguments: [ulSize] - New size
+//
+// Returns: Appropriate status code
+//
+// History: 17-Aug-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtLockBytes::SetSize(ULARGE_INTEGER ulSize)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+ FILE_END_OF_FILE_INFORMATION feofi;
+
+ ssDebugOut((DEB_ITRACE, "In CNtLockBytes::SetSize:%p(%lu:%lu)\n",
+ this, ulSize.HighPart, ulSize.LowPart));
+
+ sc = S_OK;
+
+ feofi.EndOfFile.LowPart = ulSize.LowPart;
+ feofi.EndOfFile.HighPart = ulSize.HighPart;
+ ssAssert(_h != NULL);
+ nts = NtSetInformationFile(_h, &iosb, &feofi,
+ sizeof(FILE_END_OF_FILE_INFORMATION),
+ FileEndOfFileInformation);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+
+ ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::SetSize => %lX\n", sc));
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtLockBytes::LockRegion, public
+//
+// Synopsis: Gets a lock on a portion of the LStream
+//
+// Arguments: [ulStartOffset] - Lock start
+// [cbLockLength] - Length
+// [dwLockType] - Exclusive/Read only
+//
+// Returns: Appropriate status code
+//
+// History: 17-Aug-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtLockBytes::LockRegion(ULARGE_INTEGER ulStartOffset,
+ ULARGE_INTEGER cbLockLength,
+ DWORD dwLockType)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_ITRACE, "In CNtLockBytes::LockRegion:%p("
+ "%lu:%lu, %lu:%lu, %lu)\n", this, ulStartOffset.HighPart,
+ ulStartOffset.LowPart, cbLockLength.HighPart,
+ cbLockLength.LowPart, dwLockType));
+
+ ssAssert(_h != NULL);
+ nts = NtLockFile(_h, NULL, NULL, NULL, &iosb,
+ (PLARGE_INTEGER)&ulStartOffset,
+ (PLARGE_INTEGER)&cbLockLength, 0, TRUE, TRUE);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::LockRegion => %lX\n", sc));
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtLockBytes::UnlockRegion, public
+//
+// Synopsis: Releases an existing lock
+//
+// Arguments: [ulStartOffset] - Lock start
+// [cbLockLength] - Length
+// [dwLockType] - Lock type
+//
+// Returns: Appropriate status code
+//
+// History: 17-Aug-93 DrewB Created
+//
+// Notes: Must match an existing lock exactly
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtLockBytes::UnlockRegion(ULARGE_INTEGER ulStartOffset,
+ ULARGE_INTEGER cbLockLength,
+ DWORD dwLockType)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_ITRACE, "In CNtLockBytes::UnlockRegion:%p("
+ "%lu:%lu, %lu:%lu, %lu)\n", this, ulStartOffset.HighPart,
+ ulStartOffset.LowPart, cbLockLength.HighPart,
+ cbLockLength.LowPart, dwLockType));
+
+ ssAssert(_h != NULL);
+ nts = NtUnlockFile(_h, &iosb, (PLARGE_INTEGER)&ulStartOffset,
+ (PLARGE_INTEGER)&cbLockLength, 0);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::UnlockRegion => %lX\n", sc));
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtLockBytes::Stat, public
+//
+// Synopsis: Fills in a stat buffer for this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 25-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtLockBytes::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+ STATSTG stat;
+ FILEDIR fd;
+
+ ssDebugOut((DEB_ITRACE, "In CNtLockBytes::Stat:%p(%p, %d)\n",
+ this, pstatstg, grfStatFlag));
+
+ ssAssert(_h != NULL);
+ sc = StatNtHandle(_h, grfStatFlag, 0, &stat, NULL, NULL, &fd);
+ if (SUCCEEDED(sc))
+ {
+ stat.grfMode = _grfMode;
+ stat.type = STGTY_LOCKBYTES;
+ stat.grfLocksSupported = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
+
+ // As a hack way of determining whether this ILockBytes
+ // lives on OFS or not, we return our OFSness through dwStgFmt,
+ // which is unused for ILockBytes
+ stat.STATSTG_dwStgFmt = _fOfs;
+
+ // Now we tack on the drive letter to the filename, since
+ // NtQueryInformationFile doesn't return the drive letter,
+ // and NtQueryObject returns something like
+ // "\Device\Harddisk1\Partition1"
+ SetDriveLetter (stat.pwcsName, _wcDrive);
+
+ *pstatstg = stat;
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out CNtLockBytes::Stat => %lX\n", sc));
+ return ssResult(sc);
+}
diff --git a/private/ole32/stg/fsstg/ntsupp.cxx b/private/ole32/stg/fsstg/ntsupp.cxx
new file mode 100644
index 000000000..ab71c767b
--- /dev/null
+++ b/private/ole32/stg/fsstg/ntsupp.cxx
@@ -0,0 +1,1243 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ntsupp.cxx
+//
+// Contents: NT support routines
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <iofs.h>
+#include <stgutil.hxx>
+#include <ntdddfs.h>
+
+//+---------------------------------------------------------------------------
+//
+// Function: MakeStreamName
+//
+// Synopsis: Prepend a L':' to a string and return a new string.
+// The old string is untouched.
+//
+// Arguments:
+//
+// Returns: New string, or NULL if out of memory.
+//
+// Modifies:
+//
+// History: 18-Feb-94 DrewB Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+WCHAR * MakeStreamName(const WCHAR *pwcsName)
+{
+ WCHAR *pwcsNewName;
+ ssDebugOut((DEB_ITRACE, "In MakeStreamName(%ws)\n",pwcsName));
+
+ USHORT uLen = lstrlenW(pwcsName);
+
+ pwcsNewName = new WCHAR[uLen + 2];
+ if (pwcsNewName)
+ {
+ pwcsNewName[0] = L':';
+ lstrcpyW(pwcsNewName + 1, pwcsName);
+ }
+ ssDebugOut((DEB_ITRACE, "Out MakeStreamName\n"));
+ return pwcsNewName;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CheckFdName, public
+//
+// Synopsis: Checks for illegal characters in an element name
+//
+// Arguments: [pwcs] - Name
+//
+// Returns: Appropriate status code
+//
+// History: 29-Jul-93 DrewB Created
+//
+// Notes: Doesn't check for length because that will vary by
+// file system and will be enforced by the FS itself
+//
+// Kept separate from CheckName since we may want to
+// allow different rules for file system elements
+//
+//----------------------------------------------------------------------------
+
+SCODE CheckFdName(WCHAR const *pwcs)
+{
+ static WCHAR const wcsInvalid[] = {'\\','/','\0'};
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In CheckFdName(%ws)\n", pwcs));
+ ssAssert (pwcs != NULL);
+ sc = S_OK;
+ for (; *pwcs; pwcs++)
+ if (wcschr(wcsInvalid, *pwcs))
+ {
+ sc = STG_E_INVALIDNAME;
+ break;
+ }
+ ssDebugOut((DEB_ITRACE, "Out CheckFdName => %lX\n", sc));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ModeToNtFlags, public
+//
+// Synopsis: Converts a grfMode to a set of NtCreateFile flags
+//
+// Arguments: [grfMode] - Mode
+// [co] - Create or open request
+// [fd] - File or directory
+// [pam] - ACCESS_MASK return
+// [pulAttributes] - Object attributes return
+// [pulSharing] - Sharing return
+// [pulCreateDisposition] - Create/open flags return
+// [pulCreateOptions] - Create type return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pam]
+// [pulAttributes]
+// [pulSharing]
+// [pulCreateDisposition]
+// [pulCreateOptions]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE ModeToNtFlags(DWORD grfMode,
+ CREATEOPEN co,
+ FILEDIR fd,
+ ACCESS_MASK *pam,
+ ULONG *pulAttributes,
+ ULONG *pulSharing,
+ ULONG *pulCreateDisposition,
+ ULONG *pulCreateOptions)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In ModeToNtFlags("
+ "%lX, %d, %d, %p, %p, %p, %p, %p)\n",
+ grfMode, co, fd, pam, pulAttributes, pulSharing,
+ pulCreateDisposition, pulCreateOptions));
+
+ // Note: Although you may think permissions like FILE_ADD_FILE,
+ // FILE_ADD_SUBDIRECTORY and FILE_TRAVERSE are good permissions
+ // to have for a directory, they are only used for ACL checks and
+ // are not supposed to be specified in DesiredAccess.
+ // That's the word from DarrylH
+
+ // BUGBUG: [mikese] of course, the consequence of that it that there is no
+ // way that this routine can generate a desired access mask which is
+ // sufficiently polymorphic so as to be acceptable regardless of the
+ // type of thing being opened. Therefore, we give it our best shot and
+ // retry for certain distinguishable error cases. The tricky cases are
+ // those where fd == FD_DEFAULT, since for that case must assume the
+ // most general case, nameky that of a structured storage, which behaves
+ // like both a directory and a file.
+
+ switch(grfMode & (STGM_READ | STGM_WRITE | STGM_READWRITE))
+ {
+ case STGM_READ:
+ *pam = FILE_GENERIC_READ;
+ break;
+
+ case STGM_WRITE:
+ if ((fd == FD_FILE) || (fd == FD_STREAM))
+ *pam = FILE_GENERIC_WRITE;
+ else if ( fd == FD_DIR )
+ {
+ *pam = STANDARD_RIGHTS_WRITE |
+ FILE_WRITE_EA |
+ SYNCHRONIZE |
+ FILE_WRITE_ATTRIBUTES;
+ }
+ else
+ *pam = FILE_GENERIC_WRITE;
+ break;
+
+ case STGM_READWRITE:
+ if ((fd == FD_FILE) || (fd == FD_STREAM))
+ *pam = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
+ else if ( fd == FD_DIR )
+ *pam = FILE_GENERIC_READ
+ | STANDARD_RIGHTS_WRITE
+ | FILE_WRITE_EA | SYNCHRONIZE
+ | FILE_WRITE_ATTRIBUTES;
+ else
+ *pam = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
+ break;
+
+ default:
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+ break;
+ }
+
+ if (grfMode & STGM_EDIT_ACCESS_RIGHTS)
+ {
+ *pam |= WRITE_DAC | READ_CONTROL;
+ }
+ // If we're opening something for deletion, throw on the DELETE permission
+ if (co == CO_OPEN && (grfMode & STGM_CREATE))
+ *pam |= DELETE;
+
+ switch(grfMode & (STGM_SHARE_DENY_NONE | STGM_SHARE_DENY_READ |
+ STGM_SHARE_DENY_WRITE | STGM_SHARE_EXCLUSIVE))
+ {
+ case STGM_SHARE_DENY_READ:
+ *pulSharing = FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ break;
+ case STGM_SHARE_DENY_WRITE:
+ *pulSharing = FILE_SHARE_READ | FILE_SHARE_DELETE;
+ break;
+ case STGM_SHARE_EXCLUSIVE:
+ *pulSharing = FILE_SHARE_DELETE;
+ break;
+ case STGM_SHARE_DENY_NONE:
+ case 0:
+ *pulSharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+ break;
+
+ default:
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+ break;
+ }
+
+ switch(grfMode & (STGM_CREATE | STGM_FAILIFTHERE | STGM_CONVERT))
+ {
+ case STGM_CREATE:
+ if (co == CO_CREATE)
+ if ((fd == FD_FILE) || (fd == FD_STREAM) || (fd == FD_STORAGE) ||
+ (fd == FD_CATALOG))
+ *pulCreateDisposition = FILE_SUPERSEDE;
+ else if (fd == FD_DIR)
+ *pulCreateDisposition = FILE_OPEN_IF;
+ else
+ {
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+ }
+ else
+ *pulCreateDisposition = FILE_OPEN;
+ break;
+ case STGM_FAILIFTHERE:
+ if (co == CO_CREATE)
+ *pulCreateDisposition = FILE_CREATE;
+ else
+ *pulCreateDisposition = FILE_OPEN;
+ break;
+
+ case STGM_CONVERT:
+ default:
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+ break;
+ }
+
+ *pulAttributes |= FILE_ATTRIBUTE_NORMAL;
+
+ // FILE_FLAG_OVERLAPPED is a valid Win32 flag, but invalid NT flag
+ // so we translate it into ~FILE_SYNCHRONOUS_IO_NONALERT
+ // and mask out FILE_FLAG_OVERLAPPED before calling NtCreateFile
+ if ((*pulAttributes & FILE_FLAG_OVERLAPPED) == 0 &&
+ (grfMode & STGM_OVERLAPPED) == 0)
+ *pulCreateOptions = FILE_SYNCHRONOUS_IO_NONALERT;
+ else
+ *pulAttributes &= ~FILE_FLAG_OVERLAPPED;
+
+ switch (fd)
+ {
+ case FD_DEFAULT:
+ break;
+
+ //case FD_EMBEDDING: // no longer supported
+ // *pulCreateOptions |= FILE_STORAGE_TYPE_SPECIFIED | FILE_STORAGE_TYPE_EMBEDDING;
+ // break;
+
+ case FD_STORAGE:
+ *pulCreateOptions |= FILE_STORAGE_TYPE_SPECIFIED | FILE_STORAGE_TYPE_STRUCTURED_STORAGE;
+ break;
+
+ case FD_STREAM:
+ *pulCreateOptions |= FILE_STORAGE_TYPE_SPECIFIED | FILE_STORAGE_TYPE_STREAM;
+ break;
+
+ case FD_DIR:
+ *pulCreateOptions |= FILE_DIRECTORY_FILE;
+ break;
+
+ case FD_FILE:
+ *pulCreateOptions |= FILE_NON_DIRECTORY_FILE;
+ break;
+
+ case FD_CATALOG:
+ *pulCreateOptions |= FILE_STORAGE_TYPE_SPECIFIED | FILE_STORAGE_TYPE_CATALOG;
+ break;
+
+ case FD_JUNCTION:
+ *pulCreateOptions |= FILE_STORAGE_TYPE_SPECIFIED | FILE_STORAGE_TYPE_JUNCTION_POINT;
+ break;
+
+ default:
+ ssErr (EH_Err, STG_E_INVALIDFLAG);
+ }
+
+#ifdef TRANSACT_OLE
+ if (grfMode & STGM_TRANSACTED)
+ {
+ *pulCreateOptions |= FILE_TRANSACTED_MODE;
+ }
+#endif
+
+ // Set up delete-on-release flags
+ if (grfMode & STGM_DELETEONRELEASE)
+ {
+ // We cannot use the DELETE_ON_CLOSE bits in OFS since this
+ // causes the file to become invalid for relative opens.
+
+ *pam |= DELETE;
+ }
+
+ sc = S_OK;
+
+ ssDebugOut((DEB_ITRACE, "Out ModeToNtFlags\n"));
+ EH_Err:
+ return sc;
+}
+
+SAFE_HEAP_PTR(SafeFeai, FILE_FULL_EA_INFORMATION);
+//+---------------------------------------------------------------------------
+//
+// Function: GetNtHandle, public
+//
+// Synopsis: Opens or create a file or directory using NtCreateFile
+//
+// Arguments: [hParent] - Parent handle or NULL
+// [pwcsName] - Child name or full path
+// [grfMode] - Access mode
+// [co] - Create or open
+// [fd] - File or directory
+// [pssSecurity] - Security or NULL
+// [ph] - Handle return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ph]
+//
+// History: 24-Jun-93 DrewB Created
+//
+// Notes: If [hParent] is NULL, [pwcsName] should be a full path
+// [ph] should only be set on success
+//
+//----------------------------------------------------------------------------
+
+SCODE GetNtHandle(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD grfAttrs,
+ CREATEOPEN co,
+ FILEDIR fd,
+ LPSECURITY_ATTRIBUTES pssSecurity,
+ HANDLE *ph)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ OBJECT_ATTRIBUTES oa;
+ IO_STATUS_BLOCK iosb;
+ UNICODE_STRING us;
+ HANDLE h;
+ ACCESS_MASK am;
+ ULONG ulAttrs = grfAttrs;
+ ULONG ulSharing;
+ ULONG ulCreateDisp;
+ ULONG ulCreateOpt = 0;
+ ULONG ulEaLength = 0;
+ SafeFeai pfeai = NULL;
+
+ ssDebugOut((DEB_ITRACE, "In GetNtHandle(%p, %ws, %lX, %d, %d, %p, %p)\n",
+ hParent, pwcsName, grfMode, co, fd, pssSecurity, ph));
+
+ if (hParent == NULL)
+ {
+ if (pwcsName == NULL)
+ ssErr(EH_Err, STG_E_INVALIDNAME);
+ if (!RtlDosPathNameToNtPathName_U(pwcsName, &us, NULL, NULL))
+ ssErr(EH_Err, STG_E_UNKNOWN);
+ }
+ else
+ {
+ ssChk(CheckFdName(pwcsName));
+ us.Length = lstrlenW(pwcsName)*sizeof(WCHAR);
+ us.MaximumLength = us.Length+sizeof(WCHAR);
+ us.Buffer = (PWSTR)pwcsName;
+ }
+
+ InitializeObjectAttributes(&oa, &us, OBJ_CASE_INSENSITIVE, hParent, NULL);
+ if (pssSecurity)
+ {
+ if (pssSecurity->nLength != sizeof(SECURITY_ATTRIBUTES))
+ ssErr(EH_us, STG_E_INVALIDPARAMETER);
+
+ oa.SecurityDescriptor = pssSecurity->lpSecurityDescriptor;
+ }
+ ssChkTo(EH_us,
+ ModeToNtFlags(grfMode, co, fd, &am, &ulAttrs, &ulSharing,
+ &ulCreateDisp, &ulCreateOpt));
+
+ if (fd == FD_JUNCTION || (grfMode & STGM_NOCROSSJP))
+ {
+ ulEaLength=sizeof(FILE_FULL_EA_INFORMATION)+strlen(EA_NAME_OPENIFJP)+1;
+ pfeai.Attach((FILE_FULL_EA_INFORMATION *) new BYTE[ulEaLength]);
+ ssMem((FILE_FULL_EA_INFORMATION *) pfeai);
+ pfeai->NextEntryOffset = 0;
+ pfeai->Flags = 0;
+ pfeai->EaNameLength = strlen(EA_NAME_OPENIFJP);
+ pfeai->EaValueLength = 0;
+ strcpy (pfeai->EaName, EA_NAME_OPENIFJP);
+ }
+
+ nts = NtCreateFile(&h, am, &oa, &iosb, NULL,
+ ulAttrs, ulSharing, ulCreateDisp,
+ ulCreateOpt, pfeai, ulEaLength);
+
+ // BUGBUG: thise is a hack to get around inflexibilities in the file system.
+ // if the operation failed with STATUS_INVALID_PARAMETER, it probably
+ // means we tried to open a directory using modes only valid for a file
+ // (Not sure if this can ever really happen)
+ if ( nts == STATUS_INVALID_PARAMETER )
+ {
+ nts = NtCreateFile(&h, am & ~(FILE_ADD_SUBDIRECTORY|FILE_ADD_FILE), &oa,
+ &iosb, NULL, ulAttrs, ulSharing, ulCreateDisp,
+ ulCreateOpt, pfeai, ulEaLength);
+ }
+
+ if (NT_SUCCESS(nts))
+ {
+ *ph = h;
+ sc = S_OK;
+ }
+ else
+ sc = NtStatusToScode(nts);
+ ssDebugOut((DEB_ITRACE, "Out GetNtHandle => %p\n", *ph));
+ EH_us:
+ if (hParent == NULL)
+ RtlFreeHeap(RtlProcessHeap(), 0, us.Buffer);
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: ReopenNtHandle, public
+//
+// Synopsis: Duplicates an NT handle with new permissions
+//
+// Arguments: [h] - Handle to dup
+// [grfMode] - Desired access for duplicate
+// [fd] - File or directory handle
+// [ph] - Handle return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ph]
+//
+// History: 29-Jun-93 DrewB Created
+//
+// Notes: Reopen can only change the read/write access to the
+// file; sharing cannot be changed
+//
+//----------------------------------------------------------------------------
+
+SCODE ReopenNtHandle(HANDLE h, DWORD grfMode, FILEDIR fd, HANDLE *ph)
+{
+ ACCESS_MASK am;
+ ULONG ulAttrs = 0;
+ ULONG ulSharing;
+ ULONG ulCreateDisp;
+ ULONG ulCreateOpt;
+ SCODE sc;
+ NTSTATUS nts;
+ HANDLE th;
+
+ ssDebugOut((DEB_ITRACE, "In ReopenNtHandle(%p, %lX, %d, %p)\n",
+ h, grfMode, fd, ph));
+ ssChk(ModeToNtFlags(grfMode & (STGM_READ | STGM_WRITE | STGM_READWRITE),
+ CO_OPEN, fd, &am, &ulAttrs, &ulSharing, &ulCreateDisp,
+ &ulCreateOpt));
+ nts = NtDuplicateObject(NtCurrentProcess(), h, NtCurrentProcess(), &th, am,
+ 0, DUPLICATE_SAME_ATTRIBUTES);
+ if (!NT_SUCCESS(nts))
+ {
+ sc = NtStatusToScode(nts);
+ }
+ else
+ {
+ *ph = th;
+ sc = S_OK;
+ }
+ ssDebugOut((DEB_ITRACE, "Out ReopenNtHandle => %p, 0x%lX\n", *ph, sc));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DupNtHandle, public
+//
+// Synopsis: Duplicates an NT handle
+//
+// Arguments: [h] - Handle
+// [ph] - Return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ph]
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE DupNtHandle(HANDLE h, HANDLE *ph)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ HANDLE th;
+
+ ssDebugOut((DEB_ITRACE, "In DupNtHandle(%p, %p)\n", h, ph));
+ nts = NtDuplicateObject(NtCurrentProcess(), h, NtCurrentProcess(), &th, 0,
+ 0, DUPLICATE_SAME_ATTRIBUTES |
+ DUPLICATE_SAME_ACCESS);
+ if (!NT_SUCCESS(nts))
+ {
+ sc = NtStatusToScode(nts);
+ }
+ else
+ {
+ sc = S_OK;
+ *ph = th;
+ }
+ ssDebugOut((DEB_ITRACE, "Out DupNtHandle => %p, 0x%lX\n", *ph, sc));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: StorageTypeToFileDir, public
+//
+// Synopsis: converts a NT StorageType into a FileDir type
+//
+// Arguments: [storageType] - returned from NtQueryOleAllInformation
+// [pfd] - FILEDIR used by storage layer
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-1995 HenryLee created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+SCODE StorageTypeToFileDir (ULONG storageType, FILEDIR *pfd)
+{
+ SCODE sc = S_OK;
+ switch (storageType)
+ {
+ case StorageTypeDirectory:
+ *pfd = FD_DIR;
+ break;
+ case StorageTypeFile:
+ *pfd = FD_FILE;
+ break;
+ case StorageTypeStructuredStorage:
+ case StorageTypeEmbedding:
+ *pfd = FD_STORAGE;
+ break;
+
+ case StorageTypeStream:
+ *pfd = FD_STREAM;
+ break;
+
+ case StorageTypeCatalog:
+ *pfd = FD_CATALOG;
+ break;
+
+ case StorageTypeJunctionPoint:
+ *pfd = FD_JUNCTION;
+ break;
+
+ default:
+ sc = STG_E_INVALIDPARAMETER;
+ ssAssert (!"Unhandled storage type");
+ break;
+ }
+ return sc;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Function: template<class T> FillSTATSTG, public
+//
+// Synopsis: Fills out a STATSTG by retrieving information from NT handle
+// FillSTATSTG<FILE_ALL_INFORMATION*> is instantiated for
+// non-OFS volumes, and FillSTATSTG<FILE_OLE_ALL_INFORMATION*>
+// is instantiated for OFS volumes
+//
+// Arguments: [h] - Handle
+// [grfStatFlag] - Stat flags
+// [cbExtra] - Extra space to allocate for name,
+// used for faking \CONTENTS on file contents stream
+// [pstat] - STATSTG to fill in
+// [pwcsName] - Name to fill in or NULL
+// [pfd] - Return dir/file
+//
+// Returns: Appropriate status code
+//
+// BUGBUG: This call should retrieve the storage type from the info class
+// in order to set the PFD field.
+//
+// Modifies: [pstat]
+// [pwcsName]
+// [pfDir]
+//
+// History: 14-Jul-1995 HenryLee created
+//
+// Notes: Doesn't fill in grfMode because full information
+// can't be retrieved
+//
+//----------------------------------------------------------------------------
+SCODE FillSTATSTG (FILE_ALL_INFORMATION *pfai,
+ DWORD grfStatFlag,
+ ULONG cbExtra,
+ STATSTG *pstat,
+ WCHAR *pwcsName,
+ DWORD *pdwAttrs,
+ FILEDIR *pfd)
+{
+ SCODE sc = S_OK;
+ WCHAR awcName[MAX_PATH];
+ WCHAR *pwcs = NULL;
+
+ if (grfStatFlag != STATFLAG_NONAME || pwcsName != NULL)
+ {
+ memcpy(awcName, pfai->NameInformation.FileName,
+ pfai->NameInformation.FileNameLength);
+ *(WCHAR *)((BYTE *)awcName+pfai->NameInformation.FileNameLength)=L'\0';
+ }
+
+ if (grfStatFlag != STATFLAG_NONAME)
+ { // add 3 characters for drive letter and trailing wide NULL
+ sc = GetScode(CoMemAlloc((lstrlenW(awcName)+3)*sizeof(WCHAR)+
+ cbExtra+sizeof(WCHAR), (void **)&pwcs));
+ }
+ else
+ sc = S_OK;
+
+ if (SUCCEEDED(sc))
+ {
+ if (pwcs)
+ lstrcpyW(pwcs, awcName);
+ if (pwcsName)
+ lstrcpyW(pwcsName, awcName);
+
+ pstat->pwcsName = pwcs;
+ pstat->type = STGTY_STORAGE;
+ pstat->cbSize = *(ULARGE_INTEGER *)&pfai->StandardInformation.
+ EndOfFile;
+ LARGE_INTEGER_TO_FILETIME(&pfai->BasicInformation.LastWriteTime,
+ &pstat->mtime);
+ LARGE_INTEGER_TO_FILETIME(&pfai->BasicInformation.CreationTime,
+ &pstat->ctime);
+ LARGE_INTEGER_TO_FILETIME(&pfai->BasicInformation.LastAccessTime,
+ &pstat->atime);
+ pstat->grfMode = 0;
+ pstat->grfLocksSupported = 0;
+ if (pdwAttrs) *pdwAttrs = pfai->BasicInformation.FileAttributes;
+
+ if (pfai->StandardInformation.Directory)
+ {
+ pstat->STATSTG_dwStgFmt = STGFMT_DIRECTORY;
+ *pfd = FD_DIR;
+ }
+ else
+ {
+ pstat->STATSTG_dwStgFmt = STGFMT_DOCUMENT;
+ *pfd = FD_STORAGE;
+ }
+ }
+ return sc;
+}
+
+SCODE FillOleSTATSTG (FILE_OLE_ALL_INFORMATION *pfai,
+ DWORD grfStatFlag,
+ ULONG cbExtra,
+ STATSTG *pstat,
+ WCHAR *pwcsName,
+ DWORD *pdwAttrs,
+ FILEDIR *pfd)
+{
+ SCODE sc = S_OK;
+ WCHAR awcName[MAX_PATH];
+ WCHAR *pwcs = NULL;
+
+ if (grfStatFlag != STATFLAG_NONAME || pwcsName != NULL)
+ {
+ memcpy(awcName, pfai->NameInformation.FileName,
+ pfai->NameInformation.FileNameLength);
+ *(WCHAR *)((BYTE *)awcName+pfai->NameInformation.FileNameLength)=L'\0';
+ }
+
+ if (grfStatFlag != STATFLAG_NONAME)
+ { // add 3 characters for drive letter and trailing wide NULL
+ sc = GetScode(CoMemAlloc((lstrlenW(awcName)+3)*sizeof(WCHAR)+
+ cbExtra+sizeof(WCHAR), (void **)&pwcs));
+ }
+ else
+ sc = S_OK;
+
+ if (SUCCEEDED(sc))
+ {
+ if (pwcs)
+ lstrcpyW(pwcs, awcName);
+ if (pwcsName)
+ lstrcpyW(pwcsName, awcName);
+
+ pstat->pwcsName = pwcs;
+ pstat->type = STGTY_STORAGE;
+ pstat->cbSize = *(ULARGE_INTEGER *)&pfai->StandardInformation.
+ EndOfFile;
+
+ LARGE_INTEGER_TO_FILETIME(&pfai->BasicInformation.LastWriteTime,
+ &pstat->mtime);
+ LARGE_INTEGER_TO_FILETIME(&pfai->BasicInformation.CreationTime,
+ &pstat->ctime);
+ LARGE_INTEGER_TO_FILETIME(&pfai->BasicInformation.LastAccessTime,
+ &pstat->atime);
+
+ pstat->grfMode = 0;
+ pstat->grfLocksSupported = 0;
+ if (pdwAttrs) *pdwAttrs = pfai->BasicInformation.FileAttributes;
+
+ if (pfai->StandardInformation.Directory)
+ {
+ pstat->STATSTG_dwStgFmt = STGFMT_DIRECTORY;
+ *pfd = FD_DIR;
+ }
+ else if (pfai->StorageType == StorageTypeStream)
+ {
+ if ((pfai->BasicInformation.FileAttributes &
+ FILE_ATTRIBUTE_PROPERTY_SET) == 0)
+ {
+ pstat->mtime.dwHighDateTime = pstat->mtime.dwLowDateTime = 0;
+ }
+ pstat->ctime.dwHighDateTime = pstat->ctime.dwLowDateTime = 0;
+ pstat->atime.dwHighDateTime = pstat->atime.dwLowDateTime = 0;
+ pstat->STATSTG_dwStgFmt = STGFMT_DOCUMENT;
+ *pfd = FD_STREAM;
+ }
+ else
+ {
+ pstat->STATSTG_dwStgFmt = STGFMT_DOCUMENT;
+ *pfd = FD_STORAGE;
+ }
+ }
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StatNtHandle, public
+//
+// Synopsis: Fills out a STATSTG by retrieving information for an NT handle
+//
+// Arguments: [h] - Handle
+// [grfStatFlag] - Stat flags
+// [cbExtra] - Extra space to allocate for name,
+// used for faking \CONTENTS on file contents stream
+// [pstat] - STATSTG to fill in
+// [pwcsName] - Name to fill in or NULL
+// [pfd] - Return dir/file
+//
+// Returns: Appropriate status code
+//
+// BUGBUG: This call should retrieve the storage type from the info class
+// in order to set the PFD field.
+//
+// Modifies: [pstat]
+// [pwcsName]
+// [pfDir]
+//
+// History: 09-Jul-93 DrewB Created
+// 24-Mar-95 HenryLee remove GetFullPathName, use stored drive
+//
+// Notes: Doesn't fill in grfMode because full information
+// can't be retrieved
+//
+//----------------------------------------------------------------------------
+
+SAFE_HEAP_PTR(SafeFai, FILE_ALL_INFORMATION);
+SAFE_HEAP_PTR(SafeFoai, FILE_OLE_ALL_INFORMATION);
+
+SCODE StatNtHandle(HANDLE h,
+ DWORD grfStatFlag,
+ ULONG cbExtra,
+ STATSTG *pstat,
+ WCHAR *pwcsName,
+ DWORD *pdwAttrs,
+ FILEDIR *pfd)
+{
+ NTSTATUS nts;
+ SCODE sc;
+ IO_STATUS_BLOCK iosb;
+ SafeFai pfai;
+ SafeFoai pfoai;
+ ULONG cbFai;
+ BOOL fOfs = TRUE;
+
+ ssDebugOut((DEB_ITRACE, "In StatNtHandle(%p, 0x%lX, %lu, %p, %p, %p)\n",
+ h, grfStatFlag, cbExtra, pstat, pwcsName, pfd));
+
+ cbFai = sizeof(FILE_OLE_ALL_INFORMATION) +
+ MAXIMUM_FILENAME_LENGTH*sizeof(WCHAR);
+ pfoai.Attach((FILE_OLE_ALL_INFORMATION *)new BYTE[cbFai]);
+ ssMem((FILE_OLE_ALL_INFORMATION *)pfoai);
+
+ nts = NtQueryInformationFile(h, &iosb, pfoai, cbFai, FileOleAllInformation);
+ if (!NT_SUCCESS(nts))
+ {
+ fOfs = FALSE;
+ cbFai = sizeof(FILE_ALL_INFORMATION)+
+ MAXIMUM_FILENAME_LENGTH*sizeof(WCHAR);
+ pfai.Attach((FILE_ALL_INFORMATION *)new BYTE[cbFai]);
+ ssMem((FILE_ALL_INFORMATION *)pfai);
+
+ nts = NtQueryInformationFile(h, &iosb, pfai, cbFai, FileAllInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+
+ sc = FillSTATSTG ((FILE_ALL_INFORMATION *) pfai,
+ grfStatFlag, cbExtra, pstat, pwcsName, pdwAttrs, pfd);
+
+ if (SUCCEEDED(sc))
+ {
+ pstat->clsid = CLSID_NULL;
+ pstat->grfStateBits = 0;
+ }
+ }
+ else
+ {
+ sc = FillOleSTATSTG ((FILE_OLE_ALL_INFORMATION *)pfoai,
+ grfStatFlag, cbExtra, pstat, pwcsName, pdwAttrs, pfd);
+
+ if (SUCCEEDED(sc))
+ {
+ pstat->clsid = pfoai->OleClassIdInformation.ClassId;
+ pstat->grfStateBits = pfoai->OleStateBits;
+ DWORD dwStgfmt;
+ if (SUCCEEDED(sc = StorageTypeToFileDir (pfoai->StorageType,pfd)) &&
+ SUCCEEDED(sc = DetermineHandleStgType (h,*pfd,&dwStgfmt)))
+ {
+ pstat->STATSTG_dwStgFmt = dwStgfmt;
+ }
+ }
+ }
+
+EH_Err:
+ ssDebugOut((DEB_ITRACE, "Out StatNtHandle => 0x%lX\n", sc));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: HandleRefersToOfsVolume, public
+//
+// Synopsis: Determines whether the given handle refers to an OFS volume
+//
+// Arguments: [h] - Handle
+//
+// Returns: Appropriate status code
+//
+// History: 21-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE HandleRefersToOfsVolume(HANDLE h)
+{
+ NTSTATUS nts;
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In HandleRefersToOfsVolume(%p)\n", h));
+
+ nts = OFSGetVersion(h, NULL);
+ if (!NT_SUCCESS(nts))
+ {
+ // BUGBUG - It would be nice to be able to distinguish
+ // failure from unsupported but there doesn't seem to
+ // be any way to do it
+ // For the moment, simply return S_FALSE. This will cause
+ // all failures to be retried as non-OFS operations which
+ // should fail also
+ sc = S_FALSE;
+ }
+ else
+ {
+ sc = S_OK;
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out HandleRefersToOfsVolume => %lX\n", sc));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: RefersToOfsVolume, public
+//
+// Synopsis: Determines whether the given path refers to something
+// on an OFS volume
+//
+// Arguments: [pwcsPath] - Path
+// [co] - create or open case
+//
+// Returns: Appropriate status code
+//
+// History: 15-Jul-93 DrewB Created
+//
+// Algorithm: Attempt to open the parent and return HandleRTOV
+//
+// Notes: The path doesn't have to refer to an existing object
+//
+//----------------------------------------------------------------------------
+
+SCODE RefersToOfsVolume(WCHAR const *pwcsPath, CREATEOPEN co)
+{
+ SCODE sc;
+ WCHAR awcFullPath[_MAX_PATH];
+ HANDLE h;
+
+ ssDebugOut((DEB_ITRACE, "In RefersToOfsVolume(%ws)\n", pwcsPath));
+
+ // Temporary files are always treated as non-OFS
+ if (pwcsPath == NULL)
+ ssErr(EH_Err, S_FALSE);
+
+ if (GetFullPathName(pwcsPath, _MAX_PATH, awcFullPath, NULL) == 0)
+ sc = LAST_STG_SCODE;
+ else
+ {
+ if (co == CO_CREATE)
+ {
+ WCHAR *pwc;
+
+ // Locate last separator
+ pwc = wcsrchr(awcFullPath, L'\\');
+
+ // A fully qualified path is guaranteed to have at least one '\'
+ ssAssert(pwc != NULL);
+
+ // Is this a UNC path or a device path?
+ if (lstrlenW(awcFullPath) >= 2 &&
+ memcmp(awcFullPath, L"\\\\", 2*sizeof(WCHAR)) == 0)
+ {
+ WCHAR *pwcMach, *pwcShare;
+
+ // Find separator between machine and share
+ pwcMach = wcschr(awcFullPath+2, L'\\');
+ ssAssert(pwcMach != NULL);
+
+ // Find separator after share
+ pwcShare = wcschr(pwcMach+1, L'\\');
+
+ // If there isn't a separator after the share, add one
+ // The path must be of the form \\mach\share so we can
+ // just stick a \ on the end
+ if (pwcShare == NULL)
+ {
+ pwcShare = awcFullPath+lstrlenW(awcFullPath);
+ *pwcShare = L'\\';
+ pwc = pwcShare;
+ }
+ else
+ {
+ // If we're not at the root (share separator), back up one
+ // so awcFullPath refers to the parent
+ if (pwc != pwcShare)
+ pwc--;
+ }
+ }
+ else
+ {
+ // If we're not at the root, back up one so awcFullPath refers
+ // to the parent
+ if (pwc != wcschr(awcFullPath, L'\\'))
+ pwc--;
+ }
+
+ // Terminate after parent name
+ *++pwc = 0;
+ } // endif (co == CO_CREATE)
+ else
+ {
+ ssAssert (co == CO_OPEN);
+ lstrcpyW (awcFullPath, pwcsPath);
+ }
+
+ ssChk(GetNtHandle(NULL, awcFullPath, STGM_READ, 0, CO_OPEN,
+ (co == CO_CREATE ? FD_DIR : FD_DEFAULT), NULL, &h));
+ sc = HandleRefersToOfsVolume(h);
+ dbgNtVerSucc(NtClose(h));
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out RefersToOfsVolume => %x\n", sc));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetTimes, public
+//
+// Synopsis: Sets the times for a handle
+//
+// Arguments: [h] - Handle
+// [pctime] - Creation time or NULL
+// [patime] - Modification time or NULL
+// [pmtime] - Access time or NULL
+//
+// Returns: Appropriate status code
+//
+// History: 22-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE SetTimes(HANDLE h,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ IO_STATUS_BLOCK iosb;
+ NTSTATUS nts;
+ FILE_BASIC_INFORMATION fbi;
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In SetTimes(%p, %p, %p, %p)\n",
+ h, pctime, patime, pmtime));
+
+ if (pctime)
+ FILETIME_TO_LARGE_INTEGER(pctime, &fbi.CreationTime);
+ else
+ fbi.CreationTime.LowPart = fbi.CreationTime.HighPart = 0;
+ if (patime)
+ FILETIME_TO_LARGE_INTEGER(patime, &fbi.LastAccessTime);
+ else
+ fbi.LastAccessTime.LowPart = fbi.LastAccessTime.HighPart = 0;
+ if (pmtime)
+ FILETIME_TO_LARGE_INTEGER(pmtime, &fbi.LastWriteTime);
+ else
+ fbi.LastWriteTime.LowPart = fbi.LastWriteTime.HighPart = 0;
+ fbi.ChangeTime.LowPart = fbi.ChangeTime.HighPart = 0;
+ fbi.FileAttributes = 0;
+ nts = NtSetInformationFile(h, &iosb, &fbi,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_ITRACE, "Out SetTimes => %lX\n", sc));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetNtFileAttributes, public
+//
+// Synopsis: Sets the times for a handle
+//
+// Arguments: [h] - Handle
+// [grfAttr] - File Attributes
+//
+// Returns: Appropriate status code
+//
+// History: 12-Jul-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+SCODE SetNtFileAttributes(HANDLE h, ULONG grfAttr)
+{
+ IO_STATUS_BLOCK iosb;
+ NTSTATUS nts;
+ FILE_BASIC_INFORMATION fbi = {{0,0},{0,0},{0,0},{0,0},0};
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In SetNtFileAttributes(%p, %x)\n", h, grfAttr));
+
+ fbi.FileAttributes = grfAttr;
+ nts = NtSetInformationFile(h, &iosb, &fbi,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_ITRACE, "Out SetNtFileAttributes => %lX\n", sc));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetFileOrDirHandle, public
+//
+// Synopsis: Opens either a file or directory and returns the handle
+//
+// Arguments: [hParent] - Parent handle or NULL
+// [pwcsName] - Child name or full path
+// [grfMode] - Mode
+// [ph] - Handle return
+// [pfd] - FILEDIR return or NULL
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ph]
+// [pfd]
+//
+// History: 22-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE GetFileOrDirHandle(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ HANDLE *ph,
+ CLSID *pclsid,
+ BOOL *pfOfs,
+ FILEDIR *pfd)
+{
+ SCODE sc;
+ FILEDIR fd;
+
+ if (pfd == NULL)
+ pfd = &fd;
+
+ ssDebugOut((DEB_ITRACE, "In GetFileOrDirHandle("
+ "%p, %ws, %lX, %p, %p)\n", hParent, pwcsName, grfMode, ph,
+ pfd));
+
+ sc = GetNtHandle (hParent,pwcsName,grfMode,0,CO_OPEN,FD_DEFAULT,NULL, ph);
+ if (!FAILED (sc))
+ {
+ NTSTATUS Status;
+ IO_STATUS_BLOCK iosb;
+ FILE_OLE_ALL_INFORMATION foai;
+
+ Status = NtQueryInformationFile(
+ *ph,
+ &iosb,
+ &foai,
+ sizeof(foai),
+ FileOleAllInformation);
+
+ if (NT_SUCCESS(Status) ||
+ (Status == STATUS_BUFFER_OVERFLOW &&
+ iosb.Information == sizeof(foai)))
+ {
+ StorageTypeToFileDir (foai.StorageType, pfd);
+ if (pclsid != NULL) *pclsid = foai.OleClassIdInformation.ClassId;
+ if (pfOfs != NULL)
+ if (foai.LastChangeUsn != 0)
+ *pfOfs = TRUE; // real OFS implementation
+ else
+ *pfOfs = FALSE; // FAT or NTFS supporting FileOleAllInfo
+ }
+ else
+ {
+ // Since the operation failed, we are probably dealing with
+ // a non-OFS partition. We need to disinguish a file from a directory
+ // BUGBUG: [mikese] eventually, maybe all file systems will support
+ // FileAllOleInfo and we won't need this part.
+ FILE_BASIC_INFORMATION fbi;
+ Status = NtQueryInformationFile (
+ *ph,
+ &iosb,
+ &fbi,
+ sizeof(fbi),
+ FileBasicInformation );
+ if ( NT_SUCCESS(Status) &&
+ (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ *pfd = FD_DIR;
+ }
+ else
+ {
+ // assume we have a docfile in a file
+ *pfd = FD_FILE;
+ }
+ if (pclsid != NULL) *pclsid = CLSID_NULL;
+ if (pfOfs != NULL) *pfOfs = FALSE;
+ }
+
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out GetFileOrDirHandle => %p\n", *ph));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: NameNtHandle, public
+//
+// Synopsis: Obtains the full path name from a file handle
+//
+// Arguments: [handle] - file handle
+// [wcDrive] - drive letter
+// [wcBuffer] - output result
+// [wcFile] - append optional filename
+//
+// Returns: Appropriate status code
+//
+// History: 02-Jun-1995 HenryLee created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+SAFE_HEAP_PTR(SafeFni, FILE_NAME_INFORMATION);
+
+SCODE NameNtHandle (HANDLE h, WCHAR wcDrive, WCHAR *wcBuffer,
+ const WCHAR *wcFile)
+{
+ NTSTATUS nts;
+ SCODE sc = S_OK;
+ IO_STATUS_BLOCK iosb;
+ SafeFni pfni;
+ ULONG cbFni;
+
+ cbFni=sizeof(FILE_NAME_INFORMATION)+MAXIMUM_FILENAME_LENGTH*sizeof(WCHAR);
+ pfni.Attach((FILE_NAME_INFORMATION *)new BYTE[cbFni]);
+ ssMem((FILE_NAME_INFORMATION *)pfni);
+ nts=NtQueryInformationFile(h,&iosb,pfni,cbFni,FileNameInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+
+ memcpy (wcBuffer, pfni->FileName, pfni->FileNameLength);
+ *(WCHAR *)((BYTE *)wcBuffer+pfni->FileNameLength) = L'\0';
+ SetDriveLetter (wcBuffer, wcDrive);
+
+ if (wcFile != NULL)
+ {
+ lstrcatW (wcBuffer, L"\\");
+ lstrcatW (wcBuffer, wcFile);
+ }
+EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/fsstg/omarshal.cxx b/private/ole32/stg/fsstg/omarshal.cxx
new file mode 100644
index 000000000..bd2e5044f
--- /dev/null
+++ b/private/ole32/stg/fsstg/omarshal.cxx
@@ -0,0 +1,764 @@
+/+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: omarshal.cxx
+//
+// Contents: Implementation of CNtHandleUnmarshalFactory
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+#include <headers.cxx>
+#pragma hdrstop
+
+#include <omarshal.hxx>
+#include <odocstg.hxx>
+#include <odocstm.hxx>
+
+extern const CLSID CLSID_NtHandleMarshal = {0x521a28f2,0xe40b,0x11ce,
+ {0xb2,0xc9,0x00,0xaa,0x00,0x68,0x09,0x37}};
+// This GUID is also located in \nt\public\oak\bin\oleext.ini
+
+//+--------------------------------------------------------------
+//
+// Member: ::sCNtHandleUnmarshalFactory, public static
+//
+// Synopsis: Overloaded allocator
+//
+// Returns: Memory block for CNtHandleUnmarshalFactory instance
+//
+// History: 25-Oct-95 HenryLee Created
+//
+// Notes: We only need one instance of CNtHandleUnmarshalFactory.
+//
+//---------------------------------------------------------------
+
+CNtHandleUnmarshalFactory sCNtHandleUnmarshalFactory;
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleUnmarshalFactory::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CNtHandleUnmarshalFactory::AddRef(void)
+{
+ ssDebugOut((DEB_TRACE, "Stb CNtHandleUnmarshalFactory::AddRef:%p => %ld\n",
+ this, _AddRef()));
+ return _AddRef();
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleUnmarshalFactory::Release, public
+//
+// Synopsis: Releases resources
+//
+// Returns: Appropriate status code
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CNtHandleUnmarshalFactory::Release(void)
+{
+ const LONG lRet = 0;
+
+ ssDebugOut((DEB_TRACE, "Stb CNtHandleUnmarshalFactory::Release:%p => %ld\n",
+ this, lRet));
+ return lRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleUnmarshalFactory::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CNtHandleUnmarshalFactory::QueryInterface(REFIID riid,
+ void **ppv)
+{
+ SCODE sc = S_OK;
+
+ ssDebugOut((DEB_TRACE, "In CNtHandleUnmarshalFactory::QueryInterface:%p("
+ "riid, %p)\n", this, ppv));
+ TRY
+ {
+ ssChk(Validate());
+ ssChk(ValidateOutPtrBuffer(ppv));
+ *ppv = NULL;
+ ssChk(ValidateIid(riid));
+ if (IsEqualIID(riid, IID_IClassFactory) ||
+ IsEqualIID(riid, IID_IUnknown))
+ {
+ _AddRef();
+ *ppv = (IClassFactory *)this;
+ }
+ else if (IsEqualIID(riid, IID_IMarshal))
+ {
+ _AddRef();
+ *ppv = (IMarshal *)this;
+ }
+ else
+ ssErr(EH_Err, E_NOINTERFACE);
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ ssDebugOut((DEB_TRACE, "Out CNtHandleUnmarshalFactory::QueryInterface => "
+ "%p\n", *ppv));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleUnmarshalFactory::GetUnmarshalClass, public
+//
+// Synopsis: Returns the class ID
+//
+// Arguments: [riid] - IID of object
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+// [pcid] - CLSID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcid]
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtHandleUnmarshalFactory::GetUnmarshalClass(REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pcid)
+{
+ ssDebugOut((DEB_TRACE, "Stb CNtHandleUnmarshalFactory::GetUnmarshalClass("
+ "%p, riid, %p, %lu, %p, %lu, %p)\n", this, pv, dwDestContext,
+ pvDestContext, mshlflags, pcid));
+ return ssResult(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleUnmarshalFactory::GetMarshalSizeMax, public
+//
+// Synopsis: Returns the size needed for the marshal buffer
+//
+// Arguments: [iid] - IID of object being marshaled
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+// [pcbSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbSize]
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtHandleUnmarshalFactory::GetMarshalSizeMax(REFIID iid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pcbSize)
+{
+ ssDebugOut((DEB_TRACE, "Stb CNtHandleUnmarshalFactory::GetMarshalSizeMax("
+ "%p, riid, %p, %lu, %p, %lu, %p)\n",
+ this, pv, dwDestContext, pvDestContext, mshlflags, pcbSize));
+ return ssResult(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleUnmarshalFactory::MarshalInterface, public
+//
+// Synopsis: Marshals a given object
+//
+// Arguments: [pstStm] - Stream to write marshal data into
+// [iid] - Interface to marshal
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+//
+// Returns: Appropriate status code
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtHandleUnmarshalFactory::MarshalInterface(IStream *pstStm,
+ REFIID iid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ ssDebugOut((DEB_TRACE, "Stb CNtHandleUnmarshalFactory::MarshalInterface("
+ "%p, %p, riid, %p, %lu, %p, %lu). Context == %lX\n",
+ this, pstStm, pv, dwDestContext, pvDestContext, mshlflags,
+ (ULONG)GetCurrentContextId()));
+ return ssResult(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleUnmarshalFactory::UnmarshalInterface, public
+//
+// Synopsis: Calls through to DfUnmarshalInterface
+//
+// Arguments: [pstStm] - Marshal stream
+// [riid] - IID of object to unmarshal
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtHandleUnmarshalFactory::UnmarshalInterface(IStream *pstStm,
+ REFIID iid,
+ void **ppvObj)
+{
+ SCODE sc = S_OK;
+ ULONG cbRead;
+ DWORD mshlflags;
+ SafeIUnknown punk;
+ CNtHandleMarshalPacket NtHandlePacket;
+ HANDLE hTarget = NULL;
+ SafeNtHandle hSourceProcess, hTargetProcess;
+ NTSTATUS nts;
+
+ ssDebugOut((DEB_TRACE, "In CNtHandleUnmarshalInterface::UnmarhalInterface"
+ " (%p, ?, %p)\n", pstStm, ppvObj));
+
+ ssChk(ValidateOutPtrBuffer(ppvObj));
+ *ppvObj = NULL;
+ ssChk(ValidateInterface(pstStm, IID_IStream));
+ ssChk(ValidateIid(iid));
+
+ ssChk(pstStm->Read(&NtHandlePacket, sizeof(NtHandlePacket), &cbRead));
+ if (cbRead != sizeof(NtHandlePacket))
+ ssErr(EH_Err, STG_E_READFAULT);
+
+ if (!(IsEqualIID(NtHandlePacket.iid, iid)) &&
+ !(IsEqualIID(iid, IID_IUnknown)))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+
+ if ((hSourceProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE,
+ NtHandlePacket.dwPId)) == NULL)
+ ssErr (EH_Err, STG_E_INVALIDHANDLE);
+
+ if ((hTargetProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE,
+ GetCurrentProcessId())) == NULL)
+ ssErr (EH_Err, STG_E_INVALIDHANDLE);
+
+ // The OLE spec says that a marshaled object may be unmarshaled
+ // zero or more times from the same packet. We don't support this here.
+ // BUGBUG only 1 object can be created per marshaling packet.
+ if (DuplicateHandle (hSourceProcess, NtHandlePacket.hSource,
+ hTargetProcess, &hTarget, NULL, FALSE,
+ DUPLICATE_CLOSE_SOURCE |
+ DUPLICATE_SAME_ACCESS) == FALSE)
+ {
+ ssErr (EH_Err, WIN32_SCODE(GetLastError()));
+ }
+
+ switch (NtHandlePacket.dwStgfmt)
+ {
+ case STGFMT_DOCUMENT:
+ if (IsEqualIID(iid, IID_IStream))
+ {
+ SafeCOfsDocStream pstm;
+ pstm.Attach (new COfsDocStream);
+ ssMem ((COfsDocStream *) pstm);
+ ssChk (pstm->InitFromHandle(hTarget, NULL, NtHandlePacket.grfMode,
+ FALSE));
+ TRANSFER_INTERFACE(pstm, IStream, ppvObj);
+ }
+ else if (IsEqualIID(iid, IID_IStorage))
+ {
+ SafeCOfsDocStorage pstg;
+ pstg.Attach (new COfsDocStorage);
+ ssMem ((COfsDocStorage *) pstg);
+ ssChk (pstg->InitFromHandle (hTarget, NULL,
+ NtHandlePacket.grfMode, TRUE));
+ TRANSFER_INTERFACE(pstg, IStorage, ppvObj);
+ }
+ else
+ sc = E_NOINTERFACE;
+ break;
+ default:
+ sc = STG_E_INVALIDPARAMETER;
+ }
+
+#if DBG
+ if (SUCCEEDED(sc))
+ {
+ void *pvCheck;
+ ssAssert( S_OK==((IUnknown*)*ppvObj)->QueryInterface(iid, &pvCheck));
+ ssAssert( pvCheck == *ppvObj );
+ ((IUnknown*)pvCheck)->Release();
+ }
+#endif
+
+ ssDebugOut((DEB_TRACE,"Out CNtHandleUnmarshalFactory::UnmarshalInterface "
+ "=> %p\n", *ppvObj));
+EH_Err:
+ if (!SUCCEEDED(sc) && hTarget != NULL) // something went wrong
+ nts = NtClose (hTarget); // cleanup the duped handle
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleUnmarshalFactory::ReleaseMarshalData, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [pstStm] -
+//
+// Returns: Appropriate status code
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtHandleUnmarshalFactory::ReleaseMarshalData(IStream *pstStm)
+{
+ SCODE sc = S_OK;
+ ULONG cbRead;
+ DWORD mshlflags;
+ CNtHandleMarshalPacket NtHandlePacket;
+
+ ssDebugOut((DEB_TRACE, "In CNtHandleUnmarshalFactory::ReleaseMarshalData("
+ "%p,%p)\n", this, pstStm));
+
+ ssChk(ValidateInterface(pstStm, IID_IStream));
+
+ ssChk(pstStm->Read(&NtHandlePacket, sizeof(NtHandlePacket), &cbRead));
+ if (cbRead != sizeof(NtHandlePacket))
+ ssErr(EH_Err, STG_E_READFAULT);
+
+ ssDebugOut((DEB_TRACE, "CNtHandleUnmarshalFactory::ReleaseMarshalData, "
+ " this == %p, sc == %lX\n", this, sc));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleUnmarshalFactory::DisconnectObject, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [dwRevserved] -
+//
+// Returns: Appropriate status code
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtHandleUnmarshalFactory::DisconnectObject(DWORD dwReserved)
+{
+ ssDebugOut((DEB_TRACE, "Stb CNtHandleUnmarshalFactory::DisconnectObject("
+ " %p,%lu)\n", this, dwReserved));
+ return ssResult(S_OK);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtHandleUnmarshalFactory::CreateInstance, public
+//
+// Synopsis: Creates an instance of the NtHandle unmarshaller
+//
+// Arguments: [pUnkOuter] -
+// [riid] - IID of object to create
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CNtHandleUnmarshalFactory::CreateInstance(IUnknown *pUnkOuter,
+ REFIID riid,
+ LPVOID *ppv)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CNtHandleUnmarshalFactory::CreateInstance:%p("
+ "%p, riid, %p)\n", this, pUnkOuter, ppv));
+ TRY
+ {
+ ssChk(Validate());
+ ssChk(ValidatePtrBuffer(ppv));
+ *ppv = NULL;
+ ssChk(ValidateIid(riid));
+ if (pUnkOuter != NULL || !IsEqualIID(riid, IID_IMarshal))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ _AddRef();
+ *ppv = (IMarshal *)this;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ ssDebugOut((DEB_TRACE, "Out CNtHandleUnmarshalFactory::CreateInstance => "
+ "%p\n", ppv));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtHandleUnmarshalFactory::LockServer, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [fLock] -
+//
+// Returns: Appropriate status code
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CNtHandleUnmarshalFactory::LockServer(BOOL fLock)
+{
+ ssDebugOut((DEB_TRACE, "Stb CNtHandleUnmarshalFactory::LockServer("
+ " %p,%d)\n", this, fLock));
+ return ssResult(S_OK);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleMarshal::GetUnmarshalClass, public
+//
+// Synopsis: Returns the class ID
+//
+// Arguments: [riid] - IID of object
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+// [pcid] - CLSID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcid]
+//
+// History: 04-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtHandleMarshal::GetUnmarshalClass(REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pcid)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CNtHandleMarshal::GetUnmarshalClass:%p("
+ "riid, %p, %lu, %p, %lu, %p)\n", this,
+ pv, dwDestContext, pvDestContext, mshlflags, pcid));
+
+ UNREFERENCED_PARM(pv);
+ UNREFERENCED_PARM(mshlflags);
+
+ ssChk(ValidateOutBuffer(pcid, sizeof(CLSID)));
+ *pcid = CLSID_NULL;
+ ssChk(ValidateIid(riid));
+
+ if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
+ {
+ IMarshal *pmsh;
+ if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
+ dwDestContext, pvDestContext,
+ mshlflags, &pmsh)))
+ {
+ sc = GetScode(pmsh->GetUnmarshalClass(riid, pv, dwDestContext,
+ pvDestContext, mshlflags,
+ pcid));
+ pmsh->Release();
+ }
+ }
+ else if (pvDestContext != NULL)
+ {
+ sc = STG_E_INVALIDPARAMETER;
+ }
+ else
+ {
+ *pcid = CLSID_NtHandleMarshal;
+ }
+
+ ssDebugOut((DEB_TRACE, "Out CNtHandle::GetUnmarshalClass\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleMarshal::GetMarshalSizeMax, public
+//
+// Synopsis: Returns the size needed for the marshal buffer
+//
+// Arguments: [riid] - IID of object being marshaled
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+// [pcbSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbSize]
+//
+// History: 04-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtHandleMarshal::GetMarshalSizeMax(REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pcbSize)
+{
+ SCODE sc = S_OK;
+
+ UNREFERENCED_PARM(pv);
+ ssDebugOut((DEB_TRACE, "In CNtHandleMarshal::GetMarshalSizeMax:%p("
+ "riid, %p, %lu, %p, %lu, %p)\n", this,
+ pv, dwDestContext, pvDestContext, mshlflags, pcbSize));
+
+ if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
+ {
+ IMarshal *pmsh;
+ if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
+ dwDestContext, pvDestContext,
+ mshlflags, &pmsh)))
+ {
+ sc = GetScode(pmsh->GetMarshalSizeMax(riid, pv, dwDestContext,
+ pvDestContext, mshlflags,
+ pcbSize));
+ pmsh->Release();
+ }
+ }
+ else if (pvDestContext != NULL)
+ {
+ ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+ }
+ else
+ {
+ *pcbSize = sizeof(CNtHandleMarshalPacket);
+ }
+
+ ssDebugOut((DEB_TRACE, "Out CNtHandleMarshal::GetMarshalSizeMax\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleMarshal::MarshalInterface, public
+//
+// Synopsis: Marshals a given object
+//
+// Arguments: [pstStm] - Stream to write marshal data into
+// [riid] - Interface to marshal
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+//
+// Returns: Appropriate status code
+//
+// History: 18-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtHandleMarshal::MarshalInterface(IStream *pstStm,
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ SCODE sc = S_OK;
+ NTSTATUS nts;
+ HANDLE hDup = INVALID_HANDLE_VALUE;
+
+ ssDebugOut((DEB_TRACE, "In CNtHandleMarshal::MarshalInterface:%p("
+ "%p, riid, %p, %lu, %p, %lu)\n", this, pstStm, pv,
+ dwDestContext, pvDestContext, mshlflags));
+
+ UNREFERENCED_PARM(pv);
+ ssAssert (_handle != NULL);
+
+ if ((dwDestContext != MSHCTX_LOCAL) && (dwDestContext != MSHCTX_INPROC))
+ {
+ IMarshal *pmsh;
+ if (SUCCEEDED(sc = CoGetStandardMarshal(riid, (IUnknown *)pv,
+ dwDestContext, pvDestContext,
+ mshlflags, &pmsh)))
+ {
+ sc = GetScode(pmsh->MarshalInterface(pstStm, riid, pv,
+ dwDestContext, pvDestContext,
+ mshlflags));
+ pmsh->Release();
+ }
+ }
+ else if (pvDestContext != NULL)
+ {
+ sc = STG_E_INVALIDPARAMETER;
+ }
+ else
+ {
+ ULONG cbWritten;
+ CNtHandleMarshalPacket NtHandlePacket;
+
+ NtHandlePacket.iid = riid;
+ NtHandlePacket.dwMarshFlags = mshlflags;
+ NtHandlePacket.dwPId = GetCurrentProcessId();
+ NtHandlePacket.dwTId = GetCurrentThreadId();
+
+ // The original process may close the handle before
+ // the unmarshaling packet is processed.
+ ssChk(DupNtHandle (_handle, &hDup));
+ NtHandlePacket.hSource = hDup;
+ NtHandlePacket.grfMode = _grfModeMarshal;
+ NtHandlePacket.dwStgfmt = _dwStgfmt;
+
+ ssChk(ValidateInterface(pstStm, IID_IStream));
+ ssChk(ValidateIid(riid));
+
+ ssChk(pstStm->Write((void *)&NtHandlePacket, sizeof(NtHandlePacket),
+ &cbWritten));
+ if (cbWritten != sizeof(NtHandlePacket))
+ ssErr(EH_Err, STG_E_WRITEFAULT);
+
+ if (SUCCEEDED(sc) && mshlflags != MSHLFLAGS_TABLEWEAK)
+ {
+ }
+ }
+
+ ssDebugOut((DEB_TRACE, "Out CNtHandleMarshal::MarshalInterface\n"));
+EH_Err:
+ if (!SUCCEEDED(sc) && hDup != INVALID_HANDLE_VALUE) // cleanup on failure
+ NtClose(hDup);
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleMarshal::UnmarshalInterface, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [pstStm] -
+// [riid] -
+// [ppvObj] -
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 18-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtHandleMarshal::UnmarshalInterface(IStream *pstStm,
+ REFIID riid,
+ void **ppvObj)
+{
+ ssDebugOut((DEB_TRACE, "Stb CNtHandleMarshal::UnmarshalInterface(%p)\n",
+ this));
+ return ssResult(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleMarshal::ReleaseMarshalData, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [pstStm] -
+//
+// Returns: Appropriate status code
+//
+// History: 18-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtHandleMarshal::ReleaseMarshalData(IStream *pstStm)
+{
+ ssDebugOut((DEB_TRACE, "Stb CNtHandleMarshal::ReleaseMarshalData(%p)\n",
+ this));
+ return ssResult(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleMarshal::DisconnectObject, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [dwRevserved] -
+//
+// Returns: Appropriate status code
+//
+// History: 18-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CNtHandleMarshal::DisconnectObject(DWORD dwReserved)
+{
+ ssDebugOut((DEB_TRACE,"Stb CNtHandleMarshal::DisconnectObject(%p)\n",this));
+ return ssResult(STG_E_INVALIDFUNCTION);
+}
+
diff --git a/private/ole32/stg/fsstg/overlap.cxx b/private/ole32/stg/fsstg/overlap.cxx
new file mode 100644
index 000000000..744ff25e4
--- /dev/null
+++ b/private/ole32/stg/fsstg/overlap.cxx
@@ -0,0 +1,110 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995.
+//
+// File: overlap.hxx
+//
+// Contents: COverlappedStream header
+//
+// Classes: COverlappedStream
+//
+// History: 19-Sep-95 HenryLee Created
+//
+// Notes: requires Win32 ReadFileEx, WriteFileEx, GetOverlappedResult
+// BUGBUG The following error codes need to be defined:
+// STG_S_IO_PENDING == ERROR_IO_PENDING
+// STG_S_IO_INCOMPLETE == ERROR_IO_INCOMPLETE
+// STG_E_HANDLE_EOF == ERROR_HANDLE_EOF
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <overlap.hxx>
+
+VOID WINAPI COverlappedCompletionRoutine (
+ DWORD fdwError,
+ DWORD cbTransferred,
+ OVERLAPPED *lpo)
+{
+ STGOVERLAPPED * lpOverlapped = (STGOVERLAPPED *) lpo;
+#if DBG == 1
+ ssAssert(lpOverlapped->reserved == StgOverlapped_SIG);
+#endif
+ IOverlappedCompletion * polc = lpOverlapped->lpCompletion;
+ if (polc != NULL)
+ polc->OnComplete (WIN32_SCODE(fdwError), cbTransferred, lpOverlapped);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Class: COverlappedStream
+//
+// Purpose:Implements IOverlappedStream for OFS streams and flat files
+// (as opposed to overlapped I/O for IStream for docfiles)
+//
+// Notes: This is class with a partial implementation
+// To use this class, inherit this into another class that
+// implements IUnknown and IStream (and expose QueryInterface)
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COverlappedStream::ReadOverlapped (
+ /* [in, size_is(cb)] */ void * pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG * pcbRead,
+ /* [in,out] */ STGOVERLAPPED *lpOverlapped)
+{
+ SCODE sc = S_OK;
+ OVERLAPPED *lpo = (OVERLAPPED *) lpOverlapped;
+ if (lpOverlapped == NULL)
+ ssErr (EH_Err, STG_E_INVALIDPOINTER);
+#if DBG == 1
+ lpOverlapped->reserved = StgOverlapped_SIG;
+#endif
+ if (ReadFileEx(_h, pv, cb, lpo, COverlappedCompletionRoutine) == FALSE)
+ sc = WIN32_SCODE(GetLastError());
+EH_Err:
+ return ssResult(sc);
+}
+
+STDMETHODIMP COverlappedStream::WriteOverlapped (
+ /* [in, size_is(cb)] */ void *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG * pcbWritten,
+ /* [in,out] */ STGOVERLAPPED *lpOverlapped)
+{
+ SCODE sc = S_OK;
+ LPOVERLAPPED lpo = (OVERLAPPED *) lpOverlapped;
+ if (lpOverlapped == NULL)
+ ssErr (EH_Err, STG_E_INVALIDPOINTER);
+#if DBG == 1
+ lpOverlapped->reserved = StgOverlapped_SIG;
+#endif
+ if (WriteFileEx(_h, pv, cb, lpo, COverlappedCompletionRoutine) == FALSE)
+ sc = WIN32_SCODE(GetLastError());
+EH_Err:
+ return ssResult(sc);
+}
+
+
+STDMETHODIMP COverlappedStream::GetOverlappedResult (
+ /* [in, out] */ STGOVERLAPPED *lpOverlapped,
+ /* [out] */ DWORD * lpcbTransfer,
+ /* [in] */ BOOL fWait)
+{
+ SCODE sc = S_OK;
+ LPOVERLAPPED lpo = (OVERLAPPED *) lpOverlapped;
+ if (lpOverlapped == NULL)
+ ssErr (EH_Err, STG_E_INVALIDPOINTER);
+#if DBG == 1
+ lpOverlapped->reserved = StgOverlapped_SIG;
+#endif
+ if (::GetOverlappedResult(_h, lpo, lpcbTransfer, fWait) == FALSE)
+ sc = WIN32_SCODE(GetLastError());
+EH_Err:
+ return ssResult(sc);
+}
+
diff --git a/private/ole32/stg/fsstg/stgsupp.cxx b/private/ole32/stg/fsstg/stgsupp.cxx
new file mode 100644
index 000000000..5eb9a5e23
--- /dev/null
+++ b/private/ole32/stg/fsstg/stgsupp.cxx
@@ -0,0 +1,252 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: stgsupp.cxx
+//
+// Contents: Storage create/open support routines
+//
+// History: 14-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <stgutil.hxx>
+#include <ntlkb.hxx>
+#include <dfentry.hxx>
+
+// Docfiles require read permission on the file so give it
+#define PERM_MASK (STGM_READ | STGM_WRITE | STGM_READWRITE)
+#define FORCE_READ(grfMode) \
+ if (((grfMode) & PERM_MASK) == STGM_WRITE) \
+ (grfMode) = ((grfMode) & ~PERM_MASK) | STGM_READWRITE; \
+ else 1
+
+//+---------------------------------------------------------------------------
+//
+// Function: CreateStorageType, public
+//
+// Synopsis: Creates a storage of the appropriate type
+//
+// Arguments: [hParent] - Parent handle or NULL
+// [pwcsName] - Name or path
+// [grfMode] - Mode
+// [h] - Handle of storage if already open or NULL
+// [dwStgFmt] - Type of storage
+// [pssSecurity] - Security
+// [ppstg] - New storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 24-Jun-93 DrewB Created
+// 24-Mar-95 HenryLee Save drive letter to correct Stat problem
+//
+//----------------------------------------------------------------------------
+
+SCODE CreateStorageType(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE *ph,
+ DWORD grfMode,
+ DWORD dwStgFmt,
+ LPSECURITY_ATTRIBUTES pssSecurity,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ SafeCDirStorage pds;
+#if 0
+ SafeCFileStorage pfs;
+#endif
+ HANDLE h = (ph == NULL) ? NULL : *ph;
+
+ ssDebugOut((DEB_ITRACE, "In CreateStorageType("
+ "%p, %ws, %p, %lX, %lu, %p, %p)\n",
+ hParent, pwcsName, h, grfMode, dwStgFmt, pssSecurity, ppstg));
+
+ sc = S_OK;
+ switch(dwStgFmt)
+ {
+ case STGFMT_DOCUMENT:
+ // docfile will reopen the storage will different permissions
+ if (h)
+ {
+ NTSTATUS nts = NtClose(h);
+ *ph = NULL; // inform caller not to close handle on failure
+ }
+#if WIN32 == 300
+ sc = DfCreateDocfile (pwcsName, NULL, grfMode, pssSecurity, ppstg);
+#else
+ sc = DfCreateDocfile (pwcsName, NULL, grfMode, 0, ppstg);
+#endif
+ break;
+
+ case STGFMT_CATALOG:
+ // Summary catalogs are only supported on OFS
+ sc = STG_E_INVALIDFUNCTION;
+ break;
+
+ case STGFMT_DIRECTORY:
+ pds.Attach(new CDirStorage());
+ ssMem((CDirStorage *)pds);
+ if (h != NULL)
+ {
+ ssChk(pds->InitFromHandle(h, pwcsName, grfMode));
+ }
+ else
+ {
+ ssChk(pds->InitFromPath(hParent, pwcsName, grfMode,
+ CO_CREATE, pssSecurity));
+ }
+ TRANSFER_INTERFACE(pds, IStorage, ppstg);
+ break;
+
+ case STGFMT_FILE:
+#if 0
+ pfs.Attach(new CFileStorage());
+ ssMem((CFileStorage *)pfs);
+ if (h != NULL)
+ {
+ ssChk(pfs->InitFromHandle(h, grfMode));
+ }
+ else
+ {
+ ssChk(pfs->InitFromPath(hParent, pwcsName, grfMode, CO_CREATE,
+ pssSecurity));
+ }
+ TRANSFER_INTERFACE(pfs, IStorage, ppstg);
+#endif
+ sc = STG_E_INVALIDFUNCTION;
+ break;
+
+ default:
+ ssAssert(!aMsg("CreateStorageType default hit"));
+ sc = STG_E_INVALIDPARAMETER;
+ break;
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out CreateStorageType => %p, 0x%lX\n",
+ *ppstg, sc));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OpenAnyStorage, public
+//
+// Synopsis: Opens a storage of the appropriate type
+//
+// Arguments: [hParent] - Parent handle or NULL
+// [pwcsName] - Name or path
+// [h] - Handle of storage if already open or NULL
+// [dwStgFmt] - Storage format
+// [pstgPriority] - Priority mode prior open
+// [grfMode] - Mode
+// [snbExclude] - Exclusions
+// [ppstg] - Storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 14-Jul-93 DrewB Created
+// 24-Mar-95 HenryLee Save drive letter to correct Stat problem
+//
+//----------------------------------------------------------------------------
+
+SCODE OpenAnyStorage(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE *ph,
+ DWORD dwStgFmt,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ SafeCDirStorage pds;
+#if 0
+ SafeCFileStorage pfs;
+#endif
+ SafeNtHandle hSafe;
+ HANDLE h = (ph == NULL) ? NULL : *ph;
+
+ ssDebugOut((DEB_ITRACE, "In OpenAnyStorage("
+ "%p, %ws, %p, %lu, %p, %lX, %p, %p)\n", hParent, pwcsName,
+ h, dwStgFmt, pstgPriority, grfMode, snbExclude, ppstg));
+
+ sc = S_OK;
+ if (h == NULL)
+ {
+ ssChk(DetermineStgType(hParent, pwcsName, grfMode,
+ &dwStgFmt, &hSafe));
+ h = hSafe;
+ }
+ switch(dwStgFmt)
+ {
+ case STGFMT_DOCUMENT:
+ // docfile will reopen the storage will different permissions
+ if (h)
+ {
+ NTSTATUS nts = NtClose(h);
+ *ph = NULL; // inform caller not to close handle on failure
+ }
+ sc = DfOpenDocfile (pwcsName, NULL, pstgPriority, grfMode,
+ snbExclude, NULL, ppstg);
+
+ break;
+
+ case STGFMT_CATALOG:
+ // Summary catalogs are only supported on OFS
+ sc = STG_E_INVALIDFUNCTION;
+ break;
+
+ case STGFMT_DIRECTORY:
+ if (pstgPriority != NULL || snbExclude != NULL)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+
+ pds.Attach(new CDirStorage());
+ ssMem((CDirStorage *)pds);
+ ssChk(pds->InitFromHandle(h, pwcsName, grfMode));
+ TRANSFER_INTERFACE(pds, IStorage, ppstg);
+ break;
+
+ case STGFMT_FILE:
+#if 0
+ // BUGBUG [mikese] "File as an IStorage" behaviour has been disabled,
+ // because it causes compatibility problems. For example, Excel 5.0
+ // expects StgOpenStorage on a non-Docfile to fail, not for it to
+ // return successfully.
+ // This behaviour may be reenabled, through a different public API
+ // at a later time.
+
+ if (pstgPriority != NULL || snbExclude != NULL)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+
+ pfs.Attach(new CFileStorage());
+ ssMem((CFileStorage *)pfs);
+ ssChk(pfs->InitFromHandle(h, grfMode));
+ TRANSFER_INTERFACE(pfs, IStorage, ppstg);
+#else
+ // This is the status code returned by Daytona OLE if you attempt to
+ // open a non-Docfile with StgOpenStorage.
+ sc = STG_E_FILEALREADYEXISTS;
+#endif
+ break;
+ default:
+ sc = STG_E_INVALIDPARAMETER;
+ }
+
+ // If hSafe is set, it will close its handle
+ // In the error case, this is proper cleanup
+ // In the success case, the storage has its own reference so this
+ // drops the refcount to one
+
+ ssDebugOut((DEB_ITRACE, "Out OpenAnyStorage => %p, %lX\n", *ppstg, sc));
+ EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/fsstg/stgutil.cxx b/private/ole32/stg/fsstg/stgutil.cxx
new file mode 100644
index 000000000..9502b18e3
--- /dev/null
+++ b/private/ole32/stg/fsstg/stgutil.cxx
@@ -0,0 +1,762 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: stgutil.cxx
+//
+// Contents: Storage utilities
+//
+// History: 18-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <stgutil.hxx>
+#include <ntenm.hxx>
+
+#include <iofs.h>
+
+//+---------------------------------------------------------------------------
+//
+// Function: DetermineHandleStgType, public
+//
+// Synopsis: Determines the storage type of the given handle
+//
+// Arguments: [h] - Handle
+// [fd] - File/dir type of [h]
+// [pdwStgFmt] - Storage type return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pdwStgFmt]
+//
+// History: 21-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE DetermineHandleStgType(HANDLE h,
+ FILEDIR fd,
+ DWORD *pdwStgFmt)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In DetermineHandleStgType(%p, %d, %p)\n",
+ h, fd, pdwStgFmt));
+
+ sc = S_OK;
+
+ switch (fd)
+ {
+ case FD_FILE:
+ sc = DfIsDocfile(h);
+ if (sc == S_OK)
+ *pdwStgFmt = STGFMT_DOCUMENT;
+ else
+ {
+ sc = S_OK;
+ *pdwStgFmt = STGFMT_FILE;
+ }
+ break;
+ case FD_CATALOG:
+ *pdwStgFmt = STGFMT_CATALOG;
+ break;
+ case FD_STORAGE:
+ *pdwStgFmt = STGFMT_DOCUMENT;
+ break;
+ case FD_DIR:
+ *pdwStgFmt = STGFMT_DIRECTORY;
+ break;
+ case FD_JUNCTION:
+ *pdwStgFmt = STGFMT_JUNCTION;
+ break;
+ default:
+ *pdwStgFmt = STGFMT_DIRECTORY;
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out DetermineHandleStgType => %lX, %d\n",
+ sc, *pdwStgFmt));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DetermineStgType, public
+//
+// Synopsis: Returns the appropriate STGFMT for the given FS object
+// Will also return an open handle so that files don't
+// need to be opened twice
+//
+// Arguments: [hParent] - Parent handle or NULL
+// [pwcsName] - Object name or path
+// [grfMode] - Access mode
+// [pdwStgFmt] - Type return
+// [ph] - Handle return or NULL if unneeded
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pdwStgFmt]
+// [ph]
+//
+// History: 12-Jul-93 DrewB Created
+//
+// Notes: BUGBUG - No way to identify summary catalogs
+// Waiting on filesystem support
+//
+//----------------------------------------------------------------------------
+
+SCODE DetermineStgType(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD *pdwStgFmt,
+ HANDLE *ph)
+{
+ SCODE sc;
+ SafeNtHandle hChild;
+ FILEDIR fd;
+
+ ssDebugOut((DEB_ITRACE, "In DetermineStgType(%p, %ws, %lX, %p, %p)\n",
+ hParent, pwcsName, grfMode, pdwStgFmt, ph));
+
+ sc = GetFileOrDirHandle(hParent, pwcsName, grfMode, &hChild,NULL,NULL,&fd);
+ if (SUCCEEDED(sc))
+ {
+ sc = DetermineHandleStgType(hChild, fd, pdwStgFmt);
+ if (SUCCEEDED(sc) && ph != NULL)
+ hChild.Transfer(ph);
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out DetermineStgType => 0x%lX, %lu, %p\n",
+ sc, *pdwStgFmt, ph ? *ph : NULL));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CheckFsAndOpenAnyStorage, public
+//
+// Synopsis: Checks the filesystem type and calls the appropriate storage
+// open routine
+//
+// Arguments: [hParent] - Parent handle
+// [pwcsName] - Name
+// [pstgPriority] - Priority storage
+// [grfMode] - Mode
+// [snbExclude] - Exclusions
+// [fRoot] - TRUE => storage is root storage
+// [ppstg] - Storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 21-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CheckFsAndOpenAnyStorage(HANDLE hParent,
+ WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ BOOL fRoot,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ DWORD dwStgFmt;
+ HANDLE h = NULL;
+ NTSTATUS nts;
+
+ ssDebugOut((DEB_ITRACE, "In CheckFsAndOpenAnyStorage("
+ "%p, %ws, %p, %lX, %p, %p)\n", hParent, pwcsName,
+ pstgPriority, grfMode, snbExclude, ppstg));
+
+#ifdef TRANSACT_OLE
+ const DWORD grfMode2 = grfMode & ~STGM_TRANSACTED;
+ sc = DetermineStgType(hParent, pwcsName, grfMode2, &dwStgFmt, &h);
+#else
+ sc = DetermineStgType(hParent, pwcsName, grfMode, &dwStgFmt, &h);
+#endif
+ if (SUCCEEDED(sc))
+ sc = HandleRefersToOfsVolume(h);
+ if (sc == S_OK)
+ {
+#ifdef TRANSACT_OLE
+ if (grfMode & STGM_TRANSACTED)
+ grfMode &= ~STGM_TRANSACTED;
+#endif
+ sc = OfsOpenAnyStorage(hParent, pwcsName, &h, dwStgFmt, pstgPriority,
+ grfMode, snbExclude, fRoot, ppstg);
+ }
+ else if (sc == S_FALSE)
+ {
+ sc = OpenAnyStorage(hParent, pwcsName, &h, dwStgFmt, pstgPriority,
+ grfMode, snbExclude, ppstg);
+ }
+
+ // In the success case, h is passed to and owned by the storage object
+ // and the last Release() is responsible for closing h
+ // In the failure case, we close the handle now
+ //
+ if (!SUCCEEDED(sc) && h != NULL)
+ {
+ if (!NT_SUCCESS(nts = NtClose(h)))
+ ssDebugOut((DEB_ITRACE,
+ "CheckFsAndOpenAnyStorage NtClose(%lx)\n",nts));
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out CheckFsAndOpenAnyStorage => 0x%lX, %p\n",
+ sc, *ppstg));
+ return sc;
+}
+
+SAFE_HEAP_PTR(SafeFrni, FILE_RENAME_INFORMATION);
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetupRename, public
+//
+// Synopsis: Allocates and initializes a FILE_RENAME_INFORMATION struct
+//
+// Arguments: [h] - Value for RootDirectory field.
+// [pwcsNewName] -- String for FileName field.
+// [pcbFni] -- pointer to buffer for size of structure in bytes.
+// [ppfni] -- pointer to buffer for pointer to struct.
+//
+// Returns: STG_E_INSUFFICIENT_MEMORY or S_OK.
+//
+// History: 15-May-94 BillMo Created
+//
+//----------------------------------------------------------------------------
+
+SCODE
+SetupRename(HANDLE h,
+ const WCHAR *pwcsNewName,
+ ULONG *pcbFni,
+ FILE_RENAME_INFORMATION ** ppfni)
+{
+ SCODE sc = S_OK;
+ ULONG cbNewName = lstrlenW(pwcsNewName)*sizeof(WCHAR);
+ *pcbFni = sizeof(FILE_RENAME_INFORMATION)+cbNewName;
+ *ppfni = (FILE_RENAME_INFORMATION *)new BYTE[*pcbFni];
+ olMem((FILE_RENAME_INFORMATION *)*ppfni);
+ (*ppfni)->ReplaceIfExists = FALSE;
+ (*ppfni)->RootDirectory = h;
+ (*ppfni)->FileNameLength = cbNewName;
+ memcpy((*ppfni)->FileName, pwcsNewName, cbNewName);
+EH_Err:
+ return(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GenericMoveElement, public
+//
+// Synopsis: Performs MoveElement between any two IStorages
+//
+// Arguments: [pstgFrom] - Source
+// [pwcsName] - Source element
+// [pstgTo] - Destination
+// [pwcsNewName] - Destination element
+// [grfFlags] - Flags
+//
+// Returns: Appropriate status code
+//
+// History: 15-Jul-93 DrewB Adapted from docfile code
+//
+//----------------------------------------------------------------------------
+
+SCODE GenericMoveElement(IStorage *pstgFrom,
+ WCHAR const *pwcsName,
+ IStorage *pstgTo,
+ WCHAR const *pwcsNewName,
+ DWORD grfFlags)
+{
+ SafeIStorage pstgFromElement;
+ STATSTG stat, statTmp;
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In GenericMoveElement(%p, %ws, %p, %ws, %lX)\n",
+ pstgFrom, pwcsName, pstgTo, pwcsNewName, grfFlags));
+
+ // BUGBUG - Security?
+
+ if (grfFlags == STGMOVE_MOVE)
+ {
+ //
+ // Try to use native file system move if supported.
+ //
+
+ SafeINativeFileSystem pnfsFrom;
+ SafeINativeFileSystem pnfsTo;
+
+ if (SUCCEEDED(pstgFrom->QueryInterface(IID_INativeFileSystem,
+ (VOID**) &pnfsFrom)) &&
+ SUCCEEDED(pstgTo->QueryInterface(IID_INativeFileSystem,
+ (VOID**) &pnfsTo)))
+ {
+ //
+ // Both storages support INativeFileSystem so we can
+ // can try same volume move.
+ //
+ // Design Note:
+ // We allow embeddings to be moved into/out of documents:
+ // there is no enforcement of the semantics provided by
+ // docfiles where an embedding must be moved into another
+ // docfile.
+ //
+
+ NTSTATUS nts;
+ HANDLE hFrom;
+ HANDLE hTo;
+ SafeNtHandle hToMove;
+ ULONG cbFni;
+ IO_STATUS_BLOCK iosb;
+ SafeFrni pfni;
+ UNICODE_STRING us;
+ OBJECT_ATTRIBUTES oa;
+
+ ssChk(pnfsFrom->GetHandle(&hFrom));
+ ssChk(pnfsTo->GetHandle(&hTo));
+
+ us.Length = lstrlenW(pwcsName)*sizeof(WCHAR);
+ us.MaximumLength = us.Length+sizeof(WCHAR);
+ us.Buffer = (PWSTR)pwcsName;
+
+ InitializeObjectAttributes(&oa, &us, OBJ_CASE_INSENSITIVE, hFrom, NULL);
+
+ //
+ // We open hFrom::pwcsName giving hToMove (the object to move)
+ //
+
+ nts = NtOpenFile(&hToMove,
+ (ACCESS_MASK)DELETE | SYNCHRONIZE,
+ &oa,
+ &iosb,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT);
+
+ if (!NT_SUCCESS(nts))
+ {
+ sc = NtStatusToScode(nts);
+ goto EH_Err;
+ }
+
+ //
+ // We setup hTo::pwcsNewName as destination.
+ //
+ ssChk(SetupRename(hTo, pwcsNewName, &cbFni, &pfni));
+
+ //
+ // We move the object hToMove.
+ //
+ nts = NtSetInformationFile(hToMove,
+ &iosb,
+ pfni,
+ cbFni,
+ FileRenameInformation);
+ if (NT_SUCCESS(nts))
+ {
+ sc = S_OK;
+ goto EH_Ret;
+ }
+
+ if (nts != STATUS_NOT_SAME_DEVICE && nts != STATUS_ACCESS_DENIED)
+ {
+ //
+ // STATUS_OBJECT_NAME_COLLISION -> STG_E_FILEALREADYEXISTS
+ //
+ // not successful, and not because of different device.
+ //
+ // OFS has problems moving streams and returns
+ // STATUS_ACCESS_DENIED -- try again
+ //
+ // Nt file systems return OBJECT_NAME_COLLISION whenever renaming
+ // an object on top of an existing one. DocFile returns ACCESS_DENIED.
+ //
+ if (nts == STATUS_OBJECT_NAME_COLLISION)
+ sc = STG_E_ACCESSDENIED;
+ else
+ sc = NtStatusToScode(nts);
+ goto EH_Err;
+ }
+ }
+ }
+
+ // Determine source type
+ sc = GetScode(pstgFrom->OpenStorage(pwcsName, NULL,
+ STGM_DIRECT | STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE,
+ NULL, NULL, &pstgFromElement));
+ if (SUCCEEDED(sc))
+ {
+
+ SafeIStorage pstgToElement;
+
+ // It\'s a storage
+ ssHChk(pstgFromElement->Stat(&stat, STATFLAG_NONAME));
+
+ sc = GetScode(pstgTo->CreateStorage(pwcsNewName,
+ STGM_DIRECT | STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_FAILIFTHERE,
+ stat.STATSTG_dwStgFmt,
+ 0,
+ &pstgToElement));
+ if (sc == STG_E_FILEALREADYEXISTS &&
+ grfFlags == STGMOVE_COPY)
+ {
+ sc = GetScode(pstgTo->OpenStorage(pwcsNewName, NULL,
+ STGM_DIRECT | STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE, NULL,
+ 0, &pstgToElement));
+ if (SUCCEEDED(sc))
+ {
+ sc = GetScode(pstgTo->Stat(&statTmp, STATFLAG_NONAME));
+ if ( FAILED(sc) ||
+ statTmp.STATSTG_dwStgFmt != stat.STATSTG_dwStgFmt )
+ {
+ sc = STG_E_INVALIDFUNCTION;
+ }
+ }
+ }
+ ssChk(sc);
+
+ if (grfFlags == STGMOVE_MOVE)
+ {
+ sc = GetScode(pstgFromElement->CopyTo(1,
+ &IID_IEnableObjectIdCopy,
+ NULL,
+ pstgToElement));
+ }
+ else
+ {
+ sc = GetScode(pstgFromElement->CopyTo(0, NULL, NULL,
+ pstgToElement));
+ }
+
+ // Close the source since it may be deleted later
+ // and we have exclusive access to it right now
+ IStorage *pstgFromFree;
+ pstgFromElement.Transfer(&pstgFromFree);
+ pstgFromFree->Release();
+ }
+ else // if (sc == STG_E_FILENOTFOUND)
+ {
+ SafeIStream pstmFromElement, pstmToElement;
+
+ // Try opening it as a stream
+
+ ssChk(pstgFrom->OpenStream(pwcsName, NULL,
+ STGM_DIRECT | STGM_READ |
+ STGM_SHARE_EXCLUSIVE,
+ NULL, &pstmFromElement));
+
+ // It\'s a stream
+ ssHChk(pstmFromElement->Stat(&stat, STATFLAG_NONAME));
+
+ ssHChk(pstgTo->CreateStream(pwcsNewName,
+ STGM_DIRECT | STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE |
+ (grfFlags == STGMOVE_MOVE ?
+ STGM_FAILIFTHERE :
+ STGM_CREATE),
+ 0, 0, &pstmToElement));
+
+ ULARGE_INTEGER cb = {0xffffffff, 0xffffffff};
+ sc = GetScode(pstmFromElement->CopyTo(pstmToElement,
+ cb, NULL, NULL));
+ }
+ //else
+ // ssChk(sc);
+
+ if (SUCCEEDED(sc))
+ {
+ // Make destination create time match source create time
+ // Note that we don't really care if this call succeeded.
+
+ pstgTo->SetElementTimes(pwcsNewName, &stat.ctime,
+ NULL, NULL);
+
+ if ((grfFlags & STGMOVE_COPY) == STGMOVE_MOVE)
+ olVerify(SUCCEEDED(pstgFrom->DestroyElement(pwcsName)));
+ }
+ else
+ {
+ // The copy/move failed, so get rid of the partial result.
+
+ pstgTo->DestroyElement(pwcsNewName);
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out GenericMoveElement\n"));
+EH_Ret:
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: FindExt, public
+//
+// Synopsis: Finds the extension for a path
+//
+// Arguments: [pwcsPath] - Path
+//
+// Returns: Pointer to extension or NULL
+//
+// History: 27-Jul-93 DrewB Created from file moniker code
+//
+//----------------------------------------------------------------------------
+
+WCHAR *FindExt(WCHAR const *pwcsPath)
+{
+ WCHAR const *pwcs = pwcsPath;
+
+ ssAssert(pwcs != NULL);
+
+ // Move to end of string
+ pwcs += lstrlenW(pwcs);
+ ssAssert(*pwcs == 0);
+
+ pwcs--;
+ while (*pwcs != L'.' && *pwcs != L'\\' && *pwcs != L'/' &&
+ *pwcs != L'!' && pwcs > pwcsPath)
+ pwcs--;
+
+ return *pwcs == L'.' ? (WCHAR *)pwcs : NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DestroyTree, public
+//
+// Synopsis: Destroys an element and any children
+//
+// Arguments: [hParent] - Parent handle or NULL
+// [pwcsName] - Child name or NULL
+// [h] - Handle or NULL if [hParent] and [pwcsName]
+// should be used
+// [fd] - File/dir status of [h] if given
+//
+// Returns: Appropriate status code
+//
+// History: 20-Oct-93 DrewB Created
+//
+// Notes: Attempts as complete a deletion as possible, returning
+// the last error encountered
+//
+//----------------------------------------------------------------------------
+
+// Avoid Win32 macro problems
+#undef DeleteFile
+
+SCODE DestroyTree(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE h,
+ FILEDIR fd)
+{
+ SCODE sc;
+ SafeNtHandle hSafe;
+ IO_STATUS_BLOCK iosb;
+ NTSTATUS nts;
+ FILE_DISPOSITION_INFORMATION fdi;
+ BOOL bOfsHandle;
+ WCHAR *pwcsNewName = NULL;
+
+ ssDebugOut((DEB_ITRACE, "In DestroyTree(%p, %ws, %p, %d)\n",
+ hParent, pwcsName, h, fd));
+
+ if (h == NULL)
+ {
+#ifdef TRANSACT_OLE
+ // STGM_CREATE is used to set the DELETE access on the handle
+ if (fd == FD_STREAM) // stream names need a ':' in front
+ {
+ ssMem(pwcsNewName = MakeStreamName(pwcsName));
+ ssChk(GetNtHandle (hParent, pwcsNewName, STGM_CREATE |
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0,CO_OPEN,FD_STREAM,NULL, &hSafe));
+ }
+ else
+#endif
+ ssChk(GetFileOrDirHandle(hParent, pwcsName,
+ STGM_READWRITE | STGM_CREATE,
+ &hSafe, NULL, NULL, &fd));
+ h = hSafe;
+ }
+
+ bOfsHandle = HandleRefersToOfsVolume(h) == S_OK ? TRUE : FALSE;
+ sc = S_OK;
+
+ // Destroy all children in directories
+ if (fd == FD_DIR || fd == FD_STORAGE)
+ {
+ int cNameSpaces = (fd == FD_DIR ? 2 : 1);
+
+ while (cNameSpaces--)
+ {
+ // skip the OLE namespace for non-OFS file handles
+ if (cNameSpaces == 0 && !bOfsHandle)
+ break;
+ CNtEnum nte(cNameSpaces == 0);
+
+ if (SUCCEEDED(sc = nte.InitFromHandle(h, TRUE)))
+ {
+ STATSTG stat;
+ WCHAR awcName[_MAX_PATH];
+ FILEDIR fdChild;
+
+ for (;;)
+ {
+ sc = nte.Next(&stat, awcName, NTE_BUFFERNAME, &fdChild);
+ if (FAILED(sc) || sc == S_FALSE)
+ {
+ if (sc == S_FALSE)
+ sc = S_OK;
+ break;
+ }
+
+ ssAssert((lstrcmpW(awcName, L".") != 0 && lstrcmpW(awcName, L"..") != 0));
+
+ sc = DestroyTree(h, awcName, NULL, fdChild);
+ }
+ }
+ }
+ }
+
+ fdi.DeleteFile = TRUE;
+ nts = NtSetInformationFile(h, &iosb, &fdi,
+ sizeof(FILE_DISPOSITION_INFORMATION),
+ FileDispositionInformation);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+
+ ssDebugOut((DEB_ITRACE, "Out DestroyTree => %lX\n", sc));
+ EH_Err:
+ if (pwcsNewName) delete pwcsNewName;
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: RenameChild, public
+//
+// Synopsis: Renames a file or directory
+//
+// Arguments: [hParent] - Parent handle
+// [pwcsName] - Name
+// [pwcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// History: 21-Oct-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+
+SCODE RenameChild(HANDLE hParent,
+ WCHAR const *pwcsName,
+ WCHAR const *pwcsNewName)
+{
+ SCODE sc;
+ SafeNtHandle h;
+ IO_STATUS_BLOCK iosb;
+ NTSTATUS nts;
+ ULONG cbFni;
+ SafeFrni pfni;
+
+ ssDebugOut((DEB_ITRACE, "In RenameChild(%p, %ws, %ws)\n",
+ hParent, pwcsName, pwcsNewName));
+
+ ssChk(SetupRename(NULL, pwcsNewName, &cbFni, &pfni));
+
+ // Renames require DELETE access on the handle
+ ssChk(GetFileOrDirHandle(hParent, pwcsName, STGM_WRITE | STGM_CREATE,
+ &h, NULL, NULL, NULL));
+ nts = NtSetInformationFile(h, &iosb, pfni, cbFni, FileRenameInformation);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_ITRACE, "Out RenameChild\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: SetDriveLetter
+//
+// Synopsis: inserts drive letter into a pathname
+//
+// Arguments: [pwcsName] - path name with missing drive letter
+// [wcDrive] - drive letter or L'\\' for a share
+//
+// Returns: Appropriate status code
+//
+// History: 24-Mar-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+SCODE SetDriveLetter (WCHAR *pwcsName, WCHAR const wcDrive)
+{
+ SCODE sc = S_FALSE;
+ if (pwcsName != NULL)
+ {
+ if (IsCharAlphaW(wcDrive))
+ {
+ for (int i=lstrlenW(pwcsName); i >= 0; i--)
+ pwcsName[i+2] = pwcsName[i];
+ pwcsName[1] = L':';
+ pwcsName[0] = wcDrive;
+ sc = S_OK;
+ }
+ else if (wcDrive == L'\\')
+ {
+ for (int i=lstrlenW(pwcsName); i >= 0; i--)
+ pwcsName[i+1] = pwcsName[i];
+ pwcsName[0] = L'\\';
+ sc = S_OK;
+ }
+ }
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetDriveLetter
+//
+// Synopsis: extracts a drive letter from pathname
+//
+// Arguments: [pwcsName] - path name with drive letter
+//
+// Returns: [wcDrive] - drive letter or L'\\' for a share
+//
+// History: 24-Mar-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+WCHAR GetDriveLetter (WCHAR const *pwcsName)
+{
+ WCHAR wcDrive = L'\0';
+
+ if (pwcsName != NULL)
+ {
+ if (pwcsName[0] != NULL && (pwcsName[1] == L':' ||
+ pwcsName[0] == L'\\' && pwcsName[1] == L'\\' ))
+ wcDrive = pwcsName[0]; // extract drive from pathname
+ else
+ {
+ WCHAR wcsPath[MAX_PATH]; // no drive letter in pathname
+ NTSTATUS nts = // get current drive instead
+ RtlGetCurrentDirectory_U (MAX_PATH*sizeof(WCHAR),wcsPath);
+ if (NT_SUCCESS(nts))
+ wcDrive = wcsPath[0];
+ }
+ }
+ return (wcDrive);
+};
diff --git a/private/ole32/stg/fsstg/utest/fstest.cxx b/private/ole32/stg/fsstg/utest/fstest.cxx
new file mode 100644
index 000000000..cb637b1d1
--- /dev/null
+++ b/private/ole32/stg/fsstg/utest/fstest.cxx
@@ -0,0 +1,465 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: fstest.cxx
+//
+// History: 30-Jun-93 DrewB Created
+// 1-Jun-94 BillMo Changed share mode for MoveElementTo
+// Added test for:
+// Cross volume copy with id
+// Cross volume move with id
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+void EndTest(int rc)
+{
+ if (rc == 0)
+ printf("Test SUCCEEDED\n");
+ else
+ printf("Test FAILED\n");
+ CoUninitialize();
+ exit(rc);
+}
+
+void PrintStat(STATSTG *pstat, BOOL fEnum)
+{
+ printf("%s: '%ws'\n", pstat->type == STGTY_STORAGE ? "Storage" : "Stream",
+ pstat->pwcsName);
+ printf("Type: %lu, %lu\n", pstat->type, pstat->dwStgFmt);
+ if (!fEnum)
+ printf("Mode: %lX\n", pstat->grfMode);
+ if (pstat->type == STGTY_STREAM)
+ {
+ printf("Size: %lu:%lu\n", pstat->cbSize.HighPart,
+ pstat->cbSize.LowPart);
+ if (!fEnum)
+ printf("Locks: %lX\n", pstat->grfLocksSupported);
+ }
+ else
+ {
+ if (pstat->ctime.dwHighDateTime != 0 ||
+ pstat->ctime.dwLowDateTime != 0)
+ printf("Ctime: %s\n", FileTimeText(&pstat->ctime));
+ if (pstat->mtime.dwHighDateTime != 0 ||
+ pstat->mtime.dwLowDateTime != 0)
+ printf("Mtime: %s\n", FileTimeText(&pstat->mtime));
+ if (pstat->atime.dwHighDateTime != 0 ||
+ pstat->atime.dwLowDateTime != 0)
+ printf("Atime: %s\n", FileTimeText(&pstat->atime));
+ }
+ if (!fEnum)
+ printf("Clsid: %s\n", GuidText(&pstat->clsid));
+}
+
+void t_enum(IStorage *pstg)
+{
+ IEnumSTATSTG *penm, *penm2;
+ STATSTG stat;
+ HRESULT hr;
+
+ hr = pstg->EnumElements(0, 0, 0, &penm);
+ Result(hr, "Enum");
+
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result(hr, "Next");
+ if (GetScode(hr) == S_FALSE)
+ break;
+
+ PrintStat(&stat, TRUE);
+ CoMemFree(stat.pwcsName);
+ }
+
+ hr = penm->Skip(1);
+ Result(hr, "Skip");
+ hr = penm->Reset();
+ Result(hr, "Reset");
+ hr = penm->Clone(&penm2);
+ Result(hr, "Clone");
+
+ penm2->Release();
+ penm->Release();
+}
+
+void t_dirstg(IStorage *pstg)
+{
+ HRESULT hr;
+ IStream *pstm;
+ STATSTG stat;
+ IStorage *pstg2, *pstg3;
+ WCHAR wfn[MAX_PATH];
+ SYSTEMTIME stm;
+ FILETIME ftm;
+
+ hr = pstg->Stat(&stat, 0);
+ Result(hr, "Stat");
+ PrintStat(&stat, FALSE);
+ CoMemFree(stat.pwcsName);
+
+ hr = pstg->CreateStream(L"Stream", STGM_READWRITE, 0, 0, &pstm);
+ if (hr != STG_E_INVALIDFUNCTION)
+ Fail("CreateStream returned %lX\n", hr);
+ hr = pstg->OpenStream(L"Stream", 0, STGM_READWRITE, 0, &pstm);
+ if (hr != STG_E_FILENOTFOUND)
+ Fail("OpenStream returned %lX\n", hr);
+
+ hr = pstg->CreateStorage(L"file!", STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_FILE, NULL, &pstg2);
+ Result(hr, "Create file 'file!'");
+ pstg2->Release();
+ hr = pstg->CreateStorage(L"docfile", STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_DOCUMENT, NULL, &pstg2);
+ Result(hr, "Create document");
+ pstg2->Release();
+ hr = pstg->CreateStorage(L"dir", STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_DIRECTORY, NULL, &pstg2);
+ Result(hr, "Create directory");
+ pstg2->Release();
+
+ hr = pstg->Commit(0);
+ Result(hr, "Commit");
+ hr = pstg->Revert();
+ Result(hr, "Revert");
+
+ t_enum(pstg);
+
+ hr = pstg->OpenStorage(L"file!", NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL,
+ NULL, &pstg2);
+ Result(hr, "Open file 'file!'");
+ pstg2->Release();
+ hr = pstg->OpenStorage(L"docfile", NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL,
+ NULL, &pstg2);
+ Result(hr, "Open docfile");
+ pstg2->Release();
+ hr = pstg->OpenStorage(L"dir", NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL,
+ NULL, &pstg2);
+ Result(hr, "Open directory");
+ hr = pstg2->CreateStorage(L"child", STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_DIRECTORY, NULL, &pstg3);
+ Result(hr, "Create child directory");
+ pstg3->Release();
+ pstg2->Release();
+
+ TestFile(wfn, "stg2");
+ hr = StgCreateStorage(wfn, STGM_READWRITE,
+ /* BUGBUG: review. Took off share exclusive */
+ /* for MoveElementTo | STGM_SHARE_EXCLUSIVE */
+ STGFMT_DIRECTORY, NULL, &pstg2);
+ Result(hr, "Create sibling dir");
+ hr = pstg->CopyTo(0, NULL, NULL, pstg2);
+ Result(hr, "CopyTo");
+ t_enum(pstg2);
+
+ hr = pstg2->DestroyElement(L"dir");
+ Result(hr, "Destroy dest dir -- contains child");
+ hr = pstg->MoveElementTo(L"dir", pstg2, L"dest", STGMOVE_MOVE);
+ Result(hr, "MoveElementTo");
+ t_enum(pstg2);
+ pstg2->Release();
+
+ char *pszOtherDrive = getenv("FSTEST_OTHER");
+ if (pszOtherDrive)
+ {
+ WCHAR wszBuf[16];
+ mbstowcs(wszBuf, pszOtherDrive, 1);
+ wcscpy(wszBuf+1, ":\\");
+ hr = StgOpenStorage(wszBuf, STGM_READWRITE, STGMFT_DIRECTORY, NULL, NULL, &pstg3);
+ hr = pstg2->MoveElementTo(L"dest", pstg3, L"new");
+ }
+ else
+ {
+ printf("Skipping cross volume move test because FSTEST_OTHER not defined\n");
+ }
+ hr = pstg->OpenStorage(L"dir", NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL,
+ NULL, &pstg2);
+ if (hr != STG_E_FILENOTFOUND)
+ Fail("Opened non-existent storage, %lX\n", hr);
+
+ hr = pstg->RenameElement(L"docfile", L"stg3");
+ Result(hr, "RenameElement");
+ hr = pstg->DestroyElement(L"stg3");
+ Result(hr, "DestroyElement");
+ t_enum(pstg);
+
+ Sleep(3);
+ GetLocalTime(&stm);
+ SystemTimeToFileTime(&stm, &ftm);
+ printf("Set time to %s\n", FileTimeText(&ftm));
+ hr = pstg->SetElementTimes(L"file!", NULL, NULL, &ftm);
+ Result(hr, "SetElementTimes");
+ t_enum(pstg);
+
+ hr = pstg->SetClass(IID_IStorage);
+ if (hr != STG_E_INVALIDFUNCTION)
+ Fail("SetClass returned %lX\n", hr);
+ hr = pstg->SetStateBits(0xffffffff, 0xf0f0f0f0);
+ if (hr != STG_E_INVALIDFUNCTION)
+ Fail("SetStateBits returned %lX\n", hr);
+}
+
+void t_filstg(IStorage *pstg)
+{
+ HRESULT hr;
+ STATSTG stat;
+ IStream *pstm;
+ IStorage *pstg2;
+ WCHAR wfn[MAX_PATH];
+
+ hr = pstg->Stat(&stat, 0);
+ Result(hr, "Stat");
+ PrintStat(&stat, FALSE);
+ CoMemFree(stat.pwcsName);
+
+ hr = pstg->CreateStream(L"Stream", STGM_READWRITE, 0, 0, &pstm);
+ if (hr != STG_E_INVALIDFUNCTION)
+ Fail("CreateStream succeeded for non-CONTENTS %lX\n", hr);
+ hr = pstg->OpenStream(L"Stream", 0, STGM_READWRITE, 0, &pstm);
+ if (hr != STG_E_FILENOTFOUND)
+ Fail("OpenStream succeeded for non-CONTENTS %lX\n", hr);
+
+ hr = pstg->CreateStorage(L"file", STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_FILE, NULL, &pstg2);
+ if (hr != STG_E_INVALIDFUNCTION)
+ Fail("CreateStorage succeeded %lX\n", hr);
+ hr = pstg->OpenStorage(L"file", NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL,
+ NULL, &pstg2);
+ if (hr != STG_E_FILENOTFOUND)
+ Fail("OpenStorage succeeded %lX\n", hr);
+
+ hr = pstg->Commit(0);
+ Result(hr, "Commit");
+ hr = pstg->Revert();
+ Result(hr, "Revert");
+
+ t_enum(pstg);
+
+ TestFile(wfn, "stg3");
+ hr = StgCreateStorage(wfn, STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_DOCUMENT, NULL, &pstg2);
+ Result(hr, "Open target docfile");
+ hr = pstg->CopyTo(0, NULL, NULL, pstg2);
+ Result(hr, "CopyTo");
+ t_enum(pstg2);
+
+ hr = pstg2->DestroyElement(L"CONTENTS");
+ Result(hr, "Destroy dest CONTENTS");
+ hr = pstg->MoveElementTo(L"CONTENTS", pstg2, L"dest", STGMOVE_COPY);
+ Result(hr, "MoveElementTo");
+ t_enum(pstg2);
+ pstg2->Release();
+
+ hr = pstg->RenameElement(L"stg2", L"stg3");
+ if (hr != STG_E_FILENOTFOUND)
+ Fail("RenameElement returned %lX\n", hr);
+ hr = pstg->DestroyElement(L"stg3");
+ if (hr != STG_E_FILENOTFOUND)
+ Fail("DestroyElement returned %lX\n", hr);
+ hr = pstg->SetElementTimes(L"file", NULL, NULL, NULL);
+ if (hr != STG_E_FILENOTFOUND)
+ Fail("SetElementTimes returned %lX\n", hr);
+ hr = pstg->SetClass(CLSID_NULL);
+ if (hr != STG_E_INVALIDFUNCTION)
+ Fail("SetClass returned %lX\n", hr);
+ hr = pstg->SetStateBits(0, 0);
+ if (hr != STG_E_INVALIDFUNCTION)
+ Fail("SetStateBits returned %lX\n", hr);
+}
+
+static char NUMBERS[] = "12345678901234567890123456789012345678901234567890";
+
+void t_stream(IStream *pstm)
+{
+ IStream *pstmC;
+ char buf[sizeof(NUMBERS)*2];
+ ULONG cb;
+ HRESULT hr;
+ ULARGE_INTEGER ulPos, uli;
+ LARGE_INTEGER li;
+ STATSTG stat;
+
+ hr = pstm->Stat(&stat, 0);
+ Result(hr, "Stat");
+ PrintStat(&stat, FALSE);
+ CoMemFree(stat.pwcsName);
+
+ uli.HighPart = 0;
+ uli.LowPart = 0;
+ hr = pstm->SetSize(uli);
+ Result(hr, "SetSize");
+
+ hr = pstm->Write(NUMBERS, sizeof(NUMBERS), &cb);
+ Result(hr, "Write");
+ hr = pstm->Commit(0);
+ Result(hr, "Commit");
+ hr = pstm->Revert();
+ Result(hr, "Revert");
+
+ li.HighPart = -1;
+ li.LowPart = (ULONG)(-((LONG)sizeof(NUMBERS)/2));
+ hr = pstm->Seek(li, STREAM_SEEK_END, &ulPos);
+ Result(hr, "Seek");
+ if (ulPos.HighPart != 0 ||
+ ulPos.LowPart != sizeof(NUMBERS)-sizeof(NUMBERS)/2)
+ Fail("Incorrect seek, %lu:%lu\n", ulPos.HighPart, ulPos.LowPart);
+
+ li.HighPart = 0;
+ li.LowPart = sizeof(NUMBERS)/2;
+ hr = pstm->Seek(li, STREAM_SEEK_CUR, &ulPos);
+ Result(hr, "Seek");
+ if (ulPos.HighPart != 0 ||
+ ulPos.LowPart != sizeof(NUMBERS))
+ Fail("Incorrect seek, %lu:%lu\n", ulPos.HighPart, ulPos.LowPart);
+
+ li.HighPart = li.LowPart = 0;
+ hr = pstm->Seek(li, STREAM_SEEK_SET, &ulPos);
+ Result(hr, "Seek");
+ if (ulPos.LowPart != 0 || ulPos.HighPart != 0)
+ Fail("Incorrect seek, %lu:%lu\n", ulPos.HighPart, ulPos.LowPart);
+
+ hr = pstm->Read(buf, sizeof(NUMBERS), &cb);
+ Result(hr, "Read");
+ if (strcmp(buf, NUMBERS))
+ Fail("Incorrect stream contents\n");
+
+ uli.HighPart = 0;
+ uli.LowPart = sizeof(NUMBERS)/2;
+ hr = pstm->SetSize(uli);
+ Result(hr, "SetSize");
+ hr = pstm->Seek(li, STREAM_SEEK_SET, NULL);
+ Result(hr, "Seek");
+ hr = pstm->Read(buf, sizeof(NUMBERS), &cb);
+ Result(hr, "Read");
+ if (cb != sizeof(NUMBERS)/2)
+ Fail("SetSize failed to size stream properly\n");
+ if (memcmp(buf, NUMBERS, sizeof(NUMBERS)/2))
+ Fail("SetSize corrupted contents\n");
+
+ hr = pstm->Clone(&pstmC);
+ Result(hr, "Clone");
+ hr = pstm->Seek(li, STREAM_SEEK_SET, NULL);
+ Result(hr, "Seek");
+ hr = pstm->CopyTo(pstmC, uli, NULL, NULL);
+ Result(hr, "CopyTo");
+ hr = pstm->Seek(li, STREAM_SEEK_SET, NULL);
+ Result(hr, "Seek");
+ uli.LowPart = sizeof(NUMBERS) & ~1;
+ hr = pstm->CopyTo(pstmC, uli, NULL, NULL);
+ Result(hr, "CopyTo");
+ hr = pstm->Seek(li, STREAM_SEEK_SET, NULL);
+ Result(hr, "Seek");
+ hr = pstm->Read(buf, (sizeof(NUMBERS)&~1)*2, &cb);
+ Result(hr, "Read");
+ if (memcmp(buf, NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+sizeof(NUMBERS)/2, NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+(sizeof(NUMBERS)&~1), NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+3*(sizeof(NUMBERS)/2), NUMBERS, sizeof(NUMBERS)/2))
+ Fail("Stream contents incorrect\n");
+ pstmC->Release();
+
+ ulPos.HighPart = 0xffffffff;
+ ulPos.LowPart = 0x10000;
+ uli.HighPart = 0;
+ uli.LowPart = 0x100;
+ hr = pstm->LockRegion(ulPos, uli, LOCK_ONLYONCE);
+ Result(hr, "LockRegion");
+ ulPos.LowPart = 0x10080;
+ hr = pstm->LockRegion(ulPos, uli, LOCK_ONLYONCE);
+ if (hr != STG_E_LOCKVIOLATION)
+ Fail("Illegal LockRegion returned 0x%lX\n", hr);
+ ulPos.LowPart = 0x10000;
+ hr = pstm->UnlockRegion(ulPos, uli, LOCK_ONLYONCE);
+ Result(hr, "UnlockRegion");
+}
+
+DWORD fmts[] = {STGFMT_DOCUMENT, STGFMT_FILE};
+char *fmt_names[] = {"hdoc", "hfile"};
+#define NFMTS (sizeof(fmts)/sizeof(fmts[0]))
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ IStorage *pstg, *pstgFile;
+ IStream *pstm;
+ HRESULT hr;
+ WCHAR wfn[MAX_PATH];
+
+#if WIN32 == 300
+ hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+#else
+ hr = CoInitialize(NULL);
+#endif
+ Result(hr, "CoInitialize");
+
+ TestFile(wfn, "stg");
+ hr = StgCreateStorage(wfn, STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_DIRECTORY, NULL, &pstg);
+ Result(hr, "Open root directory");
+
+ t_dirstg(pstg);
+
+ hr = pstg->CreateStorage(L"file", STGM_READWRITE | STGM_SHARE_EXCLUSIVE |
+ STGM_CREATE, STGFMT_FILE, NULL, &pstgFile);
+ Result(hr, "Create file");
+
+ t_filstg(pstgFile);
+
+ hr = pstgFile->OpenStream(L"CONTENTS", NULL, STGM_READWRITE,
+ NULL, &pstm);
+ Result(hr, "Open stream");
+
+ t_stream(pstm);
+
+ pstm->Release();
+ pstgFile->Release();
+ pstg->Release();
+
+ hr = StgOpenStorage(wfn, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ NULL, NULL, &pstg);
+ Result(hr, "Open root directory");
+ pstg->Release();
+
+ HANDLE h;
+ DWORD dwStgFmt, grfMode;
+ int i;
+ STATSTG stat;
+
+ grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
+ for (i = 0; i < NFMTS; i++)
+ {
+ dwStgFmt = fmts[i];
+ TestFile(wfn, fmt_names[i]);
+ h = CreateFile(wfn, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ Fail("Unable to create file\n");
+ hr = StgCreateStorageOnHandle(h, grfMode, dwStgFmt, &pstg);
+ Result(hr, "StgCreateStorageOnHandle fmt %lu", dwStgFmt);
+ pstg->Release();
+ CloseHandle(h);
+
+ h = CreateFile(wfn, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ Fail("Unable to open file\n");
+ hr = StgOpenStorageOnHandle(h, grfMode, &pstg);
+ Result(hr, "StgOpenStorageOnHandle fmt %lu", dwStgFmt);
+ pstg->Stat(&stat, STATFLAG_NONAME);
+ if (stat.dwStgFmt != dwStgFmt)
+ Fail("Stat returned fmt %lu rather than %lu\n", stat.dwStgFmt,
+ dwStgFmt);
+ pstg->Release();
+ CloseHandle(h);
+ }
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/fsstg/utest/idirtest.cxx b/private/ole32/stg/fsstg/utest/idirtest.cxx
new file mode 100644
index 000000000..466da3380
--- /dev/null
+++ b/private/ole32/stg/fsstg/utest/idirtest.cxx
@@ -0,0 +1,324 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: fstest.cxx
+//
+// History: 30-Jun-93 DrewB Created
+// 1-Jun-94 BillMo Changed share mode for MoveElementTo
+// Added test for:
+// Cross volume copy with id
+// Cross volume move with id
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+void EndTest(int rc)
+{
+ if (rc == 0)
+ printf("Test SUCCEEDED\n");
+ else
+ printf("Test FAILED\n");
+ CoUninitialize();
+ exit(rc);
+}
+
+void PrintStat(STATDIR *pstat, BOOL fEnum)
+{
+ printf("'%ws'\n", pstat->pwcsName);
+ printf("Type: %lu\n", pstat->stgfmt);
+ if (!fEnum)
+ {
+ printf("Mode: %lX\n", pstat->grfMode);
+ printf("Attrs: %lX\n", pstat->grfAttrs);
+ }
+ if (pstat->stgfmt == STGFMT_FILE)
+ {
+ printf("Size: %lu:%lu\n", pstat->cbSize.HighPart,
+ pstat->cbSize.LowPart);
+ //if (!fEnum)
+ // printf("Locks: %lX\n", pstat->grfLocksSupported);
+ }
+ else
+ {
+ if (pstat->ctime.dwHighDateTime != 0 ||
+ pstat->ctime.dwLowDateTime != 0)
+ printf("Ctime: %s %x %x\n", FileTimeText(&pstat->ctime),
+ pstat->ctime.dwHighDateTime, pstat->ctime.dwLowDateTime);
+ if (pstat->mtime.dwHighDateTime != 0 ||
+ pstat->mtime.dwLowDateTime != 0)
+ printf("Mtime: %s %x %x\n", FileTimeText(&pstat->mtime),
+ pstat->mtime.dwHighDateTime, pstat->mtime.dwLowDateTime);
+ if (pstat->atime.dwHighDateTime != 0 ||
+ pstat->atime.dwLowDateTime != 0)
+ printf("Atime: %s %x %x\n", FileTimeText(&pstat->atime),
+ pstat->atime.dwHighDateTime, pstat->atime.dwLowDateTime);
+ }
+ if (!fEnum)
+ printf("Clsid: %s\n", GuidText(&pstat->clsid));
+}
+
+void PrintStatStg(STATSTG *pstat, BOOL fEnum)
+{
+ printf("'%ws'\n", pstat->pwcsName);
+ printf("Type: %lu\n", pstat->type);
+ if (!fEnum)
+ {
+ printf("Mode: %lX\n", pstat->grfMode);
+ //printf("Attrs: %lX\n", pstat->grfAttrs);
+ }
+ if (pstat->type == STGTY_STREAM)
+ {
+ printf("Size: %lu:%lu\n", pstat->cbSize.HighPart,
+ pstat->cbSize.LowPart);
+ if (!fEnum)
+ printf("Locks: %lX\n", pstat->grfLocksSupported);
+ }
+ else
+ {
+ if (pstat->ctime.dwHighDateTime != 0 ||
+ pstat->ctime.dwLowDateTime != 0)
+ printf("Ctime: %s %x %x\n", FileTimeText(&pstat->ctime),
+ pstat->ctime.dwHighDateTime, pstat->ctime.dwLowDateTime);
+ if (pstat->mtime.dwHighDateTime != 0 ||
+ pstat->mtime.dwLowDateTime != 0)
+ printf("Mtime: %s %x %x\n", FileTimeText(&pstat->mtime),
+ pstat->mtime.dwHighDateTime, pstat->mtime.dwLowDateTime);
+ if (pstat->atime.dwHighDateTime != 0 ||
+ pstat->atime.dwLowDateTime != 0)
+ printf("Atime: %s %x %x\n", FileTimeText(&pstat->atime),
+ pstat->atime.dwHighDateTime, pstat->atime.dwLowDateTime);
+ }
+ if (!fEnum)
+ printf("Clsid: %s\n", GuidText(&pstat->clsid));
+}
+
+
+void t_misc (IDirectory *pstg, WCHAR *pwcsName, DWORD grfAttrs)
+{
+ FILETIME ctime;
+ FILETIME atime;
+ FILETIME mtime;
+ GUID clsid = { /* fa6aefb0-b0ac-11ce-b339-00aa00680937 */
+ 0xfa6aefb0, 0xb0ac, 0x11ce,
+ {0xb3, 0x39, 0x00, 0xaa, 0x00, 0x68, 0x09, 0x37}};
+ HRESULT hr;
+ STATDIR stat;
+
+ ctime.dwHighDateTime = atime.dwHighDateTime = mtime.dwHighDateTime =
+ 0x01ba44cc; // Jun 27 20:30:25
+ ctime.dwLowDateTime = atime.dwLowDateTime = mtime.dwLowDateTime =
+ 0xd4c81000;
+
+ hr = pstg->SetTimes(pwcsName, &ctime, &atime, &mtime);
+ Result (hr, "SetElementTimes 0x1ba44cc 0xd4c81000");
+
+ hr = pstg->SetDirectoryClass (clsid);
+ if (hr != STG_E_INVALIDPARAMETER)
+ Result (hr, "SetDirectoryClass fa6aefb0-b0ac-11ce-b339-00aa00680937");
+
+ hr = pstg->SetAttributes (pwcsName, grfAttrs);
+ Result (hr, "SetAttributes 0x30");
+
+ hr = pstg->StatElement (pwcsName, &stat, STATFLAG_DEFAULT);
+ Result (hr, "Stat");
+ PrintStat(&stat, FALSE);
+
+}
+
+void t_enum(IDirectory *pstg)
+{
+ IEnumSTATDIR *penm, *penm2;
+ STATDIR stat;
+ HRESULT hr;
+
+ hr = pstg->EnumDirectoryElements(&penm);
+ Result(hr, "Enum");
+
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result(hr, "Next");
+ if (GetScode(hr) == S_FALSE)
+ break;
+
+ PrintStat(&stat, TRUE);
+ CoMemFree(stat.pwcsName);
+ }
+
+ hr = penm->Skip(1);
+ Result(hr, "Skip");
+ hr = penm->Reset();
+ Result(hr, "Reset");
+ hr = penm->Clone(&penm2);
+ Result(hr, "Clone");
+
+ penm2->Release();
+ penm->Release();
+}
+
+void t_enumstg(IStorage *pstg)
+{
+ IEnumSTATSTG *penm, *penm2;
+ STATSTG stat;
+ HRESULT hr;
+
+ hr = pstg->EnumElements(NULL, NULL, NULL, &penm);
+ Result(hr, "Enum");
+
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result(hr, "Next");
+ if (GetScode(hr) == S_FALSE)
+ break;
+
+ PrintStatStg(&stat, TRUE);
+ CoMemFree(stat.pwcsName);
+ }
+
+ hr = penm->Skip(1);
+ Result(hr, "Skip");
+ hr = penm->Reset();
+ Result(hr, "Reset");
+ hr = penm->Clone(&penm2);
+ Result(hr, "Clone");
+
+ penm2->Release();
+ penm->Release();
+}
+
+void t_stg (IDirectory *pIDir)
+{
+ IStorage *pIStg;
+ HRESULT hr = pIDir->QueryInterface (IID_IStorage, (void**) &pIStg);
+ if (hr != E_NOINTERFACE)
+ {
+ IStream *pIStm;
+ Result (hr, "Querying for IStorage");
+ hr = pIStg->CreateStream(L"stream1", STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE, NULL, NULL, &pIStm);
+ Result (hr, "Creating a stream on a directory");
+ Result (pIStm->Release(), "Releasing IStream");
+ // BUGBUG it's not enumerating the OLE namespace now
+ t_enumstg (pIStg);
+ // This should be a refcount of 1 since IDirectory has a refcount
+ Result (pIStg->Release(), "Releasing IStorage");
+ }
+ else
+ printf ("IStorage interface not available from IDirectory\n");
+}
+
+char *fmt_names[] = {"hdir", "hfile"};
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ IStorage *pstg;
+ IStream *pstm;
+ IDirectory *pdir, *pdir2, *pdir3, *pdir5;
+ HRESULT hr = S_OK, rc = S_OK;
+ WCHAR wfn[] = L"hdir";
+ WCHAR wfn2[] = L"hdir2";
+ WCHAR wfn3[] = L"hdir3";
+ WCHAR wfn4[] = L"hdir4";
+ WCHAR wfn5[] = L"hdir5";
+ WCHAR wfn6[] = L"hdir6";
+ WCHAR wfn7[] = L"hdir7";
+ const DWORD STGM_RW_SHARE_EXCLUSIVE = STGM_READWRITE|STGM_SHARE_EXCLUSIVE;
+
+#if WIN32 == 300
+ //hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+ hr = CoInitialize(NULL);
+#else
+ hr = CoInitialize(NULL);
+#endif
+ Result(hr, "CoInitialize");
+
+ STGFMT stgfmt = STGFMT_DIRECTORY;
+ STGCREATE stgcreate = {NULL, NULL, NULL};
+ STGOPEN stgopen = {STGFMT_DIRECTORY, STGM_RW_SHARE_EXCLUSIVE, NULL};
+ STGOPEN stgopenstg = {STGFMT_DOCUMENT, STGM_RW_SHARE_EXCLUSIVE, NULL};
+ hr = StgCreateStorageEx(wfn, &stgcreate, &stgopen, IID_IDirectory,
+ (void **)&pdir);
+ Result(hr, "Create root directory");
+ Result(pdir->Release(), "Releasing root directory");
+
+ stgopen.grfMode |= STGM_CREATE;
+
+ hr = StgCreateStorageEx(wfn, &stgcreate, &stgopen, IID_IDirectory,
+ (void **)&pdir);
+ Result(hr, "Create root directory");
+
+ hr = pdir->CreateElement (wfn2, &stgcreate, &stgopen, IID_IDirectory,
+ (void **) &pdir2);
+ Result (hr, "Create subdirectory2");
+ Result(pdir2->Release(), "Releasing subdirectory");
+
+ hr = pdir->CreateElement (wfn3, &stgcreate, &stgopen, IID_IDirectory,
+ (void **) &pdir3);
+ Result (hr, "Create subdirectory3");
+ Result(pdir3->Release(), "Releasing subdirectory");
+
+ hr = pdir->MoveElement (wfn3, NULL, wfn4, STGMOVE_MOVE);
+ Result (hr, "Move subdirectory");
+
+ hr = pdir->MoveElement (wfn4, NULL, wfn3, STGMOVE_COPY);
+ Result (hr, "Copy subdirectory");
+
+ stgopen.grfMode &= ~STGM_CREATE;
+ hr = pdir->OpenElement (wfn3, &stgopen, IID_IDirectory, &stgfmt,
+ (void **) &pdir3);
+ Result (hr, "Open subdirectory3");
+
+ stgopen.grfMode |= STGM_CREATE;
+ hr = pdir3->CreateElement (wfn5, &stgcreate, &stgopen, IID_IDirectory,
+ (void **) &pdir5);
+ Result (hr, "Create subdirectory5");
+ Result (pdir5->Release(), "Releasing subdirectory5");
+
+ hr = pdir3->CreateElement (wfn6, &stgcreate, &stgopenstg,IID_IStorage,
+ (void **) &pstg);
+ Result (hr, "Create storage6");
+ Result (pstg->Release(), "Releasing storage6");
+ t_misc (pdir3, wfn6, FILE_ATTRIBUTE_READONLY); // change the storage
+
+ t_stg (pdir3); // create an embedded stream
+ Result (pdir3->Release(), "Releasing subdirectory3");
+ hr = pdir->MoveElement (wfn3, NULL, wfn4, STGMOVE_COPY);
+ Result (hr, "Copy subdirectory deep");
+
+ stgopen.grfMode &= ~STGM_CREATE;
+ hr = pdir->OpenElement (wfn2, &stgopen, IID_IDirectory, &stgfmt,
+ (void **) &pdir2);
+ Result (hr, "Open subdirectory2");
+ stgopen.grfMode |= STGM_CREATE;
+
+ t_misc (pdir,NULL,FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE);
+ t_enum (pdir);
+
+ Result (pdir2->Release(), "Releasing subdirectory");
+
+ hr = pdir->DeleteElement (wfn2);
+ Result (hr, "Delete subdirectory");
+
+ stgopen.stgfmt = STGFMT_FILE;
+ hr = pdir->CreateElement (wfn7, &stgcreate, &stgopen, IID_IStream,
+ (void **) &pstm);
+ Result (hr, "Create file stream");
+ hr = pstm->Write ("Hello World\n", strlen("Hello World\n")+1, NULL);
+ Result (hr, "Writing Hello World");
+ Result(pstm->Release(), "Releasing file stream");
+ t_misc (pdir, wfn7, FILE_ATTRIBUTE_READONLY);
+ // and delete the file
+ Result(pdir->Release(), "Releasing root directory");
+
+
+ //t_dirstg(pstg);
+ // t_filstg(pstgFile);
+ //t_stream(pstm);
+
+ EndTest(rc);
+}
diff --git a/private/ole32/stg/fsstg/utest/makefile b/private/ole32/stg/fsstg/utest/makefile
new file mode 100644
index 000000000..7ab834944
--- /dev/null
+++ b/private/ole32/stg/fsstg/utest/makefile
@@ -0,0 +1,11 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1993.
+# All rights reserved.
+#
+############################################################################
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+
+
diff --git a/private/ole32/stg/fsstg/utest/pch.cxx b/private/ole32/stg/fsstg/utest/pch.cxx
new file mode 100644
index 000000000..7e4ce3efe
--- /dev/null
+++ b/private/ole32/stg/fsstg/utest/pch.cxx
@@ -0,0 +1,26 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: pch.cxx
+//
+// History: 09-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+
+#define INC_OLE2
+#include <windows.h>
+#if WIN32 != 300
+#include <compobj.h>
+#include <storage.h>
+#endif
+#include <stgint.h>
+#include <memalloc.h>
+
+#include "tutils.hxx"
diff --git a/private/ole32/stg/fsstg/utest/sources b/private/ole32/stg/fsstg/utest/sources
new file mode 100644
index 000000000..f9c3e36a8
--- /dev/null
+++ b/private/ole32/stg/fsstg/utest/sources
@@ -0,0 +1,46 @@
+!IF 0
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Bill Morel (billmo) 20-Jan-1994
+
+NOTE: Commented description of this file is in \nt\public\oak\bin\sources.tpl
+
+!ENDIF
+
+MINORCOMP=stg
+MAJORCOMP=ole32
+
+TARGETNAME=fstest
+TARGETTYPE=PROGRAM
+TARGETPATH=obj
+
+USE_CRTDLL=1
+CAIRO_PRODUCT=1
+
+TARGETLIBS= $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib
+
+SOURCES= fstest.cxx\
+ tutils.cxx
+
+UMTYPE=console
+UMTEST=
+
+#PRECOMPILED_INCLUDE=pch.cxx
+
diff --git a/private/ole32/stg/fsstg/utest/tutils.cxx b/private/ole32/stg/fsstg/utest/tutils.cxx
new file mode 100644
index 000000000..1482dd08a
--- /dev/null
+++ b/private/ole32/stg/fsstg/utest/tutils.cxx
@@ -0,0 +1,356 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tutils.cxx
+//
+// Contents: Generic utilities for tests
+//
+// History: 06-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+static BOOL fExitOnFail = TRUE;
+
+BOOL GetExitOnFail(void)
+{
+ return fExitOnFail;
+}
+
+void SetExitOnFail(BOOL set)
+{
+ fExitOnFail = set;
+}
+
+// Print out an error message and terminate
+void Fail(char *fmt, ...)
+{
+ va_list args;
+
+ args = va_start(args, fmt);
+ fprintf(stderr, "** Fatal error **: ");
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ EndTest(1);
+}
+
+typedef struct
+{
+ SCODE sc;
+ char *text;
+} StatusCodeText;
+
+static StatusCodeText scodes[] =
+{
+ S_OK, "S_OK",
+ S_FALSE, "S_FALSE",
+ STG_E_INVALIDFUNCTION, "STG_E_INVALIDFUNCTION",
+ STG_E_FILENOTFOUND, "STG_E_FILENOTFOUND",
+ STG_E_PATHNOTFOUND, "STG_E_PATHNOTFOUND",
+ STG_E_TOOMANYOPENFILES, "STG_E_TOOMANYOPENFILES",
+ STG_E_ACCESSDENIED, "STG_E_ACCESSDENIED",
+ STG_E_INVALIDHANDLE, "STG_E_INVALIDHANDLE",
+ STG_E_INSUFFICIENTMEMORY, "STG_E_INSUFFICIENTMEMORY",
+ STG_E_INVALIDPOINTER, "STG_E_INVALIDPOINTER",
+ STG_E_NOMOREFILES, "STG_E_NOMOREFILES",
+ STG_E_DISKISWRITEPROTECTED, "STG_E_DISKISWRITEPROTECTED",
+ STG_E_SEEKERROR, "STG_E_SEEKERROR",
+ STG_E_WRITEFAULT, "STG_E_WRITEFAULT",
+ STG_E_READFAULT, "STG_E_READFAULT",
+ STG_E_SHAREVIOLATION, "STG_E_SHAREVIOLATION",
+ STG_E_LOCKVIOLATION, "STG_E_LOCKVIOLATION",
+ STG_E_FILEALREADYEXISTS, "STG_E_FILEALREADYEXISTS",
+ STG_E_INVALIDPARAMETER, "STG_E_INVALIDPARAMETER",
+ STG_E_MEDIUMFULL, "STG_E_MEDIUMFULL",
+ STG_E_ABNORMALAPIEXIT, "STG_E_ABNORMALAPIEXIT",
+ STG_E_INVALIDHEADER, "STG_E_INVALIDHEADER",
+ STG_E_INVALIDNAME, "STG_E_INVALIDNAME",
+ STG_E_UNKNOWN, "STG_E_UNKNOWN",
+ STG_E_UNIMPLEMENTEDFUNCTION, "STG_E_UNIMPLEMENTEDFUNCTION",
+ STG_E_INVALIDFLAG, "STG_E_INVALIDFLAG",
+ STG_E_INUSE, "STG_E_INUSE",
+ STG_E_NOTCURRENT, "STG_E_NOTCURRENT",
+ STG_E_REVERTED, "STG_E_REVERTED",
+ STG_E_CANTSAVE, "STG_E_CANTSAVE",
+ STG_E_OLDFORMAT, "STG_E_OLDFORMAT",
+ STG_E_OLDDLL, "STG_E_OLDDLL",
+ STG_E_SHAREREQUIRED, "STG_E_SHAREREQUIRED",
+ STG_E_NOTFILEBASEDSTORAGE, "STG_E_NOTFILEBASEDSTORAGE",
+ STG_E_EXTANTMARSHALLINGS, "STG_E_EXTANTMARSHALLINGS",
+ STG_S_CONVERTED, "STG_S_CONVERTED"
+};
+#define NSCODETEXT (sizeof(scodes)/sizeof(scodes[0]))
+
+// Convert a status code to text
+char *ScText(SCODE sc)
+{
+ int i;
+
+ for (i = 0; i<NSCODETEXT; i++)
+ if (scodes[i].sc == sc)
+ return scodes[i].text;
+ return "<Unknown SCODE>";
+}
+
+// Output a call result and check for failure
+HRESULT Result(HRESULT hr, char *fmt, ...)
+{
+ SCODE sc;
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ sc = GetScode(hr);
+ printf(" - %s (0x%lX)\n", ScText(sc), sc);
+ if (FAILED(sc) && fExitOnFail)
+ Fail("Unexpected call failure\n");
+ return hr;
+}
+
+// Perform Result() when the expectation is failure
+HRESULT IllResult(HRESULT hr, char *fmt, ...)
+{
+ SCODE sc;
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ sc = GetScode(hr);
+ printf(" - %s (0x%lX)\n", ScText(sc), sc);
+ if (SUCCEEDED(sc) && fExitOnFail)
+ Fail("Unexpected call success\n");
+ return hr;
+}
+
+char *TcsText(TCHAR *ptcs)
+{
+ static char buf[256];
+
+ TTOA(ptcs, buf, 256);
+ return buf;
+}
+
+char *FileTimeText(FILETIME *pft)
+{
+ static char buf[80];
+ struct tm ctm;
+#ifndef FLAT
+ WORD dosdate, dostime;
+
+ if (CoFileTimeToDosDateTime(pft, &dosdate, &dostime))
+ {
+ ctm.tm_sec = (dostime & 31)*2;
+ ctm.tm_min = (dostime >> 5) & 63;
+ ctm.tm_hour = dostime >> 11;
+ ctm.tm_mday = dosdate & 31;
+ ctm.tm_mon = ((dosdate >> 5) & 15)-1;
+ ctm.tm_year = (dosdate >> 9)+80;
+ ctm.tm_wday = 0;
+#else
+ SYSTEMTIME st;
+
+ if (FileTimeToSystemTime(pft, &st))
+ {
+ ctm.tm_sec = st.wSecond;
+ ctm.tm_min = st.wMinute;
+ ctm.tm_hour = st.wHour;
+ ctm.tm_mday = st.wDay;
+ ctm.tm_mon = st.wMonth-1;
+ ctm.tm_year = st.wYear-1900;
+ ctm.tm_wday = st.wDayOfWeek;
+#endif
+ ctm.tm_yday = 0;
+ ctm.tm_isdst = 0;
+ strcpy(buf, asctime(&ctm));
+ buf[strlen(buf)-1] = 0;
+ }
+ else
+ sprintf(buf, "<FILETIME %08lX:%08lX>", pft->dwHighDateTime,
+ pft->dwLowDateTime);
+ return buf;
+}
+
+#pragma pack(1)
+struct SplitGuid
+{
+ DWORD dw1;
+ WORD w1;
+ WORD w2;
+ BYTE b[8];
+};
+#pragma pack()
+
+char *GuidText(GUID *pguid)
+{
+ static char buf[39];
+ SplitGuid *psg = (SplitGuid *)pguid;
+
+ sprintf(buf, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
+ psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
+ return buf;
+}
+
+#define CROW 16
+
+void BinText(ULONG cbSize, BYTE *pb)
+{
+ ULONG cb, i;
+
+ while (cbSize > 0)
+ {
+ cb = min(CROW, cbSize);
+ cbSize -= cb;
+ for (i = 0; i<cb; i++)
+ printf(" %02X", pb[i]);
+ for (i = cb; i<CROW; i++)
+ printf(" ");
+ printf(" '");
+ for (i = 0; i<cb; i++)
+ if (pb[i] >= 0x20 && pb[i] <= 0x7f)
+ putchar(pb[i]);
+ else
+ putchar('.');
+ pb += cb;
+ printf("'\n");
+ }
+}
+
+// BUGBUG - Remove for Cairole when they exist
+STDAPI CoMemAlloc(DWORD cbSize, void **ppv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc;
+
+ if (SUCCEEDED(GetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ *ppv = pMalloc->Alloc(cbSize);
+ pMalloc->Release();
+
+ if (*ppv == NULL)
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ }
+ else
+ *ppv = NULL;
+
+ return hr;
+}
+
+STDAPI CoMemFree(void *pv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc;
+
+ if (SUCCEEDED(GetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ pMalloc->Free(pv);
+ pMalloc->Release();
+ }
+
+ return hr;
+}
+
+TCHAR *TestFile(TCHAR *ptcsName, char *pszFile)
+{
+ char achFn[MAX_PATH];
+ char *dir, *file;
+ int len;
+
+ dir = getenv("DFDATA");
+ if (dir)
+ strcpy(achFn, dir);
+ else
+ strcpy(achFn, ".");
+ len = strlen(achFn);
+ if (achFn[len-1] != '\\')
+ achFn[len++] = '\\';
+
+ if (pszFile)
+ {
+ strcpy(achFn+len, pszFile);
+ }
+ else
+ {
+ file = getenv("DFFILE");
+ if (file)
+ strcpy(achFn+len, file);
+ else
+ strcpy(achFn+len, "TEST.DFL");
+ }
+
+ ATOT(achFn, ptcsName, MAX_PATH);
+ return ptcsName+len;
+}
+
+#if WIN32 == 300
+char *TestFormat(DWORD *pdwFmt, DWORD *pgrfMode)
+{
+ char *fmt;
+
+ fmt = getenv("STGFMT");
+ if (fmt == NULL || !strcmp(fmt, "doc"))
+ {
+ fmt = "document";
+ *pdwFmt = STGFMT_DOCUMENT;
+ }
+ else if (!strcmp(fmt, "file"))
+ {
+ fmt = "file";
+ *pdwFmt = STGFMT_FILE;
+ }
+ else
+ {
+ fmt = "directory";
+ *pdwFmt = STGFMT_DIRECTORY;
+ *pgrfMode &= ~STGM_CREATE;
+ }
+ return fmt;
+}
+#endif
+
+void CreateTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName)
+{
+ HRESULT hr;
+ TCHAR atcFile[MAX_PATH];
+ char *fmt;
+
+ if (ptcsName == NULL)
+ ptcsName = atcFile;
+ TestFile(ptcsName, pszFile);
+#if WIN32 == 300
+ DWORD dwStgFmt;
+
+ fmt = TestFormat(&dwStgFmt, &grfMode);
+ hr = StgCreateStorage(ptcsName, grfMode, dwStgFmt, 0, ppstg);
+#else
+ hr = StgCreateDocfile(ptcsName, grfMode, 0, ppstg);
+ fmt = "docfile";
+#endif
+ if (fFail)
+ IllResult(hr, "Create %s %s", fmt, TcsText(ptcsName));
+ else
+ Result(hr, "Create %s %s", fmt, TcsText(ptcsName));
+}
+
+void OpenTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName)
+{
+ HRESULT hr;
+ TCHAR atcFile[MAX_PATH];
+
+ if (ptcsName == NULL)
+ ptcsName = atcFile;
+ TestFile(ptcsName, pszFile);
+ hr = StgOpenStorage(ptcsName, NULL, grfMode, NULL, 0, ppstg);
+ if (fFail)
+ IllResult(hr, "Open storage %s", TcsText(ptcsName));
+ else
+ Result(hr, "Open storage %s", TcsText(ptcsName));
+}
diff --git a/private/ole32/stg/fsstg/utest/tutils.hxx b/private/ole32/stg/fsstg/utest/tutils.hxx
new file mode 100644
index 000000000..b006da5f0
--- /dev/null
+++ b/private/ole32/stg/fsstg/utest/tutils.hxx
@@ -0,0 +1,84 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tutils.hxx
+//
+// Contents: Generic test utilities
+//
+// History: 06-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __TUTILS_HXX__
+#define __TUTILS_HXX__
+
+#ifndef UNICODE
+#define tcscpy(d, s) strcpy(d, s)
+#define tcslen(s) strlen(s)
+#define TTEXT(s) s
+#define TFMT "%s"
+#define ATOT(a, t, max) strcpy(t, a)
+#define TTOA(t, a, max) strcpy(a, t)
+#define WTOT(w, t, max) wcstombs(t, w, max)
+#define TTOW(t, w, max) mbstowcs(w, t, max)
+#else
+#define tcscpy(d, s) wcscpy(d, s)
+#define tcslen(s) wcslen(s)
+#define TTEXT(s) L##s
+#define TFMT "%ws"
+#define ATOT(a, t, max) mbstowcs(t, a, max)
+#define TTOA(t, a, max) wcstombs(a, t, max)
+#define WTOT(w, t, max) wcscpy(t, w)
+#define TTOW(t, w, max) wcscpy(w, t)
+#endif
+#ifdef WIN32
+#define ATOX(a, t, max) mbstowcs(t, a, max)
+#define XTOA(t, a, max) wcstombs(a, t, max)
+#define WTOX(w, t, max) wcscpy(t, w)
+#define XTOW(t, w, max) wcscpy(w, t)
+#else
+#define ATOX(a, t, max) strcpy(t, a)
+#define XTOA(t, a, max) strcpy(a, t)
+#define WTOX(w, t, max) wcstombs(t, w, max)
+#define XTOW(t, w, max) mbstowcs(w, t, max)
+#endif
+
+#ifdef CINTERFACE
+#define Mthd(this, name) ((this)->lpVtbl->name)
+#define SELF(p) (p),
+#else
+#define Mthd(this, name) (this)->name
+#define SELF(p)
+#endif
+
+// BUGBUG - Remove for Cairole when they exist
+STDAPI CoMemAlloc(DWORD cBytes, void **ppv);
+STDAPI CoMemFree(void *pv);
+
+BOOL GetExitOnFail(void);
+void SetExitOnFail(BOOL set);
+void Fail(char *fmt, ...);
+char *ScText(SCODE sc);
+HRESULT Result(HRESULT hr, char *fmt, ...);
+HRESULT IllResult(HRESULT hr, char *fmt, ...);
+char *TcsText(TCHAR *ptcs);
+char *FileTimeText(FILETIME *pft);
+char *GuidText(GUID *pguid);
+void BinText(ULONG cb, BYTE *pb);
+TCHAR *TestFile(TCHAR *ptcsName, char *pszFile);
+
+#if WIN32 == 300
+char *TestFormat(DWORD *pdwFmt, DWORD *pgrfMode);
+#endif
+
+void CreateTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName);
+void OpenTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName);
+
+// Defined by test, called by Fail
+void EndTest(int code);
+
+#endif // #ifndef __TUTILS_HXX__
diff --git a/private/ole32/stg/h/accstg.hxx b/private/ole32/stg/h/accstg.hxx
new file mode 100644
index 000000000..d654e2a0c
--- /dev/null
+++ b/private/ole32/stg/h/accstg.hxx
@@ -0,0 +1,164 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995.
+//
+// File: accstg.hxx
+//
+// Contents: CAccessControl header
+//
+// Classes: CAccessControl
+//
+// History: 00-Mar-95 DaveMont Created
+// 25-May-95 HenryLee Modified
+//
+// Notes: Requires CAcl class
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ACCSTG_HXX__
+#define __ACCSTG_HXX__
+
+#include <stgstm.hxx>
+#ifndef _CAIROSTG_
+#define _CAIROSTG_
+#endif
+#include <oleext.h>
+#include <aclapi.h>
+
+//+---------------------------------------------------------------------------
+//
+// Class: CAccessControl (fs)
+//
+// Purpose: Implements IAccessControl for a file
+//
+// Interface: See below
+//
+//----------------------------------------------------------------------------
+
+class CAccessControl : public IAccessControl
+{
+public:
+ inline CAccessControl ();
+
+ ~CAccessControl();
+ HRESULT InitAccessControl (HANDLE handle, DWORD grfMode, BOOL fGetDacl,
+ CAccessControl *pACParent);
+ inline HRESULT SwitchToHandle (HANDLE handle);
+ inline HRESULT RevertFromAbove ();
+ HRESULT InsertChild (CAccessControl *pACChild);
+ HRESULT RemoveChild (CAccessControl *pACChild);
+ HRESULT CommitFromAbove ();
+
+ // IAccessControl methods
+
+ STDMETHOD(GrantAccessRights)(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[]);
+ STDMETHOD(SetAccessRights)(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[]);
+ STDMETHOD(ReplaceAllAccessRights)(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[]);
+ STDMETHOD(DenyAccessRights)(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[]);
+ STDMETHOD(RevokeExplicitAccessRights)(ULONG cCount,
+ TRUSTEE Trustee[]);
+ STDMETHOD(IsAccessPermitted)(TRUSTEE *Trustee,
+ DWORD grfAccessPermissions);
+ STDMETHOD(GetEffectiveAccessRights)(TRUSTEE *Trustee,
+ DWORD *pgrfAccessPermissions );
+ STDMETHOD(GetExplicitAccessRights)(ULONG *pcCount,
+ PEXPLICIT_ACCESS *pExplicitAccessList);
+
+ STDMETHOD(CommitAccessRights)(DWORD grfCommitFlags);
+ STDMETHOD(RevertAccessRights)();
+
+private:
+ HRESULT ApplyAccessRights (ACCESS_MODE eAccessMode,
+ ULONG cCount,
+ ACCESS_REQUEST *pAccessRequestList,
+ PACL *pdacl,
+ BOOL fReplaceAll);
+
+ HRESULT InitializeCAcl(BOOL fGetDacl);
+
+HRESULT AccessRequestToExplicitAccess(
+ IN ACCESS_MODE AccessMode,
+ IN FILEDIR fd,
+ IN ACCESS_REQUEST *pListOfAccessRequests,
+ IN ULONG cCountOfAccessRequests,
+ OUT PEXPLICIT_ACCESS *pListOfExplicitAccess);
+
+HRESULT Win32ExplicitAccessToExplicitAccess(
+ IN ULONG cCountOfExplicitAccess,
+ IN PEXPLICIT_ACCESS pListOfWin32ExplicitAccess,
+ OUT PEXPLICIT_ACCESS *pListOfExplicitAccesses);
+protected:
+
+ ACL *m_pdacl; // current state of the object
+ BOOL m_isdirty; // optimization for commits
+ HANDLE m_handle; // a NULL handle means security not available
+ DWORD m_grfMode; // for transaction support
+ CAccessControl *m_pACParent; // transacted parent for nested transactions
+ CAccessControl *m_pACChild; // 1st child for nested transactions
+ CAccessControl *m_pACNext; // sibling for nested transactions
+ ACL *m_pdaclCommitted; // last committed state of the object
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: CAccessControl::CAccessControl
+//
+// Synopsis: Initialize the generic access control object.
+//
+// Arguments: none
+//
+//--------------------------------------------------------------------
+
+CAccessControl::CAccessControl() :
+ m_handle(NULL),
+ m_grfMode(NULL),
+ m_pdacl(NULL),
+ m_isdirty(FALSE),
+ m_pACParent(NULL),
+ m_pACChild(NULL),
+ m_pACNext(NULL),
+ m_pdaclCommitted(NULL)
+{
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CAccessControl::SwitchToHandle
+//
+// Synopsis: switch to a different file handle
+//
+// Arguments: [handle] File system handle
+//
+// Notes: The passed handle is saved to manipulate security
+// descriptors.
+//
+//+-------------------------------------------------------------------
+HRESULT CAccessControl::SwitchToHandle (HANDLE handle)
+{
+ m_handle = handle;
+ return ssResult(S_OK);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CAccessControl::RevertFromAbove
+//
+// Synopsis: put the object into reverted from the parent
+//
+// Arguments: [handle] File system handle
+//
+// Notes:
+//
+//+-------------------------------------------------------------------
+HRESULT CAccessControl::RevertFromAbove ()
+{
+ m_grfMode |= DF_REVERTED;
+ return ssResult(S_OK);
+}
+
+#endif // #ifndef __ACCSTG_HXX__
diff --git a/private/ole32/stg/h/async.hxx b/private/ole32/stg/h/async.hxx
new file mode 100644
index 000000000..fa05092a3
--- /dev/null
+++ b/private/ole32/stg/h/async.hxx
@@ -0,0 +1,30 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1996 - 1996.
+//
+// File: async.hxx
+//
+// Contents: Async docfile header
+//
+// Classes:
+//
+// Functions:
+//
+// History: 27-Mar-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ASYNC_HXX__
+#define __ASYNC_HXX__
+
+#define ISPENDINGERROR(x) ((x == E_PENDING) || (x == STG_E_PENDINGCONTROL))
+
+#define IID_IDefaultFillLockBytes IID_IDfReserved2
+#define IID_IAsyncFileLockBytes IID_IDfReserved3
+
+#define UNTERMINATED 0
+#define TERMINATED_NORMAL 1
+#define TERMINATED_ABNORMAL 2
+
+#endif // #ifndef __ASYNC_HXX__
diff --git a/private/ole32/stg/h/cache.hxx b/private/ole32/stg/h/cache.hxx
new file mode 100644
index 000000000..f1b5d03b8
--- /dev/null
+++ b/private/ole32/stg/h/cache.hxx
@@ -0,0 +1,106 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: cache.hxx
+//
+// Contents: Stream cache code
+//
+// Classes: CStreamCache
+//
+// Functions:
+//
+// History: 26-May-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __CACHE_HXX__
+#define __CACHE_HXX__
+
+
+class CDirectStream;
+class CDirectory;
+class CFat;
+
+#define CACHESIZE 9
+
+struct SCacheEntry
+{
+ ULONG ulOffset;
+ SECT sect;
+ ULONG ulRunLength;
+
+ inline SCacheEntry();
+};
+
+inline SCacheEntry::SCacheEntry()
+{
+ ulOffset = MAX_ULONG;
+ sect = ENDOFCHAIN;
+ ulRunLength = 0;
+}
+
+SAFE_DFBASED_PTR(CBasedDirectStreamPtr, CDirectStream);
+
+//+---------------------------------------------------------------------------
+//
+// Class: CStreamCache (stmc)
+//
+// Purpose: Cache for stream optimization
+//
+// Interface: See below.
+//
+// History: 14-Dec-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+class CStreamCache
+{
+public:
+ CStreamCache();
+ ~CStreamCache();
+
+ void Init(CMStream *pmsParent, SID sid, CDirectStream *pds);
+
+ void Empty(void);
+
+ SCODE GetSect(ULONG ulOffset, SECT *psect);
+ SCODE GetESect(ULONG ulOffset, SECT *psect);
+ SCODE EmptyRegion(ULONG oStart, ULONG oEnd);
+ SCODE Allocate(CFat *pfat, ULONG cSect, SECT *psectStart);
+
+ SCODE Contig(
+ ULONG ulOffset,
+ BOOL fWrite,
+ SSegment STACKBASED *aseg,
+ ULONG ulLength,
+ ULONG *pcSeg);
+
+private:
+ inline CDirectory *GetDir(void);
+ inline CFat * GetFat(void);
+ inline CFat * GetMiniFat(void);
+ inline ULONG GetSize(void);
+ inline SID GetSid(void);
+ inline CFat * SelectFat(void);
+ SCODE GetStart(SECT *psectStart);
+ inline BOOL CheckSegment(ULONG ulOffset,
+ SCacheEntry sce,
+ ULONG *pulCount,
+ SECT *psectCache,
+ ULONG *pulCacheOffset);
+
+ void CacheSegment(SSegment *pseg);
+
+ SCacheEntry _ase[CACHESIZE];
+ CBasedDirectStreamPtr _pds;
+ CBasedMStreamPtr _pmsParent;
+ SID _sid;
+ USHORT _uHighCacheIndex;
+ USHORT _uNextCacheIndex;
+ USHORT _uCacheState;
+};
+
+
+#endif // #ifndef __CACHE_HXX__
diff --git a/private/ole32/stg/h/cdocfile.hxx b/private/ole32/stg/h/cdocfile.hxx
new file mode 100644
index 000000000..febd45320
--- /dev/null
+++ b/private/ole32/stg/h/cdocfile.hxx
@@ -0,0 +1,188 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992
+//
+// File: cdocfile.hxx
+//
+// Contents: CDocFile class header
+//
+// Classes: CDocFile
+//
+// History: 26-Sep-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __CDOCFILE_HXX__
+#define __CDOCFILE_HXX__
+
+#include <dfmsp.hxx>
+#ifndef REF
+#include <dfbasis.hxx>
+#include <ulist.hxx>
+#endif //!REF
+#include <handle.hxx>
+#include <pdocfile.hxx>
+
+interface ILockBytes;
+class PDocFileIterator;
+
+//+--------------------------------------------------------------
+//
+// Class: CDocFile (df)
+//
+// Purpose: DocFile object
+//
+// Interface: See below
+//
+// History: 07-Nov-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+class CDocFile : public PDocFile, public CMallocBased
+{
+public:
+ inline void *operator new(size_t size, IMalloc * const pMalloc);
+ inline void *operator new(size_t size, CDFBasis * const pdfb);
+ inline void ReturnToReserve(CDFBasis * const pdfb);
+
+ inline static SCODE Reserve(UINT cItems, CDFBasis * const pdfb);
+ inline static void Unreserve(UINT cItems, CDFBasis * const pdfb);
+
+#ifndef REF
+ inline CDocFile(DFLUID luid, CDFBasis *pdfb);
+#else
+ inline CDocFile(DFLUID luid, ILockBytes *pilbBase);
+#endif //!REF
+ inline CDocFile(CMStream *pms,
+ SID sid,
+ DFLUID dl,
+#ifndef REF
+ CDFBasis *pdfb);
+#else
+ ILockBytes *pilbBase);
+#endif //!REF
+ SCODE InitFromEntry(CStgHandle *pstghParent,
+ CDfName const *dfnName,
+ BOOL const fCreate);
+
+ inline ~CDocFile(void);
+
+ // PDocFile
+ virtual void AddRef(void);
+ inline void DecRef(void);
+ virtual void Release(void);
+
+ virtual SCODE DestroyEntry(CDfName const *dfnName,
+ BOOL fClean);
+ virtual SCODE RenameEntry(CDfName const *dfnName,
+ CDfName const *dfnNewName);
+
+ virtual SCODE GetClass(CLSID *pclsid);
+ virtual SCODE SetClass(REFCLSID clsid);
+ virtual SCODE GetStateBits(DWORD *pgrfStateBits);
+ virtual SCODE SetStateBits(DWORD grfStateBits, DWORD grfMask);
+
+ virtual SCODE CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ PDocFile **ppdfDocFile);
+
+ inline SCODE CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ DWORD const dwType,
+ PDocFile **ppdfDocFile)
+ { return CreateDocFile(pdfnName, df, luidSet, ppdfDocFile); }
+
+ virtual SCODE GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ PDocFile **ppdfDocFile);
+ inline SCODE GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DWORD const dwType,
+ PDocFile **ppdfDocFile)
+ { return GetDocFile(pdfnName, df, ppdfDocFile); }
+
+ inline void ReturnDocFile(CDocFile *pdf);
+
+ virtual SCODE CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ PSStream **ppsstStream);
+ inline SCODE CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ DWORD const dwType,
+ PSStream **ppsstStream)
+ { return CreateStream(pdfnName, df, luidSet, ppsstStream); }
+
+ virtual SCODE GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ PSStream **ppsstStream);
+
+ inline SCODE GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DWORD const dwType,
+ PSStream **ppsstStream)
+ { return GetStream(pdfnName, df, ppsstStream); }
+
+ inline void ReturnStream(CDirectStream *pstm);
+
+ virtual SCODE FindGreaterEntry(CDfName const *pdfnKey,
+ SIterBuffer *pib,
+ STATSTGW *pstat);
+ virtual SCODE StatEntry(CDfName const *pdfn,
+ SIterBuffer *pib,
+ STATSTGW *pstat);
+
+#ifndef REF
+ virtual SCODE BeginCommitFromChild(CUpdateList &ulChanged,
+ DWORD const dwFlags,
+ CWrappedDocFile *pdfChild);
+ virtual void EndCommitFromChild(DFLAGS const df,
+ CWrappedDocFile *pdfChild);
+#endif //!REF
+ virtual SCODE IsEntry(CDfName const *dfnName,
+ SEntryBuffer *peb);
+ virtual SCODE DeleteContents(void);
+
+ // PTimeEntry
+ virtual SCODE GetTime(WHICHTIME wt, TIME_T *ptm);
+ virtual SCODE SetTime(WHICHTIME wt, TIME_T tm);
+ virtual SCODE GetAllTimes(TIME_T *patm, TIME_T *pmtm, TIME_T *pctm);
+ virtual SCODE SetAllTimes(TIME_T atm, TIME_T mtm, TIME_T ctm);
+
+#ifndef REF
+ inline CDocFile *GetReservedDocfile(DFLUID luid);
+ inline CDirectStream *GetReservedStream(DFLUID luid);
+#endif //!REF
+
+ // New
+ SCODE ApplyChanges(CUpdateList &ulChanged);
+ SCODE CopyTo(CDocFile *pdfTo,
+ DWORD dwFlags,
+ SNBW snbExclude);
+#ifndef REF
+#ifdef INDINST
+ void Destroy(void);
+#endif
+#endif //!REF
+ inline CStgHandle *GetHandle(void);
+
+private:
+#ifndef REF
+ CUpdateList _ulChangedHolder;
+#endif //!REF
+ LONG _cReferences;
+ CStgHandle _stgh;
+#ifdef REF
+ //BUGBUG: Should this be BASED?
+ ILockBytes *_pilbBase;
+#endif //!REF
+ CBasedDFBasisPtr const _pdfb;
+};
+
+// Inline methods are in dffuncs.hxx
+
+#endif
diff --git a/private/ole32/stg/h/chinst.hxx b/private/ole32/stg/h/chinst.hxx
new file mode 100644
index 000000000..6120a0786
--- /dev/null
+++ b/private/ole32/stg/h/chinst.hxx
@@ -0,0 +1,92 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992
+//
+// File: chinst.hxx
+//
+// Contents: DocFile child object maintenance code header file
+//
+// Classes: CChildInstance
+// CChildInstanceList
+//
+// History: 19-Nov-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __CHINST_HXX__
+#define __CHINST_HXX__
+
+class PRevertable;
+SAFE_DFBASED_PTR(CBasedRevertablePtr, PRevertable);
+
+//+--------------------------------------------------------------
+//
+// Class: CChildInstanceList (cil)
+//
+// Purpose: Maintains a list of child instances
+//
+// Interface: See below
+//
+// History: 22-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+class CChildInstanceList
+{
+public:
+ inline CChildInstanceList(void);
+ inline ~CChildInstanceList(void);
+
+ void Add(PRevertable *prv);
+ PRevertable *FindByName(CDfName const *pdfn);
+ void DeleteByName(CDfName const *pdfn);
+ void RemoveRv(PRevertable *prv);
+ void Empty(void);
+
+ SCODE IsDenied(CDfName const *pdfn,
+ DFLAGS const dwDFlagsCheck,
+ DFLAGS const dwDFlagsAgainst);
+
+#ifdef NEWPROPS
+ SCODE FlushBufferedData(int recursionlevel);
+#endif
+
+private:
+ CBasedRevertablePtr _prvHead;
+};
+
+
+//+--------------------------------------------------------------
+//
+// Member: CChildInstanceList::CChildInstanceList, pubic
+//
+// Synopsis: ctor
+//
+// History: 22-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CChildInstanceList::CChildInstanceList(void)
+{
+ _prvHead = NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CChildInstanceList::~CChildInstanceList, public
+//
+// Synopsis: dtor
+//
+// History: 22-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CChildInstanceList::~CChildInstanceList(void)
+{
+ msfAssert(_prvHead == NULL);
+}
+
+#endif
+
+
diff --git a/private/ole32/stg/h/cntxlist.hxx b/private/ole32/stg/h/cntxlist.hxx
new file mode 100644
index 000000000..f3fdd151d
--- /dev/null
+++ b/private/ole32/stg/h/cntxlist.hxx
@@ -0,0 +1,181 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: cntxlist.hxx
+//
+// Contents: CContextList header
+//
+// Classes: CContext
+// CContextList
+//
+// History: 26-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __CNTXLIST_HXX__
+#define __CNTXLIST_HXX__
+
+#include <ole.hxx>
+#include <cntxtid.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: CContext (ctx)
+//
+// Purpose: Holds a context's data
+//
+// Interface: See below
+//
+// History: 26-Oct-92 DrewB Created
+// 18-May-93 AlexT Added CMallocBased
+//
+//----------------------------------------------------------------------------
+
+class CContext; // forward declaration for SAFE macro
+SAFE_DFBASED_PTR(CBasedContextPtr, CContext);
+class CContext : public CMallocBased
+{
+public:
+ ContextId ctxid;
+ CBasedContextPtr pctxNext;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Class: CContextList (cl)
+//
+// Purpose: Maintains a list of objects that are context-sensitive
+//
+// Interface: See below
+//
+// History: 26-Oct-92 DrewB Created
+// 18-May-93 AlexT Added CMallocBased
+//
+//----------------------------------------------------------------------------
+
+class CContextList : public CMallocBased
+{
+protected:
+ inline CContextList(void);
+ inline ~CContextList(void);
+
+public:
+ inline LONG GetRefCount(void) const;
+ inline void AddRef(void);
+ inline void Release(void);
+
+ inline CContext *_GetHead(void) const;
+ CContext *_Find(ContextId ctxid);
+ void Add(CContext *pctx);
+ void Remove(CContext *pctx);
+
+private:
+ CBasedContextPtr _pctxHead;
+ LONG _cReferences;
+};
+
+// Macro to define methods for a derived class
+#define DECLARE_CONTEXT_LIST(type) \
+ inline type *Find(ContextId cid) { return (type *)_Find(cid); }\
+ inline type *GetHead(void) const { return (type *)_GetHead(); }\
+
+//+---------------------------------------------------------------------------
+//
+// Member: CContextList::CContextList, public
+//
+// Synopsis: Constructor
+//
+// History: 27-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline CContextList::CContextList(void)
+{
+ _pctxHead = NULL;
+ _cReferences = 1;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CContextList::~CContextList, public
+//
+// Synopsis: Destructor
+//
+// History: 27-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline CContextList::~CContextList(void)
+{
+ olAssert(_pctxHead == NULL);
+ olAssert(_cReferences == 0);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CContextList::GetRefCount, public
+//
+// Synopsis: Returns the current reference count
+//
+// History: 27-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline LONG CContextList::GetRefCount(void) const
+{
+ return _cReferences;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CContextList::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// History: 27-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CContextList::AddRef(void)
+{
+ AtomicInc(&_cReferences);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CContextList::Release, public
+//
+// Synopsis: Decrements the ref count
+//
+// History: 27-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CContextList::Release(void)
+{
+ LONG lRet;
+
+ olAssert(_cReferences > 0);
+ lRet = AtomicDec(&_cReferences);
+ if (lRet == 0)
+ delete this;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CContextList::_GetHead, public
+//
+// Synopsis: Returns the head of the list
+//
+// History: 26-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline CContext *CContextList::_GetHead(void) const
+{
+ return (CContext *)_pctxHead;
+}
+
+#endif // #ifndef __CNTXLIST_HXX__
diff --git a/private/ole32/stg/h/cntxtid.hxx b/private/ole32/stg/h/cntxtid.hxx
new file mode 100644
index 000000000..ce4d13b1b
--- /dev/null
+++ b/private/ole32/stg/h/cntxtid.hxx
@@ -0,0 +1,28 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: cntxtid.hxx
+//
+// Contents: Context ID header file
+//
+// History: 04-Sep-92 DrewB Created
+//
+// Notes: A context ID encapsulates the concept of a
+// unique ID for the currently executing context.
+// Every OS should define an appropriate section.
+//
+//---------------------------------------------------------------
+
+#ifndef __CNTXTID_HXX__
+#define __CNTXTID_HXX__
+
+#define INVALID_CONTEXT_ID 0
+typedef unsigned long ContextId;
+inline ContextId GetCurrentContextId(void)
+{
+ return GetCurrentProcessId();
+}
+
+#endif // #ifndef __CNTXTID_HXX__
diff --git a/private/ole32/stg/h/context.hxx b/private/ole32/stg/h/context.hxx
new file mode 100644
index 000000000..238653f87
--- /dev/null
+++ b/private/ole32/stg/h/context.hxx
@@ -0,0 +1,953 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: context.hxx
+//
+// Contents: Per-context things header
+//
+// Classes: CPerContext
+//
+// History: 14-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __CONTEXT_HXX__
+#define __CONTEXT_HXX__
+
+#include <filest.hxx>
+#include <cntxlist.hxx>
+#if WIN32 >= 100
+#include <entry.hxx>
+#include <df32.hxx>
+#endif
+
+#ifdef MULTIHEAP
+#include <smalloc.hxx>
+extern SCODE DfSyncSharedMemory(ULONG ulHeapName);
+#else
+extern SCODE DfSyncSharedMemory(void);
+#endif
+
+interface ILockBytes;
+
+// Maximum length of a mutex name for contexts
+#define CONTEXT_MUTEX_NAME_LENGTH 32
+
+
+//+--------------------------------------------------------------
+//
+// Class: CPerContext (pc)
+//
+// Purpose: Holds per-context information
+//
+// Interface: See below
+//
+// History: 14-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+class CGlobalContext;
+SAFE_DFBASED_PTR(CBasedGlobalContextPtr, CGlobalContext);
+
+class CPerContext : public CContext
+{
+public:
+ inline CPerContext(
+ IMalloc *pMalloc,
+ ILockBytes *plkbBase,
+ CFileStream *pfstDirty,
+ ILockBytes *plkbOriginal,
+ ULONG ulOpenLock);
+ inline CPerContext(IMalloc *pMalloc);
+
+ inline SCODE InitNewContext(BOOL fTakeLock,
+ DFLAGS dfOpenLock);
+ inline void SetILBInfo(ILockBytes *plkbBase,
+ CFileStream *pfstDirty,
+ ILockBytes *plkbOriginal,
+ ULONG ulOpenLock);
+ inline void SetLockInfo(BOOL fTakeLock, DFLAGS dfOpenLock);
+
+ inline SCODE InitNewContext(void);
+
+ inline SCODE InitFromGlobal(CGlobalContext *pgc);
+ ~CPerContext(void);
+
+ inline void AddRef(void);
+ inline void Release(void);
+#ifdef ASYNC
+ inline void AddRefSharedMem(void);
+ inline void ReleaseSharedMem(void);
+ inline void DecRef(void);
+#endif
+
+ inline ILockBytes *GetBase(void) const;
+ inline CFileStream *GetDirty(void) const;
+ inline ILockBytes *GetOriginal(void) const;
+ inline ULONG GetOpenLock(void) const;
+ inline ContextId GetContextId(void) const;
+ inline CGlobalContext *GetGlobal(void) const;
+ inline IMalloc * GetMalloc(void) const;
+
+ inline void SetOpenLock(ULONG ulOpenLock);
+
+ inline SCODE TakeSem(DWORD dwTimeout);
+ inline void ReleaseSem(void);
+#ifdef MULTIHEAP
+ inline SCODE SetAllocatorState(CPerContext **pppcPrev, CSmAllocator *psma);
+ inline SCODE GetThreadAllocatorState();
+ inline CSmAllocator *SetThreadAllocatorState(CPerContext **pppcPrev);
+ inline void UntakeSem() { ReleaseSem(); }; // workaround macro in docfilep
+#ifdef ASYNC
+ inline BOOL LastRef()
+ {
+ return (_cRefSharedMem == 1);
+ }; // within a TakeSem
+#else
+ inline BOOL LastRef() { return (_cReferences == 1); }; // within a TakeSem
+#endif //ASYNC
+#endif
+
+#ifdef ASYNC
+ inline IFillInfo * GetFillInfo(void) const;
+ inline HANDLE GetNotificationEvent(void) const;
+ SCODE InitNotificationEvent(void);
+#if DBG == 1
+ inline BOOL HaveMutex(void);
+#endif
+#endif
+
+ void Close(void);
+
+private:
+ ILockBytes *_plkbBase;
+ CFileStream *_pfstDirty;
+ ILockBytes *_plkbOriginal;
+ ULONG _ulOpenLock;
+ CBasedGlobalContextPtr _pgc;
+ LONG _cReferences;
+#ifdef ASYNC
+ LONG _cRefSharedMem;
+#endif
+ IMalloc * const _pMalloc;
+#ifdef ASYNC
+ IFillInfo *_pfi;
+ HANDLE _hNotificationEvent;
+#endif
+
+#ifdef MULTIHEAP
+ CSharedMemoryBlock *_psmb; // heap object
+ BYTE * _pbBase; // base address of heap
+ ULONG _ulHeapName; // name of shared mem region
+#endif
+
+#if WIN32 >= 100
+ CDfMutex _dmtx;
+#endif
+};
+
+SAFE_DFBASED_PTR(CBasedPerContextPtr, CPerContext);
+
+//+---------------------------------------------------------------------------
+//
+// Class: CGlobalContext
+//
+// Purpose: Holds context-insensitive information
+//
+// Interface: See below
+//
+// History: 26-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CGlobalContext : public CContextList
+{
+public:
+ inline CGlobalContext(IMalloc *pMalloc,
+ BOOL fTakeLock,
+ DFLAGS dfOpenLock);
+ inline CGlobalContext(IMalloc *pMalloc);
+
+ inline void SetLockInfo(BOOL fTakeLock,
+ DFLAGS dfOpenLock);
+
+ DECLARE_CONTEXT_LIST(CPerContext);
+
+ inline BOOL TakeLock(void) const;
+ inline DFLAGS GetOpenLockFlags(void) const;
+ inline IMalloc *GetMalloc(void) const;
+#if WIN32 >= 100
+ inline void GetMutexName(TCHAR *ptcsName);
+#ifdef ASYNC
+ inline void GetEventName(TCHAR *ptcsName);
+#endif
+#endif
+
+private:
+ BOOL _fTakeLock;
+ DFLAGS _dfOpenLock;
+ IMalloc * const _pMalloc;
+#if WIN32 >= 100
+ DFLUID _luidMutexName;
+#endif
+};
+
+
+inline CGlobalContext::CGlobalContext(IMalloc *pMalloc)
+ : _pMalloc(pMalloc)
+{
+#if WIN32 >= 100
+ // Use a luid as the name for the mutex because the 32-bit
+ // luid generator is guaranteed to produce machine-wide unique
+ // values each time it is called, so if we use one for our mutex
+ // name we know it won't collide with any others
+ // BUGBUG - What about when luids wrap around? Will this be a problem?
+#if !defined(MULTIHEAP)
+ _luidMutexName = PBasicEntry::GetNewLuid(pMalloc);
+#else
+ _luidMutexName = g_smAllocator.GetHeapName();
+#endif
+#endif
+}
+
+inline void CGlobalContext::SetLockInfo(BOOL fTakeLock, DFLAGS dfOpenLock)
+{
+ _fTakeLock = fTakeLock;
+ _dfOpenLock = dfOpenLock;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CGlobalContext::CGlobalContext, public
+//
+// Synopsis: Constructor
+//
+// History: 27-Oct-92 DrewB Created
+// 18-May-93 AlexT Added pMalloc
+//
+//----------------------------------------------------------------------------
+
+inline CGlobalContext::CGlobalContext(IMalloc *pMalloc,
+ BOOL fTakeLock,
+ DFLAGS dfOpenLock)
+: _pMalloc(pMalloc)
+{
+ _fTakeLock = fTakeLock;
+ _dfOpenLock = dfOpenLock;
+
+#if WIN32 >= 100
+ // Use a luid as the name for the mutex because the 32-bit
+ // luid generator is guaranteed to produce machine-wide unique
+ // values each time it is called, so if we use one for our mutex
+ // name we know it won't collide with any others
+ // BUGBUG - What about when luids wrap around? Will this be a problem?
+#if !defined(MULTIHEAP)
+ _luidMutexName = PBasicEntry::GetNewLuid(pMalloc);
+#else
+ _luidMutexName = g_smAllocator.GetHeapName();
+#endif
+#endif
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CGlobalContext::TakeLock, public
+//
+// Synopsis: Returns whether locks should be taken or not
+//
+// History: 04-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline BOOL CGlobalContext::TakeLock(void) const
+{
+ return _fTakeLock;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CGlobalContext::GetOpenLockFlags, public
+//
+// Synopsis: Returns the open lock flags
+//
+// History: 04-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline DFLAGS CGlobalContext::GetOpenLockFlags(void) const
+{
+ return _dfOpenLock;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CGlobalContext::GetMalloc, public
+//
+// Synopsis: Returns the allocator associated with this global context
+//
+// History: 05-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline IMalloc *CGlobalContext::GetMalloc(void) const
+{
+ return (IMalloc *)_pMalloc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CGlobalContext::GetMutexName, public
+//
+// Synopsis: Returns the name to use for the mutex for this tree
+//
+// Arguments: [ptcsName] - Name return
+//
+// Modifies: [ptcsName]
+//
+// History: 09-Oct-93 DrewB Created
+//
+// Notes: [ptcsName] should have space for at least
+// CONTEXT_MUTEX_NAME_LENGTH characters
+//
+//----------------------------------------------------------------------------
+
+#if WIN32 >= 100
+inline void CGlobalContext::GetMutexName(TCHAR *ptcsName)
+{
+ wsprintfT(ptcsName, TSTR("OleDfRoot%08lX"), _luidMutexName);
+}
+
+#ifdef ASYNC
+inline void CGlobalContext::GetEventName(TCHAR *ptcsName)
+{
+ wsprintfT(ptcsName, TSTR("OleAsyncE%08lX"), _luidMutexName);
+}
+#endif // ASYNC
+#endif
+
+
+inline void CPerContext::SetILBInfo(ILockBytes *plkbBase,
+ CFileStream *pfstDirty,
+ ILockBytes *plkbOriginal,
+ ULONG ulOpenLock)
+{
+ _plkbBase = plkbBase;
+ _pfstDirty = pfstDirty;
+ _plkbOriginal = plkbOriginal;
+ _ulOpenLock = ulOpenLock;
+
+#ifdef ASYNC
+ _pfi = NULL;
+ if (_plkbBase)
+ {
+ IFillInfo *pfi;
+ HRESULT hr = _plkbBase->QueryInterface(IID_IFillInfo,
+ (void **)&pfi);
+ if (SUCCEEDED(hr))
+ {
+ if (SUCCEEDED(InitNotificationEvent()))
+ {
+ _pfi = pfi;
+ }
+ else
+ {
+ pfi->Release();
+ }
+ }
+ }
+#endif
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CPerContext::CPerContext, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [plkbBase] - Base lstream
+// [pfstDirty] - Dirty lstream
+// [plkbOriginal] - Original base lstream for
+// independent copies
+// [ulOpenLock] - Open lock for base lstream
+//
+// History: 14-Aug-92 DrewB Created
+// 18-May-93 AlexT Added pMalloc
+//
+//---------------------------------------------------------------
+
+inline CPerContext::CPerContext(
+ IMalloc *pMalloc,
+ ILockBytes *plkbBase,
+ CFileStream *pfstDirty,
+ ILockBytes *plkbOriginal,
+ ULONG ulOpenLock)
+ : _pMalloc(pMalloc)
+{
+ _plkbBase = plkbBase;
+ _pfstDirty = pfstDirty;
+ _plkbOriginal = plkbOriginal;
+ _ulOpenLock = ulOpenLock;
+ _cReferences = 1;
+#ifdef ASYNC
+ _cRefSharedMem = 1;
+#endif
+ _pgc = NULL;
+#ifdef MULTIHEAP
+ g_smAllocator.GetState(&_psmb, &_pbBase, &_ulHeapName);
+#endif
+
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPerContext::CPerContext, public
+//
+// Synopsis: Constructor for a temporary stack-based object
+// This is only used for unmarshaling, since we
+// need a percontext to own the heap before the
+// actual percontext is unmarshaled
+//
+// Arguments: [pMalloc] - Base IMalloc
+//
+// History: 29-Nov-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+inline CPerContext::CPerContext(IMalloc *pMalloc) : _pMalloc(pMalloc)
+{
+#ifdef MULTIHEAP
+ g_smAllocator.GetState(&_psmb, &_pbBase, &_ulHeapName);
+#endif
+ _plkbBase = _plkbOriginal = NULL;
+ _pfstDirty = NULL;
+ _ulOpenLock = 0;
+ _cReferences = 1;
+#ifdef ASYNC
+ _cRefSharedMem = 1;
+#endif
+ _pgc = NULL;
+#ifdef ASYNC
+ _pfi = NULL;
+ _hNotificationEvent = INVALID_HANDLE_VALUE;
+#endif
+}
+
+
+#ifdef ASYNC
+inline void CPerContext::AddRefSharedMem(void)
+{
+ olAssert(_cRefSharedMem >= _cReferences);
+ AtomicInc(&_cRefSharedMem);
+ olAssert(_cRefSharedMem >= _cReferences);
+}
+
+inline void CPerContext::ReleaseSharedMem(void)
+{
+ LONG lRet;
+
+ olAssert(_cRefSharedMem > 0);
+ olAssert(_cRefSharedMem >= _cReferences);
+ lRet = AtomicDec(&_cRefSharedMem);
+
+ if ((_cReferences == 0) && (_cRefSharedMem == 0))
+ delete this;
+ else
+ {
+ _dmtx.Release();
+ }
+}
+
+inline void CPerContext::DecRef(void)
+{
+ olAssert(_cRefSharedMem >= _cReferences);
+ AtomicDec(&_cReferences);
+ olAssert(_cRefSharedMem >= _cReferences);
+}
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPerContext::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// History: 27-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CPerContext::AddRef(void)
+{
+#ifdef ASYNC
+ olAssert(_cRefSharedMem >= _cReferences);
+ AddRefSharedMem();
+#endif
+ AtomicInc(&_cReferences);
+#ifdef ASYNC
+ olAssert(_cRefSharedMem >= _cReferences);
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPerContext::Release, public
+//
+// Synopsis: Decrements the ref count
+//
+// History: 27-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CPerContext::Release(void)
+{
+ LONG lRet;
+
+ olAssert(_cReferences > 0);
+#ifdef ASYNC
+ olAssert(_cRefSharedMem >= _cReferences);
+#endif
+ lRet = AtomicDec(&_cReferences);
+ if (lRet == 0)
+ {
+#ifdef ASYNC
+ if (_plkbBase != NULL)
+ {
+ Close();
+ }
+#else
+ delete this;
+ }
+ else
+ {
+ _dmtx.Release();
+#endif
+ }
+#ifdef ASYNC
+ olAssert(_cRefSharedMem >= _cReferences);
+ //Note: If the object is going to get deleted, it will happen
+ // in the ReleaseSharedMem call.
+ ReleaseSharedMem();
+#endif
+}
+
+
+
+//+--------------------------------------------------------------
+//
+// Member: CPerContext::GetBase, public
+//
+// Synopsis: Returns the base
+//
+// History: 14-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline ILockBytes *CPerContext::GetBase(void) const
+{
+ return _plkbBase;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPerContext::GetDirty, public
+//
+// Synopsis: Returns the dirty
+//
+// History: 14-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+inline CFileStream *CPerContext::GetDirty(void) const
+{
+ return _pfstDirty;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPerContext::GetOriginal, public
+//
+// Synopsis: Returns the Original
+//
+// History: 14-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline ILockBytes *CPerContext::GetOriginal(void) const
+{
+ return _plkbOriginal;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPerContext::GetOpenLock, public
+//
+// Synopsis: Returns the open lock index
+//
+// History: 04-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline ULONG CPerContext::GetOpenLock(void) const
+{
+ return _ulOpenLock;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPerContext::GetContextId, public
+//
+// Synopsis: Returns the context id
+//
+// History: 04-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline ContextId CPerContext::GetContextId(void) const
+{
+ return ctxid;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPerContext::GetMalloc, public
+//
+// Synopsis: Returns the IMalloc pointer
+//
+// History: 04-Apr-96 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+inline IMalloc * CPerContext::GetMalloc(void) const
+{
+ return _pMalloc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPerContext::GetGlobal, public
+//
+// Synopsis: Returns the global context
+//
+// History: 04-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CGlobalContext *CPerContext::GetGlobal(void) const
+{
+ return BP_TO_P(CGlobalContext *, _pgc);
+}
+
+
+inline void CPerContext::SetLockInfo(BOOL fTakeLock,
+ DFLAGS dfOpenLock)
+{
+ _pgc->SetLockInfo(fTakeLock, dfOpenLock);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPerContext::InitNewContext, public
+//
+// Synopsis: Creates a new context and context list
+//
+// Returns: Appropriate status code
+//
+// History: 27-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+
+inline SCODE CPerContext::InitNewContext(BOOL fTakeLock,
+ DFLAGS dfOpenLock)
+{
+ SCODE sc;
+
+ CGlobalContext *pgcTemp;
+
+ sc = (pgcTemp = new (_pMalloc)
+ CGlobalContext(_pMalloc, fTakeLock, dfOpenLock)) == NULL ?
+ STG_E_INSUFFICIENTMEMORY : S_OK;
+ if (SUCCEEDED(sc))
+ {
+ _pgc = P_TO_BP(CBasedGlobalContextPtr, pgcTemp);
+#if WIN32 >= 100
+ TCHAR atcMutexName[CONTEXT_MUTEX_NAME_LENGTH];
+
+ _pgc->GetMutexName(atcMutexName);
+ sc = _dmtx.Init(atcMutexName);
+ if (FAILED(sc))
+ {
+ _pgc->Release();
+ _pgc = NULL;
+ }
+ else
+#endif
+ _pgc->Add(this);
+ }
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPerContext::InitNewContext, public
+//
+// Synopsis: Creates a new context and context list
+//
+// Returns: Appropriate status code
+//
+// History: 27-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+
+inline SCODE CPerContext::InitNewContext(void)
+{
+ SCODE sc;
+ CGlobalContext *pgcTemp;
+
+ sc = (pgcTemp = new (_pMalloc) CGlobalContext(_pMalloc)) == NULL ?
+ STG_E_INSUFFICIENTMEMORY : S_OK;
+ if (SUCCEEDED(sc))
+ {
+ _pgc = P_TO_BP(CBasedGlobalContextPtr, pgcTemp);
+#if WIN32 >= 100
+ TCHAR atcMutexName[CONTEXT_MUTEX_NAME_LENGTH];
+
+ _pgc->GetMutexName(atcMutexName);
+ sc = _dmtx.Init(atcMutexName);
+ if (FAILED(sc))
+ {
+ _pgc->Release();
+ _pgc = NULL;
+ }
+ else
+#endif
+ _pgc->Add(this);
+ }
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPerContext::InitFromGlobal, public
+//
+// Synopsis: Adds a context to the context list
+//
+// Returns: Appropriate status code
+//
+// History: 27-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CPerContext::InitFromGlobal(CGlobalContext *pgc)
+{
+ SCODE sc;
+
+ sc = S_OK;
+#if WIN32 >= 100
+ TCHAR atcMutexName[CONTEXT_MUTEX_NAME_LENGTH];
+
+ pgc->GetMutexName(atcMutexName);
+ sc = _dmtx.Init(atcMutexName);
+#endif
+ if (SUCCEEDED(sc))
+ {
+ _pgc = P_TO_BP(CBasedGlobalContextPtr, pgc);
+ _pgc->AddRef();
+ _pgc->Add(this);
+ }
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPerContext::SetOpenLock, public
+//
+// Synopsis: Sets the open lock
+//
+// History: 13-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CPerContext::SetOpenLock(ULONG ulOpenLock)
+{
+ _ulOpenLock = ulOpenLock;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPerContext::TakeSem, public
+//
+// Synopsis: Takes the mutex
+//
+// Arguments: [dwTimeout] - Timeout
+//
+// Returns: Appropriate status code
+//
+// History: 09-Oct-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CPerContext::TakeSem(DWORD dwTimeout)
+{
+#if WIN32 >= 100
+ SCODE sc;
+
+ olChk(_dmtx.Take(dwTimeout));
+
+#ifdef ONETHREAD
+ olChkTo(EH_Tree, s_dmtxProcess.Take(dwTimeout));
+#endif
+
+#ifdef MULTIHEAP
+ if (!_psmb->IsSynced())
+ {
+ olChkTo(EH_Process, _psmb->Sync());
+ }
+#else
+ olChkTo(EH_Process, DfSyncSharedMemory());
+#endif
+
+ EH_Err:
+ return sc;
+ EH_Process:
+#ifdef ONETHREAD
+ s_dmtxProcess.Release();
+ EH_Tree:
+#endif
+ _dmtx.Release();
+ return sc;
+#else
+ return S_OK;
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPerContext::ReleaseSem, public
+//
+// Synopsis: Releases the mutex
+//
+// History: 09-Oct-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CPerContext::ReleaseSem(void)
+{
+#if WIN32 >= 100
+#ifdef ONETHREAD
+ s_dmtxProcess.Release();
+#endif
+ _dmtx.Release();
+#endif
+}
+
+#ifdef MULTIHEAP
+//+-------------------------------------------------------------------------
+//
+// Member: CPerContext::SetThreadAllocatorState, public
+//
+// Synopsis: set current thread's allocator to be this percontext
+//
+// History: 29-Nov-95 HenryLee Created
+//
+//--------------------------------------------------------------------------
+inline CSmAllocator *CPerContext::SetThreadAllocatorState(CPerContext**pppcPrev)
+{
+ CSmAllocator *pSmAllocator = &g_smAllocator;
+ pSmAllocator->SetState(_psmb, _pbBase, _ulHeapName, pppcPrev, this);
+ return pSmAllocator;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPerContext::SetAllocatorState, public
+//
+// Synopsis: sets owner of shared memory heap to this percontext
+// remembers the previous context owner
+//
+// History: 29-Nov-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+inline SCODE CPerContext::SetAllocatorState (CPerContext **pppcPrev,
+ CSmAllocator *pSmAllocator)
+{
+ pSmAllocator->SetState(_psmb, _pbBase, _ulHeapName, pppcPrev, this);
+ return S_OK;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CPerContext::GetThreadAllocatorState, public
+//
+// Synopsis: retrives the current thread's allocator state
+//
+// Arguments: none
+//
+// History: 29-Nov-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CPerContext::GetThreadAllocatorState()
+{
+ g_smAllocator.GetState(&_psmb, &_pbBase, &_ulHeapName);
+ return S_OK;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Class: CSafeMultiHeap
+//
+// Purpose: 1) sets and restores allocator state for those
+// methods that do not take the tree mutex
+// 2) for self-destructive methods like IStorage::Release,
+// IStream::Release, IEnumSTATSTG::Release, the
+// previous percontext may get deleted along with
+// whole heap, and it checks for that
+//
+// Interface: See below
+//
+// History: 29-Nov-95 HenryLee Created
+//
+//---------------------------------------------------------------
+class CSafeMultiHeap
+{
+public:
+ CSafeMultiHeap(CPerContext *ppc);
+ ~CSafeMultiHeap();
+
+private:
+ CSmAllocator *_pSmAllocator;
+ CPerContext *_ppcPrev;
+};
+
+#endif // MULTIHEAP
+
+#ifdef ASYNC
+inline IFillInfo * CPerContext::GetFillInfo(void) const
+{
+ return _pfi;
+}
+
+inline HANDLE CPerContext::GetNotificationEvent(void) const
+{
+ return _hNotificationEvent;
+}
+#if DBG == 1
+inline BOOL CPerContext::HaveMutex(void)
+{
+ return _dmtx.HaveMutex();
+}
+
+#endif // #if DBG == 1
+#endif // #ifdef ASYNC
+
+#endif // #ifndef __CONTEXT_HXX__
diff --git a/private/ole32/stg/h/dblink.hxx b/private/ole32/stg/h/dblink.hxx
new file mode 100644
index 000000000..c1118504b
--- /dev/null
+++ b/private/ole32/stg/h/dblink.hxx
@@ -0,0 +1,126 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dblink.hxx
+//
+// Contents: Doubly-linked list element
+//
+// Classes: CDlElement
+//
+// History: 28-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __DBLINK_HXX__
+#define __DBLINK_HXX__
+
+class CDlElement;
+SAFE_DFBASED_PTR(CBasedDlElementPtr, CDlElement);
+//+--------------------------------------------------------------
+//
+// Class: CDlElement (dle)
+//
+// Purpose: An element of a doubly-linked list
+//
+// Interface: See below
+//
+// History: 28-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+class CDlElement
+{
+public:
+ inline CDlElement(void);
+
+ inline CDlElement *_GetNext(void) const;
+ inline void SetNext(CDlElement *pdle);
+ inline CDlElement *_GetPrev(void) const;
+ inline void SetPrev(CDlElement *pdle);
+
+protected:
+ CBasedDlElementPtr _pdlePrev, _pdleNext;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CDlElement::CDlElement, public
+//
+// Synopsis: Ctor
+//
+// History: 28-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CDlElement::CDlElement(void)
+{
+ _pdlePrev = _pdleNext = NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDlElement::_GetNext, public
+//
+// Synopsis: Returns _pdleNext
+//
+// History: 28-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CDlElement *CDlElement::_GetNext(void) const
+{
+ return BP_TO_P(CDlElement *, _pdleNext);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDlElement::_SetNext, public
+//
+// Synopsis: Sets _pdleNext
+//
+// History: 28-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CDlElement::SetNext(CDlElement *pdle)
+{
+ _pdleNext = P_TO_BP(CBasedDlElementPtr, pdle);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDlElement::_GetPrev, public
+//
+// Synopsis: Returns _pdlePrev
+//
+// History: 28-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CDlElement *CDlElement::_GetPrev(void) const
+{
+ return BP_TO_P(CDlElement *, _pdlePrev);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDlElement::_SetPrev, public
+//
+// Synopsis: Sets _pdlePrev
+//
+// History: 28-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CDlElement::SetPrev(CDlElement *pdle)
+{
+ _pdlePrev = P_TO_BP(CBasedDlElementPtr, pdle);
+}
+
+#define DECLARE_DBLINK(type) \
+ type *GetNext(void) const { return (type *)_GetNext(); } \
+ type *GetPrev(void) const { return (type *)_GetPrev(); } \
+
+#endif // #ifndef __DBLINK_HXX__
diff --git a/private/ole32/stg/h/debug.hxx b/private/ole32/stg/h/debug.hxx
new file mode 100644
index 000000000..13312f50b
--- /dev/null
+++ b/private/ole32/stg/h/debug.hxx
@@ -0,0 +1,44 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992
+//
+// File: debug.hxx
+//
+// Contents: Debugging routines
+//
+// History: 07-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __DEBUG_HXX__
+#define __DEBUG_HXX__
+
+#define DBG_NORM 1
+#define DBG_CRIT 2
+#define DBG_SLOW 4
+#define DBG_FAST (DBG_NORM | DBG_CRIT)
+#define DBG_ALL (DBG_NORM | DBG_CRIT | DBG_SLOW)
+#define DBG_VERBOSE 128
+
+void DbgChkBlocks(DWORD dwFlags, char *pszFile, int iLine);
+void DbgAddChkBlock(char *pszName,
+ void *pvAddr,
+ ULONG cBytes,
+ DWORD dwFlags);
+void DbgFreeChkBlock(void *pvAddr);
+void DbgFreeChkBlocks(void);
+
+#if DBG == 1
+#define olChkBlocks(a) DbgChkBlocks(a, __FILE__, __LINE__)
+#define olAddChkBlock(a) DbgAddChkBlock a
+#define olFreeChkBlock(a) DbgFreeChkBlock a
+#define olFreeChkBlocks(a) DbgFreeChkBlocks a
+#else
+#define olChkBlocks(a)
+#define olAddChkBlock(a)
+#define olFreeChkBlock(a)
+#define olRemChkBlock(a)
+#endif
+
+#endif
diff --git a/private/ole32/stg/h/df32.hxx b/private/ole32/stg/h/df32.hxx
new file mode 100644
index 000000000..d3dce6413
--- /dev/null
+++ b/private/ole32/stg/h/df32.hxx
@@ -0,0 +1,268 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: df32.hxx
+//
+// Contents: Docfile generic header for 32-bit functions
+//
+// Classes: CGlobalSecurity
+// CDfMutex
+//
+// History: 09-Oct-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DF32_HXX__
+#define __DF32_HXX__
+
+#ifdef WIN32
+
+#include <dfexcept.hxx>
+
+// Make an scode out of the last Win32 error
+// Error that may map to STG_* scodes should go through Win32ErrorToScode
+#define WIN32_SCODE(err) HRESULT_FROM_WIN32(err)
+#define LAST_SCODE WIN32_SCODE(GetLastError())
+#define LAST_STG_SCODE Win32ErrorToScode(GetLastError())
+
+#if WIN32 == 100
+
+// BUGBUG - The following information is copied from ntimage.h and ntrtl.h
+// Including the files directly here would cause all sorts of build
+// problems
+
+// Official storage base address. Duplicated in coffbase.txt but there's
+// no easy way to share information between it and code
+extern "C" NTSYSAPI PIMAGE_NT_HEADERS NTAPI RtlImageNtHeader(PVOID Base);
+
+// Docfile dll name
+#define DF_DLL_NAME TSTR("ole32.dll")
+
+//+---------------------------------------------------------------------------
+//
+// Function: DfCheckBaseAddress, public
+//
+// Synopsis: Return an error if the docfile isn't at the right base address
+//
+// Returns: Appropriate status code
+//
+// History: 09-Oct-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE DfCheckBaseAddress(void)
+{
+ HMODULE hModule;
+ PIMAGE_NT_HEADERS pinh;
+
+ hModule = GetModuleHandle(DF_DLL_NAME);
+ pinh = RtlImageNtHeader(hModule);
+ if (hModule != (HMODULE)pinh->OptionalHeader.ImageBase)
+ return STG_E_BADBASEADDRESS;
+ else
+ return S_OK;
+}
+
+#endif // NT 1.x
+
+//+---------------------------------------------------------------------------
+//
+// Class: CGlobalSecurity (gs)
+//
+// Purpose: Encapsulates a global SECURITY_DESCRIPTOR and
+// SECURITY_ATTRIBUTES
+//
+// Interface: See below
+//
+// History: 18-Jun-93 DrewB Created
+//
+// Notes: Only active for Win32 platforms which support security
+// Init MUST be called before this is used
+//
+//----------------------------------------------------------------------------
+
+#if WIN32 == 100 || WIN32 > 200
+class CGlobalSecurity
+{
+private:
+ SECURITY_DESCRIPTOR _sd;
+ SECURITY_ATTRIBUTES _sa;
+#if DBG == 1
+ BOOL _fInit;
+#endif
+
+public:
+#if DBG == 1
+ CGlobalSecurity(void) { _fInit = FALSE; }
+#endif
+ SCODE Init(void)
+ {
+ if (!InitializeSecurityDescriptor(&_sd, SECURITY_DESCRIPTOR_REVISION))
+ return LAST_SCODE;
+
+ // Set up a world security descriptor by explicitly setting
+ // the dacl to NULL
+ if (!SetSecurityDescriptorDacl(&_sd, TRUE, NULL, FALSE))
+ return LAST_SCODE;
+
+ _sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ _sa.lpSecurityDescriptor = &_sd;
+ _sa.bInheritHandle = FALSE;
+#if DBG == 1
+ _fInit = TRUE;
+#endif
+ return S_OK;
+ }
+
+ operator SECURITY_DESCRIPTOR *(void) { olAssert(_fInit); return &_sd; }
+ operator SECURITY_ATTRIBUTES *(void) { olAssert(_fInit); return &_sa; }
+};
+#endif
+
+
+//
+// Global Critical Sections have two components. One piece is shared between
+// all applications using the global lock. This portion will typically reside
+// in some sort of shared memory. The second piece is per-process. This
+// contains a per-process handle to the shared critical section lock semaphore.
+// The semaphore is itself shared, but each process may have a different handle
+// value to the semaphore.
+//
+// Global critical sections are attached to by name. The application wishing to
+// attach must know the name of the critical section (actually the name of the
+// shared lock semaphore, and must know the address of the global portion of
+// the critical section
+//
+
+#define SUPPORT_RECURSIVE_LOCK
+
+typedef struct _GLOBAL_SHARED_CRITICAL_SECTION {
+ LONG LockCount;
+#ifdef SUPPORT_RECURSIVE_LOCK
+ LONG RecursionCount;
+ DWORD OwningThread;
+#else
+#if DBG == 1
+ DWORD OwningThread;
+#endif
+#endif
+ DWORD Reserved;
+} GLOBAL_SHARED_CRITICAL_SECTION, *PGLOBAL_SHARED_CRITICAL_SECTION;
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CDfMutex (dmtx)
+//
+// Purpose: A multi-process synchronization object
+//
+// Interface: See below
+//
+// History: 05-Apr-93 DrewB Created
+// 19-Jul-95 SusiA Added HaveMutex
+//
+// Notes: Only active for Win32 implementations which support threads
+// For platforms with security, a global security descriptor is
+// used
+//
+//----------------------------------------------------------------------------
+
+// Default timeout of ten minutes
+#define DFM_TIMEOUT 600000
+
+class CDfMutex
+{
+public:
+ inline CDfMutex(void);
+ SCODE Init(TCHAR *ptcsName);
+ ~CDfMutex(void);
+
+ SCODE Take(DWORD dwTimeout);
+ void Release(void);
+
+#if DBG == 1
+ //check to see if the current thread already has the mutex
+ inline BOOL HaveMutex(void);
+#endif
+private:
+ PGLOBAL_SHARED_CRITICAL_SECTION _pGlobalPortion;
+ HANDLE _hLockSemaphore;
+ HANDLE _hSharedMapping;
+};
+
+inline CDfMutex::CDfMutex(void)
+{
+ _pGlobalPortion = NULL;
+ _hLockSemaphore = NULL;
+ _hSharedMapping = NULL;
+}
+
+#if DBG == 1
+//+--------------------------------------------------------------
+//
+// Member: CDfMutex::HaveMutex, public
+//
+// Synopsis: This routine checks to see if the current thread
+// already has the mutex
+//
+// History: 19-Jul-95 SusiA Created
+//
+// Algorithm: Checks the current thread to see if it already owns
+// the mutex. Returns TRUE if it does, FALSE otherwise
+//
+//
+//---------------------------------------------------------------
+
+inline BOOL
+CDfMutex::HaveMutex(
+ void
+ )
+{
+ if ( _pGlobalPortion->OwningThread == GetCurrentThreadId())
+ return TRUE;
+ else
+ return FALSE;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Class: CStaticDfMutex (sdmtx)
+//
+// Purpose: Static version of CDfMutex
+//
+// Interface: CDfMutex
+//
+// History: 10-Oct-93 DrewB Created
+//
+// Notes: Throws exceptions on initialization failures
+//
+//----------------------------------------------------------------------------
+
+class CStaticDfMutex : public CDfMutex
+{
+public:
+ inline CStaticDfMutex(TCHAR *ptcsName);
+};
+
+inline CStaticDfMutex::CStaticDfMutex(TCHAR *ptcsName)
+ : CDfMutex()
+{
+ SCODE sc;
+
+ sc = Init(ptcsName);
+ if (FAILED(sc))
+ THROW_SC(sc);
+}
+
+#ifdef ONETHREAD
+//Mutex used to control access for based pointers.
+extern CStaticDfMutex s_dmtxProcess;
+#endif
+
+#endif // WIN32
+
+#endif // #ifndef __DF32_HXX__
diff --git a/private/ole32/stg/h/dfbasis.hxx b/private/ole32/stg/h/dfbasis.hxx
new file mode 100644
index 000000000..0368eec0f
--- /dev/null
+++ b/private/ole32/stg/h/dfbasis.hxx
@@ -0,0 +1,607 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992
+//
+// File: dfbasis.hxx
+//
+// Contents: DocFile basis block class
+//
+// Classes: CDFBasis
+//
+// History: 26-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __DFBASIS_HXX__
+#define __DFBASIS_HXX__
+
+#include <dfmsp.hxx>
+#include <msf.hxx>
+#include <context.hxx>
+#include <freelist.hxx>
+
+interface ILockBytes;
+class CPubDocFile;
+class CDocFile;
+SAFE_DFBASED_PTR(CBasedPubDocFilePtr, CPubDocFile);
+
+//+--------------------------------------------------------------
+//
+// Class: CDFBasis (dfb)
+//
+// Purpose: Defines base variables for sharing between exposed
+// DocFiles
+//
+// History: 26-Feb-92 DrewB Created
+// 18-May-93 AlexT Added CMallocBased
+//
+//---------------------------------------------------------------
+
+typedef enum
+{
+ CDFB_DIRECTDOCFILE = 0,
+ CDFB_DIRECTSTREAM = 1,
+ CDFB_WRAPPEDDOCFILE = 2,
+ CDFB_TRANSACTEDSTREAM = 3
+} CDFB_CLASSTYPE;
+
+#define CDFB_CLASSCOUNT 4
+
+class CDFBasis : public CMallocBased
+{
+public:
+ inline CDFBasis(IMalloc * const pMalloc, DFLAGS df, DWORD dwLockFlags);
+ inline ~CDFBasis(void);
+
+ void vRelease(void);
+ inline void vAddRef(void);
+
+ inline void SetAccess(CPerContext *ppc);
+ inline void ClearAccess(void);
+
+ inline ILockBytes **GetPBase(void);
+ inline ILockBytes *GetBase(void);
+ inline CFileStream **GetPDirty(void);
+ inline CFileStream *GetDirty(void);
+ inline ILockBytes *GetOriginal(void);
+ inline void SetBase(ILockBytes *plkb);
+ inline void SetDirty(CFileStream *pfst);
+ inline void SetOriginal(ILockBytes *plkb);
+ inline void SetContext(CPerContext *ppc);
+
+ inline DWORD GetOrigLockFlags(void);
+
+ inline ULONG GetNewTemp(void);
+ inline DFSIGNATURE GetNewSig(void);
+
+ inline CMStream *GetScratch(void);
+ inline void SetScratch(CMStream *pms);
+
+#ifdef USE_NOSCRATCH
+ inline CMStream *GetBaseMultiStream(void);
+ inline void SetBaseMultiStream(CMStream *pms);
+#endif
+
+ inline CPubDocFile *GetCopyBase(void);
+ inline void SetCopyBase(CPubDocFile *pdf);
+
+ inline CFreeList *GetFreeList(CDFB_CLASSTYPE classtype);
+ inline SCODE Reserve(UINT cItems, CDFB_CLASSTYPE classtype);
+ inline void CDFBasis::Unreserve(UINT cItems, CDFB_CLASSTYPE classtype);
+
+ inline DFLAGS GetOpenFlags(void);
+ inline IMalloc *GetMalloc(void);
+
+private:
+#ifdef USE_NOSCRATCH
+ CBasedMStreamPtr _pms;
+#endif
+ CBasedMStreamPtr _pmsScratch;
+ DFLAGS const _dfOpen;
+ ILockBytes *_plkbBase;
+ CFileStream *_pfstDirty;
+ ILockBytes *_plkbOriginal;
+ LONG _cReferences;
+ ULONG _cTemps;
+ DFSIGNATURE _cSigs;
+ CBasedPubDocFilePtr _pdfCopyBase;
+
+ DWORD _dwOrigLocks;
+
+ IMalloc * const _pMalloc;
+ CFreeList _afrl[CDFB_CLASSCOUNT];
+ static size_t _aReserveSize[CDFB_CLASSCOUNT];
+};
+SAFE_DFBASED_PTR(CBasedDFBasisPtr, CDFBasis);
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::CDFBasis, public
+//
+// Synopsis: Constructor
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDFBasis_CDFBasis)
+#endif
+
+inline CDFBasis::CDFBasis(IMalloc * const pMalloc, DFLAGS df,
+ DWORD dwLockFlags)
+: _pMalloc(pMalloc), _dfOpen(df)
+{
+ _cReferences = 1;
+ _cTemps = 0;
+ _cSigs = 0;
+ _pdfCopyBase = NULL;
+ _plkbBase = NULL;
+ _pfstDirty = NULL;
+ _plkbOriginal = NULL;
+ _dwOrigLocks = dwLockFlags;
+#ifdef USE_NOSCRATCH
+ _pms = NULL;
+#endif
+ _pmsScratch = NULL;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::~CDFBasis, public
+//
+// Synopsis: Destructor
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDFBasis_1CDFBasis)
+#endif
+
+inline CDFBasis::~CDFBasis(void)
+{
+ delete BP_TO_P(CMStream *, _pmsScratch);
+ msfAssert(_cReferences == 0);
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::AddRef, public
+//
+// Synopsis: Increase reference count
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CDFBasis::vAddRef(void)
+{
+ InterlockedIncrement(&_cReferences);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::SetAccess, public
+//
+// Synopsis: Takes semaphore and sets pointers
+//
+// Arguments: [ppc] - Context
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CDFBasis::SetAccess(CPerContext *ppc)
+{
+ SetContext(ppc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::ClearAccess, public
+//
+// Synopsis: Releases semaphore and resets pointers
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CDFBasis::ClearAccess(void)
+{
+#if DBG == 1
+ _plkbBase = NULL;
+ _pfstDirty = NULL;
+#endif
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::GetPBase, public
+//
+// Synopsis: Returns a pointer to _plstBase
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline ILockBytes **CDFBasis::GetPBase(void)
+{
+ return &_plkbBase;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::GetPDirty, public
+//
+// Synopsis: Returns a pointer to _plstDirty
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CFileStream **CDFBasis::GetPDirty(void)
+{
+ return &_pfstDirty;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::GetBase, public
+//
+// Synopsis: Returns _plstBase
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline ILockBytes *CDFBasis::GetBase(void)
+{
+ return _plkbBase;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::SetBase, public
+//
+// Synopsis: Sets the base
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CDFBasis::SetBase(ILockBytes *plkb)
+{
+ _plkbBase = plkb;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::GetDirty, public
+//
+// Synopsis: Returns _plstDirty
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CFileStream *CDFBasis::GetDirty(void)
+{
+ return _pfstDirty;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::SetDirty, public
+//
+// Synopsis: Sets the Dirty
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CDFBasis::SetDirty(CFileStream *pfst)
+{
+ _pfstDirty = pfst;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::GetOriginal, public
+//
+// Synopsis: Returns _plstOriginal
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline ILockBytes *CDFBasis::GetOriginal(void)
+{
+ return _plkbOriginal;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::SetOriginal, public
+//
+// Synopsis: Sets the Original
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CDFBasis::SetOriginal(ILockBytes *plkb)
+{
+ _plkbOriginal = plkb;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::SetContext, public
+//
+// Synopsis: Sets the context
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDFBasis_SetContext)
+#endif
+
+inline void CDFBasis::SetContext(CPerContext *ppc)
+{
+ _plkbBase = ppc->GetBase();
+ _pfstDirty = ppc->GetDirty();
+ _plkbOriginal = ppc->GetOriginal();
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::GetNewTemp, public
+//
+// Synopsis: Return _cTemps++
+//
+// History: 03-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline ULONG CDFBasis::GetNewTemp(void)
+{
+ return _cTemps++;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::GetNewSig, public
+//
+// Synopsis: Return _cSigs++
+//
+// History: 03-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline DFSIGNATURE CDFBasis::GetNewSig(void)
+{
+ return _cSigs++;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::GetCopyBase, public
+//
+// Synopsis: Returns _pdfCopyBase
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CPubDocFile *CDFBasis::GetCopyBase(void)
+{
+ return BP_TO_P(CPubDocFile *, _pdfCopyBase);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::SetCopyBase, public
+//
+// Synopsis: Sets _pdfCopyBase
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CDFBasis::SetCopyBase(CPubDocFile *pdf)
+{
+ _pdfCopyBase = P_TO_BP(CBasedPubDocFilePtr, pdf);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::GetScratch, public
+//
+// Synopsis: Returns handle to scratch multistream
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CMStream * CDFBasis::GetScratch(void)
+{
+ return BP_TO_P(CMStream *, _pmsScratch);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::SetScratch, public
+//
+// Synopsis: Sets scratch MS
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CDFBasis::SetScratch(CMStream *pms)
+{
+ _pmsScratch = P_TO_BP(CBasedMStreamPtr, pms);
+}
+
+#ifdef USE_NOSCRATCH
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::GetBaseMultiStream, public
+//
+// Synopsis: Returns pointer to base multistream
+//
+// History: 25-Feb-95 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+inline CMStream * CDFBasis::GetBaseMultiStream(void)
+{
+ return BP_TO_P(CMStream *, _pms);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::SetBaseMultiStream, public
+//
+// Synopsis: Sets base MS
+//
+// History: 25-Feb-95 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+inline void CDFBasis::SetBaseMultiStream(CMStream *pms)
+{
+ _pms = P_TO_BP(CBasedMStreamPtr, pms);
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CDFBasis::GetOrigLockFlags, public
+//
+// Synopsis: Returns the original's lock flags
+//
+// History: 11-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline DWORD CDFBasis::GetOrigLockFlags(void)
+{
+ return _dwOrigLocks;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDFBasis::GetOpenFlags
+//
+// Synopsis: Returns access/share flags
+//
+// History: 21-Dec-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+inline DFLAGS CDFBasis::GetOpenFlags(void)
+{
+ return(_dfOpen);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDFBasis::GetFreeList, public
+//
+// Synopsis: Gets the free list for the indicated reserved type
+//
+// History: 05-Nov-92 DrewB Created
+// 18-May-93 AlexT Switch to array
+//
+//----------------------------------------------------------------------------
+
+inline CFreeList *CDFBasis::GetFreeList(CDFB_CLASSTYPE classtype)
+{
+ msfAssert(classtype >= 0 && classtype <= CDFB_CLASSCOUNT);
+ return &_afrl[classtype];
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDFBasis::Reserve, public
+//
+// Synopsis: Reserve memory for instances
+//
+// Arguments: [cItems] -- count of items to reserve
+// [classtype] -- class of items to reserve
+//
+// History: 21-May-93 AlexT Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CDFBasis::Reserve(UINT cItems, CDFB_CLASSTYPE classtype)
+{
+ msfAssert(classtype >= 0 && classtype <= CDFB_CLASSCOUNT);
+ return _afrl[classtype].Reserve(_pMalloc,
+ cItems,
+ _aReserveSize[classtype]);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDFBasis::Unreserve, public
+//
+// Synopsis: Unreserve memory for instances
+//
+// Arguments: [cItems] -- count of items to unreserve
+// [classtype] -- class of items to unreserve
+//
+// History: 21-May-93 AlexT Created
+//
+//----------------------------------------------------------------------------
+
+inline void CDFBasis::Unreserve(UINT cItems, CDFB_CLASSTYPE classtype)
+{
+ msfAssert(classtype >= 0 && classtype <= CDFB_CLASSCOUNT);
+ _afrl[classtype].Unreserve(cItems);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDFBasis::GetMalloc, public
+//
+// Synopsis: Return allocator associated with basis
+//
+// History: 21-May-93 AlexT Created
+//
+//----------------------------------------------------------------------------
+
+inline IMalloc *CDFBasis::GetMalloc(void)
+{
+#ifdef MULTIHEAP
+ //We can't return the _pMalloc pointer here, since it's only valid
+ // in the creating process. What we really want to return in the
+ // pointer to the current allocator, which is always &g_smAllocator.
+ //return (IMalloc *)_pMalloc;
+ return (IMalloc *)&g_smAllocator;
+#else
+ return (IMalloc *)_pMalloc;
+#endif
+}
+
+#endif
diff --git a/private/ole32/stg/h/dfdeb.hxx b/private/ole32/stg/h/dfdeb.hxx
new file mode 100644
index 000000000..57b33ae94
--- /dev/null
+++ b/private/ole32/stg/h/dfdeb.hxx
@@ -0,0 +1,75 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dfdeb.hxx
+//
+// Contents: Docfile debug header
+//
+// Functions: DfDebug
+// DfSetResLimit
+// DfGetResLimit
+// DfPrintAllocs
+// HaveResource
+// ModifyResLimit
+//
+// History: 13-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __DFDEB_HXX__
+#define __DFDEB_HXX__
+
+#if DBG == 1
+
+// Resources that can be controlled
+#define DBR_MEMORY 0
+#define DBR_XSCOMMITS 1
+#define DBR_FAILCOUNT 2
+#define DBR_FAILLIMIT 3
+
+// Resources that can be queried
+#define DBRQ_MEMORY_ALLOCATED 4
+
+// Internal resources
+#define DBRI_ALLOC_LIST 5
+#define DBRI_LOGFILE_LIST 6
+
+// Control flags
+#define DBRF_LOGGING 7
+
+#define CDBRESOURCES 8
+
+// Simulated failure types
+typedef enum {
+ DBF_MEMORY,
+ DBF_DISKFULL,
+ DBF_DISKREAD,
+ DBF_DISKWRITE
+} DBFAILURE;
+
+// Logging control flags (e.g. DfSetResLimit(DBRF_LOGGING, DFLOG_MIN);)
+
+#define DFLOG_OFF 0x00000000
+
+#define DFLOG_ON 0x02000000
+#define DFLOG_PIDTID 0x04000000
+
+STDAPI_(void) DfDebug(ULONG ulLevel, ULONG ulMSFLevel);
+
+STDAPI_(void) DfSetResLimit(UINT iRes, LONG lLimit);
+STDAPI_(LONG) DfGetResLimit(UINT iRes);
+
+BOOL SimulateFailure(DBFAILURE failure);
+
+STDAPI_(LONG) DfGetMemAlloced(void);
+STDAPI_(void) DfPrintAllocs(void);
+
+// Internal APIs
+BOOL HaveResource(UINT iRes, LONG lRequest);
+LONG ModifyResLimit(UINT iRes, LONG lChange);
+
+#endif // DBG == 1
+
+#endif // #ifndef __DFDEB_HXX__
diff --git a/private/ole32/stg/h/dfentry.hxx b/private/ole32/stg/h/dfentry.hxx
new file mode 100644
index 000000000..7fe0fb463
--- /dev/null
+++ b/private/ole32/stg/h/dfentry.hxx
@@ -0,0 +1,95 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dfentry.hxx
+//
+// Contents: DocFile DLL entry points not in ole2.h
+//
+// History: 22-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __DFENTRY_HXX__
+#define __DFENTRY_HXX__
+
+#ifdef COORD
+interface ITransaction;
+#endif
+
+
+SCODE OpenStorage(const OLECHAR *pwcsName,
+#ifdef COORD
+ ITransaction *pTransaction,
+#else
+ void *pTransaction,
+#endif
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+#if WIN32 == 300
+ LPSECURITY_ATTRIBUTES pssSecurity,
+#else
+ LPSTGSECURITY reserved,
+#endif
+ IStorage **ppstgOpen,
+ CLSID *pcid);
+SCODE OpenStorageOnILockBytes(ILockBytes *plkbyt,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstgOpen,
+ CLSID *pcid);
+STDAPI DfUnMarshalInterface(IStream *pstStm,
+ REFIID iid,
+ BOOL fFirst,
+ void **ppvObj);
+
+#ifdef WIN32
+STDAPI DfGetClass(HANDLE hFile, CLSID *pclsid);
+#endif
+
+#if WIN32 >= 300
+#define CLSID_FILENAME (L".clsid")
+STDAPI StgGetClassFile (HANDLE hParent,
+ const WCHAR *pwcsName,
+ CLSID *pclsid,
+ HANDLE *hFile);
+#endif
+
+// Called by StgCreateStorage and StgCreateDocfile
+STDAPI DfCreateDocfile(WCHAR const *pwcsName,
+#ifdef COORD
+ ITransaction *pTransaction,
+#else
+ void *pTransaction,
+#endif
+ DWORD grfMode,
+#if WIN32 == 300
+ LPSECURITY_ATTRIBUTES pssSecurity,
+#else
+ LPSTGSECURITY reserved,
+#endif
+ IStorage **ppstg);
+
+// Called by StgOpenStorage
+STDAPI DfOpenDocfile(WCHAR const *pwcsName,
+#ifdef COORD
+ ITransaction *pTransaction,
+#else
+ void *pTransaction,
+#endif
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+#if WIN32 == 300
+ LPSECURITY_ATTRIBUTES pssSecurity,
+#else
+ LPSTGSECURITY reserved,
+#endif
+ IStorage **ppstgOpen);
+
+
+#endif // #ifndef __DFENTRY_HXX__
diff --git a/private/ole32/stg/h/dfexcept.hxx b/private/ole32/stg/h/dfexcept.hxx
new file mode 100644
index 000000000..49e3aac00
--- /dev/null
+++ b/private/ole32/stg/h/dfexcept.hxx
@@ -0,0 +1,69 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dfexcept.hxx
+//
+// Contents: Macros to make exception code no-ops in 16-bit
+// Includes real exceptions for 32-bit
+//
+// History: 08-Apr-92 DrewB Created
+// 10-Jul-92 DrewB Added 32-bit support
+//
+//---------------------------------------------------------------
+
+#ifndef __DFEXCEPT_HXX__
+#define __DFEXCEPT_HXX__
+
+#ifndef REF
+
+#ifdef _CAIRO_
+#include <except.hxx>
+#endif
+
+struct Exception
+{
+ SCODE GetErrorCode(void) { return 0; }
+};
+
+#undef TRY
+#define TRY
+#undef CATCH
+#define CATCH(c, e) if (0) { Exception e;
+#undef AND_CATCH
+#define AND_CATCH(c, e) } else if (0) { Exception e;
+#undef END_CATCH
+#define END_CATCH }
+#undef RETHROW
+#define RETHROW(x)
+
+#ifdef WIN32
+#define THROW_SC(sc) \
+ RaiseException((DWORD)(sc), EXCEPTION_NONCONTINUABLE, 0, NULL)
+#endif
+
+#else // REF
+
+struct Exception
+{
+ SCODE GetErrorCode(void) { return 0; }
+};
+
+#undef TRY
+#define TRY
+#undef CATCH
+#define CATCH(c, e) if (0) { Exception e;
+#undef AND_CATCH
+#define AND_CATCH(c, e) } else if (0) { Exception e;
+#undef END_CATCH
+#define END_CATCH }
+#undef RETHROW
+#define RETHROW(x)
+#endif //!REF
+
+#endif // ifndef __DFEXCEPT_HXX__
+
+
+
+
diff --git a/private/ole32/stg/h/dffuncs.hxx b/private/ole32/stg/h/dffuncs.hxx
new file mode 100644
index 000000000..d79b77192
--- /dev/null
+++ b/private/ole32/stg/h/dffuncs.hxx
@@ -0,0 +1,328 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dffuncs.hxx
+//
+// Contents: CDocFile inline functions
+// In a separate file to avoid circular dependencies
+//
+// History: 06-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DFFUNCS_HXX__
+#define __DFFUNCS_HXX__
+
+#ifndef REF
+#include <dfbasis.hxx>
+#endif //!REF
+#include <cdocfile.hxx>
+#include <sstream.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::operator new, public
+//
+// Synopsis: Unreserved object allocator
+//
+// Arguments: [size] -- byte count to allocate
+// [pMalloc] -- allocator
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void *CDocFile::operator new(size_t size, IMalloc * const pMalloc)
+{
+ return(CMallocBased::operator new(size, pMalloc));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::operator new, public
+//
+// Synopsis: Reserved object allocator
+//
+// Arguments: [size] -- byte count to allocate
+// [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void *CDocFile::operator new(size_t size, CDFBasis * const pdfb)
+{
+ olAssert(size == sizeof(CDocFile));
+
+ return pdfb->GetFreeList(CDFB_DIRECTDOCFILE)->GetReserved();
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::ReturnToReserve, public
+//
+// Synopsis: Reserved object return
+//
+// Arguments: [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_ReturnToReserve)
+#endif
+
+inline void CDocFile::ReturnToReserve(CDFBasis * const pdfb)
+{
+ CDocFile::~CDocFile();
+ pdfb->GetFreeList(CDFB_DIRECTDOCFILE)->ReturnToReserve(this);
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::Reserve, public
+//
+// Synopsis: Reserve instances
+//
+// Arguments: [cItems] -- count of items
+// [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CDocFile::Reserve(UINT cItems, CDFBasis * const pdfb)
+{
+ return pdfb->Reserve(cItems, CDFB_DIRECTDOCFILE);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::Unreserve, public
+//
+// Synopsis: Unreserve instances
+//
+// Arguments: [cItems] -- count of items
+// [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void CDocFile::Unreserve(UINT cItems, CDFBasis * const pdfb)
+{
+ pdfb->Unreserve(cItems, CDFB_DIRECTDOCFILE);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::CDocFile, public
+//
+// Synopsis: Empty object ctor
+//
+// Arguments: [dl] - LUID
+// [pdfb] - Basis
+//
+// History: 30-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_CDocFile1)
+#endif
+
+#ifndef REF
+inline CDocFile::CDocFile(DFLUID dl, CDFBasis *pdfb)
+#else
+inline CDocFile::CDocFile(DFLUID dl, ILockBytes *pilbBase)
+#endif //!REF
+ : PDocFile(dl), _pdfb(P_TO_BP(CBasedDFBasisPtr, pdfb))
+{
+ _cReferences = 0;
+#ifdef REF
+ _pilbBase = pilbBase;
+#endif //!REF
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::CDocFile, public
+//
+// Synopsis: Handle-setting construction
+//
+// Arguments: [pms] - MultiStream to use
+// [sid] - SID to use
+// [dl] - LUID
+// [pdfb] - Basis
+//
+// History: 29-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_CDocFile2)
+#endif
+
+inline CDocFile::CDocFile(CMStream *pms,
+ SID sid,
+ DFLUID dl,
+#ifndef REF
+ CDFBasis *pdfb)
+#else
+ ILockBytes *pilbBase)
+#endif //!REF
+ : PDocFile(dl), _pdfb(P_TO_BP(CBasedDFBasisPtr, pdfb))
+{
+ _stgh.Init(pms, sid);
+ _cReferences = 0;
+#ifdef REF
+ _pilbBase = pilbBase;
+#endif //!REF
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::~CDocFile, public
+//
+// Synopsis: Destructor
+//
+// History: 19-Dec-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDocFile_1CDocFile)
+#endif
+
+inline CDocFile::~CDocFile(void)
+{
+ olAssert(_cReferences == 0);
+ if (_stgh.IsValid())
+ {
+ if (_stgh.IsRoot())
+ DllReleaseMultiStream(_stgh.GetMS());
+ }
+}
+
+#ifndef REF
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::GetReservedDocfile, public
+//
+// Synopsis: Gets a previously reserved object
+//
+// History: 09-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline CDocFile *CDocFile::GetReservedDocfile(DFLUID luid)
+{
+ CDFBasis *pdfb = BP_TO_P(CDFBasis *, _pdfb);
+
+ return new(pdfb) CDocFile(luid, pdfb);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::GetReservedStream, public
+//
+// Synopsis: Gets a previously reserved object
+//
+// History: 09-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline CDirectStream *CDocFile::GetReservedStream(DFLUID luid)
+{
+ return new(_pdfb) CDirectStream(luid);
+}
+#endif //!REF
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::GetHandle, public
+//
+// Synopsis: Returns the handle
+//
+// History: 05-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CStgHandle *CDocFile::GetHandle(void)
+{
+ return &_stgh;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::DecRef, public
+//
+// Synopsis: Decrements the ref count
+//
+// History: 23-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CDocFile::DecRef(void)
+{
+ AtomicDec(&_cReferences);
+}
+
+#ifndef REF
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::ReturnDocFile, public
+//
+// Synopsis: Returns a child to the freelist
+//
+// Arguments: [pdf] - Docfile
+//
+// History: 23-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CDocFile::ReturnDocFile(CDocFile *pdf)
+{
+ olDebugOut((DEB_ITRACE, "In CDocFile::ReturnDocFile:%p(%p)\n",
+ this, pdf));
+ // Force ref count to zero without freeing memory
+ pdf->DecRef();
+ pdf->ReturnToReserve(BP_TO_P(CDFBasis *, _pdfb));
+ olDebugOut((DEB_ITRACE, "Out CDocFile::ReturnDocFile\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::ReturnStream, public
+//
+// Synopsis: Returns a stream to the freelist
+//
+// Arguments: [pstm] - Stream
+//
+// History: 23-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CDocFile::ReturnStream(CDirectStream *pstm)
+{
+ olDebugOut((DEB_ITRACE, "In CDocFile::ReturnStream:%p(%p)\n",
+ this, pstm));
+ // Force ref count to zero without freeing memory
+ pstm->DecRef();
+ pstm->ReturnToReserve(BP_TO_P(CDFBasis *, _pdfb));
+ olDebugOut((DEB_ITRACE, "Out CDocFile::ReturnStream\n"));
+}
+#endif //!REF
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+#endif // #ifndef __DFFUNCS_HXX__
diff --git a/private/ole32/stg/h/dfmem.hxx b/private/ole32/stg/h/dfmem.hxx
new file mode 100644
index 000000000..5cc8c8dad
--- /dev/null
+++ b/private/ole32/stg/h/dfmem.hxx
@@ -0,0 +1,160 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: DfMem.HXX
+//
+// Contents: Memory headers
+//
+// Functions: DfCreateSharedAllocator
+// new (DBG only)
+// delete (DBG only)
+//
+// Classes: CMallocBased
+// CLocalAlloc
+//
+// History: 18-May-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __DFMEM_HXX__
+#define __DFMEM_HXX__
+
+#ifndef _HEAP_MAXREQ
+# define _HEAP_MAXREQ 0xffffffff // from 16-bit malloc.h
+#endif
+
+#if defined(WIN32)
+
+#define TaskMemAlloc CoTaskMemAlloc
+#define TaskMemFree CoTaskMemFree
+
+// Creating the shared memory indirects through a pointer for most
+// efficient once-per-process initialisation
+extern HRESULT (*DfCreateSharedAllocator) ( IMalloc ** ppm );
+
+// Constants related to the Docfile shared memory
+#define DOCFILE_SM_NAME L"XXYZZY1OleSharedHeap"
+#ifdef MULTIHEAP
+#define DOCFILE_SM_SIZE 0x400000L /* 4 Meg */
+#else
+#define DOCFILE_SM_SIZE 0x4000000L
+#endif
+#define DOCFILE_SM_NAMELEN 32
+
+#else // 16 bit
+
+// Use TaskMemAlloc and TaskMemFree for allocations that may be returned
+
+extern void *TaskMemAlloc(ULONG ulcb);
+extern void TaskMemFree(void *pv);
+
+# if DBG==0
+# define DfCreateSharedAllocator(ppm) \
+ CoCreateStandardMalloc(MEMCTX_SHARED, ppm)
+# else
+extern HRESULT DfCreateSharedAllocator(IMalloc **ppm);
+# endif
+
+#endif // defined(WIN32)
+
+
+class CMallocBased
+{
+public:
+ void *operator new(size_t size, IMalloc * const pMalloc);
+
+ void operator delete(void *pv);
+ // deallocate the memory without Mutex
+ // (requires that the MUtex is already locked)
+ void deleteNoMutex(void *pv);
+
+};
+
+//+-------------------------------------------------------------------------
+//
+// Class: CLocalAlloc
+//
+// Purpose: Base class for classes allocated in task local memory.
+//
+// Interface: See below.
+//
+// History: 17-Aug-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+class CLocalAlloc
+{
+public:
+#if DBG==0 || defined(MULTIHEAP)
+ inline
+#endif
+ void *operator new(size_t size);
+
+#if DBG==0 || defined(MULTIHEAP)
+ inline
+#endif
+ void operator delete(void *pv);
+};
+
+#if DBG==0 || defined(MULTIHEAP)
+
+//+-------------------------------------------------------------------------
+//
+// Method: CLocalAlloc::operator new, public
+//
+// Synopsis: Overloaded new operator to allocate objects from
+// task local space.
+//
+// Arguments: [size] -- Size of block to allocate
+//
+// Returns: Pointer to memory allocated.
+//
+// History: 17-Aug-92 PhilipLa Created.
+// 18-May-93 AlexT Switch to task IMalloc
+//
+//--------------------------------------------------------------------------
+
+inline void *CLocalAlloc::operator new(size_t size)
+{
+ return TaskMemAlloc(size);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CLocalAlloc::operator delete, public
+//
+// Synopsis: Free memory from task local space
+//
+// Arguments: [pv] -- Pointer to memory to free
+//
+// History: 17-Aug-92 PhilipLa Created.
+// 18-May-93 AlexT Switch to task IMalloc
+//
+//--------------------------------------------------------------------------
+
+inline void CLocalAlloc::operator delete(void *pv)
+{
+ TaskMemFree(pv);
+}
+
+#endif // DBG == 0 || defined(MULTIHEAP)
+
+// Use DfMemAlloc and DfMemFree for tempory allocations
+
+#define DfMemAlloc(cb) CLocalAlloc::operator new((size_t) (cb))
+#define DfMemFree(pv) delete (CLocalAlloc *) (pv)
+
+#ifndef REF
+
+#if DBG==1
+
+extern void * _CRTAPI1 operator new(size_t size);
+extern void _CRTAPI1 operator delete(void *pv);
+
+#endif
+
+#endif //!REF
+
+#endif // #ifndef __DFMEM_HXX__
diff --git a/private/ole32/stg/h/dfmsp.hxx b/private/ole32/stg/h/dfmsp.hxx
new file mode 100644
index 000000000..50da80256
--- /dev/null
+++ b/private/ole32/stg/h/dfmsp.hxx
@@ -0,0 +1,745 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992
+//
+// File: dfmsp.hxx
+//
+// Contents: DocFile and MultiStream shared private definitions
+//
+// History: 01-Apr-92 DrewB Created
+// 06-Sep-95 MikeHill Added P_NOSCRATCH
+//
+//---------------------------------------------------------------
+
+#ifndef __DFMSP_HXX__
+#define __DFMSP_HXX__
+
+#ifndef REF
+#include <debnot.h>
+#else
+#include <ref.hxx>
+#endif //!REF
+#include <wchar.h>
+#ifndef REF
+#include <valid.h>
+#endif //!REF
+#include <string.h>
+
+#if !defined(MULTIHEAP) && !defined(_CHICAGO_)
+#define MULTIHEAP
+#include <tls.h>
+#endif
+
+#ifdef ASYNC
+#include <async.hxx>
+#endif
+
+
+// Target-dependent things
+
+//
+// x86 16-bit build optimizations
+//
+// Some function parameters are always stack based pointers,
+// so we can let the compiler use near addressing via ss by
+// declaring the parameter stack based.
+//
+
+#ifndef REF
+#if defined(_M_I286)
+#define STACKBASED __based(__segname("_STACK"))
+#else
+#define STACKBASED
+#endif
+#else
+#define STACKBASED
+#endif //!REF
+
+//
+// x86 16-bit retail build optimizations
+//
+// For the retail build, we group the code segments,
+// allowing us to make many calls near.
+//
+
+#ifndef REF
+#if defined(_M_I286) && DBG == 0 && defined(USE_NEAR)
+#define DFBASED
+#define DIR_CLASS __near
+#define FAT_CLASS __near
+#define MSTREAM_CLASS __near
+#define VECT_CLASS __near
+#else
+#define DFBASED
+#define DIR_CLASS
+#define FAT_CLASS
+#define MSTREAM_CLASS
+#define VECT_CLASS
+#endif
+#else
+#define DFBASED
+#define DIR_CLASS
+#define FAT_CLASS
+#define MSTREAM_CLASS
+#define VECT_CLASS
+#endif //!REF
+
+#ifndef REF
+// Compiler pragma define
+// Currently defined for C7 and C8
+// Unused as of 1/18/93
+#if ((_MSC_VER == 700) || (_MSC_VER == 800))
+#define MS_COMPILER
+#endif
+#endif //!REF
+
+// Segmented memory model definitions
+#ifndef REF
+#if !defined(HUGEP)
+#if defined(_M_I286)
+#define HUGEP __huge
+#else
+#define HUGEP
+#endif
+#endif
+#else
+#define HUGEP
+#endif //!REF
+
+#ifndef LISet32
+#define LISet32(li, v) ((li).QuadPart = (LONGLONG) (v))
+#endif
+#ifndef ULISet32
+#define ULISet32(li, v) ((li).QuadPart = (DWORDLONG) (v))
+#endif
+#define LISetLow(li, v) ((li).LowPart = (v))
+#define LISetHigh(li, v) ((li).HighPart = (v))
+#define ULISetLow(li, v) ((li).LowPart = (v))
+#define ULISetHigh(li, v) ((li).HighPart = (v))
+#define LIGetLow(li) ((li).LowPart)
+#define LIGetHigh(li) ((li).HighPart)
+#define ULIGetLow(li) ((li).LowPart)
+#define ULIGetHigh(li) ((li).HighPart)
+
+// Fast safe increment/decrement
+#if !defined(REF) && defined(USEATOMICINC)
+#ifdef FLAT
+
+// Win32 specific functions
+// Should use #ifdef WIN32 instead of FLAT, but there isn't a WIN32
+
+#define AtomicInc(lp) InterlockedIncrement(lp)
+#define AtomicDec(lp) InterlockedDecrement(lp)
+
+#else
+#define AtomicInc(lp) (++*(lp))
+#define AtomicDec(lp) (--*(lp))
+
+#endif
+#else
+#define AtomicInc(lp) (++*(lp))
+#define AtomicDec(lp) (--*(lp))
+
+#endif //!REF
+
+// Switchable ANSI/Unicode support for TCHAR
+// Conversion routines assume null termination before max characters
+#ifdef UNICODE
+
+#define ATOT(a, t, max) mbstowcs(t, a, max)
+#define TTOA(t, a, max) wcstombs(a, t, max)
+#define WTOT(w, t, max) wcscpy(t, w)
+#define TTOW(t, w, max) wcscpy(w, t)
+
+#define tcscpy(t, f) lstrcpyW(t, f)
+#define tcslen(t) lstrlenW(t)
+
+#define TSTR(s) L##s
+
+// printf format string
+#define TFMT "%ws"
+
+#else
+
+#define ATOT(a, t, max) strcpy(t, a)
+#define TTOA(t, a, max) strcpy(a, t)
+#define WTOT(w, t, max) wcstombs(t, w, max)
+#define TTOW(t, w, max) mbstowcs(w, t, max)
+
+#define tcscpy(t, f) strcpy(t, f)
+#define tcslen(t) strlen(t)
+
+#define TSTR(s) s
+
+// printf format string
+#define TFMT "%s"
+
+#endif
+
+// Switchable ANSI/Unicode support for OLECHAR
+// Conversion routines assume null termination before max characters
+#ifdef WIN32
+
+#define OLEWIDECHAR
+
+#ifndef OLECHAR
+#define LPOLESTR LPWSTR
+#define LPCOLESTR LPCWSTR
+#define OLECHAR WCHAR
+#define OLESTR(str) L##str
+#endif //OLECHAR
+
+#define _OLESTDMETHODIMP STDMETHODIMP
+#define _OLEAPIDECL STDAPI
+#define _OLERETURN(sc) ResultFromScode(sc)
+#define _OLEAPI(name) name
+
+#define ATOOLE(a, t, max) mbstowcs(t, a, max)
+#define OLETOA(t, a, max) wcstombs(a, t, max)
+#define WTOOLE(w, t, max) wcscpy(t, w)
+#define OLETOW(t, w, max) wcscpy(w, t)
+
+#define olecscpy(t, f) lstrcpyW(t, f)
+#define olecslen(t) lstrlenW(t)
+
+#define OLESTR(s) L##s
+
+// printf format string
+#define OLEFMT "%ws"
+
+#else
+
+#ifndef OLECHAR
+#define LPOLESTR LPSTR
+#define LPCOLESTR LPCSTR
+#define OLECHAR char
+#define OLESTR(str) str
+#endif
+
+#define _OLESTDMETHODIMP SCODE
+#define _OLEAPIDECL SCODE
+#define _OLERETURN(sc) (sc)
+#define _OLEAPI(name) name##W
+#define ATOOLE(a, t, max) strcpy(t, a)
+#define OLETOA(t, a, max) strcpy(a, t)
+#define WTOOLE(w, t, max) wcstombs(t, w, max)
+#define OLETOW(t, w, max) mbstowcs(w, t, max)
+
+#define olecscpy(t, f) strcpy(t, f)
+#define olecslen(t) strlen(t)
+
+#define OLESTR(s) s
+
+// printf format string
+#define OLEFMT "%s"
+
+#endif
+
+// Security will only be enabled for Cairo builds, except that
+// [BUGBUG] the public include files do not yet reflect this.
+#ifdef _CAIRO_
+typedef DWORD LPSTGSECURITY;
+// [later] typedef LPSECURITY_ATTRIBUTES LPSTGSECURITY;
+#else
+typedef DWORD LPSTGSECURITY;
+#endif
+
+// In Cairo, the reserved field in STATSTG will become dwStgFmt, except
+// [BUGBUG] it is not yet.
+#ifdef _CAIRO_
+#define STATSTG_dwStgFmt reserved
+// [later] #define STATSTG_dwStgFmt dwStgFmt
+#else
+#define STATSTG_dwStgFmt reserved
+#endif
+
+// For NT 1.0a OLE we need to use based pointers for shared memory objects
+// since they might not be mapped at the same address in every process
+#if WIN32 == 100 || WIN32 > 200
+#define USEBASED
+#endif
+
+//We need DfInitSharedMemBase even if we aren't using based pointers,
+// since it sets up the shared mem allocator if one hasn't already
+// been set up.
+void DfInitSharedMemBase(void);
+
+
+#ifdef USEBASED
+#ifdef MULTIHEAP
+#define DFBASEPTR pvDfSharedMemBase()
+
+// The previous declaration of DFBASEPTR was:
+// extern __declspec(thread) void *DFBASEPTR;
+// Now, it is an inline function that returns the threadlocal base pointer
+// Reference to pointer syntax is needed for assignments to DFBASEPTR
+inline void *& DFBASEPTR
+{
+ COleTls otls;
+ return otls->pvThreadBase;
+}
+
+#else
+#define DFBASEPTR pvDfSharedMemBase
+
+extern void *DFBASEPTR;
+#endif // MULTIHEAP
+
+#pragma warning(error: 4795 4796)
+
+#undef DFBASED
+#ifdef MULTIHEAP
+// based pointers are replaced by CSafeBased... smart pointer macros
+// macros invoke conversion constructor and conversion operators
+//#define DFBASED __based(DFBASEDPTR)
+#define P_TO_BP(t, p) ((t)(p))
+#define BP_TO_P(t, bp) ((t)(bp))
+
+#else // MULTIHEAP
+#define DFBASED __based(DFBASEPTR)
+
+#define P_TO_BP(t, p) ((t)((p) ? (int)(t)(char *)(p) : 0))
+
+#define BP_TO_P(t, bp) (t)((bp) != 0 ? (bp) : 0)
+#endif // MULTIHEAP
+
+#else
+#define P_TO_BP(t, p) p
+#define BP_TO_P(t, bp) bp
+#endif //USEBASED
+
+//----------------------------------------------------------------------------
+
+// The name of this function might change, so encapsulate it
+#define DfGetScode(hr) GetScode(hr)
+
+#ifndef REF
+// Buffer/pointer validation macros
+#define AssertMsg(s) _Win4Assert(__FILE__, __LINE__, s)
+#endif //!REF
+
+#ifndef REF
+// MAC - We use Windows functions if available
+#if (WIN32 == 100 || WIN32 >= 300)
+#define IsValidHugePtrIn(pv, n) (((pv) == NULL) || !IsBadHugeReadPtr(pv, n))
+#define IsValidHugePtrOut(pv, n) (!IsBadHugeWritePtr(pv, n))
+#else
+#define IsValidHugePtrIn(pv, n) 1
+#define IsValidHugePtrOut(pv, n) ((pv) != NULL)
+#endif
+#endif //!REF
+
+#ifndef REF
+#define ValidateBuffer(pv, n) \
+ (((pv) == NULL || !IsValidPtrIn(pv, n)) ? STG_E_INVALIDPOINTER : S_OK)
+
+#define ValidatePtrBuffer(pv) \
+ ValidateBuffer(pv, sizeof(void *))
+
+#define ValidateHugeBuffer(pv, n) \
+ (((pv) == NULL || !IsValidHugePtrIn(pv, n)) ? STG_E_INVALIDPOINTER : S_OK)
+
+#define ValidateOutBuffer(pv, n) \
+ (!IsValidPtrOut(pv, n) ? STG_E_INVALIDPOINTER : S_OK)
+
+#define ValidateOutPtrBuffer(pv) \
+ ValidateOutBuffer(pv, sizeof(void *))
+
+#define ValidateHugeOutBuffer(pv, n) \
+ (!IsValidHugePtrOut(pv, n) ? STG_E_INVALIDPOINTER : S_OK)
+
+#if DBG==1
+#define ValidateIid(riid) \
+ (!IsValidIid(riid) ? STG_E_INVALIDPOINTER : S_OK)
+#else
+// killed this macro in retail build since it used to do no useful work
+// now we are faster. see comment for ValidateIid.
+#define ValidateIid(riid) S_OK
+#endif
+
+#define ValidateInterface(punk, riid) \
+ (!IsValidInterface(punk) ? STG_E_INVALIDPOINTER : S_OK)
+
+#if (WIN32 == 100 || WIN32 >= 300)
+#define ValidateWcs(pwcs, cwcMax) \
+ (IsBadStringPtrW(pwcs, cwcMax) ? STG_E_INVALIDPOINTER : S_OK)
+#else
+// OLE should provide a helper function for this
+#define ValidateWcs(pwcs, cwcMax) \
+ ((pwcs == NULL) || !IsValidPtrIn(pwcs, sizeof(WCHAR)) ? STG_E_INVALIDPOINTER : S_OK)
+#endif
+
+#if defined(_WINDOWS_)
+# define ValidateSz(psz, cchMax) \
+ (IsBadStringPtrA(psz, cchMax) ? STG_E_INVALIDPOINTER : S_OK)
+#elif defined(_INC_WINDOWS)
+# define ValidateSz(psz, cchMax) \
+ (IsBadStringPtr(psz, cchMax) ? STG_E_INVALIDPOINTER : S_OK)
+#else
+// MAC - OLE doesn't provide sufficient helper functions
+# define ValidateSz(psz, cchMax) \
+ (!IsValidPtrIn(psz, 1) ? STG_E_INVALIDPOINTER : S_OK)
+#endif
+
+#if defined(OLEWIDECHAR)
+#if (WIN32 == 100 || WIN32 >=300)
+#define ValidateNameW(pwcs, cchMax) \
+ (IsBadStringPtrW(pwcs, cchMax) ? STG_E_INVALIDNAME : S_OK)
+#else
+#define ValidateNameW(pwcs, cchMax) \
+ ((IsBadReadPtr(pwcs, sizeof(WCHAR))) ? STG_E_INVALIDNAME : S_OK)
+#endif
+#else
+// For non-Unicode builds, we verify all names before converting them
+// to wide character names, so there's no need to recheck.
+# define ValidateNameW(pwcs, cchMax) \
+ S_OK
+#endif
+
+#if defined(_WINDOWS_)
+# define ValidateNameA(psz, cchMax) \
+ (IsBadStringPtrA(psz, cchMax) ? STG_E_INVALIDNAME : S_OK)
+#elif defined(_INC_WINDOWS)
+# define ValidateNameA(psz, cchMax) \
+ (IsBadStringPtr(psz, cchMax) ? STG_E_INVALIDNAME : S_OK)
+#else
+# define ValidateNameA(psz, cchMax) \
+ (!IsValidPtrIn(psz, 1) ? STG_E_INVALIDNAME : S_OK)
+#endif
+
+#else
+#define ValidateBuffer(pv, n) S_OK
+#define ValidatePtrBuffer(pv) S_OK
+#define ValidateHugeBuffer(pv, n) S_OK
+#define ValidateOutBuffer(pv, n) S_OK
+#define ValidateOutPtrBuffer(pv) S_OK
+#define ValidateHugeOutBuffer(pv, n) S_OK
+#define ValidateIid(riid) S_OK
+#define ValidateInterface(punk,riid) S_OK
+#define ValidateWcs(pwcs, cwcMax) S_OK
+#define ValidateSz(psz, cchMax) S_OK
+#define ValidateNameW(pwcs, cchMax) S_OK
+#define ValidateNameA(psz, cchMax) S_OK
+#endif //!REF
+
+// Enumeration for Get/SetTime
+enum WHICHTIME
+{
+ WT_CREATION,
+ WT_MODIFICATION,
+ WT_ACCESS
+};
+
+// Time type
+typedef FILETIME TIME_T;
+
+// Signature for transactioning
+typedef DWORD DFSIGNATURE;
+#define DF_INVALIDSIGNATURE ((DFSIGNATURE)-1)
+
+// Convenience macros for signature creation
+#define LONGSIG(c1, c2, c3, c4) \
+ (((ULONG) (BYTE) (c1)) | \
+ (((ULONG) (BYTE) (c2)) << 8) | \
+ (((ULONG) (BYTE) (c3)) << 16) | \
+ (((ULONG) (BYTE) (c4)) << 24))
+
+#ifndef min
+#define min(a, b) ((a)<(b) ? (a) : (b))
+#endif
+#ifndef max
+#define max(a, b) ((a)>(b) ? (a) : (b))
+#endif
+
+SCODE DfGetTOD(TIME_T *ptm);
+
+// Shared signature validation routine
+SCODE CheckSignature(BYTE *pb);
+
+// Docfile locally unique identity
+// Every entry in a multistream has a LUID generated and stored for it
+typedef DWORD DFLUID;
+#define DF_NOLUID 0
+
+#ifndef OLEWIDECHAR
+typedef WCHAR **SNBW;
+
+typedef struct
+{
+ WCHAR *pwcsName;
+ DWORD type;
+ ULARGE_INTEGER cbSize;
+ FILETIME mtime;
+ FILETIME ctime;
+ FILETIME atime;
+ DWORD grfMode;
+ DWORD grfLocksSupported;
+ CLSID clsid;
+ DWORD grfStateBits;
+ DWORD reserved;
+} STATSTGW;
+
+#else
+typedef SNB SNBW;
+typedef STATSTG STATSTGW;
+#endif
+
+#define CBSTORAGENAME (CWCSTORAGENAME*sizeof(WCHAR))
+
+int dfwcsnicmp(const WCHAR *wcsa, const WCHAR *wcsb, size_t len);
+
+#include <dfname.hxx>
+
+// Fast, fixed space iterator structure
+struct SIterBuffer
+{
+ CDfName dfnName;
+ DWORD type;
+};
+
+//SID is a Stream Identifier
+#ifndef REF
+#ifdef FLAT
+#define SID DFSID
+#endif
+#endif //!REF
+typedef ULONG SID;
+
+// IsEntry entry information
+struct SEntryBuffer
+{
+ DFLUID luid;
+ DWORD dwType;
+ SID sid;
+};
+
+// Destroy flags
+#define DESTROY_FROM_HANDLE 0
+#define DESTROY_FROM_ENTRY 1
+#define DESTROY_FROM 0x01
+#define DESTROY_SELF 0x40
+#define DESTROY_RECURSIVE 0x80
+
+#define DESTROY_HANDLE (DESTROY_FROM_HANDLE | DESTROY_SELF)
+#define DESTROY_ENTRY (DESTROY_FROM_ENTRY | DESTROY_SELF)
+
+// Root startup flags
+#define RSF_OPEN 0x00
+#define RSF_CONVERT 0x01
+#define RSF_TRUNCATE 0x02
+#define RSF_CREATE 0x04
+#define RSF_DELAY 0x08
+#define RSF_DELETEONRELEASE 0x10
+#define RSF_OPENCREATE 0x20
+
+#define RSF_CREATEFLAGS (RSF_CREATE | RSF_TRUNCATE | RSF_OPENCREATE)
+
+// Stream copy buffer size
+ULONG const STREAMBUFFERSIZE = 8192;
+
+// ILockBytes copy buffer size
+ULONG const LOCKBYTESBUFFERSIZE = 16384;
+
+// Docfile flags for permissions and other information kept
+// on streams and docfiles
+typedef DWORD DFLAGS;
+
+#define DF_TRANSACTEDSELF 0x0001
+
+#define DF_TRANSACTED 0x0002
+#define DF_DIRECT 0x0000
+
+#define DF_INDEPENDENT 0x0004
+#define DF_DEPENDENT 0x0000
+
+#define DF_COMMIT 0x0008
+#define DF_ABORT 0x0000
+
+#define DF_INVALID 0x0010
+
+#define DF_REVERTED 0x0020
+#define DF_NOTREVERTED 0x0000
+
+#define DF_READ 0x0040
+#define DF_WRITE 0x0080
+#define DF_READWRITE (DF_READ | DF_WRITE)
+
+#define DF_DENYREAD 0x0100
+#define DF_DENYWRITE 0x0200
+#define DF_DENYALL (DF_DENYREAD | DF_DENYWRITE)
+
+#define DF_PRIORITY 0x0400
+#define DF_CREATE 0x0800
+#define DF_CACHE 0x1000
+#define DF_NOUPDATE 0x2000
+#define DF_NOSCRATCH 0x4000
+#if WIN32 >= 300
+#define DF_ACCESSCONTROL 0x8000
+#endif
+
+#define DF_COORD 0x10000
+#define DF_COMMITTING 0x20000
+#define DF_NOSNAPSHOT 0x40000
+
+// Shift required to translate from DF_READWRITE to DF_DENYALL
+#define DF_DENIALSHIFT 2
+
+// Permission abstraction macros
+// These only work with DF_* flags
+#define P_READ(f) ((f) & DF_READ)
+#define P_WRITE(f) ((f) & DF_WRITE)
+#define P_READWRITE(f) (((f) & (DF_READ | DF_WRITE)) == (DF_READ | DF_WRITE))
+#define P_DENYREAD(f) ((f) & DF_DENYREAD)
+#define P_DENYWRITE(f) ((f) & DF_DENYWRITE)
+#define P_DENYALL(f) (((f) & (DF_DENYREAD | DF_DENYWRITE)) == \
+ (DF_DENYREAD | DF_DENYWRITE))
+#define P_PRIORITY(f) ((f) & DF_PRIORITY)
+#define P_TRANSACTED(f) ((f) & DF_TRANSACTED)
+#define P_DIRECT(f) (!P_TRANSACTED(f))
+#define P_INDEPENDENT(f) ((f) & DF_INDEPENDENT)
+#define P_DEPENDENT(f) (!P_INDEPENDENT(f))
+#define P_TSELF(f) ((f) & DF_TRANSACTEDSELF)
+#define P_INVALID(f) ((f) & DF_INVALID)
+#define P_REVERTED(f) ((f) & DF_REVERTED)
+#define P_COMMIT(f) ((f) & DF_COMMIT)
+#define P_ABORT(f) (!P_COMMIT(f))
+#define P_CREATE(f) ((f) & DF_CREATE)
+#define P_CACHE(f) ((f) & DF_CACHE)
+#define P_NOUPDATE(f) ((f) & DF_NOUPDATE)
+#define P_COORD(f) ((f) & DF_COORD)
+#define P_COMMITTING(f) ((f) & DF_COMMITTING)
+#define P_NOSCRATCH(f) ((f) & DF_NOSCRATCH)
+#define P_NOSNAPSHOT(f) ((f) & DF_NOSNAPSHOT)
+
+// Translation functions
+DFLAGS ModeToDFlags(DWORD const dwModeFlags);
+DWORD DFlagsToMode(DFLAGS const df);
+
+// Flags for what state has been dirtied
+#define DIRTY_CREATETIME 0x0001
+#define DIRTY_MODIFYTIME 0x0002
+#define DIRTY_ACCESSTIME 0x0004
+#define DIRTY_CLASS 0x0008
+#define DIRTY_STATEBITS 0x0010
+
+// Allow text in asserts
+#define aMsg(s) ((char *)(s) != NULL)
+
+// Indicate that something is a property value
+// This must not conflict with official STGTY_* flags
+#define STGTY_REAL (STGTY_STORAGE | STGTY_STREAM | STGTY_LOCKBYTES)
+
+#define REAL_STGTY(f) (f)
+
+// Buffer management
+#define CB_LARGEBUFFER 32768
+#define CB_PAGEBUFFER 4096
+#define CB_SMALLBUFFER 512
+
+extern SCODE GetBuffer(USHORT cbMin, USHORT cbMax, BYTE **ppb,
+ USHORT *pcbActual);
+extern void GetSafeBuffer(USHORT cbMin, USHORT cbMax, BYTE **ppb,
+ USHORT *pcbActual);
+extern void FreeBuffer(BYTE *pb);
+
+#include <dfmem.hxx>
+
+#ifndef REF
+#define DfAllocWC(cwc, ppwcs) (*ppwcs = (WCHAR *)\
+ TaskMemAlloc((cwc)*sizeof(WCHAR)),\
+ (*ppwcs != NULL) ? S_OK: STG_E_INSUFFICIENTMEMORY)
+#else
+#define DfAllocWC(cwc, ppwcs) (*ppwcs = new WCHAR[cwc],\
+ (*ppwcs != NULL) ? S_OK: STG_E_INSUFFICIENTMEMORY)
+#endif //!REF
+
+#define DfAllocWCS(pwcs, ppwcs) DfAllocWC(lstrlenW(pwcs)+1, ppwcs)
+
+#ifndef WIN32
+#define STG_SCODE(err) \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, SCODE_CODE(err))
+#else
+SCODE Win32ErrorToScode(DWORD dwErr);
+#define STG_SCODE(err) Win32ErrorToScode(err)
+
+#endif
+
+#ifdef MULTIHEAP
+//+------------------------------------------------------------------------
+//
+// Macro: SAFE_DFBASED_PTR
+//
+// Purpose: Pointer to memory created by shared memory allocator.
+// This macro replaces the __based() compiler keyword
+// Only the offset is stored in _p, and conversion operators
+// return the absolute address (by adding the base address).
+// The smart pointer can only change through:
+// construction, assignment operator=
+// The smart pointer can be read through:
+// operator->, operator*, (casting to unbased type)
+// Destroying the smart pointer does not invoke _p's destructor
+//
+// Notes: There is special logic to translate a NULL based pointer
+// into a NULL absolute pointer, and vice versa.
+// We can do this without ambiguity since DFBASEPTR can
+// never be returned from CSmAlllocator::Alloc
+// (DFBASEPTR is really a CHeapHeader pointer, part of the heap)
+//
+// Arguments: [SpName] - class name of the smart based pointer
+// [SpType] - class name of the original unbased type
+//
+// History: 22-Feb-96 HenryLee Created
+//
+//-------------------------------------------------------------------------
+
+#define SAFE_DFBASED_PTR(SpName,SpType) \
+class SpName \
+{ \
+public: \
+inline SpName () : _p(NULL) \
+ { \
+ } \
+inline SpName (SpType *p) \
+ { \
+ _p = (p) ? (SpType*)((BYTE*)p - (UINT)DFBASEPTR) : NULL; \
+ } \
+inline ~##SpName () \
+ { \
+ } \
+inline SpType* operator-> () const \
+ { \
+ return (SpType *)(_p ? (BYTE *)_p + (UINT)DFBASEPTR : NULL); \
+ } \
+inline SpType& operator * () const \
+ { \
+ return * (SpType *)(_p ? (BYTE *)_p + (UINT)DFBASEPTR : NULL); \
+ } \
+inline operator SpType* () const \
+ { \
+ return (SpType *)(_p ? (BYTE *)_p + (UINT)DFBASEPTR : NULL); \
+ } \
+inline SpType* operator= (SpType* p) \
+ { \
+ _p = (p) ? (SpType*)((BYTE*)p - (UINT)DFBASEPTR) : NULL; \
+ return p; \
+ } \
+private: \
+ SpType * _p; \
+}; \
+
+#else
+#define SAFE_DFBASED_PTR(SpName,SpType) \
+typedef SpType DFBASED * SpName;
+#endif // MULTIHEAP
+
+#include <widewrap.h>
+
+#ifndef STG_E_PENDINGCONTROL
+#define STG_E_PENDINGCONTROL _HRESULT_TYPEDEF_(0x80030204L)
+#endif
+
+
+#endif // #ifndef __DFMSP_HXX__
+
+
diff --git a/private/ole32/stg/h/dfname.hxx b/private/ole32/stg/h/dfname.hxx
new file mode 100644
index 000000000..b342bb3ed
--- /dev/null
+++ b/private/ole32/stg/h/dfname.hxx
@@ -0,0 +1,83 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: dfname.hxx
+//
+// Contents: CDfName header
+//
+// Classes: CDfName
+//
+// History: 14-May-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DFNAME_HXX__
+#define __DFNAME_HXX__
+
+// A name for a docfile element
+class CDfName
+{
+private:
+ BYTE _ab[CBSTORAGENAME];
+ WORD _cb;
+
+public:
+ CDfName(void) { _cb = 0; }
+
+ inline void Set(WORD const cb, BYTE const *pb);
+ void Set(WCHAR const *pwcs) { Set((lstrlenW(pwcs)+1)*sizeof(WCHAR),
+ (BYTE const *)pwcs); }
+ void Set(char const *psz) { Set(strlen(psz)+1, (BYTE const *)psz); }
+
+ inline void Set(CDfName const *pdfn);
+
+ CDfName(WORD const cb, BYTE const *pb) { Set(cb, pb); }
+ CDfName(WCHAR const *pwcs) { Set(pwcs); }
+ CDfName(char const *psz) { Set(psz); }
+
+ WORD GetLength(void) const { return _cb; }
+ BYTE *GetBuffer(void) const { return (BYTE *) _ab; }
+
+ // Make a copy of a possibly byte-array name in a WCHAR string
+ void CopyString(WCHAR const *pwcs);
+
+#ifndef FLAT
+ BOOL IsEqual(CDfName const *dfn) const
+ {
+#ifdef CASE_SENSITIVE
+ return _cb == dfn->_cb && memcmp(_ab, dfn->GetBuffer(), _cb) == 0;
+#else
+ // This assumes that all DfNames are actually Unicode strings
+ return _cb == dfn->_cb &&
+ dfwcsnicmp((WCHAR *)_ab, (WCHAR *)dfn->GetBuffer(), _cb) == 0;
+#endif
+ }
+#else
+ BOOL IsEqual(CDfName const *pdfn) const;
+#endif
+};
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDfName_Set)
+#endif
+
+inline void CDfName::Set(WORD const cb, BYTE const *pb)
+{
+ _cb = cb;
+ if (pb)
+ memcpy(_ab, pb, cb);
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+
+inline void CDfName::Set(CDfName const *pdfn)
+{
+ Set(pdfn->GetLength(), pdfn->GetBuffer());
+}
+
+#endif // #ifndef __DFNAME_HXX__
diff --git a/private/ole32/stg/h/dfrlist.hxx b/private/ole32/stg/h/dfrlist.hxx
new file mode 100644
index 000000000..05acacfe3
--- /dev/null
+++ b/private/ole32/stg/h/dfrlist.hxx
@@ -0,0 +1,27 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dfrlist.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 08-Aug-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DFRLIST_HXX__
+#define __DFRLIST_HXX__
+
+
+//We'll use this critical section to serialize access to the docfile
+// resource list, which is single process.
+extern CRITICAL_SECTION g_csResourceList;
+
+
+#endif // #ifndef __DFRLIST_HXX__
diff --git a/private/ole32/stg/h/dfver.h b/private/ole32/stg/h/dfver.h
new file mode 100644
index 000000000..4f67daa89
--- /dev/null
+++ b/private/ole32/stg/h/dfver.h
@@ -0,0 +1,5 @@
+#define rmj 3
+#define rmm 62
+#define rup 0
+#define szVerName ""
+#define szVerUser "kevinro"
diff --git a/private/ole32/stg/h/difat.hxx b/private/ole32/stg/h/difat.hxx
new file mode 100644
index 000000000..e5e6619dd
--- /dev/null
+++ b/private/ole32/stg/h/difat.hxx
@@ -0,0 +1,191 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: difat.hxx
+//
+// Contents: Double-indirect Fat class headers
+//
+// Classes: CDIFat
+// CDIFatVector
+//
+// Functions:
+//
+// History: 02-Sep-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __DIFAT_HXX__
+#define __DIFAT_HXX__
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDIFat (dif)
+//
+// Purpose: Double Indirect Fat class for MSF
+//
+// Interface: See below.
+//
+// History: 11-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+class CDIFat
+{
+
+public:
+ CDIFat();
+#ifndef REF
+ CDIFat(CDIFat *pfatOld);
+#endif //!REF
+ inline ~CDIFat();
+
+ VOID Empty(VOID);
+
+
+ SCODE GetFatSect(const FSINDEX oSect, SECT *psect);
+ SCODE SetFatSect(const FSINDEX oSect, const SECT sect);
+
+ SCODE GetSect(const FSINDEX oSect, SECT *psect);
+
+ SCODE Init(CMStream *pmsParent, const FSINDEX cFatSect);
+#ifndef REF
+ inline void InitCopy(CDIFat *pfatOld);
+#endif //!REF
+ SCODE InitConvert(CMStream *pmsParent, SECT sectMax);
+ SCODE InitNew(CMStream *pmsParent);
+
+#ifndef REF
+ SCODE Lookup(const SECT sect, SECT *psectRet);
+
+ SCODE Fixup(CMStream * pmsShadow);
+
+ SCODE Remap(const FSINDEX oSect, SECT *psectReturn);
+
+ SCODE RemapSelf(VOID);
+#endif //!REF
+
+ SCODE Flush(void);
+
+#ifdef DIFAT_LOOKUP_ARRAY
+ inline void CacheUnmarkedSect(SECT sectNew, SECT sectMark, SECT sectFree);
+#endif
+
+ inline void SetParent(CMStream *pms);
+private:
+
+ CFatVector _fv;
+ CBasedMStreamPtr _pmsParent;
+ FSINDEX _cfsTable;
+
+#ifdef DIFAT_LOOKUP_ARRAY
+#define DIFAT_ARRAY_SIZE 8
+
+ BOOL _fDoingFixup;
+ USHORT _cUnmarked;
+ SECT _sectUnmarked[DIFAT_ARRAY_SIZE];
+ SECT _sectMarkTo[DIFAT_ARRAY_SIZE];
+ SECT _sectFree[DIFAT_ARRAY_SIZE];
+#endif
+
+ SCODE Resize(FSINDEX fsiSize);
+
+ inline VOID SectToPair(
+ SECT sect,
+ FSINDEX *pipfs,
+ FSOFFSET *pisect) const;
+
+ SECT PairToSect(FSINDEX ipfs, FSOFFSET isect) const;
+
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::~CDIFat, public
+//
+// Synopsis: CDIFat destructor
+//
+// History: 11-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline CDIFat::~CDIFat()
+{
+ msfDebugOut((DEB_ITRACE, "In CDIFat destructor\n"));
+ msfDebugOut((DEB_ITRACE, "Out CDIFat destructor\n"));
+}
+
+#ifndef REF
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::InitCopy, public
+//
+// Synopsis: Init function for copying
+//
+// Arguments: [pfatOld] -- reference to CDIFat to be copied.
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: *Finish This*
+//
+// History: 11-May-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline void CDIFat::InitCopy(CDIFat *pfatOld)
+{
+ msfDebugOut((DEB_ITRACE, "In CDIFat copy constructor\n"));
+
+ _pmsParent = pfatOld->_pmsParent;
+ _cfsTable = pfatOld->_cfsTable;
+
+ _fv.InitCommon(pfatOld->_fv.GetSectBlock(), pfatOld->_fv.GetSectTable());
+ _fv.InitCopy(&pfatOld->_fv);
+
+ msfDebugOut((DEB_ITRACE, "Out CDIFat copy constructor\n"));
+}
+#endif //!REF
+
+inline VOID CDIFat::SectToPair(FSINDEX sect, FSINDEX *pipfs, FSOFFSET *pisect) const
+{
+ msfAssert(sect >= CSECTFAT);
+
+ sect = sect - CSECTFAT;
+ *pipfs = (FSINDEX)(sect / _fv.GetSectTable());
+ *pisect = (FSOFFSET)(sect % _fv.GetSectTable());
+}
+
+inline SECT CDIFat::PairToSect(FSINDEX ipfs, FSOFFSET isect) const
+{
+ return ipfs * _fv.GetSectTable() + isect + CSECTFAT;
+}
+
+
+
+inline void CDIFat::SetParent(CMStream *pms)
+{
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pms);
+ _fv.SetParent(pms);
+}
+
+
+#ifdef DIFAT_LOOKUP_ARRAY
+inline void CDIFat::CacheUnmarkedSect(SECT sectNew,
+ SECT sectMark,
+ SECT sectFree)
+{
+ if (_cUnmarked < DIFAT_ARRAY_SIZE)
+ {
+ _sectUnmarked[_cUnmarked] = sectNew;
+ _sectMarkTo[_cUnmarked] = sectMark;
+ _sectFree[_cUnmarked] = sectFree;
+ }
+ _cUnmarked++;
+}
+#endif
+
+#endif //__DIFAT_HXX__
diff --git a/private/ole32/stg/h/dir.hxx b/private/ole32/stg/h/dir.hxx
new file mode 100644
index 000000000..8e6ef381e
--- /dev/null
+++ b/private/ole32/stg/h/dir.hxx
@@ -0,0 +1,420 @@
+//+-------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dir.hxx
+//
+// Contents: Directory header for Mstream project
+//
+// Classes: CDirEntry - Information on a single stream
+// CDirSect - Sector sized array of DirEntry
+// CDirVector - Resizable array of CDirSect
+// CDirectory - Grouping of DirSectors
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+
+
+
+#include <msf.hxx>
+#include <wchar.h>
+#include <vect.hxx>
+
+
+#ifndef __DIR_HXX__
+#define __DIR_HXX__
+
+#define DIR_HIT 0x01
+
+#ifndef REF
+#if _MSC_VER >= 700
+#pragma pack(1)
+#endif
+#endif //!REF
+
+struct SPreDirEntry
+{
+protected:
+ CDfName _dfn; // Name (word-aligned)
+ BYTE _mse; // STGTY_...
+ BYTE _bflags;
+
+ SID _sidLeftSib; // Siblings
+ SID _sidRightSib; // Siblings
+
+ SID _sidChild; // Storage - Child list
+ GUID _clsId; // Storage - Class id
+ DWORD _dwUserFlags; // Storage - User flags
+ TIME_T _time[2]; // Storage - time stamps
+
+ SECT _sectStart; // Stream - start
+ ULONG _ulSize; // Stream - size
+
+ WORD _dptPropType; // Property - type
+};
+
+#ifndef REF
+#if _MSC_VER >= 700
+#pragma pack()
+#endif
+#endif //!REF
+
+#define STGTY_INVALID 0
+#define STGTY_ROOT 5
+
+// Macros which tell whether a direntry has stream fields,
+// storage fields or property fields
+#define STREAMLIKE(mse) \
+ (((mse) & STGTY_REAL) == STGTY_STREAM || (mse) == STGTY_ROOT)
+#define STORAGELIKE(mse) \
+ (((mse) & STGTY_REAL) == STGTY_STORAGE || (mse) == STGTY_ROOT)
+
+//+----------------------------------------------------------------------
+//
+// Class: CDirEntry (de)
+//
+// Purpose: Holds information on one stream
+//
+// Interface: GetName - returns name of stream
+// GetStart - return first sector for stream
+// GetSize - returns size of stream
+// GetFlags - returns flag byte
+//
+// SetName - sets name
+// SetStart - sets first sector
+// SetSize - sets size
+// SetFlags - sets flag byte
+//
+// IsFree - returns 1 if element is not in use
+// IsEntry - returns 1 is element name matches argument
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 26-May-95 SusiA Added GetAllTimes
+// 22-Noc-95 SusiA Added SetAllTimes
+//
+// Notes: B-flat,C-sharp
+//
+//-----------------------------------------------------------------------
+const CBDIRPAD = DIRENTRYSIZE - sizeof(SPreDirEntry);
+
+// DirEntry bit flags are used for the following private state
+
+// Usage Bit
+
+#define DECOLORBIT 0x01
+#define DERESERVED 0xfe
+
+typedef enum
+{
+ DE_RED = 0,
+ DE_BLACK = 1
+} DECOLOR;
+
+class CDirEntry: private SPreDirEntry
+{
+
+public:
+ DIR_CLASS CDirEntry();
+
+ inline void DIR_CLASS Init(MSENTRYFLAGS mse);
+
+ inline CDfName const * DIR_CLASS GetName(VOID) const;
+ inline SECT DIR_CLASS GetStart(VOID) const;
+ inline ULONG DIR_CLASS GetSize(VOID) const;
+ inline SID DIR_CLASS GetLeftSib(VOID) const;
+ inline SID DIR_CLASS GetRightSib(VOID) const;
+ inline SID DIR_CLASS GetChild(VOID) const;
+ inline MSENTRYFLAGS DIR_CLASS GetFlags(VOID) const;
+ inline DECOLOR DIR_CLASS GetColor(VOID) const;
+ inline TIME_T DIR_CLASS GetTime(WHICHTIME tt) const;
+ inline void DIR_CLASS GetAllTimes(TIME_T *patm, TIME_T *pmtm, TIME_T *pctm);
+ inline void DIR_CLASS SetAllTimes(TIME_T atm, TIME_T mtm, TIME_T ctm);
+ inline GUID DIR_CLASS GetClassId(VOID) const;
+ inline DWORD DIR_CLASS GetUserFlags(VOID) const;
+
+ inline void DIR_CLASS SetName(const CDfName *pdfn);
+ inline void DIR_CLASS SetStart(const SECT);
+ inline void DIR_CLASS SetSize(const ULONG);
+ inline void DIR_CLASS SetLeftSib(const SID);
+ inline void DIR_CLASS SetRightSib(const SID);
+ inline void DIR_CLASS SetChild(const SID);
+ inline void DIR_CLASS SetFlags(const MSENTRYFLAGS mse);
+ inline void DIR_CLASS SetColor(DECOLOR);
+ inline void DIR_CLASS SetTime(WHICHTIME tt, TIME_T nt);
+ inline void DIR_CLASS SetClassId(GUID cls);
+ inline void DIR_CLASS SetUserFlags(DWORD dwUserFlags, DWORD dwMask);
+
+ inline BOOL DIR_CLASS IsFree(VOID) const;
+ inline BOOL DIR_CLASS IsEntry(CDfName const *pdfn) const;
+
+private:
+ inline BYTE DIR_CLASS GetBitFlags(VOID) const;
+ inline void DIR_CLASS SetBitFlags(BYTE bValue, BYTE bMask);
+
+ BYTE _bpad[CBDIRPAD];
+};
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDirSect (ds)
+//
+// Purpose: Provide sector sized block of DirEntries
+//
+// Interface:
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 27-Dec-91 PhilipLa Converted from const size to
+// variable sized sectors.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifndef REF
+#if _MSC_VER == 700
+#pragma warning(disable:4001)
+#elif _MSC_VER >= 800
+#pragma warning(disable:4200)
+#endif
+#endif //!REF
+
+class CDirSect
+{
+public:
+ SCODE DIR_CLASS Init(USHORT cbSector);
+#ifndef REF
+ SCODE DIR_CLASS InitCopy(USHORT cbSector,
+ const CDirSect *pdsOld);
+#endif //!REF
+
+ inline CDirEntry * DIR_CLASS GetEntry(DIROFFSET iEntry);
+
+private:
+ CDirEntry _adeEntry[];
+};
+
+#ifndef REF
+#if _MSC_VER == 700
+#pragma warning(default:4001)
+#elif _MSC_VER >= 800
+#pragma warning(default:4200)
+#endif
+#endif //!REF
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDirVector (dv)
+//
+// Purpose: Provide resizable array of DirSectors.
+//
+// Interface:
+//
+// History: 27-Dec-91 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CDirVector: public CPagedVector
+{
+public:
+ inline DIR_CLASS CDirVector(VOID);
+ inline DIR_CLASS void InitCommon(USHORT cbSector);
+
+ inline SCODE DIR_CLASS GetTable(
+ const DIRINDEX iTable,
+ const DWORD dwFlags,
+ CDirSect **ppds);
+
+private:
+ USHORT _cbSector;
+};
+
+
+inline DIR_CLASS void CDirVector::InitCommon(USHORT cbSector)
+{
+ _cbSector = cbSector;
+}
+
+//+----------------------------------------------------------------------
+//
+// Class: CDirectory (dir)
+//
+// Purpose: Main interface for directory functionality
+//
+// Interface: GetFree - returns an SID for a free DirEntry
+// Find - finds its argument in the directory list
+// SetEntry - sets up a DirEntry and writes out its sector
+// GetName - returns the name of a DirEntry
+// GetStart - returns the start sector of a DirEntry
+// GetSize - returns the size of a DirEntry
+// GetFlags - returns the flag byte of a DirEntry
+//
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 26-Aug-91 PhilipLa Added support for iterators
+// 26-Aug-92 t-chrisy Added init function for
+// corrupted directory object
+// Notes:
+//
+//-----------------------------------------------------------------------
+
+typedef enum DIRENTRYOP
+{
+ DEOP_FIND = 0,
+ DEOP_REMOVE = 1
+} DIRENTRYOP;
+
+class CDirectory
+{
+public:
+ DIR_CLASS CDirectory();
+
+ VOID DIR_CLASS Empty(VOID);
+
+
+ SCODE DIR_CLASS Init(CMStream *pmsParent, DIRINDEX cSect);
+
+#ifndef REF
+#ifdef CHKDSK
+ SCODE DIR_CLASS InitCorrupted(DIRINDEX cSect);
+#endif
+#endif //!REF
+
+ SCODE DIR_CLASS InitNew(CMStream *pmsParent);
+#ifndef REF
+ void DIR_CLASS InitCopy(CDirectory *pdirOld);
+#endif //!REF
+
+ SCODE DIR_CLASS FindGreaterEntry(
+ SID sidChildRoot,
+ CDfName const *pdfn,
+ SID *psidResult);
+
+ SCODE DIR_CLASS SetStart(const SID sid, const SECT sect);
+ SCODE DIR_CLASS SetTime(const SID sid, WHICHTIME tt, TIME_T nt);
+ SCODE DIR_CLASS SetAllTimes(SID const sid, TIME_T atm,TIME_T mtm, TIME_T ctm);
+ SCODE DIR_CLASS SetChild(const SID sid, const SID sidChild);
+ SCODE DIR_CLASS SetSize(const SID sid, const ULONG cbSize);
+ SCODE DIR_CLASS SetClassId(const SID sid, const GUID cls);
+ SCODE DIR_CLASS SetFlags(const SID sid, const MSENTRYFLAGS mse);
+ SCODE DIR_CLASS SetUserFlags(const SID sid,
+ DWORD dwUserFlags,
+ DWORD dwMask);
+
+ inline SCODE DIR_CLASS GetName(const SID sid, CDfName *pdfn);
+ inline SCODE DIR_CLASS GetStart(const SID sid, SECT * psect);
+ inline SCODE DIR_CLASS GetSize(const SID sid, ULONG *pulSize);
+
+ inline SCODE DIR_CLASS GetChild(const SID sid, SID *psid);
+ inline SCODE DIR_CLASS GetFlags(const SID sid, MSENTRYFLAGS *pmse);
+ inline SCODE DIR_CLASS GetClassId(const SID sid, GUID *pcls);
+ inline SCODE DIR_CLASS GetTime(const SID sid, WHICHTIME tt, TIME_T *ptime);
+ inline SCODE DIR_CLASS GetAllTimes(SID const sid, TIME_T *patm,TIME_T *pmtm, TIME_T *pctm);
+ inline SCODE DIR_CLASS GetUserFlags(const SID sid, DWORD *pdwUserFlags);
+
+ SCODE DIR_CLASS GetDirEntry(
+ const SID sid,
+ const DWORD dwFlags,
+ CDirEntry **ppde);
+
+ void DIR_CLASS ReleaseEntry(SID sid);
+
+ SCODE DIR_CLASS CreateEntry(
+ SID sidParent,
+ CDfName const *pdfn,
+ MSENTRYFLAGS mef,
+ SID *psidNew);
+
+ SCODE DIR_CLASS RenameEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ CDfName const *pdfnNew);
+
+ inline SCODE DIR_CLASS IsEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ SEntryBuffer *peb);
+
+ SCODE DIR_CLASS DestroyAllChildren(
+ SID const sidParent);
+
+ SCODE DIR_CLASS DestroyChild(
+ SID const sidParent,
+ CDfName const *pdfn);
+
+ SCODE DIR_CLASS StatEntry(
+ SID const sid,
+ SIterBuffer *pib,
+ STATSTGW *pstatstg);
+
+ inline SCODE DIR_CLASS Flush(VOID);
+
+ inline void DIR_CLASS SetParent(CMStream * pmsParent);
+
+ static int DIR_CLASS NameCompare(
+ CDfName const *pdfn1,
+ CDfName const *pdfn2);
+
+ inline DIRINDEX GetDirLength(void) const;
+
+private:
+
+ CDirVector _dv;
+ DIRINDEX _cdsTable;
+ CBasedMStreamPtr _pmsParent;
+ DIROFFSET _cdeEntries;
+
+ SID _sidFirstFree;
+
+ SCODE DIR_CLASS Resize(DIRINDEX);
+ inline DIRINDEX DIR_CLASS SidToTable(SID sid) const;
+ inline SID DIR_CLASS PairToSid(
+ DIRINDEX iTable,
+ DIROFFSET iEntry) const;
+
+ inline SCODE DIR_CLASS SidToPair(
+ SID sid,
+ DIRINDEX* pipds,
+ DIROFFSET* pide) const;
+
+
+ SCODE DIR_CLASS GetFree(SID * psid);
+
+ SCODE DIR_CLASS InsertEntry(
+ SID sidParent,
+ SID sidInsert,
+ CDfName const *pdfnInsert);
+
+ SCODE DIR_CLASS FindEntry(
+ SID sidParent,
+ CDfName const *pdfnFind,
+ DIRENTRYOP deop,
+ SEntryBuffer *peb);
+
+ SCODE SplitEntry(
+ CDfName const *pdfn,
+ SID sidTree,
+ SID sidGreat,
+ SID sidGrand,
+ SID sidParent,
+ SID sidChild,
+ SID *psid);
+
+ SCODE RotateEntry(
+ CDfName const *pdfn,
+ SID sidTree,
+ SID sidParent,
+ SID *psid);
+
+ SCODE DIR_CLASS SetColorBlack(const SID sid);
+};
+
+#endif //__DIR_HXX__
diff --git a/private/ole32/stg/h/dirfunc.hxx b/private/ole32/stg/h/dirfunc.hxx
new file mode 100644
index 000000000..581f6cb0a
--- /dev/null
+++ b/private/ole32/stg/h/dirfunc.hxx
@@ -0,0 +1,524 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dirfunc.hxx
+//
+// Contents: Inline functions for Directory code
+//
+// Classes:
+//
+// Functions:
+//
+// History: 28-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DIRFUNC_HXX__
+#define __DIRFUNC_HXX__
+
+#include <page.hxx>
+
+
+inline void DIR_CLASS CDirEntry::Init(MSENTRYFLAGS mse)
+{
+ msfAssert(sizeof(CDirEntry) == DIRENTRYSIZE);
+
+ msfAssert(mse <= 0xff);
+ _mse = (BYTE) mse;
+ _bflags = 0;
+
+ _dfn.Set((WORD)0, (BYTE *)NULL);
+ _sidLeftSib = _sidRightSib = _sidChild = NOSTREAM;
+
+ if (STORAGELIKE(_mse))
+ {
+ _clsId = IID_NULL;
+ _dwUserFlags = 0;
+ }
+ if (STREAMLIKE(_mse))
+ {
+ _sectStart = ENDOFCHAIN;
+ _ulSize = 0;
+ }
+}
+
+inline BOOL DIR_CLASS CDirEntry::IsFree(VOID) const
+{
+ return _mse == 0;
+}
+
+inline BOOL DIR_CLASS CDirEntry::IsEntry(CDfName const * pdfn) const
+{
+ return !IsFree() && pdfn->IsEqual(&_dfn);
+}
+
+
+inline void DIR_CLASS CDirEntry::SetLeftSib(const SID sid)
+{
+ _sidLeftSib = sid;
+}
+
+inline void DIR_CLASS CDirEntry::SetRightSib(const SID sid)
+{
+ _sidRightSib = sid;
+}
+
+
+inline void DIR_CLASS CDirEntry::SetChild(const SID sid)
+{
+ _sidChild = sid;
+}
+
+inline void DIR_CLASS CDirEntry::SetName(const CDfName *pdfn)
+{
+ _dfn.Set(pdfn->GetLength(), pdfn->GetBuffer());
+}
+
+inline void DIR_CLASS CDirEntry::SetStart(const SECT sect)
+{
+ msfAssert(STREAMLIKE(_mse));
+ _sectStart=sect;
+}
+
+inline void DIR_CLASS CDirEntry::SetSize(const ULONG ulSize)
+{
+ msfAssert(STREAMLIKE(_mse));
+ _ulSize=ulSize;
+}
+
+inline void DIR_CLASS CDirEntry::SetFlags(const MSENTRYFLAGS mse)
+{
+ msfAssert(mse <= 0xff);
+ _mse = (const BYTE) mse;
+}
+
+inline void DIR_CLASS CDirEntry::SetBitFlags(BYTE bValue, BYTE bMask)
+{
+ _bflags = (_bflags & ~bMask) | (bValue & bMask);
+}
+
+inline void DIR_CLASS CDirEntry::SetColor(DECOLOR color)
+{
+ SetBitFlags(color, DECOLORBIT);
+}
+
+inline void DIR_CLASS CDirEntry::SetTime(WHICHTIME tt, TIME_T nt)
+{
+ msfAssert((tt == WT_CREATION) || (tt == WT_MODIFICATION));
+ _time[tt] = nt;
+}
+inline void DIR_CLASS CDirEntry::SetAllTimes(TIME_T atm, TIME_T mtm, TIME_T ctm)
+{
+
+ _time[WT_MODIFICATION] = mtm;
+ _time[WT_CREATION] = ctm;
+}
+
+inline void DIR_CLASS CDirEntry::SetClassId(GUID cls)
+{
+ msfAssert(STORAGELIKE(_mse));
+ _clsId = cls;
+}
+
+inline void DIR_CLASS CDirEntry::SetUserFlags(DWORD dwUserFlags, DWORD dwMask)
+{
+ msfAssert(STORAGELIKE(_mse));
+ _dwUserFlags = (_dwUserFlags & ~dwMask) | (dwUserFlags & dwMask);
+}
+
+inline SID DIR_CLASS CDirEntry::GetLeftSib(VOID) const
+{
+ return _sidLeftSib;
+}
+
+inline SID DIR_CLASS CDirEntry::GetRightSib(VOID) const
+{
+ return _sidRightSib;
+}
+
+
+inline SID DIR_CLASS CDirEntry::GetChild(VOID) const
+{
+ return _sidChild;
+}
+
+inline GUID DIR_CLASS CDirEntry::GetClassId(VOID) const
+{
+ msfAssert(STORAGELIKE(_mse));
+ return _clsId;
+}
+
+inline CDfName const * DIR_CLASS CDirEntry::GetName(VOID) const
+{
+ return &_dfn;
+}
+
+inline SECT DIR_CLASS CDirEntry::GetStart(VOID) const
+{
+ msfAssert(STREAMLIKE(_mse));
+ return _sectStart;
+}
+
+inline ULONG DIR_CLASS CDirEntry::GetSize(VOID) const
+{
+ msfAssert(STREAMLIKE(_mse));
+ return _ulSize;
+}
+
+inline MSENTRYFLAGS DIR_CLASS CDirEntry::GetFlags(VOID) const
+{
+ return (MSENTRYFLAGS) _mse;
+}
+
+inline BYTE DIR_CLASS CDirEntry::GetBitFlags(VOID) const
+{
+ return _bflags;
+}
+
+inline DECOLOR DIR_CLASS CDirEntry::GetColor(VOID) const
+{
+ return((DECOLOR) (GetBitFlags() & DECOLORBIT));
+}
+
+inline TIME_T DIR_CLASS CDirEntry::GetTime(WHICHTIME tt) const
+{
+ msfAssert((tt == WT_CREATION) || (tt == WT_MODIFICATION));
+ return _time[tt];
+}
+inline void DIR_CLASS CDirEntry::GetAllTimes(TIME_T *patm, TIME_T *pmtm, TIME_T *pctm)
+{
+
+ *patm = *pmtm = _time[WT_MODIFICATION];
+ *pctm = _time[WT_CREATION];
+}
+
+inline DWORD DIR_CLASS CDirEntry::GetUserFlags(VOID) const
+{
+ msfAssert(STORAGELIKE(_mse));
+ return _dwUserFlags;
+}
+
+inline CDirEntry * DIR_CLASS CDirSect::GetEntry(DIROFFSET iEntry)
+{
+ return &(_adeEntry[iEntry]);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirVector::CDirVector, public
+//
+// Synopsis: Default constructor
+//
+// History: 20-Apr-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline DIR_CLASS CDirVector::CDirVector()
+ : CPagedVector(SIDDIR)
+{
+ _cbSector = 0;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirVector::GetTable, public
+//
+// Synopsis: Return a pointer to a DirSect for the given index
+// into the vector.
+//
+// Arguments: [iTable] -- index into vector
+//
+// Returns: Pointer to CDirSect indicated by index
+//
+// History: 27-Dec-91 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline SCODE DIR_CLASS CDirVector::GetTable(
+ const DIRINDEX iTable,
+ const DWORD dwFlags,
+ CDirSect **ppds)
+{
+ SCODE sc;
+
+ sc = CPagedVector::GetTable(iTable, dwFlags, (void **)ppds);
+
+ if (sc == STG_S_NEWPAGE)
+ {
+ (*ppds)->Init(_cbSector);
+ }
+ return sc;
+}
+
+inline DIRINDEX DIR_CLASS CDirectory::SidToTable(SID sid) const
+{
+ return (DIRINDEX)(sid / _cdeEntries);
+}
+
+inline SCODE DIR_CLASS CDirectory::GetName(const SID sid, CDfName *pdfn)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ *pdfn = *(CDfName *)pde->GetName();
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::GetStart, public
+//
+// Synposis: Retrieves the starting sector of a directory entry
+//
+// Arguments: [sid] -- Stream ID of stream in question
+//
+// Returns: Starting sector of stream
+//
+// Algorithm: Return the starting sector of the stream. If the
+// identifier is SIDFAT, return 0. If the identifier
+// is SIDDIR, return 1. Otherwise, return the starting
+// sector of the entry in question.
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 15-May-92 AlexT Made inline, restricted sid.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+inline SCODE DIR_CLASS CDirectory::GetStart(const SID sid, SECT *psect)
+{
+ msfAssert(sid <= MAXREGSID);
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ *psect = pde->GetStart();
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_GetSize)
+#endif
+
+inline SCODE DIR_CLASS CDirectory::GetSize(
+ const SID sid,
+ ULONG * pulSize)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+
+ *pulSize = pde->GetSize();
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_GetChild)
+#endif
+
+inline SCODE DIR_CLASS CDirectory::GetChild(const SID sid, SID * psid)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ *psid = pde->GetChild();
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+inline SCODE DIR_CLASS CDirectory::GetFlags(
+ const SID sid,
+ MSENTRYFLAGS *pmse)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ *pmse = pde->GetFlags();
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_GetClassId)
+#endif
+
+inline SCODE DIR_CLASS CDirectory::GetClassId(const SID sid, GUID *pcls)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ *pcls = pde->GetClassId();
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_GetUserFlags)
+#endif
+
+inline SCODE DIR_CLASS CDirectory::GetUserFlags(const SID sid,
+ DWORD *pdwUserFlags)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ *pdwUserFlags = pde->GetUserFlags();
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_GetTime)
+#endif
+
+inline SCODE DIR_CLASS CDirectory::GetTime(
+ const SID sid,
+ WHICHTIME tt,
+ TIME_T *ptime)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ *ptime = pde->GetTime(tt == WT_ACCESS ? WT_MODIFICATION : tt);
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_GetAllTimes)
+#endif
+
+inline SCODE DIR_CLASS CDirectory::GetAllTimes(
+ const SID sid,
+ TIME_T *patm,
+ TIME_T *pmtm,
+ TIME_T *pctm)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ pde->GetAllTimes(patm, pmtm, pctm);
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+inline SID DIR_CLASS CDirectory::PairToSid(
+ DIRINDEX iTable,
+ DIROFFSET iEntry) const
+{
+ return (SID)((iTable * _cdeEntries) + iEntry);
+}
+
+inline SCODE DIR_CLASS CDirectory::SidToPair(
+ SID sid,
+ DIRINDEX* pipds,
+ DIROFFSET* pide) const
+{
+ *pipds = (DIRINDEX)(sid / _cdeEntries);
+ *pide = (DIROFFSET)(sid % _cdeEntries);
+ return S_OK;
+}
+
+inline void DIR_CLASS CDirectory::SetParent(CMStream *pms)
+{
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pms);
+ _dv.SetParent(pms);
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_IsEntry)
+#endif
+
+inline SCODE DIR_CLASS CDirectory::IsEntry(SID const sidParent,
+ CDfName const *pdfn,
+ SEntryBuffer *peb)
+{
+ return FindEntry(sidParent, pdfn, DEOP_FIND, peb);
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectory::Flush, private
+//
+// Synopsis: Write a dirsector out to the parent
+//
+// Arguments: [sid] -- SID of modified dirEntry
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Convert SID into table number, then write that
+// table out to the parent Multistream
+//
+// History: 18-Feb-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline SCODE DIR_CLASS CDirectory::Flush(VOID)
+{
+ return _dv.Flush();
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirectory::GetDirLength, public
+//
+// Synopsis: Return the length of the directory chain in sectors
+//
+// Arguments: None.
+//
+// Returns: Length of directory chain in sectors
+//
+// History: 01-Jun-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline DIRINDEX CDirectory::GetDirLength(void) const
+{
+ return _cdsTable;
+}
+
+#endif // #ifndef __DIRFUNC_HXX__
diff --git a/private/ole32/stg/h/dl.hxx b/private/ole32/stg/h/dl.hxx
new file mode 100644
index 000000000..a9067ba81
--- /dev/null
+++ b/private/ole32/stg/h/dl.hxx
@@ -0,0 +1,385 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dl.hxx
+//
+// Contents: Delta list headers for streams
+//
+// Classes: SDeltaBlock
+// CDeltaList
+//
+// History: 28-Jul-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __DL_HXX__
+#define __DL_HXX__
+
+#define DL_GET 0
+#define DL_CREATE 1
+#define DL_READ 2
+
+class CTransactedStream;
+SAFE_DFBASED_PTR(CBasedTransactedStreamPtr, CTransactedStream);
+
+#define CBITPERUSHORT 16
+
+//+-------------------------------------------------------------------------
+//
+// Class: SDeltaBlock (db)
+//
+// Purpose: A single block of delta list entries.
+//
+// Interface:
+//
+// History: 10-Jul-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+struct SDeltaBlock
+{
+public:
+#ifndef _MAC
+ inline
+#endif
+ SDeltaBlock();
+
+#ifndef _MAC
+ inline
+#endif
+ void *operator new(size_t size, IMalloc * const pMalloc);
+
+ inline const BOOL IsOwned(const USHORT uOffset);
+ inline void MakeOwned(const USHORT uOffset);
+
+ SECT _sect[CSECTPERBLOCK];
+ USHORT _fOwn[(CSECTPERBLOCK / CBITPERUSHORT)];
+};
+SAFE_DFBASED_PTR(CBasedDeltaBlockPtr, SDeltaBlock);
+SAFE_DFBASED_PTR(CBasedDeltaBlockPtrPtr, CBasedDeltaBlockPtr);
+
+
+inline const BOOL SDeltaBlock::IsOwned(const USHORT uOffset)
+{
+ msfAssert(uOffset < CSECTPERBLOCK);
+ return (_fOwn[uOffset / CBITPERUSHORT] &
+ (1 << (uOffset % CBITPERUSHORT))) != 0;
+}
+
+inline void SDeltaBlock::MakeOwned(const USHORT uOffset)
+{
+ msfAssert(uOffset < CSECTPERBLOCK);
+ msfAssert(!IsOwned(uOffset));
+ msfAssert((uOffset / CBITPERUSHORT) < (CSECTPERBLOCK / CBITPERUSHORT));
+
+ _fOwn[uOffset / CBITPERUSHORT] |= (1 << (uOffset % CBITPERUSHORT));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDeltaList (dl)
+//
+// Purpose: Delta list for transacted streans.
+//
+// Interface:
+//
+// History: 21-Jan-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CDeltaList
+{
+public:
+#ifdef USE_NOSCRATCH
+ CDeltaList(CMStream *pms, CMStream *pmsScratch);
+#else
+ CDeltaList(CMStream *pmsScratch);
+#endif
+
+ SCODE Init(ULONG ulSize, CTransactedStream *ptsParent);
+ SCODE InitResize(ULONG ulSize);
+
+ ~CDeltaList();
+
+ SCODE GetMap(SECT sectOld, const DWORD dwFlags, SECT *psectRet);
+
+ void BeginCommit(CTransactedStream *ptsParent);
+ void EndCommit(CDeltaList *pdlNew, DFLAGS df);
+
+ inline ILockBytes *GetDataILB(void);
+ inline ILockBytes *GetControlILB(void);
+
+ inline CFat * GetDataFat(void);
+ inline CFat * GetControlFat(void);
+
+ inline USHORT GetDataSectorSize(void);
+ inline USHORT GetDataSectorShift(void);
+
+ inline USHORT GetControlSectorSize(void);
+
+ void Empty(void);
+
+ inline BOOL IsEmpty(void);
+ inline BOOL IsInMemory(void);
+ inline BOOL IsInStream(void);
+
+#ifdef USE_NOSCRATCH
+ inline BOOL IsNoScratch(void);
+#endif
+
+ SCODE IsOwned(SECT sect, SECT sectMap, BOOL *fOwn);
+
+
+private:
+ CBasedDeltaBlockPtrPtr _apdb;
+ ULONG _ulSize;
+
+ CBasedMStreamPtr _pmsScratch;
+
+#ifdef USE_NOSCRATCH
+ CBasedMStreamPtr _pms;
+#endif
+
+ CBasedTransactedStreamPtr _ptsParent;
+ SECT _sectStart;
+
+ SCODE InitStreamBlock(ULONG ul);
+
+ SCODE ReadMap(SECT *psectStart, SECT sect, SECT *psectRet);
+ SCODE WriteMap(SECT *psectStart, SECT sect, SECT sectMap);
+
+ void FreeStream(SECT sectStart, ULONG ulSize);
+
+ SCODE FindOffset(
+ SECT *psectStart,
+ SECT sect,
+ ULARGE_INTEGER *pulRet,
+ BOOL fWrite);
+
+ SCODE DumpList(void);
+
+#if DBG == 1
+ void PrintList(void);
+#endif
+
+ void ReleaseBlock(ULONG oBlock);
+
+ inline CBasedDeltaBlockPtr * GetNewDeltaArray(ULONG ulSize);
+};
+SAFE_DFBASED_PTR(CBasedDeltaListPtr, CDeltaList);
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDeltaList::GetDataILB, public
+//
+// Synopsis: Return pointer to ILockBytes for storing data
+//
+// History: 10-Jul-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline ILockBytes * CDeltaList::GetDataILB(void)
+{
+#ifdef USE_NOSCRATCH
+ if (_pms)
+ return _pms->GetILB();
+ else
+#endif
+ return _pmsScratch->GetILB();
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDeltaList::GetControlILB, public
+//
+// Synopsis: Return pointer to ILockBytes for storing control information
+//
+// History: 10-Jul-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline ILockBytes * CDeltaList::GetControlILB(void)
+{
+ return _pmsScratch->GetILB();
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDeltaList::GetDataFat, public
+//
+// Synopsis: Return pointer to fat to use for storing stream data
+//
+// History: 10-Jul-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline CFat * CDeltaList::GetDataFat(void)
+{
+#ifdef USE_NOSCRATCH
+ if (_pms)
+ return _pmsScratch->GetMiniFat();
+ else
+#endif
+ return _pmsScratch->GetFat();
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDeltaList::GetControlFat, public
+//
+// Synopsis: Return pointer to fat to use for storing control information
+//
+// History: 10-Jul-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline CFat * CDeltaList::GetControlFat(void)
+{
+ return _pmsScratch->GetFat();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDeltaList::GetDataSectorSize, public
+//
+// Synopsis: Return sector size for storing stream data
+//
+// History: 10-Jul-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline USHORT CDeltaList::GetDataSectorSize(void)
+{
+#ifdef USE_NOSCRATCH
+ if (_pms)
+ return _pms->GetSectorSize();
+ else
+ return _pmsScratch->GetSectorSize();
+#else
+ return SCRATCHSECTORSIZE;
+#endif
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDeltaList::GetDataSectorShift, public
+//
+// Synopsis: Return sector size for storing stream data
+//
+// History: 10-Jul-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline USHORT CDeltaList::GetDataSectorShift(void)
+{
+#ifdef USE_NOSCRATCH
+ if (_pms)
+ return _pms->GetSectorShift();
+ else
+ return _pmsScratch->GetSectorShift();
+#else
+ return SCRATCHSECTORSHIFT;
+#endif
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDeltaList::GetControlSectorSize, public
+//
+// Synopsis: Return sector size for storing control information
+//
+// History: 10-Jul-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline USHORT CDeltaList::GetControlSectorSize(void)
+{
+#ifdef USE_NOSCRATCH
+ return _pmsScratch->GetSectorSize();
+#else
+ return SCRATCHSECTORSIZE;
+#endif
+}
+
+#ifdef USE_NOSCRATCH
+//+---------------------------------------------------------------------------
+//
+// Member: CDeltaList::IsNoScratch, public
+//
+// Synopsis: Return TRUE if the delta list is in no-scratch mode
+//
+// Arguments: None.
+//
+// History: 19-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CDeltaList::IsNoScratch(void)
+{
+ return (_pms != NULL);
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDeltaList::IsEmpty, public
+//
+// Synopsis: Return TRUE if the delta list contains no changes.
+//
+// Arguments: None.
+//
+// History: 19-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CDeltaList::IsEmpty(void)
+{
+ return ((_apdb == NULL) && (_sectStart == ENDOFCHAIN));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDeltaList::IsInMemory, public
+//
+// Synopsis: Return TRUE if the delta list is in memory
+//
+// Arguments: None.
+//
+// History: 19-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CDeltaList::IsInMemory(void)
+{
+ return (_apdb != NULL);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDeltaList::IsInStream, public
+//
+// Synopsis: Return TRUE if the delta list is in a stream
+//
+// Arguments: None.
+//
+// History: 19-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CDeltaList::IsInStream(void)
+{
+ return ((_apdb == NULL) && (_sectStart != ENDOFCHAIN));
+}
+
+#endif //__DL_HXX__
diff --git a/private/ole32/stg/h/docfilep.hxx b/private/ole32/stg/h/docfilep.hxx
new file mode 100644
index 000000000..33142c946
--- /dev/null
+++ b/private/ole32/stg/h/docfilep.hxx
@@ -0,0 +1,278 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: docfilep.hxx
+//
+// Contents: Private DocFile definitions
+//
+// History: 15-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __DOCFILEP_HXX__
+#define __DOCFILEP_HXX__
+
+#include <dfbasis.hxx>
+#include <context.hxx>
+
+
+// Set/clear basis access
+#define SetBasisAccess(pdfb, ppc) ((pdfb)->SetAccess(ppc))
+#define ClearBasisAccess(pdfb) ((pdfb)->ClearAccess())
+
+// Set access for the basis with optimization if semaphoring
+// is not important
+#define SetDifferentBasisAccess(pdfb, ppc) SetBasisAccess(pdfb, ppc)
+
+// Optimal set/clear access for targets
+// Read and Write cases could be combined but this would limit
+// future flexibility if they ever need to be treated differently
+// Assumes _pdfb and _ppc exist
+#define SetReadAccess() SetDifferentBasisAccess(_pdfb, _ppc)
+#define SetWriteAccess() SetDifferentBasisAccess(_pdfb, _ppc)
+
+#define ClearReadAccess() ClearBasisAccess(_pdfb)
+#define ClearWriteAccess() ClearBasisAccess(_pdfb)
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSafeAccess (sa)
+//
+// Purpose: Safe class for Set/ClearAccess
+//
+// History: 19-Oct-93 DrewB Created
+//
+// Notes: Only one class since read/write access are currently the
+// same. Because of the macros, this can easily be changed
+// if necessary
+//
+//----------------------------------------------------------------------------
+
+#if WIN32 == 300
+class CSafeAccess INHERIT_UNWIND_IF_CAIRO
+{
+ DECLARE_UNWIND
+#else
+class CSafeAccess
+{
+#endif
+public:
+ CSafeAccess(CDFBasis *pdfb, CPerContext *ppc)
+ {
+ _pdfb = pdfb;
+ _ppc = ppc;
+ _fAccess = FALSE;
+#if WIN32 == 300
+ END_CONSTRUCTION(CSafeAccess);
+#endif
+ }
+#ifdef MULTIHEAP
+ // When the constructor for CSafeAccess is invoked,
+ // the base pointer may be invalid, so we set the
+ // CDFBasis pointer when reading or writing
+ void Read(CDFBasis *pdfb)
+ {
+ _pdfb = pdfb;
+ SetDifferentBasisAccess(_pdfb, _ppc);
+ _fAccess = TRUE;
+ }
+ void Write(CDFBasis *pdfb)
+ {
+ _pdfb = pdfb;
+ SetDifferentBasisAccess(_pdfb, _ppc);
+ _fAccess = TRUE;
+ }
+#else
+ void Read(void)
+ {
+ SetDifferentBasisAccess(_pdfb, _ppc);
+ _fAccess = TRUE;
+ }
+ void Write(void)
+ {
+ SetDifferentBasisAccess(_pdfb, _ppc);
+ _fAccess = TRUE;
+ }
+#endif
+ ~CSafeAccess(void)
+ {
+ if (_fAccess)
+ ClearBasisAccess(_pdfb);
+ }
+
+private:
+ CDFBasis *_pdfb;
+ CPerContext *_ppc;
+ BOOL _fAccess;
+};
+
+#ifdef MULTIHEAP
+#define SAFE_ACCESS CSafeAccess _sa(NULL, _ppc)
+#define SafeReadAccess() _sa.Read(BP_TO_P(CDFBasis *, _pdfb))
+#define SafeWriteAccess() _sa.Write(BP_TO_P(CDFBasis *, _pdfb))
+#else
+#define SAFE_ACCESS CSafeAccess _sa(BP_TO_P(CDFBasis *, _pdfb), _ppc)
+#define SafeReadAccess() _sa.Read()
+#define SafeWriteAccess() _sa.Write()
+#endif
+
+
+#define TakeSem() _ppc->TakeSem(DFM_TIMEOUT)
+#define ReleaseSem(sc) if (SUCCEEDED(sc)) _ppc->ReleaseSem(); else 1
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSafeSem (ss)
+//
+// Purpose: Safe class for holding the access semaphore
+//
+// History: 19-Oct-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#if WIN32 == 300
+class CSafeSem INHERIT_UNWIND_IF_CAIRO
+{
+ DECLARE_UNWIND
+#else
+class CSafeSem
+{
+#endif
+public:
+ CSafeSem(CPerContext *ppc)
+ {
+ _sc = STG_E_INUSE;
+ _ppc = ppc;
+#ifdef MULTIHEAP
+ _ppcPrev = NULL;
+ _pSmAllocator = NULL;
+#endif
+#if WIN32 == 300
+ END_CONSTRUCTION(CSafeSem);
+#endif
+ }
+ SCODE Take(void)
+ {
+#ifdef MULTIHEAP
+ _sc = TakeSem();
+ _pSmAllocator = &g_smAllocator;
+ _ppc->SetAllocatorState (&_ppcPrev, _pSmAllocator);
+ return _sc;
+#else
+ return _sc = TakeSem();
+#endif
+ }
+ void Release(void)
+ {
+#ifdef MULTIHEAP
+ if (_pSmAllocator != NULL)
+ {
+ if (_ppcPrev != NULL)
+ _ppcPrev->SetAllocatorState(NULL, _pSmAllocator);
+ else
+ _pSmAllocator->SetState(NULL, NULL, 0, NULL, NULL);
+ _pSmAllocator = NULL;
+ }
+#endif
+ ReleaseSem(_sc);
+ _sc = STG_E_INUSE;
+ }
+
+ ~CSafeSem(void)
+ {
+ Release();
+ }
+
+private:
+ SCODE _sc;
+ CPerContext *_ppc;
+#ifdef MULTIHEAP
+ CPerContext *_ppcPrev;
+ CSmAllocator *_pSmAllocator;
+#endif
+};
+
+#define SAFE_SEM CSafeSem _ss(_ppc)
+#define TakeSafeSem() _ss.Take()
+#define ReleaseSafeSem() _ss.Release()
+
+
+#define CWCMAXPATHCOMPLEN CWCSTREAMNAME
+#define CBMAXPATHCOMPLEN (CWCMAXPATHCOMPLEN*sizeof(WCHAR))
+
+// Common bundles of STGM flags
+#define STGM_RDWR (STGM_READ | STGM_WRITE | STGM_READWRITE)
+#define STGM_DENY (STGM_SHARE_DENY_NONE | STGM_SHARE_DENY_READ | \
+ STGM_SHARE_DENY_WRITE | STGM_SHARE_EXCLUSIVE)
+
+#define FLUSH_CACHE(cf) \
+ ((cf & STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE) == 0)
+
+#define VerifyIfThere(it) \
+ (((it) == STG_FAILIFTHERE || (it) == STG_CREATEIFTHERE || \
+ (it) == STG_CONVERTIFTHERE) ? S_OK : STG_E_INVALIDFLAG)
+
+#define VerifyCommitFlags(cf) \
+ ((((cf) & ~(STGC_OVERWRITE | STGC_ONLYIFCURRENT | \
+ STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE)) == 0) ? S_OK : \
+ STG_E_INVALIDFLAG)
+
+#define VerifyLockType(lt) \
+ (((lt) == LOCK_WRITE || (lt) == LOCK_EXCLUSIVE || \
+ (lt) == LOCK_ONLYONCE) ? S_OK : STG_E_INVALIDFLAG)
+
+// Cairo only
+#if WIN32 == 300
+#define VerifyStgFmt(sf) \
+ (((sf) == STGFMT_DOCUMENT || (sf) == STGFMT_DIRECTORY || \
+ (sf) == STGFMT_CATALOG || (sf) == STGFMT_FILE) ? S_OK : \
+ STG_E_INVALIDFLAG)
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Function: VerifyStatFlag
+//
+// Synopsis: verify Stat flag
+//
+// Arguments: [grfStatFlag] - stat flag
+//
+// Returns: S_OK or STG_E_INVALIDFLAG
+//
+// History: 10-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+inline SCODE VerifyStatFlag(DWORD grfStatFlag)
+{
+ SCODE sc = S_OK;
+ if ((grfStatFlag & ~STATFLAG_NONAME) != 0)
+ sc = STG_E_INVALIDFLAG;
+ return(sc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: VerifyMoveFlags
+//
+// Synopsis: verify Move flag
+//
+// Arguments: [grfMoveFlag] - stat flag
+//
+// Returns: S_OK or STG_E_INVALIDFLAG
+//
+// History: 10-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+inline SCODE VerifyMoveFlags(DWORD grfMoveFlag)
+{
+ SCODE sc = S_OK;
+ if ((grfMoveFlag & ~STGMOVE_COPY) != 0)
+ sc = STG_E_INVALIDFLAG;
+ return(sc);
+}
+
+#endif
diff --git a/private/ole32/stg/h/entry.hxx b/private/ole32/stg/h/entry.hxx
new file mode 100644
index 000000000..b50cdb68e
--- /dev/null
+++ b/private/ole32/stg/h/entry.hxx
@@ -0,0 +1,249 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: entry.hxx
+//
+// Contents: Entry management classes
+//
+// Classes: PBasicEntry
+// PTimeEntry
+// CTransactedBasicEntry
+// CTransactedTimeEntry
+//
+// History: 27-Jul-92 DrewB Created
+// 10-Apr-95 HenryLee Added global LUID optimization
+//
+//---------------------------------------------------------------
+
+#ifndef __ENTRY_HXX__
+#define __ENTRY_HXX__
+
+#include <msf.hxx>
+#if WIN32 >= 100
+#include <df32.hxx>
+#endif
+
+//+--------------------------------------------------------------
+//
+// Class: PBasicEntry (en)
+//
+// Purpose: Entry management
+//
+// Interface: See below
+//
+// History: 27-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#define ROOT_LUID 1
+#define MINISTREAM_LUID 2
+#define ITERATOR_LUID 3
+#define LUID_BASE 4
+
+class PBasicEntry
+{
+public:
+ inline DFLUID GetLuid(void);
+
+#ifndef FLAT
+ static inline DFLUID GetNewLuid(void);
+#else
+ static DFLUID GetNewLuid(const IMalloc *pMalloc);
+#endif
+
+protected:
+ PBasicEntry(DFLUID dl);
+
+private:
+#ifndef FLAT
+ static DFLUID _dlBase;
+#endif
+ const DFLUID _dl;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: PBasicEntry::GetNewLuid, public
+//
+// Synopsis: Returns a new luid
+//
+// History: 21-Oct-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+#ifndef FLAT
+inline DFLUID PBasicEntry::GetNewLuid(void)
+{
+ DFLUID dl = _dlBase;
+ AtomicInc((long *)&_dlBase);
+ return dl;
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: PBasicEntry::PBasicEntry, protected
+//
+// Synopsis: Constructor, sets luid
+//
+// History: 21-Oct-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline PBasicEntry::PBasicEntry(DFLUID dl)
+: _dl(dl)
+{
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PBasicEntry::GetLuid, public
+//
+// Synopsis: Returns the luid
+//
+// History: 21-Oct-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline DFLUID PBasicEntry::GetLuid(void)
+{
+ return _dl;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Class: PTimeEntry
+//
+// Purpose: A basic entry plus timestamps
+//
+// Interface: See below
+//
+// History: 01-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class PTimeEntry : public PBasicEntry
+{
+public:
+ virtual SCODE GetTime(WHICHTIME wt, TIME_T *ptm) = 0;
+ virtual SCODE SetTime(WHICHTIME wt, TIME_T tm) = 0;
+ virtual SCODE GetAllTimes(TIME_T *patm, TIME_T *pmtm, TIME_T *pctm) = 0;
+ virtual SCODE SetAllTimes(TIME_T atm, TIME_T mtm, TIME_T ctm) = 0;
+
+ SCODE CopyTimesFrom(PTimeEntry *penFrom);
+
+protected:
+ inline PTimeEntry(DFLUID luid);
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: PTimeEntry::PTimeEntry, protected
+//
+// Synopsis: Constructor
+//
+// Arguments: [luid] - LUID
+//
+// History: 01-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline PTimeEntry::PTimeEntry(DFLUID luid)
+ : PBasicEntry(luid)
+{
+}
+
+//+---------------------------------------------------------------------------
+//
+// Class: CTransactedTimeEntry (tten)
+//
+// Purpose: Transacted time entry management
+//
+// Interface: See below
+//
+// History: 01-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#define CTIMES 3
+
+class CTransactedTimeEntry
+{
+public:
+ inline void GetTime(WHICHTIME wt, TIME_T *ptm);
+ inline void SetTime(WHICHTIME wt, TIME_T tm);
+ inline void GetAllTimes(TIME_T *patm, TIME_T *pmtm,TIME_T *pctm);
+ inline void SetAllTimes(TIME_T atm, TIME_T mtm,TIME_T ctm);
+private:
+ TIME_T _tt[CTIMES];
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedTimeEntry::GetTime, public
+//
+// Synopsis: Returns the time
+//
+// History: 28-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CTransactedTimeEntry::GetTime(WHICHTIME wt, TIME_T *ptm)
+{
+ msfAssert(wt >= 0 && wt < CTIMES);
+ *ptm = _tt[wt];
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedTimeEntry::GetAllTimes, public
+//
+// Synopsis: Returns all the times
+//
+// History: 26-May-95 SusiA Created
+//
+//---------------------------------------------------------------
+
+inline void CTransactedTimeEntry::GetAllTimes(TIME_T *patm,TIME_T *pmtm, TIME_T *pctm)
+{
+ *patm = _tt[WT_ACCESS];
+ *pmtm = _tt[WT_MODIFICATION];
+ *pctm = _tt[WT_CREATION];
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedTimeEntry::SetAllTimes, public
+//
+// Synopsis: Sets all the times
+//
+// History: 26-Nov-95 SusiA Created
+//
+//---------------------------------------------------------------
+
+inline void CTransactedTimeEntry::SetAllTimes(TIME_T atm,TIME_T mtm, TIME_T ctm)
+{
+ _tt[WT_ACCESS] = atm;
+ _tt[WT_MODIFICATION] = mtm;
+ _tt[WT_CREATION] = ctm;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedTimeEntry::SetTime, public
+//
+// Synopsis: Sets the time
+//
+// History: 28-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CTransactedTimeEntry::SetTime(WHICHTIME wt, TIME_T tm)
+{
+ msfAssert(wt >= 0 && wt < CTIMES);
+ _tt[wt] = tm;
+}
+
+#endif // #ifndef __ENTRY_HXX__
diff --git a/private/ole32/stg/h/error.hxx b/private/ole32/stg/h/error.hxx
new file mode 100644
index 000000000..b4e12052c
--- /dev/null
+++ b/private/ole32/stg/h/error.hxx
@@ -0,0 +1,33 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992
+//
+// File: error.hxx
+//
+// Contents: Error code handler routines
+//
+// History: 19-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __ERROR_HXX__
+#define __ERROR_HXX__
+
+#if DBG == 1
+#define ErrJmp(comp, label, errval, var) \
+{\
+ var = errval;\
+ comp##DebugOut((DEB_IERROR, "Error %lX at %s:%d\n",\
+ (unsigned long)var, __FILE__, __LINE__));\
+ goto label;\
+}
+#else
+#define ErrJmp(comp, label, errval, var) \
+{\
+ var = errval;\
+ goto label;\
+}
+#endif
+
+#endif // #ifndef __ERROR_HXX__
diff --git a/private/ole32/stg/h/fat.hxx b/private/ole32/stg/h/fat.hxx
new file mode 100644
index 000000000..d02483117
--- /dev/null
+++ b/private/ole32/stg/h/fat.hxx
@@ -0,0 +1,705 @@
+//+-------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: fat.hxx
+//
+// Contents: Header file for fat classes
+//
+// Classes: CFatSect - sector sized array of sector info
+// CFatVector - resizable array of CFatSect
+// CFat - Grouping of FatSect
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+//--------------------------------------------------------------------
+
+
+
+#ifndef __FAT_HXX__
+#define __FAT_HXX__
+
+#include <vect.hxx>
+
+#define DEB_FAT (DEB_ITRACE|0x00010000)
+
+
+//+----------------------------------------------------------------------
+//
+// Class: CFatSect (fs)
+//
+// Purpose: Holds one sector worth of FAT data
+//
+// Interface: getsize - Returns the size of the FAT (in sectors)
+// contents - Returns contents of any given FAT entry
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//-----------------------------------------------------------------------
+
+#if _MSC_VER == 700
+#pragma warning(disable:4001)
+#elif _MSC_VER >= 800
+#pragma warning(disable:4200)
+#endif
+
+class CFatSect
+{
+public:
+ SCODE FAT_CLASS Init(FSOFFSET uEntries);
+ SCODE FAT_CLASS InitCopy(USHORT uSize, CFatSect *pfsOld);
+
+ inline SECT FAT_CLASS GetSect(const FSOFFSET sect) const;
+ inline void FAT_CLASS SetSect(const FSOFFSET sect,const SECT sectNew);
+
+ inline SECT FAT_CLASS GetNextFat(USHORT uSize) const;
+ inline void FAT_CLASS SetNextFat(USHORT uSize, const SECT sect);
+
+private:
+ SECT _asectEntry[];
+};
+
+#if _MSC_VER == 700
+#pragma warning(default:4001)
+#elif _MSC_VER >= 800
+#pragma warning(default:4200)
+#endif
+
+
+inline SECT FAT_CLASS CFatSect::GetSect(const FSOFFSET sect) const
+{
+ return _asectEntry[sect];
+}
+
+inline void FAT_CLASS CFatSect::SetSect(const FSOFFSET sect,
+ const SECT sectNew)
+{
+ _asectEntry[sect] = sectNew;
+}
+
+inline SECT FAT_CLASS CFatSect::GetNextFat(USHORT uSize) const
+{
+ return _asectEntry[uSize];
+}
+
+inline void FAT_CLASS CFatSect::SetNextFat(USHORT uSize, const SECT sect)
+{
+ _asectEntry[uSize] = sect;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CFatVector (fv)
+//
+// Purpose: *Finish This*
+//
+// Interface:
+//
+// History: 02-Sep-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CFatVector: public CPagedVector
+{
+public:
+ inline FAT_CLASS CFatVector(
+ const SID sid);
+
+ inline void FAT_CLASS InitCommon(FSOFFSET csectBlock, FSOFFSET csectTable);
+
+ SCODE FAT_CLASS InitPage(FSINDEX iPage);
+
+ inline FSOFFSET GetSectBlock() const;
+ inline FSOFFSET GetSectTable() const;
+
+ inline SCODE FAT_CLASS GetTable(
+ const FSINDEX iTable,
+ const DWORD dwFlags,
+ CFatSect **pfs);
+
+private:
+ FSOFFSET _csectTable;
+ FSOFFSET _csectBlock;
+
+};
+
+
+inline FAT_CLASS CFatVector::CFatVector(
+ const SID sid)
+ : CPagedVector(sid)
+{
+}
+
+inline void FAT_CLASS CFatVector::InitCommon(
+ FSOFFSET csectBlock,
+ FSOFFSET csectTable)
+{
+ _csectBlock = csectBlock;
+ _csectTable = csectTable;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFatVector::GetSectTable, public
+//
+// Synopsis: Returns count of sector entries per table
+//
+// Returns: count of sector entries per table
+//
+// History: 08-Jul-92 AlexT Created.
+//
+//--------------------------------------------------------------------------
+
+inline FSOFFSET CFatVector::GetSectTable() const
+{
+ return _csectTable;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFatVector::GetSectTable, public
+//
+// Synopsis: Returns count of sector entries per block
+//
+// Returns: count of sector entries per block
+//
+// History: 01-Sep-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline FSOFFSET CFatVector::GetSectBlock() const
+{
+ return _csectBlock;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFatVector::GetTable, public
+//
+// Synopsis: Return a pointer to a FatSect for the given index
+// into the vector.
+//
+// Arguments: [iTable] -- index into vector
+//
+// Returns: Pointer to CFatSect indicated by index
+//
+// History: 27-Dec-91 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline SCODE FAT_CLASS CFatVector::GetTable(
+ const FSINDEX iTable,
+ const DWORD dwFlags,
+ CFatSect **ppfs)
+{
+ SCODE sc;
+
+ sc = CPagedVector::GetTable(iTable, dwFlags, (void **)ppfs);
+
+ if (sc == STG_S_NEWPAGE)
+ {
+ (*ppfs)->Init(_csectBlock);
+ }
+
+ return sc;
+}
+
+
+
+
+//CSEG determines the maximum number of segments that will be
+//returned by a single Contig call.
+
+#define CSEG 32
+
+//+-------------------------------------------------------------------------
+//
+// Class: SSegment (seg)
+//
+// Purpose: Used for contiguity tables for multi-sector reads and
+// writes.
+//
+// Interface: None.
+//
+// History: 16-Aug-91 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+struct SSegment {
+public:
+ ULONG ulOffset;
+ SECT sectStart;
+ ULONG cSect;
+};
+
+
+inline SECT SegStart(SSegment seg)
+{
+ return seg.sectStart;
+}
+
+inline SECT SegEnd(SSegment seg)
+{
+ return seg.sectStart + seg.cSect - 1;
+}
+
+inline ULONG SegLength(SSegment seg)
+{
+ return seg.cSect;
+}
+
+inline ULONG SegStartOffset(SSegment seg)
+{
+ return seg.ulOffset;
+}
+
+inline ULONG SegEndOffset(SSegment seg)
+{
+ return seg.ulOffset + seg.cSect - 1;
+}
+
+
+class MSTREAM_CLASS CMStream;
+
+
+#define GF_READONLY TRUE
+#define GF_WRITE FALSE
+
+class CFat;
+SAFE_DFBASED_PTR(CBasedFatPtr, CFat);
+//+----------------------------------------------------------------------
+//
+// Class: CFat (fat)
+//
+// Purpose: Main interface to allocation routines
+//
+// Interface: Allocate - allocates new chain in the FAT
+// Extend - Extends an existing FAT chain
+// GetNext - Returns next sector in a chain
+// GetSect - Returns nth sector in a chain
+// GetESect - Returns nth sector in a chain, extending
+// if necessary
+// GetLength - Returns the # of sectors in a chain
+// setup - Initializes for an existing stream
+// setupnew - Initializes for a new stream
+//
+// checksanity - Debugging routine
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 17-Aug-91 PhilipLa Added dirty and full bits
+// Notes:
+//
+//-----------------------------------------------------------------------
+struct SGetFreeStruct;
+
+class CFat
+{
+public:
+
+ FAT_CLASS CFat(SID sid);
+ FAT_CLASS CFat(CFat *pfatOld);
+ FAT_CLASS ~CFat();
+
+ VOID FAT_CLASS Empty(VOID);
+
+#ifdef USE_NOSCRATCH
+ inline void SetNoScratch(CFat *pfatNoScratch);
+#endif
+
+#ifdef USE_NOSNAPSHOT
+ inline void SetNoSnapshot(SECT sectNoSnapshot);
+ inline SECT GetNoSnapshotFree(void);
+ inline void ResetNoSnapshotFree(void);
+ SCODE ResizeNoSnapshot(void);
+#endif
+
+ inline SCODE FAT_CLASS Allocate(ULONG ulSize, SECT *psectFirst);
+ SCODE FAT_CLASS GetNext(const SECT sect, SECT * psRet);
+
+ SCODE FAT_CLASS GetSect(
+ SECT sectStart,
+ ULONG ulOffset,
+ SECT *psectReturn);
+
+ SCODE FAT_CLASS GetESect(
+ SECT sectStart,
+ ULONG ulOffset,
+ SECT *psectReturn);
+
+ SCODE FAT_CLASS SetNext(SECT sectFirst, SECT sectNext);
+ SCODE FAT_CLASS GetFree(ULONG ulCount, SECT * sect, BOOL fReadOnly);
+
+ SCODE FAT_CLASS GetFreeContig(ULONG ulCount,
+ SSegment STACKBASED *aseg,
+ ULONG cSeg,
+ ULONG *pcSegReturned);
+
+ SCODE FAT_CLASS ReserveSects(ULONG cSect);
+
+ SCODE FAT_CLASS GetLength(SECT sect, ULONG * pulRet);
+
+ SCODE FAT_CLASS SetChainLength(SECT,ULONG);
+
+ SCODE FAT_CLASS Init(
+ CMStream *pmsParent,
+ FSINDEX cFatSect,
+ BOOL fConvert);
+
+ SCODE FAT_CLASS InitNew(CMStream *pmsParent);
+ void FAT_CLASS InitCopy(CFat *pfatOld);
+ SCODE FAT_CLASS InitConvert(
+ CMStream *pmsParent,
+ ULONG cbSize);
+
+#ifdef USE_NOSCRATCH
+ SCODE FAT_CLASS InitScratch(CFat *pfat, BOOL fNew);
+#endif
+
+ SCODE FAT_CLASS Remap(
+ SECT sectStart,
+ ULONG oStart,
+ ULONG ulRunLength,
+ SECT *psectOldStart,
+ SECT *psectNewStart,
+ SECT *psectOldEnd,
+ SECT *psectNewEnd);
+
+ inline SCODE FAT_CLASS QueryRemapped(const SECT sect);
+
+ inline SECT FAT_CLASS GetLast(VOID) const;
+
+ inline VOID FAT_CLASS ResetCopyOnWrite(VOID);
+ inline VOID FAT_CLASS SetCopyOnWrite(CFat *pfat, SECT sectLast);
+ inline VOID FAT_CLASS ResetUnmarkedSects(VOID);
+
+ SCODE FAT_CLASS FindLast(SECT *psectRet);
+ SCODE FAT_CLASS FindMaxSect(SECT *psectRet);
+ inline SCODE FAT_CLASS GetMaxSect(SECT *psectRet);
+
+ SCODE FAT_CLASS Contig(
+ SSegment STACKBASED *aseg,
+ BOOL fWrite,
+ SECT sect,
+ ULONG ulLength,
+ ULONG *pcSeg);
+
+ inline SCODE FAT_CLASS Flush(VOID);
+
+ inline void FAT_CLASS SetParent(CMStream *pms);
+
+ SCODE FAT_CLASS Resize(ULONG);
+
+#if DBG == 1
+ SCODE FAT_CLASS checksanity(SECT);
+ void CheckFreeCount(void);
+#else
+ #define CheckFreeCount()
+#endif
+
+
+private:
+
+inline SCODE IsFree(SECT sect);
+
+ inline SCODE FAT_CLASS MarkSect(SGetFreeStruct *pgf);
+ inline void FAT_CLASS InitGetFreeStruct(SGetFreeStruct *pgf);
+ inline void FAT_CLASS ReleaseGetFreeStruct(SGetFreeStruct *pgf);
+
+ CFatVector _fv;
+ CBasedMStreamPtr _pmsParent;
+ const SID _sid;
+
+ CBasedFatPtr _pfatReal;
+
+#ifdef USE_NOSCRATCH
+ CBasedFatPtr _pfatNoScratch;
+#endif
+
+#ifdef USE_NOSNAPSHOT
+ //When committing in no-snapshot mode, all free sectors must
+ // be greater than _sectNoSnapshot.
+ SECT _sectNoSnapshot;
+ SECT _sectNoSnapshotFree;
+#endif
+
+ USHORT _uFatShift;
+ USHORT _uFatMask;
+
+ FSINDEX _cfsTable;
+ ULONG _ulFreeSects;
+
+ ULONG _cUnmarkedSects;
+
+ SECT _sectFirstFree;
+
+ SECT _sectLastUsed;
+ SECT _sectMax;
+
+ SCODE FAT_CLASS CountFree(ULONG * ulRet);
+ SCODE FAT_CLASS Extend(SECT,ULONG);
+
+ inline VOID FAT_CLASS SectToPair(
+ SECT sect,
+ FSINDEX *pipfs,
+ FSOFFSET *pisect) const;
+
+ inline SECT FAT_CLASS PairToSect(FSINDEX ipfs, FSOFFSET isect) const;
+
+ friend class CDIFat;
+};
+
+
+inline SECT FAT_CLASS CFat::GetLast(VOID) const
+{
+ return _sectLastUsed;
+}
+
+inline VOID FAT_CLASS CFat::ResetCopyOnWrite(VOID)
+{
+ _sectLastUsed = 0;
+
+ //Reset _sectFirstFree since this change can conceivably open up
+ // new free sectors before the _sectFirstFree used in COW mode.
+ _ulFreeSects = MAX_ULONG;
+ _sectFirstFree = 0;
+ _sectMax = ENDOFCHAIN;
+ _fv.ResetBits();
+ _pfatReal = NULL;
+
+ _cUnmarkedSects = 0;
+}
+
+inline VOID FAT_CLASS CFat::ResetUnmarkedSects(VOID)
+{
+ _cUnmarkedSects = 0;
+ CheckFreeCount();
+}
+
+inline VOID FAT_CLASS CFat::SetCopyOnWrite(CFat *pfat, SECT sectLast)
+{
+ msfAssert((_cUnmarkedSects == 0) &&
+ aMsg("Unmarked sectors at enter copy-on-write."));
+ _pfatReal = P_TO_BP(CBasedFatPtr, pfat);
+ _sectLastUsed = sectLast;
+ _sectFirstFree = 0;
+
+#ifdef USE_NOSCRATCH
+ if (_pfatNoScratch != NULL)
+ {
+ _ulFreeSects = MAX_ULONG;
+ _fv.ResetBits();
+ }
+#endif
+
+#if DBG == 1
+ CheckFreeCount();
+#endif
+}
+
+
+inline VOID FAT_CLASS CFat::SectToPair(SECT sect,
+ FSINDEX *pipfs,
+ FSOFFSET *pisect) const
+{
+ *pipfs = (FSINDEX)(sect >> _uFatShift);
+ *pisect = (FSOFFSET)(sect & _uFatMask);
+}
+
+inline SECT FAT_CLASS CFat::PairToSect(FSINDEX ipfs, FSOFFSET isect) const
+{
+ return (ipfs << _uFatShift) + isect;
+}
+
+inline SCODE FAT_CLASS CFat::GetMaxSect(SECT *psectRet)
+{
+ SCODE sc;
+ msfChk(FindMaxSect(&_sectMax));
+ *psectRet = _sectMax;
+ Err:
+ return sc;
+}
+
+
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_QueryRemapped)
+#endif
+
+inline SCODE FAT_CLASS CFat::QueryRemapped(const SECT sect)
+{
+ SCODE sc = S_FALSE;
+ SECT sectNew;
+
+ if ((sect == ENDOFCHAIN) || (sect >= _sectLastUsed))
+ {
+ sc = S_OK;
+ }
+ else
+ {
+ msfChk(_pfatReal->GetNext(sect, &sectNew));
+
+ if (sectNew == FREESECT)
+ {
+ sc = S_OK;
+ }
+ else
+ {
+ sc = S_FALSE;
+ }
+ }
+
+ Err:
+ return sc;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+
+inline void FAT_CLASS CFat::SetParent(CMStream *pms)
+{
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pms);
+ _fv.SetParent(pms);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::Flush, public
+//
+// Synposis: Write all modified FatSects out to stream
+//
+// Effects: Resets all dirty bit fields on FatSects
+//
+// Arguments: Void
+//
+// Returns: S_OK if call completed OK.
+// Error code of parent write otherwise.
+//
+// Algorithm: Linearly scan through FatSects, writing any sector
+// that has the dirty bit set. Reset all dirty bits.
+//
+// History: 17-Aug-91 PhilipLa Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+inline SCODE FAT_CLASS CFat::Flush(VOID)
+{
+ return _fv.Flush();
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::Allocate, public
+//
+// Synposis: Allocates a chain within a FAT
+//
+// Effects: Modifies a single sector within the fat. Causes a
+// one sector stream write.
+//
+// Arguments: [ulSize] -- Number of sectors to allocate in chain
+//
+// Returns: Sector ID of first sector in chain
+//
+// Algorithm: Use repetitive calls to GetFree to construct a new chain
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 17-Aug-91 PhilipLa Added dirty bits opt (Dump)
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+inline SCODE FAT_CLASS CFat::Allocate(ULONG ulSize, SECT * psectFirst)
+{
+ return GetFree(ulSize, psectFirst, GF_WRITE);
+}
+
+
+#ifdef USE_NOSCRATCH
+//+---------------------------------------------------------------------------
+//
+// Member: CFat::SetNoScratch, public
+//
+// Synopsis: Set the fat for use in noscratch processing
+//
+// Arguments: [pfatNoScratch] -- Pointer to fat to use
+//
+// Returns: void
+//
+// History: 10-Mar-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CFat::SetNoScratch(CFat *pfatNoScratch)
+{
+ _pfatNoScratch = P_TO_BP(CBasedFatPtr, pfatNoScratch);
+}
+#endif
+
+#ifdef USE_NOSNAPSHOT
+//+---------------------------------------------------------------------------
+//
+// Member: CFat::SetNoSnapshot, public
+//
+// Synopsis: Set the no-snapshot sect marker for commits
+//
+// Arguments: [sectNosnapshot] -- Sect to set.
+//
+// Returns: void
+//
+// History: 18-Oct-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CFat::SetNoSnapshot(SECT sectNoSnapshot)
+{
+ _sectNoSnapshot = sectNoSnapshot;
+ if (sectNoSnapshot != 0)
+ {
+ _ulFreeSects = MAX_ULONG;
+ _sectNoSnapshotFree = _sectNoSnapshot;
+
+ _sectMax = _sectNoSnapshot;
+#if DBG == 1
+ SCODE sc;
+ SECT sectLast;
+ msfChk(FindLast(&sectLast));
+ msfAssert((_sectMax == sectLast) &&
+ aMsg("_sectMax doesn't match actual last sector"));
+ Err:
+ ;
+#endif
+ }
+
+}
+
+inline SECT CFat::GetNoSnapshotFree(void)
+{
+ return _sectNoSnapshotFree;
+}
+
+inline void CFat::ResetNoSnapshotFree(void)
+{
+ _sectNoSnapshotFree = ENDOFCHAIN;
+}
+#endif
+
+#endif //__FAT_HXX__
diff --git a/private/ole32/stg/h/filelkb.hxx b/private/ole32/stg/h/filelkb.hxx
new file mode 100644
index 000000000..d17859333
--- /dev/null
+++ b/private/ole32/stg/h/filelkb.hxx
@@ -0,0 +1,50 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: filelkb.hxx
+//
+// Contents: IFileLockBytes definition
+//
+// Classes: IFileLockBytes
+//
+// History: 14-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FILELKB_HXX__
+#define __FILELKB_HXX__
+
+#define IID_IFileLockBytes IID_IDfReserved1
+
+/****** IFileLockBytes Interface ********************************************/
+
+#define LPFILELOCKBYTES IFileLockBytes FAR*
+
+#undef INTERFACE
+#define INTERFACE IFileLockBytes
+
+DECLARE_INTERFACE_(IFileLockBytes, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IFileLockBytes methods ***
+ STDMETHOD(SwitchToFile) (THIS_ OLECHAR const *lpstrFile,
+ ULONG ulCommitSize,
+ ULONG cbBuffer,
+ LPVOID pvBuffer) PURE;
+
+ STDMETHOD(FlushCache) (THIS) PURE;
+ STDMETHOD(ReserveHandle)(THIS) PURE;
+
+ // Optimizations
+
+ STDMETHOD(GetLocksSupported)(THIS_ DWORD *pdwLockFlags) PURE;
+ STDMETHOD(GetSize)(THIS_ ULARGE_INTEGER *puliSize) PURE;
+};
+
+#endif // #ifndef __FILELKB_HXX__
diff --git a/private/ole32/stg/h/filest.hxx b/private/ole32/stg/h/filest.hxx
new file mode 100644
index 000000000..1a448675e
--- /dev/null
+++ b/private/ole32/stg/h/filest.hxx
@@ -0,0 +1,677 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992
+//
+// File: filest.hxx
+//
+// Contents: Windows FAT ILockBytes implementation
+//
+// History: 20-Nov-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __FILEST_HXX__
+#define __FILEST_HXX__
+
+#include <dfmsp.hxx>
+#include <cntxlist.hxx>
+#include <filelkb.hxx>
+#if WIN32 >= 300
+#include <accstg.hxx>
+#endif
+#ifdef ASYNC
+#include <iconn.h>
+#endif
+
+// Local flags
+#define LFF_RESERVE_HANDLE 1
+
+#ifndef FLAT
+// C700 - C7 doesn't like long interface+method names
+#define CFileStream CFS
+#endif
+
+// FILEH and INVALID_FH allow us to switch between file handle
+// types for Win16/32
+#ifndef FLAT
+typedef int FILEH;
+#define INVALID_FH (-1)
+#else
+typedef HANDLE FILEH;
+#define INVALID_FH INVALID_HANDLE_VALUE
+#endif
+
+#define CheckHandle() (_hFile == INVALID_FH ? STG_E_INVALIDHANDLE : S_OK)
+
+//+--------------------------------------------------------------
+//
+// Class: CFileStream (fst)
+//
+// Purpose: ILockBytes implementation for a file
+//
+// Interface: See below
+//
+// History: 24-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+class CGlobalFileStream;
+class CPerContext;
+SAFE_DFBASED_PTR(CBasedGlobalFileStreamPtr, CGlobalFileStream);
+
+interface CFileStream : public ILockBytes,
+ public IFileLockBytes,
+ public IMarshal,
+#ifdef ASYNC
+ public IFillLockBytes,
+ public IFillInfo,
+#endif // ASYNC
+#if WIN32 >= 300
+ public CAccessControl,
+#endif
+ public CContext
+{
+public:
+ CFileStream(IMalloc * const pMalloc);
+
+#if DBG == 1 && defined(MULTIHEAP)
+ // This is only for global instances that do not use shared memory
+ void RemoveFromGlobal () { _pgfst = NULL; _cReferences = 0; };
+#endif
+ SCODE InitFlags(DWORD dwStartFlags,
+ DFLAGS df);
+ void InitFromGlobal(CGlobalFileStream *pgfst);
+ inline SCODE Init(WCHAR const *pwcsPath);
+ inline SCODE InitUnmarshal(WCHAR const *pwcsPath);
+#ifdef WIN32
+ SCODE InitFromHandle(HANDLE h);
+#endif
+ ~CFileStream(void);
+
+ ULONG vRelease(void);
+ inline void vAddRef(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+ // IMarshal
+ STDMETHOD(GetUnmarshalClass)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID *ppv);
+ static SCODE StaticReleaseMarshalData(IStream *pstm,
+ DWORD mshlflags);
+ STDMETHOD(ReleaseMarshalData)(IStream *pStm);
+ STDMETHOD(DisconnectObject)(DWORD dwReserved);
+
+ // ILockBytes
+ STDMETHOD(ReadAt)(ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbRead);
+ STDMETHOD(WriteAt)(ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ STDMETHOD(Flush)(void);
+ STDMETHOD(SetSize)(ULARGE_INTEGER cb);
+ STDMETHOD(LockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+#ifndef OLEWIDECHAR
+ SCODE Stat(STATSTGW *pstatstg, DWORD grfStatFlag);
+#endif
+
+ // IFileLockBytes
+ STDMETHOD(SwitchToFile)(OLECHAR const *ptcsFile,
+ ULONG ulCommitSize,
+ ULONG cbBuffer,
+ void *pvBuffer);
+ STDMETHOD(FlushCache)(THIS);
+ STDMETHOD(ReserveHandle)(void);
+ STDMETHOD(GetLocksSupported)(THIS_ DWORD *pdwLockFlags);
+ STDMETHOD(GetSize)(THIS_ ULARGE_INTEGER *puliSize);
+
+#ifdef ASYNC
+ //IFillLockBytes
+ STDMETHOD(FillAppend)(void const *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ STDMETHOD(FillAt)(ULARGE_INTEGER ulOffset,
+ void const *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ STDMETHOD(SetFillSize)(ULARGE_INTEGER ulSize);
+ STDMETHOD(Terminate)(BOOL bCanceled);
+
+ //From IFillInfo
+ STDMETHOD(GetFailureInfo)(ULONG *pulWaterMark,
+ ULONG *pulFailurePoint);
+ STDMETHOD(GetTerminationStatus)(DWORD *pdwFlags);
+
+ void StartAsyncMode(void);
+ inline void SetContext(CPerContext *ppc);
+ inline CPerContext *GetContextPointer(void) const;
+#endif // ASYNC
+ // New
+ SCODE GetName(WCHAR **ppwcsName);
+ inline ContextId GetContext(void) const;
+ inline CFileStream *GetNext(void) const;
+ inline SCODE Validate(void) const;
+ inline void SetStartFlags(DWORD dwStartFlags);
+ inline DWORD GetStartFlags(void) const;
+ inline DFLAGS GetFlags(void) const;
+ inline IMalloc * GetMalloc(void) const;
+
+
+ void Delete(void);
+
+ SCODE SetTime(WHICHTIME tt,
+ TIME_T nt);
+
+ SCODE SetAllTimes(TIME_T atm,
+ TIME_T mtm,
+ TIME_T ctm);
+
+ static SCODE Unmarshal(IStream *pstm,
+ void **ppv,
+ DWORD mshlflags);
+
+#if WIN32 == 100 || WIN32 > 200
+ inline void TurnOffMapping(void);
+#endif
+
+private:
+ SCODE InitWorker(WCHAR const *pwcsPath, BOOL fCheck);
+ SCODE SetSizeWorker(ULARGE_INTEGER ulSize);
+ SCODE WriteAtWorker(ULARGE_INTEGER ulPosition,
+ VOID const *pb,
+ ULONG cb,
+ ULONG *pcbWritten);
+#if DBG == 1
+ void CheckSeekPointer(void);
+#endif
+
+#ifndef UNICODE
+ BOOL DeleteFileUnicode(LPCWSTR lpFileName);
+#define DeleteFileX(lpFileName) DeleteFileUnicode(lpFileName)
+#else
+#define DeleteFileX(lpFileName) DeleteFile(lpFileName)
+#endif
+
+ CBasedGlobalFileStreamPtr _pgfst;
+#ifdef ASYNC
+ CPerContext *_ppc;
+#endif
+ FILEH _hFile, _hReserved;
+ ULONG _sig;
+ LONG _cReferences;
+
+ // Floppy support
+ SCODE CheckIdentity(void);
+
+ BYTE _fFixedDisk;
+ DWORD _dwTicks;
+ char _achVolume[11];
+ DWORD _dwVolId;
+ WORD _cbSector;
+ IMalloc * const _pMalloc;
+ WORD _grfLocal;
+
+#if WIN32 == 100 || WIN32 > 200
+
+ // Take advantage of file mapping for read-only case
+
+ HANDLE _hMapObject;
+ LPBYTE _pbBaseAddr;
+ DWORD _cbFileSize;
+
+#endif
+
+#ifdef WIN32
+ //We rely on the fact that we never pass in a high dword other
+ //than zero. We only cache the low dword of the seek pointer.
+ ULONG _ulLowPos;
+
+#if DBG == 1
+ ULONG _ulSeeks;
+ ULONG _ulRealSeeks;
+
+ ULONG _ulLastFilePos;
+#endif
+#endif
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CGlobalFileStream (gfst)
+//
+// Purpose: Maintains context-insensitive filestream information
+//
+// Interface: See below
+//
+// History: 26-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CGlobalFileStream : public CContextList
+{
+public:
+ inline CGlobalFileStream(IMalloc * const pMalloc,
+ WCHAR const *pwcsPath,
+ DFLAGS df,
+ DWORD dwStartFlags);
+
+ DECLARE_CONTEXT_LIST(CFileStream);
+
+ inline BOOL HasName(void) const;
+ inline WCHAR *GetName(void) const;
+ inline DFLAGS GetDFlags(void) const;
+ inline DWORD GetStartFlags(void) const;
+
+ inline void SetName(WCHAR const *pwcsPath);
+ inline void SetStartFlags(DWORD dwStartFlags);
+ inline IMalloc *GetMalloc(VOID) const;
+
+#ifdef ASYNC
+ inline DWORD GetTerminationStatus(void) const;
+ inline ULONG GetHighWaterMark(void) const;
+ inline ULONG GetFailurePoint(void) const;
+
+ inline void SetTerminationStatus(DWORD dwTerminate);
+ inline void SetHighWaterMark(ULONG ulHighWater);
+ inline void SetFailurePoint(ULONG ulFailure);
+#endif
+
+private:
+ WCHAR _awcPath[_MAX_PATH+1];
+ DFLAGS _df;
+ DWORD _dwStartFlags;
+ IMalloc * const _pMalloc;
+
+#ifdef ASYNC
+ DWORD _dwTerminate;
+ ULONG _ulHighWater;
+ ULONG _ulFailurePoint;
+#endif // ASYNC
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CGlobalFileStream::CGlobalFileStream, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [pszPath] - Path
+// [df] - Permissions
+// [dwStartFlags] - Startup flags
+//
+// History: 27-Oct-92 DrewB Created
+// 18-May-93 AlexT Added pMalloc
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CGlobalFileStream_CGlobalFileStream)
+#endif
+
+inline CGlobalFileStream::CGlobalFileStream(IMalloc * const pMalloc,
+ WCHAR const *pwcsPath,
+ DFLAGS df,
+ DWORD dwStartFlags)
+: _pMalloc(pMalloc)
+{
+ SetName(pwcsPath);
+ _df = df;
+ _dwStartFlags = dwStartFlags;
+#ifdef ASYNC
+ _dwTerminate = TERMINATED_NORMAL;
+ _ulHighWater = _ulFailurePoint = 0;
+#endif
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CGlobalFileStream::HasName, public
+//
+// Synopsis: Checks for a name
+//
+// History: 13-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CGlobalFileStream::HasName(void) const
+{
+ return (BOOL)_awcPath[0];
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CGlobalFileStream::GetName, public
+//
+// Synopsis: Returns the name
+//
+// History: 13-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline WCHAR *CGlobalFileStream::GetName(void) const
+{
+ return (WCHAR *) _awcPath;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CGlobalFileStream::GetDFlags, public
+//
+// Synopsis: Returns the flags
+//
+// History: 13-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline DFLAGS CGlobalFileStream::GetDFlags(void) const
+{
+ return _df;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CGlobalFileStream::GetStartFlags, public
+//
+// Synopsis: Returns the start flags
+//
+// History: 13-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline DWORD CGlobalFileStream::GetStartFlags(void) const
+{
+ return _dwStartFlags;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CGlobalFileStream::SetName, public
+//
+// Synopsis: Sets the name
+//
+// History: 13-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CGlobalFileStream::SetName(WCHAR const *pwcsPath)
+{
+ if (pwcsPath)
+ lstrcpyW(_awcPath, pwcsPath);
+ else
+ _awcPath[0] = 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CGlobalFileStream::SetStartFlags, public
+//
+// Synopsis: Sets the start flags
+//
+// History: 13-Jan-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CGlobalFileStream::SetStartFlags(DWORD dwStartFlags)
+{
+ _dwStartFlags = dwStartFlags;
+}
+
+#ifdef ASYNC
+inline DWORD CGlobalFileStream::GetTerminationStatus(void) const
+{
+ return _dwTerminate;
+}
+
+inline ULONG CGlobalFileStream::GetHighWaterMark(void) const
+{
+ return _ulHighWater;
+}
+
+inline ULONG CGlobalFileStream::GetFailurePoint(void) const
+{
+ return _ulFailurePoint;
+}
+
+inline void CGlobalFileStream::SetTerminationStatus(DWORD dwTerminate)
+{
+ olAssert((dwTerminate == UNTERMINATED) ||
+ (dwTerminate == TERMINATED_NORMAL) ||
+ (dwTerminate == TERMINATED_ABNORMAL));
+ _dwTerminate = dwTerminate;
+}
+
+inline void CGlobalFileStream::SetHighWaterMark(ULONG ulHighWater)
+{
+ olAssert(ulHighWater >= _ulHighWater);
+ _ulHighWater = ulHighWater;
+}
+
+inline void CGlobalFileStream::SetFailurePoint(ULONG ulFailure)
+{
+ _ulFailurePoint = ulFailure;
+}
+#endif //ASYNC
+
+
+//+--------------------------------------------------------------
+//
+// Member: CGlobalFileStream::GetMalloc, public
+//
+// Synopsis: Returns the allocator associated with this global file
+//
+// History: 05-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline IMalloc *CGlobalFileStream::GetMalloc(VOID) const
+{
+ return(_pMalloc);
+}
+
+#define CFILESTREAM_SIG LONGSIG('F', 'L', 'S', 'T')
+#define CFILESTREAM_SIGDEL LONGSIG('F', 'l', 'S', 't')
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::Validate, public
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CFileStream::Validate(void) const
+{
+ return (this == NULL || _sig != CFILESTREAM_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::AddRef, public
+//
+// Synopsis: Changes the ref count
+//
+// History: 26-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CFileStream::vAddRef(void)
+{
+ InterlockedIncrement(&_cReferences);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::GetContext, public
+//
+// Synopsis: Returns the task ID.
+//
+// History: 24-Sep-92 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+inline ContextId CFileStream::GetContext(void) const
+{
+ return ctxid;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::GetNext, public
+//
+// Synopsis: Returns the next filestream in the context list
+//
+// History: 27-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline CFileStream *CFileStream::GetNext(void) const
+{
+ return (CFileStream *) (CContext *) pctxNext;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::SetStartFlags, public
+//
+// Synopsis: Sets the start flags
+//
+// History: 31-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CFileStream::SetStartFlags(DWORD dwStartFlags)
+{
+ _pgfst->SetStartFlags(dwStartFlags);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CFileStream::TurnOffMapping, public
+//
+// Synopsis: Turns off the use of file mapping
+//
+// History: 31-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#if WIN32 == 100 || WIN32 > 200
+inline void CFileStream::TurnOffMapping(void)
+{
+
+ if (_pbBaseAddr != NULL)
+ {
+ olVerify(UnmapViewOfFile(_pbBaseAddr));
+ _pbBaseAddr = NULL;
+
+ if (_hMapObject != NULL)
+ {
+ olVerify(CloseHandle(_hMapObject));
+ _hMapObject = NULL;
+ }
+ }
+}
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::Init, public
+//
+// Synopsis: Wrapper function - call through to InitWorker
+//
+// History: 30-Jun-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CFileStream::Init(WCHAR const *pwcsPath)
+{
+ return InitWorker(pwcsPath, TRUE);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFileStream::InitUnmarshal, public
+//
+// Synopsis: Wrapper function - call through to InitWorker
+//
+// History: 30-Jun-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CFileStream::InitUnmarshal(WCHAR const *pwcsPath)
+{
+ return InitWorker(pwcsPath, FALSE);
+}
+
+inline DWORD CFileStream::GetStartFlags(void) const
+{
+ return _pgfst->GetStartFlags();
+}
+
+inline DFLAGS CFileStream::GetFlags(void) const
+{
+ return _pgfst->GetDFlags();
+}
+
+inline IMalloc * CFileStream::GetMalloc(void) const
+{
+ return _pgfst->GetMalloc();
+}
+
+#ifdef ASYNC
+inline CPerContext * CFileStream::GetContextPointer(void) const
+{
+ return _ppc;
+}
+
+inline void CFileStream::SetContext(CPerContext *ppc)
+{
+ _ppc = ppc;
+}
+
+#endif //ASYNC
+
+#endif
diff --git a/private/ole32/stg/h/filstm.hxx b/private/ole32/stg/h/filstm.hxx
new file mode 100644
index 000000000..23d05e797
--- /dev/null
+++ b/private/ole32/stg/h/filstm.hxx
@@ -0,0 +1,120 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: filstm.hxx
+//
+// Contents: CNtFileStream header
+//
+// Classes: CNtFileStream
+//
+// History: 28-Jun-93 DrewB Created
+//
+// Notes: Non-OFS
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FILSTM_HXX__
+#define __FILSTM_HXX__
+
+#include <otrack.hxx>
+#include <overlap.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: CNtFileStream (fs)
+//
+// Purpose: Implements IStream for an NT handle
+//
+// Interface: IStream
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+interface CNtFileStream
+ : INHERIT_TRACKING,
+ //public IStream,
+ public COverlappedStream
+{
+public:
+ CNtFileStream(void);
+ SCODE InitFromHandle(HANDLE h,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSTGSECURITY pssSecurity);
+ SCODE InitFromPath(HANDLE hParent,
+ const WCHAR *pwcsName,
+ DWORD grfMode,
+ DWORD grfAttr,
+ CREATEOPEN co,
+ LPSTGSECURITY pssSecurity);
+ SCODE InitClone(HANDLE h,
+ DWORD grfMode);
+ ~CNtFileStream(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // IStream
+ STDMETHOD(Read)(VOID *pv,
+ ULONG cb,
+ ULONG *pcbRead);
+ STDMETHOD(Write)(VOID const *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ STDMETHOD(Seek)(LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition);
+ STDMETHOD(SetSize)(ULARGE_INTEGER cb);
+ STDMETHOD(CopyTo)(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(LockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+ STDMETHOD(Clone)(IStream **ppstm);
+
+private:
+ inline SCODE Validate(void) const;
+ SCODE ValidateMode(DWORD grfMode);
+ SCODE InitCommon(CREATEOPEN co);
+
+ //NuSafeNtHandle _h; // moved to COverlappedStream
+ ULONG _sig;
+ DWORD _grfMode;
+};
+
+SAFE_INTERFACE_PTR(SafeCNtFileStream, CNtFileStream);
+
+#define CNTFILESTREAM_SIG LONGSIG('F', 'S', 'T', 'M')
+#define CNTFILESTREAM_SIGDEL LONGSIG('F', 's', 'T', 'm')
+
+//+--------------------------------------------------------------
+//
+// Member: CNtFileStream::Validate, private
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 28-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CNtFileStream::Validate(void) const
+{
+ return (this == NULL || _sig != CNTFILESTREAM_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+#endif // #ifndef __FILSTM_HXX__
diff --git a/private/ole32/stg/h/freelist.hxx b/private/ole32/stg/h/freelist.hxx
new file mode 100644
index 000000000..3e8bbf269
--- /dev/null
+++ b/private/ole32/stg/h/freelist.hxx
@@ -0,0 +1,143 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: freelist.hxx
+//
+// Contents: CFreeList header
+//
+// Classes: CFreeList
+//
+// History: 05-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FREELIST_HXX__
+#define __FREELIST_HXX__
+
+struct SFreeBlock;
+SAFE_DFBASED_PTR(CBasedFreeBlockPtr, SFreeBlock);
+struct SFreeBlock
+{
+ CBasedFreeBlockPtr pfbNext;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Class: CFreeList (frl)
+//
+// Purpose: Maintains a list of free blocks
+//
+// Interface: See below
+//
+// History: 05-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CFreeList
+{
+public:
+ inline CFreeList(void);
+ inline ~CFreeList(void);
+
+ SCODE Reserve(IMalloc *pMalloc, UINT cBlocks, size_t cbBlock);
+ inline void *GetReserved(void);
+ inline void ReturnToReserve(void *pv);
+ void Unreserve(UINT cBlocks);
+
+private:
+ CBasedFreeBlockPtr _pfbHead;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFreeList::CFreeList, public
+//
+// Synopsis: Constructor
+//
+// History: 05-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline CFreeList::CFreeList(void)
+{
+ _pfbHead = NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFreeList::~CFreeList, public
+//
+// Synopsis: Destructor
+//
+// History: 05-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFreeList_1CFreeList)
+#endif
+
+inline CFreeList::~CFreeList(void)
+{
+ olAssert(_pfbHead == NULL);
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFreeList::GetReserved, public
+//
+// Synopsis: Returns a reserved block
+//
+// History: 05-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFreeList_GetReserved)
+#endif
+
+inline void *CFreeList::GetReserved(void)
+{
+ olAssert(_pfbHead != NULL);
+ void *pv = (void *)BP_TO_P(SFreeBlock *, _pfbHead);
+ _pfbHead = _pfbHead->pfbNext;
+ return pv;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFreeList::ReturnToReserve, public
+//
+// Synopsis: Puts a block back on the list
+//
+// History: 09-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFreeList_ReturnToReserve)
+#endif
+
+inline void CFreeList::ReturnToReserve(void *pv)
+{
+ olAssert(pv != NULL);
+ SFreeBlock *pfb = (SFreeBlock *)pv;
+ pfb->pfbNext = _pfbHead;
+ _pfbHead = P_TO_BP(CBasedFreeBlockPtr, pfb);
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+#endif // #ifndef __FREELIST_HXX__
diff --git a/private/ole32/stg/h/funcs.hxx b/private/ole32/stg/h/funcs.hxx
new file mode 100644
index 000000000..850457989
--- /dev/null
+++ b/private/ole32/stg/h/funcs.hxx
@@ -0,0 +1,38 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: funcs.hxx
+//
+// Contents: Header for funcs.cxx
+//
+// History: 22-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __FUNCS_HXX__
+#define __FUNCS_HXX__
+
+#include <dfmsp.hxx>
+
+class PSStream;
+
+SCODE VerifyPerms(DWORD grfMode);
+SCODE DeleteIStorageContents(IStorage *pstg);
+SCODE ValidateSNB(SNBW snb);
+SCODE CopySStreamToSStream(PSStream *pstFrom, PSStream *pstTo);
+SCODE NameInSNB(CDfName const *dfn, SNBW snb);
+
+#ifdef OLEWIDECHAR
+SCODE CheckName(WCHAR const *pwcsName);
+#else
+
+// For non-Unicode builds, we verify strings before converting them
+// to wide character strings, so there's no need to recheck them.
+
+# define CheckName(pwcsName) S_OK
+
+#endif
+
+#endif
diff --git a/private/ole32/stg/h/handle.hxx b/private/ole32/stg/h/handle.hxx
new file mode 100644
index 000000000..06560010f
--- /dev/null
+++ b/private/ole32/stg/h/handle.hxx
@@ -0,0 +1,491 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992
+//
+// File: handle.hxx
+//
+// Contents: Defines CHandle
+//
+// Classes: CHandle
+// CStgHandle
+// CStmHandle
+//
+// History: 02-Jan-92 DrewB Created
+// 14-Jan-1992 PhilipL Added Handle Manager
+// 10-May-1992 DrewB Converted to use clump manager
+// 13-May-1992 AlexT Moved contents to msf.hxx
+// 21-Aug-1992 DrewB Redefined handles and
+// added new stg, stm versions
+//
+//---------------------------------------------------------------
+
+#ifndef __HANDLE_HXX__
+#define __HANDLE_HXX__
+
+#include <msf.hxx>
+#include <msffunc.hxx>
+
+//+--------------------------------------------------------------
+//
+// Class: CHandle (h)
+//
+// Purpose: An opaque handle to a directory entry-based object
+//
+// Interface: See below
+//
+// History: 21-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+class CStgHandle;
+class CStmHandle;
+
+class CHandle
+{
+public:
+ inline CHandle(void);
+
+ inline void Init(CMStream *pms,
+ SID sid);
+
+ inline BOOL IsRoot(void) const;
+ inline BOOL IsValid(void) const;
+
+ inline SCODE DestroyEntry(CDfName const *pdfn);
+
+#ifdef HANDLERELEASE
+ inline void Release(void);
+#endif
+
+ inline CMStream *GetMS(void) const;
+ inline SID GetSid(void) const;
+
+private:
+ friend class CStgHandle;
+ friend class CStmHandle;
+
+ CBasedMStreamPtr _pms;
+ SID _sid;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::CHandle, public
+//
+// Synopsis: NULL constructor
+//
+// History: 21-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CHandle::CHandle(void)
+{
+ _pms = NULL;
+ _sid = NOSTREAM;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::Init, public
+//
+// Synopsis: Sets internal data members
+//
+// Arguments: [pms] - Multistream
+// [sid] - SID
+//
+// Returns: Appropriate status code
+//
+// History: 21-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CHandle::Init(CMStream *pms,
+ SID sid)
+{
+ _pms = P_TO_BP(CBasedMStreamPtr, pms);
+ _sid = sid;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::IsRoot, public
+//
+// Synopsis: Whether this is a root handle or not
+//
+// History: 21-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline BOOL CHandle::IsRoot(void) const
+{
+ return _sid == SIDROOT;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::IsValid, public
+//
+// Synopsis: Whether this handle has been initialized
+//
+// History: 21-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline BOOL CHandle::IsValid(void) const
+{
+ return _pms != NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::DestroyEntry, public
+//
+// Synopsis: Destroys this entry
+//
+// Returns: Appropriate status code
+//
+// History: 24-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CHandle::DestroyEntry(CDfName const *pdfn)
+{
+ return _pms->DestroyEntry(_sid, pdfn);
+}
+
+#ifdef HANDLERELEASE
+//+--------------------------------------------------------------
+//
+// Member: CHandle::Release, public
+//
+// Synopsis: Releases the handle
+//
+// History: 24-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CHandle::Release(void)
+{
+ _pms->ReleaseEntry(_sid);
+}
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::GetMS, public
+//
+// Synopsis: Returns the multistream
+//
+// History: 24-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CMStream * CHandle::GetMS(void) const
+{
+ return BP_TO_P(CMStream *, _pms);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::GetSid, public
+//
+// Synopsis: Returns the sid
+//
+// History: 24-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SID CHandle::GetSid(void) const
+{
+ return _sid;
+}
+
+//+--------------------------------------------------------------
+//
+// Class: CStgHandle, (stgh)
+//
+// Purpose: An opaque handle for Multistream directories
+//
+// Interface: See below
+//
+// History: 21-Aug-92 DrewB Created
+// 26-May-95 SusiA Added GetAllTimes
+// 22-Nov-95 SusiA Added SetAllTimes
+//
+//---------------------------------------------------------------
+
+class CStgHandle : public CHandle
+{
+public:
+ inline SCODE CreateEntry(CDfName const *pdfnName,
+ MSENTRYFLAGS const mefFlags,
+ CHandle *ph);
+ inline SCODE GetEntry(CDfName const *pdfnName,
+ MSENTRYFLAGS const mefFlags,
+ CHandle *ph);
+ inline SCODE RenameEntry(CDfName const *pdfnName,
+ CDfName const *pdfnNewName);
+ inline SCODE IsEntry(CDfName const *pdfnName,
+ SEntryBuffer *peb);
+ inline SCODE GetClass(CLSID *pclsid);
+ inline SCODE SetClass(REFCLSID clsid);
+ inline SCODE GetStateBits(DWORD *pgrfStateBits);
+ inline SCODE SetStateBits(DWORD grfStateBits, DWORD grfMask);
+ inline SCODE GetTime(WHICHTIME wt, TIME_T *ptm);
+ inline SCODE SetTime(WHICHTIME wt, TIME_T tm);
+ inline SCODE GetAllTimes(TIME_T *patm,TIME_T *pmtm, TIME_T *pctm);
+ inline SCODE SetAllTimes(TIME_T atm,TIME_T mtm, TIME_T ctm);
+
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CStgHandle::CreateEntry, public
+//
+// Synopsis: Creates an entry
+//
+// History: 24-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CStgHandle::CreateEntry(CDfName const *pdfnName,
+ MSENTRYFLAGS const mefFlags,
+ CHandle *ph)
+{
+ ph->_pms = _pms;
+ return _pms->CreateEntry(_sid, pdfnName, mefFlags, &ph->_sid);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStgHandle::GetEntry, public
+//
+// Synopsis: Gets an entry
+//
+// History: 24-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CStgHandle_GetEntry)
+#endif
+
+inline SCODE CStgHandle::GetEntry(CDfName const *pdfnName,
+ MSENTRYFLAGS const mefFlags,
+ CHandle *ph)
+{
+ SCODE sc;
+ SEntryBuffer eb;
+
+ ph->_pms = _pms;
+
+ sc = _pms->IsEntry(_sid, pdfnName, &eb);
+ if (SUCCEEDED(sc))
+ {
+ msfAssert(eb.sid != NOSTREAM);
+ // entry exists but it may be the wrong type
+
+ if ((mefFlags != MEF_ANY) && (mefFlags != eb.dwType))
+ {
+ sc = STG_E_FILENOTFOUND;
+ }
+ else
+ ph->_sid = eb.sid;
+ }
+ return(sc);
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CStgHandle::RenameEntry, public
+//
+// Synopsis: Renames an entry
+//
+// History: 24-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CStgHandle::RenameEntry(CDfName const *pdfnName,
+ CDfName const *pdfnNewName)
+{
+ return _pms->RenameEntry(_sid, pdfnName, pdfnNewName);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStgHandle::IsEntry, public
+//
+// Synopsis: Gets entry info and checks for existence
+//
+// History: 24-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CStgHandle::IsEntry(CDfName const *pdfnName,
+ SEntryBuffer *peb)
+{
+ return _pms->IsEntry(_sid, pdfnName, peb);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStgHandle::GetClass, public
+//
+// Synopsis: Gets the class ID
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CStgHandle::GetClass(CLSID *pclsid)
+{
+ return _pms->GetClass(_sid, pclsid);
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStgHandle::SetClass, public
+//
+// Synopsis: Sets the class ID
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CStgHandle::SetClass(REFCLSID clsid)
+{
+ return _pms->SetClass(_sid, clsid);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStgHandle::GetStateBits, public
+//
+// Synopsis: Gets state bits
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CStgHandle::GetStateBits(DWORD *pgrfStateBits)
+{
+ return _pms->GetStateBits(_sid, pgrfStateBits);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStgHandle::SetStateBits, public
+//
+// Synopsis: Sets state bits
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CStgHandle::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ return _pms->SetStateBits(_sid, grfStateBits, grfMask);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStgHandle::GetTime, public
+//
+// Synopsis: Returns the time
+//
+// History: 28-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CStgHandle::GetTime(WHICHTIME wt, TIME_T *ptm)
+{
+ return _pms->GetTime(_sid, wt, ptm);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStgHandle::GetAllTimes, public
+//
+// Synopsis: Returns all the times
+//
+// History: 26-May-95 SusiA Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CStgHandle::GetAllTimes(TIME_T *patm,TIME_T *pmtm, TIME_T *pctm )
+{
+ return _pms->GetAllTimes(_sid, patm, pmtm, pctm);
+}
+//+--------------------------------------------------------------
+//
+// Member: CStgHandle::SetAllTimes, public
+//
+// Synopsis: Sets all the times
+//
+// History: 26-May-95 SusiA Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CStgHandle::SetAllTimes(TIME_T atm,TIME_T mtm, TIME_T ctm )
+{
+ return _pms->SetAllTimes(_sid, atm, mtm, ctm);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStgHandle::SetTime, public
+//
+// Synopsis: Sets the time
+//
+// History: 28-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CStgHandle::SetTime(WHICHTIME wt, TIME_T tm)
+{
+ return _pms->SetTime(_sid, wt, tm);
+}
+
+//+--------------------------------------------------------------
+//
+// Class: CStmHandle, (stmh)
+//
+// Purpose: An opaque handle for Multistream streams
+//
+// Interface: See below
+//
+// History: 21-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+class CDirectStream;
+
+class CStmHandle : public CHandle
+{
+public:
+ inline SCODE GetSize(ULONG *pcbSize);
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CStmHandle::GetSize, public
+//
+// Synopsis: Gets the stream size
+//
+// History: 25-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CStmHandle::GetSize(ULONG *pcbSize)
+{
+ return _pms->GetEntrySize(_sid, pcbSize);
+}
+
+#endif // #ifndef __HANDLE_HXX__
+
diff --git a/private/ole32/stg/h/header.hxx b/private/ole32/stg/h/header.hxx
new file mode 100644
index 000000000..a87380b80
--- /dev/null
+++ b/private/ole32/stg/h/header.hxx
@@ -0,0 +1,333 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: header.hxx
+//
+// Contents: MSF header class
+//
+// Classes: CMSFHeader
+//
+// History: 11-Dec-91 PhilipLa Created.
+// 24-Apr-92 AlexT Added data and acccess routines
+// for minifat, ministream.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __HEADER_HXX__
+#define __HEADER_HXX__
+
+#include <msf.hxx>
+#include <storagep.h>
+
+#define HDR_NOFORCE 0x0000
+#define HDR_FORCE 0x0001
+#define HDR_ALL 0x0002
+
+struct SPreHeader : public SStorageFile
+{
+public:
+ USHORT _uMinorVersion;
+ USHORT _uDllVersion;
+ USHORT _uByteOrder;
+
+ USHORT _uSectorShift;
+ USHORT _uMiniSectorShift;
+
+ USHORT _usReserved;
+ ULONG _ulReserved1;
+ ULONG _ulReserved2;
+
+ FSINDEX _csectFat;
+ SECT _sectDirStart;
+
+ DFSIGNATURE _signature;
+
+ ULONG _ulMiniSectorCutoff;
+
+ SECT _sectMiniFatStart;
+ FSINDEX _csectMiniFat;
+
+ SECT _sectDifStart;
+ FSINDEX _csectDif;
+};
+
+
+const USHORT CSECTFATREAL = (HEADERSIZE - sizeof(SPreHeader)) / sizeof(SECT);
+
+const USHORT CSECTFAT = CSECTFATREAL;
+
+class CMSFHeaderData: public SPreHeader
+{
+public:
+ CMSFHeaderData(USHORT uSectorShift);
+
+ SECT _sectFat[CSECTFAT];
+};
+
+
+class CMSFHeader
+{
+public:
+
+ CMSFHeader(USHORT uSectorShift);
+
+ SCODE Validate(VOID) const;
+
+ inline USHORT GetMinorVersion(VOID) const;
+ inline USHORT GetDllVersion(VOID) const;
+
+ inline SCODE SetFatLength(const FSINDEX cFatSect);
+ inline FSINDEX GetFatLength(VOID) const;
+
+ inline SCODE SetMiniFatLength(const FSINDEX cFatSect);
+ inline FSINDEX GetMiniFatLength(VOID) const;
+
+ inline SCODE SetDirStart(const SECT sect);
+ inline SECT GetDirStart(VOID) const;
+
+ inline SCODE SetFatStart(const SECT sect);
+ inline SECT GetFatStart(VOID) const;
+
+ inline SCODE SetMiniFatStart(const SECT sect);
+ inline SECT GetMiniFatStart(VOID) const;
+
+ inline SCODE SetDifStart(const SECT sect);
+ inline SECT GetDifStart(VOID) const;
+
+ inline SCODE SetDifLength(const FSINDEX cFatSect);
+ inline FSINDEX GetDifLength(VOID) const;
+
+ inline SECT GetFatSect(const FSINDEX oSect) const;
+ inline SCODE SetFatSect(const FSINDEX oSect, const SECT sect);
+
+ inline USHORT GetSectorShift(VOID) const;
+ inline USHORT GetMiniSectorShift(VOID) const;
+
+ inline ULONG GetMiniSectorCutoff(VOID) const;
+
+ inline DFSIGNATURE GetCommitSig(VOID) const;
+ inline void SetCommitSig(const DFSIGNATURE sig);
+
+ inline BOOL IsDirty(void) const;
+ inline CMSFHeaderData * GetData(void);
+ inline void SetDirty(void);
+ inline void ResetDirty(void);
+
+private:
+ CMSFHeaderData _hdr;
+ BOOL _fDirty;
+
+ SCODE SetSig(const BYTE *pbSig);
+};
+
+
+inline SCODE CMSFHeader::SetFatLength(const FSINDEX cFatSect)
+{
+ msfDebugOut((DEB_ITRACE, "In CMSFHeader::SetFatLength(%lu)\n",cFatSect));
+ _hdr._csectFat = cFatSect;
+ _fDirty = TRUE;
+ msfDebugOut((DEB_ITRACE, "Out CMSFHeader::SetFatLength()\n"));
+ return S_OK;
+}
+
+inline FSINDEX CMSFHeader::GetFatLength(VOID) const
+{
+ return _hdr._csectFat;
+}
+
+inline SCODE CMSFHeader::SetMiniFatLength(const FSINDEX cFatSect)
+{
+ msfDebugOut((DEB_ITRACE, "In CMSFHeader::SetMiniFatLength(%lu)\n",
+ cFatSect));
+ _hdr._csectMiniFat = cFatSect;
+ _fDirty = TRUE;
+ msfDebugOut((DEB_ITRACE, "Out CMSFHeader::SetMiniFatLength()\n"));
+ return S_OK;
+}
+
+inline FSINDEX CMSFHeader::GetMiniFatLength(VOID) const
+{
+ return _hdr._csectMiniFat;
+}
+
+inline SCODE CMSFHeader::SetDirStart(const SECT sectNew)
+{
+ _hdr._sectDirStart = sectNew;
+ _fDirty = TRUE;
+ return S_OK;
+}
+
+inline SECT CMSFHeader::GetDirStart(VOID) const
+{
+ return _hdr._sectDirStart;
+}
+
+inline SCODE CMSFHeader::SetFatStart(const SECT sectNew)
+{
+ _hdr._sectFat[0] = sectNew;
+ _fDirty = TRUE;
+ return S_OK;
+}
+
+inline SECT CMSFHeader::GetFatStart(VOID) const
+{
+ return _hdr._sectFat[0];
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMSFHeader::SetMiniFatStart
+//
+// Synopsis: Sets minifat's first sector's index
+//
+// Arguments: [sectNew] -- sector index
+//
+// Returns: S_OK (necessary?)
+//
+// Modifies: _sectMiniFatStart
+//
+// History: 12-May-92 AlexT Added minifat support
+//
+//--------------------------------------------------------------------------
+
+inline SCODE CMSFHeader::SetMiniFatStart(const SECT sectNew)
+{
+ _hdr._sectMiniFatStart = sectNew;
+ _fDirty = TRUE;
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMSFHeader::GetMiniFatStart
+//
+// Synopsis: Gets minifat's first sector's index
+//
+// Returns: minifat's first sector's index
+//
+// History: 12-May-92 AlexT Added minifat support
+//
+//--------------------------------------------------------------------------
+
+inline SECT CMSFHeader::GetMiniFatStart(VOID) const
+{
+ return _hdr._sectMiniFatStart;
+}
+
+inline SCODE CMSFHeader::SetDifStart(const SECT sectNew)
+{
+ _hdr._sectDifStart = sectNew;
+ _fDirty = TRUE;
+ return S_OK;
+}
+
+inline SECT CMSFHeader::GetDifStart(VOID) const
+{
+ return _hdr._sectDifStart;
+}
+
+inline SECT CMSFHeader::GetFatSect(const FSINDEX oSect) const
+{
+ msfAssert(oSect < CSECTFAT);
+ return _hdr._sectFat[oSect];
+}
+
+inline SCODE CMSFHeader::SetFatSect(const FSINDEX oSect, const SECT sect)
+{
+ msfAssert(oSect < CSECTFAT);
+ _hdr._sectFat[oSect] = sect;
+ _fDirty = TRUE;
+ return S_OK;
+}
+
+inline SCODE CMSFHeader::SetDifLength(const FSINDEX cFatSect)
+{
+ _hdr._csectDif = cFatSect;
+ _fDirty = TRUE;
+ return S_OK;
+}
+
+
+inline FSINDEX CMSFHeader::GetDifLength(VOID) const
+{
+ return _hdr._csectDif;
+}
+
+
+inline USHORT CMSFHeader::GetSectorShift(VOID) const
+{
+ return _hdr._uSectorShift;
+}
+
+
+inline DFSIGNATURE CMSFHeader::GetCommitSig(VOID) const
+{
+ return _hdr._signature;
+}
+
+inline void CMSFHeader::SetCommitSig(const DFSIGNATURE sig)
+{
+ _hdr._signature = sig;
+ _fDirty = TRUE;
+}
+
+inline USHORT CMSFHeader::GetMiniSectorShift(VOID) const
+{
+ return _hdr._uMiniSectorShift;
+}
+
+inline ULONG CMSFHeader::GetMiniSectorCutoff(VOID) const
+{
+ return _hdr._ulMiniSectorCutoff;
+}
+
+inline USHORT CMSFHeader::GetMinorVersion(VOID) const
+{
+ return _hdr._uMinorVersion;
+}
+
+inline USHORT CMSFHeader::GetDllVersion(VOID) const
+{
+ return _hdr._uDllVersion;
+}
+
+inline BOOL CMSFHeader::IsDirty(void) const
+{
+ return _fDirty;
+}
+
+inline CMSFHeaderData * CMSFHeader::GetData(void)
+{
+ return &_hdr;
+}
+
+inline void CMSFHeader::SetDirty(void)
+{
+ _fDirty = TRUE;
+}
+
+inline void CMSFHeader::ResetDirty(void)
+{
+ _fDirty = FALSE;
+}
+
+
+const ULONG OACCESS = 0xFFFFFF80;
+const ULONG OREADLOCK = OACCESS + 1;
+const ULONG CREADLOCKS = 16;
+const ULONG OUPDATE = OREADLOCK + CREADLOCKS + 1;
+const ULONG OOPENLOCK = OUPDATE + 1;
+const ULONG COPENLOCKS = 20;
+const ULONG OOPENREADLOCK = OOPENLOCK;
+const ULONG OOPENWRITELOCK = OOPENLOCK + COPENLOCKS;
+const ULONG OOPENDENYREADLOCK = OOPENWRITELOCK + COPENLOCKS;
+const ULONG OOPENDENYWRITELOCK = OOPENDENYREADLOCK + COPENLOCKS;
+const ULONG OLOCKREGIONEND = OOPENDENYWRITELOCK + COPENLOCKS;
+
+#ifdef USE_NOSNAPSHOT
+const ULONG OOPENNOSNAPSHOTLOCK = OACCESS - COPENLOCKS;
+#endif
+
+#endif //__HEADER_HXX__
diff --git a/private/ole32/stg/h/infs.hxx b/private/ole32/stg/h/infs.hxx
new file mode 100644
index 000000000..f10f9284d
--- /dev/null
+++ b/private/ole32/stg/h/infs.hxx
@@ -0,0 +1,42 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: infs.hxx
+//
+// Contents: Definition for INativeFileSystem
+//
+// Classes: INativeFileSystem
+//
+// History: 6-May-94 BillMo Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __INFS_HXX__
+#define __INFS_HXX__
+
+#define IID_INativeFileSystem IID_IDfReserved2
+#define IID_IEnableObjectIdCopy IID_IDfReserved3
+
+/****** INativeFileSystem Interface ********************************************/
+
+#undef INTERFACE
+#define INTERFACE INativeFileSystem
+
+
+DECLARE_INTERFACE_(INativeFileSystem, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** INativeFileSystem methods ***
+ STDMETHOD(GetHandle) (THIS_ HANDLE *ph) PURE;
+};
+
+SAFE_INTERFACE_PTR(SafeINativeFileSystem, INativeFileSystem)
+
+#endif // #ifndef __INFS_HXX__
+
diff --git a/private/ole32/stg/h/lock.hxx b/private/ole32/stg/h/lock.hxx
new file mode 100644
index 000000000..ebb36b49b
--- /dev/null
+++ b/private/ole32/stg/h/lock.hxx
@@ -0,0 +1,38 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: lock.hxx
+//
+// Contents: Function definitions for remote exclusion functions
+//
+// History: 09-Mar-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __LOCK_HXX__
+#define __LOCK_HXX__
+
+#define NOLOCK 0x0
+
+SCODE GetAccess(ILockBytes *plst, DFLAGS df, ULONG *poReturn);
+void ReleaseAccess(ILockBytes *plst, DFLAGS df, ULONG offset);
+SCODE GetOpen(ILockBytes *plst, DFLAGS df, BOOL fCheck, ULONG *puReturn);
+void ReleaseOpen(ILockBytes *plst, DFLAGS df, ULONG offset);
+
+// For 32-bit builds we also provide a function that will repeatedly
+// attempt to get access locks for gracefully handling contention
+// Since waiting is virtually impossible in the 16-bit world, it doesn't
+// attempt it
+#if defined(FLAT)
+SCODE WaitForAccess(ILockBytes *plst, DFLAGS df, ULONG *poReturn);
+#else
+#define WaitForAccess(plst, df, poReturn) GetAccess(plst, df, poReturn)
+#endif
+
+#ifndef REF
+#define REMOTE
+#endif //!REF
+
+#endif // #ifndef __LOCK_HXX__
diff --git a/private/ole32/stg/h/logfile.hxx b/private/ole32/stg/h/logfile.hxx
new file mode 100644
index 000000000..33403f9a0
--- /dev/null
+++ b/private/ole32/stg/h/logfile.hxx
@@ -0,0 +1,52 @@
+#ifndef REF
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: logfile.cxx
+//
+// Contents: Logfile protoype functions for DocFile
+//
+// Classes: None.
+//
+// Functions:
+//
+// History: 24-Sep-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __LOGFILE_HXX__
+#define __LOGFILE_HXX__
+
+#if DBG == 1
+
+#define LOGFILESTARTFLAGS RSF_CREATE|RSF_OPENCREATE
+#define LOGFILEDFFLAGS DF_READWRITE
+#define LOGFILENAME L"logfile.txt"
+#define DEB_LOG 0x02000000
+#define DEB_LOWLOG 0x04000000
+
+SCODE _FreeLogFile(void);
+void OutputLogfileMessage(char const *format, ...);
+
+extern WCHAR *_spwcsLogFile;
+
+#define olLog(x) if (olInfoLevel & DEB_LOG) OutputLogfileMessage x
+#define olLowLog(x) if (olInfoLevel & DEB_LOWLOG) OutputLogfileMessage x
+#define FreeLogFile() _FreeLogFile()
+
+#else // !DBG
+
+#define olLog(x)
+#define olLowLog(x)
+#define FreeLogFile() S_OK
+
+#endif // DBG
+
+#endif //__LOGFILE_HXX__
+#else
+#define olLog(x)
+#define olLowLog(x)
+#define FreeLogFile() S_OK
+#endif //!REF
diff --git a/private/ole32/stg/h/msf.hxx b/private/ole32/stg/h/msf.hxx
new file mode 100644
index 000000000..879e72eec
--- /dev/null
+++ b/private/ole32/stg/h/msf.hxx
@@ -0,0 +1,959 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: msf.hxx
+//
+// Contents: Header for MSF for external use
+//
+// Classes: CMStream - Main multi-stream object
+//
+// History: 27-Aug-91 PhilipLa Created.
+// 24-Apr-92 AlexT Added constants for minifat/stream
+//
+//--------------------------------------------------------------------------
+
+#ifndef __MSF_HXX__
+#define __MSF_HXX__
+
+#ifdef REF
+#include <ref.hxx>
+#endif //!REF
+
+#include <dfmsp.hxx>
+#include <error.hxx>
+
+
+#ifndef REF
+#define SECURE
+#endif //!REF
+
+#define msfErr(l, e) ErrJmp(msf, l, e, sc)
+#define msfChkTo(l, e) if (FAILED(sc = (e))) msfErr(l, sc) else 1
+#define msfHChkTo(l, e) if (FAILED(sc = GetScode(e))) msfErr(l, sc) else 1
+#define msfChk(e) msfChkTo(Err, e)
+#define msfHChk(e) msfHChkTo(Err, e)
+#define msfMemTo(l, e) if ((e) == NULL) msfErr(l, STG_E_INSUFFICIENTMEMORY) else 1
+#define msfMem(e) msfMemTo(Err, e)
+
+#if DBG == 1
+DECLARE_DEBUG(msf);
+#endif
+
+#if DBG == 1
+
+#define msfDebugOut(x) msfInlineDebugOut x
+#ifndef REF
+#define msfAssert(e) Win4Assert(e)
+#define msfVerify(e) Win4Assert(e)
+#else
+#include <assert.h>
+#define msfAssert(e) assert(e)
+#define msfVerify(e) assert(e)
+#endif //!REF
+
+#else
+
+#define msfDebugOut(x)
+#define msfAssert(e)
+#define msfVerify(e) (e)
+
+#endif
+
+#if WIN32 == 200
+//SECURE_SIMPLE_MODE means streams in simple mode will zero themselves.
+#define SECURE_SIMPLE_MODE
+//SECURE_STREAMS means streams in regular docfile will zero themselves.
+#define SECURE_STREAMS
+//SECURE_BUFFER means there is a 4K zero-filled buffer available.
+#define SECURE_BUFFER
+//SECURE_TAIL means that regular docfile will write over tail portions of
+// unused sectors.
+#define SECURE_TAIL
+#endif
+//Enable for testing on all platforms.
+//#define SECURE_SIMPLE_MODE
+//#define SECURE_STREAMS
+//#define SECURE_BUFFER
+//#define SECURE_TAIL
+
+
+#if DBG == 1
+#define SECURECHAR 'P'
+#else
+#define SECURECHAR 0
+#endif
+
+#define USE_NEW_GETFREE
+#define DIFAT_LOOKUP_ARRAY
+#define DIFAT_OPTIMIZATIONS
+#define CACHE_ALLOCATE_OPTIMIZATION
+
+//Enable sorting on the page table.
+#define SORTPAGETABLE
+
+//Enable no-scratch mode on all platforms.
+#define USE_NOSCRATCH
+
+//Enable no-snapshot mode on all platforms.
+#define USE_NOSNAPSHOT
+//Enable USE_NOSNAPSHOT_ALWAYS for testig purposes only.
+//#define USE_NOSNAPSHOT_ALWAYS
+
+//Enable coordinated transaction code on Cairo only.
+#if WIN32 == 300
+#define COORD
+#endif
+
+//Enable coordinated transaction code on other platforms
+// For testing only.
+#ifndef COORD
+//#define COORD
+#endif
+
+//Make all transacted opens use coordinate transaction code.
+// For testing only
+//#define HACK_COORD
+
+// MSF entry flags type
+typedef DWORD MSENTRYFLAGS;
+
+// MEF_ANY refers to all entries regardless of type
+const MSENTRYFLAGS MEF_ANY = 255;
+
+//CWCSTREAMNAME is the maximum length (in wide characters) of
+// a stream name.
+const USHORT CWCSTREAMNAME = 32;
+
+//OFFSET and SECT are used to determine positions within
+//a file.
+typedef SHORT OFFSET;
+typedef ULONG SECT;
+
+#ifndef REF
+//MAXINDEX type is used to dodge warnings. It is the
+// largest type for which array[MAXINDEXTYPE] is valid.
+#ifdef FLAT
+
+#define MAXINDEXTYPE ULONG
+
+#else
+#define MAXINDEXTYPE USHORT
+#endif
+#else //NOREF
+#define MAXINDEXTYPE ULONG
+#endif //!REF
+
+//FSINDEX and FSOFFSET are used to determine the position of a sector
+//within the Fat.
+typedef ULONG FSINDEX;
+typedef USHORT FSOFFSET;
+
+// DIRINDEX and DIROFFSET and used to index directory tables
+typedef ULONG DIRINDEX;
+typedef USHORT DIROFFSET;
+
+//Size of a mini sector in bytes.
+const USHORT MINISECTORSHIFT = 6;
+const USHORT MINISECTORSIZE = 1 << MINISECTORSHIFT; //64
+
+//Maximum size of a ministream.
+const USHORT MINISTREAMSIZE=4096;
+
+//Size of a single sector in bytes.
+const USHORT SECTORSHIFT = 9;
+const USHORT SECTORSIZE = 1 << SECTORSHIFT; //512
+
+//Maximum sector shift
+const USHORT MAXSECTORSHIFT = 16;
+
+//Size of header.
+const USHORT HEADERSIZE = SECTORSIZE;
+
+//Size of single DirEntry
+const USHORT DIRENTRYSIZE = SECTORSIZE / 4;
+
+#ifndef REF
+//Size of a single sector in a scratch multistream
+const USHORT SCRATCHSECTORSHIFT = 12;
+const USHORT SCRATCHSECTORSIZE = 1 << SCRATCHSECTORSHIFT; //4096
+#endif //!REF
+
+const ULONG MAX_ULONG = 0xFFFFFFFF;
+
+
+//
+// Predefined Sector Indices
+//
+
+const SECT MAXREGSECT = 0xFFFFFFFA;
+const SECT STREAMSECT = 0xFFFFFFFB;
+const SECT DIFSECT=0xFFFFFFFC;
+const SECT FATSECT=0xFFFFFFFD;
+const SECT ENDOFCHAIN=0xFFFFFFFE;
+const SECT FREESECT=0xFFFFFFFF;
+
+
+//Start of Fat chain
+const SECT SECTFAT = 0;
+
+//Start of directory chain
+const SECT SECTDIR = 1;
+
+//
+// Predefined Stream ID's
+//
+
+//Return code for Directory
+//Used to signal a 'Stream Not Found' condition
+const SID NOSTREAM=0xFFFFFFFF;
+
+//Stream ID of FAT chain
+const SID SIDFAT=0xFFFFFFFE;
+
+//Stream ID of Directory chain
+const SID SIDDIR=0xFFFFFFFD;
+
+//SID for root level object
+const SID SIDROOT = 0;
+
+//SID of MiniFat
+const SID SIDMINIFAT = 0xFFFFFFFC;
+
+//SID of Double-indirect Fat
+const SID SIDDIF = 0xFFFFFFFB;
+
+//Stream ID for MiniStream chain
+const SID SIDMINISTREAM = SIDROOT;
+
+//SID of the largest regular (non-control) SID
+const SID MAXREGSID = 0xFFFFFFFA;
+
+#ifndef REF
+//CSECTPERBLOCK is used in CDeltaList to determine the granularity
+//of the list.
+const USHORT CSECTPERBLOCK = 16;
+#endif //!REF
+
+class MSTREAM_CLASS CMStream;
+
+class PSStream;
+class CDirectStream;
+class CMSFPageTable;
+
+class CStreamCache;
+
+#define FLUSH_ILB TRUE
+
+SAFE_DFBASED_PTR(CBasedMStreamPtr, CMStream);
+#pragma warning(disable: 4284)
+// disable warning about return type of operator->()
+SAFE_DFBASED_PTR(CBasedBytePtr, BYTE);
+SAFE_DFBASED_PTR(CBasedILockBytesPtrPtr, ILockBytes*);
+#pragma warning(default: 4284)
+
+#include <header.hxx>
+#include <fat.hxx>
+#include <dir.hxx>
+#include <difat.hxx>
+#include <cache.hxx>
+
+
+//+----------------------------------------------------------------------
+//
+// Class: CMStream (ms)
+//
+// Purpose: Main interface to multi-streams
+//
+// Interface: See below
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 26-Aug-82 t-chrisy added init function for
+// corrupted mstream
+// 26-May-95 SusiA added GetAllTimes
+// 26-Nov-95 SusiA added SetAllTimes
+// 06-Sep-95 MikeHill Added _fMaintainFLBModifyTimestamp,
+// MaintainFLBModifyTimestamp(),
+// and SetFileLockBytesTime().
+// Notes:
+//
+//-----------------------------------------------------------------------
+
+class MSTREAM_CLASS CMStream : public CMallocBased
+{
+public:
+ MSTREAM_CLASS CMStream(
+ IMalloc *pMalloc,
+ ILockBytes **pplstParent,
+#ifndef REF
+ BOOL fIsScratch,
+#if defined(USE_NOSCRATCH) || defined(USE_NOSNAPSHOT)
+ DFLAGS df,
+#endif
+#endif //!REF
+ USHORT uSectorShift);
+
+#ifndef REF
+ MSTREAM_CLASS CMStream(const CMStream *pms);
+#endif //!REF
+
+ MSTREAM_CLASS ~CMStream();
+
+ SCODE MSTREAM_CLASS Init(VOID);
+
+#ifndef REF
+#ifdef CHKDSK
+ SCODE MSTREAM_CLASS InitCorrupted(VOID);
+#endif
+#endif //!REF
+
+#ifndef REF
+ SCODE MSTREAM_CLASS InitNew(BOOL fDelay, ULARGE_INTEGER uliSize);
+#else
+ SCODE InitNew(ULARGE_INTEGER uliSize);
+#endif //!REF
+
+#ifndef REF
+ SCODE MSTREAM_CLASS InitConvert(BOOL fDelayConvert);
+#else
+ SCODE InitConvert(VOID);
+#endif //!REF
+
+#ifndef REF
+ void MSTREAM_CLASS InitCopy(CMStream *pms);
+#endif //!REF
+
+ SCODE MSTREAM_CLASS InitScratch(CMStream *pmsBase, BOOL fNew);
+
+ void Empty(void);
+
+ inline SCODE MSTREAM_CLASS CreateEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ MSENTRYFLAGS const mefFlags,
+ SID *psid);
+
+ // No implementation, currently unused, placeholder
+ void MSTREAM_CLASS ReleaseEntry(SID const sid);
+
+ inline SCODE MSTREAM_CLASS DestroyEntry(
+ SID const sidParent,
+ CDfName const *pdfn);
+
+ inline SCODE MSTREAM_CLASS KillStream(SECT sectStart, ULONG ulSize);
+
+ inline SCODE MSTREAM_CLASS RenameEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ CDfName const *pdfnNew);
+
+ inline SCODE MSTREAM_CLASS IsEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ SEntryBuffer *peb);
+
+ inline SCODE MSTREAM_CLASS StatEntry(
+ SID const sid,
+ SIterBuffer *pib,
+ STATSTGW *pstatstg);
+
+ SCODE MSTREAM_CLASS GetTime(
+ SID const sid,
+ WHICHTIME const tt,
+ TIME_T *pnt);
+
+ SCODE MSTREAM_CLASS GetAllTimes(
+ SID const sid,
+ TIME_T *patm,
+ TIME_T *pmtm,
+ TIME_T *pctm);
+
+
+ SCODE MSTREAM_CLASS SetAllTimes(
+ SID const sid,
+ TIME_T atm,
+ TIME_T mtm,
+ TIME_T ctm);
+ SCODE MSTREAM_CLASS SetFileLockBytesTime(
+ WHICHTIME const tt,
+ TIME_T nt);
+
+ SCODE MSTREAM_CLASS SetAllFileLockBytesTimes(
+ TIME_T atm,
+ TIME_T mtm,
+ TIME_T ctm);
+
+ SCODE MSTREAM_CLASS SetTime(
+ SID const sid,
+ WHICHTIME const tt,
+ TIME_T nt);
+
+ inline void MSTREAM_CLASS MaintainFLBModifyTimestamp( void );
+
+ inline SCODE MSTREAM_CLASS GetClass(SID const sid,
+ CLSID *pclsid);
+
+ inline SCODE MSTREAM_CLASS SetClass(SID const sid,
+ REFCLSID clsid);
+
+ inline SCODE MSTREAM_CLASS GetStateBits(SID const sid,
+ DWORD *pgrfStateBits);
+
+ inline SCODE MSTREAM_CLASS SetStateBits(SID const sid,
+ DWORD grfStateBits,
+ DWORD grfMask);
+
+#ifdef USE_NOSCRATCH
+ inline void MSTREAM_CLASS SetScratchMS(CMStream *pmsNoScratch);
+#endif
+
+ inline SCODE MSTREAM_CLASS GetEntrySize(
+ SID const sid,
+ ULONG *pcbSize);
+
+ inline SCODE MSTREAM_CLASS GetChild(
+ SID const sid,
+ SID *psid);
+
+ inline SCODE MSTREAM_CLASS FindGreaterEntry(
+ SID sidChildRoot,
+ CDfName const *pdfn,
+ SID *psidResult);
+
+#ifndef REF
+ SCODE MSTREAM_CLASS BeginCopyOnWrite(DWORD const dwFlags);
+
+ SCODE MSTREAM_CLASS EndCopyOnWrite(
+ DWORD const dwCommitFlags,
+ DFLAGS const df);
+
+ SCODE MSTREAM_CLASS ReadSect(
+ SID sid,
+ SECT sect,
+ VOID *pbuf,
+ ULONG& ulRetval);
+
+ SCODE MSTREAM_CLASS WriteSect(
+ SID sid,
+ SECT sect,
+ VOID *pbuf,
+ ULONG& ulRetval);
+#endif //!REF
+
+ inline SCODE MSTREAM_CLASS SetSize(VOID);
+ inline SCODE MSTREAM_CLASS SetMiniSize(VOID);
+
+
+ SCODE MSTREAM_CLASS MWrite(
+ SID sid,
+ BOOL fIsMiniStream,
+ ULONG ulOffset,
+ VOID const HUGEP *pBuffer,
+ ULONG ulCount,
+ CStreamCache *pstmc,
+ ULONG *pulRetVal);
+
+
+ inline CMSFHeader * MSTREAM_CLASS GetHeader(VOID) const;
+ inline CFat * MSTREAM_CLASS GetFat(VOID) const;
+ inline CFat * MSTREAM_CLASS GetMiniFat(VOID) const;
+ inline CDIFat * MSTREAM_CLASS GetDIFat(VOID) const;
+ inline CDirectory * MSTREAM_CLASS GetDir(VOID) const;
+ inline CMSFPageTable * MSTREAM_CLASS GetPageTable(VOID) const;
+#ifndef REF
+ inline ULONG MSTREAM_CLASS GetParentSize(VOID) const;
+#endif //!REF
+
+ inline USHORT GetSectorSize(VOID) const;
+ inline USHORT GetSectorShift(VOID) const;
+ inline USHORT GetSectorMask(VOID) const;
+
+ SCODE MSTREAM_CLASS Flush(BOOL fFlushILB);
+
+ SCODE MSTREAM_CLASS FlushHeader(USHORT uForce);
+
+#ifndef REF
+ inline BOOL MSTREAM_CLASS IsScratch(VOID) const;
+ inline BOOL MSTREAM_CLASS IsUnconverted(VOID) const;
+
+ inline BOOL MSTREAM_CLASS IsInCOW(VOID) const;
+
+ inline BOOL MSTREAM_CLASS IsShadow(VOID) const;
+
+#ifdef USE_NOSCRATCH
+ inline BOOL MSTREAM_CLASS HasNoScratch(VOID) const;
+#endif
+
+#endif //!REF
+
+ inline CDirectStream * MSTREAM_CLASS GetMiniStream(VOID) const;
+ inline ILockBytes * MSTREAM_CLASS GetILB(VOID) const;
+
+ inline SCODE GetSect(SID sid, SECT sect, SECT *psect);
+ inline SCODE GetESect(SID sid, SECT sect, SECT *psect);
+ inline SCODE GetSize(SID sid, ULONG *pulSize);
+
+#ifdef MULTIHEAP
+ IMalloc *GetMalloc(VOID) const;
+#else
+ inline IMalloc *GetMalloc(VOID) const;
+#endif
+
+#ifdef SECURE
+ SCODE SecureSect(
+ const SECT sect,
+ const ULONG ulSize,
+ const BOOL fIsMini);
+#endif //SECURE
+
+ inline CStreamCache * GetDirCache(void) const;
+ inline CStreamCache * GetMiniFatCache(void) const;
+
+ inline SECT MSTREAM_CLASS GetStart(SID sid) const;
+
+private:
+
+ // The ILockBytes ptr can be a CFileStream or custom ILockBytes from app
+ // The ILockbytes ptr is unmarshaled and stored in a CPerContext
+ // The SAFE_ACCESS macros adjust the CDFBasis before every call
+ // with the correct absolute address ILockBytes pointer values
+ CBasedILockBytesPtrPtr _pplstParent; // based ptr to an absolute ptr
+ CMSFHeader _hdr;
+
+ CBasedMSFPageTablePtr _pmpt;
+
+ CDirectory _dir;
+ CFat _fat;
+ CDIFat _fatDif;
+ CFat _fatMini;
+
+ CStreamCache _stmcDir;
+ CStreamCache _stmcMiniFat;
+
+ CBasedDirectStreamPtr _pdsministream;
+
+#ifndef REF
+ CBasedMStreamPtr _pmsShadow;
+
+ CBasedBytePtr _pCopySectBuf;
+#if DBG == 1
+ LONG _uBufferRef;
+#endif
+#endif //!REF
+
+#ifndef REF
+ BOOL const _fIsScratch;
+#ifdef USE_NOSCRATCH
+ BOOL _fIsNoScratch; //TRUE if the multistream is being used
+ //as a scratch MS in NoScratch mode.
+ CBasedMStreamPtr _pmsScratch;
+#endif
+
+#ifdef USE_NOSNAPSHOT
+ BOOL _fIsNoSnapshot;
+#endif
+
+ BOOL _fBlockWrite;
+ BOOL _fTruncate;
+ BOOL _fBlockHeader;
+ BOOL _fNewConvert;
+
+ BOOL _fIsShadow;
+ BOOL _fMaintainFLBModifyTimestamp;
+
+ ULONG _ulParentSize;
+#endif //!REF
+
+ USHORT _uSectorSize;
+ USHORT _uSectorShift;
+ USHORT _uSectorMask;
+
+ IMalloc * const _pMalloc;
+
+ SCODE MSTREAM_CLASS InitCommon(VOID);
+
+#ifndef REF
+ SCODE MSTREAM_CLASS CopySect(
+ SECT sectOld,
+ SECT sectNew,
+ OFFSET oStart,
+ OFFSET oEnd,
+ BYTE const HUGEP *pb,
+ ULONG *pulRetval);
+#endif //!REF
+
+ SCODE MSTREAM_CLASS ConvertILB(SECT sectMax);
+
+ friend SCODE DllGetScratchMultiStream(
+ CMStream **ppms,
+#ifdef USE_NOSCRATCH
+ BOOL fIsNoScratch,
+#endif
+ ILockBytes **pplstStream,
+ CMStream *pmsMaster);
+};
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetSectorSize, public
+//
+// Synopsis: Returns the current sector size
+//
+// History: 05-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline USHORT CMStream::GetSectorSize(VOID) const
+{
+ return _uSectorSize;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetSectorShift, public
+//
+// Synopsis: Returns the current shift for sector math
+//
+// History: 05-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline USHORT CMStream::GetSectorShift(VOID) const
+{
+ return _uSectorShift;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetSectorMask, public
+//
+// Synopsis: Returns the current mask for sector math
+//
+// History: 05-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline USHORT CMStream::GetSectorMask(VOID) const
+{
+ return _uSectorMask;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetHeader, public
+//
+// Synopsis: Returns a pointer to the current header.
+//
+// History: 11-Dec-91 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline CMSFHeader * MSTREAM_CLASS CMStream::GetHeader(VOID) const
+{
+ return (CMSFHeader *)&_hdr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetFat, public
+//
+// Synopsis: Returns a pointer to the current Fat
+//
+// History: 11-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline CFat * MSTREAM_CLASS CMStream::GetFat(VOID) const
+{
+ return (CFat *)&_fat;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::GetMiniFat
+//
+// Synopsis: Returns a pointer to the current minifat
+//
+// History: 12-May-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+inline CFat * MSTREAM_CLASS CMStream::GetMiniFat(VOID) const
+{
+ return (CFat *)&_fatMini;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetDIFat, public
+//
+// Synopsis: Returns pointer to the current Double Indirect Fat
+//
+// History: 11-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline CDIFat * MSTREAM_CLASS CMStream::GetDIFat(VOID) const
+{
+ return (CDIFat *)&_fatDif;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::GetDir
+//
+// Synopsis: Returns a pointer to the current directory
+//
+// History: 14-May-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+inline CDirectory * MSTREAM_CLASS CMStream::GetDir(VOID) const
+{
+ return (CDirectory *)&_dir;
+}
+
+#ifndef REF
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::IsScratch
+//
+// Synopsis: Returns TRUE for scratch multistreams, else FALSE
+//
+// History: 14-May-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+inline BOOL MSTREAM_CLASS CMStream::IsScratch(VOID) const
+{
+ return(_fIsScratch);
+}
+
+#ifdef USE_NOSCRATCH
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::HasNoScratch, public
+//
+// Synopsis: Returns TRUE if this multistream is a base MS in no-scratch
+// mode.
+//
+// History: 11-Apr-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL MSTREAM_CLASS CMStream::HasNoScratch(VOID) const
+{
+ return (_pmsScratch != NULL);
+}
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::IsInCOW
+//
+// Synopsis: Returns TRUE if multistream is in copy-on-write mode
+//
+// History: 24-Feb-93 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline BOOL MSTREAM_CLASS CMStream::IsInCOW(VOID) const
+{
+ return _fBlockHeader;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::IsShadow
+//
+// Synopsis: Returns TRUE for shadow multistreams, else FALSE
+//
+// History: 03-Nov-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline BOOL MSTREAM_CLASS CMStream::IsShadow(VOID) const
+{
+ return _fIsShadow;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::IsUnconverted, public
+//
+// Synopsis: Returns TRUE if multistream is in unconverted state.
+//
+// History: 09-Jun-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline BOOL MSTREAM_CLASS CMStream::IsUnconverted(VOID) const
+{
+ return _fBlockWrite;
+}
+#endif //!REF
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::GetMiniStream
+//
+// Synopsis: Returns pointer to the current ministream
+//
+// History: 15-May-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+inline CDirectStream * MSTREAM_CLASS CMStream::GetMiniStream(VOID)
+ const
+{
+ return BP_TO_P(CDirectStream *, _pdsministream);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::GetILB
+//
+// Synopsis: Returns a pointer to the current parent ILockBytes
+//
+// History: 15-May-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+inline ILockBytes * MSTREAM_CLASS CMStream::GetILB(VOID) const
+{
+ return(*_pplstParent);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::GetPageTable
+//
+// Synopsis: Returns a pointer to the current page table
+//
+// History: 26-Oct-92 PhilipLa Created
+//
+//--------------------------------------------------------------------------
+
+inline CMSFPageTable * MSTREAM_CLASS CMStream::GetPageTable(VOID) const
+{
+ return BP_TO_P(CMSFPageTable *, _pmpt);
+}
+
+#ifndef REF
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::GetParentSize
+//
+// Synopsis: Returns the cached parent size for this multistream.
+// If this is non-zero, it indicates a commit is in
+// progress.
+//
+// History: 01-Feb-93 PhilipLa Created
+//
+//--------------------------------------------------------------------------
+
+inline ULONG MSTREAM_CLASS CMStream::GetParentSize(VOID) const
+{
+ return _ulParentSize;
+}
+#endif //!REF
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::GetDirCache, public
+//
+// Synopsis: Returns a pointer to the directory cache
+//
+// History: 01-Jun-94 PhilipLa Created
+//----------------------------------------------------------------------------
+
+inline CStreamCache * CMStream::GetDirCache(void) const
+{
+ return (CStreamCache *)&_stmcDir;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::GetMiniFatCache, public
+//
+// Synopsis: Returns a pointer to the minifat cache
+//
+// History: 01-Jun-94 PhilipLa Created
+//----------------------------------------------------------------------------
+
+inline CStreamCache * CMStream::GetMiniFatCache(void) const
+{
+ return (CStreamCache *)&_stmcMiniFat;
+}
+
+
+#ifndef STGM_SIMPLE
+//STGM_SIMPLE should be in objbase.h - if it isn't, define it here so
+// we build.
+#define STGM_SIMPLE 0x08000000L
+#endif
+
+#ifndef STGM_NOSCRATCH
+//STGM_NOSCRATCH should be in objbase.h - if it isn't, define it here so
+// we build.
+#define STGM_NOSCRATCH 0x00100000L
+#endif
+
+#ifndef STGM_NOSNAPSHOT
+//STGM_NOSNAPSHOT should be in objbase.h - if it isn't, define it here so
+// we build.
+#define STGM_NOSNAPSHOT 0x00200000L
+#endif
+
+extern SCODE DfCreateSimpDocfile(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage **ppstgOpen);
+
+extern SCODE DllMultiStreamFromStream(
+ IMalloc *pMalloc,
+ CMStream **ppms,
+ ILockBytes **pplstStream,
+ DWORD dwStartFlags,
+ DFLAGS df);
+
+extern SCODE DllMultiStreamFromCorruptedStream(
+ CMStream **ppms,
+ ILockBytes **pplstStream,
+ DWORD dwFlags);
+
+extern void DllReleaseMultiStream(CMStream *pms);
+
+#ifndef REF
+extern SCODE DllGetScratchMultiStream(
+ CMStream **ppms,
+ BOOL fIsNoScratch,
+ ILockBytes **pplstStream,
+ CMStream *pmsMaster);
+#endif //!REF
+
+extern SCODE DllIsMultiStream(ILockBytes *plstStream);
+
+extern SCODE DllGetCommitSig(ILockBytes *plst, DFSIGNATURE *psig);
+
+extern SCODE DllSetCommitSig(ILockBytes *plst, DFSIGNATURE sig);
+
+#if DBG == 1
+extern VOID SetInfoLevel(ULONG x);
+#endif
+
+#ifdef SECURE_BUFFER
+extern BYTE s_bufSecure[MINISTREAMSIZE];
+#endif
+
+#endif //__MSF_HXX__
+
diff --git a/private/ole32/stg/h/msffunc.hxx b/private/ole32/stg/h/msffunc.hxx
new file mode 100644
index 000000000..334f80e7c
--- /dev/null
+++ b/private/ole32/stg/h/msffunc.hxx
@@ -0,0 +1,435 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: msffunc.hxx
+//
+// Contents: Multistream inline functions
+//
+// Classes: None.
+//
+// History: 14-Seo-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __MSFFUNC_HXX__
+#define __MSFFUNC_HXX__
+
+#include <msf.hxx>
+#include <dir.hxx>
+#include <dirfunc.hxx>
+
+#if !defined(MULTIHEAP) // moved to msf.cxx
+//+--------------------------------------------------------------
+//
+// Member: CMStream::GetMalloc, public
+//
+// Synopsis: Returns the allocator associated with this multistream
+//
+// History: 05-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline IMalloc * CMStream::GetMalloc(VOID) const
+{
+ return (IMalloc *)_pMalloc;
+}
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::RenameEntry, public
+//
+// Synposis: Rename an entry.
+//
+// Arguments: [sidParent] - Parent SID
+// [pdfn] - Old name
+// [pdfnNew] -- New name
+//
+// Returns: S_OK otherwise
+//
+// Algorithm: Call through to CDirectory::RenameEntry
+//
+// History: 27-Aug-91 PhilipLa Created.
+// 07-Jan-92 PhilipLa Converted to use handle.
+// 14-Sep-92 PhilipLa inlined.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+inline SCODE MSTREAM_CLASS CMStream::RenameEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ CDfName const *pdfnNew)
+{
+ return _dir.RenameEntry(sidParent, pdfn, pdfnNew);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::IsEntry, public
+//
+// Synposis: Determine if a given entry is present in a multistream
+//
+// Arguments: [sidParent] - Parent SID
+// [pdfn] -- Name of entry to be located
+// [peb] - Entry block to fill in
+//
+// Returns: S_OK if entry exists.
+// STG_E_FILENOTFOUND if it doesn't.
+//
+// History: 27-Aug-91 PhilipLa Created.
+// 07-Jan-92 PhilipLa Converted to use handle
+// 14-Sep-92 PhilipLa inlined.
+//
+//---------------------------------------------------------------------------
+
+inline SCODE MSTREAM_CLASS CMStream::IsEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ SEntryBuffer *peb)
+{
+ return _dir.IsEntry(sidParent, pdfn, peb);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::CreateEntry, public
+//
+// Synposis: Allows creation of new entries
+//
+// Arguments: [sidParent] -- SID of parent entry
+// [pdfn] -- Name of new entry
+// [mefFlags] -- Flags to be set on new entry
+// [psid] -- Location for return SID
+//
+// Returns: S_OK if call completed OK.
+// STG_E_FILEALREADYEXISTS if stream already exists
+//
+// History: 20-Jul-91 PhilipLa Created.
+// 27-Aug-91 PhilipLa Modified to fit new API
+// 06-Jan-91 PhilipLa Changed from CreateStream to
+// CreateEntry
+// 14-Sep-92 PhilipLa inlined.
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_CreateEntry)
+#endif
+
+inline SCODE MSTREAM_CLASS CMStream::CreateEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ MSENTRYFLAGS const mefFlags,
+ SID *psid)
+{
+ return _dir.CreateEntry(sidParent, pdfn, mefFlags, psid);
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::StatEntry
+//
+// Synopsis: For a given handle, fill in the Multistream specific
+// information of a STATSTG.
+//
+// Arguments: [sid] -- SID that information is requested on.
+// [pib] -- Fast iterator buffer to fill in.
+// [pstatstg] -- STATSTG to fill in.
+//
+// Returns: S_OK
+//
+// History: 25-Mar-92 PhilipLa Created.
+// 14-Sep-92 PhilipLa inlined.
+//
+//--------------------------------------------------------------------------
+
+inline SCODE MSTREAM_CLASS CMStream::StatEntry(SID const sid,
+ SIterBuffer *pib,
+ STATSTGW *pstatstg)
+{
+ return _dir.StatEntry(sid, pib, pstatstg);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::GetChild, public
+//
+// Synposis: Return the child SID for a directory entry
+//
+// Arguments: [sid] - Parent
+// [psid] - Child SID return
+//
+// Returns: Appropriate status code
+//
+// History: 19-Apr-93 DrewB Created
+//
+//---------------------------------------------------------------------------
+
+inline SCODE MSTREAM_CLASS CMStream::GetChild(
+ SID const sid,
+ SID *psid)
+{
+ return _dir.GetChild(sid, psid);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::FindGreaterEntry, public
+//
+// Synopsis: Returns the next greater entry for the given parent SID
+//
+// Arguments: [sidParent] - SID of parent storage
+// [CDfName *pdfnKey] - Previous key
+// [psid] - Result
+//
+// Returns: Appropriate status code
+//
+// Modifies: [psid]
+//
+// History: 16-Apr-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE MSTREAM_CLASS CMStream::FindGreaterEntry(SID sidParent,
+ CDfName const *pdfnKey,
+ SID *psid)
+{
+ return _dir.FindGreaterEntry(sidParent, pdfnKey, psid);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::MaintainFLBModifyTimestamp, public
+//
+// Synopsis: Calling this member indicates that this object should
+// maintain the IFileLockBytes modify-timestamp. This capability
+// is provided for backwards compatability. When this flag is not
+// set, CMStream need not maintain the modify timestamp on the underlying
+// docfile. That timestamp is maintained internally by IFileLockBytes
+// (actually, by the Filesystem). It is occasionally necessary, however,
+// for CMStream to take over this responsability. When such an
+// occasion occurs, this member is called, the _fMaintainFLBModifyTimestamp
+// flag is set, and the SetTime member knows to maintain the
+// the modify timestamp.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// Algorithm: Set the _fMaintainFLBModifyTimestamp flag.
+//
+// History: 06-Sep-95 MikeHill Created.
+//
+//--------------------------------------------------------------------------
+
+inline void MSTREAM_CLASS CMStream::MaintainFLBModifyTimestamp( void )
+{
+ _fMaintainFLBModifyTimestamp = TRUE;
+
+ return;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::GetClass, public
+//
+// Synopsis: Gets the class ID
+//
+// Arguments: [pclsid] - Class ID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pclsid]
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CMStream::GetClass(SID const sid,
+ CLSID *pclsid)
+{
+ return _dir.GetClassId(sid, pclsid);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::SetClass, public
+//
+// Synopsis: Sets the class ID
+//
+// Arguments: [clsid] - Class ID
+//
+// Returns: Appropriate status code
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CMStream::SetClass(SID const sid,
+ REFCLSID clsid)
+{
+ return _dir.SetClassId(sid, clsid);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::GetStateBits, public
+//
+// Synopsis: Gets state bits
+//
+// Arguments: [pgrfStateBits] - State bits return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pgrfStateBits]
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CMStream::GetStateBits(SID const sid,
+ DWORD *pgrfStateBits)
+{
+ return _dir.GetUserFlags(sid, pgrfStateBits);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::SetStateBits, public
+//
+// Synopsis: Sets state bits
+//
+// Arguments: [grfStateBits] - State bits
+//
+// Returns: Appropriate status code
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CMStream::SetStateBits(SID const sid,
+ DWORD grfStateBits,
+ DWORD grfMask)
+{
+ return _dir.SetUserFlags(sid, grfStateBits, grfMask);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetEntrySize, public
+//
+// Synopsis: Return the size of an entry
+//
+// Arguments: [sid] - SID of entry
+// [pcbSize] -- Location for return of size
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Ask directory for size
+//
+// History: 07-Jan-92 PhilipLa Created.
+// 25-Aug-92 DrewB Created from GetStream
+// 14-Sep-92 PhilipLa inlined.
+//
+//--------------------------------------------------------------------------
+
+inline SCODE MSTREAM_CLASS CMStream::GetEntrySize(SID const sid,
+ ULONG *pcbSize)
+{
+ return _dir.GetSize(sid, pcbSize);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::DestroyEntry
+//
+// Synposis: Delete a directory entry from a multi-stream.
+//
+// Effects: Modifies directory.
+//
+// Arguments: [sidParent] - Parent SID
+// [pdfn] - Name of entry
+//
+// Returns: S_OK if operation completed successfully.
+//
+// Algorithm: Set information on entry to default "free" case.
+// Return S_OK
+//
+// History: 27-Aug-91 PhilipLa Created.
+// 07-Jan-92 PhilipLa Converted to use handle.
+// 20-Oct-92 AlexT Removed flags
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_DestroyEntry)
+#endif
+
+inline SCODE MSTREAM_CLASS CMStream::DestroyEntry(SID const sidParent,
+ CDfName const *pdfn)
+{
+ SCODE sc;
+
+ msfDebugOut((DEB_ITRACE, "In CMStream::DestroyEntry()\n"));
+
+ // Two cases:
+ // pdfn == NULL - destroy all children of sidParent
+ // pdfn != NULL - destroy the named child of sidParent
+
+ if (pdfn == NULL)
+ sc = _dir.DestroyAllChildren(sidParent);
+ else
+ sc = _dir.DestroyChild(sidParent, pdfn);
+
+ msfDebugOut((DEB_ITRACE, "Out CMStream::DestroyEntry()\n"));
+
+ return sc;
+}
+
+#ifdef USE_NOSCRATCH
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::SetNoScratchMS, public
+//
+// Synopsis: Set the multi-stream to use for NoScratch processing.
+//
+// Arguments: [pmsNoScratch] -- Pointer to NoScratch multistream
+//
+// Returns: void
+//
+// History: 10-Mar-95 PhilipLa Created
+//
+// Notes: This function is called on a base multistream during
+// the initialization path to indicate that the user has
+// opened using STGM_NOSCRATCH
+//
+//----------------------------------------------------------------------------
+
+inline void CMStream::SetScratchMS(CMStream *pmsNoScratch)
+{
+ _pmsScratch = P_TO_BP(CBasedMStreamPtr, pmsNoScratch);
+ _fat.SetNoScratch(pmsNoScratch->GetMiniFat());
+}
+#endif
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+#endif //__MSFFUNC_HXX__
diff --git a/private/ole32/stg/h/ntenm.hxx b/private/ole32/stg/h/ntenm.hxx
new file mode 100644
index 000000000..01fab50e1
--- /dev/null
+++ b/private/ole32/stg/h/ntenm.hxx
@@ -0,0 +1,104 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ntenm.hxx
+//
+// Contents: NT handle enumerator
+//
+// Classes: CNtEnum
+//
+// History: 12-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __NTENM_HXX__
+#define __NTENM_HXX__
+
+// Name return control
+#define NTE_NONAME 0
+#define NTE_BUFFERNAME 1
+#define NTE_STATNAME 2
+
+//+---------------------------------------------------------------------------
+//
+// Class: CNtEnum (nte)
+//
+// Purpose: Enumerates using an NT handle
+//
+// Interface: See below
+//
+// History: 12-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CNtEnum
+{
+public:
+ CNtEnum (BOOL fIsStorage = TRUE) { _fIsStorage = fIsStorage; _afsi = _pfsi = _pfsiEnd = NULL; }
+ ~CNtEnum () { if (_afsi) delete [] _afsi; }
+ SCODE InitFromHandle(HANDLE h, BOOL fReset);
+
+ SCODE Next(STATSTG *pstat, WCHAR *pwcsName, DWORD dwNte, FILEDIR *pfd);
+ SCODE NextOfs(STATSTG *pstat, WCHAR *pwcsName, DWORD dwNte, FILEDIR *pfd);
+ inline void Reset(void);
+ inline HANDLE GetHandle(void);
+
+private:
+ SCODE EnumDir (STATSTG *pstat, WCHAR *pwcsName, DWORD dwNte, FILEDIR *pfd);
+ SCODE BeginEnumStm (void);
+ SCODE EnumStm (STATSTG *pstat, WCHAR *pwcsName, DWORD dwNte, FILEDIR *pfd);
+
+ enum NtEnumStatus {
+ NES_RESET_PENDING,
+ NES_ENUM_DIR,
+ };
+
+ enum {
+ CFSI_DEFAULT = 32
+ };
+
+ NtEnumStatus _nes;
+ NuSafeNtHandle _h;
+ int _cfsi;
+ FILE_STREAM_INFORMATION *_afsi;
+ FILE_STREAM_INFORMATION *_pfsi;
+ FILE_STREAM_INFORMATION *_pfsiEnd;
+ BOOL _fIsStorage;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtEnum::Reset, public
+//
+// Synopsis: Resets the enumeration
+//
+// History: 12-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CNtEnum::Reset(void)
+{
+ ssDebugOut((DEB_ITRACE, "In CNtEnum::Reset:%p()\n", this));
+ _nes = NES_RESET_PENDING;
+ ssDebugOut((DEB_ITRACE, "Out CNtEnum::Reset\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtEnum::GetHandle, public
+//
+// Synopsis: Returns the handle
+//
+// History: 12-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline HANDLE CNtEnum::GetHandle(void)
+{
+ return _h;
+}
+
+#endif // __NTENM_HXX__
+
diff --git a/private/ole32/stg/h/ntlkb.hxx b/private/ole32/stg/h/ntlkb.hxx
new file mode 100644
index 000000000..d7237253c
--- /dev/null
+++ b/private/ole32/stg/h/ntlkb.hxx
@@ -0,0 +1,104 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ntlkb.hxx
+//
+// Contents: ILockBytes for an NT handle
+//
+// History: 17-Aug-93 DrewB Created
+//
+// Notes: This implementation remembers whether it lives on OFS or
+// not to support lock spinning in WaitForAccess
+// If lock spinning is removed, the fOfs flag can be taken out
+//
+//----------------------------------------------------------------------------
+
+#ifndef __NTLKB_HXX__
+#define __NTLKB_HXX__
+
+#include <otrack.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: CNtLockBytes (nlb)
+//
+// Purpose: ILockBytes for an NT handle
+//
+// Interface: ILockBytes
+//
+// History: 17-Aug-93 DrewB Created
+// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
+//
+//----------------------------------------------------------------------------
+
+interface CNtLockBytes
+ : INHERIT_TRACKING,
+ public ILockBytes
+{
+public:
+ CNtLockBytes(BOOL fOfs);
+ SCODE InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSECURITY_ATTRIBUTES pssSecurity);
+ SCODE InitFromHandle(HANDLE h,
+ WCHAR const *pwcsName,
+ DWORD grfMode);
+#if DBG == 1
+ ~CNtLockBytes(void);
+#endif
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // ILockBytes
+ STDMETHOD(ReadAt)(ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbRead);
+ STDMETHOD(WriteAt)(ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ STDMETHOD(Flush)(void);
+ STDMETHOD(SetSize)(ULARGE_INTEGER cb);
+ STDMETHOD(LockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+
+ // New
+ inline HANDLE GetHandle(void);
+
+private:
+ DWORD _grfMode;
+ NuSafeNtHandle _h;
+ BOOL _fOfs;
+ WCHAR _wcDrive;
+};
+
+SAFE_INTERFACE_PTR(SafeCNtLockBytes, CNtLockBytes);
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtLockBytes::GetHandle, public
+//
+// Synopsis: Returns the handle
+//
+// History: 17-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline HANDLE CNtLockBytes::GetHandle(void)
+{
+ return (HANDLE)_h;
+}
+
+#endif // #ifndef __NTLKB_HXX__
diff --git a/private/ole32/stg/h/ntsupp.hxx b/private/ole32/stg/h/ntsupp.hxx
new file mode 100644
index 000000000..2b54a757b
--- /dev/null
+++ b/private/ole32/stg/h/ntsupp.hxx
@@ -0,0 +1,80 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ntsupp.hxx
+//
+// Contents: NT support routines
+//
+// History: 29-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __NTSUPP_HXX__
+#define __NTSUPP_HXX__
+
+extern "C" {
+#include <nt.h>
+}
+
+#if DBG == 1
+#define dbgNtVerSucc(e) Win4Assert(NT_SUCCESS(e))
+#else
+#define dbgNtVerSucc(e) (e)
+#endif
+
+#define FILETIME_TO_LARGE_INTEGER(pftm, pli) \
+ (pli)->LowPart = (pftm)->dwLowDateTime, \
+ (pli)->HighPart = (pftm)->dwHighDateTime
+#define LARGE_INTEGER_TO_FILETIME(pli, pftm) \
+ (pftm)->dwLowDateTime = (pli)->LowPart, \
+ (pftm)->dwHighDateTime = (pli)->HighPart
+
+SCODE CheckFdName(WCHAR const *pwcs);
+SCODE ModeToNtFlags(DWORD grfMode,
+ CREATEOPEN co,
+ FILEDIR fd,
+ ACCESS_MASK *pam,
+ ULONG *pulAttributes,
+ ULONG *pulSharing,
+ ULONG *pulCreateDisposition,
+ ULONG *pulCreateOptions);
+SCODE GetNtHandle(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD grfAttrs,
+ CREATEOPEN co,
+ FILEDIR fd,
+ LPSECURITY_ATTRIBUTES pssSecurity,
+ HANDLE *ph);
+SCODE ReopenNtHandle(HANDLE h, DWORD grfMode, FILEDIR fd, HANDLE *ph);
+SCODE DupNtHandle(HANDLE h, HANDLE *ph);
+SCODE NtStatusToScode(NTSTATUS nts);
+SCODE StatNtHandle(HANDLE h,
+ DWORD grfStatFlag,
+ ULONG cbExtra,
+ STATSTG *pstat,
+ WCHAR *pwcsName,
+ DWORD *dwAttrs,
+ FILEDIR *pfd);
+SCODE HandleRefersToOfsVolume(HANDLE h);
+SCODE RefersToOfsVolume(WCHAR const *pwcsPath, CREATEOPEN co);
+SCODE SetTimes(HANDLE h,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+SCODE SetNtFileAttributes (HANDLE h, ULONG grfAttr);
+SCODE GetFileOrDirHandle(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ HANDLE *ph,
+ CLSID *pclsid,
+ BOOL *pfOfs,
+ FILEDIR *pfd);
+SCODE NameNtHandle (HANDLE h, WCHAR wcDrive, WCHAR *wcBuffer,
+ const WCHAR *wcFile);
+
+WCHAR * MakeStreamName(const WCHAR *pwcsName);
+
+#endif // #ifndef __NTSUPP_HXX__
diff --git a/private/ole32/stg/h/ole.hxx b/private/ole32/stg/h/ole.hxx
new file mode 100644
index 000000000..b887da75d
--- /dev/null
+++ b/private/ole32/stg/h/ole.hxx
@@ -0,0 +1,72 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: ole.hxx
+//
+// Contents: OLE Project Header File
+//
+// History: 19-Sep-91 DrewB Created.
+// 10-Feb-92 DrewB Updated debugging definitions
+// 13-Mar-92 DrewB Added olVerify, INDINST
+// 19-Mar-92 DrewB Added olErr
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OLE_HXX__
+#define __OLE_HXX__
+
+#include <error.hxx>
+
+#define olErr(l, e) ErrJmp(ol, l, e, sc)
+#define olChkTo(l, e) if (FAILED(sc = (e))) olErr(l, sc) else 1
+#define olHChkTo(l, e) if (FAILED(sc = DfGetScode(e))) olErr(l, sc) else 1
+#define olChk(e) olChkTo(EH_Err, e)
+#define olHChk(e) olHChkTo(EH_Err, e)
+#define olMemTo(l, e) \
+ if ((e) == NULL) olErr(l, STG_E_INSUFFICIENTMEMORY) else 1
+#define olMem(e) olMemTo(EH_Err, e)
+
+#ifndef REF
+#include <debnot.h>
+#else
+#include <ref.hxx>
+#endif //!REF
+
+#if DBG == 1
+DECLARE_DEBUG(ol);
+#endif
+
+#if DBG == 1
+
+#define olDebugOut(x) olInlineDebugOut x
+#ifndef REF
+#define olAssert(e) Win4Assert(e)
+#define olVerify(e) Win4Assert(e)
+#define olAssSucc(e) Win4Assert(SUCCEEDED(e))
+#define olVerSucc(e) Win4Assert(SUCCEEDED(e))
+#define olHVerSucc(e) Win4Assert(SUCCEEDED(DfGetScode(e)))
+#else
+#include <assert.h>
+#define olAssert(e) assert(e)
+#define olVerify(e) assert(e)
+#define olAssSucc(e) assert(SUCCEEDED(e))
+#define olVerSucc(e) assert(SUCCEEDED(e))
+#define olHVerSucc(e) assert(SUCCEEDED(DfGetScode(e)))
+#endif //!REF
+
+
+#else
+
+#define olDebugOut(x)
+#define olAssert(e)
+#define olVerify(e) (e)
+#define olAssSucc(e)
+#define olVerSucc(e) (e)
+#define olHVerSucc(e) (e)
+
+#endif
+
+
+#endif
diff --git a/private/ole32/stg/h/omarshal.hxx b/private/ole32/stg/h/omarshal.hxx
new file mode 100644
index 000000000..30af93d2d
--- /dev/null
+++ b/private/ole32/stg/h/omarshal.hxx
@@ -0,0 +1,246 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: omarshal.hxx
+//
+// Contents: OLE2 unmarshalling support for OFS handles
+//
+// Classes: CNtHandleUnmarshalFactory
+//
+// History: 25-Oct-95 HenryLee Created
+//
+// Notes: Adapted from OLE2 dfunmfct.hxx and dfunmfct.cxx
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OMARSHAL_HXX__
+#define __OMARSHAL_HXX__
+
+extern const CLSID CLSID_NtHandleMarshal;
+
+//+---------------------------------------------------------------------------
+//
+// Class: CNtHandleMarshalPacket
+//
+// Purpose: Marshaling parameters to be saved/retrieve from IStream
+//
+// Interface: See below
+//
+// History: 25-Oct-95 HenryLee Created
+//
+// Notes: data members are got/put into the Marshaling IStream
+//
+//----------------------------------------------------------------------------
+struct CNtHandleMarshalPacket
+{
+ IID iid; // interface to marshal/unmarshal
+ DWORD dwMarshFlags; // marshaling flags
+ DWORD dwPId; // source process id
+ DWORD dwTId; // source thread id
+ DWORD grfMode; // mode bits of source object
+ DWORD dwStgfmt; // type of object to marshal/unmarshal
+ HANDLE hSource; // handle to source object
+ DWORD reserved1; // future use
+ DWORD reserved2; // future use
+};
+
+//+---------------------------------------------------------------------------
+//
+// Class: CNtHandleUnmarshalFactory
+//
+// Purpose: Implements OLE2 unmarshalling support
+//
+// Interface: See below
+//
+// History: 25-Oct-95 HenryLee Created
+//
+// Notes: This class is intended to be used statically
+// rather than dynamically with initialization being
+// deferred past construction to avoid unnecessary
+// initialization of static objects.
+// Init should be called to initialize in place of
+// a constructor.
+//
+//----------------------------------------------------------------------------
+
+class CNtHandleUnmarshalFactory : public IMarshal, public IClassFactory
+{
+
+public:
+ inline CNtHandleUnmarshalFactory();
+ inline ULONG _AddRef() const { return 1; };
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)();
+ STDMETHOD_(ULONG,Release)();
+
+ // IMarshal
+ STDMETHOD(GetUnmarshalClass)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID *ppv);
+ STDMETHOD(ReleaseMarshalData)(IStream *pStm);
+ STDMETHOD(DisconnectObject)(DWORD dwReserved);
+
+ // IClassFactory
+ STDMETHOD(CreateInstance)(IUnknown *pUnkOuter,
+ REFIID riid,
+ LPVOID *ppunkObject);
+ STDMETHOD(LockServer)(BOOL fLock);
+
+ // New methods
+ inline SCODE Validate() const;
+
+private:
+};
+
+extern CNtHandleUnmarshalFactory sCNtHandleUnmarshalFactory;
+
+//+--------------------------------------------------------------
+//
+// Member: CNtHandleUnmarshalFactory::Validate, public
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDPOINTER for failure
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CNtHandleUnmarshalFactory::Validate() const
+{
+ return (this == NULL) ? STG_E_INVALIDPOINTER : S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtHandleUnmarshalFactory::CNtHandleUnmarshalFactory, public
+//
+// Synopsis: Constructor
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+inline CNtHandleUnmarshalFactory::CNtHandleUnmarshalFactory()
+{
+}
+
+//+---------------------------------------------------------------------------
+//
+// Class: CNtHandleMarshal
+//
+// Purpose: Implements OLE2 marshalling support
+//
+// Interface: See below
+//
+// History: 25-Oct-95 HenryLee Created
+//
+// Notes: This class is intended to be inherited into
+// classes that need custom marshalling on a
+// NT or OFS file handle. This is an abstract class.
+// The derived class provides the IUnknown methods.
+//
+//----------------------------------------------------------------------------
+
+class CNtHandleMarshal: public IMarshal
+{
+
+public:
+ inline CNtHandleMarshal();
+
+ // IMarshal
+ STDMETHOD(GetUnmarshalClass)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID *ppv);
+ STDMETHOD(ReleaseMarshalData)(IStream *pStm);
+ STDMETHOD(DisconnectObject)(DWORD dwReserved);
+
+protected:
+ inline SCODE InitNtHandleMarshal (HANDLE h, DWORD grfMode, DWORD dwStgfmt);
+private:
+ HANDLE _handle;
+ DWORD _grfModeMarshal;
+ DWORD _dwStgfmt;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtHandleMarshal::CNtHandleMarshal, public
+//
+// Synopsis: Constructor
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+inline CNtHandleMarshal::CNtHandleMarshal() : _handle(NULL),
+ _grfModeMarshal(0),
+ _dwStgfmt(STGFMT_ANY)
+{
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CNtHandleMarshal::InitNtHandleMarshal, protected
+//
+// Synopsis: Initialize private members after construction
+//
+// History: 25-Oct-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CNtHandleMarshal::InitNtHandleMarshal( HANDLE h,
+ DWORD grfMode,
+ DWORD dwStgfmt)
+{
+ if (h == NULL)
+ return STG_E_INVALIDHANDLE;
+
+ _handle = h;
+ _grfModeMarshal = grfMode;
+ _dwStgfmt = dwStgfmt;
+ return S_OK;
+}
+
+
+#endif // #ifndef __OMARSHAL_HXX__
diff --git a/private/ole32/stg/h/overlap.hxx b/private/ole32/stg/h/overlap.hxx
new file mode 100644
index 000000000..969dddad0
--- /dev/null
+++ b/private/ole32/stg/h/overlap.hxx
@@ -0,0 +1,99 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995.
+//
+// File: overlap.hxx
+//
+// Contents: COverlappedStream header
+//
+// Classes: COverlappedStream
+//
+// History: 19-Sep-95 HenryLee Created
+//
+// Notes: Requires NtIoApi.h
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OVERLAP_HXX__
+#define __OVERLAP_HXX__
+
+#include <storext.h>
+
+//+---------------------------------------------------------------------------
+//
+// Class: COverlappedStream
+//
+// Purpose:Implements IOverlappedStream for OFS streams and flat files
+// (as opposed to overlapped I/O for IStream for docfiles)
+//
+// Notes: This is class with a partial implementation
+// To use this class, inherit this into another class that
+// implements IUnknown and IStream (and expose QueryInterface)
+//
+//----------------------------------------------------------------------------
+
+class COverlappedStream : public IOverlappedStream
+{
+public:
+ inline COverlappedStream (HANDLE h = NULL);
+ inline ~COverlappedStream ();
+
+ // IOverlappedStream
+ STDMETHOD(ReadOverlapped) (
+ /* [in, size_is(cb)] */ void * pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG * pcbRead,
+ /* [in,out] */ STGOVERLAPPED *lpOverlapped);
+
+ STDMETHOD(WriteOverlapped) (
+ /* [in, size_is(cb)] */ void *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG * pcbWritten,
+ /* [in,out] */ STGOVERLAPPED *lpOverlapped);
+
+ STDMETHOD(GetOverlappedResult) (
+ /* [in, out] */ STGOVERLAPPED *lpOverlapped,
+ /* [out] */ DWORD * plcbTransfer,
+ /* [in] */ BOOL fWait);
+
+protected:
+ NuSafeNtHandle _h;
+
+private:
+
+};
+
+SAFE_INTERFACE_PTR(SafeCOverlappedStream, COverlappedStream);
+#define StgOverlapped_SIG LONGSIG('O', 'V', 'E', 'R')
+#define StgOverlapped_SIGDEL LONGSIG('O', 'v', 'E', 'r')
+
+//+-------------------------------------------------------------------
+//
+// Member: COverlappedStream::COverlappedStream
+//
+// Synopsis: Initialize the generic overlapped object.
+//
+// Arguments: none
+//
+//--------------------------------------------------------------------
+
+inline COverlappedStream::COverlappedStream(HANDLE h) : _h(h)
+{
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: COverlappedStream::~COverlappedStream
+//
+// Synopsis: Destroys the generic overlapped object.
+//
+// Arguments: none
+//
+//--------------------------------------------------------------------
+
+inline COverlappedStream::~COverlappedStream()
+{
+}
+
+#endif // #ifndef __OVERLAP_HXX__
diff --git a/private/ole32/stg/h/page.hxx b/private/ole32/stg/h/page.hxx
new file mode 100644
index 000000000..594ed43ed
--- /dev/null
+++ b/private/ole32/stg/h/page.hxx
@@ -0,0 +1,727 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: page.hxx
+//
+// Contents: Paging classes for MSF
+//
+// Classes: CMSFPage
+// CMSFPageTable
+//
+// Functions:
+//
+// History: 28-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __PAGE_HXX__
+#define __PAGE_HXX__
+
+class CPagedVector;
+
+#define STG_S_NEWPAGE \
+ MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_STORAGE, 0x2FF)
+
+#define FB_NONE 0x00000000
+#define FB_DIRTY 0x00000001
+#define FB_NEW 0x00000002
+#define FB_TOUCHED 0x10000000
+
+class CMSFPageTable;
+class CMSFPage;
+
+SAFE_DFBASED_PTR(CBasedPagedVectorPtr, CPagedVector);
+SAFE_DFBASED_PTR(CBasedMSFPageTablePtr, CMSFPageTable);
+SAFE_DFBASED_PTR(CBasedMSFPagePtr, CMSFPage);
+
+//+---------------------------------------------------------------------------
+//
+// Class: CMSFPage (mp)
+//
+// Purpose: Contain MSF data in a form that is swappable to disk
+//
+// Interface: See below.
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifndef REF
+#if _MSC_VER == 700
+#pragma warning(disable:4001)
+#elif _MSC_VER >= 800
+#pragma warning(disable:4200)
+#endif
+#endif //!REF
+
+class CMSFPage : public CMallocBased
+{
+public:
+ void * operator new(size_t size, IMalloc * const pMalloc,
+ size_t sizeData);
+
+#if DBG == 1
+ CMSFPage(CMSFPage *pmpNext, CMSFPageTable *pmpt);
+#else
+ CMSFPage(CMSFPage *pmpNext);
+#endif
+
+ inline ~CMSFPage();
+
+ inline void AddRef(void);
+ inline void Release(void);
+
+ inline CMSFPage *GetNext(void) const;
+ inline CMSFPage *GetPrev(void) const;
+ inline SID GetSid(void) const;
+ inline ULONG GetOffset(void) const;
+ inline SECT GetSect(void) const;
+ inline void *GetData(void) const;
+ inline DWORD GetFlags(void) const;
+ inline CPagedVector * GetVector(void) const;
+
+ inline void Remove(void);
+
+ inline void SetChain(CMSFPage *const pmpPrev,
+ CMSFPage *const pmpNext);
+ inline void SetPrev(CMSFPage *const pmpPrev);
+ inline void SetNext(CMSFPage *const pmpNext);
+
+ inline void SetSid(const SID sid);
+ inline void SetOffset(const ULONG ulOffset);
+#ifndef SORTPAGETABLE
+ inline void SetSect(const SECT sect);
+#endif
+ inline void SetFlags(const DWORD dwFlags);
+ inline void SetVector(CPagedVector *ppv);
+
+ inline void SetDirty(void);
+ inline void ResetDirty(void);
+ inline BOOL IsDirty(void) const;
+
+ inline BOOL IsInUse(void) const;
+ inline BOOL IsFlushable(void) const;
+private:
+#ifdef SORTPAGETABLE
+ friend CMSFPageTable;
+ inline void SetSect(const SECT sect);
+#endif
+
+ CBasedMSFPagePtr _pmpNext;
+ CBasedMSFPagePtr _pmpPrev;
+
+#if DBG == 1
+ CBasedMSFPageTablePtr _pmpt;
+#endif
+
+ SID _sid;
+ ULONG _ulOffset;
+ CBasedPagedVectorPtr _ppv;
+ SECT _sect;
+ DWORD _dwFlags;
+ LONG _cReferences;
+ BYTE _ab[];
+};
+SAFE_DFBASED_PTR(CBasedMSFPagePtrPtr, CBasedMSFPagePtr);
+
+#ifndef REF
+#if _MSC_VER == 700
+#pragma warning(default:4001)
+#elif _MSC_VER >= 800
+#pragma warning(default:4200)
+#endif
+#endif //!REF
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::~CMSFPage, public
+//
+// Synopsis: Destructor
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPage_1CMSFPage)
+#endif
+
+inline CMSFPage::~CMSFPage()
+{
+ msfAssert(_cReferences == 0);
+
+ Remove();
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::Remove, public
+//
+// Synopsis: Remove page from list
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::Remove(void)
+{
+ //Avoid using SetNext and SetPrev so we don't need to unbase and
+ // then rebase everything.
+
+ _pmpPrev->_pmpNext = _pmpNext;
+ _pmpNext->_pmpPrev = _pmpPrev;
+
+ _pmpNext = _pmpPrev = NULL;
+}
+
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::operator new, public
+//
+// Synopsis: Overloaded new operator for CMSFPage.
+//
+// Arguments: [size] -- Default size field
+// [pMalloc] -- Allocator
+// [sizeData] -- Size of byte array to allocate.
+//
+// Returns: Pointer to new CMSFPage object
+//
+// History: 20-Oct-92 PhilipLa Created
+// 21-May-93 AlexT Added allocator
+//
+// Notes: *Finish This*
+//
+//----------------------------------------------------------------------------
+
+inline void * CMSFPage::operator new(size_t size, IMalloc * const pMalloc,
+ size_t sizeData)
+{
+ msfAssert(size == sizeof(CMSFPage));
+
+ return(CMallocBased::operator new(sizeData + sizeof(CMSFPage), pMalloc));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetNext, public
+//
+// Synopsis: Returns the next page in the list
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CMSFPage * CMSFPage::GetNext(void) const
+{
+ return BP_TO_P(CMSFPage *, _pmpNext);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetPrev, public
+//
+// Synopsis: Returns the next page in the list
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CMSFPage * CMSFPage::GetPrev(void) const
+{
+ return BP_TO_P(CMSFPage *, _pmpPrev);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetSid, public
+//
+// Synopsis: Returns the SID for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline SID CMSFPage::GetSid(void) const
+{
+ return _sid;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetOffset, public
+//
+// Synopsis: Returns the array offset for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CMSFPage::GetOffset(void) const
+{
+ return _ulOffset;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetSect, public
+//
+// Synopsis: Returns the SECT for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline SECT CMSFPage::GetSect(void) const
+{
+ return _sect;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetFlags, public
+//
+// Synopsis: Returns the flags for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline DWORD CMSFPage::GetFlags(void) const
+{
+ return _dwFlags;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetData, public
+//
+// Synopsis: Returns a pointer to the page storage for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void * CMSFPage::GetData(void) const
+{
+ return (void *) _ab;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetVector, public
+//
+// Synopsis: Returns a pointer to the vector holding this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CPagedVector * CMSFPage::GetVector(void) const
+{
+ return BP_TO_P(CPagedVector *, _ppv);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetChain, public
+//
+// Synopsis: Sets the chain pointers for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetChain(
+ CMSFPage *const pmpPrev,
+ CMSFPage *const pmpNext)
+{
+ _pmpPrev = P_TO_BP(CBasedMSFPagePtr, pmpPrev);
+ _pmpNext = P_TO_BP(CBasedMSFPagePtr, pmpNext);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetPrev, public
+//
+// Synopsis: Sets the prev pointer for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetPrev(CMSFPage *const pmpPrev)
+{
+ _pmpPrev = P_TO_BP(CBasedMSFPagePtr, pmpPrev);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetNext, public
+//
+// Synopsis: Sets the next pointer for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetNext(CMSFPage *const pmpNext)
+{
+ _pmpNext = P_TO_BP(CBasedMSFPagePtr, pmpNext);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetSid, public
+//
+// Synopsis: Sets the SID for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetSid(const SID sid)
+{
+ _sid = sid;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetOffset, public
+//
+// Synopsis: Sets the offset for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetOffset(const ULONG ulOffset)
+{
+ _ulOffset = ulOffset;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetSect, public
+//
+// Synopsis: Sets the SECT for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+#ifndef SORTPAGETABLE
+inline void CMSFPage::SetSect(const SECT sect)
+{
+ _sect = sect;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetFlags, public
+//
+// Synopsis: Sets the flags for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetFlags(const DWORD dwFlags)
+{
+ _dwFlags = dwFlags;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetVector, public
+//
+// Synopsis: Sets the pointer to the vector holding this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetVector(CPagedVector *ppv)
+{
+ _ppv = P_TO_BP(CBasedPagedVectorPtr, ppv);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetDirty, public
+//
+// Synopsis: Sets the dirty bit for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetDirty(void)
+{
+ _dwFlags = _dwFlags | FB_DIRTY;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::ResetDirty, public
+//
+// Synopsis: Resets the dirty bit for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::ResetDirty(void)
+{
+ _dwFlags = _dwFlags & ~FB_DIRTY;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::IsDirty, public
+//
+// Synopsis: Returns TRUE if the dirty bit is set on this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CMSFPage::IsDirty(void) const
+{
+ return (_dwFlags & FB_DIRTY) != 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::IsInUse, public
+//
+// Synopsis: Returns TRUE if the page is currently in use
+//
+// History: 05-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CMSFPage::IsInUse(void) const
+{
+ return (_cReferences != 0);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::IsFlushable, public
+//
+// Synopsis: Returns TRUE if the page can be flushed to disk
+//
+// History: 05-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CMSFPage::IsFlushable(void) const
+{
+ return (IsDirty() && !IsInUse());
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CMSFPageTable
+//
+// Purpose: Page allocator and handler for MSF
+//
+// Interface: See below
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+class CMSFPageTable : public CMallocBased
+{
+public:
+ CMSFPageTable(
+ CMStream *const pmsParent,
+ const ULONG _cMinPages,
+ const ULONG _cMaxPages);
+ ~CMSFPageTable();
+
+ inline void AddRef();
+ inline void Release();
+
+ SCODE Init(void);
+ SCODE GetPage(
+ CPagedVector *ppv,
+ SID sid,
+ ULONG ulOffset,
+ SECT sectKnown,
+ CMSFPage **ppmp);
+
+#ifndef REF
+ SCODE CopyPage(
+ CPagedVector *ppv,
+ CMSFPage *pmpOld,
+ CBasedMSFPagePtr *ppmp);
+#endif //!REF
+
+ SCODE FindPage(
+ CPagedVector *ppv,
+ SID sid,
+ ULONG ulOffset,
+ CMSFPage **ppmp);
+
+ SCODE GetFreePage(CMSFPage **ppmp);
+
+ void ReleasePage(CPagedVector *ppv, SID sid, ULONG ulOffset);
+
+ void FreePages(CPagedVector *ppv);
+
+#ifdef SORTPAGETABLE
+ void SetSect(CMSFPage *pmp, SECT sect);
+#endif
+
+ SCODE Flush(void);
+ SCODE FlushPage(CMSFPage *pmp);
+
+ inline void SetParent(CMStream *pms);
+
+#if DBG == 1
+ void AddPageRef(void);
+ void ReleasePageRef(void);
+#endif
+
+private:
+ inline CMSFPage * GetNewPage(void);
+ CMSFPage * FindSwapPage(void);
+
+ CBasedMStreamPtr _pmsParent;
+ const ULONG _cbSector;
+ const ULONG _cMinPages;
+ const ULONG _cMaxPages;
+
+ ULONG _cActivePages;
+ ULONG _cPages;
+ CBasedMSFPagePtr _pmpCurrent;
+#ifdef SORTPAGETABLE
+ CBasedMSFPagePtr _pmpStart;
+ inline BOOL IsSorted(CMSFPage *pmp);
+#endif
+
+ LONG _cReferences;
+
+#if DBG == 1
+ ULONG _cCurrentPageRef;
+ ULONG _cMaxPageRef;
+#endif
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::AddRef, public
+//
+// Synopsis: Increment the reference count
+//
+// History: 28-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::AddRef(void)
+{
+ msfAssert(_cReferences >= 0);
+#if DBG == 1
+ if (_cReferences == 0)
+ {
+ _pmpt->AddPageRef();
+ }
+#endif
+ AtomicInc(&_cReferences);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::Release, public
+//
+// Synopsis: Decrement the reference count
+//
+// History: 28-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::Release(void)
+{
+ LONG lRet;
+
+ msfAssert(_cReferences > 0);
+ lRet = AtomicDec(&_cReferences);
+#if DBG == 1
+ if (lRet == 0)
+ {
+ _pmpt->ReleasePageRef();
+ }
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::AddRef, public
+//
+// Synopsis: Increment the ref coutn
+//
+// History: 05-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPageTable::AddRef(void)
+{
+ AtomicInc(&_cReferences);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::Release, public
+//
+// Synopsis: Decrement the ref count, delete if necessary
+//
+// History: 05-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPageTable::Release(void)
+{
+ LONG lRet;
+
+ msfAssert(_cReferences > 0);
+ lRet = AtomicDec(&_cReferences);
+ if (lRet == 0)
+ {
+ delete this;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::SetParent, public
+//
+// Synopsis: Set the parent of this page table
+//
+// Arguments: [pms] -- Pointer to new parent
+//
+// History: 05-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPageTable::SetParent(CMStream *pms)
+{
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pms);
+}
+
+
+#endif // #ifndef __PAGE_HXX__
diff --git a/private/ole32/stg/h/pbstream.hxx b/private/ole32/stg/h/pbstream.hxx
new file mode 100644
index 000000000..7b7e43d81
--- /dev/null
+++ b/private/ole32/stg/h/pbstream.hxx
@@ -0,0 +1,448 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: pbstream.hxx
+//
+// Contents: CPubStream definition
+//
+// Classes: CPubStream
+//
+// History: 16-Jan-92 PhilipLa Created.
+// 12-Jun-96 MikeHill Moved the body of the FlushNoException
+// method to the new Write method (except for
+// the Commit). Made Flush & FlushNoException
+// inline.
+// 21-Jun-96 MikeHill Declare CPubMappedStream::_pb as based.
+// 01-Jul-96 MikeHill - Adjust signatures for Win32 SEH removal.
+// - Added _powner member to CPubMappedStream.
+//
+//--------------------------------------------------------------------------
+
+
+#ifndef __PBSTREAM_HXX__
+#define __PBSTREAM_HXX__
+
+#include <msf.hxx>
+#include <revert.hxx>
+#include <psstream.hxx>
+#include <smalloc.hxx>
+
+class CPubDocFile;
+class CPubStream;
+SAFE_DFBASED_PTR (CBasedPubStreamPtr, CPubStream);
+SAFE_DFBASED_PTR (CBasedMappedStreamPtr, CMappedStream);
+
+//+--------------------------------------------------------------
+//
+// Class: CPubMappedStream
+//
+// Purpose: Structure that lives in shared memory for
+// mapped stream implementation.
+//
+// History: 1-May-95 BillMo Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------
+#ifdef NEWPROPS
+class CPubMappedStream : public CMappedStream
+{
+public:
+ CPubMappedStream(CPubStream *pst)
+ {
+ _pb = NULL;
+ _cbUsed = 0;
+ _cbOriginalStreamSize = 0;
+ _fDirty = FALSE;
+ _fLowMem = FALSE;
+ _fChangePending = FALSE;
+ _pst = P_TO_BP(CBasedPubStreamPtr, pst);
+ _powner = NULL;
+ }
+
+ ~CPubMappedStream()
+ {
+ msfAssert(_pb == NULL);
+ }
+
+ VOID Open(IN NTPROP ntprop, OUT LONG *phr);
+ VOID Close(OUT LONG *phr);
+ VOID ReOpen(IN OUT VOID **ppv, OUT LONG *phr);
+ VOID Quiesce(VOID);
+ VOID Map(BOOLEAN fCreate, VOID **ppv);
+ VOID Unmap(BOOLEAN fFlush, VOID **pv);
+ ULONG GetSize(OUT LONG *phr);
+ VOID SetSize(ULONG cb, BOOLEAN fPersistent, VOID **ppv, OUT LONG *phr);
+ NTSTATUS Lock(IN BOOLEAN fExclusive);
+ NTSTATUS Unlock(VOID);
+ VOID QueryTimeStamps(STATPROPSETSTG *pspss, BOOLEAN fNonSimple) const;
+ BOOLEAN QueryModifyTime(OUT LONGLONG *pll) const;
+ BOOLEAN QuerySecurity(OUT ULONG *pul) const;
+
+#if DBGPROP
+ BOOLEAN SetChangePending(BOOLEAN fChangePending);
+ BOOLEAN IsNtMappedStream(VOID) const;
+#endif
+ BOOLEAN IsWriteable(VOID) const;
+ BOOLEAN IsStoragePropertySet(VOID) const;
+ BOOLEAN IsModified(VOID) const;
+ VOID SetModified(VOID);
+ HANDLE GetHandle(VOID) const;
+
+ inline IMalloc * GetMalloc(VOID);
+ inline VOID Cleanup(VOID);
+ VOID Flush(OUT LONG *phr);
+ HRESULT Write ();
+
+
+#if DBG
+ inline ULONG BytesCommitted(VOID) { return _cbUsed; }
+ VOID DfpdbgFillUnusedMemory(VOID);
+ VOID DfpdbgCheckUnusedMemory(VOID);
+#else
+ VOID DfpdbgFillUnusedMemory(VOID) {}
+ VOID DfpdbgCheckUnusedMemory(VOID) {}
+#endif
+
+private:
+
+private:
+ CBasedPubStreamPtr _pst;
+ CBasedBytePtr _pb;
+ ULONG _cbUsed;
+ ULONG _cbOriginalStreamSize;
+ BOOL _fDirty;
+ BOOL _fLowMem;
+ BOOL _fChangePending;
+ CBasedBytePtr _powner; // Owner of this mapped stream.
+
+};
+#endif
+
+//+--------------------------------------------------------------
+//
+// Class: CPubStream
+//
+// Purpose: Public stream interface
+//
+// Interface: See below
+//
+// History: 16-Jan-92 PhilipLa Created.
+//
+//---------------------------------------------------------------
+
+class CPubStream : public PRevertable
+{
+public:
+
+ CPubStream(CPubDocFile *ppdf,
+ DFLAGS df,
+ CDfName const *pdfn);
+ ~CPubStream();
+
+ void Init(PSStream *psParent,
+ DFLUID dlLUID);
+ inline void vAddRef(void);
+ void vRelease(void);
+
+ // PRevertable
+ virtual void RevertFromAbove(void);
+#ifdef NEWPROPS
+ virtual SCODE FlushBufferedData(int recursionlevel);
+#endif
+ SCODE Stat(STATSTGW *pstatstg, DWORD grfStatFlag);
+ inline SCODE ReadAt(ULONG ulOffset,
+ VOID *pb,
+ ULONG cb,
+ ULONG STACKBASED *pcbRead);
+ inline SCODE WriteAt(ULONG ulOffset,
+ VOID const HUGEP *pb,
+ ULONG cb,
+ ULONG STACKBASED *pcbWritten);
+ inline SCODE GetSize(ULONG *pcb);
+ inline SCODE SetSize(ULONG cb);
+
+ inline PSStream *GetSt(void) const;
+#ifdef NEWPROPS
+ inline CMappedStream & GetMappedStream(void);
+ inline const CMappedStream & GetConstMappedStream(void);
+#endif
+ inline SCODE CheckReverted(void) const;
+
+ inline void SetClean(void);
+ inline void SetDirty(void);
+
+ SCODE Commit(DWORD dwFlags);
+private:
+ CBasedSStreamPtr _psParent;
+ CBasedPubDocFilePtr _ppdfParent;
+ BOOL _fDirty;
+ LONG _cReferences;
+#ifdef NEWPROPS
+ CPubMappedStream _PubMappedStream;
+#endif
+};
+
+
+//+--------------------------------------------------------------
+//
+// Member: CPubStream::CheckReverted, public
+//
+// Synopsis: Returns revertedness
+//
+// History: 11-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CPubStream::CheckReverted(void) const
+{
+ return P_REVERTED(_df) ? STG_E_REVERTED : S_OK;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CPubStream::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// History: 26-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CPubStream::vAddRef(void)
+{
+ InterlockedIncrement(&_cReferences);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubStream::GetSt, public
+//
+// Synopsis: Returns _psParent
+//
+// History: 26-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline PSStream *CPubStream::GetSt(void) const
+{
+ return BP_TO_P(PSStream *, _psParent);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubStream::GetMappedStream, public
+//
+// Synopsis: Returns this as a CPubMappedStream
+//
+// History: 26-May-95 BillMo Created
+//
+//---------------------------------------------------------------
+#ifdef NEWPROPS
+inline CMappedStream & CPubStream::GetMappedStream(void)
+{
+ return _PubMappedStream;
+}
+
+inline const CMappedStream & CPubStream::GetConstMappedStream(void)
+{
+ return _PubMappedStream;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubStream::SetClean, public
+//
+// Synopsis: Resets the dirty flag
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CPubStream::SetClean(void)
+{
+ _fDirty = FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubStream::SetDirty, public
+//
+// Synopsis: Sets the dirty flag
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CPubStream::SetDirty(void)
+{
+ _fDirty = TRUE;
+ _ppdfParent->SetDirty();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPubStream::ReadAt, public
+//
+// Synopsis: Read from a stream
+//
+// Arguments: [ulOffset] - Byte offset to read from
+// [pb] - Buffer
+// [cb] - Count of bytes to read
+// [pcbRead] - Return number of bytes actually read
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+//
+// History: 16-Jan-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline SCODE CPubStream::ReadAt(ULONG ulOffset,
+ VOID *pb,
+ ULONG cb,
+ ULONG STACKBASED *pcbRead)
+{
+ SCODE sc;
+
+ if (SUCCEEDED(sc = CheckReverted()))
+ if (!P_READ(_df))
+ sc = STG_E_ACCESSDENIED;
+ else
+ sc = _psParent->ReadAt(ulOffset,pb,cb,pcbRead);
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPubStream::WriteAt, public
+//
+// Synopsis: Write to a stream
+//
+// Arguments: [ulOffset] - Byte offset to write at
+// [pb] - Buffer
+// [cb] - Count of bytes to write
+// [pcbWritten] - Return number of bytes actually written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbWritten]
+//
+// History: 16-Jan-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubStream_WriteAt)
+#endif
+
+inline SCODE CPubStream::WriteAt(ULONG ulOffset,
+ VOID const HUGEP *pb,
+ ULONG cb,
+ ULONG STACKBASED *pcbWritten)
+{
+ SCODE sc;
+
+ if (SUCCEEDED(sc = CheckReverted()))
+ if (!P_WRITE(_df))
+ sc = STG_E_ACCESSDENIED;
+ else
+ {
+ sc = _psParent->WriteAt(ulOffset,pb,cb,pcbWritten);
+ if (SUCCEEDED(sc))
+ SetDirty();
+ }
+ return sc;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CPubStream::GetSize, public
+//
+// Synopsis: Gets the size of the stream
+//
+// Arguments: [pcb] - Stream size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcb]
+//
+// History: 30-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CPubStream::GetSize(ULONG *pcb)
+{
+ SCODE sc;
+
+ if (SUCCEEDED(sc = CheckReverted()))
+ _psParent->GetSize(pcb);
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPubStream::SetSize, public
+//
+// Synposis: Set the size of a linear stream
+//
+// Arguments: [ulNewSize] -- New size for stream
+//
+// Returns: Error code returned by MStream call.
+//
+// Algorithm: Pass call up to parent.
+//
+// History: 29-Jul-91 PhilipLa Created.
+// 16-Jan-92 PhilipLa Moved from CSStream to CPubStream
+//
+//---------------------------------------------------------------------------
+
+inline SCODE CPubStream::SetSize(ULONG ulNewSize)
+{
+ SCODE sc;
+
+ if (SUCCEEDED(sc = CheckReverted()))
+ if (!P_WRITE(_df))
+ sc = STG_E_ACCESSDENIED;
+ else
+ {
+ sc = _psParent->SetSize(ulNewSize);
+ if (SUCCEEDED(sc))
+ SetDirty();
+ }
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPubMappedStream::GetMalloc, public
+//
+// Synposis: Get the allocator for the stream.
+//
+//---------------------------------------------------------------------------
+#ifdef NEWPROPS
+inline IMalloc * CPubMappedStream::GetMalloc(void)
+{
+ return &g_smAllocator;
+}
+
+inline VOID CPubMappedStream::Cleanup(VOID)
+{
+ if (!_fLowMem)
+ GetMalloc()->Free(BP_TO_P(BYTE *, _pb));
+ _pb = NULL;
+}
+
+#endif
+
+#endif //__PBSTREAM_HXX__
diff --git a/private/ole32/stg/h/pdocfile.hxx b/private/ole32/stg/h/pdocfile.hxx
new file mode 100644
index 000000000..36b2ed8be
--- /dev/null
+++ b/private/ole32/stg/h/pdocfile.hxx
@@ -0,0 +1,148 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: pdocfile.hxx
+//
+// Contents: DocFile protocol header
+//
+// Classes: PDocFile
+//
+// History: 08-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __PDOCFILE_HXX__
+#define __PDOCFILE_HXX__
+
+#include <dfmsp.hxx>
+#include <entry.hxx>
+
+class CDocFile;
+class PDocFileIterator;
+class PSStream;
+class CUpdate;
+class CUpdateList;
+class CWrappedDocFile;
+
+// CopyDocFileToDocFile flags
+#define CDF_NORMAL 0 // Normal copy
+#define CDF_EXACT 1 // Exact dir entry match
+#define CDF_REMAP 2 // Remap handles
+#define CDF_ENTRIESONLY 4 // Don't copy contents
+
+//+--------------------------------------------------------------
+//
+// Class: PDocFile (df)
+//
+// Purpose: DocFile protocol
+//
+// Interface: See below
+//
+// History: 08-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+class PDocFile : public PTimeEntry
+{
+public:
+ virtual void AddRef(void) = 0;
+ virtual void Release(void) = 0;
+
+ virtual SCODE DestroyEntry(CDfName const *pdfnName,
+ BOOL fClean) = 0;
+ virtual SCODE RenameEntry(CDfName const *pdfnName,
+ CDfName const *pdfnNewName) = 0;
+
+ virtual SCODE GetClass(CLSID *pclsid) = 0;
+ virtual SCODE SetClass(REFCLSID clsid) = 0;
+ virtual SCODE GetStateBits(DWORD *pgrfStateBits) = 0;
+ virtual SCODE SetStateBits(DWORD grfStateBits, DWORD grfMask) = 0;
+
+ virtual SCODE CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ PDocFile **ppdfDocFile) = 0;
+ inline SCODE CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ DWORD const dwType,
+ PDocFile **ppdfDocFile)
+ { return CreateDocFile(pdfnName, df, luidSet, ppdfDocFile); }
+
+ virtual SCODE GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ PDocFile **ppdfDocFile) = 0;
+ inline SCODE GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DWORD const dwType,
+ PDocFile **ppdfDocFile)
+ { return GetDocFile(pdfnName, df, ppdfDocFile); }
+
+ virtual SCODE CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ PSStream **ppsstStream) = 0;
+ inline SCODE CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ DWORD const dwType,
+ PSStream **ppsstStream)
+ { return CreateStream(pdfnName, df, luidSet, ppsstStream); }
+
+ virtual SCODE GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ PSStream **ppsstStream) = 0;
+ inline SCODE GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DWORD const dwType,
+ PSStream **ppsstStream)
+ { return GetStream(pdfnName, df, ppsstStream); }
+
+ virtual SCODE FindGreaterEntry(CDfName const *pdfnKey,
+ SIterBuffer *pib,
+ STATSTGW *pstat) = 0;
+ virtual SCODE StatEntry(CDfName const *pdfn,
+ SIterBuffer *pib,
+ STATSTGW *pstat) = 0;
+
+#ifndef REF
+ virtual SCODE BeginCommitFromChild(CUpdateList &ulChanged,
+ DWORD const dwFlags,
+ CWrappedDocFile *pdfChild) = 0;
+ virtual void EndCommitFromChild(DFLAGS const df,
+ CWrappedDocFile *pdfChild) = 0;
+#endif //!REF
+
+ virtual SCODE IsEntry(CDfName const *pdfnName,
+ SEntryBuffer *peb) = 0;
+ virtual SCODE DeleteContents(void) = 0;
+
+ static SCODE ExcludeEntries(PDocFile *pdf, SNBW snbExclude);
+#ifndef REF
+ static SCODE CreateFromUpdate(CUpdate *pud,
+ PDocFile *pdf,
+ DFLAGS df);
+#endif //!REF
+
+protected:
+ inline PDocFile(DFLUID dl);
+};
+SAFE_DFBASED_PTR(CBasedDocFilePtr, PDocFile);
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_PDocFile_PDocFile)
+#endif
+
+inline PDocFile::PDocFile(DFLUID dl)
+ : PTimeEntry(dl)
+{
+ NULL; // Nothing needs to be done here
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+#endif
diff --git a/private/ole32/stg/h/props.hxx b/private/ole32/stg/h/props.hxx
new file mode 100644
index 000000000..1862fc2a4
--- /dev/null
+++ b/private/ole32/stg/h/props.hxx
@@ -0,0 +1,66 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: props.hxx
+//
+// Contents: Shared property code header
+//
+// Functions: ValidatePropType
+//
+// History: 14-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __PROPS_HXX__
+#define __PROPS_HXX__
+
+typedef VARIANT DFPROPVAL;
+
+#ifdef OLDPROP
+// Property types that don't go in the property value itself
+#define VT_NOT_IN_VALUE(vt) \
+ (((vt) & VT_VECTOR) || \
+ (vt) == VT_BSTR || (vt) == VT_WBSTR || \
+ (vt) == VT_LPSTR || (vt) == VT_LPWSTR || \
+ (vt) == VT_BLOB_OBJECT || (vt) == VT_BLOB || \
+ (vt) == VT_VARIANT || (vt) == VT_CF || (vt) == VT_UUID)
+#else
+// Property types that don't go in the property value itself
+#define VT_NOT_IN_VALUE(vt) \
+ (((vt) & VT_VECTOR) || \
+ (vt) == VT_BSTR || \
+ (vt) == VT_LPSTR || (vt) == VT_LPWSTR || \
+ (vt) == VT_BLOB_OBJECT || (vt) == VT_BLOB || \
+ (vt) == VT_VARIANT || (vt) == VT_CF || (vt) == VT_UUID)
+#endif
+
+#define ValidatePropSpecKind(psk) \
+ (((psk) == PRSPEC_LPWSTR || (psk) == PRSPEC_DISPID || \
+ (psk) == PRSPEC_PROPID) ? S_OK : STG_E_INVALIDPARAMETER)
+
+SCODE ValidatePropType(DFPROPTYPE dpt);
+SCODE ValidatePropVt(DFPROPVAL *pdpv);
+
+#ifdef OLDPROPS
+#define BSTR_LLEN sizeof(UINT)
+#define BSTR_PTR(b) ((BYTE *)(b)-BSTR_LLEN)
+#define BSTR_SLEN(b) ((*(UINT *)BSTR_PTR(b)))
+#define BSTR_BLEN(b) (BSTR_SLEN(b)+1)
+#define BSTR_TLEN(b) (BSTR_BLEN(b)+BSTR_LLEN)
+
+#define WBSTR_LLEN sizeof(UINT)
+#define WBSTR_PTR(b) ((BYTE *)(b)-WBSTR_LLEN)
+#define WBSTR_SLEN(b) ((*(UINT *)WBSTR_PTR(b)))
+#define WBSTR_BLEN(b) (WBSTR_SLEN(b)+sizeof(WCHAR))
+#define WBSTR_TLEN(b) (WBSTR_BLEN(b)+WBSTR_LLEN)
+#else
+#define BSTR_LLEN sizeof(UINT)
+#define BSTR_PTR(b) ((BYTE *)(b)-BSTR_LLEN)
+#define BSTR_SLEN(b) ((*(UINT *)BSTR_PTR(b)))
+#define BSTR_BLEN(b) (BSTR_SLEN(b)+sizeof(WCHAR))
+#define BSTR_TLEN(b) (BSTR_BLEN(b)+BSTR_LLEN)
+#endif
+
+#endif // #ifndef __PROPS_HXX__
diff --git a/private/ole32/stg/h/psstream.hxx b/private/ole32/stg/h/psstream.hxx
new file mode 100644
index 000000000..6a91b2c4b
--- /dev/null
+++ b/private/ole32/stg/h/psstream.hxx
@@ -0,0 +1,70 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: psstream.hxx
+//
+// Contents: Internal stream base class
+//
+// Classes: PSStream
+//
+// History: 20-Jan-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __PSSTREAM_HXX__
+#define __PSSTREAM_HXX__
+
+#include <entry.hxx>
+
+#ifndef REF
+class CDeltaList;
+#endif //!REF
+class CDirectStream;
+#ifndef REF
+class CTransactedStream;
+#endif //!REF
+
+class PSStream: public PBasicEntry
+{
+
+ public:
+
+ virtual void AddRef(void) = 0;
+ virtual void Release(void) = 0;
+
+#ifndef REF
+ virtual SCODE BeginCommitFromChild(
+ ULONG ulSize,
+ CDeltaList *pDelta,
+ CTransactedStream *pstChild) = 0;
+
+ virtual void EndCommitFromChild(DFLAGS df,
+ CTransactedStream *pstChild) = 0;
+
+ virtual CDeltaList *GetDeltaList(void) = 0;
+
+#endif //!REF
+ virtual SCODE ReadAt(
+ ULONG ulOffset,
+ VOID HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval) = 0;
+
+ virtual SCODE WriteAt(
+ ULONG ulOffset,
+ VOID const HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval) = 0;
+
+ virtual SCODE SetSize(ULONG ulNewSize) = 0;
+
+ virtual void GetSize(ULONG *pulSize) = 0;
+
+protected:
+ inline PSStream(DFLUID dl) : PBasicEntry(dl) {}
+};
+SAFE_DFBASED_PTR(CBasedSStreamPtr, PSStream);
+
+#endif //__PSSTREAM_HXX__
diff --git a/private/ole32/stg/h/ptrcache.hxx b/private/ole32/stg/h/ptrcache.hxx
new file mode 100644
index 000000000..e514da582
--- /dev/null
+++ b/private/ole32/stg/h/ptrcache.hxx
@@ -0,0 +1,130 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ptrcache.hxx
+//
+// Contents: CPtrCache header
+//
+// Classes: CPtrCache
+//
+// History: 26-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __PTRCACHE_HXX__
+#define __PTRCACHE_HXX__
+
+#include <debnot.h>
+#include <dfmem.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: CPtrBlock (pb)
+//
+// Purpose: Holds an array of pointers
+//
+// Interface: See below
+//
+// History: 26-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#define CBLOCKPTRS 50
+
+class CPtrBlock
+{
+public:
+ inline CPtrBlock(CPtrBlock *pbNext);
+
+ inline void Add(void *pv);
+ inline BOOL Full(void);
+ inline int Count(void);
+ inline void *Nth(int n);
+ inline CPtrBlock *Next(void);
+
+private:
+ int _cPtrs;
+ CPtrBlock *_pbNext;
+ void *_apv[CBLOCKPTRS];
+};
+
+inline CPtrBlock::CPtrBlock(CPtrBlock *pbNext)
+{
+ _cPtrs = 0;
+ _pbNext = pbNext;
+}
+
+inline void CPtrBlock::Add(void *pv)
+{
+ Win4Assert(_cPtrs < CBLOCKPTRS);
+ _apv[_cPtrs++] = pv;
+}
+
+inline BOOL CPtrBlock::Full(void)
+{
+ return _cPtrs == CBLOCKPTRS;
+}
+
+inline int CPtrBlock::Count(void)
+{
+ return _cPtrs;
+}
+
+inline void *CPtrBlock::Nth(int n)
+{
+ Win4Assert(n >= 0 && n < _cPtrs);
+ return _apv[n];
+}
+
+inline CPtrBlock *CPtrBlock::Next(void)
+{
+ return _pbNext;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Class: CPtrCache (pc)
+//
+// Purpose: Holds an arbitrary number of pointers using an efficient
+// block allocation scheme
+//
+// Interface: See below
+//
+// History: 26-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CPtrCache : public CLocalAlloc
+{
+public:
+ inline CPtrCache(void);
+ ~CPtrCache(void);
+
+ SCODE Add(void *pv);
+
+ inline void StartEnum(void);
+ BOOL Next(void **ppv);
+
+private:
+ CPtrBlock _pbFirst;
+ CPtrBlock *_pbHead;
+ CPtrBlock *_pbEnum;
+ int _iEnum;
+};
+
+inline CPtrCache::CPtrCache(void)
+ : _pbFirst(NULL)
+{
+ _pbHead = &_pbFirst;
+ StartEnum();
+}
+
+inline void CPtrCache::StartEnum(void)
+{
+ _pbEnum = _pbHead;
+ _iEnum = 0;
+}
+
+#endif // #ifndef __PTRCACHE_HXX__
diff --git a/private/ole32/stg/h/publicdf.hxx b/private/ole32/stg/h/publicdf.hxx
new file mode 100644
index 000000000..eac892319
--- /dev/null
+++ b/private/ole32/stg/h/publicdf.hxx
@@ -0,0 +1,823 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: publicdf.hxx
+//
+// Contents: Public DocFile header
+//
+// Classes: CPubDocFile
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __PUBDF_HXX__
+#define __PUBDF_HXX__
+
+#include <dfmsp.hxx>
+#include <chinst.hxx>
+#include <ole.hxx>
+#include <revert.hxx>
+#ifndef REF
+#include <dfbasis.hxx>
+#endif //!REF
+#include <pdocfile.hxx>
+#ifndef REF
+#include <tlsets.hxx>
+#else
+#include <ref.hxx>
+#endif //!REF
+
+class PDocFile;
+class CPubStream;
+class CRootPubDocFile;
+
+#ifndef REF
+// XS member flags
+#define XSM_NOTHING 0x00000000
+#define XSM_DELETEIFUNTOUCHED 0x00000001
+#define XSM_DELETEONCOMMIT 0x00000002
+#define XSM_DELETED 0x00000004
+#define XSM_UNCOMMITTED 0x00000008
+
+// XS operations
+#define XSO_REVERT 1
+#define XSO_RELEASE 2
+#endif //!REF
+
+// Class signatures for object validation
+#define CPUBDOCFILE_SIG LONGSIG('P', 'B', 'D', 'F')
+#define CPUBDOCFILE_SIGDEL LONGSIG('P', 'b', 'D', 'f')
+
+//PubDocFile bitfield:
+// PF_DIRTY indicates dirty state of docfile
+// PF_PREPARED is set if the Docfile has enough space for an overwrite
+// commit (after a PrepareForOverwrite or SwitchToFile) and
+// is reset after a successful commit.
+#define PF_DIRTY 1
+#define PF_PREPARED 2
+
+
+//+--------------------------------------------------------------
+//
+// Class: CPubDocFile (df)
+//
+// Purpose: Public DocFile class
+//
+// Interface: See below
+//
+// History: 20-Jan-92 DrewB Created
+// MikeHill Made Commit virtual
+//
+//---------------------------------------------------------------
+
+class CPubDocFile : public PRevertable
+{
+public:
+ CPubDocFile(CPubDocFile *pdfParent,
+ PDocFile *pdf,
+ DFLAGS const df,
+ DFLUID luid,
+#ifndef REF
+ CDFBasis *pdfb,
+#else
+ ILockBytes *pilbBase,
+#endif //!REF
+ CDfName const *pdfn,
+#ifndef REF
+ UINT cTransactedDepth,
+#endif //!REF
+ CMStream *pmsBase);
+
+#ifndef REF
+ // C700 - Virtual destructors aren't working properly so explicitly
+ // declare one
+#endif //!REF
+ virtual void vdtor(void);
+
+ inline void vAddRef(void);
+ inline void vDecRef(void);
+ void vRelease(void);
+
+ // PRevertable
+ virtual void RevertFromAbove(void);
+#ifdef NEWPROPS
+ virtual SCODE FlushBufferedData(int recursionlevel);
+#endif
+
+ virtual SCODE Stat(STATSTGW *pstatstg, DWORD grfStatFlag);
+
+#ifdef COORD
+ SCODE CommitPhase1(DWORD const dwFlags,
+ ULONG *pulLock,
+ DFSIGNATURE *psigMSF,
+ ULONG *pcbSizeBase,
+ ULONG *pcbSizeOrig);
+ SCODE CommitPhase2(DWORD const dwFlags,
+ BOOL fCommit,
+ ULONG ulLock,
+ DFSIGNATURE sigMSF,
+ ULONG cbSizeBase,
+ ULONG cbSizeOrig);
+#endif
+
+ virtual SCODE Commit(DWORD const dwFlags);
+ SCODE Revert(void);
+
+ SCODE DestroyEntry(CDfName const *pdfnName,
+ BOOL fClean);
+ SCODE RenameEntry(CDfName const *pdfnName,
+ CDfName const *pdfnNewName);
+ SCODE SetElementTimes(CDfName const *pdfnName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+ SCODE SetClass(REFCLSID clsid);
+ SCODE SetStateBits(DWORD grfStateBits, DWORD grfMask);
+ SCODE CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubDocFile **ppdfDocFile);
+
+ SCODE GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubDocFile **ppdfDocFile);
+ SCODE CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubStream **ppdstStream);
+ SCODE GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubStream **ppdstStream);
+
+ inline SCODE FindGreaterEntry(CDfName const *pdfnKey,
+ SIterBuffer *pib,
+ STATSTGW *pstat,
+ BOOL fProps);
+
+ void AddChild(PRevertable *prv);
+ void ReleaseChild(PRevertable *prv);
+ SCODE IsEntry(CDfName const *pdfnName, SEntryBuffer *peb);
+ BOOL IsAtOrAbove(CPubDocFile *pdf);
+
+#ifndef REF
+ void AddXSMember(PTSetMember *ptsmRequestor,
+ PTSetMember *ptsmAdd,
+ DFLUID luid);
+ inline void InsertXSMember(PTSetMember *ptsm);
+ inline void RemoveXSMember(PTSetMember *ptsm);
+
+ inline PTSetMember *FindXSMember(CDfName const *pdfn,
+ DFLUID luidTree);
+ inline void RenameChild(CDfName const *pdfnOld,
+ DFLUID luidTree,
+ CDfName const *pdfnNew);
+ inline void DestroyChild(DFLUID luid);
+
+#endif //!REF
+
+ inline BOOL IsRoot(void) const;
+#ifdef COORD
+ inline BOOL IsCoord(void) const;
+ inline CRootPubDocFile * GetRoot(void);
+#endif
+
+ inline CPubDocFile *GetParent(void) const;
+ inline LONG GetRefCount(void) const;
+
+ inline PDocFile *GetDF(void) const;
+ inline void SetDF(PDocFile *pdf);
+
+ inline SCODE CheckReverted(void) const;
+#ifndef REF
+ inline UINT GetTransactedDepth(void) const;
+#endif //!REF
+ inline void SetClean(void);
+ inline BOOL IsDirty(void) const;
+ inline void SetDirty(void);
+ inline void SetDirtyBit(void);
+
+ inline CMStream * GetBaseMS(void);
+ inline CDFBasis * GetBasis(void);
+
+ inline CDfName *GetName(void);
+
+ static SCODE Validate(CPubDocFile *pdf);
+
+#ifndef REF
+#if DBG == 1
+ void VerifyXSMemberBases();
+#endif
+#endif //!REF
+
+protected:
+#ifndef REF
+ void ChangeXs(DFLUID const luidTree,
+ DWORD const dwOp);
+ SCODE PrepareForOverwrite(void);
+ SCODE GetCommitSize(ULONG *pulSize);
+
+#endif //!REF
+ static SCODE CopyLStreamToLStream(ILockBytes *plstFrom,
+ ILockBytes *plstTo);
+
+#ifndef REF
+ CTSSet _tss;
+#endif //!REF
+ CBasedPubDocFilePtr _pdfParent;
+ CBasedDocFilePtr _pdf;
+ CChildInstanceList _cilChildren;
+#ifndef REF
+ UINT _cTransactedDepth;
+#endif //!REF
+
+ WORD _wFlags;
+ CBasedMStreamPtr _pmsBase;
+ DFSIGNATURE _sigMSF;
+ ULONG _sig;
+
+ LONG _cReferences;
+#ifndef REF
+ CBasedDFBasisPtr _pdfb;
+#else
+ ILockBytes *_pilbBase;
+#endif //!REF
+};
+// already defined in dfbasis.hxx
+//SAFE_DFBASED_PTR(CBasedPubDocFilePtr, CPubDocFile);
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::GetDF, public
+//
+// Synopsis: Returns _pdf
+//
+// History: 22-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline PDocFile *CPubDocFile::GetDF(void) const
+{
+ return BP_TO_P(PDocFile *, _pdf);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::SetDF, public
+//
+// Synopsis: Sets _pdf
+//
+// History: 26-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CPubDocFile::SetDF(PDocFile *pdf)
+{
+ _pdf = P_TO_BP(CBasedDocFilePtr, pdf);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::AddRef, public
+//
+// Synopsis: Changes the ref count
+//
+// History: 26-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CPubDocFile::vAddRef(void)
+{
+ InterlockedIncrement(&_cReferences);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::vDecRef, public
+//
+// Synopsis: Decrement the ref count
+//
+// History: 07-Feb-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CPubDocFile::vDecRef(void)
+{
+ LONG lRet;
+
+ olAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ vdtor();
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::IsRoot, public
+//
+// Synopsis: Returns _pdfParent == NULL
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline BOOL CPubDocFile::IsRoot(void) const
+{
+ return _pdfParent == NULL;
+}
+
+#ifdef COORD
+inline BOOL CPubDocFile::IsCoord(void) const
+{
+ return P_COORD(_df);
+}
+
+inline CRootPubDocFile * CPubDocFile::GetRoot(void)
+{
+ olAssert(IsRoot() || IsCoord());
+ if (IsRoot())
+ {
+ return (CRootPubDocFile *)this;
+ }
+ else
+ {
+ return (CRootPubDocFile *)(BP_TO_P(CPubDocFile *, _pdfParent));
+ }
+}
+#endif
+
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::GetParent, public
+//
+// Synopsis: Returns _pdfParent
+//
+// History: 02-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CPubDocFile *CPubDocFile::GetParent(void) const
+{
+ return BP_TO_P(CPubDocFile *, _pdfParent);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::GetRefCount, public
+//
+// Synopsis: Returns the ref count
+//
+// History: 09-Apr-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline LONG CPubDocFile::GetRefCount(void) const
+{
+ return _cReferences;
+}
+
+#ifndef REF
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::GetTransactedDepth, public
+//
+// Synopsis: Returns the transaction depth
+//
+// History: 06-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline UINT CPubDocFile::GetTransactedDepth(void) const
+{
+ return _cTransactedDepth;
+}
+#endif //!REF
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::SetClean, public
+//
+// Synopsis: Resets the dirty flag
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CPubDocFile::SetClean(void)
+{
+ _wFlags = (_wFlags & ~PF_DIRTY);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::IsDirty, public
+//
+// Synopsis: Returns the dirty flag
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CPubDocFile::IsDirty(void) const
+{
+ return (_wFlags & PF_DIRTY);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::SetDirty, public
+//
+// Synopsis: Sets the dirty flag and all parents' dirty flags
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_SetDirty)
+#endif
+
+inline void CPubDocFile::SetDirty(void)
+{
+ CPubDocFile *ppdf = this;
+
+ olAssert((this != NULL) && aMsg("Attempted to dirty parent of root"));
+
+ do
+ {
+ ppdf->SetDirtyBit();
+#ifndef REF
+ if (P_TRANSACTED(ppdf->GetDFlags()))
+ {
+ // We don't propagate the dirty bit past transacted storages
+ break;
+ }
+#endif //!REF
+
+ ppdf = ppdf->GetParent();
+ } while (ppdf != NULL);
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::SetDirtyBit, public
+//
+// Synopsis: Sets the dirty flag
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CPubDocFile::SetDirtyBit(void)
+{
+ _wFlags = _wFlags | PF_DIRTY;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::Revert, public
+//
+// Synopsis: Reverts transacted changes
+//
+// Returns: Appropriate status code
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CPubDocFile::Revert(void)
+{
+#ifndef REF
+ SCODE sc;
+
+ if (SUCCEEDED(sc = CheckReverted()) && P_TRANSACTED(_df))
+ {
+ _cilChildren.DeleteByName(NULL);
+ ChangeXs(DF_NOLUID, XSO_REVERT);
+#if DBG == 1
+ VerifyXSMemberBases();
+#endif
+ SetClean();
+ _wFlags = _wFlags & ~PF_PREPARED;
+ }
+ return sc;
+#else
+ return S_OK;
+#endif //!REF
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::ReleaseChild, private
+//
+// Synopsis: Releases a child instance
+//
+// Arguments: [prv] - Child instance
+//
+// History: 03-Feb-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CPubDocFile::ReleaseChild(PRevertable *prv)
+{
+ olAssert(SUCCEEDED(CheckReverted()));
+ _cilChildren.RemoveRv(prv);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::AddChild, public
+//
+// Synopsis: Adds a child instance
+//
+// Arguments: [prv] - Child
+//
+// History: 03-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CPubDocFile::AddChild(PRevertable *prv)
+{
+ olAssert(SUCCEEDED(CheckReverted()));
+ _cilChildren.Add(prv);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::IsEntry, public
+//
+// Synopsis: Checks whether the given name is an entry or not
+//
+// Arguments: [dfnName] - Name of element
+// [peb] - Entry buffer to fill in
+//
+// Returns: Appropriate status code
+//
+// Modifies: [peb]
+//
+// History: 17-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CPubDocFile::IsEntry(CDfName const *dfnName,
+ SEntryBuffer *peb)
+{
+ SCODE sc;
+
+ if (SUCCEEDED(sc = CheckReverted()))
+ sc = _pdf->IsEntry(dfnName, peb);
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::IsAtOrAbove, public
+//
+// Synopsis: Determines whether the given public is an ancestor
+// of this public
+//
+// Arguments: [pdf] - Docfile to check
+//
+// Returns: TRUE or FALSE
+//
+// History: 07-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubDocFile_IsAtOrAbove)
+#endif
+
+inline BOOL CPubDocFile::IsAtOrAbove(CPubDocFile *pdf)
+{
+ CPubDocFile *pdfPar = this;
+
+ olAssert(SUCCEEDED(CheckReverted()));
+#ifndef REF
+ // MAC compiler can't support natural form with two returns
+#endif //!REF
+ do
+ {
+ if (pdfPar == pdf)
+ break;
+ }
+ while (pdfPar = BP_TO_P(CPubDocFile *, pdfPar->_pdfParent));
+ return pdfPar == pdf;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::CheckReverted, private
+//
+// Synopsis: Returns STG_E_REVERTED if reverted
+//
+// History: 30-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CPubDocFile::CheckReverted(void) const
+{
+#ifndef COORD
+ return P_REVERTED(_df) ? STG_E_REVERTED : S_OK;
+#else
+ //BUGBUG: Need a better error code for the committing case.
+ return P_REVERTED(_df) ? STG_E_REVERTED :
+ (P_COMMITTING(_df) ? E_UNEXPECTED : S_OK);
+#endif
+}
+
+#ifndef REF
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::InsertXSMember, public
+//
+// Synopsis: Puts an XSM into the XS
+//
+// Arguments: [ptsm] - XSM
+//
+// History: 23-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CPubDocFile::InsertXSMember(PTSetMember *ptsm)
+{
+ olAssert(_tss.FindName(ptsm->GetDfName(), ptsm->GetTree()) == NULL);
+ ptsm->AddRef();
+ _tss.AddMember(ptsm);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::RemoveXSMember, public
+//
+// Synopsis: Removes an XSM from the XS
+//
+// Arguments: [ptsm] - XSM
+//
+// History: 23-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CPubDocFile::RemoveXSMember(PTSetMember *ptsm)
+{
+ olAssert(_tss.FindName(ptsm->GetDfName(), ptsm->GetTree()) != NULL);
+ _tss.RemoveMember(ptsm);
+ ptsm->Release();
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::FindXSMember, public
+//
+// Synopsis: Looks up an XS member
+//
+// Arguments: [pdfn] - Name of object to find
+// [luidTree] - Tree to look in
+//
+// Returns: Member or NULL
+//
+// History: 29-Jan-92 DrewB Created
+// 28-Oct-92 AlexT Convert to name
+//
+//---------------------------------------------------------------
+
+inline PTSetMember *CPubDocFile::FindXSMember(CDfName const *pdfn,
+ DFLUID luidTree)
+{
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::FindXSMember:%p(%p)\n",
+ this, pdfn));
+ olAssert(pdfn != NULL && aMsg("Can't find XSM with NULL name"));
+ PTSetMember *ptsm = _tss.FindName(pdfn, luidTree);
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::FindXSMember => %p\n", ptsm));
+ return ptsm;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::DestroyChild, public
+//
+// Synopsis: Destroy a child
+//
+// Arguments: [luid] - Name of child to destroy
+//
+// History: 29-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CPubDocFile::DestroyChild(DFLUID luid)
+{
+ olAssert(luid != DF_NOLUID);
+ ChangeXs(luid, XSO_RELEASE);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::RenameChild, public
+//
+// Synopsis: Rename a child
+//
+// Arguments: [pdfnOld] - Current name
+// [luidTree] - Tree to look in
+// [pdfnNew] - New name
+//
+// History: 28-Oct-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void CPubDocFile::RenameChild(
+ CDfName const *pdfnOld,
+ DFLUID luidTree,
+ CDfName const *pdfnNew)
+{
+ _tss.RenameMember(pdfnOld, luidTree, pdfnNew);
+}
+
+#endif //!REF
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::GetBaseMS, public
+//
+// Synopsis: Return pointer to base multistream
+//
+// History: 11-Feb-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CMStream * CPubDocFile::GetBaseMS(void)
+{
+ return BP_TO_P(CMStream *, _pmsBase);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::GetName, public
+//
+// Synopsis: Returns a pointer to the name of this storage
+//
+// Returns: CDfName *
+//
+// History: 30-Nov-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline CDfName *CPubDocFile::GetName(void)
+{
+ return &_dfn;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::FindGreaterEntry, public
+//
+// Synopsis: Returns the next greater child
+//
+// Arguments: [pdfnKey] - Previous key
+// [pib] - Fast iterator buffer
+// [pstat] - Full iterator buffer
+// [fProps] - Return properties or normal entries
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pib] or [pstat]
+//
+// History: 16-Apr-93 DrewB Created
+//
+// Notes: Either [pib] or [pstat] must be NULL
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CPubDocFile::FindGreaterEntry(CDfName const *pdfnKey,
+ SIterBuffer *pib,
+ STATSTGW *pstat,
+ BOOL fProps)
+{
+ olAssert((pib == NULL) != (pstat == NULL));
+ olAssert(SUCCEEDED(CheckReverted()));
+ return _pdf->FindGreaterEntry(pdfnKey, pib, pstat);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::GetBasis, public
+//
+// Synopsis: Returns DfBasis
+//
+//----------------------------------------------------------------------------
+
+inline CDFBasis* CPubDocFile::GetBasis(void)
+{
+ return BP_TO_P(CDFBasis*, _pdfb);
+}
+
+#endif
+
diff --git a/private/ole32/stg/h/ref.hxx b/private/ole32/stg/h/ref.hxx
new file mode 100644
index 000000000..b670d2e1c
--- /dev/null
+++ b/private/ole32/stg/h/ref.hxx
@@ -0,0 +1,198 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: ref.hxx
+//
+// Contents: Reference implementation stuff
+//
+// Classes:
+//
+// Functions:
+//
+// History: 26-Apr-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __REF_HXX__
+#define __REF_HXX__
+
+#ifdef REF
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#define FARSTRUCT
+#define interface struct
+#define DECLARE_INTERFACE(iface) interface iface
+#define DECLARE_INTERFACE_(iface, baseiface) interface iface: public baseiface
+
+typedef long SCODE;
+typedef void * HRESULT;
+
+#define NOERROR 0
+
+
+#define PURE = 0
+
+#define STDMETHODIMP HRESULT
+#define STDMETHODIMP_(type) type
+#define STDMETHOD(method) virtual HRESULT method
+#define STDMETHOD_(type, method) virtual type method
+#define STDAPI HRESULT
+#define STDAPI_(type) type
+#define THIS_
+#define THIS void
+#define FAR
+
+typedef int BOOL;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned int UINT;
+typedef long LONG;
+typedef unsigned long DWORD;
+typedef short SHORT;
+typedef unsigned short USHORT;
+typedef DWORD ULONG;
+typedef void VOID;
+typedef WORD WCHAR;
+
+typedef void * LPVOID;
+typedef char * LPSTR;
+typedef char * LPCSTR;
+
+#define TRUE 1
+#define FALSE 0
+
+
+typedef struct _ULARGE_INTEGER {
+ DWORD LowPart;
+ DWORD HighPart;
+} ULARGE_INTEGER, *PULARGE_INTEGER;
+#define ULISet32(li, v) ((li).HighPart = 0, (li).LowPart = (v))
+
+typedef struct _LARGE_INTEGER {
+ DWORD LowPart;
+ LONG HighPart;
+} LARGE_INTEGER, *PLARGE_INTEGER;
+#define LISet32(li, v) ((li).HighPart = ((LONG)(v)) < 0 ? -1 : 0, (li).LowPart = (v))
+
+struct GUID
+{
+ DWORD Data1;
+ WORD Data2;
+ WORD Data3;
+ BYTE Data4[8];
+};
+
+typedef GUID CLSID;
+typedef GUID IID;
+
+#define REFGUID const GUID &
+#define REFIID const IID &
+#define REFCLSID const CLSID &
+
+
+
+
+DECLARE_INTERFACE(IUnknown)
+{
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+};
+
+
+#include <storage.h>
+
+#define S_OK 0L
+#define MAKE_SCODE(sev,fac,code) \
+ ((SCODE) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
+#define SEVERITY_SUCCESS 0
+#define SEVERITY_ERROR 1
+#define FACILITY_STORAGE 0x0003 // storage errors (STG_E_*)
+#define FACILITY_NULL 0x0000
+#define S_TRUE 0L
+#define S_FALSE MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 1)
+#define E_NOINTERFACE MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 4)
+#define E_OUTOFMEMORY MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 2)
+#define SUCCEEDED(Status) ((SCODE)(Status) >= 0)
+#define FAILED(Status) ((SCODE)(Status)<0)
+#define GetScode(hr) ((SCODE)(hr) & 0x800FFFFF)
+#define ResultFromScode(sc) ((HRESULT)((SCODE)(sc) & 0x800FFFFF))
+
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ const GUID name
+#define DEFINE_OLEGUID(name, l, w1, w2) \
+ DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)
+
+//REFBUG: This GUID won't be properly initialized by this macro.
+DEFINE_GUID(GUID_NULL, 0L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+/* storage related interfaces */
+DEFINE_OLEGUID(IID_IUnknown, 0x00000000L, 0, 0);
+DEFINE_OLEGUID(IID_IRootStorage, 0x00000012L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved1, 0x00000013L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved2, 0x00000014L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved3, 0x00000015L, 0, 0);
+DEFINE_OLEGUID(IID_ILockBytes, 0x0000000aL, 0, 0);
+DEFINE_OLEGUID(IID_IStorage, 0x0000000bL, 0, 0);
+DEFINE_OLEGUID(IID_IStream, 0x0000000cL, 0, 0);
+DEFINE_OLEGUID(IID_IEnumSTATSTG, 0x0000000dL, 0, 0);
+
+STDAPI_(BOOL) IsEqualGUID(REFGUID rguid1, REFGUID rguid2);
+#define IsEqualIID(x, y) IsEqualGUID(x, y)
+#define IsEqualCLSID(x, y) IsEqualGUID(x, y)
+
+#define IID_NULL GUID_NULL
+#define CLSID_NULL GUID_NULL
+
+
+#define UNIMPLEMENTED_PARM(x) (x)
+
+#define UNREFERENCED_PARM(x) (x)
+
+#define DEB_ERROR 0x00000001 // exported error paths
+#define DEB_TRACE 0x00000004 // exported trace messages
+
+#define DEB_IERROR 0x00000100 // internal error paths
+#define DEB_ITRACE 0x00000400 // internal trace messages
+
+
+#if DBG == 1
+
+//When this gets built into an exe, the macro below should include
+// vprintf((const char *)pszfmt, vstart) in the if block.
+#define DECLARE_DEBUG(comp) \
+extern "C" unsigned long comp##InfoLevel; \
+extern "C" char *comp##InfoLevelString; \
+_inline void \
+comp##InlineDebugOut(unsigned long fDebugMask, char const *pszfmt, ...) \
+{ \
+ va_list vstart; \
+ va_start(vstart, pszfmt); \
+ if (comp##InfoLevel & fDebugMask) \
+ { \
+ } \
+}
+
+#define DECLARE_INFOLEVEL(comp) \
+extern "C" unsigned long comp##InfoLevel = DEB_ERROR; \
+extern "C" char *comp##InfoLevelString = #comp;
+
+#else
+#define DECLARE_DEBUG(comp)
+#define DECLARE_INFOLEVEL(comp)
+#endif
+
+
+class ILockBytes;
+class CDfName;
+
+SCODE CreateFileStream(ILockBytes **ppilb, CDfName *pdfn);
+SCODE DeleteFileStream(CDfName *pdfn);
+
+#endif //REF
+
+#endif // #ifndef __REF_HXX__
diff --git a/private/ole32/stg/h/refilb.hxx b/private/ole32/stg/h/refilb.hxx
new file mode 100644
index 000000000..6752cc0a8
--- /dev/null
+++ b/private/ole32/stg/h/refilb.hxx
@@ -0,0 +1,59 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: fileilb.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+// History: 27-Apr-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FILEILB_HXX__
+#define __FILEILB_HXX__
+
+#include <storage.h>
+
+class CFileILB: public ILockBytes
+{
+public:
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ // *** ILockBytes methods ***
+ STDMETHOD(ReadAt) (THIS_ ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbRead);
+ STDMETHOD(WriteAt) (THIS_ ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten);
+ STDMETHOD(Flush) (THIS);
+ STDMETHOD(SetSize) (THIS_ ULARGE_INTEGER cb);
+ STDMETHOD(LockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag);
+
+ CFileILB(char *pszName);
+ ~CFileILB();
+
+private:
+ FILE * _f;
+ ULONG _ulRef;
+ char *_pszName;
+ BOOL _fDelete;
+};
+
+#endif // #ifndef __FILEILB_HXX__
diff --git a/private/ole32/stg/h/revert.hxx b/private/ole32/stg/h/revert.hxx
new file mode 100644
index 000000000..32f96cac0
--- /dev/null
+++ b/private/ole32/stg/h/revert.hxx
@@ -0,0 +1,96 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: revert.hxx
+//
+// Contents: PRevertable definition
+//
+// Classes: PRevertable
+//
+// History: 28-Apr-92 DrewB Created
+// 18-May-93 AlexT Added CMallocBased
+//
+// Notes: This class forms the root of all objects in the
+// transaction tree that understand reversion.
+// It allows lists of them to be formed.
+//
+//---------------------------------------------------------------
+
+#ifndef __REVERT_HXX__
+#define __REVERT_HXX__
+
+#include <dfmsp.hxx>
+
+class CChildInstanceList;
+class PRevertable;
+
+class PRevertable : public CMallocBased
+{
+public:
+ virtual void RevertFromAbove(void) = 0;
+#ifdef NEWPROPS
+ virtual SCODE FlushBufferedData(int recursionlevel) = 0;
+#endif
+ inline DFLUID GetLuid(void) const;
+ inline DFLAGS GetDFlags(void) const;
+ inline PRevertable *GetNext(void) const;
+
+ friend class CChildInstanceList;
+
+protected:
+ DFLUID _luid;
+ DFLAGS _df;
+ CDfName _dfn;
+
+private:
+ CBasedRevertablePtr _prvNext;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: PRevertable::GetLuid, public
+//
+// Synopsis: Returns the LUID
+//
+// History: 11-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline DFLUID PRevertable::GetLuid(void) const
+{
+ return _luid;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PRevertable::GetDFlags, public
+//
+// Synopsis: Returns the flags
+//
+// History: 11-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline DFLAGS PRevertable::GetDFlags(void) const
+{
+ return _df;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PRevertable::GetNext, public
+//
+// Synopsis: Returns the next revertable
+//
+// History: 11-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline PRevertable *PRevertable::GetNext(void) const
+{
+ return BP_TO_P(PRevertable *, _prvNext);
+}
+
+#endif // #ifndef __REVERT_HXX__
diff --git a/private/ole32/stg/h/rpubdf.hxx b/private/ole32/stg/h/rpubdf.hxx
new file mode 100644
index 000000000..37477ca0c
--- /dev/null
+++ b/private/ole32/stg/h/rpubdf.hxx
@@ -0,0 +1,95 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: rpubdf.hxx
+//
+// Contents: Root public docfile header
+//
+// Classes: CRootPubDocFile
+//
+// History: 26-Aug-92 DrewB Created
+// 05-Sep-95 MikeHill Added Commit and
+// _timeModifyAtCommit.
+//
+//---------------------------------------------------------------
+
+#ifndef __RPUBDF_HXX__
+#define __RPUBDF_HXX__
+
+#include <publicdf.hxx>
+
+//+--------------------------------------------------------------
+//
+// Class: CRootPubDocFile (rpdf)
+//
+// Purpose: Root form of the public docfile
+//
+// Interface: See below
+//
+// History: 26-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+class CRootPubDocFile : public CPubDocFile
+{
+public:
+ CRootPubDocFile(IMalloc * const pMalloc);
+ SCODE InitRoot(ILockBytes *plstBase,
+ DWORD const dwStartFlags,
+ DFLAGS const df,
+ SNBW snbExclude,
+#ifndef REF
+ CDFBasis **ppdfb,
+#endif //!REF
+ ULONG *pulOpenLock);
+#ifndef REF
+ // C700 - Virtual destructors aren't working properly so explicitly
+ // declare one
+#endif //!REF
+ virtual void vdtor(void);
+
+ virtual SCODE Stat(STATSTGW *pstatstg, DWORD grfStatFlag);
+
+ void ReleaseLocks(ILockBytes *plkb);
+
+#ifndef REF
+
+ SCODE SwitchToFile(OLECHAR const *ptcsFile,
+ ILockBytes *plkb,
+ ULONG *pulOpenLock);
+ virtual SCODE Commit( DWORD const dwFlags ); // CPubDocFile override
+
+#endif //!REF
+
+
+private:
+#ifndef REF
+ SCODE InitInd(ILockBytes *plstBase,
+ SNBW snbExclude,
+ DWORD const dwStartFlags,
+ DFLAGS const df);
+#endif //!REF
+#ifndef REF
+ SCODE InitNotInd(ILockBytes *plstBase,
+ SNBW snbExclude,
+ DWORD const dwStartFlags,
+ DFLAGS const df);
+ ULONG _ulPriLock;
+#else
+ SCODE Init(ILockBytes *plstBase,
+ SNBW snbExclude,
+ DWORD const dwStartFlags,
+ DFLAGS const df);
+#endif //!REF
+
+ IMalloc * const _pMalloc;
+
+#ifndef REF
+ TIME_T _timeModifyAtCommit; // Last-Modify time on Docfile after commit.
+#endif // !REF
+
+};
+
+#endif // #ifndef __RPUBDF_HXX__
diff --git a/private/ole32/stg/h/safedecl.hxx b/private/ole32/stg/h/safedecl.hxx
new file mode 100644
index 000000000..e206338cd
--- /dev/null
+++ b/private/ole32/stg/h/safedecl.hxx
@@ -0,0 +1,32 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: safedecl.hxx
+//
+// Contents: Declare some globally useful safe pointer classes
+//
+// History: 18-Oct-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __SAFEDECL_HXX__
+#define __SAFEDECL_HXX__
+
+#include <safepnt.hxx>
+
+SAFE_INTERFACE_PTR(SafeIUnknown, IUnknown);
+SAFE_INTERFACE_PTR(SafeIStorage, IStorage);
+SAFE_INTERFACE_PTR(SafeIStream, IStream);
+SAFE_HEAP_MEMPTR(SafeBytePtr, BYTE);
+
+// Declare only on Nt-based platforms
+#ifdef NT_INCLUDED
+#if !defined(_CHICAGO_)
+SAFE_NT_HANDLE(SafeNtHandle);
+SAFE_NT_HANDLE_NO_UNWIND(NuSafeNtHandle);
+#endif
+#endif
+
+#endif // #ifndef __SAFEDECL_HXX__
diff --git a/private/ole32/stg/h/segh.hxx b/private/ole32/stg/h/segh.hxx
new file mode 100644
index 000000000..293dd6c3e
--- /dev/null
+++ b/private/ole32/stg/h/segh.hxx
@@ -0,0 +1,68 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: SegH.HXX
+//
+// Contents: Segment defines for 16-bit builds
+//
+// History: 11-Jun-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __SEGH_HXX__
+#define __SEGH_HXX__
+
+// We only do segment tuning for 16-bit x86 non-DEBUG builds
+
+#if defined(_M_I286) && DBG == 0
+#define CODESEGMENTS
+
+// Common code
+
+#define SEG_CDFBasis_1CDFBasis "Common0_TEXT"
+#define SEG_CDocFile_1CDocFile "Common0_TEXT"
+#define SEG_CFreeList_1CFreeList "Common0_TEXT"
+#define SEG_CMSFPage_1CMSFPage "Common0_TEXT"
+#define SEG_CDFBasis_CDFBasis "Common0_TEXT"
+
+#define SEG_CDfName_Set "Common1_TEXT"
+#define SEG_CDirectory_GetClassId "Common1_TEXT"
+#define SEG_CDirectory_GetSize "Common1_TEXT"
+#define SEG_CDirectory_GetTime "Common1_TEXT"
+#define SEG_CDirectory_GetUserFlags "Common1_TEXT"
+#define SEG_CDocFile_CDocFile2 "Common1_TEXT"
+#define SEG_CGlobalFileStream_CGlobalFileStream "Common1_TEXT"
+
+#define SEG_CPagedVector_CPagedVector "Common2_TEXT"
+#define SEG_CPagedVector_SetSect "Common2_TEXT"
+#define SEG_CPerContext_InitNewContext "Common2_TEXT"
+#define SEG_CStgHandle_GetEntry "Common2_TEXT"
+
+#define SEG_CDirectory_IsEntry "BootSave_TEXT"
+#define SEG_CFreeList_GetReserved "BootSave_TEXT"
+
+#define SEG_CFat_QueryRemapped "OpenSave1_TEXT"
+#define SEG_CPubDocFile_SetDirty "OpenSave1_TEXT"
+#define SEG_CPubStream_WriteAt "OpenSave1_TEXT"
+#define SEG_PDocFile_PDocFile "OpenSave1_TEXT"
+
+#define SEG_CDocFile_CDocFile1 "Save_TEXT"
+#define SEG_CMStream_CreateEntry "Save_TEXT"
+
+#define SEG_CPagedVector_ResetBits "Commit_TEXT"
+
+#define SEG_CDirectory_GetChild "UnassignedH_TEXT"
+#define SEG_CDirectStream_ReturnToReserve "UnassignedH_TEXT"
+#define SEG_CMStream_DestroyEntry "UnassignedH_TEXT"
+#define SEG_CPubDocFile_IsAtOrAbove "UnassignedH_TEXT"
+#define SEG_CDFBasis_SetContext "UnassignedH_TEXT"
+#define SEG_CWrappedDocFile_ReturnDocFile "UnassignedH_TEXT"
+#define SEG_CWrappedDocFile_ReturnStream "UnassignedH_TEXT"
+#define SEG_CDocFile_ReturnToReserve "UnassignedH_TEXT"
+#define SEG_CFreeList_ReturnToReserve "UnassignedH_TEXT"
+#define SEG_CTSSet_RenameMember "UnassignedH_TEXT"
+
+#endif // defined(_M_I286) && DBG == 0
+#endif // __SEGH_HXX__
diff --git a/private/ole32/stg/h/sinklist.hxx b/private/ole32/stg/h/sinklist.hxx
new file mode 100644
index 000000000..fc3436a32
--- /dev/null
+++ b/private/ole32/stg/h/sinklist.hxx
@@ -0,0 +1,198 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: sinklist.hxx
+//
+// Contents: Linked list class
+//
+// Classes: CSinkList
+// CConnectionPoint
+//
+// Functions:
+//
+// History: 24-Dec-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __SINKLIST_HXX__
+#define __SINKLIST_HXX__
+
+class CSafeSem;
+
+#include <iconn.h>
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSinkList
+//
+// Purpose: Generic linked list class for use by async docfiles
+//
+// Interface:
+//
+// History: 24-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+class CSinkList
+{
+public:
+ inline CSinkList();
+
+ inline CSinkList *GetNext(void);
+ inline void SetNext(CSinkList *psl);
+
+ inline DWORD GetCookie(void);
+ inline void SetCookie(DWORD dwCookie);
+
+ inline IProgressNotify *GetProgressNotify(void);
+ inline void SetProgressNotify(IProgressNotify *ppn);
+
+private:
+ IProgressNotify *_ppn;
+ DWORD _dwCookie;
+ CSinkList *_pslNext;
+};
+
+
+inline CSinkList::CSinkList()
+{
+ _ppn = NULL;
+ _dwCookie = 0;
+ _pslNext = NULL;
+}
+
+
+inline CSinkList * CSinkList::GetNext(void)
+{
+ return _pslNext;
+}
+
+
+inline void CSinkList::SetNext(CSinkList *psl)
+{
+ _pslNext = psl;
+}
+
+
+inline DWORD CSinkList::GetCookie(void)
+{
+ return _dwCookie;
+}
+
+
+inline void CSinkList::SetCookie(DWORD dwCookie)
+{
+ _dwCookie = dwCookie;
+}
+
+
+inline IProgressNotify *CSinkList::GetProgressNotify(void)
+{
+ return _ppn;
+}
+
+
+inline void CSinkList::SetProgressNotify(IProgressNotify *ppn)
+{
+ _ppn = ppn;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CConnectionPoint
+//
+// Purpose:
+//
+// Interface:
+//
+// History: 28-Dec-95 SusiA Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+class CConnectionPoint: public IDocfileAsyncConnectionPoint
+{
+public:
+ CConnectionPoint();
+ ~CConnectionPoint();
+
+ inline CSinkList *GetHead(void);
+ inline void TakeCS(void);
+ inline void ReleaseCS(void);
+
+ //From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+#ifdef ASYNC
+#else
+ SCODE Notify(SCODE scFailure,
+ IFillLockBytes *piflb,
+ BOOL fDefaultLockBytes);
+#endif
+
+ //From IDocfileAsyncConnectionPoint
+ STDMETHOD(AddConnection)(IProgressNotify *pUnkSink,
+ DWORD *pdwCookie);
+ STDMETHOD(RemoveConnection)(DWORD dwCookie);
+ STDMETHOD(NotifySinks)(ULONG ulProgressCurrent,
+ ULONG ulProgressMaximum,
+ BOOL fAccurate,
+ SCODE sc);
+ STDMETHOD(GetParent)(IDocfileAsyncConnectionPoint **ppParent);
+
+ SCODE Clone (CConnectionPoint *pcp);
+ inline DWORD GetCookie(void);
+ inline void SetParent(IDocfileAsyncConnectionPoint *pParentCP);
+
+private:
+ DWORD _dwCookie;
+ LONG _cReferences;
+ CSinkList *_pSinkHead;
+ IDocfileAsyncConnectionPoint *_pParentCP;
+ CRITICAL_SECTION _csSinkList;
+};
+
+
+inline void CConnectionPoint::TakeCS(void)
+{
+ EnterCriticalSection(&_csSinkList);
+}
+
+
+inline void CConnectionPoint::ReleaseCS(void)
+{
+ LeaveCriticalSection(&_csSinkList);
+}
+
+
+inline CSinkList * CConnectionPoint::GetHead(void)
+{
+ return _pSinkHead;
+}
+
+
+inline DWORD CConnectionPoint::GetCookie(void)
+{
+ return _dwCookie;
+}
+
+
+inline void CConnectionPoint::SetParent(
+ IDocfileAsyncConnectionPoint *pParentCP)
+{
+ _pParentCP = pParentCP;
+ if (_pParentCP != NULL)
+ _pParentCP->AddRef();
+}
+
+
+#endif // #ifndef __SINKLIST_HXX__
+
+
diff --git a/private/ole32/stg/h/smalloc.hxx b/private/ole32/stg/h/smalloc.hxx
new file mode 100644
index 000000000..ba9b0790d
--- /dev/null
+++ b/private/ole32/stg/h/smalloc.hxx
@@ -0,0 +1,866 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: heap.hxx
+//
+// Contents: Heap code headers
+//
+// Classes: CHeap
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+// 10-Apr095 HenryLee Added global LUID
+// 10-May-95 KentCe Defer Heap Destruction to the last
+// process detach.
+//
+//----------------------------------------------------------------------------
+
+#ifndef __HEAP_HXX__
+#define __HEAP_HXX__
+
+#include <smblock.hxx>
+#include <memdebug.hxx>
+#include <smmutex.hxx>
+#include <msf.hxx>
+#include <df32.hxx>
+
+#ifdef COORD
+#include <dfrlist.hxx>
+#endif
+
+//Space to reserve for heap.
+const ULONG MINHEAPGROWTH = 4096;
+const ULONG INITIALHEAPSIZE = 16384;
+
+#ifdef MULTIHEAP
+#include <ntpsapi.h>
+class CPerContext;
+
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Class: CLockDfMutex
+//
+// Purpose: Simple class to guarantee that a DfMutex is unlocked
+//
+// History: 29-Apr-95 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+class CLockDfMutex
+{
+public:
+
+ CLockDfMutex(CDfMutex& dmtx);
+
+ ~CLockDfMutex(void);
+
+private:
+
+ CDfMutex& _dmtx;
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLockDfMutex::CLockDfMutex
+//
+// Synopsis: Get mutex
+//
+// Arguments: [dmtx] -- mutex to get
+//
+// History: 29-Apr-95 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+inline CLockDfMutex::CLockDfMutex(CDfMutex& dmtx) : _dmtx(dmtx)
+{
+ _dmtx.Take(DFM_TIMEOUT);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CLockDfMutex::~CLockDfMutex
+//
+// Synopsis: Release the mutex
+//
+// History: 29-Apr-95 DonnaLi Created
+//
+//--------------------------------------------------------------------------
+inline CLockDfMutex::~CLockDfMutex(void)
+{
+ _dmtx.Release();
+}
+
+//
+// Take advantage of Windows 95 Shared Heap.
+//
+#if !defined(_CHICAGO_)
+
+//+---------------------------------------------------------------------------
+//
+// Class: CBlockPreHeader
+//
+// Purpose: Required header fields for a block
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+class CBlockPreHeader
+{
+protected:
+ ULONG _ulSize; //Size of block
+ BOOL _fFree; //TRUE if block is free
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CBlockHeader
+//
+// Purpose: Fields required for free blocks but overwritten for
+// allocated blocks.
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+class CBlockHeader: public CBlockPreHeader
+{
+public:
+ inline ULONG GetSize(void) const;
+ inline BOOL IsFree(void) const;
+ inline ULONG GetNext(void) const;
+
+ inline void SetSize(ULONG ulSize);
+ inline void SetFree(void);
+ inline void ResetFree(void);
+ inline void SetNext(ULONG ulNext);
+private:
+ ULONG _ulNext; //Pointer to next block
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CBlockHeader::GetSize, public
+//
+// Synopsis: Returns the size of the block
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CBlockHeader::GetSize(void) const
+{
+ return _ulSize;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CBlockHeader::IsFree, public
+//
+// Synopsis: Returns free state of block
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CBlockHeader::IsFree(void) const
+{
+ return _fFree;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CBlockHeader::GetNext, public
+//
+// Synopsis: Return next offset
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CBlockHeader::GetNext(void) const
+{
+ return _ulNext;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CBlockHeader::SetSize, public
+//
+// Synopsis: Set size of block
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CBlockHeader::SetSize(ULONG ulSize)
+{
+ _ulSize = ulSize;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CBlockHeader::SetFree, public
+//
+// Synopsis: Set this block to free
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CBlockHeader::SetFree(void)
+{
+ _fFree = TRUE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CBlockHeader::ResetFree, public
+//
+// Synopsis: Set this block to !free
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CBlockHeader::ResetFree(void)
+{
+ _fFree = FALSE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CBlockHeader::SetNext, public
+//
+// Synopsis: Set next offset
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CBlockHeader::SetNext(ULONG ulNext)
+{
+ _ulNext = ulNext;
+}
+
+const ULONG CBLOCKMIN = ((sizeof(CBlockHeader) & 7)
+ ? sizeof(CBlockHeader) +
+ (8 - (sizeof(CBlockHeader) & 7))
+ : sizeof(CBlockHeader));
+
+//+---------------------------------------------------------------------------
+//
+// Class: CHeapHeader
+//
+// Purpose: Header information for shared memory heap
+//
+// Interface:
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+// Notes: The size of this structure must be a multiple of 8 bytes.
+//
+//----------------------------------------------------------------------------
+
+class CHeapHeader
+{
+public:
+ inline ULONG GetFirstFree(void) const;
+ inline void SetFirstFree(ULONG ulNew);
+
+ inline BOOL IsCompacted(void) const;
+ inline void SetCompacted(void);
+ inline void ResetCompacted(void);
+
+ inline void ResetAllocedBlocks(void);
+ inline ULONG IncrementAllocedBlocks(void);
+ inline ULONG DecrementAllocedBlocks(void);
+
+ inline ULONG GetAllocedBlocks(void);
+ inline DFLUID IncrementLuid(void);
+ inline void ResetLuid(void);
+
+#if DBG == 1
+ ULONG _ulAllocedBytes;
+ ULONG _ulFreeBytes;
+ ULONG _ulFreeBlocks;
+#endif
+
+private:
+ ULONG _ulFirstFree;
+ ULONG _ulAllocedBlocks;
+ BOOL _fIsCompacted;
+ DFLUID _dfLuid;
+#if DBG == 1
+ ULONG ulPad;
+#endif
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::GetFirstFree, public
+//
+// Synopsis: Return first free information
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CHeapHeader::GetFirstFree(void) const
+{
+ return _ulFirstFree;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::SetFirstFree, public
+//
+// Synopsis: Set first free information
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CHeapHeader::SetFirstFree(ULONG ulNew)
+{
+ _ulFirstFree = ulNew;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::IsCompacted, public
+//
+// Synopsis: Return TRUE if heap is compacted
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CHeapHeader::IsCompacted(void) const
+{
+ return _fIsCompacted;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::SetCompacted, public
+//
+// Synopsis: Set compacted bit
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CHeapHeader::SetCompacted(void)
+{
+ _fIsCompacted = TRUE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::ResetCompacted, public
+//
+// Synopsis: Reset compacted bit
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CHeapHeader::ResetCompacted(void)
+{
+ _fIsCompacted = FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::IncrementLuid, public
+//
+// Synopsis: Increment the global LUID
+//
+// History: 06-Apr-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+inline ULONG CHeapHeader::IncrementLuid()
+{
+ return ++_dfLuid;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::ResetLuid, public
+//
+// Synopsis: Increment the global LUID
+//
+// History: 06-Apr-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+inline void CHeapHeader::ResetLuid()
+{
+ _dfLuid = LUID_BASE; // some LUIDs are reserved
+}
+
+#else // define(_CHICAGO_)
+
+extern HANDLE gs_hSharedHeap; // hSharedHeap Handle for Win95.
+extern DFLUID gs_dfluid; // shared docfile LUID
+
+#endif // !define(_CHICAGO_)
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSmAllocator
+//
+// Purpose: Shared memory heap implementation
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+//
+//----------------------------------------------------------------------------
+
+class CSmAllocator: public IMalloc
+{
+public:
+ inline CSmAllocator();
+ inline ~CSmAllocator();
+
+ STDMETHOD_(ULONG,AddRef) ( void );
+ STDMETHOD_(ULONG,Release) ( void );
+ STDMETHOD(QueryInterface) ( REFIID riid, void ** ppv );
+
+ STDMETHOD_(void*,Alloc) ( ULONG cb );
+ STDMETHOD_(void *,Realloc) ( void *pvCurrent, ULONG cbNeeded );
+ STDMETHOD_(void,Free) ( void *pvMemToFree );
+ STDMETHOD_(ULONG,GetSize) ( void * pv );
+ STDMETHOD_(void,HeapMinimize) ( void );
+ STDMETHOD_(int,DidAlloc) ( void * pv );
+
+ inline SCODE Sync(void);
+ inline DFLUID IncrementLuid(void);
+
+#if !defined(MULTIHEAP)
+ SCODE Init ( LPWSTR pszName );
+#else
+ SCODE Init ( ULONG ulHeapName, BOOL fUnmarshal );
+#endif
+
+ inline void * GetBase(void);
+
+ // This function is equivalent to Free above, except that is does
+ // not attempt to first acquire the mutex. It should be used ONLY
+ // when the calling function guarantees to already have the mutex.
+ void FreeNoMutex (void * pv);
+#if !defined(MULTIHEAP)
+ inline CDfMutex * GetMutex (void);
+#endif
+#ifdef MULTIHEAP
+ void SetState (CSharedMemoryBlock *psmb, BYTE * pbBase,
+ ULONG ulHeapName, CPerContext ** ppcPrev,
+ CPerContext *ppcOwner);
+ void GetState (CSharedMemoryBlock **ppsmb, BYTE ** ppbBase,
+ ULONG *pulHeapName);
+ inline const ULONG GetHeapName ();
+ SCODE Uninit ();
+ inline const ULONG GetHeapSize () { return _cbSize; };
+#endif
+
+private:
+ inline void DoFree (void *pv);
+#if !defined(MULTIHEAP)
+ CDfMutex _dmtx;
+#endif
+//
+// Take advantage of Windows 95 Shared Heap.
+//
+#if !defined(_CHICAGO_)
+
+ CBlockHeader * FindBlock(ULONG cb, CBlockHeader **ppbhPrev);
+
+ inline CHeapHeader *GetHeader(void);
+
+ inline CBlockHeader * GetAddress(ULONG ulOffset) const;
+ inline ULONG GetOffset(CBlockHeader *pbh) const;
+
+ inline SCODE Reset(void);
+#if DBG == 1
+ void PrintFreeBlocks(void);
+#ifdef MULTIHEAP
+ void PrintAllocatedBlocks(void);
+#endif
+#endif
+
+#ifdef MULTIHEAP
+ CSharedMemoryBlock *_psmb;
+ BYTE *_pbBase;
+ ULONG _cbSize;
+ CPerContext * _ppcOwner;
+ ULONG _ulHeapName;
+ ULONG _cRefs; // yes, this object has a lifetime now
+#else
+ CSharedMemoryBlock _smb;
+
+ BYTE *_pbBase;
+
+ ULONG _cbSize;
+#endif // MULTIHEAP
+
+#else // defined(_CHICAGO_)
+
+ HANDLE m_hSharedHeap;
+
+#endif // !defined(_CHICAGO_)
+};
+
+#ifdef MULTIHEAP
+extern CSmAllocator g_SmAllocator; // single-threaded allocator
+extern CSharedMemoryBlock g_smb; //performance optimization
+extern ULONG g_ulHeapName;
+extern CSmAllocator& GetTlsSmAllocator(); // all other threads
+#define g_smAllocator (GetTlsSmAllocator())
+
+//+---------------------------------------------------------------------------
+//
+// Class: CErrorSmAllocator
+//
+// Synopsis: returned by GetTlsSmAllocator for out of memory failures
+//
+// History: 02-May-1996 HenryLee Created
+//
+//----------------------------------------------------------------------------
+class CErrorSmAllocator : public CSmAllocator
+{
+public:
+ STDMETHOD_(void*,Alloc) (ULONG cb) { return NULL; };
+ STDMETHOD_(void*,Realloc) (void* pv, ULONG cb) { return NULL; };
+ STDMETHOD_(void,Free) (void *pv) { return; };
+ STDMETHOD_(ULONG,GetSize) (void *pv) { return 0; };
+ STDMETHOD_(void,HeapMinimize) () { return; };
+ STDMETHOD_(int,DidAlloc) (void *pv) { return FALSE; };
+ SCODE Init (ULONG ul, BOOL f) { return STG_E_INSUFFICIENTMEMORY; };
+ SCODE Sync (void) { return STG_E_INSUFFICIENTMEMORY; };
+};
+extern CErrorSmAllocator g_ErrorSmAllocator;
+
+#else
+extern CSmAllocator g_smAllocator;
+#endif
+extern CRITICAL_SECTION g_csScratchBuffer;
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::CSmAllocator, public
+//
+// Synopsis: Constructor
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+//
+//----------------------------------------------------------------------------
+
+inline CSmAllocator::CSmAllocator(void)
+#if !defined(_CHICAGO_)
+#ifdef MULTIHEAP
+ : _cbSize(0), _pbBase(NULL), _cRefs(1), _ulHeapName(0),
+ _psmb(NULL), _ppcOwner(NULL)
+#else
+ : _cbSize(0)
+#endif // MULTIHEAP
+#else
+ : m_hSharedHeap(NULL)
+#endif
+{
+#if !defined(MULTIHEAP)
+ InitializeCriticalSection(&g_csScratchBuffer);
+#ifdef COORD
+ InitializeCriticalSection(&g_csResourceList);
+#endif
+#endif // MULTIHEAP
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::~CSmAllocator, public
+//
+// Synopsis: Destructor
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+// 10-May-95 KentCe Defer Heap Destruction to the last
+// process detach.
+//
+//----------------------------------------------------------------------------
+
+inline CSmAllocator::~CSmAllocator(void)
+{
+#if !defined(MULTIHEAP)
+ DeleteCriticalSection(&g_csScratchBuffer);
+#ifdef COORD
+ DeleteCriticalSection(&g_csResourceList);
+#endif
+#endif // MULTIHEAP
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::Sync, public
+//
+// Synopsis: Sync memory to global state.
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CSmAllocator::Sync(void)
+{
+ SCODE sc = S_OK;
+#if !defined(_CHICAGO_)
+#if !defined(MULTIHEAP)
+ if (!_smb.IsSynced())
+ {
+ CLockDfMutex lckdmtx(_dmtx);
+
+ sc = _smb.Sync();
+ _cbSize = _smb.GetSize();
+ }
+#else
+ if (!_psmb->IsSynced())
+ {
+ sc = _psmb->Sync();
+ }
+ _cbSize = _psmb->GetSize();
+#endif
+
+#endif
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::IncrementLuid, public
+//
+// Synopsis: Increments the global LUID
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+// History: 06-Apr-95 HenryLee Created
+//----------------------------------------------------------------------------
+
+inline DFLUID CSmAllocator::IncrementLuid(void)
+{
+#if !defined(MULTIHEAP)
+ CLockDfMutex lckdmx(_dmtx);
+#endif
+
+#ifdef _CHICAGO_
+ //
+ // On Chicago, we merely increment the globally available
+ // LUID to the next value.
+ //
+ return ++gs_dfluid;
+#else
+ return GetHeader()->IncrementLuid();
+#endif
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::GetBase, public
+//
+// Synopsis: Return pointer to base of heap
+//
+// History: 29-Mar-94 PhilipLa Created
+// 05-Feb-95 KentCe Use Win95 Shared Heap.
+//
+//----------------------------------------------------------------------------
+
+inline void * CSmAllocator::GetBase(void)
+{
+#if defined(_CHICAGO_)
+ return NULL;
+#else
+ return _pbBase;
+#endif
+}
+
+#if !defined(MULTIHEAP)
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::GetMutex, public
+//
+// Synopsis: Return a pointer to the Mutex
+//
+// History: 19-Jul-95 SusiA Created
+//
+//----------------------------------------------------------------------------
+
+inline CDfMutex * CSmAllocator::GetMutex(void)
+{
+ return &_dmtx;
+}
+#endif
+
+//
+// Take advantage of Windows 95 Shared Heap.
+//
+#if !defined(_CHICAGO_)
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::GetAddress, private
+//
+// Synopsis: Returns an address given an offset from the base
+//
+// Arguments: [ulOffset] -- Offset to convert to address
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CBlockHeader * CSmAllocator::GetAddress(ULONG ulOffset) const
+{
+ return (ulOffset == 0) ? NULL : (CBlockHeader *)(_pbBase + ulOffset);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::GetOffset
+//
+// Synopsis: Returns a byte offset from the base given a pointer
+//
+// Arguments: [pbh] -- Pointer to convert to offset
+//
+// History: 29-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CSmAllocator::GetOffset(CBlockHeader *pbh) const
+{
+ memAssert((BYTE *)pbh >= _pbBase && (BYTE*)pbh < _pbBase + _cbSize);
+ return (ULONG)pbh - (ULONG)_pbBase;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSmAllocator::GetHeader, private
+//
+// Synopsis: Return pointer to CHeapHeader for this heap
+//
+// History: 30-Mar-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CHeapHeader * CSmAllocator::GetHeader(void)
+{
+ return (CHeapHeader *)_pbBase;
+}
+
+#ifdef MULTIHEAP
+//+-------------------------------------------------------------------------
+//
+// Member: CSmAllocator::HeapName, public
+//
+// Synopsis: Return the luid part of the shared heap name
+//
+// History: 30-Nov-95 HenryLee Created
+//
+//--------------------------------------------------------------------------
+inline const ULONG CSmAllocator::GetHeapName()
+{
+ return _ulHeapName;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::ResetAllocedBlocks, public
+//
+// Synopsis: Reset the allocated block counter
+//
+// History: 04-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CHeapHeader::ResetAllocedBlocks(void)
+{
+ _ulAllocedBlocks = 0;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::IncrementAllocedBlocks, public
+//
+// Synopsis: Increment the allocated block count
+//
+// History: 04-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CHeapHeader::IncrementAllocedBlocks(void)
+{
+ return ++_ulAllocedBlocks;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::DecrementAllocedBlocks, public
+//
+// Synopsis: Decrement the allocated block count
+//
+// History: 04-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CHeapHeader::DecrementAllocedBlocks(void)
+{
+ return --_ulAllocedBlocks;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CHeapHeader::GetAllocedBlocks, public
+//
+// Synopsis: Return the allocated block count
+//
+// History: 04-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CHeapHeader::GetAllocedBlocks(void)
+{
+ return _ulAllocedBlocks;
+}
+
+#endif // !defined(_CHICAGO_)
+
+#endif // #ifndef __HEAP_HXX__
+
diff --git a/private/ole32/stg/h/sngprop.hxx b/private/ole32/stg/h/sngprop.hxx
new file mode 100644
index 000000000..d51065737
--- /dev/null
+++ b/private/ole32/stg/h/sngprop.hxx
@@ -0,0 +1,73 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: sngprop.hxx
+//
+// Contents: CSingleProp definition
+//
+// Classes: CSingleProp
+//
+// History: 12-Oct-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __SNGPROP_HXX__
+#define __SNGPROP_HXX__
+
+#include <dfmsp.hxx>
+
+class CPubDocFile;
+class CPubStream;
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSingleProp (sp)
+//
+// Purpose: Defines an interface for operating on a single property
+//
+// Interface: See below
+//
+// History: 13-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class CSingleProp
+{
+public:
+ inline void Init(CPubDocFile *pstg);
+
+ SCODE Get(CDfName *pdfn,
+ DFPROPVAL *pdpv,
+ ULONG *pcbSize,
+ BYTE **ppbBuffer);
+ SCODE Set(CDfName *pdfn,
+ DFPROPVAL *pdpv,
+ ULONG const cbSize,
+ BYTE *pbBuffer);
+ SCODE Exists(CDfName *pdfn);
+
+private:
+ CPubDocFile *_pstg;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSingleProp::Init, public
+//
+// Synopsis: Initializes
+//
+// Arguments: [pstg] - Storage to use
+//
+// History: 14-Oct-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CSingleProp::Init(CPubDocFile *pstg)
+{
+ _pstg = pstg;
+}
+
+#endif
+
diff --git a/private/ole32/stg/h/sstream.hxx b/private/ole32/stg/h/sstream.hxx
new file mode 100644
index 000000000..bc582d27b
--- /dev/null
+++ b/private/ole32/stg/h/sstream.hxx
@@ -0,0 +1,249 @@
+//+-------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: stream.hxx
+//
+// Contents: Stream header for mstream project
+//
+// Classes: CSStream - single linear stream for MSF
+//
+// History: 18-Jul-91 Philipla Created.
+//
+//--------------------------------------------------------------------
+
+
+
+#ifndef __STREAM_HXX__
+#define __STREAM_HXX__
+
+#include <msf.hxx>
+#include <handle.hxx>
+#include <tset.hxx>
+#include <psstream.hxx>
+#include <dfbasis.hxx>
+#include <cache.hxx>
+#include <dl.hxx>
+
+
+
+//+----------------------------------------------------------------------
+//
+// Class: CDirectStream (ds)
+//
+// Purpose: Direct stream class
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//-----------------------------------------------------------------------
+
+class CDirectStream: public PSStream, public CMallocBased
+{
+
+public:
+ inline void *operator new(size_t size, IMalloc * const pMalloc);
+ inline void *operator new(size_t size, CDFBasis * const pdfb);
+ inline void ReturnToReserve(CDFBasis * const pdfb);
+
+ inline static SCODE Reserve(UINT cItems, CDFBasis * const pdfb);
+ inline static void Unreserve(UINT cItems, CDFBasis * const pdfb);
+
+ CDirectStream(DFLUID dl);
+ ~CDirectStream(void);
+
+ void InitSystem(CMStream *pms,
+ SID sid,
+ ULONG cbSize);
+ SCODE Init(CStgHandle *pstgh,
+ CDfName const *pdfn,
+ BOOL const fCreate);
+
+ virtual void AddRef(VOID);
+
+ inline void DecRef(VOID);
+
+ virtual void Release(VOID);
+
+ virtual SCODE BeginCommitFromChild(
+ ULONG ulSize,
+ CDeltaList *pDelta,
+ CTransactedStream *pstChild);
+
+ virtual void EndCommitFromChild(DFLAGS df,
+ CTransactedStream *pstChild);
+
+ virtual CDeltaList * GetDeltaList(void);
+
+ virtual SCODE ReadAt(
+ ULONG ulOffset,
+ VOID HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval);
+
+ virtual SCODE WriteAt(
+ ULONG ulOffset,
+ VOID const HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval);
+
+ virtual SCODE SetSize(ULONG ulNewSize);
+
+ virtual void GetSize(ULONG *pulSize);
+
+ // PBasicEntry
+
+ inline CStmHandle *GetHandle(void);
+
+private:
+#ifdef SECURE_STREAMS
+ void ClearSects(ULONG ulStartOffset, ULONG ulEndOffset);
+
+ ULONG _ulHighWater;
+#endif
+
+ CStmHandle _stmh;
+ CStreamCache _stmc;
+ ULONG _ulSize;
+ ULONG _ulOldSize;
+
+ LONG _cReferences;
+
+ CBasedDeltaListPtr _pdlHolder;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CDirectStream::operator new, public
+//
+// Synopsis: Unreserved object allocator
+//
+// Arguments: [size] -- byte count to allocate
+// [pMalloc] -- allocator
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void *CDirectStream::operator new(size_t size, IMalloc * const pMalloc)
+{
+ return(CMallocBased::operator new(size, pMalloc));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDirectStream::operator new, public
+//
+// Synopsis: Reserved object allocator
+//
+// Arguments: [size] -- byte count to allocate
+// [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void *CDirectStream::operator new(size_t size, CDFBasis * const pdfb)
+{
+ olAssert(size == sizeof(CDirectStream));
+
+ return pdfb->GetFreeList(CDFB_DIRECTSTREAM)->GetReserved();
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDirectStream::ReturnToReserve, public
+//
+// Synopsis: Reserved object return
+//
+// Arguments: [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectStream_ReturnToReserve)
+#endif
+
+inline void CDirectStream::ReturnToReserve(CDFBasis * const pdfb)
+{
+ CDirectStream::~CDirectStream();
+ pdfb->GetFreeList(CDFB_DIRECTSTREAM)->ReturnToReserve(this);
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+--------------------------------------------------------------
+//
+// Member: CDirectStream::Reserve, public
+//
+// Synopsis: Reserve instances
+//
+// Arguments: [cItems] -- count of items
+// [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CDirectStream::Reserve(UINT cItems, CDFBasis * const pdfb)
+{
+ return pdfb->Reserve(cItems, CDFB_DIRECTSTREAM);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDirectStream::Unreserve, public
+//
+// Synopsis: Unreserve instances
+//
+// Arguments: [cItems] -- count of items
+// [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void CDirectStream::Unreserve(UINT cItems, CDFBasis * const pdfb)
+{
+ pdfb->Unreserve(cItems, CDFB_DIRECTSTREAM);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirectStream::GetHandle, public
+//
+// Synopsis: Returns a pointer to the stream handle
+//
+// History: 25-Jun-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline CStmHandle *CDirectStream::GetHandle(void)
+{
+ return &_stmh;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirectStream::DecRef, public
+//
+// Synopsis: Decrements the ref count
+//
+// History: 25-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CDirectStream::DecRef(void)
+{
+ AtomicDec(&_cReferences);
+}
+
+#endif //__SSTREAM_HXX__
+
+
diff --git a/private/ole32/stg/h/stgprops.hxx b/private/ole32/stg/h/stgprops.hxx
new file mode 100644
index 000000000..6928edd04
--- /dev/null
+++ b/private/ole32/stg/h/stgprops.hxx
@@ -0,0 +1,48 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: stgprops.hxx
+//
+// Contents: Declaration for IPrivateStorage
+//
+// Classes:
+//
+// Functions:
+//
+// History: 07-May-95 BillMo Created.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __STGPROPS_HXX__
+#define __STGPROPS_HXX__
+
+//+-------------------------------------------------------------------------
+//
+// Class: IPrivateStorage
+//
+// Purpose: Polymorphic but private calls on objects that implement
+// IStorage.
+//
+// Interface: GetStorage -- get the IStorage for the object
+//
+//
+//
+//
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+class IPrivateStorage
+{
+public:
+
+ STDMETHOD_(IStorage *, GetStorage) (VOID) PURE;
+ STDMETHOD(Lock) (DWORD dwTimeout) PURE;
+ STDMETHOD_(VOID, Unlock) (VOID) PURE;
+};
+
+#endif
diff --git a/private/ole32/stg/h/stgstm.hxx b/private/ole32/stg/h/stgstm.hxx
new file mode 100644
index 000000000..8bd2aadcf
--- /dev/null
+++ b/private/ole32/stg/h/stgstm.hxx
@@ -0,0 +1,112 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: stgstm.hxx
+//
+// Contents: Common header file for debug and global definitions
+//
+// History: 29-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __STGSTM_HXX__
+#define __STGSTM_HXX__
+
+#define CONTENTS_STREAM L"CONTENTS"
+
+#define aMsg(s) ((char *)(s) != NULL)
+#define ssResult(sc) ((HRESULT)(sc))
+
+#if !defined(ErrJmp)
+#if DBG == 1
+
+
+#define ErrJmp(comp, label, errval, var) \
+{\
+ var = errval;\
+ comp##DebugOut((DEB_IERROR, "Error %lX at %s:%d\n",\
+ (unsigned long)var, __FILE__, __LINE__));\
+ goto label;\
+}
+
+#else
+
+#define ErrJmp(comp, label, errval, var) \
+{\
+ var = errval;\
+ goto label;\
+}
+
+#endif
+#endif
+
+#define ssErr(l, e) ErrJmp(ss, l, e, sc)
+#define ssChkTo(l, e) if (FAILED(sc = (e))) ssErr(l, sc) else 1
+#define ssHChkTo(l, e) if (FAILED(sc = GetScode(e))) ssErr(l, sc) else 1
+#define ssChk(e) ssChkTo(EH_Err, e)
+#define ssHChk(e) ssHChkTo(EH_Err, e)
+#define ssMemTo(l, e) \
+ if ((e) == NULL) ssErr(l, STG_E_INSUFFICIENTMEMORY) else 1
+#define ssMem(e) ssMemTo(EH_Err, e)
+
+#if DBG == 1
+DECLARE_DEBUG(ss);
+#endif
+
+#if DBG == 1
+
+#define ssDebugOut(args) ssInlineDebugOut args
+
+#define ssAssert(e) Win4Assert(e)
+#define ssAssSucc(e) Win4Assert(SUCCEEDED(e))
+#define ssHAssSucc(e) Win4Assert(SUCCEEDED(e))
+
+#define ssVerify(e) Win4Assert(e)
+#define ssVerSucc(e) Win4Assert(SUCCEEDED(e))
+#define ssHVerSucc(e) Win4Assert(SUCCEEDED(e))
+
+#else
+
+#define ssDebugOut(args)
+
+#define ssAssert(e)
+#define ssAssSucc(e)
+#define ssHAssSucc(e)
+
+#define ssVerify(e) (e)
+#define ssVerSucc(e) (e)
+#define ssHVerSucc(e) (e)
+
+#endif
+
+// Generic flags for various routines
+enum CREATEOPEN
+{
+ CO_CREATE,
+ CO_OPEN
+};
+
+enum FILEDIR
+{
+ FD_STORAGE = 0, // STGFMT_DOCUMENT
+ FD_DIR = 1, // STGFMT_DIRECTORY
+ FD_CATALOG = 2, // STGFMT_CATALOG
+ FD_FILE = 3, // STGFMT_FILE
+ FD_DEFAULT = 4, // STGFMT_ANY
+ FD_DOCFILE, // STGFMT_DOCFILE
+ FD_OFSSTORAGE, // STGFMT_STORAGE
+ FD_JUNCTION = 7, // STGFMT_JUNCTION
+ FD_STREAM // STGTY_STREAM (in concept)
+};
+
+// BUGBUG - Remove when available
+STDAPI CoMemAlloc(DWORD cb, void **ppv);
+inline HRESULT CoMemFree(void *pv)
+{
+ CoTaskMemFree ( pv );
+ return S_OK;
+};
+
+#endif // #ifndef __STGSTM_HXX__
diff --git a/private/ole32/stg/h/stgutil.hxx b/private/ole32/stg/h/stgutil.hxx
new file mode 100644
index 000000000..3175246d3
--- /dev/null
+++ b/private/ole32/stg/h/stgutil.hxx
@@ -0,0 +1,123 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: stgutil.hxx
+//
+// Contents: Generic storage utilities
+//
+// History: 18-Aug-93 DrewB Created
+// 20-Mar-95 HenryLee added GetDriveLetter, SetDriveLetter
+//
+//----------------------------------------------------------------------------
+
+#ifndef __STGUTIL_HXX__
+#define __STGUTIL_HXX__
+
+SCODE DetermineStgType(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD *pdwStgFmt,
+ HANDLE *ph);
+SCODE DetermineHandleStgType(HANDLE h,
+ FILEDIR fd,
+ DWORD *pdwStgFmt);
+SCODE CheckFsAndOpenAnyStorage(HANDLE hParent,
+ WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ BOOL fRoot,
+ IStorage **ppstg);
+SCODE GenericMoveElement(IStorage *pstgFrom,
+ WCHAR const *pwcsName,
+ IStorage *pstgTo,
+ WCHAR const *pwcsNewName,
+ DWORD grfFlags);
+WCHAR *FindExt(WCHAR const *pwcsPath);
+
+// Generic storage openers, one for OFS and one for non-OFS
+STDAPI OfsCreateStorageType(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE h,
+ DWORD grfMode,
+ DWORD dwStgFmt,
+ LPSECURITY_ATTRIBUTES pssSecurity,
+ BOOL fRoot,
+ IStorage **ppstg);
+STDAPI OfsOpenAnyStorage(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE *ph,
+ DWORD dwStgFmt,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ BOOL fRoot,
+ IStorage **ppstg);
+STDAPI CreateStorageType(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE *ph,
+ DWORD grfMode,
+ DWORD dwStgFmt,
+ LPSECURITY_ATTRIBUTES pssSecurity,
+ IStorage **ppstg);
+STDAPI OpenAnyStorage(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE *ph,
+ DWORD dwStgFmt,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ IStorage **ppstg);
+
+SCODE DestroyTree(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE h,
+ FILEDIR fd);
+SCODE RenameChild(HANDLE hParent,
+ WCHAR const *pwcsName,
+ WCHAR const *pwcsNewName);
+
+SCODE InitDirectory (HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE h,
+ CREATEOPEN co,
+ STGOPEN *pStgOpen,
+ STGCREATE *pStgCreate,
+ SCODE scOfs,
+ REFIID riid,
+ void **ppObjectOpen);
+
+SCODE InitStorage (HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE h,
+ CREATEOPEN co,
+ STGOPEN *pStgOpen,
+ STGCREATE *pStgCreate,
+ WCHAR const wcDrive,
+ SCODE *pscOfs,
+ BOOL fRestricted,
+ REFIID riid,
+ void **ppObjectOpen);
+
+WCHAR GetDriveLetter (WCHAR const *pwcsName);
+
+SCODE SetDriveLetter (WCHAR *pwcsName, WCHAR const wcDrive);
+
+STDAPI OfsDocCreateStorage(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE h,
+ DWORD grfMode,
+ LPSECURITY_ATTRIBUTES pssSecurity,
+ BOOL fRoot,
+ IStorage **ppstg);
+
+STDAPI GetHandleServerInfo(
+ IN HANDLE hFile,
+ IN OUT LPWSTR lpServerName,
+ IN OUT LPDWORD lpcbServerName,
+ IN OUT LPWSTR lpReplSpecificPath,
+ IN OUT LPDWORD lpcbReplSpecificPath);
+
+#endif // #ifndef __STGUTIL_HXX__
diff --git a/private/ole32/stg/h/storagep.h b/private/ole32/stg/h/storagep.h
new file mode 100644
index 000000000..30416e7da
--- /dev/null
+++ b/private/ole32/stg/h/storagep.h
@@ -0,0 +1,31 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: storagep.h
+//
+// Contents: Internal storage information
+//
+// History: 09-Oct-92 DrewB Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __STORAGEP_H__
+#define __STORAGEP_H__
+
+// The byte combination that identifies that a file is a storage of
+// some kind
+
+const BYTE SIGSTG[] = {0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1};
+const BYTE CBSIGSTG = sizeof(SIGSTG);
+
+// The first portion of a storage file
+struct SStorageFile
+{
+ BYTE abSig[CBSIGSTG]; // Signature
+ CLSID _clid; // Class Id
+};
+
+#endif
+
diff --git a/private/ole32/stg/h/tlsets.hxx b/private/ole32/stg/h/tlsets.hxx
new file mode 100644
index 000000000..114e1448e
--- /dev/null
+++ b/private/ole32/stg/h/tlsets.hxx
@@ -0,0 +1,145 @@
+#ifndef REF
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: tlsets.hxx
+//
+// Contents: Transaction level set manager header file
+//
+// History: 20-Jan-1992 PhilipL Created
+//
+//---------------------------------------------------------------
+
+#ifndef __TLSETS_HXX__
+#define __TLSETS_HXX__
+
+#include <dfmsp.hxx>
+#include <tset.hxx>
+
+//+--------------------------------------------------------------
+//
+// Class: CTSSet (tss)
+//
+// Purpose: Maintains a list of transaction set elements
+//
+// Interface: See below
+//
+// History: 08-Apr-92 DrewB Created
+//
+// Notes:
+// All elements are kept grouped by level, with level increasing
+// from head to tail
+//
+// If an element of the list is removed, it can not be passed as
+// a value to GetNext. If an element is to be deleted, get next
+// should be called before the RemoveMember call.
+//
+//---------------------------------------------------------------
+
+#define CHILDLEVEL 1
+
+class CTSSet
+{
+public:
+ inline CTSSet(void);
+ ~CTSSet(void);
+
+ inline PTSetMember *GetHead(void);
+ PTSetMember *FindName(CDfName const *pdfn, DFLUID dlTree);
+ inline void RenameMember(CDfName const *pdfnOld,
+ DFLUID dlTree,
+ CDfName const *pdfnNew);
+
+ void AddMember(PTSetMember *ptsm);
+ void RemoveMember(PTSetMember *ptsm);
+
+private:
+ CBasedTSetMemberPtr _ptsmHead;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CTSSet::CTSSet, public
+//
+// Synopsis: Ctor
+//
+// History: 26-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CTSSet::CTSSet(void)
+{
+ _ptsmHead = NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTSSet::GetHead, public
+//
+// Synopsis: Returns _ptsmHead
+//
+// History: 26-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline PTSetMember *CTSSet::GetHead(void)
+{
+ return BP_TO_P(PTSetMember *, _ptsmHead);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTSSet::RenameMember, public
+//
+// Synopsis: Rename old name to new name
+//
+// Arguments: [pdfnOld] - old name
+// [dlTree] - tree for uniqueness
+// [pdnfNew] - new name
+//
+// Returns: Matching element or NULL
+//
+// History: 22-Jan-1992 Philipl Created
+// 08-Apr-1992 DrewB Rewritten
+// 28-Oct-1992 AlexT Convert to name
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTSSet_RenameMember)
+#endif
+
+inline void CTSSet::RenameMember(
+ CDfName const *pdfnOld,
+ DFLUID dlTree,
+ CDfName const *pdfnNew)
+{
+ PTSetMember *ptsm;
+
+ olDebugOut((DEB_ITRACE, "In CTSSet::RenameMember(%p, %p)\n",
+ pdfnOld, pdfnNew));
+ olAssert(pdfnOld != NULL && pdfnNew != NULL &&
+ aMsg("Rename names can't be NULL"));
+
+ for (ptsm = BP_TO_P(PTSetMember *, _ptsmHead);
+ ptsm;
+ ptsm = ptsm->GetNext())
+ {
+ if (ptsm->GetDfName()->IsEqual(pdfnOld) && dlTree == ptsm->GetTree())
+ {
+ ptsm->GetDfName()->Set(pdfnNew->GetLength(),
+ pdfnNew->GetBuffer());
+ break;
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out CTSSet::RenameMember\n"));
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+#endif // #ifndef __TLSETS_HXX__
+#endif //!REF
diff --git a/private/ole32/stg/h/tset.hxx b/private/ole32/stg/h/tset.hxx
new file mode 100644
index 000000000..b1aa69dba
--- /dev/null
+++ b/private/ole32/stg/h/tset.hxx
@@ -0,0 +1,225 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: tset.hxx
+//
+// Contents: Transaction set definitions
+//
+// Classes: PTSetMember
+//
+// History: 12-Dec-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __TSET_HXX__
+#define __TSET_HXX__
+
+#include <dfmsp.hxx>
+#include <ole.hxx>
+#include <dblink.hxx>
+
+//+--------------------------------------------------------------
+//
+// Class: PTSetMember (tsm)
+//
+// Purpose: Transaction set member object
+//
+// Interface: See below
+//
+// History: 07-Nov-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+class PTSetMember : public CDlElement
+{
+public:
+ virtual void AddRef(void) = 0;
+ virtual void Release(void) = 0;
+
+ virtual SCODE BeginCommit(DWORD const dwFlags) = 0;
+ virtual void EndCommit(DFLAGS const df) = 0;
+ virtual void Revert(void) = 0;
+
+ virtual void GetCommitInfo(ULONG *pulRet1, ULONG *pulRet2) = 0;
+
+ inline DWORD ObjectType(void) const;
+ inline void SetXsInfo(DFLUID dlTree, DFLUID dlName, ULONG ulLevel);
+ inline DFLUID GetTree(void);
+ inline DFLUID GetName(void);
+ inline ULONG GetLevel(void);
+ inline ULONG GetFlags(void);
+ inline void SetFlags(ULONG ulFlags);
+ inline CDfName *GetDfName(void);
+
+ SCODE Stat(STATSTGW *pstat, DWORD dwFlags);
+
+ // CDlElement support
+ DECLARE_DBLINK(PTSetMember)
+
+protected:
+ inline PTSetMember(CDfName const *pdfn, DWORD dwType);
+
+private:
+ const DWORD _dwType; // STGTY_*
+ ULONG _ulFlags;
+ DFLUID _dlTree, _dlName;
+ ULONG _ulLevel;
+ CDfName _dfnName;
+};
+SAFE_DFBASED_PTR(CBasedTSetMemberPtr, PTSetMember);
+
+//+-------------------------------------------------------------------------
+//
+// Member: PTSetMember::PTSetMember
+//
+// Synopsis: constructor
+//
+// Arguments: [dwType] - A STGTY flag
+//
+// History: 25-Jun-92 AlexT Created
+// 27-Jul-92 DrewB Changed to use STGTY
+//
+//--------------------------------------------------------------------------
+
+inline PTSetMember::PTSetMember(CDfName const *pdfn, DWORD dwType)
+: _dwType(dwType)
+{
+ olAssert(pdfn != NULL && aMsg("PTSetMember name cannot be NULL"));
+ _dfnName.Set(pdfn->GetLength(), pdfn->GetBuffer());
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: PTSetMember::ObjectType
+//
+// Synopsis: Returns type of PTSetMember this is
+//
+// Returns: Appropriate STGTY flag
+//
+// History: 25-Jun-92 AlexT Created
+// 27-Jul-92 DrewB Changed to use STGTY
+//
+//--------------------------------------------------------------------------
+
+inline DWORD PTSetMember::ObjectType(void) const
+{
+ return _dwType;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PTSetMember::SetXsInfo, public
+//
+// Synopsis: Sets the XS member info
+//
+// Arguments: [dlTree] - LUID of containing tree
+// [dlName] - LUID of self
+// [ulLevel] - Tree depth
+//
+// History: 27-Jul-1992 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void PTSetMember::SetXsInfo(DFLUID dlTree,
+ DFLUID dlName,
+ ULONG ulLevel)
+{
+ _dlTree = dlTree;
+ _dlName = dlName;
+ _ulLevel = ulLevel;
+ _ulFlags = 0;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PTSetMember::GetTree, public
+//
+// Synopsis: Returns _dlTree
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline DFLUID PTSetMember::GetTree(void)
+{
+ return _dlTree;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PTSetMember::GetName, public
+//
+// Synopsis: Returns _dlName
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline DFLUID PTSetMember::GetName(void)
+{
+ return _dlName;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PTSetMember::GetDfName, public
+//
+// Synopsis: Returns _dfnName
+//
+// History: 28-Oct-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline CDfName *PTSetMember::GetDfName(void)
+{
+ return &_dfnName;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PTSetMember::GetLevel, public
+//
+// Synopsis: Returns _ulLevel
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline ULONG PTSetMember::GetLevel(void)
+{
+ return _ulLevel;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PTSetMember::GetFlags, public
+//
+// Synopsis: Returns _ulFlags
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline ULONG PTSetMember::GetFlags(void)
+{
+ return _ulFlags;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PTSetMember::SetFlags, public
+//
+// Synopsis: Sets _ulFlags
+//
+// History: 08-Apr-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void PTSetMember::SetFlags(ULONG ulFlags)
+{
+ _ulFlags = ulFlags;
+}
+
+#endif
diff --git a/private/ole32/stg/h/tstream.hxx b/private/ole32/stg/h/tstream.hxx
new file mode 100644
index 000000000..5074dd877
--- /dev/null
+++ b/private/ole32/stg/h/tstream.hxx
@@ -0,0 +1,310 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: tstream.hxx
+//
+// Contents: Transacted stream class definition
+//
+// Classes: CTransactedStream - Transacted stream object
+// CDeltaList - Delta list object
+//
+// History: 23-Jan-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __TSTREAM_HXX__
+#define __TSTREAM_HXX__
+
+#include <msf.hxx>
+#include <tset.hxx>
+#include <psstream.hxx>
+#include <dfbasis.hxx>
+#include <freelist.hxx>
+#include <dl.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTransactedStream (ts)
+//
+// Purpose: Transacted stream object
+//
+// Interface:
+//
+// History: 21-Jan-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTransactedStream : public PSStream, public PTSetMember,
+ public CMallocBased
+{
+
+public:
+ inline void *operator new(size_t size, IMalloc * const pMalloc);
+ inline void *operator new(size_t size, CDFBasis * const pdfb);
+ inline void ReturnToReserve(CDFBasis * const pdfb);
+
+ inline static SCODE Reserve(UINT cItems, CDFBasis * const pdfb);
+ inline static void Unreserve(UINT cItems, CDFBasis * const pdfb);
+
+ CTransactedStream(CDfName const *pdfn,
+ DFLUID dl,
+ DFLAGS df,
+#ifdef USE_NOSCRATCH
+ CMStream *pms,
+#endif
+ CMStream *pmsScratch);
+ SCODE Init(PSStream *pssBase);
+
+ ~CTransactedStream();
+
+ virtual void AddRef(VOID);
+
+ inline void DecRef(VOID);
+
+ virtual void Release(VOID);
+
+ virtual SCODE ReadAt(
+ ULONG ulOffset,
+ VOID HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval);
+
+ virtual SCODE WriteAt(
+ ULONG ulOffset,
+ VOID const HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval);
+
+ virtual SCODE SetSize(ULONG ulNewSize);
+
+ virtual void GetSize(ULONG *pulSize);
+
+ virtual SCODE BeginCommitFromChild(
+ ULONG ulSize,
+ CDeltaList *pDelta,
+ CTransactedStream *pstChild);
+
+ virtual void EndCommitFromChild(DFLAGS df,
+ CTransactedStream *pstChild);
+
+ virtual CDeltaList * GetDeltaList(void);
+
+//Inherited from PTSetMember:
+ virtual SCODE BeginCommit(DWORD const dwFlags);
+ virtual void EndCommit(DFLAGS const df);
+
+ virtual void Revert(void);
+
+ virtual void GetCommitInfo(ULONG *pulRet1, ULONG *pulRet2);
+
+ // PBasicEntry
+ SCODE SetBase(PSStream *psst);
+ inline PSStream* GetBase();
+ inline void SetClean(void);
+ inline void SetDirty(UINT fDirty);
+ inline UINT GetDirty(void) const;
+
+private:
+
+ SCODE PartialWrite(
+ ULONG ulBasePos,
+ ULONG ulDirtyPos,
+ BYTE const HUGEP *pb,
+ USHORT offset,
+ USHORT uLen);
+ SCODE SetInitialState(PSStream *pssBase);
+
+
+ ULONG _ulSize;
+
+ CBasedSStreamPtr _pssBase;
+ SECT _sectLastUsed;
+ CDeltaList _dl;
+ DFLAGS _df;
+ UINT _fDirty;
+ BOOL _fBeginCommit;
+
+ LONG _cReferences;
+
+ CBasedDeltaListPtr _pdlOld;
+ ULONG _ulOldSize;
+
+#ifdef INDINST
+ DFSIGNATURE _sigOldBase;
+ DFSIGNATURE _sigOldSelf;
+#endif
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedStream::operator new, public
+//
+// Synopsis: Unreserved object allocator
+//
+// Arguments: [size] -- byte count to allocate
+// [pMalloc] -- allocator
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void *CTransactedStream::operator new(size_t size,
+ IMalloc * const pMalloc)
+{
+ return(CMallocBased::operator new(size, pMalloc));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedStream::operator new, public
+//
+// Synopsis: Reserved object allocator
+//
+// Arguments: [size] -- byte count to allocate
+// [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void *CTransactedStream::operator new(size_t size, CDFBasis * const pdfb)
+{
+ olAssert(size == sizeof(CTransactedStream));
+
+ return pdfb->GetFreeList(CDFB_TRANSACTEDSTREAM)->GetReserved();
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedStream::ReturnToReserve, public
+//
+// Synopsis: Reserved object return
+//
+// Arguments: [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void CTransactedStream::ReturnToReserve(CDFBasis * const pdfb)
+{
+ CTransactedStream::~CTransactedStream();
+ pdfb->GetFreeList(CDFB_TRANSACTEDSTREAM)->ReturnToReserve(this);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedStream::Reserve, public
+//
+// Synopsis: Reserve instances
+//
+// Arguments: [cItems] -- count of items
+// [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CTransactedStream::Reserve(UINT cItems, CDFBasis * const pdfb)
+{
+ return pdfb->Reserve(cItems, CDFB_TRANSACTEDSTREAM);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedStream::Unreserve, public
+//
+// Synopsis: Unreserve instances
+//
+// Arguments: [cItems] -- count of items
+// [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void CTransactedStream::Unreserve(UINT cItems, CDFBasis * const pdfb)
+{
+ pdfb->Unreserve(cItems, CDFB_TRANSACTEDSTREAM);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedStream::GetBase, public
+//
+// Synopsis: Returns base; used for debug checks
+//
+// History: 15-Sep-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline PSStream *CTransactedStream::GetBase()
+{
+ return BP_TO_P(PSStream *, _pssBase);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactedStream::SetClean, public
+//
+// Synopsis: Resets dirty flags
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CTransactedStream::SetClean(void)
+{
+ _fDirty = 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactedStream::SetDirty, public
+//
+// Synopsis: Sets dirty flags
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CTransactedStream::SetDirty(UINT fDirty)
+{
+ _fDirty |= fDirty;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactedStream::DecRef, public
+//
+// Synopsis: Decrements the ref count
+//
+// History: 25-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CTransactedStream::DecRef(void)
+{
+ AtomicDec(&_cReferences);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactedStream::GetDirty, public
+//
+// Synopsis: Returns the dirty flags
+//
+// History: 17-Dec-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline UINT CTransactedStream::GetDirty(void) const
+{
+ return _fDirty;
+}
+
+#endif //__TSTREAM_HXX__
diff --git a/private/ole32/stg/h/ulist.hxx b/private/ole32/stg/h/ulist.hxx
new file mode 100644
index 000000000..6bef66336
--- /dev/null
+++ b/private/ole32/stg/h/ulist.hxx
@@ -0,0 +1,492 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: ulist.hxx
+//
+// Contents: Update list definitions
+//
+// Classes: CUpdate
+// CUpdateList
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __ULIST_HXX__
+#define __ULIST_HXX__
+
+#include <dfmsp.hxx>
+#include <wchar.h>
+#include <tset.hxx>
+
+// Update list flags
+// STGTY_* are used for types
+#define ULF_TYPEFLAGS (STGTY_STORAGE | STGTY_STREAM)
+
+class CUpdate;
+SAFE_DFBASED_PTR(CBasedUpdatePtr, CUpdate);
+//+--------------------------------------------------------------
+//
+// Class: CUpdate (ud)
+//
+// Purpose: Tracks renames and deletions
+//
+// Interface: See below
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+class CUpdate : CMallocBased
+{
+public:
+ CUpdate(CDfName const *pdfnCurrentName,
+ CDfName const *pdfnOriginalName,
+ DFLUID dlLUID,
+ DWORD dwFlags,
+ PTSetMember *ptsm);
+ ~CUpdate(void);
+
+ inline CDfName *GetCurrentName(void);
+ inline CDfName *GetOriginalName(void);
+ inline DFLUID GetLUID(void) const;
+ inline DWORD GetFlags(void) const;
+ inline PTSetMember *GetXSM(void) const;
+ inline CUpdate *GetNext(void) const;
+ inline CUpdate *GetPrev(void) const;
+
+ inline BOOL IsDelete(void) const;
+ inline BOOL IsRename(void) const;
+ inline BOOL IsCreate(void) const;
+
+ inline void SetCurrentName(CDfName const *pdfn);
+ inline void SetOriginalName(CDfName const *pdfn);
+ inline void SetLUID(DFLUID dl);
+ inline void SetFlags(DWORD dwFlags);
+ inline void SetXSM(PTSetMember *ptsm);
+ inline void SetNext(CUpdate *pud);
+ inline void SetPrev(CUpdate *pud);
+
+private:
+ friend class CUpdateList;
+
+ CDfName _dfnCurrent;
+ CDfName _dfnOriginal;
+ DFLUID _dl;
+ DWORD _dwFlags;
+ CBasedTSetMemberPtr _ptsm;
+ CBasedUpdatePtr _pudNext, _pudPrev;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::GetCurrentName, public
+//
+// Synopsis: Returns the current name
+// Returns NULL for a zero length name
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CDfName *CUpdate::GetCurrentName(void)
+{
+ return &_dfnCurrent;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::GetOriginalName, public
+//
+// Synopsis: Returns the original name
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CDfName *CUpdate::GetOriginalName(void)
+{
+ return &_dfnOriginal;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::GetLUID, public
+//
+// Synopsis: Returns _dl
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline DFLUID CUpdate::GetLUID(void) const
+{
+ return _dl;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::GetFlags, public
+//
+// Synopsis: Returns _dwFlags
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline DWORD CUpdate::GetFlags(void) const
+{
+ return _dwFlags;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::GetXSM, public
+//
+// Synopsis: Returns the XSM
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline PTSetMember *CUpdate::GetXSM(void) const
+{
+ return BP_TO_P(PTSetMember *, _ptsm);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::GetNext, public
+//
+// Synopsis: Returns _pudNext
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CUpdate *CUpdate::GetNext(void) const
+{
+ return BP_TO_P(CUpdate *, _pudNext);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::GetPrev, public
+//
+// Synopsis: Returns _pudPrev
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CUpdate *CUpdate::GetPrev(void) const
+{
+ return BP_TO_P(CUpdate *, _pudPrev);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::IsDelete, public
+//
+// Synopsis: Returns whether this is a delete entry or not
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline BOOL CUpdate::IsDelete(void) const
+{
+ return _dfnCurrent.GetLength() == 0;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::IsRename, public
+//
+// Synopsis: Returns whether this is a rename or not
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline BOOL CUpdate::IsRename(void) const
+{
+ return _dfnCurrent.GetLength() != 0 && _dfnOriginal.GetLength() != 0;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::IsCreate, public
+//
+// Synopsis: Returns whether this is a create or not
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline BOOL CUpdate::IsCreate(void) const
+{
+ return _dfnOriginal.GetLength() == 0;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::SetCurrentName, public
+//
+// Synopsis: Sets the current name
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CUpdate::SetCurrentName(CDfName const *pdfn)
+{
+ if (pdfn)
+ _dfnCurrent = *pdfn;
+ else
+ _dfnCurrent.Set((WORD)0, (BYTE *)NULL);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::SetOriginalName, public
+//
+// Synopsis: Sets the original name
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CUpdate::SetOriginalName(CDfName const *pdfn)
+{
+ if (pdfn)
+ _dfnOriginal = *pdfn;
+ else
+ _dfnOriginal.Set((WORD)0, (BYTE *)NULL);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::SetLUID, public
+//
+// Synopsis: Assigns _dl
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CUpdate::SetLUID(DFLUID dl)
+{
+ _dl = dl;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::SetFlags, public
+//
+// Synopsis: Assigns _dwFlags
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CUpdate::SetFlags(DWORD dwFlags)
+{
+ _dwFlags = dwFlags;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::SetXSM, public
+//
+// Synopsis: Sets the XSM
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CUpdate::SetXSM(PTSetMember *ptsm)
+{
+ if (_ptsm)
+ _ptsm->Release();
+ _ptsm = P_TO_BP(CBasedTSetMemberPtr, ptsm);
+ if (_ptsm)
+ _ptsm->AddRef();
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::SetNext, public
+//
+// Synopsis: Assigns _pudNext
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CUpdate::SetNext(CUpdate *pud)
+{
+ _pudNext = P_TO_BP(CBasedUpdatePtr, pud);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdate::SetPrev, public
+//
+// Synopsis: Assigns _pudPrev
+//
+// History: 15-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CUpdate::SetPrev(CUpdate *pud)
+{
+ _pudPrev = P_TO_BP(CBasedUpdatePtr, pud);
+}
+
+// Return codes for IsEntry
+enum UlIsEntry
+{
+ UIE_CURRENT, UIE_ORIGINAL, UIE_NOTFOUND
+};
+
+//+--------------------------------------------------------------
+//
+// Class: CUpdateList (ul)
+//
+// Purpose: Maintains a list of update elements
+//
+// Interface: See below
+//
+// History: 22-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+class CUpdateList
+{
+public:
+ CUpdateList(void);
+ ~CUpdateList(void);
+
+ CUpdate *Add(IMalloc * const pMalloc,
+ CDfName const *pdfnCurrent,
+ CDfName const *pdfnOriginal,
+ DFLUID dlLUID,
+ DWORD dwFlags,
+ PTSetMember *ptsm);
+ void Append(CUpdate *pud);
+ void Remove(CUpdate *pud);
+ inline void Delete(CUpdate *pud);
+ void Empty(void);
+ inline void Unlink(void);
+
+ inline CUpdate *GetHead(void) const;
+ inline CUpdate *GetTail(void) const;
+
+ UlIsEntry IsEntry(CDfName const *pdfn, CUpdate **ppud);
+
+ static BOOL Exists(CUpdate *pud, CDfName const **ppdfn, BOOL fRename);
+ static CUpdate *FindBase(CUpdate *pud, CDfName const **ppdfn);
+
+private:
+ CBasedUpdatePtr _pudHead, _pudTail;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdateList::CUpdateList, public
+//
+// Synopsis: ctor
+//
+// History: 22-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CUpdateList::CUpdateList(void)
+{
+ _pudHead = _pudTail = NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdateList::~CUpdateList, public
+//
+// Synopsis: dtor
+//
+// History: 22-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline CUpdateList::~CUpdateList(void)
+{
+ olAssert(_pudHead == NULL && _pudTail == NULL);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdateList::GetHead, public
+//
+// Synopsis: Returns _pudHead
+//
+// History: 22-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CUpdate *CUpdateList::GetHead(void) const
+{
+ return BP_TO_P(CUpdate *, _pudHead);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdateList::GetTail, public
+//
+// Synopsis: Returns list tail
+//
+// History: 22-Jun-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CUpdate *CUpdateList::GetTail(void) const
+{
+ return BP_TO_P(CUpdate *, _pudTail);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdateList::Unlink, public
+//
+// Synopsis: Unlinks the list
+//
+// History: 04-Aug-92 DrewB Created
+//
+// Notes: Used for ownership transfer
+//
+//---------------------------------------------------------------
+
+inline void CUpdateList::Unlink(void)
+{
+ _pudHead = _pudTail = NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CUpdateList::Delete, public
+//
+// Synopsis: Removes the given entry from the list and frees it
+//
+// Arguments: [pud] - Element to remove
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline void CUpdateList::Delete(CUpdate *pud)
+{
+ Remove(pud);
+ delete pud;
+}
+
+#endif
diff --git a/private/ole32/stg/h/vect.hxx b/private/ole32/stg/h/vect.hxx
new file mode 100644
index 000000000..a37536d44
--- /dev/null
+++ b/private/ole32/stg/h/vect.hxx
@@ -0,0 +1,156 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: vect.hxx
+//
+// Contents: Vector common types
+//
+// Classes: CVectBits -- Bit fields for vectors
+//
+// History: 06-Aug-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __VECT_HXX__
+#define __VECT_HXX__
+
+#include <page.hxx>
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CVectBits (vb)
+//
+// Purpose: Structure for Vector flags.
+//
+// Interface:
+//
+// History: 06-Aug-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+struct CVectBits
+{
+ USHORT full:1;
+ USHORT firstfree;
+};
+SAFE_DFBASED_PTR(CBasedVectBitsPtr, CVectBits);
+
+//+-------------------------------------------------------------------------
+//
+// Class: CPagedVector (pv)
+//
+// Purpose: *Finish This*
+//
+// Interface:
+//
+// History: 27-Sep-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CPagedVector
+{
+public:
+ inline VECT_CLASS CPagedVector(const SID sid);
+
+ SCODE VECT_CLASS Init(CMStream *pms, ULONG ulSize);
+#ifndef REF
+ void VECT_CLASS InitCopy(CPagedVector *pvectOld);
+#endif //!REF
+
+ VECT_CLASS ~CPagedVector();
+
+ void Empty(void);
+
+
+ SCODE VECT_CLASS Resize(ULONG ulSize);
+
+ SCODE Flush(void);
+
+ SCODE GetTableWithSect(
+ const ULONG iTable,
+ DWORD dwFlags,
+ SECT sectKnown,
+ void **ppmp);
+
+ inline SCODE GetTable(const ULONG iTable, DWORD dwFlags, void **ppmp);
+ inline void ReleaseTable(const ULONG iTable);
+
+ inline void SetSect(const ULONG iTable, const SECT sect);
+
+ inline CVectBits * GetBits(const ULONG iTable);
+
+ inline void ResetBits(void);
+
+ SCODE SetDirty(ULONG iTable);
+ inline void ResetDirty(ULONG iTable);
+
+ inline void FreeTable(ULONG iTable);
+
+ inline CMStream * GetParent(void) const;
+ inline void SetParent(CMStream *pms);
+
+private:
+
+ inline CVectBits * GetNewVectBits(ULONG ulSize);
+ inline CBasedMSFPagePtr * GetNewPageArray(ULONG ulSize);
+
+ CBasedMSFPageTablePtr _pmpt;
+ const SID _sid;
+
+ ULONG _ulSize; // Amount in use
+ ULONG _ulAllocSize; // Amount allocated
+
+ CBasedMStreamPtr _pmsParent;
+
+ CBasedMSFPagePtrPtr _amp;
+ CBasedVectBitsPtr _avb;
+};
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPagedVector_CPagedVector)
+#endif
+
+inline VECT_CLASS CPagedVector::CPagedVector(const SID sid)
+: _sid(sid),
+ _pmpt(NULL),
+ _amp(NULL),
+ _avb(NULL),
+ _pmsParent(NULL)
+{
+ _ulSize = 0;
+ _ulAllocSize = 0;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::GetTable, public
+//
+// Synopsis: Inline function - calls through to GetTableWithSect,
+// passing a sect that indicates we don't know the
+// location of the page.
+//
+// History: 28-Jun-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CPagedVector::GetTable(
+ const ULONG iTable,
+ DWORD dwFlags,
+ void **ppmp)
+{
+ return GetTableWithSect(iTable, dwFlags, ENDOFCHAIN, ppmp);
+}
+
+#endif //__VECT_HXX__
diff --git a/private/ole32/stg/h/vectfunc.hxx b/private/ole32/stg/h/vectfunc.hxx
new file mode 100644
index 000000000..6e826a1f7
--- /dev/null
+++ b/private/ole32/stg/h/vectfunc.hxx
@@ -0,0 +1,265 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: vectfunc.hxx
+//
+// Contents: CPagedVector inline functions
+//
+// Classes:
+//
+// Functions:
+//
+// History: 28-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __VECTFUNC_HXX__
+#define __VECTFUNC_HXX__
+
+#define STG_S_FOUND MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_STORAGE, 0x400)
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPagedVector::ReleaseTable, public
+//
+// Synopsis: Release a table that is no longer needed.
+//
+// Arguments: [iTable] -- index into vector
+//
+// Returns: S_OK if call completed OK.
+//
+// History: 27-Oct-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline void VECT_CLASS CPagedVector::ReleaseTable(const FSINDEX iTable)
+{
+ if ((_amp == NULL) || (_amp[iTable] == NULL))
+ {
+ _pmpt->ReleasePage(this, _sid, iTable);
+ }
+ else
+ {
+ _amp[iTable]->Release();
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPagedVector::GetBits, public
+//
+// Synopsis: Return CVectBits for a given table
+//
+// Arguments: [iTable] -- Index of table to get bits for
+//
+// Returns: Pointer to CVectBits associated with table
+//
+// History: 27-Oct-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+inline CVectBits * CPagedVector::GetBits(const ULONG iTable)
+{
+ msfAssert(iTable < _ulSize);
+
+ if (_avb == NULL)
+ return NULL;
+ else
+ return (&_avb[iTable]);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::ResetDirty, public
+//
+// Synopsis: Reset the dirty bit on the specified page
+//
+// Arguments: [iTable] -- Table to reset bit on
+//
+// History: 28-Oct-92 PhilipLa Created
+//
+// Notes: This function is always called on a page with an
+// open reference. Therefore, the page is
+// guaranteed to be in the page table, and that
+// FindPage call should never return an error.
+//
+//----------------------------------------------------------------------------
+
+inline void CPagedVector::ResetDirty(ULONG iTable)
+{
+ SCODE sc;
+ if (_amp == NULL)
+ {
+ CMSFPage *pmp;
+
+ msfChk(_pmpt->FindPage(this, _sid, iTable, &pmp));
+ msfAssert(sc == STG_S_FOUND);
+ msfAssert(pmp->IsInUse() &&
+ aMsg("Called ResetDirty on page not in use."));
+ pmp->ResetDirty();
+ }
+ else
+ {
+ msfAssert(_amp != NULL);
+ msfAssert(_amp[iTable] != NULL);
+
+ _amp[iTable]->ResetDirty();
+ }
+ Err:
+ return;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::SetSect, public
+//
+// Synopsis: Set the sector location of a page
+//
+// Arguments: [iTable] -- Table to set page for
+// [sect] -- Sector location of page
+//
+// History: 02-Nov-92 PhilipLa Created
+//
+// Notes: This function is always called on a page with an
+// open reference. Therefore, the page is
+// guaranteed to be in the page table, and that
+// FindPage call should never return an error.
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPagedVector_SetSect)
+#endif
+
+inline void CPagedVector::SetSect(const ULONG iTable, const SECT sect)
+{
+ SCODE sc;
+ if (_amp == NULL)
+ {
+ CMSFPage *pmp;
+
+ msfChk(_pmpt->FindPage(this, _sid, iTable, &pmp));
+ msfAssert(sc == STG_S_FOUND);
+ msfAssert(pmp->IsInUse() &&
+ aMsg("Called SetSect on page not in use."));
+#ifdef SORTPAGETABLE
+ _pmpt->SetSect(pmp, sect);
+#else
+ pmp->SetSect(sect);
+#endif
+ }
+ else
+ {
+ msfAssert(_amp != NULL);
+ msfAssert(_amp[iTable] != NULL);
+
+#ifdef SORTPAGETABLE
+ _pmpt->SetSect(BP_TO_P(CMSFPage *, _amp[iTable]), sect);
+#else
+ _amp[iTable]->SetSect(sect);
+#endif
+ }
+Err:
+ return;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::FreeTable, public
+//
+// Synopsis: Free a given table (NULL its pointer)
+//
+// Arguments: [iTable] -- Table to free
+//
+// History: 04-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CPagedVector::FreeTable(ULONG iTable)
+{
+ if ((_amp != NULL) && (_amp[iTable] != NULL))
+ {
+ msfAssert(_amp[iTable]->GetVector() == this);
+ _amp[iTable] = NULL;
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::SetParent, public
+//
+// Synopsis: Set the parent of this page table
+//
+// Arguments: [pms] -- Pointer to new parent
+//
+// History: 05-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline void CPagedVector::SetParent(CMStream *pms)
+{
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pms);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::GetParent, public
+//
+// Synopsis: Return the parent MS pointer of a vector
+//
+// History: 05-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CMStream * CPagedVector::GetParent(void) const
+{
+ return BP_TO_P(CMStream *, _pmsParent);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::ResetBits, public
+//
+// Synopsis: Reset all the optimization bits in the vector
+//
+// History: 08-Feb-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPagedVector_ResetBits)
+#endif
+
+void CPagedVector::ResetBits(void)
+{
+ if (_avb != NULL)
+ {
+ for (ULONG i = 0; i < _ulSize; i++)
+ {
+ _avb[i].full = FALSE;
+ _avb[i].firstfree = 0;
+ }
+ }
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+#endif // #ifndef __VECTFUNC_HXX__
diff --git a/private/ole32/stg/h/w4wchar.h b/private/ole32/stg/h/w4wchar.h
new file mode 100644
index 000000000..a43abb731
--- /dev/null
+++ b/private/ole32/stg/h/w4wchar.h
@@ -0,0 +1,71 @@
+//+---------------------------------------------------------------------------
+//
+// File: WChar.h
+//
+// Contents: Defines wide character equivalents for standard functions
+// usually in strings.h and ctypes.h
+//
+// History: 11-Sep-91 KyleP Created
+// 20-Sep-91 ChrisMay Added several functions
+// 25-Sep-91 ChrisMay Added wcsncmp and wcsncpy
+// 04-Oct-91 ChrisMay Added wcslwr, wcsupr, wcscoll
+// 07-Oct-91 ChrisMay Added BOM and padding macro
+// 18-Oct-91 vich added w4*sprintf routines
+// 04-Mar-92 ChrisMay added wscatoi, wcsitoa, wcsatol, etc.
+//----------------------------------------------------------------------------
+
+#ifndef __WCHAR_H__
+#define __WCHAR_H__
+
+#include <stdlib.h>
+
+#if WIN32 != 300
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Unicode Byte Order Mark (BOM) for Unicode text files
+#define BOM 0xFEFF
+
+// Padding constant and macro for localized buffer allocation
+#define INTL_PADDING_VALUE 3
+#define INTL_PADDING(cb) (INTL_PADDING_VALUE * (cb))
+
+
+#if 0
+long _CRTAPI1 wcsatol(const wchar_t *wsz);
+int _CRTAPI1 wcsatoi(const wchar_t *wsz);
+wchar_t * _CRTAPI1 wcscat(wchar_t *wsz1, const wchar_t *wsz2);
+wchar_t * _CRTAPI1 wcschr(const wchar_t *wsz1, wchar_t character);
+int _CRTAPI1 wcscmp(const wchar_t *wsz1, const wchar_t *wsz2);
+int _CRTAPI1 wcsicmp(const wchar_t *wsz1, const wchar_t *wsz2);
+int _CRTAPI1 wcscoll(const wchar_t * wsz1, const wchar_t * wsz2);
+wchar_t * _CRTAPI1 wcscpy(wchar_t *wsz1, wchar_t const *wsz2);
+wchar_t * _CRTAPI1 wcsitoa(int ival, wchar_t *wsz, int radix);
+size_t _CRTAPI1 wcslen(wchar_t const *wsz);
+wchar_t * _CRTAPI1 wcsltoa(long lval, wchar_t *wsz, int radix);
+wchar_t * _CRTAPI1 wcslwr(wchar_t *wsz);
+int _CRTAPI1 wcsncmp(const wchar_t *wsz1, const wchar_t *wsz2, size_t count);
+int _CRTAPI1 wcsnicmp(const wchar_t *wsz1, const wchar_t *wsz2, size_t count);
+wchar_t * _CRTAPI1 wcsncpy(wchar_t *wsz1, const wchar_t *wsz2, size_t count);
+wchar_t * _CRTAPI1 wcsrchr(const wchar_t * wcs, wchar_t wc);
+wchar_t * _CRTAPI1 wcsupr(wchar_t *wsz);
+wchar_t * _CRTAPI1 wcswcs(const wchar_t *wsz1, const wchar_t *wsz2);
+#endif
+
+// sprintf support now included in misc.lib
+
+extern int _CRTAPI1 w4sprintf(char *pszout, const char *pszfmt, ...);
+extern int _CRTAPI1 w4vsprintf(char *pszout, const char *pszfmt, va_list arglist);
+extern int _CRTAPI1 w4wcsprintf(wchar_t *pwzout, const char *pszfmt, ...);
+extern int _CRTAPI1 w4vwcsprintf(wchar_t *pwzout, const char *pszfmt, va_list arglist);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !Cairo
+
+#endif /* __WCHAR_H__ */
diff --git a/private/ole32/stg/h/wdocfile.hxx b/private/ole32/stg/h/wdocfile.hxx
new file mode 100644
index 000000000..ee9851a4a
--- /dev/null
+++ b/private/ole32/stg/h/wdocfile.hxx
@@ -0,0 +1,491 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: wdocfile.hxx
+//
+// Contents: CWrappedDocFile class header
+//
+// Classes: CWrappedDocFile
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifndef __WDOCFILE_HXX__
+#define __WDOCFILE_HXX__
+
+#include <dfmsp.hxx>
+#include <dfbasis.hxx>
+#include <pdocfile.hxx>
+#include <ulist.hxx>
+#include <entry.hxx>
+#include <tset.hxx>
+#include <freelist.hxx>
+#include <tstream.hxx>
+
+class PDocFileIterator;
+class CPubDocFile;
+class CDFBasis;
+
+//+--------------------------------------------------------------
+//
+// Class: CWrappedDocFile
+//
+// Purpose: Wrapped DocFile object for transactioning
+//
+// Interface: See below
+//
+// History: 06-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+class CWrappedDocFile : public PDocFile, public PTSetMember,
+ public CMallocBased
+{
+public:
+ inline void *operator new(size_t size, IMalloc * const pMalloc);
+ inline void *operator new(size_t size,
+ CDFBasis * const pdfb);
+ inline void ReturnToReserve(CDFBasis * const pdfb);
+
+ inline static SCODE Reserve(UINT cItems, CDFBasis * const pdfb);
+ inline static void Unreserve(UINT cItems, CDFBasis * const pdfb);
+
+ CWrappedDocFile(CDfName const *pdfn,
+ DFLUID dl,
+ DFLAGS const df,
+ CDFBasis *pdfb,
+ CPubDocFile *ppubdf);
+ SCODE Init(PDocFile *pdfBase);
+#ifdef COORD
+ SCODE InitPub(CPubDocFile *ppubdf);
+#endif
+
+ ~CWrappedDocFile(void);
+
+ // PDocFile
+ virtual void AddRef(void);
+ inline void DecRef(void);
+ virtual void Release(void);
+
+ virtual SCODE DestroyEntry(CDfName const *dfnName,
+ BOOL fClean);
+ virtual SCODE RenameEntry(CDfName const *dfnName,
+ CDfName const *dfnNewName);
+
+ virtual SCODE GetClass(CLSID *pclsid);
+ virtual SCODE SetClass(REFCLSID clsid);
+ virtual SCODE GetStateBits(DWORD *pgrfStateBits);
+ virtual SCODE SetStateBits(DWORD grfStateBits, DWORD grfMask);
+
+ virtual SCODE CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ PDocFile **ppdfDocFile);
+ inline SCODE CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ DWORD const dwType,
+ PDocFile **ppdfDocFile)
+ { return CreateDocFile(pdfnName, df, luidSet, ppdfDocFile); }
+
+ virtual SCODE GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ PDocFile **ppdfDocFile);
+
+ inline SCODE GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DWORD const dwType,
+ PDocFile **ppdfDocFile)
+ { return GetDocFile(pdfnName, df, ppdfDocFile); }
+
+ inline void ReturnDocFile(CWrappedDocFile *pdf);
+
+ virtual SCODE CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ PSStream **ppsstStream);
+
+ inline SCODE CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ DWORD const dwType,
+ PSStream **ppsstStream)
+ { return CreateStream(pdfnName, df, luidSet, ppsstStream); }
+
+ virtual SCODE GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ PSStream **ppsstStream);
+
+ inline SCODE GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DWORD const dwType,
+ PSStream **ppsstStream)
+ { return GetStream(pdfnName, df, ppsstStream); }
+
+ inline void ReturnStream(CTransactedStream *pstm);
+
+ virtual SCODE FindGreaterEntry(CDfName const *pdfnKey,
+ SIterBuffer *pib,
+ STATSTGW *pstat);
+ virtual SCODE StatEntry(CDfName const *pdfn,
+ SIterBuffer *pib,
+ STATSTGW *pstat);
+
+ virtual SCODE BeginCommitFromChild(CUpdateList &ulChanged,
+ DWORD const dwFlags,
+ CWrappedDocFile *pdfChild);
+ virtual void EndCommitFromChild(DFLAGS const df,
+ CWrappedDocFile *pdfChild);
+ virtual SCODE IsEntry(CDfName const *dfnName,
+ SEntryBuffer *peb);
+ virtual SCODE DeleteContents(void);
+
+ // PTSetMember
+ virtual SCODE BeginCommit(DWORD const dwFlags);
+ virtual void EndCommit(DFLAGS const df);
+ virtual void Revert(void);
+ virtual void GetCommitInfo(ULONG *pulRet1, ULONG *pulRet2);
+
+ // PTimeEntry
+ virtual SCODE GetTime(WHICHTIME wt, TIME_T *ptm);
+ virtual SCODE SetTime(WHICHTIME wt, TIME_T tm);
+ virtual SCODE GetAllTimes(TIME_T *patm, TIME_T *pmtm, TIME_T *pctm);
+
+ virtual SCODE SetAllTimes(TIME_T atm, TIME_T mtm, TIME_T ctm);
+
+ inline CWrappedDocFile *GetReservedDocfile(CDfName const *pdfn,
+ DFLUID dl,
+ DFLAGS const df,
+ CPubDocFile *ppubdf);
+ inline CTransactedStream *GetReservedStream(CDfName const *pdfn,
+ DFLUID dl,
+ DFLAGS df
+ );
+
+ // Internal
+ SCODE SetBase(PDocFile *pdf);
+ inline PDocFile *GetBase(void);
+ inline CFreeList *GetDocfileFreelist(void);
+ inline CFreeList *GetStreamFreelist(void);
+ inline void SetClean(void);
+ inline void SetDirty(UINT fDirty);
+ inline UINT GetDirty(void) const;
+ inline CUpdateList *GetUpdateList(void);
+
+private:
+ SCODE SetInitialState(PDocFile *pdfBase);
+ void RevertUpdate(CUpdate *pud);
+
+ DFLAGS _df; // Transactioning flags
+ CBasedDocFilePtr _pdfParent, _pdfBase;
+ CUpdateList _ulChanged;
+ CUpdateList _ulChangedHolder;
+ CUpdateList _ulChangedOld;
+ CTSSet _tssDeletedHolder;
+ BOOL _fBeginCommit;
+ LONG _cReferences;
+ CTransactedTimeEntry _tten;
+ CBasedPubDocFilePtr _ppubdf;
+ UINT _fDirty;
+ CLSID _clsid;
+ DWORD _grfStateBits;
+ CBasedDFBasisPtr const _pdfb;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::operator new, public
+//
+// Synopsis: Unreserved object allocator
+//
+// Arguments: [size] -- byte count to allocate
+// [pMalloc] -- allocator
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void *CWrappedDocFile::operator new(size_t size,
+ IMalloc * const pMalloc)
+{
+ return(CMallocBased::operator new(size, pMalloc));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::operator new, public
+//
+// Synopsis: Reserved object allocator
+//
+// Arguments: [size] -- byte count to allocate
+// [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void *CWrappedDocFile::operator new(size_t size, CDFBasis * const pdfb)
+{
+ olAssert(size == sizeof(CWrappedDocFile));
+
+ return pdfb->GetFreeList(CDFB_WRAPPEDDOCFILE)->GetReserved();
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::ReturnToReserve, public
+//
+// Synopsis: Reserved object return
+//
+// Arguments: [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void CWrappedDocFile::ReturnToReserve(CDFBasis * const pdfb)
+{
+ CWrappedDocFile::~CWrappedDocFile();
+ pdfb->GetFreeList(CDFB_WRAPPEDDOCFILE)->ReturnToReserve(this);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::Reserve, public
+//
+// Synopsis: Reserve instances
+//
+// Arguments: [cItems] -- count of items
+// [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CWrappedDocFile::Reserve(UINT cItems, CDFBasis * const pdfb)
+{
+ return pdfb->Reserve(cItems, CDFB_WRAPPEDDOCFILE);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::Unreserve, public
+//
+// Synopsis: Unreserve instances
+//
+// Arguments: [cItems] -- count of items
+// [pdfb] -- basis
+//
+// History: 25-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline void CWrappedDocFile::Unreserve(UINT cItems, CDFBasis * const pdfb)
+{
+ pdfb->Unreserve(cItems, CDFB_WRAPPEDDOCFILE);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CWrappedDocFile::GetBase, public
+//
+// Synopsis: Returns base; used for debug checks
+//
+// History: 15-Sep-92 AlexT Created
+//
+//---------------------------------------------------------------
+
+inline PDocFile *CWrappedDocFile::GetBase(void)
+{
+ return BP_TO_P(PDocFile *, _pdfBase);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::GetReservedDocfile, public
+//
+// Synopsis: Returns a previously reserved object
+//
+// History: 09-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline CWrappedDocFile *CWrappedDocFile::GetReservedDocfile(
+ CDfName const *pdfn,
+ DFLUID dl,
+ DFLAGS const df,
+ CPubDocFile *ppubdf)
+{
+ return new(_pdfb)
+ CWrappedDocFile(pdfn, dl, df,
+ _pdfb, ppubdf);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::GetReservedStream, public
+//
+// Synopsis: Returns a previously reserved object
+//
+// History: 09-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline CTransactedStream *CWrappedDocFile::GetReservedStream(
+ CDfName const *pdfn,
+ DFLUID dl,
+ DFLAGS df
+ )
+{
+ CDFBasis * pdfb = BP_TO_P(CDFBasis *, _pdfb);
+
+ return new(pdfb)
+ CTransactedStream(pdfn, dl, df,
+#ifdef USE_NOSCRATCH
+ pdfb->GetBaseMultiStream(),
+#endif
+ pdfb->GetScratch());
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::SetClean, public
+//
+// Synopsis: Resets dirty flags
+//
+// History: 10-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CWrappedDocFile::SetClean(void)
+{
+ _fDirty = 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::SetDirty, public
+//
+// Synopsis: Sets dirty flags
+//
+// History: 10-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CWrappedDocFile::SetDirty(UINT fDirty)
+{
+ _fDirty |= fDirty;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::GetDirty, public
+//
+// Synopsis: Returns the dirty flags
+//
+// History: 25-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline UINT CWrappedDocFile::GetDirty(void) const
+{
+ return _fDirty;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::DecRef, public
+//
+// Synopsis: Decrements the ref count
+//
+// History: 23-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline void CWrappedDocFile::DecRef(void)
+{
+ AtomicDec(&_cReferences);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::GetUpdateList, public
+//
+// Synopsis: Returns a pointer to the current update list
+//
+// History: 12-Apr-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+CUpdateList *CWrappedDocFile::GetUpdateList(void)
+{
+ return &_ulChanged;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::ReturnDocFile, public
+//
+// Synopsis: Removes a docfile from the XS and returns it to the freelist
+//
+// Arguments: [pdf] - Docfile
+//
+// History: 23-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_ReturnDocFile)
+#endif
+
+inline void CWrappedDocFile::ReturnDocFile(CWrappedDocFile *pdf)
+{
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::ReturnDocFile:%p(%p)\n",
+ this, pdf));
+ _ppubdf->RemoveXSMember(pdf);
+ // Force ref count to zero without freeing memory
+ pdf->DecRef();
+ pdf->ReturnToReserve(BP_TO_P(CDFBasis *, _pdfb));
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::ReturnDocFile\n"));
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CWrappedDocFile::ReturnStream, public
+//
+// Synopsis: Removes a stream from the XS and returns it to the freelist
+//
+// Arguments: [pstm] - Stream
+//
+// History: 23-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CWrappedDocFile_ReturnStream)
+#endif
+
+inline void CWrappedDocFile::ReturnStream(CTransactedStream *pstm)
+{
+ olDebugOut((DEB_ITRACE, "In CWrappedDocFile::ReturnStream:%p(%p)\n",
+ this, pstm));
+ _ppubdf->RemoveXSMember(pstm);
+ // Force ref count to zero without freeing memory
+ pstm->DecRef();
+ pstm->ReturnToReserve(BP_TO_P(CDFBasis *, _pdfb));
+ olDebugOut((DEB_ITRACE, "Out CWrappedDocFile::ReturnStream\n"));
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+
+#endif
diff --git a/private/ole32/stg/makefile b/private/ole32/stg/makefile
new file mode 100644
index 000000000..0083bb0f1
--- /dev/null
+++ b/private/ole32/stg/makefile
@@ -0,0 +1,90 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1994 **
+#********************************************************************
+
+!ifdef NTMAKEENV
+
+all:
+ echo $(BUILDMSG)
+
+clean: all
+
+!else
+
+default: all
+
+!if "$(PLATFORM)" == "i286"
+TARGET = storage.dll
+!else
+TARGET = storag32.dll
+!endif
+
+TARGET_DESCRIPTION = "OLE 2.0 Compound File Implementation"
+
+!if "$(OPSYS)" == "NT"
+# Cairo only
+RELEASE = 1
+!endif
+
+!include $(CAIROLE)\stg\setole2.mk
+
+# Properties, we need this set when we compile the def file
+!if "$(OPSYS)" == "NT"
+CFLAGS = $(CFLAGS) -DPROPS
+!endif
+
+!if "$(HOST)" != "DOS"
+SUBDIRS = \
+!if "$(OPSYS)" != "NT"
+!if "$(BUILDTYPE)" == "DEBUG"
+ common\
+!endif
+!if "$(PLATFORM)" == "i286"
+# wclib only needed for 16-bit builds
+ wclib\
+!endif
+!else
+ fsstg\
+ ofsstg\
+!endif
+ msf\
+ docfile\
+ exp
+!endif
+
+OBJFILES = \
+!if "$(BUILDTYPE)" != "DEBUG" && "$(PLATFORM)" == "i286"
+ $(OBJDIR)\segments.obj\
+!endif
+!if "$(OPSYS)" == "NT" # Cairo only
+ $(CAIROLE)\stg\fsstg\$(OBJDIR)\fsstg.lib\
+ $(CAIROLE)\stg\ofsstg\$(OBJDIR)\ofsstg.lib\
+!endif
+ $(CAIROLE)\stg\docfile\$(OBJDIR)\docfile.lib\
+ $(CAIROLE)\stg\exp\$(OBJDIR)\exp.lib\
+ $(CAIROLE)\stg\msf\$(OBJDIR)\msf.lib
+
+!if "$(PLATFORM)" == "i286"
+RCFILES = .\storage.rc
+!endif
+
+CINC = $(CINC) -I$(OLE2H)
+
+!include $(CAIROLE)\stg\dflibs.mk
+
+!ifdef OLETARGET
+DLLCOPY = $(OLETARGET)\$(ODL)$(TGTDIR)
+!endif
+
+COFFBASE = storage
+
+!if "$(OPSYS)" == "NT"
+DEFFILE = $(COMMON)\ilib\storag32.def
+!elseif "$(PLATFORM)" != "i286"
+DEFFILE = $(CAIROLE)\ilib\storag32.def
+!endif
+
+!include $(COMMON)\src\win40.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/stg/msf/cache.cxx b/private/ole32/stg/msf/cache.cxx
new file mode 100644
index 000000000..d0ba548e8
--- /dev/null
+++ b/private/ole32/stg/msf/cache.cxx
@@ -0,0 +1,897 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: cache.cxx
+//
+// Contents: Stream cache code
+//
+// Classes:
+//
+// Functions:
+//
+// History: 26-May-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+#pragma hdrstop
+
+#include <sstream.hxx>
+#include <cache.hxx>
+#include <mread.hxx>
+
+#if DBG == 1
+static ULONG csTotalWalked = 0;
+static ULONG csSeqWalked = 0;
+static ULONG csRealWalked = 0;
+static ULONG cTotalCalls = 0;
+#endif
+
+
+inline SECT CacheStart(SCacheEntry cache)
+{
+ return cache.sect;
+}
+
+inline SECT CacheEnd(SCacheEntry cache)
+{
+ return cache.sect + cache.ulRunLength - 1;
+}
+
+inline ULONG CacheLength(SCacheEntry cache)
+{
+ return cache.ulRunLength;
+}
+
+inline ULONG CacheStartOffset(SCacheEntry cache)
+{
+ return cache.ulOffset;
+}
+
+inline ULONG CacheEndOffset(SCacheEntry cache)
+{
+ return cache.ulOffset + cache.ulRunLength - 1;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStreamCache::CheckSegment, private
+//
+// Synopsis: Given a bunch of information, determine if there is
+// a cache hit on a given segment and set return variables
+// to represent best hit.
+//
+// Arguments: [ulOffset] -- Offset being sought.
+// [sce] -- Stream cache entry being checked
+// [pulCount] -- Pointer to count of best hit so far
+// [psectCache] -- Pointer to sect of best hit so far
+// [pulCacheOffset] -- Pointer to offset of best hit so far
+//
+// Returns: TRUE if this is the best hit, FALSE otherwise.
+//
+// History: 11-Jul-94 PhilipLa Created
+//
+// Notes: This function has mega side effects. Think of it as
+// a typesafe #define.
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CStreamCache::CheckSegment(ULONG ulOffset,
+ SCacheEntry sce,
+ ULONG *pulCount,
+ SECT *psectCache,
+ ULONG *pulCacheOffset)
+{
+ if (CacheStartOffset(sce) <= ulOffset)
+ {
+ //We have a potential cache hit. Check the runlength to
+ // get the best fit.
+ if (ulOffset <= CacheEndOffset(sce))
+ {
+ //Direct hit.
+ *pulCount = 0;
+ *pulCacheOffset = ulOffset;
+ *psectCache = CacheStart(sce) + (ulOffset - CacheStartOffset(sce));
+ }
+ else
+ {
+ if (*pulCount > ulOffset - CacheEndOffset(sce))
+ {
+ //The requested sector is past the end of the cached
+ // segment. Use the endpoint as the closest hit.
+ *pulCount = ulOffset - CacheEndOffset(sce);
+ *psectCache = CacheEnd(sce);
+ *pulCacheOffset = CacheEndOffset(sce);
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ msfAssert(*pulCacheOffset <= ulOffset);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+inline CDirectory * CStreamCache::GetDir(void)
+{
+ return _pmsParent->GetDir();
+}
+
+inline CFat * CStreamCache::GetFat(void)
+{
+ return _pmsParent->GetFat();
+}
+
+inline CFat * CStreamCache::GetMiniFat(void)
+{
+ return _pmsParent->GetMiniFat();
+}
+
+inline ULONG CStreamCache::GetSize(void)
+{
+ ULONG ulSize = 0;
+ if (_pds != NULL)
+ {
+ _pds->CDirectStream::GetSize(&ulSize);
+ }
+ else
+ {
+ _pmsParent->GetSize(_sid, &ulSize);
+ }
+
+ return ulSize;
+}
+
+inline SID CStreamCache::GetSid(void)
+{
+ return _sid;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStreamCache::SelectFat, private
+//
+// Synopsis: Returns the appropriate CFat object for the cache.
+// If we are a control structure, then the real fat is
+// always the right one. Otherwise (we are a real stream)
+// key off of size to determine whether the minifat or
+// the real fat is appropriate.
+//
+// Arguments: None.
+//
+// Returns: Appropriate CFat pointer
+//
+// History: 16-Jun-94 PhilipLa Created
+//----------------------------------------------------------------------------
+
+inline CFat * CStreamCache::SelectFat(void)
+{
+ return ((_pds == NULL) || (GetSize() >= MINISTREAMSIZE) ||
+ (GetSid() == SIDMINISTREAM)) ? GetFat() : GetMiniFat();
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStreamCache::CacheSegment, private
+//
+// Synopsis: Store a segment in the cache.
+//
+// Arguments: [pseg] -- Pointer to segment to store
+//
+// Returns: void
+//
+// History: 19-Oct-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+void CStreamCache::CacheSegment(SSegment *pseg)
+{
+ USHORT iCache;
+
+ if (_uNextCacheIndex >= CACHESIZE)
+ {
+ _uNextCacheIndex = 0;
+ }
+
+ iCache = _uNextCacheIndex;
+ _ase[iCache].ulOffset = SegStartOffset(*pseg);
+ _ase[iCache].ulRunLength = SegLength(*pseg);
+ _ase[iCache].sect = SegStart(*pseg);
+
+ _uNextCacheIndex++;
+
+ _uHighCacheIndex = max(_uHighCacheIndex, iCache + 1);
+
+ //_uCacheState can be used to determine if the cache has changed.
+ _uCacheState++;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStreamCache::GetStart, private
+//
+// Synopsis: Get start sector for this chain
+//
+// Arguments: [psectStart] -- Return location
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jun-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CStreamCache::GetStart(SECT *psectStart)
+{
+ SCODE sc = S_OK;
+
+ if (_pds != NULL)
+ {
+ //We're a normal stream, so get the start sect from the
+ // directory.
+ sc = GetDir()->GetStart(_sid, psectStart);
+ }
+ else
+ {
+ //We're a control stream, so get the start sect from the
+ // multistream.
+ *psectStart = _pmsParent->GetStart(_sid);
+ }
+
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStreamCache::CStreamCache, public
+//
+// Synopsis: CStreamCache constructor
+//
+// History: 14-Dec-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CStreamCache_CStreamCache)
+#endif
+
+CStreamCache::CStreamCache()
+{
+ _sid = NOSTREAM;
+ _pmsParent = NULL;
+ _pds = NULL;
+ _uHighCacheIndex = 0;
+ _uNextCacheIndex = 0;
+ _uCacheState = 0;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CStreamCache_1CStreamCache) // inline?
+#endif
+
+CStreamCache::~CStreamCache()
+{
+#if DBG == 1
+ msfDebugOut((DEB_ITRACE,
+ "Cache stats: Total = %lu Seq = %lu Real = %lu Calls = %lu\n",
+ csTotalWalked, csSeqWalked, csRealWalked, cTotalCalls));
+#endif
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CStreamCache_Init)
+#endif
+
+void CStreamCache::Init(CMStream *pmsParent, SID sid, CDirectStream *pds)
+{
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pmsParent);
+ _sid = sid;
+ _pds = P_TO_BP(CBasedDirectStreamPtr, pds);
+ Empty();
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CStreamCache_Empty)
+#endif
+
+void CStreamCache::Empty(void)
+{
+ for (USHORT uIndex = 0; uIndex < CACHESIZE; uIndex++)
+ {
+ _ase[uIndex].ulOffset = MAX_ULONG;
+ _ase[uIndex].sect = ENDOFCHAIN;
+ _ase[uIndex].ulRunLength = 0;
+ }
+
+ _uHighCacheIndex = 0;
+ _uNextCacheIndex = 0;
+ _uCacheState++;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStreamCache::GetSect, public
+//
+// Synopsis: Retrieve a SECT from the cache given an offset
+//
+// Arguments: [ulOffset] -- Offset to look up.
+// [psect] -- Location for return value
+//
+// Returns: Appropriate status code
+//
+// History: 26-May-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CStreamCache_GetSect)
+#endif
+
+SCODE CStreamCache::GetSect(ULONG ulOffset, SECT *psect)
+{
+ SCODE sc = S_OK;
+ CFat *pfat;
+ USHORT iCache = 0;
+ ULONG ulCount = MAX_ULONG;
+ SECT sectCache = ENDOFCHAIN;
+ ULONG ulCacheOffset = MAX_ULONG;
+
+ *psect = ENDOFCHAIN;
+
+ pfat = SelectFat();
+
+ for (USHORT iCacheLoop = 0; iCacheLoop < _uHighCacheIndex; iCacheLoop++)
+ {
+ if (CheckSegment(ulOffset,
+ _ase[iCacheLoop],
+ &ulCount,
+ &sectCache,
+ &ulCacheOffset))
+ {
+ //Cache hit.
+ }
+ }
+
+ //We now have the best hit from the cache. If it is exact, return
+ // now.
+ if (ulCount == 0)
+ {
+ *psect = sectCache;
+ return S_OK;
+ }
+
+ if (ulCacheOffset == MAX_ULONG)
+ {
+ //No cache hit.
+ msfChk(GetStart(&sectCache));
+ ulCacheOffset = 0;
+ }
+
+ //Otherwise, go to the fat and get the real thing.
+#if DBG == 1 && defined(CHECKLENGTH)
+ SECT sectStart;
+ ULONG ulLengthOld, ulLengthNew;
+ GetStart(&sectStart);
+ pfat->GetLength(sectStart, &ulLengthOld);
+#endif
+
+ SSegment segtab[CSEG + 1];
+ ULONG ulSegCount;
+
+ while (TRUE)
+ {
+ msfChk(pfat->Contig(
+ segtab,
+ FALSE,
+ sectCache,
+ ulOffset - ulCacheOffset + 1,
+ &ulSegCount));
+
+ if (ulSegCount <= CSEG)
+ {
+ //We're done.
+ break;
+ }
+
+ //We need to call Contig again. Update ulCacheOffset and
+ //sectCache to be the last sector in the current table.
+
+ ulCacheOffset = ulCacheOffset + SegEndOffset(segtab[CSEG - 1]);
+ sectCache = SegEnd(segtab[CSEG - 1]);
+ }
+
+ //Last segment is in segtab[ulSegCount - 1].
+
+ //ulSegOffset is the absolute offset within the stream of the first
+ //sector in the last segment.
+ ULONG ulSegOffset;
+ ulSegOffset = ulCacheOffset + SegStartOffset(segtab[ulSegCount - 1]);
+
+ msfAssert(ulSegOffset <= ulOffset);
+
+ msfAssert(ulOffset < ulSegOffset + SegLength(segtab[ulSegCount - 1]));
+
+ *psect = SegStart(segtab[ulSegCount - 1]) + (ulOffset - ulSegOffset);
+
+ //Now, stick the last segment into our cache. We need to update
+ // the ulOffset field to be the absolute offset (i.e. ulSegOffset)
+ // before calling CacheSegment().
+
+ segtab[ulSegCount - 1].ulOffset = ulSegOffset;
+ CacheSegment(&(segtab[ulSegCount - 1]));
+
+#if DBG == 1 && defined(CHECKLENGTH)
+ //Confirm that the chain hasn't grown.
+ pfat->GetLength(sectStart, &ulLengthNew);
+ msfAssert(ulLengthOld == ulLengthNew);
+
+ //Confirm that we're getting the right sector.
+ SECT sectCheck;
+
+ pfat->GetSect(sectStart, ulOffset, &sectCheck);
+
+ msfAssert(*psect == sectCheck);
+#endif
+
+ Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStreamCache::GetESect, public
+//
+// Synopsis: Retrieve a SECT from the cache given an offset, extending
+// the stream if necessary.
+//
+// Arguments: [ulOffset] -- Offset to look up.
+// [psect] -- Location for return value
+//
+// Returns: Appropriate status code
+//
+// History: 26-May-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CStreamCache_GetESect)
+#endif
+
+SCODE CStreamCache::GetESect(ULONG ulOffset, SECT *psect)
+{
+ SCODE sc = S_OK;
+ CFat *pfat;
+ USHORT iCache = 0;
+ ULONG ulCount = MAX_ULONG;
+ SECT sectCache = ENDOFCHAIN;
+ ULONG ulCacheOffset = MAX_ULONG;
+ USHORT uCacheHit = CACHESIZE + 1;
+
+ *psect = ENDOFCHAIN;
+
+ pfat = SelectFat();
+
+ for (USHORT iCacheLoop = 0; iCacheLoop < _uHighCacheIndex; iCacheLoop++)
+ {
+ if (CheckSegment(ulOffset,
+ _ase[iCacheLoop],
+ &ulCount,
+ &sectCache,
+ &ulCacheOffset))
+ {
+ uCacheHit = iCacheLoop;
+ //Cache hit.
+ }
+ }
+
+ //We now have the best hit from the cache. If it is exact, return
+ // now.
+ if (ulCount == 0)
+ {
+ *psect = sectCache;
+ return S_OK;
+ }
+
+ if (ulCacheOffset == MAX_ULONG)
+ {
+ //No cache hit.
+ msfChk(GetStart(&sectCache));
+ ulCacheOffset = 0;
+ }
+
+ //Otherwise, go to the fat and get the real thing.
+
+ SSegment segtab[CSEG + 1];
+ ULONG ulSegCount;
+
+ while (TRUE)
+ {
+ msfChk(pfat->Contig(
+ segtab,
+ TRUE,
+ sectCache,
+ ulOffset - ulCacheOffset + 1,
+ &ulSegCount));
+
+ if (ulSegCount <= CSEG)
+ {
+ //We're done.
+ break;
+ }
+
+ //We need to call Contig again. Update ulCacheOffset and
+ //sectCache to be the last sector in the current table.
+
+ ulCacheOffset = ulCacheOffset + SegEndOffset(segtab[CSEG - 1]);
+ sectCache = SegEnd(segtab[CSEG - 1]);
+ }
+
+ //Last segment is in segtab[ulSegCount - 1].
+
+ //ulSegOffset is the absolute offset within the stream of the first
+ //sector in the last segment.
+ ULONG ulSegOffset;
+ ulSegOffset = ulCacheOffset + SegStartOffset(segtab[ulSegCount - 1]);
+
+ msfAssert(ulSegOffset <= ulOffset);
+
+ msfAssert(ulOffset < ulSegOffset + SegLength(segtab[ulSegCount - 1]));
+
+ *psect = SegStart(segtab[ulSegCount - 1]) + (ulOffset - ulSegOffset);
+ segtab[ulSegCount - 1].ulOffset = ulSegOffset;
+
+ //If we grew the chain with this call, we may need to merge the
+ // new segment with the previous best-hit in our cache.
+ // Otherwise, we end up with excessive fragmentation.
+
+ if ((uCacheHit != CACHESIZE + 1) &&
+ (SegStart(segtab[ulSegCount - 1]) <= CacheEnd(_ase[uCacheHit]) + 1) &&
+ (SegStart(segtab[ulSegCount - 1]) > CacheStart(_ase[uCacheHit])) &&
+ (SegStartOffset(segtab[ulSegCount - 1]) <=
+ CacheEndOffset(_ase[uCacheHit]) + 1))
+ {
+ //We can merge the two.
+ _ase[uCacheHit].ulRunLength += (SegLength(segtab[ulSegCount - 1]) -
+ (CacheEnd(_ase[uCacheHit]) + 1 -
+ SegStart(segtab[ulSegCount - 1])));
+
+ _uCacheState++;
+ }
+ else
+ {
+ //Now, stick the last segment into our cache. We need to update
+ // the ulOffset field to be the absolute offset (i.e. ulSegOffset)
+ // before calling CacheSegment().
+ CacheSegment(&(segtab[ulSegCount - 1]));
+ }
+
+#if DBG == 1
+ //Confirm that we're getting the right sector.
+ SECT sectCheck;
+ SECT sectStart;
+
+ msfChk(GetStart(&sectStart));
+
+ pfat->GetESect(sectStart, ulOffset, &sectCheck);
+
+ msfAssert(*psect == sectCheck);
+#endif
+
+ Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStreamCache::EmptyRegion, public
+//
+// Synopsis: Invalidate cached values for a segment that has been
+// remapped
+//
+// Arguments: [oStart] -- Offset marking first remapped sector
+// [oEnd] -- Offset marking last remapped sector
+//
+// Returns: Appropriate status code
+//
+// History: 26-May-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CStreamCache_EmptyRegion)
+#endif
+
+SCODE CStreamCache::EmptyRegion(ULONG oStart, ULONG oEnd)
+{
+ for (USHORT i = 0; i < CACHESIZE; i ++)
+ {
+ ULONG ulStart = CacheStartOffset(_ase[i]);
+ ULONG ulEnd = CacheEndOffset(_ase[i]);
+
+ if ((ulStart <= oEnd) && (ulEnd >= oStart))
+ {
+ //There are 3 possible cases:
+ // 1) The cache entry is completely contained in the
+ // region being invalidated.
+ // 2) The front part of the cache entry is contained in
+ // the region being invalidated.
+ // 3) The tail part of the cache entry is contained in
+ // the region being validated.
+
+ if ((oStart <= ulStart) && (oEnd >= ulEnd))
+ {
+ //Invalidate the entire thing.
+ _ase[i].ulOffset = MAX_ULONG;
+ _ase[i].sect = ENDOFCHAIN;
+ _ase[i].ulRunLength = 0;
+ }
+ else if (oStart <= ulStart)
+ {
+#if DBG == 1
+ ULONG ulCacheStart = _ase[i].ulOffset;
+ SECT sectCache = _ase[i].sect;
+ ULONG ulCacheLength = _ase[i].ulRunLength;
+#endif
+ //Invalidate the front of the cache entry
+ ULONG ulInvalid;
+
+ ulInvalid = oEnd - ulStart + 1;
+
+ _ase[i].ulOffset += ulInvalid;
+
+ msfAssert(_ase[i].ulRunLength > ulInvalid);
+ _ase[i].sect += ulInvalid;
+
+ _ase[i].ulRunLength -= ulInvalid;
+#if DBG == 1
+ //Make sure our cache is still within the old valid range.
+ msfAssert((_ase[i].ulOffset >= ulCacheStart) &&
+ (_ase[i].ulOffset <=
+ ulCacheStart + ulCacheLength - 1));
+ msfAssert(_ase[i].ulRunLength <= ulCacheLength);
+ msfAssert(_ase[i].ulRunLength > 0);
+ msfAssert((_ase[i].sect >= sectCache) &&
+ (_ase[i].sect <= sectCache + ulCacheLength - 1));
+#endif
+ }
+ else
+ {
+#if DBG == 1
+ ULONG ulCacheStart = _ase[i].ulOffset;
+ SECT sectCache = _ase[i].sect;
+ ULONG ulCacheLength = _ase[i].ulRunLength;
+#endif
+ //Invalidate the tail of the cache entry
+ ULONG ulInvalid;
+ ulInvalid = ulEnd - oStart + 1;
+ msfAssert(_ase[i].ulRunLength > ulInvalid);
+ _ase[i].ulRunLength -= ulInvalid;
+#if DBG == 1
+ //Make sure our cache is still within the old valid range.
+ msfAssert((_ase[i].ulOffset >= ulCacheStart) &&
+ (_ase[i].ulOffset <=
+ ulCacheStart + ulCacheLength - 1));
+ msfAssert(_ase[i].ulRunLength <= ulCacheLength);
+ msfAssert(_ase[i].ulRunLength > 0);
+ msfAssert((_ase[i].sect >= sectCache) &&
+ (_ase[i].sect <= sectCache + ulCacheLength - 1));
+#endif
+ }
+ _uCacheState++;
+ }
+ }
+
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStreamCache::Contig, public
+//
+// Synopsis: Return a contig table from a given offset and runlength
+//
+// Arguments: [ulOffset] -- Offset to begin contiguity check at
+// [fWrite] -- TRUE if segment is to be written to.
+// [aseg] -- Pointer to SSegment array
+// [ulLength] -- Run length of sectors to return table for
+//
+// Returns: Appropriate status code
+//
+// History: 21-Apr-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CStreamCache::Contig(
+ ULONG ulOffset,
+ BOOL fWrite,
+ SSegment STACKBASED *aseg,
+ ULONG ulLength,
+ ULONG *pcSeg)
+{
+ SCODE sc;
+ msfDebugOut((DEB_ITRACE, "In CStreamCache::Contig:%p()\n", this));
+ SECT sect;
+ USHORT uCacheState;
+
+ CFat *pfat;
+
+ for (USHORT iCache = 0; iCache < _uHighCacheIndex; iCache++)
+ {
+ //Look for direct hit.
+ if ((ulOffset >= _ase[iCache].ulOffset) &&
+ (ulOffset < _ase[iCache].ulOffset + _ase[iCache].ulRunLength))
+ {
+ //Direct hit. Return this segment.
+ ULONG ulCacheOffset = ulOffset - _ase[iCache].ulOffset;
+
+ aseg[0].ulOffset = ulOffset;
+ aseg[0].sectStart = _ase[iCache].sect + ulCacheOffset;
+ aseg[0].cSect = _ase[iCache].ulRunLength - ulCacheOffset;
+ *pcSeg = 1;
+ return S_OK;
+ }
+ }
+
+ uCacheState = _uCacheState;
+ if (fWrite)
+ {
+ //This can grow the chain, so get the whole thing at once
+ // instead of one sector at a time. Chances are good that
+ // the second GetESect call will be fed from the cache, so
+ // this won't be too expensive in the common case.
+ //Ideally, we'd like to make this first call only when we
+ // know the stream is growing. There isn't a convenient
+ // way to detect that here, though.
+ msfChk(GetESect(ulOffset + ulLength - 1, &sect));
+ msfChk(GetESect(ulOffset, &sect));
+ }
+ else
+ {
+ msfChk(GetSect(ulOffset, &sect));
+ }
+
+ //The GetSect() or GetESect() call may have actually snagged the
+ // segment we need, so check the cache again. If _uCacheState
+ // changed in the duration of the call, we know that something
+ // new is in the cache, so we go look again.
+ if (uCacheState != _uCacheState)
+ {
+ for (USHORT iCache = 0; iCache < _uHighCacheIndex; iCache++)
+ {
+ //Look for direct hit.
+ if ((ulOffset >= _ase[iCache].ulOffset) &&
+ (ulOffset < _ase[iCache].ulOffset + _ase[iCache].ulRunLength))
+ {
+ //Direct hit. Return this segment.
+ ULONG ulCacheOffset = ulOffset - _ase[iCache].ulOffset;
+
+ aseg[0].ulOffset = ulOffset;
+ aseg[0].sectStart = _ase[iCache].sect + ulCacheOffset;
+ aseg[0].cSect = _ase[iCache].ulRunLength - ulCacheOffset;
+ *pcSeg = 1;
+ return S_OK;
+ }
+ }
+ }
+
+ pfat = SelectFat();
+ msfChk(pfat->Contig(aseg, fWrite, sect, ulLength, pcSeg));
+
+ //At this point, we can peek at the contig table and pick out
+ // the choice entries to put in the cache.
+
+ //For the first pass, we just grab the last thing in the Contig
+ //table and cache it.
+ aseg[*pcSeg - 1].ulOffset += ulOffset;
+ CacheSegment(&(aseg[*pcSeg - 1]));
+
+ Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStreamCache::Allocate, public
+//
+// Synopsis: Allocate a new chain for a stream, returning the start
+// sector and caching the appropriate amount of contig
+// information.
+//
+// Arguments: [pfat] -- Pointer to fat to allocate in
+// [cSect] -- Number of sectors to allocate
+// [psectStart] -- Returns starts sector for chain
+//
+// Returns: Appropriate status code
+//
+// History: 19-Oct-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CStreamCache::Allocate(CFat *pfat, ULONG cSect, SECT *psectStart)
+{
+ SCODE sc;
+
+ msfAssert((_uHighCacheIndex == 0) &&
+ aMsg("Called Allocate with non-empty buffer"));
+
+#ifndef CACHE_ALLOCATE_OPTIMIZATION
+ //This will allocate the complete requested chain. We'll then
+ // walk over that chain again in the Contig() call, which isn't
+ // optimal. Ideally, we'd like GetFree() to return us the
+ // contiguity information, but that's a fairly major change.
+ // Consider it for future optimization work.
+ msfChk(pfat->GetFree(cSect, psectStart, GF_WRITE));
+#else
+ //Get the first sector (to simplify Contig code)
+
+ //First reserve enough free sectors for the whole thing.
+ msfChk(pfat->ReserveSects(cSect));
+ msfChk(pfat->GetFree(1, psectStart, GF_WRITE));
+#endif
+
+ SSegment segtab[CSEG + 1];
+ ULONG ulSegCount;
+ ULONG ulSegStart;
+ SECT sectSegStart;
+
+ sectSegStart = *psectStart;
+ ulSegStart = 0;
+
+ while (TRUE)
+ {
+ msfChk(pfat->Contig(
+ segtab,
+ TRUE,
+ sectSegStart,
+ cSect - ulSegStart,
+ &ulSegCount));
+
+ if (ulSegCount <= CSEG)
+ {
+ //We're done.
+ break;
+ }
+
+ //We need to call Contig again. Update ulSegStart and
+ //sectSegStart to be the last sector in the current table.
+
+ ulSegStart = ulSegStart + SegEndOffset(segtab[CSEG - 1]);
+ sectSegStart = SegEnd(segtab[CSEG - 1]);
+ }
+
+ //Last segment is in segtab[ulSegCount - 1].
+
+ //ulSegOffset is the absolute offset within the stream of the first
+ //sector in the last segment.
+ ULONG ulSegOffset;
+ ulSegOffset = ulSegStart + SegStartOffset(segtab[ulSegCount - 1]);
+
+ //Now, stick the last segment into our cache. We need to update
+ // the ulOffset field to be the absolute offset (i.e. ulSegOffset)
+ // before calling CacheSegment().
+
+ segtab[ulSegCount - 1].ulOffset = ulSegOffset;
+ CacheSegment(&(segtab[ulSegCount - 1]));
+
+#if DBG == 1 && defined(CHECKLENGTH)
+ ULONG ulLength;
+
+ pfat->GetLength(*psectStart, &ulLength);
+ msfAssert(ulLength == cSect);
+#endif
+ Err:
+ return sc;
+}
diff --git a/private/ole32/stg/msf/daytona/makefile b/private/ole32/stg/msf/daytona/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ole32/stg/msf/daytona/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/stg/msf/daytona/sources b/private/ole32/stg/msf/daytona/sources
new file mode 100644
index 000000000..34d09a479
--- /dev/null
+++ b/private/ole32/stg/msf/daytona/sources
@@ -0,0 +1,95 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= msf
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES=..\..\..\ih;..\..\..\common\daytona;..\..\h;..;..\..\..\com\inc;..\..\props;..\..\..\..\inc
+
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+SOURCES= \
+ ..\cache.cxx\
+ ..\difat.cxx\
+ ..\dir.cxx\
+ ..\dirp.cxx\
+ ..\dl.cxx\
+ ..\fat.cxx\
+ ..\header.cxx\
+ ..\msf.cxx\
+ ..\msfnew.cxx\
+ ..\mstream.cxx\
+ ..\page.cxx\
+ ..\pbstream.cxx\
+ ..\sstream.cxx\
+ ..\tstream.cxx\
+ ..\vect.cxx\
+ ..\wep.cxx
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+PRECOMPILED_INCLUDE= ..\msfhead.cxx
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
diff --git a/private/ole32/stg/msf/depend.mk1 b/private/ole32/stg/msf/depend.mk1
new file mode 100644
index 000000000..91df666ce
--- /dev/null
+++ b/private/ole32/stg/msf/depend.mk1
@@ -0,0 +1,787 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\cache.obj $(OBJDIR)\cache.lst: .\cache.cxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\difat.obj $(OBJDIR)\difat.lst: .\difat.cxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\STG\msf\mread.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\prspec.h $(OLE2H)\stream.h $(OLE2H)\varnt.h \
+ $(OLE2H)\wtypes.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\rpc.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\dir.obj $(OBJDIR)\dir.lst: .\dir.cxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\mread.hxx $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\wtypes.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\dirp.obj $(OBJDIR)\dirp.lst: .\dirp.cxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\wtypes.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\dl.obj $(OBJDIR)\dl.lst: .\dl.cxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\mread.hxx $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\fat.obj $(OBJDIR)\fat.lst: .\fat.cxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\mread.hxx $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\header.obj $(OBJDIR)\header.lst: .\header.cxx \
+ $(CAIROLE)\stg\h\dfver.h $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\msf.obj $(OBJDIR)\msf.lst: .\msf.cxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\msfnew.obj $(OBJDIR)\msfnew.lst: .\msfnew.cxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\mstream.obj $(OBJDIR)\mstream.lst: .\mstream.cxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\mread.hxx $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\time.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\page.obj $(OBJDIR)\page.lst: .\page.cxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\mread.hxx $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\pbstream.obj $(OBJDIR)\pbstream.lst: .\pbstream.cxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\pbstream.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\sstream.obj $(OBJDIR)\sstream.lst: .\sstream.cxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\msf\mread.hxx \
+ $(CAIROLE)\STG\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\time.h $(OLE2H)\advsnk.h $(OLE2H)\baseole.h \
+ $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\efrmte.h \
+ $(OLE2H)\emonkr.h $(OLE2H)\estatd.h $(OLE2H)\estats.h \
+ $(OLE2H)\estrng.h $(OLE2H)\idltyps.h $(OLE2H)\itabls.h \
+ $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prsist.h \
+ $(OLE2H)\prspec.h $(OLE2H)\pstrm.h $(OLE2H)\querys.h $(OLE2H)\rot.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\storag.h $(OLE2H)\stream.h $(OLE2H)\unknwn.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ntstatus.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\tstream.obj $(OBJDIR)\tstream.lst: .\tstream.cxx \
+ $(CAIROLE)\stg\h\dfdeb.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\mread.hxx \
+ .\msfhead.cxx
+
+$(OBJDIR)\vect.obj $(OBJDIR)\vect.lst: .\vect.cxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\wep.obj $(OBJDIR)\wep.lst: .\wep.cxx $(CAIROLE)\stg\h\dfdeb.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\advsnk.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\bndctx.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\msfhead.pxh $(PCHDIR)\$(OBJDIR)\msfhead.lst: \
+ $(CAIROLE)\stg\msf\msfhead.cxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\advsnk.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\bndctx.h $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\efrmte.h $(OLE2H)\emonkr.h $(OLE2H)\estatd.h \
+ $(OLE2H)\estats.h $(OLE2H)\estrng.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\monikr.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h \
+ $(OLE2H)\prsist.h $(OLE2H)\prspec.h $(OLE2H)\pstrm.h \
+ $(OLE2H)\querys.h $(OLE2H)\rot.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\storag.h $(OLE2H)\stream.h \
+ $(OLE2H)\unknwn.h $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ntstatus.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+.\$(OBJDIR)\cache.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\difat.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\dir.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\dirp.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\dl.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\fat.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\header.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\msf.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\msfnew.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\mstream.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\page.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\pbstream.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\sstream.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\tstream.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\vect.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\wep.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/msf/depend.mk3 b/private/ole32/stg/msf/depend.mk3
new file mode 100644
index 000000000..e6bf19d37
--- /dev/null
+++ b/private/ole32/stg/msf/depend.mk3
@@ -0,0 +1,648 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\cache.obj $(OBJDIR)\cache.lst: .\cache.cxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\difat.obj $(OBJDIR)\difat.lst: .\difat.cxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\msf\mread.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\scode.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winmm.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\dir.obj $(OBJDIR)\dir.lst: .\dir.cxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\msf\mread.hxx $(CAIROLE)\stg\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\dirp.obj $(OBJDIR)\dirp.lst: .\dirp.cxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\dl.obj $(OBJDIR)\dl.lst: .\dl.cxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\msf\mread.hxx $(CAIROLE)\stg\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\fat.obj $(OBJDIR)\fat.lst: .\fat.cxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\msf\mread.hxx $(CAIROLE)\stg\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\header.obj $(OBJDIR)\header.lst: .\header.cxx \
+ $(CAIROLE)\stg\h\dfver.h $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\msf.obj $(OBJDIR)\msf.lst: .\msf.cxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\msfnew.obj $(OBJDIR)\msfnew.lst: .\msfnew.cxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\mstream.obj $(OBJDIR)\mstream.lst: .\mstream.cxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\msf\mread.hxx $(CAIROLE)\stg\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\time.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\page.obj $(OBJDIR)\page.lst: .\page.cxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\msf\mread.hxx $(CAIROLE)\stg\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\pbstream.obj $(OBJDIR)\pbstream.lst: .\pbstream.cxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\pbstream.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\sstream.obj $(OBJDIR)\sstream.lst: .\sstream.cxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\msf\mread.hxx \
+ $(CAIROLE)\stg\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(CRTINC)\time.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oleguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winmm.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\tstream.obj $(OBJDIR)\tstream.lst: .\tstream.cxx \
+ $(CAIROLE)\stg\h\dfdeb.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\mread.hxx \
+ .\msfhead.cxx
+
+$(OBJDIR)\vect.obj $(OBJDIR)\vect.lst: .\vect.cxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+$(OBJDIR)\wep.obj $(OBJDIR)\wep.lst: .\wep.cxx $(CAIROLE)\stg\h\dfdeb.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\stg\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\dvobj.h $(OLE2H)\initguid.h $(OLE2H)\moniker.h \
+ $(OLE2H)\ole2.h $(OLE2H)\oleguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msfhead.cxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\msfhead.pxh $(PCHDIR)\$(OBJDIR)\msfhead.lst: \
+ $(CAIROLE)\stg\msf\msfhead.cxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winmm.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h
+
+.\$(OBJDIR)\cache.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\difat.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\dir.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\dirp.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\dl.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\fat.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\header.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\msf.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\msfnew.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\mstream.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\page.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\pbstream.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\sstream.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\tstream.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\vect.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\wep.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/msf/depend.mk9 b/private/ole32/stg/msf/depend.mk9
new file mode 100644
index 000000000..d7130431c
--- /dev/null
+++ b/private/ole32/stg/msf/depend.mk9
@@ -0,0 +1,449 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\cache.obj $(OBJDIR)\cache.lst: .\cache.cxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\msfhead.cxx
+
+$(OBJDIR)\difat.obj $(OBJDIR)\difat.lst: .\difat.cxx \
+ $(CAIROLE)\STG\msf\mread.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\stdlib.h $(CRTINC)\assert.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OLE2H)\scode.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\msfhead.cxx
+
+$(OBJDIR)\dir.obj $(OBJDIR)\dir.lst: .\dir.cxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\mread.hxx $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\msfhead.cxx
+
+$(OBJDIR)\dirp.obj $(OBJDIR)\dirp.lst: .\dirp.cxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\msfhead.cxx
+
+$(OBJDIR)\dl.obj $(OBJDIR)\dl.lst: .\dl.cxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\mread.hxx $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\msfhead.cxx
+
+$(OBJDIR)\fat.obj $(OBJDIR)\fat.lst: .\fat.cxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\mread.hxx $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\msfhead.cxx
+
+$(OBJDIR)\header.obj $(OBJDIR)\header.lst: .\header.cxx \
+ $(CAIROLE)\stg\h\dfver.h $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\msfhead.cxx
+
+$(OBJDIR)\msf.obj $(OBJDIR)\msf.lst: .\msf.cxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\msfhead.cxx
+
+$(OBJDIR)\msfnew.obj $(OBJDIR)\msfnew.lst: .\msfnew.cxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\msfhead.cxx
+
+$(OBJDIR)\mstream.obj $(OBJDIR)\mstream.lst: .\mstream.cxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\mread.hxx $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\time.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\msfhead.cxx
+
+$(OBJDIR)\page.obj $(OBJDIR)\page.lst: .\page.cxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\mread.hxx $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\msfhead.cxx
+
+$(OBJDIR)\pbstream.obj $(OBJDIR)\pbstream.lst: .\pbstream.cxx \
+ $(CAIROLE)\stg\h\chinst.hxx $(CAIROLE)\stg\h\pbstream.hxx \
+ $(CAIROLE)\stg\h\pdocfile.hxx $(CAIROLE)\stg\h\publicdf.hxx \
+ $(CAIROLE)\stg\h\revert.hxx $(CAIROLE)\stg\h\tlsets.hxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h .\msfhead.cxx
+
+$(OBJDIR)\sstream.obj $(OBJDIR)\sstream.lst: .\sstream.cxx \
+ $(CAIROLE)\stg\h\cache.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\dblink.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\dirfunc.hxx \
+ $(CAIROLE)\stg\h\dl.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\handle.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\msffunc.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\psstream.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\sstream.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\tset.hxx $(CAIROLE)\stg\h\tstream.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\msf\mread.hxx \
+ $(CAIROLE)\STG\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\time.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\initguid.h $(OLE2H)\scode.h $(OLE2H)\storage.h \
+ $(OLE2H)\valid.h $(OSINC)\windows.h .\msfhead.cxx
+
+$(OBJDIR)\tstream.obj $(OBJDIR)\tstream.lst: .\tstream.cxx \
+ $(CAIROLE)\stg\h\dfdeb.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\tstream.hxx $(CAIROLE)\stg\h\cache.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\dblink.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\dl.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\handle.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\psstream.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\sstream.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\tset.hxx \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\mread.hxx \
+ .\msfhead.cxx
+
+$(OBJDIR)\vect.obj $(OBJDIR)\vect.lst: .\vect.cxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\dirfunc.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\msffunc.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\msfhead.cxx
+
+$(OBJDIR)\wep.obj $(OBJDIR)\wep.lst: .\wep.cxx $(CAIROLE)\stg\h\dfdeb.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\segh.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\vectfunc.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\msf\segmsf.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx $(COMMON)\ih\winnot.h \
+ $(CRTINC)\assert.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\msfhead.cxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\msfhead.pxh $(PCHDIR)\$(OBJDIR)\msfhead.lst: \
+ $(CAIROLE)\stg\msf\msfhead.cxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\segh.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\vectfunc.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\msf\segmsf.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\types.hxx \
+ $(COMMON)\ih\winnot.h $(CRTINC)\assert.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h
+
+.\$(OBJDIR)\cache.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\difat.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\dir.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\dirp.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\dl.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\fat.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\header.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\msf.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\msfnew.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\mstream.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\page.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\pbstream.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\sstream.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\tstream.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\vect.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+.\$(OBJDIR)\wep.obj : $(PCHDIR)\$(OBJDIR)\msfhead.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/msf/difat.cxx b/private/ole32/stg/msf/difat.cxx
new file mode 100644
index 000000000..c0cfdd393
--- /dev/null
+++ b/private/ole32/stg/msf/difat.cxx
@@ -0,0 +1,1190 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: difat.cxx
+//
+// Contents: Double Indirected Fat Code
+//
+// Classes: None.
+//
+// Functions:
+//
+// History: 11-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#include <msfhead.cxx>
+
+#pragma hdrstop
+
+#include <difat.hxx>
+#include <mread.hxx>
+
+#ifdef DIFAT_OPTIMIZATIONS
+#define OPTIMIZE_LOOKUP
+#define OPTIMIZE_FIXUP
+#endif
+
+
+#ifndef REF
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::CDIFat, public
+//
+// Synopsis: CDIFat copy constructor
+//
+// Arguments: [fatOld] -- reference to CDIFat to be copied.
+//
+// History: 11-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_CDIFat)
+#endif
+
+CDIFat::CDIFat(CDIFat *pfatOld)
+ : _pmsParent(NULL),
+ _fv(SIDDIF)
+{
+#ifdef DIFAT_LOOKUP_ARRAY
+ _cUnmarked = 0;
+ _fDoingFixup = FALSE;
+#endif
+}
+#endif //!REF
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::CDIFat, public
+//
+// Synopsis: CDIFat constructor
+//
+// Arguments: [pmsParent] -- Pointer to parent CMStream
+//
+// History: 11-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_CDIFat2)
+#endif
+
+CDIFat::CDIFat()
+: _pmsParent(NULL),
+ _fv(SIDDIF)
+{
+ msfDebugOut((DEB_ITRACE,"In CDIFat constructor\n"));
+ _cfsTable = 0;
+#ifdef DIFAT_LOOKUP_ARRAY
+ _cUnmarked = 0;
+ _fDoingFixup = FALSE;
+#endif
+ msfDebugOut((DEB_ITRACE,"Out CDIFat constructor\n"));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDIFat::Empty, public
+//
+// Synopsis: Empty all the control structures of this instance
+//
+// Arguments: None.
+//
+// Returns: void.
+//
+// History: 04-Dec-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_Empty)
+#endif
+
+void CDIFat::Empty(void)
+{
+ _fv.Empty();
+ _pmsParent = NULL;
+ _cfsTable = 0;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CIDFat::Flush, private
+//
+// Synopsis: Flush a sector to disk
+//
+// Arguments: [oSect] -- Indicated which sector to flush
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Write sector up to parent mstream.
+//
+// History: 11-May-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_Flush)
+#endif
+
+SCODE CDIFat::Flush(void)
+{
+ return _fv.Flush();
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::GetFatSect, public
+//
+// Synopsis: Given an offset into the Fat chain, return the sector
+// value for that FatSect.
+//
+// Arguments: [oSect] -- offset in Fat chain
+//
+// Returns: Sector value of FatSect.
+//
+// Algorithm: If sector is stored in the header, retrieve it from
+// there.
+// If not, retrieve it from the FatVector.
+//
+// History: 11-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_GetFatSect)
+#endif
+
+SCODE CDIFat::GetFatSect(const FSINDEX oSect, SECT *psect)
+{
+ SCODE sc = S_OK;
+ SECT sectReturn;
+
+ msfDebugOut((DEB_ITRACE,"In CDIFat::GetFatSect(%lu)\n",oSect));
+ if (oSect < CSECTFAT)
+ {
+ msfDebugOut((DEB_ITRACE,"Getting sect from header\n"));
+ sectReturn = _pmsParent->GetHeader()->GetFatSect(oSect);
+ }
+ else
+ {
+ FSINDEX ipfs;
+ FSOFFSET isect;
+
+ SectToPair(oSect,&ipfs,&isect);
+
+ msfAssert(ipfs < _cfsTable);
+
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+ sectReturn = pfs->GetSect(isect);
+ _fv.ReleaseTable(ipfs);
+ }
+
+ msfDebugOut((DEB_ITRACE,"Out CDIFat::GetFatSect(%lu)=>%lu\n",oSect,sectReturn));
+ *psect = sectReturn;
+
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::SetFatSect, public
+//
+// Synopsis: Given an offset into the Fat chain, set the sector
+// value.
+//
+// Arguments: [oSect] -- Offset into fat chain
+// [sect] -- New sector value for that offset.
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: If the sector is stored in the header, set it and
+// flush the header.
+// Otherwise, if the sector will not fit in the current
+// CFatVector, resize it.
+// Set the sector in the FatVector and flush it.
+//
+// History: 11-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_SetFatSect)
+#endif
+
+SCODE CDIFat::SetFatSect(const FSINDEX oSect, const SECT sect)
+{
+ msfDebugOut((DEB_ITRACE,"In CDIFat::SetFatSect(%lu,%lu)\n",oSect,sect));
+ SCODE sc = S_OK;
+
+ if (oSect < CSECTFAT)
+ {
+ msfDebugOut((DEB_ITRACE,"Setting sect in header: %lu, %lu\n",oSect,sect));
+ _pmsParent->GetHeader()->SetFatSect(oSect, sect);
+ }
+ else
+ {
+ FSINDEX ipfs;
+ FSOFFSET isect;
+
+ SectToPair(oSect,&ipfs,&isect);
+ if (ipfs >= _cfsTable)
+ {
+ msfChk(Resize(_cfsTable + 1));
+ }
+
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_DIRTY, &pfs));
+
+ pfs->SetSect(isect, sect);
+ _fv.ReleaseTable(ipfs);
+
+ msfDebugOut((DEB_ITRACE,"In CDIFat::SetFatSect(%lu,%lu)\n",oSect,sect));
+ }
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::GetSect, public
+//
+// Synopsis: Given an offset into the DIFat chain, return the
+// sector value
+//
+// Arguments: [oSect] -- Offset into DIFat chain.
+//
+// Returns: Sector value for given offset.
+//
+// Algorithm: Retrieve the information from the NextFat fields of
+// the CFatVector
+//
+// History: 11-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_GetSect)
+#endif
+
+SCODE CDIFat::GetSect(const FSINDEX oSect, SECT *psect)
+{
+ SCODE sc = S_OK;
+
+ SECT sectReturn;
+
+ msfDebugOut((DEB_ITRACE,"In CDIFat::GetSect(%lu)\n",oSect));
+ msfAssert(oSect < _cfsTable);
+
+ sectReturn = _pmsParent->GetHeader()->GetDifStart();
+
+ //Possible optimization here: Do some sort of check to
+ //find the last page that's actually cached in the vector,
+ //then start the loop from there. Probably not a terribly
+ //important optimization, but it is possible.
+ for (FSINDEX oCurrent = 0; oCurrent < oSect; oCurrent++)
+ {
+ msfAssert(sectReturn != ENDOFCHAIN);
+
+ CFatSect *pfs;
+ msfChk(_fv.GetTableWithSect(oCurrent,
+ FB_NONE,
+ sectReturn,
+ (void **)&pfs));
+
+ sectReturn = pfs->GetNextFat(_fv.GetSectTable());
+ _fv.ReleaseTable(oCurrent);
+ }
+
+ msfDebugOut((DEB_ITRACE,"Out CDIFat::GetSect(%lu)=>%lu\n",oSect,sectReturn));
+ *psect = sectReturn;
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::Init, public
+//
+// Synopsis: Init function for previously stored DIFat.
+//
+// Arguments: [cFatSect] -- Length of DIFat in sectors
+//
+// Returns: S_OK if call completed properly.
+//
+// Algorithm: *Finish This*
+//
+// History: 11-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_Init)
+#endif
+
+SCODE CDIFat::Init(CMStream * pmsParent, const FSINDEX cFatSect)
+{
+ msfDebugOut((DEB_ITRACE,"In CDIFat::Init(%lu)\n",cFatSect));
+ SCODE sc;
+
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pmsParent);
+ ULONG cbSector = pmsParent->GetSectorSize();
+ _fv.InitCommon(
+ (FSOFFSET)(cbSector / sizeof(SECT)),
+ (FSOFFSET)((cbSector / sizeof(SECT)) - 1));
+
+ msfChk(_fv.Init(pmsParent, cFatSect));
+
+ _cfsTable = cFatSect;
+
+ msfDebugOut((DEB_ITRACE,"Out CDIFat::Init(%lu)\n",cFatSect));
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::InitNew, public
+//
+// Synopsis: Init function for new DIFat
+//
+// Arguments: [pmsParent] -- Pointer to parent multistream
+//
+// Returns: S_OK if call completed successfully.
+//
+// History: 11-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_InitNew)
+#endif
+
+SCODE CDIFat::InitNew(CMStream *pmsParent)
+{
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pmsParent);
+
+ ULONG cbSector = pmsParent->GetSectorSize();
+ _fv.InitCommon(
+ (FSOFFSET)(cbSector / sizeof(SECT)),
+ (FSOFFSET)((cbSector / sizeof(SECT)) - 1));
+ _fv.Init(pmsParent, 0);
+ _cfsTable = 0;
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::InitConvert, public
+//
+// Synopsis: Init function for conversion
+//
+// Arguments: [sectMax] -- Last used sector in existing file
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: *Finish This*
+//
+// History: 02-Jun-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_InitConvert)
+#endif
+
+SCODE CDIFat::InitConvert(CMStream *pmsParent, SECT sectMax)
+{
+ msfDebugOut((DEB_ITRACE,"In CDIFat::InitConvert(%lu)\n",sectMax));
+ SCODE sc;
+
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pmsParent);
+
+ USHORT cbSector = pmsParent->GetSectorSize();
+ FSOFFSET csectPer = cbSector / sizeof(SECT);
+
+ cbSector = pmsParent->GetSectorSize();
+ _fv.InitCommon(cbSector / sizeof(SECT), (cbSector / sizeof(SECT)) - 1);
+
+ FSINDEX csectFat = 0;
+ FSINDEX csectFatLast;
+
+ FSINDEX csectDif = 0;
+ FSINDEX csectDifLast;
+ do
+ {
+ //Number of fat sectors needed to represent:
+ // Number of Data Sectors (sectMax) +
+ // Number of Fat Sectors (csectFat) +
+ // Number of DIF sectors (csectDif) +
+ // Number of Directory Sectors (1)
+
+ //We must use a loop here, since the fat must be large
+ // enough to represent itself and the DIFat. See
+ // CFat::InitConvert for a more lengthy discussion of
+ // this method.
+
+ csectFatLast = csectFat;
+
+ csectFat = (sectMax + csectFatLast + csectDif + 1 + csectPer - 1) /
+ csectPer;
+
+ csectDifLast = csectDif;
+
+ if (csectFat < CSECTFAT)
+ {
+ csectDif = 0;
+ }
+ else
+ {
+ FSOFFSET ciSect;
+
+ SectToPair(csectFat, &csectDif, &ciSect);
+ csectDif++;
+ }
+ }
+ while ((csectDif != csectDifLast) || (csectFat != csectFatLast));
+
+
+ _cfsTable = csectDif;
+
+ msfChk(_fv.Init(pmsParent, _cfsTable));
+
+ pmsParent->GetHeader()->SetDifLength(_cfsTable);
+
+ if (_cfsTable > 0)
+ {
+ pmsParent->GetHeader()->SetDifStart(sectMax);
+
+ FSINDEX i;
+ for (i = 0; i < _cfsTable; i++)
+ {
+ CFatSect *pfs;
+
+ msfChk(_fv.GetTable(i, FB_NEW, &pfs));
+ _fv.SetSect(i, sectMax);
+
+ sectMax++;
+ pfs->SetNextFat(_fv.GetSectTable(),sectMax);
+ _fv.ReleaseTable(i);
+ }
+ }
+
+ msfDebugOut((DEB_ITRACE,"Out CDIFat::InitConvert()\n"));
+
+Err:
+ return sc;
+}
+
+
+#ifndef REF
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::Remap, public
+//
+// Synopsis: Remap a Fat sector for copy-on-write
+//
+// Arguments: [oSect] -- Offset into fat chain to be remapped.
+// [psectReturn] -- pointer to return value
+//
+// Returns: S_OK if call was successful.
+//
+// Algorithm: *Finish This*
+//
+// History: 11-May-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_Remap)
+#endif
+
+SCODE CDIFat::Remap(const FSINDEX oSect, SECT * psectReturn)
+{
+ msfDebugOut((DEB_ITRACE,"In CDIFat::Remap(%lu)\n",oSect));
+ SCODE sc = S_OK;
+
+ SECT sectNew;
+ SECT sectTemp;
+ msfChk(GetFatSect(oSect, &sectTemp));
+
+ msfChk(_pmsParent->GetFat()->QueryRemapped(sectTemp));
+
+ if (sc == S_FALSE)
+ {
+ msfChk(_pmsParent->GetFat()->GetFree(1, &sectNew, GF_READONLY));
+#ifdef DIFAT_LOOKUP_ARRAY
+ CacheUnmarkedSect(sectNew, FATSECT, sectTemp);
+#endif
+
+ msfDebugOut((DEB_ITRACE,"Remapping fat sector %lu from %lu to %lu\n",oSect,sectTemp,sectNew));
+
+ msfChk(SetFatSect(oSect, sectNew));
+ }
+ else
+ {
+ sectNew = ENDOFCHAIN;
+ }
+ msfDebugOut((DEB_ITRACE,"In CDIFat::Remap(%lu)=>%lu\n",oSect,sectNew));
+ *psectReturn = sectNew;
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::RemapSelf, public
+//
+// Synopsis: Remap the entire DIFat for copy-on-write.
+//
+// Arguments: None.
+//
+// Returns: S_OK if DIFat was remapped successfully.
+//
+// Algorithm: *Finish This*
+//
+// History: 11-May-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_RemapSelf)
+#endif
+
+SCODE CDIFat::RemapSelf(VOID)
+{
+ msfDebugOut((DEB_ITRACE,"In CDIFat::RemapSelf()\n"));
+ SECT sectNew, sect;
+ SCODE sc = S_OK;
+ CFatSect *pfs;
+ FSINDEX i = 0;
+
+ if (_cfsTable > 0)
+ {
+ sect = _pmsParent->GetHeader()->GetDifStart();
+
+ msfChk(_fv.GetTable(0, FB_DIRTY, &pfs));
+ msfChkTo(Err_Rel0, _pmsParent->GetFat()->GetFree(1, &sectNew, GF_READONLY));
+
+#ifdef DIFAT_LOOKUP_ARRAY
+ SECT sectOld;
+ sectOld = _pmsParent->GetHeader()->GetDifStart();
+ CacheUnmarkedSect(sectNew, DIFSECT, sectOld);
+#endif
+ _pmsParent->GetHeader()->SetDifStart(sectNew);
+
+ _fv.SetSect(0, sectNew);
+
+ _fv.ReleaseTable(0);
+ }
+
+
+ for (i = 1; i < _cfsTable; i++)
+ {
+ CFatSect *pfs2;
+
+ msfChk(_fv.GetTable(i - 1, FB_DIRTY, &pfs));
+ msfChkTo(Err_Rel1, _fv.GetTable(i, FB_DIRTY, &pfs2));
+
+ msfChkTo(Err_Rel, _pmsParent->GetFat()->GetFree(
+ 1,
+ &sectNew,
+ GF_READONLY));
+#ifdef DIFAT_LOOKUP_ARRAY
+ SECT sectOld;
+ sectOld = pfs->GetNextFat(_fv.GetSectTable());
+ CacheUnmarkedSect(sectNew, DIFSECT, sectOld);
+#endif
+
+ pfs->SetNextFat(_fv.GetSectTable(), sectNew);
+ _fv.SetSect(i, sectNew);
+
+ _fv.ReleaseTable(i - 1);
+ _fv.ReleaseTable(i);
+ }
+ msfDebugOut((DEB_ITRACE,"In CDIFat::RemapSelf()\n"));
+
+Err:
+ return sc;
+
+Err_Rel0:
+ _fv.ReleaseTable(0);
+ return sc;
+Err_Rel:
+ _fv.ReleaseTable(i);
+Err_Rel1:
+ _fv.ReleaseTable(i - 1);
+ return sc;
+}
+#endif //!REF
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::Resize, private
+//
+// Synopsis: Resize an existing DIFat.
+//
+// Arguments: [fsiSize] -- New size for object
+//
+// Returns: Nothing right now.
+//
+// Algorithm: *Finish This*
+//
+// History: 11-May-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_Resize)
+#endif
+
+SCODE CDIFat::Resize(FSINDEX fsiSize)
+{
+ msfDebugOut((DEB_ITRACE,"In CDIFat::Resize(%lu)\n",fsiSize));
+ msfAssert(fsiSize == _cfsTable + 1);
+
+ SCODE sc;
+
+ msfChk(_fv.Resize(fsiSize));
+ ULONG ipfs;
+ ipfs = fsiSize - 1;
+
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NEW, &pfs));
+
+ FSINDEX csect;
+ csect = _cfsTable;
+ _cfsTable = fsiSize;
+
+ SECT sectNew;
+
+#ifdef USE_NOSCRATCH
+ //If we're in no-scratch mode, passing GF_WRITE to the fat here can
+ // cause a nasty loop on Resize(). Do a read-only GetFree in that
+ // case, and don't try to update the fat.
+
+ if ((_pmsParent->HasNoScratch()
+#ifdef USE_NOSNAPSHOT
+ ||
+ (_pmsParent->GetFat()->GetNoSnapshotFree() != ENDOFCHAIN)
+#endif
+ ))
+ {
+ msfChk(_pmsParent->GetFat()->GetFree(1, &sectNew, GF_READONLY));
+#ifdef DIFAT_LOOKUP_ARRAY
+ CacheUnmarkedSect(sectNew, DIFSECT, ENDOFCHAIN);
+#endif
+ }
+ else
+ {
+#endif
+#ifndef REF
+ msfChk(_pmsParent->GetFat()->GetFree(1, &sectNew, GF_WRITE));
+#else
+ msfChk(_pmsParent->GetFat()->GetFree(1, &sectNew));
+#endif //!REF
+ msfChk(_pmsParent->GetFat()->SetNext(sectNew, DIFSECT));
+#ifdef USE_NOSCRATCH
+ }
+#endif
+
+#ifndef REF
+#if DBG == 1
+ STATSTG stat;
+
+ msfHChk(_pmsParent->GetILB()->Stat(&stat, STATFLAG_NONAME));
+ msfAssert(
+ ConvertSectOffset(sectNew + 1, 0, _pmsParent->GetSectorShift()) <=
+ ULIGetLow(stat.cbSize));
+#endif
+#endif //!REF
+
+
+ _fv.SetSect(ipfs, sectNew);
+ _fv.ReleaseTable(ipfs);
+
+ if (csect == 0)
+ {
+ _pmsParent->GetHeader()->SetDifStart(sectNew);
+ }
+ else
+ {
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(csect - 1, FB_DIRTY, &pfs));
+
+ pfs->SetNextFat(_fv.GetSectTable(),sectNew);
+ _fv.ReleaseTable(csect - 1);
+ }
+
+ _pmsParent->GetHeader()->SetDifLength(_cfsTable);
+
+ msfDebugOut((DEB_ITRACE,"Out CDIFat::Resize(%lu)\n",fsiSize));
+
+Err:
+ return sc;
+}
+
+
+
+#ifndef REF
+//+---------------------------------------------------------------------------
+//
+// Member: CDIFat::Lookup, public
+//
+// Synopsis: Lookup a sector and see if it is in the DIFat. If it
+// is, return FATSECT if it is allocated to a fat sector
+// or DIFSECT if it is allocated to the DIF.
+//
+// Arguments: [sect] -- Sector to look up
+// [psectRet] -- Location for return value
+// [fReadOnly] -- If FALSE, decrement the dirty count
+// after returning the page.
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 23-Feb-93 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_Lookup)
+#endif
+
+SCODE CDIFat::Lookup(const SECT sect, SECT *psectRet)
+{
+ SCODE sc = S_OK;
+
+ *psectRet = FREESECT;
+#ifdef DIFAT_LOOKUP_ARRAY
+
+ if (_cUnmarked <= DIFAT_ARRAY_SIZE)
+ {
+ for (USHORT iArray = 0; iArray < _cUnmarked; iArray++)
+ {
+ if (_sectUnmarked[iArray] == sect)
+ {
+ *psectRet = _sectMarkTo[iArray];
+ return S_OK;
+ }
+ }
+ return S_OK;
+ }
+#endif
+
+ for (FSINDEX i = 0; i < _pmsParent->GetHeader()->GetDifLength(); i++)
+ {
+ SECT sectDif;
+
+ msfChk(GetSect(i, &sectDif));
+ if (sectDif == sect)
+ {
+ *psectRet = DIFSECT;
+ return S_OK;
+ }
+ }
+#ifdef OPTIMIZE_LOOKUP
+ CFatSect *pfs;
+ pfs = NULL;
+ FSINDEX ipfsLast;
+ ipfsLast = (FSOFFSET) -1;
+ FSINDEX ipfs;
+ FSOFFSET isect;
+#endif
+ for (i = 0; i < _pmsParent->GetHeader()->GetFatLength(); i++)
+ {
+#ifndef OPTIMIZE_LOOKUP
+ SECT sectFat;
+
+ msfChk(GetFatSect(i, &sectFat));
+ if (sectFat == sect)
+ {
+ *psectRet = FATSECT;
+ return S_OK;
+ }
+#else
+ SECT sectFat;
+ if (i < CSECTFAT)
+ {
+ sectFat = _pmsParent->GetHeader()->GetFatSect(i);
+ }
+ else
+ {
+ SectToPair(i, &ipfs, &isect);
+ if (ipfs != ipfsLast)
+ {
+ if (pfs != NULL)
+ {
+ _fv.ReleaseTable(ipfsLast);
+ }
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+ }
+ sectFat = pfs->GetSect(isect);
+ ipfsLast = ipfs;
+ }
+ if (sect == sectFat)
+ {
+ if (pfs != NULL)
+ {
+ _fv.ReleaseTable(ipfs);
+ }
+ *psectRet = FATSECT;
+ return S_OK;
+ }
+#endif
+ }
+
+#ifdef OPTIMIZE_LOOKUP
+ if (pfs != NULL)
+ {
+ _fv.ReleaseTable(ipfs);
+ }
+#endif
+Err:
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDIFat::Fixup, public
+//
+// Synopsis: Fixup the Fat after a copy-on-write commit.
+//
+// Arguments: [pmsShadow] -- Pointer to shadow multistream
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 23-Feb-93 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDIFat_Fixup)
+#endif
+
+SCODE CDIFat::Fixup(CMStream *pmsShadow)
+{
+ SCODE sc = S_OK;
+
+ BOOL fChanged;
+
+ CFat *pfat = _pmsParent->GetFat();
+#if DBG == 1
+ pfat->CheckFreeCount();
+#endif
+
+#ifdef DIFAT_LOOKUP_ARRAY
+ if (_fDoingFixup)
+ return S_OK;
+
+ _fDoingFixup = TRUE;
+
+ if (_cUnmarked <= DIFAT_ARRAY_SIZE)
+ {
+ for (USHORT iArray = 0;
+ (iArray < _cUnmarked) && (_cUnmarked <= DIFAT_ARRAY_SIZE);
+ iArray++)
+ {
+ //sectNew may be out of the range of the current fat.
+ //Check and resize if necessary. This is needed for
+ //no-scratch mode.
+ FSINDEX ipfs;
+ FSOFFSET isect;
+ pfat->SectToPair(_sectUnmarked[iArray], &ipfs, &isect);
+ if (ipfs >= _pmsParent->GetHeader()->GetFatLength())
+ {
+ msfChk(pfat->Resize(ipfs + 1));
+ }
+
+ msfChk(pfat->SetNext(_sectUnmarked[iArray],
+ _sectMarkTo[iArray]));
+ if (_sectFree[iArray] != ENDOFCHAIN)
+ {
+ msfChk(pfat->SetNext(_sectFree[iArray], FREESECT));
+ }
+ }
+ }
+
+ if (_cUnmarked <= DIFAT_ARRAY_SIZE)
+ {
+ _cUnmarked = 0;
+ pfat->ResetUnmarkedSects();
+ _fDoingFixup = FALSE;
+ return S_OK;
+ }
+#endif
+
+#ifdef USE_NOSCRATCH
+ if (pmsShadow != NULL)
+ {
+#endif
+ CDIFat *pdifOld = pmsShadow->GetDIFat();
+ FSINDEX cFatOld = pmsShadow->GetHeader()->GetFatLength();
+ FSINDEX cDifOld = pmsShadow->GetHeader()->GetDifLength();
+
+ for (FSINDEX i = 0; i < _pmsParent->GetHeader()->GetDifLength(); i++)
+ {
+ SECT sectNew;
+ SECT sectOld = ENDOFCHAIN;
+ SECT sectCurrent;
+
+ msfChk(GetSect(i, &sectNew));
+
+ if (i < cDifOld)
+ msfChk(pdifOld->GetSect(i, &sectOld));
+
+ if ((sectNew != sectOld) || (sectOld == ENDOFCHAIN))
+ {
+#ifdef USE_NOSCRATCH
+ //sectNew may be out of the range of the current fat.
+ //Check and resize if necessary.
+ FSINDEX ipfs;
+ FSOFFSET isect;
+ pfat->SectToPair(sectNew, &ipfs, &isect);
+ if (ipfs >= _pmsParent->GetHeader()->GetFatLength())
+ {
+ msfChk(pfat->Resize(ipfs + 1));
+ }
+#endif
+
+ msfChk(pfat->GetNext(sectNew, &sectCurrent));
+ if (sectCurrent != DIFSECT)
+ {
+ msfChk(pfat->SetNext(sectNew, DIFSECT));
+ }
+
+ if (sectOld != ENDOFCHAIN)
+ {
+ //sectOld should always be within the range of the
+ //fat, so we don't need to check and resize here.
+ msfChk(pfat->GetNext(sectOld, &sectCurrent));
+ if (sectCurrent != FREESECT)
+ {
+ msfChk(pfat->SetNext(sectOld, FREESECT));
+ }
+ }
+ }
+ }
+
+
+ do
+ {
+ fChanged = FALSE;
+#ifdef OPTIMIZE_FIXUP
+ CFatSect *pfs;
+ pfs = NULL;
+ FSINDEX ipfsLast;
+ ipfsLast = (FSOFFSET) - 1;
+ FSINDEX ipfs;
+ FSOFFSET isect;
+
+ CFatSect *pfsShadow;
+ pfsShadow = NULL;
+ FSINDEX ipfsLastShadow;
+ ipfsLastShadow = (FSOFFSET) - 1;
+ FSINDEX ipfsShadow;
+ FSOFFSET isectShadow;
+
+#endif
+ for (i = 0; i < _pmsParent->GetHeader()->GetFatLength(); i++)
+ {
+ SECT sectNew;
+ SECT sectCurrent;
+ SECT sectOld = ENDOFCHAIN;
+
+#ifndef OPTIMIZE_FIXUP
+ msfChk(GetFatSect(i, &sectNew));
+#else
+ if (i < CSECTFAT)
+ {
+ sectNew = _pmsParent->GetHeader()->GetFatSect(i);
+ }
+ else
+ {
+ SectToPair(i, &ipfs, &isect);
+ if (ipfs != ipfsLast)
+ {
+ if (pfs != NULL)
+ {
+ _fv.ReleaseTable(ipfsLast);
+ }
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+ }
+ sectNew = pfs->GetSect(isect);
+ ipfsLast = ipfs;
+ }
+#endif
+
+#ifndef OPTIMIZE_FIXUP
+ if (i < cFatOld)
+ msfChk(pdifOld->GetFatSect(i, &sectOld));
+#else
+ if (i < cFatOld)
+ {
+ if (i < CSECTFAT)
+ {
+ sectOld = pmsShadow->GetHeader()->GetFatSect(i);
+ }
+ else
+ {
+ SectToPair(i, &ipfsShadow, &isectShadow);
+ if (ipfsShadow != ipfsLastShadow)
+ {
+ if (pfsShadow != NULL)
+ {
+ pdifOld->_fv.ReleaseTable(ipfsLastShadow);
+ }
+ msfChk(pdifOld->_fv.GetTable(ipfsShadow,
+ FB_NONE,
+ &pfsShadow));
+ }
+ sectOld = pfsShadow->GetSect(isectShadow);
+ ipfsLastShadow = ipfsShadow;
+ }
+ }
+#endif
+
+ if ((sectNew != sectOld) || (sectOld == ENDOFCHAIN))
+ {
+ //Sector has been remapped.
+
+#ifdef USE_NOSCRATCH
+ //sectNew may be outside the range of the current
+ //fat. Check and resize if necessary.
+ //If we resize, set fChanged, since we may need to
+ //go through again.
+
+ FSINDEX ipfs;
+ FSOFFSET isect;
+ pfat->SectToPair(sectNew, &ipfs, &isect);
+ if (ipfs >= _pmsParent->GetHeader()->GetFatLength())
+ {
+ msfChk(pfat->Resize(ipfs + 1));
+ fChanged = TRUE;
+ }
+#endif
+
+ msfChk(pfat->GetNext(sectNew, &sectCurrent));
+
+ if (sectCurrent != FATSECT)
+ {
+ msfChk(pfat->SetNext(sectNew, FATSECT));
+ fChanged = TRUE;
+ }
+
+ if (sectOld != ENDOFCHAIN)
+ {
+ //sectOld is always inside the existing fat,
+ //so we don't need to check and resize.
+ msfChk(pfat->GetNext(sectOld, &sectCurrent));
+ if (sectCurrent != FREESECT)
+ {
+ msfChk(pfat->SetNext(sectOld, FREESECT));
+ fChanged = TRUE;
+ }
+ }
+ }
+ }
+#ifdef OPTIMIZE_FIXUP
+ if (pfs != NULL)
+ _fv.ReleaseTable(ipfsLast);
+ if (pfsShadow != NULL)
+ pdifOld->_fv.ReleaseTable(ipfsLastShadow);
+#endif
+ }
+ while (fChanged);
+#ifdef USE_NOSCRATCH
+ }
+ else
+ {
+ //This is for fixing the fat while in overwrite mode with
+ // no-scratch.
+ do
+ {
+ fChanged = FALSE;
+ for (FSINDEX i = 0;
+ i < _pmsParent->GetHeader()->GetFatLength();
+ i++)
+ {
+ SECT sectNew;
+ SECT sectCurrent;
+
+ msfChk(GetFatSect(i, &sectNew));
+
+ //sectNew may be outside the range of the current fat. If
+ //so, resize the fat.
+ FSINDEX ipfs;
+ FSOFFSET isect;
+ pfat->SectToPair(sectNew, &ipfs, &isect);
+ if (ipfs >= _pmsParent->GetHeader()->GetFatLength())
+ {
+ msfChk(pfat->Resize(ipfs + 1));
+ fChanged = TRUE;
+ }
+
+ msfChk(pfat->GetNext(sectNew, &sectCurrent));
+ if (sectCurrent != FATSECT)
+ {
+ msfChk(pfat->SetNext(sectNew, FATSECT));
+ fChanged = TRUE;
+ }
+ }
+ }
+ while (fChanged);
+ }
+#endif
+ pfat->ResetUnmarkedSects();
+#ifdef DIFAT_LOOKUP_ARRAY
+ _cUnmarked = 0;
+#endif
+Err:
+#ifdef DIFAT_LOOKUP_ARRAY
+ _fDoingFixup = FALSE;
+#endif
+#if DBG == 1
+ pfat->CheckFreeCount();
+#endif
+ return sc;
+}
+#endif //!REF
+
diff --git a/private/ole32/stg/msf/dir.cxx b/private/ole32/stg/msf/dir.cxx
new file mode 100644
index 000000000..4531d7f32
--- /dev/null
+++ b/private/ole32/stg/msf/dir.cxx
@@ -0,0 +1,1450 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: dir.cxx
+//
+// Contents: Directory Functions
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+//---------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+#pragma hdrstop
+
+#include <dirfunc.hxx>
+#include <mread.hxx>
+
+#define DEB_DIR (DEB_ITRACE | 0x00040000)
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::KillStream, public
+//
+// Synopsis: Eliminate a given chain
+//
+// Arguments: [sectStart] -- Beginning of chain to eliminate
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: *Finish This*
+//
+// History: 14-Sep-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_KillStream)
+#endif
+
+inline SCODE MSTREAM_CLASS CMStream::KillStream(SECT sectStart, ULONG ulSize)
+{
+ CFat *pfat;
+
+#ifndef REF
+ pfat = ((!_fIsScratch) && (ulSize < MINISTREAMSIZE)) ? &_fatMini: &_fat;
+#else
+ pfat = (ulSize < MINISTREAMSIZE) ?&_fatMini: &_fat;
+#endif //!REF
+
+ return pfat->SetChainLength(sectStart, 0);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirEntry::CDirEntry, public
+//
+// Synopsis: Constructor for CDirEntry class
+//
+// Effects:
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirEntry_CDirEntry) // inline?
+#endif
+
+DIR_CLASS CDirEntry::CDirEntry()
+{
+ msfAssert(sizeof(CDirEntry) == DIRENTRYSIZE);
+ Init(STGTY_INVALID);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirSect::Init, public
+//
+// Synopsis: Initializer for directory sectors
+//
+// Arguments: [cdeEntries] -- Number of DirEntries in the sector
+//
+// Returns: S_OK if call completed OK.
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 27-Dec-91 PhilipLa Converted from const to var size
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirSect_Init)
+#endif
+
+SCODE DIR_CLASS CDirSect::Init(USHORT cbSector)
+{
+ msfDebugOut((DEB_DIR,"Allocating sector with size %u\n",cbSector));
+
+#if WIN32 == 200
+ //Make sure to zero out the memory, since Win95 doesn't do it for
+ // you. NT does, so we don't need to do this there.
+ memset(_adeEntry, 0, cbSector);
+#endif
+
+ DIROFFSET cdeEntries = cbSector / sizeof(CDirEntry);
+
+ for (ULONG i = 0; i < cdeEntries; i++)
+ {
+ _adeEntry[i].Init(STGTY_INVALID);
+ }
+
+ return S_OK;
+}
+
+
+#ifndef REF
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirSect::InitCopy, public
+//
+// Synopsis: CDirSect initializer for copying
+//
+// Arguments: [dsOld] -- Const reference to dir to be copied
+//
+// Returns: S_OK if call completed successfully.
+//
+// History: 18-Feb-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirSect_InitCopy)
+#endif
+
+SCODE DIR_CLASS CDirSect::InitCopy(USHORT cbSector,
+ const CDirSect *pdsOld)
+{
+ msfDebugOut((DEB_DIR,"In CDirSect copy constructor\n"));
+
+ memcpy(_adeEntry, pdsOld->_adeEntry, cbSector);
+
+ msfDebugOut((DEB_DIR,"Out CDirSect copy constructor\n"));
+ return S_OK;
+}
+#endif //!REF
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectory::CDirectory
+//
+// Synopsis: Default constructor
+//
+// History: 22-Apr-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_CDirectory)
+#endif
+
+DIR_CLASS CDirectory::CDirectory()
+ : _pmsParent(NULL)
+{
+ _cdsTable = _cdeEntries = 0;
+ _sidFirstFree = 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirectory::Empty, public
+//
+// Synopsis: Empty all the control structures of this instance
+//
+// Arguments: None.
+//
+// Returns: void.
+//
+// History: 04-Dec-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_Empty)
+#endif
+
+void CDirectory::Empty(void)
+{
+ _dv.Empty();
+ _pmsParent = NULL;
+ _cdsTable = 0;
+ _cdeEntries = 0;
+ _sidFirstFree = 0;
+}
+
+
+#ifndef REF
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectory::InitCopy, public
+//
+// Synopsis: Init function for copying.
+//
+// Arguments: [dirOld] -- Const reference to dir object to be copied
+//
+// History: 18-Feb-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_InitCopy)
+#endif
+
+void DIR_CLASS CDirectory::InitCopy(CDirectory *pdirOld)
+{
+ msfDebugOut((DEB_DIR,"In CDirectory copy constructor\n"));
+
+ _pmsParent = pdirOld->_pmsParent;
+
+ _cdeEntries = pdirOld->_cdeEntries;
+
+ _dv.InitCommon(_pmsParent->GetSectorSize());
+ _dv.InitCopy(&pdirOld->_dv);
+ _cdsTable = pdirOld->_cdsTable;
+ _sidFirstFree = pdirOld->_sidFirstFree;
+
+ msfDebugOut((DEB_DIR,"Out CDirectory copy constructor\n"));
+}
+#endif //!REF
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::GetFree, public
+//
+// Synposis: Locates a free directory entry
+//
+// Arguments: None.
+//
+// Returns: Stream ID of free directory entry
+//
+// Algorithm: Do a linear search of all available directories.
+// If no free spot is found, resize the directory and
+// perform the search again.
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_GetFree)
+#endif
+
+SCODE DIR_CLASS CDirectory::GetFree(SID * psid)
+{
+ msfDebugOut((DEB_DIR,"In CDirectory::GetFree()\n"));
+
+ SCODE sc = S_OK;
+ SID sidRet = NOSTREAM;
+ CDirSect * pds;
+
+ DIRINDEX ipdsStart;
+ DIROFFSET ideStart;
+
+ SidToPair(_sidFirstFree, &ipdsStart, &ideStart);
+ while (TRUE)
+ {
+ for (DIRINDEX ipds = ipdsStart; ipds < _cdsTable; ipds++)
+ {
+ msfChk(_dv.GetTable(ipds, FB_NONE, &pds));
+ for (DIROFFSET ide = ideStart; ide < _cdeEntries; ide++)
+ {
+ if (pds->GetEntry(ide)->IsFree())
+ {
+ msfDebugOut((DEB_ITRACE,"GetFree found sid %lu\n",
+ PairToSid(ipds,ide)));
+
+ *psid = PairToSid(ipds, ide);
+ _sidFirstFree = *psid + 1;
+ _dv.ReleaseTable(ipds);
+ return S_OK;
+ }
+ }
+ _dv.ReleaseTable(ipds);
+ ideStart = 0;
+ }
+ ipdsStart = ipds;
+ msfChk(Resize(_cdsTable+1));
+ }
+
+ Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::FindGreaterEntry
+//
+// Synopsis: finds next entry (for iteration)
+//
+// Arguments: [sidStart] -- child sid to start looking
+// [pdfn] -- previous entry name
+// [psidResult] -- place holder for returned sid
+//
+// Requires: sidStart != NOSTREAM
+//
+// Returns: S_OK, STG_E_NOMOREFILES, or other error
+//
+// Modifies: psidResult
+//
+// Algorithm: Iterate by returning the sid that has a name larger
+// than the given name.
+//
+// History: 16-Oct-92 AlexT Created
+//
+// Notes: This method is called recursively
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_FindGreaterEntry)
+#endif
+
+SCODE CDirectory::FindGreaterEntry(SID sidStart, CDfName const *pdfn, SID *psidResult)
+{
+ SCODE sc;
+ CDirEntry *pde;
+ msfAssert(sidStart != NOSTREAM);
+
+ msfChk(GetDirEntry(sidStart, FB_NONE, &pde));
+
+ int iCmp;
+ iCmp = NameCompare(pdfn, pde->GetName());
+
+ if (iCmp < 0)
+ {
+ // Since the last name returned is less than this name,
+ // the sid to return must either be to our left or this sid
+
+ SID sidLeft = pde->GetLeftSib();
+
+ // We can't hold onto sidStart as we recurse, (because we'll ask for
+ // a page each time we recurse)
+
+ ReleaseEntry(sidStart);
+ if (sidLeft == sidStart)
+ {
+ //Corrupt docfile - return error.
+ return STG_E_DOCFILECORRUPT;
+ }
+
+ if ((sidLeft == NOSTREAM) ||
+ (sc = FindGreaterEntry(sidLeft, pdfn, psidResult)) == STG_E_NOMOREFILES)
+ {
+ // There was no left child with a name greater than pdfn, so
+ // we return ourself
+
+ *psidResult = sidStart;
+ sc = S_OK;
+ }
+ }
+ else
+ {
+ // The last name returned is greater than this one, so we've already
+ // returned this sidStart. Look in the right subtree.
+
+ SID sidRight = pde->GetRightSib();
+
+ // We can't hold onto sidStart as we recurse, (because we'll ask for
+ // a page each time we recurse)
+
+ ReleaseEntry(sidStart);
+
+ if (sidRight == sidStart)
+ {
+ //Corrupt docfile - return error.
+ return STG_E_DOCFILECORRUPT;
+ }
+
+ if (sidRight == NOSTREAM)
+ sc = STG_E_NOMOREFILES;
+ else
+ sc = FindGreaterEntry(sidRight, pdfn, psidResult);
+ }
+Err:
+ return(sc);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectory::SetStart, public
+//
+// Synopsis: Set starting sector for a dir entry
+//
+// Arguments: [sid] -- SID of entry to be modified
+// [sect] -- New starting sector for entry
+//
+// Returns: SID of modified entry
+//
+// History: 18-Feb-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_SetStart)
+#endif
+
+SCODE DIR_CLASS CDirectory::SetStart(const SID sid, const SECT sect)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+
+ pde->SetStart(sect);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SetChild, public
+//
+// Synposis: Set the child SID of an entry
+//
+// Effects: Modifies a single directory entry. Causes a one sector
+// stream write.
+//
+// Arguments: [sid] -- Stream ID of entry to be set
+// [sidChild] -- SID of first child of this stream
+//
+// Returns: SID of modified entry
+//
+// Algorithm: Change child field on entry, then write to stream.
+//
+// History: 24-Sep-91 PhilipLa Created.
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_SetChild)
+#endif
+
+SCODE DIR_CLASS CDirectory::SetChild(const SID sid, const SID sidChild)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+
+ pde->SetChild(sidChild);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SetSize, public
+//
+// Synposis: Set the size of an entry
+//
+// Effects: Modifies a single directory entry. Causes a one sector
+// stream write.
+//
+// Arguments: [sid] -- Stream ID of entry to be set
+// [cbSize] -- Size
+//
+// Returns: SID of modified entry
+//
+// Algorithm: Change size field on entry, then write to stream.
+//
+// History: 24-Sep-91 PhilipLa Created.
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_SetSize)
+#endif
+
+SCODE DIR_CLASS CDirectory::SetSize(const SID sid, const ULONG cbSize)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+
+ pde->SetSize(cbSize);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SetTime, public
+//
+// Synposis: Set the time of an entry
+//
+// Effects: Modifies a single directory entry. Causes a one sector
+// stream write.
+//
+// Arguments: [sid] -- Stream ID of entry to be set
+// [tt] - WT_*
+// [nt] - New time
+//
+// Returns: Apropriate status code
+//
+// Algorithm: Change time field on entry, then write to stream.
+//
+// History: 24-Sep-91 PhilipLa Created.
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_SetTime)
+#endif
+
+SCODE DIR_CLASS CDirectory::SetTime(const SID sid, WHICHTIME tt, TIME_T nt)
+{
+ SCODE sc;
+
+ CDirEntry *pde;
+
+ // We don't support ACCESS times, so just ignore sets
+ if (tt == WT_ACCESS)
+ return S_OK;
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+ pde->SetTime(tt, nt);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SetAllTimes, public
+//
+// Synposis: Set the times of an entry
+//
+// Effects: Modifies a single directory entry. Causes a one sector
+// stream write.
+//
+// Arguments: [sid] -- Stream ID of entry to be set
+// [atm] - ACCESS time
+// [mtm] - MODIFICATION time
+// [ctm] - Creation Time
+//
+// Returns: Appropriate Status Code
+//
+// Algorithm: Change time fields on entry, then write to stream.
+//
+// History: 24-Nov-95 SusiA Created.
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_SetAllTimes)
+#endif
+
+SCODE DIR_CLASS CDirectory::SetAllTimes(const SID sid,
+ TIME_T atm,
+ TIME_T mtm,
+ TIME_T ctm)
+{
+ SCODE sc;
+
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+ pde->SetAllTimes(atm, mtm, ctm);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SetFlags, public
+//
+// Synposis: Set the flags of an entry
+//
+// Effects: Modifies a single directory entry. Causes a one sector
+// stream write.
+//
+// Arguments: [sid] -- Stream ID of entry to be set
+// [mse] - New flags
+//
+// Returns: Status code
+//
+// Algorithm: Change Luid field on entry, then write to stream.
+//
+// History: 08-Oct-92 PhilipLa Created
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_SetFlags)
+#endif
+
+SCODE DIR_CLASS CDirectory::SetFlags(const SID sid, const MSENTRYFLAGS mse)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+ pde->SetFlags(mse);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SetClassId, public
+//
+// Synposis: Set the class ID of an entry
+//
+// Effects: Modifies a single directory entry. Causes a one sector
+// stream write.
+//
+// Arguments: [sid] -- Stream ID of entry to be set
+// [cls] - Class ID
+//
+// Returns: Appropriate status code
+//
+// History: 11-Nov-92 DrewB Created.
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_SetClassId)
+#endif
+
+SCODE DIR_CLASS CDirectory::SetClassId(const SID sid, const GUID cls)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+ pde->SetClassId(cls);
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SetUserFlags, public
+//
+// Synposis: Set the user flags of an entry
+//
+// Effects: Modifies a single directory entry. Causes a one sector
+// stream write.
+//
+// Arguments: [sid] -- Stream ID of entry to be set
+// [dwUserFlags] - Flags
+// [dwMask] - Mask
+//
+// Returns: Appropriate status code
+//
+// History: 11-Nov-92 DrewB Created.
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_SetUserFlags)
+#endif
+
+SCODE DIR_CLASS CDirectory::SetUserFlags(SID const sid,
+ DWORD dwUserFlags,
+ DWORD dwMask)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+ pde->SetUserFlags(dwUserFlags, dwMask);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::resize, private
+//
+// Synposis: Resize a directory.
+//
+// Effects: Reallocates space for directory table, copying over
+// old pointers as necessary. Any new tables needed are
+// created here.
+//
+// Arguments: [uNewsize] -- New size for Directory
+//
+// Returns: void
+//
+// Algorithm: Allocate a new array of pointers of the necessary size.
+// Then, copy over all pointers from old array and allocate
+// new CDirSects for all new tables.
+//
+// History: 20-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_Resize)
+#endif
+
+SCODE DIR_CLASS CDirectory::Resize(DIRINDEX uNewsize)
+{
+ msfDebugOut((DEB_DIR,"In CDirectory::Resize(%i)\n",uNewsize));
+ SCODE sc;
+
+ if (uNewsize == _cdsTable) return S_OK;
+
+ SECT sect;
+ //GetESect call will make sure we have enough Fat space.
+ msfChk(_pmsParent->GetESect(SIDDIR, uNewsize - 1, &sect));
+
+ msfChk(_dv.Resize(uNewsize));
+
+ ULONG ipds;
+ for (ipds = _cdsTable; ipds < uNewsize; ipds++)
+ {
+ CDirSect *pds;
+ msfChk(_dv.GetTable(ipds, FB_NEW, &pds));
+
+ SECT sect;
+ msfChk(_pmsParent->GetESect(SIDDIR, ipds, &sect));
+ _dv.SetSect(ipds, sect);
+ _dv.ReleaseTable(ipds);
+ }
+
+ _cdsTable = uNewsize;
+ Err:
+#if DBG == 1
+ ULONG cbSect;
+ SECT sectStart;
+
+ sectStart = _pmsParent->GetHeader()->GetDirStart();
+ _pmsParent->GetFat()->GetLength(sectStart, &cbSect);
+
+ msfAssert((cbSect == _cdsTable) &&
+ aMsg("Directory length in FAT does not match cached size."));
+#endif
+
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::Init, public
+//
+// Synposis: Sets up a Directory instance and reads in all tables
+// from the stream
+//
+// Arguments: [cSect] -- Number of sectors in directory
+//
+// Returns: S_OK if call completed OK.
+// STG_E_READFAULT if not enough bytes were read for
+// a DirSector
+// Error code of read if read returned an error.
+//
+// Algorithm: Create array to hold appropriate number of tables.
+// Read in each table from disk.
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_Init)
+#endif
+
+SCODE DIR_CLASS CDirectory::Init(
+ CMStream *pmsParent,
+ DIRINDEX cSect)
+{
+ msfDebugOut((DEB_DIR,"In CDirectory::Init(%lu)\n",cSect));
+ SCODE sc;
+
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pmsParent);
+
+ _cdeEntries = pmsParent->GetSectorSize() / sizeof(CDirEntry);
+
+ _dv.InitCommon(pmsParent->GetSectorSize());
+ msfChk(_dv.Init(pmsParent, cSect));
+
+ _cdsTable = cSect;
+
+ msfDebugOut((DEB_DIR,"Out CDirectory::Init()\n"));
+
+ Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::InitNew, public
+//
+// Synposis: Sets up a new Directory instance for a new Mstream
+//
+// Arguments: None.
+//
+// Returns: S_OK if call completed OK.
+// STG_E_WRITEFAULT if not enough bytes were written.
+// Error code of write if write failed.
+//
+// Algorithm: Write initial DirSector to disk.
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_InitNew)
+#endif
+
+SCODE DIR_CLASS CDirectory::InitNew(CMStream *pmsParent)
+{
+ SCODE sc;
+ CDfName const dfnRoot(L"Root Entry");
+
+ msfDebugOut((DEB_DIR,"In CDirectory::setupnew()\n"));
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pmsParent);
+
+ _cdeEntries = pmsParent->GetSectorSize() / sizeof(CDirEntry);
+
+ _dv.InitCommon(pmsParent->GetSectorSize());
+ msfChk(_dv.Init(pmsParent, 1));
+
+ CDirSect *pds;
+
+ msfChk(_dv.GetTable(0, FB_NEW, &pds));
+ _dv.SetSect(0, pmsParent->GetHeader()->GetDirStart());
+ _dv.ReleaseTable(0);
+
+ _cdsTable = 1;
+
+ SID sidRoot;
+
+ msfChk(GetFree(&sidRoot));
+ CDirEntry *pdeTemp;
+
+ msfChk(GetDirEntry(sidRoot, FB_DIRTY, &pdeTemp));
+ pdeTemp->Init(STGTY_ROOT);
+
+ msfAssert(sidRoot == SIDROOT);
+
+ pdeTemp->SetName(&dfnRoot);
+
+ ReleaseEntry(sidRoot);
+
+ msfDebugOut((DEB_DIR,"Exiting CDirectory::setupnew()\n"));
+
+ Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectory::CreateEntry, public
+//
+// Synopsis: Create a new directory entry
+//
+// Arguments: [sidParent] -- SID of parent for new entry
+// [pwcsName] -- Name of new entry
+// [mef] -- Flags for new entry
+// [psidNew] -- Return location for new SID
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Allocate new entry.
+// Try to insert.
+// If unsuccessful, return new entry to free pool.
+//
+// History: 19-Aug-92 PhilipLa Created.
+// 20-Jul-93 AlexT Optimized (skip initial search)
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_CreateEntry) // Dir_Create_TEXT
+#endif
+
+SCODE DIR_CLASS CDirectory::CreateEntry(
+ SID sidParent,
+ CDfName const *pdfn,
+ MSENTRYFLAGS mef,
+ SID *psidNew)
+{
+ SCODE sc;
+ SID sidNew;
+ CDirEntry *pdeNew;
+
+ // Allocate new sid
+
+ msfChk(GetFree(psidNew));
+ sidNew = *psidNew;
+
+ msfChk(GetDirEntry(sidNew, FB_DIRTY, &pdeNew));
+
+ // Initialize new entry
+
+ pdeNew->Init(mef);
+
+ TIME_T timetemp;
+ if (STORAGELIKE(mef))
+ {
+ if (FAILED(sc = DfGetTOD(&timetemp)))
+ {
+ ReleaseEntry(sidNew);
+ msfErr(Err, sc);
+ }
+ }
+ else
+ {
+ timetemp.dwLowDateTime = timetemp.dwHighDateTime = 0;
+ }
+
+ pdeNew->SetTime(WT_CREATION, timetemp);
+ pdeNew->SetTime(WT_MODIFICATION, timetemp);
+ pdeNew->SetName(pdfn);
+
+ ReleaseEntry(sidNew);
+
+ // Insert new entry into the tree
+
+ msfChkTo(EH_Sid, InsertEntry(sidParent, sidNew, pdfn));
+ return(sc);
+
+EH_Sid:
+ // We were unable to insert the new entry (most likely because of a
+ // name conflict). Here we try to return the entry to the free list.
+ // If we can't, the only consequence is that we leak a dir entry on
+ // disk (128 bytes of disk space).
+
+ if (SUCCEEDED(GetDirEntry(sidNew, FB_DIRTY, &pdeNew)))
+ {
+ pdeNew->SetFlags(STGTY_INVALID);
+ ReleaseEntry(sidNew);
+
+ if (sidNew < _sidFirstFree)
+ {
+ _sidFirstFree = sidNew;
+ }
+ }
+
+Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::RenameEntry, public
+//
+// Synopsis: Rename an entry
+//
+// Arguments: [sidParent] -- Sid of parent of entry to be renamed
+// [pwcsName] -- Old name of entry to be renamed
+// [pwcsName] -- New name
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Remove old entry
+// Rename entry
+// Insert as new entry
+//
+// History: 10-Sep-92 PhilipLa Created.
+// 16-Nov-92 AlexT Binary tree structure
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_RenameEntry) // Dir_Rename_TEXT
+#endif
+
+SCODE DIR_CLASS CDirectory::RenameEntry(SID const sidParent,
+ CDfName const *pdfn,
+ CDfName const *pdfnNew)
+{
+ // Make sure new name doesn't already exist
+ SCODE sc;
+ SEntryBuffer eb;
+
+ sc = IsEntry(sidParent, pdfnNew, &eb);
+ if (sc != STG_E_FILENOTFOUND)
+ {
+ if (SUCCEEDED(sc))
+ {
+ // Entry did exist - fail this call
+ sc = STG_E_ACCESSDENIED;
+ }
+
+ return(sc);
+ }
+
+ // We can't just rename in place (because the tree is ordered)
+
+ CDirEntry *pdeRename;
+ SEntryBuffer ebRename;
+
+ msfChk(FindEntry(sidParent, pdfn, DEOP_REMOVE, &ebRename));
+
+ sc = GetDirEntry(ebRename.sid, FB_DIRTY, &pdeRename);
+
+ msfAssert(SUCCEEDED(sc) && aMsg("Could get dir entry to rename"));
+
+ msfChk(sc);
+
+ pdeRename->SetName(pdfnNew);
+
+ ReleaseEntry(ebRename.sid);
+
+ // If this InsertEntry fails, we've potentially lost the entry. This
+ // doesn't matter becase:
+ // a) The only way we could fail is if we couldn't read or write
+ // the disk (hard error)
+ // b) No one's going to call RenameEntry anyways
+ // c) If we're transacted, the whole operation is made robust by
+ // CopyOnWrite mode
+ // d) If we're direct, we already know we can fail in ways that leave
+ // the Docfile corrupt.
+
+ sc = InsertEntry(sidParent, ebRename.sid, pdfnNew);
+
+ msfAssert(SUCCEEDED(sc) && aMsg("Couldn't reinsert renamed dir entry"));
+
+ msfChk(sc);
+
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::DestroyAllChildren
+//
+// Synopsis: destroy all child entries
+//
+// Effects: destroys child tree
+//
+// Arguments: [sidParent] -- storage entry
+//
+// Returns: S_OK or error code
+//
+// Modifies: sidParent's entry
+//
+// Algorithm: While there's a child
+// destroy it
+//
+// History: 16-Nov-92 AlexT Created
+//
+// Notes: We may want to consider a more efficient implementation
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_DestroyAllChildren) // Dir_Destroy_TEXT
+#endif
+
+SCODE DIR_CLASS CDirectory::DestroyAllChildren(
+ SID const sidParent)
+{
+ SCODE sc;
+ CDirEntry *pdeParent, *pdeChild;
+ SID sidChild;
+ CDfName dfnChild;
+
+ for (;;)
+ {
+ CDfName dfnChild;
+
+ msfChk(GetDirEntry(sidParent, FB_NONE, &pdeParent));
+ sidChild = pdeParent->GetChild();
+ ReleaseEntry(sidParent);
+
+ if (sidChild == NOSTREAM)
+ break;
+
+ msfChk(GetDirEntry(sidChild, FB_NONE, &pdeChild));
+
+ dfnChild.Set(pdeChild->GetName());
+ ReleaseEntry(sidChild);
+
+ msfChk(DestroyChild(sidParent, &dfnChild));
+ }
+
+Err:
+ return(sc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::DestroyChild
+//
+// Synopsis: destroy a named child
+//
+// Effects: destroys named child's entry
+//
+// Arguments: [sidParent] -- storage entry
+// [pdfn] -- child name
+//
+// Returns: S_OK, STG_E_FILENOTFOUND, or other error code
+//
+// Modifies: child's entry
+//
+// Algorithm: Find and remove child
+// Free child entry
+//
+// History: 16-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_DestroyChild)
+#endif
+
+SCODE DIR_CLASS CDirectory::DestroyChild(
+ SID const sidParent,
+ CDfName const *pdfn)
+{
+ SCODE sc;
+ SEntryBuffer ebChild;
+
+ msfAssert(pdfn != NULL);
+
+ // Find the entry
+
+ msfChk(FindEntry(sidParent, pdfn, DEOP_FIND, &ebChild));
+
+ msfAssert(ebChild.sid != NOSTREAM);
+
+ // Before we remove this entry, we need to destroy it (including all
+ // its children). Note that we can't hold onto the entry because it
+ // might have children which get destroyed, which have children which
+ // get destroyed, etc.
+
+ if (STORAGELIKE(ebChild.dwType))
+ {
+ msfChk(DestroyAllChildren(ebChild.sid));
+ }
+
+ CDirEntry *pdeChild;
+ msfChk(GetDirEntry(ebChild.sid, FB_DIRTY, &pdeChild));
+
+ if (STREAMLIKE(ebChild.dwType))
+ {
+ // Deallocate any used streams
+ SECT sectStart = pdeChild->GetStart();
+ pdeChild->SetStart(ENDOFCHAIN);
+ msfChkTo(EH_Rel, _pmsParent->KillStream(sectStart,
+ pdeChild->GetSize()));
+ }
+
+ // remove the entry from the tree
+
+ msfChkTo(EH_Rel, FindEntry(sidParent, pdfn, DEOP_REMOVE, &ebChild));
+
+ pdeChild->SetFlags(STGTY_INVALID);
+ if (ebChild.sid < _sidFirstFree)
+ {
+ _sidFirstFree = ebChild.sid;
+ }
+
+EH_Rel:
+ ReleaseEntry(ebChild.sid);
+
+Err:
+ return(sc);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectory::StatEntry
+//
+// Synopsis: For a given handle, fill in the Multistream specific
+// information of a STATSTG.
+//
+// Arguments: [sid] -- SID that information is requested on.
+// [pib] -- Fast iterator buffer to fill in.
+// [pstatstg] -- STATSTG to fill in.
+//
+// Returns: Appropriate status code
+//
+// Algorithm: Fill in information
+//
+// History: 25-Mar-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_StatEntry) // Stat_TEXT
+#endif
+
+SCODE DIR_CLASS CDirectory::StatEntry(SID const sid,
+ SIterBuffer *pib,
+ STATSTGW *pstat)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfAssert(pib == NULL || pstat == NULL);
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+
+ if (pib)
+ {
+ pib->dfnName.Set(pde->GetName());
+ pib->type = pde->GetFlags();
+ }
+ else
+ {
+ pstat->type = pde->GetFlags();
+
+ if (pde->GetName()->GetLength() > CBSTORAGENAME)
+ olChkTo (EH_Rel, STG_E_DOCFILECORRUPT);
+
+ msfMemTo(EH_Rel, pstat->pwcsName =
+ (WCHAR *)TaskMemAlloc(pde->GetName()->GetLength()));
+ memcpy(pstat->pwcsName, pde->GetName()->GetBuffer(),
+ pde->GetName()->GetLength());
+
+ pstat->ctime = pde->GetTime(WT_CREATION);
+ pstat->mtime = pde->GetTime(WT_MODIFICATION);
+ // Don't currently keep access times
+ pstat->atime = pstat->mtime;
+
+ // Don't use REAL_STGTY here because we want this
+ // to function properly for both property and non-property builds
+ if ((pstat->type & STGTY_REAL) == STGTY_STORAGE)
+ {
+ ULISet32(pstat->cbSize, 0);
+ pstat->clsid = pde->GetClassId();
+ pstat->grfStateBits = pde->GetUserFlags();
+ }
+ else
+ {
+ ULISet32(pstat->cbSize, pde->GetSize());
+ pstat->clsid = CLSID_NULL;
+ pstat->grfStateBits = 0;
+ }
+ }
+
+EH_Rel:
+ ReleaseEntry(sid);
+
+Err:
+ return sc;
+}
+
+#ifdef CHKDSK
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::InitCorrupted, public
+//
+// Synposis: Sets up a Directory instance and reads in all tables
+// from a corrupted stream.
+//
+// Arguments: [pmsParent] -- Pointer to parent Mstream
+//
+// Returns: S_OK.
+//
+// Algorithm: Determine number of tables needed by querying FAT.
+// Resize array to hold appropriate number of tables.
+// Read in each table from disk.
+// Set parent pointer.
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 24-Aug-92 t-chrisy copied from Init routine
+// force corrupted dir object to instantiate.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE DIR_CLASS CDirectory::InitCorrupted(DIRINDEX cSect)
+{
+ msfDebugOut((DEB_DIR,"In CDirectory::setup(%lu)\n",cSect));
+ SCODE sc;
+
+ _cdeEntries = _pmsParent->GetSectorSize() / sizeof(CDirEntry);
+
+ _dv.InitCommon(_pmsParent->GetSectorSize());
+ sc = _dv.Init(_pmsParent, 1));
+
+ if (FAILED(sc))
+ msfDebugOut((DEB_DIR,"Error in CDirVector::Init. Cannot recover\n"));
+
+ _cdsTable = cSect;
+
+ DIRINDEX i;
+ for (i = 0; i < cSect; i++)
+ {
+ ULONG ulRetval;
+ CDirEntry *pds;
+ msfChk(_dv.GetBlock(i, &pds));
+ sc = _pmsParent->ReadSect(SIDDIR,i,pds,ulRetval);
+ if (!FAILED(sc))
+ {
+ if (ulRetval != _pmsParent->GetSectorSize())
+ msfDebugOut((DEB_DIR, "STG_E_READFAULT\n"));
+ }
+ }
+ msfDebugOut((DEB_DIR,"Out CDirectory::setup()\n"));
+ sc = S_OK;
+
+ Err:
+ return sc;
+}
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::GetDirEntry
+//
+// Synopsis: Get a directory entry with given permissions
+//
+// Arguments: [sid] -- SID
+// [dwFlags] -- permissions
+// [ppde] -- placeholder for directory entry
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm:
+//
+// History: ??-???-?? PhilipLa Created.
+// 19-Jan-93 AlexT Made non-inline for code savings
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_GetDirEntry) //
+#endif
+
+
+SCODE DIR_CLASS CDirectory::GetDirEntry(
+ const SID sid,
+ const DWORD dwFlags,
+ CDirEntry **ppde)
+{
+ SCODE sc;
+ CDirSect *pds;
+ DIRINDEX id;
+
+#ifdef _M_I286
+ // Optimization for common case
+ if (4 == _cdeEntries)
+ {
+ id = sid >> 2;
+
+ msfChk(_dv.GetTable(id, dwFlags, &pds));
+
+ *ppde = pds->GetEntry((DIROFFSET)(sid & 0x3));
+ }
+ else
+#endif
+ {
+ id = sid / _cdeEntries;
+
+ msfChk(_dv.GetTable(id, dwFlags, &pds));
+
+ *ppde = pds->GetEntry((DIROFFSET)(sid % _cdeEntries));
+ }
+
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::ReleaseEntry
+//
+// Synopsis: Releases a directory entry
+//
+// Arguments: [sid] -- SID
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm:
+//
+// History: ??-???-?? PhilipLa Created.
+// 19-Jan-93 AlexT Made non-inline for code savings
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_ReleaseEntry)
+#endif
+
+void DIR_CLASS CDirectory::ReleaseEntry(SID sid)
+{
+#ifdef _M_I286
+ // Optimization for common case
+ if (4 == _cdeEntries)
+ {
+ _dv.ReleaseTable(sid >> 2);
+ }
+ else
+#endif
+ {
+ _dv.ReleaseTable(sid / _cdeEntries);
+ }
+}
diff --git a/private/ole32/stg/msf/dirp.cxx b/private/ole32/stg/msf/dirp.cxx
new file mode 100644
index 000000000..78616cb7f
--- /dev/null
+++ b/private/ole32/stg/msf/dirp.cxx
@@ -0,0 +1,921 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: DirP.CXX
+//
+// Contents: Private CDirectory child tree methods
+//
+// History: 17-Nov-92 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+#pragma hdrstop
+
+
+#include <dirfunc.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::InsertEntry, private
+//
+// Synopsis: insert entry into child tree
+//
+// Arguments: [sidTree] -- storage entry in which to insert entry
+// [sidNew] -- new entry
+// [pdfnNew] -- new entry name
+//
+// Returns: S_OK, STG_E_FILEALREADYEXISTS, or other error
+//
+// Modifies: sidParent's child tree
+//
+// Algorithm: Search down the binary tree to find the leaf node to which
+// to add the new entry (failing if we find the name already
+// exists). Along the way we split nodes where needed to keep
+// the tree balanced.
+//
+// History: 16-Nov-92 AlexT Created
+// 18-Nov-92 AlexT Balanced tree
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_InsertEntry)
+#endif
+
+SCODE DIR_CLASS CDirectory::InsertEntry(
+ SID sidTree,
+ SID sidNew,
+ CDfName const *pdfnNew)
+{
+ SCODE sc;
+
+ // To insert the key and keep the tree balanced, we need to know
+ // the parent, grandparent, and greatgrandparent of the node we're
+ // inserting.
+
+ SID sidChild, sidParent, sidGrandParent, sidGreatGrandParent;
+ CDirEntry *pdeParent;
+ int iCmp;
+
+ // When we're ready to insert, sidParent will be the entry to which we
+ // attach sidNew
+
+ sidParent = sidGrandParent = sidGreatGrandParent = sidTree;
+
+ // Begin the search with the root of the child tree
+
+ msfChk(GetDirEntry(sidTree, FB_NONE, &pdeParent));
+ sidChild = pdeParent->GetChild();
+
+ // Search down the child tree to find the correct leaf entry
+
+ while (sidChild != NOSTREAM)
+ {
+ // The sidParent entry has a child along the search path, so we
+ // move down the tree (letting go of sidParent and taking hold of
+ // its child)
+
+ ReleaseEntry(sidParent);
+
+ // Check to see if we need to split this node (nothing is held)
+
+ do
+ {
+ SID sidLeft, sidRight;
+ BOOL fRed;
+
+ {
+ CDirEntry *pdeChild;
+
+ msfChk(GetDirEntry(sidChild, FB_NONE, &pdeChild));
+
+ msfAssert(((sidTree != sidParent) ||
+ (pdeChild->GetColor() == DE_BLACK)) &&
+ aMsg("Dir tree corrupt - root child not black!"));
+
+ sidLeft = pdeChild->GetLeftSib();
+ sidRight = pdeChild->GetRightSib();
+
+ ReleaseEntry(sidChild);
+ }
+
+ if (sidLeft == NOSTREAM || sidRight == NOSTREAM)
+ break;
+
+ {
+ CDirEntry *pdeLeft;
+
+ msfChk(GetDirEntry(sidLeft, FB_NONE, &pdeLeft));
+ fRed = (pdeLeft->GetColor() == DE_RED);
+ ReleaseEntry(sidLeft);
+ }
+
+ if (!fRed)
+ break;
+
+ {
+ CDirEntry *pdeRight;
+
+ msfChk(GetDirEntry(sidRight, FB_NONE, &pdeRight));
+ fRed = (pdeRight->GetColor() == DE_RED);
+ ReleaseEntry(sidRight);
+ }
+
+ if (fRed)
+ msfChk(SplitEntry(pdfnNew, sidTree, sidGreatGrandParent,
+ sidGrandParent, sidParent, sidChild,
+ &sidChild));
+ }
+ while (FALSE);
+
+ //
+
+ msfAssert(sidChild != NOSTREAM);
+
+ // Advance the search
+
+ sidGreatGrandParent = sidGrandParent;
+ sidGrandParent = sidParent;
+ sidParent = sidChild;
+
+ msfChk(GetDirEntry(sidParent, FB_NONE, &pdeParent));
+
+ iCmp = NameCompare(pdfnNew, pdeParent->GetName());
+
+ if (iCmp == 0)
+ {
+ // The new name exactly matched an existing name. Fail.
+ msfChkTo(EH_RelParent, STG_E_FILEALREADYEXISTS);
+ }
+
+ // Move down the tree, left or right depending on the comparison
+
+ if (iCmp < 0)
+ sidChild = pdeParent->GetLeftSib();
+ else
+ sidChild = pdeParent->GetRightSib();
+ }
+
+ msfAssert(sidChild == NOSTREAM);
+
+ // We've found the position to insert the new entry.
+
+ // We're going to dirty sidParent, so we need to change our holding flags
+ ReleaseEntry(sidParent);
+ msfChk(GetDirEntry(sidParent, FB_DIRTY, &pdeParent));
+
+ if (sidParent == sidTree)
+ {
+ // sidParent never made it past sidTree - we must be inserting the
+ // first child into sidTree
+
+ msfAssert(pdeParent->GetChild() == NOSTREAM);
+
+ // The SplitInsert call below will make sidNew black.
+ pdeParent->SetChild(sidNew);
+ }
+ else
+ {
+ msfAssert(iCmp != 0);
+
+ // Use the comparison to determine which side to insert the new entry
+
+ if (iCmp < 0)
+ {
+ msfAssert(pdeParent->GetLeftSib() == NOSTREAM);
+ msfAssert(NameCompare(pdfnNew, pdeParent->GetName()) < 0);
+
+ pdeParent->SetLeftSib(sidNew);
+ }
+ else
+ {
+ msfAssert(pdeParent->GetRightSib() == NOSTREAM);
+ msfAssert(NameCompare(pdfnNew, pdeParent->GetName()) > 0);
+
+ pdeParent->SetRightSib(sidNew);
+ }
+ }
+
+EH_RelParent:
+ ReleaseEntry(sidParent);
+
+ if (SUCCEEDED(sc))
+ {
+ SID sidTemp;
+ sc = SplitEntry(pdfnNew, sidTree, sidGreatGrandParent, sidGrandParent,
+ sidParent, sidNew, &sidTemp);
+ }
+Err:
+ return(sc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SplitEntry, private
+//
+// Synopsis: Split 4-node
+//
+// Effects: Passes up red link to parent
+//
+// Arguments: [pdfn] -- search key
+// [sidTree] -- child tree sid
+// [sidGreat] -- greatgrandparent of child to split
+// [sidGrand] -- grandparent of child to split
+// [sidParent] -- parent of child to split
+// [sidChild] -- child to split
+// [psid] -- place holder for tree position
+//
+// Returns: S_OK, or error
+//
+// Modifies: psid, tree
+//
+// Algorithm:
+//
+// History: 18-Nov-92 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_SplitEntry)
+#endif
+
+SCODE CDirectory::SplitEntry(
+ CDfName const *pdfn,
+ SID sidTree,
+ SID sidGreat,
+ SID sidGrand,
+ SID sidParent,
+ SID sidChild,
+ SID *psid)
+{
+ SCODE sc;
+ CDirEntry *pdeChild;
+ SID sidLeft, sidRight;
+
+ // pn is a 4-node; start split by moving red link up
+
+ // pn->GetLeft()->SetColor(BLACK);
+
+ msfChk(GetDirEntry(sidChild, FB_DIRTY, &pdeChild));
+ sidLeft = pdeChild->GetLeftSib();
+ sidRight = pdeChild->GetRightSib();
+
+ // The root must always be black; new non-root children are red
+ pdeChild->SetColor((sidParent == sidTree) ? DE_BLACK : DE_RED);
+
+ ReleaseEntry(sidChild);
+
+ if (sidLeft != NOSTREAM)
+ {
+ msfChk(SetColorBlack(sidLeft));
+ }
+
+ // pn->GetRight()->SetColor(BLACK);
+
+ if (sidRight != NOSTREAM)
+ {
+ msfChk(SetColorBlack(sidRight));
+ }
+
+ if (sidParent != sidTree)
+ {
+ CDirEntry *pdeParent;
+ BOOL fRedParent;
+ int iCmpParent;
+
+ msfChk(GetDirEntry(sidParent, FB_NONE, &pdeParent));
+
+ fRedParent = (pdeParent->GetColor() == DE_RED);
+
+ if (fRedParent)
+ iCmpParent = NameCompare(pdfn, pdeParent->GetName());
+
+ ReleaseEntry(sidParent);
+
+ // if (pnp->IsRed())
+
+ if (fRedParent)
+ {
+ int iCmpGrand;
+
+ // parent is red - adjacent red links are not allowed
+
+ // Note - grandparent may be sidTree
+
+ if (sidGrand == sidTree)
+ {
+ iCmpGrand = 1;
+ }
+ else
+ {
+ CDirEntry *pdeGrand;
+ msfChk(GetDirEntry(sidGrand, FB_DIRTY, &pdeGrand));
+
+ iCmpGrand = NameCompare(pdfn, pdeGrand->GetName());
+
+ // png->SetColor(RED);
+ pdeGrand->SetColor(DE_RED);
+
+ ReleaseEntry(sidGrand);
+ }
+
+ // if ((ikey < png->GetKey()) != (ikey < pnp->GetKey()))
+
+ if ((iCmpGrand < 0) != (iCmpParent < 0))
+ {
+ /* two cases:
+ //
+ // | |
+ // g g
+ // / \
+ // p p
+ // \ /
+ // x x
+ //
+ // the red links are oriented differently
+ */
+
+ // pn = Rotate(ikey, png);
+ msfChk(RotateEntry(pdfn, sidTree, sidGrand, &sidChild));
+
+ /*
+ // | |
+ // g g
+ // / \
+ // x x
+ // / \
+ // p p
+ */
+ }
+
+ // the red links are now oriented the same - we balance the tree
+ // by rotating
+
+ // pn = Rotate(ikey, pngg);
+ msfChk(RotateEntry(pdfn, sidTree, sidGreat, &sidChild));
+
+ // pn->SetColor(BLACK);
+ msfAssert(sidChild != sidTree);
+ msfChk(SetColorBlack(sidChild));
+ }
+ }
+
+ // return(pn);
+ *psid = sidChild;
+
+ // The first node's link must always be black.
+#if DBG == 1
+ CDirEntry *pdeTree;
+ msfChk(GetDirEntry(sidTree, FB_NONE, &pdeTree));
+ sidChild = pdeTree->GetChild();
+ ReleaseEntry(sidTree);
+
+ msfChk(GetDirEntry(sidChild, FB_NONE, &pdeChild));
+ msfAssert(pdeChild->GetColor() == DE_BLACK);
+ ReleaseEntry(sidChild);
+#endif
+
+Err:
+ return(sc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::RotateEntry
+//
+// Synopsis: rotation for balancing
+//
+// Effects: rotates localized portion of child tree
+//
+// Arguments: [pdfn] -- search key
+// [sidTree] -- child tree sid
+// [sidParent] -- root of rotation
+// [psid] -- placeholder for root after rotation
+//
+// Returns: S_OK, or error
+//
+// Modifies: child tree
+//
+// Algorithm:
+//
+// History: 17-Nov-92 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_RotateEntry)
+#endif
+
+SCODE CDirectory::RotateEntry(
+ CDfName const *pdfn,
+ SID sidTree,
+ SID sidParent,
+ SID *psid)
+{
+ SCODE sc;
+ int iCmp;
+ // PNODE pnc, pngc;
+ SID sidChild, sidGrand;
+
+ // find the child
+
+ CDirEntry *pdeParent, *pdeChild, *pdeGrand;
+ msfChk(GetDirEntry(sidParent, FB_DIRTY, &pdeParent));
+
+ if (sidParent == sidTree)
+ {
+ sidChild = pdeParent->GetChild();
+ }
+ else
+ {
+ iCmp = NameCompare(pdfn, pdeParent->GetName());
+
+ if (iCmp < 0)
+ sidChild = pdeParent->GetLeftSib();
+ else
+ sidChild = pdeParent->GetRightSib();
+ }
+
+ // find the grandchild
+
+ msfChkTo(EH_RelParent, GetDirEntry(sidChild, FB_DIRTY, &pdeChild));
+ msfAssert(sidChild != sidTree);
+
+ iCmp = NameCompare(pdfn, pdeChild->GetName());
+
+ if (iCmp < 0)
+ {
+ // pngc = pnc->GetLeft();
+ sidGrand = pdeChild->GetLeftSib();
+
+ msfChkTo(EH_RelChild, GetDirEntry(sidGrand, FB_DIRTY, &pdeGrand));
+
+ /*
+ // |
+ // c
+ // / \
+ // / \
+ // g X
+ // \
+ // Y
+ */
+
+ // pnc->SetLeft(pngc->GetRight());
+ pdeChild->SetLeftSib(pdeGrand->GetRightSib());
+
+ /*
+ // |
+ // c
+ // / \
+ // | \
+ // g | X
+ // \|
+ // Y
+ */
+
+ // pngc->SetRight(pnc);
+ pdeGrand->SetRightSib(sidChild);
+
+ /*
+ // g
+ // \
+ // \|
+ // c
+ // / \
+ // | \
+ // | X
+ // |
+ // Y
+ */
+ }
+ else
+ {
+ // pngc = pnc->GetRight();
+ sidGrand = pdeChild->GetRightSib();
+
+ msfChkTo(EH_RelChild, GetDirEntry(sidGrand, FB_DIRTY, &pdeGrand));
+
+ // pnc->SetRight(pngc->GetLeft());
+ pdeChild->SetRightSib(pdeGrand->GetLeftSib());
+
+ // pngc->SetLeft(pnc);
+ pdeGrand->SetLeftSib(sidChild);
+ }
+
+
+ // update parent
+
+ if (sidParent == sidTree)
+ {
+ // The root must always be black
+ pdeGrand->SetColor(DE_BLACK);
+ pdeParent->SetChild(sidGrand);
+ }
+ else
+ {
+ iCmp = NameCompare(pdfn, pdeParent->GetName());
+
+ if (iCmp < 0)
+ {
+ // pnp->SetLeft(pngc);
+ pdeParent->SetLeftSib(sidGrand);
+ }
+ else
+ {
+ // pnp->SetRight(pngc);
+ pdeParent->SetRightSib(sidGrand);
+ }
+ }
+
+ ReleaseEntry(sidGrand);
+
+ /*
+ // |
+ // g
+ // \
+ // \
+ // c
+ // / \
+ // | \
+ // | X
+ // |
+ // Y
+ */
+
+ // return(pngc);
+ *psid = sidGrand;
+
+EH_RelChild:
+ ReleaseEntry(sidChild);
+
+EH_RelParent:
+ ReleaseEntry(sidParent);
+
+Err:
+ return(sc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::FindEntry, private
+//
+// Synopsis: find entry info based on name (optionally removing it)
+//
+// Effects: find - none, remove - takes entry out of child list
+//
+// Arguments: [sidParent] -- sid of parent entry to search
+// [pdfn] -- name to search for
+// [deop] -- entry operation (find or remove)
+// [peb] -- entry information buffer
+//
+// Returns: S_OK, STG_E_FILENOTFOUND, or other error
+//
+// Modifies: peb
+//
+// Algorithm: To find the entry we search down the binary tree.
+// To remove the entry, we need to patch the tree to keep it
+// as a valid binary tree.
+//
+// History: 16-Nov-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_FindEntry)
+#endif
+
+SCODE DIR_CLASS CDirectory::FindEntry(
+ SID sidParent,
+ CDfName const *pdfn,
+ DIRENTRYOP deop,
+ SEntryBuffer *peb)
+{
+ SCODE sc;
+ SID sidPrev, sidFind;
+ CDirEntry *pdePrev, *pdeFind;
+ int iCmp;
+
+ // Once we've found the right child, sidPrev will be that entry's parent
+ // in the child tree
+
+ sidPrev = sidParent;
+
+ // Begin the search with the root of the child tree
+
+ msfChk(GetDirEntry(sidPrev, FB_NONE, &pdePrev));
+ sidFind = pdePrev->GetChild();
+
+ // sidPrev is held
+
+ for(;;)
+ {
+ if (sidFind == NOSTREAM)
+ {
+ // we didn't find the child. fail.
+ sc = STG_E_FILENOTFOUND;
+ goto EH_RelPrev;
+// Removed this line to supress the debug error print.
+// msfChkTo(EH_RelPrev, STG_E_FILENOTFOUND);
+ }
+
+ msfChkTo(EH_RelPrev, GetDirEntry(sidFind, FB_NONE, &pdeFind));
+
+ // sidPrev and sidFind are held
+
+ int tmpCmp = NameCompare(pdfn, pdeFind->GetName());
+
+ if (tmpCmp == 0)
+ {
+ // We found the entry that matches our search name
+ break;
+ }
+
+ // The names did not match. Advance the search down the tree.
+ ReleaseEntry(sidPrev);
+ pdePrev = pdeFind;
+ sidPrev = sidFind;
+
+ // sidPrev is held
+
+ // remember the comparison with sidPrev so we can use it to insert
+ // an entry when we patch the tree
+
+ iCmp = tmpCmp;
+
+ if (iCmp < 0)
+ sidFind = pdePrev->GetLeftSib();
+ else
+ sidFind = pdePrev->GetRightSib();
+ }
+
+ msfAssert(sidFind != NOSTREAM);
+
+ // sidFind is held
+ // sidPrev is held
+
+ msfAssert(NameCompare(pdfn, pdeFind->GetName()) == 0);
+
+ // fill in entry information
+
+ peb->sid = sidFind;
+ peb->dwType = pdeFind->GetFlags();
+ peb->luid = DF_NOLUID;
+
+ if (deop == DEOP_REMOVE)
+ {
+ ReleaseEntry(sidFind);
+ ReleaseEntry(sidPrev);
+
+ msfChk(GetDirEntry(sidPrev, FB_DIRTY, &pdePrev));
+ msfChkTo(EH_RelPrev, GetDirEntry(sidFind, FB_DIRTY, &pdeFind));
+
+ // Remove the found child from tree (carefully!). We remove it by
+ // finding another entry in the tree with which to replace it.
+ // sidFind is the node we're removing
+ // sidPrev is the parent of sidFind in the child tree
+ // sidInsert is the entry which will replace sidFind
+
+ SID sidInsert = pdeFind->GetRightSib();
+
+ if (sidInsert == NOSTREAM)
+ {
+ // sidFind has no right child, so we can patch the tree by
+ // replacing sidFind with the sidFind's left child
+
+ sidInsert = pdeFind->GetLeftSib();
+
+ // set the inserted to the right color
+ if (sidInsert != NOSTREAM)
+ {
+ // we always set the inserted node to black (since the
+ // parent may not exist (we could be inserting at the
+ // root)
+ msfChkTo(EH_RelPrev, SetColorBlack(sidInsert));
+ }
+ }
+ else
+ {
+ CDirEntry *pdeInsert;
+
+ // The node we're removing has a right child
+
+ msfChkTo(EH_RelFind, GetDirEntry(sidInsert, FB_NONE, &pdeInsert));
+
+ // sidPrev, sidFind, and sidInsert are all held
+
+ if (pdeInsert->GetLeftSib() != NOSTREAM)
+ {
+ // sidFind's right child has a left child.
+ // sidInsert will be the leftmost child of sidFind's right
+ // child (which will keep the tree ordered)
+
+ // sidPreInsert will be the leftmost child's parent int the
+ // child tree
+
+ SID sidPreInsert = sidInsert;
+ CDirEntry *pdePreInsert = pdeInsert;
+
+ // we wait to assign sidInsert so we can clean up
+ msfChkTo(EH_RelIns, GetDirEntry(pdePreInsert->GetLeftSib(),
+ FB_NONE, &pdeInsert));
+
+ sidInsert = pdePreInsert->GetLeftSib();
+
+ // sidPrev, sidFind, sidPreInsert, sidInsert are held
+
+ // find the leftmost child of sidFind's right child
+
+ SID sidLeft;
+ while ((sidLeft = pdeInsert->GetLeftSib()) != NOSTREAM)
+ {
+ ReleaseEntry(sidPreInsert);
+
+ // sidPrev, sidFind, sidInsert are held
+
+ sidPreInsert = sidInsert;
+ pdePreInsert = pdeInsert;
+
+ // we wait to assign sidInsert to we can clean up
+ msfChkTo(EH_RelIns, GetDirEntry(sidLeft,
+ FB_NONE, &pdeInsert));
+
+ sidInsert = sidLeft;
+ }
+
+ msfAssert(pdeInsert->GetLeftSib() == NOSTREAM);
+
+ // sidPrev, sidFind, sidPreInsert, sidInsert are held
+
+ // Remove sidInsert so we can reinsert it in place of sidFind.
+ // We remove sidInsert (which has no left child) by making
+ // sidPreInsert's left child point to sidInsert's right child
+
+ ReleaseEntry(sidPreInsert);
+ msfChkTo(EH_RelIns, GetDirEntry(sidPreInsert, FB_DIRTY,
+ &pdePreInsert));
+
+ pdePreInsert->SetLeftSib(pdeInsert->GetRightSib());
+ ReleaseEntry(sidPreInsert);
+
+ // sidPrev, sidFind, sidInsert is held
+
+ // Begin to replace sidFind with sidInsert by setting the
+ // right child of sidInsert to be the right child of sidFind
+
+ ReleaseEntry(sidInsert);
+ msfChkTo(EH_RelFind, GetDirEntry(sidInsert, FB_DIRTY,
+ &pdeInsert));
+ pdeInsert->SetRightSib(pdeFind->GetRightSib());
+ }
+ else
+ {
+ // sidFind's right child has no left child, so we can patch
+ // the tree by making sidFind's right child's left child
+ // point to sidFind's left child, and then replacing sidFind
+ // with sidFind's right child.
+
+ ReleaseEntry(sidInsert);
+ msfChkTo(EH_RelFind, GetDirEntry(sidInsert, FB_DIRTY,
+ &pdeInsert));
+
+ // fall through to do the work
+ }
+
+ pdeInsert->SetColor(DE_BLACK);
+
+ // Complete sidInsert's patching by setting its left child to be
+ // the left child of sidFind
+
+ pdeInsert->SetLeftSib(pdeFind->GetLeftSib());
+
+EH_RelIns:
+ ReleaseEntry(sidInsert);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ if (sidPrev == sidParent)
+ {
+ // We're removing the first child; update sidParent.
+ // We made sure sidInsert is black (above).
+ pdePrev->SetChild(sidInsert);
+ }
+ else if (iCmp < 0)
+ {
+ pdePrev->SetLeftSib(sidInsert);
+ }
+ else
+ pdePrev->SetRightSib(sidInsert);
+
+ // make sure sidFind is clean
+
+ pdeFind->SetLeftSib(NOSTREAM);
+ pdeFind->SetRightSib(NOSTREAM);
+ }
+ }
+
+EH_RelFind:
+ ReleaseEntry(sidFind);
+
+EH_RelPrev:
+ ReleaseEntry(sidPrev);
+
+Err:
+ return(sc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::NameCompare, private static
+//
+// Synopsis: name ordering function for child tree
+//
+// Arguments: [pdfn1] - name 1
+// [pdfn2] - name 2
+//
+// Requires: One but not both names cannot may have zero length.
+//
+// Returns: <0 if name 1 < name 2
+// 0 if name 1 = name 2
+// >0 if name 1 > name 2
+//
+// Algorithm: To speed the comparision (and to allow zero length names),
+// we first compare the name lengths. (Shorter names are "less"
+// than longer names). If the lengths are equal we compare the
+// strings.
+//
+// History: 16-Nov-92 AlexT Created
+//
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_NameCompare)
+#endif
+
+int CDirectory::NameCompare(CDfName const *pdfn1, CDfName const *pdfn2)
+{
+ int iCmp = pdfn1->GetLength() - pdfn2->GetLength();
+
+ if (iCmp == 0)
+ {
+ msfAssert(pdfn1->GetLength() != 0);
+#ifndef FLAT
+#ifdef CASE_SENSITIVE
+ iCmp = memcmp(pdfn1->GetBuffer(), pdfn2->GetBuffer(), pdfn1->GetLength());
+#else
+ iCmp = dfwcsnicmp((WCHAR *)pdfn1->GetBuffer(),
+ (WCHAR *)pdfn2->GetBuffer(), pdfn1->GetLength());
+#endif
+#else
+ iCmp = dfwcsnicmp((WCHAR *)pdfn1->GetBuffer(),
+ (WCHAR *)pdfn2->GetBuffer(), pdfn1->GetLength());
+#endif
+ }
+
+ return(iCmp);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectory::SetColorBlack, private
+//
+// Synopsis: Sets a directory entry to black
+//
+// Arguments: [sid] -- SID of entry to be modified
+//
+// Returns: S_OK or error
+//
+// History: 19-Jan-93 AlexT Created.
+//
+// Notes: Added to reduce code size
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectory_SetColorBlack)
+#endif
+
+SCODE DIR_CLASS CDirectory::SetColorBlack(const SID sid)
+{
+ SCODE sc;
+
+ CDirEntry *pde;
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+
+ pde->SetColor(DE_BLACK);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
diff --git a/private/ole32/stg/msf/dirs b/private/ole32/stg/msf/dirs
new file mode 100644
index 000000000..4c50c7cc4
--- /dev/null
+++ b/private/ole32/stg/msf/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/stg/msf/dl.cxx b/private/ole32/stg/msf/dl.cxx
new file mode 100644
index 000000000..352d78f9a
--- /dev/null
+++ b/private/ole32/stg/msf/dl.cxx
@@ -0,0 +1,1200 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dl.cxx
+//
+// Contents: Delta list code for streams
+//
+// Classes: Defined in dl.hxx
+//
+// History: 28-Jul-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+#pragma hdrstop
+
+#include <mread.hxx>
+#include <dl.hxx>
+#include <tstream.hxx>
+
+#ifndef _MAC
+inline
+#endif
+void *SDeltaBlock::operator new(size_t size, IMalloc * const pMalloc)
+{
+ return pMalloc->Alloc(size);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: SDeltaBlock::SDeltaBlock, public
+//
+// Synopsis: SDeltaBlock constructor
+//
+// History: 10-Jul-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_SDeltaBlock_SDeltaBlock)
+#endif
+
+#ifndef _MAC
+inline
+#endif
+SDeltaBlock::SDeltaBlock()
+{
+ for (USHORT i = 0; i < CSECTPERBLOCK; i++)
+ {
+ _sect[i] = ENDOFCHAIN;
+ }
+ for (i = 0; i < CSECTPERBLOCK / CBITPERUSHORT; i++)
+ {
+ _fOwn[i] = 0;
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDeltaList::CDeltaList, public
+//
+// Synopsis: CDeltaList constructor
+//
+// History: 21-Jan-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_CDeltaList)
+#endif
+
+#ifdef USE_NOSCRATCH
+CDeltaList::CDeltaList(CMStream *pms, CMStream *pmsScratch)
+#else
+CDeltaList::CDeltaList(CMStream *pmsScratch)
+#endif
+{
+#ifdef USE_NOSCRATCH
+ _pms = P_TO_BP(CBasedMStreamPtr, pms);
+#endif
+ _pmsScratch = P_TO_BP(CBasedMStreamPtr, pmsScratch);
+ _apdb = NULL;
+ _sectStart = ENDOFCHAIN;
+ _ulSize = 0;
+ _ptsParent = NULL;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_GetNewDeltaArray)
+#endif
+
+inline CBasedDeltaBlockPtr * CDeltaList::GetNewDeltaArray(ULONG ulSize)
+{
+// return NULL;
+ msfAssert(ulSize > 0);
+ if (ulSize > (_HEAP_MAXREQ / sizeof(SDeltaBlock *)))
+ {
+ return NULL;
+ }
+ return (CBasedDeltaBlockPtr *) _pmsScratch->GetMalloc()->
+ Alloc(sizeof(SDeltaBlock *) * ulSize);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDeltaList::Init, public
+//
+// Synopsis: Init function for CDeltaList
+//
+// Arguments: [ulSize] -- Size of delta list to be initialized
+// [ptsParent] -- Pointer to transacted stream that contains
+// this delta list.
+//
+// Returns: S_OK if call completed successfully.
+//
+// Algorithm: *Finish This*
+//
+// History: 21-Jan-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_Init)
+#endif
+
+SCODE CDeltaList::Init(ULONG ulSize, CTransactedStream *ptsParent)
+{
+ SCODE sc = S_OK;
+ ULONG ulNewSize;
+ CBasedDeltaBlockPtr *apdbTemp = NULL;
+
+ msfAssert(IsEmpty() &&
+ aMsg("Init called on non-empty delta list."));
+
+ ULONG cbSector = GetDataSectorSize();
+
+ ULONG csect = (ulSize + cbSector - 1) / cbSector;
+
+
+ ulNewSize = (csect + CSECTPERBLOCK - 1) / CSECTPERBLOCK;
+
+ _ulSize = ulNewSize;
+ _ptsParent = P_TO_BP(CBasedTransactedStreamPtr, ptsParent);
+
+ CDeltaList *pdlParent = NULL;
+
+ if (_ptsParent->GetBase() != NULL)
+ {
+ pdlParent = _ptsParent->GetBase()->GetDeltaList();
+ }
+
+ msfAssert(_ulSize > 0);
+ msfAssert(IsEmpty());
+
+ //BUGBUG: This handles the case where the parent is NULL or
+ // is InMemory. Should we try to create an InMemory delta-list
+ // if the parent is InStream?
+ if ((pdlParent == NULL) || (pdlParent->IsInMemory()))
+ {
+ //Try to copy it down. If it doesn't work, put it in a stream
+ //instead.
+ msfMem(apdbTemp = GetNewDeltaArray(_ulSize));
+
+ MAXINDEXTYPE i;
+ for (i = 0; i < _ulSize; i++)
+ {
+ apdbTemp[i] = NULL;
+ }
+
+ if (pdlParent != NULL)
+ {
+ for (i = 0; i < _ulSize; i++)
+ {
+ if ((i < pdlParent->_ulSize) && (pdlParent->_apdb[i] != NULL))
+ {
+ SDeltaBlock *pdbTemp;
+ msfMemTo(Err_Alloc, pdbTemp =
+ new(_pmsScratch->GetMalloc()) SDeltaBlock);
+
+ apdbTemp[i] = P_TO_BP(CBasedDeltaBlockPtr, pdbTemp);
+
+ for (USHORT j = 0; j < CSECTPERBLOCK; j++)
+ {
+ pdbTemp->_sect[j] = pdlParent->_apdb[i]->_sect[j];
+ }
+ }
+ }
+ }
+ _apdb = P_TO_BP(CBasedDeltaBlockPtrPtr, apdbTemp);
+
+ return S_OK;
+
+ Err_Alloc:
+ for (i = 0; i < _ulSize; i++)
+ {
+ _pmsScratch->GetMalloc()->Free(BP_TO_P(SDeltaBlock *, apdbTemp[i]));
+ apdbTemp[i] = NULL;
+ }
+ }
+
+
+ Err:
+ _apdb = NULL;
+
+ //We'll end up here if we get an error allocating memory for
+ // the InMemory case above or if the parent is InStream. We
+ // must allocate a new stream and copy down the parent.
+ if (pdlParent == NULL)
+ {
+ for (ULONG i = 0; i < _ulSize; i++)
+ {
+ msfChkTo(Err_Init, InitStreamBlock(i));
+ }
+ }
+ else
+ {
+ //Copy the parent into a stream representation.
+
+ for (ULONG i = 0;
+ i < min(_ulSize, pdlParent->_ulSize) * CSECTPERBLOCK;
+ i++)
+ {
+ SECT sectOld;
+ msfChkTo(Err_Init, pdlParent->GetMap(i, DL_READ, &sectOld));
+ msfChkTo(Err_Init, WriteMap(&_sectStart, i, sectOld));
+ }
+ for (i = pdlParent->_ulSize; i < _ulSize; i++)
+ {
+ msfChkTo(Err_Init, InitStreamBlock(i));
+ }
+ }
+
+
+ Err_Init:
+ return sc;
+
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDeltaList::InitResize, public
+//
+// Synopsis: Resize initializer for deltalists
+//
+// Arguments: [ulSize] -- Size of new deltalist
+// [pdlOld] -- Pointer to deltalist to be resized
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: *Finish This*
+//
+// History: 21-Jan-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_InitResize)
+#endif
+
+SCODE CDeltaList::InitResize(ULONG ulSize)
+{
+ msfDebugOut((DEB_ITRACE,"In CDeltaList copy constructor\n"));
+ SCODE sc = S_OK;
+ CBasedDeltaBlockPtr *temp = NULL;
+ CBasedDeltaBlockPtr *apdbTemp = NULL;
+
+ ULONG cbSector = GetDataSectorSize();
+
+ ULONG csect = (ulSize + cbSector - 1) / cbSector;
+
+ ULONG ulNewSize = (csect + CSECTPERBLOCK - 1) / CSECTPERBLOCK;
+
+ msfAssert(ulNewSize > 0);
+
+ if (ulNewSize == _ulSize)
+ {
+ return S_OK;
+ }
+
+ if (IsInStream())
+ {
+ //We have already copied the delta list contents out to the
+ // stream, and will not attempt to read them back in.
+ //
+ //All we need to do is adjust the size and return.
+ if (ulNewSize > _ulSize)
+ {
+ for (ULONG i = _ulSize; i < ulNewSize; i++)
+ {
+ msfChk(InitStreamBlock(i));
+ }
+ }
+
+ _ulSize = ulNewSize;
+ return S_OK;
+ }
+
+
+ if (ulNewSize > (_HEAP_MAXREQ / sizeof(SDeltaBlock *)))
+ {
+ //This is not an error. Write the current delta information
+ // to the stream and use that.
+
+ msfChk(DumpList());
+ if (ulNewSize > _ulSize)
+ {
+ for (ULONG i = _ulSize; i < ulNewSize; i++)
+ {
+ msfChk(InitStreamBlock(i));
+ }
+ }
+
+ _ulSize = ulNewSize;
+ return S_OK;
+ }
+
+
+ msfMemTo(ErrMem, temp = GetNewDeltaArray(ulNewSize));
+
+ //apdbTemp is an unbased version of _apdb, for efficiency.
+ apdbTemp = BP_TO_P(CBasedDeltaBlockPtr *, _apdb);
+
+ ULONG i;
+ for (i = 0; i < min(_ulSize, ulNewSize); i++)
+ {
+ temp[i] = apdbTemp[i];
+ apdbTemp[i] = NULL;
+ }
+
+ for (i = _ulSize; i < ulNewSize; i++)
+ {
+ temp[i] = NULL;
+ }
+
+ for (i = ulNewSize; i < _ulSize; i++)
+ {
+ ReleaseBlock(i);
+ }
+
+ _ulSize = ulNewSize;
+ _pmsScratch->GetMalloc()->Free(apdbTemp);
+ _apdb = P_TO_BP(CBasedDeltaBlockPtrPtr, temp);
+ return S_OK;
+
+ ErrMem:
+ //The only error that can get us here is an error allocating temp.
+ //If this happens, dump the current vector to a stream and use
+ // the stream for all future delta list operations.
+ msfChk(DumpList());
+ if (ulNewSize > _ulSize)
+ {
+ for (ULONG i = _ulSize; i < ulNewSize; i++)
+ {
+ msfChk(InitStreamBlock(i));
+ }
+ }
+
+ _ulSize = ulNewSize;
+ return S_OK;
+
+ Err:
+ //We only get here if we error out on the DumpList() or
+ //InitStreamBlock calls (i.e. Disk Error)
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDeltaList::InitStreamBlock, private
+//
+// Synopsis: Initialize a new block in a stream
+//
+// Arguments: [ulBlock] -- Block to initialize
+//
+// Returns: Appropriate status code
+//
+// History: 20-Nov-92 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_InitStreamBlock)
+#endif
+
+SCODE CDeltaList::InitStreamBlock(ULONG ulBlock)
+{
+ SCODE sc = S_OK;
+
+ ULONG cSectOld = ulBlock * CSECTPERBLOCK;
+ ULONG cSectNew = (ulBlock + 1) * CSECTPERBLOCK;
+
+ //NOTE: This can potentially be optimized to avoid the loop.
+ for (ULONG i = cSectOld; i < cSectNew; i++)
+ {
+ msfChk(WriteMap(&_sectStart, i, ENDOFCHAIN));
+ }
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDeltaList::ReleaseBlock, private
+//
+// Synopsis: Release an SDeltaBlock, freeing its storage in the
+// scratch MS.
+//
+// Arguments: [oBlock] -- Offset of block to release.
+//
+// Returns: void.
+//
+// History: 10-Jul-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_ReleaseBlock)
+#endif
+
+void CDeltaList::ReleaseBlock(ULONG oBlock)
+{
+ CFat *pfat = GetDataFat();
+
+ msfAssert(IsInMemory());
+
+ SDeltaBlock *temp = BP_TO_P(SDeltaBlock *, _apdb[(MAXINDEXTYPE)oBlock]);
+
+ if (temp != NULL)
+ {
+ for (USHORT i = 0; i < CSECTPERBLOCK; i++)
+ {
+ if ((temp->_sect[i] != ENDOFCHAIN) && temp->IsOwned(i))
+ {
+#ifdef USE_NOSCRATCH
+ SECT sectCurrent;
+
+ pfat->GetNext(temp->_sect[i], &sectCurrent);
+ if (sectCurrent == STREAMSECT)
+#endif
+ pfat->SetNext(temp->_sect[i], FREESECT);
+ }
+ }
+ _pmsScratch->GetMalloc()->Free(temp);
+ _apdb[(MAXINDEXTYPE)oBlock] = NULL;
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDeltaList::~CDeltaList, public
+//
+// Synopsis: CDeltaList destructor
+//
+// History: 21-Jan-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_1CDeltaList) // inline?
+#endif
+
+CDeltaList::~CDeltaList()
+{
+ Empty();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDeltaList::GetMap, public
+//
+// Synopsis: Get mapping information for a sector
+//
+// Arguments: [sectOld] -- Sector to get mapping information for
+// [dwFlags] -- DL_GET or DL_CREATE
+// [psectRet] -- Location for return value
+// [pfIsOwner] -- Returns TRUE if the returned sector
+// is owned by this delta list, FALSE if it
+// if owned by an ancestor.
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: If DL_READ is specified, return the current existing
+// mapping for the sector. It is not required that
+// the delta list own the sector. Return ENDOFCHAIN
+// if no mapping exists.
+// If DL_GET is specified, return the current existing
+// mapping for the sector if it is owned by this delta
+// list. If none exists, return ENDOFCHAIN.
+// If DL_CREATE, check the existing mapping. If none
+// exists, or one exists but is not owned, get a free
+// sector from the fat and set the mapping. Return
+// the new mapping (or the existing one if it had
+// previously been mapped).
+//
+// History: 21-Jan-92 PhilipLa Created.
+// 10-Jul-92 PhilipLa Changed for copy reductions.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_GetMap)
+#endif
+
+SCODE CDeltaList::GetMap(SECT sectOld, const DWORD dwFlags, SECT *psectRet)
+{
+ msfDebugOut((DEB_ITRACE,"In CDeltaList::GetMap()\n"));
+ SCODE sc = S_OK;
+
+ msfAssert(!IsEmpty());
+ msfAssert((dwFlags == DL_GET) || (dwFlags == DL_CREATE) ||
+ (dwFlags == DL_READ));
+
+ MAXINDEXTYPE odb = (MAXINDEXTYPE)(sectOld / CSECTPERBLOCK);
+ USHORT os = (USHORT)(sectOld % CSECTPERBLOCK);
+
+ msfAssert(odb < _ulSize);
+
+ if (IsInStream())
+ {
+ BOOL fOwn = TRUE;
+ msfChk(ReadMap(&_sectStart, sectOld, psectRet));
+
+ if (dwFlags == DL_READ)
+ {
+ return S_OK;
+ }
+
+ CDeltaList *pdlParent = NULL;
+ if (_ptsParent->GetBase() != NULL)
+ pdlParent = _ptsParent->GetBase()->GetDeltaList();
+
+ if (pdlParent != NULL)
+ {
+ msfChk(pdlParent->IsOwned(sectOld, *psectRet, &fOwn));
+ }
+
+ if (fOwn == FALSE)
+ *psectRet = ENDOFCHAIN;
+
+ if ((dwFlags == DL_CREATE) && (*psectRet == ENDOFCHAIN))
+ {
+ msfChk(GetDataFat()->GetFree(1, psectRet, GF_WRITE));
+#ifdef USE_NOSCRATCH
+ msfChk(GetDataFat()->SetNext(*psectRet, STREAMSECT));
+ if (!IsNoScratch())
+#endif
+ msfChk(_pmsScratch->SetSize());
+#ifdef USE_NOSCRATCH
+ else
+ msfChk(_pms->SetSize());
+#endif
+
+ msfChk(WriteMap(&_sectStart, sectOld, *psectRet));
+ }
+
+ return S_OK;
+ }
+
+ msfAssert(odb < _ulSize);
+
+ // If _apdb[odb] == NULL, there is no existing mapping so we
+ // don't need to check ownership.
+ if (_apdb[odb] == NULL)
+ {
+ if (dwFlags & DL_CREATE)
+ {
+ SDeltaBlock * pdbTemp = new(_pmsScratch->GetMalloc()) SDeltaBlock;
+ _apdb[odb] = P_TO_BP(CBasedDeltaBlockPtr, pdbTemp);
+
+ if (_apdb[odb] == NULL)
+ {
+ msfChk(DumpList());
+ msfAssert(IsInStream());
+ return GetMap(sectOld, dwFlags, psectRet);
+ }
+ }
+ else
+ {
+ *psectRet = ENDOFCHAIN;
+ return S_OK;
+ }
+ }
+
+ SECT sectTemp;
+ sectTemp = _apdb[odb]->_sect[os];
+
+ if (dwFlags != DL_READ)
+ {
+ BOOL fOwn = _apdb[odb]->IsOwned(os);
+ if (fOwn == FALSE)
+ sectTemp = ENDOFCHAIN;
+
+ if ((dwFlags == DL_CREATE) && (sectTemp == ENDOFCHAIN))
+ {
+ msfChk(GetDataFat()->GetFree(1, &sectTemp, GF_WRITE));
+#ifdef USE_NOSCRATCH
+ msfChk(GetDataFat()->SetNext(sectTemp, STREAMSECT));
+ if (!IsNoScratch())
+#endif
+ msfChk(_pmsScratch->SetSize());
+#ifdef USE_NOSCRATCH
+ else
+ msfChk(_pms->SetSize());
+#endif
+
+ _apdb[odb]->_sect[os] = sectTemp;
+ _apdb[odb]->MakeOwned(os);
+ }
+ }
+
+ *psectRet = sectTemp;
+ msfDebugOut((DEB_ITRACE,"Out CDeltaList::GetMap()\n"));
+ Err:
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDeltaList::BeginCommit, public
+//
+// Synopsis: Begin the commit of a delta list
+//
+// Arguments: [ptsParent] -- Pointer to containing Tstream.
+//
+// Returns: Appropriate status code
+//
+// History: 19-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_BeginCommit)
+#endif
+
+void CDeltaList::BeginCommit(CTransactedStream *ptsParent)
+{
+ _ptsParent = P_TO_BP(CBasedTransactedStreamPtr, ptsParent);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDeltaList::EndCommit, public
+//
+// Synopsis: Take the new delta list passed up and release the old.
+// Free any sectors used and owned in the old list but not
+// in the new.
+//
+// Arguments: [pdlNew] -- Pointer to new delta list to take
+//
+// Returns: void.
+//
+// History: 10-Jul-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_EndCommit)
+#endif
+
+void CDeltaList::EndCommit(CDeltaList *pdlNew, DFLAGS df)
+{
+ msfAssert(pdlNew != NULL);
+
+ if (pdlNew->IsEmpty()) return;
+
+ ULONG ulMaxSize = min(_ulSize, pdlNew->_ulSize);
+
+ if (P_COMMIT(df))
+ {
+#if DBG == 1
+ msfDebugOut((DEB_ITRACE, "Beginning commit process:\n"));
+ PrintList();
+
+ msfDebugOut((DEB_ITRACE, "New list is:\n"));
+ pdlNew->PrintList();
+#endif
+
+ ULONG iMax = ulMaxSize * CSECTPERBLOCK;
+
+ for (ULONG i = 0; i < iMax; i++)
+ {
+ SECT sectOld = ENDOFCHAIN, sectNew = ENDOFCHAIN;
+
+ GetMap(i, DL_GET, &sectOld);
+ pdlNew->GetMap(i, DL_GET, &sectNew);
+
+ if ((sectOld != sectNew) && (sectOld != ENDOFCHAIN) &&
+ (sectNew != ENDOFCHAIN))
+ {
+ CFat *pfat = GetDataFat();
+
+#if DBG == 1 && defined(USE_NOSCRATCH)
+ SECT sectChk;
+
+ pfat->GetNext(sectOld, &sectChk);
+ msfAssert((sectChk == STREAMSECT) &&
+ aMsg("Freeing non-dirty stream sector"));
+#endif
+ pfat->SetNext(sectOld, FREESECT);
+ }
+ }
+
+
+ //At this point, all the sectors in the current delta list
+ // that are not used in the new delta list have been freed.
+ // We still need to clean up the actual representation of
+ // the delta list, and merge the ownership bitvectors if
+ // we are InMemory.
+
+ if (IsInMemory())
+ {
+ for (i = pdlNew->_ulSize; i < _ulSize; i++)
+ {
+ ReleaseBlock(i);
+ }
+
+ CBasedDeltaBlockPtr * apdbTemp;
+ apdbTemp = BP_TO_P(CBasedDeltaBlockPtr *, _apdb);
+
+ for (MAXINDEXTYPE i = 0; i < ulMaxSize; i++)
+ {
+ if ((apdbTemp[i] != NULL) && (pdlNew->IsInMemory()))
+ {
+ msfAssert(pdlNew->_apdb[i] != NULL);
+ for (USHORT j = 0; j < CSECTPERBLOCK / CBITPERUSHORT; j++)
+ {
+ pdlNew->_apdb[i]->_fOwn[j] |= apdbTemp[i]->_fOwn[j];
+ }
+ }
+ _pmsScratch->GetMalloc()->Free(BP_TO_P(SDeltaBlock *, apdbTemp[i]));
+ }
+ _pmsScratch->GetMalloc()->Free(apdbTemp);
+ }
+ else if (IsInStream())
+ {
+ for (i = pdlNew->_ulSize * CSECTPERBLOCK;
+ i < _ulSize * CSECTPERBLOCK;
+ i++)
+ {
+ SECT sectOld = ENDOFCHAIN;
+ GetMap(i, DL_GET, &sectOld);
+ if (sectOld != ENDOFCHAIN)
+ {
+ CFat *pfat = GetDataFat();
+#if DBG == 1
+ SECT sectChk;
+ pfat->GetNext(sectOld, &sectChk);
+ msfAssert((sectChk == STREAMSECT) &&
+ aMsg("Freeing non-dirty stream sector"));
+#endif
+ pfat->SetNext(sectOld, FREESECT);
+ }
+ }
+
+ GetControlFat()->SetChainLength(_sectStart, 0);
+ }
+
+ _apdb = pdlNew->_apdb;
+ _ulSize = pdlNew->_ulSize;
+ _sectStart = pdlNew->_sectStart;
+
+ pdlNew->_apdb = NULL;
+ pdlNew->_ulSize = 0;
+ pdlNew->_sectStart = ENDOFCHAIN;
+ pdlNew->_ptsParent = NULL;
+#if DBG == 1
+ msfDebugOut((DEB_ITRACE, "Completed commit process:\n"));
+ PrintList();
+#endif
+ }
+
+ return;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDeltaList::Empty, public
+//
+// Synopsis: Empty the delta list
+//
+// Arguments: None.
+//
+// History: 18-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_Empty)
+#endif
+
+void CDeltaList::Empty(void)
+{
+ if (IsInMemory())
+ {
+ msfAssert(_sectStart == ENDOFCHAIN);
+
+ CBasedDeltaBlockPtr * apdbTemp;
+ apdbTemp = BP_TO_P(CBasedDeltaBlockPtr *, _apdb);
+
+ for (ULONG i = 0; i < _ulSize; i++)
+ {
+ if (apdbTemp[i] != NULL)
+ {
+ ReleaseBlock(i);
+ }
+ }
+ _pmsScratch->GetMalloc()->Free(apdbTemp);
+ _apdb = NULL;
+ }
+ else if (IsInStream())
+ {
+ msfAssert(_apdb == NULL);
+
+ if (_sectStart != ENDOFCHAIN)
+ {
+ FreeStream(_sectStart, _ulSize);
+ }
+ _sectStart = ENDOFCHAIN;
+ }
+
+ _ptsParent = NULL;
+ _ulSize = 0;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDeltaList::DumpList, public
+//
+// Synopsis: Dump a delta list out to a stream, then release its
+// in memory representation.
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+// History: 20-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_DumpList)
+#endif
+
+SCODE CDeltaList::DumpList(void)
+{
+ SCODE sc = S_OK;
+
+ ULONG cSect = _ulSize * CSECTPERBLOCK;
+
+ msfAssert(IsInMemory());
+ for (ULONG i = 0; i < cSect; i++)
+ {
+ SECT sectNew;
+ msfChk(GetMap(i, DL_GET, &sectNew));
+ msfChk(WriteMap(&_sectStart, i, sectNew));
+ }
+
+ CBasedDeltaBlockPtr * apdbTemp;
+ apdbTemp = BP_TO_P(CBasedDeltaBlockPtr *, _apdb);
+ for (i = 0; i < _ulSize; i++)
+ {
+ if (apdbTemp[i] != NULL)
+ {
+ ReleaseBlock(i);
+ }
+ }
+ _pmsScratch->GetMalloc()->Free(apdbTemp);
+ _apdb = NULL;
+
+ msfAssert(IsInStream());
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDeltaList::FindOffset, private
+//
+// Synopsis: Compute the correct offset from which to read a mapping
+//
+// Arguments: [psectStart] -- Pointer to start sector
+// [sect] -- Sector to find mapping for
+// [pulRet] -- Pointer to return location
+// [fWrite] -- TRUE if the sector will be written to
+//
+// Returns: Appropriate status code
+//
+// History: 20-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_FindOffset)
+#endif
+
+SCODE CDeltaList::FindOffset(
+ SECT *psectStart,
+ SECT sect,
+ ULARGE_INTEGER *pulRet,
+ BOOL fWrite)
+{
+ SCODE sc;
+
+ ULONG ulOffset = sect * sizeof(SECT);
+
+ ULONG cbSector = GetControlSectorSize();
+ msfAssert(cbSector == SCRATCHSECTORSIZE);
+
+ SECT sectChain = ulOffset / cbSector;
+
+ SECT sectReal;
+
+ CFat *pfat = GetControlFat();
+
+ if (fWrite)
+ {
+ if (*psectStart == ENDOFCHAIN)
+ {
+ msfChk(pfat->Allocate(1, psectStart));
+ }
+ msfChk(pfat->GetESect(*psectStart, sectChain, &sectReal));
+ }
+ else
+ {
+ msfChk(pfat->GetSect(*psectStart, sectChain, &sectReal));
+ }
+
+ msfAssert(sectReal != ENDOFCHAIN);
+
+ ULARGE_INTEGER ul;
+ ULISet32(ul, ConvertSectOffset(sectReal,
+ (OFFSET)(ulOffset % cbSector),
+ _pmsScratch->GetSectorShift()));
+
+ *pulRet = ul;
+
+ Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDeltaList::ReadMap, private
+//
+// Synopsis: Read a mapping from a stream representation.
+//
+// Arguments: [sect] -- Sector to read mapping for
+// [psectRet] -- Location to return mapping in.
+//
+// Returns: Appropriate status code
+//
+// History: 20-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_ReadMap)
+#endif
+
+SCODE CDeltaList::ReadMap(SECT *psectStart, SECT sect, SECT *psectRet)
+{
+ SCODE sc;
+
+ if (_sectStart == ENDOFCHAIN)
+ {
+ //We haven't written anything yet, so the sector must be
+ // unmapped.
+ *psectRet = ENDOFCHAIN;
+ return S_OK;
+ }
+
+ ULARGE_INTEGER ul;
+ ULONG ulRetval;
+
+ msfChk(FindOffset(psectStart, sect, &ul, FALSE));
+
+ msfHChk(GetControlILB()->ReadAt(ul, psectRet, sizeof(SECT),
+ &ulRetval));
+
+ if (ulRetval != sizeof(SECT))
+ {
+ //The ILB isn\'t long enough to contain that mapping,
+ // so return ENDOFCHAIN;
+ *psectRet = ENDOFCHAIN;
+ }
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDeltaList::WriteMap, private
+//
+// Synopsis: Write a mapping to a stream representation
+//
+// Arguments: [sect] -- Sect to write mapping for
+// [sectMap] -- Mapping of sect
+//
+// Returns: Appropriate status code
+//
+// History: 20-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_WriteMap)
+#endif
+
+SCODE CDeltaList::WriteMap(SECT *psectStart, SECT sect, SECT sectMap)
+{
+ SCODE sc;
+
+ ULARGE_INTEGER ul;
+ ULONG ulRetval;
+
+ SECT sectOld = *psectStart;
+
+ msfAssert(_pmsScratch->IsScratch());
+
+ msfChk(FindOffset(psectStart, sect, &ul, TRUE));
+
+ msfHChk(GetControlILB()->WriteAt(ul, &sectMap, sizeof(SECT),
+ &ulRetval));
+
+ if (ulRetval != sizeof(SECT))
+ {
+ msfErr(Err, STG_E_WRITEFAULT);
+ }
+
+ return S_OK;
+
+Err:
+ //If we failed, we may have allocated sectors for storage that
+ // cannot be written to - we should ignore these sectors. This
+ // can leave some wasted space in the fat, but we don't really
+ // care since this is the scratch.
+
+ *psectStart = sectOld;
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDeltaList::FreeStream, private
+//
+// Synopsis: Free the scratch sectors associated with a stream
+// representation of a delta list.
+//
+// Arguments: [sectStart] -- Start sector of representation to
+// free.
+//
+// Returns: void.
+//
+// History: 23-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_FreeStream)
+#endif
+
+void CDeltaList::FreeStream(SECT sectStart, ULONG ulSize)
+{
+ ULONG cSect = ulSize * CSECTPERBLOCK;
+
+ SECT sectOld;
+ BOOL fOwn = TRUE;
+
+ CDeltaList *pdlParent = NULL;
+ if (_ptsParent->GetBase() != NULL)
+ pdlParent = _ptsParent->GetBase()->GetDeltaList();
+
+ for (ULONG i = 0; i < cSect; i++)
+ {
+ ReadMap(&sectStart, i, &sectOld);
+
+ if (pdlParent != NULL)
+ {
+ pdlParent->IsOwned(i, sectOld, &fOwn);
+ }
+
+ if ((sectOld != ENDOFCHAIN) && fOwn)
+ {
+ CFat *pfat = GetDataFat();
+#if DBG == 1
+ SECT sectChk;
+
+ pfat->GetNext(sectOld, &sectChk);
+ msfAssert((sectChk == STREAMSECT) &&
+ aMsg("Freeing non-dirty stream sector"));
+#endif
+ pfat->SetNext(sectOld, FREESECT);
+ }
+ }
+ GetControlFat()->SetChainLength(sectStart, 0);
+ return;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDeltaList::IsOwned, public
+//
+// Synopsis: Return TRUE if the caller owns the sector given,
+// FALSE otherwise.
+//
+// Arguments: [sect] -- Sector for mapping given
+// [sectMap] -- Sector mapping
+// [fOwn] -- Return value
+//
+// Returns: Appropriate status code
+//
+// History: 30-Jul-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDeltaList_IsOwned)
+#endif
+
+SCODE CDeltaList::IsOwned(SECT sect, SECT sectMap, BOOL *fOwn)
+{
+ SCODE sc = S_OK;
+ //To determine ownership of a sector:
+ // 1) If the sector mapping does not exist at the current level,
+ // then the caller must own it.
+ // 2) If the sector mapping does exist at the current level, then
+ // the caller cannot own it.
+ SECT sectOld;
+
+ if (sect < _ulSize * CSECTPERBLOCK)
+ {
+ if (IsInMemory())
+ {
+ MAXINDEXTYPE odb = (MAXINDEXTYPE)(sect / CSECTPERBLOCK);
+ USHORT os = (USHORT)(sect % CSECTPERBLOCK);
+
+ sectOld = _apdb[odb]->_sect[os];
+ }
+ else
+ {
+ msfChk(GetMap(sect, DL_READ, &sectOld));
+ }
+
+ *fOwn = (sectOld != sectMap);
+ }
+ else
+ {
+ *fOwn = TRUE;
+ }
+
+Err:
+ return sc;
+}
+
+
+#if DBG == 1
+void CDeltaList::PrintList(void)
+{
+ if (!IsEmpty())
+ {
+ for (ULONG i = 0; i < _ulSize * CSECTPERBLOCK; i++)
+ {
+ SECT sect;
+ GetMap(i, DL_READ, &sect);
+
+ msfDebugOut((DEB_NOCOMPNAME|DEB_ITRACE, "%lx ",sect));
+ }
+ msfDebugOut((DEB_NOCOMPNAME|DEB_ITRACE,"\n"));
+ }
+ else
+ {
+ msfDebugOut((DEB_NOCOMPNAME|DEB_ITRACE,"List is empty\n"));
+ }
+}
+#endif
+
+
+
diff --git a/private/ole32/stg/msf/fat.cxx b/private/ole32/stg/msf/fat.cxx
new file mode 100644
index 000000000..68adba6f6
--- /dev/null
+++ b/private/ole32/stg/msf/fat.cxx
@@ -0,0 +1,3562 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: fat.cxx
+//
+// Contents: Allocation functions for MStream
+//
+// Classes: None. (defined in fat.hxx)
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+#pragma hdrstop
+
+#include <difat.hxx>
+#include <sstream.hxx>
+#include <mread.hxx>
+
+#define USE_NOSCRATCHINMARKSECT
+
+#ifndef REF
+//#define SECURETEST
+#endif //!REF
+//+---------------------------------------------------------------------------
+//
+// Member: CFat::IsFree, private
+//
+// Synopsis: Check and see if a given sector is really free, given all
+// the permutations of ways a sector can be assigned.
+//
+// Arguments: [sect] -- Sector to check
+//
+// Returns: S_OK if sector is really free.
+// S_FALSE if sector is really allocated.
+// Appropriate error in error case.
+//
+// Modifies:
+//
+// History: 30-Mar-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CFat::IsFree(SECT sect)
+{
+ SCODE sc = S_OK;
+ SECT sectCurrent = FREESECT;
+
+ msfDebugOut((DEB_ITRACE, "In CFat::IsFree:%p()\n", this));
+
+#ifdef USE_NOSNAPSHOT
+ if (sect < _sectNoSnapshot)
+ {
+ return S_FALSE;
+ }
+ if ((_sectNoSnapshotFree != ENDOFCHAIN) && (sect < _sectNoSnapshotFree))
+ {
+ return S_FALSE;
+ }
+#endif
+
+#ifdef USE_NOSCRATCH
+ if (_pfatNoScratch != NULL)
+ {
+ msfAssert((!_pmsParent->IsScratch()) &&
+ aMsg("Scratch MS in Noscratch mode"));
+
+ FSINDEX ipfs;
+ FSOFFSET isect;
+
+ _pfatNoScratch->SectToPair(sect, &ipfs, &isect);
+
+ if (ipfs < _pfatNoScratch->_cfsTable)
+ {
+ //We need to check the NoScratch fat to make sure
+ //that this sector isn't already allocated into
+ //scratch space for a stream.
+
+ msfChk(_pfatNoScratch->GetNext(
+ sect,
+ &sectCurrent));
+ }
+ }
+ //Since the no-scratch fat will have a complete copy of everything
+ // in the shadow fat, we don't need to check both. So only do this
+ // when we're not in no-scratch mode.
+ //The no-scratch fat also has a copy of the read-only GetFree()
+ // returned stuff, so we only need to do that check when not in
+ // no-scratch.
+ else
+ {
+#endif
+ if (_cUnmarkedSects > 0)
+ {
+ //We are in copy-on-write mode. Lookup this
+ //sector in the DIF and make sure that it is
+ //actually free.
+ msfAssert((_sectLastUsed > 0) &&
+ aMsg("Doing DIFat check when not in COW."));
+
+ msfChk(_pmsParent->GetDIFat()->Lookup(
+ sect,
+ &sectCurrent));
+ }
+
+ if ((sect < _sectLastUsed) && (sectCurrent == FREESECT))
+ {
+ //We're in copy-on-write mode, so
+ // this sector may not be really free.
+ msfAssert(_sid != SIDMINIFAT &&
+ aMsg("Minifat in Copy-on-Write mode"));
+ msfAssert(_pfatReal != NULL &&
+ aMsg("Copy-On-Write mode without fat copy"));
+ msfAssert(_pfatReal->_cfsTable != 0 &&
+ aMsg("Copy-on-Write mode with empty fat copy"));
+ msfAssert(_pfatReal->_pmsParent->IsShadow() &&
+ aMsg("Copy-on-Write mode with non-shadow fat copy"));
+
+ msfChk(_pfatReal->GetNext(sect, &sectCurrent));
+ }
+#ifdef USE_NOSCRATCH
+ }
+#endif
+
+ if (sectCurrent != FREESECT)
+ {
+ sc = S_FALSE;
+ }
+
+ msfDebugOut((DEB_ITRACE, "Out CFat::IsFree\n"));
+
+Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFatSect::Init, public
+//
+// Synopsis: CFatSect initialization function
+//
+// Effects: [uEntries] -- Number of entries in sector
+//
+// Algorithm: Allocate an array of SECT with size uEntries from
+// the heap.
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 27-Dec-91 PhilipLa Converted to dynamic allocation
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFatSect_Init)
+#endif
+
+SCODE FAT_CLASS CFatSect::Init(FSOFFSET uEntries)
+{
+ msfDebugOut((DEB_FAT,"In CFatSect constructor\n"));
+
+ //This assumes that FREESECT is always 0xFFFFFFFF
+ memset(_asectEntry, 0xFF, uEntries * sizeof(SECT));
+
+ msfDebugOut((DEB_FAT,"Out CFatSect constructor\n"));
+ return S_OK;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFatSect::InitCopy, public
+//
+// Synopsis: Initialization function for copying FatSects
+//
+// Arguments: [fsOld] -- Reference to FatSect to be copies
+//
+// Returns: S_OK if call completed successfully.
+//
+// Algorithm: Allocate a new array of SECT and copy old
+// information in.
+//
+// History: 06-Feb-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFatSect_InitCopy)
+#endif
+
+SCODE FAT_CLASS CFatSect::InitCopy(USHORT uSize, CFatSect *pfsOld)
+{
+ msfDebugOut((DEB_FAT,"In CFatSect copy constructor\n"));
+ msfDebugOut((DEB_FAT,"This = %p, fsOld = %p\n",this, pfsOld));
+
+ msfDebugOut((DEB_FAT,"Sector size is %u sectors\n", uSize));
+
+ memcpy(_asectEntry, &pfsOld->_asectEntry, sizeof(SECT)*uSize);
+ msfDebugOut((DEB_FAT,"Out CFatSect copy constructor\n"));
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFat::CFat, public
+//
+// Synopsis: CFat constructor.
+//
+// Arguments: [pmsParent] -- Pointer to parent multistream.
+//
+// Algorithm: Set uFatEntries to match parent MS header info.
+// Initialize all member variables.
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 27-Dec-91 PhilipLa Converted to use FatVector
+// 30-Dec-91 PhilipLa Converted to use variable size sect.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_CFat)
+#endif
+
+FAT_CLASS CFat::CFat(SID sid)
+: _fv(sid),
+#ifndef REF
+ _pfatReal(NULL),
+#endif //!REF
+#ifdef USE_NOSCRATCH
+ _pfatNoScratch(NULL),
+#endif
+#ifdef USE_NOSNAPSHOT
+ _sectNoSnapshot(0),
+ _sectNoSnapshotFree(ENDOFCHAIN),
+#endif
+ _sid(sid),
+ _pmsParent(NULL),
+ _sectFirstFree(0),
+#ifndef REF
+ _sectLastUsed(0),
+#endif //!REF
+ _sectMax(ENDOFCHAIN)
+{
+#ifndef REF
+ _cUnmarkedSects = 0;
+#endif //!REF
+}
+
+
+#ifndef REF
+//+-------------------------------------------------------------------------
+//
+// Method: CFat::CFat, public
+//
+// Synopsis: CFat copy constructor
+//
+// Arguments: [fatOld] -- Fat to be copied.
+//
+// Algorithm: Set member variables to match fat being copied.
+//
+// History: 27-Dec-91 PhilipLa Created.
+//
+// Notes: This is for use in transactioning. It is the only proper
+// way to create a Shadow Fat.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_CFat2)
+#endif
+
+FAT_CLASS CFat::CFat(CFat *pfatOld)
+ : _pmsParent(pfatOld->_pmsParent),
+ _fv(pfatOld->_sid),
+ _pfatReal(NULL),
+ _sid(pfatOld->_sid),
+ _sectFirstFree(0),
+ _sectLastUsed(0),
+ _sectMax(ENDOFCHAIN),
+ _sectNoSnapshot(pfatOld->_sectNoSnapshot)
+{
+#ifndef REF
+ _cUnmarkedSects = 0;
+#endif //!REF
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFat::InitCopy, public
+//
+// Synopsis: Init function for CFat copying
+//
+// Arguments: [fatOld] -- reference to CFat to be copied
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: *Finish This*
+//
+// History: 18-Feb-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_InitCopy)
+#endif
+
+void FAT_CLASS CFat::InitCopy(CFat *pfatOld)
+{
+ msfDebugOut((DEB_FAT,"In CFat Copy Constructor\n"));
+
+ _pmsParent = pfatOld->_pmsParent;
+ _uFatShift = _pmsParent->GetSectorShift() - 2;
+ _uFatMask = (_pmsParent->GetSectorSize() >> 2) - 1;
+
+ _fv.InitCommon(1 << _uFatShift, 1 << _uFatShift);
+
+ _cfsTable = pfatOld->_cfsTable;
+
+ _fv.InitCopy(&pfatOld->_fv);
+
+ _ulFreeSects = MAX_ULONG;
+ _sectFirstFree = pfatOld->_sectFirstFree;
+ _sectLastUsed = pfatOld->_sectLastUsed;
+ _sectMax = pfatOld->_sectMax;
+
+ msfDebugOut((DEB_FAT,"Out CFat Copy Constructor\n"));
+}
+#endif //!REF
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFat::Empty, public
+//
+// Synopsis: Empty all the control structures of this instance
+//
+// Arguments: None.
+//
+// Returns: void.
+//
+// History: 04-Dec-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_Empty)
+#endif
+
+void CFat::Empty(void)
+{
+ _fv.Empty();
+ _pmsParent = NULL;
+#ifndef REF
+ _pfatReal = NULL;
+#endif //!REF
+ _cfsTable = 0;
+ _ulFreeSects = MAX_ULONG;
+ _sectFirstFree = 0;
+#ifndef REF
+ _sectLastUsed = 0;
+#endif //!REF
+ _sectMax = ENDOFCHAIN;
+#ifndef REF
+ _cUnmarkedSects = 0;
+#endif //!REF
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFat::~CFat, public
+//
+// Synopsis: CFat Destructor
+//
+// Algorithm: delete dynamically allocated storage
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 27-Jul-91 PhilipLa Converted to use FatVect.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_1CFat) // inline?
+#endif
+
+FAT_CLASS CFat::~CFat()
+{
+ msfDebugOut((DEB_FAT,"In CFat destructor. Size of fat is %lu\n",_cfsTable));
+
+ msfDebugOut((DEB_FAT,"Exiting CFat destructor\n"));
+}
+
+#ifdef USE_NEW_GETFREE
+struct SGetFreeStruct
+{
+ CVectBits *pfb;
+
+ SECT sect;
+ CFatSect *pfs;
+ FSOFFSET isect;
+ FSINDEX ipfs;
+
+ SECT sectLast;
+ FSINDEX ipfsLast;
+ FSOFFSET isectLast;
+
+#ifdef USE_NOSCRATCH
+#ifdef USE_NOSCRATCHINMARKSECT
+ CFatSect *pfsNoScratch;
+ FSINDEX ipfsNoScratch;
+#endif
+#endif // USE_NOSCRATCH
+};
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFat::InitGetFreeStruct, private
+//
+// Synopsis: Initialize an SGetFreeStruct
+//
+// Arguments: [pgf] -- Pointer to structure to initialize
+//
+// History: 03-Nov-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+void CFat::InitGetFreeStruct(SGetFreeStruct *pgf)
+{
+ pgf->sectLast = ENDOFCHAIN;
+ pgf->pfs = NULL;
+#ifdef USE_NOSCRATCH
+#ifdef USE_NOSCRATCHINMARKSECT
+ pgf->pfsNoScratch = NULL;
+#endif
+#endif
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFat::ReleaseGetFreeStruct, private
+//
+// Synopsis: Release an SGetFreeStruct
+//
+// Arguments: [pgf] -- Pointer to structure to release
+//
+// History: 03-Nov-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+void CFat::ReleaseGetFreeStruct(SGetFreeStruct *pgf)
+{
+ if (pgf->pfs != NULL)
+ {
+ _fv.ReleaseTable(pgf->ipfs);
+ }
+#ifdef USE_NOSCRATCH
+#ifdef USE_NOSCRATCHINMARKSECT
+ if (pgf->pfsNoScratch != NULL)
+ {
+ _pfatNoScratch->_fv.ReleaseTable(pgf->ipfsNoScratch);
+ }
+#endif
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFat::MarkSect, private
+//
+// Synopsis: Mark a sector as used, for use from GetFree and GetFreeContig
+//
+// Arguments: [pgf] -- Pointer to SGetFreeStruct with information about
+// which sector to mark. This structure also returns
+// information to the caller, so that state can be
+// preserved across multiple calls for optimization.
+//
+// Returns: Appropriate status code
+//
+// History: 27-Oct-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CFat::MarkSect(SGetFreeStruct *pgf)
+{
+ msfAssert(_ulFreeSects != MAX_ULONG &&
+ aMsg("Free sect count not set"));
+
+ SCODE sc = S_OK;
+
+ _ulFreeSects--;
+
+ CVectBits * &pfb = pgf->pfb;
+
+ SECT &sect = pgf->sect;
+ FSOFFSET &isect = pgf->isect;
+ FSINDEX &ipfs = pgf->ipfs;
+ CFatSect * &pfs = pgf->pfs;
+#ifdef USE_NOSCRATCH
+#ifdef USE_NOSCRATCHINMARKSECT
+ CFatSect * &pfsNoScratch = pgf->pfsNoScratch;
+ FSINDEX &ipfsNoScratch = pgf->ipfsNoScratch;
+#endif
+#endif
+
+ SECT &sectLast = pgf->sectLast;
+ FSINDEX &ipfsLast = pgf->ipfsLast;
+ FSOFFSET &isectLast = pgf->isectLast;
+
+ //If we're tracking the first free sector, we know it must be
+ // after this one, so set firstfree.
+ if (pfb != NULL)
+ {
+ pfb->firstfree = isect + 1;
+ }
+
+ //Update _sectFirstFree, since the first free sector must be after then
+ // current one.
+ msfAssert(sect >= _sectFirstFree &&
+ aMsg("Found free sector before _sectFirstFree"));
+ _sectFirstFree = sect + 1;
+
+ //Mark the current sector as ENDOFCHAIN in the fat.
+ pfs->SetSect(isect, ENDOFCHAIN);
+
+#ifdef USE_NOSCRATCH
+ if (_pfatNoScratch != NULL)
+ {
+#ifdef USE_NOSCRATCHINMARKSECT
+ //In no-scratch, update the no-scratch fat
+ //as well.
+ FSINDEX ipfsNoScratchChk;
+ FSOFFSET isectNoScratchChk;
+ _pfatNoScratch->SectToPair(sect,
+ &ipfsNoScratchChk,
+ &isectNoScratchChk);
+
+ if ((pfsNoScratch != NULL) && (ipfsNoScratch != ipfsNoScratchChk))
+ {
+ _pfatNoScratch->_fv.ReleaseTable(ipfsNoScratch);
+ pfsNoScratch = NULL;
+ }
+
+ if (pfsNoScratch == NULL)
+ {
+ //SetNext call will grow the no-scratch fat if necessary.
+ msfChk(_pfatNoScratch->SetNext(sect, ENDOFCHAIN));
+ msfChk(_pfatNoScratch->_fv.GetTable(ipfsNoScratchChk,
+ FB_DIRTY,
+ &pfsNoScratch));
+ ipfsNoScratch = ipfsNoScratchChk;
+ }
+ else
+ {
+ pfsNoScratch->SetSect(isectNoScratchChk, ENDOFCHAIN);
+ _pfatNoScratch->_ulFreeSects--;
+ }
+#else
+ //BUGBUG: SLOW
+ msfChk(_pfatNoScratch->SetNext(sect, ENDOFCHAIN));
+#endif
+ }
+#endif
+
+ //Dirty the current page.
+ if ((sectLast == ENDOFCHAIN) || (ipfs != ipfsLast))
+ {
+ //We only need to make this call if we're touching a new
+ // page for the first time.
+ msfChk(_fv.SetDirty(ipfs));
+ }
+
+ //If we're building a chain, we want to update it here.
+ if (sectLast != ENDOFCHAIN)
+ {
+#ifdef USE_NOSCRATCH
+ if (_pfatNoScratch != NULL)
+ {
+#ifdef USE_NOSCRATCHINMARKSECT
+ FSINDEX ipfsNoScratchChk;
+ FSOFFSET isectNoScratchChk;
+ _pfatNoScratch->SectToPair(sectLast,
+ &ipfsNoScratchChk,
+ &isectNoScratchChk);
+
+ if (ipfsNoScratchChk == ipfsNoScratch)
+ {
+ msfAssert(pfsNoScratch != NULL);
+ pfsNoScratch->SetSect(isectNoScratchChk, sect);
+ }
+ else
+ {
+ msfChk(_pfatNoScratch->SetNext(sectLast, sect));
+ }
+#else
+ //BUGBUG: SLOW
+ msfChk(_pfatNoScratch->SetNext(sectLast, sect));
+#endif
+ }
+#endif
+ //If we're in the same page, we can do this cheaply.
+ if (ipfsLast == ipfs)
+ {
+ pfs->SetSect(isectLast, sect);
+ }
+ else
+ {
+ //If we're NOT on the same page, we have to go grab the
+ // old one again, which is expensive.
+ //BUGBUG: Fix this too.
+ CFatSect *pfsLast;
+
+ //Since we may only have one available page for the scratch MS,
+ // we need to release the current one before proceeding.
+ // This sucks.
+ if (_pmsParent->IsScratch())
+ {
+ _fv.ReleaseTable(ipfs);
+ }
+
+ msfChk(_fv.GetTable(ipfsLast,
+ FB_DIRTY,
+ &pfsLast));
+
+ pfsLast->SetSect(isectLast, sect);
+ _fv.ReleaseTable(ipfsLast);
+
+ //Reacquire the current page if we're in the scratch.
+ if (_pmsParent->IsScratch())
+ {
+ msfChk(_fv.GetTable(ipfs, FB_DIRTY, &pfs));
+ }
+ }
+ }
+
+ return S_OK;
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::GetFree, private
+//
+// Synposis: Locate and return a free sector in the FAT
+//
+// Effects: May modify full bit on full sectors
+//
+// Arguments: [psectRet] -- Pointer to return value
+//
+// Returns: S_OK if call completed successfully.
+//
+// Algorithm: Do a linear search of all tables until a free sector is
+// found. If all tables are full, extend the FAT by one
+// sector.
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 22-Jul-91 PhilipLa Added FAT extension.
+// 17-Aug-91 PhilipLa Added full bits optimization
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_GetFree)
+#endif
+
+#ifndef REF
+SCODE FAT_CLASS CFat::GetFree(ULONG ulCount, SECT *psectRet, BOOL fReadOnly)
+#else
+SCODE FAT_CLASS CFat::GetFree(ULONG ulCount, SECT *psectRet)
+#endif //!REF
+{
+ SGetFreeStruct gf;
+
+ SECT &sect = gf.sect;
+ CVectBits * &pfb = gf.pfb;
+ FSOFFSET &isect = gf.isect;
+ FSINDEX &ipfs = gf.ipfs;
+ CFatSect * &pfs = gf.pfs;
+ SECT &sectLast = gf.sectLast;
+ FSINDEX &ipfsLast = gf.ipfsLast;
+ FSOFFSET &isectLast = gf.isectLast;
+
+ InitGetFreeStruct(&gf);
+
+ SCODE sc;
+
+ *psectRet = ENDOFCHAIN;
+
+ msfAssert((!_pmsParent->IsShadow()) &&
+ aMsg("Modifying shadow fat."));
+
+ msfAssert(((!fReadOnly) || (ulCount == 1)) &&
+ aMsg("Read-only GetFree called with ulCount != 1"));
+#ifdef USE_NOSNAPSHOT
+ if (_sectNoSnapshotFree != ENDOFCHAIN)
+ {
+ //We're resizing our control structures to prepare for
+ // no-snapshot commit.
+ msfAssert((ulCount == 1) &&
+ aMsg("No-snapshot GetFree called with ulCount != 1"));
+ msfAssert(fReadOnly &&
+ aMsg("No-snapshot GetFree called without fReadOnly"));
+ *psectRet = _sectNoSnapshotFree++;
+ _cUnmarkedSects++;
+ if ((_ulFreeSects != 0) && (_ulFreeSects != MAX_ULONG))
+ {
+ _ulFreeSects--;
+ }
+ if (*psectRet >= _sectMax)
+ {
+ _sectMax = *psectRet + 1;
+ }
+ return S_OK;
+ }
+#endif
+
+#ifdef USE_NOSCRATCH
+ if ((fReadOnly) && (_pfatNoScratch != NULL))
+ {
+ //As an optimization, and to prevent loops, we can dispatch
+ //this call directly to the no-scratch fat, since it has a
+ //complete picture of everything allocated in this fat.
+
+ //Note that we don't need to pass the read-only flag to the
+ //no-scratch, since it's perfectly OK to scribble on it
+ //as much as we want.
+
+ //Further note that if fReadOnly is true, then ulCount must be
+ // 1, so we can just work with the constant.
+ msfChk(_pfatNoScratch->GetFree(1, psectRet, GF_WRITE));
+ if (_ulFreeSects != MAX_ULONG)
+ {
+ _ulFreeSects--;
+ }
+
+ _cUnmarkedSects++;
+ if (*psectRet >= _sectMax)
+ {
+ _sectMax = *psectRet + 1;
+ }
+ return S_OK;
+ }
+#endif
+
+ while (TRUE)
+ {
+ //Make sure there are enough free sectors to hold the whole chain
+ // we're trying to allocate.
+ if (_ulFreeSects == MAX_ULONG)
+ {
+ msfChk(CountFree(&_ulFreeSects));
+ }
+#if DBG == 1
+ else
+ {
+ CheckFreeCount();
+ }
+#endif
+
+ while (ulCount > _ulFreeSects)
+ {
+#if DBG == 1 && !defined(USE_NOSCRATCH)
+ ULONG ulFree = _ulFreeSects;
+#endif
+ msfChk(Resize(_cfsTable +
+ ((ulCount - _ulFreeSects + _fv.GetSectTable() - 1) >>
+ _uFatShift)));
+#if DBG == 1 && !defined(USE_NOSCRATCH)
+ msfAssert(_ulFreeSects > ulFree &&
+ aMsg("Number of free sectors didn't increase after Resize."));
+#endif
+
+ }
+
+ //Starting at the first known free sector, loop until we find
+ // enough sectors to complete the chain.
+ FSOFFSET isectStart;
+ FSINDEX ipfsStart;
+
+ SectToPair(_sectFirstFree, &ipfsStart, &isectStart);
+
+ for (ipfs = ipfsStart; ipfs < _cfsTable; ipfs++)
+ {
+ //Only check a page if it is not known to be full.
+ pfb = _fv.GetBits(ipfs);
+
+ if ((pfb == NULL) || (!pfb->full))
+ {
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+
+ //Eliminate part of the search based on the first-known
+ // free entry for the page
+ if (pfb != NULL)
+ {
+ isectStart = pfb->firstfree;
+ }
+
+ for (isect = isectStart; isect < _fv.GetSectTable(); isect++)
+ {
+ SECT sectCurrent = pfs->GetSect(isect);
+ sect = PairToSect(ipfs, isect);
+
+ //If the sector is marked FREESECT, it still may not
+ // really be free. The IsFree function will return
+ // S_OK if it is OK to allocate.
+ if ((sectCurrent == FREESECT) &&
+ ((sc = IsFree(sect)) == S_OK))
+ {
+ //If fReadOnly is TRUE (meaning we're being called
+ // by the DIFat), then we don't want to actually
+ // mark anything in the current fat. We'll return
+ // the current sector and then be done with it.
+ if (fReadOnly)
+ {
+ _cUnmarkedSects++;
+ _ulFreeSects--;
+ }
+ else
+ {
+ //Mark the sector as free and return it.
+ msfChkTo(Err_Rel, MarkSect(&gf));
+ }
+
+ if (*psectRet == ENDOFCHAIN)
+ {
+ *psectRet = sect;
+ }
+
+ ulCount--;
+
+ if (ulCount == 0)
+ {
+ //If we're done, release the current table,
+ // update _sectMax, and return.
+
+ if (sect >= _sectMax)
+ {
+ _sectMax = sect + 1;
+ }
+
+ ReleaseGetFreeStruct(&gf);
+ return S_OK;
+ }
+ else
+ {
+ //Otherwise update the internal counters and
+ // keep going.
+ sectLast = sect;
+ ipfsLast = ipfs;
+ isectLast = isect;
+ }
+ }
+ else
+ {
+ msfChkTo(Err_Rel, sc);
+ }
+
+ }
+ _fv.ReleaseTable(ipfs);
+ //If we are keeping a full bit, we can set it here, since
+ // we know we've allocated everything out of the current
+ // page.
+ if (pfb != NULL)
+ {
+ pfb->full = TRUE;
+ }
+ }
+ isectStart = 0;
+ }
+
+ //Keep _sectMax up to date for SetSize purposes.
+ if (sectLast >= _sectMax)
+ {
+ _sectMax = sectLast + 1;
+ }
+ }
+ msfAssert(0 &&
+ aMsg("GetFree exited improperly."));
+ sc = STG_E_ABNORMALAPIEXIT;
+
+Err:
+ ReleaseGetFreeStruct(&gf);
+ return sc;
+
+Err_Rel:
+ ReleaseGetFreeStruct(&gf);
+ return sc;
+}
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFat::GetFreeContig, public
+//
+// Synopsis: Return a chain of free sectors, including contiguity
+// information about the chain.
+//
+// Arguments: [ulCount] -- Number of sectors to allocate
+// [aseg] -- Contig table to fill in
+// [cSeg] -- Index of last used segment in contig table.
+// [pcSegReturned] -- Pointer to return location for total
+// number of segments returned.
+//
+// Returns: Appropriate status code
+//
+// History: 27-Oct-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE FAT_CLASS CFat::GetFreeContig(ULONG ulCount,
+ SSegment STACKBASED *aseg,
+ ULONG cSeg,
+ ULONG *pcSegReturned)
+{
+ SGetFreeStruct gf;
+
+ SECT &sect = gf.sect;
+ CVectBits * &pfb = gf.pfb;
+ FSOFFSET &isect = gf.isect;
+ FSINDEX &ipfs = gf.ipfs;
+ CFatSect * &pfs = gf.pfs;
+ SECT &sectLast = gf.sectLast;
+ FSINDEX &ipfsLast = gf.ipfsLast;
+ FSOFFSET &isectLast = gf.isectLast;
+
+ InitGetFreeStruct(&gf);
+
+ FSINDEX ipfsFirstDirty;
+
+ SCODE sc;
+
+ //Variables used for tracking contiguity.
+ //cSegCurrent is the current segment being processed.
+ ULONG cSegCurrent = cSeg;
+
+ //sectLast is the last sector returned. We start this with the
+ // last thing in the current contig table, and the MarkSect
+ // function will patch up the chain for us.
+ sectLast = aseg[cSeg].sectStart + aseg[cSeg].cSect - 1;
+ SectToPair(sectLast, &ipfsLast, &isectLast);
+ ipfsFirstDirty = ipfsLast;
+#if DBG == 1
+ SECT sectTest;
+ GetNext(sectLast, &sectTest);
+ msfAssert(sectTest == ENDOFCHAIN);
+#endif
+
+ msfAssert((!_pmsParent->IsShadow()) &&
+ aMsg("Modifying shadow fat."));
+
+ while (TRUE)
+ {
+ //Make sure there are enough free sectors to hold the whole chain
+ // we're trying to allocate.
+ if (_ulFreeSects == MAX_ULONG)
+ {
+ msfChk(CountFree(&_ulFreeSects));
+ }
+#if DBG == 1
+ else
+ {
+ CheckFreeCount();
+ }
+#endif
+
+ while (ulCount > _ulFreeSects)
+ {
+#if DBG == 1 && !defined(USE_NOSCRATCH)
+ ULONG ulFree = _ulFreeSects;
+#endif
+ msfChk(Resize(_cfsTable +
+ ((ulCount - _ulFreeSects + _fv.GetSectTable() - 1) >>
+ _uFatShift)));
+#if DBG == 1 && !defined(USE_NOSCRATCH)
+ msfAssert(_ulFreeSects > ulFree &&
+ aMsg("Number of free sectors didn't increase after Resize."));
+#endif
+
+ }
+
+ //Starting at the first known free sector, loop until we find
+ // enough sectors to complete the chain.
+ FSOFFSET isectStart;
+ FSINDEX ipfsStart;
+
+ SectToPair(_sectFirstFree, &ipfsStart, &isectStart);
+
+ for (ipfs = ipfsStart; ipfs < _cfsTable; ipfs++)
+ {
+ //Only check a page if it is not known to be full.
+ pfb = _fv.GetBits(ipfs);
+
+ if ((pfb == NULL) || (!pfb->full))
+ {
+ //This little contortion is necessary because the
+ // page containing the first sector may not get marked
+ // as dirty by MarkSect.
+ if (ipfs == ipfsFirstDirty)
+ {
+ msfChk(_fv.GetTable(ipfs, FB_DIRTY, &pfs));
+ }
+ else
+ {
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+ }
+
+ //Eliminate part of the search based on the first-known
+ // free entry for the page
+ if (pfb != NULL)
+ {
+ isectStart = pfb->firstfree;
+ }
+
+ for (isect = isectStart; isect < _fv.GetSectTable(); isect++)
+ {
+ SECT sectCurrent = pfs->GetSect(isect);
+ sect = PairToSect(ipfs, isect);
+
+ //If the sector is marked FREESECT, it still may not
+ // really be free. The IsFree function will return
+ // TRUE if it is OK to allocate.
+ if ((sectCurrent == FREESECT) &&
+ ((sc = IsFree(sect)) == S_OK))
+ {
+ //Mark the sector as free and return it.
+ msfChkTo(Err_Rel, MarkSect(&gf));
+
+ ulCount--;
+
+ //Update the contig table with this new information.
+
+ if (cSegCurrent < CSEG)
+ {
+ if (sect != sectLast + 1)
+ {
+ //Use a new entry in the contig table.
+ cSegCurrent++;
+ if (cSegCurrent < CSEG)
+ {
+ aseg[cSegCurrent].ulOffset =
+ aseg[cSegCurrent - 1].ulOffset +
+ aseg[cSegCurrent - 1].cSect;
+ aseg[cSegCurrent].sectStart = sect;
+ aseg[cSegCurrent].cSect = 1;
+ }
+ }
+ else
+ {
+ //Grow the current segment
+ aseg[cSegCurrent].cSect++;
+ }
+ }
+
+ if (ulCount == 0)
+ {
+ //If we're done, release the current table,
+ // update _sectMax, and return.
+
+ if (sect >= _sectMax)
+ {
+ _sectMax = sect + 1;
+ }
+
+ *pcSegReturned = cSegCurrent;
+ ReleaseGetFreeStruct(&gf);
+#if DBG == 1
+ _fv.ResetBits();
+ CheckFreeCount();
+#endif
+
+ return S_OK;
+ }
+ else
+ {
+ //Otherwise update the internal counters and
+ // keep going.
+ sectLast = sect;
+ ipfsLast = ipfs;
+ isectLast = isect;
+ }
+ }
+ else
+ {
+ msfChkTo(Err_Rel, sc);
+ }
+
+ }
+
+ _fv.ReleaseTable(ipfs);
+ //If we are keeping a full bit, we can set it here, since
+ // we know we've allocated everything out of the current
+ // page.
+ if (pfb != NULL)
+ {
+ pfb->full = TRUE;
+ }
+ }
+ isectStart = 0;
+ }
+
+ //Keep _sectMax up to date for SetSize purposes.
+ if (sectLast >= _sectMax)
+ {
+ _sectMax = sectLast + 1;
+ }
+ }
+ msfAssert(0 &&
+ aMsg("GetFree exited improperly."));
+ sc = STG_E_ABNORMALAPIEXIT;
+
+Err:
+ ReleaseGetFreeStruct(&gf);
+ return sc;
+
+Err_Rel:
+ ReleaseGetFreeStruct(&gf);
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::Contig, public
+//
+// Synposis: Create contiguous sector table
+//
+// Effects: Return contiguity information about a chain.
+//
+// Arguments: [aseg] -- Segment table to return data in
+// [sect] -- Starting sector for table to begin
+// [ulength] -- Runlength in sectors of table to produce
+// [pcSeg] -- Returns count of segments in table
+//
+// Returns: Appropriate status code.
+//
+// Algorithm: Perform calls to CFat::GetNext(). Any call that is
+// 1 higher than the previous represents contiguous blocks.
+// Construct the Segment table on that basis.
+//
+// History: 16-Aug-91 PhilipLa Created.
+// 20-May-92 AlexT Moved to CFat
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_Contig)
+#endif
+
+SCODE FAT_CLASS CFat::Contig(
+ SSegment STACKBASED *aseg,
+ BOOL fWrite,
+ SECT sectStart,
+ ULONG ulLengthStart,
+ ULONG *pcSeg)
+{
+ msfDebugOut((DEB_ITRACE,"In CFat::Contig(%lu,%lu)\n",sectStart,ulLengthStart));
+ SCODE sc = S_OK;
+
+ ULONG ulLength = ulLengthStart;
+ SECT sect = sectStart;
+ SECT stemp = sect;
+ ULONG ulCount = 1;
+ USHORT iseg = 0;
+ FSINDEX ipfs = (FSINDEX) -1;
+ FSINDEX ipfsOld = ipfs;
+ FSOFFSET isect;
+ CFatSect *pfs;
+
+ msfAssert(sect != ENDOFCHAIN &&
+ aMsg("Called Contig with ENDOFCHAIN start"));
+
+ msfAssert((ulLength > 0) && aMsg("Bad length passed to Contig()"));
+ aseg[iseg].sectStart = sect;
+ aseg[iseg].cSect = 1;
+ aseg[iseg].ulOffset = 0;
+ ulLength--;
+
+ while (TRUE)
+ {
+ msfAssert(sect != ENDOFCHAIN &&
+ aMsg("Contig found premature ENDOFCHAIN"));
+
+ SectToPair(sect, &ipfs, &isect);
+
+ if (ipfs != ipfsOld)
+ {
+ if (ipfsOld != (FSINDEX) -1)
+ {
+ _fv.ReleaseTable(ipfsOld);
+ }
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+ ipfsOld = ipfs;
+ }
+
+ sect = pfs->GetSect(isect);
+
+ if (sect == ENDOFCHAIN)
+ {
+ if ((ulLength < 1) || !fWrite)
+ break;
+
+ //Allocate new sectors.
+#if 0
+ SECT sectNew;
+ msfChk(GetFree(ulLength, &sectNew, GF_WRITE));
+ msfChk(SetNext(stemp, sectNew));
+ sect = sectNew;
+#else
+ //GetFreeContig will allocate new sectors and fill up
+ // our contig table. After this call, the chain will
+ // be the proper length and the contig table will either
+ // contain the entire chain, or will be full. Either
+ // way we can exit immediately.
+
+ if (ipfs != (FSINDEX) - 1)
+ {
+ _fv.ReleaseTable(ipfs);
+ }
+
+ ULONG isegRet;
+ aseg[iseg].cSect = ulCount;
+ msfChk(GetFreeContig(ulLength, aseg, iseg, &isegRet));
+ if (isegRet == CSEG)
+ {
+ aseg[isegRet].ulOffset = 0;
+ aseg[isegRet].cSect = 0;
+ aseg[isegRet].sectStart = FREESECT;
+ }
+ else
+ {
+ aseg[isegRet + 1].sectStart = ENDOFCHAIN;
+ }
+ *pcSeg = isegRet + 1;
+#if DBG == 1
+ SSegment segtab[CSEG + 1];
+ ULONG cSeg;
+ Contig(segtab, FALSE, sectStart, ulLengthStart, &cSeg);
+ msfAssert(cSeg == *pcSeg);
+ for (USHORT i = 0; i < cSeg; i++)
+ {
+ msfAssert(segtab[i].sectStart == aseg[i].sectStart);
+ msfAssert(segtab[i].ulOffset == aseg[i].ulOffset);
+ msfAssert(segtab[i].cSect == aseg[i].cSect);
+ }
+#endif
+ return S_OK;
+#endif
+ }
+
+ if (sect != (stemp + 1))
+ {
+ if (ulLength < 1)
+ break;
+
+ aseg[iseg].cSect = ulCount;
+ iseg++;
+ aseg[iseg].ulOffset = aseg[iseg - 1].ulOffset + ulCount;
+ aseg[iseg].sectStart = sect;
+ ulCount = 1;
+ stemp = sect;
+ }
+ else
+ {
+ ulCount++;
+ stemp = sect;
+ }
+ if (ulLength > 0)
+ ulLength--;
+
+ if (iseg >= CSEG)
+ break;
+ }
+ if (ipfs != (FSINDEX) -1)
+ {
+ _fv.ReleaseTable(ipfs);
+ }
+
+ if (iseg < CSEG)
+ {
+ aseg[iseg].cSect = ulCount;
+ aseg[iseg + 1].sectStart = ENDOFCHAIN;
+ }
+ else
+ {
+ aseg[iseg].ulOffset = 0;
+ aseg[iseg].cSect = 0;
+ aseg[iseg].sectStart = FREESECT;
+ }
+
+ *pcSeg = iseg + 1;
+ msfDebugOut((DEB_ITRACE,"Exiting Contig()\n"));
+
+Err:
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFat::ReserveSects, public
+//
+// Synopsis: Make sure the fat has at least a given number of free
+// sectors in it.
+//
+// Arguments: [cSect] -- Number of sectors to reserve.
+//
+// Returns: Appropriate status code
+//
+// History: 18-Sep-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CFat::ReserveSects(ULONG cSect)
+{
+ SCODE sc = S_OK;
+
+ msfDebugOut((DEB_ITRACE, "In CFat::ReserveSects:%p()\n", this));
+
+ //Make sure there are enough free sectors to hold the whole chain
+ // we're trying to allocate.
+ if (_ulFreeSects == MAX_ULONG)
+ {
+ msfChk(CountFree(&_ulFreeSects));
+ }
+#if DBG == 1
+ else
+ {
+ CheckFreeCount();
+ }
+#endif
+
+ while (cSect > _ulFreeSects)
+ {
+#if DBG == 1 && !defined(USE_NOSCRATCH)
+ ULONG ulFree = _ulFreeSects;
+#endif
+ msfChk(Resize(_cfsTable +
+ ((cSect - _ulFreeSects + _fv.GetSectTable() - 1) >>
+ _uFatShift)));
+#if DBG == 1 && !defined(USE_NOSCRATCH)
+ msfAssert(_ulFreeSects > ulFree &&
+ aMsg("Number of free sectors didn't increase after Resize."));
+#endif
+
+ }
+
+ msfDebugOut((DEB_ITRACE, "Out CFat::ReserveSects\n"));
+Err:
+ return sc;
+}
+
+#else
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::GetFree, private
+//
+// Synposis: Locate and return a free sector in the FAT
+//
+// Effects: May modify full bit on full sectors
+//
+// Arguments: [psectRet] -- Pointer to return value
+//
+// Returns: S_OK if call completed successfully.
+//
+// Algorithm: Do a linear search of all tables until a free sector is
+// found. If all tables are full, extend the FAT by one
+// sector.
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 22-Jul-91 PhilipLa Added FAT extension.
+// 17-Aug-91 PhilipLa Added full bits optimization
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_GetFree)
+#endif
+
+#ifndef REF
+SCODE FAT_CLASS CFat::GetFree(ULONG ulCount, SECT *psectRet, BOOL fReadOnly)
+#else
+SCODE FAT_CLASS CFat::GetFree(ULONG ulCount, SECT *psectRet)
+#endif //!REF
+{
+ FSINDEX ipfs;
+ FSOFFSET isect;
+ SECT sectRetval = 0;
+ SCODE sc;
+
+ SECT sectLast = ENDOFCHAIN;
+ FSINDEX ipfsLast;
+ FSOFFSET isectLast;
+
+ *psectRet = ENDOFCHAIN;
+
+#ifndef REF
+ msfAssert((!_pmsParent->IsShadow()) &&
+ aMsg("Modifying shadow fat."));
+
+ msfAssert(((!fReadOnly) || (ulCount == 1)) &&
+ aMsg("Read-only GetFree called with ulCount != 1"));
+#endif //!REF
+
+#ifdef USE_NOSCRATCH
+ if ((fReadOnly) && (_pfatNoScratch != NULL))
+ {
+ //As an optimization, and to prevent loops, we can dispatch
+ //this call directly to the no-scratch fat, since it has a
+ //complete picture of everything allocated in this fat.
+
+ //Note that we don't need to pass the read-only flag to the
+ //no-scratch, since it's perfectly OK to scribble on it
+ //as much as we want.
+ msfChk(_pfatNoScratch->GetFree(ulCount, psectRet, GF_WRITE));
+ if (_ulFreeSects != MAX_ULONG)
+ {
+ _ulFreeSects -= ulCount;
+ }
+
+ _cUnmarkedSects++;
+ if (*psectRet >= _sectMax)
+ {
+ _sectMax = *psectRet + 1;
+ }
+ return sc;
+ }
+#endif
+
+ while (TRUE)
+ {
+ if (_ulFreeSects == MAX_ULONG)
+ {
+ msfChk(CountFree(&_ulFreeSects));
+ }
+#if DBG == 1
+ else
+ {
+ CheckFreeCount();
+ }
+#endif
+
+ while (ulCount > _ulFreeSects)
+ {
+#if DBG == 1 && !defined(USE_NOSCRATCH)
+ ULONG ulFree = _ulFreeSects;
+#endif
+ msfChk(Resize(_cfsTable +
+ ((ulCount - _ulFreeSects + _fv.GetSectTable() - 1) >>
+ _uFatShift)));
+#if DBG == 1 && !defined(USE_NOSCRATCH)
+ msfAssert(_ulFreeSects > ulFree &&
+ aMsg("Number of free sectors didn't increase after Resize."));
+#endif
+
+ }
+
+ FSOFFSET isectStart;
+ FSINDEX ipfsStart;
+
+ SectToPair(_sectFirstFree, &ipfsStart, &isectStart);
+
+ for (ipfs = ipfsStart; ipfs < _cfsTable; ipfs++)
+ {
+ CVectBits *pfb = _fv.GetBits(ipfs);
+ if ((pfb == NULL) || (!pfb->full))
+ {
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+ if (pfb != NULL)
+ {
+ isectStart = pfb->firstfree;
+ }
+
+ for (isect = isectStart; isect < _fv.GetSectTable(); isect++)
+ {
+ SECT sectCurrent = pfs->GetSect(isect);
+ SECT sectNew = PairToSect(ipfs, isect);
+
+#ifndef REF
+ if (sectCurrent == FREESECT)
+ {
+ msfChkTo(Err_Rel, IsFree(sectNew));
+
+ if (sc == S_FALSE)
+ {
+ sectCurrent = ENDOFCHAIN;
+ }
+ }
+#endif //!REF
+
+ if (sectCurrent == FREESECT)
+ {
+ msfAssert(_ulFreeSects != MAX_ULONG &&
+ aMsg("Free sect count not set"));
+
+ _ulFreeSects--;
+
+ sectRetval = sectNew;
+#ifndef REF
+#ifdef SECURE
+#ifdef SECURETEST
+ if (_sid == SIDFAT)
+ {
+ BYTE *pb = (BYTE *) DfMemAlloc(SECTORSIZE);
+ if (pb)
+ memset(pb, 'Q', SECTORSIZE);
+
+ //Write out sector.
+ ULONG cbWritten;
+ ULARGE_INTEGER ulOff;
+ ULISet32(ulOff,
+ ConvertSectOffset(
+ sectRetval,
+ 0,
+ _pmsParent->GetSectorShift()));
+
+ _pmsParent->GetILB()->WriteAt(
+ ulOff,
+ pb,
+ SECTORSIZE,
+ &cbWritten);
+
+ DfMemFree(pb);
+ }
+#endif //SECURETEST
+#endif //SECURE
+ if (fReadOnly)
+ {
+ _fv.ReleaseTable(ipfs);
+ *psectRet = sectRetval;
+ if (sectRetval >= _sectMax)
+ {
+ _sectMax = sectRetval + 1;
+ }
+ _cUnmarkedSects++;
+ return S_OK;
+ }
+#endif //!REF
+
+ if (pfb != NULL)
+ {
+ pfb->firstfree = isect + 1;
+ }
+
+ msfAssert(sectRetval >= _sectFirstFree &&
+ aMsg("Found free sector before _sectFirstFree"));
+ _sectFirstFree = sectRetval + 1;
+
+ pfs->SetSect(isect, ENDOFCHAIN);
+
+#ifdef USE_NOSCRATCH
+ if (_pfatNoScratch != NULL)
+ {
+ //In no-scratch, update the no-scratch fat
+ //as well.
+ msfChkTo(Err_Rel, _pfatNoScratch->SetNext(
+ sectRetval, ENDOFCHAIN));
+ }
+#endif
+
+ msfChkTo(Err_Rel, _fv.SetDirty(ipfs));
+
+ if (sectLast != ENDOFCHAIN)
+ {
+ if (ipfsLast == ipfs)
+ {
+#ifdef USE_NOSCRATCH
+ if (_pfatNoScratch != NULL)
+ {
+ //In no-scratch, update the no-scratch fat
+ //as well.
+ msfChkTo(Err_Rel, _pfatNoScratch->SetNext(
+ sectLast, sectRetval));
+ }
+#endif
+ pfs->SetSect(isectLast, sectRetval);
+ }
+ else
+ {
+ CFatSect *pfsLast;
+
+ if (_pmsParent->IsScratch())
+ {
+ _fv.ReleaseTable(ipfs);
+ }
+
+ msfChkTo(Err_Rel, _fv.GetTable(
+ ipfsLast,
+ FB_DIRTY,
+ &pfsLast));
+
+ pfsLast->SetSect(isectLast, sectRetval);
+#ifdef USE_NOSCRATCH
+ if (_pfatNoScratch != NULL)
+ {
+ //In no-scratch, update the no-scratch fat
+ //as well.
+ msfChkTo(Err_Rel, _pfatNoScratch->SetNext(
+ sectLast, sectRetval));
+ }
+#endif
+ _fv.ReleaseTable(ipfsLast);
+
+ if (_pmsParent->IsScratch())
+ {
+ msfChk(_fv.GetTable(ipfs, FB_DIRTY, &pfs));
+ }
+ }
+ }
+
+ if (*psectRet == ENDOFCHAIN)
+ {
+ *psectRet = sectRetval;
+ }
+
+ ulCount--;
+
+ if (ulCount == 0)
+ {
+ _fv.ReleaseTable(ipfs);
+
+ if (sectRetval >= _sectMax)
+ {
+ _sectMax = sectRetval + 1;
+ }
+ return S_OK;
+ }
+ else
+ {
+ sectLast = sectRetval;
+ ipfsLast = ipfs;
+ isectLast = isect;
+ }
+ }
+ }
+ _fv.ReleaseTable(ipfs);
+ if (pfb != NULL)
+ {
+ pfb->full = TRUE;
+ }
+ }
+ isectStart = 0;
+ }
+ if (sectRetval >= _sectMax)
+ {
+ _sectMax = sectRetval + 1;
+ }
+ }
+ msfAssert(0 &&
+ aMsg("GetFree exited improperly."));
+ sc = STG_E_ABNORMALAPIEXIT;
+
+ Err:
+ return sc;
+
+ Err_Rel:
+ _fv.ReleaseTable(ipfs);
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::Contig, public
+//
+// Synposis: Create contiguous sector table
+//
+// Effects: Return contiguity information about a chain.
+//
+// Arguments: [aseg] -- Segment table to return data in
+// [sect] -- Starting sector for table to begin
+// [ulength] -- Runlength in sectors of table to produce
+// [pcSeg] -- Returns count of segments in table
+//
+// Returns: Appropriate status code.
+//
+// Algorithm: Perform calls to CFat::GetNext(). Any call that is
+// 1 higher than the previous represents contiguous blocks.
+// Construct the Segment table on that basis.
+//
+// History: 16-Aug-91 PhilipLa Created.
+// 20-May-92 AlexT Moved to CFat
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_Contig)
+#endif
+
+SCODE FAT_CLASS CFat::Contig(
+ SSegment STACKBASED *aseg,
+ BOOL fWrite,
+ SECT sect,
+ ULONG ulLength,
+ ULONG *pcSeg)
+{
+ msfDebugOut((DEB_ITRACE,"In CFat::Contig(%lu,%lu)\n",sect,ulLength));
+ SCODE sc = S_OK;
+
+ SECT stemp = sect;
+ ULONG ulCount = 1;
+ USHORT iseg = 0;
+ FSINDEX ipfs = (FSINDEX) -1;
+ FSINDEX ipfsOld = ipfs;
+ FSOFFSET isect;
+ CFatSect *pfs;
+
+ msfAssert(sect != ENDOFCHAIN &&
+ aMsg("Called Contig with ENDOFCHAIN start"));
+
+ msfAssert((ulLength > 0) && aMsg("Bad length passed to Contig()"));
+ aseg[iseg].sectStart = sect;
+ aseg[iseg].cSect = 1;
+ aseg[iseg].ulOffset = 0;
+ ulLength--;
+
+ while (TRUE)
+ {
+ msfAssert(sect != ENDOFCHAIN &&
+ aMsg("Contig found premature ENDOFCHAIN"));
+
+ SectToPair(sect, &ipfs, &isect);
+
+ if (ipfs != ipfsOld)
+ {
+ if (ipfsOld != (FSINDEX) -1)
+ {
+ _fv.ReleaseTable(ipfsOld);
+ }
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+ ipfsOld = ipfs;
+ }
+
+ sect = pfs->GetSect(isect);
+
+ if (sect == ENDOFCHAIN)
+ {
+ if ((ulLength < 1) || !fWrite)
+ break;
+
+ //Allocate new sectors.
+
+ SECT sectNew;
+#ifndef REF
+ msfChk(GetFree(ulLength, &sectNew, GF_WRITE));
+#else
+ msfChk(GetFree(ulLength, &sectNew));
+#endif //!REF
+ msfChk(SetNext(stemp, sectNew));
+ sect = sectNew;
+ }
+
+ if (sect != (stemp + 1))
+ {
+ if (ulLength < 1)
+ break;
+
+ aseg[iseg].cSect = ulCount;
+ iseg++;
+ aseg[iseg].ulOffset = aseg[iseg - 1].ulOffset + ulCount;
+ aseg[iseg].sectStart = sect;
+ ulCount = 1;
+ stemp = sect;
+ }
+ else
+ {
+ ulCount++;
+ stemp = sect;
+ }
+ if (ulLength > 0)
+ ulLength--;
+
+ if (iseg >= CSEG)
+ break;
+ }
+ if (ipfs != (FSINDEX) -1)
+ {
+ _fv.ReleaseTable(ipfs);
+ }
+
+ if (iseg < CSEG)
+ {
+ aseg[iseg].cSect = ulCount;
+ aseg[iseg + 1].sectStart = ENDOFCHAIN;
+ }
+ else
+ {
+ aseg[iseg].sectStart = FREESECT;
+ }
+
+ *pcSeg = iseg + 1;
+ msfDebugOut((DEB_ITRACE,"Exiting Contig()\n"));
+
+Err:
+ return sc;
+}
+
+#endif //USE_NEW_GETFREE
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::GetLength, public
+//
+// Synposis: Return the length of a fat chain.
+//
+// Arguments: [sect] -- Sector to begin count at.
+//
+// Returns: Length of the chain, in sectors
+//
+// Algorithm: Traverse the chain until ENDOFCHAIN is reached.
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_GetLength)
+#endif
+
+SCODE FAT_CLASS CFat::GetLength(SECT sect, ULONG * pulRet)
+{
+ msfDebugOut((DEB_FAT,"In CFat::GetLength(%lu)\n",sect));
+ SCODE sc = S_OK;
+ ULONG csect = 0;
+
+ while (sect != ENDOFCHAIN)
+ {
+ msfChk(GetNext(sect, &sect));
+ csect++;
+ }
+
+ msfDebugOut((DEB_FAT,"FAT: GetLength returned %u\n",csect));
+ *pulRet = csect;
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::Init, public
+//
+// Synposis: Sets up a FAT, reading data from an existing stream
+//
+// Effects: Changes all _apfsTable entries, _cfsTable, and all
+// flags fields
+//
+// Arguments: None.
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Read size from first FAT in stream.
+// Resize array to necessary size.
+// Read in FAT sectors sequentially.
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_Init)
+#endif
+
+SCODE FAT_CLASS CFat::Init(CMStream *pmsParent,
+ FSINDEX cFatSect,
+ BOOL fConvert)
+{
+ SCODE sc;
+
+ msfDebugOut((DEB_FAT,"CFat::setup thinks the FAT is size %lu\n",cFatSect));
+
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pmsParent);
+
+ _uFatShift = pmsParent->GetSectorShift() - 2;
+ _uFatMask = (pmsParent->GetSectorSize() >> 2) - 1;
+ _fv.InitCommon(1 << _uFatShift, 1 << _uFatShift);
+
+ msfChk(_fv.Init(pmsParent, cFatSect));
+
+ _cfsTable = cFatSect;
+
+ USHORT cbSectorSize;
+ cbSectorSize = pmsParent->GetSectorSize();
+
+ _ulFreeSects = MAX_ULONG;
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFat::InitConvert, public
+//
+// Synopsis: Init function used for conversion
+//
+// Arguments: [sectData] -- number of sectors used by file
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: *Finish This*
+//
+// History: 28-May-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_InitConvert)
+#endif
+
+SCODE FAT_CLASS CFat::InitConvert(CMStream *pmsParent,
+ SECT sectData)
+{
+ SCODE sc;
+ msfDebugOut((DEB_FAT,"Doing conversion\n"));
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pmsParent);
+
+ msfAssert((sectData != 0) &&
+ aMsg("Attempt to convert zero length file."));
+
+ SECT sectMax = 0;
+ FSINDEX csectFat = 0;
+ FSINDEX csectLast;
+
+ _uFatShift = pmsParent->GetSectorShift() - 2;
+ _uFatMask = (pmsParent->GetSectorSize() >> 2) - 1;
+ _fv.InitCommon(1 << _uFatShift, 1 << _uFatShift);
+
+ if (_sid == SIDFAT)
+ {
+ SECT sectTotal;
+
+ //Since the fat needs to represent itself, we can't determine
+ // the actual number of sectors needed in one pass. We
+ // therefore loop, factoring in the number of fat sectors
+ // at each iteration, until we reach a stable state.
+ //
+ //As an example, consider the case where each fat sector represents
+ // 128 sectors and the file being converted is 128 sectors long.
+ // There will be no DIFat - therefore, we have 128 sectors needed
+ // on the first pass, which will require 1 fat sector to
+ // represent them. On the second pass, we discover that we
+ // actually need 2 fat sectors, since we now have 129 total
+ // sectors to allocate space for. The third pass will result
+ // in a stable state.
+ do
+ {
+ csectLast = csectFat;
+ sectTotal = sectData + pmsParent->GetHeader()->GetDifLength() +
+ csectFat + 1;
+ csectFat = (sectTotal + _fv.GetSectTable() - 1) >> _uFatShift;
+ }
+ while (csectLast != csectFat);
+ sectMax = sectData + pmsParent->GetHeader()->GetDifLength();
+ }
+ else
+ {
+ //The minifat doesn't need to represent itself, so we can
+ // compute the number of sectors needed in one pass.
+ sectMax = sectData;
+ csectFat = (sectMax + _fv.GetSectTable() -1) >> _uFatShift;
+ }
+
+ msfChk(_fv.Init(pmsParent, csectFat));
+
+ FSINDEX i;
+
+ if (_sid == SIDMINIFAT)
+ {
+ SECT sectFirst;
+ msfChk(pmsParent->GetFat()->Allocate(csectFat, &sectFirst));
+
+ pmsParent->GetHeader()->SetMiniFatStart(sectFirst);
+
+ pmsParent->GetHeader()->SetMiniFatLength(csectFat);
+ }
+
+
+ for (i = 0; i < csectFat; i++)
+ {
+ CFatSect *pfs;
+
+ msfChk(_fv.GetTable(i, FB_NEW, &pfs));
+ if (_sid == SIDFAT)
+ {
+ _fv.SetSect(i, sectMax + i);
+ pmsParent->GetDIFat()->SetFatSect(i, sectMax + i);
+ }
+ else
+ {
+#ifdef USE_NOSCRATCH
+ msfAssert(_pfatNoScratch == NULL);
+#endif
+ SECT sect;
+ msfChk(pmsParent->GetESect(_sid, i, &sect));
+ _fv.SetSect(i, sect);
+ }
+
+ _fv.ReleaseTable(i);
+ }
+
+
+ _cfsTable = csectFat;
+
+ if (_sid != SIDMINIFAT)
+ {
+
+ pmsParent->GetHeader()->SetFatLength(_cfsTable);
+
+ SECT sect;
+
+ if (sectData > 1)
+ {
+ for (sect = 0; sect < sectData - 2; sect++)
+ {
+ msfChk(SetNext(sect, sect + 1));
+ }
+
+ msfChk(SetNext(sectData - 2, ENDOFCHAIN));
+ msfChk(SetNext(sectData - 1, 0));
+ }
+ else
+ {
+ //In the event that the file to be converted is less
+ // than one sector long, we don't need to create a
+ // real chain, just a single terminated sector.
+ msfChk(SetNext(0, ENDOFCHAIN));
+ }
+
+
+ for (sect = sectData; sect < sectMax; sect++)
+ {
+ msfChk(SetNext(sect, DIFSECT));
+ }
+
+ for (USHORT i = 0; i < csectFat; i++)
+ {
+ msfChk(SetNext(sectMax + i, FATSECT));
+ }
+
+ //Set up directory chain.
+ msfChk(SetNext(sectMax + i, ENDOFCHAIN));
+
+ pmsParent->GetHeader()->SetDirStart(sectMax + i);
+
+ _ulFreeSects = (_cfsTable << _uFatShift) - (sectMax + csectFat + 1);
+ }
+ else
+ {
+ for (SECT sect = 0; sect < sectData -1; sect++)
+ {
+ msfChk(SetNext(sect, sect + 1));
+ }
+ msfChk(SetNext(sectData - 1, ENDOFCHAIN));
+ _ulFreeSects = (_cfsTable << _uFatShift) - sectData;
+ }
+
+#ifndef REF
+ if (!pmsParent->IsScratch())
+ {
+#endif //!REF
+ msfChk(pmsParent->SetSize());
+#ifndef REF
+ }
+#endif //!REF
+
+Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::InitNew, public
+//
+// Synposis: Sets up a FAT for a newly created multi-strean
+//
+// Effects: Changes all _apfsTable entries, _cfsTable, and all
+// flags fields
+//
+// Arguments: [pmsparent] -- pointer to parent Mstream
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Set parent pointer.
+// Allocate 1 sector for FAT and 1 for Directory.
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 17-Aug-91 PhilipLa Added dirty bits optimization (Dump)
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_InitNew)
+#endif
+
+SCODE FAT_CLASS CFat::InitNew(CMStream *pmsParent)
+{
+ msfDebugOut((DEB_FAT,"In CFat::InitNew()\n"));
+ SCODE sc;
+
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pmsParent);
+ _uFatShift = pmsParent->GetSectorShift() - 2;
+ _uFatMask = (pmsParent->GetSectorSize() >> 2) - 1;
+ _fv.InitCommon(1 << _uFatShift, 1 << _uFatShift);
+
+ FSINDEX count;
+ if (SIDMINIFAT == _sid)
+ count = pmsParent->GetHeader()->GetMiniFatLength();
+ else
+ count = pmsParent->GetHeader()->GetFatLength();
+
+ msfDebugOut((DEB_FAT,"Setting up Fat of size %lu\n",count));
+
+ msfChk(_fv.Init(pmsParent, count));
+
+ _cfsTable = count;
+
+ if (SIDFAT == _sid)
+ {
+ FSINDEX ipfs;
+ FSOFFSET isect;
+ CFatSect *pfs;
+
+ SectToPair(pmsParent->GetHeader()->GetFatStart(), &ipfs, &isect);
+ msfChk(_fv.GetTable(ipfs, FB_NEW, &pfs));
+ _fv.SetSect(ipfs, pmsParent->GetHeader()->GetFatStart());
+ _fv.ReleaseTable(ipfs);
+
+ msfChk(SetNext(pmsParent->GetHeader()->GetFatStart(), FATSECT));
+ msfDebugOut((DEB_ITRACE,"Set sector %lu (FAT) to ENDOFCHAIN\n",pmsParent->GetHeader()->GetFatStart()));
+
+ msfChk(SetNext(pmsParent->GetHeader()->GetDirStart(), ENDOFCHAIN));
+ msfDebugOut((DEB_ITRACE,"Set sector %lu (DIR) to ENDOFCHAIN\n",pmsParent->GetHeader()->GetDirStart()));
+ _ulFreeSects = (count << _uFatShift) - 2;
+ }
+ else
+ {
+ _ulFreeSects = 0;
+ }
+
+#ifndef REF
+ if (!pmsParent->IsScratch())
+ {
+#endif //!REF
+ msfChk(pmsParent->SetSize());
+#ifndef REF
+ }
+#endif //!REF
+
+ msfDebugOut((DEB_FAT,"Exiting CFat::setupnew()\n"));
+
+Err:
+ return sc;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::Resize, private
+//
+// Synposis: Resize FAT, both in memory and in the file
+//
+// Effects: Modifies _cfsTable, _apfsTable, and all flags fields
+//
+// Arguments: [ulSize] -- New size (in # of tables) for FAT
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Allocate new array of new size.
+// Copy over all old pointers.
+// Allocate new tables for any necessary.
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 18-Aug-91 PhilipLa Added dirty bits optimization
+//
+// Notes: BUGBUG: This routine currently cannot reduce the size of a
+// fat. This functionality needs to be added eventually.
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_Resize)
+#endif
+
+SCODE FAT_CLASS CFat::Resize(ULONG ulSize)
+{
+ msfDebugOut((DEB_FAT,"In CFat::Resize(%lu)\n",ulSize));
+ SCODE sc;
+
+ if (ulSize == _cfsTable)
+ {
+ return S_OK;
+ }
+
+ ULONG csect = _cfsTable;
+
+ msfAssert(ulSize > _cfsTable &&
+ aMsg("Attempted to shrink Fat"));
+
+
+ ULONG ipfs;
+ SECT sectNew;
+
+ CFat *pfat = _pmsParent->GetFat();
+
+
+#ifndef REF
+ if ((!_pmsParent->IsScratch()) && (_sid == SIDFAT))
+#else
+ if (_sid == SIDFAT)
+#endif //!REF
+ {
+
+ //Make sure we have enough space for all of the sectors
+ // to be allocated.
+
+ ULONG csectFat = ulSize - _cfsTable;
+ ULONG csectPerDif = (1 << _uFatShift) - 1;
+ ULONG csectDif = (csectFat + csectPerDif - 1) / csectPerDif;
+
+
+ //Assuming all the free sectors are at the end of the file,
+ // we need a file csectNew sectors long to hold them.
+
+ ULONG csectOld, csectNew;
+
+ msfChk(FindMaxSect(&csectOld));
+
+ // Every new sector added can conceivably cause a remap of
+ // another sector while in COW mode.
+ csectNew = csectOld +
+ ((csectFat + csectDif) * ((_sectLastUsed > 0) ? 2 : 1));
+
+ ULARGE_INTEGER cbSize;
+
+ ULISet32(cbSize, ConvertSectOffset(
+ csectNew,
+ 0,
+ _pmsParent->GetSectorShift()));
+
+ if (ULIGetLow(cbSize) > _pmsParent->GetParentSize())
+ {
+ msfHChk(_pmsParent->GetILB()->SetSize(cbSize));
+ }
+
+ //If we are the fat, we have enough space in the file for
+ // ourselves at this point.
+ }
+#ifndef REF
+ else if (_sid != SIDFAT)
+#else
+ else
+#endif //!REF
+ {
+ if (_cfsTable == 0)
+ {
+ msfChk(pfat->Allocate(ulSize, &sectNew));
+ _pmsParent->GetHeader()->SetMiniFatStart(sectNew);
+ }
+ else
+ {
+ sectNew = _pmsParent->GetHeader()->GetMiniFatStart();
+
+ SECT sectLast;
+ msfChk(pfat->GetESect(sectNew, ulSize - 1, &sectLast));
+
+ }
+
+#ifndef REF
+ if (!_pmsParent->IsScratch())
+ {
+#endif //!REF
+ msfChk(_pmsParent->SetSize());
+#ifndef REF
+ }
+#endif //!REF
+
+
+ msfChk(pfat->GetSect(sectNew, csect, &sectNew));
+
+ //If we are the Minifat, we have enough space in the underlying
+ // file for ourselves at this point.
+ }
+
+
+ _fv.Resize(ulSize);
+
+
+ for (ipfs = csect; ipfs < ulSize; ipfs++)
+ {
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NEW, &pfs));
+ _cfsTable = ipfs + 1;
+
+
+ if (_sid == SIDFAT)
+ {
+#ifdef USE_NOSNAPSHOT
+ if (_sectNoSnapshotFree != ENDOFCHAIN)
+ {
+ SECT sectStart, sectEnd;
+
+ _pmsParent->GetHeader()->SetFatLength(_cfsTable);
+
+ msfChk(GetFree(1, &sectNew, GF_READONLY));
+#ifdef DIFAT_LOOKUP_ARRAY
+ _pmsParent->GetDIFat()->CacheUnmarkedSect(sectNew,
+ FATSECT,
+ ENDOFCHAIN);
+#endif
+ msfChk(_pmsParent->GetDIFat()->SetFatSect(ipfs, sectNew));
+
+ msfAssert((_ulFreeSects != MAX_ULONG) &&
+ aMsg("Free count not set in no-snapshot"));
+
+ //We don't need to look at anything less than
+ //_sectNoSnapshotFree, since those are all by definition
+ //not free.
+ sectStart = max(PairToSect(ipfs, 0), _sectNoSnapshotFree);
+ sectEnd = PairToSect(ipfs, 0) + _fv.GetSectTable();
+
+ for (SECT sectChk = sectStart;
+ sectChk < sectEnd;
+ sectChk++)
+ {
+ if (IsFree(sectChk) == S_OK)
+ {
+ _ulFreeSects++;
+ }
+ }
+ CheckFreeCount();
+ }
+ else
+ {
+#endif //USE_NOSNAPSHOT
+#ifdef USE_NOSCRATCH
+ if (_pfatNoScratch != NULL)
+ {
+ SECT sectStart, sectEnd;
+
+ msfChk(GetFree(1, &sectNew, GF_READONLY));
+#ifdef DIFAT_LOOKUP_ARRAY
+ _pmsParent->GetDIFat()->CacheUnmarkedSect(sectNew,
+ FATSECT,
+ ENDOFCHAIN);
+#endif
+ if (_ulFreeSects != MAX_ULONG)
+ {
+ sectStart = PairToSect(ipfs, 0);
+ sectEnd = sectStart + _fv.GetSectTable();
+
+ for (SECT sectChk = sectStart;
+ sectChk < sectEnd;
+ sectChk++)
+ {
+ if (IsFree(sectChk) == S_OK)
+ {
+ _ulFreeSects++;
+ }
+ }
+ CheckFreeCount();
+ }
+ }
+ else
+#endif
+ {
+ _ulFreeSects += (1 << _uFatShift);
+#ifndef REF
+ msfChk(pfat->GetFree(1, &sectNew, GF_WRITE));
+#else
+ msfChk(pfat->GetFree(1, &sectNew));
+#endif //!REF
+ msfChk(pfat->SetNext(sectNew, FATSECT));
+ }
+ msfChk(_pmsParent->GetDIFat()->SetFatSect(ipfs, sectNew));
+#ifdef USE_NOSNAPSHOT
+ }
+#endif
+ }
+
+ msfAssert(sectNew != ENDOFCHAIN &&
+ aMsg("Bad sector returned for fatsect."));
+
+ _fv.SetSect(ipfs, sectNew);
+ _fv.ReleaseTable(ipfs);
+
+ if (_sid == SIDMINIFAT)
+ {
+ _ulFreeSects += (1 << _uFatShift);
+ msfChk(pfat->GetNext(sectNew, &sectNew));
+ }
+ }
+
+ CheckFreeCount();
+
+ msfDebugOut((DEB_FAT,"CFat::Resize() - all new objects allocated\n"));
+
+ if (SIDMINIFAT == _sid)
+ {
+ _pmsParent->GetHeader()->SetMiniFatLength(_cfsTable);
+ }
+ else
+ _pmsParent->GetHeader()->SetFatLength(_cfsTable);
+
+ //This setsize should only shrink the file.
+#if DBG == 1
+ STATSTG stat;
+
+ msfHChk(_pmsParent->GetILB()->Stat(&stat, STATFLAG_NONAME));
+#endif
+
+#ifndef REF
+ if (!_pmsParent->IsScratch())
+ {
+#endif //!REF
+ msfChk(_pmsParent->SetSize());
+#ifndef REF
+ }
+#endif //!REF
+
+#ifdef USE_NOSCRATCH
+ if ((_pfatNoScratch != NULL) && (_ulFreeSects == MAX_ULONG))
+ {
+ msfChk(CountFree(&_ulFreeSects));
+ }
+#endif
+
+#if DBG == 1
+ STATSTG statNew;
+
+ msfHChk(_pmsParent->GetILB()->Stat(&statNew, STATFLAG_NONAME));
+
+ msfAssert(ULIGetLow(statNew.cbSize) <= ULIGetLow(stat.cbSize));
+#endif
+
+ msfDebugOut((DEB_FAT,"Out CFat::Resize(%lu)\n",ulSize));
+
+Err:
+ msfAssert((_ulFreeSects != MAX_ULONG) &&
+ aMsg("Free sect count not set after Resize()."));
+ return sc;
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::Extend, private
+//
+// Synposis: Increase the size of an existing chain
+//
+// Effects: Modifies ulSize sectors within the fat. Causes one or
+// more sector writes.
+//
+// Arguments: [sect] -- Sector ID of last sector in chain to be extended
+// [ulSize] -- Number of sectors to add to chain
+//
+// Requires: sect must be at the end of a chain.
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Use calls to GetFree to allocate chain.
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 17-Aug-91 PhilipLa Added dirty bits opt (Dump)
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_Extend)
+#endif
+
+SCODE FAT_CLASS CFat::Extend(SECT sect, ULONG ulSize)
+{
+ SCODE sc;
+
+ msfDebugOut((DEB_FAT,"In CFat::Extend(%lu,%lu)\n",sect,ulSize));
+ SECT sectTemp;
+
+#ifndef REF
+ msfChk(GetFree(ulSize, &sectTemp, GF_WRITE));
+#else
+ msfChk(GetFree(ulSize, &sectTemp));
+#endif //!REF
+
+ //If this SetSize fails, clean up the new space and don't do anything
+ // to the original chain.
+ if (!_pmsParent->IsScratch())
+ {
+ msfChkTo(EH_OOD, _pmsParent->SetSize());
+ }
+
+ //If this SetNext fail calls, we're screwed. Return the error but
+ // don't attempt to cleanup.
+ msfChk(SetNext(sect, sectTemp));
+
+ msfDebugOut((DEB_FAT,"Out CFat::Extend()\n"));
+
+Err:
+ return sc;
+EH_OOD:
+ SetChainLength(sectTemp, 0);
+ return sc;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::GetNext, public
+//
+// Synposis: Returns the next sector in a chain, given a sector
+//
+// Arguments: [sect] -- Sector ID of any sector in a chain.
+//
+// Returns: Sector ID of next sector in chain, ENDOFCHAIN if at end
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_GetNext)
+#endif
+
+SCODE FAT_CLASS CFat::GetNext(const SECT sect, SECT * psRet)
+{
+ SCODE sc;
+
+ FSINDEX ipfs;
+ FSOFFSET isect;
+
+ msfAssert(sect <= MAXREGSECT &&
+ aMsg("Called GetNext() on invalid sector"));
+
+ SectToPair(sect, &ipfs, &isect);
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+
+ *psRet = pfs->GetSect(isect);
+
+ _fv.ReleaseTable(ipfs);
+
+ if (sect == *psRet)
+ {
+ msfAssert(sect != *psRet &&
+ aMsg("Detected loop in fat chain."));
+ return STG_E_ABNORMALAPIEXIT;
+ }
+ return S_OK;
+
+Err:
+ return sc;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::SetNext, private
+//
+// Synposis: Set the next sector in a chain
+//
+// Effects: Modifies a single entry within the fat.
+//
+// Arguments: [sectFirst] -- Sector ID of first sector
+// [sectNext] -- Sector ID of next sector
+//
+// Returns: void
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 17-Aug-91 PhilipLa Added dirty bits optimization
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_SetNext)
+#endif
+
+SCODE FAT_CLASS CFat::SetNext(SECT sectFirst, SECT sectNext)
+{
+ FSINDEX ipfs;
+ FSOFFSET isect;
+ SCODE sc;
+
+#ifndef REF
+ msfAssert((!_pmsParent->IsShadow()) &&
+ aMsg("Modifying shadow fat."));
+#endif //!REF
+
+ // creating infinite loops is a no-no
+ msfAssert(sectFirst != sectNext &&
+ aMsg("Attempted to create loop in Fat chain"));
+ msfAssert(sectFirst <= MAXREGSECT &&
+ aMsg("Called SetNext on invalid sector"));
+
+ SectToPair(sectFirst, &ipfs, &isect);
+
+ CFatSect *pfs;
+#ifdef USE_NOSCRATCH
+ SECT sectCurrent;
+
+ if (ipfs >= _cfsTable)
+ {
+ msfChk(Resize(ipfs + 1));
+ }
+
+ msfAssert(ipfs <= _cfsTable);
+#endif
+
+ msfChk(_fv.GetTable(ipfs, FB_DIRTY, &pfs));
+
+#ifdef USE_NOSCRATCH
+ sectCurrent = pfs->GetSect(isect);
+#endif
+
+ pfs->SetSect(isect,sectNext);
+
+ _fv.ReleaseTable(ipfs);
+
+ if (sectNext == FREESECT)
+ {
+ CVectBits *pfb;
+ pfb = _fv.GetBits(ipfs);
+
+ if ((pfb != NULL) &&
+ ((pfb->full == TRUE) || (isect < pfb->firstfree)))
+ {
+ pfb->full = FALSE;
+ pfb->firstfree = isect;
+ }
+
+ if (sectFirst == _sectMax - 1)
+ {
+ _sectMax = ENDOFCHAIN;
+ }
+ if (sectFirst < _sectFirstFree)
+ {
+ _sectFirstFree = sectFirst;
+ }
+
+ if (_ulFreeSects != MAX_ULONG)
+ {
+#ifndef REF
+ SECT sectOld = FREESECT;
+
+ msfChk(IsFree(sectFirst));
+
+ if (sc != S_FALSE)
+ {
+#endif //!REF
+ _ulFreeSects++;
+#ifndef REF
+ }
+#endif //!REF
+ }
+ }
+#ifdef USE_NOSCRATCH
+ else if (_pfatNoScratch != NULL)
+ {
+ //We need to update the noscratch fat as well.
+ msfChk(_pfatNoScratch->SetNext(sectFirst, sectNext));
+ }
+ else if (sectFirst >= _sectMax)
+ {
+ _sectMax = sectFirst + 1;
+#if DBG == 1
+ SECT sectLast;
+ msfChk(FindLast(&sectLast));
+ msfAssert(((_sectMax == sectLast) || (_sectMax == _sectLastUsed)) &&
+ aMsg("_sectMax doesn't match actual last sector"));
+#endif
+ }
+
+ //If we're the no-scratch fat, then we may be marking a free sector
+ //as allocated due to the real fat allocating it. In this case, we
+ //need to update our free sector count.
+ if ((_sid == SIDMINIFAT) && (_pmsParent->IsScratch()) &&
+ (sectCurrent == FREESECT) && (sectNext != FREESECT) &&
+ (_ulFreeSects != MAX_ULONG))
+ {
+ _ulFreeSects--;
+ }
+#endif
+
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::CountFree, private
+//
+// Synposis: Count and return the number of free sectors in the Fat
+//
+// Arguments: void.
+//
+// Returns: void.
+//
+// Algorithm: Do a linear search of the Fat, counting free sectors.
+// If a FatSect has its full bit set, it is not necessary
+// to search that FatSect.
+//
+// History: 11-Sep-91 PhilipLa Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_CountFree)
+#endif
+
+SCODE FAT_CLASS CFat::CountFree(ULONG * pulRet)
+{
+ msfDebugOut((DEB_FAT,"In CFat::CountFree()\n"));
+ SCODE sc = S_OK;
+
+ FSINDEX ipfs;
+ ULONG csectFree=0;
+ FSOFFSET isectStart;
+ FSINDEX ipfsStart;
+
+ SectToPair(_sectFirstFree, &ipfsStart, &isectStart);
+
+ for (ipfs = ipfsStart; ipfs < _cfsTable; ipfs++)
+ {
+ CVectBits *pfb = _fv.GetBits(ipfs);
+
+ if ((pfb == NULL) || (!pfb->full))
+ {
+ msfDebugOut((DEB_FAT,"Checking table %lu\n",ipfs));
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+
+ if (pfb != NULL)
+ {
+ isectStart = pfb->firstfree;
+ }
+
+ FSOFFSET isect;
+ for (isect = isectStart; isect < _fv.GetSectTable(); isect++)
+ {
+ SECT sectCurrent = pfs->GetSect(isect);
+ SECT sectNew = PairToSect(ipfs, isect);
+
+#ifndef REF
+ if (sectCurrent == FREESECT)
+ {
+ msfChkTo(Err_Rel, IsFree(sectNew));
+
+ if (sc == S_FALSE)
+ {
+ sectCurrent = ENDOFCHAIN;
+ }
+ }
+#endif //!REF
+
+
+ if (sectCurrent == FREESECT)
+ {
+ csectFree++;
+ }
+ }
+ _fv.ReleaseTable(ipfs);
+ }
+ isectStart = 0;
+ }
+ msfDebugOut((DEB_FAT,"Countfree returned %lu\n",csectFree));
+ *pulRet = csectFree;
+
+Err:
+ return sc;
+#ifndef REF
+
+Err_Rel:
+ _fv.ReleaseTable(ipfs);
+ return sc;
+#endif //!REF
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::GetSect, public
+//
+// Synposis: Return the nth sector in a chain
+//
+// Arguments: [sect] -- Sector ID of beginning of chain
+// [uNum] -- indicator of which sector is to be returned
+// [psectReturn] -- Pointer to storage for return value
+//
+// Returns: S_OK.
+//
+// Algorithm: Linearly traverse chain until numth sector
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_GetSect)
+#endif
+
+SCODE FAT_CLASS CFat::GetSect(SECT sect, ULONG ulNum, SECT * psectReturn)
+{
+ msfDebugOut((DEB_FAT,"In CFat::GetSect(%lu,%lu)\n",sect,ulNum));
+
+ SCODE sc = S_OK;
+
+ if (ulNum == 0)
+ {
+ msfDebugOut((DEB_FAT,"Out CFat::GetSect()=>%lu\n",sect));
+ }
+ else if ((SIDFAT == _sid) &&
+ (_pmsParent->GetHeader()->GetFatStart() == sect))
+ {
+ msfChk(_pmsParent->GetDIFat()->GetFatSect(ulNum, &sect));
+ }
+ else for (ULONG i = 0; i < ulNum; i++)
+ {
+ msfChk(GetNext(sect, &sect));
+ if (sect > MAXREGSECT)
+ {
+ //The stream isn't long enough, so stop.
+ msfAssert(sect == ENDOFCHAIN &&
+ aMsg("Found invalid sector in fat chain."));
+ break;
+ }
+ }
+
+ *psectReturn = sect;
+ msfDebugOut((DEB_FAT,"Out CFat::GetSect()=>%lu\n",sect));
+
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::GetESect
+//
+// Synposis: Return the nth sector in a chain, extending the chain
+// if necessary.
+//
+// Effects: Modifies fat (via Extend) if necessary
+//
+// Arguments: [sect] -- Sector ID of beginning of chain
+// [ulNum] -- Indicates which sector is to be returned
+// [psectReturn] -- Pointer to storage for return value
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Linearly search chain until numth sector is found. If
+// the chain terminates early, extend it as necessary.
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_GetESect)
+#endif
+
+SCODE FAT_CLASS CFat::GetESect(SECT sect, ULONG ulNum, SECT *psectReturn)
+{
+ msfDebugOut((DEB_FAT,"In CFat::GetESect(%lu,%lu)\n",sect,ulNum));
+
+ SCODE sc = S_OK;
+
+ ULONG i = 0;
+ while (i < ulNum)
+ {
+ SECT temp;
+ msfChk(GetNext(sect, &temp));
+
+ msfAssert(temp != FREESECT &&
+ aMsg("FREESECT found in chain."));
+
+ if (temp == ENDOFCHAIN)
+ {
+
+ //The stream isn't long enough, so extend it somehow.
+ ULONG need = ulNum - i;
+
+ msfAssert((SIDMINIFAT == _sid ||
+ sect != _pmsParent->GetHeader()->GetFatStart()) &&
+ aMsg("Called GetESect on Fat chain"));
+ msfChk(Extend(sect,need));
+ }
+ else
+ {
+ sect = temp;
+ i++;
+ }
+ }
+
+ msfDebugOut((DEB_FAT,"Exiting GetESect with result %lu\n",sect));
+ *psectReturn = sect;
+
+Err:
+ return sc;
+}
+
+
+
+#ifndef REF
+#if DBG == 1
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::checksanity, private
+//
+// Synposis: Print out a FAT chain. Used for debugging only.
+//
+// Arguments: [sectStart] -- sector to begin run at.
+//
+// Returns: void
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE FAT_CLASS CFat::checksanity(SECT sectStart)
+{
+ msfDebugOut((DEB_FAT,"Sanity Check (%i)\n\t",sectStart));
+ SCODE sc = S_OK;
+
+ while (sectStart != ENDOFCHAIN)
+ {
+ msfDebugOut((DEB_FAT | DEB_NOCOMPNAME,"%lu, ",sectStart));
+ msfChk(GetNext(sectStart, &sectStart));
+ }
+ msfDebugOut((DEB_FAT | DEB_NOCOMPNAME,"ENDOFCHAIN\n"));
+Err:
+ return sc;
+}
+
+#endif
+#endif //!REF
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::SetChainLength, private
+//
+// Synposis: Set the length of a fat chain. This is used to reduce
+// the length of the chain only. To extend a chain, use
+// Extend or GetESect
+//
+// Effects: Modifies the fat
+//
+// Arguments: [sectStart] -- Sector to begin at (head of chain)
+// [uLength] -- New length for chain
+//
+// Returns: void.
+//
+// Algorithm: Traverse chain until uLength is reached or the chain
+// terminates. If it terminates prematurely, return with
+// no other action. Otherwise, deallocate all remaining
+// sectors in the chain.
+//
+// History: 14-Aug-91 PhilipLa Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_SetChainLength)
+#endif
+
+SCODE FAT_CLASS CFat::SetChainLength(SECT sectStart, ULONG ulLength)
+{
+ msfDebugOut((DEB_FAT,"In CFat::SetChainLength(%lu,%lu)\n",sectStart,ulLength));
+ SCODE sc;
+
+ if (sectStart == ENDOFCHAIN) return S_OK;
+
+ for (USHORT ui = 1; ui < ulLength; ui++)
+ {
+ msfChk(GetNext(sectStart, &sectStart));
+ if (sectStart == ENDOFCHAIN) return S_OK;
+ }
+
+ msfAssert(sectStart != ENDOFCHAIN &&
+ aMsg("Called SetChainLength is ENDOFCHAIN start"));
+
+ SECT sectEnd;
+ sectEnd = sectStart;
+
+ msfChk(GetNext(sectStart, &sectStart));
+
+ if (ulLength != 0)
+ {
+ msfChk(SetNext(sectEnd, ENDOFCHAIN));
+ }
+ else
+ {
+ msfChk(SetNext(sectEnd, FREESECT));
+ }
+
+ while (sectStart != ENDOFCHAIN)
+ {
+ SECT sectTemp;
+ msfChk(GetNext(sectStart, &sectTemp));
+ msfChk(SetNext(sectStart, FREESECT));
+ sectStart = sectTemp;
+ }
+
+ msfDebugOut((DEB_FAT,"Out CFat::SetChainLength()\n"));
+
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFat::FindLast, private
+//
+// Synopsis: Find last used sector in a fat
+//
+// Returns: Location of last used sector
+//
+// Algorithm: Perform a backward linear search until a non-free
+// sector is found.
+//
+// History: 18-Dec-91 PhilipLa Created.
+//
+// Notes: Used for shadow fats only.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_FindLast)
+#endif
+
+SCODE FAT_CLASS CFat::FindLast(SECT * psectRet)
+{
+ SCODE sc = S_OK;
+ FSINDEX ipfs = _cfsTable;
+ SECT sect = 0;
+
+ while (ipfs > 0)
+ {
+ ipfs--;
+
+ FSOFFSET isect = _fv.GetSectTable();
+
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+
+ while (isect > 0)
+ {
+ isect--;
+
+ SECT sectCurrent = pfs->GetSect(isect);
+ SECT sectNew = PairToSect(ipfs, isect);
+ if (sectCurrent == FREESECT)
+ {
+ msfChkTo(Err_Rel, IsFree(sectNew));
+ if (sc == S_FALSE)
+ sectCurrent = ENDOFCHAIN;
+ }
+
+ if (sectCurrent != FREESECT)
+ {
+ msfDebugOut((DEB_FAT,"FindLast returns %lu\n",PairToSect(ipfs,isect)));
+ sect = sectNew + 1;
+ break;
+ }
+ }
+
+ _fv.ReleaseTable(ipfs);
+ if (sect != 0)
+ break;
+ }
+
+#ifdef USE_NOSNAPSHOT
+ //We need additional checks here since in some cases there aren't
+ //enough pages in the fat to hold _sectNoSnapshot (or _sectNoSnapshotFree).
+ //Returning too small a value could result in SetSizing the file to too
+ //small a size, which is data loss.
+ if (sect < _sectNoSnapshot)
+ {
+ sect = _sectNoSnapshot;
+ }
+ if ((_sectNoSnapshotFree != ENDOFCHAIN) && (sect < _sectNoSnapshotFree))
+ {
+ sect = _sectNoSnapshotFree;
+ }
+#endif
+
+ *psectRet = sect;
+Err:
+ return sc;
+Err_Rel:
+ _fv.ReleaseTable(ipfs);
+ return sc;
+}
+
+
+#ifndef REF
+//+-------------------------------------------------------------------------
+//
+// Method: CFat::Remap, public
+//
+// Synopsis: Remap a portion of a chain for copy-on-write
+//
+// Effects:
+//
+// Arguments: [sectStart] -- Sector marking the first sector in the chain
+// [oStart] -- Offset in sectors at which to begin the remap
+// [ulRunLength] -- Number of sectors to remap
+// [psectOldStart] -- Returns old location of first remapped
+// sector.
+// [psectNewStart] -- Returns new location of first sector
+// [psectOldEnd] -- Returns old location of last sector
+// [psectNewEnd] -- Returns new location of last sector
+//
+// Returns: Appropriate status code.
+// S_FALSE if everything succeeded but no sectors were
+// remapped.
+//
+// History: 18-Feb-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_Remap)
+#endif
+
+SCODE FAT_CLASS CFat::Remap(
+ SECT sectStart,
+ ULONG oStart,
+ ULONG ulRunLength,
+ SECT *psectOldStart,
+ SECT *psectNewStart,
+ SECT *psectOldEnd,
+ SECT *psectNewEnd)
+{
+ msfDebugOut((DEB_FAT,"In CFat::Remap(%lu, %lu, %lu)\n",sectStart,oStart,ulRunLength));
+
+ msfAssert(SIDMINIFAT != _sid &&
+ aMsg("Called Remap on Minifat"));
+ msfAssert(ulRunLength != 0 &&
+ aMsg("Called Remap with 0 runlength"));
+ msfAssert(!_pmsParent->IsScratch() &&
+ aMsg("Called Remap on scratch."));
+
+ BOOL fRemapped = FALSE;
+ SCODE sc = S_OK;
+ SECT sectPrev;
+ SECT sect;
+ USHORT uCount = 0;
+
+
+ *psectNewStart = ENDOFCHAIN;
+ *psectNewEnd = ENDOFCHAIN;
+#if DBG == 1
+ *psectOldStart = ENDOFCHAIN;
+ *psectOldEnd = ENDOFCHAIN;
+#endif
+
+ if (oStart == 0)
+ {
+ sectPrev = ENDOFCHAIN;
+ sect = sectStart;
+ }
+ else
+ {
+ msfChk(GetESect(sectStart, oStart - 1, &sectPrev));
+ msfChk(GetNext(sectPrev, &sect));
+ }
+
+ *psectOldStart = sect;
+
+ while ((uCount < ulRunLength) && (sect != ENDOFCHAIN))
+ {
+ if (uCount == ulRunLength - 1)
+ {
+ *psectOldEnd = sect;
+ }
+
+ msfChk(QueryRemapped(sect));
+ if (sc == S_FALSE)
+ {
+ SECT sectNew;
+
+ msfChk(GetFree(1, &sectNew, GF_WRITE));
+
+ msfDebugOut((DEB_ITRACE,"Remapping sector %lu to %lu\n",sect,sectNew));
+ if (sectPrev != ENDOFCHAIN)
+ {
+ msfChk(SetNext(sectPrev, sectNew));
+
+#ifdef USE_NOSCRATCH
+ if (_pfatNoScratch != NULL)
+ {
+ msfChk(_pfatNoScratch->SetNext(sectPrev, sectNew));
+ }
+#endif
+ }
+
+ msfAssert((sect != ENDOFCHAIN) &&
+ aMsg("Remap precondition failed."));
+
+ SECT sectTemp;
+ msfChk(GetNext(sect, &sectTemp));
+ msfChk(SetNext(sectNew, sectTemp));
+
+#ifdef USE_NOSCRATCH
+ if (_pfatNoScratch != NULL)
+ {
+ msfChk(_pfatNoScratch->SetNext(sectNew, sectTemp));
+ }
+#endif
+
+ msfChk(SetNext(sect, FREESECT));
+
+
+ fRemapped = TRUE;
+
+ if (uCount == 0)
+ {
+ *psectNewStart = sectNew;
+ }
+
+ if (uCount == ulRunLength - 1)
+ {
+ *psectNewEnd = sectNew;
+ }
+
+ sect = sectNew;
+ }
+ sectPrev = sect;
+ msfChk(GetNext(sect, &sect));
+ uCount++;
+ }
+
+ if ((*psectNewStart != ENDOFCHAIN) && (oStart == 0))
+ {
+ if (sectStart == _pmsParent->GetHeader()->GetDirStart())
+ _pmsParent->GetHeader()->SetDirStart(*psectNewStart);
+
+ if (sectStart == _pmsParent->GetHeader()->GetMiniFatStart())
+ _pmsParent->GetHeader()->SetMiniFatStart(*psectNewStart);
+ }
+
+ msfDebugOut((DEB_FAT,"Out CFat::Remap()=>%lu\n",*psectNewStart));
+
+Err:
+ if ((sc == S_OK) && !fRemapped)
+ sc = S_FALSE;
+ return sc;
+}
+#endif //!REF
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFat::FindMaxSect, private
+//
+// Synopsis: Return last used sector in current Fat.
+//
+// Arguments: None.
+//
+// Returns: Last used sector in current Fat
+//
+// History: 15-Dec-91 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CFat_FindMaxSect)
+#endif
+
+SCODE FAT_CLASS CFat::FindMaxSect(SECT *psectRet)
+{
+ SCODE sc = S_OK;
+
+#ifdef USE_NOSCRATCH
+ if (_pfatNoScratch != NULL)
+ {
+ return _pfatNoScratch->FindMaxSect(psectRet);
+ }
+#endif
+
+ if (_sectMax == ENDOFCHAIN)
+ {
+ msfChk(FindLast(psectRet));
+ }
+ else
+ {
+#if DBG == 1
+ SECT sectLast;
+ msfChk(FindLast(&sectLast));
+#ifndef REF
+ msfAssert(((_sectMax == sectLast) || (_sectMax == _sectLastUsed)) &&
+ aMsg("_sectMax doesn't match actual last sector"));
+#endif //!REF
+#endif
+ *psectRet = _sectMax;
+ }
+
+#ifndef REF
+ if (*psectRet < _sectLastUsed)
+ {
+ *psectRet = _sectLastUsed;
+ }
+#endif //!REF
+Err:
+ return sc;
+}
+
+
+
+#ifdef USE_NOSCRATCH
+//+---------------------------------------------------------------------------
+//
+// Member: CFat::InitScratch, public
+//
+// Synopsis: Initialize the fat based on another fat. This is used
+// for NOSCRATCH mode. The fats may have different sector
+// sizes.
+//
+// Arguments: [pfat] -- Pointer to fat to copy.
+// [fNew] -- TRUE if this is being called on an empty fat.
+//
+// Returns: Appropriate status code
+//
+// History: 20-Mar-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CFat::InitScratch(CFat *pfat, BOOL fNew)
+{
+ SCODE sc;
+
+ msfAssert((_sid == SIDMINIFAT) && (_pmsParent->IsScratch()) &&
+ aMsg("Called InitScratch on the wrong thing."));
+
+ USHORT cbSectorOriginal = pfat->_pmsParent->GetSectorSize();
+
+ USHORT cSectPerRealSect = _pmsParent->GetSectorSize() /
+ cbSectorOriginal;
+
+ //This routine copies the fat from the multistream passed in into
+ // the _minifat_ of the current multistream.
+
+ ULONG cfatOriginal = pfat->_cfsTable;
+
+ //Our minifat must be large enough to hold all of the necessary
+ //sectors. Set the size appropriately.
+ ULONG cMiniFatSize = (cfatOriginal + cSectPerRealSect - 1) /
+ cSectPerRealSect;
+
+ msfAssert(((!fNew) || (_cfsTable == 0)) &&
+ aMsg("fNew TRUE when fat non-empty."));
+
+ msfAssert(((fNew) || (_pfatReal == pfat)) &&
+ aMsg("Fat pointer changed between calls to InitScratch"));
+
+ _pfatReal = P_TO_BP(CBasedFatPtr, pfat);
+
+ if (cMiniFatSize > _cfsTable)
+ {
+ msfChk(Resize(cMiniFatSize));
+ }
+
+ ULONG ifs;
+ for (ifs = 0; ifs < cfatOriginal; ifs++)
+ {
+ CFatSect *pfs;
+ CFatSect *pfsCurrent;
+
+ //Get the sector from the original fat
+
+ msfChk(pfat->_fv.GetTable(ifs, FB_NONE, &pfs));
+ msfAssert(pfs != NULL);
+
+ //Write the sector into the appropriate place in this fat.
+ ULONG ifsCurrent;
+ ifsCurrent = ifs / cSectPerRealSect;
+
+ OFFSET off;
+ off = (USHORT)((ifs % cSectPerRealSect) * cbSectorOriginal);
+
+ msfChk(_fv.GetTable(ifsCurrent, FB_DIRTY, &pfsCurrent));
+
+ if (fNew)
+ {
+ memcpy((BYTE *)pfsCurrent + off, pfs, cbSectorOriginal);
+ }
+ else
+ {
+ //Merge the table into the current one.
+ for (USHORT i = 0; i < cbSectorOriginal / sizeof(SECT); i++)
+ {
+ SECT sectCurrent;
+ OFFSET offCurrent;
+ offCurrent = i + (off / sizeof(SECT));
+
+ sectCurrent = pfsCurrent->GetSect(offCurrent);
+
+ if (sectCurrent != STREAMSECT)
+ {
+ pfsCurrent->SetSect(offCurrent, pfs->GetSect(i));
+ }
+ }
+ }
+
+ _fv.ReleaseTable(ifsCurrent);
+ pfat->_fv.ReleaseTable(ifs);
+ }
+
+ msfAssert((pfat->_cUnmarkedSects == 0) &&
+ aMsg("Fat being copied has changes in DIF"));
+
+ _fv.ResetBits();
+ _ulFreeSects = MAX_ULONG;
+ _sectFirstFree = 0;
+ _sectLastUsed = 0;
+ _sectMax = ENDOFCHAIN;
+Err:
+ return sc;
+}
+#endif
+
+
+
+#ifdef USE_NOSNAPSHOT
+//+---------------------------------------------------------------------------
+//
+// Member: CFat::ResizeNoSnapshot, public
+//
+// Synopsis: Resize the fat to handle a no-snapshot commit. In
+// no-snapshot mode it is possible that another commit has
+// grown the file to the point where it cannot be contained in
+// the existing fat in this open, so we need to grow it before
+// we can continue with anything else.
+//
+// Arguments: None.
+//
+// Returns: Appropriate SCODE.
+//
+// History: 19-Jun-96 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CFat::ResizeNoSnapshot(void)
+{
+ SCODE sc = S_OK;
+ FSINDEX ipfs;
+ FSOFFSET isect;
+
+ //If we need to grow the fat to handle the previous commits (which is
+ // possible if other opens are doing a lot of writing), we do it here,
+ // since we know for certain that the first available sector is at
+ // _sectNoSnapshot.
+ SectToPair(_sectNoSnapshot, &ipfs, &isect);
+ if (ipfs >= _cfsTable)
+ {
+ //We know we have no free sectors, so we can set this here and
+ // Resize will end up with the correct value.
+ _ulFreeSects = 0;
+
+ //This Resize will also cause a resize in the DIFat if necessary.
+ sc = Resize(ipfs + 1);
+ CheckFreeCount();
+ }
+ return sc;
+}
+#endif
+
+#if DBG == 1
+void CFat::CheckFreeCount(void)
+{
+ SCODE sc;
+ if (_ulFreeSects != MAX_ULONG)
+ {
+ ULONG ulFree;
+ msfChk(CountFree(&ulFree));
+ if (ulFree != _ulFreeSects)
+ {
+ msfDebugOut((DEB_ERROR,
+ "Free count mismatch. Cached: %lu, Real: %lu."
+ " Difference: %lu\n",
+ _ulFreeSects,
+ ulFree,
+ ulFree - _ulFreeSects));
+ }
+ msfAssert((ulFree == _ulFreeSects) &&
+ aMsg("Free count doesn't match cached value."));
+ }
+Err:
+ return;
+}
+#endif
diff --git a/private/ole32/stg/msf/filelist.mk b/private/ole32/stg/msf/filelist.mk
new file mode 100644
index 000000000..c3c63ec9e
--- /dev/null
+++ b/private/ole32/stg/msf/filelist.mk
@@ -0,0 +1,33 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1992 **
+#********************************************************************
+
+MKNAME = msf
+!if "$(OLESEP)" != ""
+LIBS = $(CAIROLE)\stg\docfile\$(OBJDIR)\docfile.lib
+!endif
+
+CXXFILES = \
+ .\cache.cxx\
+ .\difat.cxx\
+ .\dir.cxx\
+ .\dirp.cxx\
+ .\dl.cxx\
+ .\fat.cxx\
+ .\header.cxx\
+ .\msf.cxx\
+ .\msfnew.cxx\
+ .\mstream.cxx\
+ .\page.cxx\
+ .\pbstream.cxx\
+ .\sstream.cxx\
+ .\tstream.cxx\
+ .\vect.cxx\
+ .\wep.cxx
+
+!if "$(PLATFORM)" != "MAC"
+PXXFILE = .\msfhead.cxx
+!endif
+
+!include $(CAIROLE)\stg\dfms.mk
diff --git a/private/ole32/stg/msf/header.cxx b/private/ole32/stg/msf/header.cxx
new file mode 100644
index 000000000..4d64f0c27
--- /dev/null
+++ b/private/ole32/stg/msf/header.cxx
@@ -0,0 +1,117 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: header.cxx
+//
+// Contents: Code to manage MSF header
+//
+// Classes: Defined in header.hxx
+//
+// History: 11-Dec-91 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+#pragma hdrstop
+
+#include <dfver.h>
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFHeader_CMSFHeader)
+#endif
+
+CMSFHeaderData::CMSFHeaderData(USHORT uSectorShift)
+{
+ msfAssert((CSECTFATREAL != CSECTFAT) || (sizeof(CMSFHeaderData) == HEADERSIZE));
+ _uSectorShift = uSectorShift;
+ _uMiniSectorShift = MINISECTORSHIFT;
+ _ulMiniSectorCutoff = MINISTREAMSIZE;
+
+ _clid = IID_NULL;
+
+ _uByteOrder = 0xFFFE;
+
+ _uMinorVersion = rmm;
+ _uDllVersion = rmj;
+
+ for (SECT sect = 0; sect < CSECTFAT; sect ++)
+ {
+ _sectFat[sect] = FREESECT;
+ }
+
+ _csectDif = 0;
+ _sectDifStart = ENDOFCHAIN;
+
+ _csectFat = 1;
+ _sectFat[0] = SECTFAT;
+ _sectDirStart = SECTDIR;
+
+ _csectMiniFat = 0;
+ _sectMiniFatStart = ENDOFCHAIN;
+
+ _signature = 0;
+ _usReserved = 0;
+ _ulReserved1 = _ulReserved2 = 0;
+
+ // Write DocFile signature
+ memcpy(abSig, SIGSTG, CBSIGSTG);
+}
+
+
+CMSFHeader::CMSFHeader(USHORT uSectorShift)
+ :_hdr(uSectorShift)
+{
+ //We set this to dirty here. There are three cases in which a header
+ // can be initialized:
+ //1) Creating a new docfile.
+ //2) Converting a flat file to a docfile.
+ //3) Opening an existing file.
+ //
+ //We have a separate CMStream::Init* function for each of these cases.
+ //
+ //We set the header dirty, then explicitly set it clean in case 3
+ // above. For the other cases, it is constructed dirty and we
+ // want it that way.
+
+ _fDirty = TRUE;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMSFHeader::Validate, public
+//
+// Synopsis: Validate a header.
+//
+// Returns: S_OK if header is valid.
+//
+// History: 21-Aug-92 PhilipLa Created.
+// 27-Jan-93 AlexT Changed to final signature
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFHeader_Validate)
+#endif
+
+SCODE CMSFHeader::Validate(VOID) const
+{
+ SCODE sc;
+
+ sc = CheckSignature((BYTE *)_hdr.abSig);
+ if (sc == S_OK)
+ {
+ // Check file format verson number
+ if (GetDllVersion() > rmj)
+ return STG_E_OLDDLL;
+
+ // check for unreasonably large SectorShift
+ if (GetSectorShift() > MAXSECTORSHIFT)
+ return STG_E_DOCFILECORRUPT;
+
+ }
+ return sc;
+}
diff --git a/private/ole32/stg/msf/makefile b/private/ole32/stg/msf/makefile
new file mode 100644
index 000000000..1bf10bce3
--- /dev/null
+++ b/private/ole32/stg/msf/makefile
@@ -0,0 +1,21 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1994 **
+#********************************************************************
+
+!ifdef NTMAKEENV
+
+all:
+ echo $(BUILDMSG)
+
+clean: all
+
+!else
+
+default: all
+!include filelist.mk
+
+!include $(COMMON)\src\win40.mk
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/stg/msf/mread.hxx b/private/ole32/stg/msf/mread.hxx
new file mode 100644
index 000000000..9f91a1b1d
--- /dev/null
+++ b/private/ole32/stg/msf/mread.hxx
@@ -0,0 +1,420 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: mread.hxx
+//
+// Contents: Multistream inline functions
+//
+// Classes: None.
+//
+// Functions: None
+//
+// History: 21-Apr-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __MREAD_HXX__
+#define __MREAD_HXX__
+
+#include <difat.hxx>
+#include <sstream.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Function: ConvertSectAndOffset
+//
+// Synopsis: Convert a sector and offset into a byte offset in
+// a stream.
+//
+// Arguments: [sect] -- Sector
+// [off] -- Offset
+// [uShift] -- Shift count for sectorsize
+//
+// Returns: Byte offset into stream.
+//
+// Algorithm: The byte offset is sect left-shifted uShift times,
+// plus the offset, plus SECTORSIZE bytes for the
+// header.
+//
+// History: 21-Apr-92 PhilipLa Created.
+// 05-May-92 PhilipLa Changed to use << instead of *
+//
+//--------------------------------------------------------------------------
+
+inline ULONG MSTREAM_CLASS ConvertSectOffset(SECT sect,
+ OFFSET off,
+ USHORT uShift)
+{
+ ULONG ulTemp = ((ULONG)sect << uShift) + HEADERSIZE +
+ (ULONG)off;
+ msfDebugOut((DEB_ITRACE,"Convert got %lu\n",ulTemp));
+ return ulTemp;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetStart, public
+//
+// Synopsis: Given an SID, return the starting sector
+//
+// Arguments: [sid] -- Sid to find start for
+//
+// Returns: Starting sector for given SID.
+//
+// History: 21-Apr-92 PhilipLa Created.
+//
+// Notes: This function only works for controls structures,
+// not for ordinary streams.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_GetStart)
+#endif
+
+inline SECT MSTREAM_CLASS CMStream::GetStart(SID sid) const
+{
+ SECT sectRet;
+ msfAssert(sid > MAXREGSID);
+
+ switch (sid)
+ {
+ case SIDFAT:
+ sectRet = _hdr.GetFatStart();
+ break;
+ case SIDDIR:
+ sectRet = _hdr.GetDirStart();
+ break;
+ case SIDDIF:
+ sectRet = _hdr.GetDifStart();
+ break;
+ case SIDMINIFAT:
+ sectRet = _hdr.GetMiniFatStart();
+ break;
+ default:
+ msfAssert(FALSE && aMsg("Bad SID passed to CMStream::GetStart()"));
+ }
+ return sectRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::GetSize, public
+//
+// Synopsis: Return the size (in bytes) of a control structure chain
+//
+// Arguments: [sid] -- SID of chain
+// [pulSize] -- Location for return
+//
+// Returns: Appropriate status code
+//
+// History: 01-Jun-94 PhilipLa Created
+//
+// Notes: SID must be SIDDIR or SIDMINIFAT - other structures
+// do not have chains.
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CMStream::GetSize(SID sid, ULONG *pulSize)
+{
+ msfAssert(((sid == SIDDIR) || (sid == SIDMINIFAT)) &&
+ aMsg("Bad SID passed to CMStream::GetSize()"));
+
+ ULONG csect;
+
+ if (SIDDIR == sid)
+ {
+ csect = _dir.GetDirLength();
+ }
+ else
+ {
+ csect = _hdr.GetMiniFatLength();
+ }
+
+ *pulSize = csect * GetSectorSize();
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::GetSect, private
+//
+// Synopsis: For a given SID and sect, return the location of that
+// sector in the multistream.
+//
+// Arguments: [sid] -- SID of sector to locate
+// [sect] -- Offset into chain to locate
+// [psect] -- Pointer to return location.
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 22-Oct-92 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_GetSect)
+#endif
+
+inline SCODE CMStream::GetSect(SID sid, SECT sect, SECT *psect)
+{
+ SCODE sc;
+ SECT start;
+
+ switch (sid)
+ {
+ case SIDFAT:
+ msfChk(_fatDif.GetFatSect(sect, &start));
+ break;
+ case SIDDIF:
+ msfChk(_fatDif.GetSect(sect, &start));
+ break;
+ case SIDMINIFAT:
+ case SIDDIR:
+ CStreamCache *pstmc;
+ pstmc = (sid == SIDDIR) ? &_stmcDir : &_stmcMiniFat;
+ msfChk(pstmc->GetSect(sect, &start));
+ break;
+ default:
+ msfAssert(FALSE && aMsg("Bad SID passed to CMStream::GetSect()"));
+ }
+
+ *psect = start;
+Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::GetESect, private
+//
+// Synopsis: For a given SID and sect, return the location of that
+// sector in the multistream.
+//
+// Arguments: [sid] -- SID of sector to locate
+// [sect] -- Offset into chain to locate
+// [psect] -- Pointer to return location.
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 22-Oct-92 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_GetESect)
+#endif
+
+inline SCODE CMStream::GetESect(SID sid, SECT sect, SECT *psect)
+{
+ SCODE sc = S_OK;
+
+ SECT start;
+#ifndef REF
+ SECT sectNewStart, sectOldStart, sectNewEnd, sectOldEnd;
+
+ if ((_fBlockHeader) && (!_fBlockWrite))
+ {
+ switch (sid)
+ {
+ case SIDFAT:
+ SECT sectTest;
+ msfChk(_fatDif.Remap(sect, &sectTest));
+
+#ifdef DIFAT_OPTIMIZATIONS
+ if (sectTest != ENDOFCHAIN)
+ {
+ msfChk(_fatDif.Fixup(BP_TO_P(CMStream *, _pmsShadow)));
+ }
+#endif
+ break;
+ case SIDMINIFAT:
+ case SIDDIR:
+ CStreamCache *pstmc;
+ pstmc = (sid == SIDDIR) ? &_stmcDir : &_stmcMiniFat;
+
+ if (sect != 0)
+ {
+ msfChk(pstmc->GetSect(sect - 1, &start));
+ msfChk(_fat.Remap(
+ start,
+ 1,
+ 1,
+ &sectOldStart,
+ &sectNewStart,
+ &sectOldEnd,
+ &sectNewEnd));
+ }
+ else
+ {
+ start = GetStart(sid);
+ msfChk(_fat.Remap(
+ start,
+ 0,
+ 1,
+ &sectOldStart,
+ &sectNewStart,
+ &sectOldEnd,
+ &sectNewEnd));
+ }
+ //Must drop this value from the cache if it's in there.
+ if (sc != S_FALSE)
+ {
+ pstmc->EmptyRegion(sect, sect + 1);
+ }
+ break;
+ case SIDDIF:
+ break;
+ default:
+ msfAssert(FALSE && aMsg("Bad SID passed to CMStream::GetESect()"));
+ }
+ }
+#endif //!REF
+
+ switch (sid)
+ {
+ case SIDFAT:
+ msfChk(_fatDif.GetFatSect(sect, &start));
+ break;
+ case SIDDIF:
+ msfChk(_fatDif.GetSect(sect, &start));
+ break;
+ case SIDMINIFAT:
+ case SIDDIR:
+ CStreamCache *pstmc;
+ pstmc = (sid == SIDDIR) ? &_stmcDir : &_stmcMiniFat;
+
+ msfChk(pstmc->GetESect(sect, &start));
+ break;
+ default:
+ msfAssert(FALSE && aMsg("Bad SID passed to CMStream::GetESect()"));
+ }
+
+ *psect = start;
+Err:
+ return sc;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::SetSize, public
+//
+// Synposis: Sets the size of the parent LStream to match
+// current Fat information.
+//
+// Arguments: None.
+//
+// Returns: Error code from call to parent LStream SetSize()
+//
+// Algorithm: Query the Fat for the last sector used.
+// Convert that sector into a byte offset.
+// Call SetSize on the parent LStream.
+//
+// History: 30-Jul-91 PhilipLa Created.
+// 07-Jan-92 PhilipLa Converted to use handles.
+// 14-May-92 AlexT Move code to CDirectStream::SetSize
+//
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_SetSize) // Mstream_SetSize_TEXT
+#endif
+
+inline SCODE MSTREAM_CLASS CMStream::SetSize(VOID)
+{
+ SCODE sc = S_OK;
+ ULONG ulSize;
+
+ ULARGE_INTEGER cbSize;
+
+ msfDebugOut((DEB_ITRACE, "In CMStream::SetSize()\n"));
+
+ SECT sectMax;
+
+#ifndef REF
+ if (!_fBlockWrite)
+ {
+#endif //!REF
+ msfChk(_fat.GetMaxSect(&sectMax));
+ ulSize = ConvertSectOffset(sectMax, 0, GetSectorShift());
+
+#ifndef REF
+ if (ulSize > _ulParentSize)
+ {
+#endif //!REF
+ ULISet32(cbSize, ulSize);
+ msfHChk((*_pplstParent)->SetSize(cbSize));
+#ifndef REF
+ }
+ }
+#endif //!REF
+
+ msfDebugOut((DEB_ITRACE, "Out CMStream::SetSize()\n"));
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::SetMiniSize, public
+//
+// Synposis: Sets the size of the MiniFat storage stream to match
+// current Fat information.
+//
+// Arguments: None.
+//
+// Returns: Error code from call to stream SetSize()
+//
+// Algorithm: Query the Fat for the last sector used.
+// Convert that sector into a byte offset.
+// Call SetSize on the Minifat storage stream.
+//
+// History: 14-May-92 AlexT Created.
+//
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_SetMiniSize) //
+#endif
+
+inline SCODE MSTREAM_CLASS CMStream::SetMiniSize(VOID)
+{
+ SCODE sc;
+ ULONG ulNewSize;
+
+ SECT sectMax;
+ msfChk(_fatMini.GetMaxSect(&sectMax));
+ ulNewSize = sectMax << MINISECTORSHIFT;
+ msfChk(_pdsministream->CDirectStream::SetSize(ulNewSize));
+
+Err:
+ return sc;
+}
+
+#ifdef CODESEGMENTS
+#pragma code_seg()
+#endif
+
+#endif //__MREAD_HXX__
+
diff --git a/private/ole32/stg/msf/msf.cxx b/private/ole32/stg/msf/msf.cxx
new file mode 100644
index 000000000..3fac1db57
--- /dev/null
+++ b/private/ole32/stg/msf/msf.cxx
@@ -0,0 +1,493 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: msf.cxx
+//
+// Contents: Entry points for MSF DLL
+//
+// Classes: None.
+//
+// Functions: DllMuliStreamFromStream
+// DllConvertStreamToMultiStream
+// DllReleaseMultiStream
+// DllGetScratchMultiStream
+// DllIsMultiStream
+//
+// History: 17-Aug-91 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+#pragma hdrstop
+
+#include <handle.hxx>
+#include <filelkb.hxx>
+#include <ole.hxx>
+#include <entry.hxx>
+#include <smalloc.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllMultiStreamFromStream
+//
+// Synopsis: Create a new multistream instance from an existing stream.
+// This is used to reopen a stored multi-stream.
+//
+// Effects: Creates a new CMStream instance
+//
+// Arguments: [ppms] -- Pointer to storage for return of multistream
+// [pplstStream] -- Stream to be used by multi-stream for
+// reads and writes
+// [dwFlags] - Startup flags
+//
+// Returns: STG_E_INVALIDHEADER if signature on pStream does not
+// match.
+// STG_E_UNKNOWN if there was a problem in setup.
+// S_OK if call completed OK.
+//
+// Algorithm: Check the signature on the pStream and on the contents
+// of the pStream. If either is a mismatch, return
+// STG_E_INVALIDHEADER.
+// Create a new CMStream instance and run the setup function.
+// If the setup function fails, return STG_E_UNKNOWN.
+// Otherwise, return S_OK.
+//
+// History: 17-Aug-91 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_DllMultiStreamFromStream)
+#endif
+
+SCODE DllMultiStreamFromStream(IMalloc *pMalloc,
+ CMStream **ppms,
+ ILockBytes **pplstStream,
+ DWORD dwStartFlags,
+ DFLAGS df)
+{
+ SCODE sc;
+ CMStream *temp;
+
+
+ BOOL fConvert = ((dwStartFlags & RSF_CONVERT) != 0);
+#ifndef REF
+ BOOL fDelay = ((dwStartFlags & RSF_DELAY) != 0);
+#endif //!REF
+ BOOL fTruncate = ((dwStartFlags & RSF_TRUNCATE) != 0);
+ BOOL fCreate = ((dwStartFlags & RSF_CREATE) != 0);
+
+
+ msfDebugOut((DEB_ITRACE,"In DllMultiStreamFromStream\n"));
+
+#ifndef REF
+#ifdef USE_NOSCRATCH
+ msfMem(temp = new (pMalloc)
+ CMStream(pMalloc, pplstStream,
+ FALSE,
+ (df & ~DF_NOSCRATCH),
+ SECTORSHIFT));
+#else
+ msfMem(temp = new (pMalloc)
+ CMStream(pMalloc, pplstStream,
+ FALSE,
+ SECTORSHIFT));
+#endif //USE_NOSCRATCH
+#else
+ msfMem(temp = new (pMalloc)
+ CMStream(pMalloc, pplstStream, SECTORSHIFT));
+#endif //!REF
+
+ STATSTG stat;
+ HRESULT hr;
+ IFileLockBytes *pfl;
+
+ // ILockBytes::Stat is an expensive operation; for our own file
+ // stream we call our faster GetSize method.
+
+ if (SUCCEEDED((*pplstStream)->QueryInterface(IID_IFileLockBytes,
+ (void**) &pfl)))
+ {
+ msfAssert(pfl != NULL &&
+ aMsg("ILockBytes::QueryInterface succeeded but returned NULL"));
+ hr = pfl->GetSize(&stat.cbSize);
+ pfl->Release();
+ }
+ else
+ hr = (*pplstStream)->Stat(&stat, STATFLAG_NONAME);
+ msfHChk(hr);
+
+ msfAssert(ULIGetHigh(stat.cbSize) == 0);
+ msfDebugOut((DEB_ITRACE,"Size is: %lu\n",ULIGetLow(stat.cbSize)));
+
+ do
+ {
+ if ((ULIGetLow(stat.cbSize) != 0) && (fConvert))
+ {
+#ifndef REF
+ msfChk(temp->InitConvert(fDelay));
+#else
+ msfChk(temp->InitConvert());
+#endif //!REF
+ break;
+ }
+
+ if (((ULIGetLow(stat.cbSize) == 0) && fCreate) || (fTruncate))
+ {
+#ifndef REF
+ msfChk(temp->InitNew(fDelay, stat.cbSize));
+#else
+ msfChk(temp->InitNew(stat.cbSize));
+#endif //!REF
+ break;
+ }
+ msfChk(temp->Init());
+ }
+ while (FALSE);
+
+ *ppms = temp;
+
+ msfDebugOut((DEB_ITRACE,"Leaving DllMultiStreamFromStream\n"));
+
+#ifndef REF
+ if (fConvert && ULIGetLow(stat.cbSize) && !fDelay)
+#else
+ if (fConvert && ULIGetLow(stat.cbSize))
+#endif //!REF
+ {
+ return STG_S_CONVERTED;
+ }
+
+ return S_OK;
+
+Err:
+#if !defined(MULTIHEAP)
+ //take the mutex here instead of in the allocator.
+ g_smAllocator.GetMutex()->Take(DFM_TIMEOUT);
+#endif
+ delete temp;
+#if !defined(MULTIHEAP)
+ g_smAllocator.GetMutex()->Release();
+#endif
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllReleaseMultiStream
+//
+// Synopsis: Release a CMStream instance
+//
+// Effects: Deletes a multi-stream instance
+//
+// Arguments: [pms] -- pointer to object to be deleted
+//
+// Returns: S_OK.
+//
+// Modifies: Deletes the object pointed to by pMultiStream
+//
+// Algorithm: Delete the passed in pointer.
+//
+// History: 17-Aug-91 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_DllReleaseMultiStream) // inline?
+#endif
+
+void DllReleaseMultiStream(CMStream *pms)
+{
+ msfDebugOut((DEB_ITRACE,"In DllReleaseMultiStream(%p)\n",pms));
+#if !defined(MULTIHEAP)
+ //take the mutex here instead of in the allocator.
+ g_smAllocator.GetMutex()->Take(DFM_TIMEOUT);
+#endif
+ delete pms;
+#if !defined(MULTIHEAP)
+ g_smAllocator.GetMutex()->Release();
+#endif
+
+ msfDebugOut((DEB_ITRACE,"Out DllReleaseMultiStream()\n"));
+}
+
+
+
+#ifndef REF
+//+-------------------------------------------------------------------------
+//
+// Function: DllGetScratchMultiStream
+//
+// Synopsis: Get a scratch multistream for a given LStream
+//
+// Effects: Creates new MStream instance and new handle
+//
+// Arguments: [ppms] -- pointer to location in which root
+// handle is to be returned.
+// [pplstStream] -- pointer to LStream object to be used
+// [pmsMaster] - Multistream to pattern scratch after
+//
+// Returns: S_OK if call completed OK.
+// STG_E_UNKNOWN if there was a problem in setup.
+//
+// Algorithm: *Finish This*
+//
+// History: 08-Jan-91 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_DllGetScratchMultiStream)
+#endif
+
+
+SCODE DllGetScratchMultiStream(CMStream **ppms,
+#ifdef USE_NOSCRATCH
+ BOOL fIsNoScratch,
+#endif
+ ILockBytes **pplstStream,
+ CMStream *pmsMaster)
+{
+ msfDebugOut((DEB_ITRACE,"In DllGetScratchMultiStream(%p,%p,%p)\n",ppms,pplstStream,pmsMaster));
+ SCODE sc;
+ ULARGE_INTEGER uliZero;
+
+ CMStream *temp = NULL;
+
+#ifdef USE_NOSCRATCH
+ msfMem(temp = new (pmsMaster->GetMalloc())
+ CMStream(pmsMaster->GetMalloc(), pplstStream,
+ TRUE,
+ (fIsNoScratch) ? DF_NOSCRATCH : 0,
+ SCRATCHSECTORSHIFT));
+#else
+ msfMem(temp = new (pmsMaster->GetMalloc())
+ CMStream(pmsMaster->GetMalloc(), pplstStream,
+ TRUE,
+ SCRATCHSECTORSHIFT));
+#endif
+
+ ULISetHigh(uliZero, 0);
+ ULISetLow(uliZero, 0);
+ msfChk(temp->InitNew(FALSE, uliZero));
+ *ppms = temp;
+
+ msfDebugOut((DEB_ITRACE,"Out DllGetScratchMultiStream()\n"));
+ return S_OK;
+
+Err:
+#if !defined(MULTIHEAP)
+ //take the mutex here instead of in the allocator
+ g_smAllocator.GetMutex()->Take(DFM_TIMEOUT);
+#endif
+ delete temp;
+#if !defined(MULTIHEAP)
+ g_smAllocator.GetMutex()->Release();
+#endif
+ return sc;
+}
+#endif //!REF
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllIsMultiStream
+//
+// Synopsis: Check a given Lstream to determine if it is a valid
+// multistream.
+//
+// Arguments: [plst] -- Pointer to lstream to check
+//
+// Returns: S_OK if lstream is a valid multistream
+// STG_E_UNKNOWN otherwise
+//
+// History: 20-Feb-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_DllIsMultiStream)
+#endif
+
+SCODE DllIsMultiStream(ILockBytes *plst)
+{
+ SCODE sc;
+ CMSFHeader *phdr;
+ USHORT us;
+
+ GetSafeBuffer(sizeof(CMSFHeader), sizeof(CMSFHeader),
+ (BYTE **) &phdr, &us);
+
+ ULONG ulTemp;
+
+ ULARGE_INTEGER ulOffset;
+ ULISet32(ulOffset, 0);
+ msfHChk(plst->ReadAt(
+ ulOffset,
+ phdr->GetData(),
+ sizeof(CMSFHeaderData),
+ &ulTemp));
+
+ if (ulTemp != sizeof(CMSFHeaderData))
+ {
+ msfErr(Err, STG_E_UNKNOWN);
+ }
+
+ msfChk(phdr->Validate());
+
+Err:
+ FreeBuffer((BYTE *) phdr);
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllSetCommitSig
+//
+// Synopsis: Set the commit signature on a given lstream, for use
+// in OnlyIfCurrent support
+//
+// Arguments: [plst] -- Pointer to the LStream to modify.
+// [sig] -- New signature
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm:
+//
+// History: 22-Apr-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_DllSetCommitSig)
+#endif
+
+SCODE DllSetCommitSig(ILockBytes *plst, DFSIGNATURE sig)
+{
+ SCODE sc;
+ CMSFHeader *phdr;
+ USHORT us;
+
+ GetSafeBuffer(sizeof(CMSFHeader), sizeof(CMSFHeader),
+ (BYTE **) &phdr, &us);
+
+ ULONG ulTemp;
+
+ ULARGE_INTEGER ulOffset;
+ ULISet32(ulOffset, 0);
+ msfHChk(plst->ReadAt(
+ ulOffset,
+ phdr->GetData(),
+ sizeof(CMSFHeaderData),
+ &ulTemp));
+
+ if (ulTemp != sizeof(CMSFHeaderData))
+ {
+ msfErr(Err, STG_E_UNKNOWN);
+ }
+
+ msfChk(phdr->Validate());
+
+ phdr->SetCommitSig(sig);
+
+ msfHChk(plst->WriteAt(ulOffset,
+ phdr->GetData(),
+ sizeof(CMSFHeaderData),
+ &ulTemp));
+
+ if (ulTemp != sizeof(CMSFHeaderData))
+ {
+ msfErr(Err,STG_E_UNKNOWN);
+ }
+
+Err:
+ FreeBuffer((BYTE *) phdr);
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllGetCommitSig
+//
+// Synopsis: Get the commit signature from an lstream
+//
+// Arguments: [plst] -- Pointer to lstream to be operated on
+// [psig] -- Storage place for signature return
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm:
+//
+// History: 22-Apr-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_DllGetCommitSig)
+#endif
+
+SCODE DllGetCommitSig(ILockBytes *plst, DFSIGNATURE *psig)
+{
+ CMSFHeader *phdr;
+ SCODE sc;
+ USHORT us;
+
+ GetSafeBuffer(sizeof(CMSFHeader), sizeof(CMSFHeader),
+ (BYTE **) &phdr, &us);
+
+ ULONG ulTemp;
+
+ ULARGE_INTEGER ulOffset;
+ ULISet32(ulOffset, 0);
+ msfHChk(plst->ReadAt(
+ ulOffset,
+ phdr->GetData(),
+ sizeof(CMSFHeaderData),
+ &ulTemp));
+
+ if (ulTemp != sizeof(CMSFHeaderData))
+ {
+ msfErr(Err, STG_E_UNKNOWN);
+ }
+ msfChk(phdr->Validate());
+ *psig = phdr->GetCommitSig();
+
+Err:
+ FreeBuffer((BYTE *) phdr);
+ return sc;
+}
+
+
+#if DBG == 1
+
+//The following is a private function so I can set the debug level easily.
+VOID SetInfoLevel(ULONG x)
+{
+
+#ifndef REF
+#if DBG == 1
+ msfInfoLevel=x;
+ _SetWin4InfoLevel(0xFFFFFFFF);
+#endif
+#endif //!REF
+}
+
+#endif
diff --git a/private/ole32/stg/msf/msfhead.cxx b/private/ole32/stg/msf/msfhead.cxx
new file mode 100644
index 000000000..2265dc4fa
--- /dev/null
+++ b/private/ole32/stg/msf/msfhead.cxx
@@ -0,0 +1,41 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: msfhead.cxx
+//
+// Contents: Precompiled headers
+//
+// History: 23-Oct-92 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+}
+
+#include <memory.h>
+
+#ifndef REF
+#include <windows.h>
+#include <ole2.h>
+#include <segmsf.hxx>
+#endif //!REF
+
+#include <propset.h>
+#include <propapi.h>
+#include <propstm.hxx>
+
+#include <dfexcept.hxx>
+#include <msf.hxx>
+#include <header.hxx>
+#include <vect.hxx>
+#include <page.hxx>
+#include <vectfunc.hxx>
+#include <fat.hxx>
+#include <dir.hxx>
diff --git a/private/ole32/stg/msf/msfnew.cxx b/private/ole32/stg/msf/msfnew.cxx
new file mode 100644
index 000000000..a63fe0ce2
--- /dev/null
+++ b/private/ole32/stg/msf/msfnew.cxx
@@ -0,0 +1,38 @@
+//+-------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: msfnew.cxx
+//
+// Contents: CMstream new and delete operations
+//
+// Classes: CMStream
+//
+// History: 18-May-92 AlexT Created.
+//
+//--------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+#pragma hdrstop
+
+#if DBG == 0 && !defined(FLAT) && defined(USE_NEAR)
+
+void MSTREAM_NEAR * MSTREAM_NEAR CMStream::operator new(size_t size)
+{
+ HLOCAL hlc = LocalAlloc(LMEM_FIXED, (UINT)size);
+ void MSTREAM_NEAR *pv = (void MSTREAM_NEAR *) hlc;
+ return(pv);
+}
+
+void MSTREAM_NEAR CMStream::operator delete(void MSTREAM_NEAR *pv)
+{
+ if (NULL != pv)
+ {
+ HLOCAL hlc = (HLOCAL) pv;
+ LocalFree(hlc);
+ }
+}
+
+#endif
diff --git a/private/ole32/stg/msf/mstream.cxx b/private/ole32/stg/msf/mstream.cxx
new file mode 100644
index 000000000..c404ca40d
--- /dev/null
+++ b/private/ole32/stg/msf/mstream.cxx
@@ -0,0 +1,2230 @@
+//+-------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: mstream.cxx
+//
+// Contents: Mstream operations
+//
+// Classes: None. (defined in mstream.hxx)
+//
+// History: 18-Jul-91 Philipla Created.
+//
+//--------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+#pragma hdrstop
+
+#include <dirfunc.hxx>
+#include <sstream.hxx>
+#include <difat.hxx>
+#include <time.h>
+#include <mread.hxx>
+#include <docfilep.hxx>
+#include <df32.hxx>
+#include <smalloc.hxx>
+#include <filelkb.hxx>
+
+
+#if DBG == 1
+DECLARE_INFOLEVEL(msf)
+#endif
+
+#define MINPAGES 6
+#define MAXPAGES 24
+
+#ifdef USE_NOSCRATCH
+#define MINPAGESSCRATCH 2
+#define MAXPAGESSCRATCH 3
+#else
+#define MINPAGESSCRATCH 1
+#define MAXPAGESSCRATCH 2
+#endif
+
+//#define SECURETEST
+
+extern WCHAR const wcsContents[] = {'C','O','N','T','E','N','T','S','\0'};
+
+SCODE ILBFlush(ILockBytes *pilb, BOOL fFlushCache);
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetBuffer, public
+//
+// Synopsis: Gets a chunk of memory to use as a buffer
+//
+// Arguments: [cbMin] - Minimum size for buffer
+// [cbMax] - Maximum size for buffer
+// [ppb] - Buffer pointer return
+// [pcbActual] - Actual buffer size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppb]
+// [pcbActual]
+//
+// Algorithm: Attempt to dynamically allocate [cbMax] bytes
+// If that fails, halve allocation size and retry
+// If allocation size falls below [cbMin], fail
+//
+// History: 04-Mar-93 DrewB Created
+//
+// Notes: Buffer should be released with FreeBuffer
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_GetBuffer)
+#endif
+
+SCODE GetBuffer(USHORT cbMin, USHORT cbMax, BYTE **ppb, USHORT *pcbActual)
+{
+ USHORT cbSize;
+ BYTE *pb;
+
+ msfDebugOut((DEB_ITRACE, "In GetBuffer(%hu, %hu, %p, %p)\n",
+ cbMin, cbMax, ppb, pcbActual));
+ msfAssert(cbMin > 0);
+ msfAssert(cbMax >= cbMin);
+ msfAssert(ppb != NULL);
+ msfAssert(pcbActual != NULL);
+
+ cbSize = cbMax;
+ for (;;)
+ {
+ pb = (BYTE *) DfMemAlloc(cbSize);
+ if (pb == NULL)
+ {
+ cbSize >>= 1;
+ if (cbSize < cbMin)
+ break;
+ }
+ else
+ {
+ *pcbActual = cbSize;
+ break;
+ }
+ }
+
+ *ppb = pb;
+
+ msfDebugOut((DEB_ITRACE, "Out GetBuffer => %p, %hu\n", *ppb, *pcbActual));
+ return pb == NULL ? STG_E_INSUFFICIENTMEMORY : S_OK;
+}
+
+// Define the safe buffer size
+#define SCRATCHBUFFERSIZE SCRATCHSECTORSIZE
+static BYTE s_buf[SCRATCHBUFFERSIZE];
+static LONG s_bufRef = 0;
+
+
+#ifdef FLAT
+
+// Critical Section will be initiqalized in the shared memory allocator
+// constructor and deleted in the SmAllocator destructor
+CRITICAL_SECTION g_csScratchBuffer;
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetSafeBuffer, public
+//
+// Synopsis: Gets a buffer by first trying GetBuffer and if that fails,
+// returning a pointer to statically allocated storage.
+// Guaranteed to return a pointer to some storage.
+//
+// Arguments: [cbMin] - Minimum buffer size
+// [cbMax] - Maximum buffer size
+// [ppb] - Buffer pointer return
+// [pcbActual] - Actual buffer size return
+//
+// Modifies: [ppb]
+// [pcbActual]
+//
+// History: 04-Mar-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_GetSafeBuffer)
+#endif
+
+void GetSafeBuffer(USHORT cbMin, USHORT cbMax, BYTE **ppb, USHORT *pcbActual)
+{
+ msfAssert(cbMin > 0);
+ msfAssert(cbMin <= SCRATCHBUFFERSIZE &&
+ aMsg("Minimum too large for GetSafeBuffer"));
+ msfAssert(cbMax >= cbMin);
+ msfAssert(ppb != NULL);
+#ifndef FLAT
+ // Can't assert this here in preemptive environments
+ msfAssert(s_bufRef == 0 &&
+ aMsg("Tried to use scratch buffer twice"));
+#endif
+
+ // In 32-bit environments we want to minimize contention for the
+ // static buffer so we always try dynamic allocation, regardless
+ // of the size
+ if (
+#ifndef FLAT
+ cbMax <= SCRATCHBUFFERSIZE ||
+#endif
+ FAILED(GetBuffer(cbMin, cbMax, ppb, pcbActual)))
+ {
+#ifdef FLAT
+
+ EnterCriticalSection(&g_csScratchBuffer);
+ msfAssert(s_bufRef == 0 &&
+ aMsg("Tried to use scratch buffer twice"));
+#endif
+ s_bufRef = 1;
+ *ppb = s_buf;
+ *pcbActual = min(cbMax, SCRATCHBUFFERSIZE);
+ }
+ msfAssert(*ppb != NULL);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: FreeBuffer, public
+//
+// Synopsis: Releases a buffer allocated by GetBuffer or GetSafeBuffer
+//
+// Arguments: [pb] - Buffer
+//
+// History: 04-Mar-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_FreeBuffer)
+#endif
+
+void FreeBuffer(BYTE *pb)
+{
+ if (pb == s_buf)
+ {
+ msfAssert((s_bufRef == 1) && aMsg("Bad safe buffer ref count"));
+ s_bufRef = 0;
+#ifdef FLAT
+ LeaveCriticalSection(&g_csScratchBuffer);
+#endif
+ }
+ else
+ DfMemFree(pb);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::CMStream, public
+//
+// Synopsis: CMStream constructor
+//
+// Arguments: [pplstParent] -- Pointer to ILockBytes pointer of parent
+// [plGen] -- Pointer to LUID Generator to use.
+// Note: May be NULL, in which case a new
+// [uSectorShift] -- Sector shift for this MStream
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 05-Sep-95 MikeHill Initialize '_fMaintainFLBModifyTimestamp'.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_CMStream) // Mstream_Init_TEXT
+#endif
+
+
+MSTREAM_CLASS CMStream::CMStream(
+ IMalloc *pMalloc,
+ ILockBytes **pplstParent,
+ BOOL fIsScratch,
+#if defined(USE_NOSCRATCH) || defined(USE_NOSNAPSHOT)
+ DFLAGS df,
+#endif
+ USHORT uSectorShift)
+:_uSectorShift(uSectorShift),
+ _uSectorSize(1 << uSectorShift),
+ _uSectorMask(_uSectorSize - 1),
+ _pplstParent(P_TO_BP(CBasedILockBytesPtrPtr, pplstParent)),
+ _fIsScratch(fIsScratch),
+#ifdef USE_NOSCRATCH
+ _fIsNoScratch(P_NOSCRATCH(df)),
+ _pmsScratch(NULL),
+#endif
+#ifdef USE_NOSNAPSHOT
+ _fIsNoSnapshot(P_NOSNAPSHOT(df)),
+#endif
+ _hdr(uSectorShift),
+ _fat(SIDFAT),
+ _fatMini(SIDMINIFAT),
+ _pMalloc(pMalloc)
+{
+ _pmsShadow = NULL;
+ _pCopySectBuf = NULL;
+#if DBG == 1
+ _uBufferRef = 0;
+#endif
+ _fIsShadow = FALSE;
+
+ _ulParentSize = 0;
+
+ _pdsministream = NULL;
+ _pmpt = NULL;
+ _fBlockWrite = _fTruncate = _fBlockHeader = _fNewConvert = FALSE;
+ _fMaintainFLBModifyTimestamp = FALSE;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::CMStream, public
+//
+// Synopsis: CMStream copy constructor
+//
+// Arguments: [ms] -- MStream to copy
+//
+// History: 04-Nov-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_CMStream2)
+#endif
+
+MSTREAM_CLASS CMStream::CMStream(const CMStream *pms)
+:_uSectorShift(pms->_uSectorShift),
+ _uSectorSize(pms->_uSectorSize),
+ _uSectorMask(pms->_uSectorMask),
+ _pplstParent(pms->_pplstParent),
+ _fIsScratch(pms->_fIsScratch),
+ _hdr(*(CMSFHeader *)&pms->_hdr),
+ _dir(*(CDirectory *)pms->GetDir()),
+ _fat(pms->GetFat()),
+ _fatMini(pms->GetMiniFat()),
+ _fatDif(pms->GetDIFat()),
+ _pdsministream(pms->_pdsministream),
+ _pmpt(pms->_pmpt),
+ _fBlockWrite(pms->_fBlockWrite),
+ _fTruncate(pms->_fTruncate),
+ _fBlockHeader(pms->_fBlockHeader),
+ _fNewConvert(pms->_fNewConvert),
+ _pmsShadow(NULL),
+ _fIsShadow(TRUE),
+ _pMalloc(pms->_pMalloc)
+{
+ _pCopySectBuf = pms->_pCopySectBuf;
+#if DBG == 1
+ _uBufferRef = pms->_uBufferRef;
+#endif
+ _dir.SetParent(this);
+ _fat.SetParent(this);
+ _fatMini.SetParent(this);
+ _fatDif.SetParent(this);
+
+ _ulParentSize = 0;
+ _pmpt->AddRef();
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::InitCommon, private
+//
+// Synopsis: Common code for initialization routines.
+//
+// Arguments: None.
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: *Finish This*
+//
+// History: 20-May-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_InitCommon)
+#endif
+
+SCODE MSTREAM_CLASS CMStream::InitCommon(VOID)
+{
+ msfDebugOut((DEB_ITRACE,"In CMStream InitCommon()\n"));
+ SCODE sc = S_OK;
+
+#ifdef SECURE_BUFFER
+ memset(s_bufSecure, SECURECHAR, MINISTREAMSIZE);
+#endif
+
+ CMSFPageTable *pmpt;
+ msfMem(pmpt = new (GetMalloc()) CMSFPageTable(
+ this,
+ (_fIsScratch) ? MINPAGESSCRATCH: MINPAGES,
+ (_fIsScratch) ? MAXPAGESSCRATCH: MAXPAGES));
+ _pmpt = P_TO_BP(CBasedMSFPageTablePtr, pmpt);
+
+ msfChk(pmpt->Init());
+ if (!_fIsScratch)
+ {
+ CMStream *pms;
+ msfMem(pms = (CMStream *) new (GetMalloc()) CMStream(this));
+ _pmsShadow = P_TO_BP(CBasedMStreamPtr, pms);
+ }
+
+ _stmcDir.Init(this, SIDDIR, NULL);
+ _stmcMiniFat.Init(this, SIDMINIFAT, NULL);
+
+ msfDebugOut((DEB_ITRACE,"Leaving CMStream InitCommon()\n"));
+
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::InitCopy, public
+//
+// Synopsis: Copy the structures from one multistream to yourself
+//
+// Arguments: [pms] -- Pointer to multistream to copy.
+//
+// History: 04-Dec-92 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_InitCopy)
+#endif
+
+void CMStream::InitCopy(CMStream *pms)
+{
+ _stmcDir.Init(this, SIDDIR, NULL);
+ _stmcMiniFat.Init(this, SIDMINIFAT, NULL);
+
+ _fat.InitCopy(pms->GetFat());
+ _fatMini.InitCopy(pms->GetMiniFat());
+ _fatDif.InitCopy(pms->GetDIFat());
+ _dir.InitCopy(pms->GetDir());
+
+ _dir.SetParent(this);
+ _fat.SetParent(this);
+ _fatMini.SetParent(this);
+ _fatDif.SetParent(this);
+
+ memcpy(&_hdr, pms->GetHeader(), sizeof(CMSFHeader));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::Empty, public
+//
+// Synopsis: Empty all of the control structures of this CMStream
+//
+// Arguments: None.
+//
+// Returns: void.
+//
+// History: 04-Dec-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_Empty) // Mstream_Shutdown_TEXT
+#endif
+
+void CMStream::Empty(void)
+{
+ _fat.Empty();
+ _fatMini.Empty();
+ _fatDif.Empty();
+ _dir.Empty();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::~CMStream, public
+//
+// Synopsis: CMStream destructor
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 20-Jul-95 SusiA Modified to eliminate mutex in allocator
+// Caller must already have the mutex.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_1CMStream)
+#endif
+
+MSTREAM_CLASS CMStream::~CMStream()
+{
+
+ msfDebugOut((DEB_ITRACE,"In CMStream destructor\n"));
+
+
+
+ if (_pmsShadow != NULL)
+ {
+ _pmsShadow->~CMStream();
+ _pmsShadow->deleteNoMutex (BP_TO_P(CMStream *, _pmsShadow));
+ }
+
+#if DBG == 1
+ msfAssert((_uBufferRef == 0) &&
+ aMsg("CopySect buffer left with positive refcount."));
+#endif
+ g_smAllocator.FreeNoMutex(BP_TO_P(BYTE *, _pCopySectBuf));
+
+
+ if ((!_fIsShadow) && (_pdsministream != NULL))
+ {
+ _pdsministream->Release();
+ }
+
+ if (_pmpt != NULL)
+ {
+ _pmpt->Release();
+ }
+
+ msfDebugOut((DEB_ITRACE,"Leaving CMStream destructor\n"));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::Init, public
+//
+// Synposis: Set up an mstream instance from an existing stream
+//
+// Effects: Modifies Fat and Directory
+//
+// Arguments: void.
+//
+// Returns: S_OK if call completed OK.
+// Error of Fat or Dir setup otherwise.
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_Init) // Mstream_Init_TEXT
+#endif
+
+SCODE MSTREAM_CLASS CMStream::Init(VOID)
+{
+ ULONG ulTemp;
+ SCODE sc;
+ ULARGE_INTEGER ulOffset;
+
+
+ msfDebugOut((DEB_ITRACE,"In CMStream::Init()\n"));
+
+ msfAssert(!_fIsScratch &&
+ aMsg("Called Init() on scratch multistream."));
+
+ ULISet32(ulOffset, 0);
+ sc = GetScode((*_pplstParent)->ReadAt(ulOffset, (BYTE *)_hdr.GetData(),
+ sizeof(CMSFHeaderData), &ulTemp));
+ if (sc == E_PENDING)
+ {
+ sc = STG_E_PENDINGCONTROL;
+ }
+ msfChk(sc);
+
+ //We need to mark the header as not dirty, since the constructor
+ // defaults it to the dirty state. This needs to happen before
+ // any possible failures, otherwise we can end up writing a
+ // brand new header over an existing file.
+ _hdr.ResetDirty();
+
+ _uSectorShift = _hdr.GetSectorShift();
+ _uSectorSize = 1 << _uSectorShift;
+ _uSectorMask = _uSectorSize - 1;
+
+ if (ulTemp != sizeof(CMSFHeaderData))
+ {
+ msfErr(Err,STG_E_INVALIDHEADER);
+ }
+
+ msfChk(_hdr.Validate());
+
+ msfChk(InitCommon());
+
+ msfChk(_fatDif.Init(this, _hdr.GetDifLength()));
+ msfChk(_fat.Init(this, _hdr.GetFatLength(), 0));
+
+ FSINDEX fsiLen;
+ msfChk(_fat.GetLength(_hdr.GetDirStart(), &fsiLen));
+ msfChk(_dir.Init(this, fsiLen));
+
+ msfChk(_fatMini.Init(this, _hdr.GetMiniFatLength(), 0));
+
+ BYTE *pbBuf;
+
+ msfMem(pbBuf = (BYTE *) GetMalloc()->Alloc(GetSectorSize()));
+ _pCopySectBuf = P_TO_BP(CBasedBytePtr, pbBuf);
+
+ ULONG ulSize;
+ msfChk(_dir.GetSize(SIDMINISTREAM, &ulSize));
+ CDirectStream *pdsTemp;
+
+ msfMem(pdsTemp = new(GetMalloc()) CDirectStream(MINISTREAM_LUID));
+ _pdsministream = P_TO_BP(CBasedDirectStreamPtr, pdsTemp);
+ _pdsministream->InitSystem(this, SIDMINISTREAM, ulSize);
+
+ msfDebugOut((DEB_ITRACE,"Out CMStream::Init()\n"));
+
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::InitNew, public
+//
+// Synposis: Set up a brand new mstream instance
+//
+// Effects: Modifies FAT and Directory
+//
+// Arguments: [fDelay] -- If TRUE, then the parent LStream
+// will be truncated at the time of first
+// entrance to COW, and no writes to the
+// LStream will happen before then.
+//
+// Returns: S_OK if call completed OK.
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 12-Jun-92 PhilipLa Added fDelay.
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_InitNew)
+#endif
+
+SCODE MSTREAM_CLASS CMStream::InitNew(BOOL fDelay, ULARGE_INTEGER uliSize)
+{
+ SCODE sc;
+
+ msfDebugOut((DEB_ITRACE,"In CMStream::InitNew()\n"));
+
+ ULONG ulParentSize = 0;
+
+ msfChk(InitCommon());
+
+ if (!_fIsScratch)
+ {
+ msfAssert(ULIGetHigh(uliSize) == 0);
+ ulParentSize = ULIGetLow(uliSize);
+
+ if (!fDelay && ulParentSize > 0)
+ {
+ ULARGE_INTEGER ulTmp;
+
+ ULISet32(ulTmp, 0);
+ (*_pplstParent)->SetSize(ulTmp);
+ }
+ }
+
+ _fBlockWrite = (ulParentSize == 0) ? FALSE : fDelay;
+
+ msfChk(_fatDif.InitNew(this));
+ msfChk(_fat.InitNew(this));
+
+#ifdef USE_NOSCRATCH
+ if (!_fIsScratch || _fIsNoScratch)
+ {
+ msfChk(_fatMini.InitNew(this));
+ }
+#endif
+
+ if (!_fIsScratch)
+ {
+
+ msfChk(_dir.InitNew(this));
+#ifndef USE_NOSCRATCH
+ msfChk(_fatMini.InitNew(this));
+#endif
+
+ BYTE *pbBuf;
+
+ msfMem(pbBuf = (BYTE *) GetMalloc()->Alloc(GetSectorSize()));
+ _pCopySectBuf = P_TO_BP(CBasedBytePtr, pbBuf);
+
+ ULONG ulSize;
+ msfChk(_dir.GetSize(SIDMINISTREAM, &ulSize));
+
+ CDirectStream *pdsTemp;
+
+ msfMem(pdsTemp = new(GetMalloc()) CDirectStream(MINISTREAM_LUID));
+ _pdsministream = P_TO_BP(CBasedDirectStreamPtr, pdsTemp);
+ _pdsministream->InitSystem(this, SIDMINISTREAM, ulSize);
+ }
+
+ //If we have a zero length original file, this will create an
+ // empty Docfile on the disk. If the original file was
+ // not zero length, then the Flush operations will be skipped
+ // by _fBlockWrite and the file will be unmodified.
+ if (!_fBlockWrite)
+ {
+
+ msfChk(Flush(0));
+
+ }
+
+ _fTruncate = (ulParentSize != 0);
+ _fBlockWrite = fDelay;
+
+ msfDebugOut((DEB_ITRACE,"Out CMStream::InitNew()\n"));
+ return S_OK;
+
+Err:
+ Empty();
+
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::ConvertILB, private
+//
+// Synopsis: Copy the first sector of the underlying ILockBytes
+// out to the end.
+//
+// Arguments: [sectMax] -- Total number of sectors in the ILockBytes
+//
+// Returns: Appropriate status code
+//
+// History: 03-Feb-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_ConvertILB)
+#endif
+
+SCODE MSTREAM_CLASS CMStream::ConvertILB(SECT sectMax)
+{
+ SCODE sc;
+ BYTE *pb;
+ USHORT cbNull;
+
+ GetSafeBuffer(GetSectorSize(), GetSectorSize(), &pb, &cbNull);
+
+ ULONG ulTemp;
+
+ ULARGE_INTEGER ulTmp;
+ ULISet32(ulTmp, 0);
+
+ msfHChk((*_pplstParent)->ReadAt(ulTmp, pb, GetSectorSize(), &ulTemp));
+
+ ULARGE_INTEGER ulNewPos;
+ ULISet32(ulNewPos, sectMax << GetSectorShift());
+
+ msfDebugOut((DEB_ITRACE,"Copying first sector out to %lu\n",
+ ULIGetLow(ulNewPos)));
+
+ msfHChk((*_pplstParent)->WriteAt(
+ ulNewPos,
+ pb,
+ GetSectorSize(),
+ &ulTemp));
+
+Err:
+ FreeBuffer(pb);
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::InitConvert, public
+//
+// Synopsis: Init function used in conversion of files to multi
+// streams.
+//
+// Arguments: [fDelayConvert] -- If true, the actual file is not
+// touched until a BeginCopyOnWrite()
+//
+// Returns: S_OK if everything completed OK.
+//
+// Algorithm: *Finish This*
+//
+// History: 28-May-92 Philipla Created.
+//
+// Notes: We are allowed to fail here in low memory
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_InitConvert)
+#endif
+
+SCODE CMStream::InitConvert(BOOL fDelayConvert)
+{
+ SCODE sc;
+ SECT sectMax;
+ CDfName const dfnContents(wcsContents);
+
+ msfAssert(!_fIsScratch &&
+ aMsg("Called InitConvert on scratch multistream"));
+
+ _fBlockWrite = fDelayConvert;
+
+#ifndef DELAYCONVERT
+ msfAssert(!_fBlockWrite &&
+ aMsg("Delayed conversion not supported in this release."));
+#endif
+
+ msfChk(InitCommon());
+
+ STATSTG stat;
+ (*_pplstParent)->Stat(&stat, STATFLAG_NONAME);
+ msfAssert(ULIGetHigh(stat.cbSize) == 0);
+ msfDebugOut((DEB_ITRACE,"Size is: %lu\n",ULIGetLow(stat.cbSize)));
+
+
+ sectMax = (ULIGetLow(stat.cbSize) + GetSectorSize() - 1) >>
+ GetSectorShift();
+
+ SECT sectMaxMini;
+ BOOL fIsMini;
+ fIsMini = FALSE;
+
+ //If the CONTENTS stream will be in the Minifat, compute
+ // the number of Minifat sectors needed.
+ if (ULIGetLow(stat.cbSize) < MINISTREAMSIZE)
+ {
+ sectMaxMini = (ULIGetLow(stat.cbSize) + MINISECTORSIZE - 1) >>
+ MINISECTORSHIFT;
+ fIsMini = TRUE;
+ }
+
+ BYTE *pbBuf;
+
+ msfMem(pbBuf = (BYTE *) GetMalloc()->Alloc(GetSectorSize()));
+ _pCopySectBuf = P_TO_BP(CBasedBytePtr, pbBuf);
+
+ msfChk(_fatDif.InitConvert(this, sectMax));
+ msfChk(_fat.InitConvert(this, sectMax));
+ msfChk(_dir.InitNew(this));
+ msfChk(fIsMini ? _fatMini.InitConvert(this, sectMaxMini)
+ : _fatMini.InitNew(this));
+
+ SID sid;
+
+ msfChk(CreateEntry(SIDROOT, &dfnContents, STGTY_STREAM, &sid));
+ msfChk(_dir.SetSize(sid, ULIGetLow(stat.cbSize)));
+
+ if (!fIsMini)
+ msfChk(_dir.SetStart(sid, sectMax - 1));
+ else
+ {
+ msfChk(_dir.SetStart(sid, 0));
+ msfChk(_dir.SetStart(SIDMINISTREAM, sectMax - 1));
+ msfChk(_dir.SetSize(SIDMINISTREAM, ULIGetLow(stat.cbSize)));
+ }
+
+ ULONG ulMiniSize;
+ msfChk(_dir.GetSize(SIDMINISTREAM, &ulMiniSize));
+
+ CDirectStream *pdsTemp;
+
+ msfMem(pdsTemp = new(GetMalloc()) CDirectStream(MINISTREAM_LUID));
+ _pdsministream = P_TO_BP(CBasedDirectStreamPtr, pdsTemp);
+
+ _pdsministream->InitSystem(this, SIDMINISTREAM, ulMiniSize);
+
+ if (!_fBlockWrite)
+ {
+ msfChk(ConvertILB(sectMax));
+
+ msfChk(Flush(0));
+ }
+
+ return S_OK;
+
+Err:
+ Empty();
+
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::FlushHeader, public
+//
+// Synopsis: Flush the header to the LStream.
+//
+// Arguments: [uForce] -- Flag to determine if header should be
+// flushed while in copy on write mode.
+//
+// Returns: S_OK if call completed OK.
+// S_OK if the MStream is in copy on write mode or
+// is Unconverted and the header was not flushed.
+//
+// Algorithm: Write the complete header out to the 0th position of
+// the LStream.
+//
+// History: 11-Dec-91 PhilipLa Created.
+// 18-Feb-92 PhilipLa Added copy on write support.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_FlushHeader)
+#endif
+
+SCODE MSTREAM_CLASS CMStream::FlushHeader(USHORT uForce)
+{
+ ULONG ulTemp;
+ SCODE sc;
+
+ msfDebugOut((DEB_ITRACE,"In CMStream::FlushHeader()\n"));
+
+ if (_fIsScratch || _fBlockWrite ||
+ ((_fBlockHeader) && (!(uForce & HDR_FORCE))))
+ {
+ return S_OK;
+ }
+
+
+ //If the header isn't dirty, we don't flush it unless forced to.
+ if (!(uForce & HDR_FORCE) && !(_hdr.IsDirty()))
+ {
+ return S_OK;
+ }
+
+ ULARGE_INTEGER ulOffset;
+ ULISet32(ulOffset, 0);
+ sc = DfGetScode((*_pplstParent)->WriteAt(ulOffset, (BYTE *)_hdr.GetData(),
+ sizeof(CMSFHeaderData), &ulTemp));
+ if (sc == E_PENDING)
+ {
+ sc = STG_E_PENDINGCONTROL;
+ }
+
+ msfDebugOut((DEB_ITRACE,"Out CMStream::FlushHeader()\n"));
+ if (SUCCEEDED(sc))
+ {
+ _hdr.ResetDirty();
+ }
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::BeginCopyOnWrite, public
+//
+// Synopsis: Switch the multistream into copy on write mode
+//
+// Effects: Creates new in-core copies of the Fat, Directory, and
+// header.
+//
+// Arguments: None.
+//
+// Requires: The multistream cannot already be in copy on write
+// mode.
+//
+// Returns: S_OK if the call completed OK.
+// STG_E_ACCESSDENIED if multistream was already in COW mode
+//
+// Algorithm: Retrieve and store size of parent LStream.
+// If _fUnconverted & _fTruncate, call SetSize(0)
+// on the parent LStream.
+// If _fUnconverted, then flush all control structures.
+// Copy all control structures, and switch in the shadow
+// copies for current use.
+// Return S_OK.
+//
+// History: 18-Feb-92 PhilipLa Created.
+// 09-Jun-92 PhilipLa Added support for fUnconverted
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_BeginCopyOnWrite) // Mstream_Commit_TEXT
+#endif
+
+SCODE MSTREAM_CLASS CMStream::BeginCopyOnWrite(DWORD const dwFlags)
+{
+ msfDebugOut((DEB_ITRACE,"In CMStream::BeginCopyOnWrite()\n"));
+
+ SCODE sc;
+
+ msfAssert(!_fBlockHeader &&
+ aMsg("Tried to reenter Copy-on-Write mode."));
+
+ msfAssert(!_fIsScratch &&
+ aMsg("Tried to enter Copy-on-Write mode in scratch."));
+
+#ifdef USE_NOSCRATCH
+ msfAssert(!_fIsNoScratch &&
+ aMsg("Copy-on-Write started for NoScratch."));
+#endif
+
+
+ //_fBlockWrite is true if we have a delayed conversion or
+ // truncation.
+ if (_fBlockWrite)
+ {
+#ifdef DELAYCONVERT
+ _fNewConvert = !_fTruncate;
+#endif
+
+ //In the overwrite case, we don't want to release any
+ // disk space, so we skip this step.
+#ifdef USE_NOSCRATCH
+ if ((_fTruncate) && !(dwFlags & STGC_OVERWRITE) &&
+ (_pmsScratch == NULL))
+#else
+ if ((_fTruncate) && !(dwFlags & STGC_OVERWRITE))
+#endif
+ {
+ ULARGE_INTEGER ulTmp;
+ ULISet32(ulTmp, 0);
+ msfHChk((*_pplstParent)->SetSize(ulTmp));
+ }
+
+#ifdef DELAYCONVERT
+ if (_fNewConvert)
+ {
+ SECT sectMax;
+
+ sectMax = (_ulParentSize + GetSectorSize() - 1) >>
+ GetSectorShift();
+
+ msfChk(ConvertILB(sectMax));
+ }
+#endif
+
+ if (!(dwFlags & STGC_OVERWRITE))
+ {
+ _fBlockHeader = TRUE;
+ }
+
+ _fBlockWrite = FALSE;
+ msfChk(Flush(0));
+
+ _fBlockHeader = FALSE;
+ _fTruncate = FALSE;
+ }
+
+ STATSTG stat;
+ msfHChk((*_pplstParent)->Stat(&stat, STATFLAG_NONAME));
+ msfAssert(ULIGetHigh(stat.cbSize) == 0);
+ _ulParentSize = ULIGetLow(stat.cbSize);
+
+ msfDebugOut((DEB_ITRACE,"Parent size at begin is %lu\n",_ulParentSize));
+
+#ifdef USE_NOSNAPSHOT
+ if (_fIsNoSnapshot)
+ {
+ SECT sectNoSnapshot;
+ sectNoSnapshot = (_ulParentSize - HEADERSIZE + GetSectorSize() - 1) /
+ GetSectorSize();
+
+ _fat.SetNoSnapshot(sectNoSnapshot);
+ }
+#endif
+
+//We flush out all of our current dirty pages - after this point,
+ // we know that any dirty pages should be remapped before being
+ // written out, assuming we aren't in overwrite mode.
+ msfChk(Flush(0));
+
+ if (!(dwFlags & STGC_OVERWRITE))
+ {
+ SECT sectTemp;
+
+#ifdef USE_NOSCRATCH
+ if (_pmsScratch == NULL)
+ {
+#endif
+ msfChk(_fat.FindMaxSect(&sectTemp));
+#ifdef USE_NOSCRATCH
+ }
+ else
+ {
+ msfChk(_fat.FindLast(&sectTemp));
+ }
+#endif
+
+ _pmsShadow->InitCopy(this);
+
+ _pmsShadow->_pdsministream = NULL;
+
+ _fat.SetCopyOnWrite(_pmsShadow->GetFat(), sectTemp);
+
+ _fBlockHeader = TRUE;
+ msfChk(_fatDif.RemapSelf());
+
+#ifdef USE_NOSNAPSHOT
+ if (_fIsNoSnapshot)
+ msfChk(_fat.ResizeNoSnapshot());
+#endif
+
+ msfChk(_fatDif.Fixup(BP_TO_P(CMStream *, _pmsShadow)));
+
+#ifdef USE_NOSNAPSHOT
+ if (_fIsNoSnapshot)
+ _fat.ResetNoSnapshotFree();
+#endif
+#if DBG == 1
+ _fat.CheckFreeCount();
+#endif
+ }
+#ifdef USE_NOSCRATCH
+ else
+ {
+ _fat.SetCopyOnWrite(NULL, 0);
+ }
+#endif
+
+ msfDebugOut((DEB_ITRACE,"Out CMStream::BeginCopyOnWrite()\n"));
+
+ return S_OK;
+
+Err:
+ _fBlockHeader = FALSE;
+
+ _pmsShadow->Empty();
+ _fat.ResetCopyOnWrite();
+
+#ifdef USE_NOSNAPSHOT
+ if (_fIsNoSnapshot)
+ _fat.ResetNoSnapshotFree();
+#endif
+
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::EndCopyOnWrite, public
+//
+// Synopsis: End copy on write mode, either by committing the current
+// changes (in which case a merge is performed), or by
+// aborting the changes, in which case the persistent form
+// of the multistream should be identical to its form
+// before copy on write mode was entered.
+//
+// Effects: *Finish This*
+//
+// Arguments: [df] -- Flags to determine commit or abort status.
+//
+// Requires: The multistream must be in copy on write mode.
+//
+// Returns: S_OK if call completed OK.
+// STG_E_ACCESSDENIED if MStream was not in COW mode.
+//
+// Algorithm: If aborting, delete all shadow structures,
+// call SetSize() on parent LStream to restore
+// original size, and switch active controls back
+// to originals.
+// If committing, delete all old structures, switch
+// shadows into original position.
+//
+// History: 18-Feb-92 PhilipLa Created.
+// 09-Jun-92 Philipla Added support for fUnconverted
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_EndCopyOnWrite)
+#endif
+
+SCODE MSTREAM_CLASS CMStream::EndCopyOnWrite(
+ DWORD const dwCommitFlags,
+ DFLAGS const df)
+{
+ SCODE sc = S_OK;
+
+ msfDebugOut((DEB_ITRACE,"In CMStream::EndCopyOnWrite(%lu)\n",df));
+
+ BOOL fFlush = FLUSH_CACHE(dwCommitFlags);
+
+ if (dwCommitFlags & STGC_OVERWRITE)
+ {
+#ifdef USE_NOSCRATCH
+ if (_pmsScratch != NULL)
+ {
+ msfChk(_fatDif.Fixup(NULL));
+ _fat.ResetCopyOnWrite();
+ }
+#endif
+ msfChk(Flush(fFlush));
+ }
+ else
+ {
+ msfAssert(_fBlockHeader &&
+ aMsg("Tried to exit copy-on-write mode without entering."));
+
+ ULARGE_INTEGER ulParentSize;
+ ULISetHigh(ulParentSize, 0);
+
+ if (P_ABORT(df))
+ {
+ msfDebugOut((DEB_ITRACE,"Aborting Copy On Write mode\n"));
+
+ Empty();
+
+ InitCopy(BP_TO_P(CMStream *, _pmsShadow));
+
+ ULISetLow(ulParentSize, _ulParentSize);
+#ifdef DELAYCONVERT
+ if (_fNewConvert)
+ {
+ //We aborted the conversion.
+ _fBlockWrite = TRUE;
+ }
+#endif
+ }
+ else
+ {
+ SECT sectMax;
+
+ msfChk(_fatDif.Fixup(BP_TO_P(CMStream *, _pmsShadow)));
+
+ msfChk(Flush(fFlush));
+
+ _fat.ResetCopyOnWrite();
+
+ msfChk(_fat.GetMaxSect(&sectMax));
+
+ ULISetLow(ulParentSize, ConvertSectOffset(sectMax, 0,
+ GetSectorShift()));
+
+ msfChk(FlushHeader(HDR_FORCE));
+ msfVerify(SUCCEEDED(ILBFlush(*_pplstParent, fFlush)) &&
+ aMsg("CMStream::EndCopyOnWrite ILBFLush failed. "
+ "Non-fatal, hit Ok."));
+ }
+
+ //We don't ever expect this SetSize to fail, since it
+ // should never attempt to enlarge the file.
+#ifdef USE_NOSNAPSHOT
+ if (!_fIsNoSnapshot)
+#endif
+ if (ULIGetLow(ulParentSize) < _ulParentSize)
+ {
+ olHVerSucc((*_pplstParent)->SetSize(ulParentSize));
+ }
+
+ _pmsShadow->Empty();
+ _fBlockHeader = FALSE;
+ _fNewConvert = FALSE;
+ }
+
+#ifdef USE_NOSCRATCH
+ if (_pmsScratch != NULL)
+ {
+ //Let the no-scratch fat pick up whatever changed we've made.
+ _pmsScratch->InitScratch(this, FALSE);
+ }
+#endif
+
+#ifdef USE_NOSNAPSHOT
+ if (!_fIsNoSnapshot)
+ //In no-snapshot mode, we can't let the file shrink, since
+ //we might blow away someone else's state.
+#endif
+ _ulParentSize = 0;
+
+
+ {
+ SCODE sc2 = SetSize();
+ msfVerify((SUCCEEDED(sc2) || (sc2 == E_PENDING)) &&
+ aMsg("SetSize after copy-on-write failed."));
+ }
+
+#ifdef USE_NOSNAPSHOT
+ if (_fIsNoSnapshot)
+ {
+ _ulParentSize = 0;
+ _fat.SetNoSnapshot(0);
+ }
+#endif
+
+#if DBG == 1
+ STATSTG stat;
+ msfHChk((*_pplstParent)->Stat(&stat, STATFLAG_NONAME));
+ msfAssert(ULIGetHigh(stat.cbSize) == 0);
+ msfDebugOut((DEB_ITRACE, "Parent size at end is %lu\n",
+ ULIGetLow(stat.cbSize)));
+#endif
+
+ msfDebugOut((DEB_ITRACE,"Out CMStream::EndCopyOnWrite()\n"));
+Err:
+
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::CopySect, private
+//
+// Synopsis: Do a partial sector delta for copy-on-write suppoer
+//
+// Arguments: [sectOld] -- Location to copy from
+// [sectNew] -- Location to copy to
+// [oStart] -- Offset into sector to begin delta
+// [oEnd] -- Offset into sector to end delta
+// [pb] -- Buffer to delta from
+// [pulRetval] -- Return location for number of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 22-Jan-93 PhilipLa Created
+//
+// Notes: [pb] may be unsafe memory
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_CopySect) //
+#endif
+
+//This pragma is to avoid a C7 bug when building RETAIL
+#if _MSC_VER == 700 && DBG == 0
+#pragma function(memcpy)
+#endif
+
+SCODE MSTREAM_CLASS CMStream::CopySect(
+ SECT sectOld,
+ SECT sectNew,
+ OFFSET oStart,
+ OFFSET oEnd,
+ BYTE const HUGEP *pb,
+ ULONG *pulRetval)
+{
+ SCODE sc;
+
+ ULONG cb;
+ ULARGE_INTEGER ulOff;
+
+ ULISetHigh(ulOff, 0);
+
+ BYTE HUGEP *pbScratch = BP_TO_P(BYTE HUGEP *, _pCopySectBuf);
+
+#if DBG == 1
+ msfAssert((_uBufferRef == 0) &&
+ aMsg("Attempted to use CopySect buffer while refcount != 0"));
+ AtomicInc(&_uBufferRef);
+#endif
+
+ msfAssert((pbScratch != NULL) && aMsg("No CopySect buffer found."));
+
+ ULISetLow(ulOff, ConvertSectOffset(sectOld, 0, GetSectorShift()));
+ msfHChk((*_pplstParent)->ReadAt(
+ ulOff,
+ pbScratch,
+ GetSectorSize(),
+ &cb));
+
+ //Now do delta in memory.
+ BYTE HUGEP *pstart;
+ pstart = pbScratch + oStart;
+
+ USHORT memLength;
+ memLength = oEnd - oStart + 1;
+
+ TRY
+ {
+ memcpy(pstart, pb, memLength);
+ }
+ CATCH(CException, e)
+ {
+ UNREFERENCED_PARM(e);
+ msfErr(Err, STG_E_INVALIDPOINTER);
+ }
+ END_CATCH
+
+ ULISetLow(ulOff, ConvertSectOffset(sectNew, 0, GetSectorShift()));
+ msfHChk((*_pplstParent)->WriteAt(
+ ulOff,
+ pbScratch,
+ GetSectorSize(),
+ &cb));
+
+ *pulRetval = memLength;
+
+ Err:
+#if DBG == 1
+ AtomicDec(&_uBufferRef);
+#endif
+ return sc;
+}
+
+
+//This returns the compiler to the default behavior
+#if _MSC_VER == 700 && DBG == 0
+#pragma intrinsic(memcpy)
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::MWrite, public
+//
+// Synposis: Do multiple sector writes
+//
+// Effects: Causes multiple stream writes. Modifies fat and directory
+//
+// Arguments: [ph] -- Handle of stream doing write
+// [start] -- Starting sector to write
+// [oStart] -- offset into sector to begin write at
+// [end] -- Last sector to write
+// [oEnd] -- offset into last sector to write to
+// [buffer] -- Pointer to buffer into which data will be written
+// [ulRetVal] -- location to return number of bytes written
+//
+// Returns: Error code of any failed call to parent write
+// S_OK if call completed OK.
+//
+// Modifies: ulRetVal returns the number of bytes written
+//
+// Algorithm: Using a segment table, perform writes on parent stream
+// until call is completed.
+//
+// History: 16-Aug-91 PhilipLa Created.
+// 10-Sep-91 PhilipLa Converted to use sector table
+// 11-Sep-91 PhilipLa Modified interface, modified to
+// allow partial sector writes.
+// 07-Jan-92 PhilipLa Converted to use handle.
+// 18-Feb-92 PhilipLa Added copy on write support.
+//
+// Notes: [pvBuffer] may be unsafe memory
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_MWrite) // Mstream_MWrite_TEXT
+#endif
+
+SCODE MSTREAM_CLASS CMStream::MWrite(
+ SID sid,
+ BOOL fIsMini,
+ ULONG ulOffset,
+ VOID const HUGEP *pvBuffer,
+ ULONG ulCount,
+ CStreamCache *pstmc,
+ ULONG *pulRetval)
+{
+ SCODE sc;
+ BYTE const HUGEP *pbBuffer = (BYTE const HUGEP *) pvBuffer;
+
+ USHORT cbSector = GetSectorSize();
+ CFat *pfat = &_fat;
+ USHORT uShift = GetSectorShift();
+ ULONG ulLastBytes = 0;
+
+ ULARGE_INTEGER ulOff;
+ ULISetHigh(ulOff, 0);
+
+ ULONG ulOldSize = 0;
+
+ // Check if it's a small stream and whether this is a real or
+ // scratch multistream.
+
+ if ((fIsMini) &&
+ (!_fIsScratch) &&
+ (SIDMINISTREAM != sid))
+ {
+ msfAssert(sid <= MAXREGSID &&
+ aMsg("Invalid SID in MWrite"));
+ // This stream is stored in the ministream
+
+ cbSector = MINISECTORSIZE;
+ uShift = MINISECTORSHIFT;
+ pfat = GetMiniFat();
+ }
+
+ USHORT uMask = cbSector - 1;
+
+ SECT start = (SECT)(ulOffset >> uShift);
+ OFFSET oStart = (OFFSET)(ulOffset & uMask);
+
+ SECT end = (SECT)((ulOffset + ulCount - 1) >> uShift);
+ OFFSET oEnd = (OFFSET)((ulOffset + ulCount - 1) & uMask);
+
+ msfDebugOut((DEB_ITRACE,"In CMStream::MWrite(%lu,%u,%lu,%u)\n",
+ start,oStart,end,oEnd));
+
+ ULONG bytecount;
+ ULONG total = 0;
+
+ msfChk(_dir.GetSize(sid, &ulOldSize));
+
+
+//BEGIN COPYONWRITE
+
+ // Note that we don't do this for ministreams (the second pass through
+ // this code will take care of it).
+
+ msfAssert(!_fBlockWrite &&
+ aMsg("Called MWrite on Unconverted multistream"));
+
+ if ((_fBlockHeader) && (GetMiniFat() != pfat))
+ {
+ msfDebugOut((DEB_ITRACE,"**MWrite preparing for copy-on-write\n"));
+
+ SECT sectOldStart, sectNewStart, sectOldEnd, sectNewEnd;
+
+ SECT sectNew;
+ if (start != 0)
+ {
+ msfChk(pstmc->GetESect(start - 1, &sectNew));
+ }
+ else
+ {
+ msfChk(_dir.GetStart(sid, &sectNew));
+ }
+
+ msfChk(_fat.Remap(
+ sectNew,
+ (start == 0) ? 0 : 1,
+ (end - start + 1),
+ &sectOldStart,
+ &sectNewStart,
+ &sectOldEnd,
+ &sectNewEnd));
+
+ msfAssert(((end != start) || (sectNewStart == sectNewEnd)) &&
+ aMsg("Remap postcondition failed."));
+
+ if (sc != S_FALSE)
+ {
+ msfChk(pstmc->EmptyRegion(start, end));
+ }
+
+ if ((start == 0) && (sectNewStart != ENDOFCHAIN))
+ {
+ msfDebugOut((DEB_ITRACE,
+ "*** Remapped first sector. Changing directory.\n"));
+ msfChk(_dir.SetStart(sid, sectNewStart));
+ }
+
+ ULONG ulSize = ulOldSize;
+
+ if (((oStart != 0) ||
+ ((end == start) && (ulOffset + ulCount != ulSize)
+ && ((USHORT)oEnd != (cbSector - 1)))) &&
+ (sectNewStart != ENDOFCHAIN))
+ {
+ //Partial first sector.
+ ULONG ulRetval;
+
+ msfChk(CopySect(
+ sectOldStart,
+ sectNewStart,
+ oStart,
+ (end == start) ? oEnd : (cbSector - 1),
+ pbBuffer,
+ &ulRetval));
+
+ pbBuffer = pbBuffer + ulRetval;
+ total = total + ulRetval;
+ start++;
+ oStart = 0;
+ }
+
+ if (((end >= start) && ((USHORT)oEnd != cbSector - 1) &&
+ (ulCount + ulOffset != ulSize)) &&
+ (sectNewEnd != ENDOFCHAIN))
+ {
+ //Partial last sector.
+
+ msfAssert(((end != start) || (oStart == 0)) &&
+ aMsg("CopySect precondition failed."));
+
+ msfChk(CopySect(
+ sectOldEnd,
+ sectNewEnd,
+ 0,
+ oEnd,
+ pbBuffer + ((end - start) << uShift) - oStart,
+ &ulLastBytes));
+
+ end--;
+ oEnd = cbSector - 1;
+ //We don't need to update pbBuffer, since the change
+ // is at the end.
+ }
+ }
+
+
+// At this point, the entire block has been moved into the copy-on-write
+// area of the multistream, and all partial writes have been done.
+//END COPYONWRITE
+
+ msfAssert(end != 0xffffffffL);
+
+ if (end < start)
+ {
+ *pulRetval = total + ulLastBytes;
+ goto Err;
+ }
+
+ ULONG ulRunLength;
+ ulRunLength = end - start + 1;
+
+ USHORT offset;
+ offset = oStart;
+
+ while (TRUE)
+ {
+ SSegment segtab[CSEG + 1];
+
+ ULONG cSeg;
+ msfChk(pstmc->Contig(
+ start,
+ TRUE,
+ (SSegment STACKBASED *) segtab,
+ ulRunLength,
+ &cSeg));
+
+ msfAssert(cSeg <= CSEG);
+
+ USHORT oend = cbSector - 1;
+ ULONG i;
+ SECT sectStart;
+ for (USHORT iseg = 0; iseg < cSeg;)
+ {
+ sectStart = segtab[iseg].sectStart;
+ i = segtab[iseg].cSect;
+ if (i > ulRunLength)
+ i = ulRunLength;
+
+ ulRunLength -= i;
+ start += i;
+
+ iseg++;
+ if (ulRunLength == 0)
+ oend = oEnd;
+
+ ULONG ulSize = ((i - 1) << uShift) - offset + oend + 1;
+
+ msfDebugOut((
+ DEB_ITRACE,
+ "Calling lstream WriteAt(%lu,%p,%lu)\n",
+ ConvertSectOffset(sectStart,offset,uShift),
+ pbBuffer,
+ ulSize));
+
+ if (GetMiniFat() == pfat)
+ {
+ sc = _pdsministream->CDirectStream::WriteAt(
+ (sectStart << uShift) + offset,
+ pbBuffer, ulSize,
+ (ULONG STACKBASED *)&bytecount);
+ }
+ else
+ {
+ ULISetLow(ulOff, ConvertSectOffset(sectStart, offset,
+ uShift));
+ sc = DfGetScode((*_pplstParent)->WriteAt(ulOff, pbBuffer,
+ ulSize, &bytecount));
+ }
+
+ total += bytecount;
+
+#ifdef SECURE
+ //Check if this write is the last one in the stream,
+ // and that the stream ends as a partial sector.
+ //If so, fill out the remainder of the sector with
+ // something.
+ if ((0 == ulRunLength) && (total + ulOffset > ulOldSize) &&
+ (((total + ulOffset) & (GetSectorSize() - 1)) != 0))
+ {
+ //This is the last sector and the stream has grown.
+ ULONG csectOld = (ulOldSize + GetSectorSize() - 1) >>
+ GetSectorShift();
+
+ ULONG csectNew = (total + ulOffset + GetSectorSize() - 1) >>
+ GetSectorShift();
+
+ if (csectNew > csectOld)
+ {
+ msfAssert(!fIsMini &&
+ aMsg("Small stream grew in MWrite"));
+
+ SECT sectLast = sectStart + i - 1;
+
+ msfVerify(SUCCEEDED(SecureSect(
+ sectLast,
+ total + ulOffset,
+ FALSE)));
+ }
+ }
+#endif //SECURE
+
+ if (0 == ulRunLength || FAILED(sc))
+ {
+ break;
+ }
+
+ pbBuffer = pbBuffer + bytecount;
+ offset = 0;
+ }
+
+ if (0 == ulRunLength || FAILED(sc))
+ {
+ *pulRetval = total + ulLastBytes;
+ msfDebugOut((
+ DEB_ITRACE,
+ "Out CMStream::MWrite()=>%lu, retval = %lu\n",
+ sc,
+ total));
+ break;
+ }
+ }
+
+ Err:
+
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::Flush, public
+//
+// Synopsis: Flush control structures.
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+// History: 16-Dec-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_Flush) //
+#endif
+
+SCODE CMStream::Flush(BOOL fFlushCache)
+{
+ SCODE sc = S_OK;
+
+ msfAssert(!_fBlockWrite &&
+ aMsg("Flush called on unconverted base."));
+
+ if ((!_fIsScratch) && (*_pplstParent != NULL))
+ {
+#ifdef SORTPAGETABLE
+ msfChk(_pmpt->Flush());
+#else
+ msfChk(_dir.Flush());
+ msfChk(_fatMini.Flush());
+ msfChk(_fat.Flush());
+ msfChk(_fatDif.Flush());
+#endif
+ msfChk(FlushHeader(HDR_NOFORCE));
+ msfChk(ILBFlush(*_pplstParent, fFlushCache));
+ }
+Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ILBFlush
+//
+// Synopsis: Flush as thoroughly as possible
+//
+// Effects: Flushes ILockBytes
+//
+// Arguments: [pilb] - ILockBytes to flush
+// [fFlushCache] - Flush thoroughly iff TRUE
+//
+// Returns: SCODE
+//
+// Algorithm:
+//
+// History: 12-Feb-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_ILBFlush)
+#endif
+
+SCODE ILBFlush(ILockBytes *pilb, BOOL fFlushCache)
+{
+ // Try to query interface to our own implementation
+
+ IFileLockBytes *pfl;
+ SCODE sc;
+
+ msfDebugOut((DEB_ITRACE, "In ILBFlushCache(%p)\n", pilb));
+
+ // Check for FileLockBytes
+
+ if (!fFlushCache ||
+ FAILED(DfGetScode(pilb->QueryInterface(IID_IFileLockBytes, (void **)&pfl))))
+ {
+ // Either we don't have to flush the cache or its not our ILockBytes
+ sc = DfGetScode(pilb->Flush());
+ }
+ else
+ {
+ // We have to flush the cache and its our ILockBytes
+ sc = DfGetScode(pfl->FlushCache());
+ pfl->Release();
+ }
+
+ msfDebugOut((DEB_ITRACE, "Out ILBFlushCache()\n"));
+
+ return(sc);
+}
+
+
+#ifdef SECURE
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::SecureSect, public
+//
+// Synopsis: Zero out the unused portion of a sector
+//
+// Arguments: [sect] -- Sector to zero out
+// [ulSize] -- Size of stream
+// [fIsMini] -- TRUE if stream is in ministream
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Apr-93 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMStream_SecureSect)
+#endif
+
+SCODE CMStream::SecureSect(
+ const SECT sect,
+ const ULONG ulSize,
+ const BOOL fIsMini)
+{
+#ifdef SECURE_TAIL
+ SCODE sc = S_OK;
+ BYTE *pb = NULL;
+
+ if (GetSectorSize() != SECTORSIZE)
+ {
+ //We disable this 'feature' for docfiles with a sector size
+ //other than the default.
+ return S_OK;
+ }
+
+ if (!_fIsScratch)
+ {
+ ULONG cbSect = fIsMini ? MINISECTORSIZE : GetSectorSize();
+
+ msfAssert(ulSize != 0);
+
+ ULONG ulOffset = ((ulSize - 1) % cbSect) + 1;
+
+ ULONG cb = cbSect - ulOffset;
+
+ msfAssert(cb != 0);
+
+ //We can use any initialized block of memory here. The header
+ // is available and is the correct size, so we use that.
+#ifdef SECURE_BUFFER
+ pb = s_bufSecure;
+#else
+ pb = (BYTE *)_hdr.GetData();
+#endif
+
+#ifdef SECURETEST
+ pb = (BYTE *) DfMemAlloc(cb);
+ if (pb != NULL)
+ memset(pb, 'Y', cb);
+#endif
+ ULONG cbWritten;
+
+ if (!fIsMini)
+ {
+ ULARGE_INTEGER ulOff;
+ ULISet32(ulOff, ConvertSectOffset(
+ sect,
+ (OFFSET)ulOffset,
+ GetSectorShift()));
+
+ msfChk(DfGetScode((*_pplstParent)->WriteAt(
+ ulOff,
+ pb,
+ cb,
+ &cbWritten)));
+ }
+ else
+ {
+ msfChk(_pdsministream->WriteAt(
+ (sect << MINISECTORSHIFT) + ulOffset,
+ pb,
+ cb,
+ (ULONG STACKBASED *)&cbWritten));
+ }
+
+ if (cbWritten != cb)
+ {
+ sc = STG_E_WRITEFAULT;
+ }
+ }
+
+Err:
+#ifdef SECURETEST
+ DfMemFree(pb);
+#endif
+
+ return sc;
+#else
+ //On NT, our sectors get zeroed out by the file system, so we don't
+ // need this whole rigamarole.
+ return S_OK;
+#endif // WIN32 == 200
+}
+#endif //SECURE
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::SetFileLockBytesTime, public
+//
+// Synopsis: Set the IFileLockBytes time.
+//
+// Arguments: [tt] -- Timestamp requested (WT_CREATION, WT_MODIFICATION,
+// WT_ACCESS)
+// [nt] -- New timestamp
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Query for IFileLockBytes and call its SetTime member.
+//
+// History: 01-Sep-95 MikeHill Created.
+//
+//--------------------------------------------------------------------------
+
+SCODE MSTREAM_CLASS CMStream::SetFileLockBytesTime(
+ WHICHTIME const tt,
+ TIME_T nt)
+{
+ SCODE sc = S_OK;
+ ILockBytes *pilb = *_pplstParent;
+ IFileLockBytes *pfl;
+
+ if (SUCCEEDED(sc = DfGetScode(pilb->QueryInterface( IID_IFileLockBytes,
+ (void **)&pfl))))
+ {
+
+ sc = ((CFileStream *)pfl)->SetTime(tt, nt);
+ pfl->Release();
+
+ }
+
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::SetAllFileLockBytesTimes, public
+//
+// Synopsis: Set the IFileLockBytes time.
+//
+// Arguments:
+// [atm] -- ACCESS time
+// [mtm] -- MODIFICATION time
+// [ctm] -- CREATION time
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Query for IFileLockBytes and call its SetAllTimes member.
+//
+// History: 29-Nov-95 SusiA Created.
+//
+//--------------------------------------------------------------------------
+
+SCODE MSTREAM_CLASS CMStream::SetAllFileLockBytesTimes(
+ TIME_T atm,
+ TIME_T mtm,
+ TIME_T ctm)
+{
+ SCODE sc = S_OK;
+ ILockBytes *pilb = *_pplstParent;
+ IFileLockBytes *pfl;
+
+ if (SUCCEEDED(sc = DfGetScode(pilb->QueryInterface( IID_IFileLockBytes,
+ (void **)&pfl))))
+ {
+
+ sc = ((CFileStream *)pfl)->SetAllTimes(atm, mtm, ctm);
+ pfl->Release();
+
+ }
+
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::SetTime, public
+//
+// Synopsis: Set the time for a given handle
+//
+// Arguments: [sid] -- SID to retrieve time for
+// [tt] -- Timestamp requested (WT_CREATION, WT_MODIFICATION,
+// WT_ACCESS)
+// [nt] -- New timestamp
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Call through to directory
+//
+// History: 01-Apr-92 PhilipLa Created.
+// 14-Sep-92 PhilipLa inlined.
+//
+//--------------------------------------------------------------------------
+
+SCODE MSTREAM_CLASS CMStream::SetTime(
+ SID const sid,
+ WHICHTIME const tt,
+ TIME_T nt)
+{
+
+ if ( sid == SIDROOT )
+ {
+ // If it is not the modify timestamp, or if it is but the
+ // _fMaintainFLBModifyTimestamp is set, then we must pass this
+ // request on to IFileLockBytes.
+
+ if( ( tt != WT_MODIFICATION )
+ ||
+ _fMaintainFLBModifyTimestamp
+ )
+ {
+ SCODE sc;
+
+ if( FAILED( sc = SetFileLockBytesTime( tt, nt )))
+ {
+ return sc;
+ }
+
+ }// if( ( tt != WT_MODIFICATION ) ...
+ }// if( sid == SIDROOT)
+
+ return _dir.SetTime(sid, tt, nt);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::SetAllTimes, public
+//
+// Synopsis: Set all the times for a given handle
+//
+// Arguments: [sid] -- SID to retrieve time for
+// [atm] -- ACCESS time
+// [mtm] -- MODIFICATION time
+// [ctm] -- CREATION time
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Call through to directory
+//
+// History: 27-Nov-95 SusiA Created
+//
+//--------------------------------------------------------------------------
+
+SCODE MSTREAM_CLASS CMStream::SetAllTimes(
+ SID const sid,
+ TIME_T atm,
+ TIME_T mtm,
+ TIME_T ctm)
+{
+
+ if ( sid == SIDROOT )
+ {
+
+ SCODE sc;
+
+ if( FAILED( sc = SetAllFileLockBytesTimes(atm, mtm, ctm )))
+ {
+ return sc;
+ }
+ }
+ return _dir.SetAllTimes(sid, atm, mtm, ctm);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetTime, public
+//
+// Synopsis: Get the time for a given handle
+//
+// Arguments: [sid] -- SID to retrieve time for
+// [tt] -- Timestamp requested (WT_CREATION, WT_MODIFICATION,
+// WT_ACCESS)
+// [pnt] -- Pointer to return location
+//
+// Returns: S_OK if call completed OK.
+//
+// History: 01-Apr-92 PhilipLa Created.
+// 14-Sep-92 PhilipLa inlined.
+//
+//--------------------------------------------------------------------------
+
+SCODE MSTREAM_CLASS CMStream::GetTime(SID const sid,
+ WHICHTIME const tt,
+ TIME_T *pnt)
+{
+ SCODE sc = S_OK;
+
+ if (sid == SIDROOT)
+ {
+ //Get timestamp from ILockBytes
+ STATSTG stat;
+
+ msfChk((*_pplstParent)->Stat(&stat, STATFLAG_NONAME));
+
+ if (tt == WT_CREATION)
+ {
+ *pnt = stat.ctime;
+ }
+ else if (tt == WT_MODIFICATION)
+ {
+ *pnt = stat.mtime;
+ }
+ else
+ {
+ *pnt = stat.atime;
+ }
+ }
+ else
+ sc = _dir.GetTime(sid, tt, pnt);
+Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetAllTimes, public
+//
+// Synopsis: Get the times for a given handle
+//
+// Arguments: [sid] -- SID to retrieve time for
+// [patm] -- Pointer to the ACCESS time
+// [pmtm] -- Pointer to the MODIFICATION time
+// [pctm] -- Pointer to the CREATION time
+//
+// Returns: S_OK if call completed OK.
+//
+// History: 26-May-95 SusiA Created
+//
+//--------------------------------------------------------------------------
+
+SCODE MSTREAM_CLASS CMStream::GetAllTimes(SID const sid,
+ TIME_T *patm,
+ TIME_T *pmtm,
+ TIME_T *pctm)
+{
+ SCODE sc = S_OK;
+
+ if (sid == SIDROOT)
+ {
+ //Get timestamp from ILockBytes
+ STATSTG stat;
+
+ msfChk((*_pplstParent)->Stat(&stat, STATFLAG_NONAME));
+
+ *pctm = stat.ctime;
+ *pmtm = stat.mtime;
+ *patm = stat.atime;
+
+ }
+ else
+ sc = _dir.GetAllTimes(sid, patm, pmtm, pctm);
+Err:
+ return sc;
+}
+
+
+#ifdef USE_NOSCRATCH
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::InitScratch, public
+//
+// Synopsis: Set up a multistream for NoScratch operation
+//
+// Arguments: [pms] -- Pointer to base multistream
+// [fNew] -- True if this is the first time the function has
+// been called (init path), FALSE if merging behavior
+// is required (EndCopyOnWrite)
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 02-Mar-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE CMStream::InitScratch(CMStream *pms, BOOL fNew)
+{
+ msfDebugOut((DEB_ITRACE, "In CMStream::InitScratch:%p()\n", this));
+
+ msfAssert(GetSectorSize() == SCRATCHSECTORSIZE);
+ msfAssert(_fIsNoScratch &&
+ aMsg("Called InitScratch on Multistream not in NoScratch mode"));
+
+ return _fatMini.InitScratch(pms->GetFat(), fNew);
+}
+#endif
+
+#ifdef MULTIHEAP
+//+--------------------------------------------------------------
+//
+// Member: CMStream::GetMalloc, public
+//
+// Synopsis: Returns the allocator associated with this multistream
+//
+// History: 05-May-93 AlexT Created
+//
+//---------------------------------------------------------------
+
+IMalloc * CMStream::GetMalloc(VOID) const
+{
+ return (IMalloc *) &g_smAllocator;
+}
+#endif
diff --git a/private/ole32/stg/msf/page.cxx b/private/ole32/stg/msf/page.cxx
new file mode 100644
index 000000000..6ca5a25c9
--- /dev/null
+++ b/private/ole32/stg/msf/page.cxx
@@ -0,0 +1,1174 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: page.cxx
+//
+// Contents: Paging code for MSF
+//
+// Classes: Defined in page.hxx
+//
+// Functions:
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+#pragma hdrstop
+
+
+#include <mread.hxx>
+#include <filest.hxx>
+
+
+#define FLUSH_MULTIPLE
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetSect, public
+//
+// Synopsis: Sets the SECT for this page
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+#ifdef SORTPAGETABLE
+inline void CMSFPage::SetSect(const SECT sect)
+{
+ msfAssert(_pmpNext != NULL && _pmpPrev != NULL);
+
+ msfAssert((_pmpPrev->_sect >= _pmpNext->_sect) || //Edge
+ ((_sect >= _pmpPrev->_sect) && (_sect <= _pmpNext->_sect)));
+ _sect = sect;
+}
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::IsSorted, public
+//
+// Synopsis: Return TRUE if the specified page is in the right place
+// in the list.
+//
+// Arguments: [pmp] -- Page to check
+//
+// History: 13-Dec-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CMSFPageTable::IsSorted(CMSFPage *pmp)
+{
+ //There are three cases:
+ //1) Page is first in the list.
+ //2) Page is last in the list.
+ //3) Page is in the middle of the list.
+
+ SECT sect = pmp->GetSect();
+ CMSFPage *pmpStart = BP_TO_P(CMSFPage *, _pmpStart);
+ CMSFPage *pmpNext = pmp->GetNext();
+
+ if (pmp == pmpStart)
+ {
+ return (sect <= pmpNext->GetSect());
+ }
+ if (pmpNext == pmpStart)
+ {
+ return (sect >= pmp->GetPrev()->GetSect());
+ }
+ return ((sect <= pmpNext->GetSect()) &&
+ (sect >= pmp->GetPrev()->GetSect()));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::SetSect, public
+//
+// Synopsis: Set the sector stamp on a page, and sort the list if
+// necessary.
+//
+// Arguments: [pmp] -- Pointer to page to stamp
+// [sect] -- SECT to stamp it with
+//
+// Returns: void
+//
+// History: 12-Dec-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+void CMSFPageTable::SetSect(CMSFPage *pmp, SECT sect)
+{
+ msfDebugOut((DEB_ITRACE, "In CMSFPageTable::SetSect:%p(%p, %lX)\n",
+ this,
+ pmp,
+ sect));
+ pmp->SetSect(sect);
+
+ //Resort list if necessary.
+ if (!IsSorted(pmp))
+ {
+ CMSFPage *pmpTemp, *pmpStart;
+ pmpStart = BP_TO_P(CMSFPage *, _pmpStart);
+
+ if (pmpStart == pmp)
+ {
+ pmpStart = pmp->GetNext();
+ _pmpStart = P_TO_BP(CBasedMSFPagePtr , pmpStart);
+ }
+ pmp->Remove();
+
+ pmpTemp = pmpStart;
+ while (sect > pmpTemp->GetSect())
+ {
+ pmpTemp = pmpTemp->GetNext();
+ if (pmpTemp == pmpStart)
+ {
+ break;
+ }
+ }
+ //Insert node before pmpTemp.
+ pmpTemp->GetPrev()->SetNext(pmp);
+ pmp->SetChain(pmpTemp->GetPrev(), pmpTemp);
+ pmpTemp->SetPrev(pmp);
+
+ if (sect <= pmpStart->GetSect())
+ {
+ _pmpStart = P_TO_BP(CBasedMSFPagePtr, pmp);
+ }
+ }
+ msfAssert(IsSorted(pmp));
+
+ msfDebugOut((DEB_ITRACE, "Out CMSFPageTable::SetSect\n"));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::CMSFPageTable, public
+//
+// Synopsis: CMSFPageTable constructor.
+//
+// Arguments: [pmsParent] -- Pointer to multistream for this page table.
+//
+// History: 22-Oct-92 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPageTable_CMSFPageTable)
+#endif
+
+CMSFPageTable::CMSFPageTable(
+ CMStream *const pmsParent,
+ const ULONG cMinPages,
+ const ULONG cMaxPages)
+ : _cbSector(pmsParent->GetSectorSize()),
+ _cMinPages(cMinPages), _cMaxPages(cMaxPages)
+{
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pmsParent);
+ _cActivePages = 0;
+ _cPages = 0;
+ _pmpCurrent = NULL;
+#ifdef SORTPAGETABLE
+ _pmpStart = NULL;
+#endif
+ _cReferences = 1;
+#if DBG == 1
+ _cCurrentPageRef = 0;
+ _cMaxPageRef = 0;
+#endif
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::CMSFPage, public
+//
+// Synopsis: CMSFPage default constructor
+//
+// History: 20-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPage_CMSFPage)
+#endif
+
+#if DBG == 1
+CMSFPage::CMSFPage(CMSFPage *pmp, CMSFPageTable *pmpt)
+#else
+CMSFPage::CMSFPage(CMSFPage *pmp)
+#endif
+{
+ if (pmp == NULL)
+ {
+ SetChain(this, this);
+ }
+ else
+ {
+ SetChain(pmp->GetPrev(), pmp);
+ GetPrev()->SetNext(this);
+ GetNext()->SetPrev(this);
+ }
+
+#if DBG == 1
+ _pmpt = P_TO_BP(CBasedMSFPageTablePtr, pmpt);
+#endif
+
+ SetSid(NOSTREAM);
+ SetOffset(0);
+// SetSect(ENDOFCHAIN);
+ //SetSect() contains assertions to verify sortedness of the list,
+ //which we don't want here.
+ _sect = ENDOFCHAIN;
+ SetFlags(0);
+ SetVector(NULL);
+ _cReferences = 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::GetNewPage, private
+//
+// Synopsis: Insert a new page into the list and return a pointer to it.
+//
+// Arguments: None.
+//
+// Returns: Pointer to new page. Null if there was an allocation error.
+//
+// History: 22-Oct-92 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPageTable_GetNewPage)
+#endif
+
+inline CMSFPage * CMSFPageTable::GetNewPage(void)
+{
+#ifndef SORTPAGETABLE
+#if DBG == 1
+ return new (_pmsParent->GetMalloc(), (size_t)_cbSector)
+ CMSFPage(BP_TO_P(CMSFPage *, _pmpCurrent), this);
+#else
+ return new (_pmsParent->GetMalloc(), (size_t)_cbSector)
+ CMSFPage(BP_TO_P(CMSFPage *, _pmpCurrent));
+#endif
+#else
+#if DBG == 1
+ return new (_pmsParent->GetMalloc(), (size_t)_cbSector)
+ CMSFPage(BP_TO_P(CMSFPage *, _pmpStart), this);
+#else
+ return new (_pmsParent->GetMalloc(), (size_t)_cbSector)
+ CMSFPage(BP_TO_P(CMSFPage *, _pmpStart));
+#endif
+#endif //SORTPAGETABLE
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::~CMSFPageTable, public
+//
+// Synopsis: CMSFPageTable destructor
+//
+// History: 26-Oct-92 PhilipLa Created
+// 21-Jul-95 SusiA Modified to delete the object without
+// obtaining the mutex. Calling functions
+// should have locked the mutex first.
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPageTable_1CMSFPageTable)
+#endif
+
+CMSFPageTable::~CMSFPageTable()
+{
+ if (_pmpCurrent != NULL)
+ {
+ CMSFPage *pmp = BP_TO_P(CMSFPage *, _pmpCurrent);
+ CMSFPage *pmpNext;
+
+ while (pmp != pmp->GetNext())
+ {
+ pmpNext = pmp->GetNext();
+ msfAssert(pmpNext != NULL &&
+ aMsg("NULL found in page table circular list."));
+#if DBG == 1
+ msfAssert(!pmp->IsInUse() &&
+ aMsg("Active page left at page table destruct time."));
+
+ if (!_pmsParent->IsScratch())
+ {
+ //Dirty paged can be thrown away if we are unconverted or
+ // in a commit.
+ if ((!_pmsParent->IsUnconverted()) &&
+ (_pmsParent->GetParentSize() == 0))
+ {
+ msfAssert(!pmp->IsDirty() &&
+ aMsg("Dirty page left at page table destruct time."));
+ }
+ }
+#endif
+ pmp->~CMSFPage();
+ pmp->deleteNoMutex(pmp);
+
+ pmp = pmpNext;
+ }
+ pmp->~CMSFPage();
+ pmp->deleteNoMutex(pmp);
+
+
+ }
+#if DBG == 1
+ msfDebugOut((DEB_ITRACE,
+ "Page Table Max Page Count for %s: %lu\n",
+ (_pmsParent->IsScratch()) ? "Scratch" : "Base",
+ _cMaxPageRef));
+#endif
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::Init, public
+//
+// Synopsis: Initialize a CMSFPageTable
+//
+// Arguments: [cPages] -- Number of pages to preallocate.
+//
+// Returns: Appropriate status code
+//
+// History: 22-Oct-92 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPageTable_Init)
+#endif
+
+SCODE CMSFPageTable::Init(void)
+{
+ SCODE sc = S_OK;
+
+ msfDebugOut((DEB_ITRACE, "In CMSFPageTable::Init:%p()\n", this));
+
+ for (ULONG i = 0; i < _cMinPages; i++)
+ {
+ CMSFPage *pmp;
+
+ msfMem(pmp = GetNewPage());
+#ifndef SORTPAGETABLE
+ _pmpCurrent = P_TO_BP(CBasedMSFPagePtr, pmp);
+#else
+ _pmpStart = P_TO_BP(CBasedMSFPagePtr, pmp);
+#endif
+ }
+ _cPages = _cMinPages;
+ _cActivePages = 0;
+#ifdef SORTPAGETABLE
+ _pmpCurrent = _pmpStart;
+#endif
+
+ msfDebugOut((DEB_ITRACE, "Out CMSFPageTable::Init\n"));
+
+ Err:
+
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::FlushPage, public
+//
+// Synopsis: Flush a page
+//
+// Arguments: [pmp] -- Pointer to page to flush
+//
+// Returns: Appropriate status code
+//
+// History: 09-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPageTable_FlushPage)
+#endif
+
+SCODE CMSFPageTable::FlushPage(CMSFPage *pmp)
+{
+ SCODE sc = S_OK;
+
+ pmp->AddRef();
+
+ CMStream *pms;
+ pms = pmp->GetVector()->GetParent();
+
+ //Flush the page, reset the dirty bit.
+
+ msfAssert((pmp->GetSect() != ENDOFCHAIN) &&
+ aMsg("Page location not set - don't know where to flush to."));
+
+ ULONG ulRet;
+
+ ILockBytes *pilb;
+#if DBG == 1
+ if ((pmp->GetSid() == SIDFAT) && (pms->IsInCOW()))
+ {
+ msfDebugOut((DEB_ITRACE, "** Fat sect %lu written to %lX\n",
+ pmp->GetOffset(), pmp->GetSect()));
+ }
+ if ((pmp->GetSid() == SIDDIF) && (pms->IsInCOW()))
+ {
+ msfDebugOut((DEB_ITRACE, "** DIF sect %lu written to %lX\n",
+ pmp->GetOffset(), pmp->GetSect()));
+ }
+
+#endif
+ ULARGE_INTEGER ul;
+ ULISet32(ul, ConvertSectOffset(
+ pmp->GetSect(),
+ 0,
+ pms->GetSectorShift()));
+
+ pilb = pms->GetILB();
+
+ msfAssert(!pms->IsUnconverted() &&
+ aMsg("Tried to flush page to unconverted base."));
+
+ sc = GetScode(pilb->WriteAt(ul,
+ (BYTE *)(pmp->GetData()),
+ _cbSector,
+ &ulRet));
+ if (sc == E_PENDING)
+ {
+ sc = STG_E_PENDINGCONTROL;
+ }
+ msfChk(sc);
+
+ pmp->ResetDirty();
+
+ Err:
+ pmp->Release();
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::GetFreePage, public
+//
+// Synopsis: Return a pointer to a free page.
+//
+// Arguments: [ppmp] -- Pointer to storage for return pointer
+//
+// Returns: Appropriate status code
+//
+// History: 22-Oct-92 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPageTable_GetFreePage)
+#endif
+
+SCODE CMSFPageTable::GetFreePage(CMSFPage **ppmp)
+{
+ SCODE sc = S_OK;
+ CMSFPage *pmp;
+ if (_cPages > _cActivePages)
+ {
+ //We have some unused page already allocated. Find and return it.
+ pmp = BP_TO_P(CMSFPage *, _pmpCurrent);
+
+ do
+ {
+ pmp = pmp->GetNext();
+ }
+ while ((pmp != _pmpCurrent) && (pmp->GetSid() != NOSTREAM));
+
+ msfAssert((pmp->GetSid() == NOSTREAM) &&
+ aMsg("Expected empty page, none found."));
+
+ *ppmp = pmp;
+ _cActivePages++;
+ }
+ else if (_cPages == _cMaxPages)
+ {
+ msfMem(pmp = FindSwapPage());
+ msfDebugOut((DEB_ITRACE, "Got swap page %p\n",pmp));
+
+ msfAssert((pmp->GetVector() != NULL) &&
+ aMsg("FindSwapPage returned unowned page."));
+
+ msfDebugOut((DEB_ITRACE, "Freeing page %lu from vector %p\n",
+ pmp->GetOffset(), pmp->GetVector()));
+
+
+ if (pmp->IsDirty())
+ {
+ msfChk(FlushPage(pmp));
+ msfAssert(!pmp->IsDirty() &&
+ aMsg("Page remained dirty after flush call"));
+ }
+
+ pmp->GetVector()->FreeTable(pmp->GetOffset());
+#if DBG == 1
+ pmp->SetVector(NULL);
+#endif
+ *ppmp = pmp;
+ }
+ else
+ {
+ //Create a new page and return it.
+ pmp = GetNewPage();
+ if (pmp != NULL)
+ {
+ *ppmp = pmp;
+ _cActivePages++;
+ _cPages++;
+ }
+ else
+ {
+ msfMem(pmp = FindSwapPage());
+ if (pmp->IsDirty())
+ {
+ msfChk(FlushPage(pmp));
+ msfAssert(!pmp->IsDirty() &&
+ aMsg("Page remained dirty after flush call"));
+ }
+ pmp->GetVector()->FreeTable(pmp->GetOffset());
+#if DBG == 1
+ pmp->SetVector(NULL);
+#endif
+ *ppmp = pmp;
+ }
+ }
+
+ Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::FindPage, public
+//
+// Synopsis: Find and return a given page
+//
+// Arguments: [ppv] -- Pointer to vector of page to return
+// [sid] -- SID of page to return
+// [ulOffset] -- Offset of page to return
+// [ppmp] -- Location to return pointer
+//
+// Returns: Appropriate status code
+//
+// History: 22-Oct-92 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPageTable_FindPage)
+#endif
+
+SCODE CMSFPageTable::FindPage(
+ CPagedVector *ppv,
+ SID sid,
+ ULONG ulOffset,
+ CMSFPage **ppmp)
+{
+ SCODE sc;
+ CMSFPage *pmp = BP_TO_P(CMSFPage *, _pmpCurrent);
+
+ do
+ {
+ if ((pmp->GetVector() == ppv) && (pmp->GetOffset() == ulOffset))
+ {
+ //Bingo!
+
+ *ppmp = pmp;
+ return STG_S_FOUND;
+ }
+
+ pmp = pmp->GetNext();
+ }
+ while (pmp != _pmpCurrent);
+
+ //The page isn't currently in memory. Get a free page and
+ //bring it into memory.
+
+ msfChk(GetFreePage(&pmp));
+
+ msfAssert((pmp->GetVector() == NULL) &&
+ aMsg("Attempting to reassign owned page."));
+ pmp->SetVector(ppv);
+ pmp->SetSid(sid);
+ pmp->SetOffset(ulOffset);
+#ifdef SORTPAGETABLE
+ SetSect(pmp, ENDOFCHAIN);
+#else
+ pmp->SetSect(ENDOFCHAIN);
+#endif
+
+ *ppmp = pmp;
+
+ Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::GetPage, public
+//
+// Synopsis: Find and return a given page
+//
+// Arguments: [sid] -- SID of page to return
+// [ulOffset] -- Offset of page to return
+// [ppmp] -- Location to return pointer
+//
+// Returns: Appropriate status code
+//
+// History: 22-Oct-92 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPageTable_GetPage)
+#endif
+
+SCODE CMSFPageTable::GetPage(
+ CPagedVector *ppv,
+ SID sid,
+ ULONG ulOffset,
+ SECT sectKnown,
+ CMSFPage **ppmp)
+{
+ SCODE sc;
+
+ *ppmp = NULL;
+ msfChk(FindPage(ppv, sid, ulOffset, ppmp));
+
+ (*ppmp)->AddRef();
+
+ if (sc != STG_S_FOUND)
+ {
+ ULONG ulRet;
+ SECT sect;
+
+ if (sectKnown != ENDOFCHAIN)
+ {
+ sect = sectKnown;
+ }
+ else
+ {
+ msfChk(ppv->GetParent()->GetSect(sid, ulOffset, &sect));
+ }
+#ifdef SORTPAGETABLE
+ SetSect(*ppmp, sect);
+#else
+ (*ppmp)->SetSect(sect);
+#endif
+
+ CMStream *pms = (*ppmp)->GetVector()->GetParent();
+#if DBG == 1
+ if ((sid == SIDFAT) && (pms->IsInCOW()))
+ {
+ msfDebugOut((DEB_ITRACE, "Fat sect %lu read from %lX\n",
+ ulOffset, sect));
+ }
+ if ((sid == SIDDIF) && (pms->IsInCOW()))
+ {
+ msfDebugOut((DEB_ITRACE, "DIF sect %lu read from %lX\n",
+ ulOffset, sect));
+ }
+
+#endif
+
+ ULARGE_INTEGER ul;
+ ULISet32(ul, ConvertSectOffset(
+ (*ppmp)->GetSect(),
+ 0,
+ pms->GetSectorShift()));
+
+ msfAssert(pms->GetILB() != NULL &&
+ aMsg("NULL ILockBytes - missing SetAccess?"));
+
+ sc = GetScode(pms->GetILB()->ReadAt(ul,
+ (BYTE *)((*ppmp)->GetData()),
+ _cbSector,
+ &ulRet));
+ if (sc == E_PENDING)
+ {
+ sc = STG_E_PENDINGCONTROL;
+ }
+ msfChk(sc);
+
+ if (ulRet != _cbSector)
+ {
+ // 09/23/93 - No error, but insufficient bytes read
+ sc = STG_E_READFAULT;
+ }
+ }
+
+Err:
+ if (*ppmp != NULL)
+ {
+ if (FAILED(sc))
+ {
+ // 09/19/93 - Reset page so that we don't accidentally use it
+
+ (*ppmp)->SetSid(NOSTREAM);
+ (*ppmp)->SetOffset(0);
+#ifdef SORTPAGETABLE
+ SetSect(*ppmp, ENDOFCHAIN);
+#else
+ (*ppmp)->SetSect(ENDOFCHAIN);
+#endif
+ (*ppmp)->SetFlags(0);
+ (*ppmp)->SetVector(NULL);
+ _cActivePages--;
+ }
+ (*ppmp)->Release();
+ }
+
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::ReleasePage, public
+//
+// Synopsis: Release a given page
+//
+// Arguments: [sid] -- SID of page to release
+// [ulOffset] -- Offset of page to release
+//
+// History: 28-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPageTable_ReleasePage)
+#endif
+
+void CMSFPageTable::ReleasePage(CPagedVector *ppv,
+ SID sid, ULONG ulOffset)
+{
+ SCODE sc;
+ CMSFPage *pmp;
+
+ sc = FindPage(ppv, sid, ulOffset, &pmp);
+
+ if (SUCCEEDED(sc))
+ {
+ pmp->Release();
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::Flush, public
+//
+// Synopsis: Flush dirty pages to disk
+//
+// Returns: Appropriate status code
+//
+// History: 02-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPageTable_Flush)
+#endif
+
+SCODE CMSFPageTable::Flush(void)
+{
+#ifndef SORTPAGETABLE
+ SCODE sc = S_OK;
+
+ CMSFPage *pmp = BP_TO_P(CMSFPage *, _pmpCurrent);
+
+ //We use pmpLast in case FlushPage changes _pmpCurrent.
+ CMSFPage *pmpLast = pmp;
+
+ do
+ {
+ if ((pmp->IsDirty()) && !(pmp->IsInUse()) &&
+ !(pmp->GetVector()->GetParent()->IsScratch()))
+ {
+ msfChk(FlushPage(pmp));
+ }
+
+ pmp = pmp->GetNext();
+
+ }
+ while (pmp != pmpLast);
+
+ Err:
+ return sc;
+#else
+ SCODE sc = S_OK;
+ msfDebugOut((DEB_ITRACE, "In CMSFPageTable::Flush()\n"));
+
+ CMSFPage *pmp;
+ CMSFPage *pmpStart;
+ BYTE *pb = NULL;
+ ULONG ulBufferSize = 0;
+
+ pmpStart = BP_TO_P(CMSFPage *, _pmpStart);
+ pmp = pmpStart;
+ do
+ {
+ CMSFPage *pmpFirst;
+ CMSFPage *pmpLast;
+
+ //Find first page that needs to be flushed.
+ while (!pmp->IsFlushable())
+ {
+ pmp = pmp->GetNext();
+ if (pmp == pmpStart)
+ break;
+ }
+
+ //If we haven't hit the end of the list, then find a contiguous
+ // range of pages to flush.
+ if (pmp->IsFlushable())
+ {
+ pmpFirst = pmp;
+ //Store pointer to last page in range in pmpLast.
+ while (pmp->IsFlushable())
+ {
+ pmpLast = pmp;
+ pmp = pmp->GetNext();
+ if (pmp->GetSect() != pmpLast->GetSect() + 1)
+ {
+ break;
+ }
+ }
+ //At this point, we can flush everything from pmpFirst to
+ // pmpLast, and they are all contiguous. pmp points to the
+ // next sector after the current range.
+
+ if (pmpFirst == pmpLast)
+ {
+ msfDebugOut((DEB_ITRACE,
+ "Flushing page to %lx\n",
+ pmpFirst->GetSect()));
+
+ //Only one page: Call FlushPage.
+ msfChk(FlushPage(pmpFirst));
+ }
+ else
+ {
+ ULONG ulWriteSize;
+ ULONG cSect;
+ CMSFPage *pmpTemp;
+ ULONG i;
+
+ msfDebugOut((DEB_ITRACE,
+ "Flushing pages from %lx to %lx\n",
+ pmpFirst->GetSect(),
+ pmpLast->GetSect()));
+
+ cSect = pmpLast->GetSect() - pmpFirst->GetSect() + 1;
+ ulWriteSize = cSect * _cbSector;
+
+ if (ulWriteSize > ulBufferSize)
+ {
+ delete pb;
+ pb = new BYTE[ulWriteSize];
+ ulBufferSize = ulWriteSize;
+ }
+
+ pmpTemp = pmpFirst;
+ if (pb == NULL)
+ {
+ ulBufferSize = 0;
+
+ //Low memory case - write out pages one at a time
+ for (i = 0; i < cSect; i++)
+ {
+ msfChk(FlushPage(pmpTemp));
+ pmpTemp = pmpTemp->GetNext();
+ }
+ }
+ else
+ {
+ for (i = 0; i < cSect; i++)
+ {
+ memcpy(pb + (i * _cbSector),
+ pmpTemp->GetData(),
+ _cbSector);
+ pmpTemp = pmpTemp->GetNext();
+ }
+ //The buffer is loaded up - now write it out.
+ ULARGE_INTEGER ul;
+ ULONG cbWritten;
+ ULISet32(ul, ConvertSectOffset(pmpFirst->GetSect(),
+ 0,
+ _pmsParent->GetSectorShift()));
+ sc = _pmsParent->GetILB()->WriteAt(ul,
+ pb,
+ ulWriteSize,
+ &cbWritten);
+ if (sc == E_PENDING)
+ {
+ sc = STG_E_PENDINGCONTROL;
+ }
+ msfChk(sc);
+ if (cbWritten != ulWriteSize)
+ {
+ msfErr(Err, STG_E_WRITEFAULT);
+ }
+
+ //Mark all the pages as clean.
+ pmpTemp = pmpFirst;
+ for (i = 0; i < cSect; i++)
+ {
+ pmpTemp->ResetDirty();
+ pmpTemp = pmpTemp->GetNext();
+ }
+ }
+ }
+ }
+ else
+ {
+ //We've hit the end of the list, do nothing.
+ }
+ }
+ while (pmp != pmpStart);
+ msfDebugOut((DEB_ITRACE, "Out CMSFPageTable::Flush() => %lX\n", sc));
+Err:
+ if (pb != NULL)
+ {
+ delete pb;
+ }
+ return sc;
+#endif //SORTPAGETABLE
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::FreePages, public
+//
+// Synopsis: Free all the pages associated with a vector.
+//
+// Arguments: [ppv] -- Pointer to vector to free pages for.
+//
+// History: 09-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPageTable_FreePages)
+#endif
+
+void CMSFPageTable::FreePages(CPagedVector *ppv)
+{
+ CMSFPage *pmp = BP_TO_P(CMSFPage *, _pmpCurrent);
+
+ do
+ {
+ if (pmp->GetVector() == ppv)
+ {
+ pmp->SetSid(NOSTREAM);
+ pmp->SetVector(NULL);
+ pmp->ResetDirty();
+ _cActivePages--;
+ }
+ pmp = pmp->GetNext();
+ }
+ while (pmp != _pmpCurrent);
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::FindSwapPage, private
+//
+// Synopsis: Find a page to swap out.
+//
+// Arguments: None.
+//
+// Returns: Pointer to page to swap out.
+//
+// History: 22-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPageTable_FindSwapPage)
+#endif
+
+CMSFPage * CMSFPageTable::FindSwapPage(void)
+{
+#if DBG == 1
+ ULONG cpInUse = 0;
+#endif
+
+ while (TRUE)
+ {
+ if (!_pmpCurrent->IsInUse())
+ {
+ DWORD dwFlags;
+
+ dwFlags = _pmpCurrent->GetFlags();
+ _pmpCurrent->SetFlags(dwFlags & ~FB_TOUCHED);
+
+ CMSFPage *pmpTemp = _pmpCurrent->GetNext();
+ _pmpCurrent = P_TO_BP(CBasedMSFPagePtr, pmpTemp);
+
+ if (!(dwFlags & FB_TOUCHED))
+ {
+ return _pmpCurrent->GetPrev();
+ }
+ }
+ else
+ {
+ CMSFPage *pmpTemp = _pmpCurrent->GetNext();
+ _pmpCurrent = P_TO_BP(CBasedMSFPagePtr, pmpTemp);
+ }
+#if DBG == 1
+ cpInUse++;
+ msfAssert((cpInUse < 3 * _cPages) &&
+ aMsg("No swappable pages."));
+#endif
+
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::CopyPage, public
+//
+// Synopsis: Copy a page in memory, returning NULL if there is
+// insufficient space for a new page without swapping.
+//
+// Arguments: [ppv] -- Pointer to vector that will own the copy.
+// [pmpOld] -- Pointer to page to copy.
+// [ppmp] -- Pointer to return value
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 04-Dec-92 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CMSFPageTable_CopyPage)
+#endif
+
+SCODE CMSFPageTable::CopyPage(
+ CPagedVector *ppv,
+ CMSFPage *pmpOld,
+ CBasedMSFPagePtr *ppmp)
+{
+ CMSFPage *pmp;
+
+ pmp = NULL;
+
+ if (pmpOld != NULL)
+ {
+ msfAssert(!pmpOld->IsDirty() &&
+ aMsg("Copying dirty page."));
+
+ if (_cPages > _cActivePages)
+ {
+
+ //We have some unused page already allocated. Find and return it.
+ pmp = BP_TO_P(CMSFPage *, _pmpCurrent);
+
+ do
+ {
+ pmp = pmp->GetNext();
+ }
+ while ((pmp != _pmpCurrent) && (pmp->GetSid() != NOSTREAM));
+
+
+ msfAssert((pmp->GetSid() == NOSTREAM) &&
+ aMsg("Expected empty page, none found."));
+ _cActivePages++;
+
+ }
+ else if (_cPages < _cMaxPages)
+ {
+ //Create a new page and return it.
+ pmp = GetNewPage();
+ if (pmp != NULL)
+ {
+ _cActivePages++;
+ _cPages++;
+ }
+ }
+
+ if (pmp != NULL)
+ {
+ msfAssert((pmp->GetVector() == NULL) &&
+ aMsg("Attempting to reassign owned page."));
+ pmp->SetVector(ppv);
+ pmp->SetSid(pmpOld->GetSid());
+ pmp->SetOffset(pmpOld->GetOffset());
+#ifdef SORTPAGETABLE
+ SetSect(pmp, pmpOld->GetSect());
+#else
+ pmp->SetSect(pmpOld->GetSect());
+#endif
+
+ memcpy(pmp->GetData(), pmpOld->GetData(), (USHORT)_cbSector);
+ }
+ }
+
+ *ppmp = P_TO_BP(CBasedMSFPagePtr, pmp);
+
+ return S_OK;
+}
+
+
+#if DBG == 1
+
+void CMSFPageTable::AddPageRef(void)
+{
+ msfAssert(_cCurrentPageRef >= 0);
+ _cCurrentPageRef++;
+ if (_cCurrentPageRef > _cMaxPageRef)
+ {
+ _cMaxPageRef = _cCurrentPageRef;
+ }
+}
+
+void CMSFPageTable::ReleasePageRef(void)
+{
+ _cCurrentPageRef--;
+ msfAssert(_cCurrentPageRef >= 0);
+}
+#endif
diff --git a/private/ole32/stg/msf/pbstream.cxx b/private/ole32/stg/msf/pbstream.cxx
new file mode 100644
index 000000000..c50ded3a4
--- /dev/null
+++ b/private/ole32/stg/msf/pbstream.cxx
@@ -0,0 +1,974 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: pbstream.cxx
+//
+// Contents: CPubStream code
+//
+// Classes:
+//
+// Functions:
+//
+// History: 16-Jan-92 PhilipLa Created.
+// 12-Jun-96 MikeHill Renamed FlushNoException to Write,
+// and removed the Commit.
+// 21-Jun-96 MikeHill Fixed an Assert.
+// 01-Jul-96 MikeHill - Removed Win32 SEH from PropSet code.
+// - Added propset byte-swapping support.
+// 08-Nov-96 MikeHill Don't call RtlOnMappedStreamEvent unnecessarily.
+//
+//--------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+#pragma hdrstop
+
+#include <sstream.hxx>
+#include <publicdf.hxx>
+#include <pbstream.hxx>
+#ifndef REF
+#include <tstream.hxx>
+#endif //!REF
+#include <docfilep.hxx>
+#include <reserved.hxx>
+#include <propdbg.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubStream::CPubStream, public
+//
+// Synopsis: Constructor
+//
+// History: 16-Jan-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubStream_CPubStream)
+#endif
+
+
+CPubStream::CPubStream(CPubDocFile *ppdf,
+ DFLAGS df,
+ CDfName const *pdfn)
+#ifdef NEWPROPS
+#pragma warning(disable: 4355)
+ : _PubMappedStream(this)
+#pragma warning(default: 4355)
+#endif
+{
+ _psParent = NULL;
+ _df = df;
+ _ppdfParent = P_TO_BP(CBasedPubDocFilePtr, ppdf);
+ _cReferences = 1;
+ _dfn.Set(pdfn->GetLength(), pdfn->GetBuffer());
+ _ppdfParent->AddChild(this);
+ _fDirty = FALSE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubStream::Init, public
+//
+// Synopsis: Init function
+//
+// Arguments: [psParent] - Stream in transaction set
+// [dlLUID] - LUID
+//
+// History: 16-Jan-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubStream_Init)
+#endif
+
+void CPubStream::Init(PSStream *psParent,
+ DFLUID dlLUID)
+{
+ _psParent = P_TO_BP(CBasedSStreamPtr, psParent);
+ _luid = dlLUID;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubStream::~CPubStream, public
+//
+// Synopsis: Destructor
+//
+// History: 16-Jan-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubStream_1CPubStream)
+#endif
+
+CPubStream::~CPubStream()
+{
+ msfAssert(_cReferences == 0);
+
+ if (SUCCEEDED(CheckReverted()))
+ {
+ if (_ppdfParent != NULL)
+ _ppdfParent->ReleaseChild(this);
+ if (_psParent)
+ {
+ _psParent->Release();
+ }
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPubStream::Release, public
+//
+// Synopsis: Release a pubstream object
+//
+// Arguments: None.
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Delete 'this' - all real work done by destructor.
+//
+// History: 24-Jan-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubStream_vRelease) // Pubst_Release_TEXT
+#endif
+
+void CPubStream::vRelease(VOID)
+{
+ LONG lRet;
+
+ msfDebugOut((DEB_ITRACE,"In CPubStream::Release()\n"));
+ msfAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+
+#ifndef REF
+ msfAssert(!P_TRANSACTED(_df));
+#endif //!REF
+
+ if (lRet == 0)
+ {
+#ifdef NEWPROPS
+ _PubMappedStream.Cleanup();
+#endif
+ delete this;
+ }
+ msfDebugOut((DEB_ITRACE,"Out CPubStream::Release()\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubStream::Stat, public
+//
+// Synopsis: Fills in a stat buffer
+//
+// Arguments: [pstatstg] - Buffer
+// [grfStatFlag] - stat flags
+//
+// Returns: S_OK or error code
+//
+// Modifies: [pstatstg]
+//
+// History: 24-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubStream_Stat) // Stat_TEXT
+#endif
+
+SCODE CPubStream::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc = S_OK;
+
+ msfDebugOut((DEB_ITRACE, "In CPubStream::Stat(%p)\n", pstatstg));
+ msfChk(CheckReverted());
+
+ msfAssert(_ppdfParent != NULL);
+ pstatstg->grfMode = DFlagsToMode(_df);
+
+ pstatstg->clsid = CLSID_NULL;
+ pstatstg->grfStateBits = 0;
+
+ pstatstg->pwcsName = NULL;
+ if ((grfStatFlag & STATFLAG_NONAME) == 0)
+ {
+ msfMem(pstatstg->pwcsName = (WCHAR *)TaskMemAlloc(_dfn.GetLength()));
+ memcpy(pstatstg->pwcsName, _dfn.GetBuffer(), _dfn.GetLength());
+ }
+
+ ULONG cbSize;
+ _psParent->GetSize(&cbSize);
+ ULISet32(pstatstg->cbSize, cbSize);
+ msfDebugOut((DEB_ITRACE, "Out CPubStream::Stat\n"));
+
+Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubStream::RevertFromAbove, public
+//
+// Synopsis: Parent has asked for reversion
+//
+// History: 29-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubStream_RevertFromAbove) // Pubdf_Revert_TEXT
+#endif
+
+void CPubStream::RevertFromAbove(void)
+{
+ msfDebugOut((DEB_ITRACE, "In CPubStream::RevertFromAbove:%p()\n", this));
+ _df |= DF_REVERTED;
+ _psParent->Release();
+#if DBG == 1
+ _psParent = NULL;
+#endif
+ msfDebugOut((DEB_ITRACE, "Out CPubStream::RevertFromAbove\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubStream::FlushBufferedData, public
+//
+// Synopsis: Flush out the property buffers.
+//
+// History: 5-May-1995 BillMo Created
+//
+//---------------------------------------------------------------
+
+#ifdef NEWPROPS
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubStream_RevertFromAbove) // Pubdf_Revert_TEXT
+#endif
+
+SCODE CPubStream::FlushBufferedData(int recursionlevel)
+{
+ SCODE sc = S_OK;
+
+ msfDebugOut((DEB_ITRACE, "In CPubStream::FlushBufferedData:%p()\n", this));
+
+ _PubMappedStream.Flush(&sc);
+
+ msfDebugOut((DEB_ITRACE, "Out CPubStream::FlushBufferedData\n"));
+
+ PropDbg((DEB_PROP_MAP, "CPubStream(%08X):FlushBufferedData returns %08X\n",
+ this, sc));
+
+ return sc;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubStream::Commit, public
+//
+// Synopsis: Flush stream changes to disk in the direct case.
+//
+// Arguments: None
+//
+// Returns: Appropriate status code
+//
+// History: 12-Jan-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPubStream_Commit) // Pubdf_Commit_TEXT
+#endif
+
+SCODE CPubStream::Commit(DWORD dwFlags)
+{
+ SCODE sc = S_OK;
+ msfDebugOut((DEB_ITRACE, "In CPubStream::Commit:%p()\n", this));
+
+#ifndef REF
+ msfAssert(!P_TRANSACTED(_df));
+#endif //!REF
+ if (SUCCEEDED(sc = CheckReverted()))
+ {
+ if (P_WRITE(_df))
+ {
+#ifndef REF
+ if (_ppdfParent->GetTransactedDepth() == 0)
+ {
+ //Parent is direct, so call commit on it and return.
+#endif //!REF
+ sc = _ppdfParent->GetBaseMS()->Flush(FLUSH_CACHE(dwFlags));
+#ifndef REF
+ }
+#endif //!REF
+ SetClean();
+ }
+ }
+ msfDebugOut((DEB_ITRACE, "Out CPubStream::Commit\n"));
+ return sc;
+}
+
+#ifdef NEWPROPS
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::Open
+//
+// Synopsis: Opens mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes: Gets the size of the underlying stream and reads it
+// into memory so that it can be "mapped."
+//
+//--------------------------------------------------------------------
+
+VOID CPubMappedStream::Open(IN VOID *powner, OUT LONG *phr)
+{
+ *phr = S_OK;
+ olAssert(!_fLowMem);
+
+ // If given a pointer to the owner of this mapped stream,
+ // save it. This could be NULL (i.e., when called from
+ // ReOpen).
+
+ if( NULL != powner )
+ _powner = P_TO_BP( CBasedBytePtr, ((BYTE*) powner) );
+
+ if (_pb == NULL)
+ {
+ VOID *pv;
+
+ _cbUsed = 0;
+
+ *phr = _pst->GetSize(&_cbOriginalStreamSize);
+ if (*phr != S_OK)
+ goto Throw;
+
+ if (_cbOriginalStreamSize > CBMAXPROPSETSTREAM)
+ {
+ *phr = STG_E_INVALIDHEADER;
+ goto Throw;
+ }
+
+ _cbUsed = _cbOriginalStreamSize;
+
+ pv = GetMalloc()->Alloc(_cbOriginalStreamSize);
+
+ if (pv == NULL)
+ {
+ pv = g_ReservedMemory.LockMemory(); // could wait until previous
+ // property call completes
+ _fLowMem = TRUE;
+ }
+ _pb = P_TO_BP(CBasedBytePtr, ((BYTE*)pv));
+ *phr = _pst->ReadAt(0,
+ pv,
+ _cbOriginalStreamSize,
+ &_cbUsed);
+
+#ifdef _MAC
+ // Notify our owner that we've read in new data.
+ if (*phr == S_OK && _powner != NULL && 0 != _cbUsed)
+ {
+ *phr = RtlOnMappedStreamEvent( BP_TO_P(VOID*, _powner), pv, _cbUsed );
+ }
+#endif
+
+ if (*phr != S_OK)
+ {
+ if (_fLowMem)
+ g_ReservedMemory.UnlockMemory();
+ else
+ GetMalloc()->Free(pv);
+
+ _pb = NULL;
+ _cbUsed = 0;
+ _fLowMem = FALSE;
+ goto Throw;
+ }
+
+ }
+
+ PropDbg((DEB_PROP_MAP, "CPubStream(%08X):Open returns normally\n", this));
+ return;
+
+Throw:
+
+ PropDbg((DEB_PROP_MAP, "CPubStream(%08X):Open exception returns %08X\n", this, *phr));
+
+ return;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::Flush
+//
+// Synopsis: Flush the mapped Stream to the underlying Stream,
+// and Commit that Stream.
+//
+//--------------------------------------------------------------------
+
+VOID CPubMappedStream::Flush(OUT LONG *phr)
+{
+ // Write out any data we have cached to the Stream.
+ *phr = Write();
+
+ // Commite the Stream.
+ if( S_OK == *phr )
+ {
+ *phr = _pst->Commit(STGC_DEFAULT);
+ }
+
+ return;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::Close
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes: Does nothing because the object may be mapped in
+// another process.
+//
+//--------------------------------------------------------------------
+
+VOID CPubMappedStream::Close(OUT LONG *phr)
+{
+ // Write the changes. We don't need to Commit them,
+ // they will be implicitely committed when the
+ // Stream is Released.
+
+ *phr = Write();
+
+ if( FAILED(*phr) )
+ {
+ PropDbg((DEB_PROP_MAP, "CPubStream(%08X)::Close exception returns %08X\n", this, *phr));
+ }
+
+ return;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::ReOpen
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes: Combined open and map.
+//
+//--------------------------------------------------------------------
+
+VOID CPubMappedStream::ReOpen(IN OUT VOID **ppv, OUT LONG *phr)
+{
+ *ppv = NULL;
+
+ Open(NULL, // Unspecified owner.
+ phr);
+
+ if( SUCCEEDED(*phr) )
+ *ppv = BP_TO_P(VOID*, _pb);
+
+ return;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::Quiesce
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes: Meaningless for docfile mapped stream.
+//
+//--------------------------------------------------------------------
+
+VOID CPubMappedStream::Quiesce(VOID)
+{
+ olAssert(_pb != NULL);
+ DfpdbgCheckUnusedMemory();
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::Map
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes: Return the address of the "mapping" buffer.
+//
+//--------------------------------------------------------------------
+
+VOID CPubMappedStream::Map(BOOLEAN fCreate, VOID **ppv)
+{
+ olAssert(_pb != NULL);
+ DfpdbgCheckUnusedMemory();
+ *ppv = BP_TO_P(VOID*, _pb);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::Unmap
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes: Unmapping is merely zeroing the pointer. We don't
+// flush because that's done explicitly by the
+// CPropertyStorage class.
+//
+//
+//--------------------------------------------------------------------
+
+VOID CPubMappedStream::Unmap(BOOLEAN fFlush, VOID **pv)
+{
+ DfpdbgCheckUnusedMemory();
+ *pv = NULL;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::Write
+//
+// Synopsis: Writes a mapped view of an exposed Stream to the
+// underlying Stream. Used by RtlCreatePropertySet et al.
+//
+// Notes: The Stream is not commited. To commit the Stream, in
+// addition to writing it, the Flush method should be used.
+// The Commit is omitted so that it can be skipped in
+// the Property Set Close path, thus eliminating a
+// performance penalty.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPubMappedStream::Write ()
+{
+ HRESULT hr;
+ ULONG cbWritten;
+
+ if (!_fDirty)
+ {
+ PropDbg((DEB_PROP_MAP, "CPubStream(%08X):Flush returns with not-dirty\n", this));
+
+ return S_OK; // flushing a stream which isn't a property stream
+ // this could be optimized by propagating a 'no property streams'
+ // flag up the storage hierachy such that FlushBufferedData is
+ // not even called for non-property streams.
+ }
+
+ olAssert( _pst != NULL );
+ olAssert( _pb != NULL );
+ olAssert( _powner != NULL );
+
+#ifdef _MAC
+ // Notify our owner that we're about to perform a Write.
+ hr = RtlOnMappedStreamEvent( BP_TO_P(VOID*, _powner), BP_TO_P(VOID *, _pb), _cbUsed );
+ if( S_OK != hr ) goto Exit;
+#endif
+
+ hr = _pst->WriteAt(0, BP_TO_P(VOID *, _pb), _cbUsed, &cbWritten);
+ if( S_OK != hr ) goto Exit;
+
+#ifdef _MAC
+ // Notify our owner that we're done with the Write.
+ hr = RtlOnMappedStreamEvent( BP_TO_P(VOID*, _powner), BP_TO_P(VOID *, _pb), _cbUsed );
+ if( S_OK != hr ) goto Exit;
+#endif
+
+ if (_cbUsed < _cbOriginalStreamSize)
+ {
+ // if the stream is shrinking, this is a good time to do it.
+ hr = _pst->SetSize(_cbUsed);
+ if( S_OK != hr ) goto Exit;
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if (hr == S_OK || hr == STG_E_REVERTED)
+ {
+ _fDirty = FALSE;
+ }
+
+ PropDbg((DEB_PROP_MAP, "CPubStream(%08X):Flush %s returns hr=%08X\n",
+ this, hr != S_OK ? "exception" : "", hr));
+
+ return hr;
+
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::GetSize
+//
+// Synopsis: Returns size of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//--------------------------------------------------------------------
+
+ULONG CPubMappedStream::GetSize(OUT LONG *phr)
+{
+ *phr = S_OK;
+
+ if (_pb == NULL)
+ Open(NULL, // Unspecified owner
+ phr);
+
+ if( SUCCEEDED(*phr) )
+ {
+ olAssert(_pb != NULL);
+ DfpdbgCheckUnusedMemory();
+ }
+
+ return _cbUsed;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::SetSize
+//
+// Synopsis: Sets size of "map." Called by
+// NtCreatePropertySet et al.
+//
+// Arguments: [cb] -- requested size.
+// [fPersistent] -- FALSE if expanding in-memory read-only image
+// [ppv] -- new mapped address.
+//
+// Signals: Not enough disk space.
+//
+// Notes: In a low memory situation we may not be able to
+// get the requested amount of memory. In this
+// case we must fall back on disk storage as the
+// actual map.
+//
+//--------------------------------------------------------------------
+
+VOID
+CPubMappedStream::SetSize(ULONG cb, IN BOOLEAN fPersistent, VOID **ppv, OUT LONG *phr)
+{
+ VOID *pv;
+
+ *phr = S_OK;
+ olAssert(cb != 0);
+
+ DfpdbgCheckUnusedMemory();
+
+ //
+ // if we are growing the data, we should grow the stream
+ //
+
+ if (fPersistent && cb > _cbUsed)
+ {
+ *phr = _pst->SetSize(cb);
+ if (*phr != S_OK)
+ goto Throw;
+ }
+
+ if (!_fLowMem)
+ {
+ pv = GetMalloc()->Realloc(BP_TO_P(VOID*, _pb), cb);
+
+ if (pv == NULL)
+ {
+ // allocation failed: we need to try using a backup mechanism for
+ // more memory.
+ // copy the data to the global reserved chunk... we will wait until
+ // someone else has released it. it will be released on the way out
+ // of the property code.
+
+ _fLowMem = TRUE;
+ pv = g_ReservedMemory.LockMemory();
+ if (NULL != BP_TO_P(BYTE*, _pb))
+ {
+ memcpy(pv, BP_TO_P(VOID*, _pb), _cbUsed);
+ }
+ GetMalloc()->Free(BP_TO_P(VOID*, _pb));
+ }
+ _pb = P_TO_BP(CBasedBytePtr, ((BYTE*)pv));
+ *ppv = pv;
+ }
+ else
+ {
+ *ppv = BP_TO_P(VOID*, _pb);
+ }
+
+ _cbUsed = cb;
+ DfpdbgFillUnusedMemory();
+
+Throw:
+
+ PropDbg((DEB_PROP_MAP, "CPubStream(%08X):SetSize %s returns hr=%08X\n",
+ this, *phr != S_OK ? "exception" : "", *phr));
+
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::Lock
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+// the exposed stream has enforced the locking.
+//
+// we use the lock to indicate whether the object is
+// dirty
+//
+//--------------------------------------------------------------------
+
+NTSTATUS CPubMappedStream::Lock(BOOLEAN fExclusive)
+{
+ return(STATUS_SUCCESS);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::Unlock
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+NTSTATUS CPubMappedStream::Unlock(VOID)
+{
+ // if at the end of the properties set/get call we have the low
+ // memory region locked, we flush to disk.
+ HRESULT hr = S_OK;
+
+ if (_fLowMem)
+ {
+ Flush(&hr);
+
+ g_ReservedMemory.UnlockMemory();
+ _pb = NULL;
+ _cbUsed = 0;
+ _fLowMem = FALSE;
+ PropDbg((DEB_PROP_MAP, "CPubStream(%08X):Unlock low-mem returns NTSTATUS=%08X\n",
+ this, hr));
+ }
+
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::QueryTimeStamps
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+VOID CPubMappedStream::QueryTimeStamps(STATPROPSETSTG *pspss, BOOLEAN fNonSimple) const
+{
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::QueryModifyTime
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+BOOLEAN CPubMappedStream::QueryModifyTime(OUT LONGLONG *pll) const
+{
+ return(FALSE);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::QuerySecurity
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+BOOLEAN CPubMappedStream::QuerySecurity(OUT ULONG *pul) const
+{
+ return(FALSE);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::QueryTimeStamps
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+BOOLEAN CPubMappedStream::IsWriteable() const
+{
+ return TRUE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::SetChangePending
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+#if DBGPROP
+BOOLEAN CPubMappedStream::SetChangePending(BOOLEAN f)
+{
+ BOOL fOld = _fChangePending;
+ _fChangePending = f;
+ return(_fChangePending);
+}
+#endif
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::IsNtMappedStream
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+#if DBGPROP
+BOOLEAN CPubMappedStream::IsNtMappedStream(VOID) const
+{
+ return(FALSE);
+}
+#endif
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::GetHandle
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+HANDLE CPubMappedStream::GetHandle(VOID) const
+{
+ return(INVALID_HANDLE_VALUE);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::SetModified
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+VOID CPubMappedStream::SetModified(VOID)
+{
+ _fDirty = TRUE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::IsModified
+//
+// Synopsis: Operates on mapped view of exposed stream. Called by
+// NtCreatePropertySet et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+BOOLEAN CPubMappedStream::IsModified(VOID) const
+{
+ return _fDirty;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::DfpdbgFillUnusedMemory
+//
+//--------------------------------------------------------------------
+
+#if DBG
+VOID CPubMappedStream::DfpdbgFillUnusedMemory(VOID)
+{
+
+ if (_pb == NULL)
+ return;
+
+ BYTE * pbEndPlusOne = BP_TO_P(BYTE*, _pb) + BytesCommitted();
+
+ for (BYTE *pbUnused = BP_TO_P(BYTE*, _pb) + _cbUsed;
+ pbUnused < pbEndPlusOne;
+ pbUnused++)
+ {
+ *pbUnused = (BYTE)(DWORD)pbUnused;
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPubMappedStream::DfpdbgCheckUnusedMemory
+//
+//--------------------------------------------------------------------
+
+VOID CPubMappedStream::DfpdbgCheckUnusedMemory(VOID)
+{
+
+ if (_pb == NULL)
+ return;
+
+ if (_cbUsed == 0)
+ return;
+
+ BYTE * pbEndPlusOne = BP_TO_P(BYTE*, _pb) + BytesCommitted();
+
+ for (BYTE *pbUnused = BP_TO_P(BYTE*, _pb + _cbUsed) ;
+ pbUnused < pbEndPlusOne;
+ pbUnused ++)
+ {
+ olAssert(*pbUnused == (BYTE)(DWORD)pbUnused);
+ }
+}
+
+#endif // DBG
+#endif
diff --git a/private/ole32/stg/msf/refilb.cxx b/private/ole32/stg/msf/refilb.cxx
new file mode 100644
index 000000000..949546850
--- /dev/null
+++ b/private/ole32/stg/msf/refilb.cxx
@@ -0,0 +1,194 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: refilb.cxx
+//
+// Contents: Reference ILockBytes class
+//
+// Classes:
+//
+// Functions:
+//
+// History: 27-Apr-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+#pragma hdrstop
+
+#ifdef REF
+#include <refilb.hxx>
+#include <stdio.h>
+#include <stdlib.h>
+
+static int filenum = 0;
+
+char * GetTempFileName(void)
+{
+ char *psz = new char[20];
+ strcpy(psz, "dft");
+
+ _itoa(filenum, psz + 3, 10);
+ filenum++;
+ return psz;
+}
+
+CFileILB::CFileILB(char *pszName)
+{
+ _pszName = new char[_MAX_PATH + 1];
+
+ if (pszName == NULL)
+ {
+ _pszName = GetTempFileName();
+ _fDelete = TRUE;
+ }
+ else
+ {
+ strcpy(_pszName, pszName);
+ _fDelete = FALSE;
+ }
+
+ _f = fopen(_pszName, "r+b");
+ if (_f == NULL)
+ {
+ _f = fopen(_pszName, "w+b");
+ }
+ _ulRef = 1;
+}
+
+CFileILB::~CFileILB()
+{
+ fclose(_f);
+
+ if (_fDelete)
+ {
+ _unlink(_pszName);
+ }
+
+ delete _pszName;
+}
+
+STDMETHODIMP CFileILB::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
+{
+ *ppvObj = NULL;
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+STDMETHODIMP_(ULONG) CFileILB::AddRef(void)
+{
+ AtomicInc(&_ulRef);
+ return(_ulRef);
+}
+
+STDMETHODIMP_(ULONG) CFileILB::Release(void)
+{
+ AtomicDec(&_ulRef);
+
+ if (_ulRef > 0)
+ return(_ulRef);
+
+ delete this;
+
+ return(0);
+}
+
+STDMETHODIMP CFileILB::ReadAt(ULARGE_INTEGER ulPosition,
+ VOID HUGEP *pb,
+ ULONG cb,
+ ULONG *pcbRead)
+{
+ fseek(_f, ULIGetLow(ulPosition), SEEK_SET);
+
+ *pcbRead = fread(pb, 1, cb, _f);
+ return NOERROR;
+}
+
+STDMETHODIMP CFileILB::WriteAt(ULARGE_INTEGER ulPosition,
+ VOID const HUGEP *pb,
+ ULONG cb,
+ ULONG FAR *pcbWritten)
+{
+ fseek(_f, ULIGetLow(ulPosition), SEEK_SET);
+
+ *pcbWritten = fwrite(pb, 1, cb, _f);
+ return NOERROR;
+}
+
+STDMETHODIMP CFileILB::Flush(void)
+{
+ return NOERROR;
+}
+
+STDMETHODIMP CFileILB::SetSize(ULARGE_INTEGER cb)
+{
+ fseek(_f, ULIGetLow(cb), SEEK_SET);
+
+ fwrite(NULL, 0, 0, _f);
+ return NOERROR;
+}
+
+STDMETHODIMP CFileILB::LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+
+STDMETHODIMP CFileILB::UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+
+STDMETHODIMP CFileILB::Stat(STATSTG FAR *pstatstg, DWORD grfStatFlag)
+{
+ memset(pstatstg, 0, sizeof(STATSTG));
+
+ if ((grfStatFlag & STATFLAG_NONAME) == 0)
+ {
+ pstatstg->pwcsName = new char[strlen(_pszName)];
+ strcpy(pstatstg->pwcsName, _pszName);
+ }
+
+ pstatstg->type = STGTY_LOCKBYTES;
+
+ ULISetHigh(pstatstg->cbSize, 0);
+
+ fseek(_f, 0, SEEK_END);
+ ULISetLow(pstatstg->cbSize, ftell(_f));
+
+ pstatstg->grfMode = STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE;
+
+ return NOERROR;
+}
+
+
+SCODE CreateFileStream(ILockBytes **ppilb, CDfName *pdfn)
+{
+ *ppilb = new CFileILB(NULL);
+ return S_OK;
+}
+
+SCODE DeleteFileStream(CDfName *pdfn)
+{
+ return S_OK;
+}
+
+STDAPI_(BOOL) IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
+{
+ return (memcmp(&rguid1, &rguid2, sizeof(GUID)) == 0);
+}
+
+STDAPI_(BOOL) CoDosDateTimeToFileTime(
+ WORD nDosDate, WORD nDosTime, FILETIME FAR* lpFileTime)
+{
+ return TRUE;
+}
+
+#endif //REF
+
diff --git a/private/ole32/stg/msf/reftest.cxx b/private/ole32/stg/msf/reftest.cxx
new file mode 100644
index 000000000..c0346ac8a
--- /dev/null
+++ b/private/ole32/stg/msf/reftest.cxx
@@ -0,0 +1,533 @@
+#include <ref.hxx>
+#include <storage.h>
+#include <refilb.hxx>
+#include <ole.hxx>
+#include <msf.hxx>
+#include <stdlib.h>
+
+
+#define STR(x) x
+#define STGP(x) STGM_SHARE_EXCLUSIVE | x
+#define STMP(x) STGM_SHARE_EXCLUSIVE | x
+#define ROOTP(x) STGP(x)
+
+
+#define EXIT_BADSC 1
+
+void error(int code, char *fmt, ...)
+{
+ va_list args;
+
+ args = va_start(args, fmt);
+ fprintf(stderr, "** Fatal error **: ");
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ exit(code);
+}
+
+
+BOOL IsEqualTime(FILETIME ttTime, FILETIME ttCheck)
+{
+ return ttTime.dwLowDateTime == ttCheck.dwLowDateTime &&
+ ttTime.dwHighDateTime == ttCheck.dwHighDateTime;
+}
+
+
+SCODE t_create(void)
+{
+ IStorage *pstgRoot, *pstgChild, *pstgChild2;
+ IStream *pstm;
+ SCODE sc;
+
+ ILockBytes *pilb = new CFileILB("drt.dfl");
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ olHChk(StgCreateDocfileOnILockBytes(
+ pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstgRoot));
+
+ olHChk(pstgRoot->CreateStorage(STR("Child"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+
+ olHChk(pstgChild->CreateStorage(STR("Child2"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild2));
+
+ olHChk(pstgChild2->CreateStream(STR("Stream"), STMP(STGM_READWRITE), 0, 0,
+ &pstm));
+
+ pstm->Release();
+ olHChk(pstgChild2->Commit(0));
+ pstgChild2->Release();
+
+ olHChk(pstgChild->Commit(0));
+ pstgChild->Release();
+
+ pstgRoot->Release();
+ pilb->Release();
+
+ EH_Err:
+ return sc;
+}
+
+SCODE t_open(void)
+{
+ SCODE sc;
+ IStorage *pstgRoot, *pstgChild, *pstgChild2;
+ IStream *pstm;
+
+ ILockBytes *pilb = new CFileILB("drt.dfl");
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ olHChk(StgCreateDocfileOnILockBytes(pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstgRoot));
+
+ olHChk(pstgRoot->CreateStorage(STR("Child"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ olHChk(pstgChild->CreateStorage(STR("Child2"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild2));
+ olHChk(pstgChild2->CreateStream(STR("Stream"), STMP(STGM_READWRITE), 0, 0,
+ &pstm));
+ pstm->Release();
+ pstgChild2->Release();
+ pstgChild->Release();
+
+
+ olHChk(pstgRoot->Commit(0));
+ pstgRoot->Release();
+
+ olHChk(StgOpenStorageOnILockBytes(
+ pilb,
+ NULL,
+ ROOTP(STGM_READWRITE),
+ NULL,
+ 0,
+ &pstgRoot));
+
+ olHChk(pstgRoot->OpenStorage(
+ STR("Child"),
+ NULL,
+ STGP(STGM_READWRITE),
+ NULL,
+ 0,
+ &pstgChild));
+
+ olHChk(pstgChild->OpenStorage(
+ STR("Child2"),
+ NULL,
+ STGP(STGM_READWRITE),
+ NULL,
+ 0,
+ &pstgChild2));
+
+ olHChk(pstgChild2->OpenStream(
+ STR("Stream"),
+ NULL,
+ STMP(STGM_READWRITE),
+ 0,
+ &pstm));
+
+ pstm->Release();
+ pstgChild2->Release();
+ pstgChild->Release();
+ pstgRoot->Release();
+ pilb->Release();
+
+ EH_Err:
+ return sc;
+}
+
+
+SCODE t_addref(void)
+{
+ SCODE sc;
+ IStorage *pstg;
+ IStream *pstm;
+ ULONG ul;
+
+ ILockBytes *pilb = new CFileILB("drt.dfl");
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ olHChk(StgCreateDocfileOnILockBytes(pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstg));
+
+ olHChk(pstg->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+
+ if ((ul = pstm->AddRef()) != 2)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+ if ((ul = pstm->Release()) != 1)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+ pstm->Release();
+ if ((ul = pstg->AddRef()) != 2)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+ if ((ul = pstg->Release()) != 1)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+
+ pstg->Release();
+ pilb->Release();
+EH_Err:
+ return sc;
+}
+
+
+SCODE t_dmodify(void)
+{
+ SCODE sc;
+ IStorage *pstgRoot, *pstgChild, *pstgChild2;
+ IStream *pstm;
+
+ ILockBytes *pilb = new CFileILB("drt.dfl");
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ olHChk(StgCreateDocfileOnILockBytes(pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstgRoot));
+
+ olHChk(pstgRoot->CreateStorage(STR("Child"), STGP(STGM_READWRITE), 0,
+ 0, &pstgChild));
+ olHChk(pstgChild->CreateStorage(STR("Child2"), STGP(STGM_READWRITE), 0,
+ 0, &pstgChild2));
+ olHChk(pstgChild2->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+ pstm->Release();
+
+ // Test renaming a closed stream
+ olHChk(pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream")));
+
+ // Test destroying a stream
+ olHChk(pstgChild2->DestroyElement(STR("RenamedStream")));
+
+ // Test renaming an open stream
+ olHChk(pstgChild2->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+
+ olHChk(pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream")));
+
+ olHChk(pstgChild2->DestroyElement(STR("RenamedStream")));
+ pstm->Release();
+
+ pstgChild2->Release();
+
+ // Test renaming a storage
+ olHChk(pstgChild->RenameElement(STR("Child2"), STR("RenamedChild")));
+
+ olHChk(pstgChild->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+
+ pstm->Release();
+ olHChk(pstgChild->DestroyElement(STR("Stream")));
+
+ // Test SetElementTimes
+ FILETIME tm;
+ STATSTG stat;
+
+ tm.dwLowDateTime = 0x12345678;
+ tm.dwHighDateTime = 0x9abcdef0;
+
+ // Set when element not open
+ olHChk(pstgChild->SetElementTimes(STR("RenamedChild"), &tm, NULL, NULL));
+ olHChk(pstgChild->SetElementTimes(STR("RenamedChild"), NULL, &tm, NULL));
+ olHChk(pstgChild->SetElementTimes(STR("RenamedChild"), NULL, NULL, &tm));
+
+ olHChk(pstgChild->OpenStorage(
+ STR("RenamedChild"),
+ NULL,
+ STMP(STGM_READWRITE),
+ NULL,
+ 0,
+ &pstgChild2));
+ olHChk(pstgChild2->Stat(&stat, STATFLAG_NONAME));
+ if (!IsEqualTime(stat.ctime, tm) ||
+ !IsEqualTime(stat.mtime, tm))
+ error(EXIT_BADSC, "Times don't match those set by SetElementTimes\n");
+
+ // Test SetClass and SetStateBits
+ olHChk(pstgChild2->SetClass(IID_IStorage));
+ olHChk(pstgChild2->SetStateBits(0xff00ff00, 0xffffffff));
+ olHChk(pstgChild2->SetStateBits(0x00880088, 0xeeeeeeee));
+ olHChk(pstgChild2->Stat(&stat, STATFLAG_NONAME));
+ if (!IsEqualCLSID(stat.clsid, IID_IStorage))
+ error(EXIT_BADSC, "Class ID set improperly\n");
+ if (stat.grfStateBits != 0x11881188)
+ error(EXIT_BADSC, "State bits set improperly: has %lX vs. %lX\n",
+ stat.grfStateBits, 0x11881188);
+ pstgChild2->Release();
+
+ pstgChild->Release();
+
+ olHChk(pstgRoot->Revert());
+
+ olHChk(pstgRoot->Commit(0));
+
+ olHChk(pstgRoot->DestroyElement(STR("Child")));
+
+ olHChk(pstgRoot->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+
+ ULARGE_INTEGER ulSize;
+ ULISet32(ulSize, 65536);
+
+ olHChk(pstm->SetSize(ulSize));
+ pstm->Release();
+ olHChk(pstgRoot->DestroyElement(STR("Stream")));
+ olHChk(pstgRoot->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+
+ olHChk(pstm->SetSize(ulSize));
+ pstm->Release();
+
+ pstgRoot->Release();
+
+ pilb->Release();
+ pilb = new CFileILB(NULL);
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ olHChk(StgCreateDocfileOnILockBytes(pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstgRoot));
+
+ // removal cases
+ // 1) no right child
+
+ olHChk(pstgRoot->CreateStorage(STR("64"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+ olHChk(pstgRoot->CreateStorage(STR("32"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+
+ olHChk(pstgRoot->DestroyElement(STR("64")));
+
+ // 2) right child has no left child
+
+ olHChk(pstgRoot->CreateStorage(STR("64"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+ olHChk(pstgRoot->DestroyElement(STR("32")));
+
+ // 3) right child has left child
+
+ olHChk(pstgRoot->CreateStorage(STR("96"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+ olHChk(pstgRoot->CreateStorage(STR("80"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+
+ olHChk(pstgRoot->DestroyElement(STR("64")));
+
+ // 4) right child's left child has children
+
+ olHChk(pstgRoot->CreateStorage(STR("88"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+ olHChk(pstgRoot->CreateStorage(STR("84"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+ olHChk(pstgRoot->CreateStorage(STR("92"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+ olHChk(pstgRoot->DestroyElement(STR("80")));
+
+ pstgRoot->Release();
+
+ pilb->Release();
+EH_Err:
+ return sc;
+}
+
+
+SCODE t_stat(void)
+{
+ SCODE sc;
+ IStorage *pstgRoot, *pstgChild;
+ IStream *pstm;
+ STATSTG stat;
+
+ ILockBytes *pilb = new CFileILB("drt.dfl");
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ olHChk(StgCreateDocfileOnILockBytes(pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstgRoot));
+
+ olHChk(pstgRoot->CreateStorage(STR("Child"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ olHChk(pstgChild->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+
+ olHChk(pstm->Stat(&stat, 0));
+ delete [] stat.pwcsName;
+
+ olHChk(pstm->Stat(&stat, STATFLAG_NONAME));
+
+ pstm->Release();
+
+ olHChk(pstgChild->Stat(&stat, 0));
+ delete [] stat.pwcsName;
+
+ olHChk(pstgChild->Stat(&stat, STATFLAG_NONAME));
+
+ pstgChild->Release();
+
+ olHChk(pstgRoot->Stat(&stat, 0));
+
+ delete[] stat.pwcsName;
+
+ olHChk(pstgRoot->Stat(&stat, STATFLAG_NONAME));
+
+ pstgRoot->Release();
+ pilb->Release();
+EH_Err:
+ return sc;
+}
+
+static char NUMBERS[] = "12345678901234567890123456789012345678901234567890";
+
+SCODE t_stream(void)
+{
+ SCODE sc;
+ IStorage *pstg;
+ IStream *pstm, *pstmC;
+ char buf[sizeof(NUMBERS)*2];
+ ULONG cb;
+ ULARGE_INTEGER ulPos, ulSize;
+ LARGE_INTEGER lPos;
+
+ ILockBytes *pilb = new CFileILB("drt.dfl");
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ olHChk(StgCreateDocfileOnILockBytes(pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstg));
+
+ olHChk(pstg->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+ olHChk(pstm->Write(NUMBERS, sizeof(NUMBERS), &cb));
+ olHChk(pstm->Commit(0));
+ ULISet32(lPos, 0);
+
+ olHChk(pstm->Seek(lPos, STREAM_SEEK_SET, &ulPos));
+ if (ULIGetLow(ulPos) != 0)
+ error(EXIT_BADSC, "Incorrect seek, ptr is %lu\n", ULIGetLow(ulPos));
+ olHChk(pstm->Read(buf, sizeof(NUMBERS), &cb));
+ if (strcmp(buf, NUMBERS))
+ error(EXIT_BADSC, "Incorrect stream contents\n");
+
+ ULISet32(ulSize, sizeof(NUMBERS)/2);
+ olHChk(pstm->SetSize(ulSize));
+ olHChk(pstm->Seek(lPos, STREAM_SEEK_SET, NULL));
+
+ olHChk(pstm->Read(buf, sizeof(NUMBERS), &cb));
+
+ if (cb != sizeof(NUMBERS)/2)
+ error(EXIT_BADSC, "SetSize failed to size stream properly\n");
+ if (memcmp(buf, NUMBERS, sizeof(NUMBERS)/2))
+ error(EXIT_BADSC, "SetSize corrupted contents\n");
+ olHChk(pstm->Clone(&pstmC));
+ olHChk(pstm->Seek(lPos, STREAM_SEEK_SET, NULL));
+ olHChk(pstm->CopyTo(pstmC, ulSize, NULL, NULL));
+ olHChk(pstm->Seek(lPos, STREAM_SEEK_SET, NULL));
+
+ ULISet32(ulSize, sizeof(NUMBERS)&~1);
+ olHChk(pstm->CopyTo(pstmC, ulSize, NULL, NULL));
+ olHChk(pstm->Seek(lPos, STREAM_SEEK_SET, NULL));
+ olHChk(pstm->Read(buf, (sizeof(NUMBERS)&~1)*2, &cb));
+ if (memcmp(buf, NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+sizeof(NUMBERS)/2, NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+(sizeof(NUMBERS)&~1), NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+3*(sizeof(NUMBERS)/2), NUMBERS, sizeof(NUMBERS)/2))
+ error(EXIT_BADSC, "Stream contents incorrect\n");
+ pstmC->Release();
+ pstm->Release();
+ pstg->Release();
+ pilb->Release();
+EH_Err:
+ return sc;
+}
+
+
+void main()
+{
+ SCODE sc;
+
+ olChk(t_create());
+ olChk(t_open());
+ olChk(t_addref());
+ olChk(t_dmodify());
+ printf("Tests passed successfully.\n");
+ exit(0);
+EH_Err:
+ printf("Tests failed with error %lX\n",sc);
+ exit(EXIT_BADSC);
+}
diff --git a/private/ole32/stg/msf/segmsf.hxx b/private/ole32/stg/msf/segmsf.hxx
new file mode 100644
index 000000000..6d033185d
--- /dev/null
+++ b/private/ole32/stg/msf/segmsf.hxx
@@ -0,0 +1,234 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: SegMSF.HXX
+//
+// Contents: Segment defines for 16-bit builds
+//
+// History: 11-Jun-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#ifndef __SEGMSF_HXX__
+#define __SEGMSF_HXX__
+
+#include <segh.hxx>
+
+#ifdef CODESEGMENTS
+
+// Code segment defines go here
+
+// Common code
+
+#define SEG_CDirectStream_Release "Common0_TEXT" // Dirst_Release_TEXT // sstream
+#define SEG_CFat_1CFat "Common0_TEXT" // inline? // fat
+#define SEG_CMSFPageTable_1CMSFPageTable "Common0_TEXT" // page
+#define SEG_CMStream_1CMStream "Common0_TEXT" // mstream
+#define SEG_CPagedVector_1CPagedVector "Common0_TEXT" // vect
+#define SEG_CPubStream_1CPubStream "Common0_TEXT" // pbstream
+#define SEG_CPubStream_vRelease "Common0_TEXT" // Pubst_Release_TEXT // pbstream
+#define SEG_CStreamCache_1CStreamCache "Common0_TEXT" // inline? // cache
+#define SEG_DllReleaseMultiStream "Common0_TEXT" // inline? // msf
+#define SEG_ILBFlush "Common0_TEXT" // mstream
+#define SEG_CMStream_GetSect "Common0_TEXT" // mread
+
+#define SEG_CDeltaList_CDeltaList "Common1_TEXT" // dl
+#define SEG_CDIFat_CDIFat "Common1_TEXT" // difat
+#define SEG_CDIFat_CDIFat2 "Common1_TEXT" // difat
+#define SEG_CDIFat_Flush "Common1_TEXT" // difat
+#define SEG_CDIFat_GetFatSect "Common1_TEXT" // difat
+#define SEG_CDIFat_Init "Common1_TEXT" // difat
+#define SEG_CDIFat_InitNew "Common1_TEXT" // difat
+#define SEG_CDirectory_CDirectory "Common1_TEXT" // dir
+#define SEG_CDirectory_FindEntry "Common1_TEXT" // dirp
+#define SEG_CDirectory_GetDirEntry "Common1_TEXT" // // dir
+#define SEG_CDirectory_Init "Common1_TEXT" // dir
+#define SEG_CDirectory_NameCompare "Common1_TEXT" // dirp
+#define SEG_CDirectory_ReleaseEntry "Common1_TEXT" // dir
+#define SEG_CDirectStream_AddRef "Common1_TEXT" // // sstream
+#define SEG_CDirectStream_CDirectStream "Common1_TEXT" // sstream
+#define SEG_CDirectStream_GetSize "Common1_TEXT" // sstream
+#define SEG_CDirectStream_Init "Common1_TEXT" // sstream
+#define SEG_CDirectStream_InitSystem "Common1_TEXT" // sstream
+#define SEG_CDirectStream_ReadAt "Common1_TEXT" // Dirst_Read_TEXT // sstream
+#define SEG_CFat_CFat "Common1_TEXT" // fat
+#define SEG_CFat_CFat2 "Common1_TEXT" // fat
+#define SEG_CFat_Contig "Common1_TEXT" // fat
+#define SEG_CFat_FindLast "Common1_TEXT" // fat
+#define SEG_CFat_FindMaxSect "Common1_TEXT" // fat
+#define SEG_CFat_GetLength "Common1_TEXT" // fat
+#define SEG_CFat_GetNext "Common1_TEXT" // fat
+#define SEG_CFat_GetSect "Common1_TEXT" // fat
+#define SEG_CFat_Init "Common1_TEXT" // fat
+#define SEG_CFat_InitNew "Common1_TEXT" // fat
+#define SEG_CFat_SetNext "Common1_TEXT" // fat
+#define SEG_CFatSect_Init "Common1_TEXT" // fat
+
+#define SEG_CMSFHeader_CMSFHeader "Common2_TEXT" // header
+#define SEG_CMSFHeader_Validate "Common2_TEXT" // header
+#define SEG_CMSFPage_CMSFPage "Common2_TEXT" // page
+#define SEG_CMSFPageTable_CMSFPageTable "Common2_TEXT" // page
+#define SEG_CMSFPageTable_FindPage "Common2_TEXT" // page
+#define SEG_CMSFPageTable_FlushPage "Common2_TEXT" // page
+#define SEG_CMSFPageTable_GetFreePage "Common2_TEXT" // page
+#define SEG_CMSFPageTable_GetPage "Common2_TEXT" // page
+#define SEG_CMSFPageTable_Init "Common2_TEXT" // page
+#define SEG_CMStream_CMStream "Common2_TEXT" // Mstream_Init_TEXT // mstream
+#define SEG_CMStream_CMStream2 "Common2_TEXT" // mstream
+#define SEG_CMStream_Flush "Common2_TEXT" // // mstream
+#define SEG_CMStream_FlushHeader "Common2_TEXT" // mstream
+#define SEG_CMStream_GetStart "Common2_TEXT" // mread
+#define SEG_CMStream_Init "Common2_TEXT" // Mstream_Init_TEXT // mstream
+#define SEG_CMStream_InitCommon "Common2_TEXT" // mstream
+#define SEG_CMStream_InitNew "Common2_TEXT" // mstream
+#define SEG_CMStream_SetSize "Common2_TEXT" // Mstream_SetSize_TEXT // mread
+#define SEG_CPagedVector_Flush "Common2_TEXT" // vect
+#define SEG_CPagedVector_GetTable "Common2_TEXT" // vect
+#define SEG_CPagedVector_Init "Common2_TEXT" // vect
+#define SEG_CPubStream_CPubStream "Common2_TEXT" // pbstream
+#define SEG_CPubStream_Init "Common2_TEXT" // pbstream
+#define SEG_CStreamCache_CStreamCache "Common2_TEXT" // cache
+#define SEG_CStreamCache_Empty "Common2_TEXT" // cache
+#define SEG_CStreamCache_GetSect "Common2_TEXT" // cache
+#define SEG_CStreamCache_Init "Common2_TEXT" // cache
+#define SEG_CStreamCache_SetCache "Common2_TEXT" // cache
+#define SEG_CTransactedStream_AddRef "Common2_TEXT" // // tstream
+#define SEG_CTransactedStream_CTransactedStream "Common2_TEXT" // tstream
+#define SEG_CTransactedStream_Init "Common2_TEXT" // tstream
+#define SEG_CTransactedStream_SetInitialState "Common2_TEXT" // tstream
+#define SEG_DllGetScratchMultiStream "Common2_TEXT" // msf
+#define SEG_DllMultiStreamFromStream "Common2_TEXT" // msf
+#define SEG_FreeBuffer "Common2_TEXT" // mstream
+#define SEG_GetSafeBuffer "Common2_TEXT" // mstream
+
+#define SEG_CDirectory_GetFree "Common3_TEXT" // dir
+#define SEG_CDirectory_InitNew "BootSave_TEXT" // dir
+#define SEG_CDirEntry_Init "BootSave_TEXT" // dir
+#define SEG_CDirSect_Init "BootSave_TEXT" // dir
+
+#define SEG_CDeltaList_1CDeltaList "OpenSave0_TEXT" // inline? // dl
+#define SEG_CDeltaList_Empty "OpenSave0_TEXT" // dl
+#define SEG_CTransactedStream_1CTransactedStream "OpenSave0_TEXT" // tstream
+#define SEG_CTransactedStream_Release "OpenSave0_TEXT" // Trans_Release_TEXT // tstream
+
+#define SEG_CDirectory_SetTime "OpenSave1_TEXT" // dir
+#define SEG_CDirectStream_SetSize "OpenSave1_TEXT" // Dirst_SetSize_TEXT // sstream
+#define SEG_CDirectStream_WriteAt "OpenSave1_TEXT" // Dirst_Write_TEXT // sstream
+#define SEG_CFat_GetFree "OpenSave1_TEXT" // fat
+#define SEG_CMSFPageTable_FindSwapPage "OpenSave1_TEXT" // page
+#define SEG_CMStream_MWrite "OpenSave1_TEXT" // Mstream_MWrite_TEXT // mstream
+#define SEG_CPagedVector_SetDirty "OpenSave1_TEXT" // vect
+#define SEG_CStreamCache_GetESect "OpenSave1_TEXT" // cache
+#define SEG_CTransactedStream_ReadAt "OpenSave1_TEXT" // Transt_Read_TEXT // tstream
+
+#define SEG_CDeltaList_GetMap "Open_TEXT" // dl
+#define SEG_CDeltaList_Init "Open_TEXT" // dl
+#define SEG_CDeltaList_ReleaseBlock "Open_TEXT" // dl
+#define SEG_CDirectStream_BeginCommitFromChild "Open_TEXT" // Dirst_Commit_TEXT // sstream
+#define SEG_CDirectStream_EndCommitFromChild "Open_TEXT" // sstream
+#define SEG_CDirectStream_GetDeltaList "Open_TEXT" // sstream
+#define SEG_CMStream_BeginCopyOnWrite "Open_TEXT" // Mstream_Commit_TEXT // mstream
+#define SEG_CMStream_EndCopyOnWrite "Open_TEXT" // mstream
+#define SEG_CPubStream_Stat "Open_TEXT" // Stat_TEXT // pbstream
+#define SEG_CTransactedStream_BeginCommit "Open_TEXT" // tstream
+#define SEG_CTransactedStream_EndCommit "Open_TEXT" // tstream
+#define SEG_CTransactedStream_GetCommitInfo "Open_TEXT" // Transt_Overwrite_TEXT // tstream
+#define SEG_CTransactedStream_GetSize "Open_TEXT" // // tstream
+#define SEG_CTransactedStream_PartialWrite "Open_TEXT" // Transt_Write_TEXT // tstream
+#define SEG_CTransactedStream_WriteAt "Open_TEXT" // Transt_Write_TEXT // tstream
+#define SEG_CStreamCache_EmptyRegion "Open_TEXT" // cache
+
+#define SEG_CDirectory_CreateEntry "Save_TEXT" // Dir_Create_TEXT // dir
+#define SEG_CDirectory_InsertEntry "Save_TEXT" // dirp
+#define SEG_CDirectory_Resize "Save_TEXT" // dir
+#define SEG_CDirectory_RotateEntry "Save_TEXT" // dirp
+#define SEG_CDirectory_SetClassId "Save_TEXT" // dir
+#define SEG_CDirectory_SetColorBlack "Save_TEXT" // dirp
+#define SEG_CDirectory_SetSize "Save_TEXT" // dir
+#define SEG_CDirectory_SetStart "Save_TEXT" // dir
+#define SEG_CDirectory_SplitEntry "Save_TEXT" // dirp
+#define SEG_CFat_Extend "Save_TEXT" // fat
+#define SEG_CFat_GetESect "Save_TEXT" // fat
+#define SEG_CFat_Resize "Save_TEXT" // fat
+#define SEG_CMStream_GetESect "Save_TEXT" // mread
+#define SEG_CMStream_SecureSect "Save_TEXT" // mstream
+#define SEG_CMStream_SetMiniSize "Save_TEXT" // // mread
+#define SEG_CPagedVector_Resize "Save_TEXT" // vect
+#define SEG_CStreamCache_ChangeSize "Save_TEXT" // cache
+
+#define SEG_CFat_InitCopy "Commit_TEXT" // fat
+#define SEG_CTransactedStream_SetBase "Commit_TEXT" // Trans_Commit_TEXT // tstream
+#define SEG_CMSFPageTable_CopyPage "Commit_TEXT" // page
+#define SEG_CDIFat_Empty "Commit_TEXT" // difat
+#define SEG_CDirectory_Empty "Commit_TEXT" // dir
+#define SEG_CFat_Empty "Commit_TEXT" // fat
+#define SEG_CMStream_Empty "Commit_TEXT" // Mstream_Shutdown_TEXT // mstream
+#define SEG_CPagedVector_Empty "Commit_TEXT" // vect
+#define SEG_CDIFat_Fixup "Commit_TEXT" // difat
+#define SEG_CMSFPageTable_FreePages "Commit_TEXT" // page
+#define SEG_CDirectory_InitCopy "Commit_TEXT" // dir
+#define SEG_CMStream_InitCopy "Commit_TEXT" // mstream
+#define SEG_CPagedVector_InitCopy "Commit_TEXT" // vect
+#define SEG_CDIFat_Lookup "Commit_TEXT" // difat
+#define SEG_CDIFat_Remap "Commit_TEXT" // difat
+#define SEG_CDIFat_RemapSelf "Commit_TEXT" // difat
+#define SEG_CFat_Remap "Commit_TEXT" // fat
+#define SEG_CDIFat_SetFatSect "Commit_TEXT" // difat
+#define SEG_CDirectory_SetUserFlags "Commit_TEXT" // dir
+
+// Transacted code
+
+#define SEG_CDirSect_InitCopy "TransM_TEXT" // dir
+#define SEG_SDeltaBlock_SDeltaBlock "TransM_TEXT" // dl
+#define SEG_CDeltaList_GetNewDeltaArray "TransM_TEXT" // dl
+#define SEG_CDeltaList_InitResize "TransM_TEXT" // dl
+#define SEG_CDeltaList_InitStreamBlock "TransM_TEXT" // dl
+#define SEG_CDeltaList_BeginCommit "TransM_TEXT" // dl
+#define SEG_CDeltaList_EndCommit "TransM_TEXT" // dl
+#define SEG_CDeltaList_DumpList "TransM_TEXT" // dl
+#define SEG_CDeltaList_FindOffset "TransM_TEXT" // dl
+#define SEG_CDeltaList_ReadMap "TransM_TEXT" // dl
+#define SEG_CDeltaList_WriteMap "TransM_TEXT" // dl
+#define SEG_CDeltaList_FreeStream "TransM_TEXT" // dl
+#define SEG_CDeltaList_IsOwned "TransM_TEXT" // dl
+#define SEG_CTransactedStream_GetDeltaList "TransM_TEXT" // tstream
+#define SEG_CFatSect_InitCopy "TransM_TEXT" // fat
+#define SEG_DllSetCommitSig "TransM_TEXT" // msf
+#define SEG_DllGetCommitSig "TransM_TEXT" // msf
+#define SEG_GetBuffer "TransM_TEXT" // mstream
+#define SEG_CTransactedStream_SetSize "TransM_TEXT" // Transt_SetSize_TEXT // tstream
+#define SEG_CTransactedStream_Revert "TransM_TEXT" // Trans_Revert_TEXT // tstream
+#define SEG_CPubStream_RevertFromAbove "TransM_TEXT" // Pubdf_Revert_TEXT // pbstream
+#define SEG_CTransactedStream_BeginCommitFromChild "TransM_TEXT" // Transt_Commit_TEXT // tstream
+#define SEG_CTransactedStream_EndCommitFromChild "TransM_TEXT" // tstream
+
+#define SEG_CDIFat_GetSect "UnassignedM_TEXT" // difat
+#define SEG_CDIFat_InitConvert "RareM_TEXT" // difat
+#define SEG_CDIFat_Resize "RareM_TEXT" // difat
+#define SEG_CDirEntry_CDirEntry "UnassignedM_TEXT" // inline? // dir
+#define SEG_CDirectory_DestroyAllChildren "UnassignedM_TEXT" // Dir_Destroy_TEXT // dir
+#define SEG_CDirectory_DestroyChild "UnassignedM_TEXT" // dir
+#define SEG_CDirectory_FindGreaterEntry "UnassignedM_TEXT" // dir
+#define SEG_CDirectory_RenameEntry "UnassignedM_TEXT" // Dir_Rename_TEXT // dir
+#define SEG_CDirectory_SetChild "UnassignedM_TEXT" // dir (obsolete)
+#define SEG_CDirectory_SetFlags "UnassignedM_TEXT" // dir
+#define SEG_CDirectory_StatEntry "UnassignedM_TEXT" // Stat_TEXT // dir
+#define SEG_CFat_CountFree "UnassignedM_TEXT" // fat
+#define SEG_CFat_InitConvert "RareM_TEXT" // fat
+#define SEG_CFat_SetChainLength "UnassignedM_TEXT" // fat
+#define SEG_CMSFPageTable_Flush "UnassignedM_TEXT" // page
+#define SEG_CMSFPageTable_GetNewPage "UnassignedM_TEXT" // page
+#define SEG_CMSFPageTable_ReleasePage "UnassignedM_TEXT" // page
+#define SEG_CMStream_ConvertILB "UnassignedM_TEXT" // mstream
+#define SEG_CMStream_CopySect "UnassignedM_TEXT" // // mstream
+#define SEG_CMStream_InitConvert "RareM_TEXT" // mstream
+#define SEG_CMStream_KillStream "UnassignedM_TEXT" // dir
+#define SEG_CPagedVector_GetNewPageArray "UnassignedM_TEXT" // vect
+#define SEG_CPagedVector_GetNewVectBits "UnassignedM_TEXT" // vect
+#define SEG_CPubStream_Commit "UnassignedM_TEXT" // Pubdf_Commit_TEXT // pbstream
+#define SEG_DllIsMultiStream "RareM_TEXT" // msf
+
+#endif // CODESEGMENTS
+#endif // __SEGMSF_HXX__
diff --git a/private/ole32/stg/msf/sstream.cxx b/private/ole32/stg/msf/sstream.cxx
new file mode 100644
index 000000000..94dca55ae
--- /dev/null
+++ b/private/ole32/stg/msf/sstream.cxx
@@ -0,0 +1,1320 @@
+//+-------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: sstream.cxx
+//
+// Contents: Stream operations for Mstream project
+//
+// Classes: None. (defined in sstream.hxx)
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 24-Apr-92 AlexT Small object support
+//
+//--------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+#pragma hdrstop
+
+#include <dirfunc.hxx>
+#include <sstream.hxx>
+#include <dl.hxx>
+#include <tstream.hxx>
+#include <time.h>
+#include <mread.hxx>
+
+#define DEB_STREAM (DEB_ITRACE | 0x00020000)
+
+
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDirectStream::CDirectStream, public
+//
+// Synopsis: Empty object constructor
+//
+// Arguments: [dl] - LUID
+//
+// History: 25-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectStream_CDirectStream)
+#endif
+
+CDirectStream::CDirectStream(DFLUID dl)
+: PSStream(dl)
+{
+ _pdlHolder = NULL;
+ _cReferences = 0;
+#ifdef SECURE_STREAMS
+ _ulSize = 0;
+ _ulHighWater = 0;
+#endif
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectStream::~CDirectStream, public
+//
+// Synopsis: CDirectStream destructor
+//
+// History: 18-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CDirectStream::~CDirectStream()
+{
+ msfAssert(_cReferences == 0);
+#ifdef SECURE_STREAMS
+ if (_ulSize > _ulHighWater)
+ {
+ ClearSects(_ulHighWater, _ulSize);
+ }
+#endif
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDirectStream::InitSystem, public
+//
+// Synopsis: Initializes special system streams like the ministream
+//
+// Arguments: [pms] - Multistream
+// [sid] - SID
+// [cbSize] - size
+//
+// History: 25-Aug-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectStream_InitSystem)
+#endif
+
+void CDirectStream::InitSystem(CMStream *pms,
+ SID sid,
+ ULONG cbSize)
+{
+ _stmh.Init(pms, sid);
+ _ulSize = _ulOldSize = cbSize;
+
+ _stmc.Init(pms, sid, this);
+
+#ifdef SECURE_STREAMS
+#ifndef SECURE_BUFFER
+ //If SECURE_BUFFER is defined, we've already zeroed this in the
+ // multistream.
+ memset(s_bufSecure, SECURECHAR, MINISTREAMSIZE);
+#endif
+ _ulHighWater = cbSize;
+#endif
+
+ AddRef();
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectStream::Init, public
+//
+// Synopsis: CDirectStream constructor
+//
+// Arguments: [pstgh] - Parent
+// [pdfn] - Name of entry
+// [fCreate] - Create or get
+//
+// Returns: Appropriate status code
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 02-Jan-92 PhilipLa Converted to use handle.
+// 25-Aug-92 DrewB Converted to use StgHandle
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectStream_Init)
+#endif
+
+SCODE CDirectStream::Init(
+ CStgHandle *pstgh,
+ CDfName const *pdfn,
+ BOOL const fCreate)
+{
+ SCODE sc;
+
+ if (fCreate)
+ sc = pstgh->CreateEntry(pdfn, STGTY_STREAM, &_stmh);
+ else
+ sc = pstgh->GetEntry(pdfn, STGTY_STREAM, &_stmh);
+
+ if (SUCCEEDED(sc))
+ {
+ sc = _stmh.GetSize(&_ulSize);
+ _ulOldSize = _ulSize;
+#ifdef SECURE_STREAMS
+ _ulHighWater = (fCreate) ? 0 : _ulSize;
+#endif
+
+#if DBG == 1
+ if (SUCCEEDED(sc))
+ {
+ //Make sure that the stream is sane.
+ SCODE sc2;
+ CFat *pfat;
+ ULONG cbSector;
+ ULONG cSect;
+ ULONG cSectReal;
+ SECT sectStart;
+
+ if (_ulSize < MINISTREAMSIZE)
+ {
+ cbSector = MINISECTORSIZE;
+ pfat = _stmh.GetMS()->GetMiniFat();
+ }
+ else
+ {
+ cbSector = _stmh.GetMS()->GetSectorSize();
+ pfat = _stmh.GetMS()->GetFat();
+ }
+
+ cSect = (_ulSize + cbSector - 1) / cbSector;
+ sc2 = _stmh.GetMS()->GetDir()->GetStart(
+ _stmh.GetSid(),
+ &sectStart);
+ if (SUCCEEDED(sc2))
+ {
+ sc2 = pfat->GetLength(sectStart, &cSectReal);
+ if (SUCCEEDED(sc2))
+ {
+ msfAssert((cSect == cSectReal) &&
+ aMsg("Chain length incorrect at init."));
+ }
+ }
+ }
+#endif
+
+ if (SUCCEEDED(sc))
+ AddRef();
+ _stmc.Init(_stmh.GetMS(), _stmh.GetSid(), this);
+ }
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectStream::ReadAt, public
+//
+// Synposis: Reads binary data from a linear single stream
+//
+// Arguments: [ulOffset] -- Position to be read from
+//
+// [pBuffer] -- Pointer to the area into which the data
+// will be read.
+// [ulCount] -- Indicates the number of bytes to be read
+// [pulRetval] -- Area into which return value will be stored
+//
+// Returns: Error Code of parent MStream call
+//
+// Algorithm: Calculate start and end sectors and offsets, then
+// pass call up to parent MStream.
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 16-Aug-91 PhilipLa Converted to use multi-sect read
+// 23-Aug-91 PhilipLa Brought into compliance with protocol
+// 11-Sep-91 PhilipLa Moved most functionality up
+// to MStream level.
+// 24-Apr-92 AlexT Move everything to MStream::MRead
+// 09-Jun-92 PhilipLa Added fUnconverted support
+//
+// Notes: [pBuffer] may be unsafe memory
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectStream_ReadAt) // Dirst_Read_TEXT
+#endif
+
+
+SCODE CDirectStream::ReadAt(
+ ULONG ulOffset,
+ VOID HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval)
+{
+ msfDebugOut((DEB_ITRACE,"In CDirectStream::ReadAt(%lu,%p,%lu)\n",
+ ulOffset,pBuffer,ulCount));
+
+ SCODE sc = S_OK;
+
+ CMStream *pms = _stmh.GetMS();
+
+ *pulRetval = 0;
+
+ // Check for offset beyond stream size and zero count
+
+ if ((ulOffset >= _ulSize) || (0 == ulCount))
+ {
+ return S_OK;
+ }
+
+ if (ulOffset + ulCount > _ulSize)
+ {
+ msfDebugOut((DEB_ITRACE,"Truncating Read: ulOffset = %lu, ulCount = %lu, _ulSize = %lu\n",
+ ulOffset,ulCount,_ulSize));
+ ulCount = _ulSize - ulOffset;
+ }
+
+#ifdef DELAYCONVERT
+ if (pms->IsUnconverted())
+ {
+ ULARGE_INTEGER ulTmp;
+ ULISet32(ulTmp, ulOffset);
+ return DfGetScode(pms->GetILB()->ReadAt(ulTmp, pBuffer, ulCount,
+ pulRetval));
+ }
+#else
+ msfAssert(!pms->IsUnconverted());
+#endif
+
+ // Stream is stored in ministream if size < MINISTREAMSIZE
+ // and this is not a scratch stream.
+
+#ifdef SECURE_STREAMS
+ if (ulOffset + ulCount > _ulHighWater)
+ {
+ if (ulOffset > _ulHighWater)
+ {
+ //Zero the whole buffer and return.
+ memset(pBuffer, SECURECHAR, ulCount);
+ *pulRetval = ulCount;
+ return S_OK;
+ }
+
+ //Need to read into part of the buffer, then zero fill the
+ // rest.
+ if (FAILED(sc = ReadAt(ulOffset,
+ pBuffer,
+ _ulHighWater - ulOffset,
+ pulRetval)) ||
+ (*pulRetval != _ulHighWater - ulOffset))
+ {
+ return sc;
+ }
+ memset((BYTE *)pBuffer + *pulRetval,
+ SECURECHAR,
+ ulCount - (_ulHighWater - ulOffset));
+
+ *pulRetval = ulCount;
+ return S_OK;
+ }
+#endif
+
+
+ SID sid = _stmh.GetSid();
+ CFat *pfat = pms->GetFat();
+ USHORT cbSector = pms->GetSectorSize();
+ USHORT uShift = pms->GetSectorShift();
+ USHORT uMask = pms->GetSectorMask();
+
+
+
+ if ((_ulSize < MINISTREAMSIZE) &&
+ (!pms->IsScratch()) &&
+ (sid != SIDMINISTREAM))
+ {
+ msfAssert(sid <= MAXREGSID);
+
+ // This stream is stored in the ministream
+
+ cbSector = MINISECTORSIZE;
+ uShift = MINISECTORSHIFT;
+ uMask = cbSector - 1;
+ pfat = pms->GetMiniFat();
+ }
+
+ SECT start = (SECT)(ulOffset >> uShift);
+ OFFSET oStart = (OFFSET)(ulOffset & uMask);
+
+ SECT end = (SECT)((ulOffset + ulCount - 1) >> uShift);
+ OFFSET oEnd = (OFFSET)((ulOffset + ulCount - 1) & uMask);
+
+ ULONG total = 0;
+
+ ULONG cSect = end - start + 1;
+
+ USHORT offset;
+ offset = oStart;
+
+ while (TRUE)
+ {
+ ULONG cSeg;
+ SSegment segtab[CSEG + 1];
+
+ msfChk(_stmc.Contig(start,
+ FALSE,
+ (SSegment STACKBASED *) segtab,
+ cSect,
+ &cSeg));
+ msfAssert(cSeg <= CSEG);
+
+ USHORT oend = cbSector - 1;
+ for (USHORT iseg = 0; iseg < cSeg;)
+ {
+ msfDebugOut((DEB_ITRACE,"Segment: (%lu,%lu)\n",segtab[iseg].sectStart,segtab[iseg].cSect));
+ SECT sectStart = segtab[iseg].sectStart;
+ ULONG i = segtab[iseg].cSect;
+ if (i > cSect)
+ i = cSect;
+
+ cSect -= i;
+ start += i;
+
+ iseg++;
+ if (cSect == 0)
+ oend = oEnd;
+
+ ULONG ulSize = ((i - 1) << uShift) - offset + oend + 1;
+
+ ULONG bytecount;
+ SCODE sc;
+
+ if (pms->GetMiniFat() == pfat)
+ {
+ sc = pms->GetMiniStream()->CDirectStream::ReadAt(
+ (sectStart << uShift) + offset,
+ pBuffer, ulSize,
+ (ULONG STACKBASED *)&bytecount);
+ }
+ else
+ {
+ ULARGE_INTEGER ulOffset;
+ ULISet32(ulOffset, ConvertSectOffset(sectStart,offset,uShift));
+ sc = DfGetScode(pms->GetILB()->ReadAt(ulOffset,
+ (BYTE *)pBuffer, ulSize,
+ &bytecount));
+ }
+
+ total += bytecount;
+ if ((0 == cSect) || (FAILED(sc)))
+ {
+ *pulRetval = total;
+ msfDebugOut((DEB_ITRACE,
+ "Leaving CDirectStream::ReadAt()=>%lu, ret is %lu\n",
+ sc,*pulRetval));
+ return sc;
+ }
+
+ pBuffer = (BYTE HUGEP *)pBuffer + bytecount;
+ offset = 0;
+ }
+ }
+
+ msfDebugOut((DEB_ERROR,"In CDirectStream::ReadAt - reached end of function\n"));
+Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectStream::Write, public
+//
+// Synposis: Writes binary data from a linear single stream
+//
+// Effects: Modifies _ulSeekPos. May cause modification in parent
+// MStream.
+//
+// Arguments: [pBuffer] -- Pointer to the area from which the data
+// will be written.
+// [ulCount] -- Indicates the number of bytes to be written
+// [pulRetval] -- Pointer to area in which number of bytes
+// will be returned
+//
+// Returns: Error code of MStream call.
+//
+// Algorithm: Calculate sector and offset for beginning and end of
+// write, then pass call up to MStream.
+//
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 16-Aug-91 PhilipLa Converted to use multi-sect write
+// 23-Aug-91 PhilipLa Brought into compliance with protocol
+// 11-Sep-91 PhilipLa Moved most functionality up
+// to MStream level.
+//
+// Notes: [pBuffer] may be unsafe memory
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectStream_WriteAt) // Dirst_Write_TEXT
+#endif
+
+SCODE CDirectStream::WriteAt(
+ ULONG ulOffset,
+ VOID const HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval)
+{
+ msfDebugOut((DEB_ITRACE,"In CDirectStream::WriteAt(%lu,%p,%lu)\n",ulOffset,pBuffer,ulCount));
+
+ *pulRetval = 0;
+
+ if (0 == ulCount)
+ return S_OK;
+
+ SCODE sc;
+
+ CMStream *pms;
+ pms = _stmh.GetMS();
+ msfAssert(pms != NULL);
+
+ if (ulOffset + ulCount > _ulSize)
+ {
+ if (_ulSize > MINISTREAMSIZE)
+ {
+ }
+ else
+ {
+ msfChk(SetSize(ulOffset + ulCount));
+ }
+ }
+
+ // This should be an inline call to MWrite
+
+#ifdef SECURE_STREAMS
+ if (ulOffset > _ulHighWater)
+ {
+ ClearSects(_ulHighWater, ulOffset);
+ }
+#endif
+
+ msfChk(pms->MWrite(
+ _stmh.GetSid(),
+ (_ulSize < MINISTREAMSIZE),
+ ulOffset,
+ pBuffer,
+ ulCount,
+ &_stmc,
+ pulRetval));
+
+ msfDebugOut((DEB_ITRACE,"Leaving CDirectStream::WriteAt()==>%lu, ret is %lu\n",sc,*pulRetval));
+
+Err:
+#ifdef SECURE_STREAMS
+ if ((*pulRetval > 0 ) &&
+ (ulOffset + *pulRetval > _ulHighWater))
+ {
+ _ulHighWater = ulOffset + *pulRetval;
+ }
+#endif
+
+ if (*pulRetval > 0 &&
+ ulOffset + *pulRetval > _ulSize)
+ {
+ SCODE scSet;
+
+ _ulSize = ulOffset + *pulRetval;
+
+ scSet = pms->GetDir()->SetSize(_stmh.GetSid(), _ulSize);
+ if (SUCCEEDED(sc) && FAILED(scSet))
+ {
+ sc = scSet;
+ }
+ }
+#ifdef SECURE_STREAMS
+ msfAssert(_ulHighWater <= _ulSize);
+#endif
+
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectStream::SetSize, public
+//
+// Synposis: Set the size of a linear stream
+//
+// Effects: Modifies _ulSize. May cause change in parent MStream.
+//
+// Arguments: [ulNewSize] -- New size for stream
+//
+// Returns: Error code returned by MStream call.
+//
+// Algorithm: Pass call up to parent.
+//
+// History: 29-Jul-91 PhilipLa Created.
+// 14-May-92 AlexT Add small object support
+//
+// Notes: When changing the size of a stream, we need to be concerned
+// with the cases where each stream is either zero length,
+// stored in the ministream, or stored in a regular stream. The following
+// grid shows the actions that we must perform in each case:
+//
+// New Sector Count (Cn)
+//
+// 0 S L
+// O ------------------------------------------------
+// l | same size | allocate Cn | allocate Cn
+// d 0 | (fast out) | small sectors | large sectors
+// ------------------------------------------------
+// S | small | Co > Cn: | cbCopy = cbOld
+// e S | setchain(Cn) | small | large allocate Cn
+// c | | setchain(Cn)| copy bytes
+// t | | Cn > Co: | small setchain(0)
+// o | | extend small | copy data
+// r ------------------------------------------------
+// L | large | cbCopy = cbNew| Co > Cn:
+// C | setchain(Cn) | small | large setchain(Cn)
+// o | | allocate Cn | Cn > Co:
+// u | | copy bytes | extend large
+// n | | large |
+// t | | setchain(0) |
+// | | copy data |
+// (Co) ------------------------------------------------
+//
+// where S indicates small sectors, L indicates large sectors, and Cx
+// represents count of sectors. For example, the middle box represents
+// doing a setsize on a stream which is currently stored in a small
+// stream in Co small sectors and which will end up in a large stream
+// with Cn sectors.
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectStream_SetSize) // Dirst_SetSize_TEXT
+#endif
+
+SCODE CDirectStream::SetSize(ULONG cbNewSize)
+{
+ msfDebugOut((DEB_ITRACE,"In CDirectStream::SetSize(%lu)\n",cbNewSize));
+
+ SCODE sc = S_OK;
+ BYTE *pBuf = NULL;
+ SID sid = _stmh.GetSid();
+ CMStream *pms = _stmh.GetMS();
+ msfAssert(sid <= MAXREGSID);
+ CDirectory *pdir = pms->GetDir();
+
+ if (_ulSize == cbNewSize)
+ {
+ return S_OK;
+ }
+
+#ifdef SECURE_STREAMS
+ msfAssert(_ulHighWater <= _ulSize);
+#endif
+
+ USHORT cbpsOld = pms->GetSectorSize();
+ // Count of Bytes Per Sector
+ USHORT cbpsNew = cbpsOld;
+ CFat *pfatOld = pms->GetFat();
+ CFat *pfatNew = pfatOld;
+
+ if ((!pms->IsScratch()) && (SIDMINISTREAM != sid))
+ {
+ // This is not a scratch DocFile, nor is this stream the ministream;
+ // check if this stream is and/or will be stored in the ministream.
+
+ if (cbNewSize < MINISTREAMSIZE)
+ {
+ cbpsNew = MINISECTORSIZE;
+ pfatNew = pms->GetMiniFat();
+ }
+
+ if (_ulSize < MINISTREAMSIZE)
+ {
+ cbpsOld = MINISECTORSIZE;
+ pfatOld = pms->GetMiniFat();
+ }
+ }
+
+ ULONG csectOld = (ULONG)(_ulSize + cbpsOld - 1) / (ULONG) cbpsOld;
+ ULONG csectNew = (ULONG)(cbNewSize + cbpsNew - 1) / (ULONG) cbpsNew;
+
+ msfAssert(sid <= MAXREGSID);
+ SECT sectstart, sectOldStart;
+ msfChk(pdir->GetStart(sid, &sectstart));
+
+ //Save start sector so we can free it later.
+ sectOldStart = sectstart;
+
+ msfDebugOut((DEB_ITRACE,"pdbOld size is %lu\n\tSid is %lu\n\tStart is %lu\n",
+ _ulSize,sid,sectstart));
+ msfDebugOut((DEB_ITRACE,"CMStream::SetSize() needs %lu %u byte sectors\n",
+ csectNew, cbpsNew));
+ msfDebugOut((DEB_ITRACE,"SetSize() currently has %lu %u byte sectors\n",
+ csectOld, cbpsOld));
+
+ USHORT cbCopy;
+ cbCopy = 0;
+ if (cbpsOld != cbpsNew)
+ {
+ // Sector sizes are different, so we'll copy the data
+ msfAssert((cbNewSize > _ulSize ? _ulSize : cbNewSize) < 0x10000);
+ cbCopy =(USHORT)(cbNewSize > _ulSize ? _ulSize : cbNewSize);
+ }
+
+
+ if (cbCopy > 0)
+ {
+ msfDebugOut((DEB_ITRACE,"Copying between fat and minifat\n"));
+ GetSafeBuffer(cbCopy, cbCopy, &pBuf, &cbCopy);
+ msfAssert((pBuf != NULL) && aMsg("Couldn't get scratch buffer"));
+
+ ULONG ulRetVal;
+ sc = ReadAt(0, pBuf, cbCopy, (ULONG STACKBASED *)&ulRetVal);
+#ifdef SECURE_STREAMS
+ //Part of the buffer may have gunk in it, so clear it out.
+ if (_ulHighWater < cbCopy)
+ {
+ memset(pBuf + _ulHighWater, SECURECHAR, cbCopy - _ulHighWater);
+ }
+#endif
+
+ if ((FAILED(sc)) ||
+ ((ulRetVal != cbCopy) ? (sc = STG_E_UNKNOWN) : 0))
+ {
+ msfErr(Err, sc);
+ }
+#ifdef SECURE_STREAMS
+ ClearSects(_ulHighWater, _ulSize);
+ _ulHighWater = cbNewSize;
+#endif
+
+ //The cache is no longer valid, so empty it.
+ _stmc.Empty();
+
+ msfChk(_stmc.Allocate(pfatNew, csectNew, &sectstart));
+ }
+ else
+ {
+ SECT dummy;
+
+ if ((csectOld > csectNew))
+ {
+#ifdef SECURE_STREAMS
+ ClearSects(_ulHighWater, _ulSize);
+ _ulHighWater = cbNewSize;
+#endif
+ if (0 == csectNew)
+ {
+ //Note: We need to set the start sect in the directory
+ // first in case the SetChainLength call fails part way
+ // through, which would leave this directory entry pointing
+ // to a FREESECT.
+ SECT sectOldStart = sectstart;
+ msfChk(pdir->SetStart(sid, ENDOFCHAIN));
+ sectstart = ENDOFCHAIN;
+ msfChk(pfatOld->SetChainLength(sectOldStart, 0));
+ }
+ else
+ {
+ msfChk(pfatOld->SetChainLength(sectstart, csectNew));
+ }
+
+ //If this turns out to be a common case, we can
+ // sometimes keep the cache valid here.
+ _stmc.Empty();
+ }
+ else if (0 == csectOld)
+ {
+ msfChk(_stmc.Allocate(pfatNew, csectNew, &sectstart));
+ }
+ else if (csectNew > csectOld)
+ {
+ ULONG start = csectNew - 1;
+ msfChk(_stmc.GetESect(start, &dummy));
+ }
+ }
+
+
+ // Resize the ministream, if necessary
+ if (((MINISECTORSIZE == cbpsOld) && (csectOld > 0)) ||
+ ((MINISECTORSIZE == cbpsNew) && (csectNew > 0)))
+ {
+ msfChk(pms->SetMiniSize());
+ }
+
+ msfChk(pms->SetSize());
+
+ //If we fail on either of these operations and cbCopy != 0,
+ // we will have data loss. Ick.
+
+ // Optimization - we only set the start sector if it has changed.
+
+ if (sectstart != sectOldStart)
+ {
+ msfChk(pdir->SetStart(sid, sectstart));
+ }
+
+ //If we fail here, we're screwed.
+ msfChk(pdir->SetSize(sid, cbNewSize));
+
+ _ulSize = cbNewSize;
+#ifdef SECURE_STREAMS
+ if (_ulHighWater > _ulSize)
+ {
+ _ulHighWater = _ulSize;
+ }
+#endif
+
+ if (cbCopy > 0)
+ {
+ // now copy the data
+ ULONG ulRetVal;
+
+ msfAssert(cbCopy <= _ulSize);
+ msfChk(WriteAt(0, pBuf, cbCopy, (ULONG STACKBASED *)&ulRetVal));
+
+ if (ulRetVal != cbCopy)
+ {
+ msfErr(Err, STG_E_UNKNOWN);
+ }
+
+ msfChk(pfatOld->SetChainLength(sectOldStart, 0));
+ msfChk(pms->SetMiniSize());
+ msfChk(pms->SetSize());
+ }
+
+#ifdef SECURE
+ if (((csectNew > csectOld) || (cbCopy > 0)) &&
+ ((cbNewSize & (cbpsNew - 1)) != 0))
+ {
+ SECT sectLast;
+ msfChk(_stmc.GetSect(csectNew - 1, &sectLast));
+
+ msfVerify(SUCCEEDED(pms->SecureSect(
+ sectLast,
+ cbNewSize,
+ (cbNewSize < MINISTREAMSIZE) && (sid != SIDMINISTREAM))));
+ }
+#endif //SECURE
+#ifdef SECURE_STREAMS
+ msfAssert(_ulHighWater <= _ulSize);
+#endif
+Err:
+#ifdef SECURE_STREAMS
+ if (_ulHighWater > _ulSize)
+ {
+ _ulHighWater = _ulSize;
+ }
+#endif
+ // Optimization - avoid calling FreeBuffer (which will end up calling
+ // out to CompObj.DLL) when pBuf is NULL (common case).
+ if (pBuf != NULL)
+ FreeBuffer(pBuf);
+
+ if (FAILED(sc))
+ _stmc.Empty();
+
+
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectStream::BeginCommitFromChild, public
+//
+// Synopsis: Begin a commit from a child stream
+//
+// Arguments: [ulSize] -- Size of child stream
+// [pDelta] -- Pointer to delta list
+// [pstChild] - Child
+//
+// Returns: S_OK if call completed successfully.
+//
+// Algorithm: *Finish This*
+//
+// History: 22-Jan-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectStream_BeginCommitFromChild) // Dirst_Commit_TEXT
+#endif
+
+SCODE CDirectStream::BeginCommitFromChild(
+ ULONG ulSize,
+ CDeltaList *pDelta,
+ CTransactedStream *pstChild)
+{
+ msfDebugOut((DEB_ITRACE,"In CDirectStream::BeginCommitFromChild:%p("
+ "%lu, %p, %p)\n", this, ulSize, pDelta, pstChild));
+
+// msfDebugOut((DEB_ITRACE,"MultiStrean is %p\nStream name is: %ws\n",_stmh.GetMS(),((_stmh.GetMS()))->GetName(_stmh.GetSid())));
+
+ SCODE sc = S_OK;
+ ULONG temp;
+ BYTE *pb = NULL;
+
+ _pdlHolder = P_TO_BP(CBasedDeltaListPtr, pDelta);
+ _ulOldSize = _ulSize;
+
+ // Copy-on-write will back out these changes if we fail
+
+#ifdef USE_NOSCRATCH
+ //For no-scratch mode, we commit very differently than we do regularly,
+ // unless this commit is somehow involving the minifat.
+
+ if ((pDelta->IsNoScratch()) &&
+ (ulSize >= MINISTREAMSIZE) &&
+ ((_ulSize >= MINISTREAMSIZE) || (_ulSize == 0)) &&
+ (!pDelta->IsEmpty()))
+ {
+ USHORT cbSector = pDelta->GetDataSectorSize();
+ SECT sectEnd = (ulSize + cbSector - 1) / cbSector;
+ SECT sectLast = ENDOFCHAIN;
+
+ //We update our size and directory first so the stream cache
+ // code knows which fat to get to.
+ _ulSize = ulSize;
+ msfChk(_stmh.GetMS()->GetDir()->SetSize(_stmh.GetSid(), ulSize));
+
+ if (_ulOldSize > _ulSize)
+ {
+ //We need to truncate the chain.
+ SECT sectStart;
+ _stmh.GetMS()->GetDir()->GetStart(_stmh.GetSid(), &sectStart);
+ _stmh.GetMS()->GetFat()->SetChainLength(sectStart, sectEnd);
+ _stmc.Empty();
+ }
+
+ for (ULONG i = 0; i < sectEnd; i++)
+ {
+ SECT sectDirty;
+ SECT sectOld;
+ SECT sectNext;
+
+ //For each sector, chain the old sector with the
+ //existing new one.
+ msfChk(pDelta->GetMap(i, DL_READ, &sectDirty));
+ if (sectDirty != ENDOFCHAIN)
+ {
+ if (i > 0)
+ {
+ CFat *pfat = _stmh.GetMS()->GetFat();
+
+ msfChk(_stmc.GetSect(i - 1, &sectLast));
+ msfAssert(sectLast != ENDOFCHAIN);
+
+ msfChk(pfat->GetNext(sectLast, &sectOld));
+ msfChk(pfat->SetNext(sectLast, sectDirty));
+ if (sectOld != ENDOFCHAIN)
+ {
+ msfChk(pfat->GetNext(sectOld, &sectNext));
+ msfChk(pfat->SetNext(sectOld, FREESECT));
+ }
+ else
+ {
+ sectNext = ENDOFCHAIN;
+ }
+ msfChk(pfat->SetNext(sectDirty, sectNext));
+ msfChk(_stmc.EmptyRegion(i, i));
+ }
+ else
+ {
+ CFat *pfat = _stmh.GetMS()->GetFat();
+ CDirectory *pdir = _stmh.GetMS()->GetDir();
+
+ sectNext = ENDOFCHAIN;
+
+ msfChk(pdir->GetStart(_stmh.GetSid(), &sectLast));
+ if (sectLast != ENDOFCHAIN)
+ {
+ msfChk(pfat->GetNext(sectLast, &sectNext));
+ msfChk(pfat->SetNext(sectLast, FREESECT));
+ }
+ msfChk(pfat->SetNext(sectDirty, sectNext));
+ msfChk(pdir->SetStart(_stmh.GetSid(), sectDirty));
+ msfChk(_stmc.EmptyRegion(i, i));
+ }
+ }
+ }
+#ifdef SECURE_STREAMS
+ _ulHighWater = _ulSize;
+#endif
+
+#if DBG == 1
+ //Make sure that the stream is sane.
+ ULONG ulDirSize;
+ ULONG cSect;
+ ULONG cSectReal;
+ SECT sectStart;
+
+ _stmh.GetMS()->GetDir()->GetSize(_stmh.GetSid(), &ulDirSize);
+ cSect = (ulDirSize + cbSector - 1) / cbSector;
+ _stmh.GetMS()->GetDir()->GetStart(_stmh.GetSid(), &sectStart);
+ _stmh.GetMS()->GetFat()->GetLength(sectStart, &cSectReal);
+ msfAssert((cSect == cSectReal) &&
+ aMsg("Chain length incorrect after commit."));
+#endif
+ }
+ else
+ {
+#endif //USE_NOSCRATCH
+
+ // Note: It's critical that we do this SetSize first (since we
+ // use our scratch buffer below and SetSize can potentially also
+ // use the scratch buffer.
+
+ msfChk(SetSize(ulSize));
+
+ msfAssert(pDelta != NULL);
+
+ if (!pDelta->IsEmpty())
+ {
+ USHORT cbSector = pDelta->GetDataSectorSize();
+ USHORT uSectorShift = pDelta->GetDataSectorShift();
+
+ USHORT cbActualSize;
+ USHORT cbMaxSects = 15;
+
+ GetSafeBuffer(cbSector, cbSector * cbMaxSects, &pb, &cbActualSize);
+
+ BYTE *pbcurrent = pb;
+
+ msfAssert((pb != NULL) && aMsg("Couldn't get scratch buffer"));
+ cbMaxSects = cbActualSize / cbSector;
+
+ OFFSET oEnd;
+ oEnd = (OFFSET)((_ulSize - 1) % cbSector) + 1;
+
+ SECT sectEnd;
+ sectEnd = ((_ulSize + cbSector - 1) / cbSector);
+
+ ULONG ulOffset;
+ ILockBytes *pilbDirty;
+
+ SECT sectBeginRead = ENDOFCHAIN; //the first sector to read
+ SECT sectBeginWrite = ENDOFCHAIN; //the offset of the first place to write
+ SECT sectDirty = ENDOFCHAIN; //the sector at this offset
+
+ USHORT uReadCount = 0;
+
+ ULARGE_INTEGER ulTmp;
+ pilbDirty = pDelta->GetDataILB();
+
+
+ for (ulOffset = 0; ulOffset < sectEnd; ulOffset++)
+ {
+
+ if (sectDirty == ENDOFCHAIN)
+ {
+ sectBeginWrite = ulOffset;
+ }
+
+ msfChk(pDelta->GetMap(ulOffset, DL_READ, &sectDirty));
+
+
+ // Read will happen when we have determined there is something to read
+ // and either
+ // we have reached an ENDOFCHAIN
+ // we have reached a non-adjacent sector
+ // or we have reached the maximun amount that can be read
+ if ( (uReadCount) &&
+ ( (sectDirty == ENDOFCHAIN) ||
+ (sectDirty != sectBeginRead + uReadCount) ||
+ (ulOffset - sectBeginWrite == cbMaxSects) ))
+ {
+ msfDebugOut((DEB_ITRACE,"Reading %u sectors from sect %lu\n",
+ uReadCount,
+ sectBeginRead));
+
+ ULISet32(ulTmp, ConvertSectOffset(sectBeginRead, 0,
+ uSectorShift));
+ msfHChk(pilbDirty->ReadAt(
+ ulTmp,
+ pbcurrent,
+ cbSector * uReadCount,
+ (ULONG STACKBASED *)&temp));
+
+ pbcurrent += cbSector * uReadCount;
+ sectBeginRead = sectDirty;
+
+ //reset the ReadCount now that we are done reading
+ if (sectDirty == ENDOFCHAIN)
+ uReadCount = 0;
+ else
+ uReadCount = 1;
+
+ }
+
+ // increment the read count
+ else if (sectDirty != ENDOFCHAIN)
+ {
+ if (sectBeginRead == ENDOFCHAIN)
+ {
+ sectBeginRead = sectDirty;
+ uReadCount=1;
+ }
+ else if (sectDirty == sectBeginRead + uReadCount)
+ {
+ uReadCount++;
+ }
+ }
+
+ // Write occurs when we have something to write
+ // and we have reached an ENDOFCHAIN
+ // or the write buffer is full
+ if (((sectDirty == ENDOFCHAIN) &&
+ (sectBeginWrite != ulOffset) ) ||
+ (ulOffset - sectBeginWrite == cbMaxSects) )
+ {
+
+ msfDebugOut((DEB_ITRACE,"Writing %u sectors from sect %lu\n",
+ ulOffset - sectBeginWrite,
+ sectBeginWrite));
+
+ msfChk(WriteAt(sectBeginWrite * cbSector,
+ pb,
+ cbSector * (ulOffset - sectBeginWrite),
+ (ULONG STACKBASED *)&temp));
+ pbcurrent = pb;
+ sectBeginWrite = ulOffset;
+ }
+
+
+
+ }
+
+ // After loop, do last read and write
+ if (uReadCount)
+ {
+ ULISet32(ulTmp, ConvertSectOffset(sectBeginRead, 0,
+ uSectorShift));
+
+ msfDebugOut((DEB_ITRACE,"END::Reading %u sectors from sect %lu\n",
+ uReadCount,
+ sectBeginRead));
+
+ msfHChk(pilbDirty->ReadAt(
+ ulTmp,
+ pbcurrent,
+ cbSector * uReadCount,
+ (ULONG STACKBASED *)&temp));
+
+ msfDebugOut((DEB_ITRACE,"END::Writing %u sectors from sect %lu\n",
+ ulOffset - sectBeginWrite,
+ sectBeginWrite));
+
+ msfChk(WriteAt(sectBeginWrite * cbSector,
+ pb,
+ // all sectors except the last one
+ (cbSector * ((ulOffset-1) - sectBeginWrite)
+ // last sector fragment
+ + oEnd ),
+ (ULONG STACKBASED *)&temp));
+ }
+
+
+ }
+#ifdef USE_NOSCRATCH
+ }
+#endif
+ msfDebugOut((DEB_ITRACE,"Out CDirectStream::BeginCommitFromChild()\n"));
+
+ Err:
+#ifdef SECURE_STREAMS
+ msfAssert(_ulHighWater <= _ulSize);
+#endif
+ FreeBuffer(pb);
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectStream::EndCommitFromChild
+//
+// Synopsis: End a commit sequence from a child stream
+//
+// Arguments: [df] -- Indicates whether to commit or abort
+// [pstChild] - Child
+//
+// Returns: S_OK if call completed successfully.
+//
+// Algorithm: *Finish This*
+//
+// History: 22-Jan-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectStream_EndCommitFromChild)
+#endif
+
+void CDirectStream::EndCommitFromChild(DFLAGS df,
+ CTransactedStream *pstChild)
+{
+ msfDebugOut((DEB_ITRACE,"In CDirectStream::EndCommitFromChild:%p("
+ "%lu, %p)\n", this, df, pstChild));
+ if (!P_COMMIT(df))
+ {
+ _ulSize = _ulOldSize;
+#ifdef SECURE_STREAMS
+ _ulHighWater = _ulSize;
+#endif
+
+ //Stream cache is no longer valid, so nuke it.
+ _stmc.Empty();
+ }
+
+ _pdlHolder = NULL;
+ msfDebugOut((DEB_ITRACE,"Out CDirectStream::EndCommitFromChild()\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirectStream::Release, public
+//
+// Synopsis: Decrements the ref count and frees if necessary
+//
+// History: 08-May-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectStream_Release) // Dirst_Release_TEXT
+#endif
+
+void CDirectStream::Release(VOID)
+{
+ LONG lRet;
+
+ msfDebugOut((DEB_ITRACE,"In CDirectStream::Release()\n"));
+ msfAssert(_cReferences > 0);
+
+ lRet = AtomicDec(&_cReferences);
+ if (lRet == 0)
+ delete this;
+ msfDebugOut((DEB_ITRACE,"Out CDirectStream::Release()\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDirectStream::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// History: 08-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectStream_AddRef) //
+#endif
+
+void CDirectStream::AddRef(void)
+{
+ msfDebugOut((DEB_ITRACE, "In CDirectStream::AddRef()\n"));
+ AtomicInc(&_cReferences);
+ msfDebugOut((DEB_ITRACE, "Out CDirectStream::AddRef, %lu\n",
+ _cReferences));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirectStream::GetSize, public
+//
+// Synopsis: Gets the size of the stream
+//
+// Arguments: [pulSize] - Size return
+//
+// Modifies: [pulSize]
+//
+// History: 08-May-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectStream_GetSize)
+#endif
+
+void CDirectStream::GetSize(ULONG *pulSize)
+{
+ *pulSize = _ulSize;
+}
+
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CDirectStream_GetDeltaList) //
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirectStream::GetDeltaList, public
+//
+// Synopsis: Returns NULL, since a direct stream can never have
+// a delta list.
+//
+// Arguments: None.
+//
+// Returns: NULL
+//
+// History: 30-Jul-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CDeltaList * CDirectStream::GetDeltaList(void)
+{
+ return NULL;
+}
+
+#ifdef SECURE_STREAMS
+//+---------------------------------------------------------------------------
+//
+// Member: CDirectStream::ClearSects, private
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: void
+//
+// History: 10-Oct-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+void CDirectStream::ClearSects(ULONG ulStartOffset, ULONG ulEndOffset)
+{
+ ULONG cbBytesToWrite = ulEndOffset - ulStartOffset;
+ ULONG ulOffset = ulStartOffset;
+ msfAssert(ulEndOffset >= ulStartOffset);
+ //Start offset must be less than high water mark, or the WriteAt
+ // will recurse.
+ msfAssert(ulStartOffset <= _ulHighWater);
+
+ while (cbBytesToWrite > 0)
+ {
+ ULONG cbWritten;
+ if (FAILED(WriteAt(ulOffset,
+ s_bufSecure,
+ min(MINISTREAMSIZE, cbBytesToWrite),
+ &cbWritten)))
+ {
+ break;
+ }
+ ulOffset += cbWritten;
+ cbBytesToWrite -= cbWritten;
+ }
+
+ return;
+}
+#endif
diff --git a/private/ole32/stg/msf/tstream.cxx b/private/ole32/stg/msf/tstream.cxx
new file mode 100644
index 000000000..b54528dfd
--- /dev/null
+++ b/private/ole32/stg/msf/tstream.cxx
@@ -0,0 +1,1275 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: tstream.cxx
+//
+// Contents: Transacted stream functions
+//
+// Classes:
+//
+// Functions:
+//
+// History: 23-Jan-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+#pragma hdrstop
+
+#include "tstream.hxx"
+#include "dl.hxx"
+#include "mread.hxx"
+#include <handle.hxx>
+#include <memory.h>
+#include <dfdeb.hxx>
+
+#define DEB_TSTREAM (DEB_ITRACE | 0x00200000)
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedStream::CTransactedStream, public
+//
+// Synopsis: Empty object ctor
+//
+// Arguments: [pdfn] - Name
+// [dl] - LUID
+// [df] -- Permissions flags
+// [dwType] - Entry type
+// [pmsScratch] -- Scratch multistream
+//
+// History: 31-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_CTransactedStream)
+#endif
+
+CTransactedStream::CTransactedStream(CDfName const *pdfn,
+ DFLUID dl,
+ DFLAGS df,
+#ifdef USE_NOSCRATCH
+ CMStream *pms,
+#endif
+ CMStream *pmsScratch)
+ : PTSetMember(pdfn, STGTY_STREAM),
+ PSStream(dl),
+#ifdef USE_NOSCRATCH
+ _dl(pms, pmsScratch)
+#else
+ _dl(pmsScratch)
+#endif
+{
+ msfDebugOut((DEB_ITRACE, "In CTransactedStream::CTransactedStream:%p("
+ "%lu)\n", this, dl));
+
+ _pssBase = NULL;
+ _pdlOld = NULL;
+ _df = df;
+ _cReferences = 0;
+ _fDirty = 0;
+ _fBeginCommit = FALSE;
+ msfDebugOut((DEB_ITRACE, "Out CTransactedStream::CTransactedStream\n"));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CTransactedStream::Init, public
+//
+// Synopsis: CTransactedStream constructor
+//
+// Arguments: [pssBase] -- Pointer to base stream
+//
+// Returns: Appropriate status code
+//
+// History: 23-Jan-92 PhilipLa Created.
+// 31-Jul-92 DrewB Converted to Init from ctor
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_Init)
+#endif
+
+SCODE CTransactedStream::Init(PSStream *pssBase)
+{
+ SCODE sc;
+
+ msfDebugOut((DEB_ITRACE,"In %p:CTransactedStream constructor(%p)\n",
+ this, pssBase));
+
+ msfChk(SetInitialState(pssBase));
+
+ _pssBase = P_TO_BP(CBasedSStreamPtr, pssBase);
+
+ _sectLastUsed = 0;
+
+ AddRef();
+ msfDebugOut((DEB_ITRACE,"Out CTransactedStream constructor\n"));
+ // Fall through
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CTransactedStream::~CTransactedStream, public
+//
+// Synopsis: CTransactedStream destructor
+//
+// History: 23-Jan-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_1CTransactedStream)
+#endif
+
+CTransactedStream::~CTransactedStream()
+{
+
+ msfDebugOut((DEB_ITRACE,"In CTransactedStream Destructor\n"));
+ msfAssert(_cReferences == 0);
+
+ _dl.Empty();
+
+ if (_pssBase)
+ {
+ _pssBase->Release();
+ }
+
+
+ msfDebugOut((DEB_ITRACE,"Out CTransactedStream Destructor\n"));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTransactedStream::ReadAt, public
+//
+// Synposis: Reads binary data from a transacted stream
+//
+// Arguments: [ulOffset] -- Position to be read from
+//
+// [pBuffer] -- Pointer to the area into which the data
+// will be read.
+// [ulCount] -- Indicates the number of bytes to be read
+// [pulRetval] -- Area into which return value will be stored
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: *Finish This*
+//
+// History: 22-Jan-92 PhilipLa Created.
+//
+// Notes: [pBuffer] may be unsafe memory
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_ReadAt) // Transt_Read_TEXT
+#endif
+
+SCODE CTransactedStream::ReadAt(
+ ULONG ulOffset,
+ VOID HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval)
+{
+
+ msfDebugOut((DEB_ITRACE,"In %p:CTransactedStream::ReadAt(%lu,%p,%lu)\n",this,ulOffset,pBuffer,ulCount));
+ SCODE sc;
+
+ if (ulOffset + ulCount > _ulSize)
+ {
+ ulCount = _ulSize - ulOffset;
+ }
+
+ if ((ulCount == 0) || (ulOffset > _ulSize))
+ {
+ *pulRetval = 0;
+ return S_OK;
+ }
+
+ msfAssert(P_TRANSACTED(_df));
+
+
+ if (_dl.IsEmpty())
+ {
+ //If we have an empty delta list, either our size is 0 (in which
+ // case we'll never get to this line), or we have a parent.
+
+ msfAssert(_pssBase != NULL);
+ msfDebugOut((DEB_ITRACE,"Calling up to _pssBase\n"));
+ sc = _pssBase->ReadAt(ulOffset,pBuffer,ulCount,pulRetval);
+ msfDebugOut((DEB_ITRACE,
+ "Out CTransactedStream::ReadAt()=>%lu, ret is %lu\n",
+ sc, *pulRetval));
+
+ return sc;
+ }
+
+ ILockBytes *pilbDirty = _dl.GetDataILB();
+ USHORT cbSector = _dl.GetDataSectorSize();
+ USHORT uSectorShift = _dl.GetDataSectorShift();
+
+ ULONG temp = 0;
+ ULONG cb = 0;
+
+
+
+ SECT snow =(SECT)(ulOffset / cbSector);
+ OFFSET off = (OFFSET)(ulOffset % cbSector);
+
+ SECT send = (SECT)((ulOffset + ulCount - 1) / cbSector);
+ OFFSET offEnd = (OFFSET)((ulOffset + ulCount - 1) % cbSector);
+
+ USHORT csect = 0;
+ SECT sectNext;
+ SECT sectCurrent = snow;
+ BYTE HUGEP *pb = (BYTE HUGEP *)pBuffer;
+ USHORT oStart = off;
+ USHORT oEnd = 0;
+
+
+ SECT sectLast = ENDOFCHAIN;
+ SECT sectFirst = ENDOFCHAIN;
+
+ const USHORT ISDIRTY = 0;
+ const USHORT ISBASE = 1;
+
+ USHORT uLast;
+
+ msfChk(_dl.GetMap(sectCurrent, DL_READ, &sectNext));
+ if (sectNext != ENDOFCHAIN)
+ {
+ uLast = ISDIRTY;
+ sectLast = sectFirst = sectNext;
+ }
+ else
+ {
+ uLast = ISBASE;
+ sectLast = sectFirst = sectCurrent;
+ }
+
+ sectCurrent++;
+
+ while (sectCurrent <= send)
+ {
+ SECT sectNext;
+ msfChk(_dl.GetMap(sectCurrent, DL_READ, &sectNext));
+
+ //If any of the following occur, read the current segment:
+ // 1) Sector has mapping and current segment is in base
+ // 2) Sector has mapping and is not contiguous with
+ // current segment.
+ // 3) Sector has no mapping and current segment is in dirty.
+
+ if (((sectNext != ENDOFCHAIN) && (uLast == ISBASE)) ||
+ ((sectNext != ENDOFCHAIN) && (sectNext != sectLast + 1)) ||
+ ((sectNext == ENDOFCHAIN) && (uLast == ISDIRTY)))
+
+ {
+ msfDebugOut((DEB_ITRACE,"Reading block from pssLast\n"));
+
+ if (uLast == ISDIRTY)
+ {
+ ULARGE_INTEGER ulTmp;
+ ULISet32(ulTmp,
+ ConvertSectOffset(
+ sectFirst,
+ oStart,
+ uSectorShift));
+ msfHChk(pilbDirty->ReadAt(
+ ulTmp,
+ pb,
+ (sectLast - sectFirst + 1) * cbSector - oStart - oEnd,
+ &temp));
+ }
+ else
+ {
+ msfChk(_pssBase->ReadAt(
+ sectFirst * cbSector + oStart,
+ pb,
+ (sectLast - sectFirst + 1) * cbSector - oStart - oEnd,
+ (ULONG STACKBASED *)&temp));
+ }
+
+ pb += temp;
+ cb += temp;
+ oStart = 0;
+
+ if (sectNext == ENDOFCHAIN)
+ {
+ sectFirst = sectCurrent;
+ uLast = ISBASE;
+ }
+ else
+ {
+ sectFirst = sectNext;
+ uLast = ISDIRTY;
+ }
+ }
+
+ sectLast = (sectNext == ENDOFCHAIN) ? sectCurrent : sectNext;
+ sectCurrent++;
+
+ }
+
+ oEnd = (cbSector - 1) - offEnd;
+ msfDebugOut((DEB_ITRACE,"Reading last sector block\n"));
+ if (uLast == ISDIRTY)
+ {
+ ULARGE_INTEGER ulTmp;
+ ULISet32(ulTmp,
+ ConvertSectOffset(sectFirst, oStart, uSectorShift));
+ msfHChk(pilbDirty->ReadAt(
+ ulTmp,
+ pb,
+ (sectLast - sectFirst + 1) * cbSector - oStart - oEnd,
+ &temp));
+ }
+ else
+ {
+ msfChk(_pssBase->ReadAt(
+ sectFirst * cbSector + oStart,
+ pb,
+ (sectLast - sectFirst + 1) * cbSector - oStart - oEnd,
+ (ULONG STACKBASED *)&temp));
+ }
+
+ pb += temp;
+ cb += temp;
+ oStart = 0;
+
+ *pulRetval = cb;
+ msfDebugOut((DEB_ITRACE,"Out CTransactedStream::ReadAt()=>%lu, ret is %lu\n",(ULONG)S_OK,*pulRetval));
+
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTransactedStream::WriteAt, public
+//
+// Synposis: Writes binary data to a linear single stream
+//
+// Effects: Modifies _ulSeekPos. May cause modification in parent
+// MStream.
+//
+// Arguments: [pBuffer] -- Pointer to the area from which the data
+// will be written.
+// [ulCount] -- Indicates the number of bytes to be written
+// [pulRetval] -- Pointer to area in which number of bytes
+// will be returned
+//
+// Returns: Error code of MStream call.
+//
+// Algorithm: Calculate sector and offset for beginning and end of
+// write, then pass call up to MStream.
+//
+//
+// History: 18-Jul-91 PhilipLa Created.
+// 16-Aug-91 PhilipLa Converted to use multi-sect write
+// 23-Aug-91 PhilipLa Brought into compliance with protocol
+// 11-Sep-91 PhilipLa Moved most functionality up
+// to MStream level.
+//
+// Notes: [pBuffer] may be unsafe memory
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_WriteAt) // Transt_Write_TEXT
+#endif
+
+SCODE CTransactedStream::WriteAt(
+ ULONG ulOffset,
+ VOID const HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval)
+{
+
+ msfDebugOut((DEB_ITRACE,"In CTransactedStream::WriteAt(%lu,%p,%lu)\n",ulOffset,pBuffer,ulCount));
+ SCODE sc = S_OK;
+
+ msfAssert(P_TRANSACTED(_df));
+
+ USHORT cbSector = _dl.GetDataSectorSize();
+ USHORT uSectorShift = _dl.GetDataSectorShift();
+
+ BYTE *pbDirty;
+ pbDirty = NULL;
+ ULONG temp;
+ temp = 0;
+
+ if (ulCount == 0)
+ {
+ msfDebugOut((DEB_ITRACE,"ulCount==0. Returning.\n"));
+ *pulRetval = 0;
+ return S_OK;
+ }
+
+ //If size after the write will be greater than the current
+ //size, we may need a new delta list.
+ if (ulOffset + ulCount > _ulSize)
+ {
+ msfChk(SetSize(ulOffset + ulCount));
+ }
+
+
+ if (_dl.IsEmpty())
+ {
+ msfChk(_dl.Init(_ulSize, this));
+ }
+
+ ILockBytes *pilbDirty;
+ pilbDirty = _dl.GetDataILB();
+
+ SECT sectStart;
+ sectStart = (SECT)(ulOffset / cbSector);
+ OFFSET oStart;
+ oStart = (OFFSET)(ulOffset % cbSector);
+
+ SECT send;
+ send = (SECT)((ulOffset + ulCount - 1) / cbSector);
+ OFFSET offEnd;
+ offEnd = (OFFSET)((ulOffset + ulCount - 1) % cbSector) + 1;
+ OFFSET oEnd;
+ oEnd = 0;
+
+
+ BYTE const HUGEP *pb;
+ pb = (BYTE const HUGEP *)pBuffer;
+
+ ULONG cb;
+ cb = 0;
+ USHORT cbBlock;
+ cbBlock = 0;
+
+ SECT sectMap;
+ SECT sectFirst,sectLast;
+
+ if (sectStart == send)
+ {
+ oEnd = cbSector - offEnd;
+ }
+
+
+ SECT sectBlockStart;
+ msfChk(_dl.GetMap(sectStart, DL_GET, &sectBlockStart));
+
+ //This handles partial first sector and
+ // one sector only writes.
+ while ((oStart) || (sectStart == send))
+ {
+
+ cbBlock = cbSector - oStart - oEnd;
+ if (sectBlockStart == ENDOFCHAIN)
+ {
+ msfDebugOut((DEB_ITRACE,"Unmapped partial first sector\n"));
+ msfChk(_dl.GetMap(sectStart, DL_CREATE, &sectMap));
+ msfChk(PartialWrite(
+ sectStart,
+ sectMap,
+ pb,
+ oStart,
+ cbBlock));
+ }
+ else
+ {
+ sectMap = sectBlockStart;
+
+ ULARGE_INTEGER ulTmp;
+ ULISet32(ulTmp,
+ ConvertSectOffset(sectMap, oStart, uSectorShift));
+ msfHChk(pilbDirty->WriteAt(
+ ulTmp,
+ pb,
+ cbBlock,
+ &temp));
+ }
+
+ pb += cbBlock;
+ cb += cbBlock;
+
+ //If it was one-sector only, we can return here.
+ if (sectStart == send)
+ {
+ *pulRetval = cb;
+ return S_OK;
+ }
+
+ sectStart++;
+
+ oStart = 0;
+ msfChk(_dl.GetMap(sectStart, DL_GET, &sectBlockStart));
+ if (sectStart == send)
+ {
+ oEnd = cbSector - offEnd;
+ }
+ }
+
+
+ if (sectBlockStart == ENDOFCHAIN)
+ {
+ msfChk(_dl.GetMap(sectStart, DL_CREATE, &sectMap));
+ }
+
+ sectLast = sectFirst = (sectBlockStart == ENDOFCHAIN) ? sectMap
+ : sectBlockStart;
+
+ SECT sectCurrent;
+ sectCurrent = sectStart + 1;
+
+ while (sectCurrent < send)
+ {
+ msfDebugOut((DEB_ITRACE,"In main loop: sectCurrent = %lu\n",sectCurrent));
+ msfChk(_dl.GetMap(sectCurrent, DL_CREATE, &sectMap));
+
+ if (sectMap != sectLast + 1)
+ {
+ ULARGE_INTEGER ulTmp;
+ ULISet32(ulTmp,
+ ConvertSectOffset(sectFirst, oStart, uSectorShift));
+ msfHChk(pilbDirty->WriteAt(
+ ulTmp,
+ pb,
+ (sectLast - sectFirst + 1) * cbSector - oStart,
+ &temp));
+ pb += temp;
+ cb += temp;
+ oStart = 0;
+
+ sectFirst = sectMap;
+ }
+
+ sectLast = sectMap;
+ sectCurrent++;
+ }
+
+ msfAssert(oStart == 0);
+
+ msfChk(_dl.GetMap(sectCurrent, DL_GET, &sectMap));
+
+ oEnd = cbSector - offEnd;
+
+ BOOL fIsMapped;
+
+ if (sectMap == ENDOFCHAIN)
+ {
+ fIsMapped = FALSE;
+ msfChk(_dl.GetMap(sectCurrent,DL_CREATE, &sectMap));
+ }
+ else
+ {
+ fIsMapped = TRUE;
+ }
+
+ if ((sectMap != sectLast + 1) || (oEnd != 0))
+ {
+ ULARGE_INTEGER ulTmp;
+ ULISet32(ulTmp,
+ ConvertSectOffset(sectFirst, oStart, uSectorShift));
+ msfHChk(pilbDirty->WriteAt(
+ ulTmp,
+ pb,
+ (sectLast - sectFirst + 1) * cbSector - oStart,
+ &temp));
+ pb += temp;
+ cb += temp;
+ oStart = 0;
+
+ sectFirst = sectMap;
+ }
+
+ if (oEnd == 0)
+ {
+ ULARGE_INTEGER ulTmp;
+ ULISet32(ulTmp,
+ ConvertSectOffset(sectFirst, oStart, uSectorShift));
+ msfHChk(pilbDirty->WriteAt(
+ ulTmp,
+ pb,
+ (sectMap - sectFirst + 1) * cbSector - oStart - oEnd,
+ &temp));
+ pb += temp;
+ cb += temp;
+ oStart = 0;
+ }
+ else
+ {
+ cbBlock = cbSector - oEnd;
+
+ if (!fIsMapped)
+ {
+ msfChk(PartialWrite(
+ sectCurrent,
+ sectMap,
+ pb,
+ 0,
+ cbBlock));
+ }
+ else
+ {
+ ULARGE_INTEGER ulTmp;
+ ULISet32(ulTmp,
+ ConvertSectOffset(sectMap, oStart, uSectorShift));
+ msfHChk(pilbDirty->WriteAt(
+ ulTmp,
+ pb,
+ cbBlock,
+ &temp));
+ }
+
+ pb += cbBlock;
+ cb += cbBlock;
+ }
+
+ *pulRetval = cb;
+
+ msfDebugOut((DEB_ITRACE,"Leaving CTransactedStream::WriteAt()==>%lu, ret is %lu\n",(ULONG)S_OK,*pulRetval));
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CTransactedStream::SetSize, public
+//
+// Synposis: Set the size of a linear stream
+//
+// Effects: Modifies _ulSize. May cause change in parent MStream.
+//
+// Arguments: [ulNewSize] -- New size for stream
+//
+// Returns: Error code returned by MStream call.
+//
+// Algorithm: Pass call up to parent.
+//
+// History: 29-Jul-91 PhilipLa Created.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_SetSize) // Transt_SetSize_TEXT
+#endif
+
+SCODE CTransactedStream::SetSize(ULONG ulNewSize)
+{
+ SCODE sc = S_OK;
+ BYTE *pb = NULL;
+
+ msfDebugOut((DEB_ITRACE,"In CTransactedStream::SetSize(%lu)\n",ulNewSize));
+ msfAssert(P_TRANSACTED(_df));
+
+ if (ulNewSize == 0)
+ {
+ _dl.Empty();
+ }
+ else if (!_dl.IsEmpty())
+ {
+ msfChk(_dl.InitResize(ulNewSize));
+ }
+ else
+ {
+ msfChk(_dl.Init(ulNewSize, this));
+ }
+
+ if (ulNewSize > _ulSize)
+ {
+ USHORT cbSector = _dl.GetDataSectorSize();
+ USHORT uSectorShift = _dl.GetDataSectorShift();
+
+ SECT sectStart, sectEnd, sect, sectNew;
+
+ if (_ulSize == 0)
+ {
+ sectStart = 0;
+ }
+ else
+ {
+ sectStart = (_ulSize - 1) / cbSector;
+ }
+
+ sectEnd = (ulNewSize - 1 ) / cbSector;
+
+
+ //First, make sure the first sector is copied over OK if necessary.
+ msfChk(_dl.GetMap(sectStart, DL_GET, &sectNew));
+
+
+ if ((sectNew == ENDOFCHAIN) && (_pssBase != NULL) &&
+ (_ulSize != 0))
+ {
+ USHORT cbNull;
+ GetSafeBuffer(cbSector, cbSector, &pb, &cbNull);
+ msfAssert((pb != NULL) && aMsg("Couldn't get scratch buffer"));
+ ULONG dummy;
+
+ msfChk(_pssBase->ReadAt(
+ sectStart << uSectorShift,
+ pb,
+ cbSector,
+ (ULONG STACKBASED *)&dummy));
+
+ msfChk(_dl.GetMap(sectStart, DL_CREATE, &sectNew));
+
+ ULARGE_INTEGER ulTmp;
+
+ ULISet32(ulTmp, ConvertSectOffset(sectNew, 0, uSectorShift));
+
+ msfHChk(_dl.GetDataILB()->WriteAt(
+ ulTmp,
+ pb,
+ cbSector,
+ &dummy));
+ sectStart++;
+ }
+
+ for (sect = sectStart; sect <= sectEnd; sect ++)
+ {
+ msfChk(_dl.GetMap(sect, DL_CREATE, &sectNew));
+ }
+ }
+ _ulSize = ulNewSize;
+
+ msfDebugOut((DEB_ITRACE,"Out CTransactedStream::SetSize()\n"));
+
+ Err:
+ FreeBuffer(pb);
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CTransactedStream::BeginCommitFromChild, public
+//
+// Synopsis: Begin a commit from a child TStream
+//
+// Arguments: [ulSize] - New size
+// [pDelta] - Delta list
+// [pstChild] - Child
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: *Finish This*
+//
+// History: 22-Jan-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_BeginCommitFromChild) // Transt_Commit_TEXT
+#endif
+
+SCODE CTransactedStream::BeginCommitFromChild(
+ ULONG ulSize,
+ CDeltaList *pDelta,
+ CTransactedStream *pstChild)
+{
+ msfDebugOut((DEB_ITRACE,"In CTransactedStream::BeginCommitFromChild:%p("
+ "%lu, %p, %p)\n", this, ulSize, pDelta, pstChild));
+
+ msfAssert(P_TRANSACTED(_df));
+ _dl.BeginCommit(this);
+ _pdlOld = P_TO_BP(CBasedDeltaListPtr, pDelta);
+ _ulOldSize = _ulSize;
+ _ulSize = ulSize;
+
+ msfDebugOut((DEB_ITRACE,"Out CTransactedStream::BeginCommitFromChild()\n"));
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CTransactedStream::EndCommitFromChild, public
+//
+// Synopsis: End a commit from child.
+//
+// Arguments: [df] -- Flags to determine whether to commit or revert
+// [pstChild] - Child
+//
+// Returns: Void. This can't fail.
+//
+// Algorithm: *Finish This*
+//
+// History: 22-Jan-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_EndCommitFromChild)
+#endif
+
+void CTransactedStream::EndCommitFromChild(DFLAGS df,
+ CTransactedStream *pstChild)
+{
+ msfDebugOut((DEB_ITRACE,"In CTransactedStream::EndCommitFromChild:%p("
+ "%lu, %p)\n", this, df, pstChild));
+
+ msfAssert(P_TRANSACTED(_df));
+
+ _dl.EndCommit(BP_TO_P(CDeltaList *, _pdlOld), df);
+
+ //NOTE: Possible cleanup: Move _pdlOld into the delta list itself.
+ _pdlOld = NULL;
+
+ if (P_COMMIT(df))
+ {
+ _ulOldSize = 0;
+ }
+ else
+ {
+ _ulSize = _ulOldSize;
+ }
+ msfDebugOut((DEB_ITRACE,"Out CTransactedStream::EndCommitFromChild()\n"));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CTransactedStream::BeginCommit, public
+//
+// Synopsis: Begin a commit of a transacted stream object
+//
+// Arguments: [dwFlags] -- Currently not used (future expansion)
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Call BeginCommitFromChild on base
+//
+// History: 22-Jan-92 PhilipLa Created.
+//
+// Notes: This is only called by the Transaction Level object.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_BeginCommit)
+#endif
+
+SCODE CTransactedStream::BeginCommit(DWORD const dwFlags)
+{
+ SCODE sc = S_OK;
+
+ msfDebugOut((DEB_ITRACE,"In CTransactedStream::BeginCommit(%lu)\n",
+ dwFlags));
+
+ msfAssert(_pssBase != NULL);
+ msfAssert(P_TRANSACTED(_df));
+
+#if DBG == 1
+ if (!HaveResource(DBR_XSCOMMITS, 1))
+ msfErr(Err, STG_E_ABNORMALAPIEXIT);
+#endif
+
+ _fBeginCommit = TRUE;
+ msfChk(_pssBase->BeginCommitFromChild(_ulSize, &_dl, this));
+
+ msfDebugOut((DEB_ITRACE,"Out CTransactedStream::BeginCommit()\n"));
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CTransactedStream::EndCommit, public
+//
+// Synopsis: End a commit on a transacted stream object
+//
+// Arguments: [df] -- Indicator of whether to commit or revert
+//
+// Returns: void. This can't fail.
+//
+// Algorithm: Call EndCommitFromChild on base.
+// If committing, NULL out all previously passed up
+// dirty information.
+//
+// History: 22-Jan-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_EndCommit)
+#endif
+
+void CTransactedStream::EndCommit(DFLAGS const df)
+{
+ msfDebugOut((DEB_ITRACE,"In CTransactedStream::EndCommit(%lu)\n",df));
+
+ msfAssert(P_TRANSACTED(_df));
+ msfAssert((_pssBase != NULL) || (P_ABORT(df)));
+
+ if (!_fBeginCommit)
+ return;
+ _fBeginCommit = FALSE;
+
+#if DBG == 1
+ if (P_COMMIT(df))
+ ModifyResLimit(DBR_XSCOMMITS, 1);
+#endif
+
+ if (_pssBase != NULL)
+ {
+ _pssBase->EndCommitFromChild(df, this);
+ }
+
+ if (P_COMMIT(df))
+ {
+ _dl.Empty();
+ SetClean();
+ }
+
+ msfDebugOut((DEB_ITRACE,"Out CTransactedStream::EndCommit()\n"));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CTransactedStream::Revert, public
+//
+// Synopsis: Revert a transacted stream instance.
+//
+// Algorithm: Destroy dirty stream and delta list.
+// Retrieve size from base.
+// Mark object as Invalid if specified in the flags.
+//
+// History: 22-Jan-92 PhilipLa Created.
+//
+// Notes: This is only called from the Transaction Level.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_Revert) // Trans_Revert_TEXT
+#endif
+
+void CTransactedStream::Revert(void)
+{
+ msfDebugOut((DEB_ITRACE,"In CTransactedStream::Revert(%lu): This == %p\n",this));
+
+ _dl.Empty();
+ msfVerify(SUCCEEDED(SetInitialState(BP_TO_P(PSStream *, _pssBase))));
+ _sectLastUsed = 0;
+ SetClean();
+
+ msfDebugOut((DEB_ITRACE,"Out CTransactedStream::Revert()\n"));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CTransactedStream::Release, public
+//
+// Synopsis: Release 'this'
+//
+// History: 22-Jan-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_Release) // Trans_Release_TEXT
+#endif
+
+void CTransactedStream::Release(VOID)
+{
+ LONG lRet;
+
+ msfDebugOut((DEB_ITRACE,"In CTransactedStream::Release()\n"));
+ msfAssert(_cReferences > 0);
+ lRet = AtomicDec(&_cReferences);
+ if (lRet == 0)
+ delete this;
+ msfDebugOut((DEB_ITRACE,"Out CTransactedStream::Release()\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedStream::SetBase, public
+//
+// Synopsis: Sets a new base
+//
+// Arguments: [psst] - New base
+//
+// Returns: Appropriate status code
+//
+// History: 31-Jul-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_SetBase) // Trans_Commit_TEXT
+#endif
+
+SCODE CTransactedStream::SetBase(PSStream *psst)
+{
+ msfAssert(_pssBase == NULL || psst == NULL);
+ if (_pssBase)
+ _pssBase->Release();
+ _pssBase = P_TO_BP(CBasedSStreamPtr, psst);
+ return S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedStream::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// History: 08-May-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_AddRef) //
+#endif
+
+void CTransactedStream::AddRef(void)
+{
+ msfDebugOut((DEB_ITRACE, "In CTransactedStream::AddRef()\n"));
+ AtomicInc(&_cReferences);
+ msfDebugOut((DEB_ITRACE, "Out CTransactedStream::AddRef, %lu\n",
+ _cReferences));
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CTransactedStream::PartialWrite, private
+//
+// Synopsis: Do a write of a partial sector
+//
+// Arguments: [sectBase] -- Sector in base to copy
+// [sectDirty] -- Sector in dirty to write to
+// [pb] -- Buffer containing data to be writte
+// [offset] -- Offset into buffer to begin copy
+// [uLen] -- Number of bytes to copy
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: *Finish This*
+//
+// History: 30-Jun-92 PhilipLa Created.
+//
+// Notes: [pb] may be unsafe memory
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_PartialWrite) // Transt_Write_TEXT
+#endif
+
+SCODE CTransactedStream::PartialWrite(
+ SECT sectBase,
+ SECT sectDirty,
+ BYTE const HUGEP *pb,
+ USHORT offset,
+ USHORT uLen)
+{
+ msfDebugOut((DEB_ITRACE,"In CTransactedStream::PartialWrite()\n"));
+ BYTE *pbMem = NULL;
+ SCODE sc;
+ ULONG temp;
+
+ USHORT cbSector = _dl.GetDataSectorSize();
+ USHORT uSectorShift = _dl.GetDataSectorShift();
+
+ if (uLen != cbSector)
+ {
+ USHORT cbNull;
+ GetSafeBuffer(cbSector, cbSector, &pbMem, &cbNull);
+ msfAssert((pbMem != NULL) && aMsg("Couldn't get scratch buffer"));
+
+ if (_pssBase != NULL)
+ {
+ msfChk(_pssBase->ReadAt(
+ sectBase << uSectorShift,
+ pbMem,
+ cbSector,
+ (ULONG STACKBASED *)&temp));
+ }
+
+ TRY
+ {
+ memcpy(pbMem + offset, pb, uLen);
+ }
+ CATCH(CException, e)
+ {
+ UNREFERENCED_PARM(e);
+ msfErr(Err, STG_E_INVALIDPOINTER);
+ }
+ END_CATCH
+
+ pb = pbMem;
+ }
+
+ ULARGE_INTEGER ulTmp;
+ ULISet32(ulTmp,
+ ConvertSectOffset(sectDirty, 0, uSectorShift));
+
+ sc = DfGetScode((_dl.GetDataILB())->WriteAt(
+ ulTmp,
+ pb,
+ cbSector,
+ &temp));
+
+Err:
+ FreeBuffer(pbMem);
+ msfDebugOut((DEB_ITRACE,"Out CTransactedStream::PartialWrite()\n"));
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CTransactedStream::GetCommitInfo, public
+//
+// Synopsis: Return the current size of the stream and the size of
+// its base.
+//
+// Arguments: [pulRet1] -- Pointer to return location for old size
+// [pulRet2] -- Pointer to return location for current size
+//
+// History: 08-Jul-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_GetCommitInfo) // Transt_Overwrite_TEXT
+#endif
+
+void CTransactedStream::GetCommitInfo(ULONG *pulRet1, ULONG *pulRet2)
+{
+ if (_pssBase != NULL)
+ _pssBase->GetSize(pulRet1);
+ else
+ *pulRet1 = 0;
+ *pulRet2 = _ulSize;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CTransactedStream::GetSize, public
+//
+// Synopsis: Returns the size of the stream.
+//
+// Arguments: [pulSize] -- Pointer to return location for size.
+//
+// Returns: S_OK
+//
+// History: 22-Jan-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_GetSize) //
+#endif
+
+void CTransactedStream::GetSize(ULONG *pulSize)
+{
+ msfAssert(P_TRANSACTED(_df));
+
+ *pulSize = _ulSize;
+
+ msfDebugOut((DEB_ITRACE,"CTransactedStream::GetSize()==>%lu\n",*pulSize));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactedStream::SetInitialState, public
+//
+// Synopsis: Sets the initial state from a base or defaults
+//
+// Arguments: [pssBase] - Base or NULL
+//
+// Returns: Appropriate status code
+//
+// History: 11-Nov-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_SetInitialState)
+#endif
+
+SCODE CTransactedStream::SetInitialState(PSStream *pssBase)
+{
+ olDebugOut((DEB_ITRACE, "In CTransactedStream::SetInitialState:%p(%p)\n",
+ this, pssBase));
+ if (pssBase == NULL)
+ {
+ _ulSize = 0;
+ }
+ else
+ {
+ pssBase->GetSize(&_ulSize);
+ }
+ olDebugOut((DEB_ITRACE, "Out CTransactedStream::SetInitialState\n"));
+ return S_OK;
+}
+
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CTransactedStream_GetDeltaList)
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactedStream::GetDeltaList, public
+//
+// Synopsis: Return a pointer to the delta list if it is not empty.
+// If it is empty, call GetDeltaList on the parent and
+// return that.
+//
+// Arguments: None.
+//
+// Returns: Pointer as above.
+//
+// History: 30-Jul-93 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CDeltaList * CTransactedStream::GetDeltaList(void)
+{
+ if (_dl.IsEmpty())
+ {
+ if (_pssBase != NULL)
+ {
+ return _pssBase->GetDeltaList();
+ }
+ else
+ {
+ //This case will only be hit if someone creates a new
+ // stream, then commits it to its parent without writing
+ // anything to it. The parent then has an empty delta
+ // list with no parent set on it.
+ msfAssert(_ulSize == 0);
+ return NULL;
+ }
+ }
+ else
+ return &_dl;
+}
diff --git a/private/ole32/stg/msf/vect.cxx b/private/ole32/stg/msf/vect.cxx
new file mode 100644
index 000000000..6092f5d54
--- /dev/null
+++ b/private/ole32/stg/msf/vect.cxx
@@ -0,0 +1,744 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: vect.cxx
+//
+// Contents: Vector common code.
+//
+// Classes:
+//
+// Functions:
+//
+// History: 27-Oct-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+#pragma hdrstop
+
+#include <msffunc.hxx>
+#include <vect.hxx>
+#include <ole.hxx>
+#include <entry.hxx>
+#include <smalloc.hxx>
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPagedVector_GetNewVectBits)
+#endif
+
+// BUGBUG: In order to work around an optimization bug in the
+// CairOLE build, we need to turn all optimizations off
+// for this function.
+//
+#if WIN32 == 300
+#pragma optimize("", off)
+#endif
+
+
+inline CVectBits * CPagedVector::GetNewVectBits(ULONG ulSize)
+{
+ msfAssert(ulSize > 0);
+ CVectBits *pfb = NULL;
+
+ if (ulSize <= (_HEAP_MAXREQ / sizeof(CVectBits)))
+ {
+ pfb = (CVectBits *) _pmsParent->GetMalloc()->Alloc(ulSize *
+ sizeof(CVectBits));
+ if (pfb)
+ {
+ memset(pfb, 0, (USHORT)(ulSize * sizeof(CVectBits)));
+ }
+ }
+ return pfb;
+}
+
+// BUGBUG: We need to turn default optimizations back on. See
+// BUGBUG above for more information.
+//
+#if WIN32 == 300
+#pragma optimize("", on)
+#endif
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPagedVector_GetNewPageArray)
+#endif
+
+inline CBasedMSFPagePtr* VECT_CLASS
+ CPagedVector::GetNewPageArray(ULONG ulSize)
+{
+ msfAssert(ulSize > 0);
+ if (ulSize > (_HEAP_MAXREQ / sizeof(CMSFPage *)))
+ {
+ return NULL;
+ }
+
+ return (CBasedMSFPagePtr *)
+ _pmsParent->GetMalloc()->Alloc(ulSize * sizeof(CMSFPage *));
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPagedVector::Init, public
+//
+// Synopsis: CPagedVector initialization function
+//
+// Arguments: [ulSize] -- size of vector
+// [uFatEntries] -- number of entries in each table
+//
+// Algorithm: Allocate an array of pointer of size ulSize
+// For each cell in the array, allocate a CFatSect
+//
+// History: 27-Dec-91 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPagedVector_Init)
+#endif
+
+SCODE VECT_CLASS CPagedVector::Init(CMStream *pmsParent,
+ ULONG ulSize)
+{
+ msfDebugOut((DEB_ITRACE,"In CPagedVector::CPagedVector(%lu)\n",ulSize));
+ SCODE sc = S_OK;
+ _pmsParent = P_TO_BP(CBasedMStreamPtr, pmsParent);
+
+ CMSFPageTable *pmptTemp = _pmsParent->GetPageTable();
+ _pmpt = P_TO_BP(CBasedMSFPageTablePtr, pmptTemp);
+
+ msfAssert(_pmpt != NULL);
+
+ USHORT i;
+
+ // We don't bother allocating more than necessary here
+ _ulAllocSize = _ulSize = ulSize;
+
+ if (_ulSize > 0)
+ {
+ CBasedMSFPagePtr *ampTemp;
+ msfMem(ampTemp = GetNewPageArray(ulSize));
+ for (i = 0; i < _ulSize; i++)
+ {
+ ampTemp[i] = NULL;
+ }
+ _amp = P_TO_BP(CBasedMSFPagePtrPtr, ampTemp);
+
+ CVectBits *avbTemp;
+ msfMem(avbTemp = GetNewVectBits(ulSize));
+ _avb = P_TO_BP(CBasedVectBitsPtr, avbTemp);
+ }
+
+ msfDebugOut((DEB_ITRACE,"Out CPagedVector::CPagedVector()\n"));
+ return S_OK;
+
+Err:
+ //In the error case, discard whatever vectors we were able to allocate
+ // and return S_OK.
+ _pmsParent->GetMalloc()->Free(BP_TO_P(CBasedMSFPagePtr *, _amp));
+ _amp = NULL;
+
+ _pmsParent->GetMalloc()->Free(BP_TO_P(CVectBits *,_avb));
+ _avb = NULL;
+
+ return S_OK;
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPagedVector::~CPagedVector, public
+//
+// Synopsis: CPagedVector constructor
+//
+// Algorithm: Delete the pointer array.
+//
+// History: 27-Oct-92 PhilipLa Created.
+// 20-Jul-95 SusiA Changed Free to FreeNoMutex
+//
+// Notes: This function freed the SmAllocator object without first obtaining
+// the mutex. Callling functions should already have the DFMutex locked.
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPagedVector_1CPagedVector)
+#endif
+
+VECT_CLASS CPagedVector::~CPagedVector()
+{
+ if (_pmsParent != NULL)
+ {
+#ifdef MULTIHEAP
+ // Free is the same as FreeNoMutex now
+ _pmsParent->GetMalloc()->Free(BP_TO_P(CBasedMSFPagePtr*, _amp));
+ _pmsParent->GetMalloc()->Free(BP_TO_P(CVectBits *,_avb));
+#else
+ g_smAllocator.FreeNoMutex(BP_TO_P(CBasedMSFPagePtr*, _amp));
+ g_smAllocator.FreeNoMutex(BP_TO_P(CVectBits *, _avb));
+#endif
+
+ }
+ else
+ msfAssert(_amp == NULL && _avb == NULL &&
+ aMsg("Can't free arrays without allocator"));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::Empty, public
+//
+// Synopsis: Discard the storage associated with this vector.
+//
+// Arguments: None.
+//
+// Returns: void.
+//
+// History: 04-Dec-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPagedVector_Empty)
+#endif
+
+void CPagedVector::Empty(void)
+{
+ if (_pmpt != NULL)
+ {
+ _pmpt->FreePages(this);
+ }
+
+ msfAssert(((_pmsParent != NULL) || ((_amp == NULL) && (_avb == NULL))) &&
+ aMsg("Can't get to IMalloc for vector memory."));
+
+ if (_pmsParent != NULL)
+ {
+ _pmsParent->GetMalloc()->Free(BP_TO_P(CBasedMSFPagePtr*, _amp));
+ _pmsParent->GetMalloc()->Free(BP_TO_P(CVectBits *, _avb));
+ }
+
+ _amp = NULL;
+ _avb = NULL;
+ _pmpt = NULL;
+ _ulAllocSize = _ulSize = 0;
+ _pmsParent = NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::Flush, public
+//
+// Synopsis: Flush the dirty pages for this vector
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+// History: 02-Nov-92 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPagedVector_Flush)
+#endif
+
+SCODE CPagedVector::Flush(void)
+{
+#ifndef SORTPAGETABLE
+ SCODE sc;
+ SCODE scRet = S_OK;
+
+ if (_ulSize > 0)
+ {
+ if (_amp != NULL)
+ {
+ for (USHORT i = 0; i < _ulSize; i++)
+ {
+ if ((_amp[i] != NULL) && (_amp[i]->IsDirty()))
+ {
+ sc = _pmpt->FlushPage(BP_TO_P(CMSFPage *, _amp[i]));
+ if ((FAILED(sc)) && (SUCCEEDED(scRet)))
+ {
+ scRet = sc;
+ }
+ }
+ }
+ }
+ else
+ {
+ scRet = _pmpt->Flush();
+ }
+ }
+
+ return scRet;
+#else
+ return S_OK;
+#endif
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPagedVector::GetTable, public
+//
+// Synopsis: Return a pointer to a page for the given index
+// into the vector.
+//
+// Arguments: [iTable] -- index into vector
+// [ppmp] -- Pointer to return location
+//
+// Returns: S_OK if call completed OK.
+//
+// History: 27-Oct-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPagedVector_GetTable)
+#endif
+
+SCODE VECT_CLASS CPagedVector::GetTableWithSect(
+ const FSINDEX iTable,
+ DWORD dwFlags,
+ SECT sectKnown,
+ void **ppmp)
+{
+ SCODE sc = S_OK;
+ CMSFPage *pmp;
+
+ msfAssert((_pmsParent->GetILB() != NULL) &&
+ aMsg("Null ILB found on GetTable - need SetAccess call?"));
+
+ // docfile is corrupted with an invalid iTable size
+ if (iTable >= _ulSize)
+ {
+ msfErr(Err, STG_E_DOCFILECORRUPT);
+
+ }
+
+ if ((_amp == NULL) || (_amp[iTable] == NULL))
+ {
+ if (dwFlags & FB_NEW)
+ {
+ //We know that the page isn't in the page table,
+ // so we can just get a free page an allocate it
+ // ourselves.
+
+ msfChk(_pmpt->GetFreePage(&pmp));
+
+ pmp->SetVector(this);
+ pmp->SetSid(_sid);
+ pmp->SetOffset(iTable);
+#ifdef SORTPAGETABLE
+ _pmpt->SetSect(pmp, ENDOFCHAIN);
+#else
+ pmp->SetSect(ENDOFCHAIN);
+#endif
+
+ sc = STG_S_NEWPAGE;
+ dwFlags = (dwFlags & ~FB_NEW) | FB_DIRTY;
+ }
+ else
+ {
+ msfChk(_pmpt->GetPage(this,
+ _sid, iTable, sectKnown, &pmp));
+ msfAssert((pmp->GetVector() == this) &&
+ aMsg("GetPage returned wrong page."));
+ }
+
+
+ if (_amp != NULL)
+ {
+ _amp[iTable] = P_TO_BP(CBasedMSFPagePtr, pmp);
+ }
+
+ }
+ else
+ {
+ pmp = BP_TO_P(CMSFPage *, _amp[iTable]);
+ msfAssert((pmp->GetVector() == this) &&
+ aMsg("Cached page has wrong vector pointer"));
+ }
+
+ pmp->AddRef();
+
+ if (((dwFlags & FB_DIRTY) && !(pmp->IsDirty())) &&
+ (sc != STG_S_NEWPAGE))
+ {
+ //If we are not a newly created page, and we are being
+ // dirtied for the first time, make sure that our
+ // _sect field is correct.
+ //
+ //Newly created pages have to have their sect set manually
+ // _before_ being released. This is very important.
+
+#ifndef REF
+ msfAssert(!_pmsParent->IsShadow() &&
+ aMsg("Dirtying page in shadow multistream."));
+
+ msfChkTo(Err_Rel, _pmsParent->GetFat()->QueryRemapped(pmp->GetSect()));
+
+ if (sc == S_FALSE)
+ {
+#endif //!REF
+#ifdef SORTPAGETABLE
+ _pmpt->SetSect(pmp, ENDOFCHAIN);
+#else
+ pmp->SetSect(ENDOFCHAIN);
+#endif
+
+ SECT sect;
+ msfChkTo(Err_Rel, _pmsParent->GetESect(
+ pmp->GetSid(),
+ pmp->GetOffset(),
+ &sect));
+
+#ifdef SORTPAGETABLE
+ _pmpt->SetSect(pmp, sect);
+#else
+ pmp->SetSect(sect);
+#endif
+#ifndef REF
+ }
+#endif //!REF
+ }
+#ifndef REF
+#if DBG == 1
+ else if ((pmp->IsDirty()) && (!pmp->IsInUse()) && (sc != STG_S_NEWPAGE))
+ {
+ msfAssert((_pmsParent->GetFat()->QueryRemapped(pmp->GetSect()) ==
+ S_OK) &&
+ aMsg("Found unremapped dirty page."));
+ }
+#endif
+#endif //!REF
+
+ pmp->SetFlags(pmp->GetFlags() | dwFlags | FB_TOUCHED);
+ msfAssert((pmp->GetVector() == this) &&
+ aMsg("GetTable returned wrong page."));
+ *ppmp = pmp->GetData();
+
+Err:
+ return sc;
+
+Err_Rel:
+ pmp->Release();
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::SetDirty, public
+//
+// Synopsis: Set the dirty bit on the specified page
+//
+// Arguments: [iTable] -- Table to set bit on
+//
+// History: 28-Oct-92 PhilipLa Created
+//
+// Notes: This function is always called on a page with an
+// open reference. Therefore, the page is
+// guaranteed to be in the page table, and that
+// FindPage call should never return an error.
+//
+//----------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPagedVector_SetDirty)
+#endif
+
+SCODE CPagedVector::SetDirty(ULONG iTable)
+{
+ SCODE sc = S_OK;
+ CMSFPage *pmp;
+
+#ifndef REF
+ msfAssert((!_pmsParent->IsShadow()) &&
+ aMsg("Dirtying page in shadow."));
+#endif //!REF
+
+ if (_amp == NULL)
+ {
+
+ msfChk(_pmpt->FindPage(this, _sid, iTable, &pmp));
+ msfAssert(sc == STG_S_FOUND);
+ msfAssert(pmp->IsInUse() &&
+ aMsg("Called SetDirty on page not in use."));
+ }
+ else
+ {
+ msfAssert(_amp != NULL);
+ msfAssert(_amp[iTable] != NULL);
+ pmp = BP_TO_P(CMSFPage *, _amp[iTable]);
+ }
+
+ if (!pmp->IsDirty())
+ {
+ //We are not a newly created page, and we are being
+ // dirtied for the first time, make sure that our
+ // _sect field is correct.
+ //
+
+#ifndef REF
+ msfAssert(!_pmsParent->IsShadow() &&
+ aMsg("Dirtying page in shadow multistream."));
+#endif //!REF
+ pmp->AddRef();
+
+#ifndef REF
+ msfChkTo(Err_Rel, _pmsParent->GetFat()->QueryRemapped(pmp->GetSect()));
+
+ if (sc == S_FALSE)
+ {
+#endif //!REF
+#ifdef SORTPAGETABLE
+ _pmpt->SetSect(pmp, ENDOFCHAIN);
+#else
+ pmp->SetSect(ENDOFCHAIN);
+#endif
+
+ SECT sect;
+ msfChkTo(Err_Rel, _pmsParent->GetESect(
+ pmp->GetSid(),
+ pmp->GetOffset(),
+ &sect));
+
+#ifdef SORTPAGETABLE
+ _pmpt->SetSect(pmp, sect);
+#else
+ pmp->SetSect(sect);
+#endif
+#ifndef REF
+ }
+#endif //!REF
+
+ pmp->Release();
+ }
+#ifndef REF
+#if DBG == 1
+ else
+ {
+ pmp->AddRef();
+ sc = _pmsParent->GetFat()->QueryRemapped(pmp->GetSect());
+ msfAssert((SUCCEEDED(sc)) &&
+ aMsg("QueryRemapped returned error"));
+ msfAssert((sc == S_OK) &&
+ aMsg("QueryRemapped returned non-TRUE value."));
+ pmp->Release();
+ }
+#endif
+#endif //!REF
+
+ pmp->SetDirty();
+
+ Err:
+ return sc;
+
+ Err_Rel:
+ pmp->Release();
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPagedVector::Resize, public
+//
+// Synopsis: Resize a CPagedVector
+//
+// Arguments: [ulSize] -- Size of new vector
+//
+// Algorithm: Create new pointer array of size ulSize.
+// For each entry in old array, copy the pointer over.
+//
+// History: 27-Oct-92 PhilipLa Created.
+// 08-Feb-93 AlexT Add LARGETHRESHOLD support
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPagedVector_Resize)
+#endif
+
+#define LARGETHRESHOLD 1024
+#define VECTORBLOCK 1024 // Must be power of 2
+
+SCODE VECT_CLASS CPagedVector::Resize(FSINDEX ulSize)
+{
+ msfDebugOut((DEB_ITRACE,"In CPagedVector::CPagedVector(%lu)\n",ulSize));
+
+ msfAssert(ulSize >= _ulSize);
+ msfAssert(_ulSize <= _ulAllocSize);
+ msfAssert(((VECTORBLOCK & (VECTORBLOCK - 1)) == 0) &&
+ aMsg("VECTORBLOCK must be power of 2"));
+
+ msfAssert(!((_amp == NULL) && (_avb != NULL)) &&
+ aMsg("Resize precondition failed."));
+
+ if (ulSize > _ulAllocSize)
+ {
+ // We don't have room in the existing vector; grow it
+ ULONG ulNewAllocSize = ulSize;
+
+ if (ulNewAllocSize > LARGETHRESHOLD)
+ {
+ // We're dealing with a large vector; grow it a VECTORBLOCK
+ // at a time
+ ulNewAllocSize = (ulNewAllocSize + VECTORBLOCK - 1) &
+ ~(VECTORBLOCK - 1);
+ }
+
+ CBasedMSFPagePtr *amp = GetNewPageArray(ulNewAllocSize);
+ CVectBits *avb = GetNewVectBits(ulNewAllocSize);
+
+ // Can't fail after this point
+
+ _ulAllocSize = ulNewAllocSize;
+
+ // Copy over the old entries
+
+
+ if ((amp != NULL) && (avb != NULL))
+ {
+ if ((_amp != NULL) && (_avb != NULL))
+ {
+ // Both allocations succeeded
+ for (ULONG iamp = 0; iamp < _ulSize; iamp++)
+ {
+ amp[iamp] = _amp[iamp];
+ avb[iamp] = _avb[iamp];
+ }
+ }
+ else if (_amp != NULL)
+ {
+ for (ULONG iamp = 0; iamp < _ulSize; iamp++)
+ {
+ amp[iamp] = _amp[iamp];
+ }
+ }
+ else
+ {
+ for (ULONG iamp = 0; iamp < _ulSize; iamp++)
+ {
+ amp[iamp] = NULL;
+ }
+ }
+ }
+ else
+ {
+ // At least one of the allocations failed
+ _pmsParent->GetMalloc()->Free(avb);
+ avb = NULL;
+
+ _pmsParent->GetMalloc()->Free(amp);
+ amp = NULL;
+ }
+
+ // Delete the old vector and put in the new one (if any).
+ // In the error case, throw away the vectors we are currently
+ // holding (since they are of insufficient size) and return S_OK.
+
+ _pmsParent->GetMalloc()->Free(BP_TO_P(CBasedMSFPagePtr*, _amp));
+ _amp = P_TO_BP(CBasedMSFPagePtrPtr, amp);
+
+ _pmsParent->GetMalloc()->Free(BP_TO_P(CVectBits *, _avb));
+ _avb = P_TO_BP(CBasedVectBitsPtr, avb);
+ }
+
+ if (_amp != NULL)
+ {
+ // Initialize the new elements in the vector
+
+ for (ULONG iamp = _ulSize; iamp < ulSize; iamp++)
+ _amp[iamp] = NULL;
+ }
+
+ _ulSize = ulSize;
+
+ msfDebugOut((DEB_ITRACE,"Out CPagedVector resize constructor\n"));
+ return S_OK;
+}
+
+#ifndef REF
+//+-------------------------------------------------------------------------
+//
+// Method: CPagedVector::InitCopy, public
+//
+// Synopsis: CPagedVector Init function for copying
+//
+// Arguments: [vectOld] -- Reference to vector to be copied.
+//
+// Algorithm: *Finish This*
+//
+// History: 27-Oct-92 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifdef CODESEGMENTS
+#pragma code_seg(SEG_CPagedVector_InitCopy)
+#endif
+
+void VECT_CLASS CPagedVector::InitCopy(CPagedVector *pvectOld)
+{
+ msfDebugOut((DEB_ITRACE,"In CPagedVector copy constructor\n"));
+ SCODE sc;
+ USHORT i;
+
+ _pmsParent = pvectOld->_pmsParent;
+
+ CMSFPageTable *pmpt;
+ pmpt = _pmsParent->GetPageTable();
+ _pmpt = P_TO_BP(CBasedMSFPageTablePtr, pmpt);
+
+ _ulAllocSize = _ulSize = pvectOld->_ulSize;
+
+ if (_ulSize > 0)
+ {
+ CBasedMSFPagePtr* amp;
+ msfMem(amp = GetNewPageArray(_ulSize));
+ for (i = 0; i < _ulSize; i++)
+ {
+ amp[i] = NULL;
+ if (pvectOld->_amp != NULL)
+ {
+ _pmpt->CopyPage(this,
+ BP_TO_P(CMSFPage *, pvectOld->_amp[i]),
+ &(amp[i]));
+ }
+ }
+ _amp = P_TO_BP(CBasedMSFPagePtrPtr, amp);
+
+ CVectBits *avb;
+ msfMem(avb = GetNewVectBits(_ulSize));
+ if (pvectOld->_avb != NULL)
+ {
+ for (i = 0; i < _ulSize; i++)
+ {
+ avb[i] = ((CPagedVector *)pvectOld)->_avb[i];
+ }
+ }
+ _avb = P_TO_BP(CBasedVectBitsPtr, avb);
+ }
+
+ msfDebugOut((DEB_ITRACE,"Out CPagedVector copy constructor\n"));
+
+ //In the error case, keep whatever vectors we managed to allocate
+ // and return.
+Err:
+ return;
+}
+#endif //!REF
+
+
diff --git a/private/ole32/stg/msf/wep.cxx b/private/ole32/stg/msf/wep.cxx
new file mode 100644
index 000000000..03b4c4af5
--- /dev/null
+++ b/private/ole32/stg/msf/wep.cxx
@@ -0,0 +1,34 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: wep.cxx
+//
+// Contents: WEP function and cleanup code.
+//
+// Classes: None.
+//
+// Functions: WEP()
+// Cleanup()
+//
+// History: 10-Aug-92 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+#pragma hdrstop
+
+#include <dfdeb.hxx>
+
+
+#if defined(_M_I286)
+
+#define PASCAL _pascal
+extern "C" VOID FAR PASCAL _export WEP(BOOL fSystemExit)
+{
+ UNREFERENCED_PARM(fSystemExit);
+}
+
+#endif //_M_I286
diff --git a/private/ole32/stg/ofsstg/depend.mk b/private/ole32/stg/ofsstg/depend.mk
new file mode 100644
index 000000000..b24b6b3bc
--- /dev/null
+++ b/private/ole32/stg/ofsstg/depend.mk
@@ -0,0 +1,758 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\odirstg.obj $(OBJDIR)\odirstg.lst: .\odirstg.cxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ntenm.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\stgutil.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\ofsstg\ofsps.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\eprstg.h $(COMMONINC)\epsstg.h \
+ $(COMMONINC)\estatd.h $(COMMONINC)\estats.h $(COMMONINC)\estrng.h \
+ $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h \
+ $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h \
+ $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h $(COMMONINC)\prstg.h \
+ $(COMMONINC)\psstg.h $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h \
+ $(COMMONINC)\rot.h $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h \
+ $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h $(COMMONINC)\stream.h \
+ $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h $(COMMONINC)\varnt.h \
+ $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\limits.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\devioctl.h $(OSINC)\dlgs.h \
+ $(OSINC)\lint.hxx $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h \
+ $(OSINC)\mipsinst.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h \
+ $(OSINC)\ntalpha.h $(OSINC)\ntconfig.h $(OSINC)\ntdef.h \
+ $(OSINC)\ntelfapi.h $(OSINC)\ntexapi.h $(OSINC)\nti386.h \
+ $(OSINC)\ntimage.h $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h \
+ $(OSINC)\ntkeapi.h $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h \
+ $(OSINC)\ntmips.h $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h \
+ $(OSINC)\ntobapi.h $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h \
+ $(OSINC)\ntrtl.h $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h \
+ $(OSINC)\nturtl.h $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\headers.cxx .\odirstg.hxx \
+ .\odsenm.hxx .\ofilstg.hxx .\ostgsupp.hxx
+
+$(OBJDIR)\odsenm.obj $(OBJDIR)\odsenm.lst: .\odsenm.cxx \
+ $(CAIROLE)\stg\h\ptrcache.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ntenm.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\ofsstg\ofsps.hxx $(COMMON)\ih\types.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\basetyps.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\stream.h $(COMMONINC)\varnt.h $(COMMONINC)\wtypes.h \
+ $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h $(COMMONINC)\basetyps.h \
+ $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h $(COMMONINC)\cobjerr.h \
+ $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h $(COMMONINC)\disptype.h \
+ $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h $(COMMONINC)\emonkr.h \
+ $(COMMONINC)\estatd.h $(COMMONINC)\estats.h $(COMMONINC)\estrng.h \
+ $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h \
+ $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h \
+ $(COMMONINC)\prsist.h $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h \
+ $(COMMONINC)\rot.h $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h \
+ $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h $(COMMONINC)\stream.h \
+ $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h $(COMMONINC)\varnt.h \
+ $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h $(CRTINC)\limits.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OSINC)\lintfunc.hxx $(OSINC)\ntrtl.h \
+ $(OSINC)\rpc.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\devioctl.h $(OSINC)\dlgs.h \
+ $(OSINC)\lint.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntseapi.h \
+ $(OSINC)\ntstatus.h $(OSINC)\nturtl.h $(OSINC)\ntxcapi.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\headers.cxx \
+ .\odirstg.hxx .\odsenm.hxx .\ofilstg.hxx .\ostgsupp.hxx
+
+$(OBJDIR)\ofilstg.obj $(OBJDIR)\ofilstg.lst: .\ofilstg.cxx \
+ $(CAIROLE)\stg\h\filstm.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\stgutil.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\ofsstg\ofsps.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h \
+ $(COMMONINC)\efrmte.h $(COMMONINC)\estats.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\stream.h $(COMMONINC)\wtypes.h $(COMMONINC)\advsnk.h \
+ $(COMMONINC)\baseole.h $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h \
+ $(COMMONINC)\cguid.h $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h \
+ $(COMMONINC)\dispatch.h $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h \
+ $(COMMONINC)\efrmte.h $(COMMONINC)\emonkr.h $(COMMONINC)\eprstg.h \
+ $(COMMONINC)\epsstg.h $(COMMONINC)\estatd.h $(COMMONINC)\estats.h \
+ $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h \
+ $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h \
+ $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\prstg.h $(COMMONINC)\psstg.h $(COMMONINC)\pstrm.h \
+ $(COMMONINC)\querys.h $(COMMONINC)\rot.h $(COMMONINC)\scode.h \
+ $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h \
+ $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h \
+ $(COMMONINC)\varnt.h $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\limits.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\headers.cxx .\ofsenm.hxx .\odirstg.hxx \
+ .\ofilstg.hxx .\ostgsupp.hxx
+
+$(OBJDIR)\ofsenm.obj $(OBJDIR)\ofsenm.lst: .\ofsenm.cxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ntsupp.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ptrcache.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\stgstm.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\ofsstg\ofsps.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\basetyps.h $(COMMONINC)\wtypes.h \
+ $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h $(COMMONINC)\basetyps.h \
+ $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h $(COMMONINC)\cobjerr.h \
+ $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h $(COMMONINC)\disptype.h \
+ $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h $(COMMONINC)\emonkr.h \
+ $(COMMONINC)\estatd.h $(COMMONINC)\estats.h $(COMMONINC)\estrng.h \
+ $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h \
+ $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h \
+ $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h $(COMMONINC)\pstrm.h \
+ $(COMMONINC)\querys.h $(COMMONINC)\rot.h $(COMMONINC)\scode.h \
+ $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h \
+ $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h \
+ $(COMMONINC)\varnt.h $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\limits.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\headers.cxx .\odirstg.hxx .\ofilstg.hxx \
+ .\ofsenm.hxx .\ostgsupp.hxx
+
+$(OBJDIR)\ofscs.obj $(OBJDIR)\ofscs.lst: .\ofscs.cxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\STG\ofsstg\ofscs.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ntsupp.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ptrcache.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\stgstm.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\ofsstg\ofsps.hxx \
+ $(COMMON)\ih\ofsmrshl.h $(COMMON)\ih\ofsmsg.h \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\basetyps.h \
+ $(COMMONINC)\bndctx.h $(COMMONINC)\efrmte.h $(COMMONINC)\iofsprop.h \
+ $(COMMONINC)\prspec.h $(COMMONINC)\stream.h $(COMMONINC)\advsnk.h \
+ $(COMMONINC)\baseole.h $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h \
+ $(COMMONINC)\cguid.h $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h \
+ $(COMMONINC)\dispatch.h $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h \
+ $(COMMONINC)\efrmte.h $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h \
+ $(COMMONINC)\estats.h $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h \
+ $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h \
+ $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h \
+ $(COMMONINC)\prspec.h $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h \
+ $(COMMONINC)\rot.h $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h \
+ $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h $(COMMONINC)\stream.h \
+ $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h $(COMMONINC)\varnt.h \
+ $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h $(CRTINC)\excpt.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\limits.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OSINC)\rpc.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\headers.cxx .\odirstg.hxx .\ofilstg.hxx \
+ .\ostgsupp.hxx
+
+$(OBJDIR)\ostgsupp.obj $(OBJDIR)\ostgsupp.lst: .\ostgsupp.cxx \
+ $(CAIROLE)\stg\h\ntlkb.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\stgutil.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\ofsstg\ofsps.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\ofsmsg.h $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h $(COMMONINC)\estats.h \
+ $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h $(COMMONINC)\iofsprop.h \
+ $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h \
+ $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h \
+ $(COMMONINC)\prspec.h $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h \
+ $(COMMONINC)\rot.h $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h \
+ $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h $(COMMONINC)\stream.h \
+ $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h $(COMMONINC)\varnt.h \
+ $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h $(CRTINC)\limits.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OSINC)\lintfunc.hxx $(OSINC)\ntrtl.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h $(OSINC)\ntconfig.h \
+ $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h $(OSINC)\ntexapi.h \
+ $(OSINC)\nti386.h $(OSINC)\ntimage.h $(OSINC)\ntioapi.h \
+ $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h $(OSINC)\ntldr.h \
+ $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h $(OSINC)\ntmmapi.h \
+ $(OSINC)\ntnls.h $(OSINC)\ntobapi.h $(OSINC)\ntpsapi.h \
+ $(OSINC)\ntregapi.h $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h \
+ $(OSINC)\nturtl.h $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\headers.cxx .\ofscs.hxx \
+ .\prstg.hxx .\odirstg.hxx .\ofilstg.hxx .\ostgsupp.hxx
+
+$(OBJDIR)\ofsps.obj $(OBJDIR)\ofsps.lst: .\ofsps.cxx \
+ $(CAIROLE)\STG\ofsstg\ofspse.hxx $(CAIROLE)\STG\ofsstg\ofspstg.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ntsupp.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ptrcache.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\stgstm.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\ofsstg\ofsps.hxx \
+ $(COMMON)\ih\iofs.h $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h $(COMMONINC)\estats.h \
+ $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h $(COMMONINC)\iofsprop.h \
+ $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h \
+ $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h \
+ $(COMMONINC)\prspec.h $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h \
+ $(COMMONINC)\rot.h $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h \
+ $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h $(COMMONINC)\stream.h \
+ $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h $(COMMONINC)\varnt.h \
+ $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\limits.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\devioctl.h $(OSINC)\dlgs.h \
+ $(OSINC)\lint.hxx $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h \
+ $(OSINC)\mipsinst.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h \
+ $(OSINC)\ntalpha.h $(OSINC)\ntconfig.h $(OSINC)\ntdef.h \
+ $(OSINC)\ntelfapi.h $(OSINC)\ntexapi.h $(OSINC)\nti386.h \
+ $(OSINC)\ntimage.h $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h \
+ $(OSINC)\ntkeapi.h $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h \
+ $(OSINC)\ntmips.h $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h \
+ $(OSINC)\ntobapi.h $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h \
+ $(OSINC)\ntrtl.h $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h \
+ $(OSINC)\nturtl.h $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\headers.cxx .\odirstg.hxx \
+ .\ofilstg.hxx .\ostgsupp.hxx
+
+$(OBJDIR)\ofspse.obj $(OBJDIR)\ofspse.lst: .\ofspse.cxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ntsupp.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ptrcache.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\stgstm.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\ofsstg\ofsps.hxx \
+ $(CAIROLE)\STG\ofsstg\ofspse.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\except.hxx $(COMMON)\ih\iofs.h \
+ $(COMMON)\ih\otrack.hxx $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h \
+ $(COMMON)\ih\types.h $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h \
+ $(COMMON)\ih\win4p.h $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h \
+ $(COMMONINC)\baseole.h $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h \
+ $(COMMONINC)\cguid.h $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h \
+ $(COMMONINC)\dispatch.h $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h \
+ $(COMMONINC)\efrmte.h $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h \
+ $(COMMONINC)\estats.h $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h \
+ $(COMMONINC)\iofsprop.h $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h \
+ $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h \
+ $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h $(COMMONINC)\pstrm.h \
+ $(COMMONINC)\querys.h $(COMMONINC)\rot.h $(COMMONINC)\scode.h \
+ $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h \
+ $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h \
+ $(COMMONINC)\varnt.h $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\limits.h $(CRTINC)\memory.h $(CRTINC)\setjmp.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stddef.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\headers.cxx .\odirstg.hxx .\ofilstg.hxx \
+ .\ostgsupp.hxx
+
+$(OBJDIR)\ofspstg.obj $(OBJDIR)\ofspstg.lst: .\ofspstg.cxx \
+ $(CAIROLE)\stg\h\props.hxx $(CAIROLE)\STG\ofsstg\ofspenm.hxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\ofsstg\ofsps.hxx $(CAIROLE)\STG\ofsstg\ofspstg.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h $(COMMONINC)\estats.h \
+ $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h $(COMMONINC)\iofsprop.h \
+ $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h \
+ $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h \
+ $(COMMONINC)\prspec.h $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h \
+ $(COMMONINC)\rot.h $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h \
+ $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h $(COMMONINC)\stream.h \
+ $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h $(COMMONINC)\varnt.h \
+ $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\limits.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\devioctl.h $(OSINC)\dlgs.h \
+ $(OSINC)\lint.hxx $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h \
+ $(OSINC)\mipsinst.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h \
+ $(OSINC)\ntalpha.h $(OSINC)\ntconfig.h $(OSINC)\ntdef.h \
+ $(OSINC)\ntelfapi.h $(OSINC)\ntexapi.h $(OSINC)\nti386.h \
+ $(OSINC)\ntimage.h $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h \
+ $(OSINC)\ntkeapi.h $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h \
+ $(OSINC)\ntmips.h $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h \
+ $(OSINC)\ntobapi.h $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h \
+ $(OSINC)\ntrtl.h $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h \
+ $(OSINC)\nturtl.h $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\headers.cxx .\odirstg.hxx \
+ .\ofilstg.hxx .\ostgsupp.hxx
+
+$(OBJDIR)\ofspenm.obj $(OBJDIR)\ofspenm.lst: .\ofspenm.cxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\logfile.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\STG\ofsstg\ofspenm.hxx $(CAIROLE)\STG\ofsstg\ofsps.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h $(COMMONINC)\estats.h \
+ $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h $(COMMONINC)\iofsprop.h \
+ $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h \
+ $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h \
+ $(COMMONINC)\prspec.h $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h \
+ $(COMMONINC)\rot.h $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h \
+ $(COMMONINC)\stgprop.h $(COMMONINC)\storag.h $(COMMONINC)\stream.h \
+ $(COMMONINC)\unknwn.h $(COMMONINC)\valid.h $(COMMONINC)\varnt.h \
+ $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\limits.h \
+ $(CRTINC)\memory.h $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stddef.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\devioctl.h $(OSINC)\dlgs.h \
+ $(OSINC)\lint.hxx $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h \
+ $(OSINC)\mipsinst.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h \
+ $(OSINC)\ntalpha.h $(OSINC)\ntconfig.h $(OSINC)\ntdef.h \
+ $(OSINC)\ntelfapi.h $(OSINC)\ntexapi.h $(OSINC)\nti386.h \
+ $(OSINC)\ntimage.h $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h \
+ $(OSINC)\ntkeapi.h $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h \
+ $(OSINC)\ntmips.h $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h \
+ $(OSINC)\ntobapi.h $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h \
+ $(OSINC)\ntrtl.h $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h \
+ $(OSINC)\nturtl.h $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\headers.cxx .\odirstg.hxx \
+ .\ofilstg.hxx .\ostgsupp.hxx
+
+$(OBJDIR)\prstg.obj $(OBJDIR)\prstg.lst: .\prstg.cxx \
+ $(CAIROLE)\stg\h\cntxlist.hxx $(CAIROLE)\stg\h\cntxtid.hxx \
+ $(CAIROLE)\stg\h\context.hxx $(CAIROLE)\stg\h\df32.hxx \
+ $(CAIROLE)\stg\h\dfbasis.hxx $(CAIROLE)\stg\h\dfexcept.hxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\difat.hxx \
+ $(CAIROLE)\stg\h\dir.hxx $(CAIROLE)\stg\h\docfilep.hxx \
+ $(CAIROLE)\stg\h\entry.hxx $(CAIROLE)\stg\h\error.hxx \
+ $(CAIROLE)\stg\h\fat.hxx $(CAIROLE)\stg\h\filelkb.hxx \
+ $(CAIROLE)\stg\h\filest.hxx $(CAIROLE)\stg\h\freelist.hxx \
+ $(CAIROLE)\stg\h\funcs.hxx $(CAIROLE)\stg\h\header.hxx \
+ $(CAIROLE)\stg\h\msf.hxx $(CAIROLE)\stg\h\ntsupp.hxx \
+ $(CAIROLE)\stg\h\ole.hxx $(CAIROLE)\stg\h\page.hxx \
+ $(CAIROLE)\stg\h\ptrcache.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\safedecl.hxx $(CAIROLE)\stg\h\stgstm.hxx \
+ $(CAIROLE)\stg\h\storagep.h $(CAIROLE)\stg\h\vect.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(CAIROLE)\STG\ofsstg\ofsps.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h $(COMMONINC)\estats.h \
+ $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h \
+ $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h \
+ $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h $(COMMONINC)\rot.h \
+ $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h \
+ $(COMMONINC)\storag.h $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h \
+ $(COMMONINC)\valid.h $(COMMONINC)\varnt.h $(COMMONINC)\winole.h \
+ $(COMMONINC)\wtypes.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\limits.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\headers.cxx .\odirstg.hxx .\ofilstg.hxx \
+ .\ostgsupp.hxx .\prstg.hxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\headers.pxh $(PCHDIR)\$(OBJDIR)\headers.lst: \
+ $(CAIROLE)\stg\ofsstg\headers.cxx $(CAIROLE)\stg\h\cntxlist.hxx \
+ $(CAIROLE)\stg\h\cntxtid.hxx $(CAIROLE)\stg\h\context.hxx \
+ $(CAIROLE)\stg\h\df32.hxx $(CAIROLE)\stg\h\dfbasis.hxx \
+ $(CAIROLE)\stg\h\dfexcept.hxx $(CAIROLE)\stg\h\dfmem.hxx \
+ $(CAIROLE)\stg\h\dfmsp.hxx $(CAIROLE)\stg\h\dfname.hxx \
+ $(CAIROLE)\stg\h\difat.hxx $(CAIROLE)\stg\h\dir.hxx \
+ $(CAIROLE)\stg\h\docfilep.hxx $(CAIROLE)\stg\h\entry.hxx \
+ $(CAIROLE)\stg\h\error.hxx $(CAIROLE)\stg\h\fat.hxx \
+ $(CAIROLE)\stg\h\filelkb.hxx $(CAIROLE)\stg\h\filest.hxx \
+ $(CAIROLE)\stg\h\freelist.hxx $(CAIROLE)\stg\h\funcs.hxx \
+ $(CAIROLE)\stg\h\header.hxx $(CAIROLE)\stg\h\msf.hxx \
+ $(CAIROLE)\stg\h\ntsupp.hxx $(CAIROLE)\stg\h\ole.hxx \
+ $(CAIROLE)\stg\h\page.hxx $(CAIROLE)\stg\h\ptrcache.hxx \
+ $(CAIROLE)\stg\h\ref.hxx $(CAIROLE)\stg\h\safedecl.hxx \
+ $(CAIROLE)\stg\h\stgstm.hxx $(CAIROLE)\stg\h\storagep.h \
+ $(CAIROLE)\stg\h\vect.hxx $(CAIROLE)\stg\h\wchar.h \
+ $(CAIROLE)\stg\ofsstg\odirstg.hxx $(CAIROLE)\stg\ofsstg\ofilstg.hxx \
+ $(CAIROLE)\STG\ofsstg\ofsps.hxx $(CAIROLE)\stg\ofsstg\ostgsupp.hxx \
+ $(COMMON)\ih\dbgpoint.hxx $(COMMON)\ih\debnot.h \
+ $(COMMON)\ih\except.hxx $(COMMON)\ih\otrack.hxx \
+ $(COMMON)\ih\safepnt.hxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\types.hxx $(COMMON)\ih\types16.h $(COMMON)\ih\win4p.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\advsnk.h $(COMMONINC)\baseole.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\bndctx.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\efrmte.h \
+ $(COMMONINC)\emonkr.h $(COMMONINC)\estatd.h $(COMMONINC)\estats.h \
+ $(COMMONINC)\estrng.h $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h \
+ $(COMMONINC)\memalloc.h $(COMMONINC)\monikr.h $(COMMONINC)\ole2.h \
+ $(COMMONINC)\oletyp.h $(COMMONINC)\prsist.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\pstrm.h $(COMMONINC)\querys.h $(COMMONINC)\rot.h \
+ $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h \
+ $(COMMONINC)\storag.h $(COMMONINC)\stream.h $(COMMONINC)\unknwn.h \
+ $(COMMONINC)\valid.h $(COMMONINC)\varnt.h $(COMMONINC)\winole.h \
+ $(COMMONINC)\wtypes.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\limits.h $(CRTINC)\memory.h \
+ $(CRTINC)\setjmp.h $(CRTINC)\stdarg.h $(CRTINC)\stddef.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\devioctl.h $(OSINC)\dlgs.h $(OSINC)\lint.hxx \
+ $(OSINC)\lintfunc.hxx $(OSINC)\lzexpand.h $(OSINC)\mipsinst.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\nt.h $(OSINC)\ntalpha.h \
+ $(OSINC)\ntconfig.h $(OSINC)\ntdef.h $(OSINC)\ntelfapi.h \
+ $(OSINC)\ntexapi.h $(OSINC)\nti386.h $(OSINC)\ntimage.h \
+ $(OSINC)\ntioapi.h $(OSINC)\ntiolog.h $(OSINC)\ntkeapi.h \
+ $(OSINC)\ntldr.h $(OSINC)\ntlpcapi.h $(OSINC)\ntmips.h \
+ $(OSINC)\ntmmapi.h $(OSINC)\ntnls.h $(OSINC)\ntobapi.h \
+ $(OSINC)\ntpsapi.h $(OSINC)\ntregapi.h $(OSINC)\ntrtl.h \
+ $(OSINC)\ntseapi.h $(OSINC)\ntstatus.h $(OSINC)\nturtl.h \
+ $(OSINC)\ntxcapi.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
+.\$(OBJDIR)\odirstg.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\odsenm.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\ofilstg.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\ofsenm.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\ostgsupp.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\ofspenm.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\ofspstg.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\ofspse.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\prstg.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\ofscs.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\ofsps.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/ofsstg/dirs b/private/ole32/stg/ofsstg/dirs
new file mode 100644
index 000000000..f10ca67a3
--- /dev/null
+++ b/private/ole32/stg/ofsstg/dirs
@@ -0,0 +1,36 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+
diff --git a/private/ole32/stg/ofsstg/filelist.mk b/private/ole32/stg/ofsstg/filelist.mk
new file mode 100644
index 000000000..41e57ce96
--- /dev/null
+++ b/private/ole32/stg/ofsstg/filelist.mk
@@ -0,0 +1,28 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1993.
+# All rights reserved.
+#
+############################################################################
+
+
+TARGET = ofsstg.lib
+
+PXXFILE = .\headers.cxx
+
+CXXFILES = .\odirstg.cxx\
+ .\odsenm.cxx\
+ .\ofilstg.cxx\
+ .\ofsenm.cxx\
+ .\ostgsupp.cxx\
+ .\ofspenm.cxx\
+ .\ofspstg.cxx\
+ .\ofspse.cxx\
+ .\prstg.cxx\
+ .\ofscs.cxx\
+ .\ofsps.cxx
+
+LIBS = $(COMMON)\src\ofs\$(OBJDIR)\ofs.lib
+
+CINC = $(CINC) -I$(CAIROLE)\stg\h
diff --git a/private/ole32/stg/ofsstg/headers.cxx b/private/ole32/stg/ofsstg/headers.cxx
new file mode 100644
index 000000000..d42f531f3
--- /dev/null
+++ b/private/ole32/stg/ofsstg/headers.cxx
@@ -0,0 +1,50 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: headers.cxx
+//
+// Contents: Precompiled header file
+//
+// History: 02-Nov-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+}
+
+#if WIN32 != 300
+#include <compobj.h>
+#include <storage.h>
+#endif
+#ifdef _CAIRO_
+#define _CAIROSTG_
+#include <oleext.h>
+#endif
+#include <stgint.h>
+#include <oledb.h>
+
+#include <valid.h>
+#include <debnot.h>
+
+#include <otrack.hxx>
+
+#include <dfexcept.hxx>
+#include <dfmsp.hxx>
+#include <funcs.hxx>
+#include <docfilep.hxx>
+#include <ole.hxx>
+#include <safedecl.hxx>
+
+#include <infs.hxx>
+#include <stgstm.hxx>
+#include <ntsupp.hxx>
+#include <ptrcache.hxx>
+#include "odirstg.hxx"
+#include "ofilstg.hxx"
+#include "odocstg.hxx"
diff --git a/private/ole32/stg/ofsstg/makefile b/private/ole32/stg/ofsstg/makefile
new file mode 100644
index 000000000..b38db237d
--- /dev/null
+++ b/private/ole32/stg/ofsstg/makefile
@@ -0,0 +1,23 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1994.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+all:
+ echo $(BUILDMSG)
+
+clean: all
+
+!else
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/stg/ofsstg/odirdir.cxx b/private/ole32/stg/ofsstg/odirdir.cxx
new file mode 100644
index 000000000..cafef449c
--- /dev/null
+++ b/private/ole32/stg/ofsstg/odirdir.cxx
@@ -0,0 +1,1025 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995-1995.
+//
+// File: dirdir.cxx
+//
+// Contents: CDirectory implementation for OFS and FAT/NTFS
+//
+// Classes: CDirectory
+//
+// History: 19-Jun-95 HenryLee Created
+//
+// Notes: Requires NtIoApi.h
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <stgutil.hxx>
+#include <iofs.h>
+#include <odirdir.hxx>
+#include <odirstg.hxx>
+#include <filstm.hxx>
+#include <dfentry.hxx>
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::~COleDirectory
+//
+// Synopsis: Destroy the generic directory object.
+//
+// Arguments: none
+//
+//--------------------------------------------------------------------
+COleDirectory::~COleDirectory ()
+{
+ ssDebugOut((DEB_TRACE, "In COleDiretory::~COleDirectory\n"));
+ _sig = COFSDIRSTORAGE_SIGDEL;
+ ssDebugOut((DEB_TRACE, "Out COleDiretory::~COleDirectory\n"));
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::InitFromHandle
+//
+// Synopsis: Initialize a constructed COleDirectory object
+//
+// Arguments: handle file handle to duplicate
+// wcDrive drive letter
+// grfMode open option bit flags
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+SCODE COleDirectory::InitFromHandle (HANDLE handle,
+ const WCHAR *pwcsName,
+ DWORD grfMode)
+{
+ SCODE sc = S_OK;
+ ssDebugOut((DEB_TRACE, "In COleDiretory::InitFromHandle\n"));
+ _h = handle;
+ _grfMode = grfMode;
+ _sig = COFSDIRSTORAGE_SIG;
+ _wcDrive = GetDriveLetter (pwcsName);
+ ssDebugOut((DEB_TRACE, "Out COleDiretory::InitFromHandle\n"));
+ return ssResult(sc);
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::InitFromPath
+//
+// Synopsis: Initialize a constructed COleDirectory object
+//
+// Arguments: hParent parent handle for relative open
+// pwcsName name relative to the parent handle
+// grfMode open option bit flags
+// co create or open flag
+// psa initial security descriptor
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+SCODE COleDirectory::InitFromPath (HANDLE hParent,
+ const WCHAR *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSECURITY_ATTRIBUTES psa)
+{
+ SCODE sc = S_OK;
+ ssDebugOut((DEB_TRACE, "In COleDirectory::InitFromPath:%p("
+ "%p, %ws, %lX, %p)\n", this, hParent, pwcsName, grfMode, psa));
+
+ ssChk(ValidateMode(grfMode));
+ ssChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co, FD_DIR, psa, &_h));
+
+ _grfMode = grfMode;
+ _sig = COFSDIRSTORAGE_SIG;
+ _wcDrive = GetDriveLetter (pwcsName);
+ _fOfs = HandleRefersToOfsVolume (_h) == S_OK ? TRUE : FALSE;
+
+ ssDebugOut((DEB_TRACE, "Out COleDirectory::InitFromPath\n"));
+ EH_Err:
+ return ssResult(sc);
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::CreateElement
+//
+// Synopsis: create a child object in this directory
+// The child object is visible in the Win32 namespace
+//
+// Arguments: pwcsName name relative to the parent handle
+// stgcreate create options
+// stgopen open option bit flags
+// riid interface GUID of object to return
+// ppObject pointer to returned object
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+STDMETHODIMP COleDirectory::CreateElement (
+ /* [in] */ const WCHAR *pwcsName,
+ /* [in] */ STGCREATE *pStgCreate,
+ /* [in] */ STGOPEN *pStgOpen,
+ /* [in] */ REFIID riid,
+ /* [out] */ void **ppObjectOpen)
+{
+ SCODE sc = S_OK;
+ ssDebugOut((DEB_TRACE, "In COleDirectory::CreateElement:%p("
+ "%ws, %p, %p, %p)\n", this, pwcsName, pStgCreate,
+ pStgOpen, ppObjectOpen));
+
+ if (pStgCreate == NULL || pStgOpen == NULL)
+ ssErr (EH_Err, STG_E_INVALIDPOINTER);
+ if (pwcsName == NULL)
+ ssErr (EH_Err, STG_E_INVALIDNAME);
+
+ ssChk(Validate());
+ ssChk(ValidateStgfmt(pStgOpen->stgfmt, FALSE));
+ ssChk(ValidateOutPtrBuffer(ppObjectOpen));
+ *ppObjectOpen = NULL;
+ //BUGBUG need to convert security formats
+ ssAssert(_h != NULL);
+
+ if (pStgOpen->stgfmt==STGFMT_STORAGE ||
+ pStgOpen->stgfmt==STGFMT_DOCUMENT ||
+ pStgOpen->stgfmt==STGFMT_DOCFILE ||
+ pStgOpen->stgfmt==STGFMT_CATALOG )
+ {
+ SCODE scOfs = _fOfs ? S_OK : S_FALSE;
+ sc = InitStorage (_h, pwcsName, NULL,
+ CO_CREATE, pStgOpen, pStgCreate,
+ _wcDrive, &scOfs, FALSE, riid, ppObjectOpen);
+ }
+ else if (pStgOpen->stgfmt==STGFMT_DIRECTORY ||
+ pStgOpen->stgfmt==STGFMT_JUNCTION)
+ {
+ SCODE scOfs = _fOfs ? S_OK : S_FALSE;
+ ssChk(InitDirectory (_h, pwcsName, NULL,
+ CO_CREATE, pStgOpen, pStgCreate,
+ scOfs, riid, ppObjectOpen));
+ }
+ else if (pStgOpen->stgfmt==STGFMT_FILE)
+ {
+ CNtFileStream *pfs = new CNtFileStream();
+ ssMem((CNtFileStream *)pfs);
+
+ ssChk(pfs->InitFromPath (_h, pwcsName, pStgOpen->grfMode,
+ pStgCreate->grfAttrs, CO_CREATE, NULL));
+ sc = pfs->QueryInterface(riid, ppObjectOpen);
+ // success case, undo QI AddRef
+ pfs->Release(); // failure case, destroy obj
+ }
+ else ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+
+ ssDebugOut((DEB_TRACE, "Out COleDirectory::CreateElement => %p\n",
+ *ppObjectOpen));
+EH_Err:
+ return ssResult(sc);
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::OpenElement
+//
+// Synopsis: open a child object in this directory
+// The child object is visible in the Win32 namespace
+//
+// Arguments: pwcsName name relative to the parent handle
+// stgopen open option bit flags
+// riid interface GUID of object to return
+// pStgfmt storage format of ppObject
+// ppObject pointer to returned object
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+STDMETHODIMP COleDirectory::OpenElement (
+ /* [in] */ const WCHAR *pwcsName,
+ /* [in] */ STGOPEN *pStgOpen,
+ /* [in] */ REFIID riid,
+ /* [out] */ STGFMT * pStgfmt,
+ /* [out] */ void **ppObjectOpen)
+{
+ SCODE sc = S_OK;
+ DWORD dwStgfmt;
+ ssDebugOut((DEB_TRACE, "In COleDirectory::OpenElement:%p("
+ "%ws, %p, %p)\n", this, pwcsName, pStgOpen, ppObjectOpen));
+
+ if (pStgOpen == NULL || pStgfmt == NULL || ppObjectOpen == NULL)
+ ssErr (EH_Err, STG_E_INVALIDPOINTER);
+ if (pwcsName == NULL)
+ ssErr (EH_Err, STG_E_INVALIDNAME);
+
+ ssChk(Validate());
+ ssChk(ValidateStgfmt(pStgOpen->stgfmt, TRUE));
+ ssChk(ValidateOutPtrBuffer(ppObjectOpen));
+ *ppObjectOpen = NULL;
+ //BUGBUG need to convert security formats
+ ssAssert(_h != NULL);
+
+ *ppObjectOpen = NULL;
+ dwStgfmt = pStgOpen->stgfmt;
+ if (dwStgfmt==STGFMT_ANY)
+ {
+ HANDLE h = NULL;
+ ssChk(DetermineStgType(_h,pwcsName,pStgOpen->grfMode,&dwStgfmt,&h));
+ if (_fOfs && dwStgfmt == STGFMT_DOCUMENT && S_OK==DfIsDocfile(h))
+ dwStgfmt = STGFMT_DOCFILE;
+ if (h != NULL)
+ NTSTATUS nts = NtClose (h);
+ pStgOpen->stgfmt = (STGFMT) dwStgfmt;// BUGBUG changing input parameter
+ }
+ if (dwStgfmt==STGFMT_STORAGE ||
+ dwStgfmt==STGFMT_DOCUMENT ||
+ dwStgfmt==STGFMT_DOCFILE ||
+ dwStgfmt==STGFMT_CATALOG )
+ {
+ STGFMT stgfmtTemp = (STGFMT) dwStgfmt;
+ SCODE scOfs = _fOfs ? S_OK : S_FALSE;
+ sc = InitStorage (_h, pwcsName, NULL,
+ CO_OPEN, pStgOpen, NULL,
+ _wcDrive, &scOfs, FALSE, riid, ppObjectOpen);
+ if (pStgfmt != NULL)
+ *pStgfmt = stgfmtTemp;
+ }
+ else if (dwStgfmt == STGFMT_DIRECTORY ||
+ dwStgfmt == STGFMT_JUNCTION)
+ {
+ SCODE scOfs = _fOfs ? S_OK : S_FALSE;
+ ssChk(InitDirectory (_h, pwcsName, NULL,
+ CO_OPEN, pStgOpen, NULL,
+ scOfs, riid, ppObjectOpen));
+ if (pStgfmt != NULL)
+ *pStgfmt = (STGFMT) dwStgfmt;
+ }
+ else if (dwStgfmt == STGFMT_FILE)
+ {
+ CNtFileStream *pfs = new CNtFileStream();
+ ssMem((CNtFileStream *)pfs);
+
+ ssChk(pfs->InitFromPath(_h, pwcsName, pStgOpen->grfMode,
+ 0, CO_OPEN,NULL));
+ if (SUCCEEDED(sc = pfs->QueryInterface(riid, ppObjectOpen)))
+ {
+ if (pStgfmt != NULL)
+ *pStgfmt = STGFMT_FILE;
+ } // success case, undo QI AddRef
+ pfs->Release(); // failure case, destroy obj
+ }
+ else ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+
+EH_Err:
+ ssDebugOut((DEB_TRACE, "Out COleDirectory::CreateElement => %p %p\n",
+ *ppObjectOpen, pStgfmt));
+ return ssResult(sc);
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::MoveElement
+//
+// Synopsis: move or rename a directory element
+//
+// Arguments: pwcsName name relative to the parent handle
+// pDestDir destination directory
+// pwcsNewName new name
+// grfFlags move flags
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+STDMETHODIMP COleDirectory::MoveElement (
+ /* [in] */ const WCHAR *pwcsName,
+ /* [in] */ IDirectory *pDestDir,
+ /* [in] */ const WCHAR *pwcsNewName,
+ /* [in] */ DWORD grfFlags)
+{
+ SCODE sc = S_OK;
+ HANDLE h = NULL;
+
+ ssDebugOut((DEB_TRACE, "In COleDirectory::MoveElement:%p(%ws, %ws)\n",
+ this, pwcsName, pwcsNewName));
+ if (pwcsName == NULL)
+ ssErr (EH_Err, STG_E_INVALIDNAME);
+ if (grfFlags & ~(STGMOVE_MOVE|STGMOVE_COPY|STGMOVE_SHALLOWCOPY))
+ ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+ if (pDestDir == NULL && pwcsNewName == NULL)
+ ssErr (EH_Err, STG_E_INVALIDNAME);
+
+ if (pDestDir == NULL && (grfFlags & STGMOVE_COPY) == 0)
+ {
+ ssChk(Validate());
+ ssChk(CheckFdName(pwcsNewName));
+ ssAssert(_h != NULL);
+ // pwcsName is checked by GetFileOrDirHandle
+ sc = RenameChild(_h, pwcsName, pwcsNewName);
+ }
+ else
+ {
+ STATDIR statDir, statNewDir;
+ STGCREATE stgcreate = {0,0,0};
+ STGOPEN stgopen = {STGFMT_DIRECTORY, STGM_READ |
+ STGM_SHARE_DENY_WRITE, NULL};
+ STGOPEN stgopen2 = {STGFMT_DIRECTORY, STGM_CREATE |
+ STGM_READWRITE | STGM_SHARE_DENY_NONE , NULL};
+ STGFMT stgfmt2;
+ FILEDIR fd;
+ IDirectory *pIDir0, *pIDirDest;
+ IStorage *pIStg, *pIStgDest;
+ COleDirectory *pIDir;
+ DWORD stgfmt;
+
+ ssChk(GetFileOrDirHandle(_h, pwcsName, STGM_READ, &h, NULL, NULL, &fd));
+ ssChk(DetermineHandleStgType (h, fd, &stgfmt));
+ NTSTATUS nts = NtClose(h);
+
+ switch (stgfmt)
+ {
+ case STGFMT_FILE:
+ BOOL bOK;
+ WCHAR awcsToPath[_MAX_PATH], awcsFromPath[_MAX_PATH];
+ ULONG ulToPath;
+
+ ulToPath = (pwcsNewName != NULL) ? wcslen(pwcsNewName) :
+ wcslen(pwcsName);
+ if (pDestDir != NULL)
+ {
+
+ ssChk(StatElement(NULL, &statDir, STATFLAG_DEFAULT));
+ ssChk(pDestDir->StatElement(NULL, &statNewDir,
+ STATFLAG_DEFAULT));
+
+ if ((wcslen(statDir.pwcsName)+wcslen(pwcsName)+2) > _MAX_PATH
+ || (wcslen(statNewDir.pwcsName)+ulToPath+2) > _MAX_PATH)
+ {
+ ssVerSucc(CoMemFree(statDir.pwcsName));
+ ssVerSucc(CoMemFree(statNewDir.pwcsName));
+ ssErr (EH_Err, STG_E_INVALIDNAME);
+ }
+ wcscpy (awcsFromPath, statDir.pwcsName);
+ wcscat (awcsFromPath, L"\\");
+ wcscat (awcsFromPath, pwcsName);
+ wcscpy (awcsToPath, statNewDir.pwcsName);
+ wcscat (awcsToPath, L"\\");
+ wcscat (awcsToPath, (pwcsNewName!=NULL) ? pwcsNewName:pwcsName);
+ }
+ else
+ {
+ if ((wcslen(pwcsName) +1) > _MAX_PATH ||
+ (ulToPath + 2) > _MAX_PATH)
+ {
+ ssErr (EH_Err, STG_E_INVALIDNAME);
+ }
+ wcscpy (awcsFromPath, pwcsName);
+ wcscat (awcsToPath, (pwcsNewName!=NULL) ? pwcsNewName:pwcsName);
+ }
+
+ ssVerSucc(CoMemFree(statDir.pwcsName));
+ ssVerSucc(CoMemFree(statNewDir.pwcsName));
+
+ bOK = CopyFileW (awcsFromPath, awcsToPath, FALSE);
+ if(!(bOK))
+ ssErr (EH_Err, Win32ErrorToScode(GetLastError()));
+ break;
+ case STGFMT_DIRECTORY:
+ // if no new name given, move/copy the old name
+ if (pwcsNewName == NULL)
+ pwcsNewName = pwcsName;
+ // if the destination directory is null, use the source
+ ssChk( ((pDestDir == NULL) ? this : pDestDir)->
+ CreateElement(pwcsNewName, &stgcreate, &stgopen2,
+ IID_IDirectory, (void **) &pIDirDest));
+ // if this is deep copy, then we enumerate & recurse
+ if ((grfFlags & STGMOVE_SHALLOWCOPY) == 0)
+ {
+ IEnumSTATDIR *penum;
+ STATDIR stat;
+ ssChkTo(EH_Release, OpenElement(pwcsName, &stgopen,
+ IID_IDirectory, &stgfmt2, (void **) &pIDir));
+ if (SUCCEEDED(sc = pIDir->EnumDirectoryElements(&penum)))
+ {
+ while ((sc = penum->Next(1, &stat, NULL)) == S_OK)
+ {
+ sc = pIDir->MoveElement(stat.pwcsName, pIDirDest,
+ NULL, grfFlags);
+ if (stat.pwcsName)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ if (!SUCCEEDED(sc)) break;
+ }
+ penum->Release();
+ if (sc == S_FALSE)
+ sc = S_OK;
+ }
+ // BUGBUG when storages properly enum OLE namespace
+ // turn this function on
+ //sc = pIDir->MoveEmbeddings (pIDirDest, STGMOVE_COPY);
+ pIDir->Release();
+ }
+ EH_Release:
+ pIDirDest->Release();
+ break;
+ case STGFMT_DOCUMENT:
+ case STGFMT_DOCFILE:
+ case STGFMT_STORAGE:
+ case STGFMT_CATALOG:
+ stgopen.stgfmt = (STGFMT) stgfmt;
+ if (pwcsNewName == NULL)
+ pwcsNewName = pwcsName;
+ ssChk(OpenElement(pwcsName, &stgopen,
+ IID_IStorage, &stgfmt2, (void **) &pIStg));
+
+ stgopen2.stgfmt = stgfmt2;
+ stgopen2.grfMode = STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE;
+ ssChkTo(EH_Storage, ((pDestDir == NULL) ? this : pDestDir)->
+ CreateElement(pwcsNewName, &stgcreate, &stgopen2,
+ IID_IStorage, (void **) &pIStgDest));
+ sc = pIStg->CopyTo(0, NULL, NULL, pIStgDest);
+ pIStgDest->Release();
+ EH_Storage:
+ pIStg->Release();
+ break;
+ default:
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+ };
+
+ if (grfFlags & STGMOVE_MOVE)
+ {
+ ssChk(DeleteElement (pwcsName));
+ }
+ }
+EH_Err:
+ ssDebugOut((DEB_TRACE, "Out COleDireectory::MoveElement\n"));
+ return ssResult(sc);
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::MoveEmbeddings
+//
+// Synopsis: Move or Copy all embeddings on a directory
+//
+// Arguments: grfCommitFlags commit flags
+//
+// Notes: both source and destination must support IStorage
+//
+//+-------------------------------------------------------------------
+SCODE COleDirectory::MoveEmbeddings (IDirectory *pdirDest, DWORD grfFlags)
+{
+ SCODE sc;
+ IStorage *pIStg, *pIStgDest;
+ DWORD dwFlags = grfFlags == STGMOVE_MOVE ? STGMOVE_MOVE : STGMOVE_COPY;
+ if (SUCCEEDED(sc = QueryInterface(IID_IStorage, (void **) &pIStg)))
+ {
+ if (SUCCEEDED(sc=pdirDest->QueryInterface(IID_IStorage,
+ (void **) &pIStgDest)))
+ {
+ IEnumSTATSTG *pIEnumStatStg;
+ STATSTG statstg;
+ if (SUCCEEDED(sc = pIStg->EnumElements(NULL, NULL,
+ NULL, &pIEnumStatStg)))
+ {
+ while ((sc = pIEnumStatStg->Next(1,&statstg,NULL)) == S_OK)
+ {
+ sc = pIStg->MoveElementTo(statstg.pwcsName,
+ pIStgDest, statstg.pwcsName, dwFlags);
+ if (statstg.pwcsName)
+ ssVerSucc(CoMemFree(statstg.pwcsName));
+ if (!SUCCEEDED(sc))
+ break;
+ }
+ pIEnumStatStg->Release();
+ if (sc == S_FALSE)
+ sc = S_OK;
+ }
+ pIStgDest->Release();
+ }
+ pIStg->Release();
+ }
+
+ // if either source or destination does not support IStorage
+ // we do not copy any embeddings and return S_OK
+ if (sc == E_NOINTERFACE) sc = S_OK;
+ return sc;
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::CommitDirectory
+//
+// Synopsis: commit a direction transaction, no-op for direct mode
+//
+// Arguments: grfCommitFlags commit flags
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+STDMETHODIMP COleDirectory::CommitDirectory(
+ /* [in] */ DWORD grfCommitFlags)
+{
+ SCODE sc = S_OK;
+ ssDebugOut((DEB_TRACE, "In COleDiretory::CommitDirectory\n"));
+ if (grfCommitFlags & ~(STGC_DEFAULT))
+ ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+EH_Err:
+ ssDebugOut((DEB_TRACE, "Out COleDiretory::CommitDirectory\n"));
+ return ssResult(sc);
+};
+
+STDMETHODIMP COleDirectory::RevertDirectory ()
+{
+ SCODE sc = S_OK;
+ ssDebugOut((DEB_TRACE, "In COleDiretory::RevertDirectory\n"));
+ ssDebugOut((DEB_TRACE, "Out COleDiretory::RevertDirectory\n"));
+ return ssResult(sc);
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::DeleteElement
+//
+// Synopsis: delete a directory element, if possible
+//
+// Arguments:
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+STDMETHODIMP COleDirectory::DeleteElement (
+ /* [in] */ const WCHAR *pwcsName)
+{
+ SCODE sc = S_OK;
+
+ ssDebugOut((DEB_TRACE, "In COleDirectory::DestroyElement:%p(%ws)\n",
+ this, pwcsName));
+
+ if (pwcsName == NULL)
+ ssErr (EH_Err, STG_E_INVALIDNAME);
+ ssChk(Validate());
+
+ ssChk(CheckFdName(pwcsName));
+ ssAssert(_h != NULL);
+ sc = DestroyTree(_h, pwcsName, NULL, FD_FILE); //non-recursive
+
+ ssDebugOut((DEB_TRACE, "Out COleDirectory::DestroyElement\n"));
+EH_Err:
+ return ssResult(sc);
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::SetTimes
+//
+// Synopsis: set change, modification, and access times
+//
+// Arguments:
+//
+// Notes: renamed from SetElementTimes, IStorage conflict
+//
+//--------------------------------------------------------------------
+STDMETHODIMP COleDirectory::SetTimes(
+ /* [in] */ const WCHAR *pwcsName,
+ /* [in] */ const FILETIME *pctime,
+ /* [in] */ const FILETIME *patime,
+ /* [in] */ const FILETIME *pmtime)
+{
+ SCODE sc = S_OK;
+ HANDLE h = _h;
+ FILEDIR fd = FD_DIR;
+
+ ssDebugOut((DEB_TRACE, "In COleDirectory::SetElementTimes:%p("
+ "%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime));
+
+ ssChk(Validate());
+
+ ssAssert(_h != NULL);
+ if (pwcsName != NULL)
+ ssChk(GetFileOrDirHandle(_h, pwcsName, STGM_WRITE, &h, NULL,NULL, &fd));
+
+ sc = ::SetTimes(h, pctime, patime, pmtime);
+
+EH_Err:
+ if (pwcsName != NULL && h != _h)
+ NTSTATUS nts = NtClose(h);
+ ssDebugOut((DEB_TRACE, "Out COleDirectory::SetElementTimes\n"));
+ return ssResult(sc);
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::SetDirectoryClass
+//
+// Synopsis: set the clsid
+//
+// Arguments: [clsid] the class GUID of this directory
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+STDMETHODIMP COleDirectory::SetDirectoryClass(
+ /* [in] */ REFCLSID clsid)
+{
+ SCODE sc = S_OK;
+ NTSTATUS nts = ERROR_SUCCESS;
+ olDebugOut((DEB_TRACE,"In COleDirectory::SetDirectoryClass:%p(clsid %p)\n",
+ this, &clsid));
+ if (_fOfs)
+ {
+ NTSTATUS nts = RtlSetClassId(_h, &clsid);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode (nts);
+ }
+ else
+ {
+ IO_STATUS_BLOCK iosb;
+ HANDLE h = NULL;
+ if (SUCCEEDED( sc = GetNtHandle (_h, CLSID_FILENAME,
+ STGM_WRITE | STGM_CREATE, FILE_ATTRIBUTE_HIDDEN,
+ CO_CREATE, FD_FILE, NULL, &h)))
+ {
+ nts = NtWriteFile (h, NULL, NULL, NULL, &iosb, (void *) &clsid,
+ sizeof(clsid), NULL, NULL);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode (nts);
+ if (h != NULL)
+ nts = NtClose(h);
+ }
+ }
+//EH_Err:
+ olDebugOut((DEB_TRACE, "Out COleDirectory::SetDirectoryClass => %lX\n",sc));
+ return ssResult(sc);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::GetDirectoryClass
+//
+// Synopsis: set the clsid
+//
+// Arguments: [clsid] the class GUID of this directory
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+SCODE COleDirectory::GetDirectoryClass (HANDLE h, CLSID *pclsid)
+{
+ SCODE sc = S_OK;
+ NTSTATUS nts = ERROR_SUCCESS;
+ HANDLE hHidden = NULL;
+ olDebugOut((DEB_TRACE,"In COleDirectory::GetDirectoryClass:%p(clsid %p)\n",
+ this, pclsid));
+ *pclsid = CLSID_NULL;
+ if (!_fOfs)
+ {
+ IO_STATUS_BLOCK iosb;
+ HANDLE h = NULL;
+ if (SUCCEEDED( sc = GetNtHandle ((h == NULL ? _h : h), CLSID_FILENAME,
+ STGM_READ, 0, CO_OPEN, FD_FILE, NULL, &hHidden)))
+ {
+ nts = NtReadFile (hHidden, NULL, NULL, NULL, &iosb, (void *)pclsid,
+ sizeof(*pclsid), NULL, NULL);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode (nts);
+ if (hHidden != NULL)
+ nts = NtClose(hHidden);
+ if (iosb.Information < sizeof(*pclsid))
+ sc = STG_E_READFAULT;
+ }
+ }
+//EH_Err:
+ olDebugOut((DEB_TRACE, "Out COleDirectory::GetDirectoryClass => %lX\n",sc));
+ return ssResult(sc);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::SetAttributes
+//
+// Synopsis: set a file's attributes
+//
+// Arguments:
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+STDMETHODIMP COleDirectory::SetAttributes(
+ /* [in] */ const WCHAR *pwcsName,
+ /* [in] */ DWORD grfAttrs)
+{
+ SCODE sc = S_OK;
+ HANDLE h = _h;
+ FILEDIR fd = FD_DIR;
+ ssDebugOut((DEB_TRACE, "In COleDiretory::SetAttributes\n"));
+
+ ssAssert(_h != NULL);
+ if (pwcsName != NULL)
+ ssChk(GetFileOrDirHandle(_h, pwcsName, STGM_WRITE, &h, NULL,NULL, &fd));
+
+ sc = SetNtFileAttributes (h, grfAttrs);
+
+EH_Err:
+ if (pwcsName != NULL && h != _h)
+ NTSTATUS nts = NtClose(h);
+ ssDebugOut((DEB_TRACE, "Out COleDiretory::SetAttributes\n"));
+ return ssResult(sc);
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::StatElement
+//
+// Synopsis: retrieve information about a directory or element
+//
+// Arguments:
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+STDMETHODIMP COleDirectory::StatElement(
+ /* [in] */ const WCHAR *pwcsName,
+ /* [out] */ STATDIR *pstatdir,
+ /* [in] */ DWORD grfStatFlag)
+{
+ SCODE sc = S_OK;
+ HANDLE h = _h;
+ STATSTG stat;
+ FILEDIR fd;
+ NTSTATUS nts;
+
+ ssDebugOut((DEB_TRACE, "In COleDiretory::StatElement\n"));
+ if (pstatdir == NULL)
+ ssErr (EH_Err, STG_E_INVALIDPOINTER);
+ if (grfStatFlag & ~(STATFLAG_DEFAULT|STATFLAG_NONAME|STATFLAG_NOOPEN))
+ ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+
+ ssChk(VerifyStatFlag(grfStatFlag));
+ ssChk(Validate());
+
+ if (pwcsName != NULL)
+ ssChk(GetFileOrDirHandle(_h, pwcsName, STGM_READ, &h, NULL,NULL, &fd));
+
+ __try
+ {
+ DWORD grfAttrs;
+ ssAssert(h != NULL);
+ sc = StatNtHandle(h, grfStatFlag, 0, &stat, NULL, &grfAttrs, &fd);
+ if (SUCCEEDED(sc))
+ {
+ sc = SetDriveLetter (stat.pwcsName, _wcDrive);
+ if (SUCCEEDED(sc))
+ {
+ stat.grfMode = _grfMode;
+ stat.cbSize.HighPart = stat.cbSize.LowPart = 0;
+ pstatdir->pwcsName = stat.pwcsName;
+ pstatdir->atime = stat.atime;
+ pstatdir->ctime = stat.ctime;
+ pstatdir->mtime = stat.mtime;
+ pstatdir->grfMode = stat.grfMode;
+ pstatdir->grfStateBits = stat.grfStateBits;
+ pstatdir->clsid = stat.clsid;
+ if (_fOfs)
+ pstatdir->clsid = stat.clsid;
+ else
+ GetDirectoryClass (h, &pstatdir->clsid);
+ pstatdir->cbSize = stat.cbSize;
+ pstatdir->stgfmt = (STGFMT) stat.STATSTG_dwStgFmt;
+ pstatdir->grfAttrs = grfAttrs;
+ }
+ else if (stat.pwcsName)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (stat.pwcsName != NULL)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ sc = HRESULT_FROM_NT(GetExceptionCode());
+ }
+
+EH_Err:
+ if (pwcsName != NULL && h != _h)
+ nts = NtClose(h);
+ ssDebugOut((DEB_TRACE, "Out COleDiretory::StatElement\n"));
+ return ssResult(sc);
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::EnumDirectoryElements
+//
+// Synopsis: enumerate child elements
+//
+// Arguments:
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+STDMETHODIMP COleDirectory::EnumDirectoryElements(
+ /* [out] */ IEnumSTATDIR **ppenum)
+{
+ SCODE sc = S_OK;
+ SafeCEnumSTATDIR pde;
+
+ olDebugOut((DEB_TRACE, "In COleDirectory::EnumElements:%p(%p)\n", this,
+ ppenum));
+
+ if (ppenum == NULL)
+ ssErr (EH_Err, STG_E_INVALIDPOINTER) // missing ';' macro problem
+ else
+ ssChk(ValidateOutPtrBuffer(ppenum));
+ *ppenum = NULL;
+ olChk(Validate());
+
+ pde.Attach(new CEnumSTATDIR(_fOfs));
+ olMem((CEnumSTATDIR *)pde);
+ olAssert(_h != NULL);
+ olChk(pde->InitFromHandle(_h));
+ TRANSFER_INTERFACE(pde, IEnumSTATDIR, ppenum);
+
+ olDebugOut((DEB_TRACE, "Out COleDirectory::EnumElements => %p\n",
+ *ppenum));
+EH_Err:
+ return ssResult(sc);
+};
+
+//+---------------------------------------------------------------------------
+//
+// Class: CEnumSTATDIR
+//
+// Purpose: Implements IEnumSTATDIR for Win32 directories
+//
+// Interface: See below
+//
+//----------------------------------------------------------------------------
+
+CEnumSTATDIR::~CEnumSTATDIR ()
+{
+ ssDebugOut((DEB_TRACE, "In CEnumSTATDIR::~CEnumSTATDIR\n"));
+ m_sig = CENUMSTATDIR_SIGDEL;
+ ssDebugOut((DEB_TRACE, "Out CEnumSTATDIR::~CEnumSTATDIR\n"));
+};
+
+STDMETHODIMP CEnumSTATDIR::Next (
+ /* [in] */ ULONG celt,
+ /* [in] */ STATDIR *rgelt,
+ /* [out] */ ULONG *pceltFetched)
+{
+ SCODE sc = S_OK;
+ STATDIR *pelt = rgelt;
+ STATSTG stat;
+ ULONG celtDone;
+ FILEDIR fd;
+ CPtrCache pc;
+ WCHAR *pwcs;
+
+ ssDebugOut((DEB_TRACE, "In CEnumSTATDIR::Next\n"));
+ if (pceltFetched == NULL && celt > 1)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+
+ __try
+ {
+ for (celtDone = 0; pelt<rgelt+celt; pelt++, celtDone++)
+ {
+ if (m_fOfs)
+ sc = m_nte.NextOfs(&stat, NULL, NTE_STATNAME, &fd);
+ else
+ sc = m_nte.Next(&stat, NULL, NTE_STATNAME, &fd);
+
+ if (FAILED(sc) || sc == S_FALSE)
+ break;
+ if (FAILED(sc = pc.Add(stat.pwcsName)))
+ break;
+ pelt->pwcsName = stat.pwcsName;
+ pelt->atime = stat.atime;
+ pelt->ctime = stat.ctime;
+ pelt->mtime = stat.mtime;
+ pelt->grfMode = stat.grfMode;
+ pelt->grfStateBits = stat.grfStateBits;
+ pelt->clsid = stat.clsid;
+ pelt->cbSize = stat.cbSize;
+ pelt->stgfmt = (STGFMT) stat.STATSTG_dwStgFmt;
+ pelt->grfAttrs = 0;
+ }
+
+ if (SUCCEEDED(sc) && pceltFetched)
+ *pceltFetched = celtDone;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ pc.StartEnum();
+ while (pc.Next((void **)&pwcs))
+ ssHVerSucc(CoMemFree(pwcs));
+ sc = HRESULT_FROM_NT(GetExceptionCode());
+ // BUGBUG are we freeing twice?
+ }
+EH_Err:
+ if (FAILED(sc))
+ {
+ pc.StartEnum();
+ while (pc.Next((void **)&pwcs))
+ ssHVerSucc(CoMemFree(pwcs));
+ }
+ ssDebugOut((DEB_TRACE, "Out CEnumSTATDIR::Next\n"));
+ return ssResult(sc);
+};
+
+STDMETHODIMP CEnumSTATDIR::Skip (
+ /* [in] */ ULONG celt)
+{
+ SCODE sc = S_OK;
+ STATSTG stat; // dummy buffer
+ FILEDIR fd;
+
+ ssDebugOut((DEB_TRACE, "In CEnumSTATDIR::Skip (%p,%lu)\n",this,celt));
+ ssChk(Validate());
+
+ while (celt-- > 0)
+ {
+ sc = m_nte.Next(&stat, NULL, NTE_NONAME, &fd);
+ if (FAILED(sc) || sc == S_FALSE)
+ break;
+ }
+EH_Err:
+ ssDebugOut((DEB_TRACE, "Out CEnumSTATDIR::Skip\n"));
+ return ssResult(sc);
+};
+
+STDMETHODIMP CEnumSTATDIR::Reset()
+{
+ SCODE sc = S_OK;
+ ssDebugOut((DEB_TRACE, "In CEnumSTATDIR::Reset\n"));
+ ssChk(Validate());
+ m_nte.Reset();
+EH_Err:
+ ssDebugOut((DEB_TRACE, "Out CEnumSTATDIR::Reset\n"));
+ return ssResult(sc);
+};
+
+STDMETHODIMP CEnumSTATDIR::Clone (
+ /* [out] */ IEnumSTATDIR **ppenum)
+{
+ SCODE sc = S_OK;
+ SafeCEnumSTATDIR pde;
+
+ ssDebugOut((DEB_TRACE, "In CEnumSTATDIR::Clone\n"));
+
+ ssChk(Validate());
+
+ pde.Attach(new CEnumSTATDIR(m_fOfs));
+ ssMem((CEnumSTATDIR *)pde);
+ ssChk(pde->InitFromHandle(m_nte.GetHandle()));
+ TRANSFER_INTERFACE(pde, IEnumSTATDIR, ppenum);
+ // BUGBUG need to allow multiple enumerators
+
+EH_Err:
+ ssDebugOut((DEB_TRACE, "Out CEnumSTATDIR::Clone (%p)\n", ppenum));
+ return ssResult(sc);
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CEnumSTATDIR::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 28-Jun-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CEnumSTATDIR::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In CEnumSTATDIR::QueryInterface:%p(riid, %p)\n",
+ this, ppvObj));
+ if (!IsValidIid(iid))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+ if (IsEqualIID(iid, IID_IEnumSTATDIR) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IEnumSTATDIR *)this;
+ CEnumSTATDIR::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppvObj = NULL;
+ }
+ ssDebugOut((DEB_TRACE, "Out CEnumSTATDIR::QueryInterface => %p\n",
+ *ppvObj));
+ EH_Err:
+ return ssResult(sc);
+}
diff --git a/private/ole32/stg/ofsstg/odirdir.hxx b/private/ole32/stg/ofsstg/odirdir.hxx
new file mode 100644
index 000000000..c4f61351a
--- /dev/null
+++ b/private/ole32/stg/ofsstg/odirdir.hxx
@@ -0,0 +1,305 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1995.
+//
+// File: dirdir.hxx
+//
+// Contents: COleDirectory header
+//
+// Classes: COleDirectory
+//
+// History: 19-Jun-95 HenryLee Created
+//
+// Notes: Requires NtIoApi.h
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DIRECTRY_HXX__
+#define __DIRECTRY_HXX__
+
+#ifndef _CAIROSTG_
+#define _CAIROSTG_
+#endif
+#include <oleext.h>
+#include <ntenm.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: COleDirectory
+//
+// Purpose: Implements IDirectory for Win32 directories
+// (as opposed to IStorage for Win32 directories)
+//
+// Interface: See below
+//
+//----------------------------------------------------------------------------
+
+class COleDirectory : public IDirectory
+{
+public:
+ inline COleDirectory (BOOL fOfs = STG_E_INVALIDFLAG);
+ ~COleDirectory ();
+
+ // IDirectory
+ STDMETHOD(CreateElement) (
+ /* [in] */ const WCHAR *pwcsName,
+ /* [in] */ STGCREATE *pStgCreate,
+ /* [in] */ STGOPEN *pStgOpen,
+ /* [in] */ REFIID riid,
+ /* [out] */ void **ppObjectCreated);
+
+ STDMETHOD(OpenElement) (
+ /* [in] */ const WCHAR *pwcsName,
+ /* [in] */ STGOPEN *pStgOpen,
+ /* [in] */ REFIID riid,
+ /* [out] */ STGFMT *pStgfmt,
+ /* [out] */ void **ppObjectOpened);
+
+ STDMETHOD(MoveElement) (
+ /* [in] */ const WCHAR *pwcsName,
+ /* [in] */ IDirectory *pdirDest,
+ /* [in] */ const WCHAR *pwcsNewName,
+ /* [in] */ DWORD grfFlags);
+
+ STDMETHOD(CommitDirectory)(
+ /* [in] */ DWORD grfCommitFlags);
+
+ STDMETHOD(RevertDirectory) ();
+
+ STDMETHOD(DeleteElement) (
+ /* [in] */ const WCHAR *pwcsName);
+
+ STDMETHOD(SetTimes)(
+ /* [in] */ const WCHAR *pwcsName,
+ /* [in] */ const FILETIME *pctime,
+ /* [in] */ const FILETIME *patime,
+ /* [in] */ const FILETIME *pmtime);
+
+ STDMETHOD(SetDirectoryClass)(
+ /* [in] */ REFCLSID clsid);
+
+ STDMETHOD(SetAttributes)(
+ /* [in] */ const WCHAR *pwcsName,
+ /* [in] */ DWORD grfAttrs);
+
+ STDMETHOD(StatElement)(
+ /* [in] */ const WCHAR *pwcsName,
+ /* [out] */ STATDIR *pstatdir,
+ /* [in] */ DWORD grfStatFlag);
+
+ STDMETHOD(EnumDirectoryElements)(
+ /* [out] */ IEnumSTATDIR **ppenum);
+
+ SCODE InitFromHandle (HANDLE handle,const WCHAR *pwcsName,DWORD grfMode);
+ SCODE InitFromPath (HANDLE hParent, const WCHAR *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co, LPSECURITY_ATTRIBUTES psa);
+protected:
+ NuSafeNtHandle _h; // NT file handle
+ WCHAR _wcDrive; // Drive letter
+ DWORD _grfMode; // Open mode
+ BOOL _fOfs; // Flag special code for OFS directories
+ ULONG _sig; // Detect data corruption
+
+private:
+ SCODE MoveEmbeddings (IDirectory *pdirDest, DWORD grfFlags);
+ SCODE GetDirectoryClass (HANDLE h, CLSID *pclsid);
+ inline SCODE Validate() const;
+ inline SCODE ValidateMode (DWORD grfMode) const;
+ inline SCODE ValidateStgfmt(STGFMT dwStgfmt, BOOL fAny) const;
+};
+
+SAFE_INTERFACE_PTR(SafeCOleDirectory, COleDirectory);
+
+#define COFSDIRSTORAGE_SIG LONGSIG('O', 'D', 'S', 'G')
+#define COFSDIRSTORAGE_SIGDEL LONGSIG('O', 'd', 'S', 'g')
+
+//+-------------------------------------------------------------------
+//
+// Member: COleDirectory::COleDirectory
+//
+// Synopsis: Initialize the generic directory object.
+//
+// Arguments: none
+//
+//--------------------------------------------------------------------
+
+inline COleDirectory::COleDirectory(BOOL fOfs) :
+ _h(NULL),
+ _wcDrive(0),
+ _grfMode(0),
+ _fOfs(fOfs),
+ _sig(COFSDIRSTORAGE_SIGDEL)
+{
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COleDirectory::Validate, private
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 24-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE COleDirectory::Validate() const
+{
+ return (this == NULL || _sig != COFSDIRSTORAGE_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COleDirectory::ValidateMode, private
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDFLAG for failure
+//
+// History: 24-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE COleDirectory::ValidateMode(DWORD grfMode) const
+{
+ if (grfMode & (STGM_TRANSACTED | STGM_CONVERT | STGM_PRIORITY))
+ return STG_E_INVALIDFLAG;
+ else
+ return S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COleDirectory::ValidateStgfmt, private
+//
+// Synopsis: Validates the input storage format
+//
+// Returns: Returns STG_E_INVALIDFLAG for failure
+//
+// History: 24-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE COleDirectory::ValidateStgfmt (STGFMT stgfmt, BOOL fAny) const
+{
+ switch (stgfmt)
+ {
+ case STGFMT_DOCUMENT:
+ case STGFMT_DIRECTORY:
+ case STGFMT_CATALOG:
+ case STGFMT_FILE:
+ case STGFMT_DOCFILE:
+ case STGFMT_STORAGE:
+ return S_OK;
+ case STGFMT_ANY:
+ if (fAny)
+ return S_OK;
+ else
+ return STG_E_INVALIDFLAG;
+ default:
+ return STG_E_INVALIDFLAG;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Class: CEnumSTATDIR
+//
+// Purpose: Implements IEnumSTATDIR for Win32 directories
+//
+// Interface: See below
+//
+//----------------------------------------------------------------------------
+
+class CEnumSTATDIR : public IEnumSTATDIR, INHERIT_TRACKING
+{
+public:
+ inline CEnumSTATDIR (BOOL fOfs);
+ ~CEnumSTATDIR ();
+ inline SCODE InitFromHandle (HANDLE h);
+
+ STDMETHOD(Next) (
+ /* [in] */ ULONG celt,
+ /* [in] */ STATDIR *rgelt,
+ /* [out] */ ULONG *pceltFetched);
+
+ STDMETHOD(Skip) (
+ /* [in] */ ULONG celt);
+
+ STDMETHOD(Reset)();
+
+ STDMETHOD(Clone) (
+ /* [out] */ IEnumSTATDIR **ppenum);
+
+ STDMETHOD(QueryInterface) (REFIID riid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+private:
+ inline SCODE Validate() const;
+
+ ULONG m_sig;
+ CNtEnum m_nte;
+ BOOL m_fOfs;
+};
+
+SAFE_INTERFACE_PTR(SafeCEnumSTATDIR, CEnumSTATDIR);
+
+#define CENUMSTATDIR_SIG LONGSIG('C', 'D', 'E', 'N')
+#define CENUMSTATDIR_SIGDEL LONGSIG('C', 'd', 'E', 'N')
+
+//+--------------------------------------------------------------
+//
+// Member: CEnumSTATDIR::CEnumSTATDIR public
+//
+// Synopsis: default constructor
+//
+// Returns:
+//
+// History: 09-Jul-95 HenryLee Created
+//
+//---------------------------------------------------------------
+inline CEnumSTATDIR::CEnumSTATDIR (BOOL fOfs) : m_sig(0),
+ m_nte(FALSE),
+ m_fOfs(fOfs)
+{
+ ssDebugOut((DEB_TRACE, "In CEnumSTATDIR::CEnumSTATDIR\n"));
+ ssDebugOut((DEB_TRACE, "Out CEnumSTATDIR::CEnumSTATDIR\n"));
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CEnumSTATDIR::Validate, private
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 09-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE CEnumSTATDIR::Validate(void) const
+{
+ return (this == NULL || m_sig != CENUMSTATDIR_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+inline SCODE CEnumSTATDIR::InitFromHandle(HANDLE h)
+{
+ SCODE sc = S_OK;
+
+ ssDebugOut((DEB_ITRACE, "In CEnumSTATDIR::InitFromHandle:%p(%p)\n",
+ this, h));
+ sc = m_nte.InitFromHandle(h, TRUE);
+ if (SUCCEEDED(sc))
+ m_sig = CENUMSTATDIR_SIG;
+
+ ssDebugOut((DEB_ITRACE, "Out CEnumSTATDIR::InitFromHandle => %lX\n", sc));
+ return sc;
+}
+
+#endif // #ifndef __DIRECTRY_HXX__
diff --git a/private/ole32/stg/ofsstg/odirstg.cxx b/private/ole32/stg/ofsstg/odirstg.cxx
new file mode 100644
index 000000000..0bd4a336f
--- /dev/null
+++ b/private/ole32/stg/ofsstg/odirstg.cxx
@@ -0,0 +1,1121 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: odirstg.cxx
+//
+// Contents: IStorage for directories implementation
+//
+// History: 24-Jun-93 DrewB Created
+//
+// Notes: BUGBUG [mikese] Many of these routines are identical
+// to those for COfsDocStorage. We should create a common
+// base class to contain the common code.
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <stgutil.hxx>
+#include "odsenm.hxx"
+
+#include <odocstm.hxx>
+#include <iofs.h>
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In COfsDirStorage::QueryInterface:%p(riid,%p)\n",
+ this, ppvObj));
+ if (!IsValidIid(iid))
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(Validate());
+ if (IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IStorage *)this;
+ COfsDirStorage::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IStorage) && _fOfs)
+ {
+ *ppvObj = (IStorage *)this;
+ COfsDirStorage::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IPropertySetStorage) && _fOfs)
+ {
+ *ppvObj = (IPropertySetStorage *)this;
+ COfsDirStorage::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IDirectory))
+ {
+ *ppvObj = (IDirectory *)this;
+ COfsDirStorage::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_INativeFileSystem))
+ {
+ *ppvObj = (INativeFileSystem *)this;
+ COfsDirStorage::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IStorageReplica))
+ {
+ *ppvObj = (IStorageReplica *)this;
+ COfsDirStorage::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppvObj = NULL;
+ }
+ olDebugOut((DEB_TRACE, "Out COfsDirStorage::QueryInterface => %p\n",
+ *ppvObj));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::COfsDirStorage, public
+//
+// Synopsis: Empty object construction
+//
+// History: 30-Jun-93 DrewB Created
+// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
+//
+//----------------------------------------------------------------------------
+
+#pragma warning(disable: 4355)
+
+COfsDirStorage::COfsDirStorage(BOOL fOfs)
+ : CPropertySetStorage(this), COleDirectory(fOfs)
+{
+
+#pragma warning(default: 4355)
+
+ olDebugOut((DEB_ITRACE, "In COfsDirStorage::COfsDirStorage:%p()\n",
+ this));
+ _sig = 0;
+ _wcDrive = L'\0';
+ olDebugOut((DEB_ITRACE, "Out COfsDirStorage::COfsDirStorage\n"));
+ ENLIST_TRACKING(COfsDirStorage);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::InitFromHandle, public
+//
+// Synopsis: From-handle constructor
+//
+// Arguments: [h] - Handle of directory
+// [grfMode] - Mode of handle
+//
+// Returns: Appropriate status code
+//
+// History: 29-Jun-93 DrewB Created
+// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
+//
+// Notes: Takes a new reference on the handle
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDirStorage::InitFromHandle(HANDLE h,
+ WCHAR const *pwcsName,
+ DWORD grfMode)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In COfsDirStorage::InitFromHandle:%p(%p, %lX)\n",
+ this, h, grfMode));
+
+ ssChk(ValidateMode(grfMode));
+ _h = h;
+ ssAssert(_h != NULL);
+ _grfMode = grfMode;
+ _sig = COFSDIRSTORAGE_SIG;
+ _wcDrive = GetDriveLetter (pwcsName);
+
+ ssDebugOut((DEB_ITRACE, "Out COfsDirStorage::InitFromHandle\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::InitFromPath, public
+//
+// Synopsis: From-path constructor
+//
+// Arguments: [hParent] - Handle of parent directory
+// [pwcsName] - Name of directory
+// [grfMode] - Mode
+// [fCreate] - Create or open
+// [pssSecurity] - Security
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDirStorage::InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ BOOL fJunction,
+ LPSECURITY_ATTRIBUTES pssSecurity)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In COfsDirStorage::InitFromPath:%p("
+ "%p, %ws, %lX, %d, %p)\n", this, hParent, pwcsName, grfMode,
+ co, pssSecurity));
+
+ ssChk(ValidateMode(grfMode));
+ ssChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co,
+ (fJunction ? FD_JUNCTION : FD_DIR),
+ pssSecurity, &_h));
+
+ _grfMode = grfMode;
+ _sig = COFSDIRSTORAGE_SIG;
+ _wcDrive = GetDriveLetter (pwcsName);
+
+ ssDebugOut((DEB_ITRACE, "Out COfsDirStorage::InitFromPath\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::~COfsDirStorage, public
+//
+// Synopsis: Destructor
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+COfsDirStorage::~COfsDirStorage(void)
+{
+ ssDebugOut((DEB_ITRACE, "In COfsDirStorage::~COfsDirStorage()\n"));
+
+ _sig = COFSDIRSTORAGE_SIGDEL;
+
+ if ((HANDLE)_h != NULL && (_grfMode & STGM_DELETEONRELEASE))
+ {
+ SCODE sc = DestroyTree(NULL, NULL, _h, FD_STORAGE);
+ if (!SUCCEEDED(sc))
+ {
+ ssDebugOut ((DEB_ERROR, " DestroyTree => %x\n", sc));
+ ssVerSucc(sc);
+ }
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out COfsDirStorage::~COfsDirStorage\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::CreateStream, public
+//
+// Synopsis: Creates a stream
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [reserved1]
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::CreateStream(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ olDebugOut((DEB_TRACE, "Stb COfsDirStorage::CreateStream:%p("
+ "%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode,
+ reserved1, reserved2, ppstm));
+ SCODE sc;
+ SafeCOfsDocStream pst;
+ WCHAR *pwcsNewName = NULL;
+
+ ssChk(Validate());
+ // BUGBUG: this code has just been copy-pasted from COfsDocStorage.
+
+ //BUGBUG: Figure out what to do about STGM_CREATE and STGM_CONVERT.
+ if (reserved1 != 0 || reserved2 != 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(ValidateOutPtrBuffer(ppstm));
+ *ppstm = NULL;
+
+ pst.Attach(new COfsDocStream());
+ ssMem((COfsDocStream *)pst);
+
+ ssMem(pwcsNewName = MakeStreamName(pwcsName));
+ ssChk(pst->InitFromPath(_h, pwcsNewName, grfMode, CO_CREATE,FALSE,NULL));
+
+ TRANSFER_INTERFACE(pst, IStream, ppstm);
+
+ ssDebugOut((DEB_TRACE, "COfsDocStorage::CreateStream => %p\n", *ppstm));
+ EH_Err:
+ delete pwcsNewName;
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::OpenStream, public
+//
+// Synopsis: Opens an existing stream
+//
+// Arguments: [pwcsName] - Name
+// [reserved1]
+// [grfMode] - Permissions
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::OpenStream(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+ SafeCOfsDocStream pst;
+ WCHAR *pwcsNewName = NULL;
+
+ // BUGBUG: this code has just been copy-pasted from COfsDocStorage
+
+ ssDebugOut((DEB_TRACE, "COfsDocStorage::OpenStream:%p("
+ "%ws, %p, %lX, %lu, %p)\n", this, pwcsName, reserved1,
+ grfMode, reserved2, ppstm));
+
+ ssChk(Validate());
+ if (reserved1 != 0 || reserved2 != 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if (grfMode & (STGM_CREATE | STGM_CONVERT))
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+ ssChk(ValidateOutPtrBuffer(ppstm));
+ *ppstm = NULL;
+
+ pst.Attach(new COfsDocStream());
+ ssMem((COfsDocStream *)pst);
+
+ pwcsNewName = MakeStreamName(pwcsName);
+ ssChk(pst->InitFromPath(_h, pwcsNewName, grfMode, CO_OPEN, FALSE,NULL));
+
+ TRANSFER_INTERFACE(pst, IStream, ppstm);
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage:: OpenStream => %p\n", *ppstm));
+
+ EH_Err:
+ delete pwcsNewName;
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::CreateStorage, public
+//
+// Synopsis: Creates a child storage
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [dwStgFmt] - Type of storage to create
+// [pssSecurity] - Security
+// [ppstg] - New storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::CreateStorage (
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD dwStgFmt,
+ LPSTGSECURITY pssSecurity,
+ IStorage **ppstg)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In COfsDirStorage::CreateStorage:%p("
+ "%ws, %lX, %lu, %p, %p)\n", this, pwcsName, grfMode,
+ dwStgFmt, pssSecurity, ppstg));
+
+ olChk(Validate());
+ olChk(VerifyStgFmt(dwStgFmt));
+ ssChk(ValidateOutPtrBuffer(ppstg));
+ *ppstg = NULL;
+ olAssert(_h != NULL);
+ sc = OfsCreateStorageType(_h, pwcsName, NULL, grfMode, dwStgFmt,
+ (LPSECURITY_ATTRIBUTES)pssSecurity, FALSE, ppstg);
+
+ olDebugOut((DEB_TRACE, "Out COfsDirStorage::CreateStorage => %p\n", *ppstg));
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::OpenStorage, public
+//
+// Synopsis: Gets an existing child storage
+//
+// Arguments: [pwcsName] - Name
+// [pstgPriority] - Priority reopens
+// [grfMode] - Permissions
+// [snbExclude] - Priority reopens
+// [reserved]
+// [ppstg] - Storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::OpenStorage(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In COfsDirStorage::OpenStorage:%p("
+ "%ws, %p, %lX, %p, %lu, %p)\n", this, pwcsName, pstgPriority,
+ grfMode, snbExclude, reserved, ppstg));
+
+ olChk(Validate());
+ if (pstgPriority != NULL || snbExclude != NULL ||
+ reserved != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if (grfMode & (STGM_CREATE | STGM_CONVERT))
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ ssChk(ValidateOutPtrBuffer(ppstg));
+ *ppstg = NULL;
+
+ olAssert(_h != NULL);
+ sc = CheckFsAndOpenAnyStorage(_h, pwcsName, pstgPriority, grfMode,
+ snbExclude, FALSE, ppstg);
+
+ olDebugOut((DEB_TRACE, "Out COfsDirStorage::OpenStorage => %p\n", *ppstg));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::CopyTo, public
+//
+// Synopsis: Makes a copy of a storage
+//
+// Arguments: [ciidExclude] - Length of rgiid array
+// [rgiidExclude] - Array of IIDs to exclude
+// [snbExclude] - Names to exclude
+// [pstgDest] - Parent of copy
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+// Notes: BUGBUG - This function operates recursively and so
+// is bounded by stack space
+// It could also be optimized to recognize special cases
+// of copying (like treating a docfile as a file)
+//
+// BUGBUG [mikese] This routine is probably all wrong, since
+// at present it performs a tree copy, whereas in all likelihood
+// it should just copy the embedding heirarchy and not the
+// file system hierarchy.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::CopyTo(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest)
+{
+ ssDebugOut((DEB_TRACE, "In COfsDirStorage::CopyTo:%p(%lu, %p, %p, %p)\n",
+ this, ciidExclude, rgiidExclude, snbExclude, pstgDest));
+
+ SCODE sc;
+ ULONG i;
+ BOOL fCopyStorage = TRUE;
+ BOOL fCopyStreams = TRUE;
+ STATSTG stat;
+ DWORD grfModeFrom;
+
+ ssChk(Validate());
+ if (!IsValidInterface(pstgDest))
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+
+ // Copy class ID and state bits if the destination supports them
+ ssChk(Stat(&stat, STATFLAG_NONAME));
+ // force direct read, inherit the sharing flags from parent
+ grfModeFrom = (stat.grfMode & (STGM_SHARE_EXCLUSIVE|
+ STGM_SHARE_DENY_READ| STGM_SHARE_DENY_WRITE | STGM_SHARE_DENY_NONE))
+ | STGM_READ | STGM_DIRECT;
+ sc = GetScode(pstgDest->SetClass(stat.clsid));
+ if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
+ olErr(EH_Err, sc);
+ sc = GetScode(pstgDest->SetStateBits(stat.grfStateBits, 0xffffffff));
+ if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
+ olErr(EH_Err, sc);
+
+ // Check IID exclusions
+ for (i = 0; i < ciidExclude; i++)
+ {
+ if (IsEqualIID(rgiidExclude[i], IID_IStorage))
+ {
+ fCopyStorage = FALSE;
+ }
+ else if ( IsEqualIID ( rgiidExclude[i], IID_IStream ) )
+ {
+ fCopyStreams = FALSE;
+ }
+ }
+
+ sc = S_OK;
+
+ if (fCopyStorage)
+ {
+ SCODE scFinal;
+ WCHAR pwcsName[MAXIMUM_FILENAME_LENGTH];
+ FILEDIR fd;
+ CNtEnum nte;
+ CDfName dfn;
+
+ scFinal = S_OK;
+ ssAssert(_h != NULL);
+ ssChk(nte.InitFromHandle(_h, TRUE));
+ for (;;)
+ {
+ sc = nte.Next(&stat, pwcsName, NTE_BUFFERNAME, &fd);
+ if (sc == S_FALSE)
+ break;
+ else if (FAILED(sc))
+ olErr(EH_Err, sc);
+
+ // Ignore . and ..
+ if (!wcscmp(pwcsName, L".") || !wcscmp(pwcsName, L".."))
+ continue;
+
+ // BUGBUG: [mikese] What's wrong with raw pwcsName?
+ dfn.Set(pwcsName);
+ if (snbExclude == NULL || !NameInSNB(&dfn, snbExclude))
+ {
+ if ( stat.type == STGTY_STORAGE )
+ {
+ SafeIStorage pstgFrom, pstgTo;
+ STATSTG statTo;
+
+ olHChkTo(EH_Next, OpenStorage(pwcsName, NULL, grfModeFrom,
+ NULL, NULL, &pstgFrom));
+ // BUGBUG: [mikese] The following seemingly redundany Stat is
+ // in fact necessary because CNtEnum does not set the STGFMT
+ // correctly (cannot distinguish a directory from an OFS
+ // structured storage)
+ olHChkTo(EH_Next, pstgFrom->Stat(&stat, STATFLAG_NONAME));
+ sc = GetScode(pstgDest->CreateStorage(pwcsName,
+ STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_FAILIFTHERE,
+ stat.STATSTG_dwStgFmt,
+ NULL,
+ &pstgTo));
+ if (FAILED(sc))
+ {
+ if (sc == STG_E_FILEALREADYEXISTS)
+ {
+ // Try to open rather than creating
+ sc = GetScode(pstgDest->OpenStorage(pwcsName, NULL,
+ STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE,
+ NULL, NULL,
+ &pstgTo));
+ if (SUCCEEDED(sc))
+ {
+ sc = GetScode(pstgTo->Stat(&statTo,
+ STATFLAG_NONAME));
+ if (FAILED(sc) ||
+ statTo.STATSTG_dwStgFmt != stat.STATSTG_dwStgFmt)
+ {
+ sc = STG_E_INVALIDFUNCTION;
+ }
+ }
+ }
+ }
+
+ if (SUCCEEDED(sc))
+ sc = pstgFrom->CopyTo( ciidExclude, rgiidExclude,
+ snbExclude, pstgTo);
+ }
+ else if ( (stat.type == STGTY_STREAM) && fCopyStreams )
+ {
+ SafeIStream pstmTo, pstmFrom;
+
+ olHChkTo(EH_Next, OpenStream ( pwcsName,
+ NULL, grfModeFrom,
+ 0, &pstmFrom ) );
+ // BUGBUG [mikese] Ambiguous. I'm just going to create
+ // the stream in the destination, overwriting any
+ // kind of element with the same name.
+ sc = pstgDest->CreateStream ( pwcsName,
+ STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_CREATE,
+ 0, 0, &pstmTo );
+ if ( SUCCEEDED(sc) )
+ {
+ static ULARGE_INTEGER uli = { 0xFFFFFFFF, 0xFFFFFFFF };
+ sc = pstmFrom->CopyTo ( pstmTo, uli, NULL, NULL );
+ }
+ }
+
+ EH_Next:
+ if (FAILED(sc))
+ scFinal = sc;
+ }
+ }
+ sc = scFinal;
+ }
+
+EH_Err:
+ ssDebugOut((DEB_TRACE, "Out COfsDirStorage::CopyTo\n"));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::MoveElementTo, public
+//
+// Synopsis: Move an element of a storage to another storage
+//
+// Arguments: [pwcsName] - Current name
+// [ptcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// Algorithm: Open source as storage or stream (whatever works)
+// Create appropriate destination
+// Copy source to destination
+// Set create time of destination equal to create time of source
+// If appropriate, delete source
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::MoveElementTo(WCHAR const *pwcsName,
+ IStorage *pstgParent,
+ WCHAR const *ptcsNewName,
+ DWORD grfFlags)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In COfsDirStorage::MoveElementTo:%p("
+ "%ws, %p, %ws, %lu)\n", this, pwcsName, pstgParent,
+ ptcsNewName, grfFlags));
+
+ olChk(Validate());
+ olChk(VerifyMoveFlags(grfFlags));
+
+ sc = GenericMoveElement(this, pwcsName, pstgParent, ptcsNewName, grfFlags);
+
+ olDebugOut((DEB_TRACE, "Out COfsDirStorage::MoveElementTo => %lX\n", sc));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::Commit, public
+//
+// Synopsis: Commits transacted changes
+//
+// Arguments: [dwFlags] - DFC_*
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::Commit(DWORD dwFlags)
+{
+ olDebugOut((DEB_TRACE, "Stb COfsDirStorage::Commit:%p(%lX)\n",
+ this, dwFlags));
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::Revert, public
+//
+// Synopsis: Reverts transacted changes
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::Revert(void)
+{
+ olDebugOut((DEB_TRACE, "Stb COfsDirStorage::Revert:%p()\n", this));
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::EnumElements, public
+//
+// Synopsis: Starts an iterator
+//
+// Arguments: [reserved1]
+// [reserved2]
+// [reserved3]
+// [ppenm] - Enumerator return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::EnumElements(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm)
+{
+ SCODE sc;
+ SafeCOfsDirEnum pde;
+
+ olDebugOut((DEB_TRACE, "In COfsDirStorage::EnumElements:%p("
+ "%lu, %p, %lu, %p)\n", this, reserved1, reserved2,
+ reserved3, ppenm));
+
+ if (ppenm == NULL)
+ ssErr (EH_Err, STG_E_INVALIDPOINTER) // missing ';' macro problem
+ else
+ ssChk(ValidateOutPtrBuffer(ppenm));
+ *ppenm = NULL;
+ if (reserved1 != 0 || reserved2 != NULL || reserved3 != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(Validate());
+
+ pde.Attach(new COfsDirEnum(TRUE));
+
+ olMem((COfsDirEnum *)pde);
+ olAssert(_h != NULL);
+ olChk(pde->InitFromHandle(_h));
+ TRANSFER_INTERFACE(pde, IEnumSTATSTG, ppenm);
+
+ olDebugOut((DEB_TRACE, "Out COfsDirStorage::EnumElements => %p\n",
+ *ppenm));
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::DestroyElement, public
+//
+// Synopsis: Permanently deletes an element of a storage
+//
+// Arguments: [pwcsName] - Name of element
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::DestroyElement(WCHAR const *pwcsName)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In COfsDirStorage::DestroyElement:%p(%ws)\n",
+ this, pwcsName));
+
+ if (SUCCEEDED(sc = Validate()))
+ {
+ olAssert(_h != NULL);
+ sc = DestroyTree(_h, pwcsName, NULL, FD_FILE);
+ }
+
+ olDebugOut((DEB_TRACE, "Out COfsDirStorage::DestroyElement\n"));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::RenameElement, public
+//
+// Synopsis: Renames an element of a storage
+//
+// Arguments: [pwcsName] - Current name
+// [pwcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::RenameElement(WCHAR const *pwcsName,
+ WCHAR const *pwcsNewName)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In COfsDirStorage::RenameElement:%p(%ws, %ws)\n",
+ this, pwcsName, pwcsNewName));
+
+ olChk(Validate());
+ // pwcsName is checked by GetFileOrDirHandle
+ olChk(CheckFdName(pwcsNewName));
+
+ olAssert(_h != NULL);
+ sc = RenameChild(_h, pwcsName, pwcsNewName);
+
+ olDebugOut((DEB_TRACE, "Out COfsDirStorage::RenameElement\n"));
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::SetElementTimes, public
+//
+// Synopsis: Sets element time stamps
+//
+// Arguments: [pwcsName] - Name
+// [pctime] - Create time
+// [patime] - Access time
+// [pmtime] - Modify time
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::SetElementTimes(WCHAR const *pwcsName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ SCODE sc;
+ SafeNtHandle h;
+
+ olDebugOut((DEB_TRACE, "In COfsDirStorage::SetElementTimes:%p("
+ "%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime));
+
+ olChk(Validate());
+
+ olAssert(_h != NULL);
+ olChk(GetFileOrDirHandle(_h, pwcsName, STGM_WRITE, &h, NULL, NULL, NULL));
+ sc = ::SetTimes(h, pctime, patime, pmtime);
+
+ olDebugOut((DEB_TRACE, "Out COfsDirStorage::SetElementTimes\n"));
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::SetClass, public
+//
+// Synopsis: Sets storage class
+//
+// Arguments: [clsid] - class id
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::SetClass(REFCLSID clsid)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In COfsDirStorage::SetClass:%p(clsid)\n", this));
+ sc = RtlSetClassId(_h, &clsid);
+ olDebugOut((DEB_TRACE, "Out COfsDirStorage::SetClass => %lX\n", sc));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::SetStateBits, public
+//
+// Synopsis: Sets state bits
+//
+// Arguments: [grfStateBits] - state bits
+// [grfMask] - state bits mask
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ NTSTATUS nts;
+ SCODE sc = S_OK;
+ IO_STATUS_BLOCK iosb;
+ FILE_OLE_STATE_BITS_INFORMATION fosbi;
+
+ ssDebugOut((DEB_TRACE, "In COfsDirStorage::SetStateBits:%p("
+ "%lu, %lu)\n", this, grfStateBits, grfMask));
+
+ fosbi.StateBits = grfStateBits;
+ fosbi.StateBitsMask = grfMask;
+
+ nts = NtSetInformationFile(_h, &iosb, &fosbi,
+ sizeof(FILE_OLE_STATE_BITS_INFORMATION),
+ FileOleStateBitsInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+EH_Err:
+ ssDebugOut((DEB_TRACE, "Out COfsDirStorage::SetStateBits => %lX\n", sc));
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::Stat, public
+//
+// Synopsis: Fills in a buffer of information about this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+ STATSTG stat;
+ FILEDIR fd;
+
+ olDebugOut((DEB_TRACE, "In COfsDirStorage::Stat:%p(%p, %lX)\n",
+ this, pstatstg, grfStatFlag));
+
+ olChk(VerifyStatFlag(grfStatFlag));
+ olChk(Validate());
+
+ __try
+ {
+ olAssert(_h != NULL);
+ stat.clsid = CLSID_NULL;
+ sc = StatNtHandle(_h, grfStatFlag, 0, &stat, NULL, NULL, &fd);
+ if (SUCCEEDED(sc))
+ {
+ SetDriveLetter (stat.pwcsName, _wcDrive);
+ ssAssert(fd == FD_DIR || fd == FD_JUNCTION);
+ stat.grfMode = _grfMode;
+ stat.cbSize.HighPart = stat.cbSize.LowPart = 0;
+ *pstatstg = stat;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (stat.pwcsName)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ sc = HRESULT_FROM_NT(GetExceptionCode());
+ }
+
+ olDebugOut((DEB_TRACE, "Out COfsDirStorage::Stat\n"));
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::ValidateMode, private
+//
+// Synopsis: Checks for legal access modes
+//
+// Arguments: [grfMode] - Mode
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDirStorage::ValidateMode(DWORD grfMode)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In COfsDirStorage::ValidateMode:%p(0x%lX)\n",
+ this, grfMode));
+ // BUGBUG - Can we simply ignore priority mode?
+ if (grfMode & (STGM_CONVERT))
+ sc = STG_E_INVALIDFLAG;
+ else
+ sc = S_OK;
+ olDebugOut((DEB_ITRACE, "Out COfsDirStorage::ValidateMode => 0x%lX\n",
+ sc));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::ExtValidate, private
+//
+// Synopsis: COfsPropSet validation routine
+//
+// History: 18-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDirStorage::ExtValidate(void)
+{
+ return Validate();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::GetHandle, private
+//
+// Synopsis: Get the handle backing this OFS IStorage.
+//
+// History: 10-May-94 BillMo Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::GetHandle(HANDLE *ph)
+{
+ SCODE sc;
+
+ ssChk(Validate());
+
+ *ph = _h;
+
+EH_Err:
+ return(ssResult(sc));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::GetStorage, public IPrivateStorage
+//
+// Synopsis: Returns the IStorage for this object.
+//
+// Notes: This member is called by CPropertyStorage.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(IStorage *)
+COfsDirStorage::GetStorage(VOID)
+{
+ return this;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::Lock, public IPrivateStorage
+//
+// Synopsis: Acquires the semaphore associated with the docfile.
+//
+// Notes: This member is called by CPropertyStorage.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP
+COfsDirStorage::Lock(DWORD dwTimeout)
+{
+ return STG_E_UNIMPLEMENTEDFUNCTION;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::Unlock, public IPrivateStorage
+//
+// Synopsis: Releases the semaphore associated with the docfile.
+//
+// Notes: This member is called by CPropertyStorage.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(VOID)
+COfsDirStorage::Unlock(VOID)
+{
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirStorage::GetServerInfo, public IStorageReplica
+//
+// Synopsis: Get the actual DFS path for a storage's home location
+//
+// Notes: This member is exposed for Internal Use Only
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirStorage::GetServerInfo(
+ IN OUT LPWSTR lpServerName,
+ IN OUT LPDWORD lpcbServerName,
+ IN OUT LPWSTR lpReplSpecificPath,
+ IN OUT LPDWORD lpcbReplSpecificPath)
+{
+ return GetHandleServerInfo (_h,
+ lpServerName,
+ lpcbServerName,
+ lpReplSpecificPath,
+ lpcbReplSpecificPath);
+}
diff --git a/private/ole32/stg/ofsstg/odirstg.hxx b/private/ole32/stg/ofsstg/odirstg.hxx
new file mode 100644
index 000000000..08b4de915
--- /dev/null
+++ b/private/ole32/stg/ofsstg/odirstg.hxx
@@ -0,0 +1,157 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: odirstg.hxx
+//
+// Contents: COfsDirStorage header
+//
+// Classes: COfsDirStorage
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ODIRSTG_HXX__
+#define __ODIRSTG_HXX__
+
+#include <psetstg.hxx>
+#include <odirdir.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: COfsDirStorage (ds)
+//
+// Purpose: Implements IStorage for a directory
+//
+// Interface: See below
+//
+// History: 24-Jun-93 DrewB Created
+// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
+//
+//----------------------------------------------------------------------------
+
+interface COfsDirStorage
+ : public CPropertySetStorage,
+ INHERIT_TRACKING,
+ public IStorage,
+ public COleDirectory,
+ public INativeFileSystem,
+ public IStorageReplica,
+ public IPrivateStorage
+{
+public:
+ COfsDirStorage(BOOL fOfs = STG_E_INVALIDFLAG);
+ SCODE InitFromHandle(HANDLE h, WCHAR const *pwcsName, DWORD grfMode);
+ SCODE InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ BOOL fJunction,
+ LPSECURITY_ATTRIBUTES pssSecurity);
+ ~COfsDirStorage(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // IStorage
+ STDMETHOD(CreateStream)(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(OpenStream)(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(CreateStorage)(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD stgType,
+ LPSTGSECURITY pssSecurity,
+ IStorage **ppstg);
+ STDMETHOD(OpenStorage)(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg);
+ STDMETHOD(CopyTo)(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest);
+ STDMETHOD(MoveElementTo)(WCHAR const *lpszName,
+ IStorage *pstgDest,
+ WCHAR const *lpszNewName,
+ DWORD grfFlags);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(EnumElements)(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm);
+ STDMETHOD(DestroyElement)(WCHAR const *pwcsName);
+ STDMETHOD(RenameElement)(WCHAR const *pwcsOldName,
+ WCHAR const *pwcsNewName);
+ STDMETHOD(SetElementTimes)(const WCHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+ STDMETHOD(SetClass)(REFCLSID clsid);
+ STDMETHOD(SetStateBits)(DWORD grfStateBits, DWORD grfMask);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+
+ // INativeFileSystem
+ STDMETHOD(GetHandle(HANDLE *ph));
+
+ //IStorageReplica
+ STDMETHOD(GetServerInfo) (IN OUT LPWSTR lpServerName,
+ IN OUT LPDWORD lpcbServerName,
+ IN OUT LPWSTR lpReplSpecificPath,
+ IN OUT LPDWORD lpcbReplSpecificPath);
+
+#ifdef NEWPROPS
+ // IPrivateStorage
+ STDMETHOD_(IStorage *,GetStorage)(VOID);
+ STDMETHOD(Lock)(DWORD dwTime);
+ STDMETHOD_(VOID, Unlock)(VOID);
+#endif
+
+protected:
+ inline SCODE Validate(void) const;
+private:
+ virtual SCODE ExtValidate(void);
+ SCODE ValidateMode(DWORD grfMode);
+
+ //ULONG _sig;
+ //DWORD _grfMode;
+ //WCHAR _wcDrive;
+ //NuSafeNtHandle _h;
+};
+
+SAFE_INTERFACE_PTR(SafeCOfsDirStorage, COfsDirStorage);
+
+#define COFSDIRSTORAGE_SIG LONGSIG('O', 'D', 'S', 'G')
+#define COFSDIRSTORAGE_SIGDEL LONGSIG('O', 'd', 'S', 'g')
+
+//+--------------------------------------------------------------
+//
+// Member: COfsDirStorage::Validate, private
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 24-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE COfsDirStorage::Validate(void) const
+{
+ return (this == NULL || _sig != COFSDIRSTORAGE_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+#endif // #ifndef __DIRSTG_HXX__
diff --git a/private/ole32/stg/ofsstg/odocstg.cxx b/private/ole32/stg/ofsstg/odocstg.cxx
new file mode 100644
index 000000000..1992cacf7
--- /dev/null
+++ b/private/ole32/stg/ofsstg/odocstg.cxx
@@ -0,0 +1,1445 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: odocstg.cxx
+//
+// Contents: IStorage for compound docs on OFS implementation
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+// Notes: BUGBUG [mikese] Many of these routines are identical
+// to those for COfsDirStorage. We should create a common
+// base class to contain the common code.
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <stgutil.hxx>
+#include "odsenm.hxx"
+#include "odocstm.hxx"
+
+#include <psetstg.hxx>
+#include <iofs.h>
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::QueryInterface:%p(riid, %p)\n",
+ this, ppvObj));
+ if (!IsValidIid(iid))
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+ if (IsEqualIID(iid, IID_IStorage) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IStorage *)this;
+ COfsDocStorage::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IPropertySetStorage))
+ {
+ *ppvObj = (IPropertySetStorage *)this;
+ COfsDocStorage::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_INativeFileSystem))
+ {
+ *ppvObj = (INativeFileSystem *)this;
+ COfsDocStorage::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IAccessControl))
+ {
+ // BUGBUG need to artifically restrict to root & property storages
+ *ppvObj = (IAccessControl *)this;
+ COfsDocStorage::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IMarshal) &&
+ (_grfMode & STGM_DELETEONRELEASE) == 0)
+ {
+ *ppvObj = (IMarshal *)this;
+ COfsDocStorage::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IStorageReplica))
+ {
+ *ppvObj = (IStorageReplica *)this;
+ COfsDocStorage::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppvObj = NULL;
+ }
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::QueryInterface => %p\n",
+ *ppvObj));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::COfsDocStorage, public
+//
+// Synopsis: Empty object construction
+//
+// History: 07-Feb-94 PhilipLa Created
+// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
+//
+//----------------------------------------------------------------------------
+
+#pragma warning(disable: 4355)
+COfsDocStorage::COfsDocStorage(void) : CPropertySetStorage(this)
+#pragma warning(default: 4355)
+{
+ ssDebugOut((DEB_ITRACE, "In COfsDocStorage::COfsDocStorage:%p()\n",
+ this));
+ _sig = 0;
+ _wcDrive = L'\0';
+ ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::COfsDocStorage\n"));
+ ENLIST_TRACKING(COfsDocStorage);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::InitFromHandle, public
+//
+// Synopsis: From-handle constructor
+//
+// Arguments: [h] - Handle of directory
+// [grfMode] - Mode of handle
+// [fRoot] - TRUE => storage is a root storage
+//
+// Returns: Appropriate status code
+//
+// History: 07-Feb-94 PhilipLa Created
+// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
+//
+// Notes: Takes a new reference on the handle
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDocStorage::InitFromHandle(HANDLE h,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ BOOL fRoot)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In COfsDocStorage::InitFromHandle:%p(%p, %lX)\n",
+ this, h, grfMode));
+
+ ssChk(ValidateMode(grfMode));
+ _h = h;
+ ssAssert(_h != NULL);
+ _grfMode = grfMode;
+ _sig = COfsDocStorage_SIG;
+ _fRoot = fRoot;
+ _wcDrive = GetDriveLetter (pwcsName);
+ ssChk(InitAccessControl(_h, _grfMode, FALSE, NULL));
+ ssChk(InitNtHandleMarshal(_h, _grfMode, STGFMT_DOCUMENT));
+
+ ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::InitFromHandle\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::InitFromPath, public
+//
+// Synopsis: From-path constructor
+//
+// Arguments: [pwcsName] - Name of document
+// [grfMode] - Mode
+// [fCreate] - Create or open
+// [pssSecurity] - Security
+// [fRoot] - TRUE => root storage
+//
+// Returns: Appropriate status code
+//
+// History: 07-Feb-94 PhilipLa Created
+// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDocStorage::InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSECURITY_ATTRIBUTES pssSecurity,
+ BOOL fRoot)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In COfsDocStorage::InitFromPath:%p("
+ "%p, %ws, %lX, %d, %p)\n", this, hParent, pwcsName, grfMode,
+ co, pssSecurity));
+
+ ssChk(ValidateMode(grfMode));
+
+ // BUGBUG: [mikese] This class is used for both root documents and
+ // embeddings, so FD_STORAGE is not always correct.
+
+ ssChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co, FD_STORAGE,
+ (LPSECURITY_ATTRIBUTES)pssSecurity, &_h));
+
+ _grfMode = grfMode;
+ _sig = COfsDocStorage_SIG;
+ _fRoot = fRoot;
+ _wcDrive = GetDriveLetter (pwcsName);
+ ssChk(InitAccessControl(_h, _grfMode, FALSE, NULL));
+ ssChk(InitNtHandleMarshal(_h, _grfMode, STGFMT_DOCUMENT));
+
+ ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::InitFromPath\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::~COfsDocStorage, public
+//
+// Synopsis: Destructor
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+COfsDocStorage::~COfsDocStorage(void)
+{
+ ssDebugOut((DEB_ITRACE, "In COfsDocStorage::~COfsDocStorage()\n"));
+
+ _sig = COfsDocStorage_SIGDEL;
+
+ //BUGBUG: Replace with real delete on release support?
+ if ((HANDLE)_h != NULL && (_grfMode & STGM_DELETEONRELEASE))
+ {
+ SCODE sc = DestroyTree(NULL, NULL, _h, FD_STORAGE);
+ if (!SUCCEEDED(sc))
+ {
+ ssDebugOut ((DEB_ERROR, " DestroyTree => %x\n", sc));
+ ssVerSucc(sc);
+ }
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::~COfsDocStorage\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::CreateStream, public
+//
+// Synopsis: Creates a stream
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [reserved1]
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::CreateStream(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+ SafeCOfsDocStream pst;
+ WCHAR *pwcsNewName = NULL;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::CreateStream:%p("
+ "%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode,
+ reserved1, reserved2, ppstm));
+
+ ssChk(Validate());
+ if (reserved1 != 0 || reserved2 != 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if (grfMode & (STGM_CONVERT | STGM_PRIORITY | STGM_DELETEONRELEASE))
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+#ifdef TRANSACT_OLE
+ if (_grfMode & STGM_TRANSACTED)
+ {
+ if (grfMode & (STGM_CREATE | STGM_TRANSACTED))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if ((grfMode & STGM_SHARE_EXCLUSIVE) == 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ }
+#endif
+ ssChk(ValidateOutPtrBuffer(ppstm));
+ *ppstm = NULL;
+
+ pst.Attach(new COfsDocStream());
+ ssMem((COfsDocStream *)pst);
+
+ ssMem(pwcsNewName = MakeStreamName(pwcsName));
+#ifdef TRANSACT_OLE
+ ssChk(pst->InitFromPath(_h, pwcsNewName, grfMode, CO_CREATE,
+ (_grfMode & STGM_TRANSACTED) == STGM_TRANSACTED, NULL));
+#else
+ ssChk(pst->InitFromPath(_h, pwcsNewName, grfMode, CO_CREATE,
+ FALSE, NULL));
+#endif
+
+ TRANSFER_INTERFACE(pst, IStream, ppstm);
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::CreateStream => %p\n", *ppstm));
+ EH_Err:
+ delete pwcsNewName;
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::OpenStream, public
+//
+// Synopsis: Opens an existing stream
+//
+// Arguments: [pwcsName] - Name
+// [reserved1]
+// [grfMode] - Permissions
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::OpenStream(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+ SafeCOfsDocStream pst;
+ WCHAR *pwcsNewName = NULL;
+
+ ssDebugOut((DEB_TRACE, "COfsDocStorage::OpenStream:%p("
+ "%ws, %p, %lX, %lu, %p)\n", this, pwcsName, reserved1,
+ grfMode, reserved2, ppstm));
+
+ ssChk(ValidateSimple());
+ ssChk(Validate());
+ if (reserved1 != 0 || reserved2 != 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if (grfMode & (STGM_CREATE | STGM_CONVERT))
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+ if (grfMode & (STGM_PRIORITY | STGM_DELETEONRELEASE))
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+#ifdef TRANSACT_OLE
+ if (_grfMode & STGM_TRANSACTED)
+ {
+ if (grfMode & (STGM_CREATE | STGM_TRANSACTED))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if ((grfMode & STGM_SHARE_EXCLUSIVE) == 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ }
+#endif
+ ssChk(ValidateOutPtrBuffer(ppstm));
+ *ppstm = NULL;
+
+ pst.Attach(new COfsDocStream());
+ ssMem((COfsDocStream *)pst);
+
+ ssMem(pwcsNewName = MakeStreamName(pwcsName));
+#ifdef TRANSACT_OLE
+ ssChk(pst->InitFromPath(_h, pwcsNewName, grfMode, CO_OPEN,
+ (_grfMode & STGM_TRANSACTED) == STGM_TRANSACTED, NULL));
+#else
+ ssChk(pst->InitFromPath(_h, pwcsNewName, grfMode, CO_OPEN,
+ FALSE, NULL));
+#endif
+
+ TRANSFER_INTERFACE(pst, IStream, ppstm);
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage:: OpenStream => %p\n", *ppstm));
+
+ EH_Err:
+ delete pwcsNewName;
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::CreateStorage, public
+//
+// Synopsis: Creates a child storage
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [dwStgFmt] - Type of storage to create
+// [pssSecurity] - Security
+// [ppstg] - New storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::CreateStorage(
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD dwStgFmt,
+ LPSTGSECURITY pssSecurity,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ SafeCOfsDocStorage pstg;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::CreateStorage:%p("
+ "%ws, %lX, %lu, %p, %p)\n", this, pwcsName, grfMode,
+ dwStgFmt, pssSecurity, ppstg));
+
+ ssChk(ValidateSimple());
+ ssChk(Validate());
+ ssChk(VerifyStgFmt(dwStgFmt));
+ ssAssert(_h != NULL);
+ ssChk(ValidateOutPtrBuffer(ppstg));
+ *ppstg = NULL;
+
+ //FORCE_READ(grfMode);
+ pstg.Attach(new COfsDocStorage());
+ ssMem((COfsDocStorage *)pstg);
+
+ ssChk(pstg->InitFromPath(_h, pwcsName, grfMode, CO_CREATE,
+ (LPSECURITY_ATTRIBUTES) pssSecurity, FALSE));
+
+ if ((grfMode & STGM_EDIT_ACCESS_RIGHTS) && // child is editing ACLS
+ (_grfMode & STGM_TRANSACTED)) // parent is transacted
+ {
+ InsertChild (pstg); // hold on to the child for
+ pstg->AddRef(); // nested transactions
+ }
+
+ TRANSFER_INTERFACE(pstg, IStorage, ppstg);
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::CreateStorage => %p\n",*ppstg));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::OpenStorage, public
+//
+// Synopsis: Gets an existing child storage
+//
+// Arguments: [pwcsName] - Name
+// [pstgPriority] - Priority reopens
+// [grfMode] - Permissions
+// [snbExclude] - Priority reopens
+// [reserved]
+// [ppstg] - Storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::OpenStorage(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ SafeCOfsDocStorage pstg;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::OpenStorage:%p("
+ "%ws, %p, %lX, %p, %lu, %p)\n", this, pwcsName, pstgPriority,
+ grfMode, snbExclude, reserved, ppstg));
+
+ ssChk(ValidateSimple());
+ ssChk(Validate());
+ if (pstgPriority != NULL || snbExclude != NULL ||
+ reserved != 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if (grfMode & (STGM_CREATE | STGM_CONVERT))
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+ ssChk(ValidateOutPtrBuffer(ppstg));
+ *ppstg = NULL;
+
+ ssAssert(_h != NULL);
+
+ // The only thing we can open inside a document is an embedding
+
+ pstg.Attach(new COfsDocStorage());
+ ssMem((COfsDocStorage *)pstg);
+
+ ssChk(pstg->InitFromPath(_h, pwcsName, grfMode, CO_OPEN, NULL, FALSE));
+
+ if (snbExclude != NULL)
+ ssChk(pstg->ExcludeEntries(snbExclude));
+
+ if ((grfMode & STGM_EDIT_ACCESS_RIGHTS) && // child is editing ACLS
+ (_grfMode & STGM_TRANSACTED)) // parent is transacted
+ {
+ InsertChild (pstg); // hold on to the child for
+ pstg->AddRef(); // nested transactions
+ }
+
+ TRANSFER_INTERFACE(pstg, IStorage, ppstg);
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::OpenStorage => %p\n", *ppstg));
+
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::CopyTo, public
+//
+// Synopsis: Makes a copy of a storage
+//
+// Arguments: [ciidExclude] - Length of rgiid array
+// [rgiidExclude] - Array of IIDs to exclude
+// [snbExclude] - Names to exclude
+// [pstgDest] - Parent of copy
+//
+// Returns: Appropriate status code
+//
+// History: 07-Feb-94 PhilipLa Copied from DrewB's stuff
+//
+// Notes: BUGBUG - This function operates recursively and so
+// is bounded by stack space
+// It could also be optimized to recognize special cases
+// of copying (like treating a docfile as a file)
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::CopyTo(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest)
+{
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::CopyTo:%p(%lu, %p, %p, %p)\n",
+ this, ciidExclude, rgiidExclude, snbExclude, pstgDest));
+
+ SCODE sc;
+ ULONG i;
+ BOOL fCopyStorage = TRUE;
+ BOOL fCopyStreams = TRUE;
+ STATSTG stat;
+ STATSTG statDest;
+ DWORD grfModeFrom;
+ DWORD grfModeTo;
+ DWORD grfModeTo2;
+
+ ssChk(ValidateSimple());
+ ssChk(Validate());
+ if (!IsValidInterface(pstgDest))
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+
+ // Stat the source to obtain the open mode (and also class id and
+ // state bits).
+ ssChk(Stat(&stat, STATFLAG_NONAME));
+ // The open mode for subelements of the source is derived from that
+ // of the root. We preserve the sharing mode part, force read only
+ // and direct (because we do not want a nested transaction).
+ grfModeFrom = (stat.grfMode & (STGM_SHARE_EXCLUSIVE|
+ STGM_SHARE_DENY_READ|
+ STGM_SHARE_DENY_WRITE|
+ STGM_SHARE_DENY_NONE))
+ | STGM_READ | STGM_DIRECT;
+
+ // Stat the destination to obtain the open mode
+ ssChk(pstgDest->Stat(&statDest,STATFLAG_NONAME));
+ // The open mode for subelements of the destination is derived from that
+ // of the root. We force direct mode, since we do not want nested
+ // transactions.
+ grfModeTo = statDest.grfMode & (~(STGM_TRANSACTED | STGM_DELETEONRELEASE));
+
+ // Copy class ID and state bits if the destination supports them
+ // BUGBUG [mikese] Do we really need to do this, since won't these
+ // get copied as part of the system properties?
+ sc = GetScode(pstgDest->SetClass(stat.clsid));
+ if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
+ olErr(EH_Err, sc);
+ sc = GetScode(pstgDest->SetStateBits(stat.grfStateBits, 0xffffffff));
+ if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
+ olErr(EH_Err, sc);
+
+ // Check IID exclusions
+ for (i = 0; i < ciidExclude; i++)
+ {
+ if (IsEqualIID(rgiidExclude[i], IID_IStorage))
+ {
+ fCopyStorage = FALSE;
+ }
+ else if ( IsEqualIID ( rgiidExclude[i], IID_IStream ) )
+ {
+ fCopyStreams = FALSE;
+ }
+ }
+
+ sc = S_OK;
+
+ if (fCopyStorage)
+ {
+ SCODE scFinal;
+ WCHAR pwcsName[MAXIMUM_FILENAME_LENGTH];
+ FILEDIR fd;
+ CNtEnum nte;
+ CDfName dfn;
+ BOOL fOfs;
+ HANDLE hDest = NULL;
+
+ // henrylee: BUGBUG this is a hack to detect copyto a docfile
+ INativeFileSystem *pINFS;
+ if (SUCCEEDED(pstgDest->QueryInterface (IID_INativeFileSystem,
+ (void**) &pINFS)))
+ {
+ pINFS->GetHandle(&hDest);
+ pINFS->Release();
+ grfModeTo2 = grfModeTo;
+ fOfs = TRUE;
+ }
+ else
+ { // permissions for docfile compatibility
+ grfModeTo = STGM_WRITE | STGM_SHARE_EXCLUSIVE;
+ grfModeTo2 = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
+ fOfs = FALSE;
+ }
+
+ scFinal = S_OK;
+ ssAssert(_h != NULL);
+ ssChk(nte.InitFromHandle(_h, TRUE));
+ for (;;)
+ {
+ sc = nte.Next(&stat, pwcsName, NTE_BUFFERNAME, &fd);
+ if (sc == S_FALSE)
+ break;
+ else if (FAILED(sc))
+ olErr(EH_Err, sc);
+
+ // Ignore . and ..
+ if (!wcscmp(pwcsName, L".") || !wcscmp(pwcsName, L".."))
+ continue;
+
+ // BUGBUG: [mikese] What's wrong with raw pwcsName?
+ dfn.Set(pwcsName);
+ if (snbExclude == NULL || !NameInSNB(&dfn, snbExclude))
+ {
+ if ( stat.type == STGTY_STORAGE )
+ {
+ SafeIStorage pstgFrom, pstgTo;
+ STATSTG statTo;
+
+ olHChkTo(EH_Next, OpenStorage(pwcsName, NULL,
+ grfModeFrom,
+ NULL, NULL, &pstgFrom));
+
+ // We know that the source must be an embedding (STGFMT_DOCUMENT)
+ sc = pstgDest->CreateStorage( pwcsName,
+ grfModeTo | STGM_FAILIFTHERE,
+ STGFMT_DOCUMENT,
+ NULL,
+ &pstgTo );
+ if (FAILED(sc))
+ {
+ if (sc == STG_E_FILEALREADYEXISTS)
+ {
+ // Try to open rather than creating
+ sc = pstgDest->OpenStorage( pwcsName, NULL,
+ grfModeTo2,
+ NULL, NULL,
+ &pstgTo );
+ if (SUCCEEDED(sc))
+ {
+ sc = pstgTo->Stat ( &statTo, STATFLAG_NONAME );
+ if (FAILED(sc) ||
+ statTo.STATSTG_dwStgFmt != STGFMT_DOCUMENT)
+ {
+ sc = STG_E_INVALIDFUNCTION;
+ }
+ }
+ }
+ }
+
+ if (SUCCEEDED(sc))
+ sc = pstgFrom->CopyTo( ciidExclude, rgiidExclude,
+ snbExclude, pstgTo);
+ }
+ else if ( (stat.type == STGTY_STREAM) && fCopyStreams )
+ {
+ SafeIStream pstmTo, pstmFrom;
+ static ULARGE_INTEGER uli = { 0xFFFFFFFF, 0xFFFFFFFF };
+
+ olHChkTo(EH_Next, OpenStream ( pwcsName,
+ NULL,
+ grfModeFrom,
+ 0, &pstmFrom ) );
+ // BUGBUG instead of overwriting, we create another
+ // stream and rename -- really need transacted mode
+ sc = pstgDest->CreateStream ( pwcsName,
+ grfModeTo | STGM_FAILIFTHERE,
+ 0, 0, &pstmTo );
+ if (sc == STG_E_FILEALREADYEXISTS)
+ {
+ WCHAR awcsName[MAXIMUM_FILENAME_LENGTH];
+ wcscpy (awcsName, pwcsName);
+ if (fOfs)
+ awcsName[0] = L'@';
+ IStream *pstm;
+ olHChkTo(EH_Next, pstgDest->CreateStream ( awcsName,
+ grfModeTo|STGM_CREATE,
+ 0, 0, &pstm ));
+ sc = pstmFrom->CopyTo ( pstm, uli, NULL, NULL );
+ pstm->Release();
+ if (SUCCEEDED(sc) && fOfs)
+ {
+ ssAssert (hDest != NULL);
+ WCHAR awcsSave[MAXIMUM_FILENAME_LENGTH+4];
+ wcscpy (awcsSave, pwcsName);
+ wcscat (awcsSave, L".old");
+ sc = RenameChild (hDest, pwcsName, awcsSave);
+ if (!SUCCEEDED(sc))
+ {
+ sc = DestroyTree (hDest, awcsSave, NULL, FD_FILE);
+ sc = RenameChild (hDest, pwcsName, awcsSave);
+ }
+ olHChkTo(EH_Next,RenameChild (hDest, awcsName, pwcsName));
+ sc = DestroyTree (hDest, awcsSave, NULL, FD_FILE);
+ }
+ else if (fOfs)
+ olHChkTo(EH_Next,pstgDest->DestroyElement (awcsName));
+ }
+ else if ( SUCCEEDED(sc) )
+ {
+ sc = pstmFrom->CopyTo ( pstmTo, uli, NULL, NULL );
+ }
+ }
+
+ EH_Next:
+ if (FAILED(sc))
+ scFinal = sc;
+ }
+ }
+ sc = scFinal;
+ }
+
+EH_Err:
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::CopyTo\n"));
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::MoveElementTo, public
+//
+// Synopsis: Move an element of a storage to another storage
+//
+// Arguments: [pwcsName] - Current name
+// [ptcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// Algorithm: Open source as storage or stream (whatever works)
+// Create appropriate destination
+// Copy source to destination
+// Set create time of destination equal to create time of source
+// If appropriate, delete source
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::MoveElementTo(WCHAR const *pwcsName,
+ IStorage *pstgParent,
+ WCHAR const *ptcsNewName,
+ DWORD grfFlags)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::MoveElementTo:%p("
+ "%ws, %p, %ws, %lu)\n", this, pwcsName, pstgParent,
+ ptcsNewName, grfFlags));
+
+ ssChk(ValidateSimple());
+ ssChk(Validate());
+ ssChk(VerifyMoveFlags(grfFlags));
+
+ sc = GenericMoveElement(this, pwcsName, pstgParent, ptcsNewName, grfFlags);
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::MoveElementTo => %lX\n", sc));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::Commit, public
+//
+// Synopsis: Commits transacted changes
+//
+// Arguments: [dwFlags] - DFC_*
+//
+// Returns: Appropriate status code
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::Commit(DWORD dwFlags)
+{
+ SCODE sc = S_OK;
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::Commit:%p(%lX)\n",
+ this, dwFlags));
+
+#ifdef TRANSACT_OLE
+ if (_grfMode & STGM_TRANSACTED)
+ {
+ IO_STATUS_BLOCK iosb;
+ COMMIT_PARAMETERS ftci = {FALSE, dwFlags};
+ NTSTATUS nts;
+
+ if ((dwFlags & ~(STGC_DEFAULT | STGC_ONLYIFCURRENT)) != 0)
+ ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+
+ if (!NT_SUCCESS(nts = NtFsControlFile (_h, NULL, NULL, NULL, &iosb,
+ FSCTL_XOLE_COMMIT, &ftci, sizeof(ftci), NULL, 0)))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+ }
+#endif // TRANSACT_OLE
+
+ if (_grfMode & STGM_EDIT_ACCESS_RIGHTS)
+ ssChk(CommitAccessRights(0));
+EH_Err:
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::Commit => %lX\n",sc));
+ return ssResult (sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::Revert, public
+//
+// Synopsis: Reverts transacted changes
+//
+// Returns: Appropriate status code
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::Revert(void)
+{
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::Revert:%p\n", this));
+
+ SCODE sc = S_OK;
+ ssChk(ValidateSimple());
+
+#ifdef TRANSACT_OLE
+ if (_grfMode & STGM_TRANSACTED)
+ {
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+ IO_STATUS_BLOCK iosb;
+ COMMIT_PARAMETERS ftci = {TRUE, 0L};
+ NTSTATUS nts;
+
+ if (!NT_SUCCESS(nts = NtFsControlFile (_h, NULL, NULL, NULL, &iosb,
+ FSCTL_XOLE_COMMIT, &ftci, sizeof(ftci), NULL, 0)))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+ }
+#endif // TRANSACT_OLE
+
+ if (_grfMode & STGM_EDIT_ACCESS_RIGHTS)
+ ssChk(RevertAccessRights());
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::Revert => %lX\n",sc));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::EnumElements, public
+//
+// Synopsis: Starts an iterator
+//
+// Arguments: [reserved1]
+// [reserved2]
+// [reserved3]
+// [ppenm] - Enumerator return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::EnumElements(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm)
+{
+ SCODE sc;
+ SafeCOfsDirEnum pde;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::EnumElements:%p("
+ "%lu, %p, %lu, %p)\n", this, reserved1, reserved2,
+ reserved3, ppenm));
+
+ ssChk(ValidateSimple());
+ if (ppenm == NULL)
+ ssErr (EH_Err, STG_E_INVALIDPOINTER) // missing ';' macro problem
+ else
+ ssChk(ValidateOutPtrBuffer(ppenm));
+ *ppenm = NULL;
+ if (reserved1 != 0 || reserved2 != NULL || reserved3 != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+
+ ssChk(Validate());
+
+ pde.Attach(new COfsDirEnum(TRUE));
+ olMem((COfsDirEnum *)pde);
+ ssAssert(_h != NULL);
+ ssChk(pde->InitFromHandle(_h));
+ TRANSFER_INTERFACE(pde, IEnumSTATSTG, ppenm);
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::EnumElements => %p\n",
+ *ppenm));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::DestroyElement, public
+//
+// Synopsis: Permanently deletes an element of a storage
+//
+// Arguments: [pwcsName] - Name of element
+//
+// Returns: Appropriate status code
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::DestroyElement(WCHAR const *pwcsName)
+{
+ SCODE sc = S_OK;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::DestroyElement:%p(%ws)\n",
+ this, pwcsName));
+
+ ssChk(ValidateSimple());
+ ssChk(Validate());
+
+ ssAssert(_h != NULL);
+#ifdef TRANSACT_OLE
+ if (_grfMode & STGM_TRANSACTED)
+ sc = DestroyTree(_h, pwcsName, NULL, FD_STREAM);
+ else
+#endif
+ sc = DestroyTree(_h, pwcsName, NULL, FD_FILE);
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::DestroyElement\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::RenameElement, public
+//
+// Synopsis: Renames an element of a storage
+//
+// Arguments: [pwcsName] - Current name
+// [pwcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::RenameElement(WCHAR const *pwcsName,
+ WCHAR const *pwcsNewName)
+{
+ //BUGBUG: Reimplement?
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::RenameElement:%p(%ws, %ws)\n",
+ this, pwcsName, pwcsNewName));
+
+#ifdef TRANSACT_OLE
+ if (_grfMode & STGM_TRANSACTED)
+ ssErr (EH_Err, STG_E_INVALIDFUNCTION);
+#endif
+ ssChk(ValidateSimple());
+ ssChk(Validate());
+ // pwcsName is checked by GetFileOrDirHandle
+ ssChk(CheckFdName(pwcsNewName));
+
+ ssAssert(_h != NULL);
+ sc = RenameChild(_h, pwcsName, pwcsNewName);
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::RenameElement\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::SetElementTimes, public
+//
+// Synopsis: Sets element time stamps
+//
+// Arguments: [pwcsName] - Name
+// [pctime] - Create time
+// [patime] - Access time
+// [pmtime] - Modify time
+//
+// Returns: Appropriate status code
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::SetElementTimes(WCHAR const *pwcsName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ SCODE sc;
+ SafeNtHandle h;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::SetElementTimes:%p("
+ "%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime));
+
+ if (pwcsName != NULL)
+ ssChk(ValidateSimple());
+ ssChk(Validate());
+
+ ssAssert(_h != NULL);
+ if (pwcsName != NULL)
+ {
+#ifdef TRANSACT_OLE
+ if (_grfMode & STGM_TRANSACTED)
+ ssErr (EH_Err, STG_E_INVALIDFUNCTION);
+#endif
+ ssChk(GetFileOrDirHandle(_h, pwcsName, STGM_WRITE, &h,NULL,NULL,NULL));
+ sc = SetTimes(h, pctime, patime, pmtime);
+ }
+ else
+ sc = SetTimes(_h, pctime, patime, pmtime);
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::SetElementTimes\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::SetClass, public
+//
+// Synopsis: Sets storage class
+//
+// Arguments: [clsid] - class id
+//
+// Returns: Appropriate status code
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::SetClass(REFCLSID clsid)
+{
+ SCODE sc = S_OK;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::SetClass:%p(clsid)\n", this));
+ NTSTATUS nts = RtlSetClassId(_h, &clsid);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::SetClass => %lX\n", sc));
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::SetStateBits, public
+//
+// Synopsis: Sets state bits
+//
+// Arguments: [grfStateBits] - state bits
+// [grfMask] - state bits mask
+//
+// Returns: Appropriate status code
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ NTSTATUS nts;
+ SCODE sc = S_OK;
+ IO_STATUS_BLOCK iosb;
+ FILE_OLE_STATE_BITS_INFORMATION fosbi;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::SetStateBits:%p("
+ "%lu, %lu)\n", this, grfStateBits, grfMask));
+
+ ssChk(ValidateSimple());
+ fosbi.StateBits = grfStateBits;
+ fosbi.StateBitsMask = grfMask;
+
+ nts = NtSetInformationFile(_h, &iosb, &fosbi,
+ sizeof(FILE_OLE_STATE_BITS_INFORMATION),
+ FileOleStateBitsInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+EH_Err:
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::SetStateBits => %lX\n", sc));
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::Stat, public
+//
+// Synopsis: Fills in a buffer of information about this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 07-Feb-94 PhilipLa Created
+// 24-Mar-95 HenryLee Set drive letter to fix Stat problem
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+ STATSTG stat;
+ FILEDIR fd;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStorage::Stat:%p(%p, %lX)\n",
+ this, pstatstg, grfStatFlag));
+
+ ssChk(ValidateSimple());
+ ssChk(VerifyStatFlag(grfStatFlag));
+ ssChk(Validate());
+
+ __try
+ {
+ ssAssert(_h != NULL);
+ stat.clsid = CLSID_NULL;
+ sc = StatNtHandle(_h, grfStatFlag, 0, &stat, NULL, NULL, &fd);
+ if (SUCCEEDED(sc))
+ {
+
+ if (stat.pwcsName)
+ if (!_fRoot)
+ {
+ // The name coming back from StatNtHandle is a full
+ // path from the root. We scan forward looking for
+ // the final "\" which delimits the name of the stream.
+
+ WCHAR *pwcs = stat.pwcsName;
+ WCHAR *pwcsSlash = pwcs;
+
+ while (*pwcs != L'\0')
+ if (*pwcs++ == L'\\')
+ pwcsSlash = pwcs;
+
+ // pwcsSlash now points at the name of the stream. Move it
+ // back to the beginning of the block
+
+ wcscpy (stat.pwcsName, pwcsSlash);
+ }
+ else
+ {
+ // Now we tack on the drive letter to the filename, since
+ // NtQueryInformationFile doesn't return the drive letter,
+ // and NtQueryObject returns something like
+ // "\Device\Harddisk1\Partition1" // HenryLee
+ SetDriveLetter (stat.pwcsName, _wcDrive);
+ }
+
+// BUGBUG: Can't put this assert in until we have a way to distinguish
+// an empty storage from a directory. :-(
+// ssAssert(fd == FD_STORAGE);
+ stat.grfMode = _grfMode &
+ (STGM_DIRECT | STGM_TRANSACTED | STGM_READ |
+ STGM_WRITE | STGM_READWRITE | STGM_SHARE_DENY_NONE |
+ STGM_SHARE_DENY_READ | STGM_SHARE_DENY_WRITE |
+ STGM_SHARE_EXCLUSIVE | STGM_PRIORITY |
+ STGM_DELETEONRELEASE);
+
+ stat.cbSize.HighPart = stat.cbSize.LowPart = 0;
+ stat.STATSTG_dwStgFmt = STGFMT_DOCUMENT;
+ *pstatstg = stat;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (stat.pwcsName)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ sc = HRESULT_FROM_NT(GetExceptionCode());
+ }
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStorage::Stat\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::ValidateMode, private
+//
+// Synopsis: Checks for legal access modes
+//
+// Arguments: [grfMode] - Mode
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jul-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDocStorage::ValidateMode(DWORD grfMode)
+{
+ SCODE sc = S_OK;
+
+ ssDebugOut((DEB_ITRACE, "In COfsDocStorage::ValidateMode:%p(0x%lX)\n",
+ this, grfMode));
+ // BUGBUG - Can we simply ignore priority mode?
+#ifdef TRANSACT_OLE
+ if (grfMode & STGM_TRANSACTED)
+ {
+ if ((grfMode &
+ (STGM_SHARE_DENY_NONE | STGM_SHARE_DENY_READ |
+ STGM_SHARE_DENY_WRITE | STGM_SHARE_EXCLUSIVE)) !=
+ STGM_SHARE_DENY_NONE)
+ ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+ if (grfMode & STGM_DELETEONRELEASE)
+ ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+ }
+#endif
+ if ((grfMode & STGM_CONVERT) != 0)
+ ssErr (EH_Err, STG_E_INVALIDFLAG);
+
+ ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::ValidateMode => 0x%lX\n",
+ sc));
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::ExtValidate, private
+//
+// Synopsis: COfsPropSet validation routine
+//
+// History: 18-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDocStorage::ExtValidate(void)
+{
+ return Validate();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::GetHandle, private from INativeFileSystem
+//
+// Synopsis: Get the internal handle
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDocStorage::GetHandle(HANDLE *ph)
+{
+ *ph = _h;
+ return(S_OK);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::ExcludeEntries, public
+//
+// Synopsis: excludes the SNB list after opening
+//
+// Arguments: [snbExclude] - zero out these elements
+//
+// Returns: Appropriate status code
+//
+// History: 09-Aug-95 HenryLee Created
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDocStorage::ExcludeEntries (SNB snbExclude)
+{
+ SCODE sc = S_OK;
+ IEnumSTATSTG *penm;
+ IStorage *pstg;
+ IStream *pstm;
+ STATSTG sstg;
+ CDfName dfnName;
+ const ULARGE_INTEGER uli = {0, 0};
+
+ ssAssert (this != NULL);
+ ssDebugOut((DEB_ITRACE, "In COfsDocStorage::ExcludeEntries(%p)\n", this));
+ ssChk(EnumElements(0, NULL, 0, &penm));
+ for (;;)
+ {
+ olChkTo(EH_penm, penm->Next(1, &sstg, NULL));
+ if (S_FALSE == sc)
+ {
+ sc = S_OK;
+ break;
+ }
+ dfnName.Set (sstg.pwcsName);
+ if (NameInSNB (&dfnName, snbExclude) == S_OK)
+ {
+ switch (REAL_STGTY(sstg.type))
+ {
+ case STGTY_STORAGE:
+ ssChkTo(EH_pwcsName, DestroyTree(_h,
+ sstg.pwcsName, NULL, FD_STORAGE));
+ ssChkTo(EH_pwcsName, CreateStorage(sstg.pwcsName,
+ STGM_READWRITE | STGM_CREATE,
+ STGFMT_DOCUMENT, NULL, &pstg));
+ ssVerSucc(pstg->Release());
+ break;
+ case STGTY_STREAM:
+ ssChkTo(EH_pwcsName, OpenStream(sstg.pwcsName, NULL,
+ STGM_WRITE, NULL, &pstm));
+ sc = pstm->SetSize(uli);
+ ssVerSucc(pstm->Release());
+ break;
+ default:
+ break;
+ }
+ }
+EH_pwcsName:
+ TaskMemFree(sstg.pwcsName);
+ if (FAILED(sc))
+ break;
+ }
+EH_penm:
+ ssVerSucc(penm->Release());
+
+ ssDebugOut((DEB_ITRACE, "Out COfsDocStorage::ExcludeEntries\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::GetStorage, public IPrivateStorage
+//
+// Synopsis: Returns the IStorage for this object.
+//
+// Notes: This member is called by CPropertyStorage.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(IStorage *)
+COfsDocStorage::GetStorage(VOID)
+{
+ return this;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::Lock, public IPrivateStorage
+//
+// Synopsis: Acquires the semaphore associated with the docfile.
+//
+// Notes: This member is called by CPropertyStorage.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP
+COfsDocStorage::Lock(DWORD dwTimeout)
+{
+ return STG_E_UNIMPLEMENTEDFUNCTION;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::Unlock, public IPrivateStorage
+//
+// Synopsis: Releases the semaphore associated with the docfile.
+//
+// Notes: This member is called by CPropertyStorage.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(VOID)
+COfsDocStorage::Unlock(VOID)
+{
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStorage::GetServerInfo, public IStorageReplica
+//
+// Synopsis: Get the actual DFS path for a storage's home location
+//
+// Notes: This member is exposed for Internal Use Only
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStorage::GetServerInfo(
+ IN OUT LPWSTR lpServerName,
+ IN OUT LPDWORD lpcbServerName,
+ IN OUT LPWSTR lpReplSpecificPath,
+ IN OUT LPDWORD lpcbReplSpecificPath)
+{
+ return GetHandleServerInfo (_h,
+ lpServerName,
+ lpcbServerName,
+ lpReplSpecificPath,
+ lpcbReplSpecificPath);
+}
+
diff --git a/private/ole32/stg/ofsstg/odocstg.hxx b/private/ole32/stg/ofsstg/odocstg.hxx
new file mode 100644
index 000000000..f3fe87d6c
--- /dev/null
+++ b/private/ole32/stg/ofsstg/odocstg.hxx
@@ -0,0 +1,181 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: odocstg.hxx
+//
+// Contents: COfsDocStorage header
+//
+// Classes: COfsDocStorage
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ODOCSTG_HXX__
+#define __ODOCSTG_HXX__
+
+#include <accstg.hxx>
+#include <psetstg.hxx>
+#include <omarshal.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: COfsDocStorage (ds)
+//
+// Purpose: Implements IStorage for a compound doc on OFS
+//
+// Interface: See below
+//
+// History: 07-Feb-94 PhilipLa Created
+// 24-Mar-95 HenryLee Store drive letter fix Stat problem
+//
+//----------------------------------------------------------------------------
+
+interface COfsDocStorage
+ : public CPropertySetStorage,
+ INHERIT_TRACKING,
+ public IStorage,
+ public CAccessControl,
+ public INativeFileSystem,
+ public CNtHandleMarshal,
+ public IStorageReplica,
+ public IPrivateStorage
+{
+public:
+ COfsDocStorage(void);
+ SCODE InitFromHandle(HANDLE h,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ BOOL fRoot);
+ SCODE InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSECURITY_ATTRIBUTES pssSecurity,
+ BOOL fRoot);
+ ~COfsDocStorage(void);
+ SCODE ExcludeEntries (SNB snbExclude);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // IStorage
+ STDMETHOD(CreateStream)(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(OpenStream)(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(CreateStorage)(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD stgType,
+ LPSTGSECURITY pssSecurity,
+ IStorage **ppstg);
+ STDMETHOD(OpenStorage)(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg);
+ STDMETHOD(CopyTo)(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest);
+ STDMETHOD(MoveElementTo)(WCHAR const *lpszName,
+ IStorage *pstgDest,
+ WCHAR const *lpszNewName,
+ DWORD grfFlags);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(EnumElements)(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm);
+ STDMETHOD(DestroyElement)(WCHAR const *pwcsName);
+ STDMETHOD(RenameElement)(WCHAR const *pwcsOldName,
+ WCHAR const *pwcsNewName);
+ STDMETHOD(SetElementTimes)(const WCHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+ STDMETHOD(SetClass)(REFCLSID clsid);
+ STDMETHOD(SetStateBits)(DWORD grfStateBits, DWORD grfMask);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+
+ //INativeFileSystem
+ STDMETHOD(GetHandle)(HANDLE *ph);
+
+#ifdef NEWPROPS
+ // IPrivateStorage
+ STDMETHOD_(IStorage *,GetStorage)(VOID);
+ STDMETHOD(Lock)(DWORD dwTime);
+ STDMETHOD_(VOID, Unlock)(VOID);
+#endif
+
+ //IStorageReplica
+ STDMETHOD(GetServerInfo) (IN OUT LPWSTR lpServerName,
+ IN OUT LPDWORD lpcbServerName,
+ IN OUT LPWSTR lpReplSpecificPath,
+ IN OUT LPDWORD lpcbReplSpecificPath);
+
+protected:
+ inline SCODE Validate(void) const;
+ inline SCODE ValidateSimple () const;
+ virtual SCODE ExtValidate(void);
+ SCODE ValidateMode(DWORD grfMode);
+
+ ULONG _sig;
+ DWORD _grfMode;
+ BOOL _fRoot;
+ WCHAR _wcDrive;
+ NuSafeNtHandle _h;
+};
+
+SAFE_INTERFACE_PTR(SafeCOfsDocStorage, COfsDocStorage);
+
+#define COfsDocStorage_SIG LONGSIG('O', 'D', 'D', 'G')
+#define COfsDocStorage_SIGDEL LONGSIG('O', 'd', 'D', 'g')
+
+//+--------------------------------------------------------------
+//
+// Member: COfsDocStorage::Validate, private
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 24-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE COfsDocStorage::Validate(void) const
+{
+ return (this == NULL || _sig != COfsDocStorage_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsDocStorage::ValidateSimple, private
+//
+// Synopsis: Determines if simple mode was requested
+//
+// Returns: Returns STG_E_INVALIDFUNCTION for failure
+//
+// History: 08-Aug-95 HenryLee created
+//
+//---------------------------------------------------------------
+
+inline SCODE COfsDocStorage::ValidateSimple() const
+{
+ return (_grfMode & STGM_SIMPLE) ? STG_E_INVALIDFUNCTION : S_OK;
+}
+
+#endif // #ifndef __ODOCSTG_HXX__
diff --git a/private/ole32/stg/ofsstg/odocstm.cxx b/private/ole32/stg/ofsstg/odocstm.cxx
new file mode 100644
index 000000000..349d1fe42
--- /dev/null
+++ b/private/ole32/stg/ofsstg/odocstm.cxx
@@ -0,0 +1,1087 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: odocstm.cxx
+//
+// Contents: IStream for documents implementation
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include "odocstm.hxx"
+#include <iofs.h>
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStream::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStream::QueryInterface:%p(riid, %p)\n",
+ this, ppvObj));
+ if (!IsValidIid(iid))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+ if (IsEqualIID(iid, IID_IStream) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IStream *)this;
+ COfsDocStream::AddRef();
+ }
+ else
+ if (IsEqualIID(iid, IID_INativeFileSystem))
+ {
+ *ppvObj = (INativeFileSystem *)this;
+ COfsDocStream::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IAccessControl))
+ {
+ *ppvObj = (IAccessControl *) this;
+ COfsDocStream::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IOverlappedStream))
+ {
+ *ppvObj = (IOverlappedStream *) this;
+ COfsDocStream::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IMarshal) &&
+ (_grfMode & STGM_DELETEONRELEASE) == 0)
+ {
+ // use standard marshaling for delete-on-release to
+ // prevent STG_E_REVERTED problems
+ *ppvObj = (IMarshal *) this;
+ COfsDocStream::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppvObj = NULL;
+ }
+ ssDebugOut((DEB_TRACE, "Out COfsDocStream::QueryInterface => %p\n",
+ *ppvObj));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::COfsDocStream, public
+//
+// Synopsis: Empty object constructor
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+COfsDocStream::COfsDocStream(void)
+{
+ ssDebugOut((DEB_ITRACE, "In COfsDocStream::COfsDocStream:%p()\n", this));
+ _sig = 0;
+ _liSeekPtr.LowPart = _liSeekPtr.HighPart = 0xffffffff;
+ InitializeCriticalSection (&_csSeekPtr);
+ ssDebugOut((DEB_ITRACE, "Out COfsDocStream::COfsDocStream\n"));
+ ENLIST_TRACKING(COfsDocStream);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::InitCommon, private
+//
+// Synopsis: Common initialization code
+//
+// Arguments: [co] - For detecting creation flags
+//
+// Returns: Appropriate status code
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+#if 0
+SCODE COfsDocStream::InitCommon(CREATEOPEN co)
+{
+ NTSTATUS nts;
+ SCODE sc;
+ IO_STATUS_BLOCK iosb;
+ FILE_POSITION_INFORMATION fpi;
+ FILE_END_OF_FILE_INFORMATION feofi;
+
+ ssDebugOut((DEB_ITRACE, "In COfsDocStream::InitCommon:%p(%d)\n",
+ this, co));
+
+ //BUGBUG: This assumption is no longer true.
+ // If we're supposed to be creating, truncate
+ // STGM_CREATE must have been passed since FAILIFTHERE always will fail
+ if (co == CO_CREATE)
+ {
+ feofi.EndOfFile.LowPart = 0;
+ feofi.EndOfFile.HighPart = 0;
+ nts = NtSetInformationFile(_h, &iosb, &feofi,
+ sizeof(FILE_END_OF_FILE_INFORMATION),
+ FileEndOfFileInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+ }
+
+ // Make sure the file pointer is at zero
+ fpi.CurrentByteOffset.LowPart = 0;
+ fpi.CurrentByteOffset.HighPart = 0;
+ nts = NtSetInformationFile(_h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_ITRACE, "Out COfsDocStream::InitCommon\n"));
+ EH_Err:
+ return sc;
+}
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::InitFromHandle, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [h] - Handle to duplicate
+// [pwcsName] - used to extract drive letter
+// [grfMode] - Mode of handle
+// [fRestricted] - turn on restrictions for Dsys
+//
+// Returns: Appropriate status code
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+// Notes: Takes a new reference on the given handle
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDocStream::InitFromHandle(HANDLE h,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ BOOL fRestricted)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In COfsDocStream::InitFromHandle:%p("
+ "%p, %lX)\n", this, h, grfMode));
+
+ ssChk(ValidateMode(grfMode));
+ _h = h;
+ ssAssert (_h != NULL);
+
+ _grfMode = grfMode;
+ _sig = COfsDocStream_SIG;
+ ssChk(InitAccessControl(_h, _grfMode, FALSE, NULL));
+ ssChk(InitNtHandleMarshal(_h, _grfMode, STGFMT_DOCUMENT));
+ _fRestricted = fRestricted;
+
+ ssDebugOut((DEB_ITRACE, "Out COfsDocStream::InitFromHandle\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::InitFromPath, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [hParent] -- Handle of parent storage
+// [pwcsName] -- Name to open or create
+// [grfMode] -- Mode of stream
+// [co] -- Create/open flag
+// [pssSecurity] -- Security parameters
+//
+// Returns: Appropriate status code
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDocStream::InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ BOOL fRestricted,
+ LPSECURITY_ATTRIBUTES pssSecurity)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In COfsDocStream::InitFromPath:%p("
+ "%p, %ws, %lX, %d, %p)\n", this, hParent, pwcsName, grfMode,
+ co, pssSecurity));
+
+ ssChk(ValidateMode(grfMode));
+ if (pssSecurity != NULL)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+
+ ssChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co, FD_STREAM,
+ pssSecurity, &_h));
+
+ _grfMode = grfMode;
+ _sig = COfsDocStream_SIG;
+ ssChk(InitAccessControl(_h, _grfMode, FALSE, NULL));
+ ssChk(InitNtHandleMarshal(_h, _grfMode, STGFMT_DOCUMENT));
+ _fRestricted = fRestricted;
+
+ ssDebugOut((DEB_ITRACE, "Out COfsDocStream::InitFromPath\n"));
+ EH_Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::InitClone, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [h] - Handle to duplicate
+// [grfMode] - Mode of handle
+// [liSeekPtr] - Seek pointer of handle
+//
+// Returns: Appropriate status code
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+// Notes: Takes a new reference on the given handle
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDocStream::InitClone(HANDLE h,DWORD grfMode,LARGE_INTEGER liSeekPtr)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In COfsDocStream::InitClone:%p(%p, %lX)\n",
+ this, h, grfMode));
+
+ ssChk(ValidateMode(grfMode));
+ ssChk(DupNtHandle(h, &_h));
+
+ _grfMode = grfMode;
+ _sig = COfsDocStream_SIG;
+ _liSeekPtr.QuadPart = liSeekPtr.QuadPart;
+
+ ssDebugOut((DEB_ITRACE, "Out COfsDocStream::InitClone\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::~COfsDocStream, public
+//
+// Synopsis: Destructor
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+COfsDocStream::~COfsDocStream(void)
+{
+ ssDebugOut((DEB_ITRACE, "In COfsDocStream::~COfsDocStream:%p()\n", this));
+ _sig = COfsDocStream_SIGDEL;
+ DeleteCriticalSection (&_csSeekPtr);
+ ssDebugOut((DEB_ITRACE, "Out COfsDocStream::~COfsDocStream\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::Read, public
+//
+// Synopsis: Read from a stream
+//
+// Arguments: [pb] - Buffer
+// [cb] - Count of bytes to read
+// [pcbRead] - Return number of bytes read
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStream::Read(VOID *pb, ULONG cb, ULONG *pcbRead)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+ BOOL fClone = _liSeekPtr.HighPart != 0xffffffff ||
+ _liSeekPtr.LowPart != 0xffffffff;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStream::Read:%p(%p, %lu, %p)\n",
+ this, pb, cb, pcbRead));
+
+ sc = S_OK;
+ ssChk(Validate());
+
+ ssAssert(_h != NULL);
+ nts = NtReadFile(_h, NULL, NULL, NULL, &iosb, pb, cb,
+ (fClone ? &_liSeekPtr : NULL) ,NULL);
+ if (!NT_SUCCESS(nts))
+ {
+ if (nts != STATUS_END_OF_FILE)
+ sc = NtStatusToScode(nts);
+ else
+ iosb.Information = 0;
+ }
+ else if (fClone)
+ {
+ EnterCriticalSection (&_csSeekPtr);
+ _liSeekPtr.LowPart += iosb.Information;
+ LeaveCriticalSection (&_csSeekPtr);
+ }
+
+ if (pcbRead)
+ {
+ if (SUCCEEDED(sc))
+ *pcbRead = iosb.Information;
+ else
+ *pcbRead = 0;
+ }
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStream::Read => %lu\n",
+ iosb.Information));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::Write, public
+//
+// Synopsis: Write to a stream
+//
+// Arguments: [pb] - Buffer
+// [cb] - Count of bytes to write
+// [pcbWritten] - Return of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbWritten]
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStream::Write(VOID const *pb,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+ BOOL fClone = _liSeekPtr.HighPart != 0xffffffff ||
+ _liSeekPtr.LowPart != 0xffffffff;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStream::Write:%p(%p, %lu, %p)\n",
+ this, pb, cb, pcbWritten));
+
+ sc = S_OK;
+ ssChk(Validate());
+
+ ssAssert(_h != NULL);
+ nts = NtWriteFile(_h, NULL, NULL, NULL, &iosb, (void *)pb, cb,
+ (fClone ? &_liSeekPtr : NULL) , NULL);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else if (fClone)
+ {
+ EnterCriticalSection (&_csSeekPtr);
+ _liSeekPtr.LowPart += iosb.Information;
+ LeaveCriticalSection (&_csSeekPtr);
+ }
+
+ if (pcbWritten)
+ {
+ if (SUCCEEDED(sc))
+ *pcbWritten = iosb.Information;
+ else
+ *pcbWritten = 0;
+ }
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStream::Write => %lu\n",
+ iosb.Information));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::Seek, public
+//
+// Synopsis: Seek to a point in a stream
+//
+// Arguments: [dlibMove] - Offset to move by
+// [dwOrigin] - SEEK_SET, SEEK_CUR, SEEK_END
+// [plibNewPosition] - Return of new offset
+//
+// Returns: Appropriate status code
+//
+// Modifies: [plibNewPosition]
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStream::Seek(LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+ FILE_POSITION_INFORMATION fpi;
+ FILE_STANDARD_INFORMATION fsi;
+ BOOL fClone = _liSeekPtr.HighPart != 0xffffffff ||
+ _liSeekPtr.LowPart != 0xffffffff;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStream::Seek:%p(%ld:%ld, %lu, %p)\n",
+ this, dlibMove.HighPart, dlibMove.LowPart, dwOrigin,
+ plibNewPosition));
+
+ if (dwOrigin != STREAM_SEEK_SET && dwOrigin != STREAM_SEEK_CUR &&
+ dwOrigin != STREAM_SEEK_END)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+
+ ssAssert(_h != NULL);
+ switch(dwOrigin)
+ {
+ case STREAM_SEEK_SET:
+ fpi.CurrentByteOffset.LowPart = dlibMove.LowPart;
+ fpi.CurrentByteOffset.HighPart = dlibMove.HighPart;
+ break;
+
+ case STREAM_SEEK_CUR:
+ if (!fClone)
+ {
+ nts = NtQueryInformationFile(_h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+ }
+ else
+ fpi.CurrentByteOffset.QuadPart = _liSeekPtr.QuadPart;
+
+ // Check for seek before beginning and overflow
+ if (dlibMove.HighPart < 0)
+ {
+ if ((-dlibMove.QuadPart) > fpi.CurrentByteOffset.QuadPart)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+ }
+ else if (!((fpi.CurrentByteOffset.QuadPart + dlibMove.QuadPart) >=
+ fpi.CurrentByteOffset.QuadPart))
+ {
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+ }
+
+ fpi.CurrentByteOffset.QuadPart =
+ fpi.CurrentByteOffset.QuadPart + dlibMove.QuadPart;
+ break;
+
+ case STREAM_SEEK_END:
+ nts = NtQueryInformationFile(_h, &iosb, &fsi,
+ sizeof(FILE_STANDARD_INFORMATION),
+ FileStandardInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+
+ // Check for seek before beginning and overflow
+ if (dlibMove.HighPart < 0)
+ {
+ if (-dlibMove.QuadPart > fsi.EndOfFile.QuadPart)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+ }
+ else if (!((fsi.EndOfFile.QuadPart + dlibMove.QuadPart) >=
+ fsi.EndOfFile.QuadPart))
+ {
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+ }
+
+ fpi.CurrentByteOffset.QuadPart =
+ fsi.EndOfFile.QuadPart + dlibMove.QuadPart;
+ break;
+ }
+
+ sc = S_OK;
+ if (!fClone)
+ {
+ nts = NtSetInformationFile(_h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else if (plibNewPosition)
+ *plibNewPosition = *(ULARGE_INTEGER *)&fpi.CurrentByteOffset;
+ }
+ else
+ {
+ if (plibNewPosition)
+ *plibNewPosition = *(ULARGE_INTEGER *)&fpi.CurrentByteOffset;
+ EnterCriticalSection (&_csSeekPtr);
+ _liSeekPtr.QuadPart = fpi.CurrentByteOffset.QuadPart;
+ LeaveCriticalSection (&_csSeekPtr);
+ }
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStream::Seek => %lu:%lu\n",
+ fpi.CurrentByteOffset.HighPart,
+ fpi.CurrentByteOffset.LowPart));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::SetSize, public
+//
+// Synopsis: Sets the size of a stream
+//
+// Arguments: [ulNewSize] - New size
+//
+// Returns: Appropriate status code
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStream::SetSize(ULARGE_INTEGER ulNewSize)
+{
+ SCODE sc;
+ IO_STATUS_BLOCK iosb;
+ FILE_END_OF_FILE_INFORMATION feofi;
+ NTSTATUS nts;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStream::SetSize:%p(%lu:%lu)\n",
+ this, ulNewSize.HighPart, ulNewSize.LowPart));
+
+ sc = S_OK;
+ ssChk(Validate());
+
+ feofi.EndOfFile.LowPart = ulNewSize.LowPart;
+ feofi.EndOfFile.HighPart = (ULONG)ulNewSize.HighPart;
+ ssAssert(_h != NULL);
+ nts = NtSetInformationFile(_h, &iosb, &feofi,
+ sizeof(FILE_END_OF_FILE_INFORMATION),
+ FileEndOfFileInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStream::SetSize\n"));
+
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::CopyTo, public
+//
+// Synopsis: Copies information from one stream to another
+//
+// Arguments: [pstm] - Destination
+// [cb] - Number of bytes to copy
+// [pcbRead] - Return number of bytes read
+// [pcbWritten] - Return number of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+// [pcbWritten]
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+// Notes: We do our best to handle overlap correctly. This allows
+// CopyTo to be used to insert and remove space within a
+// stream.
+//
+// In the error case, we make no gurantees as to the
+// validity of pcbRead, pcbWritten, or either stream's
+// seek position.
+//
+//----------------------------------------------------------------------------
+
+#define CBBUFFER 8192
+
+STDMETHODIMP COfsDocStream::CopyTo(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten)
+{
+ SCODE sc;
+ LARGE_INTEGER cbRead = {0, 0}, cbWritten = {0, 0}, cbDone;
+ LARGE_INTEGER liPosFrom, liPosTo, liTmp;
+ LARGE_INTEGER liZero = {0, 0};
+ LARGE_INTEGER liStep;
+ LARGE_INTEGER licb;
+ BOOL fForward;
+ ULONG ulcbDone, cbDo;
+ SafeBytePtr pbBuffer;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStream::CopyTo:%p("
+ "%p, %lu:%lu, %p, %p)\n",
+ this, pstm, cb.HighPart, cb.LowPart, pcbRead, pcbWritten));
+
+ // BUGBUG - Possible 63-bit overflow problems?
+
+ ssChk(ValidateSimple());
+ if (!IsValidInterface(pstm))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ sc = S_OK;
+ ssChk(Validate());
+
+ if (cb.HighPart >= 0x80000000)
+ cb.HighPart = 0x7fffffff;
+ licb = *(LARGE_INTEGER *)&cb;
+
+ pbBuffer.Attach(new BYTE[CBBUFFER]);
+ ssMem((BYTE *)pbBuffer);
+
+ ssHChk(Seek(liZero, STREAM_SEEK_CUR, (ULARGE_INTEGER *)&liPosFrom));
+ ssHChk(pstm->Seek(liZero, STREAM_SEEK_CUR,
+ (ULARGE_INTEGER *)&liPosTo));
+
+ // Determine which direction to copy to avoid overlap problems
+ if ((liPosFrom.QuadPart < liPosTo.QuadPart) &&
+ (licb.QuadPart > (liPosTo.QuadPart - liPosFrom.QuadPart)))
+ {
+ liStep.HighPart = -1;
+ liStep.LowPart = (ULONG)(-CBBUFFER);
+ fForward = FALSE;
+
+ // Seek to the end of the copy area plus one step
+ // so that we're in place for the loop seek backwards
+ liTmp.QuadPart = liPosFrom.QuadPart + licb.QuadPart;
+ liTmp.QuadPart = liTmp.QuadPart - liStep.QuadPart;
+ ssHChk(Seek(liTmp, STREAM_SEEK_SET, NULL));
+ liTmp.QuadPart = liPosTo.QuadPart + licb.QuadPart;
+ liTmp.QuadPart = liTmp.QuadPart - liStep.QuadPart;
+ ssHChk(pstm->Seek(liTmp, STREAM_SEEK_SET, NULL));
+
+ // We seek backwards by twice the step size, once
+ // to back up beyond the step we just read and once
+ // more to back up to a fresh step worth of data
+ ssAssert(CBBUFFER <= 0x3fffffff);
+ liStep.LowPart *= 2;
+ }
+ else
+ {
+ liStep.HighPart = 0;
+ liStep.LowPart = CBBUFFER;
+ fForward = TRUE;
+ }
+
+ cbDone.HighPart = 0;
+ for (;;)
+ {
+ if (licb.HighPart == 0 && licb.LowPart < CBBUFFER)
+ cbDo = licb.LowPart;
+ else
+ cbDo = CBBUFFER;
+
+ if (!fForward)
+ {
+ // If we're doing the last fragment make sure we don't overshoot
+ // when backing up
+ if (cbDo < CBBUFFER)
+ {
+ liStep.LowPart /= 2;
+ liStep.LowPart -= CBBUFFER-(LONG)cbDo;
+ }
+
+ // Seek backwards to fresh data
+ ssHChkTo(EH_End, Seek(liStep, STREAM_SEEK_CUR, NULL));
+ ssHChkTo(EH_End, pstm->Seek(liStep, STREAM_SEEK_CUR, NULL));
+ }
+
+ ssHChkTo(EH_End, Read(pbBuffer, cbDo, &cbDone.LowPart));
+ if (cbDone.LowPart == 0)
+ break;
+ cbRead.QuadPart = cbRead.QuadPart + cbDone.QuadPart;
+ ssHChkTo(EH_End, pstm->Write(pbBuffer, cbDone.LowPart,
+ &ulcbDone));
+ if (ulcbDone != cbDone.LowPart)
+ ssErr(EH_End, STG_E_WRITEFAULT);
+ cbWritten.QuadPart = cbWritten.QuadPart + cbDone.QuadPart;
+
+ licb.QuadPart = licb.QuadPart - cbDone.QuadPart;
+ if (licb.HighPart < 0 ||
+ (licb.HighPart == 0 && licb.LowPart == 0))
+ break;
+ }
+
+ EH_End:
+ if (pcbRead)
+ *(LARGE_INTEGER *)pcbRead = cbRead;
+ if (pcbWritten)
+ *(LARGE_INTEGER *)pcbWritten = cbWritten;
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStream::CopyTo => %lu:%lu, %lu:%lu\n",
+ cbRead.HighPart, cbRead.LowPart, cbWritten.HighPart,
+ cbWritten.LowPart));
+ // Fall through
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::Commit, public
+//
+// Synopsis: Commits transacted changes
+//
+// Arguments: [grfCommitFlags] - Flags
+//
+// Returns: Appropriate status code
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStream::Commit(DWORD grfCommitFlags)
+{
+ NTSTATUS nts;
+ SCODE sc;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStream::Commit:%p(%lX)\n",
+ this, grfCommitFlags));
+
+ ssChk(ValidateSimple());
+ if (grfCommitFlags != STGC_DEFAULT)
+ ssErr (EH_Err, STG_E_INVALIDFLAG);
+ ssChk(Validate());
+
+ ssAssert(_h != NULL);
+ nts = NtFlushBuffersFile(_h, &iosb);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStream::Commit => %lX\n", sc));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::Revert, public
+//
+// Synopsis: Reverts transacted changes
+//
+// Returns: Appropriate status code
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStream::Revert(void)
+{
+ ssDebugOut((DEB_TRACE, "In COfsDocStream::Revert:%p\n", this));
+
+ SCODE sc = S_OK;
+ ssChk(ValidateSimple());
+EH_Err:
+ ssDebugOut((DEB_TRACE, "Out COfsDocStream::Revert => %lX\n",sc));
+ return ssResult (sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::LockRegion, public
+//
+// Synopsis: Locks a portion of the stream
+//
+// Arguments: [libOffset] - Offset to lock at
+// [cb] - Length of lock
+// [dwLockType] - LockType
+//
+// Returns: Appropriate status code
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStream::LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStream::LockRegion:%p("
+ "%lu:%lu, %lu:%lu, %lu)\n", this, libOffset.HighPart,
+ libOffset.LowPart, cb.HighPart, cb.LowPart, dwLockType));
+
+ sc = S_OK;
+ ssChk(ValidateSimple());
+ ssChk(Validate());
+ ssChk(ValidateLockType(dwLockType));
+
+ ssAssert(_h != NULL);
+ nts = NtLockFile(_h, NULL, NULL, NULL, &iosb, (PLARGE_INTEGER)&libOffset,
+ (PLARGE_INTEGER)&cb, 0, TRUE, TRUE);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStream::LockRegion\n"));
+
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::UnlockRegion, public
+//
+// Synopsis: Unlocks a locked region
+//
+// Arguments: [libOffset] - Offset to lock at
+// [cb] - Length of lock
+// [dwLockType] - LockType
+//
+// Returns: Appropriate status code
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStream::UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStream::UnlockRegion:%p("
+ "%lu:%lu, %lu:%lu, %lu)\n", this, libOffset.HighPart,
+ libOffset.LowPart, cb.HighPart, cb.LowPart, dwLockType));
+
+ sc = S_OK;
+ ssChk(ValidateSimple());
+ ssChk(Validate());
+ ssChk(ValidateLockType(dwLockType));
+
+ ssAssert(_h != NULL);
+ nts = NtUnlockFile(_h, &iosb, (PLARGE_INTEGER)&libOffset,
+ (PLARGE_INTEGER)&cb, 0);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStream::UnlockRegion\n"));
+
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::Stat, public
+//
+// Synopsis: Fills in a buffer of information about this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+ STATSTG stat;
+ FILEDIR fd;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStream::Stat:%p(%p, %lX)\n",
+ this, pstatstg, grfStatFlag));
+
+ ssChk(ValidateSimple());
+ ssChk(VerifyStatFlag(grfStatFlag));
+ ssChk(Validate());
+
+ __try
+ {
+ // \CONTENTS must be appended to name
+ ssAssert(_h != NULL);
+ sc = StatNtHandle(_h, grfStatFlag,
+ sizeof(CONTENTS_STREAM)+sizeof(WCHAR), &stat,
+ NULL, NULL, &fd);
+ if (SUCCEEDED(sc))
+ {
+ if (stat.pwcsName)
+ {
+ // The name coming back from StatNtHandle is a full
+ // path from the root. We scan forward looking for
+ // the final ":" which delimits the name of the stream.
+
+ WCHAR *pwcs = stat.pwcsName;
+ WCHAR *pwcsColon = pwcs;
+
+ while (*pwcs != L'\0')
+ if (*pwcs++ == L':')
+ pwcsColon = pwcs;
+
+ // pwcsColon now points at the name of the stream. Move it
+ // back to the beginning of the block
+
+ wcscpy (stat.pwcsName, pwcsColon);
+ }
+ stat.grfMode = _grfMode;
+ stat.type = STGTY_STREAM;
+ stat.grfLocksSupported = LOCK_EXCLUSIVE | LOCK_ONLYONCE;
+ *pstatstg = stat;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (stat.pwcsName)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ sc = HRESULT_FROM_NT(GetExceptionCode());
+ }
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStream::Stat\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::Clone, public
+//
+// Synopsis: Clones a stream
+//
+// Returns: Appropriate status code
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDocStream::Clone(IStream **ppstm)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+ FILE_POSITION_INFORMATION fpi;
+ SafeCOfsDocStream pfs;
+
+ ssDebugOut((DEB_TRACE, "In COfsDocStream::Clone:%p(%p)\n",
+ this, ppstm));
+
+ sc = S_OK;
+#ifdef TRANSACT_OLE
+ if (_fRestricted)
+ ssErr (EH_Err, STG_E_INVALIDFUNCTION);
+#endif
+ ssChk(ValidateSimple());
+ ssChk(Validate());
+
+ nts = NtQueryInformationFile(_h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+
+ EnterCriticalSection (&_csSeekPtr);
+ _liSeekPtr.QuadPart = fpi.CurrentByteOffset.QuadPart;
+ LeaveCriticalSection (&_csSeekPtr);
+
+ pfs.Attach(new COfsDocStream());
+ ssMem((COfsDocStream *)pfs);
+ ssAssert(_h != NULL);
+ ssChk(pfs->InitClone(_h, _grfMode, _liSeekPtr));
+ TRANSFER_INTERFACE(pfs, IStream, ppstm);
+
+ ssDebugOut((DEB_TRACE, "Out COfsDocStream::Clone => %p\n", *ppstm));
+
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::ValidateMode, private
+//
+// Synopsis: Validates a mode
+//
+// Arguments: [grfMode] - Mode
+//
+// Returns: Appropriate status code
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+// Notes: Streams allow any sharing permissions but ignore all of them
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDocStream::ValidateMode(DWORD grfMode)
+{
+ SCODE sc = S_OK;
+
+ ssDebugOut((DEB_ITRACE, "In COfsDocStream::ValidateMode:%p(0x%lX)\n",
+ this, grfMode));
+
+ if ((grfMode & (STGM_CONVERT | STGM_PRIORITY | STGM_DELETEONRELEASE |
+ STGM_TRANSACTED)))
+ sc = STG_E_INVALIDPARAMETER;
+
+ ssDebugOut((DEB_ITRACE, "Out COfsDocStream::ValidateMode => 0x%lX\n"));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDocStream::GetHandle, private
+//
+// Synopsis: Implements INativeFileSystem::GetHandle.
+//
+// Arguments: [ph] -- Where to put the handle.
+//
+// Returns: S_OK
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsDocStream::GetHandle(HANDLE *ph)
+{
+ *ph = _h;
+ return S_OK;
+}
+
diff --git a/private/ole32/stg/ofsstg/odocstm.hxx b/private/ole32/stg/ofsstg/odocstm.hxx
new file mode 100644
index 000000000..2dd657ad2
--- /dev/null
+++ b/private/ole32/stg/ofsstg/odocstm.hxx
@@ -0,0 +1,165 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: odocstm.hxx
+//
+// Contents: COfsDocStream header
+//
+// Classes: COfsDocStream
+//
+// History: 11-Feb-94 PhilipLa Created.
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ODOCSTM_HXX__
+#define __ODOCSTM_HXX__
+
+#include <overlap.hxx>
+#include <accstg.hxx>
+#include <omarshal.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: COfsDocStream (ds)
+//
+// Purpose: Implements IStream for a compound doc on OFS
+//
+// Interface: See below
+//
+// History: 07-Feb-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+interface COfsDocStream : public COverlappedStream,
+ INHERIT_TRACKING,
+ // public IStream,
+ public CAccessControl,
+ public CNtHandleMarshal,
+ public INativeFileSystem
+{
+public:
+ COfsDocStream(void);
+ SCODE InitFromHandle(HANDLE h,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ BOOL fRestricted);
+ SCODE InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ BOOL fRestricted,
+ LPSECURITY_ATTRIBUTES pssSecurity);
+ SCODE InitCommon(CREATEOPEN co);
+ SCODE InitClone(HANDLE h, DWORD grfMode, LARGE_INTEGER liSeekPtr);
+ ~COfsDocStream(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+
+ // *** IStream methods ***
+ STDMETHOD(Read) (THIS_ VOID HUGEP *pv,
+ ULONG cb, ULONG FAR *pcbRead);
+ STDMETHOD(Write) (THIS_ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten);
+ STDMETHOD(Seek) (THIS_ LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER FAR *plibNewPosition);
+ STDMETHOD(SetSize) (THIS_ ULARGE_INTEGER libNewSize);
+ STDMETHOD(CopyTo) (THIS_ IStream FAR *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER FAR *pcbRead,
+ ULARGE_INTEGER FAR *pcbWritten);
+ STDMETHOD(Commit) (THIS_ DWORD grfCommitFlags);
+ STDMETHOD(Revert) (THIS);
+ STDMETHOD(LockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag);
+ STDMETHOD(Clone)(THIS_ IStream FAR * FAR *ppstm);
+
+ STDMETHOD(GetHandle)(THIS_ HANDLE *ph);
+
+private:
+ inline SCODE Validate(void) const;
+ inline SCODE ValidateSimple() const;
+// virtual SCODE ExtValidate(void);
+ SCODE ValidateMode(DWORD grfMode);
+ inline SCODE ValidateLockType (DWORD lt);
+
+ ULONG _sig;
+ DWORD _grfMode;
+
+// NuSafeNtHandle _h; // moved to COverlappedStream
+ LARGE_INTEGER _liSeekPtr;
+ CRITICAL_SECTION _csSeekPtr;
+ BOOL _fRestricted; // BUGBUG restricted function for Dsys APIs only
+};
+
+SAFE_INTERFACE_PTR(SafeCOfsDocStream, COfsDocStream);
+
+#define COfsDocStream_SIG LONGSIG('O', 'D', 'S', 'T')
+#define COfsDocStream_SIGDEL LONGSIG('O', 'd', 'S', 't')
+
+//+--------------------------------------------------------------
+//
+// Member: COfsDocStream::Validate, private
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 24-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE COfsDocStream::Validate(void) const
+{
+ return (this == NULL || _sig != COfsDocStream_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsDocStream::ValidateSimple, private
+//
+// Synopsis: Determines if simple mode was requested
+//
+// Returns: Returns STG_E_INVALIDFUNCTION for failure
+//
+// History: 08-Aug-95 HenryLee created
+//
+//---------------------------------------------------------------
+
+inline SCODE COfsDocStream::ValidateSimple() const
+{
+ return (_grfMode & STGM_SIMPLE) ? STG_E_INVALIDFUNCTION : S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsDocStream::ValidateLockType, private
+//
+// Synopsis: Determines if valid locks were passed in
+//
+// Returns: Returns STG_E_INVALIDPARAMETER for failure
+//
+// History: 08-Aug-95 HenryLee created
+//
+//---------------------------------------------------------------
+inline SCODE COfsDocStream::ValidateLockType (DWORD lt)
+{
+ return ((lt) == LOCK_EXCLUSIVE || (lt) == LOCK_ONLYONCE) ?
+ S_OK : STG_E_INVALIDPARAMETER;
+}
+
+#endif // #ifndef __ODOCSTM_HXX__
diff --git a/private/ole32/stg/ofsstg/odsenm.cxx b/private/ole32/stg/ofsstg/odsenm.cxx
new file mode 100644
index 000000000..09d8db2c9
--- /dev/null
+++ b/private/ole32/stg/ofsstg/odsenm.cxx
@@ -0,0 +1,284 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: odsenm.cxx
+//
+// Contents: COfsDirEnum implementation
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include "odsenm.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirEnum::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsDirEnum::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In COfsDirEnum::QueryInterface:%p(riid, %p)\n",
+ this, ppvObj));
+ if (!IsValidIid(iid))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+ if (IsEqualIID(iid, IID_IEnumSTATSTG) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IEnumSTATSTG *)this;
+ COfsDirEnum::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppvObj = NULL;
+ }
+ ssDebugOut((DEB_TRACE, "Out COfsDirEnum::QueryInterface => %p\n",
+ *ppvObj));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirEnum::COfsDirEnum, public
+//
+// Synopsis: Constructor
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+COfsDirEnum::COfsDirEnum(BOOL fIsStorage)
+ : _nte(fIsStorage)
+{
+ ssDebugOut((DEB_ITRACE, "In COfsDirEnum::COfsDirEnum:%p(%u)\n",
+ this, fIsStorage));
+ _sig = 0;
+ _fIsStorage = fIsStorage;
+ ssDebugOut((DEB_ITRACE, "Out COfsDirEnum::COfsDirEnum\n"));
+ ENLIST_TRACKING(COfsDirEnum);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirEnum::~COfsDirEnum, public
+//
+// Synopsis: Destructor
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+COfsDirEnum::~COfsDirEnum(void)
+{
+ ssDebugOut((DEB_ITRACE, "In COfsDirEnum::~COfsDirEnum:%p()\n", this));
+ _sig = COFSDIRENUM_SIGDEL;
+ ssDebugOut((DEB_ITRACE, "Out COfsDirEnum::~COfsDirEnum\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsDirEnum::Next, public
+//
+// Synopsis: Gets N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+// [rgelt] - Array for element return
+// [pceltFetched] - If non-NULL, contains the number of
+// elements fetched
+//
+// Returns: Appropriate status code
+//
+// Modifies: [rgelt]
+// [pceltFetched]
+//
+// History: 09-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsDirEnum::Next(ULONG celt,
+ STATSTG *rgelt,
+ ULONG *pceltFetched)
+{
+ SCODE sc;
+ STATSTG *pelt = rgelt, stat;
+ ULONG celtDone;
+ FILEDIR fd;
+ CPtrCache pc;
+ WCHAR *pwcs;
+
+ ssDebugOut((DEB_TRACE, "In COfsDirEnum::Next:%p(%lu, %p, %p)\n",
+ this, celt, rgelt, pceltFetched));
+
+ if (pceltFetched == NULL && celt > 1)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+
+ __try
+ {
+ for (celtDone = 0; pelt<rgelt+celt; pelt++, celtDone++)
+ {
+ sc = _nte.NextOfs(&stat, NULL, NTE_STATNAME, &fd);
+
+ //If we're working on structured objects, then turn streams
+ // into storages.
+ if (FAILED(sc) || sc == S_FALSE)
+ break;
+
+ if ((_fIsStorage) && (fd == FD_FILE))
+ {
+ stat.type = STGTY_STREAM;
+ }
+
+ if (FAILED(sc = pc.Add(stat.pwcsName)))
+ break;
+ *pelt = stat;
+ }
+
+ if (SUCCEEDED(sc) && pceltFetched)
+ *pceltFetched = celtDone;
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ pc.StartEnum();
+ while (pc.Next((void **)&pwcs))
+ ssHVerSucc(CoMemFree(pwcs));
+ sc = HRESULT_FROM_NT(GetExceptionCode());
+ }
+
+ ssDebugOut((DEB_TRACE, "Out COfsDirEnum::Next => 0x%lX\n", sc));
+EH_Err:
+ if (FAILED(sc))
+ {
+ pc.StartEnum();
+ while (pc.Next((void **)&pwcs))
+ ssHVerSucc(CoMemFree(pwcs));
+ }
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsDirEnum::Skip, public
+//
+// Synopsis: Skips N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsDirEnum::Skip(ULONG celt)
+{
+ SCODE sc;
+ STATSTG stat;
+ FILEDIR fd;
+
+ ssDebugOut((DEB_TRACE, "In COfsDirEnum::Skip:%p(%lu)\n", this, celt));
+
+ ssChk(Validate());
+
+ while (celt-- > 0)
+ {
+ sc = _nte.Next(&stat, NULL, NTE_NONAME, &fd);
+ if (FAILED(sc) || sc == S_FALSE)
+ break;
+ }
+
+ ssDebugOut((DEB_TRACE, "Out COfsDirEnum::Skip\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsDirEnum::Reset, public
+//
+// Synopsis: Rewinds the iterator
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsDirEnum::Reset(void)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In COfsDirEnum::Reset:%p()\n", this));
+
+ ssChk(Validate());
+ _nte.Reset();
+
+ ssDebugOut((DEB_TRACE, "Out COfsDirEnum::Reset\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsDirEnum::Clone, public
+//
+// Synopsis: Clones this iterator
+//
+// Arguments: [ppenm] - Clone return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 09-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsDirEnum::Clone(IEnumSTATSTG **ppenm)
+{
+ SCODE sc;
+ SafeCOfsDirEnum pde;
+
+ ssDebugOut((DEB_TRACE, "In COfsDirEnum::Clone:%p(%p)\n", this, ppenm));
+
+#ifdef TRANSACT_OLE
+ if (_fIsStorage)
+ ssErr (EH_Err, STG_E_INVALIDFUNCTION);
+#endif
+ if (ppenm == NULL)
+ ssErr(EH_Err, STG_E_INVALIDPOINTER) // ; missing due to macro
+ else
+ ssChk((ValidateOutPtrBuffer(ppenm)));
+ ssChk(Validate());
+ *ppenm = NULL;
+
+ pde.Attach(new COfsDirEnum(_fIsStorage));
+ ssMem((COfsDirEnum *)pde);
+ ssChk(pde->InitFromHandle(_nte.GetHandle()));
+ TRANSFER_INTERFACE(pde, IEnumSTATSTG, ppenm);
+
+ ssDebugOut((DEB_TRACE, "Out COfsDirEnum::Clone => %p\n", *ppenm));
+EH_Err:
+ return ssResult(sc);
+}
diff --git a/private/ole32/stg/ofsstg/odsenm.hxx b/private/ole32/stg/ofsstg/odsenm.hxx
new file mode 100644
index 000000000..0e6596eaa
--- /dev/null
+++ b/private/ole32/stg/ofsstg/odsenm.hxx
@@ -0,0 +1,110 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: odsenm.hxx
+//
+// Contents: Directory storage enumerator
+//
+// Classes: COfsDirEnum
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ODSENM_HXX__
+#define __ODSENM_HXX__
+
+#include <ntenm.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: COfsDirEnum (de)
+//
+// Purpose: Directory storage enumerator
+//
+// Interface: IEnumSTATSTG
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class COfsDirEnum
+ : INHERIT_TRACKING,
+ public IEnumSTATSTG
+{
+public:
+ COfsDirEnum(BOOL fIsStorage);
+ inline SCODE InitFromHandle(HANDLE h);
+ ~COfsDirEnum(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // IEnumSTATSTG
+ STDMETHOD(Next)(ULONG celt, STATSTG FAR *rgelt, ULONG *pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(IEnumSTATSTG **ppenm);
+
+private:
+ inline SCODE Validate(void) const;
+
+ ULONG _sig;
+ CNtEnum _nte;
+ BOOL _fIsStorage;
+};
+
+SAFE_INTERFACE_PTR(SafeCOfsDirEnum, COfsDirEnum);
+
+#define COFSDIRENUM_SIG LONGSIG('O', 'D', 'N', 'M')
+#define COFSDIRENUM_SIGDEL LONGSIG('O', 'd', 'N', 'm')
+
+//+--------------------------------------------------------------
+//
+// Member: COfsDirEnum::Validate, private
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 09-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE COfsDirEnum::Validate(void) const
+{
+ return (this == NULL || _sig != COFSDIRENUM_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsDirEnum::InitFromHandle, public
+//
+// Synopsis: Initializes from a handle
+//
+// Arguments: [h] - Handle
+//
+// Returns: Throws exceptions on failure
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE COfsDirEnum::InitFromHandle(HANDLE h)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In COfsDirEnum::InitFromHandle:%p(%p)\n",
+ this, h));
+ sc = _nte.InitFromHandle(h, TRUE);
+ if (SUCCEEDED(sc))
+ _sig = COFSDIRENUM_SIG;
+ ssDebugOut((DEB_ITRACE, "Out COfsDirEnum::InitFromHandle => %lX\n", sc));
+ return sc;
+}
+
+#endif // #ifndef __DSENM_HXX__
diff --git a/private/ole32/stg/ofsstg/ofilstg.cxx b/private/ole32/stg/ofsstg/ofilstg.cxx
new file mode 100644
index 000000000..62cb3d04a
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ofilstg.cxx
@@ -0,0 +1,1116 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofilstg.cxx
+//
+// Contents: IStorage for files implementation
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <ctype.h>
+#include <stgutil.hxx>
+#include "filstm.hxx"
+#include "ofsenm.hxx"
+#include <iofs.h>
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In COfsFileStorage::QueryInterface:%p("
+ "riid, %p)\n", this, ppvObj));
+ if (!IsValidIid(iid))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+ if (IsEqualIID(iid, IID_IStorage) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IStorage *)this;
+ COfsFileStorage::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_INativeFileSystem))
+ {
+ *ppvObj = (INativeFileSystem *)this;
+ COfsFileStorage::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppvObj = NULL;
+ }
+ ssDebugOut((DEB_TRACE, "Out COfsFileStorage::QueryInterface => %p\n",
+ *ppvObj));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::COfsFileStorage, public
+//
+// Synopsis: Empty object constructor
+//
+// History: 30-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#pragma warning(disable: 4355)
+
+COfsFileStorage::COfsFileStorage(void)
+{
+
+#pragma warning(default: 4355)
+
+ ssDebugOut((DEB_ITRACE, "In COfsFileStorage::COfsFileStorage:%p()\n",
+ this));
+ _sig = 0;
+ ssDebugOut((DEB_ITRACE, "Out COfsFileStorage::COfsFileStorage\n"));
+ ENLIST_TRACKING(COfsFileStorage);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::InitFromPath, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [hParent] - Handle of parent directory
+// [pwcsName] - Name of directory
+// [grfMode] - Mode
+// [co] - Create or open
+// [pssSecurity] - Security
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsFileStorage::InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSECURITY_ATTRIBUTES pssSecurity)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In COfsFileStorage::InitFromPath:%p("
+ "%p, %ws, %lX, %d, %p)\n", this, hParent, pwcsName,
+ grfMode, co, pssSecurity));
+
+ ssChk(ValidateMode(grfMode));
+ ssChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co,
+ FD_FILE, pssSecurity, &_h));
+
+ _grfMode = grfMode;
+ _sig = COFSFILESTORAGE_SIG;
+
+ ssDebugOut((DEB_ITRACE, "Out COfsFileStorage::InitFromPath\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::InitFromHandle, public
+//
+// Synopsis: Initialize from a handle
+//
+// Arguments: [h] - Handle
+// [grfMode] - Mode
+//
+// Returns: Appropriate status code
+//
+// History: 14-Jul-93 DrewB Created
+//
+// Notes: Takes a new reference on the handle
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsFileStorage::InitFromHandle(HANDLE h, DWORD grfMode)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In COfsFileStorage::InitFromHandle:%p("
+ "%p, %lX)\n", this, h, grfMode));
+
+ ssChk(ValidateMode(grfMode));
+ _h = h;
+ ssAssert(_h != NULL);
+ _grfMode = grfMode;
+ _sig = COFSFILESTORAGE_SIG;
+
+ ssDebugOut((DEB_ITRACE, "Out COfsFileStorage::InitFromHandle\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::~COfsFileStorage, public
+//
+// Synopsis: Destructor
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+COfsFileStorage::~COfsFileStorage(void)
+{
+ ssDebugOut((DEB_ITRACE, "In COfsFileStorage::~COfsFileStorage()\n"));
+ _sig = COFSFILESTORAGE_SIGDEL;
+ ssDebugOut((DEB_ITRACE, "Out COfsFileStorage::~COfsFileStorage\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::CreateStream, public
+//
+// Synopsis: Creates a stream
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [reserved1]
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+// History: 28-Jun-93 DrewB Created
+//
+// Notes: Files only support the contents stream
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::CreateStream(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+ SafeCNtFileStream pfs;
+
+ ssDebugOut((DEB_TRACE, "In COfsFileStorage::CreateStream:%p("
+ "%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode,
+ reserved1, reserved2, ppstm));
+
+ ssChk(Validate());
+ if (_wcsicmp(pwcsName, CONTENTS_STREAM) != 0)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+ // Contents always exist so fail if FAILIFTHERE
+ if ((grfMode & (STGM_CREATE | STGM_CONVERT)) == 0)
+ ssErr(EH_Err, STG_E_FILEALREADYEXISTS);
+ if (reserved1 != 0 || reserved2 != 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+
+ pfs.Attach(new CNtFileStream());
+ ssMem((CNtFileStream *)pfs);
+ ssAssert(_h != NULL);
+ ssChk(pfs->InitFromHandle(_h, grfMode, CO_CREATE, NULL));
+ TRANSFER_INTERFACE(pfs, IStream, ppstm);
+
+ ssDebugOut((DEB_TRACE, "Out COfsFileStorage::CreateStream => %p\n",
+ *ppstm));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::OpenStream, public
+//
+// Synopsis: Opens an existing stream
+//
+// Arguments: [pwcsName] - Name
+// [reserved1]
+// [grfMode] - Permissions
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::OpenStream(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+ SafeCNtFileStream pfs;
+
+ ssDebugOut((DEB_TRACE, "In COfsFileStorage::OpenStream:%p("
+ "%ws, %p, %lX, %lu, %p)\n", this, pwcsName, reserved1,
+ grfMode, reserved2, ppstm));
+
+ ssChk(Validate());
+ if (_wcsicmp(pwcsName, CONTENTS_STREAM) != 0)
+ ssErr(EH_Err, STG_E_FILENOTFOUND);
+ if (reserved1 != 0 || reserved2 != 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if (grfMode & (STGM_CREATE | STGM_CONVERT))
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+
+ pfs.Attach(new CNtFileStream());
+ ssMem((CNtFileStream *)pfs);
+ ssAssert(_h != NULL);
+ ssChk(pfs->InitFromHandle(_h, grfMode, CO_OPEN, NULL));
+ TRANSFER_INTERFACE(pfs, IStream, ppstm);
+
+ ssDebugOut((DEB_TRACE, "Out COfsFileStorage::OpenStream => %p\n", *ppstm));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::CreateStorage, public
+//
+// Synopsis: Creates a child storage
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [stgType] - Type of storage to create
+// [pssSecurity] - Security
+// [ppstg] - New storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::CreateStorage (
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD stgType,
+ LPSTGSECURITY pssSecurity,
+ IStorage **ppstg)
+{
+ ssDebugOut((DEB_TRACE, "Stb COfsFileStorage::CreateStorage:%p("
+ "%ws, %lX, %lu, %p, %p)\n", this, pwcsName, grfMode,
+ stgType, pssSecurity, ppstg));
+ return ssResult(STG_E_INVALIDFUNCTION);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::OpenStorage, public
+//
+// Synopsis: Gets an existing child storage
+//
+// Arguments: [pwcsName] - Name
+// [pstgPriority] - Priority reopens
+// [grfMode] - Permissions
+// [snbExclude] - Priority reopens
+// [pssSecurity] - Security
+// [ppstg] - Storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::OpenStorage(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+{
+ ssDebugOut((DEB_TRACE, "Stb COfsFileStorage::OpenStorage:%p("
+ "%ws, %p, %lX, %p, %p, %p)\n", this, pwcsName, pstgPriority,
+ grfMode, snbExclude, reserved, ppstg));
+ return ssResult(STG_E_FILENOTFOUND);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::CopyTo, public
+//
+// Synopsis: Makes a copy of a storage
+//
+// Arguments: [ciidExclude] - Length of rgiid array
+// [rgiidExclude] - Array of IIDs to exclude
+// [snbExclude] - Names to exclude
+// [pstgDest] - Parent of copy
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::CopyTo(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest)
+{
+ SCODE sc;
+ ULONG i;
+ CDfName dfn;
+ BOOL fCopyStream = TRUE;
+ STATSTG stat;
+
+ ssDebugOut((DEB_TRACE, "In COfsFileStorage::CopyTo:%p(%lu, %p, %p, %p)\n",
+ this, ciidExclude, rgiidExclude, snbExclude, pstgDest));
+
+ ssChk(Validate());
+
+ // Copy class ID and state bits if the destination supports them
+ olChk(Stat(&stat, STATFLAG_NONAME));
+ sc = GetScode(pstgDest->SetClass(stat.clsid));
+ if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
+ olErr(EH_Err, sc);
+ sc = GetScode(pstgDest->SetStateBits(stat.grfStateBits, 0xffffffff));
+ if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
+ olErr(EH_Err, sc);
+
+ // Check exclusions
+ dfn.Set(CONTENTS_STREAM);
+ if (snbExclude != NULL && NameInSNB(&dfn, snbExclude))
+ fCopyStream = FALSE;
+ for (i = 0; i < ciidExclude; i++)
+ if (IsEqualIID(rgiidExclude[i], IID_IStream))
+ {
+ fCopyStream = FALSE;
+ }
+
+ sc = S_OK;
+
+ if (fCopyStream)
+ {
+ SafeCNtFileStream pfs;
+ SafeIStream pstm;
+ ULARGE_INTEGER cb;
+
+ // CONTENTS_STREAM is the only thing contained by a file
+ // storage, so copy it
+
+ pfs.Attach(new CNtFileStream());
+ ssMem((CNtFileStream *)pfs);
+ ssAssert(_h != NULL);
+ ssChk(pfs->InitFromHandle(_h, STGM_DIRECT | STGM_READ |
+ STGM_SHARE_DENY_NONE, CO_OPEN, NULL));
+
+ ssChk(GetScode(pstgDest->CreateStream(CONTENTS_STREAM, STGM_DIRECT |
+ STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_CREATE,
+ 0, NULL, &pstm)));
+ cb.LowPart = cb.HighPart = 0xffffffff;
+ sc = GetScode(pfs->CopyTo(pstm, cb, NULL, NULL));
+ }
+
+ ssDebugOut((DEB_TRACE, "Out COfsFileStorage::CopyTo\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::MoveElementTo, public
+//
+// Synopsis: Move an element of a storage to another storage
+//
+// Arguments: [pwcsName] - Current name
+// [ptcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// Algorithm: Open source as storage or stream (whatever works)
+// Create appropriate destination
+// Copy source to destination
+// Set create time of destination equal to create time of source
+// If appropriate, delete source
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::MoveElementTo(WCHAR const *pwcsName,
+ IStorage *pstgParent,
+ WCHAR const *ptcsNewName,
+ DWORD grfFlags)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In COfsFileStorage::MoveElementTo:%p("
+ "%ws, %p, %ws, %lu)\n", this, pwcsName, pstgParent,
+ ptcsNewName, grfFlags));
+
+ ssChk(Validate());
+ ssChk(VerifyMoveFlags(grfFlags));
+
+ sc = GenericMoveElement(this, pwcsName, pstgParent, ptcsNewName, grfFlags);
+
+ ssDebugOut((DEB_TRACE, "Out COfsFileStorage::MoveElementTo => %lX\n", sc));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::Commit, public
+//
+// Synopsis: Commits transacted changes
+//
+// Arguments: [dwFlags] - DFC_*
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::Commit(DWORD dwFlags)
+{
+ NTSTATUS nts;
+ SCODE sc;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_TRACE, "In COfsFileStorage::Commit:%p(%lX)\n",
+ this, dwFlags));
+
+ ssChk(VerifyCommitFlags(dwFlags));
+ ssChk(Validate());
+
+ ssAssert(_h != NULL);
+ nts = NtFlushBuffersFile(_h, &iosb);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ ssDebugOut((DEB_TRACE, "Out COfsFileStorage::Commit => %lX\n", sc));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::Revert, public
+//
+// Synopsis: Reverts transacted changes
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::Revert(void)
+{
+ ssDebugOut((DEB_TRACE, "Stb COfsFileStorage::Revert:%p()\n", this));
+ return NOERROR;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::EnumElements, public
+//
+// Synopsis: Starts an iterator
+//
+// Arguments: [reserved1]
+// [reserved2]
+// [reserved3]
+// [ppenm] - Enumerator return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::EnumElements(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm)
+{
+ SCODE sc;
+ SafeCOfsFileEnum pfe;
+
+ ssDebugOut((DEB_TRACE, "In COfsFileStorage::EnumElements:%p("
+ "%lu, %p, %lu, %p)\n", this, reserved1, reserved2,
+ reserved3, ppenm));
+
+ if (reserved1 != 0 || reserved2 != NULL || reserved3 != 0)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+
+ pfe.Attach(new COfsFileEnum());
+ ssMem((COfsFileEnum *)pfe);
+ ssAssert(_h != NULL);
+ ssChk(pfe->InitFromHandle(_h, FALSE));
+ TRANSFER_INTERFACE(pfe, IEnumSTATSTG, ppenm);
+
+ ssDebugOut((DEB_TRACE, "Out COfsFileStorage::EnumElements => %p\n",
+ *ppenm));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::DestroyElement, public
+//
+// Synopsis: Permanently deletes an element of a storage
+//
+// Arguments: [pwcsName] - Name of element
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::DestroyElement(WCHAR const *pwcsName)
+{
+ ssDebugOut((DEB_TRACE, "Stb COfsFileStorage::DestroyElement:%p(%ws)\n",
+ this, pwcsName));
+ if (_wcsicmp(pwcsName, CONTENTS_STREAM) == 0)
+ return ssResult(STG_E_INVALIDFUNCTION);
+ else
+ return ssResult(STG_E_FILENOTFOUND);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::RenameElement, public
+//
+// Synopsis: Renames an element of a storage
+//
+// Arguments: [pwcsName] - Current name
+// [pwcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::RenameElement(WCHAR const *pwcsName,
+ WCHAR const *pwcsNewName)
+{
+ ssDebugOut((DEB_TRACE, "Stb COfsFileStorage::RenameElement:%p(%ws, %ws)\n",
+ this, pwcsName, pwcsNewName));
+ if (_wcsicmp(pwcsName, CONTENTS_STREAM) == 0)
+ {
+ if (_wcsicmp(pwcsNewName, CONTENTS_STREAM) == 0)
+ return ssResult(STG_E_ACCESSDENIED);
+ else
+ return ssResult(STG_E_INVALIDFUNCTION);
+ }
+ else
+ return ssResult(STG_E_FILENOTFOUND);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::SetElementTimes, public
+//
+// Synopsis: Sets element time stamps
+//
+// Arguments: [pwcsName] - Name
+// [pctime] - Create time
+// [patime] - Access time
+// [pmtime] - Modify time
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::SetElementTimes(WCHAR const *pwcsName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ ssDebugOut((DEB_TRACE, "Stb COfsFileStorage::SetElementTimes:%p("
+ "%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime));
+ if (_wcsicmp(pwcsName, CONTENTS_STREAM) == 0)
+ return ssResult(STG_E_INVALIDFUNCTION);
+ else
+ return ssResult(STG_E_FILENOTFOUND);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::SetClass, public
+//
+// Synopsis: Sets storage class
+//
+// Arguments: [clsid] - class id
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::SetClass(REFCLSID clsid)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In COfsFileStorage::SetClass:%p(clsid)\n", this));
+ sc = RtlSetClassId(_h, &clsid);
+ ssDebugOut((DEB_TRACE, "Out COfsFileStorage::SetClass => %lX\n", sc));
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::SetStateBits, public
+//
+// Synopsis: Sets state bits
+//
+// Arguments: [grfStateBits] - state bits
+// [grfMask] - state bits mask
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ ssDebugOut((DEB_TRACE, "Stb COfsFileStorage::SetStateBits:%p("
+ "%lu, %lu)\n", this, grfStateBits, grfMask));
+ return ssResult(STG_E_INVALIDFUNCTION);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: StrToLong, private
+//
+// Synopsis: Converts a string to a long value
+//
+// Arguments: [pwcs] - String
+//
+// Returns: LONG
+//
+// History: 27-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+static LONG StrToLong(WCHAR *pwcs)
+{
+ LONG l = 0;
+
+ while (*pwcs >= L'0' && *pwcs <= L'9')
+ {
+ l = l*10+(int)*pwcs-(int)L'0';
+ pwcs++;
+ }
+ return l;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: Matches, private
+//
+// Synopsis: Determines if a file signature matches the given pattern
+//
+// Arguments: [h] - File handle
+// [pwcsBuf] - Pattern
+// [cb] - Size of pattern
+//
+// Returns: Appropriate status code
+//
+// History: 27-Jul-93 DrewB Created from moniker code
+//
+//----------------------------------------------------------------------------
+
+static SCODE Matches(HANDLE h, WCHAR *pwcsBuf, ULONG cb)
+{
+ // Parse <offset>,<cb>,<mask>,<pattern>
+ WCHAR *pwcs = pwcsBuf;
+ WCHAR *pwcsMask, *pwcsPattern;
+ int nOffset;
+ WORD wCb;
+ WORD wCtr;
+ BYTE bMask;
+ BYTE bPattern;
+ SafeBytePtr pbFileContents;
+ IO_STATUS_BLOCK iosb;
+ FILE_POSITION_INFORMATION fpi;
+ NTSTATUS nts;
+ LARGE_INTEGER liOriginalPos;
+ SCODE sc = S_FALSE;
+
+ nOffset = (WORD)StrToLong(pwcs);
+ while (*pwcs && *pwcs != L',')
+ pwcs++;
+ ssAssert(*pwcs == L',');
+ pwcs++;
+
+ wCb = (WORD)StrToLong(pwcs);
+ ssAssert(wCb > 0);
+ while (*pwcs && *pwcs != L',')
+ pwcs++;
+ ssAssert(*pwcs == L',');
+ pwcs++;
+ while (iswspace(*pwcs))
+ pwcs++;
+
+ // pwcsMask points to the beginning of the mask
+ pwcsMask = pwcs;
+ pwcsPattern = pwcsMask;
+ while (*pwcsPattern && *pwcsPattern != L',')
+ pwcsPattern++;
+ ssAssert(*pwcsPattern == L',');
+ pwcsPattern++;
+ while (iswspace(*pwcsPattern))
+ pwcsPattern++;
+
+ pbFileContents.Attach(new BYTE[wCb]);
+ ssMem((BYTE *)pbFileContents);
+
+ // Remember the current file position
+ nts = NtQueryInformationFile(h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+ liOriginalPos = fpi.CurrentByteOffset;
+
+ // We seek to zero if necessary since we may have read from the file before
+ if (nOffset >= 0)
+ {
+ fpi.CurrentByteOffset.LowPart = (ULONG)nOffset;
+ fpi.CurrentByteOffset.HighPart = 0;
+ nts = NtSetInformationFile(h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Seek, NtStatusToScode(nts));
+ }
+ else if (nOffset < 0)
+ {
+ fpi.CurrentByteOffset.HighPart = -1;
+ fpi.CurrentByteOffset.LowPart = (ULONG)nOffset;
+ fpi.CurrentByteOffset.QuadPart =
+ fpi.CurrentByteOffset.QuadPart + liOriginalPos.QuadPart;
+ nts = NtSetInformationFile(h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Seek, NtStatusToScode(nts));
+ }
+
+ nts = NtReadFile(h, NULL, NULL, NULL, &iosb, pbFileContents, wCb,
+ NULL, NULL);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Seek, NtStatusToScode(nts));
+
+ if (wCb == iosb.Information)
+ {
+ for (wCtr = 0; wCtr < wCb; wCtr++)
+ {
+ // Get the mask byte, 0xFF is the default
+ bMask = 0xFF;
+ if (iswxdigit(*pwcsMask))
+ {
+ bMask = iswdigit(*pwcsMask) ? *pwcsMask - L'0' :
+ toupper(*pwcsMask) - L'A' + 10;
+ pwcsMask++;
+ if (iswxdigit(*pwcsMask))
+ {
+ bMask *= 16;
+ bMask += iswdigit(*pwcsMask) ? *pwcsMask - L'0' :
+ toupper(*pwcsMask) - L'A' + 10;
+ pwcsMask++;
+ }
+ }
+ // Get the pattern byte
+ ssAssert(iswxdigit(*pwcsPattern));
+ bPattern = iswdigit(*pwcsPattern) ? *pwcsPattern - L'0' :
+ toupper(*pwcsPattern) - L'A' + 10;
+ pwcsPattern++;
+ ssAssert(iswxdigit(*pwcsPattern));
+ bPattern *= 16;
+ bPattern += iswdigit(*pwcsPattern) ? *pwcsPattern - L'0' :
+ toupper(*pwcsPattern) - L'A' + 10;
+ pwcsPattern++;
+
+ if ((BYTE)(*((BYTE *)pbFileContents + wCtr) & bMask) != bPattern)
+ ssErr(EH_Seek, S_FALSE);
+ }
+ sc = S_OK;
+ }
+
+ EH_Seek:
+ // Can't do anything about failure
+ fpi.CurrentByteOffset = liOriginalPos;
+ NtSetInformationFile(h, &iosb, &fpi,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation);
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: DoesMatchPattern, private
+//
+// Synopsis: Determines whether the given file matches its registry pattern
+//
+// Arguments: [h] - File handle
+// [pclsid] - CLSID return if successful
+//
+// Returns: Appropriate status code
+//
+// History: 27-Jul-93 DrewB Created from moniker code
+//
+//----------------------------------------------------------------------------
+
+#define CB_DEF_BUFF 80
+#define CB_DEF_NUM 10
+#define CB_DEF_PATTERN 1024
+
+SAFE_HEAP_MEMPTR(SafeWcharPtr, WCHAR);
+
+static SCODE DoesMatchPattern(HANDLE h, CLSID *pclsid)
+{
+ DWORD dwIndexClsid;
+ DWORD dwIndexPattern;
+ HKEY hkFileType;
+ HKEY hkClsid;
+ DWORD cbBuff = CB_DEF_BUFF;
+ DWORD cbNum = CB_DEF_NUM;
+ DWORD cbPattern = CB_DEF_PATTERN;
+ ULONG cb;
+ SafeWcharPtr pwcsBuff;
+ SafeWcharPtr pwcsPattern;
+ SafeWcharPtr pwcsNum;
+ SCODE sc = S_FALSE;
+
+ pwcsBuff.Attach(new TCHAR[CB_DEF_BUFF]);
+ ssMem((WCHAR *)pwcsBuff);
+ pwcsPattern.Attach(new TCHAR[CB_DEF_PATTERN]);
+ ssMem((WCHAR *)pwcsPattern);
+ pwcsNum.Attach(new TCHAR[CB_DEF_NUM]);
+ ssMem((WCHAR *)pwcsNum);
+
+ if (RegOpenKey(HKEY_CLASSES_ROOT, L"FileType", &hkFileType) ==
+ ERROR_SUCCESS)
+ {
+ for (dwIndexClsid = 0;
+ sc == S_FALSE &&
+ RegEnumKey(hkFileType, dwIndexClsid, pwcsBuff, cbBuff) ==
+ ERROR_SUCCESS;
+ ++dwIndexClsid)
+ {
+ if (RegOpenKey(hkFileType, pwcsBuff, &hkClsid) == ERROR_SUCCESS)
+ {
+ for (dwIndexPattern = 0;
+ RegEnumKey(hkClsid, dwIndexPattern, pwcsNum, cbNum) ==
+ ERROR_SUCCESS;
+ ++dwIndexPattern)
+ {
+ cb = cbPattern;
+ if (RegQueryValue(hkClsid, pwcsNum, pwcsPattern,
+ (LONG *)&cb) == ERROR_SUCCESS)
+ {
+ sc = Matches(h, pwcsPattern, cbPattern);
+ if (sc == S_OK)
+ CLSIDFromString(pwcsBuff, pclsid);
+ if (sc != S_FALSE)
+ break;
+ }
+ }
+ RegCloseKey(hkClsid);
+ }
+ }
+ RegCloseKey(hkFileType);
+ }
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::Stat, public
+//
+// Synopsis: Fills in a buffer of information about this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+// BUGBUG - Should be in an internal compobj header
+HRESULT wCoGetClassExt(WCHAR const *pwcs, CLSID *clsid);
+
+STDMETHODIMP COfsFileStorage::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+ STATSTG stat;
+ FILEDIR fd;
+ CLSID clsid;
+ WCHAR awcName[MAX_PATH];
+
+ ssDebugOut((DEB_TRACE, "In COfsFileStorage::Stat:%p(%p, %lX)\n",
+ this, pstatstg, grfStatFlag));
+
+ ssChk(VerifyStatFlag(grfStatFlag));
+ ssChk(Validate());
+
+ __try
+ {
+ ssAssert(_h != NULL);
+ sc = StatNtHandle(_h, grfStatFlag, 0, &stat, awcName, NULL, &fd);
+ if (SUCCEEDED(sc))
+ {
+ // Attempt to get a CLSID for this file
+ clsid = stat.clsid;
+ if ((sc == S_FALSE) || (STATUS_NOT_FOUND == sc))
+ {
+ sc = DoesMatchPattern(_h, &clsid);
+ if (sc == S_FALSE)
+ {
+ WCHAR *pwcsExt;
+
+ // No pattern matched, so look up the class by extension
+ pwcsExt = FindExt(awcName);
+ if (pwcsExt != NULL && wCoGetClassExt(pwcsExt, &clsid) == 0)
+ sc = S_OK;
+ }
+ }
+ if (sc == S_OK)
+ stat.clsid = clsid;
+ if (SUCCEEDED(sc))
+ {
+ stat.grfMode = _grfMode;
+ stat.cbSize.HighPart = stat.cbSize.LowPart = 0;
+ stat.STATSTG_dwStgFmt = STGFMT_FILE;
+ *pstatstg = stat;
+ sc = S_OK;
+ }
+ else if (stat.pwcsName)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (stat.pwcsName)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ sc = HRESULT_FROM_NT(GetExceptionCode());
+ }
+
+ ssDebugOut((DEB_TRACE, "Out COfsFileStorage::Stat\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::ValidateMode, private
+//
+// Synopsis: Validates a grfMode
+//
+// Arguments: [grfMode] - Mode
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsFileStorage::ValidateMode(DWORD grfMode)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In COfsFileStorage::ValidateMode:%p(0x%lX)\n",
+ this, grfMode));
+ // BUGBUG - Can we simply ignore priority mode?
+ if (grfMode & (STGM_TRANSACTED | STGM_CONVERT))
+ sc = STG_E_INVALIDFLAG;
+ else
+ sc = S_OK;
+ ssDebugOut((DEB_ITRACE, "Out COfsFileStorage::ValidateMode => 0x%lX\n",
+ sc));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::ExtValidate, private
+//
+// Synopsis: COfsPropSet validation routine
+//
+// History: 18-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsFileStorage::ExtValidate(void)
+{
+ return Validate();
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileStorage::GetHandle, private
+//
+// Synopsis: Get the handle backing this OFS IStorage.
+//
+// History: 10-May-94 BillMo Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileStorage::GetHandle(HANDLE *ph)
+{
+ SCODE sc;
+
+ ssChk(Validate());
+
+ *ph = _h;
+
+EH_Err:
+ return(ssResult(sc));
+}
diff --git a/private/ole32/stg/ofsstg/ofilstg.hxx b/private/ole32/stg/ofsstg/ofilstg.hxx
new file mode 100644
index 000000000..1d2df2027
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ofilstg.hxx
@@ -0,0 +1,134 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofilstg.hxx
+//
+// Contents: COfsFileStorage header
+//
+// Classes: COfsFileStorage
+//
+// History: 28-Jun-93 DrewB Created
+//
+// Notes: Non-OFS
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FILSTG_HXX__
+#define __FILSTG_HXX__
+
+//+---------------------------------------------------------------------------
+//
+// Class: COfsFileStorage (fs)
+//
+// Purpose: Implements IStorage for a file
+//
+// Interface: See below
+//
+// History: 28-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+interface COfsFileStorage
+ : INHERIT_TRACKING,
+ public IStorage,
+ public INativeFileSystem
+{
+public:
+ COfsFileStorage(void);
+ SCODE InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSECURITY_ATTRIBUTES pssSecurity);
+ SCODE InitFromHandle(HANDLE h, DWORD grfMode);
+ ~COfsFileStorage(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // IStorage
+ STDMETHOD(CreateStream)(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(OpenStream)(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(CreateStorage)(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD stgType,
+ LPSTGSECURITY pssSecurity,
+ IStorage **ppstg);
+ STDMETHOD(OpenStorage)(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg);
+ STDMETHOD(CopyTo)(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest);
+ STDMETHOD(MoveElementTo)(WCHAR const *lpszName,
+ IStorage *pstgDest,
+ WCHAR const *lpszNewName,
+ DWORD grfFlags);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(EnumElements)(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm);
+ STDMETHOD(DestroyElement)(WCHAR const *pwcsName);
+ STDMETHOD(RenameElement)(WCHAR const *pwcsOldName,
+ WCHAR const *pwcsNewName);
+ STDMETHOD(SetElementTimes)(const WCHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+ STDMETHOD(SetClass)(REFCLSID clsid);
+ STDMETHOD(SetStateBits)(DWORD grfStateBits, DWORD grfMask);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+
+ STDMETHOD(GetHandle(HANDLE *ph));
+
+protected:
+ inline SCODE Validate(void) const;
+ virtual SCODE ExtValidate(void);
+ SCODE ValidateMode(DWORD grfMode);
+
+ ULONG _sig;
+ DWORD _grfMode;
+ NuSafeNtHandle _h;
+};
+
+SAFE_INTERFACE_PTR(SafeCOfsFileStorage, COfsFileStorage);
+
+#define COFSFILESTORAGE_SIG LONGSIG('O', 'F', 'S', 'G')
+#define COFSFILESTORAGE_SIGDEL LONGSIG('O', 'f', 'S', 'g')
+
+//+--------------------------------------------------------------
+//
+// Member: COfsFileStorage::Validate, private
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 28-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE COfsFileStorage::Validate(void) const
+{
+ return (this == NULL || _sig != COFSFILESTORAGE_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+#endif // #ifndef __FILSTG_HXX__
diff --git a/private/ole32/stg/ofsstg/ofscs.cxx b/private/ole32/stg/ofsstg/ofscs.cxx
new file mode 100644
index 000000000..8761dc3b3
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ofscs.cxx
@@ -0,0 +1,1016 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofscs.cxx
+//
+// Contents: COfsCatalogFile implementation
+//
+// Classes: COfsCatalogFile
+//
+// History: Oct-93 DaveMont Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop // Remove for MAC build
+
+#include <align.h>
+#include <iofs.h>
+#include <stgprop.h>
+#include <logfile.hxx>
+#include <ofscs.hxx>
+#include <stgutil.hxx>
+
+
+extern VOID SetRtlUnicodeCallouts(VOID);
+
+//+-----------------------------------------------------------------------
+//
+// Method: GetOfsViewFunctionAddr, private
+//
+// Synopsis: Hoop jumping so that ole32 need not link with query.
+//
+// History: 28-Aug-95 DaveStr Created
+//
+// Notes:
+//
+//------------------------------------------------------------------------
+
+#define OFS_CREATE_VIEW 0
+#define OFS_DELETE_VIEW 1
+#define OFS_ENUMERATE_VIEWS 2
+
+FARPROC rpfnOfsView[3] = { NULL, NULL, NULL };
+
+HRESULT GetOfsViewFunctionAddr(
+ ULONG fid, // function identifier
+ VOID **ppfn)
+{
+ if ( fid > OFS_ENUMERATE_VIEWS )
+ {
+ OutputDebugStringA("\n!!! Bad ofs view function id !!!\n");
+ return(E_INVALIDARG);
+ }
+
+ if ( NULL == rpfnOfsView[fid] )
+ {
+ const CHAR *pszFunction;
+
+ switch ( fid )
+ {
+ case OFS_CREATE_VIEW:
+
+ pszFunction = "CreateView";
+ break;
+
+ case OFS_DELETE_VIEW:
+
+ pszFunction = "DeleteView";
+ break;
+
+ case OFS_ENUMERATE_VIEWS:
+
+ pszFunction = "EnumerateViews";
+ break;
+ }
+
+ HINSTANCE hDll = LoadLibraryA("query");
+
+ if ( NULL == hDll )
+ {
+ OutputDebugStringA("\n!!! query.dll not found !!!\n");
+ return(ERROR_FILE_NOT_FOUND);
+ }
+
+ rpfnOfsView[fid] = GetProcAddress(hDll, pszFunction);
+
+ if ( NULL == rpfnOfsView[fid] )
+ {
+ OutputDebugStringA("\n!!! View function not in query.dll !!!\n");
+ return(E_FAIL);
+ }
+ }
+
+ *ppfn = rpfnOfsView[fid];
+
+ return(S_OK);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsCatalogFile::InitFromHandle, public
+//
+// Synopsis: From-handle constructor
+//
+// Arguments: [h] - Handle of directory
+// [grfMode] - Mode of handle
+//
+// Returns: Appropriate status code
+//
+// History: 29-Jun-93 DrewB Created
+//
+// Notes: Takes a new reference on the handle
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsCatalogFile::InitFromHandle(HANDLE h, DWORD grfMode,
+ const WCHAR *pwcsName)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In COfsCatalogFile::InitFromHandle:%p(%p, %lX)\n",
+ this, h, grfMode));
+
+ olChk(ValidateMode(grfMode));
+ _h = h;
+ ssAssert (_h != NULL);
+
+ _grfMode = grfMode;
+ _sig = COfsDocStorage_SIG;
+ _fRoot = TRUE;
+ _wcDrive = GetDriveLetter (pwcsName);
+
+ olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::InitFromHandle\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsCatalogFile::InitFromPath, public
+//
+// Synopsis: From-path constructor
+//
+// Arguments: [hParent] - Handle of parent directory
+// [pwcsName] - Name of directory
+// [grfMode] - Mode
+// [fCreate] - Create or open
+// [pssSecurity] - Security
+//
+// Returns: Appropriate status code
+//
+// History: 24-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsCatalogFile::InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSECURITY_ATTRIBUTES pssSecurity)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In COfsCatalogFile::InitFromPath:%p("
+ "%p, %ws, %lX, %d, %p)\n", this, hParent, pwcsName, grfMode,
+ co, pssSecurity));
+
+ olChk(ValidateMode(grfMode));
+ olChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co, FD_CATALOG,
+ pssSecurity, &_h));
+
+ _grfMode = grfMode;
+ _sig = COfsDocStorage_SIG;
+ _fRoot = TRUE;
+ _wcDrive = GetDriveLetter (pwcsName);
+
+ olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::InitFromPath\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsCatalogFile::InitPath, public
+//
+// Synopsis: initialize and save the path
+//
+// Arguments: [pwszPath] - the path of the object being opened/created
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+SCODE COfsCatalogFile::InitPath(WCHAR const *pwszPath)
+{
+ SCODE sc = S_OK;
+
+ if (NULL != pwszPath)
+ {
+ // bugbug, save the path until can QI for IQuery on IStorage
+ _pwszName = (WCHAR*) CoTaskMemAlloc ((wcslen(pwszPath)+1)*sizeof(WCHAR));
+ if ( _pwszName != NULL )
+ wcscpy(_pwszName, pwszPath);
+ else
+ sc = E_OUTOFMEMORY;
+
+ } // otherwise pwszname is left null
+ return(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsCatalogFile::QueryInterface, public
+//
+// Synopsis: Return supported interfaces
+//
+// Arguments: [riid] - Interface
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsCatalogFile::QueryInterface(REFIID riid, void **ppv)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In COfsCatalogFile::QueryInterface:%p(riid, %p)\n",
+ this, ppv));
+ if (!IsValidIid(riid))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+ if (IsEqualIID(riid, IID_ISummaryCatalogStorage))
+ {
+ *ppv = (ISummaryCatalogStorage *)this;
+ COfsCatalogFile::AddRef();
+ }
+ else if (IsEqualIID(riid, IID_ISummaryCatalogStorageView))
+ {
+ *ppv = (ISummaryCatalogStorageView *)this;
+ COfsCatalogFile::AddRef();
+ }
+ else if (IsEqualIID(riid, IID_ICatalogStorage))
+ {
+ *ppv = (ICatalogStorage *)this;
+ COfsCatalogFile::AddRef();
+ }
+ else if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IStorage))
+ {
+ *ppv = (IStorage *)this;
+ COfsCatalogFile::AddRef();
+ }
+ else if (IsEqualIID(riid, IID_IPropertySetStorage))
+ {
+ *ppv = (IPropertySetStorage *)this;
+ COfsCatalogFile::AddRef();
+ }
+ else if (IsEqualIID(riid, IID_INativeFileSystem))
+ {
+ *ppv = (INativeFileSystem *)this;
+ COfsCatalogFile::AddRef();
+ }
+ else if (IsEqualIID(riid, IID_IStorageReplica))
+ {
+ *ppv = (IStorageReplica *)this;
+ COfsCatalogFile::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppv = NULL;
+ }
+ olDebugOut((DEB_TRACE, "Out COfsCatalogFile::QueryInterface => %p\n",
+ *ppv));
+ EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsCatalogFile::GetSCPath, public
+//
+// Synopsis: Return the path to the catalog storage
+// (used by Summary Catalog class code to
+// get IQuery interface via EvalQuery3)
+//
+// Arguments: [pwszPath] - path of the catalog storage
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsCatalogFile::GetSCPath(PWCHAR * pwszPath)
+{
+ SCODE sc;
+
+ if ( NULL == _pwszName)
+ {
+ sc = E_FAIL; // bugbug scaffolding error return
+ } else
+ {
+ *pwszPath = (WCHAR*)CoTaskMemAlloc ((wcslen(_pwszName)+1)*sizeof(WCHAR));
+ if ( (*pwszPath) != NULL )
+ {
+ wcscpy(*pwszPath, _pwszName);
+ sc = S_OK;
+ }
+ else
+ sc = E_OUTOFMEMORY;
+ }
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsCatalogFile::SetRows, public
+//
+// Synopsis: Sets or updates rows in a summary catalog
+//
+// Arguments: [pcols] - the columns to set in the rows to set
+// [pwids] - array of wids of rows to update
+// [crows] - the number of rows to set
+// [prows] - the variants of the rows, in the same form
+// as returned by query
+//
+// Returns: Appropriate status code
+//
+// Notes: There is a inconsistency in the way the fourth parameter
+// is passed in. We require an array of table rows rather than
+// a pointer to an array of table rows, i.e., we require a
+// TABLEROW * rather than a TABLEROW**.
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsCatalogFile::SetRows(COLUMNSET * pcols,
+ LONG * pwids,
+ ULONG cRows,
+ TABLEROW ** prows)
+{
+ SCODE sc = S_OK;
+ NTSTATUS Status;
+ HANDLE h;
+ TABLEROW *pTableRow = *prows;
+
+ SetRtlUnicodeCallouts();
+ sc = GetHandle(&h);
+ if ((sc == S_OK) && (cRows > 0)) {
+ ULONG cColumns = pcols->cCol;
+ CATALOG_ROW_INFO *pRowInfo;
+
+ pRowInfo = (CATALOG_ROW_INFO *) CoTaskMemAlloc(sizeof(CATALOG_ROW_INFO) * cRows);
+ if (pRowInfo != NULL) {
+ ULONG i;
+ for (i = 0; i < cRows; i++) {
+ if (pwids != NULL) {
+ pRowInfo[i].RowId = pwids[i];
+ } else {
+ pRowInfo[i].RowId = CATALOGSTG_ROWID_INVALID;
+ }
+ pRowInfo[i].dwReserved = 0;
+ pRowInfo[i].aVariants = pTableRow[i].aValue;
+ }
+
+ // Invoke the appropriate NT API.
+ Status = RtlUpdateCatalog(h,
+ cColumns,
+ (FULLPROPSPEC const *) pcols->aCol,
+ cRows,
+ pRowInfo);
+
+ if (!NT_SUCCESS(Status)) {
+ sc = HRESULT_FROM_NT(Status);
+ }
+
+ CoTaskMemFree(pRowInfo);
+ } else {
+ sc = E_OUTOFMEMORY;
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::SetRows\n"));
+ return ResultFromScode(sc);
+}
+
+//-----------------------------------------------------------------------------
+//
+// Member: CSCStorage::DeleteRow - public
+//
+// Synopsis: Deletes a row specified by wid in a catalog storage,
+//
+// Arguments: [wid] - the wid of the row to delete
+//
+// Returns: the apropriate error code.
+//
+//-----------------------------------------------------------------------------
+
+STDMETHODIMP COfsCatalogFile::DeleteRow(ULONG wid)
+{
+ SCODE sc = S_OK;
+ olDebugOut((DEB_ITRACE, "In COfsCatalogFile::DeleteRow:%p("
+ "%lu)\n", this, wid));
+
+ NTSTATUS Status;
+ HANDLE h;
+
+ SetRtlUnicodeCallouts();
+ sc = GetHandle(&h);
+ if (sc == S_OK) {
+ Status = RtlDeleteCatalogRows(h,1,((CATALOGSTG_ROWID *)&wid));
+ sc = HRESULT_FROM_NT(Status);
+ }
+ olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::DeleteRow\n"));
+ return(sc);
+}
+
+//+-----------------------------------------------------------------------
+//
+// Method: COfsCatalogFile::UpdateRows, public
+//
+// Synopsis: Updates catalog rows. Maps NILE-ized arguments down to
+// pre-NILE structures.
+//
+// History: 27-Jun-95 DaveStr Created
+//
+// Notes: Not necessarily efficient - temporary until VicH finalizes
+// ntdll catalog APIs.
+//
+//------------------------------------------------------------------------
+
+HRESULT COfsCatalogFile::UpdateRows(
+ ULONG cCol,
+ DBID *rDBCOLID,
+ ULONG cBinding,
+ DBBINDING *rDBBINDING,
+ ULONG cRow,
+ CATALOG_UPDATE_ROWINFO *rROWINFO)
+{
+ olDebugOut((DEB_ITRACE, "In COfsCatalogFile::UpdateRows\n"));
+
+ // Validate parameters.
+
+ if ( (0 == cCol) ||
+ (NULL == rDBCOLID) ||
+ (0 == cBinding) ||
+ (NULL == rDBBINDING) ||
+ (0 == cRow) ||
+ (NULL == rROWINFO) )
+ {
+ return(E_INVALIDARG);
+ }
+
+ // Disallow NAME-only column identifiers.
+
+ for ( ULONG col = 0; col < cCol; col++ )
+ if ( DBKIND_NAME == rDBCOLID[col].eKind )
+ return(E_INVALIDARG);
+
+ // Validate CATALOG_UPDATE_ROWINFOs.
+
+ for ( ULONG row = 0; row < cRow; row++ )
+ {
+ if ( (CATALOGSTG_DELETE < rROWINFO[row].wAction) ||
+ (0 != rROWINFO[row].wReserved) ||
+ ((CATALOGSTG_NOACTION != rROWINFO[row].wAction) &&
+ (NULL == rROWINFO[row].pData)) )
+ {
+ return(E_INVALIDARG);
+ }
+ }
+
+ HRESULT hr;
+ HANDLE hCatalog;
+
+ SetRtlUnicodeCallouts();
+ hr = GetHandle(&hCatalog);
+
+ if ( FAILED(hr) )
+ return(hr);
+
+ NTSTATUS status = RtlUpdateCatalogRows(hCatalog,
+ cCol,
+ rDBCOLID,
+ cBinding,
+ rDBBINDING,
+ cRow,
+ rROWINFO);
+
+ if ( !NT_SUCCESS(status) )
+ hr = HRESULT_FROM_NT(status);
+
+ return(hr);
+}
+
+//+-----------------------------------------------------------------------
+//
+// Method: COfsCatalogFile::CreateView, public
+//
+// Synopsis: Create a view over a summary catalog.
+//
+// History: 12-Jul-95 DaveStr Created
+// 31-Jul-95 DaveStr Implemented
+// 30-Oct-95 DaveStr Removed columns which are keys
+//
+// Notes:
+//
+//------------------------------------------------------------------------
+
+HRESULT COfsCatalogFile::CreateView(
+ CATALOG_VIEW *pView,
+ BOOL fWait)
+{
+ olDebugOut((DEB_ITRACE, "In COfsCatalogFile::CreateView\n"));
+
+ if ( (NULL == pView) ||
+ (0 == pView->cCols) ||
+ (NULL == pView->rCols) )
+ {
+ return(E_INVALIDARG);
+ }
+
+ HRESULT hr = S_OK;
+ HANDLE hCatalog;
+
+ hr = GetHandle(&hCatalog);
+
+ if ( FAILED(hr) )
+ return(hr);
+
+ // Map non-key columns in CATALOG_VIEW to a COLUMNSET and key columns
+ // to a SORTSET.
+
+ ULONG cKeys = 0;
+ ULONG cCols = pView->cCols;
+
+ for ( ULONG i = 0; i < pView->cCols; i++ )
+ {
+ if ( pView->rCols[i].fSortKey )
+ {
+ cKeys++;
+ cCols--;
+ }
+ }
+
+ COLUMNSET colset = { cCols, NULL };
+ SORTSET sortset = { cKeys, NULL };
+
+ if ( 0 != cCols )
+ {
+ colset.aCol = (FULLPROPSPEC *)
+ CoTaskMemAlloc(cCols * sizeof(FULLPROPSPEC));
+
+ if ( NULL == colset.aCol )
+ return(E_OUTOFMEMORY);
+ }
+
+ if ( 0 != cKeys )
+ {
+ sortset.aCol = (SORTKEY *) CoTaskMemAlloc(cKeys * sizeof(SORTKEY));
+
+ if ( NULL == sortset.aCol )
+ {
+ CoTaskMemFree(colset.aCol);
+ return(E_OUTOFMEMORY);
+ }
+ }
+
+ ULONG iKey = 0;
+ ULONG iCol = 0;
+
+ for ( i = 0; i < pView->cCols; i++ )
+ {
+ FULLPROPSPEC fps;
+
+ switch ( pView->rCols[i].colid.eKind )
+ {
+ case DBKIND_GUID_NAME:
+
+ fps.guidPropSet = pView->rCols[i].colid.guid;
+ fps.psProperty.ulKind = PRSPEC_LPWSTR;
+ fps.psProperty.lpwstr = (WCHAR *) pView->rCols[i].colid.pwszName;
+ break;
+
+ case DBKIND_GUID_PROPID:
+
+ fps.guidPropSet = pView->rCols[i].colid.guid;
+ fps.psProperty.ulKind = PRSPEC_PROPID;
+ fps.psProperty.lpwstr = (WCHAR *) pView->rCols[i].colid.ulPropid;
+ break;
+
+ case DBKIND_PGUID_NAME:
+
+ fps.guidPropSet = *pView->rCols[i].colid.pguid;
+ fps.psProperty.ulKind = PRSPEC_LPWSTR;
+ fps.psProperty.lpwstr = (WCHAR *) pView->rCols[i].colid.pwszName;
+ break;
+
+ case DBKIND_PGUID_PROPID:
+
+ fps.guidPropSet = *pView->rCols[i].colid.pguid;
+ fps.psProperty.ulKind = PRSPEC_PROPID;
+ fps.psProperty.lpwstr = (WCHAR *) pView->rCols[i].colid.ulPropid;
+ break;
+
+ default:
+
+ CoTaskMemFree(sortset.aCol);
+ CoTaskMemFree(colset.aCol);
+ return(E_INVALIDARG);
+ }
+
+ if ( pView->rCols[i].fSortKey )
+ {
+ sortset.aCol[iKey].propColumn = fps;
+ sortset.aCol[iKey].dwOrder = pView->rCols[i].sortOrder;
+ sortset.aCol[iKey].locale = pView->rCols[i].locale;
+ iKey++;
+ }
+ else
+ {
+ colset.aCol[iCol] = fps;
+ iCol++;
+ }
+ }
+
+ NTSTATUS (*pfn)(HANDLE, RESTRICTION *, COLUMNSET *, SORTSET *);
+ NTSTATUS nts;
+
+ hr = GetOfsViewFunctionAddr(OFS_CREATE_VIEW, (void **) &pfn);
+
+ if ( SUCCEEDED(hr) )
+ {
+ nts = (pfn)(hCatalog,
+ (RESTRICTION *) NULL,
+ &colset,
+ &sortset);
+
+ if ( !NT_SUCCESS(nts) )
+ {
+ hr = HRESULT_FROM_NT(nts);
+ }
+ }
+
+ CoTaskMemFree(sortset.aCol);
+ CoTaskMemFree(colset.aCol);
+
+ if ( SUCCEEDED(hr) && fWait )
+ {
+ while ( TRUE )
+ {
+ LONG_OPERATION_STATUS lstatus;
+ IO_STATUS_BLOCK iosb;
+
+ nts = NtFsControlFile(hCatalog, NULL, NULL, NULL, &iosb,
+ FSCTL_OFS_LONG_OPERATION_STATUS,
+ NULL, 0, &lstatus, sizeof(lstatus));
+
+ if ( !NT_SUCCESS(nts) )
+ {
+ hr = HRESULT_FROM_NT(nts);
+ break;
+ }
+
+ if ( !lstatus.fPending )
+ break;
+
+ Sleep(10); // 10 ms
+ }
+ }
+
+ olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::CreateView\n"));
+
+ return(hr);
+}
+
+//+-----------------------------------------------------------------------
+//
+// Method: MapSingleView, internal helper
+//
+// Synopsis: Maps a single VIEW_INDEX_ENTRY to a single CATALOG_VIEW.
+// All fields allocated via CoTaskMemAlloc - see ReleaseViews.
+// Returned DBID are always either DBKIND_GUID_PROPID or
+// DBKIND_GUID_NAME.
+//
+// History: 31-Jul-95 DaveStr Created
+//
+// Notes:
+//
+//------------------------------------------------------------------------
+
+HRESULT MapSingleView(
+ VIEW_INDEX_ENTRY *pvie,
+ CATALOG_VIEW *pcv)
+{
+ pcv->id = pvie->id;
+ pcv->cCols = pvie->ccol;
+
+ pcv->rCols = (CATALOG_VIEW_COLUMN *)
+ CoTaskMemAlloc(pcv->cCols * sizeof(CATALOG_VIEW_COLUMN));
+
+ if ( NULL == pcv->rCols )
+ return(E_OUTOFMEMORY);
+
+ // pvie->avc can not be indexed via subscript because VIEW_COLUMN
+ // structs are varying length! Use pointer instead.
+
+ VIEW_COLUMN *pCurViewCol = &pvie->avc[0];
+
+ for ( ULONG i = 0; i < pcv->cCols; i++ )
+ {
+ // First pvie->ckey columns are sort key columns.
+ pcv->rCols[i].fSortKey = (i < pvie->ckey);
+ // BUGBUG - manufacture an LCID since Ofs APIs don't return it.
+ pcv->rCols[i].locale = 0xffffffff;
+ pcv->rCols[i].sortOrder = pCurViewCol->dwOrder;
+ pcv->rCols[i].colid.guid = pCurViewCol->PropertySet;
+
+ if ( 0 == pCurViewCol->cwcName )
+ {
+ pcv->rCols[i].colid.eKind = DBKIND_GUID_PROPID;
+ pcv->rCols[i].colid.ulPropid = pCurViewCol->propid;
+ }
+ else
+ {
+ pcv->rCols[i].colid.eKind = DBKIND_GUID_NAME;
+
+ // VIEW_COLUMN.cwcName field does not include the L'\0',
+ // even though the appended name *is* terminated.
+
+ pcv->rCols[i].colid.pwszName = (WCHAR *)
+ CoTaskMemAlloc(sizeof(WCHAR) * (1 + pCurViewCol->cwcName));
+
+ if ( NULL == pcv->rCols[i].colid.pwszName )
+ {
+ for ( ULONG j = 0; j < i; j++ )
+ if ( DBKIND_GUID_NAME == pcv->rCols[j].colid.eKind )
+ CoTaskMemFree((WCHAR *) pcv->rCols[j].colid.pwszName);
+
+ CoTaskMemFree(pcv->rCols);
+ pcv->rCols = NULL;
+ return(E_OUTOFMEMORY);
+ }
+
+ wcscpy((WCHAR *) pcv->rCols[i].colid.pwszName,
+ (WCHAR *) ((BYTE *) pCurViewCol + sizeof(VIEW_COLUMN)));
+ }
+
+ // Advance to next VIEW_COLUMN in pvie->avc[].
+
+ ULONG cwcSave = pCurViewCol->cwcName;
+ PBYTE pb = (PBYTE) pCurViewCol;
+
+ pb += (sizeof(VIEW_COLUMN) +
+ ((0 == cwcSave)
+ ? 0
+ : sizeof(WCHAR) * (1 + cwcSave)));
+
+ pCurViewCol = (VIEW_COLUMN *) ROUND_UP_POINTER(pb, ALIGN_DWORD);
+ }
+
+ return(S_OK);
+}
+
+//+-----------------------------------------------------------------------
+//
+// Method: COfsCatalogFile::GetViews, public
+//
+// Synopsis: Return the views defined on a summary catalog.
+//
+// History: 12-Jul-95 DaveStr Created
+// 31-Jul-95 DaveStr Implemented
+//
+// Notes: Assumption is made that this is an infrequent call and
+// not overly performance sensitive.
+//
+//------------------------------------------------------------------------
+
+HRESULT COfsCatalogFile::GetViews(
+ ULONG *pcViews,
+ CATALOG_VIEW **prViews)
+{
+ olDebugOut((DEB_ITRACE, "In COfsCatalogFile::GetViews\n"));
+
+ if ( (NULL == pcViews) ||
+ (NULL == prViews) )
+ {
+ return(E_INVALIDARG);
+ }
+ *pcViews = 0;
+ *prViews = NULL;
+
+ HRESULT hr = S_OK;
+ HANDLE hCatalog;
+
+ hr = GetHandle(&hCatalog);
+
+ if ( FAILED(hr) )
+ return(hr);
+
+#define VIEW_INCREMENT 5 // view allocation increment
+#define BUFFER_INCREMENT 4096 // buffer allocation increment
+
+ // Allocate EnumerateViews buffer.
+
+ ULONG cbvie = BUFFER_INCREMENT;
+ VIEW_INDEX_ENTRY *pvie = (VIEW_INDEX_ENTRY *) CoTaskMemAlloc(cbvie);
+
+ if ( NULL == pvie )
+ return(E_OUTOFMEMORY);
+
+ NTSTATUS (*pfn)(HANDLE, ULONG, VIEW_INDEX_ENTRY *, ULONG);
+
+ hr = GetOfsViewFunctionAddr(OFS_ENUMERATE_VIEWS, (void **) &pfn);
+
+ if ( FAILED(hr) )
+ return(hr);
+
+ // Make successive EnumerateView calls and map/copy the data to a
+ // CATALOG_VIEW array. (re)Allocate the return array as needed.
+
+ NTSTATUS nts;
+ ULONG id = 0;
+
+ while ( TRUE )
+ {
+ nts = (pfn)(hCatalog, id, pvie, cbvie);
+
+ // Grow buffer and retry if it is too small.
+
+ if ( STATUS_BUFFER_OVERFLOW == nts )
+ {
+ CoTaskMemFree(pvie);
+ cbvie += BUFFER_INCREMENT;
+ pvie = (VIEW_INDEX_ENTRY *) CoTaskMemAlloc(cbvie);
+
+ if ( NULL == pvie )
+ {
+ hr = E_OUTOFMEMORY;
+ break;
+ }
+
+ continue;
+ }
+ else if ( (STATUS_NO_MORE_FILES == nts) ||
+ (STATUS_NO_SUCH_FILE == nts) )
+ {
+ hr = S_OK;
+ break;
+ }
+ else if ( !NT_SUCCESS(nts) )
+ {
+ hr = HRESULT_FROM_NT(nts);
+ break;
+ }
+
+ // There is at least one complete view in pvie.
+ // Iterate through views in pvie and copy to return array.
+
+ VIEW_INDEX_ENTRY *pvieCur = pvie;
+
+ while ( TRUE )
+ {
+ // (re)Allocate output buffer as required.
+
+ if ( 0 == (*pcViews % VIEW_INCREMENT) )
+ {
+ CATALOG_VIEW *pcvTmp = *prViews;
+
+ *prViews = (CATALOG_VIEW *) CoTaskMemAlloc(
+ (*pcViews + VIEW_INCREMENT) * sizeof(CATALOG_VIEW));
+
+ if ( NULL == *prViews )
+ {
+ CoTaskMemFree(pcvTmp);
+ hr = E_OUTOFMEMORY;
+ break;
+ }
+
+ if ( NULL != pcvTmp )
+ {
+ memcpy(*prViews,
+ pcvTmp,
+ *pcViews * sizeof(CATALOG_VIEW));
+ }
+ }
+
+ // Map/copy the view.
+
+ hr = MapSingleView(pvieCur, &(*prViews)[*pcViews]);
+
+ if ( SUCCEEDED(hr) )
+ *pcViews += 1;
+ else
+ break;
+
+ // Advance to next view in buffer or set up for next
+ // EnumerateView call.
+
+ if ( 0 == pvieCur->ibEntry )
+ {
+ id = pvieCur->id + 1;
+ break;
+ }
+ else
+ {
+ pvieCur = (VIEW_INDEX_ENTRY *)
+ ((BYTE *) pvieCur + pvieCur->ibEntry);
+ }
+
+ } // while ( more views in pvie buffer )
+
+ if ( FAILED(hr) )
+ break;
+
+ } // while ( more views available via EnumerateViews )
+
+ CoTaskMemFree(pvie);
+
+ if ( FAILED(hr) )
+ {
+ *pcViews = 0;
+ CoTaskMemFree(*prViews);
+ *prViews = NULL;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::GetViews\n"));
+
+ return(hr);
+}
+
+//+-----------------------------------------------------------------------
+//
+// Method: COfsCatalogFile::DeleteView, public
+//
+// Synopsis: Delete a view defined on a summary catalog.
+//
+// History: 12-Jul-95 DaveStr Created
+// 31-Jul-95 DaveStr Implemented
+//
+// Notes:
+//
+//------------------------------------------------------------------------
+
+HRESULT COfsCatalogFile::DeleteView(
+ ULONG id)
+{
+ olDebugOut((DEB_ITRACE, "In COfsCatalogFile::DeleteView\n"));
+
+ HRESULT hr;
+ HANDLE hCatalog;
+ NTSTATUS nts;
+ NTSTATUS (*pfn)(HANDLE, ULONG);
+
+ hr = GetHandle(&hCatalog);
+
+ if ( FAILED(hr) )
+ return(hr);
+
+ hr = GetOfsViewFunctionAddr(OFS_DELETE_VIEW, (void **) &pfn);
+
+ if ( FAILED(hr) )
+ return(hr);
+
+ nts = (pfn)(hCatalog, id);
+
+ if ( !NT_SUCCESS(nts) )
+ return(HRESULT_FROM_NT(nts));
+
+ olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::DeleteView\n"));
+
+ return(S_OK);
+}
+
+//+-----------------------------------------------------------------------
+//
+// Method: COfsCatalogFile::ReleaseViews, public
+//
+// Synopsis: Release a set of CATALOG_VIEW returned by GetViews.
+// See comments on MapSingleView.
+//
+// History: 12-Jul-95 DaveStr Created
+// 31-Jul-95 DaveStr Implemented
+//
+// Notes:
+//
+//------------------------------------------------------------------------
+
+HRESULT COfsCatalogFile::ReleaseViews(
+ ULONG cViews,
+ CATALOG_VIEW *rViews)
+{
+ olDebugOut((DEB_ITRACE, "In COfsCatalogFile::ReleaseViews\n"));
+
+ if ( NULL != rViews )
+ {
+ for ( ULONG i = 0; i < cViews; i++ )
+ {
+ if ( NULL != rViews[i].rCols )
+ {
+ for ( ULONG j = 0; j < rViews[i].cCols; j++ )
+ {
+ if ( DBKIND_GUID_NAME == rViews[i].rCols[j].colid.eKind )
+ CoTaskMemFree((WCHAR *) rViews[i].rCols[j].colid.pwszName);
+ }
+
+ CoTaskMemFree(rViews[i].rCols);
+ }
+ }
+
+ CoTaskMemFree(rViews);
+ }
+
+ olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::ReleaseViews\n"));
+
+ return(S_OK);
+}
+
diff --git a/private/ole32/stg/ofsstg/ofscs.hxx b/private/ole32/stg/ofsstg/ofscs.hxx
new file mode 100644
index 000000000..ee861b026
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ofscs.hxx
@@ -0,0 +1,140 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofscs.hxx
+//
+// Contents: COfsCatalogFile header
+//
+// Classes: COfsCatalogFile
+//
+// History: Oct-93 DaveMont Created
+// Jun-95 DaveStr Added ISummaryCatalogStorage
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OFSSC_HXX__
+#define __OFSSC_HXX__
+
+#include <query.h> // BUGBUG should be unnecessary
+#include <catstg.h> // NILE style interfaces
+
+//+---------------------------------------------------------------------------
+//
+// Class: COfsCatalogFile (ops)
+//
+// Purpose: ICatalogStorage implementation for OFS
+//
+// Interface: ICatalogStorage
+//
+// History: Oct-93 DaveMont Created
+//
+//----------------------------------------------------------------------------
+
+class COfsCatalogFile
+ : public COfsDocStorage,
+ public ISummaryCatalogStorage,
+ public ISummaryCatalogStorageView,
+ public ICatalogStorage
+
+{
+public:
+
+ inline COfsCatalogFile();
+ inline ~COfsCatalogFile();
+
+ SCODE InitFromHandle(HANDLE h, DWORD grfMode, const WCHAR *pwcsName);
+ SCODE InitFromPath(HANDLE hParent,
+ WCHAR const *pwcsName,
+ DWORD grfMode,
+ CREATEOPEN co,
+ LPSECURITY_ATTRIBUTES pssSecurity);
+
+ SCODE InitPath(WCHAR const *pwszPath);
+
+ // IUnknown
+
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+
+ DECLARE_STD_REFCOUNTING;
+
+ // ICatalogStorage
+ STDMETHOD(GetSCPath)(PWCHAR * pwszPath);
+
+ STDMETHOD(SetRows)(THIS_
+ COLUMNSET * pcol,
+ LONG * pwids,
+ ULONG crows,
+ TABLEROW ** prow);
+
+ STDMETHOD(DeleteRow)(THIS_
+ ULONG wid);
+
+ // BUGBUG validation should be signature for summary catalog
+
+ // ISummaryCatalogStorage
+
+ STDMETHOD(UpdateRows)(THIS_
+ ULONG cColumns,
+ DBID *rColumns,
+ ULONG cBindings,
+ DBBINDING *rBindings,
+ ULONG cRows,
+ CATALOG_UPDATE_ROWINFO *rRowInfo);
+
+ // ISummaryCatalogStorageView
+
+ STDMETHOD(CreateView)(THIS_
+ CATALOG_VIEW *pView,
+ BOOL fWait);
+
+ STDMETHOD(GetViews)(THIS_
+ ULONG *pcViews,
+ CATALOG_VIEW **rpViews);
+
+ STDMETHOD(DeleteView)(THIS_
+ ULONG id);
+
+ STDMETHOD(ReleaseViews)(THIS_
+ ULONG cViews,
+ CATALOG_VIEW *rViews);
+
+private:
+
+ ULONG _dpad;
+
+ WCHAR * _pwszName;
+
+};
+SAFE_INTERFACE_PTR(SafeCOfsCatalogFile, COfsCatalogFile);
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsCatalogFile::~COfsCatalogFile, public
+//
+// Synopsis: free the memory used to hold the file name & path
+//
+// History: Dec-93 DaveMont Created
+//
+//----------------------------------------------------------------------------
+
+COfsCatalogFile::~COfsCatalogFile()
+{
+ CoTaskMemFree(_pwszName);
+}
+//+---------------------------------------------------------------------------
+//
+// Member: COfsCatalogFile::COfsCatalogFile, public
+//
+// Synopsis: initializes the file name & path to null
+//
+// History: Dec-93 DaveMont Created
+//
+//----------------------------------------------------------------------------
+
+COfsCatalogFile::COfsCatalogFile()
+ : _pwszName(NULL)
+{
+}
+#endif // #ifndef __OFSSC_HXX__
diff --git a/private/ole32/stg/ofsstg/ofsenm.cxx b/private/ole32/stg/ofsstg/ofsenm.cxx
new file mode 100644
index 000000000..a321ea469
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ofsenm.cxx
@@ -0,0 +1,326 @@
+g//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofsenm.cxx
+//
+// Contents: File storage enumerator
+//
+// History: 21-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include "ofsenm.hxx"
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileEnum::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 21-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsFileEnum::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In COfsFileEnum::QueryInterface:%p(riid, %p)\n",
+ this, ppvObj));
+ if (!IsValidIid(iid))
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+ if (IsEqualIID(iid, IID_IEnumSTATSTG) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IEnumSTATSTG *)this;
+ COfsFileEnum::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppvObj = NULL;
+ }
+ ssDebugOut((DEB_TRACE, "Out COfsFileEnum::QueryInterface => %p\n",
+ *ppvObj));
+ EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileEnum::COfsFileEnum, public
+//
+// Synopsis: Constructor
+//
+// History: 21-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+COfsFileEnum::COfsFileEnum(void)
+{
+ ssDebugOut((DEB_ITRACE, "In COfsFileEnum::COfsFileEnum:%p()\n", this));
+ _sig = 0;
+ ssDebugOut((DEB_ITRACE, "Out COfsFileEnum::COfsFileEnum\n"));
+ ENLIST_TRACKING(COfsFileEnum);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileEnum::InitFromHandle, public
+//
+// Synopsis: Initializes from the given information
+//
+// Arguments: [h] - Handle
+// [fDone] - Done status
+//
+// Returns: Appropriate status code
+//
+// History: 21-Jul-93 DrewB Created
+//
+// Notes: Takes a new reference on the handle
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsFileEnum::InitFromHandle(HANDLE h, BOOL fDone)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_ITRACE, "In COfsFileEnum::InitFromHandle:%p(%p, %d)\n",
+ this, h, fDone));
+
+ ssChk(DupNtHandle(h, &_h));
+
+ _fDone = fDone;
+ _sig = COFSFILEENUM_SIG;
+
+ ssDebugOut((DEB_ITRACE, "Out COfsFileEnum::InitFromHandle\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsFileEnum::~COfsFileEnum, public
+//
+// Synopsis: Destructor
+//
+// History: 21-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+COfsFileEnum::~COfsFileEnum(void)
+{
+ ssDebugOut((DEB_ITRACE, "In COfsFileEnum::~COfsFileEnum:%p()\n", this));
+ _sig = COFSFILEENUM_SIGDEL;
+ ssDebugOut((DEB_ITRACE, "Out COfsFileEnum::~COfsFileEnum\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsFileEnum::Next, public
+//
+// Synopsis: Gets N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+// [rgelt] - Array for element return
+// [pceltFetched] - If non-NULL, contains the number of
+// elements fetched
+//
+// Returns: Appropriate status code
+//
+// Modifies: [rgelt]
+// [pceltFetched]
+//
+// History: 21-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsFileEnum::Next(ULONG celt,
+ STATSTG *rgelt,
+ ULONG *pceltFetched)
+{
+ SCODE sc;
+ STATSTG stat;
+ FILE_STANDARD_INFORMATION fi;
+ NTSTATUS nts;
+ IO_STATUS_BLOCK iosb;
+
+ ssDebugOut((DEB_TRACE, "In COfsFileEnum::Next:%p(%lu, %p, %p)\n",
+ this, celt, rgelt, pceltFetched));
+
+ if (pceltFetched == NULL && celt > 1)
+ ssErr(EH_Err, STG_E_INVALIDPARAMETER);
+ ssChk(Validate());
+
+ ssAssert(_h != NULL);
+ __try
+ {
+ if (celt == 0)
+ {
+ if (pceltFetched)
+ *pceltFetched = 0;
+ ssErr(EH_Err, S_OK);
+ }
+
+ stat.pwcsName = NULL;
+ if (!_fDone)
+ {
+ nts = NtQueryInformationFile(_h, &iosb, &fi,
+ sizeof(FILE_STANDARD_INFORMATION),
+ FileStandardInformation);
+ if (!NT_SUCCESS(nts))
+ ssErr(EH_Err, NtStatusToScode(nts));
+
+ ssChk(CoMemAlloc(sizeof(CONTENTS_STREAM),
+ (void **)&stat.pwcsName));
+ wcscpy(stat.pwcsName, CONTENTS_STREAM);
+
+ stat.type = STGTY_STREAM;
+ stat.cbSize = *(ULARGE_INTEGER *)&fi.EndOfFile;
+ stat.mtime.dwLowDateTime = stat.mtime.dwHighDateTime = 0;
+ stat.atime.dwLowDateTime = stat.atime.dwHighDateTime = 0;
+ stat.ctime.dwLowDateTime = stat.ctime.dwHighDateTime = 0;
+ stat.grfMode = 0;
+ stat.grfLocksSupported = 0;
+ stat.clsid = CLSID_NULL;
+ stat.grfStateBits = 0;
+ stat.STATSTG_dwStgFmt = STGFMT_DOCUMENT;
+
+ rgelt[0] = stat;
+ if (pceltFetched)
+ *pceltFetched = 1;
+
+ _fDone = TRUE;
+
+ if (celt > 1)
+ sc = S_FALSE;
+ else
+ sc = S_OK;
+ }
+ else
+ {
+ if (pceltFetched)
+ *pceltFetched = 0;
+ sc = S_FALSE;
+ }
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER)
+ {
+ if (stat.pwcsName)
+ ssVerSucc(CoMemFree(stat.pwcsName));
+ sc = HRESULT_FROM_NT(GetExceptionCode());
+ }
+
+ ssDebugOut((DEB_TRACE, "Out COfsFileEnum::Next => 0x%lX\n", sc));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsFileEnum::Skip, public
+//
+// Synopsis: Skips N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+//
+// Returns: Appropriate status code
+//
+// History: 21-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsFileEnum::Skip(ULONG celt)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In COfsFileEnum::Skip:%p(%lu)\n", this, celt));
+
+ ssChk(Validate());
+
+ if (celt > 0)
+ {
+ if (_fDone)
+ sc = S_FALSE;
+ else
+ _fDone = TRUE;
+ }
+
+ ssDebugOut((DEB_TRACE, "Out COfsFileEnum::Skip\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsFileEnum::Reset, public
+//
+// Synopsis: Rewinds the iterator
+//
+// Returns: Appropriate status code
+//
+// History: 21-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsFileEnum::Reset(void)
+{
+ SCODE sc;
+
+ ssDebugOut((DEB_TRACE, "In COfsFileEnum::Reset:%p()\n", this));
+
+ ssChk(Validate());
+ _fDone = FALSE;
+
+ ssDebugOut((DEB_TRACE, "Out COfsFileEnum::Reset\n"));
+EH_Err:
+ return ssResult(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsFileEnum::Clone, public
+//
+// Synopsis: Clones this iterator
+//
+// Arguments: [ppenm] - Clone return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 21-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsFileEnum::Clone(IEnumSTATSTG **ppenm)
+{
+ SCODE sc;
+ SafeCOfsFileEnum pfe;
+
+ ssDebugOut((DEB_TRACE, "In COfsFileEnum::Clone:%p(%p)\n", this, ppenm));
+
+ ssChk(Validate());
+
+ pfe.Attach(new COfsFileEnum());
+ ssMem((COfsFileEnum *)pfe);
+ ssAssert(_h != NULL);
+ ssChk(pfe->InitFromHandle(_h, _fDone));
+ TRANSFER_INTERFACE(pfe, IEnumSTATSTG, ppenm);
+
+ ssDebugOut((DEB_TRACE, "Out COfsFileEnum::Clone => %p\n", *ppenm));
+EH_Err:
+ return ssResult(sc);
+}
diff --git a/private/ole32/stg/ofsstg/ofsenm.hxx b/private/ole32/stg/ofsstg/ofsenm.hxx
new file mode 100644
index 000000000..05feb74ba
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ofsenm.hxx
@@ -0,0 +1,81 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofsenm.hxx
+//
+// Contents: File storage enumerator
+//
+// Classes: COfsFileEnum
+//
+// History: 21-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OFSENM_HXX__
+#define __OFSENM_HXX__
+
+//+---------------------------------------------------------------------------
+//
+// Class: COfsFileEnum (fe)
+//
+// Purpose: File storage enumerator
+//
+// Interface: IEnumSTATSTG
+//
+// History: 21-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class COfsFileEnum
+ : INHERIT_TRACKING,
+ public IEnumSTATSTG
+{
+public:
+ COfsFileEnum(void);
+ SCODE InitFromHandle(HANDLE h, BOOL fDone);
+ ~COfsFileEnum(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // IEnumSTATSTG
+ STDMETHOD(Next)(ULONG celt, STATSTG FAR *rgelt, ULONG *pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(IEnumSTATSTG **ppenm);
+
+private:
+ inline SCODE Validate(void) const;
+
+ ULONG _sig;
+ NuSafeNtHandle _h;
+ BOOL _fDone;
+};
+
+SAFE_INTERFACE_PTR(SafeCOfsFileEnum, COfsFileEnum);
+
+#define COFSFILEENUM_SIG LONGSIG('O', 'F', 'N', 'M')
+#define COFSFILEENUM_SIGDEL LONGSIG('O', 'f', 'N', 'm')
+
+//+--------------------------------------------------------------
+//
+// Member: COfsFileEnum::Validate, private
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 21-Jul-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE COfsFileEnum::Validate(void) const
+{
+ return (this == NULL || _sig != COFSFILEENUM_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+#endif // #ifndef __FSENM_HXX__
diff --git a/private/ole32/stg/ofsstg/ofspenm.cxx b/private/ole32/stg/ofsstg/ofspenm.cxx
new file mode 100644
index 000000000..a1fed3cb2
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ofspenm.cxx
@@ -0,0 +1,288 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofspenm.cxx
+//
+// Contents: COfsPropStgEnum implementation
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <iofsprop.h>
+#include <ofspenm.hxx>
+#include <logfile.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStgEnum::COfsPropStgEnum, public
+//
+// Synopsis: Constructor
+//
+// History: 17-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+COfsPropStgEnum::COfsPropStgEnum(void)
+{
+ olDebugOut((DEB_ITRACE, "In COfsPropStgEnum::COfsPropStgEnum:%p()\n",
+ this));
+ _sig = 0;
+ olDebugOut((DEB_ITRACE, "Out COfsPropStgEnum::COfsPropStgEnum\n"));
+ ENLIST_TRACKING(COfsPropStgEnum);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStgEnum::InitFromHandle, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [h] - Handle of object being enumerated
+// [riid] - IID of property set
+// [cEntry] - Entry to start at
+//
+// Returns: Appropriate status code
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsPropStgEnum::InitFromHandle(HANDLE h, REFIID riid, ULONG cEntry)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In COfsPropStgEnum::InitFromHandle:%p("
+ "%p, riid, %lu)\n", this, h, cEntry));
+
+ olChk(DupNtHandle(h, &_h));
+ _iid = riid;
+ _sig = COFSPROPSTGENUM_SIG;
+ _cEntry = cEntry;
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropStgEnum::InitFromHandle\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStgEnum::~COfsPropStgEnum, public
+//
+// Synopsis: Destructor
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+COfsPropStgEnum::~COfsPropStgEnum(void)
+{
+ olDebugOut((DEB_ITRACE, "In COfsPropStgEnum::~COfsPropStgEnum\n"));
+ _sig = COFSPROPSTGENUM_SIGDEL;
+ olDebugOut((DEB_ITRACE, "Out COfsPropStgEnum::~COfsPropStgEnum\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStgEnum::QueryInterface, public
+//
+// Synopsis: Return supported interfaces
+//
+// Arguments: [riid] - Interface
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsPropStgEnum::QueryInterface(REFIID riid, void **ppv)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In COfsPropStgEnum::QueryInterface:%p("
+ "riid, %p)\n", this, ppv));
+ if (IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IEnumSTATPROPSTG))
+ {
+ sc = S_OK;
+ *ppv = this;
+ COfsPropStgEnum::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppv = NULL;
+ }
+ olDebugOut((DEB_TRACE, "Out COfsPropStgEnum::QueryInterface => %p\n",
+ *ppv));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsPropStgEnum::Next, public
+//
+// Synopsis: Gets N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+// [rgelt] - Array for element return
+// [pceltFetched] - If non-NULL, contains the number of
+// elements fetched
+//
+// Returns: Appropriate status code
+//
+// Modifies: [rgelt]
+// [pceltFetched]
+//
+// History: 09-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsPropStgEnum::Next(ULONG celt,
+ STATPROPSTG *rgelt,
+ ULONG *pceltFetched)
+{
+ SCODE sc;
+ ULONG celtDone;
+ NTSTATUS nts;
+
+ olDebugOut((DEB_ITRACE, "In COfsPropStgEnum::Next(%lu, %p, %p)\n",
+ celt, rgelt, pceltFetched));
+
+ if (celt > 1 && pceltFetched == NULL)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(Validate());
+
+ celtDone = celt;
+ nts = OFSEnumProp(_h, _iid, &celtDone, rgelt, _cEntry, CoTaskMemAlloc);
+ if (!NT_SUCCESS(nts))
+ olErr(EH_Err, NtStatusToScode(nts));
+
+ if (pceltFetched)
+ *pceltFetched = celtDone;
+
+ // Update entry count
+ _cEntry += celtDone;
+
+ // Check for end-of-enumeration
+ if (celtDone < celt)
+ sc = S_FALSE;
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropStgEnum::Next => %lX\n", sc));
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsPropStgEnum::Skip, public
+//
+// Synopsis: Skips N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsPropStgEnum::Skip(ULONG celt)
+{
+ SCODE sc = S_OK;
+ NTSTATUS nts;
+ ULONG cprop;
+ STATPROPSTG stat;
+
+ olDebugOut((DEB_ITRACE, "In COfsPropStgEnum::Skip(%lu)\n", celt));
+
+ olChk(Validate());
+
+ cprop = 1;
+ nts = OFSEnumProp(_h, _iid, &cprop, &stat, _cEntry+celt, CoTaskMemAlloc);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ {
+ if (cprop != 1)
+ sc = S_FALSE;
+ _cEntry += celt;
+ }
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropStgEnum::Skip\n"));
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsPropStgEnum::Reset, public
+//
+// Synopsis: Rewinds the iterator
+//
+// Returns: Appropriate status code
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsPropStgEnum::Reset(void)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In COfsPropStgEnum::Reset()\n"));
+
+ olChk(Validate());
+
+ _cEntry = 0;
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropStgEnum::Reset\n"));
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsPropStgEnum::Clone, public
+//
+// Synopsis: Clones this iterator
+//
+// Arguments: [ppenm] - Clone return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 09-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsPropStgEnum::Clone(IEnumSTATPROPSTG **ppenm)
+{
+ SCODE sc;
+ SafeCOfsPropStgEnum popge;
+
+ olDebugOut((DEB_ITRACE, "In COfsPropStgEnum::Clone(%p)\n", ppenm));
+
+ olChk(Validate());
+
+ popge.Attach(new COfsPropStgEnum());
+ olMem((COfsPropStgEnum *)popge);
+ olChk(popge->InitFromHandle(_h, _iid, _cEntry));
+ TRANSFER_INTERFACE(popge, IEnumSTATPROPSTG, ppenm);
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropStgEnum::Clone => %p\n",
+ *ppenm));
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
diff --git a/private/ole32/stg/ofsstg/ofspenm.hxx b/private/ole32/stg/ofsstg/ofspenm.hxx
new file mode 100644
index 000000000..54a185b8e
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ofspenm.hxx
@@ -0,0 +1,89 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofspenm.hxx
+//
+// Contents: COfsPropStgEnum header
+//
+// Classes: COfsPropStgEnum
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OFSPENM_HXX__
+#define __OFSPENM_HXX__
+
+#include <otrack.hxx>
+#include <dfmem.hxx>
+#include <safepnt.hxx>
+#include <ntsupp.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: COfsPropStgEnum (opge)
+//
+// Purpose: IEnumSTATPROPSTG for OFS
+//
+// Interface: IEnumSTATPROPSTG
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+interface COfsPropStgEnum
+ : INHERIT_TRACKING,
+ public IEnumSTATPROPSTG
+{
+public:
+ COfsPropStgEnum(void);
+ SCODE InitFromHandle(HANDLE h, REFIID riid, ULONG cEntry);
+ ~COfsPropStgEnum(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // IEnumSTATPROPSTG
+ STDMETHOD(Next)(ULONG celt,
+ STATPROPSTG FAR *rgelt,
+ ULONG *pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(IEnumSTATPROPSTG **ppenm);
+
+private:
+ inline SCODE Validate(void) const;
+
+ IID _iid;
+ ULONG _sig;
+ ULONG _cEntry;
+ NuSafeNtHandle _h;
+};
+
+SAFE_INTERFACE_PTR(SafeCOfsPropStgEnum, COfsPropStgEnum);
+
+#define COFSPROPSTGENUM_SIG LONGSIG('O', 'P', 'G', 'E')
+#define COFSPROPSTGENUM_SIGDEL LONGSIG('O', 'p', 'G', 'e')
+
+//+--------------------------------------------------------------
+//
+// Member: COfsPropStgEnum::Validate, public
+//
+// Synopsis: Validates the signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE if the signature doesn't match
+//
+// History: 12-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE COfsPropStgEnum::Validate(void) const
+{
+ return (this == NULL || _sig != COFSPROPSTGENUM_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+#endif // #ifndef __OFSPENM_HXX__
diff --git a/private/ole32/stg/ofsstg/ofsps.cxx b/private/ole32/stg/ofsstg/ofsps.cxx
new file mode 100644
index 000000000..79330873f
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ofsps.cxx
@@ -0,0 +1,178 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofsps.cxx
+//
+// Contents: COfsPropSet
+//
+// History: 18-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <ofsps.hxx>
+#include <ofspstg.hxx>
+#include <ofspse.hxx>
+#include <iofs.h>
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropSet::Create, public
+//
+// Synopsis: Creates a property set
+//
+// Arguments: [riid] - IID of propset
+// [grfMode] - Mode to instantiate in
+// [ppprstg] - Return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppprstg]
+//
+// History: 18-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsPropSet::Create(REFIID riid,
+ DWORD grfMode,
+ IPropertyStorage **ppprstg)
+{
+ SCODE sc;
+ SafeCOfsPropStg pops;
+ NTSTATUS nts;
+
+ olDebugOut((DEB_TRACE, "In COfsPropSet::Create:%p(riid, %lX, %p)\n",
+ this, grfMode, ppprstg));
+
+ olChk(ExtValidate());
+ pops.Attach(new COfsPropStg);
+ olMem((COfsPropStg *)pops);
+ olChk(pops->InitFromHandle(_h, riid));
+ // BUGBUG - This is necessary to create the property set
+ // Should be unnecessary when real OFS propsets exist
+ if (!NT_SUCCESS(nts = OFSSetProp(_h, riid, 0, NULL, NULL, NULL)))
+ sc = NtStatusToScode(nts);
+ else
+ TRANSFER_INTERFACE(pops, IPropertyStorage, ppprstg);
+
+ olDebugOut((DEB_TRACE, "Out COfsPropSet::Create\n"));
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropSet::Open, public
+//
+// Synopsis: Opens a property set
+//
+// Arguments: [riid] - IID of propset
+// [grfMode] - Mode to instantiate in
+// [ppprstg] - Return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppprstg]
+//
+// History: 18-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsPropSet::Open(REFIID riid,
+ DWORD grfMode,
+ IPropertyStorage **ppprstg)
+{
+ SCODE sc;
+ SafeCOfsPropStg pops;
+ NTSTATUS nts;
+
+ olDebugOut((DEB_TRACE, "In COfsPropSet::Open:%p(riid, %lX, %p)\n",
+ this, grfMode, ppprstg));
+
+ olChk(ExtValidate());
+
+ // Check for propset existence
+ // BUGBUG - This is a temporary method of doing so
+ nts = OFSGetProp(_h, riid, 0, NULL, NULL, NULL, NULL, NULL);
+ if (nts == STATUS_PROPSET_NOT_FOUND)
+ {
+ olErr(EH_Err, STG_E_FILENOTFOUND);
+ }
+ else if (!NT_SUCCESS(nts))
+ {
+ olErr(EH_Err, NtStatusToScode(nts));
+ }
+
+ pops.Attach(new COfsPropStg);
+ olMem((COfsPropStg *)pops);
+ olChk(pops->InitFromHandle(_h, riid));
+ TRANSFER_INTERFACE(pops, IPropertyStorage, ppprstg);
+
+ olDebugOut((DEB_TRACE, "Out COfsPropSet::Open\n"));
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropSet::Delete, public
+//
+// Synopsis: Deletes a property set
+//
+// Arguments: [riid] - IID of property set
+//
+// Returns: Appropriate status code
+//
+// History: 18-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsPropSet::Delete(REFIID riid)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In COfsPropSet::Delete:%p(riid)\n", this));
+
+ olChk(ExtValidate());
+
+ // BUGBUG - No way to do it yet
+ sc = STG_E_UNIMPLEMENTEDFUNCTION;
+
+ olDebugOut((DEB_TRACE, "Out COfsPropSet::Delete\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropSet::Enum, public
+//
+// Synopsis: Creates a property set enumerator
+//
+// Arguments: [ppenm] - Return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 18-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsPropSet::Enum(IEnumSTATPROPSETSTG **ppenm)
+{
+ SCODE sc;
+ SafeCOfsPropSetEnum popse;
+
+ olChk(ExtValidate());
+ popse.Attach(new COfsPropSetEnum);
+ olMem((COfsPropSetEnum *)popse);
+ olChk(popse->InitFromHandle(_h, 0));
+ TRANSFER_INTERFACE(popse, IEnumSTATPROPSETSTG, ppenm);
+EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/ofsstg/ofsps.hxx b/private/ole32/stg/ofsstg/ofsps.hxx
new file mode 100644
index 000000000..a74309078
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ofsps.hxx
@@ -0,0 +1,70 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofsps.hxx
+//
+// Contents: COfsPropSet
+//
+// History: 18-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OFSPS_HXX__
+#define __OFSPS_HXX__
+
+//+---------------------------------------------------------------------------
+//
+// Class: COfsPropSet (ops)
+//
+// Purpose: IPropertySetStorage for an OFS handle
+//
+// Interface: IPropertySetStorage
+//
+// History: 18-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+class COfsPropSet
+ : public IPropertySetStorage
+{
+public:
+ inline SCODE InitDup(HANDLE h);
+
+ STDMETHOD(Create)(THIS_
+ REFIID riid,
+ DWORD grfMode,
+ IPropertyStorage FAR * FAR *ppprstg);
+ STDMETHOD(Open)(THIS_
+ REFIID riid,
+ DWORD grfMode,
+ IPropertyStorage FAR * FAR *ppprstg);
+ STDMETHOD(Delete)(THIS_
+ REFIID riid);
+ STDMETHOD(Enum)(THIS_
+ IEnumSTATPROPSETSTG FAR * FAR *ppenm);
+
+protected:
+ // For signature validation on external classes
+ virtual SCODE ExtValidate(void) = 0;
+
+ NuSafeNtHandle _h;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropSet::InitDup, public
+//
+// Synopsis: Initialization
+//
+// History: 18-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+inline SCODE COfsPropSet::InitDup(HANDLE h)
+{
+ return DupNtHandle(h, &_h);
+}
+
+#endif // #ifndef __OFSPS_HXX__
diff --git a/private/ole32/stg/ofsstg/ofspse.cxx b/private/ole32/stg/ofsstg/ofspse.cxx
new file mode 100644
index 000000000..ca76dc305
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ofspse.cxx
@@ -0,0 +1,291 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofspse.cxx
+//
+// Contents: COfsPropSetEnum implementation
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <ofspse.hxx>
+#include <iofs.h>
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropSetEnum::COfsPropSetEnum, public
+//
+// Synopsis: Constructor
+//
+// History: 17-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+COfsPropSetEnum::COfsPropSetEnum(void)
+{
+ olDebugOut((DEB_ITRACE, "In COfsPropSetEnum::COfsPropSetEnum:%p()\n",
+ this));
+ _sig = 0;
+ olDebugOut((DEB_ITRACE, "Out COfsPropSetEnum::COfsPropSetEnum\n"));
+ ENLIST_TRACKING(COfsPropSetEnum);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropSetEnum::InitFromHandle, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [h] - Handle of object being enumerated
+// [key] - Enumeration key, zero for a new enumeration
+//
+// Returns: Appropriate status code
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsPropSetEnum::InitFromHandle(HANDLE h, ULONG key)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In COfsPropSetEnum::InitFromHandle:%p("
+ "%p, %lu)\n", this, h));
+
+ olChk(DupNtHandle(h, &_h));
+ _sig = COFSPROPSETENUM_SIG;
+ _key = key;
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropStg::InitFromHandle\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropSetEnum::~COfsPropSetEnum, public
+//
+// Synopsis: Destructor
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+COfsPropSetEnum::~COfsPropSetEnum(void)
+{
+ olDebugOut((DEB_ITRACE, "In COfsPropSetEnum::~COfsPropSetEnum:%p()\n",
+ this));
+ _sig = COFSPROPSETENUM_SIGDEL;
+ olDebugOut((DEB_ITRACE, "Out COfsPropSetEnum::~COfsPropSetEnum\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropSetEnum::QueryInterface, public
+//
+// Synopsis: Return supported interfaces
+//
+// Arguments: [riid] - Interface
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsPropSetEnum::QueryInterface(REFIID riid, void **ppv)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In COfsPropSetEnum::QueryInterface:%p("
+ "riid, %p)\n", this, ppv));
+ if (IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IEnumSTATPROPSETSTG))
+ {
+ sc = S_OK;
+ *ppv = this;
+ COfsPropSetEnum::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppv = NULL;
+ }
+ olDebugOut((DEB_TRACE, "Out COfsPropSetEnum::QueryInterface => %p\n",
+ *ppv));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsPropSetEnum::Next, public
+//
+// Synopsis: Gets N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+// [rgelt] - Array for element return
+// [pceltFetched] - If non-NULL, contains the number of
+// elements fetched
+//
+// Returns: Appropriate status code
+//
+// Modifies: [rgelt]
+// [pceltFetched]
+//
+// History: 09-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsPropSetEnum::Next(ULONG celt,
+ STATPROPSETSTG *rgelt,
+ ULONG *pceltFetched)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ ULONG celtFetched;
+
+ olDebugOut((DEB_ITRACE, "In COfsPropSetEnum::Next(%lu, %p, %p)\n",
+ celt, rgelt, pceltFetched));
+
+ if (celt > 1 && pceltFetched == NULL)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(Validate());
+
+ celtFetched = celt;
+ nts = OFSEnumPropSet(_h, &celtFetched, &_key, rgelt);
+ if ( NT_SUCCESS(nts) )
+ {
+ sc = ( celt == celtFetched ) ? S_OK : S_FALSE;
+ }
+ else
+ {
+ celtFetched = 0;
+ sc = ( nts == STATUS_PROPSET_NOT_FOUND) ?
+ S_FALSE : NtStatusToScode(nts);
+ }
+
+ if (pceltFetched)
+ *pceltFetched = celtFetched;
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropSetEnum::Next => %lX\n", sc));
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsPropSetEnum::Skip, public
+//
+// Synopsis: Skips N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsPropSetEnum::Skip(ULONG celt)
+{
+ SCODE sc;
+ NTSTATUS nts;
+ ULONG celtDone;
+ STATPROPSETSTG stat;
+
+ olDebugOut((DEB_ITRACE, "In COfsPropSetEnum::Skip(%lu)\n", celt));
+
+ olChk(Validate());
+
+ sc = S_OK;
+ while (celt-- > 0)
+ {
+ celtDone = 1;
+ nts = OFSEnumPropSet(_h, &celtDone, &_key, &stat);
+ if (!NT_SUCCESS(nts))
+ {
+ sc = (nts == STATUS_PROPSET_NOT_FOUND) ?
+ S_FALSE: NtStatusToScode(nts);
+ break;
+ }
+
+ // OFS returns success iff it returned at least one propset.
+ // Since we only asked for one, there is nothing to do except
+ // keep looping.
+ }
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropSetEnum::Skip\n"));
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsPropSetEnum::Reset, public
+//
+// Synopsis: Rewinds the iterator
+//
+// Returns: Appropriate status code
+//
+// History: 21-Dec-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsPropSetEnum::Reset(void)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In COfsPropSetEnum::Reset()\n"));
+
+ sc = Validate();
+ if (SUCCEEDED(sc))
+ _key = 0;
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropSetEnum::Reset\n"));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: COfsPropSetEnum::Clone, public
+//
+// Synopsis: Clones this iterator
+//
+// Arguments: [ppenm] - Clone return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 09-Jun-93 DrewB Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP COfsPropSetEnum::Clone(IEnumSTATPROPSETSTG **ppenm)
+{
+ SCODE sc;
+ SafeCOfsPropSetEnum popse;
+
+ olDebugOut((DEB_ITRACE, "In COfsPropSetEnum::Clone(%p)\n", ppenm));
+
+ olChk(Validate());
+
+ popse.Attach(new COfsPropSetEnum);
+ olMem((COfsPropSetEnum *)popse);
+ olChk(popse->InitFromHandle(_h, _key));
+ TRANSFER_INTERFACE(popse, IEnumSTATPROPSETSTG, ppenm);
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropSetEnum::Clone => %p\n",
+ *ppenm));
+EH_Err:
+ return ResultFromScode(sc);
+}
diff --git a/private/ole32/stg/ofsstg/ofspse.hxx b/private/ole32/stg/ofsstg/ofspse.hxx
new file mode 100644
index 000000000..b651425b0
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ofspse.hxx
@@ -0,0 +1,88 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofspse.hxx
+//
+// Contents: COfsPropSetEnum header
+//
+// Classes: COfsPropSetEnum
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OFSPSE_HXX__
+#define __OFSPSE_HXX__
+
+#include <otrack.hxx>
+#include <dfmem.hxx>
+#include <ntsupp.hxx>
+#include <safepnt.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: COfsPropSetEnum (opse)
+//
+// Purpose: Property set enumerator for OFS
+//
+// Interface: IEnumSTATPROPSETSTG
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+interface COfsPropSetEnum
+ : INHERIT_TRACKING,
+ public IEnumSTATPROPSETSTG
+{
+public:
+ COfsPropSetEnum(void);
+ SCODE InitFromHandle(HANDLE h, ULONG key);
+ ~COfsPropSetEnum(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // IEnumSTATPROPSETSTG
+ STDMETHOD(Next)(ULONG celt,
+ STATPROPSETSTG FAR *rgelt,
+ ULONG *pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(IEnumSTATPROPSETSTG **ppenm);
+
+private:
+ inline SCODE Validate(void) const;
+
+ ULONG _sig;
+ NuSafeNtHandle _h;
+ ULONG _key;
+};
+
+SAFE_INTERFACE_PTR(SafeCOfsPropSetEnum, COfsPropSetEnum);
+
+#define COFSPROPSETENUM_SIG LONGSIG('O', 'P', 'S', 'E')
+#define COFSPROPSETENUM_SIGDEL LONGSIG('O', 'p', 'S', 'e')
+
+//+--------------------------------------------------------------
+//
+// Member: COfsPropSetEnum::Validate, public
+//
+// Synopsis: Validates the signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE if the signature doesn't match
+//
+// History: 12-Mar-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE COfsPropSetEnum::Validate(void) const
+{
+ return (this == NULL || _sig != COFSPROPSETENUM_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+#endif // #ifndef __OFSPSE_HXX__
diff --git a/private/ole32/stg/ofsstg/ofspstg.cxx b/private/ole32/stg/ofsstg/ofspstg.cxx
new file mode 100644
index 000000000..8714a46cd
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ofspstg.cxx
@@ -0,0 +1,417 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofspstg.cxx
+//
+// Contents: COfsPropStg implementation
+//
+// Classes: COfsPropStg
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <iofsprop.h>
+#include <props.hxx>
+#include <ofspstg.hxx>
+#include <ofspenm.hxx>
+#include <logfile.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStg::COfsPropStg, public
+//
+// Synopsis: Constructor
+//
+// History: 17-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+COfsPropStg::COfsPropStg(void)
+{
+ olDebugOut((DEB_ITRACE, "In COfsPropStg::COfsPropStg:%p()\n",
+ this));
+ _sig = 0;
+ olDebugOut((DEB_ITRACE, "Out COfsPropStg::COfsPropStg\n"));
+ ENLIST_TRACKING(COfsPropStg);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStg::InitFromHandle, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [h] - Property set parent handle
+// [riid] - Property set IID
+//
+// Returns: Appropriate status code
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE COfsPropStg::InitFromHandle(HANDLE h, REFIID riid)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In COfsPropStg::InitFromHandle:%p(%p, riid)\n",
+ this, h));
+
+ olChk(DupNtHandle(h, &_h));
+ _iid = riid;
+ _sig = COFSPROPSTG_SIG;
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropStg::InitFromHandle\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStg::~COfsPropStg, public
+//
+// Synopsis: Destructor
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+COfsPropStg::~COfsPropStg(void)
+{
+ olDebugOut((DEB_ITRACE, "In COfsPropStg::~COfsPropStg:%p()\n",
+ this));
+ _sig = COFSPROPSTG_SIGDEL;
+ olDebugOut((DEB_ITRACE, "Out COfsPropStg::~COfsPropStg\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStg::QueryInterface, public
+//
+// Synopsis: Return supported interfaces
+//
+// Arguments: [riid] - Interface
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsPropStg::QueryInterface(REFIID riid, void **ppv)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_TRACE, "In COfsPropStg::QueryInterface:%p(riid, %p)\n",
+ this, ppv));
+ if (IsEqualIID(riid, IID_IUnknown) ||
+ IsEqualIID(riid, IID_IPropertyStorage))
+ {
+ sc = S_OK;
+ *ppv = this;
+ COfsPropStg::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ *ppv = NULL;
+ }
+ olDebugOut((DEB_TRACE, "Out COfsPropStg::QueryInterface => %p\n",
+ *ppv));
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStg::ReadMultiple, public
+//
+// Synopsis: Gets property values
+//
+// Arguments: [cpspec] - Count of properties
+// [rgpspec] - Property names
+// [pftmModified] - Modify time
+// [rgpropid] - Id return
+// [pprgdpv] - Value array return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pprgdpv]
+// [rgpropid]
+//
+// History: 09-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsPropStg::ReadMultiple(ULONG cpspec,
+ PROPSPEC rgpspec[],
+ FILETIME *pftmModified,
+ PROPID rgpropid[],
+ STGVARIANT rgdpv[])
+{
+ SCODE sc = S_OK;
+ NTSTATUS nts;
+ TTL ttl;
+ FILE_BASIC_INFORMATION fbi;
+ IO_STATUS_BLOCK iosb;
+
+ olLog(("%p::In COfsPropStg::ReadMultiple(%lu, %p, %p, %p, %p)\n",
+ this, cpspec, rgpspec, pftmModified, rgpropid, rgdpv));
+ olDebugOut((DEB_ITRACE, "In COfsPropStg::ReadMultiple:%p("
+ "%lu, %p, %p, %p, %p)\n", this, cpspec, rgpspec,
+ pftmModified, rgpropid, rgdpv));
+
+ olChk(Validate());
+
+ nts = NtQueryInformationFile(_h, &iosb, &fbi,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation);
+ if (!NT_SUCCESS(nts))
+ olErr(EH_Err, NtStatusToScode(nts));
+
+ if (pftmModified)
+ {
+ LARGE_INTEGER_TO_FILETIME(&fbi.LastWriteTime, pftmModified);
+ }
+
+ nts = OFSGetProp(_h, _iid, cpspec, rgpspec, rgpropid, &ttl, rgdpv,
+ CoTaskMemAlloc);
+ if (!NT_SUCCESS(nts))
+ {
+ olErr(EH_Err, NtStatusToScode(nts));
+ }
+ sc = S_OK;
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropStg::ReadMultiple\n"));
+
+ EH_Err:
+ olLog(("%p::Out COfsPropStg::ReadMultiple(). sc == %lX\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStg::WriteMultiple, public
+//
+// Synopsis: Sets property values
+//
+// Arguments: [cpspec] - Count of properties
+// [rgpspec] - Property names
+// [rgpropid] - Property id return
+// [rgdpv] - Value array
+//
+// Returns: Appropriate status code
+//
+// Modifies: [rgpropid]
+//
+// History: 09-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsPropStg::WriteMultiple(ULONG cpspec,
+ PROPSPEC rgpspec[],
+ PROPID rgpropid[],
+ STGVARIANT rgdpv[])
+{
+ SCODE sc = S_OK;
+ NTSTATUS nts;
+
+ olLog(("%p::In COfsPropStg::WriteMultiple(%lu, %p, %p, %p)\n",
+ this, cpspec, rgpspec, rgpropid, rgdpv));
+ olDebugOut((DEB_ITRACE, "In COfsPropStg::WriteMultiple:%p("
+ "%lu, %p, %p, %p)\n", this, cpspec, rgpspec, rgpropid, rgdpv));
+
+ olChk(Validate());
+
+ nts = OFSSetProp(_h, _iid, cpspec, rgpspec, rgpropid, rgdpv);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropStg::WriteMultiple\n"));
+ EH_Err:
+ olLog(("%p::Out COfsPropStg::WriteMultiple(). sc == %lX\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStg::DeleteMultiple, public
+//
+// Synopsis: Deletes properties
+//
+// Arguments: [cpspec] - Count of names
+// [rgpspec] - Names
+//
+// Returns: Appropriate status code
+//
+// History: 09-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsPropStg::DeleteMultiple(ULONG cpspec,
+ PROPSPEC rgpspec[])
+{
+ SCODE sc;
+ NTSTATUS nts;
+
+ olLog(("%p::In COfsPropStg::DeleteMultiple(%lu, %p)\n",
+ this, cpspec, rgpspec));
+ olDebugOut((DEB_ITRACE, "In COfsPropStg::DeleteMultiple:%p("
+ "%lu, %p)\n", this, cpspec, rgpspec));
+
+ olChk(Validate());
+
+ nts = OFSDeleteProp(_h, _iid, cpspec, rgpspec);
+ if (!NT_SUCCESS(nts))
+ sc = NtStatusToScode(nts);
+ else
+ sc = S_OK;
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropStg::DeleteMultiple\n"));
+ EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStg::Enum, public
+//
+// Synopsis: Create a property enumerator
+//
+// Arguments: [ppenm] - Enumerator return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 09-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsPropStg::Enum(IEnumSTATPROPSTG **ppenm)
+{
+ SCODE sc;
+ SafeCOfsPropStgEnum popge;
+
+ olLog(("%p::In COfsPropStg::Enum(%p)\n", this, ppenm));
+ olDebugOut((DEB_ITRACE, "In COfsPropStg::Enum:%p(%p)\n",
+ this, ppenm));
+
+ olChk(Validate());
+
+ popge.Attach(new COfsPropStgEnum);
+ olMem((COfsPropStgEnum *)popge);
+ olChk(popge->InitFromHandle(_h, _iid, 0));
+ TRANSFER_INTERFACE(popge, IEnumSTATPROPSTG, ppenm);
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropStg::Enum\n"));
+ EH_Err:
+ olLog(("%p::Out COfsPropStg::Enum(). sc == %lX\n", sc));
+ return ResultFromScode(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStg::Commit, public
+//
+// Synopsis: Commits transacted changes
+//
+// Arguments: [grfCommitFlags] - Flags controlling commit
+//
+// Returns: Appropriate status code
+//
+// History: 30-Nov-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsPropStg::Commit(DWORD grfCommitFlags)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In COfsPropStg::Commit:%p(%lX)\n",
+ this, grfCommitFlags));
+
+ // Right now OFS property sets can't be transacted so this doesn't
+ // do anything
+
+ olChk(Validate());
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropStg::Commit\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStg::Revert, public
+//
+// Synopsis: Reverts transacted changes
+//
+// Returns: Appropriate status code
+//
+// History: 30-Nov-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsPropStg::Revert(void)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In COfsPropStg::Revert:%p()\n", this));
+
+ // Right now OFS property sets can't be transacted so this doesn't
+ // do anything
+
+ olChk(Validate());
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropStg::Revert\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: COfsPropStg::Stat, public
+//
+// Synopsis: Returns information about this property set
+//
+// Arguments: [pstat] - Stat structure to fill in
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstat]
+//
+// History: 30-Nov-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP COfsPropStg::Stat(STATPROPSETSTG *pstat)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In COfsPropStg::Stat:%p(%p)\n",
+ this, pstat));
+
+ olChk(Validate());
+
+ // We can't fill in the times right now so zero them
+ memset(pstat, 0, sizeof(STATPROPSETSTG));
+
+ pstat->iid = _iid;
+
+ olDebugOut((DEB_ITRACE, "Out COfsPropStg::Stat\n"));
+ EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/ofsstg/ofspstg.hxx b/private/ole32/stg/ofsstg/ofspstg.hxx
new file mode 100644
index 000000000..9eea995a2
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ofspstg.hxx
@@ -0,0 +1,103 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofspstg.hxx
+//
+// Contents: COfsPropStg header
+//
+// Classes: COfsPropStg
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OFSPSTG_HXX__
+#define __OFSPSTG_HXX__
+
+#include <otrack.hxx>
+#include <dfmem.hxx>
+#include <ntsupp.hxx>
+#include <safepnt.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: COfsPropStg (ops)
+//
+// Purpose: IPropertyStorage implementation for OFS
+//
+// Interface: IPropertyStorage
+//
+// History: 10-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+interface COfsPropStg
+ : INHERIT_TRACKING,
+ public IPropertyStorage
+{
+public:
+ COfsPropStg(void);
+ SCODE InitFromHandle(HANDLE h, REFIID riid);
+ ~COfsPropStg(void);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // IPropertyStorage
+ STDMETHOD(ReadMultiple)(THIS_
+ ULONG cpspec,
+ PROPSPEC FAR rgpspec[],
+ FILETIME FAR *pftmModified,
+ PROPID FAR rgdispid[],
+ PROPVARIANT FAR rgvar[]);
+ STDMETHOD(WriteMultiple)(THIS_
+ ULONG cpspec,
+ PROPSPEC FAR rgpspec[],
+ PROPID FAR rgdispid[],
+ PROPVARIANT FAR rgvar[]);
+ STDMETHOD(DeleteMultiple)(THIS_
+ ULONG cpspec,
+ PROPSPEC FAR rgpspec[]);
+ STDMETHOD(Enum)(THIS_
+ IEnumSTATPROPSTG FAR * FAR *ppenm);
+ STDMETHOD(Commit)(THIS_
+ DWORD grfCommitFlags);
+ STDMETHOD(Revert)(THIS);
+ STDMETHOD(Stat)(THIS_
+ STATPROPSETSTG FAR *pstat);
+
+private:
+ inline SCODE Validate(void) const;
+
+ IID _iid;
+ ULONG _sig;
+ NuSafeNtHandle _h;
+};
+
+SAFE_INTERFACE_PTR(SafeCOfsPropStg, COfsPropStg);
+
+#define COFSPROPSTG_SIG LONGSIG('O', 'F', 'P', 'S')
+#define COFSPROPSTG_SIGDEL LONGSIG('O', 'f', 'P', 's')
+
+//+--------------------------------------------------------------
+//
+// Member: COfsPropStg::Validate, public
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+// History: 20-Jan-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+inline SCODE COfsPropStg::Validate(void) const
+{
+ return (this == NULL || _sig != COFSPROPSTG_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+#endif // #ifndef __OFSPSTG_HXX__
diff --git a/private/ole32/stg/ofsstg/ostgsupp.cxx b/private/ole32/stg/ofsstg/ostgsupp.cxx
new file mode 100644
index 000000000..ae4c22b7e
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ostgsupp.cxx
@@ -0,0 +1,1163 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ostgsupp.cxx
+//
+// Contents: Storage create/open support routines
+//
+// History: 14-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include <iofs.h>
+#include <stgprop.h>
+#include <ntlkb.hxx>
+#include <stgutil.hxx>
+//#include "prstg.hxx"
+#include "ofscs.hxx"
+#include <dfentry.hxx>
+
+#include <initguid.h> // IID is defined in stgint.h for Internal Use Only
+DEFINE_GUID (IID_IStorageReplica,
+ 0x521a28f3,0xe40b,0x11ce,0xb2,0xc9,0x00,0xaa,0x00,0x68,0x09,0x37);
+
+// Docfiles require read permission on the file so give it
+#define PERM_MASK (STGM_READ | STGM_WRITE | STGM_READWRITE)
+#define FORCE_READ(grfMode) \
+ if (((grfMode) & PERM_MASK) == STGM_WRITE) \
+ (grfMode) = ((grfMode) & ~PERM_MASK) | STGM_READWRITE; \
+ else 1
+
+//+---------------------------------------------------------------------------
+//
+// Function: OfsTaskAlloc, public
+//
+// Synopsis: Task allocator function for OFS property APIs
+//
+// Arguments: [cb] - Count of bytes to allocate
+//
+// Returns: Appropriate status code
+//
+// History: 05-Jan-94 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+LPVOID WINAPI OfsTaskAlloc(ULONG cb)
+{
+ ssDebugOut((DEB_ITRACE, "In OfsTaskAlloc(%lu)\n", cb));
+ ssDebugOut((DEB_ITRACE, "Out OfsTaskAlloc\n"));
+ return CoTaskMemAlloc(cb);
+}
+
+#if 0
+//+---------------------------------------------------------------------------
+//
+// Function: OfsDfCreateStorage, public
+//
+// Synopsis: BUGBUG - Stub function
+//
+// History: 13-Jul-93 DrewB Created
+// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
+//
+//----------------------------------------------------------------------------
+
+STDAPI OfsDfCreateStorage(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE h,
+ DWORD grfMode,
+ LPSECURITY_ATTRIBUTES pssSecurity,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ SafeCNtLockBytes pnlb;
+ SafeIStorage pstg;
+
+ FORCE_READ(grfMode);
+ pnlb.Attach(new CNtLockBytes(TRUE));
+ ssMem((CNtLockBytes *)pnlb);
+ if (h != NULL)
+ {
+ ssChk(pnlb->InitFromHandle(h, pwcsName, grfMode));
+ }
+ else
+ {
+ ssChk(pnlb->InitFromPath(hParent, pwcsName, grfMode,
+ CO_CREATE, pssSecurity));
+ }
+ grfMode = (grfMode & ~STGM_DELETEONRELEASE) | STGM_CREATE;
+ ssChk(StgCreateDocfileOnILockBytes(pnlb, grfMode, 0, &pstg));
+
+ TRANSFER_INTERFACE(pstg, IStorage, ppstg);
+
+ EH_Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OfsDfOpenStorage, public
+//
+// Synopsis: BUGBUG - Stub function
+//
+// History: 13-Jul-93 DrewB Created
+// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
+//
+//----------------------------------------------------------------------------
+
+STDAPI OfsDfOpenStorage(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE h,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ SafeCNtLockBytes pnlb;
+ SafeIStorage pstg;
+
+ FORCE_READ(grfMode);
+ pnlb.Attach(new CNtLockBytes(TRUE));
+ ssMem((CNtLockBytes *)pnlb);
+ if (h != NULL)
+ {
+ ssChk(pnlb->InitFromHandle(h, pwcsName, grfMode));
+ }
+ else
+ {
+ ssChk(pnlb->InitFromPath(hParent, pwcsName, grfMode,
+ CO_OPEN, NULL));
+ }
+ ssChk(StgOpenStorageOnILockBytes(pnlb, pstgPriority, grfMode,
+ snbExclude, 0, &pstg));
+ TRANSFER_INTERFACE(pstg, IStorage, ppstg);
+
+ EH_Err:
+ return sc;
+}
+// OfsDfCreateStorage and OfsDfOpenStorage have been replaced
+// by DfCreateDocfile and DfOpenDocfile
+#endif // 0
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OfsDocCreateStorage, public
+//
+// Synopsis: Create a new document storage
+//
+// History: 11-Feb-94 PhilipLa Created.
+// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
+//
+//----------------------------------------------------------------------------
+
+STDAPI OfsDocCreateStorage(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE h,
+ DWORD grfMode,
+ LPSECURITY_ATTRIBUTES pssSecurity,
+ BOOL fRoot,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ SafeCOfsDocStorage pstg;
+
+ FORCE_READ(grfMode);
+
+ pstg.Attach(new COfsDocStorage());
+ ssMem((COfsDocStorage *)pstg);
+
+ if (h != NULL)
+ {
+ ssChk(pstg->InitFromHandle(h, pwcsName, grfMode, fRoot));
+ }
+ else
+ {
+ ssChk(pstg->InitFromPath(hParent, pwcsName, grfMode,
+ CO_CREATE, pssSecurity, fRoot));
+ }
+ TRANSFER_INTERFACE(pstg, IStorage, ppstg);
+
+ EH_Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OfsDocOpenStorage, public
+//
+// Synopsis: Open an existing document storage
+//
+// History: 11-Feb-94 PhilipLa Created.
+// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
+//
+//----------------------------------------------------------------------------
+
+STDAPI OfsDocOpenStorage(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE *ph,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ BOOL fRoot,
+ IStorage **ppstg)
+{
+
+ SCODE sc;
+ SafeCOfsDocStorage pstg;
+
+ //BUGBUG: What do we do for PRIORITY mode?
+ ssAssert(((grfMode & STGM_PRIORITY) == 0) ||
+ aMsg("Priority mode not supported yet."));
+
+ FORCE_READ(grfMode);
+ pstg.Attach(new COfsDocStorage());
+ ssMem((COfsDocStorage *)pstg);
+
+ if (*ph != NULL)
+ {
+ ssChk(pstg->InitFromHandle(*ph, pwcsName, grfMode, fRoot));
+ }
+ else
+ {
+ ssChk(pstg->InitFromPath(hParent, pwcsName, grfMode,
+ CO_OPEN, NULL, fRoot));
+ }
+
+ if (snbExclude)
+ {
+ HANDLE hDummy;
+ sc = pstg->ExcludeEntries(snbExclude);
+ if (FAILED(sc)) // On failure, pstg will destroy object
+ *ph = NULL; // and automatically close the handle
+ ssChk (sc); // Inform outer routine not to close
+ }
+
+ TRANSFER_INTERFACE(pstg, IStorage, ppstg);
+
+
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OfsDirOpenStorage, public
+//
+// Synopsis: Open an existing document storage
+//
+// History: 11-Feb-94 PhilipLa Created.
+// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
+//
+//----------------------------------------------------------------------------
+
+STDAPI OfsDirOpenStorage(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE h,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ BOOL fRoot,
+ IStorage **ppstg)
+{
+
+ SCODE sc;
+ SafeCOfsDirStorage pdirstg;
+
+ //BUGBUG: What do we do for PRIORITY mode?
+ ssAssert(((grfMode & STGM_PRIORITY) == 0) ||
+ aMsg("Priority mode not supported yet."));
+ ssAssert((pstgPriority == NULL) && (snbExclude == NULL));
+
+ FORCE_READ(grfMode);
+ pdirstg.Attach(new COfsDirStorage());
+ ssMem((COfsDirStorage *)pdirstg);
+
+ if (h != NULL)
+ {
+ ssChk(pdirstg->InitFromHandle(h, pwcsName, grfMode));
+ }
+ else
+ {
+ ssChk(pdirstg->InitFromPath(hParent, pwcsName, grfMode,
+ CO_OPEN, FALSE, NULL));
+ }
+ TRANSFER_INTERFACE(pdirstg, IStorage, ppstg);
+
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OfsCreateStorageType, public
+//
+// Synopsis: Creates a storage of the appropriate type
+//
+// Arguments: [hParent] - Parent handle or NULL
+// [pwcsName] - Name or path
+// [grfMode] - Mode
+// [dwStgFmt] - Type of storage
+// [pssSecurity] - Security
+// [fRoot] - TRUE => creating root of storage
+// [ppstg] - New storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 24-Jun-93 DrewB Created
+// 24-Mar-95 HenryLee Store drive letter to fix Stat problem
+//
+//----------------------------------------------------------------------------
+
+SCODE OfsCreateStorageType(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE h,
+ DWORD grfMode,
+ DWORD dwStgFmt,
+ LPSECURITY_ATTRIBUTES pssSecurity,
+ BOOL fRoot,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ SafeCOfsDirStorage pds;
+ SafeCOfsFileStorage pfs;
+ SafeCOfsCatalogFile pcf;
+
+ ssDebugOut((DEB_ITRACE, "In OfsCreateStorageType("
+ "%p, %ws, %p, %lX, %lu, %p, %p)\n",
+ hParent, pwcsName, h, grfMode, dwStgFmt, pssSecurity, ppstg));
+
+ sc = S_OK;
+ switch(dwStgFmt)
+ {
+ case STGFMT_DOCUMENT:
+ sc = GetScode(OfsDocCreateStorage(hParent, pwcsName, h, grfMode,
+ pssSecurity, fRoot, ppstg));
+ break;
+
+ case STGFMT_CATALOG:
+ pcf.Attach(new COfsCatalogFile());
+ ssMem((COfsCatalogFile *)pcf);
+ ssChk(pcf->InitPath(pwcsName));
+ if (h != NULL)
+ {
+ ssChk(pcf->InitFromHandle(h, grfMode, pwcsName));
+ }
+ else
+ {
+ ssChk(pcf->InitFromPath(hParent, pwcsName, grfMode, CO_CREATE,
+ pssSecurity));
+ }
+
+ TRANSFER_INTERFACE(pcf, IStorage, ppstg);
+ break;
+
+ case STGFMT_DIRECTORY:
+ case STGFMT_JUNCTION:
+ pds.Attach(new COfsDirStorage());
+ ssMem((COfsDirStorage *)pds);
+ if (h != NULL)
+ {
+ ssChk(pds->InitFromHandle(h, pwcsName, grfMode));
+ }
+ else
+ {
+ ssChk(pds->InitFromPath(hParent, pwcsName, grfMode,
+ CO_CREATE, FALSE, pssSecurity));
+ }
+ TRANSFER_INTERFACE(pds, IStorage, ppstg);
+ break;
+
+ case STGFMT_FILE:
+ pfs.Attach(new COfsFileStorage());
+ ssMem((COfsFileStorage *)pfs);
+ if (h != NULL)
+ {
+ ssChk(pfs->InitFromHandle(h, grfMode));
+ }
+ else
+ {
+ ssChk(pfs->InitFromPath(hParent, pwcsName, grfMode, CO_CREATE,
+ pssSecurity));
+ }
+ TRANSFER_INTERFACE(pfs, IStorage, ppstg);
+ break;
+
+ default:
+ ssAssert(!aMsg("OfsCreateStorageType default hit"));
+ *ppstg = NULL;
+ break;
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out OfsCreateStorageType => %p, 0x%lX\n",
+ *ppstg, sc));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OfsOpenAnyStorage, public
+//
+// Synopsis: Opens a storage of the appropriate type
+//
+// Arguments: [hParent] - Parent handle or NULL
+// [pwcsName] - Name or path
+// [h] - Handle if already open or NULL
+// [dwStgFmt] - Storage format for [h]
+// [pstgPriority] - Priority mode prior open
+// [grfMode] - Mode
+// [snbExclude] - Exclusions
+// [fRoot] - TRUE -> root storage
+// [ppstg] - Storage return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 14-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SCODE OfsOpenAnyStorage(HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE *ph,
+ DWORD dwStgFmt,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ BOOL fRoot,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ SafeCOfsFileStorage pfs;
+ SafeCOfsCatalogFile pcf;
+ SafeNtHandle hSafe;
+ HANDLE h = (ph == NULL) ? NULL : *ph;
+
+ ssDebugOut((DEB_ITRACE, "In OfsOpenAnyStorage("
+ "%p, %ws, %p, %lu, %p, %lX, %p, %p)\n", hParent, pwcsName,
+ h, dwStgFmt, pstgPriority, grfMode, snbExclude, ppstg));
+
+ sc = S_OK;
+ if (h == NULL)
+ {
+ ssChk(DetermineStgType(hParent, pwcsName, grfMode,
+ &dwStgFmt, &hSafe));
+ h = hSafe;
+ }
+ switch(dwStgFmt)
+ {
+ case STGFMT_DOCUMENT:
+ sc = DfIsDocfile(h);
+ if (sc == S_OK)
+ {
+ // docfile will reopen the storage will different permissions
+ if (h)
+ {
+ NTSTATUS nts = NtClose(h);
+ h = NULL;
+ }
+ sc = DfOpenDocfile (pwcsName, NULL, pstgPriority, grfMode,
+ snbExclude, NULL, ppstg);
+
+ } else if ( sc == S_FALSE ) {
+ sc = GetScode(OfsDocOpenStorage(hParent, pwcsName, ph,
+ pstgPriority, grfMode,
+ snbExclude, fRoot, ppstg));
+ }
+ break;
+
+ case STGFMT_DIRECTORY:
+ case STGFMT_JUNCTION:
+ if (pstgPriority != NULL || snbExclude != NULL)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+
+ sc = GetScode(OfsDirOpenStorage(hParent, pwcsName, h,
+ pstgPriority, grfMode,
+ snbExclude, fRoot, ppstg));
+ break;
+
+ case STGFMT_CATALOG:
+ if (pstgPriority != NULL || snbExclude != NULL)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+
+ pcf.Attach(new COfsCatalogFile());
+ ssMem((COfsCatalogFile *)pcf);
+ ssChk(pcf->InitPath(pwcsName));
+ ssChk(pcf->InitFromHandle(h, grfMode, pwcsName));
+ TRANSFER_INTERFACE(pcf, IStorage, ppstg);
+ break;
+
+ case STGFMT_FILE:
+#if 0
+ // BUGBUG [mikese] "File as an IStorage" behaviour has been disabled,
+ // because it causes compatibility problems. For example, Excel 5.0
+ // expects StgOpenStorage on a non-Docfile to fail, not for it to
+ // return successfully.
+ // This behaviour may be reenabled, through a different public API
+ // at a later time.
+
+ if (pstgPriority != NULL || snbExclude != NULL)
+ ssErr(EH_Err, STG_E_INVALIDFUNCTION);
+
+ pfs.Attach(new COfsFileStorage());
+ ssMem((COfsFileStorage *)pfs);
+ ssChk(pfs->InitFromHandle(h, grfMode));
+ TRANSFER_INTERFACE(pfs, IStorage, ppstg);
+#else
+ // This is the status code returned by Daytona OLE if you attempt to
+ // open a non-Docfile with StgOpenStorage.
+ sc = STG_E_FILEALREADYEXISTS;
+#endif
+ break;
+ default:
+ ssAssert(!aMsg("OfsOpenAnyStorage default hit"));
+ *ppstg = NULL;
+ break;
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out OfsOpenAnyStorage => %p, %lX\n", *ppstg, sc));
+ EH_Err:
+ return sc;
+}
+
+#if 0
+
+//+---------------------------------------------------------------------------
+//
+// Function: CopyProperties, public
+//
+// Synopsis: Copies all properties from one property storage to another
+//
+// Arguments: [ppstgFrom] - Source
+// [ppstgTo] - Destination
+// [fSkipOid] - TRUE iff this is the system properties and we are
+// to skip the object id.
+//
+// Returns: Appropriate status code
+//
+// History: 22-Sep-93 DrewB Created
+//
+// Notes: This function is separate only for readability, and this is
+// declared inline.
+//
+//----------------------------------------------------------------------------
+
+
+inline SCODE CopyProperties(
+ IPropertyStorage *ppstgFrom,
+ IPropertyStorage *ppstgTo,
+ BOOL fSkipOid )
+{
+ SafeIEnumSTATPROPSTG penm;
+ STATPROPSTG stat;
+ SCODE sc;
+ PROPVARIANT var;
+
+ ssDebugOut((DEB_ITRACE, "In CopyProperties(%p, %p)\n",
+ ppstgFrom, ppstgTo));
+
+ olHChk(ppstgFrom->Enum(&penm));
+ for (;;)
+ {
+ sc = GetScode(penm->Next(1, &stat, NULL));
+ if (FAILED(sc) || sc == S_FALSE)
+ {
+ if (sc == S_FALSE)
+ sc = S_OK;
+ break;
+ }
+ else
+ {
+ PROPSPEC pspec;
+ WCHAR awcName[CWCSTORAGENAME];
+
+ if (stat.lpwstrName)
+ {
+ pspec.ulKind = PRSPEC_LPWSTR;
+ pspec.lpwstr = awcName;
+ olAssert(wcslen(stat.lpwstrName) < CWCSTORAGENAME);
+ wcscpy(awcName, stat.lpwstrName);
+ olHVerSucc(CoMemFree(stat.lpwstrName));
+ }
+ else
+ {
+ pspec.ulKind = PRSPEC_PROPID;
+ pspec.propid = stat.propid;
+ }
+
+ if ( !( fSkipOid
+ && (pspec.ulKind == PRSPEC_PROPID)
+ && (pspec.propid == PROPID_STG_OBJECTID)) )
+ {
+ olHChk(ppstgFrom->ReadMultiple(1, &pspec, NULL, NULL, &var));
+ sc = ppstgTo->WriteMultiple(1, &pspec, NULL, &var);
+ StgVariantClear(&var);
+ olChk(sc);
+ }
+ }
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out CopyProperties\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CopyPropSets, public
+//
+// Synopsis: Copies all property sets from one property set storage
+// to another
+//
+// Arguments: [ppsstgFrom] - Source
+// [ppsstgTo] - Destination
+// [ciidExclude] - Count of IIDs to exclude
+// [rgiidExclude] - IIDs to exclude from the copy
+//
+// Returns: Appropriate status code
+//
+// History: 22-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+SAFE_INTERFACE_PTR(SafeIEnumSTATPROPSETSTG, IEnumSTATPROPSETSTG);
+
+SCODE CopyPropSets(IPropertySetStorage *ppsstgFrom,
+ IPropertySetStorage *ppsstgTo,
+ ULONG ciidExclude,
+ IID const *rgiidExclude)
+{
+ SafeIEnumSTATPROPSETSTG penm;
+ STATPROPSETSTG stat;
+ SCODE sc;
+ ULONG i;
+ ULONG j;
+
+ ssDebugOut((DEB_ITRACE, "In CopyPropSets(%p, %p, %lu, %p)\n",
+ ppsstgFrom, ppsstgTo, ciidExclude, rgiidExclude));
+
+ // The following loop leaves j as is the index of IEnableObjectIdCopy
+ // if specified, or as ciidExclude is not specified.
+
+ for (j=0; j<ciidExclude;j++)
+ {
+ if (IsEqualIID(rgiidExclude[j], IID_IEnableObjectIdCopy))
+ break;
+ }
+
+ BOOL fEnableObjectIdCopy = ( j != ciidExclude );
+
+ olHChk(ppsstgFrom->Enum(&penm));
+ for (;;)
+ {
+ sc = GetScode(penm->Next(1, &stat, NULL));
+ if (FAILED(sc) || sc == S_FALSE)
+ {
+ if (sc == S_FALSE)
+ sc = S_OK;
+ break;
+ }
+
+ for (i = 0; i < ciidExclude; i++)
+ if (IsEqualIID(stat.iid, rgiidExclude[i]))
+ break;
+ if (i != ciidExclude)
+ {
+ continue;
+ }
+ else
+ {
+ SafeIPropertyStorage ppstgFrom, ppstgTo;
+
+ olHChk(ppsstgFrom->Open(stat.iid, STGM_DIRECT | STGM_READ |
+ STGM_SHARE_EXCLUSIVE, &ppstgFrom));
+ sc = GetScode(ppsstgTo->Open(stat.iid, STGM_DIRECT | STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE, &ppstgTo));
+ if (sc == STG_E_FILENOTFOUND)
+ sc = GetScode(ppsstgTo->Create(stat.iid, STGM_DIRECT |
+ STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE,
+ &ppstgTo));
+ olChk(sc);
+
+ // Does this property set contain the object id and property, and
+ // should we skip it?
+ BOOL fSkipOid = !fEnableObjectIdCopy
+ && IsEqualGUID ( stat.iid, guidSysProp );
+
+ olChk(CopyProperties(ppstgFrom, ppstgTo, fSkipOid));
+ }
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out CopyPropSets\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: PropCopyTo, public
+//
+// Synopsis: Performs property portion of CopyTo
+//
+// Arguments: [pstgFrom] - Source
+// [pstgTo] - Destination
+// [ciidExclude] - IID exclusions
+// [rgiidExclude] - IIDs to exclude
+//
+// Returns: Appropriate status code
+//
+// History: 30-Sep-93 DrewB Created
+//
+// Notes: Assumes source supports IPropertySetStorage
+//
+//----------------------------------------------------------------------------
+
+SAFE_INTERFACE_PTR(SafeIPropertySetStorage, IPropertySetStorage);
+
+SCODE PropCopyTo(IStorage *pstgFrom,
+ IStorage *pstgTo,
+ ULONG ciidExclude,
+ IID const *rgiidExclude)
+{
+ SCODE sc;
+ SafeIPropertySetStorage ppsstgFrom, ppsstgTo;
+ BOOL fCopyProps = TRUE;
+ ULONG i;
+
+ ssDebugOut((DEB_ITRACE, "In PropCopyTo(%p, %p, %lu, rgiid)\n",
+ pstgTo, pstgFrom, ciidExclude));
+
+ sc = S_OK;
+ for (i = 0; i < ciidExclude; i++)
+ if (IsEqualIID(rgiidExclude[i], IID_IPropertySetStorage))
+ {
+ fCopyProps = FALSE;
+ break;
+ }
+
+ if (fCopyProps)
+ {
+ olVerSucc(pstgFrom->QueryInterface(IID_IPropertySetStorage,
+ (void **)&ppsstgFrom));
+ sc = pstgTo->QueryInterface(IID_IPropertySetStorage,
+ (void **)&ppsstgTo);
+ if (SUCCEEDED(sc))
+ {
+ sc = CopyPropSets(ppsstgFrom, ppsstgTo, ciidExclude, rgiidExclude);
+ }
+ else if (sc == E_NOINTERFACE)
+ {
+ // BUGBUG - STG_E_DESTLACKSINTERFACE seems to be gone,
+ // but it's in the spec
+ // sc = STG_E_DESTLACKSINTERFACE;
+ }
+ }
+
+ ssDebugOut((DEB_ITRACE, "Out PropCopyTo => %lX\n", sc));
+ return sc;
+}
+
+#endif // 0
+
+//+---------------------------------------------------------------------------
+//
+// Function: CopyTemplateProperties, public
+//
+// Synopsis: copy contents from a template object
+//
+// Arguments: [pstgSource] - source storage containing properties
+// [pstgDest] - destination storage to receive properties
+//
+// Returns: Appropriate status code
+//
+// History: 10-July-1995 HenryLee created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+SCODE CopyTemplateProperties (IStorage *pstgSource, IStorage *pstgDest)
+{
+ SCODE sc = S_OK;
+
+ IEnumSTATSTG *penum;
+ STATSTG statstg;
+ // BUGBUG IStorage should enumerate the OLE namespace
+ ssChk(pstgSource->EnumElements(NULL,NULL,NULL,&penum));
+ while ((sc = penum->Next(1,&statstg,NULL)) == S_OK)
+ {
+ // BUGBUG when ready, use Vic's new method to determine property set
+ if (statstg.pwcsName && statstg.pwcsName[0] == L'\005')
+ {
+ sc = pstgSource->MoveElementTo(statstg.pwcsName,
+ pstgDest, statstg.pwcsName, STGMOVE_COPY);
+ }
+ if (statstg.pwcsName)
+ ssVerSucc(CoMemFree(statstg.pwcsName));
+ if (!SUCCEEDED(sc))
+ break;
+ }
+ penum->Release();
+ if (sc == S_FALSE)
+ sc = S_OK;
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: CopyTemplateObject, public
+//
+// Synopsis: copy contents from a template object
+//
+// Arguments: [pTemplate] - source object and interfaces to copy
+// [pUnkDest] - destination object
+// [riid] - interface supported on destination object
+//
+// Returns: Appropriate status code
+//
+// History: 10-July-1995 HenryLee created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+SCODE CopyTemplateObject (STGTEMPLATE *pTemplate,IUnknown *pUnkDest,REFIID riid)
+{
+ SCODE sc = S_OK;
+ if (pTemplate->pUnkTemplate == NULL || pTemplate->riidTemplate == NULL)
+ ssErr (EH_Err, STG_E_INVALIDPOINTER);
+
+ if (riid == IID_IStorage)
+ {
+ for (DWORD dw=0; dw < pTemplate->ciidTemplate; dw++)
+ {
+ if (pTemplate->riidTemplate[dw] == IID_IPropertySetStorage)
+ {
+ // enum the property sets and copy them
+ IStorage *pstgSource;
+ IStorage *pstgDest = (IStorage *) pUnkDest;
+ sc = pTemplate->pUnkTemplate->QueryInterface (IID_IStorage,
+ (void**)&pstgSource);
+ if (SUCCEEDED(sc))
+ {
+ sc = CopyTemplateProperties (pstgSource, pstgDest);
+ pstgSource->Release();
+ }
+ }
+ }
+ }
+ else if (riid == IID_IDirectory)
+ {
+ for (DWORD dw=0; dw < pTemplate->ciidTemplate; dw++)
+ {
+ if (pTemplate->riidTemplate[dw] == IID_IPropertySetStorage)
+ {
+ // enum the property sets and copy them
+ IStorage *pstgSource;
+ IStorage *pstgDest;
+ if (SUCCEEDED(sc = pTemplate->pUnkTemplate->QueryInterface
+ (IID_IStorage,
+ (void**)&pstgSource)))
+ {
+ if (SUCCEEDED(sc = pUnkDest->QueryInterface (IID_IStorage,
+ (void**)&pstgDest)))
+ {
+ sc = CopyTemplateProperties (pstgSource, pstgDest);
+ pstgDest->Release();
+ }
+ pstgSource->Release();
+ }
+ }
+ }
+ }
+ else if (riid == IID_IStream)
+ {
+ for (DWORD dw=0; dw < pTemplate->ciidTemplate; dw++);
+ {
+ // properties on files not supported yet
+ }
+ }
+ else sc = STG_E_INVALIDPARAMETER;
+
+EH_Err:
+ return ssResult(sc);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: InitDirectory, public
+//
+// Synopsis: creates or opens an IDirectory object
+//
+// Arguments: [hParent] - parent file handle for relative opens
+// [pwcsName] - directory name
+// [h] - initialize with this handle
+// [co] - create or open flag
+// [grfMode] - open/create mode
+// [pSecurity] - initial security attributes
+// [scOfs] - S_OK if OFS, S_FALSE if not, STG_E_INVALIDFLAG
+// [riid] - IID of interface pointer to return
+// [ppObjectOpen] - interface pointer to return
+//
+// Returns: Appropriate status code
+//
+// History: 10-July-1995 HenryLee created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE InitDirectory (HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE h,
+ CREATEOPEN co,
+ STGOPEN *pStgOpen,
+ STGCREATE *pStgCreate,
+ SCODE scOfs,
+ REFIID riid,
+ void ** ppObjectOpen)
+{
+ SCODE sc = S_OK;
+ COfsDirStorage *pds;
+ LPSECURITY_ATTRIBUTES pSecurity = NULL;
+
+ ssAssert (pStgOpen != NULL);
+ // if (co == CO_CREATE) ssAssert (pStgCreate != NULL);
+ ssAssert (!(co == CO_CREATE) || pStgCreate != NULL);
+ *ppObjectOpen = NULL;
+ if (co == CO_CREATE)
+ {
+ if (pStgOpen->grfMode & (STGM_CONVERT | STGM_SIMPLE))
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+ // BUGBUG convert OBJECT_SECURITY_INIT to SECURITY_ATTRIBUTES
+ pSecurity = (LPSECURITY_ATTRIBUTES) pStgCreate->pSecurity;
+ }
+ else if (co == CO_OPEN)
+ {
+ if (pStgOpen->grfMode & (STGM_CREATE | STGM_CONVERT | STGM_SIMPLE |
+ STGM_DELETEONRELEASE))
+ ssErr(EH_Err, STG_E_INVALIDFLAG);
+ }
+ else ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+
+ if (scOfs == STG_E_INVALIDFLAG)
+ if (hParent != NULL)
+ scOfs = HandleRefersToOfsVolume (hParent);
+ else
+ ssChk (scOfs = RefersToOfsVolume (pwcsName, CO_CREATE));
+
+ pds = new COfsDirStorage(scOfs == S_OK ? TRUE : FALSE);
+ ssMem((COfsDirStorage *)pds);
+ if (h != NULL)
+ {
+ ssChk(pds->InitFromHandle(h, pwcsName, pStgOpen->grfMode));
+ }
+ else
+ {
+ ssChk(pds->InitFromPath(hParent, pwcsName, pStgOpen->grfMode,
+ co, pStgOpen->stgfmt==STGFMT_JUNCTION, pSecurity));
+ }
+
+ sc = pds->QueryInterface (riid, ppObjectOpen);
+ // success case, undo QI AddRef
+ pds->Release(); // failure case, destroy obj
+
+ if (co == CO_CREATE && pStgCreate->pTemplate != NULL)
+ {
+ IDirectory * pdir = (IDirectory *) pds;
+ CopyTemplateObject (pStgCreate->pTemplate, pdir, IID_IDirectory);
+ }
+EH_Err:
+ return sc;
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: InitStorage, public
+//
+// Synopsis: creates or opens an IStorage object
+//
+// Arguments: [hParent] - parent file handle for relative opens
+// [pwcsName] - directory name
+// [h] - initialize with this handle (not supported)
+// [grfMode] - open/create mode
+// [stgfmt] - intended storage format
+// [co] - create or open flag
+// [pSecurity] - initial security attributes
+// [wcDrive] - drive letter of hParent
+// [pscOfs] - if hParent is on an OFS drive
+// [riid] - IID of interface pointer to return
+// [ppObjectOpen] - interface pointer to return
+//
+// Returns: Appropriate status code
+//
+// History: 10-July-1995 HenryLee created
+//
+// Notes:
+//
+//
+//----------------------------------------------------------------------------
+SCODE InitStorage (HANDLE hParent,
+ WCHAR const *pwcsName,
+ HANDLE h,
+ CREATEOPEN co,
+ STGOPEN *pStgOpen,
+ STGCREATE *pStgCreate,
+ WCHAR const wcDrive,
+ SCODE *pscOfs,
+ BOOL fRestricted,
+ REFIID riid,
+ void **ppObjectOpen)
+{
+ SCODE sc = S_OK;
+ DWORD dwStgfmt = STGFMT_DOCUMENT;
+ IStorage *pstg;
+ NTSTATUS nts;
+ LPSECURITY_ATTRIBUTES pSecurity = NULL;
+
+ ssAssert (pscOfs != NULL);
+ ssAssert (pStgOpen != NULL);
+ // if (co == CO_CREATE) ssAssert (pStgCreate != NULL);
+ ssAssert (!(co == CO_CREATE) || pStgCreate != NULL);
+
+ STGFMT stgfmt = pStgOpen->stgfmt;
+ if (*pscOfs == STG_E_INVALIDFLAG) // true, false, or uninitialized
+ if (hParent != NULL)
+ *pscOfs = HandleRefersToOfsVolume (hParent);
+ else
+ {
+#ifdef TRANSACT_OLE
+ ssChk (sc = RefersToOfsVolume (pwcsName, CO_CREATE));
+#else
+ ssChk (sc = RefersToOfsVolume (pwcsName, co));
+#endif
+ *pscOfs = sc;
+ }
+
+#ifdef TRANSACT_OLE
+ if (*pscOfs == S_OK && stgfmt != STGFMT_DOCFILE)
+ {
+ if (fRestricted && // Dsys API, no direct mode
+ (pStgOpen->grfMode & STGM_TRANSACTED) == 0)
+ ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+ if (!fRestricted && // Stg API, map transacted into direct
+ (pStgOpen->grfMode & STGM_TRANSACTED))
+ pStgOpen->grfMode &= ~STGM_TRANSACTED;
+ }
+#endif
+
+ if (co == CO_CREATE)
+ {
+ // BUGBUG convert OBJECT_SECURITY_INIT to SECURITY_ATTRIBUTES
+ pSecurity = (LPSECURITY_ATTRIBUTES) pStgCreate->pSecurity;
+ if (*pscOfs == S_OK && stgfmt != STGFMT_DOCFILE)
+ {
+ if (stgfmt == STGFMT_STORAGE)
+ stgfmt = STGFMT_DOCUMENT;
+
+ sc = OfsCreateStorageType(hParent, pwcsName,NULL,pStgOpen->grfMode,
+ (DWORD) stgfmt, pSecurity,
+ TRUE, &pstg);
+ }
+ else
+ {
+ ssAssert ((*pscOfs == S_FALSE || stgfmt == STGFMT_DOCFILE));
+ // structured storage and summary catalog not supported non-OFS
+ if (stgfmt == STGFMT_STORAGE || stgfmt == STGFMT_CATALOG)
+ ssErr (EH_Err, STG_E_INVALIDFUNCTION);
+
+ if (stgfmt == STGFMT_DOCFILE)
+ stgfmt = STGFMT_DOCUMENT;
+
+ WCHAR awcsFullName[_MAX_PATH];
+ if (hParent != NULL)
+ sc = NameNtHandle (hParent, wcDrive, awcsFullName, pwcsName);
+ else
+ wcscpy (awcsFullName, pwcsName);
+
+ sc = DfCreateDocfile (awcsFullName,
+ pStgOpen->pTransaction,
+ pStgOpen->grfMode,
+#if WIN32 == 300
+ pSecurity, &pstg);
+#else
+ 0, &pstg);
+#endif
+ }
+ }
+ else if (co == CO_OPEN)
+ {
+ if (*pscOfs == S_OK && stgfmt != STGFMT_DOCFILE)
+ {
+ if (stgfmt == STGFMT_DOCUMENT || stgfmt == STGFMT_STORAGE)
+ {
+ sc = OfsDocOpenStorage(hParent, pwcsName, &h,
+ NULL, pStgOpen->grfMode,
+ NULL, TRUE, &pstg);
+ }
+ else if (stgfmt == STGFMT_CATALOG)
+ {
+ SafeCOfsCatalogFile pcf;
+ pcf.Attach(new COfsCatalogFile());
+ ssMem((COfsCatalogFile *)pcf);
+ ssChk(pcf->InitPath(pwcsName));
+ ssChk(GetNtHandle(hParent, pwcsName, pStgOpen->grfMode, 0, co,
+ FD_CATALOG, NULL, &h));
+ ssChk(pcf->InitFromHandle(h, pStgOpen->grfMode, pwcsName));
+ TRANSFER_INTERFACE(pcf, IStorage, &pstg);
+ }
+ else ssErr (EH_Err, STG_E_INVALIDFUNCTION);
+ }
+ else
+ {
+ ssAssert ((*pscOfs == S_FALSE || stgfmt == STGFMT_DOCFILE));
+ // structured storage and summary catalog not supported non-OFS
+ if (stgfmt == STGFMT_STORAGE || stgfmt == STGFMT_CATALOG)
+ ssErr (EH_Err, STG_E_INVALIDFUNCTION);
+
+ WCHAR pwcsFullName[_MAX_PATH];
+ if (stgfmt == STGFMT_CATALOG)
+ ssErr (EH_Err, STG_E_INVALIDFLAG);
+
+ if (hParent != NULL)
+ ssChk(NameNtHandle (hParent,wcDrive,pwcsFullName,pwcsName));
+ else
+ wcscpy (pwcsFullName, pwcsName);
+
+ //BUGBUG: Remove cast on pTransaction
+ sc = DfOpenDocfile (pwcsFullName,
+ (ITransaction *)pStgOpen->pTransaction,
+ NULL, pStgOpen->grfMode,
+ NULL, NULL, &pstg);
+
+ }
+
+ }
+ else ssErr (EH_Err, STG_E_INVALIDPARAMETER);
+
+ if (SUCCEEDED(sc))
+ {
+ sc = pstg->QueryInterface (riid, ppObjectOpen);
+ // success case, undo QI AddRef
+ pstg->Release(); // failure case, destroy obj
+
+ }
+
+ if (co == CO_CREATE && pStgCreate->pTemplate != NULL)
+ CopyTemplateObject (pStgCreate->pTemplate, pstg, IID_IStorage);
+EH_Err:
+ return sc;
+};
+
diff --git a/private/ole32/stg/ofsstg/ostgsupp.hxx b/private/ole32/stg/ofsstg/ostgsupp.hxx
new file mode 100644
index 000000000..8b019d5b6
--- /dev/null
+++ b/private/ole32/stg/ofsstg/ostgsupp.hxx
@@ -0,0 +1,35 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ostgsupp.hxx
+//
+// Contents: Storage support routines
+//
+// History: 14-Jul-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OSTGSUPP_HXX__
+#define __OSTGSUPP_HXX__
+
+SCODE OfsGetClassId(HANDLE h,
+ CLSID *pclsid);
+SCODE OfsSetClassId(HANDLE h,
+ REFCLSID rclsid);
+SCODE CopyProperties(IPropertyStorage *ppstgFrom,
+ IPropertyStorage *ppstgTo);
+SCODE CopyPropSets(IPropertySetStorage *ppsstgFrom,
+ IPropertySetStorage *ppsstgTo,
+ ULONG ciidExclude,
+ IID const *rgiidExclude);
+SCODE PropCopyTo(IStorage *pstgFrom,
+ IStorage *pstgTo,
+ ULONG ciidExclude,
+ IID const *rgiidExclude);
+
+SAFE_INTERFACE_PTR(SafeIPropertyStorage, IPropertyStorage);
+SAFE_INTERFACE_PTR(SafeIEnumSTATPROPSTG, IEnumSTATPROPSTG);
+
+#endif // #ifndef __OSTGSUPP_HXX__
diff --git a/private/ole32/stg/ofsstg/prstg.cxx b/private/ole32/stg/ofsstg/prstg.cxx
new file mode 100644
index 000000000..e326f9928
--- /dev/null
+++ b/private/ole32/stg/ofsstg/prstg.cxx
@@ -0,0 +1,67 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: prstg.cxx
+//
+// Contents: CPropStg
+//
+// History: 17-Aug-93 DrewB Created
+//
+// Notes: BUGBUG - Temporary
+//
+//----------------------------------------------------------------------------
+
+#include "headers.cxx"
+#pragma hdrstop
+
+#include "prstg.hxx"
+
+STDMETHODIMP CPropStg::QueryInterface(REFIID iid, void **ppvObj)
+{
+ if (IsEqualIID(iid, IID_IPropertySetStorage))
+ {
+ *ppvObj = (IPropertySetStorage *)this;
+ CPropStg::AddRef();
+ return NOERROR;
+ }
+ else
+ {
+ return _pstg->QueryInterface(iid, ppvObj);
+ }
+}
+
+STDMETHODIMP CPropStg::Stat(STATSTG *pstat, DWORD grfStatFlags)
+{
+ // We could pick up the class ID through the property interface
+ // but currently we're storing it in the docfile also so
+ // just use the standard code
+ return _pstg->Stat(pstat, grfStatFlags);
+}
+
+STDMETHODIMP CPropStg::SetClass(REFCLSID rclsid)
+{
+ SCODE sc;
+
+ // Set docfile class id
+ if (FAILED(sc = GetScode(_pstg->SetClass(rclsid))))
+ return sc;
+ // Set OFS class id
+ return OfsSetClassId(_h, rclsid);
+}
+
+STDMETHODIMP CPropStg::CopyTo(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest)
+{
+ SCODE sc;
+
+ // Copy properties if basic copy succeeds
+ sc = _pstg->CopyTo(ciidExclude, rgiidExclude, snbExclude,
+ pstgDest);
+ if (SUCCEEDED(sc))
+ sc = PropCopyTo(this, pstgDest, ciidExclude, rgiidExclude);
+ return sc;
+}
diff --git a/private/ole32/stg/ofsstg/prstg.hxx b/private/ole32/stg/ofsstg/prstg.hxx
new file mode 100644
index 000000000..c7bf1c92a
--- /dev/null
+++ b/private/ole32/stg/ofsstg/prstg.hxx
@@ -0,0 +1,158 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: prstg.hxx
+//
+// Contents: CPropStg
+//
+// History: 17-Aug-93 DrewB Created
+//
+// Notes: BUGBUG - Temporary
+//
+//----------------------------------------------------------------------------
+
+#ifndef __PRSTG_HXX__
+#define __PRSTG_HXX__
+
+#include <ofsps.hxx>
+
+class CPropStg
+ : public COfsPropSet,
+ INHERIT_TRACKING,
+ public IStorage
+{
+public:
+ CPropStg(void)
+ {
+ _pstg = NULL;
+ ENLIST_TRACKING(CPropStg);
+ }
+ SCODE InitFromHandle(HANDLE h, IStorage *pstg)
+ {
+ SCODE sc;
+
+ if (SUCCEEDED(sc = InitDup(h)))
+ {
+ _pstg = pstg;
+ olDebugOut((DEB_IWARN, "CPropStg %p handle %p thread %lX\n",
+ this, (HANDLE)_h, GetCurrentThreadId()));
+ }
+ return sc;
+ };
+ ~CPropStg(void)
+ {
+ olDebugOut((DEB_IWARN, "~CPropStg %p handle %p thread %lX\n",
+ this, (HANDLE)_h, GetCurrentThreadId()));
+ if (_pstg)
+ _pstg->Release();
+ }
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ DECLARE_STD_REFCOUNTING;
+
+ // The following IStorage methods are the only methods that have a
+ // non-trivial implementation
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+ STDMETHOD(SetClass)(REFCLSID clsid);
+ STDMETHOD(CopyTo)(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest);
+
+ // All other methods are delegated to the contained storage
+ STDMETHOD(CreateStream)(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm)
+ {
+ return _pstg->CreateStream(pwcsName, grfMode, reserved1,
+ reserved2, ppstm);
+ }
+ STDMETHOD(OpenStream)(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm)
+ {
+ return _pstg->OpenStream(pwcsName, reserved1, grfMode, reserved2,
+ ppstm);
+ }
+ STDMETHOD(CreateStorage)(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD stgType,
+ LPSTGSECURITY pssSecurity,
+ IStorage **ppstg)
+ {
+ return _pstg->CreateStorage(pwcsName, grfMode, stgType, pssSecurity,
+ ppstg);
+ }
+ STDMETHOD(OpenStorage)(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+ {
+ return _pstg->OpenStorage(pwcsName, pstgPriority, grfMode,
+ snbExclude, reserved, ppstg);
+ }
+ STDMETHOD(MoveElementTo)(WCHAR const *lpszName,
+ IStorage *pstgDest,
+ WCHAR const *lpszNewName,
+ DWORD grfFlags)
+ {
+ return _pstg->MoveElementTo(lpszName, pstgDest, lpszNewName,
+ grfFlags);
+ }
+ STDMETHOD(Commit)(DWORD grfCommitFlags)
+ {
+ return _pstg->Commit(grfCommitFlags);
+ }
+ STDMETHOD(Revert)(void)
+ {
+ return _pstg->Revert();
+ }
+ STDMETHOD(EnumElements)(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm)
+ {
+ return _pstg->EnumElements(reserved1, reserved2, reserved3, ppenm);
+ }
+ STDMETHOD(DestroyElement)(WCHAR const *pwcsName)
+ {
+ return _pstg->DestroyElement(pwcsName);
+ }
+ STDMETHOD(RenameElement)(WCHAR const *pwcsOldName,
+ WCHAR const *pwcsNewName)
+ {
+ return _pstg->RenameElement(pwcsOldName, pwcsNewName);
+ }
+ STDMETHOD(SetElementTimes)(const WCHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+ {
+ return _pstg->SetElementTimes(lpszName, pctime, patime, pmtime);
+ }
+ STDMETHOD(SetStateBits)(DWORD grfStateBits, DWORD grfMask)
+ {
+ return _pstg->SetStateBits(grfStateBits, grfMask);
+ }
+
+ virtual SCODE ExtValidate(void)
+ {
+ return S_OK;
+ }
+
+private:
+ IStorage *_pstg;
+};
+
+SAFE_INTERFACE_PTR(SafeCPropStg, CPropStg);
+
+#endif // #ifndef __PRSTG_HXX__
diff --git a/private/ole32/stg/ofsstg/utest/depend.mk b/private/ole32/stg/ofsstg/utest/depend.mk
new file mode 100644
index 000000000..bffe5b33f
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest/depend.mk
@@ -0,0 +1,91 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\ofstest.obj $(OBJDIR)\ofstest.lst: .\ofstest.cxx \
+ $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h $(COMMON)\ih\winnot.h \
+ $(COMMONINC)\baseole.h $(COMMONINC)\basetyps.h $(COMMONINC)\cguid.h \
+ $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h $(COMMONINC)\dispatch.h \
+ $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h $(COMMONINC)\idltyps.h \
+ $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h $(COMMONINC)\ole2.h \
+ $(COMMONINC)\oletyp.h $(COMMONINC)\prspec.h $(COMMONINC)\querys.h \
+ $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h $(COMMONINC)\stgprop.h \
+ $(COMMONINC)\varnt.h $(COMMONINC)\winole.h $(COMMONINC)\wtypes.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\time.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\pch.cxx .\tutils.hxx
+
+$(OBJDIR)\tutils.obj $(OBJDIR)\tutils.lst: .\tutils.cxx \
+ $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h $(COMMON)\ih\winnot.h \
+ $(COMMONINC)\basetyps.h $(COMMONINC)\prspec.h $(COMMONINC)\varnt.h \
+ $(COMMONINC)\wtypes.h $(COMMONINC)\baseole.h $(COMMONINC)\basetyps.h \
+ $(COMMONINC)\cguid.h $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h \
+ $(COMMONINC)\dispatch.h $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h \
+ $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h \
+ $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\querys.h $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h \
+ $(COMMONINC)\stgprop.h $(COMMONINC)\varnt.h $(COMMONINC)\winole.h \
+ $(COMMONINC)\wtypes.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\time.h $(OSINC)\rpc.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\pch.cxx \
+ .\tutils.hxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\pch.pxh $(PCHDIR)\$(OBJDIR)\pch.lst: \
+ $(OLE)\ofsstg\utest\pch.cxx $(COMMON)\ih\stgint.h $(COMMON)\ih\types.h \
+ $(COMMON)\ih\winnot.h $(COMMONINC)\baseole.h $(COMMONINC)\basetyps.h \
+ $(COMMONINC)\cguid.h $(COMMONINC)\cobjerr.h $(COMMONINC)\dfsh.h \
+ $(COMMONINC)\dispatch.h $(COMMONINC)\disptype.h $(COMMONINC)\dsbase.h \
+ $(COMMONINC)\idltyps.h $(COMMONINC)\itabls.h $(COMMONINC)\memalloc.h \
+ $(COMMONINC)\ole2.h $(COMMONINC)\oletyp.h $(COMMONINC)\prspec.h \
+ $(COMMONINC)\querys.h $(COMMONINC)\scode.h $(COMMONINC)\shtyps.h \
+ $(COMMONINC)\stgprop.h $(COMMONINC)\varnt.h $(COMMONINC)\winole.h \
+ $(COMMONINC)\wtypes.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\time.h $(OLE)\ofsstg\utest\tutils.hxx \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
+.\$(OBJDIR)\ofstest.obj : $(PCHDIR)\$(OBJDIR)\pch.pxh
+.\$(OBJDIR)\tutils.obj : $(PCHDIR)\$(OBJDIR)\pch.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/ofsstg/utest/dirs b/private/ole32/stg/ofsstg/utest/dirs
new file mode 100644
index 000000000..17774f2cd
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest/dirs
@@ -0,0 +1,22 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+DIRS=
+OPTIONAL_DIRS=
diff --git a/private/ole32/stg/ofsstg/utest/filelist.mk b/private/ole32/stg/ofsstg/utest/filelist.mk
new file mode 100644
index 000000000..484f6bfbd
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest/filelist.mk
@@ -0,0 +1,23 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1993.
+# All rights reserved.
+#
+############################################################################
+
+
+NAME = ofstest
+
+TARGET = $(NAME).exe
+
+CXXFILES = .\$(NAME).cxx\
+ .\tutils.cxx
+
+PXXFILE = .\pch.cxx
+
+LIBS = $(CAIROLIB)
+
+CINC = $(CINC) -I..
+NO_WINMAIN = 1
+EXECOPY = v:\$(OBJDIR)
diff --git a/private/ole32/stg/ofsstg/utest/makefile b/private/ole32/stg/ofsstg/utest/makefile
new file mode 100644
index 000000000..a7052e4a5
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest/makefile
@@ -0,0 +1,12 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1993.
+# All rights reserved.
+#
+############################################################################
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
diff --git a/private/ole32/stg/ofsstg/utest/ofstest.cxx b/private/ole32/stg/ofsstg/utest/ofstest.cxx
new file mode 100644
index 000000000..0c968c10a
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest/ofstest.cxx
@@ -0,0 +1,594 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: ofstest.cxx
+//
+// History: 30-Jun-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+#include <assert.h>
+
+
+#define INITGUID
+#include "initguid.h"
+
+//
+// Bogus values, fill in the correct stuff.
+//
+DEFINE_GUID(IID_IPropertySetStorage, 0x66650000,0x0000,0x0008,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
+DEFINE_GUID(IID_IPropertyStorage, 0x66600014,0x0000,0x0008,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
+DEFINE_GUID(IID_IEnumSTATPROPSTG, 0x66600015,0x0000,0x0008,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
+DEFINE_GUID(IID_IEnumSTATPROPSETSTG, 0x66650001,0x0000,0x0008,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
+
+void EndTest(int rc)
+{
+ if (rc == 0)
+ printf("Test SUCCEEDED\n");
+ else
+ printf("Test FAILED\n");
+ CoUninitialize();
+ exit(rc);
+}
+
+void PrintStat(STATSTG *pstat, BOOL fEnum)
+{
+ printf("%s: '%ws'\n", pstat->type == STGTY_STORAGE ? "Storage" : "Stream",
+ pstat->pwcsName);
+ //printf("Type: %lu, %lu\n", pstat->type, pstat->dwStgFmt);
+ printf("Type: %lu, %lu\n", pstat->type);
+ if (!fEnum)
+ printf("Mode: %lX\n", pstat->grfMode);
+ if (pstat->type == STGTY_STREAM)
+ {
+ printf("Size: %lu:%lu\n", pstat->cbSize.HighPart,
+ pstat->cbSize.LowPart);
+ if (!fEnum)
+ printf("Locks: %lX\n", pstat->grfLocksSupported);
+ }
+ else
+ {
+ if (pstat->ctime.dwHighDateTime != 0 ||
+ pstat->ctime.dwLowDateTime != 0)
+ printf("Ctime: %s\n", FileTimeText(&pstat->ctime));
+ if (pstat->mtime.dwHighDateTime != 0 ||
+ pstat->mtime.dwLowDateTime != 0)
+ printf("Mtime: %s\n", FileTimeText(&pstat->mtime));
+ if (pstat->atime.dwHighDateTime != 0 ||
+ pstat->atime.dwLowDateTime != 0)
+ printf("Atime: %s\n", FileTimeText(&pstat->atime));
+ }
+ if (!fEnum)
+ printf("Clsid: %s\n", GuidText(&pstat->clsid));
+}
+
+void t_enum(IStorage *pstg)
+{
+ IEnumSTATSTG *penm, *penm2;
+ STATSTG stat;
+ HRESULT hr;
+
+ hr = pstg->EnumElements(0, 0, 0, &penm);
+ Result(hr, "Enum");
+
+ for (;;)
+ {
+ hr = penm->Next(1, &stat, NULL);
+ Result(hr, "Next");
+ if (GetScode(hr) == S_FALSE)
+ break;
+
+ PrintStat(&stat, TRUE);
+ CoMemFree(stat.pwcsName);
+ }
+
+ hr = penm->Skip(1);
+ Result(hr, "Skip");
+ hr = penm->Reset();
+ Result(hr, "Reset");
+ hr = penm->Clone(&penm2);
+ Result(hr, "Clone");
+
+ penm2->Release();
+ penm->Release();
+}
+
+void t_props(IStorage *pstg, int nTests=2)
+{
+ // sanity test for properties
+ FMTID fmtid;
+ HRESULT hr;
+ IPropertySetStorage *pPropSetStg;
+ IPropertyStorage *pPropSet;
+ STATSTG stat;
+
+ hr = pstg->Stat(&stat, 0);
+ Result(hr, "Stat");
+
+ hr = pstg->QueryInterface(IID_IPropertySetStorage, (void**)&pPropSetStg);
+ Result(hr, "QI prop");
+
+ for (int i=0; i<nTests; i++)
+ {
+ UuidCreate(&fmtid);
+
+ hr = pPropSetStg->Open(fmtid, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, &pPropSet);
+ if (hr != STG_E_FILENOTFOUND)
+ {
+ Fail("IPropertySetStorage::Open returned %lX\n", hr);
+ }
+
+ hr = pPropSetStg->Create(fmtid, NULL, i == 0 ? PROPSETFLAG_DEFAULT : PROPSETFLAG_NONSIMPLE,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &pPropSet);
+ Result(hr, "IPropertySetStorage::Create");
+ pPropSet->Release();
+
+ hr = pPropSetStg->Open(fmtid, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, &pPropSet);
+ Result(hr, "IPropertySetStorage::Open2");
+
+ PROPSPEC ps[4];
+ ps[0].ulKind = PRSPEC_PROPID;
+ ps[0].propid = 100;
+ ps[1].ulKind = PRSPEC_PROPID;
+ ps[1].propid = 101;
+ ps[2].ulKind = PRSPEC_LPWSTR;
+ ps[2].lpwstr = L"prop1";
+ ps[3].ulKind = PRSPEC_LPWSTR;
+ ps[3].lpwstr = L"prop2";
+
+ PROPVARIANT pv[4];
+ pv[0].vt = VT_I4;
+ pv[0].lVal = 1234;
+ pv[1].vt = VT_LPWSTR;
+ pv[1].pwszVal = L"wide string";
+
+ if (i == 0)
+ {
+ pv[2].vt = VT_UI2;
+ pv[2].uiVal = 2345;
+ pv[3].vt = VT_I4;
+ pv[3].lVal = 3456;
+ }
+ else
+ {
+ pv[2].vt = VT_STREAM;
+ pv[2].pStream = NULL;
+ pv[3].vt = VT_STORAGE;
+ pv[3].pStorage = NULL;
+ }
+
+ hr = pPropSet->WriteMultiple(4, ps, pv, 1000);
+ Result(hr, "WriteMultiple");
+
+ for (int j=0; j<2; j++)
+ {
+ memset(pv, 0, sizeof(pv));
+
+ hr = pPropSet->ReadMultiple(4, ps, pv);
+ Result(hr, "ReadMultiple");
+
+ assert(pv[0].vt == VT_I4);
+ assert(pv[1].vt == VT_LPWSTR);
+
+ if (i==0)
+ {
+ assert(pv[2].vt == VT_UI2);
+ assert(pv[3].vt == VT_I4);
+ }
+ else
+ {
+ assert(pv[2].vt == VT_STREAM);
+ assert(pv[3].vt == VT_STORAGE);
+ STATSTG stat;
+ hr = pv[2].pStream->Stat(&stat, STATFLAG_NONAME);
+ pv[2].pStream->Release();
+ Result(hr, "ReadMultiple Stream Stat");
+ hr = pv[3].pStorage->Stat(&stat, STATFLAG_NONAME);
+ Result(hr, "ReadMultiple Storage Stat");
+ pv[3].pStorage->Release();
+ }
+
+ pPropSet->Release();
+
+ hr = pPropSetStg->Open(fmtid, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, &pPropSet);
+ Result(hr, "Second IPropertySetStorage::Open");
+ }
+ pPropSet->Release();
+ }
+
+ pPropSetStg->Release();
+}
+
+void t_dirstg(IStorage *pstg)
+{
+ HRESULT hr;
+ IStream *pstm;
+ STATSTG stat;
+ IStorage *pstg2, *pstg3;
+ WCHAR wfn[MAX_PATH];
+ SYSTEMTIME stm;
+ FILETIME ftm;
+
+ t_props(pstg);
+
+ hr = pstg->Stat(&stat, 0);
+ Result(hr, "Stat");
+ PrintStat(&stat, FALSE);
+ CoMemFree(stat.pwcsName);
+
+ hr = pstg->CreateStream(L"Stream", STGM_READWRITE, 0, 0, &pstm);
+ Result(hr, "Create stream 'Stream'");
+ pstm->Release();
+ //if (hr != STG_E_INVALIDFUNCTION)
+ // Fail("CreateStream returned %lX\n", hr);
+ hr = pstg->OpenStream(L"Stream", 0, STGM_READWRITE, 0, &pstm);
+ Result(hr, "Open stream 'Stream'");
+ pstm->Release();
+
+ //if (hr != STG_E_FILENOTFOUND)
+ // Fail("OpenStream returned %lX\n", hr);
+
+ hr = pstg->CreateStorage(L"file!", STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_FILE, NULL, &pstg2);
+ Result(hr, "Create file 'file!'");
+ pstg2->Release();
+ hr = pstg->CreateStorage(L"docfile", STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_DOCUMENT, NULL, &pstg2);
+ t_props(pstg2);
+ Result(hr, "Create document");
+ pstg2->Release();
+ hr = pstg->CreateStorage(L"dir", STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_DIRECTORY, NULL, &pstg2);
+ Result(hr, "Create directory");
+ t_props(pstg2);
+ pstg2->Release();
+
+ hr = pstg->Commit(0);
+ Result(hr, "Commit");
+ hr = pstg->Revert();
+ Result(hr, "Revert");
+
+ t_enum(pstg);
+
+ hr = pstg->OpenStorage(L"file!", NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL,
+ NULL, &pstg2);
+ if (hr != STG_E_FILEALREADYEXISTS)
+ Fail("OpenStorage on file did not return STG_E_FILEALREADYEXISTS");
+
+ //Result(hr, "Open file 'file!'");
+ //pstg2->Release();
+ hr = pstg->OpenStorage(L"docfile", NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL,
+ NULL, &pstg2);
+ Result(hr, "Open docfile");
+ t_props(pstg2);
+ pstg2->Release();
+ hr = pstg->OpenStorage(L"dir", NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL,
+ NULL, &pstg2);
+ Result(hr, "Open directory");
+ t_props(pstg2);
+ hr = pstg2->CreateStorage(L"child", STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_DIRECTORY, NULL, &pstg3);
+ Result(hr, "Create child directory");
+ t_props(pstg3);
+ pstg3->Release();
+ pstg2->Release();
+
+ TestFile(wfn, "stg2");
+ hr = StgCreateStorage(wfn, STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_DIRECTORY, NULL, &pstg2);
+ Result(hr, "Create sibling dir");
+ t_props(pstg2);
+ hr = pstg->CopyTo(0, NULL, NULL, pstg2);
+ Result(hr, "CopyTo");
+ t_enum(pstg2);
+
+ hr = pstg2->DestroyElement(L"dir");
+ Result(hr, "Destroy dest dir -- contains child");
+ hr = pstg->MoveElementTo(L"dir", pstg2, L"dest", STGMOVE_MOVE);
+ Result(hr, "MoveElementTo");
+ t_enum(pstg2);
+ pstg2->Release();
+
+ hr = pstg->OpenStorage(L"dir", NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL,
+ NULL, &pstg2);
+ if (hr != STG_E_FILENOTFOUND)
+ Fail("Opened non-existent storage, %lX\n", hr);
+
+ hr = pstg->RenameElement(L"docfile", L"stg3");
+ Result(hr, "RenameElement");
+ hr = pstg->DestroyElement(L"stg3");
+ Result(hr, "DestroyElement");
+ t_enum(pstg);
+
+ Sleep(3);
+ GetLocalTime(&stm);
+ SystemTimeToFileTime(&stm, &ftm);
+ printf("Set time to %s\n", FileTimeText(&ftm));
+ hr = pstg->SetElementTimes(L"file!", NULL, NULL, &ftm);
+ Result(hr, "SetElementTimes");
+ t_enum(pstg);
+
+ hr = pstg->SetClass(IID_IStream);
+ Result(hr, "SetClass");
+ hr = pstg->Stat(&stat, STATFLAG_NONAME);
+ Result(hr, "Stat");
+ if (!IsEqualCLSID(stat.clsid, IID_IStream))
+ Fail("Dir SetClass/Stat didn't match, got %s\n",
+ GuidText(&stat.clsid));
+ hr = pstg->SetStateBits(0, 0);
+ if (hr != STG_E_INVALIDFUNCTION)
+ Fail("SetStateBits returned %lX\n", hr);
+}
+
+void t_filstg(IStorage *pstg)
+{
+ HRESULT hr;
+ STATSTG stat;
+ IStream *pstm;
+ IStorage *pstg2;
+ WCHAR wfn[MAX_PATH];
+
+ hr = pstg->Stat(&stat, 0);
+ Result(hr, "Stat");
+ PrintStat(&stat, FALSE);
+ CoMemFree(stat.pwcsName);
+
+ hr = pstg->CreateStream(L"Stream", STGM_READWRITE, 0, 0, &pstm);
+ if (hr != STG_E_INVALIDFUNCTION)
+ Fail("CreateStream succeeded for non-CONTENTS %lX\n", hr);
+ hr = pstg->OpenStream(L"Stream", 0, STGM_READWRITE, 0, &pstm);
+ if (hr != STG_E_FILENOTFOUND)
+ Fail("OpenStream succeeded for non-CONTENTS %lX\n", hr);
+
+ hr = pstg->CreateStorage(L"file", STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_FILE, NULL, &pstg2);
+ if (hr != STG_E_INVALIDFUNCTION)
+ Fail("CreateStorage succeeded %lX\n", hr);
+ hr = pstg->OpenStorage(L"file", NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL,
+ NULL, &pstg2);
+ if (hr != STG_E_FILENOTFOUND)
+ Fail("OpenStorage succeeded %lX\n", hr);
+
+ hr = pstg->Commit(0);
+ Result(hr, "Commit");
+ hr = pstg->Revert();
+ Result(hr, "Revert");
+
+ t_enum(pstg);
+
+ TestFile(wfn, "stg3");
+ hr = StgCreateStorage(wfn, STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_DOCUMENT, NULL, &pstg2);
+ Result(hr, "Open target docfile");
+ hr = pstg->CopyTo(0, NULL, NULL, pstg2);
+ Result(hr, "CopyTo");
+ t_enum(pstg2);
+
+ hr = pstg2->DestroyElement(L"CONTENTS");
+ Result(hr, "Destroy dest CONTENTS");
+ hr = pstg->MoveElementTo(L"CONTENTS", pstg2, L"dest", STGMOVE_COPY);
+ Result(hr, "MoveElementTo");
+ t_enum(pstg2);
+ pstg2->Release();
+
+ hr = pstg->RenameElement(L"stg2", L"stg3");
+ if (hr != STG_E_FILENOTFOUND)
+ Fail("RenameElement returned %lX\n", hr);
+ hr = pstg->DestroyElement(L"stg3");
+ if (hr != STG_E_FILENOTFOUND)
+ Fail("DestroyElement returned %lX\n", hr);
+ hr = pstg->SetElementTimes(L"file", NULL, NULL, NULL);
+ if (hr != STG_E_FILENOTFOUND)
+ Fail("SetElementTimes returned %lX\n", hr);
+ hr = pstg->SetClass(IID_IStorage);
+ Result(hr, "SetClass");
+ hr = pstg->Stat(&stat, STATFLAG_NONAME);
+ Result(hr, "Stat");
+ if (!IsEqualCLSID(stat.clsid, IID_IStorage))
+ Fail("File SetClass/Stat didn't match, got %s\n",
+ GuidText(&stat.clsid));
+ hr = pstg->SetStateBits(0, 0);
+ if (hr != STG_E_INVALIDFUNCTION)
+ Fail("SetStateBits returned %lX\n", hr);
+}
+
+static char NUMBERS[] = "12345678901234567890123456789012345678901234567890";
+
+void t_stream(IStream *pstm)
+{
+ IStream *pstmC;
+ char buf[sizeof(NUMBERS)*2];
+ ULONG cb;
+ HRESULT hr;
+ ULARGE_INTEGER ulPos, uli;
+ LARGE_INTEGER li;
+ STATSTG stat;
+
+ hr = pstm->Stat(&stat, 0);
+ Result(hr, "Stat");
+ PrintStat(&stat, FALSE);
+ CoMemFree(stat.pwcsName);
+
+ uli.HighPart = 0;
+ uli.LowPart = 0;
+ hr = pstm->SetSize(uli);
+ Result(hr, "SetSize");
+
+ hr = pstm->Write(NUMBERS, sizeof(NUMBERS), &cb);
+ Result(hr, "Write");
+ hr = pstm->Commit(0);
+ Result(hr, "Commit");
+ hr = pstm->Revert();
+ Result(hr, "Revert");
+
+ li.HighPart = -1;
+ li.LowPart = (ULONG)(-((LONG)sizeof(NUMBERS)/2));
+ hr = pstm->Seek(li, STREAM_SEEK_END, &ulPos);
+ Result(hr, "Seek");
+ if (ulPos.HighPart != 0 ||
+ ulPos.LowPart != sizeof(NUMBERS)-sizeof(NUMBERS)/2)
+ Fail("Incorrect seek, %lu:%lu\n", ulPos.HighPart, ulPos.LowPart);
+
+ li.HighPart = 0;
+ li.LowPart = sizeof(NUMBERS)/2;
+ hr = pstm->Seek(li, STREAM_SEEK_CUR, &ulPos);
+ Result(hr, "Seek");
+ if (ulPos.HighPart != 0 ||
+ ulPos.LowPart != sizeof(NUMBERS))
+ Fail("Incorrect seek, %lu:%lu\n", ulPos.HighPart, ulPos.LowPart);
+
+ li.HighPart = li.LowPart = 0;
+ hr = pstm->Seek(li, STREAM_SEEK_SET, &ulPos);
+ Result(hr, "Seek");
+ if (ulPos.LowPart != 0 || ulPos.HighPart != 0)
+ Fail("Incorrect seek, %lu:%lu\n", ulPos.HighPart, ulPos.LowPart);
+
+ hr = pstm->Read(buf, sizeof(NUMBERS), &cb);
+ Result(hr, "Read");
+ if (strcmp(buf, NUMBERS))
+ Fail("Incorrect stream contents\n");
+
+ uli.HighPart = 0;
+ uli.LowPart = sizeof(NUMBERS)/2;
+ hr = pstm->SetSize(uli);
+ Result(hr, "SetSize");
+ hr = pstm->Seek(li, STREAM_SEEK_SET, NULL);
+ Result(hr, "Seek");
+ hr = pstm->Read(buf, sizeof(NUMBERS), &cb);
+ Result(hr, "Read");
+ if (cb != sizeof(NUMBERS)/2)
+ Fail("SetSize failed to size stream properly\n");
+ if (memcmp(buf, NUMBERS, sizeof(NUMBERS)/2))
+ Fail("SetSize corrupted contents\n");
+
+ hr = pstm->Clone(&pstmC);
+ Result(hr, "Clone");
+ hr = pstm->Seek(li, STREAM_SEEK_SET, NULL);
+ Result(hr, "Seek");
+ hr = pstm->CopyTo(pstmC, uli, NULL, NULL);
+ Result(hr, "CopyTo");
+ hr = pstm->Seek(li, STREAM_SEEK_SET, NULL);
+ Result(hr, "Seek");
+ uli.LowPart = sizeof(NUMBERS) & ~1;
+ hr = pstm->CopyTo(pstmC, uli, NULL, NULL);
+ Result(hr, "CopyTo");
+ hr = pstm->Seek(li, STREAM_SEEK_SET, NULL);
+ Result(hr, "Seek");
+ hr = pstm->Read(buf, (sizeof(NUMBERS)&~1)*2, &cb);
+ Result(hr, "Read");
+ if (memcmp(buf, NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+sizeof(NUMBERS)/2, NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+(sizeof(NUMBERS)&~1), NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+3*(sizeof(NUMBERS)/2), NUMBERS, sizeof(NUMBERS)/2))
+ Fail("Stream contents incorrect\n");
+ pstmC->Release();
+
+ ulPos.HighPart = 0xffffffff;
+ ulPos.LowPart = 0x10000;
+ uli.HighPart = 0;
+ uli.LowPart = 0x100;
+ hr = pstm->LockRegion(ulPos, uli, LOCK_ONLYONCE);
+ Result(hr, "LockRegion");
+ ulPos.LowPart = 0x10080;
+ hr = pstm->LockRegion(ulPos, uli, LOCK_ONLYONCE);
+ if (hr != STG_E_LOCKVIOLATION)
+ Fail("Illegal LockRegion returned 0x%lX\n", hr);
+ ulPos.LowPart = 0x10000;
+ hr = pstm->UnlockRegion(ulPos, uli, LOCK_ONLYONCE);
+ Result(hr, "UnlockRegion");
+}
+
+DWORD fmts[] = {STGFMT_DOCUMENT, STGFMT_FILE};
+char *fmt_names[] = {"hdoc", "hfile"};
+#define NFMTS (sizeof(fmts)/sizeof(fmts[0]))
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ IStorage *pstg, *pstgFile;
+ IStream *pstm;
+ HRESULT hr;
+ WCHAR wfn[MAX_PATH];
+
+ hr = CoInitialize(NULL);
+ Result(hr, "CoInitialize");
+
+ TestFile(wfn, "sumcat");
+ hr = StgCreateStorage(wfn, STGM_SHARE_DENY_NONE, STGFMT_CATALOG, NULL, &pstg);
+ Result(hr, "Open catalog");
+ t_props(pstg);
+ pstg->Release();
+
+ TestFile(wfn, "stg");
+ hr = StgCreateStorage(wfn, STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ STGFMT_DIRECTORY, NULL, &pstg);
+ Result(hr, "Open root directory");
+
+ t_dirstg(pstg);
+
+ hr = pstg->CreateStorage(L"file", STGM_READWRITE | STGM_SHARE_EXCLUSIVE |
+ STGM_CREATE, STGFMT_FILE, NULL, &pstgFile);
+ Result(hr, "Create file");
+
+ t_filstg(pstgFile);
+
+ hr = pstgFile->OpenStream(L"CONTENTS", NULL, STGM_READWRITE,
+ NULL, &pstm);
+ Result(hr, "Open stream");
+
+ t_stream(pstm);
+
+ pstm->Release();
+ pstgFile->Release();
+ pstg->Release();
+
+ hr = StgOpenStorage(wfn, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ NULL, NULL, &pstg);
+ Result(hr, "Open root directory");
+ pstg->Release();
+
+ HANDLE h;
+ DWORD dwStgFmt, grfMode;
+ int i;
+ STATSTG stat;
+
+ grfMode = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
+ for (i = 0; i < NFMTS; i++)
+ {
+ dwStgFmt = fmts[i];
+ TestFile(wfn, fmt_names[i]);
+ h = CreateFile(wfn, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ Fail("Unable to create file\n");
+ hr = StgCreateStorageOnHandle(h, grfMode, dwStgFmt, &pstg);
+ Result(hr, "StgCreateStorageOnHandle fmt %lu", dwStgFmt);
+ pstg->Release();
+ CloseHandle(h);
+
+ h = CreateFile(wfn, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ Fail("Unable to open file\n");
+ hr = StgOpenStorageOnHandle(h, grfMode, &pstg);
+ Result(hr, "StgOpenStorageOnHandle fmt %lu", dwStgFmt);
+ pstg->Stat(&stat, STATFLAG_NONAME);
+ //if (stat.dwStgFmt != dwStgFmt)
+ // Fail("Stat returned fmt %lu rather than %lu\n", stat.dwStgFmt,
+ // dwStgFmt);
+ pstg->Release();
+ CloseHandle(h);
+ }
+
+ EndTest(0);
+}
diff --git a/private/ole32/stg/ofsstg/utest/pch.cxx b/private/ole32/stg/ofsstg/utest/pch.cxx
new file mode 100644
index 000000000..c3439524c
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest/pch.cxx
@@ -0,0 +1,24 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: pch.cxx
+//
+// History: 09-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include <windows.h>
+#ifdef _CAIRO_
+#define _CAIROSTG_
+#include <oleext.h>
+#endif
+#include <stgint.h>
+#include "tutils.hxx"
+
diff --git a/private/ole32/stg/ofsstg/utest/tutils.cxx b/private/ole32/stg/ofsstg/utest/tutils.cxx
new file mode 100644
index 000000000..1482dd08a
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest/tutils.cxx
@@ -0,0 +1,356 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tutils.cxx
+//
+// Contents: Generic utilities for tests
+//
+// History: 06-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+static BOOL fExitOnFail = TRUE;
+
+BOOL GetExitOnFail(void)
+{
+ return fExitOnFail;
+}
+
+void SetExitOnFail(BOOL set)
+{
+ fExitOnFail = set;
+}
+
+// Print out an error message and terminate
+void Fail(char *fmt, ...)
+{
+ va_list args;
+
+ args = va_start(args, fmt);
+ fprintf(stderr, "** Fatal error **: ");
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ EndTest(1);
+}
+
+typedef struct
+{
+ SCODE sc;
+ char *text;
+} StatusCodeText;
+
+static StatusCodeText scodes[] =
+{
+ S_OK, "S_OK",
+ S_FALSE, "S_FALSE",
+ STG_E_INVALIDFUNCTION, "STG_E_INVALIDFUNCTION",
+ STG_E_FILENOTFOUND, "STG_E_FILENOTFOUND",
+ STG_E_PATHNOTFOUND, "STG_E_PATHNOTFOUND",
+ STG_E_TOOMANYOPENFILES, "STG_E_TOOMANYOPENFILES",
+ STG_E_ACCESSDENIED, "STG_E_ACCESSDENIED",
+ STG_E_INVALIDHANDLE, "STG_E_INVALIDHANDLE",
+ STG_E_INSUFFICIENTMEMORY, "STG_E_INSUFFICIENTMEMORY",
+ STG_E_INVALIDPOINTER, "STG_E_INVALIDPOINTER",
+ STG_E_NOMOREFILES, "STG_E_NOMOREFILES",
+ STG_E_DISKISWRITEPROTECTED, "STG_E_DISKISWRITEPROTECTED",
+ STG_E_SEEKERROR, "STG_E_SEEKERROR",
+ STG_E_WRITEFAULT, "STG_E_WRITEFAULT",
+ STG_E_READFAULT, "STG_E_READFAULT",
+ STG_E_SHAREVIOLATION, "STG_E_SHAREVIOLATION",
+ STG_E_LOCKVIOLATION, "STG_E_LOCKVIOLATION",
+ STG_E_FILEALREADYEXISTS, "STG_E_FILEALREADYEXISTS",
+ STG_E_INVALIDPARAMETER, "STG_E_INVALIDPARAMETER",
+ STG_E_MEDIUMFULL, "STG_E_MEDIUMFULL",
+ STG_E_ABNORMALAPIEXIT, "STG_E_ABNORMALAPIEXIT",
+ STG_E_INVALIDHEADER, "STG_E_INVALIDHEADER",
+ STG_E_INVALIDNAME, "STG_E_INVALIDNAME",
+ STG_E_UNKNOWN, "STG_E_UNKNOWN",
+ STG_E_UNIMPLEMENTEDFUNCTION, "STG_E_UNIMPLEMENTEDFUNCTION",
+ STG_E_INVALIDFLAG, "STG_E_INVALIDFLAG",
+ STG_E_INUSE, "STG_E_INUSE",
+ STG_E_NOTCURRENT, "STG_E_NOTCURRENT",
+ STG_E_REVERTED, "STG_E_REVERTED",
+ STG_E_CANTSAVE, "STG_E_CANTSAVE",
+ STG_E_OLDFORMAT, "STG_E_OLDFORMAT",
+ STG_E_OLDDLL, "STG_E_OLDDLL",
+ STG_E_SHAREREQUIRED, "STG_E_SHAREREQUIRED",
+ STG_E_NOTFILEBASEDSTORAGE, "STG_E_NOTFILEBASEDSTORAGE",
+ STG_E_EXTANTMARSHALLINGS, "STG_E_EXTANTMARSHALLINGS",
+ STG_S_CONVERTED, "STG_S_CONVERTED"
+};
+#define NSCODETEXT (sizeof(scodes)/sizeof(scodes[0]))
+
+// Convert a status code to text
+char *ScText(SCODE sc)
+{
+ int i;
+
+ for (i = 0; i<NSCODETEXT; i++)
+ if (scodes[i].sc == sc)
+ return scodes[i].text;
+ return "<Unknown SCODE>";
+}
+
+// Output a call result and check for failure
+HRESULT Result(HRESULT hr, char *fmt, ...)
+{
+ SCODE sc;
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ sc = GetScode(hr);
+ printf(" - %s (0x%lX)\n", ScText(sc), sc);
+ if (FAILED(sc) && fExitOnFail)
+ Fail("Unexpected call failure\n");
+ return hr;
+}
+
+// Perform Result() when the expectation is failure
+HRESULT IllResult(HRESULT hr, char *fmt, ...)
+{
+ SCODE sc;
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ sc = GetScode(hr);
+ printf(" - %s (0x%lX)\n", ScText(sc), sc);
+ if (SUCCEEDED(sc) && fExitOnFail)
+ Fail("Unexpected call success\n");
+ return hr;
+}
+
+char *TcsText(TCHAR *ptcs)
+{
+ static char buf[256];
+
+ TTOA(ptcs, buf, 256);
+ return buf;
+}
+
+char *FileTimeText(FILETIME *pft)
+{
+ static char buf[80];
+ struct tm ctm;
+#ifndef FLAT
+ WORD dosdate, dostime;
+
+ if (CoFileTimeToDosDateTime(pft, &dosdate, &dostime))
+ {
+ ctm.tm_sec = (dostime & 31)*2;
+ ctm.tm_min = (dostime >> 5) & 63;
+ ctm.tm_hour = dostime >> 11;
+ ctm.tm_mday = dosdate & 31;
+ ctm.tm_mon = ((dosdate >> 5) & 15)-1;
+ ctm.tm_year = (dosdate >> 9)+80;
+ ctm.tm_wday = 0;
+#else
+ SYSTEMTIME st;
+
+ if (FileTimeToSystemTime(pft, &st))
+ {
+ ctm.tm_sec = st.wSecond;
+ ctm.tm_min = st.wMinute;
+ ctm.tm_hour = st.wHour;
+ ctm.tm_mday = st.wDay;
+ ctm.tm_mon = st.wMonth-1;
+ ctm.tm_year = st.wYear-1900;
+ ctm.tm_wday = st.wDayOfWeek;
+#endif
+ ctm.tm_yday = 0;
+ ctm.tm_isdst = 0;
+ strcpy(buf, asctime(&ctm));
+ buf[strlen(buf)-1] = 0;
+ }
+ else
+ sprintf(buf, "<FILETIME %08lX:%08lX>", pft->dwHighDateTime,
+ pft->dwLowDateTime);
+ return buf;
+}
+
+#pragma pack(1)
+struct SplitGuid
+{
+ DWORD dw1;
+ WORD w1;
+ WORD w2;
+ BYTE b[8];
+};
+#pragma pack()
+
+char *GuidText(GUID *pguid)
+{
+ static char buf[39];
+ SplitGuid *psg = (SplitGuid *)pguid;
+
+ sprintf(buf, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
+ psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
+ return buf;
+}
+
+#define CROW 16
+
+void BinText(ULONG cbSize, BYTE *pb)
+{
+ ULONG cb, i;
+
+ while (cbSize > 0)
+ {
+ cb = min(CROW, cbSize);
+ cbSize -= cb;
+ for (i = 0; i<cb; i++)
+ printf(" %02X", pb[i]);
+ for (i = cb; i<CROW; i++)
+ printf(" ");
+ printf(" '");
+ for (i = 0; i<cb; i++)
+ if (pb[i] >= 0x20 && pb[i] <= 0x7f)
+ putchar(pb[i]);
+ else
+ putchar('.');
+ pb += cb;
+ printf("'\n");
+ }
+}
+
+// BUGBUG - Remove for Cairole when they exist
+STDAPI CoMemAlloc(DWORD cbSize, void **ppv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc;
+
+ if (SUCCEEDED(GetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ *ppv = pMalloc->Alloc(cbSize);
+ pMalloc->Release();
+
+ if (*ppv == NULL)
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ }
+ else
+ *ppv = NULL;
+
+ return hr;
+}
+
+STDAPI CoMemFree(void *pv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc;
+
+ if (SUCCEEDED(GetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ pMalloc->Free(pv);
+ pMalloc->Release();
+ }
+
+ return hr;
+}
+
+TCHAR *TestFile(TCHAR *ptcsName, char *pszFile)
+{
+ char achFn[MAX_PATH];
+ char *dir, *file;
+ int len;
+
+ dir = getenv("DFDATA");
+ if (dir)
+ strcpy(achFn, dir);
+ else
+ strcpy(achFn, ".");
+ len = strlen(achFn);
+ if (achFn[len-1] != '\\')
+ achFn[len++] = '\\';
+
+ if (pszFile)
+ {
+ strcpy(achFn+len, pszFile);
+ }
+ else
+ {
+ file = getenv("DFFILE");
+ if (file)
+ strcpy(achFn+len, file);
+ else
+ strcpy(achFn+len, "TEST.DFL");
+ }
+
+ ATOT(achFn, ptcsName, MAX_PATH);
+ return ptcsName+len;
+}
+
+#if WIN32 == 300
+char *TestFormat(DWORD *pdwFmt, DWORD *pgrfMode)
+{
+ char *fmt;
+
+ fmt = getenv("STGFMT");
+ if (fmt == NULL || !strcmp(fmt, "doc"))
+ {
+ fmt = "document";
+ *pdwFmt = STGFMT_DOCUMENT;
+ }
+ else if (!strcmp(fmt, "file"))
+ {
+ fmt = "file";
+ *pdwFmt = STGFMT_FILE;
+ }
+ else
+ {
+ fmt = "directory";
+ *pdwFmt = STGFMT_DIRECTORY;
+ *pgrfMode &= ~STGM_CREATE;
+ }
+ return fmt;
+}
+#endif
+
+void CreateTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName)
+{
+ HRESULT hr;
+ TCHAR atcFile[MAX_PATH];
+ char *fmt;
+
+ if (ptcsName == NULL)
+ ptcsName = atcFile;
+ TestFile(ptcsName, pszFile);
+#if WIN32 == 300
+ DWORD dwStgFmt;
+
+ fmt = TestFormat(&dwStgFmt, &grfMode);
+ hr = StgCreateStorage(ptcsName, grfMode, dwStgFmt, 0, ppstg);
+#else
+ hr = StgCreateDocfile(ptcsName, grfMode, 0, ppstg);
+ fmt = "docfile";
+#endif
+ if (fFail)
+ IllResult(hr, "Create %s %s", fmt, TcsText(ptcsName));
+ else
+ Result(hr, "Create %s %s", fmt, TcsText(ptcsName));
+}
+
+void OpenTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName)
+{
+ HRESULT hr;
+ TCHAR atcFile[MAX_PATH];
+
+ if (ptcsName == NULL)
+ ptcsName = atcFile;
+ TestFile(ptcsName, pszFile);
+ hr = StgOpenStorage(ptcsName, NULL, grfMode, NULL, 0, ppstg);
+ if (fFail)
+ IllResult(hr, "Open storage %s", TcsText(ptcsName));
+ else
+ Result(hr, "Open storage %s", TcsText(ptcsName));
+}
diff --git a/private/ole32/stg/ofsstg/utest/tutils.hxx b/private/ole32/stg/ofsstg/utest/tutils.hxx
new file mode 100644
index 000000000..b006da5f0
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest/tutils.hxx
@@ -0,0 +1,84 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tutils.hxx
+//
+// Contents: Generic test utilities
+//
+// History: 06-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __TUTILS_HXX__
+#define __TUTILS_HXX__
+
+#ifndef UNICODE
+#define tcscpy(d, s) strcpy(d, s)
+#define tcslen(s) strlen(s)
+#define TTEXT(s) s
+#define TFMT "%s"
+#define ATOT(a, t, max) strcpy(t, a)
+#define TTOA(t, a, max) strcpy(a, t)
+#define WTOT(w, t, max) wcstombs(t, w, max)
+#define TTOW(t, w, max) mbstowcs(w, t, max)
+#else
+#define tcscpy(d, s) wcscpy(d, s)
+#define tcslen(s) wcslen(s)
+#define TTEXT(s) L##s
+#define TFMT "%ws"
+#define ATOT(a, t, max) mbstowcs(t, a, max)
+#define TTOA(t, a, max) wcstombs(a, t, max)
+#define WTOT(w, t, max) wcscpy(t, w)
+#define TTOW(t, w, max) wcscpy(w, t)
+#endif
+#ifdef WIN32
+#define ATOX(a, t, max) mbstowcs(t, a, max)
+#define XTOA(t, a, max) wcstombs(a, t, max)
+#define WTOX(w, t, max) wcscpy(t, w)
+#define XTOW(t, w, max) wcscpy(w, t)
+#else
+#define ATOX(a, t, max) strcpy(t, a)
+#define XTOA(t, a, max) strcpy(a, t)
+#define WTOX(w, t, max) wcstombs(t, w, max)
+#define XTOW(t, w, max) mbstowcs(w, t, max)
+#endif
+
+#ifdef CINTERFACE
+#define Mthd(this, name) ((this)->lpVtbl->name)
+#define SELF(p) (p),
+#else
+#define Mthd(this, name) (this)->name
+#define SELF(p)
+#endif
+
+// BUGBUG - Remove for Cairole when they exist
+STDAPI CoMemAlloc(DWORD cBytes, void **ppv);
+STDAPI CoMemFree(void *pv);
+
+BOOL GetExitOnFail(void);
+void SetExitOnFail(BOOL set);
+void Fail(char *fmt, ...);
+char *ScText(SCODE sc);
+HRESULT Result(HRESULT hr, char *fmt, ...);
+HRESULT IllResult(HRESULT hr, char *fmt, ...);
+char *TcsText(TCHAR *ptcs);
+char *FileTimeText(FILETIME *pft);
+char *GuidText(GUID *pguid);
+void BinText(ULONG cb, BYTE *pb);
+TCHAR *TestFile(TCHAR *ptcsName, char *pszFile);
+
+#if WIN32 == 300
+char *TestFormat(DWORD *pdwFmt, DWORD *pgrfMode);
+#endif
+
+void CreateTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName);
+void OpenTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName);
+
+// Defined by test, called by Fail
+void EndTest(int code);
+
+#endif // #ifndef __TUTILS_HXX__
diff --git a/private/ole32/stg/ofsstg/utest2/dirs b/private/ole32/stg/ofsstg/utest2/dirs
new file mode 100644
index 000000000..fd5ee649a
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest2/dirs
@@ -0,0 +1,35 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS=
diff --git a/private/ole32/stg/ofsstg/utest2/ofstest.cxx b/private/ole32/stg/ofsstg/utest2/ofstest.cxx
new file mode 100644
index 000000000..792647dc1
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest2/ofstest.cxx
@@ -0,0 +1,350 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: ofstest.cxx
+//
+// Contents: OFS IStorage/IStream unit test
+//
+// History: 14-Feb-94 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+#include <pch.cxx>
+#pragma hdrstop
+
+BYTE inbuf[4096];
+#define STREAMNAME L"MyStream"
+#define STGNAME L"EmbeddedStorage"
+#define STGNAME2 L"RenamedStorage"
+#define ROOTNAME "e:\\RootStorage"
+
+WCHAR pwcsRootName[1024];
+
+
+void PrintStatInfo(STATSTG *pstat)
+{
+ printstat(pstat, TRUE);
+}
+
+
+#define FailMsg(MSG) {printf MSG; exit(1);}
+
+#define DoCmd(MSG, CODE, FAILMSG) \
+printf(MSG " => %s (0x%lX)\n", (sc = DfGetScode(CODE), ScText(sc)), sc); \
+if (FAILED(sc)) {printf(FAILMSG "\n"); goto Cleanup;}
+
+#define SHIFT(c,v) ( (c)--, (v)++)
+
+void _CRTAPI1 main(int argc, char *argv[])
+{
+ IStorage *pdf = NULL;
+ IStorage *pdf2 = NULL;
+ IStream *pst = NULL;
+ IEnumSTATSTG *penm = NULL;
+
+ SCODE sc;
+
+ CHAR *pszName = ROOTNAME;
+ const CHAR *test = "This is a test string";
+
+
+ StartTest("OFStest");
+
+ SHIFT (argc, argv);
+
+ // process arguments
+
+ BOOL fOpen = FALSE;
+ while (argc != 0 && argv[0][0] == '-')
+ {
+ switch (argv[0][1])
+ {
+ case 'o':
+ fOpen = TRUE;
+ break;
+
+ default:
+ fprintf (stderr, "Usage: OFSTEST [-o] [filename]\n");
+ exit (1);
+ }
+
+ SHIFT (argc, argv);
+ }
+
+
+ if (argc != 0)
+ {
+ pszName = argv[0];
+ SHIFT (argc, argv);
+ }
+
+ mbstowcs(pwcsRootName, pszName, 1024);
+
+ if (fOpen)
+ {
+ // reopen root to make sure it still works
+ DoCmd("Open root", StgOpenStorage (pwcsRootName,
+ NULL,
+ STGM_DIRECT| STGM_RW | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ NULL,
+ &pdf), "Unable to open root");
+ }
+ else
+ DoCmd("Create root", StgCreateStorage(pwcsRootName,
+ STGM_DIRECT| STGM_RW |
+ STGM_SHARE_EXCLUSIVE,
+ STGFMT_DOCUMENT,
+ NULL,
+ &pdf), "Unable to create root");
+
+ DoCmd("Create stream",pdf->CreateStream(STREAMNAME,
+ STGM_RW |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_CREATE,
+ 0,
+ 0,
+ &pst),"Unable to create stream");
+
+ ULONG ulBytes;
+
+ strcpy((char *)inbuf, test);
+
+ DoCmd("Write to stream", pst->Write(inbuf, strlen(test), &ulBytes),
+ "Unable to write");
+
+ if (ulBytes != strlen(test))
+ FailMsg(("Wrote %lu bytes, expected %lu\n", ulBytes, strlen(test)));
+
+ memset(inbuf, 0, strlen(test));
+
+ LARGE_INTEGER li;
+ LISet32(li, 0);
+
+ DoCmd("Seek", pst->Seek(li, STREAM_SEEK_SET, NULL),"Seek failed.");
+
+ DoCmd("Read", pst->Read(inbuf, strlen(test), &ulBytes), "Read failed.");
+
+ if (ulBytes != strlen(test))
+ FailMsg(("Read %lu, expected %lu\n", ulBytes, strlen(test)));
+
+ printf("String read was %s\n",inbuf);
+ if (strcmp((char *)inbuf, test))
+ FailMsg(("Strings are not identical\n"));
+
+ printf("Release stream = %lu\n",
+ pst->Release());
+ pst = NULL;
+
+ DoCmd("Open stream", pdf->OpenStream(STREAMNAME,
+ NULL,
+ STGM_RW |
+ STGM_SHARE_EXCLUSIVE,
+ 0,
+ &pst),
+ "Could not open stream.");
+
+ memset(inbuf, 0, strlen(test));
+
+ LISet32(li, 0);
+
+ DoCmd("Seek", pst->Seek(li, STREAM_SEEK_SET, NULL), "Seek failed.");
+
+ DoCmd("Read", pst->Read(inbuf, strlen(test), &ulBytes),
+ "Read failed.");
+
+ if (ulBytes != strlen(test))
+ FailMsg(("Read %lu, expected %lu\n", ulBytes, strlen(test)));
+
+ printf("String read was %s\n",inbuf);
+ if (strcmp((char *)inbuf, test))
+ FailMsg(("Strings are not identical\n"));
+
+ printf("Release stream = %lu\n",
+ pst->Release());
+ pst = NULL;
+
+ //Try to delete the stream
+
+// DoCmd("Delete stream", pdf->DestroyElement(STREAMNAME),
+// "Could not delete stream");
+
+ DoCmd("Open storage", pdf->CreateStorage(STGNAME,
+ STGM_RW |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_FAILIFTHERE,
+ STGFMT_DOCUMENT,
+ NULL,
+ &pdf2),
+ "Unable to create internal storage");
+
+ DoCmd("SetClass", pdf2->SetClass(IID_IUnknown), "SetClass failed.");
+
+ STATSTG stat;
+
+ DoCmd("Embedding Stat()", pdf2->Stat(&stat, STATFLAG_DEFAULT),
+ "Stat failed.");
+ PrintStatInfo(&stat);
+
+ printf("Release internal storage = %lu\n", pdf2->Release());
+ pdf2 = NULL;
+
+ //Stat IStorage
+
+ DoCmd("Root storage Stat()", pdf->Stat(&stat, STATFLAG_DEFAULT),
+ "Stat failed.");
+ PrintStatInfo(&stat);
+
+ //Enumerate contents of root.
+
+ DoCmd("EnumElements()", pdf->EnumElements(0, NULL, 0, &penm),
+ "EnumElements failed.");
+
+ do
+ {
+ ULONG ulTemp;
+
+ DoCmd("Next()", penm->Next(1, &stat, &ulTemp),
+ "Next failed.");
+
+ if (SUCCEEDED(sc) && (sc != S_FALSE))
+ {
+ PrintStatInfo(&stat);
+ }
+ } while (sc == S_OK);
+ printf("\n\n");
+
+ //Rename the embedded storage
+ DoCmd("Rename storage", pdf->RenameElement(STGNAME, STGNAME2),
+ "Rename failed.");
+
+ //Rewind iterator
+ DoCmd("Reset",penm->Reset(),"Reset failed.");
+ do
+ {
+ ULONG ulTemp;
+
+ DoCmd("Next()", penm->Next(1, &stat, &ulTemp),
+ "Next failed.");
+
+ if (SUCCEEDED(sc) && (sc != S_FALSE))
+ {
+ PrintStatInfo(&stat);
+ }
+ } while (sc == S_OK);
+ printf("\n\n");
+
+ //Delete the embedded storage
+ DoCmd("Delete storage", pdf->DestroyElement(STGNAME2),
+ "Could not delete storage.");
+
+ //Rewind iterator
+ DoCmd("Reset",penm->Reset(),"Reset failed.");
+ do
+ {
+ ULONG ulTemp;
+
+ DoCmd("Next()", penm->Next(1, &stat, &ulTemp),
+ "Next failed.");
+ if (SUCCEEDED(sc) && (sc != S_FALSE))
+ {
+ PrintStatInfo(&stat);
+ }
+ } while (sc == S_OK);
+ printf("\n\n");
+
+ printf("Release enumerator = %lu\n",
+ penm->Release());
+ penm = NULL;
+
+ // Get property set storage
+ IPropertySetStorage *pipss;
+ DoCmd ("QueryInterface", pdf->QueryInterface (IID_IPropertySetStorage, (void **) &pipss), "QueryInterface Failed");
+
+ // Create a new property set
+ IPropertyStorage *pips;
+ DoCmd ("Create PropertyStorage", pipss->Create (IID_IUnknown, 0, &pips), "Create PropertyStorage Failed");
+
+ // write some properties
+ PROPVARIANT v[3];
+ PROPSPEC p[3];
+ v[0].vt = VT_I2;
+ v[0].iVal = 0x4D5A;
+ p[0].ulKind = PRSPEC_LPWSTR;
+ p[0].lpwstr = L"Zark Mbikowski";
+
+ v[1].vt = VT_BOOL;
+ v[1].bool = TRUE; // truth is where you find it
+ p[1].ulKind = PRSPEC_DISPID;
+ p[1].dispid = 1; // Isn't this true?
+
+ v[2].vt = VT_LPSTR;
+ v[2].pszVal = "TestTestOddAlignment!";
+ p[2].ulKind = PRSPEC_DISPID;
+ p[2].dispid = 0x1234;
+
+ DoCmd ("WriteMultiple", pips->WriteMultiple (3, p, NULL, v), "WriteMultiple Failed.");
+
+ // read some properties
+ PROPSPEC p1[4];
+ PROPVARIANT v1[4];
+ int i;
+ for (i = 0; i < 3; i++)
+ p1[i] = p[2-i];
+ p1[3].ulKind = PRSPEC_DISPID;
+ p1[3].dispid = 0x666;
+
+ DoCmd ("ReadMultiple", pips->ReadMultiple (4, p1, NULL, NULL, v1), "ReadMultiple Failed.");
+ for (i = 0; i < 4; i++)
+ switch (v1[i].vt)
+ {
+ case VT_I2: printf ("VT_I2 %x\n", v1[i].iVal); break;
+ case VT_BOOL: printf ("VT_BOOL %d\n", v1[i].bool); break;
+ case VT_LPSTR: printf ("VT_LPSTR %s\n", v1[i].pszVal); break;
+ default:
+ printf ("vt = %x\n", v1[i].vt);
+ }
+
+
+ // release property set
+ printf ("Release property storage = %lx\n", pips->Release ());
+
+ // release property set storage
+ printf ("Release property set storage = %lx\n", pipss->Release ());
+
+
+ printf("Release root = %lu\n",
+ pdf->Release());
+
+ pdf = NULL;
+
+ EndTest(0);
+ exit(0);
+
+ Cleanup:
+ printf("\n\nCleaning up...\n");
+ if (pst != NULL)
+ {
+ printf("Release stream = %lu\n",
+ pst->Release());
+ }
+
+ if (pdf2 != NULL)
+ {
+ printf("Release internal storage = %lu\n", pdf2->Release());
+ }
+
+ if (penm != NULL)
+ {
+ printf("Release enumerator = %lu\n",
+ penm->Release());
+ }
+
+ if (pdf != NULL)
+ {
+ printf("Release root = %lu\n",
+ pdf->Release());
+ }
+}
diff --git a/private/ole32/stg/ofsstg/utest2/pch.cxx b/private/ole32/stg/ofsstg/utest2/pch.cxx
new file mode 100644
index 000000000..f854d9294
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest2/pch.cxx
@@ -0,0 +1,24 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: pch.cxx
+//
+// Contents: Precompiled header file
+//
+// History: 03-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+
+#include <ole2.h>
+#define _CAIROSTG_ 1
+#define _DCOM_
+#include <oleext.h>
+#include "tsupp.hxx"
diff --git a/private/ole32/stg/ofsstg/utest2/tsupp.cxx b/private/ole32/stg/ofsstg/utest2/tsupp.cxx
new file mode 100644
index 000000000..0421888af
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest2/tsupp.cxx
@@ -0,0 +1,253 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tsupp.cxx
+//
+// Contents: Test support routines
+//
+// History: 03-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+DWORD dwTransacted = STGM_DIRECT, dwRootDenyWrite = STGM_SHARE_EXCLUSIVE;
+BOOL fVerbose = FALSE;
+
+#define START_MEMORY_NOT_SET 0x7fffffff
+
+static LONG cbStartMemory = START_MEMORY_NOT_SET;
+
+static char *types[3] =
+{
+ "???",
+ "storage",
+ "stream"
+};
+
+static char testname[256];
+
+void StartTest(char *test)
+{
+ SCODE sc;
+
+ strcpy(testname, test);
+#if WIN32 == 300
+ if (FAILED(sc = GetScode(CoInitializeEx(NULL, COINIT_MULTITHREADED))))
+#else
+ if (FAILED(sc = GetScode(CoInitialize(NULL))))
+#endif
+ {
+ fprintf(stderr, "CoInitialize failed with sc = %lX\n", sc);
+ exit(1);
+ }
+#if DBG == 1
+ cbStartMemory = DfGetMemAlloced();
+#endif
+}
+
+void EndTest(int code)
+{
+ if (code == 0)
+ CheckMemory();
+ CoUninitialize();
+ if (code == 0)
+ printf("%s SUCCEEDED\n", testname);
+ else
+ printf("%s FAILED\n", testname);
+ exit(code);
+}
+
+void printstat(STATSTG *psstg, BOOL verbose)
+{
+ char szName[NAMELEN];
+#ifndef WIN32
+ time_t tm;
+#endif
+
+ TTOA(psstg->pwcsName, szName, CWCSTORAGENAME);
+ if (verbose)
+ {
+ printf("%s:%s =>\n", szName, types[psstg->type]);
+ if (psstg->grfMode != 0)
+ printf(" Mode: 0x%lX\n", psstg->grfMode);
+ if (psstg->type == STGTY_STREAM)
+ {
+ printf(" Size: %lu:%lu\n", ULIGetHigh(psstg->cbSize),
+ ULIGetLow(psstg->cbSize));
+ if (psstg->grfLocksSupported & LOCK_WRITE)
+ printf(" Supports write locks\n");
+ if (psstg->grfLocksSupported & LOCK_EXCLUSIVE)
+ printf(" Supports exclusive locks\n");
+ if (psstg->grfLocksSupported & LOCK_ONLYONCE)
+ printf(" Supports only-once locking\n");
+ }
+ else
+ {
+#ifndef WIN32
+ tm = psstg->ctime.dwLowDateTime;
+ if (tm != 0)
+ printf(" Created : %s", ctime(&tm));
+ tm = psstg->mtime.dwLowDateTime;
+ if (tm != 0)
+ printf(" Modified: %s", ctime(&tm));
+ tm = psstg->atime.dwLowDateTime;
+ if (tm != 0)
+ printf(" Accessed: %s", ctime(&tm));
+#else
+ printf(" Created : %s\n", FileTimeText(&psstg->ctime));
+ printf(" Modified: %s\n", FileTimeText(&psstg->mtime));
+ printf(" Accessed: %s\n", FileTimeText(&psstg->atime));
+#endif
+ printf(" Class ID: %s\n", GuidText(&psstg->clsid));
+ printf(" State bits: 0x%lX\n", psstg->grfStateBits);
+ }
+ }
+ else
+ printf("%s:%lu\n", szName, psstg->type);
+}
+
+void c_contents(IStorage *pdf, int level, BOOL recurse, BOOL verbose)
+{
+ IEnumSTATSTG *pdfi;
+ ULONG ulRet;
+ IStorage *pdfChild;
+ int i;
+ STATSTG sstg;
+ SCODE sc;
+
+ if (FAILED(sc = GetScode(pdf->EnumElements(0, NULL, 0, &pdfi))))
+ {
+ printf("Unable to create iterator, error %lX\n", sc);
+ return;
+ }
+ for (;;)
+ {
+ ulRet = GetScode(pdfi->Next(1, &sstg, NULL));
+ if (ulRet != S_OK)
+ break;
+ if (!verbose)
+ for (i = 0; i<level; i++)
+ putchar(' ');
+ printstat(&sstg, verbose);
+ if (sstg.type == STGTY_STORAGE && recurse)
+ {
+ if (SUCCEEDED(sc = GetScode(pdf->OpenStorage(sstg.pwcsName, NULL,
+ STGP(STGM_READ),
+ NULL, 0, &pdfChild))))
+ {
+ c_contents(pdfChild, level+2, recurse, verbose);
+ pdfChild->Release();
+ }
+ else
+ printf("Unable to recurse, error %lX\n", sc);
+ }
+ CoMemFree(sstg.pwcsName);
+ }
+ pdfi->Release();
+}
+
+static void GetDbgValues(char *psz, DWORD *pdwDf, DWORD *pdwMs)
+{
+ switch(psz[0])
+ {
+ case 'a':
+ *pdwDf = 0xfdffffdf;
+ *pdwMs = 0xfdffffdf;
+ break;
+ case 'd':
+ *pdwDf = 0xfdffffdf;
+ *pdwMs = 0x101;
+ break;
+ case 'G':
+ *pdwDf = 0x02000000;
+ *pdwMs = 0;
+ break;
+ case 'i':
+ *pdwDf = 0x101;
+ *pdwMs = 0x101;
+ break;
+ case 'm':
+ *pdwDf = 0x101;
+ *pdwMs = 0xfdffff2f;
+ break;
+ case 'M':
+ *pdwDf = 0x01100000;
+ *pdwMs = 0;
+ break;
+ case 'L':
+ *pdwDf = 0x00100000;
+ *pdwMs = 0;
+ break;
+ case ':':
+ sscanf(psz+1, "%lx,%lx", pdwDf, pdwMs);
+ break;
+ default:
+ *pdwDf = 0;
+ *pdwMs = 0;
+ break;
+ }
+}
+
+void CmdArgs(int argc, char *argv[])
+{
+ int i;
+ ULONG dbD = 0, dbM = 0, dbtD, dbtM;
+
+ for (i = 1; i<argc; i++)
+ if (*argv[i] == '-')
+ switch(argv[i][1])
+ {
+ case 't':
+ dwTransacted = STGM_TRANSACTED;
+ dwRootDenyWrite = STGM_SHARE_DENY_NONE;
+ break;
+ case 'w':
+ dwTransacted = STGM_TRANSACTED;
+ dwRootDenyWrite = STGM_SHARE_DENY_WRITE;
+ break;
+ case 'v':
+ fVerbose = TRUE;
+ break;
+ case 'y':
+ GetDbgValues(argv[i]+2, &dbD, &dbM);
+ SetDebug(dbD, dbM);
+ break;
+ case 'Y':
+ GetDbgValues(argv[i]+2, &dbtD, &dbtM);
+ dbD |= dbtD;
+ dbM |= dbtM;
+ SetDebug(dbD, dbM);
+ break;
+ }
+ if (dwTransacted == STGM_TRANSACTED)
+ printf(" Transacted");
+ else
+ printf(" Direct");
+ if (dwRootDenyWrite == STGM_SHARE_DENY_WRITE ||
+ dwRootDenyWrite == STGM_SHARE_EXCLUSIVE)
+ printf(" Dependent");
+ else
+ printf(" Independent");
+ if (fVerbose)
+ printf(" Verbose");
+ putchar('\n');
+}
+
+#if DBG == 1
+void CheckMemory(void)
+{
+ if (fVerbose ||
+ (cbStartMemory == START_MEMORY_NOT_SET && DfGetMemAlloced() != 0) ||
+ (DfGetMemAlloced() != cbStartMemory))
+ {
+ DfPrintAllocs();
+ Fail("%s: memory start = %ld, memory held = %ld, change = %ld\n",
+ testname, cbStartMemory, DfGetMemAlloced(),
+ DfGetMemAlloced()-cbStartMemory);
+ }
+}
+#endif
diff --git a/private/ole32/stg/ofsstg/utest2/tsupp.hxx b/private/ole32/stg/ofsstg/utest2/tsupp.hxx
new file mode 100644
index 000000000..3796e025a
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest2/tsupp.hxx
@@ -0,0 +1,41 @@
+#include <windows.h>
+#include <memory.h>
+#if WIN32 != 300
+#include <compobj.h>
+#include <storage.h>
+#endif
+#include <wchar.h>
+#include <dfdeb.hxx>
+#include <dfmsp.hxx>
+#include <dfentry.hxx>
+#include <tutils.hxx>
+
+#if DBG == 1
+#define SetDebug(d, m) DfDebug(d, m)
+void CheckMemory(void);
+#else
+#define SetDebug(d, m)
+#define CheckMemory()
+#endif
+
+#define NAMELEN CWCSTORAGENAME
+
+#define STGM_RW STGM_READWRITE
+#define STGM_DRDW STGM_SHARE_EXCLUSIVE
+
+#define ROOTP(p) ((p) | dwTransacted | dwRootDenyWrite)
+#define STGP(p) ((p) | dwTransacted | STGM_DRDW)
+#define STMP(p) ((p) | STGM_DRDW)
+
+void printstat(STATSTG *psstg, BOOL verbose);
+void c_contents(IStorage *pdf, int level, BOOL recurse, BOOL verbose);
+void CmdArgs(int argc, char *argv[]);
+
+void StartTest(char *test);
+void EndTest(int code);
+
+#define c_list(pdf) c_contents(pdf, 0, FALSE, FALSE)
+#define c_tree(pdf) c_contents(pdf, 0, TRUE, FALSE)
+
+extern DWORD dwTransacted, dwRootDenyWrite;
+extern BOOL fVerbose;
diff --git a/private/ole32/stg/ofsstg/utest2/tutils.cxx b/private/ole32/stg/ofsstg/utest2/tutils.cxx
new file mode 100644
index 000000000..794d80b2a
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest2/tutils.cxx
@@ -0,0 +1,485 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tutils.cxx
+//
+// Contents: Generic utilities for tests
+//
+// History: 06-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+static BOOL fExitOnFail = TRUE;
+
+BOOL GetExitOnFail(void)
+{
+ return fExitOnFail;
+}
+
+void SetExitOnFail(BOOL set)
+{
+ fExitOnFail = set;
+}
+
+// Print out an error message and terminate
+void Fail(char *fmt, ...)
+{
+ va_list args;
+
+ args = va_start(args, fmt);
+ fprintf(stderr, "** Fatal error **: ");
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ EndTest(1);
+}
+
+typedef struct
+{
+ SCODE sc;
+ char *text;
+} StatusCodeText;
+
+static StatusCodeText scodes[] =
+{
+ S_OK, "S_OK",
+ S_FALSE, "S_FALSE",
+ STG_E_INVALIDFUNCTION, "STG_E_INVALIDFUNCTION",
+ STG_E_FILENOTFOUND, "STG_E_FILENOTFOUND",
+ STG_E_PATHNOTFOUND, "STG_E_PATHNOTFOUND",
+ STG_E_TOOMANYOPENFILES, "STG_E_TOOMANYOPENFILES",
+ STG_E_ACCESSDENIED, "STG_E_ACCESSDENIED",
+ STG_E_INVALIDHANDLE, "STG_E_INVALIDHANDLE",
+ STG_E_INSUFFICIENTMEMORY, "STG_E_INSUFFICIENTMEMORY",
+ STG_E_INVALIDPOINTER, "STG_E_INVALIDPOINTER",
+ STG_E_NOMOREFILES, "STG_E_NOMOREFILES",
+ STG_E_DISKISWRITEPROTECTED, "STG_E_DISKISWRITEPROTECTED",
+ STG_E_SEEKERROR, "STG_E_SEEKERROR",
+ STG_E_WRITEFAULT, "STG_E_WRITEFAULT",
+ STG_E_READFAULT, "STG_E_READFAULT",
+ STG_E_SHAREVIOLATION, "STG_E_SHAREVIOLATION",
+ STG_E_LOCKVIOLATION, "STG_E_LOCKVIOLATION",
+ STG_E_FILEALREADYEXISTS, "STG_E_FILEALREADYEXISTS",
+ STG_E_INVALIDPARAMETER, "STG_E_INVALIDPARAMETER",
+ STG_E_MEDIUMFULL, "STG_E_MEDIUMFULL",
+ STG_E_ABNORMALAPIEXIT, "STG_E_ABNORMALAPIEXIT",
+ STG_E_INVALIDHEADER, "STG_E_INVALIDHEADER",
+ STG_E_INVALIDNAME, "STG_E_INVALIDNAME",
+ STG_E_UNKNOWN, "STG_E_UNKNOWN",
+ STG_E_UNIMPLEMENTEDFUNCTION, "STG_E_UNIMPLEMENTEDFUNCTION",
+ STG_E_INVALIDFLAG, "STG_E_INVALIDFLAG",
+ STG_E_INUSE, "STG_E_INUSE",
+ STG_E_NOTCURRENT, "STG_E_NOTCURRENT",
+ STG_E_REVERTED, "STG_E_REVERTED",
+ STG_E_CANTSAVE, "STG_E_CANTSAVE",
+ STG_E_OLDFORMAT, "STG_E_OLDFORMAT",
+ STG_E_OLDDLL, "STG_E_OLDDLL",
+ STG_E_SHAREREQUIRED, "STG_E_SHAREREQUIRED",
+ STG_E_NOTFILEBASEDSTORAGE, "STG_E_NOTFILEBASEDSTORAGE",
+ STG_E_EXTANTMARSHALLINGS, "STG_E_EXTANTMARSHALLINGS",
+ STG_S_CONVERTED, "STG_S_CONVERTED"
+};
+#define NSCODETEXT (sizeof(scodes)/sizeof(scodes[0]))
+
+// Convert a status code to text
+char *ScText(SCODE sc)
+{
+ int i;
+
+ for (i = 0; i<NSCODETEXT; i++)
+ if (scodes[i].sc == sc)
+ return scodes[i].text;
+ return "<Unknown SCODE>";
+}
+
+// Output a call result and check for failure
+HRESULT Result(HRESULT hr, char *fmt, ...)
+{
+ SCODE sc;
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ sc = GetScode(hr);
+ printf(" - %s (0x%lX)\n", ScText(sc), sc);
+ if (FAILED(sc) && fExitOnFail)
+ Fail("Unexpected call failure\n");
+ return hr;
+}
+
+// Perform Result() when the expectation is failure
+HRESULT IllResult(HRESULT hr, char *fmt, ...)
+{
+ SCODE sc;
+ va_list args;
+
+ va_start(args, fmt);
+ vprintf(fmt, args);
+ va_end(args);
+ sc = GetScode(hr);
+ printf(" - %s (0x%lX)\n", ScText(sc), sc);
+ if (SUCCEEDED(sc) && fExitOnFail)
+ Fail("Unexpected call success\n");
+ return hr;
+}
+
+char *TcsText(TCHAR *ptcs)
+{
+ static char buf[256];
+
+ TTOA(ptcs, buf, 256);
+ return buf;
+}
+
+char *FileTimeText(FILETIME *pft)
+{
+ static char buf[80];
+ struct tm ctm;
+#ifndef FLAT
+ WORD dosdate, dostime;
+
+ if (CoFileTimeToDosDateTime(pft, &dosdate, &dostime))
+ {
+ ctm.tm_sec = (dostime & 31)*2;
+ ctm.tm_min = (dostime >> 5) & 63;
+ ctm.tm_hour = dostime >> 11;
+ ctm.tm_mday = dosdate & 31;
+ ctm.tm_mon = ((dosdate >> 5) & 15)-1;
+ ctm.tm_year = (dosdate >> 9)+80;
+ ctm.tm_wday = 0;
+#else
+ SYSTEMTIME st;
+
+ if (FileTimeToSystemTime(pft, &st))
+ {
+ ctm.tm_sec = st.wSecond;
+ ctm.tm_min = st.wMinute;
+ ctm.tm_hour = st.wHour;
+ ctm.tm_mday = st.wDay;
+ ctm.tm_mon = st.wMonth-1;
+ ctm.tm_year = st.wYear-1900;
+ ctm.tm_wday = st.wDayOfWeek;
+#endif
+ ctm.tm_yday = 0;
+ ctm.tm_isdst = 0;
+ strcpy(buf, asctime(&ctm));
+ buf[strlen(buf)-1] = 0;
+ }
+ else
+ sprintf(buf, "<FILETIME %08lX:%08lX>", pft->dwHighDateTime,
+ pft->dwLowDateTime);
+ return buf;
+}
+
+#pragma pack(1)
+struct SplitGuid
+{
+ DWORD dw1;
+ WORD w1;
+ WORD w2;
+ BYTE b[8];
+};
+#pragma pack()
+
+char *GuidText(GUID *pguid)
+{
+ static char buf[39];
+ SplitGuid *psg = (SplitGuid *)pguid;
+
+ sprintf(buf, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
+ psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
+ return buf;
+}
+
+#define CROW 16
+
+void BinText(ULONG cbSize, BYTE *pb)
+{
+ ULONG cb, i;
+
+ while (cbSize > 0)
+ {
+ cb = min(CROW, cbSize);
+ cbSize -= cb;
+ for (i = 0; i<cb; i++)
+ printf(" %02X", pb[i]);
+ for (i = cb; i<CROW; i++)
+ printf(" ");
+ printf(" '");
+ for (i = 0; i<cb; i++)
+ if (pb[i] >= 0x20 && pb[i] <= 0x7f)
+ putchar(pb[i]);
+ else
+ putchar('.');
+ pb += cb;
+ printf("'\n");
+ }
+}
+
+// BUGBUG - Remove for Cairole when they exist
+STDAPI CoMemAlloc(DWORD cbSize, void **ppv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc;
+
+ if (SUCCEEDED(GetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ *ppv = pMalloc->Alloc(cbSize);
+ pMalloc->Release();
+
+ if (*ppv == NULL)
+ hr = ResultFromScode(E_OUTOFMEMORY);
+ }
+ else
+ *ppv = NULL;
+
+ return hr;
+}
+
+STDAPI CoMemFree(void *pv)
+{
+ HRESULT hr;
+ IMalloc *pMalloc;
+
+ if (SUCCEEDED(GetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ pMalloc->Free(pv);
+ pMalloc->Release();
+ }
+
+ return hr;
+}
+
+TCHAR *TestFile(TCHAR *ptcsName, char *pszFile)
+{
+ char achFn[MAX_PATH];
+ char *dir, *file;
+ int len;
+
+ dir = getenv("DFDATA");
+ if (dir)
+ strcpy(achFn, dir);
+ else
+ strcpy(achFn, ".");
+ len = strlen(achFn);
+ if (achFn[len-1] != '\\')
+ achFn[len++] = '\\';
+
+ if (pszFile)
+ {
+ strcpy(achFn+len, pszFile);
+ }
+ else
+ {
+ file = getenv("DFFILE");
+ if (file)
+ strcpy(achFn+len, file);
+ else
+ strcpy(achFn+len, "TEST.DFL");
+ }
+
+ ATOT(achFn, ptcsName, MAX_PATH);
+ return ptcsName+len;
+}
+
+#if WIN32 == 300
+char *TestFormat(DWORD *pdwFmt, DWORD *pgrfMode)
+{
+ char *fmt;
+
+ fmt = getenv("STGFMT");
+ if (fmt == NULL || !strcmp(fmt, "doc"))
+ {
+ fmt = "document";
+ *pdwFmt = STGFMT_DOCUMENT;
+ }
+ else if (!strcmp(fmt, "file"))
+ {
+ fmt = "file";
+ *pdwFmt = STGFMT_FILE;
+ }
+ else
+ {
+ fmt = "directory";
+ *pdwFmt = STGFMT_DIRECTORY;
+ *pgrfMode &= ~STGM_CREATE;
+ }
+ return fmt;
+}
+#endif
+
+void CreateTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName)
+{
+ HRESULT hr;
+ TCHAR atcFile[MAX_PATH];
+ char *fmt;
+
+ if (ptcsName == NULL)
+ ptcsName = atcFile;
+ TestFile(ptcsName, pszFile);
+#if WIN32 == 300
+ DWORD dwStgFmt;
+
+ fmt = TestFormat(&dwStgFmt, &grfMode);
+ hr = StgCreateStorage(ptcsName, grfMode, dwStgFmt, 0, ppstg);
+#else
+ hr = StgCreateDocfile(ptcsName, grfMode, 0, ppstg);
+ fmt = "docfile";
+#endif
+ if (fFail)
+ IllResult(hr, "Create %s %s", fmt, TcsText(ptcsName));
+ else
+ Result(hr, "Create %s %s", fmt, TcsText(ptcsName));
+}
+
+void OpenTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName)
+{
+ HRESULT hr;
+ TCHAR atcFile[MAX_PATH];
+
+ if (ptcsName == NULL)
+ ptcsName = atcFile;
+ TestFile(ptcsName, pszFile);
+ hr = StgOpenStorage(ptcsName, NULL, grfMode, NULL, 0, ppstg);
+ if (fFail)
+ IllResult(hr, "Open storage %s", TcsText(ptcsName));
+ else
+ Result(hr, "Open storage %s", TcsText(ptcsName));
+}
+//+--------------------------------------------------------------
+//
+// Member: CStrList::CStrList, public
+//
+// Synopsis: Ctor
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CStrList::CStrList(void)
+{
+ _pseHead = NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::~CStrList, public
+//
+// Synopsis: Dtor
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+CStrList::~CStrList(void)
+{
+ Empty();
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::Add, public
+//
+// Synopsis: Adds a string to the list
+//
+// Arguments: [ptcs] - String
+//
+// Returns: Pointer to entry or NULL
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+SStrEntry *CStrList::Add(TCHAR *ptcs)
+{
+ SStrEntry *pse;
+
+ // One char of string already counted in sizeof
+ pse = (SStrEntry *)new char[sizeof(SStrEntry)+tcslen(ptcs)*sizeof(TCHAR)];
+ if (pse == NULL)
+ return NULL;
+ pse->pseNext = _pseHead;
+ pse->psePrev = NULL;
+ if (_pseHead)
+ _pseHead->psePrev = pse;
+ _pseHead = pse;
+ tcscpy(pse->atc, ptcs);
+ return pse;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::Remove, public
+//
+// Synopsis: Removes an entry from the list
+//
+// Arguments: [pse] - Entry
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+void CStrList::Remove(SStrEntry *pse)
+{
+ if (pse->psePrev)
+ pse->psePrev->pseNext = pse->pseNext;
+ else
+ _pseHead = pse->pseNext;
+ if (pse->pseNext)
+ pse->pseNext->psePrev = pse->psePrev;
+ delete pse;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::Find, public
+//
+// Synopsis: Attempts to find a string in the list
+//
+// Arguments: [ptcs] - String
+//
+// Returns: Entry or NULL
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+SStrEntry *CStrList::Find(TCHAR *ptcs)
+{
+ SStrEntry *pse;
+
+ for (pse = _pseHead; pse; pse = pse->pseNext)
+ if (!tcscmp(ptcs, pse->atc))
+ return pse;
+ return NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStrList::Empty, public
+//
+// Synopsis: Frees all elements in list
+//
+// History: 24-Sep-92 DrewB Created
+//
+//---------------------------------------------------------------
+
+void CStrList::Empty(void)
+{
+ SStrEntry *pse;
+
+ while (_pseHead)
+ {
+ pse = _pseHead->pseNext;
+ delete _pseHead;
+ _pseHead = pse;
+ }
+}
diff --git a/private/ole32/stg/ofsstg/utest2/tutils.hxx b/private/ole32/stg/ofsstg/utest2/tutils.hxx
new file mode 100644
index 000000000..1fd9992c2
--- /dev/null
+++ b/private/ole32/stg/ofsstg/utest2/tutils.hxx
@@ -0,0 +1,124 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: tutils.hxx
+//
+// Contents: Generic test utilities
+//
+// History: 06-Aug-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __TUTILS_HXX__
+#define __TUTILS_HXX__
+
+#ifndef UNICODE
+#define tcscpy(d, s) strcpy(d, s)
+#define tcslen(s) strlen(s)
+#define tcscmp(s1, s2) strcmp(s1, s2)
+#define TTEXT(s) s
+#define TFMT "%s"
+#define ATOT(a, t, max) strcpy(t, a)
+#define TTOA(t, a, max) strcpy(a, t)
+#define WTOT(w, t, max) wcstombs(t, w, max)
+#define TTOW(t, w, max) mbstowcs(w, t, max)
+#else
+#define tcscpy(d, s) wcscpy(d, s)
+#define tcslen(s) wcslen(s)
+#define tcscmp(s1, s2) wcscmp(s1, s2)
+#define TTEXT(s) L##s
+#define TFMT "%ws"
+#define ATOT(a, t, max) mbstowcs(t, a, max)
+#define TTOA(t, a, max) wcstombs(a, t, max)
+#define WTOT(w, t, max) wcscpy(t, w)
+#define TTOW(t, w, max) wcscpy(w, t)
+#endif
+#ifdef WIN32
+#define ATOX(a, t, max) mbstowcs(t, a, max)
+#define XTOA(t, a, max) wcstombs(a, t, max)
+#define WTOX(w, t, max) wcscpy(t, w)
+#define XTOW(t, w, max) wcscpy(w, t)
+#else
+#define ATOX(a, t, max) strcpy(t, a)
+#define XTOA(t, a, max) strcpy(a, t)
+#define WTOX(w, t, max) wcstombs(t, w, max)
+#define XTOW(t, w, max) mbstowcs(w, t, max)
+#endif
+
+#ifdef CINTERFACE
+#define Mthd(this, name) ((this)->lpVtbl->name)
+#define SELF(p) (p),
+#else
+#define Mthd(this, name) (this)->name
+#define SELF(p)
+#endif
+
+// BUGBUG - Remove for Cairole when they exist
+STDAPI CoMemAlloc(DWORD cBytes, void **ppv);
+STDAPI CoMemFree(void *pv);
+
+BOOL GetExitOnFail(void);
+void SetExitOnFail(BOOL set);
+void Fail(char *fmt, ...);
+char *ScText(SCODE sc);
+HRESULT Result(HRESULT hr, char *fmt, ...);
+HRESULT IllResult(HRESULT hr, char *fmt, ...);
+char *TcsText(TCHAR *ptcs);
+char *FileTimeText(FILETIME *pft);
+char *GuidText(GUID *pguid);
+void BinText(ULONG cb, BYTE *pb);
+TCHAR *TestFile(TCHAR *ptcsName, char *pszFile);
+
+#if WIN32 == 300
+char *TestFormat(DWORD *pdwFmt, DWORD *pgrfMode);
+#endif
+
+void CreateTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName);
+void OpenTestFile(char *pszFile, DWORD grfMode, BOOL fFail, IStorage **ppstg,
+ TCHAR *ptcsName);
+
+// Defined by test, called by Fail
+void EndTest(int code);
+
+//+---------------------------------------------------------------------------
+//
+// Class: CStrList (sl)
+//
+// Purpose: Maintains a list of strings
+//
+// History: 30-Nov-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+struct SStrEntry
+{
+ SStrEntry *pseNext, *psePrev;
+ union
+ {
+ void *pv;
+ unsigned long dw;
+ } user;
+ TCHAR atc[1]; // Actually contains the whole string
+};
+
+class CStrList
+{
+public:
+ CStrList(void);
+ ~CStrList(void);
+
+ SStrEntry *Add(TCHAR *ptcs);
+ void Remove(SStrEntry *pse);
+ SStrEntry *Find(TCHAR *ptcs);
+ void Empty(void);
+
+ SStrEntry *GetHead(void) { return _pseHead; }
+
+private:
+ SStrEntry *_pseHead;
+};
+
+#endif // #ifndef __TUTILS_HXX__
diff --git a/private/ole32/stg/ofsstg/variant.cxx b/private/ole32/stg/ofsstg/variant.cxx
new file mode 100644
index 000000000..f7e03b9d3
--- /dev/null
+++ b/private/ole32/stg/ofsstg/variant.cxx
@@ -0,0 +1,742 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: variant.cxx
+//
+// Contents: Variant helper API stubs
+//
+// Functions: StgVariantClear
+// StgVariantCopy
+//
+// History: 30-Jun-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+#include "headers.cxx"
+#pragma hdrstop
+
+
+void CopyString(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest);
+void FreeString(PROPVARIANT *pvar);
+
+void CopyWString(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest);
+void FreeWString(PROPVARIANT *pvar);
+
+void CopyBString(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest);
+void FreeBString(PROPVARIANT *pvar);
+
+void CopyUUID(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest);
+void FreeUUID(PROPVARIANT *pvar);
+
+void CopyArray(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest, ULONG cbElem);
+void FreeArray(PROPVARIANT *pvar);
+
+void CopyStrings(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest);
+void FreeStrings(PROPVARIANT *pvar);
+
+void CopyWStrings(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest);
+void FreeWStrings(PROPVARIANT *pvar);
+
+void CopyVariants(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest);
+void FreeVariants(PROPVARIANT *pvar);
+
+//+-------------------------------------------------------------------------
+//
+// Function: StgVariantCopy (stub)
+//
+// Synopsis: Copies a variant structure
+//
+// Arguments: [pvargDest] - destination variant
+// [pvargSrc] - source variant
+//
+// Modifies: [pvargDest]
+//
+// History: 30-Jun-93 CarlH Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+HRESULT StgVariantCopy(PROPVARIANTARG *pvargDest, PROPVARIANTARG *pvargSrc)
+{
+ Win4Assert(!(pvargSrc->vt & VT_BYREF) && "VariantCopy() does not support VT_BYREF yet!");
+
+ // Copy the fields of the variant first. If the source contains
+ // a value that needs special treatment, we'll take care of it
+ // after this.
+ //
+ *pvargDest = *pvargSrc;
+
+ // We need to figure out if this variant contains a value that requires
+ // any special treatment (e.g. an interface or data pointer).
+ //
+ switch (pvargSrc->vt)
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ case VT_I2:
+ case VT_I4:
+ case VT_I8:
+ case VT_R4:
+ case VT_R8:
+ case VT_BOOL:
+ case VT_CY:
+ case VT_DATE:
+ case VT_FILETIME:
+ case VT_ERROR:
+ break;
+ case VT_BSTR:
+ Win4Assert(!"StgVariantCopy() does not support VT_BSTR yet!");
+ break;
+
+ case VT_LPSTR:
+ CopyString(pvargSrc, pvargDest);
+ break;
+
+ case VT_LPWSTR:
+ CopyWString(pvargSrc, pvargDest);
+ break;
+
+ case VT_CLSID:
+ CopyUUID(pvargSrc, pvargDest);
+ break;
+
+ case VT_BLOB:
+ CopyArray(
+ pvargSrc,
+ pvargDest,
+ sizeof(*pvargSrc->blob.pBlobData));
+ break;
+
+ case (VT_VECTOR | VT_I2):
+ CopyArray(
+ pvargSrc,
+ pvargDest,
+ sizeof(*pvargSrc->cai.pElems));
+ break;
+ case (VT_VECTOR | VT_I4):
+ CopyArray(
+ pvargSrc,
+ pvargDest,
+ sizeof(*pvargSrc->cal.pElems));
+ break;
+ case (VT_VECTOR | VT_I8):
+ CopyArray(
+ pvargSrc,
+ pvargDest,
+ sizeof(*pvargSrc->cali.pElems));
+ break;
+ case (VT_VECTOR | VT_R4):
+ CopyArray(
+ pvargSrc,
+ pvargDest,
+ sizeof(*pvargSrc->caflt.pElems));
+ break;
+ case (VT_VECTOR | VT_R8):
+ CopyArray(
+ pvargSrc,
+ pvargDest,
+ sizeof(*pvargSrc->cadbl.pElems));
+ break;
+ case (VT_VECTOR | VT_BOOL):
+ CopyArray(
+ pvargSrc,
+ pvargDest,
+ sizeof(*pvargSrc->cabool.pElems));
+ break;
+ case (VT_VECTOR | VT_CY):
+ CopyArray(
+ pvargSrc,
+ pvargDest,
+ sizeof(*pvargSrc->cacy.pElems));
+ break;
+ case (VT_VECTOR | VT_DATE):
+ CopyArray(
+ pvargSrc,
+ pvargDest,
+ sizeof(*pvargSrc->cadate.pElems));
+ break;
+ case (VT_VECTOR | VT_FILETIME):
+ CopyArray(
+ pvargSrc,
+ pvargDest,
+ sizeof(*pvargSrc->cafiletime.pElems));
+ break;
+ case (VT_VECTOR | VT_CLSID):
+ CopyArray(
+ pvargSrc,
+ pvargDest,
+ sizeof(*pvargSrc->cauuid.pElems));
+ break;
+ case (VT_VECTOR | VT_LPSTR):
+ CopyStrings(pvargSrc, pvargDest);
+ break;
+ case (VT_VECTOR | VT_LPWSTR):
+ CopyWStrings(pvargSrc, pvargDest);
+ break;
+ case (VT_VECTOR | VT_BSTR):
+ Win4Assert(!"VariantCopy() does not support VT_VECTOR | VT_BSTR yet!");
+ break;
+ case (VT_VECTOR | VT_VARIANT):
+ CopyVariants(pvargSrc, pvargDest);
+ break;
+ case VT_CF:
+ Win4Assert(!"VariantCopy() does not support VT_CF yet!");
+ break;
+ case VT_SAFEARRAY:
+ Win4Assert(!"VariantCopy() does not support VT_SAFEARRAY yet!");
+ break;
+#ifdef FULL_VARIANT
+ // BUGBUG: [mikese] I'm pretty sure this is wrong for PROPVARIANT
+
+ case VT_STREAM:
+ pvargSrc->pStream->AddRef();
+ pvargDest->pStream = pvargSrc->pStream;
+ break;
+
+ case VT_STORAGE:
+ pvargSrc->pStorage->AddRef();
+ pvargDest->pStorage = pvargSrc->pStorage;
+ break;
+#endif // FULL_VARIANT
+ default:
+ Win4Assert(!"VariantCopy() unknown type!");
+ break;
+ }
+
+ return (NO_ERROR);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: StgVariantClear
+//
+// Synopsis: Clears a variant structure
+//
+// Arguments: [pvarg] - variant to clear
+//
+// Modifies: [pvarg]
+//
+// History: 30-Jun-93 CarlH Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+HRESULT StgVariantClear(PROPVARIANTARG *pvarg)
+{
+ Win4Assert(!(pvarg->vt & VT_BYREF) && "VariantClear() does not support VT_BYREF yet!");
+
+ // We need to figure out if this variant contains a value that requires
+ // any special treatment (e.g. an interface or data pointer).
+ //
+ switch (pvarg->vt)
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ case VT_I2:
+ case VT_I4:
+ case VT_I8:
+ case VT_R4:
+ case VT_R8:
+ case VT_BOOL:
+ case VT_CY:
+ case VT_DATE:
+ case VT_FILETIME:
+ case VT_ERROR:
+ break;
+ case VT_BSTR:
+ Win4Assert(!"VariantClear() does not support VT_BSTR yet!");
+ break;
+ case VT_LPSTR:
+ FreeString(pvarg);
+ break;
+ case VT_LPWSTR:
+ FreeWString(pvarg);
+ break;
+ case VT_CLSID:
+ FreeUUID(pvarg);
+ break;
+ case VT_BLOB:
+ case (VT_VECTOR | VT_I2):
+ case (VT_VECTOR | VT_I4):
+ case (VT_VECTOR | VT_I8):
+ case (VT_VECTOR | VT_R4):
+ case (VT_VECTOR | VT_R8):
+ case (VT_VECTOR | VT_BOOL):
+ case (VT_VECTOR | VT_CY):
+ case (VT_VECTOR | VT_DATE):
+ case (VT_VECTOR | VT_FILETIME):
+ case (VT_VECTOR | VT_CLSID):
+ FreeArray(pvarg);
+ break;
+ case (VT_VECTOR | VT_LPSTR):
+ FreeStrings(pvarg);
+ break;
+ case (VT_VECTOR | VT_LPWSTR):
+ FreeWStrings(pvarg);
+ break;
+ case (VT_VECTOR | VT_BSTR):
+ Win4Assert(!"VariantClear() does not support VT_VECTOR | VT_BSTR yet!");
+ break;
+ case (VT_VECTOR | VT_VARIANT):
+ FreeVariants(pvarg);
+ break;
+ case VT_SAFEARRAY:
+ Win4Assert(!"VariantClear() does not support VT_SAFEARRAY yet!");
+ break;
+#ifdef FULL_VARIANT
+ case VT_STREAM:
+ pvarg->pStream->Release();
+ break;
+
+ case VT_STORAGE:
+ pvarg->pStorage->Release();
+ break;
+
+#endif // FULL_VARIANT
+ default:
+ Win4Assert(!"VariantClear() unknown type!");
+ break;
+ }
+
+ // We have all of the important information about the variant, so
+ // let's clear it out.
+ //
+ StgVariantInit(pvarg);
+
+ return (NO_ERROR);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: FreeStgVariantArray, public
+//
+// Synopsis: Frees a value array returned from ReadMultiple
+//
+// Arguments: [cval] - Number of elements
+// [rgvar] - Array
+//
+// Returns: Appropriate status code
+//
+// History: 18-Dec-92 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+STDAPI FreeStgVariantArray (
+ ULONG cVariants,
+ PROPVARIANT *rgvars)
+{
+ for ( ULONG I=0; I < cVariants; I++ )
+ StgVariantClear ( rgvars + I );
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CopyString, private
+//
+// Synopsis: Copies a VARIANT thin string
+//
+// Arguments: [pvarSrc] - source VARIANT
+// [pvarDest] - destination VARIANT
+//
+// Modifies: [pvarDest]
+//
+// History: 02-Jul-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+void CopyString(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest)
+{
+ ULONG cb = (strlen(pvarSrc->pszVal) + 1) * sizeof(*pvarSrc->pszVal);
+
+ if ((pvarDest->pszVal = (char *)CoTaskMemAlloc(cb)) != NULL)
+ {
+ strcpy(pvarDest->pszVal, pvarSrc->pszVal);
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: FreeString, private
+//
+// Synopsis: Frees a VARIANT thin string
+//
+// Arguments: [pvar] - variant of which to free string
+//
+// History: 07-12-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+void FreeString(PROPVARIANT *pvar)
+{
+ CoTaskMemFree(pvar->pszVal);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CopyWString, private
+//
+// Synopsis: Copies a PROPVARIANT wide string
+//
+// Arguments: [pvarSrc] - source PROPVARIANT
+// [pvarDest] - destination PROPVARIANT
+//
+// Modifies: [pvarDest]
+//
+// History: 02-Jul-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+void CopyWString(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest)
+{
+ ULONG cb = (wcslen(pvarSrc->pwszVal) + 1) * sizeof(*pvarSrc->pwszVal);
+
+ if ((pvarDest->pwszVal = (WCHAR *)CoTaskMemAlloc(cb)) != NULL)
+ {
+ wcscpy(pvarDest->pwszVal, pvarSrc->pwszVal);
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: FreeWString, private
+//
+// Synopsis: Frees a PROPVARIANT wide string
+//
+// Arguments: [pvar] - PROPVARIANT of which to free string
+//
+// Returns: NO_ERROR is successful, error value otherwise
+//
+// History: 07-12-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+void FreeWString(PROPVARIANT *pvar)
+{
+ CoTaskMemFree(pvar->pwszVal);
+}
+
+#ifdef BSTR_SUPPORT
+
+//+-------------------------------------------------------------------------
+//
+// Function: CopyBString, private
+//
+// Synopsis: Copies a PROPVARIANT wide basic string
+//
+// Arguments: [pvarSrc] - source PROPVARIANT
+// [pvarDest] - destination PROPVARIANT
+//
+// Returns: NO_ERROR is successful, error value otherwise
+//
+// Modifies: [pvarDest]
+//
+// History: 02-Jul-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+void CopyBString(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest)
+{
+ pvarDest->bstrVal = SysAllocString(pvarSrc->bstrVal);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: FreeBString, private
+//
+// Synopsis: Frees a PROPVARIANT wide basic string
+//
+// Arguments: [pvar] - variant of which to free string
+//
+// Returns: NO_ERROR is successful, error value otherwise
+//
+// History: 07-12-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+void FreeBString(PROPVARIANT *pvar)
+{
+ SysFreeString(pvar->bstrVal);
+}
+
+#endif
+
+//+-------------------------------------------------------------------------
+//
+// Function: CopyUUID, private
+//
+// Synopsis: Copies a PROPVARIANT unique identifier
+//
+// Arguments: [pvarSrc] - source PROPVARIANT
+// [pvarDest] - destination PROPVARIANT
+//
+// Returns: NO_ERROR is successful, error value otherwise
+//
+// Modifies: [pvarDest]
+//
+// History: 02-Jul-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+void CopyUUID(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest)
+{
+ ULONG cb = sizeof(*pvarSrc->puuid);
+
+ if ((pvarDest->puuid = (GUID *)CoTaskMemAlloc(cb)) != NULL)
+ {
+ *pvarDest->puuid = *pvarSrc->puuid;
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: FreeUUID, private
+//
+// Synopsis: Frees a PROPVARIANT unique identifier
+//
+// Arguments: [pvar] - variant of which to identifier
+//
+// Returns: NO_ERROR is successful, error value otherwise
+//
+// History: 07-12-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+void FreeUUID(PROPVARIANT *pvar)
+{
+ CoTaskMemFree(pvar->puuid);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CopyArray, private
+//
+// Synopsis: Copies a PROPVARIANT counted array
+//
+// Arguments: [pvarSrc] - source PROPVARIANT
+// [pvarDest] - destination PROPVARIANT
+//
+// Returns: NO_ERROR is successful, error value otherwise
+//
+// Modifies: [pvarDest]
+//
+// History: 02-Jul-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+void CopyArray(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest, ULONG cbElem)
+{
+ ULONG cb = pvarSrc->cai.cElems * cbElem;
+
+ // BUGBUG: What the hell should I cast this allocation to?
+ // I'm going to throw in (short *) for right now,
+ // but there must be something better.
+ //
+ if ((pvarDest->cai.pElems = (short *)CoTaskMemAlloc(cb)) != NULL)
+ {
+ pvarDest->cai.cElems = pvarSrc->cai.cElems;
+
+ memcpy(
+ pvarDest->cai.pElems,
+ pvarSrc->cai.pElems,
+ pvarSrc->cai.cElems * cbElem);
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: FreeArray, private
+//
+// Synopsis: Frees a PROPVARIANT counted array
+//
+// Arguments: [pvar] - variant of which to counted array
+//
+// Returns: NO_ERROR is successful, error value otherwise
+//
+// History: 07-12-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+void FreeArray(PROPVARIANT *pvar)
+{
+ CoTaskMemFree(pvar->cai.pElems);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CopyStrings, private
+//
+// Synopsis: Copies a PROPVARIANT array of thin strings
+//
+// Arguments: [pvarSrc] - source PROPVARIANT
+// [pvarDest] - destination PROPVARIANT
+//
+// Returns: NO_ERROR is successful, error value otherwise
+//
+// Modifies: [pvarDest]
+//
+// Notes: BUGBUG: If any of the allocations after the first
+// one below fails, we are in big trouble because
+// we are going to leak memory.
+//
+// History: 02-Jul-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+void CopyStrings(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest)
+{
+ ULONG cb;
+
+ // First, we need to allocate an array of string pointers
+ // to hold all of the strings we are copying.
+ //
+ pvarDest->calpstr.cElems = pvarSrc->calpstr.cElems;
+
+ cb = pvarSrc->calpstr.cElems * sizeof(*pvarSrc->calpstr.pElems);
+ if ((pvarDest->calpstr.pElems = (char **)CoTaskMemAlloc(cb)) != NULL)
+ {
+ // And now we need to allocate memory for each string
+ // and copy the source string to the destination.
+ //
+ for (ULONG ipsz = 0; ipsz < pvarSrc->calpstr.cElems; ipsz++)
+ {
+ cb = (strlen(pvarSrc->calpstr.pElems[ipsz]) + 1) *
+ sizeof(**pvarSrc->calpstr.pElems);
+
+ if ((pvarDest->calpstr.pElems[ipsz] = (char *)CoTaskMemAlloc(cb)) != NULL)
+ {
+ strcpy(
+ pvarDest->calpstr.pElems[ipsz],
+ pvarSrc->calpstr.pElems[ipsz]);
+ }
+ }
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: FreeStrings, private
+//
+// Synopsis: Frees a PROPVARIANT array of thin strings
+//
+// Arguments: [pvar] - variant of which to free strings
+//
+// Returns: NO_ERROR is successful, error value otherwise
+//
+// History: 07-12-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+void FreeStrings(PROPVARIANT *pvar)
+{
+ for (ULONG ipsz = 0; ipsz < pvar->calpstr.cElems; ipsz++)
+ {
+ CoTaskMemFree(pvar->calpstr.pElems[ipsz]);
+ }
+
+ CoTaskMemFree(pvar->calpstr.pElems);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: CopyWStrings, private
+//
+// Synopsis: Copies a PROPVARIANT array of wide strings
+//
+// Arguments: [pvarSrc] - source PROPVARIANT
+// [pvarDest] - destination PROPVARIANT
+//
+// Returns: NO_ERROR is successful, error value otherwise
+//
+// Modifies: [pvarDest]
+//
+// History: 02-Jul-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+void CopyWStrings(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest)
+{
+ ULONG cb;
+
+ // First, we need to allocate an array of string pointers
+ // to hold all of the strings we are copying.
+ //
+ pvarDest->calpwstr.cElems = pvarSrc->calpwstr.cElems;
+
+ cb = pvarSrc->calpwstr.cElems * sizeof(*pvarSrc->calpwstr.pElems);
+ if ((pvarDest->calpwstr.pElems = (WCHAR **)CoTaskMemAlloc(cb)) != NULL)
+ {
+ // And now we need to allocate memory for each string
+ // and copy the source string to the destination.
+ //
+ for (ULONG ipsz = 0; ipsz < pvarSrc->calpwstr.cElems; ipsz++)
+ {
+ cb = (wcslen(pvarSrc->calpwstr.pElems[ipsz]) + 1) *
+ sizeof(**pvarSrc->calpwstr.pElems);
+
+ if ((pvarDest->calpwstr.pElems[ipsz] = (WCHAR *)CoTaskMemAlloc(cb)) != NULL)
+ {
+ wcscpy(
+ pvarDest->calpwstr.pElems[ipsz],
+ pvarSrc->calpwstr.pElems[ipsz]);
+ }
+ }
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: FreeWStrings, private
+//
+// Synopsis: Frees a PROPVARIANT array of wide strings
+//
+// Arguments: [pvar] - variant of which to free strings
+//
+// Returns: NO_ERROR is successful, error value otherwise
+//
+// History: 07-12-93 CarlH Created
+//
+//--------------------------------------------------------------------------
+void FreeWStrings(PROPVARIANT *pvar)
+{
+ for (ULONG ipsz = 0; ipsz < pvar->calpwstr.cElems; ipsz++)
+ {
+ CoTaskMemFree(pvar->calpwstr.pElems[ipsz]);
+ }
+
+ CoTaskMemFree(pvar->calpwstr.pElems);
+}
+
+
+void CopyVariants(PROPVARIANT *pvarSrc, PROPVARIANT *pvarDest)
+{
+ ULONG cb = sizeof(*pvarDest->castgvar.pElems) * pvarDest->castgvar.cElems;
+
+ if ((pvarDest->castgvar.pElems = (PROPVARIANT *)CoTaskMemAlloc(cb)) != NULL)
+ {
+ pvarDest->castgvar.cElems = pvarSrc->castgvar.cElems;
+
+ for (ULONG ivar = 0; ivar < pvarDest->castgvar.cElems; ivar++)
+ {
+ // BUGBUG: what do we do if one of these copies fails?
+ //
+ StgVariantCopy(
+ pvarDest->castgvar.pElems + ivar,
+ pvarSrc->castgvar.pElems + ivar);
+ }
+ }
+}
+
+
+void FreeVariants(PROPVARIANT *pvar)
+{
+ for (ULONG ivar = 0; ivar < pvar->castgvar.cElems; ivar++)
+ {
+ StgVariantClear(pvar->castgvar.pElems + ivar);
+ }
+
+ CoTaskMemFree(pvar->castgvar.pElems);
+}
+
+
diff --git a/private/ole32/stg/ole2flat/coguid.h b/private/ole32/stg/ole2flat/coguid.h
new file mode 100644
index 000000000..049884168
--- /dev/null
+++ b/private/ole32/stg/ole2flat/coguid.h
@@ -0,0 +1,65 @@
+/*****************************************************************************\
+* *
+* coguid.h - Master definition of GUIDs for compobj.dll *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+/* this file is the master definition of all GUIDs for the component object
+ model and is included in compobj.h. Some GUIDs for moinkers and storage
+ appear here as well. All of these GUIDs are OLE GUIDs only in the sense
+ that part of the GUID range owned by OLE was used to define them.
+
+ NOTE: The second byte of all of these GUIDs is 0.
+*/
+
+
+DEFINE_GUID(GUID_NULL, 0L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+DEFINE_OLEGUID(IID_IUnknown, 0x00000000L, 0, 0);
+DEFINE_OLEGUID(IID_IClassFactory, 0x00000001L, 0, 0);
+DEFINE_OLEGUID(IID_IMalloc, 0x00000002L, 0, 0);
+DEFINE_OLEGUID(IID_IMarshal, 0x00000003L, 0, 0);
+
+/* RPC related interfaces */
+DEFINE_OLEGUID(IID_IRpcChannel, 0x00000004L, 0, 0);
+DEFINE_OLEGUID(IID_IRpcStub, 0x00000005L, 0, 0);
+DEFINE_OLEGUID(IID_IStubManager, 0x00000006L, 0, 0);
+DEFINE_OLEGUID(IID_IRpcProxy, 0x00000007L, 0, 0);
+DEFINE_OLEGUID(IID_IProxyManager, 0x00000008L, 0, 0);
+DEFINE_OLEGUID(IID_IPSFactory, 0x00000009L, 0, 0);
+
+/* storage related interfaces */
+DEFINE_OLEGUID(IID_ILockBytes, 0x0000000aL, 0, 0);
+DEFINE_OLEGUID(IID_IStorage, 0x0000000bL, 0, 0);
+DEFINE_OLEGUID(IID_IStream, 0x0000000cL, 0, 0);
+DEFINE_OLEGUID(IID_IEnumSTATSTG, 0x0000000dL, 0, 0);
+
+/* moniker related interfaces */
+DEFINE_OLEGUID(IID_IBindCtx, 0x0000000eL, 0, 0);
+DEFINE_OLEGUID(IID_IMoniker, 0x0000000fL, 0, 0);
+DEFINE_OLEGUID(IID_IRunningObjectTable, 0x00000010L, 0, 0);
+DEFINE_OLEGUID(IID_IInternalMoniker, 0x00000011L, 0, 0);
+
+/* storage related interfaces */
+DEFINE_OLEGUID(IID_IRootStorage, 0x00000012L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved1, 0x00000013L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved2, 0x00000014L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved3, 0x00000015L, 0, 0);
+
+/* concurrency releated interfaces */
+DEFINE_OLEGUID(IID_IMessageFilter, 0x00000016L, 0, 0);
+
+/* CLSID of standard marshaler */
+DEFINE_OLEGUID(CLSID_StdMarshal, 0x00000017L, 0, 0);
+
+/* interface on server for getting info for std marshaler */
+DEFINE_OLEGUID(IID_IStdMarshalInfo, 0x00000018L, 0, 0);
+
+/* interface to inform object of number of external connections */
+DEFINE_OLEGUID(IID_IExternalConnection, 0x00000019L, 0, 0);
+
+/* NOTE: LSB 0x1a through 0xff are reserved for future use */
diff --git a/private/ole32/stg/ole2flat/compobj.h b/private/ole32/stg/ole2flat/compobj.h
new file mode 100644
index 000000000..d21166ab3
--- /dev/null
+++ b/private/ole32/stg/ole2flat/compobj.h
@@ -0,0 +1,1059 @@
+/*****************************************************************************\
+* *
+* compobj.h - Component object model definitions *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#if !defined( _COMPOBJ_H_ )
+#define _COMPOBJ_H_
+
+/****** Linkage Definitions *************************************************/
+
+/*
+ * These are macros for declaring methods/functions. They exist so that
+ * control over the use of keywords (CDECL, PASCAL, __export,
+ * extern "C") resides in one place, and because this is the least
+ * intrusive way of writing function declarations that do not have
+ * to be modified in order to port to the Mac.
+ *
+ * The macros without the trailing underscore are for functions/methods
+ * which a return value of type HRESULT; this is by far the most common
+ * case in OLE. The macros with a trailing underscore take a return
+ * type as a parameter.
+ *
+ * WARNING: STDAPI is hard coded into the LPFNGETCLASSOBJECT typedef below.
+ */
+
+#ifdef __cplusplus
+ #define EXTERN_C extern "C"
+#else
+ #define EXTERN_C extern
+#endif
+
+#ifdef _MAC
+#define STDMETHODCALLTYPE
+#define STDAPICALLTYPE pascal
+
+#define STDAPI EXTERN_C STDAPICALLTYPE HRESULT
+#define STDAPI_(type) EXTERN_C STDAPICALLTYPE type
+
+#else // !_MAC
+
+#ifdef WIN32
+#define STDMETHODCALLTYPE __cdecl
+#define STDAPICALLTYPE __stdcall
+
+#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE
+#define STDAPI_(type) EXTERN_C type STDAPICALLTYPE
+
+#else
+#define STDMETHODCALLTYPE __export FAR CDECL
+#define STDAPICALLTYPE __export FAR PASCAL
+
+#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE
+#define STDAPI_(type) EXTERN_C type STDAPICALLTYPE
+
+#endif // WIN32
+
+#endif //!_MAC
+
+#define STDMETHODIMP HRESULT STDMETHODCALLTYPE
+#define STDMETHODIMP_(type) type STDMETHODCALLTYPE
+
+
+/****** Interface Declaration ***********************************************/
+
+/*
+ * These are macros for declaring interfaces. They exist so that
+ * a single definition of the interface is simulataneously a proper
+ * declaration of the interface structures (C++ abstract classes)
+ * for both C and C++.
+ *
+ * DECLARE_INTERFACE(iface) is used to declare an interface that does
+ * not derive from a base interface.
+ * DECLARE_INTERFACE_(iface, baseiface) is used to declare an interface
+ * that does derive from a base interface.
+ *
+ * By default if the source file has a .c extension the C version of
+ * the interface declaratations will be expanded; if it has a .cpp
+ * extension the C++ version will be expanded. if you want to force
+ * the C version expansion even though the source file has a .cpp
+ * extension, then define the macro "CINTERFACE".
+ * eg. cl -DCINTERFACE file.cpp
+ *
+ * Example Interface declaration:
+ *
+ * #undef INTERFACE
+ * #define INTERFACE IClassFactory
+ *
+ * DECLARE_INTERFACE_(IClassFactory, IUnknown)
+ * {
+ * // *** IUnknown methods ***
+ * STDMETHOD(QueryInterface) (THIS_
+ * REFIID riid,
+ * LPVOID FAR* ppvObj) PURE;
+ * STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ * STDMETHOD_(ULONG,Release) (THIS) PURE;
+ *
+ * // *** IClassFactory methods ***
+ * STDMETHOD(CreateInstance) (THIS_
+ * LPUNKNOWN pUnkOuter,
+ * REFIID riid,
+ * LPVOID FAR* ppvObject) PURE;
+ * };
+ *
+ * Example C++ expansion:
+ *
+ * struct FAR IClassFactory : public IUnknown
+ * {
+ * virtual HRESULT STDMETHODCALLTYPE QueryInterface(
+ * IID FAR& riid,
+ * LPVOID FAR* ppvObj) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE AddRef(void) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE Release(void) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE CreateInstance(
+ * LPUNKNOWN pUnkOuter,
+ * IID FAR& riid,
+ * LPVOID FAR* ppvObject) = 0;
+ * };
+ *
+ * NOTE: Our documentation says '#define interface class' but we use
+ * 'struct' instead of 'class' to keep a lot of 'public:' lines
+ * out of the interfaces. The 'FAR' forces the 'this' pointers to
+ * be far, which is what we need.
+ *
+ * Example C expansion:
+ *
+ * typedef struct IClassFactory
+ * {
+ * const struct IClassFactoryVtbl FAR* lpVtbl;
+ * } IClassFactory;
+ *
+ * typedef struct IClassFactoryVtbl IClassFactoryVtbl;
+ *
+ * struct IClassFactoryVtbl
+ * {
+ * HRESULT (STDMETHODCALLTYPE * QueryInterface) (
+ * IClassFactory FAR* This,
+ * IID FAR* riid,
+ * LPVOID FAR* ppvObj) ;
+ * HRESULT (STDMETHODCALLTYPE * AddRef) (IClassFactory FAR* This) ;
+ * HRESULT (STDMETHODCALLTYPE * Release) (IClassFactory FAR* This) ;
+ * HRESULT (STDMETHODCALLTYPE * CreateInstance) (
+ * IClassFactory FAR* This,
+ * LPUNKNOWN pUnkOuter,
+ * IID FAR* riid,
+ * LPVOID FAR* ppvObject);
+ * HRESULT (STDMETHODCALLTYPE * LockServer) (
+ * IClassFactory FAR* This,
+ * BOOL fLock);
+ * };
+ */
+
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+#ifdef __TURBOC__
+#define interface struct huge
+#else
+#define interface struct FAR
+#endif
+#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method
+#define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method
+#define PURE = 0
+#define THIS_
+#define THIS void
+#define DECLARE_INTERFACE(iface) interface iface
+#define DECLARE_INTERFACE_(iface, baseiface) interface iface : public baseiface
+
+#else
+#define interface struct
+
+#ifdef _MAC
+
+#define STDMETHOD(method) long method##pad;\
+ HRESULT (STDMETHODCALLTYPE * method)
+#define STDMETHOD_(type,method) long method##pad;\
+ type (STDMETHODCALLTYPE * method)
+
+#else // _MAC
+
+#define STDMETHOD(method) HRESULT (STDMETHODCALLTYPE * method)
+#define STDMETHOD_(type,method) type (STDMETHODCALLTYPE * method)
+
+#endif // !_MAC
+
+#define PURE
+#define THIS_ INTERFACE FAR* This,
+#define THIS INTERFACE FAR* This
+#ifdef CONST_VTABLE
+#define DECLARE_INTERFACE(iface) typedef interface iface { \
+ const struct iface##Vtbl FAR* lpVtbl; \
+ } iface; \
+ typedef const struct iface##Vtbl iface##Vtbl; \
+ const struct iface##Vtbl
+#else
+#define DECLARE_INTERFACE(iface) typedef interface iface { \
+ struct iface##Vtbl FAR* lpVtbl; \
+ } iface; \
+ typedef struct iface##Vtbl iface##Vtbl; \
+ struct iface##Vtbl
+#endif
+#define DECLARE_INTERFACE_(iface, baseiface) DECLARE_INTERFACE(iface)
+
+#endif
+
+
+/****** Additional basic types **********************************************/
+
+
+#ifndef FARSTRUCT
+#ifdef __cplusplus
+#define FARSTRUCT FAR
+#else
+#define FARSTRUCT
+#endif // __cplusplus
+#endif // FARSTRUCT
+
+#ifndef WIN32
+//this is historical stuff
+
+#ifndef WINAPI /* If not included with 3.1 headers... */
+
+#ifdef WIN32
+#define FAR
+#define PASCAL __stdcall
+#define CDECL
+#else
+#define FAR _far
+#define PASCAL _pascal
+#define CDECL _cdecl
+#endif
+
+#define VOID void
+#define WINAPI FAR PASCAL
+#define CALLBACK FAR PASCAL
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+typedef int BOOL;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned int UINT;
+
+typedef long LONG;
+typedef unsigned long DWORD;
+
+
+typedef UINT WPARAM;
+typedef LONG LPARAM;
+typedef LONG LRESULT;
+
+typedef unsigned int HANDLE;
+#define DECLARE_HANDLE(name) typedef UINT name
+
+DECLARE_HANDLE(HMODULE);
+DECLARE_HANDLE(HINSTANCE);
+DECLARE_HANDLE(HLOCAL);
+DECLARE_HANDLE(HGLOBAL);
+DECLARE_HANDLE(HDC);
+DECLARE_HANDLE(HRGN);
+DECLARE_HANDLE(HWND);
+DECLARE_HANDLE(HMENU);
+DECLARE_HANDLE(HACCEL);
+DECLARE_HANDLE(HTASK);
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+typedef void FAR * LPVOID;
+typedef WORD FAR * LPWORD;
+typedef DWORD FAR * LPDWORD;
+typedef char FAR* LPSTR;
+typedef const char FAR* LPCSTR;
+typedef void FAR* LPLOGPALETTE;
+typedef void FAR* LPMSG;
+//typedef struct tagMSG FAR *LPMSG;
+
+typedef HANDLE FAR *LPHANDLE;
+typedef struct tagRECT FAR *LPRECT;
+
+typedef struct FARSTRUCT tagSIZE
+{
+ int cx;
+ int cy;
+} SIZE;
+typedef SIZE* PSIZE;
+
+
+#endif /* WINAPI */
+
+#endif // !WIN32
+
+typedef short SHORT;
+typedef unsigned short USHORT;
+typedef DWORD ULONG;
+
+
+#ifndef HUGEP
+#ifdef WIN32
+#define HUGEP
+#else
+#define HUGEP __huge
+#endif // WIN32
+#endif // HUGEP
+
+//Handle Unicode for all platforms
+
+//Win 16 platforms
+#ifndef UNICODE
+
+#define LPXSTR LPSTR
+#define LPCXSTR LPCSTR
+#define XCHAR char
+#define XSTR(str) str
+
+#else //Win32
+
+#define LPXSTR LPWSTR
+#define LPCXSTR LPCWSTR
+#define XCHAR WCHAR
+#define XSTR(str) L##str
+
+#endif //!WIN32
+
+//end of Unicode issues
+
+#ifndef WIN32
+typedef struct FARSTRUCT _LARGE_INTEGER {
+ DWORD LowPart;
+ LONG HighPart;
+} LARGE_INTEGER, *PLARGE_INTEGER;
+#endif
+#define LISet32(li, v) ((li).HighPart = ((LONG)(v)) < 0 ? -1 : 0, (li).LowPart = (v))
+
+#ifndef WIN32
+typedef struct FARSTRUCT _ULARGE_INTEGER {
+ DWORD LowPart;
+ DWORD HighPart;
+} ULARGE_INTEGER, *PULARGE_INTEGER;
+#endif
+#define ULISet32(li, v) ((li).HighPart = 0, (li).LowPart = (v))
+
+#ifndef _WINDOWS_
+#ifndef _FILETIME_
+#define _FILETIME_
+typedef struct FARSTRUCT tagFILETIME
+{
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+} FILETIME;
+#endif
+#endif
+
+#ifdef WIN32
+#define HTASK DWORD
+#endif
+
+#include "scode.h"
+
+
+
+// *********************** Compobj errors **********************************
+
+#define CO_E_NOTINITIALIZED (CO_E_FIRST + 0x0)
+// CoInitialize has not been called and must be
+
+#define CO_E_ALREADYINITIALIZED (CO_E_FIRST + 0x1)
+// CoInitialize has already been called and cannot be called again (temporary)
+
+#define CO_E_CANTDETERMINECLASS (CO_E_FIRST + 0x2)
+// can't determine clsid (e.g., extension not in reg.dat)
+
+#define CO_E_CLASSSTRING (CO_E_FIRST + 0x3)
+// the string form of the clsid is invalid (including ole1 classes)
+
+#define CO_E_IIDSTRING (CO_E_FIRST + 0x4)
+// the string form of the iid is invalid
+
+#define CO_E_APPNOTFOUND (CO_E_FIRST + 0x5)
+// application not found
+
+#define CO_E_APPSINGLEUSE (CO_E_FIRST + 0x6)
+// application cannot be run more than once
+
+#define CO_E_ERRORINAPP (CO_E_FIRST + 0x7)
+// some error in the app program file
+
+#define CO_E_DLLNOTFOUND (CO_E_FIRST + 0x8)
+// dll not found
+
+#define CO_E_ERRORINDLL (CO_E_FIRST + 0x9)
+// some error in the dll file
+
+#define CO_E_WRONGOSFORAPP (CO_E_FIRST + 0xa)
+// app written for other version of OS or other OS altogether
+
+#define CO_E_OBJNOTREG (CO_E_FIRST + 0xb)
+// object is not registered
+
+#define CO_E_OBJISREG (CO_E_FIRST + 0xc)
+// object is already registered
+
+#define CO_E_OBJNOTCONNECTED (CO_E_FIRST + 0xd)
+// handler is not connected to server
+
+#define CO_E_APPDIDNTREG (CO_E_FIRST + 0xe)
+// app was launched, but didn't registered a class factory
+
+
+// ********************* ClassObject errors ********************************
+
+#define CLASS_E_NOAGGREGATION (CLASSFACTORY_E_FIRST + 0x0)
+// class does not support aggregation (or class object is remote)
+
+#define CLASS_E_CLASSNOTAVAILABLE (CLASSFACTORY_E_FIRST + 0x1)
+// dll doesn't support that class (returned from DllGetClassObject)
+
+
+// *********************** Reg.dat errors **********************************
+
+#define REGDB_E_READREGDB (REGDB_E_FIRST + 0x0)
+// some error reading the registration database
+
+#define REGDB_E_WRITEREGDB (REGDB_E_FIRST + 0x1)
+// some error reading the registration database
+
+#define REGDB_E_KEYMISSING (REGDB_E_FIRST + 0x2)
+// some error reading the registration database
+
+#define REGDB_E_INVALIDVALUE (REGDB_E_FIRST + 0x3)
+// some error reading the registration database
+
+#define REGDB_E_CLASSNOTREG (REGDB_E_FIRST + 0x4)
+// some error reading the registration database
+
+#define REGDB_E_IIDNOTREG (REGDB_E_FIRST + 0x5)
+// some error reading the registration database
+
+
+// *************************** RPC errors **********************************
+
+#define RPC_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_RPC, 0x000)
+
+// call was rejected by callee, either by MF::HandleIncomingCall or
+#define RPC_E_CALL_REJECTED (RPC_E_FIRST + 0x1)
+
+// call was canceld by call - returned by MessagePending
+// this code only occurs if MessagePending return cancel
+#define RPC_E_CALL_CANCELED (RPC_E_FIRST + 0x2)
+
+// the caller is dispatching an intertask SendMessage call and
+// can NOT call out via PostMessage
+#define RPC_E_CANTPOST_INSENDCALL (RPC_E_FIRST + 0x3)
+
+// the caller is dispatching an asynchronus call can NOT
+// make an outgoing call on behalf of this call
+#define RPC_E_CANTCALLOUT_INASYNCCALL (RPC_E_FIRST + 0x4)
+
+// the caller is not in a state where an outgoing call can be made
+// this is the case if the caller has an outstandig call and
+// another incoming call was excepted by HIC; now the caller is
+// not allowed to call out again
+#define RPC_E_CANTCALLOUT_INEXTERNALCALL (RPC_E_FIRST + 0x5)
+
+// the connection terminated or is in a bogus state
+// and can not be used any more. Other connections
+// are still valid.
+#define RPC_E_CONNECTION_TERMINATED (RPC_E_FIRST + 0x6)
+
+// the callee (server [not server application]) is not available
+// and disappeared; all connections are invalid
+#define RPC_E_SERVER_DIED (RPC_E_FIRST + 0x7)
+
+// the caller (client ) disappeared while the callee (server) was
+// processing a call
+#define RPC_E_CLIENT_DIED (RPC_E_FIRST + 0x8)
+
+// the date paket with the marshalled parameter data is
+// incorrect
+#define RPC_E_INVALID_DATAPACKET (RPC_E_FIRST + 0x9)
+
+// the call was not transmitted properly; the message queue
+// was full and was not emptied after yielding
+#define RPC_E_CANTTRANSMIT_CALL (RPC_E_FIRST + 0xa)
+
+// the client (caller) can not marshall the parameter data
+// or unmarshall the return data - low memory etc.
+#define RPC_E_CLIENT_CANTMARSHAL_DATA (RPC_E_FIRST + 0xb)
+#define RPC_E_CLIENT_CANTUNMARSHAL_DATA (RPC_E_FIRST + 0xc)
+
+// the server (caller) can not unmarshall the parameter data
+// or marshall the return data - low memory
+#define RPC_E_SERVER_CANTMARSHAL_DATA (RPC_E_FIRST + 0xd)
+#define RPC_E_SERVER_CANTUNMARSHAL_DATA (RPC_E_FIRST + 0xe)
+
+// received data are invalid; can be server or
+// client data
+#define RPC_E_INVALID_DATA (RPC_E_FIRST + 0xf)
+
+// a particular parameter is invalid and can not be un/marshalled
+#define RPC_E_INVALID_PARAMETER (RPC_E_FIRST + 0x10)
+
+// DDE conversation - no second outgoing call on same channel
+#define RPC_E_CANTCALLOUT_AGAIN (RPC_E_FIRST + 0x11)
+
+// a internal error occured
+#define RPC_E_UNEXPECTED (RPC_E_FIRST + 0xFFFF)
+
+
+/****** Globally Unique Ids *************************************************/
+
+#ifndef GUID_DEFINED
+#define GUID_DEFINED
+
+#ifdef __cplusplus
+
+struct FAR GUID
+{
+ DWORD Data1;
+ WORD Data2;
+ WORD Data3;
+ BYTE Data4[8];
+
+ BOOL operator==(const GUID& iidOther) const
+
+#ifdef WIN32
+ { return !memcmp(&Data1,&iidOther.Data1,sizeof(GUID)); }
+#else
+ { return !_fmemcmp(&Data1,&iidOther.Data1,sizeof(GUID)); }
+#endif
+ BOOL operator!=(const GUID& iidOther) const
+ { return !((*this) == iidOther); }
+};
+
+#else
+typedef struct GUID
+{
+ DWORD Data1;
+ WORD Data2;
+ WORD Data3;
+ BYTE Data4[8];
+} GUID;
+#endif
+
+#endif //GUID_DEFINED
+
+typedef GUID FAR* LPGUID;
+
+
+// macros to define byte pattern for a GUID.
+// Example: DEFINE_GUID(GUID_XXX, a, b, c, ...);
+//
+// Each dll/exe must initialize the GUIDs once. This is done in one of
+// two ways. If you are not using precompiled headers for the file(s) which
+// initializes the GUIDs, define INITGUID before including compobj.h. This
+// is how OLE builds the initialized versions of the GUIDs which are included
+// in compobj.dll.
+//
+// The alternative (which some versions of the compiler don't handle properly;
+// they wind up with the initialized GUIDs in a data, not a text segment),
+// is to use a precompiled version of compobj.h and then include initguid.h
+// after compobj.h followed by one or more of the guid defintion files.
+
+
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID CDECL FAR name
+
+#ifdef INITGUID
+#include "initguid.h"
+#endif
+
+#define DEFINE_OLEGUID(name, l, w1, w2) \
+ DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)
+
+
+// Interface ID are just a kind of GUID
+typedef GUID IID;
+typedef IID FAR* LPIID;
+#define IID_NULL GUID_NULL
+#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2)
+
+
+// Class ID are just a kind of GUID
+typedef GUID CLSID;
+typedef CLSID FAR* LPCLSID;
+#define CLSID_NULL GUID_NULL
+#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2)
+
+
+#if defined(__cplusplus)
+#define REFGUID const GUID FAR&
+#define REFIID const IID FAR&
+#define REFCLSID const CLSID FAR&
+#else
+#define REFGUID const GUID FAR* const
+#define REFIID const IID FAR* const
+#define REFCLSID const CLSID FAR* const
+#endif
+
+
+#ifndef INITGUID
+#include "coguid.h"
+#endif
+
+/****** Other value types ***************************************************/
+
+// memory context values; passed to CoGetMalloc
+typedef enum tagMEMCTX
+{
+ MEMCTX_TASK = 1, // task (private) memory
+ MEMCTX_SHARED = 2, // shared memory (between processes)
+#ifdef _MAC
+ MEMCTX_MACSYSTEM = 3, // on the mac, the system heap
+#endif
+
+ // these are mostly for internal use...
+ MEMCTX_UNKNOWN = -1, // unknown context (when asked about it)
+ MEMCTX_SAME = -2, // same context (as some other pointer)
+} MEMCTX;
+
+
+
+// class context: used to determine what scope and kind of class object to use
+// NOTE: this is a bitwise enum
+typedef enum tagCLSCTX
+{
+ CLSCTX_INPROC_SERVER = 1, // server dll (runs in same process as caller)
+ CLSCTX_INPROC_HANDLER = 2, // handler dll (runs in same process as caller)
+ CLSCTX_LOCAL_SERVER = 4 // server exe (runs on same machine; diff proc)
+} CLSCTX;
+
+#define CLSCTX_ALL (CLSCTX_INPROC_SERVER| \
+ CLSCTX_INPROC_HANDLER| \
+ CLSCTX_LOCAL_SERVER)
+
+#define CLSCTX_INPROC (CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER)
+
+#define CLSCTX_SERVER (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER)
+
+
+// class registration flags; passed to CoRegisterClassObject
+typedef enum tagREGCLS
+{
+ REGCLS_SINGLEUSE = 0, // class object only generates one instance
+ REGCLS_MULTIPLEUSE = 1, // same class object genereates multiple inst.
+ // and local automatically goes into inproc tbl.
+ REGCLS_MULTI_SEPARATE = 2, // multiple use, but separate control over each
+ // context.
+
+ // NOTE: CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE is the same as
+ // (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER), REGCLS_MULTI_SEPARATE, but
+ // not the same as CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE.
+} REGCLS;
+
+
+// interface marshaling definitions
+#define MARSHALINTERFACE_MIN 40 // minimum number of bytes for interface marshl
+
+// marshaling flags; passed to CoMarshalInterface
+typedef enum tagMSHLFLAGS
+{
+ MSHLFLAGS_NORMAL = 0, // normal marshaling via proxy/stub
+ MSHLFLAGS_TABLESTRONG = 1, // keep object alive; must explicitly release
+ MSHLFLAGS_TABLEWEAK = 2 // doesn't hold object alive; still must release
+} MSHLFLAGS;
+
+// marshal context: determines the destination context of the marshal operation
+typedef enum tagMSHCTX
+{
+ MSHCTX_LOCAL = 0, // unmarshal context is local (eg.shared memory)
+ MSHCTX_NOSHAREDMEM = 1, // unmarshal context has no shared memory access
+} MSHCTX;
+
+
+// call type used by IMessageFilter::HandleIncommingMessage
+typedef enum tagCALLTYPE
+{
+ CALLTYPE_TOPLEVEL = 1, // toplevel call - no outgoing call
+ CALLTYPE_NESTED = 2, // callback on behalf of previous outgoing call - should always handle
+ CALLTYPE_ASYNC = 3, // aysnchronous call - can NOT be rejected
+ CALLTYPE_TOPLEVEL_CALLPENDING = 4, // new toplevel call with new LID
+ CALLTYPE_ASYNC_CALLPENDING = 5 // async call - can NOT be rejected
+} CALLTYPE;
+
+typedef struct tagINTERFACEINFO
+{
+ interface IUnknown FAR *pUnk; // the pointer to the object
+ IID iid; // interface id
+ WORD wMethod; // interface methode
+} INTERFACEINFO, FAR * LPINTERFACEINFO;
+
+// status of server call - returned by IMessageFilter::HandleIncommingCall
+// and passed to IMessageFilter::RetryRejectedCall
+typedef enum tagSERVERCALL
+{
+ SERVERCALL_ISHANDLED = 0,
+ SERVERCALL_REJECTED = 1,
+ SERVERCALL_RETRYLATER = 2
+} SERVERCALL;
+
+
+// Pending type indicates the level of nesting
+typedef enum tagPENDINGTYPE
+{
+ PENDINGTYPE_TOPLEVEL = 1, // toplevel call
+ PENDINGTYPE_NESTED = 2, // nested call
+} PENDINGTYPE;
+
+// return values of MessagePending
+typedef enum tagPENDINGMSG
+{
+ PENDINGMSG_CANCELCALL = 0, // cancel the outgoing call
+ PENDINGMSG_WAITNOPROCESS = 1, // wait for the return and don't dispatch the message
+ PENDINGMSG_WAITDEFPROCESS = 2 // wait and dispatch the message
+
+} PENDINGMSG;
+
+
+// bit flags for IExternalConnection
+typedef enum tagEXTCONN
+{
+ EXTCONN_STRONG = 0x0001 // strong connection
+} EXTCONN;
+
+
+/****** IUnknown Interface **************************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IUnknown
+
+DECLARE_INTERFACE(IUnknown)
+{
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+};
+
+typedef IUnknown FAR* LPUNKNOWN;
+
+
+/****** Class Factory Interface *******************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IClassFactory
+
+DECLARE_INTERFACE_(IClassFactory, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IClassFactory methods ***
+ STDMETHOD(CreateInstance) (THIS_ LPUNKNOWN pUnkOuter,
+ REFIID riid,
+ LPVOID FAR* ppvObject) PURE;
+ STDMETHOD(LockServer) (THIS_ BOOL fLock) PURE;
+
+};
+typedef IClassFactory FAR* LPCLASSFACTORY;
+
+
+/****** Memory Allocation Interface ***************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IMalloc
+
+DECLARE_INTERFACE_(IMalloc, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IMalloc methods ***
+ STDMETHOD_(void FAR*, Alloc) (THIS_ ULONG cb) PURE;
+ STDMETHOD_(void FAR*, Realloc) (THIS_ void FAR* pv, ULONG cb) PURE;
+ STDMETHOD_(void, Free) (THIS_ void FAR* pv) PURE;
+ STDMETHOD_(ULONG, GetSize) (THIS_ void FAR* pv) PURE;
+ STDMETHOD_(int, DidAlloc) (THIS_ void FAR* pv) PURE;
+ STDMETHOD_(void, HeapMinimize) (THIS) PURE;
+};
+typedef IMalloc FAR* LPMALLOC;
+
+
+/****** IMarshal Interface ************************************************/
+
+// forward declaration for IStream; must include storage.h later to use
+#ifdef __cplusplus
+interface IStream;
+#else
+typedef interface IStream IStream;
+#endif
+typedef IStream FAR* LPSTREAM;
+
+
+#undef INTERFACE
+#define INTERFACE IMarshal
+
+DECLARE_INTERFACE_(IMarshal, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IMarshal methods ***
+ STDMETHOD(GetUnmarshalClass)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid) PURE;
+ STDMETHOD(GetMarshalSizeMax)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize) PURE;
+ STDMETHOD(MarshalInterface)(THIS_ LPSTREAM pStm, REFIID riid,
+ LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags) PURE;
+ STDMETHOD(UnmarshalInterface)(THIS_ LPSTREAM pStm, REFIID riid,
+ LPVOID FAR* ppv) PURE;
+ STDMETHOD(ReleaseMarshalData)(THIS_ LPSTREAM pStm) PURE;
+ STDMETHOD(DisconnectObject)(THIS_ DWORD dwReserved) PURE;
+};
+typedef IMarshal FAR* LPMARSHAL;
+
+
+#undef INTERFACE
+#define INTERFACE IStdMarshalInfo
+
+DECLARE_INTERFACE_(IStdMarshalInfo, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IStdMarshalInfo methods ***
+ STDMETHOD(GetClassForHandler)(THIS_ DWORD dwDestContext,
+ LPVOID pvDestContext, LPCLSID pClsid) PURE;
+};
+typedef IStdMarshalInfo FAR* LPSTDMARSHALINFO;
+
+
+/****** Message Filter Interface *******************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IMessageFilter
+
+DECLARE_INTERFACE_(IMessageFilter, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IMessageFilter methods ***
+ STDMETHOD_(DWORD, HandleInComingCall) (THIS_ DWORD dwCallType,
+ HTASK htaskCaller, DWORD dwTickCount,
+ DWORD dwReserved ) PURE;
+ STDMETHOD_(DWORD, RetryRejectedCall) (THIS_
+ HTASK htaskCallee, DWORD dwTickCount,
+ DWORD dwRejectType ) PURE;
+ STDMETHOD_(DWORD, MessagePending) (THIS_
+ HTASK htaskCallee, DWORD dwTickCount,
+ DWORD dwPendingType ) PURE;
+};
+typedef IMessageFilter FAR* LPMESSAGEFILTER;
+
+
+/****** External Connection Information ***********************************/
+
+#undef INTERFACE
+#define INTERFACE IExternalConnection
+
+DECLARE_INTERFACE_(IExternalConnection, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IExternalConnection methods ***
+ STDMETHOD_(DWORD, AddConnection) (THIS_ DWORD extconn, DWORD reserved) PURE;
+ STDMETHOD_(DWORD, ReleaseConnection) (THIS_ DWORD extconn, DWORD reserved, BOOL fLastReleaseCloses) PURE;
+};
+typedef IExternalConnection FAR* LPEXTERNALCONNECTION;
+
+
+/****** Enumerator Interfaces *********************************************/
+
+/*
+ * Since we don't use parametrized types, we put in explicit declarations
+ * of the enumerators we need.
+ */
+
+
+#undef INTERFACE
+#define INTERFACE IEnumString
+
+DECLARE_INTERFACE_(IEnumString, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumString methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt,
+ LPXSTR FAR* rgelt,
+ ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumString FAR* FAR* ppenm) PURE;
+};
+typedef IEnumString FAR* LPENUMSTRING;
+
+
+#undef INTERFACE
+#define INTERFACE IEnumUnknown
+
+DECLARE_INTERFACE_(IEnumUnknown, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumUnknown methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, LPUNKNOWN FAR* rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumUnknown FAR* FAR* ppenm) PURE;
+};
+typedef IEnumUnknown FAR* LPENUMUNKNOWN;
+
+
+/****** STD Object API Prototypes *****************************************/
+
+STDAPI_(DWORD) CoBuildVersion( VOID );
+
+/* init/uninit */
+
+STDAPI CoInitialize(LPMALLOC pMalloc);
+STDAPI_(void) CoUninitialize(void);
+STDAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC FAR* ppMalloc);
+STDAPI_(DWORD) CoGetCurrentProcess(void);
+STDAPI CoCreateStandardMalloc(DWORD memctx, IMalloc FAR* FAR* ppMalloc);
+
+
+/* register/revoke/get class objects */
+
+STDAPI CoGetClassObject(REFCLSID rclsid, DWORD dwClsContext, LPVOID pvReserved,
+ REFIID riid, LPVOID FAR* ppv);
+STDAPI CoRegisterClassObject(REFCLSID rclsid, LPUNKNOWN pUnk,
+ DWORD dwClsContext, DWORD flags, LPDWORD lpdwRegister);
+STDAPI CoRevokeClassObject(DWORD dwRegister);
+
+
+/* marshaling interface pointers */
+
+STDAPI CoMarshalInterface(LPSTREAM pStm, REFIID riid, LPUNKNOWN pUnk,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags);
+STDAPI CoUnmarshalInterface(LPSTREAM pStm, REFIID riid, LPVOID FAR* ppv);
+STDAPI CoMarshalHresult(LPSTREAM pstm, HRESULT hresult);
+STDAPI CoUnmarshalHresult(LPSTREAM pstm, HRESULT FAR * phresult);
+STDAPI CoReleaseMarshalData(LPSTREAM pStm);
+STDAPI CoDisconnectObject(LPUNKNOWN pUnk, DWORD dwReserved);
+STDAPI CoLockObjectExternal(LPUNKNOWN pUnk, BOOL fLock, BOOL fLastUnlockReleases);
+STDAPI CoGetStandardMarshal(REFIID riid, LPUNKNOWN pUnk,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags,
+ LPMARSHAL FAR* ppMarshal);
+
+STDAPI_(BOOL) CoIsHandlerConnected(LPUNKNOWN pUnk);
+STDAPI_(BOOL) CoHasStrongExternalConnections(LPUNKNOWN pUnk);
+
+/* dll loading helpers; keeps track of ref counts and unloads all on exit */
+
+STDAPI_(HINSTANCE) CoLoadLibrary(LPXSTR lpszLibName, BOOL bAutoFree);
+STDAPI_(void) CoFreeLibrary(HINSTANCE hInst);
+STDAPI_(void) CoFreeAllLibraries(void);
+STDAPI_(void) CoFreeUnusedLibraries(void);
+
+
+/* helper for creating instances */
+
+STDAPI CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
+ DWORD dwClsContext, REFIID riid, LPVOID FAR* ppv);
+
+
+/* other helpers */
+STDAPI_(BOOL) IsEqualGUID(REFGUID rguid1, REFGUID rguid2);
+STDAPI StringFromCLSID(REFCLSID rclsid, LPXSTR FAR* lplpsz);
+STDAPI CLSIDFromString(LPXSTR lpsz, LPCLSID pclsid);
+STDAPI StringFromIID(REFIID rclsid, LPXSTR FAR* lplpsz);
+STDAPI IIDFromString(LPXSTR lpsz, LPIID lpiid);
+STDAPI_(BOOL) CoIsOle1Class(REFCLSID rclsid);
+STDAPI ProgIDFromCLSID (REFCLSID clsid, LPXSTR FAR* lplpszProgID);
+STDAPI CLSIDFromProgID (LPCXSTR lpszProgID, LPCLSID lpclsid);
+STDAPI_(int) StringFromGUID2(REFGUID rguid, LPXSTR lpsz, int cbMax);
+
+STDAPI CoCreateGuid(GUID FAR *pguid);
+
+STDAPI_(BOOL) CoFileTimeToDosDateTime(
+ FILETIME FAR* lpFileTime, LPWORD lpDosDate, LPWORD lpDosTime);
+STDAPI_(BOOL) CoDosDateTimeToFileTime(
+ WORD nDosDate, WORD nDosTime, FILETIME FAR* lpFileTime);
+STDAPI CoFileTimeNow( FILETIME FAR* lpFileTime );
+
+
+STDAPI CoRegisterMessageFilter( LPMESSAGEFILTER lpMessageFilter,
+ LPMESSAGEFILTER FAR* lplpMessageFilter );
+
+
+/* TreatAs APIS */
+
+STDAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID pClsidNew);
+STDAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew);
+
+
+/* the server dlls must define their DllGetClassObject and DllCanUnloadNow
+ * to match these; the typedefs are located here to ensure all are changed at
+ * the same time.
+ */
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID FAR* ppv);
+#ifdef _MAC
+typedef STDAPICALLTYPE HRESULT (FAR* LPFNGETCLASSOBJECT) (REFCLSID, REFIID, LPVOID FAR*);
+#else
+typedef HRESULT (STDAPICALLTYPE FAR* LPFNGETCLASSOBJECT) (REFCLSID, REFIID, LPVOID FAR*);
+#endif
+
+
+STDAPI DllCanUnloadNow(void);
+#ifdef _MAC
+typedef STDAPICALLTYPE HRESULT (FAR* LPFNCANUNLOADNOW)(void);
+#else
+typedef HRESULT (STDAPICALLTYPE FAR* LPFNCANUNLOADNOW)(void);
+#endif
+
+
+/****** Debugging Helpers *************************************************/
+
+#ifdef _DEBUG
+// writes to the debug port and displays a message box
+STDAPI FnAssert(LPXSTR lpstrExpr, LPXSTR lpstrMsg, LPXSTR lpstrFileName, UINT iLine);
+#endif // _DEBUG
+
+#endif // _COMPOBJ_H_
diff --git a/private/ole32/stg/ole2flat/dvobj.h b/private/ole32/stg/ole2flat/dvobj.h
new file mode 100644
index 000000000..06a596073
--- /dev/null
+++ b/private/ole32/stg/ole2flat/dvobj.h
@@ -0,0 +1,480 @@
+/*****************************************************************************\
+* *
+* dvobj.h - Data/View object definitions *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+#if !defined( _DVOBJ_H_ )
+#define _DVOBJ_H_
+
+/****** DV value types ******************************************************/
+
+// forward type declarations
+#if defined(__cplusplus)
+interface IStorage;
+interface IStream;
+interface IAdviseSink;
+interface IMoniker;
+#else
+typedef interface IStorage IStorage;
+typedef interface IStream IStream;
+typedef interface IAdviseSink IAdviseSink;
+typedef interface IMoniker IMoniker;
+#endif
+
+typedef IStorage FAR* LPSTORAGE;
+typedef IStream FAR* LPSTREAM;
+typedef IAdviseSink FAR* LPADVISESINK;
+typedef IMoniker FAR* LPMONIKER;
+
+
+#if !defined(_MAC)
+typedef WORD CLIPFORMAT;
+#else
+typedef unsigned long CLIPFORMAT; // ResType
+#endif
+typedef CLIPFORMAT FAR* LPCLIPFORMAT;
+
+
+// Data/View aspect; specifies the desired aspect of the object when
+// drawing or getting data.
+typedef enum tagDVASPECT
+{
+ DVASPECT_CONTENT = 1,
+ DVASPECT_THUMBNAIL = 2,
+ DVASPECT_ICON = 4,
+ DVASPECT_DOCPRINT = 8
+} DVASPECT;
+
+
+// Data/View target device; determines the device for drawing or gettting data
+typedef struct FARSTRUCT tagDVTARGETDEVICE
+{
+ DWORD tdSize;
+ WORD tdDriverNameOffset;
+ WORD tdDeviceNameOffset;
+ WORD tdPortNameOffset;
+ WORD tdExtDevmodeOffset;
+ BYTE tdData[1];
+} DVTARGETDEVICE;
+
+
+// Format, etc.; completely specifices the kind of data desired, including tymed
+typedef struct FARSTRUCT tagFORMATETC
+{
+ CLIPFORMAT cfFormat;
+ DVTARGETDEVICE FAR* ptd;
+ DWORD dwAspect;
+ LONG lindex;
+ DWORD tymed;
+} FORMATETC, FAR* LPFORMATETC;
+
+
+// TYpes of storage MEDiums; determines how data is stored or passed around
+typedef enum tagTYMED
+{
+ TYMED_HGLOBAL = 1,
+ TYMED_FILE = 2,
+ TYMED_ISTREAM = 4,
+ TYMED_ISTORAGE = 8,
+ TYMED_GDI = 16,
+ TYMED_MFPICT = 32,
+ TYMED_NULL = 0
+} TYMED;
+
+
+// DATA format DIRection
+typedef enum tagDATADIR
+{
+ DATADIR_GET = 1,
+ DATADIR_SET = 2,
+} DATADIR;
+
+
+// SToraGe MEDIUM; a block of data on a particular medium
+typedef struct FARSTRUCT tagSTGMEDIUM
+{
+ DWORD tymed;
+ union
+ {
+ HANDLE hGlobal;
+ LPXSTR lpszFileName;
+ IStream FAR* pstm;
+ IStorage FAR* pstg;
+ }
+#ifdef NONAMELESSUNION
+ u // add a tag when name less unions not supported
+#endif
+ ;
+ IUnknown FAR* pUnkForRelease;
+} STGMEDIUM, FAR* LPSTGMEDIUM;
+
+
+// Advise Flags
+typedef enum tagADVF
+{
+ ADVF_NODATA = 1,
+ ADVF_PRIMEFIRST = 2,
+ ADVF_ONLYONCE = 4,
+ ADVF_DATAONSTOP = 64,
+ ADVFCACHE_NOHANDLER = 8,
+ ADVFCACHE_FORCEBUILTIN = 16,
+ ADVFCACHE_ONSAVE = 32
+} ADVF;
+
+
+// Stats for data; used by several enumerations and by at least one
+// implementation of IDataAdviseHolder; if a field is not used, it
+// will be NULL.
+typedef struct FARSTRUCT tagSTATDATA
+{ // field used by:
+ FORMATETC formatetc; // EnumAdvise, EnumData (cache), EnumFormats
+ DWORD advf; // EnumAdvise, EnumData (cache)
+ IAdviseSink FAR* pAdvSink; // EnumAdvise
+ DWORD dwConnection; // EnumAdvise
+} STATDATA;
+
+typedef STATDATA FAR* LPSTATDATA;
+
+
+
+/****** DV Interfaces ***************************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IEnumFORMATETC
+
+DECLARE_INTERFACE_(IEnumFORMATETC, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumFORMATETC methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, FORMATETC FAR * rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumFORMATETC FAR* FAR* ppenum) PURE;
+};
+typedef IEnumFORMATETC FAR* LPENUMFORMATETC;
+
+
+#undef INTERFACE
+#define INTERFACE IEnumSTATDATA
+
+DECLARE_INTERFACE_(IEnumSTATDATA, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG, AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG, Release) (THIS) PURE;
+
+ // *** IEnumSTATDATA methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, STATDATA FAR * rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumSTATDATA FAR* FAR* ppenum) PURE;
+};
+typedef IEnumSTATDATA FAR* LPENUMSTATDATA;
+
+
+
+#undef INTERFACE
+#define INTERFACE IDataObject
+
+#define DATA_E_FORMATETC DV_E_FORMATETC
+#define DATA_S_SAMEFORMATETC (DATA_S_FIRST + 0)
+
+DECLARE_INTERFACE_(IDataObject, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG, Release) (THIS) PURE;
+
+ // *** IDataObject methods ***
+ STDMETHOD(GetData) (THIS_ LPFORMATETC pformatetcIn,
+ LPSTGMEDIUM pmedium ) PURE;
+ STDMETHOD(GetDataHere) (THIS_ LPFORMATETC pformatetc,
+ LPSTGMEDIUM pmedium ) PURE;
+ STDMETHOD(QueryGetData) (THIS_ LPFORMATETC pformatetc ) PURE;
+ STDMETHOD(GetCanonicalFormatEtc) (THIS_ LPFORMATETC pformatetc,
+ LPFORMATETC pformatetcOut) PURE;
+ STDMETHOD(SetData) (THIS_ LPFORMATETC pformatetc, STGMEDIUM FAR * pmedium,
+ BOOL fRelease) PURE;
+ STDMETHOD(EnumFormatEtc) (THIS_ DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenumFormatEtc) PURE;
+
+ STDMETHOD(DAdvise) (THIS_ FORMATETC FAR* pFormatetc, DWORD advf,
+ LPADVISESINK pAdvSink, DWORD FAR* pdwConnection) PURE;
+ STDMETHOD(DUnadvise) (THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumDAdvise) (THIS_ LPENUMSTATDATA FAR* ppenumAdvise) PURE;
+};
+typedef IDataObject FAR* LPDATAOBJECT;
+
+
+
+#undef INTERFACE
+#define INTERFACE IViewObject
+
+#define VIEW_E_DRAW (VIEW_E_FIRST)
+#define E_DRAW VIEW_E_DRAW
+
+#define VIEW_S_ALREADY_FROZEN (VIEW_S_FIRST)
+
+DECLARE_INTERFACE_(IViewObject, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IViewObject methods ***
+ STDMETHOD(Draw) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev,
+ HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ BOOL (CALLBACK * pfnContinue) (DWORD),
+ DWORD dwContinue) PURE;
+
+ STDMETHOD(GetColorSet) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev,
+ LPLOGPALETTE FAR* ppColorSet) PURE;
+
+ STDMETHOD(Freeze)(THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect,
+ DWORD FAR* pdwFreeze) PURE;
+ STDMETHOD(Unfreeze) (THIS_ DWORD dwFreeze) PURE;
+ STDMETHOD(SetAdvise) (THIS_ DWORD aspects, DWORD advf,
+ LPADVISESINK pAdvSink) PURE;
+ STDMETHOD(GetAdvise) (THIS_ DWORD FAR* pAspects, DWORD FAR* pAdvf,
+ LPADVISESINK FAR* ppAdvSink) PURE;
+};
+typedef IViewObject FAR* LPVIEWOBJECT;
+
+
+#undef INTERFACE
+#define INTERFACE IViewObject2
+
+DECLARE_INTERFACE_(IViewObject2, IViewObject)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IViewObject methods ***
+ STDMETHOD(Draw) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev,
+ HDC hdcDraw,
+ LPCRECTL lprcBounds,
+ LPCRECTL lprcWBounds,
+ BOOL (CALLBACK * pfnContinue) (DWORD),
+ DWORD dwContinue) PURE;
+
+ STDMETHOD(GetColorSet) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect, DVTARGETDEVICE FAR * ptd,
+ HDC hicTargetDev,
+ LPLOGPALETTE FAR* ppColorSet) PURE;
+
+ STDMETHOD(Freeze)(THIS_ DWORD dwDrawAspect, LONG lindex,
+ void FAR* pvAspect,
+ DWORD FAR* pdwFreeze) PURE;
+ STDMETHOD(Unfreeze) (THIS_ DWORD dwFreeze) PURE;
+ STDMETHOD(SetAdvise) (THIS_ DWORD aspects, DWORD advf,
+ LPADVISESINK pAdvSink) PURE;
+ STDMETHOD(GetAdvise) (THIS_ DWORD FAR* pAspects, DWORD FAR* pAdvf,
+ LPADVISESINK FAR* ppAdvSink) PURE;
+
+ // *** IViewObject2 methods ***
+ STDMETHOD(GetExtent) (THIS_ DWORD dwDrawAspect, LONG lindex,
+ DVTARGETDEVICE FAR * ptd, LPSIZEL lpsizel) PURE;
+
+};
+typedef IViewObject2 FAR* LPVIEWOBJECT2;
+
+
+#undef INTERFACE
+#define INTERFACE IAdviseSink
+
+DECLARE_INTERFACE_(IAdviseSink, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IAdviseSink methods ***
+ STDMETHOD_(void,OnDataChange)(THIS_ FORMATETC FAR* pFormatetc,
+ STGMEDIUM FAR* pStgmed) PURE;
+ STDMETHOD_(void,OnViewChange)(THIS_ DWORD dwAspect, LONG lindex) PURE;
+ STDMETHOD_(void,OnRename)(THIS_ LPMONIKER pmk) PURE;
+ STDMETHOD_(void,OnSave)(THIS) PURE;
+ STDMETHOD_(void,OnClose)(THIS) PURE;
+};
+typedef IAdviseSink FAR* LPADVISESINK;
+
+
+
+#undef INTERFACE
+#define INTERFACE IAdviseSink2
+
+DECLARE_INTERFACE_(IAdviseSink2, IAdviseSink)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IAdviseSink methods ***
+ STDMETHOD_(void,OnDataChange)(THIS_ FORMATETC FAR* pFormatetc,
+ STGMEDIUM FAR* pStgmed) PURE;
+ STDMETHOD_(void,OnViewChange)(THIS_ DWORD dwAspect, LONG lindex) PURE;
+ STDMETHOD_(void,OnRename)(THIS_ LPMONIKER pmk) PURE;
+ STDMETHOD_(void,OnSave)(THIS) PURE;
+ STDMETHOD_(void,OnClose)(THIS) PURE;
+
+ // *** IAdviseSink2 methods ***
+ STDMETHOD_(void,OnLinkSrcChange)(THIS_ LPMONIKER pmk) PURE;
+};
+typedef IAdviseSink2 FAR* LPADVISESINK2;
+
+
+
+#undef INTERFACE
+#define INTERFACE IDataAdviseHolder
+
+DECLARE_INTERFACE_(IDataAdviseHolder, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IDataAdviseHolder methods ***
+ STDMETHOD(Advise)(THIS_ LPDATAOBJECT pDataObject, FORMATETC FAR* pFetc,
+ DWORD advf, LPADVISESINK pAdvise, DWORD FAR* pdwConnection) PURE;
+ STDMETHOD(Unadvise)(THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumAdvise)(THIS_ LPENUMSTATDATA FAR* ppenumAdvise) PURE;
+
+ STDMETHOD(SendOnDataChange)(THIS_ LPDATAOBJECT pDataObject, DWORD dwReserved, DWORD advf) PURE;
+};
+typedef IDataAdviseHolder FAR* LPDATAADVISEHOLDER;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleCache
+
+#define CACHE_E_NOCACHE_UPDATED (CACHE_E_FIRST)
+
+#define CACHE_S_FORMATETC_NOTSUPPORTED (CACHE_S_FIRST)
+#define CACHE_S_SAMECACHE (CACHE_S_FIRST+1)
+#define CACHE_S_SOMECACHES_NOTUPDATED (CACHE_S_FIRST+2)
+
+
+DECLARE_INTERFACE_(IOleCache, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleCache methods ***
+ STDMETHOD(Cache) (THIS_ LPFORMATETC lpFormatetc, DWORD advf, LPDWORD lpdwConnection) PURE;
+ STDMETHOD(Uncache) (THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumCache) (THIS_ LPENUMSTATDATA FAR* ppenumStatData) PURE;
+ STDMETHOD(InitCache) (THIS_ LPDATAOBJECT pDataObject) PURE;
+ STDMETHOD(SetData) (THIS_ LPFORMATETC pformatetc, STGMEDIUM FAR * pmedium,
+ BOOL fRelease) PURE;
+};
+typedef IOleCache FAR* LPOLECACHE;
+
+
+
+// Cache update Flags
+
+#define UPDFCACHE_NODATACACHE 0x00000001
+#define UPDFCACHE_ONSAVECACHE 0x00000002
+#define UPDFCACHE_ONSTOPCACHE 0x00000004
+#define UPDFCACHE_NORMALCACHE 0x00000008
+#define UPDFCACHE_IFBLANK 0x00000010
+#define UPDFCACHE_ONLYIFBLANK 0x80000000
+
+#define UPDFCACHE_IFBLANKORONSAVECACHE (UPDFCACHE_IFBLANK | UPDFCACHE_ONSAVECACHE )
+#define UPDFCACHE_ALL (~UPDFCACHE_ONLYIFBLANK)
+#define UPDFCACHE_ALLBUTNODATACACHE (UPDFCACHE_ALL & ~UPDFCACHE_NODATACACHE)
+
+
+// IOleCache2::DiscardCache options
+typedef enum tagDISCARDCACHE
+{
+ DISCARDCACHE_SAVEIFDIRTY = 0, // Save all dirty cache before discarding
+ DISCARDCACHE_NOSAVE = 1 // Don't save dirty caches before
+ // discarding
+} DISCARDCACHE;
+
+
+#undef INTERFACE
+#define INTERFACE IOleCache2
+
+DECLARE_INTERFACE_(IOleCache2, IOleCache)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG, Release) (THIS) PURE;
+
+ // *** IOleCache methods ***
+ STDMETHOD(Cache) (THIS_ LPFORMATETC lpFormatetc, DWORD advf, LPDWORD lpdwConnection) PURE;
+ STDMETHOD(Uncache) (THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumCache) (THIS_ LPENUMSTATDATA FAR* ppenumStatData) PURE;
+ STDMETHOD(InitCache) (THIS_ LPDATAOBJECT pDataObject) PURE;
+ STDMETHOD(SetData) (THIS_ LPFORMATETC pformatetc, STGMEDIUM FAR * pmedium,
+ BOOL fRelease) PURE;
+
+ // *** IOleCache2 methods ***
+ STDMETHOD(UpdateCache) (THIS_ LPDATAOBJECT pDataObject, DWORD grfUpdf,
+ LPVOID pReserved) PURE;
+ STDMETHOD(DiscardCache) (THIS_ DWORD dwDiscardOptions) PURE;
+
+};
+typedef IOleCache2 FAR* LPOLECACHE2;
+
+
+#undef INTERFACE
+#define INTERFACE IOleCacheControl
+
+DECLARE_INTERFACE_(IOleCacheControl, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG, Release) (THIS) PURE;
+
+ // *** IDataObject methods ***
+ STDMETHOD(OnRun) (THIS_ LPDATAOBJECT pDataObject) PURE;
+ STDMETHOD(OnStop) (THIS) PURE;
+};
+typedef IOleCacheControl FAR* LPOLECACHECONTROL;
+
+
+
+/****** DV APIs ***********************************************************/
+
+
+STDAPI CreateDataAdviseHolder(LPDATAADVISEHOLDER FAR* ppDAHolder);
+
+STDAPI CreateDataCache(LPUNKNOWN pUnkOuter, REFCLSID rclsid,
+ REFIID iid, LPVOID FAR* ppv);
+
+#endif // _DVOBJ_H_
diff --git a/private/ole32/stg/ole2flat/initguid.h b/private/ole32/stg/ole2flat/initguid.h
new file mode 100644
index 000000000..76b946e7f
--- /dev/null
+++ b/private/ole32/stg/ole2flat/initguid.h
@@ -0,0 +1,38 @@
+/*****************************************************************************\
+* *
+* initguid.h - Definitions for controlling GUID initialization *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+// Include after compobj.h to enable GUID initialization. This
+// must be done once per exe/dll.
+//
+// After this file, include one or more of the GUID definition files.
+//
+// NOTE: ole2.lib contains references to all GUIDs defined by OLE.
+
+#ifndef DEFINE_GUID
+#pragma error "initguid: must include compobj.h first."
+#endif
+
+#undef DEFINE_GUID
+
+#ifdef _MAC
+#define __based(a)
+#endif
+
+#ifdef WIN32
+#define __based(a)
+#endif
+
+#ifdef __TURBOC__
+#define __based(a)
+#endif
+
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID CDECL __based(__segname("_CODE")) name \
+ = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
diff --git a/private/ole32/stg/ole2flat/moniker.h b/private/ole32/stg/ole2flat/moniker.h
new file mode 100644
index 000000000..4681bdb46
--- /dev/null
+++ b/private/ole32/stg/ole2flat/moniker.h
@@ -0,0 +1,248 @@
+/*****************************************************************************\
+* *
+* moniker.h - Moniker and related interfaces and APIs *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#if !defined( _MONIKER_H_ )
+#define _MONIKER_H_
+
+#define MK_E_CONNECTMANUALLY MK_E_FIRST
+#define MK_E_EXCEEDEDDEADLINE (MK_E_FIRST + 1)
+#define MK_E_NEEDGENERIC (MK_E_FIRST + 2)
+#define MK_E_UNAVAILABLE (MK_E_FIRST + 3)
+#define MK_E_SYNTAX (MK_E_FIRST + 4)
+#define MK_E_NOOBJECT (MK_E_FIRST + 5)
+#define MK_E_INVALIDEXTENSION (MK_E_FIRST + 6)
+#define MK_E_INTERMEDIATEINTERFACENOTSUPPORTED (MK_E_FIRST + 7)
+#define MK_E_NOTBINDABLE (MK_E_FIRST + 8)
+#define MK_E_NOTBOUND (MK_E_FIRST + 9)
+ // called IBindCtx->RevokeObjectBound for an
+ // object which was not bound
+#define MK_E_CANTOPENFILE (MK_E_FIRST + 10)
+#define MK_E_MUSTBOTHERUSER (MK_E_FIRST + 11)
+#define MK_E_NOINVERSE (MK_E_FIRST + 12)
+#define MK_E_NOSTORAGE (MK_E_FIRST + 13)
+#define MK_E_NOPREFIX (MK_E_FIRST + 14)
+
+
+// reserved MK_S_FIRST
+// reserved (MK_S_FIRST + 1)
+#define MK_S_REDUCED_TO_SELF (MK_S_FIRST + 2)
+// reserved (MK_S_FIRST + 3)
+#define MK_S_ME (MK_S_FIRST + 4)
+#define MK_S_HIM (MK_S_FIRST + 5)
+#define MK_S_US (MK_S_FIRST + 6)
+#define MK_S_MONIKERALREADYREGISTERED (MK_S_FIRST + 7)
+
+
+// bind options; variable sized
+typedef struct FARSTRUCT tagBIND_OPTS
+{
+ DWORD cbStruct; // sizeof(BIND_OPTS)
+ DWORD grfFlags;
+ DWORD grfMode;
+ DWORD dwTickCountDeadline;
+} BIND_OPTS, FAR* LPBIND_OPTS;
+
+
+// bind flags; controls binding; stored in bind options above
+typedef enum
+{
+ BIND_MAYBOTHERUSER = 1,
+ BIND_JUSTTESTEXISTENCE = 2
+} BIND_FLAGS;
+
+
+// system moniker types; returned from IsSystemMoniker.
+typedef enum tagMKSYS
+{
+ MKSYS_NONE = 0,
+ MKSYS_GENERICCOMPOSITE = 1,
+ MKSYS_FILEMONIKER = 2,
+ MKSYS_ANTIMONIKER = 3,
+ MKSYS_ITEMMONIKER = 4,
+ MKSYS_POINTERMONIKER = 5
+}MKSYS;
+
+
+// bit wise enum to control how much reduction takes place.
+typedef enum tagMKREDUCE
+{
+ MKRREDUCE_ONE = 3<<16,
+ MKRREDUCE_TOUSER = 2<<16,
+ MKRREDUCE_THROUGHUSER = 1<<16,
+ MKRREDUCE_ALL = 0
+} MKRREDUCE;
+
+
+#if defined(__cplusplus)
+interface IEnumMoniker;
+interface IRunningObjectTable;
+#else
+typedef interface IEnumMoniker IEnumMoniker;
+typedef interface IRunningObjectTable IRunningObjectTable;
+#endif
+
+typedef IEnumMoniker FAR* LPENUMMONIKER;
+typedef IRunningObjectTable FAR* LPRUNNINGOBJECTTABLE;
+
+
+
+#undef INTERFACE
+#define INTERFACE IBindCtx
+
+DECLARE_INTERFACE_(IBindCtx, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IBindCtx methods ***
+ STDMETHOD(RegisterObjectBound) (THIS_ LPUNKNOWN punk) PURE;
+ STDMETHOD(RevokeObjectBound) (THIS_ LPUNKNOWN punk) PURE;
+ STDMETHOD(ReleaseBoundObjects) (THIS) PURE;
+
+ STDMETHOD(SetBindOptions) (THIS_ LPBIND_OPTS pbindopts) PURE;
+ STDMETHOD(GetBindOptions) (THIS_ LPBIND_OPTS pbindopts) PURE;
+ STDMETHOD(GetRunningObjectTable) (THIS_ LPRUNNINGOBJECTTABLE FAR*
+ pprot) PURE;
+ STDMETHOD(RegisterObjectParam) (THIS_ LPXSTR lpszKey, LPUNKNOWN punk) PURE;
+ STDMETHOD(GetObjectParam) (THIS_ LPXSTR lpszKey, LPUNKNOWN FAR* ppunk) PURE;
+ STDMETHOD(EnumObjectParam) (THIS_ LPENUMSTRING FAR* ppenum) PURE;
+ STDMETHOD(RevokeObjectParam) (THIS_ LPXSTR lpszKey) PURE;
+};
+typedef IBindCtx FAR* LPBC;
+typedef IBindCtx FAR* LPBINDCTX;
+
+
+
+#undef INTERFACE
+#define INTERFACE IMoniker
+
+DECLARE_INTERFACE_(IMoniker, IPersistStream)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+
+ // *** IPersistStream methods ***
+ STDMETHOD(IsDirty) (THIS) PURE;
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm) PURE;
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty) PURE;
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR * pcbSize) PURE;
+
+ // *** IMoniker methods ***
+ STDMETHOD(BindToObject) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riidResult, LPVOID FAR* ppvResult) PURE;
+ STDMETHOD(BindToStorage) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD(Reduce) (THIS_ LPBC pbc, DWORD dwReduceHowFar, LPMONIKER FAR*
+ ppmkToLeft, LPMONIKER FAR * ppmkReduced) PURE;
+ STDMETHOD(ComposeWith) (THIS_ LPMONIKER pmkRight, BOOL fOnlyIfNotGeneric,
+ LPMONIKER FAR* ppmkComposite) PURE;
+ STDMETHOD(Enum) (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker)
+ PURE;
+ STDMETHOD(IsEqual) (THIS_ LPMONIKER pmkOtherMoniker) PURE;
+ STDMETHOD(Hash) (THIS_ LPDWORD pdwHash) PURE;
+ STDMETHOD(IsRunning) (THIS_ LPBC pbc, LPMONIKER pmkToLeft, LPMONIKER
+ pmkNewlyRunning) PURE;
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ FILETIME FAR* pfiletime) PURE;
+ STDMETHOD(Inverse) (THIS_ LPMONIKER FAR* ppmk) PURE;
+ STDMETHOD(CommonPrefixWith) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkPrefix) PURE;
+ STDMETHOD(RelativePathTo) (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
+ ppmkRelPath) PURE;
+ STDMETHOD(GetDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPXSTR FAR* lplpszDisplayName) PURE;
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPMONIKER pmkToLeft,
+ LPXSTR lpszDisplayName, ULONG FAR* pchEaten,
+ LPMONIKER FAR* ppmkOut) PURE;
+ STDMETHOD(IsSystemMoniker) (THIS_ LPDWORD pdwMksys) PURE;
+};
+typedef IMoniker FAR* LPMONIKER;
+
+
+// IRunningObjectTable::Register flags
+#define ROTFLAGS_REGISTRATIONKEEPSALIVE 1
+
+#undef INTERFACE
+#define INTERFACE IRunningObjectTable
+
+DECLARE_INTERFACE_(IRunningObjectTable, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IRunningObjectTable methods ***
+ STDMETHOD(Register) (THIS_ DWORD grfFlags, LPUNKNOWN punkObject,
+ LPMONIKER pmkObjectName, DWORD FAR * pdwRegister) PURE;
+ STDMETHOD(Revoke) (THIS_ DWORD dwRegister) PURE;
+ STDMETHOD(IsRunning) (THIS_ LPMONIKER pmkObjectName) PURE;
+ STDMETHOD(GetObject) (THIS_ LPMONIKER pmkObjectName,
+ LPUNKNOWN FAR* ppunkObject) PURE;
+ STDMETHOD(NoteChangeTime) (THIS_ DWORD dwRegister, FILETIME FAR * pfiletime) PURE;
+ STDMETHOD(GetTimeOfLastChange) (THIS_ LPMONIKER pmkObjectName, FILETIME FAR * pfiletime) PURE;
+ STDMETHOD(EnumRunning) (THIS_ LPENUMMONIKER FAR * ppenumMoniker ) PURE;
+};
+typedef IRunningObjectTable FAR* LPRUNNINGOBJECTTABLE;
+
+
+
+#undef INTERFACE
+#define INTERFACE IEnumMoniker
+
+DECLARE_INTERFACE_(IEnumMoniker, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumOleDataObject methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, LPMONIKER FAR* rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumMoniker FAR* FAR* ppenm) PURE;
+};
+typedef IEnumMoniker FAR* LPENUMMONIKER;
+
+
+
+
+STDAPI BindMoniker(LPMONIKER pmk, DWORD grfOpt, REFIID iidResult, LPVOID FAR* ppvResult);
+STDAPI MkParseDisplayName(LPBC pbc, LPXSTR szUserName,
+ ULONG FAR * pchEaten, LPMONIKER FAR * ppmk);
+STDAPI MonikerRelativePathTo(LPMONIKER pmkSrc, LPMONIKER pmkDest, LPMONIKER
+ FAR* ppmkRelPath, BOOL fCalledFromMethod);
+STDAPI MonikerCommonPrefixWith(LPMONIKER pmkThis, LPMONIKER pmkOther,
+ LPMONIKER FAR* ppmkCommon);
+STDAPI CreateBindCtx(DWORD reserved, LPBC FAR* ppbc);
+STDAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest,
+ LPMONIKER FAR* ppmkComposite);
+STDAPI GetClassFile (LPCXSTR szFilename, CLSID FAR* pclsid);
+
+STDAPI CreateFileMoniker(LPXSTR lpszPathName, LPMONIKER FAR* ppmk);
+STDAPI CreateItemMoniker(LPXSTR lpszDelim, LPXSTR lpszItem,
+ LPMONIKER FAR* ppmk);
+STDAPI CreateAntiMoniker(LPMONIKER FAR* ppmk);
+STDAPI CreatePointerMoniker(LPUNKNOWN punk, LPMONIKER FAR* ppmk);
+
+STDAPI GetRunningObjectTable( DWORD reserved, LPRUNNINGOBJECTTABLE FAR* pprot);
+
+
+#endif // _MONIKER_H_
diff --git a/private/ole32/stg/ole2flat/ole2.h b/private/ole32/stg/ole2flat/ole2.h
new file mode 100644
index 000000000..936940c39
--- /dev/null
+++ b/private/ole32/stg/ole2flat/ole2.h
@@ -0,0 +1,1342 @@
+/*****************************************************************************\
+* *
+* ole2.h - Main OLE2 header; includes all subcomponents *
+* *
+* OLE Version 2.01 for Win16 and Win32 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#if !defined( _OLE2_H_ )
+#define _OLE2_H_
+
+#ifndef RC_INVOKED
+#pragma warning(disable:4001)
+#endif /* RC_INVOKED */
+
+#include <string.h>
+
+/****** Standard Object Definitions *****************************************/
+
+#include <compobj.h>
+
+
+// *************** FACILITY_ITF scodes common to all interfaces ************
+//
+// By convention, OLE interfaces divide the FACILITY_ITF range of errors
+// into nonoverlapping subranges. If an interface returns a FACILITY_ITF
+// scode, it must be from the range associated with that interface or from
+// the shared range: OLE_E_FIRST...OLE_E_LAST.
+//
+
+// error codes
+
+#define OLE_E_OLEVERB (OLE_E_FIRST)
+// invalid OLEVERB structure
+
+#define OLE_E_ADVF (OLE_E_FIRST+1)
+// invalid advise flags
+
+#define OLE_E_ENUM_NOMORE (OLE_E_FIRST+2)
+// you can't enuemrate any more, because the associated data is missing
+
+#define OLE_E_ADVISENOTSUPPORTED (OLE_E_FIRST+3)
+// this implementation doesn't take advises
+
+#define OLE_E_NOCONNECTION (OLE_E_FIRST+4)
+// there is no connection for this connection id
+
+#define OLE_E_NOTRUNNING (OLE_E_FIRST+5)
+// need run the object to perform this operation
+
+#define OLE_E_NOCACHE (OLE_E_FIRST+6)
+// there is no cache to operate on
+
+#define OLE_E_BLANK (OLE_E_FIRST+7)
+// Uninitialized object
+
+#define OLE_E_CLASSDIFF (OLE_E_FIRST+8)
+// linked object's source class has changed
+
+#define OLE_E_CANT_GETMONIKER (OLE_E_FIRST+9)
+// not able to get the moniker of the object
+
+#define OLE_E_CANT_BINDTOSOURCE (OLE_E_FIRST+10)
+// not able to bind to the source
+
+#define OLE_E_STATIC (OLE_E_FIRST+11)
+// object is static, operation not allowed
+
+#define OLE_E_PROMPTSAVECANCELLED (OLE_E_FIRST+12)
+// user cancelled out of save dialog
+
+#define OLE_E_INVALIDRECT (OLE_E_FIRST+13)
+// invalid rectangle
+
+#define OLE_E_WRONGCOMPOBJ (OLE_E_FIRST+14)
+// compobj.dll is too old for the ole2.dll initialized
+
+#define OLE_E_INVALIDHWND (OLE_E_FIRST+15)
+// invalid window handle
+
+#define OLE_E_NOT_INPLACEACTIVE (OLE_E_FIRST+16)
+// object is not in any of the inplace active states
+
+#define OLE_E_CANTCONVERT (OLE_E_FIRST+17)
+// not able to convert the object
+
+#define OLE_E_NOSTORAGE (OLE_E_FIRST+18)
+// not able to perform the operation because object is not given storage yet.
+
+
+#define DVGEN_E_FIRST (OLE_E_FIRST+100)
+
+#define DV_E_FORMATETC (DVGEN_E_FIRST)
+// invalid FORMATETC structure
+
+#define DV_E_DVTARGETDEVICE (DVGEN_E_FIRST+1)
+// invalid DVTARGETDEVICE structure
+
+#define DV_E_STGMEDIUM (DVGEN_E_FIRST+2)
+// invalid STDGMEDIUM structure
+
+#define DV_E_STATDATA (DVGEN_E_FIRST+3)
+// invalid STATDATA structure
+
+#define DV_E_LINDEX (DVGEN_E_FIRST+4)
+// invalid lindex
+
+#define DV_E_TYMED (DVGEN_E_FIRST+5)
+// invalid tymed
+
+#define DV_E_CLIPFORMAT (DVGEN_E_FIRST+6)
+// invalid clipboard format
+
+#define DV_E_DVASPECT (DVGEN_E_FIRST+7)
+// invalid aspect(s)
+
+#define DV_E_DVTARGETDEVICE_SIZE (DVGEN_E_FIRST+8)
+// tdSize paramter of the DVTARGETDEVICE structure is invalid
+
+#define DV_E_NOIVIEWOBJECT (DVGEN_E_FIRST+9)
+// object doesn't support IViewObject interface
+
+
+// Success codes
+
+#define OLE_S_USEREG (OLE_S_FIRST)
+// use the reg database to provide the requested info
+
+#define OLE_S_STATIC (OLE_S_FIRST+1)
+// success, but static
+
+#define OLE_S_MAC_CLIPFORMAT (OLE_S_FIRST+2)
+// macintosh clipboard format
+
+//*************************** Interface or API specific scodes *************
+
+// Errors for OleConvertOLESTREAMToIStorage and OleConvertIStorageToOLESTREAM
+
+// OLESTREAM Get method failed
+#define CONVERT10_E_OLESTREAM_GET (CONVERT10_E_FIRST + 0)
+
+// OLESTREAM Put method failed
+#define CONVERT10_E_OLESTREAM_PUT (CONVERT10_E_FIRST + 1)
+
+// Contents of the OLESTREAM not in correct format
+#define CONVERT10_E_OLESTREAM_FMT (CONVERT10_E_FIRST + 2)
+
+// There was in an error in a Windows GDI call while converting the bitmap
+// to a DIB.
+#define CONVERT10_E_OLESTREAM_BITMAP_TO_DIB (CONVERT10_E_FIRST + 3)
+
+// Contents of the IStorage not in correct format
+#define CONVERT10_E_STG_FMT (CONVERT10_E_FIRST + 4)
+
+// Contents of IStorage is missing one of the standard streams ("\1CompObj",
+// "\1Ole", "\2OlePres000"). This may be the storage for a DLL object, or a
+// class that does not use the def handler.
+#define CONVERT10_E_STG_NO_STD_STREAM (CONVERT10_E_FIRST + 5)
+
+// There was in an error in a Windows GDI call while converting the DIB
+// to a bitmap.
+#define CONVERT10_E_STG_DIB_TO_BITMAP (CONVERT10_E_FIRST + 6)
+
+
+// Returned by either API, this scode indicates that the original object
+// had no presentation, therefore the converted object does not either.
+#define CONVERT10_S_NO_PRESENTATION (CONVERT10_S_FIRST + 0)
+
+
+// Errors for Clipboard functions
+
+// OpenClipboard Failed
+#define CLIPBRD_E_CANT_OPEN (CLIPBRD_E_FIRST + 0)
+
+// EmptyClipboard Failed
+#define CLIPBRD_E_CANT_EMPTY (CLIPBRD_E_FIRST + 1)
+
+// SetClipboard Failed
+#define CLIPBRD_E_CANT_SET (CLIPBRD_E_FIRST + 2)
+
+// Data on clipboard is invalid
+#define CLIPBRD_E_BAD_DATA (CLIPBRD_E_FIRST + 3)
+
+// CloseClipboard Failed
+#define CLIPBRD_E_CANT_CLOSE (CLIPBRD_E_FIRST + 4)
+
+
+/****** OLE value types *****************************************************/
+
+/* rendering options */
+typedef enum tagOLERENDER
+{
+ OLERENDER_NONE = 0,
+ OLERENDER_DRAW = 1,
+ OLERENDER_FORMAT = 2,
+ OLERENDER_ASIS = 3
+} OLERENDER;
+typedef OLERENDER FAR* LPOLERENDER;
+
+// OLE verb; returned by IEnumOLEVERB
+typedef struct FARSTRUCT tagOLEVERB
+{
+ LONG lVerb;
+ LPXSTR lpszVerbName;
+ DWORD fuFlags;
+ DWORD grfAttribs;
+} OLEVERB, FAR* LPOLEVERB;
+
+
+// Bitwise verb attributes used in OLEVERB.grfAttribs
+typedef enum tagOLEVERBATTRIB // bitwise
+{
+ OLEVERBATTRIB_NEVERDIRTIES = 1,
+ OLEVERBATTRIB_ONCONTAINERMENU = 2
+} OLEVERBATTRIB;
+
+
+// IOleObject::GetUserType optons; determines which form of the string to use
+typedef enum tagUSERCLASSTYPE
+{
+ USERCLASSTYPE_FULL = 1,
+ USERCLASSTYPE_SHORT= 2,
+ USERCLASSTYPE_APPNAME= 3,
+} USERCLASSTYPE;
+
+
+// bits returned from IOleObject::GetMistStatus
+typedef enum tagOLEMISC // bitwise
+{
+ OLEMISC_RECOMPOSEONRESIZE = 1,
+ OLEMISC_ONLYICONIC = 2,
+ OLEMISC_INSERTNOTREPLACE = 4,
+ OLEMISC_STATIC = 8,
+ OLEMISC_CANTLINKINSIDE = 16,
+ OLEMISC_CANLINKBYOLE1 = 32,
+ OLEMISC_ISLINKOBJECT = 64,
+ OLEMISC_INSIDEOUT = 128,
+ OLEMISC_ACTIVATEWHENVISIBLE = 256,
+ OLEMISC_RENDERINGISDEVICEINDEPENDENT = 512
+} OLEMISC;
+
+
+// IOleObject::Close options
+typedef enum tagOLECLOSE
+{
+ OLECLOSE_SAVEIFDIRTY = 0,
+ OLECLOSE_NOSAVE = 1,
+ OLECLOSE_PROMPTSAVE = 2
+} OLECLOSE;
+
+
+// IOleObject::GetMoniker and IOleClientSite::GetMoniker options; determines
+// if and how monikers should be assigned.
+typedef enum tagOLEGETMONIKER
+{
+ OLEGETMONIKER_ONLYIFTHERE=1,
+ OLEGETMONIKER_FORCEASSIGN=2,
+ OLEGETMONIKER_UNASSIGN=3,
+ OLEGETMONIKER_TEMPFORUSER=4
+} OLEGETMONIKER;
+
+
+// IOleObject::GetMoniker, IOleObject::SetMoniker and
+// IOleClientSite::GetMoniker options; determines which moniker to use
+typedef enum tagOLEWHICHMK
+{
+ OLEWHICHMK_CONTAINER=1,
+ OLEWHICHMK_OBJREL=2,
+ OLEWHICHMK_OBJFULL=3
+} OLEWHICHMK;
+
+
+#ifdef WIN32
+#define LPSIZEL PSIZEL
+#else
+typedef struct FARSTRUCT tagSIZEL
+{
+ long cx;
+ long cy;
+} SIZEL, FAR* LPSIZEL;
+#endif
+
+
+#ifdef WIN32
+#define LPRECTL PRECTL
+#else
+typedef struct FARSTRUCT tagRECTL
+{
+ long left;
+ long top;
+ long right;
+ long bottom;
+} RECTL, FAR* LPRECTL;
+
+typedef struct FARSTRUCT tagPOINTL {
+ LONG x;
+ LONG y;
+} POINTL;
+
+#endif
+
+
+#ifndef LPCRECT
+typedef const RECT FAR* LPCRECT;
+#endif
+
+#ifndef LPCRECTL
+typedef const RECTL FAR* LPCRECTL;
+#endif
+
+
+// for OleCreateEmbeddingHelper flags; roles in low word; options in high word
+#define EMBDHLP_INPROC_HANDLER 0x0000L // role is handler; implementation is
+ // default handler; pCF can be NULL
+#define EMBDHLP_INPROC_SERVER 0x0001L // role is server; pCF can't be NULL
+
+#define EMBDHLP_CREATENOW 0x00000000L // create using pCF immediately; if pCF
+ // is NULL, uses std remoting handler
+#define EMBDHLP_DELAYCREATE 0x00010000L // delayed create; must supply pCF
+
+
+// NOTE: OleCreateEmbeddingHelper(clsid, pUnkOuter,
+// EMBDHLP_INPROC_HANDLER | EMBDHLP_CREATENOW, NULL, riid, lplpObj)
+// is the same as OleCreateDefaultHandler(clsid, pUnkOuter, riid, lplpObj);
+// i.e., the embedding helper is the default handler in various roles.
+
+//Win32 OLE does not support Ole1.0-Ole2.0 interoperability
+
+#ifndef WIN32
+
+/***** OLE 1.0 OLESTREAM declarations *************************************/
+
+typedef struct _OLESTREAM FAR* LPOLESTREAM;
+
+typedef struct _OLESTREAMVTBL
+{
+ DWORD (CALLBACK* Get)(LPOLESTREAM, void FAR*, DWORD);
+ DWORD (CALLBACK* Put)(LPOLESTREAM, const void FAR*, DWORD);
+} OLESTREAMVTBL;
+typedef OLESTREAMVTBL FAR* LPOLESTREAMVTBL;
+
+typedef struct _OLESTREAM
+{
+ LPOLESTREAMVTBL lpstbl;
+} OLESTREAM;
+
+#endif // !WIN32
+
+
+/****** Clipboard Data structures *****************************************/
+
+typedef struct tagOBJECTDESCRIPTOR
+{
+ ULONG cbSize; // Size of structure in bytes
+ CLSID clsid; // CLSID of data being transferred
+ DWORD dwDrawAspect; // Display aspect of the object
+ // normally DVASPECT_CONTENT or ICON.
+ // dwDrawAspect will be 0 (which is NOT
+ // DVASPECT_CONTENT) if the copier or
+ // dragsource didn't draw the object to
+ // begin with.
+ SIZEL sizel; // size of the object in HIMETRIC
+ // sizel is opt.: will be (0,0) for apps
+ // which don't draw the object being
+ // transferred
+ POINTL pointl; // Offset in HIMETRIC units from the
+ // upper-left corner of the obj where the
+ // mouse went down for the drag.
+ // NOTE: y coordinates increase downward.
+ // x coordinates increase to right
+ // pointl is opt.; it is only meaningful
+ // if object is transfered via drag/drop.
+ // (0, 0) if mouse position is unspecified
+ // (eg. when obj transfered via clipboard)
+ DWORD dwStatus; // Misc. status flags for object. Flags are
+ // defined by OLEMISC enum. these flags
+ // are as would be returned
+ // by IOleObject::GetMiscStatus.
+ DWORD dwFullUserTypeName; // Offset from beginning of structure to
+ // null-terminated string that specifies
+ // Full User Type Name of the object.
+ // 0 indicates string not present.
+ DWORD dwSrcOfCopy; // Offset from beginning of structure to
+ // null-terminated string that specifies
+ // source of the transfer.
+ // dwSrcOfCOpy is normally implemented as
+ // the display name of the temp-for-user
+ // moniker which identifies the source of
+ // the data.
+ // 0 indicates string not present.
+ // NOTE: moniker assignment is NOT forced.
+ // see IOleObject::GetMoniker(
+ // OLEGETMONIKER_TEMPFORUSER)
+
+ /* variable sized string data may appear here */
+
+} OBJECTDESCRIPTOR, *POBJECTDESCRIPTOR, FAR *LPOBJECTDESCRIPTOR,
+ LINKSRCDESCRIPTOR, *PLINKSRCDESCRIPTOR, FAR *LPLINKSRCDESCRIPTOR;
+
+
+
+/* verbs */
+#define OLEIVERB_PRIMARY (0L)
+#define OLEIVERB_SHOW (-1L)
+#define OLEIVERB_OPEN (-2L)
+#define OLEIVERB_HIDE (-3L)
+#define OLEIVERB_UIACTIVATE (-4L)
+#define OLEIVERB_INPLACEACTIVATE (-5L)
+#define OLEIVERB_DISCARDUNDOSTATE (-6L)
+
+
+// forward type declarations
+#if defined(__cplusplus)
+interface IOleClientSite;
+interface IOleContainer;
+interface IOleObject;
+#else
+typedef interface IOleClientSite IOleClientSite;
+typedef interface IOleContainer IOleContainer;
+typedef interface IOleObject IOleObject;
+#endif
+
+typedef IOleObject FAR* LPOLEOBJECT;
+typedef IOleClientSite FAR* LPOLECLIENTSITE;
+typedef IOleContainer FAR* LPOLECONTAINER;
+
+
+/****** OLE GUIDs *********************************************************/
+
+#ifndef INITGUID
+#include "oleguid.h"
+#endif
+
+
+/****** Other Major Interfaces ********************************************/
+
+#include <dvobj.h>
+
+#include <storage.h>
+
+
+
+/****** IDrop??? Interfaces ********************************************/
+
+#define MK_ALT 0x0020
+
+
+#define DROPEFFECT_NONE 0
+#define DROPEFFECT_COPY 1
+#define DROPEFFECT_MOVE 2
+#define DROPEFFECT_LINK 4
+#define DROPEFFECT_SCROLL 0x80000000
+
+// default inset-width of the hot zone, in pixels
+// typical use: GetProfileInt("windows","DragScrollInset",DD_DEFSCROLLINSET)
+#define DD_DEFSCROLLINSET 11
+
+// default delay before scrolling, in milliseconds
+// typical use: GetProfileInt("windows","DragScrollDelay",DD_DEFSCROLLDELAY)
+#define DD_DEFSCROLLDELAY 50
+
+// default scroll interval, in milliseconds
+// typical use: GetProfileInt("windows","DragScrollInterval",
+// DD_DEFSCROLLINTERVAL)
+#define DD_DEFSCROLLINTERVAL 50
+
+// default delay before dragging should start, in milliseconds
+// typical use: GetProfileInt("windows", "DragDelay", DD_DEFDRAGDELAY)
+#define DD_DEFDRAGDELAY 200
+
+// default minimum distance (radius) before dragging should start, in pixels
+// typical use: GetProfileInt("windows", "DragMinDist", DD_DEFDRAGMINDIST)
+#define DD_DEFDRAGMINDIST 2
+
+
+
+/* Dragdrop specific error codes */
+
+#define DRAGDROP_E_NOTREGISTERED (DRAGDROP_E_FIRST)
+// trying to revoke a drop target that has not been registered
+
+#define DRAGDROP_E_ALREADYREGISTERED (DRAGDROP_E_FIRST+1)
+// this window has already been registered as a drop target
+
+#define DRAGDROP_E_INVALIDHWND (DRAGDROP_E_FIRST+2)
+// invalid HWND
+
+
+#define DRAGDROP_S_DROP (DRAGDROP_S_FIRST + 0)
+// successful drop took place
+
+#define DRAGDROP_S_CANCEL (DRAGDROP_S_FIRST + 1)
+// drag-drop operation canceled
+
+#define DRAGDROP_S_USEDEFAULTCURSORS (DRAGDROP_S_FIRST + 2)
+// use the default cursor
+
+
+#undef INTERFACE
+#define INTERFACE IDropTarget
+
+DECLARE_INTERFACE_(IDropTarget, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IDropTarget methods ***
+ STDMETHOD(DragEnter) (THIS_ LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) PURE;
+ STDMETHOD(DragOver) (THIS_ DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) PURE;
+ STDMETHOD(DragLeave) (THIS) PURE;
+ STDMETHOD(Drop) (THIS_ LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect) PURE;
+};
+typedef IDropTarget FAR* LPDROPTARGET;
+
+
+
+#undef INTERFACE
+#define INTERFACE IDropSource
+
+DECLARE_INTERFACE_(IDropSource, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IDropSource methods ***
+ STDMETHOD(QueryContinueDrag) (THIS_ BOOL fEscapePressed, DWORD grfKeyState) PURE;
+ STDMETHOD(GiveFeedback) (THIS_ DWORD dwEffect) PURE;
+};
+typedef IDropSource FAR* LPDROPSOURCE;
+
+
+
+/****** IPersist??? Interfaces ********************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IPersist
+
+DECLARE_INTERFACE_(IPersist, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+};
+typedef IPersist FAR* LPPERSIST;
+
+
+
+#undef INTERFACE
+#define INTERFACE IPersistStorage
+
+DECLARE_INTERFACE_(IPersistStorage, IPersist)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+
+ // *** IPersistStorage methods ***
+ STDMETHOD(IsDirty) (THIS) PURE;
+ STDMETHOD(InitNew) (THIS_ LPSTORAGE pStg) PURE;
+ STDMETHOD(Load) (THIS_ LPSTORAGE pStg) PURE;
+ STDMETHOD(Save) (THIS_ LPSTORAGE pStgSave, BOOL fSameAsLoad) PURE;
+ STDMETHOD(SaveCompleted) (THIS_ LPSTORAGE pStgNew) PURE;
+ STDMETHOD(HandsOffStorage) (THIS) PURE;
+};
+typedef IPersistStorage FAR* LPPERSISTSTORAGE;
+
+
+
+#undef INTERFACE
+#define INTERFACE IPersistStream
+
+DECLARE_INTERFACE_(IPersistStream, IPersist)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+
+ // *** IPersistStream methods ***
+ STDMETHOD(IsDirty) (THIS) PURE;
+ STDMETHOD(Load) (THIS_ LPSTREAM pStm) PURE;
+ STDMETHOD(Save) (THIS_ LPSTREAM pStm,
+ BOOL fClearDirty) PURE;
+ STDMETHOD(GetSizeMax) (THIS_ ULARGE_INTEGER FAR* pcbSize) PURE;
+};
+typedef IPersistStream FAR* LPPERSISTSTREAM;
+
+
+
+#undef INTERFACE
+#define INTERFACE IPersistFile
+
+DECLARE_INTERFACE_(IPersistFile, IPersist)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IPersist methods ***
+ STDMETHOD(GetClassID) (THIS_ LPCLSID lpClassID) PURE;
+
+ // *** IPersistFile methods ***
+ STDMETHOD(IsDirty) (THIS) PURE;
+ STDMETHOD(Load) (THIS_ LPCXSTR lpszFileName, DWORD grfMode) PURE;
+ STDMETHOD(Save) (THIS_ LPCXSTR lpszFileName, BOOL fRemember) PURE;
+ STDMETHOD(SaveCompleted) (THIS_ LPCXSTR lpszFileName) PURE;
+ STDMETHOD(GetCurFile) (THIS_ LPXSTR FAR* lplpszFileName) PURE;
+};
+typedef IPersistFile FAR* LPPERSISTFILE;
+
+
+/****** Moniker Object Interfaces ******************************************/
+
+#include <moniker.h>
+
+
+/****** OLE Object Interfaces ******************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IEnumOLEVERB
+
+DECLARE_INTERFACE_(IEnumOLEVERB, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumOLEVERB methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, LPOLEVERB rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumOLEVERB FAR* FAR* ppenm) PURE;
+};
+typedef IEnumOLEVERB FAR* LPENUMOLEVERB;
+
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleObject
+
+#define OLEOBJ_E_NOVERBS (OLEOBJ_E_FIRST + 0)
+
+#define OLEOBJ_E_INVALIDVERB (OLEOBJ_E_FIRST + 1)
+
+#define OLEOBJ_S_INVALIDVERB (OLEOBJ_S_FIRST + 0)
+
+#define OLEOBJ_S_CANNOT_DOVERB_NOW (OLEOBJ_S_FIRST + 1)
+// verb number is valid but verb cannot be done now, for instance
+// hiding a link or hiding a visible OLE 1.0 server
+
+#define OLEOBJ_S_INVALIDHWND (OLEOBJ_S_FIRST + 2)
+// invalid hwnd passed
+
+
+DECLARE_INTERFACE_(IOleObject, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleObject methods ***
+ STDMETHOD(SetClientSite) (THIS_ LPOLECLIENTSITE pClientSite) PURE;
+ STDMETHOD(GetClientSite) (THIS_ LPOLECLIENTSITE FAR* ppClientSite) PURE;
+ STDMETHOD(SetHostNames) (THIS_ LPCXSTR szContainerApp, LPCXSTR szContainerObj) PURE;
+ STDMETHOD(Close) (THIS_ DWORD dwSaveOption) PURE;
+ STDMETHOD(SetMoniker) (THIS_ DWORD dwWhichMoniker, LPMONIKER pmk) PURE;
+ STDMETHOD(GetMoniker) (THIS_ DWORD dwAssign, DWORD dwWhichMoniker,
+ LPMONIKER FAR* ppmk) PURE;
+ STDMETHOD(InitFromData) (THIS_ LPDATAOBJECT pDataObject,
+ BOOL fCreation,
+ DWORD dwReserved) PURE;
+ STDMETHOD(GetClipboardData) (THIS_ DWORD dwReserved,
+ LPDATAOBJECT FAR* ppDataObject) PURE;
+ STDMETHOD(DoVerb) (THIS_ LONG iVerb,
+ LPMSG lpmsg,
+ LPOLECLIENTSITE pActiveSite,
+ LONG lindex,
+ HWND hwndParent,
+ LPCRECT lprcPosRect) PURE;
+ STDMETHOD(EnumVerbs) (THIS_ LPENUMOLEVERB FAR* ppenumOleVerb) PURE;
+ STDMETHOD(Update) (THIS) PURE;
+ STDMETHOD(IsUpToDate) (THIS) PURE;
+ STDMETHOD(GetUserClassID) (THIS_ CLSID FAR* pClsid) PURE;
+ STDMETHOD(GetUserType) (THIS_ DWORD dwFormOfType, LPXSTR FAR* pszUserType) PURE;
+ STDMETHOD(SetExtent) (THIS_ DWORD dwDrawAspect, LPSIZEL lpsizel) PURE;
+ STDMETHOD(GetExtent) (THIS_ DWORD dwDrawAspect, LPSIZEL lpsizel) PURE;
+
+ STDMETHOD(Advise)(THIS_ LPADVISESINK pAdvSink, DWORD FAR* pdwConnection) PURE;
+ STDMETHOD(Unadvise)(THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumAdvise) (THIS_ LPENUMSTATDATA FAR* ppenumAdvise) PURE;
+ STDMETHOD(GetMiscStatus) (THIS_ DWORD dwAspect, DWORD FAR* pdwStatus) PURE;
+ STDMETHOD(SetColorScheme) (THIS_ LPLOGPALETTE lpLogpal) PURE;
+};
+typedef IOleObject FAR* LPOLEOBJECT;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleClientSite
+
+DECLARE_INTERFACE_(IOleClientSite, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleClientSite methods ***
+ STDMETHOD(SaveObject) (THIS) PURE;
+ STDMETHOD(GetMoniker) (THIS_ DWORD dwAssign, DWORD dwWhichMoniker,
+ LPMONIKER FAR* ppmk) PURE;
+ STDMETHOD(GetContainer) (THIS_ LPOLECONTAINER FAR* ppContainer) PURE;
+ STDMETHOD(ShowObject) (THIS) PURE;
+ STDMETHOD(OnShowWindow) (THIS_ BOOL fShow) PURE;
+ STDMETHOD(RequestNewObjectLayout) (THIS) PURE;
+};
+typedef IOleClientSite FAR* LPOLECLIENTSITE;
+
+
+/****** OLE Runnable Object Interface **********************************/
+
+#undef INTERFACE
+#define INTERFACE IRunnableObject
+
+DECLARE_INTERFACE_(IRunnableObject, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IRunnableObject methods ***
+ STDMETHOD(GetRunningClass) (THIS_ LPCLSID lpClsid) PURE;
+ STDMETHOD(Run) (THIS_ LPBINDCTX pbc) PURE;
+ STDMETHOD_(BOOL, IsRunning) (THIS) PURE;
+ STDMETHOD(LockRunning)(THIS_ BOOL fLock, BOOL fLastUnlockCloses) PURE;
+ STDMETHOD(SetContainedObject)(THIS_ BOOL fContained) PURE;
+};
+typedef IRunnableObject FAR* LPRUNNABLEOBJECT;
+
+
+/****** OLE Container Interfaces ***************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IParseDisplayName
+
+DECLARE_INTERFACE_(IParseDisplayName, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IParseDisplayName method ***
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPXSTR lpszDisplayName,
+ ULONG FAR* pchEaten, LPMONIKER FAR* ppmkOut) PURE;
+};
+typedef IParseDisplayName FAR* LPPARSEDISPLAYNAME;
+
+
+#undef INTERFACE
+#define INTERFACE IOleContainer
+
+DECLARE_INTERFACE_(IOleContainer, IParseDisplayName)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IParseDisplayName method ***
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPXSTR lpszDisplayName,
+ ULONG FAR* pchEaten, LPMONIKER FAR* ppmkOut) PURE;
+
+ // *** IOleContainer methods ***
+ STDMETHOD(EnumObjects) ( DWORD grfFlags, LPENUMUNKNOWN FAR* ppenumUnknown) PURE;
+ STDMETHOD(LockContainer) (THIS_ BOOL fLock) PURE;
+};
+typedef IOleContainer FAR* LPOLECONTAINER;
+
+
+typedef enum tagBINDSPEED
+{
+ BINDSPEED_INDEFINITE = 1,
+ BINDSPEED_MODERATE = 2,
+ BINDSPEED_IMMEDIATE = 3
+} BINDSPEED;
+
+typedef enum tagOLECONTF
+{
+ OLECONTF_EMBEDDINGS = 1,
+ OLECONTF_LINKS = 2,
+ OLECONTF_OTHERS = 4,
+ OLECONTF_ONLYUSER = 8,
+ OLECONTF_ONLYIFRUNNING = 16
+} OLECONTF;
+
+
+#undef INTERFACE
+#define INTERFACE IOleItemContainer
+
+DECLARE_INTERFACE_(IOleItemContainer, IOleContainer)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IParseDisplayName method ***
+ STDMETHOD(ParseDisplayName) (THIS_ LPBC pbc, LPXSTR lpszDisplayName,
+ ULONG FAR* pchEaten, LPMONIKER FAR* ppmkOut) PURE;
+
+ // *** IOleContainer methods ***
+ STDMETHOD(EnumObjects) (THIS_ DWORD grfFlags, LPENUMUNKNOWN FAR* ppenumUnknown) PURE;
+ STDMETHOD(LockContainer) (THIS_ BOOL fLock) PURE;
+
+ // *** IOleItemContainer methods ***
+ STDMETHOD(GetObject) (THIS_ LPXSTR lpszItem, DWORD dwSpeedNeeded,
+ LPBINDCTX pbc, REFIID riid, LPVOID FAR* ppvObject) PURE;
+ STDMETHOD(GetObjectStorage) (THIS_ LPXSTR lpszItem, LPBINDCTX pbc,
+ REFIID riid, LPVOID FAR* ppvStorage) PURE;
+ STDMETHOD(IsRunning) (THIS_ LPXSTR lpszItem) PURE;
+};
+typedef IOleItemContainer FAR* LPOLEITEMCONTAINER;
+
+
+/****** OLE Advise Holder Interface ***************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IOleAdviseHolder
+
+DECLARE_INTERFACE_(IOleAdviseHolder, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppv) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleAdviseHolder methods ***
+ STDMETHOD(Advise)(THIS_ LPADVISESINK pAdvise, DWORD FAR* pdwConnection) PURE;
+ STDMETHOD(Unadvise)(THIS_ DWORD dwConnection) PURE;
+ STDMETHOD(EnumAdvise)(THIS_ LPENUMSTATDATA FAR* ppenumAdvise) PURE;
+
+ STDMETHOD(SendOnRename)(THIS_ LPMONIKER pmk) PURE;
+ STDMETHOD(SendOnSave)(THIS) PURE;
+ STDMETHOD(SendOnClose)(THIS) PURE;
+};
+typedef IOleAdviseHolder FAR* LPOLEADVISEHOLDER;
+
+
+/****** OLE Link Interface ************************************************/
+
+/* Link update options */
+typedef enum tagOLEUPDATE
+{
+ OLEUPDATE_ALWAYS=1,
+ OLEUPDATE_ONCALL=3
+} OLEUPDATE;
+typedef OLEUPDATE FAR* LPOLEUPDATE;
+
+
+// for IOleLink::BindToSource
+typedef enum tagOLELINKBIND
+{
+ OLELINKBIND_EVENIFCLASSDIFF = 1,
+} OLELINKBIND;
+
+
+#undef INTERFACE
+#define INTERFACE IOleLink
+
+DECLARE_INTERFACE_(IOleLink, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleLink methods ***
+ STDMETHOD(SetUpdateOptions) (THIS_ DWORD dwUpdateOpt) PURE;
+ STDMETHOD(GetUpdateOptions) (THIS_ LPDWORD pdwUpdateOpt) PURE;
+ STDMETHOD(SetSourceMoniker) (THIS_ LPMONIKER pmk, REFCLSID rclsid) PURE;
+ STDMETHOD(GetSourceMoniker) (THIS_ LPMONIKER FAR* ppmk) PURE;
+ STDMETHOD(SetSourceDisplayName) (THIS_ LPCXSTR lpszDisplayName) PURE;
+ STDMETHOD(GetSourceDisplayName) (THIS_ LPXSTR FAR* lplpszDisplayName) PURE;
+ STDMETHOD(BindToSource) (THIS_ DWORD bindflags, LPBINDCTX pbc) PURE;
+ STDMETHOD(BindIfRunning) (THIS) PURE;
+ STDMETHOD(GetBoundSource) (THIS_ LPUNKNOWN FAR* ppUnk) PURE;
+ STDMETHOD(UnbindSource) (THIS) PURE;
+ STDMETHOD(Update) (THIS_ LPBINDCTX pbc) PURE;
+};
+typedef IOleLink FAR* LPOLELINK;
+
+
+/****** OLE InPlace Editing Interfaces ************************************/
+
+#ifdef _MAC
+typedef Handle HOLEMENU;
+typedef long SIZE;
+typedef long HACCEL;
+#else
+DECLARE_HANDLE(HOLEMENU);
+#endif
+
+typedef struct FARSTRUCT tagOIFI // OleInPlaceFrameInfo
+{
+ UINT cb;
+ BOOL fMDIApp;
+ HWND hwndFrame;
+ HACCEL haccel;
+ int cAccelEntries;
+} OLEINPLACEFRAMEINFO, FAR* LPOLEINPLACEFRAMEINFO;
+
+
+typedef struct FARSTRUCT tagOleMenuGroupWidths
+{
+ LONG width[6];
+} OLEMENUGROUPWIDTHS, FAR* LPOLEMENUGROUPWIDTHS;
+
+typedef RECT BORDERWIDTHS;
+typedef LPRECT LPBORDERWIDTHS;
+typedef LPCRECT LPCBORDERWIDTHS;
+
+/* Inplace editing specific error codes */
+
+#define INPLACE_E_NOTUNDOABLE (INPLACE_E_FIRST)
+// undo is not avaiable
+
+#define INPLACE_E_NOTOOLSPACE (INPLACE_E_FIRST+1)
+// Space for tools is not available
+
+#define INPLACE_S_TRUNCATED (INPLACE_S_FIRST)
+// Message is too long, some of it had to be truncated before displaying
+
+//misc definitions
+#define INPLACE_DEFBORDERWIDTH 4
+
+// forward type declarations
+#if defined(__cplusplus)
+interface IOleInPlaceUIWindow;
+#else
+typedef interface IOleInPlaceUIWindow IOleInPlaceUIWindow;
+#endif
+
+typedef IOleInPlaceUIWindow FAR* LPOLEINPLACEUIWINDOW;
+
+
+#undef INTERFACE
+#define INTERFACE IOleWindow
+
+DECLARE_INTERFACE_(IOleWindow, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+};
+
+typedef IOleWindow FAR* LPOLEWINDOW;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceObject
+
+DECLARE_INTERFACE_(IOleInPlaceObject, IOleWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceObject methods ***
+ STDMETHOD(InPlaceDeactivate) (THIS) PURE;
+ STDMETHOD(UIDeactivate) (THIS) PURE;
+ STDMETHOD(SetObjectRects) (THIS_ LPCRECT lprcPosRect,
+ LPCRECT lprcClipRect) PURE;
+ STDMETHOD(ReactivateAndUndo) (THIS) PURE;
+};
+typedef IOleInPlaceObject FAR* LPOLEINPLACEOBJECT;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceActiveObject
+
+DECLARE_INTERFACE_(IOleInPlaceActiveObject, IOleWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceActiveObject methods ***
+ STDMETHOD(TranslateAccelerator) (THIS_ LPMSG lpmsg) PURE;
+ STDMETHOD(OnFrameWindowActivate) (THIS_ BOOL fActivate) PURE;
+ STDMETHOD(OnDocWindowActivate) (THIS_ BOOL fActivate) PURE;
+ STDMETHOD(ResizeBorder) (THIS_ LPCRECT lprectBorder, LPOLEINPLACEUIWINDOW lpUIWindow, BOOL fFrameWindow) PURE;
+ STDMETHOD(EnableModeless) (THIS_ BOOL fEnable) PURE;
+};
+typedef IOleInPlaceActiveObject FAR* LPOLEINPLACEACTIVEOBJECT;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceUIWindow
+
+DECLARE_INTERFACE_(IOleInPlaceUIWindow, IOleWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceUIWindow methods ***
+ STDMETHOD(GetBorder) (THIS_ LPRECT lprectBorder) PURE;
+ STDMETHOD(RequestBorderSpace) (THIS_ LPCBORDERWIDTHS lpborderwidths) PURE;
+ STDMETHOD(SetBorderSpace) (THIS_ LPCBORDERWIDTHS lpborderwidths) PURE;
+ STDMETHOD(SetActiveObject) (THIS_ LPOLEINPLACEACTIVEOBJECT lpActiveObject,
+ LPCXSTR lpszObjName) PURE;
+};
+typedef IOleInPlaceUIWindow FAR* LPOLEINPLACEUIWINDOW;
+
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceFrame
+
+DECLARE_INTERFACE_(IOleInPlaceFrame, IOleInPlaceUIWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceUIWindow methods ***
+ STDMETHOD(GetBorder) (THIS_ LPRECT lprectBorder) PURE;
+ STDMETHOD(RequestBorderSpace) (THIS_ LPCBORDERWIDTHS lpborderwidths) PURE;
+ STDMETHOD(SetBorderSpace) (THIS_ LPCBORDERWIDTHS lpborderwidths) PURE;
+ STDMETHOD(SetActiveObject) (THIS_ LPOLEINPLACEACTIVEOBJECT lpActiveObject,
+ LPCXSTR lpszObjName) PURE;
+
+
+ // *** IOleInPlaceFrame methods ***
+ STDMETHOD(InsertMenus) (THIS_ HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) PURE;
+ STDMETHOD(SetMenu) (THIS_ HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) PURE;
+ STDMETHOD(RemoveMenus) (THIS_ HMENU hmenuShared) PURE;
+ STDMETHOD(SetStatusText) (THIS_ LPCXSTR lpszStatusText) PURE;
+ STDMETHOD(EnableModeless) (THIS_ BOOL fEnable) PURE;
+ STDMETHOD(TranslateAccelerator) (THIS_ LPMSG lpmsg, WORD wID) PURE;
+};
+typedef IOleInPlaceFrame FAR* LPOLEINPLACEFRAME;
+
+
+#undef INTERFACE
+#define INTERFACE IOleInPlaceSite
+
+DECLARE_INTERFACE_(IOleInPlaceSite, IOleWindow)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IOleWindow methods ***
+ STDMETHOD(GetWindow) (THIS_ HWND FAR* lphwnd) PURE;
+ STDMETHOD(ContextSensitiveHelp) (THIS_ BOOL fEnterMode) PURE;
+
+ // *** IOleInPlaceSite methods ***
+ STDMETHOD(CanInPlaceActivate) (THIS) PURE;
+ STDMETHOD(OnInPlaceActivate) (THIS) PURE;
+ STDMETHOD(OnUIActivate) (THIS) PURE;
+ STDMETHOD(GetWindowContext) (THIS_ LPOLEINPLACEFRAME FAR* lplpFrame,
+ LPOLEINPLACEUIWINDOW FAR* lplpDoc,
+ LPRECT lprcPosRect,
+ LPRECT lprcClipRect,
+ LPOLEINPLACEFRAMEINFO lpFrameInfo) PURE;
+ STDMETHOD(Scroll) (THIS_ SIZE scrollExtent) PURE;
+ STDMETHOD(OnUIDeactivate) (THIS_ BOOL fUndoable) PURE;
+ STDMETHOD(OnInPlaceDeactivate) (THIS) PURE;
+ STDMETHOD(DiscardUndoState) (THIS) PURE;
+ STDMETHOD(DeactivateAndUndo) (THIS) PURE;
+ STDMETHOD(OnPosRectChange) (THIS_ LPCRECT lprcPosRect) PURE;
+};
+typedef IOleInPlaceSite FAR* LPOLEINPLACESITE;
+
+
+
+/****** OLE API Prototypes ************************************************/
+
+STDAPI_(DWORD) OleBuildVersion( VOID );
+
+/* helper functions */
+STDAPI ReadClassStg(LPSTORAGE pStg, CLSID FAR* pclsid);
+STDAPI WriteClassStg(LPSTORAGE pStg, REFCLSID rclsid);
+STDAPI ReadClassStm(LPSTREAM pStm, CLSID FAR* pclsid);
+STDAPI WriteClassStm(LPSTREAM pStm, REFCLSID rclsid);
+STDAPI WriteFmtUserTypeStg (LPSTORAGE pstg, CLIPFORMAT cf, LPXSTR lpszUserType);
+STDAPI ReadFmtUserTypeStg (LPSTORAGE pstg, CLIPFORMAT FAR* pcf, LPXSTR FAR* lplpszUserType);
+
+
+/* init/term */
+
+STDAPI OleInitialize(LPMALLOC pMalloc);
+STDAPI_(void) OleUninitialize(void);
+
+
+/* APIs to query whether (Embedded/Linked) object can be created from
+ the data object */
+
+STDAPI OleQueryLinkFromData(LPDATAOBJECT pSrcDataObject);
+STDAPI OleQueryCreateFromData(LPDATAOBJECT pSrcDataObject);
+
+
+/* Object creation APIs */
+
+STDAPI OleCreate(REFCLSID rclsid, REFIID riid, DWORD renderopt,
+ LPFORMATETC pFormatEtc, LPOLECLIENTSITE pClientSite,
+ LPSTORAGE pStg, LPVOID FAR* ppvObj);
+
+STDAPI OleCreateFromData(LPDATAOBJECT pSrcDataObj, REFIID riid,
+ DWORD renderopt, LPFORMATETC pFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
+ LPVOID FAR* ppvObj);
+
+STDAPI OleCreateLinkFromData(LPDATAOBJECT pSrcDataObj, REFIID riid,
+ DWORD renderopt, LPFORMATETC pFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
+ LPVOID FAR* ppvObj);
+
+STDAPI OleCreateStaticFromData(LPDATAOBJECT pSrcDataObj, REFIID iid,
+ DWORD renderopt, LPFORMATETC pFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg,
+ LPVOID FAR* ppvObj);
+
+
+STDAPI OleCreateLink(LPMONIKER pmkLinkSrc, REFIID riid,
+ DWORD renderopt, LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg, LPVOID FAR* ppvObj);
+
+STDAPI OleCreateLinkToFile(LPCXSTR lpszFileName, REFIID riid,
+ DWORD renderopt, LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg, LPVOID FAR* ppvObj);
+
+STDAPI OleCreateFromFile(REFCLSID rclsid, LPCXSTR lpszFileName, REFIID riid,
+ DWORD renderopt, LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite, LPSTORAGE pStg, LPVOID FAR* ppvObj);
+
+STDAPI OleLoad(LPSTORAGE pStg, REFIID riid, LPOLECLIENTSITE pClientSite,
+ LPVOID FAR* ppvObj);
+
+STDAPI OleSave(LPPERSISTSTORAGE pPS, LPSTORAGE pStg, BOOL fSameAsLoad);
+
+STDAPI OleLoadFromStream( LPSTREAM pStm, REFIID iidInterface, LPVOID FAR* ppvObj);
+STDAPI OleSaveToStream( LPPERSISTSTREAM pPStm, LPSTREAM pStm );
+
+
+STDAPI OleSetContainedObject(LPUNKNOWN pUnknown, BOOL fContained);
+STDAPI OleNoteObjectVisible(LPUNKNOWN pUnknown, BOOL fVisible);
+
+
+/* Drag/Drop APIs */
+
+STDAPI RegisterDragDrop(HWND hwnd, LPDROPTARGET pDropTarget);
+STDAPI RevokeDragDrop(HWND hwnd);
+STDAPI DoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
+ DWORD dwOKEffects, LPDWORD pdwEffect);
+
+/* Clipboard APIs */
+
+STDAPI OleSetClipboard(LPDATAOBJECT pDataObj);
+STDAPI OleGetClipboard(LPDATAOBJECT FAR* ppDataObj);
+STDAPI OleFlushClipboard(void);
+STDAPI OleIsCurrentClipboard(LPDATAOBJECT pDataObj);
+
+
+/* InPlace Editing APIs */
+
+STDAPI_(HOLEMENU) OleCreateMenuDescriptor (HMENU hmenuCombined,
+ LPOLEMENUGROUPWIDTHS lpMenuWidths);
+STDAPI OleSetMenuDescriptor (HOLEMENU holemenu, HWND hwndFrame,
+ HWND hwndActiveObject,
+ LPOLEINPLACEFRAME lpFrame,
+ LPOLEINPLACEACTIVEOBJECT lpActiveObj);
+STDAPI OleDestroyMenuDescriptor (HOLEMENU holemenu);
+
+STDAPI OleTranslateAccelerator (LPOLEINPLACEFRAME lpFrame,
+ LPOLEINPLACEFRAMEINFO lpFrameInfo, LPMSG lpmsg);
+
+
+/* Helper APIs */
+STDAPI_(HANDLE) OleDuplicateData (HANDLE hSrc, CLIPFORMAT cfFormat,
+ UINT uiFlags);
+
+STDAPI OleDraw (LPUNKNOWN pUnknown, DWORD dwAspect, HDC hdcDraw,
+ LPCRECT lprcBounds);
+
+STDAPI OleRun(LPUNKNOWN pUnknown);
+STDAPI_(BOOL) OleIsRunning(LPOLEOBJECT pObject);
+STDAPI OleLockRunning(LPUNKNOWN pUnknown, BOOL fLock, BOOL fLastUnlockCloses);
+
+STDAPI_(void) ReleaseStgMedium(LPSTGMEDIUM);
+STDAPI CreateOleAdviseHolder(LPOLEADVISEHOLDER FAR* ppOAHolder);
+
+STDAPI OleCreateDefaultHandler(REFCLSID clsid, LPUNKNOWN pUnkOuter,
+ REFIID riid, LPVOID FAR* lplpObj);
+
+STDAPI OleCreateEmbeddingHelper(REFCLSID clsid, LPUNKNOWN pUnkOuter,
+ DWORD flags, LPCLASSFACTORY pCF,
+ REFIID riid, LPVOID FAR* lplpObj);
+
+STDAPI_(BOOL) IsAccelerator(HACCEL hAccel, int cAccelEntries, LPMSG lpMsg,
+ WORD FAR* lpwCmd);
+
+
+/* Icon extraction Helper APIs */
+
+STDAPI_(HGLOBAL) OleGetIconOfFile(LPXSTR lpszPath, BOOL fUseFileAsLabel);
+
+STDAPI_(HGLOBAL) OleGetIconOfClass(REFCLSID rclsid, LPXSTR lpszLabel,
+ BOOL fUseTypeAsLabel);
+
+STDAPI_(HGLOBAL) OleMetafilePictFromIconAndLabel(HICON hIcon, LPXSTR lpszLabel,
+ LPXSTR lpszSourceFile, UINT iIconIndex);
+
+
+
+/* Registration Database Helper APIs */
+
+STDAPI OleRegGetUserType (REFCLSID clsid, DWORD dwFormOfType,
+ LPXSTR FAR* pszUserType);
+
+STDAPI OleRegGetMiscStatus (REFCLSID clsid, DWORD dwAspect,
+ DWORD FAR* pdwStatus);
+
+STDAPI OleRegEnumFormatEtc (REFCLSID clsid, DWORD dwDirection,
+ LPENUMFORMATETC FAR* ppenum);
+
+STDAPI OleRegEnumVerbs (REFCLSID clsid, LPENUMOLEVERB FAR* ppenum);
+
+
+#ifndef WIN32 //Ole 1.0 conversion is not available in 32-bit OLE
+
+/* OLE 1.0 conversion APIS */
+
+STDAPI OleConvertIStorageToOLESTREAM
+ (LPSTORAGE pstg,
+ LPOLESTREAM polestm);
+
+STDAPI OleConvertOLESTREAMToIStorage
+ (LPOLESTREAM polestm,
+ LPSTORAGE pstg,
+ const DVTARGETDEVICE FAR* ptd);
+
+STDAPI OleConvertIStorageToOLESTREAMEx
+ (LPSTORAGE pstg,
+ // Presentation data to OLESTREAM
+ CLIPFORMAT cfFormat, // format
+ LONG lWidth, // width
+ LONG lHeight, // height
+ DWORD dwSize, // size in bytes
+ LPSTGMEDIUM pmedium, // bits
+ LPOLESTREAM polestm);
+
+STDAPI OleConvertOLESTREAMToIStorageEx
+ (LPOLESTREAM polestm,
+ LPSTORAGE pstg,
+ // Presentation data from OLESTREAM
+ CLIPFORMAT FAR* pcfFormat, // format
+ LONG FAR* plwWidth, // width
+ LONG FAR* plHeight, // height
+ DWORD FAR* pdwSize, // size in bytes
+ LPSTGMEDIUM pmedium); // bits
+
+#endif //WIN32
+
+/* Storage Utility APIs */
+STDAPI GetHGlobalFromILockBytes (LPLOCKBYTES plkbyt, HGLOBAL FAR* phglobal);
+STDAPI CreateILockBytesOnHGlobal (HGLOBAL hGlobal, BOOL fDeleteOnRelease,
+ LPLOCKBYTES FAR* pplkbyt);
+
+STDAPI GetHGlobalFromStream (LPSTREAM pstm, HGLOBAL FAR* phglobal);
+STDAPI CreateStreamOnHGlobal (HGLOBAL hGlobal, BOOL fDeleteOnRelease,
+ LPSTREAM FAR* ppstm);
+
+
+/* ConvertTo APIS */
+
+STDAPI OleDoAutoConvert(LPSTORAGE pStg, LPCLSID pClsidNew);
+STDAPI OleGetAutoConvert(REFCLSID clsidOld, LPCLSID pClsidNew);
+STDAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew);
+STDAPI GetConvertStg(LPSTORAGE pStg);
+STDAPI SetConvertStg(LPSTORAGE pStg, BOOL fConvert);
+
+
+#endif // _OLE2_H_
diff --git a/private/ole32/stg/ole2flat/oleguid.h b/private/ole32/stg/ole2flat/oleguid.h
new file mode 100644
index 000000000..723fa50d7
--- /dev/null
+++ b/private/ole32/stg/ole2flat/oleguid.h
@@ -0,0 +1,80 @@
+/*****************************************************************************\
+* *
+* oleguid.h - Master definition of GUIDs for ole2.dll *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+/* this file is the master definition of all public GUIDs specific to OLE
+ and is included in ole2.h.
+
+ NOTE: The second least significant byte of all of these GUIDs is 1.
+*/
+
+
+DEFINE_OLEGUID(IID_IEnumUnknown, 0x00000100, 0, 0);
+DEFINE_OLEGUID(IID_IEnumString, 0x00000101, 0, 0);
+DEFINE_OLEGUID(IID_IEnumMoniker, 0x00000102, 0, 0);
+DEFINE_OLEGUID(IID_IEnumFORMATETC, 0x00000103, 0, 0);
+DEFINE_OLEGUID(IID_IEnumOLEVERB, 0x00000104, 0, 0);
+DEFINE_OLEGUID(IID_IEnumSTATDATA, 0x00000105, 0, 0);
+
+DEFINE_OLEGUID(IID_IEnumGeneric, 0x00000106, 0, 0);
+DEFINE_OLEGUID(IID_IEnumHolder, 0x00000107, 0, 0);
+DEFINE_OLEGUID(IID_IEnumCallback, 0x00000108, 0, 0);
+
+DEFINE_OLEGUID(IID_IPersistStream, 0x00000109, 0, 0);
+DEFINE_OLEGUID(IID_IPersistStorage, 0x0000010a, 0, 0);
+DEFINE_OLEGUID(IID_IPersistFile, 0x0000010b, 0, 0);
+DEFINE_OLEGUID(IID_IPersist, 0x0000010c, 0, 0);
+
+DEFINE_OLEGUID(IID_IViewObject, 0x0000010d, 0, 0);
+DEFINE_OLEGUID(IID_IDataObject, 0x0000010e, 0, 0);
+DEFINE_OLEGUID(IID_IAdviseSink, 0x0000010f, 0, 0);
+DEFINE_OLEGUID(IID_IDataAdviseHolder, 0x00000110, 0, 0);
+DEFINE_OLEGUID(IID_IOleAdviseHolder, 0x00000111, 0, 0);
+
+DEFINE_OLEGUID(IID_IOleObject, 0x00000112, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceObject, 0x00000113, 0, 0);
+DEFINE_OLEGUID(IID_IOleWindow, 0x00000114, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceUIWindow, 0x00000115, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceFrame, 0x00000116, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceActiveObject, 0x00000117, 0, 0);
+
+DEFINE_OLEGUID(IID_IOleClientSite, 0x00000118, 0, 0);
+DEFINE_OLEGUID(IID_IOleInPlaceSite, 0x00000119, 0, 0);
+
+DEFINE_OLEGUID(IID_IParseDisplayName, 0x0000011a, 0, 0);
+DEFINE_OLEGUID(IID_IOleContainer, 0x0000011b, 0, 0);
+DEFINE_OLEGUID(IID_IOleItemContainer, 0x0000011c, 0, 0);
+
+DEFINE_OLEGUID(IID_IOleLink, 0x0000011d, 0, 0);
+DEFINE_OLEGUID(IID_IOleCache, 0x0000011e, 0, 0);
+DEFINE_OLEGUID(IID_IOleManager, 0x0000011f, 0, 0); // unused
+DEFINE_OLEGUID(IID_IOlePresObj, 0x00000120, 0, 0);
+
+DEFINE_OLEGUID(IID_IDropSource, 0x00000121, 0, 0);
+DEFINE_OLEGUID(IID_IDropTarget, 0x00000122, 0, 0);
+
+DEFINE_OLEGUID(IID_IDebug, 0x00000123, 0, 0);
+DEFINE_OLEGUID(IID_IDebugStream, 0x00000124, 0, 0);
+
+DEFINE_OLEGUID(IID_IAdviseSink2, 0x00000125, 0, 0);
+
+DEFINE_OLEGUID(IID_IRunnableObject, 0x00000126, 0, 0);
+
+DEFINE_OLEGUID(IID_IViewObject2, 0x00000127, 0, 0);
+DEFINE_OLEGUID(IID_IOleCache2, 0x00000128, 0, 0);
+DEFINE_OLEGUID(IID_IOleCacheControl, 0x00000129, 0, 0);
+
+/* NOTE: LSB values 0x27 through 0xff are reserved */
+
+
+/* GUIDs defined in OLE's private range */
+DEFINE_OLEGUID(CLSID_Picture_Metafile, 0x00000315, 0, 0);
+DEFINE_OLEGUID(CLSID_Picture_Dib, 0x00000316, 0, 0);
+
+
diff --git a/private/ole32/stg/ole2flat/scode.h b/private/ole32/stg/ole2flat/scode.h
new file mode 100644
index 000000000..cbfb2751c
--- /dev/null
+++ b/private/ole32/stg/ole2flat/scode.h
@@ -0,0 +1,283 @@
+/*****************************************************************************\
+* *
+* scode.h - Defines standard status code services. *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#ifndef __SCODE_H__
+#define __SCODE_H__
+
+//
+// SCODE
+//
+
+typedef long SCODE;
+typedef SCODE *PSCODE;
+typedef void FAR * HRESULT;
+#define NOERROR 0
+
+//
+// Status values are 32 bit values layed out as follows:
+//
+// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-+---------------------+-------+-------------------------------+
+// |S| Context | Facil | Code |
+// +-+---------------------+-------+-------------------------------+
+//
+// where
+//
+// S - is the severity code
+//
+// 0 - Success
+// 1 - Error
+//
+// Context - context info
+//
+// Facility - is the facility code
+//
+// Code - is the facility's status code
+//
+
+//
+// Severity values
+//
+
+#define SEVERITY_SUCCESS 0
+#define SEVERITY_ERROR 1
+
+
+
+#define SUCCEEDED(Status) ((SCODE)(Status) >= 0)
+
+#define FAILED(Status) ((SCODE)(Status)<0)
+
+
+//
+// Return the code
+//
+
+#define SCODE_CODE(sc) ((sc) & 0xFFFF)
+
+//
+// Return the facility
+//
+
+#define SCODE_FACILITY(sc) (((sc) >> 16) & 0x1fff)
+
+//
+// Return the severity
+//
+
+#define SCODE_SEVERITY(sc) (((sc) >> 31) & 0x1)
+
+//
+// Create an SCODE value from component pieces
+//
+
+#define MAKE_SCODE(sev,fac,code) \
+ ((SCODE) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
+
+
+
+// --------------------- Functions ---------------------------------------
+
+#define GetScode(hr) ((SCODE)(hr) & 0x800FFFFF)
+#define ResultFromScode(sc) ((HRESULT)((SCODE)(sc) & 0x800FFFFF))
+
+STDAPI PropagateResult(HRESULT hrPrev, SCODE scNew);
+
+
+// -------------------------- Facility definitions -------------------------
+
+#define FACILITY_NULL 0x0000 // generally useful errors ([SE]_*)
+#define FACILITY_RPC 0x0001 // remote procedure call errors (RPC_E_*)
+#define FACILITY_DISPATCH 0x0002 // late binding dispatch errors
+#define FACILITY_STORAGE 0x0003 // storage errors (STG_E_*)
+#define FACILITY_ITF 0x0004 // interface-specific errors
+
+
+
+#define S_OK 0L
+#define S_FALSE MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 1)
+
+
+
+// --------------------- FACILITY_NULL errors ------------------------------
+
+#define E_UNEXPECTED MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 0xffff)
+ // relatively catastrophic failure
+
+#define E_NOTIMPL MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 1)
+ // not implemented
+
+#define E_OUTOFMEMORY MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 2)
+ // ran out of memory
+
+#define E_INVALIDARG MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 3)
+ // one or more arguments are invalid
+
+#define E_NOINTERFACE MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 4)
+ // no such interface supported
+
+
+#define E_POINTER MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 5)
+ // invalid pointer
+
+#define E_HANDLE MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 6)
+ // invalid handle
+
+#define E_ABORT MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 7)
+ // operation aborted
+
+#define E_FAIL MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 8)
+ // unspecified error
+
+
+#define E_ACCESSDENIED MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 9)
+ // general access denied error
+
+
+// ----------------- FACILITY_ITF errors used by OLE ---------------------
+//
+// By convention, OLE interfaces divide the FACILITY_ITF range of errors
+// into nonoverlapping subranges. If an OLE interface returns a FACILITY_ITF
+// scode, it must be from the range associated with that interface or from
+// the shared range: OLE_E_FIRST...OLE_E_LAST.
+//
+// The ranges, their associated interfaces, and the header file that defines
+// the actual scodes are given below.
+//
+
+// Generic OLE errors that may be returned by many interfaces
+#define OLE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0000)
+#define OLE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x00FF)
+#define OLE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0000)
+#define OLE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x00FF)
+// interfaces: all
+// file: ole2.h
+
+
+#define DRAGDROP_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0100)
+#define DRAGDROP_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x010F)
+#define DRAGDROP_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0100)
+#define DRAGDROP_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x010F)
+// interfaces: IDropSource, IDropTarget
+// file: ole2.h
+
+#define CLASSFACTORY_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0110)
+#define CLASSFACTORY_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x011F)
+#define CLASSFACTORY_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0110)
+#define CLASSFACTORY_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x011F)
+// interfaces: IClassFactory
+// file:
+
+#define MARSHAL_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0120)
+#define MARSHAL_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x012F)
+#define MARSHAL_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0120)
+#define MARSHAL_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x012F)
+// interfaces: IMarshal, IStdMarshalInfo, marshal APIs
+// file:
+
+#define DATA_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0130)
+#define DATA_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x013F)
+#define DATA_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0130)
+#define DATA_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x013F)
+// interfaces: IDataObject
+// file: dvobj.h
+
+#define VIEW_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0140)
+#define VIEW_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x014F)
+#define VIEW_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0140)
+#define VIEW_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x014F)
+// interfaces: IViewObject
+// file: dvobj.h
+
+#define REGDB_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0150)
+#define REGDB_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x015F)
+#define REGDB_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0150)
+#define REGDB_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x015F)
+// API: reg.dat manipulation
+// file:
+
+
+// range 160 - 16F reserved
+
+#define CACHE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0170)
+#define CACHE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x017F)
+#define CACHE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0170)
+#define CACHE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x017F)
+// interfaces: IOleCache
+// file:
+
+#define OLEOBJ_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0180)
+#define OLEOBJ_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x018F)
+#define OLEOBJ_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0180)
+#define OLEOBJ_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x018F)
+// interfaces: IOleObject
+// file:
+
+#define CLIENTSITE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0190)
+#define CLIENTSITE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x019F)
+#define CLIENTSITE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0190)
+#define CLIENTSITE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x019F)
+// interfaces: IOleClientSite
+// file:
+
+#define INPLACE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01A0)
+#define INPLACE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01AF)
+#define INPLACE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01A0)
+#define INPLACE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01AF)
+// interfaces: IOleWindow, IOleInPlaceObject, IOleInPlaceActiveObject,
+// IOleInPlaceUIWindow, IOleInPlaceFrame, IOleInPlaceSite
+// file:
+
+#define ENUM_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01B0)
+#define ENUM_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01BF)
+#define ENUM_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01B0)
+#define ENUM_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01BF)
+// interfaces: IEnum*
+// file:
+
+#define CONVERT10_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01C0)
+#define CONVERT10_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01CF)
+#define CONVERT10_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01C0)
+#define CONVERT10_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01CF)
+// API: OleConvertOLESTREAMToIStorage, OleConvertIStorageToOLESTREAM
+// file:
+
+
+#define CLIPBRD_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01D0)
+#define CLIPBRD_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01DF)
+#define CLIPBRD_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01D0)
+#define CLIPBRD_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01DF)
+// interfaces: OleSetClipboard, OleGetClipboard, OleFlushClipboard
+// file: ole2.h
+
+#define MK_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01E0)
+#define MK_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01EF)
+#define MK_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01E0)
+#define MK_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01EF)
+// interfaces: IMoniker, IBindCtx, IRunningObjectTable, IParseDisplayName,
+// IOleContainer, IOleItemContainer, IOleLink
+// file: moniker.h
+
+
+#define CO_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01F0)
+#define CO_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01FF)
+#define CO_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01F0)
+#define CO_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01FF)
+// all Co* API
+// file: compobj.h
+
+
+// range 200 - ffff for new error codes
+
+
+
+#endif // ifndef __SCODE_H__
diff --git a/private/ole32/stg/ole2flat/storage.h b/private/ole32/stg/ole2flat/storage.h
new file mode 100644
index 000000000..8779bf160
--- /dev/null
+++ b/private/ole32/stg/ole2flat/storage.h
@@ -0,0 +1,457 @@
+/*****************************************************************************\
+* *
+* storage.h - Definitions for the strutured storage system
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#if !defined( _STORAGE_H_ )
+#define _STORAGE_H_
+
+
+#include <compobj.h>
+
+
+/****** Storage Error Codes *************************************************/
+
+/* DOS-based error codes */
+#define STG_E_INVALIDFUNCTION \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x01)
+
+#define STG_E_FILENOTFOUND \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x02)
+
+#define STG_E_PATHNOTFOUND \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x03)
+
+#define STG_E_TOOMANYOPENFILES \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x04)
+
+#define STG_E_ACCESSDENIED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x05)
+
+#define STG_E_INVALIDHANDLE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x06)
+
+#define STG_E_INSUFFICIENTMEMORY \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x08)
+
+#define STG_E_INVALIDPOINTER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x09)
+
+#define STG_E_NOMOREFILES \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x12)
+
+#define STG_E_DISKISWRITEPROTECTED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x13)
+
+#define STG_E_SEEKERROR \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x19)
+
+#define STG_E_WRITEFAULT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x1d)
+
+#define STG_E_READFAULT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x1e)
+
+#define STG_E_SHAREVIOLATION \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x20)
+
+#define STG_E_LOCKVIOLATION \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x21)
+
+#define STG_E_FILEALREADYEXISTS \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x50)
+
+#define STG_E_INVALIDPARAMETER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x57)
+
+#define STG_E_MEDIUMFULL \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x70)
+
+#define STG_E_ABNORMALAPIEXIT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfa)
+
+#define STG_E_INVALIDHEADER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfb)
+
+#define STG_E_INVALIDNAME \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfc)
+
+#define STG_E_UNKNOWN \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfd)
+
+#define STG_E_UNIMPLEMENTEDFUNCTION\
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfe)
+
+#define STG_E_INVALIDFLAG \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xff)
+
+/* Standard storage error codes */
+#define STG_E_INUSE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x100)
+
+#define STG_E_NOTCURRENT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x101)
+
+#define STG_E_REVERTED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x102)
+
+#define STG_E_CANTSAVE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x103)
+
+#define STG_E_OLDFORMAT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x104)
+
+#define STG_E_OLDDLL \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x105)
+
+#define STG_E_SHAREREQUIRED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x106)
+
+#define STG_E_NOTFILEBASEDSTORAGE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x107)
+
+#define STG_E_EXTANTMARSHALLINGS \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x108)
+
+/* Information returns */
+#define STG_S_CONVERTED \
+ MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_STORAGE, 0x200)
+
+/****** Storage types *******************************************************/
+
+#if defined(_M_I286)
+typedef XCHAR TCHAR;
+#ifndef HUGEP
+#define HUGEP _huge
+#endif
+#else
+//typedef XCHAR TCHAR; already defined in wtypes.h
+#ifndef HUGEP
+#define HUGEP
+#endif
+#endif
+
+#define CWCSTORAGENAME 32
+
+/* Storage instantiation modes */
+#define STGM_DIRECT 0x00000000L
+#define STGM_TRANSACTED 0x00010000L
+
+#define STGM_READ 0x00000000L
+#define STGM_WRITE 0x00000001L
+#define STGM_READWRITE 0x00000002L
+
+#define STGM_SHARE_DENY_NONE 0x00000040L
+#define STGM_SHARE_DENY_READ 0x00000030L
+#define STGM_SHARE_DENY_WRITE 0x00000020L
+#define STGM_SHARE_EXCLUSIVE 0x00000010L
+
+#define STGM_PRIORITY 0x00040000L
+#define STGM_DELETEONRELEASE 0x04000000L
+
+#define STGM_CREATE 0x00001000L
+#define STGM_CONVERT 0x00020000L
+#define STGM_FAILIFTHERE 0x00000000L
+
+/* Storage commit types */
+typedef enum tagSTGC
+{
+ STGC_DEFAULT = 0,
+ STGC_OVERWRITE = 1,
+ STGC_ONLYIFCURRENT = 2,
+ STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4
+} STGC;
+
+/* Stream name block definitions */
+typedef XCHAR FAR * FAR *SNB;
+
+
+#ifndef _WINDOWS_
+#ifndef _FILETIME_
+#define _FILETIME_
+typedef struct FARSTRUCT tagFILETIME
+{
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+} FILETIME;
+#endif
+#endif
+
+
+/* Storage stat buffer */
+
+typedef struct FARSTRUCT tagSTATSTG
+{
+ XCHAR FAR* pwcsName;
+ DWORD type;
+ ULARGE_INTEGER cbSize;
+ FILETIME mtime;
+ FILETIME ctime;
+ FILETIME atime;
+ DWORD grfMode;
+ DWORD grfLocksSupported;
+ CLSID clsid;
+ DWORD grfStateBits;
+ DWORD reserved;
+} STATSTG;
+
+
+/* Storage element types */
+typedef enum tagSTGTY
+{
+ STGTY_STORAGE = 1,
+ STGTY_STREAM = 2,
+ STGTY_LOCKBYTES = 3,
+ STGTY_PROPERTY = 4
+} STGTY;
+
+typedef enum tagSTREAM_SEEK
+{
+ STREAM_SEEK_SET = 0,
+ STREAM_SEEK_CUR = 1,
+ STREAM_SEEK_END = 2
+} STREAM_SEEK;
+
+typedef enum tagLOCKTYPE
+{
+ LOCK_WRITE = 1,
+ LOCK_EXCLUSIVE = 2,
+ LOCK_ONLYONCE = 4
+} LOCKTYPE;
+
+typedef enum tagSTGMOVE
+{
+ STGMOVE_MOVE = 0,
+ STGMOVE_COPY = 1
+} STGMOVE;
+
+typedef enum tagSTATFLAG
+{
+ STATFLAG_DEFAULT = 0,
+ STATFLAG_NONAME = 1
+} STATFLAG;
+
+
+/****** Storage Enumerators *************************************************/
+
+#undef INTERFACE
+#define INTERFACE IEnumSTATSTG
+
+DECLARE_INTERFACE_(IEnumSTATSTG, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IENUMSTATSTG methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, STATSTG FAR * rgelt, ULONG FAR *pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumSTATSTG FAR *FAR *ppenm) PURE;
+};
+
+typedef IEnumSTATSTG FAR* LPENUMSTATSTG;
+
+
+
+/****** ILockBytes Interface ************************************************/
+
+#undef INTERFACE
+#define INTERFACE ILockBytes
+
+DECLARE_INTERFACE_(ILockBytes, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** ILockBytes methods ***
+ STDMETHOD(ReadAt) (THIS_ ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbRead) PURE;
+ STDMETHOD(WriteAt) (THIS_ ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten) PURE;
+ STDMETHOD(Flush) (THIS) PURE;
+ STDMETHOD(SetSize) (THIS_ ULARGE_INTEGER cb) PURE;
+ STDMETHOD(LockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(UnlockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+};
+
+typedef ILockBytes FAR* LPLOCKBYTES;
+
+
+
+/****** IStream Interface ***************************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IStream
+
+DECLARE_INTERFACE_(IStream, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IStream methods ***
+ STDMETHOD(Read) (THIS_ VOID HUGEP *pv,
+ ULONG cb, ULONG FAR *pcbRead) PURE;
+ STDMETHOD(Write) (THIS_ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten) PURE;
+ STDMETHOD(Seek) (THIS_ LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER FAR *plibNewPosition) PURE;
+ STDMETHOD(SetSize) (THIS_ ULARGE_INTEGER libNewSize) PURE;
+ STDMETHOD(CopyTo) (THIS_ IStream FAR *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER FAR *pcbRead,
+ ULARGE_INTEGER FAR *pcbWritten) PURE;
+ STDMETHOD(Commit) (THIS_ DWORD grfCommitFlags) PURE;
+ STDMETHOD(Revert) (THIS) PURE;
+ STDMETHOD(LockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(UnlockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+ STDMETHOD(Clone)(THIS_ IStream FAR * FAR *ppstm) PURE;
+};
+
+typedef IStream FAR* LPSTREAM;
+
+
+
+/****** IStorage Interface **************************************************/
+
+#undef INTERFACE
+#define INTERFACE IStorage
+
+DECLARE_INTERFACE_(IStorage, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IStorage methods ***
+ STDMETHOD(CreateStream) (THIS_ const XCHAR FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream FAR *FAR *ppstm) PURE;
+ STDMETHOD(OpenStream) (THIS_ const XCHAR FAR* pwcsName,
+ void FAR *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream FAR *FAR *ppstm) PURE;
+ STDMETHOD(CreateStorage) (THIS_ const XCHAR FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStorage FAR *FAR *ppstg) PURE;
+ STDMETHOD(OpenStorage) (THIS_ const XCHAR FAR* pwcsName,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR *FAR *ppstg) PURE;
+ STDMETHOD(CopyTo) (THIS_ DWORD ciidExclude,
+ IID const FAR *rgiidExclude,
+ SNB snbExclude,
+ IStorage FAR *pstgDest) PURE;
+ STDMETHOD(MoveElementTo) (THIS_ XCHAR const FAR* lpszName,
+ IStorage FAR *pstgDest,
+ XCHAR const FAR* lpszNewName,
+ DWORD grfFlags) PURE;
+ STDMETHOD(Commit) (THIS_ DWORD grfCommitFlags) PURE;
+ STDMETHOD(Revert) (THIS) PURE;
+ STDMETHOD(EnumElements) (THIS_ DWORD reserved1,
+ void FAR *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG FAR *FAR *ppenm) PURE;
+ STDMETHOD(DestroyElement) (THIS_ const XCHAR FAR* pwcsName) PURE;
+ STDMETHOD(RenameElement) (THIS_ const XCHAR FAR* pwcsOldName,
+ const XCHAR FAR* pwcsNewName) PURE;
+ STDMETHOD(SetElementTimes) (THIS_ const XCHAR FAR *lpszName,
+ FILETIME const FAR *pctime,
+ FILETIME const FAR *patime,
+ FILETIME const FAR *pmtime) PURE;
+ STDMETHOD(SetClass) (THIS_ REFCLSID clsid) PURE;
+ STDMETHOD(SetStateBits) (THIS_ DWORD grfStateBits, DWORD grfMask) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+};
+
+typedef IStorage FAR* LPSTORAGE;
+
+
+
+/****** IRootStorage Interface **********************************************/
+
+#undef INTERFACE
+#define INTERFACE IRootStorage
+
+DECLARE_INTERFACE_(IRootStorage, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IRootStorage methods ***
+ STDMETHOD(SwitchToFile) (THIS_ LPXSTR lpstrFile) PURE;
+};
+
+typedef IRootStorage FAR* LPROOTSTORAGE;
+
+
+
+/****** Storage API Prototypes ********************************************/
+
+STDAPI StgCreateDocfile(const XCHAR FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgCreateDocfileOnILockBytes(ILockBytes FAR *plkbyt,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgOpenStorage(const XCHAR FAR* pwcsName,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgOpenStorageOnILockBytes(ILockBytes FAR *plkbyt,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgIsStorageFile(const XCHAR FAR* pwcsName);
+STDAPI StgIsStorageILockBytes(ILockBytes FAR* plkbyt);
+
+STDAPI StgSetTimes(XCHAR const FAR* lpszName,
+ FILETIME const FAR* pctime,
+ FILETIME const FAR* patime,
+ FILETIME const FAR* pmtime);
+
+#endif
diff --git a/private/ole32/stg/ole2flat/valid.h b/private/ole32/stg/ole2flat/valid.h
new file mode 100644
index 000000000..0c25dc733
--- /dev/null
+++ b/private/ole32/stg/ole2flat/valid.h
@@ -0,0 +1,72 @@
+#define IsValidPtrIn(pv,cb) (!IsBadReadPtr ((pv),(cb)))
+#define IsValidPtrOut(pv,cb) (!IsBadWritePtr((pv),(cb)))
+
+STDAPI_(BOOL) IsValidInterface( void FAR* pv );
+STDAPI_(BOOL) IsValidIid( REFIID riid );
+
+
+#ifdef _DEBUG
+
+//** POINTER IN validation macros:
+#define VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid in ptr", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTRIN( pv, TYPE, retval ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid in ptr", _szAssertFile, __LINE__), retval)
+#define VOID_VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) {\
+ FnAssert(#pv,"Invalid in ptr", _szAssertFile, __LINE__); return; }
+
+//** POINTER OUT validation macros:
+#define VDATEPTROUT( pv, TYPE ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid out ptr", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTROUT( pv, TYPE, retval ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid out ptr", _szAssertFile, __LINE__), retval)
+
+//** INTERFACE validation macro:
+#define GEN_VDATEIFACE( pv, retval ) if (!IsValidInterface(pv)) \
+ return (FnAssert(#pv,"Invalid interface", _szAssertFile, __LINE__), retval)
+#define VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return (FnAssert(#pv,"Invalid interface", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define VOID_VDATEIFACE( pv ) if (!IsValidInterface(pv)) {\
+ FnAssert(#pv,"Invalid interface", _szAssertFile, __LINE__); return; }
+
+//** INTERFACE ID validation macro:
+#define VDATEIID( iid ) if (!IsValidIid( iid )) \
+ return (FnAssert(#iid,"Invalid iid", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEIID( iid, retval ) if (!IsValidIid( iid )) {\
+ FnAssert(#iid,"Invalid iid", _szAssertFile, __LINE__); return retval; }
+#else
+
+
+
+// --assertless macros for non-debug case
+//** POINTER IN validation macros:
+#define VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTRIN( pv, TYPE, retval ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (retval)
+#define VOID_VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) {\
+ return; }
+
+//** POINTER OUT validation macros:
+#define VDATEPTROUT( pv, TYPE ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (ResultFromScode(E_INVALIDARG))
+
+#define GEN_VDATEPTROUT( pv, TYPE, retval ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (retval)
+
+//** INTERFACE validation macro:
+#define VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return (ResultFromScode(E_INVALIDARG))
+#define VOID_VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return;
+#define GEN_VDATEIFACE( pv, retval ) if (!IsValidInterface(pv)) \
+ return (retval)
+
+//** INTERFACE ID validation macro:
+#define VDATEIID( iid ) if (!IsValidIid( iid )) \
+ return (ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEIID( iid, retval ) if (!IsValidIid( iid )) \
+ return retval;
+
+#endif
+
diff --git a/private/ole32/stg/ole2flat/verinfo.h b/private/ole32/stg/ole2flat/verinfo.h
new file mode 100644
index 000000000..4267128fd
--- /dev/null
+++ b/private/ole32/stg/ole2flat/verinfo.h
@@ -0,0 +1,22 @@
+
+#ifdef RC_INVOKED
+
+#include <ver.h>
+
+#define VER_FILEVERSION_STR "2.01\0"
+#define VER_FILEVERSION 2,01,0100,06
+
+#define VER_PRODUCTNAME_STR "Microsoft OLE 2.01 for Windows\0"
+#define VER_COMPANYNAME_STR "Microsoft Corporation\0"
+#define VER_LEGALTRADEMARKS_STR "Microsoft\256 is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation\0"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corp. 1992 - 1993\0"
+#define VER_PRODUCTVERSION_STR "2.01\0"
+#define VER_PRODUCTVERSION 2,01,0100,06
+#define VER_COMMENT_STR "Windows OLE DLLs\0"
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE 0
+#define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#define VER_FILEFLAGS 0L
+#define VER_FILEOS VOS_DOS_WINDOWS16
+
+#endif /* RC_INVOKED */
diff --git a/private/ole32/stg/ole2h/coguid.h b/private/ole32/stg/ole2h/coguid.h
new file mode 100644
index 000000000..a872d6919
--- /dev/null
+++ b/private/ole32/stg/ole2h/coguid.h
@@ -0,0 +1,52 @@
+/* this file is the master definition of all GUIDs for the component object
+ model and is included in compobj.h. Some GUIDs for moinkers and storage
+ appear here as well. All of these GUIDs are OLE GUIDs only in the sense
+ that part of the GUID range owned by OLE was used to define them.
+
+ NOTE: The second byte of all of these GUIDs is 0.
+*/
+
+
+DEFINE_GUID(GUID_NULL, 0L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+DEFINE_OLEGUID(IID_IUnknown, 0x00000000L, 0, 0);
+DEFINE_OLEGUID(IID_IClassFactory, 0x00000001L, 0, 0);
+DEFINE_OLEGUID(IID_IMalloc, 0x00000002L, 0, 0);
+DEFINE_OLEGUID(IID_IMarshal, 0x00000003L, 0, 0);
+
+/* RPC related interfaces */
+DEFINE_OLEGUID(IID_IRpcChannel, 0x00000004L, 0, 0);
+DEFINE_OLEGUID(IID_IRpcStub, 0x00000005L, 0, 0);
+DEFINE_OLEGUID(IID_IStubManager, 0x00000006L, 0, 0);
+DEFINE_OLEGUID(IID_IRpcProxy, 0x00000007L, 0, 0);
+DEFINE_OLEGUID(IID_IProxyManager, 0x00000008L, 0, 0);
+DEFINE_OLEGUID(IID_IPSFactory, 0x00000009L, 0, 0);
+
+/* storage related interfaces */
+DEFINE_OLEGUID(IID_ILockBytes, 0x0000000aL, 0, 0);
+DEFINE_OLEGUID(IID_IStorage, 0x0000000bL, 0, 0);
+DEFINE_OLEGUID(IID_IStream, 0x0000000cL, 0, 0);
+DEFINE_OLEGUID(IID_IEnumSTATSTG, 0x0000000dL, 0, 0);
+
+/* moniker related interfaces */
+DEFINE_OLEGUID(IID_IBindCtx, 0x0000000eL, 0, 0);
+DEFINE_OLEGUID(IID_IMoniker, 0x0000000fL, 0, 0);
+DEFINE_OLEGUID(IID_IRunningObjectTable, 0x00000010L, 0, 0);
+DEFINE_OLEGUID(IID_IInternalMoniker, 0x00000011L, 0, 0);
+
+/* storage related interfaces */
+DEFINE_OLEGUID(IID_IRootStorage, 0x00000012L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved1, 0x00000013L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved2, 0x00000014L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved3, 0x00000015L, 0, 0);
+
+/* concurrency releated interfaces */
+DEFINE_OLEGUID(IID_IMessageFilter, 0x00000016L, 0, 0);
+
+/* CLSID of standard marshaler */
+DEFINE_OLEGUID(CLSID_StdMarshal, 0x00000017L, 0, 0);
+
+/* interface on server for getting info for std marshaler */
+DEFINE_OLEGUID(IID_IStdMarshalInfo, 0x00000018L, 0, 0);
+
+/* NOTE: LSB 0x19 through 0xff are reserved for future use */
diff --git a/private/ole32/stg/ole2h/compobj.h b/private/ole32/stg/ole2h/compobj.h
new file mode 100644
index 000000000..1967433e5
--- /dev/null
+++ b/private/ole32/stg/ole2h/compobj.h
@@ -0,0 +1,1025 @@
+/*****************************************************************************\
+* *
+* compobj.h - Component object model definitions *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#if !defined( _COMPOBJ_H_ )
+#define _COMPOBJ_H_
+
+/****** Linkage Definitions *************************************************/
+
+/*
+ * These are macros for declaring methods/functions. They exist so that
+ * control over the use of keywords (CDECL, PASCAL, __export,
+ * extern "C") resides in one place, and because this is the least
+ * intrusive way of writing function declarations that do not have
+ * to be modified in order to port to the Mac.
+ *
+ * The macros without the trailing underscore are for functions/methods
+ * which a return value of type HRESULT; this is by far the most common
+ * case in OLE. The macros with a trailing underscore take a return
+ * type as a parameter.
+ *
+ * WARNING: STDAPI is hard coded into the LPFNGETCLASSOBJECT typedef below.
+ */
+
+#ifdef __cplusplus
+ #define EXTERN_C extern "C"
+#else
+ #define EXTERN_C extern
+#endif
+
+#ifdef _MAC
+#define STDMETHODCALLTYPE
+#define STDAPICALLTYPE pascal
+
+#define STDAPI EXTERN_C STDAPICALLTYPE HRESULT
+#define STDAPI_(type) EXTERN_C STDAPICALLTYPE type
+
+#else // !_MAC
+
+#ifdef WIN32
+#define STDMETHODCALLTYPE __export __cdecl
+#define STDAPICALLTYPE __export __stdcall
+
+#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE
+#define STDAPI_(type) EXTERN_C type STDAPICALLTYPE
+
+#else
+#define STDMETHODCALLTYPE __export FAR CDECL
+#define STDAPICALLTYPE __export FAR PASCAL
+
+#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE
+#define STDAPI_(type) EXTERN_C type STDAPICALLTYPE
+
+#endif
+
+#endif //!_MAC
+
+#define STDMETHODIMP HRESULT STDMETHODCALLTYPE
+#define STDMETHODIMP_(type) type STDMETHODCALLTYPE
+
+
+/****** Interface Declaration ***********************************************/
+
+/*
+ * These are macros for declaring interfaces. They exist so that
+ * a single definition of the interface is simulataneously a proper
+ * declaration of the interface structures (C++ abstract classes)
+ * for both C and C++.
+ *
+ * DECLARE_INTERFACE(iface) is used to declare an interface that does
+ * not derive from a base interface.
+ * DECLARE_INTERFACE_(iface, baseiface) is used to declare an interface
+ * that does derive from a base interface.
+ *
+ * By default if the source file has a .c extension the C version of
+ * the interface declaratations will be expanded; if it has a .cpp
+ * extension the C++ version will be expanded. if you want to force
+ * the C version expansion even though the source file has a .cpp
+ * extension, then define the macro "CINTERFACE".
+ * eg. cl -DCINTERFACE file.cpp
+ *
+ * Example Interface declaration:
+ *
+ * #undef INTERFACE
+ * #define INTERFACE IClassFactory
+ *
+ * DECLARE_INTERFACE_(IClassFactory, IUnknown)
+ * {
+ * // *** IUnknown methods ***
+ * STDMETHOD(QueryInterface) (THIS_
+ * REFIID riid,
+ * LPVOID FAR* ppvObj) PURE;
+ * STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ * STDMETHOD_(ULONG,Release) (THIS) PURE;
+ *
+ * // *** IClassFactory methods ***
+ * STDMETHOD(CreateInstance) (THIS_
+ * LPUNKNOWN pUnkOuter,
+ * REFIID riid,
+ * LPVOID FAR* ppvObject) PURE;
+ * };
+ *
+ * Example C++ expansion:
+ *
+ * struct FAR IClassFactory : public IUnknown
+ * {
+ * virtual HRESULT STDMETHODCALLTYPE QueryInterface(
+ * IID FAR& riid,
+ * LPVOID FAR* ppvObj) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE AddRef(void) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE Release(void) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE CreateInstance(
+ * LPUNKNOWN pUnkOuter,
+ * IID FAR& riid,
+ * LPVOID FAR* ppvObject) = 0;
+ * };
+ *
+ * NOTE: Our documentation says '#define interface class' but we use
+ * 'struct' instead of 'class' to keep a lot of 'public:' lines
+ * out of the interfaces. The 'FAR' forces the 'this' pointers to
+ * be far, which is what we need.
+ *
+ * Example C expansion:
+ *
+ * typedef struct IClassFactory
+ * {
+ * const struct IClassFactoryVtbl FAR* lpVtbl;
+ * } IClassFactory;
+ *
+ * typedef struct IClassFactoryVtbl IClassFactoryVtbl;
+ *
+ * struct IClassFactoryVtbl
+ * {
+ * HRESULT (STDMETHODCALLTYPE * QueryInterface) (
+ * IClassFactory FAR* This,
+ * IID FAR* riid,
+ * LPVOID FAR* ppvObj) ;
+ * HRESULT (STDMETHODCALLTYPE * AddRef) (IClassFactory FAR* This) ;
+ * HRESULT (STDMETHODCALLTYPE * Release) (IClassFactory FAR* This) ;
+ * HRESULT (STDMETHODCALLTYPE * CreateInstance) (
+ * IClassFactory FAR* This,
+ * LPUNKNOWN pUnkOuter,
+ * IID FAR* riid,
+ * LPVOID FAR* ppvObject);
+ * HRESULT (STDMETHODCALLTYPE * LockServer) (
+ * IClassFactory FAR* This,
+ * BOOL fLock);
+ * };
+ */
+
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+#ifdef __TURBOC__
+#define interface struct huge
+#else
+#define interface struct FAR
+#endif
+#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method
+#define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method
+#define PURE = 0
+#define THIS_
+#define THIS void
+#define DECLARE_INTERFACE(iface) interface iface
+#define DECLARE_INTERFACE_(iface, baseiface) interface iface : public baseiface
+
+#else
+#define interface struct
+
+#ifdef _MAC
+
+#define STDMETHOD(method) long method##pad;\
+ HRESULT (STDMETHODCALLTYPE * method)
+#define STDMETHOD_(type,method) long method##pad;\
+ type (STDMETHODCALLTYPE * method)
+
+#else // _MAC
+
+#define STDMETHOD(method) HRESULT (STDMETHODCALLTYPE * method)
+#define STDMETHOD_(type,method) type (STDMETHODCALLTYPE * method)
+
+#endif // !_MAC
+
+#define PURE
+#define THIS_ INTERFACE FAR* This,
+#define THIS INTERFACE FAR* This
+#ifdef CONST_VTABLE
+#define DECLARE_INTERFACE(iface) typedef interface iface { \
+ const struct iface##Vtbl FAR* lpVtbl; \
+ } iface; \
+ typedef const struct iface##Vtbl iface##Vtbl; \
+ const struct iface##Vtbl
+#else
+#define DECLARE_INTERFACE(iface) typedef interface iface { \
+ struct iface##Vtbl FAR* lpVtbl; \
+ } iface; \
+ typedef struct iface##Vtbl iface##Vtbl; \
+ struct iface##Vtbl
+#endif
+#define DECLARE_INTERFACE_(iface, baseiface) DECLARE_INTERFACE(iface)
+
+#endif
+
+#if defined(TUNING)
+ #define LOCAL static
+#else
+ #define LOCAL static
+#endif
+
+
+/****** Additional basic types **********************************************/
+
+
+#ifndef FARSTRUCT
+#ifdef __cplusplus
+#define FARSTRUCT FAR
+#else
+#define FARSTRUCT
+#endif // __cplusplus
+#endif // FARSTRUCT
+
+
+#ifndef WINAPI /* If not included with 3.1 headers... */
+
+#ifdef WIN32
+#define FAR
+#define PASCAL __stdcall
+#define CDECL
+#else
+#define FAR _far
+#define PASCAL _pascal
+#define CDECL _cdecl
+#endif
+
+#define VOID void
+#define WINAPI FAR PASCAL
+#define CALLBACK FAR PASCAL
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+typedef int BOOL;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned int UINT;
+
+typedef long LONG;
+typedef unsigned long DWORD;
+
+
+typedef UINT WPARAM;
+typedef LONG LPARAM;
+typedef LONG LRESULT;
+
+typedef unsigned int HANDLE;
+#define DECLARE_HANDLE(name) typedef UINT name
+
+DECLARE_HANDLE(HMODULE);
+DECLARE_HANDLE(HINSTANCE);
+DECLARE_HANDLE(HLOCAL);
+DECLARE_HANDLE(HGLOBAL);
+DECLARE_HANDLE(HDC);
+DECLARE_HANDLE(HRGN);
+DECLARE_HANDLE(HWND);
+DECLARE_HANDLE(HMENU);
+DECLARE_HANDLE(HACCEL);
+DECLARE_HANDLE(HTASK);
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+typedef void FAR * LPVOID;
+typedef WORD FAR * LPWORD;
+typedef DWORD FAR * LPDWORD;
+typedef char FAR* LPSTR;
+typedef const char FAR* LPCSTR;
+typedef void FAR* LPLOGPALETTE;
+typedef void FAR* LPMSG;
+//typedef struct tagMSG FAR *LPMSG;
+
+typedef HANDLE FAR *LPHANDLE;
+typedef struct tagRECT FAR *LPRECT;
+
+typedef struct FARSTRUCT tagSIZE
+{
+ int cx;
+ int cy;
+} SIZE;
+typedef SIZE* PSIZE;
+
+
+#endif /* WINAPI */
+
+
+typedef short SHORT;
+typedef unsigned short USHORT;
+typedef DWORD ULONG;
+
+
+#ifndef HUGEP
+#ifdef WIN32
+#define HUGEP
+#else
+#define HUGEP __huge
+#endif // WIN32
+#endif // HUGEP
+
+typedef WORD WCHAR;
+
+#ifndef WIN32
+typedef struct FARSTRUCT _LARGE_INTEGER {
+ DWORD LowPart;
+ LONG HighPart;
+} LARGE_INTEGER, *PLARGE_INTEGER;
+#endif
+#define LISet32(li, v) ((li).HighPart = ((LONG)(v)) < 0 ? -1 : 0, (li).LowPart = (v))
+
+#ifndef WIN32
+typedef struct FARSTRUCT _ULARGE_INTEGER {
+ DWORD LowPart;
+ DWORD HighPart;
+} ULARGE_INTEGER, *PULARGE_INTEGER;
+#endif
+#define ULISet32(li, v) ((li).HighPart = 0, (li).LowPart = (v))
+
+#ifndef _WINDOWS_
+#ifndef _FILETIME_
+#define _FILETIME_
+typedef struct FARSTRUCT tagFILETIME
+{
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+} FILETIME;
+#endif
+#endif
+
+#ifdef WIN32
+#define HTASK DWORD
+#endif
+
+#include "scode.h"
+
+
+
+// *********************** Compobj errors **********************************
+
+#define CO_E_NOTINITIALIZED (CO_E_FIRST + 0x0)
+// CoInitialize has not been called and must be
+
+#define CO_E_ALREADYINITIALIZED (CO_E_FIRST + 0x1)
+// CoInitialize has already been called and cannot be called again (temporary)
+
+#define CO_E_CANTDETERMINECLASS (CO_E_FIRST + 0x2)
+// can't determine clsid (e.g., extension not in reg.dat)
+
+#define CO_E_CLASSSTRING (CO_E_FIRST + 0x3)
+// the string form of the clsid is invalid (including ole1 classes)
+
+#define CO_E_IIDSTRING (CO_E_FIRST + 0x4)
+// the string form of the iid is invalid
+
+#define CO_E_APPNOTFOUND (CO_E_FIRST + 0x5)
+// application not found
+
+#define CO_E_APPSINGLEUSE (CO_E_FIRST + 0x6)
+// application cannot be run more than once
+
+#define CO_E_ERRORINAPP (CO_E_FIRST + 0x7)
+// some error in the app program file
+
+#define CO_E_DLLNOTFOUND (CO_E_FIRST + 0x8)
+// dll not found
+
+#define CO_E_ERRORINDLL (CO_E_FIRST + 0x9)
+// some error in the dll file
+
+#define CO_E_WRONGOSFORAPP (CO_E_FIRST + 0xa)
+// app written for other version of OS or other OS altogether
+
+#define CO_E_OBJNOTREG (CO_E_FIRST + 0xb)
+// object is not registered
+
+#define CO_E_OBJISREG (CO_E_FIRST + 0xc)
+// object is already registered
+
+#define CO_E_OBJNOTCONNECTED (CO_E_FIRST + 0xd)
+// handler is not connected to server
+
+#define CO_E_APPDIDNTREG (CO_E_FIRST + 0xe)
+// app was launched, but didn't registered a class factory
+
+
+// ********************* ClassObject errors ********************************
+
+#define CLASS_E_NOAGGREGATION (CLASSFACTORY_E_FIRST + 0x0)
+// class does not support aggregation (or class object is remote)
+
+
+// *********************** Reg.dat errors **********************************
+
+#define REGDB_E_READREGDB (REGDB_E_FIRST + 0x0)
+// some error reading the registration database
+
+#define REGDB_E_WRITEREGDB (REGDB_E_FIRST + 0x1)
+// some error reading the registration database
+
+#define REGDB_E_KEYMISSING (REGDB_E_FIRST + 0x2)
+// some error reading the registration database
+
+#define REGDB_E_INVALIDVALUE (REGDB_E_FIRST + 0x3)
+// some error reading the registration database
+
+#define REGDB_E_CLASSNOTREG (REGDB_E_FIRST + 0x4)
+// some error reading the registration database
+
+#define REGDB_E_IIDNOTREG (REGDB_E_FIRST + 0x5)
+// some error reading the registration database
+
+
+// *************************** RPC errors **********************************
+
+#define RPC_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_RPC, 0x000)
+
+// call was rejected by callee, either by MF::HandleIncomingCall or
+#define RPC_E_CALL_REJECTED (RPC_E_FIRST + 0x1)
+
+// call was canceld by call - returned by MessagePending
+// this code only occurs if MessagePending return cancel
+#define RPC_E_CALL_CANCELED (RPC_E_FIRST + 0x2)
+
+// the caller is dispatching an intertask SendMessage call and
+// can NOT call out via PostMessage
+#define RPC_E_CANTPOST_INSENDCALL (RPC_E_FIRST + 0x3)
+
+// the caller is dispatching an asynchronus call can NOT
+// make an outgoing call on behalf of this call
+#define RPC_E_CANTCALLOUT_INASYNCCALL (RPC_E_FIRST + 0x4)
+
+// the caller is not in a state where an outgoing call can be made
+// this is the case if the caller has an outstandig call and
+// another incoming call was excepted by HIC; now the caller is
+// not allowed to call out again
+#define RPC_E_CANTCALLOUT_INEXTERNALCALL (RPC_E_FIRST + 0x5)
+
+// the connection terminated or is in a bogus state
+// and can not be used any more. Other connections
+// are still valid.
+#define RPC_E_CONNECTION_TERMINATED (RPC_E_FIRST + 0x6)
+
+// the callee (server [not server application]) is not available
+// and disappeared; all connections are invalid
+#define RPC_E_SERVER_DIED (RPC_E_FIRST + 0x7)
+
+// the caller (client ) disappeared while the callee (server) was
+// processing a call
+#define RPC_E_CLIENT_DIED (RPC_E_FIRST + 0x8)
+
+// the date paket with the marshalled parameter data is
+// incorrect
+#define RPC_E_INVALID_DATAPACKET (RPC_E_FIRST + 0x9)
+
+// the call was not transmitted properly; the message queue
+// was full and was not emptied after yielding
+#define RPC_E_CANTTRANSMIT_CALL (RPC_E_FIRST + 0xa)
+
+// the client (caller) can not marshall the parameter data
+// or unmarshall the return data - low memory etc.
+#define RPC_E_CLIENT_CANTMARSHAL_DATA (RPC_E_FIRST + 0xb)
+#define RPC_E_CLIENT_CANTUNMARSHAL_DATA (RPC_E_FIRST + 0xc)
+
+// the server (caller) can not unmarshall the parameter data
+// or marshall the return data - low memory
+#define RPC_E_SERVER_CANTMARSHAL_DATA (RPC_E_FIRST + 0xd)
+#define RPC_E_SERVER_CANTUNMARSHAL_DATA (RPC_E_FIRST + 0xe)
+
+// received data are invalid; can be server or
+// client data
+#define RPC_E_INVALID_DATA (RPC_E_FIRST + 0xf)
+
+// a particular parameter is invalid and can not be un/marshalled
+#define RPC_E_INVALID_PARAMETER (RPC_E_FIRST + 0x10)
+
+
+// a internal error occured
+#define RPC_E_UNEXPECTED (RPC_E_FIRST + 0xFFFF)
+
+
+/****** Globally Unique Ids *************************************************/
+
+#ifdef __cplusplus
+
+struct FAR GUID
+{
+ DWORD Data1;
+ WORD Data2;
+ WORD Data3;
+ BYTE Data4[8];
+
+ BOOL operator==(const GUID& iidOther) const
+
+#ifdef WIN32
+ { return !memcmp(&Data1,&iidOther.Data1,sizeof(GUID)); }
+#else
+ { return !_fmemcmp(&Data1,&iidOther.Data1,sizeof(GUID)); }
+#endif
+ BOOL operator!=(const GUID& iidOther) const
+ { return !((*this) == iidOther); }
+};
+
+#else
+typedef struct GUID
+{
+ DWORD Data1;
+ WORD Data2;
+ WORD Data3;
+ BYTE Data4[8];
+} GUID;
+#endif
+
+typedef GUID FAR* LPGUID;
+
+
+// macros to define byte pattern for a GUID.
+// Example: DEFINE_GUID(GUID_XXX, a, b, c, ...);
+//
+// Each dll/exe must initialize the GUIDs once. This is done in one of
+// two ways. If you are not using precompiled headers for the file(s) which
+// initializes the GUIDs, define INITGUID before including compobj.h. This
+// is how OLE builds the initialized versions of the GUIDs which are included
+// in ole2.lib. The GUIDs in ole2.lib are all defined in the same text
+// segment GUID_TEXT.
+//
+// The alternative (which some versions of the compiler don't handle properly;
+// they wind up with the initialized GUIDs in a data, not a text segment),
+// is to use a precompiled version of compobj.h and then include initguid.h
+// after compobj.h followed by one or more of the guid defintion files.
+
+
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID CDECL FAR name
+
+#ifdef INITGUID
+#include "initguid.h"
+#endif
+
+#define DEFINE_OLEGUID(name, l, w1, w2) \
+ DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)
+
+
+// Interface ID are just a kind of GUID
+typedef GUID IID;
+typedef IID FAR* LPIID;
+#define IID_NULL GUID_NULL
+#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2)
+
+
+// Class ID are just a kind of GUID
+typedef GUID CLSID;
+typedef CLSID FAR* LPCLSID;
+#define CLSID_NULL GUID_NULL
+#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2)
+
+
+#if defined(__cplusplus)
+#define REFGUID const GUID FAR&
+#define REFIID const IID FAR&
+#define REFCLSID const CLSID FAR&
+#else
+#define REFGUID const GUID FAR* const
+#define REFIID const IID FAR* const
+#define REFCLSID const CLSID FAR* const
+#endif
+
+
+#ifndef INITGUID
+#include "coguid.h"
+#endif
+
+/****** Other value types ***************************************************/
+
+// memory context values; passed to CoGetMalloc
+typedef enum tagMEMCTX
+{
+ MEMCTX_TASK = 1, // task (private) memory
+ MEMCTX_SHARED = 2, // shared memory (between processes)
+#ifdef _MAC
+ MEMCTX_MACSYSTEM = 3, // on the mac, the system heap
+#endif
+
+ // these are mostly for internal use...
+ MEMCTX_UNKNOWN = -1, // unknown context (when asked about it)
+ MEMCTX_SAME = -2, // same context (as some other pointer)
+} MEMCTX;
+
+
+
+// class context: used to determine what scope and kind of class object to use
+// NOTE: this is a bitwise enum
+typedef enum tagCLSCTX
+{
+ CLSCTX_INPROC_SERVER = 1, // server dll (runs in same process as caller)
+ CLSCTX_INPROC_HANDLER = 2, // handler dll (runs in same process as caller)
+ CLSCTX_LOCAL_SERVER = 4 // server exe (runs on same machine; diff proc)
+} CLSCTX;
+
+#define CLSCTX_ALL (CLSCTX_INPROC_SERVER| \
+ CLSCTX_INPROC_HANDLER| \
+ CLSCTX_LOCAL_SERVER)
+
+#define CLSCTX_INPROC (CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER)
+
+#define CLSCTX_SERVER (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER)
+
+
+// class registration flags; passed to CoRegisterClassObject
+typedef enum tagREGCLS
+{
+ REGCLS_SINGLEUSE = 0, // class object only generates one instance
+ REGCLS_MULTIPLEUSE = 1, // same class object genereates multiple inst.
+ // and local automatically goes into inproc tbl.
+ REGCLS_MULTI_SEPARATE = 2, // multiple use, but separate control over each
+ // context.
+
+ // NOTE: CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE is the same as
+ // (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER), REGCLS_MULTI_SEPARATE, but
+ // not the same as CLSCTX_LOCAL_SERVER, REGCLS_MULTI_SEPARATE.
+} REGCLS;
+
+
+// interface marshaling definitions
+#define MARSHALINTERFACE_MIN 40 // minimum number of bytes for interface marshl
+
+// marshaling flags; passed to CoMarshalInterface
+typedef enum tagMSHLFLAGS
+{
+ MSHLFLAGS_NORMAL = 0, // normal marshaling via proxy/stub
+ MSHLFLAGS_TABLESTRONG = 1, // keep object alive; must explicitly release
+ MSHLFLAGS_TABLEWEAK = 2 // doesn't hold object alive; still must release
+} MSHLFLAGS;
+
+// marshal context: determines the destination context of the marshal operation
+typedef enum tagMSHCTX
+{
+ MSHCTX_LOCAL = 0, // unmarshal context is local (eg.shared memory)
+ MSHCTX_NOSHAREDMEM = 1, // unmarshal context has no shared memory access
+} MSHCTX;
+
+
+// call type used by IMessageFilter::HandleIncommingMessage
+typedef enum tagCALLTYPE
+{
+ CALLTYPE_TOPLEVEL = 1, // toplevel call - no outgoing call
+ CALLTYPE_NESTED = 2, // callback on behalf of previous outgoing call - should always handle
+ CALLTYPE_ASYNC = 3, // aysnchronous call - can NOT be rejected
+ CALLTYPE_TOPLEVEL_CALLPENDING = 4, // new toplevel call with new LID
+ CALLTYPE_ASYNC_CALLPENDING = 5 // async call - can NOT be rejected
+} CALLTYPE;
+
+typedef struct tagINTERFACEINFO
+{
+ interface IUnknown FAR *pUnk; // the pointer to the object
+ IID iid; // interface id
+ WORD wMethod; // interface methode
+} INTERFACEINFO, FAR * LPINTERFACEINFO;
+
+// status of server call - returned by IMessageFilter::HandleIncommingCall
+// and passed to IMessageFilter::RetryRejectedCall
+typedef enum tagSERVERCALL
+{
+ SERVERCALL_ISHANDLED = 0,
+ SERVERCALL_REJECTED = 1,
+ SERVERCALL_RETRYLATER = 2
+} SERVERCALL;
+
+
+// Pending type indicates the level of nesting
+typedef enum tagPENDINGTYPE
+{
+ PENDINGTYPE_TOPLEVEL = 1, // toplevel call
+ PENDINGTYPE_NESTED = 2, // nested call
+} PENDINGTYPE;
+
+// return values of MessagePending
+typedef enum tagPENDINGMSG
+{
+ PENDINGMSG_CANCELCALL = 0, // cancel the outgoing call
+ PENDINGMSG_WAITNOPROCESS = 1, // wait for the return and don't dispatch the message
+ PENDINGMSG_WAITDEFPROCESS = 2 // wait and dispatch the message
+
+} PENDINGMSG;
+
+/****** IUnknown Interface **************************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IUnknown
+
+DECLARE_INTERFACE(IUnknown)
+{
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+};
+
+typedef IUnknown FAR* LPUNKNOWN;
+
+
+/****** Class Factory Interface *******************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IClassFactory
+
+DECLARE_INTERFACE_(IClassFactory, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IClassFactory methods ***
+ STDMETHOD(CreateInstance) (THIS_ LPUNKNOWN pUnkOuter,
+ REFIID riid,
+ LPVOID FAR* ppvObject) PURE;
+ STDMETHOD(LockServer) (THIS_ BOOL fLock) PURE;
+
+};
+typedef IClassFactory FAR* LPCLASSFACTORY;
+
+
+/****** Memory Allocation Interface ***************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IMalloc
+
+DECLARE_INTERFACE_(IMalloc, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IMalloc methods ***
+ STDMETHOD_(void FAR*, Alloc) (THIS_ ULONG cb) PURE;
+ STDMETHOD_(void FAR*, Realloc) (THIS_ void FAR* pv, ULONG cb) PURE;
+ STDMETHOD_(void, Free) (THIS_ void FAR* pv) PURE;
+ STDMETHOD_(ULONG, GetSize) (THIS_ void FAR* pv) PURE;
+ STDMETHOD_(int, DidAlloc) (THIS_ void FAR* pv) PURE;
+ STDMETHOD_(void, HeapMinimize) (THIS) PURE;
+};
+typedef IMalloc FAR* LPMALLOC;
+
+
+/****** IMarshal Interface ************************************************/
+
+// forward declaration for IStream; must include storage.h later to use
+#ifdef __cplusplus
+interface IStream;
+#else
+typedef interface IStream IStream;
+#endif
+typedef IStream FAR* LPSTREAM;
+
+
+#undef INTERFACE
+#define INTERFACE IMarshal
+
+DECLARE_INTERFACE_(IMarshal, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IMarshal methods ***
+ STDMETHOD(GetUnmarshalClass)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPCLSID pCid) PURE;
+ STDMETHOD(GetMarshalSizeMax)(THIS_ REFIID riid, LPVOID pv,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags, LPDWORD pSize) PURE;
+ STDMETHOD(MarshalInterface)(THIS_ LPSTREAM pStm, REFIID riid,
+ LPVOID pv, DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags) PURE;
+ STDMETHOD(UnmarshalInterface)(THIS_ LPSTREAM pStm, REFIID riid,
+ LPVOID FAR* ppv) PURE;
+ STDMETHOD(ReleaseMarshalData)(THIS_ LPSTREAM pStm) PURE;
+ STDMETHOD(DisconnectObject)(THIS_ DWORD dwReserved) PURE;
+};
+typedef IMarshal FAR* LPMARSHAL;
+
+
+#undef INTERFACE
+#define INTERFACE IStdMarshalInfo
+
+DECLARE_INTERFACE_(IStdMarshalInfo, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IStdMarshalInfo methods ***
+ STDMETHOD(GetClassForHandler)(THIS_ DWORD dwDestContext,
+ LPVOID pvDestContext, LPCLSID pClsid) PURE;
+};
+typedef IStdMarshalInfo FAR* LPSTDMARSHALINFO;
+
+
+/****** Message Filter Interface *******************************************/
+
+
+#undef INTERFACE
+#define INTERFACE IMessageFilter
+
+DECLARE_INTERFACE_(IMessageFilter, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IMessageFilter methods ***
+ STDMETHOD_(DWORD, HandleInComingCall) (THIS_ DWORD dwCallType,
+ HTASK htaskCaller, DWORD dwTickCount,
+ DWORD dwReserved ) PURE;
+ STDMETHOD_(DWORD, RetryRejectedCall) (THIS_
+ HTASK htaskCallee, DWORD dwTickCount,
+ DWORD dwRejectType ) PURE;
+ STDMETHOD_(DWORD, MessagePending) (THIS_
+ HTASK htaskCallee, DWORD dwTickCount,
+ DWORD dwPendingType ) PURE;
+};
+typedef IMessageFilter FAR* LPMESSAGEFILTER;
+
+
+/****** External Connection Information ***********************************/
+
+#undef INTERFACE
+#define INTERFACE IExternalConnection
+
+DECLARE_INTERFACE_(IExternalConnection, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IExternalConnection methods ***
+ STDMETHOD_(DWORD, AddConnection) (THIS_ DWORD reserved) PURE;
+ STDMETHOD_(DWORD, ReleaseConnection) (THIS_ DWORD reserved, BOOL fLastReleaseCloses) PURE;
+};
+typedef IExternalConnection FAR* LPEXTERNALCONNECTION;
+
+
+/****** Enumerator Interfaces *********************************************/
+
+/*
+ * Since we don't use parametrized types, we put in explicit declarations
+ * of the enumerators we need.
+ */
+
+
+#undef INTERFACE
+#define INTERFACE IEnumString
+
+DECLARE_INTERFACE_(IEnumString, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumString methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt,
+ LPSTR FAR* rgelt,
+ ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumString FAR* FAR* ppenm) PURE;
+};
+typedef IEnumString FAR* LPENUMSTRING;
+
+
+#undef INTERFACE
+#define INTERFACE IEnumUnknown
+
+DECLARE_INTERFACE_(IEnumUnknown, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IEnumUnknown methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, LPUNKNOWN FAR* rgelt, ULONG FAR* pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumUnknown FAR* FAR* ppenm) PURE;
+};
+typedef IEnumUnknown FAR* LPENUMUNKNOWN;
+
+
+/****** STD Object API Prototypes *****************************************/
+
+STDAPI_(DWORD) CoBuildVersion( VOID );
+
+/* init/uninit */
+
+STDAPI CoInitialize(LPMALLOC pMalloc);
+STDAPI_(void) CoUninitialize(void);
+STDAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC FAR* ppMalloc);
+STDAPI_(DWORD) CoGetCurrentProcess(void);
+STDAPI CoCreateStandardMalloc(DWORD memctx, IMalloc FAR* FAR* ppMalloc);
+
+
+/* register/revoke/get class objects */
+
+STDAPI CoGetClassObject(REFCLSID rclsid, DWORD dwClsContext, LPVOID pvReserved,
+ REFIID riid, LPVOID FAR* ppv);
+STDAPI CoRegisterClassObject(REFCLSID rclsid, LPUNKNOWN pUnk,
+ DWORD dwClsContext, DWORD flags, LPDWORD lpdwRegister);
+STDAPI CoRevokeClassObject(DWORD dwRegister);
+
+
+/* marshaling interface pointers */
+
+STDAPI CoMarshalInterface(LPSTREAM pStm, REFIID riid, LPUNKNOWN pUnk,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags);
+STDAPI CoUnmarshalInterface(LPSTREAM pStm, REFIID riid, LPVOID FAR* ppv);
+STDAPI CoMarshalHresult(LPSTREAM pstm, HRESULT hresult);
+STDAPI CoUnmarshalHresult(LPSTREAM pstm, HRESULT FAR * phresult);
+STDAPI CoReleaseMarshalData(LPSTREAM pStm);
+STDAPI CoDisconnectObject(LPUNKNOWN pUnk, DWORD dwReserved);
+STDAPI CoLockObjectExternal(LPUNKNOWN pUnk, BOOL fLock, BOOL fLastUnlockReleases);
+STDAPI CoGetStandardMarshal(REFIID riid, LPUNKNOWN pUnk,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags,
+ LPMARSHAL FAR* ppMarshal);
+
+
+/* dll loading helpers; keeps track of ref counts and unloads all on exit */
+
+STDAPI_(HINSTANCE) CoLoadLibrary(LPSTR lpszLibName, BOOL bAutoFree);
+STDAPI_(void) CoFreeLibrary(HINSTANCE hInst);
+STDAPI_(void) CoFreeAllLibraries(void);
+STDAPI_(void) CoFreeUnusedLibraries(void);
+
+
+/* helper for creating instances */
+
+STDAPI CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
+ DWORD dwClsContext, REFIID riid, LPVOID FAR* ppv);
+
+
+/* other helpers */
+
+STDAPI_(BOOL) IsEqualGUID(REFGUID rguid1, REFGUID rguid2);
+STDAPI StringFromCLSID(REFCLSID rclsid, LPSTR FAR* lplpsz);
+STDAPI CLSIDFromString(LPSTR lpsz, LPCLSID pclsid);
+STDAPI StringFromIID(REFIID rclsid, LPSTR FAR* lplpsz);
+STDAPI IIDFromString(LPSTR lpsz, LPIID lpiid);
+STDAPI_(BOOL) CoIsOle1Class(REFCLSID rclsid);
+STDAPI ProgIDFromCLSID (REFCLSID clsid, LPSTR FAR* lplpszProgID);
+STDAPI CLSIDFromProgID (LPCSTR lpszProgID, LPCLSID lpclsid);
+STDAPI_(int) StringFromGUID2(REFGUID rguid, LPSTR lpsz, int cbMax);
+
+STDAPI CoCreateGuid(GUID FAR *pguid);
+
+STDAPI_(BOOL) CoFileTimeToDosDateTime(
+ FILETIME FAR* lpFileTime, LPWORD lpDosDate, LPWORD lpDosTime);
+STDAPI_(BOOL) CoDosDateTimeToFileTime(
+ WORD nDosDate, WORD nDosTime, FILETIME FAR* lpFileTime);
+STDAPI CoFileTimeNow( FILETIME FAR* lpFileTime );
+
+
+STDAPI CoRegisterMessageFilter( LPMESSAGEFILTER lpMessageFilter,
+ LPMESSAGEFILTER FAR* lplpMessageFilter );
+
+
+/* TreatAs APIS */
+
+STDAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID pClsidNew);
+STDAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew);
+
+
+/* the server dlls must define their DllGetClassObject and DllCanUnloadNow
+ * to match these; the typedefs are located here to ensure all are changed at
+ * the same time.
+ */
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID FAR* ppv);
+#ifdef _MAC
+typedef STDAPICALLTYPE HRESULT (FAR* LPFNGETCLASSOBJECT) (REFCLSID, REFIID, LPVOID FAR*);
+#else
+typedef HRESULT (STDAPICALLTYPE FAR* LPFNGETCLASSOBJECT) (REFCLSID, REFIID, LPVOID FAR*);
+#endif
+
+
+STDAPI DllCanUnloadNow(void);
+#ifdef _MAC
+typedef STDAPICALLTYPE HRESULT (FAR* LPFNCANUNLOADNOW)(void);
+#else
+typedef HRESULT (STDAPICALLTYPE FAR* LPFNCANUNLOADNOW)(void);
+#endif
+
+
+/****** Debugging Helpers *************************************************/
+
+#ifdef _DEBUG
+// writes to the debug port and displays a message box
+STDAPI FnAssert(LPSTR lpstrExpr, LPSTR lpstrMsg, LPSTR lpstrFileName, UINT iLine);
+#endif // _DEBUG
+
+#endif // _COMPOBJ_H_
diff --git a/private/ole32/stg/ole2h/initguid.h b/private/ole32/stg/ole2h/initguid.h
new file mode 100644
index 000000000..e7406e3c2
--- /dev/null
+++ b/private/ole32/stg/ole2h/initguid.h
@@ -0,0 +1,38 @@
+/*****************************************************************************\
+* *
+* initguid.h - Definitions for controlling GUID initialization *
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+// Include after compobj.h to enable GUID initialization. This
+// must be done once per exe/dll.
+//
+// After this file, include one or more of the GUID definition files.
+//
+// NOTE: ole2.lib contains references to all GUIDs defined by OLE.
+
+#ifndef DEFINE_GUID
+#pragma error "initguid: must include compobj.h first."
+#endif
+
+#undef DEFINE_GUID
+
+#ifdef _MAC
+#define __based(a)
+#endif
+
+#ifdef WIN32
+#define __based(a)
+#endif
+
+#ifdef __TURBOC__
+#define __based(a)
+#endif
+
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID CDECL __based(__segname("_CODE")) name \
+ = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
diff --git a/private/ole32/stg/ole2h/scode.h b/private/ole32/stg/ole2h/scode.h
new file mode 100644
index 000000000..5e673dfcb
--- /dev/null
+++ b/private/ole32/stg/ole2h/scode.h
@@ -0,0 +1,281 @@
+//+---------------------------------------------------------------------------
+//
+// File: SCode.h
+//
+// Contents: Defines standard status code services.
+//
+//
+//----------------------------------------------------------------------------
+
+#ifndef __SCODE_H__
+#define __SCODE_H__
+
+//
+// SCODE
+//
+
+typedef long SCODE;
+typedef SCODE *PSCODE;
+typedef void FAR * HRESULT;
+#define NOERROR 0
+
+//
+// Status values are 32 bit values layed out as follows:
+//
+// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-+---------------------+-------+-------------------------------+
+// |S| Context | Facil | Code |
+// +-+---------------------+-------+-------------------------------+
+//
+// where
+//
+// S - is the severity code
+//
+// 0 - Success
+// 1 - Error
+//
+// Context - context info
+//
+// Facility - is the facility code
+//
+// Code - is the facility's status code
+//
+
+//
+// Severity values
+//
+
+#define SEVERITY_SUCCESS 0
+#define SEVERITY_ERROR 1
+
+
+
+#define SUCCEEDED(Status) ((SCODE)(Status) >= 0)
+
+#define FAILED(Status) ((SCODE)(Status)<0)
+
+
+//
+// Return the code
+//
+
+#define SCODE_CODE(sc) ((sc) & 0xFFFF)
+
+//
+// Return the facility
+//
+
+#define SCODE_FACILITY(sc) (((sc) >> 16) & 0x1fff)
+
+//
+// Return the severity
+//
+
+#define SCODE_SEVERITY(sc) (((sc) >> 31) & 0x1)
+
+//
+// Create an SCODE value from component pieces
+//
+
+#define MAKE_SCODE(sev,fac,code) \
+ ((SCODE) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
+
+
+
+// --------------------- Functions ---------------------------------------
+
+#define GetScode(hr) ((SCODE)(hr) & 0x800FFFFF)
+#define ResultFromScode(sc) ((HRESULT)((SCODE)(sc) & 0x800FFFFF))
+
+STDAPI PropagateResult(HRESULT hrPrev, SCODE scNew);
+
+
+// -------------------------- Facility definitions -------------------------
+
+#define FACILITY_NULL 0x0000 // generally useful errors ([SE]_*)
+#define FACILITY_RPC 0x0001 // remote procedure call errors (RPC_E_*)
+#define FACILITY_DISPATCH 0x0002 // late binding dispatch errors
+#define FACILITY_STORAGE 0x0003 // storage errors (STG_E_*)
+#define FACILITY_ITF 0x0004 // interface-specific errors
+
+
+
+#define S_OK 0L
+#define S_FALSE MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 1)
+
+
+
+// --------------------- FACILITY_NULL errors ------------------------------
+
+#define E_UNEXPECTED MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 0xffff)
+ // relatively catastrophic failure
+
+#define E_NOTIMPL MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 1)
+ // not implemented
+
+#define E_OUTOFMEMORY MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 2)
+ // ran out of memory
+
+#define E_INVALIDARG MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 3)
+ // one or more arguments are invalid
+
+#define E_NOINTERFACE MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 4)
+ // no such interface supported
+
+
+#define E_POINTER MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 5)
+ // invalid pointer
+
+#define E_HANDLE MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 6)
+ // invalid handle
+
+#define E_ABORT MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 7)
+ // operation aborted
+
+#define E_FAIL MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 8)
+ // unspecified error
+
+
+#define E_ACCESSDENIED MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 9)
+ // general access denied error
+
+
+// ----------------- FACILITY_ITF errors used by OLE ---------------------
+//
+// By convention, OLE interfaces divide the FACILITY_ITF range of errors
+// into nonoverlapping subranges. If an OLE interface returns a FACILITY_ITF
+// scode, it must be from the range associated with that interface or from
+// the shared range: OLE_E_FIRST...OLE_E_LAST.
+//
+// The ranges, their associated interfaces, and the header file that defines
+// the actual scodes are given below.
+//
+
+// Generic OLE errors that may be returned by many interfaces
+#define OLE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0000)
+#define OLE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x00FF)
+#define OLE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0000)
+#define OLE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x00FF)
+// interfaces: all
+// file: ole2.h
+
+
+#define DRAGDROP_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0100)
+#define DRAGDROP_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x010F)
+#define DRAGDROP_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0100)
+#define DRAGDROP_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x010F)
+// interfaces: IDropSource, IDropTarget
+// file: ole2.h
+
+#define CLASSFACTORY_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0110)
+#define CLASSFACTORY_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x011F)
+#define CLASSFACTORY_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0110)
+#define CLASSFACTORY_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x011F)
+// interfaces: IClassFactory
+// file:
+
+#define MARSHAL_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0120)
+#define MARSHAL_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x012F)
+#define MARSHAL_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0120)
+#define MARSHAL_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x012F)
+// interfaces: IMarshal, IStdMarshalInfo, marshal APIs
+// file:
+
+#define DATA_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0130)
+#define DATA_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x013F)
+#define DATA_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0130)
+#define DATA_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x013F)
+// interfaces: IDataObject
+// file: dvobj.h
+
+#define VIEW_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0140)
+#define VIEW_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x014F)
+#define VIEW_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0140)
+#define VIEW_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x014F)
+// interfaces: IViewObject
+// file: dvobj.h
+
+#define REGDB_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0150)
+#define REGDB_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x015F)
+#define REGDB_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0150)
+#define REGDB_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x015F)
+// API: reg.dat manipulation
+// file:
+
+
+// range 160 - 16F reserved
+
+#define CACHE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0170)
+#define CACHE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x017F)
+#define CACHE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0170)
+#define CACHE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x017F)
+// interfaces: IOleCache
+// file:
+
+#define OLEOBJ_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0180)
+#define OLEOBJ_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x018F)
+#define OLEOBJ_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0180)
+#define OLEOBJ_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x018F)
+// interfaces: IOleObject
+// file:
+
+#define CLIENTSITE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0190)
+#define CLIENTSITE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x019F)
+#define CLIENTSITE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0190)
+#define CLIENTSITE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x019F)
+// interfaces: IOleClientSite
+// file:
+
+#define INPLACE_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01A0)
+#define INPLACE_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01AF)
+#define INPLACE_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01A0)
+#define INPLACE_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01AF)
+// interfaces: IOleWindow, IOleInPlaceObject, IOleInPlaceActiveObject,
+// IOleInPlaceUIWindow, IOleInPlaceFrame, IOleInPlaceSite
+// file:
+
+#define ENUM_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01B0)
+#define ENUM_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01BF)
+#define ENUM_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01B0)
+#define ENUM_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01BF)
+// interfaces: IEnum*
+// file:
+
+#define CONVERT10_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01C0)
+#define CONVERT10_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01CF)
+#define CONVERT10_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01C0)
+#define CONVERT10_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01CF)
+// API: OleConvertOLESTREAMToIStorage, OleConvertIStorageToOLESTREAM
+// file:
+
+
+#define CLIPBRD_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01D0)
+#define CLIPBRD_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01DF)
+#define CLIPBRD_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01D0)
+#define CLIPBRD_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01DF)
+// interfaces: OleSetClipboard, OleGetClipboard, OleFlushClipboard
+// file: ole2.h
+
+#define MK_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01E0)
+#define MK_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01EF)
+#define MK_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01E0)
+#define MK_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01EF)
+// interfaces: IMoniker, IBindCtx, IRunningObjectTable, IParseDisplayName,
+// IOleContainer, IOleItemContainer, IOleLink
+// file: moniker.h
+
+
+#define CO_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01F0)
+#define CO_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x01FF)
+#define CO_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01F0)
+#define CO_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x01FF)
+// all Co* API
+// file: compobj.h
+
+
+// range 200 - ffff for new error codes
+
+
+
+#endif // ifndef __SCODE_H__
diff --git a/private/ole32/stg/ole2h/storage.h b/private/ole32/stg/ole2h/storage.h
new file mode 100644
index 000000000..98192050b
--- /dev/null
+++ b/private/ole32/stg/ole2h/storage.h
@@ -0,0 +1,452 @@
+/*****************************************************************************\
+* *
+* storage.h - Definitions for the strutured storage system
+* *
+* OLE Version 2.0 *
+* *
+* Copyright (c) 1992-1993, Microsoft Corp. All rights reserved. *
+* *
+\*****************************************************************************/
+
+
+#if !defined( _STORAGE_H_ )
+#define _STORAGE_H_
+
+
+#include <compobj.h>
+
+
+/****** Storage Error Codes *************************************************/
+
+/* DOS-based error codes */
+#define STG_E_INVALIDFUNCTION \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x01)
+
+#define STG_E_FILENOTFOUND \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x02)
+
+#define STG_E_PATHNOTFOUND \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x03)
+
+#define STG_E_TOOMANYOPENFILES \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x04)
+
+#define STG_E_ACCESSDENIED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x05)
+
+#define STG_E_INVALIDHANDLE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x06)
+
+#define STG_E_INSUFFICIENTMEMORY \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x08)
+
+#define STG_E_INVALIDPOINTER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x09)
+
+#define STG_E_NOMOREFILES \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x12)
+
+#define STG_E_DISKISWRITEPROTECTED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x13)
+
+#define STG_E_SEEKERROR \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x19)
+
+#define STG_E_WRITEFAULT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x1d)
+
+#define STG_E_READFAULT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x1e)
+
+#define STG_E_SHAREVIOLATION \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x20)
+
+#define STG_E_LOCKVIOLATION \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x21)
+
+#define STG_E_FILEALREADYEXISTS \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x50)
+
+#define STG_E_INVALIDPARAMETER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x57)
+
+#define STG_E_MEDIUMFULL \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x70)
+
+#define STG_E_ABNORMALAPIEXIT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfa)
+
+#define STG_E_INVALIDHEADER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfb)
+
+#define STG_E_INVALIDNAME \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfc)
+
+#define STG_E_UNKNOWN \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfd)
+
+#define STG_E_UNIMPLEMENTEDFUNCTION\
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfe)
+
+#define STG_E_INVALIDFLAG \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xff)
+
+/* Standard storage error codes */
+#define STG_E_INUSE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x100)
+
+#define STG_E_NOTCURRENT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x101)
+
+#define STG_E_REVERTED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x102)
+
+#define STG_E_CANTSAVE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x103)
+
+#define STG_E_OLDFORMAT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x104)
+
+#define STG_E_OLDDLL \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x105)
+
+#define STG_E_SHAREREQUIRED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x106)
+
+#define STG_E_NOTFILEBASEDSTORAGE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x107)
+
+#define STG_E_EXTANTMARSHALLINGS \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x108)
+
+/* Information returns */
+#define STG_S_CONVERTED \
+ MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_STORAGE, 0x200)
+
+/****** Storage types *******************************************************/
+
+#if defined(_M_I286)
+typedef char TCHAR;
+#ifndef HUGEP
+#define HUGEP _huge
+#endif
+#else
+typedef char TCHAR;
+#ifndef HUGEP
+#define HUGEP
+#endif
+#endif
+
+#define CWCSTORAGENAME 32
+
+/* Storage instantiation modes */
+#define STGM_DIRECT 0x00000000L
+#define STGM_TRANSACTED 0x00010000L
+
+#define STGM_READ 0x00000000L
+#define STGM_WRITE 0x00000001L
+#define STGM_READWRITE 0x00000002L
+
+#define STGM_SHARE_DENY_NONE 0x00000040L
+#define STGM_SHARE_DENY_READ 0x00000030L
+#define STGM_SHARE_DENY_WRITE 0x00000020L
+#define STGM_SHARE_EXCLUSIVE 0x00000010L
+
+#define STGM_PRIORITY 0x00040000L
+#define STGM_DELETEONRELEASE 0x04000000L
+
+#define STGM_CREATE 0x00001000L
+#define STGM_CONVERT 0x00020000L
+#define STGM_FAILIFTHERE 0x00000000L
+
+/* Storage commit types */
+typedef enum tagSTGC
+{
+ STGC_DEFAULT = 0,
+ STGC_OVERWRITE = 1,
+ STGC_ONLYIFCURRENT = 2,
+ STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4
+} STGC;
+
+/* Stream name block definitions */
+typedef char FAR * FAR *SNB;
+
+
+#ifndef _WINDOWS_
+#ifndef _FILETIME_
+#define _FILETIME_
+typedef struct FARSTRUCT tagFILETIME
+{
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+} FILETIME;
+#endif
+#endif
+
+
+/* Storage stat buffer */
+
+typedef struct FARSTRUCT tagSTATSTG
+{
+ char FAR* pwcsName;
+ DWORD type;
+ ULARGE_INTEGER cbSize;
+ FILETIME mtime;
+ FILETIME ctime;
+ FILETIME atime;
+ DWORD grfMode;
+ DWORD grfLocksSupported;
+ CLSID clsid;
+ DWORD grfStateBits;
+ DWORD reserved;
+} STATSTG;
+
+
+/* Storage element types */
+typedef enum tagSTGTY
+{
+ STGTY_STORAGE = 1,
+ STGTY_STREAM = 2,
+ STGTY_LOCKBYTES = 3,
+ STGTY_PROPERTY = 4
+} STGTY;
+
+typedef enum tagSTREAM_SEEK
+{
+ STREAM_SEEK_SET = 0,
+ STREAM_SEEK_CUR = 1,
+ STREAM_SEEK_END = 2
+} STREAM_SEEK;
+
+typedef enum tagLOCKTYPE
+{
+ LOCK_WRITE = 1,
+ LOCK_EXCLUSIVE = 2,
+ LOCK_ONLYONCE = 4
+} LOCKTYPE;
+
+typedef enum tagSTGMOVE
+{
+ STGMOVE_MOVE = 0,
+ STGMOVE_COPY = 1
+} STGMOVE;
+
+typedef enum tagSTATFLAG
+{
+ STATFLAG_DEFAULT = 0,
+ STATFLAG_NONAME = 1
+} STATFLAG;
+
+
+/****** Storage Enumerators *************************************************/
+
+#define LPENUMSTATSTG IEnumSTATSTG FAR*
+
+#undef INTERFACE
+#define INTERFACE IEnumSTATSTG
+
+DECLARE_INTERFACE_(IEnumSTATSTG, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IENUMSTATSTG methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, STATSTG FAR * rgelt, ULONG FAR *pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumSTATSTG FAR *FAR *ppenm) PURE;
+};
+
+
+/****** ILockBytes Interface ************************************************/
+
+#define LPLOCKBYTES ILockBytes FAR*
+
+#undef INTERFACE
+#define INTERFACE ILockBytes
+
+DECLARE_INTERFACE_(ILockBytes, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** ILockBytes methods ***
+ STDMETHOD(ReadAt) (THIS_ ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbRead) PURE;
+ STDMETHOD(WriteAt) (THIS_ ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten) PURE;
+ STDMETHOD(Flush) (THIS) PURE;
+ STDMETHOD(SetSize) (THIS_ ULARGE_INTEGER cb) PURE;
+ STDMETHOD(LockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(UnlockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+};
+
+
+/****** IStream Interface ***************************************************/
+
+
+#define LPSTREAM IStream FAR*
+
+#undef INTERFACE
+#define INTERFACE IStream
+
+DECLARE_INTERFACE_(IStream, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IStream methods ***
+ STDMETHOD(Read) (THIS_ VOID HUGEP *pv,
+ ULONG cb, ULONG FAR *pcbRead) PURE;
+ STDMETHOD(Write) (THIS_ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten) PURE;
+ STDMETHOD(Seek) (THIS_ LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER FAR *plibNewPosition) PURE;
+ STDMETHOD(SetSize) (THIS_ ULARGE_INTEGER libNewSize) PURE;
+ STDMETHOD(CopyTo) (THIS_ IStream FAR *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER FAR *pcbRead,
+ ULARGE_INTEGER FAR *pcbWritten) PURE;
+ STDMETHOD(Commit) (THIS_ DWORD grfCommitFlags) PURE;
+ STDMETHOD(Revert) (THIS) PURE;
+ STDMETHOD(LockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(UnlockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+ STDMETHOD(Clone)(THIS_ IStream FAR * FAR *ppstm) PURE;
+};
+
+
+/****** IStorage Interface **************************************************/
+
+#define LPSTORAGE IStorage FAR*
+
+#undef INTERFACE
+#define INTERFACE IStorage
+
+DECLARE_INTERFACE_(IStorage, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IStorage methods ***
+ STDMETHOD(CreateStream) (THIS_ const char FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream FAR *FAR *ppstm) PURE;
+ STDMETHOD(OpenStream) (THIS_ const char FAR* pwcsName,
+ void FAR *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream FAR *FAR *ppstm) PURE;
+ STDMETHOD(CreateStorage) (THIS_ const char FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStorage FAR *FAR *ppstg) PURE;
+ STDMETHOD(OpenStorage) (THIS_ const char FAR* pwcsName,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR *FAR *ppstg) PURE;
+ STDMETHOD(CopyTo) (THIS_ DWORD ciidExclude,
+ IID const FAR *rgiidExclude,
+ SNB snbExclude,
+ IStorage FAR *pstgDest) PURE;
+ STDMETHOD(MoveElementTo) (THIS_ char const FAR* lpszName,
+ IStorage FAR *pstgDest,
+ char const FAR* lpszNewName,
+ DWORD grfFlags) PURE;
+ STDMETHOD(Commit) (THIS_ DWORD grfCommitFlags) PURE;
+ STDMETHOD(Revert) (THIS) PURE;
+ STDMETHOD(EnumElements) (THIS_ DWORD reserved1,
+ void FAR *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG FAR *FAR *ppenm) PURE;
+ STDMETHOD(DestroyElement) (THIS_ const char FAR* pwcsName) PURE;
+ STDMETHOD(RenameElement) (THIS_ const char FAR* pwcsOldName,
+ const char FAR* pwcsNewName) PURE;
+ STDMETHOD(SetElementTimes) (THIS_ const char FAR *lpszName,
+ FILETIME const FAR *pctime,
+ FILETIME const FAR *patime,
+ FILETIME const FAR *pmtime) PURE;
+ STDMETHOD(SetClass) (THIS_ REFCLSID clsid) PURE;
+ STDMETHOD(SetStateBits) (THIS_ DWORD grfStateBits, DWORD grfMask) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+};
+
+
+/****** IRootStorage Interface **********************************************/
+
+#define LPROOTSTORAGE IRootStorage FAR*
+
+#undef INTERFACE
+#define INTERFACE IRootStorage
+
+DECLARE_INTERFACE_(IRootStorage, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IRootStorage methods ***
+ STDMETHOD(SwitchToFile) (THIS_ LPSTR lpstrFile) PURE;
+};
+
+
+/****** Storage API Prototypes ********************************************/
+
+STDAPI StgCreateDocfile(const char FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgCreateDocfileOnILockBytes(ILockBytes FAR *plkbyt,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgOpenStorage(const char FAR* pwcsName,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgOpenStorageOnILockBytes(ILockBytes FAR *plkbyt,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgIsStorageFile(const char FAR* pwcsName);
+STDAPI StgIsStorageILockBytes(ILockBytes FAR* plkbyt);
+
+STDAPI StgSetTimes(char const FAR* lpszName,
+ FILETIME const FAR* pctime,
+ FILETIME const FAR* patime,
+ FILETIME const FAR* pmtime);
+
+#endif
diff --git a/private/ole32/stg/ole2h/valid.h b/private/ole32/stg/ole2h/valid.h
new file mode 100644
index 000000000..bd0aab5ee
--- /dev/null
+++ b/private/ole32/stg/ole2h/valid.h
@@ -0,0 +1,72 @@
+
+STDAPI_(BOOL) IsValidPtrIn( const void FAR* pv, UINT cb );
+STDAPI_(BOOL) IsValidPtrOut( void FAR* pv, UINT cb );
+STDAPI_(BOOL) IsValidInterface( void FAR* pv );
+STDAPI_(BOOL) IsValidIid( REFIID riid );
+
+
+#ifdef _DEBUG
+
+//** POINTER IN validation macros:
+#define VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid in ptr", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTRIN( pv, TYPE, retval ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid in ptr", _szAssertFile, __LINE__), retval)
+#define VOID_VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) {\
+ FnAssert(#pv,"Invalid in ptr", _szAssertFile, __LINE__); return; }
+
+//** POINTER OUT validation macros:
+#define VDATEPTROUT( pv, TYPE ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid out ptr", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTROUT( pv, TYPE, retval ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (FnAssert(#pv,"Invalid out ptr", _szAssertFile, __LINE__), retval)
+
+//** INTERFACE validation macro:
+#define GEN_VDATEIFACE( pv, retval ) if (!IsValidInterface(pv)) \
+ return (FnAssert(#pv,"Invalid interface", _szAssertFile, __LINE__), retval)
+#define VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return (FnAssert(#pv,"Invalid interface", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define VOID_VDATEIFACE( pv ) if (!IsValidInterface(pv)) {\
+ FnAssert(#pv,"Invalid interface", _szAssertFile, __LINE__); return; }
+
+//** INTERFACE ID validation macro:
+#define VDATEIID( iid ) if (!IsValidIid( iid )) \
+ return (FnAssert(#iid,"Invalid iid", _szAssertFile, __LINE__),ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEIID( iid, retval ) if (!IsValidIid( iid )) {\
+ FnAssert(#iid,"Invalid iid", _szAssertFile, __LINE__); return retval; }
+#else
+
+
+
+// --assertless macros for non-debug case
+//** POINTER IN validation macros:
+#define VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEPTRIN( pv, TYPE, retval ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) \
+ return (retval)
+#define VOID_VDATEPTRIN( pv, TYPE ) if (!IsValidPtrIn( (pv), sizeof(TYPE))) {\
+ return; }
+
+//** POINTER OUT validation macros:
+#define VDATEPTROUT( pv, TYPE ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (ResultFromScode(E_INVALIDARG))
+
+#define GEN_VDATEPTROUT( pv, TYPE, retval ) if (!IsValidPtrOut( (pv), sizeof(TYPE))) \
+ return (retval)
+
+//** INTERFACE validation macro:
+#define VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return (ResultFromScode(E_INVALIDARG))
+#define VOID_VDATEIFACE( pv ) if (!IsValidInterface(pv)) \
+ return;
+#define GEN_VDATEIFACE( pv, retval ) if (!IsValidInterface(pv)) \
+ return (retval)
+
+//** INTERFACE ID validation macro:
+#define VDATEIID( iid ) if (!IsValidIid( iid )) \
+ return (ResultFromScode(E_INVALIDARG))
+#define GEN_VDATEIID( iid, retval ) if (!IsValidIid( iid )) \
+ return retval;
+
+#endif
+
diff --git a/private/ole32/stg/ole2h/verinfo.h b/private/ole32/stg/ole2h/verinfo.h
new file mode 100644
index 000000000..8eee91591
--- /dev/null
+++ b/private/ole32/stg/ole2h/verinfo.h
@@ -0,0 +1,22 @@
+
+#ifdef RC_INVOKED
+
+#include <ver.h>
+
+#define VER_FILEVERSION_STR "2.0\0"
+#define VER_FILEVERSION 2,00,1000,11
+
+#define VER_PRODUCTNAME_STR "Microsoft OLE 2.0 for Windows\0"
+#define VER_COMPANYNAME_STR "Microsoft Corporation\0"
+#define VER_LEGALTRADEMARKS_STR "Microsoft\256 is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation\0"
+#define VER_LEGALCOPYRIGHT_STR "Copyright \251 Microsoft Corp. 1992 - 1993\0"
+#define VER_PRODUCTVERSION_STR "2.0\0"
+#define VER_PRODUCTVERSION 2,00,1000,11
+#define VER_COMMENT_STR "Windows OLE DLLs\0"
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE 0
+#define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+#define VER_FILEFLAGS 0L
+#define VER_FILEOS VOS_DOS_WINDOWS16
+
+#endif /* RC_INVOKED */
diff --git a/private/ole32/stg/props/cfmapstm.cxx b/private/ole32/stg/props/cfmapstm.cxx
new file mode 100644
index 000000000..bf30bcf10
--- /dev/null
+++ b/private/ole32/stg/props/cfmapstm.cxx
@@ -0,0 +1,766 @@
+
+
+//+============================================================================
+//
+// File: CFMapStm.cxx
+//
+// Purpose: This file defines the CCFMappedStream class.
+// This class provdes a CMappedStream implementation
+// which maps an IStream from a Compound File.
+//
+// History:
+// 08-Nov-96 MikeHil Don't call RtlOnMappedStream unnecessarily.
+//
+//+============================================================================
+
+// --------
+// Includes
+// --------
+
+#include <pch.cxx>
+#include "CFMapStm.hxx"
+
+#ifdef _MAC_NODOC
+ASSERTDATA // File-specific data for FnAssert
+#endif
+
+//+----------------------------------------------------------------------------
+//
+// Method: CCFMappedStream::Initialize
+//
+// Synopsis: Zero-out all of the member data.
+//
+// Arguments: None
+//
+// Returns: None
+//
+//
+//+----------------------------------------------------------------------------
+
+VOID
+CCFMappedStream::Initialize()
+{
+ _pstm = NULL;
+ _pbMappedStream = NULL;
+ _cbMappedStream = 0;
+ _cbOriginalStreamSize = 0;
+ _powner = NULL;
+ _fLowMem = FALSE;
+ _fDirty = FALSE;
+
+#if DBGPROP
+ _fChangePending = FALSE;
+#endif
+
+} // CCFMappedStream::Initialize()
+
+
+//+----------------------------------------------------------------------------
+//
+// Member: Constructor/Destructor
+//
+// Synopsis: Initialize/cleanup this object.
+//
+//+----------------------------------------------------------------------------
+
+CCFMappedStream::CCFMappedStream( IStream *pstm )
+{
+ DfpAssert( NULL != pstm );
+
+ // Initialize the member data.
+ Initialize();
+
+ // Keep a copy of the Stream that we're mapping.
+ _pstm = pstm;
+ _pstm->AddRef();
+}
+
+
+CCFMappedStream::~CCFMappedStream( )
+{
+ // Just to be safe, free the mapping buffer (it should have
+ // already been freed).
+
+ DfpAssert( NULL == _pbMappedStream );
+ CoTaskMemFree( _pbMappedStream );
+
+ // If we've got the global reserved buffer locked,
+ // free it now.
+
+ if (_fLowMem)
+ {
+ g_ReservedMemory.UnlockMemory();
+ }
+
+ // Free the stream which we were mapping.
+
+ if( NULL != _pstm )
+ _pstm->Release();
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Method: CCFMappedStream::Open
+//
+// Synopsis: Open up the Stream which we're mapping, and
+// read it's data into a buffer.
+//
+// Arguments: [VOID*] powner
+// The owner of this Stream. We use this for the
+// RtlOnMappedStreamEvent call.
+// [HRESULT*] phr
+// The return code.
+//
+// Returns: Nothing.
+//
+//+----------------------------------------------------------------------------
+
+
+VOID
+CCFMappedStream::Open( IN VOID *powner,
+ OUT HRESULT *phr )
+{
+ *phr = S_OK;
+ VOID *pv = NULL;
+ DfpAssert(!_fLowMem);
+
+ // If given a pointer to the owner of this mapped stream,
+ // save it. This could be NULL (i.e., when called from
+ // ReOpen).
+
+ if( NULL != powner )
+ _powner = powner;
+
+ // If we haven't already read the stream, read it now.
+
+ if( NULL == _pbMappedStream )
+ {
+ STATSTG statstg;
+ LARGE_INTEGER liSeek;
+
+ DfpAssert( NULL != _pstm );
+ DfpAssert( 0 == _cbMappedStream );
+ DfpAssert( 0 == _cbOriginalStreamSize );
+
+ // Get and validate the size of the Stream.
+
+ *phr = _pstm->Stat( &statstg, STATFLAG_NONAME );
+ if( FAILED(*phr) ) goto Exit;
+
+ if( statstg.cbSize.HighPart != 0
+ ||
+ statstg.cbSize.LowPart > CBMAXPROPSETSTREAM )
+ {
+ *phr = STG_E_INVALIDHEADER;
+ goto Exit;
+ }
+ _cbMappedStream = _cbOriginalStreamSize = statstg.cbSize.LowPart;
+
+ // Allocate a buffer to hold the Stream. If there isn't sufficient
+ // memory in the system, lock and get the reserved buffer. In the
+ // end, 'pv' points to the appropriate buffer.
+
+ pv = CoTaskMemAlloc( _cbOriginalStreamSize );
+
+ if (pv == NULL)
+ {
+ pv = g_ReservedMemory.LockMemory(); // could wait until previous
+ // property call completes
+ _fLowMem = TRUE;
+ }
+ _pbMappedStream = (BYTE*) pv;
+
+ // Seek to the start of the Stream.
+
+ liSeek.HighPart = 0;
+ liSeek.LowPart = 0;
+ *phr = _pstm->Seek( liSeek, STREAM_SEEK_SET, NULL );
+ if( FAILED(*phr) ) goto Exit;
+
+ // Read in the Stream. But only if it is non-zero; some
+ // stream implementations (namely the Mac StreamOnHGlobal imp)
+ // don't allow 0-length reads.
+
+ if( 0 != _cbOriginalStreamSize )
+ {
+ *phr = _pstm->Read(
+ _pbMappedStream,
+ _cbOriginalStreamSize,
+ &_cbMappedStream);
+ if( FAILED(*phr) ) goto Exit;
+
+ // Ensure that we got all the bytes we requested.
+
+ if( _cbMappedStream != _cbOriginalStreamSize )
+ {
+ PropDbg((DEBTRACE_ERROR,
+ "CCFMappedStream(%08X)::Open bytes-read (%lu) doesn't match bytes-requested (%lu)\n",
+ this, _cbMappedStream, _cbOriginalStreamSize ));
+ *phr = STG_E_INVALIDHEADER;
+ goto Exit;
+ }
+ }
+
+
+#if BIGENDIAN==1
+ // Notify our owner that we've read in new data.
+
+ if( _powner != NULL && 0 != _cbMappedStream )
+ {
+ *phr = RtlOnMappedStreamEvent( _powner, _pbMappedStream, _cbMappedStream );
+ if( FAILED(*phr) ) goto Exit;
+ }
+#endif
+
+ } // if( NULL == _pbMappedStream )
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // If there was an error, free any memory we have.
+
+ if( FAILED(*phr) )
+ {
+ PropDbg((DEB_PROP_MAP, "CCFMappedStream(%08X):Open exception returns %08X\n", this, *phr));
+
+ if (_fLowMem)
+ g_ReservedMemory.UnlockMemory();
+ else
+ CoTaskMemFree(pv);
+
+ _pbMappedStream = NULL;
+ _cbMappedStream = 0;
+ _cbOriginalStreamSize = 0;
+ _fLowMem = FALSE;
+ }
+
+ return;
+
+} // CCFMappedStream::Open
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::Flush
+//
+// Synopsis: Write out the mapping buffer to the Stream,
+// and Commit it.
+//
+// Arguments: [LONG*] phr
+// An HRESULT return code.
+//
+// Returns: None.
+//
+//--------------------------------------------------------------------
+
+VOID CCFMappedStream::Flush(OUT LONG *phr)
+{
+ // Write out any data we have cached to the Stream.
+ *phr = Write();
+
+ // Commit the Stream.
+ if( S_OK == *phr )
+ {
+ *phr = _pstm->Commit(STGC_DEFAULT);
+ }
+
+ return;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::Close
+//
+// Synopsis: Close the mapped stream by writing out
+// the mapping buffer and then freeing it.
+//
+// Arguments: [LONG*] phr
+// An HRESULT error code.
+//
+// Returns: None.
+//
+//--------------------------------------------------------------------
+
+VOID CCFMappedStream::Close(OUT LONG *phr)
+{
+ // Write the changes. We don't need to Commit them,
+ // they will be implicitely committed when the
+ // Stream is Released.
+
+ PropDbg((DEB_PROP_MAP, "CCFStream(%08X)::Close\n", this ));
+
+ *phr = Write();
+
+ if( FAILED(*phr) )
+ {
+ PropDbg((DEB_PROP_MAP, "CCFStream(%08X)::Close exception returns %08X\n", this, *phr));
+ }
+
+ // Even if we fail the write, we must free the memory.
+ // (RtlClosePropertySet deletes everything whether or not
+ // there was an error here, so we must free the memory.
+ // There's no danger of this happenning due to out-of-
+ // disk-space conditions, because the propset code
+ // pre-allocates).
+
+ CoTaskMemFree( _pbMappedStream );
+ _pstm->Release();
+
+ // Re-zero the member data.
+ Initialize();
+
+ return;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::ReOpen
+//
+// Synopsis: Gets the caller a pointer to the already-opened
+// mapping buffer. If it isn't already opened, then
+// it is opened here.
+//
+// Arguments: [VOID**] ppv
+// Used to return the mapping buffer.
+// [LONG*] phr
+// Used to return an HRESULT.
+//
+// Returns: None.
+//
+//--------------------------------------------------------------------
+
+VOID CCFMappedStream::ReOpen(IN OUT VOID **ppv, OUT LONG *phr)
+{
+ *ppv = NULL;
+
+ Open(NULL, // Unspecified owner.
+ phr);
+
+ if( SUCCEEDED(*phr) )
+ *ppv = _pbMappedStream;
+
+ return;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::Quiesce
+//
+// Synopsis: Unnecessary for this CMappedStream implementation.
+//
+//--------------------------------------------------------------------
+
+VOID CCFMappedStream::Quiesce(VOID)
+{
+ DfpAssert(_pbMappedStream != NULL);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::Map
+//
+// Synopsis: Used to get a pointer to the current mapping.
+//
+// Arguments: [BOOLEAN] fCreate
+// Not used by this CMappedStream implementation.
+// [VOID**] ppv
+// Used to return the mapping buffer.
+//
+// Returns: None.
+//
+//--------------------------------------------------------------------
+
+VOID CCFMappedStream::Map(BOOLEAN fCreate, VOID **ppv)
+{
+ DfpAssert(_pbMappedStream != NULL);
+ *ppv = _pbMappedStream;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::Unmap
+//
+// Synopsis: Unnecessary for this CMappedStream implementation.
+//
+//--------------------------------------------------------------------
+
+VOID CCFMappedStream::Unmap(BOOLEAN fFlush, VOID **ppv)
+{
+ *ppv = NULL;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::Write
+//
+// Synopsis: Writes the mapping buffer out to the original
+// Stream.
+//
+// Arguments: None.
+//
+// Returns: [HRESULT]
+//
+//--------------------------------------------------------------------
+
+HRESULT CCFMappedStream::Write ()
+{
+ HRESULT hr;
+ ULONG cbWritten;
+ LARGE_INTEGER liSeek;
+ BOOL fOwnerSignaled = FALSE;
+
+ // We can return right away if there's nothing to write.
+ // (_pbMappedStream may be NULL in the error path of our
+ // caller).
+
+ if (!_fDirty || NULL == _pbMappedStream )
+ {
+ PropDbg((DEB_PROP_MAP, "CPubStream(%08X):Flush returns with not-dirty\n", this));
+
+ return S_OK;
+ }
+
+ DfpAssert( _pstm != NULL );
+ DfpAssert( _powner != NULL );
+
+#if BIGENDIAN==1
+ // Notify our owner that we're about to perform a Write.
+ hr = RtlOnMappedStreamEvent( _powner, _pbMappedStream, _cbMappedStream );
+ if( S_OK != hr ) goto Exit;
+ fOwnerSignaled = TRUE;
+#endif
+
+ // Seek to the start of the Stream.
+ liSeek.HighPart = 0;
+ liSeek.LowPart = 0;
+ hr = _pstm->Seek( liSeek, STREAM_SEEK_SET, NULL );
+ if( FAILED(hr) ) goto Exit;
+
+ // Write out the mapping buffer.
+ hr = _pstm->Write(_pbMappedStream, _cbMappedStream, &cbWritten);
+ if( S_OK != hr ) goto Exit;
+ if( cbWritten != _cbMappedStream )
+ {
+ PropDbg((DEBTRACE_ERROR,
+ "CCFMappedStream(%08X)::Write bytes-written (%lu) doesn't match bytes-requested (%lu)\n",
+ this, cbWritten, _cbMappedStream ));
+ hr = STG_E_INVALIDHEADER;
+ goto Exit;
+ }
+
+ // If the buffer is shrinking, this is a good time to shrink the Stream.
+ if (_cbMappedStream < _cbOriginalStreamSize)
+ {
+ ULARGE_INTEGER uli;
+ uli.HighPart = 0;
+ uli.LowPart = _cbMappedStream;
+
+ hr = _pstm->SetSize(uli);
+ if( S_OK != hr ) goto Exit;
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // Notify our owner that we're done with the Write. We do this
+ // whether or not there was an error, because _pbMappedStream is
+ // not modified, and therefore intact even in the error path.
+
+#if BIGENDIAN==1
+ if( fOwnerSignaled )
+ {
+ hr = RtlOnMappedStreamEvent( _powner, _pbMappedStream, _cbMappedStream );
+ if( S_OK != hr ) goto Exit;
+ }
+#endif
+
+ if (hr == S_OK || hr == STG_E_REVERTED)
+ {
+ _fDirty = FALSE;
+ }
+
+ PropDbg((DEB_PROP_MAP, "CCFMappedStream(%08X)::Write %s returns hr=%08X\n",
+ this, hr != S_OK ? "exception" : "", hr));
+
+ return hr;
+
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::GetSize
+//
+// Synopsis: Returns the current size of the mapped stream.
+//
+// Arguments: [LONG*] phr
+// Used to return an HRESULT.
+//
+// Returns: [ULONG]
+// The current size.
+//
+//--------------------------------------------------------------------
+
+ULONG CCFMappedStream::GetSize(OUT LONG *phr)
+{
+ *phr = S_OK;
+
+ // If necessary, open the Stream.
+
+ if( NULL == _pbMappedStream )
+ {
+ Open(NULL, // Unspecified owner
+ phr);
+ }
+
+ if( SUCCEEDED(*phr) )
+ {
+ DfpAssert( NULL != _pbMappedStream );
+ }
+
+ // Return the size of the mapped stream. If there was an
+ // Open error, it will be zero, and *phr will be set.
+
+ return _cbMappedStream;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::SetSize
+//
+// Synopsis: Set the size of the mapped stream.
+//
+// Arguments: [ULONG] cb
+// The new size.
+// [BOOLEAN] fPersistent
+// If not set, then this change will not be stored -
+// thus the mapping buffer must be set, but the
+// Stream itself must not. This was added so that
+// CPropertySetStream could grow the buffer for internal
+// processing, when the Stream itself is read-only.
+// [VOID**] ppv
+// Used to return the new mapping buffer location.
+//
+// Returns: None.
+//
+// Pre-Conditions:
+// cb is below the maximum property set size.
+//
+//--------------------------------------------------------------------
+
+VOID
+CCFMappedStream::SetSize(ULONG cb,
+ IN BOOLEAN fPersistent,
+ VOID **ppv, OUT LONG *phr)
+{
+ VOID *pv;
+
+ *phr = S_OK;
+ DfpAssert(cb != 0);
+ DfpAssert(cb <= CBMAXPROPSETSTREAM);
+
+ //
+ // if we are growing the data, we should grow the stream
+ //
+
+ if( fPersistent && cb > _cbMappedStream )
+ {
+ ULARGE_INTEGER uli;
+ uli.HighPart = 0;
+ uli.LowPart = cb;
+
+ *phr = _pstm->SetSize( uli );
+ if( FAILED(*phr) ) goto Exit;
+ }
+
+
+ // Re-size the buffer.
+
+ if (_fLowMem)
+ {
+ // In low-memory conditions, no realloc is necessary, because
+ // _pbMappedStream is already large enough for the largest
+ // property set.
+
+ *ppv = _pbMappedStream;
+ }
+ else
+ {
+ // We must re-alloc the buffer.
+
+ pv = CoTaskMemRealloc( _pbMappedStream, cb );
+
+ if (pv == NULL)
+ {
+ // allocation failed: we need to try using a backup mechanism for
+ // more memory.
+ // copy the data to the global reserved chunk... we will wait until
+ // someone else has released it. it will be released on the way out
+ // of the property code.
+
+ _fLowMem = TRUE;
+ pv = g_ReservedMemory.LockMemory();
+ if( NULL != _pbMappedStream )
+ {
+ memcpy( pv, _pbMappedStream, _cbMappedStream );
+ }
+ CoTaskMemFree( _pbMappedStream );
+ }
+ _pbMappedStream = (BYTE*) pv;
+ *ppv = pv;
+ }
+
+ _cbMappedStream = cb;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ PropDbg((DEB_PROP_MAP, "CCFMappedStream(%08X):SetSize %s returns hr=%08X\n",
+ this, *phr != S_OK ? "exception" : "", *phr));
+
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::Lock
+//
+// Synopsis: Locking is not supported by this class.
+//
+//--------------------------------------------------------------------
+
+NTSTATUS CCFMappedStream::Lock(BOOLEAN fExclusive)
+{
+ return(STATUS_SUCCESS);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::Unlock
+//
+// Synopsis: Locking is not supported by this class.
+// However, this method still must check to
+// see if the reserved memory pool should be
+// freed for use by another property set.
+//
+//--------------------------------------------------------------------
+
+NTSTATUS CCFMappedStream::Unlock(VOID)
+{
+ // if at the end of the properties set/get call we have the low
+ // memory region locked, we flush to disk.
+ HRESULT hr = S_OK;
+
+ if (_fLowMem)
+ {
+ Flush(&hr);
+
+ g_ReservedMemory.UnlockMemory();
+ _pbMappedStream = NULL;
+ _cbMappedStream = 0;
+ _fLowMem = FALSE;
+ PropDbg((DEB_PROP_MAP, "CPubStream(%08X):Unlock low-mem returns NTSTATUS=%08X\n",
+ this, hr));
+ }
+
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::QueryTimeStamps
+//
+// Synopsis: Not used by this CMappedStream derivation.
+//
+//--------------------------------------------------------------------
+
+VOID CCFMappedStream::QueryTimeStamps(STATPROPSETSTG *pspss, BOOLEAN fNonSimple) const
+{
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::QueryModifyTime
+//
+// Synopsis: Not used by this CMappedStream derivation.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+BOOLEAN CCFMappedStream::QueryModifyTime(OUT LONGLONG *pll) const
+{
+ return(FALSE);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: Unused methods by this CMappedStream implementation:
+// QuerySecurity, IsWritable, GetHandle
+//
+//--------------------------------------------------------------------
+
+BOOLEAN CCFMappedStream::QuerySecurity(OUT ULONG *pul) const
+{
+ return(FALSE);
+}
+
+BOOLEAN CCFMappedStream::IsWriteable() const
+{
+ return TRUE;
+}
+
+HANDLE CCFMappedStream::GetHandle(VOID) const
+{
+ return(INVALID_HANDLE_VALUE);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::SetModified/IsModified
+//
+//--------------------------------------------------------------------
+
+VOID CCFMappedStream::SetModified(VOID)
+{
+ _fDirty = TRUE;
+}
+
+BOOLEAN CCFMappedStream::IsModified(VOID) const
+{
+ return _fDirty;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CCFMappedStream::IsNtMappedStream/SetChangePending
+//
+// Synopsis: Debug routines.
+//
+//--------------------------------------------------------------------
+
+#if DBGPROP
+BOOLEAN CCFMappedStream::IsNtMappedStream(VOID) const
+{
+ return(FALSE);
+}
+#endif
+
+
+#if DBGPROP
+BOOLEAN CCFMappedStream::SetChangePending(BOOLEAN f)
+{
+ BOOL fOld = _fChangePending;
+ _fChangePending = f;
+ return(_fChangePending);
+}
+#endif
+
diff --git a/private/ole32/stg/props/cfmapstm.hxx b/private/ole32/stg/props/cfmapstm.hxx
new file mode 100644
index 000000000..7e68255e1
--- /dev/null
+++ b/private/ole32/stg/props/cfmapstm.hxx
@@ -0,0 +1,102 @@
+
+//+============================================================================
+//
+// File: CFMapStm.hxx
+//
+// Purpose: Define the CCFMappedStream class.
+// This class provides a CMappedStream implementation
+// which maps an IStream from a Structured Storage.
+//
+//+============================================================================
+
+
+#ifndef _CF_MPD_STM_HXX_
+#define _CF_MPD_STM_HXX_
+
+// --------
+// Includes
+// --------
+
+#include <stgvarb.hxx> // CBaseStorageVariant declarations
+#include <propset.h> // Appendix B Property set structure definitions
+
+#ifndef _MAC
+#include <ddeml.h> // For CP_WINUNICODE
+#include <objidl.h> // OLE Interfaces
+#endif
+
+#include <byteordr.hxx> // Byte-swapping routines
+
+
+// ---------------
+// CCFMappedStream
+// ---------------
+
+class CCFMappedStream : public CMappedStream
+{
+
+// Constructors
+
+public:
+
+ CCFMappedStream( IStream *pstm );
+ ~CCFMappedStream();
+
+// Exposed methods
+
+public:
+
+ VOID Open(IN NTPROP np, OUT LONG *phr);
+ VOID Close(OUT LONG *phr);
+ VOID ReOpen(IN OUT VOID **ppv, OUT LONG *phr);
+ VOID Quiesce(VOID);
+ VOID Map(IN BOOLEAN fCreate, OUT VOID **ppv);
+ VOID Unmap(IN BOOLEAN fFlush, IN OUT VOID **ppv);
+ VOID Flush(OUT LONG *phr);
+
+ ULONG GetSize(OUT LONG *phr);
+ VOID SetSize(IN ULONG cb, IN BOOLEAN fPersistent, IN OUT VOID **ppv, OUT LONG *phr);
+ NTSTATUS Lock(IN BOOLEAN fExclusive);
+ NTSTATUS Unlock(VOID);
+ VOID QueryTimeStamps(OUT STATPROPSETSTG *pspss, BOOLEAN fNonSimple) const;
+ BOOLEAN QueryModifyTime(OUT LONGLONG *pll) const;
+ BOOLEAN QuerySecurity(OUT ULONG *pul) const;
+
+ BOOLEAN IsWriteable(VOID) const;
+ BOOLEAN IsModified(VOID) const;
+ VOID SetModified(VOID);
+ HANDLE GetHandle(VOID) const;
+
+#if DBGPROP
+ BOOLEAN SetChangePending(BOOLEAN fChangePending);
+ BOOLEAN IsNtMappedStream(VOID) const;
+#endif
+
+// Internal Methods
+
+protected:
+
+ VOID Initialize();
+ HRESULT Write();
+
+// Internal Data
+
+protected:
+
+ IStream *_pstm;
+ BYTE *_pbMappedStream;
+ ULONG _cbMappedStream;
+ ULONG _cbOriginalStreamSize;
+ VOID *_powner;
+
+ BOOL _fLowMem;
+ BOOL _fDirty;
+
+#if DBGPROP
+ BOOL _fChangePending;
+#endif
+
+};
+
+
+#endif // #ifndef _CF_MPD_STM_HXX_
diff --git a/private/ole32/stg/props/daytona/makefile b/private/ole32/stg/props/daytona/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ole32/stg/props/daytona/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/stg/props/daytona/sources b/private/ole32/stg/props/daytona/sources
new file mode 100644
index 000000000..05d2a971b
--- /dev/null
+++ b/private/ole32/stg/props/daytona/sources
@@ -0,0 +1,55 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Bill Morel 14-Mar-1995
+
+!ENDIF
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+
+!include ..\..\..\daytona.inc
+
+TARGETNAME= props
+TARGETPATH= obj
+TARGETTYPE= LIBRARY
+
+INCLUDES= .;..;..\..\h;..\..\common;..\..\..\ih;..\..\exp;..\..\..\com\inc;..\..\..\..\inc
+
+BLDCRT= 1
+USE_CRTDLL= 1
+
+SOURCES= \
+ ..\propapi.cxx\
+ ..\propstg.cxx\
+ ..\psetstg.cxx\
+ ..\utils.cxx\
+ ..\reserved.cxx\
+ ..\cfmapstm.cxx
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+
+PRECOMPILED_INCLUDE=..\pch.cxx
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
+
diff --git a/private/ole32/stg/props/debtrace.hxx b/private/ole32/stg/props/debtrace.hxx
new file mode 100644
index 000000000..8c520a6dc
--- /dev/null
+++ b/private/ole32/stg/props/debtrace.hxx
@@ -0,0 +1,15 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: debtrace.hxx
+//
+// Contents: DEBTRACE compatibliity definitions
+//
+// History: 20-Mar-95 VicH Created
+//
+//--------------------------------------------------------------------------
+
+#define DBGFLAG
+#define DEBTRACE(args) DebugTrace(0, ulLevel, args)
diff --git a/private/ole32/stg/props/dirs b/private/ole32/stg/props/dirs
new file mode 100644
index 000000000..b374f3000
--- /dev/null
+++ b/private/ole32/stg/props/dirs
@@ -0,0 +1,18 @@
+!IF 0
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+!ENDIF
+
+DIRS= iprop prpsetup
+
+OPTIONAL_DIRS= \
+ \
+ daytona \
+
+
+
diff --git a/private/ole32/stg/props/iprop/call_as.c b/private/ole32/stg/props/iprop/call_as.c
new file mode 100644
index 000000000..7734543cb
--- /dev/null
+++ b/private/ole32/stg/props/iprop/call_as.c
@@ -0,0 +1,633 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994.
+//
+// File: call_as.c
+//
+// Contents: [call_as] wrapper functions for COMMON\types.
+//
+// Functions: IEnumSTATPROPSTG_Next_Proxy
+// IEnumSTATPROPSTG_Next_Stub
+// IEnumSTATPROPSETSTG_Next_Proxy
+// IEnumSTATPROPSETSTG_Next_Stub
+// IPropertyStorage_WriteMultiple_Proxy
+// IPropertyStorage_WriteMultiple_Stub
+// IPropertyStorage_ReadMultiple_Proxy
+// IPropertyStorage_ReadMultiple_Stub
+// IPropertyStorage_DeleteMultiple_Proxy
+// IPropertyStorage_DeleteMultiple_Stub
+//
+// History:
+//
+//--------------------------------------------------------------------------
+#include <rpcproxy.h>
+#include <debnot.h>
+#include "prstg_ca.h" // For IPropertyStorage [call_as] routines.
+
+#pragma code_seg(".orpc")
+
+#define ASSERT(expr) Win4Assert(expr)
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumSTATPROPSTG_Next_Proxy
+//
+// Synopsis:
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumSTATPROPSTG_Next_Proxy(
+ IEnumSTATPROPSTG __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [out] */ STATPROPSTG __RPC_FAR *rgelt,
+ /* [unique][out][in] */ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+ ULONG celtFetched = 0;
+
+ if((celt > 1) && (pceltFetched == 0))
+ return E_INVALIDARG;
+
+ hr = IEnumSTATPROPSTG_RemoteNext_Proxy(This, celt, rgelt, &celtFetched);
+
+ if (pceltFetched != 0)
+ {
+ *pceltFetched = celtFetched;
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumSTATPROPSTG_Next_Stub
+//
+// Synopsis:
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumSTATPROPSTG_Next_Stub(
+ IEnumSTATPROPSTG __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ STATPROPSTG __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched)
+{
+ return This->lpVtbl->Next(This, celt, rgelt, pceltFetched);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumSTATPROPSETSTG_Next_Proxy
+//
+// Synopsis:
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumSTATPROPSETSTG_Next_Proxy(
+ IEnumSTATPROPSETSTG __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [out] */ STATPROPSETSTG __RPC_FAR *rgelt,
+ /* [unique][out][in] */ ULONG __RPC_FAR *pceltFetched)
+{
+ HRESULT hr;
+ ULONG celtFetched = 0;
+
+ if((celt > 1) && (pceltFetched == 0))
+ return E_INVALIDARG;
+
+ hr = IEnumSTATPROPSETSTG_RemoteNext_Proxy(This, celt, rgelt, &celtFetched);
+
+ if (pceltFetched != 0)
+ {
+ *pceltFetched = celtFetched;
+ }
+
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IEnumSTATPROPSETSTG_Next_Stub
+//
+// Synopsis:
+//
+//--------------------------------------------------------------------------
+HRESULT STDMETHODCALLTYPE IEnumSTATPROPSETSTG_Next_Stub(
+ IEnumSTATPROPSETSTG __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ STATPROPSETSTG __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched)
+{
+ return This->lpVtbl->Next(This, celt, rgelt, pceltFetched);
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IPropertyStorage_WriteMultiple_Proxy
+// (See "prstg_ca.c" for an overview)
+//
+// Synopsis: With a WriteMultiple, we must convert
+// the input PropVariant array so that it
+// is marshalable. The property which
+// makes a PropVariant un-marshalable is the BSTR.
+// So we convert BSTRs to BLOBs (actually, BSTR_BLOBs).
+//
+// We don't modify the caller's PropVariant[],
+// since it may not be writable, rather we create a
+// copy of the PropVariant[] if there are some BSTRs
+// in it. We tell the stub if
+// any BSTRs are present, so the stub doesn't
+// have to search the PropVariant[] to find out.
+//
+// Aside from BSTRs, we also assume that non-simple
+// properties are not marshalable We assume this
+// because we assume that this code will only run
+// on systems where OLE doesn't already provide
+// the IProperty marshaling code - Win95 & NT 3.51 -
+// and on those systems, a bug in the RPC runtime
+// prevents interface pointers in unions from
+// being marshaled. So, if we discover a non-
+// simple property, we return with a failure.
+//
+// Note: The PROPSPEC and PROPVARIANT arrays
+// must be typed in the form of a pointer in
+// this interface. See the
+// IPropertyStorage_DeleteMultiple_Proxy/Stub
+// comments for an explanation.
+//
+//+-------------------------------------------------------------------------
+
+
+STDMETHODIMP
+IPropertyStorage_WriteMultiple_Proxy(
+ IPropertyStorage __RPC_FAR *This,
+ /*[in]*/ ULONG cpspec,
+ /*[in, size_is(cpspec)]*/
+ const PROPSPEC rgpspec[],
+ /*[in, size_is(cpspec)]*/
+ const PROPVARIANT rgpropvar[],
+ /*[in]*/ PROPID propidNameFirst
+ )
+{
+ HRESULT hr = S_OK;
+ ULONG ulVTExists;
+
+ // The remotable PropVariant[]
+ PROPVARIANT *rgpropvarRem = NULL;
+
+ // Are there any special properties which we must handle?
+
+ if( NULL != rgpropvar
+ &&
+ ( ulVTExists = ContainsSpecialProperty( cpspec, rgpropvar ))
+ )
+ {
+ // Was there a non-simple property?
+
+ if( ulVTExists & NONSIMPLE_EXISTS )
+ {
+ hr = RPC_E_CLIENT_CANTMARSHAL_DATA;
+ goto Exit;
+ }
+
+ // Otherwise, there must have been a BSTR property
+ else
+ {
+ ULONG ulIndex;
+
+ // Allocate a new PropVariant[]. We'll copy the
+ // original PropVariant into this for pre-marshaling
+ // (we must make a copy because we don't want to modify
+ // our caller's buffer, which may not even be writable).
+
+ rgpropvarRem = CoTaskMemAlloc( cpspec * sizeof(*rgpropvarRem) );
+ if( NULL == rgpropvarRem )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+ memset( rgpropvarRem, 0, cpspec * sizeof(*rgpropvarRem) );
+
+ // Copy each element of rgpropvar into rgpropvarRem
+
+ for( ulIndex = 0; ulIndex < cpspec; ulIndex++ )
+ {
+ hr = PropVariantCopy( &rgpropvarRem[ ulIndex ],
+ &rgpropvar[ ulIndex ] );
+ if( FAILED(hr) ) goto Exit;
+ }
+
+ // Pre-marshal this PropVariant[], converting the
+ // BSTRs to BSTR_BLOBs.
+
+ hr = PropVarMarshal( cpspec, rgpropvarRem );
+ if( FAILED(hr) ) goto Exit;
+
+ } // if( ulExists & NONSIMPLE_EXISTS ) ... else
+ } // if( NULL != rgpropvar ...
+ else
+ {
+ // No pre-marshaling is necessary.
+ rgpropvarRem = (PROPVARIANT*) rgpropvar;
+
+ } // if( NULL != rgpropvar ... else
+
+ // Perform the WriteMultiple
+ hr = IPropertyStorage_RemoteWriteMultiple_Proxy( This,
+ rgpropvar != rgpropvarRem, // BSTR exists?
+ cpspec, rgpspec,
+ rgpropvarRem,
+ propidNameFirst );
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // If we created a pre-marshaled array, free it now
+
+ if( NULL != rgpropvarRem
+ &&
+ rgpropvar != rgpropvarRem )
+ {
+ FreePropVariantArray( cpspec, rgpropvarRem );
+ CoTaskMemFree( rgpropvarRem );
+ }
+
+ return( hr );
+
+} // IPropertyStorage_WriteMultiple_Proxy
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: IPropertyStorage_Write_Multiple_Stub
+// (See "prstg_ca.c" for an overview)
+//
+// Synopsis: This routine finishes the unmarshaling
+// of an array of PropVariants by making
+// regular BSTRs out of BSTR_BLOBs.
+//
+// The fBstrPresent flag indicates if any
+// such conversion is required. After
+// fixing the PropVariant[], we pass
+// the call on to the server.
+//
+// Note: The PROPSPEC and PROPVARIANT arrays
+// must be typed in the form of a pointer in
+// this interface. See the
+// IPropertyStorage_DeleteMultiple_Proxy/Stub
+// comments for an explanation.
+//
+//+-------------------------------------------------------------------------
+
+STDMETHODIMP
+IPropertyStorage_WriteMultiple_Stub(
+ IPropertyStorage __RPC_FAR *This,
+ /*[in]*/ BOOL fBstrPresent,
+ /*[in]*/ ULONG cpspec,
+ /*[in, size_is(cpspec)]*/
+ const PROPSPEC *rgpspec,
+ /*[in, size_is(cpspec)]*/
+ const PROPVARIANT *rgpropvarRem,
+ /*[in]*/ PROPID propidNameFirst
+ )
+{
+ HRESULT hr = S_OK;
+ ULONG ulIndex;
+
+ // The un-marshaled PropVariant[].
+
+ PROPVARIANT *rgpropvar = NULL;
+
+ // Is any BSTR-unmarshaling required?
+
+ if( fBstrPresent )
+ {
+ // Make a copy of the PropVariant[] so that we can
+ // modify pointers (we're going to need to free buffers
+ // during PropVarUnmarshal, and rgpropvarRem may not be
+ // allocated in the IMalloc heap).
+
+ rgpropvar = (PROPVARIANT*) CoTaskMemAlloc( cpspec * sizeof(*rgpropvar) );
+ if( NULL == rgpropvar )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+ memset( rgpropvar, 0, cpspec * sizeof(*rgpropvar) );
+
+ // Copy the individual PropVariants. BSTR_BLOBs
+ // in the destination will be in IMalloc heap.
+
+ for( ulIndex = 0; ulIndex < cpspec; ulIndex++ )
+ {
+ hr = PropVariantCopy( &rgpropvar[ ulIndex ],
+ &rgpropvarRem[ ulIndex ] );
+ if( FAILED(hr) ) goto Exit;
+ }
+
+ // Unmarshal the PropVariant[]. BSTRs will be in the
+ // OleAutomation heap.
+
+ hr = PropVarUnmarshal( cpspec,
+ rgpropvar );
+ if( FAILED(hr) ) goto Exit;
+ }
+ else
+ {
+ // No unmarshaling is required.
+ rgpropvar = (PROPVARIANT*) rgpropvarRem;
+
+ } // if( fBstrPresent )
+
+ // Write the properties.
+
+ hr = This->lpVtbl->WriteMultiple( This, cpspec, rgpspec,
+ rgpropvar,
+ propidNameFirst );
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // If we allocated a new PropVariant array during the Unmarshaling,
+ // free it now.
+
+ if( rgpropvar != rgpropvarRem
+ &&
+ NULL != rgpropvar )
+ {
+ FreePropVariantArray( cpspec, rgpropvar );
+ }
+
+ return( hr );
+
+} // IPropertyStorage_WriteMultiple_Stub
+
+
+
+//+-----------------------------------------------------------------------
+//
+// Function: IPropertyStorage_ReadMultiple_Proxy
+// (See "prstg_ca.c" for an overview)
+//
+// Synopsis: This routine first passes the request
+// on to the Server. If the Server indicates
+// in the return result that the PropVariant
+// array has specially-marshaled BSTR
+// properties, then this routine restores
+// them to normal BSTRs. This is necessary
+// because there is no standard marshaling
+// support for BSTRs.
+//
+// BSTR properties are made marshalable
+// on the Server side by converting them
+// to BLOBs, and changing their type
+// from VT_BSTR to VT_BSTR_BLOB.
+//
+// Note: The PROPSPEC and PROPVARIANT arrays
+// must be typed in the form of a pointer in
+// this interface. See the
+// IPropertyStorage_DeleteMultiple_Proxy/Stub
+// comments for an explanation.
+//
+//+-----------------------------------------------------------------------
+
+
+STDMETHODIMP
+IPropertyStorage_ReadMultiple_Proxy(
+ IPropertyStorage __RPC_FAR *This,
+ /*[in]*/ ULONG cpspec,
+ /*[in, size_is(cpspec)]*/
+ const PROPSPEC rgpspec[],
+ /*[in, size_is(cpspec)]*/
+ PROPVARIANT rgpropvar[]
+ )
+{
+ HRESULT hr = E_FAIL;
+ HRESULT hrPrivate = S_OK;
+ BOOL fBstrPresent;
+
+ // Pass the call on to the server
+
+ hr = IPropertyStorage_RemoteReadMultiple_Proxy( This, &fBstrPresent,
+ cpspec, rgpspec, rgpropvar );
+ if( FAILED(hr) ) goto Exit;
+
+ // Were there any BSTR properties?
+
+ if( fBstrPresent )
+ {
+ // Finish un-marshaling the PropVariant[] by
+ // restoring the BSTRs from BSTR_BLOBs. The BSTRs
+ // will be allocated from the OleAutomation heap.
+ // We save into hrPrivate so that if the RemoteReadMultiple
+ // call returns a success-code, we won't lose it in this
+ // un-marshaling call.
+
+ hrPrivate = PropVarUnmarshal( cpspec,
+ rgpropvar);
+ if( FAILED(hrPrivate) )
+ {
+ // Free the PropVariant[]; the caller expects
+ // to get all VT_EMPTYs if there was an error.
+
+ hr = hrPrivate;
+ FreePropVariantArray( cpspec, rgpropvar );
+ goto Exit;
+ }
+ } // if( fBstrPresent )
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return( hr );
+
+}
+
+
+//+---------------------------------------------------------------------------------
+//
+// Function: IPropertyStorage_ReadMultiple_Stub
+// (See "prstg_ca.c" for an overview)
+//
+// Synopsis: This routine passes the ReadMultiple
+// request on to the Server. The result
+// is then pre-marshaled; that is, the
+// PropVariant is converted so that it is in
+// remotable form. This entails converting
+// BSTRs (which aren't marshalable) into
+// BSTRBLOBs. Note that there could be a BSTR
+// property, and/or a vector of BSTRs, and/or
+// a vector of Variants where one Variant is a
+// BSTR.
+//
+// Aside from BSTRs, we also assume that non-simple
+// properties are not marshalable We assume this
+// because we assume that this code will only run
+// on systems where OLE doesn't already provide
+// the IProperty marshaling code - Win95 & NT 3.51 -
+// and on those systems, a bug in the RPC runtime
+// prevents interface pointers in unions from
+// being marshaled. So, if we discover a non-
+// simple property, we return with a failure.
+//
+// Note: The PROPSPEC and PROPVARIANT arrays
+// must be typed in the form of a pointer in
+// this interface. See the
+// IPropertyStorage_DeleteMultiple_Proxy/Stub
+// comments for an explanation.
+//
+//+---------------------------------------------------------------------------------
+
+STDMETHODIMP
+IPropertyStorage_ReadMultiple_Stub(
+ IPropertyStorage __RPC_FAR *This,
+ /*[out]*/ BOOL *pfBstrPresent,
+ /*[in]*/ ULONG cpspec,
+ /*[in, size_is(cpspec)]*/
+ const PROPSPEC *rgpspec,
+ /*[out, size_is(cpspec)]*/
+ PROPVARIANT *rgpropvar
+ )
+{
+ HRESULT hr = S_OK;
+ HRESULT hrPrivate = S_OK;
+ ULONG ulVTExists;
+
+ // Assume that there will be no BSTRs read.
+
+ *pfBstrPresent = FALSE;
+
+ // Pass on the ReadMultiple request to the Server
+
+ hr = This->lpVtbl->ReadMultiple( This, cpspec, rgpspec, rgpropvar );
+ if( FAILED(hr) ) goto Exit;
+
+ // Are there special properties that we need to worry about?
+
+ if( ulVTExists = ContainsSpecialProperty( cpspec, rgpropvar ))
+ {
+ // Yes. Is it a non-simple property? If so, we can't marshal
+ // it (see the synopsis above).
+
+ if( ulVTExists & NONSIMPLE_EXISTS )
+ {
+ hr = RPC_E_SERVER_CANTMARSHAL_DATA;
+ goto Exit;
+ }
+
+ // Otherwise, there must be a BSTR property in the PROPVARIANT[].
+
+ else
+ {
+ // Let the caller know that post-marshaling will be required.
+ *pfBstrPresent = TRUE;
+
+ // Pre-marshal the read PropVariant[]. BSTRs
+ // (allocated in the OleAut heap) will be converted
+ // to BSTR_BLOBs (in the IMalloc heap).
+
+ hrPrivate = PropVarMarshal( cpspec,
+ rgpropvar );
+ if( FAILED(hrPrivate) )
+ {
+ hr = hrPrivate;
+ goto Exit;
+ }
+ } // if( ulVTExists & NONSIMPLE_EXISTS ) ... else
+ } // if( ulVTExists = ContainsSpecialProperties( cpspec, rgpropvar ))
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( FAILED(hr) )
+ {
+ // Free the array, returning all VT_EMPTYs to the
+ // caller.
+
+ FreePropVariantArray( cpspec, rgpropvar );
+ }
+
+ return( hr );
+
+}
+
+
+//+----------------------------------------------------------------------------------
+//
+// Function: IPropertyStorage_DeleteMultiple_Proxy/Stub
+//
+// Synopsis: The purpose of these routines is not obvious.
+// Midl can produce "fat" or "skinny" proxies and
+// stubs. A fat Proxy/Stub can be generated with the
+// "-Os" option. This generates inline Proxy/Stub
+// code which uses the RPCRT4 library, and which
+// the Client/Server statically link. A skinny
+// Proxy/Stub can be generated with the "-Oi[#]"
+// option. This generates only a small amount
+// of inline code, which calls to dynamically linked
+// RPC interperator to do the majority of the work.
+//
+// The interperated method is preferable. However,
+// in order to keep the interperator small, it cannot
+// handle certain interfaces which are in some way
+// too complicated. In such cases, inline code is
+// generated instead. The PROPSPEC array on the
+// Delete/Read/WriteMultiple routines is one such
+// complication, as is the PROPVARIANT array.
+// However, by simply changing these parameters
+// to pointers, rather than arrays, the complication
+// is removed.
+//
+// The public ([local]) routines must remain
+// array-based, but the remotable routines are
+// pointer-based. Thus, the purpose of the DeleteMultiple
+// [call_as] code is to simply convert between the
+// two types of interfaces. This conversion is handled
+// implicitely by the compiler.
+//
+//+----------------------------------------------------------------------------------
+
+
+STDMETHODIMP
+IPropertyStorage_DeleteMultiple_Proxy(
+ IPropertyStorage __RPC_FAR *This,
+ /*[in]*/ ULONG cpspec,
+ /*[in, size_is(cpspec)]*/
+ const PROPSPEC rgpspec[]
+ )
+{
+
+ return( IPropertyStorage_RemoteDeleteMultiple_Proxy( This, cpspec, rgpspec ));
+
+}
+
+
+STDMETHODIMP
+IPropertyStorage_DeleteMultiple_Stub(
+ IPropertyStorage __RPC_FAR *This,
+ /*[in]*/ ULONG cpspec,
+ /*[in, size_is(cpspec)]*/
+ const PROPSPEC *rgpspec
+ )
+{
+ return( This->lpVtbl->DeleteMultiple( This, cpspec, rgpspec) );
+}
+
+
diff --git a/private/ole32/stg/props/iprop/dllmain.cxx b/private/ole32/stg/props/iprop/dllmain.cxx
new file mode 100644
index 000000000..43df8edbd
--- /dev/null
+++ b/private/ole32/stg/props/iprop/dllmain.cxx
@@ -0,0 +1,517 @@
+
+//+============================================================================
+//
+// File: dllmain.cxx
+//
+// Purpose: This file provides the registration and deregistration
+// functions for the IProp DLL: DllRegisterServer and
+// DllUnregisterServer. These two functions register/
+// deregister the property set marshaling code:
+// IPropertySetStorage, IPropertyStorage, IEnumSTATPROPSETSTG,
+// and IEnumSTATPROPSTG. Note that this registration is
+// different from the typical server registration in that
+// it only registers the marshaling code, it does not
+// register an instantiable COM server. Also, no registration
+// takes place if OLE32 is already registered to perform
+// this marshaling.
+//
+// The actual DllRegisterServer and DllUnregisterServer
+// implementations are at the end of this file. First,
+// several helper functions are defined.
+//
+// History:
+// 08-Nov-96 MikeHill Don't include olectl.h
+//
+//+============================================================================
+
+// --------
+// Includes
+// --------
+
+#include <pch.cxx>
+#include <tchar.h>
+
+// The following is from "olectl.h". That file couldn't simply
+// be included, however, because it isn't compatible with the
+// special objidl.h and wtypes.h used by IProp DLL.
+
+#define SELFREG_E_FIRST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x0200)
+#define SELFREG_E_LAST MAKE_SCODE(SEVERITY_ERROR, FACILITY_ITF, 0x020F)
+#define SELFREG_S_FIRST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x0200)
+#define SELFREG_S_LAST MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_ITF, 0x020F)
+
+#define SELFREG_E_TYPELIB (SELFREG_E_FIRST+0)
+#define SELFREG_E_CLASS (SELFREG_E_FIRST+1)
+
+// -------
+// Globals
+// -------
+
+// Important DLL names.
+const LPTSTR tszNameDll = TEXT( "IProp.dll" );
+
+// Registry entry descriptions
+const LPTSTR tszOle32PSFactoryClsid = TEXT( "{00000320-0000-0000-C000-000000000046}" );
+const LPTSTR tszNamePropertySetStorage = TEXT( "IPropertySetStorage" );
+const LPTSTR tszNamePropertyStorage = TEXT( "IPropertyStorage" );
+const LPTSTR tszNameIEnumSTATPROPSETSTG = TEXT( "IEnumSTATPROPSETSTG" );
+const LPTSTR tszNameIEnumSTATPROPSTG = TEXT( "IEnumSTATPROPSTG" );
+
+// GUIDs in Registry format
+const LPTSTR tszGuidPropertySetStorage = TEXT( "{0000013A-0000-0000-C000-000000000046}" );
+const LPTSTR tszGuidPropertyStorage = TEXT( "{00000138-0000-0000-C000-000000000046}" );
+const LPTSTR tszGuidIEnumSTATPROPSETSTG = TEXT( "{0000013B-0000-0000-C000-000000000046}" );
+const LPTSTR tszGuidIEnumSTATPROPSTG = TEXT( "{00000139-0000-0000-C000-000000000046}" );
+
+//+----------------------------------------------------------------------------
+//
+// Function: UpdateKeyAndSubKey
+//
+// Synopsis: This function either creates or deletes first
+// a key and un-named value under HKEY_CLASSES_ROOT,
+// then a sub-key and associated un-named value. The
+// caller indicates whether a create or delete should occur.
+//
+// However, the caller may specify that nothing be done
+// if the sub-key exists and already has a specific
+// un-named REG_SZ value.
+//
+// Inputs: [const LPTSTR] tszMainKey (in)
+// The name of the key under HKEY_CLASSES_ROOT.
+// [const LPTSTR] tszMainKeyDescription (in)
+// The un-named REG_SZ value under this key (not necessary
+// if fDelete is true).
+// [const LPTSTR] tszSubKey (in)
+// The name of the key under the first key.
+// [const LPTSTR] tszSubKeyDescription (in)
+// The un-named REG_SZ value to write under this sub-key
+// (not necessary if fDelete is true).
+// [const LPTSTR] tszSubKeyCheck (in)
+// If non-NULL, and the subkey already exists, see if
+// this string matches an un-named REG_SZ value in
+// the sub-key. If so, abort the operation and return
+// ERROR_ALREADY_EXISTS.
+// [BOOL] fDelete
+// If TRUE, delete the keys, if FALSE, create them.
+// But this is ignored if tszSubKeyCheck matches
+// (in which case nothing happens).
+//
+// Returns: [long] A GetLastError value.
+//
+//+----------------------------------------------------------------------------
+
+long
+UpdateKeyAndSubKey( const LPTSTR tszMainKey,
+ const LPTSTR tszMainKeyDescription,
+ const LPTSTR tszSubKey,
+ const LPTSTR tszSubKeyDescription,
+ const LPTSTR tszSubKeyCheck,
+ BOOL fDelete )
+{
+ // ------
+ // Locals
+ // ------
+
+ long lResult = ERROR_SUCCESS;
+ DWORD dwDisposition;
+
+ HKEY hkeyMain = NULL; // E.g. "HKEY_CLASSES_ROOT\\CLSID\\{.....}"
+ HKEY hkeySub = NULL; // E.g. ..."InProcServer32"
+
+ // -------------
+ // Open the keys
+ // -------------
+
+ // Are we opening for delete?
+
+ if( fDelete )
+ {
+ // Yes - we're deleting. We'll just attempt to do an Open.
+ dwDisposition = REG_OPENED_EXISTING_KEY;
+
+ lResult = RegOpenKeyEx( HKEY_CLASSES_ROOT,
+ tszMainKey,
+ 0L,
+ KEY_ALL_ACCESS,
+ &hkeyMain );
+
+ if( ERROR_SUCCESS == lResult )
+ {
+ lResult = RegOpenKeyEx( hkeyMain,
+ tszSubKey,
+ 0L,
+ KEY_ALL_ACCESS,
+ &hkeySub );
+ }
+
+ if( ERROR_FILE_NOT_FOUND == lResult )
+ lResult = ERROR_SUCCESS;
+ else if( ERROR_SUCCESS != lResult )
+ goto Exit;
+
+ } // if( fDelete )
+
+ else
+ {
+ // We're not opening for delete. So we'll use RegCreateKey,
+ // which does an Open if the key exists, and a Create otherwise.
+
+ lResult = RegCreateKeyEx( HKEY_CLASSES_ROOT,
+ tszMainKey,
+ 0L,
+ NULL,
+ 0,
+ KEY_ALL_ACCESS,
+ NULL,
+ &hkeyMain,
+ &dwDisposition );
+ if( lResult != ERROR_SUCCESS ) goto Exit;
+
+ // Open the sub-key.
+
+ lResult = RegCreateKeyEx( hkeyMain,
+ tszSubKey,
+ 0L,
+ NULL,
+ 0,
+ KEY_ALL_ACCESS,
+ NULL,
+ &hkeySub,
+ &dwDisposition );
+ if( ERROR_SUCCESS != lResult ) goto Exit;
+
+ } // if( fDelete ) ... else
+
+ // --------------------------
+ // Do we need to do anything?
+ // --------------------------
+
+ // Does it look like we might not need to do anything?
+
+ if( NULL != tszSubKeyCheck // The caller said to check first
+ &&
+ NULL != hkeySub // We Created or Opened a sub-key
+ && // Specifically, it was an Open.
+ REG_OPENED_EXISTING_KEY == dwDisposition )
+ {
+ // Yes - we need to see if the key already contains
+ // tszSubKeyCheck. If so, then we're done.
+
+ DWORD dwType = 0;
+ TCHAR tszData[ MAX_PATH ];
+ DWORD dwDataSize = sizeof( tszData );
+
+ // Is there an un-named value in this key?
+
+ lResult = RegQueryValueEx( hkeySub,
+ NULL, // Name
+ NULL, // Reserved
+ &dwType, // E.g. REG_SZ
+ (LPBYTE) tszData,// Return value
+ &dwDataSize ); // In: size of buf. Out: size of value
+
+ // We should have gotten a success-code or a not-extant code
+ if( ERROR_SUCCESS != lResult
+ &&
+ ERROR_FILE_NOT_FOUND != lResult )
+ {
+ goto Exit;
+ }
+
+ // If we got an extant SZ value that matches tszSubKeyCheck,
+ // then there's nothing we need do.
+
+ if( ERROR_SUCCESS == lResult
+ &&
+ REG_SZ == dwType
+ &&
+ !_tcsicmp( tszData, tszSubKeyCheck )
+ )
+ {
+ lResult = ERROR_ALREADY_EXISTS;
+ goto Exit;
+ }
+
+ } // if( REG_OPENED_EXISTING_KEY == dwDisposition ...
+
+ // --------------------------
+ // Delete keys, or set values
+ // --------------------------
+
+ if( fDelete )
+ {
+ // Reset the result code, since the code below may not set it.
+ lResult = ERROR_SUCCESS;
+
+ // We're doing a delete. First, delete the sub-key, which
+ // will delete any values. If there was no subkey, hkeySub will
+ // be NULL.
+
+ if( NULL != hkeySub )
+ {
+ CloseHandle( hkeySub );
+ hkeySub = NULL;
+
+ lResult = RegDeleteKey( hkeyMain,
+ tszSubKey );
+ if( ERROR_SUCCESS != lResult ) goto Exit;
+ }
+
+ // Second, delete the main key
+
+ if( NULL != hkeyMain )
+ {
+ CloseHandle( hkeyMain );
+ hkeyMain = NULL;
+
+ lResult = RegDeleteKey( HKEY_CLASSES_ROOT,
+ tszMainKey );
+ if( ERROR_SUCCESS != lResult ) goto Exit;
+ }
+
+ } // if( fDelete )
+
+ else
+ {
+ // We're adding to the Registry. The two keys are now
+ // created & opened, so we can add the REG_SZ values.
+
+ // The REG_SZ value for the main key.
+ lResult = RegSetValueEx(hkeyMain,
+ NULL,
+ 0L,
+ REG_SZ,
+ (const BYTE *) tszMainKeyDescription,
+ sizeof(TCHAR) * (1 + _tcslen(tszMainKeyDescription) ));
+ if( ERROR_SUCCESS != lResult ) goto Exit;
+
+ // The REG_SZ value for the sub-key.
+ lResult = RegSetValueEx(hkeySub,
+ NULL, 0L,
+ REG_SZ,
+ (const BYTE *) tszSubKeyDescription,
+ sizeof(TCHAR) * (1 + _tcslen(tszSubKeyDescription) ));
+ if( ERROR_SUCCESS != lResult ) goto Exit;
+
+ } // if( fDelete ) ... else
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( NULL != hkeySub )
+ CloseHandle( hkeySub );
+
+ if( NULL != hkeyMain )
+ CloseHandle( hkeyMain );
+
+ return( lResult );
+
+} // WriteKeyAndSubKey()
+
+
+//+----------------------------------------------------------------------------
+//
+// Function: RegisterForMarshaling
+//
+// Synopsis: This function takes the GUID ane name of an interface
+// for which MIDL-generated marshaling code exists in the
+// caller-specified DLL. First we try to update the
+// CLSID entries, but we'll fail this if the entries already
+// exist and reference OLE32 (OLE32 has better marshaling
+// code). If this doesn't fail, then we'll update the
+// Interface entries.
+//
+// The caller specifies if this "update" of the registry
+// is a write or a delete. This this routine can be used
+// in either a registration or a de-registration.
+//
+// Inputs: [const LPTSTR] tszGuid (in)
+// The GUID in registery format ("{...-...-...}")
+// [const LPTSTR] tszName (in)
+// The name of the interface
+// [const LPTSTR] tszDllPath (in)
+// The complete path and filename of the DLL which contains
+// the marshaling code.
+// [BOOL] fDelete (in)
+// Determines if we add to the Registry or delete from it.
+//
+// Returns: [long] a GetLastError() value
+//
+//+----------------------------------------------------------------------------
+
+
+long
+RegisterForMarshaling( const LPTSTR tszGuid,
+ const LPTSTR tszName,
+ const LPTSTR tszDllPath,
+ BOOL fDelete )
+{
+ // ------
+ // Locals
+ // ------
+
+ long lResult;
+ TCHAR tszMainKey[ MAX_PATH ];
+
+ // -----------------------------------
+ // Update HKEY_CLASSES_ROOT\Interfaces
+ // -----------------------------------
+
+ // Calculate the key name name
+ _tcscpy( tszMainKey, TEXT( "Interface\\" ));
+ _tcscat( tszMainKey, tszGuid );
+
+ // Update the registry, but only if there isn't a current
+ // entry pointing to OLE32's proxy/stub factory.
+
+ lResult = UpdateKeyAndSubKey( tszMainKey,
+ tszName,
+ TEXT( "ProxyStubClsid32" ),
+ tszGuid,
+ tszOle32PSFactoryClsid,
+ fDelete );
+ if( ERROR_SUCCESS != lResult ) goto Exit;
+
+
+ // ------------------------------
+ // Update HKEY_CLASSES_ROOT\CLSID
+ // ------------------------------
+
+ // Calculate the name.
+ _tcscpy( tszMainKey, TEXT( "CLSID\\" ));
+ _tcscat( tszMainKey, tszGuid );
+
+ // Update the entries. This will add the path (if !fDelete) or remove
+ // the registry entry (if fDelete) regardless of the current state
+ // of the key; if we weren't supposed to remove it, the previous
+ // call to UpdateKeyAndSubKey would have returned an error.
+
+ lResult = UpdateKeyAndSubKey( tszMainKey,
+ tszName,
+ TEXT( "InprocServer32" ),
+ tszDllPath,
+ NULL, // Add/delete, regardless of what exists
+ fDelete );
+ if( ERROR_SUCCESS != lResult ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( ERROR_ALREADY_EXISTS == lResult )
+ {
+ PropDbg(( DEB_WARN, "IProp DLL UpdateKeyAndSubKey: Entry already exists\n" ));
+ lResult = ERROR_SUCCESS;
+ }
+
+ return( lResult );
+
+} // RegisterForMarshaling()
+
+
+//+----------------------------------------------------------------------------
+//
+// Function: RegisterServer
+//
+// Synopsis: This routine can be used with both DllRegisterServer and
+// DllUnregisterServer. It adds/deletes IPropertySetStorage
+// IPropertyStorage, IEnumSTATPROPSETSTG, and IEnumSTATPROPSTG.
+//
+// Inputs: [BOOL] fDelete (in)
+// Indicates whether the registry entries should be added
+// or removed.
+//
+// Returns: [HRESULT]
+//
+//+----------------------------------------------------------------------------
+
+
+STDAPI RegisterServer( BOOL fDelete )
+{
+ // ------
+ // Locals
+ // ------
+
+ LONG lResult;
+
+ // -----
+ // Begin
+ // -----
+
+ // Register IPropertySetStorage
+ lResult = RegisterForMarshaling( tszGuidPropertySetStorage,
+ tszNamePropertySetStorage,
+ tszNameDll,
+ fDelete );
+ if( ERROR_SUCCESS != lResult ) goto Exit;
+
+ // Register IPropertyStorage
+ lResult = RegisterForMarshaling( tszGuidPropertyStorage,
+ tszNamePropertyStorage,
+ tszNameDll,
+ fDelete );
+ if( ERROR_SUCCESS != lResult ) goto Exit;
+
+ // Register IEnumSTATPROPSETSTG
+ lResult = RegisterForMarshaling( tszGuidIEnumSTATPROPSETSTG,
+ tszNameIEnumSTATPROPSETSTG,
+ tszNameDll,
+ fDelete );
+ if( ERROR_SUCCESS != lResult ) goto Exit;
+
+ // Register IEnumSTATPROPSTG
+ lResult = RegisterForMarshaling( tszGuidIEnumSTATPROPSTG,
+ tszNameIEnumSTATPROPSTG,
+ tszNameDll,
+ fDelete );
+ if( ERROR_SUCCESS != lResult ) goto Exit;
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( ERROR_SUCCESS != lResult )
+ {
+ PropDbg(( DEB_ERROR, "IProp DLL RegisterServer failed (%lu)\n", lResult ));
+ return( SELFREG_E_CLASS );
+ }
+ else
+ {
+ return( S_OK );
+ }
+
+} // RegisterServer()
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Function: DllRegisterServer & DllUnregisterServer
+//
+// Synopsis: These routines are the standard DLL registration entry
+// points for a self-registering in-proc COM server. They
+// are used to register the property set marshaling code.
+// These routines are called, for example,
+// by a setup program during installation and de-installation,
+// respectively.
+//
+//+----------------------------------------------------------------------------
+
+STDAPI DllRegisterServer()
+{
+ return( RegisterServer( FALSE ));
+}
+
+STDAPI DllUnregisterServer()
+{
+ return( RegisterServer( TRUE ));
+}
+
diff --git a/private/ole32/stg/props/iprop/iprop.def b/private/ole32/stg/props/iprop/iprop.def
new file mode 100644
index 000000000..d83ff9c81
--- /dev/null
+++ b/private/ole32/stg/props/iprop/iprop.def
@@ -0,0 +1,15 @@
+LIBRARY IPROP
+DESCRIPTION 'OLE Property Set APIs and Interfaces'
+EXPORTS PropVariantCopy
+ PropVariantClear
+ FreePropVariantArray
+ StgCreatePropStg
+ StgOpenPropStg
+ StgCreatePropSetStg
+ PropStgNameToFmtId
+ FmtIdToPropStgName
+ DllGetClassObject
+ DllCanUnloadNow
+ DllRegisterServer
+ DllUnregisterServer
+ GetProxyDllInfo
diff --git a/private/ole32/stg/props/iprop/iprop.r b/private/ole32/stg/props/iprop/iprop.r
new file mode 100644
index 000000000..02b5d7e09
--- /dev/null
+++ b/private/ole32/stg/props/iprop/iprop.r
@@ -0,0 +1,18 @@
+#include "CodeFrag.r"
+
+ resource 'cfrg' (0)
+ {
+ {
+ kPowerPC,
+ kFullLib,
+ kNoVersionNum,
+ kNoVersionNum,
+ kDefaultStackSize,
+ kNoAppSubFolder,
+ kIsLib,
+ kOnDiskFlat,
+ kZeroOffset,
+ kWholeFork,
+ "IProperty"
+ }
+ };
diff --git a/private/ole32/stg/props/iprop/iprop.rc b/private/ole32/stg/props/iprop/iprop.rc
new file mode 100644
index 000000000..1e02c3447
--- /dev/null
+++ b/private/ole32/stg/props/iprop/iprop.rc
@@ -0,0 +1,16 @@
+
+//
+// Version resources
+//
+#include <ntverp.h>
+#include <winver.h>
+#undef VER_PRODUCTNAME_STR
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_PRODUCTNAME_STR "OLE PropertySet Implementation\0"
+#define VER_COMMENT_STR "OLE PropertySet Implementation\0"
+#define VER_FILEDESCRIPTION_STR "OLE PropertySet Implementation\0"
+#define VER_INTERNALNAME_STR "IPROP.DLL"
+#define VER_ORIGINALFILENAME_STR "IPROP.DLL"
+#include <common.ver>
diff --git a/private/ole32/stg/props/iprop/ipropidl.idl b/private/ole32/stg/props/iprop/ipropidl.idl
new file mode 100644
index 000000000..e8febf135
--- /dev/null
+++ b/private/ole32/stg/props/iprop/ipropidl.idl
@@ -0,0 +1,579 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1996.
+//
+// File: ipropidl.idl
+//
+//--------------------------------------------------------------------------
+
+cpp_quote("//+-------------------------------------------------------------------------")
+cpp_quote("//")
+cpp_quote("// Microsoft Windows")
+cpp_quote("// Copyright (C) Microsoft Corporation, 1992 - 1996.")
+cpp_quote("//")
+cpp_quote("//--------------------------------------------------------------------------")
+
+
+/****************************************************************************
+ * Property Storage Interfaces
+ ****************************************************************************/
+
+import "unknwn.idl";
+import "wtypes.idl";
+import "objidl.idl";
+import "oaidl.idl";
+
+interface IEnumSTATPROPSTG;
+interface IEnumSTATPROPSETSTG;
+
+[
+ object,
+ uuid(00000138-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IPropertyStorage : IUnknown
+{
+ typedef struct tagBSTRBLOB
+ {
+ ULONG cbSize;
+ [size_is(cbSize)] BYTE *pData;
+ } BSTRBLOB, * LPBSTRBLOB;
+
+ // Format ID are just a kind of GUID
+ typedef GUID FMTID;
+ typedef FMTID *LPFMTID;
+ cpp_quote("#define FMTID_NULL GUID_NULL")
+ cpp_quote("#define IsEqualFMTID(rfmtid1, rfmtid2) IsEqualGUID(rfmtid1, rfmtid2)")
+
+ //The following typedefs are used internally by MIDL.
+ cpp_quote("#if 0")
+ #if defined(__midl)
+ /* MIDL 2.0 definitions */
+ typedef FMTID *REFFMTID;
+ #else
+ /* MIDL 1.1 definitions */
+ typedef FMTID REFFMTID;
+ #endif
+ cpp_quote("#endif // 0")
+
+ cpp_quote("#if defined(__cplusplus)")
+
+ cpp_quote("#ifndef _REFFMTID_DEFINED")
+ cpp_quote("#define _REFFMTID_DEFINED")
+ cpp_quote("#define REFFMTID const FMTID &")
+ cpp_quote("#endif // !_REFFMTID_DEFINED")
+
+
+ cpp_quote("#else // !__cplusplus")
+
+ cpp_quote("#ifndef _REFFMTID_DEFINED")
+ cpp_quote("#define _REFFMTID_DEFINED")
+ cpp_quote("#define REFFMTID const FMTID * const")
+ cpp_quote("#endif // !_REFFMTID_DEFINED")
+
+ cpp_quote("#endif // !__cplusplus")
+
+ cpp_quote("")
+ cpp_quote("// Well-known Property Set Format IDs")
+ extern const FMTID FMTID_SummaryInformation;
+ extern const FMTID FMTID_DocSummaryInformation;
+ extern const FMTID FMTID_UserDefinedProperties;
+
+ cpp_quote("")
+ cpp_quote("// Flags for IPropertySetStorage::Create")
+ const DWORD PROPSETFLAG_DEFAULT = 0;
+ const DWORD PROPSETFLAG_NONSIMPLE = 1;
+ const DWORD PROPSETFLAG_ANSI = 2;
+ cpp_quote("// This flag is only supported on StgCreatePropStg & StgOpenPropStg")
+ const DWORD PROPSETFLAG_UNBUFFERED = 4;
+
+ typedef [unique] IPropertyStorage * LPPROPERTYSTORAGE;
+
+ typedef struct tagPROPVARIANT PROPVARIANT;
+
+ #define TYPEDEF_CA(type, name) \
+ typedef struct tag##name\
+ {\
+ ULONG cElems;\
+ [size_is( cElems )]\
+ type * pElems;\
+ } name
+
+ TYPEDEF_CA(unsigned char, CAUB);
+ TYPEDEF_CA(short, CAI);
+ TYPEDEF_CA(USHORT, CAUI);
+ TYPEDEF_CA(long, CAL);
+ TYPEDEF_CA(ULONG, CAUL);
+ TYPEDEF_CA(float, CAFLT);
+ TYPEDEF_CA(double, CADBL);
+ TYPEDEF_CA(CY, CACY);
+ TYPEDEF_CA(DATE, CADATE);
+ TYPEDEF_CA(BSTR, CABSTR);
+ TYPEDEF_CA(BSTRBLOB, CABSTRBLOB);
+ TYPEDEF_CA(VARIANT_BOOL, CABOOL);
+ TYPEDEF_CA(SCODE, CASCODE);
+ TYPEDEF_CA(PROPVARIANT, CAPROPVARIANT);
+ TYPEDEF_CA(LARGE_INTEGER, CAH);
+ TYPEDEF_CA(ULARGE_INTEGER, CAUH);
+ TYPEDEF_CA(LPSTR, CALPSTR);
+ TYPEDEF_CA(LPWSTR, CALPWSTR);
+ TYPEDEF_CA(FILETIME, CAFILETIME);
+ TYPEDEF_CA(CLIPDATA, CACLIPDATA);
+ TYPEDEF_CA(CLSID, CACLSID);
+
+ const DWORD VT_ILLEGAL = 0xffff;
+ const DWORD VT_BSTR_BLOB = 0x0fff;
+ const DWORD VT_ILLEGALMASKED = 0x0fff;
+ const DWORD VT_TYPEMASK = 0x0fff;
+
+cpp_quote("// Macro to calculate the size of the above pClipData")
+cpp_quote("#define CBPCLIPDATA(clipdata) ( (clipdata).cbSize - sizeof((clipdata).ulClipFmt) )")
+
+cpp_quote("// Disable the warning about the obsolete member named 'bool'")
+cpp_quote("// 'bool', 'true', 'false', 'mutable', 'explicit', & 'typename'")
+cpp_quote("// are reserved keywords")
+cpp_quote("#pragma warning(disable:4237)")
+
+
+ struct tagPROPVARIANT
+ {
+ VARTYPE vt;
+ WORD wReserved1;
+ WORD wReserved2;
+ WORD wReserved3;
+ [switch_is((unsigned short) (vt & 0x1fff))] union
+ {
+ [case(VT_EMPTY, VT_NULL)]
+ ;
+ [case(VT_UI1)]
+ UCHAR bVal;
+ [case(VT_I2)]
+ short iVal;
+ [case(VT_UI2)]
+ USHORT uiVal;
+ [case(VT_BOOL)]
+ VARIANT_BOOL boolVal;
+ [case(VT_ILLEGAL)] // obsolete field name; use boolVal
+ VARIANT_BOOL bool;
+ [case(VT_I4)]
+ long lVal;
+ [case(VT_UI4)]
+ ULONG ulVal;
+ [case(VT_R4)]
+ float fltVal;
+ [case(VT_ERROR)]
+ SCODE scode;
+ [case(VT_I8)]
+ LARGE_INTEGER hVal;
+ [case(VT_UI8)]
+ ULARGE_INTEGER uhVal;
+ [case(VT_R8)]
+ double dblVal;
+ [case(VT_CY)]
+ CY cyVal;
+ [case(VT_DATE)]
+ DATE date;
+ [case(VT_FILETIME)]
+ FILETIME filetime;
+ [case(VT_CLSID)]
+ CLSID * puuid;
+ [case(VT_BLOB, VT_BLOB_OBJECT)]
+ BLOB blob;
+ [case(VT_CF)]
+ CLIPDATA *pclipdata;
+ [case(VT_STREAM, VT_STREAMED_OBJECT)]
+ IStream * pStream;
+ [case(VT_STORAGE, VT_STORED_OBJECT)]
+ IStorage * pStorage;
+ [case(VT_BSTR)]
+ BSTR bstrVal;
+ [case(VT_BSTR_BLOB)]
+ BSTRBLOB bstrblobVal;
+ [case(VT_LPSTR)]
+ LPSTR pszVal;
+ [case(VT_LPWSTR)]
+ LPWSTR pwszVal;
+ [case(VT_UI1|VT_VECTOR)]
+ CAUB caub;
+ [case(VT_I2|VT_VECTOR)]
+ CAI cai;
+ [case(VT_UI2|VT_VECTOR)]
+ CAUI caui;
+ [case(VT_BOOL|VT_VECTOR)]
+ CABOOL cabool;
+ [case(VT_I4|VT_VECTOR)]
+ CAL cal;
+ [case(VT_UI4|VT_VECTOR)]
+ CAUL caul;
+ [case(VT_R4|VT_VECTOR)]
+ CAFLT caflt;
+ [case(VT_ERROR|VT_VECTOR)]
+ CASCODE cascode;
+ [case(VT_I8|VT_VECTOR)]
+ CAH cah;
+ [case(VT_UI8|VT_VECTOR)]
+ CAUH cauh;
+ [case(VT_R8|VT_VECTOR)]
+ CADBL cadbl;
+ [case(VT_CY|VT_VECTOR)]
+ CACY cacy;
+ [case(VT_DATE|VT_VECTOR)]
+ CADATE cadate;
+ [case(VT_FILETIME|VT_VECTOR)]
+ CAFILETIME cafiletime;
+ [case(VT_CLSID|VT_VECTOR)]
+ CACLSID cauuid;
+ [case(VT_CF|VT_VECTOR)]
+ CACLIPDATA caclipdata;
+ [case(VT_BSTR|VT_VECTOR)]
+ CABSTR cabstr;
+ [case(VT_BSTR_BLOB|VT_VECTOR)]
+ CABSTRBLOB cabstrblob;
+ [case(VT_LPSTR|VT_VECTOR)]
+ CALPSTR calpstr;
+ [case(VT_LPWSTR|VT_VECTOR)]
+ CALPWSTR calpwstr;
+ [case(VT_VARIANT|VT_VECTOR)]
+ CAPROPVARIANT capropvar;
+ };
+ };
+
+ typedef struct tagPROPVARIANT * LPPROPVARIANT;
+
+ cpp_quote("// Reserved global Property IDs")
+ const PROPID PID_DICTIONARY = 0x00000000;
+ const PROPID PID_CODEPAGE = 0x00000001;
+ const PROPID PID_FIRST_USABLE = 0x00000002;
+ const PROPID PID_FIRST_NAME_DEFAULT = 0x00000fff;
+ const PROPID PID_LOCALE = 0x80000000;
+ const PROPID PID_MODIFY_TIME = 0x80000001;
+ const PROPID PID_SECURITY = 0x80000002;
+ const PROPID PID_ILLEGAL = 0xffffffff;
+
+
+ cpp_quote("// Property IDs for the SummaryInformation Property Set")
+ cpp_quote("")
+ cpp_quote("#define PIDSI_TITLE 0x00000002L // VT_LPSTR")
+ cpp_quote("#define PIDSI_SUBJECT 0x00000003L // VT_LPSTR")
+ cpp_quote("#define PIDSI_AUTHOR 0x00000004L // VT_LPSTR")
+ cpp_quote("#define PIDSI_KEYWORDS 0x00000005L // VT_LPSTR")
+ cpp_quote("#define PIDSI_COMMENTS 0x00000006L // VT_LPSTR")
+ cpp_quote("#define PIDSI_TEMPLATE 0x00000007L // VT_LPSTR")
+ cpp_quote("#define PIDSI_LASTAUTHOR 0x00000008L // VT_LPSTR")
+ cpp_quote("#define PIDSI_REVNUMBER 0x00000009L // VT_LPSTR")
+ cpp_quote("#define PIDSI_EDITTIME 0x0000000aL // VT_FILETIME (UTC)")
+ cpp_quote("#define PIDSI_LASTPRINTED 0x0000000bL // VT_FILETIME (UTC)")
+ cpp_quote("#define PIDSI_CREATE_DTM 0x0000000cL // VT_FILETIME (UTC)")
+ cpp_quote("#define PIDSI_LASTSAVE_DTM 0x0000000dL // VT_FILETIME (UTC)")
+ cpp_quote("#define PIDSI_PAGECOUNT 0x0000000eL // VT_I4")
+ cpp_quote("#define PIDSI_WORDCOUNT 0x0000000fL // VT_I4")
+ cpp_quote("#define PIDSI_CHARCOUNT 0x00000010L // VT_I4")
+ cpp_quote("#define PIDSI_THUMBNAIL 0x00000011L // VT_CF")
+ cpp_quote("#define PIDSI_APPNAME 0x00000012L // VT_LPSTR")
+ cpp_quote("#define PIDSI_DOC_SECURITY 0x00000013L // VT_I4")
+
+ const ULONG PRSPEC_INVALID = 0xffffffff;
+ const ULONG PRSPEC_LPWSTR = 0;
+ const ULONG PRSPEC_PROPID = 1;
+
+ typedef struct tagPROPSPEC
+ {
+
+ ULONG ulKind;
+ [switch_is(ulKind)] union
+ {
+ [case(PRSPEC_PROPID)]
+ PROPID propid;
+ [case(PRSPEC_LPWSTR)]
+ LPOLESTR lpwstr;
+ [default] ;
+ } ;
+
+ } PROPSPEC;
+
+ typedef struct tagSTATPROPSTG
+ {
+
+ LPOLESTR lpwstrName;
+ PROPID propid;
+ VARTYPE vt;
+
+ } STATPROPSTG;
+
+ cpp_quote("// Macros for parsing the OS Version of the Property Set Header")
+ cpp_quote("#define PROPSETHDR_OSVER_KIND(dwOSVer) HIWORD( (dwOSVer) )")
+ cpp_quote("#define PROPSETHDR_OSVER_MAJOR(dwOSVer) LOBYTE(LOWORD( (dwOSVer) ))")
+ cpp_quote("#define PROPSETHDR_OSVER_MINOR(dwOSVer) HIBYTE(LOWORD( (dwOSVer) ))")
+ cpp_quote("#define PROPSETHDR_OSVERSION_UNKNOWN 0xFFFFFFFF")
+
+ typedef struct tagSTATPROPSETSTG
+ {
+
+ FMTID fmtid;
+ CLSID clsid;
+ DWORD grfFlags;
+ FILETIME mtime;
+ FILETIME ctime;
+ FILETIME atime;
+ DWORD dwOSVersion;
+
+ } STATPROPSETSTG;
+
+ // For the remotable routines, we must use pointer
+ // parameters (e.g. "*rgspec" rather than "rgspec[]")
+ // so that the MIDL 2.0 compiler will generate an
+ // interpereted proxy/stub, rather than inline.
+
+ [local]
+ HRESULT ReadMultiple(
+ [in] ULONG cpspec,
+ [in, size_is(cpspec)]
+ const PROPSPEC rgpspec[],
+ [out, size_is(cpspec)]
+ PROPVARIANT rgpropvar[]
+ );
+
+ [call_as(ReadMultiple)]
+ HRESULT RemoteReadMultiple(
+ [out] BOOL *pfBstrPresent,
+ [in] ULONG cpspec,
+ [in, size_is(cpspec)]
+ const PROPSPEC *rgpspec,
+ [out, size_is(cpspec)]
+ PROPVARIANT *rgpropvar
+ );
+
+ [local]
+ HRESULT WriteMultiple(
+ [in] ULONG cpspec,
+ [in, size_is(cpspec)]
+ const PROPSPEC rgpspec[],
+ [in, size_is(cpspec)]
+ const PROPVARIANT rgpropvar[],
+ [in] PROPID propidNameFirst
+ );
+
+ [call_as(WriteMultiple)]
+ HRESULT RemoteWriteMultiple(
+ [in] BOOL fBstrPresent,
+ [in] ULONG cpspec,
+ [in, size_is(cpspec)]
+ const PROPSPEC *rgpspec,
+ [in, size_is(cpspec)]
+ const PROPVARIANT *rgpropvar,
+ [in] PROPID propidNameFirst
+ );
+
+ [local]
+ HRESULT DeleteMultiple(
+ [in] ULONG cpspec,
+ [in, size_is(cpspec)]
+ const PROPSPEC rgpspec[]
+ );
+
+ [call_as(DeleteMultiple)]
+ HRESULT RemoteDeleteMultiple(
+ [in] ULONG cpspec,
+ [in, size_is(cpspec)]
+ const PROPSPEC *rgpspec
+ );
+
+ HRESULT ReadPropertyNames(
+ [in] ULONG cpropid,
+ [in, size_is(cpropid)]
+ const PROPID rgpropid[],
+ [out, size_is(cpropid)]
+ LPOLESTR rglpwstrName[]
+ );
+
+ HRESULT WritePropertyNames(
+ [in] ULONG cpropid,
+ [in, size_is(cpropid)]
+ const PROPID rgpropid[],
+ [in, size_is(cpropid)]
+ const LPOLESTR rglpwstrName[]
+ );
+
+ HRESULT DeletePropertyNames(
+ [in] ULONG cpropid,
+ [in, size_is(cpropid)]
+ const PROPID rgpropid[]
+ );
+
+ HRESULT Commit(
+ [in] DWORD grfCommitFlags
+ );
+
+ HRESULT Revert();
+
+ HRESULT Enum(
+ [out] IEnumSTATPROPSTG ** ppenum
+ );
+
+ HRESULT SetTimes(
+ [in] FILETIME const * pctime,
+ [in] FILETIME const * patime,
+ [in] FILETIME const * pmtime
+ );
+
+ HRESULT SetClass(
+ [in] REFCLSID clsid
+ );
+
+ HRESULT Stat(
+ [out] STATPROPSETSTG * pstatpsstg
+ );
+}
+
+
+[
+ object,
+ uuid(0000013A-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IPropertySetStorage : IUnknown
+{
+
+ typedef [unique] IPropertySetStorage * LPPROPERTYSETSTORAGE;
+
+ HRESULT Create(
+ [in] REFFMTID rfmtid,
+ [in, unique]
+ const CLSID * pclsid,
+ [in] DWORD grfFlags,
+ [in] DWORD grfMode,
+ [out] IPropertyStorage ** ppprstg
+ );
+
+ HRESULT Open(
+ [in] REFFMTID rfmtid,
+ [in] DWORD grfMode,
+ [out] IPropertyStorage ** ppprstg
+ );
+
+ HRESULT Delete(
+ [in] REFFMTID rfmtid
+ );
+
+ HRESULT Enum(
+ [out] IEnumSTATPROPSETSTG ** ppenum
+ );
+
+}
+
+
+[
+ object,
+ uuid(00000139-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IEnumSTATPROPSTG : IUnknown
+{
+
+ typedef [unique] IEnumSTATPROPSTG * LPENUMSTATPROPSTG;
+
+ [local]
+ HRESULT Next(
+ [in] ULONG celt,
+ [in] STATPROPSTG * rgelt,
+ [out] ULONG * pceltFetched
+ );
+
+ [call_as(Next)]
+ HRESULT RemoteNext(
+ [in] ULONG celt,
+ [out, size_is(celt), length_is(*pceltFetched)]
+ STATPROPSTG * rgelt,
+ [out] ULONG * pceltFetched
+ );
+
+ HRESULT Skip(
+ [in] ULONG celt
+ );
+
+ HRESULT Reset();
+
+ HRESULT Clone(
+ [out] IEnumSTATPROPSTG ** ppenum
+ );
+}
+
+
+[
+ object,
+ uuid(0000013B-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IEnumSTATPROPSETSTG : IUnknown
+{
+
+ typedef [unique] IEnumSTATPROPSETSTG * LPENUMSTATPROPSETSTG;
+
+ [local]
+ HRESULT Next(
+ [in] ULONG celt,
+ [in] STATPROPSETSTG * rgelt,
+ [out] ULONG * pceltFetched
+ );
+
+ [call_as(Next)]
+ HRESULT RemoteNext(
+ [in] ULONG celt,
+ [out, size_is(celt), length_is(*pceltFetched)]
+ STATPROPSETSTG * rgelt,
+ [out] ULONG * pceltFetched
+ );
+
+ HRESULT Skip(
+ [in] ULONG celt
+ );
+
+ HRESULT Reset();
+
+ HRESULT Clone(
+ [out] IEnumSTATPROPSETSTG ** ppenum
+ );
+}
+
+
+cpp_quote("")
+cpp_quote("#ifndef _IPropertyStorage_DEFINED")
+cpp_quote("WINOLEAPI PropVariantCopy ( PROPVARIANT * pvarDest, const PROPVARIANT * pvarSrc );")
+cpp_quote("WINOLEAPI PropVariantClear ( PROPVARIANT * pvar );")
+cpp_quote("WINOLEAPI FreePropVariantArray ( ULONG cVariants, PROPVARIANT * rgvars );")
+
+cpp_quote("")
+cpp_quote("#define _PROPVARIANTINIT_DEFINED_")
+cpp_quote("# ifdef __cplusplus")
+cpp_quote("inline void PropVariantInit ( PROPVARIANT * pvar )")
+cpp_quote("{")
+cpp_quote(" memset ( pvar, 0, sizeof(PROPVARIANT) );")
+cpp_quote("}")
+cpp_quote("# else")
+cpp_quote("# define PropVariantInit(pvar) memset ( pvar, 0, sizeof(PROPVARIANT) )")
+cpp_quote("# endif")
+cpp_quote("#endif // #ifndef _IPropertyStorage_DEFINED")
+cpp_quote("")
+
+
+
+
+cpp_quote("")
+cpp_quote("#ifndef _STGCREATEPROPSTG_DEFINED_")
+cpp_quote("WINOLEAPI StgCreatePropStg( IUnknown* pUnk, REFFMTID fmtid, const CLSID *pclsid, DWORD grfFlags, DWORD dwReserved, IPropertyStorage **ppPropStg );")
+cpp_quote("WINOLEAPI StgOpenPropStg( IUnknown* pUnk, REFFMTID fmtid, DWORD grfFlags, DWORD dwReserved, IPropertyStorage **ppPropStg );")
+cpp_quote("WINOLEAPI StgCreatePropSetStg( IStorage *pStorage, DWORD dwReserved, IPropertySetStorage **ppPropSetStg);")
+
+cpp_quote("")
+cpp_quote("#define CCH_MAX_PROPSTG_NAME 31")
+cpp_quote("#define CCH_MAX_PROPSTG_NAMESZ (CCH_MAX_PROPSTG_NAME + 1) // Includes NULL terminator")
+cpp_quote("WINOLEAPI FmtIdToPropStgName( const FMTID *pfmtid, LPOLESTR oszName );" )
+cpp_quote("WINOLEAPI PropStgNameToFmtId( const LPOLESTR oszName, FMTID *pfmtid );" )
+cpp_quote("#endif")
+
+
diff --git a/private/ole32/stg/props/iprop/makefile b/private/ole32/stg/props/iprop/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/props/iprop/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/props/iprop/makefile.inc b/private/ole32/stg/props/iprop/makefile.inc
new file mode 100644
index 000000000..4d6910ce3
--- /dev/null
+++ b/private/ole32/stg/props/iprop/makefile.inc
@@ -0,0 +1,41 @@
+!ifndef MIDL
+MIDL = midl.exe
+!endif
+
+#
+# The following lines remove the "-DDBG=1" from the command-line.
+# This was done so that we could build with debug (with CV symbols)
+# without requiring a checked OLE32 on the system
+#
+#!MESSAGE Changed TARGET_DBG_DEFINES from "$(TARGET_DBG_DEFINES)"
+#TARGET_DBG_DEFINES=$(TARGET_DBG_DEFINES:DBG=NOOP_DBG)
+#!MESSAGE New TARGET_DBG_DEFINES is "$(TARGET_DBG_DEFINES)"
+
+MIDL_FLAGS= \
+ -Zp8 \
+ -I$(INCLUDES) \
+ -I$(BASEDIR)/public/sdk/inc \
+ -char unsigned \
+ -ms_ext -c_ext \
+ -proxy ipropidl_p.c \
+ -dlldata dlldata.c \
+ -iid ipropidl_i.c \
+ $(C_DEFINES) \
+ -cpp_cmd $(TARGET_CPP) \
+ -DMIDL_PASS $(C_DEFINES) -I$(INCLUDES) \
+ -Oi \
+ -D_WCHAR_T_DEFINED
+
+SSWITCH=-prefix sstub _
+
+ipropidl.h: ipropidl.idl
+ @echo MIDLing - $** > con:
+ $(MIDL20) $(MIDL_FLAGS) -header ipropidl.h ipropidl.idl
+
+
+DEST_TREE=daytona
+
+allidl: ipropidl.h
+
+clean:
+ -erase ipropidl.h >NUL 2>NUL
diff --git a/private/ole32/stg/props/iprop/oaidl.h b/private/ole32/stg/props/iprop/oaidl.h
new file mode 100644
index 000000000..41c3d21b5
--- /dev/null
+++ b/private/ole32/stg/props/iprop/oaidl.h
@@ -0,0 +1,3843 @@
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+/* File created by MIDL compiler version 2.00.0102 */
+/* at Fri Apr 28 07:02:38 1995
+ */
+//@@MIDL_FILE_HEADING( )
+#ifndef __RPCBASE_H__
+#include "rpcbase.h"
+#endif /* ___RPCBASE_H__ */
+#ifndef NORPC
+#ifndef __RPC_H__
+#include "rpc.h"
+#endif /* ___RPC_H__ */
+#ifndef __RPCNDR_H__
+#include "rpcndr.h"
+#endif /* __RPCNDR_H_ */
+#endif /* NORPC */
+#ifndef COM_NO_WINDOWS_H
+#ifndef _INC_WINDOWS
+#include "windows.h"
+#endif /* _INC_WINDOWS */
+#ifndef _OLE2_H_
+#include "ole2.h"
+#endif /* _OLE2_H_ */
+#endif /*COM_NO_WINDOWS_H*/
+
+#ifndef __oaidl_h__
+#define __oaidl_h__
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/* Forward Declarations */
+
+#ifndef __ICreateTypeInfo_FWD_DEFINED__
+#define __ICreateTypeInfo_FWD_DEFINED__
+typedef interface ICreateTypeInfo ICreateTypeInfo;
+#endif /* __ICreateTypeInfo_FWD_DEFINED__ */
+
+
+#ifndef __ICreateTypeLib_FWD_DEFINED__
+#define __ICreateTypeLib_FWD_DEFINED__
+typedef interface ICreateTypeLib ICreateTypeLib;
+#endif /* __ICreateTypeLib_FWD_DEFINED__ */
+
+
+#ifndef __IDispatch_FWD_DEFINED__
+#define __IDispatch_FWD_DEFINED__
+typedef interface IDispatch IDispatch;
+#endif /* __IDispatch_FWD_DEFINED__ */
+
+
+#ifndef __IEnumVARIANT_FWD_DEFINED__
+#define __IEnumVARIANT_FWD_DEFINED__
+typedef interface IEnumVARIANT IEnumVARIANT;
+#endif /* __IEnumVARIANT_FWD_DEFINED__ */
+
+
+#ifndef __ITypeComp_FWD_DEFINED__
+#define __ITypeComp_FWD_DEFINED__
+typedef interface ITypeComp ITypeComp;
+#endif /* __ITypeComp_FWD_DEFINED__ */
+
+
+#ifndef __ITypeInfo_FWD_DEFINED__
+#define __ITypeInfo_FWD_DEFINED__
+typedef interface ITypeInfo ITypeInfo;
+#endif /* __ITypeInfo_FWD_DEFINED__ */
+
+
+#ifndef __ITypeLib_FWD_DEFINED__
+#define __ITypeLib_FWD_DEFINED__
+typedef interface ITypeLib ITypeLib;
+#endif /* __ITypeLib_FWD_DEFINED__ */
+
+
+#ifndef __IErrorInfo_FWD_DEFINED__
+#define __IErrorInfo_FWD_DEFINED__
+typedef interface IErrorInfo IErrorInfo;
+#endif /* __IErrorInfo_FWD_DEFINED__ */
+
+
+#ifndef __ICreateErrorInfo_FWD_DEFINED__
+#define __ICreateErrorInfo_FWD_DEFINED__
+typedef interface ICreateErrorInfo ICreateErrorInfo;
+#endif /* __ICreateErrorInfo_FWD_DEFINED__ */
+
+
+#ifndef __ISupportErrorInfo_FWD_DEFINED__
+#define __ISupportErrorInfo_FWD_DEFINED__
+typedef interface ISupportErrorInfo ISupportErrorInfo;
+#endif /* __ISupportErrorInfo_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#ifndef __objidl_h__
+#include "objidl.h"
+#endif /* __objidl_h__ */
+
+void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
+void __RPC_USER MIDL_user_free( void __RPC_FAR * );
+
+/****************************************
+ * Generated header for interface: __MIDL__intf_0000
+ * at Fri Apr 28 07:02:38 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [local] */
+
+
+ /* size is 0 */
+
+ /* size is 0 */
+
+ /* size is 0 */
+
+ /* size is 0 */
+
+ /* size is 0 */
+
+
+#ifndef NORPC
+extern RPC_IF_HANDLE __MIDL__intf_0000_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL__intf_0000_v0_0_s_ifspec;
+#endif //NORPC
+
+#ifndef __RemVariant_INTERFACE_DEFINED__
+#define __RemVariant_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: RemVariant
+ * at Fri Apr 28 07:02:38 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [local][unique][version] */
+
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+//--------------------------------------------------------------------------
+/* XBSTR is for internal use only, it is subject to change */
+ /* size is 4 */
+typedef struct tagXBSTR
+ {
+ ULONG cbSize;
+ /* [size_is] */ OLECHAR rgBstrData[ 1 ];
+ } XBSTR;
+
+ /* size is 4 */
+typedef OLECHAR __RPC_FAR *BSTR;
+
+ /* size is 4 */
+typedef BSTR __RPC_FAR *LPBSTR;
+
+#ifndef _tagBLOB_DEFINED
+#define _tagBLOB_DEFINED
+#define _BLOB_DEFINED
+#define _LPBLOB_DEFINED
+ /* size is 8 */
+typedef struct tagBLOB
+ {
+ ULONG cbSize;
+ /* [size_is] */ BYTE __RPC_FAR *pBlobData;
+ } BLOB;
+
+ /* size is 4 */
+typedef struct tagBLOB __RPC_FAR *LPBLOB;
+
+#endif
+#ifndef _tagCLIPDATA_DEFINED
+#define _tagCLIPDATA_DEFINED
+#define _CLIPDATA_DEFINED
+ /* size is 12 */
+typedef struct tagCLIPDATA
+ {
+ ULONG cbSize;
+ long ulClipFmt;
+ /* [size_is] */ BYTE __RPC_FAR *pClipData;
+ } CLIPDATA;
+
+#endif
+#ifndef _tagSAFEARRAYBOUND_DEFINED
+#define _tagSAFEARRAYBOUND_DEFINED
+#define _SAFEARRAYBOUND_DEFINED
+#define _LPSAFEARRAYBOUND_DEFINED
+ /* size is 8 */
+typedef struct tagSAFEARRAYBOUND
+ {
+ ULONG cElements;
+ LONG lLbound;
+ } SAFEARRAYBOUND;
+
+ /* size is 4 */
+typedef struct tagSAFEARRAYBOUND __RPC_FAR *LPSAFEARRAYBOUND;
+
+#endif
+#ifndef _tagSAFEARRAY_DEFINED
+#define _tagSAFEARRAY_DEFINED
+#define _SAFEARRAY_DEFINED
+#define _LPSAFEARRAY_DEFINED
+#if 0
+/* the following is what RPC knows how to remote */
+ /* size is 16 */
+typedef struct tagSAFEARRAY
+ {
+ unsigned short cDims;
+ unsigned short fFeatures;
+ unsigned long cbElements;
+ unsigned long cLocks;
+ BYTE __RPC_FAR *pvData;
+ /* [size_is] */ SAFEARRAYBOUND rgsabound[ 1 ];
+ } SAFEARRAY;
+
+ /* size is 4 */
+typedef struct tagSAFEARRAY __RPC_FAR *LPSAFEARRAY;
+
+#else
+typedef struct FARSTRUCT tagSAFEARRAY {
+ unsigned short cDims;
+ unsigned short fFeatures;
+#if defined(_WIN32)
+ unsigned long cbElements;
+ unsigned long cLocks;
+#else
+ unsigned short cbElements;
+ unsigned short cLocks;
+ unsigned long handle; // unused but kept for compatiblity
+#endif
+ void HUGEP* pvData;
+ SAFEARRAYBOUND rgsabound[1];
+} SAFEARRAY, FAR* LPSAFEARRAY;
+#endif
+#endif
+ /* size is 2 */
+#define FADF_AUTO ( 0x1 )
+
+ /* size is 2 */
+#define FADF_STATIC ( 0x2 )
+
+ /* size is 2 */
+#define FADF_EMBEDDED ( 0x4 )
+
+ /* size is 2 */
+#define FADF_FIXEDSIZE ( 0x10 )
+
+ /* size is 2 */
+#define FADF_BSTR ( 0x100 )
+
+ /* size is 2 */
+#define FADF_UNKNOWN ( 0x200 )
+
+ /* size is 2 */
+#define FADF_DISPATCH ( 0x400 )
+
+ /* size is 2 */
+#define FADF_VARIANT ( 0x800 )
+
+ /* size is 2 */
+#define FADF_RESERVED ( 0xf0e8 )
+
+ /* size is 8 */
+typedef double DATE;
+
+#ifndef _tagCY_DEFINED
+#define _tagCY_DEFINED
+#define _CY_DEFINED
+#if 0
+/* the following isn't the real definition of CY, but it is */
+/* what RPC knows how to remote */
+ /* size is 8 */
+typedef struct tagCY
+ {
+ LONGLONG int64;
+ } CY;
+
+#else
+/* real definition that makes the C++ compiler happy */
+typedef union tagCY {
+ struct {
+#ifdef _MAC
+ long Hi;
+ long Lo;
+#else
+ unsigned long Lo;
+ long Hi;
+#endif
+ };
+ LONGLONG int64;
+} CY;
+#endif
+#endif
+ /* size is 8 */
+typedef CY CURRENCY;
+
+/* 0 == FALSE, -1 == TRUE */
+ /* size is 2 */
+typedef short VARIANT_BOOL;
+
+#ifndef VARIANT_TRUE
+#define VARIANT_TRUE ((VARIANT_BOOL)0xffff)
+#endif
+#ifndef VARIANT_FALSE
+#define VARIANT_FALSE ((VARIANT_BOOL)0)
+#endif
+#ifndef _VARENUM_DEFINED
+#define _VARENUM_DEFINED
+/*
+ * VARENUM usage key,
+ *
+ * * [V] - may appear in a VARIANT
+ * * [T] - may appear in a TYPEDESC
+ * * [P] - may appear in an OLE property set
+ * * [S] - may appear in a Safe Array
+ *
+ *
+ * VT_EMPTY [V] [P] nothing
+ * VT_NULL [V] SQL style Null
+ * VT_I2 [V][T][P][S] 2 byte signed int
+ * VT_I4 [V][T][P][S] 4 byte signed int
+ * VT_R4 [V][T][P][S] 4 byte real
+ * VT_R8 [V][T][P][S] 8 byte real
+ * VT_CY [V][T][P][S] currency
+ * VT_DATE [V][T][P][S] date
+ * VT_BSTR [V][T][P][S] OLE Automation string
+ * VT_DISPATCH [V][T] [S] IDispatch FAR*
+ * VT_ERROR [V][T] [S] SCODE
+ * VT_BOOL [V][T][P][S] True=-1, False=0
+ * VT_VARIANT [V][T][P][S] VARIANT FAR*
+ * VT_UNKNOWN [V][T] [S] IUnknown FAR*
+ * VT_I1 [T] signed char
+ * VT_UI1 [V][T] [S] unsigned char
+ * VT_UI2 [T] unsigned short
+ * VT_UI4 [T] unsigned short
+ * VT_I8 [T][P] signed 64-bit int
+ * VT_UI8 [T] unsigned 64-bit int
+ * VT_INT [T] signed machine int
+ * VT_UINT [T] unsigned machine int
+ * VT_VOID [T] C style void
+ * VT_HRESULT [T]
+ * VT_PTR [T] pointer type
+ * VT_SAFEARRAY [T] (use VT_ARRAY in VARIANT)
+ * VT_CARRAY [T] C style array
+ * VT_USERDEFINED [T] user defined type
+ * VT_LPSTR [T][P] null terminated string
+ * VT_LPWSTR [T][P] wide null terminated string
+ * VT_FILETIME [P] FILETIME
+ * VT_BLOB [P] Length prefixed bytes
+ * VT_STREAM [P] Name of the stream follows
+ * VT_STORAGE [P] Name of the storage follows
+ * VT_STREAMED_OBJECT [P] Stream contains an object
+ * VT_STORED_OBJECT [P] Storage contains an object
+ * VT_BLOB_OBJECT [P] Blob contains an object
+ * VT_CF [P] Clipboard format
+ * VT_CLSID [P] A Class ID
+ * VT_VECTOR [P] simple counted array
+ * VT_ARRAY [V] SAFEARRAY*
+ * VT_BYREF [V]
+ */
+ /* size is 2 */
+
+enum VARENUM
+ { VT_EMPTY = 0,
+ VT_NULL = 1,
+ VT_I2 = 2,
+ VT_I4 = 3,
+ VT_R4 = 4,
+ VT_R8 = 5,
+ VT_CY = 6,
+ VT_DATE = 7,
+ VT_BSTR = 8,
+ VT_DISPATCH = 9,
+ VT_ERROR = 10,
+ VT_BOOL = 11,
+ VT_VARIANT = 12,
+ VT_UNKNOWN = 13,
+ VT_I1 = 16,
+ VT_UI1 = 17,
+ VT_UI2 = 18,
+ VT_UI4 = 19,
+ VT_I8 = 20,
+ VT_UI8 = 21,
+ VT_INT = 22,
+ VT_UINT = 23,
+ VT_VOID = 24,
+ VT_HRESULT = 25,
+ VT_PTR = 26,
+ VT_SAFEARRAY = 27,
+ VT_CARRAY = 28,
+ VT_USERDEFINED = 29,
+ VT_LPSTR = 30,
+ VT_LPWSTR = 31,
+ VT_FILETIME = 64,
+ VT_BLOB = 65,
+ VT_STREAM = 66,
+ VT_STORAGE = 67,
+ VT_STREAMED_OBJECT = 68,
+ VT_STORED_OBJECT = 69,
+ VT_BLOB_OBJECT = 70,
+ VT_CF = 71,
+ VT_CLSID = 72
+ };
+#endif
+ /* size is 2 */
+#define VT_VECTOR ( 0x1000 )
+
+ /* size is 2 */
+#define VT_ARRAY ( 0x2000 )
+
+ /* size is 2 */
+#define VT_BYREF ( 0x4000 )
+
+ /* size is 2 */
+#define VT_RESERVED ( 0x8000 )
+
+#ifndef _VARTYPE_DEFINED
+#define _VARTYPE_DEFINED
+ /* size is 2 */
+typedef unsigned short VARTYPE;
+
+#endif
+ /* size is 0 */
+typedef struct tagVARIANT VARIANT;
+
+/* forward declare IDispatch */
+typedef interface IDispatch IDispatch;
+/* VARIANT STRUCTURE
+ *
+ * VARTYPE vt;
+ * unsigned short wReserved1;
+ * unsigned short wReserved2;
+ * unsigned short wReserved3;
+ * union {
+ * unsigned char VT_UI1
+ * short VT_I2
+ * long VT_I4
+ * float VT_R4
+ * double VT_R8
+ * VARIANT_BOOL VT_BOOL
+ * SCODE VT_ERROR
+ * CY VT_CY
+ * DATE VT_DATE
+ * BSTR VT_BSTR
+ * IUnknown FAR* VT_UNKNOWN
+ * IDispatch FAR* VT_DISPATCH
+ * SAFEARRAY FAR* VT_ARRAY|*
+ * short FAR* VT_BYREF|VT_I2
+ * long FAR* VT_BYREF|VT_I4
+ * float FAR* VT_BYREF|VT_R4
+ * double FAR* VT_BYREF|VT_R8
+ * VARIANT_BOOL FAR* VT_BYREF|VT_BOOL
+ * SCODE FAR* VT_BYREF|VT_ERROR
+ * CY FAR* VT_BYREF|VT_CY
+ * DATE FAR* VT_BYREF|VT_DATE
+ * BSTR FAR* VT_BYREF|VT_BSTR
+ * IUnknown FAR* FAR* VT_BYREF|VT_UNKNOWN
+ * IDispatch FAR* FAR* VT_BYREF|VT_DISPATCH
+ * SAFEARRAY FAR* FAR* VT_BYREF|VT_ARRAY|*
+ * VARIANT FAR* VT_BYREF|VT_VARIANT
+ * void FAR* Generic ByRef
+ */
+#ifndef _tagVARIANT_DEFINED
+#define _tagVARIANT_DEFINED
+#if 0
+/* the following is what RPC knows how to remote */
+ /* size is 16 */
+struct tagVARIANT
+ {
+ VARTYPE vt;
+ WORD wReserved1;
+ WORD wReserved2;
+ WORD wReserved3;
+ /* [switch_is][switch_type] */ union
+ {
+ /* [case] */ long lVal;
+ /* [case] */ unsigned char bVal;
+ /* [case] */ short iVal;
+ /* [case] */ float fltVal;
+ /* [case] */ double dblVal;
+ /* [case] */ VARIANT_BOOL bool;
+ /* [case] */ SCODE scode;
+ /* [case] */ CY cyVal;
+ /* [case] */ DATE date;
+ /* [case] */ BSTR bstrVal;
+ /* [case] */ IUnknown __RPC_FAR *punkVal;
+ /* [case] */ SAFEARRAY __RPC_FAR *parray;
+ /* [case] */ unsigned char __RPC_FAR *pbVal;
+ /* [case] */ short __RPC_FAR *piVal;
+ /* [case] */ long __RPC_FAR *plVal;
+ /* [case] */ float __RPC_FAR *pfltVal;
+ /* [case] */ double __RPC_FAR *pdblVal;
+ /* [case] */ VARIANT_BOOL __RPC_FAR *pbool;
+ /* [case] */ SCODE __RPC_FAR *pscode;
+ /* [case] */ CY __RPC_FAR *pcyVal;
+ /* [case] */ DATE __RPC_FAR *pdate;
+ /* [case] */ BSTR __RPC_FAR *pbstrVal;
+ /* [case] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkVal;
+ /* [case] */ SAFEARRAY __RPC_FAR *__RPC_FAR *pparray;
+ /* [case] */ VARIANT __RPC_FAR *pvarVal;
+ /* [case] */ long __RPC_FAR *byref;
+ } ;
+ };
+#endif
+struct tagVARIANT{
+ VARTYPE vt;
+ WORD wReserved1;
+ WORD wReserved2;
+ WORD wReserved3;
+ union
+ {
+ long lVal; /* VT_I4 */
+ unsigned char bVal; /* VT_UI1 */
+ short iVal; /* VT_I2 */
+ float fltVal; /* VT_R4 */
+ double dblVal; /* VT_R8 */
+ VARIANT_BOOL bool; /* VT_BOOL */
+ SCODE scode; /* VT_ERROR */
+ CY cyVal; /* VT_CY */
+ DATE date; /* VT_DATE */
+ BSTR bstrVal; /* VT_BSTR */
+ IUnknown *punkVal; /* VT_UNKNOWN */
+ IDispatch *pdispVal; /* VT_DISPATCH */
+ SAFEARRAY *parray; /* VT_ARRAY|* */
+ unsigned char *pbVal; /* VT_BYREF|VT_UI1 */
+ short *piVal; /* VT_BYREF|VT_I2 */
+ long *plVal; /* VT_BYREF|VT_I4 */
+ float *pfltVal; /* VT_BYREF|VT_R4 */
+ double *pdblVal; /* VT_BYREF|VT_R8 */
+ VARIANT_BOOL *pbool; /* VT_BYREF|VT_BOOL */
+ SCODE *pscode; /* VT_BYREF|VT_ERROR */
+ CY *pcyVal; /* VT_BYREF|VT_CY */
+ DATE *pdate; /* VT_BYREF|VT_DATE */
+ BSTR *pbstrVal; /* VT_BYREF|VT_BSTR */
+ IUnknown **ppunkVal; /* VT_BYREF|VT_UNKNOWN */
+ IDispatch **ppdispVal; /* VT_BYREF|VT_DISPATCH */
+ SAFEARRAY **pparray; /* VT_BYREF|VT_ARRAY|* */
+ VARIANT *pvarVal; /* VT_BYREF|VT_VARIANT */
+ void * byref; /* Generic ByRef */
+ }
+#if(defined(NONAMELESSUNION))
+ u
+#endif
+ ;
+};
+#endif
+#ifndef _LPVARIANT_DEFINED
+#define _LPVARIANT_DEFINED
+ /* size is 4 */
+typedef struct tagVARIANT __RPC_FAR *LPVARIANT;
+
+#endif
+#ifndef _VARIANTARG_DEFINED
+#define _VARIANTARG_DEFINED
+ /* size is 16 */
+typedef struct tagVARIANT VARIANTARG;
+
+#endif
+#ifndef _LPVARIANTARG_DEFINED
+#define _LPVARIANTARG_DEFINED
+ /* size is 4 */
+typedef struct tagVARIANT __RPC_FAR *LPVARIANTARG;
+
+#endif
+#ifndef _DISPID_DEFINED
+#define _DISPID_DEFINED
+ /* size is 4 */
+typedef LONG DISPID;
+
+#endif
+#ifndef _MEMBERID_DEFINED
+#define _MEMBERID_DEFINED
+ /* size is 4 */
+typedef DISPID MEMBERID;
+
+#endif
+#ifndef _HREFTYPE_DEFINED
+#define _HREFTYPE_DEFINED
+ /* size is 4 */
+typedef DWORD HREFTYPE;
+
+#endif
+ /* size is 4 */
+typedef ULONG PROPID;
+
+ /* size is 2 */
+typedef /* [transmit] */
+enum tagTYPEKIND
+ { TKIND_ENUM = 0,
+ TKIND_RECORD = TKIND_ENUM + 1,
+ TKIND_MODULE = TKIND_RECORD + 1,
+ TKIND_INTERFACE = TKIND_MODULE + 1,
+ TKIND_DISPATCH = TKIND_INTERFACE + 1,
+ TKIND_COCLASS = TKIND_DISPATCH + 1,
+ TKIND_ALIAS = TKIND_COCLASS + 1,
+ TKIND_UNION = TKIND_ALIAS + 1,
+ TKIND_MAX = TKIND_UNION + 1
+ } TYPEKIND;
+
+#define TYPEKIND_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)
+#define TYPEKIND_from_xmit(pLong, pEnum) *(pEnum) = (TYPEKIND) *(pLong)
+#define TYPEKIND_free_inst(pEnum)
+#define TYPEKIND_free_xmit(pLong)
+#ifndef _tagTYPEDESC_DEFINED
+#define _tagTYPEDESC_DEFINED
+#define _TYPEDESC_DEFINED
+/* VT_PTR - lptdesc, the pointed at type */
+/* VT_CARRAY - lpadesc */
+/* VT_USERDEFINED - hreftype, used to get the UDT typeinfo */
+ /* size is 6 */
+typedef struct tagTYPEDESC
+ {
+ /* [switch_is][switch_type] */ union
+ {
+ /* [case] */ struct tagTYPEDESC __RPC_FAR *lptdesc;
+ /* [case] */ struct tagARRAYDESC __RPC_FAR *lpadesc;
+ /* [case] */ HREFTYPE hreftype;
+ } ;
+ VARTYPE vt;
+ } TYPEDESC;
+
+#endif
+#ifndef _tagARRAYDESC_DEFINED
+#define _tagARRAYDESC_DEFINED
+#define _ARRAYDESC_DEFINED
+#if 0
+ /* size is 8 */
+typedef struct tagARRAYDESC
+ {
+ TYPEDESC tdescElem;
+ USHORT cDims;
+ /* [size_is] */ SAFEARRAYBOUND rgbounds[ 1 ];
+ } ARRAYDESC;
+
+#else
+typedef struct tagARRAYDESC {
+ TYPEDESC tdescElem; /* element type */
+ USHORT cDims; /* dimension count */
+ SAFEARRAYBOUND rgbounds[1]; /* variable length array of bounds */
+} ARRAYDESC;
+#endif
+#endif
+#ifndef _tagIDLDESC_DEFINED
+#define _tagIDLDESC_DEFINED
+#define _IDLDESC_DEFINED
+#define _LPIDLDESC_DEFINED
+#ifdef _WIN32
+ /* size is 6 */
+typedef struct tagIDLDESC
+ {
+ unsigned long dwReserved;
+ unsigned short wIDLFlags;
+ } IDLDESC;
+
+ /* size is 4 */
+typedef struct tagIDLDESC __RPC_FAR *LPIDLDESC;
+
+#else
+typedef struct FARSTRUCT tagIDLDESC {
+#if defined(_WIN32)
+ unsigned long dwReserved;
+#else
+ BSTR bstrIDLInfo; /* reserved, but original name retained for
+ compatibilty */
+#endif
+ unsigned short wIDLFlags; /* IN, OUT, etc */
+} IDLDESC, FAR* LPIDLDESC;
+#endif
+#endif
+#ifndef _tagELEMDESC_DEFINED
+#define _tagELEMDESC_DEFINED
+#define _ELEMDESC_DEFINED
+#define _LPELEMDESC_DEFINED
+ /* size is 14 */
+typedef struct tagELEMDESC
+ {
+ TYPEDESC tdesc;
+ IDLDESC idldesc;
+ } ELEMDESC;
+
+ /* size is 4 */
+typedef struct tagELEMDESC __RPC_FAR *LPELEMDESC;
+
+#endif
+#ifndef _tagTYPEATTR_DEFINED
+#define _tagTYPEATTR_DEFINED
+#define _TYPEATTR_DEFINED
+#define _LPTYPEATTR_DEFINED
+ /* size is 74 */
+typedef struct tagTYPEATTR
+ {
+ GUID guid;
+ LCID lcid;
+ DWORD dwReserved;
+ MEMBERID memidConstructor;
+ MEMBERID memidDestructor;
+ LPOLESTR lpstrSchema;
+ ULONG cbSizeInstance;
+ TYPEKIND typekind;
+ WORD cFuncs;
+ WORD cVars;
+ WORD cImplTypes;
+ WORD cbSizeVft;
+ WORD cbAlignment;
+ WORD wTypeFlags;
+ WORD wMajorVerNum;
+ WORD wMinorVerNum;
+ TYPEDESC tdescAlias;
+ IDLDESC idldescType;
+ } TYPEATTR;
+
+ /* size is 4 */
+typedef struct tagTYPEATTR __RPC_FAR *LPTYPEATTR;
+
+#endif
+ /* size is 16 */
+typedef struct tagDISPPARAMS
+ {
+ /* [size_is] */ VARIANTARG __RPC_FAR *rgvarg;
+ /* [size_is] */ DISPID __RPC_FAR *rgdispidNamedArgs;
+ UINT cArgs;
+ UINT cNamedArgs;
+ } DISPPARAMS;
+
+ /* size is 24 */
+typedef struct tagRemEXCEPINFO
+ {
+ WORD wCode;
+ WORD wReserved;
+ DWORD dwHelpContext;
+ DWORD scode;
+ DWORD cSource;
+ DWORD cDescription;
+ DWORD cHelpFile;
+ /* [size_is] */ OLECHAR strings[ 1 ];
+ } RemEXCEPINFO;
+
+#if 0
+ /* size is 32 */
+typedef /* [transmit] */ struct tagEXCEPINFO
+ {
+ WORD wCode;
+ WORD wReserved;
+ BSTR bstrSource;
+ BSTR bstrDescription;
+ BSTR bstrHelpFile;
+ DWORD dwHelpContext;
+ /* [unique] */ void __RPC_FAR *pvReserved;
+ HRESULT ( __stdcall __RPC_FAR *pfnDeferredFillIn )(
+ struct tagEXCEPINFO __RPC_FAR *__MIDL_0004);
+ SCODE scode;
+ } EXCEPINFO;
+
+ /* size is 4 */
+typedef /* [transmit] */ struct tagEXCEPINFO __RPC_FAR *LPEXCEPINFO;
+
+#else
+typedef struct tagEXCEPINFO {
+ WORD wCode;
+ WORD wReserved;
+ BSTR bstrSource;
+ BSTR bstrDescription;
+ BSTR bstrHelpFile;
+ DWORD dwHelpContext;
+ void __RPC_FAR * pvReserved;
+ HRESULT (__stdcall __RPC_FAR * pfnDeferredFillIn)(struct tagEXCEPINFO __RPC_FAR *);
+ SCODE scode;
+} EXCEPINFO, __RPC_FAR * LPEXCEPINFO;
+#endif
+ /* size is 2 */
+typedef /* [transmit] */
+enum tagCALLCONV
+ { CC_CDECL = 1,
+ CC_MSCPASCAL = CC_CDECL + 1,
+ CC_PASCAL = CC_MSCPASCAL,
+ CC_MACPASCAL = CC_PASCAL + 1,
+ CC_STDCALL = CC_MACPASCAL + 1,
+ CC_RESERVED = CC_STDCALL + 1,
+ CC_SYSCALL = CC_RESERVED + 1,
+ CC_MPWCDECL = CC_SYSCALL + 1,
+ CC_MPWPASCAL = CC_MPWCDECL + 1,
+ CC_MAX = CC_MPWPASCAL + 1
+ } CALLCONV;
+
+#define CALLCONV_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)
+#define CALLCONV_from_xmit(pLong, pEnum) *(pEnum) = (CALLCONV) *(pLong)
+#define CALLCONV_free_inst(pEnum)
+#define CALLCONV_free_xmit(pLong)
+ /* size is 2 */
+typedef /* [transmit] */
+enum tagFUNCKIND
+ { FUNC_VIRTUAL = 0,
+ FUNC_PUREVIRTUAL = FUNC_VIRTUAL + 1,
+ FUNC_NONVIRTUAL = FUNC_PUREVIRTUAL + 1,
+ FUNC_STATIC = FUNC_NONVIRTUAL + 1,
+ FUNC_DISPATCH = FUNC_STATIC + 1
+ } FUNCKIND;
+
+#define FUNCKIND_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)
+#define FUNCKIND_from_xmit(pLong, pEnum) *(pEnum) = (FUNCKIND) *(pLong)
+#define FUNCKIND_free_inst(pEnum)
+#define FUNCKIND_free_xmit(pLong)
+ /* size is 2 */
+typedef /* [transmit] */
+enum tagINVOKEKIND
+ { INVOKE_FUNC = 1,
+ INVOKE_PROPERTYGET = 2,
+ INVOKE_PROPERTYPUT = 4,
+ INVOKE_PROPERTYPUTREF = 8
+ } INVOKEKIND;
+
+#define INVOKEKIND_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)
+#define INVOKEKIND_from_xmit(pLong, pEnum) *(pEnum) = (INVOKEKIND) *(pLong)
+#define INVOKEKIND_free_inst(pEnum)
+#define INVOKEKIND_free_xmit(pLong)
+ /* size is 44 */
+typedef struct tagFUNCDESC
+ {
+ MEMBERID memid;
+ /* [size_is] */ SCODE __RPC_FAR *lprgscode;
+ /* [size_is] */ ELEMDESC __RPC_FAR *lprgelemdescParam;
+ FUNCKIND funckind;
+ INVOKEKIND invkind;
+ CALLCONV callconv;
+ SHORT cParams;
+ SHORT cParamsOpt;
+ SHORT oVft;
+ SHORT cScodes;
+ ELEMDESC elemdescFunc;
+ WORD wFuncFlags;
+ } FUNCDESC;
+
+ /* size is 4 */
+typedef struct tagFUNCDESC __RPC_FAR *LPFUNCDESC;
+
+ /* size is 2 */
+typedef /* [transmit] */
+enum tagVARKIND
+ { VAR_PERINSTANCE = 0,
+ VAR_STATIC = VAR_PERINSTANCE + 1,
+ VAR_CONST = VAR_STATIC + 1,
+ VAR_DISPATCH = VAR_CONST + 1
+ } VARKIND;
+
+#define VARKIND_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)
+#define VARKIND_from_xmit(pLong, pEnum) *(pEnum) = (VARKIND) *(pLong)
+#define VARKIND_free_inst(pEnum)
+#define VARKIND_free_xmit(pLong)
+ /* size is 2 */
+#define IMPLTYPEFLAG_FDEFAULT ( 0x1 )
+
+ /* size is 2 */
+#define IMPLTYPEFLAG_FSOURCE ( 0x2 )
+
+ /* size is 2 */
+#define IMPLTYPEFLAG_FRESTRICTED ( 0x4 )
+
+ /* size is 30 */
+typedef struct tagVARDESC
+ {
+ MEMBERID memid;
+ LPOLESTR lpstrSchema;
+ /* [switch_is][switch_type] */ union
+ {
+ /* [case] */ ULONG oInst;
+ /* [case] */ VARIANT __RPC_FAR *lpvarValue;
+ } ;
+ ELEMDESC elemdescVar;
+ WORD wVarFlags;
+ VARKIND varkind;
+ } VARDESC;
+
+ /* size is 4 */
+typedef struct tagVARDESC __RPC_FAR *LPVARDESC;
+
+#ifndef _tagTYPEFLAGS_DEFINED
+#define _tagTYPEFLAGS_DEFINED
+#define _TYPEFLAGS_DEFINED
+ /* size is 2 */
+typedef
+enum tagTYPEFLAGS
+ { TYPEFLAG_FAPPOBJECT = 0x1,
+ TYPEFLAG_FCANCREATE = 0x2,
+ TYPEFLAG_FLICENSED = 0x4,
+ TYPEFLAG_FPREDECLID = 0x8,
+ TYPEFLAG_FHIDDEN = 0x10,
+ TYPEFLAG_FCONTROL = 0x20,
+ TYPEFLAG_FDUAL = 0x40,
+ TYPEFLAG_FNONEXTENSIBLE = 0x80,
+ TYPEFLAG_FOLEAUTOMATION = 0x100,
+ TYPEFLAG_FRESTRICTED = 0x200
+ } TYPEFLAGS;
+
+#endif
+#ifndef _tagFUNCFLAGS_DEFINED
+#define _tagFUNCFLAGS_DEFINED
+#define _FUNCFLAGS_DEFINED
+ /* size is 2 */
+typedef
+enum tagFUNCFLAGS
+ { FUNCFLAG_FRESTRICTED = 1,
+ FUNCFLAG_FSOURCE = 0x2,
+ FUNCFLAG_FBINDABLE = 0x4,
+ FUNCFLAG_FREQUESTEDIT = 0x8,
+ FUNCFLAG_FDISPLAYBIND = 0x10,
+ FUNCFLAG_FDEFAULTBIND = 0x20,
+ FUNCFLAG_FHIDDEN = 0x40,
+ FUNCFLAG_FUSESGETLASTERROR = 0x80
+ } FUNCFLAGS;
+
+#endif
+#ifndef _tagVARFLAGS_DEFINED
+#define _tagVARFLAGS_DEFINED
+#define _VARFLAGS_DEFINED
+ /* size is 2 */
+typedef
+enum tagVARFLAGS
+ { VARFLAG_FREADONLY = 1,
+ VARFLAG_FSOURCE = 0x2,
+ VARFLAG_FBINDABLE = 0x4,
+ VARFLAG_FREQUESTEDIT = 0x8,
+ VARFLAG_FDISPLAYBIND = 0x10,
+ VARFLAG_FDEFAULTBIND = 0x20,
+ VARFLAG_FHIDDEN = 0x40
+ } VARFLAGS;
+
+#endif
+
+#ifndef NORPC
+extern RPC_IF_HANDLE RemVariant_v0_1_c_ifspec;
+extern RPC_IF_HANDLE RemVariant_v0_1_s_ifspec;
+#endif // NORPC
+#endif /* __RemVariant_INTERFACE_DEFINED__ */
+
+#ifndef __ICreateTypeInfo_INTERFACE_DEFINED__
+#define __ICreateTypeInfo_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: ICreateTypeInfo
+ * at Fri Apr 28 07:02:38 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [local][unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ ICreateTypeInfo __RPC_FAR *LPCREATETYPEINFO;
+
+
+EXTERN_C const IID IID_ICreateTypeInfo;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface ICreateTypeInfo : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall SetGuid(
+ /* [in] */ REFGUID guid) = 0;
+
+ virtual HRESULT __stdcall SetTypeFlags(
+ /* [in] */ UINT uTypeFlags) = 0;
+
+ virtual HRESULT __stdcall SetDocString(
+ /* [in] */ LPOLESTR lpstrDoc) = 0;
+
+ virtual HRESULT __stdcall SetHelpContext(
+ /* [in] */ DWORD dwHelpContext) = 0;
+
+ virtual HRESULT __stdcall SetVersion(
+ /* [in] */ WORD wMajorVerNum,
+ /* [in] */ WORD wMinorVerNum) = 0;
+
+ virtual HRESULT __stdcall AddRefTypeInfo(
+ /* [in] */ ITypeInfo __RPC_FAR *ptinfo,
+ /* [in] */ HREFTYPE __RPC_FAR *phreftype) = 0;
+
+ virtual HRESULT __stdcall AddFuncDesc(
+ /* [in] */ UINT index,
+ /* [in] */ FUNCDESC __RPC_FAR *pfuncdesc) = 0;
+
+ virtual HRESULT __stdcall AddImplType(
+ /* [in] */ UINT index,
+ /* [in] */ HREFTYPE hreftype) = 0;
+
+ virtual HRESULT __stdcall SetImplTypeFlags(
+ /* [in] */ UINT index,
+ /* [in] */ INT impltypeflags) = 0;
+
+ virtual HRESULT __stdcall SetAlignment(
+ /* [in] */ WORD cbAlignment) = 0;
+
+ virtual HRESULT __stdcall SetSchema(
+ /* [in] */ LPOLESTR lpstrSchema) = 0;
+
+ virtual HRESULT __stdcall AddVarDesc(
+ /* [in] */ UINT index,
+ /* [in] */ VARDESC __RPC_FAR *pvardesc) = 0;
+
+ virtual HRESULT __stdcall SetFuncAndParamNames(
+ /* [in] */ UINT index,
+ /* [in][size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
+ /* [in] */ UINT cNames) = 0;
+
+ virtual HRESULT __stdcall SetVarName(
+ /* [in] */ UINT index,
+ /* [in] */ LPOLESTR szName) = 0;
+
+ virtual HRESULT __stdcall SetTypeDescAlias(
+ /* [in] */ TYPEDESC __RPC_FAR *ptdescAlias) = 0;
+
+ virtual HRESULT __stdcall DefineFuncAsDllEntry(
+ /* [in] */ UINT index,
+ /* [in] */ LPOLESTR szDllName,
+ /* [in] */ LPOLESTR szProcName) = 0;
+
+ virtual HRESULT __stdcall SetFuncDocString(
+ /* [in] */ UINT index,
+ /* [in] */ LPOLESTR szDocString) = 0;
+
+ virtual HRESULT __stdcall SetVarDocString(
+ /* [in] */ UINT index,
+ /* [in] */ LPOLESTR szDocString) = 0;
+
+ virtual HRESULT __stdcall SetFuncHelpContext(
+ /* [in] */ UINT index,
+ /* [in] */ DWORD dwHelpContext) = 0;
+
+ virtual HRESULT __stdcall SetVarHelpContext(
+ /* [in] */ UINT index,
+ /* [in] */ DWORD dwHelpContext) = 0;
+
+ virtual HRESULT __stdcall SetMops(
+ /* [in] */ UINT index,
+ /* [in] */ BSTR bstrMops) = 0;
+
+ virtual HRESULT __stdcall SetTypeIdldesc(
+ /* [in] */ IDLDESC __RPC_FAR *pidldesc) = 0;
+
+ virtual HRESULT __stdcall LayOut( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ICreateTypeInfoVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ ICreateTypeInfo __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ ICreateTypeInfo __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *SetGuid )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ REFGUID guid);
+
+ HRESULT ( __stdcall __RPC_FAR *SetTypeFlags )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT uTypeFlags);
+
+ HRESULT ( __stdcall __RPC_FAR *SetDocString )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ LPOLESTR lpstrDoc);
+
+ HRESULT ( __stdcall __RPC_FAR *SetHelpContext )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ DWORD dwHelpContext);
+
+ HRESULT ( __stdcall __RPC_FAR *SetVersion )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ WORD wMajorVerNum,
+ /* [in] */ WORD wMinorVerNum);
+
+ HRESULT ( __stdcall __RPC_FAR *AddRefTypeInfo )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ ITypeInfo __RPC_FAR *ptinfo,
+ /* [in] */ HREFTYPE __RPC_FAR *phreftype);
+
+ HRESULT ( __stdcall __RPC_FAR *AddFuncDesc )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ FUNCDESC __RPC_FAR *pfuncdesc);
+
+ HRESULT ( __stdcall __RPC_FAR *AddImplType )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ HREFTYPE hreftype);
+
+ HRESULT ( __stdcall __RPC_FAR *SetImplTypeFlags )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ INT impltypeflags);
+
+ HRESULT ( __stdcall __RPC_FAR *SetAlignment )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ WORD cbAlignment);
+
+ HRESULT ( __stdcall __RPC_FAR *SetSchema )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ LPOLESTR lpstrSchema);
+
+ HRESULT ( __stdcall __RPC_FAR *AddVarDesc )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ VARDESC __RPC_FAR *pvardesc);
+
+ HRESULT ( __stdcall __RPC_FAR *SetFuncAndParamNames )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in][size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
+ /* [in] */ UINT cNames);
+
+ HRESULT ( __stdcall __RPC_FAR *SetVarName )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ LPOLESTR szName);
+
+ HRESULT ( __stdcall __RPC_FAR *SetTypeDescAlias )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ TYPEDESC __RPC_FAR *ptdescAlias);
+
+ HRESULT ( __stdcall __RPC_FAR *DefineFuncAsDllEntry )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ LPOLESTR szDllName,
+ /* [in] */ LPOLESTR szProcName);
+
+ HRESULT ( __stdcall __RPC_FAR *SetFuncDocString )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ LPOLESTR szDocString);
+
+ HRESULT ( __stdcall __RPC_FAR *SetVarDocString )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ LPOLESTR szDocString);
+
+ HRESULT ( __stdcall __RPC_FAR *SetFuncHelpContext )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ DWORD dwHelpContext);
+
+ HRESULT ( __stdcall __RPC_FAR *SetVarHelpContext )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ DWORD dwHelpContext);
+
+ HRESULT ( __stdcall __RPC_FAR *SetMops )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ BSTR bstrMops);
+
+ HRESULT ( __stdcall __RPC_FAR *SetTypeIdldesc )(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ IDLDESC __RPC_FAR *pidldesc);
+
+ HRESULT ( __stdcall __RPC_FAR *LayOut )(
+ ICreateTypeInfo __RPC_FAR * This);
+
+ } ICreateTypeInfoVtbl;
+
+ interface ICreateTypeInfo
+ {
+ CONST_VTBL struct ICreateTypeInfoVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICreateTypeInfo_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define ICreateTypeInfo_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define ICreateTypeInfo_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define ICreateTypeInfo_SetGuid(This,guid) \
+ (This)->lpVtbl -> SetGuid(This,guid)
+
+#define ICreateTypeInfo_SetTypeFlags(This,uTypeFlags) \
+ (This)->lpVtbl -> SetTypeFlags(This,uTypeFlags)
+
+#define ICreateTypeInfo_SetDocString(This,lpstrDoc) \
+ (This)->lpVtbl -> SetDocString(This,lpstrDoc)
+
+#define ICreateTypeInfo_SetHelpContext(This,dwHelpContext) \
+ (This)->lpVtbl -> SetHelpContext(This,dwHelpContext)
+
+#define ICreateTypeInfo_SetVersion(This,wMajorVerNum,wMinorVerNum) \
+ (This)->lpVtbl -> SetVersion(This,wMajorVerNum,wMinorVerNum)
+
+#define ICreateTypeInfo_AddRefTypeInfo(This,ptinfo,phreftype) \
+ (This)->lpVtbl -> AddRefTypeInfo(This,ptinfo,phreftype)
+
+#define ICreateTypeInfo_AddFuncDesc(This,index,pfuncdesc) \
+ (This)->lpVtbl -> AddFuncDesc(This,index,pfuncdesc)
+
+#define ICreateTypeInfo_AddImplType(This,index,hreftype) \
+ (This)->lpVtbl -> AddImplType(This,index,hreftype)
+
+#define ICreateTypeInfo_SetImplTypeFlags(This,index,impltypeflags) \
+ (This)->lpVtbl -> SetImplTypeFlags(This,index,impltypeflags)
+
+#define ICreateTypeInfo_SetAlignment(This,cbAlignment) \
+ (This)->lpVtbl -> SetAlignment(This,cbAlignment)
+
+#define ICreateTypeInfo_SetSchema(This,lpstrSchema) \
+ (This)->lpVtbl -> SetSchema(This,lpstrSchema)
+
+#define ICreateTypeInfo_AddVarDesc(This,index,pvardesc) \
+ (This)->lpVtbl -> AddVarDesc(This,index,pvardesc)
+
+#define ICreateTypeInfo_SetFuncAndParamNames(This,index,rgszNames,cNames) \
+ (This)->lpVtbl -> SetFuncAndParamNames(This,index,rgszNames,cNames)
+
+#define ICreateTypeInfo_SetVarName(This,index,szName) \
+ (This)->lpVtbl -> SetVarName(This,index,szName)
+
+#define ICreateTypeInfo_SetTypeDescAlias(This,ptdescAlias) \
+ (This)->lpVtbl -> SetTypeDescAlias(This,ptdescAlias)
+
+#define ICreateTypeInfo_DefineFuncAsDllEntry(This,index,szDllName,szProcName) \
+ (This)->lpVtbl -> DefineFuncAsDllEntry(This,index,szDllName,szProcName)
+
+#define ICreateTypeInfo_SetFuncDocString(This,index,szDocString) \
+ (This)->lpVtbl -> SetFuncDocString(This,index,szDocString)
+
+#define ICreateTypeInfo_SetVarDocString(This,index,szDocString) \
+ (This)->lpVtbl -> SetVarDocString(This,index,szDocString)
+
+#define ICreateTypeInfo_SetFuncHelpContext(This,index,dwHelpContext) \
+ (This)->lpVtbl -> SetFuncHelpContext(This,index,dwHelpContext)
+
+#define ICreateTypeInfo_SetVarHelpContext(This,index,dwHelpContext) \
+ (This)->lpVtbl -> SetVarHelpContext(This,index,dwHelpContext)
+
+#define ICreateTypeInfo_SetMops(This,index,bstrMops) \
+ (This)->lpVtbl -> SetMops(This,index,bstrMops)
+
+#define ICreateTypeInfo_SetTypeIdldesc(This,pidldesc) \
+ (This)->lpVtbl -> SetTypeIdldesc(This,pidldesc)
+
+#define ICreateTypeInfo_LayOut(This) \
+ (This)->lpVtbl -> LayOut(This)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall ICreateTypeInfo_SetGuid_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ REFGUID guid);
+
+
+void __RPC_STUB ICreateTypeInfo_SetGuid_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetTypeFlags_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT uTypeFlags);
+
+
+void __RPC_STUB ICreateTypeInfo_SetTypeFlags_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetDocString_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ LPOLESTR lpstrDoc);
+
+
+void __RPC_STUB ICreateTypeInfo_SetDocString_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetHelpContext_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ DWORD dwHelpContext);
+
+
+void __RPC_STUB ICreateTypeInfo_SetHelpContext_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetVersion_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ WORD wMajorVerNum,
+ /* [in] */ WORD wMinorVerNum);
+
+
+void __RPC_STUB ICreateTypeInfo_SetVersion_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_AddRefTypeInfo_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ ITypeInfo __RPC_FAR *ptinfo,
+ /* [in] */ HREFTYPE __RPC_FAR *phreftype);
+
+
+void __RPC_STUB ICreateTypeInfo_AddRefTypeInfo_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_AddFuncDesc_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ FUNCDESC __RPC_FAR *pfuncdesc);
+
+
+void __RPC_STUB ICreateTypeInfo_AddFuncDesc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_AddImplType_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ HREFTYPE hreftype);
+
+
+void __RPC_STUB ICreateTypeInfo_AddImplType_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetImplTypeFlags_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ INT impltypeflags);
+
+
+void __RPC_STUB ICreateTypeInfo_SetImplTypeFlags_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetAlignment_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ WORD cbAlignment);
+
+
+void __RPC_STUB ICreateTypeInfo_SetAlignment_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetSchema_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ LPOLESTR lpstrSchema);
+
+
+void __RPC_STUB ICreateTypeInfo_SetSchema_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_AddVarDesc_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ VARDESC __RPC_FAR *pvardesc);
+
+
+void __RPC_STUB ICreateTypeInfo_AddVarDesc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetFuncAndParamNames_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in][size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
+ /* [in] */ UINT cNames);
+
+
+void __RPC_STUB ICreateTypeInfo_SetFuncAndParamNames_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetVarName_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ LPOLESTR szName);
+
+
+void __RPC_STUB ICreateTypeInfo_SetVarName_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetTypeDescAlias_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ TYPEDESC __RPC_FAR *ptdescAlias);
+
+
+void __RPC_STUB ICreateTypeInfo_SetTypeDescAlias_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_DefineFuncAsDllEntry_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ LPOLESTR szDllName,
+ /* [in] */ LPOLESTR szProcName);
+
+
+void __RPC_STUB ICreateTypeInfo_DefineFuncAsDllEntry_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetFuncDocString_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ LPOLESTR szDocString);
+
+
+void __RPC_STUB ICreateTypeInfo_SetFuncDocString_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetVarDocString_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ LPOLESTR szDocString);
+
+
+void __RPC_STUB ICreateTypeInfo_SetVarDocString_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetFuncHelpContext_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ DWORD dwHelpContext);
+
+
+void __RPC_STUB ICreateTypeInfo_SetFuncHelpContext_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetVarHelpContext_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ DWORD dwHelpContext);
+
+
+void __RPC_STUB ICreateTypeInfo_SetVarHelpContext_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetMops_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [in] */ BSTR bstrMops);
+
+
+void __RPC_STUB ICreateTypeInfo_SetMops_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_SetTypeIdldesc_Proxy(
+ ICreateTypeInfo __RPC_FAR * This,
+ /* [in] */ IDLDESC __RPC_FAR *pidldesc);
+
+
+void __RPC_STUB ICreateTypeInfo_SetTypeIdldesc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeInfo_LayOut_Proxy(
+ ICreateTypeInfo __RPC_FAR * This);
+
+
+void __RPC_STUB ICreateTypeInfo_LayOut_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __ICreateTypeInfo_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICreateTypeLib_INTERFACE_DEFINED__
+#define __ICreateTypeLib_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: ICreateTypeLib
+ * at Fri Apr 28 07:02:38 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [local][unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ ICreateTypeLib __RPC_FAR *LPCREATETYPELIB;
+
+
+EXTERN_C const IID IID_ICreateTypeLib;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface ICreateTypeLib : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall CreateTypeInfo(
+ /* [in] */ LPOLESTR szName,
+ /* [in] */ TYPEKIND tkind,
+ /* [out] */ ICreateTypeInfo __RPC_FAR *__RPC_FAR *lplpictinfo) = 0;
+
+ virtual HRESULT __stdcall SetName(
+ LPOLESTR szName) = 0;
+
+ virtual HRESULT __stdcall SetVersion(
+ /* [in] */ WORD wMajorVerNum,
+ /* [in] */ WORD wMinorVerNum) = 0;
+
+ virtual HRESULT __stdcall SetGuid(
+ /* [in] */ REFGUID guid) = 0;
+
+ virtual HRESULT __stdcall SetDocString(
+ /* [in] */ LPOLESTR szDoc) = 0;
+
+ virtual HRESULT __stdcall SetHelpFileName(
+ /* [in] */ LPOLESTR szHelpFileName) = 0;
+
+ virtual HRESULT __stdcall SetHelpContext(
+ /* [in] */ DWORD dwHelpContext) = 0;
+
+ virtual HRESULT __stdcall SetLcid(
+ /* [in] */ LCID lcid) = 0;
+
+ virtual HRESULT __stdcall SetLibFlags(
+ /* [in] */ UINT uLibFlags) = 0;
+
+ virtual HRESULT __stdcall SaveAllChanges( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ICreateTypeLibVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ ICreateTypeLib __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ ICreateTypeLib __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *CreateTypeInfo )(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ LPOLESTR szName,
+ /* [in] */ TYPEKIND tkind,
+ /* [out] */ ICreateTypeInfo __RPC_FAR *__RPC_FAR *lplpictinfo);
+
+ HRESULT ( __stdcall __RPC_FAR *SetName )(
+ ICreateTypeLib __RPC_FAR * This,
+ LPOLESTR szName);
+
+ HRESULT ( __stdcall __RPC_FAR *SetVersion )(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ WORD wMajorVerNum,
+ /* [in] */ WORD wMinorVerNum);
+
+ HRESULT ( __stdcall __RPC_FAR *SetGuid )(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ REFGUID guid);
+
+ HRESULT ( __stdcall __RPC_FAR *SetDocString )(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ LPOLESTR szDoc);
+
+ HRESULT ( __stdcall __RPC_FAR *SetHelpFileName )(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ LPOLESTR szHelpFileName);
+
+ HRESULT ( __stdcall __RPC_FAR *SetHelpContext )(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ DWORD dwHelpContext);
+
+ HRESULT ( __stdcall __RPC_FAR *SetLcid )(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ LCID lcid);
+
+ HRESULT ( __stdcall __RPC_FAR *SetLibFlags )(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ UINT uLibFlags);
+
+ HRESULT ( __stdcall __RPC_FAR *SaveAllChanges )(
+ ICreateTypeLib __RPC_FAR * This);
+
+ } ICreateTypeLibVtbl;
+
+ interface ICreateTypeLib
+ {
+ CONST_VTBL struct ICreateTypeLibVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICreateTypeLib_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define ICreateTypeLib_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define ICreateTypeLib_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define ICreateTypeLib_CreateTypeInfo(This,szName,tkind,lplpictinfo) \
+ (This)->lpVtbl -> CreateTypeInfo(This,szName,tkind,lplpictinfo)
+
+#define ICreateTypeLib_SetName(This,szName) \
+ (This)->lpVtbl -> SetName(This,szName)
+
+#define ICreateTypeLib_SetVersion(This,wMajorVerNum,wMinorVerNum) \
+ (This)->lpVtbl -> SetVersion(This,wMajorVerNum,wMinorVerNum)
+
+#define ICreateTypeLib_SetGuid(This,guid) \
+ (This)->lpVtbl -> SetGuid(This,guid)
+
+#define ICreateTypeLib_SetDocString(This,szDoc) \
+ (This)->lpVtbl -> SetDocString(This,szDoc)
+
+#define ICreateTypeLib_SetHelpFileName(This,szHelpFileName) \
+ (This)->lpVtbl -> SetHelpFileName(This,szHelpFileName)
+
+#define ICreateTypeLib_SetHelpContext(This,dwHelpContext) \
+ (This)->lpVtbl -> SetHelpContext(This,dwHelpContext)
+
+#define ICreateTypeLib_SetLcid(This,lcid) \
+ (This)->lpVtbl -> SetLcid(This,lcid)
+
+#define ICreateTypeLib_SetLibFlags(This,uLibFlags) \
+ (This)->lpVtbl -> SetLibFlags(This,uLibFlags)
+
+#define ICreateTypeLib_SaveAllChanges(This) \
+ (This)->lpVtbl -> SaveAllChanges(This)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall ICreateTypeLib_CreateTypeInfo_Proxy(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ LPOLESTR szName,
+ /* [in] */ TYPEKIND tkind,
+ /* [out] */ ICreateTypeInfo __RPC_FAR *__RPC_FAR *lplpictinfo);
+
+
+void __RPC_STUB ICreateTypeLib_CreateTypeInfo_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeLib_SetName_Proxy(
+ ICreateTypeLib __RPC_FAR * This,
+ LPOLESTR szName);
+
+
+void __RPC_STUB ICreateTypeLib_SetName_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeLib_SetVersion_Proxy(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ WORD wMajorVerNum,
+ /* [in] */ WORD wMinorVerNum);
+
+
+void __RPC_STUB ICreateTypeLib_SetVersion_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeLib_SetGuid_Proxy(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ REFGUID guid);
+
+
+void __RPC_STUB ICreateTypeLib_SetGuid_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeLib_SetDocString_Proxy(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ LPOLESTR szDoc);
+
+
+void __RPC_STUB ICreateTypeLib_SetDocString_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeLib_SetHelpFileName_Proxy(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ LPOLESTR szHelpFileName);
+
+
+void __RPC_STUB ICreateTypeLib_SetHelpFileName_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeLib_SetHelpContext_Proxy(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ DWORD dwHelpContext);
+
+
+void __RPC_STUB ICreateTypeLib_SetHelpContext_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeLib_SetLcid_Proxy(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ LCID lcid);
+
+
+void __RPC_STUB ICreateTypeLib_SetLcid_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeLib_SetLibFlags_Proxy(
+ ICreateTypeLib __RPC_FAR * This,
+ /* [in] */ UINT uLibFlags);
+
+
+void __RPC_STUB ICreateTypeLib_SetLibFlags_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateTypeLib_SaveAllChanges_Proxy(
+ ICreateTypeLib __RPC_FAR * This);
+
+
+void __RPC_STUB ICreateTypeLib_SaveAllChanges_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __ICreateTypeLib_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDispatch_INTERFACE_DEFINED__
+#define __IDispatch_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IDispatch
+ * at Fri Apr 28 07:02:38 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [local][unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IDispatch __RPC_FAR *LPDISPATCH;
+
+/* DISPID reserved to indicate an "unknown" name */
+/* only reserved for data members (properties); reused as a method dispid below */
+ /* size is 4 */
+#define DISPID_UNKNOWN ( -1 )
+
+/* DISPID reserved for the "value" property */
+ /* size is 4 */
+#define DISPID_VALUE ( 0 )
+
+/* The following DISPID is reserved to indicate the param
+ * that is the right-hand-side (or "put" value) of a PropertyPut
+ */
+ /* size is 4 */
+#define DISPID_PROPERTYPUT ( -3 )
+
+/* DISPID reserved for the standard "NewEnum" method */
+ /* size is 4 */
+#define DISPID_NEWENUM ( -4 )
+
+/* DISPID reserved for the standard "Evaluate" method */
+ /* size is 4 */
+#define DISPID_EVALUATE ( -5 )
+
+ /* size is 4 */
+#define DISPID_CONSTRUCTOR ( -6 )
+
+ /* size is 4 */
+#define DISPID_DESTRUCTOR ( -7 )
+
+ /* size is 4 */
+#define DISPID_COLLECT ( -8 )
+
+/* The range -500 through -999 is reserved for Controls */
+/* The range 0x80010000 through 0x8001FFFF is reserved for Controls */
+/* The remainder of the negative DISPIDs are reserved for future use */
+
+EXTERN_C const IID IID_IDispatch;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IDispatch : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall GetTypeInfoCount(
+ /* [out] */ UINT __RPC_FAR *pctinfo) = 0;
+
+ virtual HRESULT __stdcall GetTypeInfo(
+ /* [in] */ UINT itinfo,
+ /* [in] */ LCID lcid,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo) = 0;
+
+ virtual HRESULT __stdcall GetIDsOfNames(
+ /* [in] */ REFIID riid,
+ /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
+ /* [in] */ UINT cNames,
+ /* [in] */ LCID lcid,
+ /* [size_is][out][in] */ DISPID __RPC_FAR *rgdispid) = 0;
+
+ virtual HRESULT __stdcall Invoke(
+ /* [in] */ DISPID dispidMember,
+ /* [in] */ REFIID riid,
+ /* [in] */ LCID lcid,
+ /* [in] */ WORD wFlags,
+ /* [unique][in] */ DISPPARAMS __RPC_FAR *pdispparams,
+ /* [unique][out][in] */ VARIANT __RPC_FAR *pvarResult,
+ /* [out] */ EXCEPINFO __RPC_FAR *pexcepinfo,
+ /* [out] */ UINT __RPC_FAR *puArgErr) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IDispatchVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IDispatch __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IDispatch __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IDispatch __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetTypeInfoCount )(
+ IDispatch __RPC_FAR * This,
+ /* [out] */ UINT __RPC_FAR *pctinfo);
+
+ HRESULT ( __stdcall __RPC_FAR *GetTypeInfo )(
+ IDispatch __RPC_FAR * This,
+ /* [in] */ UINT itinfo,
+ /* [in] */ LCID lcid,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo);
+
+ HRESULT ( __stdcall __RPC_FAR *GetIDsOfNames )(
+ IDispatch __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
+ /* [in] */ UINT cNames,
+ /* [in] */ LCID lcid,
+ /* [size_is][out][in] */ DISPID __RPC_FAR *rgdispid);
+
+ HRESULT ( __stdcall __RPC_FAR *Invoke )(
+ IDispatch __RPC_FAR * This,
+ /* [in] */ DISPID dispidMember,
+ /* [in] */ REFIID riid,
+ /* [in] */ LCID lcid,
+ /* [in] */ WORD wFlags,
+ /* [unique][in] */ DISPPARAMS __RPC_FAR *pdispparams,
+ /* [unique][out][in] */ VARIANT __RPC_FAR *pvarResult,
+ /* [out] */ EXCEPINFO __RPC_FAR *pexcepinfo,
+ /* [out] */ UINT __RPC_FAR *puArgErr);
+
+ } IDispatchVtbl;
+
+ interface IDispatch
+ {
+ CONST_VTBL struct IDispatchVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDispatch_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IDispatch_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IDispatch_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IDispatch_GetTypeInfoCount(This,pctinfo) \
+ (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)
+
+#define IDispatch_GetTypeInfo(This,itinfo,lcid,pptinfo) \
+ (This)->lpVtbl -> GetTypeInfo(This,itinfo,lcid,pptinfo)
+
+#define IDispatch_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgdispid) \
+ (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgdispid)
+
+#define IDispatch_Invoke(This,dispidMember,riid,lcid,wFlags,pdispparams,pvarResult,pexcepinfo,puArgErr) \
+ (This)->lpVtbl -> Invoke(This,dispidMember,riid,lcid,wFlags,pdispparams,pvarResult,pexcepinfo,puArgErr)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IDispatch_GetTypeInfoCount_Proxy(
+ IDispatch __RPC_FAR * This,
+ /* [out] */ UINT __RPC_FAR *pctinfo);
+
+
+void __RPC_STUB IDispatch_GetTypeInfoCount_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDispatch_GetTypeInfo_Proxy(
+ IDispatch __RPC_FAR * This,
+ /* [in] */ UINT itinfo,
+ /* [in] */ LCID lcid,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo);
+
+
+void __RPC_STUB IDispatch_GetTypeInfo_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDispatch_GetIDsOfNames_Proxy(
+ IDispatch __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
+ /* [in] */ UINT cNames,
+ /* [in] */ LCID lcid,
+ /* [size_is][out][in] */ DISPID __RPC_FAR *rgdispid);
+
+
+void __RPC_STUB IDispatch_GetIDsOfNames_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDispatch_Invoke_Proxy(
+ IDispatch __RPC_FAR * This,
+ /* [in] */ DISPID dispidMember,
+ /* [in] */ REFIID riid,
+ /* [in] */ LCID lcid,
+ /* [in] */ WORD wFlags,
+ /* [unique][in] */ DISPPARAMS __RPC_FAR *pdispparams,
+ /* [unique][out][in] */ VARIANT __RPC_FAR *pvarResult,
+ /* [out] */ EXCEPINFO __RPC_FAR *pexcepinfo,
+ /* [out] */ UINT __RPC_FAR *puArgErr);
+
+
+void __RPC_STUB IDispatch_Invoke_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IDispatch_INTERFACE_DEFINED__ */
+
+
+#ifndef __IEnumVARIANT_INTERFACE_DEFINED__
+#define __IEnumVARIANT_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IEnumVARIANT
+ * at Fri Apr 28 07:02:38 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][local][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IEnumVARIANT __RPC_FAR *LPENUMVARIANT;
+
+
+EXTERN_C const IID IID_IEnumVARIANT;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IEnumVARIANT : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall Next(
+ /* [in] */ unsigned long celt,
+ /* [out] */ VARIANT __RPC_FAR *rgvar,
+ /* [out] */ unsigned long __RPC_FAR *pceltFetched) = 0;
+
+ virtual HRESULT __stdcall Skip(
+ /* [in] */ unsigned long celt) = 0;
+
+ virtual HRESULT __stdcall Reset( void) = 0;
+
+ virtual HRESULT __stdcall Clone(
+ /* [out] */ IEnumVARIANT __RPC_FAR *__RPC_FAR *ppenum) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IEnumVARIANTVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IEnumVARIANT __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IEnumVARIANT __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IEnumVARIANT __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Next )(
+ IEnumVARIANT __RPC_FAR * This,
+ /* [in] */ unsigned long celt,
+ /* [out] */ VARIANT __RPC_FAR *rgvar,
+ /* [out] */ unsigned long __RPC_FAR *pceltFetched);
+
+ HRESULT ( __stdcall __RPC_FAR *Skip )(
+ IEnumVARIANT __RPC_FAR * This,
+ /* [in] */ unsigned long celt);
+
+ HRESULT ( __stdcall __RPC_FAR *Reset )(
+ IEnumVARIANT __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Clone )(
+ IEnumVARIANT __RPC_FAR * This,
+ /* [out] */ IEnumVARIANT __RPC_FAR *__RPC_FAR *ppenum);
+
+ } IEnumVARIANTVtbl;
+
+ interface IEnumVARIANT
+ {
+ CONST_VTBL struct IEnumVARIANTVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IEnumVARIANT_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IEnumVARIANT_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IEnumVARIANT_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IEnumVARIANT_Next(This,celt,rgvar,pceltFetched) \
+ (This)->lpVtbl -> Next(This,celt,rgvar,pceltFetched)
+
+#define IEnumVARIANT_Skip(This,celt) \
+ (This)->lpVtbl -> Skip(This,celt)
+
+#define IEnumVARIANT_Reset(This) \
+ (This)->lpVtbl -> Reset(This)
+
+#define IEnumVARIANT_Clone(This,ppenum) \
+ (This)->lpVtbl -> Clone(This,ppenum)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IEnumVARIANT_Next_Proxy(
+ IEnumVARIANT __RPC_FAR * This,
+ /* [in] */ unsigned long celt,
+ /* [out] */ VARIANT __RPC_FAR *rgvar,
+ /* [out] */ unsigned long __RPC_FAR *pceltFetched);
+
+
+void __RPC_STUB IEnumVARIANT_Next_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumVARIANT_Skip_Proxy(
+ IEnumVARIANT __RPC_FAR * This,
+ /* [in] */ unsigned long celt);
+
+
+void __RPC_STUB IEnumVARIANT_Skip_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumVARIANT_Reset_Proxy(
+ IEnumVARIANT __RPC_FAR * This);
+
+
+void __RPC_STUB IEnumVARIANT_Reset_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumVARIANT_Clone_Proxy(
+ IEnumVARIANT __RPC_FAR * This,
+ /* [out] */ IEnumVARIANT __RPC_FAR *__RPC_FAR *ppenum);
+
+
+void __RPC_STUB IEnumVARIANT_Clone_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IEnumVARIANT_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITypeComp_INTERFACE_DEFINED__
+#define __ITypeComp_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: ITypeComp
+ * at Fri Apr 28 07:02:38 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [local][unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ ITypeComp __RPC_FAR *LPTYPECOMP;
+
+ /* size is 2 */
+typedef /* [v1_enum] */
+enum tagDESCKIND
+ { DESCKIND_NONE = 0,
+ DESCKIND_FUNCDESC = DESCKIND_NONE + 1,
+ DESCKIND_VARDESC = DESCKIND_FUNCDESC + 1,
+ DESCKIND_TYPECOMP = DESCKIND_VARDESC + 1,
+ DESCKIND_IMPLICITAPPOBJ = DESCKIND_TYPECOMP + 1,
+ DESCKIND_MAX = DESCKIND_IMPLICITAPPOBJ + 1
+ } DESCKIND;
+
+#define DESCKIND_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)
+#define DESCKIND_from_xmit(pLong, pEnum) *(pEnum) = (DESCKIND) *(pLong)
+#define DESCKIND_free_inst(pEnum)
+#define DESCKIND_free_xmit(pLong)
+ /* size is 4 */
+/* [switch_type] */ union tagBINDPTR
+ {
+ /* [case] */ FUNCDESC __RPC_FAR *lpfuncdesc;
+ /* [case] */ VARDESC __RPC_FAR *lpvardesc;
+ /* [case][unique] */ ITypeComp __RPC_FAR *lptcomp;
+ /* [default] */ /* Empty union arm */
+ };
+ /* size is 4 */
+typedef union tagBINDPTR BINDPTR;
+
+ /* size is 4 */
+typedef BINDPTR __RPC_FAR *LPBINDPTR;
+
+
+EXTERN_C const IID IID_ITypeComp;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface ITypeComp : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall Bind(
+ /* [in] */ LPOLESTR szName,
+ /* [in] */ ULONG lHashVal,
+ /* [in] */ WORD fFlags,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo,
+ /* [out] */ DESCKIND __RPC_FAR *pdesckind,
+ /* [switch_is][out] */ BINDPTR __RPC_FAR *pbindptr) = 0;
+
+ virtual HRESULT __stdcall BindType(
+ /* [in] */ LPOLESTR szName,
+ /* [in] */ ULONG lHashVal,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo,
+ /* [out] */ ITypeComp __RPC_FAR *__RPC_FAR *pptcomp) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITypeCompVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ ITypeComp __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ ITypeComp __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ ITypeComp __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Bind )(
+ ITypeComp __RPC_FAR * This,
+ /* [in] */ LPOLESTR szName,
+ /* [in] */ ULONG lHashVal,
+ /* [in] */ WORD fFlags,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo,
+ /* [out] */ DESCKIND __RPC_FAR *pdesckind,
+ /* [switch_is][out] */ BINDPTR __RPC_FAR *pbindptr);
+
+ HRESULT ( __stdcall __RPC_FAR *BindType )(
+ ITypeComp __RPC_FAR * This,
+ /* [in] */ LPOLESTR szName,
+ /* [in] */ ULONG lHashVal,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo,
+ /* [out] */ ITypeComp __RPC_FAR *__RPC_FAR *pptcomp);
+
+ } ITypeCompVtbl;
+
+ interface ITypeComp
+ {
+ CONST_VTBL struct ITypeCompVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITypeComp_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define ITypeComp_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define ITypeComp_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define ITypeComp_Bind(This,szName,lHashVal,fFlags,pptinfo,pdesckind,pbindptr) \
+ (This)->lpVtbl -> Bind(This,szName,lHashVal,fFlags,pptinfo,pdesckind,pbindptr)
+
+#define ITypeComp_BindType(This,szName,lHashVal,pptinfo,pptcomp) \
+ (This)->lpVtbl -> BindType(This,szName,lHashVal,pptinfo,pptcomp)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall ITypeComp_Bind_Proxy(
+ ITypeComp __RPC_FAR * This,
+ /* [in] */ LPOLESTR szName,
+ /* [in] */ ULONG lHashVal,
+ /* [in] */ WORD fFlags,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo,
+ /* [out] */ DESCKIND __RPC_FAR *pdesckind,
+ /* [switch_is][out] */ BINDPTR __RPC_FAR *pbindptr);
+
+
+void __RPC_STUB ITypeComp_Bind_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeComp_BindType_Proxy(
+ ITypeComp __RPC_FAR * This,
+ /* [in] */ LPOLESTR szName,
+ /* [in] */ ULONG lHashVal,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo,
+ /* [out] */ ITypeComp __RPC_FAR *__RPC_FAR *pptcomp);
+
+
+void __RPC_STUB ITypeComp_BindType_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __ITypeComp_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITypeInfo_INTERFACE_DEFINED__
+#define __ITypeInfo_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: ITypeInfo
+ * at Fri Apr 28 07:02:38 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [local][unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ ITypeInfo __RPC_FAR *LPTYPEINFO;
+
+
+EXTERN_C const IID IID_ITypeInfo;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface ITypeInfo : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall GetTypeAttr(
+ /* [out] */ TYPEATTR __RPC_FAR *__RPC_FAR *pptypeattr) = 0;
+
+ virtual HRESULT __stdcall GetTypeComp(
+ /* [out] */ ITypeComp __RPC_FAR *__RPC_FAR *pptcomp) = 0;
+
+ virtual HRESULT __stdcall GetFuncDesc(
+ /* [in] */ UINT index,
+ /* [out] */ FUNCDESC __RPC_FAR *__RPC_FAR *pppfuncdesc) = 0;
+
+ virtual HRESULT __stdcall GetVarDesc(
+ /* [in] */ UINT index,
+ /* [out] */ VARDESC __RPC_FAR *__RPC_FAR *ppvardesc) = 0;
+
+ virtual HRESULT __stdcall GetNames(
+ /* [in] */ MEMBERID memid,
+ /* [length_is][size_is][out] */ BSTR __RPC_FAR *rgbstrNames,
+ /* [in] */ UINT cMaxNames,
+ /* [out] */ UINT __RPC_FAR *pcNames) = 0;
+
+ virtual HRESULT __stdcall GetRefTypeOfImplType(
+ /* [in] */ UINT index,
+ /* [out] */ HREFTYPE __RPC_FAR *hpreftype) = 0;
+
+ virtual HRESULT __stdcall GetImplTypeFlags(
+ /* [in] */ UINT index,
+ /* [out] */ INT __RPC_FAR *pimpltypeflags) = 0;
+
+ virtual HRESULT __stdcall GetIDsOfNames(
+ /* [size_is][in] */ OLECHAR __RPC_FAR *__RPC_FAR *rglpszNames,
+ /* [in] */ UINT cNames,
+ /* [size_is][out] */ MEMBERID __RPC_FAR *rgmemid) = 0;
+
+ virtual HRESULT __stdcall Invoke(
+ /* [unique][in] */ void __RPC_FAR *pvInstance,
+ /* [in] */ MEMBERID memid,
+ /* [in] */ WORD wFlags,
+ /* [in] */ DISPPARAMS __RPC_FAR *pdispparams,
+ /* [out] */ VARIANT __RPC_FAR *pvarResult,
+ /* [out] */ EXCEPINFO __RPC_FAR *pexcepinfo,
+ /* [out] */ UINT __RPC_FAR *puArgErr) = 0;
+
+ virtual HRESULT __stdcall GetDocumentation(
+ /* [in] */ MEMBERID memid,
+ /* [out] */ BSTR __RPC_FAR *pbstrName,
+ /* [out] */ BSTR __RPC_FAR *pbstrDocString,
+ /* [out] */ DWORD __RPC_FAR *pdwHelpContext,
+ /* [out] */ BSTR __RPC_FAR *pbstrHelpFile) = 0;
+
+ virtual HRESULT __stdcall GetDllEntry(
+ /* [in] */ MEMBERID memid,
+ /* [in] */ INVOKEKIND invkind,
+ /* [out] */ BSTR __RPC_FAR *pbstrDllName,
+ /* [out] */ BSTR __RPC_FAR *pbstrName,
+ /* [out] */ WORD __RPC_FAR *pwOrdinal) = 0;
+
+ virtual HRESULT __stdcall GetRefTypeInfo(
+ /* [in] */ HREFTYPE hreftype,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo) = 0;
+
+ virtual HRESULT __stdcall AddressOfMember(
+ /* [in] */ MEMBERID memid,
+ /* [in] */ INVOKEKIND invkind,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppv) = 0;
+
+ virtual HRESULT __stdcall CreateInstance(
+ /* [in] */ IUnknown __RPC_FAR *puncOuter,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObj) = 0;
+
+ virtual HRESULT __stdcall GetMops(
+ /* [in] */ MEMBERID memid,
+ /* [out] */ BSTR __RPC_FAR *pbstrMops) = 0;
+
+ virtual HRESULT __stdcall GetContainingTypeLib(
+ /* [out] */ ITypeLib __RPC_FAR *__RPC_FAR *pptlib,
+ /* [out] */ UINT __RPC_FAR *pindex) = 0;
+
+ virtual void __stdcall ReleaseTypeAttr(
+ /* [in] */ TYPEATTR __RPC_FAR *ptypeattr) = 0;
+
+ virtual void __stdcall ReleaseFuncDesc(
+ /* [in] */ FUNCDESC __RPC_FAR *pfuncdesc) = 0;
+
+ virtual void __stdcall ReleaseVarDesc(
+ /* [in] */ VARDESC __RPC_FAR *pvardesc) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITypeInfoVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ ITypeInfo __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ ITypeInfo __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetTypeAttr )(
+ ITypeInfo __RPC_FAR * This,
+ /* [out] */ TYPEATTR __RPC_FAR *__RPC_FAR *pptypeattr);
+
+ HRESULT ( __stdcall __RPC_FAR *GetTypeComp )(
+ ITypeInfo __RPC_FAR * This,
+ /* [out] */ ITypeComp __RPC_FAR *__RPC_FAR *pptcomp);
+
+ HRESULT ( __stdcall __RPC_FAR *GetFuncDesc )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [out] */ FUNCDESC __RPC_FAR *__RPC_FAR *pppfuncdesc);
+
+ HRESULT ( __stdcall __RPC_FAR *GetVarDesc )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [out] */ VARDESC __RPC_FAR *__RPC_FAR *ppvardesc);
+
+ HRESULT ( __stdcall __RPC_FAR *GetNames )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ MEMBERID memid,
+ /* [length_is][size_is][out] */ BSTR __RPC_FAR *rgbstrNames,
+ /* [in] */ UINT cMaxNames,
+ /* [out] */ UINT __RPC_FAR *pcNames);
+
+ HRESULT ( __stdcall __RPC_FAR *GetRefTypeOfImplType )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [out] */ HREFTYPE __RPC_FAR *hpreftype);
+
+ HRESULT ( __stdcall __RPC_FAR *GetImplTypeFlags )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [out] */ INT __RPC_FAR *pimpltypeflags);
+
+ HRESULT ( __stdcall __RPC_FAR *GetIDsOfNames )(
+ ITypeInfo __RPC_FAR * This,
+ /* [size_is][in] */ OLECHAR __RPC_FAR *__RPC_FAR *rglpszNames,
+ /* [in] */ UINT cNames,
+ /* [size_is][out] */ MEMBERID __RPC_FAR *rgmemid);
+
+ HRESULT ( __stdcall __RPC_FAR *Invoke )(
+ ITypeInfo __RPC_FAR * This,
+ /* [unique][in] */ void __RPC_FAR *pvInstance,
+ /* [in] */ MEMBERID memid,
+ /* [in] */ WORD wFlags,
+ /* [in] */ DISPPARAMS __RPC_FAR *pdispparams,
+ /* [out] */ VARIANT __RPC_FAR *pvarResult,
+ /* [out] */ EXCEPINFO __RPC_FAR *pexcepinfo,
+ /* [out] */ UINT __RPC_FAR *puArgErr);
+
+ HRESULT ( __stdcall __RPC_FAR *GetDocumentation )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ MEMBERID memid,
+ /* [out] */ BSTR __RPC_FAR *pbstrName,
+ /* [out] */ BSTR __RPC_FAR *pbstrDocString,
+ /* [out] */ DWORD __RPC_FAR *pdwHelpContext,
+ /* [out] */ BSTR __RPC_FAR *pbstrHelpFile);
+
+ HRESULT ( __stdcall __RPC_FAR *GetDllEntry )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ MEMBERID memid,
+ /* [in] */ INVOKEKIND invkind,
+ /* [out] */ BSTR __RPC_FAR *pbstrDllName,
+ /* [out] */ BSTR __RPC_FAR *pbstrName,
+ /* [out] */ WORD __RPC_FAR *pwOrdinal);
+
+ HRESULT ( __stdcall __RPC_FAR *GetRefTypeInfo )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ HREFTYPE hreftype,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo);
+
+ HRESULT ( __stdcall __RPC_FAR *AddressOfMember )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ MEMBERID memid,
+ /* [in] */ INVOKEKIND invkind,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppv);
+
+ HRESULT ( __stdcall __RPC_FAR *CreateInstance )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ IUnknown __RPC_FAR *puncOuter,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObj);
+
+ HRESULT ( __stdcall __RPC_FAR *GetMops )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ MEMBERID memid,
+ /* [out] */ BSTR __RPC_FAR *pbstrMops);
+
+ HRESULT ( __stdcall __RPC_FAR *GetContainingTypeLib )(
+ ITypeInfo __RPC_FAR * This,
+ /* [out] */ ITypeLib __RPC_FAR *__RPC_FAR *pptlib,
+ /* [out] */ UINT __RPC_FAR *pindex);
+
+ void ( __stdcall __RPC_FAR *ReleaseTypeAttr )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ TYPEATTR __RPC_FAR *ptypeattr);
+
+ void ( __stdcall __RPC_FAR *ReleaseFuncDesc )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ FUNCDESC __RPC_FAR *pfuncdesc);
+
+ void ( __stdcall __RPC_FAR *ReleaseVarDesc )(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ VARDESC __RPC_FAR *pvardesc);
+
+ } ITypeInfoVtbl;
+
+ interface ITypeInfo
+ {
+ CONST_VTBL struct ITypeInfoVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITypeInfo_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define ITypeInfo_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define ITypeInfo_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define ITypeInfo_GetTypeAttr(This,pptypeattr) \
+ (This)->lpVtbl -> GetTypeAttr(This,pptypeattr)
+
+#define ITypeInfo_GetTypeComp(This,pptcomp) \
+ (This)->lpVtbl -> GetTypeComp(This,pptcomp)
+
+#define ITypeInfo_GetFuncDesc(This,index,pppfuncdesc) \
+ (This)->lpVtbl -> GetFuncDesc(This,index,pppfuncdesc)
+
+#define ITypeInfo_GetVarDesc(This,index,ppvardesc) \
+ (This)->lpVtbl -> GetVarDesc(This,index,ppvardesc)
+
+#define ITypeInfo_GetNames(This,memid,rgbstrNames,cMaxNames,pcNames) \
+ (This)->lpVtbl -> GetNames(This,memid,rgbstrNames,cMaxNames,pcNames)
+
+#define ITypeInfo_GetRefTypeOfImplType(This,index,hpreftype) \
+ (This)->lpVtbl -> GetRefTypeOfImplType(This,index,hpreftype)
+
+#define ITypeInfo_GetImplTypeFlags(This,index,pimpltypeflags) \
+ (This)->lpVtbl -> GetImplTypeFlags(This,index,pimpltypeflags)
+
+#define ITypeInfo_GetIDsOfNames(This,rglpszNames,cNames,rgmemid) \
+ (This)->lpVtbl -> GetIDsOfNames(This,rglpszNames,cNames,rgmemid)
+
+#define ITypeInfo_Invoke(This,pvInstance,memid,wFlags,pdispparams,pvarResult,pexcepinfo,puArgErr) \
+ (This)->lpVtbl -> Invoke(This,pvInstance,memid,wFlags,pdispparams,pvarResult,pexcepinfo,puArgErr)
+
+#define ITypeInfo_GetDocumentation(This,memid,pbstrName,pbstrDocString,pdwHelpContext,pbstrHelpFile) \
+ (This)->lpVtbl -> GetDocumentation(This,memid,pbstrName,pbstrDocString,pdwHelpContext,pbstrHelpFile)
+
+#define ITypeInfo_GetDllEntry(This,memid,invkind,pbstrDllName,pbstrName,pwOrdinal) \
+ (This)->lpVtbl -> GetDllEntry(This,memid,invkind,pbstrDllName,pbstrName,pwOrdinal)
+
+#define ITypeInfo_GetRefTypeInfo(This,hreftype,pptinfo) \
+ (This)->lpVtbl -> GetRefTypeInfo(This,hreftype,pptinfo)
+
+#define ITypeInfo_AddressOfMember(This,memid,invkind,ppv) \
+ (This)->lpVtbl -> AddressOfMember(This,memid,invkind,ppv)
+
+#define ITypeInfo_CreateInstance(This,puncOuter,riid,ppvObj) \
+ (This)->lpVtbl -> CreateInstance(This,puncOuter,riid,ppvObj)
+
+#define ITypeInfo_GetMops(This,memid,pbstrMops) \
+ (This)->lpVtbl -> GetMops(This,memid,pbstrMops)
+
+#define ITypeInfo_GetContainingTypeLib(This,pptlib,pindex) \
+ (This)->lpVtbl -> GetContainingTypeLib(This,pptlib,pindex)
+
+#define ITypeInfo_ReleaseTypeAttr(This,ptypeattr) \
+ (This)->lpVtbl -> ReleaseTypeAttr(This,ptypeattr)
+
+#define ITypeInfo_ReleaseFuncDesc(This,pfuncdesc) \
+ (This)->lpVtbl -> ReleaseFuncDesc(This,pfuncdesc)
+
+#define ITypeInfo_ReleaseVarDesc(This,pvardesc) \
+ (This)->lpVtbl -> ReleaseVarDesc(This,pvardesc)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall ITypeInfo_GetTypeAttr_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [out] */ TYPEATTR __RPC_FAR *__RPC_FAR *pptypeattr);
+
+
+void __RPC_STUB ITypeInfo_GetTypeAttr_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_GetTypeComp_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [out] */ ITypeComp __RPC_FAR *__RPC_FAR *pptcomp);
+
+
+void __RPC_STUB ITypeInfo_GetTypeComp_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_GetFuncDesc_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [out] */ FUNCDESC __RPC_FAR *__RPC_FAR *pppfuncdesc);
+
+
+void __RPC_STUB ITypeInfo_GetFuncDesc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_GetVarDesc_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [out] */ VARDESC __RPC_FAR *__RPC_FAR *ppvardesc);
+
+
+void __RPC_STUB ITypeInfo_GetVarDesc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_GetNames_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ MEMBERID memid,
+ /* [length_is][size_is][out] */ BSTR __RPC_FAR *rgbstrNames,
+ /* [in] */ UINT cMaxNames,
+ /* [out] */ UINT __RPC_FAR *pcNames);
+
+
+void __RPC_STUB ITypeInfo_GetNames_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_GetRefTypeOfImplType_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [out] */ HREFTYPE __RPC_FAR *hpreftype);
+
+
+void __RPC_STUB ITypeInfo_GetRefTypeOfImplType_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_GetImplTypeFlags_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [out] */ INT __RPC_FAR *pimpltypeflags);
+
+
+void __RPC_STUB ITypeInfo_GetImplTypeFlags_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_GetIDsOfNames_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [size_is][in] */ OLECHAR __RPC_FAR *__RPC_FAR *rglpszNames,
+ /* [in] */ UINT cNames,
+ /* [size_is][out] */ MEMBERID __RPC_FAR *rgmemid);
+
+
+void __RPC_STUB ITypeInfo_GetIDsOfNames_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_Invoke_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [unique][in] */ void __RPC_FAR *pvInstance,
+ /* [in] */ MEMBERID memid,
+ /* [in] */ WORD wFlags,
+ /* [in] */ DISPPARAMS __RPC_FAR *pdispparams,
+ /* [out] */ VARIANT __RPC_FAR *pvarResult,
+ /* [out] */ EXCEPINFO __RPC_FAR *pexcepinfo,
+ /* [out] */ UINT __RPC_FAR *puArgErr);
+
+
+void __RPC_STUB ITypeInfo_Invoke_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_GetDocumentation_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ MEMBERID memid,
+ /* [out] */ BSTR __RPC_FAR *pbstrName,
+ /* [out] */ BSTR __RPC_FAR *pbstrDocString,
+ /* [out] */ DWORD __RPC_FAR *pdwHelpContext,
+ /* [out] */ BSTR __RPC_FAR *pbstrHelpFile);
+
+
+void __RPC_STUB ITypeInfo_GetDocumentation_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_GetDllEntry_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ MEMBERID memid,
+ /* [in] */ INVOKEKIND invkind,
+ /* [out] */ BSTR __RPC_FAR *pbstrDllName,
+ /* [out] */ BSTR __RPC_FAR *pbstrName,
+ /* [out] */ WORD __RPC_FAR *pwOrdinal);
+
+
+void __RPC_STUB ITypeInfo_GetDllEntry_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_GetRefTypeInfo_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ HREFTYPE hreftype,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo);
+
+
+void __RPC_STUB ITypeInfo_GetRefTypeInfo_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_AddressOfMember_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ MEMBERID memid,
+ /* [in] */ INVOKEKIND invkind,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppv);
+
+
+void __RPC_STUB ITypeInfo_AddressOfMember_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_CreateInstance_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ IUnknown __RPC_FAR *puncOuter,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObj);
+
+
+void __RPC_STUB ITypeInfo_CreateInstance_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_GetMops_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ MEMBERID memid,
+ /* [out] */ BSTR __RPC_FAR *pbstrMops);
+
+
+void __RPC_STUB ITypeInfo_GetMops_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeInfo_GetContainingTypeLib_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [out] */ ITypeLib __RPC_FAR *__RPC_FAR *pptlib,
+ /* [out] */ UINT __RPC_FAR *pindex);
+
+
+void __RPC_STUB ITypeInfo_GetContainingTypeLib_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __stdcall ITypeInfo_ReleaseTypeAttr_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ TYPEATTR __RPC_FAR *ptypeattr);
+
+
+void __RPC_STUB ITypeInfo_ReleaseTypeAttr_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __stdcall ITypeInfo_ReleaseFuncDesc_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ FUNCDESC __RPC_FAR *pfuncdesc);
+
+
+void __RPC_STUB ITypeInfo_ReleaseFuncDesc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __stdcall ITypeInfo_ReleaseVarDesc_Proxy(
+ ITypeInfo __RPC_FAR * This,
+ /* [in] */ VARDESC __RPC_FAR *pvardesc);
+
+
+void __RPC_STUB ITypeInfo_ReleaseVarDesc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __ITypeInfo_INTERFACE_DEFINED__ */
+
+
+#ifndef __ITypeLib_INTERFACE_DEFINED__
+#define __ITypeLib_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: ITypeLib
+ * at Fri Apr 28 07:02:38 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [local][unique][uuid][object] */
+
+
+ /* size is 2 */
+typedef /* [transmit] */
+enum tagSYSKIND
+ { SYS_WIN16 = 0,
+ SYS_WIN32 = SYS_WIN16 + 1,
+ SYS_MAC = SYS_WIN32 + 1
+ } SYSKIND;
+
+ /* size is 2 */
+typedef /* [transmit] */
+enum tagLIBFLAGS
+ { LIBFLAG_FRESTRICTED = 0x1,
+ LIBFLAG_FCONTROL = 0x2,
+ LIBFLAG_FHIDDEN = 0x4
+ } LIBFLAGS;
+
+#define SYSKIND_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)
+#define SYSKIND_from_xmit(pLong, pEnum) *(pEnum) = (SYSKIND) *(pLong)
+#define SYSKIND_free_inst(pEnum)
+#define SYSKIND_free_xmit(pLong)
+ /* size is 4 */
+typedef /* [unique] */ ITypeLib __RPC_FAR *LPTYPELIB;
+
+ /* size is 28 */
+typedef struct tagTLIBATTR
+ {
+ GUID guid;
+ LCID lcid;
+ SYSKIND syskind;
+ WORD wMajorVerNum;
+ WORD wMinorVerNum;
+ WORD wLibFlags;
+ } TLIBATTR;
+
+ /* size is 4 */
+typedef TLIBATTR __RPC_FAR *LPTLIBATTR;
+
+
+EXTERN_C const IID IID_ITypeLib;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface ITypeLib : public IUnknown
+ {
+ public:
+ virtual UINT __stdcall GetTypeInfoCount( void) = 0;
+
+ virtual HRESULT __stdcall GetTypeInfo(
+ /* [in] */ UINT index,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppitinfo) = 0;
+
+ virtual HRESULT __stdcall GetTypeInfoType(
+ /* [in] */ UINT index,
+ /* [out] */ TYPEKIND __RPC_FAR *ptkind) = 0;
+
+ virtual HRESULT __stdcall GetTypeInfoOfGuid(
+ /* [in] */ REFGUID guid,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo) = 0;
+
+ virtual HRESULT __stdcall GetLibAttr(
+ /* [out] */ TLIBATTR __RPC_FAR *__RPC_FAR *pptlibattr) = 0;
+
+ virtual HRESULT __stdcall GetTypeComp(
+ /* [out] */ ITypeComp __RPC_FAR *__RPC_FAR *pptcomp) = 0;
+
+ virtual HRESULT __stdcall GetDocumentation(
+ /* [in] */ INT index,
+ /* [out] */ BSTR __RPC_FAR *pbstrName,
+ /* [out] */ BSTR __RPC_FAR *pbstrDocString,
+ /* [out] */ DWORD __RPC_FAR *pdwHelpContext,
+ /* [out] */ BSTR __RPC_FAR *pbstrHelpFile) = 0;
+
+ virtual HRESULT __stdcall IsName(
+ /* [in] */ LPOLESTR szNameBuf,
+ /* [in] */ ULONG lHashVal,
+ /* [out] */ BOOL __RPC_FAR *pfName) = 0;
+
+ virtual HRESULT __stdcall FindName(
+ /* [in] */ LPOLESTR szNameBuf,
+ /* [in] */ ULONG lHashVal,
+ /* [length_is][size_is][out] */ ITypeInfo __RPC_FAR *__RPC_FAR *rgptinfo,
+ /* [length_is][size_is][out] */ MEMBERID __RPC_FAR *rgmemid,
+ /* [out][in] */ USHORT __RPC_FAR *pcFound) = 0;
+
+ virtual void __stdcall ReleaseTLibAttr(
+ /* [in] */ TLIBATTR __RPC_FAR *ptlibattr) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ITypeLibVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ ITypeLib __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ ITypeLib __RPC_FAR * This);
+
+ UINT ( __stdcall __RPC_FAR *GetTypeInfoCount )(
+ ITypeLib __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetTypeInfo )(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppitinfo);
+
+ HRESULT ( __stdcall __RPC_FAR *GetTypeInfoType )(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [out] */ TYPEKIND __RPC_FAR *ptkind);
+
+ HRESULT ( __stdcall __RPC_FAR *GetTypeInfoOfGuid )(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ REFGUID guid,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo);
+
+ HRESULT ( __stdcall __RPC_FAR *GetLibAttr )(
+ ITypeLib __RPC_FAR * This,
+ /* [out] */ TLIBATTR __RPC_FAR *__RPC_FAR *pptlibattr);
+
+ HRESULT ( __stdcall __RPC_FAR *GetTypeComp )(
+ ITypeLib __RPC_FAR * This,
+ /* [out] */ ITypeComp __RPC_FAR *__RPC_FAR *pptcomp);
+
+ HRESULT ( __stdcall __RPC_FAR *GetDocumentation )(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ INT index,
+ /* [out] */ BSTR __RPC_FAR *pbstrName,
+ /* [out] */ BSTR __RPC_FAR *pbstrDocString,
+ /* [out] */ DWORD __RPC_FAR *pdwHelpContext,
+ /* [out] */ BSTR __RPC_FAR *pbstrHelpFile);
+
+ HRESULT ( __stdcall __RPC_FAR *IsName )(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ LPOLESTR szNameBuf,
+ /* [in] */ ULONG lHashVal,
+ /* [out] */ BOOL __RPC_FAR *pfName);
+
+ HRESULT ( __stdcall __RPC_FAR *FindName )(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ LPOLESTR szNameBuf,
+ /* [in] */ ULONG lHashVal,
+ /* [length_is][size_is][out] */ ITypeInfo __RPC_FAR *__RPC_FAR *rgptinfo,
+ /* [length_is][size_is][out] */ MEMBERID __RPC_FAR *rgmemid,
+ /* [out][in] */ USHORT __RPC_FAR *pcFound);
+
+ void ( __stdcall __RPC_FAR *ReleaseTLibAttr )(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ TLIBATTR __RPC_FAR *ptlibattr);
+
+ } ITypeLibVtbl;
+
+ interface ITypeLib
+ {
+ CONST_VTBL struct ITypeLibVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ITypeLib_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define ITypeLib_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define ITypeLib_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define ITypeLib_GetTypeInfoCount(This) \
+ (This)->lpVtbl -> GetTypeInfoCount(This)
+
+#define ITypeLib_GetTypeInfo(This,index,ppitinfo) \
+ (This)->lpVtbl -> GetTypeInfo(This,index,ppitinfo)
+
+#define ITypeLib_GetTypeInfoType(This,index,ptkind) \
+ (This)->lpVtbl -> GetTypeInfoType(This,index,ptkind)
+
+#define ITypeLib_GetTypeInfoOfGuid(This,guid,pptinfo) \
+ (This)->lpVtbl -> GetTypeInfoOfGuid(This,guid,pptinfo)
+
+#define ITypeLib_GetLibAttr(This,pptlibattr) \
+ (This)->lpVtbl -> GetLibAttr(This,pptlibattr)
+
+#define ITypeLib_GetTypeComp(This,pptcomp) \
+ (This)->lpVtbl -> GetTypeComp(This,pptcomp)
+
+#define ITypeLib_GetDocumentation(This,index,pbstrName,pbstrDocString,pdwHelpContext,pbstrHelpFile) \
+ (This)->lpVtbl -> GetDocumentation(This,index,pbstrName,pbstrDocString,pdwHelpContext,pbstrHelpFile)
+
+#define ITypeLib_IsName(This,szNameBuf,lHashVal,pfName) \
+ (This)->lpVtbl -> IsName(This,szNameBuf,lHashVal,pfName)
+
+#define ITypeLib_FindName(This,szNameBuf,lHashVal,rgptinfo,rgmemid,pcFound) \
+ (This)->lpVtbl -> FindName(This,szNameBuf,lHashVal,rgptinfo,rgmemid,pcFound)
+
+#define ITypeLib_ReleaseTLibAttr(This,ptlibattr) \
+ (This)->lpVtbl -> ReleaseTLibAttr(This,ptlibattr)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+UINT __stdcall ITypeLib_GetTypeInfoCount_Proxy(
+ ITypeLib __RPC_FAR * This);
+
+
+void __RPC_STUB ITypeLib_GetTypeInfoCount_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeLib_GetTypeInfo_Proxy(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppitinfo);
+
+
+void __RPC_STUB ITypeLib_GetTypeInfo_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeLib_GetTypeInfoType_Proxy(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ UINT index,
+ /* [out] */ TYPEKIND __RPC_FAR *ptkind);
+
+
+void __RPC_STUB ITypeLib_GetTypeInfoType_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeLib_GetTypeInfoOfGuid_Proxy(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ REFGUID guid,
+ /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *pptinfo);
+
+
+void __RPC_STUB ITypeLib_GetTypeInfoOfGuid_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeLib_GetLibAttr_Proxy(
+ ITypeLib __RPC_FAR * This,
+ /* [out] */ TLIBATTR __RPC_FAR *__RPC_FAR *pptlibattr);
+
+
+void __RPC_STUB ITypeLib_GetLibAttr_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeLib_GetTypeComp_Proxy(
+ ITypeLib __RPC_FAR * This,
+ /* [out] */ ITypeComp __RPC_FAR *__RPC_FAR *pptcomp);
+
+
+void __RPC_STUB ITypeLib_GetTypeComp_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeLib_GetDocumentation_Proxy(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ INT index,
+ /* [out] */ BSTR __RPC_FAR *pbstrName,
+ /* [out] */ BSTR __RPC_FAR *pbstrDocString,
+ /* [out] */ DWORD __RPC_FAR *pdwHelpContext,
+ /* [out] */ BSTR __RPC_FAR *pbstrHelpFile);
+
+
+void __RPC_STUB ITypeLib_GetDocumentation_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeLib_IsName_Proxy(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ LPOLESTR szNameBuf,
+ /* [in] */ ULONG lHashVal,
+ /* [out] */ BOOL __RPC_FAR *pfName);
+
+
+void __RPC_STUB ITypeLib_IsName_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ITypeLib_FindName_Proxy(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ LPOLESTR szNameBuf,
+ /* [in] */ ULONG lHashVal,
+ /* [length_is][size_is][out] */ ITypeInfo __RPC_FAR *__RPC_FAR *rgptinfo,
+ /* [length_is][size_is][out] */ MEMBERID __RPC_FAR *rgmemid,
+ /* [out][in] */ USHORT __RPC_FAR *pcFound);
+
+
+void __RPC_STUB ITypeLib_FindName_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __stdcall ITypeLib_ReleaseTLibAttr_Proxy(
+ ITypeLib __RPC_FAR * This,
+ /* [in] */ TLIBATTR __RPC_FAR *ptlibattr);
+
+
+void __RPC_STUB ITypeLib_ReleaseTLibAttr_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __ITypeLib_INTERFACE_DEFINED__ */
+
+
+#ifndef __IErrorInfo_INTERFACE_DEFINED__
+#define __IErrorInfo_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IErrorInfo
+ * at Fri Apr 28 07:02:38 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [local][unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IErrorInfo __RPC_FAR *LPERRORINFO;
+
+
+EXTERN_C const IID IID_IErrorInfo;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IErrorInfo : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall GetGUID(
+ /* [out] */ GUID __RPC_FAR *pguid) = 0;
+
+ virtual HRESULT __stdcall GetSource(
+ /* [out] */ BSTR __RPC_FAR *pbstrSource) = 0;
+
+ virtual HRESULT __stdcall GetDescription(
+ /* [out] */ BSTR __RPC_FAR *pbstrDescription) = 0;
+
+ virtual HRESULT __stdcall GetHelpFile(
+ /* [out] */ BSTR __RPC_FAR *pbstrHelpFile) = 0;
+
+ virtual HRESULT __stdcall GetHelpContext(
+ /* [out] */ DWORD __RPC_FAR *pdwHelpContext) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IErrorInfoVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IErrorInfo __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IErrorInfo __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IErrorInfo __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetGUID )(
+ IErrorInfo __RPC_FAR * This,
+ /* [out] */ GUID __RPC_FAR *pguid);
+
+ HRESULT ( __stdcall __RPC_FAR *GetSource )(
+ IErrorInfo __RPC_FAR * This,
+ /* [out] */ BSTR __RPC_FAR *pbstrSource);
+
+ HRESULT ( __stdcall __RPC_FAR *GetDescription )(
+ IErrorInfo __RPC_FAR * This,
+ /* [out] */ BSTR __RPC_FAR *pbstrDescription);
+
+ HRESULT ( __stdcall __RPC_FAR *GetHelpFile )(
+ IErrorInfo __RPC_FAR * This,
+ /* [out] */ BSTR __RPC_FAR *pbstrHelpFile);
+
+ HRESULT ( __stdcall __RPC_FAR *GetHelpContext )(
+ IErrorInfo __RPC_FAR * This,
+ /* [out] */ DWORD __RPC_FAR *pdwHelpContext);
+
+ } IErrorInfoVtbl;
+
+ interface IErrorInfo
+ {
+ CONST_VTBL struct IErrorInfoVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IErrorInfo_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IErrorInfo_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IErrorInfo_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IErrorInfo_GetGUID(This,pguid) \
+ (This)->lpVtbl -> GetGUID(This,pguid)
+
+#define IErrorInfo_GetSource(This,pbstrSource) \
+ (This)->lpVtbl -> GetSource(This,pbstrSource)
+
+#define IErrorInfo_GetDescription(This,pbstrDescription) \
+ (This)->lpVtbl -> GetDescription(This,pbstrDescription)
+
+#define IErrorInfo_GetHelpFile(This,pbstrHelpFile) \
+ (This)->lpVtbl -> GetHelpFile(This,pbstrHelpFile)
+
+#define IErrorInfo_GetHelpContext(This,pdwHelpContext) \
+ (This)->lpVtbl -> GetHelpContext(This,pdwHelpContext)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IErrorInfo_GetGUID_Proxy(
+ IErrorInfo __RPC_FAR * This,
+ /* [out] */ GUID __RPC_FAR *pguid);
+
+
+void __RPC_STUB IErrorInfo_GetGUID_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IErrorInfo_GetSource_Proxy(
+ IErrorInfo __RPC_FAR * This,
+ /* [out] */ BSTR __RPC_FAR *pbstrSource);
+
+
+void __RPC_STUB IErrorInfo_GetSource_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IErrorInfo_GetDescription_Proxy(
+ IErrorInfo __RPC_FAR * This,
+ /* [out] */ BSTR __RPC_FAR *pbstrDescription);
+
+
+void __RPC_STUB IErrorInfo_GetDescription_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IErrorInfo_GetHelpFile_Proxy(
+ IErrorInfo __RPC_FAR * This,
+ /* [out] */ BSTR __RPC_FAR *pbstrHelpFile);
+
+
+void __RPC_STUB IErrorInfo_GetHelpFile_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IErrorInfo_GetHelpContext_Proxy(
+ IErrorInfo __RPC_FAR * This,
+ /* [out] */ DWORD __RPC_FAR *pdwHelpContext);
+
+
+void __RPC_STUB IErrorInfo_GetHelpContext_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IErrorInfo_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICreateErrorInfo_INTERFACE_DEFINED__
+#define __ICreateErrorInfo_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: ICreateErrorInfo
+ * at Fri Apr 28 07:02:38 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [local][unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ ICreateErrorInfo __RPC_FAR *LPCREATEERRORINFO;
+
+
+EXTERN_C const IID IID_ICreateErrorInfo;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface ICreateErrorInfo : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall SetGUID(
+ /* [in] */ REFGUID rguid) = 0;
+
+ virtual HRESULT __stdcall SetSource(
+ /* [in] */ LPOLESTR szSource) = 0;
+
+ virtual HRESULT __stdcall SetDescription(
+ /* [in] */ LPOLESTR szDescription) = 0;
+
+ virtual HRESULT __stdcall SetHelpFile(
+ /* [in] */ LPOLESTR szHelpFile) = 0;
+
+ virtual HRESULT __stdcall SetHelpContext(
+ /* [in] */ DWORD dwHelpContext) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ICreateErrorInfoVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ ICreateErrorInfo __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ ICreateErrorInfo __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ ICreateErrorInfo __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *SetGUID )(
+ ICreateErrorInfo __RPC_FAR * This,
+ /* [in] */ REFGUID rguid);
+
+ HRESULT ( __stdcall __RPC_FAR *SetSource )(
+ ICreateErrorInfo __RPC_FAR * This,
+ /* [in] */ LPOLESTR szSource);
+
+ HRESULT ( __stdcall __RPC_FAR *SetDescription )(
+ ICreateErrorInfo __RPC_FAR * This,
+ /* [in] */ LPOLESTR szDescription);
+
+ HRESULT ( __stdcall __RPC_FAR *SetHelpFile )(
+ ICreateErrorInfo __RPC_FAR * This,
+ /* [in] */ LPOLESTR szHelpFile);
+
+ HRESULT ( __stdcall __RPC_FAR *SetHelpContext )(
+ ICreateErrorInfo __RPC_FAR * This,
+ /* [in] */ DWORD dwHelpContext);
+
+ } ICreateErrorInfoVtbl;
+
+ interface ICreateErrorInfo
+ {
+ CONST_VTBL struct ICreateErrorInfoVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ICreateErrorInfo_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define ICreateErrorInfo_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define ICreateErrorInfo_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define ICreateErrorInfo_SetGUID(This,rguid) \
+ (This)->lpVtbl -> SetGUID(This,rguid)
+
+#define ICreateErrorInfo_SetSource(This,szSource) \
+ (This)->lpVtbl -> SetSource(This,szSource)
+
+#define ICreateErrorInfo_SetDescription(This,szDescription) \
+ (This)->lpVtbl -> SetDescription(This,szDescription)
+
+#define ICreateErrorInfo_SetHelpFile(This,szHelpFile) \
+ (This)->lpVtbl -> SetHelpFile(This,szHelpFile)
+
+#define ICreateErrorInfo_SetHelpContext(This,dwHelpContext) \
+ (This)->lpVtbl -> SetHelpContext(This,dwHelpContext)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall ICreateErrorInfo_SetGUID_Proxy(
+ ICreateErrorInfo __RPC_FAR * This,
+ /* [in] */ REFGUID rguid);
+
+
+void __RPC_STUB ICreateErrorInfo_SetGUID_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateErrorInfo_SetSource_Proxy(
+ ICreateErrorInfo __RPC_FAR * This,
+ /* [in] */ LPOLESTR szSource);
+
+
+void __RPC_STUB ICreateErrorInfo_SetSource_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateErrorInfo_SetDescription_Proxy(
+ ICreateErrorInfo __RPC_FAR * This,
+ /* [in] */ LPOLESTR szDescription);
+
+
+void __RPC_STUB ICreateErrorInfo_SetDescription_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateErrorInfo_SetHelpFile_Proxy(
+ ICreateErrorInfo __RPC_FAR * This,
+ /* [in] */ LPOLESTR szHelpFile);
+
+
+void __RPC_STUB ICreateErrorInfo_SetHelpFile_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ICreateErrorInfo_SetHelpContext_Proxy(
+ ICreateErrorInfo __RPC_FAR * This,
+ /* [in] */ DWORD dwHelpContext);
+
+
+void __RPC_STUB ICreateErrorInfo_SetHelpContext_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __ICreateErrorInfo_INTERFACE_DEFINED__ */
+
+
+#ifndef __ISupportErrorInfo_INTERFACE_DEFINED__
+#define __ISupportErrorInfo_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: ISupportErrorInfo
+ * at Fri Apr 28 07:02:38 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [local][unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ ISupportErrorInfo __RPC_FAR *LPSUPPORTERRORINFO;
+
+
+EXTERN_C const IID IID_ISupportErrorInfo;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface ISupportErrorInfo : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall InterfaceSupportsErrorInfo(
+ /* [in] */ REFIID riid) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ISupportErrorInfoVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ ISupportErrorInfo __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ ISupportErrorInfo __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ ISupportErrorInfo __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *InterfaceSupportsErrorInfo )(
+ ISupportErrorInfo __RPC_FAR * This,
+ /* [in] */ REFIID riid);
+
+ } ISupportErrorInfoVtbl;
+
+ interface ISupportErrorInfo
+ {
+ CONST_VTBL struct ISupportErrorInfoVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ISupportErrorInfo_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define ISupportErrorInfo_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define ISupportErrorInfo_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define ISupportErrorInfo_InterfaceSupportsErrorInfo(This,riid) \
+ (This)->lpVtbl -> InterfaceSupportsErrorInfo(This,riid)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall ISupportErrorInfo_InterfaceSupportsErrorInfo_Proxy(
+ ISupportErrorInfo __RPC_FAR * This,
+ /* [in] */ REFIID riid);
+
+
+void __RPC_STUB ISupportErrorInfo_InterfaceSupportsErrorInfo_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __ISupportErrorInfo_INTERFACE_DEFINED__ */
+
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/ole32/stg/props/iprop/oaidl.idl b/private/ole32/stg/props/iprop/oaidl.idl
new file mode 100644
index 000000000..365c60ee9
--- /dev/null
+++ b/private/ole32/stg/props/iprop/oaidl.idl
@@ -0,0 +1,1651 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: oaidl.idl
+//
+//----------------------------------------------------------------------------
+
+#ifndef DO_NO_IMPORTS
+import "objidl.idl";
+#endif
+
+interface ITypeInfo;
+interface ITypeLib;
+interface IErrorInfo;
+interface ICreateErrorInfo;
+interface ISupportErrorInfo;
+
+[
+ version(0.1), pointer_default(unique),
+ local /* marshalling supplied by oleaut32.dll */
+]
+interface RemVariant
+{
+
+cpp_quote("//+-------------------------------------------------------------------------")
+cpp_quote("//")
+cpp_quote("// Microsoft Windows")
+cpp_quote("// Copyright (C) Microsoft Corporation, 1992 - 1995.")
+cpp_quote("//")
+cpp_quote("//--------------------------------------------------------------------------")
+
+#ifndef HUGEP
+# ifdef WIN16
+# define HUGEP _huge
+# else
+# define HUGEP
+# define FAR
+# define FARSTRUCT
+# endif
+#endif
+
+/* Forward Declarations */
+#ifdef HPP
+interface IDispatch;
+interface IStream;
+interface IStorage;
+interface IUnknown;
+#endif
+
+/* IDL declarations for BSTR how to transmit them */
+
+cpp_quote("/* XBSTR is for internal use only, it is subject to change */")
+typedef struct tagXBSTR {
+ ULONG cbSize;
+ [size_is(cbSize)]
+ OLECHAR rgBstrData[];
+ } XBSTR;
+
+typedef OLECHAR FAR* BSTR;
+
+typedef BSTR FAR* LPBSTR;
+
+/* Cairo extension: BLOB, CLIPDATA */
+cpp_quote("#ifndef _tagBLOB_DEFINED")
+cpp_quote("#define _tagBLOB_DEFINED")
+cpp_quote("#define _BLOB_DEFINED")
+cpp_quote("#define _LPBLOB_DEFINED")
+typedef struct tagBLOB {
+ ULONG cbSize;
+ [size_is(cbSize)]
+ BYTE *pBlobData;
+ } BLOB, * LPBLOB;
+cpp_quote("#endif")
+
+cpp_quote("#ifndef _tagCLIPDATA_DEFINED")
+cpp_quote("#define _tagCLIPDATA_DEFINED")
+cpp_quote("#define _CLIPDATA_DEFINED")
+typedef struct tagCLIPDATA {
+ ULONG cbSize; // count that includes sizeof(ulClipFmt)
+ long ulClipFmt; // long to keep alignment
+ [size_is(cbSize-4)]
+ BYTE * pClipData; // cbSize-sizeof(ULONG) bytes of data in clipboard format
+ } CLIPDATA;
+cpp_quote("#endif")
+
+cpp_quote("#ifndef _tagSAFEARRAYBOUND_DEFINED")
+cpp_quote("#define _tagSAFEARRAYBOUND_DEFINED")
+cpp_quote("#define _SAFEARRAYBOUND_DEFINED")
+cpp_quote("#define _LPSAFEARRAYBOUND_DEFINED")
+typedef struct tagSAFEARRAYBOUND {
+ ULONG cElements;
+ LONG lLbound;
+} SAFEARRAYBOUND, * LPSAFEARRAYBOUND;
+cpp_quote("#endif")
+
+
+cpp_quote("#ifndef _tagSAFEARRAY_DEFINED")
+cpp_quote("#define _tagSAFEARRAY_DEFINED")
+cpp_quote("#define _SAFEARRAY_DEFINED")
+cpp_quote("#define _LPSAFEARRAY_DEFINED")
+cpp_quote("#if 0")
+cpp_quote("/* the following is what RPC knows how to remote */")
+typedef struct FARSTRUCT tagSAFEARRAY {
+ unsigned short cDims;
+ unsigned short fFeatures;
+#if defined(_WIN32)
+ unsigned long cbElements;
+ unsigned long cLocks;
+#else
+ unsigned short cbElements;
+ unsigned short cLocks;
+#ifdef _MAC
+ Handle handle;
+#else
+ unsigned long handle; // unused but kept for compatiblity
+#endif
+#endif
+#ifdef LATER
+ void HUGEP* pvData;
+#else
+ BYTE *pvData;
+#endif
+ [size_is(cDims)] SAFEARRAYBOUND rgsabound[];
+} SAFEARRAY, FAR* LPSAFEARRAY;
+cpp_quote("#else")
+cpp_quote("typedef struct FARSTRUCT tagSAFEARRAY {")
+cpp_quote(" unsigned short cDims;")
+cpp_quote(" unsigned short fFeatures;")
+cpp_quote("#if defined(_WIN32)")
+cpp_quote(" unsigned long cbElements;")
+cpp_quote(" unsigned long cLocks;")
+cpp_quote("#else")
+cpp_quote(" unsigned short cbElements;")
+cpp_quote(" unsigned short cLocks;")
+cpp_quote(" unsigned long handle; // unused but kept for compatiblity")
+cpp_quote("#endif")
+cpp_quote(" void HUGEP* pvData;")
+cpp_quote(" SAFEARRAYBOUND rgsabound[1];")
+cpp_quote("} SAFEARRAY, FAR* LPSAFEARRAY;")
+cpp_quote("#endif")
+
+cpp_quote("#endif")
+
+const USHORT FADF_AUTO = 0x0001; /* the array is allocated on the stack */
+const USHORT FADF_STATIC = 0x0002; /* the array is staticly allocated */
+const USHORT FADF_EMBEDDED = 0x0004; /* array is embedded in a structure */
+const USHORT FADF_FIXEDSIZE = 0x0010; /* array may not be resized or reallocated */
+const USHORT FADF_BSTR = 0x0100; /* an array of BSTRs */
+const USHORT FADF_UNKNOWN = 0x0200; /* an array of IUnknown* */
+const USHORT FADF_DISPATCH = 0x0400; /* and array of IDispatch* */
+const USHORT FADF_VARIANT = 0x0800; /* an array of VARIANTs */
+const USHORT FADF_RESERVED = 0xF0E8; /* reserved bits */
+
+typedef double DATE;
+
+/* This is a helper struct for use in handling currency. */
+cpp_quote("#ifndef _tagCY_DEFINED")
+cpp_quote("#define _tagCY_DEFINED")
+cpp_quote("#define _CY_DEFINED")
+
+cpp_quote("#if 0")
+#if 0 // MIDL can't handle this
+cpp_quote("/* the following get a midl-generated tag added, which messes up */")
+cpp_quote("/* unqualified references to the Lo and Hi members under C++ */")
+typedef union tagCY {
+ struct {
+#ifdef _MAC
+ long Hi;
+ long Lo;
+#else
+ unsigned long Lo;
+ long Hi;
+#endif
+ };
+ LONGLONG int64;
+} CY;
+#else //0
+cpp_quote("/* the following isn't the real definition of CY, but it is */")
+cpp_quote("/* what RPC knows how to remote */")
+typedef struct tagCY {
+ LONGLONG int64;
+} CY;
+#endif //0
+cpp_quote("#else")
+
+cpp_quote("/* real definition that makes the C++ compiler happy */")
+cpp_quote("typedef union tagCY {")
+cpp_quote(" struct { ")
+cpp_quote("#ifdef _MAC ")
+cpp_quote(" long Hi;")
+cpp_quote(" long Lo; ")
+cpp_quote("#else ")
+cpp_quote(" unsigned long Lo;")
+cpp_quote(" long Hi;")
+cpp_quote("#endif ")
+cpp_quote(" }; ")
+cpp_quote(" LONGLONG int64; ")
+cpp_quote("} CY; ")
+cpp_quote("#endif")
+
+cpp_quote("#endif")
+
+
+typedef CY CURRENCY;
+
+cpp_quote("/* 0 == FALSE, -1 == TRUE */")
+typedef short VARIANT_BOOL;
+cpp_quote("#ifndef VARIANT_TRUE")
+cpp_quote("#define VARIANT_TRUE ((VARIANT_BOOL)0xffff)")
+cpp_quote("#endif")
+cpp_quote("#ifndef VARIANT_FALSE")
+cpp_quote("#define VARIANT_FALSE ((VARIANT_BOOL)0)")
+cpp_quote("#endif")
+
+
+
+/*
+ * VARENUM usage key,
+ *
+ * [V] - may appear in a VARIANT
+ * [T] - may appear in a TYPEDESC
+ * [P] - may appear in an OLE property set
+ *
+ */
+cpp_quote("#ifndef _VARENUM_DEFINED")
+cpp_quote("#define _VARENUM_DEFINED")
+/*
+ * VARENUM usage key,
+ *
+ * [V] - may appear in a VARIANT
+ * [T] - may appear in a TYPEDESC
+ * [P] - may appear in an OLE property set
+ * [S] - may appear in a Safe Array
+ *
+ */
+cpp_quote("/*")
+cpp_quote(" * VARENUM usage key,")
+cpp_quote(" *")
+cpp_quote(" * * [V] - may appear in a VARIANT")
+cpp_quote(" * * [T] - may appear in a TYPEDESC")
+cpp_quote(" * * [P] - may appear in an OLE property set")
+cpp_quote(" * * [S] - may appear in a Safe Array")
+cpp_quote(" *")
+cpp_quote(" *")
+cpp_quote(" * VT_EMPTY [V] [P] nothing ")
+cpp_quote(" * VT_NULL [V] SQL style Null ")
+cpp_quote(" * VT_I2 [V][T][P][S] 2 byte signed int ")
+cpp_quote(" * VT_I4 [V][T][P][S] 4 byte signed int ")
+cpp_quote(" * VT_R4 [V][T][P][S] 4 byte real ")
+cpp_quote(" * VT_R8 [V][T][P][S] 8 byte real ")
+cpp_quote(" * VT_CY [V][T][P][S] currency ")
+cpp_quote(" * VT_DATE [V][T][P][S] date ")
+cpp_quote(" * VT_BSTR [V][T][P][S] OLE Automation string ")
+cpp_quote(" * VT_DISPATCH [V][T] [S] IDispatch FAR* ")
+cpp_quote(" * VT_ERROR [V][T] [S] SCODE ")
+cpp_quote(" * VT_BOOL [V][T][P][S] True=-1, False=0 ")
+cpp_quote(" * VT_VARIANT [V][T][P][S] VARIANT FAR* ")
+cpp_quote(" * VT_UNKNOWN [V][T] [S] IUnknown FAR* ")
+
+cpp_quote(" * VT_I1 [T] signed char ")
+cpp_quote(" * VT_UI1 [V][T] [S] unsigned char ")
+cpp_quote(" * VT_UI2 [T] unsigned short ")
+cpp_quote(" * VT_UI4 [T] unsigned short ")
+cpp_quote(" * VT_I8 [T][P] signed 64-bit int ")
+cpp_quote(" * VT_UI8 [T] unsigned 64-bit int ")
+cpp_quote(" * VT_INT [T] signed machine int ")
+cpp_quote(" * VT_UINT [T] unsigned machine int ")
+cpp_quote(" * VT_VOID [T] C style void ")
+cpp_quote(" * VT_HRESULT [T] ")
+cpp_quote(" * VT_PTR [T] pointer type ")
+cpp_quote(" * VT_SAFEARRAY [T] (use VT_ARRAY in VARIANT) ")
+cpp_quote(" * VT_CARRAY [T] C style array ")
+cpp_quote(" * VT_USERDEFINED [T] user defined type ")
+cpp_quote(" * VT_LPSTR [T][P] null terminated string ")
+cpp_quote(" * VT_LPWSTR [T][P] wide null terminated string ")
+
+cpp_quote(" * VT_FILETIME [P] FILETIME ")
+cpp_quote(" * VT_BLOB [P] Length prefixed bytes ")
+cpp_quote(" * VT_STREAM [P] Name of the stream follows ")
+cpp_quote(" * VT_STORAGE [P] Name of the storage follows ")
+cpp_quote(" * VT_STREAMED_OBJECT [P] Stream contains an object ")
+cpp_quote(" * VT_STORED_OBJECT [P] Storage contains an object ")
+cpp_quote(" * VT_BLOB_OBJECT [P] Blob contains an object ")
+cpp_quote(" * VT_CF [P] Clipboard format ")
+cpp_quote(" * VT_CLSID [P] A Class ID ")
+
+cpp_quote(" * VT_VECTOR [P] simple counted array ")
+cpp_quote(" * VT_ARRAY [V] SAFEARRAY* ")
+cpp_quote(" * VT_BYREF [V] ")
+cpp_quote(" */")
+
+enum VARENUM
+{
+ VT_EMPTY = 0,
+ VT_NULL = 1,
+ VT_I2 = 2,
+ VT_I4 = 3,
+ VT_R4 = 4,
+ VT_R8 = 5,
+ VT_CY = 6,
+ VT_DATE = 7,
+ VT_BSTR = 8,
+ VT_DISPATCH = 9,
+ VT_ERROR = 10,
+ VT_BOOL = 11,
+ VT_VARIANT = 12,
+ VT_UNKNOWN = 13,
+
+ VT_I1 = 16,
+ VT_UI1 = 17,
+ VT_UI2 = 18,
+ VT_UI4 = 19,
+ VT_I8 = 20,
+ VT_UI8 = 21,
+ VT_INT = 22,
+ VT_UINT = 23,
+ VT_VOID = 24,
+ VT_HRESULT = 25,
+ VT_PTR = 26,
+ VT_SAFEARRAY = 27,
+ VT_CARRAY = 28,
+ VT_USERDEFINED = 29,
+ VT_LPSTR = 30,
+ VT_LPWSTR = 31,
+
+ VT_FILETIME = 64,
+ VT_BLOB = 65,
+ VT_STREAM = 66,
+ VT_STORAGE = 67,
+ VT_STREAMED_OBJECT = 68,
+ VT_STORED_OBJECT = 69,
+ VT_BLOB_OBJECT = 70,
+ VT_CF = 71,
+ VT_CLSID = 72
+};
+cpp_quote("#endif")
+
+
+const USHORT VT_VECTOR = 0x1000;
+const USHORT VT_ARRAY = 0x2000;
+const USHORT VT_BYREF = 0x4000;
+const USHORT VT_RESERVED = 0x8000;
+
+
+cpp_quote("#ifndef _VARTYPE_DEFINED")
+cpp_quote("#define _VARTYPE_DEFINED")
+typedef unsigned short VARTYPE;
+cpp_quote("#endif")
+
+typedef struct tagVARIANT VARIANT;
+
+cpp_quote("/* forward declare IDispatch */")
+cpp_quote("typedef interface IDispatch IDispatch;")
+
+cpp_quote("/* VARIANT STRUCTURE")
+cpp_quote(" *")
+cpp_quote(" * VARTYPE vt;")
+cpp_quote(" * unsigned short wReserved1;")
+cpp_quote(" * unsigned short wReserved2;")
+cpp_quote(" * unsigned short wReserved3;")
+cpp_quote(" * union {")
+cpp_quote(" * unsigned char VT_UI1 ")
+cpp_quote(" * short VT_I2 ")
+cpp_quote(" * long VT_I4 ")
+cpp_quote(" * float VT_R4 ")
+cpp_quote(" * double VT_R8 ")
+cpp_quote(" * VARIANT_BOOL VT_BOOL ")
+cpp_quote(" * SCODE VT_ERROR ")
+cpp_quote(" * CY VT_CY ")
+cpp_quote(" * DATE VT_DATE ")
+cpp_quote(" * BSTR VT_BSTR ")
+cpp_quote(" * IUnknown FAR* VT_UNKNOWN ")
+cpp_quote(" * IDispatch FAR* VT_DISPATCH ")
+cpp_quote(" * SAFEARRAY FAR* VT_ARRAY|* ")
+
+cpp_quote(" * short FAR* VT_BYREF|VT_I2 ")
+cpp_quote(" * long FAR* VT_BYREF|VT_I4 ")
+cpp_quote(" * float FAR* VT_BYREF|VT_R4 ")
+cpp_quote(" * double FAR* VT_BYREF|VT_R8 ")
+cpp_quote(" * VARIANT_BOOL FAR* VT_BYREF|VT_BOOL ")
+cpp_quote(" * SCODE FAR* VT_BYREF|VT_ERROR ")
+cpp_quote(" * CY FAR* VT_BYREF|VT_CY ")
+cpp_quote(" * DATE FAR* VT_BYREF|VT_DATE ")
+cpp_quote(" * BSTR FAR* VT_BYREF|VT_BSTR ")
+cpp_quote(" * IUnknown FAR* FAR* VT_BYREF|VT_UNKNOWN ")
+cpp_quote(" * IDispatch FAR* FAR* VT_BYREF|VT_DISPATCH ")
+cpp_quote(" * SAFEARRAY FAR* FAR* VT_BYREF|VT_ARRAY|* ")
+cpp_quote(" * VARIANT FAR* VT_BYREF|VT_VARIANT ")
+
+cpp_quote(" * void FAR* Generic ByRef ")
+cpp_quote(" */")
+
+cpp_quote("#ifndef _tagVARIANT_DEFINED")
+cpp_quote("#define _tagVARIANT_DEFINED")
+cpp_quote("#if 0")
+cpp_quote("/* the following is what RPC knows how to remote */")
+struct tagVARIANT{
+ VARTYPE vt;
+ WORD wReserved1;
+ WORD wReserved2;
+ WORD wReserved3;
+ [switch_type(unsigned short), switch_is((unsigned short) (vt & 0x1fff))] union
+ {
+[case(VT_I4)] // moved first so you can statically init most of the structure
+ long lVal; /* VT_I4 */
+[case(VT_UI1)]
+ unsigned char bVal; /* VT_UI1 */
+[case(VT_I2)]
+ short iVal; /* VT_I2 */
+[case(VT_R4)]
+ float fltVal; /* VT_R4 */
+[case(VT_R8)]
+ double dblVal; /* VT_R8 */
+[case(VT_BOOL)]
+ VARIANT_BOOL bool; /* VT_BOOL */
+[case(VT_ERROR)]
+ SCODE scode; /* VT_ERROR */
+[case(VT_CY)]
+ CY cyVal; /* VT_CY */
+[case(VT_DATE)]
+ DATE date; /* VT_DATE */
+[case(VT_BSTR)]
+ BSTR bstrVal; /* VT_BSTR */
+
+#if !defined(NO_MARSHAL_INTERFACE)
+[case(VT_UNKNOWN)]
+ IUnknown *punkVal; /* VT_UNKNOWN */
+#endif //!defined(NO_MARSHAL_INTERFACE)
+
+#ifdef HPP
+[case(VT_DISPATCH)]
+ IDispatch *pdispVal; /* VT_DISPATCH */
+#endif
+
+[case(VT_ARRAY)]
+ SAFEARRAY *parray; /* VT_ARRAY|* */
+
+[case(VT_UI1|VT_BYREF)]
+ unsigned char *pbVal; /* VT_BYREF|VT_UI1 */
+[case(VT_I2|VT_BYREF)]
+ short *piVal; /* VT_BYREF|VT_I2 */
+[case(VT_I4|VT_BYREF)]
+ long *plVal; /* VT_BYREF|VT_I4 */
+[case(VT_R4|VT_BYREF)]
+ float *pfltVal; /* VT_BYREF|VT_R4 */
+[case(VT_R8|VT_BYREF)]
+ double *pdblVal; /* VT_BYREF|VT_R8 */
+[case(VT_BOOL|VT_BYREF)]
+ VARIANT_BOOL *pbool; /* VT_BYREF|VT_BOOL */
+[case(VT_ERROR|VT_BYREF)]
+ SCODE *pscode; /* VT_BYREF|VT_ERROR */
+[case(VT_CY|VT_BYREF)]
+ CY *pcyVal; /* VT_BYREF|VT_CY */
+[case(VT_DATE|VT_BYREF)]
+ DATE *pdate; /* VT_BYREF|VT_DATE */
+[case(VT_BSTR|VT_BYREF)]
+ BSTR *pbstrVal; /* VT_BYREF|VT_BSTR */
+
+#if !defined(NO_MARSHAL_INTERFACE)
+[case(VT_UNKNOWN|VT_BYREF)]
+ IUnknown **ppunkVal; /* VT_BYREF|VT_UNKNOWN */
+#endif //!defined(NO_MARSHAL_INTERFACE)
+
+#ifdef HPP
+[case(VT_DISPATCH|VT_BYREF)]
+ IDispatch **ppdispVal; /* VT_BYREF|VT_DISPATCH */
+#endif
+
+[case(VT_ARRAY|VT_BYREF)]
+ SAFEARRAY **pparray; /* VT_BYREF|VT_ARRAY|* */
+[case(VT_VARIANT, VT_VARIANT|VT_BYREF)]
+ VARIANT *pvarVal; /* VT_BYREF|VT_VARIANT */
+[case(VT_BYREF)]
+#ifdef LATER
+ void * byref; /* Generic ByRef */
+#else
+ long * byref; /* form midl likes */
+#endif
+ }
+#if(defined(NONAMELESSUNION))
+ u
+#endif
+ ;
+};
+cpp_quote("#endif")
+
+cpp_quote("struct tagVARIANT{")
+cpp_quote(" VARTYPE vt;")
+cpp_quote(" WORD wReserved1;")
+cpp_quote(" WORD wReserved2;")
+cpp_quote(" WORD wReserved3;")
+cpp_quote(" union")
+cpp_quote(" {")
+cpp_quote(" long lVal; /* VT_I4 */")
+cpp_quote(" unsigned char bVal; /* VT_UI1 */")
+cpp_quote(" short iVal; /* VT_I2 */")
+cpp_quote(" float fltVal; /* VT_R4 */")
+cpp_quote(" double dblVal; /* VT_R8 */")
+cpp_quote(" VARIANT_BOOL bool; /* VT_BOOL */")
+cpp_quote(" SCODE scode; /* VT_ERROR */")
+cpp_quote(" CY cyVal; /* VT_CY */")
+cpp_quote(" DATE date; /* VT_DATE */")
+cpp_quote(" BSTR bstrVal; /* VT_BSTR */")
+cpp_quote(" IUnknown *punkVal; /* VT_UNKNOWN */")
+cpp_quote(" IDispatch *pdispVal; /* VT_DISPATCH */")
+cpp_quote(" SAFEARRAY *parray; /* VT_ARRAY|* */")
+cpp_quote(" unsigned char *pbVal; /* VT_BYREF|VT_UI1 */")
+cpp_quote(" short *piVal; /* VT_BYREF|VT_I2 */")
+cpp_quote(" long *plVal; /* VT_BYREF|VT_I4 */")
+cpp_quote(" float *pfltVal; /* VT_BYREF|VT_R4 */")
+cpp_quote(" double *pdblVal; /* VT_BYREF|VT_R8 */")
+cpp_quote(" VARIANT_BOOL *pbool; /* VT_BYREF|VT_BOOL */")
+cpp_quote(" SCODE *pscode; /* VT_BYREF|VT_ERROR */")
+cpp_quote(" CY *pcyVal; /* VT_BYREF|VT_CY */")
+cpp_quote(" DATE *pdate; /* VT_BYREF|VT_DATE */")
+cpp_quote(" BSTR *pbstrVal; /* VT_BYREF|VT_BSTR */")
+cpp_quote(" IUnknown **ppunkVal; /* VT_BYREF|VT_UNKNOWN */")
+cpp_quote(" IDispatch **ppdispVal; /* VT_BYREF|VT_DISPATCH */")
+cpp_quote(" SAFEARRAY **pparray; /* VT_BYREF|VT_ARRAY|* */")
+cpp_quote(" VARIANT *pvarVal; /* VT_BYREF|VT_VARIANT */")
+cpp_quote(" void * byref; /* Generic ByRef */")
+cpp_quote(" }")
+cpp_quote("#if(defined(NONAMELESSUNION))")
+cpp_quote(" u")
+cpp_quote("#endif")
+cpp_quote(" ;")
+cpp_quote("};")
+
+cpp_quote("#endif")
+
+ cpp_quote("#ifndef _LPVARIANT_DEFINED")
+ cpp_quote("#define _LPVARIANT_DEFINED")
+ typedef struct tagVARIANT * LPVARIANT;
+ cpp_quote("#endif")
+
+ cpp_quote("#ifndef _VARIANTARG_DEFINED")
+ cpp_quote("#define _VARIANTARG_DEFINED")
+ typedef struct tagVARIANT VARIANTARG;
+ cpp_quote("#endif")
+
+ cpp_quote("#ifndef _LPVARIANTARG_DEFINED")
+ cpp_quote("#define _LPVARIANTARG_DEFINED")
+ typedef struct tagVARIANT * LPVARIANTARG;
+ cpp_quote("#endif")
+
+
+
+//TypeInfo stuff.
+
+ cpp_quote("#ifndef _DISPID_DEFINED")
+ cpp_quote("#define _DISPID_DEFINED")
+ typedef LONG DISPID;
+ cpp_quote("#endif")
+
+
+ cpp_quote("#ifndef _MEMBERID_DEFINED")
+ cpp_quote("#define _MEMBERID_DEFINED")
+ typedef DISPID MEMBERID;
+ cpp_quote("#endif")
+
+ cpp_quote("#ifndef _HREFTYPE_DEFINED")
+ cpp_quote("#define _HREFTYPE_DEFINED")
+ typedef DWORD HREFTYPE;
+ cpp_quote("#endif")
+
+// Property stuff
+ typedef ULONG PROPID;
+
+
+typedef [transmit_as(long)] enum tagTYPEKIND
+{
+ TKIND_ENUM = 0,
+ TKIND_RECORD,
+ TKIND_MODULE,
+ TKIND_INTERFACE,
+ TKIND_DISPATCH,
+ TKIND_COCLASS,
+ TKIND_ALIAS,
+ TKIND_UNION,
+ TKIND_MAX /* end of enum marker */
+} TYPEKIND;
+cpp_quote("#define TYPEKIND_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)")
+cpp_quote("#define TYPEKIND_from_xmit(pLong, pEnum) *(pEnum) = (TYPEKIND) *(pLong)")
+cpp_quote("#define TYPEKIND_free_inst(pEnum) ")
+cpp_quote("#define TYPEKIND_free_xmit(pLong) ")
+
+
+
+cpp_quote("#ifndef _tagTYPEDESC_DEFINED")
+cpp_quote("#define _tagTYPEDESC_DEFINED")
+cpp_quote("#define _TYPEDESC_DEFINED")
+
+cpp_quote("/* VT_PTR - lptdesc, the pointed at type */")
+cpp_quote("/* VT_CARRAY - lpadesc */")
+cpp_quote("/* VT_USERDEFINED - hreftype, used to get the UDT typeinfo */")
+
+typedef struct tagTYPEDESC {
+ [switch_type(short), switch_is((short)vt)] union
+ {
+ [case(VT_PTR)] struct tagTYPEDESC * lptdesc;
+ [case(VT_CARRAY)] struct tagARRAYDESC * lpadesc;
+ [case(VT_USERDEFINED)] HREFTYPE hreftype;
+ }
+#if(defined(NONAMELESSUNION))
+ u
+#endif
+ ;
+ VARTYPE vt;
+} TYPEDESC;
+cpp_quote("#endif")
+
+
+cpp_quote("#ifndef _tagARRAYDESC_DEFINED")
+cpp_quote("#define _tagARRAYDESC_DEFINED")
+cpp_quote("#define _ARRAYDESC_DEFINED")
+cpp_quote("#if 0")
+ typedef struct tagARRAYDESC {
+ TYPEDESC tdescElem; /* element type */
+ USHORT cDims; /* dimension count */
+ [size_is(cDims)] SAFEARRAYBOUND rgbounds[]; /* variable length array of bounds */
+ } ARRAYDESC;
+cpp_quote("#else")
+cpp_quote("typedef struct tagARRAYDESC {")
+cpp_quote(" TYPEDESC tdescElem; /* element type */")
+cpp_quote(" USHORT cDims; /* dimension count */")
+cpp_quote(" SAFEARRAYBOUND rgbounds[1]; /* variable length array of bounds */")
+cpp_quote("} ARRAYDESC;")
+cpp_quote("#endif")
+cpp_quote("#endif")
+
+
+cpp_quote("#ifndef _tagIDLDESC_DEFINED")
+cpp_quote("#define _tagIDLDESC_DEFINED")
+cpp_quote("#define _IDLDESC_DEFINED")
+cpp_quote("#define _LPIDLDESC_DEFINED")
+cpp_quote("#ifdef _WIN32")
+typedef struct FARSTRUCT tagIDLDESC {
+#if defined(_WIN32) || defined(_MAC)
+ unsigned long dwReserved;
+#else
+ BSTR bstrIDLInfo; /* reserved, but original name retained for
+ compatibilty */
+#endif
+ unsigned short wIDLFlags; /* IN, OUT, etc */
+} IDLDESC, FAR* LPIDLDESC;
+
+cpp_quote("#else")
+cpp_quote("typedef struct FARSTRUCT tagIDLDESC {")
+cpp_quote("#if defined(_WIN32)")
+cpp_quote(" unsigned long dwReserved;")
+cpp_quote("#else")
+cpp_quote(" BSTR bstrIDLInfo; /* reserved, but original name retained for")
+cpp_quote(" compatibilty */")
+cpp_quote("#endif")
+cpp_quote(" unsigned short wIDLFlags; /* IN, OUT, etc */")
+cpp_quote("} IDLDESC, FAR* LPIDLDESC;")
+cpp_quote("#endif")
+cpp_quote("#endif")
+
+
+cpp_quote("#ifndef _tagELEMDESC_DEFINED")
+cpp_quote("#define _tagELEMDESC_DEFINED")
+cpp_quote("#define _ELEMDESC_DEFINED")
+cpp_quote("#define _LPELEMDESC_DEFINED")
+typedef struct tagELEMDESC {
+ TYPEDESC tdesc; /* the type of the element */
+ IDLDESC idldesc; /* info for remoting the element */
+} ELEMDESC, * LPELEMDESC;
+cpp_quote("#endif")
+
+
+cpp_quote("#ifndef _tagTYPEATTR_DEFINED")
+cpp_quote("#define _tagTYPEATTR_DEFINED")
+cpp_quote("#define _TYPEATTR_DEFINED")
+cpp_quote("#define _LPTYPEATTR_DEFINED")
+typedef struct tagTYPEATTR {
+ GUID guid; /* the GUID of the TypeInfo */
+ LCID lcid; /* locale of member names and doc strings */
+ DWORD dwReserved;
+ MEMBERID memidConstructor; /* ID of constructor, MEMBERID_NIL if none */
+ MEMBERID memidDestructor; /* ID of destructor, MEMBERID_NIL if none */
+ LPOLESTR lpstrSchema;
+ ULONG cbSizeInstance; /* the size of an instance of this type */
+ TYPEKIND typekind; /* the kind of type this typeinfo describes */
+ WORD cFuncs; /* number of functions */
+ WORD cVars; /* number of variables / data members */
+ WORD cImplTypes; /* number of implemented interfaces */
+ WORD cbSizeVft; /* the size of this types virtual func table */
+ WORD cbAlignment; /* specifies the alignment requirements for
+ an instance of this type,
+ 0 = align on 64k boundary
+ 1 = byte align
+ 2 = word align
+ 4 = dword align... */
+ WORD wTypeFlags;
+ WORD wMajorVerNum; /* major version number */
+ WORD wMinorVerNum; /* minor version number */
+ TYPEDESC tdescAlias; /* if typekind == TKIND_ALIAS this field
+ specifies the type for which this type
+ is an alias */
+ IDLDESC idldescType; /* IDL attributes of the described type */
+} TYPEATTR, * LPTYPEATTR;
+cpp_quote("#endif")
+
+
+typedef struct tagDISPPARAMS{
+ [size_is(cArgs)] VARIANTARG * rgvarg;
+ [size_is(cNamedArgs)] DISPID * rgdispidNamedArgs;
+ UINT cArgs;
+ UINT cNamedArgs;
+} DISPPARAMS;
+
+
+typedef struct tagRemEXCEPINFO {
+ WORD wCode; /* An error code describing the error. */
+ WORD wReserved;
+ DWORD dwHelpContext; /* help context of topic within the help file. */
+ DWORD scode;
+ DWORD cSource;
+ DWORD cDescription;
+ DWORD cHelpFile;
+ [size_is(cSource + cDescription + cHelpFile)] OLECHAR strings[]; //Contains bstrSource, bstrDescription, bstrHelpFile.
+} RemEXCEPINFO;
+
+
+cpp_quote("#if 0")
+typedef [transmit_as(RemEXCEPINFO)] struct tagEXCEPINFO {
+ WORD wCode; /* An error code describing the error. */
+ WORD wReserved;
+
+ BSTR bstrSource; /* A textual, human readable name of the
+ source of the exception. It is up to the
+ IDispatch implementor to fill this in.
+ Typically this will be an application name. */
+
+ BSTR bstrDescription; /* A textual, human readable description of the
+ error. If no description is available, NULL
+ should be used. */
+
+ BSTR bstrHelpFile; /* Fully qualified drive, path, and file name
+ of a help file with more information about
+ the error. If no help is available, NULL
+ should be used. */
+
+ DWORD dwHelpContext; /* help context of topic within the help file. */
+
+ [unique] void * pvReserved;
+
+ HRESULT (__stdcall * pfnDeferredFillIn)(struct tagEXCEPINFO *);
+ /* Use of this field allows an application
+ to defer filling in the bstrDescription,
+ bstrHelpFile, and dwHelpContext fields
+ until they are needed. This field might
+ be used, for example, if loading the
+ string for the error is a time-consuming
+ operation. If deferred fill-in is not
+ desired, this field should be set to NULL. */
+
+ SCODE scode;
+} EXCEPINFO, * LPEXCEPINFO;
+cpp_quote("#else")
+cpp_quote("typedef struct tagEXCEPINFO {")
+cpp_quote(" WORD wCode;")
+cpp_quote(" WORD wReserved;")
+cpp_quote(" BSTR bstrSource;")
+cpp_quote(" BSTR bstrDescription;")
+cpp_quote(" BSTR bstrHelpFile;")
+cpp_quote(" DWORD dwHelpContext;")
+cpp_quote(" void __RPC_FAR * pvReserved;")
+cpp_quote(" HRESULT (__stdcall __RPC_FAR * pfnDeferredFillIn)(struct tagEXCEPINFO __RPC_FAR *);")
+cpp_quote(" SCODE scode;")
+cpp_quote("} EXCEPINFO, __RPC_FAR * LPEXCEPINFO;")
+cpp_quote("#endif")
+
+
+typedef [transmit_as(long)] enum tagCALLCONV {
+ CC_CDECL = 1
+ , CC_MSCPASCAL
+ , CC_PASCAL = CC_MSCPASCAL
+ , CC_MACPASCAL
+ , CC_STDCALL
+ , CC_RESERVED
+ , CC_SYSCALL
+ , CC_MPWCDECL
+ , CC_MPWPASCAL
+ , CC_MAX /* end of enum marker */
+#ifdef _MAC
+ , CC_FORCELONG = 2147483647
+#endif
+} CALLCONV;
+
+
+
+
+cpp_quote("#define CALLCONV_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)")
+cpp_quote("#define CALLCONV_from_xmit(pLong, pEnum) *(pEnum) = (CALLCONV) *(pLong)")
+cpp_quote("#define CALLCONV_free_inst(pEnum) ")
+cpp_quote("#define CALLCONV_free_xmit(pLong) ")
+
+
+typedef [transmit_as(long)] enum tagFUNCKIND {
+ FUNC_VIRTUAL,
+ FUNC_PUREVIRTUAL,
+ FUNC_NONVIRTUAL,
+ FUNC_STATIC,
+ FUNC_DISPATCH
+} FUNCKIND;
+cpp_quote("#define FUNCKIND_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)")
+cpp_quote("#define FUNCKIND_from_xmit(pLong, pEnum) *(pEnum) = (FUNCKIND) *(pLong)")
+cpp_quote("#define FUNCKIND_free_inst(pEnum) ")
+cpp_quote("#define FUNCKIND_free_xmit(pLong) ")
+
+
+typedef [transmit_as(long)] enum tagINVOKEKIND {
+ INVOKE_FUNC = 1,
+ INVOKE_PROPERTYGET = 2,
+ INVOKE_PROPERTYPUT = 4,
+ INVOKE_PROPERTYPUTREF = 8
+} INVOKEKIND;
+cpp_quote("#define INVOKEKIND_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)")
+cpp_quote("#define INVOKEKIND_from_xmit(pLong, pEnum) *(pEnum) = (INVOKEKIND) *(pLong)")
+cpp_quote("#define INVOKEKIND_free_inst(pEnum) ")
+cpp_quote("#define INVOKEKIND_free_xmit(pLong) ")
+
+
+typedef struct tagFUNCDESC {
+ MEMBERID memid;
+ [size_is(cScodes)] SCODE * lprgscode;
+ [size_is(cParams)] ELEMDESC * lprgelemdescParam; /* array of parameter types */
+ FUNCKIND funckind;
+ INVOKEKIND invkind;
+ CALLCONV callconv;
+ SHORT cParams;
+ SHORT cParamsOpt;
+ SHORT oVft;
+ SHORT cScodes;
+ ELEMDESC elemdescFunc;
+ WORD wFuncFlags;
+} FUNCDESC, * LPFUNCDESC;
+
+
+typedef [transmit_as(long)] enum tagVARKIND {
+ VAR_PERINSTANCE,
+ VAR_STATIC,
+ VAR_CONST,
+ VAR_DISPATCH
+} VARKIND;
+cpp_quote("#define VARKIND_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)")
+cpp_quote("#define VARKIND_from_xmit(pLong, pEnum) *(pEnum) = (VARKIND) *(pLong)")
+cpp_quote("#define VARKIND_free_inst(pEnum) ")
+cpp_quote("#define VARKIND_free_xmit(pLong) ")
+
+
+
+/* IMPLTYPE Flags */
+const USHORT IMPLTYPEFLAG_FDEFAULT = 0x1;
+const USHORT IMPLTYPEFLAG_FSOURCE = 0x2;
+const USHORT IMPLTYPEFLAG_FRESTRICTED = 0x4;
+
+
+
+
+
+
+typedef struct tagVARDESC {
+ MEMBERID memid;
+ LPOLESTR lpstrSchema;
+ [switch_type(unsigned short), switch_is((unsigned short)varkind)]
+ union
+ {
+ [case(VAR_PERINSTANCE)] ULONG oInst; /* VAR_PERINSTANCE - the offset of this
+ variable within the instance */
+ [case(VAR_CONST)] VARIANT * lpvarValue; /* VAR_CONST - the value of the constant */
+ };
+ ELEMDESC elemdescVar;
+ WORD wVarFlags;
+ VARKIND varkind;
+} VARDESC, * LPVARDESC;
+
+
+cpp_quote("#ifndef _tagTYPEFLAGS_DEFINED")
+cpp_quote("#define _tagTYPEFLAGS_DEFINED")
+cpp_quote("#define _TYPEFLAGS_DEFINED")
+typedef enum tagTYPEFLAGS {
+ TYPEFLAG_FAPPOBJECT = 0x01
+ , TYPEFLAG_FCANCREATE = 0x02
+ , TYPEFLAG_FLICENSED = 0x04
+ , TYPEFLAG_FPREDECLID = 0x08
+ , TYPEFLAG_FHIDDEN = 0x10
+ , TYPEFLAG_FCONTROL = 0x20
+ , TYPEFLAG_FDUAL = 0x40
+ , TYPEFLAG_FNONEXTENSIBLE = 0x80
+ , TYPEFLAG_FOLEAUTOMATION = 0x100
+ , TYPEFLAG_FRESTRICTED = 0x200
+#ifdef _MAC
+ , TYPEFLAG_FORCELONG = 2147483647
+#endif
+} TYPEFLAGS;
+cpp_quote("#endif")
+
+
+
+cpp_quote("#ifndef _tagFUNCFLAGS_DEFINED")
+cpp_quote("#define _tagFUNCFLAGS_DEFINED")
+cpp_quote("#define _FUNCFLAGS_DEFINED")
+typedef enum tagFUNCFLAGS {
+ FUNCFLAG_FRESTRICTED= 1
+ , FUNCFLAG_FSOURCE= 0x2
+ , FUNCFLAG_FBINDABLE= 0x4
+ , FUNCFLAG_FREQUESTEDIT= 0x8
+ , FUNCFLAG_FDISPLAYBIND= 0x10
+ , FUNCFLAG_FDEFAULTBIND= 0x20
+ , FUNCFLAG_FHIDDEN= 0x40
+ , FUNCFLAG_FUSESGETLASTERROR= 0x80
+#ifdef _MAC
+ , FUNCFLAG_FORCELONG = 2147483647
+#endif
+} FUNCFLAGS;
+cpp_quote("#endif")
+
+
+cpp_quote("#ifndef _tagVARFLAGS_DEFINED")
+cpp_quote("#define _tagVARFLAGS_DEFINED")
+cpp_quote("#define _VARFLAGS_DEFINED")
+typedef enum tagVARFLAGS {
+ VARFLAG_FREADONLY = 1
+ , VARFLAG_FSOURCE= 0x2
+ , VARFLAG_FBINDABLE= 0x4
+ , VARFLAG_FREQUESTEDIT= 0x8
+ , VARFLAG_FDISPLAYBIND= 0x10
+ , VARFLAG_FDEFAULTBIND= 0x20
+ , VARFLAG_FHIDDEN = 0x40
+#ifdef _MAC
+ , VARFLAG_FORCELONG = 2147483647
+#endif
+} VARFLAGS;
+cpp_quote("#endif")
+}
+[
+ object,
+ uuid(00020405-0000-0000-C000-000000000046),
+ pointer_default(unique),
+ local /* marshalling supplied by oleaut32.dll */
+]
+
+interface ICreateTypeInfo: IUnknown
+{
+
+ typedef [unique] ICreateTypeInfo *LPCREATETYPEINFO;
+
+
+
+ HRESULT SetGuid(
+ [in] REFGUID guid
+ );
+
+ HRESULT SetTypeFlags(
+ [in] UINT uTypeFlags
+ );
+
+ HRESULT SetDocString(
+ [in] LPOLESTR lpstrDoc
+ );
+
+ HRESULT SetHelpContext(
+ [in] DWORD dwHelpContext
+ );
+
+ HRESULT SetVersion(
+ [in] WORD wMajorVerNum,
+ [in] WORD wMinorVerNum
+ );
+
+ HRESULT AddRefTypeInfo(
+
+ [in] ITypeInfo * ptinfo,
+ [in] HREFTYPE * phreftype
+ );
+
+ HRESULT AddFuncDesc(
+ [in] UINT index,
+ [in] FUNCDESC * pfuncdesc
+ );
+
+ HRESULT AddImplType(
+ [in] UINT index,
+ [in] HREFTYPE hreftype
+ );
+
+ HRESULT SetImplTypeFlags(
+ [in] UINT index,
+ [in] INT impltypeflags
+ );
+
+ HRESULT SetAlignment(
+ [in] WORD cbAlignment
+ );
+
+ HRESULT SetSchema(
+ [in] LPOLESTR lpstrSchema
+ );
+
+ HRESULT AddVarDesc(
+ [in] UINT index,
+ [in] VARDESC * pvardesc
+ );
+
+ HRESULT SetFuncAndParamNames(
+ [in] UINT index,
+ [in, size_is((long) cNames)]
+ [in] LPOLESTR * rgszNames,
+ [in] UINT cNames
+ );
+
+ HRESULT SetVarName(
+ [in] UINT index,
+ [in] LPOLESTR szName
+ );
+
+ HRESULT SetTypeDescAlias(
+ [in] TYPEDESC * ptdescAlias
+ );
+
+ HRESULT DefineFuncAsDllEntry(
+ [in] UINT index,
+ [in] LPOLESTR szDllName,
+ [in] LPOLESTR szProcName
+ );
+
+ HRESULT SetFuncDocString(
+ [in] UINT index,
+ [in] LPOLESTR szDocString
+ );
+
+ HRESULT SetVarDocString(
+ [in] UINT index,
+ [in] LPOLESTR szDocString
+ );
+
+ HRESULT SetFuncHelpContext(
+ [in] UINT index,
+ [in] DWORD dwHelpContext
+ );
+
+ HRESULT SetVarHelpContext(
+ [in] UINT index,
+ [in] DWORD dwHelpContext
+ );
+
+ HRESULT SetMops(
+ [in] UINT index,
+ [in] BSTR bstrMops
+ );
+
+ HRESULT SetTypeIdldesc(
+ [in] IDLDESC * pidldesc
+ );
+
+ HRESULT LayOut(
+ void
+ );
+
+}
+
+
+
+
+[
+ object,
+ uuid(00020406-0000-0000-C000-000000000046),
+ pointer_default(unique),
+ local /* marshalling supplied by oleaut32.dll */
+]
+
+interface ICreateTypeLib : IUnknown
+{
+
+ typedef [unique] ICreateTypeLib *LPCREATETYPELIB;
+
+
+ HRESULT CreateTypeInfo(
+ [in] LPOLESTR szName,
+ [in] TYPEKIND tkind,
+ [out] ICreateTypeInfo **lplpictinfo
+ );
+
+ HRESULT SetName( LPOLESTR szName);
+
+ HRESULT SetVersion
+ (
+ [in] WORD wMajorVerNum,
+ [in] WORD wMinorVerNum
+ );
+
+
+
+
+ HRESULT SetGuid
+ (
+ [in] REFGUID guid
+ );
+
+ HRESULT SetDocString
+ (
+ [in] LPOLESTR szDoc
+ );
+
+
+ HRESULT SetHelpFileName
+ (
+ [in] LPOLESTR szHelpFileName
+ );
+
+ HRESULT SetHelpContext
+ (
+ [in] DWORD dwHelpContext
+ );
+
+ HRESULT SetLcid
+ (
+ [in] LCID lcid
+ );
+
+ HRESULT SetLibFlags
+ (
+ [in] UINT uLibFlags
+ );
+
+
+ HRESULT SaveAllChanges
+ (
+ void
+ );
+
+}
+
+[
+ object,
+ uuid(00020400-0000-0000-C000-000000000046),
+ pointer_default(unique),
+ local /* marshalling supplied by oleaut32.dll */
+]
+
+interface IDispatch : IUnknown
+{
+
+ typedef [unique] IDispatch *LPDISPATCH;
+
+ HRESULT GetTypeInfoCount
+ (
+ [out] UINT *pctinfo
+ );
+
+ HRESULT GetTypeInfo
+ (
+ [in] UINT itinfo,
+ [in] LCID lcid,
+ [out] ITypeInfo ** pptinfo
+ );
+
+ HRESULT GetIDsOfNames
+ (
+ [in] REFIID riid,
+ [in, size_is(cNames)] LPOLESTR *rgszNames,
+ [in] UINT cNames,
+ [in] LCID lcid,
+ [in, out, size_is(cNames)] DISPID *rgdispid
+ );
+
+ HRESULT Invoke
+ (
+ [in] DISPID dispidMember,
+ [in] REFIID riid,
+ [in] LCID lcid,
+ [in] WORD wFlags,
+ [in, unique] DISPPARAMS *pdispparams,
+ [in, out, unique] VARIANT *pvarResult,
+ [out] EXCEPINFO *pexcepinfo,
+ [out] UINT *puArgErr
+ );
+
+cpp_quote("/* DISPID reserved to indicate an \"unknown\" name */")
+cpp_quote("/* only reserved for data members (properties); reused as a method dispid below */")
+ const DISPID DISPID_UNKNOWN = -1;
+
+cpp_quote("/* DISPID reserved for the \"value\" property */")
+ const DISPID DISPID_VALUE = 0;
+
+cpp_quote("/* The following DISPID is reserved to indicate the param")
+cpp_quote(" * that is the right-hand-side (or \"put\" value) of a PropertyPut")
+cpp_quote(" */")
+const DISPID DISPID_PROPERTYPUT = -3;
+
+cpp_quote("/* DISPID reserved for the standard \"NewEnum\" method */")
+const DISPID DISPID_NEWENUM = -4;
+
+cpp_quote("/* DISPID reserved for the standard \"Evaluate\" method */")
+const DISPID DISPID_EVALUATE = -5;
+
+const DISPID DISPID_CONSTRUCTOR = -6;
+
+const DISPID DISPID_DESTRUCTOR = -7;
+
+const DISPID DISPID_COLLECT = -8;
+
+cpp_quote("/* The range -500 through -999 is reserved for Controls */")
+cpp_quote("/* The range 0x80010000 through 0x8001FFFF is reserved for Controls */")
+cpp_quote("/* The remainder of the negative DISPIDs are reserved for future use */")
+
+}
+
+[
+ object,
+ local,
+ uuid(00020404-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IEnumVARIANT : IUnknown
+{
+
+ typedef [unique] IEnumVARIANT* LPENUMVARIANT;
+
+
+ HRESULT Next(
+ [in] unsigned long celt,
+ [out] VARIANT *rgvar,
+ [out] unsigned long *pceltFetched);
+
+ HRESULT Skip(
+ [in] unsigned long celt);
+
+ HRESULT Reset();
+
+ HRESULT Clone(
+ [out] IEnumVARIANT** ppenum);
+
+}
+
+[
+ object,
+ uuid(00020403-0000-0000-C000-000000000046),
+ pointer_default(unique),
+ local /* marshalling supplied by oleaut32.dll */
+]
+
+interface ITypeComp : IUnknown
+{
+
+ typedef [unique] ITypeComp *LPTYPECOMP;
+
+ typedef [v1_enum] enum tagDESCKIND
+ {
+ DESCKIND_NONE = 0,
+ DESCKIND_FUNCDESC,
+ DESCKIND_VARDESC,
+ DESCKIND_TYPECOMP,
+ DESCKIND_IMPLICITAPPOBJ,
+ DESCKIND_MAX
+ } DESCKIND;
+
+ cpp_quote("#define DESCKIND_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)")
+ cpp_quote("#define DESCKIND_from_xmit(pLong, pEnum) *(pEnum) = (DESCKIND) *(pLong)")
+ cpp_quote("#define DESCKIND_free_inst(pEnum) ")
+ cpp_quote("#define DESCKIND_free_xmit(pLong) ")
+
+ [switch_type(long)] union tagBINDPTR
+ {
+ [case(DESCKIND_FUNCDESC)]
+ FUNCDESC *lpfuncdesc;
+
+ [case(DESCKIND_VARDESC)]
+ VARDESC *lpvardesc;
+
+ [case(DESCKIND_TYPECOMP)]
+ [unique] ITypeComp *lptcomp;
+
+ [default]
+ ;
+ };
+
+ typedef union tagBINDPTR BINDPTR;
+ typedef BINDPTR *LPBINDPTR;
+
+ HRESULT Bind
+ (
+ [in] LPOLESTR szName,
+ [in] ULONG lHashVal,
+ [in] WORD fFlags,
+ [out] ITypeInfo **pptinfo,
+ [out] DESCKIND *pdesckind,
+ [out, switch_is((long) *pdesckind)] BINDPTR *pbindptr
+ );
+
+ HRESULT BindType
+ (
+ [in] LPOLESTR szName,
+ [in] ULONG lHashVal,
+ [out] ITypeInfo **pptinfo,
+ [out] ITypeComp **pptcomp
+ );
+}
+
+[
+ object,
+ uuid(00020401-0000-0000-C000-000000000046),
+ pointer_default(unique),
+ local /* marshalling supplied by oleaut32.dll */
+]
+
+interface ITypeInfo : IUnknown
+{
+
+ typedef [unique] ITypeInfo *LPTYPEINFO;
+
+/*---------------------------------------------------------------------*/
+/* ITypeInfo */
+/*---------------------------------------------------------------------*/
+
+ HRESULT GetTypeAttr
+ (
+ [out] TYPEATTR **pptypeattr
+ );
+
+ HRESULT GetTypeComp
+ (
+ [out] ITypeComp **pptcomp
+ );
+
+ HRESULT GetFuncDesc
+ (
+ [in] UINT index,
+ [out] FUNCDESC **pppfuncdesc
+ );
+
+ HRESULT GetVarDesc
+ (
+ [in] UINT index,
+ [out] VARDESC **ppvardesc
+ );
+
+ HRESULT GetNames
+ (
+ [in] MEMBERID memid,
+ [out, size_is(cMaxNames), length_is(*pcNames)] BSTR *rgbstrNames,
+ [in] UINT cMaxNames,
+ [out] UINT *pcNames
+ );
+
+
+ HRESULT GetRefTypeOfImplType
+ (
+ [in] UINT index,
+ [out] HREFTYPE *hpreftype
+ );
+
+
+ HRESULT GetImplTypeFlags
+ (
+ [in] UINT index,
+ [out] INT * pimpltypeflags
+ );
+
+
+
+ HRESULT GetIDsOfNames
+ (
+ [in, size_is(cNames)] OLECHAR **rglpszNames,
+ [in] UINT cNames,
+ [out, size_is(cNames)] MEMBERID *rgmemid
+ );
+
+ HRESULT Invoke
+ (
+ [in, unique] void *pvInstance,
+ [in] MEMBERID memid,
+ [in] WORD wFlags,
+ [in] DISPPARAMS *pdispparams,
+ [out] VARIANT *pvarResult,
+ [out] EXCEPINFO *pexcepinfo,
+ [out] UINT *puArgErr
+ );
+
+ HRESULT GetDocumentation
+ (
+ [in] MEMBERID memid,
+ [out] BSTR *pbstrName,
+ [out] BSTR *pbstrDocString,
+ [out] DWORD *pdwHelpContext,
+ [out] BSTR * pbstrHelpFile
+ );
+
+ HRESULT GetDllEntry
+ (
+ [in] MEMBERID memid,
+ [in] INVOKEKIND invkind,
+ [out] BSTR *pbstrDllName,
+ [out] BSTR *pbstrName,
+ [out] WORD *pwOrdinal
+ );
+
+ HRESULT GetRefTypeInfo
+ (
+ [in] HREFTYPE hreftype,
+ [out] ITypeInfo ** pptinfo
+ );
+
+ HRESULT __stdcall AddressOfMember
+ (
+ [in] MEMBERID memid,
+ [in] INVOKEKIND invkind,
+ [out] void **ppv
+ );
+
+ HRESULT CreateInstance
+ (
+ [in] IUnknown * puncOuter,
+ [in] REFIID riid,
+ [out] void **ppvObj
+ );
+
+ HRESULT GetMops
+ (
+ [in] MEMBERID memid,
+ [out] BSTR *pbstrMops
+ );
+
+ HRESULT GetContainingTypeLib
+ (
+ [out] ITypeLib **pptlib,
+ [out] UINT *pindex
+ );
+
+ void ReleaseTypeAttr
+ (
+ [in] TYPEATTR *ptypeattr
+ );
+
+ void ReleaseFuncDesc
+ (
+ [in] FUNCDESC *pfuncdesc
+ );
+
+ void ReleaseVarDesc
+ (
+ [in] VARDESC *pvardesc
+ );
+}
+
+[
+ object,
+ uuid(00020402-0000-0000-C000-000000000046),
+ pointer_default(unique),
+ local /* marshalling supplied by oleaut32.dll */
+
+]
+
+interface ITypeLib : IUnknown
+{
+
+ typedef [transmit_as(long)] enum tagSYSKIND
+ {
+ SYS_WIN16 = 0,
+ SYS_WIN32,
+ SYS_MAC
+ } SYSKIND;
+
+
+ typedef [transmit_as(long)] enum tagLIBFLAGS
+ {
+ LIBFLAG_FRESTRICTED = 0x01
+ , LIBFLAG_FCONTROL = 0x02
+ , LIBFLAG_FHIDDEN = 0x04
+ } LIBFLAGS;
+
+ // macros to work around a casting problem with midl generated code
+ // and to preserve all 32-bits of the enum value
+ //
+ cpp_quote("#define SYSKIND_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)")
+ cpp_quote("#define SYSKIND_from_xmit(pLong, pEnum) *(pEnum) = (SYSKIND) *(pLong)")
+ cpp_quote("#define SYSKIND_free_inst(pEnum) ")
+ cpp_quote("#define SYSKIND_free_xmit(pLong) ")
+
+
+ typedef [unique] ITypeLib *LPTYPELIB;
+
+ typedef struct tagTLIBATTR
+ {
+ GUID guid;
+ LCID lcid;
+ SYSKIND syskind;
+ WORD wMajorVerNum;
+ WORD wMinorVerNum;
+ WORD wLibFlags;
+ } TLIBATTR;
+
+ typedef TLIBATTR *LPTLIBATTR;
+
+ UINT GetTypeInfoCount
+ (
+ void
+ );
+
+ HRESULT GetTypeInfo
+ (
+ [in] UINT index,
+ [out] ITypeInfo **ppitinfo
+ );
+
+ HRESULT GetTypeInfoType
+ (
+ [in] UINT index,
+ [out] TYPEKIND * ptkind
+ );
+
+ HRESULT GetTypeInfoOfGuid
+ (
+ [in] REFGUID guid,
+ [out] ITypeInfo **pptinfo
+ );
+
+ HRESULT GetLibAttr
+ (
+ [out] TLIBATTR **pptlibattr
+ );
+
+ HRESULT GetTypeComp
+ (
+ [out] ITypeComp **pptcomp
+ );
+
+ HRESULT GetDocumentation
+ (
+ [in] INT index,
+ [out] BSTR *pbstrName,
+ [out] BSTR *pbstrDocString,
+ [out] DWORD *pdwHelpContext,
+ [out] BSTR *pbstrHelpFile
+ );
+
+ HRESULT IsName
+ (
+ [in] LPOLESTR szNameBuf,
+ [in] ULONG lHashVal,
+ [out] BOOL *pfName
+ );
+
+ HRESULT FindName
+ (
+ [in] LPOLESTR szNameBuf,
+ [in] ULONG lHashVal,
+ [out, size_is(*pcFound), length_is(*pcFound)] ITypeInfo ** rgptinfo,
+ [out, size_is(*pcFound), length_is(*pcFound)] MEMBERID * rgmemid,
+ [in, out] USHORT *pcFound
+ );
+
+ void ReleaseTLibAttr
+ (
+ [in] TLIBATTR *ptlibattr
+ );
+
+}
+
+[
+ object,
+ uuid(1CF2B120-547D-101B-8E65-08002B2BD119),
+ pointer_default(unique),
+ local /* marshalling supplied by oleaut32.dll */
+]
+
+interface IErrorInfo: IUnknown
+{
+
+ typedef [unique] IErrorInfo *LPERRORINFO;
+
+ HRESULT GetGUID(
+ [out] GUID FAR* pguid
+ );
+
+ HRESULT GetSource(
+ [out] BSTR FAR* pbstrSource
+ );
+
+ HRESULT GetDescription(
+ [out] BSTR FAR* pbstrDescription
+ );
+
+ HRESULT GetHelpFile(
+ [out] BSTR FAR* pbstrHelpFile
+ );
+
+ HRESULT GetHelpContext(
+ [out] DWORD FAR* pdwHelpContext
+ );
+
+}
+
+[
+ object,
+ uuid(22F03340-547D-101B-8E65-08002B2BD119),
+ pointer_default(unique),
+ local /* marshalling supplied by oleaut32.dll */
+]
+
+interface ICreateErrorInfo: IUnknown
+{
+
+ typedef [unique] ICreateErrorInfo *LPCREATEERRORINFO;
+
+ HRESULT SetGUID(
+ [in] REFGUID rguid
+ );
+
+ HRESULT SetSource(
+ [in] LPOLESTR szSource
+ );
+
+ HRESULT SetDescription(
+ [in] LPOLESTR szDescription
+ );
+
+ HRESULT SetHelpFile(
+ [in] LPOLESTR szHelpFile
+ );
+
+ HRESULT SetHelpContext(
+ [in] DWORD dwHelpContext
+ );
+
+}
+
+[
+ object,
+ uuid(DF0B3D60-548F-101B-8E65-08002B2BD119),
+ pointer_default(unique),
+ local /* marshalling supplied by oleaut32.dll */
+]
+
+interface ISupportErrorInfo: IUnknown
+{
+
+ typedef [unique] ISupportErrorInfo *LPSUPPORTERRORINFO;
+
+ HRESULT InterfaceSupportsErrorInfo(
+ [in] REFIID riid
+ );
+
+}
+
diff --git a/private/ole32/stg/props/iprop/objbase.h b/private/ole32/stg/props/iprop/objbase.h
new file mode 100644
index 000000000..be629513e
--- /dev/null
+++ b/private/ole32/stg/props/iprop/objbase.h
@@ -0,0 +1,594 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: objbase.h
+//
+// Contents: Component object model defintions.
+//
+//----------------------------------------------------------------------------
+
+#ifndef __RPCBASE_H__
+#include "rpcbase.h"
+#endif /* ___RPCBASE_H__ */
+#ifndef NORPC
+#ifndef __RPC_H__
+#include <rpc.h>
+#endif /* ___RPC_H__ */
+#ifndef __RPCNDR_H__
+#include <rpcndr.h>
+#endif /* __RPCNDR_H_ */
+#endif /* NORPC */
+
+#if !defined( _OBJBASE_H_ )
+#define _OBJBASE_H_
+
+#include <pshpack8.h>
+
+// Component Object Model defines, and macros
+
+#ifdef __cplusplus
+ #define EXTERN_C extern "C"
+#else
+ #define EXTERN_C extern
+#endif
+
+#ifdef _WIN32
+
+// Win32 doesn't support __export
+
+#define STDMETHODCALLTYPE __stdcall
+#define STDMETHODVCALLTYPE __cdecl
+
+#define STDAPICALLTYPE __stdcall
+#define STDAPIVCALLTYPE __cdecl
+
+#else
+
+#define STDMETHODCALLTYPE __export __stdcall
+#define STDMETHODVCALLTYPE __export __cdecl
+
+#define STDAPICALLTYPE __export __stdcall
+#define STDAPIVCALLTYPE __export __cdecl
+
+#endif
+
+
+#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE
+#define STDAPI_(type) EXTERN_C type STDAPICALLTYPE
+
+#define STDMETHODIMP HRESULT STDMETHODCALLTYPE
+#define STDMETHODIMP_(type) type STDMETHODCALLTYPE
+
+// The 'V' versions allow Variable Argument lists.
+
+#define STDAPIV EXTERN_C HRESULT STDAPIVCALLTYPE
+#define STDAPIV_(type) EXTERN_C type STDAPIVCALLTYPE
+
+#define STDMETHODIMPV HRESULT STDMETHODVCALLTYPE
+#define STDMETHODIMPV_(type) type STDMETHODVCALLTYPE
+
+#ifdef _OLE32_
+#define WINOLEAPI STDAPI
+#define WINOLEAPI_(type) STDAPI_(type)
+#else
+#define WINOLEAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE
+#define WINOLEAPI_(type) EXTERN_C DECLSPEC_IMPORT type STDAPICALLTYPE
+#endif
+
+/****** Interface Declaration ***********************************************/
+
+/*
+ * These are macros for declaring interfaces. They exist so that
+ * a single definition of the interface is simulataneously a proper
+ * declaration of the interface structures (C++ abstract classes)
+ * for both C and C++.
+ *
+ * DECLARE_INTERFACE(iface) is used to declare an interface that does
+ * not derive from a base interface.
+ * DECLARE_INTERFACE_(iface, baseiface) is used to declare an interface
+ * that does derive from a base interface.
+ *
+ * By default if the source file has a .c extension the C version of
+ * the interface declaratations will be expanded; if it has a .cpp
+ * extension the C++ version will be expanded. if you want to force
+ * the C version expansion even though the source file has a .cpp
+ * extension, then define the macro "CINTERFACE".
+ * eg. cl -DCINTERFACE file.cpp
+ *
+ * Example Interface declaration:
+ *
+ * #undef INTERFACE
+ * #define INTERFACE IClassFactory
+ *
+ * DECLARE_INTERFACE_(IClassFactory, IUnknown)
+ * {
+ * // *** IUnknown methods ***
+ * STDMETHOD(QueryInterface) (THIS_
+ * REFIID riid,
+ * LPVOID FAR* ppvObj) PURE;
+ * STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ * STDMETHOD_(ULONG,Release) (THIS) PURE;
+ *
+ * // *** IClassFactory methods ***
+ * STDMETHOD(CreateInstance) (THIS_
+ * LPUNKNOWN pUnkOuter,
+ * REFIID riid,
+ * LPVOID FAR* ppvObject) PURE;
+ * };
+ *
+ * Example C++ expansion:
+ *
+ * struct FAR IClassFactory : public IUnknown
+ * {
+ * virtual HRESULT STDMETHODCALLTYPE QueryInterface(
+ * IID FAR& riid,
+ * LPVOID FAR* ppvObj) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE AddRef(void) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE Release(void) = 0;
+ * virtual HRESULT STDMETHODCALLTYPE CreateInstance(
+ * LPUNKNOWN pUnkOuter,
+ * IID FAR& riid,
+ * LPVOID FAR* ppvObject) = 0;
+ * };
+ *
+ * NOTE: Our documentation says '#define interface class' but we use
+ * 'struct' instead of 'class' to keep a lot of 'public:' lines
+ * out of the interfaces. The 'FAR' forces the 'this' pointers to
+ * be far, which is what we need.
+ *
+ * Example C expansion:
+ *
+ * typedef struct IClassFactory
+ * {
+ * const struct IClassFactoryVtbl FAR* lpVtbl;
+ * } IClassFactory;
+ *
+ * typedef struct IClassFactoryVtbl IClassFactoryVtbl;
+ *
+ * struct IClassFactoryVtbl
+ * {
+ * HRESULT (STDMETHODCALLTYPE * QueryInterface) (
+ * IClassFactory FAR* This,
+ * IID FAR* riid,
+ * LPVOID FAR* ppvObj) ;
+ * HRESULT (STDMETHODCALLTYPE * AddRef) (IClassFactory FAR* This) ;
+ * HRESULT (STDMETHODCALLTYPE * Release) (IClassFactory FAR* This) ;
+ * HRESULT (STDMETHODCALLTYPE * CreateInstance) (
+ * IClassFactory FAR* This,
+ * LPUNKNOWN pUnkOuter,
+ * IID FAR* riid,
+ * LPVOID FAR* ppvObject);
+ * HRESULT (STDMETHODCALLTYPE * LockServer) (
+ * IClassFactory FAR* This,
+ * BOOL fLock);
+ * };
+ */
+
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+//#define interface struct FAR
+#define interface struct
+#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method
+#define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method
+#define PURE = 0
+#define THIS_
+#define THIS void
+#define DECLARE_INTERFACE(iface) interface iface
+#define DECLARE_INTERFACE_(iface, baseiface) interface iface : public baseiface
+
+
+
+#else
+
+#define interface struct
+
+#define STDMETHOD(method) HRESULT (STDMETHODCALLTYPE * method)
+#define STDMETHOD_(type,method) type (STDMETHODCALLTYPE * method)
+
+
+
+
+#define PURE
+#define THIS_ INTERFACE FAR* This,
+#define THIS INTERFACE FAR* This
+#ifdef CONST_VTABLE
+#define CONST_VTBL const
+#define DECLARE_INTERFACE(iface) typedef interface iface { \
+ const struct iface##Vtbl FAR* lpVtbl; \
+ } iface; \
+ typedef const struct iface##Vtbl iface##Vtbl; \
+ const struct iface##Vtbl
+#else
+#define CONST_VTBL
+#define DECLARE_INTERFACE(iface) typedef interface iface { \
+ struct iface##Vtbl FAR* lpVtbl; \
+ } iface; \
+ typedef struct iface##Vtbl iface##Vtbl; \
+ struct iface##Vtbl
+#endif
+#define DECLARE_INTERFACE_(iface, baseiface) DECLARE_INTERFACE(iface)
+
+#endif
+
+
+
+
+/****** Additional basic types **********************************************/
+
+
+#ifndef FARSTRUCT
+#ifdef __cplusplus
+#define FARSTRUCT FAR
+#else
+#define FARSTRUCT
+#endif // __cplusplus
+#endif // FARSTRUCT
+
+
+
+#ifndef HUGEP
+#ifdef _WIN32
+#define HUGEP
+#else
+#define HUGEP __huge
+#endif // WIN32
+#endif // HUGEP
+
+
+#include <stdlib.h>
+
+#define LISet32(li, v) ((li).HighPart = (v) < 0 ? -1 : 0, (li).LowPart = (v))
+
+#define ULISet32(li, v) ((li).HighPart = 0, (li).LowPart = (v))
+
+
+
+
+
+
+#define CLSCTX_ALL (CLSCTX_INPROC_SERVER| \
+ CLSCTX_INPROC_HANDLER| \
+ CLSCTX_LOCAL_SERVER)
+
+#define CLSCTX_INPROC (CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER)
+
+#define CLSCTX_SERVER (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER)
+
+
+// class registration flags; passed to CoRegisterClassObject
+typedef enum tagREGCLS
+{
+ REGCLS_SINGLEUSE = 0, // class object only generates one instance
+ REGCLS_MULTIPLEUSE = 1, // same class object genereates multiple inst.
+ // and local automatically goes into inproc tbl.
+ REGCLS_MULTI_SEPARATE = 2 // multiple use, but separate control over each
+ // context.
+} REGCLS;
+
+// interface marshaling definitions
+#define MARSHALINTERFACE_MIN 500 // minimum number of bytes for interface marshl
+
+
+//
+// Common typedefs for paramaters used in Storage API's, gleamed from storage.h
+// Also contains Storage error codes, which should be moved into the storage
+// idl files.
+//
+
+
+#define CWCSTORAGENAME 32
+
+/* Storage instantiation modes */
+#define STGM_DIRECT 0x00000000L
+#define STGM_TRANSACTED 0x00010000L
+#define STGM_SIMPLE 0x08000000L
+
+#define STGM_READ 0x00000000L
+#define STGM_WRITE 0x00000001L
+#define STGM_READWRITE 0x00000002L
+
+#define STGM_SHARE_DENY_NONE 0x00000040L
+#define STGM_SHARE_DENY_READ 0x00000030L
+#define STGM_SHARE_DENY_WRITE 0x00000020L
+#define STGM_SHARE_EXCLUSIVE 0x00000010L
+
+#define STGM_PRIORITY 0x00040000L
+#define STGM_DELETEONRELEASE 0x04000000L
+#if (WINVER >= 400)
+#define STGM_NOSCRATCH 0x00100000L
+#endif /* WINVER */
+
+#define STGM_CREATE 0x00001000L
+#define STGM_CONVERT 0x00020000L
+#define STGM_FAILIFTHERE 0x00000000L
+
+
+/* here is where we pull in the MIDL generated headers for the interfaces */
+typedef interface IRpcStubBuffer IRpcStubBuffer;
+typedef interface IRpcChannelBuffer IRpcChannelBuffer;
+
+#ifndef __wtypes_h__
+#include <wtypes.h>
+#endif /* __wtypes_h__ */
+#ifndef __unknwn_h__
+#include <unknwn.h>
+#endif /* __unknwn_h__ */
+#ifndef __objidl_h__
+#include <objidl.h>
+#endif /* __objidl_h__ */
+
+
+// macros to define byte pattern for a GUID.
+// Example: DEFINE_GUID(GUID_XXX, a, b, c, ...);
+//
+// Each dll/exe must initialize the GUIDs once. This is done in one of
+// two ways. If you are not using precompiled headers for the file(s) which
+// initializes the GUIDs, define INITGUID before including objbase.h. This
+// is how OLE builds the initialized versions of the GUIDs which are included
+// in ole2.lib. The GUIDs in ole2.lib are all defined in the same text
+// segment GUID_TEXT.
+//
+// The alternative (which some versions of the compiler don't handle properly;
+// they wind up with the initialized GUIDs in a data, not a text segment),
+// is to use a precompiled version of objbase.h and then include initguid.h
+// after objbase.h followed by one or more of the guid defintion files.
+
+#ifndef INITGUID
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID CDECL FAR name
+#else
+
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ EXTERN_C const GUID CDECL name \
+ = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
+#endif // INITGUID
+
+#define DEFINE_OLEGUID(name, l, w1, w2) \
+ DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)
+
+#ifdef __cplusplus
+inline BOOL IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
+{
+ return !memcmp(&rguid1, &rguid2, sizeof(GUID));
+}
+#else // ! __cplusplus
+#define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID)))
+#endif // __cplusplus
+
+#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2)
+#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2)
+
+#ifdef __cplusplus
+
+// because GUID is defined elsewhere in WIN32 land, the operator == and !=
+// are moved outside the class to global scope.
+
+inline BOOL operator==(const GUID& guidOne, const GUID& guidOther)
+{
+#ifdef _WIN32
+ return !memcmp(&guidOne,&guidOther,sizeof(GUID));
+#else
+ return !_fmemcmp(&guidOne,&guidOther,sizeof(GUID)); }
+#endif
+}
+
+inline BOOL operator!=(const GUID& guidOne, const GUID& guidOther)
+{
+ return !(guidOne == guidOther);
+}
+
+#endif // __cpluscplus
+
+
+#ifndef INITGUID
+#include <cguid.h>
+#endif
+
+
+
+/****** STD Object API Prototypes *****************************************/
+
+WINOLEAPI_(DWORD) CoBuildVersion( VOID );
+
+/* init/uninit */
+
+WINOLEAPI CoInitialize(LPVOID pvReserved);
+WINOLEAPI_(void) CoUninitialize(void);
+WINOLEAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC FAR* ppMalloc);
+WINOLEAPI_(DWORD) CoGetCurrentProcess(void);
+WINOLEAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy);
+WINOLEAPI CoRevokeMallocSpy(void);
+WINOLEAPI CoCreateStandardMalloc(DWORD memctx, IMalloc FAR* FAR* ppMalloc);
+
+#if DBG == 1
+WINOLEAPI_(ULONG) DebugCoGetRpcFault( void );
+WINOLEAPI_(void) DebugCoSetRpcFault( ULONG );
+#endif
+
+/* register/revoke/get class objects */
+
+WINOLEAPI CoGetClassObject(REFCLSID rclsid, DWORD dwClsContext, LPVOID pvReserved,
+ REFIID riid, LPVOID FAR* ppv);
+WINOLEAPI CoRegisterClassObject(REFCLSID rclsid, LPUNKNOWN pUnk,
+ DWORD dwClsContext, DWORD flags, LPDWORD lpdwRegister);
+WINOLEAPI CoRevokeClassObject(DWORD dwRegister);
+
+
+/* marshaling interface pointers */
+
+WINOLEAPI CoGetMarshalSizeMax(ULONG *pulSize, REFIID riid, LPUNKNOWN pUnk,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags);
+WINOLEAPI CoMarshalInterface(LPSTREAM pStm, REFIID riid, LPUNKNOWN pUnk,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags);
+WINOLEAPI CoUnmarshalInterface(LPSTREAM pStm, REFIID riid, LPVOID FAR* ppv);
+WINOLEAPI CoMarshalHresult(LPSTREAM pstm, HRESULT hresult);
+WINOLEAPI CoUnmarshalHresult(LPSTREAM pstm, HRESULT FAR * phresult);
+WINOLEAPI CoReleaseMarshalData(LPSTREAM pStm);
+WINOLEAPI CoDisconnectObject(LPUNKNOWN pUnk, DWORD dwReserved);
+WINOLEAPI CoLockObjectExternal(LPUNKNOWN pUnk, BOOL fLock, BOOL fLastUnlockReleases);
+WINOLEAPI CoGetStandardMarshal(REFIID riid, LPUNKNOWN pUnk,
+ DWORD dwDestContext, LPVOID pvDestContext, DWORD mshlflags,
+ LPMARSHAL FAR* ppMarshal);
+
+WINOLEAPI_(BOOL) CoIsHandlerConnected(LPUNKNOWN pUnk);
+WINOLEAPI_(BOOL) CoHasStrongExternalConnections(LPUNKNOWN pUnk);
+
+// Apartment model inter-thread interface passing helpers
+WINOLEAPI CoMarshalInterThreadInterfaceInStream(REFIID riid, LPUNKNOWN pUnk,
+ LPSTREAM *ppStm);
+
+WINOLEAPI CoGetInterfaceAndReleaseStream(LPSTREAM pStm, REFIID iid,
+ LPVOID FAR* ppv);
+
+WINOLEAPI CoCreateFreeThreadedMarshaler(LPUNKNOWN punkOuter,
+ LPUNKNOWN *ppunkMarshal);
+
+/* dll loading helpers; keeps track of ref counts and unloads all on exit */
+
+WINOLEAPI_(HINSTANCE) CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree);
+WINOLEAPI_(void) CoFreeLibrary(HINSTANCE hInst);
+WINOLEAPI_(void) CoFreeAllLibraries(void);
+WINOLEAPI_(void) CoFreeUnusedLibraries(void);
+
+
+/* helper for creating instances */
+
+WINOLEAPI CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
+ DWORD dwClsContext, REFIID riid, LPVOID FAR* ppv);
+
+
+/* other helpers */
+
+WINOLEAPI StringFromCLSID(REFCLSID rclsid, LPOLESTR FAR* lplpsz);
+WINOLEAPI CLSIDFromString(LPOLESTR lpsz, LPCLSID pclsid);
+WINOLEAPI StringFromIID(REFIID rclsid, LPOLESTR FAR* lplpsz);
+WINOLEAPI IIDFromString(LPOLESTR lpsz, LPIID lpiid);
+WINOLEAPI_(BOOL) CoIsOle1Class(REFCLSID rclsid);
+WINOLEAPI ProgIDFromCLSID (REFCLSID clsid, LPOLESTR FAR* lplpszProgID);
+WINOLEAPI CLSIDFromProgID (LPCOLESTR lpszProgID, LPCLSID lpclsid);
+WINOLEAPI_(int) StringFromGUID2(REFGUID rguid, LPOLESTR lpsz, int cbMax);
+
+WINOLEAPI CoCreateGuid(GUID FAR *pguid);
+
+WINOLEAPI_(BOOL) CoFileTimeToDosDateTime(
+ FILETIME FAR* lpFileTime, LPWORD lpDosDate, LPWORD lpDosTime);
+WINOLEAPI_(BOOL) CoDosDateTimeToFileTime(
+ WORD nDosDate, WORD nDosTime, FILETIME FAR* lpFileTime);
+WINOLEAPI CoFileTimeNow( FILETIME FAR* lpFileTime );
+
+
+WINOLEAPI CoRegisterMessageFilter( LPMESSAGEFILTER lpMessageFilter,
+ LPMESSAGEFILTER FAR* lplpMessageFilter );
+
+
+/* TreatAs APIS */
+
+WINOLEAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID pClsidNew);
+WINOLEAPI CoTreatAsClass(REFCLSID clsidOld, REFCLSID clsidNew);
+
+
+/* the server dlls must define their DllGetClassObject and DllCanUnloadNow
+ * to match these; the typedefs are located here to ensure all are changed at
+ * the same time.
+ */
+
+#ifdef _MAC
+typedef STDAPICALLTYPE HRESULT (* LPFNGETCLASSOBJECT) (REFCLSID, REFIID, LPVOID *);
+#else
+typedef HRESULT (STDAPICALLTYPE * LPFNGETCLASSOBJECT) (REFCLSID, REFIID, LPVOID *);
+#endif
+
+#ifdef _MAC
+typedef STDAPICALLTYPE HRESULT (* LPFNCANUNLOADNOW)(void);
+#else
+typedef HRESULT (STDAPICALLTYPE * LPFNCANUNLOADNOW)(void);
+#endif
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID FAR* ppv);
+
+STDAPI DllCanUnloadNow(void);
+
+
+/****** Default Memory Allocation ******************************************/
+WINOLEAPI_(LPVOID) CoTaskMemAlloc(ULONG cb);
+WINOLEAPI_(LPVOID) CoTaskMemRealloc(LPVOID pv, ULONG cb);
+WINOLEAPI_(void) CoTaskMemFree(LPVOID pv);
+
+/****** DV APIs ***********************************************************/
+
+
+WINOLEAPI CreateDataAdviseHolder(LPDATAADVISEHOLDER FAR* ppDAHolder);
+
+WINOLEAPI CreateDataCache(LPUNKNOWN pUnkOuter, REFCLSID rclsid,
+ REFIID iid, LPVOID FAR* ppv);
+
+
+
+
+/****** Storage API Prototypes ********************************************/
+
+
+WINOLEAPI StgCreateDocfile(const OLECHAR FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+
+WINOLEAPI StgCreateDocfileOnILockBytes(ILockBytes FAR *plkbyt,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+
+WINOLEAPI StgOpenStorage(const OLECHAR FAR* pwcsName,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+WINOLEAPI StgOpenStorageOnILockBytes(ILockBytes FAR *plkbyt,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+
+WINOLEAPI StgIsStorageFile(const OLECHAR FAR* pwcsName);
+WINOLEAPI StgIsStorageILockBytes(ILockBytes FAR* plkbyt);
+
+WINOLEAPI StgSetTimes(OLECHAR const FAR* lpszName,
+ FILETIME const FAR* pctime,
+ FILETIME const FAR* patime,
+ FILETIME const FAR* pmtime);
+
+
+//
+// Moniker APIs
+//
+
+WINOLEAPI BindMoniker(LPMONIKER pmk, DWORD grfOpt, REFIID iidResult, LPVOID FAR* ppvResult);
+WINOLEAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName,
+ ULONG FAR * pchEaten, LPMONIKER FAR * ppmk);
+WINOLEAPI MonikerRelativePathTo(LPMONIKER pmkSrc, LPMONIKER pmkDest, LPMONIKER
+ FAR* ppmkRelPath, BOOL dwReserved);
+WINOLEAPI MonikerCommonPrefixWith(LPMONIKER pmkThis, LPMONIKER pmkOther,
+ LPMONIKER FAR* ppmkCommon);
+WINOLEAPI CreateBindCtx(DWORD reserved, LPBC FAR* ppbc);
+WINOLEAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest,
+ LPMONIKER FAR* ppmkComposite);
+WINOLEAPI GetClassFile (LPCOLESTR szFilename, CLSID FAR* pclsid);
+
+WINOLEAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER FAR* ppmk);
+
+WINOLEAPI CreateItemMoniker(LPCOLESTR lpszDelim, LPCOLESTR lpszItem,
+ LPMONIKER FAR* ppmk);
+WINOLEAPI CreateAntiMoniker(LPMONIKER FAR* ppmk);
+WINOLEAPI CreatePointerMoniker(LPUNKNOWN punk, LPMONIKER FAR* ppmk);
+
+WINOLEAPI GetRunningObjectTable( DWORD reserved, LPRUNNINGOBJECTTABLE FAR* pprot);
+
+#ifndef RC_INVOKED
+#include <poppack.h>
+#endif // RC_INVOKED
+
+#endif // __OBJBASE_H__
diff --git a/private/ole32/stg/props/iprop/objidl.h b/private/ole32/stg/props/iprop/objidl.h
new file mode 100644
index 000000000..d61ef29c1
--- /dev/null
+++ b/private/ole32/stg/props/iprop/objidl.h
@@ -0,0 +1,7741 @@
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+/* File created by MIDL compiler version 2.00.0102 */
+/* at Fri Apr 28 07:02:32 1995
+ */
+//@@MIDL_FILE_HEADING( )
+#ifndef __RPCBASE_H__
+#include "rpcbase.h"
+#endif /* ___RPCBASE_H__ */
+#ifndef NORPC
+#ifndef __RPC_H__
+#include "rpc.h"
+#endif /* ___RPC_H__ */
+#ifndef __RPCNDR_H__
+#include "rpcndr.h"
+#endif /* __RPCNDR_H_ */
+#endif /* NORPC */
+#ifndef COM_NO_WINDOWS_H
+#ifndef _INC_WINDOWS
+#include "windows.h"
+#endif /* _INC_WINDOWS */
+#ifndef _OLE2_H_
+#include "ole2.h"
+#endif /* _OLE2_H_ */
+#endif /*COM_NO_WINDOWS_H*/
+
+#ifndef __objidl_h__
+#define __objidl_h__
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/* Forward Declarations */
+
+#ifndef __IMarshal_FWD_DEFINED__
+#define __IMarshal_FWD_DEFINED__
+typedef interface IMarshal IMarshal;
+#endif /* __IMarshal_FWD_DEFINED__ */
+
+
+#ifndef __IMalloc_FWD_DEFINED__
+#define __IMalloc_FWD_DEFINED__
+typedef interface IMalloc IMalloc;
+#endif /* __IMalloc_FWD_DEFINED__ */
+
+
+#ifndef __IMallocSpy_FWD_DEFINED__
+#define __IMallocSpy_FWD_DEFINED__
+typedef interface IMallocSpy IMallocSpy;
+#endif /* __IMallocSpy_FWD_DEFINED__ */
+
+
+#ifndef __IStdMarshalInfo_FWD_DEFINED__
+#define __IStdMarshalInfo_FWD_DEFINED__
+typedef interface IStdMarshalInfo IStdMarshalInfo;
+#endif /* __IStdMarshalInfo_FWD_DEFINED__ */
+
+
+#ifndef __IExternalConnection_FWD_DEFINED__
+#define __IExternalConnection_FWD_DEFINED__
+typedef interface IExternalConnection IExternalConnection;
+#endif /* __IExternalConnection_FWD_DEFINED__ */
+
+
+#ifndef __IEnumUnknown_FWD_DEFINED__
+#define __IEnumUnknown_FWD_DEFINED__
+typedef interface IEnumUnknown IEnumUnknown;
+#endif /* __IEnumUnknown_FWD_DEFINED__ */
+
+
+#ifndef __IBindCtx_FWD_DEFINED__
+#define __IBindCtx_FWD_DEFINED__
+typedef interface IBindCtx IBindCtx;
+#endif /* __IBindCtx_FWD_DEFINED__ */
+
+
+#ifndef __IEnumMoniker_FWD_DEFINED__
+#define __IEnumMoniker_FWD_DEFINED__
+typedef interface IEnumMoniker IEnumMoniker;
+#endif /* __IEnumMoniker_FWD_DEFINED__ */
+
+
+#ifndef __IRunnableObject_FWD_DEFINED__
+#define __IRunnableObject_FWD_DEFINED__
+typedef interface IRunnableObject IRunnableObject;
+#endif /* __IRunnableObject_FWD_DEFINED__ */
+
+
+#ifndef __IRunningObjectTable_FWD_DEFINED__
+#define __IRunningObjectTable_FWD_DEFINED__
+typedef interface IRunningObjectTable IRunningObjectTable;
+#endif /* __IRunningObjectTable_FWD_DEFINED__ */
+
+
+#ifndef __IPersist_FWD_DEFINED__
+#define __IPersist_FWD_DEFINED__
+typedef interface IPersist IPersist;
+#endif /* __IPersist_FWD_DEFINED__ */
+
+
+#ifndef __IPersistStream_FWD_DEFINED__
+#define __IPersistStream_FWD_DEFINED__
+typedef interface IPersistStream IPersistStream;
+#endif /* __IPersistStream_FWD_DEFINED__ */
+
+
+#ifndef __IMoniker_FWD_DEFINED__
+#define __IMoniker_FWD_DEFINED__
+typedef interface IMoniker IMoniker;
+#endif /* __IMoniker_FWD_DEFINED__ */
+
+
+#ifndef __IROTData_FWD_DEFINED__
+#define __IROTData_FWD_DEFINED__
+typedef interface IROTData IROTData;
+#endif /* __IROTData_FWD_DEFINED__ */
+
+
+#ifndef __IEnumString_FWD_DEFINED__
+#define __IEnumString_FWD_DEFINED__
+typedef interface IEnumString IEnumString;
+#endif /* __IEnumString_FWD_DEFINED__ */
+
+
+#ifndef __IStream_FWD_DEFINED__
+#define __IStream_FWD_DEFINED__
+typedef interface IStream IStream;
+#endif /* __IStream_FWD_DEFINED__ */
+
+
+#ifndef __IEnumSTATSTG_FWD_DEFINED__
+#define __IEnumSTATSTG_FWD_DEFINED__
+typedef interface IEnumSTATSTG IEnumSTATSTG;
+#endif /* __IEnumSTATSTG_FWD_DEFINED__ */
+
+
+#ifndef __IStorage_FWD_DEFINED__
+#define __IStorage_FWD_DEFINED__
+typedef interface IStorage IStorage;
+#endif /* __IStorage_FWD_DEFINED__ */
+
+
+#ifndef __IPersistFile_FWD_DEFINED__
+#define __IPersistFile_FWD_DEFINED__
+typedef interface IPersistFile IPersistFile;
+#endif /* __IPersistFile_FWD_DEFINED__ */
+
+
+#ifndef __IPersistStorage_FWD_DEFINED__
+#define __IPersistStorage_FWD_DEFINED__
+typedef interface IPersistStorage IPersistStorage;
+#endif /* __IPersistStorage_FWD_DEFINED__ */
+
+
+#ifndef __ILockBytes_FWD_DEFINED__
+#define __ILockBytes_FWD_DEFINED__
+typedef interface ILockBytes ILockBytes;
+#endif /* __ILockBytes_FWD_DEFINED__ */
+
+
+#ifndef __IEnumFORMATETC_FWD_DEFINED__
+#define __IEnumFORMATETC_FWD_DEFINED__
+typedef interface IEnumFORMATETC IEnumFORMATETC;
+#endif /* __IEnumFORMATETC_FWD_DEFINED__ */
+
+
+#ifndef __IEnumSTATDATA_FWD_DEFINED__
+#define __IEnumSTATDATA_FWD_DEFINED__
+typedef interface IEnumSTATDATA IEnumSTATDATA;
+#endif /* __IEnumSTATDATA_FWD_DEFINED__ */
+
+
+#ifndef __IRootStorage_FWD_DEFINED__
+#define __IRootStorage_FWD_DEFINED__
+typedef interface IRootStorage IRootStorage;
+#endif /* __IRootStorage_FWD_DEFINED__ */
+
+
+#ifndef __IAdviseSink_FWD_DEFINED__
+#define __IAdviseSink_FWD_DEFINED__
+typedef interface IAdviseSink IAdviseSink;
+#endif /* __IAdviseSink_FWD_DEFINED__ */
+
+
+#ifndef __IAdviseSink2_FWD_DEFINED__
+#define __IAdviseSink2_FWD_DEFINED__
+typedef interface IAdviseSink2 IAdviseSink2;
+#endif /* __IAdviseSink2_FWD_DEFINED__ */
+
+
+#ifndef __IDataObject_FWD_DEFINED__
+#define __IDataObject_FWD_DEFINED__
+typedef interface IDataObject IDataObject;
+#endif /* __IDataObject_FWD_DEFINED__ */
+
+
+#ifndef __IDataAdviseHolder_FWD_DEFINED__
+#define __IDataAdviseHolder_FWD_DEFINED__
+typedef interface IDataAdviseHolder IDataAdviseHolder;
+#endif /* __IDataAdviseHolder_FWD_DEFINED__ */
+
+
+#ifndef __IMessageFilter_FWD_DEFINED__
+#define __IMessageFilter_FWD_DEFINED__
+typedef interface IMessageFilter IMessageFilter;
+#endif /* __IMessageFilter_FWD_DEFINED__ */
+
+
+#ifndef __IRpcChannelBuffer_FWD_DEFINED__
+#define __IRpcChannelBuffer_FWD_DEFINED__
+typedef interface IRpcChannelBuffer IRpcChannelBuffer;
+#endif /* __IRpcChannelBuffer_FWD_DEFINED__ */
+
+
+#ifndef __IRpcProxyBuffer_FWD_DEFINED__
+#define __IRpcProxyBuffer_FWD_DEFINED__
+typedef interface IRpcProxyBuffer IRpcProxyBuffer;
+#endif /* __IRpcProxyBuffer_FWD_DEFINED__ */
+
+
+#ifndef __IRpcStubBuffer_FWD_DEFINED__
+#define __IRpcStubBuffer_FWD_DEFINED__
+typedef interface IRpcStubBuffer IRpcStubBuffer;
+#endif /* __IRpcStubBuffer_FWD_DEFINED__ */
+
+
+#ifndef __IPSFactoryBuffer_FWD_DEFINED__
+#define __IPSFactoryBuffer_FWD_DEFINED__
+typedef interface IPSFactoryBuffer IPSFactoryBuffer;
+#endif /* __IPSFactoryBuffer_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#include "unknwn.h"
+
+void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
+void __RPC_USER MIDL_user_free( void __RPC_FAR * );
+
+/****************************************
+ * Generated header for interface: __MIDL__intf_0000
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [local] */
+
+
+ /* size is 0 */
+
+ /* size is 0 */
+
+ /* size is 0 */
+
+ /* size is 0 */
+
+ /* size is 0 */
+
+ /* size is 0 */
+
+ /* size is 0 */
+
+ /* size is 0 */
+
+ /* size is 0 */
+
+ /* size is 0 */
+
+
+#ifndef NOPROXYSTUB
+extern RPC_IF_HANDLE __MIDL__intf_0000_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL__intf_0000_v0_0_s_ifspec;
+#endif //NOPROXYSTUB
+
+#ifndef __IMarshal_INTERFACE_DEFINED__
+#define __IMarshal_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IMarshal
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+//--------------------------------------------------------------------------
+ /* size is 4 */
+typedef /* [unique] */ IMarshal __RPC_FAR *LPMARSHAL;
+
+
+EXTERN_C const IID IID_IMarshal;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IMarshal : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall GetUnmarshalClass(
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags,
+ /* [out] */ CLSID __RPC_FAR *pCid) = 0;
+
+ virtual HRESULT __stdcall GetMarshalSizeMax(
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags,
+ /* [out] */ DWORD __RPC_FAR *pSize) = 0;
+
+ virtual HRESULT __stdcall MarshalInterface(
+ /* [unique][in] */ IStream __RPC_FAR *pStm,
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags) = 0;
+
+ virtual HRESULT __stdcall UnmarshalInterface(
+ /* [unique][in] */ IStream __RPC_FAR *pStm,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppv) = 0;
+
+ virtual HRESULT __stdcall ReleaseMarshalData(
+ /* [unique][in] */ IStream __RPC_FAR *pStm) = 0;
+
+ virtual HRESULT __stdcall DisconnectObject(
+ /* [in] */ DWORD dwReserved) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IMarshalVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IMarshal __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IMarshal __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IMarshal __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetUnmarshalClass )(
+ IMarshal __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags,
+ /* [out] */ CLSID __RPC_FAR *pCid);
+
+ HRESULT ( __stdcall __RPC_FAR *GetMarshalSizeMax )(
+ IMarshal __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags,
+ /* [out] */ DWORD __RPC_FAR *pSize);
+
+ HRESULT ( __stdcall __RPC_FAR *MarshalInterface )(
+ IMarshal __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pStm,
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags);
+
+ HRESULT ( __stdcall __RPC_FAR *UnmarshalInterface )(
+ IMarshal __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pStm,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppv);
+
+ HRESULT ( __stdcall __RPC_FAR *ReleaseMarshalData )(
+ IMarshal __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pStm);
+
+ HRESULT ( __stdcall __RPC_FAR *DisconnectObject )(
+ IMarshal __RPC_FAR * This,
+ /* [in] */ DWORD dwReserved);
+
+ } IMarshalVtbl;
+
+ interface IMarshal
+ {
+ CONST_VTBL struct IMarshalVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IMarshal_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IMarshal_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IMarshal_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IMarshal_GetUnmarshalClass(This,riid,pv,dwDestContext,pvDestContext,mshlflags,pCid) \
+ (This)->lpVtbl -> GetUnmarshalClass(This,riid,pv,dwDestContext,pvDestContext,mshlflags,pCid)
+
+#define IMarshal_GetMarshalSizeMax(This,riid,pv,dwDestContext,pvDestContext,mshlflags,pSize) \
+ (This)->lpVtbl -> GetMarshalSizeMax(This,riid,pv,dwDestContext,pvDestContext,mshlflags,pSize)
+
+#define IMarshal_MarshalInterface(This,pStm,riid,pv,dwDestContext,pvDestContext,mshlflags) \
+ (This)->lpVtbl -> MarshalInterface(This,pStm,riid,pv,dwDestContext,pvDestContext,mshlflags)
+
+#define IMarshal_UnmarshalInterface(This,pStm,riid,ppv) \
+ (This)->lpVtbl -> UnmarshalInterface(This,pStm,riid,ppv)
+
+#define IMarshal_ReleaseMarshalData(This,pStm) \
+ (This)->lpVtbl -> ReleaseMarshalData(This,pStm)
+
+#define IMarshal_DisconnectObject(This,dwReserved) \
+ (This)->lpVtbl -> DisconnectObject(This,dwReserved)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IMarshal_GetUnmarshalClass_Proxy(
+ IMarshal __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags,
+ /* [out] */ CLSID __RPC_FAR *pCid);
+
+
+void __RPC_STUB IMarshal_GetUnmarshalClass_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMarshal_GetMarshalSizeMax_Proxy(
+ IMarshal __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags,
+ /* [out] */ DWORD __RPC_FAR *pSize);
+
+
+void __RPC_STUB IMarshal_GetMarshalSizeMax_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMarshal_MarshalInterface_Proxy(
+ IMarshal __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pStm,
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ void __RPC_FAR *pv,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [in] */ DWORD mshlflags);
+
+
+void __RPC_STUB IMarshal_MarshalInterface_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMarshal_UnmarshalInterface_Proxy(
+ IMarshal __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pStm,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppv);
+
+
+void __RPC_STUB IMarshal_UnmarshalInterface_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMarshal_ReleaseMarshalData_Proxy(
+ IMarshal __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pStm);
+
+
+void __RPC_STUB IMarshal_ReleaseMarshalData_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMarshal_DisconnectObject_Proxy(
+ IMarshal __RPC_FAR * This,
+ /* [in] */ DWORD dwReserved);
+
+
+void __RPC_STUB IMarshal_DisconnectObject_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif
+
+#endif /* __IMarshal_INTERFACE_DEFINED__ */
+
+
+#ifndef __IMalloc_INTERFACE_DEFINED__
+#define __IMalloc_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IMalloc
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IMalloc __RPC_FAR *LPMALLOC;
+
+
+EXTERN_C const IID IID_IMalloc;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IMalloc : public IUnknown
+ {
+ public:
+ virtual void __RPC_FAR *__stdcall Alloc(
+ /* [in] */ ULONG cb) = 0;
+
+ virtual void __RPC_FAR *__stdcall Realloc(
+ /* [in] */ void __RPC_FAR *pv,
+ /* [in] */ ULONG cb) = 0;
+
+ virtual void __stdcall Free(
+ /* [in] */ void __RPC_FAR *pv) = 0;
+
+ virtual ULONG __stdcall GetSize(
+ /* [in] */ void __RPC_FAR *pv) = 0;
+
+ virtual int __stdcall DidAlloc(
+ void __RPC_FAR *pv) = 0;
+
+ virtual void __stdcall HeapMinimize( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IMallocVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IMalloc __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IMalloc __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IMalloc __RPC_FAR * This);
+
+ void __RPC_FAR *( __stdcall __RPC_FAR *Alloc )(
+ IMalloc __RPC_FAR * This,
+ /* [in] */ ULONG cb);
+
+ void __RPC_FAR *( __stdcall __RPC_FAR *Realloc )(
+ IMalloc __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pv,
+ /* [in] */ ULONG cb);
+
+ void ( __stdcall __RPC_FAR *Free )(
+ IMalloc __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pv);
+
+ ULONG ( __stdcall __RPC_FAR *GetSize )(
+ IMalloc __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pv);
+
+ int ( __stdcall __RPC_FAR *DidAlloc )(
+ IMalloc __RPC_FAR * This,
+ void __RPC_FAR *pv);
+
+ void ( __stdcall __RPC_FAR *HeapMinimize )(
+ IMalloc __RPC_FAR * This);
+
+ } IMallocVtbl;
+
+ interface IMalloc
+ {
+ CONST_VTBL struct IMallocVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IMalloc_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IMalloc_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IMalloc_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IMalloc_Alloc(This,cb) \
+ (This)->lpVtbl -> Alloc(This,cb)
+
+#define IMalloc_Realloc(This,pv,cb) \
+ (This)->lpVtbl -> Realloc(This,pv,cb)
+
+#define IMalloc_Free(This,pv) \
+ (This)->lpVtbl -> Free(This,pv)
+
+#define IMalloc_GetSize(This,pv) \
+ (This)->lpVtbl -> GetSize(This,pv)
+
+#define IMalloc_DidAlloc(This,pv) \
+ (This)->lpVtbl -> DidAlloc(This,pv)
+
+#define IMalloc_HeapMinimize(This) \
+ (This)->lpVtbl -> HeapMinimize(This)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+void __RPC_FAR *__stdcall IMalloc_Alloc_Proxy(
+ IMalloc __RPC_FAR * This,
+ /* [in] */ ULONG cb);
+
+
+void __RPC_STUB IMalloc_Alloc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __RPC_FAR *__stdcall IMalloc_Realloc_Proxy(
+ IMalloc __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pv,
+ /* [in] */ ULONG cb);
+
+
+void __RPC_STUB IMalloc_Realloc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __stdcall IMalloc_Free_Proxy(
+ IMalloc __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pv);
+
+
+void __RPC_STUB IMalloc_Free_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+ULONG __stdcall IMalloc_GetSize_Proxy(
+ IMalloc __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pv);
+
+
+void __RPC_STUB IMalloc_GetSize_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+int __stdcall IMalloc_DidAlloc_Proxy(
+ IMalloc __RPC_FAR * This,
+ void __RPC_FAR *pv);
+
+
+void __RPC_STUB IMalloc_DidAlloc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __stdcall IMalloc_HeapMinimize_Proxy(
+ IMalloc __RPC_FAR * This);
+
+
+void __RPC_STUB IMalloc_HeapMinimize_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IMalloc_INTERFACE_DEFINED__ */
+
+
+#ifndef __IMallocSpy_INTERFACE_DEFINED__
+#define __IMallocSpy_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IMallocSpy
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IMallocSpy __RPC_FAR *LPMALLOCSPY;
+
+
+EXTERN_C const IID IID_IMallocSpy;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IMallocSpy : public IUnknown
+ {
+ public:
+ virtual ULONG __stdcall PreAlloc(
+ /* [in] */ ULONG cbRequest) = 0;
+
+ virtual void __RPC_FAR *__stdcall PostAlloc(
+ /* [in] */ void __RPC_FAR *pActual) = 0;
+
+ virtual void __RPC_FAR *__stdcall PreFree(
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ BOOL fSpyed) = 0;
+
+ virtual void __stdcall PostFree(
+ /* [in] */ BOOL fSpyed) = 0;
+
+ virtual ULONG __stdcall PreRealloc(
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ ULONG cbRequest,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppNewRequest,
+ /* [in] */ BOOL fSpyed) = 0;
+
+ virtual void __RPC_FAR *__stdcall PostRealloc(
+ /* [in] */ void __RPC_FAR *pActual,
+ /* [in] */ BOOL fSpyed) = 0;
+
+ virtual void __RPC_FAR *__stdcall PreGetSize(
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ BOOL fSpyed) = 0;
+
+ virtual ULONG __stdcall PostGetSize(
+ /* [in] */ ULONG cbActual,
+ /* [in] */ BOOL fSpyed) = 0;
+
+ virtual void __RPC_FAR *__stdcall PreDidAlloc(
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ BOOL fSpyed) = 0;
+
+ virtual int __stdcall PostDidAlloc(
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ BOOL fSpyed,
+ /* [in] */ int fActual) = 0;
+
+ virtual void __stdcall PreHeapMinimize( void) = 0;
+
+ virtual void __stdcall PostHeapMinimize( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IMallocSpyVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IMallocSpy __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IMallocSpy __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *PreAlloc )(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ ULONG cbRequest);
+
+ void __RPC_FAR *( __stdcall __RPC_FAR *PostAlloc )(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pActual);
+
+ void __RPC_FAR *( __stdcall __RPC_FAR *PreFree )(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ BOOL fSpyed);
+
+ void ( __stdcall __RPC_FAR *PostFree )(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ BOOL fSpyed);
+
+ ULONG ( __stdcall __RPC_FAR *PreRealloc )(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ ULONG cbRequest,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppNewRequest,
+ /* [in] */ BOOL fSpyed);
+
+ void __RPC_FAR *( __stdcall __RPC_FAR *PostRealloc )(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pActual,
+ /* [in] */ BOOL fSpyed);
+
+ void __RPC_FAR *( __stdcall __RPC_FAR *PreGetSize )(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ BOOL fSpyed);
+
+ ULONG ( __stdcall __RPC_FAR *PostGetSize )(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ ULONG cbActual,
+ /* [in] */ BOOL fSpyed);
+
+ void __RPC_FAR *( __stdcall __RPC_FAR *PreDidAlloc )(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ BOOL fSpyed);
+
+ int ( __stdcall __RPC_FAR *PostDidAlloc )(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ BOOL fSpyed,
+ /* [in] */ int fActual);
+
+ void ( __stdcall __RPC_FAR *PreHeapMinimize )(
+ IMallocSpy __RPC_FAR * This);
+
+ void ( __stdcall __RPC_FAR *PostHeapMinimize )(
+ IMallocSpy __RPC_FAR * This);
+
+ } IMallocSpyVtbl;
+
+ interface IMallocSpy
+ {
+ CONST_VTBL struct IMallocSpyVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IMallocSpy_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IMallocSpy_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IMallocSpy_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IMallocSpy_PreAlloc(This,cbRequest) \
+ (This)->lpVtbl -> PreAlloc(This,cbRequest)
+
+#define IMallocSpy_PostAlloc(This,pActual) \
+ (This)->lpVtbl -> PostAlloc(This,pActual)
+
+#define IMallocSpy_PreFree(This,pRequest,fSpyed) \
+ (This)->lpVtbl -> PreFree(This,pRequest,fSpyed)
+
+#define IMallocSpy_PostFree(This,fSpyed) \
+ (This)->lpVtbl -> PostFree(This,fSpyed)
+
+#define IMallocSpy_PreRealloc(This,pRequest,cbRequest,ppNewRequest,fSpyed) \
+ (This)->lpVtbl -> PreRealloc(This,pRequest,cbRequest,ppNewRequest,fSpyed)
+
+#define IMallocSpy_PostRealloc(This,pActual,fSpyed) \
+ (This)->lpVtbl -> PostRealloc(This,pActual,fSpyed)
+
+#define IMallocSpy_PreGetSize(This,pRequest,fSpyed) \
+ (This)->lpVtbl -> PreGetSize(This,pRequest,fSpyed)
+
+#define IMallocSpy_PostGetSize(This,cbActual,fSpyed) \
+ (This)->lpVtbl -> PostGetSize(This,cbActual,fSpyed)
+
+#define IMallocSpy_PreDidAlloc(This,pRequest,fSpyed) \
+ (This)->lpVtbl -> PreDidAlloc(This,pRequest,fSpyed)
+
+#define IMallocSpy_PostDidAlloc(This,pRequest,fSpyed,fActual) \
+ (This)->lpVtbl -> PostDidAlloc(This,pRequest,fSpyed,fActual)
+
+#define IMallocSpy_PreHeapMinimize(This) \
+ (This)->lpVtbl -> PreHeapMinimize(This)
+
+#define IMallocSpy_PostHeapMinimize(This) \
+ (This)->lpVtbl -> PostHeapMinimize(This)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+ULONG __stdcall IMallocSpy_PreAlloc_Proxy(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ ULONG cbRequest);
+
+
+void __RPC_STUB IMallocSpy_PreAlloc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __RPC_FAR *__stdcall IMallocSpy_PostAlloc_Proxy(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pActual);
+
+
+void __RPC_STUB IMallocSpy_PostAlloc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __RPC_FAR *__stdcall IMallocSpy_PreFree_Proxy(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ BOOL fSpyed);
+
+
+void __RPC_STUB IMallocSpy_PreFree_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __stdcall IMallocSpy_PostFree_Proxy(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ BOOL fSpyed);
+
+
+void __RPC_STUB IMallocSpy_PostFree_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+ULONG __stdcall IMallocSpy_PreRealloc_Proxy(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ ULONG cbRequest,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppNewRequest,
+ /* [in] */ BOOL fSpyed);
+
+
+void __RPC_STUB IMallocSpy_PreRealloc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __RPC_FAR *__stdcall IMallocSpy_PostRealloc_Proxy(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pActual,
+ /* [in] */ BOOL fSpyed);
+
+
+void __RPC_STUB IMallocSpy_PostRealloc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __RPC_FAR *__stdcall IMallocSpy_PreGetSize_Proxy(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ BOOL fSpyed);
+
+
+void __RPC_STUB IMallocSpy_PreGetSize_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+ULONG __stdcall IMallocSpy_PostGetSize_Proxy(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ ULONG cbActual,
+ /* [in] */ BOOL fSpyed);
+
+
+void __RPC_STUB IMallocSpy_PostGetSize_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __RPC_FAR *__stdcall IMallocSpy_PreDidAlloc_Proxy(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ BOOL fSpyed);
+
+
+void __RPC_STUB IMallocSpy_PreDidAlloc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+int __stdcall IMallocSpy_PostDidAlloc_Proxy(
+ IMallocSpy __RPC_FAR * This,
+ /* [in] */ void __RPC_FAR *pRequest,
+ /* [in] */ BOOL fSpyed,
+ /* [in] */ int fActual);
+
+
+void __RPC_STUB IMallocSpy_PostDidAlloc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __stdcall IMallocSpy_PreHeapMinimize_Proxy(
+ IMallocSpy __RPC_FAR * This);
+
+
+void __RPC_STUB IMallocSpy_PreHeapMinimize_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __stdcall IMallocSpy_PostHeapMinimize_Proxy(
+ IMallocSpy __RPC_FAR * This);
+
+
+void __RPC_STUB IMallocSpy_PostHeapMinimize_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif //NOPROXYSTUB
+
+#endif /* __IMallocSpy_INTERFACE_DEFINED__ */
+
+
+#ifndef __IStdMarshalInfo_INTERFACE_DEFINED__
+#define __IStdMarshalInfo_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IStdMarshalInfo
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IStdMarshalInfo __RPC_FAR *LPSTDMARSHALINFO;
+
+
+EXTERN_C const IID IID_IStdMarshalInfo;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IStdMarshalInfo : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall GetClassForHandler(
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [out] */ CLSID __RPC_FAR *pClsid) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IStdMarshalInfoVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IStdMarshalInfo __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IStdMarshalInfo __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IStdMarshalInfo __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetClassForHandler )(
+ IStdMarshalInfo __RPC_FAR * This,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [out] */ CLSID __RPC_FAR *pClsid);
+
+ } IStdMarshalInfoVtbl;
+
+ interface IStdMarshalInfo
+ {
+ CONST_VTBL struct IStdMarshalInfoVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IStdMarshalInfo_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IStdMarshalInfo_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IStdMarshalInfo_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IStdMarshalInfo_GetClassForHandler(This,dwDestContext,pvDestContext,pClsid) \
+ (This)->lpVtbl -> GetClassForHandler(This,dwDestContext,pvDestContext,pClsid)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IStdMarshalInfo_GetClassForHandler_Proxy(
+ IStdMarshalInfo __RPC_FAR * This,
+ /* [in] */ DWORD dwDestContext,
+ /* [unique][in] */ void __RPC_FAR *pvDestContext,
+ /* [out] */ CLSID __RPC_FAR *pClsid);
+
+
+void __RPC_STUB IStdMarshalInfo_GetClassForHandler_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif
+
+#endif /* __IStdMarshalInfo_INTERFACE_DEFINED__ */
+
+
+#ifndef __IExternalConnection_INTERFACE_DEFINED__
+#define __IExternalConnection_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IExternalConnection
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][local][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IExternalConnection __RPC_FAR *LPEXTERNALCONNECTION;
+
+ /* size is 2 */
+typedef
+enum tagEXTCONN
+ { EXTCONN_STRONG = 0x1,
+ EXTCONN_WEAK = 0x2,
+ EXTCONN_CALLABLE = 0x4
+ } EXTCONN;
+
+
+EXTERN_C const IID IID_IExternalConnection;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IExternalConnection : public IUnknown
+ {
+ public:
+ virtual DWORD __stdcall AddConnection(
+ /* [in] */ DWORD extconn,
+ /* [in] */ DWORD reserved) = 0;
+
+ virtual DWORD __stdcall ReleaseConnection(
+ /* [in] */ DWORD extconn,
+ /* [in] */ DWORD reserved,
+ /* [in] */ BOOL fLastReleaseCloses) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IExternalConnectionVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IExternalConnection __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IExternalConnection __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IExternalConnection __RPC_FAR * This);
+
+ DWORD ( __stdcall __RPC_FAR *AddConnection )(
+ IExternalConnection __RPC_FAR * This,
+ /* [in] */ DWORD extconn,
+ /* [in] */ DWORD reserved);
+
+ DWORD ( __stdcall __RPC_FAR *ReleaseConnection )(
+ IExternalConnection __RPC_FAR * This,
+ /* [in] */ DWORD extconn,
+ /* [in] */ DWORD reserved,
+ /* [in] */ BOOL fLastReleaseCloses);
+
+ } IExternalConnectionVtbl;
+
+ interface IExternalConnection
+ {
+ CONST_VTBL struct IExternalConnectionVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IExternalConnection_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IExternalConnection_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IExternalConnection_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IExternalConnection_AddConnection(This,extconn,reserved) \
+ (This)->lpVtbl -> AddConnection(This,extconn,reserved)
+
+#define IExternalConnection_ReleaseConnection(This,extconn,reserved,fLastReleaseCloses) \
+ (This)->lpVtbl -> ReleaseConnection(This,extconn,reserved,fLastReleaseCloses)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+DWORD __stdcall IExternalConnection_AddConnection_Proxy(
+ IExternalConnection __RPC_FAR * This,
+ /* [in] */ DWORD extconn,
+ /* [in] */ DWORD reserved);
+
+
+void __RPC_STUB IExternalConnection_AddConnection_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+DWORD __stdcall IExternalConnection_ReleaseConnection_Proxy(
+ IExternalConnection __RPC_FAR * This,
+ /* [in] */ DWORD extconn,
+ /* [in] */ DWORD reserved,
+ /* [in] */ BOOL fLastReleaseCloses);
+
+
+void __RPC_STUB IExternalConnection_ReleaseConnection_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif //NOPROXYSTUB
+
+#endif /* __IExternalConnection_INTERFACE_DEFINED__ */
+
+
+#ifndef __IEnumUnknown_INTERFACE_DEFINED__
+#define __IEnumUnknown_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IEnumUnknown
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IEnumUnknown __RPC_FAR *LPENUMUNKNOWN;
+
+
+EXTERN_C const IID IID_IEnumUnknown;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IEnumUnknown : public IUnknown
+ {
+ public:
+ virtual /* [local] */ HRESULT __stdcall Next(
+ /* [in] */ ULONG celt,
+ /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched) = 0;
+
+ virtual HRESULT __stdcall Skip(
+ /* [in] */ ULONG celt) = 0;
+
+ virtual HRESULT __stdcall Reset( void) = 0;
+
+ virtual HRESULT __stdcall Clone(
+ /* [out] */ IEnumUnknown __RPC_FAR *__RPC_FAR *ppenum) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IEnumUnknownVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IEnumUnknown __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IEnumUnknown __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IEnumUnknown __RPC_FAR * This);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *Next )(
+ IEnumUnknown __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+ HRESULT ( __stdcall __RPC_FAR *Skip )(
+ IEnumUnknown __RPC_FAR * This,
+ /* [in] */ ULONG celt);
+
+ HRESULT ( __stdcall __RPC_FAR *Reset )(
+ IEnumUnknown __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Clone )(
+ IEnumUnknown __RPC_FAR * This,
+ /* [out] */ IEnumUnknown __RPC_FAR *__RPC_FAR *ppenum);
+
+ } IEnumUnknownVtbl;
+
+ interface IEnumUnknown
+ {
+ CONST_VTBL struct IEnumUnknownVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IEnumUnknown_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IEnumUnknown_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IEnumUnknown_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IEnumUnknown_Next(This,celt,rgelt,pceltFetched) \
+ (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched)
+
+#define IEnumUnknown_Skip(This,celt) \
+ (This)->lpVtbl -> Skip(This,celt)
+
+#define IEnumUnknown_Reset(This) \
+ (This)->lpVtbl -> Reset(This)
+
+#define IEnumUnknown_Clone(This,ppenum) \
+ (This)->lpVtbl -> Clone(This,ppenum)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [call_as] */ HRESULT __stdcall IEnumUnknown_RemoteNext_Proxy(
+ IEnumUnknown __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+
+void __RPC_STUB IEnumUnknown_RemoteNext_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumUnknown_Skip_Proxy(
+ IEnumUnknown __RPC_FAR * This,
+ /* [in] */ ULONG celt);
+
+
+void __RPC_STUB IEnumUnknown_Skip_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumUnknown_Reset_Proxy(
+ IEnumUnknown __RPC_FAR * This);
+
+
+void __RPC_STUB IEnumUnknown_Reset_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumUnknown_Clone_Proxy(
+ IEnumUnknown __RPC_FAR * This,
+ /* [out] */ IEnumUnknown __RPC_FAR *__RPC_FAR *ppenum);
+
+
+void __RPC_STUB IEnumUnknown_Clone_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif
+
+#endif /* __IEnumUnknown_INTERFACE_DEFINED__ */
+
+
+#ifndef __IBindCtx_INTERFACE_DEFINED__
+#define __IBindCtx_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IBindCtx
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IBindCtx __RPC_FAR *LPBC;
+
+ /* size is 4 */
+typedef /* [unique] */ IBindCtx __RPC_FAR *LPBINDCTX;
+
+ /* size is 16 */
+typedef struct tagBIND_OPTS
+ {
+ DWORD cbStruct;
+ DWORD grfFlags;
+ DWORD grfMode;
+ DWORD dwTickCountDeadline;
+ } BIND_OPTS;
+
+ /* size is 4 */
+typedef struct tagBIND_OPTS __RPC_FAR *LPBIND_OPTS;
+
+ /* size is 2 */
+typedef
+enum tagBIND_FLAGS
+ { BIND_MAYBOTHERUSER = 1,
+ BIND_JUSTTESTEXISTENCE = 2
+ } BIND_FLAGS;
+
+
+EXTERN_C const IID IID_IBindCtx;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IBindCtx : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall RegisterObjectBound(
+ /* [unique][in] */ IUnknown __RPC_FAR *punk) = 0;
+
+ virtual HRESULT __stdcall RevokeObjectBound(
+ /* [unique][in] */ IUnknown __RPC_FAR *punk) = 0;
+
+ virtual HRESULT __stdcall ReleaseBoundObjects( void) = 0;
+
+ virtual HRESULT __stdcall SetBindOptions(
+ /* [in] */ BIND_OPTS __RPC_FAR *pbindopts) = 0;
+
+ virtual HRESULT __stdcall GetBindOptions(
+ /* [out][in] */ BIND_OPTS __RPC_FAR *pbindopts) = 0;
+
+ virtual HRESULT __stdcall GetRunningObjectTable(
+ /* [out] */ IRunningObjectTable __RPC_FAR *__RPC_FAR *pprot) = 0;
+
+ virtual HRESULT __stdcall RegisterObjectParam(
+ /* [in] */ LPOLESTR pszKey,
+ /* [unique][in] */ IUnknown __RPC_FAR *punk) = 0;
+
+ virtual HRESULT __stdcall GetObjectParam(
+ /* [in] */ LPOLESTR pszKey,
+ /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunk) = 0;
+
+ virtual HRESULT __stdcall EnumObjectParam(
+ /* [out] */ IEnumString __RPC_FAR *__RPC_FAR *ppenum) = 0;
+
+ virtual HRESULT __stdcall RevokeObjectParam(
+ /* [in] */ LPOLESTR pszKey) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IBindCtxVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IBindCtx __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IBindCtx __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IBindCtx __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *RegisterObjectBound )(
+ IBindCtx __RPC_FAR * This,
+ /* [unique][in] */ IUnknown __RPC_FAR *punk);
+
+ HRESULT ( __stdcall __RPC_FAR *RevokeObjectBound )(
+ IBindCtx __RPC_FAR * This,
+ /* [unique][in] */ IUnknown __RPC_FAR *punk);
+
+ HRESULT ( __stdcall __RPC_FAR *ReleaseBoundObjects )(
+ IBindCtx __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *SetBindOptions )(
+ IBindCtx __RPC_FAR * This,
+ /* [in] */ BIND_OPTS __RPC_FAR *pbindopts);
+
+ HRESULT ( __stdcall __RPC_FAR *GetBindOptions )(
+ IBindCtx __RPC_FAR * This,
+ /* [out][in] */ BIND_OPTS __RPC_FAR *pbindopts);
+
+ HRESULT ( __stdcall __RPC_FAR *GetRunningObjectTable )(
+ IBindCtx __RPC_FAR * This,
+ /* [out] */ IRunningObjectTable __RPC_FAR *__RPC_FAR *pprot);
+
+ HRESULT ( __stdcall __RPC_FAR *RegisterObjectParam )(
+ IBindCtx __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszKey,
+ /* [unique][in] */ IUnknown __RPC_FAR *punk);
+
+ HRESULT ( __stdcall __RPC_FAR *GetObjectParam )(
+ IBindCtx __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszKey,
+ /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunk);
+
+ HRESULT ( __stdcall __RPC_FAR *EnumObjectParam )(
+ IBindCtx __RPC_FAR * This,
+ /* [out] */ IEnumString __RPC_FAR *__RPC_FAR *ppenum);
+
+ HRESULT ( __stdcall __RPC_FAR *RevokeObjectParam )(
+ IBindCtx __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszKey);
+
+ } IBindCtxVtbl;
+
+ interface IBindCtx
+ {
+ CONST_VTBL struct IBindCtxVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IBindCtx_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IBindCtx_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IBindCtx_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IBindCtx_RegisterObjectBound(This,punk) \
+ (This)->lpVtbl -> RegisterObjectBound(This,punk)
+
+#define IBindCtx_RevokeObjectBound(This,punk) \
+ (This)->lpVtbl -> RevokeObjectBound(This,punk)
+
+#define IBindCtx_ReleaseBoundObjects(This) \
+ (This)->lpVtbl -> ReleaseBoundObjects(This)
+
+#define IBindCtx_SetBindOptions(This,pbindopts) \
+ (This)->lpVtbl -> SetBindOptions(This,pbindopts)
+
+#define IBindCtx_GetBindOptions(This,pbindopts) \
+ (This)->lpVtbl -> GetBindOptions(This,pbindopts)
+
+#define IBindCtx_GetRunningObjectTable(This,pprot) \
+ (This)->lpVtbl -> GetRunningObjectTable(This,pprot)
+
+#define IBindCtx_RegisterObjectParam(This,pszKey,punk) \
+ (This)->lpVtbl -> RegisterObjectParam(This,pszKey,punk)
+
+#define IBindCtx_GetObjectParam(This,pszKey,ppunk) \
+ (This)->lpVtbl -> GetObjectParam(This,pszKey,ppunk)
+
+#define IBindCtx_EnumObjectParam(This,ppenum) \
+ (This)->lpVtbl -> EnumObjectParam(This,ppenum)
+
+#define IBindCtx_RevokeObjectParam(This,pszKey) \
+ (This)->lpVtbl -> RevokeObjectParam(This,pszKey)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IBindCtx_RegisterObjectBound_Proxy(
+ IBindCtx __RPC_FAR * This,
+ /* [unique][in] */ IUnknown __RPC_FAR *punk);
+
+
+void __RPC_STUB IBindCtx_RegisterObjectBound_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IBindCtx_RevokeObjectBound_Proxy(
+ IBindCtx __RPC_FAR * This,
+ /* [unique][in] */ IUnknown __RPC_FAR *punk);
+
+
+void __RPC_STUB IBindCtx_RevokeObjectBound_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IBindCtx_ReleaseBoundObjects_Proxy(
+ IBindCtx __RPC_FAR * This);
+
+
+void __RPC_STUB IBindCtx_ReleaseBoundObjects_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IBindCtx_SetBindOptions_Proxy(
+ IBindCtx __RPC_FAR * This,
+ /* [in] */ BIND_OPTS __RPC_FAR *pbindopts);
+
+
+void __RPC_STUB IBindCtx_SetBindOptions_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IBindCtx_GetBindOptions_Proxy(
+ IBindCtx __RPC_FAR * This,
+ /* [out][in] */ BIND_OPTS __RPC_FAR *pbindopts);
+
+
+void __RPC_STUB IBindCtx_GetBindOptions_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IBindCtx_GetRunningObjectTable_Proxy(
+ IBindCtx __RPC_FAR * This,
+ /* [out] */ IRunningObjectTable __RPC_FAR *__RPC_FAR *pprot);
+
+
+void __RPC_STUB IBindCtx_GetRunningObjectTable_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IBindCtx_RegisterObjectParam_Proxy(
+ IBindCtx __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszKey,
+ /* [unique][in] */ IUnknown __RPC_FAR *punk);
+
+
+void __RPC_STUB IBindCtx_RegisterObjectParam_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IBindCtx_GetObjectParam_Proxy(
+ IBindCtx __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszKey,
+ /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunk);
+
+
+void __RPC_STUB IBindCtx_GetObjectParam_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IBindCtx_EnumObjectParam_Proxy(
+ IBindCtx __RPC_FAR * This,
+ /* [out] */ IEnumString __RPC_FAR *__RPC_FAR *ppenum);
+
+
+void __RPC_STUB IBindCtx_EnumObjectParam_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IBindCtx_RevokeObjectParam_Proxy(
+ IBindCtx __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszKey);
+
+
+void __RPC_STUB IBindCtx_RevokeObjectParam_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif //NOPROXYSTUB
+
+#endif /* __IBindCtx_INTERFACE_DEFINED__ */
+
+
+#ifndef __IEnumMoniker_INTERFACE_DEFINED__
+#define __IEnumMoniker_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IEnumMoniker
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IEnumMoniker __RPC_FAR *LPENUMMONIKER;
+
+
+EXTERN_C const IID IID_IEnumMoniker;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IEnumMoniker : public IUnknown
+ {
+ public:
+ virtual /* [local] */ HRESULT __stdcall Next(
+ /* [in] */ ULONG celt,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched) = 0;
+
+ virtual HRESULT __stdcall Skip(
+ /* [in] */ ULONG celt) = 0;
+
+ virtual HRESULT __stdcall Reset( void) = 0;
+
+ virtual HRESULT __stdcall Clone(
+ /* [out] */ IEnumMoniker __RPC_FAR *__RPC_FAR *ppenum) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IEnumMonikerVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IEnumMoniker __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IEnumMoniker __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IEnumMoniker __RPC_FAR * This);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *Next )(
+ IEnumMoniker __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+ HRESULT ( __stdcall __RPC_FAR *Skip )(
+ IEnumMoniker __RPC_FAR * This,
+ /* [in] */ ULONG celt);
+
+ HRESULT ( __stdcall __RPC_FAR *Reset )(
+ IEnumMoniker __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Clone )(
+ IEnumMoniker __RPC_FAR * This,
+ /* [out] */ IEnumMoniker __RPC_FAR *__RPC_FAR *ppenum);
+
+ } IEnumMonikerVtbl;
+
+ interface IEnumMoniker
+ {
+ CONST_VTBL struct IEnumMonikerVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IEnumMoniker_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IEnumMoniker_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IEnumMoniker_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IEnumMoniker_Next(This,celt,rgelt,pceltFetched) \
+ (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched)
+
+#define IEnumMoniker_Skip(This,celt) \
+ (This)->lpVtbl -> Skip(This,celt)
+
+#define IEnumMoniker_Reset(This) \
+ (This)->lpVtbl -> Reset(This)
+
+#define IEnumMoniker_Clone(This,ppenum) \
+ (This)->lpVtbl -> Clone(This,ppenum)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [call_as] */ HRESULT __stdcall IEnumMoniker_RemoteNext_Proxy(
+ IEnumMoniker __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ IMoniker __RPC_FAR *__RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+
+void __RPC_STUB IEnumMoniker_RemoteNext_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumMoniker_Skip_Proxy(
+ IEnumMoniker __RPC_FAR * This,
+ /* [in] */ ULONG celt);
+
+
+void __RPC_STUB IEnumMoniker_Skip_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumMoniker_Reset_Proxy(
+ IEnumMoniker __RPC_FAR * This);
+
+
+void __RPC_STUB IEnumMoniker_Reset_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumMoniker_Clone_Proxy(
+ IEnumMoniker __RPC_FAR * This,
+ /* [out] */ IEnumMoniker __RPC_FAR *__RPC_FAR *ppenum);
+
+
+void __RPC_STUB IEnumMoniker_Clone_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif //NOPROXYSTUB
+
+#endif /* __IEnumMoniker_INTERFACE_DEFINED__ */
+
+
+#ifndef __IRunnableObject_INTERFACE_DEFINED__
+#define __IRunnableObject_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IRunnableObject
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IRunnableObject __RPC_FAR *LPRUNNABLEOBJECT;
+
+
+EXTERN_C const IID IID_IRunnableObject;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IRunnableObject : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall GetRunningClass(
+ /* [out] */ LPCLSID lpClsid) = 0;
+
+ virtual HRESULT __stdcall Run(
+ /* [in] */ LPBINDCTX pbc) = 0;
+
+ virtual BOOL __stdcall IsRunning( void) = 0;
+
+ virtual HRESULT __stdcall LockRunning(
+ /* [in] */ BOOL fLock,
+ /* [in] */ BOOL fLastUnlockCloses) = 0;
+
+ virtual HRESULT __stdcall SetContainedObject(
+ /* [in] */ BOOL fContained) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IRunnableObjectVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IRunnableObject __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IRunnableObject __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IRunnableObject __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetRunningClass )(
+ IRunnableObject __RPC_FAR * This,
+ /* [out] */ LPCLSID lpClsid);
+
+ HRESULT ( __stdcall __RPC_FAR *Run )(
+ IRunnableObject __RPC_FAR * This,
+ /* [in] */ LPBINDCTX pbc);
+
+ BOOL ( __stdcall __RPC_FAR *IsRunning )(
+ IRunnableObject __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *LockRunning )(
+ IRunnableObject __RPC_FAR * This,
+ /* [in] */ BOOL fLock,
+ /* [in] */ BOOL fLastUnlockCloses);
+
+ HRESULT ( __stdcall __RPC_FAR *SetContainedObject )(
+ IRunnableObject __RPC_FAR * This,
+ /* [in] */ BOOL fContained);
+
+ } IRunnableObjectVtbl;
+
+ interface IRunnableObject
+ {
+ CONST_VTBL struct IRunnableObjectVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IRunnableObject_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IRunnableObject_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IRunnableObject_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IRunnableObject_GetRunningClass(This,lpClsid) \
+ (This)->lpVtbl -> GetRunningClass(This,lpClsid)
+
+#define IRunnableObject_Run(This,pbc) \
+ (This)->lpVtbl -> Run(This,pbc)
+
+#define IRunnableObject_IsRunning(This) \
+ (This)->lpVtbl -> IsRunning(This)
+
+#define IRunnableObject_LockRunning(This,fLock,fLastUnlockCloses) \
+ (This)->lpVtbl -> LockRunning(This,fLock,fLastUnlockCloses)
+
+#define IRunnableObject_SetContainedObject(This,fContained) \
+ (This)->lpVtbl -> SetContainedObject(This,fContained)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IRunnableObject_GetRunningClass_Proxy(
+ IRunnableObject __RPC_FAR * This,
+ /* [out] */ LPCLSID lpClsid);
+
+
+void __RPC_STUB IRunnableObject_GetRunningClass_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRunnableObject_Run_Proxy(
+ IRunnableObject __RPC_FAR * This,
+ /* [in] */ LPBINDCTX pbc);
+
+
+void __RPC_STUB IRunnableObject_Run_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+BOOL __stdcall IRunnableObject_IsRunning_Proxy(
+ IRunnableObject __RPC_FAR * This);
+
+
+void __RPC_STUB IRunnableObject_IsRunning_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRunnableObject_LockRunning_Proxy(
+ IRunnableObject __RPC_FAR * This,
+ /* [in] */ BOOL fLock,
+ /* [in] */ BOOL fLastUnlockCloses);
+
+
+void __RPC_STUB IRunnableObject_LockRunning_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRunnableObject_SetContainedObject_Proxy(
+ IRunnableObject __RPC_FAR * This,
+ /* [in] */ BOOL fContained);
+
+
+void __RPC_STUB IRunnableObject_SetContainedObject_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif
+
+#endif /* __IRunnableObject_INTERFACE_DEFINED__ */
+
+
+#ifndef __IRunningObjectTable_INTERFACE_DEFINED__
+#define __IRunningObjectTable_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IRunningObjectTable
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IRunningObjectTable __RPC_FAR *LPRUNNINGOBJECTTABLE;
+
+
+EXTERN_C const IID IID_IRunningObjectTable;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IRunningObjectTable : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall Register(
+ /* [in] */ DWORD grfFlags,
+ /* [unique][in] */ IUnknown __RPC_FAR *punkObject,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkObjectName,
+ /* [out] */ DWORD __RPC_FAR *pdwRegister) = 0;
+
+ virtual HRESULT __stdcall Revoke(
+ /* [in] */ DWORD dwRegister) = 0;
+
+ virtual HRESULT __stdcall IsRunning(
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkObjectName) = 0;
+
+ virtual HRESULT __stdcall GetObject(
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkObjectName,
+ /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkObject) = 0;
+
+ virtual HRESULT __stdcall NoteChangeTime(
+ /* [in] */ DWORD dwRegister,
+ /* [in] */ FILETIME __RPC_FAR *pfiletime) = 0;
+
+ virtual HRESULT __stdcall GetTimeOfLastChange(
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkObjectName,
+ /* [out] */ FILETIME __RPC_FAR *pfiletime) = 0;
+
+ virtual HRESULT __stdcall EnumRunning(
+ /* [out] */ IEnumMoniker __RPC_FAR *__RPC_FAR *ppenumMoniker) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IRunningObjectTableVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IRunningObjectTable __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IRunningObjectTable __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Register )(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [in] */ DWORD grfFlags,
+ /* [unique][in] */ IUnknown __RPC_FAR *punkObject,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkObjectName,
+ /* [out] */ DWORD __RPC_FAR *pdwRegister);
+
+ HRESULT ( __stdcall __RPC_FAR *Revoke )(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [in] */ DWORD dwRegister);
+
+ HRESULT ( __stdcall __RPC_FAR *IsRunning )(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkObjectName);
+
+ HRESULT ( __stdcall __RPC_FAR *GetObject )(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkObjectName,
+ /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkObject);
+
+ HRESULT ( __stdcall __RPC_FAR *NoteChangeTime )(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [in] */ DWORD dwRegister,
+ /* [in] */ FILETIME __RPC_FAR *pfiletime);
+
+ HRESULT ( __stdcall __RPC_FAR *GetTimeOfLastChange )(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkObjectName,
+ /* [out] */ FILETIME __RPC_FAR *pfiletime);
+
+ HRESULT ( __stdcall __RPC_FAR *EnumRunning )(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [out] */ IEnumMoniker __RPC_FAR *__RPC_FAR *ppenumMoniker);
+
+ } IRunningObjectTableVtbl;
+
+ interface IRunningObjectTable
+ {
+ CONST_VTBL struct IRunningObjectTableVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IRunningObjectTable_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IRunningObjectTable_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IRunningObjectTable_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IRunningObjectTable_Register(This,grfFlags,punkObject,pmkObjectName,pdwRegister) \
+ (This)->lpVtbl -> Register(This,grfFlags,punkObject,pmkObjectName,pdwRegister)
+
+#define IRunningObjectTable_Revoke(This,dwRegister) \
+ (This)->lpVtbl -> Revoke(This,dwRegister)
+
+#define IRunningObjectTable_IsRunning(This,pmkObjectName) \
+ (This)->lpVtbl -> IsRunning(This,pmkObjectName)
+
+#define IRunningObjectTable_GetObject(This,pmkObjectName,ppunkObject) \
+ (This)->lpVtbl -> GetObject(This,pmkObjectName,ppunkObject)
+
+#define IRunningObjectTable_NoteChangeTime(This,dwRegister,pfiletime) \
+ (This)->lpVtbl -> NoteChangeTime(This,dwRegister,pfiletime)
+
+#define IRunningObjectTable_GetTimeOfLastChange(This,pmkObjectName,pfiletime) \
+ (This)->lpVtbl -> GetTimeOfLastChange(This,pmkObjectName,pfiletime)
+
+#define IRunningObjectTable_EnumRunning(This,ppenumMoniker) \
+ (This)->lpVtbl -> EnumRunning(This,ppenumMoniker)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IRunningObjectTable_Register_Proxy(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [in] */ DWORD grfFlags,
+ /* [unique][in] */ IUnknown __RPC_FAR *punkObject,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkObjectName,
+ /* [out] */ DWORD __RPC_FAR *pdwRegister);
+
+
+void __RPC_STUB IRunningObjectTable_Register_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRunningObjectTable_Revoke_Proxy(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [in] */ DWORD dwRegister);
+
+
+void __RPC_STUB IRunningObjectTable_Revoke_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRunningObjectTable_IsRunning_Proxy(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkObjectName);
+
+
+void __RPC_STUB IRunningObjectTable_IsRunning_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRunningObjectTable_GetObject_Proxy(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkObjectName,
+ /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunkObject);
+
+
+void __RPC_STUB IRunningObjectTable_GetObject_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRunningObjectTable_NoteChangeTime_Proxy(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [in] */ DWORD dwRegister,
+ /* [in] */ FILETIME __RPC_FAR *pfiletime);
+
+
+void __RPC_STUB IRunningObjectTable_NoteChangeTime_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRunningObjectTable_GetTimeOfLastChange_Proxy(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkObjectName,
+ /* [out] */ FILETIME __RPC_FAR *pfiletime);
+
+
+void __RPC_STUB IRunningObjectTable_GetTimeOfLastChange_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRunningObjectTable_EnumRunning_Proxy(
+ IRunningObjectTable __RPC_FAR * This,
+ /* [out] */ IEnumMoniker __RPC_FAR *__RPC_FAR *ppenumMoniker);
+
+
+void __RPC_STUB IRunningObjectTable_EnumRunning_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif
+
+#endif /* __IRunningObjectTable_INTERFACE_DEFINED__ */
+
+
+#ifndef __IPersist_INTERFACE_DEFINED__
+#define __IPersist_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IPersist
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IPersist __RPC_FAR *LPPERSIST;
+
+
+EXTERN_C const IID IID_IPersist;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IPersist : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall GetClassID(
+ /* [out] */ CLSID __RPC_FAR *pClassID) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IPersistVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IPersist __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IPersist __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IPersist __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetClassID )(
+ IPersist __RPC_FAR * This,
+ /* [out] */ CLSID __RPC_FAR *pClassID);
+
+ } IPersistVtbl;
+
+ interface IPersist
+ {
+ CONST_VTBL struct IPersistVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IPersist_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IPersist_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IPersist_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IPersist_GetClassID(This,pClassID) \
+ (This)->lpVtbl -> GetClassID(This,pClassID)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IPersist_GetClassID_Proxy(
+ IPersist __RPC_FAR * This,
+ /* [out] */ CLSID __RPC_FAR *pClassID);
+
+
+void __RPC_STUB IPersist_GetClassID_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif //NOPROXYSTUB
+
+#endif /* __IPersist_INTERFACE_DEFINED__ */
+
+
+#ifndef __IPersistStream_INTERFACE_DEFINED__
+#define __IPersistStream_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IPersistStream
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IPersistStream __RPC_FAR *LPPERSISTSTREAM;
+
+
+EXTERN_C const IID IID_IPersistStream;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IPersistStream : public IPersist
+ {
+ public:
+ virtual HRESULT __stdcall IsDirty( void) = 0;
+
+ virtual HRESULT __stdcall Load(
+ /* [unique][in] */ IStream __RPC_FAR *pStm) = 0;
+
+ virtual HRESULT __stdcall Save(
+ /* [unique][in] */ IStream __RPC_FAR *pStm,
+ /* [in] */ BOOL fClearDirty) = 0;
+
+ virtual HRESULT __stdcall GetSizeMax(
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbSize) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IPersistStreamVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IPersistStream __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IPersistStream __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IPersistStream __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetClassID )(
+ IPersistStream __RPC_FAR * This,
+ /* [out] */ CLSID __RPC_FAR *pClassID);
+
+ HRESULT ( __stdcall __RPC_FAR *IsDirty )(
+ IPersistStream __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Load )(
+ IPersistStream __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pStm);
+
+ HRESULT ( __stdcall __RPC_FAR *Save )(
+ IPersistStream __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pStm,
+ /* [in] */ BOOL fClearDirty);
+
+ HRESULT ( __stdcall __RPC_FAR *GetSizeMax )(
+ IPersistStream __RPC_FAR * This,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbSize);
+
+ } IPersistStreamVtbl;
+
+ interface IPersistStream
+ {
+ CONST_VTBL struct IPersistStreamVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IPersistStream_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IPersistStream_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IPersistStream_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IPersistStream_GetClassID(This,pClassID) \
+ (This)->lpVtbl -> GetClassID(This,pClassID)
+
+
+#define IPersistStream_IsDirty(This) \
+ (This)->lpVtbl -> IsDirty(This)
+
+#define IPersistStream_Load(This,pStm) \
+ (This)->lpVtbl -> Load(This,pStm)
+
+#define IPersistStream_Save(This,pStm,fClearDirty) \
+ (This)->lpVtbl -> Save(This,pStm,fClearDirty)
+
+#define IPersistStream_GetSizeMax(This,pcbSize) \
+ (This)->lpVtbl -> GetSizeMax(This,pcbSize)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IPersistStream_IsDirty_Proxy(
+ IPersistStream __RPC_FAR * This);
+
+
+void __RPC_STUB IPersistStream_IsDirty_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IPersistStream_Load_Proxy(
+ IPersistStream __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pStm);
+
+
+void __RPC_STUB IPersistStream_Load_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IPersistStream_Save_Proxy(
+ IPersistStream __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pStm,
+ /* [in] */ BOOL fClearDirty);
+
+
+void __RPC_STUB IPersistStream_Save_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IPersistStream_GetSizeMax_Proxy(
+ IPersistStream __RPC_FAR * This,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbSize);
+
+
+void __RPC_STUB IPersistStream_GetSizeMax_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif //NOPROXYSTUB
+
+#endif /* __IPersistStream_INTERFACE_DEFINED__ */
+
+
+#ifndef __IMoniker_INTERFACE_DEFINED__
+#define __IMoniker_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IMoniker
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IMoniker __RPC_FAR *LPMONIKER;
+
+ /* size is 2 */
+typedef
+enum tagMKSYS
+ { MKSYS_NONE = 0,
+ MKSYS_GENERICCOMPOSITE = 1,
+ MKSYS_FILEMONIKER = 2,
+ MKSYS_ANTIMONIKER = 3,
+ MKSYS_ITEMMONIKER = 4,
+ MKSYS_POINTERMONIKER = 5
+ } MKSYS;
+
+ /* size is 2 */
+typedef /* [v1_enum] */
+enum tagMKREDUCE
+ { MKRREDUCE_ONE = 3 << 16,
+ MKRREDUCE_TOUSER = 2 << 16,
+ MKRREDUCE_THROUGHUSER = 1 << 16,
+ MKRREDUCE_ALL = 0
+ } MKRREDUCE;
+
+
+EXTERN_C const IID IID_IMoniker;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IMoniker : public IPersistStream
+ {
+ public:
+ virtual /* [local] */ HRESULT __stdcall BindToObject(
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [in] */ REFIID riidResult,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvResult) = 0;
+
+ virtual /* [local] */ HRESULT __stdcall BindToStorage(
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObj) = 0;
+
+ virtual HRESULT __stdcall Reduce(
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ DWORD dwReduceHowFar,
+ /* [unique][out][in] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkToLeft,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkReduced) = 0;
+
+ virtual HRESULT __stdcall ComposeWith(
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkRight,
+ /* [in] */ BOOL fOnlyIfNotGeneric,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkComposite) = 0;
+
+ virtual HRESULT __stdcall Enum(
+ /* [in] */ BOOL fForward,
+ /* [out] */ IEnumMoniker __RPC_FAR *__RPC_FAR *ppenumMoniker) = 0;
+
+ virtual HRESULT __stdcall IsEqual(
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkOtherMoniker) = 0;
+
+ virtual HRESULT __stdcall Hash(
+ /* [out] */ DWORD __RPC_FAR *pdwHash) = 0;
+
+ virtual HRESULT __stdcall IsRunning(
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkNewlyRunning) = 0;
+
+ virtual HRESULT __stdcall GetTimeOfLastChange(
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [out] */ FILETIME __RPC_FAR *pFileTime) = 0;
+
+ virtual HRESULT __stdcall Inverse(
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk) = 0;
+
+ virtual HRESULT __stdcall CommonPrefixWith(
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkOther,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkPrefix) = 0;
+
+ virtual HRESULT __stdcall RelativePathTo(
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkOther,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkRelPath) = 0;
+
+ virtual HRESULT __stdcall GetDisplayName(
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [out] */ LPOLESTR __RPC_FAR *ppszDisplayName) = 0;
+
+ virtual HRESULT __stdcall ParseDisplayName(
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [in] */ LPOLESTR pszDisplayName,
+ /* [out] */ ULONG __RPC_FAR *pchEaten,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut) = 0;
+
+ virtual HRESULT __stdcall IsSystemMoniker(
+ /* [out] */ DWORD __RPC_FAR *pdwMksys) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IMonikerVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IMoniker __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IMoniker __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IMoniker __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetClassID )(
+ IMoniker __RPC_FAR * This,
+ /* [out] */ CLSID __RPC_FAR *pClassID);
+
+ HRESULT ( __stdcall __RPC_FAR *IsDirty )(
+ IMoniker __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Load )(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pStm);
+
+ HRESULT ( __stdcall __RPC_FAR *Save )(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pStm,
+ /* [in] */ BOOL fClearDirty);
+
+ HRESULT ( __stdcall __RPC_FAR *GetSizeMax )(
+ IMoniker __RPC_FAR * This,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbSize);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *BindToObject )(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [in] */ REFIID riidResult,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvResult);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *BindToStorage )(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObj);
+
+ HRESULT ( __stdcall __RPC_FAR *Reduce )(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ DWORD dwReduceHowFar,
+ /* [unique][out][in] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkToLeft,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkReduced);
+
+ HRESULT ( __stdcall __RPC_FAR *ComposeWith )(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkRight,
+ /* [in] */ BOOL fOnlyIfNotGeneric,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkComposite);
+
+ HRESULT ( __stdcall __RPC_FAR *Enum )(
+ IMoniker __RPC_FAR * This,
+ /* [in] */ BOOL fForward,
+ /* [out] */ IEnumMoniker __RPC_FAR *__RPC_FAR *ppenumMoniker);
+
+ HRESULT ( __stdcall __RPC_FAR *IsEqual )(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkOtherMoniker);
+
+ HRESULT ( __stdcall __RPC_FAR *Hash )(
+ IMoniker __RPC_FAR * This,
+ /* [out] */ DWORD __RPC_FAR *pdwHash);
+
+ HRESULT ( __stdcall __RPC_FAR *IsRunning )(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkNewlyRunning);
+
+ HRESULT ( __stdcall __RPC_FAR *GetTimeOfLastChange )(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [out] */ FILETIME __RPC_FAR *pFileTime);
+
+ HRESULT ( __stdcall __RPC_FAR *Inverse )(
+ IMoniker __RPC_FAR * This,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk);
+
+ HRESULT ( __stdcall __RPC_FAR *CommonPrefixWith )(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkOther,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkPrefix);
+
+ HRESULT ( __stdcall __RPC_FAR *RelativePathTo )(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkOther,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkRelPath);
+
+ HRESULT ( __stdcall __RPC_FAR *GetDisplayName )(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [out] */ LPOLESTR __RPC_FAR *ppszDisplayName);
+
+ HRESULT ( __stdcall __RPC_FAR *ParseDisplayName )(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [in] */ LPOLESTR pszDisplayName,
+ /* [out] */ ULONG __RPC_FAR *pchEaten,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut);
+
+ HRESULT ( __stdcall __RPC_FAR *IsSystemMoniker )(
+ IMoniker __RPC_FAR * This,
+ /* [out] */ DWORD __RPC_FAR *pdwMksys);
+
+ } IMonikerVtbl;
+
+ interface IMoniker
+ {
+ CONST_VTBL struct IMonikerVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IMoniker_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IMoniker_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IMoniker_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IMoniker_GetClassID(This,pClassID) \
+ (This)->lpVtbl -> GetClassID(This,pClassID)
+
+
+#define IMoniker_IsDirty(This) \
+ (This)->lpVtbl -> IsDirty(This)
+
+#define IMoniker_Load(This,pStm) \
+ (This)->lpVtbl -> Load(This,pStm)
+
+#define IMoniker_Save(This,pStm,fClearDirty) \
+ (This)->lpVtbl -> Save(This,pStm,fClearDirty)
+
+#define IMoniker_GetSizeMax(This,pcbSize) \
+ (This)->lpVtbl -> GetSizeMax(This,pcbSize)
+
+
+#define IMoniker_BindToObject(This,pbc,pmkToLeft,riidResult,ppvResult) \
+ (This)->lpVtbl -> BindToObject(This,pbc,pmkToLeft,riidResult,ppvResult)
+
+#define IMoniker_BindToStorage(This,pbc,pmkToLeft,riid,ppvObj) \
+ (This)->lpVtbl -> BindToStorage(This,pbc,pmkToLeft,riid,ppvObj)
+
+#define IMoniker_Reduce(This,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced) \
+ (This)->lpVtbl -> Reduce(This,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced)
+
+#define IMoniker_ComposeWith(This,pmkRight,fOnlyIfNotGeneric,ppmkComposite) \
+ (This)->lpVtbl -> ComposeWith(This,pmkRight,fOnlyIfNotGeneric,ppmkComposite)
+
+#define IMoniker_Enum(This,fForward,ppenumMoniker) \
+ (This)->lpVtbl -> Enum(This,fForward,ppenumMoniker)
+
+#define IMoniker_IsEqual(This,pmkOtherMoniker) \
+ (This)->lpVtbl -> IsEqual(This,pmkOtherMoniker)
+
+#define IMoniker_Hash(This,pdwHash) \
+ (This)->lpVtbl -> Hash(This,pdwHash)
+
+#define IMoniker_IsRunning(This,pbc,pmkToLeft,pmkNewlyRunning) \
+ (This)->lpVtbl -> IsRunning(This,pbc,pmkToLeft,pmkNewlyRunning)
+
+#define IMoniker_GetTimeOfLastChange(This,pbc,pmkToLeft,pFileTime) \
+ (This)->lpVtbl -> GetTimeOfLastChange(This,pbc,pmkToLeft,pFileTime)
+
+#define IMoniker_Inverse(This,ppmk) \
+ (This)->lpVtbl -> Inverse(This,ppmk)
+
+#define IMoniker_CommonPrefixWith(This,pmkOther,ppmkPrefix) \
+ (This)->lpVtbl -> CommonPrefixWith(This,pmkOther,ppmkPrefix)
+
+#define IMoniker_RelativePathTo(This,pmkOther,ppmkRelPath) \
+ (This)->lpVtbl -> RelativePathTo(This,pmkOther,ppmkRelPath)
+
+#define IMoniker_GetDisplayName(This,pbc,pmkToLeft,ppszDisplayName) \
+ (This)->lpVtbl -> GetDisplayName(This,pbc,pmkToLeft,ppszDisplayName)
+
+#define IMoniker_ParseDisplayName(This,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut) \
+ (This)->lpVtbl -> ParseDisplayName(This,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut)
+
+#define IMoniker_IsSystemMoniker(This,pdwMksys) \
+ (This)->lpVtbl -> IsSystemMoniker(This,pdwMksys)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [call_as] */ HRESULT __stdcall IMoniker_RemoteBindToObject_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [in] */ REFIID riidResult,
+ /* [iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppvResult);
+
+
+void __RPC_STUB IMoniker_RemoteBindToObject_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [call_as] */ HRESULT __stdcall IMoniker_RemoteBindToStorage_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppvObj);
+
+
+void __RPC_STUB IMoniker_RemoteBindToStorage_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMoniker_Reduce_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ DWORD dwReduceHowFar,
+ /* [unique][out][in] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkToLeft,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkReduced);
+
+
+void __RPC_STUB IMoniker_Reduce_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMoniker_ComposeWith_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkRight,
+ /* [in] */ BOOL fOnlyIfNotGeneric,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkComposite);
+
+
+void __RPC_STUB IMoniker_ComposeWith_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMoniker_Enum_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [in] */ BOOL fForward,
+ /* [out] */ IEnumMoniker __RPC_FAR *__RPC_FAR *ppenumMoniker);
+
+
+void __RPC_STUB IMoniker_Enum_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMoniker_IsEqual_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkOtherMoniker);
+
+
+void __RPC_STUB IMoniker_IsEqual_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMoniker_Hash_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [out] */ DWORD __RPC_FAR *pdwHash);
+
+
+void __RPC_STUB IMoniker_Hash_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMoniker_IsRunning_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkNewlyRunning);
+
+
+void __RPC_STUB IMoniker_IsRunning_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMoniker_GetTimeOfLastChange_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [out] */ FILETIME __RPC_FAR *pFileTime);
+
+
+void __RPC_STUB IMoniker_GetTimeOfLastChange_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMoniker_Inverse_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk);
+
+
+void __RPC_STUB IMoniker_Inverse_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMoniker_CommonPrefixWith_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkOther,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkPrefix);
+
+
+void __RPC_STUB IMoniker_CommonPrefixWith_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMoniker_RelativePathTo_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkOther,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkRelPath);
+
+
+void __RPC_STUB IMoniker_RelativePathTo_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMoniker_GetDisplayName_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [out] */ LPOLESTR __RPC_FAR *ppszDisplayName);
+
+
+void __RPC_STUB IMoniker_GetDisplayName_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMoniker_ParseDisplayName_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [in] */ LPOLESTR pszDisplayName,
+ /* [out] */ ULONG __RPC_FAR *pchEaten,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut);
+
+
+void __RPC_STUB IMoniker_ParseDisplayName_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IMoniker_IsSystemMoniker_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [out] */ DWORD __RPC_FAR *pdwMksys);
+
+
+void __RPC_STUB IMoniker_IsSystemMoniker_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif //NOPROXYSTUB
+
+#endif /* __IMoniker_INTERFACE_DEFINED__ */
+
+
+#ifndef __IROTData_INTERFACE_DEFINED__
+#define __IROTData_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IROTData
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+
+EXTERN_C const IID IID_IROTData;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IROTData : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall GetComparisonData(
+ /* [size_is][out] */ byte __RPC_FAR *pbData,
+ /* [in] */ ULONG cbMax,
+ /* [out] */ ULONG __RPC_FAR *pcbData) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IROTDataVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IROTData __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IROTData __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IROTData __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetComparisonData )(
+ IROTData __RPC_FAR * This,
+ /* [size_is][out] */ byte __RPC_FAR *pbData,
+ /* [in] */ ULONG cbMax,
+ /* [out] */ ULONG __RPC_FAR *pcbData);
+
+ } IROTDataVtbl;
+
+ interface IROTData
+ {
+ CONST_VTBL struct IROTDataVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IROTData_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IROTData_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IROTData_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IROTData_GetComparisonData(This,pbData,cbMax,pcbData) \
+ (This)->lpVtbl -> GetComparisonData(This,pbData,cbMax,pcbData)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IROTData_GetComparisonData_Proxy(
+ IROTData __RPC_FAR * This,
+ /* [size_is][out] */ byte __RPC_FAR *pbData,
+ /* [in] */ ULONG cbMax,
+ /* [out] */ ULONG __RPC_FAR *pcbData);
+
+
+void __RPC_STUB IROTData_GetComparisonData_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif //NOPROXYSTUB
+
+#endif /* __IROTData_INTERFACE_DEFINED__ */
+
+
+#ifndef __IEnumString_INTERFACE_DEFINED__
+#define __IEnumString_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IEnumString
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IEnumString __RPC_FAR *LPENUMSTRING;
+
+
+EXTERN_C const IID IID_IEnumString;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IEnumString : public IUnknown
+ {
+ public:
+ virtual /* [local] */ HRESULT __stdcall Next(
+ /* [in] */ ULONG celt,
+ /* [out] */ LPOLESTR __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched) = 0;
+
+ virtual HRESULT __stdcall Skip(
+ /* [in] */ ULONG celt) = 0;
+
+ virtual HRESULT __stdcall Reset( void) = 0;
+
+ virtual HRESULT __stdcall Clone(
+ /* [out] */ IEnumString __RPC_FAR *__RPC_FAR *ppenum) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IEnumStringVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IEnumString __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IEnumString __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IEnumString __RPC_FAR * This);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *Next )(
+ IEnumString __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [out] */ LPOLESTR __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+ HRESULT ( __stdcall __RPC_FAR *Skip )(
+ IEnumString __RPC_FAR * This,
+ /* [in] */ ULONG celt);
+
+ HRESULT ( __stdcall __RPC_FAR *Reset )(
+ IEnumString __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Clone )(
+ IEnumString __RPC_FAR * This,
+ /* [out] */ IEnumString __RPC_FAR *__RPC_FAR *ppenum);
+
+ } IEnumStringVtbl;
+
+ interface IEnumString
+ {
+ CONST_VTBL struct IEnumStringVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IEnumString_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IEnumString_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IEnumString_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IEnumString_Next(This,celt,rgelt,pceltFetched) \
+ (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched)
+
+#define IEnumString_Skip(This,celt) \
+ (This)->lpVtbl -> Skip(This,celt)
+
+#define IEnumString_Reset(This) \
+ (This)->lpVtbl -> Reset(This)
+
+#define IEnumString_Clone(This,ppenum) \
+ (This)->lpVtbl -> Clone(This,ppenum)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [call_as] */ HRESULT __stdcall IEnumString_RemoteNext_Proxy(
+ IEnumString __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ LPOLESTR __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+
+void __RPC_STUB IEnumString_RemoteNext_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumString_Skip_Proxy(
+ IEnumString __RPC_FAR * This,
+ /* [in] */ ULONG celt);
+
+
+void __RPC_STUB IEnumString_Skip_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumString_Reset_Proxy(
+ IEnumString __RPC_FAR * This);
+
+
+void __RPC_STUB IEnumString_Reset_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumString_Clone_Proxy(
+ IEnumString __RPC_FAR * This,
+ /* [out] */ IEnumString __RPC_FAR *__RPC_FAR *ppenum);
+
+
+void __RPC_STUB IEnumString_Clone_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif //NOPROXYSTUB
+
+#endif /* __IEnumString_INTERFACE_DEFINED__ */
+
+
+#ifndef __IStream_INTERFACE_DEFINED__
+#define __IStream_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IStream
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IStream __RPC_FAR *LPSTREAM;
+
+ /* size is 72 */
+typedef struct tagSTATSTG
+ {
+ LPOLESTR pwcsName;
+ DWORD type;
+ ULARGE_INTEGER cbSize;
+ FILETIME mtime;
+ FILETIME ctime;
+ FILETIME atime;
+ DWORD grfMode;
+ DWORD grfLocksSupported;
+ CLSID clsid;
+ DWORD grfStateBits;
+ DWORD reserved;
+ } STATSTG;
+
+ /* size is 2 */
+typedef
+enum tagSTGTY
+ { STGTY_STORAGE = 1,
+ STGTY_STREAM = 2,
+ STGTY_LOCKBYTES = 3,
+ STGTY_PROPERTY = 4
+ } STGTY;
+
+ /* size is 2 */
+typedef
+enum tagSTREAM_SEEK
+ { STREAM_SEEK_SET = 0,
+ STREAM_SEEK_CUR = 1,
+ STREAM_SEEK_END = 2
+ } STREAM_SEEK;
+
+ /* size is 2 */
+typedef
+enum tagLOCKTYPE
+ { LOCK_WRITE = 1,
+ LOCK_EXCLUSIVE = 2,
+ LOCK_ONLYONCE = 4
+ } LOCKTYPE;
+
+
+EXTERN_C const IID IID_IStream;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IStream : public IUnknown
+ {
+ public:
+ virtual /* [local] */ HRESULT __stdcall Read(
+ /* [out] */ void __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbRead) = 0;
+
+ virtual /* [local] */ HRESULT __stdcall Write(
+ /* [size_is][in] */ const void __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbWritten) = 0;
+
+ virtual /* [local] */ HRESULT __stdcall Seek(
+ /* [in] */ LARGE_INTEGER dlibMove,
+ /* [in] */ DWORD dwOrigin,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *plibNewPosition) = 0;
+
+ virtual HRESULT __stdcall SetSize(
+ /* [in] */ ULARGE_INTEGER libNewSize) = 0;
+
+ virtual /* [local] */ HRESULT __stdcall CopyTo(
+ /* [unique][in] */ IStream __RPC_FAR *pstm,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbRead,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbWritten) = 0;
+
+ virtual HRESULT __stdcall Commit(
+ /* [in] */ DWORD grfCommitFlags) = 0;
+
+ virtual HRESULT __stdcall Revert( void) = 0;
+
+ virtual HRESULT __stdcall LockRegion(
+ /* [in] */ ULARGE_INTEGER libOffset,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [in] */ DWORD dwLockType) = 0;
+
+ virtual HRESULT __stdcall UnlockRegion(
+ /* [in] */ ULARGE_INTEGER libOffset,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [in] */ DWORD dwLockType) = 0;
+
+ virtual HRESULT __stdcall Stat(
+ /* [out] */ STATSTG __RPC_FAR *pstatstg,
+ /* [in] */ DWORD grfStatFlag) = 0;
+
+ virtual HRESULT __stdcall Clone(
+ /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IStreamVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IStream __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IStream __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IStream __RPC_FAR * This);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *Read )(
+ IStream __RPC_FAR * This,
+ /* [out] */ void __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbRead);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *Write )(
+ IStream __RPC_FAR * This,
+ /* [size_is][in] */ const void __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbWritten);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *Seek )(
+ IStream __RPC_FAR * This,
+ /* [in] */ LARGE_INTEGER dlibMove,
+ /* [in] */ DWORD dwOrigin,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *plibNewPosition);
+
+ HRESULT ( __stdcall __RPC_FAR *SetSize )(
+ IStream __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER libNewSize);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *CopyTo )(
+ IStream __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pstm,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbRead,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbWritten);
+
+ HRESULT ( __stdcall __RPC_FAR *Commit )(
+ IStream __RPC_FAR * This,
+ /* [in] */ DWORD grfCommitFlags);
+
+ HRESULT ( __stdcall __RPC_FAR *Revert )(
+ IStream __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *LockRegion )(
+ IStream __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER libOffset,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [in] */ DWORD dwLockType);
+
+ HRESULT ( __stdcall __RPC_FAR *UnlockRegion )(
+ IStream __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER libOffset,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [in] */ DWORD dwLockType);
+
+ HRESULT ( __stdcall __RPC_FAR *Stat )(
+ IStream __RPC_FAR * This,
+ /* [out] */ STATSTG __RPC_FAR *pstatstg,
+ /* [in] */ DWORD grfStatFlag);
+
+ HRESULT ( __stdcall __RPC_FAR *Clone )(
+ IStream __RPC_FAR * This,
+ /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
+
+ } IStreamVtbl;
+
+ interface IStream
+ {
+ CONST_VTBL struct IStreamVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IStream_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IStream_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IStream_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IStream_Read(This,pv,cb,pcbRead) \
+ (This)->lpVtbl -> Read(This,pv,cb,pcbRead)
+
+#define IStream_Write(This,pv,cb,pcbWritten) \
+ (This)->lpVtbl -> Write(This,pv,cb,pcbWritten)
+
+#define IStream_Seek(This,dlibMove,dwOrigin,plibNewPosition) \
+ (This)->lpVtbl -> Seek(This,dlibMove,dwOrigin,plibNewPosition)
+
+#define IStream_SetSize(This,libNewSize) \
+ (This)->lpVtbl -> SetSize(This,libNewSize)
+
+#define IStream_CopyTo(This,pstm,cb,pcbRead,pcbWritten) \
+ (This)->lpVtbl -> CopyTo(This,pstm,cb,pcbRead,pcbWritten)
+
+#define IStream_Commit(This,grfCommitFlags) \
+ (This)->lpVtbl -> Commit(This,grfCommitFlags)
+
+#define IStream_Revert(This) \
+ (This)->lpVtbl -> Revert(This)
+
+#define IStream_LockRegion(This,libOffset,cb,dwLockType) \
+ (This)->lpVtbl -> LockRegion(This,libOffset,cb,dwLockType)
+
+#define IStream_UnlockRegion(This,libOffset,cb,dwLockType) \
+ (This)->lpVtbl -> UnlockRegion(This,libOffset,cb,dwLockType)
+
+#define IStream_Stat(This,pstatstg,grfStatFlag) \
+ (This)->lpVtbl -> Stat(This,pstatstg,grfStatFlag)
+
+#define IStream_Clone(This,ppstm) \
+ (This)->lpVtbl -> Clone(This,ppstm)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [call_as] */ HRESULT __stdcall IStream_RemoteRead_Proxy(
+ IStream __RPC_FAR * This,
+ /* [length_is][size_is][out] */ byte __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbRead);
+
+
+void __RPC_STUB IStream_RemoteRead_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [call_as] */ HRESULT __stdcall IStream_RemoteWrite_Proxy(
+ IStream __RPC_FAR * This,
+ /* [size_is][in] */ const byte __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbWritten);
+
+
+void __RPC_STUB IStream_RemoteWrite_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [call_as] */ HRESULT __stdcall IStream_RemoteSeek_Proxy(
+ IStream __RPC_FAR * This,
+ /* [in] */ LARGE_INTEGER dlibMove,
+ /* [in] */ DWORD dwOrigin,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *plibNewPosition);
+
+
+void __RPC_STUB IStream_RemoteSeek_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStream_SetSize_Proxy(
+ IStream __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER libNewSize);
+
+
+void __RPC_STUB IStream_SetSize_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [call_as] */ HRESULT __stdcall IStream_RemoteCopyTo_Proxy(
+ IStream __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pstm,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbRead,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbWritten);
+
+
+void __RPC_STUB IStream_RemoteCopyTo_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStream_Commit_Proxy(
+ IStream __RPC_FAR * This,
+ /* [in] */ DWORD grfCommitFlags);
+
+
+void __RPC_STUB IStream_Commit_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStream_Revert_Proxy(
+ IStream __RPC_FAR * This);
+
+
+void __RPC_STUB IStream_Revert_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStream_LockRegion_Proxy(
+ IStream __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER libOffset,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [in] */ DWORD dwLockType);
+
+
+void __RPC_STUB IStream_LockRegion_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStream_UnlockRegion_Proxy(
+ IStream __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER libOffset,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [in] */ DWORD dwLockType);
+
+
+void __RPC_STUB IStream_UnlockRegion_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStream_Stat_Proxy(
+ IStream __RPC_FAR * This,
+ /* [out] */ STATSTG __RPC_FAR *pstatstg,
+ /* [in] */ DWORD grfStatFlag);
+
+
+void __RPC_STUB IStream_Stat_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStream_Clone_Proxy(
+ IStream __RPC_FAR * This,
+ /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
+
+
+void __RPC_STUB IStream_Clone_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif //NOPROXYSTUB
+
+#endif /* __IStream_INTERFACE_DEFINED__ */
+
+
+#ifndef __IEnumSTATSTG_INTERFACE_DEFINED__
+#define __IEnumSTATSTG_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IEnumSTATSTG
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IEnumSTATSTG __RPC_FAR *LPENUMSTATSTG;
+
+
+EXTERN_C const IID IID_IEnumSTATSTG;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IEnumSTATSTG : public IUnknown
+ {
+ public:
+ virtual /* [local] */ HRESULT __stdcall Next(
+ /* [in] */ ULONG celt,
+ /* [in] */ STATSTG __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched) = 0;
+
+ virtual HRESULT __stdcall Skip(
+ /* [in] */ ULONG celt) = 0;
+
+ virtual HRESULT __stdcall Reset( void) = 0;
+
+ virtual HRESULT __stdcall Clone(
+ /* [out] */ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IEnumSTATSTGVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IEnumSTATSTG __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IEnumSTATSTG __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IEnumSTATSTG __RPC_FAR * This);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *Next )(
+ IEnumSTATSTG __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [in] */ STATSTG __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+ HRESULT ( __stdcall __RPC_FAR *Skip )(
+ IEnumSTATSTG __RPC_FAR * This,
+ /* [in] */ ULONG celt);
+
+ HRESULT ( __stdcall __RPC_FAR *Reset )(
+ IEnumSTATSTG __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Clone )(
+ IEnumSTATSTG __RPC_FAR * This,
+ /* [out] */ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum);
+
+ } IEnumSTATSTGVtbl;
+
+ interface IEnumSTATSTG
+ {
+ CONST_VTBL struct IEnumSTATSTGVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IEnumSTATSTG_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IEnumSTATSTG_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IEnumSTATSTG_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IEnumSTATSTG_Next(This,celt,rgelt,pceltFetched) \
+ (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched)
+
+#define IEnumSTATSTG_Skip(This,celt) \
+ (This)->lpVtbl -> Skip(This,celt)
+
+#define IEnumSTATSTG_Reset(This) \
+ (This)->lpVtbl -> Reset(This)
+
+#define IEnumSTATSTG_Clone(This,ppenum) \
+ (This)->lpVtbl -> Clone(This,ppenum)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [call_as] */ HRESULT __stdcall IEnumSTATSTG_RemoteNext_Proxy(
+ IEnumSTATSTG __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ STATSTG __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+
+void __RPC_STUB IEnumSTATSTG_RemoteNext_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumSTATSTG_Skip_Proxy(
+ IEnumSTATSTG __RPC_FAR * This,
+ /* [in] */ ULONG celt);
+
+
+void __RPC_STUB IEnumSTATSTG_Skip_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumSTATSTG_Reset_Proxy(
+ IEnumSTATSTG __RPC_FAR * This);
+
+
+void __RPC_STUB IEnumSTATSTG_Reset_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumSTATSTG_Clone_Proxy(
+ IEnumSTATSTG __RPC_FAR * This,
+ /* [out] */ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum);
+
+
+void __RPC_STUB IEnumSTATSTG_Clone_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IEnumSTATSTG_INTERFACE_DEFINED__ */
+
+
+#ifndef __IStorage_INTERFACE_DEFINED__
+#define __IStorage_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IStorage
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IStorage __RPC_FAR *LPSTORAGE;
+
+ /* size is 8 */
+typedef struct tagRemSNB
+ {
+ unsigned long ulCntStr;
+ unsigned long ulCntChar;
+ /* [size_is] */ OLECHAR rgString[ 1 ];
+ } RemSNB;
+
+ /* size is 4 */
+typedef /* [transmit] */ OLECHAR __RPC_FAR *__RPC_FAR *SNB;
+
+
+EXTERN_C const IID IID_IStorage;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IStorage : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall CreateStream(
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ DWORD grfMode,
+ /* [in] */ DWORD reserved1,
+ /* [in] */ DWORD reserved2,
+ /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm) = 0;
+
+ virtual /* [local] */ HRESULT __stdcall OpenStream(
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [unique][in] */ void __RPC_FAR *reserved1,
+ /* [in] */ DWORD grfMode,
+ /* [in] */ DWORD reserved2,
+ /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm) = 0;
+
+ virtual HRESULT __stdcall CreateStorage(
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ DWORD grfMode,
+ /* [in] */ DWORD dwStgFmt,
+ /* [in] */ DWORD reserved2,
+ /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg) = 0;
+
+ virtual HRESULT __stdcall OpenStorage(
+ /* [string][unique][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [unique][in] */ IStorage __RPC_FAR *pstgPriority,
+ /* [in] */ DWORD grfMode,
+ /* [unique][in] */ SNB snbExclude,
+ /* [in] */ DWORD reserved,
+ /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg) = 0;
+
+ virtual HRESULT __stdcall CopyTo(
+ /* [in] */ DWORD ciidExclude,
+ /* [size_is][unique][in] */ const IID __RPC_FAR *rgiidExclude,
+ /* [unique][in] */ SNB snbExclude,
+ /* [unique][in] */ IStorage __RPC_FAR *pstgDest) = 0;
+
+ virtual HRESULT __stdcall MoveElementTo(
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [unique][in] */ IStorage __RPC_FAR *pstgDest,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName,
+ /* [in] */ DWORD grfFlags) = 0;
+
+ virtual HRESULT __stdcall Commit(
+ /* [in] */ DWORD grfCommitFlags) = 0;
+
+ virtual HRESULT __stdcall Revert( void) = 0;
+
+ virtual /* [local] */ HRESULT __stdcall EnumElements(
+ /* [in] */ DWORD reserved1,
+ /* [size_is][unique][in] */ void __RPC_FAR *reserved2,
+ /* [in] */ DWORD reserved3,
+ /* [out] */ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum) = 0;
+
+ virtual HRESULT __stdcall DestroyElement(
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName) = 0;
+
+ virtual HRESULT __stdcall RenameElement(
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsOldName,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName) = 0;
+
+ virtual HRESULT __stdcall SetElementTimes(
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ const FILETIME __RPC_FAR *pctime,
+ /* [in] */ const FILETIME __RPC_FAR *patime,
+ /* [in] */ const FILETIME __RPC_FAR *pmtime) = 0;
+
+ virtual HRESULT __stdcall SetClass(
+ /* [in] */ REFCLSID clsid) = 0;
+
+ virtual HRESULT __stdcall SetStateBits(
+ /* [in] */ DWORD grfStateBits,
+ /* [in] */ DWORD grfMask) = 0;
+
+ virtual HRESULT __stdcall Stat(
+ /* [out] */ STATSTG __RPC_FAR *pstatstg,
+ /* [in] */ DWORD grfStatFlag) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IStorageVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IStorage __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IStorage __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IStorage __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *CreateStream )(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ DWORD grfMode,
+ /* [in] */ DWORD reserved1,
+ /* [in] */ DWORD reserved2,
+ /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *OpenStream )(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [unique][in] */ void __RPC_FAR *reserved1,
+ /* [in] */ DWORD grfMode,
+ /* [in] */ DWORD reserved2,
+ /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
+
+ HRESULT ( __stdcall __RPC_FAR *CreateStorage )(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ DWORD grfMode,
+ /* [in] */ DWORD dwStgFmt,
+ /* [in] */ DWORD reserved2,
+ /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg);
+
+ HRESULT ( __stdcall __RPC_FAR *OpenStorage )(
+ IStorage __RPC_FAR * This,
+ /* [string][unique][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [unique][in] */ IStorage __RPC_FAR *pstgPriority,
+ /* [in] */ DWORD grfMode,
+ /* [unique][in] */ SNB snbExclude,
+ /* [in] */ DWORD reserved,
+ /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg);
+
+ HRESULT ( __stdcall __RPC_FAR *CopyTo )(
+ IStorage __RPC_FAR * This,
+ /* [in] */ DWORD ciidExclude,
+ /* [size_is][unique][in] */ const IID __RPC_FAR *rgiidExclude,
+ /* [unique][in] */ SNB snbExclude,
+ /* [unique][in] */ IStorage __RPC_FAR *pstgDest);
+
+ HRESULT ( __stdcall __RPC_FAR *MoveElementTo )(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [unique][in] */ IStorage __RPC_FAR *pstgDest,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName,
+ /* [in] */ DWORD grfFlags);
+
+ HRESULT ( __stdcall __RPC_FAR *Commit )(
+ IStorage __RPC_FAR * This,
+ /* [in] */ DWORD grfCommitFlags);
+
+ HRESULT ( __stdcall __RPC_FAR *Revert )(
+ IStorage __RPC_FAR * This);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *EnumElements )(
+ IStorage __RPC_FAR * This,
+ /* [in] */ DWORD reserved1,
+ /* [size_is][unique][in] */ void __RPC_FAR *reserved2,
+ /* [in] */ DWORD reserved3,
+ /* [out] */ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum);
+
+ HRESULT ( __stdcall __RPC_FAR *DestroyElement )(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName);
+
+ HRESULT ( __stdcall __RPC_FAR *RenameElement )(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsOldName,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName);
+
+ HRESULT ( __stdcall __RPC_FAR *SetElementTimes )(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ const FILETIME __RPC_FAR *pctime,
+ /* [in] */ const FILETIME __RPC_FAR *patime,
+ /* [in] */ const FILETIME __RPC_FAR *pmtime);
+
+ HRESULT ( __stdcall __RPC_FAR *SetClass )(
+ IStorage __RPC_FAR * This,
+ /* [in] */ REFCLSID clsid);
+
+ HRESULT ( __stdcall __RPC_FAR *SetStateBits )(
+ IStorage __RPC_FAR * This,
+ /* [in] */ DWORD grfStateBits,
+ /* [in] */ DWORD grfMask);
+
+ HRESULT ( __stdcall __RPC_FAR *Stat )(
+ IStorage __RPC_FAR * This,
+ /* [out] */ STATSTG __RPC_FAR *pstatstg,
+ /* [in] */ DWORD grfStatFlag);
+
+ } IStorageVtbl;
+
+ interface IStorage
+ {
+ CONST_VTBL struct IStorageVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IStorage_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IStorage_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IStorage_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IStorage_CreateStream(This,pwcsName,grfMode,reserved1,reserved2,ppstm) \
+ (This)->lpVtbl -> CreateStream(This,pwcsName,grfMode,reserved1,reserved2,ppstm)
+
+#define IStorage_OpenStream(This,pwcsName,reserved1,grfMode,reserved2,ppstm) \
+ (This)->lpVtbl -> OpenStream(This,pwcsName,reserved1,grfMode,reserved2,ppstm)
+
+#define IStorage_CreateStorage(This,pwcsName,grfMode,dwStgFmt,reserved2,ppstg) \
+ (This)->lpVtbl -> CreateStorage(This,pwcsName,grfMode,dwStgFmt,reserved2,ppstg)
+
+#define IStorage_OpenStorage(This,pwcsName,pstgPriority,grfMode,snbExclude,reserved,ppstg) \
+ (This)->lpVtbl -> OpenStorage(This,pwcsName,pstgPriority,grfMode,snbExclude,reserved,ppstg)
+
+#define IStorage_CopyTo(This,ciidExclude,rgiidExclude,snbExclude,pstgDest) \
+ (This)->lpVtbl -> CopyTo(This,ciidExclude,rgiidExclude,snbExclude,pstgDest)
+
+#define IStorage_MoveElementTo(This,pwcsName,pstgDest,pwcsNewName,grfFlags) \
+ (This)->lpVtbl -> MoveElementTo(This,pwcsName,pstgDest,pwcsNewName,grfFlags)
+
+#define IStorage_Commit(This,grfCommitFlags) \
+ (This)->lpVtbl -> Commit(This,grfCommitFlags)
+
+#define IStorage_Revert(This) \
+ (This)->lpVtbl -> Revert(This)
+
+#define IStorage_EnumElements(This,reserved1,reserved2,reserved3,ppenum) \
+ (This)->lpVtbl -> EnumElements(This,reserved1,reserved2,reserved3,ppenum)
+
+#define IStorage_DestroyElement(This,pwcsName) \
+ (This)->lpVtbl -> DestroyElement(This,pwcsName)
+
+#define IStorage_RenameElement(This,pwcsOldName,pwcsNewName) \
+ (This)->lpVtbl -> RenameElement(This,pwcsOldName,pwcsNewName)
+
+#define IStorage_SetElementTimes(This,pwcsName,pctime,patime,pmtime) \
+ (This)->lpVtbl -> SetElementTimes(This,pwcsName,pctime,patime,pmtime)
+
+#define IStorage_SetClass(This,clsid) \
+ (This)->lpVtbl -> SetClass(This,clsid)
+
+#define IStorage_SetStateBits(This,grfStateBits,grfMask) \
+ (This)->lpVtbl -> SetStateBits(This,grfStateBits,grfMask)
+
+#define IStorage_Stat(This,pstatstg,grfStatFlag) \
+ (This)->lpVtbl -> Stat(This,pstatstg,grfStatFlag)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IStorage_CreateStream_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ DWORD grfMode,
+ /* [in] */ DWORD reserved1,
+ /* [in] */ DWORD reserved2,
+ /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
+
+
+void __RPC_STUB IStorage_CreateStream_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [call_as] */ HRESULT __stdcall IStorage_RemoteOpenStream_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ unsigned long cbReserved1,
+ /* [size_is][unique][in] */ byte __RPC_FAR *reserved1,
+ /* [in] */ DWORD grfMode,
+ /* [in] */ DWORD reserved2,
+ /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
+
+
+void __RPC_STUB IStorage_RemoteOpenStream_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStorage_CreateStorage_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ DWORD grfMode,
+ /* [in] */ DWORD dwStgFmt,
+ /* [in] */ DWORD reserved2,
+ /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg);
+
+
+void __RPC_STUB IStorage_CreateStorage_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStorage_OpenStorage_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [string][unique][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [unique][in] */ IStorage __RPC_FAR *pstgPriority,
+ /* [in] */ DWORD grfMode,
+ /* [unique][in] */ SNB snbExclude,
+ /* [in] */ DWORD reserved,
+ /* [out] */ IStorage __RPC_FAR *__RPC_FAR *ppstg);
+
+
+void __RPC_STUB IStorage_OpenStorage_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStorage_CopyTo_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [in] */ DWORD ciidExclude,
+ /* [size_is][unique][in] */ const IID __RPC_FAR *rgiidExclude,
+ /* [unique][in] */ SNB snbExclude,
+ /* [unique][in] */ IStorage __RPC_FAR *pstgDest);
+
+
+void __RPC_STUB IStorage_CopyTo_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStorage_MoveElementTo_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [unique][in] */ IStorage __RPC_FAR *pstgDest,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName,
+ /* [in] */ DWORD grfFlags);
+
+
+void __RPC_STUB IStorage_MoveElementTo_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStorage_Commit_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [in] */ DWORD grfCommitFlags);
+
+
+void __RPC_STUB IStorage_Commit_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStorage_Revert_Proxy(
+ IStorage __RPC_FAR * This);
+
+
+void __RPC_STUB IStorage_Revert_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [call_as] */ HRESULT __stdcall IStorage_RemoteEnumElements_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [in] */ DWORD reserved1,
+ /* [in] */ unsigned long cbReserved2,
+ /* [size_is][unique][in] */ byte __RPC_FAR *reserved2,
+ /* [in] */ DWORD reserved3,
+ /* [out] */ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum);
+
+
+void __RPC_STUB IStorage_RemoteEnumElements_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStorage_DestroyElement_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName);
+
+
+void __RPC_STUB IStorage_DestroyElement_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStorage_RenameElement_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsOldName,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsNewName);
+
+
+void __RPC_STUB IStorage_RenameElement_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStorage_SetElementTimes_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ const FILETIME __RPC_FAR *pctime,
+ /* [in] */ const FILETIME __RPC_FAR *patime,
+ /* [in] */ const FILETIME __RPC_FAR *pmtime);
+
+
+void __RPC_STUB IStorage_SetElementTimes_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStorage_SetClass_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [in] */ REFCLSID clsid);
+
+
+void __RPC_STUB IStorage_SetClass_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStorage_SetStateBits_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [in] */ DWORD grfStateBits,
+ /* [in] */ DWORD grfMask);
+
+
+void __RPC_STUB IStorage_SetStateBits_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IStorage_Stat_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [out] */ STATSTG __RPC_FAR *pstatstg,
+ /* [in] */ DWORD grfStatFlag);
+
+
+void __RPC_STUB IStorage_Stat_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IStorage_INTERFACE_DEFINED__ */
+
+
+#ifndef __IPersistFile_INTERFACE_DEFINED__
+#define __IPersistFile_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IPersistFile
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IPersistFile __RPC_FAR *LPPERSISTFILE;
+
+
+EXTERN_C const IID IID_IPersistFile;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IPersistFile : public IPersist
+ {
+ public:
+ virtual HRESULT __stdcall IsDirty( void) = 0;
+
+ virtual HRESULT __stdcall Load(
+ /* [in] */ LPCOLESTR pszFileName,
+ /* [in] */ DWORD dwMode) = 0;
+
+ virtual HRESULT __stdcall Save(
+ /* [unique][in] */ LPCOLESTR pszFileName,
+ /* [in] */ BOOL fRemember) = 0;
+
+ virtual HRESULT __stdcall SaveCompleted(
+ /* [unique][in] */ LPCOLESTR pszFileName) = 0;
+
+ virtual HRESULT __stdcall GetCurFile(
+ /* [out] */ LPOLESTR __RPC_FAR *ppszFileName) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IPersistFileVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IPersistFile __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IPersistFile __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IPersistFile __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetClassID )(
+ IPersistFile __RPC_FAR * This,
+ /* [out] */ CLSID __RPC_FAR *pClassID);
+
+ HRESULT ( __stdcall __RPC_FAR *IsDirty )(
+ IPersistFile __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Load )(
+ IPersistFile __RPC_FAR * This,
+ /* [in] */ LPCOLESTR pszFileName,
+ /* [in] */ DWORD dwMode);
+
+ HRESULT ( __stdcall __RPC_FAR *Save )(
+ IPersistFile __RPC_FAR * This,
+ /* [unique][in] */ LPCOLESTR pszFileName,
+ /* [in] */ BOOL fRemember);
+
+ HRESULT ( __stdcall __RPC_FAR *SaveCompleted )(
+ IPersistFile __RPC_FAR * This,
+ /* [unique][in] */ LPCOLESTR pszFileName);
+
+ HRESULT ( __stdcall __RPC_FAR *GetCurFile )(
+ IPersistFile __RPC_FAR * This,
+ /* [out] */ LPOLESTR __RPC_FAR *ppszFileName);
+
+ } IPersistFileVtbl;
+
+ interface IPersistFile
+ {
+ CONST_VTBL struct IPersistFileVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IPersistFile_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IPersistFile_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IPersistFile_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IPersistFile_GetClassID(This,pClassID) \
+ (This)->lpVtbl -> GetClassID(This,pClassID)
+
+
+#define IPersistFile_IsDirty(This) \
+ (This)->lpVtbl -> IsDirty(This)
+
+#define IPersistFile_Load(This,pszFileName,dwMode) \
+ (This)->lpVtbl -> Load(This,pszFileName,dwMode)
+
+#define IPersistFile_Save(This,pszFileName,fRemember) \
+ (This)->lpVtbl -> Save(This,pszFileName,fRemember)
+
+#define IPersistFile_SaveCompleted(This,pszFileName) \
+ (This)->lpVtbl -> SaveCompleted(This,pszFileName)
+
+#define IPersistFile_GetCurFile(This,ppszFileName) \
+ (This)->lpVtbl -> GetCurFile(This,ppszFileName)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IPersistFile_IsDirty_Proxy(
+ IPersistFile __RPC_FAR * This);
+
+
+void __RPC_STUB IPersistFile_IsDirty_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IPersistFile_Load_Proxy(
+ IPersistFile __RPC_FAR * This,
+ /* [in] */ LPCOLESTR pszFileName,
+ /* [in] */ DWORD dwMode);
+
+
+void __RPC_STUB IPersistFile_Load_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IPersistFile_Save_Proxy(
+ IPersistFile __RPC_FAR * This,
+ /* [unique][in] */ LPCOLESTR pszFileName,
+ /* [in] */ BOOL fRemember);
+
+
+void __RPC_STUB IPersistFile_Save_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IPersistFile_SaveCompleted_Proxy(
+ IPersistFile __RPC_FAR * This,
+ /* [unique][in] */ LPCOLESTR pszFileName);
+
+
+void __RPC_STUB IPersistFile_SaveCompleted_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IPersistFile_GetCurFile_Proxy(
+ IPersistFile __RPC_FAR * This,
+ /* [out] */ LPOLESTR __RPC_FAR *ppszFileName);
+
+
+void __RPC_STUB IPersistFile_GetCurFile_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IPersistFile_INTERFACE_DEFINED__ */
+
+
+#ifndef __IPersistStorage_INTERFACE_DEFINED__
+#define __IPersistStorage_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IPersistStorage
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IPersistStorage __RPC_FAR *LPPERSISTSTORAGE;
+
+
+EXTERN_C const IID IID_IPersistStorage;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IPersistStorage : public IPersist
+ {
+ public:
+ virtual HRESULT __stdcall IsDirty( void) = 0;
+
+ virtual HRESULT __stdcall InitNew(
+ /* [unique][in] */ IStorage __RPC_FAR *pStg) = 0;
+
+ virtual HRESULT __stdcall Load(
+ /* [unique][in] */ IStorage __RPC_FAR *pStg) = 0;
+
+ virtual HRESULT __stdcall Save(
+ /* [unique][in] */ IStorage __RPC_FAR *pStgSave,
+ /* [in] */ BOOL fSameAsLoad) = 0;
+
+ virtual HRESULT __stdcall SaveCompleted(
+ /* [unique][in] */ IStorage __RPC_FAR *pStgNew) = 0;
+
+ virtual HRESULT __stdcall HandsOffStorage( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IPersistStorageVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IPersistStorage __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IPersistStorage __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IPersistStorage __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetClassID )(
+ IPersistStorage __RPC_FAR * This,
+ /* [out] */ CLSID __RPC_FAR *pClassID);
+
+ HRESULT ( __stdcall __RPC_FAR *IsDirty )(
+ IPersistStorage __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *InitNew )(
+ IPersistStorage __RPC_FAR * This,
+ /* [unique][in] */ IStorage __RPC_FAR *pStg);
+
+ HRESULT ( __stdcall __RPC_FAR *Load )(
+ IPersistStorage __RPC_FAR * This,
+ /* [unique][in] */ IStorage __RPC_FAR *pStg);
+
+ HRESULT ( __stdcall __RPC_FAR *Save )(
+ IPersistStorage __RPC_FAR * This,
+ /* [unique][in] */ IStorage __RPC_FAR *pStgSave,
+ /* [in] */ BOOL fSameAsLoad);
+
+ HRESULT ( __stdcall __RPC_FAR *SaveCompleted )(
+ IPersistStorage __RPC_FAR * This,
+ /* [unique][in] */ IStorage __RPC_FAR *pStgNew);
+
+ HRESULT ( __stdcall __RPC_FAR *HandsOffStorage )(
+ IPersistStorage __RPC_FAR * This);
+
+ } IPersistStorageVtbl;
+
+ interface IPersistStorage
+ {
+ CONST_VTBL struct IPersistStorageVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IPersistStorage_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IPersistStorage_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IPersistStorage_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IPersistStorage_GetClassID(This,pClassID) \
+ (This)->lpVtbl -> GetClassID(This,pClassID)
+
+
+#define IPersistStorage_IsDirty(This) \
+ (This)->lpVtbl -> IsDirty(This)
+
+#define IPersistStorage_InitNew(This,pStg) \
+ (This)->lpVtbl -> InitNew(This,pStg)
+
+#define IPersistStorage_Load(This,pStg) \
+ (This)->lpVtbl -> Load(This,pStg)
+
+#define IPersistStorage_Save(This,pStgSave,fSameAsLoad) \
+ (This)->lpVtbl -> Save(This,pStgSave,fSameAsLoad)
+
+#define IPersistStorage_SaveCompleted(This,pStgNew) \
+ (This)->lpVtbl -> SaveCompleted(This,pStgNew)
+
+#define IPersistStorage_HandsOffStorage(This) \
+ (This)->lpVtbl -> HandsOffStorage(This)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IPersistStorage_IsDirty_Proxy(
+ IPersistStorage __RPC_FAR * This);
+
+
+void __RPC_STUB IPersistStorage_IsDirty_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IPersistStorage_InitNew_Proxy(
+ IPersistStorage __RPC_FAR * This,
+ /* [unique][in] */ IStorage __RPC_FAR *pStg);
+
+
+void __RPC_STUB IPersistStorage_InitNew_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IPersistStorage_Load_Proxy(
+ IPersistStorage __RPC_FAR * This,
+ /* [unique][in] */ IStorage __RPC_FAR *pStg);
+
+
+void __RPC_STUB IPersistStorage_Load_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IPersistStorage_Save_Proxy(
+ IPersistStorage __RPC_FAR * This,
+ /* [unique][in] */ IStorage __RPC_FAR *pStgSave,
+ /* [in] */ BOOL fSameAsLoad);
+
+
+void __RPC_STUB IPersistStorage_Save_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IPersistStorage_SaveCompleted_Proxy(
+ IPersistStorage __RPC_FAR * This,
+ /* [unique][in] */ IStorage __RPC_FAR *pStgNew);
+
+
+void __RPC_STUB IPersistStorage_SaveCompleted_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IPersistStorage_HandsOffStorage_Proxy(
+ IPersistStorage __RPC_FAR * This);
+
+
+void __RPC_STUB IPersistStorage_HandsOffStorage_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IPersistStorage_INTERFACE_DEFINED__ */
+
+
+#ifndef __ILockBytes_INTERFACE_DEFINED__
+#define __ILockBytes_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: ILockBytes
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ ILockBytes __RPC_FAR *LPLOCKBYTES;
+
+
+EXTERN_C const IID IID_ILockBytes;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface ILockBytes : public IUnknown
+ {
+ public:
+ virtual /* [local] */ HRESULT __stdcall ReadAt(
+ /* [in] */ ULARGE_INTEGER ulOffset,
+ /* [in] */ void __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbRead) = 0;
+
+ virtual /* [local] */ HRESULT __stdcall WriteAt(
+ /* [in] */ ULARGE_INTEGER ulOffset,
+ /* [in] */ const void __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbWritten) = 0;
+
+ virtual HRESULT __stdcall Flush( void) = 0;
+
+ virtual HRESULT __stdcall SetSize(
+ /* [in] */ ULARGE_INTEGER cb) = 0;
+
+ virtual HRESULT __stdcall LockRegion(
+ /* [in] */ ULARGE_INTEGER libOffset,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [in] */ DWORD dwLockType) = 0;
+
+ virtual HRESULT __stdcall UnlockRegion(
+ /* [in] */ ULARGE_INTEGER libOffset,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [in] */ DWORD dwLockType) = 0;
+
+ virtual HRESULT __stdcall Stat(
+ /* [out] */ STATSTG __RPC_FAR *pstatstg,
+ /* [in] */ DWORD grfStatFlag) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct ILockBytesVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ ILockBytes __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ ILockBytes __RPC_FAR * This);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *ReadAt )(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER ulOffset,
+ /* [in] */ void __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbRead);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *WriteAt )(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER ulOffset,
+ /* [in] */ const void __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbWritten);
+
+ HRESULT ( __stdcall __RPC_FAR *Flush )(
+ ILockBytes __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *SetSize )(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER cb);
+
+ HRESULT ( __stdcall __RPC_FAR *LockRegion )(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER libOffset,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [in] */ DWORD dwLockType);
+
+ HRESULT ( __stdcall __RPC_FAR *UnlockRegion )(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER libOffset,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [in] */ DWORD dwLockType);
+
+ HRESULT ( __stdcall __RPC_FAR *Stat )(
+ ILockBytes __RPC_FAR * This,
+ /* [out] */ STATSTG __RPC_FAR *pstatstg,
+ /* [in] */ DWORD grfStatFlag);
+
+ } ILockBytesVtbl;
+
+ interface ILockBytes
+ {
+ CONST_VTBL struct ILockBytesVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ILockBytes_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define ILockBytes_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define ILockBytes_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define ILockBytes_ReadAt(This,ulOffset,pv,cb,pcbRead) \
+ (This)->lpVtbl -> ReadAt(This,ulOffset,pv,cb,pcbRead)
+
+#define ILockBytes_WriteAt(This,ulOffset,pv,cb,pcbWritten) \
+ (This)->lpVtbl -> WriteAt(This,ulOffset,pv,cb,pcbWritten)
+
+#define ILockBytes_Flush(This) \
+ (This)->lpVtbl -> Flush(This)
+
+#define ILockBytes_SetSize(This,cb) \
+ (This)->lpVtbl -> SetSize(This,cb)
+
+#define ILockBytes_LockRegion(This,libOffset,cb,dwLockType) \
+ (This)->lpVtbl -> LockRegion(This,libOffset,cb,dwLockType)
+
+#define ILockBytes_UnlockRegion(This,libOffset,cb,dwLockType) \
+ (This)->lpVtbl -> UnlockRegion(This,libOffset,cb,dwLockType)
+
+#define ILockBytes_Stat(This,pstatstg,grfStatFlag) \
+ (This)->lpVtbl -> Stat(This,pstatstg,grfStatFlag)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [call_as] */ HRESULT __stdcall ILockBytes_RemoteReadAt_Proxy(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER ulOffset,
+ /* [length_is][size_is][out] */ byte __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbRead);
+
+
+void __RPC_STUB ILockBytes_RemoteReadAt_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [call_as] */ HRESULT __stdcall ILockBytes_RemoteWriteAt_Proxy(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER ulOffset,
+ /* [size_is][in] */ const byte __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbWritten);
+
+
+void __RPC_STUB ILockBytes_RemoteWriteAt_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ILockBytes_Flush_Proxy(
+ ILockBytes __RPC_FAR * This);
+
+
+void __RPC_STUB ILockBytes_Flush_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ILockBytes_SetSize_Proxy(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER cb);
+
+
+void __RPC_STUB ILockBytes_SetSize_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ILockBytes_LockRegion_Proxy(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER libOffset,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [in] */ DWORD dwLockType);
+
+
+void __RPC_STUB ILockBytes_LockRegion_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ILockBytes_UnlockRegion_Proxy(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER libOffset,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [in] */ DWORD dwLockType);
+
+
+void __RPC_STUB ILockBytes_UnlockRegion_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall ILockBytes_Stat_Proxy(
+ ILockBytes __RPC_FAR * This,
+ /* [out] */ STATSTG __RPC_FAR *pstatstg,
+ /* [in] */ DWORD grfStatFlag);
+
+
+void __RPC_STUB ILockBytes_Stat_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __ILockBytes_INTERFACE_DEFINED__ */
+
+
+#ifndef __IEnumFORMATETC_INTERFACE_DEFINED__
+#define __IEnumFORMATETC_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IEnumFORMATETC
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IEnumFORMATETC __RPC_FAR *LPENUMFORMATETC;
+
+ /* size is 12 */
+typedef struct tagDVTARGETDEVICE
+ {
+ DWORD tdSize;
+ WORD tdDriverNameOffset;
+ WORD tdDeviceNameOffset;
+ WORD tdPortNameOffset;
+ WORD tdExtDevmodeOffset;
+ /* [size_is] */ BYTE tdData[ 1 ];
+ } DVTARGETDEVICE;
+
+ /* size is 2 */
+typedef WORD CLIPFORMAT;
+
+ /* size is 4 */
+typedef CLIPFORMAT __RPC_FAR *LPCLIPFORMAT;
+
+ /* size is 20 */
+typedef struct tagFORMATETC
+ {
+ CLIPFORMAT cfFormat;
+ /* [unique] */ DVTARGETDEVICE __RPC_FAR *ptd;
+ DWORD dwAspect;
+ LONG lindex;
+ DWORD tymed;
+ } FORMATETC;
+
+ /* size is 4 */
+typedef struct tagFORMATETC __RPC_FAR *LPFORMATETC;
+
+
+EXTERN_C const IID IID_IEnumFORMATETC;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IEnumFORMATETC : public IUnknown
+ {
+ public:
+ virtual /* [local] */ HRESULT __stdcall Next(
+ /* [in] */ ULONG celt,
+ /* [out] */ FORMATETC __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched) = 0;
+
+ virtual HRESULT __stdcall Skip(
+ /* [in] */ ULONG celt) = 0;
+
+ virtual HRESULT __stdcall Reset( void) = 0;
+
+ virtual HRESULT __stdcall Clone(
+ /* [out] */ IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenum) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IEnumFORMATETCVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IEnumFORMATETC __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IEnumFORMATETC __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IEnumFORMATETC __RPC_FAR * This);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *Next )(
+ IEnumFORMATETC __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [out] */ FORMATETC __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+ HRESULT ( __stdcall __RPC_FAR *Skip )(
+ IEnumFORMATETC __RPC_FAR * This,
+ /* [in] */ ULONG celt);
+
+ HRESULT ( __stdcall __RPC_FAR *Reset )(
+ IEnumFORMATETC __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Clone )(
+ IEnumFORMATETC __RPC_FAR * This,
+ /* [out] */ IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenum);
+
+ } IEnumFORMATETCVtbl;
+
+ interface IEnumFORMATETC
+ {
+ CONST_VTBL struct IEnumFORMATETCVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IEnumFORMATETC_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IEnumFORMATETC_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IEnumFORMATETC_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IEnumFORMATETC_Next(This,celt,rgelt,pceltFetched) \
+ (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched)
+
+#define IEnumFORMATETC_Skip(This,celt) \
+ (This)->lpVtbl -> Skip(This,celt)
+
+#define IEnumFORMATETC_Reset(This) \
+ (This)->lpVtbl -> Reset(This)
+
+#define IEnumFORMATETC_Clone(This,ppenum) \
+ (This)->lpVtbl -> Clone(This,ppenum)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [call_as] */ HRESULT __stdcall IEnumFORMATETC_RemoteNext_Proxy(
+ IEnumFORMATETC __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ FORMATETC __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+
+void __RPC_STUB IEnumFORMATETC_RemoteNext_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumFORMATETC_Skip_Proxy(
+ IEnumFORMATETC __RPC_FAR * This,
+ /* [in] */ ULONG celt);
+
+
+void __RPC_STUB IEnumFORMATETC_Skip_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumFORMATETC_Reset_Proxy(
+ IEnumFORMATETC __RPC_FAR * This);
+
+
+void __RPC_STUB IEnumFORMATETC_Reset_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumFORMATETC_Clone_Proxy(
+ IEnumFORMATETC __RPC_FAR * This,
+ /* [out] */ IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenum);
+
+
+void __RPC_STUB IEnumFORMATETC_Clone_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IEnumFORMATETC_INTERFACE_DEFINED__ */
+
+
+#ifndef __IEnumSTATDATA_INTERFACE_DEFINED__
+#define __IEnumSTATDATA_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IEnumSTATDATA
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IEnumSTATDATA __RPC_FAR *LPENUMSTATDATA;
+
+ /* size is 2 */
+typedef
+enum tagADVF
+ { ADVF_NODATA = 1,
+ ADVF_PRIMEFIRST = 2,
+ ADVF_ONLYONCE = 4,
+ ADVF_DATAONSTOP = 64,
+ ADVFCACHE_NOHANDLER = 8,
+ ADVFCACHE_FORCEBUILTIN = 16,
+ ADVFCACHE_ONSAVE = 32
+ } ADVF;
+
+ /* size is 32 */
+typedef struct tagSTATDATA
+ {
+ FORMATETC formatetc;
+ DWORD advf;
+ /* [unique] */ IAdviseSink __RPC_FAR *pAdvSink;
+ DWORD dwConnection;
+ } STATDATA;
+
+ /* size is 4 */
+typedef STATDATA __RPC_FAR *LPSTATDATA;
+
+
+EXTERN_C const IID IID_IEnumSTATDATA;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IEnumSTATDATA : public IUnknown
+ {
+ public:
+ virtual /* [local] */ HRESULT __stdcall Next(
+ /* [in] */ ULONG celt,
+ STATDATA __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched) = 0;
+
+ virtual HRESULT __stdcall Skip(
+ /* [in] */ ULONG celt) = 0;
+
+ virtual HRESULT __stdcall Reset( void) = 0;
+
+ virtual HRESULT __stdcall Clone(
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenum) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IEnumSTATDATAVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IEnumSTATDATA __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IEnumSTATDATA __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IEnumSTATDATA __RPC_FAR * This);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *Next )(
+ IEnumSTATDATA __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ STATDATA __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+ HRESULT ( __stdcall __RPC_FAR *Skip )(
+ IEnumSTATDATA __RPC_FAR * This,
+ /* [in] */ ULONG celt);
+
+ HRESULT ( __stdcall __RPC_FAR *Reset )(
+ IEnumSTATDATA __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Clone )(
+ IEnumSTATDATA __RPC_FAR * This,
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenum);
+
+ } IEnumSTATDATAVtbl;
+
+ interface IEnumSTATDATA
+ {
+ CONST_VTBL struct IEnumSTATDATAVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IEnumSTATDATA_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IEnumSTATDATA_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IEnumSTATDATA_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IEnumSTATDATA_Next(This,celt,rgelt,pceltFetched) \
+ (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched)
+
+#define IEnumSTATDATA_Skip(This,celt) \
+ (This)->lpVtbl -> Skip(This,celt)
+
+#define IEnumSTATDATA_Reset(This) \
+ (This)->lpVtbl -> Reset(This)
+
+#define IEnumSTATDATA_Clone(This,ppenum) \
+ (This)->lpVtbl -> Clone(This,ppenum)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [call_as] */ HRESULT __stdcall IEnumSTATDATA_RemoteNext_Proxy(
+ IEnumSTATDATA __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ STATDATA __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+
+void __RPC_STUB IEnumSTATDATA_RemoteNext_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumSTATDATA_Skip_Proxy(
+ IEnumSTATDATA __RPC_FAR * This,
+ /* [in] */ ULONG celt);
+
+
+void __RPC_STUB IEnumSTATDATA_Skip_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumSTATDATA_Reset_Proxy(
+ IEnumSTATDATA __RPC_FAR * This);
+
+
+void __RPC_STUB IEnumSTATDATA_Reset_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumSTATDATA_Clone_Proxy(
+ IEnumSTATDATA __RPC_FAR * This,
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenum);
+
+
+void __RPC_STUB IEnumSTATDATA_Clone_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IEnumSTATDATA_INTERFACE_DEFINED__ */
+
+
+#ifndef __IRootStorage_INTERFACE_DEFINED__
+#define __IRootStorage_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IRootStorage
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IRootStorage __RPC_FAR *LPROOTSTORAGE;
+
+
+EXTERN_C const IID IID_IRootStorage;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IRootStorage : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall SwitchToFile(
+ /* [string][in] */ LPOLESTR pszFile) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IRootStorageVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IRootStorage __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IRootStorage __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IRootStorage __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *SwitchToFile )(
+ IRootStorage __RPC_FAR * This,
+ /* [string][in] */ LPOLESTR pszFile);
+
+ } IRootStorageVtbl;
+
+ interface IRootStorage
+ {
+ CONST_VTBL struct IRootStorageVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IRootStorage_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IRootStorage_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IRootStorage_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IRootStorage_SwitchToFile(This,pszFile) \
+ (This)->lpVtbl -> SwitchToFile(This,pszFile)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IRootStorage_SwitchToFile_Proxy(
+ IRootStorage __RPC_FAR * This,
+ /* [string][in] */ LPOLESTR pszFile);
+
+
+void __RPC_STUB IRootStorage_SwitchToFile_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IRootStorage_INTERFACE_DEFINED__ */
+
+
+#ifndef __IAdviseSink_INTERFACE_DEFINED__
+#define __IAdviseSink_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IAdviseSink
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef IAdviseSink __RPC_FAR *LPADVISESINK;
+
+ /* size is 2 */
+typedef /* [v1_enum] */
+enum tagTYMED
+ { TYMED_HGLOBAL = 1,
+ TYMED_FILE = 2,
+ TYMED_ISTREAM = 4,
+ TYMED_ISTORAGE = 8,
+ TYMED_GDI = 16,
+ TYMED_MFPICT = 32,
+ TYMED_ENHMF = 64,
+ TYMED_NULL = 0
+ } TYMED;
+
+#ifndef RC_INVOKED
+#pragma warning(disable:4200)
+#endif
+ /* size is 20 */
+typedef struct tagRemSTGMEDIUM
+ {
+ DWORD tymed;
+ DWORD dwHandleType;
+ unsigned long pData;
+ unsigned long pUnkForRelease;
+ unsigned long cbData;
+ /* [size_is] */ byte data[ 1 ];
+ } RemSTGMEDIUM;
+
+#ifndef RC_INVOKED
+#pragma warning(default:4200)
+#endif
+#ifdef NONAMELESSUNION
+typedef struct tagSTGMEDIUM {
+ DWORD tymed;
+ union {
+ HBITMAP hBitmap;
+ HMETAFILEPICT hMetaFilePict;
+ HENHMETAFILE hEnhMetaFile;
+ HGLOBAL hGlobal;
+ LPOLESTR lpszFileName;
+ IStream *pstm;
+ IStorage *pstg;
+ } u;
+ IUnknown *pUnkForRelease;
+}STGMEDIUM;
+#else
+ /* size is 12 */
+typedef struct tagSTGMEDIUM
+ {
+ DWORD tymed;
+ /* [switch_is][switch_type] */ union
+ {
+ /* [case] */ HBITMAP hBitmap;
+ /* [case] */ HMETAFILEPICT hMetaFilePict;
+ /* [case] */ HENHMETAFILE hEnhMetaFile;
+ /* [case] */ HGLOBAL hGlobal;
+ /* [case] */ LPOLESTR lpszFileName;
+ /* [case] */ IStream __RPC_FAR *pstm;
+ /* [case] */ IStorage __RPC_FAR *pstg;
+ /* [default] */ /* Empty union arm */
+ } ;
+ /* [unique] */ IUnknown __RPC_FAR *pUnkForRelease;
+ } STGMEDIUM;
+
+#endif /* !NONAMELESSUNION */
+ /* size is 4 */
+typedef STGMEDIUM __RPC_FAR *LPSTGMEDIUM;
+
+
+EXTERN_C const IID IID_IAdviseSink;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IAdviseSink : public IUnknown
+ {
+ public:
+ virtual /* [local] */ void __stdcall OnDataChange(
+ /* [unique][in] */ FORMATETC __RPC_FAR *pFormatetc,
+ /* [unique][in] */ STGMEDIUM __RPC_FAR *pStgmed) = 0;
+
+ virtual /* [local] */ void __stdcall OnViewChange(
+ /* [in] */ DWORD dwAspect,
+ /* [in] */ LONG lindex) = 0;
+
+ virtual /* [local] */ void __stdcall OnRename(
+ /* [in] */ IMoniker __RPC_FAR *pmk) = 0;
+
+ virtual /* [local] */ void __stdcall OnSave( void) = 0;
+
+ virtual /* [local] */ void __stdcall OnClose( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IAdviseSinkVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IAdviseSink __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IAdviseSink __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IAdviseSink __RPC_FAR * This);
+
+ /* [local] */ void ( __stdcall __RPC_FAR *OnDataChange )(
+ IAdviseSink __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pFormatetc,
+ /* [unique][in] */ STGMEDIUM __RPC_FAR *pStgmed);
+
+ /* [local] */ void ( __stdcall __RPC_FAR *OnViewChange )(
+ IAdviseSink __RPC_FAR * This,
+ /* [in] */ DWORD dwAspect,
+ /* [in] */ LONG lindex);
+
+ /* [local] */ void ( __stdcall __RPC_FAR *OnRename )(
+ IAdviseSink __RPC_FAR * This,
+ /* [in] */ IMoniker __RPC_FAR *pmk);
+
+ /* [local] */ void ( __stdcall __RPC_FAR *OnSave )(
+ IAdviseSink __RPC_FAR * This);
+
+ /* [local] */ void ( __stdcall __RPC_FAR *OnClose )(
+ IAdviseSink __RPC_FAR * This);
+
+ } IAdviseSinkVtbl;
+
+ interface IAdviseSink
+ {
+ CONST_VTBL struct IAdviseSinkVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IAdviseSink_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IAdviseSink_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IAdviseSink_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IAdviseSink_OnDataChange(This,pFormatetc,pStgmed) \
+ (This)->lpVtbl -> OnDataChange(This,pFormatetc,pStgmed)
+
+#define IAdviseSink_OnViewChange(This,dwAspect,lindex) \
+ (This)->lpVtbl -> OnViewChange(This,dwAspect,lindex)
+
+#define IAdviseSink_OnRename(This,pmk) \
+ (This)->lpVtbl -> OnRename(This,pmk)
+
+#define IAdviseSink_OnSave(This) \
+ (This)->lpVtbl -> OnSave(This)
+
+#define IAdviseSink_OnClose(This) \
+ (This)->lpVtbl -> OnClose(This)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [async][call_as] */ void __stdcall IAdviseSink_RemoteOnDataChange_Proxy(
+ IAdviseSink __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pFormatetc,
+ /* [unique][in] */ RemSTGMEDIUM __RPC_FAR *pStgmed);
+
+
+void __RPC_STUB IAdviseSink_RemoteOnDataChange_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [async][call_as] */ void __stdcall IAdviseSink_RemoteOnViewChange_Proxy(
+ IAdviseSink __RPC_FAR * This,
+ /* [in] */ DWORD dwAspect,
+ /* [in] */ LONG lindex);
+
+
+void __RPC_STUB IAdviseSink_RemoteOnViewChange_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [async][call_as] */ void __stdcall IAdviseSink_RemoteOnRename_Proxy(
+ IAdviseSink __RPC_FAR * This,
+ /* [in] */ IMoniker __RPC_FAR *pmk);
+
+
+void __RPC_STUB IAdviseSink_RemoteOnRename_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [async][call_as] */ void __stdcall IAdviseSink_RemoteOnSave_Proxy(
+ IAdviseSink __RPC_FAR * This);
+
+
+void __RPC_STUB IAdviseSink_RemoteOnSave_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [call_as] */ HRESULT __stdcall IAdviseSink_RemoteOnClose_Proxy(
+ IAdviseSink __RPC_FAR * This);
+
+
+void __RPC_STUB IAdviseSink_RemoteOnClose_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IAdviseSink_INTERFACE_DEFINED__ */
+
+
+#ifndef __IAdviseSink2_INTERFACE_DEFINED__
+#define __IAdviseSink2_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IAdviseSink2
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IAdviseSink2 __RPC_FAR *LPADVISESINK2;
+
+
+EXTERN_C const IID IID_IAdviseSink2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IAdviseSink2 : public IAdviseSink
+ {
+ public:
+ virtual /* [local] */ void __stdcall OnLinkSrcChange(
+ /* [unique][in] */ IMoniker __RPC_FAR *pmk) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IAdviseSink2Vtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IAdviseSink2 __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IAdviseSink2 __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IAdviseSink2 __RPC_FAR * This);
+
+ /* [local] */ void ( __stdcall __RPC_FAR *OnDataChange )(
+ IAdviseSink2 __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pFormatetc,
+ /* [unique][in] */ STGMEDIUM __RPC_FAR *pStgmed);
+
+ /* [local] */ void ( __stdcall __RPC_FAR *OnViewChange )(
+ IAdviseSink2 __RPC_FAR * This,
+ /* [in] */ DWORD dwAspect,
+ /* [in] */ LONG lindex);
+
+ /* [local] */ void ( __stdcall __RPC_FAR *OnRename )(
+ IAdviseSink2 __RPC_FAR * This,
+ /* [in] */ IMoniker __RPC_FAR *pmk);
+
+ /* [local] */ void ( __stdcall __RPC_FAR *OnSave )(
+ IAdviseSink2 __RPC_FAR * This);
+
+ /* [local] */ void ( __stdcall __RPC_FAR *OnClose )(
+ IAdviseSink2 __RPC_FAR * This);
+
+ /* [local] */ void ( __stdcall __RPC_FAR *OnLinkSrcChange )(
+ IAdviseSink2 __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmk);
+
+ } IAdviseSink2Vtbl;
+
+ interface IAdviseSink2
+ {
+ CONST_VTBL struct IAdviseSink2Vtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IAdviseSink2_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IAdviseSink2_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IAdviseSink2_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IAdviseSink2_OnDataChange(This,pFormatetc,pStgmed) \
+ (This)->lpVtbl -> OnDataChange(This,pFormatetc,pStgmed)
+
+#define IAdviseSink2_OnViewChange(This,dwAspect,lindex) \
+ (This)->lpVtbl -> OnViewChange(This,dwAspect,lindex)
+
+#define IAdviseSink2_OnRename(This,pmk) \
+ (This)->lpVtbl -> OnRename(This,pmk)
+
+#define IAdviseSink2_OnSave(This) \
+ (This)->lpVtbl -> OnSave(This)
+
+#define IAdviseSink2_OnClose(This) \
+ (This)->lpVtbl -> OnClose(This)
+
+
+#define IAdviseSink2_OnLinkSrcChange(This,pmk) \
+ (This)->lpVtbl -> OnLinkSrcChange(This,pmk)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [async][call_as] */ void __stdcall IAdviseSink2_RemoteOnLinkSrcChange_Proxy(
+ IAdviseSink2 __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmk);
+
+
+void __RPC_STUB IAdviseSink2_RemoteOnLinkSrcChange_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IAdviseSink2_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDataObject_INTERFACE_DEFINED__
+#define __IDataObject_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IDataObject
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IDataObject __RPC_FAR *LPDATAOBJECT;
+
+ /* size is 2 */
+typedef
+enum tagDATADIR
+ { DATADIR_GET = 1,
+ DATADIR_SET = 2
+ } DATADIR;
+
+
+EXTERN_C const IID IID_IDataObject;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IDataObject : public IUnknown
+ {
+ public:
+ virtual /* [local] */ HRESULT __stdcall GetData(
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetcIn,
+ /* [out] */ STGMEDIUM __RPC_FAR *pmedium) = 0;
+
+ virtual /* [local] */ HRESULT __stdcall GetDataHere(
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [out][in] */ STGMEDIUM __RPC_FAR *pmedium) = 0;
+
+ virtual HRESULT __stdcall QueryGetData(
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc) = 0;
+
+ virtual HRESULT __stdcall GetCanonicalFormatEtc(
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatectIn,
+ /* [out] */ FORMATETC __RPC_FAR *pformatetcOut) = 0;
+
+ virtual /* [local] */ HRESULT __stdcall SetData(
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [unique][in] */ STGMEDIUM __RPC_FAR *pmedium,
+ /* [in] */ BOOL fRelease) = 0;
+
+ virtual HRESULT __stdcall EnumFormatEtc(
+ /* [in] */ DWORD dwDirection,
+ /* [out] */ IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenumFormatEtc) = 0;
+
+ virtual HRESULT __stdcall DAdvise(
+ /* [in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [in] */ DWORD advf,
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection) = 0;
+
+ virtual HRESULT __stdcall DUnadvise(
+ /* [in] */ DWORD dwConnection) = 0;
+
+ virtual HRESULT __stdcall EnumDAdvise(
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IDataObjectVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IDataObject __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IDataObject __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IDataObject __RPC_FAR * This);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *GetData )(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetcIn,
+ /* [out] */ STGMEDIUM __RPC_FAR *pmedium);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *GetDataHere )(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [out][in] */ STGMEDIUM __RPC_FAR *pmedium);
+
+ HRESULT ( __stdcall __RPC_FAR *QueryGetData )(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc);
+
+ HRESULT ( __stdcall __RPC_FAR *GetCanonicalFormatEtc )(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatectIn,
+ /* [out] */ FORMATETC __RPC_FAR *pformatetcOut);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *SetData )(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [unique][in] */ STGMEDIUM __RPC_FAR *pmedium,
+ /* [in] */ BOOL fRelease);
+
+ HRESULT ( __stdcall __RPC_FAR *EnumFormatEtc )(
+ IDataObject __RPC_FAR * This,
+ /* [in] */ DWORD dwDirection,
+ /* [out] */ IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenumFormatEtc);
+
+ HRESULT ( __stdcall __RPC_FAR *DAdvise )(
+ IDataObject __RPC_FAR * This,
+ /* [in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [in] */ DWORD advf,
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection);
+
+ HRESULT ( __stdcall __RPC_FAR *DUnadvise )(
+ IDataObject __RPC_FAR * This,
+ /* [in] */ DWORD dwConnection);
+
+ HRESULT ( __stdcall __RPC_FAR *EnumDAdvise )(
+ IDataObject __RPC_FAR * This,
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise);
+
+ } IDataObjectVtbl;
+
+ interface IDataObject
+ {
+ CONST_VTBL struct IDataObjectVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDataObject_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IDataObject_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IDataObject_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IDataObject_GetData(This,pformatetcIn,pmedium) \
+ (This)->lpVtbl -> GetData(This,pformatetcIn,pmedium)
+
+#define IDataObject_GetDataHere(This,pformatetc,pmedium) \
+ (This)->lpVtbl -> GetDataHere(This,pformatetc,pmedium)
+
+#define IDataObject_QueryGetData(This,pformatetc) \
+ (This)->lpVtbl -> QueryGetData(This,pformatetc)
+
+#define IDataObject_GetCanonicalFormatEtc(This,pformatectIn,pformatetcOut) \
+ (This)->lpVtbl -> GetCanonicalFormatEtc(This,pformatectIn,pformatetcOut)
+
+#define IDataObject_SetData(This,pformatetc,pmedium,fRelease) \
+ (This)->lpVtbl -> SetData(This,pformatetc,pmedium,fRelease)
+
+#define IDataObject_EnumFormatEtc(This,dwDirection,ppenumFormatEtc) \
+ (This)->lpVtbl -> EnumFormatEtc(This,dwDirection,ppenumFormatEtc)
+
+#define IDataObject_DAdvise(This,pformatetc,advf,pAdvSink,pdwConnection) \
+ (This)->lpVtbl -> DAdvise(This,pformatetc,advf,pAdvSink,pdwConnection)
+
+#define IDataObject_DUnadvise(This,dwConnection) \
+ (This)->lpVtbl -> DUnadvise(This,dwConnection)
+
+#define IDataObject_EnumDAdvise(This,ppenumAdvise) \
+ (This)->lpVtbl -> EnumDAdvise(This,ppenumAdvise)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [call_as] */ HRESULT __stdcall IDataObject_RemoteGetData_Proxy(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetcIn,
+ /* [out] */ RemSTGMEDIUM __RPC_FAR *__RPC_FAR *ppRemoteMedium);
+
+
+void __RPC_STUB IDataObject_RemoteGetData_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [call_as] */ HRESULT __stdcall IDataObject_RemoteGetDataHere_Proxy(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [out][in] */ RemSTGMEDIUM __RPC_FAR *__RPC_FAR *ppRemoteMedium);
+
+
+void __RPC_STUB IDataObject_RemoteGetDataHere_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDataObject_QueryGetData_Proxy(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc);
+
+
+void __RPC_STUB IDataObject_QueryGetData_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDataObject_GetCanonicalFormatEtc_Proxy(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatectIn,
+ /* [out] */ FORMATETC __RPC_FAR *pformatetcOut);
+
+
+void __RPC_STUB IDataObject_GetCanonicalFormatEtc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [call_as] */ HRESULT __stdcall IDataObject_RemoteSetData_Proxy(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [unique][in] */ RemSTGMEDIUM __RPC_FAR *pmedium,
+ /* [in] */ BOOL fRelease);
+
+
+void __RPC_STUB IDataObject_RemoteSetData_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDataObject_EnumFormatEtc_Proxy(
+ IDataObject __RPC_FAR * This,
+ /* [in] */ DWORD dwDirection,
+ /* [out] */ IEnumFORMATETC __RPC_FAR *__RPC_FAR *ppenumFormatEtc);
+
+
+void __RPC_STUB IDataObject_EnumFormatEtc_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDataObject_DAdvise_Proxy(
+ IDataObject __RPC_FAR * This,
+ /* [in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [in] */ DWORD advf,
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection);
+
+
+void __RPC_STUB IDataObject_DAdvise_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDataObject_DUnadvise_Proxy(
+ IDataObject __RPC_FAR * This,
+ /* [in] */ DWORD dwConnection);
+
+
+void __RPC_STUB IDataObject_DUnadvise_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDataObject_EnumDAdvise_Proxy(
+ IDataObject __RPC_FAR * This,
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise);
+
+
+void __RPC_STUB IDataObject_EnumDAdvise_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IDataObject_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDataAdviseHolder_INTERFACE_DEFINED__
+#define __IDataAdviseHolder_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IDataAdviseHolder
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IDataAdviseHolder __RPC_FAR *LPDATAADVISEHOLDER;
+
+
+EXTERN_C const IID IID_IDataAdviseHolder;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IDataAdviseHolder : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall Advise(
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObject,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pFetc,
+ /* [in] */ DWORD advf,
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvise,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection) = 0;
+
+ virtual HRESULT __stdcall Unadvise(
+ /* [in] */ DWORD dwConnection) = 0;
+
+ virtual HRESULT __stdcall EnumAdvise(
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise) = 0;
+
+ virtual HRESULT __stdcall SendOnDataChange(
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObject,
+ /* [in] */ DWORD dwReserved,
+ /* [in] */ DWORD advf) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IDataAdviseHolderVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IDataAdviseHolder __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IDataAdviseHolder __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IDataAdviseHolder __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Advise )(
+ IDataAdviseHolder __RPC_FAR * This,
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObject,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pFetc,
+ /* [in] */ DWORD advf,
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvise,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection);
+
+ HRESULT ( __stdcall __RPC_FAR *Unadvise )(
+ IDataAdviseHolder __RPC_FAR * This,
+ /* [in] */ DWORD dwConnection);
+
+ HRESULT ( __stdcall __RPC_FAR *EnumAdvise )(
+ IDataAdviseHolder __RPC_FAR * This,
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise);
+
+ HRESULT ( __stdcall __RPC_FAR *SendOnDataChange )(
+ IDataAdviseHolder __RPC_FAR * This,
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObject,
+ /* [in] */ DWORD dwReserved,
+ /* [in] */ DWORD advf);
+
+ } IDataAdviseHolderVtbl;
+
+ interface IDataAdviseHolder
+ {
+ CONST_VTBL struct IDataAdviseHolderVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDataAdviseHolder_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IDataAdviseHolder_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IDataAdviseHolder_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IDataAdviseHolder_Advise(This,pDataObject,pFetc,advf,pAdvise,pdwConnection) \
+ (This)->lpVtbl -> Advise(This,pDataObject,pFetc,advf,pAdvise,pdwConnection)
+
+#define IDataAdviseHolder_Unadvise(This,dwConnection) \
+ (This)->lpVtbl -> Unadvise(This,dwConnection)
+
+#define IDataAdviseHolder_EnumAdvise(This,ppenumAdvise) \
+ (This)->lpVtbl -> EnumAdvise(This,ppenumAdvise)
+
+#define IDataAdviseHolder_SendOnDataChange(This,pDataObject,dwReserved,advf) \
+ (This)->lpVtbl -> SendOnDataChange(This,pDataObject,dwReserved,advf)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IDataAdviseHolder_Advise_Proxy(
+ IDataAdviseHolder __RPC_FAR * This,
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObject,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pFetc,
+ /* [in] */ DWORD advf,
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvise,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection);
+
+
+void __RPC_STUB IDataAdviseHolder_Advise_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDataAdviseHolder_Unadvise_Proxy(
+ IDataAdviseHolder __RPC_FAR * This,
+ /* [in] */ DWORD dwConnection);
+
+
+void __RPC_STUB IDataAdviseHolder_Unadvise_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDataAdviseHolder_EnumAdvise_Proxy(
+ IDataAdviseHolder __RPC_FAR * This,
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise);
+
+
+void __RPC_STUB IDataAdviseHolder_EnumAdvise_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDataAdviseHolder_SendOnDataChange_Proxy(
+ IDataAdviseHolder __RPC_FAR * This,
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObject,
+ /* [in] */ DWORD dwReserved,
+ /* [in] */ DWORD advf);
+
+
+void __RPC_STUB IDataAdviseHolder_SendOnDataChange_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IDataAdviseHolder_INTERFACE_DEFINED__ */
+
+
+#ifndef __IMessageFilter_INTERFACE_DEFINED__
+#define __IMessageFilter_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IMessageFilter
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IMessageFilter __RPC_FAR *LPMESSAGEFILTER;
+
+ /* size is 2 */
+typedef
+enum tagCALLTYPE
+ { CALLTYPE_TOPLEVEL = 1,
+ CALLTYPE_NESTED = 2,
+ CALLTYPE_ASYNC = 3,
+ CALLTYPE_TOPLEVEL_CALLPENDING = 4,
+ CALLTYPE_ASYNC_CALLPENDING = 5
+ } CALLTYPE;
+
+ /* size is 2 */
+typedef
+enum tagSERVERCALL
+ { SERVERCALL_ISHANDLED = 0,
+ SERVERCALL_REJECTED = 1,
+ SERVERCALL_RETRYLATER = 2
+ } SERVERCALL;
+
+ /* size is 2 */
+typedef
+enum tagPENDINGTYPE
+ { PENDINGTYPE_TOPLEVEL = 1,
+ PENDINGTYPE_NESTED = 2
+ } PENDINGTYPE;
+
+ /* size is 2 */
+typedef
+enum tagPENDINGMSG
+ { PENDINGMSG_CANCELCALL = 0,
+ PENDINGMSG_WAITNOPROCESS = 1,
+ PENDINGMSG_WAITDEFPROCESS = 2
+ } PENDINGMSG;
+
+ /* size is 22 */
+typedef struct tagINTERFACEINFO
+ {
+ IUnknown __RPC_FAR *pUnk;
+ IID iid;
+ WORD wMethod;
+ } INTERFACEINFO;
+
+ /* size is 4 */
+typedef struct tagINTERFACEINFO __RPC_FAR *LPINTERFACEINFO;
+
+
+EXTERN_C const IID IID_IMessageFilter;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IMessageFilter : public IUnknown
+ {
+ public:
+ virtual DWORD __stdcall HandleInComingCall(
+ /* [in] */ DWORD dwCallType,
+ /* [in] */ HTASK htaskCaller,
+ /* [in] */ DWORD dwTickCount,
+ /* [in] */ LPINTERFACEINFO lpInterfaceInfo) = 0;
+
+ virtual DWORD __stdcall RetryRejectedCall(
+ /* [in] */ HTASK htaskCallee,
+ /* [in] */ DWORD dwTickCount,
+ /* [in] */ DWORD dwRejectType) = 0;
+
+ virtual DWORD __stdcall MessagePending(
+ /* [in] */ HTASK htaskCallee,
+ /* [in] */ DWORD dwTickCount,
+ /* [in] */ DWORD dwPendingType) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IMessageFilterVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IMessageFilter __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IMessageFilter __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IMessageFilter __RPC_FAR * This);
+
+ DWORD ( __stdcall __RPC_FAR *HandleInComingCall )(
+ IMessageFilter __RPC_FAR * This,
+ /* [in] */ DWORD dwCallType,
+ /* [in] */ HTASK htaskCaller,
+ /* [in] */ DWORD dwTickCount,
+ /* [in] */ LPINTERFACEINFO lpInterfaceInfo);
+
+ DWORD ( __stdcall __RPC_FAR *RetryRejectedCall )(
+ IMessageFilter __RPC_FAR * This,
+ /* [in] */ HTASK htaskCallee,
+ /* [in] */ DWORD dwTickCount,
+ /* [in] */ DWORD dwRejectType);
+
+ DWORD ( __stdcall __RPC_FAR *MessagePending )(
+ IMessageFilter __RPC_FAR * This,
+ /* [in] */ HTASK htaskCallee,
+ /* [in] */ DWORD dwTickCount,
+ /* [in] */ DWORD dwPendingType);
+
+ } IMessageFilterVtbl;
+
+ interface IMessageFilter
+ {
+ CONST_VTBL struct IMessageFilterVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IMessageFilter_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IMessageFilter_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IMessageFilter_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IMessageFilter_HandleInComingCall(This,dwCallType,htaskCaller,dwTickCount,lpInterfaceInfo) \
+ (This)->lpVtbl -> HandleInComingCall(This,dwCallType,htaskCaller,dwTickCount,lpInterfaceInfo)
+
+#define IMessageFilter_RetryRejectedCall(This,htaskCallee,dwTickCount,dwRejectType) \
+ (This)->lpVtbl -> RetryRejectedCall(This,htaskCallee,dwTickCount,dwRejectType)
+
+#define IMessageFilter_MessagePending(This,htaskCallee,dwTickCount,dwPendingType) \
+ (This)->lpVtbl -> MessagePending(This,htaskCallee,dwTickCount,dwPendingType)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+DWORD __stdcall IMessageFilter_HandleInComingCall_Proxy(
+ IMessageFilter __RPC_FAR * This,
+ /* [in] */ DWORD dwCallType,
+ /* [in] */ HTASK htaskCaller,
+ /* [in] */ DWORD dwTickCount,
+ /* [in] */ LPINTERFACEINFO lpInterfaceInfo);
+
+
+void __RPC_STUB IMessageFilter_HandleInComingCall_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+DWORD __stdcall IMessageFilter_RetryRejectedCall_Proxy(
+ IMessageFilter __RPC_FAR * This,
+ /* [in] */ HTASK htaskCallee,
+ /* [in] */ DWORD dwTickCount,
+ /* [in] */ DWORD dwRejectType);
+
+
+void __RPC_STUB IMessageFilter_RetryRejectedCall_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+DWORD __stdcall IMessageFilter_MessagePending_Proxy(
+ IMessageFilter __RPC_FAR * This,
+ /* [in] */ HTASK htaskCallee,
+ /* [in] */ DWORD dwTickCount,
+ /* [in] */ DWORD dwPendingType);
+
+
+void __RPC_STUB IMessageFilter_MessagePending_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IMessageFilter_INTERFACE_DEFINED__ */
+
+
+#ifndef __IRpcChannelBuffer_INTERFACE_DEFINED__
+#define __IRpcChannelBuffer_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IRpcChannelBuffer
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+ /* size is 4 */
+typedef unsigned long RPCOLEDATAREP;
+
+ /* size is 44 */
+typedef struct tagRPCOLEMESSAGE
+ {
+ void __RPC_FAR *reserved1;
+ RPCOLEDATAREP dataRepresentation;
+ void __RPC_FAR *Buffer;
+ ULONG cbBuffer;
+ ULONG iMethod;
+ void __RPC_FAR *reserved2[ 5 ];
+ ULONG rpcFlags;
+ } RPCOLEMESSAGE;
+
+ /* size is 4 */
+typedef RPCOLEMESSAGE __RPC_FAR *PRPCOLEMESSAGE;
+
+
+EXTERN_C const IID IID_IRpcChannelBuffer;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IRpcChannelBuffer : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall GetBuffer(
+ /* [in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+ /* [in] */ REFIID riid) = 0;
+
+ virtual HRESULT __stdcall SendReceive(
+ /* [out][in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+ /* [out] */ ULONG __RPC_FAR *pStatus) = 0;
+
+ virtual HRESULT __stdcall FreeBuffer(
+ /* [in] */ RPCOLEMESSAGE __RPC_FAR *pMessage) = 0;
+
+ virtual HRESULT __stdcall GetDestCtx(
+ /* [out] */ DWORD __RPC_FAR *pdwDestContext,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvDestContext) = 0;
+
+ virtual HRESULT __stdcall IsConnected( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IRpcChannelBufferVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IRpcChannelBuffer __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IRpcChannelBuffer __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IRpcChannelBuffer __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetBuffer )(
+ IRpcChannelBuffer __RPC_FAR * This,
+ /* [in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+ /* [in] */ REFIID riid);
+
+ HRESULT ( __stdcall __RPC_FAR *SendReceive )(
+ IRpcChannelBuffer __RPC_FAR * This,
+ /* [out][in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+ /* [out] */ ULONG __RPC_FAR *pStatus);
+
+ HRESULT ( __stdcall __RPC_FAR *FreeBuffer )(
+ IRpcChannelBuffer __RPC_FAR * This,
+ /* [in] */ RPCOLEMESSAGE __RPC_FAR *pMessage);
+
+ HRESULT ( __stdcall __RPC_FAR *GetDestCtx )(
+ IRpcChannelBuffer __RPC_FAR * This,
+ /* [out] */ DWORD __RPC_FAR *pdwDestContext,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvDestContext);
+
+ HRESULT ( __stdcall __RPC_FAR *IsConnected )(
+ IRpcChannelBuffer __RPC_FAR * This);
+
+ } IRpcChannelBufferVtbl;
+
+ interface IRpcChannelBuffer
+ {
+ CONST_VTBL struct IRpcChannelBufferVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IRpcChannelBuffer_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IRpcChannelBuffer_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IRpcChannelBuffer_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IRpcChannelBuffer_GetBuffer(This,pMessage,riid) \
+ (This)->lpVtbl -> GetBuffer(This,pMessage,riid)
+
+#define IRpcChannelBuffer_SendReceive(This,pMessage,pStatus) \
+ (This)->lpVtbl -> SendReceive(This,pMessage,pStatus)
+
+#define IRpcChannelBuffer_FreeBuffer(This,pMessage) \
+ (This)->lpVtbl -> FreeBuffer(This,pMessage)
+
+#define IRpcChannelBuffer_GetDestCtx(This,pdwDestContext,ppvDestContext) \
+ (This)->lpVtbl -> GetDestCtx(This,pdwDestContext,ppvDestContext)
+
+#define IRpcChannelBuffer_IsConnected(This) \
+ (This)->lpVtbl -> IsConnected(This)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IRpcChannelBuffer_GetBuffer_Proxy(
+ IRpcChannelBuffer __RPC_FAR * This,
+ /* [in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+ /* [in] */ REFIID riid);
+
+
+void __RPC_STUB IRpcChannelBuffer_GetBuffer_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRpcChannelBuffer_SendReceive_Proxy(
+ IRpcChannelBuffer __RPC_FAR * This,
+ /* [out][in] */ RPCOLEMESSAGE __RPC_FAR *pMessage,
+ /* [out] */ ULONG __RPC_FAR *pStatus);
+
+
+void __RPC_STUB IRpcChannelBuffer_SendReceive_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRpcChannelBuffer_FreeBuffer_Proxy(
+ IRpcChannelBuffer __RPC_FAR * This,
+ /* [in] */ RPCOLEMESSAGE __RPC_FAR *pMessage);
+
+
+void __RPC_STUB IRpcChannelBuffer_FreeBuffer_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRpcChannelBuffer_GetDestCtx_Proxy(
+ IRpcChannelBuffer __RPC_FAR * This,
+ /* [out] */ DWORD __RPC_FAR *pdwDestContext,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvDestContext);
+
+
+void __RPC_STUB IRpcChannelBuffer_GetDestCtx_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRpcChannelBuffer_IsConnected_Proxy(
+ IRpcChannelBuffer __RPC_FAR * This);
+
+
+void __RPC_STUB IRpcChannelBuffer_IsConnected_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IRpcChannelBuffer_INTERFACE_DEFINED__ */
+
+
+#ifndef __IRpcProxyBuffer_INTERFACE_DEFINED__
+#define __IRpcProxyBuffer_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IRpcProxyBuffer
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+
+EXTERN_C const IID IID_IRpcProxyBuffer;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IRpcProxyBuffer : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall Connect(
+ /* [unique][in] */ IRpcChannelBuffer __RPC_FAR *pRpcChannelBuffer) = 0;
+
+ virtual void __stdcall Disconnect( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IRpcProxyBufferVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IRpcProxyBuffer __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IRpcProxyBuffer __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IRpcProxyBuffer __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Connect )(
+ IRpcProxyBuffer __RPC_FAR * This,
+ /* [unique][in] */ IRpcChannelBuffer __RPC_FAR *pRpcChannelBuffer);
+
+ void ( __stdcall __RPC_FAR *Disconnect )(
+ IRpcProxyBuffer __RPC_FAR * This);
+
+ } IRpcProxyBufferVtbl;
+
+ interface IRpcProxyBuffer
+ {
+ CONST_VTBL struct IRpcProxyBufferVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IRpcProxyBuffer_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IRpcProxyBuffer_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IRpcProxyBuffer_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IRpcProxyBuffer_Connect(This,pRpcChannelBuffer) \
+ (This)->lpVtbl -> Connect(This,pRpcChannelBuffer)
+
+#define IRpcProxyBuffer_Disconnect(This) \
+ (This)->lpVtbl -> Disconnect(This)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IRpcProxyBuffer_Connect_Proxy(
+ IRpcProxyBuffer __RPC_FAR * This,
+ /* [unique][in] */ IRpcChannelBuffer __RPC_FAR *pRpcChannelBuffer);
+
+
+void __RPC_STUB IRpcProxyBuffer_Connect_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __stdcall IRpcProxyBuffer_Disconnect_Proxy(
+ IRpcProxyBuffer __RPC_FAR * This);
+
+
+void __RPC_STUB IRpcProxyBuffer_Disconnect_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IRpcProxyBuffer_INTERFACE_DEFINED__ */
+
+
+#ifndef __IRpcStubBuffer_INTERFACE_DEFINED__
+#define __IRpcStubBuffer_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IRpcStubBuffer
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+
+EXTERN_C const IID IID_IRpcStubBuffer;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IRpcStubBuffer : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall Connect(
+ /* [in] */ IUnknown __RPC_FAR *pUnkServer) = 0;
+
+ virtual void __stdcall Disconnect( void) = 0;
+
+ virtual HRESULT __stdcall Invoke(
+ /* [in] */ RPCOLEMESSAGE __RPC_FAR *_prpcmsg,
+ /* [in] */ IRpcChannelBuffer __RPC_FAR *_pRpcChannelBuffer) = 0;
+
+ virtual IRpcStubBuffer __RPC_FAR *__stdcall IsIIDSupported(
+ /* [in] */ REFIID riid) = 0;
+
+ virtual ULONG __stdcall CountRefs( void) = 0;
+
+ virtual HRESULT __stdcall DebugServerQueryInterface(
+ void __RPC_FAR *__RPC_FAR *ppv) = 0;
+
+ virtual void __stdcall DebugServerRelease(
+ void __RPC_FAR *pv) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IRpcStubBufferVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IRpcStubBuffer __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IRpcStubBuffer __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IRpcStubBuffer __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Connect )(
+ IRpcStubBuffer __RPC_FAR * This,
+ /* [in] */ IUnknown __RPC_FAR *pUnkServer);
+
+ void ( __stdcall __RPC_FAR *Disconnect )(
+ IRpcStubBuffer __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Invoke )(
+ IRpcStubBuffer __RPC_FAR * This,
+ /* [in] */ RPCOLEMESSAGE __RPC_FAR *_prpcmsg,
+ /* [in] */ IRpcChannelBuffer __RPC_FAR *_pRpcChannelBuffer);
+
+ IRpcStubBuffer __RPC_FAR *( __stdcall __RPC_FAR *IsIIDSupported )(
+ IRpcStubBuffer __RPC_FAR * This,
+ /* [in] */ REFIID riid);
+
+ ULONG ( __stdcall __RPC_FAR *CountRefs )(
+ IRpcStubBuffer __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *DebugServerQueryInterface )(
+ IRpcStubBuffer __RPC_FAR * This,
+ void __RPC_FAR *__RPC_FAR *ppv);
+
+ void ( __stdcall __RPC_FAR *DebugServerRelease )(
+ IRpcStubBuffer __RPC_FAR * This,
+ void __RPC_FAR *pv);
+
+ } IRpcStubBufferVtbl;
+
+ interface IRpcStubBuffer
+ {
+ CONST_VTBL struct IRpcStubBufferVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IRpcStubBuffer_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IRpcStubBuffer_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IRpcStubBuffer_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IRpcStubBuffer_Connect(This,pUnkServer) \
+ (This)->lpVtbl -> Connect(This,pUnkServer)
+
+#define IRpcStubBuffer_Disconnect(This) \
+ (This)->lpVtbl -> Disconnect(This)
+
+#define IRpcStubBuffer_Invoke(This,_prpcmsg,_pRpcChannelBuffer) \
+ (This)->lpVtbl -> Invoke(This,_prpcmsg,_pRpcChannelBuffer)
+
+#define IRpcStubBuffer_IsIIDSupported(This,riid) \
+ (This)->lpVtbl -> IsIIDSupported(This,riid)
+
+#define IRpcStubBuffer_CountRefs(This) \
+ (This)->lpVtbl -> CountRefs(This)
+
+#define IRpcStubBuffer_DebugServerQueryInterface(This,ppv) \
+ (This)->lpVtbl -> DebugServerQueryInterface(This,ppv)
+
+#define IRpcStubBuffer_DebugServerRelease(This,pv) \
+ (This)->lpVtbl -> DebugServerRelease(This,pv)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IRpcStubBuffer_Connect_Proxy(
+ IRpcStubBuffer __RPC_FAR * This,
+ /* [in] */ IUnknown __RPC_FAR *pUnkServer);
+
+
+void __RPC_STUB IRpcStubBuffer_Connect_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __stdcall IRpcStubBuffer_Disconnect_Proxy(
+ IRpcStubBuffer __RPC_FAR * This);
+
+
+void __RPC_STUB IRpcStubBuffer_Disconnect_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRpcStubBuffer_Invoke_Proxy(
+ IRpcStubBuffer __RPC_FAR * This,
+ /* [in] */ RPCOLEMESSAGE __RPC_FAR *_prpcmsg,
+ /* [in] */ IRpcChannelBuffer __RPC_FAR *_pRpcChannelBuffer);
+
+
+void __RPC_STUB IRpcStubBuffer_Invoke_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+IRpcStubBuffer __RPC_FAR *__stdcall IRpcStubBuffer_IsIIDSupported_Proxy(
+ IRpcStubBuffer __RPC_FAR * This,
+ /* [in] */ REFIID riid);
+
+
+void __RPC_STUB IRpcStubBuffer_IsIIDSupported_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+ULONG __stdcall IRpcStubBuffer_CountRefs_Proxy(
+ IRpcStubBuffer __RPC_FAR * This);
+
+
+void __RPC_STUB IRpcStubBuffer_CountRefs_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IRpcStubBuffer_DebugServerQueryInterface_Proxy(
+ IRpcStubBuffer __RPC_FAR * This,
+ void __RPC_FAR *__RPC_FAR *ppv);
+
+
+void __RPC_STUB IRpcStubBuffer_DebugServerQueryInterface_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+void __stdcall IRpcStubBuffer_DebugServerRelease_Proxy(
+ IRpcStubBuffer __RPC_FAR * This,
+ void __RPC_FAR *pv);
+
+
+void __RPC_STUB IRpcStubBuffer_DebugServerRelease_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IRpcStubBuffer_INTERFACE_DEFINED__ */
+
+
+#ifndef __IPSFactoryBuffer_INTERFACE_DEFINED__
+#define __IPSFactoryBuffer_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IPSFactoryBuffer
+ * at Fri Apr 28 07:02:32 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+
+EXTERN_C const IID IID_IPSFactoryBuffer;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IPSFactoryBuffer : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall CreateProxy(
+ /* [in] */ IUnknown __RPC_FAR *pUnkOuter,
+ /* [in] */ REFIID riid,
+ /* [out] */ IRpcProxyBuffer __RPC_FAR *__RPC_FAR *ppProxy,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppv) = 0;
+
+ virtual HRESULT __stdcall CreateStub(
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ IUnknown __RPC_FAR *pUnkServer,
+ /* [out] */ IRpcStubBuffer __RPC_FAR *__RPC_FAR *ppStub) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IPSFactoryBufferVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IPSFactoryBuffer __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IPSFactoryBuffer __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IPSFactoryBuffer __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *CreateProxy )(
+ IPSFactoryBuffer __RPC_FAR * This,
+ /* [in] */ IUnknown __RPC_FAR *pUnkOuter,
+ /* [in] */ REFIID riid,
+ /* [out] */ IRpcProxyBuffer __RPC_FAR *__RPC_FAR *ppProxy,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppv);
+
+ HRESULT ( __stdcall __RPC_FAR *CreateStub )(
+ IPSFactoryBuffer __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ IUnknown __RPC_FAR *pUnkServer,
+ /* [out] */ IRpcStubBuffer __RPC_FAR *__RPC_FAR *ppStub);
+
+ } IPSFactoryBufferVtbl;
+
+ interface IPSFactoryBuffer
+ {
+ CONST_VTBL struct IPSFactoryBufferVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IPSFactoryBuffer_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IPSFactoryBuffer_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IPSFactoryBuffer_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IPSFactoryBuffer_CreateProxy(This,pUnkOuter,riid,ppProxy,ppv) \
+ (This)->lpVtbl -> CreateProxy(This,pUnkOuter,riid,ppProxy,ppv)
+
+#define IPSFactoryBuffer_CreateStub(This,riid,pUnkServer,ppStub) \
+ (This)->lpVtbl -> CreateStub(This,riid,pUnkServer,ppStub)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IPSFactoryBuffer_CreateProxy_Proxy(
+ IPSFactoryBuffer __RPC_FAR * This,
+ /* [in] */ IUnknown __RPC_FAR *pUnkOuter,
+ /* [in] */ REFIID riid,
+ /* [out] */ IRpcProxyBuffer __RPC_FAR *__RPC_FAR *ppProxy,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppv);
+
+
+void __RPC_STUB IPSFactoryBuffer_CreateProxy_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IPSFactoryBuffer_CreateStub_Proxy(
+ IPSFactoryBuffer __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [unique][in] */ IUnknown __RPC_FAR *pUnkServer,
+ /* [out] */ IRpcStubBuffer __RPC_FAR *__RPC_FAR *ppStub);
+
+
+void __RPC_STUB IPSFactoryBuffer_CreateStub_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IPSFactoryBuffer_INTERFACE_DEFINED__ */
+
+
+/* Additional Prototypes for ALL interfaces */
+
+
+void __RPC_USER SNB_to_xmit( SNB __RPC_FAR *, RemSNB __RPC_FAR * __RPC_FAR * );
+void __RPC_USER SNB_from_xmit( RemSNB __RPC_FAR *, SNB __RPC_FAR * );
+void __RPC_USER SNB_free_inst( SNB __RPC_FAR * );
+void __RPC_USER SNB_free_xmit( RemSNB __RPC_FAR * );
+
+/* [local] */ HRESULT __stdcall IEnumUnknown_Next_Proxy(
+ IEnumUnknown __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+
+/* [call_as] */ HRESULT __stdcall IEnumUnknown_Next_Stub(
+ IEnumUnknown __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+/* [local] */ HRESULT __stdcall IEnumMoniker_Next_Proxy(
+ IEnumMoniker __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+
+/* [call_as] */ HRESULT __stdcall IEnumMoniker_Next_Stub(
+ IEnumMoniker __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ IMoniker __RPC_FAR *__RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+/* [local] */ HRESULT __stdcall IMoniker_BindToObject_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [in] */ REFIID riidResult,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvResult);
+
+
+/* [call_as] */ HRESULT __stdcall IMoniker_BindToObject_Stub(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [in] */ REFIID riidResult,
+ /* [iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppvResult);
+
+/* [local] */ HRESULT __stdcall IMoniker_BindToStorage_Proxy(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObj);
+
+
+/* [call_as] */ HRESULT __stdcall IMoniker_BindToStorage_Stub(
+ IMoniker __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppvObj);
+
+/* [local] */ HRESULT __stdcall IEnumString_Next_Proxy(
+ IEnumString __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [out] */ LPOLESTR __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+
+/* [call_as] */ HRESULT __stdcall IEnumString_Next_Stub(
+ IEnumString __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ LPOLESTR __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+/* [local] */ HRESULT __stdcall IStream_Read_Proxy(
+ IStream __RPC_FAR * This,
+ /* [out] */ void __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbRead);
+
+
+/* [call_as] */ HRESULT __stdcall IStream_Read_Stub(
+ IStream __RPC_FAR * This,
+ /* [length_is][size_is][out] */ byte __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbRead);
+
+/* [local] */ HRESULT __stdcall IStream_Write_Proxy(
+ IStream __RPC_FAR * This,
+ /* [size_is][in] */ const void __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbWritten);
+
+
+/* [call_as] */ HRESULT __stdcall IStream_Write_Stub(
+ IStream __RPC_FAR * This,
+ /* [size_is][in] */ const byte __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbWritten);
+
+/* [local] */ HRESULT __stdcall IStream_Seek_Proxy(
+ IStream __RPC_FAR * This,
+ /* [in] */ LARGE_INTEGER dlibMove,
+ /* [in] */ DWORD dwOrigin,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *plibNewPosition);
+
+
+/* [call_as] */ HRESULT __stdcall IStream_Seek_Stub(
+ IStream __RPC_FAR * This,
+ /* [in] */ LARGE_INTEGER dlibMove,
+ /* [in] */ DWORD dwOrigin,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *plibNewPosition);
+
+/* [local] */ HRESULT __stdcall IStream_CopyTo_Proxy(
+ IStream __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pstm,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbRead,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbWritten);
+
+
+/* [call_as] */ HRESULT __stdcall IStream_CopyTo_Stub(
+ IStream __RPC_FAR * This,
+ /* [unique][in] */ IStream __RPC_FAR *pstm,
+ /* [in] */ ULARGE_INTEGER cb,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbRead,
+ /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbWritten);
+
+/* [local] */ HRESULT __stdcall IEnumSTATSTG_Next_Proxy(
+ IEnumSTATSTG __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [in] */ STATSTG __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+
+/* [call_as] */ HRESULT __stdcall IEnumSTATSTG_Next_Stub(
+ IEnumSTATSTG __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ STATSTG __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+/* [local] */ HRESULT __stdcall IStorage_OpenStream_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [unique][in] */ void __RPC_FAR *reserved1,
+ /* [in] */ DWORD grfMode,
+ /* [in] */ DWORD reserved2,
+ /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
+
+
+/* [call_as] */ HRESULT __stdcall IStorage_OpenStream_Stub(
+ IStorage __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ unsigned long cbReserved1,
+ /* [size_is][unique][in] */ byte __RPC_FAR *reserved1,
+ /* [in] */ DWORD grfMode,
+ /* [in] */ DWORD reserved2,
+ /* [out] */ IStream __RPC_FAR *__RPC_FAR *ppstm);
+
+/* [local] */ HRESULT __stdcall IStorage_EnumElements_Proxy(
+ IStorage __RPC_FAR * This,
+ /* [in] */ DWORD reserved1,
+ /* [size_is][unique][in] */ void __RPC_FAR *reserved2,
+ /* [in] */ DWORD reserved3,
+ /* [out] */ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum);
+
+
+/* [call_as] */ HRESULT __stdcall IStorage_EnumElements_Stub(
+ IStorage __RPC_FAR * This,
+ /* [in] */ DWORD reserved1,
+ /* [in] */ unsigned long cbReserved2,
+ /* [size_is][unique][in] */ byte __RPC_FAR *reserved2,
+ /* [in] */ DWORD reserved3,
+ /* [out] */ IEnumSTATSTG __RPC_FAR *__RPC_FAR *ppenum);
+
+/* [local] */ HRESULT __stdcall ILockBytes_ReadAt_Proxy(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER ulOffset,
+ /* [in] */ void __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbRead);
+
+
+/* [call_as] */ HRESULT __stdcall ILockBytes_ReadAt_Stub(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER ulOffset,
+ /* [length_is][size_is][out] */ byte __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbRead);
+
+/* [local] */ HRESULT __stdcall ILockBytes_WriteAt_Proxy(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER ulOffset,
+ /* [in] */ const void __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbWritten);
+
+
+/* [call_as] */ HRESULT __stdcall ILockBytes_WriteAt_Stub(
+ ILockBytes __RPC_FAR * This,
+ /* [in] */ ULARGE_INTEGER ulOffset,
+ /* [size_is][in] */ const byte __RPC_FAR *pv,
+ /* [in] */ ULONG cb,
+ /* [out] */ ULONG __RPC_FAR *pcbWritten);
+
+/* [local] */ HRESULT __stdcall IEnumFORMATETC_Next_Proxy(
+ IEnumFORMATETC __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [out] */ FORMATETC __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+
+/* [call_as] */ HRESULT __stdcall IEnumFORMATETC_Next_Stub(
+ IEnumFORMATETC __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ FORMATETC __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+/* [local] */ HRESULT __stdcall IEnumSTATDATA_Next_Proxy(
+ IEnumSTATDATA __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ STATDATA __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+
+/* [call_as] */ HRESULT __stdcall IEnumSTATDATA_Next_Stub(
+ IEnumSTATDATA __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ STATDATA __RPC_FAR *rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+/* [local] */ void __stdcall IAdviseSink_OnDataChange_Proxy(
+ IAdviseSink __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pFormatetc,
+ /* [unique][in] */ STGMEDIUM __RPC_FAR *pStgmed);
+
+
+/* [async][call_as] */ void __stdcall IAdviseSink_OnDataChange_Stub(
+ IAdviseSink __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pFormatetc,
+ /* [unique][in] */ RemSTGMEDIUM __RPC_FAR *pStgmed);
+
+/* [local] */ void __stdcall IAdviseSink_OnViewChange_Proxy(
+ IAdviseSink __RPC_FAR * This,
+ /* [in] */ DWORD dwAspect,
+ /* [in] */ LONG lindex);
+
+
+/* [async][call_as] */ void __stdcall IAdviseSink_OnViewChange_Stub(
+ IAdviseSink __RPC_FAR * This,
+ /* [in] */ DWORD dwAspect,
+ /* [in] */ LONG lindex);
+
+/* [local] */ void __stdcall IAdviseSink_OnRename_Proxy(
+ IAdviseSink __RPC_FAR * This,
+ /* [in] */ IMoniker __RPC_FAR *pmk);
+
+
+/* [async][call_as] */ void __stdcall IAdviseSink_OnRename_Stub(
+ IAdviseSink __RPC_FAR * This,
+ /* [in] */ IMoniker __RPC_FAR *pmk);
+
+/* [local] */ void __stdcall IAdviseSink_OnSave_Proxy(
+ IAdviseSink __RPC_FAR * This);
+
+
+/* [async][call_as] */ void __stdcall IAdviseSink_OnSave_Stub(
+ IAdviseSink __RPC_FAR * This);
+
+/* [local] */ void __stdcall IAdviseSink_OnClose_Proxy(
+ IAdviseSink __RPC_FAR * This);
+
+
+/* [call_as] */ HRESULT __stdcall IAdviseSink_OnClose_Stub(
+ IAdviseSink __RPC_FAR * This);
+
+/* [local] */ void __stdcall IAdviseSink2_OnLinkSrcChange_Proxy(
+ IAdviseSink2 __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmk);
+
+
+/* [async][call_as] */ void __stdcall IAdviseSink2_OnLinkSrcChange_Stub(
+ IAdviseSink2 __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmk);
+
+/* [local] */ HRESULT __stdcall IDataObject_GetData_Proxy(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetcIn,
+ /* [out] */ STGMEDIUM __RPC_FAR *pmedium);
+
+
+/* [call_as] */ HRESULT __stdcall IDataObject_GetData_Stub(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetcIn,
+ /* [out] */ RemSTGMEDIUM __RPC_FAR *__RPC_FAR *ppRemoteMedium);
+
+/* [local] */ HRESULT __stdcall IDataObject_GetDataHere_Proxy(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [out][in] */ STGMEDIUM __RPC_FAR *pmedium);
+
+
+/* [call_as] */ HRESULT __stdcall IDataObject_GetDataHere_Stub(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [out][in] */ RemSTGMEDIUM __RPC_FAR *__RPC_FAR *ppRemoteMedium);
+
+/* [local] */ HRESULT __stdcall IDataObject_SetData_Proxy(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [unique][in] */ STGMEDIUM __RPC_FAR *pmedium,
+ /* [in] */ BOOL fRelease);
+
+
+/* [call_as] */ HRESULT __stdcall IDataObject_SetData_Stub(
+ IDataObject __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [unique][in] */ RemSTGMEDIUM __RPC_FAR *pmedium,
+ /* [in] */ BOOL fRelease);
+
+
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/ole32/stg/props/iprop/objidl.idl b/private/ole32/stg/props/iprop/objidl.idl
new file mode 100644
index 000000000..00fa4f34f
--- /dev/null
+++ b/private/ole32/stg/props/iprop/objidl.idl
@@ -0,0 +1,1745 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: objidl.idl
+//
+//--------------------------------------------------------------------------
+
+#ifndef DO_NO_IMPORTS
+import "unknwn.idl";
+#endif
+
+interface IStream;
+interface IMoniker;
+interface IEnumMoniker;
+interface IEnumString;
+interface IRunningObjectTable;
+interface IStorage;
+interface IEnumSTATSTG;
+interface IAdviseSink;
+interface IBindCtx;
+interface IEnumMoniker;
+
+/****************************************************************************
+ * Component Object Interfaces
+ ****************************************************************************/
+
+[
+ local,
+ object,
+ uuid(00000003-0000-0000-C000-000000000046)
+]
+
+interface IMarshal : IUnknown
+{
+
+cpp_quote("//+-------------------------------------------------------------------------")
+cpp_quote("//")
+cpp_quote("// Microsoft Windows")
+cpp_quote("// Copyright (C) Microsoft Corporation, 1992 - 1995.")
+cpp_quote("//")
+cpp_quote("//--------------------------------------------------------------------------")
+
+ typedef [unique] IMarshal *LPMARSHAL;
+
+ HRESULT GetUnmarshalClass
+ (
+ [in] REFIID riid,
+ [in, unique] void *pv,
+ [in] DWORD dwDestContext,
+ [in, unique] void *pvDestContext,
+ [in] DWORD mshlflags,
+ [out] CLSID *pCid
+ );
+
+ HRESULT GetMarshalSizeMax
+ (
+ [in] REFIID riid,
+ [in, unique] void *pv,
+ [in] DWORD dwDestContext,
+ [in, unique] void *pvDestContext,
+ [in] DWORD mshlflags,
+ [out] DWORD *pSize
+ );
+
+ HRESULT MarshalInterface
+ (
+ [in, unique] IStream *pStm,
+ [in] REFIID riid,
+ [in, unique] void *pv,
+ [in] DWORD dwDestContext,
+ [in, unique] void *pvDestContext,
+ [in] DWORD mshlflags
+ );
+
+ HRESULT UnmarshalInterface
+ (
+ [in, unique] IStream *pStm,
+ [in] REFIID riid,
+ [out] void **ppv
+ );
+
+ HRESULT ReleaseMarshalData
+ (
+ [in, unique] IStream *pStm
+ );
+
+ HRESULT DisconnectObject
+ (
+ [in] DWORD dwReserved
+ );
+}
+
+[
+ local,
+ object,
+ uuid(00000002-0000-0000-C000-000000000046)
+]
+
+interface IMalloc : IUnknown
+{
+
+ typedef [unique] IMalloc *LPMALLOC;
+
+ void *Alloc([in] ULONG cb);
+
+ void *Realloc ([in] void *pv,
+ [in] ULONG cb);
+
+ void Free([in] void *pv);
+
+ ULONG GetSize([in] void *pv);
+
+ int DidAlloc(void *pv);
+
+ void HeapMinimize(void);
+}
+
+[
+ local,
+ object,
+ uuid(0000001d-0000-0000-C000-000000000046)
+]
+
+interface IMallocSpy : IUnknown
+{
+
+ typedef [unique] IMallocSpy *LPMALLOCSPY;
+
+ ULONG PreAlloc
+ (
+ [in] ULONG cbRequest
+ );
+
+ void *PostAlloc
+ (
+ [in] void *pActual
+ );
+
+ void *PreFree
+ (
+ [in] void *pRequest,
+ [in] BOOL fSpyed
+ );
+
+ void PostFree
+ (
+ [in] BOOL fSpyed
+ );
+
+ ULONG PreRealloc
+ (
+ [in] void *pRequest,
+ [in] ULONG cbRequest,
+ [out] void **ppNewRequest,
+ [in] BOOL fSpyed
+ );
+
+ void *PostRealloc
+ (
+ [in] void *pActual,
+ [in] BOOL fSpyed
+ );
+
+ void *PreGetSize
+ (
+ [in] void *pRequest,
+ [in] BOOL fSpyed
+ );
+
+ ULONG PostGetSize
+ (
+ [in] ULONG cbActual,
+ [in] BOOL fSpyed
+ );
+
+ void *PreDidAlloc
+ (
+ [in] void *pRequest,
+ [in] BOOL fSpyed
+ );
+
+ int PostDidAlloc
+ (
+ [in] void *pRequest,
+ [in] BOOL fSpyed,
+ [in] int fActual
+ );
+
+ void PreHeapMinimize(void);
+
+ void PostHeapMinimize(void);
+}
+
+[
+ local,
+ object,
+ uuid(00000018-0000-0000-C000-000000000046)
+]
+
+interface IStdMarshalInfo : IUnknown
+{
+
+ typedef [unique] IStdMarshalInfo * LPSTDMARSHALINFO;
+
+ HRESULT GetClassForHandler
+ (
+ [in] DWORD dwDestContext,
+ [in, unique] void *pvDestContext,
+ [out] CLSID *pClsid
+ );
+}
+
+[
+ object,
+ local,
+ uuid(00000019-0000-0000-C000-000000000046)
+]
+
+interface IExternalConnection : IUnknown
+{
+
+ typedef [unique] IExternalConnection* LPEXTERNALCONNECTION;
+
+
+ // bit flags for IExternalConnection
+ typedef enum tagEXTCONN
+ {
+ EXTCONN_STRONG = 0x0001, // strong connection
+ EXTCONN_WEAK = 0x0002, // weak connection (table, container)
+ EXTCONN_CALLABLE = 0x0004, // table .vs. callable
+ } EXTCONN;
+
+ // *** IExternalConnection methods ***
+ DWORD AddConnection
+ (
+ [in] DWORD extconn,
+ [in] DWORD reserved
+ );
+
+ DWORD ReleaseConnection
+ (
+ [in] DWORD extconn,
+ [in] DWORD reserved,
+ [in] BOOL fLastReleaseCloses
+ );
+}
+
+
+[
+ object,
+ uuid(00000100-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IEnumUnknown : IUnknown
+{
+
+ typedef [unique] IEnumUnknown *LPENUMUNKNOWN;
+
+ [local]
+ HRESULT __stdcall Next(
+ [in] ULONG celt,
+ [out] IUnknown **rgelt,
+ [out] ULONG *pceltFetched);
+
+ [call_as(Next)]
+ HRESULT __stdcall RemoteNext(
+ [in] ULONG celt,
+ [out, size_is(celt), length_is(*pceltFetched)]
+ IUnknown **rgelt,
+ [out] ULONG *pceltFetched);
+
+ HRESULT Skip(
+ [in] ULONG celt);
+
+ HRESULT Reset();
+
+ HRESULT Clone(
+ [out] IEnumUnknown **ppenum);
+}
+
+
+/****************************************************************************
+ * Binding Interfaces
+ ****************************************************************************/
+
+[
+ object,
+ uuid(0000000e-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IBindCtx : IUnknown
+{
+
+ typedef [unique] IBindCtx *LPBC;
+
+ typedef [unique] IBindCtx *LPBINDCTX;
+
+ typedef struct tagBIND_OPTS {
+ DWORD cbStruct; // sizeof(BIND_OPTS)
+ DWORD grfFlags;
+ DWORD grfMode;
+ DWORD dwTickCountDeadline;
+ } BIND_OPTS, * LPBIND_OPTS;
+
+
+ typedef enum tagBIND_FLAGS
+ {
+ BIND_MAYBOTHERUSER = 1,
+ BIND_JUSTTESTEXISTENCE = 2
+ } BIND_FLAGS;
+
+ HRESULT RegisterObjectBound
+ (
+ [in, unique] IUnknown *punk
+ );
+
+ HRESULT RevokeObjectBound
+ (
+ [in, unique] IUnknown *punk
+ );
+
+ HRESULT ReleaseBoundObjects
+ (
+ void
+ );
+
+ HRESULT SetBindOptions
+ (
+ [in] BIND_OPTS *pbindopts
+ );
+
+ HRESULT GetBindOptions
+ (
+ [in,out] BIND_OPTS *pbindopts
+ );
+
+ HRESULT GetRunningObjectTable
+ (
+ [out] IRunningObjectTable **pprot
+ );
+
+ HRESULT RegisterObjectParam(
+ [in] LPOLESTR pszKey,
+ [in, unique] IUnknown *punk
+ );
+
+ HRESULT GetObjectParam(
+ [in] LPOLESTR pszKey,
+ [out] IUnknown **ppunk
+ );
+
+ HRESULT EnumObjectParam
+ (
+ [out] IEnumString **ppenum
+ );
+
+ HRESULT RevokeObjectParam
+ (
+ [in] LPOLESTR pszKey
+ );
+}
+
+[
+ object,
+ uuid(00000102-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IEnumMoniker : IUnknown
+{
+
+ typedef [unique] IEnumMoniker *LPENUMMONIKER;
+
+ [local]
+ HRESULT __stdcall Next(
+ [in] ULONG celt,
+ [out] IMoniker **rgelt,
+ [out] ULONG *pceltFetched);
+
+ [call_as(Next)]
+ HRESULT __stdcall RemoteNext(
+ [in] ULONG celt,
+ [out, size_is(celt), length_is(*pceltFetched)]
+ IMoniker **rgelt,
+ [out] ULONG *pceltFetched);
+
+
+ HRESULT Skip(
+ [in] ULONG celt);
+
+ HRESULT Reset();
+
+ HRESULT Clone(
+ [out] IEnumMoniker **ppenum);
+}
+
+[
+ local,
+ object,
+ uuid(00000126-0000-0000-C000-000000000046)
+]
+interface IRunnableObject : IUnknown
+{
+
+ typedef [unique] IRunnableObject *LPRUNNABLEOBJECT;
+
+ HRESULT GetRunningClass(
+ [out] LPCLSID lpClsid);
+
+ HRESULT Run(
+ [in] LPBINDCTX pbc);
+
+ BOOL IsRunning();
+
+ HRESULT LockRunning(
+ [in] BOOL fLock,
+ [in] BOOL fLastUnlockCloses);
+
+ HRESULT SetContainedObject(
+ [in] BOOL fContained);
+}
+
+[
+ object,
+ uuid(00000010-0000-0000-C000-000000000046)
+]
+
+interface IRunningObjectTable : IUnknown
+{
+
+ typedef [unique] IRunningObjectTable *LPRUNNINGOBJECTTABLE;
+
+ HRESULT Register
+ (
+ [in] DWORD grfFlags,
+ [in, unique] IUnknown *punkObject,
+ [in, unique] IMoniker *pmkObjectName,
+ [out] DWORD *pdwRegister
+ );
+
+ HRESULT Revoke
+ (
+ [in] DWORD dwRegister
+ );
+
+ HRESULT IsRunning
+ (
+ [in, unique] IMoniker *pmkObjectName
+ );
+
+ HRESULT GetObject
+ (
+ [in, unique] IMoniker *pmkObjectName,
+ [out] IUnknown **ppunkObject
+ );
+
+ HRESULT NoteChangeTime
+ (
+ [in] DWORD dwRegister,
+ [in] FILETIME *pfiletime
+ );
+
+ HRESULT GetTimeOfLastChange
+ (
+ [in, unique] IMoniker *pmkObjectName,
+ [out] FILETIME *pfiletime
+ );
+
+ HRESULT EnumRunning
+ (
+ [out] IEnumMoniker **ppenumMoniker
+ );
+
+}
+
+[
+ object,
+ uuid(0000010c-0000-0000-C000-000000000046)
+]
+
+interface IPersist : IUnknown
+{
+
+ typedef [unique] IPersist *LPPERSIST;
+
+ HRESULT GetClassID
+ (
+ [out] CLSID *pClassID
+ );
+}
+
+[
+ object,
+ uuid(00000109-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IPersistStream : IPersist
+{
+
+ typedef [unique] IPersistStream *LPPERSISTSTREAM;
+
+ HRESULT IsDirty
+ (
+ void
+ );
+
+ HRESULT Load
+ (
+ [in, unique] IStream *pStm
+ );
+
+ HRESULT Save
+ (
+ [in, unique] IStream *pStm,
+ [in] BOOL fClearDirty
+ );
+
+ HRESULT GetSizeMax
+ (
+ [out] ULARGE_INTEGER *pcbSize
+ );
+
+}
+
+[
+ object,
+ uuid(0000000f-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IMoniker : IPersistStream
+{
+
+ typedef [unique] IMoniker *LPMONIKER;
+
+ // system moniker types; returned from IsSystemMoniker.
+ typedef enum tagMKSYS
+ {
+ MKSYS_NONE = 0,
+ MKSYS_GENERICCOMPOSITE = 1,
+ MKSYS_FILEMONIKER = 2,
+ MKSYS_ANTIMONIKER = 3,
+ MKSYS_ITEMMONIKER = 4,
+ MKSYS_POINTERMONIKER = 5
+ }MKSYS;
+
+
+ typedef [v1_enum] enum tagMKREDUCE
+ {
+ MKRREDUCE_ONE = 3<<16,
+
+ MKRREDUCE_TOUSER = 2<<16,
+ MKRREDUCE_THROUGHUSER = 1<<16,
+ MKRREDUCE_ALL = 0
+ } MKRREDUCE;
+
+
+ [local]
+ HRESULT __stdcall BindToObject(
+ [in, unique] IBindCtx *pbc,
+ [in, unique] IMoniker *pmkToLeft,
+ [in] REFIID riidResult,
+ [out] void **ppvResult);
+
+ [call_as(BindToObject)]
+ HRESULT __stdcall RemoteBindToObject(
+ [in, unique] IBindCtx *pbc,
+ [in, unique] IMoniker *pmkToLeft,
+ [in] REFIID riidResult,
+ [out, iid_is(riidResult)] IUnknown **ppvResult);
+
+ [local]
+ HRESULT __stdcall BindToStorage(
+ [in, unique] IBindCtx *pbc,
+ [in, unique] IMoniker *pmkToLeft,
+ [in] REFIID riid,
+ [out] void **ppvObj);
+
+ [call_as(BindToStorage)]
+ HRESULT __stdcall RemoteBindToStorage(
+ [in, unique] IBindCtx *pbc,
+ [in, unique] IMoniker *pmkToLeft,
+ [in] REFIID riid,
+ [out, iid_is(riid)] IUnknown **ppvObj);
+
+ HRESULT Reduce(
+ [in, unique] IBindCtx *pbc,
+ [in] DWORD dwReduceHowFar,
+ [in, out, unique] IMoniker **ppmkToLeft,
+ [out] IMoniker **ppmkReduced);
+
+ HRESULT ComposeWith(
+ [in, unique] IMoniker *pmkRight,
+ [in] BOOL fOnlyIfNotGeneric,
+ [out] IMoniker **ppmkComposite);
+
+ HRESULT Enum(
+ [in] BOOL fForward,
+ [out] IEnumMoniker **ppenumMoniker);
+
+ HRESULT IsEqual(
+ [in, unique] IMoniker *pmkOtherMoniker);
+
+ HRESULT Hash(
+ [out] DWORD *pdwHash);
+
+ HRESULT IsRunning(
+ [in, unique] IBindCtx *pbc,
+ [in, unique] IMoniker *pmkToLeft,
+ [in, unique] IMoniker *pmkNewlyRunning);
+
+ HRESULT GetTimeOfLastChange(
+ [in, unique] IBindCtx *pbc,
+ [in, unique] IMoniker *pmkToLeft,
+ [out] FILETIME *pFileTime);
+
+ HRESULT Inverse(
+ [out] IMoniker **ppmk);
+
+ HRESULT CommonPrefixWith(
+ [in, unique] IMoniker *pmkOther,
+ [out] IMoniker **ppmkPrefix);
+
+ HRESULT RelativePathTo(
+ [in, unique] IMoniker *pmkOther,
+ [out] IMoniker **ppmkRelPath);
+
+ HRESULT GetDisplayName(
+ [in, unique] IBindCtx *pbc,
+ [in, unique] IMoniker *pmkToLeft,
+ [out] LPOLESTR *ppszDisplayName);
+
+ HRESULT ParseDisplayName(
+ [in, unique] IBindCtx *pbc,
+ [in, unique] IMoniker *pmkToLeft,
+ [in] LPOLESTR pszDisplayName,
+ [out] ULONG *pchEaten,
+ [out] IMoniker **ppmkOut);
+
+ HRESULT IsSystemMoniker(
+ [out] DWORD *pdwMksys);
+
+}
+
+[
+ object,
+ uuid(f29f6bc0-5021-11ce-aa15-00006901293f),
+ pointer_default(unique)
+]
+
+interface IROTData : IUnknown
+{
+ HRESULT GetComparisonData(
+ [out, size_is(cbMax)] byte *pbData,
+ [in] ULONG cbMax,
+ [out] ULONG *pcbData);
+}
+
+[
+ object,
+ uuid(00000101-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IEnumString : IUnknown
+{
+
+ typedef [unique] IEnumString *LPENUMSTRING;
+
+ [local]
+ HRESULT __stdcall Next(
+ [in] ULONG celt,
+ [out] LPOLESTR *rgelt,
+ [out] ULONG *pceltFetched);
+
+ [call_as(Next)]
+ HRESULT __stdcall RemoteNext(
+ [in] ULONG celt,
+ [out, size_is(celt), length_is(*pceltFetched)]
+ LPOLESTR *rgelt,
+ [out] ULONG *pceltFetched);
+
+
+ HRESULT Skip(
+ [in] ULONG celt);
+
+ HRESULT Reset();
+
+ HRESULT Clone(
+ [out] IEnumString **ppenum);
+}
+
+
+/****************************************************************************
+ * Structured Storage Interfaces
+ ****************************************************************************/
+
+[
+ object,
+ uuid(0000000c-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IStream : IUnknown
+{
+
+ typedef [unique] IStream *LPSTREAM;
+
+ /* Storage stat buffer */
+
+ typedef struct tagSTATSTG
+ {
+ LPOLESTR pwcsName;
+ DWORD type;
+ ULARGE_INTEGER cbSize;
+ FILETIME mtime;
+ FILETIME ctime;
+ FILETIME atime;
+ DWORD grfMode;
+ DWORD grfLocksSupported;
+ CLSID clsid;
+ DWORD grfStateBits;
+ DWORD reserved;
+ } STATSTG;
+
+
+ /* Storage element types */
+ typedef enum tagSTGTY
+ {
+ STGTY_STORAGE = 1,
+ STGTY_STREAM = 2,
+ STGTY_LOCKBYTES = 3,
+ STGTY_PROPERTY = 4
+ } STGTY;
+
+ typedef enum tagSTREAM_SEEK
+ {
+ STREAM_SEEK_SET = 0,
+ STREAM_SEEK_CUR = 1,
+ STREAM_SEEK_END = 2
+ } STREAM_SEEK;
+
+ typedef enum tagLOCKTYPE
+ {
+ LOCK_WRITE = 1,
+ LOCK_EXCLUSIVE = 2,
+ LOCK_ONLYONCE = 4
+ } LOCKTYPE;
+
+ [local]
+ HRESULT __stdcall Read(
+ [out] void *pv,
+ [in] ULONG cb,
+ [out] ULONG *pcbRead);
+
+ [call_as(Read)]
+ HRESULT __stdcall RemoteRead(
+ [out, size_is(cb), length_is(*pcbRead)]
+ byte *pv,
+ [in] ULONG cb,
+ [out] ULONG *pcbRead);
+
+ [local]
+ HRESULT __stdcall Write(
+ [in, size_is(cb)] void const *pv,
+ [in] ULONG cb,
+ [out] ULONG *pcbWritten);
+
+ [call_as(Write)]
+ HRESULT __stdcall RemoteWrite(
+ [in, size_is(cb)] byte const *pv,
+ [in] ULONG cb,
+ [out] ULONG *pcbWritten);
+
+ [local]
+ HRESULT __stdcall Seek(
+ [in] LARGE_INTEGER dlibMove,
+ [in] DWORD dwOrigin,
+ [out] ULARGE_INTEGER *plibNewPosition);
+
+ [call_as(Seek)]
+ HRESULT __stdcall RemoteSeek(
+ [in] LARGE_INTEGER dlibMove,
+ [in] DWORD dwOrigin,
+ [out] ULARGE_INTEGER *plibNewPosition);
+
+ HRESULT SetSize(
+ [in] ULARGE_INTEGER libNewSize);
+
+ [local]
+ HRESULT __stdcall CopyTo(
+ [in, unique] IStream *pstm,
+ [in] ULARGE_INTEGER cb,
+ [out] ULARGE_INTEGER *pcbRead,
+ [out] ULARGE_INTEGER *pcbWritten);
+
+ [call_as(CopyTo)]
+ HRESULT __stdcall RemoteCopyTo(
+ [in, unique] IStream *pstm,
+ [in] ULARGE_INTEGER cb,
+ [out] ULARGE_INTEGER *pcbRead,
+ [out] ULARGE_INTEGER *pcbWritten);
+
+ HRESULT Commit(
+ [in] DWORD grfCommitFlags);
+
+ HRESULT Revert();
+
+ HRESULT LockRegion(
+ [in] ULARGE_INTEGER libOffset,
+ [in] ULARGE_INTEGER cb,
+ [in] DWORD dwLockType);
+
+ HRESULT UnlockRegion(
+ [in] ULARGE_INTEGER libOffset,
+ [in] ULARGE_INTEGER cb,
+ [in] DWORD dwLockType);
+
+ HRESULT Stat(
+ [out] STATSTG *pstatstg,
+ [in] DWORD grfStatFlag);
+
+ HRESULT Clone(
+ [out] IStream **ppstm);
+
+}
+
+[
+ object,
+ uuid(0000000d-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IEnumSTATSTG : IUnknown
+{
+
+ typedef [unique] IEnumSTATSTG *LPENUMSTATSTG;
+
+ [local]
+ HRESULT __stdcall Next(
+ [in] ULONG celt,
+ [in] STATSTG *rgelt,
+ [out] ULONG *pceltFetched);
+
+ [call_as(Next)]
+ HRESULT __stdcall RemoteNext(
+ [in] ULONG celt,
+ [out, size_is(celt), length_is(*pceltFetched)]
+ STATSTG *rgelt,
+ [out] ULONG *pceltFetched);
+
+ HRESULT Skip(
+ [in] ULONG celt);
+
+ HRESULT Reset();
+
+ HRESULT Clone(
+ [out] IEnumSTATSTG **ppenum);
+}
+
+[
+ object,
+ uuid(0000000b-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IStorage : IUnknown
+{
+
+ typedef [unique] IStorage * LPSTORAGE;
+
+ typedef struct tagRemSNB
+ {
+ unsigned long ulCntStr;
+ unsigned long ulCntChar;
+ [size_is(ulCntChar)] OLECHAR rgString[];
+ } RemSNB;
+
+ typedef [transmit_as(RemSNB)] OLECHAR **SNB;
+
+ HRESULT CreateStream(
+ [in, string] const OLECHAR *pwcsName,
+ [in] DWORD grfMode,
+ [in] DWORD reserved1,
+ [in] DWORD reserved2,
+ [out] IStream **ppstm);
+
+ [local]
+ HRESULT __stdcall OpenStream(
+ [in, string] const OLECHAR *pwcsName,
+ [in, unique] void *reserved1,
+ [in] DWORD grfMode,
+ [in] DWORD reserved2,
+ [out] IStream **ppstm);
+
+ [call_as(OpenStream)]
+ HRESULT __stdcall RemoteOpenStream(
+ [in, string] const OLECHAR *pwcsName,
+ [in] unsigned long cbReserved1,
+ [in, unique, size_is(cbReserved1)] byte *reserved1,
+ [in] DWORD grfMode,
+ [in] DWORD reserved2,
+ [out] IStream **ppstm);
+
+ HRESULT CreateStorage(
+ [in, string] const OLECHAR *pwcsName,
+ [in] DWORD grfMode,
+ [in] DWORD dwStgFmt,
+ [in] DWORD reserved2,
+ [out] IStorage **ppstg);
+
+ HRESULT OpenStorage(
+ [in, unique, string] const OLECHAR *pwcsName,
+ [in, unique] IStorage *pstgPriority,
+ [in] DWORD grfMode,
+ [in, unique] SNB snbExclude,
+ [in] DWORD reserved,
+ [out] IStorage **ppstg);
+
+ HRESULT CopyTo(
+ [in] DWORD ciidExclude,
+ [in, unique, size_is(ciidExclude)] IID const *rgiidExclude,
+ [in, unique] SNB snbExclude,
+ [in, unique] IStorage *pstgDest);
+
+ HRESULT MoveElementTo(
+ [in, string] const OLECHAR * pwcsName,
+ [in, unique] IStorage *pstgDest,
+ [in, string] const OLECHAR *pwcsNewName,
+ [in] DWORD grfFlags);
+
+ HRESULT Commit(
+ [in] DWORD grfCommitFlags);
+
+ HRESULT Revert();
+
+ [local]
+ HRESULT __stdcall EnumElements(
+ [in] DWORD reserved1,
+ [in, unique, size_is(1)] void *reserved2,
+ [in] DWORD reserved3,
+ [out] IEnumSTATSTG **ppenum);
+
+
+ [call_as(EnumElements)]
+ HRESULT __stdcall RemoteEnumElements(
+ [in] DWORD reserved1,
+ [in] unsigned long cbReserved2,
+ [in, unique, size_is(cbReserved2)] byte *reserved2,
+ [in] DWORD reserved3,
+ [out] IEnumSTATSTG **ppenum);
+
+ HRESULT DestroyElement(
+ [in, string] const OLECHAR *pwcsName);
+
+ HRESULT RenameElement(
+ [in, string] const OLECHAR *pwcsOldName,
+ [in, string] const OLECHAR *pwcsNewName);
+
+ HRESULT SetElementTimes(
+ [in, string] const OLECHAR *pwcsName,
+ [in] FILETIME const *pctime,
+ [in] FILETIME const *patime,
+ [in] FILETIME const *pmtime);
+
+ HRESULT SetClass(
+ [in] REFCLSID clsid);
+
+ HRESULT SetStateBits(
+ [in] DWORD grfStateBits,
+ [in] DWORD grfMask);
+
+ HRESULT Stat(
+ [out] STATSTG *pstatstg,
+ [in] DWORD grfStatFlag);
+}
+
+[
+ object,
+ uuid(0000010b-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IPersistFile : IPersist
+{
+
+ typedef [unique] IPersistFile *LPPERSISTFILE;
+
+ HRESULT IsDirty
+ (
+ void
+ );
+
+ HRESULT Load
+ (
+ [in] LPCOLESTR pszFileName,
+ [in] DWORD dwMode
+ );
+
+ HRESULT Save
+ (
+ [in, unique] LPCOLESTR pszFileName,
+ [in] BOOL fRemember
+ );
+
+ HRESULT SaveCompleted
+ (
+ [in, unique] LPCOLESTR pszFileName
+ );
+
+ HRESULT GetCurFile
+ (
+ [out] LPOLESTR *ppszFileName
+ );
+}
+
+[
+ object,
+ uuid(0000010a-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IPersistStorage : IPersist
+{
+
+ typedef [unique] IPersistStorage *LPPERSISTSTORAGE;
+
+ HRESULT IsDirty
+ (
+ void
+ );
+
+ HRESULT InitNew
+ (
+ [in, unique] IStorage *pStg
+ );
+
+ HRESULT Load
+ (
+ [in, unique] IStorage *pStg
+ );
+
+ HRESULT Save
+ (
+ [in, unique] IStorage *pStgSave,
+ [in] BOOL fSameAsLoad
+ );
+
+ HRESULT SaveCompleted
+ (
+ [in, unique] IStorage *pStgNew
+ );
+
+ HRESULT HandsOffStorage
+ (
+ void
+ );
+}
+
+[
+ object,
+ uuid(0000000a-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface ILockBytes : IUnknown
+{
+
+ typedef [unique] ILockBytes *LPLOCKBYTES;
+
+ [local]
+ HRESULT __stdcall ReadAt(
+ [in] ULARGE_INTEGER ulOffset,
+ [in] void *pv,
+ [in] ULONG cb,
+ [out] ULONG *pcbRead);
+
+ [call_as(ReadAt)]
+ HRESULT _stdcall RemoteReadAt(
+ [in] ULARGE_INTEGER ulOffset,
+ [out, size_is(cb), length_is(*pcbRead)]
+ byte *pv,
+ [in] ULONG cb,
+ [out] ULONG *pcbRead);
+
+ [local]
+ HRESULT __stdcall WriteAt(
+ [in] ULARGE_INTEGER ulOffset,
+ [in] void const *pv,
+ [in] ULONG cb,
+ [out] ULONG *pcbWritten);
+
+ [call_as(WriteAt)]
+ HRESULT __stdcall RemoteWriteAt(
+ [in] ULARGE_INTEGER ulOffset,
+ [in, size_is(cb)] byte const *pv,
+ [in] ULONG cb,
+ [out] ULONG *pcbWritten);
+
+ HRESULT Flush();
+
+ HRESULT SetSize(
+ [in] ULARGE_INTEGER cb);
+
+ HRESULT LockRegion(
+ [in] ULARGE_INTEGER libOffset,
+ [in] ULARGE_INTEGER cb,
+ [in] DWORD dwLockType);
+
+ HRESULT UnlockRegion(
+ [in] ULARGE_INTEGER libOffset,
+ [in] ULARGE_INTEGER cb,
+ [in] DWORD dwLockType);
+
+ HRESULT Stat(
+ [out] STATSTG *pstatstg,
+ [in] DWORD grfStatFlag);
+}
+
+[
+ object,
+ uuid(00000103-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IEnumFORMATETC : IUnknown
+{
+
+ typedef [unique] IEnumFORMATETC *LPENUMFORMATETC;
+
+
+ typedef struct tagDVTARGETDEVICE {
+ DWORD tdSize;
+ WORD tdDriverNameOffset;
+ WORD tdDeviceNameOffset;
+ WORD tdPortNameOffset;
+ WORD tdExtDevmodeOffset;
+ [size_is(tdSize - sizeof(DWORD) - 4*sizeof(WORD))]
+ BYTE tdData[];
+ }DVTARGETDEVICE;
+
+
+ typedef WORD CLIPFORMAT;
+ typedef CLIPFORMAT *LPCLIPFORMAT;
+
+ typedef struct tagFORMATETC {
+ CLIPFORMAT cfFormat;
+ [unique] DVTARGETDEVICE * ptd;
+ DWORD dwAspect;
+ LONG lindex;
+ DWORD tymed;
+ }FORMATETC, *LPFORMATETC;
+
+ [local]
+ HRESULT __stdcall Next(
+ [in] ULONG celt,
+ [out] FORMATETC *rgelt,
+ [out] ULONG *pceltFetched);
+
+ [call_as(Next)]
+ HRESULT __stdcall RemoteNext(
+ [in] ULONG celt,
+ [out, size_is(celt), length_is(*pceltFetched )]
+ FORMATETC *rgelt,
+ [out] ULONG *pceltFetched);
+
+ HRESULT Skip(
+ [in] ULONG celt);
+
+ HRESULT Reset();
+
+ HRESULT Clone(
+ [out] IEnumFORMATETC **ppenum);
+}
+
+[
+ object,
+ uuid(00000105-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IEnumSTATDATA : IUnknown
+{
+
+ typedef [unique] IEnumSTATDATA *LPENUMSTATDATA;
+
+ //Advise Flags
+ typedef enum tagADVF
+ {
+ ADVF_NODATA = 1,
+ ADVF_PRIMEFIRST = 2,
+ ADVF_ONLYONCE = 4,
+ ADVF_DATAONSTOP = 64,
+ ADVFCACHE_NOHANDLER = 8,
+ ADVFCACHE_FORCEBUILTIN = 16,
+ ADVFCACHE_ONSAVE = 32
+ } ADVF;
+
+
+ // Stats for data; used by several enumerations and by at least one
+ // implementation of IDataAdviseHolder; if a field is not used, it
+ // will be NULL.
+
+ typedef struct tagSTATDATA
+ { // field used by:
+ FORMATETC formatetc; // EnumAdvise, EnumData (cache), EnumFormats
+ DWORD advf; // EnumAdvise, EnumData (cache)
+ [unique] IAdviseSink * pAdvSink; // EnumAdvise
+ DWORD dwConnection; // EnumAdvise
+ } STATDATA;
+ typedef STATDATA *LPSTATDATA;
+
+ [local]
+ HRESULT __stdcall Next(
+ [in] ULONG celt,
+ STATDATA *rgelt,
+ [out] ULONG *pceltFetched);
+
+ [call_as(Next)]
+ HRESULT __stdcall RemoteNext(
+ [in] ULONG celt,
+ [out, size_is(celt), length_is(*pceltFetched)]
+ STATDATA *rgelt,
+ [out] ULONG *pceltFetched);
+
+ HRESULT Skip(
+ [in] ULONG celt);
+
+ HRESULT Reset();
+
+ HRESULT Clone(
+ [out] IEnumSTATDATA **ppenum);
+}
+
+[
+ object,
+ uuid(00000012-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IRootStorage : IUnknown
+{
+
+ typedef [unique] IRootStorage *LPROOTSTORAGE;
+
+ HRESULT SwitchToFile
+ (
+ [in, string] LPOLESTR pszFile
+ );
+}
+
+
+/****************************************************************************
+ * Notification Interfaces
+ ****************************************************************************/
+
+[
+ object,
+ uuid(0000010f-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IAdviseSink : IUnknown
+{
+
+ typedef IAdviseSink *LPADVISESINK;
+
+ typedef [v1_enum] enum tagTYMED {
+ TYMED_HGLOBAL = 1,
+ TYMED_FILE = 2,
+ TYMED_ISTREAM = 4,
+ TYMED_ISTORAGE = 8,
+ TYMED_GDI = 16,
+ TYMED_MFPICT = 32,
+ TYMED_ENHMF = 64,
+ TYMED_NULL = 0
+ } TYMED;
+
+ cpp_quote("#ifndef RC_INVOKED")
+ cpp_quote("#pragma warning(disable:4200)")
+ cpp_quote("#endif")
+
+ typedef struct tagRemSTGMEDIUM {
+ DWORD tymed;
+ DWORD dwHandleType;
+ unsigned long pData;
+ unsigned long pUnkForRelease;
+ unsigned long cbData;
+ [size_is(cbData)] byte data[];
+ } RemSTGMEDIUM;
+ cpp_quote("#ifndef RC_INVOKED")
+ cpp_quote("#pragma warning(default:4200)")
+ cpp_quote("#endif")
+
+
+cpp_quote("#ifdef NONAMELESSUNION")
+cpp_quote("typedef struct tagSTGMEDIUM {")
+cpp_quote(" DWORD tymed;")
+cpp_quote(" union {")
+cpp_quote(" HBITMAP hBitmap;")
+cpp_quote(" HMETAFILEPICT hMetaFilePict;")
+cpp_quote(" HENHMETAFILE hEnhMetaFile;")
+cpp_quote(" HGLOBAL hGlobal;")
+cpp_quote(" LPOLESTR lpszFileName;")
+cpp_quote(" IStream *pstm;")
+cpp_quote(" IStorage *pstg;")
+cpp_quote(" } u;")
+cpp_quote(" IUnknown *pUnkForRelease;")
+cpp_quote("}STGMEDIUM;")
+cpp_quote("#else")
+
+ typedef struct tagSTGMEDIUM {
+ DWORD tymed;
+ [switch_type(DWORD), switch_is((DWORD) tymed)]
+ union
+ {
+ [case(TYMED_GDI)]
+ HBITMAP hBitmap;
+ [case(TYMED_MFPICT)]
+ HMETAFILEPICT hMetaFilePict;
+ [case(TYMED_ENHMF)]
+ HENHMETAFILE hEnhMetaFile;
+ [case(TYMED_HGLOBAL)]
+ HGLOBAL hGlobal;
+ [case(TYMED_FILE)]
+ LPOLESTR lpszFileName;
+ [case(TYMED_ISTREAM)]
+ IStream *pstm;
+ [case(TYMED_ISTORAGE)]
+ IStorage *pstg;
+ [default]
+ ;
+ };
+ [unique] IUnknown *pUnkForRelease;
+ }STGMEDIUM;
+
+cpp_quote("#endif /* !NONAMELESSUNION */")
+
+ typedef STGMEDIUM *LPSTGMEDIUM;
+
+
+ [local]
+ void __stdcall OnDataChange(
+ [in, unique] FORMATETC *pFormatetc,
+ [in, unique] STGMEDIUM *pStgmed);
+
+ [call_as(OnDataChange), async]
+ void __stdcall RemoteOnDataChange(
+ [in, unique] FORMATETC *pFormatetc,
+ [in, unique] RemSTGMEDIUM *pStgmed);
+
+ [local]
+ void __stdcall OnViewChange(
+ [in] DWORD dwAspect,
+ [in] LONG lindex);
+
+ [call_as(OnViewChange), async]
+ void __stdcall RemoteOnViewChange(
+ [in] DWORD dwAspect,
+ [in] LONG lindex);
+
+ [local]
+ void __stdcall OnRename(
+ [in] IMoniker *pmk);
+
+ [call_as(OnRename), async]
+ void __stdcall RemoteOnRename(
+ [in] IMoniker *pmk);
+
+ [local]
+ void __stdcall OnSave();
+
+ [call_as(OnSave), async]
+ void __stdcall RemoteOnSave();
+
+ [local]
+ void __stdcall OnClose();
+
+ [call_as(OnClose)]
+ HRESULT __stdcall RemoteOnClose();
+}
+
+[
+ object,
+ uuid(00000125-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IAdviseSink2 : IAdviseSink
+{
+
+ typedef [unique] IAdviseSink2 *LPADVISESINK2;
+
+ [local]
+ void __stdcall OnLinkSrcChange(
+ [in, unique] IMoniker *pmk);
+
+ [call_as(OnLinkSrcChange), async]
+ void __stdcall RemoteOnLinkSrcChange(
+ [in, unique] IMoniker *pmk);
+}
+
+[
+ object,
+ uuid(0000010e-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IDataObject : IUnknown
+{
+
+ typedef [unique] IDataObject *LPDATAOBJECT;
+
+ //DATA format DIRection
+ typedef enum tagDATADIR
+ {
+ DATADIR_GET = 1,
+ DATADIR_SET = 2
+ } DATADIR;
+
+ [local]
+ HRESULT __stdcall GetData(
+ [in, unique] FORMATETC *pformatetcIn,
+ [out] STGMEDIUM *pmedium);
+
+ [call_as(GetData)]
+ HRESULT __stdcall RemoteGetData(
+ [in, unique] FORMATETC *pformatetcIn,
+ [out] RemSTGMEDIUM **ppRemoteMedium);
+
+ [local]
+ HRESULT __stdcall GetDataHere(
+ [in, unique] FORMATETC *pformatetc,
+ [in, out] STGMEDIUM *pmedium);
+
+ [call_as(GetDataHere)]
+ HRESULT __stdcall RemoteGetDataHere(
+ [in, unique] FORMATETC *pformatetc,
+ [in, out] RemSTGMEDIUM **ppRemoteMedium);
+
+ HRESULT QueryGetData(
+ [in, unique] FORMATETC *pformatetc);
+
+
+ HRESULT GetCanonicalFormatEtc(
+ [in, unique] FORMATETC *pformatectIn,
+ [out] FORMATETC *pformatetcOut);
+
+ [local]
+ HRESULT __stdcall SetData(
+ [in, unique] FORMATETC *pformatetc,
+ [in, unique] STGMEDIUM *pmedium,
+ [in] BOOL fRelease);
+
+ [call_as(SetData)]
+ HRESULT __stdcall RemoteSetData(
+ [in, unique] FORMATETC *pformatetc,
+ [in, unique] RemSTGMEDIUM *pmedium,
+ [in] BOOL fRelease);
+
+ HRESULT EnumFormatEtc(
+ [in] DWORD dwDirection,
+ [out] IEnumFORMATETC **ppenumFormatEtc);
+
+ HRESULT DAdvise(
+ [in] FORMATETC *pformatetc,
+ [in] DWORD advf,
+ [in, unique] IAdviseSink *pAdvSink,
+ [out] DWORD *pdwConnection);
+
+ HRESULT DUnadvise(
+ [in] DWORD dwConnection);
+
+ HRESULT EnumDAdvise(
+ [out] IEnumSTATDATA **ppenumAdvise);
+
+}
+
+[
+ local,
+ object,
+ uuid(00000110-0000-0000-C000-000000000046)
+]
+
+interface IDataAdviseHolder : IUnknown
+{
+
+ typedef [unique] IDataAdviseHolder *LPDATAADVISEHOLDER;
+
+ HRESULT Advise
+ (
+ [in, unique] IDataObject *pDataObject,
+ [in, unique] FORMATETC *pFetc,
+ [in] DWORD advf,
+ [in, unique] IAdviseSink *pAdvise,
+ [out] DWORD *pdwConnection
+ );
+
+ HRESULT Unadvise
+ (
+ [in] DWORD dwConnection
+ );
+
+ HRESULT EnumAdvise
+ (
+ [out] IEnumSTATDATA **ppenumAdvise
+ );
+
+ HRESULT SendOnDataChange
+ (
+ [in, unique] IDataObject *pDataObject,
+ [in] DWORD dwReserved,
+ [in] DWORD advf
+ );
+
+}
+
+[
+ local,
+ object,
+ uuid(00000016-0000-0000-C000-000000000046)
+]
+
+interface IMessageFilter : IUnknown
+{
+
+ typedef [unique] IMessageFilter *LPMESSAGEFILTER;
+
+// call type used by IMessageFilter::HandleIncomingMessage
+typedef enum tagCALLTYPE
+{
+ CALLTYPE_TOPLEVEL = 1, // toplevel call - no outgoing call
+ CALLTYPE_NESTED = 2, // callback on behalf of previous outgoing call - should always handle
+ CALLTYPE_ASYNC = 3, // aysnchronous call - can NOT be rejected
+ CALLTYPE_TOPLEVEL_CALLPENDING = 4, // new toplevel call with new LID
+ CALLTYPE_ASYNC_CALLPENDING = 5 // async call - can NOT be rejected
+} CALLTYPE;
+
+// status of server call - returned by IMessageFilter::HandleIncomingCall
+// and passed to IMessageFilter::RetryRejectedCall
+typedef enum tagSERVERCALL
+{
+ SERVERCALL_ISHANDLED = 0,
+ SERVERCALL_REJECTED = 1,
+ SERVERCALL_RETRYLATER = 2
+} SERVERCALL;
+
+// Pending type indicates the level of nesting
+typedef enum tagPENDINGTYPE
+{
+ PENDINGTYPE_TOPLEVEL = 1, // toplevel call
+ PENDINGTYPE_NESTED = 2 // nested call
+} PENDINGTYPE;
+
+// return values of MessagePending
+typedef enum tagPENDINGMSG
+{
+ PENDINGMSG_CANCELCALL = 0, // cancel the outgoing call
+ PENDINGMSG_WAITNOPROCESS = 1, // wait for the return and don't dispatch the message
+ PENDINGMSG_WAITDEFPROCESS = 2 // wait and dispatch the message
+
+} PENDINGMSG;
+
+// additional interface information about the incoming call
+typedef struct tagINTERFACEINFO
+{
+ IUnknown *pUnk; // the pointer to the object
+ IID iid; // interface id
+ WORD wMethod; // interface method
+} INTERFACEINFO, *LPINTERFACEINFO;
+
+ DWORD HandleInComingCall
+ (
+ [in] DWORD dwCallType,
+ [in] HTASK htaskCaller,
+ [in] DWORD dwTickCount,
+ [in] LPINTERFACEINFO lpInterfaceInfo
+ );
+
+ DWORD RetryRejectedCall
+ (
+ [in] HTASK htaskCallee,
+ [in] DWORD dwTickCount,
+ [in] DWORD dwRejectType
+ );
+
+ DWORD MessagePending
+ (
+ [in] HTASK htaskCallee,
+ [in] DWORD dwTickCount,
+ [in] DWORD dwPendingType
+ );
+}
+
+
+/****************************************************************************
+ * Object Remoting Interfaces
+ ****************************************************************************/
+
+[
+ local,
+ object,
+ uuid(D5F56B60-593B-101A-B569-08002B2DBF7A)
+]
+interface IRpcChannelBuffer : IUnknown
+{
+
+ typedef unsigned long RPCOLEDATAREP;
+
+ typedef struct tagRPCOLEMESSAGE
+ {
+ void *reserved1;
+ RPCOLEDATAREP dataRepresentation;
+ void *Buffer;
+ ULONG cbBuffer;
+ ULONG iMethod;
+ void *reserved2[5];
+ ULONG rpcFlags;
+ } RPCOLEMESSAGE;
+
+ typedef RPCOLEMESSAGE *PRPCOLEMESSAGE;
+
+ HRESULT GetBuffer
+ (
+ [in] RPCOLEMESSAGE *pMessage,
+ [in] REFIID riid
+ );
+
+ HRESULT SendReceive
+ (
+ [in,out] RPCOLEMESSAGE *pMessage,
+ [out] ULONG *pStatus
+ );
+
+ HRESULT FreeBuffer
+ (
+ [in] RPCOLEMESSAGE *pMessage
+ );
+
+ HRESULT GetDestCtx
+ (
+ [out] DWORD *pdwDestContext,
+ [out] void **ppvDestContext
+ );
+
+ HRESULT IsConnected
+ (
+ void
+ );
+
+}
+
+[
+ local,
+ object,
+ uuid(D5F56A34-593B-101A-B569-08002B2DBF7A)
+]
+interface IRpcProxyBuffer : IUnknown
+{
+
+ HRESULT Connect
+ (
+ [in, unique] IRpcChannelBuffer *pRpcChannelBuffer
+ );
+
+ void Disconnect
+ (
+ void
+ );
+
+}
+
+[
+ local,
+ object,
+ uuid(D5F56AFC-593B-101A-B569-08002B2DBF7A)
+]
+interface IRpcStubBuffer : IUnknown
+{
+
+ HRESULT Connect
+ (
+ [in] IUnknown *pUnkServer
+ );
+
+ void Disconnect();
+
+ HRESULT Invoke
+ (
+ [in] RPCOLEMESSAGE *_prpcmsg,
+ [in] IRpcChannelBuffer *_pRpcChannelBuffer
+ );
+
+ IRpcStubBuffer *IsIIDSupported
+ (
+ [in] REFIID riid
+ );
+
+ ULONG CountRefs
+ (
+ void
+ );
+
+ HRESULT DebugServerQueryInterface
+ (
+ void **ppv
+ );
+
+ void DebugServerRelease
+ (
+ void *pv
+ );
+
+}
+
+
+
+[
+ local,
+ object,
+ uuid(D5F569D0-593B-101A-B569-08002B2DBF7A)
+]
+interface IPSFactoryBuffer : IUnknown
+{
+
+ HRESULT CreateProxy
+ (
+ [in] IUnknown *pUnkOuter,
+ [in] REFIID riid,
+ [out] IRpcProxyBuffer **ppProxy,
+ [out] void **ppv
+ );
+
+ HRESULT CreateStub
+ (
+ [in] REFIID riid,
+ [in, unique] IUnknown *pUnkServer,
+ [out] IRpcStubBuffer **ppStub
+ );
+}
diff --git a/private/ole32/stg/props/iprop/oleauto.h b/private/ole32/stg/props/iprop/oleauto.h
new file mode 100644
index 000000000..4de86604a
--- /dev/null
+++ b/private/ole32/stg/props/iprop/oleauto.h
@@ -0,0 +1,683 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: oleauto.h
+//
+// Contents: Defines the Ole Automation interfaces and APIs.
+//
+// Interfaces:
+// IDispatch;
+// ITypeInfo;
+// ITypeLib;
+// ITypeComp;
+// ICreateTypeInfo;
+// ICreateTypeLib;
+// IErrorInfo;
+// ICreateErrorInfo;
+// ISupportErrorInfo;
+//
+// Functions: SysAllocString BSTR API
+// SysReAllocString
+// SysAllocStringLen
+// SysReAllocStringLen
+// SysFreeString
+// SysStringLen
+// DosDateTimeToVariantTime Time API
+// VariantTimeToDosDateTime
+// SafeArrayCreate Safe Array API
+// SafeArrayDestroy
+// SafeArrayGetDim
+// SafeArrayGetElemsize
+// SafeArrayGetUBound
+// SafeArrayGetLBound
+// SafeArrayLock
+// SafeArrayUnlock
+// SafeArrayAccessData
+// SafeArrayUnaccessData
+// SafeArrayGetElement
+// SafeArrayPutElement
+// SafeArrayCopy
+// VariantInit Variant API
+// VariantClear
+// VariantCopy
+// VariantCopyInd
+// VariantChangeType
+// LHashValOfName TypeInfo API
+// LoadTypeLib
+// LoadRegTypeLib
+// RegisterTypeLib
+// DeregisterTypeLib
+// CreateTypeLib
+// DispGetParam Dispatch API
+// DispGetIDsOfNames
+// DispInvoke
+// CreateDispTypeInfo
+// CreateStdDispatch
+// RegisterActiveObject Active Object Registration API
+// RevokeActiveObject
+// GetActiveObject
+// OaBuildVersion
+//
+//----------------------------------------------------------------------------
+
+#if !defined( _OLEAUTO_H_ )
+#define _OLEAUTO_H_
+
+// Set packing to 8 for ISV, and Win95 support
+#ifndef RC_INVOKED
+#include <pshpack8.h>
+#endif // RC_INVOKED
+
+// Definition of the OLE Automation APIs, and macros.
+
+#ifdef _OLEAUT32_
+#define WINOLEAUTAPI STDAPI
+#define WINOLEAUTAPI_(type) STDAPI_(type)
+#else
+#define WINOLEAUTAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE
+#define WINOLEAUTAPI_(type) EXTERN_C DECLSPEC_IMPORT type STDAPICALLTYPE
+#endif
+
+#define STDOLE_MAJORVERNUM 0x1
+#define STDOLE_MINORVERNUM 0x0
+#define STDOLE_LCID 0x0000
+
+/* if not already picked up from olenls.h */
+#ifndef _LCID_DEFINED
+typedef DWORD LCID;
+# define _LCID_DEFINED
+#endif
+
+/* pull in the MIDL generated header */
+#include <oaidl.h>
+
+
+/*---------------------------------------------------------------------*/
+/* BSTR API */
+/*---------------------------------------------------------------------*/
+
+WINOLEAUTAPI_(BSTR) SysAllocString(const OLECHAR FAR*);
+WINOLEAUTAPI_(int) SysReAllocString(BSTR FAR*, const OLECHAR FAR*);
+WINOLEAUTAPI_(BSTR) SysAllocStringLen(const OLECHAR FAR*, unsigned int);
+WINOLEAUTAPI_(int) SysReAllocStringLen(BSTR FAR*, const OLECHAR FAR*, unsigned int);
+WINOLEAUTAPI_(void) SysFreeString(BSTR);
+WINOLEAUTAPI_(unsigned int) SysStringLen(BSTR);
+
+#ifdef _WIN32
+WINOLEAUTAPI_(unsigned int) SysStringByteLen(BSTR bstr);
+WINOLEAUTAPI_(BSTR) SysAllocStringByteLen(const char FAR* psz, unsigned int len);
+#endif
+
+/*---------------------------------------------------------------------*/
+/* Time API */
+/*---------------------------------------------------------------------*/
+
+WINOLEAUTAPI_(int)
+DosDateTimeToVariantTime(
+ unsigned short wDosDate,
+ unsigned short wDosTime,
+ double FAR* pvtime);
+
+WINOLEAUTAPI_(int)
+VariantTimeToDosDateTime(
+ double vtime,
+ unsigned short FAR* pwDosDate,
+ unsigned short FAR* pwDosTime);
+
+/*---------------------------------------------------------------------*/
+/* SafeArray API */
+/*---------------------------------------------------------------------*/
+
+WINOLEAUTAPI
+SafeArrayAllocDescriptor(unsigned int cDims, SAFEARRAY FAR* FAR* ppsaOut);
+
+WINOLEAUTAPI SafeArrayAllocData(SAFEARRAY FAR* psa);
+
+WINOLEAUTAPI_(SAFEARRAY FAR*)
+SafeArrayCreate(
+ VARTYPE vt,
+ unsigned int cDims,
+ SAFEARRAYBOUND FAR* rgsabound);
+
+WINOLEAUTAPI SafeArrayDestroyDescriptor(SAFEARRAY FAR* psa);
+
+WINOLEAUTAPI SafeArrayDestroyData(SAFEARRAY FAR* psa);
+
+WINOLEAUTAPI SafeArrayDestroy(SAFEARRAY FAR* psa);
+
+WINOLEAUTAPI SafeArrayRedim(SAFEARRAY FAR* psa, SAFEARRAYBOUND FAR* psaboundNew);
+
+WINOLEAUTAPI_(unsigned int) SafeArrayGetDim(SAFEARRAY FAR* psa);
+
+WINOLEAUTAPI_(unsigned int) SafeArrayGetElemsize(SAFEARRAY FAR* psa);
+
+WINOLEAUTAPI
+SafeArrayGetUBound(SAFEARRAY FAR* psa, unsigned int nDim, long FAR* plUbound);
+
+WINOLEAUTAPI
+SafeArrayGetLBound(SAFEARRAY FAR* psa, unsigned int nDim, long FAR* plLbound);
+
+WINOLEAUTAPI SafeArrayLock(SAFEARRAY FAR* psa);
+
+WINOLEAUTAPI SafeArrayUnlock(SAFEARRAY FAR* psa);
+
+WINOLEAUTAPI SafeArrayAccessData(SAFEARRAY FAR* psa, void HUGEP* FAR* ppvData);
+
+WINOLEAUTAPI SafeArrayUnaccessData(SAFEARRAY FAR* psa);
+
+WINOLEAUTAPI
+SafeArrayGetElement(
+ SAFEARRAY FAR* psa,
+ long FAR* rgIndices,
+ void FAR* pv);
+
+WINOLEAUTAPI
+SafeArrayPutElement(
+ SAFEARRAY FAR* psa,
+ long FAR* rgIndices,
+ void FAR* pv);
+
+WINOLEAUTAPI
+SafeArrayCopy(
+ SAFEARRAY FAR* psa,
+ SAFEARRAY FAR* FAR* ppsaOut);
+
+WINOLEAUTAPI
+SafeArrayPtrOfIndex(
+ SAFEARRAY FAR* psa,
+ long FAR* rgIndices,
+ void HUGEP* FAR* ppvData);
+
+
+/*---------------------------------------------------------------------*/
+/* VARIANT API */
+/*---------------------------------------------------------------------*/
+
+WINOLEAUTAPI_(void)
+VariantInit(VARIANTARG FAR* pvarg);
+
+WINOLEAUTAPI
+VariantClear(VARIANTARG FAR* pvarg);
+
+WINOLEAUTAPI
+VariantCopy(
+ VARIANTARG FAR* pvargDest,
+ VARIANTARG FAR* pvargSrc);
+
+WINOLEAUTAPI
+VariantCopyInd(
+ VARIANT FAR* pvarDest,
+ VARIANTARG FAR* pvargSrc);
+
+WINOLEAUTAPI
+VariantChangeType(
+ VARIANTARG FAR* pvargDest,
+ VARIANTARG FAR* pvarSrc,
+ unsigned short wFlags,
+ VARTYPE vt);
+
+WINOLEAUTAPI
+VariantChangeTypeEx(
+ VARIANTARG FAR* pvargDest,
+ VARIANTARG FAR* pvarSrc,
+ LCID lcid,
+ unsigned short wFlags,
+ VARTYPE vt);
+
+#define VARIANT_NOVALUEPROP 1
+
+
+/*---------------------------------------------------------------------*/
+/* VARTYPE Coercion API */
+/*---------------------------------------------------------------------*/
+
+/* Note: The routines that convert *from* a string are defined
+ * to take a OLECHAR* rather than a BSTR because no allocation is
+ * required, and this makes the routines a bit more generic.
+ * They may of course still be passed a BSTR as the strIn param.
+ */
+
+
+/* Any of the coersion functions that converts either from or to a string
+ * takes an additional lcid and dwFlags arguments. The lcid argument allows
+ * locale specific parsing to occur. The dwFlags allow additional function
+ * specific condition to occur. All function that accept the dwFlags argument
+ * can include either 0 or LOCALE_NOUSEROVERRIDE flag. In addition, the
+ * VarDateFromStr functions also accepts the VAR_TIMEVALUEONLY and
+ * VAR_DATEVALUEONLY flags
+ */
+
+#define VAR_TIMEVALUEONLY 0x0001 /* return time value */
+#define VAR_DATEVALUEONLY 0x0002 /* return date value */
+
+
+WINOLEAUTAPI VarUI1FromI2(short sIn, unsigned char FAR* pbOut);
+WINOLEAUTAPI VarUI1FromI4(long lIn, unsigned char FAR* pbOut);
+WINOLEAUTAPI VarUI1FromR4(float fltIn, unsigned char FAR* pbOut);
+WINOLEAUTAPI VarUI1FromR8(double dblIn, unsigned char FAR* pbOut);
+WINOLEAUTAPI VarUI1FromCy(CY cyIn, unsigned char FAR* pbOut);
+WINOLEAUTAPI VarUI1FromDate(DATE dateIn, unsigned char FAR* pbOut);
+WINOLEAUTAPI VarUI1FromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, unsigned char FAR* pbOut);
+WINOLEAUTAPI VarUI1FromDisp(IDispatch FAR* pdispIn, LCID lcid, unsigned char FAR* pbOut);
+WINOLEAUTAPI VarUI1FromBool(VARIANT_BOOL boolIn, unsigned char FAR* pbOut);
+
+WINOLEAUTAPI VarI2FromUI1(unsigned char bIn, short FAR* psOut);
+WINOLEAUTAPI VarI2FromI4(long lIn, short FAR* psOut);
+WINOLEAUTAPI VarI2FromR4(float fltIn, short FAR* psOut);
+WINOLEAUTAPI VarI2FromR8(double dblIn, short FAR* psOut);
+WINOLEAUTAPI VarI2FromCy(CY cyIn, short FAR* psOut);
+WINOLEAUTAPI VarI2FromDate(DATE dateIn, short FAR* psOut);
+WINOLEAUTAPI VarI2FromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, short FAR* psOut);
+WINOLEAUTAPI VarI2FromDisp(IDispatch FAR* pdispIn, LCID lcid, short FAR* psOut);
+WINOLEAUTAPI VarI2FromBool(VARIANT_BOOL boolIn, short FAR* psOut);
+
+WINOLEAUTAPI VarI4FromUI1(unsigned char bIn, long FAR* plOut);
+WINOLEAUTAPI VarI4FromI2(short sIn, long FAR* plOut);
+WINOLEAUTAPI VarI4FromR4(float fltIn, long FAR* plOut);
+WINOLEAUTAPI VarI4FromR8(double dblIn, long FAR* plOut);
+WINOLEAUTAPI VarI4FromCy(CY cyIn, long FAR* plOut);
+WINOLEAUTAPI VarI4FromDate(DATE dateIn, long FAR* plOut);
+WINOLEAUTAPI VarI4FromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, long FAR* plOut);
+WINOLEAUTAPI VarI4FromDisp(IDispatch FAR* pdispIn, LCID lcid, long FAR* plOut);
+WINOLEAUTAPI VarI4FromBool(VARIANT_BOOL boolIn, long FAR* plOut);
+
+WINOLEAUTAPI VarR4FromUI1(unsigned char bIn, float FAR* pfltOut);
+WINOLEAUTAPI VarR4FromI2(short sIn, float FAR* pfltOut);
+WINOLEAUTAPI VarR4FromI4(long lIn, float FAR* pfltOut);
+WINOLEAUTAPI VarR4FromR8(double dblIn, float FAR* pfltOut);
+WINOLEAUTAPI VarR4FromCy(CY cyIn, float FAR* pfltOut);
+WINOLEAUTAPI VarR4FromDate(DATE dateIn, float FAR* pfltOut);
+WINOLEAUTAPI VarR4FromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, float FAR* pfltOut);
+WINOLEAUTAPI VarR4FromDisp(IDispatch FAR* pdispIn, LCID lcid, float FAR* pfltOut);
+WINOLEAUTAPI VarR4FromBool(VARIANT_BOOL boolIn, float FAR* pfltOut);
+
+WINOLEAUTAPI VarR8FromUI1(unsigned char bIn, double FAR* pdblOut);
+WINOLEAUTAPI VarR8FromI2(short sIn, double FAR* pdblOut);
+WINOLEAUTAPI VarR8FromI4(long lIn, double FAR* pdblOut);
+WINOLEAUTAPI VarR8FromR4(float fltIn, double FAR* pdblOut);
+WINOLEAUTAPI VarR8FromCy(CY cyIn, double FAR* pdblOut);
+WINOLEAUTAPI VarR8FromDate(DATE dateIn, double FAR* pdblOut);
+WINOLEAUTAPI VarR8FromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, double FAR* pdblOut);
+WINOLEAUTAPI VarR8FromDisp(IDispatch FAR* pdispIn, LCID lcid, double FAR* pdblOut);
+WINOLEAUTAPI VarR8FromBool(VARIANT_BOOL boolIn, double FAR* pdblOut);
+
+WINOLEAUTAPI VarDateFromUI1(unsigned char bIn, DATE FAR* pdateOut);
+WINOLEAUTAPI VarDateFromI2(short sIn, DATE FAR* pdateOut);
+WINOLEAUTAPI VarDateFromI4(long lIn, DATE FAR* pdateOut);
+WINOLEAUTAPI VarDateFromR4(float fltIn, DATE FAR* pdateOut);
+WINOLEAUTAPI VarDateFromR8(double dblIn, DATE FAR* pdateOut);
+WINOLEAUTAPI VarDateFromCy(CY cyIn, DATE FAR* pdateOut);
+WINOLEAUTAPI VarDateFromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, DATE FAR* pdateOut);
+WINOLEAUTAPI VarDateFromDisp(IDispatch FAR* pdispIn, LCID lcid, DATE FAR* pdateOut);
+WINOLEAUTAPI VarDateFromBool(VARIANT_BOOL boolIn, DATE FAR* pdateOut);
+
+WINOLEAUTAPI VarCyFromUI1(unsigned char bIn, CY FAR* pcyOut);
+WINOLEAUTAPI VarCyFromI2(short sIn, CY FAR* pcyOut);
+WINOLEAUTAPI VarCyFromI4(long lIn, CY FAR* pcyOut);
+WINOLEAUTAPI VarCyFromR4(float fltIn, CY FAR* pcyOut);
+WINOLEAUTAPI VarCyFromR8(double dblIn, CY FAR* pcyOut);
+WINOLEAUTAPI VarCyFromDate(DATE dateIn, CY FAR* pcyOut);
+WINOLEAUTAPI VarCyFromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, CY FAR* pcyOut);
+WINOLEAUTAPI VarCyFromDisp(IDispatch FAR* pdispIn, LCID lcid, CY FAR* pcyOut);
+WINOLEAUTAPI VarCyFromBool(VARIANT_BOOL boolIn, CY FAR* pcyOut);
+
+WINOLEAUTAPI VarBstrFromUI1(unsigned char bVal, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut);
+WINOLEAUTAPI VarBstrFromI2(short iVal, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut);
+WINOLEAUTAPI VarBstrFromI4(long lIn, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut);
+WINOLEAUTAPI VarBstrFromR4(float fltIn, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut);
+WINOLEAUTAPI VarBstrFromR8(double dblIn, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut);
+WINOLEAUTAPI VarBstrFromCy(CY cyIn, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut);
+WINOLEAUTAPI VarBstrFromDate(DATE dateIn, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut);
+WINOLEAUTAPI VarBstrFromDisp(IDispatch FAR* pdispIn, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut);
+WINOLEAUTAPI VarBstrFromBool(VARIANT_BOOL boolIn, LCID lcid, unsigned long dwFlags, BSTR FAR* pbstrOut);
+
+WINOLEAUTAPI VarBoolFromUI1(unsigned char bIn, VARIANT_BOOL FAR* pboolOut);
+WINOLEAUTAPI VarBoolFromI2(short sIn, VARIANT_BOOL FAR* pboolOut);
+WINOLEAUTAPI VarBoolFromI4(long lIn, VARIANT_BOOL FAR* pboolOut);
+WINOLEAUTAPI VarBoolFromR4(float fltIn, VARIANT_BOOL FAR* pboolOut);
+WINOLEAUTAPI VarBoolFromR8(double dblIn, VARIANT_BOOL FAR* pboolOut);
+WINOLEAUTAPI VarBoolFromDate(DATE dateIn, VARIANT_BOOL FAR* pboolOut);
+WINOLEAUTAPI VarBoolFromCy(CY cyIn, VARIANT_BOOL FAR* pboolOut);
+WINOLEAUTAPI VarBoolFromStr(OLECHAR FAR* strIn, LCID lcid, unsigned long dwFlags, VARIANT_BOOL FAR* pboolOut);
+WINOLEAUTAPI VarBoolFromDisp(IDispatch FAR* pdispIn, LCID lcid, VARIANT_BOOL FAR* pboolOut);
+
+
+/* Mac Note: On the Mac, the coersion functions support the
+ * Symantec C++ calling convention for float/double. To support
+ * float/double arguments compiled with the MPW C compiler,
+ * use the following APIs to move MPW float/double values into
+ * a VARIANT.
+ */
+
+/*---------------------------------------------------------------------*/
+/* ITypeLib */
+/*---------------------------------------------------------------------*/
+
+
+typedef ITypeLib FAR* LPTYPELIB;
+
+
+/*---------------------------------------------------------------------*/
+/* ITypeInfo */
+/*---------------------------------------------------------------------*/
+
+
+typedef LONG DISPID;
+typedef DISPID MEMBERID;
+
+#define MEMBERID_NIL DISPID_UNKNOWN
+#define ID_DEFAULTINST -2
+
+
+#define IDLFLAG_NONE 0
+#define IDLFLAG_FIN 0x1
+#define IDLFLAG_FOUT 0x2
+#define IDLFLAG_FLCID 0x4
+#define IDLFLAG_FRETVAL 0x8
+
+
+/* Flags for IDispatch::Invoke */
+#define DISPATCH_METHOD 0x1
+#define DISPATCH_PROPERTYGET 0x2
+#define DISPATCH_PROPERTYPUT 0x4
+#define DISPATCH_PROPERTYPUTREF 0x8
+
+
+typedef ITypeInfo FAR* LPTYPEINFO;
+
+
+/*---------------------------------------------------------------------*/
+/* ITypeComp */
+/*---------------------------------------------------------------------*/
+
+typedef ITypeComp FAR* LPTYPECOMP;
+
+
+/*---------------------------------------------------------------------*/
+/* ICreateTypeLib */
+/*---------------------------------------------------------------------*/
+
+typedef ICreateTypeLib FAR* LPCREATETYPELIB;
+
+
+typedef ICreateTypeInfo FAR* LPCREATETYPEINFO;
+
+/*---------------------------------------------------------------------*/
+/* TypeInfo API */
+/*---------------------------------------------------------------------*/
+
+/* compute a 16bit hash value for the given name
+ */
+#ifdef _WIN32
+WINOLEAUTAPI_(ULONG)
+LHashValOfNameSysA(SYSKIND syskind, LCID lcid, const char FAR* szName);
+#endif
+
+WINOLEAUTAPI_(ULONG)
+LHashValOfNameSys(SYSKIND syskind, LCID lcid, const OLECHAR FAR* szName);
+
+#define LHashValOfName(lcid, szName) \
+ LHashValOfNameSys(SYS_WIN32, lcid, szName)
+
+#define WHashValOfLHashVal(lhashval) \
+ ((unsigned short) (0x0000ffff & (lhashval)))
+
+#define IsHashValCompatible(lhashval1, lhashval2) \
+ ((BOOL) ((0x00ff0000 & (lhashval1)) == (0x00ff0000 & (lhashval2))))
+
+/* load the typelib from the file with the given filename
+ */
+WINOLEAUTAPI
+LoadTypeLib(const OLECHAR FAR *szFile, ITypeLib FAR* FAR* pptlib);
+
+/* load registered typelib
+ */
+WINOLEAUTAPI
+LoadRegTypeLib(
+ REFGUID rguid,
+ WORD wVerMajor,
+ WORD wVerMinor,
+ LCID lcid,
+ ITypeLib FAR* FAR* pptlib);
+
+/* get path to registered typelib
+ */
+WINOLEAUTAPI
+QueryPathOfRegTypeLib(
+ REFGUID guid,
+ unsigned short wMaj,
+ unsigned short wMin,
+ LCID lcid,
+ LPBSTR lpbstrPathName);
+
+/* add typelib to registry
+ */
+WINOLEAUTAPI
+RegisterTypeLib(ITypeLib FAR* ptlib, OLECHAR FAR *szFullPath,
+ OLECHAR FAR *szHelpDir);
+
+/* remove typelib from registry
+ */
+WINOLEAUTAPI
+DeregisterTypeLib(REFGUID rguid, WORD wVerMajor, WORD wVerMinor, LCID lcid);
+
+WINOLEAUTAPI
+CreateTypeLib(SYSKIND syskind, const OLECHAR FAR *szFile,
+ ICreateTypeLib FAR* FAR* ppctlib);
+
+/*---------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------*/
+/* IDispatch */
+/*---------------------------------------------------------------------*/
+
+typedef IDispatch FAR* LPDISPATCH;
+
+
+
+/*---------------------------------------------------------------------*/
+/* IDispatch implementation support */
+/*---------------------------------------------------------------------*/
+
+typedef struct FARSTRUCT tagPARAMDATA {
+ OLECHAR FAR* szName; /* parameter name */
+ VARTYPE vt; /* parameter type */
+} PARAMDATA, FAR* LPPARAMDATA;
+
+typedef struct FARSTRUCT tagMETHODDATA {
+ OLECHAR FAR* szName; /* method name */
+ PARAMDATA FAR* ppdata; /* pointer to an array of PARAMDATAs */
+ DISPID dispid; /* method ID */
+ UINT iMeth; /* method index */
+ CALLCONV cc; /* calling convention */
+ UINT cArgs; /* count of arguments */
+ WORD wFlags; /* same wFlags as on IDispatch::Invoke() */
+ VARTYPE vtReturn;
+} METHODDATA, FAR* LPMETHODDATA;
+
+typedef struct FARSTRUCT tagINTERFACEDATA {
+ METHODDATA FAR* pmethdata; /* pointer to an array of METHODDATAs */
+ UINT cMembers; /* count of members */
+} INTERFACEDATA, FAR* LPINTERFACEDATA;
+
+
+
+/* Locate the parameter indicated by the given position, and
+ * return it coerced to the given target VARTYPE (vtTarg).
+ */
+WINOLEAUTAPI
+DispGetParam(
+ DISPPARAMS FAR* pdispparams,
+ UINT position,
+ VARTYPE vtTarg,
+ VARIANT FAR* pvarResult,
+ UINT FAR* puArgErr);
+
+/* Automatic TypeInfo driven implementation of IDispatch::GetIDsOfNames()
+ */
+WINOLEAUTAPI
+DispGetIDsOfNames(
+ ITypeInfo FAR* ptinfo,
+ OLECHAR FAR* FAR* rgszNames,
+ UINT cNames,
+ DISPID FAR* rgdispid);
+
+/* Automatic TypeInfo driven implementation of IDispatch::Invoke()
+ */
+WINOLEAUTAPI
+DispInvoke(
+ void FAR* _this,
+ ITypeInfo FAR* ptinfo,
+ DISPID dispidMember,
+ WORD wFlags,
+ DISPPARAMS FAR* pparams,
+ VARIANT FAR* pvarResult,
+ EXCEPINFO FAR* pexcepinfo,
+ UINT FAR* puArgErr);
+
+/* Construct a TypeInfo from an interface data description
+ */
+WINOLEAUTAPI
+CreateDispTypeInfo(
+ INTERFACEDATA FAR* pidata,
+ LCID lcid,
+ ITypeInfo FAR* FAR* pptinfo);
+
+/* Create an instance of the standard TypeInfo driven IDispatch
+ * implementation.
+ */
+WINOLEAUTAPI
+CreateStdDispatch(
+ IUnknown FAR* punkOuter,
+ void FAR* pvThis,
+ ITypeInfo FAR* ptinfo,
+ IUnknown FAR* FAR* ppunkStdDisp);
+
+
+/*---------------------------------------------------------------------*/
+/* Active Object Registration API */
+/*---------------------------------------------------------------------*/
+
+/* flags for RegisterActiveObject */
+#define ACTIVEOBJECT_STRONG 0x0
+#define ACTIVEOBJECT_WEAK 0x1
+
+WINOLEAUTAPI
+RegisterActiveObject(
+ IUnknown FAR* punk,
+ REFCLSID rclsid,
+ DWORD dwFlags,
+ DWORD FAR* pdwRegister);
+
+WINOLEAUTAPI
+RevokeActiveObject(
+ DWORD dwRegister,
+ void FAR* pvReserved);
+
+WINOLEAUTAPI
+GetActiveObject(
+ REFCLSID rclsid,
+ void FAR* pvReserved,
+ IUnknown FAR* FAR* ppunk);
+
+/*---------------------------------------------------------------------*/
+/* ErrorInfo API */
+/*---------------------------------------------------------------------*/
+
+WINOLEAUTAPI SetErrorInfo(unsigned long dwReserved, IErrorInfo FAR* perrinfo);
+WINOLEAUTAPI GetErrorInfo(unsigned long dwReserved, IErrorInfo FAR* FAR* pperrinfo);
+WINOLEAUTAPI CreateErrorInfo(ICreateErrorInfo FAR* FAR* pperrinfo);
+
+/*---------------------------------------------------------------------*/
+/* MISC API */
+/*---------------------------------------------------------------------*/
+
+WINOLEAUTAPI_(unsigned long) OaBuildVersion(void);
+
+// Declare variant access functions.
+
+
+
+#ifdef NONAMELESSUNION
+# define V_UNION(X, Y) ((X)->u.Y)
+#else
+# define V_UNION(X, Y) ((X)->Y)
+#endif
+
+/* Variant access macros */
+#define V_VT(X) ((X)->vt)
+#define V_ISBYREF(X) (V_VT(X)&VT_BYREF)
+#define V_ISARRAY(X) (V_VT(X)&VT_ARRAY)
+#define V_ISVECTOR(X) (V_VT(X)&VT_VECTOR)
+
+#define V_NONE(X) V_I2(X)
+
+#define V_UI1(X) V_UNION(X, bVal)
+#define V_UI1REF(X) V_UNION(X, pbVal)
+
+#define V_I2(X) V_UNION(X, iVal)
+#define V_I2REF(X) V_UNION(X, piVal)
+
+#define V_I4(X) V_UNION(X, lVal)
+#define V_I4REF(X) V_UNION(X, plVal)
+
+#define V_I8(X) V_UNION(X, hVal)
+#define V_I8REF(X) V_UNION(X, phVal)
+
+#define V_R4(X) V_UNION(X, fltVal)
+#define V_R4REF(X) V_UNION(X, pfltVal)
+
+#define V_R8(X) V_UNION(X, dblVal)
+#define V_R8REF(X) V_UNION(X, pdblVal)
+
+#define V_CY(X) V_UNION(X, cyVal)
+#define V_CYREF(X) V_UNION(X, pcyVal)
+
+#define V_DATE(X) V_UNION(X, date)
+#define V_DATEREF(X) V_UNION(X, pdate)
+
+#define V_BSTR(X) V_UNION(X, bstrVal)
+#define V_BSTRREF(X) V_UNION(X, pbstrVal)
+
+#define V_DISPATCH(X) V_UNION(X, pdispVal)
+#define V_DISPATCHREF(X) V_UNION(X, ppdispVal)
+
+#define V_ERROR(X) V_UNION(X, scode)
+#define V_ERRORREF(X) V_UNION(X, pscode)
+
+#define V_BOOL(X) V_UNION(X, bool)
+#define V_BOOLREF(X) V_UNION(X, pbool)
+
+#define V_UNKNOWN(X) V_UNION(X, punkVal)
+#define V_UNKNOWNREF(X) V_UNION(X, ppunkVal)
+
+
+#define V_VARIANTREF(X) V_UNION(X, pvarVal)
+
+#define V_LPSTR(X) V_UNION(X, pszVal)
+#define V_LPSTRREF(X) V_UNION(X, ppszVal)
+
+#define V_LPWSTR(X) V_UNION(X, pwszVal)
+#define V_LPWSTRREF(X) V_UNION(X, ppwszVal)
+
+#define V_FILETIME(X) V_UNION(X, filetime)
+#define V_FILETIMEREF(X) V_UNION(X, pfiletime)
+
+#define V_BLOB(X) V_UNION(X, blob)
+
+#define V_UUID(X) V_UNION(X, puuid)
+#define V_CLSID(X) V_UNION(X, puuid)
+
+#define V_ARRAY(X) V_UNION(X, parray)
+#define V_ARRAYREF(X) V_UNION(X, pparray)
+
+#define V_BYREF(X) V_UNION(X, byref)
+
+#ifndef RC_INVOKED
+#include <poppack.h>
+#endif // RC_INVOKED
+
+#endif // __OLEAUTO_H__
+
diff --git a/private/ole32/stg/props/iprop/oleidl.h b/private/ole32/stg/props/iprop/oleidl.h
new file mode 100644
index 000000000..9cfd68f96
--- /dev/null
+++ b/private/ole32/stg/props/iprop/oleidl.h
@@ -0,0 +1,4916 @@
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+/* File created by MIDL compiler version 2.00.0102 */
+/* at Fri Apr 28 07:02:35 1995
+ */
+//@@MIDL_FILE_HEADING( )
+#ifndef __RPCBASE_H__
+#include "rpcbase.h"
+#endif /* ___RPCBASE_H__ */
+#ifndef NORPC
+#ifndef __RPC_H__
+#include "rpc.h"
+#endif /* ___RPC_H__ */
+#ifndef __RPCNDR_H__
+#include "rpcndr.h"
+#endif /* __RPCNDR_H_ */
+#endif /* NORPC */
+#ifndef COM_NO_WINDOWS_H
+#ifndef _INC_WINDOWS
+#include "windows.h"
+#endif /* _INC_WINDOWS */
+#ifndef _OLE2_H_
+#include "ole2.h"
+#endif /* _OLE2_H_ */
+#endif /*COM_NO_WINDOWS_H*/
+
+#ifndef __oleidl_h__
+#define __oleidl_h__
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/* Forward Declarations */
+
+#ifndef __IOleAdviseHolder_FWD_DEFINED__
+#define __IOleAdviseHolder_FWD_DEFINED__
+typedef interface IOleAdviseHolder IOleAdviseHolder;
+#endif /* __IOleAdviseHolder_FWD_DEFINED__ */
+
+
+#ifndef __IOleCache_FWD_DEFINED__
+#define __IOleCache_FWD_DEFINED__
+typedef interface IOleCache IOleCache;
+#endif /* __IOleCache_FWD_DEFINED__ */
+
+
+#ifndef __IOleCache2_FWD_DEFINED__
+#define __IOleCache2_FWD_DEFINED__
+typedef interface IOleCache2 IOleCache2;
+#endif /* __IOleCache2_FWD_DEFINED__ */
+
+
+#ifndef __IOleCacheControl_FWD_DEFINED__
+#define __IOleCacheControl_FWD_DEFINED__
+typedef interface IOleCacheControl IOleCacheControl;
+#endif /* __IOleCacheControl_FWD_DEFINED__ */
+
+
+#ifndef __IParseDisplayName_FWD_DEFINED__
+#define __IParseDisplayName_FWD_DEFINED__
+typedef interface IParseDisplayName IParseDisplayName;
+#endif /* __IParseDisplayName_FWD_DEFINED__ */
+
+
+#ifndef __IOleContainer_FWD_DEFINED__
+#define __IOleContainer_FWD_DEFINED__
+typedef interface IOleContainer IOleContainer;
+#endif /* __IOleContainer_FWD_DEFINED__ */
+
+
+#ifndef __IOleClientSite_FWD_DEFINED__
+#define __IOleClientSite_FWD_DEFINED__
+typedef interface IOleClientSite IOleClientSite;
+#endif /* __IOleClientSite_FWD_DEFINED__ */
+
+
+#ifndef __IOleObject_FWD_DEFINED__
+#define __IOleObject_FWD_DEFINED__
+typedef interface IOleObject IOleObject;
+#endif /* __IOleObject_FWD_DEFINED__ */
+
+
+#ifndef __IOleWindow_FWD_DEFINED__
+#define __IOleWindow_FWD_DEFINED__
+typedef interface IOleWindow IOleWindow;
+#endif /* __IOleWindow_FWD_DEFINED__ */
+
+
+#ifndef __IOleLink_FWD_DEFINED__
+#define __IOleLink_FWD_DEFINED__
+typedef interface IOleLink IOleLink;
+#endif /* __IOleLink_FWD_DEFINED__ */
+
+
+#ifndef __IOleItemContainer_FWD_DEFINED__
+#define __IOleItemContainer_FWD_DEFINED__
+typedef interface IOleItemContainer IOleItemContainer;
+#endif /* __IOleItemContainer_FWD_DEFINED__ */
+
+
+#ifndef __IOleInPlaceUIWindow_FWD_DEFINED__
+#define __IOleInPlaceUIWindow_FWD_DEFINED__
+typedef interface IOleInPlaceUIWindow IOleInPlaceUIWindow;
+#endif /* __IOleInPlaceUIWindow_FWD_DEFINED__ */
+
+
+#ifndef __IOleInPlaceActiveObject_FWD_DEFINED__
+#define __IOleInPlaceActiveObject_FWD_DEFINED__
+typedef interface IOleInPlaceActiveObject IOleInPlaceActiveObject;
+#endif /* __IOleInPlaceActiveObject_FWD_DEFINED__ */
+
+
+#ifndef __IOleInPlaceFrame_FWD_DEFINED__
+#define __IOleInPlaceFrame_FWD_DEFINED__
+typedef interface IOleInPlaceFrame IOleInPlaceFrame;
+#endif /* __IOleInPlaceFrame_FWD_DEFINED__ */
+
+
+#ifndef __IOleInPlaceObject_FWD_DEFINED__
+#define __IOleInPlaceObject_FWD_DEFINED__
+typedef interface IOleInPlaceObject IOleInPlaceObject;
+#endif /* __IOleInPlaceObject_FWD_DEFINED__ */
+
+
+#ifndef __IOleInPlaceSite_FWD_DEFINED__
+#define __IOleInPlaceSite_FWD_DEFINED__
+typedef interface IOleInPlaceSite IOleInPlaceSite;
+#endif /* __IOleInPlaceSite_FWD_DEFINED__ */
+
+
+#ifndef __IViewObject_FWD_DEFINED__
+#define __IViewObject_FWD_DEFINED__
+typedef interface IViewObject IViewObject;
+#endif /* __IViewObject_FWD_DEFINED__ */
+
+
+#ifndef __IViewObject2_FWD_DEFINED__
+#define __IViewObject2_FWD_DEFINED__
+typedef interface IViewObject2 IViewObject2;
+#endif /* __IViewObject2_FWD_DEFINED__ */
+
+
+#ifndef __IDropSource_FWD_DEFINED__
+#define __IDropSource_FWD_DEFINED__
+typedef interface IDropSource IDropSource;
+#endif /* __IDropSource_FWD_DEFINED__ */
+
+
+#ifndef __IDropTarget_FWD_DEFINED__
+#define __IDropTarget_FWD_DEFINED__
+typedef interface IDropTarget IDropTarget;
+#endif /* __IDropTarget_FWD_DEFINED__ */
+
+
+#ifndef __IEnumOLEVERB_FWD_DEFINED__
+#define __IEnumOLEVERB_FWD_DEFINED__
+typedef interface IEnumOLEVERB IEnumOLEVERB;
+#endif /* __IEnumOLEVERB_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#ifndef __objidl_h__
+#include "objidl.h"
+#endif /* __objidl_h__ */
+
+void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
+void __RPC_USER MIDL_user_free( void __RPC_FAR * );
+
+/****************************************
+ * Generated header for interface: __MIDL__intf_0000
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [local] */
+
+
+ /* size is 0 */
+
+ /* size is 0 */
+
+
+
+#ifndef NOPROXYSTUB
+extern RPC_IF_HANDLE __MIDL__intf_0000_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL__intf_0000_v0_0_s_ifspec;
+#endif
+
+#ifndef __IOleAdviseHolder_INTERFACE_DEFINED__
+#define __IOleAdviseHolder_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleAdviseHolder
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+//--------------------------------------------------------------------------
+ /* size is 4 */
+typedef /* [unique] */ IOleAdviseHolder __RPC_FAR *LPOLEADVISEHOLDER;
+
+
+EXTERN_C const IID IID_IOleAdviseHolder;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleAdviseHolder : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall Advise(
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvise,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection) = 0;
+
+ virtual HRESULT __stdcall Unadvise(
+ /* [in] */ DWORD dwConnection) = 0;
+
+ virtual HRESULT __stdcall EnumAdvise(
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise) = 0;
+
+ virtual HRESULT __stdcall SendOnRename(
+ /* [unique][in] */ IMoniker __RPC_FAR *pmk) = 0;
+
+ virtual HRESULT __stdcall SendOnSave( void) = 0;
+
+ virtual HRESULT __stdcall SendOnClose( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleAdviseHolderVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleAdviseHolder __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleAdviseHolder __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleAdviseHolder __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Advise )(
+ IOleAdviseHolder __RPC_FAR * This,
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvise,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection);
+
+ HRESULT ( __stdcall __RPC_FAR *Unadvise )(
+ IOleAdviseHolder __RPC_FAR * This,
+ /* [in] */ DWORD dwConnection);
+
+ HRESULT ( __stdcall __RPC_FAR *EnumAdvise )(
+ IOleAdviseHolder __RPC_FAR * This,
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise);
+
+ HRESULT ( __stdcall __RPC_FAR *SendOnRename )(
+ IOleAdviseHolder __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmk);
+
+ HRESULT ( __stdcall __RPC_FAR *SendOnSave )(
+ IOleAdviseHolder __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *SendOnClose )(
+ IOleAdviseHolder __RPC_FAR * This);
+
+ } IOleAdviseHolderVtbl;
+
+ interface IOleAdviseHolder
+ {
+ CONST_VTBL struct IOleAdviseHolderVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleAdviseHolder_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleAdviseHolder_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleAdviseHolder_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleAdviseHolder_Advise(This,pAdvise,pdwConnection) \
+ (This)->lpVtbl -> Advise(This,pAdvise,pdwConnection)
+
+#define IOleAdviseHolder_Unadvise(This,dwConnection) \
+ (This)->lpVtbl -> Unadvise(This,dwConnection)
+
+#define IOleAdviseHolder_EnumAdvise(This,ppenumAdvise) \
+ (This)->lpVtbl -> EnumAdvise(This,ppenumAdvise)
+
+#define IOleAdviseHolder_SendOnRename(This,pmk) \
+ (This)->lpVtbl -> SendOnRename(This,pmk)
+
+#define IOleAdviseHolder_SendOnSave(This) \
+ (This)->lpVtbl -> SendOnSave(This)
+
+#define IOleAdviseHolder_SendOnClose(This) \
+ (This)->lpVtbl -> SendOnClose(This)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IOleAdviseHolder_Advise_Proxy(
+ IOleAdviseHolder __RPC_FAR * This,
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvise,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection);
+
+
+void __RPC_STUB IOleAdviseHolder_Advise_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleAdviseHolder_Unadvise_Proxy(
+ IOleAdviseHolder __RPC_FAR * This,
+ /* [in] */ DWORD dwConnection);
+
+
+void __RPC_STUB IOleAdviseHolder_Unadvise_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleAdviseHolder_EnumAdvise_Proxy(
+ IOleAdviseHolder __RPC_FAR * This,
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise);
+
+
+void __RPC_STUB IOleAdviseHolder_EnumAdvise_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleAdviseHolder_SendOnRename_Proxy(
+ IOleAdviseHolder __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmk);
+
+
+void __RPC_STUB IOleAdviseHolder_SendOnRename_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleAdviseHolder_SendOnSave_Proxy(
+ IOleAdviseHolder __RPC_FAR * This);
+
+
+void __RPC_STUB IOleAdviseHolder_SendOnSave_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleAdviseHolder_SendOnClose_Proxy(
+ IOleAdviseHolder __RPC_FAR * This);
+
+
+void __RPC_STUB IOleAdviseHolder_SendOnClose_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleAdviseHolder_INTERFACE_DEFINED__ */
+
+
+#ifndef __IOleCache_INTERFACE_DEFINED__
+#define __IOleCache_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleCache
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object][local] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IOleCache __RPC_FAR *LPOLECACHE;
+
+
+EXTERN_C const IID IID_IOleCache;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleCache : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall Cache(
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [in] */ DWORD advf,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection) = 0;
+
+ virtual HRESULT __stdcall Uncache(
+ /* [in] */ DWORD dwConnection) = 0;
+
+ virtual HRESULT __stdcall EnumCache(
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumSTATDATA) = 0;
+
+ virtual HRESULT __stdcall InitCache(
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObject) = 0;
+
+ virtual HRESULT __stdcall SetData(
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [unique][in] */ STGMEDIUM __RPC_FAR *pmedium,
+ /* [in] */ BOOL fRelease) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleCacheVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleCache __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleCache __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleCache __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Cache )(
+ IOleCache __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [in] */ DWORD advf,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection);
+
+ HRESULT ( __stdcall __RPC_FAR *Uncache )(
+ IOleCache __RPC_FAR * This,
+ /* [in] */ DWORD dwConnection);
+
+ HRESULT ( __stdcall __RPC_FAR *EnumCache )(
+ IOleCache __RPC_FAR * This,
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumSTATDATA);
+
+ HRESULT ( __stdcall __RPC_FAR *InitCache )(
+ IOleCache __RPC_FAR * This,
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObject);
+
+ HRESULT ( __stdcall __RPC_FAR *SetData )(
+ IOleCache __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [unique][in] */ STGMEDIUM __RPC_FAR *pmedium,
+ /* [in] */ BOOL fRelease);
+
+ } IOleCacheVtbl;
+
+ interface IOleCache
+ {
+ CONST_VTBL struct IOleCacheVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleCache_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleCache_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleCache_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleCache_Cache(This,pformatetc,advf,pdwConnection) \
+ (This)->lpVtbl -> Cache(This,pformatetc,advf,pdwConnection)
+
+#define IOleCache_Uncache(This,dwConnection) \
+ (This)->lpVtbl -> Uncache(This,dwConnection)
+
+#define IOleCache_EnumCache(This,ppenumSTATDATA) \
+ (This)->lpVtbl -> EnumCache(This,ppenumSTATDATA)
+
+#define IOleCache_InitCache(This,pDataObject) \
+ (This)->lpVtbl -> InitCache(This,pDataObject)
+
+#define IOleCache_SetData(This,pformatetc,pmedium,fRelease) \
+ (This)->lpVtbl -> SetData(This,pformatetc,pmedium,fRelease)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IOleCache_Cache_Proxy(
+ IOleCache __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [in] */ DWORD advf,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection);
+
+
+void __RPC_STUB IOleCache_Cache_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleCache_Uncache_Proxy(
+ IOleCache __RPC_FAR * This,
+ /* [in] */ DWORD dwConnection);
+
+
+void __RPC_STUB IOleCache_Uncache_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleCache_EnumCache_Proxy(
+ IOleCache __RPC_FAR * This,
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumSTATDATA);
+
+
+void __RPC_STUB IOleCache_EnumCache_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleCache_InitCache_Proxy(
+ IOleCache __RPC_FAR * This,
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObject);
+
+
+void __RPC_STUB IOleCache_InitCache_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleCache_SetData_Proxy(
+ IOleCache __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [unique][in] */ STGMEDIUM __RPC_FAR *pmedium,
+ /* [in] */ BOOL fRelease);
+
+
+void __RPC_STUB IOleCache_SetData_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleCache_INTERFACE_DEFINED__ */
+
+
+#ifndef __IOleCache2_INTERFACE_DEFINED__
+#define __IOleCache2_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleCache2
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][local][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IOleCache2 __RPC_FAR *LPOLECACHE2;
+
+ /* size is 4 */
+#define UPDFCACHE_NODATACACHE ( 0x1 )
+
+ /* size is 4 */
+#define UPDFCACHE_ONSAVECACHE ( 0x2 )
+
+ /* size is 4 */
+#define UPDFCACHE_ONSTOPCACHE ( 0x4 )
+
+ /* size is 4 */
+#define UPDFCACHE_NORMALCACHE ( 0x8 )
+
+ /* size is 4 */
+#define UPDFCACHE_IFBLANK ( 0x10 )
+
+ /* size is 4 */
+#define UPDFCACHE_ONLYIFBLANK ( 0x80000000 )
+
+ /* size is 4 */
+#define UPDFCACHE_IFBLANKORONSAVECACHE ( UPDFCACHE_IFBLANK | UPDFCACHE_ONSAVECACHE )
+
+ /* size is 4 */
+#define UPDFCACHE_ALL ( ( DWORD )~UPDFCACHE_ONLYIFBLANK )
+
+ /* size is 4 */
+#define UPDFCACHE_ALLBUTNODATACACHE ( UPDFCACHE_ALL & ( DWORD )~UPDFCACHE_NODATACACHE )
+
+ /* size is 2 */
+typedef /* [transmit] */
+enum tagDISCARDCACHE
+ { DISCARDCACHE_SAVEIFDIRTY = 0,
+ DISCARDCACHE_NOSAVE = 1
+ } DISCARDCACHE;
+
+#define DISCARDCACHE_to_xmit(pEnum, ppLong) *(ppLong) = (long *) (pEnum)
+#define DISCARDCACHE_from_xmit(pLong, pEnum) *(pEnum) = (DISCARDCACHE) *(pLong)
+#define DISCARDCACHE_free_inst(pEnum)
+#define DISCARDCACHE_free_xmit(pLong)
+
+EXTERN_C const IID IID_IOleCache2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleCache2 : public IOleCache
+ {
+ public:
+ virtual HRESULT __stdcall UpdateCache(
+ /* [in] */ LPDATAOBJECT pDataObject,
+ /* [in] */ DWORD grfUpdf,
+ /* [in] */ LPVOID pReserved) = 0;
+
+ virtual HRESULT __stdcall DiscardCache(
+ /* [in] */ DWORD dwDiscardOptions) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleCache2Vtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleCache2 __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleCache2 __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleCache2 __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Cache )(
+ IOleCache2 __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [in] */ DWORD advf,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection);
+
+ HRESULT ( __stdcall __RPC_FAR *Uncache )(
+ IOleCache2 __RPC_FAR * This,
+ /* [in] */ DWORD dwConnection);
+
+ HRESULT ( __stdcall __RPC_FAR *EnumCache )(
+ IOleCache2 __RPC_FAR * This,
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumSTATDATA);
+
+ HRESULT ( __stdcall __RPC_FAR *InitCache )(
+ IOleCache2 __RPC_FAR * This,
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObject);
+
+ HRESULT ( __stdcall __RPC_FAR *SetData )(
+ IOleCache2 __RPC_FAR * This,
+ /* [unique][in] */ FORMATETC __RPC_FAR *pformatetc,
+ /* [unique][in] */ STGMEDIUM __RPC_FAR *pmedium,
+ /* [in] */ BOOL fRelease);
+
+ HRESULT ( __stdcall __RPC_FAR *UpdateCache )(
+ IOleCache2 __RPC_FAR * This,
+ /* [in] */ LPDATAOBJECT pDataObject,
+ /* [in] */ DWORD grfUpdf,
+ /* [in] */ LPVOID pReserved);
+
+ HRESULT ( __stdcall __RPC_FAR *DiscardCache )(
+ IOleCache2 __RPC_FAR * This,
+ /* [in] */ DWORD dwDiscardOptions);
+
+ } IOleCache2Vtbl;
+
+ interface IOleCache2
+ {
+ CONST_VTBL struct IOleCache2Vtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleCache2_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleCache2_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleCache2_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleCache2_Cache(This,pformatetc,advf,pdwConnection) \
+ (This)->lpVtbl -> Cache(This,pformatetc,advf,pdwConnection)
+
+#define IOleCache2_Uncache(This,dwConnection) \
+ (This)->lpVtbl -> Uncache(This,dwConnection)
+
+#define IOleCache2_EnumCache(This,ppenumSTATDATA) \
+ (This)->lpVtbl -> EnumCache(This,ppenumSTATDATA)
+
+#define IOleCache2_InitCache(This,pDataObject) \
+ (This)->lpVtbl -> InitCache(This,pDataObject)
+
+#define IOleCache2_SetData(This,pformatetc,pmedium,fRelease) \
+ (This)->lpVtbl -> SetData(This,pformatetc,pmedium,fRelease)
+
+
+#define IOleCache2_UpdateCache(This,pDataObject,grfUpdf,pReserved) \
+ (This)->lpVtbl -> UpdateCache(This,pDataObject,grfUpdf,pReserved)
+
+#define IOleCache2_DiscardCache(This,dwDiscardOptions) \
+ (This)->lpVtbl -> DiscardCache(This,dwDiscardOptions)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IOleCache2_UpdateCache_Proxy(
+ IOleCache2 __RPC_FAR * This,
+ /* [in] */ LPDATAOBJECT pDataObject,
+ /* [in] */ DWORD grfUpdf,
+ /* [in] */ LPVOID pReserved);
+
+
+void __RPC_STUB IOleCache2_UpdateCache_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleCache2_DiscardCache_Proxy(
+ IOleCache2 __RPC_FAR * This,
+ /* [in] */ DWORD dwDiscardOptions);
+
+
+void __RPC_STUB IOleCache2_DiscardCache_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleCache2_INTERFACE_DEFINED__ */
+
+
+#ifndef __IOleCacheControl_INTERFACE_DEFINED__
+#define __IOleCacheControl_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleCacheControl
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][local][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IOleCacheControl __RPC_FAR *LPOLECACHECONTROL;
+
+
+EXTERN_C const IID IID_IOleCacheControl;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleCacheControl : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall OnRun(
+ LPDATAOBJECT pDataObject) = 0;
+
+ virtual HRESULT __stdcall OnStop( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleCacheControlVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleCacheControl __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleCacheControl __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleCacheControl __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *OnRun )(
+ IOleCacheControl __RPC_FAR * This,
+ LPDATAOBJECT pDataObject);
+
+ HRESULT ( __stdcall __RPC_FAR *OnStop )(
+ IOleCacheControl __RPC_FAR * This);
+
+ } IOleCacheControlVtbl;
+
+ interface IOleCacheControl
+ {
+ CONST_VTBL struct IOleCacheControlVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleCacheControl_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleCacheControl_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleCacheControl_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleCacheControl_OnRun(This,pDataObject) \
+ (This)->lpVtbl -> OnRun(This,pDataObject)
+
+#define IOleCacheControl_OnStop(This) \
+ (This)->lpVtbl -> OnStop(This)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IOleCacheControl_OnRun_Proxy(
+ IOleCacheControl __RPC_FAR * This,
+ LPDATAOBJECT pDataObject);
+
+
+void __RPC_STUB IOleCacheControl_OnRun_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleCacheControl_OnStop_Proxy(
+ IOleCacheControl __RPC_FAR * This);
+
+
+void __RPC_STUB IOleCacheControl_OnStop_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleCacheControl_INTERFACE_DEFINED__ */
+
+
+#ifndef __IParseDisplayName_INTERFACE_DEFINED__
+#define __IParseDisplayName_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IParseDisplayName
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IParseDisplayName __RPC_FAR *LPPARSEDISPLAYNAME;
+
+
+EXTERN_C const IID IID_IParseDisplayName;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IParseDisplayName : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall ParseDisplayName(
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ LPOLESTR pszDisplayName,
+ /* [out] */ ULONG __RPC_FAR *pchEaten,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IParseDisplayNameVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IParseDisplayName __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IParseDisplayName __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IParseDisplayName __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *ParseDisplayName )(
+ IParseDisplayName __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ LPOLESTR pszDisplayName,
+ /* [out] */ ULONG __RPC_FAR *pchEaten,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut);
+
+ } IParseDisplayNameVtbl;
+
+ interface IParseDisplayName
+ {
+ CONST_VTBL struct IParseDisplayNameVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IParseDisplayName_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IParseDisplayName_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IParseDisplayName_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IParseDisplayName_ParseDisplayName(This,pbc,pszDisplayName,pchEaten,ppmkOut) \
+ (This)->lpVtbl -> ParseDisplayName(This,pbc,pszDisplayName,pchEaten,ppmkOut)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IParseDisplayName_ParseDisplayName_Proxy(
+ IParseDisplayName __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ LPOLESTR pszDisplayName,
+ /* [out] */ ULONG __RPC_FAR *pchEaten,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut);
+
+
+void __RPC_STUB IParseDisplayName_ParseDisplayName_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IParseDisplayName_INTERFACE_DEFINED__ */
+
+
+#ifndef __IOleContainer_INTERFACE_DEFINED__
+#define __IOleContainer_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleContainer
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IOleContainer __RPC_FAR *LPOLECONTAINER;
+
+
+EXTERN_C const IID IID_IOleContainer;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleContainer : public IParseDisplayName
+ {
+ public:
+ virtual HRESULT __stdcall EnumObjects(
+ /* [in] */ DWORD grfFlags,
+ /* [out] */ IEnumUnknown __RPC_FAR *__RPC_FAR *ppenum) = 0;
+
+ virtual HRESULT __stdcall LockContainer(
+ /* [in] */ BOOL fLock) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleContainerVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleContainer __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleContainer __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleContainer __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *ParseDisplayName )(
+ IOleContainer __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ LPOLESTR pszDisplayName,
+ /* [out] */ ULONG __RPC_FAR *pchEaten,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut);
+
+ HRESULT ( __stdcall __RPC_FAR *EnumObjects )(
+ IOleContainer __RPC_FAR * This,
+ /* [in] */ DWORD grfFlags,
+ /* [out] */ IEnumUnknown __RPC_FAR *__RPC_FAR *ppenum);
+
+ HRESULT ( __stdcall __RPC_FAR *LockContainer )(
+ IOleContainer __RPC_FAR * This,
+ /* [in] */ BOOL fLock);
+
+ } IOleContainerVtbl;
+
+ interface IOleContainer
+ {
+ CONST_VTBL struct IOleContainerVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleContainer_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleContainer_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleContainer_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleContainer_ParseDisplayName(This,pbc,pszDisplayName,pchEaten,ppmkOut) \
+ (This)->lpVtbl -> ParseDisplayName(This,pbc,pszDisplayName,pchEaten,ppmkOut)
+
+
+#define IOleContainer_EnumObjects(This,grfFlags,ppenum) \
+ (This)->lpVtbl -> EnumObjects(This,grfFlags,ppenum)
+
+#define IOleContainer_LockContainer(This,fLock) \
+ (This)->lpVtbl -> LockContainer(This,fLock)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IOleContainer_EnumObjects_Proxy(
+ IOleContainer __RPC_FAR * This,
+ /* [in] */ DWORD grfFlags,
+ /* [out] */ IEnumUnknown __RPC_FAR *__RPC_FAR *ppenum);
+
+
+void __RPC_STUB IOleContainer_EnumObjects_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleContainer_LockContainer_Proxy(
+ IOleContainer __RPC_FAR * This,
+ /* [in] */ BOOL fLock);
+
+
+void __RPC_STUB IOleContainer_LockContainer_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleContainer_INTERFACE_DEFINED__ */
+
+
+#ifndef __IOleClientSite_INTERFACE_DEFINED__
+#define __IOleClientSite_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleClientSite
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IOleClientSite __RPC_FAR *LPOLECLIENTSITE;
+
+
+EXTERN_C const IID IID_IOleClientSite;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleClientSite : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall SaveObject( void) = 0;
+
+ virtual HRESULT __stdcall GetMoniker(
+ /* [in] */ DWORD dwAssign,
+ /* [in] */ DWORD dwWhichMoniker,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk) = 0;
+
+ virtual HRESULT __stdcall GetContainer(
+ /* [out] */ IOleContainer __RPC_FAR *__RPC_FAR *ppContainer) = 0;
+
+ virtual HRESULT __stdcall ShowObject( void) = 0;
+
+ virtual HRESULT __stdcall OnShowWindow(
+ /* [in] */ BOOL fShow) = 0;
+
+ virtual HRESULT __stdcall RequestNewObjectLayout( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleClientSiteVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleClientSite __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleClientSite __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleClientSite __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *SaveObject )(
+ IOleClientSite __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetMoniker )(
+ IOleClientSite __RPC_FAR * This,
+ /* [in] */ DWORD dwAssign,
+ /* [in] */ DWORD dwWhichMoniker,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk);
+
+ HRESULT ( __stdcall __RPC_FAR *GetContainer )(
+ IOleClientSite __RPC_FAR * This,
+ /* [out] */ IOleContainer __RPC_FAR *__RPC_FAR *ppContainer);
+
+ HRESULT ( __stdcall __RPC_FAR *ShowObject )(
+ IOleClientSite __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *OnShowWindow )(
+ IOleClientSite __RPC_FAR * This,
+ /* [in] */ BOOL fShow);
+
+ HRESULT ( __stdcall __RPC_FAR *RequestNewObjectLayout )(
+ IOleClientSite __RPC_FAR * This);
+
+ } IOleClientSiteVtbl;
+
+ interface IOleClientSite
+ {
+ CONST_VTBL struct IOleClientSiteVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleClientSite_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleClientSite_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleClientSite_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleClientSite_SaveObject(This) \
+ (This)->lpVtbl -> SaveObject(This)
+
+#define IOleClientSite_GetMoniker(This,dwAssign,dwWhichMoniker,ppmk) \
+ (This)->lpVtbl -> GetMoniker(This,dwAssign,dwWhichMoniker,ppmk)
+
+#define IOleClientSite_GetContainer(This,ppContainer) \
+ (This)->lpVtbl -> GetContainer(This,ppContainer)
+
+#define IOleClientSite_ShowObject(This) \
+ (This)->lpVtbl -> ShowObject(This)
+
+#define IOleClientSite_OnShowWindow(This,fShow) \
+ (This)->lpVtbl -> OnShowWindow(This,fShow)
+
+#define IOleClientSite_RequestNewObjectLayout(This) \
+ (This)->lpVtbl -> RequestNewObjectLayout(This)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IOleClientSite_SaveObject_Proxy(
+ IOleClientSite __RPC_FAR * This);
+
+
+void __RPC_STUB IOleClientSite_SaveObject_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleClientSite_GetMoniker_Proxy(
+ IOleClientSite __RPC_FAR * This,
+ /* [in] */ DWORD dwAssign,
+ /* [in] */ DWORD dwWhichMoniker,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk);
+
+
+void __RPC_STUB IOleClientSite_GetMoniker_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleClientSite_GetContainer_Proxy(
+ IOleClientSite __RPC_FAR * This,
+ /* [out] */ IOleContainer __RPC_FAR *__RPC_FAR *ppContainer);
+
+
+void __RPC_STUB IOleClientSite_GetContainer_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleClientSite_ShowObject_Proxy(
+ IOleClientSite __RPC_FAR * This);
+
+
+void __RPC_STUB IOleClientSite_ShowObject_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleClientSite_OnShowWindow_Proxy(
+ IOleClientSite __RPC_FAR * This,
+ /* [in] */ BOOL fShow);
+
+
+void __RPC_STUB IOleClientSite_OnShowWindow_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleClientSite_RequestNewObjectLayout_Proxy(
+ IOleClientSite __RPC_FAR * This);
+
+
+void __RPC_STUB IOleClientSite_RequestNewObjectLayout_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleClientSite_INTERFACE_DEFINED__ */
+
+
+#ifndef __IOleObject_INTERFACE_DEFINED__
+#define __IOleObject_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleObject
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IOleObject __RPC_FAR *LPOLEOBJECT;
+
+ /* size is 2 */
+typedef
+enum tagOLEGETMONIKER
+ { OLEGETMONIKER_ONLYIFTHERE = 1,
+ OLEGETMONIKER_FORCEASSIGN = 2,
+ OLEGETMONIKER_UNASSIGN = 3,
+ OLEGETMONIKER_TEMPFORUSER = 4
+ } OLEGETMONIKER;
+
+ /* size is 2 */
+typedef
+enum tagOLEWHICHMK
+ { OLEWHICHMK_CONTAINER = 1,
+ OLEWHICHMK_OBJREL = 2,
+ OLEWHICHMK_OBJFULL = 3
+ } OLEWHICHMK;
+
+ /* size is 2 */
+typedef
+enum tagUSERCLASSTYPE
+ { USERCLASSTYPE_FULL = 1,
+ USERCLASSTYPE_SHORT = 2,
+ USERCLASSTYPE_APPNAME = 3
+ } USERCLASSTYPE;
+
+ /* size is 2 */
+typedef
+enum tagOLEMISC
+ { OLEMISC_RECOMPOSEONRESIZE = 1,
+ OLEMISC_ONLYICONIC = 2,
+ OLEMISC_INSERTNOTREPLACE = 4,
+ OLEMISC_STATIC = 8,
+ OLEMISC_CANTLINKINSIDE = 16,
+ OLEMISC_CANLINKBYOLE1 = 32,
+ OLEMISC_ISLINKOBJECT = 64,
+ OLEMISC_INSIDEOUT = 128,
+ OLEMISC_ACTIVATEWHENVISIBLE = 256,
+ OLEMISC_RENDERINGISDEVICEINDEPENDENT = 512
+ } OLEMISC;
+
+ /* size is 2 */
+typedef
+enum tagOLECLOSE
+ { OLECLOSE_SAVEIFDIRTY = 0,
+ OLECLOSE_NOSAVE = 1,
+ OLECLOSE_PROMPTSAVE = 2
+ } OLECLOSE;
+
+
+EXTERN_C const IID IID_IOleObject;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleObject : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall SetClientSite(
+ /* [unique][in] */ IOleClientSite __RPC_FAR *pClientSite) = 0;
+
+ virtual HRESULT __stdcall GetClientSite(
+ /* [out] */ IOleClientSite __RPC_FAR *__RPC_FAR *ppClientSite) = 0;
+
+ virtual HRESULT __stdcall SetHostNames(
+ /* [in] */ LPCOLESTR szContainerApp,
+ /* [unique][in] */ LPCOLESTR szContainerObj) = 0;
+
+ virtual HRESULT __stdcall Close(
+ /* [in] */ DWORD dwSaveOption) = 0;
+
+ virtual HRESULT __stdcall SetMoniker(
+ /* [in] */ DWORD dwWhichMoniker,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmk) = 0;
+
+ virtual HRESULT __stdcall GetMoniker(
+ /* [in] */ DWORD dwAssign,
+ /* [in] */ DWORD dwWhichMoniker,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk) = 0;
+
+ virtual HRESULT __stdcall InitFromData(
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObject,
+ /* [in] */ BOOL fCreation,
+ /* [in] */ DWORD dwReserved) = 0;
+
+ virtual HRESULT __stdcall GetClipboardData(
+ /* [in] */ DWORD dwReserved,
+ /* [out] */ IDataObject __RPC_FAR *__RPC_FAR *ppDataObject) = 0;
+
+ virtual HRESULT __stdcall DoVerb(
+ /* [in] */ LONG iVerb,
+ /* [unique][in] */ LPMSG lpmsg,
+ /* [unique][in] */ IOleClientSite __RPC_FAR *pActiveSite,
+ /* [in] */ LONG lindex,
+ /* [in] */ HWND hwndParent,
+ /* [unique][in] */ LPCRECT lprcPosRect) = 0;
+
+ virtual HRESULT __stdcall EnumVerbs(
+ /* [out] */ IEnumOLEVERB __RPC_FAR *__RPC_FAR *ppEnumOleVerb) = 0;
+
+ virtual HRESULT __stdcall Update( void) = 0;
+
+ virtual HRESULT __stdcall IsUpToDate( void) = 0;
+
+ virtual HRESULT __stdcall GetUserClassID(
+ /* [out] */ CLSID __RPC_FAR *pClsid) = 0;
+
+ virtual HRESULT __stdcall GetUserType(
+ /* [in] */ DWORD dwFormOfType,
+ /* [out] */ LPOLESTR __RPC_FAR *pszUserType) = 0;
+
+ virtual HRESULT __stdcall SetExtent(
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ SIZEL __RPC_FAR *psizel) = 0;
+
+ virtual HRESULT __stdcall GetExtent(
+ /* [in] */ DWORD dwDrawAspect,
+ /* [out] */ SIZEL __RPC_FAR *psizel) = 0;
+
+ virtual HRESULT __stdcall Advise(
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection) = 0;
+
+ virtual HRESULT __stdcall Unadvise(
+ /* [in] */ DWORD dwConnection) = 0;
+
+ virtual HRESULT __stdcall EnumAdvise(
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise) = 0;
+
+ virtual HRESULT __stdcall GetMiscStatus(
+ /* [in] */ DWORD dwAspect,
+ /* [out] */ DWORD __RPC_FAR *pdwStatus) = 0;
+
+ virtual HRESULT __stdcall SetColorScheme(
+ /* [in] */ LOGPALETTE __RPC_FAR *pLogpal) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleObjectVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleObject __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleObject __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *SetClientSite )(
+ IOleObject __RPC_FAR * This,
+ /* [unique][in] */ IOleClientSite __RPC_FAR *pClientSite);
+
+ HRESULT ( __stdcall __RPC_FAR *GetClientSite )(
+ IOleObject __RPC_FAR * This,
+ /* [out] */ IOleClientSite __RPC_FAR *__RPC_FAR *ppClientSite);
+
+ HRESULT ( __stdcall __RPC_FAR *SetHostNames )(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ LPCOLESTR szContainerApp,
+ /* [unique][in] */ LPCOLESTR szContainerObj);
+
+ HRESULT ( __stdcall __RPC_FAR *Close )(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwSaveOption);
+
+ HRESULT ( __stdcall __RPC_FAR *SetMoniker )(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwWhichMoniker,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmk);
+
+ HRESULT ( __stdcall __RPC_FAR *GetMoniker )(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwAssign,
+ /* [in] */ DWORD dwWhichMoniker,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk);
+
+ HRESULT ( __stdcall __RPC_FAR *InitFromData )(
+ IOleObject __RPC_FAR * This,
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObject,
+ /* [in] */ BOOL fCreation,
+ /* [in] */ DWORD dwReserved);
+
+ HRESULT ( __stdcall __RPC_FAR *GetClipboardData )(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwReserved,
+ /* [out] */ IDataObject __RPC_FAR *__RPC_FAR *ppDataObject);
+
+ HRESULT ( __stdcall __RPC_FAR *DoVerb )(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ LONG iVerb,
+ /* [unique][in] */ LPMSG lpmsg,
+ /* [unique][in] */ IOleClientSite __RPC_FAR *pActiveSite,
+ /* [in] */ LONG lindex,
+ /* [in] */ HWND hwndParent,
+ /* [unique][in] */ LPCRECT lprcPosRect);
+
+ HRESULT ( __stdcall __RPC_FAR *EnumVerbs )(
+ IOleObject __RPC_FAR * This,
+ /* [out] */ IEnumOLEVERB __RPC_FAR *__RPC_FAR *ppEnumOleVerb);
+
+ HRESULT ( __stdcall __RPC_FAR *Update )(
+ IOleObject __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *IsUpToDate )(
+ IOleObject __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetUserClassID )(
+ IOleObject __RPC_FAR * This,
+ /* [out] */ CLSID __RPC_FAR *pClsid);
+
+ HRESULT ( __stdcall __RPC_FAR *GetUserType )(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwFormOfType,
+ /* [out] */ LPOLESTR __RPC_FAR *pszUserType);
+
+ HRESULT ( __stdcall __RPC_FAR *SetExtent )(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ SIZEL __RPC_FAR *psizel);
+
+ HRESULT ( __stdcall __RPC_FAR *GetExtent )(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [out] */ SIZEL __RPC_FAR *psizel);
+
+ HRESULT ( __stdcall __RPC_FAR *Advise )(
+ IOleObject __RPC_FAR * This,
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection);
+
+ HRESULT ( __stdcall __RPC_FAR *Unadvise )(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwConnection);
+
+ HRESULT ( __stdcall __RPC_FAR *EnumAdvise )(
+ IOleObject __RPC_FAR * This,
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise);
+
+ HRESULT ( __stdcall __RPC_FAR *GetMiscStatus )(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwAspect,
+ /* [out] */ DWORD __RPC_FAR *pdwStatus);
+
+ HRESULT ( __stdcall __RPC_FAR *SetColorScheme )(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ LOGPALETTE __RPC_FAR *pLogpal);
+
+ } IOleObjectVtbl;
+
+ interface IOleObject
+ {
+ CONST_VTBL struct IOleObjectVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleObject_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleObject_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleObject_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleObject_SetClientSite(This,pClientSite) \
+ (This)->lpVtbl -> SetClientSite(This,pClientSite)
+
+#define IOleObject_GetClientSite(This,ppClientSite) \
+ (This)->lpVtbl -> GetClientSite(This,ppClientSite)
+
+#define IOleObject_SetHostNames(This,szContainerApp,szContainerObj) \
+ (This)->lpVtbl -> SetHostNames(This,szContainerApp,szContainerObj)
+
+#define IOleObject_Close(This,dwSaveOption) \
+ (This)->lpVtbl -> Close(This,dwSaveOption)
+
+#define IOleObject_SetMoniker(This,dwWhichMoniker,pmk) \
+ (This)->lpVtbl -> SetMoniker(This,dwWhichMoniker,pmk)
+
+#define IOleObject_GetMoniker(This,dwAssign,dwWhichMoniker,ppmk) \
+ (This)->lpVtbl -> GetMoniker(This,dwAssign,dwWhichMoniker,ppmk)
+
+#define IOleObject_InitFromData(This,pDataObject,fCreation,dwReserved) \
+ (This)->lpVtbl -> InitFromData(This,pDataObject,fCreation,dwReserved)
+
+#define IOleObject_GetClipboardData(This,dwReserved,ppDataObject) \
+ (This)->lpVtbl -> GetClipboardData(This,dwReserved,ppDataObject)
+
+#define IOleObject_DoVerb(This,iVerb,lpmsg,pActiveSite,lindex,hwndParent,lprcPosRect) \
+ (This)->lpVtbl -> DoVerb(This,iVerb,lpmsg,pActiveSite,lindex,hwndParent,lprcPosRect)
+
+#define IOleObject_EnumVerbs(This,ppEnumOleVerb) \
+ (This)->lpVtbl -> EnumVerbs(This,ppEnumOleVerb)
+
+#define IOleObject_Update(This) \
+ (This)->lpVtbl -> Update(This)
+
+#define IOleObject_IsUpToDate(This) \
+ (This)->lpVtbl -> IsUpToDate(This)
+
+#define IOleObject_GetUserClassID(This,pClsid) \
+ (This)->lpVtbl -> GetUserClassID(This,pClsid)
+
+#define IOleObject_GetUserType(This,dwFormOfType,pszUserType) \
+ (This)->lpVtbl -> GetUserType(This,dwFormOfType,pszUserType)
+
+#define IOleObject_SetExtent(This,dwDrawAspect,psizel) \
+ (This)->lpVtbl -> SetExtent(This,dwDrawAspect,psizel)
+
+#define IOleObject_GetExtent(This,dwDrawAspect,psizel) \
+ (This)->lpVtbl -> GetExtent(This,dwDrawAspect,psizel)
+
+#define IOleObject_Advise(This,pAdvSink,pdwConnection) \
+ (This)->lpVtbl -> Advise(This,pAdvSink,pdwConnection)
+
+#define IOleObject_Unadvise(This,dwConnection) \
+ (This)->lpVtbl -> Unadvise(This,dwConnection)
+
+#define IOleObject_EnumAdvise(This,ppenumAdvise) \
+ (This)->lpVtbl -> EnumAdvise(This,ppenumAdvise)
+
+#define IOleObject_GetMiscStatus(This,dwAspect,pdwStatus) \
+ (This)->lpVtbl -> GetMiscStatus(This,dwAspect,pdwStatus)
+
+#define IOleObject_SetColorScheme(This,pLogpal) \
+ (This)->lpVtbl -> SetColorScheme(This,pLogpal)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IOleObject_SetClientSite_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [unique][in] */ IOleClientSite __RPC_FAR *pClientSite);
+
+
+void __RPC_STUB IOleObject_SetClientSite_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_GetClientSite_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [out] */ IOleClientSite __RPC_FAR *__RPC_FAR *ppClientSite);
+
+
+void __RPC_STUB IOleObject_GetClientSite_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_SetHostNames_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ LPCOLESTR szContainerApp,
+ /* [unique][in] */ LPCOLESTR szContainerObj);
+
+
+void __RPC_STUB IOleObject_SetHostNames_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_Close_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwSaveOption);
+
+
+void __RPC_STUB IOleObject_Close_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_SetMoniker_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwWhichMoniker,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmk);
+
+
+void __RPC_STUB IOleObject_SetMoniker_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_GetMoniker_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwAssign,
+ /* [in] */ DWORD dwWhichMoniker,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk);
+
+
+void __RPC_STUB IOleObject_GetMoniker_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_InitFromData_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObject,
+ /* [in] */ BOOL fCreation,
+ /* [in] */ DWORD dwReserved);
+
+
+void __RPC_STUB IOleObject_InitFromData_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_GetClipboardData_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwReserved,
+ /* [out] */ IDataObject __RPC_FAR *__RPC_FAR *ppDataObject);
+
+
+void __RPC_STUB IOleObject_GetClipboardData_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_DoVerb_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ LONG iVerb,
+ /* [unique][in] */ LPMSG lpmsg,
+ /* [unique][in] */ IOleClientSite __RPC_FAR *pActiveSite,
+ /* [in] */ LONG lindex,
+ /* [in] */ HWND hwndParent,
+ /* [unique][in] */ LPCRECT lprcPosRect);
+
+
+void __RPC_STUB IOleObject_DoVerb_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_EnumVerbs_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [out] */ IEnumOLEVERB __RPC_FAR *__RPC_FAR *ppEnumOleVerb);
+
+
+void __RPC_STUB IOleObject_EnumVerbs_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_Update_Proxy(
+ IOleObject __RPC_FAR * This);
+
+
+void __RPC_STUB IOleObject_Update_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_IsUpToDate_Proxy(
+ IOleObject __RPC_FAR * This);
+
+
+void __RPC_STUB IOleObject_IsUpToDate_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_GetUserClassID_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [out] */ CLSID __RPC_FAR *pClsid);
+
+
+void __RPC_STUB IOleObject_GetUserClassID_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_GetUserType_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwFormOfType,
+ /* [out] */ LPOLESTR __RPC_FAR *pszUserType);
+
+
+void __RPC_STUB IOleObject_GetUserType_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_SetExtent_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ SIZEL __RPC_FAR *psizel);
+
+
+void __RPC_STUB IOleObject_SetExtent_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_GetExtent_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [out] */ SIZEL __RPC_FAR *psizel);
+
+
+void __RPC_STUB IOleObject_GetExtent_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_Advise_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink,
+ /* [out] */ DWORD __RPC_FAR *pdwConnection);
+
+
+void __RPC_STUB IOleObject_Advise_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_Unadvise_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwConnection);
+
+
+void __RPC_STUB IOleObject_Unadvise_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_EnumAdvise_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [out] */ IEnumSTATDATA __RPC_FAR *__RPC_FAR *ppenumAdvise);
+
+
+void __RPC_STUB IOleObject_EnumAdvise_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_GetMiscStatus_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ DWORD dwAspect,
+ /* [out] */ DWORD __RPC_FAR *pdwStatus);
+
+
+void __RPC_STUB IOleObject_GetMiscStatus_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleObject_SetColorScheme_Proxy(
+ IOleObject __RPC_FAR * This,
+ /* [in] */ LOGPALETTE __RPC_FAR *pLogpal);
+
+
+void __RPC_STUB IOleObject_SetColorScheme_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleObject_INTERFACE_DEFINED__ */
+
+
+#ifndef __IOLETypes_INTERFACE_DEFINED__
+#define __IOLETypes_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOLETypes
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [auto_handle][uuid] */
+
+
+ /* size is 2 */
+typedef
+enum tagOLERENDER
+ { OLERENDER_NONE = 0,
+ OLERENDER_DRAW = 1,
+ OLERENDER_FORMAT = 2,
+ OLERENDER_ASIS = 3
+ } OLERENDER;
+
+ /* size is 4 */
+typedef OLERENDER __RPC_FAR *LPOLERENDER;
+
+ /* size is 52 */
+typedef struct tagOBJECTDESCRIPTOR
+ {
+ ULONG cbSize;
+ CLSID clsid;
+ DWORD dwDrawAspect;
+ SIZEL sizel;
+ POINTL pointl;
+ DWORD dwStatus;
+ DWORD dwFullUserTypeName;
+ DWORD dwSrcOfCopy;
+ } OBJECTDESCRIPTOR;
+
+ /* size is 4 */
+typedef struct tagOBJECTDESCRIPTOR __RPC_FAR *POBJECTDESCRIPTOR;
+
+ /* size is 4 */
+typedef struct tagOBJECTDESCRIPTOR __RPC_FAR *LPOBJECTDESCRIPTOR;
+
+ /* size is 52 */
+typedef struct tagOBJECTDESCRIPTOR LINKSRCDESCRIPTOR;
+
+ /* size is 4 */
+typedef struct tagOBJECTDESCRIPTOR __RPC_FAR *PLINKSRCDESCRIPTOR;
+
+ /* size is 4 */
+typedef struct tagOBJECTDESCRIPTOR __RPC_FAR *LPLINKSRCDESCRIPTOR;
+
+
+
+#ifndef NOPROXYSTUB
+extern RPC_IF_HANDLE IOLETypes_v0_0_c_ifspec;
+extern RPC_IF_HANDLE IOLETypes_v0_0_s_ifspec;
+#endif
+
+#endif /* __IOLETypes_INTERFACE_DEFINED__ */
+
+#ifndef __IOleWindow_INTERFACE_DEFINED__
+#define __IOleWindow_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleWindow
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IOleWindow __RPC_FAR *LPOLEWINDOW;
+
+
+EXTERN_C const IID IID_IOleWindow;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleWindow : public IUnknown
+ {
+ public:
+ virtual /* [input_sync] */ HRESULT __stdcall GetWindow(
+ /* [out] */ HWND __RPC_FAR *phwnd) = 0;
+
+ virtual HRESULT __stdcall ContextSensitiveHelp(
+ /* [in] */ BOOL fEnterMode) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleWindowVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleWindow __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleWindow __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleWindow __RPC_FAR * This);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *GetWindow )(
+ IOleWindow __RPC_FAR * This,
+ /* [out] */ HWND __RPC_FAR *phwnd);
+
+ HRESULT ( __stdcall __RPC_FAR *ContextSensitiveHelp )(
+ IOleWindow __RPC_FAR * This,
+ /* [in] */ BOOL fEnterMode);
+
+ } IOleWindowVtbl;
+
+ interface IOleWindow
+ {
+ CONST_VTBL struct IOleWindowVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleWindow_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleWindow_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleWindow_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleWindow_GetWindow(This,phwnd) \
+ (This)->lpVtbl -> GetWindow(This,phwnd)
+
+#define IOleWindow_ContextSensitiveHelp(This,fEnterMode) \
+ (This)->lpVtbl -> ContextSensitiveHelp(This,fEnterMode)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [input_sync] */ HRESULT __stdcall IOleWindow_GetWindow_Proxy(
+ IOleWindow __RPC_FAR * This,
+ /* [out] */ HWND __RPC_FAR *phwnd);
+
+
+void __RPC_STUB IOleWindow_GetWindow_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleWindow_ContextSensitiveHelp_Proxy(
+ IOleWindow __RPC_FAR * This,
+ /* [in] */ BOOL fEnterMode);
+
+
+void __RPC_STUB IOleWindow_ContextSensitiveHelp_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleWindow_INTERFACE_DEFINED__ */
+
+
+#ifndef __IOleLink_INTERFACE_DEFINED__
+#define __IOleLink_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleLink
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IOleLink __RPC_FAR *LPOLELINK;
+
+ /* size is 2 */
+typedef
+enum tagOLEUPDATE
+ { OLEUPDATE_ALWAYS = 1,
+ OLEUPDATE_ONCALL = 3
+ } OLEUPDATE;
+
+ /* size is 4 */
+typedef OLEUPDATE __RPC_FAR *LPOLEUPDATE;
+
+ /* size is 4 */
+typedef OLEUPDATE __RPC_FAR *POLEUPDATE;
+
+ /* size is 2 */
+typedef
+enum tagOLELINKBIND
+ { OLELINKBIND_EVENIFCLASSDIFF = 1
+ } OLELINKBIND;
+
+
+EXTERN_C const IID IID_IOleLink;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleLink : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall SetUpdateOptions(
+ /* [in] */ DWORD dwUpdateOpt) = 0;
+
+ virtual HRESULT __stdcall GetUpdateOptions(
+ /* [out] */ DWORD __RPC_FAR *pdwUpdateOpt) = 0;
+
+ virtual HRESULT __stdcall SetSourceMoniker(
+ /* [unique][in] */ IMoniker __RPC_FAR *pmk,
+ /* [in] */ REFCLSID rclsid) = 0;
+
+ virtual HRESULT __stdcall GetSourceMoniker(
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk) = 0;
+
+ virtual HRESULT __stdcall SetSourceDisplayName(
+ /* [in] */ LPCOLESTR pszStatusText) = 0;
+
+ virtual HRESULT __stdcall GetSourceDisplayName(
+ /* [out] */ LPOLESTR __RPC_FAR *ppszDisplayName) = 0;
+
+ virtual HRESULT __stdcall BindToSource(
+ /* [in] */ DWORD bindflags,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc) = 0;
+
+ virtual HRESULT __stdcall BindIfRunning( void) = 0;
+
+ virtual HRESULT __stdcall GetBoundSource(
+ /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunk) = 0;
+
+ virtual HRESULT __stdcall UnbindSource( void) = 0;
+
+ virtual HRESULT __stdcall Update(
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleLinkVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleLink __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleLink __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleLink __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *SetUpdateOptions )(
+ IOleLink __RPC_FAR * This,
+ /* [in] */ DWORD dwUpdateOpt);
+
+ HRESULT ( __stdcall __RPC_FAR *GetUpdateOptions )(
+ IOleLink __RPC_FAR * This,
+ /* [out] */ DWORD __RPC_FAR *pdwUpdateOpt);
+
+ HRESULT ( __stdcall __RPC_FAR *SetSourceMoniker )(
+ IOleLink __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmk,
+ /* [in] */ REFCLSID rclsid);
+
+ HRESULT ( __stdcall __RPC_FAR *GetSourceMoniker )(
+ IOleLink __RPC_FAR * This,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk);
+
+ HRESULT ( __stdcall __RPC_FAR *SetSourceDisplayName )(
+ IOleLink __RPC_FAR * This,
+ /* [in] */ LPCOLESTR pszStatusText);
+
+ HRESULT ( __stdcall __RPC_FAR *GetSourceDisplayName )(
+ IOleLink __RPC_FAR * This,
+ /* [out] */ LPOLESTR __RPC_FAR *ppszDisplayName);
+
+ HRESULT ( __stdcall __RPC_FAR *BindToSource )(
+ IOleLink __RPC_FAR * This,
+ /* [in] */ DWORD bindflags,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc);
+
+ HRESULT ( __stdcall __RPC_FAR *BindIfRunning )(
+ IOleLink __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetBoundSource )(
+ IOleLink __RPC_FAR * This,
+ /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunk);
+
+ HRESULT ( __stdcall __RPC_FAR *UnbindSource )(
+ IOleLink __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Update )(
+ IOleLink __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc);
+
+ } IOleLinkVtbl;
+
+ interface IOleLink
+ {
+ CONST_VTBL struct IOleLinkVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleLink_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleLink_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleLink_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleLink_SetUpdateOptions(This,dwUpdateOpt) \
+ (This)->lpVtbl -> SetUpdateOptions(This,dwUpdateOpt)
+
+#define IOleLink_GetUpdateOptions(This,pdwUpdateOpt) \
+ (This)->lpVtbl -> GetUpdateOptions(This,pdwUpdateOpt)
+
+#define IOleLink_SetSourceMoniker(This,pmk,rclsid) \
+ (This)->lpVtbl -> SetSourceMoniker(This,pmk,rclsid)
+
+#define IOleLink_GetSourceMoniker(This,ppmk) \
+ (This)->lpVtbl -> GetSourceMoniker(This,ppmk)
+
+#define IOleLink_SetSourceDisplayName(This,pszStatusText) \
+ (This)->lpVtbl -> SetSourceDisplayName(This,pszStatusText)
+
+#define IOleLink_GetSourceDisplayName(This,ppszDisplayName) \
+ (This)->lpVtbl -> GetSourceDisplayName(This,ppszDisplayName)
+
+#define IOleLink_BindToSource(This,bindflags,pbc) \
+ (This)->lpVtbl -> BindToSource(This,bindflags,pbc)
+
+#define IOleLink_BindIfRunning(This) \
+ (This)->lpVtbl -> BindIfRunning(This)
+
+#define IOleLink_GetBoundSource(This,ppunk) \
+ (This)->lpVtbl -> GetBoundSource(This,ppunk)
+
+#define IOleLink_UnbindSource(This) \
+ (This)->lpVtbl -> UnbindSource(This)
+
+#define IOleLink_Update(This,pbc) \
+ (This)->lpVtbl -> Update(This,pbc)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IOleLink_SetUpdateOptions_Proxy(
+ IOleLink __RPC_FAR * This,
+ /* [in] */ DWORD dwUpdateOpt);
+
+
+void __RPC_STUB IOleLink_SetUpdateOptions_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleLink_GetUpdateOptions_Proxy(
+ IOleLink __RPC_FAR * This,
+ /* [out] */ DWORD __RPC_FAR *pdwUpdateOpt);
+
+
+void __RPC_STUB IOleLink_GetUpdateOptions_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleLink_SetSourceMoniker_Proxy(
+ IOleLink __RPC_FAR * This,
+ /* [unique][in] */ IMoniker __RPC_FAR *pmk,
+ /* [in] */ REFCLSID rclsid);
+
+
+void __RPC_STUB IOleLink_SetSourceMoniker_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleLink_GetSourceMoniker_Proxy(
+ IOleLink __RPC_FAR * This,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk);
+
+
+void __RPC_STUB IOleLink_GetSourceMoniker_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleLink_SetSourceDisplayName_Proxy(
+ IOleLink __RPC_FAR * This,
+ /* [in] */ LPCOLESTR pszStatusText);
+
+
+void __RPC_STUB IOleLink_SetSourceDisplayName_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleLink_GetSourceDisplayName_Proxy(
+ IOleLink __RPC_FAR * This,
+ /* [out] */ LPOLESTR __RPC_FAR *ppszDisplayName);
+
+
+void __RPC_STUB IOleLink_GetSourceDisplayName_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleLink_BindToSource_Proxy(
+ IOleLink __RPC_FAR * This,
+ /* [in] */ DWORD bindflags,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc);
+
+
+void __RPC_STUB IOleLink_BindToSource_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleLink_BindIfRunning_Proxy(
+ IOleLink __RPC_FAR * This);
+
+
+void __RPC_STUB IOleLink_BindIfRunning_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleLink_GetBoundSource_Proxy(
+ IOleLink __RPC_FAR * This,
+ /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppunk);
+
+
+void __RPC_STUB IOleLink_GetBoundSource_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleLink_UnbindSource_Proxy(
+ IOleLink __RPC_FAR * This);
+
+
+void __RPC_STUB IOleLink_UnbindSource_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleLink_Update_Proxy(
+ IOleLink __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc);
+
+
+void __RPC_STUB IOleLink_Update_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleLink_INTERFACE_DEFINED__ */
+
+
+#ifndef __IOleItemContainer_INTERFACE_DEFINED__
+#define __IOleItemContainer_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleItemContainer
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IOleItemContainer __RPC_FAR *LPOLEITEMCONTAINER;
+
+ /* size is 2 */
+typedef
+enum tagBINDSPEED
+ { BINDSPEED_INDEFINITE = 1,
+ BINDSPEED_MODERATE = 2,
+ BINDSPEED_IMMEDIATE = 3
+ } BINDSPEED;
+
+ /* size is 2 */
+typedef /* [v1_enum] */
+enum tagOLECONTF
+ { OLECONTF_EMBEDDINGS = 1,
+ OLECONTF_LINKS = 2,
+ OLECONTF_OTHERS = 4,
+ OLECONTF_ONLYUSER = 8,
+ OLECONTF_ONLYIFRUNNING = 16
+ } OLECONTF;
+
+
+EXTERN_C const IID IID_IOleItemContainer;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleItemContainer : public IOleContainer
+ {
+ public:
+ virtual /* [local] */ HRESULT __stdcall GetObject(
+ /* [in] */ LPOLESTR pszItem,
+ /* [in] */ DWORD dwSpeedNeeded,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject) = 0;
+
+ virtual /* [local] */ HRESULT __stdcall GetObjectStorage(
+ /* [in] */ LPOLESTR pszItem,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvStorage) = 0;
+
+ virtual HRESULT __stdcall IsRunning(
+ /* [in] */ LPOLESTR pszItem) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleItemContainerVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleItemContainer __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleItemContainer __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleItemContainer __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *ParseDisplayName )(
+ IOleItemContainer __RPC_FAR * This,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ LPOLESTR pszDisplayName,
+ /* [out] */ ULONG __RPC_FAR *pchEaten,
+ /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut);
+
+ HRESULT ( __stdcall __RPC_FAR *EnumObjects )(
+ IOleItemContainer __RPC_FAR * This,
+ /* [in] */ DWORD grfFlags,
+ /* [out] */ IEnumUnknown __RPC_FAR *__RPC_FAR *ppenum);
+
+ HRESULT ( __stdcall __RPC_FAR *LockContainer )(
+ IOleItemContainer __RPC_FAR * This,
+ /* [in] */ BOOL fLock);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *GetObject )(
+ IOleItemContainer __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszItem,
+ /* [in] */ DWORD dwSpeedNeeded,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *GetObjectStorage )(
+ IOleItemContainer __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszItem,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvStorage);
+
+ HRESULT ( __stdcall __RPC_FAR *IsRunning )(
+ IOleItemContainer __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszItem);
+
+ } IOleItemContainerVtbl;
+
+ interface IOleItemContainer
+ {
+ CONST_VTBL struct IOleItemContainerVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleItemContainer_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleItemContainer_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleItemContainer_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleItemContainer_ParseDisplayName(This,pbc,pszDisplayName,pchEaten,ppmkOut) \
+ (This)->lpVtbl -> ParseDisplayName(This,pbc,pszDisplayName,pchEaten,ppmkOut)
+
+
+#define IOleItemContainer_EnumObjects(This,grfFlags,ppenum) \
+ (This)->lpVtbl -> EnumObjects(This,grfFlags,ppenum)
+
+#define IOleItemContainer_LockContainer(This,fLock) \
+ (This)->lpVtbl -> LockContainer(This,fLock)
+
+
+#define IOleItemContainer_GetObject(This,pszItem,dwSpeedNeeded,pbc,riid,ppvObject) \
+ (This)->lpVtbl -> GetObject(This,pszItem,dwSpeedNeeded,pbc,riid,ppvObject)
+
+#define IOleItemContainer_GetObjectStorage(This,pszItem,pbc,riid,ppvStorage) \
+ (This)->lpVtbl -> GetObjectStorage(This,pszItem,pbc,riid,ppvStorage)
+
+#define IOleItemContainer_IsRunning(This,pszItem) \
+ (This)->lpVtbl -> IsRunning(This,pszItem)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [call_as] */ HRESULT __stdcall IOleItemContainer_RemoteGetObject_Proxy(
+ IOleItemContainer __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszItem,
+ /* [in] */ DWORD dwSpeedNeeded,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppvObject);
+
+
+void __RPC_STUB IOleItemContainer_RemoteGetObject_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [call_as] */ HRESULT __stdcall IOleItemContainer_RemoteGetObjectStorage_Proxy(
+ IOleItemContainer __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszItem,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppvStorage);
+
+
+void __RPC_STUB IOleItemContainer_RemoteGetObjectStorage_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleItemContainer_IsRunning_Proxy(
+ IOleItemContainer __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszItem);
+
+
+void __RPC_STUB IOleItemContainer_IsRunning_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleItemContainer_INTERFACE_DEFINED__ */
+
+
+#ifndef __IOleInPlaceUIWindow_INTERFACE_DEFINED__
+#define __IOleInPlaceUIWindow_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleInPlaceUIWindow
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IOleInPlaceUIWindow __RPC_FAR *LPOLEINPLACEUIWINDOW;
+
+ /* size is 16 */
+typedef RECT BORDERWIDTHS;
+
+ /* size is 4 */
+typedef LPRECT LPBORDERWIDTHS;
+
+ /* size is 4 */
+typedef LPCRECT LPCBORDERWIDTHS;
+
+
+EXTERN_C const IID IID_IOleInPlaceUIWindow;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleInPlaceUIWindow : public IOleWindow
+ {
+ public:
+ virtual /* [input_sync] */ HRESULT __stdcall GetBorder(
+ /* [out] */ LPRECT lprectBorder) = 0;
+
+ virtual /* [input_sync] */ HRESULT __stdcall RequestBorderSpace(
+ /* [unique][in] */ LPCBORDERWIDTHS pborderwidths) = 0;
+
+ virtual /* [input_sync] */ HRESULT __stdcall SetBorderSpace(
+ /* [unique][in] */ LPCBORDERWIDTHS pborderwidths) = 0;
+
+ virtual HRESULT __stdcall SetActiveObject(
+ /* [unique][in] */ IOleInPlaceActiveObject __RPC_FAR *pActiveObject,
+ /* [unique][string][in] */ LPCOLESTR pszObjName) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleInPlaceUIWindowVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleInPlaceUIWindow __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleInPlaceUIWindow __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleInPlaceUIWindow __RPC_FAR * This);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *GetWindow )(
+ IOleInPlaceUIWindow __RPC_FAR * This,
+ /* [out] */ HWND __RPC_FAR *phwnd);
+
+ HRESULT ( __stdcall __RPC_FAR *ContextSensitiveHelp )(
+ IOleInPlaceUIWindow __RPC_FAR * This,
+ /* [in] */ BOOL fEnterMode);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *GetBorder )(
+ IOleInPlaceUIWindow __RPC_FAR * This,
+ /* [out] */ LPRECT lprectBorder);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *RequestBorderSpace )(
+ IOleInPlaceUIWindow __RPC_FAR * This,
+ /* [unique][in] */ LPCBORDERWIDTHS pborderwidths);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *SetBorderSpace )(
+ IOleInPlaceUIWindow __RPC_FAR * This,
+ /* [unique][in] */ LPCBORDERWIDTHS pborderwidths);
+
+ HRESULT ( __stdcall __RPC_FAR *SetActiveObject )(
+ IOleInPlaceUIWindow __RPC_FAR * This,
+ /* [unique][in] */ IOleInPlaceActiveObject __RPC_FAR *pActiveObject,
+ /* [unique][string][in] */ LPCOLESTR pszObjName);
+
+ } IOleInPlaceUIWindowVtbl;
+
+ interface IOleInPlaceUIWindow
+ {
+ CONST_VTBL struct IOleInPlaceUIWindowVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleInPlaceUIWindow_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleInPlaceUIWindow_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleInPlaceUIWindow_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleInPlaceUIWindow_GetWindow(This,phwnd) \
+ (This)->lpVtbl -> GetWindow(This,phwnd)
+
+#define IOleInPlaceUIWindow_ContextSensitiveHelp(This,fEnterMode) \
+ (This)->lpVtbl -> ContextSensitiveHelp(This,fEnterMode)
+
+
+#define IOleInPlaceUIWindow_GetBorder(This,lprectBorder) \
+ (This)->lpVtbl -> GetBorder(This,lprectBorder)
+
+#define IOleInPlaceUIWindow_RequestBorderSpace(This,pborderwidths) \
+ (This)->lpVtbl -> RequestBorderSpace(This,pborderwidths)
+
+#define IOleInPlaceUIWindow_SetBorderSpace(This,pborderwidths) \
+ (This)->lpVtbl -> SetBorderSpace(This,pborderwidths)
+
+#define IOleInPlaceUIWindow_SetActiveObject(This,pActiveObject,pszObjName) \
+ (This)->lpVtbl -> SetActiveObject(This,pActiveObject,pszObjName)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [input_sync] */ HRESULT __stdcall IOleInPlaceUIWindow_GetBorder_Proxy(
+ IOleInPlaceUIWindow __RPC_FAR * This,
+ /* [out] */ LPRECT lprectBorder);
+
+
+void __RPC_STUB IOleInPlaceUIWindow_GetBorder_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [input_sync] */ HRESULT __stdcall IOleInPlaceUIWindow_RequestBorderSpace_Proxy(
+ IOleInPlaceUIWindow __RPC_FAR * This,
+ /* [unique][in] */ LPCBORDERWIDTHS pborderwidths);
+
+
+void __RPC_STUB IOleInPlaceUIWindow_RequestBorderSpace_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [input_sync] */ HRESULT __stdcall IOleInPlaceUIWindow_SetBorderSpace_Proxy(
+ IOleInPlaceUIWindow __RPC_FAR * This,
+ /* [unique][in] */ LPCBORDERWIDTHS pborderwidths);
+
+
+void __RPC_STUB IOleInPlaceUIWindow_SetBorderSpace_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceUIWindow_SetActiveObject_Proxy(
+ IOleInPlaceUIWindow __RPC_FAR * This,
+ /* [unique][in] */ IOleInPlaceActiveObject __RPC_FAR *pActiveObject,
+ /* [unique][string][in] */ LPCOLESTR pszObjName);
+
+
+void __RPC_STUB IOleInPlaceUIWindow_SetActiveObject_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleInPlaceUIWindow_INTERFACE_DEFINED__ */
+
+
+#ifndef __IOleInPlaceActiveObject_INTERFACE_DEFINED__
+#define __IOleInPlaceActiveObject_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleInPlaceActiveObject
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IOleInPlaceActiveObject __RPC_FAR *LPOLEINPLACEACTIVEOBJECT;
+
+
+EXTERN_C const IID IID_IOleInPlaceActiveObject;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleInPlaceActiveObject : public IOleWindow
+ {
+ public:
+ virtual /* [local] */ HRESULT __stdcall TranslateAccelerator(
+ /* [in] */ LPMSG lpmsg) = 0;
+
+ virtual /* [input_sync] */ HRESULT __stdcall OnFrameWindowActivate(
+ /* [in] */ BOOL fActivate) = 0;
+
+ virtual /* [input_sync] */ HRESULT __stdcall OnDocWindowActivate(
+ /* [in] */ BOOL fActivate) = 0;
+
+ virtual /* [local] */ HRESULT __stdcall ResizeBorder(
+ /* [in] */ LPCRECT prcBorder,
+ /* [unique][in] */ IOleInPlaceUIWindow __RPC_FAR *pUIWindow,
+ /* [in] */ BOOL fFrameWindow) = 0;
+
+ virtual HRESULT __stdcall EnableModeless(
+ /* [in] */ BOOL fEnable) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleInPlaceActiveObjectVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleInPlaceActiveObject __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleInPlaceActiveObject __RPC_FAR * This);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *GetWindow )(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [out] */ HWND __RPC_FAR *phwnd);
+
+ HRESULT ( __stdcall __RPC_FAR *ContextSensitiveHelp )(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [in] */ BOOL fEnterMode);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *TranslateAccelerator )(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [in] */ LPMSG lpmsg);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *OnFrameWindowActivate )(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [in] */ BOOL fActivate);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *OnDocWindowActivate )(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [in] */ BOOL fActivate);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *ResizeBorder )(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [in] */ LPCRECT prcBorder,
+ /* [unique][in] */ IOleInPlaceUIWindow __RPC_FAR *pUIWindow,
+ /* [in] */ BOOL fFrameWindow);
+
+ HRESULT ( __stdcall __RPC_FAR *EnableModeless )(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [in] */ BOOL fEnable);
+
+ } IOleInPlaceActiveObjectVtbl;
+
+ interface IOleInPlaceActiveObject
+ {
+ CONST_VTBL struct IOleInPlaceActiveObjectVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleInPlaceActiveObject_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleInPlaceActiveObject_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleInPlaceActiveObject_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleInPlaceActiveObject_GetWindow(This,phwnd) \
+ (This)->lpVtbl -> GetWindow(This,phwnd)
+
+#define IOleInPlaceActiveObject_ContextSensitiveHelp(This,fEnterMode) \
+ (This)->lpVtbl -> ContextSensitiveHelp(This,fEnterMode)
+
+
+#define IOleInPlaceActiveObject_TranslateAccelerator(This,lpmsg) \
+ (This)->lpVtbl -> TranslateAccelerator(This,lpmsg)
+
+#define IOleInPlaceActiveObject_OnFrameWindowActivate(This,fActivate) \
+ (This)->lpVtbl -> OnFrameWindowActivate(This,fActivate)
+
+#define IOleInPlaceActiveObject_OnDocWindowActivate(This,fActivate) \
+ (This)->lpVtbl -> OnDocWindowActivate(This,fActivate)
+
+#define IOleInPlaceActiveObject_ResizeBorder(This,prcBorder,pUIWindow,fFrameWindow) \
+ (This)->lpVtbl -> ResizeBorder(This,prcBorder,pUIWindow,fFrameWindow)
+
+#define IOleInPlaceActiveObject_EnableModeless(This,fEnable) \
+ (This)->lpVtbl -> EnableModeless(This,fEnable)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [call_as] */ HRESULT __stdcall IOleInPlaceActiveObject_RemoteTranslateAccelerator_Proxy(
+ IOleInPlaceActiveObject __RPC_FAR * This);
+
+
+void __RPC_STUB IOleInPlaceActiveObject_RemoteTranslateAccelerator_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [input_sync] */ HRESULT __stdcall IOleInPlaceActiveObject_OnFrameWindowActivate_Proxy(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [in] */ BOOL fActivate);
+
+
+void __RPC_STUB IOleInPlaceActiveObject_OnFrameWindowActivate_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [input_sync] */ HRESULT __stdcall IOleInPlaceActiveObject_OnDocWindowActivate_Proxy(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [in] */ BOOL fActivate);
+
+
+void __RPC_STUB IOleInPlaceActiveObject_OnDocWindowActivate_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [input_sync][call_as] */ HRESULT __stdcall IOleInPlaceActiveObject_RemoteResizeBorder_Proxy(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [in] */ LPCRECT prcBorder,
+ /* [in] */ REFIID riid,
+ /* [iid_is][unique][in] */ IOleInPlaceUIWindow __RPC_FAR *pUIWindow,
+ /* [in] */ BOOL fFrameWindow);
+
+
+void __RPC_STUB IOleInPlaceActiveObject_RemoteResizeBorder_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceActiveObject_EnableModeless_Proxy(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [in] */ BOOL fEnable);
+
+
+void __RPC_STUB IOleInPlaceActiveObject_EnableModeless_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleInPlaceActiveObject_INTERFACE_DEFINED__ */
+
+
+#ifndef __IOleInPlaceFrame_INTERFACE_DEFINED__
+#define __IOleInPlaceFrame_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleInPlaceFrame
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IOleInPlaceFrame __RPC_FAR *LPOLEINPLACEFRAME;
+
+ /* size is 20 */
+typedef struct tagOIFI
+ {
+ UINT cb;
+ BOOL fMDIApp;
+ HWND hwndFrame;
+ HACCEL haccel;
+ UINT cAccelEntries;
+ } OLEINPLACEFRAMEINFO;
+
+ /* size is 4 */
+typedef struct tagOIFI __RPC_FAR *LPOLEINPLACEFRAMEINFO;
+
+ /* size is 24 */
+typedef struct tagOleMenuGroupWidths
+ {
+ LONG width[ 6 ];
+ } OLEMENUGROUPWIDTHS;
+
+ /* size is 4 */
+typedef struct tagOleMenuGroupWidths __RPC_FAR *LPOLEMENUGROUPWIDTHS;
+
+ /* size is 4 */
+typedef HGLOBAL HOLEMENU;
+
+
+EXTERN_C const IID IID_IOleInPlaceFrame;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleInPlaceFrame : public IOleInPlaceUIWindow
+ {
+ public:
+ virtual HRESULT __stdcall InsertMenus(
+ /* [in] */ HMENU hmenuShared,
+ /* [out][in] */ LPOLEMENUGROUPWIDTHS lpMenuWidths) = 0;
+
+ virtual /* [input_sync] */ HRESULT __stdcall SetMenu(
+ /* [in] */ HMENU hmenuShared,
+ /* [in] */ HOLEMENU holemenu,
+ /* [in] */ HWND hwndActiveObject) = 0;
+
+ virtual HRESULT __stdcall RemoveMenus(
+ /* [in] */ HMENU hmenuShared) = 0;
+
+ virtual /* [input_sync] */ HRESULT __stdcall SetStatusText(
+ /* [in] */ LPCOLESTR pszStatusText) = 0;
+
+ virtual HRESULT __stdcall EnableModeless(
+ /* [in] */ BOOL fEnable) = 0;
+
+ virtual HRESULT __stdcall TranslateAccelerator(
+ /* [in] */ LPMSG lpmsg,
+ /* [in] */ WORD wID) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleInPlaceFrameVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleInPlaceFrame __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleInPlaceFrame __RPC_FAR * This);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *GetWindow )(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [out] */ HWND __RPC_FAR *phwnd);
+
+ HRESULT ( __stdcall __RPC_FAR *ContextSensitiveHelp )(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [in] */ BOOL fEnterMode);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *GetBorder )(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [out] */ LPRECT lprectBorder);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *RequestBorderSpace )(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [unique][in] */ LPCBORDERWIDTHS pborderwidths);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *SetBorderSpace )(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [unique][in] */ LPCBORDERWIDTHS pborderwidths);
+
+ HRESULT ( __stdcall __RPC_FAR *SetActiveObject )(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [unique][in] */ IOleInPlaceActiveObject __RPC_FAR *pActiveObject,
+ /* [unique][string][in] */ LPCOLESTR pszObjName);
+
+ HRESULT ( __stdcall __RPC_FAR *InsertMenus )(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [in] */ HMENU hmenuShared,
+ /* [out][in] */ LPOLEMENUGROUPWIDTHS lpMenuWidths);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *SetMenu )(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [in] */ HMENU hmenuShared,
+ /* [in] */ HOLEMENU holemenu,
+ /* [in] */ HWND hwndActiveObject);
+
+ HRESULT ( __stdcall __RPC_FAR *RemoveMenus )(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [in] */ HMENU hmenuShared);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *SetStatusText )(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [in] */ LPCOLESTR pszStatusText);
+
+ HRESULT ( __stdcall __RPC_FAR *EnableModeless )(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [in] */ BOOL fEnable);
+
+ HRESULT ( __stdcall __RPC_FAR *TranslateAccelerator )(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [in] */ LPMSG lpmsg,
+ /* [in] */ WORD wID);
+
+ } IOleInPlaceFrameVtbl;
+
+ interface IOleInPlaceFrame
+ {
+ CONST_VTBL struct IOleInPlaceFrameVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleInPlaceFrame_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleInPlaceFrame_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleInPlaceFrame_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleInPlaceFrame_GetWindow(This,phwnd) \
+ (This)->lpVtbl -> GetWindow(This,phwnd)
+
+#define IOleInPlaceFrame_ContextSensitiveHelp(This,fEnterMode) \
+ (This)->lpVtbl -> ContextSensitiveHelp(This,fEnterMode)
+
+
+#define IOleInPlaceFrame_GetBorder(This,lprectBorder) \
+ (This)->lpVtbl -> GetBorder(This,lprectBorder)
+
+#define IOleInPlaceFrame_RequestBorderSpace(This,pborderwidths) \
+ (This)->lpVtbl -> RequestBorderSpace(This,pborderwidths)
+
+#define IOleInPlaceFrame_SetBorderSpace(This,pborderwidths) \
+ (This)->lpVtbl -> SetBorderSpace(This,pborderwidths)
+
+#define IOleInPlaceFrame_SetActiveObject(This,pActiveObject,pszObjName) \
+ (This)->lpVtbl -> SetActiveObject(This,pActiveObject,pszObjName)
+
+
+#define IOleInPlaceFrame_InsertMenus(This,hmenuShared,lpMenuWidths) \
+ (This)->lpVtbl -> InsertMenus(This,hmenuShared,lpMenuWidths)
+
+#define IOleInPlaceFrame_SetMenu(This,hmenuShared,holemenu,hwndActiveObject) \
+ (This)->lpVtbl -> SetMenu(This,hmenuShared,holemenu,hwndActiveObject)
+
+#define IOleInPlaceFrame_RemoveMenus(This,hmenuShared) \
+ (This)->lpVtbl -> RemoveMenus(This,hmenuShared)
+
+#define IOleInPlaceFrame_SetStatusText(This,pszStatusText) \
+ (This)->lpVtbl -> SetStatusText(This,pszStatusText)
+
+#define IOleInPlaceFrame_EnableModeless(This,fEnable) \
+ (This)->lpVtbl -> EnableModeless(This,fEnable)
+
+#define IOleInPlaceFrame_TranslateAccelerator(This,lpmsg,wID) \
+ (This)->lpVtbl -> TranslateAccelerator(This,lpmsg,wID)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IOleInPlaceFrame_InsertMenus_Proxy(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [in] */ HMENU hmenuShared,
+ /* [out][in] */ LPOLEMENUGROUPWIDTHS lpMenuWidths);
+
+
+void __RPC_STUB IOleInPlaceFrame_InsertMenus_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [input_sync] */ HRESULT __stdcall IOleInPlaceFrame_SetMenu_Proxy(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [in] */ HMENU hmenuShared,
+ /* [in] */ HOLEMENU holemenu,
+ /* [in] */ HWND hwndActiveObject);
+
+
+void __RPC_STUB IOleInPlaceFrame_SetMenu_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceFrame_RemoveMenus_Proxy(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [in] */ HMENU hmenuShared);
+
+
+void __RPC_STUB IOleInPlaceFrame_RemoveMenus_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [input_sync] */ HRESULT __stdcall IOleInPlaceFrame_SetStatusText_Proxy(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [in] */ LPCOLESTR pszStatusText);
+
+
+void __RPC_STUB IOleInPlaceFrame_SetStatusText_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceFrame_EnableModeless_Proxy(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [in] */ BOOL fEnable);
+
+
+void __RPC_STUB IOleInPlaceFrame_EnableModeless_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceFrame_TranslateAccelerator_Proxy(
+ IOleInPlaceFrame __RPC_FAR * This,
+ /* [in] */ LPMSG lpmsg,
+ /* [in] */ WORD wID);
+
+
+void __RPC_STUB IOleInPlaceFrame_TranslateAccelerator_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleInPlaceFrame_INTERFACE_DEFINED__ */
+
+
+#ifndef __IOleInPlaceObject_INTERFACE_DEFINED__
+#define __IOleInPlaceObject_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleInPlaceObject
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IOleInPlaceObject __RPC_FAR *LPOLEINPLACEOBJECT;
+
+
+EXTERN_C const IID IID_IOleInPlaceObject;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleInPlaceObject : public IOleWindow
+ {
+ public:
+ virtual HRESULT __stdcall InPlaceDeactivate( void) = 0;
+
+ virtual HRESULT __stdcall UIDeactivate( void) = 0;
+
+ virtual /* [input_sync] */ HRESULT __stdcall SetObjectRects(
+ /* [in] */ LPCRECT lprcPosRect,
+ /* [in] */ LPCRECT lprcClipRect) = 0;
+
+ virtual HRESULT __stdcall ReactivateAndUndo( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleInPlaceObjectVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleInPlaceObject __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleInPlaceObject __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleInPlaceObject __RPC_FAR * This);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *GetWindow )(
+ IOleInPlaceObject __RPC_FAR * This,
+ /* [out] */ HWND __RPC_FAR *phwnd);
+
+ HRESULT ( __stdcall __RPC_FAR *ContextSensitiveHelp )(
+ IOleInPlaceObject __RPC_FAR * This,
+ /* [in] */ BOOL fEnterMode);
+
+ HRESULT ( __stdcall __RPC_FAR *InPlaceDeactivate )(
+ IOleInPlaceObject __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *UIDeactivate )(
+ IOleInPlaceObject __RPC_FAR * This);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *SetObjectRects )(
+ IOleInPlaceObject __RPC_FAR * This,
+ /* [in] */ LPCRECT lprcPosRect,
+ /* [in] */ LPCRECT lprcClipRect);
+
+ HRESULT ( __stdcall __RPC_FAR *ReactivateAndUndo )(
+ IOleInPlaceObject __RPC_FAR * This);
+
+ } IOleInPlaceObjectVtbl;
+
+ interface IOleInPlaceObject
+ {
+ CONST_VTBL struct IOleInPlaceObjectVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleInPlaceObject_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleInPlaceObject_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleInPlaceObject_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleInPlaceObject_GetWindow(This,phwnd) \
+ (This)->lpVtbl -> GetWindow(This,phwnd)
+
+#define IOleInPlaceObject_ContextSensitiveHelp(This,fEnterMode) \
+ (This)->lpVtbl -> ContextSensitiveHelp(This,fEnterMode)
+
+
+#define IOleInPlaceObject_InPlaceDeactivate(This) \
+ (This)->lpVtbl -> InPlaceDeactivate(This)
+
+#define IOleInPlaceObject_UIDeactivate(This) \
+ (This)->lpVtbl -> UIDeactivate(This)
+
+#define IOleInPlaceObject_SetObjectRects(This,lprcPosRect,lprcClipRect) \
+ (This)->lpVtbl -> SetObjectRects(This,lprcPosRect,lprcClipRect)
+
+#define IOleInPlaceObject_ReactivateAndUndo(This) \
+ (This)->lpVtbl -> ReactivateAndUndo(This)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IOleInPlaceObject_InPlaceDeactivate_Proxy(
+ IOleInPlaceObject __RPC_FAR * This);
+
+
+void __RPC_STUB IOleInPlaceObject_InPlaceDeactivate_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceObject_UIDeactivate_Proxy(
+ IOleInPlaceObject __RPC_FAR * This);
+
+
+void __RPC_STUB IOleInPlaceObject_UIDeactivate_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+/* [input_sync] */ HRESULT __stdcall IOleInPlaceObject_SetObjectRects_Proxy(
+ IOleInPlaceObject __RPC_FAR * This,
+ /* [in] */ LPCRECT lprcPosRect,
+ /* [in] */ LPCRECT lprcClipRect);
+
+
+void __RPC_STUB IOleInPlaceObject_SetObjectRects_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceObject_ReactivateAndUndo_Proxy(
+ IOleInPlaceObject __RPC_FAR * This);
+
+
+void __RPC_STUB IOleInPlaceObject_ReactivateAndUndo_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleInPlaceObject_INTERFACE_DEFINED__ */
+
+
+#ifndef __IOleInPlaceSite_INTERFACE_DEFINED__
+#define __IOleInPlaceSite_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IOleInPlaceSite
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IOleInPlaceSite __RPC_FAR *LPOLEINPLACESITE;
+
+
+EXTERN_C const IID IID_IOleInPlaceSite;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IOleInPlaceSite : public IOleWindow
+ {
+ public:
+ virtual HRESULT __stdcall CanInPlaceActivate( void) = 0;
+
+ virtual HRESULT __stdcall OnInPlaceActivate( void) = 0;
+
+ virtual HRESULT __stdcall OnUIActivate( void) = 0;
+
+ virtual HRESULT __stdcall GetWindowContext(
+ /* [out] */ IOleInPlaceFrame __RPC_FAR *__RPC_FAR *ppFrame,
+ /* [out] */ IOleInPlaceUIWindow __RPC_FAR *__RPC_FAR *ppDoc,
+ /* [out] */ LPRECT lprcPosRect,
+ /* [out] */ LPRECT lprcClipRect,
+ /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo) = 0;
+
+ virtual HRESULT __stdcall Scroll(
+ /* [in] */ SIZE scrollExtant) = 0;
+
+ virtual HRESULT __stdcall OnUIDeactivate(
+ /* [in] */ BOOL fUndoable) = 0;
+
+ virtual HRESULT __stdcall OnInPlaceDeactivate( void) = 0;
+
+ virtual HRESULT __stdcall DiscardUndoState( void) = 0;
+
+ virtual HRESULT __stdcall DeactivateAndUndo( void) = 0;
+
+ virtual HRESULT __stdcall OnPosRectChange(
+ /* [in] */ LPCRECT lprcPosRect) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IOleInPlaceSiteVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IOleInPlaceSite __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IOleInPlaceSite __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IOleInPlaceSite __RPC_FAR * This);
+
+ /* [input_sync] */ HRESULT ( __stdcall __RPC_FAR *GetWindow )(
+ IOleInPlaceSite __RPC_FAR * This,
+ /* [out] */ HWND __RPC_FAR *phwnd);
+
+ HRESULT ( __stdcall __RPC_FAR *ContextSensitiveHelp )(
+ IOleInPlaceSite __RPC_FAR * This,
+ /* [in] */ BOOL fEnterMode);
+
+ HRESULT ( __stdcall __RPC_FAR *CanInPlaceActivate )(
+ IOleInPlaceSite __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *OnInPlaceActivate )(
+ IOleInPlaceSite __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *OnUIActivate )(
+ IOleInPlaceSite __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *GetWindowContext )(
+ IOleInPlaceSite __RPC_FAR * This,
+ /* [out] */ IOleInPlaceFrame __RPC_FAR *__RPC_FAR *ppFrame,
+ /* [out] */ IOleInPlaceUIWindow __RPC_FAR *__RPC_FAR *ppDoc,
+ /* [out] */ LPRECT lprcPosRect,
+ /* [out] */ LPRECT lprcClipRect,
+ /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo);
+
+ HRESULT ( __stdcall __RPC_FAR *Scroll )(
+ IOleInPlaceSite __RPC_FAR * This,
+ /* [in] */ SIZE scrollExtant);
+
+ HRESULT ( __stdcall __RPC_FAR *OnUIDeactivate )(
+ IOleInPlaceSite __RPC_FAR * This,
+ /* [in] */ BOOL fUndoable);
+
+ HRESULT ( __stdcall __RPC_FAR *OnInPlaceDeactivate )(
+ IOleInPlaceSite __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *DiscardUndoState )(
+ IOleInPlaceSite __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *DeactivateAndUndo )(
+ IOleInPlaceSite __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *OnPosRectChange )(
+ IOleInPlaceSite __RPC_FAR * This,
+ /* [in] */ LPCRECT lprcPosRect);
+
+ } IOleInPlaceSiteVtbl;
+
+ interface IOleInPlaceSite
+ {
+ CONST_VTBL struct IOleInPlaceSiteVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IOleInPlaceSite_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IOleInPlaceSite_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IOleInPlaceSite_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IOleInPlaceSite_GetWindow(This,phwnd) \
+ (This)->lpVtbl -> GetWindow(This,phwnd)
+
+#define IOleInPlaceSite_ContextSensitiveHelp(This,fEnterMode) \
+ (This)->lpVtbl -> ContextSensitiveHelp(This,fEnterMode)
+
+
+#define IOleInPlaceSite_CanInPlaceActivate(This) \
+ (This)->lpVtbl -> CanInPlaceActivate(This)
+
+#define IOleInPlaceSite_OnInPlaceActivate(This) \
+ (This)->lpVtbl -> OnInPlaceActivate(This)
+
+#define IOleInPlaceSite_OnUIActivate(This) \
+ (This)->lpVtbl -> OnUIActivate(This)
+
+#define IOleInPlaceSite_GetWindowContext(This,ppFrame,ppDoc,lprcPosRect,lprcClipRect,lpFrameInfo) \
+ (This)->lpVtbl -> GetWindowContext(This,ppFrame,ppDoc,lprcPosRect,lprcClipRect,lpFrameInfo)
+
+#define IOleInPlaceSite_Scroll(This,scrollExtant) \
+ (This)->lpVtbl -> Scroll(This,scrollExtant)
+
+#define IOleInPlaceSite_OnUIDeactivate(This,fUndoable) \
+ (This)->lpVtbl -> OnUIDeactivate(This,fUndoable)
+
+#define IOleInPlaceSite_OnInPlaceDeactivate(This) \
+ (This)->lpVtbl -> OnInPlaceDeactivate(This)
+
+#define IOleInPlaceSite_DiscardUndoState(This) \
+ (This)->lpVtbl -> DiscardUndoState(This)
+
+#define IOleInPlaceSite_DeactivateAndUndo(This) \
+ (This)->lpVtbl -> DeactivateAndUndo(This)
+
+#define IOleInPlaceSite_OnPosRectChange(This,lprcPosRect) \
+ (This)->lpVtbl -> OnPosRectChange(This,lprcPosRect)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IOleInPlaceSite_CanInPlaceActivate_Proxy(
+ IOleInPlaceSite __RPC_FAR * This);
+
+
+void __RPC_STUB IOleInPlaceSite_CanInPlaceActivate_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceSite_OnInPlaceActivate_Proxy(
+ IOleInPlaceSite __RPC_FAR * This);
+
+
+void __RPC_STUB IOleInPlaceSite_OnInPlaceActivate_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceSite_OnUIActivate_Proxy(
+ IOleInPlaceSite __RPC_FAR * This);
+
+
+void __RPC_STUB IOleInPlaceSite_OnUIActivate_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceSite_GetWindowContext_Proxy(
+ IOleInPlaceSite __RPC_FAR * This,
+ /* [out] */ IOleInPlaceFrame __RPC_FAR *__RPC_FAR *ppFrame,
+ /* [out] */ IOleInPlaceUIWindow __RPC_FAR *__RPC_FAR *ppDoc,
+ /* [out] */ LPRECT lprcPosRect,
+ /* [out] */ LPRECT lprcClipRect,
+ /* [out][in] */ LPOLEINPLACEFRAMEINFO lpFrameInfo);
+
+
+void __RPC_STUB IOleInPlaceSite_GetWindowContext_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceSite_Scroll_Proxy(
+ IOleInPlaceSite __RPC_FAR * This,
+ /* [in] */ SIZE scrollExtant);
+
+
+void __RPC_STUB IOleInPlaceSite_Scroll_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceSite_OnUIDeactivate_Proxy(
+ IOleInPlaceSite __RPC_FAR * This,
+ /* [in] */ BOOL fUndoable);
+
+
+void __RPC_STUB IOleInPlaceSite_OnUIDeactivate_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceSite_OnInPlaceDeactivate_Proxy(
+ IOleInPlaceSite __RPC_FAR * This);
+
+
+void __RPC_STUB IOleInPlaceSite_OnInPlaceDeactivate_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceSite_DiscardUndoState_Proxy(
+ IOleInPlaceSite __RPC_FAR * This);
+
+
+void __RPC_STUB IOleInPlaceSite_DiscardUndoState_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceSite_DeactivateAndUndo_Proxy(
+ IOleInPlaceSite __RPC_FAR * This);
+
+
+void __RPC_STUB IOleInPlaceSite_DeactivateAndUndo_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IOleInPlaceSite_OnPosRectChange_Proxy(
+ IOleInPlaceSite __RPC_FAR * This,
+ /* [in] */ LPCRECT lprcPosRect);
+
+
+void __RPC_STUB IOleInPlaceSite_OnPosRectChange_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IOleInPlaceSite_INTERFACE_DEFINED__ */
+
+
+#ifndef __IViewObject_INTERFACE_DEFINED__
+#define __IViewObject_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IViewObject
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IViewObject __RPC_FAR *LPVIEWOBJECT;
+
+
+EXTERN_C const IID IID_IViewObject;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IViewObject : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall Draw(
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [unique][in] */ void __RPC_FAR *pvAspect,
+ /* [unique][in] */ DVTARGETDEVICE __RPC_FAR *ptd,
+ /* [in] */ HDC hdcTargetDev,
+ /* [in] */ HDC hdcDraw,
+ /* [in] */ LPCRECTL lprcBounds,
+ /* [in] */ LPCRECTL lprcWBounds,
+ /* [in] */ BOOL ( __stdcall __stdcall __RPC_FAR *pfnContinue )(
+ DWORD dwContinue),
+ /* [in] */ DWORD dwContinue) = 0;
+
+ virtual HRESULT __stdcall GetColorSet(
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [unique][in] */ void __RPC_FAR *pvAspect,
+ /* [in] */ DVTARGETDEVICE __RPC_FAR *ptd,
+ /* [in] */ HDC hicTargetDev,
+ /* [out] */ LOGPALETTE __RPC_FAR *__RPC_FAR *ppColorSet) = 0;
+
+ virtual HRESULT __stdcall Freeze(
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [unique][in] */ void __RPC_FAR *pvAspect,
+ /* [out] */ DWORD __RPC_FAR *pdwFreeze) = 0;
+
+ virtual HRESULT __stdcall Unfreeze(
+ /* [in] */ DWORD dwFreeze) = 0;
+
+ virtual HRESULT __stdcall SetAdvise(
+ /* [in] */ DWORD aspects,
+ /* [in] */ DWORD advf,
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink) = 0;
+
+ virtual HRESULT __stdcall GetAdvise(
+ /* [out] */ DWORD __RPC_FAR *pAspects,
+ /* [out] */ DWORD __RPC_FAR *pAdvf,
+ /* [out] */ IAdviseSink __RPC_FAR *__RPC_FAR *ppAdvSink) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IViewObjectVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IViewObject __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IViewObject __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IViewObject __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Draw )(
+ IViewObject __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [unique][in] */ void __RPC_FAR *pvAspect,
+ /* [unique][in] */ DVTARGETDEVICE __RPC_FAR *ptd,
+ /* [in] */ HDC hdcTargetDev,
+ /* [in] */ HDC hdcDraw,
+ /* [in] */ LPCRECTL lprcBounds,
+ /* [in] */ LPCRECTL lprcWBounds,
+ /* [in] */ BOOL ( __stdcall __stdcall __RPC_FAR *pfnContinue )(
+ DWORD dwContinue),
+ /* [in] */ DWORD dwContinue);
+
+ HRESULT ( __stdcall __RPC_FAR *GetColorSet )(
+ IViewObject __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [unique][in] */ void __RPC_FAR *pvAspect,
+ /* [in] */ DVTARGETDEVICE __RPC_FAR *ptd,
+ /* [in] */ HDC hicTargetDev,
+ /* [out] */ LOGPALETTE __RPC_FAR *__RPC_FAR *ppColorSet);
+
+ HRESULT ( __stdcall __RPC_FAR *Freeze )(
+ IViewObject __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [unique][in] */ void __RPC_FAR *pvAspect,
+ /* [out] */ DWORD __RPC_FAR *pdwFreeze);
+
+ HRESULT ( __stdcall __RPC_FAR *Unfreeze )(
+ IViewObject __RPC_FAR * This,
+ /* [in] */ DWORD dwFreeze);
+
+ HRESULT ( __stdcall __RPC_FAR *SetAdvise )(
+ IViewObject __RPC_FAR * This,
+ /* [in] */ DWORD aspects,
+ /* [in] */ DWORD advf,
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink);
+
+ HRESULT ( __stdcall __RPC_FAR *GetAdvise )(
+ IViewObject __RPC_FAR * This,
+ /* [out] */ DWORD __RPC_FAR *pAspects,
+ /* [out] */ DWORD __RPC_FAR *pAdvf,
+ /* [out] */ IAdviseSink __RPC_FAR *__RPC_FAR *ppAdvSink);
+
+ } IViewObjectVtbl;
+
+ interface IViewObject
+ {
+ CONST_VTBL struct IViewObjectVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IViewObject_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IViewObject_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IViewObject_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IViewObject_Draw(This,dwDrawAspect,lindex,pvAspect,ptd,hdcTargetDev,hdcDraw,lprcBounds,lprcWBounds,pfnContinue,dwContinue) \
+ (This)->lpVtbl -> Draw(This,dwDrawAspect,lindex,pvAspect,ptd,hdcTargetDev,hdcDraw,lprcBounds,lprcWBounds,pfnContinue,dwContinue)
+
+#define IViewObject_GetColorSet(This,dwDrawAspect,lindex,pvAspect,ptd,hicTargetDev,ppColorSet) \
+ (This)->lpVtbl -> GetColorSet(This,dwDrawAspect,lindex,pvAspect,ptd,hicTargetDev,ppColorSet)
+
+#define IViewObject_Freeze(This,dwDrawAspect,lindex,pvAspect,pdwFreeze) \
+ (This)->lpVtbl -> Freeze(This,dwDrawAspect,lindex,pvAspect,pdwFreeze)
+
+#define IViewObject_Unfreeze(This,dwFreeze) \
+ (This)->lpVtbl -> Unfreeze(This,dwFreeze)
+
+#define IViewObject_SetAdvise(This,aspects,advf,pAdvSink) \
+ (This)->lpVtbl -> SetAdvise(This,aspects,advf,pAdvSink)
+
+#define IViewObject_GetAdvise(This,pAspects,pAdvf,ppAdvSink) \
+ (This)->lpVtbl -> GetAdvise(This,pAspects,pAdvf,ppAdvSink)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IViewObject_Draw_Proxy(
+ IViewObject __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [unique][in] */ void __RPC_FAR *pvAspect,
+ /* [unique][in] */ DVTARGETDEVICE __RPC_FAR *ptd,
+ /* [in] */ HDC hdcTargetDev,
+ /* [in] */ HDC hdcDraw,
+ /* [in] */ LPCRECTL lprcBounds,
+ /* [in] */ LPCRECTL lprcWBounds,
+ /* [in] */ BOOL ( __stdcall __stdcall __RPC_FAR *pfnContinue )(
+ DWORD dwContinue),
+ /* [in] */ DWORD dwContinue);
+
+
+void __RPC_STUB IViewObject_Draw_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IViewObject_GetColorSet_Proxy(
+ IViewObject __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [unique][in] */ void __RPC_FAR *pvAspect,
+ /* [in] */ DVTARGETDEVICE __RPC_FAR *ptd,
+ /* [in] */ HDC hicTargetDev,
+ /* [out] */ LOGPALETTE __RPC_FAR *__RPC_FAR *ppColorSet);
+
+
+void __RPC_STUB IViewObject_GetColorSet_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IViewObject_Freeze_Proxy(
+ IViewObject __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [unique][in] */ void __RPC_FAR *pvAspect,
+ /* [out] */ DWORD __RPC_FAR *pdwFreeze);
+
+
+void __RPC_STUB IViewObject_Freeze_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IViewObject_Unfreeze_Proxy(
+ IViewObject __RPC_FAR * This,
+ /* [in] */ DWORD dwFreeze);
+
+
+void __RPC_STUB IViewObject_Unfreeze_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IViewObject_SetAdvise_Proxy(
+ IViewObject __RPC_FAR * This,
+ /* [in] */ DWORD aspects,
+ /* [in] */ DWORD advf,
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink);
+
+
+void __RPC_STUB IViewObject_SetAdvise_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IViewObject_GetAdvise_Proxy(
+ IViewObject __RPC_FAR * This,
+ /* [out] */ DWORD __RPC_FAR *pAspects,
+ /* [out] */ DWORD __RPC_FAR *pAdvf,
+ /* [out] */ IAdviseSink __RPC_FAR *__RPC_FAR *ppAdvSink);
+
+
+void __RPC_STUB IViewObject_GetAdvise_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IViewObject_INTERFACE_DEFINED__ */
+
+
+#ifndef __IViewObject2_INTERFACE_DEFINED__
+#define __IViewObject2_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IViewObject2
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IViewObject2 __RPC_FAR *LPVIEWOBJECT2;
+
+
+EXTERN_C const IID IID_IViewObject2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IViewObject2 : public IViewObject
+ {
+ public:
+ virtual HRESULT __stdcall GetExtent(
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [in] */ DVTARGETDEVICE __RPC_FAR *ptd,
+ /* [out] */ LPSIZEL lpsizel) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IViewObject2Vtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IViewObject2 __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IViewObject2 __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IViewObject2 __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Draw )(
+ IViewObject2 __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [unique][in] */ void __RPC_FAR *pvAspect,
+ /* [unique][in] */ DVTARGETDEVICE __RPC_FAR *ptd,
+ /* [in] */ HDC hdcTargetDev,
+ /* [in] */ HDC hdcDraw,
+ /* [in] */ LPCRECTL lprcBounds,
+ /* [in] */ LPCRECTL lprcWBounds,
+ /* [in] */ BOOL ( __stdcall __stdcall __RPC_FAR *pfnContinue )(
+ DWORD dwContinue),
+ /* [in] */ DWORD dwContinue);
+
+ HRESULT ( __stdcall __RPC_FAR *GetColorSet )(
+ IViewObject2 __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [unique][in] */ void __RPC_FAR *pvAspect,
+ /* [in] */ DVTARGETDEVICE __RPC_FAR *ptd,
+ /* [in] */ HDC hicTargetDev,
+ /* [out] */ LOGPALETTE __RPC_FAR *__RPC_FAR *ppColorSet);
+
+ HRESULT ( __stdcall __RPC_FAR *Freeze )(
+ IViewObject2 __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [unique][in] */ void __RPC_FAR *pvAspect,
+ /* [out] */ DWORD __RPC_FAR *pdwFreeze);
+
+ HRESULT ( __stdcall __RPC_FAR *Unfreeze )(
+ IViewObject2 __RPC_FAR * This,
+ /* [in] */ DWORD dwFreeze);
+
+ HRESULT ( __stdcall __RPC_FAR *SetAdvise )(
+ IViewObject2 __RPC_FAR * This,
+ /* [in] */ DWORD aspects,
+ /* [in] */ DWORD advf,
+ /* [unique][in] */ IAdviseSink __RPC_FAR *pAdvSink);
+
+ HRESULT ( __stdcall __RPC_FAR *GetAdvise )(
+ IViewObject2 __RPC_FAR * This,
+ /* [out] */ DWORD __RPC_FAR *pAspects,
+ /* [out] */ DWORD __RPC_FAR *pAdvf,
+ /* [out] */ IAdviseSink __RPC_FAR *__RPC_FAR *ppAdvSink);
+
+ HRESULT ( __stdcall __RPC_FAR *GetExtent )(
+ IViewObject2 __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [in] */ DVTARGETDEVICE __RPC_FAR *ptd,
+ /* [out] */ LPSIZEL lpsizel);
+
+ } IViewObject2Vtbl;
+
+ interface IViewObject2
+ {
+ CONST_VTBL struct IViewObject2Vtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IViewObject2_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IViewObject2_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IViewObject2_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IViewObject2_Draw(This,dwDrawAspect,lindex,pvAspect,ptd,hdcTargetDev,hdcDraw,lprcBounds,lprcWBounds,pfnContinue,dwContinue) \
+ (This)->lpVtbl -> Draw(This,dwDrawAspect,lindex,pvAspect,ptd,hdcTargetDev,hdcDraw,lprcBounds,lprcWBounds,pfnContinue,dwContinue)
+
+#define IViewObject2_GetColorSet(This,dwDrawAspect,lindex,pvAspect,ptd,hicTargetDev,ppColorSet) \
+ (This)->lpVtbl -> GetColorSet(This,dwDrawAspect,lindex,pvAspect,ptd,hicTargetDev,ppColorSet)
+
+#define IViewObject2_Freeze(This,dwDrawAspect,lindex,pvAspect,pdwFreeze) \
+ (This)->lpVtbl -> Freeze(This,dwDrawAspect,lindex,pvAspect,pdwFreeze)
+
+#define IViewObject2_Unfreeze(This,dwFreeze) \
+ (This)->lpVtbl -> Unfreeze(This,dwFreeze)
+
+#define IViewObject2_SetAdvise(This,aspects,advf,pAdvSink) \
+ (This)->lpVtbl -> SetAdvise(This,aspects,advf,pAdvSink)
+
+#define IViewObject2_GetAdvise(This,pAspects,pAdvf,ppAdvSink) \
+ (This)->lpVtbl -> GetAdvise(This,pAspects,pAdvf,ppAdvSink)
+
+
+#define IViewObject2_GetExtent(This,dwDrawAspect,lindex,ptd,lpsizel) \
+ (This)->lpVtbl -> GetExtent(This,dwDrawAspect,lindex,ptd,lpsizel)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IViewObject2_GetExtent_Proxy(
+ IViewObject2 __RPC_FAR * This,
+ /* [in] */ DWORD dwDrawAspect,
+ /* [in] */ LONG lindex,
+ /* [in] */ DVTARGETDEVICE __RPC_FAR *ptd,
+ /* [out] */ LPSIZEL lpsizel);
+
+
+void __RPC_STUB IViewObject2_GetExtent_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IViewObject2_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDropSource_INTERFACE_DEFINED__
+#define __IDropSource_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IDropSource
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [uuid][object][local] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IDropSource __RPC_FAR *LPDROPSOURCE;
+
+
+EXTERN_C const IID IID_IDropSource;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IDropSource : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall QueryContinueDrag(
+ /* [in] */ BOOL fEscapePressed,
+ /* [in] */ DWORD grfKeyState) = 0;
+
+ virtual HRESULT __stdcall GiveFeedback(
+ /* [in] */ DWORD dwEffect) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IDropSourceVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IDropSource __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IDropSource __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IDropSource __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *QueryContinueDrag )(
+ IDropSource __RPC_FAR * This,
+ /* [in] */ BOOL fEscapePressed,
+ /* [in] */ DWORD grfKeyState);
+
+ HRESULT ( __stdcall __RPC_FAR *GiveFeedback )(
+ IDropSource __RPC_FAR * This,
+ /* [in] */ DWORD dwEffect);
+
+ } IDropSourceVtbl;
+
+ interface IDropSource
+ {
+ CONST_VTBL struct IDropSourceVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDropSource_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IDropSource_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IDropSource_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IDropSource_QueryContinueDrag(This,fEscapePressed,grfKeyState) \
+ (This)->lpVtbl -> QueryContinueDrag(This,fEscapePressed,grfKeyState)
+
+#define IDropSource_GiveFeedback(This,dwEffect) \
+ (This)->lpVtbl -> GiveFeedback(This,dwEffect)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IDropSource_QueryContinueDrag_Proxy(
+ IDropSource __RPC_FAR * This,
+ /* [in] */ BOOL fEscapePressed,
+ /* [in] */ DWORD grfKeyState);
+
+
+void __RPC_STUB IDropSource_QueryContinueDrag_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDropSource_GiveFeedback_Proxy(
+ IDropSource __RPC_FAR * This,
+ /* [in] */ DWORD dwEffect);
+
+
+void __RPC_STUB IDropSource_GiveFeedback_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IDropSource_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDropTarget_INTERFACE_DEFINED__
+#define __IDropTarget_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IDropTarget
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IDropTarget __RPC_FAR *LPDROPTARGET;
+
+ /* size is 4 */
+#define MK_ALT ( 0x20 )
+
+ /* size is 4 */
+#define DROPEFFECT_NONE ( 0 )
+
+ /* size is 4 */
+#define DROPEFFECT_COPY ( 1 )
+
+ /* size is 4 */
+#define DROPEFFECT_MOVE ( 2 )
+
+ /* size is 4 */
+#define DROPEFFECT_LINK ( 4 )
+
+ /* size is 4 */
+#define DROPEFFECT_SCROLL ( 0x80000000 )
+
+// default inset-width of the hot zone, in pixels
+// typical use: GetProfileInt("windows","DragScrollInset",DD_DEFSCROLLINSET)
+ /* size is 4 */
+#define DD_DEFSCROLLINSET ( 11 )
+
+// default delay before scrolling, in milliseconds
+// typical use: GetProfileInt("windows","DragScrollDelay",DD_DEFSCROLLDELAY)
+ /* size is 4 */
+#define DD_DEFSCROLLDELAY ( 50 )
+
+// default scroll interval, in milliseconds
+// typical use: GetProfileInt("windows","DragScrollInterval", DD_DEFSCROLLINTERVAL)
+ /* size is 4 */
+#define DD_DEFSCROLLINTERVAL ( 50 )
+
+// default delay before dragging should start, in milliseconds
+// typical use: GetProfileInt("windows", "DragDelay", DD_DEFDRAGDELAY)
+ /* size is 4 */
+#define DD_DEFDRAGDELAY ( 200 )
+
+// default minimum distance (radius) before dragging should start, in pixels
+// typical use: GetProfileInt("windows", "DragMinDist", DD_DEFDRAGMINDIST)
+ /* size is 4 */
+#define DD_DEFDRAGMINDIST ( 2 )
+
+
+EXTERN_C const IID IID_IDropTarget;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IDropTarget : public IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall DragEnter(
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
+ /* [in] */ DWORD grfKeyState,
+ /* [in] */ POINTL pt,
+ /* [out][in] */ DWORD __RPC_FAR *pdwEffect) = 0;
+
+ virtual HRESULT __stdcall DragOver(
+ /* [in] */ DWORD grfKeyState,
+ /* [in] */ POINTL pt,
+ /* [out][in] */ DWORD __RPC_FAR *pdwEffect) = 0;
+
+ virtual HRESULT __stdcall DragLeave( void) = 0;
+
+ virtual HRESULT __stdcall Drop(
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
+ /* [in] */ DWORD grfKeyState,
+ /* [in] */ POINTL pt,
+ /* [out][in] */ DWORD __RPC_FAR *pdwEffect) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IDropTargetVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IDropTarget __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IDropTarget __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IDropTarget __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *DragEnter )(
+ IDropTarget __RPC_FAR * This,
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
+ /* [in] */ DWORD grfKeyState,
+ /* [in] */ POINTL pt,
+ /* [out][in] */ DWORD __RPC_FAR *pdwEffect);
+
+ HRESULT ( __stdcall __RPC_FAR *DragOver )(
+ IDropTarget __RPC_FAR * This,
+ /* [in] */ DWORD grfKeyState,
+ /* [in] */ POINTL pt,
+ /* [out][in] */ DWORD __RPC_FAR *pdwEffect);
+
+ HRESULT ( __stdcall __RPC_FAR *DragLeave )(
+ IDropTarget __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Drop )(
+ IDropTarget __RPC_FAR * This,
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
+ /* [in] */ DWORD grfKeyState,
+ /* [in] */ POINTL pt,
+ /* [out][in] */ DWORD __RPC_FAR *pdwEffect);
+
+ } IDropTargetVtbl;
+
+ interface IDropTarget
+ {
+ CONST_VTBL struct IDropTargetVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDropTarget_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IDropTarget_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IDropTarget_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IDropTarget_DragEnter(This,pDataObj,grfKeyState,pt,pdwEffect) \
+ (This)->lpVtbl -> DragEnter(This,pDataObj,grfKeyState,pt,pdwEffect)
+
+#define IDropTarget_DragOver(This,grfKeyState,pt,pdwEffect) \
+ (This)->lpVtbl -> DragOver(This,grfKeyState,pt,pdwEffect)
+
+#define IDropTarget_DragLeave(This) \
+ (This)->lpVtbl -> DragLeave(This)
+
+#define IDropTarget_Drop(This,pDataObj,grfKeyState,pt,pdwEffect) \
+ (This)->lpVtbl -> Drop(This,pDataObj,grfKeyState,pt,pdwEffect)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IDropTarget_DragEnter_Proxy(
+ IDropTarget __RPC_FAR * This,
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
+ /* [in] */ DWORD grfKeyState,
+ /* [in] */ POINTL pt,
+ /* [out][in] */ DWORD __RPC_FAR *pdwEffect);
+
+
+void __RPC_STUB IDropTarget_DragEnter_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDropTarget_DragOver_Proxy(
+ IDropTarget __RPC_FAR * This,
+ /* [in] */ DWORD grfKeyState,
+ /* [in] */ POINTL pt,
+ /* [out][in] */ DWORD __RPC_FAR *pdwEffect);
+
+
+void __RPC_STUB IDropTarget_DragOver_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDropTarget_DragLeave_Proxy(
+ IDropTarget __RPC_FAR * This);
+
+
+void __RPC_STUB IDropTarget_DragLeave_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IDropTarget_Drop_Proxy(
+ IDropTarget __RPC_FAR * This,
+ /* [unique][in] */ IDataObject __RPC_FAR *pDataObj,
+ /* [in] */ DWORD grfKeyState,
+ /* [in] */ POINTL pt,
+ /* [out][in] */ DWORD __RPC_FAR *pdwEffect);
+
+
+void __RPC_STUB IDropTarget_Drop_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IDropTarget_INTERFACE_DEFINED__ */
+
+
+#ifndef __IEnumOLEVERB_INTERFACE_DEFINED__
+#define __IEnumOLEVERB_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IEnumOLEVERB
+ * at Fri Apr 28 07:02:35 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IEnumOLEVERB __RPC_FAR *LPENUMOLEVERB;
+
+ /* size is 16 */
+typedef struct tagOLEVERB
+ {
+ LONG lVerb;
+ LPOLESTR lpszVerbName;
+ DWORD fuFlags;
+ DWORD grfAttribs;
+ } OLEVERB;
+
+ /* size is 4 */
+typedef struct tagOLEVERB __RPC_FAR *LPOLEVERB;
+
+ /* size is 2 */
+typedef /* [v1_enum] */
+enum tagOLEVERBATTRIB
+ { OLEVERBATTRIB_NEVERDIRTIES = 1,
+ OLEVERBATTRIB_ONCONTAINERMENU = 2
+ } OLEVERBATTRIB;
+
+
+EXTERN_C const IID IID_IEnumOLEVERB;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IEnumOLEVERB : public IUnknown
+ {
+ public:
+ virtual /* [local] */ HRESULT __stdcall Next(
+ /* [in] */ ULONG celt,
+ /* [out] */ LPOLEVERB rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched) = 0;
+
+ virtual HRESULT __stdcall Skip(
+ /* [in] */ ULONG celt) = 0;
+
+ virtual HRESULT __stdcall Reset( void) = 0;
+
+ virtual HRESULT __stdcall Clone(
+ /* [out] */ IEnumOLEVERB __RPC_FAR *__RPC_FAR *ppenum) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IEnumOLEVERBVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IEnumOLEVERB __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IEnumOLEVERB __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IEnumOLEVERB __RPC_FAR * This);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *Next )(
+ IEnumOLEVERB __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [out] */ LPOLEVERB rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+ HRESULT ( __stdcall __RPC_FAR *Skip )(
+ IEnumOLEVERB __RPC_FAR * This,
+ /* [in] */ ULONG celt);
+
+ HRESULT ( __stdcall __RPC_FAR *Reset )(
+ IEnumOLEVERB __RPC_FAR * This);
+
+ HRESULT ( __stdcall __RPC_FAR *Clone )(
+ IEnumOLEVERB __RPC_FAR * This,
+ /* [out] */ IEnumOLEVERB __RPC_FAR *__RPC_FAR *ppenum);
+
+ } IEnumOLEVERBVtbl;
+
+ interface IEnumOLEVERB
+ {
+ CONST_VTBL struct IEnumOLEVERBVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IEnumOLEVERB_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IEnumOLEVERB_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IEnumOLEVERB_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IEnumOLEVERB_Next(This,celt,rgelt,pceltFetched) \
+ (This)->lpVtbl -> Next(This,celt,rgelt,pceltFetched)
+
+#define IEnumOLEVERB_Skip(This,celt) \
+ (This)->lpVtbl -> Skip(This,celt)
+
+#define IEnumOLEVERB_Reset(This) \
+ (This)->lpVtbl -> Reset(This)
+
+#define IEnumOLEVERB_Clone(This,ppenum) \
+ (This)->lpVtbl -> Clone(This,ppenum)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [call_as] */ HRESULT __stdcall IEnumOLEVERB_RemoteNext_Proxy(
+ IEnumOLEVERB __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ LPOLEVERB rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+
+void __RPC_STUB IEnumOLEVERB_RemoteNext_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumOLEVERB_Skip_Proxy(
+ IEnumOLEVERB __RPC_FAR * This,
+ /* [in] */ ULONG celt);
+
+
+void __RPC_STUB IEnumOLEVERB_Skip_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumOLEVERB_Reset_Proxy(
+ IEnumOLEVERB __RPC_FAR * This);
+
+
+void __RPC_STUB IEnumOLEVERB_Reset_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IEnumOLEVERB_Clone_Proxy(
+ IEnumOLEVERB __RPC_FAR * This,
+ /* [out] */ IEnumOLEVERB __RPC_FAR *__RPC_FAR *ppenum);
+
+
+void __RPC_STUB IEnumOLEVERB_Clone_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IEnumOLEVERB_INTERFACE_DEFINED__ */
+
+
+/* Additional Prototypes for ALL interfaces */
+#ifndef NOPROXYSTUB
+
+void __RPC_USER UINT_to_xmit( UINT __RPC_FAR *, unsigned long __RPC_FAR * __RPC_FAR * );
+void __RPC_USER UINT_from_xmit( unsigned long __RPC_FAR *, UINT __RPC_FAR * );
+void __RPC_USER UINT_free_inst( UINT __RPC_FAR * );
+void __RPC_USER UINT_free_xmit( unsigned long __RPC_FAR * );
+
+void __RPC_USER WPARAM_to_xmit( WPARAM __RPC_FAR *, unsigned long __RPC_FAR * __RPC_FAR * );
+void __RPC_USER WPARAM_from_xmit( unsigned long __RPC_FAR *, WPARAM __RPC_FAR * );
+void __RPC_USER WPARAM_free_inst( WPARAM __RPC_FAR * );
+void __RPC_USER WPARAM_free_xmit( unsigned long __RPC_FAR * );
+
+void __RPC_USER HWND_to_xmit( HWND __RPC_FAR *, long __RPC_FAR * __RPC_FAR * );
+void __RPC_USER HWND_from_xmit( long __RPC_FAR *, HWND __RPC_FAR * );
+void __RPC_USER HWND_free_inst( HWND __RPC_FAR * );
+void __RPC_USER HWND_free_xmit( long __RPC_FAR * );
+
+void __RPC_USER HMENU_to_xmit( HMENU __RPC_FAR *, long __RPC_FAR * __RPC_FAR * );
+void __RPC_USER HMENU_from_xmit( long __RPC_FAR *, HMENU __RPC_FAR * );
+void __RPC_USER HMENU_free_inst( HMENU __RPC_FAR * );
+void __RPC_USER HMENU_free_xmit( long __RPC_FAR * );
+
+void __RPC_USER HACCEL_to_xmit( HACCEL __RPC_FAR *, long __RPC_FAR * __RPC_FAR * );
+void __RPC_USER HACCEL_from_xmit( long __RPC_FAR *, HACCEL __RPC_FAR * );
+void __RPC_USER HACCEL_free_inst( HACCEL __RPC_FAR * );
+void __RPC_USER HACCEL_free_xmit( long __RPC_FAR * );
+
+void __RPC_USER HOLEMENU_to_xmit( HOLEMENU __RPC_FAR *, RemHGLOBAL __RPC_FAR * __RPC_FAR * );
+void __RPC_USER HOLEMENU_from_xmit( RemHGLOBAL __RPC_FAR *, HOLEMENU __RPC_FAR * );
+void __RPC_USER HOLEMENU_free_inst( HOLEMENU __RPC_FAR * );
+void __RPC_USER HOLEMENU_free_xmit( RemHGLOBAL __RPC_FAR * );
+
+/* [local] */ HRESULT __stdcall IOleItemContainer_GetObject_Proxy(
+ IOleItemContainer __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszItem,
+ /* [in] */ DWORD dwSpeedNeeded,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+
+/* [call_as] */ HRESULT __stdcall IOleItemContainer_GetObject_Stub(
+ IOleItemContainer __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszItem,
+ /* [in] */ DWORD dwSpeedNeeded,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppvObject);
+
+/* [local] */ HRESULT __stdcall IOleItemContainer_GetObjectStorage_Proxy(
+ IOleItemContainer __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszItem,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvStorage);
+
+
+/* [call_as] */ HRESULT __stdcall IOleItemContainer_GetObjectStorage_Stub(
+ IOleItemContainer __RPC_FAR * This,
+ /* [in] */ LPOLESTR pszItem,
+ /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppvStorage);
+
+/* [local] */ HRESULT __stdcall IOleInPlaceActiveObject_TranslateAccelerator_Proxy(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [in] */ LPMSG lpmsg);
+
+
+/* [call_as] */ HRESULT __stdcall IOleInPlaceActiveObject_TranslateAccelerator_Stub(
+ IOleInPlaceActiveObject __RPC_FAR * This);
+
+/* [local] */ HRESULT __stdcall IOleInPlaceActiveObject_ResizeBorder_Proxy(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [in] */ LPCRECT prcBorder,
+ /* [unique][in] */ IOleInPlaceUIWindow __RPC_FAR *pUIWindow,
+ /* [in] */ BOOL fFrameWindow);
+
+
+/* [input_sync][call_as] */ HRESULT __stdcall IOleInPlaceActiveObject_ResizeBorder_Stub(
+ IOleInPlaceActiveObject __RPC_FAR * This,
+ /* [in] */ LPCRECT prcBorder,
+ /* [in] */ REFIID riid,
+ /* [iid_is][unique][in] */ IOleInPlaceUIWindow __RPC_FAR *pUIWindow,
+ /* [in] */ BOOL fFrameWindow);
+
+/* [local] */ HRESULT __stdcall IEnumOLEVERB_Next_Proxy(
+ IEnumOLEVERB __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [out] */ LPOLEVERB rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+
+/* [call_as] */ HRESULT __stdcall IEnumOLEVERB_Next_Stub(
+ IEnumOLEVERB __RPC_FAR * This,
+ /* [in] */ ULONG celt,
+ /* [length_is][size_is][out] */ LPOLEVERB rgelt,
+ /* [out] */ ULONG __RPC_FAR *pceltFetched);
+
+#endif //NOPROXYSTUB
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/ole32/stg/props/iprop/privoa.cxx b/private/ole32/stg/props/iprop/privoa.cxx
new file mode 100644
index 000000000..660709c0c
--- /dev/null
+++ b/private/ole32/stg/props/iprop/privoa.cxx
@@ -0,0 +1,154 @@
+
+#include <pch.cxx>
+#pragma hdrstop
+
+
+HINSTANCE hOleAut32 = 0;
+
+EXTERN_C SYS_ALLOC_STRING *pfnSysAllocString = LoadSysAllocString;
+EXTERN_C SYS_FREE_STRING *pfnSysFreeString = LoadSysFreeString;
+EXTERN_C SYS_REALLOC_STRING_LEN *pfnSysReAllocStringLen = LoadSysReAllocStringLen;
+EXTERN_C SYS_STRING_BYTE_LEN *pfnSysStringByteLen = LoadSysStringByteLen;
+
+//+-------------------------------------------------------------------
+//
+// Function: LoadSysAllocString
+//
+// Synopsis: Loads oleaut32.dll and calls SysAllocString.
+//
+// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
+//
+// Notes: If successful, this function will save a pointer
+// to the SysAllocString function. Subsequent calls
+// will go directly to SysAllocString.
+//
+//--------------------------------------------------------------------
+BSTR STDAPICALLTYPE
+LoadSysAllocString(OLECHAR FAR* pwsz)
+{
+ BSTR bstr = NULL;
+
+ if(!hOleAut32)
+ {
+ hOleAut32 = LoadLibraryA("oleaut32");
+ }
+
+ if(hOleAut32 != 0)
+ {
+ void *pfn = GetProcAddress(hOleAut32, "SysAllocString");
+ if(pfn != NULL)
+ {
+ pfnSysAllocString = (SYS_ALLOC_STRING *) pfn;
+ bstr = (*pfnSysAllocString)(pwsz);
+ }
+ }
+
+ return bstr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: LoadSysFreeString
+//
+// Synopsis: Loads oleaut32.dll and calls SysFreeString.
+//
+// Returns: None.
+//
+// Notes: If successful, this function will save a pointer
+// to the SysFreeString function. Subsequent calls
+// will go directly to SysFreeString.
+//
+//--------------------------------------------------------------------
+VOID STDAPICALLTYPE
+LoadSysFreeString(BSTR bstr)
+{
+ if(!hOleAut32)
+ {
+ hOleAut32 = LoadLibraryA("oleaut32");
+ }
+
+ if(hOleAut32 != 0)
+ {
+ void *pfn = GetProcAddress(hOleAut32, "SysFreeString");
+ if(pfn != NULL)
+ {
+ pfnSysFreeString = (SYS_FREE_STRING *) pfn;
+ (*pfnSysFreeString)(bstr);
+ }
+ }
+
+ return;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: LoadSysReAllocStringLen
+//
+// Synopsis: Loads oleaut32.dll and calls SysReAllocStringLen.
+//
+// Returns: TRUE if and only if successful.
+//
+// Notes: If successful, this function will save a pointer
+// to the SysReAllocString function. Subsequent calls
+// will go directly to SysReAllocStringLen.
+//
+//--------------------------------------------------------------------
+BOOL STDAPICALLTYPE
+LoadSysReAllocStringLen(BSTR FAR *pbstr, OLECHAR FAR *pwsz, UINT cch)
+{
+ BOOL fRet = FALSE;
+
+ if(!hOleAut32)
+ {
+ hOleAut32 = LoadLibraryA("oleaut32");
+ }
+
+ if(hOleAut32 != 0)
+ {
+ void *pfn = GetProcAddress(hOleAut32, "SysReAllocStringLen");
+ if(pfn != NULL)
+ {
+ pfnSysReAllocStringLen = (SYS_REALLOC_STRING_LEN *) pfn;
+ fRet = (*pfnSysReAllocStringLen)(pbstr, pwsz, cch);
+ }
+ }
+
+ return( fRet );
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: LoadSysStringByteLen
+//
+// Synopsis: Loads oleaut32.dll and calls SysFreeString.
+//
+// Returns: The byte length of the string.
+//
+// Notes: If successful, this function will save a pointer
+// to the SysStringByteLen function. Subsequent calls
+// will go directly to SysStringByteLen.
+//
+//--------------------------------------------------------------------
+UINT STDAPICALLTYPE
+LoadSysStringByteLen(BSTR bstr)
+{
+ UINT uiLen = 0;
+
+ if(!hOleAut32)
+ {
+ hOleAut32 = LoadLibraryA("oleaut32");
+ }
+
+ if(hOleAut32 != 0)
+ {
+ void *pfn = GetProcAddress(hOleAut32, "SysStringByteLen");
+ if(pfn != NULL)
+ {
+ pfnSysStringByteLen = (SYS_STRING_BYTE_LEN *) pfn;
+ uiLen = (*pfnSysStringByteLen)(bstr);
+ }
+ }
+
+ return( uiLen );
+}
+
diff --git a/private/ole32/stg/props/iprop/prstg_ca.c b/private/ole32/stg/props/iprop/prstg_ca.c
new file mode 100644
index 000000000..e2f7b6788
--- /dev/null
+++ b/private/ole32/stg/props/iprop/prstg_ca.c
@@ -0,0 +1,685 @@
+
+
+//====================================================================
+//
+// File:
+// pstg_ca.c
+//
+// Purpose:
+// This file provides helper functions for the
+// IPropertyStorage call_as routines. Those call_as
+// routines are necessary to convert BSTR properties
+// into a remotable form (BSTR_BLOBs).
+//
+// BSTRs are always allocated from the OleAutomation
+// heap. BSTR_BLOBs are always allocated from the
+// IMalloc heap.
+//
+//====================================================================
+
+#include <rpcproxy.h>
+#include <privoa.h> // Private OleAutomation wrappers
+#include "prstg_ca.h"
+
+//+-------------------------------------------------------------------
+//
+// Function: ContainsSpecialProperty
+//
+// Synopsis: This routine scans an array of PropVariants
+// and checks for existance of a BSTR property
+// or non-simple property. These types require
+// special handling.
+// This routine recurses on Variant Vectors.
+//
+// Pre-Conditions:
+// None.
+//
+// Inputs: [ULONG] cElems
+// Count of elements in the array.
+// [LPPROPVARIANT] lppropvar
+// The PropVariant[] to check.
+//
+// Outputs: An OR of the bits BSTR_EXISTS and
+// NONSIMPLE_EXISTS, or 0 if neither exists.
+//
+//+-------------------------------------------------------------------
+
+ULONG
+ContainsSpecialProperty( ULONG cElems, const PROPVARIANT rgpropvar[] )
+{
+ ULONG ulVTExists = 0;
+
+ // Walk the array and search for BSTR and non-simple properties.
+ // Note that we will needlessly continue to search here even after
+ // we've found both a BSTR and a non-simple property. But to check
+ // for this condition would hurt normal-case performance, in order
+ // to make a savings in the error-case (since existance of a non-
+ // simple is an error).
+
+ ULONG ulIndex;
+ for( ulIndex = 0; ulIndex < cElems; ulIndex++ )
+ {
+ switch( rgpropvar[ ulIndex ].vt )
+ {
+ // Is this a BSTR?
+
+ case VT_BSTR:
+ case (VT_BSTR | VT_VECTOR):
+
+ ulVTExists |= BSTR_EXISTS;
+ break;
+
+ // Or is it a non-simple?
+
+ case VT_STORAGE:
+ case VT_STREAM:
+ case VT_STORED_OBJECT:
+ case VT_STREAMED_OBJECT:
+
+ ulVTExists |= NONSIMPLE_EXISTS;
+ break;
+
+ // Or is it a vector of variants which we need
+ // to search recursively?
+
+ case (VT_VECTOR | VT_VARIANT):
+
+ ulVTExists |= ContainsSpecialProperty(
+ rgpropvar[ ulIndex ].capropvar.cElems,
+ rgpropvar[ ulIndex ].capropvar.pElems );
+ break;
+
+ } // switch( rgpropvar[ ulIndex ].vt )
+ } // for( ulIndex = 0; ulIndex < cElems; ulIndex++ )
+
+
+ return( ulVTExists );
+
+} // ContainsSpecialProperty()
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: PropVarMarshalBstr
+//
+// Synopsis: This routine converts a PropVariant from a BSTR to a
+// BSTR_BLOB. The old buffer is freed (from the OleAut
+// heap) and the new buffer is allocated from the
+// IMalloc heap.
+//
+// Pre-Conditions:
+// The input is a VT_BSTR.
+//
+// Inputs: [LPPROPVARIANT] lppropvar
+// The PropVariant to convert.
+//
+// Outputs: HRESULT.
+//
+//+-------------------------------------------------------------------
+
+HRESULT
+PropVarMarshalBstr( LPPROPVARIANT lppropvar )
+{
+ HRESULT hr = S_OK;
+
+ // Save a pointer to the characters.
+ BSTR bstrVal = lppropvar->bstrVal;
+
+ // Is this a NULL BSTR value?
+
+ if( NULL == bstrVal )
+ {
+ lppropvar->bstrblobVal.cbSize = 0;
+ lppropvar->bstrblobVal.pData = NULL;
+ }
+ else
+ {
+ // Set the size to be the *byte* count of the string, plus
+ // the bytes for the length DWORD, plus the bytes for the NULL
+ // terminator.
+
+ lppropvar->bstrblobVal.cbSize = *SYSSTRINGBUF( bstrVal )
+ + sizeof(ULONG)
+ + sizeof(OLECHAR);
+
+
+ // Reallocate with IMalloc (as opposed to SysAllocString).
+ lppropvar->bstrblobVal.pData
+ = (BYTE*) CoTaskMemAlloc( lppropvar->bstrblobVal.cbSize );
+
+ if( FAILED(hr) )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // Copy the BSTR, including the length field and the NULL.
+ memcpy( lppropvar->bstrblobVal.pData,
+ (BYTE*) SYSSTRINGBUF( bstrVal ),
+ lppropvar->bstrblobVal.cbSize);
+
+ // Free the old value.
+ PrivSysFreeString( bstrVal );
+ bstrVal = NULL;
+
+ } // if( NULL == bstrVal ) ... else
+
+
+ // Convert the VT
+ lppropvar->vt = VT_BSTR_BLOB;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // Restore the input on failures.
+
+ if( FAILED(hr) )
+ {
+ // We don't need to free anything, because the
+ // only possible failure is from the one and only
+ // memory allocation.
+
+ lppropvar->bstrVal = bstrVal;
+ }
+
+ return( hr );
+
+} // PropVarMarshalBstr
+
+
+//+-------------------------------------------------------------------
+//
+// Function: PropVarUnmarshalBstr
+//
+// Synopsis: We convert a PropVariant from a BSTR_BLOB to a
+// BSTR. The new BSTR is allocated from the
+// OleAutomation heap, and the old buffer is freed
+// from the IMalloc heap.
+//
+// Pre-Conditions:
+// The input is a VT_BSTR_BLOB.
+//
+// Inputs: [LPPROPVARIANT] lppropvar
+// The PropVariant to convert.
+//
+// Outputs: HRESULT
+//
+//+-------------------------------------------------------------------
+
+HRESULT
+PropVarUnmarshalBstr( LPPROPVARIANT lppropvar )
+{
+ HRESULT hr = S_OK;
+
+ // Save the original value.
+ BSTRBLOB bstrblob = lppropvar->bstrblobVal;
+
+ // Convert the Bstr property
+
+ if( NULL == bstrblob.pData )
+ {
+ // There is no BSTR buffer
+ lppropvar->bstrVal = NULL;
+ }
+ else
+ {
+ // Alloc a BSTR from OleAut32 heap, and copy to it the string data.
+
+ lppropvar->bstrVal = PrivSysAllocString( SYSSTRINGOFBUF( bstrblob.pData ));
+ if( NULL == lppropvar->bstrVal )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // Free the old buffer
+ CoTaskMemFree( bstrblob.pData );
+
+ } // if( NULL == lppropvar->bstrblobVal.pData )
+
+
+ // Update the VT
+ lppropvar->vt = VT_BSTR;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // Restore the input on failure.
+
+ if( FAILED(hr) )
+ lppropvar->bstrblobVal = bstrblob;
+
+ return( hr );
+
+} // PropVarUnmarshalBstr
+
+
+//+-------------------------------------------------------------------
+//
+// Function: PropVarMarshalBstrVector
+//
+// Synopsis: This routine converts a Propvariant from
+// a VT_BSTR|VT_VECTOR to a VT_BSTR_BLOB|VT_VECTOR.
+//
+// Pre-Conditions:
+// The input is a VT_BSTR | VT_VECTOR.
+//
+// Inputs: [LPPROPVARIANT] lppropvar
+// The PropVariant to convert.
+//
+// Outputs: HRESULT
+//
+//+-------------------------------------------------------------------
+
+HRESULT
+PropVarMarshalBstrVector( LPPROPVARIANT lppropvar )
+{
+ // ------
+ // Locals
+ // ------
+
+ HRESULT hr = S_OK;
+ ULONG cElems;
+ ULONG nIndex;
+
+ LPBSTRBLOB rgbstrblob = NULL;
+
+ // -----
+ // Begin
+ // -----
+
+ cElems = lppropvar->cabstr.cElems;
+
+ // Allocate a BSTRBLOB array.
+
+ rgbstrblob = CoTaskMemAlloc( cElems * sizeof(*rgbstrblob) );
+ if( NULL == rgbstrblob )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+ memset( rgbstrblob, 0, cElems * sizeof(*rgbstrblob) );
+
+ // Fill in the BSTRBLOB array.
+
+ for( nIndex = 0; nIndex < cElems; nIndex++ )
+ {
+ // Is this a NULL BSTR?
+ if( NULL == lppropvar->cabstr.pElems[nIndex] )
+ {
+ rgbstrblob[nIndex].cbSize = 0;
+ rgbstrblob[nIndex].pData = NULL;
+ }
+
+ // Otherwise, alloc a new BSTRBLOB buffer fill it from the BSTR.
+ else
+ {
+ // Set the size to the byte-count for the characters, plus the size
+ // of the length DWORD and the NULL terminator.
+
+ rgbstrblob[nIndex].cbSize = *SYSSTRINGBUF( lppropvar->cabstr.pElems[nIndex] )
+ + sizeof(ULONG)
+ + sizeof(OLECHAR);
+
+ // Allocate from IMalloc
+
+ rgbstrblob[nIndex].pData
+ = (BYTE*) CoTaskMemAlloc( rgbstrblob[nIndex].cbSize );
+
+ if( NULL == rgbstrblob[nIndex].pData )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // Copy the string, plus the length field & NULL terminator.
+ // We'll free the old buffer after this for loop.
+
+ memcpy( rgbstrblob[nIndex].pData,
+ (BYTE*) SYSSTRINGBUF( lppropvar->cabstr.pElems[nIndex] ),
+ rgbstrblob[nIndex].cbSize );
+
+ } // if( NULL == lppropvar->cabstr.pElems[nIndex] ) ... else
+ } // for( nIndex = 0; nIndex < cElems; nIndex++ )
+
+ // Free the original BSTRs.
+
+ for( nIndex = 0; nIndex < cElems; nIndex++ )
+ {
+ PrivSysFreeString( lppropvar->cabstr.pElems[nIndex] );
+ }
+
+ // Update the PropVariant to use the new buffer. We don't
+ // need to set the cElems, because it hasn't changed.
+
+ lppropvar->vt = VT_BSTR_BLOB | VT_VECTOR;
+ CoTaskMemFree( lppropvar->cabstr.pElems );
+ lppropvar->cabstrblob.pElems = rgbstrblob;
+ rgbstrblob = NULL;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // Free the new array (if there was an error).
+
+ if( NULL != rgbstrblob )
+ {
+ for( nIndex = 0; nIndex < cElems; nIndex++ )
+ CoTaskMemFree( rgbstrblob[ nIndex ].pData );
+
+ CoTaskMemFree( rgbstrblob );
+ }
+
+ return( hr );
+
+} // PropVarMarshalBstrVector
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: PropVarUnmarshalBstrVector
+//
+// Synopsis: This routine converts a Propvariant from a
+// VT_BSTR_BLOB|VT_VECTOR to a VT_BSTR|VT_VECTOR.
+//
+// Pre-Conditions:
+// The input is a VT_BSTR_BLOB | VT_VECTOR.
+// The old memory may be freed.
+//
+// Inputs: [LPPROPVARIANT] lppropvar
+// The PropVariant to convert.
+//
+// Outputs: HRESULT
+//
+//+-------------------------------------------------------------------
+
+HRESULT
+PropVarUnmarshalBstrVector( LPPROPVARIANT lppropvar )
+{
+ // ------
+ // Locals
+ // ------
+
+ ULONG nIndex;
+ ULONG cElems;
+ LPBSTR rgbstr = NULL;
+ HRESULT hr = S_OK;
+
+ // -----
+ // Begin
+ // -----
+
+ cElems = lppropvar->cabstrblob.cElems;
+
+ // Allocate a new array of BSTRs.
+
+ rgbstr = CoTaskMemAlloc( cElems * sizeof(*rgbstr) );
+ if( NULL == rgbstr )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+ memset( rgbstr, 0, cElems * sizeof(*rgbstr) );
+
+
+ // Convert each of the buffers to BSTRs
+
+ for( nIndex = 0; nIndex < cElems; nIndex++ )
+ {
+ // Is this a NULL BSTR?
+
+ if( NULL == lppropvar->cabstrblob.pElems[nIndex].pData )
+ {
+ rgbstr[nIndex] = NULL;
+ }
+
+ // Otherwise, allocate a buffer for the BSTR fill it
+ // from the BSTRBLOB.
+
+ else
+ {
+
+ // We'll free the old buffer after we get out of this for loop.
+
+ rgbstr[nIndex]
+ = PrivSysAllocString(
+ SYSSTRINGOFBUF( lppropvar->cabstrblob.pElems[nIndex].pData )
+ );
+ if( NULL == rgbstr[nIndex] )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+ } // if( NULL == lppropvar->cabstrblob.pElems[nIndex].pData ) ... else
+ } // for( nIndex = 0; nIndex < cElems; nIndex++ )
+
+ // Free the BSTRBLOBs
+
+ for( nIndex = 0; nIndex < cElems; nIndex++ )
+ {
+ CoTaskMemFree( lppropvar->cabstrblob.pElems[nIndex].pData );
+ }
+
+ // Update the PropVariant with the new data.
+
+ lppropvar->vt = VT_BSTR | VT_VECTOR;
+ CoTaskMemFree( lppropvar->cabstrblob.pElems );
+ lppropvar->cabstr.pElems = rgbstr;
+ rgbstr = NULL;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // If there was an error, free what memory was
+ // allocated.
+
+ if( NULL != rgbstr )
+ {
+ for( nIndex = 0; nIndex < cElems; nIndex++ )
+ {
+ PrivSysFreeString( rgbstr[nIndex] );
+ }
+
+ CoTaskMemFree( rgbstr );
+ }
+
+ return( hr );
+
+} // PropVariantUnmarshalBstrVector
+
+
+
+//+-------------------------------------------------------------------
+//
+// Function: PropVarMarshal
+//
+// Synopsis: This routine is used by the IPropertyStorage wrappers.
+// We convert an array of PropVariants so that they are
+// remotable. This involves the conversion of BSTR
+// properties to a remotable type (BSTRBLOBs).
+//
+// Pre-Conditions:
+// The inputs must not be NULL.
+//
+// Inputs: [ULONG] cVariants
+// The size of the PropVariant array.
+// [LPPROPVARIANT] rgpropvar
+// The PropVariant to convert.
+//
+// Outputs: [HRESULT]
+// Whether or not there is an error, the
+// caller is responsible for freeing the
+// PropVariant[]
+//
+//+-------------------------------------------------------------------
+
+HRESULT
+PropVarMarshal( ULONG cVariants,
+ PROPVARIANT rgpropvar[] )
+{
+ // ------
+ // Locals
+ // ------
+
+ HRESULT hr = S_OK;
+ ULONG ulIndex;
+
+ // --------------------------------------------------------
+ // Walk through the PropVariant array, converting all BSTRs
+ // to BSTRBLOBs.
+ // --------------------------------------------------------
+
+ for( ulIndex = 0; ulIndex < cVariants; ulIndex++ )
+ {
+ switch( rgpropvar[ulIndex].vt )
+ {
+ // -------
+ // VT_BSTR
+ // -------
+
+ case VT_BSTR:
+
+ hr = PropVarMarshalBstr( &rgpropvar[ulIndex] );
+ if( FAILED(hr) ) goto Exit;
+ break;
+
+ // -------------------
+ // VT_BSTR | VT_VECTOR
+ // -------------------
+
+ case VT_BSTR | VT_VECTOR:
+
+ hr = PropVarMarshalBstrVector( &rgpropvar[ulIndex] );
+ if( FAILED(hr) ) goto Exit;
+ break;
+
+ // ----------------------
+ // VT_VARIANT | VT_VECTOR
+ // ----------------------
+
+ case VT_VARIANT | VT_VECTOR:
+
+ hr = PropVarMarshal( rgpropvar[ulIndex].capropvar.cElems,
+ rgpropvar[ulIndex].capropvar.pElems );
+ if( FAILED(hr) ) goto Exit;
+ break;
+
+ } // switch( rgpropvar[ulIndex].vt )
+ } // for( ulIndex = 0; ulIndex < cVariants; ulIndex++ )
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return( hr );
+
+} // PropVarMarshal()
+
+
+//+-----------------------------------------------------------------------
+//
+// Function: PropVarUnmarshal
+//
+// Synopsis: Unmarshal an array of PropVariants.
+// The BSTRs in the original PropVariant[]
+// were converted to BSTRBLOBs for the remoting
+// process.
+//
+// Inputs: [ULONG] cVariants
+// The number of elements in the PropVariant[]
+// [PROPVARIANT*] rgpropvar
+// The PropVariant[] to be unmarshaled
+//
+// Output: HRESULT
+// Whether or not there is an error, the
+// caller is responsible for freeing the
+// PropVariant[]
+//
+//+-----------------------------------------------------------------------
+
+HRESULT
+PropVarUnmarshal( ULONG cVariants,
+ PROPVARIANT rgpropvar[])
+{
+ // ------
+ // Locals
+ // ------
+
+ HRESULT hr = S_OK;
+ ULONG ulIndex;
+
+
+ // -------------------
+ // Unmarshal the array
+ // -------------------
+
+ for( ulIndex = 0; ulIndex < cVariants; ulIndex++ )
+ {
+
+ switch( rgpropvar[ ulIndex ].vt )
+ {
+ // ------------
+ // VT_BSTR_BLOB
+ // ------------
+
+ case VT_BSTR_BLOB:
+
+ hr = PropVarUnmarshalBstr( &rgpropvar[ ulIndex ] );
+ if( FAILED(hr) ) goto Exit;
+ break;
+
+ // ------------------------
+ // VT_BSTR_BLOB | VT_VECTOR
+ // ------------------------
+
+ case VT_BSTR_BLOB | VT_VECTOR:
+
+ hr = PropVarUnmarshalBstrVector( &rgpropvar[ ulIndex ] );
+ if( FAILED(hr) ) goto Exit;
+ break;
+
+ // ----------------------
+ // VT_VARIANT | VT_VECTOR
+ // ----------------------
+
+ case VT_VARIANT | VT_VECTOR:
+
+ hr = PropVarUnmarshal( rgpropvar[ ulIndex ].capropvar.cElems,
+ rgpropvar[ ulIndex ].capropvar.pElems );
+ if( FAILED(hr) ) goto Exit;
+ break;
+
+ } // switch( rgpropvar[ ulIndex ].vt )
+ } // for( ulIndex = 0; ulIndex < cVariants; ulIndex++ )
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return( hr );
+
+} // PropVarUnmarshal
+
+
+
diff --git a/private/ole32/stg/props/iprop/prstg_ca.h b/private/ole32/stg/props/iprop/prstg_ca.h
new file mode 100644
index 000000000..8b842af0d
--- /dev/null
+++ b/private/ole32/stg/props/iprop/prstg_ca.h
@@ -0,0 +1,67 @@
+
+
+//====================================================================
+//
+// File:
+// pstg_ca.h
+//
+// Purpose:
+// This file provides macros and prototypes for
+// the IPropertyStorage [call_as] helper functions.
+//
+//====================================================================
+
+#ifndef _PRSTG_CA_H_
+#define _PRSTG_CA_H_
+
+// --------
+// Includes
+// --------
+
+#include "ipropidl.h"
+
+// ------
+// Macros
+// ------
+
+// These macros are used to access BSTRs. BSTRs
+// are unicode strings which are preceded with a DWORD
+// of the byte-count. The strings are terminated with a NULL,
+// but the byte-count doesn't include it. A pointer to
+// a BSTR is a pointer to the first character, not to the
+// length DWORD.
+
+
+// Given a pointer to a BSTR buffer (i.e., a pointer to the
+// length DWORD) return a BSTR (i.e., a pointer to the first
+// character).
+
+#define SYSSTRINGOFBUF(buffer) ( (BSTR) ( (ULONG*)(buffer) + 1 ) )
+
+// Given a BSTR, return a pointer to the buffer (i.e., a pointer to
+// the length DWORD).
+
+#define SYSSTRINGBUF(bstr) ( (ULONG*)(bstr) - 1 )
+
+// Given a BSTR, return the character-count, not including the
+// NULL terminator.
+
+#define SYSSTRINGLEN(bstr) ( *SYSSTRINGBUF(bstr) / sizeof(WCHAR) )
+
+
+// ----------
+// Prototypes
+// ----------
+
+#define BSTR_EXISTS 1
+#define NONSIMPLE_EXISTS 2
+ULONG ContainsSpecialProperty( ULONG cElems, const PROPVARIANT rgpropvar[] );
+
+HRESULT PropVarMarshalBstr( LPPROPVARIANT lppropvar );
+HRESULT PropVarUnmarshalBstr( LPPROPVARIANT lppropvar );
+HRESULT PropVarMarshalBstrVector( LPPROPVARIANT lppropvar );
+HRESULT PropVarUnmarshalBstrVector( LPPROPVARIANT lppropvar );
+HRESULT PropVarMarshal( ULONG cElems, PROPVARIANT rgpropvar[] );
+HRESULT PropVarUnmarshal( ULONG cVariants, PROPVARIANT rgpropvarOriginal[]);
+
+#endif // !_PRSTG_CA_H_
diff --git a/private/ole32/stg/props/iprop/rpcbase.h b/private/ole32/stg/props/iprop/rpcbase.h
new file mode 100644
index 000000000..43b3a16c7
--- /dev/null
+++ b/private/ole32/stg/props/iprop/rpcbase.h
@@ -0,0 +1,34 @@
+/*++
+
+Copyright (c) 1991-1995 Microsoft Corporation
+
+Module Name:
+
+ rpcbase.h
+
+Abstract:
+
+ Basic definitions for OLE
+
+--*/
+
+#ifndef __RPCBASE_H__
+#define __RPCBASE_H__
+
+#if (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
+#define __RPC_FAR
+#define __RPC_API __stdcall
+#define __RPC_USER __stdcall
+#define __RPC_STUB __stdcall
+#define RPC_ENTRY __stdcall
+#else
+#define __RPC_FAR
+#define __RPC_API
+#define __RPC_USER
+#define __RPC_STUB
+#define RPC_ENTRY
+#endif
+
+typedef unsigned char byte;
+
+#endif // __RPCBASE_H__
diff --git a/private/ole32/stg/props/iprop/sources b/private/ole32/stg/props/iprop/sources
new file mode 100644
index 000000000..7bc92d8ea
--- /dev/null
+++ b/private/ole32/stg/props/iprop/sources
@@ -0,0 +1,90 @@
+!IF 0
+
+Copyright (c) 1995 Microsoft Corporation
+
+!ENDIF
+
+!include ..\..\..\daytona.inc
+
+# "daytona.inc" sets the UNICODE pre-processor defines, which we don't want,
+# so we'll noop them.
+C_DEFINES=$(C_DEFINES:UNICODE=NOT_UNICODE)
+
+# "daytona.inc" also sets USE_CRTDLL, which we don't want (since we want to
+# be compatible with Win95 & NT3.51).
+!ifdef USE_CRTDLL
+!undef USE_CRTDLL
+!endif
+
+MAJORCOMP= iprop
+MINORCOMP= iprop
+TARGETNAME= IProp
+TARGETPATH= $(BASEDIR)\public\sdk\lib
+TARGETTYPE= DYNLINK
+
+C_DEFINES= $(C_DEFINES) -DIPROPERTY_DLL -D_OLE32_
+LINKER_FLAGS=/MAP:temp.map
+
+INCLUDES= .;..;..\..;..\..\h;..\..\common;..\..\..\ih;..\..\..\..\inc;..\..\..\com\inc;..\..\exp
+
+SOURCES= \
+ iprop.rc \
+ dllmain.cxx \
+ call_as.c \
+ prstg_ca.c \
+ dlldata.c \
+ ipropidl_i.c \
+ ipropidl_p.c \
+ ..\propstm.cxx \
+ ..\ntprop.cxx \
+ ..\ntpropb.cxx \
+ ..\propstm.cxx \
+ ..\propvar.cxx \
+ ..\stgvarb.cxx \
+ ..\psetstg.cxx \
+ ..\propstg.cxx \
+ ..\utils.cxx \
+ ..\propapi.cxx \
+ ..\cfmapstm.cxx\
+ ..\reserved.cxx\
+ ..\privoa.cxx
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+DLLDEF= IProp.def
+DLLBASE= @$(BASEDIR)\public\sdk\lib\coffbase.txt,usermode
+DLLENTRY= _DllMainCRTStartup
+
+TARGETLIBS= $(BASEDIR)\public\sdk\lib\*\ole32.lib\
+ $(BASEDIR)\public\sdk\lib\*\oleaut32.lib\
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib\
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib\
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib\
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib
+
+
+USE_LIBCMT=1
+NTTARGETFILE0=allidl
+MIDL20=midl20.exe
+NTLEGO=1
+
+
+#
+# IProp requires the Version 2 MIDL compiler. So the MIDL exe file
+# is part of this project, with one copy for each version.
+#
+
+!IF $(386)
+MIDL20=midlx86.exe
+!ELSEIF $(MIPS)
+MIDL20=midlmips.exe
+!ELSEIF $(ALPHA)
+MIDL20=midlalph.exe
+!ELSEIF $(PPC)
+MIDL20=midlppc.exe
+!ELSE
+!ERROR Couldn't determine MIDL compiler.
+!ENDIF
+
+
diff --git a/private/ole32/stg/props/iprop/unknwn.h b/private/ole32/stg/props/iprop/unknwn.h
new file mode 100644
index 000000000..490679bf7
--- /dev/null
+++ b/private/ole32/stg/props/iprop/unknwn.h
@@ -0,0 +1,325 @@
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+/* File created by MIDL compiler version 2.00.0102 */
+/* at Fri Apr 28 07:02:30 1995
+ */
+//@@MIDL_FILE_HEADING( )
+#ifndef __RPCBASE_H__
+#include "rpcbase.h"
+#endif /* ___RPCBASE_H__ */
+#ifndef NORPC
+#ifndef __RPC_H__
+#include "rpc.h"
+#endif /* ___RPC_H__ */
+#ifndef __RPCNDR_H__
+#include "rpcndr.h"
+#endif /* __RPCNDR_H_ */
+#endif /* NORPC */
+#ifndef COM_NO_WINDOWS_H
+#ifndef _INC_WINDOWS
+#include "windows.h"
+#endif /* _INC_WINDOWS */
+#ifndef _OLE2_H_
+#include "ole2.h"
+#endif /* _OLE2_H_ */
+#endif /*COM_NO_WINDOWS_H*/
+
+#ifndef __unknwn_h__
+#define __unknwn_h__
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/* Forward Declarations */
+
+#ifndef __IUnknown_FWD_DEFINED__
+#define __IUnknown_FWD_DEFINED__
+typedef interface IUnknown IUnknown;
+#endif /* __IUnknown_FWD_DEFINED__ */
+
+
+#ifndef __IClassFactory_FWD_DEFINED__
+#define __IClassFactory_FWD_DEFINED__
+typedef interface IClassFactory IClassFactory;
+#endif /* __IClassFactory_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#ifndef __wtypes_h__
+#include "wtypes.h"
+#endif /* __wtypes_h__ */
+
+void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
+void __RPC_USER MIDL_user_free( void __RPC_FAR * );
+
+#ifndef __IUnknown_INTERFACE_DEFINED__
+#define __IUnknown_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IUnknown
+ * at Fri Apr 28 07:02:30 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object][local] */
+
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+//--------------------------------------------------------------------------
+ /* size is 4 */
+typedef /* [unique] */ IUnknown __RPC_FAR *LPUNKNOWN;
+
+//////////////////////////////////////////////////////////////////
+// IID_IUnknown and all other system IIDs are provided in UUID.LIB
+// Link that library in with your proxies, clients and servers
+//////////////////////////////////////////////////////////////////
+
+EXTERN_C const IID IID_IUnknown;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IUnknown
+ {
+ public:
+ virtual HRESULT __stdcall QueryInterface(
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject) = 0;
+
+ virtual ULONG __stdcall AddRef( void) = 0;
+
+ virtual ULONG __stdcall Release( void) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IUnknownVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IUnknown __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IUnknown __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IUnknown __RPC_FAR * This);
+
+ } IUnknownVtbl;
+
+ interface IUnknown
+ {
+ CONST_VTBL struct IUnknownVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IUnknown_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IUnknown_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IUnknown_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+HRESULT __stdcall IUnknown_QueryInterface_Proxy(
+ IUnknown __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+
+void __RPC_STUB IUnknown_QueryInterface_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+ULONG __stdcall IUnknown_AddRef_Proxy(
+ IUnknown __RPC_FAR * This);
+
+
+void __RPC_STUB IUnknown_AddRef_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+ULONG __stdcall IUnknown_Release_Proxy(
+ IUnknown __RPC_FAR * This);
+
+
+void __RPC_STUB IUnknown_Release_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif // NOPROXYSTUB
+
+#endif /* __IUnknown_INTERFACE_DEFINED__ */
+
+
+#ifndef __IClassFactory_INTERFACE_DEFINED__
+#define __IClassFactory_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IClassFactory
+ * at Fri Apr 28 07:02:30 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [unique][uuid][object] */
+
+
+ /* size is 4 */
+typedef /* [unique] */ IClassFactory __RPC_FAR *LPCLASSFACTORY;
+
+
+EXTERN_C const IID IID_IClassFactory;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IClassFactory : public IUnknown
+ {
+ public:
+ virtual /* [local] */ HRESULT __stdcall CreateInstance(
+ /* [unique][in] */ IUnknown __RPC_FAR *pUnkOuter,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject) = 0;
+
+ virtual HRESULT __stdcall LockServer(
+ /* [in] */ BOOL fLock) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IClassFactoryVtbl
+ {
+
+ HRESULT ( __stdcall __RPC_FAR *QueryInterface )(
+ IClassFactory __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( __stdcall __RPC_FAR *AddRef )(
+ IClassFactory __RPC_FAR * This);
+
+ ULONG ( __stdcall __RPC_FAR *Release )(
+ IClassFactory __RPC_FAR * This);
+
+ /* [local] */ HRESULT ( __stdcall __RPC_FAR *CreateInstance )(
+ IClassFactory __RPC_FAR * This,
+ /* [unique][in] */ IUnknown __RPC_FAR *pUnkOuter,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ HRESULT ( __stdcall __RPC_FAR *LockServer )(
+ IClassFactory __RPC_FAR * This,
+ /* [in] */ BOOL fLock);
+
+ } IClassFactoryVtbl;
+
+ interface IClassFactory
+ {
+ CONST_VTBL struct IClassFactoryVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IClassFactory_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IClassFactory_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IClassFactory_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IClassFactory_CreateInstance(This,pUnkOuter,riid,ppvObject) \
+ (This)->lpVtbl -> CreateInstance(This,pUnkOuter,riid,ppvObject)
+
+#define IClassFactory_LockServer(This,fLock) \
+ (This)->lpVtbl -> LockServer(This,fLock)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+#ifndef NOPROXYSTUB
+
+/* [call_as] */ HRESULT __stdcall IClassFactory_RemoteCreateInstance_Proxy(
+ IClassFactory __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppvObject);
+
+
+void __RPC_STUB IClassFactory_RemoteCreateInstance_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT __stdcall IClassFactory_LockServer_Proxy(
+ IClassFactory __RPC_FAR * This,
+ /* [in] */ BOOL fLock);
+
+
+void __RPC_STUB IClassFactory_LockServer_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+#endif //NOPROXYSTUB
+
+#endif /* __IClassFactory_INTERFACE_DEFINED__ */
+
+
+/* Additional Prototypes for ALL interfaces */
+
+/* [local] */ HRESULT __stdcall IClassFactory_CreateInstance_Proxy(
+ IClassFactory __RPC_FAR * This,
+ /* [unique][in] */ IUnknown __RPC_FAR *pUnkOuter,
+ /* [in] */ REFIID riid,
+ /* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+
+/* [call_as] */ HRESULT __stdcall IClassFactory_CreateInstance_Stub(
+ IClassFactory __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppvObject);
+
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/ole32/stg/props/iprop/unknwn.idl b/private/ole32/stg/props/iprop/unknwn.idl
new file mode 100644
index 000000000..0c3e5bb3b
--- /dev/null
+++ b/private/ole32/stg/props/iprop/unknwn.idl
@@ -0,0 +1,76 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: unknwn.idl
+//
+// Contents: IUnknown interface definition
+//
+//
+//--------------------------------------------------------------------------
+
+#ifndef DO_NO_IMPORTS
+import "wtypes.idl";
+#endif
+
+[
+ local,
+ object,
+ uuid(00000000-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IUnknown
+{
+cpp_quote("//+-------------------------------------------------------------------------")
+cpp_quote("//")
+cpp_quote("// Microsoft Windows")
+cpp_quote("// Copyright (C) Microsoft Corporation, 1992 - 1995.")
+cpp_quote("//")
+cpp_quote("//--------------------------------------------------------------------------")
+
+
+ typedef [unique] IUnknown *LPUNKNOWN;
+
+cpp_quote("//////////////////////////////////////////////////////////////////" )
+cpp_quote("// IID_IUnknown and all other system IIDs are provided in UUID.LIB" )
+cpp_quote("// Link that library in with your proxies, clients and servers")
+cpp_quote("//////////////////////////////////////////////////////////////////" )
+
+ HRESULT QueryInterface(
+ [in] REFIID riid,
+ [out] void **ppvObject);
+
+ ULONG AddRef();
+
+ ULONG Release();
+}
+
+[
+ object,
+ uuid(00000001-0000-0000-C000-000000000046),
+ pointer_default(unique)
+]
+
+interface IClassFactory : IUnknown
+{
+
+ typedef [unique] IClassFactory *LPCLASSFACTORY;
+
+ [local]
+ HRESULT __stdcall CreateInstance(
+ [in, unique] IUnknown *pUnkOuter,
+ [in] REFIID riid,
+ [out] void **ppvObject);
+
+ [call_as(CreateInstance)]
+ HRESULT __stdcall RemoteCreateInstance(
+ [in] REFIID riid,
+ [out, iid_is(riid)] IUnknown **ppvObject);
+
+ HRESULT LockServer(
+ [in] BOOL fLock);
+}
+
+
diff --git a/private/ole32/stg/props/iprop/wtypes.h b/private/ole32/stg/props/iprop/wtypes.h
new file mode 100644
index 000000000..2116d149c
--- /dev/null
+++ b/private/ole32/stg/props/iprop/wtypes.h
@@ -0,0 +1,848 @@
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+/* File created by MIDL compiler version 2.00.0102 */
+/* at Fri Apr 28 07:02:29 1995
+ */
+//@@MIDL_FILE_HEADING( )
+#ifndef __RPCBASE_H__
+#include "rpcbase.h"
+#endif /* ___RPCBASE_H__ */
+#ifndef NORPC
+#ifndef __RPC_H__
+#include "rpc.h"
+#endif /* ___RPC_H__ */
+#ifndef __RPCNDR_H__
+#include "rpcndr.h"
+#endif /* __RPCNDR_H_ */
+#endif /* NORPC */
+
+#ifndef __wtypes_h__
+#define __wtypes_h__
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/* Forward Declarations */
+
+void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
+void __RPC_USER MIDL_user_free( void __RPC_FAR * );
+
+#ifndef __IWinTypes_INTERFACE_DEFINED__
+#define __IWinTypes_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IWinTypes
+ * at Fri Apr 28 07:02:29 1995
+ * using MIDL 2.00.0102
+ ****************************************/
+/* [auto_handle][unique][version][uuid] */
+
+
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+//--------------------------------------------------------------------------
+ /* size is 8 */
+typedef struct tagRemHGLOBAL
+ {
+ long fNullHGlobal;
+ unsigned long cbData;
+ /* [size_is] */ byte data[ 1 ];
+ } RemHGLOBAL;
+
+ /* size is 16 */
+typedef struct tagRemHMETAFILEPICT
+ {
+ long mm;
+ long xExt;
+ long yExt;
+ unsigned long cbData;
+ /* [size_is] */ byte data[ 1 ];
+ } RemHMETAFILEPICT;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HMETAFILEPICT;
+
+ /* size is 4 */
+typedef struct tagRemHENHMETAFILE
+ {
+ unsigned long cbData;
+ /* [size_is] */ byte data[ 1 ];
+ } RemHENHMETAFILE;
+
+ /* size is 4 */
+typedef struct tagRemHBITMAP
+ {
+ unsigned long cbData;
+ /* [size_is] */ byte data[ 1 ];
+ } RemHBITMAP;
+
+ /* size is 4 */
+typedef struct tagRemHPALETTE
+ {
+ unsigned long cbData;
+ /* [size_is] */ byte data[ 1 ];
+ } RemHPALETTE;
+
+ /* size is 4 */
+typedef struct tagRemBRUSH
+ {
+ unsigned long cbData;
+ /* [size_is] */ byte data[ 1 ];
+ } RemHBRUSH;
+
+#ifndef _WIN32 // The following code is for Win16 only
+#ifndef WINAPI // If not included with 3.1 headers...
+#define FAR _far
+#define PASCAL _pascal
+#define CDECL _cdecl
+#define VOID void
+#define WINAPI FAR PASCAL
+#define CALLBACK FAR PASCAL
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif // !FALSE
+#ifndef _BYTE_DEFINED
+#define _BYTE_DEFINED
+ /* size is 1 */
+typedef unsigned char BYTE;
+
+#endif // !_BYTE_DEFINED
+#ifndef _WORD_DEFINED
+#define _WORD_DEFINED
+ /* size is 2 */
+typedef unsigned short WORD;
+
+#endif // !_WORD_DEFINED
+ /* size is 4 */
+typedef /* [transmit] */ unsigned int UINT;
+
+ /* size is 4 */
+typedef /* [transmit] */ int INT;
+
+ /* size is 4 */
+typedef long BOOL;
+
+#ifndef _LONG_DEFINED
+#define _LONG_DEFINED
+ /* size is 4 */
+typedef long LONG;
+
+#endif // !_LONG_DEFINED
+#ifndef _WPARAM_DEFINED
+#define _WPARAM_DEFINED
+ /* size is 4 */
+typedef UINT WPARAM;
+
+#endif // _WPARAM_DEFINED
+#ifndef _DWORD_DEFINED
+#define _DWORD_DEFINED
+ /* size is 4 */
+typedef unsigned long DWORD;
+
+#endif // !_DWORD_DEFINED
+#ifndef _LPARAM_DEFINED
+#define _LPARAM_DEFINED
+ /* size is 4 */
+typedef LONG LPARAM;
+
+#endif // !_LPARAM_DEFINED
+#ifndef _LRESULT_DEFINED
+#define _LRESULT_DEFINED
+ /* size is 4 */
+typedef LONG LRESULT;
+
+#endif // !_LRESULT_DEFINED
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HANDLE;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HMODULE;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HINSTANCE;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HICON;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HFONT;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HGLOBAL;
+
+ /* size is 4 */
+typedef HGLOBAL HLOCAL;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HBITMAP;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HPALETTE;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HBRUSH;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HENHMETAFILE;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HDC;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HRGN;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HWND;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HMENU;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HACCEL;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HTASK;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HKEY;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HDESK;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HMF;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HEMF;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HMETAFILE;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HPEN;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HRSRC;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HSTR;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HWINSTA;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HKL;
+
+ /* size is 4 */
+typedef /* [transmit] */ void __RPC_FAR *HGDIOBJ;
+
+ /* size is 4 */
+typedef HANDLE HDWP;
+
+#ifndef _HFILE_DEFINED
+#define _HFILE_DEFINED
+ /* size is 4 */
+typedef INT HFILE;
+
+#endif // !_HFILE_DEFINED
+#ifndef _HCURSOR_DEFINED
+#define _HCURSOR_DEFINED
+ /* size is 4 */
+typedef HICON HCURSOR;
+
+#endif // !_HCURSOR_DEFINED
+#ifndef _LPWORD_DEFINED
+#define _LPWORD_DEFINED
+ /* size is 4 */
+typedef WORD __RPC_FAR *LPWORD;
+
+#endif // !_LPWORD_DEFINED
+#ifndef _LPDWORD_DEFINED
+#define _LPDWORD_DEFINED
+ /* size is 4 */
+typedef DWORD __RPC_FAR *LPDWORD;
+
+#endif // !_LPDWORD_DEFINED
+ /* size is 4 */
+typedef /* [string] */ char __RPC_FAR *LPSTR;
+
+ /* size is 4 */
+typedef /* [string] */ const char __RPC_FAR *LPCSTR;
+
+#ifndef _WCHAR_DEFINED
+#define _WCHAR_DEFINED
+ /* size is 2 */
+typedef wchar_t WCHAR;
+
+ /* size is 2 */
+typedef WCHAR TCHAR;
+
+#endif // !_WCHAR_DEFINED
+ /* size is 4 */
+typedef /* [string] */ WCHAR __RPC_FAR *LPWSTR;
+
+ /* size is 4 */
+typedef /* [string] */ TCHAR __RPC_FAR *LPTSTR;
+
+ /* size is 4 */
+typedef /* [string] */ const WCHAR __RPC_FAR *LPCWSTR;
+
+ /* size is 4 */
+typedef /* [string] */ const TCHAR __RPC_FAR *LPCTSTR;
+
+ /* size is 4 */
+typedef struct tagPALETTEENTRY
+ {
+ BYTE peRed;
+ BYTE peGreen;
+ BYTE peBlue;
+ BYTE peFlags;
+ } PALETTEENTRY;
+
+ /* size is 4 */
+typedef struct tagPALETTEENTRY __RPC_FAR *PPALETTEENTRY;
+
+ /* size is 4 */
+typedef struct tagPALETTEENTRY __RPC_FAR *LPPALETTEENTRY;
+
+#if 0
+ /* size is 4 */
+typedef struct tagLOGPALETTE
+ {
+ WORD palVersion;
+ WORD palNumEntries;
+ /* [size_is] */ PALETTEENTRY palPalEntry[ 1 ];
+ } LOGPALETTE;
+
+ /* size is 4 */
+typedef struct tagLOGPALETTE __RPC_FAR *PLOGPALETTE;
+
+ /* size is 4 */
+typedef struct tagLOGPALETTE __RPC_FAR *LPLOGPALETTE;
+
+#else
+typedef struct tagLOGPALETTE {
+ WORD palVersion;
+ WORD palNumEntries;
+ PALETTEENTRY palPalEntry[1];
+} LOGPALETTE, *PLOGPALETTE, *LPLOGPALETTE;
+#endif
+#ifndef _COLORREF_DEFINED
+#define _COLORREF_DEFINED
+ /* size is 4 */
+typedef DWORD COLORREF;
+
+#endif // !_COLORREF_DEFINED
+#ifndef _LPCOLORREF_DEFINED
+#define _LPCOLORREF_DEFINED
+ /* size is 4 */
+typedef DWORD __RPC_FAR *LPCOLORREF;
+
+#endif // !_LPCOLORREF_DEFINED
+ /* size is 4 */
+typedef HANDLE __RPC_FAR *LPHANDLE;
+
+ /* size is 16 */
+typedef struct _RECTL
+ {
+ LONG left;
+ LONG top;
+ LONG right;
+ LONG bottom;
+ } RECTL;
+
+ /* size is 4 */
+typedef struct _RECTL __RPC_FAR *PRECTL;
+
+ /* size is 4 */
+typedef struct _RECTL __RPC_FAR *LPRECTL;
+
+ /* size is 8 */
+typedef struct tagPOINT
+ {
+ LONG x;
+ LONG y;
+ } POINT;
+
+ /* size is 4 */
+typedef struct tagPOINT __RPC_FAR *PPOINT;
+
+ /* size is 4 */
+typedef struct tagPOINT __RPC_FAR *LPPOINT;
+
+ /* size is 8 */
+typedef struct _POINTL
+ {
+ LONG x;
+ LONG y;
+ } POINTL;
+
+ /* size is 4 */
+typedef struct _POINTL __RPC_FAR *PPOINTL;
+
+#ifndef WIN16
+ /* size is 8 */
+typedef struct tagSIZE
+ {
+ LONG cx;
+ LONG cy;
+ } SIZE;
+
+ /* size is 4 */
+typedef struct tagSIZE __RPC_FAR *PSIZE;
+
+ /* size is 4 */
+typedef struct tagSIZE __RPC_FAR *LPSIZE;
+
+#else // WIN16
+typedef struct tagSIZE
+{
+ INT cx;
+ INT cy;
+} SIZE, *PSIZE, *LPSIZE;
+#endif // WIN16
+ /* size is 28 */
+typedef struct tagMSG
+ {
+ HWND hwnd;
+ UINT message;
+ WPARAM wParam;
+ LPARAM lParam;
+ DWORD time;
+ POINT pt;
+ } MSG;
+
+ /* size is 4 */
+typedef struct tagMSG __RPC_FAR *PMSG;
+
+ /* size is 4 */
+typedef struct tagMSG __RPC_FAR *NPMSG;
+
+ /* size is 4 */
+typedef struct tagMSG __RPC_FAR *LPMSG;
+
+ /* size is 8 */
+typedef struct tagSIZEL
+ {
+ LONG cx;
+ LONG cy;
+ } SIZEL;
+
+ /* size is 4 */
+typedef struct tagSIZEL __RPC_FAR *PSIZEL;
+
+ /* size is 4 */
+typedef struct tagSIZEL __RPC_FAR *LPSIZEL;
+
+#endif //WINAPI
+#endif //!WIN32
+#if defined(_WIN32) && !defined(OLE2ANSI)
+ /* size is 2 */
+typedef WCHAR OLECHAR;
+
+ /* size is 4 */
+typedef /* [string] */ OLECHAR __RPC_FAR *LPOLESTR;
+
+ /* size is 4 */
+typedef /* [string] */ const OLECHAR __RPC_FAR *LPCOLESTR;
+
+#define OLESTR(str) L##str
+#else
+typedef char OLECHAR;
+typedef LPSTR LPOLESTR;
+typedef LPCSTR LPCOLESTR;
+#define OLESTR(str) str
+#endif
+#ifndef _WINDEF_
+ /* size is 4 */
+typedef const RECTL __RPC_FAR *LPCRECTL;
+
+ /* size is 4 */
+typedef void __RPC_FAR *PVOID;
+
+ /* size is 4 */
+typedef void __RPC_FAR *LPVOID;
+
+ /* size is 16 */
+typedef struct tagRECT
+ {
+ LONG left;
+ LONG top;
+ LONG right;
+ LONG bottom;
+ } RECT;
+
+ /* size is 4 */
+typedef struct tagRECT __RPC_FAR *PRECT;
+
+ /* size is 4 */
+typedef struct tagRECT __RPC_FAR *LPRECT;
+
+ /* size is 4 */
+typedef const RECT __RPC_FAR *LPCRECT;
+
+#endif //_WINDEF_
+ /* size is 1 */
+typedef unsigned char UCHAR;
+
+ /* size is 2 */
+typedef short SHORT;
+
+ /* size is 2 */
+typedef unsigned short USHORT;
+
+ /* size is 4 */
+typedef DWORD ULONG;
+
+#if 0
+ /* size is 8 */
+typedef hyper LONGLONG;
+
+ /* size is 8 */
+typedef MIDL_uhyper ULONGLONG;
+
+ /* size is 4 */
+typedef LONGLONG __RPC_FAR *PLONGLONG;
+
+ /* size is 4 */
+typedef ULONGLONG __RPC_FAR *PULONGLONG;
+
+ /* size is 8 */
+typedef struct _LARGE_INTEGER
+ {
+ LONGLONG QuadPart;
+ } LARGE_INTEGER;
+
+ /* size is 4 */
+typedef LARGE_INTEGER __RPC_FAR *PLARGE_INTEGER;
+
+ /* size is 8 */
+typedef struct _ULARGE_INTEGER
+ {
+ ULONGLONG QuadPart;
+ } ULARGE_INTEGER;
+
+#endif //
+#ifndef _WINBASE_
+#ifndef _FILETIME_
+#define _FILETIME_
+ /* size is 8 */
+typedef struct _FILETIME
+ {
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+ } FILETIME;
+
+ /* size is 4 */
+typedef struct _FILETIME __RPC_FAR *PFILETIME;
+
+ /* size is 4 */
+typedef struct _FILETIME __RPC_FAR *LPFILETIME;
+
+#endif // !_FILETIME
+#ifndef _SYSTEMTIME_
+#define _SYSTEMTIME_
+ /* size is 16 */
+typedef struct _SYSTEMTIME
+ {
+ WORD wYear;
+ WORD wMonth;
+ WORD wDayOfWeek;
+ WORD wDay;
+ WORD wHour;
+ WORD wMinute;
+ WORD wSecond;
+ WORD wMilliseconds;
+ } SYSTEMTIME;
+
+ /* size is 4 */
+typedef struct _SYSTEMTIME __RPC_FAR *PSYSTEMTIME;
+
+ /* size is 4 */
+typedef struct _SYSTEMTIME __RPC_FAR *LPSYSTEMTIME;
+
+#endif // !_SYSTEMTIME
+#ifndef _SECURITY_ATTRIBUTES_
+#define _SECURITY_ATTRIBUTES_
+ /* size is 12 */
+typedef struct _SECURITY_ATTRIBUTES
+ {
+ DWORD nLength;
+ /* [size_is] */ LPVOID lpSecurityDescriptor;
+ BOOL bInheritHandle;
+ } SECURITY_ATTRIBUTES;
+
+ /* size is 4 */
+typedef struct _SECURITY_ATTRIBUTES __RPC_FAR *PSECURITY_ATTRIBUTES;
+
+ /* size is 4 */
+typedef struct _SECURITY_ATTRIBUTES __RPC_FAR *LPSECURITY_ATTRIBUTES;
+
+#endif // !_SECURITY_ATTRIBUTES_
+#ifndef SECURITY_DESCRIPTOR_REVISION
+ /* size is 2 */
+typedef USHORT SECURITY_DESCRIPTOR_CONTROL;
+
+ /* size is 4 */
+typedef USHORT __RPC_FAR *PSECURITY_DESCRIPTOR_CONTROL;
+
+ /* size is 4 */
+typedef PVOID PSID;
+
+ /* size is 8 */
+typedef struct _ACL
+ {
+ UCHAR AclRevision;
+ UCHAR Sbz1;
+ USHORT AclSize;
+ USHORT AceCount;
+ USHORT Sbz2;
+ } ACL;
+
+ /* size is 4 */
+typedef ACL __RPC_FAR *PACL;
+
+ /* size is 20 */
+typedef struct _SECURITY_DESCRIPTOR
+ {
+ UCHAR Revision;
+ UCHAR Sbz1;
+ SECURITY_DESCRIPTOR_CONTROL Control;
+ PSID Owner;
+ PSID Group;
+ PACL Sacl;
+ PACL Dacl;
+ } SECURITY_DESCRIPTOR;
+
+ /* size is 4 */
+typedef struct _SECURITY_DESCRIPTOR __RPC_FAR *PISECURITY_DESCRIPTOR;
+
+#endif // !SECURITY_DESCRIPTOR_REVISION
+#endif //_WINBASE_
+ /* size is 4 */
+typedef LONG SCODE;
+
+ /* size is 4 */
+typedef LONG HRESULT;
+
+ /* size is 4 */
+typedef SCODE __RPC_FAR *PSCODE;
+
+#ifndef GUID_DEFINED
+#define GUID_DEFINED
+ /* size is 16 */
+typedef struct _GUID
+ {
+ DWORD Data1;
+ WORD Data2;
+ WORD Data3;
+ BYTE Data4[ 8 ];
+ } GUID;
+
+#endif // !GUID_DEFINED
+#if !defined( __LPGUID_DEFINED__ )
+#define __LPGUID_DEFINED__
+ /* size is 4 */
+typedef GUID __RPC_FAR *LPGUID;
+
+#endif // !__LPGUID_DEFINED__
+#ifndef __OBJECTID_DEFINED
+#define __OBJECTID_DEFINED
+#define _OBJECTID_DEFINED
+ /* size is 20 */
+typedef struct _OBJECTID
+ {
+ GUID Lineage;
+ unsigned long Uniquifier;
+ } OBJECTID;
+
+#endif // !_OBJECTID_DEFINED
+#if !defined( __IID_DEFINED__ )
+#define __IID_DEFINED__
+ /* size is 16 */
+typedef GUID IID;
+
+ /* size is 4 */
+typedef IID __RPC_FAR *LPIID;
+
+#define IID_NULL GUID_NULL
+#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2)
+ /* size is 16 */
+typedef GUID CLSID;
+
+ /* size is 4 */
+typedef CLSID __RPC_FAR *LPCLSID;
+
+#define CLSID_NULL GUID_NULL
+#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2)
+#if 0
+ /* size is 4 */
+typedef GUID __RPC_FAR *REFGUID;
+
+ /* size is 4 */
+typedef IID __RPC_FAR *REFIID;
+
+ /* size is 4 */
+typedef CLSID __RPC_FAR *REFCLSID;
+
+#endif // 0
+#if defined(__cplusplus)
+#ifndef _REFGUID_DEFINED
+#define _REFGUID_DEFINED
+#define REFGUID const GUID &
+#endif // !_REFGUID_DEFINED
+#ifndef _REFIID_DEFINED
+#define _REFIID_DEFINED
+#define REFIID const IID &
+#endif // !_REFIID_DEFINED
+#ifndef _REFCLSID_DEFINED
+#define _REFCLSID_DEFINED
+#define REFCLSID const CLSID &
+#endif // !_REFCLSID_DEFINED
+#else // !__cplusplus
+#ifndef _REFGUID_DEFINED
+#define _REFGUID_DEFINED
+#define REFGUID const GUID * const
+#endif // !_REFGUID_DEFINED
+#ifndef _REFIID_DEFINED
+#define _REFIID_DEFINED
+#define REFIID const IID * const
+#endif // !_REFIID_DEFINED
+#ifndef _REFCLSID_DEFINED
+#define _REFCLSID_DEFINED
+#define REFCLSID const CLSID * const
+#endif // !_REFCLSID_DEFINED
+#endif // !__cplusplus
+#endif // !__IID_DEFINED__
+ /* size is 2 */
+typedef
+enum tagMEMCTX
+ { MEMCTX_TASK = 1,
+ MEMCTX_SHARED = 2,
+ MEMCTX_MACSYSTEM = 3,
+ MEMCTX_UNKNOWN = -1,
+ MEMCTX_SAME = -2
+ } MEMCTX;
+
+#ifndef _ROTFLAGS_DEFINED
+#define _ROTFLAGS_DEFINED
+#define ROTFLAGS_REGISTRATIONKEEPSALIVE 1
+#endif // !_ROTFLAGS_DEFINED
+#ifndef _ROT_COMPARE_MAX_DEFINED
+#define _ROT_COMPARE_MAX_DEFINED
+#define ROT_COMPARE_MAX 2048
+#endif // !_ROT_COMPARE_MAX_DEFINED
+ /* size is 2 */
+typedef
+enum tagCLSCTX
+ { CLSCTX_INPROC_SERVER = 1,
+ CLSCTX_INPROC_HANDLER = 2,
+ CLSCTX_LOCAL_SERVER = 4,
+ CLSCTX_INPROC_SERVER16 = 8
+ } CLSCTX;
+
+ /* size is 2 */
+typedef
+enum tagMSHLFLAGS
+ { MSHLFLAGS_NORMAL = 0,
+ MSHLFLAGS_TABLESTRONG = 1,
+ MSHLFLAGS_TABLEWEAK = 2
+ } MSHLFLAGS;
+
+ /* size is 2 */
+typedef
+enum tagMSHCTX
+ { MSHCTX_LOCAL = 0,
+ MSHCTX_NOSHAREDMEM = 1,
+ MSHCTX_DIFFERENTMACHINE = 2,
+ MSHCTX_INPROC = 3
+ } MSHCTX;
+
+ /* size is 2 */
+typedef
+enum tagDVASPECT
+ { DVASPECT_CONTENT = 1,
+ DVASPECT_THUMBNAIL = 2,
+ DVASPECT_ICON = 4,
+ DVASPECT_DOCPRINT = 8
+ } DVASPECT;
+
+ /* size is 2 */
+typedef
+enum tagSTGC
+ { STGC_DEFAULT = 0,
+ STGC_OVERWRITE = 1,
+ STGC_ONLYIFCURRENT = 2,
+ STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4
+ } STGC;
+
+ /* size is 2 */
+typedef
+enum tagSTGMOVE
+ { STGMOVE_MOVE = 0,
+ STGMOVE_COPY = 1
+ } STGMOVE;
+
+ /* size is 2 */
+typedef
+enum tagSTATFLAG
+ { STATFLAG_DEFAULT = 0,
+ STATFLAG_NONAME = 1
+ } STATFLAG;
+
+ /* size is 4 */
+typedef /* [context_handle] */ void __RPC_FAR *HCONTEXT;
+
+#ifndef _LCID_DEFINED
+#define _LCID_DEFINED
+ /* size is 4 */
+typedef DWORD LCID;
+
+#endif // !_LCID_DEFINED
+#ifndef NORPC
+void __RPC_API HGLOBAL_to_xmit (HGLOBAL __RPC_FAR *, RemHGLOBAL __RPC_FAR * __RPC_FAR *);
+void __RPC_API HGLOBAL_from_xmit (RemHGLOBAL __RPC_FAR *, HGLOBAL __RPC_FAR *);
+void __RPC_API HGLOBAL_free_inst (HGLOBAL __RPC_FAR *);
+void __RPC_API HGLOBAL_free_xmit (RemHGLOBAL __RPC_FAR *);
+void __RPC_API HBITMAP_to_xmit (HBITMAP __RPC_FAR *, RemHBITMAP __RPC_FAR * __RPC_FAR *);
+void __RPC_API HBITMAP_from_xmit (RemHBITMAP __RPC_FAR *, HBITMAP __RPC_FAR *);
+void __RPC_API HBITMAP_free_inst (HBITMAP __RPC_FAR *);
+void __RPC_API HBITMAP_free_xmit (RemHBITMAP __RPC_FAR *);
+void __RPC_API HPALETTE_to_xmit (HPALETTE __RPC_FAR *, RemHPALETTE __RPC_FAR * __RPC_FAR *);
+void __RPC_API HPALETTE_from_xmit (RemHPALETTE __RPC_FAR *, HPALETTE __RPC_FAR *);
+void __RPC_API HPALETTE_free_inst (HPALETTE __RPC_FAR *);
+void __RPC_API HPALETTE_free_xmit (RemHPALETTE __RPC_FAR *);
+void __RPC_API HBRUSH_to_xmit (HBRUSH __RPC_FAR *, RemHBRUSH __RPC_FAR * __RPC_FAR *);
+void __RPC_API HBRUSH_from_xmit (RemHBRUSH __RPC_FAR *, HBRUSH __RPC_FAR *);
+void __RPC_API HBRUSH_free_inst (HBRUSH __RPC_FAR *);
+void __RPC_API HBRUSH_free_xmit (RemHBRUSH __RPC_FAR *);
+void __RPC_API HMETAFILEPICT_to_xmit (HMETAFILEPICT __RPC_FAR *, RemHMETAFILEPICT __RPC_FAR * __RPC_FAR *);
+void __RPC_API HMETAFILEPICT_from_xmit (RemHMETAFILEPICT __RPC_FAR *, HMETAFILEPICT __RPC_FAR *);
+void __RPC_API HMETAFILEPICT_free_inst (HMETAFILEPICT __RPC_FAR *);
+void __RPC_API HMETAFILEPICT_free_xmit (RemHMETAFILEPICT __RPC_FAR *);
+void __RPC_API HENHMETAFILE_to_xmit (HENHMETAFILE __RPC_FAR *, RemHENHMETAFILE __RPC_FAR * __RPC_FAR *);
+void __RPC_API HENHMETAFILE_from_xmit (RemHENHMETAFILE __RPC_FAR *, HENHMETAFILE __RPC_FAR *);
+void __RPC_API HENHMETAFILE_free_inst (HENHMETAFILE __RPC_FAR *);
+void __RPC_API HENHMETAFILE_free_xmit (RemHENHMETAFILE __RPC_FAR *);
+
+
+extern RPC_IF_HANDLE IWinTypes_v0_1_c_ifspec;
+extern RPC_IF_HANDLE IWinTypes_v0_1_s_ifspec;
+#endif // NORPC
+#endif /* __IWinTypes_INTERFACE_DEFINED__ */
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/ole32/stg/props/iprop/wtypes.idl b/private/ole32/stg/props/iprop/wtypes.idl
new file mode 100644
index 000000000..e3ede6c3f
--- /dev/null
+++ b/private/ole32/stg/props/iprop/wtypes.idl
@@ -0,0 +1,729 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: wtypes.idl
+//
+// Contents: This interface definition contains typedefs for remotable
+// data types.
+//
+//--------------------------------------------------------------------------
+
+[ uuid(D3980A60-910C-1068-9341-00DD010F2F1C),
+ version(0.1), pointer_default(unique) ]
+
+interface IWinTypes
+{
+
+cpp_quote("//+-------------------------------------------------------------------------")
+cpp_quote("//")
+cpp_quote("// Microsoft Windows")
+cpp_quote("// Copyright (C) Microsoft Corporation, 1992 - 1995.")
+cpp_quote("//")
+cpp_quote("//--------------------------------------------------------------------------")
+
+typedef struct tagRemHGLOBAL
+{
+ long fNullHGlobal;
+ unsigned long cbData;
+ [size_is(cbData)] byte data[];
+} RemHGLOBAL;
+
+typedef struct tagRemHMETAFILEPICT
+{
+ long mm;
+ long xExt;
+ long yExt;
+ unsigned long cbData;
+ [size_is(cbData)] byte data[];
+} RemHMETAFILEPICT;
+
+typedef [transmit_as(RemHMETAFILEPICT)] void * HMETAFILEPICT;
+
+typedef struct tagRemHENHMETAFILE
+{
+ unsigned long cbData;
+ [size_is(cbData)] byte data[];
+} RemHENHMETAFILE;
+
+typedef struct tagRemHBITMAP
+{
+ unsigned long cbData;
+ [size_is(cbData)] byte data[];
+} RemHBITMAP;
+
+typedef struct tagRemHPALETTE
+{
+ unsigned long cbData;
+ [size_is(cbData)] byte data[];
+} RemHPALETTE;
+
+typedef struct tagRemBRUSH
+{
+ unsigned long cbData;
+ [size_is(cbData)] byte data[];
+} RemHBRUSH;
+
+
+cpp_quote("#ifndef _WIN32 // The following code is for Win16 only")
+cpp_quote("#ifndef WINAPI // If not included with 3.1 headers... ")
+
+cpp_quote("#define FAR _far")
+cpp_quote("#define PASCAL _pascal")
+cpp_quote("#define CDECL _cdecl")
+
+cpp_quote("#define VOID void")
+cpp_quote("#define WINAPI FAR PASCAL")
+cpp_quote("#define CALLBACK FAR PASCAL")
+
+
+
+cpp_quote("#ifndef FALSE")
+cpp_quote("#define FALSE 0")
+cpp_quote("#define TRUE 1")
+cpp_quote("#endif // !FALSE")
+
+cpp_quote("#ifndef _BYTE_DEFINED")
+cpp_quote("#define _BYTE_DEFINED")
+typedef unsigned char BYTE;
+cpp_quote("#endif // !_BYTE_DEFINED")
+
+cpp_quote("#ifndef _WORD_DEFINED")
+cpp_quote("#define _WORD_DEFINED")
+typedef unsigned short WORD;
+cpp_quote("#endif // !_WORD_DEFINED")
+
+typedef [transmit_as(unsigned long)] unsigned int UINT;
+typedef [transmit_as(long)] int INT;
+typedef long BOOL;
+
+cpp_quote("#ifndef _LONG_DEFINED")
+cpp_quote("#define _LONG_DEFINED")
+typedef long LONG;
+cpp_quote("#endif // !_LONG_DEFINED")
+
+cpp_quote("#ifndef _WPARAM_DEFINED")
+cpp_quote("#define _WPARAM_DEFINED")
+typedef UINT WPARAM;
+cpp_quote("#endif // _WPARAM_DEFINED")
+
+cpp_quote("#ifndef _DWORD_DEFINED")
+cpp_quote("#define _DWORD_DEFINED")
+typedef unsigned long DWORD;
+cpp_quote("#endif // !_DWORD_DEFINED")
+
+cpp_quote("#ifndef _LPARAM_DEFINED")
+cpp_quote("#define _LPARAM_DEFINED")
+typedef LONG LPARAM;//BUGBUG: this should be a discriminated union.
+cpp_quote("#endif // !_LPARAM_DEFINED")
+
+cpp_quote("#ifndef _LRESULT_DEFINED")
+cpp_quote("#define _LRESULT_DEFINED")
+typedef LONG LRESULT;
+cpp_quote("#endif // !_LRESULT_DEFINED")
+
+typedef [transmit_as(long)] void *HANDLE;
+
+#define DECLARE_HANDLE(name) typedef [transmit_as(long)] void * name
+
+DECLARE_HANDLE(HMODULE);
+DECLARE_HANDLE(HINSTANCE);
+DECLARE_HANDLE(HICON);
+DECLARE_HANDLE(HFONT);
+typedef [transmit_as(RemHGLOBAL)] void * HGLOBAL;
+typedef HGLOBAL HLOCAL;
+typedef [transmit_as(RemHBITMAP)] void * HBITMAP;
+typedef [transmit_as(RemHPALETTE)] void * HPALETTE;
+typedef [transmit_as(RemHBRUSH)] void * HBRUSH;
+typedef [transmit_as(RemHENHMETAFILE)] void * HENHMETAFILE;
+DECLARE_HANDLE(HDC);
+DECLARE_HANDLE(HRGN);
+DECLARE_HANDLE(HWND);
+DECLARE_HANDLE(HMENU);
+DECLARE_HANDLE(HACCEL);
+DECLARE_HANDLE(HTASK);
+DECLARE_HANDLE(HKEY);
+
+DECLARE_HANDLE(HDESK);
+/* DECLARE_HANDLE(HENHMETAFILE); */
+DECLARE_HANDLE(HMF);
+DECLARE_HANDLE(HEMF);
+DECLARE_HANDLE(HMETAFILE);
+/* DECLARE_HANDLE(HPALETTE); */
+DECLARE_HANDLE(HPEN);
+DECLARE_HANDLE(HRSRC);
+DECLARE_HANDLE(HSTR);
+DECLARE_HANDLE(HWINSTA);
+DECLARE_HANDLE(HKL);
+DECLARE_HANDLE(HGDIOBJ);
+
+typedef HANDLE HDWP;
+
+cpp_quote("#ifndef _HFILE_DEFINED")
+cpp_quote("#define _HFILE_DEFINED")
+typedef INT HFILE; /* Polymorphic with C runtime file handle type */
+cpp_quote("#endif // !_HFILE_DEFINED")
+
+
+cpp_quote("#ifndef _HCURSOR_DEFINED")
+cpp_quote("#define _HCURSOR_DEFINED")
+typedef HICON HCURSOR; /* HICONs & HCURSORs are polymorphic */
+cpp_quote("#endif // !_HCURSOR_DEFINED")
+
+
+
+cpp_quote("#ifndef _LPWORD_DEFINED")
+cpp_quote("#define _LPWORD_DEFINED")
+typedef WORD *LPWORD;
+cpp_quote("#endif // !_LPWORD_DEFINED")
+
+
+cpp_quote("#ifndef _LPDWORD_DEFINED")
+cpp_quote("#define _LPDWORD_DEFINED")
+typedef DWORD *LPDWORD;
+cpp_quote("#endif // !_LPDWORD_DEFINED")
+
+
+typedef [string] char *LPSTR;
+
+typedef [string] const char *LPCSTR;
+
+
+cpp_quote("#ifndef _WCHAR_DEFINED")
+cpp_quote("#define _WCHAR_DEFINED")
+typedef wchar_t WCHAR;
+typedef WCHAR TCHAR;
+cpp_quote("#endif // !_WCHAR_DEFINED")
+
+typedef [string] WCHAR *LPWSTR;
+
+
+typedef [string] TCHAR *LPTSTR;
+
+typedef [string] const WCHAR *LPCWSTR;
+typedef [string] const TCHAR *LPCTSTR;
+
+
+typedef struct tagPALETTEENTRY {
+ BYTE peRed;
+ BYTE peGreen;
+ BYTE peBlue;
+ BYTE peFlags;
+} PALETTEENTRY, *PPALETTEENTRY, *LPPALETTEENTRY;
+
+// Logical Palette
+cpp_quote("#if 0")
+
+ typedef struct tagLOGPALETTE {
+ WORD palVersion;
+ WORD palNumEntries;
+ [size_is(palNumEntries)] PALETTEENTRY palPalEntry[];
+ } LOGPALETTE, *PLOGPALETTE, *LPLOGPALETTE;
+
+cpp_quote("#else")
+cpp_quote("typedef struct tagLOGPALETTE {")
+cpp_quote(" WORD palVersion;")
+cpp_quote(" WORD palNumEntries;")
+cpp_quote(" PALETTEENTRY palPalEntry[1];")
+cpp_quote("} LOGPALETTE, *PLOGPALETTE, *LPLOGPALETTE;")
+cpp_quote("#endif")
+
+cpp_quote("#ifndef _COLORREF_DEFINED")
+cpp_quote("#define _COLORREF_DEFINED")
+typedef DWORD COLORREF;
+cpp_quote("#endif // !_COLORREF_DEFINED")
+
+cpp_quote("#ifndef _LPCOLORREF_DEFINED")
+cpp_quote("#define _LPCOLORREF_DEFINED")
+typedef DWORD *LPCOLORREF;
+cpp_quote("#endif // !_LPCOLORREF_DEFINED")
+
+
+typedef HANDLE *LPHANDLE;
+
+//typedefs for remotable types from wingdi.h
+
+typedef struct _RECTL
+{
+ LONG left;
+ LONG top;
+ LONG right;
+ LONG bottom;
+} RECTL, *PRECTL, *LPRECTL;
+
+
+typedef struct tagPOINT
+{
+ LONG x;
+ LONG y;
+} POINT, *PPOINT, *LPPOINT;
+
+typedef struct _POINTL
+{
+ LONG x;
+ LONG y;
+} POINTL, *PPOINTL;
+
+
+
+cpp_quote("#ifndef WIN16")
+typedef struct tagSIZE
+{
+ LONG cx;
+ LONG cy;
+} SIZE, *PSIZE, *LPSIZE;
+cpp_quote("#else // WIN16")
+cpp_quote("typedef struct tagSIZE")
+cpp_quote("{")
+cpp_quote(" INT cx;")
+cpp_quote(" INT cy;")
+cpp_quote("} SIZE, *PSIZE, *LPSIZE;")
+cpp_quote("#endif // WIN16")
+
+
+// Message structure
+
+typedef struct tagMSG {
+ HWND hwnd;
+ UINT message;
+ WPARAM wParam;
+ LPARAM lParam;
+ DWORD time;
+ POINT pt;
+} MSG, *PMSG, *NPMSG, *LPMSG;
+
+
+
+typedef struct tagSIZEL
+{
+ LONG cx;
+ LONG cy;
+} SIZEL, *PSIZEL, *LPSIZEL;
+
+
+cpp_quote("#endif //WINAPI")
+cpp_quote("#endif //!WIN32")
+
+cpp_quote("#if defined(_WIN32) && !defined(OLE2ANSI)")
+
+typedef WCHAR OLECHAR;
+typedef [string] OLECHAR *LPOLESTR;
+typedef [string] const OLECHAR *LPCOLESTR;
+cpp_quote("#define OLESTR(str) L##str")
+
+cpp_quote("#else")
+
+cpp_quote("typedef char OLECHAR;")
+cpp_quote("typedef LPSTR LPOLESTR;")
+cpp_quote("typedef LPCSTR LPCOLESTR;")
+cpp_quote("#define OLESTR(str) str")
+
+cpp_quote("#endif")
+
+
+
+
+
+// This block contains types that are normally defined by the nt sdk in WINDEF.H
+// but we need them here for definitions that follow in this file. If WINDEF.H
+// hasn't been included then we need to define them now so that WTYPES.H
+// will compile.
+cpp_quote("#ifndef _WINDEF_")
+typedef const RECTL *LPCRECTL;
+
+typedef void * PVOID, *LPVOID;
+typedef struct tagRECT
+{
+ LONG left;
+ LONG top;
+ LONG right;
+ LONG bottom;
+} RECT, *PRECT, *LPRECT;
+typedef const RECT *LPCRECT;
+
+cpp_quote("#endif //_WINDEF_")
+
+
+
+
+
+
+
+typedef unsigned char UCHAR;
+typedef short SHORT;
+typedef unsigned short USHORT;
+typedef DWORD ULONG;
+
+cpp_quote("#if 0")
+//
+// __int64 is only supported by 2.0 and later midl.
+// __midl is set by the 2.0 midl and not by 1.0 midl.
+//
+
+#if (defined(__midl))
+typedef __int64 LONGLONG;
+typedef unsigned __int64 ULONGLONG;
+#else
+typedef double LONGLONG;
+typedef double ULONGLONG;
+#endif
+
+typedef LONGLONG *PLONGLONG;
+typedef ULONGLONG *PULONGLONG;
+
+typedef struct _LARGE_INTEGER {
+ LONGLONG QuadPart;
+} LARGE_INTEGER;
+
+typedef LARGE_INTEGER *PLARGE_INTEGER;
+
+typedef struct _ULARGE_INTEGER {
+ ULONGLONG QuadPart;
+} ULARGE_INTEGER;
+
+cpp_quote("#endif // ")
+
+
+cpp_quote("#ifndef _WINBASE_")
+
+cpp_quote("#ifndef _FILETIME_")
+cpp_quote("#define _FILETIME_")
+typedef struct _FILETIME
+{
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+} FILETIME, *PFILETIME, *LPFILETIME;
+cpp_quote("#endif // !_FILETIME")
+
+cpp_quote("#ifndef _SYSTEMTIME_")
+cpp_quote("#define _SYSTEMTIME_")
+typedef struct _SYSTEMTIME {
+ WORD wYear;
+ WORD wMonth;
+ WORD wDayOfWeek;
+ WORD wDay;
+ WORD wHour;
+ WORD wMinute;
+ WORD wSecond;
+ WORD wMilliseconds;
+} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
+cpp_quote("#endif // !_SYSTEMTIME")
+
+cpp_quote("#ifndef _SECURITY_ATTRIBUTES_")
+cpp_quote("#define _SECURITY_ATTRIBUTES_")
+typedef struct _SECURITY_ATTRIBUTES {
+ DWORD nLength;
+ [size_is(nLength)] LPVOID lpSecurityDescriptor;
+ BOOL bInheritHandle;
+} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
+cpp_quote("#endif // !_SECURITY_ATTRIBUTES_")
+
+cpp_quote("#ifndef SECURITY_DESCRIPTOR_REVISION")
+
+typedef USHORT SECURITY_DESCRIPTOR_CONTROL, *PSECURITY_DESCRIPTOR_CONTROL;
+
+typedef PVOID PSID; // winnt
+
+typedef struct _ACL {
+ UCHAR AclRevision;
+ UCHAR Sbz1;
+ USHORT AclSize;
+ USHORT AceCount;
+ USHORT Sbz2;
+} ACL;
+typedef ACL *PACL;
+
+typedef struct _SECURITY_DESCRIPTOR {
+ UCHAR Revision;
+ UCHAR Sbz1;
+ SECURITY_DESCRIPTOR_CONTROL Control;
+ PSID Owner;
+ PSID Group;
+ PACL Sacl;
+ PACL Dacl;
+} SECURITY_DESCRIPTOR, *PISECURITY_DESCRIPTOR;
+
+cpp_quote("#endif // !SECURITY_DESCRIPTOR_REVISION")
+
+cpp_quote("#endif //_WINBASE_")
+
+
+//
+// SCODE, HRESULT
+//
+//
+// Status values are 32 bit values layed out as follows:
+//
+// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-+-----------------------------+-------------------------------+
+// |S| Facility | Code |
+// +-+-----------------------------+-------------------------------+
+//
+// where
+//
+// S - is the severity code
+//
+// 0 - Success
+// 1 - Error
+//
+//
+// Facility - is the facility code
+//
+// Code - is the facility's status code
+//
+// SCODE and HRESULT are mktyplib base types.
+//
+typedef LONG SCODE;
+typedef LONG HRESULT;
+
+typedef SCODE *PSCODE;
+
+
+cpp_quote("#ifndef GUID_DEFINED")
+cpp_quote("#define GUID_DEFINED")
+typedef struct _GUID
+{
+ DWORD Data1;
+ WORD Data2;
+ WORD Data3;
+ BYTE Data4[8];
+} GUID;
+cpp_quote("#endif // !GUID_DEFINED")
+
+cpp_quote("#if !defined( __LPGUID_DEFINED__ )")
+cpp_quote("#define __LPGUID_DEFINED__")
+typedef GUID *LPGUID;
+cpp_quote("#endif // !__LPGUID_DEFINED__")
+
+cpp_quote("#ifndef __OBJECTID_DEFINED")
+cpp_quote("#define __OBJECTID_DEFINED")
+cpp_quote("#define _OBJECTID_DEFINED")
+typedef struct _OBJECTID // NOTE!! Order of structure members is important for OFS
+{ // enumeration.
+ GUID Lineage; // Unique for objects copied from same original and copies of.
+ unsigned long Uniquifier; // Random, to provide uniqueness within small set with same
+} OBJECTID; // lineage id.
+cpp_quote("#endif // !_OBJECTID_DEFINED")
+
+
+
+
+cpp_quote("#if !defined( __IID_DEFINED__ )")
+cpp_quote("#define __IID_DEFINED__")
+
+// Interface ID are just a kind of GUID
+typedef GUID IID;
+typedef IID *LPIID;
+cpp_quote("#define IID_NULL GUID_NULL")
+cpp_quote("#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2)")
+
+// Class ID are just a kind of GUID
+typedef GUID CLSID;
+typedef CLSID *LPCLSID;
+cpp_quote("#define CLSID_NULL GUID_NULL")
+cpp_quote("#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2)")
+
+//The following typedefs are used internally by MIDL.
+cpp_quote("#if 0")
+#if defined(__midl)
+ /* MIDL 2.0 definitions */
+ typedef GUID *REFGUID;
+ typedef IID *REFIID;
+ typedef CLSID *REFCLSID;
+#else
+ /* MIDL 1.1 definitions */
+ typedef GUID REFGUID;
+ typedef IID REFIID;
+ typedef CLSID REFCLSID;
+#endif
+cpp_quote("#endif // 0")
+
+cpp_quote("#if defined(__cplusplus)")
+
+cpp_quote("#ifndef _REFGUID_DEFINED")
+cpp_quote("#define _REFGUID_DEFINED")
+cpp_quote("#define REFGUID const GUID &")
+cpp_quote("#endif // !_REFGUID_DEFINED")
+
+cpp_quote("#ifndef _REFIID_DEFINED")
+cpp_quote("#define _REFIID_DEFINED")
+cpp_quote("#define REFIID const IID &")
+cpp_quote("#endif // !_REFIID_DEFINED")
+
+cpp_quote("#ifndef _REFCLSID_DEFINED")
+cpp_quote("#define _REFCLSID_DEFINED")
+cpp_quote("#define REFCLSID const CLSID &")
+cpp_quote("#endif // !_REFCLSID_DEFINED")
+
+
+cpp_quote("#else // !__cplusplus")
+
+cpp_quote("#ifndef _REFGUID_DEFINED")
+cpp_quote("#define _REFGUID_DEFINED")
+cpp_quote("#define REFGUID const GUID * const")
+cpp_quote("#endif // !_REFGUID_DEFINED")
+
+cpp_quote("#ifndef _REFIID_DEFINED")
+cpp_quote("#define _REFIID_DEFINED")
+cpp_quote("#define REFIID const IID * const")
+cpp_quote("#endif // !_REFIID_DEFINED")
+
+
+cpp_quote("#ifndef _REFCLSID_DEFINED")
+cpp_quote("#define _REFCLSID_DEFINED")
+cpp_quote("#define REFCLSID const CLSID * const")
+cpp_quote("#endif // !_REFCLSID_DEFINED")
+
+cpp_quote("#endif // !__cplusplus")
+
+cpp_quote("#endif // !__IID_DEFINED__")
+
+ /************************* Misc types ***********************************/
+
+ // Common typdefs used in API paramaters, gleamed from compobj.h
+
+ // memory context values; passed to CoGetMalloc
+ typedef enum tagMEMCTX
+ {
+ MEMCTX_TASK = 1, // task (private) memory
+ MEMCTX_SHARED = 2, // shared memory (between processes)
+ MEMCTX_MACSYSTEM = 3, // on the mac, the system heap
+ // these are mostly for internal use...
+ MEMCTX_UNKNOWN = -1, // unknown context (when asked about it)
+ MEMCTX_SAME = -2, // same context (as some other pointer)
+ } MEMCTX;
+
+
+// For IRunningObjectTable::Register
+cpp_quote("#ifndef _ROTFLAGS_DEFINED")
+cpp_quote("#define _ROTFLAGS_DEFINED")
+cpp_quote("#define ROTFLAGS_REGISTRATIONKEEPSALIVE 1")
+cpp_quote("#endif // !_ROTFLAGS_DEFINED")
+
+// Maximum size of comparison buffer for IROTData::GetComparisonData
+cpp_quote("#ifndef _ROT_COMPARE_MAX_DEFINED")
+cpp_quote("#define _ROT_COMPARE_MAX_DEFINED")
+cpp_quote("#define ROT_COMPARE_MAX 2048")
+cpp_quote("#endif // !_ROT_COMPARE_MAX_DEFINED")
+
+
+ // class context: used to determine what scope and kind of class object to use
+ // NOTE: this is a bitwise enum
+ typedef enum tagCLSCTX
+ {
+ CLSCTX_INPROC_SERVER = 1, // server dll (runs in same process as caller)
+ CLSCTX_INPROC_HANDLER = 2, // handler dll (runs in same process as caller)
+ CLSCTX_LOCAL_SERVER = 4, // server exe (runs on same machine; diff proc)
+ CLSCTX_INPROC_SERVER16 = 8 // 16-bit server dll (runs in same process as caller)
+ } CLSCTX;
+
+
+ // marshaling flags; passed to CoMarshalInterface
+ typedef enum tagMSHLFLAGS
+ {
+ MSHLFLAGS_NORMAL = 0, // normal marshaling via proxy/stub
+ MSHLFLAGS_TABLESTRONG = 1, // keep object alive; must explicitly release
+ MSHLFLAGS_TABLEWEAK = 2 // doesn't hold object alive; still must release
+ } MSHLFLAGS;
+
+ // marshal context: determines the destination context of the marshal operation
+ typedef enum tagMSHCTX
+ {
+ MSHCTX_LOCAL = 0, // unmarshal context is local (eg.shared memory)
+ MSHCTX_NOSHAREDMEM = 1, // unmarshal context has no shared memory access
+ MSHCTX_DIFFERENTMACHINE = 2,// unmarshal context is on a different machine
+ MSHCTX_INPROC = 3, // unmarshal context is on different thread
+ } MSHCTX;
+
+
+
+
+ //
+ // Common typedefs for paramaters used in data view API's, gleamed
+ // from dvobj.h
+ //
+
+ // Data/View aspect; specifies the desired aspect of the object when
+ // drawing or getting data.
+ typedef enum tagDVASPECT
+ {
+ DVASPECT_CONTENT = 1,
+ DVASPECT_THUMBNAIL = 2,
+ DVASPECT_ICON = 4,
+ DVASPECT_DOCPRINT = 8
+ } DVASPECT;
+
+ /****** Storage types *************************************************/
+
+
+ /* Storage commit types */
+ typedef enum tagSTGC
+ {
+ STGC_DEFAULT = 0,
+ STGC_OVERWRITE = 1,
+ STGC_ONLYIFCURRENT = 2,
+ STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4
+ } STGC;
+
+
+
+ typedef enum tagSTGMOVE
+ {
+ STGMOVE_MOVE = 0,
+ STGMOVE_COPY = 1
+ } STGMOVE;
+
+ typedef enum tagSTATFLAG
+ {
+ STATFLAG_DEFAULT = 0,
+ STATFLAG_NONAME = 1
+ } STATFLAG;
+
+
+typedef [context_handle] void *HCONTEXT;
+
+/****** Critical Section Wrappers ***********************************/
+
+
+/* if not already picked up from olenls.h */
+cpp_quote("#ifndef _LCID_DEFINED")
+cpp_quote("#define _LCID_DEFINED")
+typedef DWORD LCID;
+cpp_quote("#endif // !_LCID_DEFINED")
+
+
+
+
+cpp_quote("void __RPC_API HGLOBAL_to_xmit (HGLOBAL __RPC_FAR *, RemHGLOBAL __RPC_FAR * __RPC_FAR *);")
+cpp_quote("void __RPC_API HGLOBAL_from_xmit (RemHGLOBAL __RPC_FAR *, HGLOBAL __RPC_FAR *);")
+cpp_quote("void __RPC_API HGLOBAL_free_inst (HGLOBAL __RPC_FAR *);")
+cpp_quote("void __RPC_API HGLOBAL_free_xmit (RemHGLOBAL __RPC_FAR *);")
+
+cpp_quote("void __RPC_API HBITMAP_to_xmit (HBITMAP __RPC_FAR *, RemHBITMAP __RPC_FAR * __RPC_FAR *);")
+cpp_quote("void __RPC_API HBITMAP_from_xmit (RemHBITMAP __RPC_FAR *, HBITMAP __RPC_FAR *);")
+cpp_quote("void __RPC_API HBITMAP_free_inst (HBITMAP __RPC_FAR *);")
+cpp_quote("void __RPC_API HBITMAP_free_xmit (RemHBITMAP __RPC_FAR *);")
+
+cpp_quote("void __RPC_API HPALETTE_to_xmit (HPALETTE __RPC_FAR *, RemHPALETTE __RPC_FAR * __RPC_FAR *);")
+cpp_quote("void __RPC_API HPALETTE_from_xmit (RemHPALETTE __RPC_FAR *, HPALETTE __RPC_FAR *);")
+cpp_quote("void __RPC_API HPALETTE_free_inst (HPALETTE __RPC_FAR *);")
+cpp_quote("void __RPC_API HPALETTE_free_xmit (RemHPALETTE __RPC_FAR *);")
+
+cpp_quote("void __RPC_API HBRUSH_to_xmit (HBRUSH __RPC_FAR *, RemHBRUSH __RPC_FAR * __RPC_FAR *);")
+cpp_quote("void __RPC_API HBRUSH_from_xmit (RemHBRUSH __RPC_FAR *, HBRUSH __RPC_FAR *);")
+cpp_quote("void __RPC_API HBRUSH_free_inst (HBRUSH __RPC_FAR *);")
+cpp_quote("void __RPC_API HBRUSH_free_xmit (RemHBRUSH __RPC_FAR *);")
+
+cpp_quote("void __RPC_API HMETAFILEPICT_to_xmit (HMETAFILEPICT __RPC_FAR *, RemHMETAFILEPICT __RPC_FAR * __RPC_FAR *);")
+cpp_quote("void __RPC_API HMETAFILEPICT_from_xmit (RemHMETAFILEPICT __RPC_FAR *, HMETAFILEPICT __RPC_FAR *);")
+cpp_quote("void __RPC_API HMETAFILEPICT_free_inst (HMETAFILEPICT __RPC_FAR *);")
+cpp_quote("void __RPC_API HMETAFILEPICT_free_xmit (RemHMETAFILEPICT __RPC_FAR *);")
+
+cpp_quote("void __RPC_API HENHMETAFILE_to_xmit (HENHMETAFILE __RPC_FAR *, RemHENHMETAFILE __RPC_FAR * __RPC_FAR *);")
+cpp_quote("void __RPC_API HENHMETAFILE_from_xmit (RemHENHMETAFILE __RPC_FAR *, HENHMETAFILE __RPC_FAR *);")
+cpp_quote("void __RPC_API HENHMETAFILE_free_inst (HENHMETAFILE __RPC_FAR *);")
+cpp_quote("void __RPC_API HENHMETAFILE_free_xmit (RemHENHMETAFILE __RPC_FAR *);")
+
+}
diff --git a/private/ole32/stg/props/issues.txt b/private/ole32/stg/props/issues.txt
new file mode 100644
index 000000000..5a942fb68
--- /dev/null
+++ b/private/ole32/stg/props/issues.txt
@@ -0,0 +1,21 @@
+Migration to new interface
+o deal with missing stuff in prop.idl :
+ #define STG_E_PROPSETMISMATCHED 0x800300F0
+
+Specification changes to reflect implementation
+o threading issues
+
+Unresolved implementation/design issues
+o Returing STG_E_INVALIDPOINTER ?
+o threading issues -- two ref counts : one for enumerations and one for regular refs
+o Enumerating properties of VT_STREAM etc type - do we check that the stream exists ? Or document
+ that just because it is enumerated doesn't mean you can open it ? How is VT_STREAM enumerated anyway ?
+ As a stream or as a string ?
+
+Test cases to consider:
+
+
+
+
+
+
diff --git a/private/ole32/stg/props/ntdllmac.hxx b/private/ole32/stg/props/ntdllmac.hxx
new file mode 100644
index 000000000..542299edf
--- /dev/null
+++ b/private/ole32/stg/props/ntdllmac.hxx
@@ -0,0 +1,187 @@
+//+--------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993
+//
+// File: ntdllmac.hxx
+//
+// Contents: various macros used in property set code
+//
+// History: 15-Jul-94 brianb created
+//
+//---------------------------------------------------------------------------
+
+
+extern "C" NTSTATUS
+SynchronousNtFsControlFile(
+ IN HANDLE h,
+ OUT IO_STATUS_BLOCK *pisb,
+ IN ULONG FsControlCode,
+ IN VOID *pvIn OPTIONAL,
+ IN ULONG cbIn,
+ OUT VOID *pvOut OPTIONAL,
+ IN ULONG cbOut);
+
+
+//+---------------------------------------------------------------------------
+// Function: Add2Ptr
+//
+// Synopsis: Add an unscaled increment to a ptr regardless of type.
+//
+// Arguments: [pv] -- Initial ptr.
+// [cb] -- Increment
+//
+// Returns: Incremented ptr.
+//
+//----------------------------------------------------------------------------
+
+inline VOID *
+Add2Ptr(VOID *pv, ULONG cb)
+{
+ return((BYTE *) pv + cb);
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: Add2ConstPtr
+//
+// Synopsis: Add an unscaled increment to a ptr regardless of type.
+//
+// Arguments: [pv] -- Initial ptr.
+// [cb] -- Increment
+//
+// Returns: Incremented ptr.
+//
+//----------------------------------------------------------------------------
+
+inline
+const VOID *
+Add2ConstPtr(const VOID *pv, ULONG cb)
+{
+ return((const BYTE *) pv + cb);
+}
+
+
+//+--------------------------------------------------------------------------
+// Function: CopyFileTime, private
+//
+// Synopsis: Copy LARGE_INTEGER time to FILETIME structure
+//
+// Arguments: [pft] -- pointer to FILETIME
+// [pli] -- pointer to LARGE_INTEGER
+//
+// Returns: Nothing
+//---------------------------------------------------------------------------
+
+__inline VOID
+CopyFileTime(OUT FILETIME *pft, IN LARGE_INTEGER *pli)
+{
+ pft->dwLowDateTime = pli->LowPart;
+ pft->dwHighDateTime = pli->HighPart;
+}
+
+
+//+--------------------------------------------------------------------------
+// Function: ZeroFileTime, private
+//
+// Synopsis: Zero FILETIME structure
+//
+// Arguments: [pft] -- pointer to FILETIME
+//
+// Returns: Nothing
+//---------------------------------------------------------------------------
+
+__inline VOID
+ZeroFileTime(OUT FILETIME *pft)
+{
+ pft->dwLowDateTime = pft->dwHighDateTime = 0;
+}
+
+
+#define DwordAlign(n) (((n) + sizeof(ULONG) - 1) & ~(sizeof(ULONG) - 1))
+#define QuadAlign(n) (((n) + sizeof(LONGLONG) - 1) & ~(sizeof(LONGLONG) - 1))
+
+// stuff to make Nashville properties build
+#include <propapi.h>
+
+#if DBG
+extern "C" LONG ExceptionFilter(struct _EXCEPTION_POINTERS *pep);
+#else // DBG
+#define ExceptionFilter(pep) EXCEPTION_EXECUTE_HANDLER
+#endif // DBG
+
+extern "C" UNICODECALLOUTS UnicodeCallouts;
+
+
+// The CMemSerStream and CDeMemSerStream have different requirements for
+// handling buffer overflow conditions. In the case of the driver this
+// is indicative of a corrupted stream and we would like to raise an
+// exception. On the other hand in Query implementation we deal with
+// streams whose sizes are precomputed in the user mode. Therefore we
+// do not wish to incur any additional penalty in handling such situations.
+// In debug builds this condition is asserted while in retail builds it is
+// ignored. The CMemSerStream and CMemDeSerStream implementation are
+// implemented using a macro HANDLE_OVERFLOW(fOverflow) which take the
+// appropriate action.
+
+#define HANDLE_OVERFLOW(fOverflow) \
+ if (fOverflow) { \
+ PropRaiseException(STATUS_BUFFER_OVERFLOW); \
+ }
+
+
+void* _CRTAPI1 operator new(size_t cb);
+void _CRTAPI1 operator delete(void *pv);
+
+#define newk(Tag, pCounter) new
+
+#if DBG
+extern "C" ULONG DebugLevel;
+extern "C" ULONG DebugIndent;
+
+#define DEBTRACE_ERROR (ULONG) 0x00000001
+#define DEBTRACE_WARN (ULONG) 0x00000002
+#define DEBTRACE_CREATESTREAM (ULONG) 0x00000004
+#define DEBTRACE_NTPROP (ULONG) 0x00000008
+#define DEBTRACE_MAPSTM (ULONG) 0x00000010
+#define DEBTRACE_PROPERTY (ULONG) 0x00000020
+#define DEBTRACE_SUMCAT (ULONG) 0x00000040
+
+#ifndef WINNT
+// in Nashville this is defined in ole32\stg\props\utils.cxx
+extern ULONG DbgPrint(PCHAR Format, ...);
+#endif
+
+#define DebugTrace(indent, flag, args) \
+ if ((flag) == 0 || (DebugLevel & (flag))) \
+ { \
+ DebugIndent += (ULONG) (indent); \
+ DbgPrint("NTDLL: %*s", DebugIndent, ""); \
+ DbgPrint args; \
+ } \
+ else
+
+class CDebugTrace {
+public:
+ inline CDebugTrace(CHAR *psz);
+ inline ~CDebugTrace();
+private:
+ CHAR const *const _psz;
+};
+
+inline CDebugTrace::CDebugTrace(CHAR *psz): _psz(psz)
+{
+ DebugTrace(+1, 0, ("Entering -- %s\n", _psz));
+}
+
+inline CDebugTrace::~CDebugTrace()
+{
+ DebugTrace(-1, 0, ("Exiting -- %s\n", _psz));
+}
+
+#define DEBUG_TRACE(ProcName) CDebugTrace _trace_(#ProcName);
+#else
+#define DebugTrace(indent, flag, args)
+#define DEBUG_TRACE(ProcName)
+#endif
+
diff --git a/private/ole32/stg/props/ntprop.cxx b/private/ole32/stg/props/ntprop.cxx
new file mode 100644
index 000000000..451eff4d9
--- /dev/null
+++ b/private/ole32/stg/props/ntprop.cxx
@@ -0,0 +1,409 @@
+//+--------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993
+//
+// File: ntprop.cxx
+//
+// Contents: OLE Appendix B property set support.
+//
+// History: 28-Nov-94 vich created
+// 15-Jul-96 MikeHill - PropSetNames: WCHAR=>OLECHAR, byte-swapping.
+// - Added special-cases for PictureIt! propsets.
+//
+//---------------------------------------------------------------------------
+
+#include <pch.cxx>
+#include <olechar.h>
+
+//#include <iofs.h>
+//#include <stgprop.h>
+
+// These optionally-compiled directives tell the compiler & debugger
+// where the real file, rather than the copy, is located.
+#ifdef _ORIG_FILE_LOCATION_
+#if __LINE__ != 25
+#error File heading has change size
+#else
+#line 29 "\\nt\\private\\dcomidl\\ntprop.cxx"
+#endif
+#endif
+
+#define CCH_MAP (1 << CBIT_CHARMASK) // 32
+#define CHARMASK (CCH_MAP - 1) // 0x1f
+
+// we use static array instead of string literals because some systems
+// have 4 bytes string literals, and would not produce the correct result
+// for REF's 2 byte Unicode convention
+//
+OLECHAR aocMap[CCH_MAP + 1] = {'a','b','c','d','e','f','g',
+ 'h','i','j','k','l','m','n',
+ 'o','p','q','r','s','t','u',
+ 'v','w','x','y','z',
+ '0','1','2','3','4','5','\0'};
+
+#define CALPHACHARS (1 + (OLECHAR)'z' - (OLECHAR)'a')
+
+GUID guidSummary =
+ { 0xf29f85e0,
+ 0x4ff9, 0x1068,
+ { 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9 } };
+
+OLECHAR oszSummary[] = {'S','u','m','m','a','r','y',
+ 'I','n','f','o','r','m','a','t','i','o','n','\0'};
+
+GUID guidDocumentSummary =
+ { 0xd5cdd502,
+ 0x2e9c, 0x101b,
+ { 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae } };
+
+OLECHAR oszDocumentSummary[] = {'D','o','c','u','m','e','n','t',
+ 'S','u','m','m','a','r','y',
+ 'I','n','f','o','r','m','a','t','i','o','n',
+ '\0'};
+
+// Note that user defined properties are placed in section 2 with the below
+// GUID as the FMTID -- alas, we did not expect Office95 to actually use it.
+
+GUID guidDocumentSummarySection2 =
+ { 0xd5cdd505,
+ 0x2e9c, 0x101b,
+ { 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae } };
+
+// *Global Info*
+
+OLECHAR oszGlobalInfo[] = {'G','l','o','b','a','l',' ','I','n','f','o','\0'};
+
+GUID guidGlobalInfo =
+ { 0x56616F00,
+ 0xC154, 0x11ce,
+ { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
+
+// *Image Contents*
+
+OLECHAR oszImageContents[] = {'I','m','a','g','e',' ',
+ 'C','o','n','t','e','n','t','s','\0'};
+
+GUID guidImageContents =
+ { 0x56616400,
+ 0xC154, 0x11ce,
+ { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
+
+// *Image Info*
+
+OLECHAR oszImageInfo[] = {'I','m','a','g','e',' ','I','n','f','o','\0'};
+
+GUID guidImageInfo =
+ { 0x56616500,
+ 0xC154, 0x11ce,
+ { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
+
+
+__inline OLECHAR
+MapChar(IN ULONG i)
+{
+ return((OLECHAR) aocMap[i & CHARMASK]);
+}
+
+
+//+--------------------------------------------------------------------------
+// Function: RtlGuidToPropertySetName
+//
+// Synopsis: Map property set GUID to null-terminated UNICODE name string.
+//
+// The awcname parameter is assumed to be a buffer with room for
+// CWC_PROPSETSZ (28) UNICODE characters. The first character
+// is always WC_PROPSET0 (0x05), as specified by the OLE Appendix
+// B documentation. The colon character normally used as an NT
+// stream name separator is not written to the caller's buffer.
+//
+// No error is possible.
+//
+// Arguments: IN GUID *pguid -- pointer to GUID to convert
+// OUT OLECHAR aocname[] -- output string buffer
+//
+// Returns: count of non-NULL characters in the output string buffer
+//---------------------------------------------------------------------------
+
+ULONG PROPSYSAPI PROPAPI
+RtlGuidToPropertySetName(
+ IN GUID const *pguid,
+ OUT OLECHAR aocname[])
+{
+ ULONG cbitRemain = CBIT_BYTE;
+ OLECHAR *poc = aocname;
+
+ BYTE *pb;
+ BYTE *pbEnd;
+
+ *poc++ = OC_PROPSET0;
+
+ // -----------------------
+ // Check for special-cases
+ // -----------------------
+
+ // Note: CCH_PROPSET includes the OC_PROPSET0, and sizeof(osz...)
+ // includes the trailing '\0', so sizeof(osz...) is ok because the
+ // OC_PROPSET0 character compensates for the trailing NULL character.
+
+ // Is this the SummaryInformation propset?
+ PROPASSERT(CCH_PROPSET >= sizeof(oszSummary)/sizeof(OLECHAR));
+
+ if (*pguid == guidSummary)
+ {
+ RtlCopyMemory(poc, oszSummary, sizeof(oszSummary));
+ return(sizeof(oszSummary)/sizeof(OLECHAR));
+ }
+
+ // Is this The DocumentSummaryInformation or User-Defined propset?
+ PROPASSERT(CCH_PROPSET >= sizeof(oszDocumentSummary)/sizeof(OLECHAR));
+
+ if (*pguid == guidDocumentSummary || *pguid == guidDocumentSummarySection2)
+ {
+ RtlCopyMemory(poc, oszDocumentSummary, sizeof(oszDocumentSummary));
+ return(sizeof(oszDocumentSummary)/sizeof(OLECHAR));
+ }
+
+ // Is this the Global Info propset?
+ PROPASSERT(CCH_PROPSET >= sizeof(oszGlobalInfo)/sizeof(OLECHAR));
+ if (*pguid == guidGlobalInfo)
+ {
+ RtlCopyMemory(poc, oszGlobalInfo, sizeof(oszGlobalInfo));
+ return(sizeof(oszGlobalInfo)/sizeof(OLECHAR));
+ }
+
+ // Is this the Image Contents propset?
+ PROPASSERT(CCH_PROPSET >= sizeof(oszImageContents)/sizeof(OLECHAR));
+ if (*pguid == guidImageContents)
+ {
+ RtlCopyMemory(poc, oszImageContents, sizeof(oszImageContents));
+ return(sizeof(oszImageContents)/sizeof(OLECHAR));
+ }
+
+ // Is this the Image Info propset?
+ PROPASSERT(CCH_PROPSET >= sizeof(oszImageInfo)/sizeof(OLECHAR));
+ if (*pguid == guidImageInfo)
+ {
+ RtlCopyMemory(poc, oszImageInfo, sizeof(oszImageInfo));
+ return(sizeof(oszImageInfo)/sizeof(OLECHAR));
+ }
+
+
+ // ------------------------------
+ // Calculate the string-ized GUID
+ // ------------------------------
+
+ // If this is a big-endian system, we need to convert
+ // the GUID to little-endian for the conversion.
+
+#if BIGENDIAN
+ GUID guidByteSwapped = *pguid;
+ PropByteSwap( &guidByteSwapped );
+ pguid = &guidByteSwapped;
+#endif
+
+ // Point to the beginning and ending of the GUID
+ pb = (BYTE*) pguid;
+ pbEnd = pb + sizeof(*pguid);
+
+ // Walk 'pb' through each byte of the GUID.
+
+ while (pb < pbEnd)
+ {
+ ULONG i = *pb >> (CBIT_BYTE - cbitRemain);
+
+ if (cbitRemain >= CBIT_CHARMASK)
+ {
+ *poc = MapChar(i);
+ if (cbitRemain == CBIT_BYTE && *poc >= (OLECHAR)'a'
+ && *poc <= ((OLECHAR)'z'))
+ {
+ *poc += (OLECHAR) ( ((OLECHAR)'A') - ((OLECHAR)'a') );
+ }
+ poc++;
+ cbitRemain -= CBIT_CHARMASK;
+ if (cbitRemain == 0)
+ {
+ pb++;
+ cbitRemain = CBIT_BYTE;
+ }
+ }
+ else
+ {
+ if (++pb < pbEnd)
+ {
+ i |= *pb << cbitRemain;
+ }
+ *poc++ = MapChar(i);
+ cbitRemain += CBIT_BYTE - CBIT_CHARMASK;
+ }
+ } // while (pb < pbEnd)
+
+ *poc = OLESTR( '\0' );
+ return(CCH_PROPSET);
+
+}
+
+
+//+--------------------------------------------------------------------------
+// Function: RtlPropertySetNameToGuid
+//
+// Synopsis: Map non null-terminated UNICODE string to a property set GUID.
+//
+// If the name is not properly formed as per
+// RtlGuidToPropertySetName(), STATUS_INVALID_PARAMETER is
+// returned. The pguid parameter is assumed to point to a buffer
+// with room for a GUID structure.
+//
+// Arguments: IN ULONG cocname -- count of OLECHARs in string to convert
+// IN OLECHAR aocname[] -- input string to convert
+// OUT GUID *pguid -- pointer to buffer for converted GUID
+//
+// Returns: NTSTATUS
+//---------------------------------------------------------------------------
+
+NTSTATUS PROPSYSAPI PROPAPI
+RtlPropertySetNameToGuid(
+ IN ULONG cocname,
+ IN OLECHAR const aocname[],
+ OUT GUID *pguid)
+{
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ OLECHAR const *poc = aocname;
+
+ if (poc[0] == OC_PROPSET0)
+ {
+ // -----------------------
+ // Check for Special-Cases
+ // -----------------------
+
+ // Note: cocname includes the OC_PROPSET0, and sizeof(osz...)
+ // includes the trailing OLESTR('\0'), but the comparison excludes both
+ // the leading OC_PROPSET0 and the trailing '\0'.
+
+ // Is this SummaryInformation?
+ if (cocname == sizeof(oszSummary)/sizeof(OLECHAR) &&
+ ocsnicmp(&poc[1], oszSummary, cocname - 1) == 0)
+ {
+ *pguid = guidSummary;
+ return(STATUS_SUCCESS);
+ }
+
+ // Is this DocumentSummaryInformation?
+ if (cocname == sizeof(oszDocumentSummary)/sizeof(OLECHAR) &&
+ ocsnicmp(&poc[1], oszDocumentSummary, cocname - 1) == 0)
+ {
+ *pguid = guidDocumentSummary;
+ return(STATUS_SUCCESS);
+ }
+
+ // Is this Global Info?
+ if (cocname == sizeof(oszGlobalInfo)/sizeof(OLECHAR) &&
+ ocsnicmp(&poc[1], oszGlobalInfo, cocname - 1) == 0)
+ {
+ *pguid = guidGlobalInfo;
+ return(STATUS_SUCCESS);
+ }
+
+ // Is this Image Info?
+ if (cocname == sizeof(oszImageInfo)/sizeof(OLECHAR) &&
+ ocsnicmp(&poc[1], oszImageInfo, cocname - 1) == 0)
+ {
+ *pguid = guidImageInfo;
+ return(STATUS_SUCCESS);
+ }
+
+ // Is this Image Contents?
+ if (cocname == sizeof(oszImageContents)/sizeof(OLECHAR) &&
+ ocsnicmp(&poc[1], oszImageContents, cocname - 1) == 0)
+ {
+ *pguid = guidImageContents;
+ return(STATUS_SUCCESS);
+ }
+
+ // ------------------
+ // Calculate the GUID
+ // ------------------
+
+ // None of the special-cases hit, so we must calculate
+ // the GUID from the name.
+
+ if (cocname == CCH_PROPSET)
+ {
+ ULONG cbit;
+ BYTE *pb = (BYTE *) pguid - 1;
+
+ RtlZeroMemory(pguid, sizeof(*pguid));
+ for (cbit = 0; cbit < CBIT_GUID; cbit += CBIT_CHARMASK)
+ {
+ ULONG cbitUsed = cbit % CBIT_BYTE;
+ ULONG cbitStored;
+ OLECHAR oc;
+
+ if (cbitUsed == 0)
+ {
+ pb++;
+ }
+
+ oc = *++poc - (OLECHAR)'A'; // assume upper case
+ // for wchar (unsigned) -ve values becomes a large number
+ // but for char, which is signed, -ve is -ve
+ if (oc > CALPHACHARS || oc < 0)
+ {
+ // oops, try lower case
+ oc += (OLECHAR) ( ((OLECHAR)'A') - ((OLECHAR)'a'));
+ if (oc > CALPHACHARS || oc < 0)
+ {
+ // must be a digit
+ oc += ((OLECHAR)'a') - ((OLECHAR)'0') + CALPHACHARS;
+ if (oc > CHARMASK)
+ {
+ goto Exit; // invalid character
+ }
+ }
+ }
+ *pb |= (BYTE) (oc << cbitUsed);
+
+ cbitStored = min(CBIT_BYTE - cbitUsed, CBIT_CHARMASK);
+
+ // If the translated bits wouldn't all fit in the current byte
+
+ if (cbitStored < CBIT_CHARMASK)
+ {
+ oc >>= CBIT_BYTE - cbitUsed;
+
+ if (cbit + cbitStored == CBIT_GUID)
+ {
+ if (oc != 0)
+ {
+ goto Exit; // extra bits
+ }
+ break;
+ }
+ pb++;
+
+ *pb |= (BYTE) oc;
+ }
+ } // for (cbit = 0; cbit < CBIT_GUID; cbit += CBIT_CHARMASK)
+
+ Status = STATUS_SUCCESS;
+
+ // If byte-swapping is necessary, do so now on the calculated
+ // GUID.
+
+ PropByteSwap( pguid );
+
+ } // if (cocname == CCH_PROPSET)
+ } // if (poc[0] == OC_PROPSET0)
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return(Status);
+}
+
diff --git a/private/ole32/stg/props/ntpropb.cxx b/private/ole32/stg/props/ntpropb.cxx
new file mode 100644
index 000000000..7c93d7790
--- /dev/null
+++ b/private/ole32/stg/props/ntpropb.cxx
@@ -0,0 +1,2377 @@
+//+--------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1994
+//
+// File: ntpropb.cxx
+//
+// Contents: Nt property set implementation based on OLE Appendix B.
+//
+// History: 5-Dec-94 vich created
+// 09-May-96 MikeHill Use the 'boolVal' member of PropVariant,
+// rather than the member named 'bool'
+// (which is a reserved keyword).
+// 22-May-96 MikeHill - Get the OSVersion during a CreatePropSet.
+// - Let CPropSetStm allocate prop name buffers.
+// 07-Jun-96 MikeHill - Correct ClipData.cbSize to include
+// sizeof(ulClipFmt).
+// - Removed unnecessary Flushes.
+// - Take the psstm lock on RtlClosePropSet.
+// 12-Jun-96 MikeHill - Fix locking in RtlClosePropertySet.
+// - VT_I1 support (under ifdefs)
+// 25-Jul-96 MikeHill - Removed Win32 SEH.
+// - BSTRs & prop names: WCHAR => OLECHAR.
+// - Added RtlOnMappedStreamEvent
+// - Enabled for use in "iprop.dll".
+//
+//---------------------------------------------------------------------------
+
+#include <pch.cxx>
+#include "propvar.h"
+#include <olechar.h>
+
+// These optionally-compiled directives tell the compiler & debugger
+// where the real file, rather than the copy, is located.
+#ifdef _ORIG_FILE_LOCATION_
+#if __LINE__ != 36
+#error File heading has change size
+#else
+#line 40 "\\nt\\private\\dcomidl\\ntpropb.cxx"
+#endif
+#endif
+
+
+#define Dbg DEBTRACE_NTPROP
+#define DbgS(s) (NT_SUCCESS(s)? Dbg : DEBTRACE_ERROR)
+
+
+#if DBG
+ULONG DebugLevel = DEBTRACE_ERROR;
+//ULONG DebugLevel = DEBTRACE_ERROR | DEBTRACE_CREATESTREAM;
+//ULONG DebugLevel = DEBTRACE_ERROR | MAXULONG;
+ULONG DebugIndent;
+ULONG cAlloc;
+ULONG cFree;
+#endif
+
+extern "C" UNICODECALLOUTS UnicodeCallouts =
+{
+#ifdef WINNT
+ NULL
+#else
+ WIN32_UNICODECALLOUTS
+#endif
+};
+
+
+#if defined(WINNT) && !defined(IPROPERTY_DLL)
+
+GUID guidStorage = PSGUID_STORAGE;
+
+// ----------- Allocation routines are not used on X86 DosWindows Platform ---
+
+//+---------------------------------------------------------------------------
+// Function: new, public
+//
+// Synopsis: Allocate memory
+//
+// Arguments: [cb] -- size
+//
+// Returns: pointer to memory, NULL if not available
+//---------------------------------------------------------------------------
+
+
+void* _CRTAPI1
+operator new(size_t cb)
+{
+#if DBG
+ cAlloc++;
+#endif
+ return(RtlAllocateHeap(RtlProcessHeap(), 0, cb));
+}
+
+//+---------------------------------------------------------------------------
+// Function: delete, public
+//
+// Synopsis: Free memory
+//
+// Arguments: [pv] -- pointer to memory to be freed
+//
+// Returns: pointer to memory, NULL if not available
+//---------------------------------------------------------------------------
+
+void _CRTAPI1
+operator delete(void *pv)
+{
+#if DBG
+ cFree++;
+#endif
+ RtlFreeHeap(RtlProcessHeap(), 0, pv);
+}
+
+#endif // #if defined(WINNT) && !defined(IPROPERTY_DLL)
+
+
+//+---------------------------------------------------------------------------
+// Function: UnLock, private
+//
+// Synopsis: Unlock a PropertySetStream, and return the
+// more severe of two NTSTATUSs; the result of
+// the Unlock, or the one passed in by the caller.
+//
+// Arguments: [ppsstm] -- The CPropertySetStream to unlock
+// [Status] -- NTSTATUS
+//
+// Returns: NTSTATUS
+//---------------------------------------------------------------------------
+
+inline NTSTATUS
+Unlock( CPropertySetStream *ppsstm, NTSTATUS Status )
+{
+ NTSTATUS StatusT = ppsstm->Unlock();
+
+ // Note that the statement below preserves
+ // success codes in the original Status unless
+ // there was an error in the Unlock.
+
+ if( NT_SUCCESS(Status) && !NT_SUCCESS(StatusT) )
+ Status = StatusT;
+
+ return( Status );
+}
+
+//+---------------------------------------------------------------------------
+// Function: RtlSetUnicodeCallouts, public
+//
+// Synopsis: Set the Unicode conversion function pointers
+//
+// Arguments: [pUnicodeCallouts] -- Unicode callouts table
+//
+// Returns: Nothing
+//---------------------------------------------------------------------------
+
+VOID PROPSYSAPI PROPAPI
+RtlSetUnicodeCallouts(
+ IN UNICODECALLOUTS *pUnicodeCallouts)
+{
+ UnicodeCallouts = *pUnicodeCallouts;
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlCreateMappedStream, public
+//
+// Synopsis: Allocate and initialize a property set context
+//
+// Arguments: [h] -- property set handle
+// [Flags] -- [CMS_WRITE] | [CMS_TRANSACTED]
+// [pms] -- pointer to returned mapped stream context
+//
+// Returns: Status code
+//---------------------------------------------------------------------------
+
+#ifdef _CAIRO_
+NTSTATUS PROPSYSAPI PROPAPI
+RtlCreateMappedStream(
+ IN HANDLE h, // property set handle
+ IN ULONG Flags, // [CMS_WRITE] | [CMS_TRANSACTED]
+ OUT NTMAPPEDSTREAM *pms) // pointer to return mapped stream
+{
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ DebugTrace(0, Dbg, (
+ "RtlCreateMappedStream(h=%x, %s%s)\n",
+ h,
+ (Flags & CMS_WRITE)? "Write" : "Read",
+ (Flags & CMS_TRANSACTED)? " Transacted" : ""));
+ if ((Flags & ~(CMS_WRITE | CMS_TRANSACTED)) == 0)
+ {
+ *pms = NULL;
+ __try
+ {
+ Status = STATUS_SUCCESS;
+ *pms = (NTMAPPEDSTREAM) new CNtMappedStream(h, Flags);
+ if (*pms == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+#if DBGPROP
+ else if (DebugLevel & (Dbg | DEBTRACE_CREATESTREAM))
+ {
+#define CB_NAMEINFOx (sizeof(FILE_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR))
+ FILE_NAME_INFORMATION *pfni;
+ LONGLONG fni[QuadAlign(CB_NAMEINFOx)/sizeof(LONGLONG)];
+ IO_STATUS_BLOCK isb;
+
+ pfni = (FILE_NAME_INFORMATION *) fni;
+ Status = NtQueryInformationFile(
+ h,
+ &isb,
+ pfni,
+ sizeof(fni),
+ FileNameInformation);
+ if (NT_SUCCESS(Status))
+ {
+ DebugTrace(0, Dbg | DEBTRACE_CREATESTREAM, (
+ "%x.%x: RtlCreateMappedStream(%.*ws, %s%s) ==> ms=%x, s=%x\n",
+ (ULONG) NtCurrentTeb()->ClientId.UniqueProcess,
+ (ULONG) NtCurrentTeb()->ClientId.UniqueThread,
+ pfni->FileNameLength/sizeof(WCHAR),
+ pfni->FileName,
+ (Flags & CMS_WRITE)? "Write" : "Read",
+ (Flags & CMS_TRANSACTED)? " Transacted" : "",
+ *pms,
+ Status));
+ }
+ }
+#endif // if DBGPROP
+ }
+ __except(ExceptionFilter(GetExceptionInformation()))
+ {
+ Status = GetExceptionCode();
+ PROPASSERT(!NT_SUCCESS(Status));
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "RtlCreateMappedStream() ==> except=%x\n", Status));
+ }
+ }
+ DebugTrace(0, DbgS(Status), (
+ "RtlCreateMappedStream() ==> ms=%x, s=%x\n--------\n",
+ *pms,
+ Status));
+ return(Status);
+}
+#endif // ifdef _CAIRO_
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlCloseMappedStream, public
+//
+// Synopsis: Delete an Nt Mapped Stream
+//
+// Arguments: [ms] -- Nt Mapped Stream
+//
+// Returns: Status code
+//---------------------------------------------------------------------------
+
+#ifdef _CAIRO_
+NTSTATUS PROPSYSAPI PROPAPI
+RtlCloseMappedStream(
+ IN NTMAPPEDSTREAM ms) // Nt Mapped Stream
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ DebugTrace(0, Dbg, ("RtlCloseMappedStream(ms=%x)\n", ms));
+ __try
+ {
+ CNtMappedStream *pmstm = (CNtMappedStream *) ms;
+
+ PROPASSERT(pmstm->IsNtMappedStream());
+ delete pmstm;
+ }
+ __except(ExceptionFilter(GetExceptionInformation()))
+ {
+ Status = GetExceptionCode();
+ PROPASSERT(!NT_SUCCESS(Status));
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "RtlCloseMappedStream() ==> except=%x\n", Status));
+ }
+ DebugTrace(0, DbgS(Status), ("RtlCloseMappedStream() ==> s=%x\n--------\n", Status));
+ return(Status);
+}
+#endif // ifdef _CAIRO_
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlCreatePropertySet, public
+//
+// Synopsis: Allocate and initialize a property set context
+//
+// Arguments: [ms] -- Nt Mapped Stream
+// [Flags] -- *one* of READ/WRITE/CREATE/CREATEIF/DELETE
+// [pguid] -- property set guid (create only)
+// [pclsid] -- CLASSID of propset code (create only)
+// [ma] -- caller's memory allocator
+// [LocaleId] -- Locale Id (create only)
+// [pOSVersion] -- pointer to the OS Version header field
+// [pCodePage] -- pointer to new/returned CodePage of propset
+// [pnp] -- pointer to returned property set context
+//
+// Returns: Status code
+//---------------------------------------------------------------------------
+
+NTSTATUS PROPSYSAPI PROPAPI
+RtlCreatePropertySet(
+ IN NTMAPPEDSTREAM ms, // Nt Mapped Stream
+ IN USHORT Flags, // *one* of READ/WRITE/CREATE/CREATEIF/DELETE
+ OPTIONAL IN GUID const *pguid, // property set guid (create only)
+ OPTIONAL IN GUID const *pclsid, // CLASSID of propset code (create only)
+ IN NTMEMORYALLOCATOR ma, // caller's memory allocator
+ IN ULONG LocaleId, // Locale Id (create only)
+ OPTIONAL OUT ULONG *pOSVersion, // OS Version from the propset header
+ IN OUT USHORT *pCodePage, // IN: CodePage of property set (create only)
+ // OUT: CodePage of property set (always)
+ OUT NTPROP *pnp) // pointer to return prop set context
+{
+ NTSTATUS Status;
+ CMappedStream *pmstm = (CMappedStream *) ms;
+ CPropertySetStream *ppsstm = NULL;
+ BOOLEAN fLocked = FALSE;
+ BOOLEAN fOpened = FALSE;
+
+ DebugTrace(0, Dbg, (
+ "RtlCreatePropertySet(ms=%x, f=%x, codepage=%x)\n",
+ ms,
+ Flags,
+ *pCodePage));
+
+ *pnp = NULL;
+ Status = STATUS_INVALID_PARAMETER;
+
+ if( pOSVersion != NULL )
+ *pOSVersion = PROPSETHDR_OSVERSION_UNKNOWN;
+
+ // Validate the input flags
+
+ if (Flags & ~(CREATEPROP_MODEMASK | CREATEPROP_NONSIMPLE))
+ {
+ DebugTrace(0, DbgS(Status), (
+ "RtlCreatePropertySet(ms=%x, Flags=%x) ==> bad flags!\n",
+ ms,
+ Flags));
+ goto Exit;
+ }
+
+ switch (Flags & CREATEPROP_MODEMASK)
+ {
+ case CREATEPROP_DELETE:
+ case CREATEPROP_CREATE:
+ case CREATEPROP_CREATEIF:
+
+#if defined(WINNT) && !defined(IPROPERTY_DLL)
+ if (pguid != NULL &&
+ RtlCompareMemory(
+ (VOID *) pguid, // BUGBUG: const
+ &guidStorage,
+ sizeof(guidStorage)) == sizeof(guidStorage))
+ {
+ DebugTrace(0, DbgS(Status), (
+ "RtlCreatePropertySet(%x, guid=guidStorage) ==> OBSOLETE!\n",
+ ms));
+ goto Exit;
+ }
+ if (pclsid != NULL &&
+ RtlCompareMemory(
+ (VOID *) pclsid, // BUGBUG: const
+ &guidStorage,
+ sizeof(guidStorage)) == sizeof(guidStorage))
+ {
+ DebugTrace(0, DbgS(Status), (
+ "RtlCreatePropertySet(%x, clsid=guidStorage) ==> OBSOLETE!\n",
+ ms));
+ goto Exit;
+ }
+ // FALLTHROUGH
+#endif
+ case CREATEPROP_WRITE:
+ if (!pmstm->IsWriteable())
+ {
+ Status = STATUS_ACCESS_DENIED;
+ goto Exit;
+ }
+ // FALLTHROUGH
+
+ case CREATEPROP_READ:
+ if (ma == NULL)
+ {
+ goto Exit;
+ }
+ break;
+
+ default:
+ DebugTrace(0, DbgS(Status), (
+ "RtlCreatePropertySet(ms=%x, Flags=%x) ==> invalid mode!\n",
+ ms,
+ Flags));
+ goto Exit;
+ }
+
+ Status = pmstm->Lock((Flags & CREATEPROP_MODEMASK) != CREATEPROP_READ);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ fLocked = TRUE;
+
+ ppsstm = new CPropertySetStream(
+ Flags,
+ pmstm,
+ (PMemoryAllocator *) ma);
+ if (ppsstm == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+ else
+ {
+ ppsstm->Open(pguid, pclsid, LocaleId,
+ pOSVersion,
+ *pCodePage,
+ &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+#ifdef _CAIRO_
+ ppsstm->Flush();
+#endif
+
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if (fLocked)
+ {
+ Status = Unlock( ppsstm, Status );
+ }
+
+ // If we were successfull with everything, set the
+ // out-parameters.
+
+ if( NT_SUCCESS(Status) )
+ {
+ // pOSVersion has already been set.
+ *pCodePage = ppsstm->GetCodePage();
+ *pnp = (NTPROP) ppsstm;
+ }
+
+ // Otherwise, if we created a CPropertySetStream object, but
+ // the overall operation failed, we must close/delete
+ // the object. Note that we must do this after
+ // the above unlock, since ppsstm will be gone after
+ // this call.
+
+ else if( NULL != ppsstm )
+ {
+ RtlClosePropertySet((NTPROP) ppsstm);
+ }
+
+ DebugTrace(0, DbgS(Status), (
+ "RtlCreatePropertySet() ==> ms=%x, s=%x\n--------\n",
+ *pnp,
+ Status));
+ return(Status);
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlClosePropertySet, public
+//
+// Synopsis: Delete a property set context
+//
+// Arguments: [np] -- property set context
+//
+// Returns: Status code
+//---------------------------------------------------------------------------
+
+NTSTATUS PROPSYSAPI PROPAPI
+RtlClosePropertySet(
+ IN NTPROP np) // property set context
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fLocked = FALSE;
+ CPropertySetStream *ppsstm = (CPropertySetStream *) np;
+
+ DebugTrace(0, Dbg, ("RtlClosePropertySet(np=%x)\n", np));
+
+ // Lock the mapped stream, because this close
+ // may trigger a Write.
+
+ Status = ppsstm->Lock(TRUE);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ fLocked = TRUE;
+
+ ppsstm->Close(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if (fLocked)
+ Status = Unlock( ppsstm, Status );
+
+ delete ppsstm;
+
+ DebugTrace(0, DbgS(Status), ("RtlClosePropertySet() ==> s=%x\n", Status));
+ return(Status);
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlOnMappedStreamEvent, public
+//
+// Synopsis: Handle a MappedStream event. Every such
+// event requires a byte-swap of the property set
+// headers.
+//
+// Arguments: [np] -- property set context
+// [pbuf] -- property set buffer
+// [cbstm] -- size of mapped stream (or CBSTM_UNKNOWN)
+//
+// NOTE: It is assumed that the caller has already taken
+// the CPropertySetStream::Lock.
+//
+// Returns: Status code
+//---------------------------------------------------------------------------
+
+NTSTATUS PROPSYSAPI PROPAPI
+RtlOnMappedStreamEvent(
+ IN VOID * np, // property set context (an NTPROP)
+ IN VOID *pbuf, // property set buffer
+ IN ULONG cbstm )
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ CPropertySetStream *ppsstm = (CPropertySetStream *) np;
+
+ DebugTrace(0, Dbg, ("RtlOnMappedStreamEvent(np=%x)\n", np));
+
+ // Byte-swap the property set headers.
+ ppsstm->ByteSwapHeaders((PROPERTYSETHEADER*) pbuf, cbstm, &Status );
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ DebugTrace(0, DbgS(Status), ("RtlOnMappedStreamEvent() ==> s=%x\n", Status));
+ return(Status);
+
+} // RtlOnMappedStreamEvent()
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlFlushPropertySet, public
+//
+// Synopsis: Flush property set changes to disk
+//
+// Arguments: [np] -- property set context
+//
+// Returns: Status code
+//---------------------------------------------------------------------------
+
+NTSTATUS PROPSYSAPI PROPAPI
+RtlFlushPropertySet(
+ IN NTPROP np) // property set context
+{
+ CPropertySetStream *ppsstm = (CPropertySetStream *) np;
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fLocked = FALSE;
+
+ DebugTrace(0, Dbg, ("RtlFlushPropertySet(np=%x)\n", np));
+
+ Status = ppsstm->Lock(TRUE);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ fLocked = TRUE;
+
+ if (ppsstm->IsModified())
+ {
+ ppsstm->ReOpen(&Status); // Reload header/size info
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->Flush(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ }
+
+Exit:
+
+ if( fLocked )
+ Status = Unlock( ppsstm, Status );
+
+ DebugTrace(0, DbgS(Status), ("RtlFlushPropertySet() ==> s=%x\n--------\n", Status));
+ return(Status);
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: MapNameToPropId, private
+//
+// Synopsis: Find an available propid and map it to the passed name
+//
+// Arguments: [ppsstm] -- property set stream
+// [CodePage] -- property set codepage
+// [aprs] -- array of property specifiers
+// [cprop] -- count of property specifiers
+// [iprop] -- index of propspec with name to map
+// [pidStart] -- first PROPID to start mapping attempts
+// [pstatus] -- NTSTATUS code
+//
+// Returns: PROPID mapped to passed name
+//
+// Note: Find the first unused propid starting at pidStart.
+//---------------------------------------------------------------------------
+
+PROPID
+MapNameToPropId(
+ IN CPropertySetStream *ppsstm, // property set stream
+ IN USHORT CodePage,
+ IN PROPSPEC const aprs[], // array of property specifiers
+ IN ULONG cprop,
+ IN ULONG iprop,
+ IN PROPID pidStart,
+ OUT NTSTATUS *pstatus)
+{
+ PROPID pid = PID_ILLEGAL;
+ OLECHAR const *poszName;
+
+ OLECHAR aocName[CCH_MAXPROPNAMESZ];
+ ULONG cbName;
+
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(aprs[iprop].ulKind == PRSPEC_LPWSTR);
+ poszName = aprs[iprop].lpwstr;
+ PROPASSERT(IsOLECHARString( poszName, MAXULONG ));
+
+ // Starting with the caller-provided PID, search sequentially
+ // until we find a PID we can use.
+
+ for (pid = pidStart; ; pid++)
+ {
+ ULONG i;
+
+ // The caller must specify a starting propid of 2 or larger, and we
+ // must not increment into the reserved propids.
+
+ if (pid == PID_DICTIONARY ||
+ pid == PID_CODEPAGE ||
+ pid < PID_FIRST_USABLE)
+ {
+ *pstatus = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ // Do not assign any propids that explitly appear in the array of
+ // propspecs involved in this RtlSetProperties call, nor any propids
+ // that are associated with any names in the propspec array.
+
+ for (i = 0; i < cprop; i++)
+ {
+ if (i != iprop) // skip the entry we are mapping
+ {
+ // Is the current PID in the PropSpec[]?
+
+ if (aprs[i].ulKind == PRSPEC_PROPID &&
+ aprs[i].propid == pid)
+ {
+ goto nextpid; // skip colliding pid
+ }
+
+ // Is the current PID already used in the property set?
+
+ if (aprs[i].ulKind == PRSPEC_LPWSTR &&
+ ppsstm->QueryPropid(aprs[i].lpwstr, pstatus) == pid)
+ {
+ goto nextpid; // skip colliding pid
+ }
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+ } // for (i = 0; i < cprop; i++)
+
+ // Do not assign any propids that currently map to any name.
+ // Note that the property name we are mapping does not appear in the
+ // dictionary -- the caller checked for this case already.
+
+ cbName = sizeof(aocName);
+ if (!ppsstm->QueryPropertyNameBuf(pid, aocName, &cbName, pstatus))
+ {
+ // The property name could not be found in the dictionary.
+
+ ULONG cbT;
+ SERIALIZEDPROPERTYVALUE const *pprop;
+
+ // Was the name not found due to an error in QueryPropertyNameBuf?
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // Do not assign any propids that currently have a property value.
+
+ pprop = ppsstm->GetValue(pid, &cbT, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if (pprop == NULL)
+ {
+ // There was no property value corresponding to this PID.
+
+ DebugTrace(0, Dbg, (
+ "MapNameToPropId(Set Entry: pid=%x, name=L'%ws')\n",
+ pid,
+ poszName));
+
+ // Add the caller-provided name to the dictionary, using
+ // the PID that we now know is nowhere in use.
+
+ ppsstm->SetPropertyNames(1, &pid, &poszName, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ ppsstm->Validate(pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ break;
+
+ } // if (pprop == NULL)
+ } // if (!ppsstm->QueryPropertyNameBuf(pid, awcName, &cbName, pstatus))
+
+nextpid:
+ ;
+ } // for (pid = pidStart; ; pid++)
+
+Exit:
+
+ return(pid);
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: ConvertVariantToPropInfo, private
+//
+// Synopsis: Convert variant property values to PROPERTY_INFORMATION values
+//
+// Arguments: [ppsstm] -- property set stream
+// [cprop] -- property count
+// [pidNameFirst] -- first PROPID for new named properties
+// [aprs] -- array of property specifiers
+// [apid] -- buffer for array of propids
+// [avar] -- array of PROPVARIANTs
+// [apinfo] -- output array of property info
+// [pcIndirect] -- output count of indirect properties
+//
+// Returns: None
+//
+// Note: If pcIndirect is NULL,
+//---------------------------------------------------------------------------
+
+VOID
+ConvertVariantToPropInfo(
+ IN CPropertySetStream *ppsstm, // property set stream
+ IN ULONG cprop, // property count
+ IN PROPID pidNameFirst, // first PROPID for new named properties
+ IN PROPSPEC const aprs[], // array of property specifiers
+ OPTIONAL OUT PROPID apid[], // buffer for array of propids
+ OPTIONAL IN PROPVARIANT const avar[],// array of properties+values
+ OUT PROPERTY_INFORMATION *apinfo, // output array of property info
+ OUT ULONG *pcIndirect, // output count of indirect properties
+ OUT NTSTATUS *pstatus )
+{
+ *pstatus = STATUS_SUCCESS;
+
+ USHORT CodePage = ppsstm->GetCodePage();
+ PROPID pidStart = pidNameFirst;
+ ULONG iprop;
+
+ if (pcIndirect != NULL)
+ {
+ *pcIndirect = 0;
+ }
+
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ PROPID pid;
+ ULONG cbprop;
+
+ switch(aprs[iprop].ulKind)
+ {
+ case PRSPEC_LPWSTR:
+ {
+ PROPASSERT(IsOLECHARString(aprs[iprop].lpwstr, MAXULONG));
+ pid = ppsstm->QueryPropid(aprs[iprop].lpwstr, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if (pid == PID_ILLEGAL && avar != NULL)
+ {
+ pid = MapNameToPropId(
+ ppsstm,
+ CodePage,
+ aprs,
+ cprop,
+ iprop,
+ pidStart,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ pidStart = pid + 1;
+ }
+ break;
+ }
+
+ case PRSPEC_PROPID:
+ pid = aprs[iprop].propid;
+ break;
+
+ default:
+ PROPASSERT(!"Bad ulKind");
+ *pstatus = STATUS_INVALID_PARAMETER;
+ goto Exit;
+
+ break;
+ }
+
+ if (apid != NULL)
+ {
+ apid[iprop] = pid;
+ }
+
+ // RtlConvertVariantToProperty returns NULL on overflow and
+ // Raises on bad data.
+
+ cbprop = 0; // Assume property deletion
+ if (pid != PID_ILLEGAL && avar != NULL)
+ {
+ RtlConvertVariantToPropertyNoEH(
+ &avar[iprop],
+ CodePage,
+ NULL,
+ &cbprop,
+ pid,
+ FALSE,
+ pcIndirect,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ PROPASSERT(cbprop == DwordAlign(cbprop));
+ }
+ apinfo[iprop].cbprop = cbprop;
+ apinfo[iprop].pid = pid;
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: BuildIndirectIndexArray, private
+//
+// Synopsis: Set property values for a property set
+//
+// Arguments: [cprop] -- count of properties in avar
+// [cAlloc] -- max count of indirect properties
+// [cIndirect] -- count of indirect properties in avar
+// [avar] -- array of PROPVARIANTs
+// [ppip] -- ptr to ptr to Indirect property structures
+//
+// Returns: None
+//---------------------------------------------------------------------------
+
+VOID
+BuildIndirectIndexArray(
+ IN ULONG cprop, // count of properties in avar
+ IN ULONG cAlloc, // max count of indirect properties
+ IN ULONG cIndirect, // count of indirect properties in avar
+ IN PROPVARIANT const avar[],// array of properties+values
+ OPTIONAL OUT INDIRECTPROPERTY **ppip, // pointer to returned pointer to
+ // MAXULONG terminated array of Indirect
+ // properties w/indexes into aprs & avar
+ OUT NTSTATUS *pstatus)
+{
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(cIndirect > 0);
+ PROPASSERT(cAlloc >= cIndirect);
+ PROPASSERT(cprop >= cAlloc);
+
+ if (ppip != NULL)
+ {
+ INDIRECTPROPERTY *pip;
+ ULONG iprop;
+
+ if (cprop == 1)
+ {
+ pip = (INDIRECTPROPERTY *) ppip;
+ }
+ else
+ {
+ pip = (INDIRECTPROPERTY *) new INDIRECTPROPERTY[cAlloc + 1];
+ if (pip == NULL)
+ {
+ *pstatus = STATUS_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+ *ppip = pip;
+ }
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ if (IsIndirectVarType(avar[iprop].vt))
+ {
+ PROPASSERT(cprop == 1 || (ULONG) (pip - *ppip) < cIndirect);
+ pip->Index = iprop;
+ pip->poszName = NULL;
+ pip++;
+ }
+ }
+ if (cprop > 1)
+ {
+ pip->Index = MAXULONG;
+ PROPASSERT((ULONG) (pip - *ppip) == cIndirect);
+ }
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlSetProperties, public
+//
+// Synopsis: Set property values for a property set
+//
+// Arguments: [np] -- property set context
+// [cprop] -- property count
+// [pidNameFirst] -- first PROPID for new named properties
+// [aprs] -- array of property specifiers
+// [apid] -- buffer for array of propids
+// [ppip] -- ptr to ptr to Indirect property structures
+// [avar] -- array of PROPVARIANTs
+//
+// Returns: Status code
+//---------------------------------------------------------------------------
+
+NTSTATUS PROPSYSAPI PROPAPI
+RtlSetProperties(
+ IN NTPROP np, // property set context
+ IN ULONG cprop, // property count
+ IN PROPID pidNameFirst, // first PROPID for new named properties
+ IN PROPSPEC const aprs[], // array of property specifiers
+ OPTIONAL OUT PROPID apid[], // buffer for array of propids
+ OPTIONAL OUT INDIRECTPROPERTY **ppip, // pointer to returned pointer to
+ // MAXULONG terminated array of Indirect
+ // properties w/indexes into aprs & avar
+ OPTIONAL IN PROPVARIANT const avar[]) // array of properties+values
+{
+ CPropertySetStream *ppsstm = (CPropertySetStream *) np;
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fLocked = FALSE;
+
+ PROPERTY_INFORMATION apinfoStack[6];
+ PROPERTY_INFORMATION *apinfo = apinfoStack;
+ ULONG cIndirect = 0;
+
+ DebugTrace(0, Dbg, (
+ "RtlSetProperties(np=%x, cprop=%x, pidNameFirst=%x, aprs=%x, apid=%x, ppip=%x)\n",
+ np,
+ cprop,
+ pidNameFirst,
+ aprs,
+ apid,
+ ppip));
+
+ // Initialize the INDIRECTPROPERTY structure.
+
+ if (ppip != NULL)
+ {
+ *ppip = NULL;
+
+ // If cprop is 1, ppip is actually pip (one level
+ // of indirection).
+
+ if (cprop == 1)
+ {
+ // Default the index.
+ ((INDIRECTPROPERTY *) ppip)->Index = MAXULONG;
+ }
+ }
+
+ // Lock the property set.
+ Status = ppsstm->Lock(TRUE);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ fLocked = TRUE;
+
+ // Is the stack-based apinfo big enough?
+ if (cprop > sizeof(apinfoStack)/sizeof(apinfoStack[0]))
+ {
+ // No - we need to allocate an apinfo.
+ apinfo = new PROPERTY_INFORMATION[cprop];
+
+ if( NULL == apinfo )
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+ }
+
+ ppsstm->ReOpen(&Status); // Reload header/size info
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ConvertVariantToPropInfo(
+ ppsstm,
+ cprop,
+ pidNameFirst,
+ aprs,
+ apid,
+ avar,
+ apinfo,
+ ppip == NULL? NULL : &cIndirect,
+ &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ // If the caller wants to know about indirect streams and
+ // storages (and if there were any), allocate memory for a
+ // MAXULONG terminated array of indexes to the indirect
+ // variant structures, and fill it in.
+
+ ppsstm->SetValue(cprop, ppip, avar, apinfo, &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // If we allocated a temporary apinfo buffer, free it.
+ if (apinfo != apinfoStack)
+ {
+ delete [] apinfo;
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ if (ppip != NULL)
+ {
+ if (cprop == 1)
+ {
+ ((INDIRECTPROPERTY *) ppip)->Index = MAXULONG;
+ }
+ else if (*ppip != NULL)
+ {
+ delete [] *ppip;
+ *ppip = NULL;
+ }
+ }
+ }
+
+ if (fLocked)
+ Status = Unlock( ppsstm, Status );
+
+ DebugTrace(0, DbgS(Status), (
+ "RtlSetProperties() ==> *ppip=%x, s=%x\n--------\n",
+ ppip == NULL? NULL : *ppip,
+ Status));
+
+ return(Status);
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlQueryProperties, public
+//
+// Synopsis: Query property values from a property set
+//
+// Arguments: [np] -- property set context
+// [cprop] -- property count
+// [aprs] -- array of property specifiers
+// [apid] -- buffer for array of propids
+// [ppip] -- ptr to ptr to Indirect property structures
+// [avar] -- array of PROPVARIANTs
+//
+// Returns: Status code
+//---------------------------------------------------------------------------
+
+NTSTATUS PROPSYSAPI PROPAPI
+RtlQueryProperties(
+ IN NTPROP np, // property set context
+ IN ULONG cprop, // property count
+ IN PROPSPEC const aprs[], // array of property specifiers
+ OPTIONAL OUT PROPID apid[], // buffer for array of propids
+ OPTIONAL OUT INDIRECTPROPERTY **ppip, // pointer to returned pointer to
+ // MAXULONG terminated array of Indirect
+ // properties w/indexes into aprs & avar
+ IN OUT PROPVARIANT *avar, // IN: array of uninitialized PROPVARIANTs,
+ // OUT: may contain pointers to alloc'd memory
+ OUT ULONG *pcpropFound) // count of property values retrieved
+{
+ CPropertySetStream *ppsstm = (CPropertySetStream *) np;
+ SERIALIZEDPROPERTYVALUE const *pprop = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG cIndirect = 0;
+ ULONG iprop;
+ BOOL fLocked = FALSE;
+
+ DebugTrace(0, Dbg, (
+ "RtlQueryProperties(np=%x, cprop=%x, aprs=%x, apid=%x, ppip=%x)\n",
+ np,
+ cprop,
+ aprs,
+ apid,
+ ppip));
+
+ // Initialize the variant array enough to allow it to be cleaned up
+ // by the caller (even on partial failure).
+
+ *pcpropFound = 0;
+ if (ppip != NULL)
+ {
+ *ppip = NULL;
+ if (cprop == 1)
+ {
+ ((INDIRECTPROPERTY *) ppip)->Index = MAXULONG;
+ }
+ }
+
+ // Zero-ing out the caller-provided PropVariants, essentially
+ // sets them all to VT_EMPTY. It also zeros out the data portion,
+ // which prevents cleanup problems in error paths.
+
+ RtlZeroMemory(avar, cprop * sizeof(avar[0]));
+
+
+ Status = ppsstm->Lock(FALSE);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ fLocked = TRUE;
+
+ ppsstm->ReOpen(&Status); // Reload header/size info
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ PROPID pid;
+ ULONG cbprop;
+
+ switch(aprs[iprop].ulKind)
+ {
+ case PRSPEC_LPWSTR:
+ pid = ppsstm->QueryPropid(aprs[iprop].lpwstr, &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ break;
+
+ case PRSPEC_PROPID:
+ pid = aprs[iprop].propid;
+ break;
+
+ default:
+ PROPASSERT(!"Bad ulKind");
+ Status = STATUS_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ pprop = ppsstm->GetValue(pid, &cbprop, &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ if (pprop != NULL)
+ {
+ BOOL fIndirect;
+
+ (*pcpropFound)++;
+ fIndirect = RtlConvertPropertyToVariantNoEH(
+ pprop,
+ ppsstm->GetCodePage(),
+ &avar[iprop],
+ ppsstm->GetAllocator(),
+ &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ if( fIndirect )
+ {
+ cIndirect++;
+ }
+ }
+ if (apid != NULL)
+ {
+ apid[iprop] = pid;
+ }
+ } // for (iprop = 0; iprop < cprop; iprop++)
+
+ // If the caller wants to know about indirect streams and
+ // storages (and if there were any), allocate memory for a
+ // MAXULONG terminated array of indexes to the indirect
+ // variant structures, and fill it in.
+
+ if (cIndirect != 0)
+ {
+ BuildIndirectIndexArray(
+ cprop,
+ cIndirect,
+ cIndirect,
+ avar,
+ ppip,
+ &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ }
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( !NT_SUCCESS(Status) )
+ {
+ if (ppip != NULL)
+ {
+ if (cprop == 1)
+ {
+ ((INDIRECTPROPERTY *) ppip)->Index = MAXULONG;
+ }
+ else if (*ppip != NULL)
+ {
+ delete [] *ppip;
+ *ppip = NULL;
+ }
+ }
+ CleanupVariants(avar, cprop, ppsstm->GetAllocator());
+ }
+
+ if (fLocked)
+ Status = Unlock( ppsstm, Status );
+
+ DebugTrace(0, DbgS(Status), (
+ "RtlQueryProperties() ==> *ppip=%x, s=%x\n--------\n",
+ ppip == NULL? NULL : *ppip,
+ Status));
+
+ return(Status);
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlEnumerateProperties, public
+//
+// Synopsis: Enumerate properties in a property set
+//
+// Arguments: [np] -- property set context
+// [cskip] -- count of properties to skip
+// [pcprop] -- pointer to property count
+// [Flags] -- flags: No Names (propids only), etc.
+// [asps] -- array of STATPROPSTGs
+//
+// Returns: Status code
+//---------------------------------------------------------------------------
+
+NTSTATUS PROPSYSAPI PROPAPI
+RtlEnumerateProperties(
+ IN NTPROP np, // property set context
+ IN ULONG Flags, // flags: No Names (propids only), etc.
+ IN ULONG *pkey, // count of properties to skip
+ IN OUT ULONG *pcprop, // pointer to property count
+ OPTIONAL OUT PROPSPEC aprs[],// IN: array of uninitialized PROPSPECs
+ // OUT: may contain pointers to alloc'd strings
+ OPTIONAL OUT STATPROPSTG asps[]) // IN: array of uninitialized STATPROPSTGs
+ // OUT: may contain pointers to alloc'd strings
+{
+ CPropertySetStream *ppsstm = (CPropertySetStream *) np;
+ NTSTATUS Status = STATUS_SUCCESS;
+ SERIALIZEDPROPERTYVALUE const *pprop = NULL;
+ PROPSPEC *pprs;
+ STATPROPSTG *psps;
+ PROPID *ppidBase = NULL;
+ ULONG i;
+ ULONG cpropin;
+ BOOL fLocked = FALSE;
+
+ PROPID apidStack[20];
+ PROPID *ppid;
+ ULONG cprop;
+ PMemoryAllocator *pma = ppsstm->GetAllocator();
+
+ DebugTrace(0, Dbg, (
+ "RtlEnumerateProperties(np=%x, f=%x, key=%x, cprop=%x, aprs=%x, asps=%x)\n",
+ np,
+ Flags,
+ *pkey,
+ *pcprop,
+ aprs,
+ asps));
+
+ cpropin = *pcprop;
+
+ // Eliminate confusion for easy cleanup
+
+ if (aprs != NULL)
+ {
+ // Set all the PropSpecs to PROPID (which require
+ // no cleanup).
+
+ for (i = 0; i < cpropin; i++)
+ {
+ aprs[i].ulKind = PRSPEC_PROPID;
+ }
+ }
+
+ // Zero all pointers in the array for easy cleanup
+
+ if (asps != NULL)
+ {
+ RtlZeroMemory(asps, cpropin * sizeof(asps[0]));
+ }
+
+ Status = ppsstm->Lock(FALSE);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ fLocked = TRUE;
+
+
+ ppidBase = NULL;
+
+ cprop = ppsstm->ReOpen(&Status); // Reload header/size info
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ if (cprop > cpropin)
+ {
+ cprop = cpropin;
+ }
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppid = NULL;
+ if (aprs != NULL || asps != NULL)
+ {
+ ppid = apidStack;
+ if (cprop > sizeof(apidStack)/sizeof(apidStack[0]))
+ {
+ ppidBase = new PROPID[cprop];
+ if (ppidBase == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+ ppid = ppidBase;
+ }
+ }
+
+ ppsstm->EnumeratePropids(pkey, &cprop, ppid, &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ *pcprop = cprop;
+
+ if (ppid != NULL)
+ {
+ psps = asps;
+ pprs = aprs;
+ while (cprop-- > 0)
+ {
+ OLECHAR aocName[CCH_MAXPROPNAMESZ];
+
+ ULONG cbName;
+ ULONG cbprop;
+ BOOLEAN fHasName;
+
+ PROPASSERT(*ppid != PID_DICTIONARY && *ppid != PID_CODEPAGE);
+ fHasName = FALSE;
+
+ if ((Flags & ENUMPROP_NONAMES) == 0)
+ {
+ cbName = sizeof(aocName);
+ fHasName = ppsstm->QueryPropertyNameBuf(
+ *ppid,
+ aocName,
+ &cbName,
+ &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ }
+
+ if (pprs != NULL)
+ {
+ PROPASSERT(pprs->ulKind == PRSPEC_PROPID);
+ if (fHasName)
+ {
+ pprs->lpwstr = ppsstm->DuplicatePropertyName(
+ aocName,
+ cbName,
+ &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ PROPASSERT(pprs->lpwstr != NULL);
+
+ // Make this assignment *after* memory allocation
+ // succeeds so we free only valid pointers in below
+ // cleanup code.
+ pprs->ulKind = PRSPEC_LPWSTR;
+ }
+ else
+ {
+ pprs->propid = *ppid;
+ }
+ pprs++;
+
+ } // if (pprs != NULL)
+
+ if (psps != NULL)
+ {
+ pprop = ppsstm->GetValue(*ppid, &cbprop, &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ PROPASSERT(psps->lpwstrName == NULL);
+ if (fHasName)
+ {
+ psps->lpwstrName = ppsstm->DuplicatePropertyName(
+ aocName,
+ cbName,
+ &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ PROPASSERT(psps->lpwstrName != NULL);
+ }
+
+ psps->propid = *ppid;
+ psps->vt = (VARTYPE) PropByteSwap( pprop->dwType );
+
+ psps++;
+
+ } // if (psps != NULL)
+
+ ppid++;
+
+ } // while (cprop-- > 0)
+ } // if (ppid != NULL)
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if (fLocked)
+ Status = Unlock( ppsstm, Status );
+
+ delete [] ppidBase;
+
+ if (!NT_SUCCESS(Status))
+ {
+ PMemoryAllocator *pma = ppsstm->GetAllocator();
+
+ if (aprs != NULL)
+ {
+ for (i = 0; i < cpropin; i++)
+ {
+ if (aprs[i].ulKind == PRSPEC_LPWSTR)
+ {
+ pma->Free(aprs[i].lpwstr);
+ aprs[i].ulKind = PRSPEC_PROPID;
+ }
+ }
+ }
+
+ if (asps != NULL)
+ {
+ for (i = 0; i < cpropin; i++)
+ {
+ if (asps[i].lpwstrName != NULL)
+ {
+ pma->Free(asps[i].lpwstrName);
+ asps[i].lpwstrName = NULL;
+ }
+ }
+ }
+ } // if (!NT_SUCCESS(Status))
+
+#if DBG
+ if (NT_SUCCESS(Status))
+ {
+ if (aprs != NULL)
+ {
+ for (i = 0; i < cpropin; i++)
+ {
+ if (aprs[i].ulKind == PRSPEC_LPWSTR)
+ {
+ PROPASSERT(aprs[i].lpwstr != NULL);
+ PROPASSERT(ocslen(aprs[i].lpwstr) > 0);
+ }
+ }
+ }
+ if (asps != NULL)
+ {
+ for (i = 0; i < cpropin; i++)
+ {
+ if (asps[i].lpwstrName != NULL)
+ {
+ PROPASSERT(ocslen(asps[i].lpwstrName) > 0);
+ }
+ }
+ }
+ }
+#endif // DBG
+
+ DebugTrace(0, DbgS(Status), (
+ "RtlEnumerateProperties() ==> key=%x, cprop=%x, s=%x\n--------\n",
+ *pkey,
+ *pcprop,
+ Status));
+
+ return(Status);
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlQueryPropertyNames, public
+//
+// Synopsis: Read property names for PROPIDs in a property set
+//
+// Arguments: [np] -- property set context
+// [cprop] -- property count
+// [apid] -- array of PROPIDs
+// [aposz] -- array of pointers to WCHAR strings
+//
+// Returns: Status code
+//---------------------------------------------------------------------------
+
+NTSTATUS PROPSYSAPI PROPAPI
+RtlQueryPropertyNames(
+ IN NTPROP np, // property set context
+ IN ULONG cprop, // property count
+ IN PROPID const *apid, // PROPID array
+ OUT OLECHAR *aposz[]) // OUT pointers to allocated strings
+{
+ CPropertySetStream *ppsstm = (CPropertySetStream *) np;
+ NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS StatusQuery = STATUS_SUCCESS;
+ BOOL fLocked = FALSE;
+
+ DebugTrace(0, Dbg, (
+ "RtlQueryPropertyNames(np=%x, cprop=%x, apid=%x, apwsz=%x)\n",
+ np,
+ cprop,
+ apid,
+ aposz));
+
+ RtlZeroMemory(aposz, cprop * sizeof(aposz[0]));
+
+ Status = ppsstm->Lock(FALSE);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ fLocked = TRUE;
+
+ ppsstm->ReOpen(&Status); // Reload header/size info
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ // We'll save the Status from the following call. If there
+ // are no other errors, we'll return it to the caller (it
+ // might contain a useful success code).
+
+ ppsstm->QueryPropertyNames(cprop, apid, aposz, &StatusQuery);
+ if( !NT_SUCCESS(StatusQuery) )
+ {
+ Status = StatusQuery;
+ goto Exit;
+ }
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if (fLocked)
+ Status = Unlock( ppsstm, Status );
+
+ DebugTrace(
+ 0,
+ Status == STATUS_BUFFER_ALL_ZEROS? Dbg : DbgS(Status),
+ ("RtlQueryPropertyNames() ==> s=%x\n--------\n", Status));
+
+ if( NT_SUCCESS(Status) )
+ Status = StatusQuery;
+
+ return(Status);
+
+} // RtlQueryPropertyNames()
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlSetPropertyNames, public
+//
+// Synopsis: Write property names for PROPIDs in a property set
+//
+// Arguments: [np] -- property set context
+// [cprop] -- property count
+// [apid] -- array of PROPIDs
+// [aposz] -- array of pointers to OLECHAR strings
+//
+// Returns: Status code
+//---------------------------------------------------------------------------
+
+NTSTATUS PROPSYSAPI PROPAPI
+RtlSetPropertyNames(
+ IN NTPROP np, // property set context
+ IN ULONG cprop, // property count
+ IN PROPID const *apid, // PROPID array
+ IN OLECHAR const * const aposz[]) // pointers to property names
+{
+ CPropertySetStream *ppsstm = (CPropertySetStream *) np;
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fLocked = FALSE;
+
+ DebugTrace(0, Dbg, (
+ "RtlSetPropertyNames(np=%x, cprop=%x, apid=%x, apwsz=%x)\n",
+ np,
+ cprop,
+ apid,
+ aposz));
+
+ Status = ppsstm->Lock(TRUE);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ fLocked = TRUE;
+
+ ppsstm->ReOpen(&Status); // Reload header/size info
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->SetPropertyNames(cprop, apid, aposz, &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if (fLocked)
+ Status = Unlock( ppsstm, Status );
+
+ DebugTrace(0, DbgS(Status), ("RtlSetPropertyNames() ==> s=%x\n--------\n", Status));
+ return(Status);
+
+} // RtlSetPropertyNames()
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlSetPropertySetClassId, public
+//
+// Synopsis: Set the property set's ClassId
+//
+// Arguments: [np] -- property set context
+// [pspss] -- pointer to STATPROPSETSTG
+//
+// Returns: Status code
+//---------------------------------------------------------------------------
+
+NTSTATUS PROPSYSAPI PROPAPI
+RtlSetPropertySetClassId(
+ IN NTPROP np, // property set context
+ IN GUID const *pclsid) // new CLASSID of propset code
+{
+ CPropertySetStream *ppsstm = (CPropertySetStream *) np;
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fLocked = FALSE;
+
+ DebugTrace(0, Dbg, ("RtlSetPropertySetClassId(np=%x)\n", np));
+
+ Status = ppsstm->Lock(TRUE);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ fLocked = TRUE;
+
+ ppsstm->ReOpen(&Status); // Reload header/size info
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->SetClassId(pclsid, &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if (fLocked)
+ Status = Unlock( ppsstm, Status );
+
+ DebugTrace(0, DbgS(Status), ("RtlSetPropertySetClassId() ==> s=%x\n--------\n", Status));
+ return(Status);
+
+} // RtlSetPropertySetClassId()
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlQueryPropertySet, public
+//
+// Synopsis: Query the passed property set
+//
+// Arguments: [np] -- property set context
+// [pspss] -- pointer to STATPROPSETSTG
+//
+// Returns: Status code
+//---------------------------------------------------------------------------
+
+NTSTATUS PROPSYSAPI PROPAPI
+RtlQueryPropertySet(
+ IN NTPROP np, // property set context
+ OUT STATPROPSETSTG *pspss) // buffer for property set stat information
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ BOOL fLocked = FALSE;
+ CPropertySetStream *ppsstm = (CPropertySetStream *) np;
+
+ DebugTrace(0, Dbg, ("RtlQueryPropertySet(np=%x, pspss=%x)\n", np, pspss));
+ RtlZeroMemory(pspss, sizeof(*pspss));
+
+ Status = ppsstm->Lock(FALSE);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+ fLocked = TRUE;
+
+ ppsstm->ReOpen(&Status); // Reload header/size info
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->QueryPropertySet(pspss, &Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ ppsstm->Validate(&Status);
+ if( !NT_SUCCESS(Status) ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if (fLocked)
+ Status = Unlock( ppsstm, Status );
+
+ DebugTrace(0, DbgS(Status), ("RtlQueryPropertySet() ==> s=%x\n--------\n", Status));
+ return(Status);
+
+} // RtlQueryPropertySet()
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlEnumeratePropertySets, public
+//
+// Synopsis: Enumerate property sets on a structured storage
+//
+// Arguments: [hstg] -- structured storage handle
+// [pcspss] -- pointer to count of STATPROPSETSTGs
+// [pkey] -- bookmark; caller set to 0 before 1st call
+// [pspss] -- array of STATPROPSETSTGs
+//
+// Returns: Status code
+//---------------------------------------------------------------------------
+
+#ifdef _CAIRO_
+NTSTATUS PROPSYSAPI PROPAPI
+RtlEnumeratePropertySets(
+ IN HANDLE hstg, // structured storage handle
+ IN BOOLEAN fRestart, // TRUE --> restart scan
+ IN OUT ULONG *pcspss, // pointer to count of STATPROPSETSTGs
+ IN OUT GUID *pkey, // bookmark
+ OUT STATPROPSETSTG *pspss) // array of STATPROPSETSTGs
+{
+ NTSTATUS Status;
+ LONGLONG abufStack[2048/sizeof(LONGLONG)];
+ ULONG cspss = 0;
+ GUID *pguidLast;
+ IO_STATUS_BLOCK isb;
+ BOOLEAN fFoundKey, fRestartOleEnum;
+#ifndef USE_OLE_DIR_FILE
+ UNICODE_STRING strProp;
+ UNICODE_STRING *pstr;
+#endif
+
+ DebugTrace(0, Dbg, (
+ "RtlEnumeratePropertySets(h=%x, fRestart=%x, cspss=%x, key=%x, pspss=%x)\n",
+ hstg,
+ fRestart,
+ *pcspss,
+ *pkey,
+ pspss));
+
+ if (*pcspss == 0)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto exit;
+ }
+
+ fFoundKey = fRestart; // assume start at first propset AFTER *pkey.
+
+#ifndef USE_OLE_DIR_FILE
+ strProp.Length = strProp.MaximumLength = 2*sizeof(WCHAR);
+ strProp.Buffer = L"\1*";
+#endif
+
+forcerestart:
+#ifndef USE_OLE_DIR_FILE
+ pstr = &strProp;
+#endif
+ fRestartOleEnum = TRUE;
+
+ while (TRUE)
+ {
+ FILE_OLE_DIR_INFORMATION *pfodiBase;
+ FILE_OLE_DIR_INFORMATION *pfodi, *pfodiEnd;
+ ULONG NextOffset;
+
+#ifndef USE_OLE_DIR_FILE
+#define NtQueryOleDirectoryFile NtQueryDirectoryFile
+#endif
+ pfodiBase = (FILE_OLE_DIR_INFORMATION *) abufStack;
+
+ Status = NtQueryOleDirectoryFile(
+ hstg,
+ NULL,
+ NULL,
+ NULL,
+ &isb,
+ pfodiBase,
+ sizeof(abufStack),
+ FileOleDirectoryInformation,
+ FALSE,
+#ifndef USE_OLE_DIR_FILE
+ pstr,
+#else
+ NULL,
+#endif
+ fRestartOleEnum);
+ if (!NT_SUCCESS(Status))
+ {
+ break;
+ }
+#ifndef USE_OLE_DIR_FILE
+ pstr = NULL;
+#endif
+ fRestartOleEnum = FALSE;
+
+ // copy out requested info
+
+ pfodi = pfodiBase;
+ pfodiEnd = (FILE_OLE_DIR_INFORMATION *)
+ Add2Ptr(pfodiBase, isb.Information);
+
+ do
+ {
+ GUID guid;
+
+ if ((pfodi->FileAttributes & FILE_ATTRIBUTE_PROPERTY_SET) &&
+ NT_SUCCESS(RtlPropertySetNameToGuid(
+ pfodi->FileNameLength/sizeof(WCHAR),
+ pfodi->FileName,
+ &guid)))
+ {
+ if (fFoundKey)
+ {
+ if (cspss >= *pcspss)
+ {
+ break; // return success
+ }
+ pspss->fmtid = guid;
+ pguidLast = &pspss->fmtid;
+
+ CopyFileTime(&pspss->mtime, &pfodi->LastWriteTime);
+
+ if (pfodi->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ pspss->grfFlags = PROPSETFLAG_NONSIMPLE;
+ CopyFileTime(&pspss->ctime, &pfodi->CreationTime);
+ CopyFileTime(&pspss->atime, &pfodi->LastAccessTime);
+ pspss->clsid = pfodi->OleClassId;
+ }
+ else
+ {
+ pspss->grfFlags = PROPSETFLAG_DEFAULT;
+ ZeroFileTime(&pspss->ctime);
+ ZeroFileTime(&pspss->atime);
+ RtlZeroMemory(&pspss->clsid, sizeof(pspss->clsid));
+ }
+ pspss++;
+ cspss++;
+ }
+ else if (RtlCompareMemory(
+ pkey,
+ &guid,
+ sizeof(guid)) == sizeof(guid))
+ {
+ fFoundKey = TRUE;
+ }
+ }
+ NextOffset = pfodi->NextEntryOffset;
+ pfodi = (FILE_OLE_DIR_INFORMATION *) Add2Ptr(pfodi, NextOffset);
+ } while (NextOffset != 0 && pfodi < pfodiEnd);
+ }
+ if (Status == STATUS_NO_SUCH_FILE || Status == STATUS_NO_MORE_FILES)
+ {
+ Status = STATUS_SUCCESS;
+ }
+ if (NT_SUCCESS(Status))
+ {
+ // if we didn't find the search key, it must have been deleted.
+ // Loop back and start with the first 'real' property set.
+ // 'Tis better to return duplicates, than to skip entries.
+
+ if (!fFoundKey)
+ {
+ PROPASSERT(cspss == 0);
+ fFoundKey = TRUE;
+ goto forcerestart;
+ }
+ if (cspss == 0)
+ {
+ Status = STATUS_PROPSET_NOT_FOUND;
+ }
+ else
+ {
+ *pkey = *pguidLast;
+ }
+ }
+
+exit:
+ *pcspss = cspss; // return actual count
+
+ DebugTrace(
+ 0,
+ Status == STATUS_PROPSET_NOT_FOUND? Dbg : DbgS(Status), (
+ "RtlEnumeratePropertySets() ==> cspss=%x, pkey=%x, s=%x\n--------\n",
+ *pcspss,
+ pkey,
+ Status));
+
+ return(Status);
+}
+#endif // ifdef _CAIRO_
+
+
+
+inline BOOLEAN
+_Compare_VT_BOOL(VARIANT_BOOL bool1, VARIANT_BOOL bool2)
+{
+ // Allow any non-zero value to match any non-zero value
+
+ return((bool1 == FALSE) == (bool2 == FALSE));
+}
+
+
+BOOLEAN
+_Compare_VT_CF(CLIPDATA *pclipdata1, CLIPDATA *pclipdata2)
+{
+ BOOLEAN fSame;
+
+ if (pclipdata1 != NULL && pclipdata2 != NULL)
+ {
+ fSame = ( pclipdata1->cbSize == pclipdata2->cbSize
+ &&
+ pclipdata1->ulClipFmt == pclipdata2->ulClipFmt );
+
+ if (fSame)
+ {
+ if (pclipdata1->pClipData != NULL && pclipdata2->pClipData != NULL)
+ {
+ fSame = memcmp(
+ pclipdata1->pClipData,
+ pclipdata2->pClipData,
+ CBPCLIPDATA(*pclipdata1)
+ ) == 0;
+ }
+ else
+ {
+ // They're the same if both are NULL, or if
+ // they have a zero length (if they have a zero
+ // length, either one may or may not be NULL, but they're
+ // still considered the same).
+ // Note that CBPCLIPDATA(*pclipdata1)==CBPCLIPDATA(*pclipdata2).
+
+ fSame = pclipdata1->pClipData == pclipdata2->pClipData
+ ||
+ CBPCLIPDATA(*pclipdata1) == 0;
+ }
+ }
+ }
+ else
+ {
+ fSame = pclipdata1 == pclipdata2;
+ }
+ return(fSame);
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlCompareVariants, public
+//
+// Synopsis: Compare two passed PROPVARIANTs -- case sensitive for strings
+//
+// Arguments: [CodePage] -- CodePage
+// [pvar1] -- pointer to PROPVARIANT
+// [pvar2] -- pointer to PROPVARIANT
+//
+// Returns: TRUE if identical, else FALSE
+//---------------------------------------------------------------------------
+
+#ifdef _MAC
+EXTERN_C // The Mac linker doesn't seem to be able to export with C++ decorations
+#endif
+
+BOOLEAN PROPSYSAPI PROPAPI
+RtlCompareVariants(
+ USHORT CodePage,
+ PROPVARIANT const *pvar1,
+ PROPVARIANT const *pvar2)
+{
+ if (pvar1->vt != pvar2->vt)
+ {
+ return(FALSE);
+ }
+
+ BOOLEAN fSame;
+ ULONG i;
+
+ switch (pvar1->vt)
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ fSame = TRUE;
+ break;
+
+#ifdef PROPVAR_VT_I1
+ case VT_I1:
+#endif
+ case VT_UI1:
+ fSame = pvar1->bVal == pvar2->bVal;
+ break;
+
+ case VT_I2:
+ case VT_UI2:
+ fSame = pvar1->iVal == pvar2->iVal;
+ break;
+
+ case VT_BOOL:
+ fSame = _Compare_VT_BOOL(pvar1->boolVal, pvar2->boolVal);
+ break;
+
+ case VT_I4:
+ case VT_UI4:
+ case VT_R4:
+ case VT_ERROR:
+ fSame = pvar1->lVal == pvar2->lVal;
+ break;
+
+ case VT_I8:
+ case VT_UI8:
+ case VT_R8:
+ case VT_CY:
+ case VT_DATE:
+ case VT_FILETIME:
+ fSame = pvar1->hVal.HighPart == pvar2->hVal.HighPart
+ &&
+ pvar1->hVal.LowPart == pvar2->hVal.LowPart;
+ break;
+
+ case VT_CLSID:
+ fSame = memcmp(pvar1->puuid, pvar2->puuid, sizeof(CLSID)) == 0;
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ fSame = ( pvar1->blob.cbSize == pvar2->blob.cbSize );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->blob.pBlobData,
+ pvar2->blob.pBlobData,
+ pvar1->blob.cbSize) == 0;
+ }
+ break;
+
+ case VT_CF:
+ fSame = _Compare_VT_CF(pvar1->pclipdata, pvar2->pclipdata);
+ break;
+
+ case VT_BSTR:
+ if (pvar1->bstrVal != NULL && pvar2->bstrVal != NULL)
+ {
+ fSame = ( BSTRLEN(pvar1->bstrVal) == BSTRLEN(pvar2->bstrVal) );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->bstrVal,
+ pvar2->bstrVal,
+ BSTRLEN(pvar1->bstrVal)) == 0;
+ }
+ }
+ else
+ {
+ fSame = pvar1->bstrVal == pvar2->bstrVal;
+ }
+ break;
+
+ case VT_LPSTR:
+ if (pvar1->pszVal != NULL && pvar2->pszVal != NULL)
+ {
+ fSame = strcmp(pvar1->pszVal, pvar2->pszVal) == 0;
+ }
+ else
+ {
+ fSame = pvar1->pszVal == pvar2->pszVal;
+ }
+ break;
+
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ case VT_LPWSTR:
+ if (pvar1->pwszVal != NULL && pvar2->pwszVal != NULL)
+ {
+ fSame = Prop_wcscmp(pvar1->pwszVal, pvar2->pwszVal) == 0;
+ }
+ else
+ {
+ fSame = pvar1->pwszVal == pvar2->pwszVal;
+ }
+ break;
+
+#ifdef PROPVAR_VT_I1
+ case VT_VECTOR | VT_I1:
+#endif
+ case VT_VECTOR | VT_UI1:
+ fSame = ( pvar1->caub.cElems == pvar2->caub.cElems );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->caub.pElems,
+ pvar2->caub.pElems,
+ pvar1->caub.cElems * sizeof(pvar1->caub.pElems[0])) == 0;
+ }
+ break;
+
+ case VT_VECTOR | VT_I2:
+ case VT_VECTOR | VT_UI2:
+ fSame = ( pvar1->cai.cElems == pvar2->cai.cElems );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->cai.pElems,
+ pvar2->cai.pElems,
+ pvar1->cai.cElems * sizeof(pvar1->cai.pElems[0])) == 0;
+ }
+ break;
+
+ case VT_VECTOR | VT_BOOL:
+ fSame = ( pvar1->cabool.cElems == pvar2->cabool.cElems );
+ if (fSame)
+ {
+ for (i = 0; i < pvar1->cabool.cElems; i++)
+ {
+ fSame = _Compare_VT_BOOL(
+ pvar1->cabool.pElems[i],
+ pvar2->cabool.pElems[i]);
+ if (!fSame)
+ {
+ break;
+ }
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_I4:
+ case VT_VECTOR | VT_UI4:
+ case VT_VECTOR | VT_R4:
+ case VT_VECTOR | VT_ERROR:
+ fSame = ( pvar1->cal.cElems == pvar2->cal.cElems );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->cal.pElems,
+ pvar2->cal.pElems,
+ pvar1->cal.cElems * sizeof(pvar1->cal.pElems[0])) == 0;
+ }
+ break;
+
+ case VT_VECTOR | VT_I8:
+ case VT_VECTOR | VT_UI8:
+ case VT_VECTOR | VT_R8:
+ case VT_VECTOR | VT_CY:
+ case VT_VECTOR | VT_DATE:
+ case VT_VECTOR | VT_FILETIME:
+ fSame = ( pvar1->cah.cElems == pvar2->cah.cElems );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->cah.pElems,
+ pvar2->cah.pElems,
+ pvar1->cah.cElems *
+ sizeof(pvar1->cah.pElems[0])) == 0;
+ }
+ break;
+
+ case VT_VECTOR | VT_CLSID:
+ fSame = ( pvar1->cauuid.cElems == pvar2->cauuid.cElems );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->cauuid.pElems,
+ pvar2->cauuid.pElems,
+ pvar1->cauuid.cElems *
+ sizeof(pvar1->cauuid.pElems[0])) == 0;
+ }
+ break;
+
+ case VT_VECTOR | VT_CF:
+ fSame = ( pvar1->caclipdata.cElems == pvar2->caclipdata.cElems );
+ if (fSame)
+ {
+ for (i = 0; i < pvar1->caclipdata.cElems; i++)
+ {
+ fSame = _Compare_VT_CF(
+ &pvar1->caclipdata.pElems[i],
+ &pvar2->caclipdata.pElems[i]);
+ if (!fSame)
+ {
+ break;
+ }
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_BSTR:
+ fSame = ( pvar1->cabstr.cElems == pvar2->cabstr.cElems );
+ if (fSame)
+ {
+ for (i = 0; i < pvar1->cabstr.cElems; i++)
+ {
+ if (pvar1->cabstr.pElems[i] != NULL &&
+ pvar2->cabstr.pElems[i] != NULL)
+ {
+ fSame = ( BSTRLEN(pvar1->cabstr.pElems[i])
+ ==
+ BSTRLEN(pvar2->cabstr.pElems[i]) );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->cabstr.pElems[i],
+ pvar2->cabstr.pElems[i],
+ BSTRLEN(pvar1->cabstr.pElems[i])) == 0;
+ }
+ }
+ else
+ {
+ fSame = pvar1->cabstr.pElems[i] == pvar2->cabstr.pElems[i];
+ }
+ if (!fSame)
+ {
+ break;
+ }
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_LPSTR:
+ fSame = ( pvar1->calpstr.cElems == pvar2->calpstr.cElems );
+ if (fSame)
+ {
+ for (i = 0; i < pvar1->calpstr.cElems; i++)
+ {
+ if (pvar1->calpstr.pElems[i] != NULL &&
+ pvar2->calpstr.pElems[i] != NULL)
+ {
+ fSame = strcmp(
+ pvar1->calpstr.pElems[i],
+ pvar2->calpstr.pElems[i]) == 0;
+ }
+ else
+ {
+ fSame = pvar1->calpstr.pElems[i] ==
+ pvar2->calpstr.pElems[i];
+ }
+ if (!fSame)
+ {
+ break;
+ }
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_LPWSTR:
+ fSame = ( pvar1->calpwstr.cElems == pvar2->calpwstr.cElems );
+ if (fSame)
+ {
+ for (i = 0; i < pvar1->calpwstr.cElems; i++)
+ {
+ if (pvar1->calpwstr.pElems[i] != NULL &&
+ pvar2->calpwstr.pElems[i] != NULL)
+ {
+ fSame = Prop_wcscmp(
+ pvar1->calpwstr.pElems[i],
+ pvar2->calpwstr.pElems[i]) == 0;
+ }
+ else
+ {
+ fSame = pvar1->calpwstr.pElems[i] ==
+ pvar2->calpwstr.pElems[i];
+ }
+ if (!fSame)
+ {
+ break;
+ }
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_VARIANT:
+ fSame = ( pvar1->capropvar.cElems == pvar2->capropvar.cElems );
+ if (fSame)
+ {
+ for (i = 0; i < pvar1->capropvar.cElems; i++)
+ {
+ fSame = RtlCompareVariants(
+ CodePage,
+ &pvar1->capropvar.pElems[i],
+ &pvar2->capropvar.pElems[i]);
+ if (!fSame)
+ {
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ PROPASSERT(!"Invalid type for PROPVARIANT Comparison");
+ fSame = FALSE;
+ break;
+
+ }
+ return(fSame);
+}
diff --git a/private/ole32/stg/props/pch.cxx b/private/ole32/stg/props/pch.cxx
new file mode 100644
index 000000000..830915383
--- /dev/null
+++ b/private/ole32/stg/props/pch.cxx
@@ -0,0 +1,102 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1995.
+//
+// File: pch.cxx
+//
+// Contents: Precompiled header includes.
+//
+//--------------------------------------------------------------------------
+
+
+extern "C"
+{
+# include <nt.h>
+# include <ntrtl.h>
+# include <nturtl.h>
+# include <windef.h>
+}
+
+#include <ddeml.h>
+#include <objbase.h>
+
+#if IPROPERTY_DLL
+#include "ipropidl.h"
+#endif
+
+#ifdef _CAIRO_
+#define _CAIROSTG_
+#include <oleext.h>
+#endif
+#include <stgint.h>
+
+#include <valid.h>
+
+#include <debnot.h>
+
+#include <otrack.hxx>
+#include <funcs.hxx>
+#include <safedecl.hxx>
+#include <infs.hxx>
+
+
+#include <propset.h> // for PROPID_CODEPAGE
+
+#ifdef _CAIRO_
+#include <iofs.h> // Declaration for NtSetProperties etc
+ // FNNTPROPALLOC etc
+#else
+extern "C"
+{
+#include <propapi.h>
+}
+#endif
+
+#include <propstm.hxx> // Declaration for CMappedStream i/f that
+ // is used to let the ntdll implementation of
+ // OLE properties access the underlying stream data.
+
+#include <olechar.h> // Wrappers. E.g.: ocscpy, ocscat.
+
+#ifndef IPROPERTY_DLL
+# include <msf.hxx>
+# include <publicdf.hxx>
+# include <pbstream.hxx>
+# include <expdf.hxx>
+# include <expst.hxx>
+#endif
+
+#include <privoa.h> // Private OleAut32 wrappers
+#include <psetstg.hxx> // CPropertySetStorage which implements
+ // IPropertySetStorage for docfile and ofs
+
+#include <utils.hxx>
+
+#include <propstg.hxx>
+#include <CFMapStm.hxx>
+#include <propdbg.hxx>
+
+#include <propmac.hxx>
+
+#include <reserved.hxx>
+#include <objidl.h>
+
+extern WCHAR const wcsContents[];
+extern const GUID GUID_NULL;
+
+#define DfpAssert Win4Assert
+#define DFMAXPROPSETSIZE (256*1024)
+
+#if DBG
+#define DfpVerify(x) { BOOL f=x; GetLastError(); DfpAssert(f);}
+#else
+#define DfpVerify(x) x
+#endif
+
+
+#ifndef STG_E_PROPSETMISMATCHED
+#define STG_E_PROPSETMISMATCHED 0x800300F0
+#endif
+
+#pragma hdrstop
diff --git a/private/ole32/stg/props/propapi.cxx b/private/ole32/stg/props/propapi.cxx
new file mode 100644
index 000000000..462b2a4bf
--- /dev/null
+++ b/private/ole32/stg/props/propapi.cxx
@@ -0,0 +1,573 @@
+
+
+//+==================================================================
+//
+// File: PropAPI.cxx
+//
+// This file provides the Property Set API routines.
+//
+// APIs: StgCreatePropSetStg (creates an IPropertySetStorage)
+//
+// StgCreatePropStg (creates an IPropertyStorage)
+//
+// StgOpenPropStg (opens an IPropertyStorage)
+//
+//+==================================================================
+
+#include <pch.cxx>
+
+#ifdef _MAC_NODOC
+ASSERTDATA // File-specific data for FnAssert
+#endif
+
+//+------------------------------------------------------------------
+//
+// Function: QueryForIStream
+//
+// Synopsis: This routine queries an IUnknown for
+// an IStream interface. This is isolated into
+// a separate routine because some workaround code
+// is required on the Mac.
+//
+// Inputs: [IUnknown*] pUnk
+// The interface to be queried.
+// [IStream**] ppStm
+// Location to return the result.
+//
+// Returns: [HRESULT]
+//
+// Notes: On older Mac implementations (<=2.08, <=~1996)
+// the memory-based IStream implementation
+// (created by CreateStreamOnHGlobal) had a bug
+// in QueryInterface: when you QI for an
+// IStream or IUnknown, an addref is done, but an
+// HR of E_NOINTERFACE is returned.
+//
+// Below, we look for this condition: if we get an
+// E_NOINTERFACE on the Mac, we check to see if it's
+// an OLE mem-based IStream. If it is, we simply cast
+// IUnknown as an IStream. We validate it as an OLE
+// the mem-based IStream by creating one of our own, and
+// comparing the QueryInterface addresses.
+//
+// This is some ugly code, but at least it is isolated,
+// only runs on the older Macs, and ensures that we
+// work on all platforms.
+//
+//+------------------------------------------------------------------
+
+
+inline HRESULT QueryForIStream( IUnknown * pUnk, IStream** ppStm )
+{
+ HRESULT hr;
+
+ // Attempt to get the interface
+ hr = pUnk->QueryInterface( IID_IStream, (void**) ppStm );
+
+#ifdef _MAC
+
+ // On the Mac, if we get a no-interface error, see if it is really
+ // a buggy mem-based IStream implementation.
+
+ if( E_NOINTERFACE == hr )
+ {
+ IStream *pstmMem = NULL;
+
+ // Create our own mem-based IStream.
+
+ hr = CreateStreamOnHGlobal( NULL, TRUE, &pstmMem );
+ if( FAILED(hr) ) goto Exit;
+
+ // If the mem-based Stream's QI implementation has the same
+ // address as the Unknown's QI implementation, then the Unknown
+ // must be an OLE mem-based stream.
+
+ if( pUnk->QueryInterface == pstmMem->QueryInterface )
+ {
+ // We can just cast the IUnknown* as an IStream* and
+ // we're done (the original QI, despite returning an
+ // error, has already done an AddRef).
+
+ hr = S_OK;
+ *ppStm = (IStream*) pUnk;
+ }
+ else
+ {
+ // This is a real no-interface error, so let's return it.
+ hr = E_NOINTERFACE;
+ }
+
+ pstmMem->Release();
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+#endif // #ifdef _MAC
+
+ return( hr );
+
+} // QueryForIStream()
+
+
+
+//+------------------------------------------------------------------
+//
+// Function: StgCreatePropStg
+//
+// Synopsis: Given an IStorage or IStream, create an
+// IPropertyStorage. This is similar to the
+// IPropertySetStorage::Create method. Existing
+// contents of the Storage/Stream are removed.
+//
+// Inputs: [IUnknown*] pUnk
+// An IStorage* for non-simple propsets,
+// an IStream* for simple. grfFlags is
+// used to disambiguate.
+// [REFFMTID] fmtid
+// The ID of the property set.
+// [DWORD] grfFlags
+// From the PROPSETFLAG_* enumeration.
+// [IPropertySetStorage**] ppPropStg
+// The result.
+//
+// Returns: [HRESULT]
+//
+// Notes: The caller is responsible for maintaining
+// thread-safety between the original
+// IStorage/IStream and this IPropertyStorage.
+//
+//+------------------------------------------------------------------
+
+STDAPI StgCreatePropStg( IUnknown *pUnk,
+ REFFMTID fmtid,
+ const CLSID *pclsid,
+ DWORD grfFlags,
+ DWORD dwReserved,
+ IPropertyStorage **ppPropStg)
+{
+ // ------
+ // Locals
+ // ------
+
+ HRESULT hr;
+ IStream *pstm = NULL;
+ IStorage *pstg = NULL;
+
+ // ----------
+ // Validation
+ // ----------
+
+ GEN_VDATEIFACE_LABEL( pUnk, E_INVALIDARG, Exit, hr );
+ GEN_VDATEREADPTRIN_LABEL(&fmtid, FMTID, E_INVALIDARG, Exit, hr );
+ GEN_VDATEPTRIN_LABEL(pclsid, CLSID, E_INVALIDARG, Exit, hr );
+ // grfFlags is validated by CPropertyStorage
+ GEN_VDATEPTROUT_LABEL( ppPropStg, IPropertyStorage*, E_INVALIDARG, Exit, hr );
+
+ *ppPropStg = NULL;
+
+ // -----------------------
+ // Non-Simple Property Set
+ // -----------------------
+
+ if( grfFlags & PROPSETFLAG_NONSIMPLE )
+ {
+ // Get the IStorage*
+ hr = pUnk->QueryInterface( IID_IStorage, (void**) &pstg );
+ if( FAILED(hr) ) goto Exit;
+
+ // Create the IPropertyStorage implementation
+ *ppPropStg = new CPropertyStorage();
+ if( NULL== *ppPropStg )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // Initialize the IPropertyStorage
+ ((CPropertyStorage*) *ppPropStg)->Create( pstg,
+ fmtid,
+ pclsid,
+ grfFlags,
+ &hr );
+ if( FAILED(hr) ) goto Exit;
+
+ } // if( grfFlags & PROPSETFLAG_NONSIMPLE )
+
+ // -------------------
+ // Simple Property Set
+ // -------------------
+
+ else
+ {
+ // Get the IStream*
+ hr = QueryForIStream( pUnk, &pstm );
+ if( FAILED(hr) ) goto Exit;
+
+ // Create an IPropertyStorage implementation.
+ *ppPropStg = new CPropertyStorage();
+ if( NULL == *ppPropStg )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // Initialize the IPropertyStorage (which
+ // is responsible for sizing and seeking the
+ // stream).
+
+ ((CPropertyStorage*) *ppPropStg)->Create( pstm,
+ fmtid,
+ pclsid,
+ grfFlags,
+ &hr );
+ if( FAILED(hr) ) goto Exit;
+
+ } // if( grfFlags & PROPSETFLAG_NONSIMPLE ) ... else
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // If we created *ppPropStg, and there was an error, delete it.
+
+ if( FAILED(hr) )
+ {
+ PropDbg((DEB_ERROR, "StgCreatePropStg returns %08X\n", hr ));
+
+ // Only delete it if the caller gave us valid parameters
+ // and we created a CPropertyStorage
+
+ if( E_INVALIDARG != hr && NULL != *ppPropStg )
+ {
+ delete *ppPropStg;
+ *ppPropStg = NULL;
+ }
+ }
+
+ if( NULL != pstm )
+ pstm->Release();
+ if( NULL != pstg )
+ pstg->Release();
+
+ return( hr );
+
+} // StgCreatePropStg()
+
+
+
+//+------------------------------------------------------------------
+//
+// Function: StgOpenPropStg
+//
+// Synopsis: Given an IStorage or IStream which hold a
+// serialized property set, create an
+// IPropertyStorage. This is similar to the
+// IPropertySetStorage::Open method.
+//
+// Inputs: [IUnknown*] pUnk
+// An IStorage* for non-simple propsets,
+// an IStream* for simple. grfFlags is
+// used to disambiguate.
+// [REFFMTID] fmtid
+// The ID of the property set.
+// [DWORD] grfFlags
+// From the PROPSETFLAG_* enumeration.
+// [IPropertySetStorage**] ppPropStg
+// The result.
+//
+// Returns: [HRESULT]
+//
+// Notes: The caller is responsible for maintaining
+// thread-safety between the original
+// IStorage/IStream and this IPropertyStorage.
+//
+//+------------------------------------------------------------------
+
+STDAPI StgOpenPropStg( IUnknown* pUnk,
+ REFFMTID fmtid,
+ DWORD grfFlags,
+ DWORD dwReserved,
+ IPropertyStorage **ppPropStg)
+{
+ // ------
+ // Locals
+ // ------
+
+ HRESULT hr;
+ IStream *pstm = NULL;
+ IStorage *pstg = NULL;
+
+ // ----------
+ // Validation
+ // ----------
+
+ GEN_VDATEIFACE_LABEL( pUnk, E_INVALIDARG, Exit, hr );
+ GEN_VDATEREADPTRIN_LABEL(&fmtid, FMTID, E_INVALIDARG, Exit, hr);
+ // grfFlags is validated by CPropertyStorage
+ GEN_VDATEPTROUT_LABEL( ppPropStg, IPropertyStorage*, E_INVALIDARG, Exit, hr );
+
+ // -----------------------
+ // Non-Simple Property Set
+ // -----------------------
+
+ *ppPropStg = NULL;
+
+ if( grfFlags & PROPSETFLAG_NONSIMPLE )
+ {
+ // Get the IStorage*
+ hr = pUnk->QueryInterface( IID_IStorage, (void**) &pstg );
+ if( FAILED(hr) ) goto Exit;
+
+ // Create an IPropertyStorage* implementation.
+ *ppPropStg = new CPropertyStorage();
+ if( NULL == *ppPropStg )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // Initialize the IPropertyStorage by reading
+ // the serialized property set.
+
+ ((CPropertyStorage*) *ppPropStg)->Open(
+ pstg,
+ fmtid,
+ grfFlags,
+ &hr );
+ if( FAILED(hr) ) goto Exit;
+
+ } // if( grfFlags & PROPSETFLAG_NONSIMPLE )
+
+ // -------------------
+ // Simple Property Set
+ // -------------------
+
+ else
+ {
+ // Get the IStream*
+ hr = QueryForIStream( pUnk, &pstm );
+ if( FAILED(hr) ) goto Exit;
+
+ // Create an IPropertyStorage* implementation.
+ *ppPropStg = new CPropertyStorage();
+ if( NULL == *ppPropStg )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // Initialize the IPropertyStorage by reading
+ // the serialized property set (the CPropertyStorage
+ // is responsible for seeking to the stream start).
+
+ ((CPropertyStorage*) *ppPropStg)->Open( pstm,
+ fmtid,
+ grfFlags,
+ FALSE, // Not deleting
+ &hr );
+ if( FAILED(hr) ) goto Exit;
+
+ } // if( grfFlags & PROPSETFLAG_NONSIMPLE ) ... else
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // If we created *ppPropStg, and there was an error, delete it.
+
+ if( FAILED(hr) )
+ {
+ PropDbg((DEB_ERROR, "StgOpenPropStg returns %08X\n", hr ));
+
+ // Only delete it if the caller gave us a valid ppPropStg
+ // and we created a CPropertyStorage
+
+ if( E_INVALIDARG != hr && NULL != *ppPropStg )
+ {
+ delete *ppPropStg;
+ *ppPropStg = NULL;
+ }
+ }
+
+ if( NULL != pstm )
+ pstm->Release();
+
+ if( NULL != pstg )
+ pstg->Release();
+
+ return( hr );
+
+} // StgOpenPropStg()
+
+
+
+//+------------------------------------------------------------------
+//
+// Function: StgCreatePropSetStg
+//
+// Synopsis: Given an IStorage, create an IPropertySetStorage.
+// This is similar to QI-ing a DocFile IStorage for
+// the IPropertySetStorage interface.
+//
+// Inputs: [IStorage*] pStorage
+// Will be held by the propsetstg and used
+// for create/open.
+// [IPropertySetStorage**] ppPropSetStg
+// Receives the result.
+//
+// Returns: [HRESULT]
+//
+// Notes: The caller is responsible for maintaining
+// thread-safety between the original
+// IStorage and this IPropertySetStorage.
+//
+//+------------------------------------------------------------------
+
+STDAPI
+StgCreatePropSetStg( IStorage *pStorage,
+ DWORD dwReserved,
+ IPropertySetStorage **ppPropSetStg)
+{
+ HRESULT hr = S_OK;
+
+ // Validation
+
+ GEN_VDATEIFACE_LABEL( pStorage, E_INVALIDARG, Exit, hr );
+ GEN_VDATEPTROUT_LABEL( ppPropSetStg, IPropertySetStorage*, E_INVALIDARG, Exit, hr );
+
+ // Create the IPropertySetStorage implementation.
+
+ *ppPropSetStg = new CPropertySetStorage( pStorage );
+ if( NULL == *ppPropSetStg )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( FAILED(hr) )
+ {
+ PropDbg((DEB_ERROR, "StgCreatePropSetStg() returns %08X\n", hr ));
+ }
+
+ return( hr );
+
+} // StgCreatePropSetStg()
+
+
+//+----------------------------------------------------------------------------
+//
+// Function: FmtIdToPropStgName
+//
+// Synopsis: This function maps a property set's FMTID to the name of
+// the Stream or Storage which contains it. This name
+// is 27 characters (including the terminator).
+//
+// Inputs: [const FMTID*] pfmtid (in)
+// The FMTID of the property set.
+// [LPOLESTR] oszName (out)
+// The name of the Property Set's Stream/Storage
+//
+// Returns: [HRESULT] S_OK or E_INVALIDARG
+//
+//+----------------------------------------------------------------------------
+
+STDAPI
+FmtIdToPropStgName( const FMTID *pfmtid, LPOLESTR oszName )
+{
+
+ HRESULT hr = S_OK;
+
+ // Validate Inputs
+
+ GEN_VDATEREADPTRIN_LABEL(pfmtid, FMTID, E_INVALIDARG, Exit, hr);
+ VDATESIZEPTROUT_LABEL(oszName,
+ sizeof(OLECHAR) * (CCH_MAX_PROPSTG_NAME+1),
+ Exit, hr);
+
+ // Make the Conversion
+
+ RtlGuidToPropertySetName( pfmtid, oszName );
+
+ // Exit
+
+Exit:
+
+ if( FAILED(hr) )
+ {
+ PropDbg((DEB_ERROR, "FmtIdToPropStgName returns %08X\n", hr ));
+ }
+
+ return( hr );
+
+} // FmtIdToPropStgName()
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Function: PropStgNameToFmtId
+//
+// Synopsis: This function maps a property set's Stream/Storage name
+// to its FMTID.
+//
+// Inputs: [const LPOLESTR] oszName (in)
+// The name of the Property Set's Stream/Storage
+// [FMTID*] pfmtid (out)
+// The FMTID of the property set.
+//
+//
+// Returns: [HRESULT] S_OK or E_INVALIDARG
+//
+//+----------------------------------------------------------------------------
+
+STDAPI
+PropStgNameToFmtId( const LPOLESTR oszName, FMTID *pfmtid )
+{
+
+ HRESULT hr = S_OK;
+
+ // Validate Inputs
+
+ GEN_VDATEPTROUT_LABEL(pfmtid, FMTID, E_INVALIDARG, Exit, hr);
+
+#ifdef OLE2ANSI
+ if( FAILED(hr = ValidateNameA(oszName, CCH_MAX_PROPSTG_NAME )))
+ goto Exit;
+#else
+ if( FAILED(hr = ValidateNameW(oszName, CCH_MAX_PROPSTG_NAME )))
+ goto Exit;
+#endif
+
+
+ // Make the Conversion, passing in the name and its character-length
+ // (not including the null-terminator).
+
+ RtlPropertySetNameToGuid( ocslen(oszName), oszName, pfmtid );
+
+ // Exit
+
+Exit:
+
+ if( FAILED(hr) )
+ {
+ PropDbg((DEB_ERROR, "PropStgNameToFmtId returns %08X\n", hr ));
+ }
+
+ return( hr );
+
+} // PropStgNameToFmtId()
+
diff --git a/private/ole32/stg/props/propdbg.hxx b/private/ole32/stg/props/propdbg.hxx
new file mode 100644
index 000000000..0f7fdfddc
--- /dev/null
+++ b/private/ole32/stg/props/propdbg.hxx
@@ -0,0 +1,68 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: propdbg.hxx
+//
+// Contents: Declarations for tracing property code
+//
+// History:
+// 28-Aug-96 MikeHill Added a Mac version of propinlineDebugOut
+//
+//--------------------------------------------------------------------------
+
+#ifndef _MAC
+DECLARE_DEBUG(prop)
+#endif
+
+#define DEB_PROP_EXIT DEB_USER1 // 00010000
+#define DEB_PROP_TRACE_CREATE DEB_USER2 // 00020000
+#define DEB_PROP_MAP DEB_ITRACE // 00000400
+
+
+#ifdef _MAC
+
+ inline void propInlineDebugOut(DWORD dwDebugLevel, CHAR *szFormat, ...)
+ {
+#if 0
+ if( DEB_PROP_MAP >= dwDebugLevel )
+ {
+ CHAR szBuffer[ 256 ];
+ va_list Arguments;
+ va_start( Arguments, szFormat );
+
+ *szBuffer = '\p'; // This is a zero-terminated string.
+
+ if( -1 == _vsnprintf( szBuffer+1, sizeof(szBuffer)-1, szFormat, Arguments ))
+ {
+ // Terminate the buffer, since the string was too long.
+ szBuffer[ sizeof(szBuffer)-1 ] = '\0';
+ }
+
+ DebugStr( (unsigned char*) szBuffer );
+ }
+#endif
+ }
+
+#endif // #ifdef _MAC
+
+#if DBG
+
+# define PropDbg(x) propInlineDebugOut x
+# define DBGBUF(buf) CHAR buf[400]
+
+ CHAR *DbgFmtId(REFFMTID rfmtid, CHAR *pszBuf);
+ CHAR *DbgMode(DWORD grfMode, CHAR *pszBuf);
+ CHAR *DbgFlags(DWORD grfMode, CHAR *pszBuf);
+
+#else
+
+# define PropDbg(x)
+# define DBGBUF(buf)
+# define DbgFmtId(rfmtid, pszBuf)
+# define DbgMode(grfMode, pszBuf)
+# define DbgFlags(grfMode, pszBuf)
+
+#endif
+
diff --git a/private/ole32/stg/props/prophdr.hxx b/private/ole32/stg/props/prophdr.hxx
new file mode 100644
index 000000000..19a1622d6
--- /dev/null
+++ b/private/ole32/stg/props/prophdr.hxx
@@ -0,0 +1,20 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: prophdr.hxx
+//
+// Contents: Private definitions to this subdir.
+//
+// History: 1-Mar-95 BillMo Created.
+//
+// Notes:
+//--------------------------------------------------------------------------
+
+#ifndef _PROPHDR_HXX_
+#define _PROPHDR_HXX_
+
+
+#endif
+
diff --git a/private/ole32/stg/props/propstg.cxx b/private/ole32/stg/props/propstg.cxx
new file mode 100644
index 000000000..363e1fa57
--- /dev/null
+++ b/private/ole32/stg/props/propstg.cxx
@@ -0,0 +1,3661 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: propstg.cxx
+//
+// Contents: Class that directly implements IPropertyStorage
+//
+// Classes: CCoTaskAllocator
+// CPropertyStorage
+//
+// Notes: For methods that state 'if successful returns S_OK,
+// otherwise error code', the possible error codes include:
+//
+// STG_E_INVALIDHANDLE
+// STG_E_INSUFFICIENTMEMORY
+// STG_E_MEDIUMFULL
+// STG_E_REVERTED
+// STG_E_INVALIDPARAMETER
+// STG_E_INVALIDFLAG
+//
+// History: 1-Mar-95 BillMo Created.
+// 22-Feb-96 MikeHill Use VT_EMPTY instead of VT_ILLEGAL.
+// 14-Mar-96 MikeHill Set _fUserDefinedProperties in open constructor.
+// 09-May-96 MikeHill Don't return an error when someone calls
+// IPropertyStorage::Revert on a direct-mode propset.
+// 22-May-96 MikeHill Use the new _dwOSVersion.
+// 06-Jun-96 MikeHill Validate inputs.
+// 31-Jul-96 MikeHill - Treat prop names as OLECHARs, not WCHARs
+// - Added CDocFilePropertyStorage
+// - Modified for Mac support.
+//
+//--------------------------------------------------------------------------
+
+#include <pch.cxx>
+#include <tstr.h>
+
+#ifdef _MAC_NODOC
+ASSERTDATA // File-specific data for FnAssert
+#endif
+
+#ifndef _MAC // No InfoLevel debug functionality on Mac.
+DECLARE_INFOLEVEL(prop)
+#endif
+
+
+//
+// On NT, we (OLE32) must give the Rtl propset routines (in NTDLL)
+// function pointers for Win32/OleAut functions.
+//
+
+#ifdef WINNT
+VOID
+SetRtlUnicodeCallouts(VOID)
+{
+ static UNICODECALLOUTS UnicodeCallouts = { WIN32_UNICODECALLOUTS };
+ static BOOLEAN fSetUnicodeCallouts = FALSE;
+
+ if (!fSetUnicodeCallouts)
+ {
+ RtlSetUnicodeCallouts(&UnicodeCallouts);
+ fSetUnicodeCallouts = TRUE;
+ }
+}
+#endif
+
+
+//
+// The name of the main data stream in non-simple property sets.
+//
+
+OLECHAR const ocsContents[] = {OLESTR("CONTENTS")};
+
+//+-------------------------------------------------------------------
+//
+// Member: CCoTaskAllocator::Allocate, Free.
+//
+// Synopsis: A PMemoryAllocator used by the Rtl*
+// property set routines. This is required
+// so that those routines can work in any
+// heap.
+//
+//--------------------------------------------------------------------
+
+
+void *
+CCoTaskAllocator::Allocate(ULONG cbSize)
+{
+ return(CoTaskMemAlloc(cbSize));
+}
+
+void
+CCoTaskAllocator::Free(void *pv)
+{
+ CoTaskMemFree(pv);
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CDocFilePropertyStorage::Create
+//
+// Synopsis: This method creates an IPropertyStorage on a given
+// IPrivateStorage, which is known to be a
+// CExposedDocFile. Unlike the to CPropertyStorage::Create
+// methods, this method is used for both simple and non-
+// simple property sets.
+//
+// Arguments: [IPrivateStorage*] pprivstg
+// The CExposedDocFile.
+// [REFFMTID] rfmtid
+// The ID of the property set.
+// [const CLSID*]
+// The COM object which can interpret the property set.
+// [DWORD] grfFlags
+// From the PROPSETFLAG_* enumeration.
+// [DWORD] grfMode
+// From the STGM_* enumeration
+// [HRESULT*]
+// The return code.
+//
+// Returns: None.
+//
+// Notes: Since this routine has access to the DocFile
+// (via the IPrivateStorage), it can lock both the
+// IStorage object and the IPropertyStorage object
+// (using the DocFile's tree mutex).
+//
+//--------------------------------------------------------------------
+
+VOID
+CDocFilePropertyStorage::Create(
+ IPrivateStorage *pprivstg,
+ REFFMTID rfmtid,
+ const CLSID *pclsid,
+ DWORD grfFlags,
+ DWORD grfMode,
+ HRESULT *phr)
+{
+ HRESULT & hr = *phr;
+ CPropSetName psn(rfmtid); // acts as Probe(&rfmtid, sizeof(rfmtid));
+ BOOL fCreated = FALSE;
+ BOOL fLocked = FALSE;
+ IStorage *pstg = pprivstg->GetStorage();
+
+ //
+ // here we take the tree mutex of the docfile
+ // this can be reacquired in ->CreateStorage too so
+ // the lock must be reentrant for the thread
+ //
+ pprivstg->Lock(INFINITE);
+ fLocked = TRUE;
+
+ // Initialize the CPropertyStorage data.
+
+ hr = InitializeOnCreateOrOpen( grfFlags, grfMode, rfmtid,
+ TRUE ); // => Create
+ if( FAILED(hr) ) goto Exit;
+
+ // Ignore the PROPSETFLAG_UNBUFFERED flag. We can do this because
+ // a buffered and unbuffered implementation of *docfile* IPropertyStorage
+ // are functionally equivalent. That is, there is no visible difference
+ // to the client, because we flush the buffer on Commits and CopyTos,
+ // and because we open SHARE_EXCLUSIVE.
+
+ _grfFlags = _grfFlags & ~PROPSETFLAG_UNBUFFERED;
+
+
+ // BUGBUG: BillMo, Raid# 13235 -- if opening in shared mode can get uninitialized
+ // propset (OFS only).
+
+ if (IsNonSimple())
+ {
+ int i=0;
+
+ while (i<=1)
+ {
+ hr = pstg->CreateStorage(psn.GetPropSetName(), grfMode, 0, 0, &_pstgPropSet);
+ if (FAILED(hr))
+ {
+ PropDbg((DEB_PROP_TRACE_CREATE, "CPropertyStorage(%08X)::CPropertyStorage"
+ " - CreateStorage(%ls) attempt %d, hr=%08X\n", this, psn.GetPropSetName(), i+1, hr));
+ }
+ if (hr == S_OK)
+ {
+ fCreated = TRUE;
+
+ if (pclsid != NULL)
+ {
+ hr = _pstgPropSet->SetClass(*pclsid);
+ if (FAILED(hr))
+ {
+ PropDbg((DEB_PROP_TRACE_CREATE, "CPropertyStorage(%08X)::CPropertyStorage"
+ " - SetClass(), hr=%08X\n", this, hr));
+ }
+ }
+
+ if (hr == S_OK)
+ {
+ DWORD grfMode2 = STGM_CREATE | _grfAccess | _grfShare;// BUGBUG: don't need this on docfile.
+
+ hr = _pstgPropSet->CreateStream(ocsContents, grfMode2, 0, 0, &_pstmPropSet);
+ if (FAILED(hr))
+ {
+ DBGBUF(buf);
+ PropDbg((DEB_PROP_TRACE_CREATE, "CPropertyStorage(%08X)::CPropertyStorage"
+ " - CreateStream(contents), %s, hr=%08X\n",
+ this, DbgMode(grfMode2, buf), hr));
+ }
+ }
+ break;
+ }
+ else
+ if (hr != STG_E_FILEALREADYEXISTS)
+ {
+ break;
+ }
+ else
+ if (i == 0 && (grfMode & STGM_CREATE) == STGM_CREATE)
+ {
+ // BUGBUG: check whether this happens if we're overwriting a stream
+ pstg->DestroyElement(psn.GetPropSetName());
+ }
+ i++;
+ }
+ } // if (IsNonSimple())
+
+ else // This is a simple property set.
+ {
+ int i=0;
+ while (i<=1)
+ {
+ // Create the property set stream in pstg.
+ // The second section of the DocumentSummaryInformation Property Set
+ // is a special-case.
+
+ if( IsEqualGUID( rfmtid, FMTID_UserDefinedProperties ))
+ {
+ hr = _CreateDocumentSummary2Stream( pstg, psn, grfMode, &fCreated );
+ }
+ else
+ {
+ hr = pstg->CreateStream(psn.GetPropSetName(), grfMode, 0, 0, &_pstmPropSet);
+ if( hr == S_OK )
+ fCreated = TRUE;
+ }
+
+ if (hr == S_OK)
+ {
+ break;
+ }
+ else
+ {
+ PropDbg((DEB_PROP_TRACE_CREATE, "CPropertyStorage(%08X)::CPropertyStorage"
+ " - CreateStream(%ls) attempt %d, hr=%08X\n", this, psn.GetPropSetName(), i+1, hr));
+
+
+ if (hr != STG_E_FILEALREADYEXISTS)
+ {
+ break;
+ }
+ else
+ if (i == 0 && (grfMode & STGM_CREATE) == STGM_CREATE)
+ {
+ pstg->DestroyElement(psn.GetPropSetName());
+ }
+ } // if (hr == S_OK) ... else
+
+ i++;
+ }
+ }
+
+ if (hr == S_OK)
+ {
+ hr = InitializePropertyStream((USHORT) CREATEPROP_CREATE |
+ (IsNonSimple() ? CREATEPROP_NONSIMPLE : 0),
+ &rfmtid,
+ pclsid);
+
+ if (hr == S_OK && (grfMode & STGM_TRANSACTED))
+ {
+ // make sure the contents stream is actually published if
+ // it was created in transacted mode.
+ hr = CPropertyStorage::Commit(STGC_DEFAULT);
+ if (FAILED(hr))
+ {
+ PropDbg((DEB_PROP_TRACE_CREATE, "CPropertyStorage(%08X)::CPropertyStorage"
+ " - Commit(STGC_DEFAULT) hr=%08X\n", this, hr));
+ }
+
+ }
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if (hr != S_OK && fCreated)
+ {
+ //
+ // if we fail after creating the property set in storage, cleanup.
+ //
+ pstg->DestroyElement(psn.GetPropSetName());
+ // BUGBUG: review: this will revert them: they will close in destructor
+ }
+
+ // If we took the lock, release it.
+ if( fLocked )
+ pprivstg->Unlock();
+
+} // CDocFilePropertyStorage::Create
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::_CreateDocumentSummary2Stream
+//
+// Synopsis: Open the "DocumentSummaryInformation" stream, creating
+// it if necessary.
+//
+// Arguments: [pstg] -- container storage
+// [psn] -- the property set name
+// [grfMode] -- mode of the property set
+// [fCreated] -- TRUE if Stream is created, FALSE if opened.
+//
+// Notes: This special case is necessary because this property set
+// is the only one in which we support more than one section.
+// For this property set, if the caller Creates the second
+// Section, we must not *Create* the Stream, because that would
+// lost the first Section. So, we must open it.
+//
+// This routine is only called when creating the second
+// Section. The first Section is created normally (note
+// that if the client creates the first section, the second
+// section is lost).
+//
+// Also note that it may not be possible to open the Stream,
+// since it may already be opened. This is significant
+// because it may not be obvious to the caller. I.e.,
+// to a client of IPropertyStorage, the 2 sections are
+// distinct property sets, and you would think that you could
+// open them for simultaneous write.
+//
+//--------------------------------------------------------------------
+
+HRESULT
+CPropertyStorage::_CreateDocumentSummary2Stream( IStorage * pstg,
+ CPropSetName & psn,
+ DWORD grfMode,
+ BOOL * pfCreated )
+{
+
+ HRESULT hr;
+ DWORD grfOpenMode;
+
+ // Calculate the STGM flags to use for the Open. Create & Convert
+ // don't have meaning for the Open, and Transacted isn't supported
+ // by IPropertyStorage
+
+ grfOpenMode = grfMode & ~(STGM_CREATE | STGM_CONVERT | STGM_TRANSACTED);
+
+ *pfCreated = FALSE;
+
+ // Try an Open
+
+ hr = pstg->OpenStream( psn.GetPropSetName(), NULL,
+ grfOpenMode,
+ 0L, &_pstmPropSet );
+
+ // If the file wasn't there, try a create.
+
+ if( hr == STG_E_FILENOTFOUND )
+ {
+ hr = pstg->CreateStream(psn.GetPropSetName(), grfMode, 0, 0, &_pstmPropSet);
+
+ if( SUCCEEDED( hr ))
+ {
+ *pfCreated = TRUE;
+ }
+ }
+
+ return( hr );
+
+} // CPropertyStorage::_CreateDocumentSummary2Stream()
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CDocFilePropertyStorage::Open
+//
+// Synopsis: This method opens an IPropertyStorage on a
+// CExposedDocFile (using its IPrivateStorage
+// interface).
+//
+// Arguments: [IPrivateStorage*] pprivstg
+// The CExposedDocFile.
+// [REFFMTID] rfmtid
+// The ID of the property set.
+// [DWORD] grfMode
+// From the STGM_* enumeration
+// [BOOL] fDelete
+// If TRUE, the property set is actually to be deleted,
+// rather than opened (this is used for the special-case
+// "UserDefined" property set).
+// [HRESULT*]
+// The return code.
+//
+// Returns: None.
+//
+//--------------------------------------------------------------------
+
+VOID
+CDocFilePropertyStorage::Open(
+ IPrivateStorage * pprivstg,
+ REFFMTID rfmtid,
+ DWORD grfMode,
+ BOOL fDelete,
+ HRESULT * phr)
+{
+ HRESULT & hr = *phr;
+ USHORT createprop = 0L;
+
+ // String-ize the FMTID GUID to get the Stream/Storage name.
+ CPropSetName psn(rfmtid);
+
+ // Get the IStorage* from the IPrivateStorage.
+ IStorage *pstgParent;
+ IStorage *pstg = pprivstg->GetStorage();
+
+ // Get exclusive access to the Storage (using the DocFile
+ // tree mutex). We do an unconditional unlock in the Exit, so
+ // we must be sure to reach this statement before any gotos.
+
+ pprivstg->Lock(INFINITE);
+
+ // Initialize the CPropertyStorage members. We pass "Default"
+ // as the grfFlags value, because we're really going to infer its
+ // value from the property set.
+
+ hr = InitializeOnCreateOrOpen( PROPSETFLAG_DEFAULT, grfMode, rfmtid,
+ FALSE ); // => Open
+ if( FAILED(hr) ) goto Exit;
+
+
+ // Assume the property set is simple and attempt to open it.
+ // Mask out the STGM_TRANSACTED bit because we don't support it.
+
+ hr = pstg->OpenStream(psn.GetPropSetName(), NULL,
+ (_grfAccess | _grfShare) & ~STGM_TRANSACTED,
+ 0, &_pstmPropSet);
+
+ // If we got a not-found error, then it might be a non-simple
+ // property set.
+ if (hr == STG_E_FILENOTFOUND)
+ {
+ hr = pstg->OpenStorage(psn.GetPropSetName(), NULL, grfMode, NULL, 0, &_pstgPropSet);
+ if (hr == S_OK)
+ {
+ // We've opened the IStorage with the property set.
+ // Now open the CONTENTS Stream.
+ // Mask out the STGM_TRANSACTED bit because we don't support it.
+
+ _grfFlags |= PROPSETFLAG_NONSIMPLE;
+ pstgParent = _pstgPropSet;
+ hr = _pstgPropSet->OpenStream(ocsContents, NULL,
+ (_grfAccess | _grfShare) & ~STGM_TRANSACTED,
+ 0, &_pstmPropSet);
+ }
+ }
+ else
+ {
+ pstgParent = pstg;
+ }
+
+
+ // Determine the CREATEPROP flags.
+
+ if( fDelete )
+ {
+ // Only simple Sections may be deleted (really, only the
+ // second section of the DocumentSummaryInformation property
+ // set may be deleted in this way).
+ DfpAssert( !IsNonSimple() );
+
+ createprop = CREATEPROP_DELETE;
+ }
+ else
+ {
+ createprop = (S_OK == IsWriteable() ? CREATEPROP_WRITE : CREATEPROP_READ)
+ |
+ (IsNonSimple() ? CREATEPROP_NONSIMPLE : 0);
+ }
+
+ // Initialize the property set Stream.
+
+ if (hr == S_OK)
+ {
+ // sets up _usCodePage
+ hr = InitializePropertyStream(
+ createprop,
+ &rfmtid,
+ NULL);
+
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ pprivstg->Unlock();
+
+} // CDocFilePropertyStorage::Open()
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::Initialize
+//
+// Synopsis: Initialize members to known values.
+//
+//--------------------------------------------------------------------
+
+VOID CPropertyStorage::Initialize(VOID)
+{
+ _ulSig = PROPERTYSTORAGE_SIG;
+ _cRefs = 1;
+ _pstgPropSet = NULL;
+ _pstmPropSet = NULL;
+ _dwOSVersion = PROPSETHDR_OSVERSION_UNKNOWN;
+ _np = NULL;
+ _ms = NULL;
+ _usCodePage = CP_WINUNICODE;
+ _grfFlags = 0;
+ _grfAccess = 0;
+ _grfShare = 0;
+
+#ifndef _MAC
+ InitializeCriticalSection( &_CriticalSection );
+#endif
+
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::InitializePropertyStream.
+//
+// Synopsis: Initialize the storage-type specific members.
+//
+// Arguments: [Flags] -- Flags for RtlCreatePropertySet: CREATEPROP_*
+// [pguid] -- FMTID, in for create only.
+// [pclsid] -- Class id, in for create only.
+//
+// Returns: HRESULT
+//
+// Requires:
+// _pstmPropSet -- The IStream of the main property set stream.
+//
+// Modifies: _fNative TRUE if native file system
+// FALSE if docfile
+//
+// _ms (NTMAPPEDSTREAM)
+//
+// (assumed NULL on entry) will be NULL or valid on exit
+//
+// if _fNative, then _ms is CNtMappedStream*
+// if !_fNative, then _ms is CMappedStream* of CExposedStream
+//
+// _np (NTPROP) aka CPropertySetStream
+//
+// (assumed NULL on entry) will be NULL or valid on exit
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+HRESULT
+CPropertyStorage::InitializePropertyStream(
+ USHORT Flags,
+ const GUID *pguid,
+ GUID const *pclsid)
+{
+ HRESULT hr = S_OK;
+
+#ifdef WINNT
+ SetRtlUnicodeCallouts();
+#endif
+
+ hr = CreateMappedStream();
+ if( FAILED(hr) ) goto Exit;
+
+ NTSTATUS Status;
+
+ DfpAssert( NULL == _np );
+
+ Status = RtlCreatePropertySet(
+ _ms,
+ Flags,
+ pguid,
+ pclsid,
+ (NTMEMORYALLOCATOR) &_cCoTaskAllocator,
+ GetUserDefaultLCID(),
+ &_dwOSVersion,
+ &_usCodePage,
+ &_np);
+
+ if (!NT_SUCCESS(Status))
+ {
+ PropDbg((DEB_PROP_TRACE_CREATE, "CPropertyStorage(%08X)::InitializePropertyStream"
+ " - RtlCreatePropertySet Status=%08X\n", this, Status));
+ hr = DfpNtStatusToHResult(Status);
+ goto Exit;
+ }
+
+ if (_usCodePage != CP_WINUNICODE)
+ _grfFlags |= PROPSETFLAG_ANSI; // for Stat
+
+Exit:
+
+ return(hr);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::~CPropertyStorage
+//
+// Synopsis: Free up object resources.
+//
+// Notes: Cleans up even from partial construction.
+//
+//--------------------------------------------------------------------
+
+CPropertyStorage::~CPropertyStorage()
+{
+ _ulSig = PROPERTYSTORAGE_SIGDEL; // prevent someone else deleting it
+
+ // Close the property set.
+
+ if (_np != NULL)
+ {
+ RtlClosePropertySet(_np);
+ }
+
+ // Free the mapped stream.
+
+ if (_ms != NULL)
+ {
+ delete (CCFMappedStream*) _ms;
+ }
+
+ // Free the Stream and/or Storage with the serialized data.
+
+ if (_pstmPropSet != NULL)
+ _pstmPropSet->Release();
+
+ if (_pstgPropSet != NULL)
+ _pstgPropSet->Release();
+
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::QueryInterface, AddRef, Release
+//
+// Synopsis: IUnknown members
+//
+// Notes: IPropertyStorage supports IPropertyStorage and IUnknown
+//
+//--------------------------------------------------------------------
+
+
+HRESULT CPropertyStorage::QueryInterface( REFIID riid, void **ppvObject)
+{
+ HRESULT hr;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = ValidateRef()))
+ return(hr);
+
+ // Validate the inputs
+
+ VDATEREADPTRIN( &riid, IID );
+ VDATEPTROUT( ppvObject, void* );
+
+ // -----------------
+ // Perform the Query
+ // -----------------
+
+ *ppvObject = NULL;
+
+ if (IsEqualIID(riid,IID_IPropertyStorage) || IsEqualIID(riid,IID_IUnknown))
+ {
+ *ppvObject = (IPropertyStorage *)this;
+ CPropertyStorage::AddRef();
+ }
+#ifdef _CAIRO_
+ else
+ if (IsEqualIID(riid, IID_IAccessControl))
+ {
+ if (_pstmPropSet && S_OK==
+ _pstmPropSet->QueryInterface(IID_IAccessControl,(void**)&_pIAC))
+ {
+ *ppvObject = (IAccessControl *)this;
+ CPropertyStorage::AddRef();
+ _pIAC->Release();
+ }
+ else if (_pstgPropSet && S_OK==
+ _pstgPropSet->QueryInterface(IID_IAccessControl,(void**)&_pIAC))
+ {
+ // here we depend on _pIAC being the same for multiple QIs
+ // in the multi-thread case.
+ *ppvObject = (IAccessControl *)this;
+ CPropertyStorage::AddRef();
+ _pIAC->Release();
+ }
+ else
+ hr = E_NOINTERFACE;
+ }
+#endif
+ else
+ {
+ hr = E_NOINTERFACE;
+ }
+
+ return(hr);
+}
+
+ULONG CPropertyStorage::AddRef(void)
+{
+ if (S_OK != ValidateRef())
+ return(0);
+
+ InterlockedIncrement(&_cRefs);
+ return(_cRefs);
+}
+
+ULONG CPropertyStorage::Release(void)
+{
+ LONG lRet;
+
+ if (S_OK != ValidateRef())
+ return(0);
+
+ lRet = InterlockedDecrement(&_cRefs);
+
+ if (lRet == 0)
+ {
+ delete this; // this will do a flush if dirty
+ }
+ else
+ if (lRet <0)
+ {
+ lRet = 0;
+ }
+ return(lRet);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::CleanupOpenedObjects
+//
+// Synopsis: Cleans up the objects that have been opened
+// during the ReadMultiple. Sets all entries to
+// VT_ILLEGAL so that the later free doesn't try to
+// treat the pointers as interface pointers.
+//
+// Arguments: [avar] -- The user's array of PROPVARIANTs
+//
+// [pip] -- The array of INDIRECTPROPERTY structures
+// for non-simple properties.
+//
+// [cpspec] -- if 1 then no MAX_ULONG end of list marker.
+//
+// [iFailIndex] -- An index into [pip] which
+// indicates the non-simple property
+// which failed to open, and represents
+// the index at which the avar's begin
+// to be strings rather than IStream's et al.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+VOID CPropertyStorage::CleanupOpenedObjects(
+ PROPVARIANT avar[],
+ INDIRECTPROPERTY *pip,
+ ULONG cpspec,
+ ULONG iFailIndex)
+{
+ ULONG iStgProp;
+ ULONG iiScan;
+
+ // the one that fails is passed in as ppPropVarFail.
+
+ for (iiScan = 0;
+ (iStgProp = pip[iiScan].Index) != MAX_ULONG;
+ iiScan++)
+ {
+ // since we've just opened a bunch of storages we should
+ // release them in this error case. We don't release the
+ // one at ppPropVarFail because that one is still a string.
+
+ PROPVARIANT *pPropVar = avar + iStgProp;
+
+ if (iiScan < iFailIndex)
+ {
+ switch (pPropVar->vt)
+ {
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ pPropVar->pStream->Release();
+ break;
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ pPropVar->pStorage->Release();
+ break;
+ }
+ }
+ else
+ {
+ CoTaskMemFree(pPropVar->pStream);
+ }
+
+ pPropVar->vt = VT_ILLEGAL;
+ pPropVar->pStream = NULL; // mark pStorage and pStream as nul
+
+ if (cpspec == 1)
+ {
+ break;
+ }
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::ReadMultiple
+//
+// Synopsis: Read properties from the property set.
+//
+// Arguments: [cpspec] -- Count of PROPSPECs in [rgpspec]
+// [rgpspec] -- Array of PROPSPECs
+// [rgpropvar] -- Array of PROPVARIANTs to be filled in
+// with callee allocated data.
+//
+// Returns: S_FALSE if none found
+// S_OK if >=1 found
+// FAILED(hr) otherwise.
+//
+// Notes: BUGBUG: SPEC: Returning the same IStream* for the same
+// VT queried multiple times.
+//
+// RtlQueryProperties has been specified to return
+// useful data: the count of properties found (controls
+// return code) and an array of indexes of non-simple
+// PROPSPECs (useful for simply opening the storages and
+// streams.) This extra returned data means we don't
+// have to walk the [rgpropvar] in the success cases.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertyStorage::ReadMultiple(
+ ULONG cpspec,
+ const PROPSPEC rgpspec[],
+ PROPVARIANT rgpropvar[])
+{
+ NTSTATUS Status;
+ HRESULT hr;
+ INDIRECTPROPERTY * pip; //array for non-simple
+ INDIRECTPROPERTY ip;
+ ULONG cpropFound;
+ BOOL fLocked = FALSE;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ if (S_OK != (hr = IsReverted()))
+ goto errRet;
+
+ if (S_OK != (hr = IsReadable()))
+ goto errRet;
+
+ // Validate inputs
+
+ if (0 == cpspec)
+ {
+ hr = S_FALSE;
+ goto errRet;
+ }
+
+ if (S_OK != (hr = ValidateRGPROPSPEC( cpspec, rgpspec )))
+ goto errRet;
+
+ if (S_OK != (hr = ValidateOutRGPROPVARIANT( cpspec, rgpropvar )))
+ goto errRet;
+
+ // -------------------
+ // Read the Properties
+ // -------------------
+
+ Lock(INFINITE);
+ fLocked = TRUE;
+
+ Status = RtlQueryProperties(
+ _np,
+ cpspec,
+ rgpspec,
+ NULL, // don't want PROPID's
+ cpspec == 1 ? (INDIRECTPROPERTY**)&ip : &pip,
+ rgpropvar,
+ &cpropFound);
+
+ if (NT_SUCCESS(Status))
+ {
+ if (cpropFound != 0)
+ {
+ if (cpspec == 1)
+ {
+ if (ip.Index != MAX_ULONG)
+ {
+ pip = &ip;
+ }
+ else
+ {
+ pip = NULL;
+ }
+ }
+
+ if (pip != NULL)
+ {
+
+ // we have one or more of VT_STREAM, VT_STREAMED_OBJECT,
+ // VT_STORAGE, VT_STORED_OBJECT
+
+ ULONG iiScan;
+ ULONG iStgProp;
+
+ for (iiScan = 0;
+ hr == S_OK && (iStgProp = pip[iiScan].Index) != MAX_ULONG;
+ iiScan++ )
+ {
+ PROPVARIANT *pPropVar = rgpropvar + iStgProp;
+
+ if (IsNonSimple() && pPropVar->pwszVal[0] != L'\0')
+ {
+ VOID *pStreamOrStorage;
+
+ switch (pPropVar->vt)
+ {
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+
+ // Mask out the STGM_TRANSACTED bit because we don't
+ // support it.
+
+ hr = _pstgPropSet->OpenStream((LPOLESTR) pPropVar->pwszVal,
+ NULL,
+ (_grfAccess | _grfShare) & ~STGM_TRANSACTED,
+ 0,
+ (IStream**)&pStreamOrStorage);
+ break;
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ hr = _pstgPropSet->OpenStorage((LPOLESTR) pPropVar->pwszVal,
+ NULL,
+ _grfAccess | _grfShare,
+ NULL,
+ 0,
+ (IStorage**)&pStreamOrStorage);
+ break;
+ }
+
+ if (hr == S_OK)
+ {
+ void **ppv = (void**) &(pPropVar->pStorage);
+ CoTaskMemFree(*ppv);
+ *ppv = pStreamOrStorage;
+ }
+ else
+ if (hr != STG_E_FILENOTFOUND)
+ {
+ // the one that fails is passed in as
+ // iiScan and is still a string.
+ CleanupOpenedObjects(rgpropvar, pip, cpspec, iiScan);
+ }
+ }
+ else
+ {
+ hr = STG_E_FILENOTFOUND;
+ }
+
+ if (hr == STG_E_FILENOTFOUND)
+ {
+ //
+ // if the stream/storage is not found, or this is
+ // a simple stream with VT_STORAGE etc, then treat
+ // like the property is not found.
+ //
+ CoTaskMemFree(pPropVar->pStream);
+ pPropVar->pStream = NULL;
+ pPropVar->vt = VT_EMPTY;
+ cpropFound --;
+ hr = S_OK;
+ }
+
+ if (cpspec == 1)
+ break;
+ }
+
+ if (cpspec != 1 && pip != NULL)
+ PropFreeHeap(RtlProcessHeap(), 0, pip);
+ }
+
+ if (hr != S_OK)
+ {
+ // we succeeded in getting the basic property types but
+ // the non-simple stuff failed, so we zap out the whole lot
+ // and return a complete failure
+ FreePropVariantArray(cpspec, rgpropvar);
+ }
+ }
+
+ if (hr == S_OK && cpropFound == 0)
+ {
+ hr = S_FALSE;
+ }
+ }
+ else
+ {
+ hr = DfpNtStatusToHResult(Status);
+ }
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ if( fLocked )
+ Unlock();
+
+ PropDbg((DEB_PROP_EXIT, "CPropertyStorage(%08X)::ReadMultiple(cpspec=%d, rgpspec=%08X, "
+ "rgpropvar=%08X) returns %08X\n",
+ this, cpspec, rgpspec, rgpropvar, hr));
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::_WriteMultiple, private
+//
+// Synopsis: Write the properties to the property set. Allows
+// a NULL rgpropvar pointer for deletion case.
+//
+// Arguments: [cpspec] -- count of PROPSPECs and PROPVARIANTs in
+// [rgpspec] and [rgpropvar]
+//
+// [rgpspec] -- pointer to array of PROPSPECs
+//
+// [rgpropvar] -- pointer to array of PROPVARIANTs with
+// the values to write.
+//
+// [propidNameFirst] -- id below which not to assign
+// ids for named properties.
+//
+//
+// Returns: S_OK, -- all requested data was written.
+// S_FALSE -- all simple properties written, but non-simple
+// types (VT_STREAM etc) were ignored.
+// Errors --
+//
+// Modifies:
+//
+// Derivation:
+//
+// Notes: RtlSetProperties has been carefully specified to return
+// useful information so that we can deal with the case
+// where a non-simple type (VT_STREAM etc) is overwritten
+// by a simple type.
+//
+// This routine assumes the object has been validated
+// and is writeable.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertyStorage::_WriteMultiple(
+ ULONG cpspec,
+ const PROPSPEC rgpspec[],
+ const PROPVARIANT rgpropvar[],
+ PROPID propidNameFirst)
+{
+ HRESULT hr;
+ NTSTATUS Status;
+ CStackPropIdArray spia;
+ INDIRECTPROPERTY * pip;
+ INDIRECTPROPERTY ip;
+
+ if (S_OK != (hr = spia.Init(cpspec)))
+ return(hr);
+
+ Status = RtlSetProperties(_np, // property set context
+ cpspec, // property count
+ propidNameFirst, // first propid for new named props
+ rgpspec, // array of property specifiers
+ spia.GetBuf(), // buffer for array of propids
+ cpspec == 1 ? (INDIRECTPROPERTY**)&ip : &pip,
+ // array for indirect prop indexes
+ // indexes of entries that are
+ // now non-simple, or are simple
+ // but were non-simple.
+ rgpropvar);
+
+ if (NT_SUCCESS(Status))
+ {
+ if (cpspec == 1)
+ {
+ if (ip.Index != MAX_ULONG)
+ pip = &ip;
+ else
+ pip = NULL;
+ }
+
+ if ( pip != NULL)
+ {
+ ULONG iiScan; // in this scope because we always use
+ ULONG iStgProp; // these variables in the free memory loop below.
+
+ if (IsSimple())
+ {
+ //
+ // VT_STREAM was requested to be written and this
+ // is a "SIMPLE" property set.
+ //
+ hr = STG_E_PROPSETMISMATCHED;
+ }
+ else
+ {
+ //
+ // Two cases now:
+ // 1. Wrote a simple over a non-simple -- must delete the
+ // old non-simple.
+ // 2. Wrote a non-simple -- must actually copy data into it.
+ //
+
+
+ for (iiScan = 0;
+ hr == S_OK &&
+ (iStgProp = pip[iiScan].Index) != MAX_ULONG;
+ iiScan++ )
+ {
+
+ // BUGBUG: pwszName was NULL when writing VT_STREAM
+ OLECHAR oszStdPropName[sizeof("prop")+10+1];
+ OLECHAR *poszPropName = (LPOLESTR) pip[iiScan].poszName;
+ const PROPVARIANT *pPropVar = rgpropvar + iStgProp;
+
+ if (poszPropName == NULL)
+ {
+ DfpAssert(iStgProp >= 0 && iStgProp < cpspec);
+ PROPGENPROPERTYNAME (oszStdPropName, spia.GetBuf()[iStgProp]);
+ poszPropName = oszStdPropName;
+ }
+
+ switch (rgpropvar == NULL ? VT_ILLEGAL : pPropVar->vt)
+ {
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ {
+ IStream *pstm;
+ int i=0;
+
+ while (i<=1)
+ {
+ hr = _pstgPropSet->CreateStream(poszPropName,
+ GetCreationMode(),
+ 0,
+ 0,
+ &pstm);
+ if (hr == S_OK)
+ {
+ // BUGBUG: spec bug: does this destroy the seek position on
+ // source ? does it read from current position or
+ // from the beginning of the stream.
+
+ if (pPropVar->pStream != NULL)
+ {
+ ULARGE_INTEGER uli;
+ memset(&uli, -1, sizeof(uli));
+ hr = pPropVar->pStream->CopyTo(pstm,
+ uli, NULL, NULL);
+ }
+ pstm->Release();
+ break;
+ }
+ else
+ if (hr != STG_E_FILEALREADYEXISTS)
+ {
+ break;
+ }
+ else
+ if (i == 0)
+ {
+ _pstgPropSet->DestroyElement(poszPropName);
+ }
+ i++;
+ }
+ }
+ break;
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ {
+ IStorage *pstg;
+ int i=0;
+ while (i<=1)
+ {
+ hr = _pstgPropSet->CreateStorage(poszPropName,
+ GetCreationMode(),
+ 0,
+ 0,
+ &pstg);
+ if (hr == S_OK)
+ {
+ if (pPropVar->pStorage != NULL)
+ {
+ hr = pPropVar->pStorage->CopyTo(0, NULL,
+ NULL, pstg);
+ }
+ pstg->Release();
+ break;
+ }
+ else
+ if (hr != STG_E_FILEALREADYEXISTS)
+ {
+ break;
+ }
+ else
+ if (i == 0)
+ {
+ _pstgPropSet->DestroyElement(poszPropName);
+ }
+ i++;
+ }
+ }
+ break;
+ default:
+ //
+ // Any other VT_ type is simple and therefore
+ // was a non-simple overwritten by a simple.
+ //
+ hr = _pstgPropSet->DestroyElement(poszPropName);
+ break;
+ }
+
+ if (cpspec == 1)
+ break;
+ }
+ }
+
+ // in both the success and failure cases we do this cleanup.
+
+ for (iiScan = 0; pip[iiScan].Index != MAX_ULONG; iiScan++ )
+ {
+ if (pip[iiScan].poszName != NULL)
+ PropFreeHeap(RtlProcessHeap(), 0, pip[iiScan].poszName);
+
+ if (cpspec == 1)
+ break;
+ }
+
+ if (cpspec != 1 && pip != NULL)
+ PropFreeHeap(RtlProcessHeap(), 0, pip);
+ }
+ else
+ {
+ //
+ // No VT_STREAM etc was requested to be written.
+ // and no simple property overwrote a non-simple one.
+ }
+ }
+ else
+ {
+ hr = DfpNtStatusToHResult(Status);
+ }
+
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::WriteMultiple
+//
+// Synopsis: Write properties.
+//
+// Arguments: [cpspec] -- count of PROPSPECs and PROPVARIANTs in
+// [rgpspec] and [rgpropvar]
+// [rgpspec] -- pointer to array of PROPSPECs
+// [rgpropvar] -- pointer to array of PROPVARIANTs with
+// the values to write.
+// [propidNameFirst] -- id below which not to assign
+// ids for named properties.
+//
+// Returns: S_OK, -- all requested data was written.
+// S_FALSE -- all simple properties written, but non-simple
+// types (VT_STREAM etc) were ignored.
+// Errors --
+//
+// Notes: Checks that rgpropvar is not NULL, then calls
+// _WriteMultiple.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertyStorage::WriteMultiple(
+ ULONG cpspec,
+ const PROPSPEC rgpspec[],
+ const PROPVARIANT rgpropvar[],
+ PROPID propidNameFirst)
+{
+ HRESULT hr;
+ BOOL fLocked = FALSE;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ if (S_OK != (hr = IsReverted()))
+ goto errRet;
+
+ if (S_OK != (hr = IsWriteable()))
+ goto errRet;
+
+ // Validate the inputs
+
+ if (0 == cpspec)
+ {
+ hr = S_OK;
+ goto errRet;
+ }
+
+ if (S_OK != (hr = ValidateRGPROPSPEC( cpspec, rgpspec )))
+ goto errRet;
+
+ if (S_OK != (hr = ValidateInRGPROPVARIANT( cpspec, rgpropvar )))
+ goto errRet;
+
+ // --------------------
+ // Write the Properties
+ // --------------------
+
+ Lock(INFINITE);
+ fLocked = TRUE;
+
+ hr = _WriteMultiple(cpspec, rgpspec, rgpropvar, propidNameFirst);
+ if (hr == STG_E_INSUFFICIENTMEMORY)
+ {
+ hr = S_OK;
+
+ for (ULONG i=0; hr == S_OK && i < cpspec; i++)
+ {
+ hr = _WriteMultiple(1, rgpspec+i, rgpropvar+i, propidNameFirst);
+ if( FAILED(hr) ) goto errRet;
+ }
+ }
+ if( FAILED(hr) ) goto errRet;
+
+ // If buffering is not desired, flush the property storage
+ // to the underlying Stream.
+
+ if( _grfFlags & PROPSETFLAG_UNBUFFERED )
+ {
+ NTSTATUS Status = RtlFlushPropertySet(_np);
+ if (!NT_SUCCESS(Status))
+ {
+ hr = DfpNtStatusToHResult(Status);
+ }
+ }
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ if( fLocked )
+ Unlock();
+
+ PropDbg((DEB_PROP_EXIT, "CPropertyStorage(%08X)::WriteMultiple(cpspec=%d, rgpspec=%08X, "
+ "rgpropvar=%08X, propidNameFirst=%d) returns %08X\n",
+ this, cpspec, rgpspec, rgpropvar, propidNameFirst, hr));
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::DeleteMultiple
+//
+// Synopsis: Delete properties.
+//
+// Arguments: [cpspec] -- count of PROPSPECs and PROPVARIANTs in
+// [rgpspec] and [rgpropvar]
+// [rgpspec] -- pointer to array of PROPSPECs
+//
+// Returns: S_OK, -- all requested data was deleted.
+// S_FALSE -- all simple properties written, but non-simple
+// types (VT_STREAM etc) were ignored.
+// Errors --
+//
+// Notes: Checks that rgpropvar is not NULL, then calls
+// _WriteMultiple.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertyStorage::DeleteMultiple(
+ ULONG cpspec,
+ const PROPSPEC rgpspec[])
+{
+ HRESULT hr;
+ BOOL fLocked = FALSE;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ if (S_OK != (hr = IsReverted()))
+ goto errRet;
+
+ if (S_OK != (hr = IsWriteable()))
+ goto errRet;
+
+ // Validate the inputs
+
+ if (0 == cpspec)
+ {
+ hr = S_OK;
+ goto errRet;
+ }
+
+ if (S_OK != (hr = ValidateRGPROPSPEC( cpspec, rgpspec )))
+ goto errRet;
+
+ // ---------------------
+ // Delete the Properties
+ // ---------------------
+
+ Lock(INFINITE);
+ fLocked = TRUE;
+
+ hr = _WriteMultiple(cpspec, rgpspec, NULL, 2);
+ if (hr == STG_E_INSUFFICIENTMEMORY)
+ {
+ hr = S_OK;
+
+ for (ULONG i=0; hr == S_OK && i < cpspec; i++)
+ {
+ hr = _WriteMultiple(1, rgpspec+i, NULL, 2);
+ if( FAILED(hr) ) goto errRet;
+ }
+ }
+ if( FAILED(hr) ) goto errRet;
+
+ // If buffering is not desired, flush the property storage
+ // to the underlying Stream.
+
+ if( _grfFlags & PROPSETFLAG_UNBUFFERED )
+ {
+ NTSTATUS Status = RtlFlushPropertySet(_np);
+ if (!NT_SUCCESS(Status))
+ {
+ hr = DfpNtStatusToHResult(Status);
+ }
+ }
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ if( fLocked )
+ Unlock();
+
+ PropDbg((DEB_PROP_EXIT, "CPropertyStorage(%08X)::DeleteMultiple(cpspec=%d, rgpspec=%08X) "
+ "returns %08X\n",
+ this, cpspec, rgpspec, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::ReadPropertyNames
+//
+// Synopsis: Attempt to read names for all identified properties.
+//
+// Arguments: [cpropid] -- Count of PROPIDs in [rgpropid]
+// [rgpropid] -- Pointer to array of [cpropid] PROPIDs
+// [rglpstrName] -- Pointer to array of [cpropid] LPOLESTRs
+//
+// Returns: S_OK -- success, one or more names returned
+// S_FALSE -- success, no names returned
+// STG_E_INVALIDHEADER -- no propid->name mapping property
+// other errors -- STG_E_INSUFFICIENTMEMORY etc
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertyStorage::ReadPropertyNames(
+ ULONG cpropid,
+ const PROPID rgpropid[],
+ LPOLESTR rglpwstrName[])
+{
+ HRESULT hr;
+ NTSTATUS Status;
+ BOOL fLocked = FALSE;
+
+ // --------
+ // Validate
+ // --------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ if (S_OK != (hr = IsReverted()))
+ goto errRet;
+
+ if (S_OK != (hr = IsReadable()))
+ goto errRet;
+
+ // Validate the inputs
+
+ if (0 == cpropid)
+ {
+ hr = S_FALSE;
+ goto errRet;
+ }
+
+ if (S_OK != (hr = ValidateRGPROPID( cpropid, rgpropid )))
+ goto errRet;
+
+ if (S_OK != (hr = ValidateOutRGLPOLESTR( cpropid, rglpwstrName )))
+ goto errRet;
+
+ // --------------
+ // Read the Names
+ // --------------
+
+ Lock( INFINITE );
+ fLocked = TRUE;
+
+ Status = RtlQueryPropertyNames(_np, cpropid, rgpropid, rglpwstrName);
+ if (Status == STATUS_NOT_FOUND)
+ hr = STG_E_INVALIDHEADER;
+ else
+ if (Status == STATUS_BUFFER_ALL_ZEROS)
+ hr = S_FALSE;
+ else
+ if (!NT_SUCCESS(Status))
+ hr = DfpNtStatusToHResult(Status);
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ if( fLocked )
+ Unlock();
+
+ PropDbg((DEB_PROP_EXIT, "CPropertyStorage(%08X)::ReadPropertyNames(cpropid=%d, rgpropid=%08X, "
+ "rglpwstrName=%08X) returns %08X\n",
+ this, cpropid, rgpropid, rglpwstrName, hr));
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::_WritePropertyNames
+//
+// Synopsis: Internal function used by WritePropertyNames and
+// DeletePropertyNames.
+//
+// Arguments: [cpropid] -- Count of PROPIDs in [rgpropid]
+// [rgpropid] -- Pointer to array of [cpropid] PROPIDs
+// [rglpstrName] -- Pointer to array of [cpropid] LPOLESTRs
+//
+// Returns: S_OK if successful, otherwise error code.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertyStorage::_WritePropertyNames(
+ ULONG cpropid,
+ const PROPID rgpropid[],
+ const LPOLESTR rglpwstrName[])
+{
+ NTSTATUS Status;
+
+ Status = RtlSetPropertyNames(_np, cpropid, rgpropid, (OLECHAR const * const *) rglpwstrName);
+ return NT_SUCCESS(Status) ? S_OK : DfpNtStatusToHResult(Status);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::WritePropertyNames
+//
+// Synopsis: Attempt to write names for all identified properties.
+//
+// Arguments: [cpropid] -- Count of PROPIDs in [rgpropid]
+// [rgpropid] -- Pointer to array of [cpropid] PROPIDs
+// [rglpstrName] -- Pointer to array of [cpropid] LPOLESTRs
+//
+// Returns: S_OK -- success, otherwise error code.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertyStorage::WritePropertyNames(
+ ULONG cpropid,
+ const PROPID rgpropid[],
+ const LPOLESTR rglpwstrName[])
+{
+ HRESULT hr;
+ BOOL fLocked = FALSE;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ if (S_OK != (hr = IsReverted()))
+ goto errRet;
+
+ if (S_OK != (hr = IsWriteable()))
+ goto errRet;
+
+ // Validate inputs
+
+ if (0 == cpropid)
+ {
+ hr = S_OK;
+ goto errRet;
+ }
+
+ if (S_OK != (hr = ValidateRGPROPID( cpropid, rgpropid )))
+ goto errRet;
+
+ if (S_OK != (hr = ValidateInRGLPOLESTR( cpropid, rglpwstrName )))
+ goto errRet;
+
+ // ---------------
+ // Write the Names
+ // ---------------
+
+ Lock(INFINITE);
+ fLocked = TRUE;
+
+ hr = _WritePropertyNames(cpropid, rgpropid, rglpwstrName);
+
+ if (hr == STG_E_INSUFFICIENTMEMORY)
+ {
+ hr = S_OK;
+
+ for (ULONG i=0; hr == S_OK && i < cpropid; i++)
+ {
+ hr = _WritePropertyNames(1, rgpropid+i, rglpwstrName+i);
+ if( FAILED(hr) ) goto errRet;
+ }
+ }
+ if( FAILED(hr) ) goto errRet;
+
+ // If buffering is not desired, flush the property storage
+ // to the underlying Stream.
+
+ if( _grfFlags & PROPSETFLAG_UNBUFFERED )
+ {
+ NTSTATUS Status = RtlFlushPropertySet(_np);
+ if (!NT_SUCCESS(Status))
+ {
+ hr = DfpNtStatusToHResult(Status);
+ }
+ }
+
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ if( fLocked )
+ Unlock();
+
+ PropDbg((DEB_PROP_EXIT, "CPropertyStorage(%08X)::WritePropertyNames(cpropid=%d, rgpropid=%08X, "
+ "rglpwstrName=%08X) returns %08X\n",
+ this, cpropid, rgpropid, rglpwstrName, hr));
+ return hr;
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::DeletePropertyNames
+//
+// Synopsis: Attempt to delete names for all identified properties.
+//
+// Arguments: [cpropid] -- Count of PROPIDs in [rgpropid]
+// [rgpropid] -- Pointer to array of [cpropid] PROPIDs
+//
+// Returns: S_OK -- success, otherwise error.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertyStorage::DeletePropertyNames(
+ ULONG cpropid,
+ const PROPID rgpropid[])
+{
+ HRESULT hr;
+ BOOL fLocked = FALSE;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ if (S_OK != (hr = IsReverted()))
+ goto errRet;
+
+ if (S_OK != (hr = IsWriteable()))
+ goto errRet;
+
+ // Validate the inputs
+
+ if( 0 == cpropid )
+ {
+ hr = S_OK;
+ goto errRet;
+ }
+
+ if (S_OK != (hr = ValidateRGPROPID( cpropid, rgpropid )))
+ goto errRet;
+
+ // ----------------
+ // Delete the Names
+ // ----------------
+
+ Lock(INFINITE);
+ fLocked = TRUE;
+
+ hr = _WritePropertyNames(cpropid, rgpropid, NULL);
+ if (hr == STG_E_INSUFFICIENTMEMORY)
+ {
+ hr = S_OK;
+
+ for (ULONG i=0; hr == S_OK && i < cpropid; i++)
+ {
+ hr = _WritePropertyNames(1, rgpropid+i, NULL);
+ if( FAILED(hr) ) goto errRet;
+ }
+ }
+ if( FAILED(hr) ) goto errRet;
+
+ // If buffering is not desired, flush the property storage
+ // to the underlying Stream.
+
+ if( _grfFlags & PROPSETFLAG_UNBUFFERED )
+ {
+ NTSTATUS Status = RtlFlushPropertySet(_np);
+ if (!NT_SUCCESS(Status))
+ {
+ hr = DfpNtStatusToHResult(Status);
+ }
+ }
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ if( fLocked )
+ Unlock();
+
+ PropDbg((DEB_PROP_EXIT, "CPropertyStorage(%08X)::DeletePropertyNames(cpropid=%d, rgpropid=%08X) "
+ "returns %08X\n",
+ this, cpropid, rgpropid, hr));
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::Commit
+//
+// Synopsis: Flush and/or commit the property set
+//
+// Arguments: [grfCommittFlags] -- Commit flags.
+//
+// Returns: S_OK -- success, otherwise error.
+//
+// Notes: For both simple and non-simple, this flushes the
+// memory image to disk subsystem. In addition,
+// for non-simple transacted-mode property sets, this
+// performs a commit on the property set.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertyStorage::Commit(DWORD grfCommitFlags)
+{
+ HRESULT hr;
+ NTSTATUS Status;
+ BOOL fLocked = FALSE;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ if (S_OK != (hr = IsReverted()))
+ goto errRet;
+
+ if (S_OK != (hr = IsWriteable()))
+ goto errRet;
+
+ // Validate the inputs
+
+ if (S_OK != (hr = VerifyCommitFlags(grfCommitFlags)))
+ goto errRet;
+
+ // --------------------------
+ // Commit the PropertyStorage
+ // --------------------------
+
+ Lock( INFINITE );
+ fLocked = TRUE;
+
+ Status = RtlFlushPropertySet(_np);
+ if (!NT_SUCCESS(Status))
+ {
+ hr = DfpNtStatusToHResult(Status);
+ }
+
+ if (IsNonSimple())
+ {
+ if (hr == S_OK)
+ hr = _pstgPropSet->Commit(grfCommitFlags);
+ }
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ if( fLocked )
+ Unlock();
+
+ PropDbg((DEB_PROP_EXIT, "CPropertyStorage(%08X)::Commit(grfCommitFlags=%08X) "
+ "returns %08X\n",
+ this, grfCommitFlags, hr));
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::Revert
+//
+// Synopsis: For non-simple property sets, revert it.
+//
+// Returns: S_OK if successful. STG_E_UNIMPLEMENTEDFUNCTION for
+// simple property sets.
+//
+// Notes: For non-simple property sets, call the underlying
+// storage's Revert and re-open the 'contents' stream.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertyStorage::Revert()
+{
+ HRESULT hr;
+ BOOL fLocked = FALSE;
+
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ if (IsNonSimple())
+ {
+ Lock(INFINITE);
+ fLocked = TRUE;
+
+ hr = _pstgPropSet->Revert(); // BUGBUG: dirty flags
+ if (hr == S_OK)
+ {
+ RtlClosePropertySet(_np);
+ _np = NULL;
+
+#ifdef _CAIRO_
+ if (_fNative) // BUGBUG: put this specific code in IPrivateStorage
+ {
+ if (_ms != NULL)
+ {
+ RtlCloseMappedStream(_ms);
+ }
+ }
+#endif
+ _pstmPropSet->Release();
+ _pstmPropSet = NULL;
+ _ms = NULL;
+
+ // BUGBUG: if one of these fails then we are in deep trouble.
+ // Mask out the STGM_TRANSACTED bit because we don't support it.
+
+ hr = _pstgPropSet->OpenStream(ocsContents, NULL,
+ (_grfAccess | _grfShare) & ~STGM_TRANSACTED,
+ 0, &_pstmPropSet);
+ if (hr == S_OK)
+ {
+ // Initialize the property set. If this property set is the 2nd section
+ // of the DocumentSummaryInformation property set (used by Office),
+ // then we must specify the FMTID.
+ hr = InitializePropertyStream(
+ (S_OK == IsWriteable() ? CREATEPROP_WRITE : CREATEPROP_READ) |
+ CREATEPROP_NONSIMPLE,
+ _fUserDefinedProperties ? &FMTID_UserDefinedProperties : NULL,
+ NULL);
+ }
+
+ if (hr != S_OK)
+ {
+ _ulSig = PROPERTYSTORAGE_SIGZOMBIE;
+ }
+ }
+
+ }
+ else
+ hr = S_OK;
+
+errRet:
+
+ if( fLocked )
+ Unlock();
+
+ PropDbg((DEB_PROP_EXIT, "CPropertyStorage(%08X)::Revert() "
+ "returns %08X\n",
+ this, hr));
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::Enum
+//
+// Synopsis: Create an enumerator over the property set.
+//
+// Arguments: [ppenum] -- where to return the IEnumSTATPROPSTG *
+//
+// Returns: S_OK or error.
+//
+// Notes: The constructor of CEnumSTATPROPSTG creates a
+// CStatArray which reads the entire property set and
+// which can be shared when IEnumSTATPROPSTG::Clone is
+// used.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertyStorage::Enum(IEnumSTATPROPSTG ** ppenum)
+{
+ HRESULT hr;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ return(hr);
+
+ if (S_OK != (hr = IsReadable()))
+ return(hr);
+
+ if (S_OK != (hr = IsReverted()))
+ return(hr);
+
+ // Validate the inputs
+
+ VDATEPTROUT( ppenum, IEnumSTATPROPSTG* );
+
+ // ----------------------
+ // Create the Enumeration
+ // ----------------------
+
+ *ppenum = NULL;
+
+ hr = STG_E_INSUFFICIENTMEMORY;
+
+ *ppenum = new CEnumSTATPROPSTG(_np, &hr);
+ if (FAILED(hr))
+ {
+ delete (CEnumSTATPROPSTG*) *ppenum;
+ *ppenum = NULL;
+ }
+
+ // ----
+ // Exit
+ // ----
+
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::SetTimes
+//
+// Synopsis: Set the given times on the underlying storage
+//
+// Arguments: [pctime] -- creation time
+// [patime[ -- access time
+// [pmtime] -- modify time
+//
+// Returns: S_OK or error.
+//
+// Notes:
+// (non-simple only) Only the times supported by the
+// underlying docfile implementation are
+// supported.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertyStorage::SetTimes(
+ FILETIME const * pctime,
+ FILETIME const * patime,
+ FILETIME const * pmtime)
+{
+ HRESULT hr;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ if (S_OK != (hr = IsReverted()))
+ goto errRet;
+
+ if (S_OK != (hr = IsWriteable()))
+ goto errRet;
+
+ // Validate the inputs
+
+ VDATEPTRIN_LABEL( pctime, FILETIME, errRet, hr );
+ VDATEPTRIN_LABEL( patime, FILETIME, errRet, hr );
+ VDATEPTRIN_LABEL( pmtime, FILETIME, errRet, hr );
+
+ // -------------
+ // Set the Times
+ // -------------
+
+ if (IsNonSimple())
+ {
+ hr = _pstgPropSet->SetElementTimes(
+ NULL,
+ pctime,
+ patime,
+ pmtime);
+ }
+ if( FAILED(hr) ) goto errRet;
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ PropDbg((DEB_PROP_EXIT, "CPropertyStorage(%08X)::SetTimes(pctime=%08X, patime=%08X, pmtime=%08X) "
+ "returns %08X\n",
+ this, pctime, patime, pmtime, hr));
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::SetClass
+//
+// Synopsis: Sets the class of the property set.
+//
+// Arguments: [clsid] -- class id to set.
+//
+// Returns: S_OK or error.
+//
+// Notes: If non-simple, the underlying storage has SetClass
+// called. Both simple and non-simple will have
+// clsid set into the property set stream.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertyStorage::SetClass(REFCLSID clsid)
+{
+ HRESULT hr;
+ NTSTATUS Status;
+ BOOL fLocked = FALSE;
+ DBGBUF(buf);
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ if (S_OK != (hr = IsReverted()))
+ goto errRet;
+
+ if (S_OK != (hr = IsWriteable()))
+ goto errRet;
+
+ // Validate the inputs
+
+ GEN_VDATEREADPTRIN_LABEL(&clsid, CLSID, E_INVALIDARG, errRet, hr);
+
+ // -------------
+ // Set the CLSID
+ // -------------
+
+ Lock( INFINITE );
+ fLocked = TRUE;
+
+ // Set it in the property set header
+
+ Status = RtlSetPropertySetClassId(_np, &clsid);
+ if (NT_SUCCESS(Status))
+ {
+ // And if this is an IStorage, set it there as well.
+ if (IsNonSimple())
+ {
+ hr = _pstgPropSet->SetClass(clsid);
+ }
+ }
+ else
+ {
+ hr = DfpNtStatusToHResult(Status);
+ }
+ if( FAILED(hr) ) goto errRet;
+
+ // If buffering is not desired, flush the property storage
+ // to the underlying Stream.
+
+ if( _grfFlags & PROPSETFLAG_UNBUFFERED )
+ {
+ NTSTATUS Status = RtlFlushPropertySet(_np);
+ if (!NT_SUCCESS(Status))
+ {
+ hr = DfpNtStatusToHResult(Status);
+ }
+ }
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ if( fLocked )
+ Unlock();
+
+ if( E_INVALIDARG != hr )
+ {
+ PropDbg((DEB_PROP_EXIT, "CPropertyStorage(%08X)::SetClass(clsid=%s) "
+ "returns %08X\n",
+ this, DbgFmtId(clsid, buf), hr));
+ }
+ else
+ {
+ PropDbg((DEB_PROP_EXIT, "CPropertyStorage(%08X)::SetClass(clsid@%08X) "
+ "returns %08X\n",
+ this, &clsid, hr));
+ }
+
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::Stat
+//
+// Synopsis: Get STATPROPSETSTG about the property set.
+//
+// Arguments: [p] -- STATPROPSETSTG *
+//
+// Returns: S_OK if successful, error otherwise. On failure,
+// *p is all zeros.
+//
+// Notes: See spec. Gets times from underlying storage or stream
+// using IStorage or IStream ::Stat.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertyStorage::Stat(STATPROPSETSTG * p)
+{
+ HRESULT hr;
+ NTSTATUS Status;
+ BOOL fLocked = FALSE;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ if (S_OK != (hr = IsReverted()))
+ goto errRet;
+
+ if (S_OK != (hr = IsReadable()))
+ goto errRet;
+
+ // Validate inputs
+
+ VDATEPTROUT_LABEL(p, STATPROPSETSTG, errRet, hr);
+
+ // ------------
+ // Get the Stat
+ // ------------
+
+ Lock( INFINITE );
+ fLocked = TRUE;
+
+ ZeroMemory(p, sizeof(*p));
+
+ // returns mtime, ansi flag, clsid, fmtid
+ Status = RtlQueryPropertySet(_np, p);
+ if (NT_SUCCESS(Status))
+ {
+ STATSTG statstg;
+
+ hr = S_OK;
+
+ if (IsNonSimple())
+ {
+ hr = _pstgPropSet->Stat(&statstg, STATFLAG_NONAME);
+ }
+ else
+ {
+ hr = _pstmPropSet->Stat(&statstg, STATFLAG_NONAME);
+ }
+
+ if (hr == S_OK)
+ {
+ p->mtime = statstg.mtime;
+ p->ctime = statstg.ctime;
+ p->atime = statstg.atime;
+ p->grfFlags = _grfFlags;
+ p->dwOSVersion = _dwOSVersion;
+ }
+ }
+ else
+ {
+ hr = DfpNtStatusToHResult(Status);
+ }
+
+ if (FAILED(hr))
+ {
+ ZeroMemory(p, sizeof(*p));
+ }
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ if( fLocked )
+ Unlock();
+
+ PropDbg((DEB_PROP_EXIT, "CPropertyStorage(%08X)::Stat(STATPROPSETSTG *p = %08X) "
+ "returns %08X\n",
+ this, p, hr));
+ return(hr);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CDocFilePropertyStorage::Lock/Unlock
+//
+// Synopsis: Wait for acquisition of DocFile tree mutex.
+//
+// Inputs: [DWORD] dwTimeout (for Lock method)
+// Timeout delay.
+//
+// Returns: Nothing
+//
+//--------------------------------------------------------------------
+
+VOID
+CDocFilePropertyStorage::Lock(DWORD dwTimeout)
+{
+#ifndef IPROPERTY_DLL
+
+ if (IsNonSimple())
+ {
+ ((CExposedDocFile*)_pstgPropSet)->Lock(dwTimeout);
+ }
+ else
+ {
+ ((CExposedStream*)_pstmPropSet)->Lock(S_OK != IsWriteable());
+ }
+
+#else
+ DfpAssert( !"DocFile used in IProperty DLL" );
+#endif
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CDocFilePropertyStorage::Unlock
+//
+// Synopsis: Release tree mutex.
+//
+//--------------------------------------------------------------------
+VOID CDocFilePropertyStorage::Unlock()
+{
+#ifndef IPROPERTY_DLL
+
+ if (IsNonSimple())
+ {
+ ((CExposedDocFile*)_pstgPropSet)->Unlock();
+ }
+ else
+ {
+ ((CExposedStream*)_pstmPropSet)->Unlock();
+ }
+
+#else
+ DfpAssert( !"DocFile used in IProperty DLL" );
+#endif
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CStatArray::CStatArray
+//
+// Synopsis: Read in the enumeration using RtlEnumerateProperties
+//
+// Arguments: [np] -- the NTPROP to use
+// [phr] -- S_OK on success, error otherwise.
+//
+// Notes: Retry getting number of properties and reading all of
+// them into a caller-allocated buffer until it fits.
+//
+//--------------------------------------------------------------------
+
+CStatArray::CStatArray(NTPROP np, HRESULT *phr)
+{
+ NTSTATUS Status;
+ ULONG ulKeyZero;
+ ULONG cpropAllocated;
+
+ _cRefs = 1;
+ _psps = NULL;
+
+ do
+ {
+ // when *pkey == 0, *pcprop == MAXULONG, aprs == NULL and asps == NULL on input,
+ // *pcprop will be the total count of properties in the enumeration set. OLE needs to
+ // allocate memory and enumerate out of the cached PROPID+propname list.
+
+ ulKeyZero = 0;
+ _cpropActual = MAX_ULONG;
+
+ delete [] _psps;
+ _psps = NULL;
+
+ Status = RtlEnumerateProperties(
+ np,
+ ENUMPROP_NONAMES,
+ &ulKeyZero,
+ &_cpropActual,
+ NULL, // aprs
+ NULL);
+
+ if (!NT_SUCCESS(Status))
+ break;
+
+ cpropAllocated = _cpropActual + 1;
+
+ _psps = new STATPROPSTG [ cpropAllocated ];
+ if (_psps == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+
+ ulKeyZero = 0;
+ Status = RtlEnumerateProperties(
+ np,
+ 0,
+ &ulKeyZero,
+ &cpropAllocated,
+ NULL, // aprs
+ _psps);
+ } while (NT_SUCCESS(Status) && cpropAllocated != _cpropActual);
+
+ *phr = NT_SUCCESS(Status) ? S_OK : DfpNtStatusToHResult(Status);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStatArray::~CStatArray
+//
+// Synopsis: Deallocated the object's data.
+//
+//--------------------------------------------------------------------
+
+CStatArray::~CStatArray()
+{
+ if (_psps != NULL)
+ {
+ CleanupSTATPROPSTG(_cpropActual, _psps);
+ }
+ delete [] _psps;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStatArray::NextAt
+//
+// Synopsis: Read from the internal STATPROPSTG array.
+//
+// Effects: The cursor is passed in, and this function acts
+// as a IEnumXX::Next would behave if the current cursor
+// was [ipropNext].
+//
+// Arguments: [ipropNext] -- index of cursor to use
+// [pspsDest] -- if NULL, emulate read's effect on cursor.
+// if non-NULL, return data with cursor effect.
+// [pceltFetched] -- buffer for count fetched
+//
+// Returns: STATUS_SUCCESS if successful, otherwise
+// STATUS_INSUFFICIENT_RESOURCES.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+NTSTATUS
+CStatArray::NextAt(ULONG ipropNext, STATPROPSTG *pspsDest, ULONG *pceltFetched)
+{
+ ULONG ipropLastPlus1;
+
+ //
+ // Copy the requested number of elements from the cache
+ // (including strings, the allocation of which may fail.)
+ //
+
+ ipropLastPlus1 = ipropNext + *pceltFetched;
+ if (ipropLastPlus1 > _cpropActual)
+ {
+ ipropLastPlus1 = _cpropActual;
+ }
+
+ *pceltFetched = ipropLastPlus1 - ipropNext;
+
+ if (pspsDest != NULL)
+ return CopySTATPROPSTG(*pceltFetched, pspsDest, _psps + ipropNext);
+ else
+ return(STATUS_SUCCESS);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSTG::CEnumSTATPROPSTG
+//
+// Synopsis: Constructor for object that has cursor over CStatArray
+// and implements IEnumSTATPROPSTG, used by
+// CPropertyStorage::Enum.
+//
+// Arguments: [np] -- the NTPROP to use
+// [phr] -- where to put the HRESULT
+//
+//--------------------------------------------------------------------
+
+CEnumSTATPROPSTG::CEnumSTATPROPSTG(NTPROP np, HRESULT *phr)
+{
+ _ulSig = ENUMSTATPROPSTG_SIG;
+ _cRefs = 1;
+
+ _psa = new CStatArray(np, phr);
+
+ _ipropNext = 0;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSTG::CEnumSTATPROPSTG
+//
+// Synopsis: Constructor which is used by IEnumSTATPROPSTG::Clone.
+//
+// Arguments: [other] -- the CEnumSTATPROPSTG to copy
+// [phr] -- the error code.
+//
+// Notes: Since the CStatArray actually contains the object this
+// just adds to the ref count.
+//
+//--------------------------------------------------------------------
+
+CEnumSTATPROPSTG::CEnumSTATPROPSTG(const CEnumSTATPROPSTG & other, HRESULT *phr)
+{
+ _ulSig = ENUMSTATPROPSTG_SIG;
+ _cRefs = 1;
+
+ _psa = other._psa;
+ _psa->AddRef();
+
+ _ipropNext = other._ipropNext;
+
+ *phr = S_OK;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSTG::~CEnumSTATPROPSTG
+//
+// Synopsis: Deallocated storage.
+//
+// Arguments:
+//
+// Returns:
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+CEnumSTATPROPSTG::~CEnumSTATPROPSTG()
+{
+ _ulSig = ENUMSTATPROPSTG_SIGDEL; // prevent another thread doing it - kinda
+
+ if (_psa != NULL)
+ _psa->Release();
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSTG::QueryInterface
+//
+// Synopsis: Respond to IEnumSTATPROPSTG and IUnknown.
+//
+// Returns: S_OK or E_NOINTERFACE
+//
+//--------------------------------------------------------------------
+
+HRESULT CEnumSTATPROPSTG::QueryInterface( REFIID riid, void **ppvObject)
+{
+ HRESULT hr;
+
+ *ppvObject = NULL;
+
+ if (S_OK != (hr = Validate()))
+ return(hr);
+
+ if (IsEqualIID(riid, IID_IEnumSTATPROPSTG))
+ {
+ *ppvObject = (IEnumSTATPROPSTG *)this;
+ AddRef();
+ }
+ else
+ if (IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppvObject = (IUnknown *)this;
+ AddRef();
+ }
+ else
+ {
+ hr = E_NOINTERFACE;
+ }
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSTG::AddRef
+//
+// Synopsis: Add 1 to ref count.
+//
+//--------------------------------------------------------------------
+
+ULONG CEnumSTATPROPSTG::AddRef(void)
+{
+ if (S_OK != Validate())
+ return(0);
+
+ InterlockedIncrement(&_cRefs);
+ return(_cRefs);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSTG::Release
+//
+// Synopsis: Subtract 1 from ref count and delete if 0.
+//
+//--------------------------------------------------------------------
+
+ULONG CEnumSTATPROPSTG::Release(void)
+{
+ LONG lRet;
+
+ if (S_OK != Validate())
+ return(0);
+
+ lRet = InterlockedDecrement(&_cRefs);
+
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else
+ if (lRet <0)
+ {
+ lRet = 0;
+ }
+ return(lRet);
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: CopySTATPROPSTG
+//
+// Synopsis: Copy out the range of elements from [pspsSrc] to
+// [pspsDest].
+//
+// Arguments: [celt] -- count of elements to copy
+// [pspsDest] -- where to copy to, always filled with
+// zeros before anything else (helps cleanup
+// case.)
+//
+// [pspsSrc] -- where to copy from
+//
+// Returns: STATUS_SUCCESS if ok, otherwise
+// STATUS_INSUFFICIENT_RESOURCES in which case there
+// may be pointers that need deallocating. Use
+// CleanupSTATPROPSTG to do that.
+//
+//--------------------------------------------------------------------
+
+NTSTATUS
+CopySTATPROPSTG(ULONG celt,
+ STATPROPSTG * pspsDest,
+ const STATPROPSTG * pspsSrc)
+{
+ memset(pspsDest, 0, sizeof(*pspsDest) * celt);
+
+ while (celt)
+ {
+ *pspsDest = *pspsSrc;
+
+ if (pspsSrc->lpwstrName != NULL)
+ {
+ pspsDest->lpwstrName = (LPOLESTR)CoTaskMemAlloc(
+ sizeof(OLECHAR)*(1+ocslen(pspsSrc->lpwstrName)));
+ if (pspsDest->lpwstrName != NULL)
+ {
+ ocscpy(pspsDest->lpwstrName,
+ pspsSrc->lpwstrName);
+ }
+ else
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ celt--;
+ pspsDest++;
+ pspsSrc++;
+ }
+
+ return(STATUS_SUCCESS);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CleanupSTATPROPSTG
+//
+// Synopsis: Free any elements in the passed array.
+//
+// Arguments: [celt] -- number of elements to examine.
+// [psps] -- array of STATPROPSTG to examine.
+//
+// Notes: Zeros them out too.
+//
+//--------------------------------------------------------------------
+
+VOID
+CleanupSTATPROPSTG(ULONG celt, STATPROPSTG * psps)
+{
+ while (celt)
+ {
+ CoTaskMemFree(psps->lpwstrName);
+ memset(psps, 0, sizeof(*psps));
+ celt--;
+ psps++;
+ }
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSTG::Next
+//
+// Synopsis: Get the next [celt] STATPROPSTGs from the enumerator.
+//
+// Arguments: [celt] -- count requested.
+// [rgelt] -- where to return them
+// [pceltFetched] -- buffer for returned-count.
+// if pceltFetched==NULL && celt != 1 -> STG_E_INVALIDPARAMETER
+// if pceltFetched!=NULL && celt == 0 -> S_OK
+//
+// Returns: S_OK if successful, otherwise error.
+//
+//--------------------------------------------------------------------
+
+HRESULT CEnumSTATPROPSTG::Next(
+ ULONG celt,
+ STATPROPSTG * rgelt,
+ ULONG * pceltFetched)
+{
+ HRESULT hr;
+ NTSTATUS Status;
+ ULONG celtFetched = celt;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ return(hr);
+
+ // Validate the inputs
+
+ if (NULL == pceltFetched)
+ {
+ if (celt != 1)
+ return(STG_E_INVALIDPARAMETER);
+ }
+ else
+ {
+ VDATEPTROUT( pceltFetched, ULONG );
+ *pceltFetched = 0;
+ }
+
+ if( 0 == celt )
+ return( S_OK );
+
+ if( !IsValidPtrOut(rgelt, celt * sizeof(rgelt[0])) )
+ return( E_INVALIDARG );
+
+
+ // -----------------------
+ // Perform the enumeration
+ // -----------------------
+
+ if (celt == 0)
+ return(hr);
+
+ Status = _psa->NextAt(_ipropNext, rgelt, &celtFetched);
+
+ if (NT_SUCCESS(Status))
+ {
+ _ipropNext += celtFetched;
+
+ if (pceltFetched != NULL)
+ *pceltFetched = celtFetched;
+
+ hr = celtFetched == celt ? S_OK : S_FALSE;
+ }
+ else
+ {
+ CleanupSTATPROPSTG(celt, rgelt);
+ hr = DfpNtStatusToHResult(Status);
+ }
+
+ return(hr);
+
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSTG::Skip
+//
+// Synopsis: Skip the next [celt] elements in the enumeration.
+//
+// Arguments: [celt] -- number of elts to skip
+//
+// Returns: S_OK if skipped [celt] elements
+// S_FALSE if skipped < [celt] elements
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+HRESULT CEnumSTATPROPSTG::Skip(ULONG celt)
+{
+ HRESULT hr;
+ ULONG celtFetched = celt;
+
+ if (S_OK != (hr = Validate()))
+ return(hr);
+
+ _psa->NextAt(_ipropNext, NULL, &celtFetched);
+
+ _ipropNext += celtFetched;
+
+ return celtFetched == celt ? S_OK : S_FALSE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSTG::Reset
+//
+// Synopsis: Set cursor to beginnging of enumeration.
+//
+// Returns: S_OK otherwise STG_E_INVALIDHANDLE.
+//
+//--------------------------------------------------------------------
+
+HRESULT CEnumSTATPROPSTG::Reset()
+{
+ HRESULT hr;
+
+ if (S_OK != (hr = Validate()))
+ return(hr);
+
+ _ipropNext = 0;
+
+ return(S_OK);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSTG::Clone
+//
+// Synopsis: Creates an IEnumSTATPROPSTG with same cursor
+// as this.
+//
+// Arguments: S_OK or error.
+//
+//--------------------------------------------------------------------
+
+HRESULT CEnumSTATPROPSTG::Clone(IEnumSTATPROPSTG ** ppenum)
+{
+ HRESULT hr;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ return(hr);
+
+ // Validate the input
+
+ VDATEPTROUT( ppenum, IEnumSTATPROPSTG* );
+
+ // --------------------
+ // Clone the enumerator
+ // --------------------
+
+ *ppenum = NULL;
+
+ hr = STG_E_INSUFFICIENTMEMORY;
+
+ *ppenum = new CEnumSTATPROPSTG(*this, &hr);
+
+ if (FAILED(hr))
+ {
+ delete (CEnumSTATPROPSTG*)*ppenum;
+ *ppenum = NULL;
+ }
+
+ return(hr);
+}
+
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Function: Lock & Unlock
+//
+// Synopsis: This methods take and release the CPropertyStorage's
+// critical section.
+//
+// Inputs: [DWORD] dwTimeout (for Lock)
+// Must be INFINITE
+//
+// Returns: Nothing
+//
+// Notes: These methods are overridden by the CDocFilePropertyStorage
+// derivation, and do nothing when built for the Macintosh
+// (since the Mac has cooperative multi-threading, there is
+// no concurrency problem).
+//
+//+----------------------------------------------------------------------------
+
+VOID
+CPropertyStorage::Lock(DWORD dwTimeout)
+{
+ DfpAssert( INFINITE == dwTimeout );
+#ifndef _MAC
+ EnterCriticalSection( &_CriticalSection );
+#endif
+
+}
+
+VOID
+CPropertyStorage::Unlock()
+{
+#ifndef _MAC
+ LeaveCriticalSection( &_CriticalSection );
+#endif
+}
+
+
+//+-----------------------------------------------------------------------
+//
+// Member: InitializeOnCreateOrOpen
+//
+// Synopsis: This routine is called during the creation or opening
+// of a Property Storage, and initializes everything
+// it can without being concerned about whether this
+// is a simple or non-simple property set.
+//
+// Inputs: [DWORD] grfFlags (in)
+// From the PROPSETFLAG_* enumeration.
+// [DWORD] grfMode (in)
+// From the STGM_* enumeration.
+// [REFFMTID] rfmtid (in)
+// The ID of the property set.
+// [BOOL] fCreate (in)
+// Distinguishes Create from Open.
+//
+// Returns: [HRESULT]
+//
+// Effects: _grfFlags, _grfAccess, _grfShare, _fUserDefinedProperties,
+// and g_ReservedMemory.
+//
+//+-----------------------------------------------------------------------
+
+
+HRESULT
+CPropertyStorage::InitializeOnCreateOrOpen(
+ DWORD grfFlags,
+ DWORD grfMode,
+ REFFMTID rfmtid,
+ BOOL fCreate )
+{
+ HRESULT hr = S_OK;
+
+ // Validate that grfFlags is within the enumeration.
+ if (grfFlags & ~(PROPSETFLAG_ANSI | PROPSETFLAG_NONSIMPLE | PROPSETFLAG_UNBUFFERED))
+ {
+ hr = STG_E_INVALIDFLAG;
+ goto Exit;
+ }
+
+ // Check for any mode disallowed flags
+ if (grfMode & ( (fCreate ? 0 : STGM_CREATE)
+ |
+ STGM_PRIORITY | STGM_CONVERT
+ |
+ STGM_SIMPLE | STGM_DELETEONRELEASE ))
+ {
+ hr = STG_E_INVALIDFLAG;
+ goto Exit;
+ }
+
+ // Ensure that we'll have read/write access to any storage/stream we create.
+ if( fCreate
+ &&
+ (grfMode & STGM_READWRITE) != STGM_READWRITE )
+ {
+ hr = STG_E_INVALIDFLAG;
+ goto Exit;
+ }
+
+ // Store the grfFlags & grfMode.
+ _grfFlags = grfFlags;
+ _grfAccess = 3 & grfMode;
+ _grfShare = 0xF0 & grfMode;
+
+ // Is this the special-case second-section property set?
+ _fUserDefinedProperties = ( rfmtid == FMTID_UserDefinedProperties ) ? TRUE : FALSE;
+
+ if (fCreate
+ &&
+ (_grfFlags & PROPSETFLAG_ANSI) )
+ {
+ _usCodePage = GetACP();
+ }
+
+ // Initialize the global reserved memory (to prevent problems
+ // in low-memory conditions).
+
+ if (S_OK != (hr = g_ReservedMemory.Init()))
+ goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return( hr );
+
+
+} // CPropertyStorage::InitializeOnCreate()
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::Create( IStream * ...
+//
+// Synopsis: This method creates an IPropertyStorage on a
+// given *Stream*. It is therefore a simple property
+// set. The given Stream is addref-ed.
+//
+// Arguments: [IStream*] pstm
+// The Stream which will hold the serialized property set.
+// [REFFMTID] rfmtid
+// The ID of the property set.
+// [const CLSID*]
+// The COM object which can interpret the property set.
+// [DWORD] grfFlags
+// From the PROPSETFLAG_* enumeration.
+// [DWORD] grfMode
+// From the STGM_* enumeration
+// [HRESULT*]
+// The return code.
+//
+// Returns: None.
+//
+//--------------------------------------------------------------------
+
+VOID
+CPropertyStorage::Create(
+ IStream *pstm,
+ REFFMTID rfmtid,
+ const CLSID *pclsid,
+ DWORD grfFlags,
+ HRESULT *phr)
+{
+ HRESULT & hr = *phr;
+ BOOL fCreated = FALSE;
+ STATSTG statstg;
+
+ // Save and addref the Stream.
+
+ _pstmPropSet = pstm;
+ _pstmPropSet->AddRef();
+
+ // Initialize this object. We'll assume that the STGM_READWRITE bit
+ // is set, even if the statstg.grfMode doesn't have it set
+ // (this bit doesn't get set by the memory-based IStream::Stat implementation).
+
+ hr = _pstmPropSet->Stat( &statstg, STATFLAG_NONAME );
+ if( FAILED(hr) ) goto Exit;
+
+ hr = InitializeOnCreateOrOpen( grfFlags, statstg.grfMode | STGM_READWRITE, rfmtid,
+ TRUE ); // => Create
+ if( FAILED(hr) ) goto Exit;
+
+ DfpAssert( !IsNonSimple() );
+
+ // Initialize the Stream.
+
+ hr = InitializePropertyStream(CREATEPROP_CREATE |
+ 0,
+ &rfmtid,
+ pclsid);
+ if( FAILED(hr) ) goto Exit;
+
+ // If buffering is not desired, flush the property storage
+ // to the underlying Stream.
+
+ if( _grfFlags & PROPSETFLAG_UNBUFFERED )
+ {
+ NTSTATUS Status = RtlFlushPropertySet(_np);
+ if (!NT_SUCCESS(Status))
+ {
+ hr = DfpNtStatusToHResult(Status);
+ }
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // On error, remove our reference to the Stream.
+ if( FAILED(hr) )
+ {
+ _pstmPropSet->Release();
+ _pstmPropSet = NULL;
+
+ PropDbg((DEB_PROP_TRACE_CREATE, "CPropertyStorage(%08X)::Create(IStream*)"
+ " hr=%08X\n", this, hr));
+ }
+
+ return;
+
+} // CPropertyStorage::Create( IStream *, ...
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::Create( IStorage *, ...
+//
+// Synopsis: This method creates an IPropertyStorage on a
+// given *Storage*. It is therefore a non-simple property
+// set. The Storage is addref-ed.
+//
+// Arguments: [IStorage*] pstm
+// The Storage which will hold the serialized property set.
+// [REFFMTID] rfmtid
+// The ID of the property set.
+// [const CLSID*]
+// The COM object which can interpret the property set.
+// [DWORD] grfFlags
+// From the PROPSETFLAG_* enumeration.
+// [HRESULT*]
+// The return code.
+//
+// Returns: None.
+//
+//--------------------------------------------------------------------
+
+VOID
+CPropertyStorage::Create(
+ IStorage *pstg,
+ REFFMTID rfmtid,
+ const CLSID *pclsid,
+ DWORD grfFlags,
+ HRESULT *phr)
+{
+ HRESULT & hr = *phr;
+ BOOL fCreated = FALSE;
+ STATSTG statstg;
+
+ // Save the given Storage.
+
+ _pstgPropSet = pstg;
+ _pstgPropSet->AddRef();
+
+ // Initialize this object. We'll assume that the STGM_READWRITE bit
+ // is set, even if the statstg.grfMode doesn't have it set
+ // (this bit doesn't get set by the memory-based IStream::Stat implementation).
+
+
+ hr = _pstgPropSet->Stat( &statstg, STATFLAG_NONAME );
+ if( FAILED(hr) ) goto Exit;
+
+ DfpAssert( grfFlags & PROPSETFLAG_NONSIMPLE );
+ hr = InitializeOnCreateOrOpen( grfFlags, statstg.grfMode | STGM_READWRITE, rfmtid,
+ TRUE ); // => Create
+ if( FAILED(hr) ) goto Exit;
+
+ DfpAssert( IsNonSimple() );
+
+ // Create the "CONTENTS" stream. Mask out the STGM_TRANSACTED
+ // bit because we don't support it.
+
+ hr = _pstgPropSet->CreateStream(ocsContents,
+ ( _grfAccess | _grfShare | STGM_CREATE ) & ~STGM_TRANSACTED,
+ 0, 0, &_pstmPropSet);
+ if (FAILED(hr)) goto Exit;
+ fCreated = TRUE;
+
+ // Initialize the CONTENTS Stream.
+
+ hr = InitializePropertyStream(
+ CREATEPROP_CREATE,
+ &rfmtid,
+ pclsid);
+ if( FAILED(hr) ) goto Exit;
+
+ // In the transacted case, ensure that the contents
+ // stream is actually published right away.
+
+ if( statstg.grfMode & STGM_TRANSACTED )
+ {
+ hr = Commit(STGC_DEFAULT);
+ if( FAILED(hr) ) goto Exit;
+
+ }
+
+ // If buffering is not desired, flush the property storage
+ // to the underlying Stream.
+
+ else if( _grfFlags & PROPSETFLAG_UNBUFFERED )
+ {
+ NTSTATUS Status = RtlFlushPropertySet(_np);
+ if (!NT_SUCCESS(Status))
+ {
+ hr = DfpNtStatusToHResult(Status);
+ }
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // On error, remove our reference to the Storage.
+
+ if( FAILED(hr) )
+ {
+ _pstgPropSet->Release();
+ _pstgPropSet = NULL;
+
+ // Also, delete the "CONTENTS" stream.
+ if( fCreated )
+ pstg->DestroyElement( ocsContents );
+
+ PropDbg((DEB_PROP_TRACE_CREATE, "CPropertyStorage(%08X)::Create(IStorage*)"
+ " hr=%08X\n", this, hr));
+ }
+
+ return;
+} // CPropertyStorage::Create( IStorage *, ...
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::Open( IStream * ...
+//
+// Synopsis: This method opens an IPropertyStorage on a
+// given *Stream*. It is therefore a simple property
+// set. The Stream is addref-ed.
+//
+// Arguments: [IStream*] pstm
+// The Stream which will hold the serialized property set.
+// [REFFMTID] rfmtid
+// The ID of the property set.
+// [DWORD] grfFlags
+// From the PROPSETFLAG_ enumeration. Only the
+// _UNBUFFERED flag is relevant _ANSI and
+// _NONSIMPLE are inferred from the property set.
+// [BOOL] fDelete
+// If TRUE, the property set is actually to be deleted,
+// rather than opened (this is used for the special-case
+// "UserDefined" property set).
+// [HRESULT*]
+// The return code.
+//
+// Returns: None.
+//
+//--------------------------------------------------------------------
+
+VOID
+CPropertyStorage::Open(
+ IStream *pstm,
+ REFFMTID rfmtid,
+ DWORD grfFlags,
+ BOOL fDelete,
+ HRESULT *phr)
+{
+ HRESULT & hr = *phr;
+
+ USHORT createprop = 0L;
+ STATSTG statstg;
+
+ // Keep a copy of the Stream.
+
+ _pstmPropSet = pstm;
+ _pstmPropSet->AddRef();
+
+ // Initialize this object.
+
+ hr = _pstmPropSet->Stat( &statstg, STATFLAG_NONAME );
+ if( FAILED(hr) ) goto Exit;
+
+ hr = InitializeOnCreateOrOpen( grfFlags,
+ statstg.grfMode,
+ rfmtid,
+ FALSE ); // => Open
+ if( FAILED(hr) ) goto Exit;
+
+ // Determine the CREATEPROP flags.
+
+ if( fDelete )
+ {
+ // Only simple Sections may be deleted (really, only the
+ // second section of the DocumentSummaryInformation property
+ // set may be deleted in this way).
+ DfpAssert( !IsNonSimple() );
+
+ createprop = CREATEPROP_DELETE;
+ }
+ else
+ {
+ createprop = (S_OK == IsWriteable() ? CREATEPROP_WRITE : CREATEPROP_READ);
+ }
+
+ // Initialize the property set Stream.
+
+ if (hr == S_OK)
+ {
+ // sets up _usCodePage
+ hr = InitializePropertyStream(
+ createprop,
+ &rfmtid,
+ NULL);
+
+ }
+ if( FAILED(hr) ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // On error, remove our reference to the Stream.
+ if( FAILED(hr) )
+ {
+ _pstmPropSet->Release();
+ _pstmPropSet = NULL;
+
+ PropDbg((DEB_PROP_TRACE_CREATE, "CPropertyStorage(%08X)::Open(IStream*)"
+ " hr=%08X\n", this, hr));
+ }
+
+ return;
+
+} // CPropertyStorage::Open( IStream *, ...
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::Open( IStorage * ...
+//
+// Synopsis: This method opens an IPropertyStorage on a
+// given *Storage*. It is therefore a non-simple property
+// set. The Storage is addref-ed.
+//
+// Arguments: [IStorage*] pstg
+// The Storage which will hold the serialized property set.
+// [REFFMTID] rfmtid
+// The ID of the property set.
+// [DWORD] grfFlags
+// From the PROPSETFLAG_ enumeration. Only the
+// _UNBUFFERED flag is relevant _ANSI and
+// _NONSIMPLE are inferred from the property set.
+// [HRESULT*]
+// The return code.
+//
+// Returns: None.
+//
+//--------------------------------------------------------------------
+
+VOID
+CPropertyStorage::Open(
+ IStorage *pstg,
+ REFFMTID rfmtid,
+ DWORD grfFlags,
+ HRESULT *phr)
+{
+ HRESULT & hr = *phr;
+ CPropSetName psn(rfmtid);
+ USHORT createprop = 0L;
+ STATSTG statstg;
+
+
+ // Keep a copy of the Storage
+
+ _pstgPropSet = pstg;
+ _pstgPropSet->AddRef();
+
+ // Initialize this object.
+
+ hr = _pstgPropSet->Stat( &statstg, STATFLAG_NONAME );
+ if( FAILED(hr) ) goto Exit;
+
+ hr = InitializeOnCreateOrOpen( grfFlags,
+ statstg.grfMode,
+ rfmtid,
+ FALSE ); // => Open
+ if( FAILED(hr) ) goto Exit;
+
+ _grfFlags |= PROPSETFLAG_NONSIMPLE;
+
+ // Open the CONTENTS stream. Mask out the STGM_TRANSACTED bit
+ // because it causes an error on Mac OLE2.
+
+ hr = _pstgPropSet->OpenStream( ocsContents,
+ 0,
+ (_grfAccess | _grfShare) & ~STGM_TRANSACTED,
+ 0,
+ &_pstmPropSet );
+ if( FAILED(hr) ) goto Exit;
+
+
+ // Set the CREATEPROP flags.
+ createprop = (S_OK == IsWriteable() ? CREATEPROP_WRITE : CREATEPROP_READ);
+
+ // Load the property set Stream.
+
+ if (hr == S_OK)
+ {
+ // sets up _usCodePage
+ hr = InitializePropertyStream(
+ createprop,
+ &rfmtid,
+ NULL);
+
+ }
+ if( FAILED(hr) ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // On error, remove our reference to the Storage.
+
+ if( FAILED(hr) )
+ {
+ _pstgPropSet->Release();
+ _pstgPropSet = NULL;
+
+ if( NULL != _pstmPropSet )
+ {
+ _pstmPropSet->Release();
+ _pstmPropSet = NULL;
+ }
+
+ PropDbg((DEB_PROP_TRACE_CREATE, "CPropertyStorage(%08X)::Open(IStorage*)"
+ " hr=%08X\n", this, hr));
+ }
+
+ return;
+
+
+} // CPropertyStorage::Open( IStorage *, ...
+
+
+//+----------------------------------------------------------------
+//
+// Member: CPropertyStorage::CreateMappedStream
+//
+// Synopsis: Create a CMappedStream object on an IStream.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// Notes: This method creates a CMappedStream which maps
+// an IStream. The CDocFilePropertyStorage derivative
+// overrides this member to create a CMappedStream
+// on a CExposedStream.
+//
+//+----------------------------------------------------------------
+
+HRESULT
+CPropertyStorage::CreateMappedStream()
+{
+ HRESULT hr = S_OK;
+
+ DfpAssert( NULL != _pstmPropSet );
+ DfpAssert( NULL == _ms );
+
+ _ms = new CCFMappedStream( _pstmPropSet );
+ if( NULL == _ms )
+ hr = E_OUTOFMEMORY;
+
+ return( hr );
+
+}
+
+//+----------------------------------------------------------------
+//
+// Member: CDocFilePropertyStorage::CreateMappedStream
+//
+// Synopsis: Create a CMappedStream object on a
+// CExposedStream.
+//
+// Arguments: None.
+//
+// Returns: None.
+//
+// Notes: This method creates a CMappedStream which maps
+// a CExposedStream. I.e. it bypasses the
+// IStream interface, and can access internal
+// functionality (such as the tree mutex).
+//
+//+----------------------------------------------------------------
+
+HRESULT
+CDocFilePropertyStorage::CreateMappedStream()
+{
+ HRESULT hr = S_OK;
+
+ // In the DLL implementation of this code, this class can't be used,
+ // and causes compiler errors, so we ifdef it out.
+
+#ifdef IPROPERTY_DLL
+ DfpAssert( !"CDocFilePropertyStorage used in IProp DLL" );
+#else
+
+ DfpAssert( NULL != _pstmPropSet );
+
+ // Convert the underlying IStream to a CExposedStream.
+ CExposedStream *pexpstm = (CExposedStream*)_pstmPropSet;
+ DfpAssert(pexpstm->Validate() != STG_E_INVALIDHANDLE );
+
+ // Convert the CExposedStream to a CMappedStream and we're done.
+ _ms = (CMappedStream*)pexpstm;
+
+ PropDbg((DEB_PROP_TRACE_CREATE, "CPropertyStorage(%08X)::CreateMappedStream"
+ " - using CExposedDocfile as CMappedStream\n", this));
+
+#endif
+
+ return( hr );
+}
+
+//+-------------------------------------------------------------------
+//
+// Members: CPropertyStorage:: access control method forwarders.
+//
+//--------------------------------------------------------------------
+
+#ifdef _CAIRO_
+// IAccessControl methods
+STDMETHODIMP CPropertyStorage::GrantAccessRights(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[])
+{
+ DfpAssert((_pIAC != NULL));
+ return _pIAC->GrantAccessRights(cCount, pAccessRequestList);
+}
+
+STDMETHODIMP CPropertyStorage::SetAccessRights(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[])
+{
+ DfpAssert((_pIAC != NULL));
+ return _pIAC->SetAccessRights(cCount, pAccessRequestList);
+}
+
+STDMETHODIMP CPropertyStorage::ReplaceAllAccessRights(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[])
+{
+ DfpAssert((_pIAC != NULL));
+ return _pIAC->ReplaceAllAccessRights(cCount, pAccessRequestList);
+}
+
+STDMETHODIMP CPropertyStorage::DenyAccessRights(ULONG cCount,
+ ACCESS_REQUEST pAccessRequestList[])
+{
+ DfpAssert((_pIAC != NULL));
+ return _pIAC->DenyAccessRights(cCount, pAccessRequestList);
+}
+
+STDMETHODIMP CPropertyStorage::RevokeExplicitAccessRights(ULONG cCount,
+ TRUSTEE pTrustee[])
+{
+ DfpAssert((_pIAC != NULL));
+ return _pIAC->RevokeExplicitAccessRights(cCount, pTrustee);
+}
+
+STDMETHODIMP CPropertyStorage::IsAccessPermitted(TRUSTEE *pTrustee,
+ DWORD grfAccessPermissions)
+{
+ DfpAssert((_pIAC != NULL));
+ return _pIAC->IsAccessPermitted(pTrustee, grfAccessPermissions);
+}
+
+STDMETHODIMP CPropertyStorage::GetEffectiveAccessRights(TRUSTEE *pTrustee,
+ DWORD *pgrfAccessPermissions )
+{
+ DfpAssert((_pIAC != NULL));
+ return _pIAC->GetEffectiveAccessRights(pTrustee, pgrfAccessPermissions);
+}
+
+STDMETHODIMP CPropertyStorage::GetExplicitAccessRights(ULONG *pcCount,
+ PEXPLICIT_ACCESS *pExplicitAccessList)
+{
+ DfpAssert((_pIAC != NULL));
+ return _pIAC->GetExplicitAccessRights(pcCount, pExplicitAccessList);
+}
+
+STDMETHODIMP CPropertyStorage::CommitAccessRights(DWORD grfCommitFlags)
+{
+ DfpAssert((_pIAC != NULL));
+ return _pIAC->CommitAccessRights(grfCommitFlags);
+}
+
+STDMETHODIMP CPropertyStorage::RevertAccessRights()
+{
+ DfpAssert((_pIAC != NULL));
+ return _pIAC->RevertAccessRights();
+}
+#endif
+
diff --git a/private/ole32/stg/props/propstg.hxx b/private/ole32/stg/props/propstg.hxx
new file mode 100644
index 000000000..c72800114
--- /dev/null
+++ b/private/ole32/stg/props/propstg.hxx
@@ -0,0 +1,838 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: propstg.hxx
+//
+// Contents: Class that directly implements IPropertyStorage
+//
+// Classes: CCoTaskAllocator
+// CPropertyStorage
+// CEnumSTATPROPSTG
+//
+// Functions:
+//
+//
+//
+// History: 1-Mar-95 BillMo Created.
+// 25-Jan-96 MikeHill Added _fmtidSection.
+// 22-May-96 MikeHill Added _dwOSVersion to CPropertyStorage.
+// 06-Jun-96 MikeHill Added support for input validation.
+// 18-Aug-96 MikeHill - Added CDocFilePropertyStorage.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#include <stgprops.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Class: CCoTaskAllocator
+//
+// Purpose: Class used by RtlQueryProperties to allocate memory.
+//
+//--------------------------------------------------------------------------
+
+class CCoTaskAllocator : public PMemoryAllocator
+{
+public:
+ virtual void *Allocate(ULONG cbSize);
+ virtual void Free(void *pv);
+
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CPropertyStorage
+//
+// Purpose: Implements IPropertyStorage.
+//
+// Notes: This class uses the functionality provided by
+// RtlCreatePropertySet, RtlSetProperties, RtlQueryProperties etc
+// to manipulate the property set stream.
+//
+//--------------------------------------------------------------------------
+
+#define PROPERTYSTORAGE_SIG LONGSIG('P','R','P','S')
+#define PROPERTYSTORAGE_SIGDEL LONGSIG('P','R','P','s')
+#define PROPERTYSTORAGE_SIGZOMBIE LONGSIG('P','R','P','z')
+#define ENUMSTATPROPSTG_SIG LONGSIG('E','P','S','S')
+#define ENUMSTATPROPSTG_SIGDEL LONGSIG('E','P','S','s')
+
+class CPropertyStorage : public IPropertyStorage
+{
+ // ------------
+ // Constructors
+ // ------------
+
+public:
+
+ // The destructor must be virtual so that derivative destructors
+ // will execute.
+
+ virtual ~CPropertyStorage();
+
+ CPropertyStorage()
+ {
+ Initialize();
+ }
+
+ // ---------------
+ // Exposed Methods
+ // ---------------
+
+public:
+
+ virtual VOID Create(
+ IStream *stm,
+ REFFMTID rfmtid,
+ const CLSID *pclsid,
+ DWORD grfFlags,
+ HRESULT *phr);
+
+ virtual VOID Create(
+ IStorage *pstg,
+ REFFMTID rfmtid,
+ const CLSID *pclsid,
+ DWORD grfFlags,
+ HRESULT *phr);
+
+ virtual VOID Open(
+ IStorage *pstg,
+ REFFMTID rfmtid,
+ DWORD grfFlags,
+ HRESULT *phr);
+ virtual VOID Open(
+ IStream *pstm,
+ REFFMTID rfmtid,
+ DWORD grfFlags,
+ BOOL fDelete,
+ HRESULT *phr);
+
+ // IUnknown
+ STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject);
+
+ STDMETHOD_(ULONG, AddRef)(void);
+
+ STDMETHOD_(ULONG, Release)(void);
+
+ // IPropertyStorage
+ STDMETHOD(ReadMultiple)(
+ ULONG cpspec,
+ const PROPSPEC rgpspec[],
+ PROPVARIANT rgpropvar[]);
+
+ STDMETHOD(WriteMultiple)(
+ ULONG cpspec,
+ const PROPSPEC rgpspec[],
+ const PROPVARIANT rgpropvar[],
+ PROPID propidNameFirst);
+
+ STDMETHOD(DeleteMultiple)(
+ ULONG cpspec,
+ const PROPSPEC rgpspec[]);
+
+ STDMETHOD(ReadPropertyNames)(
+ ULONG cpropid,
+ const PROPID rgpropid[],
+ LPOLESTR rglpwstrName[]);
+
+ STDMETHOD(WritePropertyNames)(
+ ULONG cpropid,
+ const PROPID rgpropid[],
+ const LPOLESTR rglpwstrName[]);
+
+ STDMETHOD(DeletePropertyNames)(
+ ULONG cpropid,
+ const PROPID rgpropid[]);
+
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+
+ STDMETHOD(Revert)();
+
+ STDMETHOD(Enum)(IEnumSTATPROPSTG ** ppenum);
+
+ STDMETHOD(SetTimes)(
+ FILETIME const * pctime,
+ FILETIME const * patime,
+ FILETIME const * pmtime);
+
+ STDMETHOD(SetClass)(REFCLSID clsid);
+
+ STDMETHOD(Stat)(STATPROPSETSTG * pstatpsstg);
+
+ // used by implementation helper classes
+ inline NTPROP GetNtPropSetHandle(void) { return _np; }
+
+
+ // ----------------
+ // Internal Methods
+ // ----------------
+
+protected:
+
+ VOID Initialize();
+ HRESULT InitializeOnCreateOrOpen(
+ DWORD grfFlags,
+ DWORD grfMode,
+ REFFMTID rfmtid,
+ BOOL fCreate );
+
+ VOID CleanupOpenedObjects(
+ PROPVARIANT avar[],
+ INDIRECTPROPERTY * pip,
+ ULONG cpspec,
+ ULONG iFailIndex);
+
+ HRESULT InitializePropertyStream(
+ USHORT Flags,
+ const GUID * pguid,
+ GUID const * pclsid);
+
+ HRESULT _WriteMultiple(
+ ULONG cpspec,
+ const PROPSPEC rgpspec[],
+ const PROPVARIANT rgpropvar[],
+ PROPID propidNameFirst);
+
+ HRESULT _WritePropertyNames(
+ ULONG cpropid,
+ const PROPID rgpropid[],
+ const LPOLESTR rglpwstrName[]);
+
+ HRESULT HandleLowMemory();
+
+ HRESULT _CreateDocumentSummary2Stream(
+ IStorage * pstg,
+ CPropSetName & psn,
+ DWORD grfMode,
+ BOOL * fCreated);
+
+ virtual HRESULT CreateMappedStream( );
+
+ virtual VOID Lock(DWORD dwTimeout);
+ virtual VOID Unlock();
+
+ inline HRESULT Validate();
+ inline HRESULT ValidateRef();
+
+ inline HRESULT ValidateRGPROPSPEC( ULONG cpspec, const PROPSPEC rgpropspec[] );
+ inline HRESULT ValidateInRGPROPVARIANT( ULONG cpspec, const PROPVARIANT rgpropvar[] );
+ inline HRESULT ValidateOutRGPROPVARIANT( ULONG cpspec, PROPVARIANT rgpropvar[] );
+ inline HRESULT ValidateRGPROPID( ULONG cpropid, const PROPID rgpropid[] );
+ inline HRESULT ValidateInRGLPOLESTR( ULONG cpropid, const LPOLESTR rglpwstrName[] );
+ inline HRESULT ValidateOutRGLPOLESTR( ULONG cpropid, LPOLESTR rglpwstrName[] );
+
+ inline BOOL IsNonSimple();
+ inline BOOL IsSimple();
+ inline HRESULT IsWriteable();
+ inline HRESULT IsReadable();
+ inline DWORD GetCreationMode();
+ inline HRESULT IsReverted();
+
+ // -------------
+ // Internal Data
+ // -------------
+
+protected:
+
+ ULONG _ulSig;
+ LONG _cRefs;
+ IStorage * _pstgPropSet;
+ IStream * _pstmPropSet;
+ NTPROP _np;
+ NTMAPPEDSTREAM _ms;
+
+#ifndef _MAC
+ CRITICAL_SECTION _CriticalSection;
+#endif
+
+ // We need to remember if the property set is the second section
+ // of the DocumentSummaryInformation property set used by Office. This
+ // is the only case where we support a multiple-section property set, and
+ // requires special handling in ::Revert().
+
+ BOOL _fUserDefinedProperties;
+
+ USHORT _usCodePage; // Ansi Codepage or Mac Script
+ // (disambiguate with _dwOSVersion)
+ ULONG _dwOSVersion; // Shows the OS Kind, major/minor version
+
+
+ DWORD _grfFlags; // PROPSETFLAG_NONSIMPLE and PROPSETFLAG_ANSI
+ DWORD _grfAccess; // grfMode & 3
+ DWORD _grfShare; // grfMode & 0xF0
+
+ // The following is a PMemoryAllocator for the Rtl property
+ // set routines. This instantiation was formerly a file-global
+ // in propstg.cxx. Howevewr, on the Mac, the object was not
+ // being instantiated.
+
+ CCoTaskAllocator _cCoTaskAllocator;
+
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::Validate
+//
+// Synopsis: S_OK if signature valid and not zombie.
+//
+// Notes: If the Revert calls fails due to low memory, then
+// the object becomes a zombie.
+//
+//--------------------------------------------------------------------
+
+inline HRESULT CPropertyStorage::Validate()
+{
+ if (_ulSig == PROPERTYSTORAGE_SIG)
+ return S_OK;
+ else
+ if (_ulSig == PROPERTYSTORAGE_SIGZOMBIE)
+ return STG_E_INSUFFICIENTMEMORY;
+ else
+ return STG_E_INVALIDHANDLE;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::ValidateRef
+//
+// Synopsis: S_OK if signature valid.
+//
+//--------------------------------------------------------------------
+
+inline HRESULT CPropertyStorage::ValidateRef()
+{
+ if (_ulSig == PROPERTYSTORAGE_SIG || _ulSig == PROPERTYSTORAGE_SIGZOMBIE)
+ return(S_OK);
+ else
+ return(STG_E_INVALIDHANDLE);
+
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::ValidateRGPROPSPEC
+//
+// Synopsis: S_OK if PROPSPEC[] is valid
+// E_INVALIDARG otherwise.
+//
+//--------------------------------------------------------------------
+
+inline HRESULT CPropertyStorage::ValidateRGPROPSPEC( ULONG cpspec,
+ const PROPSPEC rgpropspec[] )
+{
+ HRESULT hr = E_INVALIDARG;
+
+ // Validate the array itself.
+
+ VDATESIZEREADPTRIN_LABEL(rgpropspec, cpspec * sizeof(PROPSPEC), errRet, hr);
+
+ // Validate the elements of the array.
+
+ for( ; cpspec > 0; cpspec-- )
+ {
+ // Is this an LPWSTR?
+ if( PRSPEC_LPWSTR == rgpropspec[cpspec-1].ulKind )
+ {
+ // We better at least be able to read the first
+ // character.
+ VDATEREADPTRIN_LABEL(rgpropspec[cpspec-1].lpwstr, WCHAR, errRet, hr);
+ }
+
+ // Otherwise, this better be a PROPID.
+ else if( PRSPEC_PROPID != rgpropspec[cpspec-1].ulKind )
+ {
+ goto errRet;
+ }
+ }
+
+ hr = S_OK;
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ return( hr );
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::ValidateInRGPROPVARIANT
+//
+// Synopsis: S_OK if PROPVARIANT[] is valid for Read.
+// E_INVALIDARG otherwise.
+//
+//--------------------------------------------------------------------
+
+inline HRESULT CPropertyStorage::ValidateInRGPROPVARIANT( ULONG cpspec,
+ const PROPVARIANT rgpropvar[] )
+{
+ // We verify that we can read the whole PropVariant[], but
+ // we don't validate the content of those elements.
+
+ HRESULT hr;
+ VDATESIZEREADPTRIN_LABEL(rgpropvar, cpspec * sizeof(PROPVARIANT), errRet, hr);
+ hr = S_OK;
+
+errRet:
+
+ return( hr );
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::ValidateOutRGPROPVARIANT
+//
+// Synopsis: S_OK if PROPVARIANT[] is valid for Write.
+// E_INVALIDARG otherwise.
+//
+//--------------------------------------------------------------------
+
+inline HRESULT CPropertyStorage::ValidateOutRGPROPVARIANT( ULONG cpspec,
+ PROPVARIANT rgpropvar[] )
+{
+ // We verify that we can write the whole PropVariant[], but
+ // we don't validate the content of those elements.
+
+ HRESULT hr;
+ VDATESIZEPTROUT_LABEL(rgpropvar, cpspec * sizeof(PROPVARIANT), errRet, hr);
+ hr = S_OK;
+
+errRet:
+
+ return( hr );
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::ValidateRGPROPID
+//
+// Synopsis: S_OK if RGPROPID[] is valid for Read.
+// E_INVALIDARG otherwise.
+//
+//--------------------------------------------------------------------
+
+inline HRESULT CPropertyStorage::ValidateRGPROPID( ULONG cpropid,
+ const PROPID rgpropid[] )
+{
+ HRESULT hr;
+ VDATESIZEREADPTRIN_LABEL( rgpropid, cpropid * sizeof(PROPID), errRet, hr );
+ hr = S_OK;
+
+errRet:
+
+ return( hr );
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::ValidateOutRGLPOLESTR.
+//
+// Synopsis: S_OK if LPOLESTR[] is valid for Write.
+// E_INVALIDARG otherwise.
+//
+//--------------------------------------------------------------------
+
+inline HRESULT CPropertyStorage::ValidateOutRGLPOLESTR( ULONG cpropid,
+ LPOLESTR rglpwstrName[] )
+{
+ HRESULT hr;
+ VDATESIZEPTROUT_LABEL( rglpwstrName, cpropid * sizeof(LPOLESTR), errRet, hr );
+ hr = S_OK;
+
+errRet:
+
+ return( hr );
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::ValidateInRGLPOLESTR
+//
+// Synopsis: S_OK if LPOLESTR[] is valid for Read.
+// E_INVALIDARG otherwise.
+//
+//--------------------------------------------------------------------
+
+inline HRESULT CPropertyStorage::ValidateInRGLPOLESTR( ULONG cpropid,
+ const LPOLESTR rglpwstrName[] )
+{
+ // Validate that we can read the entire vector.
+
+ HRESULT hr;
+ VDATESIZEREADPTRIN_LABEL( rglpwstrName, cpropid * sizeof(LPOLESTR), errRet, hr );
+
+ // Validate that we can at least read the first character of
+ // each of the strings.
+
+ for( ; cpropid > 0; cpropid-- )
+ {
+ VDATEREADPTRIN_LABEL( rglpwstrName[cpropid-1], WCHAR, errRet, hr );
+ }
+
+ hr = S_OK;
+
+errRet:
+
+ return( hr );
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::IsNonSimple
+//
+// Synopsis: true if non-simple
+//
+//--------------------------------------------------------------------
+
+inline BOOL CPropertyStorage::IsNonSimple()
+{
+ return (_grfFlags & PROPSETFLAG_NONSIMPLE) != 0;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::IsSimple
+//
+// Synopsis: true if simple
+//
+//--------------------------------------------------------------------
+
+inline BOOL CPropertyStorage::IsSimple()
+{
+ return !IsNonSimple();
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::IsWriteable
+//
+// Synopsis: S_OK if writeable otherwise STG_E_ACCESSDENIED
+//
+//--------------------------------------------------------------------
+
+inline HRESULT CPropertyStorage::IsWriteable()
+{
+ return (_grfAccess == STGM_WRITE || _grfAccess == STGM_READWRITE) ?
+ S_OK : STG_E_ACCESSDENIED;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::IsReadable
+//
+// Synopsis: S_OK if readable otherwise STG_E_ACCESSDENIED
+//
+//--------------------------------------------------------------------
+
+inline HRESULT CPropertyStorage::IsReadable()
+{
+ return (_grfAccess == STGM_READ || _grfAccess == STGM_READWRITE) ?
+ S_OK : STG_E_ACCESSDENIED;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::GetCreationMode
+//
+// Synopsis: Get grfMode for creating streams/storages for VT_STREAM etc
+//
+//--------------------------------------------------------------------
+
+inline DWORD CPropertyStorage::GetCreationMode()
+{
+#ifndef _CAIRO_
+ const BOOL _fNative = FALSE;
+#endif
+ return(STGM_DIRECT | STGM_CREATE |
+ (_fNative ? _grfShare : STGM_SHARE_EXCLUSIVE) | _grfAccess);
+
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertyStorage::IsReverted
+//
+// Synopsis: S_OK if not reverted, STG_E_REVERTED otherwise.
+//
+//--------------------------------------------------------------------
+
+inline HRESULT CPropertyStorage::IsReverted()
+{
+ IUnknown *punk;
+ HRESULT hr = (IsNonSimple() ? (IUnknown*)_pstgPropSet : (IUnknown*)_pstmPropSet) ->
+ QueryInterface(IID_IUnknown, (void**)&punk);
+
+ // Normalize the result to either 'reverted' or 'OK'.
+ // Note: On older Mac implementations, memory-based streams will
+ // return E_NOINTERFACE here, due to a bug in the QueryInterface
+ // implementation.
+
+ if( STG_E_REVERTED != hr )
+ {
+ hr = S_OK;
+ }
+
+ if( punk )
+ punk->Release();
+
+ return(hr);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDocFilePropertyStorage
+//
+// Purpose: Implements a CPropertyStorage customized for
+// use with IStorages & IStreams which are known
+// to be DocFile (the OLE32 Compound File implementation).
+//
+// This derivation of CPropertyStorage takes advantage
+// of the DocFile tree mutex, so that locking this
+// object also locks the associated IStorage/IStream.
+//
+//--------------------------------------------------------------------------
+
+class CDocFilePropertyStorage : public CPropertyStorage
+{
+
+public:
+
+ CDocFilePropertyStorage() {};
+ ~CDocFilePropertyStorage()
+ {
+ // Prevent ~CPropertyStorage from attempting to delete
+ // the mapped stream, which in this case is actually
+ // a CExposedStream.
+
+ _ms = NULL;
+ }
+
+ // ----------------
+ // Public Overrides
+ // ----------------
+
+ // These methods are overridden to ensure that they are
+ // not used on a DocFile.
+
+public:
+
+ VOID Create(
+ IStream *stm,
+ REFFMTID rfmtid,
+ const CLSID *pclsid,
+ DWORD grfFlags,
+ HRESULT *phr)
+ {
+ *phr = ERROR_CALL_NOT_IMPLEMENTED;
+ return;
+ }
+
+ VOID Create(
+ IStorage *pstg,
+ REFFMTID rfmtid,
+ const CLSID *pclsid,
+ DWORD grfFlags,
+ HRESULT *phr)
+ {
+ *phr = ERROR_CALL_NOT_IMPLEMENTED;
+ return;
+ }
+
+ VOID Open(
+ IStorage *pstg,
+ REFFMTID rfmtid,
+ DWORD grfFlags,
+ HRESULT *phr)
+ {
+ *phr = ERROR_CALL_NOT_IMPLEMENTED;
+ return;
+ }
+ VOID Open(
+ IStream *pstm,
+ REFFMTID rfmtid,
+ DWORD grfFlags,
+ BOOL fDelete,
+ HRESULT *phr)
+ {
+ *phr = ERROR_CALL_NOT_IMPLEMENTED;
+ return;
+ }
+
+ // ---------------
+ // Exposed Methods
+ // ---------------
+
+public:
+
+ VOID Create(
+ IPrivateStorage * pprivstg,
+ REFFMTID rfmtid,
+ const CLSID * pclsid,
+ DWORD grfFlags,
+ DWORD grfMode,
+ HRESULT * phr);
+
+ VOID Open(
+ IPrivateStorage * pprivstg,
+ REFFMTID rfmtid,
+ DWORD grfMode,
+ BOOL fDelete,
+ HRESULT * phr);
+
+
+ // ------------------
+ // Internal Overrides
+ // ------------------
+
+protected:
+
+ HRESULT CreateMappedStream( );
+ VOID Lock( DWORD dwTimeout );
+ VOID Unlock();
+
+};
+
+//+-------------------------------------------------------------------------
+//
+// Class: CStatArray
+//
+// Purpose: Class to allow sharing of enumeration STATPROPSTG state.
+//
+// Interface: CStatArray -- Enumerate entire NTPROP np.
+// NextAt -- Perform an OLE-type Next operation starting at
+// specified offset.
+// AddRef -- for sharing of this by CEnumSTATPROPSTG
+// Release -- ditto
+//
+// Notes: Each IEnumSTATPROPSTG instance has a reference to a
+// CStatArray. When IEnumSTATPROPSTG::Clone is called, a
+// new reference to the extant CStatArray is used: no copying.
+//
+// The CEnumSTATPROPSTG has a cursor into the CStatArray.
+//
+//--------------------------------------------------------------------------
+
+class CStatArray
+{
+public:
+ CStatArray(NTPROP np, HRESULT *phr);
+
+ NTSTATUS NextAt(ULONG ipropNext, STATPROPSTG *pspsDest, ULONG *pceltFetched);
+ inline VOID AddRef();
+ inline VOID Release();
+
+private:
+ ~CStatArray();
+
+ LONG _cRefs;
+
+ STATPROPSTG * _psps;
+ ULONG _cpropActual;
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: CStatArray::AddRef
+//
+// Synopsis: Increment ref count.
+//
+//--------------------------------------------------------------------
+
+inline VOID CStatArray::AddRef()
+{
+ InterlockedIncrement(&_cRefs);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStatArray::AddRef
+//
+// Synopsis: Decrement ref count and delete object if refs == 0.
+//
+//--------------------------------------------------------------------
+
+inline VOID CStatArray::Release()
+{
+ if (0 == InterlockedDecrement(&_cRefs))
+ delete this;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CEnumSTATPROPSTG
+//
+// Purpose: Implement IEnumSTATPROPSTG
+//
+// Notes: Just holds a reference to a CStatArray that contains
+// a static copy of the enumeration when the original
+// Enum call was made. This object contains the cursor
+// into the CStatArray.
+//
+//--------------------------------------------------------------------------
+
+NTSTATUS CopySTATPROPSTG(ULONG celt,
+ STATPROPSTG * pspsDest,
+ const STATPROPSTG * pspsSrc);
+
+VOID CleanupSTATPROPSTG(ULONG celt, STATPROPSTG * psps);
+
+class CEnumSTATPROPSTG : public IEnumSTATPROPSTG
+{
+public:
+ CEnumSTATPROPSTG(NTPROP np, HRESULT *phr);
+ CEnumSTATPROPSTG(const CEnumSTATPROPSTG &other, HRESULT *phr);
+
+ ~CEnumSTATPROPSTG();
+
+ STDMETHOD(QueryInterface)( REFIID riid, void **ppvObject);
+
+ STDMETHOD_(ULONG, AddRef)(void);
+
+ STDMETHOD_(ULONG, Release)(void);
+
+ STDMETHOD(Next)(ULONG celt,
+ STATPROPSTG * rgelt,
+ ULONG * pceltFetched);
+
+ // We don't need RemoteNext.
+
+ STDMETHOD(Skip)(ULONG celt);
+
+ STDMETHOD(Reset)();
+
+ STDMETHOD(Clone)(IEnumSTATPROPSTG ** ppenum);
+
+private:
+ HRESULT Validate();
+
+
+ ULONG _ulSig;
+ LONG _cRefs;
+
+ CStatArray * _psa;
+ ULONG _ipropNext;
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSTG::Validate
+//
+// Synopsis: S_OK if signature is valid, otherwise error
+//
+//--------------------------------------------------------------------
+
+inline HRESULT CEnumSTATPROPSTG::Validate()
+{
+ return _ulSig == ENUMSTATPROPSTG_SIG ? S_OK : STG_E_INVALIDHANDLE;
+}
+
diff --git a/private/ole32/stg/props/propstm.cxx b/private/ole32/stg/props/propstm.cxx
new file mode 100644
index 000000000..2b2f3b260
--- /dev/null
+++ b/private/ole32/stg/props/propstm.cxx
@@ -0,0 +1,7971 @@
+
+//+--------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993
+//
+// File: propstm.cxx
+//
+// Contents: property set value extraction code
+//
+// History: 15-Jul-94 brianb created
+// 12-Aug-94 SethuR Included Assertions for # of sections
+// split PropertySet class into
+// CPropertySetStream & CPropertySetStorage
+// Included Update methods on the property
+// stream.
+// 22-Feb-96 MikeHill DWORD-align the dictionary entries,
+// & use char-counts for dict entries.
+// 29-Feb-96 MikeHill Moved _DictionaryEntryLength and _NextDictionaryEntry
+// inlines here from propstm.hxx.
+// 09-May-96 MikeHill - Keep the dictionary in the UserDef propset
+// immediately after the last entry in the PID/Offset
+// array (for Office95 compatibility).
+// - Create an empty dictionary in the UD propset
+// when it is created. If we wait till later,
+// we can't make the dictionary the first property,
+// which is required by Office95.
+// - Provide compatibility with Publisher95 (which doesn't
+// DWORD-align the section/stream size).
+// - Provide compatibility with PowerPoint 4.0 (which
+// over-pads some properties, and under-pads others).
+// - Don't try to unpack the DocParts and HeadingPair
+// DocSumInfo properties in Ansi property sets.
+// 22-May-96 MikeHill - Return the OSVersion on an Open.
+// - Use the PropSet's code page, not the system's.
+// 11-Jun-96 MikeHill - Initialize all members in the constructor.
+// 25-Jul-96 MikeHill - Removed usage of Win32 SEH.
+// - BSTRs & prop names: WCHAR => OLECHAR.
+// - Added big-endian support.
+// - Determine the OSVer at run-time.
+// - Fix for Excel 5.0a compatibility.
+// 26-Nov-96 MikeHill Handle invalid oSection values.
+//
+// Notes:
+//
+// The OLE 2.0 Appendix B property set specifies multiple sections in the
+// property stream specification. Multiple sections were intended to allow
+// the schema associated with the property set to evolve over a period of time,
+// but there is no reason that new PROPIDs cannot serve the same purpose. The
+// current implementation of the property stream is limited to one section,
+// except for the Office DocumentSummaryInformation property set's specific use
+// of a second section. Other property sets with multiple sections can only be
+// accessed in read-only mode, and then only for the first property section.
+//
+// The current implementation of property set stream is built around a class
+// called CPropertySetStream. The various details of the OLE property spec is
+// confined to this class. Since the property set streams need to be parsed
+// in the kernel mode (OFS driver) as well as the user mode, this class
+// encapsulates a stream implementation (CMappedStream). This is different
+// from other stream implementations in that the fundamental mechanism provided
+// for acessing the contents is Map/Unmap rather than Read/Write. There are
+// two user mode implementations of this CMappedStream interface, one for
+// docfile streams, and another for native streams. There is one
+// implementation in kernel mode for the OFS driver. For more details,
+// refer to propstm.hxx.
+//---------------------------------------------------------------------------
+
+#include <pch.cxx>
+
+#include <olechar.h>
+
+#if DBGPROP
+#include <stdio.h> // for sprintf/strcpy
+#endif
+#include "propvar.h"
+
+
+#define Dbg DEBTRACE_PROPERTY
+
+#define szX "x" // allows radix change for offsets & sizes
+//#define szX "d" // allows radix change for offsets & sizes
+
+#ifndef newk
+#define newk(Tag, pCounter) new
+#endif
+
+#ifndef IsDwordAligned
+#define IsDwordAligned(p) (((ULONG) (p) & (sizeof(ULONG) - 1)) == 0)
+#endif
+
+#ifndef DwordRemain
+#define DwordRemain(cb) \
+ ((sizeof(ULONG) - ((cb) % sizeof(ULONG))) % sizeof(ULONG))
+#endif
+
+
+// Information for the the OS Version field of the
+// property set header.
+
+#if !defined(IPROPERTY_DLL)
+# define PROPSETVER_CURRENT MAKEPSVER(OSKIND_WIN32, WINVER >> 8, WINVER & 0xff)
+#endif
+
+#define PROPSETVER_WIN310 MAKEPSVER(OSKIND_WINDOWS, 3, 10)
+#define PROPSETVER_WIN333 MAKEPSVER(OSKIND_WIN32, 3, 0x33)
+
+
+
+extern GUID guidSummary;
+extern GUID guidDocumentSummary;
+extern GUID guidDocumentSummarySection2;
+
+#define CP_DEFAULT_NONUNICODE 1252 // ANSI Latin1 (US, Western Europe)
+#ifdef KERNEL
+#define CP_CREATEDEFAULT(state) \
+ ((state & CPSS_PROPHEADER)? CP_DEFAULT_NONUNICODE : CP_WINUNICODE)
+#else
+extern "C" UNICODECALLOUTS UnicodeCallouts;
+#define CP_CREATEDEFAULT(state) (*UnicodeCallouts.pfnGetACP)()
+#endif
+
+#if DBGPROP
+#define StatusCorruption(pstatus, szReason) \
+ _StatusCorruption(szReason " ", pstatus)
+#else
+#define StatusCorruption(pstatus, szReason) \
+ _StatusCorruption(pstatus)
+#endif
+
+
+#ifndef KERNEL
+VOID RtlpConvertToUnicode(
+ IN CHAR const *pch,
+ IN ULONG cb,
+ IN USHORT CodePage,
+ OUT WCHAR **ppwc,
+ OUT ULONG *pcb,
+ OUT NTSTATUS *pstatus);
+VOID RtlpConvertToMultiByte(
+ IN WCHAR const *pwc,
+ IN ULONG cb,
+ IN USHORT CodePage,
+ OUT CHAR **ppch,
+ OUT ULONG *pcb,
+ OUT NTSTATUS *pstatus);
+#endif
+
+
+
+//
+// Re-direct RtlEqual[Unicode]String routines
+//
+// These macros redirect two NTDLL routines which don't exist in
+// the IProperty DLL. They are redirected to CRT calls.
+//
+// Note: These redirections assume that the Length and
+// MaximumLength fields, on both String structures, are the
+// same (e.g. s1.len == s1.maxlen == s2.len == s2.maxlen).
+//
+
+#ifdef IPROPERTY_DLL
+
+ #define RtlEqualString(String1,String2,fCaseInSensitive) \
+ fCaseInSensitive \
+ ? ( !_strnicmp( (String1)->Buffer, \
+ (String2)->Buffer, \
+ (String1)->MaximumLength) ) \
+ : ( !strncmp( (String1)->Buffer, \
+ (String2)->Buffer, \
+ (String1)->MaximumLength) )
+
+ #define RtlEqualUnicodeString(String1,String2,fCaseInSensitive) \
+ fCaseInSensitive \
+ ? ( !_wcsnicmp( (String1)->Buffer, \
+ (String2)->Buffer, \
+ (String1)->MaximumLength / sizeof(WCHAR) )) \
+ : ( !wcsncmp( (String1)->Buffer, \
+ (String2)->Buffer, \
+ (String1)->MaximumLength / sizeof(WCHAR) ))
+
+#endif // #ifdef IPROPERTY_DLL
+
+
+#if DBGPROP
+
+#define CB_VALUEDISPLAY 8 // Number of bytes to display
+#define CB_VALUESTRING (CB_VALUEDISPLAY * 3 + 3) // "xx xx xx xx...\0"
+
+char *
+ValueToString(SERIALIZEDPROPERTYVALUE const *pprop, ULONG cbprop, char buf[])
+{
+ char *p = buf;
+ BYTE const *pb = pprop->rgb;
+ BOOLEAN fOverflow = FALSE;
+ static char szDots[] = "...";
+
+ if (cbprop >= FIELD_OFFSET(SERIALIZEDPROPERTYVALUE, rgb))
+ {
+ cbprop -= FIELD_OFFSET(SERIALIZEDPROPERTYVALUE, rgb);
+ if (cbprop > CB_VALUEDISPLAY)
+ {
+ cbprop = CB_VALUEDISPLAY;
+ fOverflow = TRUE;
+ }
+ while (cbprop-- > 0)
+ {
+ if (p != buf)
+ {
+ *p++ = ' ';
+ }
+ p += PropSprintfA( p, "%02.2x", *pb++ );
+ }
+ }
+ *p = '\0';
+ PROPASSERT(p - buf + sizeof(szDots) <= CB_VALUESTRING);
+ if (fOverflow)
+ {
+ strcpy(p, szDots);
+ }
+ return(buf);
+}
+
+
+#define CB_VARIANT_TO_STRING 35
+
+char *
+VariantToString(PROPVARIANT const &var, char buf[], ULONG cbprop)
+{
+ char *p = buf;
+
+ PROPASSERT( cbprop >= CB_VARIANT_TO_STRING );
+
+
+ // Add the VT to the output buffer.
+
+ p += PropSprintfA( p, "vt=%04.4x", var.vt );
+ p += PropSprintfA( p, ", val=(%08.8x, %08.8x)", var.uhVal.LowPart, var.uhVal.HighPart );
+
+ *p = '\0';
+ PROPASSERT( (p - buf) == CB_VARIANT_TO_STRING);
+ return(buf);
+}
+
+#endif
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_DictionaryEntryLength
+//
+// Synopsis: Calculate the length of an entry in the
+// dictionary. This is non-trivial because
+// it is codepage-dependent.
+//
+// Arguments: [pent] -- pointer to a dictionary entry.
+//
+// Returns: The entry's length.
+//+--------------------------------------------------------------------------
+
+
+inline ULONG
+CPropertySetStream::_DictionaryEntryLength(
+ IN ENTRY UNALIGNED const * pent
+ ) const
+{
+ // If this is a Unicode property set, it should be DWORD-aligned.
+ PROPASSERT( _CodePage != CP_WINUNICODE
+ ||
+ IsDwordAligned( (ULONG) pent ));
+
+ // The size consists of the length of the
+ // PROPID and character count ...
+
+ ULONG ulSize = CB_ENTRY;
+
+ // Plus the length of the string ...
+
+ ulSize += PropByteSwap( pent->cch )
+ *
+ ( _CodePage == CP_WINUNICODE ? sizeof( WCHAR )
+ : sizeof( CHAR )
+ );
+
+ // Plus, possibly, padding to make the entry DWORD-aligned
+ // (for Unicode property sets).
+
+ if( _CodePage == CP_WINUNICODE )
+ {
+ ulSize = DwordAlign( ulSize );
+ }
+
+ return( ulSize );
+
+}
+
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_NextDictionaryEntry
+//
+// Synopsis: Given a pointer to an entry in the dictionary,
+// create a pointer to the next entry.
+//
+// Arguments: [pent] -- pointer to a dictionary entry.
+//
+// Returns: Pointer to the next entry. If the input
+// points to the last entry in the dictionary,
+// then return a pointer to just beyond the
+// end of the dictionary.
+//+--------------------------------------------------------------------------
+
+
+inline ENTRY UNALIGNED *
+CPropertySetStream::_NextDictionaryEntry(
+ IN ENTRY UNALIGNED const * pent
+ ) const
+{
+
+ return (ENTRY UNALIGNED *)
+ Add2Ptr( pent, _DictionaryEntryLength( pent ));
+
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_SignalCorruption
+//
+// Synopsis: possibly PROPASSERT and return data corrupt error
+//
+// Arguments: [szReason] -- string explanation (DBGPROP only)
+// [pstatus] -- NTSTATUS code.
+//
+// Returns: None
+//+--------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::_StatusCorruption(
+#if DBGPROP
+ char *szReason,
+#endif
+ OUT NTSTATUS *pstatus
+ ) const
+{
+#if DBGPROP
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "_StatusCorruption(%s, psstm=%lx, mapstm=%lx, %s, flags=%x)\n",
+ szReason,
+ this,
+ KERNELSELECT(&_mstm, _pmstm),
+ KERNELSELECT("Kernel", _MSTM(IsNtMappedStream)()? "Nt" : "DocFile"),
+ _Flags));
+
+#ifdef KERNEL
+ if ((_Flags & CREATEPROP_MODEMASK) != CREATEPROP_READ)
+#endif
+ {
+ PROPASSERTMSG(szReason, FALSE);
+ DebugTrace(0, DEBTRACE_WARN, (
+ "_StatusCorruption(%s, psstm=%lx, mapstm=%lx, %s, flags=%x)\n",
+ szReason,
+ this,
+ KERNELSELECT(&_mstm, _pmstm),
+ KERNELSELECT("Kernel", _MSTM(IsNtMappedStream)()? "Nt" : "DocFile"),
+ _Flags));
+ if (DebugLevel & DEBTRACE_WARN)
+ {
+ PROPASSERTMSG(szReason, FALSE);
+ }
+ }
+#endif
+
+ *pstatus = STATUS_INTERNAL_DB_CORRUPTION;
+ return;
+}
+
+
+//+--------------------------------------------------------------------------
+// Function: _PropMoveMemory
+//
+// Synopsis: call DebugTrace and RtlMoveMemory
+//
+// Arguments: [pszReason] -- string explanation (Debug only)
+// [pvSection] -- base of section (Debug only)
+// [pvDst] -- destination
+// [pvSrc] -- source
+// [cbMove] -- byte count to move
+//
+// Returns: None
+//+--------------------------------------------------------------------------
+
+#if DBGPROP
+#define PropMoveMemory(pszReason, pvSection, pvDst, pvSrc, cbMove) \
+ _PropMoveMemory(pszReason, pvSection, pvDst, pvSrc, cbMove)
+#else
+#define PropMoveMemory(pszReason, pvSection, pvDst, pvSrc, cbMove) \
+ _PropMoveMemory(pvDst, pvSrc, cbMove)
+#endif
+
+inline VOID
+_PropMoveMemory(
+#if DBGPROP
+ char *pszReason,
+ VOID *pvSection,
+#endif
+ VOID *pvDst,
+ VOID const *pvSrc,
+ ULONG cbMove)
+{
+ DebugTrace(0, Dbg, (
+ "%s: Moving Dst=%lx(%l" szX ") Src=%lx(%l" szX ") Size=%l" szX "\n",
+ pszReason,
+ pvDst,
+ (BYTE *) pvDst - (BYTE *) pvSection,
+ pvSrc,
+ (BYTE *) pvSrc - (BYTE *) pvSection,
+ cbMove));
+ RtlMoveMemory(pvDst, pvSrc, cbMove);
+}
+
+
+inline BOOLEAN
+IsReadOnlyPropertySet(BYTE flags, BYTE state)
+{
+ return(
+ (flags & CREATEPROP_MODEMASK) == CREATEPROP_READ ||
+ (state & CPSS_USERDEFINEDDELETED) ||
+ (state & (CPSS_MULTIPLESECTIONS | CPSS_DOCUMENTSUMMARYINFO)) ==
+ CPSS_MULTIPLESECTIONS);
+}
+
+
+inline BOOLEAN
+IsReadOnlyPropid(PROPID pid)
+{
+ return(
+ pid == PID_DICTIONARY ||
+ pid == PID_CODEPAGE ||
+ pid == PID_LOCALE ||
+ pid == PID_MODIFY_TIME ||
+ pid == PID_SECURITY);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CStreamChunkList::CStreamChunkList
+//
+// Synopsis: constructor
+//
+// Arguments: [cChunks] -- count of chunks that will be needed
+//
+// Returns: None
+//+--------------------------------------------------------------------------
+
+CStreamChunkList::CStreamChunkList(
+ ULONG cChunks,
+ CStreamChunk *ascnk) :
+ _cMaxChunks(cChunks),
+ _cChunks(0),
+ _ascnk(ascnk),
+ _fDelete(FALSE)
+{
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CStreamChunkList::Delete
+//
+// Synopsis: destructor
+//
+// Arguments: None
+//
+// Returns: None
+//+--------------------------------------------------------------------------
+
+inline
+VOID
+CStreamChunkList::Delete(VOID)
+{
+ if (_fDelete)
+ {
+ delete [] _ascnk;
+ }
+#if DBGPROP
+ _cMaxChunks = _cChunks = 0;
+ _ascnk = NULL;
+ _fDelete = FALSE;
+#endif
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CStreamChunkList::GetChunk
+//
+// Synopsis: retrieves a chunk given the index
+//
+// Arguments: [i] -- index of the chunk to retrieve
+//
+// Returns: specified chunk pointer
+//+--------------------------------------------------------------------------
+
+inline
+CStreamChunk const *
+CStreamChunkList::GetChunk(ULONG i) const
+{
+ PROPASSERT(i < _cChunks);
+ PROPASSERT(i < _cMaxChunks);
+ PROPASSERT(_ascnk != NULL);
+ return(&_ascnk[i]);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CStreamChunkList::Count
+//
+// Synopsis: returns the count of chunks
+//
+// Arguments: None
+//
+// Returns: the number of chunks.
+//+--------------------------------------------------------------------------
+
+inline ULONG
+CStreamChunkList::Count(VOID) const
+{
+ return(_cChunks);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CStreamChunkList::GetFreeChunk
+//
+// Synopsis: gets a unused chunk descriptor
+//
+// Arguments: [pstatus] -- NTSTATUS code
+//
+// Returns: a ptr to a stream chunk descriptor.
+// This will be NULL if there was an
+// error.
+//+--------------------------------------------------------------------------
+
+CStreamChunk *
+CStreamChunkList::GetFreeChunk(OUT NTSTATUS *pstatus)
+{
+ CStreamChunk *pscnk = NULL;
+
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(_cChunks < _cMaxChunks);
+ if (_ascnk == NULL)
+ {
+ PROPASSERT(_cChunks == 0);
+ _ascnk = newk(mtPropSetStream, NULL) CStreamChunk[_cMaxChunks];
+ if (_ascnk == NULL)
+ {
+ StatusNoMemory(pstatus, "GetFreeChunk");
+ goto Exit;
+ }
+ _fDelete = TRUE;
+ }
+
+ pscnk = &_ascnk[_cChunks++];
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return( pscnk );
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CStreamChunkList::AssertCbChangeTotal
+//
+// Synopsis: make sure the computed cbChangeTotal is correct for the chunk
+//
+// Arguments: None
+//
+// Returns: Nothing
+//+--------------------------------------------------------------------------
+
+#if DBGPROP
+VOID
+CStreamChunkList::AssertCbChangeTotal(
+ CStreamChunk const *pscnk,
+ ULONG cbChangeTotal) const
+{
+ ULONG cb = 0;
+ ULONG i;
+
+ for (i = 0; i < Count(); i++)
+ {
+ CStreamChunk const *pscnkT = GetChunk(i);
+
+ cb += pscnkT->cbChange;
+ if (pscnk == pscnkT)
+ {
+ PROPASSERT(cb == cbChangeTotal);
+ return;
+ }
+ }
+ PROPASSERT(i < Count());
+}
+#endif
+
+
+//+--------------------------------------------------------------------------
+// Member: fnChunkCompare
+//
+// Synopsis: qsort helper to compare chunks in the chunk list.
+//
+// Arguments: [pscnk1] -- pointer to chunk1
+// [pscnk2] -- pointer to chunk2
+//
+// Returns: difference
+//+--------------------------------------------------------------------------
+
+INT _CRTAPI1
+fnChunkCompare(VOID const *pscnk1, VOID const *pscnk2)
+{
+ return(((CStreamChunk const *) pscnk1)->oOld -
+ ((CStreamChunk const *) pscnk2)->oOld);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CStreamChunkList::SortByStartAddress
+//
+// Synopsis: sort all the chunks that are being modified in a stream in the
+// ascending order.
+//
+// Arguments: None
+//
+// Returns: None
+//+--------------------------------------------------------------------------
+
+VOID
+CStreamChunkList::SortByStartAddress(VOID)
+{
+ DebugTrace(0, Dbg, ("Sorting %l" szX " Chunks @%lx\n", _cChunks, _ascnk));
+
+ qsort(_ascnk, _cChunks, sizeof(_ascnk[0]), fnChunkCompare);
+
+#if DBGPROP
+ LONG cbChangeTotal;
+ ULONG i;
+
+ cbChangeTotal = 0;
+ for (i = 0; i < _cChunks; i++)
+ {
+ cbChangeTotal += _ascnk[i].cbChange;
+
+ DebugTrace(0, Dbg, (
+ "Chunk[%l" szX "] oOld=%l" szX " cbChange=%s%l" szX
+ " cbChangeTotal=%s%l" szX "\n",
+ i,
+ _ascnk[i].oOld,
+ _ascnk[i].cbChange < 0? "-" : "",
+ _ascnk[i].cbChange < 0? -_ascnk[i].cbChange : _ascnk[i].cbChange,
+ cbChangeTotal < 0? "-" : "",
+ cbChangeTotal < 0? -cbChangeTotal : cbChangeTotal));
+ }
+#endif
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_GetFormatidOffset
+//
+// Synopsis: Get a pointer to the (first) section header
+//
+// Arguments: None
+//
+// Returns: pointer to section header
+//+--------------------------------------------------------------------------
+
+inline FORMATIDOFFSET *
+CPropertySetStream::_GetFormatidOffset(ULONG iSection) const
+{
+ return(&((FORMATIDOFFSET *) Add2Ptr(_pph, sizeof(*_pph)))[iSection]);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_GetSectionHeader
+//
+// Synopsis: Get a pointer to the (first) section header
+//
+// Arguments: None
+//
+// Returns: pointer to section header
+//+--------------------------------------------------------------------------
+
+inline PROPERTYSECTIONHEADER *
+CPropertySetStream::_GetSectionHeader(VOID) const
+{
+ return((PROPERTYSECTIONHEADER *) Add2Ptr(_pph, _oSection));
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_GetSectionHeader
+//
+// Synopsis: Get a pointer to the specified section header
+//
+// Arguments: [iSection] -- section number
+// [pstatus] -- Pointer to NTSTATUS code.
+//
+// Returns: pointer to specified section header
+//+--------------------------------------------------------------------------
+
+PROPERTYSECTIONHEADER *
+CPropertySetStream::_GetSectionHeader(ULONG iSection, OUT NTSTATUS *pstatus)
+{
+ *pstatus = STATUS_SUCCESS;
+ PROPERTYSECTIONHEADER *psh = NULL;
+
+ ULONG oSection = 0; // Assume no header
+ ULONG cbstm = _MSTM(GetSize)(pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // Don't assume *any* class variables (except _pph) are loaded yet!
+
+ PROPASSERT(iSection < _pph->reserved );
+
+ // Get the section offset, after verifying that we can read all
+ // of the FmtID/Offset table.
+
+ if (cbstm >= CB_PROPERTYSETHEADER + (iSection + 1) * CB_FORMATIDOFFSET)
+ oSection = _GetFormatidOffset(iSection)->dwOffset;
+ else
+ StatusCorruption (pstatus, "GetSectionHeader(i): stream size too short to read section offset");
+
+ // Create a pointer to the section header, after verifying that we can
+ // read all of the section header. We don't verify that we can actually
+ // read the whole section (using cbSection), the caller must be responsible
+ // for this.
+
+ // We have to check oSection first, then oSection+cb_psh, because oSection
+ // could be a negative number (such as 0xffffffff), so adding it to cb_psh
+ // could make it look valid.
+
+ if (cbstm >= oSection
+ &&
+ cbstm >= oSection + CB_PROPERTYSECTIONHEADER)
+ {
+ psh = (PROPERTYSECTIONHEADER *) Add2Ptr(_pph, oSection);
+ }
+ else
+ StatusCorruption (pstatus, "GetSectionHeader(i): stream size too short to read section header");
+
+ // Finally, ensure that the section is 32 bit aligned. We handle several
+ // compatibility problems in the _Fix* routines, but not a misaligned
+ // section header.
+
+ if( !IsDwordAligned( psh ))
+ StatusCorruption( pstatus, "GetSectionHeader(i): section header is misaligned" );
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return(psh);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_SearchForCodePage, private
+//
+// Synopsis: Searches a section of a property set for the code page.
+//
+// This routine searches for the code page by iterating
+// through the PID/Offset array in search of
+// PID_CODEPAGE. The difference between calling
+// this routine, and calling GetValue(PID_CODEPAGE),
+// is that this routine does not assume that the
+// property set is formatted correctly; it only assumes
+// that the PID/Offset array is correct.
+//
+// Note that this routine is like a specialized _LoadProperty(),
+// the important difference is that this routine must use
+// unaligned pointers, since it cannot assume that the
+// property set is aligned properly.
+//
+// Pre-Conditions:
+// The PID/Offset array is correct.
+// &&
+// _oSection & _cSection are set correctly.
+//
+// Post-Conditions:
+// If PID_CODEPAGE exists, it is put into _CodePage.
+// If it doesn't exist, _CodePage is left unchanged.
+//
+// Arguments: [pstatus] -- Pointer to NTSTATUS code.
+//
+// Notes: We do *not* assume that the property set's
+// cbSection field is valid (this was added to handle a
+// special-case compatibility problem).
+//
+// Returns: None.
+//+--------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::_SearchForCodePage( OUT NTSTATUS *pstatus )
+{
+
+ PROPERTYSECTIONHEADER UNALIGNED *psh;
+ PROPERTYIDOFFSET UNALIGNED *ppo;
+ PROPERTYIDOFFSET UNALIGNED *ppoMax;
+
+ ULONG cbstm;
+
+ *pstatus = STATUS_SUCCESS;
+
+ // Verify the pre-conditions.
+
+ PROPASSERT( _oSection != 0 );
+ PROPASSERT( _cSection != 0 );
+
+ // It's invalid to call any function on a deleted
+ // DocSumInfo user-defined (section section) section.
+
+ if (_State & CPSS_USERDEFINEDDELETED)
+ {
+ StatusAccessDenied(pstatus, "GetValue: deleted");
+ goto Exit;
+ }
+
+ // Get the section's header.
+
+ psh = _GetSectionHeader();
+
+ // Ensure that we can at least read the section header and
+ // PID/Offset table.
+
+ cbstm = _MSTM(GetSize)(pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if (cbstm < _oSection + CB_PROPERTYSECTIONHEADER
+ ||
+ cbstm < _oSection + CB_PROPERTYSECTIONHEADER
+ + psh->cProperties * CB_PROPERTYIDOFFSET
+ )
+ {
+ StatusCorruption(pstatus, "_SearchForCodePage: stream too short to read section header");
+ goto Exit;
+ }
+
+ // Calculate the first & last PID/Offset pointers.
+ // We can't use _LoadPropertyOffsetPointers, because it assumes
+ // alignment.
+
+ ppo = psh->rgprop;
+ ppoMax = psh->rgprop + psh->cProperties;
+
+ // Search the PID/Offset array for PID_CODEPAGE
+
+ for ( ; ppo < ppoMax; ppo++)
+ {
+ if (ppo->propid == PID_CODEPAGE)
+ {
+ SERIALIZEDPROPERTYVALUE UNALIGNED *pprop;
+
+ // Get the real address of serialized property.
+
+ pprop = (SERIALIZEDPROPERTYVALUE *)
+ _MapOffsetToAddress( ppo->dwOffset );
+
+ // Check for corruption.
+
+ if ( ( (_oSection + ppo->dwOffset + CB_SERIALIZEDPROPERTYVALUE + sizeof(DWORD))
+ >
+ cbstm
+ )
+ ||
+ PropByteSwap(pprop->dwType) != VT_I2
+ )
+ {
+ StatusCorruption(pstatus, "_SearchForCodePage");
+ goto Exit;
+ }
+
+ // Set the member code page from the serialized property.
+ // (The codepage is an I2).
+
+ _CodePage = PropByteSwap( *(UNALIGNED USHORT *) &pprop->rgb );
+ break;
+
+ } // if (ppo->propid == PID_CODEPAGE)
+ } // for ( ; ppo < ppoMax; ppo++)
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+
+} // CPropertySetStream::_SearchForCodePage()
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_MapOffsetToAddress, private
+//
+// Synopsis: maps an offset to an address
+//
+// Arguments: [Offset] -- the offset in the section
+//
+// Returns: ptr to the offset mapped
+//+--------------------------------------------------------------------------
+
+inline VOID *
+CPropertySetStream::_MapOffsetToAddress(ULONG Offset) const
+{
+ PROPASSERT(_cSection != 0);
+
+ return(Add2Ptr(_GetSectionHeader(), Offset));
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_MapAddressToOffset, private
+//
+// Synopsis: maps an address to an offset
+//
+// Arguments: [pvAddr] -- the address in the section
+//
+// Returns: section-relative offset for passed pointer
+//+--------------------------------------------------------------------------
+
+inline ULONG
+CPropertySetStream::_MapAddressToOffset(VOID const *pvAddr) const
+{
+ PROPASSERT(_cSection != 0);
+
+ // Get a ptr to the section header.
+ VOID const *pvSectionHeader = _GetSectionHeader();
+
+ PROPASSERT((BYTE const *) pvAddr >= (BYTE const *) pvSectionHeader);
+ return((BYTE const *) pvAddr - (BYTE const *) pvSectionHeader);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_MapAbsOffsetToAddress, private
+//
+// Synopsis: maps an address to an offset
+//
+// Arguments: [oAbsolute] -- the absolute offset
+//
+// Returns: a ptr to the offset mapped
+//+--------------------------------------------------------------------------
+
+inline VOID *
+CPropertySetStream::_MapAbsOffsetToAddress(ULONG oAbsolute) const
+{
+ return(Add2Ptr(_pph, oAbsolute));
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_MapAddressToAbsOffset, private
+//
+// Synopsis: maps an address to an offset
+//
+// Arguments: [pvAddr] -- the address
+//
+// Returns: the absolute offset
+//+--------------------------------------------------------------------------
+
+inline ULONG
+CPropertySetStream::_MapAddressToAbsOffset(VOID const *pvAddr) const
+{
+ PROPASSERT((BYTE const *) pvAddr >= (BYTE *) _pph);
+ return((BYTE const *) pvAddr - (BYTE *) _pph);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::CPropertySetStream
+//
+// Synopsis: constructor for property set class
+//
+// Arguments:UK [Flags] -- NONSIMPLE|*1* of READ/WRITE/CREATE/CREATEIF/DELETE
+// K [pscb] -- SCB for property stream
+// K [pirpc] -- pointer to Irp Context
+// K [State] -- CPSS_PROPHEADER
+// U [pmstm] -- mapped stream implementation
+// U [pma] -- caller's memory allocator
+//
+// Returns: None
+//---------------------------------------------------------------------------
+
+CPropertySetStream::CPropertySetStream(
+ IN USHORT Flags, // NONSIMPLE|*1* of READ/WRITE/CREATE/CREATEIF/DELETE
+#ifdef KERNEL
+ IN SCB *pscb,
+ IN IRPCONTEXT *pirpc,
+ IN BYTE State
+#else
+ IN CMappedStream *pmstm, // mapped stream impelementation
+ IN PMemoryAllocator *pma // caller's memory allocator
+#endif
+ ) :
+ _Flags((BYTE) Flags),
+#ifdef KERNEL
+ _State(State),
+ _mstm(
+ pscb,
+ pirpc,
+ (Flags & CREATEPROP_MODEMASK) == CREATEPROP_READ?
+ KMS_PROPSET : (KMS_PROPSET | KMS_WRITE)),
+#else
+ _State(0),
+ _pmstm(pmstm),
+ _pma(pma),
+#endif
+ _pph(NULL)
+{
+ _CodePage = CP_CREATEDEFAULT(_State); // Default if not present
+ PROPASSERT(_Flags == Flags); // Should fit in a byte
+#ifdef KERNEL
+ PROPASSERT((_State & ~CPSS_PROPHEADER) == 0);
+#endif
+
+ _oSection = 0;
+ _cSection = 0;
+ _cbTail = 0;
+
+}
+
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::Close
+//
+// Synopsis: shutdown property set prior to calling destructor
+//
+// Arguments: [pstatus] -- Pointer to NTSTATUS code.
+//
+// Returns: None
+//---------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::Close(OUT NTSTATUS *pstatus)
+{
+ *pstatus = STATUS_SUCCESS;
+
+ // Validate the byte-order (_pph could be NULL in certain
+ // close scenarios, e.g. an RtlCreatePropertySet fails).
+ PROPASSERT(NULL == _pph || PROPSET_BYTEORDER == _pph->wByteOrder);
+
+ PROPASSERT(
+ (_Flags & CREATEPROP_MODEMASK) != CREATEPROP_READ ||
+ !IsModified());
+
+ _MSTM(Unmap)(IsModified(), (VOID **) &_pph);
+
+ _MSTM(Close)(pstatus);
+// if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+//Exit:
+
+ return;
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::Open
+//
+// Synopsis: Open property set image
+//
+// Arguments: None
+//
+// Returns: None
+//---------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::Open(
+ IN GUID const *pfmtid, // property set fmtid
+ OPTIONAL IN GUID const *pclsid, // CLASSID of propset code (create only)
+ IN ULONG LocaleId, // Locale Id (create only)
+ OPTIONAL OUT ULONG *pOSVersion, // OS Version from header
+ IN USHORT CodePage, // CodePage of property set (create only)
+ OUT NTSTATUS *pstatus
+ )
+{
+ *pstatus = STATUS_SUCCESS;
+ LOADSTATE LoadState;
+ PROPASSERT(!_IsMapped());
+
+ if( pOSVersion != NULL )
+ *pOSVersion = PROPSETHDR_OSVERSION_UNKNOWN;
+
+ // Open the underlying stream which holds the property set.
+ // We give it a callback pointer so that it can call
+ // RtlOnMappedStreamEvent.
+
+ _MSTM(Open)(this, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // Load the header, including fixing the in-memory image of
+ // poorly-formatted property sets.
+
+ LoadState = _LoadHeader(pfmtid, _Flags & CREATEPROP_MODEMASK, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if (LoadState != LOADSTATE_DONE)
+ {
+ switch (_Flags & CREATEPROP_MODEMASK)
+ {
+ case CREATEPROP_READ:
+ case CREATEPROP_WRITE:
+ if (LoadState == LOADSTATE_FAIL)
+ {
+ StatusCorruption(pstatus, "Open: _LoadHeader");
+ goto Exit;
+ }
+ PROPASSERT(
+ LoadState == LOADSTATE_BADFMTID ||
+ LoadState == LOADSTATE_USERDEFINEDNOTFOUND);
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "_LoadHeader: LoadState=%x\n", LoadState));
+
+ *pstatus = STATUS_PROPSET_NOT_FOUND;
+ goto Exit;
+ }
+
+ _Create(
+ pfmtid,
+ pclsid,
+ LocaleId,
+ CodePage,
+ LoadState,
+ pstatus
+ );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ } // if (LoadState != LOADSTATE_DONE)
+
+ PROPASSERT(PROPSET_BYTEORDER == _pph->wByteOrder);
+
+ if (_HasPropHeader() &&
+ (_pph->dwOSVer == PROPSETVER_WIN310 ||
+ _pph->dwOSVer == PROPSETVER_WIN333))
+ {
+ DebugTrace(0, DEBTRACE_PROPPATCH, (
+ "Open(%s) downlevel: %x\n",
+ (_Flags & CREATEPROP_MODEMASK) == CREATEPROP_READ? "Read" : "Write",
+ _Flags));
+ _State |= CPSS_DOWNLEVEL;
+ }
+
+ if ((_Flags & CREATEPROP_MODEMASK) != CREATEPROP_READ)
+ {
+ if (_State & CPSS_PACKEDPROPERTIES)
+ {
+ StatusAccessDenied(pstatus, "Open: writing Unaligned propset");
+ goto Exit;
+ }
+ if ((_State & (CPSS_MULTIPLESECTIONS | CPSS_DOCUMENTSUMMARYINFO)) ==
+ CPSS_MULTIPLESECTIONS)
+ {
+ StatusAccessDenied(pstatus, "Open: writing unknown multiple section propset");
+ goto Exit;
+ }
+ }
+
+ // Return the OS Version to the caller.
+
+ if( pOSVersion != NULL )
+ *pOSVersion = _pph->dwOSVer;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+}
+
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::ReOpen
+//
+// Synopsis: ReOpen property set image
+//
+// Arguments: [pstatus] -- Pointer to NSTATUS code.
+//
+// Returns: Number of properties.
+//---------------------------------------------------------------------------
+
+ULONG
+CPropertySetStream::ReOpen(OUT NTSTATUS *pstatus)
+{
+ LOADSTATE LoadState;
+ PROPERTYSECTIONHEADER const *psh;
+ ULONG cProperties = 0;
+
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(_IsMapped());
+
+ _MSTM(ReOpen)((VOID **) &_pph, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if (_State & CPSS_USERDEFINEDDELETED)
+ {
+ goto Exit;
+ }
+
+ LoadState = _LoadHeader(NULL,
+ CREATEPROP_READ, // all we need is !create
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if (LoadState != LOADSTATE_DONE)
+ {
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "ReOpen: LoadState=%lx\n",
+ LoadState));
+ StatusCorruption(pstatus, "ReOpen: _LoadHeader");
+ goto Exit;
+ }
+
+ PROPASSERT(PROPSET_BYTEORDER == _pph->wByteOrder);
+
+ psh = _GetSectionHeader();
+ PROPASSERT(psh != NULL);
+
+ cProperties = psh->cProperties;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return( cProperties );
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_InitSection
+//
+// Synopsis: Initialize a section header and the default properties.
+//
+// Arguments: [pfo] -- pointer to section info
+// [LocaleId] -- Locale Id
+//
+// Returns: None
+//---------------------------------------------------------------------------
+
+ // Serialized Code-Page size
+#define CB_CODEPAGE (sizeof(ULONG) + DwordAlign(sizeof(USHORT)))
+
+ // Serialized Locale ID (LCID) size.
+#define CB_LOCALE (sizeof(ULONG) + sizeof(ULONG))
+
+ // Minimum section size (minimum has Code Page & LCID)
+#define CB_MINSECTIONSIZE (CB_PROPERTYSECTIONHEADER \
+ + 2 * CB_PROPERTYIDOFFSET \
+ + CB_CODEPAGE \
+ + CB_LOCALE)
+
+ // Minimum serialized dictionary size (a dict with no entries).
+#define CB_EMPTYDICTSIZE (sizeof(DWORD)) // Entry count
+
+ // Minimum User-Defined section size (in DocumentSummaryInformation propset).
+ // (Must include an empty dictionary & a PID/Offset for it.)
+#define CB_MINUSERDEFSECTIONSIZE \
+ (CB_MINSECTIONSIZE \
+ + \
+ CB_PROPERTYIDOFFSET \
+ + \
+ CB_EMPTYDICTSIZE)
+
+VOID
+CPropertySetStream::_InitSection(
+ IN FORMATIDOFFSET *pfo,
+ IN ULONG LocaleId,
+ IN BOOL fCreateDictionary // Create an empty dictionary?
+ )
+{
+ PROPERTYSECTIONHEADER *psh;
+
+ ULONG ulPropIndex; // Index into the PID/Offset array.
+ DWORD dwPropValOffset; // The offset to where the next prop val will be written.
+ // Pointer to a serialized property value.
+ SERIALIZEDPROPERTYVALUE *pprop;
+
+ psh = (PROPERTYSECTIONHEADER *) _MapAbsOffsetToAddress(pfo->dwOffset);
+
+ // Set the property count and section size in the section header.
+ // This must account for the Code Page and Locale ID properties, and
+ // might need to account for an empty dictionary property.
+ // dwPropValOffset identifies the location of the next property value
+ // to be written.
+
+ if( fCreateDictionary )
+ {
+ // Three properties: Code Page, LCID, and Dictionary.
+
+ psh->cProperties = 3;
+ dwPropValOffset = CB_PROPERTYSECTIONHEADER + 3 * CB_PROPERTYIDOFFSET;
+ psh->cbSection = CB_MINUSERDEFSECTIONSIZE;
+ }
+ else
+ {
+ // Two properties: Code Page and LCID (no dictionary).
+
+ psh->cProperties = 2;
+ dwPropValOffset = CB_PROPERTYSECTIONHEADER + 2 * CB_PROPERTYIDOFFSET;
+ psh->cbSection = CB_MINSECTIONSIZE;
+ }
+
+
+ ulPropIndex = 0;
+
+ // If requested by the caller, create a dictionary property, but
+ // leave the dictionary empty. We always create this first. It shouldn't
+ // matter where it's located, but Office95 requires it
+ // and it doesn't do any harm to put it there.
+
+ if( fCreateDictionary )
+ {
+ // Fill in the PID/Offset table.
+
+ psh->rgprop[ ulPropIndex ].propid = PID_DICTIONARY;
+ psh->rgprop[ ulPropIndex ].dwOffset = dwPropValOffset;
+
+ // Fill in the property value.
+
+ pprop = (SERIALIZEDPROPERTYVALUE *) Add2Ptr( psh, dwPropValOffset );
+ pprop->dwType = 0L; // For the dictonary, this is actually the entry count.
+
+ // Advance the table & value indices.
+
+ ulPropIndex++;
+ dwPropValOffset += CB_EMPTYDICTSIZE;
+
+ } // if( fCreateDictionary )
+
+
+ // Write the code page. We write a zero first to initialize
+ // the padding bytes.
+
+ psh->rgprop[ ulPropIndex ].propid = PID_CODEPAGE;
+ psh->rgprop[ ulPropIndex ].dwOffset = dwPropValOffset;
+
+ pprop = (SERIALIZEDPROPERTYVALUE *) Add2Ptr( psh, dwPropValOffset );
+ pprop->dwType = PropByteSwap((DWORD) VT_I2);
+ *(DWORD *) pprop->rgb = 0; // Zero out extra two bytes.
+ *(WORD *) pprop->rgb = PropByteSwap( _CodePage );
+
+ ulPropIndex++;
+ dwPropValOffset += CB_CODEPAGE;
+
+
+ // Write the Locale ID.
+
+ psh->rgprop[ ulPropIndex ].propid = PID_LOCALE;
+ psh->rgprop[ ulPropIndex ].dwOffset = dwPropValOffset;
+
+ pprop = (SERIALIZEDPROPERTYVALUE *) Add2Ptr(psh, dwPropValOffset );
+ pprop->dwType = PropByteSwap( (DWORD) VT_UI4 );
+ *(DWORD *) pprop->rgb = PropByteSwap( (DWORD) LocaleId );
+
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+// Member: _MultiByteToWideChar, private
+//
+// Synopsis: Convert a MultiByte string to a Unicode string,
+// using the _pma memory allocator if necessary.
+//
+// Arguments: [pch] -- pointer to MultiByte string
+// [cb] -- byte length of MultiByte string
+// (-1 if null terminated)
+// [CodePage] -- Codepage of input string.
+// [ppwc] -- pointer to pointer to converted string
+// (if *ppwc is NULL, it will be alloced,
+// if non-NULL, *ppwc must be *pcb bytes long).
+// [pcb] -- IN: byte length of *ppwc
+// OUT: byte length of Unicode string.
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: Nothing
+//---------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::_MultiByteToWideChar(
+ IN CHAR const *pch,
+ IN ULONG cb,
+ IN USHORT CodePage,
+ OUT WCHAR **ppwc,
+ OUT ULONG *pcb,
+ OUT NTSTATUS *pstatus)
+{
+ // ------
+ // Locals
+ // ------
+
+ // Did we allocate *ppwc?
+ BOOL fAlloc = FALSE;
+
+ // --------------
+ // Initialization
+ // --------------
+
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(pch != NULL);
+ PROPASSERT(ppwc != NULL);
+ PROPASSERT(pcb != NULL);
+
+ PROPASSERT(IsAnsiString(pch, ((ULONG)-1 == cb ) ? MAXULONG : cb));
+
+ PROPASSERT(NULL != *ppwc || 0 == *pcb);
+ PROPASSERT(UnicodeCallouts.pfnMultiByteToWideChar != NULL);
+
+ // ------------------
+ // Convert the String
+ // ------------------
+
+ // We will pass through this loop once (if the caller provided a buffer
+ // or twice (otherwise).
+
+ while (TRUE)
+ {
+ // Attempt to convert the string.
+
+ *pcb = (*UnicodeCallouts.pfnMultiByteToWideChar)(
+ CodePage, // Source codepage
+ 0, // Flags
+ pch, // Source string
+ cb, // Source string length
+ *ppwc, // Target string
+ *pcb); // Size of target string buffer
+
+ // The converted length should never be zero.
+ if (0 == *pcb)
+ {
+ // If we alloced a buffer, free it now.
+ if( fAlloc )
+ {
+ _pma->Free( *ppwc );
+ *ppwc = NULL;
+ }
+
+ // If there was an error, assume that it was a code-page
+ // incompatibility problem.
+
+ StatusError(pstatus, "_MultiByteToWideChar error",
+ STATUS_UNMAPPABLE_CHARACTER);
+ goto Exit;
+ }
+
+ // There was no error. If we provided a non-NULL buffer,
+ // then the conversion was performed and we're done.
+
+ *pcb *= sizeof(WCHAR); // cch => cb
+ if (*ppwc != NULL)
+ {
+ DebugTrace(0, DEBTRACE_PROPERTY, (
+ "_MultiByteToWideChar: pch='%s'[%x] pwc='%ws'[%x->%x]\n",
+ pch,
+ cb,
+ *ppwc,
+ *pcb,
+ *pcb * sizeof(WCHAR)));
+ break;
+ }
+
+ // We haven't actually the string yet. Now that
+ // we know the length, we can allocate a buffer and try the
+ // conversion for real.
+
+ *ppwc = (WCHAR *) _pma->Allocate( *pcb );
+ if (NULL == *ppwc)
+ {
+ StatusNoMemory(pstatus, "_MultiByteToWideChar: no memory");
+ goto Exit;
+ }
+ fAlloc = TRUE;
+
+ } // while(TRUE)
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+
+} // CPropertySetStream::_MultiByteToWideChar
+
+
+
+//+---------------------------------------------------------------------------
+// Member: _WideCharToMultiByte, private
+//
+// Synopsis: Convert a Unicode string to a MultiByte string,
+// using the _pma memory allocator if necessary.
+//
+// Arguments: [pwc] -- pointer to Unicode string
+// [cch] -- character length of Unicode string
+// (-1 if null terminated)
+// [CodePage] -- codepage of target string
+// [ppch] -- pointer to pointer to converted string
+// (if *ppch is NULL, it will be alloced,
+// if non-NULL, *ppch must be *pcb bytes long).
+// [pcb] -- IN: byte length of *ppch
+// OUT: byte length of MultiByte string
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: Nothing
+//---------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::_WideCharToMultiByte(
+ IN WCHAR const *pwc,
+ IN ULONG cch,
+ IN USHORT CodePage,
+ OUT CHAR **ppch,
+ OUT ULONG *pcb,
+ OUT NTSTATUS *pstatus)
+{
+ // ------
+ // Locals
+ // ------
+
+ // Did we allocate *ppch?
+ BOOL fAlloc = FALSE;
+
+ // --------------
+ // Initialization
+ // --------------
+
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(pwc != NULL);
+ PROPASSERT(ppch != NULL);
+ PROPASSERT(pcb != NULL);
+
+ PROPASSERT(IsUnicodeString(pwc, ((ULONG)-1 == cch ) ? MAXULONG : cch*sizeof(WCHAR)));
+
+ PROPASSERT(NULL != *ppch || 0 == *pcb);
+ PROPASSERT(UnicodeCallouts.pfnWideCharToMultiByte != NULL);
+
+ // ------------------
+ // Convert the String
+ // ------------------
+
+ // We will pass through this loop once (if the caller provided a buffer
+ // or twice (otherwise).
+
+ while (TRUE)
+ {
+ // Attempt the conversion.
+ *pcb = (*UnicodeCallouts.pfnWideCharToMultiByte)(
+ CodePage, // Codepage to convert to
+ 0, // Flags
+ pwc, // Source string
+ cch, // Size of source string
+ *ppch, // Target string
+ *pcb, // Size of target string buffer
+ NULL, // lpDefaultChar
+ NULL); // lpUsedDefaultChar
+
+ // A converted length of zero indicates an error.
+ if (0 == *pcb)
+ {
+ // If we allocated a buffer in this routine, free it.
+ if( fAlloc )
+ {
+ _pma->Free( *ppch );
+ *ppch = NULL;
+ }
+
+ // If there was an error, assume that it was a code-page
+ // incompatibility problem.
+
+ StatusError(pstatus, "_WideCharToMultiByte: WideCharToMultiByte error",
+ STATUS_UNMAPPABLE_CHARACTER);
+ goto Exit;
+ }
+
+ // If we have a non-zero length, and we provided a buffer,
+ // then we're done (successfully).
+
+ if (*ppch != NULL)
+ {
+ DebugTrace(0, DEBTRACE_PROPERTY, (
+ "_WideCharToMultiByte: pwc='%ws'[%x] pch='%s'[%x->%x]\n",
+ pwc,
+ cch,
+ *ppch,
+ *pcb,
+ *pcb));
+ break;
+ }
+
+ // There were no errors, but we need to allocate a buffer
+ // to do the actual conversion.
+
+ *ppch = (CHAR*) _pma->Allocate( *pcb );
+ if (*ppch == NULL)
+ {
+ StatusNoMemory(pstatus, "_WideCharToMultiByte: no memory");
+ goto Exit;
+ }
+ fAlloc = TRUE;
+
+ } // while (TRUE)
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+
+} // CPropertySetStream::_WideCharToMultiByte
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::ByteSwapHeaders
+//
+// Synopsis: Byte-swap the headers of a property set header
+// (both the propset header and any section headers).
+//
+// Arguments: [PROPERTYSETHEADER*] pph
+// Pointer to the beginning of the property set.
+// [ULONG] cbstm
+// Total size of the property stream.
+// [NTSTATUS*] pstatus
+// Pointer to NTSTATUS code.
+//
+// Pre-Conditions:
+// There are no more than two sections.
+//
+// Note that this routine does not assume anything
+// about the current state of the CPropertySetStream
+// (it accesses no member variables).
+//
+// Post-Conditions:
+// If the property set headers are valid, the
+// propset and section headers are byte-swapped.
+// Note that if the property set is invalid, this
+// routine may only partially swap it. Therefore,
+// the caller must ensure in this case that no
+// attempt is made to use the property set.
+//
+// Returns: None. *pstatus will only be non-successful
+// if the Stream was too small for the property set
+// (i.e, the property set is corrupt). If the caller
+// knows this not to be the case, then it can assume
+// that this routine will return STATUS_SUCCESS.
+//
+//---------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::ByteSwapHeaders( IN PROPERTYSETHEADER *pph,
+ IN DWORD cbstm,
+ OUT NTSTATUS *pstatus )
+{
+#if LITTLEENDIAN
+
+ *pstatus = STATUS_SUCCESS;
+ return;
+
+#else
+
+ // ------
+ // Locals
+ // ------
+
+ ULONG cSections;
+ ULONG ulIndex, ulSectionIndex;
+
+ // pfoPropSet points into pph, pfoReal is a local copy
+ // in the system's endian-ness.
+ FORMATIDOFFSET *pfoPropSet, pfoReal[2];
+
+ // Pointers into pph.
+ PROPERTYSECTIONHEADER *psh = NULL;
+ PROPERTYIDOFFSET *po = NULL;
+
+ // Are we converting *to* the system's endian-ness?
+ BOOL fToSystemEndian;
+
+ // ----------
+ // Initialize
+ // ----------
+
+ *pstatus = STATUS_SUCCESS;
+ PROPASSERT( NULL != pph );
+ PROPASSERT(PROPSET_BYTEORDER == pph->wByteOrder
+ ||
+ PROPSET_BYTEORDER == ByteSwap( pph->wByteOrder )
+ );
+
+
+ // ----------------------------
+ // Swap the Property Set header
+ // ----------------------------
+
+ // Validate the stream length.
+ if( sizeof(*pph) > cbstm )
+ {
+ StatusCorruption(pstatus, "CPropertySetStream::ByteSwapHeaders: PropertySet header size");
+ goto Exit;
+ }
+
+ // Swap the fields in place.
+ PropByteSwap( &pph->wByteOrder );
+ PropByteSwap( &pph->wFormat );
+ PropByteSwap( &pph->dwOSVer );
+ PropByteSwap( &pph->clsid );
+ PropByteSwap( &pph->reserved );
+
+ // Are we converting to little-endian?
+ if( PROPSET_BYTEORDER == pph->wByteOrder)
+ fToSystemEndian = TRUE;
+ else
+ {
+ fToSystemEndian = FALSE;
+ PROPASSERT( PROPSET_BYTEORDER == PropByteSwap(pph->wByteOrder) );
+ }
+
+ // Get the correctly-endianed section count and validate.
+
+ cSections = fToSystemEndian ? pph->reserved
+ : PropByteSwap( pph->reserved );
+
+ if( cSections > 2 )
+ {
+ StatusCorruption(pstatus, "CPropertySetStream::ByteSwapHeaders: PropertySet header size");
+ goto Exit;
+ }
+
+ // -------------------------
+ // Swap the per-section data
+ // -------------------------
+
+ pfoPropSet = (FORMATIDOFFSET*) ((BYTE*) pph + sizeof(*pph));
+
+ for( ulSectionIndex = 0; ulSectionIndex < cSections; ulSectionIndex++ )
+ {
+ ULONG cbSection, cProperties;
+
+ // ------------------------------
+ // Swap the FormatID/Offset entry
+ // ------------------------------
+
+ // Is the Stream long enough for the array?
+ if( cbstm < (ULONG) &pfoPropSet[ulSectionIndex]
+ + sizeof(*pfoPropSet)
+ - (ULONG) pph )
+ {
+ StatusCorruption(pstatus,
+ "CPropertySetStream::_ByteSwapHeaders: FormatID/Offset size");
+ goto Exit;
+ }
+
+ // Get a local copy of this FMTID/Offset array entry
+ // If it is propset-endian format, swap to make usable.
+
+ pfoReal[ ulSectionIndex ].fmtid = pfoPropSet[ulSectionIndex].fmtid;
+ pfoReal[ ulSectionIndex ].dwOffset = pfoPropSet[ulSectionIndex].dwOffset;
+
+ if( fToSystemEndian )
+ {
+ PropByteSwap( &pfoReal[ulSectionIndex].fmtid );
+ PropByteSwap( &pfoReal[ulSectionIndex].dwOffset );
+ }
+
+ // Swap this FMTID/Offset entry in place.
+ PropByteSwap( &pfoPropSet[ulSectionIndex].fmtid );
+ PropByteSwap( &pfoPropSet[ulSectionIndex].dwOffset );
+
+
+ // -----------------------
+ // Swap the section header
+ // -----------------------
+
+ // Locate the section header and the first entry in the
+ // PID/Offset table.
+
+ psh = (PROPERTYSECTIONHEADER*)
+ ( (BYTE*) pph + pfoReal[ ulSectionIndex ].dwOffset );
+
+ po = (PROPERTYIDOFFSET*)
+ ( (BYTE*) psh + sizeof(psh->cbSection) + sizeof(psh->cProperties) );
+
+ // Validate that we can see up to the PID/Offset table.
+ if( cbstm < (ULONG) ((BYTE*) po - (BYTE*) pph) )
+ {
+ StatusCorruption(pstatus,
+ "CPropertySetStream::ByteSwapHeaders: Section header size");
+ goto Exit;
+ }
+
+ // Get local copies of the section & property counts.
+ // Again we may need to swap them from propset-endian format
+ // in order to make them usable.
+
+ cbSection = psh->cbSection;
+ cProperties = psh->cProperties;
+
+ if( fToSystemEndian)
+ {
+ PropByteSwap( &cbSection );
+ PropByteSwap( &cProperties );
+ }
+
+ // Swap the two fields at the top of the section header.
+
+ PropByteSwap( &psh->cbSection );
+ PropByteSwap( &psh->cProperties );
+
+ // -------------------------
+ // Swap the PID/Offset table
+ // -------------------------
+
+ // Validate that we can see the whole table.
+ if( cbstm < (BYTE*) po - (BYTE*) pph + cProperties * sizeof(*po) )
+ {
+ StatusCorruption(pstatus,
+ "CPropertySetStream::ByteSwapHeaders: Section header size");
+ goto Exit;
+ }
+
+ // Swap each of the array entries.
+ for( ulIndex = 0; ulIndex < cProperties; ulIndex++ )
+ {
+ PropByteSwap( &po[ulIndex].propid );
+ PropByteSwap( &po[ulIndex].dwOffset );
+ }
+
+ } // for( ulSectionIndex = 0; ulSectionIndex < cSections, ulIndex++ )
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+
+#endif // #if LITTLEENDIAN ... #else
+
+} // CPropertySetStream::ByteSwapHeaders
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_CreateUserDefinedSection
+//
+// Synopsis: Create second property section
+//
+// Arguments: [LoadState] -- _LoadHeader returned state
+// [LocaleId] -- Locale Id
+// [pstatus] -- Pointer to NTSTATUS code.
+//
+// Returns: TRUE if LoadState handled successfully. If TRUE,
+// *pstatus will be STATUS_SUCCESS.
+//---------------------------------------------------------------------------
+
+#ifndef KERNEL
+BOOLEAN
+CPropertySetStream::_CreateUserDefinedSection(
+ IN LOADSTATE LoadState,
+ IN ULONG LocaleId,
+ OUT NTSTATUS *pstatus)
+{
+ BOOL fSuccess = FALSE;
+ FORMATIDOFFSET *pfo;
+ ULONG cbstmNew;
+ PROPERTYSECTIONHEADER *psh;
+
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(_State & CPSS_USERDEFINEDPROPERTIES);
+ switch (_Flags & CREATEPROP_MODEMASK)
+ {
+ case CREATEPROP_CREATEIF:
+ case CREATEPROP_CREATE:
+ if (LoadState == LOADSTATE_USERDEFINEDNOTFOUND)
+ {
+ ULONG cbmove;
+
+ PROPASSERT(_cSection == 1);
+ pfo = _GetFormatidOffset(0);
+ PROPASSERT(pfo->fmtid == guidDocumentSummary);
+ PROPASSERT(IsDwordAligned(pfo->dwOffset));
+
+ // Get a pointer to the first section header, using the
+ // FmtID/Offset array.
+
+ psh = (PROPERTYSECTIONHEADER *) _MapAbsOffsetToAddress(pfo->dwOffset);
+
+ // Determine if we need to move the first section back in order
+ // to make room for this new entry in the FmtID/Offset array.
+
+ cbmove = 0;
+ if (pfo->dwOffset < CB_PROPERTYSETHEADER + 2 * CB_FORMATIDOFFSET)
+ {
+ cbmove = CB_PROPERTYSETHEADER + 2*CB_FORMATIDOFFSET - pfo->dwOffset;
+ }
+
+ // How big should the Stream be?
+
+ cbstmNew = pfo->dwOffset // The offset of the first section
+ +
+ cbmove // Room for new FormatID/Offset array entry
+ + // Size of first section
+ DwordAlign(psh->cbSection)
+ + // Size of User-Defined section.
+ CB_MINUSERDEFSECTIONSIZE;
+
+ // Set the stream size.
+
+ _MSTM(SetSize)(cbstmNew, TRUE, (VOID **) &_pph, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // reload all pointers into mapped image:
+
+ pfo = _GetFormatidOffset(0);
+ psh = (PROPERTYSECTIONHEADER *) _MapAbsOffsetToAddress(pfo->dwOffset);
+
+ if (cbmove != 0)
+ {
+ // Move section back to make room for new FORMATIDOFFSET entry
+
+ PropMoveMemory(
+ "_AddSection",
+ psh,
+ Add2Ptr(psh, cbmove),
+ psh,
+ psh->cbSection);
+
+ pfo->dwOffset += cbmove;
+ PROPASSERT(IsDwordAligned(pfo->dwOffset));
+ }
+
+ psh->cbSection = DwordAlign(psh->cbSection);
+
+ PROPASSERT(_oSection == 0);
+ PROPASSERT(_cSection == 1);
+ PROPASSERT(_pph->reserved == 1);
+
+ _cSection++;
+ _pph->reserved++;
+
+ _oSection = pfo->dwOffset + psh->cbSection;
+ pfo = _GetFormatidOffset(1);
+ pfo->fmtid = guidDocumentSummarySection2;
+ pfo->dwOffset = _oSection;
+ _InitSection(pfo,
+ LocaleId,
+ TRUE ); // Create an empty dictionary.
+
+ fSuccess = TRUE;
+ }
+ break;
+
+ case CREATEPROP_DELETE:
+ PROPASSERT(
+ LoadState == LOADSTATE_USERDEFINEDDELETE ||
+ LoadState == LOADSTATE_USERDEFINEDNOTFOUND);
+ if (LoadState == LOADSTATE_USERDEFINEDDELETE)
+ {
+ PROPASSERT(_cSection == 2);
+ PROPASSERT(_pph->reserved == 2);
+ pfo = _GetFormatidOffset(1);
+ RtlZeroMemory(pfo, sizeof(*pfo));
+
+ _cSection--;
+ _pph->reserved--;
+ pfo = _GetFormatidOffset(0);
+ PROPASSERT(pfo->fmtid == guidDocumentSummary);
+ PROPASSERT(IsDwordAligned(pfo->dwOffset));
+ psh = (PROPERTYSECTIONHEADER *)
+ _MapAbsOffsetToAddress(pfo->dwOffset);
+ psh->cbSection = DwordAlign(psh->cbSection);
+ cbstmNew = pfo->dwOffset + psh->cbSection;
+
+ _MSTM(SetSize)(cbstmNew, TRUE, (VOID **) &_pph, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ }
+ _State |= CPSS_USERDEFINEDDELETED;
+
+ fSuccess = TRUE;
+ break;
+
+ default:
+ PROPASSERT(!"_Flags: bad open mode");
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return( fSuccess );
+}
+#endif
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_Create
+//
+// Synopsis: Create property set image
+//
+// Arguments: [pfmtid] -- format id
+// [pclsid] -- class id
+// [LocaleId] -- Locale Id
+// [CodePage] -- CodePage
+// [LoadState] -- _LoadHeader returned state
+//
+// Returns: None
+//---------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::_Create(
+ IN GUID const *pfmtid,
+ OPTIONAL IN GUID const *pclsid,
+ IN ULONG LocaleId, // Locale Id (create only)
+ IN USHORT CodePage,
+ IN LOADSTATE LoadState,
+ OUT NTSTATUS *pstatus
+ )
+{
+ ULONG cb;
+ FORMATIDOFFSET *pfo;
+
+ *pstatus = STATUS_SUCCESS;
+
+ _SetModified();
+
+ // Set the size of the stream to correspond to the header for the
+ // property set as well as the section.
+
+ _CodePage = CodePage;
+ ULONG cSectionT = 1;
+
+ // Are we creating the UserDefined property set
+ // (the second section of the DocumentSummaryInformation
+ // property set)?
+
+ if (_State & CPSS_USERDEFINEDPROPERTIES)
+ {
+ // Create the UD propset, and set the cSection.
+ // If this routine returns TRUE, it means that
+ // the first section already existed, and we're done.
+ // Otherwise, we must continue and create the first section.
+
+ if (_CreateUserDefinedSection(LoadState, LocaleId, pstatus))
+ {
+ // If we get here, we know that *pstatus is Success.
+
+ if (pclsid != NULL)
+ {
+ _pph->clsid = *pclsid;
+ }
+ goto Exit;
+ }
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ cSectionT = 2;
+ }
+
+ // Calculate the exact size of the Stream (we know exactly
+ // what it will be because we only initialize the set(s) with
+ // fixed size data).
+
+ PROPASSERT( 1 <= cSectionT && cSectionT <= 2 );
+ cb = CB_PROPERTYSETHEADER // The size of the propset header.
+ + // The size of the FmtID/Offset array
+ cSectionT * CB_FORMATIDOFFSET
+ +
+ CB_MINSECTIONSIZE // The size of the first section
+ + // Maybe the size of the User-Defined section
+ ( cSectionT <= 1 ? 0 : CB_MINUSERDEFSECTIONSIZE );
+
+
+ DebugTrace(0, Dbg, ("SetSize(%x) init\n", cb));
+
+ // Set the size of the stream
+ _MSTM(SetSize)(cb, TRUE, (VOID **) &_pph, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // And get a mapping of the Stream.
+ _MSTM(Map)(TRUE, (VOID **) &_pph);
+ RtlZeroMemory(_pph, cb); // Zeros classid, fmtid(s), etc
+
+ // Initialize the OS Version in the header.
+ // Getting the current OS version depends on the OS.
+
+#if defined(_MAC)
+
+ {
+ // Get the Mac System Version (e.g., 7.53). If we get an API error,
+ // we won't treat it as fatal, we'll just set the version to 0.
+
+ OSErr oserr;
+ SysEnvRec theWorld;
+ oserr = SysEnvirons( curSysEnvVers, &theWorld );
+ PROPASSERT( noErr == oserr );
+
+ if( noErr == oserr )
+ {
+ _pph->dwOSVer = MAKEPSVER( OSKIND_MACINTOSH,
+ HIBYTE(theWorld.systemVersion), // Major
+ LOBYTE(theWorld.systemVersion) );// Minor
+ }
+ else
+ {
+ _pph->dwOSVer = MAKEPSVER( OSKIND_MACINTOSH, 0, 0 );
+ }
+
+ }
+
+#elif defined(IPROPERTY_DLL)
+
+ {
+ // Get the Windows version.
+ DWORD dwWinVersion = GetVersion();
+
+ // Use it to set the OSVersion
+ _pph->dwOSVer = MAKEPSVER( OSKIND_WIN32,
+ LOBYTE(LOWORD( dwWinVersion )), // Major
+ HIBYTE(LOWORD( dwWinVersion )) ); // Minor
+ }
+
+#else // #if defined(_MAC) ... #elif defined(IPROPERTY_DLL)
+
+ // Since we're part of the system, we can hard-code the OSVersion,
+ // and save the expense of an API call.
+
+ _pph->dwOSVer = PROPSETVER_CURRENT;
+
+#endif // #if defined(_MAC) ... #elif ... #else
+
+ // Initialize the rest of the header.
+
+ _pph->wByteOrder = 0xfffe;
+ //_pph->wFormat = 0; // RtlZeroMemory does this
+ PROPASSERT(_pph->wFormat == 0);
+
+ if (pclsid != NULL)
+ {
+ _pph->clsid = *pclsid;
+ }
+ _pph->reserved = cSectionT;
+
+ // Initialize the format id offset for the section(s).
+
+ pfo = _GetFormatidOffset(0);
+ pfo->dwOffset = CB_PROPERTYSETHEADER + cSectionT * CB_FORMATIDOFFSET;
+
+ // Are we creating the second section of the DocSumInfo property set?
+
+ if (cSectionT == 2)
+ {
+ // We need to initialize any empty first section.
+
+ pfo->fmtid = guidDocumentSummary;
+
+ _InitSection(pfo,
+ LocaleId,
+ FALSE); // Don't create an empty dictionary.
+
+ // Advance the FmtID/Offset table pointer to the second entry,
+ // and set it's offset to just beyond the first section.
+
+ pfo = _GetFormatidOffset(1);
+ pfo->dwOffset = CB_PROPERTYSETHEADER +
+ cSectionT * CB_FORMATIDOFFSET +
+ CB_MINSECTIONSIZE;
+ }
+
+ // Initialize the requested property set.
+
+ PROPASSERT(pfmtid != NULL);
+ pfo->fmtid = *pfmtid;
+ _InitSection(pfo,
+ LocaleId,
+ // TRUE => Create an empty dictionary
+ pfo->fmtid == guidDocumentSummarySection2 );
+
+ _cSection = cSectionT;
+ _oSection = pfo->dwOffset;
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+
+} // CPropertySetStream::_Create
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_LoadHeader
+//
+// Synopsis: verify header of a property set and read the code page
+//
+// Arguments: [pfmtid] -- format id
+// [Mode] -- open mode
+// [pstatus] -- Pointer to NTSTATUS code.
+//
+// Returns: LOADSTATE
+//---------------------------------------------------------------------------
+
+LOADSTATE
+CPropertySetStream::_LoadHeader(
+ OPTIONAL IN GUID const *pfmtid,
+ IN BYTE Mode,
+ OUT NTSTATUS *pstatus)
+{
+ LOADSTATE loadstate = LOADSTATE_FAIL;
+ ULONG cbstm, cbMin;
+ PROPERTYSECTIONHEADER *psh;
+ FORMATIDOFFSET const *pfo;
+ BOOLEAN fSummaryInformation = FALSE;
+#if DBGPROP
+ BOOLEAN fFirst = _pph == NULL;
+#endif
+
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT((_State & CPSS_USERDEFINEDDELETED) == 0);
+
+ // If this is one of the DocSumInfo property sets,
+ // we need to set some _State bits. If this is an
+ // Open, rather than a Create, pfmtid may be NULL.
+ // In that case, we'll set these bits after the open
+ // (since we can then get the fmtid from the header).
+
+ if( pfmtid != NULL && *pfmtid == guidDocumentSummary )
+ {
+ _State |= CPSS_DOCUMENTSUMMARYINFO;
+ }
+
+ if (pfmtid != NULL && *pfmtid == guidDocumentSummarySection2)
+ {
+ _State |= CPSS_USERDEFINEDPROPERTIES;
+ }
+ else
+ {
+ // If this isn't the UD property set, the Mode
+ // better not be "Delete" (all other property sets
+ // are deleted simply be deleting the underlying
+ // stream).
+
+ if (Mode == CREATEPROP_DELETE)
+ {
+ DebugTrace(0, Dbg, ("_LoadHeader: CREATEPROP_DELETE\n"));
+ StatusInvalidParameter(pstatus, "_LoadHeader: CREATEPROP_DELETE");
+ goto Exit;
+ }
+ if (Mode == CREATEPROP_CREATE)
+ {
+ goto Exit; // We're going to overwrite it anyway
+ }
+ }
+
+ // Get the size of the underlying stream.
+ cbstm = _MSTM(GetSize)(pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // Map the serialized property set to a pointer.
+ _MSTM(Map)(FALSE, (VOID **) &_pph);
+
+ // Compute the minimum size of this property set, as specified
+ // by the property set header and the section headers. This call
+ // will fail if any part of these headers is beyond the end of the
+ // the stream (as determined from cbstm). It will *not* fail if
+ // a section's cbSection indicates that the section goes beyond the
+ // end of the stream.
+
+ cbMin = _ComputeMinimumSize(cbstm, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // The following assert should technically ASSERT equality. However,
+ // to avoid unmapping and closing sections for every property operation,
+ // we allow shrinks to fail when other instances of the same property
+ // set are active. So we on occasion will legitimately see streams larger
+ // than necessary. The wasted space will be cleaned up when the property
+ // set is next modified.
+ //PROPASSERT(cbMin == cbstm);
+
+ // The following assert should be valid, but it isn't for some
+ // older property sets which we fix in the _Fix* routines, which
+ // are called below.
+ //PROPASSERT(cbMin <= cbstm);
+
+ DebugTrace(0, KERNELSELECT(Dbg, Dbg | DEBTRACE_CREATESTREAM), (
+ "ComputeMinimumSize: cbMin=%l" szX " cbstm=%l" szX " cbUnused=%l" szX "\n",
+ cbMin,
+ cbstm,
+ cbstm - cbMin));
+
+ _oSection = 0;
+ _cSection = 1;
+ _cbTail = 0;
+#ifdef KERNEL
+ _CodePage = CP_WINUNICODE;
+#endif
+
+ if (_HasPropHeader())
+ {
+ // The first expression must be TRUE before we can dereference _pph
+ // for the second expression.
+
+ if (cbstm < CB_PROPERTYSETHEADER + CB_FORMATIDOFFSET ||
+ cbstm < CB_PROPERTYSETHEADER + _pph->reserved * CB_FORMATIDOFFSET ||
+ _pph->wByteOrder != 0xfffe ||
+ _pph->wFormat != 0 ||
+ _pph->reserved < 1)
+ {
+ _cSection = 0; // Mark property set invalid
+ DebugTrace(0, cbstm != 0? DEBTRACE_ERROR : Dbg, (
+ "_LoadHeader: %s (ver=%lx)\n",
+ cbstm == 0? "Empty Stream" :
+ cbstm < CB_PROPERTYSETHEADER + CB_FORMATIDOFFSET?
+ "Stream too small for header" :
+ _pph->wByteOrder != 0xfffe? "Bad wByteOrder field" :
+ _pph->wFormat != 0? "Bad wFormat field" :
+ _pph->reserved < 1? "Bad reserved field" :
+ "Bad dwOSVer field",
+ _pph != NULL? _pph->dwOSVer : 0));
+ goto Exit;
+ }
+
+ // Now that we've loaded the property set, check again
+ // to see if this is a SumInfo or DocSumInfo set.
+
+ pfo = _GetFormatidOffset(0);
+ if (pfo->fmtid == guidDocumentSummary)
+ {
+ _State |= CPSS_DOCUMENTSUMMARYINFO;
+ }
+ else if (pfo->fmtid == guidSummary)
+ {
+ fSummaryInformation = TRUE;
+ }
+
+ // If what we're after is the property set in the
+ // second section, verify that it's there.
+
+ if (_State & CPSS_USERDEFINEDPROPERTIES)
+ {
+ // Ensure that this is the second section of
+ // the DocSumInfo property set; that's the only
+ // two-section property set we support.
+
+ if ((_State & CPSS_DOCUMENTSUMMARYINFO) == 0)
+ {
+ DebugTrace(0, DEBTRACE_ERROR, ("Not DocumentSummaryInfo 1st FMTID\n"));
+ goto Exit;
+ }
+
+ // Verify that this property set has two sections, and that
+ // the second section is the UD propset.
+
+ if (_pph->reserved < 2 ||
+ (pfo = _GetFormatidOffset(1))->fmtid != guidDocumentSummarySection2)
+ {
+ DebugTrace(
+ 0,
+ _pph->reserved < 2? Dbg : DEBTRACE_ERROR,
+ ("Bad/missing 2nd section FMTID\n"));
+ loadstate = LOADSTATE_USERDEFINEDNOTFOUND;
+ goto Exit;
+ }
+ }
+ else if (pfmtid != NULL)
+ {
+ // This isn't the UserDefined property set, so it
+ // should be the first section, so it should match
+ // the caller-requested format ID.
+
+ if (*pfmtid != pfo->fmtid)
+ {
+ // The propset's FmtID doesn't match, but maybe that's
+ // because it's a MacWord6 SumInfo property set, in which
+ // the FmtID isn't byte-swapped. Otherwise, it's a problem.
+
+ if( OSKIND_MACINTOSH == PROPSETHDR_OSVER_KIND(_pph->dwOSVer)
+ &&
+ guidSummary == *pfmtid
+ &&
+ IsEqualFMTIDByteSwap( *pfmtid, pfo->fmtid )
+ )
+ {
+ fSummaryInformation = TRUE;
+ }
+ else
+ {
+ _cSection = 0;
+ DebugTrace(0, DEBTRACE_ERROR, ("Bad FMTID\n"));
+ loadstate = LOADSTATE_BADFMTID;
+ goto Exit;
+ }
+ } // if (*pfmtid != pfo->fmtid)
+ } // else if (pfmtid != NULL)
+
+ _oSection = pfo->dwOffset;
+ _cSection = _pph->reserved;
+
+ } // if (_HasPropHeader())
+
+ psh = _GetSectionHeader();
+
+ // Scan the property set for a code page, and set _CodePage.
+
+ _SearchForCodePage( pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // If we have multiple sections, record the tail length
+ // (the size of the property set beyond this section).
+
+ if (_cSection > 1)
+ {
+ _State |= CPSS_MULTIPLESECTIONS;
+ _cbTail = cbMin - (_oSection + psh->cbSection);
+ DebugTrace(0, Dbg, ("_LoadHeader: cbTail=%x\n", _cbTail));
+ }
+
+
+ // Fix all header-related problems in the in-memory representation.
+ // The only header-related problems we fix are with SummaryInformation
+ // property sets.
+
+ if (fSummaryInformation)
+ {
+ _FixSummaryInformation(&cbstm, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+
+
+ // Now that, to the best of our ability, the headers are good,
+ // let's validate them against the actual stream size.
+
+ if (cbstm < _oSection + CB_PROPERTYSECTIONHEADER ||
+ psh->cbSection < CB_PROPERTYSECTIONHEADER +
+ psh->cProperties * CB_PROPERTYIDOFFSET ||
+ cbstm < _oSection + CB_PROPERTYSECTIONHEADER +
+ psh->cProperties * CB_PROPERTYIDOFFSET ||
+ cbstm < _oSection + psh->cbSection)
+ {
+ _cSection = 0;
+ DebugTrace(0, Dbg, ("_LoadHeader: too small for section\n"));
+ goto Exit;
+ }
+
+ // Now we know the headers are OK, so let's see if there are any
+ // problems in the properties themselves that we know how
+ // to fix.
+
+ if (fSummaryInformation || (_State & CPSS_DOCUMENTSUMMARYINFO))
+ {
+ _FixPackedPropertySet( pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+
+ if (Mode == CREATEPROP_DELETE)
+ {
+ loadstate = LOADSTATE_USERDEFINEDDELETE;
+ goto Exit;
+ }
+
+ // ----
+ // Exit
+ // ----
+
+ loadstate = LOADSTATE_DONE;
+
+Exit:
+
+ return( loadstate );
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_FixSummaryInformation
+//
+// Synopsis: Fix up the memory image of a SummaryInformation propset,
+// except for packing or padding problems (which are fixed
+// in _FixPackedPropertySet).
+//
+// Arguments: [pcbstm] - The size of the mapped stream. This may
+// be updated by this routine.
+// [pstatus] - Pointer to NTSTATUS code.
+//
+// Returns: None
+//
+//---------------------------------------------------------------------------
+
+#define PID_THUMBNAIL 0x00000011 // SummaryInformation thumbnail property
+
+VOID
+CPropertySetStream::_FixSummaryInformation(IN OUT ULONG *pcbstm,
+ OUT NTSTATUS *pstatus)
+{
+ PROPERTYSECTIONHEADER *psh;
+ PROPERTYIDOFFSET *ppo, *ppoMax;
+
+ *pstatus = STATUS_SUCCESS;
+
+ // If this property set has multiple sections, then it's not one
+ // of the ones we know how to fix in this routine.
+
+ if (1 != _cSection) goto Exit;
+
+ // Load pointers to the section header and the PID/Offset array.
+ psh = _LoadPropertyOffsetPointers(&ppo, &ppoMax, pstatus);
+ if( !NT_SUCCESS(*pstatus) || NULL == psh ) goto Exit;
+
+ // Look for the MS Publisher problem. Pub only writes
+ // a Thumbnail, but it sets the section size too short (by 4 bytes).
+ // Pub95 has the additional problem that it doesn't DWORD-align the
+ // section and stream size. We fix both of these problems below.
+
+ if (*pcbstm == _oSection + psh->cbSection + sizeof(ULONG))
+ {
+ // Look for the thumbnail property.
+
+ for ( ; ppo < ppoMax; ppo++)
+ {
+ if (ppo->propid == PID_THUMBNAIL)
+ {
+ SERIALIZEDPROPERTYVALUE const *pprop;
+
+ // If this property isn't properly aligned, then ignore it.
+
+ if (ppo->dwOffset & (sizeof(DWORD) - 1))
+ {
+ break;
+ }
+
+ // Get a pointer to the property.
+
+ pprop = (SERIALIZEDPROPERTYVALUE *)
+ _MapOffsetToAddress(ppo->dwOffset);
+
+ // Look specifically for the Publisher's Thumbnail property.
+ // If this is a Publisher set, the lengths won't add
+ // up correctly. For the lengths to add up correctly,
+ // the offset of the property, plus
+ // the length of the thumbnail, plus the size of the VT
+ // DWORD and the size of the length DWORD should be the
+ // size of the Section. But In the case of Publisher,
+ // the section length is 4 bytes short.
+
+ if (PropByteSwap(pprop->dwType) == VT_CF // It's in a clipboard format
+ && // For Windows
+ *(ULONG *) &pprop->rgb[sizeof(ULONG)] == PropByteSwap((ULONG)MAXULONG)
+ &&
+ ppo->dwOffset + // And the lengths don't add up
+ PropByteSwap( *(ULONG *) pprop->rgb ) +
+ (3 - 2) * sizeof(ULONG) == psh->cbSection)
+ {
+ // We've found the Publisher problem.
+
+ // For Pub95 files, we must dword-align the section
+ // and stream size. We don't change the size of the underlying
+ // stream, however, just the mapping. This is because if the caller
+ // doesn't make any explicit changes, we don't want the mapped Stream
+ // to be modified. We do this step before fixing the section-size
+ // problem, so if it should fail we haven't touched anything.
+
+ if( !IsDwordAligned( *pcbstm ))
+ {
+ // Increase the size of the buffer, and reload the
+ // psh pointer.
+
+ *pcbstm += DwordRemain(*pcbstm);
+ _MSTM(SetSize)(*pcbstm, // The new size
+ FALSE, // Don't update the underlying stream
+ (VOID **) &_pph, // The new mapping
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ psh = _LoadPropertyOffsetPointers(&ppo, &ppoMax, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // Align the section size.
+
+ psh->cbSection += DwordRemain(psh->cbSection);
+ }
+
+ // Now correct the section size.
+
+ DebugTrace(0, DEBTRACE_PROPPATCH, (
+ "_FixSummaryInformation: Patch section size: %x->%x\n",
+ psh->cbSection,
+ psh->cbSection + sizeof(ULONG)));
+
+ psh->cbSection += sizeof(ULONG);
+
+ } // if (pprop->dwType == VT_CF ...
+
+ break;
+
+ } // if (ppo->propid == PID_THUMBNAIL)
+ } // for ( ; ppo < ppoMax; ppo++)
+ } // if (cbstm == _oSection + psh->cbSection + sizeof(ULONG))
+
+ // Look for the Excel 5.0a problem.
+ // Excel 5.0a set the cbSection field to be 4 bytes too
+ // high. This code handles the more general case where the
+ // cbSection is too long for the stream. In such cases, if
+ // all the properties actually fit within the stream, the
+ // cbSection field is corrected.
+
+ if (*pcbstm < _oSection + psh->cbSection)
+ {
+ // We'll fix this problem by adjusting the cbSection
+ // value. We have to be careful, though,
+ // that the entire section fits within this new cbSection
+ // value. For efficiency, we'll just find the property
+ // which is at the highest offset, and verify that it's
+ // within the new section size.
+
+ // Get what we think is the actual section length.
+ ULONG cbSectionActual = *pcbstm - _oSection;
+
+ ULONG dwHighestOffset = 0;
+ ULONG cbProperty;
+
+ // Find the property with the highest offset.
+
+ for ( ; ppo < ppoMax; ppo++)
+ {
+ if( ppo->dwOffset > dwHighestOffset )
+ dwHighestOffset = ppo->dwOffset;
+ }
+
+ // How long is this property?
+
+ cbProperty = PropertyLengthNoEH(
+ // Pointer to property
+ (SERIALIZEDPROPERTYVALUE *)
+ _MapOffsetToAddress(dwHighestOffset),
+ // Bytes between above ptr & end of stream
+ *pcbstm - _oSection - dwHighestOffset,
+ 0, // Flags
+ pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // Does this property fit within the section? If so, then fix this
+ // property set.
+
+ if( dwHighestOffset + DwordAlign(cbProperty) <= cbSectionActual )
+ {
+ psh->cbSection = dwHighestOffset + DwordAlign(cbProperty);
+ }
+ else
+ {
+ StatusCorruption(pstatus, "SumInfo cbSection is too long for the Stream.");
+ }
+
+ } // if (*pcbstm < _oSection + psh->cbSection)
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+
+} // CPropertySetStream::_FixSummaryInformation()
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_FixPackedPropertySet
+//
+// Synopsis: Align the memory image of a propset.
+//
+// Algorithm: We need to move the properties within the
+// property set so that they are properly aligned,
+// and we need to adjust the PID/Offset array accordingly.
+// This is complicated by the fact that we may have to
+// grow some propertes (which are not properly padded
+// for alignement) and at the same time we may have to
+// shrink some properties (which are over-padded).
+//
+// To handle these two constraints, and to
+// avoid growing the underlying stream any more
+// than necessary, we process the property set in
+// two phases. In the Compaction phase, we shrink
+// properties which are over-padded. In the Expansion
+// phase, we grow properties which are under-padded.
+// For example, say we have a property set with 3
+// properties, all of which should be 4 bytes. But
+// say they are currently 2, 4, and 6 bytes. Thus
+// we must grow the first property, hold the second
+// constant, and shrink the third property. In this
+// example, after the Compaction phase, the 3 properties
+// will be 2, 4, and 4 bytes. After the Expansion phase,
+// the properties will be 4, 4, and 4 bytes.
+//
+// To do all of this, we make a copy of the PID/Offset
+// array (apoT) and sort it. We then proceed to make
+// two arrays of just offsets (no PIDs) - aopropShrink
+// and aopropFinal. aopropShrink holds the offset for
+// each property after the Compaction phase. aopropFinal
+// holds the offset for each property after the
+// Expansion phase. (Note that each of these phases
+// could be skipped if they aren't necessary.)
+//
+// Finally, we perform the Compaction and Expansion,
+// using aopropShrink and aopropFinal, respectively,
+// as our guide.
+//
+// Arguments: [pstatus] -- Pointer to NTSTATUS code.
+//
+// Returns: None
+//---------------------------------------------------------------------------
+
+INT _CRTAPI1 fnOffsetCompare(VOID const *ppo1, VOID const *ppo2);
+
+// DocumentSummaryInformation special case properties (w/packed vector elements)
+#define PID_HEADINGPAIR 0x0000000c // heading pair (VT_VECTOR | VT_VARIANT):
+ // {VT_LPSTR, VT_I4} pairs
+#define PID_DOCPARTS 0x0000000d // docparts (VT_VECTOR | VT_LPSTR)
+//#define PID_HLINKS 0x00000015 // hlinks vector
+
+VOID
+CPropertySetStream::_FixPackedPropertySet(OUT NTSTATUS *pstatus)
+{
+ // ------
+ // Locals
+ // ------
+
+ BOOLEAN fPacked = FALSE;
+ BOOLEAN fDocSummaryInfo = FALSE;
+#if DBGPROP
+ BOOLEAN fExpandDocSummaryInfo = FALSE;
+#endif
+ PROPERTYSECTIONHEADER *psh = NULL;
+ PROPERTYIDOFFSET *ppoT, *ppoTMax;
+ PROPERTYIDOFFSET *ppo, *ppoBase, *ppoMax;
+
+ PROPERTYIDOFFSET *apoT = NULL;
+
+ ULONG *aopropShrink = NULL;
+ ULONG *aopropFinal = NULL;
+ ULONG cbprop;
+ ULONG cCompact, cExpand;
+ ULONG *poprop = NULL;
+
+#if i386 == 0
+ SERIALIZEDPROPERTYVALUE *ppropbuf = NULL;
+ ULONG cbpropbuf = 0;
+#endif
+
+ ULONG cbtotal = 0;
+
+ // -----
+ // Begin
+ // -----
+
+ *pstatus = STATUS_SUCCESS;
+
+ // Determine if this is the first section of the DocSumInfo
+ // property set.
+ if ((_State & (CPSS_USERDEFINEDPROPERTIES | CPSS_DOCUMENTSUMMARYINFO)) ==
+ CPSS_DOCUMENTSUMMARYINFO)
+ {
+ fDocSummaryInfo = TRUE;
+ }
+
+ // Get pointers into this section's header.
+ psh = _LoadPropertyOffsetPointers(&ppoBase, &ppoMax, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // We know it's packed if the section-length isn't aligned.
+ fPacked = !IsDwordAligned(psh->cbSection);
+
+ // If we don't already know it's packed, check each of the properties in
+ // the PID/Offset array to see if one is not properly aligned, if so we'll
+ // assume that it's packed. Also, if this is an Ansi DocSumInfo property set,
+ // (first section), we'll assume that the HeadingPair and DocParts properties
+ // are packed (vectors).
+
+ if (!fPacked && psh != NULL)
+ {
+ for (ppo = ppoBase; ppo < ppoMax; ppo++)
+ {
+ if ( !IsDwordAligned(ppo->dwOffset)
+ ||
+ ( fDocSummaryInfo
+ &&
+ _CodePage != CP_WINUNICODE
+ &&
+ ( ppo->propid == PID_HEADINGPAIR
+ ||
+ ppo->propid == PID_DOCPARTS
+ )
+ )
+ )
+ {
+ fPacked = TRUE;
+ break;
+ }
+ }
+ }
+
+ // ----------------------------------------------------
+ // Fix the properties if they are packed or if there is
+ // unnecessary padding.
+ // ----------------------------------------------------
+
+ // If we know there's a problem, set a _State flag
+ // now. If we can fix the problem below, we'll clear it.
+ // Otherwise, the rest of the Class will know that there's
+ // an unresolved problem.
+
+ if (fPacked)
+ {
+ DebugTrace(0, DEBTRACE_PROPPATCH, (
+ "_FixPackedPropertySet: packed properties\n"));
+ _State |= CPSS_PACKEDPROPERTIES;
+ }
+
+
+ // ---------------------------------------------------------
+ // Create apoT (a sorted array of PID/Offsets), aopropShrink
+ // (the offsets for the Compaction phase) and aopropFinal
+ // (the offsets for the Expansion phase).
+ // ---------------------------------------------------------
+
+ // Create a buffer for a temporary PID/Offset array.
+
+ apoT = newk(mtPropSetStream, NULL) PROPERTYIDOFFSET[psh->cProperties + 1];
+ if (apoT == NULL)
+ {
+ *pstatus = STATUS_NO_MEMORY;
+ goto Exit;
+ }
+
+ // Copy the PID/offset pairs from the property set to the
+ // temporary PID/Offset array.
+
+ RtlCopyMemory(
+ apoT,
+ psh->rgprop,
+ psh->cProperties * CB_PROPERTYIDOFFSET);
+
+ // Mark the end of the temporary array.
+
+ ppoTMax = apoT + psh->cProperties;
+ ppoTMax->propid = PID_ILLEGAL;
+ ppoTMax->dwOffset = psh->cbSection;
+
+ // Sort the PID/Offset array by offset and check for overlapping values:
+
+ qsort(apoT, psh->cProperties, sizeof(apoT[0]), fnOffsetCompare);
+
+ // Create two arrays which will hold property offsets.
+ // aopropShrink holds the offsets for the Compaction phase where
+ // we shrink the property set. aopropFinal holds the offsets
+ // of the final property set, which will be achieved in the
+ // Expansion phase.
+
+ aopropShrink = newk(mtPropSetStream, NULL) ULONG[psh->cProperties + 1];
+ if (aopropShrink == NULL)
+ {
+ *pstatus = STATUS_NO_MEMORY;
+ goto Exit;
+ }
+
+ aopropFinal = newk(mtPropSetStream, NULL) ULONG[psh->cProperties + 1];
+ if (aopropFinal == NULL)
+ {
+ *pstatus = STATUS_NO_MEMORY;
+ goto Exit;
+ }
+
+#if i386 == 0
+ // On non-x86 machines, we can't directly access unaligned
+ // properties. So, allocate enough (aligned) memory to hold
+ // the largest unaligned property. We'll copy properties here
+ // when we need to access them.
+
+ for (ppoT = apoT; ppoT < ppoTMax; ppoT++)
+ {
+ if (!IsDwordAligned(ppoT->dwOffset))
+ {
+ cbprop = DwordAlign(ppoT[1].dwOffset - ppoT->dwOffset);
+ if (cbpropbuf < cbprop)
+ {
+ cbpropbuf = cbprop;
+ }
+ }
+ }
+
+ if (cbpropbuf != 0)
+ {
+ ppropbuf = (SERIALIZEDPROPERTYVALUE *)
+ newk(mtPropSetStream, NULL) BYTE[cbpropbuf];
+ if (ppropbuf == NULL)
+ {
+ *pstatus = STATUS_NO_MEMORY;
+ goto Exit;
+ }
+ }
+#endif // i386==0
+
+
+ // ----------------------------------------------
+ // Iterate through the properties, filling in the
+ // entries of aopropShrink and aopropFinal.
+ // ----------------------------------------------
+
+ // We'll also count the number of compacts and expands
+ // necessary.
+
+ aopropShrink[0] = aopropFinal[0] = apoT[0].dwOffset;
+ PROPASSERT(IsDwordAligned(aopropShrink[0]));
+ cExpand = 0;
+ cCompact = 0;
+
+ for (ppoT = apoT; ppoT < ppoTMax; ppoT++)
+ {
+ SERIALIZEDPROPERTYVALUE *pprop;
+ BOOLEAN fDocSumLengthComputed = FALSE;
+ ULONG cbpropOriginal;
+
+ // How much space does the property take up in the current
+ // property set?
+
+ cbpropOriginal = cbprop = ppoT[1].dwOffset - ppoT->dwOffset;
+ pprop = (SERIALIZEDPROPERTYVALUE *)
+ _MapOffsetToAddress(ppoT->dwOffset);
+
+#if i386 == 0
+ // If necessary, put this property into an aligned buffer.
+
+ if (!IsDwordAligned(ppoT->dwOffset))
+ {
+ DebugTrace(0, Dbg, (
+ "_FixPackedPropertySet: unaligned pid=%x off=%x\n",
+ ppoT->propid,
+ ppoT->dwOffset));
+ PROPASSERT(DwordAlign(cbprop) <= cbpropbuf);
+ RtlCopyMemory((VOID *) ppropbuf, pprop, cbprop);
+ pprop = ppropbuf;
+ }
+#endif
+ // Calculate the actual length of this property, including
+ // the necessary padding. This might be bigger than the
+ // property's current length (if the propset wasn't properly
+ // padded), and it might be smaller than the property's current
+ // length (if the propset was over-padded).
+
+ if (ppoT->propid == PID_DICTIONARY)
+ {
+ // Get the size of the dictionary.
+
+ cbprop = DwordAlign(_DictionaryLength(
+ (DICTIONARY const *) pprop,
+ cbprop,
+ pstatus));
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+ else
+ {
+ ULONG cbpropT;
+
+ // Ansi DocSumInfo property sets have two vector properties
+ // which are packed. If this is one of those properties,
+ // we won't fix it yet, but we'll compute the size required
+ // when the elements are un-packed.
+
+ if (fDocSummaryInfo && _CodePage != CP_WINUNICODE)
+ {
+ if (ppoT->propid == PID_HEADINGPAIR)
+ {
+ fDocSumLengthComputed = _FixHeadingPairVector(
+ PATCHOP_COMPUTESIZE,
+ pprop,
+ &cbpropT);
+ }
+ else
+ if (ppoT->propid == PID_DOCPARTS)
+ {
+ fDocSumLengthComputed = _FixDocPartsVector(
+ PATCHOP_COMPUTESIZE,
+ pprop,
+ &cbpropT);
+ }
+ }
+
+ // If we computed a length above, use it, otherwise calculate
+ // the length using the standard rules (we've already checked
+ // for the special cases).
+
+ if (fDocSumLengthComputed)
+ {
+ cbprop = cbpropT;
+#if DBGPROP
+ fExpandDocSummaryInfo = TRUE;
+#endif
+ }
+ else
+ {
+ cbprop = PropertyLengthNoEH(pprop, DwordAlign(cbprop), 0, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+
+ } // if (ppoT->propid == PID_DICTIONARY) ... else
+
+ PROPASSERT(IsDwordAligned(cbprop));
+
+ // Now that we know the actual cbprop, use it to update the
+ // *next* entry in the two arrays of correct offsets.
+ //
+ // We want aopropFinal to hold the final, correct offsets,
+ // so we'll use cbprop to calculate this array.
+ // But for aopropShrink, we only want it to differ from
+ // the original array (apoT) when a property is shrinking,
+ // so we'll use min(cbNew,cbOld) for this array.
+
+ poprop = &aopropShrink[ ppoT - apoT ]; // 1st do aopropShrink
+ poprop[1] = poprop[0] + min(cbprop, cbpropOriginal);
+
+ poprop = &aopropFinal[ ppoT - apoT ]; // 2nd do aopropFinal
+ poprop[1] = poprop[0] + cbprop;
+
+ DebugTrace(0, Dbg, (
+ "_FixPackedPropertySet: pid=%x off=%x->%x\n",
+ ppoT->propid,
+ ppoT->dwOffset,
+ poprop[0],
+ poprop[0] < ppoT->dwOffset?
+ " (compact)" :
+ poprop[0] > ppoT->dwOffset? " (expand)" : ""));
+
+
+ // Is this compaction or an expansion?
+ // If we computed the doc-sum length, we count it as
+ // an expansion, even if the total property size didn't change,
+ // because we need the expand the elements within the vector.
+
+ if (cbprop < cbpropOriginal)
+ {
+ cCompact++;
+ }
+ else
+ if (cbprop > cbpropOriginal || fDocSumLengthComputed)
+ {
+ cExpand++;
+ }
+ } // for (ppoT = apoT; ppoT < ppoTMax; ppoT++)
+
+
+ // -------------------------------
+ // Compact/Expand the Property Set
+ // -------------------------------
+
+ // We've now generated the complete aopropShrink and aopropFinal
+ // offset arrays. Now, if necessary, let's expand and/or compact
+ // the property set to match these offsets.
+
+ if (cExpand || cCompact)
+ {
+ ULONG cbstm;
+ LONG cbdelta;
+
+ cbstm = _oSection + psh->cbSection + _cbTail;
+ cbdelta = aopropFinal[psh->cProperties] - psh->cbSection;
+
+ DebugTrace(0, Dbg, (
+ "_FixPackedPropertySet: cbstm=%x cbdelta=%x cexpand=%x ccompact=%x\n",
+ cbstm,
+ cbdelta,
+ cExpand,
+ cCompact));
+
+ // -----------------------------
+ // Grow the Stream if necessary.
+ // -----------------------------
+
+ if (cbdelta > 0)
+ {
+ DebugTrace(0, Dbg, (
+ "SetSize(%x) _FixPackedPropertySet grow %x bytes\n",
+ cbstm + cbdelta,
+ cbdelta));
+
+ // On the set-size, say that this is a non-persistent
+ // change, so that the underlying Stream isn't modified.
+ // At this point, we don't know if this change should remain
+ // permanent (if the caller closes without making any changes
+ // the file should remain un-changed).
+
+ _MSTM(SetSize)(
+ cbstm + cbdelta,
+ FALSE, // Not persistent
+ (VOID **) &_pph,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // reload all pointers into mapped image:
+
+ psh = _LoadPropertyOffsetPointers(&ppoBase, &ppoMax, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // If there's another section after this one, move it back
+ // to the end of the stream now, which will create room for
+ // our expansion.
+
+ if (_cbTail != 0)
+ {
+ VOID *pvSrc = _MapAbsOffsetToAddress(cbstm - _cbTail);
+
+ PropMoveMemory(
+ "_FixPackedPropertySet(_cbTail:grow)",
+ psh,
+ Add2Ptr(pvSrc, cbdelta),
+ pvSrc,
+ _cbTail);
+ }
+ } // if (cbdelta > 0)
+
+ // This previous step (growing the Stream), was the last one which can
+ // fail. We're about to modify the actual property set (we've been
+ // working only with temporary buffers so far). So we're always guaranteed
+ // a good property set, or the original set, we'll never end up with a
+ // half-updated set.
+
+
+ // ----------------
+ // Compaction Phase
+ // ----------------
+
+ // Compact the property set if necessary. I.e., adjust
+ // the property set buffer so that it matches aopropShrink.
+
+ if (cCompact > 0)
+ {
+ // Start at the beginning and move each property up.
+
+ poprop = aopropShrink;
+ for (ppoT = apoT; ppoT < ppoTMax; ppoT++, poprop++)
+ {
+ if (*poprop != ppoT->dwOffset)
+ {
+ PROPASSERT(*poprop < ppoT->dwOffset);
+ PROPASSERT(poprop[1] > *poprop);
+
+ // We're compacting; the property should not grow!
+
+ PROPASSERT(
+ poprop[1] - *poprop <=
+ ppoT[1].dwOffset - ppoT->dwOffset);
+
+ PropMoveMemory(
+ "_FixPackedPropertySet(compact)",
+ psh,
+ Add2Ptr(psh, *poprop),
+ Add2Ptr(psh, ppoT->dwOffset),
+ poprop[1] - *poprop);
+ }
+ } // for (ppoT = apoT; ppoT < ppoTMax; ppoT++, poprop++)
+ } // if (cCompact > 0)
+
+
+ // ---------------
+ // Expansion phase
+ // ---------------
+
+ // Recall that, whether or not we just did a compaction, aopropShrink
+ // holds the property set offsets as they currently exist in the
+ // property set.
+
+ if (cExpand > 0)
+ {
+ // Start at the end and move each property back.
+ // The 'poprop' gives us the final correct offset
+ // of the current property.
+
+ LONG lOffsetIndex;
+ poprop = &aopropFinal[psh->cProperties - 1];
+
+ // Start at the second-to-last entry in the arrays of offsets
+ // (the last entry is an artificially added one to mark the end of the
+ // property set).
+
+ for (lOffsetIndex = ppoTMax - apoT - 1, ppoT = ppoTMax - 1;
+ lOffsetIndex >=0;
+ lOffsetIndex--, poprop--, ppoT--)
+ {
+ // Get a pointer to the final location of this
+ // property.
+
+ SERIALIZEDPROPERTYVALUE *pprop;
+ pprop = (SERIALIZEDPROPERTYVALUE *)
+ Add2Ptr(psh, *poprop);
+
+ if (*poprop != aopropShrink[ lOffsetIndex ])
+ {
+ ULONG cbCopy, cbOld;
+
+ PROPASSERT(*poprop > aopropShrink[ lOffsetIndex ]);
+ PROPASSERT(poprop[1] > *poprop);
+ PROPASSERT(aopropShrink[ lOffsetIndex+1 ] > aopropShrink[ lOffsetIndex ]);
+
+ // How many bytes should we copy? The minimum size of the property
+ // calculated using the old and new offsets.
+
+ cbCopy = poprop[1] - poprop[0];
+ cbOld = aopropShrink[ lOffsetIndex+1 ]
+ - aopropShrink[ lOffsetIndex+0 ];
+
+ if (cbCopy > cbOld)
+ {
+ cbCopy = cbOld;
+ }
+
+ // Copy the property from its old location
+ // (psh+aopropShrink[lOffsetIndex]) to its new location
+ // (pprop == psh+*poprop).
+
+ DebugTrace(0, DEBTRACE_PROPPATCH, (
+ "_FixPackedPropertySet:move pid=%x off=%x->%x "
+ "cb=%x->%x cbCopy=%x z=%x @%x\n",
+ ppoT->propid,
+ ppoT->dwOffset,
+ *poprop,
+ cbOld,
+ poprop[1] - *poprop,
+ cbCopy,
+ DwordRemain(cbCopy),
+ _MapAddressToOffset(Add2Ptr(pprop, cbCopy))));
+
+ PropMoveMemory(
+ "_FixPackedPropertySet(expand)",
+ psh,
+ pprop,
+ Add2Ptr(psh, aopropShrink[ lOffsetIndex ]),
+ cbCopy);
+ RtlZeroMemory(
+ Add2Ptr(pprop, cbCopy),
+ DwordRemain(cbCopy));
+
+ } // if (*poprop != ppoT->dwOffset)
+
+ // If this is an older DocSumInfo property set,
+ // and this property is one of the vector values,
+ // we must expand the vector elements now that we've
+ // room for it.
+
+ if (fDocSummaryInfo && _CodePage != CP_WINUNICODE)
+ {
+ ULONG cbpropT;
+
+ if (ppoT->propid == PID_HEADINGPAIR)
+ {
+ _FixHeadingPairVector(
+ PATCHOP_EXPAND,
+ pprop,
+ &cbpropT);
+ }
+ else
+ if (ppoT->propid == PID_DOCPARTS)
+ {
+ _FixDocPartsVector(
+ PATCHOP_EXPAND,
+ pprop,
+ &cbpropT);
+ }
+ } // if (fDocSummaryInfo)
+ } // for (ppoT = ppoTMax; --ppoT >= apoT; popropNew--)
+ } // if (cExpand != 0)
+
+
+
+ // ---------------------------------------------------------
+ // Patch the section size and the moved properties' offsets.
+ // ---------------------------------------------------------
+
+ DebugTrace(0, DEBTRACE_PROPPATCH, (
+ "_FixPackedPropertySet: Patch section size %x->%x\n",
+ psh->cbSection,
+ psh->cbSection + cbdelta));
+
+ psh->cbSection += cbdelta;
+
+ // Iterate through the original PID/Offset array to update the
+ // offsets.
+
+ for (ppo = ppoBase; ppo < ppoMax; ppo++)
+ {
+ // Search the temporary PID/Offset array (which has the updated
+ // offsets) for ppo->propid.
+
+ for (ppoT = apoT; ppoT < ppoTMax; ppoT++)
+ {
+ if (ppo->propid == ppoT->propid)
+ {
+ // We've found ppo->propid in the temporary PID/Offset
+ // array. Copy the offset value from the temporary array
+ // to the actual array in the property set.
+
+ PROPASSERT(ppo->dwOffset == ppoT->dwOffset);
+ ppo->dwOffset = aopropFinal[ppoT - apoT];
+#if DBGPROP
+ if (ppo->dwOffset != ppoT->dwOffset)
+ {
+ DebugTrace(0, DEBTRACE_PROPPATCH, (
+ "_FixPackedPropertySet: Patch propid %x"
+ " offset=%x->%x\n",
+ ppo->propid,
+ ppoT->dwOffset,
+ ppo->dwOffset));
+ } // if (ppo->dwOffset != ppoT->dwOffset)
+#endif
+ break;
+
+ } // if (ppo->propid == ppoT->propid)
+ } // for (ppoT = apoT; ppoT < ppoTMax; ppoT++)
+ } // for (ppo = ppoBase; ppo < ppoMax; ppo++)
+
+ // ------------
+ // Fix the tail
+ // ------------
+
+
+ // If we have a tail, fix it's offset in the FmtID/Offset
+ // array. Also, if we've overall shrunk this section, bring
+ // the tail in accordingly.
+
+ if (_cbTail != 0)
+ {
+ if (cbdelta < 0)
+ {
+ VOID *pvSrc = _MapAbsOffsetToAddress(cbstm - _cbTail);
+
+ PropMoveMemory(
+ "_FixPackedPropertySet(_cbTail:shrink)",
+ psh,
+ Add2Ptr(pvSrc, cbdelta),
+ pvSrc,
+ _cbTail);
+ }
+
+ _PatchSectionOffsets(cbdelta);
+
+ } // if (_cbTail != 0)
+
+
+ // If we get to this point we've successfully un-packed (or
+ // un-over-padded) the property set, so we can clear the
+ // state flag.
+
+ _State &= ~CPSS_PACKEDPROPERTIES;
+
+ } // if (cExpand || cCompact)
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ delete [] apoT;
+ delete [] aopropShrink;
+ delete [] aopropFinal;
+
+#if i386 == 0
+ delete [] (BYTE *) ppropbuf;
+#endif // i386
+
+} // CPropertySetStream::_FixPackedPropertySet()
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_FixDocPartsVector
+//
+// Synopsis: Align the memory image of a DocParts vector
+// The DocParts property is part of the DocSumInfo
+// property set (first section). It is a vector
+// of strings, and in Ansi property sets it's packed
+// and must be un-packed.
+//
+// Arguments: [PatchOp] -- patch request
+// [pprop] -- property value to be patched or sized
+// [pcbprop] -- pointer to computed property length
+//
+// Returns: TRUE if property type and all elements meet expectations;
+// FALSE on error
+//
+// Note: Operate on a DocumentSummaryInformation first section property,
+// PID_DOCPARTS. This property is assumed to be an array of
+// VT_LPSTRs.
+//
+// PATCHOP_COMPUTESIZE merely computes the size required to unpack
+// the property, and must assume it is currently unaligned.
+//
+// PATCHOP_ALIGNLENGTHS patches all VT_LPSTR lengths to DWORD
+// multiples, and may rely on the property already being aligned.
+//
+// PATCHOP_EXPAND expands the property from the Src to Dst buffer,
+// moving elements to DWORD boundaries, and patching VT_LPSTR
+// lengths to DWORD multiples. The Src buffer is assumed to be
+// unaligned, and the Dst buffer is assumed to be properly sized.
+//---------------------------------------------------------------------------
+
+BOOLEAN
+CPropertySetStream::_FixDocPartsVector(
+ IN PATCHOP PatchOp,
+ IN OUT SERIALIZEDPROPERTYVALUE *pprop,
+ OUT ULONG *pcbprop)
+{
+ PROPASSERT(
+ PatchOp == PATCHOP_COMPUTESIZE ||
+ PatchOp == PATCHOP_ALIGNLENGTHS ||
+ PatchOp == PATCHOP_EXPAND);
+ PROPASSERT(pprop != NULL);
+ PROPASSERT(pcbprop != NULL);
+
+ // If the property is a variant vector,
+ // it's in an ANSI property set, and
+ // there are an even number of elements, ...
+
+ if ( PropByteSwap(pprop->dwType) == (VT_VECTOR | VT_LPSTR)
+ &&
+ _CodePage != CP_WINUNICODE)
+ {
+ ULONG cString;
+ VOID *pv;
+
+ cString = PropByteSwap( *(DWORD *) pprop->rgb );
+ pv = Add2Ptr(pprop->rgb, sizeof(DWORD));
+
+ if (_FixDocPartsElements(PatchOp, cString, pv, pv, pcbprop))
+ {
+ *pcbprop += CB_SERIALIZEDPROPERTYVALUE + sizeof(ULONG);
+ return(TRUE);
+ }
+ }
+ return(FALSE); // Not a recognizable DocParts vector
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_FixDocPartsElements
+//
+// Synopsis: Recursively align the memory image of DocParts elements
+//
+// Arguments: [PatchOp] -- patch request
+// [cString] -- count of strings remaining in the vector
+// [pvDst] -- aligned overlapping destination buffer
+// [pvSrc] -- unaligned overlapping source buffer
+// [pcbprop] -- pointer to computed property length
+//
+// Returns: TRUE if all remaining elements meet expectations;
+// FALSE on error
+//
+// Note: The pvDst & pvSrc buffers must be in property-set
+// byte order (little endian).
+//---------------------------------------------------------------------------
+
+BOOLEAN
+CPropertySetStream::_FixDocPartsElements(
+ IN PATCHOP PatchOp,
+ IN ULONG cString,
+ OUT VOID *pvDst,
+ IN VOID UNALIGNED const *pvSrc,
+ OUT ULONG *pcbprop)
+{
+ ULONG cb;
+
+ PROPASSERT(
+ PatchOp == PATCHOP_COMPUTESIZE ||
+ PatchOp == PATCHOP_ALIGNLENGTHS ||
+ PatchOp == PATCHOP_EXPAND);
+ PROPASSERT(pvDst >= pvSrc);
+ PROPASSERT(PatchOp != PATCHOP_ALIGNLENGTHS || pvDst == pvSrc);
+
+ if (cString == 0)
+ {
+ *pcbprop = 0;
+ return(TRUE);
+ }
+ cb = sizeof(DWORD) + PropByteSwap( *(DWORD UNALIGNED *) pvSrc );
+
+ // If the caller serialized the vector properly, all we need to do is
+ // to round up the string lengths to DWORD multiples, so readers that
+ // treat these vectors as byte-aligned get faked out. We expect
+ // readers will not have problems with a DWORD aligned length, and a
+ // '\0' character a few bytes earlier than the length indicates.
+
+ if (PatchOp == PATCHOP_ALIGNLENGTHS)
+ {
+ cb = DwordAlign(cb); // Caller says it's already aligned
+ }
+ if (_FixDocPartsElements(
+ PatchOp,
+ cString - 1,
+ Add2Ptr(pvDst, DwordAlign(cb)),
+ (VOID UNALIGNED const *) Add2ConstPtr(pvSrc, cb),
+ pcbprop))
+ {
+ *pcbprop += DwordAlign(cb);
+
+ if (PatchOp == PATCHOP_EXPAND)
+ {
+ PropMoveMemory(
+ "_FixDocPartsElements",
+ _GetSectionHeader(),
+ pvDst,
+ pvSrc,
+ cb);
+ RtlZeroMemory(Add2Ptr(pvDst, cb), DwordRemain(cb));
+
+ DebugTrace(0, DEBTRACE_PROPPATCH, (
+ "_FixDocPartsElements: Move(%x:%s) "
+ "cb=%x->%x off=%x->%x z=%x @%x\n",
+ cString,
+ Add2Ptr(pvDst, sizeof(ULONG)),
+ cb - sizeof(ULONG),
+ DwordAlign(cb) - sizeof(ULONG),
+ _MapAddressToOffset(pvSrc),
+ _MapAddressToOffset(pvDst),
+ DwordRemain(cb),
+ _MapAddressToOffset(Add2Ptr(pvDst, cb))));
+ }
+ if (PatchOp != PATCHOP_COMPUTESIZE)
+ {
+ PROPASSERT(
+ PatchOp == PATCHOP_ALIGNLENGTHS ||
+ PatchOp == PATCHOP_EXPAND);
+
+ DebugTrace(0, DEBTRACE_PROPPATCH, (
+ "_FixDocPartsElements: Patch(%x:%s) cb=%x->%x\n",
+ cString,
+ Add2Ptr(pvDst, sizeof(ULONG)),
+ *(ULONG *) pvDst,
+ DwordAlign(*(ULONG *) pvDst)));
+
+ *(ULONG *) pvDst = PropByteSwap( DwordAlign( PropByteSwap( *(ULONG *) pvDst )));
+ }
+ return(TRUE);
+ }
+ return(FALSE); // Not a recognizable DocParts vector
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_FixHeadingPairVector
+//
+// Synopsis: Align the memory image of a HeadingPair vector.
+// The HeadingPair property is part of the DocSumInfo
+// property set (first section). It's a vector of
+// Variants, where the elements are alternating
+// strings and I4s (the string is a heading name,
+// and the I4 is the count of DocumentParts in that
+// heading). In Ansi property sets, these elements
+// are packed, and must be un-packed.
+//
+// Arguments: [PatchOp] -- patch request
+// [pprop] -- property value to be patched or sized
+// [pcbprop] -- pointer to computed property length
+//
+// Returns: TRUE if property and all elements meet expectations;
+// FALSE on error
+//
+// Note: Operate on a DocumentSummaryInformation first section property,
+// PID_HEADINGPAIR. This property is assumed to be an array of
+// VT_VARIANTs with an even number of elements. Each pair must
+// consist of a VT_LPSTR followed by a VT_I4.
+//
+// PATCHOP_COMPUTESIZE merely computes the size required to unpack
+// the property, and must assume it is currently unaligned.
+//
+// PATCHOP_ALIGNLENGTHS patches all VT_LPSTR lengths to DWORD
+// multiples, and may rely on the property already being aligned.
+//
+// PATCHOP_EXPAND expands the property from the Src to Dst buffer,
+// moving elements to DWORD boundaries, and patching VT_LPSTR
+// lengths to DWORD multiples. The Src buffer is assumed to be
+// unaligned, and the Dst buffer is assumed to be properly sized.
+//---------------------------------------------------------------------------
+
+BOOLEAN
+CPropertySetStream::_FixHeadingPairVector(
+ IN PATCHOP PatchOp,
+ IN OUT SERIALIZEDPROPERTYVALUE *pprop,
+ OUT ULONG *pcbprop)
+{
+ ULONG celem;
+ ULONG cbprop = 0;
+
+ PROPASSERT(
+ PatchOp == PATCHOP_COMPUTESIZE ||
+ PatchOp == PATCHOP_ALIGNLENGTHS ||
+ PatchOp == PATCHOP_EXPAND);
+ PROPASSERT(pprop != NULL);
+ PROPASSERT(pcbprop != NULL);
+
+ // If the property is a variant vector, and
+ // there are an even number of elements, ...
+
+ if( PropByteSwap(pprop->dwType) == (VT_VECTOR | VT_VARIANT)
+ &&
+ ( (celem = PropByteSwap(*(ULONG *) pprop->rgb) ) & 1) == 0
+ &&
+ _CodePage != CP_WINUNICODE)
+ {
+ pprop = (SERIALIZEDPROPERTYVALUE *) Add2Ptr(pprop->rgb, sizeof(ULONG));
+
+ if (_FixHeadingPairElements(PatchOp, celem/2, pprop, pprop, pcbprop))
+ {
+ *pcbprop += CB_SERIALIZEDPROPERTYVALUE + sizeof(ULONG);
+ return(TRUE);
+ }
+ }
+ return(FALSE); // Not a recognizable HeadingPair vector
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_FixHeadingPairElements
+//
+// Synopsis: Recursively align the memory image of HeadingPair elements
+//
+// Arguments: [PatchOp] -- patch request
+// [cPairs] -- count of heading pairs remaining
+// [ppropDst] -- aligned overlapping destination buffer
+// [ppropSrc] -- unaligned overlapping source buffer
+// [pcbprop] -- pointer to computed property length
+//
+// Returns: TRUE if all remaining elements meet expectations;
+// FALSE on error
+//---------------------------------------------------------------------------
+
+BOOLEAN
+CPropertySetStream::_FixHeadingPairElements(
+ IN PATCHOP PatchOp,
+ IN ULONG cPairs,
+ OUT SERIALIZEDPROPERTYVALUE *ppropDst,
+ IN SERIALIZEDPROPERTYVALUE UNALIGNED const *ppropSrc,
+ OUT ULONG *pcbprop)
+{
+ PROPASSERT(
+ PatchOp == PATCHOP_COMPUTESIZE ||
+ PatchOp == PATCHOP_ALIGNLENGTHS ||
+ PatchOp == PATCHOP_EXPAND);
+ PROPASSERT(ppropDst >= ppropSrc);
+ PROPASSERT(PatchOp != PATCHOP_ALIGNLENGTHS || ppropDst == ppropSrc);
+
+ if (cPairs == 0)
+ {
+ *pcbprop = 0;
+ return(TRUE);
+ }
+
+ // If the first element of the pair is a VT_LPSTR, ...
+
+ if( PropByteSwap(ppropSrc->dwType) == VT_LPSTR )
+ {
+ ULONG cb;
+
+ // Compute size of the string element.
+
+ cb = CB_SERIALIZEDPROPERTYVALUE
+ +
+ sizeof(ULONG)
+ +
+ PropByteSwap( *(DWORD UNALIGNED *) ppropSrc->rgb );
+
+ // If the caller serialized the vector properly, all we need to do is
+ // to round up the string lengths to DWORD multiples, so readers that
+ // treat these vectors as byte-aligned get faked out. We expect
+ // readers will not have problems with a DWORD aligned length, and a
+ // '\0' character a few bytes earlier than the length indicates.
+
+ if (PatchOp == PATCHOP_ALIGNLENGTHS)
+ {
+ cb = DwordAlign(cb); // Caller says it's already aligned
+ }
+
+ // and if the second element of the pair is a VT_I4, ...
+
+ if ( PropByteSwap( (DWORD) VT_I4 )
+ ==
+ ( (SERIALIZEDPROPERTYVALUE UNALIGNED const *)
+ Add2ConstPtr(ppropSrc, cb)
+ )->dwType )
+ {
+ cb += CB_SERIALIZEDPROPERTYVALUE + sizeof(DWORD);
+
+ if (_FixHeadingPairElements(
+ PatchOp,
+ cPairs - 1,
+ (SERIALIZEDPROPERTYVALUE *)
+ Add2Ptr(ppropDst, DwordAlign(cb)),
+ (SERIALIZEDPROPERTYVALUE UNALIGNED const *)
+ Add2ConstPtr(ppropSrc, cb),
+ pcbprop))
+ {
+ *pcbprop += DwordAlign(cb);
+
+ if (PatchOp == PATCHOP_EXPAND)
+ {
+ // Move the unaligned VT_I4 property back in memory to an
+ // aligned boundary, move the string back to a (possibly
+ // different) aligned boundary, zero the space in between
+ // the two and patch the string length to be a DWORD
+ // multiple to fake out code that expects vector elements
+ // to be byte aligned.
+
+ // Adjust byte count to include just the string element.
+
+ cb -= CB_SERIALIZEDPROPERTYVALUE + sizeof(ULONG);
+
+ // Move the VT_I4 element.
+
+ PropMoveMemory(
+ "_FixHeadingPairElements:I4",
+ _GetSectionHeader(),
+ Add2Ptr(ppropDst, DwordAlign(cb)),
+ Add2ConstPtr(ppropSrc, cb),
+ CB_SERIALIZEDPROPERTYVALUE + sizeof(ULONG));
+
+ // Move the VT_LPSTR element.
+
+ PropMoveMemory(
+ "_FixHeadingPairElements:LPSTR",
+ _GetSectionHeader(),
+ ppropDst,
+ ppropSrc,
+ cb);
+
+ // Zero the space in between.
+
+ RtlZeroMemory(Add2Ptr(ppropDst, cb), DwordRemain(cb));
+
+ DebugTrace(0, DEBTRACE_PROPPATCH, (
+ "_FixHeadingPairElements: Move(%x:%s) "
+ "cb=%x->%x off=%x->%x z=%x @%x\n",
+ cPairs,
+ &ppropDst->rgb[sizeof(ULONG)],
+ PropByteSwap( *(ULONG *) ppropDst->rgb ),
+ DwordAlign(PropByteSwap( *(ULONG *) ppropDst->rgb )),
+ _MapAddressToOffset(ppropSrc),
+ _MapAddressToOffset(ppropDst),
+ DwordRemain(cb),
+ _MapAddressToOffset(Add2Ptr(ppropDst, cb))));
+ }
+
+ if (PatchOp != PATCHOP_COMPUTESIZE)
+ {
+ PROPASSERT(
+ PatchOp == PATCHOP_ALIGNLENGTHS ||
+ PatchOp == PATCHOP_EXPAND);
+#ifdef DBGPROP
+ SERIALIZEDPROPERTYVALUE const *ppropT =
+ (SERIALIZEDPROPERTYVALUE const *)
+ Add2Ptr(ppropDst, DwordAlign(cb));
+#endif
+ DebugTrace(0, DEBTRACE_PROPPATCH, (
+ "_FixHeadingPairElements: Patch(%x:%s) "
+ "cb=%x->%x, vt=%x, %x\n",
+ cPairs,
+ &ppropDst->rgb[sizeof(ULONG)],
+ PropByteSwap( *(ULONG *) ppropDst->rgb ),
+ DwordAlign( PropByteSwap( *(ULONG *) ppropDst->rgb )),
+ PropByteSwap( ppropT->dwType ),
+ PropByteSwap( *(ULONG *) ppropT->rgb )));
+
+ // Patch the string length to be a DWORD multiple.
+
+ *(ULONG *) ppropDst->rgb
+ = PropByteSwap( DwordAlign( PropByteSwap( *(ULONG *) ppropDst->rgb )));
+ }
+ return(TRUE);
+ }
+ }
+ }
+ return(FALSE); // Not a recognizable HeadingPair vector
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::QueryPropertySet
+//
+// Synopsis: Return the classid for the property set code
+//
+// Arguments: [pspss] -- pointer to buffer for output
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: None
+//---------------------------------------------------------------------------
+
+#ifndef KERNEL
+VOID
+CPropertySetStream::QueryPropertySet(OUT STATPROPSETSTG *pspss,
+ OUT NTSTATUS *pstatus) const
+{
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(_IsMapped());
+ PROPASSERT(PROPSET_BYTEORDER == _pph->wByteOrder);
+
+ if ((_State & CPSS_USERDEFINEDDELETED) || _cSection < 1)
+ {
+ StatusAccessDenied(pstatus, "QueryPropertySet: deleted or no section");
+ goto Exit;
+ }
+ _MSTM(QueryTimeStamps)(
+ pspss,
+ (BOOLEAN) ((_Flags & CREATEPROP_NONSIMPLE) != 0));
+ pspss->clsid = _pph->clsid;
+ pspss->fmtid = _GetFormatidOffset(
+ (_State & CPSS_USERDEFINEDPROPERTIES)? 1 : 0)->fmtid;
+ pspss->grfFlags = _CodePage == CP_WINUNICODE?
+ PROPSETFLAG_DEFAULT : PROPSETFLAG_ANSI;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+}
+#endif // !KERNEL
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::SetClassId
+//
+// Synopsis: Set the classid for the property set code
+//
+// Arguments: [pclsid] -- pointer to new ClassId
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: None
+//---------------------------------------------------------------------------
+
+#ifndef KERNEL
+VOID
+CPropertySetStream::SetClassId(IN GUID const *pclsid,
+ OUT NTSTATUS *pstatus)
+{
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(_IsMapped());
+ PROPASSERT(PROPSET_BYTEORDER == _pph->wByteOrder);
+
+ if (IsReadOnlyPropertySet(_Flags, _State))
+ {
+ StatusAccessDenied(pstatus, "SetClassId: deleted or read-only");
+ goto Exit;
+ }
+
+ _SetModified();
+ _pph->clsid = *pclsid;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+}
+#endif // KERNEL
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::EnumeratePropids
+//
+// Synopsis: enumerates the property ids in a prop set
+//
+// Arguments: [pkey] -- pointer to bookmark (0 implies beginning)
+// [pcprop] -- on input: size; on output: # of props returned.
+// [apropids] -- output buffer
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: TRUE if more properties are available
+//---------------------------------------------------------------------------
+
+#ifndef KERNEL
+BOOLEAN
+CPropertySetStream::EnumeratePropids(
+ IN OUT ULONG *pkey,
+ IN OUT ULONG *pcprop,
+ OPTIONAL OUT PROPID *apropids,
+ OUT NTSTATUS *pstatus)
+{
+ PROPERTYIDOFFSET *ppo, *ppoStart, *ppoMax;
+ ULONG cprop = 0;
+ BOOLEAN fMorePropids = FALSE;
+ PROPID propidPrev = *pkey;
+
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(_IsMapped());
+ PROPASSERT(PROPSET_BYTEORDER == _pph->wByteOrder);
+
+ if (_State & CPSS_USERDEFINEDDELETED)
+ {
+ StatusAccessDenied(pstatus, "EnumeratePropids: deleted");
+ goto Exit;
+ }
+
+ if (_LoadPropertyOffsetPointers(&ppoStart, &ppoMax, pstatus) == NULL)
+ {
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+ else
+ {
+ if (propidPrev != 0) // if not first call, start w/last propid
+ {
+ for (ppo = ppoStart; ppo < ppoMax; ppo++)
+ {
+ if (ppo->propid == propidPrev)
+ {
+ ppoStart = ++ppo;
+ break;
+ }
+ }
+ }
+ for (ppo = ppoStart; ppo < ppoMax; ppo++)
+ {
+ if (ppo->propid != PID_DICTIONARY &&
+ ppo->propid != PID_CODEPAGE &&
+ ppo->propid != PID_LOCALE)
+ {
+ if (cprop >= *pcprop)
+ {
+ fMorePropids = TRUE;
+ break;
+ }
+ if (apropids != NULL)
+ {
+ apropids[cprop] = ppo->propid;
+ }
+ cprop++;
+ propidPrev = ppo->propid;
+ }
+ }
+ }
+ *pkey = propidPrev;
+ *pcprop = cprop;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return(fMorePropids);
+}
+#endif
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_LoadPropertyOffsetPointers
+//
+// Synopsis: Load start and (past) end pointers to PROPERTYIDOFFSET array
+//
+// Arguments: [pppo] -- pointer to base of PROPERTYIDOFFSET array
+// [pppoMax] -- pointer past end of PROPERTYIDOFFSET array
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: Pointer to Section Header, NULL if section not present
+// or if there was an error.
+//---------------------------------------------------------------------------
+
+PROPERTYSECTIONHEADER *
+CPropertySetStream::_LoadPropertyOffsetPointers(
+ OUT PROPERTYIDOFFSET **pppo,
+ OUT PROPERTYIDOFFSET **pppoMax,
+ OUT NTSTATUS *pstatus)
+{
+ PROPERTYSECTIONHEADER *psh;
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(_IsMapped());
+
+ if (_cSection != 0)
+ {
+ psh = _GetSectionHeader();
+ ULONG cbstm = _MSTM(GetSize)(pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // Ensure that we can read all of the PID/Offset
+ // table.
+
+ if (cbstm < _oSection + CB_PROPERTYSECTIONHEADER ||
+ cbstm < _oSection + CB_PROPERTYSECTIONHEADER +
+ psh->cProperties * CB_PROPERTYIDOFFSET)
+ {
+ StatusCorruption(pstatus, "LoadPropertyOffsetPointers: stream size");
+ goto Exit;
+ }
+
+ *pppo = psh->rgprop;
+ *pppoMax = psh->rgprop + psh->cProperties;
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+ if( !NT_SUCCESS(*pstatus) )
+ psh = NULL;
+
+ return(psh);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_LoadProperty
+//
+// Synopsis: return a pointer to the specified property value
+//
+// Arguments: [propid] -- property id for property
+// [pcbprop] -- pointer to return property size, 0 on error
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: SERIALIZEDPROPERTYVALUE * -- NULL if not present
+//---------------------------------------------------------------------------
+
+SERIALIZEDPROPERTYVALUE *
+CPropertySetStream::_LoadProperty(
+ IN PROPID propid,
+ OUT OPTIONAL ULONG *pcbprop,
+ OUT NTSTATUS *pstatus )
+{
+ PROPERTYSECTIONHEADER const *psh;
+ PROPERTYIDOFFSET *ppo, *ppoBase, *ppoMax;
+ SERIALIZEDPROPERTYVALUE *pprop = NULL;
+
+ *pstatus = STATUS_SUCCESS;
+
+ psh = _LoadPropertyOffsetPointers(&ppoBase, &ppoMax, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if (psh != NULL)
+ {
+ for (ppo = ppoBase; ppo < ppoMax; ppo++)
+ {
+ if (IsDwordAligned(ppo->dwOffset)
+ &&
+ ppo->dwOffset >= CB_PROPERTYSECTIONHEADER
+ +
+ psh->cProperties * CB_PROPERTYIDOFFSET
+ &&
+ psh->cbSection >= ppo->dwOffset + CB_SERIALIZEDPROPERTYVALUE)
+ {
+
+ if (ppo->propid != propid)
+ {
+ continue;
+ }
+ pprop = (SERIALIZEDPROPERTYVALUE *)
+ _MapOffsetToAddress(ppo->dwOffset);
+
+ if (pcbprop != NULL)
+ {
+ ULONG cb;
+
+ cb = psh->cbSection - ppo->dwOffset;
+ if (propid == PID_DICTIONARY)
+ {
+ *pcbprop = _DictionaryLength(
+ (DICTIONARY const *) pprop,
+ cb,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+ else
+ {
+ *pcbprop = PropertyLengthNoEH(pprop, cb, 0, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+ }
+ if (pcbprop == NULL ||
+ psh->cbSection >= ppo->dwOffset + *pcbprop)
+ {
+ // Success
+ goto Exit;
+ }
+ }
+
+ pprop = NULL;
+ StatusCorruption(pstatus, "LoadProperty: property offset");
+ goto Exit;
+ }
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return(pprop);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::GetValue
+//
+// Synopsis: return a pointer to the specified property value
+//
+// Arguments: [propid] -- property id of property
+// [pcbprop] -- pointer to returned property length
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: pointer to property value
+//---------------------------------------------------------------------------
+
+SERIALIZEDPROPERTYVALUE const *
+CPropertySetStream::GetValue(
+ IN PROPID propid,
+ OUT ULONG *pcbprop,
+ OUT NTSTATUS *pstatus)
+{
+ SERIALIZEDPROPERTYVALUE *pprop = NULL;
+
+ PROPASSERT(_IsMapped());
+ PROPASSERT(PROPSET_BYTEORDER == _pph->wByteOrder);
+
+ if (_State & CPSS_USERDEFINEDDELETED)
+ {
+ StatusAccessDenied(pstatus, "GetValue: deleted");
+ goto Exit;
+ }
+ if (propid == PID_DICTIONARY)
+ {
+ DebugTrace(0, DEBTRACE_ERROR, ("GetValue: PID_DICTIONARY\n"));
+ StatusInvalidParameter(pstatus, "GetValue: PID_DICTIONARY");
+ goto Exit;
+ }
+
+ pprop = NULL;
+ if (propid == PID_SECURITY || propid == PID_MODIFY_TIME)
+ {
+ SERIALIZEDPROPERTYVALUE aprop[2];
+
+ PROPASSERT(sizeof(aprop) >= sizeof(ULONG) + sizeof(LONGLONG));
+
+ aprop[0].dwType = PropByteSwap( (DWORD) VT_EMPTY );
+ if (propid == PID_SECURITY)
+ {
+ if (_MSTM(QuerySecurity)((ULONG *) aprop[0].rgb))
+ {
+ aprop[0].dwType = PropByteSwap( (DWORD) VT_UI4 );
+ *pcbprop = 2 * sizeof(ULONG);
+ }
+ }
+ else // (propid == PID_MODIFY_TIME)
+ {
+ LONGLONG ll;
+
+ if (_MSTM(QueryModifyTime)(&ll))
+ {
+ *(LONGLONG UNALIGNED *) aprop[0].rgb = PropByteSwap( ll );
+ aprop[0].dwType = PropByteSwap( (DWORD) VT_FILETIME );
+ *pcbprop = sizeof(ULONG) + sizeof(LONGLONG);
+ }
+ }
+
+ if( VT_EMPTY != PropByteSwap(aprop[0].dwType) )
+ {
+ pprop = (SERIALIZEDPROPERTYVALUE *)
+ newk(mtPropSetStream, NULL) BYTE[*pcbprop];
+
+ if (pprop == NULL)
+ {
+ StatusNoMemory(pstatus, "GetValue: no memory");
+ goto Exit;
+ }
+ DebugTrace(0, Dbg, (
+ "GetValue: pprop=%lx, vt=%lx, cb=%lx\n",
+ pprop,
+ PropByteSwap( aprop[0].dwType ),
+ *pcbprop));
+ RtlCopyMemory(pprop, aprop, *pcbprop);
+ }
+ } // if (propid == PID_SECURITY || propid == PID_MODIFY_TIME)
+
+ else
+ {
+ pprop = _LoadProperty(propid, pcbprop, pstatus);
+ if( !NT_SUCCESS(*pstatus) )
+ {
+ pprop = NULL;
+ goto Exit;
+ }
+ } // if (propid == PID_SECURITY || propid == PID_MODIFY_TIME) ... else
+
+#if DBGPROP
+ if (pprop == NULL)
+ {
+ DebugTrace(0, Dbg, ("GetValue: propid=%lx pprop=NULL\n", propid));
+ }
+ else
+ {
+ char valbuf[CB_VALUESTRING];
+
+ DebugTrace(0, Dbg, (
+ "GetValue: propid=%lx pprop=%l" szX " vt=%hx val=%s cb=%l" szX "\n",
+ propid,
+ _MapAddressToOffset(pprop),
+ PropByteSwap( pprop->dwType ),
+ ValueToString(pprop, *pcbprop, valbuf),
+ *pcbprop));
+ }
+#endif
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return(pprop);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::SetValue
+//
+// Synopsis: update/add/delete property values
+//
+// Arguments: [cprop] -- count of properties
+// [pip] -- pointer to indirect indexes
+// [avar] -- PROPVARIANT array
+// [apinfo] -- PROPERTY_INFORMATION array
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: None
+//
+// Note: All the properties in the apinfo array can be classified into
+// one of the following categories:
+//
+// PROPOP_IGNORE:
+// No change. Deleting a non-existent property or the same
+// propid appears later in the apinfo array.
+//
+// PROPOP_DELETE:
+// Deletion of an existing property. Remove the
+// PROPERTYIDOFFSET structure from the property offset array and
+// and pack the remaining entries. Delete the property value
+// and pack remaining property values
+//
+// PROPOP_INSERT:
+// Addition of a new property. Insert the new PROPERTYIDOFFSET
+// structure at the end of the property offset array. Insert
+// the new property value at the end of the section/stream.
+//
+// PROPOP_MOVE:
+// A property whose value needs to be updated out of place
+// because of a change in the property value's size. A property
+// value is moved to the end of the section if it grows or
+// shrinks across a DWORD boundary. The existing value is
+// removed from the section and the remaining values are packed.
+// Then, the new value is inserted at the end of the section.
+// The idea here is to move variable length properties that are
+// being changed frequently as near as possible to the end of
+// the stream to minimize the cost of maintaining a packed set
+// of property values. Note that the property offset structure
+// is not moved around in the array.
+//
+// PROPOP_UPDATE:
+// A property whose value can be updated in-place. The property
+// value's new size is equal to the old size. There are a
+// number of variant types that take up a fixed amount of space,
+// e.g., VT_I4, VT_R8 etc. This would also apply to any
+// variable length property that is updated without changing
+// the property value's size across a DWORD boundary.
+//
+// Note that while the property offset array is itself packed out
+// of necessity (to conform to the spec), there may be unused
+// entries at the end of the array that are not compressed out of
+// the stream when properties are deleted. The unused space is
+// detected and reused when new properties are added later.
+//---------------------------------------------------------------------------
+
+#define CCHUNKSTACK (sizeof(ascnkStack)/sizeof(ascnkStack[0]))
+
+VOID
+CPropertySetStream::SetValue(
+ IN ULONG cprop,
+ OPTIONAL IN OUT INDIRECTPROPERTY **ppip,
+ IN PROPVARIANT const avar[],
+ IN PROPERTY_INFORMATION *apinfo,
+ OUT NTSTATUS *pstatus)
+{
+ // ------
+ // Locals
+ // ------
+
+ CStreamChunk ascnkStack[6];
+
+ ULONG cpoReserve;
+ ULONG cDelete, cInsert, cMove, cUpdate;
+
+#if DBGPROP
+ ULONG cIgnore;
+ char valbuf[CB_VALUESTRING];
+ KERNELSELECT(
+ char valbuf2[CB_VALUESTRING],
+ char varbuf[CB_VARIANT_TO_STRING]);
+#endif
+
+ ULONG iprop;
+ ULONG cbstm;
+ LONG cbChange, cbInsertMove;
+ PROPERTYSECTIONHEADER *psh;
+ int cIndirect = 0;
+ CStreamChunk *pscnk0 = NULL;
+ ULONG cbNewSize;
+
+
+ // ----------
+ // Initialize
+ // ----------
+
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(PROPSET_BYTEORDER == _pph->wByteOrder);
+
+ // Worst case, we will need chunks for:
+ // - the possible growth of the PROPERTYIDOFFSET array,
+ // - one for EACH property that is being modified,
+ // - and one chunk to mark the end of the property data.
+
+ CStreamChunkList scl(
+ 1 + cprop + 1,
+ 1 + cprop + 1 <= CCHUNKSTACK? ascnkStack : NULL);
+
+ PROPASSERT(_IsMapped());
+
+
+ // Validate that this property set can be written to.
+ if (IsReadOnlyPropertySet(_Flags, _State))
+ {
+ StatusAccessDenied(pstatus, "SetValue: deleted or read-only");
+ goto Exit;
+ }
+
+ // Mark the propset dirty.
+ _SetModified();
+
+
+ psh = _GetSectionHeader();
+
+ cpoReserve = 0;
+ cDelete = cInsert = cMove = cUpdate = 0;
+#if DBGPROP
+ cIgnore = 0;
+#endif
+ cbInsertMove = cbChange = 0;
+
+ pscnk0 = scl.GetFreeChunk(pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ pscnk0->oOld = 0;
+ pscnk0->cbChange = 0;
+ PROPASSERT(pscnk0 == scl.GetChunk(0));
+
+ cbstm = _oSection + psh->cbSection + _cbTail;
+ PROPASSERT( cbstm <= _MSTM(GetSize)(pstatus) && NT_SUCCESS(*pstatus) );
+ PROPASSERT(cbstm == _oSection + psh->cbSection + _cbTail);
+
+ // ------------------------
+ // Classify all the updates
+ // ------------------------
+
+ // Each update gets classified as ignore, delete, insert, move,
+ // or update.
+ // Lookup the old value for each of the properties specified and
+ // compute the current size.
+
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ ULONG i;
+ ULONG cbPropOld;
+ SERIALIZEDPROPERTYVALUE const *pprop = NULL;
+
+ PROPASSERT(cbstm == _oSection + psh->cbSection + _cbTail);
+
+ if (IsReadOnlyPropid(apinfo[iprop].pid))
+ {
+ if (cprop != 1 ||
+ apinfo[0].pid != PID_DICTIONARY ||
+ apinfo[0].cbprop == 0 ||
+ ( avar == NULL || avar[0].vt != VT_DICTIONARY )
+ )
+ {
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "SetValue: read-only propid=%lx\n",
+ apinfo[iprop].pid));
+ StatusInvalidParameter(pstatus, "SetValue: read-only PROPID");
+ goto Exit;
+ }
+ }
+
+ if (apinfo[iprop].pid != PID_ILLEGAL)
+ {
+ pprop = _LoadProperty(apinfo[iprop].pid, &cbPropOld, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ PROPASSERT(cbstm == _oSection + psh->cbSection + _cbTail);
+ }
+
+ // If this propid appears later in the array, ignore it.
+
+ for (i = iprop + 1; i < cprop; i++)
+ {
+ if (apinfo[i].pid == apinfo[iprop].pid)
+ {
+#if DBGPROP
+ cIgnore++;
+#endif
+ apinfo[iprop].operation = PROPOP_IGNORE;
+ break;
+ }
+ }
+
+ // If this propid appears only once or if it's the last instance,
+ // load the property and compute its size.
+
+ if (i == cprop)
+ {
+ VOID *pvStart = NULL;
+
+ PROPASSERT(cbstm == _oSection + psh->cbSection + _cbTail);
+ if (pprop != NULL)
+ {
+ ULONG cbPropNew;
+
+ PROPASSERT(apinfo[iprop].pid != PID_DICTIONARY);
+ if (apinfo[iprop].cbprop == 0)
+ {
+ DebugTrace(0, Dbg, (
+ "SetValue: Deleting propid=%lx oOld=%l" szX
+ " vt=%hx val=%s cb=%l" szX "\n",
+ apinfo[iprop].pid,
+ _MapAddressToOffset(pprop),
+ PropByteSwap( pprop->dwType ),
+ ValueToString(pprop, cbPropOld, valbuf),
+ cbPropOld));
+
+ cbPropNew = 0;
+ cDelete++;
+ apinfo[iprop].operation = PROPOP_DELETE;
+ }
+ else
+ {
+ DebugTrace(0, Dbg, (
+ "SetValue: Modifying propid=%lx oOld=%l" szX
+ " vt=%hx-->%hx cb=%l" szX "-->%l" szX " val=%s-->%s\n",
+ apinfo[iprop].pid,
+ _MapAddressToOffset(pprop),
+ PropByteSwap( pprop->dwType ),
+ KERNELSELECT(
+ PropByteSwap( apinfo[iprop].pprop->dwType ),
+ avar[iprop].vt),
+ cbPropOld,
+ apinfo[iprop].cbprop,
+ ValueToString(pprop, cbPropOld, valbuf),
+ KERNELSELECT(
+ ValueToString(
+ apinfo[iprop].pprop,
+ apinfo[iprop].cbprop,
+ valbuf2),
+ VariantToString(
+ avar[iprop],
+ varbuf,
+ sizeof( varbuf )))));
+
+ cbPropNew = apinfo[iprop].cbprop;
+ if (cbPropOld != cbPropNew)
+ {
+ cbInsertMove += apinfo[iprop].cbprop;
+ cMove++;
+ apinfo[iprop].operation = PROPOP_MOVE;
+ }
+ else
+ {
+ cUpdate++;
+ apinfo[iprop].operation = PROPOP_UPDATE;
+ }
+ }
+
+ if (apinfo[iprop].operation != PROPOP_UPDATE)
+ {
+ // Update the list of chunks that need to be adjusted
+ CStreamChunk *pscnk = scl.GetFreeChunk(pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ pscnk->oOld = _MapAddressToOffset(pprop);
+ pscnk->cbChange = - (LONG) cbPropOld;
+ }
+
+ // Stream size change
+ cbChange += cbPropNew - cbPropOld;
+ }
+
+ // Delete non-existent property:
+
+ else if (apinfo[iprop].cbprop == 0)
+ {
+#if DBGPROP
+ cIgnore++;
+#endif
+ PROPASSERT(apinfo[iprop].pid != PID_DICTIONARY);
+ apinfo[iprop].operation = PROPOP_IGNORE;
+ }
+
+ // Insert new property:
+
+ else
+ {
+ DebugTrace(0, Dbg, (
+ "SetValue: Inserting new propid=%lx vt=%hx "
+ "cbNew=%l" szX " val=%s\n",
+ apinfo[iprop].pid,
+ KERNELSELECT(
+ PropByteSwap( apinfo[iprop].pprop->dwType ),
+ avar[iprop].vt),
+ apinfo[iprop].cbprop,
+ KERNELSELECT(
+ ValueToString(
+ apinfo[iprop].pprop,
+ apinfo[iprop].cbprop,
+ valbuf),
+ VariantToString(
+ avar[iprop],
+ varbuf,
+ sizeof( varbuf )))));
+
+ PROPASSERT(apinfo[iprop].pid != PID_ILLEGAL);
+
+ cbInsertMove += apinfo[iprop].cbprop;
+ cbChange += apinfo[iprop].cbprop;
+
+ cInsert++;
+ apinfo[iprop].operation = PROPOP_INSERT;
+ }
+ PROPASSERT(cbstm == _oSection + psh->cbSection + _cbTail);
+
+ // In order to delete any old stream or storage type properties
+ // we count the properties which used to be VT_STREAM etc.
+ // Also, we count the properties which are to be created as
+ // streams or storages.
+
+ if (ppip != NULL && apinfo[iprop].operation != PROPOP_IGNORE)
+ {
+ if ((pprop != NULL && IsIndirectVarType(PropByteSwap(pprop->dwType)))
+ ||
+ (avar != NULL && IsIndirectVarType(avar[iprop].vt)))
+ {
+ cIndirect++;
+ }
+ }
+ } // if (i == cprop)
+ } // for (iprop = 0; iprop < cprop; iprop++)
+ // We're now done classifying each of the properties to be added.
+
+
+ // ------------------------------------------------------------
+ // Put existing, to-be-overwritten, indirect properties in ppip
+ // ------------------------------------------------------------
+
+ // Did the caller give us an INDIRECTPROPERTY buffer, and are
+ // there indirect properties being added and/or overwritten?
+
+ if (ppip != NULL && cIndirect != 0)
+ {
+ // allocate needed space for indirect information
+ INDIRECTPROPERTY *pipUse;
+
+ if (cprop != 1)
+ {
+ pipUse = *ppip = new INDIRECTPROPERTY[cIndirect + 1];
+ if (*ppip == NULL)
+ {
+ // BUGBUG check no leaks
+ StatusNoMemory(pstatus, "SetValue: Indirect Name");
+ goto Exit;
+ }
+ RtlZeroMemory( pipUse, sizeof(INDIRECTPROPERTY) * (cIndirect + 1) );
+ pipUse[cIndirect].Index = MAXULONG;
+ }
+ else
+ {
+ pipUse = (INDIRECTPROPERTY *) ppip;
+ RtlZeroMemory( pipUse, sizeof(*pipUse) );
+ }
+
+
+ int iIndirect = 0;
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ ULONG cbPropOld;
+ SERIALIZEDPROPERTYVALUE const *pprop = NULL;
+
+ PROPASSERT(cbstm == _oSection + psh->cbSection + _cbTail);
+ if (apinfo[iprop].operation == PROPOP_IGNORE ||
+ apinfo[iprop].pid == PID_ILLEGAL)
+ {
+ continue;
+ }
+
+ pprop = _LoadProperty(apinfo[iprop].pid, &cbPropOld, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ PROPASSERT(cbstm == _oSection + psh->cbSection + _cbTail);
+
+ if (pprop != NULL && IsIndirectVarType(PropByteSwap(pprop->dwType)))
+ {
+ CHAR *pszName;
+ BOOL fAlloc = FALSE; // Did we alloc pszName?
+
+ // we are overwriting an indirect property value
+
+ PROPASSERT(cbPropOld >= 2 * sizeof(ULONG));
+ cbPropOld -= 2 * sizeof(ULONG);
+ pszName = (CHAR *) Add2ConstPtr(pprop->rgb, sizeof(ULONG));
+
+ // Do we need to convert the name between Ansi & Unicode?
+
+ if (_CodePage != CP_WINUNICODE // Ansi propset
+ &&
+ OLECHAR_IS_UNICODE) // Unicode OLE APIs
+ {
+ // Convert the indirect reference to Unicode
+
+ RtlpConvertToUnicode(
+ pszName,
+ cbPropOld, //BUGBUG: Could be byte-granular?
+ _CodePage,
+ (WCHAR **) &pszName,
+ &cbPropOld,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ fAlloc = TRUE; // We need to free pszName
+ }
+ else
+ if (_CodePage == CP_WINUNICODE // Unicode propset
+ &&
+ !OLECHAR_IS_UNICODE ) // Ansi OLE APIs
+ {
+ // Byte-Swap the Unicode indirect reference value
+
+ WCHAR *pwszBuffer = NULL;
+
+ // After this call, the appropriately swapped name will be
+ // in pszName. If an alloc was required, pszBuffer will point
+ // to the new buffer (we must free this).
+
+ PBSInPlaceAlloc( (WCHAR**) &pszName, &pwszBuffer, pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // Convert the reference value to Ansi.
+
+ RtlpConvertToMultiByte(
+ (WCHAR*) pszName,
+ cbPropOld,
+ CP_ACP,
+ (CHAR **) &pszName,
+ &cbPropOld,
+ pstatus);
+ delete( pwszBuffer );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ fAlloc = TRUE; // We need to free pszName
+ }
+
+ pipUse[iIndirect].poszName =
+ new OLECHAR[cbPropOld/sizeof(OLECHAR)];
+
+ if (pipUse[iIndirect].poszName == NULL)
+ {
+ StatusNoMemory(pstatus, "SetValue: Indirect Name2");
+ goto Exit;
+ }
+
+ RtlCopyMemory(
+ pipUse[iIndirect].poszName,
+ pszName,
+ cbPropOld);
+
+
+ // Is byte-swapping necessary? It is if the property set
+ // codepage is Unicode, and if OLECHARs are also Unicode.
+ // If both are Ansi, then no byte-swapping is ever necessary,
+ // and if one is Ansi and the other is Unicode, then we
+ // already byte-swapped above during the conversion.
+
+ if (_CodePage == CP_WINUNICODE
+ &&
+ OLECHAR_IS_UNICODE )
+ {
+ // Convert from propset-endian to system-endian.
+ PBSBuffer( pipUse[iIndirect].poszName, cbPropOld, sizeof(OLECHAR) );
+ }
+
+ // Clean up pszName
+
+ if( fAlloc )
+ {
+ // In the Unicode/MBCS conversions, we did an alloc which
+ // we must free now.
+
+ PROPASSERT(pszName != NULL);
+ PROPASSERT(
+ pszName !=
+ (CHAR *) Add2ConstPtr(pprop->rgb, sizeof(ULONG)));
+ delete [] pszName;
+ }
+
+ } // if (pprop != NULL && IsIndirectVarType(PropByteSwap(pprop->dwType)))
+
+ else
+ if (avar == NULL || !IsIndirectVarType(avar[iprop].vt))
+ {
+ // Neither the property being overwritten, nor the property
+ // being written is indirect, so we can continue on to
+ // check the next property (skipping the pipUse updating
+ // below).
+
+ continue;
+ }
+
+ // If we get here, we know that either this property is
+ // an indirect type, or it's overwriting an indirect property.
+ // We established pipUse[].pszName above, so we just need to
+ // insert the index and move on.
+
+ pipUse[iIndirect].Index = iprop;
+ iIndirect++;
+
+ } // for (iprop = 0; iprop < cprop; iprop++)
+
+ PROPASSERT(iIndirect == cIndirect);
+
+ } // if (ppip != NULL && cIndirect != 0)
+
+
+ DebugTrace(0, Dbg, ("SetValue: Total Props %l" szX "\n", cprop));
+ DebugTrace(0, Dbg, (
+ "SetValue: Delete=%l" szX " Insert=%l" szX " Move=%l" szX
+ " Update=%l" szX " Ignore=%l" szX "\n",
+ cDelete,
+ cInsert,
+ cMove,
+ cUpdate,
+ cIgnore));
+
+ PROPASSERT(cDelete + cInsert + cMove + cUpdate + cIgnore == cprop);
+ PROPASSERT(cbstm == _oSection + psh->cbSection + _cbTail);
+
+ // If we need to grow the property offset array, detect any unused
+ // entries at the end of the array that are available for reuse.
+ // and adjust the size difference to reflect the reuse.
+
+ if (cInsert > cDelete)
+ {
+ ULONG cpoReuse, cpoExpand;
+
+ cpoExpand = cInsert - cDelete;
+ cpoReuse = _CountFreePropertyOffsets(pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if (cpoReuse > cpoExpand)
+ {
+ cpoReuse = cpoExpand;
+ }
+ cpoExpand -= cpoReuse;
+
+ // If adding a small number of new entries, but not reusing any old
+ // ones, add 10% more reserved entries (but only up to 10 more) to
+ // avoid having to continually grow the property offset array for
+ // clients that insist on adding a few properties at a time.
+
+ // We don't do this for the User-Defined property set, however,
+ // because older apps assume that the dictionary immediately follows
+ // the last entry in the PID/Offset array.
+
+ if (cpoExpand >= 1 && cpoExpand <= 2 && cpoReuse == 0
+ &&
+ !(_State & CPSS_USERDEFINEDPROPERTIES)
+ )
+ {
+ cpoReserve = 1 + min(psh->cProperties, 90)/10;
+ cpoExpand += cpoReserve;
+ }
+ DebugTrace(0, Dbg, (
+ "SetValue: Reusing %l" szX " offsets, Expanding %l" szX
+ " offsets\n",
+ cpoReuse,
+ cpoExpand));
+
+ pscnk0->oOld = CB_PROPERTYSECTIONHEADER +
+ (psh->cProperties + cpoReuse) * CB_PROPERTYIDOFFSET;
+ pscnk0->cbChange = cpoExpand * CB_PROPERTYIDOFFSET;
+ cbChange += cpoExpand * CB_PROPERTYIDOFFSET;
+ PROPASSERT(cbstm == _oSection + psh->cbSection + _cbTail);
+
+ } // if (cInsert > cDelete)
+
+ // Do we instead need to *shrink* the PID/Offset array?
+ // If so, don't shrink any more than necessary. We'll
+ // leave up to min(10%,10) blank entries.
+ // Also, if this is the User-Defined property set,
+ // there can never be any unused entries (for compatibility
+ // with older apps), so we do a complete shrink.
+
+ else if (cInsert < cDelete)
+ {
+ ULONG cpoRemove = 0;
+ ULONG cpoDelta = cDelete - cInsert;
+
+ // How many blank entries do we already have?
+ ULONG cpoCurBlankEntries = _CountFreePropertyOffsets( pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if( _State & CPSS_USERDEFINEDPROPERTIES )
+ {
+ cpoRemove = cpoDelta;
+ }
+ else
+ {
+ // How many blank entries can we have?
+ ULONG cpoMaxBlankEntries;
+ cpoMaxBlankEntries = 1 + min(psh->cProperties - cpoDelta, 90)/10;
+
+ // If, after deleting the properties, we'd have too many,
+ // remove only enough to get us down to the max allowable.
+
+ if( cpoCurBlankEntries + cpoDelta
+ >
+ cpoMaxBlankEntries
+ )
+ {
+ cpoRemove = cpoCurBlankEntries + cpoDelta - cpoMaxBlankEntries;
+ }
+ } // if( _State & CPSS_USERDEFINEDPROPERTIES )
+
+ // Should we remove any PID/Offset entries?
+
+ if( cpoRemove > 0 )
+ {
+ // Start removing at cpoRemove entries from the end of the PID/Offset array
+ pscnk0->oOld = CB_PROPERTYSECTIONHEADER
+ +
+ (psh->cProperties + cpoCurBlankEntries - cpoRemove)
+ *
+ CB_PROPERTYIDOFFSET;
+
+ // Remove the bytes of the cpoRemove entries.
+ pscnk0->cbChange = - (LONG) (cpoRemove * CB_PROPERTYIDOFFSET );
+
+ // Adjust the size of the section equivalently.
+ cbChange += pscnk0->cbChange;
+ }
+
+ } // else if (cInsert < cDelete)
+
+ PROPASSERT(
+ cbstm + cbChange >=
+ _oSection + CB_PROPERTYSECTIONHEADER +
+ (psh->cProperties + cInsert - cDelete) * CB_PROPERTYIDOFFSET +
+ _cbTail);
+
+ // If we need to grow the stream, do it now.
+
+ if (cbChange > 0)
+ {
+ if (cbstm + cbChange > CBMAXPROPSETSTREAM)
+ {
+ StatusDiskFull(pstatus, "SetValue: 256k limit");
+ goto Exit;
+ }
+
+ DebugTrace(0, Dbg, (
+ "SetSize(%x) SetValue grow\n",
+ cbstm + cbChange));
+
+ _MSTM(SetSize)(cbstm + cbChange, TRUE, (VOID **) &_pph, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // reload all pointers into mapped image:
+
+ psh = _GetSectionHeader();
+ PROPASSERT(cbstm == _oSection + psh->cbSection + _cbTail);
+
+ // If there's another section after this one, move it back to the
+ // end of the stream now.
+
+ if (_cbTail != 0)
+ {
+ VOID *pvSrc = _MapAbsOffsetToAddress(cbstm - _cbTail);
+
+ PropMoveMemory(
+ "SetValue(_cbTail:grow)",
+ psh,
+ Add2Ptr(pvSrc, cbChange),
+ pvSrc,
+ _cbTail);
+ }
+ } // if (cbChange > 0)
+
+ // From this point on, the operation should succeed.
+ // If necessary, the stream has already been grown.
+
+ if (cDelete + cInsert + cMove != 0)
+ {
+ // Delete and compact property offsets in the section header.
+
+ if (cDelete + cMove != 0)
+ {
+ _DeleteMovePropertyOffsets(apinfo, cprop, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ psh->cProperties -= cDelete;
+ }
+ PROPASSERT(cbstm == _oSection + psh->cbSection + _cbTail);
+
+ // Use the last chunk to mark the section end, and sort the chunks
+ // in ascending order by start offset.
+
+ CStreamChunk *pscnk = scl.GetFreeChunk(pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ pscnk->oOld = psh->cbSection;
+ pscnk->cbChange = 0;
+
+ scl.SortByStartAddress();
+
+ // If we're reducing the number of properties, we may be shrinking
+ // the PID/Offset array. So, update that array now, since
+ // we may remove some bytes at the end of it when we compact
+ // the stream.
+
+ if( cDelete > cInsert )
+ {
+ _UpdatePropertyOffsets( &scl, pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+
+ // Compact the Stream following the directions in the
+ // chunk list.
+
+ _CompactStream(&scl);
+
+ // If the number of properties is holding constant or increasing,
+ // we can update the PID/Offset array now (because _CompactStream
+ // allocated any necessary space for us).
+
+ if( cDelete <= cInsert )
+ {
+ _UpdatePropertyOffsets( &scl, pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+
+ // Set the new section size to include the deleted and inserted
+ // property offsets, and the deleted property values.
+
+ psh->cbSection += cbChange;
+
+ // Insert new property offsets at the end of the array.
+
+ if (cInsert + cMove != 0)
+ {
+ _InsertMovePropertyOffsets(
+ apinfo,
+ cprop,
+ psh->cbSection - cbInsertMove,
+ cpoReserve,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ psh->cProperties += cInsert;
+ }
+
+ PROPASSERT(cbstm + cbChange == _oSection + psh->cbSection + _cbTail);
+ if (_cbTail != 0)
+ {
+ // There's another section after this one; if we're shrinking
+ // the stream, move it up to the new end of the stream now.
+
+ if (cbChange < 0)
+ {
+ VOID *pvSrc = _MapAbsOffsetToAddress(cbstm - _cbTail);
+
+ PropMoveMemory(
+ "SetValue(_cbTail:shrink)",
+ psh,
+ Add2Ptr(pvSrc, cbChange),
+ pvSrc,
+ _cbTail);
+ }
+ _PatchSectionOffsets(cbChange);
+ }
+ } // if (cDelete + cInsert + cMove != 0)
+
+ // Copy the new values.
+
+ // NOTE: It might seem unnecessary to delay the in-place updates until
+ // this for loop. We do not perform the in-place updates while
+ // classifying the changes because unmapping, remapping and changing
+ // the size required for handling other updates can fail. In the event
+ // of such a failure, the update would not be atomic. By delaying the
+ // in-place updates, we provide some degree of atomicity.
+
+ if (cInsert + cUpdate + cMove != 0)
+ {
+ BOOLEAN fDocSummaryInfo = FALSE;
+
+ if ((_State &
+ (CPSS_USERDEFINEDPROPERTIES | CPSS_DOCUMENTSUMMARYINFO)) ==
+ CPSS_DOCUMENTSUMMARYINFO)
+ {
+ fDocSummaryInfo = TRUE;
+ }
+
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ // Find property in the offset array and copy in the new value.
+ if (apinfo[iprop].operation == PROPOP_INSERT ||
+ apinfo[iprop].operation == PROPOP_UPDATE ||
+ apinfo[iprop].operation == PROPOP_MOVE)
+ {
+ SERIALIZEDPROPERTYVALUE *pprop;
+ ULONG cbprop;
+ ULONG cIndirectProps;
+ PROPID propid = apinfo[iprop].pid;
+
+ pprop = _LoadProperty(propid, NULL, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ PROPASSERT(pprop != NULL);
+
+ // Special case for SetPropertyNames dictionary creation:
+
+ if (propid == PID_DICTIONARY)
+ {
+ PROPASSERT(CB_SERIALIZEDPROPERTYVALUE == CB_DICTIONARY);
+ PROPASSERT(apinfo[iprop].cbprop == CB_SERIALIZEDPROPERTYVALUE);
+ PROPASSERT(avar[iprop].vt == VT_DICTIONARY);
+ ((DICTIONARY *) pprop)->cEntries = 0;
+ } // if (propid == PID_DICTIONARY)
+ else
+ {
+ // In User, serialize the PROPVARIANT in avar
+ // directly into the mapped stream. We ask for the
+ // count of indirect properties, even though we don't
+ // use it, in order to tell the routine that we
+ // can handle them. Any handling that is actually
+ // required must be handled by our caller.
+
+ cbprop = apinfo[iprop].cbprop;
+ pprop = RtlConvertVariantToPropertyNoEH(
+ &avar[iprop],
+ _CodePage,
+ pprop,
+ &cbprop,
+ apinfo[iprop].pid,
+ FALSE,
+ &cIndirectProps,
+ pstatus
+ );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ PROPASSERT(pprop != NULL);
+ PROPASSERT(cbprop == DwordAlign(cbprop));
+ PROPASSERT(cbprop == apinfo[iprop].cbprop);
+
+ // If writing a DocumentSummaryInformation property
+ // for which an alignment hack is provided, hack it now.
+
+ if (fDocSummaryInfo && _CodePage != CP_WINUNICODE)
+ {
+ // The two vectors in the DocSumInfo property set
+ // (if Ansi) are un-packed, but we'll adjust the lengths
+ // so that if a propset reader expects them to be packed,
+ // it will still work. E.g., a one character string will
+ // have a length of 4, with padding of NULL characters.
+
+ ULONG cbpropT;
+
+ if (propid == PID_HEADINGPAIR)
+ {
+ _FixHeadingPairVector(
+ PATCHOP_ALIGNLENGTHS,
+ pprop,
+ &cbpropT);
+ }
+ else
+ if (propid == PID_DOCPARTS)
+ {
+ _FixDocPartsVector(
+ PATCHOP_ALIGNLENGTHS,
+ pprop,
+ &cbpropT);
+ }
+ }
+ DebugTrace(0, Dbg, (
+ "SetValue:Insert: pph=%x pprop=%x cb=%3l" szX
+ " vt=%4x val=%s o=%x oEnd=%x\n",
+ _pph,
+ pprop,
+ apinfo[iprop].cbprop,
+ PropByteSwap(pprop->dwType),
+ ValueToString(pprop, apinfo[iprop].cbprop, valbuf),
+ _MapAddressToOffset(pprop),
+ _MapAddressToOffset(pprop) + apinfo[iprop].cbprop));
+
+ } // if (propid == PID_DICTIONARY) ... else
+ } // if (apinfo[iprop].operation == PROPOP_INSERT || ...
+ } // for (iprop = 0; iprop < cprop; iprop++)
+ } // if (cInsert + cUpdate + cMove != 0)
+
+ // If we need to shrink the stream or if we are cleaning up after a
+ // previous shrink that failed, do it last.
+
+ cbNewSize = _MSTM(GetSize)(pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if (cbNewSize != cbstm + cbChange)
+ {
+ DebugTrace(0, Dbg, (
+ "SetSize(%x) SetValue shrink\n",
+ cbstm + cbChange));
+ _MSTM(SetSize)(cbstm + cbChange, TRUE, (VOID **) &_pph, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ scl.Delete();
+
+ if( !NT_SUCCESS(*pstatus) )
+ {
+ if( ppip != NULL && 0 != cIndirect )
+ {
+ INDIRECTPROPERTY *pipUse;
+
+ pipUse = (1 == cprop) ? (INDIRECTPROPERTY*) ppip
+ : *ppip;
+
+ for (int iFree = 0; iFree < cIndirect; iFree++)
+ {
+ delete [] pipUse[iFree].poszName;
+ }
+ if (cprop != 1)
+ {
+ delete [] pipUse;
+ *ppip = NULL;
+ }
+ }
+ } // if( !NT_SUCCESS(*pstatus) )
+
+
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_CountFreePropertyOffsets, private
+//
+// Synopsis: counts available (free) property offsets at and of array
+//
+// Arguments: [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: count of available property offsets at and of array
+//+--------------------------------------------------------------------------
+
+ULONG
+CPropertySetStream::_CountFreePropertyOffsets(OUT NTSTATUS *pstatus)
+{
+ PROPERTYIDOFFSET *ppo, *ppoMax;
+ PROPERTYSECTIONHEADER const *psh;
+ ULONG oMin = MAXULONG;
+ ULONG oEnd;
+ ULONG cFree = 0;
+
+ psh = _LoadPropertyOffsetPointers(&ppo, &ppoMax, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if (psh != NULL)
+ {
+ for ( ; ppo < ppoMax; ppo++)
+ {
+ if (oMin > ppo->dwOffset)
+ {
+ oMin = ppo->dwOffset;
+ }
+ }
+ }
+ if (oMin == MAXULONG)
+ {
+ goto Exit;
+ }
+ PROPASSERT(psh != NULL);
+ oEnd = CB_PROPERTYSECTIONHEADER + psh->cProperties * CB_PROPERTYIDOFFSET;
+ PROPASSERT(oEnd <= oMin);
+
+ cFree = (oMin - oEnd)/CB_PROPERTYIDOFFSET;
+
+Exit:
+
+ return( cFree );
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_DeleteMovePropertyOffsets, private
+//
+// Synopsis: updates the offsets following the changes to the stream
+//
+// Arguments: [apinfo] -- array of property information
+// [cprop] -- number of properties
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: None
+//+--------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::_DeleteMovePropertyOffsets(
+ IN PROPERTY_INFORMATION const *apinfo,
+ IN ULONG cprop,
+ OUT NTSTATUS *pstatus)
+{
+ ULONG i;
+ ULONG cDelete;
+ PROPERTYSECTIONHEADER const *psh;
+ PROPERTYIDOFFSET *ppo, *ppoBase, *ppoMax;
+
+ psh = _LoadPropertyOffsetPointers(&ppoBase, &ppoMax, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ PROPASSERT(psh != NULL);
+
+ // Remove the deleted properties
+
+ DebugTrace(0, Dbg, ("Marking deleted/moved property offsets\n"));
+ cDelete = 0;
+ for (i = 0; i < cprop; i++)
+ {
+ if (apinfo[i].operation == PROPOP_DELETE ||
+ apinfo[i].operation == PROPOP_MOVE)
+ {
+ for (ppo = ppoBase; ppo < ppoMax; ppo++)
+ {
+ if (ppo->propid == apinfo[i].pid)
+ {
+ DebugTrace(0, Dbg, (
+ "%sing propid=%lx oOld=%l" szX "\n",
+ apinfo[i].operation == PROPOP_DELETE? "Delet" : "Mov",
+ ppo->propid,
+ ppo->dwOffset));
+ if (apinfo[i].operation == PROPOP_DELETE)
+ {
+ cDelete++;
+ ppo->dwOffset = MAXULONG;
+ }
+ else
+ {
+ ppo->dwOffset = 0;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // scan once and compact the property offset array.
+
+ if (cDelete > 0)
+ {
+ PROPERTYIDOFFSET *ppoDst = ppoBase;
+
+ DebugTrace(0, Dbg, ("Compacting %l" szX " deleted props\n", cDelete));
+ for (ppo = ppoBase; ppo < ppoMax; ppo++)
+ {
+ if (ppo->dwOffset != MAXULONG)
+ {
+ if (ppo > ppoDst)
+ {
+ *ppoDst = *ppo;
+ }
+ DebugTrace(0, Dbg, (
+ "%sing propid=%lx oOld=%l" szX "\n",
+ ppo > ppoDst? "Compact" : "Preserv",
+ ppo->propid,
+ ppo->dwOffset));
+ ppoDst++;
+ }
+ }
+ PROPASSERT(cDelete == (ULONG) (ppoMax - ppoDst));
+ DebugTrace(0, Dbg, ("Zeroing %l" szX " entries\n", cDelete));
+ RtlZeroMemory(ppoDst, (BYTE *) ppoMax - (BYTE *) ppoDst);
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_UpdatePropertyOffsets, private
+//
+// Synopsis: update property offsets in section header
+//
+// Arguments: [pscl] -- list of chunks in stream that were changed
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: None
+//+--------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::_UpdatePropertyOffsets(
+ IN CStreamChunkList const *pscl,
+ OUT NTSTATUS *pstatus)
+{
+ PROPERTYSECTIONHEADER const *psh;
+ PROPERTYIDOFFSET *ppo, *ppoMax;
+
+ // Update the offsets for the existing properties.
+ DebugTrace(0, Dbg, ("Updating existing property offsets\n"));
+
+ psh = _LoadPropertyOffsetPointers(&ppo, &ppoMax, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ PROPASSERT(psh != NULL);
+
+ for ( ; ppo < ppoMax; ppo++)
+ {
+ if (ppo->dwOffset != 0)
+ {
+#if DBGPROP
+ ULONG oOld = ppo->dwOffset;
+#endif
+ ppo->dwOffset = _GetNewOffset(pscl, ppo->dwOffset);
+
+ DebugTrace(0, Dbg, (
+ "UpdatePropertyOffsets: propid=%lx offset=%l" szX "-->%l" szX"\n",
+ ppo->propid,
+ oOld,
+ ppo->dwOffset));
+ }
+ }
+
+Exit:
+
+ return;
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_InsertMovePropertyOffsets, private
+//
+// Synopsis: updates the offsets following the changes to the stream
+//
+// Arguments: [apinfo] -- array of property information
+// [cprop] -- number of properties
+// [oInsert] -- offset in section for new properties
+// [cpoReserve] -- newly reserved property offsets to zero
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: None
+//+--------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::_InsertMovePropertyOffsets(
+ IN PROPERTY_INFORMATION const *apinfo,
+ IN ULONG cprop,
+ IN ULONG oInsert,
+ IN ULONG cpoReserve,
+ OUT NTSTATUS *pstatus)
+{
+ ULONG i;
+ PROPERTYSECTIONHEADER const *psh;
+ PROPERTYIDOFFSET *ppo, *ppoBase, *ppoMax;
+
+ *pstatus = STATUS_SUCCESS;
+
+ psh = _LoadPropertyOffsetPointers(&ppoBase, &ppoMax, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ PROPASSERT(psh != NULL);
+
+ // Insert the new property offsets at the end.
+ DebugTrace(0, Dbg, ("Inserting/Moving/Zeroing property offsets\n"));
+
+ for (i = 0; i < cprop; i++)
+ {
+ if (apinfo[i].operation == PROPOP_INSERT)
+ {
+ ppo = ppoMax++;
+ ppo->propid = apinfo[i].pid;
+ }
+ else if (apinfo[i].operation == PROPOP_MOVE)
+ {
+ for (ppo = ppoBase; ppo < ppoMax; ppo++)
+ {
+ if (ppo->propid == apinfo[i].pid)
+ {
+ PROPASSERT(ppo->dwOffset == 0);
+ break;
+ }
+ }
+ }
+ else
+ {
+ continue;
+ }
+
+ PROPASSERT(ppo->propid == apinfo[i].pid);
+ ppo->dwOffset = oInsert;
+ oInsert += apinfo[i].cbprop;
+
+ DebugTrace(0, Dbg, (
+ "%sing propid=%lx offset=%l" szX " size=%l" szX "\n",
+ apinfo[i].operation == PROPOP_INSERT? "Insert" : "Mov",
+ ppo->propid,
+ ppo->dwOffset,
+ apinfo[i].cbprop));
+ }
+ DebugTrace(0, Dbg, (
+ "Zeroing %x property offsets o=%l" szX " size=%l" szX "\n",
+ cpoReserve,
+ _MapAddressToOffset(ppoMax),
+ cpoReserve * CB_PROPERTYIDOFFSET));
+ RtlZeroMemory(ppoMax, cpoReserve * CB_PROPERTYIDOFFSET);
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_CompactStream, private
+//
+// Synopsis: compact all of the property stream chunks
+//
+// Arguments: [pscl] -- list of chunks in stream that were changed
+//
+// Returns: None
+//
+// Note:
+// Each chunk structure represents a contiguous range of the stream to be
+// completely removed or added. A terminating chunk is appended to
+// transparently mark the end of the data stream. The unmodified data
+// after each chunk (except the last one) must be preserved and compacted
+// as necessary. Chunk structures contain section-relative offsets.
+//
+// Invariants:
+// - Only the first chunk can represent an insertion; subsequent chunks
+// always represent deletions.
+// - The first chunk can never cause a deletion, but it might not cause
+// any change at all.
+// - The last chunk is a dummy used to mark the end of the stream.
+//
+// Algorithm:
+// In the optimal case without insertions, each chunk's trailing data can
+// be moved ahead (compacted) individually in ascending chunk index order.
+// If the first chunk represents an insertion, then some consecutive
+// number of data blocks must be moved back (in *descending* chunk index
+// order) to make room for the insertion.
+//
+// Walk the chunk array to find the first point where the accumulated size
+// change is less than or equal to zero.
+//
+// After (possibly) compacting a single range in descending chunk index
+// order, compact all remaining chunks in ascending chunk index order.
+//
+// Example: the first chunk inserts 18 bytes for new property offsets
+// (apo'[]), and the second two delete 10 bytes each (chnk1 & chnk2).
+// There are four chunks in the array, and three blocks of data to move.
+//
+// oOld cbChange | AccumulatedChange oNew
+// chunk[0]: 38 +18 | +18 38 (apo'[])
+// chunk[1]: 48 -10 | +8 50 (chnk1)
+// chunk[2]: 6c -10 | -8 74 (chnk2)
+// chunk[3]: 8c 0 | -8 84 (end)
+//
+// Data blocks are moved in the following sequence to avoid overlap:
+// DstOff SrcOff cbMove | Chunk#
+// 60 58 14 | 1 chnk1/data2: descending pass (Dst > Src)
+// 50 38 10 | 0 apo'[]/data1: descending pass (Dst > Src)
+// 74 7c 10 | 2 chnk2/data3: ascending pass (Dst < Src)
+//
+// SrcOff = oOld - min(cbChange, 0)
+// DstOff = SrcOff + AccumulatedChange
+// cbMove = chnk[i+1].oOld - SrcOff
+//
+// Before compacting:
+// 0 38 48 58 6c 7c 8c
+// | | | | | | |
+// V V 10 V -10 V 14 V -10 V 10 V
+// +----+-------+----+-------+-------+-------+----------+-------+-------+
+// | ph | afo[] | sh | apo[] | data1 | chnk1 | data2 | chnk2 | data3 |
+// +----+-------+----+-------+-------+-------+----------+-------+-------+
+//
+// After compacting:
+// 0 38 50 60 74 84
+// | | | | | |
+// V V +18 V 10 V 14 V 10 V
+// +----+-------+----+-------+-----------+-------+----------+-------+
+// | ph | afo[] | sh | apo[] | apo'[] | data1 | data2 | data3 |
+// +----+-------+----+-------+-----------+-------+----------+-------+
+//+--------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::_CompactStream(
+ IN CStreamChunkList const *pscl)
+{
+ ULONG i, iMax, iAscend;
+ LONG cbChangeTotal, cbChangeTotalAscend;
+ CStreamChunk const *pscnk;
+
+ // Subtract one to avoid operating on the terminating chunk directly.
+
+ iMax = pscl->Count() - 1;
+
+ // If the first chunk does not indicate an insertion, the first for loop is
+ // exited with i == 0.
+ //
+ // If the first chunk represents an insertion, either i == iMax or i itself
+ // indexes the first chunk that can be compacted normally (in ascending
+ // chunk index order). In either case, we compact in descending chunk
+ // index order starting just below i.
+
+ DebugTrace(0, Dbg, (
+ "CompactStream: %l" szX " chunks @%lx\n",
+ pscl->Count(),
+ pscl->GetChunk(0)));
+
+ cbChangeTotal = 0;
+ for (i = 0; i < iMax; i++)
+ {
+ pscnk = pscl->GetChunk(i);
+ PROPASSERT(i == 0 || pscnk->cbChange < 0);
+ if (cbChangeTotal + pscnk->cbChange <= 0)
+ {
+ break;
+ }
+ cbChangeTotal += pscnk->cbChange;
+ }
+ iAscend = i; // save ascending order start
+ cbChangeTotalAscend = cbChangeTotal;
+
+ DebugTrace(0, Dbg, ("CompactStream: iAscend=%l" szX "\n", iAscend));
+
+ // First compact range in descending chunk index order if necessary:
+
+ while (i-- > 0)
+ {
+ pscnk = pscl->GetChunk(i);
+ PROPASSERT(i == 0 || pscnk->cbChange < 0);
+
+ DebugTrace(0, Dbg, ("CompactStream: descend: i=%l" szX "\n", i));
+#if DBGPROP
+ pscl->AssertCbChangeTotal(pscnk, cbChangeTotal);
+#endif
+ _CompactChunk(pscnk, cbChangeTotal, pscl->GetChunk(i + 1)->oOld);
+ cbChangeTotal -= pscnk->cbChange;
+ }
+
+ // Compact any remaining chunks in ascending chunk index order.
+
+ cbChangeTotal = cbChangeTotalAscend;
+ for (i = iAscend; i < iMax; i++)
+ {
+ pscnk = pscl->GetChunk(i);
+ PROPASSERT(i == 0 || pscnk->cbChange < 0);
+
+ DebugTrace(0, Dbg, ("CompactStream: ascend: i=%l" szX "\n", i));
+ cbChangeTotal += pscnk->cbChange;
+#if DBGPROP
+ pscl->AssertCbChangeTotal(pscnk, cbChangeTotal);
+#endif
+ _CompactChunk(pscnk, cbChangeTotal, pscl->GetChunk(i + 1)->oOld);
+ }
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_CompactChunk, private
+//
+// Synopsis: Compact the data block following one chunk
+//
+// Arguments: [pscnk] -- pointer to stream chunk
+// [cbChangeTotal] -- Bias for this chunk
+// [oOldNext] -- offset of next chunk
+//
+// Returns: None
+//+--------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::_CompactChunk(
+ IN CStreamChunk const *pscnk,
+ IN LONG cbChangeTotal,
+ IN ULONG oOldNext)
+{
+ LONG cbDelta = cbChangeTotal + min(pscnk->cbChange, 0); // BUGBUG: temp
+
+ DebugTrace(0, Dbg, (
+ "CompactChunk(pscnk->oOld=%l" szX ", pscnk->cbChange=%s%l" szX "\n"
+ " cbChangeTotal=%s%l" szX
+ ", cbDelta=%s%l" szX // BUGBUG: temp
+ ", oOldNext=%l" szX ")\n",
+ pscnk->oOld,
+ pscnk->cbChange < 0? "-" : "",
+ pscnk->cbChange < 0? -pscnk->cbChange : pscnk->cbChange,
+ cbChangeTotal < 0? "-" : "",
+ cbChangeTotal < 0? -cbChangeTotal : cbChangeTotal,
+ cbDelta < 0? "-" : "", // BUGBUG: temp
+ cbDelta < 0? -cbDelta : cbDelta, // BUGBUG: temp
+ oOldNext));
+
+ if (cbChangeTotal != 0)
+ {
+ ULONG oSrc;
+ VOID const *pvSrc;
+
+ oSrc = pscnk->oOld - min(pscnk->cbChange, 0);
+ pvSrc = _MapOffsetToAddress(oSrc);
+ PropMoveMemory(
+ "CompactChunk",
+ _GetSectionHeader(),
+ (VOID *) Add2ConstPtr(pvSrc, cbChangeTotal),
+ pvSrc,
+ oOldNext - oSrc);
+ }
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_PatchSectionOffsets, private
+//
+// Synopsis: patch section offsets after moving data around
+//
+// Arguments: [cbChange] -- size delta
+//
+// Returns: none
+//+--------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::_PatchSectionOffsets(
+ LONG cbChange)
+{
+ ULONG i;
+
+ for (i = 0; i < _cSection; i++)
+ {
+ FORMATIDOFFSET *pfo;
+
+ pfo = _GetFormatidOffset(i);
+ if (pfo->dwOffset > _oSection)
+ {
+ DebugTrace(0, DEBTRACE_PROPPATCH, (
+ "PatchSectionOffsets(%x): %l" szX " + %l" szX " --> %l" szX "\n",
+ i,
+ pfo->dwOffset,
+ cbChange,
+ pfo->dwOffset + cbChange));
+ pfo->dwOffset += cbChange;
+ }
+ }
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_GetNewOffset, private
+//
+// Synopsis: gets the new address
+//
+// Arguments: [pscl] -- list of stream chunks that were changed
+// [oOld] -- old offset
+//
+// Returns: new offset
+//+--------------------------------------------------------------------------
+
+ULONG
+CPropertySetStream::_GetNewOffset(
+ IN CStreamChunkList const *pscl,
+ IN ULONG oOld) const
+{
+ // The Chunk list is sorted by start offsets. Locate the chunk to which
+ // the old offset belongs, then use the total change undergone by the chunk
+ // to compute the new offset.
+
+ ULONG i;
+ ULONG iMax = pscl->Count();
+ LONG cbChangeTotal = 0;
+
+ for (i = 0; i < iMax; i++)
+ {
+ CStreamChunk const *pscnk = pscl->GetChunk(i);
+ if (pscnk->oOld > oOld)
+ {
+ break;
+ }
+ cbChangeTotal += pscnk->cbChange;
+ if (pscnk->oOld == oOld)
+ {
+ PROPASSERT(pscnk->cbChange >= 0);
+ break;
+ }
+ }
+ PROPASSERT(i < iMax);
+ DebugTrace(0, Dbg, (
+ "GetNewOffset: %l" szX " + %l" szX " --> %l" szX "\n",
+ oOld,
+ cbChangeTotal,
+ oOld + cbChangeTotal));
+ return(oOld + cbChangeTotal);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_ComputeMinimumSize, private
+//
+// Synopsis: computes the minimum possible size of a property set stream
+//
+// Arguments: [cbstm] -- actual stream size
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: computed highest offset in use
+//+--------------------------------------------------------------------------
+
+ULONG
+CPropertySetStream::_ComputeMinimumSize(
+ IN ULONG cbstm,
+ OUT NTSTATUS *pstatus)
+{
+ ULONG oMax = 0;
+ *pstatus = STATUS_SUCCESS;
+
+ // Don't assume *any* class variables except _pph are loaded yet!
+
+ if (_pph != NULL && cbstm != 0)
+ {
+ ULONG cbMin;
+ ULONG i;
+ ULONG cSection;
+
+ cSection = 1;
+ cbMin = 0;
+
+ if (_HasPropHeader())
+ {
+ cSection = _pph->reserved;
+ cbMin = CB_PROPERTYSETHEADER + cSection * CB_FORMATIDOFFSET;
+ }
+ oMax = cbMin;
+
+ // Add the size of each section
+
+ for (i = 0; i < cSection; i++)
+ {
+ ULONG oSectionEnd;
+
+ PROPERTYSECTIONHEADER const *psh = _GetSectionHeader(i, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ cbMin += psh->cbSection;
+ oSectionEnd = _MapAddressToAbsOffset(psh) + psh->cbSection;
+ if (oMax < oSectionEnd)
+ {
+ oMax = oSectionEnd;
+ }
+ }
+
+ // The following can't be asserted, because there may be
+ // a correctable reason why cbstm < oMax at in the Open path
+ // (see the Excel 5.0a problem in _FixSummaryInformation)
+ //PROPASSERT(oMax <= cbstm);
+
+ PROPASSERT(cbMin <= oMax);
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // oMax may have been set before an error occurred.
+ // In this case, set it to zero.
+
+ if( !NT_SUCCESS(*pstatus) )
+ oMax = 0;
+
+ return(oMax);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_DictionaryLength
+//
+// Synopsis: compute length of property set dictionary
+//
+// Arguments: [pdy] -- pointer to dictionary
+// [cbbuf] -- maximum length of accessible memory at pdy
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: Byte-granular count of bytes in dictionary
+//+--------------------------------------------------------------------------
+
+ULONG
+CPropertySetStream::_DictionaryLength(
+ IN DICTIONARY const *pdy,
+ IN ULONG cbbuf,
+ OUT NTSTATUS *pstatus ) const
+{
+ ENTRY UNALIGNED const *pent;
+ ULONG cbDict = CB_DICTIONARY;
+ ULONG i;
+
+ *pstatus = STATUS_SUCCESS;
+
+ for (i = 0, pent = &pdy->rgEntry[0];
+ i < PropByteSwap( pdy->cEntries );
+ i++, pent = _NextDictionaryEntry( pent ))
+ {
+ if (cbbuf < cbDict + CB_ENTRY ||
+ cbbuf < _DictionaryEntryLength( pent ))
+ {
+ StatusCorruption(pstatus, "_DictionaryLength: section size");
+ goto Exit;
+ }
+
+ cbDict += _DictionaryEntryLength( pent );
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return(cbDict);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_PropertyNameLength
+//
+// Synopsis: compute length (*byte* count) of a property name
+//
+// Arguments: [pvName] -- property name, in the codepage of
+// the property set
+// [pcbName] -- pointer to returned byte length of name
+//
+// Returns: TRUE if name length is valid; else FALSE
+//
+// Note: The OLE 2.0 format mandates that the null be included as part
+// of the length of the name that is stored in the dictionary.
+// If the propset uses the Unicode code page, names contain
+// WCHARs, otherwise they contain CHARs. In either case, the
+// length is a byte count that includes the L'\0' or '\0'.
+//
+// Also note that this routine does not concern itself with
+// the byte-order of the name: for Ansi names, it's irrelevant;
+// and for Unicode names, L'\0' == PropByteSwap(L'\0').
+//
+//+--------------------------------------------------------------------------
+
+BOOLEAN
+CPropertySetStream::_PropertyNameLength(
+ IN VOID const *pvName,
+ OUT ULONG *pcbName) const
+{
+ ULONG cch;
+
+ if (_CodePage == CP_WINUNICODE)
+ {
+ cch = Prop_wcslen((WCHAR const *) pvName) + 1;
+ *pcbName = cch * sizeof(WCHAR);
+ }
+ else
+ {
+ *pcbName = cch = strlen((char const *) pvName) + 1;
+ }
+ return(cch > 1 && cch <= CCH_MAXPROPNAMESZ );
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_ComparePropertyNames
+//
+// Synopsis: Compare two property names.
+//
+// Pre-Conditions:
+// The property names are in the codepage of the
+// property set.
+//
+// Arguments: [pvName1] -- property name 1
+// [pvName2] -- property name 2
+// [fSameByteOrder]-- TRUE: names are both big- or little-endian
+// FALSE: 2nd name is wrong endian
+// [cbName] -- byte count of name length
+// (includes terminator)
+//
+// Returns: TRUE if names are equal
+//+--------------------------------------------------------------------------
+
+
+
+BOOLEAN
+CPropertySetStream::_ComparePropertyNames(
+ IN VOID const *pvName1,
+ IN VOID const *pvName2,
+ IN BOOL fSameByteOrder,
+ IN ULONG cbName) const
+{
+ // BUGBUG: When the property code is moved to OLE32,
+ // remove awcByteSwap, and compare unicode strings one
+ // character at a time, using CharLowerW.
+
+ WCHAR awcByteSwap[ CCH_MAXPROPNAMESZ ];
+
+#ifdef WINNT
+
+ if (_CodePage == CP_WINUNICODE)
+ {
+ // On big-endian systems, when the second name
+ // is byte-swapped, we'll byte-swap it into a new
+ // buffer to use for the comparisson.
+
+#ifdef BIGENDIAN
+ if( !fSameByteOrder )
+ {
+ ULONG ulIndex = 0;
+ PROPASSERT( (WCHAR) L'\0' == ByteSwap( (WCHAR) L'\0' ));
+
+ do
+ {
+ awcByteSwap[ ulIndex ] = ByteSwap( ((WCHAR*)pvName2)[ ulIndex ] );
+
+ } while( awcByteSwap[ulIndex++] != L'\0' );
+ }
+#endif // BIGENDIAN
+
+ UNICODE_STRING s1, s2;
+
+ s1.Buffer = (WCHAR *) pvName1;
+
+#ifdef BIGENDIAN
+ s2.Buffer = fSameByteOrder ? (WCHAR *) pvName2
+ : awcByteSwap;
+#else
+ s2.Buffer = (WCHAR *) pvName2;
+#endif
+
+ s1.Length =
+ s1.MaximumLength =
+ s2.Length =
+ s2.MaximumLength = (USHORT) (cbName - sizeof(WCHAR));
+
+ return(RtlEqualUnicodeString(&s1, &s2, TRUE));
+
+ } // if (_CodePage == CP_WINUNICODE)
+
+ else
+ {
+
+ STRING s1, s2;
+
+ s1.Buffer = (CHAR *) pvName1;
+ s2.Buffer = (CHAR *) pvName2;
+ s1.Length =
+ s1.MaximumLength =
+ s2.Length =
+ s2.MaximumLength = (USHORT) (cbName - sizeof(CHAR));
+ return(RtlEqualString(&s1, &s2, TRUE));
+ } // if (_CodePage == CP_WINUNICODE) ... else
+
+
+#else // !WINNT
+
+ if (_CodePage == CP_WINUNICODE)
+ {
+ // On big-endian systems, when the second name
+ // is byte-swapped, we'll byte-swap it into a new
+ // buffer to use for the comparisson.
+
+#ifdef BIGENDIAN
+ if( !fSameByteOrder )
+ {
+ ULONG ulIndex = 0;
+ PROPASSERT( L'\0' == ByteSwap( (WCHAR) L'\0' ));
+
+ do
+ {
+ awcByteSwap[ ulIndex ] = ByteSwap( ((WCHAR*)pvName2)[ ulIndex ] );
+
+ } while( awcByteSwap[ulIndex++] != L'\0' );
+ }
+#endif // BIGENDIAN
+
+ // Nashville has no Rtl routines:
+ return(Prop_wcsnicmp(
+ (WCHAR const *) pvName1,
+#ifdef BIGENDIAN
+ fSameByteOrder ? (WCHAR const *) pvName2
+ : awcByteSwap,
+#else
+ (WCHAR const *) pvName2,
+#endif
+ cbName / sizeof(WCHAR) ) == 0);
+
+ } // if (_CodePage == CP_WINUNICODE)
+
+ else
+ {
+
+ // Nashville has no Rtl routines:
+ return(_strnicmp(
+ (char const *) pvName1,
+ (char const *) pvName2,
+ cbName) == 0);
+ } // if (_CodePage == CP_WINUNICODE) ... else
+
+#endif // !WINNT
+
+}
+
+
+
+//+---------------------------------------------------------------------------
+// Function: CPropertySetStream::DuplicatePropertyName
+//
+// Synopsis: Duplicate an OLECHAR property name string
+//
+// Arguments: [poszName] -- input string
+// [cbName] -- count of bytes in string (includes null)
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: pointer to new string
+//---------------------------------------------------------------------------
+
+OLECHAR *
+CPropertySetStream::DuplicatePropertyName(
+ IN OLECHAR const *poszName,
+ IN ULONG cbName,
+ OUT NTSTATUS *pstatus) const
+{
+ OLECHAR *poc = NULL;
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(cbName != 0);
+ PROPASSERT(IsOLECHARString(poszName, cbName));
+
+ if (cbName != 0)
+ {
+ PROPASSERT((ocslen(poszName) + 1) * sizeof(OLECHAR) == cbName);
+
+ poc = (OLECHAR *) _pma->Allocate(cbName);
+
+ if (NULL == poc)
+ {
+ StatusNoMemory(pstatus, "DuplicatePropertyName: no memory");
+ goto Exit;
+ }
+ RtlCopyMemory(poc, poszName, cbName);
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return(poc);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::QueryPropid
+//
+// Synopsis: translate a property name to a property id using the
+// dictionary on the property stream
+//
+// Arguments: [poszName] -- name of property
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: propid for property if found; PID_ILLEGAL if not found
+//---------------------------------------------------------------------------
+
+PROPID
+CPropertySetStream::QueryPropid(
+ IN OLECHAR const *poszName,
+ OUT NTSTATUS *pstatus )
+{
+ // ------
+ // Locals
+ // ------
+
+ ULONG cbname;
+ DICTIONARY const *pdy;
+ ENTRY UNALIGNED const *pent;
+ ULONG cdye;
+ ULONG cbDict; // BYTE granular size!
+ VOID const *pvName = NULL;
+ PROPID propid = PID_ILLEGAL;
+
+ // ----------
+ // Initialize
+ // ----------
+
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(_HasPropHeader());
+ PROPASSERT(_IsMapped());
+ PROPASSERT( IsOLECHARString( poszName, MAXULONG ));
+ PROPASSERT(PROPSET_BYTEORDER == _pph->wByteOrder);
+
+
+ // Make sure this isn't a UD propset which has been deleted.
+ if (_State & CPSS_USERDEFINEDDELETED)
+ {
+ StatusAccessDenied(pstatus, "QueryPropid: deleted");
+ goto Exit;
+ }
+
+ // Put the name into pvName, converting it if
+ // necessary to the code-page of the property set.
+
+ pvName = poszName;
+ if (_CodePage == CP_WINUNICODE // Property set is Unicode
+ &&
+ !OLECHAR_IS_UNICODE ) // Name is in Ansi
+ {
+ // Convert the caller-provided name from the system
+ // Ansi codepage to Unicode.
+
+ ULONG cb = 0;
+ pvName = NULL;
+ _OLECHARToWideChar( poszName, (ULONG)-1, CP_ACP,
+ (WCHAR**)&pvName, &cb, pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+
+ else
+ if (_CodePage != CP_WINUNICODE // Property set is Ansi
+ &&
+ OLECHAR_IS_UNICODE ) // Name is in Unicode
+ {
+ // Convert the caller-provided name from Unicode
+ // to the propset's Ansi codepage.
+
+ ULONG cb = 0;
+ pvName = NULL;
+ _OLECHARToMultiByte( poszName, (ULONG)-1, _CodePage,
+ (CHAR**)&pvName, &cb, pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+
+ // How long is this property name (in bytes)?
+
+ if (!_PropertyNameLength(pvName, &cbname))
+ {
+ // The length is invalid.
+ StatusInvalidParameter(pstatus, "QueryPropid: name length");
+ goto Exit;
+ }
+
+ // Get a pointer to the raw dictionary.
+
+ pdy = (DICTIONARY const *) _LoadProperty(PID_DICTIONARY, &cbDict, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // Is there a dictionary?
+
+ if (pdy != NULL)
+ {
+ // Yes - there is a dictionary.
+
+ PROPERTYSECTIONHEADER const *psh = _GetSectionHeader();
+
+ // Search the dictionary for an entry name matching
+ // pvName.
+
+ for (cdye = PropByteSwap(pdy->cEntries), pent = &pdy->rgEntry[0];
+ cdye > 0;
+ cdye--, pent = _NextDictionaryEntry( pent ))
+ {
+ // Is the length of this dictionary entry valid?
+ if ( _MapAddressToOffset(pent) + _DictionaryEntryLength( pent )
+ > psh->cbSection
+ )
+ {
+ StatusCorruption(pstatus, "QueryPropid: section size");
+ goto Exit;
+ }
+
+ // If the byte-length matches what we're looking for,
+ // and the names compare successfully, then we're done.
+
+ if ( CCh2CB(PropByteSwap( pent->cch )) == cbname
+ &&
+ _ComparePropertyNames(pvName, pent->sz,
+ FALSE, // pvName, pent->sz could be dif Endians
+ cbname)
+ )
+ {
+ propid = PropByteSwap( pent->propid );
+ break;
+ }
+ } // for (cdye = PropByteSwap(pdy->cEntries), pent = &pdy->rgEntry[0]; ...
+
+ PROPASSERT(cdye > 0 || pent == Add2ConstPtr(pdy, cbDict));
+
+ } // if (pdy != NULL)
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // If we did an alloc on the name to munge it,
+ // delete that buffer now. We must cast pvName
+ // as a non-const in order for the compiler to accept
+ // the free call.
+
+ if( pvName != poszName )
+ _pma->Free( (VOID*) pvName );
+
+ return(propid);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::QueryPropertyNameBuf
+//
+// Synopsis: convert from a property id to a property name using the
+// dictionary in the property set, and putting the result
+// in a caller-provided buffer.
+//
+// Arguments: [propid] -- property id to look up
+// [aocName] -- output buffer
+// [pcbName] -- IN: length of aocName;
+// OUT: actual length of name
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: TRUE if name is found in dictionary
+//---------------------------------------------------------------------------
+
+BOOLEAN
+CPropertySetStream::QueryPropertyNameBuf(
+ IN PROPID propid,
+ OUT OLECHAR *aocName,
+ IN OUT ULONG *pcbName,
+ OUT NTSTATUS *pstatus)
+{
+ BOOL fFound = FALSE;
+ DICTIONARY const *pdy;
+ ULONG cbDict; // BYTE granular size!
+
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(_IsMapped());
+ PROPASSERT(propid != PID_DICTIONARY);
+ PROPASSERT(PROPSET_BYTEORDER == _pph->wByteOrder);
+ PROPASSERT(NULL != aocName);
+
+ // Ensure that this isn't an already-deleted UD propset.
+ if (_State & CPSS_USERDEFINEDDELETED)
+ {
+ StatusAccessDenied(pstatus, "QueryPropertyNameBuf: deleted");
+ goto Exit;
+ }
+
+ // Get a pointer to the raw dictionary.
+
+ pdy = (DICTIONARY const *) _LoadProperty(PID_DICTIONARY, &cbDict, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // Is there a dictionary?
+ if (pdy != NULL)
+ {
+ // Yes - the dictionary was found.
+
+ ULONG cdye;
+ ENTRY UNALIGNED const *pent;
+ VOID const *pvDictEnd;
+
+ // Get pointers to the first and last+1 entries.
+
+ pent = pdy->rgEntry;
+ pvDictEnd = Add2ConstPtr(pdy, cbDict);
+
+ // Scan through the dictionary, searching for 'propid'.
+
+ for (cdye = PropByteSwap(pdy->cEntries), pent = &pdy->rgEntry[0];
+ cdye > 0;
+ cdye--, pent = _NextDictionaryEntry( pent ))
+ {
+ // Make sure this entry doesn't go off the end of the
+ // dictionary.
+
+ if (Add2ConstPtr(pent, _DictionaryEntryLength( pent )) > pvDictEnd)
+ {
+ StatusCorruption(pstatus, "QueryPropertyNameBuf: dictionary entry size");
+ goto Exit;
+ }
+
+ // Is this the PID we're looking for?
+ if (PropByteSwap(pent->propid) == propid)
+ {
+ // Yes. Copy or convert the name into the caller's
+ // buffer.
+
+ // Is a Unicode to Ansi conversion required?
+ if (_CodePage == CP_WINUNICODE // Property set is Unicode
+ &&
+ !OLECHAR_IS_UNICODE ) // Caller's buffer is Ansi
+ {
+ WCHAR *pwszName = (WCHAR*) pent->sz;
+
+ // If we're byte-swapping, alloc a new buffer, swap
+ // pwszName into it (getting the string into system-endian
+ // byte-order), and point pwszName to the result.
+
+ PBSInPlaceAlloc( &pwszName, NULL, pstatus );
+ if( !NT_SUCCESS( *pstatus )) goto Exit;
+
+ // Convert the Unicode string in the property set
+ // to the system default codepage.
+
+ _WideCharToOLECHAR( pwszName, (ULONG)-1, CP_ACP,
+ &aocName, pcbName, pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // If we allocated a buffer for byte-swapping,
+ // we don't need it any longer.
+
+ if( pwszName != (WCHAR*) pent->sz )
+ delete pwszName;
+ }
+
+ // Or is an Ansi to Unicode conversion required?
+ else
+ if (_CodePage != CP_WINUNICODE // Property set is Ansi
+ &&
+ OLECHAR_IS_UNICODE ) // Caller's buffer is Unicode
+ {
+ // Convert the Ansi property set name from the
+ // propset's codepage to Unicode.
+
+ _MultiByteToOLECHAR( (CHAR*) pent->sz, (ULONG)-1, _CodePage,
+ &aocName, pcbName, pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+
+ // Otherwise, no conversion of the name is required
+ else
+ {
+ // Copy the name into the caller's buffer.
+ RtlCopyMemory(aocName, pent->sz,
+ min(CCh2CB(PropByteSwap(pent->cch)), *pcbName));
+
+ // BUGBUG: Shouldn't we terminate the string if we truncated it?
+
+ // Swap the name to the correct endian
+ // (This will do nothing if OLECHARs are CHARs).
+ PBSBuffer( aocName,
+ min( CCh2CB(PropByteSwap( pent->cch )), *pcbName),
+ sizeof(OLECHAR) );
+
+ // Tell the caller the actual size of the name.
+ *pcbName = CCh2CB( PropByteSwap( pent->cch ));
+ }
+
+ PROPASSERT( NULL == aocName || IsOLECHARString( aocName, MAXULONG ));
+ fFound = TRUE;
+ break;
+
+ } // if (pent->propid == propid)
+ } // for (cdye = pdy->cEntries, pent = &pdy->rgEntry[0]; ...
+
+ PROPASSERT(fFound || pent == pvDictEnd);
+
+ } // if (pdy != NULL)
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return( fFound );
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::QueryPropertyNames
+//
+// Synopsis: query dictionary names for the passed property ids.
+//
+// Arguments: [cprop] -- count of name to propid mappings to change
+// [apid] -- array of property ids
+// [aposz] -- array of pointers to the new names
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: TRUE if the property exists.
+//+--------------------------------------------------------------------------
+
+BOOLEAN
+CPropertySetStream::QueryPropertyNames(
+ IN ULONG cprop,
+ IN PROPID const *apid,
+ OUT OLECHAR *aposz[],
+ OUT NTSTATUS *pstatus)
+{
+ DICTIONARY const *pdy;
+ ULONG cbDict; // BYTE granular size!
+ ULONG iprop;
+ BOOLEAN fFound = FALSE;
+
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(_HasPropHeader());
+ PROPASSERT(_IsMapped());
+ PROPASSERT(PROPSET_BYTEORDER == _pph->wByteOrder);
+
+ // If this is an attempt to access a deleted UD
+ // propset, exit now.
+ if (_State & CPSS_USERDEFINEDDELETED)
+ {
+ StatusAccessDenied(pstatus, "QueryPropertyNames: deleted");
+ goto Exit;
+ }
+
+ // Validate the input array of strings.
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ PROPASSERT(aposz[iprop] == NULL);
+ }
+
+ // Get a pointer to the beginning of the dictionary
+ pdy = (DICTIONARY const *) _LoadProperty(PID_DICTIONARY, &cbDict, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // Did we get a dictionary?
+ if (pdy != NULL)
+ {
+ // Yes, the dictionary exists.
+
+ ULONG i;
+ ENTRY UNALIGNED const *pent;
+
+ // Iterate through each of the entries in the dictionary.
+
+ for (i = 0, pent = &pdy->rgEntry[0];
+ i < PropByteSwap( pdy->cEntries );
+ i++, pent = _NextDictionaryEntry( pent ))
+ {
+ // Scan the input array of PIDs to see if one matches
+ // this dictionary entry.
+
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ if( PropByteSwap(pent->propid) == apid[iprop] )
+ {
+ // We've found an entry in the dictionary
+ // that's in the input PID array. Put the property's
+ // name in the caller-provided array (aposz).
+
+ PROPASSERT(aposz[iprop] == NULL);
+
+ // Do we need to convert to Unicode?
+
+ if (_CodePage != CP_WINUNICODE // Ansi property set
+ &&
+ OLECHAR_IS_UNICODE) // Unicode property names
+ {
+ ULONG cbName = 0;
+ _MultiByteToOLECHAR( (CHAR*)pent->sz, (ULONG)-1, _CodePage,
+ &aposz[iprop], &cbName, pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+
+ // Or, do we need to convert to Ansi?
+ else
+ if (_CodePage == CP_WINUNICODE // Unicode property set
+ &&
+ !OLECHAR_IS_UNICODE) // Ansi property names
+ {
+ ULONG cbName = 0;
+ WCHAR *pwszName = (WCHAR*) pent->sz;
+
+ // If necessary, swap the Unicode name in the dictionary,
+ // pointing pwszName to the new, byte-swapped, buffer.
+
+ PBSInPlaceAlloc( &pwszName, NULL, pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // And convert to Ansi.
+ _WideCharToOLECHAR( pwszName, (ULONG)-1, CP_ACP,
+ &aposz[iprop], &cbName, pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // If we alloced a new buffer for byte-swapping,
+ // we can free it now.
+
+ if( pwszName != (WCHAR*) pent->sz )
+ delete pwszName;
+
+ } // else if (_CodePage == CP_WINUNICODE ...
+
+ // Otherwise, both the propset & in-memory property names
+ // are both Unicode or both Ansi, so we can just do
+ // an alloc & copy.
+
+ else
+ {
+ aposz[iprop] = DuplicatePropertyName(
+ (OLECHAR *) pent->sz,
+ CCh2CB( PropByteSwap( pent->cch )),
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // If necessary, swap the in-memory copy.
+ PBSBuffer( (OLECHAR*) aposz[iprop],
+ CCh2CB( PropByteSwap( pent->cch )),
+ sizeof(OLECHAR) );
+
+ } // if (_CodePage != CP_WINUNICODE ... else if ... else
+
+ PROPASSERT( IsOLECHARString( aposz[iprop], MAXULONG ));
+
+ fFound = TRUE;
+
+ } // if (pent->propid == apid[iprop])
+ } // for (iprop = 0; iprop < cprop; iprop++)
+ } // for (i = 0, pent = &pdy->rgEntry[0];
+
+ PROPASSERT(pent == Add2ConstPtr(pdy, cbDict));
+
+ } // if (pdy != NULL)
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // If the property name simply didn't exist, return
+ // a special success code.
+
+ if( !fFound && NT_SUCCESS(*pstatus) )
+ *pstatus = STATUS_BUFFER_ALL_ZEROS;
+
+ return( fFound );
+
+} // CPropertySetStream::QueryPropertyNames
+
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::SetPropertyNames
+//
+// Synopsis: changes dictionary entry names associated with property ids.
+//
+// Arguments: [cprop] -- count of name to propid mappings to change
+// [apid] -- array of property ids
+// [aposz] -- array of pointers to the new names
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: None
+//
+// Note: Attempting to set a property name for a property that does not
+// exist in the property set is not an error.
+//
+// Attempting to set a property name or property id that would
+// result in a duplicate name or property id causes the existing
+// entry(ies) to be replaced.
+//+--------------------------------------------------------------------------
+
+VOID
+CPropertySetStream::SetPropertyNames(
+ IN ULONG cprop,
+ IN const PROPID *apid,
+ IN OPTIONAL OLECHAR const * const aposz[],
+ OUT NTSTATUS *pstatus )
+{
+
+ // ------
+ // Locals
+ // ------
+
+ DICTIONARY *pdy = NULL;
+ ULONG cbDictOld = 0; // Byte granular Old dictionary size
+ ULONG cbDictOldD = 0; // Dword granular Old dictionary size
+ ULONG iprop = 0;
+ ULONG i = 0;
+ ULONG cDel, cAdd;
+ LONG cbDel, cbAdd; // Byte granular sizes
+ LONG cbChangeD; // Dword granular size
+ ENTRY UNALIGNED *pent;
+ BOOLEAN fDupPropid = FALSE;
+ BOOLEAN fDupName = FALSE;
+ BOOLEAN fDeleteByName = FALSE;
+ BOOLEAN fDeleteAll = FALSE;
+ VOID **appvNames = NULL;
+
+ ULONG cbstm;
+ ULONG oDictionary;
+ ULONG cbTail;
+ ULONG cbNewSize;
+
+ // ----------
+ // Initialize
+ // ----------
+
+ *pstatus = STATUS_SUCCESS;
+
+ DebugTrace(0, Dbg, (
+ "SetPropertyNames(cprop=%x, apid=%x, apwsz=%x)\n",
+ cprop,
+ apid,
+ aposz));
+
+ PROPASSERT(_HasPropHeader());
+ PROPASSERT(_IsMapped());
+ PROPASSERT(PROPSET_BYTEORDER == _pph->wByteOrder);
+
+ // --------
+ // Validate
+ // --------
+
+ // Verify that this propset is modifiable.
+ if (IsReadOnlyPropertySet(_Flags, _State))
+ {
+ StatusAccessDenied(pstatus, "SetPropertyNames: deleted or read-only");
+ goto Exit;
+ }
+
+ // Verify that none of the names are illegally long.
+
+ if (aposz != NULL)
+ {
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ PROPASSERT( IsOLECHARString( aposz[iprop], MAXULONG ));
+
+ if (ocslen( aposz[iprop] ) > CCH_MAXPROPNAME)
+ {
+ StatusInvalidParameter(pstatus, "SetPropertyNames: Name is too long" );
+ goto Exit;
+ }
+ }
+ } // if (apwsz != NULL)
+
+ // ----------------------------------------------------------------
+ // If necessary, convert each of the caller-provided names:
+ // to Unicode (if the property set is Unicode) or Ansi (otherwise).
+ // ----------------------------------------------------------------
+
+ // In the end, appvNames will have the names in the same codepage
+ // as the property set.
+
+ appvNames = (VOID **) aposz;
+ if (appvNames != NULL)
+ {
+ // Do we need to convert the caller's names to Ansi?
+
+ if( _CodePage != CP_WINUNICODE // Property set is Ansi
+ &&
+ OLECHAR_IS_UNICODE ) // Caller's names are Unicode
+ {
+ // Allocate an array of cprop string pointers.
+
+ appvNames = (VOID **) newk(mtPropSetStream, NULL) char *[cprop];
+ if (appvNames == NULL)
+ {
+ StatusNoMemory(pstatus, "SetpropertyNames: Ansi Name Pointers");
+ goto Exit;
+ }
+ RtlZeroMemory(appvNames, cprop * sizeof(appvNames[0]));
+
+ // Convert the caller-provided property names from Unicode to
+ // the property set's codepage.
+
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ ULONG cb = 0;
+ appvNames[iprop] = NULL;
+ _OLECHARToMultiByte( (OLECHAR*) aposz[iprop], (ULONG)-1, _CodePage,
+ (CHAR**) &appvNames[iprop], &cb, pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+ } // if( _CodePage != CP_WINUNICODE ...
+
+ // Or, do we need to convert the caller's names to Unicode?
+
+ if( _CodePage == CP_WINUNICODE // Property set is Unicode
+ &&
+ !OLECHAR_IS_UNICODE ) // Caller's names are Ansi
+ {
+ // Allocate an array of cprop string pointers.
+
+ appvNames = (VOID **) newk(mtPropSetStream, NULL) WCHAR *[cprop];
+ if (appvNames == NULL)
+ {
+ StatusNoMemory(pstatus, "SetpropertyNames: Unicode Name Pointers");
+ goto Exit;
+ }
+ RtlZeroMemory(appvNames, cprop * sizeof(appvNames[0]));
+
+ // Convert the caller-provided property names from the system
+ // default Ansi codepage to Unicode.
+
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ ULONG cb = 0;
+ appvNames[iprop] = NULL;
+ _OLECHARToWideChar( (OLECHAR*) aposz[iprop], (ULONG)-1, CP_ACP,
+ (WCHAR**) &appvNames[iprop], &cb, pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+ } // if( _CodePage == CP_WINUNICODE )
+ } // if (appvNames != NULL)
+
+
+ // -----------------------------------------------------
+ // Compute total size of entries to be modified or added
+ // -----------------------------------------------------
+
+ cbAdd = 0;
+ cAdd = 0;
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ // Did the caller give us no array of names? If so,
+ // it means that the name for this PID is to be deleted.
+
+ if (appvNames == NULL)
+ {
+ // If the PID is for the dictionary, then it must be the
+ // only entry in apid, and it indicates that we're going to
+ // delete all the names in the dictionary.
+
+ if (apid[iprop] == PID_DICTIONARY)
+ {
+ if (cprop != 1)
+ {
+ StatusInvalidParameter(pstatus, "SetPropertyNames: DeleteAll parms");
+ goto Exit;
+ }
+ fDeleteAll = TRUE;
+ }
+ }
+
+ // Otherwise, we're setting a new name for this PID.
+
+ else
+ {
+ ULONG cbname;
+
+ // Validate the caller-provided length.
+
+ if (!_PropertyNameLength(appvNames[iprop], &cbname))
+ {
+ StatusInvalidParameter(pstatus, "SetPropertyNames: name length");
+ goto Exit;
+ }
+
+ // See if this propid or name appears later in the array.
+
+ for (i = iprop + 1; i < cprop; i++)
+ {
+ ULONG cbname2;
+
+ if (apid[i] == apid[iprop])
+ {
+ fDupPropid = TRUE;
+ break;
+ }
+
+ _PropertyNameLength(appvNames[i], &cbname2);
+
+ if (cbname == cbname2 &&
+ _ComparePropertyNames(
+ appvNames[iprop],
+ appvNames[i],
+ TRUE, // Both names are in the same byte-order
+ cbname))
+ {
+ fDupName = TRUE;
+ break;
+ }
+ }
+
+ // If this propid appears only once or if it's the last instance,
+ // count it. If the property set is Unicode, include DWORD padding.
+
+ if (i == cprop)
+ {
+ DebugTrace(0, Dbg, (
+ _CodePage == CP_WINUNICODE?
+ "Adding New Entry: propid=%lx L'%ws'\n" :
+ "Adding New Entry: propid=%lx '%s'\n",
+ apid[iprop],
+ appvNames[iprop]));
+
+ cAdd++;
+
+ cbAdd += CB_ENTRY + cbname;
+ if( _CodePage == CP_WINUNICODE )
+ {
+ cbAdd = DwordAlign( cbAdd );
+ }
+ }
+ }
+ }
+ PROPASSERT( _CodePage == CP_WINUNICODE ? IsDwordAligned( cbAdd ) : TRUE );
+
+
+ // ---------------------------------------------
+ // Get the dictionary, creating it if necessary.
+ // ---------------------------------------------
+
+ _SetModified();
+
+ for (i = 0; ; i++)
+ {
+ PROPERTY_INFORMATION pinfo;
+ PROPVARIANT var;
+
+ pdy = (DICTIONARY *) _LoadProperty(PID_DICTIONARY, &cbDictOld, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if (pdy != NULL)
+ {
+ break;
+ }
+ PROPASSERT(i == 0);
+ if (cprop == 0 || appvNames == NULL)
+ {
+ // no dictionary and we are deleting or doing nothing -- return
+ goto Exit;
+ }
+ // create dictionary if it doesn't exist
+ DebugTrace(0, Dbg, ("Creating empty dictionary\n"));
+
+ PROPASSERT(CB_SERIALIZEDPROPERTYVALUE == CB_DICTIONARY);
+ pinfo.cbprop = CB_SERIALIZEDPROPERTYVALUE;
+ pinfo.pid = PID_DICTIONARY;
+
+ var.vt = VT_DICTIONARY;
+ SetValue(1, NULL, &var, &pinfo, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ Validate(pstatus); // Make sure dictionary was properly created
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ DebugTrace(0, Dbg, ("Created empty dictionary\n"));
+
+ } // for (i = 0; ; i++)
+
+ // ----------------------------------------------------------------
+ // Compute total size of existing entries to be modified or deleted
+ // ----------------------------------------------------------------
+
+ // Walk the dictionary looking for entries which are referenced
+ // in the caller's 'apid' array or 'appvNames' array.
+
+ cbDel = 0;
+ cDel = 0;
+ for (i = 0, pent = &pdy->rgEntry[0];
+ i < PropByteSwap( pdy->cEntries );
+ i++, pent = _NextDictionaryEntry( pent ))
+ {
+ DebugTrace(0, Dbg, (
+ _CodePage == CP_WINUNICODE?
+ "Dictionary Entry @%lx: propid=%lx L'%ws'\n" :
+ "Dictionary Entry @%lx: propid=%lx '%s'\n",
+ pent,
+ PropByteSwap( pent->propid ),
+ pent->sz ));
+
+ // For this dictionary entry, walk the caller's
+ // 'apid' and 'appvNames' arrays, looking for a match.
+
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ // If we get to the bottom of this 'for' loop,
+ // then we know that we've found an entry to delete.
+ // If fDeleteAll, or the PID in apid matches this
+ // dictionary entry, then we can fall to the bottom.
+ // Otherwise, the following 'if' block checks the
+ // name in 'appvNames' against this dictionary entry.
+
+ if (!fDeleteAll
+ &&
+ apid[iprop] != PropByteSwap( pent->propid ))
+ {
+ // The caller's PID didn't match this dictionary entry,
+ // does the name?
+
+ ULONG cbname;
+
+ // If we have no names from the caller, then we obviously
+ // don't have a match, and we can continue on to check this
+ // dictionary entry against the next of the caller's PIDs.
+
+ if (appvNames == NULL)
+ {
+ continue;
+ }
+
+ // Or, if this name from the caller doesn't match this
+ // dictionary entry, we again can continue on to check
+ // the next of the caller's properties.
+
+ _PropertyNameLength(appvNames[iprop], &cbname);
+ if (cbname != CCh2CB( PropByteSwap( pent->cch ))
+ ||
+ !_ComparePropertyNames(
+ appvNames[iprop],
+ pent->sz,
+ FALSE, // appvNames & pent->sz may be dif endians.
+ cbname)
+ )
+ {
+ continue;
+ }
+ fDeleteByName = TRUE;
+
+ } // if (!fDeleteAll ...
+
+ // If we reach this point, we're going to delete this entry
+ // in the dictionary. So update cDel & cbDel.
+
+ DebugTrace(0, Dbg, (
+ "Deleting Entry (%s) @%lx: propid=%lx\n",
+ fDeleteAll? "DeleteAll" :
+ apid[iprop] == PropByteSwap(pent->propid)
+ ? "replace by propid"
+ : "replace by name",
+ pent,
+ PropByteSwap( pent->propid )));
+
+ cDel++;
+ cbDel += _DictionaryEntryLength( pent );
+
+ // We don't need to continue through the caller's arrays,
+ // we can move on to the next dictionary entry.
+
+ break;
+
+ } // for (iprop = 0; iprop < cprop; iprop++)
+ } // for (i = 0, pent = &pdy->rgEntry[0]; ...
+
+ PROPASSERT(pent == Add2Ptr(pdy, cbDictOld));
+ PROPASSERT( _CodePage == CP_WINUNICODE ? IsDwordAligned( cbDel ) : TRUE );
+
+
+ cbDictOldD = DwordAlign(cbDictOld);
+ cbChangeD = DwordAlign(cbDictOld + cbAdd - cbDel) - cbDictOldD;
+
+ cbstm = _oSection + _GetSectionHeader()->cbSection + _cbTail;
+ oDictionary = _MapAddressToOffset(pdy);
+ cbTail;
+
+ cbTail = cbstm - (_oSection + oDictionary + cbDictOldD);
+
+ // --------------------------------------------------------
+ // Before we change anything, grow the stream if necessary.
+ // --------------------------------------------------------
+
+ if (cbChangeD > 0)
+ {
+ DebugTrace(0, Dbg, (
+ "SetSize(%x) dictionary grow\n", cbstm + cbChangeD));
+ if (cbstm + cbChangeD > CBMAXPROPSETSTREAM)
+ {
+ StatusDiskFull(pstatus, "SetPropertyNames: 256k limit");
+ goto Exit;
+ }
+
+ _MSTM(SetSize)(cbstm + cbChangeD, TRUE, (VOID **) &_pph, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // reload all pointers into mapped image:
+
+ pdy = (DICTIONARY *) _MapOffsetToAddress(oDictionary);
+
+ // move everything after the dictionary back by cbChangeD bytes.
+
+ PropMoveMemory(
+ "SetPropertyNames:TailBack",
+ _GetSectionHeader(),
+ Add2Ptr(pdy, cbDictOldD + cbChangeD),
+ Add2Ptr(pdy, cbDictOldD),
+ cbTail);
+ }
+
+ // -------------------------------------------------------------------
+ // Walk through the existing dictionary and compact unmodified entries
+ // toward the front. New and modified entries will be appended later.
+ // -------------------------------------------------------------------
+
+ VOID *pvSrc;
+ VOID *pvDst;
+ ULONG cbCopy;
+
+ pvDst = pvSrc = pent = &pdy->rgEntry[0];
+ cbCopy = 0;
+
+ if (!fDeleteAll)
+ {
+ ULONG cb;
+
+ for (i = 0; i < PropByteSwap(pdy->cEntries); i++)
+ {
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ if( apid[iprop] == PropByteSwap(pent->propid) )
+ {
+ break;
+ }
+ if (fDeleteByName) // if deleting any properties by name
+ {
+ ULONG cbname;
+
+ _PropertyNameLength(appvNames[iprop], &cbname);
+ if (cbname == CCh2CB( PropByteSwap( pent->cch ))
+ &&
+ _ComparePropertyNames(
+ appvNames[iprop],
+ pent->sz,
+ FALSE, // appvNames & pent->sz may be dif endians
+ cbname)
+ )
+ {
+ break; // found an entry to be removed.
+ }
+ }
+ } // for (iprop = 0; iprop < cprop; iprop++)
+
+ cb = _DictionaryEntryLength( pent );
+ pent = _NextDictionaryEntry( pent );
+
+ if (iprop == cprop) // keep the dictionary entry
+ {
+ cbCopy += cb;
+ }
+ else // remove the dictionary entry
+ {
+ if (cbCopy != 0)
+ {
+ if (pvSrc != pvDst)
+ {
+ PropMoveMemory(
+ "SetPropertyNames:Compact",
+ _GetSectionHeader(),
+ pvDst,
+ pvSrc,
+ cbCopy);
+ }
+ pvDst = Add2Ptr(pvDst, cbCopy);
+ cbCopy = 0;
+ }
+ pvSrc = pent;
+ }
+ } // for (i = 0; i < PropByteSwap(pdy->cEntries); i++)
+
+ // Compact last chunk and point past compacted entries.
+
+ if (cbCopy != 0 && pvSrc != pvDst)
+ {
+ PropMoveMemory(
+ "SetPropertyNames:CompactLast",
+ _GetSectionHeader(),
+ pvDst,
+ pvSrc,
+ cbCopy);
+ }
+ pent = (ENTRY UNALIGNED *) Add2Ptr(pvDst, cbCopy);
+
+ } // if (!fDeleteAll)
+
+ pdy->cEntries = PropByteSwap( PropByteSwap(pdy->cEntries) - cDel );
+
+ // ------------------------------------
+ // Append new and modified entries now.
+ // ------------------------------------
+
+ if (appvNames != NULL)
+ {
+ // Add each name to the property set.
+
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ // See if this propid appears later in the array.
+
+ i = cprop;
+ if (fDupPropid)
+ {
+ for (i = iprop + 1; i < cprop; i++)
+ {
+ if (apid[i] == apid[iprop])
+ {
+ break;
+ }
+ }
+ }
+
+ // See if this name appears later in the array.
+
+ if (i == cprop && fDupName)
+ {
+ ULONG cbname;
+
+ _PropertyNameLength(appvNames[iprop], &cbname);
+
+ for (i = iprop + 1; i < cprop; i++)
+ {
+ ULONG cbname2;
+
+ _PropertyNameLength(appvNames[i], &cbname2);
+
+ if (cbname == cbname2 &&
+ _ComparePropertyNames(
+ appvNames[iprop],
+ appvNames[i],
+ TRUE, // Both names are the same endian
+ cbname))
+ {
+ break;
+ }
+ }
+ }
+
+ // If this propid appears only once or if it's the last instance,
+ // append the mapping entry.
+
+ if (i == cprop)
+ {
+ ULONG cbname;
+
+ // Set the PID & character-count fields for this entry.
+ _PropertyNameLength(appvNames[iprop], &cbname);
+ pent->propid = PropByteSwap( apid[iprop] );
+ pent->cch = PropByteSwap( CB2CCh( cbname ));
+
+ // Copy the name into the dictionary.
+ RtlCopyMemory(pent->sz, appvNames[iprop], cbname);
+
+ // If this is a Unicode property set, we need to correct
+ // the byte-order.
+
+ if( CP_WINUNICODE == _CodePage )
+ {
+ PBSBuffer( pent->sz, cbname, sizeof(WCHAR) );
+ }
+
+ // Zero-out the pad bytes.
+
+ RtlZeroMemory(
+ Add2Ptr(pent->sz, cbname),
+ DwordRemain((ULONG) pent->sz + cbname));
+
+
+ pent = _NextDictionaryEntry( pent );
+ }
+ } // for (iprop = 0; iprop < cprop; iprop++)
+
+ // We've added all the names, now let's update the entry count.
+ pdy->cEntries = PropByteSwap( PropByteSwap(pdy->cEntries) + cAdd );
+
+ } // if (appvNames != NULL)
+
+ // Zero the possible partial DWORD at the end of the dictionary.
+
+ {
+ ULONG cb = (ULONG) ((BYTE *) pent - (BYTE *) pdy);
+ PROPASSERT(DwordAlign(cb) == cbDictOldD + cbChangeD);
+ RtlZeroMemory(pent, DwordRemain(cb));
+ }
+
+
+ // -----------------------------------------------------
+ // Adjust the remaining property offsets in the section.
+ // -----------------------------------------------------
+
+ PROPERTYIDOFFSET *ppo, *ppoMax;
+ PROPERTYSECTIONHEADER *psh;
+
+ psh = _LoadPropertyOffsetPointers(&ppo, &ppoMax, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ PROPASSERT(psh != NULL);
+
+ // Don't rely on the dictionary being the first property.
+ // Skip PID_DICTIONARY and adjust every other higher entry.
+
+ for ( ; ppo < ppoMax; ppo++)
+ {
+ if (ppo->dwOffset > oDictionary)
+ {
+ ppo->dwOffset += cbChangeD;
+ PROPASSERT(ppo->propid != PID_DICTIONARY);
+ }
+ }
+
+ // Update the size of the section
+ psh->cbSection += cbChangeD;
+
+ if (cbChangeD < 0)
+ {
+ // move everything after the dictionary forward by cbChangeD bytes.
+
+ PropMoveMemory(
+ "SetPropertyNames:TailUp",
+ _GetSectionHeader(),
+ Add2Ptr(pdy, cbDictOldD + cbChangeD),
+ Add2Ptr(pdy, cbDictOldD),
+ cbTail);
+ }
+ if (_cbTail != 0)
+ {
+ _PatchSectionOffsets(cbChangeD);
+ }
+
+ // If we need to shrink the stream or if we are cleaning up after a
+ // previous shrink that failed, do it last.
+
+ cbNewSize = _MSTM(GetSize)(pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if ( cbNewSize != cbstm + cbChangeD)
+ {
+ DebugTrace(0, Dbg, (
+ "SetSize(%x) dictionary shrink\n",
+ cbstm + cbChangeD));
+ _MSTM(SetSize)(cbstm + cbChangeD, TRUE, (VOID **) &_pph, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // If we had to convert the array of names into a different
+ // codepage, delete those temporary buffers now.
+
+ if (appvNames != NULL && appvNames != (VOID **) aposz)
+ {
+ for (iprop = 0; iprop < cprop; iprop++)
+ {
+ _pma->Free( appvNames[iprop] );
+ }
+ delete [] (char **) appvNames;
+ }
+
+ DebugTrace(0, Dbg, ("SetPropertyNames() ==> s=%x\n", STATUS_SUCCESS));
+ return;
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_ValidateStructure
+//
+// Synopsis: validate property set structure
+//
+// Arguments: [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: None
+//+--------------------------------------------------------------------------
+
+#if DBGPROP
+VOID
+CPropertySetStream::_ValidateStructure(OUT NTSTATUS *pstatus)
+{
+ PROPID propid;
+ ULONG cb;
+
+ OLECHAR aocName[ CCH_MAXPROPNAMESZ ];
+ ULONG cbName;
+
+ *pstatus = STATUS_SUCCESS;
+
+ // Walk through properties to make sure all properties are consistent
+ // and are contained within the section size. A NULL return value
+ // means _LoadProperty walked the entire section, so we can quit then.
+
+ for (propid = PID_CODEPAGE; propid != PID_ILLEGAL; propid++)
+ {
+ SERIALIZEDPROPERTYVALUE const *pprop;
+
+ pprop = GetValue(propid, &cb, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if (NULL == pprop)
+ {
+ break;
+ }
+ }
+
+ // Walk through dictionary entries to make sure all entries are consistent
+ // and are contained within the dictionary size. A FALSE return value
+ // means QueryPropertyNameBuf walked the entire dictionary, so quit then.
+
+ for (propid = PID_CODEPAGE + 1; propid != PID_ILLEGAL; propid++)
+ {
+ BOOL fExists;
+ cb = 0;
+
+ cbName = sizeof(aocName);
+ fExists = QueryPropertyNameBuf(propid, aocName, &cbName, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if( !fExists )
+ {
+ break;
+ }
+ }
+
+ if (_cSection > 1)
+ {
+ FORMATIDOFFSET const *pfo;
+
+ if (_cSection != 2)
+ {
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "_ValidateStructure: csection(%x) != 2",
+ _cSection));
+ StatusCorruption(pstatus, "_ValidateStructure: csection != 2");
+ goto Exit;
+ }
+ pfo = _GetFormatidOffset(0);
+ if (pfo->fmtid != guidDocumentSummary)
+ {
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "_ValidateStructure: DocumentSummary[0] fmtid"));
+ StatusCorruption(pstatus, "_ValidateStructure: DocumentSummary[0] fmtid");
+ goto Exit;
+ }
+ if (!IsDwordAligned(pfo->dwOffset))
+ {
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "_ValidateStructure: dwOffset[0] = %x",
+ pfo->dwOffset));
+ StatusCorruption(pstatus, "_ValidateStructure: dwOffset[0]");
+ goto Exit;
+ }
+
+ pfo = _GetFormatidOffset(1);
+ if (pfo->fmtid != guidDocumentSummarySection2)
+ {
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "_ValidateStructure: DocumentSummary[1] fmtid"));
+ StatusCorruption(pstatus, "_ValidateStructure: DocumentSummary[1] fmtid");
+ goto Exit;
+ }
+ if (!IsDwordAligned(pfo->dwOffset))
+ {
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "_ValidateStructure: dwOffset[1] = %x",
+ pfo->dwOffset));
+ StatusCorruption(pstatus, "_ValidateStructure: dwOffset[1]");
+ goto Exit;
+ }
+ } // if (_cSection > 1)
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+}
+#endif
+
+
+//+--------------------------------------------------------------------------
+// Member: fnPropidCompare
+//
+// Synopsis: qsort helper to compare propids in a PROPERTYIDOFFSET array.
+//
+// Arguments: [ppo1] -- pointer to PROPERTYIDOFFSET 1
+// [ppo2] -- pointer to PROPERTYIDOFFSET 2
+//
+// Returns: difference
+//+--------------------------------------------------------------------------
+
+#if DBGPROP
+INT _CRTAPI1
+fnPropidCompare(VOID const *ppo1, VOID const *ppo2)
+{
+ return(((PROPERTYIDOFFSET const *) ppo1)->propid -
+ ((PROPERTYIDOFFSET const *) ppo2)->propid);
+}
+#endif
+
+
+//+--------------------------------------------------------------------------
+// Member: fnOffsetCompare
+//
+// Synopsis: qsort helper to compare offsets in a PROPERTYIDOFFSET array.
+//
+// Arguments: [ppo1] -- pointer to PROPERTYIDOFFSET 1
+// [ppo2] -- pointer to PROPERTYIDOFFSET 2
+//
+// Returns: difference
+//+--------------------------------------------------------------------------
+
+INT _CRTAPI1
+fnOffsetCompare(VOID const *ppo1, VOID const *ppo2)
+{
+ return(((PROPERTYIDOFFSET const *) ppo1)->dwOffset -
+ ((PROPERTYIDOFFSET const *) ppo2)->dwOffset);
+}
+
+
+//+--------------------------------------------------------------------------
+// Member: GetStringLength
+//
+// Synopsis: return length of possibly unicode string.
+//
+// Arguments: [CodePage] -- TRUE if string is Unicode
+// [pwsz] -- pointer to string
+// [cb] -- MAXULONG or string length with L'\0' or '\0'
+//
+// Returns: length of string in bytes including trailing L'\0' or '\0'
+//+--------------------------------------------------------------------------
+
+ULONG
+GetStringLength(
+ IN USHORT CodePage,
+ IN WCHAR const *pwsz,
+ IN ULONG cb)
+{
+ ULONG i;
+
+ if (CodePage == CP_WINUNICODE)
+ {
+ for (i = 0; i < cb/sizeof(WCHAR); i++)
+ {
+ if (pwsz[i] == L'\0')
+ {
+ break;
+ }
+ }
+ PROPASSERT(cb == MAXULONG || cb == (i + 1) * sizeof(WCHAR));
+ return((i + 1) * sizeof(WCHAR));
+ }
+ else
+ {
+ char *psz = (char *) pwsz;
+
+ for (i = 0; i < cb; i++)
+ {
+ if (psz[i] == '\0')
+ {
+ break;
+ }
+ }
+ PROPASSERT(cb == MAXULONG || cb == (i + 1) * sizeof(char));
+ return((i + 1) * sizeof(char));
+ }
+}
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_ValidateProperties
+//
+// Synopsis: validate properties
+//
+// Arguments: [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: None
+//+--------------------------------------------------------------------------
+
+#if DBGPROP
+VOID
+CPropertySetStream::_ValidateProperties(OUT NTSTATUS *pstatus) const
+{
+ PROPERTYIDOFFSET *apo = NULL;
+ PROPERTYSECTIONHEADER const *psh = _GetSectionHeader();
+ static ULONG cValidate = 0;
+ ULONG cbwasted = 0;
+ ULONG cbtotal = 0;
+
+ *pstatus = STATUS_SUCCESS;
+
+ cValidate++;
+ DebugTrace(0, DEBTRACE_PROPVALIDATE, (
+ "_ValidateProperties(%x ppsstm=%x state=%x pph=%x)\n",
+ cValidate,
+ this,
+ _State,
+ _pph));
+
+ if (psh->cProperties != 0)
+ {
+ PROPERTYIDOFFSET *ppo, *ppoMax;
+
+ apo = newk(mtPropSetStream, NULL) PROPERTYIDOFFSET[psh->cProperties + 1];
+ if (apo == NULL)
+ {
+ *pstatus = STATUS_NO_MEMORY;
+ goto Exit;
+ }
+
+ RtlCopyMemory(
+ apo,
+ psh->rgprop,
+ psh->cProperties * CB_PROPERTYIDOFFSET);
+
+ ppoMax = apo + psh->cProperties;
+ ppoMax->propid = PID_ILLEGAL;
+ ppoMax->dwOffset = psh->cbSection;
+
+ // Sort by property id and check for duplicate propids:
+
+ qsort(apo, psh->cProperties, sizeof(apo[0]), fnPropidCompare);
+
+ for (ppo = apo; ppo < ppoMax; ppo++)
+ {
+ if (ppo->propid == PID_ILLEGAL ||
+ ppo->propid == ppo[1].propid)
+ {
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "_ValidateProperties(bad propid=%x @%x)\n",
+ ppo->propid,
+ ppo->dwOffset));
+ StatusCorruption(pstatus, "_ValidateProperties: bad or dup propid");
+ goto Exit;
+ }
+ }
+
+ // Sort by offset and check for overlapping values:
+
+ qsort(apo, psh->cProperties, sizeof(apo[0]), fnOffsetCompare);
+
+ cbtotal = _oSection;
+ for (ppo = apo; ppo < ppoMax; ppo++)
+ {
+ ULONG cbdiff, cbprop, cbpropraw;
+ SERIALIZEDPROPERTYVALUE const *pprop;
+
+ cbprop = MAXULONG;
+ cbpropraw = cbprop;
+ cbdiff = ppo[1].dwOffset - ppo->dwOffset;
+ if (IsDwordAligned(ppo->dwOffset) &&
+ IsDwordAligned(ppo[1].dwOffset))
+ {
+ pprop = (SERIALIZEDPROPERTYVALUE const *)
+ _MapOffsetToAddress(ppo->dwOffset);
+
+ if (ppo->propid == PID_DICTIONARY)
+ {
+ cbprop = _DictionaryLength(
+ (DICTIONARY const *) pprop,
+ cbdiff,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ cbpropraw = cbprop;
+ cbprop = DwordAlign(cbprop);
+ }
+ else
+ {
+ cbprop = PropertyLengthNoEH(pprop, cbdiff, 0, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ cbpropraw = cbprop;
+ }
+ DebugTrace(0, DEBTRACE_PROPVALIDATE, (
+ "_ValidateProperties(%x) i=%x cb=%x/%x/%x @%x/%x pid=%x\n",
+ cValidate,
+ ppo - apo,
+ cbprop,
+ cbdiff,
+ ppo->dwOffset,
+ pprop,
+ ppo->propid));
+ cbtotal += cbdiff;
+
+ // Technically, the OLE spec allows extra unused space
+ // between properties, but this implementation never
+ // writes out streams with space between properties.
+
+ if (cbdiff == cbprop)
+ {
+ continue;
+ }
+ }
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "_ValidateProperties(bad value length: propid=%x @%x/%x cb=%x/%x/%x ppsstm=%x)\n",
+ ppo->propid,
+ ppo->dwOffset,
+ pprop,
+ cbpropraw,
+ cbprop,
+ cbdiff,
+ this));
+ StatusCorruption(pstatus, "_ValidateProperties: bad property length");
+ goto Exit;
+
+ } // for (ppo = apo; ppo < ppoMax; ppo++)
+
+ } // if (psh->cProperties != 0)
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ delete [] apo;
+
+ DebugTrace(0, cbwasted != 0? 0 : Dbg, (
+ "_ValidateProperties(wasted %x bytes, total=%x)\n",
+ cbwasted,
+ cbtotal));
+
+}
+#endif
+
+
+#if DBGPROP
+typedef struct tagENTRYVALIDATE // ev
+{
+ ENTRY UNALIGNED const *pent;
+ CPropertySetStream const *ppsstm;
+} ENTRYVALIDATE;
+#endif
+
+
+//+--------------------------------------------------------------------------
+// Member: fnEntryPropidCompare
+//
+// Synopsis: qsort helper to compare propids in a ENTRYVALIDATE array.
+//
+// Arguments: [pev1] -- pointer to ENTRYVALIDATE 1
+// [pev2] -- pointer to ENTRYVALIDATE 2
+//
+// Returns: difference
+//+--------------------------------------------------------------------------
+
+#if DBGPROP
+INT _CRTAPI1
+fnEntryPropidCompare(VOID const *pev1, VOID const *pev2)
+{
+ return(((ENTRYVALIDATE const *) pev1)->pent->propid -
+ ((ENTRYVALIDATE const *) pev2)->pent->propid);
+}
+#endif
+
+
+//+--------------------------------------------------------------------------
+// Member: fnEntryNameCompare
+//
+// Synopsis: qsort helper to compare names in a ENTRYVALIDATE array.
+//
+// Arguments: [pev1] -- pointer to ENTRYVALIDATE 1
+// [pev2] -- pointer to ENTRYVALIDATE 2
+//
+// Returns: difference
+//+--------------------------------------------------------------------------
+
+#if DBGPROP
+INT _CRTAPI1
+fnEntryNameCompare(VOID const *pev1, VOID const *pev2)
+{
+ ENTRY UNALIGNED const *pent1;
+ ENTRY UNALIGNED const *pent2;
+ INT rc;
+
+ pent1 = ((ENTRYVALIDATE const *) pev1)->pent;
+ pent2 = ((ENTRYVALIDATE const *) pev2)->pent;
+
+ rc = PropByteSwap(pent1->cch) - PropByteSwap(pent2->cch);
+ if (rc == 0)
+ {
+ rc = !((ENTRYVALIDATE const *) pev1)->ppsstm->_ComparePropertyNames(
+ pent1->sz,
+ pent2->sz,
+ TRUE, // Both names have the same byte-order
+ ( (ENTRYVALIDATE const *)
+ pev1
+ )->ppsstm->CCh2CB(PropByteSwap( pent1->cch )));
+ }
+ return(rc);
+}
+#endif
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::_ValidateDictionary
+//
+// Synopsis: validate property set dictionary
+//
+// Arguments: [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: None
+//+--------------------------------------------------------------------------
+
+#if DBGPROP
+VOID
+CPropertySetStream::_ValidateDictionary(OUT NTSTATUS *pstatus)
+{
+ DICTIONARY const *pdy;
+ ULONG cbDict; // BYTE granular size!
+
+ ENTRYVALIDATE *aev = NULL;
+ ENTRYVALIDATE *pev, *pevMax;
+ PROPERTYSECTIONHEADER const *psh;
+ ENTRY UNALIGNED const *pent;
+ ENTRY entMax;
+ VOID const *pvDictEnd;
+
+ *pstatus = STATUS_SUCCESS;
+
+ pdy = (DICTIONARY const *) _LoadProperty(PID_DICTIONARY, &cbDict, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ if (pdy != NULL && PropByteSwap(pdy->cEntries) != 0)
+ {
+ aev = newk (mtPropSetStream, NULL)
+ ENTRYVALIDATE[ PropByteSwap(pdy->cEntries) + 1 ];
+ if (aev == NULL)
+ {
+ *pstatus = STATUS_NO_MEMORY;
+ goto Exit;
+ }
+
+ psh = _GetSectionHeader();
+ pent = pdy->rgEntry;
+ pvDictEnd = Add2ConstPtr(pdy, cbDict);
+ pevMax = aev + PropByteSwap( pdy->cEntries );
+
+ for (pev = aev; pev < pevMax; pev++)
+ {
+ ULONG cb = _DictionaryEntryLength( pent );
+
+ if (Add2ConstPtr(pent, cb) > pvDictEnd)
+ {
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "_ValidateDictionary(bad entry size for propid=%x)\n",
+ PropByteSwap( pev->pent->propid )));
+ StatusCorruption(pstatus, "ValidateDictionary: entry size");
+ goto Exit;
+ }
+ pev->pent = pent;
+ pev->ppsstm = this;
+#if DBGPROP
+#ifdef LITTLEENDIAN
+ if (_CodePage == CP_WINUNICODE)
+ {
+ PROPASSERT(IsUnicodeString((WCHAR const *) pent->sz,
+ CCh2CB(PropByteSwap( pent->cch ))));
+ }
+ else
+ {
+ PROPASSERT(IsAnsiString((char const *) pent->sz,
+ CCh2CB( PropByteSwap( pent->cch ))));
+ }
+#endif
+#endif
+ pent = _NextDictionaryEntry( pent );
+ }
+ if ((VOID const *) pent != pvDictEnd)
+ {
+ StatusCorruption(pstatus, "ValidateDictionary: end offset");
+ goto Exit;
+ }
+ entMax.cch = 0;
+ entMax.propid = PID_ILLEGAL;
+ pevMax->pent = &entMax;
+ pevMax->ppsstm = this;
+
+ // Sort by property id and check for duplicate propids:
+
+ qsort(aev, PropByteSwap(pdy->cEntries), sizeof(aev[0]), fnEntryPropidCompare);
+
+ for (pev = aev; pev < pevMax; pev++)
+ {
+ if (PID_ILLEGAL == PropByteSwap(pev->pent->propid)
+ ||
+ pev[1].pent->propid == pev->pent->propid)
+ {
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "_ValidateDictionary(bad propid=%x)\n",
+ PropByteSwap( pev->pent->propid )));
+ StatusCorruption(pstatus, "_ValidateDictionary: bad or dup propid");
+ goto Exit;
+ }
+ }
+
+ // Sort by property name and check for duplicate names:
+
+ qsort(aev, PropByteSwap(pdy->cEntries), sizeof(aev[0]), fnEntryNameCompare);
+
+ for (pev = aev; pev < pevMax; pev++)
+ {
+ if (pev->pent->cch == 0
+ ||
+ ( pev->pent->cch == pev[1].pent->cch
+ &&
+ _ComparePropertyNames(
+ pev->pent->sz,
+ pev[1].pent->sz,
+ TRUE, // Names are the same byte-order
+ CCh2CB(PropByteSwap(pev->pent->cch)))
+ )
+ )
+ {
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "_ValidateDictionary(bad name for propid=%x)\n",
+ PropByteSwap( pev->pent->propid )));
+ StatusCorruption(pstatus, "_ValidateDictionary: bad or dup name");
+ goto Exit;
+ }
+ } // for (pev = aev; pev < pevMax; pev++)
+ } // if (pdy != NULL && pdy->cEntries != 0)
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ delete [] aev;
+
+}
+#endif // DBGPROP
+
+
+//+--------------------------------------------------------------------------
+// Member: CPropertySetStream::Validate
+//
+// Synopsis: validate entire property stream
+//
+// Arguments: [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: None
+//+--------------------------------------------------------------------------
+
+#if DBGPROP
+
+extern "C" BOOLEAN fValidatePropSets = KERNELSELECT(DBG, TRUE);
+
+VOID
+CPropertySetStream::Validate(OUT NTSTATUS *pstatus)
+{
+ if (fValidatePropSets && (_State & CPSS_USERDEFINEDDELETED) == 0)
+ {
+ ULONG cbstm = _MSTM(GetSize)(pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // Walk through section headers to make sure all sections are contained
+ // within the stream size.
+
+ if (_ComputeMinimumSize(cbstm, pstatus) != 0)
+ {
+ // If an error had occurred in the above call,
+ // it would have returned zero.
+
+ _ValidateStructure( pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ _ValidateProperties( pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ _ValidateDictionary( pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ _ComputeMinimumSize(cbstm, pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+ } // if (fValidatePropSets && (_State & CPSS_USERDEFINEDDELETED) == 0)
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+}
+#endif
+
+
+//+--------------------------------------------------------------------------
+// Function: CopyPropertyValue
+//
+// Synopsis: copy a property value into a supplied buffer
+//
+// Arguments: [pprop] -- property value (possibly NULL)
+// [cb] -- property length
+// [ppropDst] -- output buffer for property value
+// [pcb] -- length of buffer (in); actual length (out)
+//
+// Returns: None
+//---------------------------------------------------------------------------
+
+#ifdef WINNT
+VOID
+CopyPropertyValue(
+ IN OPTIONAL SERIALIZEDPROPERTYVALUE const *pprop,
+ IN ULONG cb,
+ OUT SERIALIZEDPROPERTYVALUE *ppropDst,
+ OUT ULONG *pcb)
+{
+#if DBG==1
+ NTSTATUS Status;
+#endif
+
+ if (pprop == NULL)
+ {
+ static SERIALIZEDPROPERTYVALUE prop = { VT_EMPTY, };
+
+ pprop = &prop;
+ cb = CB_SERIALIZEDPROPERTYVALUE;
+ }
+ PROPASSERT(cb == PropertyLengthNoEH(pprop, cb, 0, &Status)
+ &&
+ NT_SUCCESS(Status) );
+
+ RtlCopyMemory(ppropDst, pprop, min(cb, *pcb));
+ *pcb = cb;
+}
+#endif // WINNT
diff --git a/private/ole32/stg/props/propvar.cxx b/private/ole32/stg/props/propvar.cxx
new file mode 100644
index 000000000..a8988e548
--- /dev/null
+++ b/private/ole32/stg/props/propvar.cxx
@@ -0,0 +1,3264 @@
+//+--------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1993
+//
+// File: propvar.cxx
+//
+// Contents: PROPVARIANT manipulation code
+//
+// History: 15-Aug-95 vich created
+// 22-Feb-96 MikeHill Moved DwordRemain to "propmac.hxx".
+// 09-May-96 MikeHill Use the 'boolVal' member of PropVariant
+// rather than the member named 'bool'.
+// 22-May-96 MikeHill Use the caller-provided codepage for
+// string conversions, not the system default.
+// 06-Jun-96 MikeHill Modify CLIPDATA.cbData to include sizeof
+// ulClipFmt.
+// 12-Jun-96 MikeHill - Use new BSTR alloc/free routines.
+// - Added VT_I1 support (under ifdefs)
+// - Bug for VT_CF|VT_VECTOR in RtlConvPropToVar
+// 25-Jul-96 MikeHill - Removed Win32 SEH.
+// - BSTRs: WCHAR=>OLECHAR
+// - Added big-endian support.
+//
+//---------------------------------------------------------------------------
+
+#include <pch.cxx>
+
+#include <stdio.h>
+
+#ifndef _MAC
+#include <ddeml.h> // for CP_WINUNICODE
+#endif
+
+#include "propvar.h"
+
+// These optionally-compiled directives tell the compiler & debugger
+// where the real file, rather than the copy, is located.
+#ifdef _ORIG_FILE_LOCATION_
+#if __LINE__ != 40
+#error File heading has change size
+#else
+#line 44 "\\nt\\private\\dcomidl\\propvar.cxx"
+#endif
+#endif
+
+#ifndef newk
+#define newk(Tag, pCounter) new
+#endif
+
+
+
+// The below variant types are supported in property set streams. In addition,
+// the variants found in an array of variants (VT_VECTOR | VT_VARIANT) can only
+// contain the types listed below as legal for arrays. Nested vectors of
+// VT_VARIANT are specifically *allowed*.
+//
+// dd xx symbolic name field size
+// -- --- ------------- ----- ----
+// -1 - ffff VT_ILLEGAL <none> can't legally be stored
+//
+// 0 - x00 VT_EMPTY <none> 0
+// 1 - x01 VT_NULL <none> 0
+//
+// 16 - x10 VT_I1 CHAR cVal sizeof(char)
+// 17 - x11 VT_UI1 UCHAR bVal sizeof(char)
+//
+// 2 - x02 VT_I2 short iVal sizeof(short)
+// 18 - x12 VT_UI2 USHORT uiVal sizeof(short)
+// 11 - x0b VT_BOOL VARIANT_BOOL boolVal sizeof(short)
+//
+// 3 - x03 VT_I4 long lVal sizeof(long)
+// 19 - x13 VT_UI4 ULONG ulVal sizeof(long)
+// 4 - x04 VT_R4 float fltVal sizeof(long)
+// 10 - x0a VT_ERROR SCODE scode sizeof(long)
+//
+// 20 - x14 VT_I8 LARGE_INTEGER hVal sizeof(ll)
+// 21 - x15 VT_UI8 ULARGE_INTEGER uhVal sizeof(ll)
+// 5 - x05 VT_R8 double dblVal sizeof(ll)
+// 6 - x06 VT_CY CY cyVal sizeof(ll)
+// 7 - x07 VT_DATE DATE date sizeof(ll)
+// 64 - x40 VT_FILETIME FILETIME filetime sizeof(ll)
+//
+// 72 - x48 VT_CLSID CLSID *puuid sizeof(GUID)
+//
+// 65 - x41 VT_BLOB BLOB blob counted array of bytes
+// 70 - x46 VT_BLOB_OBJECT BLOB blob counted array of bytes
+// 71 - x47 VT_CF CLIPDATA *pclipdata " + ulClipFmt
+// 66 - x42 VT_STREAM LPSTR pszVal counted array of bytes
+// 68 - x44 VT_STREAMED_OBJECT LPSTR pszVal counted array of bytes
+// 67 - x43 VT_STORAGE LPSTR pszVal counted array of bytes
+// 69 - x45 VT_STORED_OBJECT LPSTR pszVal counted array of bytes
+// 8 - x08 VT_BSTR BSTR bstrVal counted array of bytes
+// 30 - x1e VT_LPSTR LPSTR pszVal counted array of bytes
+//
+// 31 - x1f VT_LPWSTR LPWSTR pwszVal counted array of WCHARs
+//
+// x1010 VT_VECTOR | VT_I1 CAC cac cElems * sizeof(char)
+// x1011 VT_VECTOR | VT_UI1 CAUB caub cElems * sizeof(char)
+//
+// x1002 VT_VECTOR | VT_I2 CAI cai cElems * sizeof(short)
+// x1012 VT_VECTOR | VT_UI2 CAUI caui cElems * sizeof(short)
+// x100b VT_VECTOR | VT_BOOL CABOOL cabool cElems * sizeof(short)
+//
+// x1003 VT_VECTOR | VT_I4 CAL cal cElems * sizeof(long)
+// x1013 VT_VECTOR | VT_UI4 CAUL caul cElems * sizeof(long)
+// x1004 VT_VECTOR | VT_R4 CAFLT caflt cElems * sizeof(long)
+// x100a VT_VECTOR | VT_ERROR CAERROR cascode cElems * sizeof(long)
+//
+// x1014 VT_VECTOR | VT_I8 CAH cah cElems * sizeof(ll)
+// x1015 VT_VECTOR | VT_UI8 CAUH cauh cElems * sizeof(ll)
+// x1005 VT_VECTOR | VT_R8 CADBL cadbl cElems * sizeof(ll)
+// x1006 VT_VECTOR | VT_CY CACY cacy cElems * sizeof(ll)
+// x1007 VT_VECTOR | VT_DATE CADATE cadate cElems * sizeof(ll)
+// x1040 VT_VECTOR | VT_FILETIME CAFILETIME cafiletime cElems * sizeof(ll)
+//
+// x1048 VT_VECTOR | VT_CLSID CACLSID cauuid cElems * sizeof(GUID)
+//
+// x1047 VT_VECTOR | VT_CF CACLIPDATA caclipdata cElems cntarray of bytes
+// x1008 VT_VECTOR | VT_BSTR CABSTR cabstr cElems cntarray of bytes
+// x101e VT_VECTOR | VT_LPSTR CALPSTR calpstr cElems cntarray of bytes
+//
+// x101f VT_VECTOR | VT_LPWSTR CALPWSTR calpwstr cElems cntarray of WCHAR
+//
+// x100c VT_VECTOR | VT_VARIANT CAPROPVARIANT capropvar cElems variants
+// (recurse on each)
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlpConvertToUnicode, private
+//
+// Synopsis: Convert a MultiByte string to a Unicode string
+//
+// Arguments: [pch] -- pointer to MultiByte string
+// [cb] -- byte length of MultiByte string
+// [CodePage] -- property set codepage
+// [ppwc] -- pointer to returned pointer to Unicode string
+// [pcb] -- returned byte length of Unicode string
+//
+// Returns: Nothing
+//---------------------------------------------------------------------------
+
+VOID
+RtlpConvertToUnicode(
+ IN CHAR const *pch,
+ IN ULONG cb,
+ IN USHORT CodePage,
+ OUT WCHAR **ppwc,
+ OUT ULONG *pcb,
+ OUT NTSTATUS *pstatus)
+{
+ WCHAR *pwszName;
+
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(pch != NULL);
+ PROPASSERT(ppwc != NULL);
+ PROPASSERT(pcb != NULL);
+
+ *ppwc = NULL;
+ *pcb = 0;
+
+ ULONG cwcName;
+
+ PROPASSERT(UnicodeCallouts.pfnMultiByteToWideChar != NULL);
+
+ pwszName = NULL;
+ cwcName = 0;
+ while (TRUE)
+ {
+ cwcName = (*UnicodeCallouts.pfnMultiByteToWideChar)(
+ CodePage,
+ 0, // dwFlags
+ pch,
+ cb,
+ pwszName,
+ cwcName);
+ if (cwcName == 0)
+ {
+ delete [] pwszName;
+ // If there was an error, assume that it was a code-page
+ // incompatibility problem.
+ StatusError(pstatus, "RtlpConvertToUnicode: MultiByteToWideChar error",
+ STATUS_UNMAPPABLE_CHARACTER);
+ goto Exit;
+ }
+ if (pwszName != NULL)
+ {
+ DebugTrace(0, DEBTRACE_PROPERTY, (
+ "RtlpConvertToUnicode: pch='%s'[%x] pwc='%ws'[%x->%x]\n",
+ pch,
+ cb,
+ pwszName,
+ *pcb,
+ cwcName * sizeof(WCHAR)));
+ break;
+ }
+ *pcb = cwcName * sizeof(WCHAR);
+ *ppwc = pwszName = (WCHAR *) newk(mtPropSetStream, NULL) CHAR[*pcb];
+ if (pwszName == NULL)
+ {
+ StatusNoMemory(pstatus, "RtlpConvertToUnicode: no memory");
+ goto Exit;
+ }
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlpConvertToMultiByte, private
+//
+// Synopsis: Convert a Unicode string to a MultiByte string
+//
+// Arguments: [pwc] -- pointer to Unicode string
+// [cb] -- byte length of Unicode string
+// [CodePage] -- property set codepage
+// [ppch] -- pointer to returned pointer to MultiByte string
+// [pcb] -- returned byte length of MultiByte string
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: Nothing
+//---------------------------------------------------------------------------
+
+VOID
+RtlpConvertToMultiByte(
+ IN WCHAR const *pwc,
+ IN ULONG cb,
+ IN USHORT CodePage,
+ OUT CHAR **ppch,
+ OUT ULONG *pcb,
+ OUT NTSTATUS *pstatus)
+{
+ ULONG cbName;
+ CHAR *pszName;
+
+ *pstatus = STATUS_SUCCESS;
+
+ PROPASSERT(pwc != NULL);
+ PROPASSERT(ppch != NULL);
+ PROPASSERT(pcb != NULL);
+
+ *ppch = NULL;
+ *pcb = 0;
+
+ PROPASSERT(UnicodeCallouts.pfnWideCharToMultiByte != NULL);
+
+ pszName = NULL;
+ cbName = 0;
+ while (TRUE)
+ {
+ cbName = (*UnicodeCallouts.pfnWideCharToMultiByte)(
+ CodePage,
+ 0, // dwFlags
+ pwc,
+ cb/sizeof(WCHAR),
+ pszName,
+ cbName,
+ NULL, // lpDefaultChar
+ NULL); // lpUsedDefaultChar
+ if (cbName == 0)
+ {
+ delete [] pszName;
+ // If there was an error, assume that it was a code-page
+ // incompatibility problem.
+ StatusError(pstatus, "RtlpConvertToMultiByte: WideCharToMultiByte error",
+ STATUS_UNMAPPABLE_CHARACTER);
+ goto Exit;
+ }
+ if (pszName != NULL)
+ {
+ DebugTrace(0, DEBTRACE_PROPERTY, (
+ "RtlpConvertToMultiByte: pwc='%ws'[%x] pch='%s'[%x->%x]\n",
+ pwc,
+ cb,
+ pszName,
+ *pcb,
+ cbName));
+ break;
+ }
+ *pcb = cbName;
+ *ppch = pszName = newk(mtPropSetStream, NULL) CHAR[cbName];
+ if (pszName == NULL)
+ {
+ StatusNoMemory(pstatus, "RtlpConvertToMultiByte: no memory");
+ goto Exit;
+ }
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlConvertVariantToProperty, private
+//
+// Synopsis: Convert a PROPVARIANT to a SERIALIZEDPROPERTYVALUE
+//
+// Arguments: [pvar] -- pointer to PROPVARIANT
+// [CodePage] -- property set codepage
+// [pprop] -- pointer to SERIALIZEDPROPERTYVALUE
+// [pcb] -- pointer to remaining stream length,
+// updated to actual property size on return
+// [pid] -- propid (used if indirect)
+// [fVariantVector] -- TRUE if recursing on VT_VECTOR | VT_VARIANT
+// [pcIndirect] -- pointer to indirect property count
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: NULL if buffer too small, else input [pprop] argument
+//---------------------------------------------------------------------------
+
+
+// Define a macro which sets a variable named 'cbByteSwap', but
+// only on big-endian builds. This value is not needed on little-
+// endian builds (because byte-swapping is not necessary).
+
+#ifdef BIGENDIAN
+#define CBBYTESWAP(cb) cbByteSwap = cb
+#elif LITTLEENDIAN
+#define CBBYTESWAP(cb)
+#else
+#error Either BIGENDIAN or LITTLEENDIAN must be set.
+#endif
+
+
+// First, define a wrapper for this function which returns errors
+// using NT Exception Handling, rather than returning an NTSTATUS.
+
+SERIALIZEDPROPERTYVALUE *
+RtlConvertVariantToProperty(
+ IN PROPVARIANT const *pvar,
+ IN USHORT CodePage,
+ OPTIONAL OUT SERIALIZEDPROPERTYVALUE *pprop,
+ IN OUT ULONG *pcb,
+ IN PROPID pid,
+ IN BOOLEAN fVariantVector,
+ OPTIONAL OUT ULONG *pcIndirect)
+{
+ SERIALIZEDPROPERTYVALUE *ppropRet;
+ NTSTATUS status;
+
+ ppropRet = RtlConvertVariantToPropertyNoEH(
+ pvar, CodePage, pprop,
+ pcb, pid, fVariantVector,
+ pcIndirect, &status );
+
+ if (!NT_SUCCESS( status ))
+ RtlRaiseStatus( status );
+
+ return (ppropRet );
+
+}
+
+// Now define the body of the function, returning errors with an
+// NTSTATUS value instead of raising.
+
+SERIALIZEDPROPERTYVALUE *
+RtlConvertVariantToPropertyNoEH(
+ IN PROPVARIANT const *pvar,
+ IN USHORT CodePage,
+ OPTIONAL OUT SERIALIZEDPROPERTYVALUE *pprop,
+ IN OUT ULONG *pcb,
+ IN PROPID pid,
+ IN BOOLEAN fVariantVector,
+ OPTIONAL OUT ULONG *pcIndirect,
+ OUT NTSTATUS *pstatus)
+{
+ *pstatus = STATUS_SUCCESS;
+
+ // ------
+ // Locals
+ // ------
+ CHAR *pchConvert = NULL;
+
+ ULONG count;
+ BYTE *pbdst;
+ ULONG cbch = 0;
+ ULONG cbchdiv = 0;
+ ULONG cb = 0;
+
+ // Size of byte-swapping units (e.g. 2 to swap a WORD).
+ INT cbByteSwap = 0;
+
+ ULONG const *pcount = NULL;
+ VOID const *pv = NULL;
+ LONG *pclipfmt = NULL;
+ BOOLEAN fCheckNullSource = (BOOLEAN) ((pvar->vt & VT_VECTOR) != 0);
+ BOOLEAN fIllegalType = FALSE;
+ VOID **ppv;
+ OLECHAR aocName[4 + 10 + 1]; // enough for "prop%lu" + L'\0'
+
+ // -------------------------------------------------------
+ // Analyze the PropVariant, and store information about it
+ // in fIllegalType, cb, pv, pcount, count, pclipfmt,
+ // fCheckNullSource, cbch, chchdiv, and ppv.
+ // -------------------------------------------------------
+
+ switch (pvar->vt)
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ fIllegalType = fVariantVector;
+ break;
+
+#ifdef PROPVAR_VT_I1
+ case VT_I1:
+ AssertByteField(cVal); // VT_I1
+#endif
+ case VT_UI1:
+ AssertByteField(bVal); // VT_UI1
+ cb = sizeof(pvar->bVal);
+ pv = &pvar->bVal;
+ break;
+
+ case VT_I2:
+ case VT_UI2:
+ case VT_BOOL:
+ AssertShortField(iVal); // VT_I2
+ AssertShortField(uiVal); // VT_UI2
+ AssertShortField(boolVal); // VT_BOOL
+ cb = sizeof(pvar->iVal);
+ pv = &pvar->iVal;
+
+ // If swapping, swap as a WORD
+ CBBYTESWAP(cb);
+ break;
+
+ case VT_I4:
+ case VT_UI4:
+ case VT_R4:
+ case VT_ERROR:
+ AssertLongField(lVal); // VT_I4
+ AssertLongField(ulVal); // VT_UI4
+ AssertLongField(fltVal); // VT_R4
+ AssertLongField(scode); // VT_ERROR
+ cb = sizeof(pvar->lVal);
+ pv = &pvar->lVal;
+
+ // If swapping, swap as a DWORD
+ CBBYTESWAP(cb);
+ break;
+
+ case VT_I8:
+ case VT_UI8:
+ case VT_FILETIME:
+ AssertLongLongField(hVal); // VT_I8
+ AssertLongLongField(uhVal); // VT_UI8
+ AssertLongLongField(filetime); // VT_FILETIME
+ cb = sizeof(pvar->hVal);
+ pv = &pvar->hVal;
+
+ // If swapping, swap each DWORD independently.
+ CBBYTESWAP(sizeof(DWORD));
+ break;
+
+ case VT_R8:
+ case VT_CY:
+ case VT_DATE:
+ AssertLongLongField(dblVal); // VT_R8
+ AssertLongLongField(cyVal); // VT_CY
+ AssertLongLongField(date); // VT_DATE
+ cb = sizeof(pvar->dblVal);
+ pv = &pvar->dblVal;
+
+ // If swapping, swap as a LONGLONG (64 bits).
+ CBBYTESWAP(cb);
+ break;
+
+ case VT_CLSID:
+ AssertStringField(puuid); // VT_CLSID
+ cb = sizeof(GUID);
+ pv = pvar->puuid;
+ fCheckNullSource = TRUE;
+
+ // If swapping, special handling is required.
+ CBBYTESWAP( CBBYTESWAP_UID );
+ break;
+
+ case VT_CF:
+
+ // Validate the PropVariant
+ if (pvar->pclipdata == NULL
+ ||
+ pvar->pclipdata->cbSize < sizeof(pvar->pclipdata->ulClipFmt) )
+ {
+ StatusInvalidParameter(pstatus, "RtlConvertVariantToProperty: pclipdata NULL");
+ goto Exit;
+ }
+
+ // How many bytes should we copy?
+ cb = CBPCLIPDATA( *(pvar->pclipdata) );
+
+ // Identify the value for this property's count field.
+ // (which includes sizeof(ulClipFmt))
+ count = pvar->pclipdata->cbSize;
+ pcount = &count;
+
+ // Identify the clipdata's format & data
+ pclipfmt = &pvar->pclipdata->ulClipFmt;
+ pv = pvar->pclipdata->pClipData;
+
+ fCheckNullSource = TRUE;
+
+ // Note that no byte-swapping of 'pv' is necessary.
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ fIllegalType = fVariantVector;
+ pcount = &pvar->blob.cbSize;
+ cb = *pcount;
+ pv = pvar->blob.pBlobData;
+ fCheckNullSource = TRUE;
+
+ // Note that no byte-swapping of 'pv' is necessary.
+ break;
+
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ if (fVariantVector)
+ {
+ fIllegalType = TRUE;
+ break;
+ }
+ if (pcIndirect != NULL)
+ {
+ (*pcIndirect)++;
+ PROPGENPROPERTYNAME(aocName, pid);
+ pv = aocName;
+ }
+ else
+ {
+ PROPASSERT(
+ pvar->pwszVal == NULL ||
+ IsUnicodeString(pvar->pwszVal, MAXULONG));
+ pv = pvar->pwszVal;
+ }
+ count = 1; // default to forcing an error on NULL pointer
+ goto noansicheck;
+
+ case VT_LPSTR:
+ PROPASSERT(
+ pvar->pszVal == NULL ||
+ IsAnsiString(pvar->pszVal, MAXULONG));
+ // FALLTHROUGH
+
+ case VT_BSTR:
+ count = 0; // allow NULL pointer
+ pv = pvar->pszVal;
+noansicheck:
+ AssertStringField(pwszVal); // VT_STREAM, VT_STREAMED_OBJECT
+ AssertStringField(pwszVal); // VT_STORAGE, VT_STORED_OBJECT
+ AssertStringField(bstrVal); // VT_BSTR
+ AssertStringField(pszVal); // VT_LPSTR
+
+ // We have the string for an LPSTR, BSTR, or indirect
+ // property pointed to by 'pv'. Now we'll perform any
+ // Ansi/Unicode conversions and byte-swapping that's
+ // necessary (putting the result in 'pv').
+
+ if (pv == NULL)
+ {
+ fCheckNullSource = TRUE;
+ }
+
+ else
+ if (pvar->vt == VT_LPSTR)
+ {
+ count = strlen((char *) pv) + 1;
+
+ // If the propset is Unicode, convert the LPSTR to Unicode.
+
+ if (CodePage == CP_WINUNICODE)
+ {
+ // Convert to Unicode.
+
+ PROPASSERT(IsAnsiString((CHAR const *) pv, count));
+ RtlpConvertToUnicode(
+ (CHAR const *) pv,
+ count,
+ CP_ACP, // Variants are in the system codepage
+ (WCHAR **) &pchConvert,
+ &count,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // 'pv' always has the ready-to-serialize string.
+ pv = pchConvert;
+
+ // This unicode string may require byte-swapping.
+ CBBYTESWAP( sizeof(WCHAR) );
+ }
+ } // else if (pvar->vt == VT_LPSTR)
+
+ else
+ {
+ // If this is a BSTR, increment the count to include
+ // the string terminator.
+ if (pvar->vt == VT_BSTR)
+ {
+ count = BSTRLEN(pv);
+
+ // Verify that the input BSTR is terminated.
+ if (pvar->bstrVal[count/sizeof(OLECHAR)] != OLESTR('\0'))
+ {
+ PROPASSERT(pvar->bstrVal[count/sizeof(OLECHAR)] == OLESTR('\0'));
+ StatusInvalidParameter(pstatus,
+ "RtlConvertVariantToProperty: bad BSTR null char");
+ goto Exit;
+ }
+
+ // Increment the count to include the terminator.
+ count += sizeof(OLECHAR);
+ }
+ else
+ {
+ count = (Prop_ocslen((OLECHAR *) pv) + 1) * sizeof(OLECHAR);
+ PROPASSERT(IsOLECHARString((OLECHAR const *) pv, count));
+ }
+
+ // This string is either an indirect property name,
+ // or a BSTR, both of which could be Ansi or Unicode.
+
+ if (CodePage != CP_WINUNICODE // Ansi property set
+ &&
+ OLECHAR_IS_UNICODE // The PropVariant is in Unicode
+ )
+ {
+ // A Unicode to Ansi conversion is required.
+
+ PROPASSERT( IsUnicodeString( (WCHAR*)pv, count ));
+
+ RtlpConvertToMultiByte(
+ (WCHAR const *) pv,
+ count,
+ CodePage,
+ &pchConvert,
+ &count,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ pv = pchConvert;
+ }
+
+ else
+ if (CodePage == CP_WINUNICODE // Unicode property set,
+ &&
+ !OLECHAR_IS_UNICODE // The PropVariant is in Ansi
+ )
+ {
+ // An Ansi to Unicode conversion is required.
+
+ PROPASSERT(IsAnsiString((CHAR const *) pv, count));
+ PROPASSERT(sizeof(OLECHAR) == sizeof(CHAR));
+
+ RtlpConvertToUnicode(
+ (CHAR const *) pv,
+ count,
+ CP_ACP, // In-mem BSTR is in system CP
+ (WCHAR **) &pchConvert,
+ &count,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // 'pv' always holds the ready-to-serialize value.
+ pv = pchConvert;
+
+ // This unicode string may require swapping.
+ CBBYTESWAP( sizeof(WCHAR) );
+ }
+
+ else
+ if (CodePage == CP_WINUNICODE)
+ {
+ // No conversion is required (i.e., both 'pv' and the
+ // property set are Unicode). But we must remember
+ // to perform a byte-swap (if byte-swapping is necessary).
+
+ CBBYTESWAP( sizeof(WCHAR) );
+ }
+ } // if (pv == NULL) ... else if ... else
+
+ // Validate 'pv'.
+
+#ifdef LITTLEENDIAN
+ // BUGBUG: Create an IsByteSwappedUnicodeString routine
+ PROPASSERT( NULL == pv
+ ||
+ CodePage == CP_WINUNICODE && IsUnicodeString((WCHAR*)pv, count)
+ ||
+ CodePage != CP_WINUNICODE && IsAnsiString((CHAR*)pv, count) );
+#endif
+
+ cb = count;
+ pcount = &count;
+ break;
+
+ case VT_LPWSTR:
+ AssertStringField(pwszVal); // VT_LPWSTR
+ PROPASSERT(
+ pvar->pwszVal == NULL ||
+ IsUnicodeString(pvar->pwszVal, MAXULONG));
+
+ pv = pvar->pwszVal;
+ if (pv == NULL)
+ {
+ count = 0;
+ fCheckNullSource = TRUE;
+ }
+ else
+ {
+ // Calculate the [length] field.
+ count = Prop_wcslen(pvar->pwszVal) + 1;
+
+ // If byte-swapping will be necessary to get to the serialized
+ // format, we'll do so in units of WCHARs.
+
+ CBBYTESWAP( sizeof(WCHAR) );
+ }
+
+ cb = count * sizeof(WCHAR);
+ pcount = &count;
+ break;
+
+ // Vector properties:
+
+#ifdef PROPVAR_VT_I1
+ case VT_VECTOR | VT_I1:
+ AssertByteVector(cac); // VT_I1
+#endif
+ case VT_VECTOR | VT_UI1:
+ AssertByteVector(caub); // VT_UI1
+ pcount = &pvar->caub.cElems;
+ cb = *pcount * sizeof(pvar->caub.pElems[0]);
+ pv = pvar->caub.pElems;
+ break;
+
+ case VT_VECTOR | VT_I2:
+ case VT_VECTOR | VT_UI2:
+ case VT_VECTOR | VT_BOOL:
+ AssertShortVector(cai); // VT_I2
+ AssertShortVector(caui); // VT_UI2
+ AssertShortVector(cabool); // VT_BOOL
+ pcount = &pvar->cai.cElems;
+ cb = *pcount * sizeof(pvar->cai.pElems[0]);
+ pv = pvar->cai.pElems;
+
+ // If swapping, swap as WORDs
+ CBBYTESWAP(sizeof(pvar->cai.pElems[0]));
+ break;
+
+ case VT_VECTOR | VT_I4:
+ case VT_VECTOR | VT_UI4:
+ case VT_VECTOR | VT_R4:
+ case VT_VECTOR | VT_ERROR:
+ AssertLongVector(cal); // VT_I4
+ AssertLongVector(caul); // VT_UI4
+ AssertLongVector(caflt); // VT_R4
+ AssertLongVector(cascode); // VT_ERROR
+ pcount = &pvar->cal.cElems;
+ cb = *pcount * sizeof(pvar->cal.pElems[0]);
+ pv = pvar->cal.pElems;
+
+ // If swapping, swap as DWORDs
+ CBBYTESWAP(sizeof(pvar->cal.pElems[0]));
+ break;
+
+ case VT_VECTOR | VT_I8:
+ case VT_VECTOR | VT_UI8:
+ case VT_VECTOR | VT_FILETIME:
+ AssertLongLongVector(cah); // VT_I8
+ AssertLongLongVector(cauh); // VT_UI8
+ AssertLongLongVector(cafiletime);// VT_FILETIME
+ pcount = &pvar->cah.cElems;
+ cb = *pcount * sizeof(pvar->cah.pElems[0]);
+ pv = pvar->cah.pElems;
+
+ // If swapping, swap as DWORDs
+ CBBYTESWAP(sizeof(DWORD));
+ break;
+
+ case VT_VECTOR | VT_R8:
+ case VT_VECTOR | VT_CY:
+ case VT_VECTOR | VT_DATE:
+ AssertLongLongVector(cadbl); // VT_R8
+ AssertLongLongVector(cacy); // VT_CY
+ AssertLongLongVector(cadate); // VT_DATE
+ pcount = &pvar->cah.cElems;
+ cb = *pcount * sizeof(pvar->cadbl.pElems[0]);
+ pv = pvar->cadbl.pElems;
+
+ // If swapping, swap as LONGLONGs (8 bytes)
+ CBBYTESWAP(sizeof(pvar->cadbl.pElems[0]));
+ break;
+
+
+ case VT_VECTOR | VT_CLSID:
+ AssertVarVector(cauuid, sizeof(GUID));
+ pcount = &pvar->cauuid.cElems;
+ cb = *pcount * sizeof(pvar->cauuid.pElems[0]);
+ pv = pvar->cauuid.pElems;
+
+ // If swapping, special handling is required.
+ CBBYTESWAP( CBBYTESWAP_UID );
+ break;
+
+ case VT_VECTOR | VT_CF:
+ cbch = sizeof(CLIPDATA);
+ cbchdiv = sizeof(BYTE);
+ goto stringvector;
+
+ case VT_VECTOR | VT_BSTR:
+ case VT_VECTOR | VT_LPSTR:
+ cbchdiv = cbch = sizeof(BYTE);
+ goto stringvector;
+
+ case VT_VECTOR | VT_LPWSTR:
+ cbchdiv = cbch = sizeof(WCHAR);
+ goto stringvector;
+
+ case VT_VECTOR | VT_VARIANT:
+ cbch = MAXULONG;
+stringvector:
+ AssertVarVector(caclipdata, sizeof(CLIPDATA)); // VT_CF
+ AssertStringVector(cabstr); // VT_BSTR
+ AssertStringVector(calpstr); // VT_LPSTR
+ AssertStringVector(calpwstr); // VT_LPWSTR
+ AssertVarVector(capropvar, sizeof(PROPVARIANT));// VT_VARIANT
+
+ pcount = &pvar->calpstr.cElems;
+ ppv = (VOID **) pvar->calpstr.pElems;
+ break;
+
+ default:
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "RtlConvertVariantToProperty: unsupported vt=%x\n",
+ pvar->vt));
+ StatusInvalidParameter(pstatus, "RtlConvertVariantToProperty: bad type");
+ goto Exit;
+
+ } // switch (pvar->vt)
+
+ // At this point we've analyzed the PropVariant, and stored
+ // information about it in various local variables. Now we
+ // can use this information to serialize the propvar.
+
+ // Early exit if this is an illegal type.
+
+ if (fIllegalType)
+ {
+ StatusInvalidParameter(pstatus, "RtlConvertVariantToProperty: Illegal VarType");
+ goto Exit;
+ }
+
+ // Set pbdst to point into the serialization buffer, or to
+ // NULL if there is no such buffer.
+
+ if (pprop == NULL)
+ {
+ pbdst = NULL;
+ }
+ else
+ {
+ pbdst = pprop->rgb;
+ }
+
+ // Is this a Vector of Strings/Variants/CFs?
+ if (cbch != 0)
+ {
+ // Yes.
+
+ ULONG cElems;
+
+ PROPASSERT(pcount != NULL);
+ PROPASSERT(*pcount == 0 || ppv != NULL);
+ PROPASSERT(0 == cbByteSwap);
+
+ // Start calculating the serialized size. Include the sizes
+ // of the VT & element count.
+
+ cb = sizeof(ULONG) + sizeof(ULONG);
+
+ // Is this a Variant Vector?
+ if (cbch != MAXULONG)
+ {
+ // No. Include each element's length field.
+ cb += *pcount * sizeof(ULONG);
+ }
+
+ // Is there room in the caller's buffer for everything
+ // counted so far?
+ if (*pcb < cb)
+ {
+ // No - we won't serialize the data, but we will continue
+ // to calculate cb.
+ pprop = NULL;
+ }
+
+ // Write the count of vector elements.
+ if (pprop != NULL)
+ {
+ *(ULONG *) pbdst = PropByteSwap((ULONG) *pcount);
+ pbdst += sizeof(ULONG);
+ }
+
+ // Walk through the vector and write the elements.
+
+ for (cElems = *pcount; cElems > 0; cElems--)
+ {
+ ULONG cbcopy = 0;
+
+ // Switch on the size of the element.
+ switch (cbch)
+ {
+ //
+ // VT_VARIANT
+ //
+ case MAXULONG:
+ cbcopy = MAXULONG;
+
+ // Perform a recursive serialization
+ RtlConvertVariantToPropertyNoEH(
+ (PROPVARIANT *) ppv,
+ CodePage,
+ NULL,
+ &cbcopy,
+ PID_ILLEGAL,
+ TRUE,
+ NULL,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ break;
+
+ //
+ // VT_CF
+ //
+ case sizeof(CLIPDATA):
+
+ // We copy cbSize-sizeof(ulClipFmt) bytes.
+
+ if( ((CLIPDATA *) ppv)->cbSize < sizeof(ULONG) )
+ {
+ StatusInvalidParameter(pstatus, "RtlConvertVariantToProperty: short cbSize on VT_CF");
+ goto Exit;
+ }
+ else
+ {
+ cbcopy = CBPCLIPDATA( *(CLIPDATA*) ppv );
+ }
+
+ // But increment cb to to include sizeof(ulClipFmt)
+ cb += sizeof(ULONG);
+ break;
+
+ //
+ // VT_LPWSTR
+ //
+ case sizeof(WCHAR):
+ if (*ppv != NULL)
+ {
+ PROPASSERT(IsUnicodeString((WCHAR const *) *ppv, MAXULONG));
+ cbcopy = (Prop_wcslen((WCHAR *) *ppv) + 1) * sizeof(WCHAR);
+ pv = *ppv;
+
+ // If byte-swapping is necessary, swap in units of WCHARs
+ CBBYTESWAP( sizeof(WCHAR) );
+
+ }
+ break;
+
+ //
+ // VT_LPSTR/VT_BSTR
+ //
+ default:
+ PROPASSERT(cbch == sizeof(BYTE));
+ PROPASSERT(pchConvert == NULL);
+ if (*ppv != NULL)
+ {
+ pv = *ppv;
+
+ // Is this a BSTR?
+ if (pvar->vt == (VT_VECTOR | VT_BSTR))
+ {
+ // Initialize the # bytes to copy.
+ cbcopy = BSTRLEN(pv);
+
+ // Verify that the BSTR is terminated.
+ if (((OLECHAR const *) pv)[cbcopy/sizeof(OLECHAR)] != OLESTR('\0'))
+ {
+ PROPASSERT(((OLECHAR const *) pv)[cbcopy/sizeof(OLECHAR)] == OLESTR('\0'));
+ StatusInvalidParameter(pstatus,
+ "RtlConvertVariantToProperty: bad BSTR array null char");
+ goto Exit;
+ }
+
+ // Also copy the string terminator.
+ cbcopy += sizeof(OLECHAR);
+
+ // If the propset and the BSTR are in mismatched
+ // codepages (one's Unicode, the other's Ansi),
+ // correct the BSTR now. In any case, the correct
+ // string is in 'pv'.
+
+ if (CodePage != CP_WINUNICODE // Ansi property set
+ &&
+ OLECHAR_IS_UNICODE) // Unicode BSTR
+ {
+ PROPASSERT(IsUnicodeString((WCHAR*)pv, cbcopy));
+
+ RtlpConvertToMultiByte(
+ (WCHAR const *) pv,
+ cbcopy,
+ CodePage,
+ &pchConvert,
+ &cbcopy,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ pv = pchConvert;
+ }
+
+ else
+ if (CodePage == CP_WINUNICODE // Unicode property set
+ &&
+ !OLECHAR_IS_UNICODE) // Ansi BSTRs
+ {
+ PROPASSERT(IsAnsiString((CHAR const *) pv, cbcopy));
+
+ RtlpConvertToUnicode(
+ (CHAR const *) pv,
+ cbcopy,
+ CP_ACP, // In-mem BSTR is in system CP
+ (WCHAR **) &pchConvert,
+ &cbcopy,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // The Unicode string must have the proper byte order
+ CBBYTESWAP( sizeof(WCHAR) );
+
+ pv = pchConvert;
+
+ }
+
+ else
+ if (CodePage == CP_WINUNICODE )
+ {
+ // Both the BSTR and the property set are Unicode.
+ // No conversion is required, but byte-swapping
+ // is (if byte-swapping is enabled).
+
+ CBBYTESWAP( sizeof(WCHAR) );
+ }
+
+ } // if (pvar->vt == (VT_VECTOR | VT_BSTR))
+
+ // Otherwise it's an LPSTR
+ else
+ {
+ PROPASSERT(IsAnsiString((char const *) pv, MAXULONG));
+ PROPASSERT(pvar->vt == (VT_VECTOR | VT_LPSTR));
+ cbcopy = strlen((char *) pv) + 1; // + trailing null
+
+ if (CodePage == CP_WINUNICODE)
+ {
+ PROPASSERT(IsAnsiString(
+ (CHAR const *) pv,
+ cbcopy));
+ RtlpConvertToUnicode(
+ (CHAR const *) pv,
+ cbcopy,
+ CP_ACP,
+ (WCHAR **) &pchConvert,
+ &cbcopy,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // If byte-swapping, we'll do so with the WCHARs
+ CBBYTESWAP( sizeof(WCHAR) );
+
+ pv = pchConvert;
+ }
+ } // if (pvar->vt == (VT_VECTOR | VT_BSTR)) ... else
+ } // if (*ppv != NULL)
+
+ // In the end, pv should be in the codepage of
+ // the property set.
+
+#ifdef LITTLEENDIAN
+ PROPASSERT( NULL == pv
+ ||
+ CodePage == CP_WINUNICODE && IsUnicodeString((WCHAR*)pv, cbcopy)
+ ||
+ CodePage != CP_WINUNICODE && IsAnsiString((CHAR*)pv, cbcopy));
+#endif
+
+ break;
+
+ } // switch (cbch)
+
+ // Add the size of this vector element to the property total
+ cb += DwordAlign(cbcopy);
+
+ // Will there be enough room for this vector element?
+
+ if (*pcb < cb)
+ {
+ // No - we'll continue (thus calculating the total size
+ // necessary), but we won't write to the caller's buffer.
+ pprop = NULL;
+ }
+
+ // Is this a vector of Variants?
+
+ if (cbch == MAXULONG)
+ {
+ // Yes. Convert this variant.
+ if (pprop != NULL)
+ {
+ RtlConvertVariantToPropertyNoEH(
+ (PROPVARIANT *) ppv,
+ CodePage,
+ (SERIALIZEDPROPERTYVALUE *) pbdst,
+ &cbcopy,
+ PID_ILLEGAL,
+ TRUE,
+ NULL,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ pbdst += cbcopy;
+ }
+ ppv = (VOID **) Add2Ptr(ppv, sizeof(PROPVARIANT));
+ } // if (cbch == MAXULONG)
+
+ else
+ {
+ // This is a vector of something other than Variants.
+
+ PROPASSERT(
+ cbch == sizeof(BYTE) ||
+ cbch == sizeof(WCHAR) ||
+ cbch == sizeof(CLIPDATA));
+
+ PROPASSERT(cbchdiv == sizeof(BYTE) || cbchdiv == sizeof(WCHAR));
+
+ // Are we writing the serialized property?
+ if (pprop != NULL)
+ {
+ ULONG cbVectElement;
+
+ // Calculate the length of the vector element.
+ cbVectElement = (ULONG) cbcopy/cbchdiv;
+
+ // Is this a ClipData?
+ if (cbch == sizeof(CLIPDATA))
+ {
+ // Adjust the length to include sizeof(ulClipFmt)
+ cbVectElement += sizeof(ULONG);
+
+ // Write the vector element length.
+ *(ULONG *) pbdst = PropByteSwap( cbVectElement );
+
+ // Advance pbdst & write the clipboard format.
+ pbdst += sizeof(ULONG);
+ *(ULONG *) pbdst = PropByteSwap( ((CLIPDATA *) ppv)->ulClipFmt );
+ }
+ else // This isn't a ClipFormat vector element.
+ {
+ // Write the vector element length.
+ *(ULONG *) pbdst = PropByteSwap( cbVectElement );
+ }
+
+ // Advance pbdst & write the property data.
+ pbdst += sizeof(ULONG);
+ RtlCopyMemory(
+ pbdst,
+ cbch == sizeof(CLIPDATA)?
+ ((CLIPDATA *) ppv)->pClipData :
+ pv,
+ cbcopy);
+
+ // Zero out the pad bytes.
+ RtlZeroMemory(pbdst + cbcopy, DwordRemain(cbcopy));
+
+ // If byte-swapping is necessary, do so now.
+ PBSBuffer( pbdst, DwordAlign(cbcopy), cbByteSwap );
+
+ // Advance pbdst to the next property.
+ pbdst += DwordAlign(cbcopy);
+
+ } // if (pprop != NULL)
+
+ // Advance ppv to point into the PropVariant at the
+ // next element in the array.
+
+ if (cbch == sizeof(CLIPDATA))
+ {
+ ppv = (VOID **) Add2Ptr(ppv, sizeof(CLIPDATA));
+ }
+ else
+ {
+ ppv++;
+ delete [] pchConvert;
+ pchConvert = NULL;
+ }
+ } // if (cbch == MAXULONG) ... else
+ } // for (cElems = *pcount; cElems > 0; cElems--)
+ } // if (cbch != 0) // STRING/VARIANT/CF VECTOR property
+
+ else
+ {
+ // This isn't a vector, or if it is, the elements
+ // aren't Strings, Variants, or CFs.
+
+ ULONG cbCopy = cb;
+
+ // Adjust cb (the total serialized buffer size) for
+ // pre-data.
+
+ if (pvar->vt != VT_EMPTY)
+ { // Allow for the VT
+ cb += sizeof(ULONG);
+ }
+ if (pcount != NULL)
+ { // Allow for the count field
+ cb += sizeof(ULONG);
+ }
+ if (pclipfmt != NULL)
+ { // Allow for the ulClipFmt field.
+ cb += sizeof(ULONG);
+ }
+
+ // Is there room in the caller's buffer?
+ if (*pcb < cb)
+ { // No - calculate cb but don't write anything.
+ pprop = NULL;
+ }
+
+ // 'pv' should point to the source data. If it does, then
+ // we'll copy it into the property set. If it doesn't but
+ // it should, then we'll report an error.
+
+ if (pv != NULL || fCheckNullSource)
+ {
+ ULONG cbZero = DwordRemain(cbCopy);
+
+ // Do we have a destination (propset) buffer?
+
+ if (pprop != NULL)
+ {
+ // Does this property have a count field?
+ if (pcount != NULL)
+ {
+ // Write the count & advance pbdst
+ *(ULONG *) pbdst = PropByteSwap( *pcount );
+ pbdst += sizeof(ULONG);
+ }
+
+ // Is this a VT_CF?
+ if (pclipfmt != NULL)
+ {
+ // Write the ClipFormat & advance pbdst
+ *(ULONG *) pbdst = PropByteSwap( (DWORD) *pclipfmt );
+ pbdst += sizeof(ULONG);
+ }
+ }
+
+ // Are we missing the source data?
+ if (pv == NULL)
+ {
+ // The Source pointer is NULL. If cbCopy != 0, the passed
+ // VARIANT is not properly formed.
+
+ if (cbCopy != 0)
+ {
+ StatusInvalidParameter(pstatus, "RtlConvertVariantToProperty: bad NULL");
+ goto Exit;
+ }
+ }
+ else if (pprop != NULL)
+ {
+ // We have a non-NULL source & destination.
+ // First, copy the bytes from the former to the latter.
+
+ RtlCopyMemory(pbdst, pv, cbCopy);
+
+ // Then, if necessary, swap the bytes in the property
+ // set (leaving the PropVariant bytes untouched).
+
+ PBSBuffer( (VOID*) pbdst, cbCopy, cbByteSwap );
+ }
+
+ // Did we write the serialization?
+ if (pprop != NULL)
+ {
+ // Zero the padding bytes.
+ RtlZeroMemory(pbdst + cbCopy, cbZero);
+
+ // Canonicalize VARIANT_BOOLs. We do this here because
+ // we don't want to muck with the caller's buffer directly.
+
+ if ((pvar->vt & ~VT_VECTOR) == VT_BOOL)
+ {
+ VARIANT_BOOL *pvb = (VARIANT_BOOL *) pbdst;
+ VARIANT_BOOL *pvbEnd = &pvb[cbCopy/sizeof(*pvb)];
+
+ while (pvb < pvbEnd)
+ {
+ if (*pvb
+ &&
+ PropByteSwap(*pvb) != VARIANT_TRUE)
+ {
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "Patching VARIANT_TRUE value: %hx --> %hx\n",
+ *pvb,
+ VARIANT_TRUE));
+
+ *pvb = PropByteSwap( (VARIANT_BOOL) VARIANT_TRUE );
+ }
+ pvb++;
+ }
+ }
+ } // if (pprop != NULL)
+ }
+ } // if (cbch != 0) ... else // non - STRING/VARIANT/CF VECTOR property
+
+ // Set the VT in the serialized buffer now that all size
+ // checks completed.
+
+ if (pprop != NULL && pvar->vt != VT_EMPTY)
+ {
+ // When byte-swapping the VT, treat it as a DWORD
+ // (it's a WORD in the PropVariant, but a DWORD when
+ // serialized).
+
+ pprop->dwType = PropByteSwap( (DWORD) pvar->vt );
+ }
+
+ // Update the caller's copy of the total size.
+ *pcb = DwordAlign(cb);
+
+Exit:
+
+ delete [] pchConvert;
+ return(pprop);
+
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlConvertPropertyToVariant, private
+//
+// Synopsis: Convert a SERIALIZEDPROPERTYVALUE to a PROPVARIANT
+//
+// Arguments: [pprop] -- pointer to SERIALIZEDPROPERTYVALUE
+// [PointerDelta] -- adjustment to pointers to get user addresses
+// [fConvertNullStrings] -- map NULL strings to empty strings
+// [CodePage] -- property set codepage
+// [pvar] -- pointer to PROPVARIANT
+// [pma] -- caller's memory allocation routine
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: TRUE if property is an indirect property type
+//---------------------------------------------------------------------------
+
+#ifdef KERNEL
+#define ADJUSTPOINTER(ptr, delta, type) (ptr) = (type) Add2Ptr((ptr), (delta))
+#else
+#define ADJUSTPOINTER(ptr, delta, type)
+#endif
+
+// First, define a wrapper for this function which returns errors
+// using NT Exception Handling, rather than returning an NTSTATUS.
+
+BOOLEAN
+RtlConvertPropertyToVariant(
+ IN SERIALIZEDPROPERTYVALUE const *pprop,
+ IN USHORT CodePage,
+ OUT PROPVARIANT *pvar,
+ IN PMemoryAllocator *pma)
+{
+ BOOLEAN boolRet;
+ NTSTATUS status;
+
+ boolRet = RtlConvertPropertyToVariantNoEH(
+ pprop, CodePage, pvar,
+ pma, &status );
+
+ if (!NT_SUCCESS( status ))
+ RtlRaiseStatus( status );
+
+ return (boolRet);
+
+}
+
+// Now define the body of the function, returning errors with an
+// NTSTATUS value instead of raising.
+
+BOOLEAN
+RtlConvertPropertyToVariantNoEH(
+ IN SERIALIZEDPROPERTYVALUE const *pprop,
+ IN USHORT CodePage,
+ OUT PROPVARIANT *pvar,
+ IN PMemoryAllocator *pma,
+ OUT NTSTATUS *pstatus)
+{
+ *pstatus = STATUS_SUCCESS;
+
+ // ------
+ // Locals
+ // ------
+
+ BOOLEAN fIndirect = FALSE;
+
+ // Buffers which must be freed before exiting.
+ CHAR *pchConvert = NULL, *pchByteSwap = NULL;
+
+ VOID **ppv = NULL;
+ VOID *pv = NULL;
+ ULONG cbskip = sizeof(ULONG);
+ ULONG cb = 0;
+
+ // Size of byte-swapping units (must be signed).
+ INT cbByteSwap = 0;
+
+ BOOLEAN fPostAllocInit = FALSE;
+ BOOLEAN fNullLegal = (BOOLEAN) ( (PropByteSwap(pprop->dwType) & VT_VECTOR) != 0 );
+ const BOOLEAN fConvertToEmpty = FALSE;
+
+ // ---------------------------------------------------------
+ // Based on the VT, calculate ppv, pv, cbskip,
+ // cb, fPostAllocInit, fNullLegal, & fConvertToEmpty
+ // ---------------------------------------------------------
+
+ // Set the VT in the PropVariant. Note that in 'pprop' it's a
+ // DWORD, but it's a WORD in 'pvar'.
+
+ pvar->vt = (VARTYPE) PropByteSwap(pprop->dwType);
+
+ switch (pvar->vt)
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ break;
+
+#ifdef PROPVAR_VT_I1
+ case VT_I1:
+ AssertByteField(cVal); // VT_I1
+#endif
+ case VT_UI1:
+ AssertByteField(bVal); // VT_UI1
+ cb = sizeof(pvar->bVal);
+ pv = &pvar->bVal;
+ break;
+
+ case VT_I2:
+ case VT_UI2:
+ case VT_BOOL:
+ AssertShortField(iVal); // VT_I2
+ AssertShortField(uiVal); // VT_UI2
+ AssertShortField(boolVal); // VT_BOOL
+ cb = sizeof(pvar->iVal);
+ pv = &pvar->iVal;
+
+ // If swapping, swap as a WORD
+ CBBYTESWAP(cb);
+ break;
+
+ case VT_I4:
+ case VT_UI4:
+ case VT_R4:
+ case VT_ERROR:
+ AssertLongField(lVal); // VT_I4
+ AssertLongField(ulVal); // VT_UI4
+ AssertLongField(fltVal); // VT_R4
+ AssertLongField(scode); // VT_ERROR
+ cb = sizeof(pvar->lVal);
+ pv = &pvar->lVal;
+
+ // If swapping, swap as a DWORD
+ CBBYTESWAP(cb);
+ break;
+
+ case VT_I8:
+ case VT_UI8:
+ case VT_FILETIME:
+ AssertLongLongField(hVal); // VT_I8
+ AssertLongLongField(uhVal); // VT_UI8
+ AssertLongLongField(filetime); // VT_FILETIME
+ cb = sizeof(pvar->hVal);
+ pv = &pvar->hVal;
+
+ // If swapping, swap as a pair of DWORDs
+ CBBYTESWAP(sizeof(DWORD));
+ break;
+
+ case VT_R8:
+ case VT_CY:
+ case VT_DATE:
+ AssertLongLongField(dblVal); // VT_R8
+ AssertLongLongField(cyVal); // VT_CY
+ AssertLongLongField(date); // VT_DATE
+ cb = sizeof(pvar->dblVal);
+ pv = &pvar->dblVal;
+
+ // If swapping, swap as a LONGLONG
+ CBBYTESWAP(cb);
+ break;
+
+ case VT_CLSID:
+ AssertStringField(puuid); // VT_CLSID
+ cb = sizeof(GUID);
+ ppv = (VOID **) &pvar->puuid;
+ cbskip = 0;
+
+ // If swapping, special handling is required
+ CBBYTESWAP( CBBYTESWAP_UID );
+ break;
+
+ case VT_CF:
+
+ // Allocate a CLIPDATA buffer
+ pvar->pclipdata = (CLIPDATA *) pma->Allocate(sizeof(CLIPDATA));
+ if (pvar->pclipdata == NULL)
+ {
+ StatusKBufferOverflow(pstatus, "RtlConvertPropertyToVariant: no memory for CF");
+ goto Exit;
+ }
+
+ // Set the size (includes sizeof(ulClipFmt))
+ pvar->pclipdata->cbSize = PropByteSwap( ((CLIPDATA *) pprop->rgb)->cbSize );
+ if( pvar->pclipdata->cbSize < sizeof(pvar->pclipdata->ulClipFmt) )
+ {
+ StatusError(pstatus, "RtlConvertPropertyToVariant: Invalid VT_CF cbSize",
+ STATUS_INTERNAL_DB_CORRUPTION);
+ goto Exit;
+ }
+
+ // Set the # bytes-to-copy. We can't use the CBPCLIPDATA macro
+ // here because it assumes that the CLIPDATA parameter is correctly
+ // byte-swapped.
+ cb = PropByteSwap( *(DWORD*) pprop->rgb ) - sizeof(pvar->pclipdata->ulClipFmt);
+
+ // Set the ClipFormat itself.
+ pvar->pclipdata->ulClipFmt = PropByteSwap( ((CLIPDATA *) pprop->rgb)->ulClipFmt );
+
+ // Prepare for the alloc & copy. Put the buffer pointer
+ // in pClipData, & skip the ulClipFmt in the copy.
+ ppv = (VOID **) &pvar->pclipdata->pClipData;
+ cbskip += sizeof(ULONG);
+
+ // It's legal for cb to be 0.
+ fNullLegal = TRUE;
+
+ // Adjust to the user-mode pointer (Kernel only)
+ ADJUSTPOINTER(pvar->pclipdata, PointerDelta, CLIPDATA *);
+
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ cb = pvar->blob.cbSize = PropByteSwap( *(ULONG *) pprop->rgb );
+ ppv = (VOID **) &pvar->blob.pBlobData;
+ fNullLegal = TRUE;
+ break;
+
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ fIndirect = TRUE;
+ goto lpstr;
+
+ case VT_BSTR:
+ case VT_LPSTR:
+lpstr:
+ AssertStringField(pszVal); // VT_STREAM, VT_STREAMED_OBJECT
+ AssertStringField(pszVal); // VT_STORAGE, VT_STORED_OBJECT
+ AssertStringField(bstrVal); // VT_BSTR
+ AssertStringField(pszVal); // VT_LPSTR
+
+ // [length field] bytes should be allocated
+ cb = PropByteSwap( *(ULONG *) pprop->rgb );
+
+ // When a buffer is allocated, it's pointer will go
+ // in *ppv.
+ ppv = (VOID **) &pvar->pszVal;
+
+ // Is this a non-empty string?
+ if (cb != 0)
+ {
+ // Is the serialized value one that should be
+ // an Ansi string in the PropVariant?
+
+ if (pvar->vt == VT_LPSTR // It's an LPSTR (always Ansi), or
+ ||
+ !OLECHAR_IS_UNICODE ) // PropVariant strings are Ansi
+ {
+ // If the propset is Unicode, we must do a
+ // conversion to Ansi.
+
+ if (CodePage == CP_WINUNICODE)
+ {
+ WCHAR *pwsz = (WCHAR *) Add2ConstPtr(pprop->rgb, sizeof(ULONG));
+
+ // If necessary, swap the WCHARs. 'pwsz' will point to
+ // the correct (system-endian) string either way. If an
+ // alloc is necessary, 'pchByteSwap' will point to the new
+ // buffer.
+
+ PBSInPlaceAlloc( &pwsz, (WCHAR**) &pchByteSwap, pstatus );
+ if( !NT_SUCCESS( *pstatus )) goto Exit;
+ PROPASSERT(IsUnicodeString( pwsz, cb));
+
+ // Convert the properly-byte-ordered string in 'pwsz'
+ // into MBCS, putting the result in pchConvert.
+
+ RtlpConvertToMultiByte(
+ pwsz,
+ cb,
+ CP_ACP, // Use the system default codepage
+ &pchConvert,
+ &cb,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ }
+ } // if (pvar->vt == VT_LPSTR) ...
+
+ // Otherwise, even though this string may be
+ // Ansi in the Property Set, it must be Unicode
+ // in the PropVariant.
+
+ else
+ {
+ // If necessary, convert to Unicode
+
+ if (CodePage != CP_WINUNICODE)
+ {
+ PROPASSERT(
+ IsAnsiString(
+ (CHAR const *)
+ Add2ConstPtr(pprop->rgb, sizeof(ULONG)),
+ cb));
+
+ RtlpConvertToUnicode(
+ (CHAR const *)
+ Add2ConstPtr(pprop->rgb, sizeof(ULONG)),
+ cb,
+ CodePage,
+ (WCHAR **) &pchConvert,
+ &cb,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ } // if (CodePage != CP_WINUNICODE)
+ else
+ {
+ // The value is Unicode both the property set
+ // and the PropVariant. If byte-swapping is
+ // necessary, we'll do so in units of WCHARs.
+
+ CBBYTESWAP( sizeof(WCHAR) );
+ }
+
+ } // if (pvar->vt == VT_LPSTR) ... else
+
+ // If this is a BSTR property, verify that it is terminated
+ // appropriately.
+
+ if (VT_BSTR == pvar->vt)
+ {
+ BSTR bstr = ( NULL == pchConvert )
+ ? (BSTR) Add2ConstPtr(pprop->rgb, sizeof(ULONG))
+ : (BSTR) pchConvert;
+
+ // On little-endian machines, validate the string.
+#ifdef LITTLEENDIAN
+ PROPASSERT( IsOLECHARString( bstr, MAXULONG ));
+#endif
+
+ // Validate the bstr. Note that even though this bstr may
+ // be byte-swapped, this 'if' block still works because
+ // ByteSwap('\0') == ('\0').
+
+ PROPASSERT( PropByteSwap( (OLECHAR) OLESTR('\0') )
+ ==
+ (OLECHAR) OLESTR('\0') );
+
+ if( (cb & (sizeof(OLECHAR) - 1)) != 0
+ &&
+ OLECHAR_IS_UNICODE
+ ||
+ bstr[cb/sizeof(OLECHAR) - 1] != OLESTR('\0') )
+ {
+ StatusError(pstatus, "RtlConvertPropertyToVariant: Invalid BSTR Property",
+ STATUS_INTERNAL_DB_CORRUPTION);
+ goto Exit;
+ }
+ } // if (VT_BSTR == pvar->vt)
+ } // if (cb != 0)
+
+ fNullLegal = TRUE;
+ break;
+
+ case VT_LPWSTR:
+ fNullLegal = TRUE;
+ AssertStringField(pwszVal); // VT_LPWSTR
+ cb = PropByteSwap( *(ULONG *) pprop->rgb ) * sizeof(WCHAR);
+ ppv = (VOID **) &pvar->pwszVal;
+
+ // If byte-swapping will be necessary, do so for the WCHARs
+ CBBYTESWAP( sizeof(WCHAR) );
+
+ break;
+
+#ifdef PROPVAR_VT_I1
+ case VT_VECTOR | VT_I1:
+ AssertByteVector(cac); // VT_I1
+#endif
+ case VT_VECTOR | VT_UI1:
+ AssertByteVector(caub); // VT_UI1
+ pvar->caub.cElems = PropByteSwap( *(ULONG *) pprop->rgb );
+ cb = pvar->caub.cElems * sizeof(pvar->caub.pElems[0]);
+ ppv = (VOID **) &pvar->caub.pElems;
+ break;
+
+ case VT_VECTOR | VT_I2:
+ case VT_VECTOR | VT_UI2:
+ case VT_VECTOR | VT_BOOL:
+ AssertShortVector(cai); // VT_I2
+ AssertShortVector(caui); // VT_UI2
+ AssertShortVector(cabool); // VT_BOOL
+ pvar->cai.cElems = PropByteSwap( *(ULONG *) pprop->rgb );
+ cb = pvar->cai.cElems * sizeof(pvar->cai.pElems[0]);
+ ppv = (VOID **) &pvar->cai.pElems;
+
+ // If swapping, swap as a WORD
+ CBBYTESWAP(sizeof(pvar->cai.pElems[0]));
+ break;
+
+ case VT_VECTOR | VT_I4:
+ case VT_VECTOR | VT_UI4:
+ case VT_VECTOR | VT_R4:
+ case VT_VECTOR | VT_ERROR:
+ AssertLongVector(cal); // VT_I4
+ AssertLongVector(caul); // VT_UI4
+ AssertLongVector(caflt); // VT_R4
+ AssertLongVector(cascode); // VT_ERROR
+ pvar->cal.cElems = PropByteSwap( *(ULONG *) pprop->rgb );
+ cb = pvar->cal.cElems * sizeof(pvar->cal.pElems[0]);
+ ppv = (VOID **) &pvar->cal.pElems;
+
+ // If byte swapping, swap as DWORDs
+ CBBYTESWAP(sizeof(pvar->cal.pElems[0]));
+ break;
+
+ case VT_VECTOR | VT_I8:
+ case VT_VECTOR | VT_UI8:
+ case VT_VECTOR | VT_FILETIME:
+ AssertLongLongVector(cah); // VT_I8
+ AssertLongLongVector(cauh); // VT_UI8
+ AssertLongLongVector(cafiletime); // VT_FILETIME
+ pvar->cah.cElems = PropByteSwap( *(ULONG *) pprop->rgb );
+ cb = pvar->cah.cElems * sizeof(pvar->cah.pElems[0]);
+ ppv = (VOID **) &pvar->cah.pElems;
+
+ // If byte swapping, swap as DWORDs
+ CBBYTESWAP(sizeof(DWORD));
+ break;
+
+ case VT_VECTOR | VT_R8:
+ case VT_VECTOR | VT_CY:
+ case VT_VECTOR | VT_DATE:
+ AssertLongLongVector(cadbl); // VT_R8
+ AssertLongLongVector(cacy); // VT_CY
+ AssertLongLongVector(cadate); // VT_DATE
+ pvar->cadbl.cElems = PropByteSwap( *(ULONG *) pprop->rgb );
+ cb = pvar->cadbl.cElems * sizeof(pvar->cadbl.pElems[0]);
+ ppv = (VOID **) &pvar->cadbl.pElems;
+
+ // If byte swapping, swap as LONGLONGs
+ CBBYTESWAP(sizeof(pvar->cadbl.pElems[0]));
+ break;
+
+
+ case VT_VECTOR | VT_CLSID:
+ AssertVarVector(cauuid, sizeof(GUID));
+ pvar->cauuid.cElems = PropByteSwap( *(ULONG *) pprop->rgb );
+ cb = pvar->cauuid.cElems * sizeof(pvar->cauuid.pElems[0]);
+ ppv = (VOID **) &pvar->cauuid.pElems;
+
+ // If byte swapping, special handling is required.
+ CBBYTESWAP( CBBYTESWAP_UID );
+ break;
+
+ case VT_VECTOR | VT_CF:
+
+ // Set the count of clipdatas
+ pvar->caclipdata.cElems = PropByteSwap( *(ULONG *) pprop->rgb );
+
+ // How much should we allocate for caclipdata.pElems, & where
+ // should that buffer pointer go?
+ cb = pvar->caclipdata.cElems * sizeof(pvar->caclipdata.pElems[0]);
+ ppv = (VOID **) &pvar->caclipdata.pElems;
+
+ // We need to do work after pElems is allocated.
+ fPostAllocInit = TRUE;
+ break;
+
+ case VT_VECTOR | VT_BSTR:
+ case VT_VECTOR | VT_LPSTR:
+ AssertStringVector(cabstr); // VT_BSTR
+ AssertStringVector(calpstr); // VT_LPSTR
+
+ // Put the element count in the PropVar
+ pvar->calpstr.cElems = PropByteSwap( *(ULONG *) pprop->rgb );
+
+ // An array of cElems pointers should be alloced
+ cb = pvar->calpstr.cElems * sizeof(CHAR*);
+
+ // Show where the array of pointers should go.
+ ppv = (VOID **) &pvar->calpstr.pElems;
+
+ // Additional allocs will be necessary after the vector
+ // is alloced.
+ fPostAllocInit = TRUE;
+
+ break;
+
+ case VT_VECTOR | VT_LPWSTR:
+ AssertStringVector(calpwstr); // VT_LPWSTR
+ pvar->calpwstr.cElems = PropByteSwap( *(ULONG *) pprop->rgb );
+ cb = pvar->calpwstr.cElems * sizeof(ULONG);
+ ppv = (VOID **) &pvar->calpwstr.pElems;
+ fPostAllocInit = TRUE;
+ break;
+
+ case VT_VECTOR | VT_VARIANT:
+ AssertVariantVector(capropvar); // VT_VARIANT
+ pvar->capropvar.cElems = PropByteSwap( *(ULONG *) pprop->rgb );
+ cb = pvar->capropvar.cElems * sizeof(PROPVARIANT);
+ ppv = (VOID **) &pvar->capropvar.pElems;
+ fPostAllocInit = TRUE;
+ break;
+
+ default:
+ DebugTrace(0, DEBTRACE_ERROR, (
+ "RtlConvertPropertyToVariant: unsupported vt=%x\n",
+ pvar->vt));
+ StatusInvalidParameter(pstatus, "RtlConvertPropertyToVariant: bad type");
+ goto Exit;
+
+ } // switch (pvar->vt)
+
+ // ------------------------------------------------------
+ // We've now analyzed the serialized property and learned
+ // about it, now we can put it into the PropVariant.
+ // ------------------------------------------------------
+
+ // Is this a simple, unaligned scalar?
+
+ if (pv != NULL)
+ {
+ // Yes. All we need to do is copy some bytes.
+ PROPASSERT(pchConvert == NULL);
+ RtlCopyMemory(pv, pprop->rgb, cb);
+
+ // We also might need to byte-swap them (but only in the PropVar).
+ PBSBuffer( pv, cb, cbByteSwap );
+ }
+
+ // Otherwise, we need to allocate memory, to which the
+ // PropVariant will point.
+
+ else if (ppv != NULL)
+ {
+ *ppv = NULL;
+
+ if (!fConvertToEmpty && cb == 0) // Kernel only
+ {
+ if (!fNullLegal)
+ {
+ StatusInvalidParameter(pstatus, "RtlConvertPropertyToVariant: bad NULL");
+ goto Exit;
+ }
+ }
+
+ else
+ {
+
+ PROPASSERT(cb != 0 || fConvertToEmpty);
+
+ // Allocate the necessary buffer (which we figured out in the
+ // switch above). For vector properties,
+ // this will just be the pElems buffer at this point.
+ // For singleton BSTR properties, we'll skip this allocate
+ // altogether; they're allocated with SysStringAlloc.
+
+ if( VT_BSTR != pvar->vt )
+ {
+ *ppv = pma->Allocate(max(1, cb));
+ if (*ppv == NULL)
+ {
+ StatusKBufferOverflow(pstatus, "RtlConvertPropertyToVariant: no memory");
+ goto Exit;
+ }
+ }
+
+ // Can we load the PropVariant with a simple copy?
+ if (!fPostAllocInit)
+ {
+ // Yes - all we need is a copy (and an implicit
+ // alloc for BSTRs).
+
+ if (VT_BSTR == pvar->vt)
+ {
+ // We do the copy with the OleAutomation routine
+ // (which does an allocation too).
+ // If byte-swapping is necessary, the switch block
+ // already took care of it, leaving the buffer in
+ // 'pchConvert'.
+
+ PROPASSERT( NULL == *ppv );
+ *ppv = (*UnicodeCallouts.pfnSysAllocString)(
+ ( pchConvert != NULL )
+ ? (OLECHAR *) pchConvert
+ : (OLECHAR *) (pprop->rgb + cbskip) );
+ if (*ppv == NULL)
+ {
+ StatusKBufferOverflow(pstatus, "RtlConvertPropertyToVariant: no memory");
+ goto Exit;
+ }
+ }
+ else
+ {
+ // Copy the property into the PropVariant.
+ RtlCopyMemory(
+ *ppv,
+ pchConvert != NULL?
+ (BYTE const *) pchConvert : pprop->rgb + cbskip,
+ cb);
+
+ }
+
+ // If necessary, byte-swap the property (only in the PropVar).
+ PBSBuffer( *ppv, cb, cbByteSwap );
+
+ } // if (!fPostAllocInit)
+
+ else
+ {
+ // We must do more than just a copy.
+ // (Thus this is a vector of strings, variants, or CFs).
+
+ ULONG cElems = pvar->calpstr.cElems;
+
+ // Initialize the source pointer to point just beyond
+ // the element count.
+
+ BYTE const *pbsrc = pprop->rgb + sizeof(ULONG);
+
+ // Zero all pointers in the pElems array for easy caller cleanup
+ ppv = (VOID **) *ppv;
+ RtlZeroMemory(ppv, cb);
+
+ // Handle Variants, ClipFormats, & Strings separately.
+
+ if (pvar->vt == (VT_VECTOR | VT_VARIANT))
+ {
+ PROPVARIANT *pvarT = (PROPVARIANT *) ppv;
+
+ PROPASSERT(!fIndirect);
+ while (cElems-- > 0)
+ {
+ ULONG cbelement;
+
+ fIndirect = RtlConvertPropertyToVariantNoEH(
+ (SERIALIZEDPROPERTYVALUE const *) pbsrc,
+ CodePage,
+ pvarT,
+ pma,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ PROPASSERT(!fIndirect);
+
+ cbelement = PropertyLengthNoEH(
+ (SERIALIZEDPROPERTYVALUE const *) pbsrc,
+ MAXULONG,
+ CPSS_VARIANTVECTOR,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ pbsrc += cbelement;
+ pvarT++;
+ }
+ } // if (pvar->vt == (VT_VECTOR | VT_VARIANT))
+
+ else if (pvar->vt == (VT_VECTOR | VT_CF))
+ {
+ // Set pcd to &pElems[0]
+ CLIPDATA *pcd = (CLIPDATA *) ppv;
+
+ // Loop through pElems
+ while (cElems-- > 0)
+ {
+ // What is the size of the clipdata (including sizeof(ulClipFmt))?
+ pcd->cbSize = PropByteSwap( ((CLIPDATA *) pbsrc)->cbSize );
+ if( pcd->cbSize < sizeof(pcd->ulClipFmt) )
+ {
+ StatusError(pstatus, "RtlConvertPropertyToVariant: Invalid VT_CF cbSize",
+ STATUS_INTERNAL_DB_CORRUPTION);
+ goto Exit;
+ }
+
+ // How many bytes should we copy to pClipData?
+ cb = CBPCLIPDATA( *pcd );
+
+ // Set the ClipFormat & advance pbsrc to the clipdata.
+ pcd->ulClipFmt = PropByteSwap( ((CLIPDATA *) pbsrc)->ulClipFmt );
+ pbsrc += 2 * sizeof(ULONG);
+
+ // Copy the ClipData into the PropVariant
+
+ pcd->pClipData = NULL;
+ if (cb > 0)
+ {
+ // Get a buffer for the clip data.
+ pcd->pClipData = (BYTE *) pma->Allocate(cb);
+ if (pcd->pClipData == NULL)
+ {
+ StatusKBufferOverflow(pstatus, "RtlConvertPropertyToVariant: no memory for CF[]");
+ goto Exit;
+ }
+
+ // Copy the clipdata into pElems[i].pClipData
+ RtlCopyMemory(pcd->pClipData, pbsrc, cb);
+ ADJUSTPOINTER(pcd->pClipData, PointerDelta, BYTE *);
+
+ } // if (cb > 0)
+
+ // Move pcd to &pElems[i+1], and advance the buffer pointer.
+ pcd++;
+ pbsrc += DwordAlign(cb);
+
+ } // while (cElems-- > 0)
+ } // else if (pvar->vt == (VT_VECTOR | VT_CF))
+
+ else // This is a vector of some kind of string.
+ {
+ // Assume that characters are CHARs
+ ULONG cbch = sizeof(char);
+
+ if (pvar->vt == (VT_VECTOR | VT_LPWSTR))
+ {
+ // Characters are WCHARs
+ cbch = sizeof(WCHAR);
+
+ // If byte-swapping is enabled, LPWSTRs must have
+ // their WCHARs swapped.
+ CBBYTESWAP( sizeof(WCHAR) );
+ }
+
+ while (cElems-- > 0)
+ {
+ ULONG cbcopy;
+
+ cbcopy = cb = PropByteSwap( *((ULONG *) pbsrc) ) * cbch;
+ pbsrc += sizeof(ULONG);
+ pv = (VOID *) pbsrc;
+ PROPASSERT(*ppv == NULL);
+ PROPASSERT(pchConvert == NULL);
+
+ if (fConvertToEmpty || cb != 0)
+ {
+ // Do we have actual data to work with?
+ if (cb != 0)
+ {
+ // Special BSTR pre-processing ...
+ if (pvar->vt == (VT_VECTOR | VT_BSTR))
+ {
+ // If the propset & in-memory BSTRs are of
+ // different Unicode-ness, convert now.
+
+ if (CodePage != CP_WINUNICODE // Ansi PropSet
+ &&
+ OLECHAR_IS_UNICODE ) // Unicode BSTRs
+ {
+ PROPASSERT(IsAnsiString((CHAR*) pv, cb));
+ RtlpConvertToUnicode(
+ (CHAR const *) pv,
+ cb,
+ CodePage,
+ (WCHAR **) &pchConvert,
+ &cbcopy,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ pv = pchConvert;
+ }
+
+ else
+ if (CodePage == CP_WINUNICODE // Unicode PropSet
+ &&
+ !OLECHAR_IS_UNICODE ) // Ansi BSTRs
+ {
+ // If byte-swapping is necessary, the string from
+ // the propset must be swapped before it can be
+ // converted to MBCS. If such a conversion
+ // is necessary, a new buffer is alloced and
+ // put in pchByteSwap. Either way, 'pv' points
+ // to the correct string.
+
+ PBSInPlaceAlloc( (WCHAR**) &pv,
+ (WCHAR**) &pchByteSwap,
+ pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ PROPASSERT(IsUnicodeString((WCHAR*)pv, cb));
+
+ // Convert the Unicode string from the property
+ // set to Ansi.
+
+ RtlpConvertToMultiByte(
+ (WCHAR const *) pv,
+ cb,
+ CP_ACP, // Use the system default codepage
+ &pchConvert,
+ &cbcopy,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ // 'pv' always has the correct string.
+ pv = pchConvert;
+ }
+ else
+ if (CodePage == CP_WINUNICODE)
+ {
+ // Both the BSTR is unicode in the property set,
+ // and must remain unicode in the PropVariant.
+ // But byte-swapping may still be necessary.
+
+ CBBYTESWAP( sizeof(WCHAR) );
+ }
+
+
+#ifdef LITTLEENDIAN
+ PROPASSERT( IsOLECHARString((BSTR)pv, cbcopy ));
+#endif
+
+ // Verify that the BSTR is valid.
+ if( (cbcopy & (sizeof(OLECHAR)-1)) != 0
+ &&
+ OLECHAR_IS_UNICODE
+ ||
+ ((OLECHAR const *) pv)[cbcopy/sizeof(OLECHAR) - 1] != OLESTR('\0') )
+ {
+ StatusError(pstatus, "RtlConvertPropertyToVariant: Invalid BSTR element",
+ STATUS_INTERNAL_DB_CORRUPTION);
+ goto Exit;
+ }
+
+ } // if (pvar->vt == (VT_VECTOR | VT_BSTR))
+
+ // Special LPSTR pre-processing
+ else if (pvar->vt == (VT_VECTOR | VT_LPSTR))
+ {
+ // LPSTRs are always Ansi. If the string
+ // is Unicode in the propset, convert now.
+
+ if (CodePage == CP_WINUNICODE)
+ {
+ // If byte-swapping is necessary, the string from
+ // the propset must be swapped before it can be
+ // converted to MBCS. If such a conversion
+ // is necessary, a new buffer is alloced and
+ // put in pchByteSwap. Either way, 'pv' points
+ // to the correct string.
+
+ PBSInPlaceAlloc( (WCHAR**) &pv, (WCHAR**) &pchByteSwap,
+ pstatus );
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ PROPASSERT(IsUnicodeString((WCHAR*)pv, cb));
+
+ // Convert to Ansi.
+ RtlpConvertToMultiByte(
+ (WCHAR const *) pv,
+ cb,
+ CP_ACP, // Use the system default codepage
+ &pchConvert,
+ &cbcopy,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ pv = pchConvert;
+ }
+
+ PROPASSERT( IsAnsiString( (CHAR const *)pv, cbcopy ));
+ } // else if (pvar->vt == (VT_VECTOR | VT_LPSTR))
+ } // if (cb != 0)
+
+
+ // Allocate memory in the PropVariant and copy
+ // the string.
+
+ if( (VT_BSTR | VT_VECTOR) == pvar->vt )
+ {
+ // For BSTRs, the allocate/copy is performed
+ // by SysStringAlloc.
+
+ *ppv = (*UnicodeCallouts.pfnSysAllocString)( (BSTR) pv );
+ if (*ppv == NULL)
+ {
+ StatusKBufferOverflow(pstatus, "RtlConvertPropertyToVariant: no memory for BSTR element");
+ goto Exit;
+ }
+
+ // The BSTR length should be the property length
+ // minus the NULL.
+ PROPASSERT( BSTRLEN(*ppv) == cbcopy - sizeof(OLECHAR) );
+
+ } // if( VT_BSTR == pvar->vt )
+
+ else
+ {
+ // Allocate a buffer in the PropVariant
+ *ppv = pma->Allocate(max(1, cbcopy));
+ if (*ppv == NULL)
+ {
+ StatusKBufferOverflow(pstatus, "RtlConvertPropertyToVariant: no memory for string element");
+ goto Exit;
+ }
+
+ // Copy from the propset buffer to the PropVariant
+ RtlCopyMemory(*ppv, pv, cbcopy);
+
+ } // if( VT_BSTR == pvar->vt ) ... else
+
+ // If necessary, byte-swap in the PropVariant to get
+ // the proper byte-ordering.
+ PBSBuffer( *ppv, cbcopy, cbByteSwap );
+
+ // Adjust the PropVar element ptr to user-space (kernel only)
+ ADJUSTPOINTER(*ppv, PointerDelta, VOID *);
+
+ // Move, within the propset buffer, to the
+ // next element in the vector.
+ pbsrc += DwordAlign(cb);
+
+ // Delete the temporary buffers
+
+ delete[] pchByteSwap;
+ pchByteSwap = NULL;
+
+ delete [] pchConvert;
+ pchConvert = NULL;
+
+ } // if (fConvertToEmpty || cb != 0)
+
+ // Move, within the PropVariant, to the next
+ // element in the vector.
+ ppv++;
+
+ } // while (cElems-- > 0)
+ } // else if (pvar->vt == (VT_VECTOR | VT_CF)) ... else
+ } // if (!fPostAllocInit) ... else
+
+ ADJUSTPOINTER(*ppvK, PointerDelta, VOID *);
+
+ } // if (!fConvertToEmpty && cb == 0) ... else
+ } // else if (ppv != NULL)
+
+Exit:
+
+ delete[] pchByteSwap;
+ delete [] pchConvert;
+
+ return(fIndirect);
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: CleanupVariants, private
+//
+// Synopsis: Free all memory used by an array of PROPVARIANT
+//
+// Arguments: [pvar] -- pointer to PROPVARIANT
+// [cprop] -- property count
+// [pma] -- caller's memory free routine
+//
+// Returns: None
+//---------------------------------------------------------------------------
+
+#ifndef KERNEL
+VOID
+CleanupVariants(
+ IN PROPVARIANT *pvar,
+ IN ULONG cprop,
+ IN PMemoryAllocator *pma)
+{
+ while (cprop-- > 0)
+ {
+ VOID *pv = NULL;
+ VOID **ppv = NULL;
+#ifdef KERNEL
+ ULONG cbbstr = 0;
+#endif
+ ULONG cElems;
+
+ switch (pvar->vt)
+ {
+ case VT_CF:
+ pv = pvar->pclipdata;
+ if (pv != NULL && pvar->pclipdata->pClipData)
+ {
+ pma->Free(pvar->pclipdata->pClipData);
+ }
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ pv = pvar->blob.pBlobData;
+ break;
+
+ case VT_BSTR:
+#ifdef KERNEL
+ cbbstr = sizeof(ULONG);
+ //FALLTHROUGH
+#endif
+
+ case VT_CLSID:
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ case VT_LPSTR:
+ case VT_LPWSTR:
+ AssertStringField(puuid); // VT_CLSID
+ AssertStringField(pszVal); // VT_STREAM, VT_STREAMED_OBJECT
+ AssertStringField(pszVal); // VT_STORAGE, VT_STORED_OBJECT
+ AssertStringField(bstrVal); // VT_BSTR
+ AssertStringField(pszVal); // VT_LPSTR
+ AssertStringField(pwszVal); // VT_LPWSTR
+ pv = pvar->pszVal;
+ break;
+
+ // Vector properties:
+
+#ifdef PROPVAR_VT_I1
+ case VT_VECTOR | VT_I1:
+ AssertByteVector(cac); // VT_I1
+#endif
+ case VT_VECTOR | VT_UI1:
+ case VT_VECTOR | VT_I2:
+ case VT_VECTOR | VT_UI2:
+ case VT_VECTOR | VT_BOOL:
+ case VT_VECTOR | VT_I4:
+ case VT_VECTOR | VT_UI4:
+ case VT_VECTOR | VT_R4:
+ case VT_VECTOR | VT_ERROR:
+ case VT_VECTOR | VT_I8:
+ case VT_VECTOR | VT_UI8:
+ case VT_VECTOR | VT_R8:
+ case VT_VECTOR | VT_CY:
+ case VT_VECTOR | VT_DATE:
+ case VT_VECTOR | VT_FILETIME:
+ case VT_VECTOR | VT_CLSID:
+ AssertByteVector(caub); // VT_UI1
+ AssertShortVector(cai); // VT_I2
+ AssertShortVector(caui); // VT_UI2
+ AssertShortVector(cabool); // VT_BOOL
+ AssertLongVector(cal); // VT_I4
+ AssertLongVector(caul); // VT_UI4
+ AssertLongVector(caflt); // VT_R4
+ AssertLongVector(cascode); // VT_ERROR
+ AssertLongLongVector(cah); // VT_I8
+ AssertLongLongVector(cauh); // VT_UI8
+ AssertLongLongVector(cadbl); // VT_R8
+ AssertLongLongVector(cacy); // VT_CY
+ AssertLongLongVector(cadate); // VT_DATE
+ AssertLongLongVector(cafiletime); // VT_FILETIME
+ AssertVarVector(cauuid, sizeof(GUID)); // VT_CLSID
+ pv = pvar->cai.pElems;
+ break;
+
+ case VT_VECTOR | VT_CF:
+ {
+ CLIPDATA *pcd;
+
+ cElems = pvar->caclipdata.cElems;
+ pv = pcd = pvar->caclipdata.pElems;
+ while (cElems-- > 0)
+ {
+ if (pcd->pClipData != NULL)
+ {
+ pma->Free(pcd->pClipData);
+ }
+ pcd++;
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_BSTR:
+#ifdef KERNEL
+ cbbstr = sizeof(ULONG);
+ //FALLTHROUGH
+#endif
+
+ case VT_VECTOR | VT_LPSTR:
+ case VT_VECTOR | VT_LPWSTR:
+ AssertStringVector(cabstr); // VT_BSTR
+ AssertStringVector(calpstr); // VT_LPSTR
+ AssertStringVector(calpwstr); // VT_LPWSTR
+ cElems = pvar->calpstr.cElems;
+ ppv = (VOID **) pvar->calpstr.pElems;
+ break;
+
+ case VT_VECTOR | VT_VARIANT:
+ CleanupVariants(
+ pvar->capropvar.pElems,
+ pvar->capropvar.cElems,
+ pma);
+ pv = pvar->capropvar.pElems;
+ break;
+
+ } // switch (pvar->vt)
+
+ if (ppv != NULL) // STRING VECTOR property
+ {
+ // Save the vector of pointers
+ pv = (VOID *) ppv;
+
+ // Free the vector elements
+ while (cElems-- > 0)
+ {
+ if (*ppv != NULL)
+ {
+#ifdef KERNEL
+ pma->Free((BYTE *) *ppv - cbbstr);
+#else
+ if( (VT_BSTR | VT_VECTOR) == pvar->vt )
+ {
+ (*UnicodeCallouts.pfnSysFreeString)( (BSTR) *ppv );
+ }
+ else
+ {
+ pma->Free((BYTE *) *ppv);
+ }
+#endif
+ }
+ ppv++;
+ }
+
+ // Free the vector of pointers.
+ pma->Free(pv);
+ pv = NULL;
+
+ } // if (ppv != NULL)
+
+ if (pv != NULL)
+ {
+#ifdef KERNEL
+ pma->Free((BYTE *) pv - cbbstr);
+#else
+ if( VT_BSTR == pvar->vt )
+ {
+ (*UnicodeCallouts.pfnSysFreeString)( (BSTR) pv );
+ }
+ else
+ {
+ pma->Free((BYTE *) pv);
+ }
+#endif
+ }
+
+ pvar->vt = VT_EMPTY;
+
+ // Move on to the next PropVar in the vector.
+ pvar++;
+
+ } // while (cprop-- > 0)
+}
+#endif // !KERNEL
+
+
+//+--------------------------------------------------------------------------
+// Function: PropertyLength
+//
+// Synopsis: compute the length of a property including the variant type
+//
+// Arguments: [pprop] -- property value
+// [cbbuf] -- max length of accessible memory at pprop
+// [flags] -- CPropertySetStream flags
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: length of property
+//---------------------------------------------------------------------------
+
+
+// First, define a wrapper for this function which returns errors
+// using NT Exception Handling, rather than returning an NTSTATUS.
+
+ULONG
+PropertyLength(
+ SERIALIZEDPROPERTYVALUE const *pprop,
+ ULONG cbbuf,
+ BYTE flags)
+{
+ NTSTATUS status;
+ ULONG ulRet;
+
+ ulRet = PropertyLengthNoEH( pprop, cbbuf, flags, &status );
+
+ if (!NT_SUCCESS( status ))
+ RtlRaiseStatus( status );
+
+ return( ulRet );
+}
+
+// Now define the body of the function, returning errors with an
+// NTSTATUS value instead of raising.
+
+ULONG
+PropertyLengthNoEH(
+ SERIALIZEDPROPERTYVALUE const *pprop,
+ ULONG cbbuf,
+ BYTE flags,
+ OUT NTSTATUS *pstatus)
+{
+ ULONG const *pl = (ULONG const *) pprop->rgb;
+ ULONG cElems = 1;
+ ULONG cbremain = cbbuf;
+ ULONG cb = 0, cbch;
+ BOOLEAN fIllegalType = FALSE;
+
+ *pstatus = STATUS_SUCCESS;
+
+ if (cbremain < CB_SERIALIZEDPROPERTYVALUE)
+ {
+ StatusOverflow(pstatus, "PropertyLength: dwType");
+ goto Exit;
+ }
+ cbremain -= CB_SERIALIZEDPROPERTYVALUE;
+ if( PropByteSwap(pprop->dwType) & VT_VECTOR )
+ {
+ if (cbremain < sizeof(ULONG))
+ {
+ StatusOverflow(pstatus, "PropertyLength: cElems");
+ goto Exit;
+ }
+ cbremain -= sizeof(ULONG);
+ cElems = PropByteSwap( *pl++ );
+ }
+ if( PropByteSwap(pprop->dwType) == (VT_VECTOR | VT_VARIANT) )
+ {
+ while (cElems-- > 0)
+ {
+ cb = PropertyLengthNoEH(
+ (SERIALIZEDPROPERTYVALUE const *) pl,
+ cbremain,
+ flags | CPSS_VARIANTVECTOR,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+ pl = (ULONG const *) Add2ConstPtr(pl, cb);
+ cbremain -= cb;
+ }
+ }
+ else
+ {
+ cbch = sizeof(WCHAR);
+
+ switch( PropByteSwap(pprop->dwType) & VT_TYPEMASK)
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ fIllegalType = (flags & CPSS_VARIANTVECTOR) != 0;
+ break;
+
+#ifdef PROPVAR_VT_I1
+ case VT_I1:
+#endif
+ case VT_UI1:
+ pl = (ULONG const *) Add2ConstPtr(pl, DwordAlign(cElems * sizeof(BYTE)));
+ break;
+
+ case VT_I2:
+ case VT_UI2:
+ case VT_BOOL:
+ pl = (ULONG const *) Add2ConstPtr(pl, DwordAlign(cElems * sizeof(USHORT)));
+ break;
+
+ case VT_I4:
+ case VT_UI4:
+ case VT_R4:
+ case VT_ERROR:
+ pl = (ULONG const *) Add2ConstPtr(pl, cElems * sizeof(ULONG));
+ break;
+
+ case VT_I8:
+ case VT_UI8:
+ case VT_R8:
+ case VT_CY:
+ case VT_DATE:
+ case VT_FILETIME:
+ pl = (ULONG const *) Add2ConstPtr(pl, cElems * sizeof(LONGLONG));
+ break;
+
+ case VT_CLSID:
+ pl = (ULONG const *) Add2ConstPtr(pl, cElems * sizeof(GUID));
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ // FALLTHROUGH
+
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ if (flags & CPSS_VARIANTVECTOR)
+ {
+ fIllegalType = TRUE;
+ break;
+ }
+ // FALLTHROUGH
+
+ case VT_CF:
+ case VT_BSTR:
+ case VT_LPSTR:
+ cbch = sizeof(BYTE);
+ // FALLTHROUGH
+
+ case VT_LPWSTR:
+ while (cElems-- > 0)
+ {
+ if (cbremain < sizeof(ULONG) ||
+ cbremain < (cb = sizeof(ULONG) + DwordAlign(PropByteSwap(*pl) * cbch)))
+ {
+ StatusOverflow(pstatus, "PropertyLength: String/BLOB/CF/Indirect");
+ goto Exit;
+ }
+
+#ifdef LITTLEENDIAN
+ PROPASSERT(
+ (PropByteSwap(pprop->dwType) & VT_TYPEMASK) != VT_LPWSTR
+ ||
+ IsUnicodeString( (WCHAR const *) &pl[1],
+ PropByteSwap(*pl) * sizeof(WCHAR)));
+#endif
+
+ pl = (ULONG const *) Add2ConstPtr(pl, cb);
+ cbremain -= cb;
+ }
+ break;
+
+ default:
+ fIllegalType = TRUE;
+ break;
+ }
+ }
+ if (fIllegalType)
+ {
+ StatusInvalidParameter(pstatus, "PropertyLength: Illegal VarType");
+ goto Exit;
+ }
+ cb = (BYTE *) pl - (BYTE *) pprop;
+ if (cbbuf < cb)
+ {
+ StatusOverflow(pstatus, "PropertyLength: cb");
+ goto Exit;
+ }
+
+ // Make sure PropertyLength works when limited to an exact size buffer.
+ PROPASSERT(cb == cbbuf || PropertyLengthNoEH(pprop, cb, flags, pstatus) == cb);
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // Normalize the error return value.
+ if( !NT_SUCCESS(*pstatus) )
+ cb = 0;
+
+ return(cb);
+}
+
+
+//+--------------------------------------------------------------------------
+// Function: PropertyLengthAsVariant
+//
+// Synopsis: compute the size of external memory required to store the
+// property as a PROPVARIANT
+//
+// Arguments: [pprop] -- property value
+// [cbprop] -- computed length of pprop in propset stream
+// [CodePage] -- property set codepage
+// [flags] -- CPropertySetStream flags
+// [pstatus] -- pointer to NTSTATUS code
+//
+// Returns: length of property
+//---------------------------------------------------------------------------
+
+#ifdef WINNT
+
+// First, define a wrapper which raises NT Exceptions for compatibility
+// with older callers who expect it.
+
+ULONG
+PropertyLengthAsVariant(
+ IN SERIALIZEDPROPERTYVALUE const *pprop,
+ IN ULONG cbprop,
+ IN USHORT CodePage,
+ IN BYTE flags)
+{
+ NTSTATUS status;
+ ULONG ulRet;
+
+ ulRet = PropertyLengthAsVariantNoEH( pprop, cbprop, CodePage, flags, &status );
+
+ if (!NT_SUCCESS( status ))
+ RtlRaiseStatus( status );
+
+ return( ulRet );
+}
+
+// Now define the body of the function, returning errors with an
+// NTSTATUS value instead of raising.
+
+ULONG
+PropertyLengthAsVariantNoEH(
+ IN SERIALIZEDPROPERTYVALUE const *pprop,
+ IN ULONG cbprop,
+ IN USHORT CodePage,
+ IN BYTE flags,
+ OUT NTSTATUS *pstatus)
+{
+ ULONG cElems;
+ ULONG cbvar = 0;
+
+ *pstatus = STATUS_SUCCESS;
+
+
+ PROPASSERT(cbprop == PropertyLengthNoEH(pprop, cbprop, flags, pstatus));
+ if( PropByteSwap(pprop->dwType) & VT_VECTOR )
+ {
+ cElems = *(ULONG *) pprop->rgb;
+ }
+ switch (pprop->dwType)
+ {
+ //default:
+ //case VT_EMPTY:
+ //case VT_NULL:
+ //case VT_I1:
+ //case VT_UI1:
+ //case VT_I2:
+ //case VT_UI2:
+ //case VT_BOOL:
+ //case VT_I4:
+ //case VT_UI4:
+ //case VT_R4:
+ //case VT_ERROR:
+ //case VT_I8:
+ //case VT_UI8:
+ //case VT_R8:
+ //case VT_CY:
+ //case VT_DATE:
+ //case VT_FILETIME:
+ //cbvar = 0;
+ //break;
+
+ case VT_CLSID:
+ cbvar = cbprop - sizeof(ULONG); // don't include VARTYPE
+ break;
+
+ // VT_CF: Round CLIPDATA up to Quad boundary, then drop VARTYPE+size+
+ // clipfmt, which get tossed or unmarshalled into CLIPDATA. Round
+ // byte-granular data size to a Quad boundary when returning result.
+
+ case VT_CF:
+ cbvar = QuadAlign(sizeof(CLIPDATA)) + cbprop - 3 * sizeof(ULONG);
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ cbvar = cbprop - 2 * sizeof(ULONG); // don't include VARTYPE & size
+ break;
+
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+
+ cbvar = cbprop - 2 * sizeof(ULONG);
+ if (CodePage != CP_WINUNICODE)
+ {
+ cbvar *= sizeof(WCHAR); // worst case Unicode conversion
+ }
+
+ break;
+
+ case VT_BSTR:
+
+ // Don't include the size of the VT field, but leave
+ // the size of the length field accounted for.
+ cbvar = cbprop - sizeof(ULONG);
+
+ // Worst-case Ansi->Unicode conversion:
+ cbvar *= sizeof(OLECHAR);
+
+ break;
+
+ case VT_LPSTR: // Assume Ansi conversion saves no space
+ case VT_LPWSTR:
+ cbvar = cbprop - 2 * sizeof(ULONG);
+ break;
+
+ // Vector properties:
+
+#ifdef PROPVAR_VT_I1
+ case VT_VECTOR | VT_I1:
+ AssertByteVector(cac); // VT_I1
+#endif
+ case VT_VECTOR | VT_UI1:
+ case VT_VECTOR | VT_I2:
+ case VT_VECTOR | VT_UI2:
+ case VT_VECTOR | VT_BOOL:
+ case VT_VECTOR | VT_I4:
+ case VT_VECTOR | VT_UI4:
+ case VT_VECTOR | VT_R4:
+ case VT_VECTOR | VT_ERROR:
+ case VT_VECTOR | VT_I8:
+ case VT_VECTOR | VT_UI8:
+ case VT_VECTOR | VT_R8:
+ case VT_VECTOR | VT_CY:
+ case VT_VECTOR | VT_DATE:
+ case VT_VECTOR | VT_FILETIME:
+ case VT_VECTOR | VT_CLSID:
+ AssertByteVector(caub); // VT_UI1
+ AssertShortVector(cai); // VT_I2
+ AssertShortVector(caui); // VT_UI2
+ AssertShortVector(cabool); // VT_BOOL
+ AssertLongVector(cal); // VT_I4
+ AssertLongVector(caul); // VT_UI4
+ AssertLongVector(caflt); // VT_R4
+ AssertLongVector(cascode); // VT_ERROR
+ AssertLongLongVector(cah); // VT_I8
+ AssertLongLongVector(cauh); // VT_UI8
+ AssertLongLongVector(cadbl); // VT_R8
+ AssertLongLongVector(cacy); // VT_CY
+ AssertLongLongVector(cadate); // VT_DATE
+ AssertLongLongVector(cafiletime); // VT_FILETIME
+ AssertVarVector(cauuid, sizeof(GUID));
+
+ // don't include VARTYPE and count fields
+ cbvar = cbprop - 2 * sizeof(ULONG);
+ break;
+
+ case VT_VECTOR | VT_CF: // add room for each pointer
+ AssertVarVector(caclipdata, sizeof(CLIPDATA)); // VT_CF
+
+ // don't include VARTYPE and count fields
+ cbvar = cbprop - 2 * sizeof(ULONG);
+
+ // add room for each CLIPDATA data pointer and enough to Quad align
+ // every clipdata data element and 1 ULONG to Quad align the
+ // CLIPDATA array
+ cbvar += cElems * (sizeof(BYTE *) + sizeof(ULONG)) + sizeof(ULONG);
+ break;
+
+ case VT_VECTOR | VT_BSTR: // add room for each BSTRLEN
+ AssertStringVector(cabstr); // VT_BSTR
+
+ // don't include VARTYPE and count fields
+ cbvar = cbprop - 2 * sizeof(ULONG);
+
+ if (CodePage != CP_WINUNICODE)
+ {
+ cbvar *= sizeof(OLECHAR); // worst case Unicode conversion
+ }
+
+ // add room for each BSTRLEN value and enough to Quad align
+ // every BSTR and 1 ULONG to Quad align the array of BSTR pointers.
+
+ cbvar += cElems * (sizeof(ULONG) + sizeof(ULONG)) + sizeof(ULONG);
+ break;
+
+ case VT_VECTOR | VT_LPSTR: // Assume Ansi conversion saves no space
+ case VT_VECTOR | VT_LPWSTR:
+ AssertStringVector(calpstr); // VT_LPSTR
+ AssertStringVector(calpwstr); // VT_LPWSTR
+
+ // don't include VARTYPE and count fields
+ cbvar = cbprop - 2 * sizeof(ULONG);
+
+ // add enough room to Quad align every string and 1 ULONG to Quad
+ // align the array of string pointers.
+
+ cbvar += cElems * sizeof(ULONG) + sizeof(ULONG);
+ break;
+
+ case VT_VECTOR | VT_VARIANT:
+ {
+ ULONG const *pl = (ULONG const *) pprop->rgb + 1;
+ ULONG cbremain = cbprop - 2 * sizeof(ULONG);
+
+ cbvar = cElems * sizeof(PROPVARIANT);
+
+ while (cElems-- > 0)
+ {
+ ULONG cbpropElem;
+ ULONG cbvarElem;
+
+ cbpropElem = PropertyLengthNoEH(
+ (SERIALIZEDPROPERTYVALUE *) pl,
+ cbremain,
+ flags | CPSS_VARIANTVECTOR,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ cbvarElem = PropertyLengthAsVariantNoEH(
+ (SERIALIZEDPROPERTYVALUE *) pl,
+ cbpropElem,
+ CodePage,
+ flags | CPSS_VARIANTVECTOR,
+ pstatus);
+ if( !NT_SUCCESS(*pstatus) ) goto Exit;
+
+ pl = (ULONG const *) Add2ConstPtr(pl, cbpropElem);
+ cbremain -= cbpropElem;
+ cbvar += cbvarElem;
+ }
+ break;
+ }
+ }
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // Normalize the error return value.
+ if( !NT_SUCCESS(*pstatus) )
+ cbvar = 0;
+
+ return(QuadAlign(cbvar));
+}
+#endif
+
+
+//+--------------------------------------------------------------------------
+// Function: PBSCopy
+//
+// Synopsis: This is a Property Byte-Swap routine. The PBS routines
+// only compile in the BIGENDIAN build. In the
+// LITTLEENDIAN build, they are inlined with NOOP functions.
+//
+// This routine copies the source to the destination,
+// byte-swapping as it copies.
+//
+// Arguments: [VOID*] pvDest
+// Pointer to the target (swapped) buffer.
+// This must be pre-allocated by the caller.
+// [VOID*] pvSource
+// Pointer to the original buffer.
+// [ULONG] cbSize
+// Size in bytes of the buffer.
+// [ULONG] cbByteSwap
+// Size of byte-swapping units.
+//
+// Returns: None.
+//
+//---------------------------------------------------------------------------
+
+#ifdef BIGENDIAN
+
+VOID PBSCopy( OUT VOID *pvDest,
+ IN VOID const *pvSource,
+ IN ULONG cbCopy,
+ IN LONG cbByteSwap )
+{
+ PROPASSERT( (cbCopy & 1) == 0 );
+ PROPASSERT( pvDest != NULL && pvSource != NULL );
+
+ memcpy( pvDest, pvSource, cbCopy );
+ PBSBuffer( pvDest, cbCopy, cbByteSwap );
+}
+
+#endif // BIGENDIAN
+
+
+//+--------------------------------------------------------------------------
+// Function: PBSAllocAndCopy
+//
+// Synopsis: This is a Property Byte-Swap routine. The PBS routines
+// only compile in the BIGENDIAN build. In the
+// LITTLEENDIAN build, they are inlined with NOOP functions.
+//
+// This routine allocs a buffer, and swaps the bytes from
+// the source buffer into the destination.
+//
+// Arguments: [VOID**] ppvDest (out)
+// On success will point to the swapped buffer.
+// [VOID*] pvSource (in)
+// Pointer to the original buffer.
+// [ULONG] cbSize (in)
+// Size in bytes of the buffer.
+// [LONG] cbByteSwap (in)
+// Size of byte-swapping units.
+// [NTSTATUS*] pstatus (out)
+// NTSTATUS code.
+//
+// Returns: None.
+//
+// Note: The caller is responsible for freeing *ppvDest
+// (using ::delete).
+//
+//---------------------------------------------------------------------------
+
+#ifdef BIGENDIAN
+
+VOID PBSAllocAndCopy( OUT VOID **ppvDest,
+ IN VOID const *pvSource,
+ ULONG cbSize,
+ LONG cbByteSwap,
+ OUT NTSTATUS *pstatus)
+{
+ // -----
+ // Begin
+ // -----
+
+ *pstatus = STATUS_SUCCESS;
+ PROPASSERT( ppvDest != NULL && pvSource != NULL );
+
+ // Allocate a buffer.
+ *ppvDest = new BYTE[ cbSize ];
+ if( NULL == *ppvDest )
+ {
+ *pstatus = STATUS_NO_MEMORY;
+ goto Exit;
+ }
+
+ // Swap/copy the bytes.
+ PBSCopy( *ppvDest, pvSource, cbSize, cbByteSwap );
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return;
+
+} // PBSAllocAndCopy
+
+#endif // BIGENDIAN
+
+//+--------------------------------------------------------------------------
+// Function: PBSInPlaceAlloc
+//
+// Synopsis: This is a Property Byte-Swap routine. The PBS routines
+// only compile in the BIGENDIAN build. In the
+// LITTLEENDIAN build, they are inlined with NOOP functions.
+//
+// This routine takes a WCHAR array, allocates a new buffer,
+// and swaps the original array into the new buffer.
+//
+//
+// Arguments: [WCHAR**] ppwszResult
+// IN: *ppwszResult points to string to be swapped.
+// OUT: *ppwszResult points to the swapped string.
+// [WCHAR**] ppwszBuffer
+// *ppwszBuffer points to the buffer which was allocated
+// for the swapped bytes (should be the same as *ppwszResult).
+// *ppwszBuffer must be NULL on input, and must be freed
+// by the caller (using ::delete).
+// [NTSTATUS*] pstatus
+// NTSTATUS code.
+//
+// Returns: None.
+//
+// On input, *ppwszResult contains the original string.
+// An equivalently sized buffer is allocated in *ppwszBuffer,
+// and *ppwszResult is byte-swapped into it. *ppwszResult
+// is then set to the new *ppwszBuffer.
+//
+// It doesn't appear to useful to have both buffer parameters,
+// but it makes it easier on the caller in certain circumstances;
+// *ppwszResult always points to the correct string, whether the
+// build is BIGENDIAN (alloc & swap takes place) or the build
+// is LITTLEENDIAN (nothing happes, so *ppwszResult continues
+// to point to the proper string). The LITTLEENDIAN version of
+// this function is implemented as an inline routine.
+//
+//---------------------------------------------------------------------------
+
+#ifdef BIGENDIAN
+
+VOID PBSInPlaceAlloc( IN OUT WCHAR** ppwszResult,
+ OUT WCHAR** ppwszBuffer,
+ OUT NTSTATUS *pstatus )
+{
+ // ------
+ // Locals
+ // ------
+
+ WCHAR *pwszNewBuffer;
+
+ // Pointers which will walk through the input buffers.
+ WCHAR *pwszOriginal, *pwszSwapped;
+
+ // -----
+ // Begin
+ // -----
+
+ *pstatus = STATUS_SUCCESS;
+
+ // Allocate a new buffer.
+ pwszNewBuffer = new WCHAR[ Prop_wcslen(*ppwszResult) + 1 ];
+ if( NULL == pwszNewBuffer )
+ {
+ *pstatus = STATUS_NO_MEMORY;
+ goto Exit;
+ }
+
+ // Swap the WCHARs into the new buffer.
+
+ pwszOriginal = *ppwszResult;
+ pwszSwapped = pwszNewBuffer;
+
+ do
+ {
+ *pwszSwapped = PropByteSwap(*pwszOriginal++);
+ } while( *pwszSwapped++ != L'\0' );
+
+ // If the caller wants a special pointer to the new buffer,
+ // set it now.
+
+ if( NULL != ppwszBuffer )
+ {
+ PROPASSERT( NULL== *ppwszBuffer );
+ *ppwszBuffer = pwszNewBuffer;
+ }
+
+ // Also point *ppwszResult to the new buffer.
+ *ppwszResult = pwszNewBuffer;
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+ return;
+} // PropByteSwap( WCHAR**, WCHAR**, NTSTATUS*)
+
+#endif // BIGENDIAN
+
+
+//+--------------------------------------------------------------------------
+// Function: PBSBuffer
+//
+// Synopsis: This is a Property Byte-Swap routine. The PBS routines
+// only compile in the BIGENDIAN build. In the
+// LITTLEENDIAN build, they are inlined with NOOP functions.
+//
+// This routine takes a buffer and byte-swaps it. The caller
+// specifies the size of the buffer, and the granularity of
+// the byte-swapping.
+//
+// Arguments: [VOID*] pv
+// Pointer to the buffer to be swapped.
+// [ULONG] cbSize
+// Size in bytes of the buffer.
+// [ULONG] cbByteSwap
+// Size of byte-swapping units.
+//
+// Returns: None.
+//
+// For example, an array of 4 WORDs could be swapped with:
+//
+// PBSBuffer( (VOID*) aw, 8, sizeof(WORD) );
+//
+//---------------------------------------------------------------------------
+
+#ifdef BIGENDIAN
+
+VOID PBSBuffer( IN OUT VOID *pv,
+ IN ULONG cbSize,
+ IN ULONG cbByteSwap )
+{
+ ULONG ulIndex;
+
+ // What kind of swapping should be do?
+
+ switch( cbByteSwap )
+ {
+ // No swapping required
+
+ case 0:
+ case( sizeof(BYTE) ):
+
+ // Nothing to do.
+ break;
+
+ // Swap WORDs
+
+ case( sizeof(WORD) ):
+
+ for( ulIndex = 0; ulIndex < cbSize/sizeof(WORD); ulIndex++ )
+ ByteSwap( &((WORD*)pv)[ulIndex] );
+ break;
+
+ // Swap DWORDs
+
+ case( sizeof(DWORD) ):
+
+ for( ulIndex = 0; ulIndex < cbSize/sizeof(DWORD); ulIndex++ )
+ ByteSwap( &((DWORD*)pv)[ulIndex] );
+ break;
+
+ // Swap LONGLONGs
+
+ case( sizeof(LONGLONG) ):
+
+ for( ulIndex = 0; ulIndex < cbSize/sizeof(LONGLONG); ulIndex++ )
+ ByteSwap( &((LONGLONG*)pv)[ulIndex] );
+ break;
+
+ // Swap GUIDs
+
+ case CBBYTESWAP_UID:
+
+ for( ulIndex = 0; ulIndex < cbSize/sizeof(GUID); ulIndex++ )
+ ByteSwap( &((GUID*)pv)[ulIndex] );
+ break;
+
+ // Error
+
+ default:
+ PROPASSERT( !"Invalid generic byte-swap size" );
+ }
+} // PropByteSwap( VOID*, ULONG, ULONG )
+
+#endif // BIGENDIAN
+
+
+
+
+DEFINE_CBufferAllocator__Allocate
diff --git a/private/ole32/stg/props/prpsetup/makefile b/private/ole32/stg/props/prpsetup/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/props/prpsetup/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/props/prpsetup/makefile.inc b/private/ole32/stg/props/prpsetup/makefile.inc
new file mode 100644
index 000000000..9422df6d2
--- /dev/null
+++ b/private/ole32/stg/props/prpsetup/makefile.inc
@@ -0,0 +1,44 @@
+##
+## Special MakeFile instructions for the IProp Setup
+## (PrpSetup) utility
+##
+## This makefile compiles the resources. Ordinarily,
+## you cause the resources to be compiled by including
+## the .rc file in your SOURCES macro. This, however,
+## compiles the .rc file during pass 1. But our .rc
+## file uses iprop.dll, which doesn't exist until pass 2.
+## So, we don't include the .rc file in SOURCES, and
+## we add all the necessary rules for building it here.
+##
+
+#
+# Make sure we're not here on passes 0/1
+#
+
+!IF "$(NOLINK)" != ""
+!ERROR *** PrpSetup makefile.inc included in pass 0/1
+!ENDIF
+
+#
+# Make the exe file dependent on the res file.
+#
+
+$(TARGET) : $O\prpsetup.res
+
+#
+# Show how what resources need to be compiled.
+#
+
+$O\prpsetup.res : .\prpsetup.rc
+
+# Show that the RC file should be re-compiled if the compressed
+# DLL is updated.
+
+prpsetup.rc : iprop.dl_
+
+# Show how to build the compressed IProp DLL file
+
+iprop.dl_ : $(_NTTREE)\Dump\iprop.dll
+ @echo Compressing - $** to $@ > con:
+ compress $** $@
+
diff --git a/private/ole32/stg/props/prpsetup/prpsetup.cxx b/private/ole32/stg/props/prpsetup/prpsetup.cxx
new file mode 100644
index 000000000..db76c1bf2
--- /dev/null
+++ b/private/ole32/stg/props/prpsetup/prpsetup.cxx
@@ -0,0 +1,612 @@
+
+//+============================================================================
+//
+// File: PrpSetup.cxx
+//
+// Purpose: This file builds to an executable which installs the
+// IProp DLL in the System(32) directory. This is provided
+// for the use of applications which re-distribute that DLL.
+//
+// Usage: PrpSetup [/u] [/c]
+//
+// The /u option indicates that an un-install should be performed.
+// The /c option indicates that console output is desired.
+//
+// History: 10/30/96 MikeHill Get "iprop.dl_" from the exe's resources.
+// 11/26/96 MikeHill Don't use GetTempPath (it's unreliable).
+// Fix printf in error path.
+//
+//+============================================================================
+
+// --------
+// Includes
+// --------
+
+#include <windows.h>
+#include <ole2.h>
+#include <tchar.h>
+#include <stdio.h>
+
+// -------------
+// Global values
+// -------------
+
+// Name-related information for the DLL
+const LPTSTR tszResourceType = TEXT( "FILE" ); // Resource type
+const LPTSTR tszCompressedFilename = TEXT( "IPROP.DL_" ); // Temp file name
+const LPTSTR tszTargetFilename = TEXT( "IPROP.DLL" ); // Final file name
+
+// The reg key where we keep the DLL's install ref-count.
+const LPTSTR tszRegSharedDLLs
+ = TEXT( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs" );
+
+// Registration functions in IProp DLL.
+const LPTSTR tszRegistrationFunction = TEXT( "DllRegisterServer" );
+const LPTSTR tszUnregistrationFunction = TEXT( "DllUnregisterServer" );
+
+
+// ------------
+// Return Codes
+// ------------
+
+#define RETURN_SUCCESS 0
+#define RETURN_ARGUMENT_ERROR 1
+#define RETURN_COULDNT_CREATE_TEMP_FILE 2
+#define RETURN_COULDNT_INSTALL_DLL 3
+#define RETURN_COULDNT_DELETE_DLL 4
+#define RETURN_COULDNT_REGISTER_DLL 5
+#define RETURN_COULDNT_ACCESS_REGISTRY 6
+#define RETURN_OUT_OF_MEMORY 7
+#define RETURN_INTERNAL_ERROR 8
+
+
+//+----------------------------------------------------------------------------
+//
+// Function: Register
+//
+// Synopsis: This function registers or de-registers the IProp DLL.
+//
+// Inputs: [BOOL] fUninstall (in)
+// If true, call DllUnregisterServer, otherwise call
+// DllRegisterServer
+//
+// Returns: [HRESULT]
+//
+//+----------------------------------------------------------------------------
+
+
+HRESULT Register( BOOL fUninstall )
+{
+ HRESULT hr;
+ HINSTANCE hinst = NULL;
+
+ // A function pointer for the registration function
+ typedef HRESULT (STDAPICALLTYPE FNREGISTRATION)();
+ FNREGISTRATION *pfnRegistration = NULL;
+
+ // Load the DLL
+
+ hinst = LoadLibrary( tszTargetFilename );
+ if( NULL == hinst )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ goto Exit;
+ }
+
+ // Get the registration function
+
+ pfnRegistration = (FNREGISTRATION*)
+ GetProcAddress( hinst,
+ fUninstall ? tszUnregistrationFunction
+ : tszRegistrationFunction );
+ if( NULL == pfnRegistration )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ goto Exit;
+ }
+
+ // Register or De-register IProp.
+
+ hr = (*pfnRegistration)();
+ if( FAILED(hr) ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( NULL != hinst )
+ FreeLibrary( hinst );
+
+ return( hr );
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// Function: main()
+//
+// Synopsis: This program loads/removes IProp.DLL into/from the
+// System directory. A ref-count of the number of installs
+// of this DLL is kept in the Registry. The DLL is
+// also registered/deregistered.
+//
+//+----------------------------------------------------------------------------
+
+HRESULT _CRTAPI1 main(int argc, char **argv)
+{
+ // File names and paths
+
+ TCHAR tszSystemPath[_MAX_PATH+1]; // Path to System(32) directory
+ TCHAR tszTempFilename[_MAX_PATH+1]; // Used by VerInstallFile()
+ UINT cbTempFilename = sizeof( tszTempFilename ) - sizeof(TCHAR);
+ TCHAR tszTargetPathAndFile[_MAX_PATH+1]; // E.g. "C:\Win\System32\IProp.dll"
+ // E.g. "C:\Win\System32\iprop.dl_"
+ TCHAR tszTempPathAndFile[_MAX_PATH+1] = {""};
+
+ // Index into argv
+ int nArgIndex;
+
+ // User-settable flags.
+ BOOL fConsole = FALSE;
+ BOOL fInstall = FALSE;
+ BOOL fUninstall = FALSE;
+
+ // Registry data
+ HKEY hkey;
+ DWORD dwRegValueType;
+ DWORD dwRefCount;
+ DWORD cbRefCountSize = sizeof( dwRefCount );
+ DWORD dwDisposition;
+
+ // Handles for reading "iprop.dl_" out of the resources
+ HRSRC hrsrcIProp = NULL; // Handle to the "iprop.dl_" resource.
+ HGLOBAL hglobIProp = NULL; // Handle to the "iprop.dl_" data.
+ LPVOID lpvIProp = NULL; // Pointer to the "iprop.dl_" data.
+ HMODULE hmodCurrent = NULL; // Our module handle
+ HANDLE hfileIProp = NULL; // Handle to "%TEMP%\iprop.dl_" file
+
+
+ // Misc.
+ HRESULT hr = S_OK;
+ INT nReturnCode = RETURN_INTERNAL_ERROR;
+
+ // -----------------
+ // Process the Input
+ // -----------------
+
+ for( nArgIndex = 1; nArgIndex < argc; nArgIndex++ )
+ {
+ if( // Is this argument an option?
+ ( argv[nArgIndex][0] == '/'
+ ||
+ argv[nArgIndex][0] == '-'
+ )
+ && // and is it more than one character?
+ argv[nArgIndex][1] != '\0'
+ && // and is it exactly two characters?
+ argv[nArgIndex][2] == '\0'
+ )
+ {
+ // See if it's an argument we recognize.
+ switch( argv[nArgIndex][1] )
+ {
+ // Installation
+
+ case 'i':
+ case 'I':
+
+ fInstall = TRUE;
+ break;
+
+ // Uninstall
+ case 'u':
+ case 'U':
+
+ fUninstall = TRUE;
+ break;
+
+ // Console output
+ case 'c':
+ case 'C':
+
+ fConsole = TRUE;
+ break;
+ }
+ } // if( ( argv[nArgIndex][0] == '/' ...
+ } // for( nArgIndex = 1; nArgIndex < argc; nArgIndex++ )
+
+ // Did we get an illegal command-line combination?
+
+ if( fInstall && fUninstall )
+ {
+ nReturnCode = RETURN_ARGUMENT_ERROR;
+ goto Exit;
+ }
+
+ // Did the user fail to tell us what to do? If so,
+ // display usage information.
+
+ if( !fInstall && !fUninstall )
+ {
+ _tprintf( TEXT("\n") );
+ _tprintf( TEXT(" Installation program for the Microsoft OLE Property Set Implementation\n") );
+ _tprintf( TEXT(" Usage: IProp [/i | /u] [/c]\n") );
+ _tprintf( TEXT(" Options: /i => Install\n")
+ TEXT(" /u => Uninstall\n")
+ TEXT(" /c => Console output\n") );
+ _tprintf( TEXT(" Examples: IProp /i\n")
+ TEXT(" IProp /u /c\n") );
+
+ nReturnCode = RETURN_SUCCESS;
+ goto Exit;
+ }
+
+
+ // ----------
+ // Initialize
+ // ----------
+
+ // Find the target installation directory.
+
+ if( GetSystemDirectory( tszSystemPath,
+ sizeof(tszSystemPath) - sizeof(TCHAR))
+ == 0 )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ nReturnCode = RETURN_COULDNT_INSTALL_DLL;
+ goto Exit;
+ }
+
+ // Determine the target's total path & filename.
+
+ _tcscpy( tszTargetPathAndFile, tszSystemPath );
+ _tcscat( tszTargetPathAndFile, TEXT("\\") );
+ _tcscat( tszTargetPathAndFile, tszTargetFilename );
+
+ // Generate the filename we'll use for the compressed
+ // IProp DLL file ("iprop.dl_"); use the system directory
+ // and post-pend a filename to it. We can't use GetTempPath,
+ // because it doesn't necessary return a directory which
+ // exists, or which is writable.
+
+ _tcscpy( tszTempPathAndFile, tszSystemPath );
+ _tcscat( tszTempPathAndFile, TEXT("\\") );
+ _tcscat( tszTempPathAndFile, tszCompressedFilename );
+
+ // Open the registry key that holds this DLL's ref-count.
+
+ hr = RegCreateKeyEx( HKEY_LOCAL_MACHINE, // Open key
+ tszRegSharedDLLs, // Name of subkey
+ 0L, // Reserved
+ NULL, // Class
+ 0, // Options
+ KEY_ALL_ACCESS, // SAM desired
+ NULL, // Security attributes
+ &hkey, // Result
+ &dwDisposition ); // "Created" or "Opened"
+ if( ERROR_SUCCESS != hr )
+ {
+ hr = HRESULT_FROM_WIN32( hr );
+ nReturnCode = RETURN_COULDNT_ACCESS_REGISTRY;
+ goto Exit;
+ }
+
+ // Attempt to read our ref-count
+
+ hr = RegQueryValueEx( hkey, // Open key
+ tszTargetPathAndFile, // Value name
+ NULL, // Reserved
+ &dwRegValueType, // Out: value type
+ (LPBYTE) &dwRefCount, // Out: value
+ &cbRefCountSize ); // In: buf size, out: data size
+
+ if( ERROR_FILE_NOT_FOUND == hr )
+ // This entry didn't already exist.
+ dwRefCount = 0;
+
+ else if( ERROR_SUCCESS != hr )
+ {
+ // There was a real error during the Query attempt.
+ hr = HRESULT_FROM_WIN32(hr);
+ nReturnCode = RETURN_COULDNT_ACCESS_REGISTRY;
+ goto Exit;
+ }
+
+ else if ( REG_DWORD != dwRegValueType )
+ {
+ // This is an invalid entry. We won't abort, we'll just
+ // re-initialize it to zero, and at the end we'll overwrite
+ // whatever was already there.
+
+ dwRefCount = 0;
+ }
+
+
+ if( fConsole )
+ {
+ if( fUninstall )
+ _tprintf ( TEXT("Uninstalling \"%s\"\n"), tszTargetPathAndFile );
+ else
+ _tprintf( TEXT("Installing \"%s\"\n"), tszTargetPathAndFile );
+ }
+
+ // ------------------------------
+ // Installation or Uninstallation
+ // ------------------------------
+
+ if( fUninstall )
+ { // We're doing an Un-Install
+
+ // Should we actually delete it? We haven't done a dec-ref yet,
+ // so in the normal case, on the last delete, the RefCount will
+ // currently be 1.
+
+ if( dwRefCount <= 1 )
+ {
+ // Yes - we need to do a delete. First unregister the IProp
+ // DLL. If there's an error we'll abort. So we might leave
+ // an unused file on the machine, but that's better than
+ // possibly deleting a file that is still in use by another
+ // app.
+
+ hr = Register( fUninstall );
+ if( FAILED(hr) )
+ {
+ nReturnCode = RETURN_COULDNT_REGISTER_DLL;
+ goto Exit;
+ }
+
+ // And delete the file
+
+ if( !DeleteFile( tszTargetPathAndFile )
+ &&
+ ERROR_FILE_NOT_FOUND != GetLastError() )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ nReturnCode = RETURN_COULDNT_DELETE_DLL;
+ goto Exit;
+ }
+
+ if( fConsole )
+ _tprintf( TEXT("Removed IProp.DLL\n") );
+
+ // Zero-out the ref count. We'll delete it from the
+ // registry later
+
+ dwRefCount = 0;
+ }
+ else
+ {
+ // We don't need to delete it, just dec-ref it.
+ dwRefCount--;
+
+ if( fConsole )
+ _tprintf( TEXT("IProp.DLL not removed (reference count is now %d)\n"), dwRefCount );
+ }
+ } // if( fUninstall )
+
+ else
+ { // We're doing an Install
+
+ DWORD dwSize; // Size of "iprop.dl_".
+ DWORD cbWritten = 0;
+
+ if( fConsole )
+ _tprintf( TEXT("Extracting \"%s\"\n"), tszTempPathAndFile );
+
+ // Get our module handle;
+
+ hmodCurrent = GetModuleHandle( NULL );
+ if( NULL == hmodCurrent )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ nReturnCode = RETURN_OUT_OF_MEMORY;
+ goto Exit;
+ }
+
+ // Get the resource which is actually the compressed IProp DLL
+
+ hrsrcIProp = FindResource( hmodCurrent,
+ tszCompressedFilename,
+ tszResourceType );
+ if( NULL == hrsrcIProp )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ nReturnCode = RETURN_OUT_OF_MEMORY;
+ goto Exit;
+ }
+
+ // Get the size of "iprop.dl_"
+
+ dwSize = SizeofResource( hmodCurrent, hrsrcIProp );
+ if( 0 == dwSize )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ nReturnCode = RETURN_OUT_OF_MEMORY;
+ goto Exit;
+ }
+
+ // Get "iprop.dl_" into a memory buffer.
+
+ hglobIProp = LoadResource( hmodCurrent, hrsrcIProp );
+ if( NULL == hglobIProp )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ nReturnCode = RETURN_OUT_OF_MEMORY;
+ goto Exit;
+ }
+
+ // Get a pointer to the "iprop.dl_" data.
+
+ lpvIProp = LockResource( hglobIProp );
+ if( NULL == lpvIProp )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ nReturnCode = RETURN_OUT_OF_MEMORY;
+ goto Exit;
+ }
+
+ // Create a temporary file, which will be "iprop.dl_"
+
+ hfileIProp = CreateFile(
+ tszTempPathAndFile, // E.g. "C:\Temp\iprop.dl_"
+ GENERIC_READ | GENERIC_WRITE, // Requested access
+ FILE_SHARE_READ, // Sharing mode
+ NULL, // No security attributes
+ CREATE_ALWAYS, // Overwrite existing
+ FILE_ATTRIBUTE_NORMAL, // Default attributes
+ NULL ); // No template file
+ if( INVALID_HANDLE_VALUE == hfileIProp )
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ nReturnCode = RETURN_COULDNT_CREATE_TEMP_FILE;
+ goto Exit;
+ }
+
+ // Write the contents of "iprop.dl_"
+
+ if( !WriteFile( hfileIProp, lpvIProp, dwSize, &cbWritten, NULL ))
+ {
+ hr = HRESULT_FROM_WIN32( GetLastError() );
+ nReturnCode = RETURN_COULDNT_CREATE_TEMP_FILE;
+ goto Exit;
+ }
+
+ // We must close the file, or VerInstallFile won't open it.
+
+ CloseHandle( hfileIProp );
+ hfileIProp = NULL;
+
+ // Install the file.
+
+ hr = VerInstallFile( 0, // Flags
+ tszCompressedFilename, // Source filename
+ tszTargetFilename, // Dest filename
+ tszSystemPath, // Source location
+ tszSystemPath, // Target location
+ tszSystemPath, // Location of old version
+ tszTempFilename, // Out: name of temp file
+ &cbTempFilename); // In: size of buf, Out: name
+
+ // If VerInstallFile left a temporary file, delete it now.
+
+ if( hr & VIF_TEMPFILE )
+ {
+ TCHAR tszDeleteTempFile[_MAX_PATH+1];
+
+ _tcscpy( tszDeleteTempFile, tszSystemPath );
+ _tcscat( tszDeleteTempFile, TEXT("\\") );
+ _tcscat( tszDeleteTempFile, tszTempFilename );
+ DeleteFile( tszDeleteTempFile );
+ }
+
+ // If the file was installed successfully, register it.
+
+ if( 0 == hr )
+ {
+ hr = Register( fUninstall );
+ if( FAILED(hr) )
+ {
+ nReturnCode = RETURN_COULDNT_REGISTER_DLL;
+ goto Exit;
+ }
+ }
+
+ // If the error wasn't "newer version exists", then we
+ // have a fatal error.
+
+ else if( 0 == (hr & VIF_SRCOLD) )
+ {
+ nReturnCode = RETURN_COULDNT_INSTALL_DLL;
+ goto Exit;
+ }
+ else if( fConsole )
+ {
+ _tprintf( TEXT("A newer version of the file is already installed\n") );
+ }
+
+
+ // Do an add-ref.
+ dwRefCount++;
+
+ } // if( fUninstall ) ... else
+
+
+ // ------------------
+ // Save the Ref-Count
+ // ------------------
+
+ // Did we actually delete the DLL?
+
+ if( 0 == dwRefCount )
+ {
+ // Delete our entry from the SharedDlls entry
+ hr = RegDeleteValue( hkey, tszTargetPathAndFile );
+
+ if( ERROR_FILE_NOT_FOUND == hr )
+ hr = ERROR_SUCCESS;
+
+ else if( ERROR_SUCCESS != hr )
+ {
+ hr = HRESULT_FROM_WIN32(hr);
+ nReturnCode = RETURN_COULDNT_ACCESS_REGISTRY;
+ goto Exit;
+ }
+ }
+ else
+ {
+ // Otherwise, put the new ref-count in the registry.
+ hr = RegSetValueEx( hkey, // Open key
+ tszTargetPathAndFile, // Value name
+ 0, // Reserved
+ REG_DWORD, // Value type
+ (LPBYTE) &dwRefCount, // Value buffer
+ sizeof( dwRefCount )); // Size of value
+ if( ERROR_SUCCESS != hr )
+ {
+ hr = HRESULT_FROM_WIN32(hr);
+ nReturnCode = RETURN_COULDNT_ACCESS_REGISTRY;
+ goto Exit;
+ }
+ } // if( 0 == dwRefCount ) ... else
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( fConsole )
+ {
+ // We only succeeded if hr is 0; VerInstallFile might return
+ // a bitmapped error that doesn't look like an HRESULT error
+ // code.
+
+ if( 0 == hr )
+ _tprintf( TEXT("%s successful\n"),
+ fUninstall ? TEXT("Uninstall") : TEXT("Install") );
+ else
+ _tprintf( TEXT("%s failed. Return code = %d (%08X)\n"),
+ fUninstall ? TEXT("Uninstall") : TEXT("Install"),
+ nReturnCode,
+ hr );
+ }
+
+ // Remove the temporary file (we initialized this to "", so this
+ // call should always return success or file-not-found).
+
+ DeleteFile( tszTempPathAndFile );
+
+ // Free all the handles we've used.
+
+ if( hfileIProp ) CloseHandle( hfileIProp );
+ if( lpvIProp ) GlobalUnlock( lpvIProp );
+
+
+ return( nReturnCode );
+
+}
diff --git a/private/ole32/stg/props/prpsetup/prpsetup.rc b/private/ole32/stg/props/prpsetup/prpsetup.rc
new file mode 100644
index 000000000..ce55c07f9
--- /dev/null
+++ b/private/ole32/stg/props/prpsetup/prpsetup.rc
@@ -0,0 +1,17 @@
+#include <windows.h>
+
+//
+// Version resources
+//
+#include <ntverp.h>
+#undef VER_PRODUCTNAME_STR
+#define VER_PRODUCTNAME_STR "OLE PropertySet Implementation Setup\0"
+#define VER_COMMENT_STR "OLE PropertySet Implementation Setup\0"
+#define VER_FILEDESCRIPTION_STR "OLE PropertySet Implementation Setup\0"
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_INTERNALNAME_STR "PRPSETUP.EXE"
+#define VER_ORIGINALFILENAME_STR "PRPSETUP.EXE"
+#include <common.ver>
+
+iprop.dl_ FILE iprop.dl_
diff --git a/private/ole32/stg/props/prpsetup/sources b/private/ole32/stg/props/prpsetup/sources
new file mode 100644
index 000000000..90f4b7ddc
--- /dev/null
+++ b/private/ole32/stg/props/prpsetup/sources
@@ -0,0 +1,91 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+!ENDIF
+
+
+MAJORCOMP = PrpSetup
+MINORCOMP = PrpSetup
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= IProp
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= PROGRAM
+
+INCLUDES=
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -DNOEXCEPTIONS \
+ -DINC_OLE2 \
+ -DFLAT \
+ -DWIN32=100 \
+ -D_NT1X_=100 \
+ -DCAIROLE_DOWNLEVEL \
+ -DDCOM \
+ -DMSWMSG \
+ -DDCOM_SECURITY \
+ -DNEWPROPS \
+ -D_TRACKLINK_=1 \
+ $(TRACELOG)
+
+
+NTLEGO=1
+
+GPCH_BUILD=daytona
+
+# Note that we don't include prpsetup.rc in the SOURCES macro.
+# There is special handling for this in makefile.inc
+
+SOURCES= \
+ prpsetup.cxx
+
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+
+TARGETLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\version.lib
+
+#
+# We need some special dependencies from makefile.inc in order to link IProp.exe
+# But these only work if iprop.dll already exists. Therefore, we can only
+# include these dependencies in the second pass of the build (in the second
+# pass, "iprop.dll" will have been built already). So we only include the
+# makefile.inc if NOLINK isn't set (it's set on the 0/1 passes).
+#
+
+!IF "$(NOLINK)" == ""
+NTTARGETFILE0=iprop.dl_
+!ENDIF
diff --git a/private/ole32/stg/props/psetstg.cxx b/private/ole32/stg/props/psetstg.cxx
new file mode 100644
index 000000000..724e736ce
--- /dev/null
+++ b/private/ole32/stg/props/psetstg.cxx
@@ -0,0 +1,1583 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: psetstg.cxx
+//
+// Contents: Implementation of common class for OFS and DocFile
+// IPropertySetStorage
+//
+// Classes: CPropertySetStorage
+// CEnumSTATPROPSETSTG
+//
+// History: 1-Mar-95 BillMo Created.
+// 09-May-96 MikeHill Don't delete a CPropertyStorage object,
+// it deletes itself in the Release.
+// 22-May-96 MikeHill Set STATPROPSETSTG.dwOSVersion.
+// 06-Jun-96 MikeHill Added input validation.
+// 15-Jul-96 MikeHill - Handle STATSTG as OLECHAR (not WCHAR).
+// - Added CDocFilePropertySetStorage imp.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#include <pch.cxx>
+#include <prophdr.hxx>
+
+#ifdef _MAC_NODOC
+ASSERTDATA // File-specific data for FnAssert
+#endif
+
+//
+// debugging support
+//
+#if DBG
+CHAR *
+DbgFmtId(REFFMTID rfmtid, CHAR *pszBuf)
+{
+ PropSprintfA(pszBuf, "rfmtid=%08X.%04X.%04X.%02X.%02X.%02X.%02X.%02X.%02X.%02X.%02X",
+ rfmtid.Data1,
+ rfmtid.Data2,
+ rfmtid.Data3,
+ rfmtid.Data4[0],
+ rfmtid.Data4[1],
+ rfmtid.Data4[2],
+ rfmtid.Data4[3],
+ rfmtid.Data4[4],
+ rfmtid.Data4[5],
+ rfmtid.Data4[6],
+ rfmtid.Data4[7]);
+
+ return(pszBuf);
+}
+
+CHAR *
+DbgMode(DWORD grfMode, CHAR *psz)
+{
+ *psz = 0;
+
+ if (grfMode & STGM_TRANSACTED)
+ strcat(psz, "STGM_TRANSACTED | ");
+ else
+ strcat(psz, "STGM_DIRECT | ");
+
+ if (grfMode & STGM_SIMPLE)
+ strcat(psz, "STGM_SIMPLE | ");
+
+ switch (grfMode & 3)
+ {
+ case STGM_READ:
+ strcat(psz, "STGM_READ |");
+ break;
+ case STGM_WRITE:
+ strcat(psz, "STGM_WRITE |");
+ break;
+ case STGM_READWRITE:
+ strcat(psz, "STGM_READWRITE |");
+ break;
+ default:
+ strcat(psz, "BAD grfMode |");
+ break;
+ }
+
+ switch (grfMode & 0x70)
+ {
+ case STGM_SHARE_DENY_NONE:
+ strcat(psz, "STGM_SHARE_DENY_NONE |");
+ break;
+ case STGM_SHARE_DENY_READ:
+ strcat(psz, "STGM_SHARE_DENY_READ |");
+ break;
+ case STGM_SHARE_DENY_WRITE:
+ strcat(psz, "STGM_SHARE_DENY_WRITE |");
+ break;
+ case STGM_SHARE_EXCLUSIVE:
+ strcat(psz, "STGM_SHARE_EXCLUSIVE |");
+ break;
+ default:
+ strcat(psz, "BAD grfMode | ");
+ break;
+ }
+
+
+ if (grfMode & STGM_PRIORITY)
+ strcat(psz, "STGM_PRIORITY | ");
+
+ if (grfMode & STGM_DELETEONRELEASE)
+ strcat(psz, "STGM_DELETEONRELEASE | ");
+
+ if (grfMode & STGM_NOSCRATCH)
+ strcat(psz, "STGM_NOSCRATCH | ");
+
+ if (grfMode & STGM_CREATE)
+ strcat(psz, "STGM_CREATE | ");
+
+ if (grfMode & STGM_CONVERT)
+ strcat(psz, "STGM_CONVERT | ");
+
+ if (grfMode & STGM_FAILIFTHERE)
+ strcat(psz, "STGM_FAILIFTHERE | ");
+
+ return(psz);
+}
+
+CHAR *
+DbgFlags(DWORD grfFlags, CHAR *psz)
+{
+ strcpy(psz, "grfFlags=");
+
+ if (grfFlags & PROPSETFLAG_NONSIMPLE)
+ strcat(psz, "PROPSETFLAG_NONSIMPLE |");
+ else
+ strcat(psz, "PROPSETFLAG_SIMPLE |");
+
+ if (grfFlags & PROPSETFLAG_ANSI)
+ strcat(psz, "PROPSETFLAG_ANSI |");
+ else
+ strcat(psz, "PROPSETFLAG_WIDECHAR |");
+
+ return(psz);
+}
+#endif
+
+//+-------------------------------------------------------------------
+//
+// Member: CDocFilePropertySetStorage::
+// QueryInterface, AddRef, and Release
+//
+// Synopsis: These members differ from the base CPropertySetStorage
+// implementation in that they use the underlying
+// CExposedStream's ref counter.
+//
+//--------------------------------------------------------------------
+
+HRESULT CDocFilePropertySetStorage::QueryInterface( REFIID riid, void **ppvObject)
+{
+ HRESULT hr;
+
+ // ----------
+ // Validation
+ // ----------
+
+ if (S_OK != (hr = Validate()))
+ return(hr);
+
+ VDATEREADPTRIN( &riid, IID );
+ VDATEPTROUT( ppvObject, void* );
+
+ // -----
+ // Query
+ // -----
+
+ return(_pprivstg->GetStorage()->QueryInterface(riid, ppvObject));
+}
+
+ULONG CDocFilePropertySetStorage::AddRef(void)
+{
+ if (S_OK != Validate())
+ return(0);
+ return(_pprivstg->GetStorage()->AddRef());
+}
+
+ULONG CDocFilePropertySetStorage::Release(void)
+{
+ if (S_OK != Validate())
+ return(0);
+ return(_pprivstg->GetStorage()->Release());
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertySetStorage::Create
+//
+// Synopsis: Create a property set for outermost client of
+// IPropertSetStorage.
+//
+// Arguments: Passed through to CPropertyStorage ctor.
+//
+// Returns: S_OK or failure code.
+//
+// Notes: Create a new CPropertyStorage object which will
+// implement IPropertyStorage. The _pprivstg parameter
+// passed into CPropertyStorage::CPropertyStorage is
+// used to create (via QI) a matching type of mapped
+// stream (for OFS or DocFile properties.)
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertySetStorage::Create( REFFMTID rfmtid,
+ const CLSID * pclsid,
+ DWORD grfFlags,
+ DWORD grfMode,
+ IPropertyStorage ** ppprstg)
+{
+ HRESULT hr;
+ DBGBUF(buf1);
+ DBGBUF(buf2);
+ DBGBUF(buf3);
+
+ // ----------
+ // Validation
+ // ----------
+
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ GEN_VDATEREADPTRIN_LABEL(&rfmtid, FMTID, E_INVALIDARG, errRet, hr);
+ GEN_VDATEPTRIN_LABEL(pclsid, CLSID, E_INVALIDARG, errRet, hr);
+ GEN_VDATEPTROUT_LABEL( ppprstg, IPropertyStorage*, E_INVALIDARG, errRet, hr);
+
+ // We don't support PROPSETFLAG_UNBUFFERED from the IPropertySetStorage
+ // interface. This may only be used in the StgOpenPropStg
+ // and StgCreatePropStg APIs. This was done because we can't support
+ // the flag on IPropertySetStorage::Open, so it would be inconsistent
+ // to support it on the Create method.
+
+ if( grfFlags & PROPSETFLAG_UNBUFFERED )
+ {
+ hr = STG_E_INVALIDFLAG;
+ goto errRet;
+ }
+
+
+ // ---------------------------
+ // Create the Property Storage
+ // ---------------------------
+
+ hr = _Create( rfmtid, pclsid, grfFlags, grfMode, ppprstg );
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+ if( E_INVALIDARG != hr )
+ {
+ PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Create(%s, %s, %s, retif=%08X, hr = %08X\n",
+ this, DbgFmtId(rfmtid, buf1), DbgFlags(grfFlags, buf2), DbgMode(grfMode, buf3), *ppprstg, hr));
+ }
+ else
+ {
+ PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Create(%08X, %s, %s, retif=%08X, hr = %08X\n",
+ this, &rfmtid, DbgFlags(grfFlags, buf2), DbgMode(grfMode, buf3), ppprstg, hr));
+ }
+
+ return(hr);
+}
+
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertySetStorage::Open
+//
+// Synopsis: Open a property set for outermost client.
+//
+// Arguments: passed through to CPropertyStorage ctor.
+//
+// Returns: S_OK or error.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertySetStorage::Open( REFFMTID rfmtid,
+ DWORD grfMode,
+ IPropertyStorage ** ppprstg)
+{
+ HRESULT hr;
+ DBGBUF(buf1);
+ DBGBUF(buf2);
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ // Validate inputs
+ GEN_VDATEREADPTRIN_LABEL(&rfmtid, FMTID, E_INVALIDARG, errRet, hr);
+ GEN_VDATEPTROUT_LABEL( ppprstg, IPropertyStorage*, E_INVALIDARG, errRet, hr);
+
+ // -------------------------
+ // Open the Property Storage
+ // -------------------------
+
+ hr = _Open( rfmtid, grfMode, ppprstg );
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ if( E_INVALIDARG != hr )
+ {
+ PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Open(%s, %s) retif=%08X, hr=%08X\n",
+ this, DbgFmtId(rfmtid, buf1), DbgMode(grfMode, buf2), *ppprstg, hr));
+ }
+ else
+ {
+ PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Open(), hr=%08X\n",
+ this, hr));
+ }
+
+ return(hr);
+}
+
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertySetStorage::Delete
+//
+// Synopsis: Delete the specified property set.
+//
+// Arguments: [rfmtid] -- format id of property set to delete.
+//
+// Returns: S_OK if successful, error otherwise.
+//
+// Notes: Get the matching name and try the element deletion.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertySetStorage::Delete( REFFMTID rfmtid)
+{
+ HRESULT hr;
+ DBGBUF(buf);
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ // Validate the input
+ GEN_VDATEREADPTRIN_LABEL(&rfmtid, FMTID, E_INVALIDARG, errRet, hr);
+
+ // --------------------------
+ // Delete the PropertyStorage
+ // --------------------------
+
+ hr = _Delete( rfmtid );
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ if( E_INVALIDARG != hr )
+ {
+ PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Delete(%s) hr = %08X\n",
+ this, DbgFmtId(rfmtid, buf), hr));
+ }
+ else
+ {
+ PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Delete(%08X) hr = %08X\n",
+ this, &rfmtid, hr));
+ }
+
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertySetStorage::Enum
+//
+// Synopsis: Create an enumerator over the property set
+//
+// Arguments: [ppenum] -- where to return the pointer to the
+// enumerator.
+//
+// Returns: S_OK if ok, error otherwise.
+//
+// Notes: [ppenum] is NULL on error.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertySetStorage::Enum( IEnumSTATPROPSETSTG ** ppenum)
+{
+
+ HRESULT hr;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+ if (S_OK != (hr = Validate()))
+ goto errRet;
+
+ // Validate the input
+ GEN_VDATEPTROUT_LABEL( ppenum, IEnumSTATPROPSETSTG*, E_INVALIDARG, errRet, hr);
+ *ppenum = NULL;
+
+ // --------------------
+ // Create the enuerator
+ // --------------------
+
+ hr = STG_E_INSUFFICIENTMEMORY;
+
+ *ppenum = new CEnumSTATPROPSETSTG(_pstg, &hr);
+
+ if (FAILED(hr))
+ {
+ delete (CEnumSTATPROPSETSTG*) *ppenum;
+ *ppenum = NULL;
+ }
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ if( E_INVALIDARG != hr )
+ {
+ PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Enum(retif=%08X), hr = %08X\n",
+ this, *ppenum, hr));
+ }
+ else
+ {
+ PropDbg((DEB_PROP_EXIT, "CPropertySetStorage(%08X)::Enum(), hr = %08X\n",
+ this, hr));
+ }
+
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSETSTG::CEnumSTATPROPSETSTG
+//
+// Synopsis: Constructor which is used to implement
+// IPropertySetStorage::Enum
+//
+// Arguments: [pstg] -- the storage of the container to enumerate.
+// [phr] -- place to return HRESULT, S_OK or error.
+//
+// Notes: We use an STATSTG enumerator over the actual storage
+// to get the information about the property sets.
+//
+//--------------------------------------------------------------------
+
+
+CEnumSTATPROPSETSTG::CEnumSTATPROPSETSTG(IStorage *pstg, HRESULT *phr)
+{
+ HRESULT & hr = *phr;
+
+ _ulSig = ENUMSTATPROPSETSTG_SIG;
+ _cRefs = 1;
+ // BUGBUG: we could use one of the reserved parameters as a pattern
+ // match on \5*
+ hr = pstg->EnumElements(FALSE, NULL, 0, &_penumSTATSTG);
+ if (FAILED(hr))
+ _penumSTATSTG = NULL;
+ _cstatTotalInArray = 0;
+ _istatNextToRead = 0;
+
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSETSTG::CEnumSTATPROPSETSTG
+//
+// Synopsis: Copy constructor which is used to implement
+// IEnumSTATPROPSETSTG::Clone.
+//
+// Arguments: [Other] -- The CEnumSTATPROPSETSTG to clone.
+// [phr] -- place to return HRESULT, S_OK or error.
+//
+//--------------------------------------------------------------------
+
+CEnumSTATPROPSETSTG::CEnumSTATPROPSETSTG( CEnumSTATPROPSETSTG &Other,
+ HRESULT *phr)
+{
+ HRESULT & hr = *phr;
+
+ _ulSig = ENUMSTATPROPSETSTG_SIG;
+ _cRefs = 1;
+ _cstatTotalInArray = 0;
+ _istatNextToRead = Other._istatNextToRead;
+
+ hr = Other._penumSTATSTG->Clone(&_penumSTATSTG);
+ if (hr == S_OK)
+ {
+ // Copy the data in the buffer
+ memcpy(_statarray, Other._statarray, sizeof(_statarray));
+ _cstatTotalInArray = Other._cstatTotalInArray;
+
+ // Copy the strings in the buffer
+ for (ULONG i=0; i<_cstatTotalInArray; i++)
+ {
+ _statarray[i].pwcsName =
+ (OLECHAR*)CoTaskMemAlloc(sizeof(OLECHAR)*(ocslen(Other._statarray[i].pwcsName)+1));
+ if (_statarray[i].pwcsName == NULL)
+ {
+ _cstatTotalInArray = i;
+ hr = STG_E_INSUFFICIENTMEMORY;
+ break;
+ }
+ else
+ {
+ ocscpy(_statarray[i].pwcsName, Other._statarray[i].pwcsName);
+ }
+ }
+ }
+ // note: destructor will cleanup the the strings or enumerator left behind
+ // in the error case
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSETSTG::~CEnumSTATPROPSETSTG
+//
+// Synopsis: Delete the enumerator.
+//
+// Notes: Just releases the contained IEnumSTATSTG
+//
+//--------------------------------------------------------------------
+
+CEnumSTATPROPSETSTG::~CEnumSTATPROPSETSTG()
+{
+ _ulSig = ENUMSTATPROPSETSTG_SIGDEL;
+
+ if (_penumSTATSTG != NULL)
+ _penumSTATSTG->Release();
+
+ CleanupStatArray();
+
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSETSTG::QueryInterface, AddRef, Release
+//
+// Synopsis: IUnknown
+//
+// Arguments: The usual thing.
+//
+//--------------------------------------------------------------------
+
+HRESULT CEnumSTATPROPSETSTG::QueryInterface( REFIID riid, void **ppvObject)
+{
+ HRESULT hr;
+
+ if (S_OK != (hr = Validate()))
+ return(hr);
+
+ *ppvObject = NULL;
+
+ if (IsEqualIID(riid, IID_IEnumSTATPROPSETSTG))
+ {
+ *ppvObject = (IEnumSTATPROPSETSTG *)this;
+ CEnumSTATPROPSETSTG::AddRef();
+ }
+ else
+ if (IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppvObject = (IUnknown *)this;
+ CEnumSTATPROPSETSTG::AddRef();
+ }
+ else
+ {
+ hr = E_NOINTERFACE;
+ }
+ return(hr);
+
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSETSTG::AddRef
+//
+//--------------------------------------------------------------------
+
+ULONG CEnumSTATPROPSETSTG::AddRef(void)
+{
+ if (S_OK != Validate())
+ return(0);
+
+ InterlockedIncrement(&_cRefs);
+ return(_cRefs);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSETSTG::Release
+//
+//--------------------------------------------------------------------
+
+ULONG CEnumSTATPROPSETSTG::Release(void)
+{
+ LONG lRet;
+
+ if (S_OK != Validate())
+ return(0);
+
+ lRet = InterlockedDecrement(&_cRefs);
+
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else
+ if (lRet <0)
+ {
+ lRet = 0;
+ }
+ return(lRet);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSETSTG::Next
+//
+// Synopsis: Implement IEnumSTATPROPSETSTG for ofs and docfile.
+//
+// Arguments: [celt] -- Count of elements to attempt to retrieve.
+// [rgelt] -- Where to put the results. Must be valid for at least
+// celt * sizeof(STATPROPSETSTG) bytes in length.
+// [pceltFetched] -- Count of elements returned is put here if
+// the pointer is non-null. If celt > 1, pceltFetched must
+// be valid non-NULL. If pcelt is non-NULL, it must be valid.
+// if pcelt is NULL, celt must be 1.
+//
+// Returns: S_OK if ok, error otherwise.
+//
+// Notes: We use a stack buffer to get more stuff per call to
+// underlying storage IEnumSTATSTG::Next. We then copy
+// data from the STATSTG's to STATPROPSETSTG's.
+//
+// An outer loop enumerates into statarray and then an
+// inner loop copies each batch into the [rgelt] buffer.
+//
+//--------------------------------------------------------------------
+
+HRESULT CEnumSTATPROPSETSTG::Next(ULONG celt,
+ STATPROPSETSTG * rgelt,
+ ULONG * pceltFetched)
+{
+ HRESULT hr;
+ ULONG celtCallerTotal;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ return(hr);
+
+ // Validate inputs
+
+ if (NULL == pceltFetched)
+ {
+ if (1 != celt)
+ return(STG_E_INVALIDPARAMETER);
+ }
+ else
+ {
+ VDATEPTROUT( pceltFetched, ULONG );
+ *pceltFetched = 0;
+ }
+
+ if (0 == celt)
+ return(hr);
+
+ if( !IsValidPtrOut(rgelt, celt * sizeof(rgelt[0])) )
+ return( E_INVALIDARG );
+
+
+ // -----------------------
+ // Perform the enumeration
+ // -----------------------
+
+ celtCallerTotal = 0;
+
+ //
+ // we do this loop until we have what the caller wanted or error, or
+ // no more.
+ //
+ do
+ {
+ //
+ // If our internal buffer is empty, we (re)load it
+ //
+ if (_istatNextToRead == _cstatTotalInArray)
+ {
+ if (_cstatTotalInArray != 0)
+ CleanupStatArray();
+
+ hr = _penumSTATSTG->Next(sizeof(_statarray)/sizeof(_statarray[0]),
+ _statarray,
+ &_cstatTotalInArray);
+ }
+
+ // S_OK or S_FALSE indicate that we got something
+ if (SUCCEEDED(hr))
+ {
+ //
+ // we loop reading out of this buffer until either we have
+ // all that the caller asked for, or we have exhausted the
+ // buffer.
+ //
+ for (; celtCallerTotal < celt &&
+ _istatNextToRead < _cstatTotalInArray ;
+ _istatNextToRead++)
+ {
+ OLECHAR *pocsName = _statarray[_istatNextToRead].pwcsName;
+ BOOL fDone = FALSE;
+
+ DfpAssert(pocsName != NULL);
+
+ if (pocsName[0] == 5)
+ {
+ // BUGBUG: spec, if no matching fmtid then return GUID_NULL
+
+ // *** get fmtid *** //
+
+ if (!NT_SUCCESS(RtlPropertySetNameToGuid(
+ ocslen(pocsName), pocsName, &rgelt->fmtid)))
+ {
+ ZeroMemory(&rgelt->fmtid, sizeof(rgelt->fmtid));
+ }
+
+ // *** get clsid *** //
+ // *** get grfFlags *** //
+ // BUGBUG: spec: don't support returning PROPSETFLAG_ANSI
+
+ if (_statarray[_istatNextToRead].type == STGTY_STORAGE)
+ {
+ rgelt->clsid = _statarray[_istatNextToRead].clsid;
+ rgelt->grfFlags = PROPSETFLAG_NONSIMPLE;
+ }
+ else
+ {
+ // BUGBUG: spec: don't get the clsid for !PROPSET_NONSIMPLE
+ ZeroMemory(&rgelt->clsid, sizeof(rgelt->clsid));
+ rgelt->grfFlags = 0;
+ }
+
+ // *** get mtime *** //
+ rgelt->mtime = _statarray[_istatNextToRead].mtime;
+
+ // *** get ctime *** //
+ rgelt->ctime = _statarray[_istatNextToRead].ctime;
+
+ // *** get atime *** //
+ rgelt->atime = _statarray[_istatNextToRead].atime;
+
+ // *** default the OS Version *** //
+ rgelt->dwOSVersion = PROPSETHDR_OSVERSION_UNKNOWN;
+
+ rgelt ++;
+ celtCallerTotal ++;
+ }
+ }
+ }
+ }
+ while (celtCallerTotal < celt && hr == S_OK);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = celt == celtCallerTotal ? S_OK : S_FALSE;
+ DfpAssert(hr == S_OK || celtCallerTotal < celt);
+
+ if (pceltFetched != NULL)
+ *pceltFetched = celtCallerTotal;
+ }
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSETSTG::Skip
+//
+// Synopsis: Skip the requested number of elements.
+//
+// Arguments: [celt] -- number to skip.
+//
+// Returns: S_OK if all skipped, S_FALSE if less than requested
+// number skipped, error otherwise.
+//
+// Notes:
+//
+//--------------------------------------------------------------------
+
+HRESULT CEnumSTATPROPSETSTG::Skip(ULONG celt)
+{
+ HRESULT hr;
+ STATPROPSETSTG stat;
+ ULONG celtCallerTotal = 0;
+
+ if (S_OK != (hr = Validate()))
+ return(hr);
+
+ do
+ {
+ hr = Next(1, &stat, NULL);
+ } while ( hr == S_OK && ++celtCallerTotal < celt );
+
+ if (SUCCEEDED(hr))
+ hr = celt == celtCallerTotal ? S_OK : S_FALSE;
+
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSETSTG::CleanupStatArray
+//
+// Synopsis: Free any strings in the array.
+//
+//--------------------------------------------------------------------
+
+VOID CEnumSTATPROPSETSTG::CleanupStatArray()
+{
+ for (ULONG i=0; i<_cstatTotalInArray; i++)
+ {
+ CoTaskMemFree(_statarray[i].pwcsName);
+ _statarray[i].pwcsName = NULL;
+ }
+ _istatNextToRead = 0;
+ _cstatTotalInArray = 0;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSETSTG::Reset
+//
+// Synopsis: Reset the enumerator.
+//
+// Notes: Merely resetting the underlying enumerator should be
+// adequate,
+//
+//--------------------------------------------------------------------
+
+HRESULT CEnumSTATPROPSETSTG::Reset()
+{
+ HRESULT hr;
+
+ if (S_OK != (hr = Validate()))
+ return(hr);
+
+ hr = _penumSTATSTG->Reset();
+ if (hr == S_OK)
+ {
+ CleanupStatArray();
+ }
+
+ return(hr);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSETSTG::Clone
+//
+// Synopsis: Copy the enumeration state of this enumerator.
+//
+// Arguments: [ppenum] -- where to put the pointer to the clone
+//
+// Returns: S_OK if ok, error otherwise.
+//
+// Notes: We end up just calling IEnumSTATSTG::Clone in the
+// CEnumSTATPROPSETSTG constructor.
+//
+//--------------------------------------------------------------------
+
+HRESULT CEnumSTATPROPSETSTG::Clone(IEnumSTATPROPSETSTG ** ppenum)
+{
+ HRESULT hr;
+
+ // ----------
+ // Validation
+ // ----------
+
+ // Validate 'this'
+
+ if (S_OK != (hr = Validate()))
+ return(hr);
+
+ // Validate inputs
+
+ VDATEPTROUT( ppenum, IEnumSTATPROPSETSTG* );
+
+ // --------------------
+ // Clone the enumerator
+ // --------------------
+
+ hr = STG_E_INSUFFICIENTMEMORY;
+
+ *ppenum = new CEnumSTATPROPSETSTG(*this, &hr);
+ if (FAILED(hr))
+ {
+ delete (CEnumSTATPROPSETSTG*) *ppenum;
+ *ppenum = NULL;
+ }
+
+ return(hr);
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertySetStorage::
+// QueryInterface, AddRef, and Release
+//
+// Synopsis: IUnknown members.
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertySetStorage::QueryInterface( REFIID riid, void **ppvObject)
+{
+ HRESULT hr = S_OK;
+
+ // ----------
+ // Validation
+ // ----------
+
+ if (S_OK != (hr = Validate()))
+ return(hr);
+
+ VDATEREADPTRIN( &riid, IID );
+ VDATEPTROUT( ppvObject, void* );
+
+ // -----
+ // Query
+ // -----
+
+ if( IID_IPropertySetStorage == riid
+ ||
+ IID_IUnknown == riid )
+ {
+ *ppvObject = this;
+ AddRef();
+ }
+ else
+ {
+ *ppvObject = NULL;
+ hr = E_NOINTERFACE;
+ }
+
+ return( hr );
+}
+
+ULONG CPropertySetStorage::AddRef(void)
+{
+ LONG lRet;
+
+ // ----------
+ // Validation
+ // ----------
+
+ if (S_OK != Validate())
+ return(0);
+
+ // ------
+ // AddRef
+ // ------
+
+ lRet = InterlockedIncrement( &_cReferences );
+ return( lRet );
+}
+
+ULONG CPropertySetStorage::Release(void)
+{
+ LONG lRet;
+
+ // ----------
+ // Validation
+ // ----------
+
+ if (S_OK != Validate())
+ return(0);
+
+ // ----------------
+ // Decrement/Delete
+ // ----------------
+
+ lRet = InterlockedDecrement( &_cReferences );
+
+ if( 0 == lRet )
+ delete this;
+ else if( 0 > lRet )
+ lRet = 0;
+
+ return( lRet );
+}
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertySetStorage::_Create
+//
+// Synopsis: Create an IPropertyStorage under _pstg.
+//
+// Arguments: [REFFMTID] rfmtid
+// The ID of the new property storage.
+// [const CLSID*] pclsid
+// The instance which can manipulate this
+// property storage.
+// [DWORD] grfFlags
+// From the PROPSETFLAG_* enumeration. _UNBUFFERED
+// is assumed not to be set.
+// [DWORD] grfMode
+// From the STGM_* enumeration.
+// [IPropertyStorage**] ppprstg
+// Receives the result.
+//
+// Returns: [HRESULT]
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertySetStorage::_Create( REFFMTID rfmtid,
+ const CLSID * pclsid,
+ DWORD grfFlags,
+ DWORD grfMode,
+ IPropertyStorage ** ppprstg)
+{
+ // ------
+ // Locals
+ // ------
+
+ HRESULT hr;
+ IStream *pstmPropSet = NULL;
+ IStorage *pstgPropSet = NULL;
+ CPropSetName psn(rfmtid);
+ BOOL fCreated = FALSE;
+
+ *ppprstg = NULL;
+
+ // --------------------------------
+ // Create a child Stream or Storage
+ // --------------------------------
+
+ // Just in case an entry by this name already exists,
+ // attempt to delete it (if necessary).
+
+ if( grfMode & STGM_CREATE )
+ {
+ hr = _pstg->DestroyElement( psn.GetPropSetName() );
+ if( FAILED(hr) && STG_E_FILENOTFOUND != hr )
+ goto Exit;
+ }
+
+
+ if( PROPSETFLAG_NONSIMPLE & grfFlags )
+ {
+ // The Child should be a Storage
+
+ hr = _pstg->CreateStorage( psn.GetPropSetName(),
+ grfMode,
+ 0L, 0L,
+ &pstgPropSet );
+ if( FAILED(hr) ) goto Exit;
+ fCreated = TRUE;
+
+ if( NULL != pclsid )
+ {
+ // We should also set the CLSID of the Storage.
+ hr = pstgPropSet->SetClass(*pclsid);
+ if( FAILED(hr) ) goto Exit;
+ }
+
+ }
+ else
+ {
+ // The Child should be a Stream
+ hr = _pstg->CreateStream( psn.GetPropSetName(),
+ grfMode,
+ 0L, 0L,
+ &pstmPropSet );
+ if( FAILED(hr) ) goto Exit;
+ fCreated = TRUE;
+ }
+
+
+ // ---------------------------
+ // Create the Property Storage
+ // ---------------------------
+
+ // Create a CPropertyStorage
+ *ppprstg = new CPropertyStorage( );
+ if( NULL == *ppprstg )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // Initialize the property set.
+ if( PROPSETFLAG_NONSIMPLE & grfFlags )
+ {
+ // We need a non-simple IPropertyStorage
+
+ ( (CPropertyStorage*) *ppprstg )->Create( pstgPropSet,
+ rfmtid,
+ pclsid,
+ grfFlags,
+ &hr);
+
+ }
+ else
+ {
+ // We need a simple IPropertyStorage
+
+ ( (CPropertyStorage*) *ppprstg)->Create( pstmPropSet,
+ rfmtid,
+ pclsid,
+ grfFlags,
+ &hr);
+
+ }
+ if( FAILED(hr) ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ // On failure ...
+ if( FAILED(hr) )
+ {
+ // Delete the CPropertyStorage
+ delete (CPropertyStorage*) *ppprstg;
+ *ppprstg = NULL;
+
+ // If an entry was created, attempt to delete it.
+ if( fCreated )
+ _pstg->DestroyElement( psn.GetPropSetName() );
+ }
+
+ if( NULL != pstmPropSet )
+ pstmPropSet->Release();
+ if( NULL != pstgPropSet )
+ pstgPropSet->Release();
+
+ return( hr );
+
+} // CPropertySetStorage::_Create()
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertySetStorage::_Open
+//
+// Synopsis: Load a serialized property set into a
+// new IPropertyStorage.
+//
+// Arguments: [REFFMTID] rfmtid
+// The ID of the serialized propset.
+// [DWORD] grfMode
+// From the STGM_* enumeration.
+// [IPropertyStorage**] ppprstg
+// Receives the result.
+//
+// Returns: [HRESULT]
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertySetStorage::_Open( REFFMTID rfmtid,
+ DWORD grfMode,
+ IPropertyStorage ** ppprstg)
+{
+ HRESULT hr;
+
+ IUnknown *punkPropSet = NULL;
+ BOOL fSimple = TRUE;
+ CPropSetName psn(rfmtid);
+
+ *ppprstg = NULL;
+
+ // --------------------------------
+ // Open the child Stream or Storage
+ // --------------------------------
+
+ hr = _pstg->OpenStream( psn.GetPropSetName(),
+ 0L,
+ grfMode & ~STGM_TRANSACTED,
+ 0L,
+ (IStream**) &punkPropSet );
+
+ if( STG_E_FILENOTFOUND == hr )
+ {
+ fSimple = FALSE;
+ hr = _pstg->OpenStorage( psn.GetPropSetName(),
+ NULL,
+ grfMode,
+ NULL,
+ 0L,
+ (IStorage**) &punkPropSet );
+ }
+
+ if( FAILED(hr) ) goto Exit;
+
+
+ // -------------------------
+ // Open the Property Storage
+ // -------------------------
+
+ // Create an empty CPropertyStorage object.
+ *ppprstg = new CPropertyStorage();
+ if( NULL == *ppprstg )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // Open the property set and load it into the CPropertyStorage
+ // object. We pas the default grfFlags, letting the Open method
+ // infer its correct value from the property set.
+
+ if( !fSimple )
+ {
+ ( (CPropertyStorage*) *ppprstg)->Open((IStorage*) punkPropSet,
+ rfmtid,
+ PROPSETFLAG_DEFAULT, // Flags are inferred
+ &hr);
+ }
+ else
+ {
+ ( (CPropertyStorage*) *ppprstg)->Open( (IStream*) punkPropSet,
+ rfmtid,
+ PROPSETFLAG_DEFAULT, // Flags are inferred
+ FALSE, // Don't delete this property set
+ &hr);
+
+ }
+ if( FAILED(hr) ) goto Exit;
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( FAILED(hr) )
+ {
+ delete (CPropertyStorage*) *ppprstg;
+ *ppprstg = NULL;
+ }
+
+ if( NULL != punkPropSet )
+ punkPropSet->Release();
+
+ return( hr );
+
+} // CPropertySetStorage::_Open()
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertySetStorage::_Delete
+//
+// Synopsis: Delete a property set from an property
+// set storage.
+//
+// Arguments: [REFFMTID] rfmtid
+// The property set to delete.
+//
+// Returns: [HRESULT]
+//
+//--------------------------------------------------------------------
+
+HRESULT CPropertySetStorage::_Delete( REFFMTID rfmtid)
+{
+
+ // ------
+ // Locals
+ // ------
+
+ HRESULT hr;
+ CPropSetName psn(rfmtid);
+ IStream *pstm = NULL;
+
+ // --------------------------
+ // Delete the PropertyStorage
+ // --------------------------
+
+ // Check for the special-case
+
+ if( IsEqualIID( rfmtid, FMTID_UserDefinedProperties ))
+ {
+ // This property set is actually the second section of the Document
+ // Summary Information property set. We must delete this
+ // section, but we can't delete the Stream because it
+ // still contains the first section.
+
+ CPropertyStorage* pprstg;
+
+ // Open the Stream.
+ hr = _pstg->OpenStream( psn.GetPropSetName(),
+ NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L,
+ &pstm );
+ if( FAILED(hr) ) goto Exit;
+
+ // Create a CPropertyStorage
+ pprstg = new CPropertyStorage( );
+ if( NULL == pprstg )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // Use the CPropertyStorage to delete the section.
+ pprstg->Open( pstm,
+ rfmtid,
+ PROPSETFLAG_DEFAULT,
+ TRUE, // Delete this section
+ &hr );
+
+ pprstg->Release(); // Deletes *pprstg
+ pprstg = NULL;
+
+ if( FAILED(hr) ) goto Exit;
+
+ } // if( IsEqualIID( rfmtid, FMTID_DocSummaryInformation2 ))
+
+ else
+ {
+ // This is not a special case, so we can just delete
+ // the Stream. Note that if the rfmtid represents the first
+ // section of the DocumentSummaryInformation set, we might be
+ // deleting the second section here as well. That is a documented
+ // side-effect.
+
+ hr = _pstg->DestroyElement(psn.GetPropSetName());
+
+ } // if( IsEqualIID( rfmtid, FMTID_DocSummaryInformation2 )) ... else
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( NULL != pstm )
+ pstm->Release();
+
+ return( hr );
+
+} // CPropertySetStorage::_Delete()
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CDocFilePropertySetStorage::_Create
+//
+// Synopsis: Create a new IPropertyStorage in this
+// DocFile.
+//
+// Arguments: [REFFMTID] rfmtid
+// The ID of the property storage.
+// [const CLSID*] pclsid
+// The instance which understands this
+// property set.
+// [DWORD] grfFlags
+// From the PROPSETFLAG_* enumeration. _UNBUFFERED
+// is assumed not to be set.
+// [DWORD] grfMode
+// From the STGM_* enumeration.
+// [IPropertyStorage**] ppprstg
+// Receives the result.
+//
+// Returns: [HRESULT]
+//
+//--------------------------------------------------------------------
+
+HRESULT CDocFilePropertySetStorage::_Create( REFFMTID rfmtid,
+ const CLSID * pclsid,
+ DWORD grfFlags,
+ DWORD grfMode,
+ IPropertyStorage ** ppprstg)
+{
+ HRESULT hr;
+
+ // ---------------------------
+ // Create the Property Storage
+ // ---------------------------
+
+ *ppprstg = new CDocFilePropertyStorage();
+ if( NULL == *ppprstg )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ ( (CDocFilePropertyStorage*) *ppprstg)->Create(
+ _pprivstg,
+ rfmtid,
+ pclsid,
+ grfFlags,
+ grfMode,
+ &hr);
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if (FAILED(hr))
+ {
+ delete (CDocFilePropertyStorage*) *ppprstg;
+ *ppprstg = NULL;
+ }
+
+ return( hr );
+
+} // CDocFilePropertySetStorage::_Create()
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CDocFilePropertySetStorage::_Open
+//
+// Synopsis: Creates an IPropertyStorage object and
+// loads it with an existing serialized propset
+// from a DocFile.
+//
+// Arguments: [REFFMTID] rfmtid
+// ID of property storage.
+// [DWORD] grfMode
+// From the STGM_* enumeraton. _UNBUFFERED is
+// assumed not to be set.
+// [IPropertyStorage**] ppprstg
+// Receives the result.
+//
+// Returns: [HRESULT]
+//
+// Notes: This differs from CPropertySetStorage::_Open
+// in that it uses a CExposedDocfile.
+//
+//--------------------------------------------------------------------
+
+HRESULT CDocFilePropertySetStorage::_Open( REFFMTID rfmtid,
+ DWORD grfMode,
+ IPropertyStorage ** ppprstg)
+{
+ HRESULT hr;
+
+ // -------------------------
+ // Open the IPropertyStorage
+ // -------------------------
+
+ // Instantiate the implementation.
+
+ *ppprstg = new CDocFilePropertyStorage();
+ if( NULL == *ppprstg )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ // Load from the serialized propsets.
+
+ ( (CDocFilePropertyStorage*) *ppprstg)->Open(
+ _pprivstg, rfmtid, grfMode,
+ FALSE, // Don't delete this section
+ &hr);
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if (FAILED(hr))
+ {
+ delete (CDocFilePropertyStorage*) *ppprstg;
+ *ppprstg = NULL;
+ }
+
+ return( hr );
+
+} // CDocFilePropertySetStorage::_Open()
+
+
+//+-------------------------------------------------------------------
+//
+// Member: CDocFilePropertySetStorage::_Delete
+//
+// Synopsis: Delete a serialized property set in a DocFile.
+//
+// Arguments: [REFFMTID] rfmtid
+// The property set to delete.
+//
+// Returns: [HRESULT]
+//
+//--------------------------------------------------------------------
+
+HRESULT CDocFilePropertySetStorage::_Delete( REFFMTID rfmtid)
+{
+ // ------
+ // Locals
+ // ------
+
+ HRESULT hr;
+
+ // --------------------------
+ // Delete the PropertyStorage
+ // --------------------------
+
+ // Check for the special-case
+
+ if( IsEqualIID( rfmtid, FMTID_UserDefinedProperties ))
+ {
+ // This property set is actually the second section of the Document
+ // Summary Information property set. We must delete this
+ // section, but we can't delete the Stream because it
+ // still contain the first section.
+
+ CDocFilePropertyStorage* pprstg;
+
+ pprstg = new CDocFilePropertyStorage();
+ if( NULL == pprstg )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+ pprstg->Open( _pprivstg,
+ rfmtid,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ TRUE, // Delete this section.
+ &hr);
+
+ pprstg->Release(); // Deletes *pprstg
+ pprstg = NULL;
+
+ } // if( IsEqualIID( rfmtid, FMTID_DocSummaryInformation2 ))
+
+ else
+ {
+ // This is not a special case, so we can just delete
+ // the Stream. Note that if the rfmtid represents the first
+ // section of the DocumentSummaryInformation set, we might be
+ // deleting the second section here as well.
+
+ CPropSetName psn(rfmtid);
+
+ hr = _pprivstg->GetStorage()->DestroyElement(psn.GetPropSetName());
+
+ } // if( IsEqualIID( rfmtid, FMTID_DocSummaryInformation2 )) ... else
+
+Exit:
+
+ return( hr );
+
+} // CDocFilePropertySetStorage::_Delete()
+
+
+
diff --git a/private/ole32/stg/props/psetstg.hxx b/private/ole32/stg/props/psetstg.hxx
new file mode 100644
index 000000000..0448d37c7
--- /dev/null
+++ b/private/ole32/stg/props/psetstg.hxx
@@ -0,0 +1,297 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: psetstg.hxx
+//
+// Contents: Header for classes which provides common implementation of
+// IPropertySetStorage. CPropertySetStorage is a generic
+// implementation, and CDocFilePropertySetStorage is
+// a docfile-specific implementation.
+//
+// Classes: CPropertySetStorage
+//
+// History: 17-Mar-93 BillMo Created.
+// 18-Aug-96 MikeHill Updated for StgCreatePropSet APIs.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#ifndef _PSETSTG_HXX_
+#define _PSETSTG_HXX_
+
+#include <stgprops.hxx>
+
+#define PROPERTYSETSTORAGE_SIG LONGSIG('P','S','S','T')
+#define PROPERTYSETSTORAGE_SIGDEL LONGSIG('P','S','S','t')
+
+#define ENUMSTATPROPSETSTG_SIG LONGSIG('S','P','S','S')
+#define ENUMSTATPROPSETSTG_SIGDEL LONGSIG('S','P','S','s')
+
+//+-------------------------------------------------------------------------
+//
+// Class: CPropertySetStorage
+//
+// Purpose: Implementation of IPropertySetStorage for generic
+// IStorage objects.
+//
+//--------------------------------------------------------------------------
+
+class CPropertySetStorage : public IPropertySetStorage
+{
+public:
+
+ // ---------------
+ // Exposed Methods
+ // ---------------
+
+ CPropertySetStorage(IStorage *pstg);
+ ~CPropertySetStorage();
+
+ STDMETHOD(QueryInterface)( REFIID riid, void **ppvObject);
+
+ STDMETHOD_(ULONG, AddRef)(void);
+
+ STDMETHOD_(ULONG, Release)(void);
+
+ STDMETHOD(Create)( REFFMTID rfmtid,
+ const CLSID * pclsid,
+ DWORD grfFlags,
+ DWORD grfMode,
+ IPropertyStorage ** ppprstg);
+
+ STDMETHOD(Open)( REFFMTID rfmtid,
+ DWORD grfMode,
+ IPropertyStorage ** ppprstg);
+
+ STDMETHOD(Delete)( REFFMTID rfmtid);
+
+ STDMETHOD(Enum)( IEnumSTATPROPSETSTG ** ppenum);
+
+ // -----------------------
+ // Non-overridable Methods
+ // -----------------------
+
+protected:
+
+ inline HRESULT Validate();
+
+ // -------------------
+ // Overridable Methods
+ // -------------------
+
+protected:
+
+ STDMETHOD(_Create)( REFFMTID rfmtid,
+ const CLSID * pclsid,
+ DWORD grfFlags,
+ DWORD grfMode,
+ IPropertyStorage ** ppprstg);
+
+ STDMETHOD(_Open)( REFFMTID rfmtid,
+ DWORD grfMode,
+ IPropertyStorage ** ppprstg);
+
+ STDMETHOD(_Delete)( REFFMTID rfmtid);
+
+ // ------------
+ // Data Members
+ // ------------
+
+protected:
+
+ ULONG _ulSig;
+ IStorage *_pstg;
+
+ // _cRefernces isn't used in the CDocFilePropertySetStorage derivation
+ LONG _cReferences;
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertySetStorage::CPropertySetStorage
+//
+// Synopsis: Initialize the generic property storage object.
+//
+// Arguments: [IStorage*] pstg
+// Can be used to create new property storages.
+//
+//--------------------------------------------------------------------
+
+inline CPropertySetStorage::CPropertySetStorage(IStorage *pstg) :
+ _ulSig(PROPERTYSETSTORAGE_SIG),
+ _pstg( pstg ),
+ _cReferences(1)
+{
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertySetStorage::~CPropertySetStorage
+//
+// Synopsis: Set the deletion signature.
+//
+//--------------------------------------------------------------------
+
+inline CPropertySetStorage::~CPropertySetStorage()
+{
+ _ulSig = PROPERTYSETSTORAGE_SIGDEL;
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropertySetStorage::Validate
+//
+// Synopsis: Validate signature.
+//
+//--------------------------------------------------------------------
+
+inline HRESULT CPropertySetStorage::Validate()
+{
+ return _ulSig == PROPERTYSETSTORAGE_SIG ? S_OK : STG_E_INVALIDHANDLE;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDocFilePropertySetStorage
+//
+// Synopsis: Implementation of IPropertySetStorage which assumes
+// that it is working with a DocFile implementation of IStorage
+// (i.e., _pprivstg is a CExposedDocFile*).
+//
+//--------------------------------------------------------------------------
+
+class CDocFilePropertySetStorage : public CPropertySetStorage
+{
+ // ------------------------
+ // Constructors/Destructors
+ // ------------------------
+
+public:
+
+ CDocFilePropertySetStorage(IPrivateStorage *pprivstg, IStorage *pstg)
+ : CPropertySetStorage( pstg ),
+ _pprivstg(pprivstg)
+ {
+ }
+
+ ~CDocFilePropertySetStorage()
+ {}
+
+ // ---------
+ // Overrides
+ // ---------
+
+ // These methods hold the DocFile-specific code for
+ // this IPropertySetStorage object.
+
+public:
+
+ // IUnknown methods.
+
+ STDMETHOD(QueryInterface)( REFIID riid, void **ppvObject);
+
+ STDMETHOD_(ULONG, AddRef)(void);
+
+ STDMETHOD_(ULONG, Release)(void);
+
+
+protected:
+
+ // Internal CPropertySetStorage methods.
+
+ STDMETHOD(_Create)( REFFMTID rfmtid,
+ const CLSID * pclsid,
+ DWORD grfFlags,
+ DWORD grfMode,
+ IPropertyStorage ** ppprstg);
+
+ STDMETHOD(_Open)( REFFMTID rfmtid,
+ DWORD grfMode,
+ IPropertyStorage ** ppprstg);
+
+ STDMETHOD(_Delete)( REFFMTID rfmtid);
+
+ // ------------
+ // Data members
+ // ------------
+
+protected:
+
+ IPrivateStorage * _pprivstg;
+
+};
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CEnumSTATPROPSETSTG
+//
+// Purpose: Implementation of IEnumSTATPROPSETSTG for native and docfile
+// IStorage objects.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CEnumSTATPROPSETSTG : public IEnumSTATPROPSETSTG
+{
+public:
+ // for IPropertySetStorage::Enum
+ CEnumSTATPROPSETSTG(IStorage *pstg, HRESULT *phr);
+
+ // for IEnumSTATPROPSETSTG::Clone
+ CEnumSTATPROPSETSTG(CEnumSTATPROPSETSTG &Other, HRESULT *phr);
+
+ ~CEnumSTATPROPSETSTG();
+
+ STDMETHOD(QueryInterface)( REFIID riid, void **ppvObject);
+
+ STDMETHOD_(ULONG, AddRef)(void);
+
+ STDMETHOD_(ULONG, Release)(void);
+
+ STDMETHOD(Next)(ULONG celt,
+ STATPROPSETSTG * rgelt,
+ ULONG * pceltFetched);
+
+ // We don't need RemoteNext.
+
+ STDMETHOD(Skip)(ULONG celt);
+
+ STDMETHOD(Reset)();
+
+ STDMETHOD(Clone)(IEnumSTATPROPSETSTG ** ppenum);
+
+private:
+
+ inline HRESULT Validate();
+ VOID CleanupStatArray();
+
+private:
+ ULONG _ulSig;
+ LONG _cRefs;
+ IEnumSTATSTG * _penumSTATSTG;
+ STATSTG _statarray[8];
+ ULONG _cstatTotalInArray;
+ ULONG _istatNextToRead;
+};
+
+//+-------------------------------------------------------------------
+//
+// Member: CEnumSTATPROPSETSTG::Validate
+//
+// Synopsis: Validate signature.
+//
+//--------------------------------------------------------------------
+
+inline HRESULT CEnumSTATPROPSETSTG::Validate()
+{
+ return _ulSig == ENUMSTATPROPSETSTG_SIG ? S_OK : STG_E_INVALIDHANDLE;
+}
+
+#endif
+
diff --git a/private/ole32/stg/props/reserved.cxx b/private/ole32/stg/props/reserved.cxx
new file mode 100644
index 000000000..1d8da8509
--- /dev/null
+++ b/private/ole32/stg/props/reserved.cxx
@@ -0,0 +1,236 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: reserved.cxx
+//
+// Contents: Class that implements reserved memory for properties.
+// This implementation is in the form of two derivations
+// of the CReservedMemory class.
+//
+// Classes: CWin32ReservedMemory
+// CWin31ReservedMemory
+//
+// History: 1-Mar-95 BillMo Created.
+// 29-Aug-96 MikeHill Split CReservedMemory into CWin31 & CWin32
+//
+// Notes:
+//
+// Codework:
+//
+//--------------------------------------------------------------------------
+
+#include <pch.cxx>
+#include "reserved.hxx"
+
+#ifdef _MAC_NODOC
+ASSERTDATA // File-specific data for FnAssert
+#endif
+
+// Instantiate the appropriate object.
+
+#ifdef _MAC
+ CWin31ReservedMemory g_ReservedMemory;
+#else
+ CWin32ReservedMemory g_ReservedMemory;
+#endif
+
+
+//+----------------------------------------------------------------------------
+//
+// Method: CWin32ReservedMemory::_Init
+//
+// Synopsis: We initialize the reserved memory by creating a mutex
+// to protect it, and mapping a view of the pagefile.
+//
+// Inputs: None.
+//
+// Returns: None.
+//
+//+----------------------------------------------------------------------------
+
+
+#ifndef _MAC
+
+HRESULT
+CWin32ReservedMemory::_Init(VOID)
+{
+
+ // We use the Ansi Win32 APIs (e.g. CreateMutexA) so that
+ // we can run on Win95.
+
+ HRESULT hr = STG_E_INSUFFICIENTMEMORY;
+ HANDLE hExclusive = CreateMutexA(NULL, FALSE, "OLESTGPROPMUTEX");
+
+ if (hExclusive == NULL)
+ goto errRet;
+
+ if (WaitForSingleObject(hExclusive, INFINITE) != WAIT_OBJECT_0)
+ goto errCloseExclusive;
+
+ if (_hLock == NULL)
+ {
+ // Holder for attributes to pass in on create.
+ SECURITY_ATTRIBUTES secattr;
+ SECURITY_DESCRIPTOR sd;
+
+ InitializeSecurityDescriptor(&sd, 1);
+ SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
+ secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ secattr.lpSecurityDescriptor = &sd;
+ secattr.bInheritHandle = FALSE;
+
+ _hLock = CreateMutexA(&secattr, FALSE, "OLESTGPROPLOCK");
+ if (_hLock == NULL)
+ goto errReleaseExclusive;
+
+ _hMapping = CreateFileMappingA((HANDLE)0xFFFFFFFF, // handle of file to map
+ &secattr, // optional security attributes
+ PAGE_READWRITE, // protection for mapping object
+ 0, // high-order 32 bits of object size
+ CBMAXPROPSETSTREAM, // low-order 32 bits of object size
+ "OLESTGPROPMAP"); // name of file-mapping object
+ if (_hMapping == NULL)
+ goto errCloseLock;
+
+ _pb = (BYTE*)MapViewOfFile(_hMapping, // file-mapping object to map into address space
+ FILE_MAP_WRITE, // access mode
+ 0, // high-order 32 bits of file offset
+ 0, // low-order 32 bits of file offset
+ 0); // number of bytes to map
+ if (_pb == NULL)
+ goto errCloseMapping;
+ }
+
+ _fInitializedHint = TRUE;
+ hr = S_OK;
+
+errCloseMapping:
+ if (hr != S_OK)
+ {
+ CloseHandle(_hMapping);
+ _hMapping = NULL;
+ }
+
+errCloseLock:
+ if (hr != S_OK)
+ {
+ CloseHandle(_hLock);
+ _hLock = NULL;
+ }
+
+errReleaseExclusive:
+ ReleaseMutex(hExclusive);
+
+errCloseExclusive:
+ CloseHandle(hExclusive);
+
+errRet:
+ return(hr);
+
+}
+
+#endif // #ifndef _MAC
+
+
+//+----------------------------------------------------------------------------
+//
+// Method: CWin32ReservedMemory::~CWin32ReservedMemory
+//
+// Inputs: N/A
+//
+// Returns: N/A
+//
+//+----------------------------------------------------------------------------
+
+#ifndef _MAC
+
+CWin32ReservedMemory::~CWin32ReservedMemory()
+{
+ // If we were successfully initialized, free everything
+ // now.
+
+ if (_fInitializedHint)
+ {
+ UnmapViewOfFile(_pb);
+ CloseHandle(_hMapping);
+ CloseHandle(_hLock);
+ }
+}
+
+#endif // #ifndef _MAC
+
+
+//+----------------------------------------------------------------------------
+//
+// Method: CWin32ReservedMemory::LockMemory/UnlockMemory
+//
+// Synopsis: These methods use a Mutex to lock & unlock the
+// shared memory region. The Lock call is blocking.
+//
+// Inputs: None.
+//
+// Returns: Lock() returns a pointer to the locked memory.
+//
+//+----------------------------------------------------------------------------
+
+#ifndef _MAC
+
+BYTE * CWin32ReservedMemory::LockMemory(VOID)
+{
+ DfpVerify(WaitForSingleObject(_hLock, INFINITE) == WAIT_OBJECT_0);
+ return _pb;
+}
+
+VOID CWin32ReservedMemory::UnlockMemory(VOID)
+{
+ DfpVerify(ReleaseMutex(_hLock));
+}
+
+#endif // #ifndef _MAC
+
+
+//+----------------------------------------------------------------------------
+//
+// Method: CWin31ReservedMemory::LockMemory/UnlockMemory
+//
+// Synopsis: This derivation of the CReservedMemory does not provide
+// a locking mechanism, so no locking is performed. The Lock
+// method simply returns the shared memory buffer.
+//
+// Inputs: None.
+//
+// Returns: Nothing
+//
+//+----------------------------------------------------------------------------
+
+
+#ifdef _MAC
+
+BYTE * CWin31ReservedMemory::LockMemory(VOID)
+{
+
+ DfpAssert( !_fLocked );
+ #if DBG==1
+ _fLocked = TRUE;
+ #endif
+
+ return (BYTE*) g_pbPropSetReserved;
+
+}
+
+
+VOID CWin31ReservedMemory::UnlockMemory(VOID)
+{
+
+ // No locking required on the Mac.
+
+ DfpAssert( _fLocked );
+ #if DBG==1
+ _fLocked = FALSE;
+ #endif
+
+}
+
+#endif // #ifdef _MAC
diff --git a/private/ole32/stg/props/reserved.hxx b/private/ole32/stg/props/reserved.hxx
new file mode 100644
index 000000000..623815f39
--- /dev/null
+++ b/private/ole32/stg/props/reserved.hxx
@@ -0,0 +1,183 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: reserved.hxx
+//
+// Contents: Definition for class to handle reserved memory for
+// property operation.
+//
+// Classes: CWin32ReservedMemory
+// CWin31ReservedMemory
+//
+// History: 07-Jun-92 BillMo Created.
+// 29-Aug-96 MikeHill Split CReservedMemory into CWin31 & CWin32
+//
+//--------------------------------------------------------------------------
+
+#ifndef _RESERVED_HXX_
+#define _RESERVED_HXX_
+
+//+-------------------------------------------------------------------------
+//
+// Class: CReservedMemory
+//
+// Purpose: Provide a memory reservation mechanism. Once initialized,
+// a pointer to the memory can be retrieved with the Lock
+// which obviously locks the buffer as well.
+//
+//--------------------------------------------------------------------------
+
+class CReservedMemory
+{
+public:
+
+ virtual ~CReservedMemory() {};
+
+public:
+
+ virtual HRESULT Init(VOID) = 0;
+ virtual BYTE * LockMemory(VOID) = 0;
+ virtual VOID UnlockMemory(VOID) = 0;
+
+};
+
+
+//+----------------------------------------------------------------------------
+//
+// Class: CWin32ReservedMemory
+//
+// Purpose: Defines a derivation of CReservedMemory which can be
+// used in a Win32 environment. Win32 is necessary
+// for its Mutex and file-mapping APIs.
+//
+//+----------------------------------------------------------------------------
+
+#ifndef _MAC
+
+class CWin32ReservedMemory : public CReservedMemory
+{
+
+// Constructors.
+
+public:
+ CWin32ReservedMemory()
+ {
+ _hLock = NULL;
+ _hMapping = NULL;
+ _pb = NULL;
+ _fInitializedHint = FALSE;
+ }
+ ~CWin32ReservedMemory();
+
+// Public overrides
+
+public:
+
+ HRESULT Init(VOID)
+ {
+ if (!_fInitializedHint)
+ return(_Init());
+ else
+ return(S_OK);
+ }
+
+ BYTE * LockMemory(VOID);
+ VOID UnlockMemory(VOID);
+
+// Internal methods
+
+private:
+
+ HRESULT _Init(VOID);
+
+// Internal data
+
+private:
+
+ HANDLE _hLock; // all initialized to zero...
+ HANDLE _hMapping;
+ BYTE * _pb;
+ BOOL _fInitializedHint;
+
+};
+
+#endif // #ifndef _MAC
+
+
+//+----------------------------------------------------------------------------
+//
+// Class: CWin31ReservedMemory
+//
+// Purpose: This derivation of CReservedMemory assumes the Win 3.1
+// architecture of shared-memory DLLs and cooperative multi-threading.
+//
+// This class assumes that the g_pbPropSetReserved extern is a
+// large enough buffer for the largest property set.
+// Note that on the Mac, g_pbPropSetReserved should exist in
+// a shared-data library, so that there need not be one
+// Reserved buffer per instance of the property set library.
+//
+//+----------------------------------------------------------------------------
+
+#ifdef _MAC
+
+class CWin31ReservedMemory : public CReservedMemory
+{
+// Constructors
+
+public:
+
+ CWin31ReservedMemory()
+ {
+ #if DBG==1
+ _fLocked = FALSE;
+ #endif
+ }
+
+ ~CWin31ReservedMemory()
+ {
+ DfpAssert( !_fLocked );
+ }
+
+// Public overrides
+
+public:
+
+ HRESULT Init(VOID)
+ {
+ return(S_OK);
+ }
+
+ BYTE * LockMemory(VOID);
+ VOID UnlockMemory(VOID);
+
+// Private data
+
+private:
+
+ #if DBG==1
+ BOOL _fLocked;
+ #endif
+
+};
+
+#endif // #ifdef _MAC
+
+
+//
+// Provide an extern for the instantiation of CReservedMemory.
+// We use the CWin31 class on the Mac, and the CWin32 everywhere
+// else. Also, along with the CWin31 extern, we must extern
+// the global reserved memory buffer.
+//
+
+#ifdef _MAC
+ EXTERN_C long g_pbPropSetReserved[];
+ extern CWin31ReservedMemory g_ReservedMemory;
+#else
+ extern CWin32ReservedMemory g_ReservedMemory;
+#endif
+
+#endif // #ifndef _RESERVED_HXX_
diff --git a/private/ole32/stg/props/stgvarb.cxx b/private/ole32/stg/props/stgvarb.cxx
new file mode 100644
index 000000000..c5fd2365f
--- /dev/null
+++ b/private/ole32/stg/props/stgvarb.cxx
@@ -0,0 +1,1206 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: StgVarB.cxx
+//
+// Contents: C++ Base wrapper for PROPVARIANT.
+//
+// History: 01-Aug-94 KyleP Created
+// 31-Jul-96 MikeHill - Relaxed assert in IsUnicodeString.
+// - Allow NULL strings.
+//
+//--------------------------------------------------------------------------
+
+#include <pch.cxx>
+
+#include "debtrace.hxx"
+#include <propset.h>
+#include <propvar.h>
+
+// These optionally-compiled directives tell the compiler & debugger
+// where the real file, rather than the copy, is located.
+#ifdef _ORIG_FILE_LOCATION_
+#if __LINE__ != 25
+#error File heading has change size
+#else
+#line 29 "\\nt\\private\\dcomidl\\stgvarb.cxx"
+#endif
+#endif
+
+#if DBGPROP
+
+BOOLEAN
+IsUnicodeString(WCHAR const *pwszname, ULONG cb)
+{
+ if (cb != 0)
+ {
+ ULONG i, cchDoubleAnsi, cchNull;
+
+ cchNull = cchDoubleAnsi = 0;
+ for (i = 0; pwszname[i] != L'\0'; i++)
+ {
+ if ((char) pwszname[i] == '\0' || (char) (pwszname[i] >> 8) == '\0')
+ {
+ cchNull++;
+ if (i > 8 && cchDoubleAnsi > (3*i)/4)
+ {
+ // BUGBUG: This is a heuristic that should NOT be left in
+ // the build for long (even the checked build).
+ //PROPASSERT(!"IsUnicodeString: Suspicious string: double Ansi chars");
+ //return(FALSE);
+ return(TRUE);
+ }
+ }
+ else
+ if (isprint((char) pwszname[i]) && isprint((char) (pwszname[i] >> 8)))
+ {
+ cchDoubleAnsi++;
+ }
+ }
+ if (cchNull < i/4)
+ {
+ // BUGBUG: This is a heuristic that should NOT be left in the
+ // build for long (even the checked build).
+
+ //BUGBUG: cscdrt stringizes GUIDs, leaving lots of high bytes set.
+ //The DRT needs to change to avoid case mapping problems.
+ //Until then, return TRUE
+ //PROPASSERT(!"IsUnicodeString: Suspicious string: too few zero-extended Ansi chars");
+ //return(FALSE);
+ }
+
+ // If cb isn't MAXULONG we verify that cb is at least as
+ // big as the string. We can't check for equality, because
+ // there are some property sets in which the length field
+ // for a string may include several zero padding bytes.
+
+ PROPASSERT(cb == MAXULONG || (i + 1) * sizeof(WCHAR) <= cb);
+ }
+ return(TRUE);
+}
+
+
+BOOLEAN
+IsAnsiString(CHAR const *pszname, ULONG cb)
+{
+ if (cb != 0)
+ {
+ ULONG i;
+
+ // If the string is NULL, then it's not not an Ansi string,
+ // so we'll call it an Ansi string.
+
+ if( NULL == pszname )
+ return( TRUE );
+
+ for (i = 0; pszname[i] != '\0'; i++)
+ {
+ }
+ if (i == 1 && isprint(pszname[0]) &&
+ ((ULONG) &pszname[8] & 0xfff) == ((ULONG) pszname & 0xfff) &&
+ isprint(pszname[2]) && pszname[3] == '\0' &&
+ isprint(pszname[4]) && pszname[5] == '\0' &&
+ isprint(pszname[6]) && pszname[7] == '\0')
+ {
+ // BUGBUG: This is a heuristic that should NOT be left in the
+ // build for long (even the checked build).
+ PROPASSERT(!"IsAnsiString: Suspicious string: looks like Unicode");
+ return(FALSE);
+ }
+
+ // If cb isn't MAXULONG we verify that cb is at least as
+ // big as the string. We can't check for equality, because
+ // there are some property sets in which the length field
+ // for a string may include several zero padding bytes.
+
+ PROPASSERT(cb == MAXULONG || i + 1 <= cb);
+ }
+ return(TRUE);
+}
+#endif
+
+
+//+-------------------------------------------------------------------
+// Member: CBaseStorageVariant::UnmarshalledSize, public
+//
+// Synopsis: Unmarshalls a PROPVARIANT value serialized in a PDeSerStream.
+//
+// Arguments: [stm] -- serialized stream
+// [cb] -- size of *additional* data goes here. Size of
+// base PROPVARIANT not included.
+//
+// Returns: one of the following NTSTATUS values
+// STATUS_SUCCESS -- the call was successful.
+// STATUS_INVALID_PARAMETER -- unsupported type for unmarshalling.
+//
+// Notes: The size is computed assuming 4-byte granular allocations.
+//
+//--------------------------------------------------------------------
+
+#if defined(WINNT) && !defined(IPROPERTY_DLL)
+
+#ifdef KERNEL
+NTSTATUS
+CBaseStorageVariant::UnmarshalledSize(
+ PDeSerStream& stm,
+ ULONG &cb)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG cElems = 0;
+ ULONG i;
+
+ cb = 0;
+
+ VARTYPE vt = (VARTYPE) stm.GetULong();
+
+ switch (vt)
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ case VT_UI1:
+ case VT_I2:
+ case VT_UI2:
+ case VT_BOOL:
+ case VT_I4:
+ case VT_UI4:
+ case VT_R4:
+ case VT_ERROR:
+ case VT_I8:
+ case VT_UI8:
+ case VT_R8:
+ case VT_CY:
+ case VT_DATE:
+ case VT_FILETIME:
+ break;
+
+ case VT_CLSID:
+ cb = sizeof(GUID);
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ cb = stm.GetULong();
+ break;
+
+ case VT_CF:
+ cb = stm.GetULong() + sizeof(CLIPDATA);
+ break;
+
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ PROPASSERT("Serialization of stream not yet supported!");
+ Status = STATUS_INVALID_PARAMETER; // BUGBUG -- better error code ?
+ break;
+
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ PROPASSERT("Serialization of storage not yet supported!");
+ Status = STATUS_INVALID_PARAMETER; // BUGBUG -- better error code ?
+ break;
+
+ case VT_BSTR:
+ cb = sizeof(ULONG) + stm.GetULong();
+ break;
+
+ case VT_LPSTR:
+ cb = stm.GetULong();
+ break;
+
+ case VT_LPWSTR:
+ cb = stm.GetULong() * sizeof(WCHAR);
+ break;
+
+ case VT_VECTOR | VT_UI1:
+ cb = stm.GetULong();
+ break;
+
+ case VT_VECTOR | VT_I2:
+ case VT_VECTOR | VT_UI2:
+ case VT_VECTOR | VT_BOOL:
+ cb = stm.GetULong() * sizeof(SHORT);
+ break;
+
+ case VT_VECTOR | VT_I4:
+ case VT_VECTOR | VT_UI4:
+ case VT_VECTOR | VT_R4:
+ case VT_VECTOR | VT_ERROR:
+ cb = stm.GetULong() * sizeof(LONG);
+ break;
+
+ case VT_VECTOR | VT_I8:
+ case VT_VECTOR | VT_UI8:
+ case VT_VECTOR | VT_R8:
+ case VT_VECTOR | VT_CY:
+ case VT_VECTOR | VT_DATE:
+ case VT_VECTOR | VT_FILETIME:
+ cb = stm.GetULong() * sizeof(LARGE_INTEGER);
+ break;
+
+ case VT_VECTOR | VT_CLSID:
+ cb = stm.GetULong() * sizeof(GUID);
+ break;
+
+ case VT_VECTOR | VT_CF:
+ cElems = stm.GetULong();
+ cb = cElems * sizeof(CLIPDATA);
+ break;
+
+ case VT_VECTOR | VT_BSTR:
+ cElems = stm.GetULong();
+ cb = cElems * (sizeof(ULONG) + sizeof(LPSTR));
+ break;
+
+ case VT_VECTOR | VT_LPSTR:
+ cElems = stm.GetULong();
+ cb = cElems * sizeof(LPSTR);
+ break;
+
+ case VT_VECTOR | VT_LPWSTR:
+ cElems = stm.GetULong();
+ cb = cElems * sizeof(LPWSTR);
+ break;
+
+ case VT_VECTOR | VT_VARIANT:
+ cElems = stm.GetULong();
+ cb = cElems * sizeof(PROPVARIANT);
+ break;
+
+ default:
+ PROPASSERT(!"Invalid type for PROPVARIANT marshalling");
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ cb = (cb + 3) & ~3;
+
+ if (cElems == 0 || Status != STATUS_SUCCESS)
+ {
+ return(Status);
+ }
+
+ // We have a variant with variable sized data which requires
+ // further unmarshalling.
+ switch(vt)
+ {
+ case VT_VECTOR | VT_CF:
+ for (i = 0; i < cElems; i++)
+ {
+ ULONG len = (stm.GetULong() + 3) & ~3;
+
+ cb += len;
+ stm.SkipChar(sizeof(ULONG) + len);
+ }
+ break;
+
+ case VT_VECTOR | VT_BSTR:
+ case VT_VECTOR | VT_LPSTR:
+ for (i = 0; i < cElems; i++)
+ {
+ ULONG len = (stm.GetULong() + 3) & ~3;
+
+ cb += len;
+ stm.SkipChar(len);
+ }
+ break;
+
+ case VT_VECTOR | VT_LPWSTR:
+ for (i = 0; i < cElems; i++)
+ {
+ ULONG len = (stm.GetULong() * sizeof(WCHAR) + 3) & ~3;
+
+ cb += len;
+ stm.SkipWChar(len / sizeof(WCHAR));
+ }
+ break;
+
+ case VT_VECTOR | VT_VARIANT:
+ for (i = 0; i < cElems; i++)
+ {
+ ULONG cbElem = 0;
+
+ Status = CBaseStorageVariant::UnmarshalledSize(stm, cbElem);
+ if (Status != STATUS_SUCCESS)
+ {
+ break;
+ }
+ cb += cbElem;
+ }
+ break;
+ }
+ return(Status);
+}
+#endif //ifdef KERNEL
+
+
+//+-------------------------------------------------------------------
+// Member: CBaseStorageVariant::Unmarshall, public
+//
+// Synopsis: Unmarshalls a PROPVARIANT value serialized in a PDeSerStream.
+//
+// Arguments: [stm] -- serialized stream
+// [var] -- unmarshalled PROPVARIANT instance
+// [MemAlloc] -- memory allocator for unmarshalling
+//
+// Returns: one of the following NTSTATUS values
+// STATUS_SUCCESS -- the call was successful.
+// STATUS_INSUFFICIENT_RESOURCES -- out of memory.
+// STATUS_INVALID_PARAMETER -- unsupported type for unmarshalling.
+//--------------------------------------------------------------------
+
+NTSTATUS
+CBaseStorageVariant::Unmarshall(
+ PDeSerStream& stm,
+ PROPVARIANT& var,
+ PMemoryAllocator &MemAlloc)
+{
+#if DBG
+ switch (stm.PeekULong())
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ case VT_I1:
+ case VT_I2:
+ case VT_UI2:
+ case VT_BOOL:
+ case VT_I4:
+ case VT_UI4:
+ case VT_R4:
+ case VT_ERROR:
+ case VT_I8:
+ case VT_UI8:
+ case VT_R8:
+ case VT_CY:
+ case VT_DATE:
+ case VT_FILETIME:
+ case VT_CLSID:
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ case VT_CF:
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ case VT_BSTR:
+ case VT_LPSTR:
+ case VT_LPWSTR:
+ case VT_VECTOR | VT_UI1:
+ case VT_VECTOR | VT_I2:
+ case VT_VECTOR | VT_UI2:
+ case VT_VECTOR | VT_BOOL:
+ case VT_VECTOR | VT_I4:
+ case VT_VECTOR | VT_UI4:
+ case VT_VECTOR | VT_R4:
+ case VT_VECTOR | VT_ERROR:
+ case VT_VECTOR | VT_I8:
+ case VT_VECTOR | VT_UI8:
+ case VT_VECTOR | VT_R8:
+ case VT_VECTOR | VT_CY:
+ case VT_VECTOR | VT_DATE:
+ case VT_VECTOR | VT_FILETIME:
+ case VT_VECTOR | VT_CLSID:
+ case VT_VECTOR | VT_CF:
+ case VT_VECTOR | VT_BSTR:
+ case VT_VECTOR | VT_LPSTR:
+ case VT_VECTOR | VT_LPWSTR:
+ case VT_VECTOR | VT_VARIANT:
+ break;
+
+ default:
+ PROPASSERT(!"Invalid type (peek) for PROPVARIANT unmarshalling");
+ break;
+ }
+#endif
+
+ NTSTATUS Status = STATUS_SUCCESS;
+ ULONG cbAlloc = 0;
+ VOID **ppv = NULL;
+ BOOLEAN fZero = FALSE;
+
+ // Zero the entire variant data structure before assembling it together.
+ memset(&var, 0, sizeof(PROPVARIANT));
+
+ var.vt = (VARTYPE) stm.GetULong();
+
+ switch (var.vt)
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ break;
+
+ case VT_UI1:
+ var.bVal = stm.GetByte();
+ break;
+
+ case VT_I2:
+ case VT_UI2:
+ case VT_BOOL:
+ var.iVal = stm.GetUShort();
+ break;
+
+ case VT_I4:
+ case VT_UI4:
+ case VT_R4:
+ case VT_ERROR:
+ var.lVal = stm.GetULong();
+ break;
+
+ case VT_I8:
+ case VT_UI8:
+ case VT_R8:
+ case VT_CY:
+ case VT_DATE:
+ case VT_FILETIME:
+ stm.GetBlob((BYTE *)&var.hVal, sizeof(LARGE_INTEGER));
+ break;
+
+ case VT_CLSID:
+ cbAlloc = sizeof(GUID);
+ ppv = (void **)&var.puuid;
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ var.blob.cbSize = stm.GetULong();
+ cbAlloc = var.blob.cbSize;
+ ppv = (void **)&var.blob.pBlobData;
+ break;
+
+ case VT_CF:
+ var.pclipdata = (CLIPDATA *) MemAlloc.Allocate(sizeof(*var.pclipdata));
+ if (var.pclipdata == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ var.pclipdata->cbSize = stm.GetULong();
+ cbAlloc = CBPCLIPDATA(*var.pclipdata);
+ var.pclipdata->ulClipFmt = stm.GetULong();
+ ppv = (void **) &var.pclipdata->pClipData;
+ break;
+
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ PROPASSERT("Serialization of stream not yet supported!");
+ Status = STATUS_INVALID_PARAMETER; // BUGBUG -- better error code ?
+ break;
+
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ PROPASSERT("Serialization of storage not yet supported!");
+ Status = STATUS_INVALID_PARAMETER; // BUGBUG -- better error code ?
+ break;
+
+ case VT_BSTR:
+ cbAlloc = sizeof(ULONG) + stm.GetULong();
+ ppv = (void **)&var.bstrVal;
+ break;
+
+ case VT_LPSTR:
+ cbAlloc = stm.GetULong();
+ ppv = (void **)&var.pszVal;
+ break;
+
+ case VT_LPWSTR:
+ cbAlloc = stm.GetULong() * sizeof(WCHAR);
+ ppv = (void **)&var.pwszVal;
+ break;
+
+ case VT_VECTOR | VT_UI1:
+ var.caub.cElems = stm.GetULong();
+ cbAlloc = var.caub.cElems * sizeof(BYTE);
+ ppv = (void **)&var.caub.pElems;
+ break;
+
+ case VT_VECTOR | VT_I2:
+ case VT_VECTOR | VT_UI2:
+ case VT_VECTOR | VT_BOOL:
+ var.cai.cElems = stm.GetULong();
+ cbAlloc = var.cai.cElems * sizeof(SHORT);
+ ppv = (void **)&var.cai.pElems;
+ break;
+
+ case VT_VECTOR | VT_I4:
+ case VT_VECTOR | VT_UI4:
+ case VT_VECTOR | VT_R4:
+ case VT_VECTOR | VT_ERROR:
+ var.cal.cElems = stm.GetULong();
+ cbAlloc = var.cal.cElems * sizeof(LONG);
+ ppv = (void **)&var.cal.pElems;
+ break;
+
+ case VT_VECTOR | VT_I8:
+ case VT_VECTOR | VT_UI8:
+ case VT_VECTOR | VT_R8:
+ case VT_VECTOR | VT_CY:
+ case VT_VECTOR | VT_DATE:
+ case VT_VECTOR | VT_FILETIME:
+ var.cah.cElems = stm.GetULong();
+ cbAlloc = var.cah.cElems * sizeof(LARGE_INTEGER);
+ ppv = (void **)&var.cah.pElems;
+ break;
+
+ case VT_VECTOR | VT_CLSID:
+ var.cauuid.cElems = stm.GetULong();
+ cbAlloc = var.cauuid.cElems * sizeof(GUID);
+ ppv = (void **)&var.cauuid.pElems;
+ break;
+
+ case VT_VECTOR | VT_CF:
+ var.caclipdata.cElems = stm.GetULong();
+ cbAlloc = var.caclipdata.cElems * sizeof(CLIPDATA);
+ ppv = (void **)&var.caclipdata.pElems;
+ fZero = TRUE; // set all pClipData pointers to NULL
+ break;
+
+ case VT_VECTOR | VT_BSTR:
+ var.cabstr.cElems = stm.GetULong();
+ cbAlloc = var.cabstr.cElems * sizeof(BSTR);
+ ppv = (void **)&var.cabstr.pElems;
+ fZero = TRUE; // set all BSTR pointers to NULL
+ break;
+
+ case VT_VECTOR | VT_LPSTR:
+ var.calpstr.cElems = stm.GetULong();
+ cbAlloc = var.calpstr.cElems * sizeof(LPSTR);
+ ppv = (void **)&var.calpstr.pElems;
+ fZero = TRUE; // set all LPSTR pointers to NULL
+ break;
+
+ case VT_VECTOR | VT_LPWSTR:
+ var.calpwstr.cElems = stm.GetULong();
+ cbAlloc = var.calpwstr.cElems * sizeof(LPWSTR);
+ ppv = (void **)&var.calpwstr.pElems;
+ fZero = TRUE; // set all LPWSTR pointers to NULL
+ break;
+
+ case VT_VECTOR | VT_VARIANT:
+ var.capropvar.cElems = stm.GetULong();
+ cbAlloc = var.capropvar.cElems * sizeof(PROPVARIANT);
+ ppv = (void **)&var.capropvar.pElems;
+ fZero = TRUE; // set all vt pointers to VT_EMPTY
+ PROPASSERT(VT_EMPTY == 0);
+ break;
+
+ default:
+ PROPASSERT(!"Invalid type for PROPVARIANT unmarshalling");
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ if (cbAlloc == 0 || Status != STATUS_SUCCESS)
+ {
+ // No further work need be done. The Ummarshalling is complete,
+ // i.e., fixed size variant or no variable length data.
+
+ if (ppv != NULL)
+ {
+ *ppv = NULL;
+ }
+ return(Status);
+ }
+
+ // Allocate the desired amount of memory and continue unmarshalling
+ // if allocation was successfull.
+
+ ULONG i;
+
+ PROPASSERT(ppv != NULL);
+ *ppv = MemAlloc.Allocate(cbAlloc);
+
+ if (*ppv == NULL)
+ {
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+ if (fZero)
+ {
+ memset(*ppv, 0, cbAlloc);
+ }
+
+ // We have a variant with variable sized data which requires
+ // further unmarshalling.
+ switch(var.vt)
+ {
+ case VT_CLSID:
+ stm.GetBlob((BYTE *)var.puuid, sizeof(CLSID));
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ stm.GetBlob(var.blob.pBlobData, var.blob.cbSize);
+ break;
+
+ case VT_CF:
+ stm.GetBlob(var.pclipdata->pClipData, CBPCLIPDATA(*var.pclipdata));
+ break;
+
+ case VT_BSTR:
+ cbAlloc -= sizeof(ULONG);
+ *(ULONG *) var.bstrVal = cbAlloc - sizeof (OLECHAR);
+ var.bstrVal = (BSTR) ((ULONG *) var.bstrVal + 1);
+ stm.GetChar((char *) var.bstrVal, cbAlloc);
+ break;
+
+ case VT_LPSTR:
+ stm.GetChar(var.pszVal, cbAlloc);
+ break;
+
+ case VT_LPWSTR:
+ stm.GetWChar(var.pwszVal, cbAlloc / sizeof(WCHAR));
+ break;
+
+ case VT_VECTOR | VT_UI1:
+ for (i = 0; i < var.caub.cElems; i++)
+ {
+ var.caub.pElems[i] = stm.GetByte();
+ }
+ break;
+
+ case VT_VECTOR | VT_I2:
+ case VT_VECTOR | VT_UI2:
+ case VT_VECTOR | VT_BOOL:
+ for (i = 0; i < var.cai.cElems; i++)
+ {
+ var.cai.pElems[i] = stm.GetUShort();
+ }
+ break;
+
+ case VT_VECTOR | VT_I4:
+ case VT_VECTOR | VT_UI4:
+ case VT_VECTOR | VT_R4:
+ case VT_VECTOR | VT_ERROR:
+ for (i = 0; i < var.cal.cElems; i++)
+ {
+ var.cal.pElems[i] = stm.GetULong();
+ }
+ break;
+
+ case VT_VECTOR | VT_I8:
+ case VT_VECTOR | VT_UI8:
+ case VT_VECTOR | VT_R8:
+ case VT_VECTOR | VT_CY:
+ case VT_VECTOR | VT_DATE:
+ case VT_VECTOR | VT_FILETIME:
+ for (i = 0; i < var.cah.cElems; i++)
+ {
+ stm.GetBlob((BYTE *)&var.cah.pElems[i], sizeof(LARGE_INTEGER));
+ }
+ break;
+
+ case VT_VECTOR | VT_CLSID:
+ for (i = 0; i < var.cauuid.cElems; i++)
+ {
+ stm.GetBlob((BYTE *)&var.cauuid.pElems[i], sizeof(CLSID));
+ }
+ break;
+
+ case VT_VECTOR | VT_CF:
+ for (i = 0; i < var.caclipdata.cElems; i++)
+ {
+ PROPASSERT(var.caclipdata.pElems[i].pClipData == NULL);
+ var.caclipdata.pElems[i].cbSize = stm.GetULong();
+ cbAlloc = CBPCLIPDATA(var.caclipdata.pElems[i]);
+ var.caclipdata.pElems[i].ulClipFmt = stm.GetULong();
+ if (cbAlloc == 0)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ var.caclipdata.pElems[i].pClipData =
+ (BYTE *) MemAlloc.Allocate(cbAlloc);
+ if (var.caclipdata.pElems[i].pClipData == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ stm.GetBlob(var.caclipdata.pElems[i].pClipData, cbAlloc);
+ }
+ break;
+
+ case VT_VECTOR | VT_BSTR:
+ for (i = 0; i < var.cabstr.cElems; i++)
+ {
+ PROPASSERT(var.cabstr.pElems[i] == NULL);
+ cbAlloc = stm.GetULong();
+ if (cbAlloc == 0)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ var.cabstr.pElems[i] =
+ (BSTR) MemAlloc.Allocate(sizeof(ULONG) + cbAlloc);
+ if (var.cabstr.pElems[i] == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ *(ULONG *) var.cabstr.pElems[i] = cbAlloc - sizeof (OLECHAR);
+ var.cabstr.pElems[i] = (BSTR) ((ULONG *) var.cabstr.pElems[i] + 1);
+ stm.GetChar((char *) var.cabstr.pElems[i], cbAlloc);
+ }
+ break;
+
+ case VT_VECTOR | VT_LPSTR:
+ for (i = 0; i < var.calpstr.cElems; i++)
+ {
+ PROPASSERT(var.calpstr.pElems[i] == NULL);
+ cbAlloc = stm.GetULong();
+ if (cbAlloc == 0)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ var.calpstr.pElems[i] = (LPSTR) MemAlloc.Allocate(cbAlloc);
+ if (var.calpstr.pElems[i] == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ stm.GetChar(var.calpstr.pElems[i], cbAlloc);
+ }
+ break;
+
+ case VT_VECTOR | VT_LPWSTR:
+ for (i = 0; i < var.calpwstr.cElems; i++)
+ {
+ PROPASSERT(var.calpwstr.pElems[i] == NULL);
+ cbAlloc = stm.GetULong(); // actually, a count of WCHARs
+ if (cbAlloc == 0)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ var.calpwstr.pElems[i] = (WCHAR *) MemAlloc.Allocate(cbAlloc * sizeof(WCHAR));
+ if (var.calpwstr.pElems[i] == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ break;
+ }
+ stm.GetWChar(var.calpwstr.pElems[i], cbAlloc);
+ }
+ break;
+
+ case VT_VECTOR | VT_VARIANT:
+ for (i = 0; i < var.capropvar.cElems; i++)
+ {
+ PROPASSERT(var.capropvar.pElems[i].vt == VT_EMPTY);
+ Status = CBaseStorageVariant::Unmarshall(
+ stm,
+ var.capropvar.pElems[i],
+ MemAlloc);
+ if (Status != STATUS_SUCCESS)
+ {
+ break;
+ }
+ }
+ break;
+ }
+ return(Status);
+}
+
+
+#ifdef ENABLE_MARSHAL_VARIANT
+inline void
+_Marshall_VT_CF(CLIPDATA *pclipdata, PSerStream &stm)
+{
+ CLIPDATA clipdata;
+
+ clipdata.cbSize = 0;
+ clipdata.ulClipFmt = 0;
+
+ if (pclipdata != NULL)
+ {
+ clipdata.cbSize = pclipdata->cbSize;
+ clipdata.ulClipFmt = pclipdata->ulClipFmt;
+ if (pclipdata->pClipData == NULL)
+ {
+ clipdata.cbSize = 0;
+ }
+ }
+ stm.PutULong(clipdata.cbSize);
+ stm.PutULong(clipdata.ulClipFmt);
+ if (clipdata.cbSize)
+ {
+ stm.PutBlob((BYTE *) pclipdata->pClipData, CBPCLIPDATA(clipdata));
+ }
+}
+#endif //ifdef ENABLE_MARSHAL_VARIANT
+
+
+#ifdef ENABLE_MARSHAL_VARIANT
+inline void
+_Marshall_VT_BSTR(BSTR bstrVal, PSerStream &stm)
+{
+ if (bstrVal != NULL)
+ {
+ ULONG cc = BSTRLEN(bstrVal) + sizeof (OLECHAR);
+
+ stm.PutULong(cc);
+ stm.PutChar((char *) bstrVal, cc);
+ }
+ else
+ {
+ stm.PutULong(0);
+ }
+}
+#endif //ifdef ENABLE_MARSHAL_VARIANT
+
+
+#ifdef ENABLE_MARSHAL_VARIANT
+inline void
+_Marshall_VT_LPSTR(CHAR *pszVal, PSerStream &stm)
+{
+ if (pszVal != NULL)
+ {
+ // Include NULL because OLE 2.0 spec says so.
+ ULONG cc = strlen(pszVal) + 1;
+
+ stm.PutULong(cc);
+ stm.PutChar(pszVal, cc);
+ PROPASSERT(IsAnsiString(pszVal, cc));
+ }
+ else
+ {
+ stm.PutULong(0);
+ }
+}
+#endif //ifdef ENABLE_MARSHAL_VARIANT
+
+
+#ifdef ENABLE_MARSHAL_VARIANT
+inline void
+_Marshall_VT_LPWSTR(LPWSTR pwszVal, PSerStream &stm)
+{
+ if (pwszVal != NULL)
+ {
+ // Include NULL because OLE 2.0 spec says so.
+
+ ULONG cc = Prop_wcslen(pwszVal) + 1;
+
+ PROPASSERT(IsUnicodeString(pwszVal, cc * sizeof(WCHAR)));
+ stm.PutULong(cc);
+ stm.PutWChar(pwszVal, cc);
+ }
+ else
+ {
+ stm.PutULong(0);
+ }
+}
+#endif //ifdef ENABLE_MARSHAL_VARIANT
+
+
+#ifdef ENABLE_MARSHAL_VARIANT
+void
+CBaseStorageVariant::Marshall(PSerStream & stm) const
+{
+ ULONG i;
+
+ stm.PutULong(vt);
+
+ switch (vt)
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ break;
+
+ case VT_UI1:
+ stm.PutByte(bVal);
+ break;
+
+ case VT_I2:
+ case VT_UI2:
+ case VT_BOOL:
+ stm.PutUShort(iVal);
+ break;
+
+ case VT_I4:
+ case VT_UI4:
+ case VT_R4:
+ case VT_ERROR:
+ stm.PutULong(lVal);
+ break;
+
+ case VT_I8:
+ case VT_UI8:
+ case VT_R8:
+ case VT_CY:
+ case VT_DATE:
+ case VT_FILETIME:
+ stm.PutBlob((BYTE *) &hVal, sizeof(hVal));
+ break;
+
+ case VT_CLSID:
+ stm.PutBlob((BYTE *)puuid, sizeof(CLSID));
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ stm.PutULong(blob.cbSize);
+ stm.PutBlob(blob.pBlobData, blob.cbSize);
+ break;
+
+ case VT_CF:
+ _Marshall_VT_CF(pclipdata, stm);
+ break;
+
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ PROPASSERT("Serialization of stream not yet supported!");
+ break;
+
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ PROPASSERT("Serialization of storage not yet supported!");
+ break;
+
+ case VT_BSTR:
+ _Marshall_VT_BSTR(bstrVal, stm);
+ break;
+
+ case VT_LPSTR:
+ _Marshall_VT_LPSTR(pszVal, stm);
+ break;
+
+ case VT_LPWSTR:
+ _Marshall_VT_LPWSTR(pwszVal, stm);
+ break;
+
+ case VT_VECTOR | VT_UI1:
+ stm.PutULong(caub.cElems);
+ for (i = 0; i < caub.cElems; i++)
+ {
+ stm.PutByte(caub.pElems[i]);
+ }
+ break;
+
+ case VT_VECTOR | VT_I2:
+ case VT_VECTOR | VT_UI2:
+ case VT_VECTOR | VT_BOOL:
+ stm.PutULong(cai.cElems);
+ for (i = 0; i < cai.cElems; i++)
+ {
+ stm.PutUShort(cai.pElems[i]);
+ }
+ break;
+
+ case VT_VECTOR | VT_I4:
+ case VT_VECTOR | VT_UI4:
+ case VT_VECTOR | VT_R4:
+ case VT_VECTOR | VT_ERROR:
+ stm.PutULong(cal.cElems);
+ for (i = 0; i < cal.cElems; i++)
+ {
+ stm.PutULong(cal.pElems[i]);
+ }
+ break;
+
+ case VT_VECTOR | VT_I8:
+ case VT_VECTOR | VT_UI8:
+ case VT_VECTOR | VT_R8:
+ case VT_VECTOR | VT_CY:
+ case VT_VECTOR | VT_DATE:
+ case VT_VECTOR | VT_FILETIME:
+ stm.PutULong(cah.cElems);
+ for (i = 0; i < cah.cElems; i++)
+ {
+ stm.PutBlob((BYTE *) &cah.pElems[i], sizeof(LARGE_INTEGER));
+ }
+ break;
+
+ case VT_VECTOR | VT_CLSID:
+ stm.PutULong(cauuid.cElems);
+ for (i = 0; i < cauuid.cElems; i++)
+ {
+ stm.PutBlob((BYTE *)&cauuid.pElems[i], sizeof(CLSID));
+ }
+ break;
+
+ case VT_VECTOR | VT_CF:
+ stm.PutULong(caclipdata.cElems);
+ for (i = 0; i < caclipdata.cElems; i++)
+ {
+ _Marshall_VT_CF(&caclipdata.pElems[i], stm);
+ }
+ break;
+ break;
+
+ case VT_VECTOR | VT_BSTR:
+ stm.PutULong(cabstr.cElems);
+ for (i = 0; i < cabstr.cElems; i++)
+ {
+ _Marshall_VT_BSTR(cabstr.pElems[i], stm);
+ }
+ break;
+
+ case VT_VECTOR | VT_LPSTR:
+ stm.PutULong(calpstr.cElems);
+ for (i = 0; i < calpstr.cElems; i++)
+ {
+ _Marshall_VT_LPSTR(calpstr.pElems[i], stm);
+ }
+ break;
+
+ case VT_VECTOR | VT_LPWSTR:
+ stm.PutULong(calpwstr.cElems);
+ for (i = 0; i < calpwstr.cElems; i++)
+ {
+ _Marshall_VT_LPWSTR(calpwstr.pElems[i], stm);
+ }
+ break;
+
+ case VT_VECTOR | VT_VARIANT:
+ stm.PutULong(capropvar.cElems);
+ for (i = 0; i < capropvar.cElems; i++)
+ {
+ ((CBaseStorageVariant *) &capropvar.pElems[i])->Marshall(stm);
+ }
+ break;
+
+ default:
+ PROPASSERT(!"Invalid type for PROPVARIANT marshalling");
+ break;
+
+ }
+}
+#endif //ifdef ENABLE_MARSHAL_VARIANT
+
+
+#ifdef OLDSUMCATAPI
+void
+MarshallVariant(PSerStream &stm, PROPVARIANT &stgvar)
+{
+ CBaseStorageVariant *pstgvar = (CBaseStorageVariant *)&stgvar;
+ pstgvar->Marshall(stm);
+}
+#endif //ifdef OLDSUMCATAPI
+
+
+#ifdef ENABLE_DISPLAY_VARIANT
+VOID
+CBaseStorageVariant::DisplayVariant(
+ ULONG ulLevel,
+ USHORT CodePage) const
+{
+ char *psz;
+
+ switch (vt)
+ {
+ case VT_ILLEGAL: psz = "ILLEGAL"; goto EmptyType;
+ case VT_EMPTY: psz = "EMPTY"; goto EmptyType;
+ case VT_NULL: psz = "NULL"; goto EmptyType;
+
+BlobType:
+EmptyType:
+ DEBTRACE((DBGFLAG "%s", psz));
+ break;
+
+ case VT_UI1:
+ AssertByteField(bVal); // VT_UI1
+ DEBTRACE((DBGFLAG "UI1=%hx", bVal));
+ break;
+
+ case VT_I2: psz = "I2"; goto ShortType;
+ case VT_UI2: psz = "UI2"; goto ShortType;
+
+ShortType:
+ AssertShortField(iVal); // VT_I2
+ AssertShortField(uiVal); // VT_UI2
+ DEBTRACE((DBGFLAG "%s=%hx", psz, iVal));
+ break;
+
+ case VT_BOOL:
+ switch (boolVal)
+ {
+ case VARIANT_TRUE:
+ DEBTRACE((DBGFLAG "BOOL=TRUE"));
+ break;
+
+ case FALSE:
+ DEBTRACE((DBGFLAG "BOOL=FALSE"));
+ break;
+
+ default:
+ DEBTRACE((DBGFLAG "BOOL=%hx???", boolVal));
+ break;
+ }
+ break;
+
+ case VT_I4: psz = "I4"; goto LongType;
+ case VT_UI4: psz = "UI4"; goto LongType;
+ case VT_R4: psz = "R4"; goto LongType;
+ case VT_ERROR: psz = "ERROR"; goto LongType;
+
+LongType:
+ AssertLongField(lVal); // VT_I4
+ AssertLongField(ulVal); // VT_UI4
+ AssertLongField(fltVal); // VT_R4
+ AssertLongField(scode); // VT_ERROR
+ DEBTRACE((DBGFLAG "%s=%x", psz, lVal));
+ break;
+
+ case VT_I8: psz = "I8"; goto LongLongType;
+ case VT_UI8: psz = "UI8"; goto LongLongType;
+ case VT_R8: psz = "R8"; goto LongLongType;
+ case VT_CY: psz = "CY"; goto LongLongType;
+ case VT_DATE: psz = "DATE"; goto LongLongType;
+ case VT_FILETIME: psz = "FILETIME"; goto LongLongType;
+
+LongLongType:
+ AssertLongLongField(hVal); // VT_I8
+ AssertLongLongField(uhVal); // VT_UI8
+ AssertLongLongField(dblVal); // VT_R8
+ AssertLongLongField(cyVal); // VT_CY
+ AssertLongLongField(date); // VT_DATE
+ AssertLongLongField(filetime); // VT_FILETIME
+ DEBTRACE((DBGFLAG "%s=%x:%x", psz, hVal.HighPart, hVal.LowPart));
+ break;
+
+ case VT_CLSID: psz = "CLSID"; goto EmptyType;
+
+ case VT_BLOB: psz = "BLOB"; goto BlobType;
+ case VT_BLOB_OBJECT: psz = "BLOB_OBJECT"; goto BlobType;
+ case VT_CF: psz = "CF"; goto BlobType;
+
+ case VT_STREAM: psz = "STREAM"; goto TestUnicode;
+ case VT_STREAMED_OBJECT: psz = "STREAMED_OBJECT"; goto TestUnicode;
+ case VT_STORAGE: psz = "STORAGE"; goto TestUnicode;
+ case VT_STORED_OBJECT: psz = "STORED_OBJECT"; goto TestUnicode;
+ case VT_LPSTR: psz = "LPSTR"; goto TestUnicode;
+
+TestUnicode:
+ AssertStringField(pszVal); // VT_STREAM, VT_STREAMED_OBJECT
+ AssertStringField(pszVal); // VT_STORAGE, VT_STORED_OBJECT
+ AssertStringField(pszVal); // VT_LPSTR
+ DEBTRACE((
+ DBGFLAG
+ CodePage == CP_WINUNICODE? "%s=L'%ws'" : "%s='%s'",
+ psz,
+ pszVal));
+ break;
+
+ case VT_BSTR: psz = "BSTR"; goto PrintUnicode;
+ case VT_LPWSTR: psz = "LPWSTR"; goto PrintUnicode;
+
+PrintUnicode:
+ AssertStringField(pwszVal); // VT_LPWSTR
+ AssertStringField(bstrVal); // VT_BSTR
+ DEBTRACE((DBGFLAG "%s=L'%ws'", psz, pwszVal));
+ break;
+
+ default:
+ if (vt & VT_VECTOR)
+ {
+ DEBTRACE((DBGFLAG "UNPRINTABLE VECTOR TYPE=%x(%u)", vt, vt));
+ }
+ else
+ {
+ DEBTRACE((DBGFLAG "UNKNOWN TYPE=%x(%u)", vt, vt));
+ }
+ break;
+
+ }
+}
+#endif //ifdef ENABLE_DISPLAY_VARIANT
+
+#endif //ifdef WINNT
diff --git a/private/ole32/stg/props/utest/chresult.hxx b/private/ole32/stg/props/utest/chresult.hxx
new file mode 100644
index 000000000..70241fa12
--- /dev/null
+++ b/private/ole32/stg/props/utest/chresult.hxx
@@ -0,0 +1,118 @@
+
+#ifndef _CHRESULT_HXX_
+#define _CHRESULT_HXX_
+
+class CHResult
+{
+public:
+
+ ~CHResult()
+ {
+ Initialize();
+ }
+
+ CHResult()
+ {
+ _hr = (HRESULT) E_FAIL;
+ _bstrMessage = NULL;
+ _pszFile = NULL;
+ _ulLine = (ULONG) 0;
+ }
+
+ CHResult( CHResult &chr )
+ {
+ _hr = chr._hr;
+ _ulLine = chr._ulLine;
+
+ _bstrMessage = SysAllocString( chr._bstrMessage );
+ _pszFile = new CHAR[ strlen(chr._pszFile) + sizeof(CHAR) ];
+ if( NULL != _pszFile )
+ memcpy( _pszFile, chr._pszFile, strlen(chr._pszFile) + sizeof(CHAR) );
+ }
+
+ CHResult( HRESULT hr, const LPOLESTR pwszMessage, const LPSTR pszFile, ULONG ulLine )
+ {
+ _hr = hr;
+
+ _bstrMessage = SysAllocString( pwszMessage );
+
+ _pszFile = new CHAR[strlen(pszFile) + sizeof(CHAR)];
+ if( NULL != _pszFile )
+ memcpy( _pszFile, pszFile, strlen(pszFile) + sizeof(CHAR) );
+
+ _ulLine = ulLine;
+ }
+
+ CHResult( HRESULT hr, LPOLESTR pwszMessage )
+ {
+ this->CHResult::CHResult( hr, pwszMessage, NULL, 0 );
+ }
+
+
+public:
+
+ operator HRESULT()
+ {
+ return( _hr );
+ }
+
+ operator LPOLESTR()
+ {
+ return( _bstrMessage );
+ }
+
+ HRESULT operator =(HRESULT hr)
+ {
+ _hr = hr;
+
+ SysFreeString( _bstrMessage );
+ _bstrMessage = NULL;
+
+ return(_hr);
+ }
+
+public:
+
+ HRESULT GetLastError()
+ {
+ Initialize();
+ _hr = HRESULT_FROM_WIN32(::GetLastError());
+ return( _hr );
+ }
+
+ LPSTR GetFile()
+ {
+ return( _pszFile );
+ }
+
+ ULONG GetLine()
+ {
+ return( _ulLine );
+ }
+
+private:
+
+ void Initialize()
+ {
+ _hr = (HRESULT) E_FAIL;
+ _ulLine = 0;
+
+ SysFreeString( _bstrMessage );
+ _bstrMessage = NULL;
+
+ CoTaskMemFree( _pszFile );
+ _pszFile = NULL;
+ }
+
+private:
+
+ HRESULT _hr;
+ BSTR _bstrMessage;
+ LPSTR _pszFile;
+ ULONG _ulLine;
+};
+
+
+#define CHRESULT(hr,pwszMessage) CHResult( hr, pwszMessage, __FILE__, __LINE__ )
+
+#endif
diff --git a/private/ole32/stg/props/utest/cpropvar.cxx b/private/ole32/stg/props/utest/cpropvar.cxx
new file mode 100644
index 000000000..cb395b785
--- /dev/null
+++ b/private/ole32/stg/props/utest/cpropvar.cxx
@@ -0,0 +1,573 @@
+
+#include "pch.cxx"
+
+#include "CPropVar.hxx"
+#include "CHResult.hxx"
+#include <stdio.h>
+#include <tchar.h>
+
+
+// Declare this prototype here, for now. For non-Mac, the prototype
+// in "iofs.h" uses C decorations, but the definition in
+// ntpropb.cxx uses C++.
+
+#ifdef _MAC_NODOC
+EXTERN_C BOOLEAN
+#else
+BOOLEAN __declspec(dllimport) __stdcall
+#endif
+RtlCompareVariants(
+ USHORT CodePage,
+ PROPVARIANT const *pvar1,
+ PROPVARIANT const *pvar2);
+
+
+DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(LPSTR, LPSTR);
+DEFINE_CPROPVARIANT_CONVERSION_OPERATOR(LPSTR, calpstr, pszVal );
+
+DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(LPWSTR, LPWSTR);
+DEFINE_CPROPVARIANT_CONVERSION_OPERATOR(LPWSTR, calpwstr, pwszVal );
+
+DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CF, CLIPDATA&);
+DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CF, CClipData&);
+
+DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CLSID, CLSID);
+
+
+
+CPropVariant::CPropVariant(
+ VARENUM v,
+ ULONG cElements)
+{
+ ULONG cbElement;
+ BOOLEAN fZero = FALSE;
+
+ // Ignore vector flag. This constructor is always for vectors only.
+
+ vt = v | VT_VECTOR;
+
+ switch (vt)
+ {
+ case VT_VECTOR | VT_UI1:
+ cbElement = sizeof(caub.pElems[0]);
+ break;
+
+ case VT_VECTOR | VT_I2:
+ case VT_VECTOR | VT_UI2:
+ case VT_VECTOR | VT_BOOL:
+ cbElement = sizeof(cai.pElems[0]);
+ break;
+
+ case VT_VECTOR | VT_I4:
+ case VT_VECTOR | VT_UI4:
+ case VT_VECTOR | VT_R4:
+ case VT_VECTOR | VT_ERROR:
+ cbElement = sizeof(cal.pElems[0]);
+ break;
+
+ case VT_VECTOR | VT_I8:
+ case VT_VECTOR | VT_UI8:
+ case VT_VECTOR | VT_R8:
+ case VT_VECTOR | VT_CY:
+ case VT_VECTOR | VT_DATE:
+ case VT_VECTOR | VT_FILETIME:
+ cbElement = sizeof(cah.pElems[0]);
+ break;
+
+ case VT_VECTOR | VT_CLSID:
+ cbElement = sizeof(GUID);
+ fZero = TRUE;
+ break;
+
+ case VT_VECTOR | VT_CF:
+ cbElement = sizeof(CLIPDATA);
+ fZero = TRUE;
+ break;
+
+ case VT_VECTOR | VT_BSTR:
+ case VT_VECTOR | VT_LPSTR:
+ case VT_VECTOR | VT_LPWSTR:
+ cbElement = sizeof(VOID *);
+ fZero = TRUE;
+ break;
+
+ case VT_VECTOR | VT_VARIANT:
+ cbElement = sizeof(PROPVARIANT);
+ ASSERT(VT_EMPTY == 0);
+ fZero = TRUE;
+ break;
+
+ default:
+ ASSERT(!"CAllocStorageVariant -- Invalid vector type");
+ vt = VT_EMPTY;
+ break;
+ }
+ if (vt != VT_EMPTY)
+ {
+ caub.cElems = 0;
+ caub.pElems = (BYTE *) CoTaskMemAlloc(cElements * cbElement);
+ if (caub.pElems != NULL)
+ {
+ if (fZero)
+ {
+ memset(caub.pElems, 0, cElements * cbElement);
+ }
+ caub.cElems = cElements;
+ }
+ }
+}
+
+
+VOID *
+CPropVariant::_AddStringToVector(
+ unsigned pos,
+ VOID *pv,
+ ULONG cb)
+{
+ ASSERT(vt == (VT_VECTOR | VT_BSTR) ||
+ vt == (VT_VECTOR | VT_LPSTR) ||
+ vt == (VT_VECTOR | VT_LPWSTR) ||
+ vt == (VT_VECTOR | VT_CF) );
+ ASSERT(calpstr.pElems != NULL);
+
+ if (pos >= calpstr.cElems)
+ {
+ char **ppsz = calpstr.pElems;
+
+ calpstr.pElems =
+ (char **) CoTaskMemAlloc((pos + 1) * sizeof(calpstr.pElems[0]));
+ if (calpstr.pElems == NULL)
+ {
+ calpstr.pElems = ppsz;
+ return(NULL);
+ }
+ memcpy(calpstr.pElems, ppsz, calpstr.cElems * sizeof(calpstr.pElems[0]));
+ memset(
+ &calpstr.pElems[calpstr.cElems],
+ 0,
+ ((pos + 1) - calpstr.cElems) * sizeof(calpstr.pElems[0]));
+ calpstr.cElems = pos + 1;
+ CoTaskMemFree(ppsz);
+ }
+
+ LPSTR psz;
+
+ if( (VT_VECTOR | VT_BSTR) == vt )
+ {
+ if( NULL == pv )
+ {
+ psz = NULL;
+ }
+ else
+ {
+ psz = (LPSTR) SysAllocString( (BSTR) pv );
+ if (psz == NULL)
+ {
+ return(NULL);
+ }
+ }
+
+ if (calpstr.pElems[pos] != NULL)
+ {
+ SysFreeString((BSTR) calpstr.pElems[pos]);
+ }
+ calpstr.pElems[pos] = psz;
+ }
+ else
+ {
+ if( NULL == pv )
+ {
+ psz = NULL;
+ }
+ else
+ {
+ psz = (LPSTR) CoTaskMemAlloc((VT_BSTR == (vt & ~VT_VECTOR) )
+ ? cb + sizeof(ULONG)
+ : cb );
+ if (psz == NULL)
+ {
+ return(NULL);
+ }
+
+ memcpy(psz, pv, cb);
+ }
+
+ if (calpstr.pElems[pos] != NULL)
+ {
+ CoTaskMemFree(calpstr.pElems[pos]);
+ }
+ calpstr.pElems[pos] = psz;
+ }
+
+
+ return(calpstr.pElems[pos]);
+}
+
+
+VOID *
+CPropVariant::_AddScalerToVector(
+ unsigned pos,
+ VOID *pv,
+ ULONG cb)
+{
+ ASSERT(calpstr.pElems != NULL);
+
+ if (pos >= calpstr.cElems)
+ {
+ char **ppsz = calpstr.pElems;
+
+ calpstr.pElems =
+ (char **) CoTaskMemAlloc((pos + 1) * cb);
+ if (calpstr.pElems == NULL)
+ {
+ calpstr.pElems = ppsz;
+ return(NULL);
+ }
+ memset(
+ calpstr.pElems,
+ 0,
+ ((pos + 1) - calpstr.cElems) * cb);
+ memcpy(calpstr.pElems, ppsz, calpstr.cElems * cb);
+ calpstr.cElems = pos + 1;
+ CoTaskMemFree(ppsz);
+ }
+
+
+ memcpy( (BYTE*)calpstr.pElems + pos*cb, pv, cb );
+ return( (BYTE*)calpstr.pElems + pos*cb );
+
+}
+void
+CPropVariant::SetLPSTR(
+ char const *psz,
+ unsigned pos)
+{
+ ULONG cch;
+
+ if( NULL == psz )
+ cch = 0;
+ else
+ cch = strlen(psz) + 1;
+
+ if (vt != (VT_VECTOR | VT_LPSTR))
+ {
+ PropVariantClear( this );
+ new (this) CPropVariant(VT_LPSTR, pos);
+ }
+ _AddStringToVector(pos, (VOID *) psz, cch);
+}
+
+
+void
+CPropVariant::SetLPWSTR(
+ WCHAR const *pwsz,
+ unsigned pos)
+{
+ if (vt != (VT_VECTOR | VT_LPWSTR))
+ {
+ PropVariantClear( this );
+ new (this) CPropVariant(VT_LPWSTR, pos);
+ }
+ _AddStringToVector(pos, (VOID *) pwsz,
+ sizeof(WCHAR) * (wcslen(pwsz) + 1) );
+}
+
+
+void
+CPropVariant::SetCF(
+ const CLIPDATA *pclipdata,
+ unsigned pos)
+{
+ CLIPDATA *pclipdataNew;
+
+ if (vt != (VT_VECTOR | VT_CF))
+ {
+ PropVariantClear( this );
+ new (this) CPropVariant(VT_CF, pos);
+ }
+
+ pclipdataNew = (CLIPDATA*) _AddScalerToVector(pos, (VOID *) pclipdata, sizeof(CLIPDATA) );
+
+ if( NULL != pclipdataNew
+ &&
+ NULL != pclipdata )
+ {
+ pclipdataNew->pClipData = (BYTE*) CoTaskMemAlloc( CBPCLIPDATA(*pclipdata) );
+ if( NULL == pclipdataNew->pClipData )
+ {
+ ASSERT( !"Couldn't allocate pclipdataNew" );
+ return;
+ }
+ else
+ {
+ pclipdataNew->cbSize = pclipdata->cbSize;
+ pclipdataNew->ulClipFmt = pclipdata->ulClipFmt;
+
+ memcpy( pclipdataNew->pClipData,
+ pclipdata->pClipData,
+ CBPCLIPDATA(*pclipdata) );
+ return;
+ }
+ }
+}
+
+
+void
+CPropVariant::SetBSTR(
+ const BSTR posz,
+ unsigned pos)
+{
+ ULONG cch;
+
+ if( NULL == posz )
+ cch = 0;
+ else
+ cch = ocslen(posz) + 1;
+
+ if (vt != (VT_VECTOR | VT_BSTR))
+ {
+ PropVariantClear( this );
+ new (this) CPropVariant(VT_BSTR, pos+1);
+ }
+ _AddStringToVector(pos, (VOID *) posz,
+ sizeof(OLECHAR) * cch );
+}
+
+
+BSTR
+CPropVariant::GetBSTR( int nSubscript )
+{
+ ASSERT( vt & VT_VECTOR );
+ ASSERT( vt == (VT_BSTR | VT_VECTOR) );
+ ASSERT( wReserved1 > 0 );
+
+ if( wReserved1 > 0
+ &&
+ cabstr.cElems > 0
+ &&
+ wReserved1 <= cabstr.cElems )
+ {
+ int nSubscript = wReserved1 - 1;
+ wReserved1 = INVALID_SUBSCRIPT;
+ return( cabstr.pElems[ nSubscript ] );
+ }
+ else
+ return( NULL );
+}
+
+
+
+
+CPropVariant & CPropVariant::operator =(LPPROPVARIANT lppropvar)
+{
+ if( INVALID_SUBSCRIPT == wReserved1 )
+ {
+ ASSERT( INVALID_SUBSCRIPT != wReserved1 );
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant();
+ return (*this);
+ }
+ else
+ {
+ if( !(vt & VT_VECTOR)
+ ||
+ (vt & ~VT_VECTOR) != VT_VARIANT )
+ {
+ USHORT wReserved1Save = wReserved1;
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant( VT_VARIANT,
+ wReserved1Save );
+ wReserved1 = wReserved1Save;
+ }
+
+ SetLPPROPVARIANT( lppropvar, wReserved1 - 1 );
+ wReserved1 = INVALID_SUBSCRIPT;
+ return (*this);
+ }
+}
+
+
+CPropVariant::operator LPPROPVARIANT()
+{
+ if( vt & VT_VECTOR )
+ {
+ if( wReserved1 > 0
+ &&
+ capropvar.cElems > 0
+ &&
+ wReserved1 <= capropvar.cElems )
+ {
+ int nSubscript = wReserved1 - 1;
+ wReserved1 = INVALID_SUBSCRIPT;
+ return( &capropvar.pElems[ nSubscript ] );
+ }
+ else
+ {
+ ASSERT( INVALID_SUBSCRIPT == wReserved1 );
+ return( (LPPROPVARIANT) this );
+ }
+ }
+ else
+ return( (LPPROPVARIANT) this );
+}
+
+
+void
+CPropVariant::SetLPPROPVARIANT( LPPROPVARIANT lppropvar, unsigned pos )
+{
+ if (vt != (VT_VECTOR | VT_VARIANT))
+ {
+ PropVariantClear( this );
+ new (this) CPropVariant(VT_VARIANT, pos + 1);
+ }
+
+ if (pos >= capropvar.cElems)
+ {
+ LPPROPVARIANT rgpropvar = capropvar.pElems;
+
+ capropvar.pElems =
+ (PROPVARIANT *) CoTaskMemAlloc((pos + 1) * sizeof(capropvar.pElems[0]));
+ if (capropvar.pElems == NULL)
+ {
+ capropvar.pElems = rgpropvar;
+ return;
+ }
+ memcpy(capropvar.pElems, rgpropvar, capropvar.cElems * sizeof(capropvar.pElems[0]));
+ memset(
+ &capropvar.pElems[capropvar.cElems],
+ 0,
+ ((pos + 1) - capropvar.cElems) * sizeof(capropvar.pElems[0]));
+ capropvar.cElems = pos + 1;
+ CoTaskMemFree(rgpropvar);
+ }
+
+ PropVariantClear( &capropvar.pElems[pos] );
+ PropVariantCopy( &capropvar.pElems[pos], lppropvar );
+
+ return;
+
+}
+
+
+
+CPropVariant::CPropVariant(const CLIPDATA *p)
+{
+ this->CPropVariant::CPropVariant();
+
+ if( NULL == p )
+ return;
+
+ pclipdata = (CLIPDATA*) CoTaskMemAlloc( sizeof(CLIPDATA) );
+ if( NULL == pclipdata )
+ {
+ return;
+ }
+
+ pclipdata->cbSize = p->cbSize;
+ pclipdata->ulClipFmt = p->ulClipFmt;
+ pclipdata->pClipData = NULL;
+
+ if( sizeof(pclipdata->ulClipFmt) > p->cbSize )
+ {
+ this->CPropVariant::CPropVariant();
+ return;
+ }
+
+
+ if( NULL != p->pClipData )
+ {
+ pclipdata->pClipData = (BYTE*) CoTaskMemAlloc( pclipdata->cbSize
+ - sizeof(pclipdata->ulClipFmt) );
+ if( NULL == pclipdata->pClipData )
+ return;
+
+ memcpy( pclipdata->pClipData, p->pClipData, pclipdata->cbSize - sizeof(pclipdata->ulClipFmt) );
+ }
+
+ vt = VT_CF;
+
+}
+
+void
+CPropVariant::SetCLSID( const CLSID &clsid )
+{
+ PropVariantClear( this );
+
+ puuid = (CLSID*) CoTaskMemAlloc( sizeof(CLSID) );
+ if( NULL == puuid )
+ throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("CPropVariant::SetCLSID couldn't alloc a new CLSID") );
+
+ *puuid = clsid;
+ vt = VT_CLSID;
+}
+
+
+void
+CPropVariant::SetCLSID(
+ const CLSID &clsid,
+ unsigned pos)
+{
+ CLSID *pclsidNew;
+
+ if (vt != (VT_VECTOR | VT_CLSID))
+ {
+ PropVariantClear( this );
+ new (this) CPropVariant(VT_CLSID, pos);
+ }
+
+ pclsidNew = (CLSID*) _AddScalerToVector(pos, (VOID *) &clsid, sizeof(CLSID) );
+
+ if( NULL != pclsidNew )
+ {
+ *pclsidNew = clsid;
+ }
+}
+
+
+HRESULT
+CPropVariant::Compare( PROPVARIANT *ppropvar1, PROPVARIANT *ppropvar2 )
+{
+ VARTYPE vt1 = ppropvar1->vt;
+
+ if( VT_STREAM == vt1
+ ||
+ VT_STREAMED_OBJECT == vt1
+ ||
+ VT_STORAGE == vt1
+ ||
+ VT_STORED_OBJECT == vt1
+ )
+ {
+ if( ppropvar1->vt == ppropvar2->vt
+ &&
+ ( NULL == ppropvar1->vt
+ &&
+ NULL == ppropvar2->vt
+ ||
+ NULL != ppropvar1->vt
+ &&
+ NULL != ppropvar2->vt
+ )
+ )
+ {
+ return( (HRESULT) S_OK );
+ }
+ else
+ {
+ return( (HRESULT) S_FALSE );
+ }
+ }
+
+ else if( RtlCompareVariants( CP_ACP, // Ignored,
+ ppropvar1,
+ ppropvar2 ))
+ {
+ return( (HRESULT) S_OK );
+ }
+ else
+ {
+ return( (HRESULT) S_FALSE );
+ }
+}
+
+
diff --git a/private/ole32/stg/props/utest/cpropvar.hxx b/private/ole32/stg/props/utest/cpropvar.hxx
new file mode 100644
index 000000000..c70f6eab0
--- /dev/null
+++ b/private/ole32/stg/props/utest/cpropvar.hxx
@@ -0,0 +1,811 @@
+
+#ifndef _CPROPVAR_HXX_
+#define _CPROPVAR_HXX_
+
+#ifndef _MAC
+#include <wtypes.h>
+#include <objidl.h>
+#include <oaidl.h>
+#endif
+
+#include "CHResult.hxx"
+#include <olechar.h>
+
+
+#ifndef ASSERT
+ #if DBG==1
+ #ifdef _MAC
+ #define ASSERT(assertion) PROPASSERT(assertion)
+ #else
+ #include "debnot.h"
+ #define ASSERT(assertion) {if(!(assertion)) Win4AssertEx(__FILE__, __LINE__, (#assertion));}
+ #endif
+ #else
+ #define ASSERT(assertion)
+ #endif
+#endif
+
+class CClipData;
+class CBlob;
+
+#define INVALID_SUBSCRIPT 0
+
+#define DECLARE_CPROPVARIANT_ASSIGNMENT_OPERATOR(Type) \
+ CPropVariant & operator =( Type);
+
+#define DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(VT, Type ) \
+ \
+ CPropVariant & CPropVariant::operator =( Type pType) \
+ { \
+ if( INVALID_SUBSCRIPT == wReserved1 ) \
+ { \
+ PropVariantClear(this); \
+ this->CPropVariant::CPropVariant(pType); \
+ return (*this); \
+ } \
+ else \
+ { \
+ if( !(vt & VT_VECTOR) \
+ || \
+ (vt & ~VT_VECTOR) != VT_##VT ) \
+ { \
+ WORD wReserved1Save = wReserved1; \
+ PropVariantClear(this); \
+ this->CPropVariant::CPropVariant( VT_##VT, \
+ wReserved1Save ); \
+ wReserved1 = wReserved1Save; \
+ } \
+ \
+ Set##VT( pType, wReserved1 - 1); \
+ wReserved1 = 0; \
+ return (*this); \
+ } \
+ }
+
+#define DECLARE_CPROPVARIANT_CONVERSION_OPERATOR(VarType) \
+ operator VarType();
+
+#define DEFINE_CPROPVARIANT_CONVERSION_OPERATOR(VarType, CAName, SingletonName) \
+ CPropVariant::operator VarType() \
+ { \
+ if( vt & VT_VECTOR ) \
+ { \
+ ASSERT( vt == (VT_##VarType | VT_VECTOR) \
+ || \
+ vt == (VT_VARIANT | VT_VECTOR) ); \
+ ASSERT( wReserved1 > 0 ); \
+ \
+ if( wReserved1 > 0 \
+ && \
+ ##CAName.cElems > 0 \
+ && \
+ wReserved1 <= (##CAName.cElems) ) \
+ { \
+ USHORT usSubscript = wReserved1 - 1; \
+ wReserved1 = 0; \
+ if( (vt & ~VT_VECTOR) == VT_VARIANT ) \
+ return( capropvar.pElems[ usSubscript ].##SingletonName );\
+ else \
+ return( ##CAName.pElems[ usSubscript ] ); \
+ } \
+ else \
+ return( NULL ); \
+ } \
+ else \
+ { \
+ ASSERT( vt == VT_##VarType ); \
+ return( ##SingletonName ); \
+ } \
+ }
+
+
+class CPropVariant : public tagPROPVARIANT
+{
+
+public:
+
+ //
+ // Default Constructor & Destructor
+ //
+
+ CPropVariant()
+ {
+ PropVariantInit(this);
+ wReserved1 = INVALID_SUBSCRIPT;
+ }
+
+ ~CPropVariant()
+ {
+ PropVariantClear(this);
+ }
+
+ CPropVariant & operator =(CPropVariant& cpropvar)
+ {
+ PropVariantCopy( this, &cpropvar );
+ return( *this );
+ }
+
+ //
+ // Simple Constructors and assignment operators, and conversion
+ // operators.
+ //
+
+ CPropVariant(UCHAR b)
+ {
+ this->CPropVariant::CPropVariant();
+ vt = VT_UI1;
+ bVal = b;
+ }
+ CPropVariant & operator =(UCHAR b)
+ {
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant(b);
+ return (*this);
+ }
+
+ CPropVariant(short i)
+ {
+ this->CPropVariant::CPropVariant();
+ vt = VT_I2;
+ iVal = i;
+ }
+ CPropVariant & operator =(short i)
+ {
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant(i);
+ return (*this);
+ }
+
+ CPropVariant(USHORT ui) { vt = VT_UI2; uiVal = ui; wReserved1 = INVALID_SUBSCRIPT; }
+ CPropVariant & operator =(USHORT ui)
+ {
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant(ui);
+ return (*this);
+ }
+
+ CPropVariant(long l) { vt = VT_I4; lVal = l; wReserved1 = INVALID_SUBSCRIPT; }
+ CPropVariant & operator =(long l)
+ {
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant(l);
+ return (*this);
+ }
+
+ CPropVariant(ULONG ul) { vt = VT_UI4; ulVal = ul; wReserved1 = INVALID_SUBSCRIPT; }
+ CPropVariant & operator =(ULONG ul)
+ {
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant(ul);
+ return (*this);
+ }
+
+ CPropVariant(LARGE_INTEGER h) { vt = VT_I8; hVal = h; wReserved1 = INVALID_SUBSCRIPT; }
+ inline CPropVariant & operator =(LARGE_INTEGER h)
+ {
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant(h);
+ return (*this);
+ }
+
+ CPropVariant(ULARGE_INTEGER uh) { vt = VT_UI8; uhVal = uh; wReserved1 = INVALID_SUBSCRIPT; }
+ CPropVariant & operator =(ULARGE_INTEGER uh)
+ {
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant(uh);
+ return (*this);
+ }
+
+
+ CPropVariant(float flt) { vt = VT_R4; fltVal = flt; wReserved1 = INVALID_SUBSCRIPT; }
+ CPropVariant & operator =(float flt)
+ {
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant(flt);
+ return (*this);
+ }
+
+ CPropVariant(double dbl) { vt = VT_R8; dblVal = dbl; wReserved1 = INVALID_SUBSCRIPT; }
+ CPropVariant & operator =(double dbl)
+ {
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant(dbl);
+ return (*this);
+ }
+
+ CPropVariant(CY cy) { vt = VT_CY; cyVal = cy; wReserved1 = INVALID_SUBSCRIPT; }
+ CPropVariant & operator =(CY cy)
+ {
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant(cy);
+ return (*this);
+ }
+
+ CPropVariant(FILETIME ft) { vt = VT_FILETIME; filetime = ft; wReserved1 = INVALID_SUBSCRIPT; }
+ CPropVariant & operator =(FILETIME ft)
+ {
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant(ft);
+ return (*this);
+ }
+
+ void SetCLSID( const CLSID &clsid );
+ void SetCLSID(const CLSID &clsid, unsigned pos);
+
+ CPropVariant(CLSID *pclsid)
+ {
+ SetCLSID( *pclsid );
+ }
+ CPropVariant(CLSID &clsid)
+ {
+ SetCLSID( clsid );
+ }
+ DECLARE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CLSID);
+
+ CPropVariant(IStream *pStm)
+ {
+ vt = VT_STREAM;
+ pStream = pStm;
+ wReserved1 = INVALID_SUBSCRIPT;
+
+ if( NULL != pStream )
+ pStream->AddRef();
+ }
+ CPropVariant & operator =(IStream *pStm)
+ {
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant(pStm);
+ return (*this);
+ }
+ operator IStream*()
+ {
+ ASSERT( VT_STREAM == vt );
+ return( pStream );
+ }
+
+ CPropVariant(IStorage *pStg)
+ {
+ vt = VT_STORAGE;
+ pStorage = pStg;
+ wReserved1 = INVALID_SUBSCRIPT;
+
+ if( NULL != pStorage )
+ pStorage->AddRef();
+ }
+ CPropVariant & operator =(IStorage *pStg)
+ {
+ PropVariantClear(this);
+ this->CPropVariant::CPropVariant(pStg);
+ return (*this);
+ }
+ operator IStorage*()
+ {
+ ASSERT( VT_STORAGE == vt );
+ return( pStorage );
+ }
+
+
+public:
+
+ CPropVariant(LPSTR psz);
+ void SetLPSTR( char const *psz, unsigned pos);
+ DECLARE_CPROPVARIANT_ASSIGNMENT_OPERATOR(LPSTR);
+ DECLARE_CPROPVARIANT_CONVERSION_OPERATOR(LPSTR);
+
+ CPropVariant(LPWSTR pwsz);
+ void SetLPWSTR( WCHAR const *psz, unsigned pos);
+ DECLARE_CPROPVARIANT_ASSIGNMENT_OPERATOR(LPWSTR);
+ DECLARE_CPROPVARIANT_CONVERSION_OPERATOR(LPWSTR);
+
+ CPropVariant(const CLIPDATA *p);
+ CPropVariant(const CLIPDATA& clipdata)
+ {
+ this->CPropVariant::CPropVariant( &clipdata );
+ }
+ CPropVariant( const CClipData *pcclipdata )
+ {
+ this->CPropVariant::CPropVariant( (CLIPDATA*)(void*) pcclipdata );
+ }
+ CPropVariant( const CClipData& cclipdata )
+ {
+ this->CPropVariant::CPropVariant( (CLIPDATA*)(void*) &cclipdata );
+ }
+ void SetCF( const CLIPDATA *pclipdata, unsigned pos);
+ void SetCF( const CLIPDATA& clipdata, unsigned pos )
+ {
+ SetCF( &clipdata, pos );
+ }
+ void SetCF( const CClipData *pcclipdata, unsigned pos )
+ {
+ SetCF( (CLIPDATA*)(void*) pcclipdata, pos );
+ }
+ void SetCF( const CClipData& cclipdata, unsigned pos )
+ {
+ SetCF( (CLIPDATA*)(void*) &cclipdata, pos );
+ }
+ DECLARE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CLIPDATA&);
+ DECLARE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CClipData&);
+
+
+ CPropVariant( const BLOB *pblob )
+ {
+ PropVariantClear( this );
+ blob.pBlobData = (BYTE*) CoTaskMemAlloc( pblob->cbSize );
+ if( NULL == blob.pBlobData )
+ throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("CPropVariant couldn't alloc for VT_BLOB") );
+
+ memcpy( blob.pBlobData, pblob->pBlobData, pblob->cbSize );
+ blob.cbSize = pblob->cbSize;
+ vt = VT_BLOB;
+ }
+ CPropVariant( BLOB& blob )
+ {
+ this->CPropVariant::CPropVariant( &blob );
+ }
+ CPropVariant( const CBlob *pcblob )
+ {
+ this->CPropVariant::CPropVariant( (BLOB*)(void*) pcblob );
+ }
+ CPropVariant( const CBlob& cblob )
+ {
+ this->CPropVariant::CPropVariant( &cblob );
+ }
+ CPropVariant &operator = (CBlob &cblob)
+ {
+ this->CPropVariant::CPropVariant( (BLOB*)(void*)&cblob );
+ return( *this );
+ }
+ CPropVariant &operator = (BLOB &blob)
+ {
+ this->CPropVariant::CPropVariant( &blob );
+ return( *this );
+ }
+
+ void SetBSTR( const BSTR pwsz )
+ {
+ bstrVal = SysAllocString( pwsz );
+ if( NULL == bstrVal )
+ {
+ vt = VT_EMPTY;
+ }
+ else
+ {
+ vt = VT_BSTR;
+ }
+ }
+ void SetBSTR( const BSTR pwsz, unsigned pos );
+ BSTR GetBSTR()
+ {
+ ASSERT( vt == VT_BSTR );
+ ASSERT( !(vt & VT_VECTOR) );
+ return( bstrVal );
+ }
+ BSTR GetBSTR( int nSubscript );
+
+ void SetBOOL( BOOL b)
+ {
+ boolVal = b;
+ vt = VT_BOOL;
+ }
+ BOOL GetBOOL()
+ {
+ ASSERT( vt == VT_BOOL );
+ return( boolVal );
+ }
+
+ void SetERROR( SCODE sc)
+ {
+ scode = sc;
+ vt = VT_ERROR;
+ }
+ BOOL GetERROR()
+ {
+ ASSERT( vt == VT_ERROR );
+ return( scode );
+ }
+
+ void SetDATE( DATE dt)
+ {
+ date = dt;
+ vt = VT_DATE;
+ }
+ DATE GetDATE()
+ {
+ ASSERT( vt == VT_DATE );
+ return( date );
+ }
+
+
+ DECLARE_CPROPVARIANT_ASSIGNMENT_OPERATOR(LPPROPVARIANT);
+ DECLARE_CPROPVARIANT_CONVERSION_OPERATOR(LPPROPVARIANT);
+ void SetLPPROPVARIANT( LPPROPVARIANT lppropvar, unsigned pos );
+
+
+
+public:
+
+ inline void *operator new(size_t size);
+ inline void operator delete(void *p);
+ inline void *operator new(size_t size, void *p);
+
+
+public:
+
+ CPropVariant & operator[] (int nSubscript)
+ {
+ wReserved1 = (WORD) nSubscript + 1;
+ return (*this);
+ }
+
+ LPPROPVARIANT operator&()
+ {
+ return( this );
+ }
+
+
+public:
+
+ VARTYPE VarType() const
+ {
+ return( vt );
+ }
+
+ void Clear()
+ {
+ PropVariantClear( this );
+ }
+
+ ULONG Count() const
+ {
+ if( vt & VT_VECTOR )
+ return caui.cElems;
+ else
+ return 0;
+ }
+
+ void SetVarType(VARTYPE vtNew)
+ {
+ PropVariantClear( this );
+ PropVariantInit( this );
+ vt = vtNew;
+ }
+
+
+public:
+
+ CPropVariant(VARENUM vartype, ULONG cElements);
+
+public:
+
+ static HRESULT Compare( PROPVARIANT* ppropvar1, PROPVARIANT *ppropvar2 );
+
+private:
+
+ VOID *_AddStringToVector(
+ unsigned pos,
+ VOID *pv,
+ ULONG cb);
+
+ VOID *_AddScalerToVector(
+ unsigned pos,
+ VOID *pv,
+ ULONG cb);
+
+
+};
+
+
+
+inline CPropVariant::CPropVariant(LPWSTR pwsz)
+{
+ pwszVal = (LPWSTR) CoTaskMemAlloc( sizeof(WCHAR) * (wcslen(pwsz) + 1) );
+ if( pwszVal == NULL )
+ {
+ vt = VT_EMPTY;
+ }
+ else
+ {
+ vt = VT_LPWSTR;
+ memcpy( pwszVal, pwsz, sizeof(WCHAR) * (wcslen(pwsz) + 1) );
+ }
+}
+
+inline CPropVariant::CPropVariant(LPSTR psz)
+{
+ pszVal = (LPSTR) CoTaskMemAlloc( strlen(psz) + 1 );
+ if( NULL == pszVal )
+ {
+ vt = VT_EMPTY;
+ }
+ else
+ {
+ vt = VT_LPSTR;
+ memcpy( pszVal, psz, strlen(psz) + 1 );
+ }
+}
+
+
+
+inline void *
+CPropVariant::operator new(size_t size)
+{
+ void *p = CoTaskMemAlloc(size);
+
+ return(p);
+}
+
+
+inline void *
+CPropVariant::operator new(size_t size, void *p)
+{
+ return(p);
+}
+
+
+inline void
+CPropVariant::operator delete(void *p)
+{
+ if (p != NULL)
+ {
+ CoTaskMemFree(p);
+ }
+}
+
+
+
+class CClipData : private CLIPDATA
+{
+public:
+
+ ~CClipData()
+ {
+ if( NULL != pClipData)
+ CoTaskMemFree( pClipData);
+ }
+
+ CClipData()
+ {
+ cbSize = sizeof( ulClipFmt );
+ ulClipFmt = (ULONG) -1;
+ pClipData = NULL;
+ }
+
+ CClipData( ULONG ul, const void *p, ULONG cb )
+ {
+ HRESULT hr;
+ this->CClipData::CClipData();
+ hr = Set( ul, p, cb );
+ ASSERT( SUCCEEDED(hr) );
+ }
+
+ CClipData( LPSTR psz )
+ {
+ this->CClipData::CClipData( (ULONG) -1, psz, strlen(psz) + 1 );
+ }
+
+ CClipData( LPWSTR pwsz )
+ {
+ this->CClipData::CClipData( (ULONG) -1, pwsz,
+ sizeof(WCHAR) * (wcslen(pwsz) + 1) );
+ }
+
+ CClipData( CClipData &cClipData )
+ {
+ HRESULT hr;
+ hr = Set( cClipData.ulClipFmt,
+ cClipData.pClipData,
+ cClipData.cbSize - sizeof(ulClipFmt));
+ ASSERT( SUCCEEDED(hr) );
+ }
+
+ CClipData& operator =(CClipData &cClipData)
+ {
+ HRESULT hr;
+ hr = Set( cClipData.ulClipFmt,
+ cClipData.pClipData,
+ cClipData.cbSize - sizeof(ulClipFmt));
+ ASSERT( SUCCEEDED(hr) );
+ return( *this );
+ }
+
+ HRESULT Set( ULONG ul, const void *p, ULONG cb )
+ {
+ if( NULL != pClipData )
+ {
+ cb = sizeof( ulClipFmt );
+ ulClipFmt = (ULONG) -1;
+ CoTaskMemFree( pClipData );
+ }
+
+ if( NULL != p )
+ {
+ pClipData = (BYTE*) CoTaskMemAlloc( cb );
+ if( NULL == pClipData )
+ return( (HRESULT) E_OUTOFMEMORY );
+
+ memcpy( pClipData, p, cb );
+ }
+
+ cbSize = sizeof( ulClipFmt ) + cb;
+ ulClipFmt = ul;
+
+ return( S_OK );
+ }
+
+
+ operator CLIPDATA*()
+ {
+ return( this );
+ }
+
+};
+
+
+
+class CPropSpec : public PROPSPEC
+{
+public:
+
+ CPropSpec()
+ {
+ ulKind = PRSPEC_PROPID;
+ propid = 0;
+ }
+
+ ~CPropSpec()
+ {
+ if( PRSPEC_LPWSTR == ulKind )
+ CoTaskMemFree( lpwstr );
+
+ this->CPropSpec::CPropSpec();
+ }
+
+ operator PROPSPEC*()
+ {
+ return( this );
+ }
+
+ PROPSPEC* operator&()
+ {
+ return( this );
+ }
+ operator CPropSpec&()
+ {
+ return( *this );
+ }
+
+ CPropSpec( LPOLESTR posz )
+ {
+ memset( this, 0, sizeof(PROPSPEC) );
+ this->operator=(posz);
+ }
+ CPropSpec & operator = (LPOLESTR posz)
+ {
+ this->CPropSpec::~CPropSpec();
+
+ ULONG cb = ( ocslen(posz) + 1 ) * sizeof(OLECHAR);
+
+ lpwstr = (LPOLESTR) CoTaskMemAlloc( cb );
+ if( NULL != lpwstr )
+ {
+ memcpy( lpwstr, posz, cb );
+ ulKind = PRSPEC_LPWSTR;
+ }
+
+ return( *this );
+ }
+
+ CPropSpec & operator = (PROPID propidNew)
+ {
+ this->CPropSpec::~CPropSpec();
+
+ ulKind = PRSPEC_PROPID;
+ propid = propidNew;
+
+ return( *this );
+ }
+
+};
+
+
+class CBlob : public BLOB
+{
+public:
+
+ ~CBlob()
+ {
+ if( NULL != pBlobData )
+ CoTaskMemFree( pBlobData );
+ }
+
+ CBlob( LPSTR psz )
+ {
+ ULONG cb = 0;
+
+ if( NULL != psz )
+ {
+ cb = strlen( psz ) + sizeof(CHAR);
+ }
+
+ pBlobData = (BYTE*) CoTaskMemAlloc( cb );
+ if( NULL == pBlobData )
+ throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Couldn't allocate for CBlob") );
+
+ cbSize = cb;
+ memcpy( pBlobData, psz, cbSize );
+ }
+
+ CBlob( LPWSTR pwsz )
+ {
+ ULONG cb = 0;
+
+ if( NULL != pwsz )
+ {
+ cb = wcslen( pwsz ) + sizeof(WCHAR);
+ }
+
+ pBlobData = (BYTE*) CoTaskMemAlloc( cb + sizeof(cb) );
+ if( NULL == pBlobData )
+ throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Couldn't allocate for CBlob") );
+
+ cbSize = cb;
+ memcpy( pBlobData, pwsz, cbSize );
+ }
+
+ CBlob( ULONG cb )
+ {
+ pBlobData = (BYTE*) CoTaskMemAlloc( cb );
+ if( NULL == pBlobData )
+ throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Couldn't allocate for CBlob") );
+
+ cbSize = cb;
+ memset( pBlobData, 0, cb );
+ }
+
+ CBlob( int cb )
+ {
+ this->CBlob::CBlob( (ULONG) cb );
+ }
+
+};
+
+
+
+inline BOOL operator == ( CPropVariant &cpropvar1, CPropVariant &cpropvar2 )
+{
+ return( S_OK == CPropVariant::Compare(&cpropvar1, &cpropvar2) );
+}
+inline BOOL operator == ( CPropVariant &cpropvar, PROPVARIANT &propvar )
+{
+ return( (HRESULT) S_OK == CPropVariant::Compare(&cpropvar, &propvar) );
+}
+inline BOOL operator == ( PROPVARIANT &propvar, CPropVariant &cpropvar )
+{
+ return( (HRESULT) S_OK == CPropVariant::Compare(&cpropvar, &propvar) );
+}
+inline BOOL operator == ( PROPVARIANT propvar1, PROPVARIANT propvar2)
+{
+ return( (HRESULT) S_OK == CPropVariant::Compare(&propvar1, &propvar2) );
+}
+
+inline BOOL operator != ( CPropVariant &cpropvar1, CPropVariant &cpropvar2 )
+{
+ return( (HRESULT) S_FALSE == CPropVariant::Compare(&cpropvar1, &cpropvar2) );
+}
+inline BOOL operator != ( CPropVariant &cpropvar, PROPVARIANT &propvar )
+{
+ return( (HRESULT) S_FALSE == CPropVariant::Compare(&cpropvar, &propvar) );
+}
+inline BOOL operator != ( PROPVARIANT &propvar, CPropVariant &cpropvar )
+{
+ return( (HRESULT) S_FALSE == CPropVariant::Compare(&cpropvar, &propvar) );
+}
+inline BOOL operator != ( PROPVARIANT &propvar1, PROPVARIANT &propvar2)
+{
+ return( (HRESULT) S_FALSE == CPropVariant::Compare(&propvar1, &propvar2) );
+}
+
+
+
+
+#endif // !_CPROPVAR_HXX_
diff --git a/private/ole32/stg/props/utest/daytona/makefile b/private/ole32/stg/props/utest/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/props/utest/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/props/utest/daytona/makefile.inc b/private/ole32/stg/props/utest/daytona/makefile.inc
new file mode 100644
index 000000000..7d48c4d92
--- /dev/null
+++ b/private/ole32/stg/props/utest/daytona/makefile.inc
@@ -0,0 +1,5 @@
+
+!MESSAGE Old TARGET_DBG_DEFINES = "$(TARGET_DBG_DEFINES)"
+TARGET_DBG_DEFINES=$(TARGET_DBG_DEFINES:-DDBG=-DNOT_DBG)
+!MESSAGE New TARGET_DBG_DEFINES = "$(TARGET_DBG_DEFINES)"
+
diff --git a/private/ole32/stg/props/utest/daytona/sources b/private/ole32/stg/props/utest/daytona/sources
new file mode 100644
index 000000000..68b0506ff
--- /dev/null
+++ b/private/ole32/stg/props/utest/daytona/sources
@@ -0,0 +1,49 @@
+!IF 0
+
+Copyright (c) 1995 Microsoft Corporation
+
+!ENDIF
+
+!include ..\..\..\..\daytona.inc
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+TARGETNAME= proptest
+TARGETPATH= obj
+TARGETTYPE= PROGRAM
+
+INCLUDES= .;..;..\..\..\h;..\..\..\common;..\..\..\..\ih
+INCLUDES=$(INCLUDES);..\..\..\exp;..\..\..\h;..\..\..\..\com\inc;..\..
+INCLUDES=$(INCLUDES);..\pstgserv\proxstub\daytona\obj;..\pstgserv\proxstub
+INCLUDES=$(INCLUDES);..\..\..\..\..\inc
+
+SOURCES= \
+ ..\proptest.rc\
+ ..\propdump.cxx\
+ ..\testdoc.cxx\
+ ..\proptest.cxx\
+ ..\propmshl.cxx\
+ ..\cpropvar.cxx\
+ ..\testcase.cxx\
+ ..\rtlstub.cxx
+
+USE_NATIVE_EH=1
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+UMLIBS= $(BASEDIR)\public\sdk\lib\*\uuid.lib\
+ $(BASEDIR)\public\sdk\lib\*\iprop.lib\
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib\
+ $(BASEDIR)\public\sdk\lib\*\oleaut32.lib\
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib\
+ ..\pstgserv\proxstub\daytona\obj\*\pstgserv.lib
+
+#USE_NOLIBS=0
+#USE_CRTDLL=1
+USE_LIBCMT=1
+
+#PRECOMPILED_INCLUDE=..\pch.cxx
+
+NTTARGETFILES=
+
diff --git a/private/ole32/stg/props/utest/dirs b/private/ole32/stg/props/utest/dirs
new file mode 100644
index 000000000..d8de6a505
--- /dev/null
+++ b/private/ole32/stg/props/utest/dirs
@@ -0,0 +1,2 @@
+dirs=PStgServ
+optional_dirs= daytona
diff --git a/private/ole32/stg/props/utest/open.cxx b/private/ole32/stg/props/utest/open.cxx
new file mode 100644
index 000000000..d224e9943
--- /dev/null
+++ b/private/ole32/stg/props/utest/open.cxx
@@ -0,0 +1,213 @@
+//+-----------------------------------------------------------------------
+//
+// File: open.cxx
+//
+// Synopsis: Helper functions for opening all kinds of FILE_STORAGE_TYPEs.
+//
+// History: 06-May-95 DaveStr created
+//
+// Notes:
+//
+//------------------------------------------------------------------------
+
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+}
+
+#include <windows.h>
+#include <stgint.h>
+#include <iofs.h>
+#include <stgprop.h>
+#define _CAIROSTG_
+#include <olecairo.h>
+
+extern BOOL g_fOFS;
+
+HRESULT _Open(
+ WCHAR *path,
+ FILE_STORAGE_TYPE type,
+ BOOL fCreate,
+ HANDLE *ph)
+{
+ NTSTATUS status;
+ UNICODE_STRING str;
+ IO_STATUS_BLOCK iosb;
+ OBJECT_ATTRIBUTES oa;
+ HRESULT hr = S_OK;
+
+ if ( !RtlDosPathNameToNtPathName_U(path,&str,NULL,NULL) )
+ {
+ hr = HRESULT_FROM_NT(STATUS_OBJECT_PATH_INVALID);
+ }
+ else
+ {
+ InitializeObjectAttributes(
+ &oa,
+ &str,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL);
+
+ status = NtCreateFile(ph,
+ FILE_GENERIC_READ |
+ FILE_GENERIC_WRITE |
+ WRITE_OWNER |
+ WRITE_DAC |
+ SYNCHRONIZE |
+ DELETE,
+ &oa,
+ &iosb,
+ NULL,
+ 0,
+ FILE_SHARE_READ,
+ ( fCreate ) ? FILE_CREATE : 0,
+ FILE_SYNCHRONOUS_IO_NONALERT |
+ (g_fOFS ? (FILE_STORAGE_TYPE_SPECIFIED |
+ (type << FILE_STORAGE_TYPE_SHIFT)) : 0),
+ NULL,
+ 0);
+
+ if ( !NT_SUCCESS(status) )
+ {
+ hr = HRESULT_FROM_NT(status);
+ }
+
+ RtlFreeUnicodeString(&str);
+ }
+
+ return(hr);
+}
+
+static DWORD grfmode = (STGM_READWRITE | STGM_SHARE_EXCLUSIVE);
+
+HRESULT OpenDir(
+ WCHAR *path,
+ BOOL fCreate,
+ IStorage **ppistg)
+{
+ if ( fCreate )
+ {
+ return(StgCreateStorage(path,
+ grfmode,
+ STGFMT_DIRECTORY,
+ NULL,
+ ppistg));
+ }
+ else
+ {
+ return(StgOpenStorage(path,
+ NULL,
+ grfmode,
+ NULL,
+ 0,
+ ppistg));
+ }
+}
+
+HRESULT OpenFile(
+ WCHAR *path,
+ BOOL fCreate,
+ IStorage **ppistg)
+{
+ if ( fCreate )
+ {
+ return(StgCreateStorage(path,
+ grfmode,
+ STGFMT_FILE,
+ NULL,
+ ppistg));
+ }
+ else
+ {
+ return(StgOpenStorage(path,
+ NULL,
+ grfmode,
+ NULL,
+ 0,
+ ppistg));
+ }
+}
+
+HRESULT OpenJP(
+ WCHAR *path,
+ BOOL fCreate,
+ IStorage **ppistg)
+{
+ HRESULT hr;
+ HANDLE h;
+
+ hr = _Open(path, StorageTypeJunctionPoint, fCreate, &h);
+
+ if ( SUCCEEDED(hr) )
+ {
+ if ( fCreate )
+ {
+ hr = StgCreateStorageOnHandle(h,
+ grfmode,
+ STGFMT_DIRECTORY,
+ ppistg);
+ }
+ else
+ {
+ hr = StgOpenStorageOnHandle(h,
+ grfmode,
+ ppistg);
+ }
+
+ NtClose(h);
+ }
+
+ return(hr);
+}
+
+HRESULT OpenSC(
+ WCHAR *path,
+ BOOL fCreate,
+ IStorage **ppistg)
+{
+ if ( fCreate )
+ {
+ return(StgCreateStorage(path,
+ grfmode,
+ STGFMT_CATALOG,
+ NULL,
+ ppistg));
+ }
+ else
+ {
+ return(StgOpenStorage(path,
+ NULL,
+ grfmode,
+ NULL,
+ 0,
+ ppistg));
+ }
+}
+
+HRESULT OpenStg(
+ WCHAR *path,
+ BOOL fCreate,
+ IStorage **ppistg)
+
+{
+ if ( fCreate )
+ {
+ return(StgCreateStorage(path,
+ grfmode,
+ STGFMT_DOCUMENT,
+ NULL,
+ ppistg));
+ }
+ else
+ {
+ return(StgOpenStorage(path,
+ NULL,
+ grfmode,
+ NULL,
+ 0,
+ ppistg));
+ }
+}
diff --git a/private/ole32/stg/props/utest/pch.cxx b/private/ole32/stg/props/utest/pch.cxx
new file mode 100644
index 000000000..6031b918a
--- /dev/null
+++ b/private/ole32/stg/props/utest/pch.cxx
@@ -0,0 +1,220 @@
+
+
+//+============================================================================
+//
+// File: pch.cxx
+//
+// Purpose: This file composes the pre-compiled header for the
+// PropTest DRT.
+//
+//+============================================================================
+
+
+#ifdef _MAC_NODOC
+
+// ================
+// Mac NODOC Format
+// ================
+
+// The following set of pre-compiler directives is used in the
+// Mac "NODOC" build environment.
+
+ // ----------------------------------------
+ // Build Environment Configuration Settings
+ // ----------------------------------------
+
+ #define _PPCMAC // Macintosh PPC build
+ #define OLE2ANSI // Ansi OLE (OLECHAR == char)
+ #undef WIN32 // Do not include Win32 information
+ #define IPROPERTY_DLL // Use code for IProp.DLL
+ #define BIGENDIAN 1 // Enable byte-swapping.
+ #define IPROP_NO_OLEAUTO_H 1 // Don't try to include "oleauto.h"
+
+ // If the NODOC environment's "debug" flag is set, then set the
+ // NT environment's corresponding flag.
+
+ #ifdef _DEBUG
+ #define DBG 1
+ #endif
+
+ // ------
+ // Macros
+ // ------
+
+ // The default Ansi CodePage
+ #define CP_ACP 0
+
+ // unsigned-long to Ansi
+ #define ULTOA(ul, ch, i) _ultoa( ul, ch, i )
+
+ // NTSTATUS and HRESULT information not available in the NODOC build.
+
+ #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
+
+ #define FACILITY_WIN32 7
+ #define FACILITY_NT_BIT 0x10000000
+ #define HRESULT_FROM_WIN32(x) (x ? ((HRESULT) (((x) &0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000)) : 0 )
+ #define ERROR_NO_UNICODE_TRANSLATION 1113L
+ #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
+ #define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL)
+
+
+ // --------------
+ // Basic Includes
+ // --------------
+
+ // NOOP two #defines that are unnecessary in the NODOC environment.
+
+ #define __RPC_FAR
+ #define __RPC_STUB
+
+ // Include the property set information (this same file is included
+ // in the shipping package for use by ISVs.
+ #include "iprop.h"
+
+ // Include macros for dealing with OLECHARs
+ #include <olechar.h>
+
+
+ // --------
+ // TypeDefs
+ // --------
+
+ typedef LONG NTSTATUS;
+ typedef ULONG PROPID;
+
+
+ // ----------
+ // Prototypes
+ // ----------
+
+ // IMalloc wrappers
+
+ LPVOID _CRTAPI1 CoTaskMemAlloc( ULONG cb );
+ LPVOID _CRTAPI1 CoTaskMemRealloc( LPVOID pvInput, ULONG cb );
+ VOID _CRTAPI1 CoTaskMemFree( LPVOID pv );
+
+ // wide-character routines.
+ int wcscmp( const WCHAR*, const WCHAR* );
+ UINT __cdecl wcslen( const WCHAR* ); // BUGBUG: size_t?
+ int wcsnicmp( const WCHAR*, const WCHAR*, UINT );
+ WCHAR *wcscpy( WCHAR* wszDest, const WCHAR* wszSource );
+
+ // Ansi/Unicode routines
+
+ UINT _CRTAPI1 GetACP();
+
+ // BSTR routines
+
+ BSTR SysAllocString(BSTR);
+ VOID SysFreeString(BSTR);
+
+
+ // -------
+ // Externs
+ // -------
+
+ // An array used by UuidCreate()
+ extern GUID g_curUuid;
+
+
+ // -------
+ // Inlines
+ // -------
+
+ // Compare two FMTIDs
+ inline BOOL operator == (const FMTID &fmtid1, const FMTID &fmtid2)
+ {
+ return IsEqualGUID( fmtid1, fmtid2 );
+ }
+
+ // Stub out the Win32 GetLastError() API.
+ inline DWORD GetLastError(){ return 0; }
+
+ // Stub out UuidCreate() by using a global list of
+ // GUIDs
+
+ inline void UuidCreate ( OUT GUID * pUuid )
+ {
+ g_curUuid.Data1++;
+ *pUuid = g_curUuid; // member to member copy
+ }
+
+
+ // -----------------
+ // Extended Includes
+ // -----------------
+
+ #include <propmac.hxx> // Property macros
+ #include "cpropvar.hxx" // CPropVariant class
+ #include "CDisplay.hxx" // CDisplay class (used by PRINTF macros)
+ #include "PropTest.hxx" // General information
+
+
+#else // #ifdef _MAC_NODOC
+
+// =========
+// NT Format
+// =========
+
+ // We'll take all the same abstractions that IProp.dll uses
+ #define IPROPERTY_DLL
+
+ extern "C"
+ {
+ #include <nt.h>
+ #include <ntrtl.h>
+ #include <nturtl.h>
+ #include <windows.h>
+ }
+
+ #define _CAIROSTG_
+ #include <oleext.h>
+ #include <stdio.h>
+ #include <time.h>
+
+ #define INITGUID
+ #include "initguid.h"
+
+ #include <safedecl.hxx>
+ #include <infs.hxx>
+// #include <iofs.h>
+ #include <oaidl.h>
+ #include <propset.h>
+ #include <expdf.hxx>
+ #include <propmac.hxx>
+ #include <olechar.h>
+
+ // Don't use the Win32 Unicode wcs routines, since they're
+ // not available on Win95.
+
+ #ifndef OLE2ANSI
+ #undef ocscpy
+ #undef ocscmp
+ #undef ocscat
+
+ #define ocscpy wcscpy
+ #define ocscmp wcscmp
+ #define ocscat wcscat
+ #endif
+
+ #include "cpropvar.hxx"
+
+ #include "PropMshl.hxx"
+ #include "PropTest.hxx"
+
+ #include "PStgServ.h"
+
+#endif
+
+// ==================
+// NT/Mac Information
+// ==================
+
+// ------
+// Macros
+// ------
+
+// Abstract the VT of an OLESTR
+#define VT_LPOLESTR VT_LPSTR
+
diff --git a/private/ole32/stg/props/utest/propdump.cxx b/private/ole32/stg/props/utest/propdump.cxx
new file mode 100644
index 000000000..24deb5adf
--- /dev/null
+++ b/private/ole32/stg/props/utest/propdump.cxx
@@ -0,0 +1,1453 @@
+
+
+//+============================================================================
+//
+// File: PropDump.cxx
+//
+// Purpose:
+// This file contains routines to dump all the properties of all
+// the property sets of a DocFile. It's started by calling
+// DumpOleStorage().
+//
+//+============================================================================
+
+// --------
+// Includes
+// --------
+
+#include "pch.cxx"
+
+
+// -------
+// Globals
+// -------
+
+OLECHAR *oszDays[] =
+{
+ OLESTR("Sun"),
+ OLESTR("Mon"),
+ OLESTR("Tue"),
+ OLESTR("Wed"),
+ OLESTR("Thu"),
+ OLESTR("Fri"),
+ OLESTR("Sat")
+};
+
+OLECHAR *oszMonths[] =
+{
+ OLESTR("Jan"), OLESTR("Feb"), OLESTR("Mar"), OLESTR("Apr"), OLESTR("May"), OLESTR("Jun"),
+ OLESTR("Jul"), OLESTR("Aug"), OLESTR("Sep"), OLESTR("Oct"), OLESTR("Nov"), OLESTR("Dec")
+};
+
+
+//+----------------------------------------------------------------------------
+//+----------------------------------------------------------------------------
+
+OLECHAR *
+oszft(FILETIME *pft)
+{
+ static OLECHAR oszbuf[32];
+
+#ifdef _MAC
+
+ soprintf( oszbuf, OLESTR("%08X-%08X"), pft->dwHighDateTime, pft->dwLowDateTime );
+
+#else
+
+ FILETIME ftlocal;
+ SYSTEMTIME st;
+
+ oszbuf[0] = '\0';
+ if (pft->dwHighDateTime != 0 || pft->dwLowDateTime != 0)
+ {
+ if (!FileTimeToLocalFileTime(pft, &ftlocal) ||
+ !FileTimeToSystemTime(&ftlocal, &st))
+ {
+ return(OLESTR("Time???"));
+ }
+ soprintf(
+ oszbuf,
+ OLESTR("%s %s %2d %2d:%02d:%02d %4d"),
+ oszDays[st.wDayOfWeek],
+ oszMonths[st.wMonth - 1],
+ st.wDay,
+ st.wHour,
+ st.wMinute,
+ st.wSecond,
+ st.wYear);
+ }
+
+#endif
+
+ return(oszbuf);
+}
+
+
+VOID
+DumpTime(OLECHAR *pozname, FILETIME *pft)
+{
+ LARGE_INTEGER UNALIGNED *pli = (LARGE_INTEGER UNALIGNED *) pft;
+
+ ASYNC_PRINTF(
+ "%s%08lx:%08lx%hs%s\n",
+ pozname,
+ pli->HighPart,
+ pli->LowPart,
+ pli->QuadPart == 0? g_szEmpty : " - ",
+ oszft((FILETIME *) pft));
+}
+
+
+VOID
+PrintGuid(GUID *pguid)
+{
+ ASYNC_PRINTF(
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ pguid->Data1,
+ pguid->Data2,
+ pguid->Data3,
+ pguid->Data4[0],
+ pguid->Data4[1],
+ pguid->Data4[2],
+ pguid->Data4[3],
+ pguid->Data4[4],
+ pguid->Data4[5],
+ pguid->Data4[6],
+ pguid->Data4[7]);
+}
+
+
+VOID
+ListPropSetHeader(
+ STATPROPSETSTG *pspss,
+ OLECHAR *poszName)
+{
+ BOOLEAN fDocumentSummarySection2;
+ OLECHAR oszStream[CCH_PROPSETSZ];
+
+ fDocumentSummarySection2 = (BOOLEAN)
+ memcmp(&pspss->fmtid, &FMTID_UserDefinedProperties, sizeof(GUID)) == 0;
+
+ ASYNC_PRINTF(" Property set ");
+ PrintGuid(&pspss->fmtid);
+
+ RtlGuidToPropertySetName(&pspss->fmtid, oszStream);
+
+ ASYNC_OPRINTF(
+ OLESTR("\n %hs Name %s"),
+ (pspss->grfFlags & PROPSETFLAG_NONSIMPLE)?
+ "Embedding" : "Stream",
+ oszStream);
+ if (poszName != NULL || fDocumentSummarySection2)
+ {
+ ASYNC_OPRINTF(
+ OLESTR(" (%s)"),
+ poszName != NULL? poszName : OLESTR("User defined properties"));
+ }
+ ASYNC_PRINTF("\n");
+
+ if (pspss->grfFlags & PROPSETFLAG_NONSIMPLE)
+ {
+ DumpTime(OLESTR(" Create Time "), &pspss->ctime);
+ }
+ DumpTime(OLESTR(" Modify Time "), &pspss->mtime);
+ if (pspss->grfFlags & PROPSETFLAG_NONSIMPLE)
+ {
+ DumpTime(OLESTR(" Access Time "), &pspss->atime);
+ }
+}
+
+
+
+
+typedef enum _PUBLICPROPSET
+{
+ PUBPS_UNKNOWN = 0,
+ PUBPS_SUMMARYINFO = 3,
+ PUBPS_DOCSUMMARYINFO = 4,
+ PUBPS_USERDEFINED = 5,
+} PUBLICPROPSET;
+
+
+#define BSTRLEN(bstrVal) *((ULONG *) bstrVal - 1)
+ULONG
+SizeProp(PROPVARIANT *pv)
+{
+ ULONG j;
+ ULONG cbprop = 0;
+
+ switch (pv->vt)
+ {
+ default:
+ case VT_EMPTY:
+ case VT_NULL:
+ break;
+
+ case VT_UI1:
+ cbprop = sizeof(pv->bVal);
+ break;
+
+ case VT_I2:
+ case VT_UI2:
+ case VT_BOOL:
+ cbprop = sizeof(pv->iVal);
+ break;
+
+ case VT_I4:
+ case VT_UI4:
+ case VT_R4:
+ case VT_ERROR:
+ cbprop = sizeof(pv->lVal);
+ break;
+
+ case VT_I8:
+ case VT_UI8:
+ case VT_R8:
+ case VT_CY:
+ case VT_DATE:
+ case VT_FILETIME:
+ cbprop = sizeof(pv->hVal);
+ break;
+
+ case VT_CLSID:
+ cbprop = sizeof(*pv->puuid);
+ break;
+
+ case VT_BLOB_OBJECT:
+ case VT_BLOB:
+ cbprop = pv->blob.cbSize + sizeof(pv->blob.cbSize);
+ break;
+
+ case VT_CF:
+ cbprop = sizeof(pv->pclipdata->cbSize) +
+ pv->pclipdata->cbSize;
+ break;
+
+ case VT_BSTR:
+ // count + string
+ cbprop = sizeof(ULONG);
+ if (pv->bstrVal != NULL)
+ {
+ cbprop += BSTRLEN(pv->bstrVal);
+ }
+ break;
+
+ case VT_LPSTR:
+ // count + string + null char
+ cbprop = sizeof(ULONG);
+ if (pv->pszVal != NULL)
+ {
+ cbprop += strlen(pv->pszVal) + 1;
+ }
+ break;
+
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ case VT_LPWSTR:
+ // count + string + null char
+ cbprop = sizeof(ULONG);
+ if (pv->pwszVal != NULL)
+ {
+ cbprop += sizeof(pv->pwszVal[0]) * (wcslen(pv->pwszVal) + 1);
+ }
+ break;
+
+ // vectors
+ case VT_VECTOR | VT_UI1:
+ cbprop = sizeof(pv->caub.cElems) +
+ pv->caub.cElems * sizeof(pv->caub.pElems[0]);
+ break;
+
+ case VT_VECTOR | VT_I2:
+ case VT_VECTOR | VT_UI2:
+ case VT_VECTOR | VT_BOOL:
+ cbprop = sizeof(pv->cai.cElems) +
+ pv->cai.cElems * sizeof(pv->cai.pElems[0]);
+ break;
+
+ case VT_VECTOR | VT_I4:
+ case VT_VECTOR | VT_UI4:
+ case VT_VECTOR | VT_R4:
+ case VT_VECTOR | VT_ERROR:
+ cbprop = sizeof(pv->cal.cElems) +
+ pv->cal.cElems * sizeof(pv->cal.pElems[0]);
+ break;
+
+ case VT_VECTOR | VT_I8:
+ case VT_VECTOR | VT_UI8:
+ case VT_VECTOR | VT_R8:
+ case VT_VECTOR | VT_CY:
+ case VT_VECTOR | VT_DATE:
+ case VT_VECTOR | VT_FILETIME:
+ cbprop = sizeof(pv->cah.cElems) +
+ pv->cah.cElems * sizeof(pv->cah.pElems[0]);
+ break;
+
+ case VT_VECTOR | VT_CLSID:
+ cbprop = sizeof(pv->cauuid.cElems) +
+ pv->cauuid.cElems * sizeof(pv->cauuid.pElems[0]);
+ break;
+
+ case VT_VECTOR | VT_CF:
+ cbprop = sizeof(pv->caclipdata.cElems);
+ for (j = 0; j < pv->caclipdata.cElems; j++)
+ {
+ cbprop += sizeof(pv->caclipdata.pElems[j].cbSize) +
+ DwordAlign(pv->caclipdata.pElems[j].cbSize);
+ }
+ break;
+
+ case VT_VECTOR | VT_BSTR:
+ cbprop = sizeof(pv->cabstr.cElems);
+ for (j = 0; j < pv->cabstr.cElems; j++)
+ {
+ // count + string + null char
+ cbprop += sizeof(ULONG);
+ if (pv->cabstr.pElems[j] != NULL)
+ {
+ cbprop += DwordAlign(BSTRLEN(pv->cabstr.pElems[j]));
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_LPSTR:
+ cbprop = sizeof(pv->calpstr.cElems);
+ for (j = 0; j < pv->calpstr.cElems; j++)
+ {
+ // count + string + null char
+ cbprop += sizeof(ULONG);
+ if (pv->calpstr.pElems[j] != NULL)
+ {
+ cbprop += DwordAlign(strlen(pv->calpstr.pElems[j]) + 1);
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_LPWSTR:
+ cbprop = sizeof(pv->calpwstr.cElems);
+ for (j = 0; j < pv->calpwstr.cElems; j++)
+ {
+ // count + string + null char
+ cbprop += sizeof(ULONG);
+ if (pv->calpwstr.pElems[j] != NULL)
+ {
+ cbprop += DwordAlign(
+ sizeof(pv->calpwstr.pElems[j][0]) *
+ (wcslen(pv->calpwstr.pElems[j]) + 1));
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_VARIANT:
+ cbprop = sizeof(pv->calpwstr.cElems);
+ for (j = 0; j < pv->calpwstr.cElems; j++)
+ {
+ cbprop += SizeProp(&pv->capropvar.pElems[j]);
+ }
+ break;
+ }
+ return(DwordAlign(cbprop) + DwordAlign(sizeof(pv->vt)));
+}
+
+
+PUBLICPROPSET
+GuidToPropSet(GUID *pguid)
+{
+ PUBLICPROPSET pubps = PUBPS_UNKNOWN;
+
+ if (pguid != NULL)
+ {
+ if (memcmp(pguid, &FMTID_SummaryInformation, sizeof(GUID)) == 0)
+ {
+ pubps = PUBPS_SUMMARYINFO;
+ }
+ else if (memcmp(pguid, &FMTID_DocSummaryInformation, sizeof(GUID)) == 0)
+ {
+ pubps = PUBPS_DOCSUMMARYINFO;
+ }
+ else if (memcmp(pguid, &FMTID_UserDefinedProperties, sizeof(GUID)) == 0)
+ {
+ pubps = PUBPS_USERDEFINED;
+ }
+ }
+ return(pubps);
+}
+
+
+char
+PrintableChar(char ch)
+{
+ if (ch < ' ' || ch > '~')
+ {
+ ch = '.';
+ }
+ return(ch);
+}
+
+
+VOID
+DumpHex(BYTE *pb, ULONG cb, ULONG base)
+{
+ char *pszsep;
+ ULONG r, i, cbremain;
+ int fZero = FALSE;
+ int fSame = FALSE;
+
+ for (r = 0; r < cb; r += 16)
+ {
+ cbremain = cb - r;
+ if (r != 0 && cbremain >= 16)
+ {
+ if (pb[r] == 0)
+ {
+ ULONG j;
+
+ for (j = r + 1; j < cb; j++)
+ {
+ if (pb[j] != 0)
+ {
+ break;
+ }
+ }
+ if (j == cb)
+ {
+ fZero = TRUE;
+ break;
+ }
+ }
+ if (memcmp(&pb[r], &pb[r - 16], 16) == 0)
+ {
+ fSame = TRUE;
+ continue;
+ }
+ }
+ if (fSame)
+ {
+ ASYNC_PRINTF("\n\t *");
+ fSame = FALSE;
+ }
+ for (i = 0; i < min(cbremain, 16); i++)
+ {
+ pszsep = " ";
+ if ((i % 8) == 0) // 0 or 8
+ {
+ pszsep = " ";
+ if (i == 0) // 0
+ {
+ // start a new line
+ ASYNC_PRINTF("%s %04x:", r == 0? "" : "\n", r + base);
+ pszsep = " ";
+ }
+ }
+ ASYNC_PRINTF("%s%02x", pszsep, pb[r + i]);
+ }
+ if (i != 0)
+ {
+ ASYNC_PRINTF("%*s", 3 + (16 - i)*3 + ((i <= 8)? 1 : 0), "");
+ for (i = 0; i < min(cbremain, 16); i++)
+ {
+ ASYNC_PRINTF("%c", PrintableChar(pb[r + i]));
+ }
+ }
+ }
+ if (r != 0)
+ {
+ ASYNC_PRINTF("\n");
+ }
+ if (fZero)
+ {
+ ASYNC_PRINTF(" Remaining %lx bytes are zero\n", cbremain);
+ }
+}
+
+
+// Property Id's for Summary Info
+#define PID_TITLE 0x00000002L // VT_LPSTR
+#define PID_SUBJECT 0x00000003L // VT_LPSTR
+#define PID_AUTHOR 0x00000004L // VT_LPSTR
+#define PID_KEYWORDS 0x00000005L // VT_LPSTR
+#define PID_COMMENTS 0x00000006L // VT_LPSTR
+#define PID_TEMPLATE 0x00000007L // VT_LPSTR
+#define PID_LASTAUTHOR 0x00000008L // VT_LPSTR
+#define PID_REVNUMBER 0x00000009L // VT_LPSTR
+#define PID_EDITTIME 0x0000000aL // VT_FILETIME
+#define PID_LASTPRINTED 0x0000000bL // VT_FILETIME
+#define PID_CREATE_DTM 0x0000000cL // VT_FILETIME
+#define PID_LASTSAVE_DTM 0x0000000dL // VT_FILETIME
+#define PID_PAGECOUNT 0x0000000eL // VT_I4
+#define PID_WORDCOUNT 0x0000000fL // VT_I4
+#define PID_CHARCOUNT 0x00000010L // VT_I4
+#define PID_THUMBNAIL 0x00000011L // VT_CF
+#define PID_APPNAME 0x00000012L // VT_LPSTR
+#define PID_SECURITY_DSI 0x00000013L // VT_I4
+
+// Property Id's for Document Summary Info
+#define PID_CATEGORY 0x00000002L // VT_LPSTR
+#define PID_PRESFORMAT 0x00000003L // VT_LPSTR
+#define PID_BYTECOUNT 0x00000004L // VT_I4
+#define PID_LINECOUNT 0x00000005L // VT_I4
+#define PID_PARACOUNT 0x00000006L // VT_I4
+#define PID_SLIDECOUNT 0x00000007L // VT_I4
+#define PID_NOTECOUNT 0x00000008L // VT_I4
+#define PID_HIDDENCOUNT 0x00000009L // VT_I4
+#define PID_MMCLIPCOUNT 0x0000000aL // VT_I4
+#define PID_SCALE 0x0000000bL // VT_BOOL
+#define PID_HEADINGPAIR 0x0000000cL // VT_VECTOR | VT_VARIANT
+#define PID_DOCPARTS 0x0000000dL // VT_VECTOR | VT_LPSTR
+#define PID_MANAGER 0x0000000eL // VT_LPSTR
+#define PID_COMPANY 0x0000000fL // VT_LPSTR
+#define PID_LINKSDIRTY 0x00000010L // VT_BOOL
+#define PID_CCHWITHSPACES 0x00000011L // VT_I4
+#define PID_GUID 0x00000012L // VT_LPSTR
+#define PID_SHAREDDOC 0x00000013L // VT_BOOL
+#define PID_LINKBASE 0x00000014L // VT_LPSTR
+#define PID_HLINKS 0x00000015L // VT_VECTOR | VT_VARIANT
+#define PID_HYPERLINKSCHANGED 0x00000016L // VT_BOOL
+
+
+VOID
+DisplayProps(
+ GUID *pguid,
+ ULONG cprop,
+ PROPID apid[],
+ STATPROPSTG asps[],
+ PROPVARIANT *av,
+ BOOLEAN fsumcat,
+ ULONG *pcbprop)
+{
+ PROPVARIANT *pv;
+ PROPVARIANT *pvend;
+ STATPROPSTG *psps;
+ BOOLEAN fVariantVector;
+ PUBLICPROPSET pubps;
+
+ fVariantVector = (asps == NULL);
+
+ pubps = GuidToPropSet(pguid);
+ pvend = &av[cprop];
+ for (pv = av, psps = asps; pv < pvend; pv++, psps++)
+ {
+ ULONG j;
+ ULONG cbprop;
+ PROPID propid;
+ OLECHAR *postrName;
+ char *psz;
+ BOOLEAN fNewLine = TRUE;
+ int ccol;
+ static char szNoFormat[] = " (no display format)";
+ char achvt[19 + 8 + 1];
+
+ cbprop = SizeProp(pv);
+ *pcbprop += cbprop;
+
+ postrName = NULL;
+ if (asps != NULL)
+ {
+ propid = psps->propid;
+ postrName = psps->lpwstrName;
+ }
+ else
+ {
+ ASSERT(apid != NULL);
+ propid = apid[0];
+ }
+
+ ASYNC_PRINTF(" ");
+ ccol = 0;
+
+ if (propid != PID_ILLEGAL)
+ {
+ ASYNC_PRINTF(" %04x", propid);
+ ccol += 5;
+ if (propid & (0xf << 28))
+ {
+ ccol += 4;
+ }
+ else if (propid & (0xf << 24))
+ {
+ ccol += 3;
+ }
+ else if (propid & (0xf << 20))
+ {
+ ccol += 2;
+ }
+ else if (propid & (0xf << 16))
+ {
+ ccol++;
+ }
+ }
+ if (postrName != NULL)
+ {
+ ASYNC_OPRINTF(OLESTR(" '%s'"), postrName);
+ ccol += ocslen(postrName) + 3;
+ }
+ else if (fVariantVector)
+ {
+ ULONG i = pv - av;
+
+ ASYNC_PRINTF("[%x]", i);
+ do
+ {
+ ccol++;
+ i >>= 4;
+ } while (i != 0);
+ ccol += 2;
+ }
+ else
+ {
+ psz = NULL;
+
+ switch (propid)
+ {
+ case PID_LOCALE: psz = "Locale"; break;
+ case PID_SECURITY: psz = "SecurityId"; break;
+ case PID_MODIFY_TIME: psz = "ModifyTime"; break;
+ case PID_CODEPAGE: psz = "CodePage"; break;
+ case PID_DICTIONARY: psz = "Dictionary"; break;
+ }
+ if (psz == NULL)
+ switch (pubps)
+ {
+ case PUBPS_SUMMARYINFO:
+ switch (propid)
+ {
+ case PID_TITLE: psz = "Title"; break;
+ case PID_SUBJECT: psz = "Subject"; break;
+ case PID_AUTHOR: psz = "Author"; break;
+ case PID_KEYWORDS: psz = "Keywords"; break;
+ case PID_COMMENTS: psz = "Comments"; break;
+ case PID_TEMPLATE: psz = "Template"; break;
+ case PID_LASTAUTHOR: psz = "LastAuthor"; break;
+ case PID_REVNUMBER: psz = "RevNumber"; break;
+ case PID_EDITTIME: psz = "EditTime"; break;
+ case PID_LASTPRINTED: psz = "LastPrinted"; break;
+ case PID_CREATE_DTM: psz = "CreateDateTime"; break;
+ case PID_LASTSAVE_DTM: psz = "LastSaveDateTime";break;
+ case PID_PAGECOUNT: psz = "PageCount"; break;
+ case PID_WORDCOUNT: psz = "WordCount"; break;
+ case PID_CHARCOUNT: psz = "CharCount"; break;
+ case PID_THUMBNAIL: psz = "ThumbNail"; break;
+ case PID_APPNAME: psz = "AppName"; break;
+ case PID_DOC_SECURITY: psz = "Security"; break;
+
+ }
+ break;
+
+ case PUBPS_DOCSUMMARYINFO:
+ switch (propid)
+ {
+ case PID_CATEGORY: psz = "Category"; break;
+ case PID_PRESFORMAT: psz = "PresFormat"; break;
+ case PID_BYTECOUNT: psz = "ByteCount"; break;
+ case PID_LINECOUNT: psz = "LineCount"; break;
+ case PID_PARACOUNT: psz = "ParaCount"; break;
+ case PID_SLIDECOUNT: psz = "SlideCount"; break;
+ case PID_NOTECOUNT: psz = "NoteCount"; break;
+ case PID_HIDDENCOUNT: psz = "HiddenCount"; break;
+ case PID_MMCLIPCOUNT: psz = "MmClipCount"; break;
+ case PID_SCALE: psz = "Scale"; break;
+ case PID_HEADINGPAIR: psz = "HeadingPair"; break;
+ case PID_DOCPARTS: psz = "DocParts"; break;
+ case PID_MANAGER: psz = "Manager"; break;
+ case PID_COMPANY: psz = "Company"; break;
+ case PID_LINKSDIRTY: psz = "LinksDirty"; break;
+ case PID_CCHWITHSPACES: psz = "CchWithSpaces"; break;
+ case PID_GUID: psz = "Guid"; break;
+ case PID_SHAREDDOC: psz = "SharedDoc"; break;
+ case PID_LINKBASE: psz = "LinkBase"; break;
+ case PID_HLINKS: psz = "HLinks"; break;
+ case PID_HYPERLINKSCHANGED: psz = "HyperLinksChanged";break;
+ }
+ break;
+ }
+ if (psz != NULL)
+ {
+ ASYNC_PRINTF(" %s", psz);
+ ccol += strlen(psz) + 1;
+ }
+ }
+#define CCOLPROPID 20
+ if (ccol != CCOLPROPID)
+ {
+ if (ccol > CCOLPROPID)
+ {
+ ccol = -1;
+ }
+ ASYNC_PRINTF("%s%*s", ccol == -1? "\n" : "", CCOLPROPID - ccol, "");
+ }
+ ASYNC_PRINTF(" %08x %04x %04x ", propid, cbprop, pv->vt);
+
+ psz = "";
+ switch (pv->vt)
+ {
+ default:
+ psz = achvt;
+ sprintf(psz, "Unknown (vt = %hx)", pv->vt);
+ break;
+
+ case VT_EMPTY:
+ ASYNC_PRINTF("EMPTY");
+ break;
+
+ case VT_NULL:
+ ASYNC_PRINTF("NULL");
+ break;
+
+ case VT_UI1:
+ ASYNC_PRINTF("UI1 = %02lx", pv->bVal);
+ psz = "";
+ break;
+
+ case VT_I2:
+ psz = "I2";
+ goto doshort;
+
+ case VT_UI2:
+ psz = "UI2";
+ goto doshort;
+
+ case VT_BOOL:
+ psz = "BOOL";
+doshort:
+ ASYNC_PRINTF("%s = %04hx", psz, pv->iVal);
+ psz = g_szEmpty;
+ break;
+
+ case VT_I4:
+ psz = "I4";
+ goto dolong;
+
+ case VT_UI4:
+ psz = "UI4";
+ goto dolong;
+
+ case VT_R4:
+ psz = "R4";
+ goto dolong;
+
+ case VT_ERROR:
+ psz = "ERROR";
+dolong:
+ ASYNC_PRINTF("%s = %08lx", psz, pv->lVal);
+ psz = g_szEmpty;
+ break;
+
+ case VT_I8:
+ psz = "I8";
+ goto dolonglong;
+
+ case VT_UI8:
+ psz = "UI8";
+ goto dolonglong;
+
+ case VT_R8:
+ psz = "R8";
+ goto dolonglong;
+
+ case VT_CY:
+ psz = "R8";
+ goto dolonglong;
+
+ case VT_DATE:
+ psz = "R8";
+dolonglong:
+ ASYNC_PRINTF(
+ "%s = %08lx:%08lx",
+ psz,
+ pv->hVal.HighPart,
+ pv->hVal.LowPart);
+ psz = g_szEmpty;
+ break;
+
+ case VT_FILETIME:
+ DumpTime(OLESTR("FILETIME =\n\t "), &pv->filetime);
+ fNewLine = FALSE; // skip newline printf
+ break;
+
+ case VT_CLSID:
+ ASYNC_PRINTF("CLSID =\n\t ");
+ PrintGuid(pv->puuid);
+ break;
+
+ case VT_BLOB:
+ psz = "BLOB";
+ goto doblob;
+
+ case VT_BLOB_OBJECT:
+ psz = "BLOB_OBJECT";
+doblob:
+ ASYNC_PRINTF("%s (cbSize %x)", psz, pv->blob.cbSize);
+ if (pv->blob.cbSize != 0)
+ {
+ ASYNC_PRINTF(" =\n");
+ DumpHex(pv->blob.pBlobData, pv->blob.cbSize, 0);
+ }
+ psz = g_szEmpty;
+ break;
+
+ case VT_CF:
+ ASYNC_PRINTF(
+ "CF (cbSize %x, ulClipFmt %x)\n",
+ pv->pclipdata->cbSize,
+ pv->pclipdata->ulClipFmt);
+ DumpHex(pv->pclipdata->pClipData,
+ pv->pclipdata->cbSize - sizeof(pv->pclipdata->ulClipFmt),
+ 0);
+ break;
+
+ case VT_STREAM:
+ psz = "STREAM";
+ goto dostring;
+
+ case VT_STREAMED_OBJECT:
+ psz = "STREAMED_OBJECT";
+ goto dostring;
+
+ case VT_STORAGE:
+ psz = "STORAGE";
+ goto dostring;
+
+ case VT_STORED_OBJECT:
+ psz = "STORED_OBJECT";
+ goto dostring;
+
+ case VT_BSTR:
+ ASYNC_PRINTF(
+ "BSTR (cb = %04lx)%s\n",
+ pv->bstrVal == NULL? 0 : BSTRLEN(pv->bstrVal),
+ pv->bstrVal == NULL? " NULL" : g_szEmpty);
+ if (pv->bstrVal != NULL)
+ {
+ DumpHex(
+ (BYTE *) pv->bstrVal,
+ BSTRLEN(pv->bstrVal) + sizeof(WCHAR),
+ 0);
+ }
+ break;
+
+ case VT_LPSTR:
+ psz = "LPSTR";
+ ASYNC_PRINTF(
+ "%s = %s%s%s",
+ psz,
+ pv->pszVal == NULL? g_szEmpty : "'",
+ pv->pszVal == NULL? "NULL" : pv->pszVal,
+ pv->pszVal == NULL? g_szEmpty : "'");
+ psz = g_szEmpty;
+ break;
+
+ case VT_LPWSTR:
+ psz = "LPWSTR";
+dostring:
+ ASYNC_PRINTF(
+ "%s = %s%ws%s",
+ psz,
+ pv->pwszVal == NULL? g_szEmpty : "'",
+ pv->pwszVal == NULL? L"NULL" : pv->pwszVal,
+ pv->pwszVal == NULL? g_szEmpty : "'");
+ psz = g_szEmpty;
+ break;
+
+ // vectors
+
+ case VT_VECTOR | VT_UI1:
+ ASYNC_PRINTF("UI1[%x] =", pv->caub.cElems);
+ for (j = 0; j < pv->caub.cElems; j++)
+ {
+ if ((j % 16) == 0)
+ {
+ ASYNC_PRINTF("\n %02hx:", j);
+ }
+ ASYNC_PRINTF(" %02hx", pv->caub.pElems[j]);
+ }
+ break;
+
+ case VT_VECTOR | VT_I2:
+ psz = "I2";
+ goto doshortvector;
+
+ case VT_VECTOR | VT_UI2:
+ psz = "UI2";
+ goto doshortvector;
+
+ case VT_VECTOR | VT_BOOL:
+ psz = "BOOL";
+doshortvector:
+ ASYNC_PRINTF("%s[%x] =", psz, pv->cai.cElems);
+ for (j = 0; j < pv->cai.cElems; j++)
+ {
+ if ((j % 8) == 0)
+ {
+ ASYNC_PRINTF("\n %04hx:", j);
+ }
+ ASYNC_PRINTF(" %04hx", pv->cai.pElems[j]);
+ }
+ psz = g_szEmpty;
+ break;
+
+ case VT_VECTOR | VT_I4:
+ psz = "I4";
+ goto dolongvector;
+
+ case VT_VECTOR | VT_UI4:
+ psz = "UI4";
+ goto dolongvector;
+
+ case VT_VECTOR | VT_R4:
+ psz = "R4";
+ goto dolongvector;
+
+ case VT_VECTOR | VT_ERROR:
+ psz = "ERROR";
+dolongvector:
+ ASYNC_PRINTF("%s[%x] =", psz, pv->cal.cElems);
+ for (j = 0; j < pv->cal.cElems; j++)
+ {
+ if ((j % 4) == 0)
+ {
+ ASYNC_PRINTF("\n %04x:", j);
+ }
+ ASYNC_PRINTF(" %08lx", pv->cal.pElems[j]);
+ }
+ psz = g_szEmpty;
+ break;
+
+ case VT_VECTOR | VT_I8:
+ psz = "I8";
+ goto dolonglongvector;
+
+ case VT_VECTOR | VT_UI8:
+ psz = "UI8";
+ goto dolonglongvector;
+
+ case VT_VECTOR | VT_R8:
+ psz = "R8";
+ goto dolonglongvector;
+
+ case VT_VECTOR | VT_CY:
+ psz = "CY";
+ goto dolonglongvector;
+
+ case VT_VECTOR | VT_DATE:
+ psz = "DATE";
+dolonglongvector:
+ ASYNC_PRINTF("%s[%x] =", psz, pv->cah.cElems);
+ for (j = 0; j < pv->cah.cElems; j++)
+ {
+ if ((j % 2) == 0)
+ {
+ ASYNC_PRINTF("\n %04x:", j);
+ }
+ ASYNC_PRINTF(
+ " %08lx:%08lx",
+ pv->cah.pElems[j].HighPart,
+ pv->cah.pElems[j].LowPart);
+ }
+ psz = g_szEmpty;
+ break;
+
+ case VT_VECTOR | VT_FILETIME:
+ ASYNC_PRINTF("FILETIME[%x] =\n", pv->cafiletime.cElems);
+ for (j = 0; j < pv->cafiletime.cElems; j++)
+ {
+ ASYNC_PRINTF(" %04x: ", j);
+ DumpTime(OLESTR(""), &pv->cafiletime.pElems[j]);
+ }
+ fNewLine = FALSE; // skip newline printf
+ break;
+
+ case VT_VECTOR | VT_CLSID:
+ ASYNC_PRINTF("CLSID[%x] =", pv->cauuid.cElems);
+ for (j = 0; j < pv->cauuid.cElems; j++)
+ {
+ ASYNC_PRINTF("\n %04x: ", j);
+ PrintGuid(&pv->cauuid.pElems[j]);
+ }
+ break;
+
+ case VT_VECTOR | VT_CF:
+ ASYNC_PRINTF("CF[%x] =", pv->caclipdata.cElems);
+ for (j = 0; j < pv->caclipdata.cElems; j++)
+ {
+ ASYNC_PRINTF("\n %04x: (cbSize %x, ulClipFmt %x) =\n",
+ j,
+ pv->caclipdata.pElems[j].cbSize,
+ pv->caclipdata.pElems[j].ulClipFmt);
+ DumpHex(
+ pv->caclipdata.pElems[j].pClipData,
+ pv->caclipdata.pElems[j].cbSize - sizeof(pv->caclipdata.pElems[j].ulClipFmt),
+ 0);
+ }
+ break;
+
+ case VT_VECTOR | VT_BSTR:
+ ASYNC_PRINTF("BSTR[%x] =", pv->cabstr.cElems);
+ for (j = 0; j < pv->cabstr.cElems; j++)
+ {
+ BSTR bstr = pv->cabstr.pElems[j];
+
+ ASYNC_PRINTF(
+ "\n %04x: cb = %04lx%s\n",
+ j,
+ bstr == NULL? 0 : BSTRLEN(pv->cabstr.pElems[j]),
+ bstr == NULL? " NULL" : g_szEmpty);
+ if (bstr != NULL)
+ {
+ DumpHex((BYTE *) bstr, BSTRLEN(bstr) + sizeof(WCHAR), 0);
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_LPSTR:
+ ASYNC_PRINTF("LPSTR[%x] =", pv->calpstr.cElems);
+ for (j = 0; j < pv->calpstr.cElems; j++)
+ {
+ CHAR *psz = pv->calpstr.pElems[j];
+
+ ASYNC_PRINTF(
+ "\n %04x: %s%s%s",
+ j,
+ psz == NULL? g_szEmpty : "'",
+ psz == NULL? "NULL" : psz,
+ psz == NULL? g_szEmpty : "'");
+ }
+ break;
+
+ case VT_VECTOR | VT_LPWSTR:
+ ASYNC_PRINTF("LPWSTR[%x] =", pv->calpwstr.cElems);
+ for (j = 0; j < pv->calpwstr.cElems; j++)
+ {
+ WCHAR *pwsz = pv->calpwstr.pElems[j];
+
+ ASYNC_PRINTF(
+ "\n %04x: %s%ws%s",
+ j,
+ pwsz == NULL? g_szEmpty : "'",
+ pwsz == NULL? L"NULL" : pwsz,
+ pwsz == NULL? g_szEmpty : "'");
+ }
+ break;
+
+ case VT_VECTOR | VT_VARIANT:
+ ASYNC_PRINTF("VARIANT[%x] =\n", pv->capropvar.cElems);
+ DisplayProps(
+ pguid,
+ pv->capropvar.cElems,
+ &propid,
+ NULL,
+ pv->capropvar.pElems,
+ fsumcat,
+ pcbprop);
+ fNewLine = FALSE; // skip newline printf
+ break;
+ }
+ if (*psz != '\0')
+ {
+ ASYNC_PRINTF("%s", psz);
+ if (pv->vt & VT_VECTOR)
+ {
+ ASYNC_PRINTF("[%x]", pv->cal.cElems);
+ }
+ ASYNC_PRINTF("%s", szNoFormat);
+ }
+ if (!fVariantVector && apid != NULL && apid[pv - av] != propid)
+ {
+ ASYNC_PRINTF(" (bad PROPID: %04x)", apid[pv - av]);
+ fNewLine = TRUE;
+ }
+ if (asps != NULL && pv->vt != psps->vt)
+ {
+ ASYNC_PRINTF(" (bad STATPROPSTG VARTYPE: %04x)", psps->vt);
+ fNewLine = TRUE;
+ }
+ if (fNewLine)
+ {
+ ASYNC_PRINTF("\n");
+ }
+ }
+}
+
+
+STATPROPSTG aspsStatic[] = {
+ { NULL, PID_CODEPAGE, VT_I2 },
+ { NULL, PID_MODIFY_TIME, VT_FILETIME },
+ { NULL, PID_SECURITY, VT_UI4 },
+};
+#define CPROPSTATIC (sizeof(aspsStatic)/sizeof(aspsStatic[0]))
+
+
+#define CB_STREAM_OVERHEAD 28
+#define CB_PROPSET_OVERHEAD (CB_STREAM_OVERHEAD + 8)
+#define CB_PROP_OVERHEAD 8
+
+HRESULT
+DumpOlePropertySet(
+ IPropertySetStorage *ppsstg,
+ STATPROPSETSTG *pspss,
+ ULONG *pcprop,
+ ULONG *pcbprop)
+{
+ HRESULT hr;
+ IEnumSTATPROPSTG *penumsps = NULL;
+ IPropertyStorage *pps;
+ ULONG cprop, cbpropset;
+ PROPID propid;
+ OLECHAR *poszName;
+ ULONG ispsStatic;
+
+ *pcprop = *pcbprop = 0;
+
+ hr = ppsstg->Open(
+ pspss->fmtid,
+ STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
+ &pps);
+
+ if( FAILED(hr) )
+ return(hr);
+
+ propid = PID_DICTIONARY;
+
+ hr = pps->ReadPropertyNames(1, &propid, &poszName);
+ if( (HRESULT) S_FALSE == hr )
+ hr = S_OK;
+ Check( S_OK, hr );
+
+ ListPropSetHeader(pspss, poszName);
+ if (poszName != NULL)
+ {
+ CoTaskMemFree(poszName);
+ }
+
+ cprop = cbpropset = 0;
+
+ Check(S_OK, pps->Enum(&penumsps) );
+
+ ispsStatic = 0;
+ hr = S_OK;
+ while (hr == S_OK)
+ {
+ STATPROPSTG sps;
+ PROPSPEC propspec;
+ PROPVARIANT propvar;
+ ULONG count;
+
+ hr = (HRESULT) S_FALSE;
+ if (ispsStatic == 0)
+ {
+ hr = penumsps->Next(1, &sps, &count);
+ }
+
+ if (hr != S_OK)
+ {
+ if (hr == (HRESULT) S_FALSE)
+ {
+ hr = S_OK;
+ if (ispsStatic >= CPROPSTATIC)
+ {
+ break;
+ }
+ sps = aspsStatic[ispsStatic];
+ ispsStatic++;
+ count = 1;
+ }
+ Check( S_OK, hr );
+ }
+ PropVariantInit(&propvar);
+ if (sps.lpwstrName != NULL)
+ {
+ propspec.ulKind = PRSPEC_LPWSTR;
+ propspec.lpwstr = sps.lpwstrName;
+ }
+ else
+ {
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = sps.propid;
+ }
+
+ hr = pps->ReadMultiple(1, &propspec, &propvar);
+ if (hr == (HRESULT) S_FALSE)
+ {
+ if (g_fVerbose)
+ {
+ ASYNC_PRINTF(
+ "%s(%u, %x) vt=%x returned hr=%x\n",
+ "IPropertyStorage::ReadMultiple",
+ ispsStatic,
+ propspec.propid,
+ propvar.vt,
+ hr);
+ }
+ ASSERT(propvar.vt == VT_EMPTY);
+ hr = S_OK;
+ }
+ Check( S_OK, hr );
+
+ if (ispsStatic == 0 || propvar.vt != VT_EMPTY)
+ {
+ ASSERT(count == 1);
+ cprop += count;
+ if (cprop == 1)
+ {
+ ASYNC_PRINTF(g_szPropHeader);
+ }
+
+ DisplayProps(
+ &pspss->fmtid,
+ 1,
+ NULL,
+ &sps,
+ &propvar,
+ FALSE,
+ &cbpropset);
+ PropVariantClear(&propvar);
+ }
+ if (sps.lpwstrName != NULL)
+ {
+ CoTaskMemFree(sps.lpwstrName);
+ }
+ }
+ if (penumsps != NULL)
+ {
+ penumsps->Release();
+ }
+ pps->Release();
+ if (cprop != 0)
+ {
+ cbpropset += CB_PROPSET_OVERHEAD + cprop * CB_PROP_OVERHEAD;
+ ASYNC_PRINTF(" %04x bytes in %u properties\n\n", cbpropset, cprop);
+ }
+ *pcprop = cprop;
+ *pcbprop = cbpropset;
+ return(hr);
+}
+
+
+HRESULT
+DumpOlePropertySets(
+ IStorage *pstg,
+ OLECHAR *aocpath)
+{
+
+ HRESULT hr = S_OK;
+ IPropertySetStorage *ppsstg;
+ ULONG cbproptotal = 0;
+ ULONG cproptotal = 0;
+ ULONG cpropset = 0;
+ IID IIDpsstg = IID_IPropertySetStorage;
+
+ Check(S_OK, StgCreatePropSetStg( pstg, 0L, &ppsstg ));
+
+ {
+ IEnumSTATPROPSETSTG *penumspss = NULL;
+
+ Check(S_OK, ppsstg->Enum(&penumspss) );
+
+ while (hr == S_OK)
+ {
+ STATPROPSETSTG spss;
+ ULONG count;
+ BOOLEAN fDocumentSummarySection2;
+
+ hr = penumspss->Next(1, &spss, &count);
+
+ if (hr != S_OK)
+ {
+ if (hr == (HRESULT) S_FALSE)
+ {
+ hr = (HRESULT) S_OK;
+ }
+
+ Check( (HRESULT) S_OK, hr );
+ break;
+ }
+ ASSERT(count == 1);
+
+ fDocumentSummarySection2 = FALSE;
+ while (TRUE)
+ {
+ ULONG cprop, cbprop;
+ HRESULT hr;
+
+ hr = DumpOlePropertySet(
+ ppsstg,
+ &spss,
+ &cprop,
+ &cbprop);
+
+ if( (HRESULT) STG_E_FILENOTFOUND == hr
+ &&
+ fDocumentSummarySection2 )
+ {
+ hr = S_OK;
+ }
+
+ cpropset++;
+ cproptotal += cprop;
+ cbproptotal += cbprop;
+
+ if (memcmp(&spss.fmtid, &FMTID_DocSummaryInformation, sizeof(FMTID)))
+ {
+ break;
+ }
+ spss.fmtid = FMTID_UserDefinedProperties;
+ fDocumentSummarySection2 = TRUE;
+ }
+ }
+
+ if (penumspss != NULL)
+ {
+ penumspss->Release();
+ }
+ ppsstg->Release();
+ }
+ if ((cbproptotal | cproptotal | cpropset) != 0)
+ {
+ ASYNC_PRINTF(
+ " %04x bytes in %u properties in %u property sets\n",
+ cbproptotal,
+ cproptotal,
+ cpropset);
+ }
+ return(hr);
+}
+
+
+NTSTATUS
+DumpOleStream(
+ LPSTREAM pstm,
+ ULONG cb)
+{
+ ULONG cbTotal = 0;
+
+ while (TRUE)
+ {
+ ULONG cbOut;
+ BYTE ab[4096];
+
+ Check(S_OK, pstm->Read(ab, min(cb, sizeof(ab)), &cbOut) );
+ if (cbOut == 0)
+ {
+ break;
+ }
+ if (g_fVerbose)
+ {
+ DumpHex(ab, cbOut, cbTotal);
+ }
+ cb -= cbOut;
+ cbTotal += cbOut;
+ }
+ return(STATUS_SUCCESS);
+}
+
+VOID
+DumpOleStorage(
+ IStorage *pstg,
+ LPOLESTR aocpath )
+{
+ LPENUMSTATSTG penum;
+ STATSTG ss;
+ IStorage* pstgChild;
+ LPSTREAM pstmChild;
+ char *szType;
+ OLECHAR *pocChild;
+ HRESULT hr;
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ Check( S_OK, DumpOlePropertySets(pstg, aocpath) );
+ Check( S_OK, pstg->EnumElements(0, NULL, 0, &penum) );
+
+ pocChild = &aocpath[ocslen(aocpath)];
+
+ // Continue enumeration until IEnumStatStg::Next returns non-S_OK
+
+ while (TRUE)
+ {
+ ULONG ulCount;
+
+ // Enumerate one element at a time
+ hr = penum->Next(1, &ss, &ulCount);
+ if( (HRESULT) S_FALSE == hr )
+ break;
+ else
+ Check( S_OK, hr );
+
+ // Select the human-readable type of object to display
+ switch (ss.type)
+ {
+ case STGTY_STREAM: szType = "Stream"; break;
+ case STGTY_STORAGE: szType = "Storage"; break;
+ case STGTY_LOCKBYTES: szType = "LockBytes"; break;
+ case STGTY_PROPERTY: szType = "Property"; break;
+ default: szType = "<Unknown>"; break;
+ }
+ if (g_fVerbose)
+ {
+ ASYNC_OPRINTF(
+ OLESTR("Type=%hs Size=%lx Mode=%lx LocksSupported=%lx StateBits=%lx '%s' + '%s'\n"),
+ szType,
+ ss.cbSize.LowPart,
+ ss.grfMode,
+ ss.grfLocksSupported,
+ ss.grfStateBits,
+ aocpath,
+ ss.pwcsName);
+ ASYNC_PRINTF("ss.clsid = ");
+ PrintGuid(&ss.clsid);
+ ASYNC_PRINTF("\n");
+ }
+
+ // If a stream, output the data in hex format.
+
+ if (ss.type == STGTY_STREAM)
+ {
+ ASYNC_OPRINTF(
+ OLESTR("Stream %s:%s, Size=%lx\n"),
+ aocpath,
+ ss.pwcsName,
+ ss.cbSize.LowPart);
+
+ Check(S_OK, pstg->OpenStream(
+ ss.pwcsName,
+ NULL,
+ STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
+ 0,
+ &pstmChild) );
+
+ Check(S_OK, DumpOleStream(pstmChild, ss.cbSize.LowPart) );
+ pstmChild->Release();
+ }
+
+ // If a storage, recurse
+ if (ss.type == STGTY_STORAGE)
+ {
+ ASYNC_OPRINTF(
+ OLESTR("Storage %s\\%s, Size=%lx\n"),
+ aocpath,
+ ss.pwcsName,
+ ss.cbSize.LowPart);
+ Check( S_OK, pstg->OpenStorage(
+ ss.pwcsName,
+ NULL,
+ STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0,
+ &pstgChild) );
+ *pocChild = L'\\';
+ ocscpy(pocChild + 1, ss.pwcsName);
+
+ DumpOleStorage(pstgChild, aocpath);
+ pstgChild->Release();
+
+ *pocChild = L'\0';
+ }
+ CoTaskMemFree(ss.pwcsName);
+ PRINTF( "\n" );
+ }
+ penum->Release();
+ return;
+
+}
+
+
diff --git a/private/ole32/stg/props/utest/propmshl.cxx b/private/ole32/stg/props/utest/propmshl.cxx
new file mode 100644
index 000000000..781ff1365
--- /dev/null
+++ b/private/ole32/stg/props/utest/propmshl.cxx
@@ -0,0 +1,409 @@
+/*
+#include <stdio.h>
+#include "PStgServ.h"
+#include "PropMshl.hxx"
+#include "CPropVar.hxx"
+#include "CHResult.hxx"
+#include "proptest.hxx"
+*/
+
+#include "pch.cxx"
+
+const IID IID_IDocFileMarshal = {0xaf4ae0d0,0xa37f,0x11cf,{0x8d,0x73,0x00,0xaa,0x00,0x4c,0xd0,0x1a}};
+
+
+
+CPropStgMarshalTest::CPropStgMarshalTest( )
+{
+ m_cAllProperties = 0;
+ m_cSimpleProperties = 0;
+ m_rgpropspec = NULL;
+ m_rgpropvar = NULL;
+ m_pwszDocFileName = NULL;
+ m_fInitialized = FALSE;
+}
+
+
+CPropStgMarshalTest::~CPropStgMarshalTest()
+{
+ if( m_pwszDocFileName != NULL )
+ delete m_pwszDocFileName;
+}
+
+
+
+CPropStgMarshalTest::Init( OLECHAR *pwszDocFileName,
+ PROPVARIANT rgpropvar[],
+ PROPSPEC rgpropspec[],
+ ULONG cAllProperties,
+ ULONG cSimpleProperties )
+{
+ HRESULT hr = E_FAIL;
+
+ // Validate the input.
+
+ if( pwszDocFileName == NULL )
+ {
+ hr = STG_E_INVALIDPARAMETER;
+ goto Exit;
+ }
+
+ m_cAllProperties = cAllProperties;
+ m_cSimpleProperties = cSimpleProperties;
+ m_rgpropvar = rgpropvar;
+ m_rgpropspec = rgpropspec;
+
+ // Copy the docfile name.
+
+ m_pwszDocFileName = new WCHAR[ wcslen(pwszDocFileName) + 1 ];
+
+ if( m_pwszDocFileName != NULL )
+ {
+ wcscpy( m_pwszDocFileName, pwszDocFileName );
+ }
+ else
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+
+ hr = S_OK;
+
+Exit:
+
+ return( hr );
+}
+
+
+
+
+CPropStgMarshalTest::Run()
+{
+
+ HRESULT hr = S_OK;
+
+ IPropertyStorageServer *pdfm = NULL;
+ IStorage *pstg = NULL;
+ IPropertySetStorage *ppsstg = NULL;
+ IPropertyStorage *ppstg = NULL;
+
+ // ------------------------
+ // Create a PropSet locally
+ // ------------------------
+
+ // Create a local IPropertySetStorage
+
+ hr = StgCreateDocfile( m_pwszDocFileName,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L,
+ &pstg );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Failed open of local DocFile") );
+
+ hr = StgCreatePropSetStg( pstg, 0L, &ppsstg );
+ if( FAILED(hr) ) ERROR_EXIT( TEXT("Couldn't create local IPropertySetStorage") );
+
+ // Create an IPropertyStorage
+
+ hr = ppsstg->Create( IID_IDocFileMarshal, NULL,
+ PROPSETFLAG_ANSI | PROPSETFLAG_NONSIMPLE,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &ppstg );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't create a local IPropertyStorage") );
+ RELEASE_INTERFACE( ppsstg );
+
+ // Write properties to it and close it.
+
+ hr = WriteProperties( ppstg, FALSE /* Not Marshaled */ );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Failed to write properties to local PropStg") );
+
+ RELEASE_INTERFACE( ppstg );
+ RELEASE_INTERFACE( pstg );
+
+ // -----------------------------------------
+ // Verify the properties through a marshaled
+ // IPropertySetStorage
+ // -----------------------------------------
+
+ // Get a remote IPropertySetStorage
+
+ Status( TEXT("Starting Server") );
+ hr = CoCreateInstance( IID_IDocFileMarshal,
+ NULL,
+ CLSCTX_LOCAL_SERVER,
+ IID_IDocFileMarshal,
+ (void **)&pdfm );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Failed CoCreateInstance") );
+
+ Status( TEXT("Requesting remote IPropertySetStorage") );
+ hr = pdfm->StgOpenPropSetStg( m_pwszDocFileName,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &ppsstg );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Failed to open remote PropSetStg") );
+
+ // Get an IPropertyStorage
+
+ hr = ppsstg->Open( IID_IDocFileMarshal,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &ppstg );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't create a local IPropertyStorage") );
+ RELEASE_INTERFACE( ppsstg );
+
+ // Read from the marshalled Storage and compare the properties against
+ // the local copy we kept.
+
+ Status( TEXT("Reading/verifying properties from marshalled IPropertySetStorage") );
+ hr = ReadAndCompareProperties( ppstg, TRUE /* Marshaled */ );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Failed marshalled read and compare") );
+
+ // Remove the existing properties via the marhsalled interface, and
+ // re-write them.
+
+ hr = DeleteProperties( ppstg, TRUE /* Marshaled */ );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't delete properties from remote IPropertySetStorage") );
+
+ // Write the properties back to the remote storage.
+
+ Status( TEXT("Writing properties through marshalled IPropertySetStorage") );
+ hr = WriteProperties( ppstg, TRUE /* Marshaled */ );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't write properties to remote Storage") );
+ RELEASE_INTERFACE( ppstg );
+
+
+ // -----------------------------------------
+ // Verify the properties through a marshaled
+ // IPropertyStorage
+ // -----------------------------------------
+
+ // Get a remote IPropertyStorage
+
+ Status( TEXT("Requesting remote IPropertyStorage") );
+ hr = pdfm->StgOpenPropStg( m_pwszDocFileName,
+ IID_IDocFileMarshal,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &ppstg );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Failed to open remote PropStg") );
+
+ // Read from the marshalled Storage and compare the properties against
+ // the local copy we kept.
+
+ Status( TEXT("Reading/verifying properties from marshalled IPropertyStorage") );
+ hr = ReadAndCompareProperties( ppstg, TRUE /* Marshaled */ );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Failed marshalled read and compare") );
+
+ // Remove the existing properties via the marhsalled interface, and
+ // re-write them.
+
+ hr = DeleteProperties( ppstg, TRUE /* Marshaled */ );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't delete properties from remote Storage") );
+
+ // Write the properties back to the remote storage.
+
+ Status( TEXT("Writing properties through marshalled IPropertyStorage") );
+ hr = WriteProperties( ppstg, TRUE /* Marshaled */ );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't write properties to remote Storage") );
+
+ RELEASE_INTERFACE( ppstg );
+ RELEASE_INTERFACE( pdfm );
+
+ // --------------------------------
+ // Re-verify the properties locally
+ // --------------------------------
+
+ // Re-open the DocFile locally.
+
+ hr = StgOpenStorage( m_pwszDocFileName,
+ NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0,
+ &pstg );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't re-open the DocFile locally") );
+
+
+ hr = StgCreatePropSetStg( pstg, 0L, &ppsstg );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't create IPropertySetStorage on local DocFile") );
+
+ hr = ppsstg->Open( IID_IDocFileMarshal,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &ppstg );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Couldn't open load IPropertyStorage") );
+ RELEASE_INTERFACE( ppsstg );
+
+ // Compare the properties in the property set, which we wrote through
+ // the marshalled interface, against what they should be.
+
+ Status( TEXT("Reading/verifying properties from local IPropertyStorage") );
+ hr = ReadAndCompareProperties( ppstg, FALSE /* Not Marshaled */ );
+ if(FAILED(hr)) ERROR_EXIT( TEXT("Properties written through marshalled interface do not appear correct") );
+
+ RELEASE_INTERFACE( ppstg );
+ RELEASE_INTERFACE( pstg );
+
+Exit:
+
+ RELEASE_INTERFACE( pstg );
+ RELEASE_INTERFACE( ppsstg );
+ RELEASE_INTERFACE( ppstg );
+ RELEASE_INTERFACE( pdfm );
+
+ return( hr );
+
+}
+
+
+
+HRESULT CPropStgMarshalTest::WriteProperties( IPropertyStorage *ppstg, BOOL fMarshaled )
+{
+ HRESULT hr = E_FAIL;
+
+ // If this is a local IPropertyStorage, or we're marshaling with
+ // OLE32, we can just write all the properties
+
+ if( !fMarshaled || !g_SystemInfo.fIPropMarshaling )
+ {
+ hr = ppstg->WriteMultiple( m_cAllProperties, m_rgpropspec, m_rgpropvar, PID_FIRST_USABLE );
+ if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed WriteMultiple") );
+ }
+
+ // Otherwise we're marshaling through IProp.DLL, which doesn't support
+ // non-simple property marshaling. So, let's verify that we can
+ // write simple but only simple properties.
+
+ else
+ {
+ // We should get an error attempting to write all (including
+ // non-simple) properties.
+
+ hr = ppstg->WriteMultiple( m_cAllProperties, m_rgpropspec, m_rgpropvar, PID_FIRST_USABLE );
+ if( RPC_E_CLIENT_CANTMARSHAL_DATA != hr )
+ {
+ hr = E_FAIL;
+ ERROR_EXIT( TEXT("Failed WriteMultiple") );
+ }
+
+ // But we should be able to write the simple properties.
+ hr = ppstg->WriteMultiple( m_cSimpleProperties, m_rgpropspec, m_rgpropvar, PID_FIRST_USABLE );
+ if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed WriteMultiple") );
+ }
+
+
+ // ----
+ // Exit
+ // ----
+
+ hr = S_OK;
+
+Exit:
+
+ return( hr );
+
+}
+
+
+
+HRESULT CPropStgMarshalTest::ReadAndCompareProperties( IPropertyStorage *ppstg, BOOL fMarshaled )
+{
+ HRESULT hr = E_FAIL;
+ ULONG cProperties;
+ int i;
+
+ // Allocate a PROPVARIANT[] into which we can read the
+ // properties
+
+ PROPVARIANT *rgpropvar = new PROPVARIANT[ m_cAllProperties ];
+ if( NULL == rgpropvar )
+ {
+ hr = E_OUTOFMEMORY;
+ goto Exit;
+ }
+
+
+ // If we're marshaling via IProp.DLL, we can't read
+ // the non-simple properties. In addition to reading the
+ // simple properties, let's validate that we get a marshaling error
+ // on an attempt to read the non-simples.
+
+ if( fMarshaled && g_SystemInfo.fIPropMarshaling )
+ {
+ cProperties = m_cSimpleProperties;
+
+ // Try to read all the properties, including the non-simples.
+ hr = ppstg->ReadMultiple( m_cAllProperties, m_rgpropspec, rgpropvar );
+ if( RPC_E_SERVER_CANTMARSHAL_DATA != hr )
+ {
+ hr = E_FAIL;
+ ERROR_EXIT( TEXT("Failed ReadMultiple") );
+ }
+
+ // Now read just the simple properties
+ hr = ppstg->ReadMultiple( cProperties, m_rgpropspec, rgpropvar );
+ if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed ReadMultiple") );
+
+ } // if( !fMarshaling || !g_SystemInfo.fIPropMarshaling ) ... else
+
+ // Otherwise we needn't look for the marshaling error, but there
+ // still may only be simple properties available
+
+ else
+ {
+ cProperties = m_cAllProperties;
+
+ // Read the properties
+ hr = ppstg->ReadMultiple( cProperties, m_rgpropspec, rgpropvar );
+ if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed ReadMultiple") );
+ }
+
+
+ // Compare the properties with what we expect.
+
+ for( i = 0; i < (int)cProperties; i++ )
+ {
+ hr = CPropVariant::Compare( &rgpropvar[i], &m_rgpropvar[i] );
+ if( S_OK != hr )
+ {
+ hr = E_FAIL;
+ ERROR_EXIT( TEXT("Property mismatch") );
+ }
+ }
+
+ // ----
+ // Exit
+ // ----
+
+ hr = S_OK;
+
+Exit:
+
+ if( NULL != rgpropvar )
+ {
+ FreePropVariantArray( m_cAllProperties, rgpropvar );
+ delete[]( rgpropvar );
+ }
+
+ return( hr );
+
+}
+
+
+
+HRESULT CPropStgMarshalTest::DeleteProperties( IPropertyStorage *ppstg, BOOL fMarshaled )
+{
+ HRESULT hr = E_FAIL;
+ ULONG cProperties;
+
+ if( fMarshaled && g_SystemInfo.fIPropMarshaling )
+ cProperties = m_cSimpleProperties;
+ else
+ cProperties = m_cAllProperties;
+
+ hr = ppstg->DeleteMultiple( cProperties, m_rgpropspec );
+ if( FAILED(hr) ) ERROR_EXIT( TEXT("Failed DeleteMultiple") );
+
+ hr = S_OK;
+
+Exit:
+
+ return( hr );
+
+}
diff --git a/private/ole32/stg/props/utest/propmshl.hxx b/private/ole32/stg/props/utest/propmshl.hxx
new file mode 100644
index 000000000..b07c8c46e
--- /dev/null
+++ b/private/ole32/stg/props/utest/propmshl.hxx
@@ -0,0 +1,63 @@
+
+
+#include <tchar.h> // for _tprintf
+
+class CPropStgMarshalTest
+{
+public:
+
+ CPropStgMarshalTest( );
+ ~CPropStgMarshalTest();
+
+public:
+
+ Init( OLECHAR *pwszDocFileName,
+ PROPVARIANT rgpropvar[],
+ PROPSPEC rgpropspec[],
+ ULONG cAllProperties,
+ ULONG cSimpleProperties );
+ Run();
+
+private:
+
+ void Status( LPCTSTR tsz )
+ {
+// wprintf( TEXT(" %s\n"), tsz );
+ }
+
+ void ErrorStatus( LPCTSTR tsz )
+ {
+ _tprintf( TEXT(" Error: %s\n"), tsz );
+ }
+
+ HRESULT DeleteProperties( IPropertyStorage *ppstg, BOOL fMarshaled );
+ HRESULT WriteProperties( IPropertyStorage *ppstg, BOOL fMarshaled );
+ HRESULT ReadAndCompareProperties( IPropertyStorage *ppstg, BOOL fMarshaled );
+
+private:
+
+ // The total number of propertie sin m_rgpropvar, and the
+ // number of those which are simple properties (all the non-simple
+ // properties are at the end of the array).
+
+ ULONG m_cAllProperties;
+ ULONG m_cSimpleProperties;
+
+ // The properties and propspecs
+
+ PROPSPEC *m_rgpropspec;
+ PROPVARIANT *m_rgpropvar;
+
+ // The file to work with.
+ OLECHAR *m_pwszDocFileName;
+
+ // Are we initialize?
+ BOOL m_fInitialized;
+
+
+};
+
+
+
+#define ERROR_EXIT(tsz) { ErrorStatus(tsz); goto Exit; }
+#define RELEASE_INTERFACE(punk) { if(punk != NULL) { punk->Release(); punk = NULL; }}
diff --git a/private/ole32/stg/props/utest/proptest.cxx b/private/ole32/stg/props/utest/proptest.cxx
new file mode 100644
index 000000000..15ae59492
--- /dev/null
+++ b/private/ole32/stg/props/utest/proptest.cxx
@@ -0,0 +1,2035 @@
+
+
+//+=================================================================
+//
+// File:
+// PropTest.cxx
+//
+// Description:
+// This file contains the main() and most supporting functions
+// for the PropTest command-line DRT. Run "PropTest /?" for
+// usage information.
+//
+//+=================================================================
+
+
+
+
+// tests to do:
+// IEnumSTATPROPSTG
+// Create some properties, named and id'd
+// Enumerate them and check
+// (check vt, lpwstrName, propid)
+// (check when asking for more than there is: S_FALSE, S_OK)
+// Delete one
+// Reset the enumerator
+// Enumerate them and check
+// Delete one
+//
+// Reset the enumeratorA
+// Read one from enumeratorA
+// Clone enumerator -> enumeratorB
+// Loop comparing rest of enumerator contents
+//
+// Reset the enumerator
+// Skip all
+// Check none left
+//
+// Reset the enumerator
+// Skip all but one
+// Check one left
+//
+// Check refcounting and IUnknown
+//
+// IPropertyStorage tests
+//
+// Multiple readers/writers access tests
+//
+
+
+//+----------------------------------------------------------------------------
+//
+// I n c l u d e s
+//
+//+----------------------------------------------------------------------------
+
+#include "pch.cxx" // Brings in most other includes/defines/etc.
+
+//#include <memory.h> //
+
+
+//+----------------------------------------------------------------------------
+//
+// G l o b a l s
+//
+//+----------------------------------------------------------------------------
+
+OLECHAR g_aocMap[CCH_MAP + 1] = OLESTR("abcdefghijklmnopqrstuvwxyz012345");
+
+const OLECHAR oszSummaryInformation[] = OLESTR("\005SummaryInformation");
+ULONG cboszSummaryInformation = sizeof(oszSummaryInformation);
+const OLECHAR oszDocSummaryInformation[] = OLESTR("\005DocumentSummaryInformation");
+ULONG cboszDocSummaryInformation = sizeof(oszDocSummaryInformation);
+const OLECHAR oszGlobalInfo[] = OLESTR("\005Global Info");
+ULONG cboszGlobalInfo = sizeof(oszGlobalInfo);
+const OLECHAR oszImageContents[] = OLESTR("\005Image Contents");
+ULONG cboszImageContents = sizeof(oszImageContents);
+const OLECHAR oszImageInfo[] = OLESTR("\005Image Info");
+ULONG cboszImageInfo = sizeof(oszImageInfo);
+
+
+// PictureIt! Format IDs
+
+const FMTID fmtidGlobalInfo =
+ { 0x56616F00,
+ 0xC154, 0x11ce,
+ { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
+
+const FMTID fmtidImageContents =
+ { 0x56616400,
+ 0xC154, 0x11ce,
+ { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
+
+const FMTID fmtidImageInfo =
+ { 0x56616500,
+ 0xC154, 0x11ce,
+ { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
+
+
+BOOL g_fOFS;
+LARGE_INTEGER g_li0;
+
+CPropVariant g_rgcpropvarAll[ CPROPERTIES_ALL ];
+CPropSpec g_rgcpropspecAll[ CPROPERTIES_ALL ];
+char g_szPropHeader[] = " propid/name propid cb type value\n";
+char g_szEmpty[] = "";
+BOOL g_fVerbose = FALSE;
+
+// This flag indicates whether or not the run-time system supports
+// IPropertySetStorage on the DocFile IStorage object.
+
+BOOL g_fQIPropertySetStorage = FALSE;
+
+
+// g_curUuid is used by UuidCreate(). Everycall to that function
+// returns the current value of g_curUuid, and increments the DWORD
+// field.
+
+GUID g_curUuid =
+{ /* e4ecf7f0-e587-11cf-b10d-00aa005749e9 */
+ 0xe4ecf7f0,
+ 0xe587,
+ 0x11cf,
+ {0xb1, 0x0d, 0x00, 0xaa, 0x00, 0x57, 0x49, 0xe9}
+};
+
+// Instantiate an object for the Marshaling tests
+
+#ifndef _MAC_NODOC
+CPropStgMarshalTest g_cpsmt;
+#endif
+
+// On the Mac, instantiate a CDisplay object, which is used
+// by these tests to write to the screen (see #define PRINTF).
+
+#ifdef _MAC
+CDisplay *g_pcDisplay;
+#endif
+
+// System information
+
+SYSTEMINFO g_SystemInfo;
+
+
+
+//+=================================================================
+//
+// Function: _Check
+//
+// Synopsis: Verify that the actual HR is the expected
+// value. If not, report an error and exit.
+//
+// Inputs: [HRESULT] hrExpected
+// What we expected
+// [HRESULT] hrActual
+// The actual HR of the previous operation.
+// [int] line
+// The line number of the operation.
+//
+// Outputs: None.
+//
+//+=================================================================
+
+void _Check(HRESULT hrExpected, HRESULT hrActual, LPCSTR szFile, int line)
+{
+ if (hrExpected != hrActual)
+ {
+ PRINTF("\nFailed with hr=%08x at line %d\n"
+ "in \"%s\"\n"
+ "(expected hr=%08x, GetLastError=%lu)\n",
+ hrActual, line, szFile, hrExpected, GetLastError() );
+
+ // On NT, we simply exit here. On the Mac, where PropTest is a function rather
+ // than a main(), we throw an exception so that the test may terminate somewhat
+ // cleanly.
+
+#ifdef _MAC
+ throw CHRESULT( hrActual, OLESTR("Fatal Error") );
+#else
+ exit(1);
+#endif
+
+ }
+}
+
+OLECHAR * GetNextTest()
+{
+ static int nTest;
+ static OLECHAR ocsBuf[10];
+
+ soprintf(ocsBuf, OLESTR("%d"), nTest++);
+
+ return(ocsBuf);
+}
+
+#ifndef _MAC // SYSTEMTIME isn't supported on the Mac.
+void Now(FILETIME *pftNow)
+{
+ SYSTEMTIME stStart;
+ GetSystemTime(&stStart);
+ SystemTimeToFileTime(&stStart, pftNow);
+}
+#endif
+
+
+IStorage *_pstgTemp;
+IStorage *_pstgTempCopyTo; // _pstgTemp is copied to _pstgTempCopyTo
+
+
+unsigned int CTempStorage::_iName;
+
+
+
+PROPVARIANT * CGenProps::GetNext(int HowMany, int *pActual, BOOL fWrapOk, BOOL fNoNonSimple)
+{
+ PROPVARIANT *pVar = new PROPVARIANT[HowMany];
+
+ if (pVar == NULL)
+ return(NULL);
+
+ for (int l=0; l<HowMany && _GetNext(pVar + l, fWrapOk, fNoNonSimple); l++) { };
+
+ if (pActual)
+ *pActual = l;
+
+ if (l == 0)
+ {
+ delete pVar;
+ return(NULL);
+ }
+
+ return(pVar);
+}
+
+BOOL CGenProps::_GetNext(PROPVARIANT *pVar, BOOL fWrapOk, BOOL fNoNonSimple)
+{
+ if (_vt == (VT_VECTOR | VT_CLSID)+1)
+ {
+ if (!fWrapOk)
+ return(FALSE);
+ else
+ _vt = (VARENUM)2;
+ }
+
+ PROPVARIANT Var;
+ BOOL fFirst = TRUE;
+
+ do
+ {
+ GUID *pg;
+
+ if (!fFirst)
+ {
+ PropVariantClear(&Var);
+ }
+
+ fFirst = FALSE;
+
+ memset(&Var, 0, sizeof(Var));
+ Var.vt = _vt;
+ (*((int*)&_vt))++;
+
+ switch (Var.vt)
+ {
+ case VT_LPSTR:
+ Var.pszVal = (LPSTR)CoTaskMemAlloc(6);
+ strcpy(Var.pszVal, "lpstr");
+ break;
+ case VT_LPWSTR:
+ Var.pwszVal = (LPWSTR)CoTaskMemAlloc(14);
+ wcscpy(Var.pwszVal, L"lpwstr");
+ break;
+ case VT_CLSID:
+ pg = (GUID*)CoTaskMemAlloc(sizeof(GUID));
+ UuidCreate(pg);
+ Var.puuid = pg;
+ break;
+ case VT_CF:
+ Var.pclipdata = (CLIPDATA*)CoTaskMemAlloc(sizeof(CLIPDATA));
+ Var.pclipdata->cbSize = 10;
+ Var.pclipdata->pClipData = (BYTE*)CoTaskMemAlloc(10);
+ Var.pclipdata->ulClipFmt = 0;
+ break;
+ }
+ } while ( (fNoNonSimple && (Var.vt == VT_STREAM || Var.vt == VT_STREAMED_OBJECT ||
+ Var.vt == VT_STORAGE || Var.vt == VT_STORED_OBJECT)) ||
+ // BUGBUG: BillMo, waiting on support in VicH's ntdll code. (RAID 13753)
+ Var.vt == (VT_VECTOR | VT_VARIANT) ||
+ Var.vt == (VT_VECTOR | VT_CF) ||
+ Var.vt == (VT_VECTOR | VT_BSTR) ||
+ (Var.vt & ~VT_VECTOR) == VT_BSTR_BLOB ||
+ S_OK != PropVariantCopy(pVar, &Var) ); // Is valid propvariant ?
+
+ PropVariantClear(&Var);
+
+ return(TRUE);
+}
+
+VOID
+CleanStat(ULONG celt, STATPROPSTG *psps)
+{
+ while (celt--)
+ {
+ CoTaskMemFree(psps->lpwstrName);
+ psps++;
+ }
+}
+
+
+//+----------------------------------------------------------------------------
+//
+// Function: PopulateRGPropVar
+//
+// Synopsis: This function fills an input array of PROPVARIANTs
+// with an assortment of properties.
+//
+// Note: For compatibility with the marshaling test, all
+// non-simple properties must be at the end of the array.
+//
+//+----------------------------------------------------------------------------
+
+
+HRESULT
+PopulateRGPropVar( CPropVariant rgcpropvar[],
+ CPropSpec rgcpropspec[],
+ IStorage *pstg )
+{
+ HRESULT hr = (HRESULT) E_FAIL;
+ int i;
+ ULONG ulPropIndex = 0;
+ CLIPDATA clipdataNull, clipdataNonNull;
+
+ // Initialize the PropVariants
+
+ for( i = 0; i < CPROPERTIES_ALL; i++ )
+ {
+ rgcpropvar[i].Clear();
+ }
+
+
+ // Create a UI1 property
+
+ rgcpropspec[ulPropIndex] = OLESTR( "UI1 Property" );
+ rgcpropvar[ulPropIndex] = (UCHAR) 39;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_UI1 );
+ ulPropIndex++;
+
+ // Create an I2 property
+
+ rgcpropspec[ulPropIndex] = OLESTR( "I2 Property" );
+ rgcpropvar[ulPropIndex] = (SHORT) -502;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_I2 );
+ ulPropIndex++;
+
+ // Create a UI2 property
+
+ rgcpropspec[ulPropIndex] = OLESTR( "UI2 Property" );
+ rgcpropvar[ulPropIndex] = (USHORT) 502;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_UI2 );
+ ulPropIndex++;
+
+ // Create a BOOL property
+
+ rgcpropspec[ulPropIndex] = OLESTR( "Bool Property" );
+ rgcpropvar[ulPropIndex].SetBOOL( VARIANT_TRUE );
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_BOOL );
+ ulPropIndex++;
+
+ // Create a I4 property
+
+ rgcpropspec[ulPropIndex] = OLESTR( "I4 Property" );
+ rgcpropvar[ulPropIndex] = (long) -523;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_I4 );
+ ulPropIndex++;
+
+ // Create a UI4 property
+
+ rgcpropspec[ulPropIndex] = OLESTR( "UI4 Property" );
+ rgcpropvar[ulPropIndex] = (ULONG) 530;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_UI4 );
+ ulPropIndex++;
+
+ // Create a R4 property
+
+ rgcpropspec[ulPropIndex] = OLESTR( "R4 Property" );
+ rgcpropvar[ulPropIndex] = (float) 5.37;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_R4 );
+ ulPropIndex++;
+
+ // Create an ERROR property
+
+ rgcpropspec[ulPropIndex] = OLESTR( "ERROR Property" );
+ rgcpropvar[ulPropIndex].SetERROR( STG_E_FILENOTFOUND );
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_ERROR );
+ ulPropIndex++;
+
+ // Create an I8 property
+
+ LARGE_INTEGER large_integer;
+ large_integer.LowPart = 551;
+ large_integer.HighPart = 30;
+ rgcpropspec[ulPropIndex] = OLESTR( "I8 Property" );
+ rgcpropvar[ulPropIndex] = large_integer;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_I8 );
+ ulPropIndex++;
+
+ // Create a UI8 property
+
+ ULARGE_INTEGER ularge_integer;
+ ularge_integer.LowPart = 561;
+ ularge_integer.HighPart = 30;
+ rgcpropspec[ulPropIndex] = OLESTR( "UI8 Property" );
+ rgcpropvar[ulPropIndex] = ularge_integer;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_UI8 );
+ ulPropIndex++;
+
+ // Create an R8 property
+
+ rgcpropspec[ulPropIndex] = OLESTR( "R8 Property" );
+ rgcpropvar[ulPropIndex] = (double) 571.36;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_R8 );
+ ulPropIndex++;
+
+ // Create a CY property
+
+ CY cy;
+ cy.Hi = 123;
+ cy.Lo = 456;
+ rgcpropspec[ulPropIndex] = OLESTR( "Cy Property" );
+ rgcpropvar[ulPropIndex] = cy;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_CY );
+ ulPropIndex++;
+
+ // Create a DATE property
+
+ rgcpropspec[ulPropIndex] = OLESTR( "DATE Property" );
+ rgcpropvar[ulPropIndex].SetDATE( 587 );
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_DATE );
+ ulPropIndex++;
+
+ // Create a FILETIME property
+
+ FILETIME filetime;
+ filetime.dwLowDateTime = 0x767c0570;
+ filetime.dwHighDateTime = 0x1bb7ecf;
+ rgcpropspec[ulPropIndex] = OLESTR( "FILETIME Property" );
+ rgcpropvar[ulPropIndex] = filetime;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_FILETIME );
+ ulPropIndex++;
+
+ // Create a CLSID property
+
+ rgcpropspec[ulPropIndex] = OLESTR( "CLSID Property" );
+ rgcpropvar[ulPropIndex] = FMTID_SummaryInformation;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_CLSID );
+ ulPropIndex++;
+
+ // Create a vector of CLSIDs
+
+ rgcpropspec[ulPropIndex] = OLESTR( "CLSID Vector Property" );
+ rgcpropvar[ulPropIndex][0] = FMTID_SummaryInformation;
+ rgcpropvar[ulPropIndex][1] = FMTID_DocSummaryInformation;
+ rgcpropvar[ulPropIndex][2] = FMTID_UserDefinedProperties;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_CLSID | VT_VECTOR );
+ ulPropIndex++;
+
+ // Create a BSTR property
+
+ rgcpropspec[ulPropIndex] = OLESTR("BSTR");
+ rgcpropvar[ulPropIndex].SetBSTR( OLESTR("BSTR Value") );
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_BSTR );
+ ulPropIndex++;
+
+ // Create a BSTR Vector property
+
+ rgcpropspec[ulPropIndex] = OLESTR("BSTR Vector");
+ for( i = 0; i < 3; i++ )
+ {
+ OLECHAR olestrElement[] = OLESTR("# - BSTR Vector Element");
+ olestrElement[0] = (OLECHAR) i%10 + OLESTR('0');
+ rgcpropvar[ulPropIndex].SetBSTR( olestrElement, i );
+ }
+
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == (VT_BSTR | VT_VECTOR) );
+ ulPropIndex++;
+
+ // Create a variant vector BSTR property.
+
+ rgcpropspec[ulPropIndex ] = OLESTR("BSTR Variant Vector");
+
+ for( i = 0; i < 3; i++ )
+ {
+ if( i == 0 )
+ {
+ rgcpropvar[ulPropIndex][0] = (PROPVARIANT*) CPropVariant((long) 0x1234);
+ }
+ else
+ {
+ CPropVariant cpropvarBSTR;
+ cpropvarBSTR.SetBSTR( OLESTR("# - Vector Variant BSTR") );
+ (cpropvarBSTR.GetBSTR())[0] = (OLECHAR) i%10 + OLESTR('0');
+ rgcpropvar[ulPropIndex][i] = (PROPVARIANT*) cpropvarBSTR;
+ }
+ }
+
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == (VT_VARIANT | VT_VECTOR) );
+ ulPropIndex++;
+
+ // Create an LPSTR property
+
+ rgcpropspec[ulPropIndex] = OLESTR("LPSTR Property");
+ rgcpropvar[ulPropIndex] = "LPSTR Value";
+
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_LPSTR );
+ ulPropIndex++;
+
+ // Create some ClipFormat properties
+
+ rgcpropspec[ ulPropIndex ] = OLESTR("ClipFormat property");
+ rgcpropvar[ ulPropIndex ] = CClipData( L"Clipboard Data" );
+ ASSERT( rgcpropvar[ ulPropIndex ].VarType() == VT_CF );
+ ulPropIndex++;
+
+ rgcpropspec[ ulPropIndex ] = OLESTR("Empty ClipFormat property (NULL pointer)");
+ clipdataNull.cbSize = 4;
+ clipdataNull.ulClipFmt = (ULONG) -1;
+ clipdataNull.pClipData = NULL;
+ rgcpropvar[ ulPropIndex ] = clipdataNull;
+ ASSERT( rgcpropvar[ ulPropIndex ].VarType() == VT_CF );
+ ulPropIndex++;
+
+ rgcpropspec[ ulPropIndex ] = OLESTR("Empty ClipFormat property (non-NULL pointer)");
+ clipdataNonNull.cbSize = 4;
+ clipdataNonNull.ulClipFmt = (ULONG) -1;
+ clipdataNonNull.pClipData = (BYTE*) CoTaskMemAlloc(0);
+ rgcpropvar[ ulPropIndex ] = clipdataNonNull;
+ ASSERT( rgcpropvar[ ulPropIndex ].VarType() == VT_CF );
+ ulPropIndex++;
+
+ // Create a vector of ClipFormat properties
+
+ CClipData cclipdataEmpty;
+ cclipdataEmpty.Set( (ULONG) -1, "", 0 );
+
+ rgcpropspec[ ulPropIndex ] = OLESTR("ClipFormat Array Property");
+ rgcpropvar[ ulPropIndex ][0] = CClipData( L"Clipboard Date element 1" );
+ rgcpropvar[ ulPropIndex ][1] = cclipdataEmpty;
+ rgcpropvar[ ulPropIndex ][2] = clipdataNull;
+ rgcpropvar[ ulPropIndex ][3] = clipdataNonNull;
+ rgcpropvar[ ulPropIndex ][4] = CClipData( L"Clipboard Date element 2" );
+
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == (VT_CF | VT_VECTOR) );
+ ASSERT( rgcpropvar[ulPropIndex].Count() == 5 );
+ ulPropIndex++;
+
+ // Create an LPSTR|Vector property (e.g., the DocSumInfo
+ // Document Parts array).
+
+ rgcpropspec[ ulPropIndex ] = OLESTR("LPSTR|Vector property");
+ rgcpropvar[ ulPropIndex ][0] = "LPSTR Element 0";
+ rgcpropvar[ ulPropIndex ][1] = "LPSTR Element 1";
+
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == (VT_LPSTR | VT_VECTOR) );
+ ulPropIndex++;
+
+ // Create an LPWSTR|Vector property
+
+ rgcpropspec[ ulPropIndex ] = OLESTR("LPWSTR|Vector property");
+ rgcpropvar[ ulPropIndex ][0] = L"LPWSTR Element 0";
+ rgcpropvar[ ulPropIndex ][1] = L"LPWSTR Element 1";
+
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == (VT_LPWSTR | VT_VECTOR) );
+ ulPropIndex++;
+
+ // Create a DocSumInfo HeadingPairs array.
+
+ rgcpropspec[ ulPropIndex ] = OLESTR("HeadingPair array");
+
+ rgcpropvar[ ulPropIndex ][0] = (PROPVARIANT*) CPropVariant( "Heading 0" );
+ rgcpropvar[ ulPropIndex ][1] = (PROPVARIANT*) CPropVariant( (long) 1 );
+ rgcpropvar[ ulPropIndex ][2] = (PROPVARIANT*) CPropVariant( "Heading 1" );
+ rgcpropvar[ ulPropIndex ][1] = (PROPVARIANT*) CPropVariant( (long) 1 );
+
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == (VT_VARIANT | VT_VECTOR) );
+ ulPropIndex++;
+
+ // Create some NULL (but extant) properties
+
+ rgcpropspec[ulPropIndex] = OLESTR("Empty LPSTR");
+ rgcpropvar[ulPropIndex] = "";
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_LPSTR );
+ ulPropIndex++;
+
+ rgcpropspec[ulPropIndex] = OLESTR("Empty LPWSTR");
+ rgcpropvar[ulPropIndex] = L"";
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_LPWSTR );
+ ulPropIndex++;
+
+ rgcpropspec[ulPropIndex] = OLESTR("Empty BLOB");
+ rgcpropvar[ulPropIndex] = CBlob(0);
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_BLOB );
+ ulPropIndex++;
+
+ rgcpropspec[ulPropIndex] = OLESTR("Empty BSTR");
+ rgcpropvar[ulPropIndex].SetBSTR( OLESTR("") );
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_BSTR );
+ ulPropIndex++;
+
+ // Create some NULL (and non-extant) properties
+
+ rgcpropspec[ulPropIndex] = OLESTR("NULL BSTR");
+ ((PROPVARIANT*)&rgcpropvar[ulPropIndex])->vt = VT_BSTR;
+ ((PROPVARIANT*)&rgcpropvar[ulPropIndex])->bstrVal = NULL;
+ ulPropIndex++;
+
+ /* BUGBUG: Fix support for these and put them back in
+ rgcpropspec[ulPropIndex] = OLESTR("NULL LPSTR");
+ ((PROPVARIANT*)&rgcpropvar[ulPropIndex])->vt = VT_LPSTR;
+ ((PROPVARIANT*)&rgcpropvar[ulPropIndex])->pszVal = NULL;
+ ulPropIndex++;
+
+ rgcpropspec[ulPropIndex] = OLESTR("NULL LPWSTR");
+ ((PROPVARIANT*)&rgcpropvar[ulPropIndex])->vt = VT_LPWSTR;
+ ((PROPVARIANT*)&rgcpropvar[ulPropIndex])->pwszVal = NULL;
+ ulPropIndex++;
+ */
+
+ rgcpropspec[ulPropIndex] = OLESTR("BSTR Vector with NULL element");
+ rgcpropvar[ulPropIndex].SetBSTR( NULL, 0 );
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_VECTOR | VT_BSTR );
+ ulPropIndex++;
+
+ /*
+ rgcpropspec[ulPropIndex] = OLESTR("LPSTR Vector with NULL element");
+ rgcpropvar[ulPropIndex].SetLPSTR( NULL, 0 );
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_VECTOR | VT_LPSTR );
+ ulPropIndex++;
+ */
+
+
+ // Create an IStream property
+
+ IStream *pstmProperty = NULL;
+ Check(S_OK, pstg->CreateStream( OLESTR("Stream Property"),
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L, 0L,
+ &pstmProperty ));
+ Check(S_OK, pstmProperty->Write("Hi There",
+ sizeof("Hi There"),
+ NULL ));
+
+ rgcpropspec[ ulPropIndex ] = OLESTR("Stream Property");
+ rgcpropvar[ ulPropIndex ] = pstmProperty;
+ pstmProperty->Release();
+ pstmProperty = NULL;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_STREAM );
+ ulPropIndex++;
+
+ // Create an IStorage property
+
+ IStorage *pstgProperty = NULL;
+ Check(S_OK, pstg->CreateStorage( OLESTR("Storage Property"),
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L, 0L,
+ &pstgProperty ));
+
+ rgcpropspec[ ulPropIndex ] = OLESTR("Storage Property");
+ rgcpropvar[ ulPropIndex ] = pstgProperty;
+ pstgProperty->Release();
+ pstgProperty = NULL;
+ ASSERT( rgcpropvar[ulPropIndex].VarType() == VT_STORAGE );
+ ulPropIndex++;
+
+
+ // ----
+ // Exit
+ // ----
+
+ CoTaskMemFree( clipdataNonNull.pClipData );
+ memset( &clipdataNonNull, 0, sizeof(clipdataNonNull) );
+
+ ASSERT( CPROPERTIES_ALL == ulPropIndex );
+ hr = S_OK;
+ return(hr);
+
+}
+
+
+
+
+FILETIME operator - ( const FILETIME &ft1, const FILETIME &ft2 )
+{
+ FILETIME ftDiff;
+
+ if( ft1 < ft2 )
+ {
+ ftDiff.dwLowDateTime = 0;
+ ftDiff.dwHighDateTime = 0;
+ }
+
+ else if( ft1.dwLowDateTime >= ft2.dwLowDateTime )
+ {
+ ftDiff.dwLowDateTime = ft1.dwLowDateTime - ft2.dwLowDateTime;
+ ftDiff.dwHighDateTime = ft1.dwHighDateTime - ft2.dwHighDateTime;
+ }
+ else
+ {
+ ftDiff.dwLowDateTime = ft1.dwLowDateTime - ft2.dwLowDateTime;
+ ftDiff.dwLowDateTime = (DWORD) -1 - ftDiff.dwLowDateTime;
+
+ ftDiff.dwHighDateTime = ft1.dwHighDateTime - ft2.dwHighDateTime - 1;
+ }
+
+ return( ftDiff );
+}
+
+FILETIME operator -= ( FILETIME &ft1, const FILETIME &ft2 )
+{
+ ft1 = ft1 - ft2;
+ return( ft1 );
+}
+
+
+
+
+void CheckTime(const FILETIME &ftStart, const FILETIME &ftPropSet)
+{
+ FILETIME ftNow;
+ CoFileTimeNow(&ftNow);
+
+ if (ftPropSet.dwLowDateTime == 0 && ftPropSet.dwHighDateTime == 0)
+ {
+ return;
+ }
+
+ // if ftPropSet < ftStart || ftNow < ftPropSet, error
+ if (!g_fOFS)
+ ASSERT( ftStart <= ftPropSet
+ &&
+ ftPropSet <= ftNow );
+}
+
+
+void
+CheckStat( IPropertyStorage *pPropSet, REFFMTID fmtid,
+ REFCLSID clsid, ULONG PropSetFlag,
+ const FILETIME & ftStart, DWORD dwOSVersion )
+{
+ STATPROPSETSTG StatPropSetStg;
+ Check(S_OK, pPropSet->Stat(&StatPropSetStg));
+
+ Check(TRUE, StatPropSetStg.fmtid == fmtid);
+ Check(TRUE, StatPropSetStg.clsid == clsid);
+ Check(TRUE, StatPropSetStg.grfFlags == PropSetFlag);
+ Check(TRUE, StatPropSetStg.dwOSVersion == dwOSVersion);
+ CheckTime(ftStart, StatPropSetStg.mtime);
+ CheckTime(ftStart, StatPropSetStg.ctime);
+ CheckTime(ftStart, StatPropSetStg.atime);
+}
+
+
+BOOL
+IsEqualSTATPROPSTG(const STATPROPSTG *p1, const STATPROPSTG *p2)
+{
+ BOOL f1 = p1->propid == p2->propid;
+ BOOL f2 = p1->vt == p2->vt;
+ BOOL f3 = (p1->lpwstrName == NULL && p2->lpwstrName == NULL) ||
+ ((p1->lpwstrName != NULL && p2->lpwstrName != NULL) &&
+ ocscmp(p1->lpwstrName, p2->lpwstrName) == 0);
+ return(f1 && f2 && f3);
+}
+
+
+void
+CreateCodePageTestFile( LPOLESTR poszFileName, IStorage **ppStg )
+{
+ ASSERT( poszFileName != NULL );
+
+ // --------------
+ // Initialization
+ // --------------
+
+ TSafeStorage< IPropertySetStorage > pPSStg;
+ TSafeStorage< IPropertyStorage > pPStg;
+
+ PROPSPEC propspec;
+ CPropVariant cpropvar;
+
+ *ppStg = NULL;
+
+ // Create the Docfile.
+
+ Check(S_OK, StgCreateDocfile( poszFileName,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0,
+ ppStg ));
+
+ // Get an IPropertySetStorage
+
+// Check(S_OK, (*ppStg)->QueryInterface( IID_IPropertySetStorage, (void**)&pPSStg ));
+ Check(S_OK, StgCreatePropSetStg( *ppStg, 0L, &pPSStg ));
+
+ // Create an IPropertyStorage
+
+ Check(S_OK, pPSStg->Create( FMTID_NULL,
+ NULL,
+ PROPSETFLAG_ANSI,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPStg ));
+
+ // ----------------------
+ // Write a named property
+ // ----------------------
+
+ // Write a named I4 property
+
+ propspec.ulKind = PRSPEC_LPWSTR;
+ propspec.lpwstr = CODEPAGE_TEST_NAMED_PROPERTY;
+
+ cpropvar = (LONG) 0x12345678;
+ Check(S_OK, pPStg->WriteMultiple( 1, &propspec, cpropvar, PID_FIRST_USABLE ));
+
+ // --------------------------
+ // Write singleton properties
+ // --------------------------
+
+ // Write an un-named BSTR.
+
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = CODEPAGE_TEST_UNNAMED_BSTR_PROPID;
+
+ cpropvar.SetBSTR( OLESTR("BSTR Property") );
+ Check(S_OK, pPStg->WriteMultiple( 1, &propspec, cpropvar, PID_FIRST_USABLE ));
+
+ // Write an un-named I4
+
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = CODEPAGE_TEST_UNNAMED_I4_PROPID;
+
+ cpropvar = (LONG) 0x76543210;
+ Check(S_OK, pPStg->WriteMultiple( 1, &propspec, cpropvar, PID_FIRST_USABLE ));
+
+ // -----------------------
+ // Write vector properties
+ // -----------------------
+
+ // Write a vector of BSTRs.
+
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = CODEPAGE_TEST_VBSTR_PROPID;
+
+ cpropvar.SetBSTR( OLESTR("BSTR Element 1"), 1 );
+ cpropvar.SetBSTR( OLESTR("BSTR Element 0"), 0 );
+ ASSERT( (VT_VECTOR | VT_BSTR) == cpropvar.VarType() );
+ Check(S_OK, pPStg->WriteMultiple( 1, &propspec, cpropvar, PID_FIRST_USABLE ));
+
+ // -------------------------------
+ // Write Variant Vector Properties
+ // -------------------------------
+
+ // Write a variant vector that has a BSTR
+
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = CODEPAGE_TEST_VPROPVAR_BSTR_PROPID;
+
+ CPropVariant cpropvarT;
+ cpropvarT.SetBSTR( OLESTR("PropVar Vector BSTR") );
+ cpropvar[1] = (LPPROPVARIANT) cpropvarT;
+ cpropvar[0] = (LPPROPVARIANT) CPropVariant((long) 44);
+ ASSERT( (VT_VARIANT | VT_VECTOR) == cpropvar.VarType() );
+ Check(S_OK, pPStg->WriteMultiple( 1, &propspec, cpropvar, PID_FIRST_USABLE ));
+
+} // CreateCodePageTestFile()
+
+
+void
+ModifyPropSetCodePage( IStorage *pStg, USHORT usCodePage )
+{
+
+ ASSERT( pStg != NULL );
+
+ // --------------
+ // Initialization
+ // --------------
+
+ OLECHAR aocPropSetName[ 32 ];
+ DWORD dwOffset = 0;
+ DWORD dwcbSection = 0;
+ DWORD dwcProperties = 0;
+ ULONG ulcbWritten = 0;
+
+ LARGE_INTEGER liSectionOffset, liCodePageOffset;
+
+ TSafeStorage< IStream > pStm;
+
+ CPropVariant cpropvar;
+
+ // Open the Stream
+
+ RtlGuidToPropertySetName( &FMTID_NULL, aocPropSetName );
+ Check(S_OK, pStg->OpenStream( aocPropSetName,
+ NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ &pStm ));
+
+
+
+ // Seek past the propset header and the format ID.
+
+ liSectionOffset.HighPart = 0;
+ liSectionOffset.LowPart = sizeof(PROPERTYSETHEADER) + sizeof(FMTID);
+ Check(S_OK, pStm->Seek(liSectionOffset, STREAM_SEEK_SET, NULL ));
+
+ // Move to the beginning of the property set.
+
+ liSectionOffset.HighPart = 0;
+ Check(S_OK, pStm->Read( &liSectionOffset.LowPart, sizeof(DWORD), NULL ));
+ PropByteSwap(&liSectionOffset.LowPart);
+ Check(S_OK, pStm->Seek( liSectionOffset, STREAM_SEEK_SET, NULL ));
+
+ // Get the section size & property count.
+
+ Check(S_OK, pStm->Read( &dwcbSection, sizeof(DWORD), NULL ));
+ PropByteSwap( &dwcbSection );
+
+ Check(S_OK, pStm->Read( &dwcProperties, sizeof(DWORD), NULL ));
+ PropByteSwap( &dwcProperties );
+
+ // Scan for the PID_CODEPAGE property.
+
+ for( ULONG ulIndex = 0; ulIndex < dwcProperties; ulIndex++ )
+ {
+ PROPID propid;
+ DWORD dwOffset;
+
+ // Read in the PROPID
+ Check(S_OK, pStm->Read( &propid, sizeof(PROPID), NULL ));
+
+ // Is it the codepage?
+ if( PropByteSwap(propid) == PID_CODEPAGE )
+ break;
+
+ // Read in this PROPIDs offset (we don't need it, but we want
+ // to seek past it.
+ Check(S_OK, pStm->Read( &dwOffset, sizeof(dwOffset), NULL ));
+ }
+
+ // Verify that the above for loop terminated because we found
+ // the codepage.
+ Check( TRUE, ulIndex < dwcProperties );
+
+ // Move to the code page.
+
+ liCodePageOffset.HighPart = 0;
+ Check(S_OK, pStm->Read( &liCodePageOffset.LowPart, sizeof(DWORD), NULL ));
+ PropByteSwap( &liCodePageOffset.LowPart );
+
+ liCodePageOffset.LowPart += liSectionOffset.LowPart + sizeof(ULONG); // Move past VT too.
+ ASSERT( liSectionOffset.HighPart == 0 );
+
+ Check(S_OK, pStm->Seek( liCodePageOffset, STREAM_SEEK_SET, NULL ));
+
+ // Write the new code page.
+
+ PropByteSwap( &usCodePage );
+ Check(S_OK, pStm->Write( &usCodePage, sizeof(usCodePage), &ulcbWritten ));
+ Check(TRUE, ulcbWritten == sizeof(usCodePage) );
+
+} // ModifyPropSetCodePage()
+
+
+
+void
+ModifyOSVersion( IStorage* pStg, DWORD dwOSVersion )
+{
+
+ ASSERT( pStg != NULL );
+
+ // --------------
+ // Initialization
+ // --------------
+
+ OLECHAR aocPropSetName[ 32 ];
+ ULONG ulcbWritten = 0;
+
+ LARGE_INTEGER liOffset;
+ TSafeStorage< IStream > pStm;
+
+ // Open the Stream
+
+ RtlGuidToPropertySetName( &FMTID_NULL, aocPropSetName );
+ Check(S_OK, pStg->OpenStream( aocPropSetName,
+ NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ &pStm ));
+
+
+ // Seek to the OS Version field in the header.
+
+ liOffset.HighPart = 0;
+ liOffset.LowPart = sizeof(WORD) /*(byte-order)*/ + sizeof(WORD) /*(format)*/ ;
+ Check(S_OK, pStm->Seek( liOffset, STREAM_SEEK_SET, NULL ));
+
+ // Set the new OS Version
+
+ PropByteSwap( &dwOSVersion );
+ Check(S_OK, pStm->Write( &dwOSVersion, sizeof(dwOSVersion), &ulcbWritten ));
+ Check(TRUE, ulcbWritten == sizeof(dwOSVersion) );
+
+
+} // ModifyOSVersion()
+
+
+
+//+---------------------------------------------------------
+//
+// Function: MungePropertyStorage
+//
+// Synopsis: This routine munges the properties in a
+// Property Storage. The values of the properties
+// remain the same, but the underlying serialization
+// is new (the properties are read, the property
+// storage is deleted, and the properties are
+// re-written).
+//
+// Inputs: [IPropertySetStorage*] ppropsetgstg (in)
+// The Property Storage container.
+// [FMTID] fmtid
+// The Property Storage to munge.
+//
+// Returns: None.
+//
+// Note: Property names in the dictionary for which
+// there is no property are not munged.
+//
+//+---------------------------------------------------------
+
+#define MUNGE_PROPVARIANT_STEP 10
+
+void
+MungePropertyStorage( IPropertySetStorage *ppropsetstg,
+ FMTID fmtid )
+{
+ // ------
+ // Locals
+ // ------
+
+ HRESULT hr;
+ ULONG celt, ulIndex;
+ TSafeStorage< IPropertyStorage > ppropstg;
+
+ IEnumSTATPROPSTG *penumstatpropstg;
+
+ PROPVARIANT *rgpropvar = NULL;
+ STATPROPSTG *rgstatpropstg = NULL;
+ ULONG cProperties = 0;
+
+ // Allocate an array of PropVariants. We may grow this later.
+ rgpropvar = (PROPVARIANT*) CoTaskMemAlloc( MUNGE_PROPVARIANT_STEP * sizeof(*rgpropvar) );
+ Check( FALSE, NULL == rgpropvar );
+
+ // Allocate an array of STATPROPSTGs. We may grow this also.
+ rgstatpropstg = (STATPROPSTG*) CoTaskMemAlloc( MUNGE_PROPVARIANT_STEP * sizeof(*rgstatpropstg) );
+ Check( FALSE, NULL == rgstatpropstg );
+
+ // -----------------
+ // Get an Enumerator
+ // -----------------
+
+ // Open the Property Storage. We may get an error if we're attempting
+ // the UserDefined propset. If it's file-not-found, then simply return,
+ // it's not an error, and there's nothing to do.
+
+ hr = ppropsetstg->Open( fmtid,
+ STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &ppropstg );
+ if( FMTID_UserDefinedProperties == fmtid
+ &&
+ (HRESULT) STG_E_FILENOTFOUND == hr )
+ {
+ goto Exit;
+ }
+ Check( S_OK, hr );
+
+ // Get an Enumerator
+ Check(S_OK, ppropstg->Enum( &penumstatpropstg ));
+
+
+ // --------------------------------------------
+ // Read & delete in all of the properties/names
+ // --------------------------------------------
+
+ // Get the first property from the enumerator
+ hr = penumstatpropstg->Next( 1, &rgstatpropstg[cProperties], &celt );
+ Check( TRUE, (HRESULT) S_OK == hr || (HRESULT) S_FALSE == hr );
+
+ // Iterate through the properties.
+ while( celt > 0 )
+ {
+ PROPSPEC propspec;
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = rgstatpropstg[cProperties].propid;
+
+ // Read and delete the property
+
+ Check(S_OK, ppropstg->ReadMultiple( 1, &propspec, &rgpropvar[cProperties] ));
+ Check(S_OK, ppropstg->DeleteMultiple( 1, &propspec ));
+
+ // If there is a property name, delete it also.
+
+ if( NULL != rgstatpropstg[cProperties].lpwstrName )
+ {
+ // We have a name.
+ Check(S_OK, ppropstg->DeletePropertyNames( 1, &rgstatpropstg[cProperties].propid ));
+ }
+
+ // Increment the property count.
+ cProperties++;
+
+ // Do we need to grow the arrays?
+
+ if( 0 != cProperties
+ &&
+ (cProperties % MUNGE_PROPVARIANT_STEP) == 0 )
+ {
+ // Yes - they must be reallocated.
+
+ rgpropvar = (PROPVARIANT*)
+ CoTaskMemRealloc( rgpropvar,
+ ( (cProperties + MUNGE_PROPVARIANT_STEP)
+ *
+ sizeof(*rgpropvar)
+ ));
+ Check( FALSE, NULL == rgpropvar );
+
+ rgstatpropstg = (STATPROPSTG*)
+ CoTaskMemRealloc( rgstatpropstg,
+ ( (cProperties + MUNGE_PROPVARIANT_STEP)
+ *
+ sizeof(*rgstatpropstg)
+ ));
+ Check( FALSE, NULL == rgstatpropstg );
+ }
+
+ // Move on to the next property.
+ hr = penumstatpropstg->Next( 1, &rgstatpropstg[cProperties], &celt );
+ Check( TRUE, (HRESULT) S_OK == hr || (HRESULT) S_FALSE == hr );
+
+ } // while( celt > 0 )
+
+
+ // -------------------------------------
+ // Write the properties & names back out
+ // -------------------------------------
+
+ for( ulIndex = 0; ulIndex < cProperties; ulIndex++ )
+ {
+
+ // Write the property.
+
+ PROPSPEC propspec;
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = rgstatpropstg[ ulIndex ].propid;
+
+ Check(S_OK, ppropstg->WriteMultiple(1, &propspec, &rgpropvar[ulIndex], PID_FIRST_USABLE ));
+
+ // If this property has a name, write it too.
+ if( rgstatpropstg[ ulIndex ].lpwstrName != NULL )
+ {
+ Check(S_OK, ppropstg->WritePropertyNames(
+ 1,
+ &rgstatpropstg[ulIndex].propid,
+ &rgstatpropstg[ulIndex].lpwstrName ));
+ }
+
+ } // for( ulIndex = 0; ulIndex < cProperties; ulIndex++ )
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ if( penumstatpropstg )
+ {
+ penumstatpropstg->Release();
+ penumstatpropstg = NULL;
+ }
+
+ // Free the PropVariants
+ if( rgpropvar )
+ {
+ FreePropVariantArray( cProperties, rgpropvar );
+ CoTaskMemFree( rgpropvar );
+ }
+
+ // Free the property names
+ if( rgstatpropstg )
+ {
+ for( ulIndex = 0; ulIndex < cProperties; ulIndex++ )
+ {
+ if( NULL != rgstatpropstg[ ulIndex ].lpwstrName )
+ {
+ CoTaskMemFree( rgstatpropstg[ ulIndex ].lpwstrName );
+ }
+ } // for( ulIndex = 0; ulIndex < cProperties; ulIndex++ )
+
+ CoTaskMemFree( rgstatpropstg );
+ }
+
+
+} // MungePropertyStorage
+
+//+---------------------------------------------------------
+//
+// Function: MungeStorage
+//
+// Synopsis: This routine munges the property sets in a
+// Storage. The properties themselves are not
+// modified, but the serialized bytes are.
+// For each property set, all the properties are
+// read, the property set is deleted, and
+// the properties are re-written.
+//
+// Inputs: [IStorage*] pstg (in)
+// The Storage to munge.
+//
+// Returns: None.
+//
+// Note: This routine only munges simple property
+// sets.
+//
+//+---------------------------------------------------------
+
+void
+MungeStorage( IStorage *pstg )
+{
+ // ------
+ // Locals
+ // ------
+
+ HRESULT hr;
+ ULONG celt;
+
+ STATPROPSETSTG statpropsetstg;
+ STATSTG statstg;
+
+ TSafeStorage< IPropertySetStorage > ppropsetstg;
+ TSafeStorage< IPropertyStorage > ppropstg;
+
+ IEnumSTATPROPSETSTG *penumstatpropsetstg;
+ IEnumSTATSTG *penumstatstg;
+
+ // -----------------------------------------------
+ // Munge each of the property sets in this Storage
+ // -----------------------------------------------
+
+ // Get the IPropertySetStorage interface
+ Check(S_OK, StgCreatePropSetStg( pstg, 0L, &ppropsetstg ));
+
+ // Get a property storage enumerator
+ Check(S_OK, ppropsetstg->Enum( &penumstatpropsetstg ));
+
+ // Get the first STATPROPSETSTG
+ hr = penumstatpropsetstg->Next( 1, &statpropsetstg, &celt );
+ Check( TRUE, (HRESULT) S_OK == hr || (HRESULT) S_FALSE == hr );
+
+ // Loop through the STATPROPSETSTGs.
+ while( celt > 0 )
+ {
+ // Is this a simple property storage (we don't
+ // handle non-simple sets)?
+
+ if( !(statpropsetstg.grfFlags & PROPSETFLAG_NONSIMPLE) )
+ {
+ // Munge the Property Storage.
+ MungePropertyStorage( ppropsetstg, statpropsetstg.fmtid );
+ }
+
+ // Get the next STATPROPSETSTG
+ // If we just did the first section of the DocSumInfo
+ // property set, then attempt the second section.
+
+ if( FMTID_DocSummaryInformation == statpropsetstg.fmtid )
+ {
+ statpropsetstg.fmtid = FMTID_UserDefinedProperties;
+ }
+ else
+ {
+ hr = penumstatpropsetstg->Next( 1, &statpropsetstg, &celt );
+ Check( TRUE, (HRESULT) S_OK == hr || (HRESULT) S_FALSE == hr );
+ }
+ }
+
+ // We're done with the Property Storage enumerator.
+ penumstatpropsetstg->Release();
+ penumstatpropsetstg = NULL;
+
+ // ------------------------------------------
+ // Recursively munge each of the sub-storages
+ // ------------------------------------------
+
+ // Get the IEnumSTATSTG enumerator
+ Check(S_OK, pstg->EnumElements( 0L, NULL, 0L, &penumstatstg ));
+
+ // Get the first STATSTG structure.
+ hr = penumstatstg->Next( 1, &statstg, &celt );
+ Check( TRUE, (HRESULT) S_OK == hr || (HRESULT) S_FALSE == hr );
+
+ // Loop through the elements of this Storage.
+ while( celt > 0 )
+ {
+ // Is this a sub-Storage which must be
+ // munged?
+
+ if( STGTY_STORAGE & statstg.type // This is a Storage
+ &&
+ 0x20 <= *statstg.pwcsName ) // But not a system Storage.
+ {
+ // We'll munge it.
+ IStorage *psubstg;
+
+ // Open the sub-storage.
+ Check(S_OK, pstg->OpenStorage( statstg.pwcsName,
+ NULL,
+ STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ NULL,
+ 0L,
+ &psubstg ));
+
+ // Munge the sub-storage.
+ MungeStorage( psubstg );
+ psubstg->Release();
+ psubstg = NULL;
+ }
+
+ CoTaskMemFree( statstg.pwcsName );
+ statstg.pwcsName = NULL;
+
+ // Move on to the next Storage element.
+ hr = penumstatstg->Next( 1, &statstg, &celt );
+ Check( TRUE, (HRESULT) S_OK == hr || (HRESULT) S_FALSE == hr );
+ }
+
+ penumstatstg->Release();
+ penumstatstg = NULL;
+
+
+} // MungeStorage
+
+
+//+----------------------------------------------------------------------------
+//
+// Function: DetermineSystemInfo
+//
+// Synopsis: Fill in the g_SystemInfo structure.
+//
+// Inputs: None.
+//
+// Returns: None.
+//
+//+----------------------------------------------------------------------------
+
+void DetermineSystemInfo()
+{
+ // Initilize g_SystemInfo.
+
+ g_SystemInfo.osenum = osenumUnknown;
+ g_SystemInfo.fIPropMarshaling = FALSE;
+
+#ifdef _MAC
+
+ // Set the OS type.
+ g_SystemInfo.osenum = osenumMac;
+
+#else
+
+ DWORD dwVersion;
+
+ // Get the OS Version
+ dwVersion = GetVersion();
+
+ // Is this an NT system?
+
+ if( (dwVersion & 0x80000000) == 0 )
+ {
+ // Is this at least NT4?
+ if( LOBYTE(LOWORD( dwVersion )) >= 4 )
+ g_SystemInfo.osenum = osenumNT4;
+
+ // Or, is this pre-NT4?
+ else
+ if( LOBYTE(LOWORD( dwVersion )) == 3 )
+ {
+ g_SystemInfo.osenum = osenumNT3;
+ }
+ }
+
+ // Otherwise, this is some kind of Win95 machine.
+ else
+ {
+ HINSTANCE hinst;
+ FARPROC farproc;
+
+ // Load OLE32, and see if CoIntializeEx exists. If it does,
+ // then DCOM95 is installed. Otherwise, this is just the base
+ // Win95.
+
+ hinst = LoadLibraryA( "ole32.dll" );
+ Check( TRUE, hinst != NULL );
+
+ farproc = GetProcAddress( hinst, "CoInitializeEx" );
+
+ if( NULL != farproc )
+ {
+ g_SystemInfo.osenum = osenumDCOM95;
+ }
+ else if( ERROR_PROC_NOT_FOUND == GetLastError() )
+ {
+ g_SystemInfo.osenum = osenumWin95;
+ }
+ } // if( (dwVersion & 0x80000000) == 0 )
+
+ Check( TRUE, g_SystemInfo.osenum != osenumUnknown );
+
+#endif // #ifdef _MAC ... #else
+
+ if( osenumWin95 == g_SystemInfo.osenum
+ ||
+ osenumNT3 == g_SystemInfo.osenum
+ )
+ {
+ g_SystemInfo.fIPropMarshaling = TRUE;
+ }
+}
+
+
+void
+DisplayUsage( LPSTR pszCommand )
+{
+#ifndef _MAC
+ printf("\n");
+ printf(" Usage: %s [options]\n", pszCommand);
+ printf(" Options:\n");
+ printf(" /q run Quick tests\n" );
+ printf(" /s run Standard tests (superset of Quick)\n" );
+ printf(" /w run the Word 6 test\n");
+ printf(" /m run the Marshaling test\n");
+ printf(" /c run the CoFileTimeNow\n");
+ printf(" /p run the Performance test\n");
+ printf(" /a run All tests\n" );
+ printf(" /v Verbose output\n" );
+ printf("\n");
+ printf(" File & Directory Options:\n" );
+ printf(" /t<directory> specifies temporary directory\n" );
+ printf(" (used during standard & optional tests - if not specified,\n" );
+ printf(" a default will be used)\n" );
+ printf(" /g<file> specifies a file to be munGed\n" );
+ printf(" (propsets are read, deleted, & re-written)\n" );
+ printf(" /d<file> specifies a file to be Dumped\n" );
+ printf(" (propsets are dumped to stdout\n" );
+ printf("\n");
+ printf(" For Example:\n" );
+ printf(" %s -smw -td:\\test\n", pszCommand );
+ printf(" %s -dword6.doc\n", pszCommand );
+ printf(" %s -gword6.doc\n", pszCommand );
+ printf("\n");
+
+#endif
+
+ return;
+}
+
+#define TEST_QUICK 0x01
+#define TEST_STANDARD 0x02
+#define TEST_WORD6 0x04
+#define TEST_MARSHALING 0x08
+#define TEST_COFILETIMENOW 0x10
+#define TEST_PERFORMANCE 0x20
+
+
+#ifdef _MAC
+int _CRTAPI1 PropTestMain(int argc, char **argv, CDisplay *pcDisplay )
+#else
+int __cdecl main(int argc, char *argv[])
+#endif
+{
+ int nArgIndex;
+
+ ULONG ulTestOptions = 0L;
+ CHAR* pszFileToMunge = NULL;
+ CHAR* pszTemporaryDirectory = NULL;
+ CHAR* pszFileToDump = NULL;
+
+ BOOL fMiscTest = FALSE;
+
+#ifdef _MAC
+ g_pcDisplay = pcDisplay;
+ Check( S_OK, InitOleManager( OLEMGR_BIND_NORMAL ));
+
+ #if DBG
+ FnAssertOn( TRUE );
+ #endif
+#endif
+
+#ifdef WINNT
+#ifdef _CAIRO_
+ PRINTF("\nCairo Property Set Tests\n");
+#else
+ PRINTF("\nSUR Property Set Tests\n");
+#endif
+#elif defined(_MAC)
+ PRINTF("\nMacintosh Property Set Tests\n" );
+#else
+ PRINTF("\nChicago Property Set Tests\n");
+#endif
+
+ // Check for command-line switches
+
+ if( 2 > argc )
+ {
+ DisplayUsage( argv[0] );
+ exit(0);
+ }
+
+ for( nArgIndex = 1; nArgIndex < argc; nArgIndex++ )
+ {
+ if( argv[nArgIndex][0] == '/'
+ ||
+ argv[nArgIndex][0] == '-'
+ )
+ {
+ BOOL fNextArgument = FALSE;
+
+ for( int nOptionSubIndex = 1;
+ argv[nArgIndex][nOptionSubIndex] != '\0' && !fNextArgument;
+ nOptionSubIndex++
+ )
+ {
+ switch( argv[nArgIndex][nOptionSubIndex] )
+ {
+ case 'x':
+ case 'X':
+
+ fMiscTest = TRUE;
+ break;
+
+ case 'q':
+ case 'Q':
+
+ ulTestOptions |= TEST_QUICK;
+ break;
+
+ case 's':
+ case 'S':
+
+ ulTestOptions |= TEST_STANDARD;
+ break;
+
+ case 'a':
+ case 'A':
+
+ ulTestOptions |= TEST_WORD6 | TEST_MARSHALING | TEST_COFILETIMENOW | TEST_PERFORMANCE;
+ break;
+
+ case 'g':
+ case 'G':
+
+ if( NULL != pszFileToMunge )
+ {
+ printf( "Error: Only one file may be munged\n" );
+ DisplayUsage( argv[0] );
+ exit(1);
+ }
+ else
+ {
+ pszFileToMunge = &argv[nArgIndex][nOptionSubIndex+1];
+ fNextArgument = TRUE;
+ }
+
+ if( '\0' == *pszFileToMunge )
+ {
+ printf( "Error: Missing filename for munge option\n" );
+ DisplayUsage( argv[0] );
+ exit(1);
+ }
+ break;
+
+ case 'w':
+ case 'W':
+
+ ulTestOptions |= TEST_WORD6;
+ break;
+
+ case 'm':
+ case 'M':
+
+ ulTestOptions |= TEST_MARSHALING;
+ break;
+
+ case 'c':
+ case 'C':
+
+ ulTestOptions |= TEST_COFILETIMENOW;
+ break;
+
+ case 'p':
+ case 'P':
+
+ ulTestOptions |= TEST_PERFORMANCE;
+ break;
+
+ case 't':
+ case 'T':
+
+ if( NULL != pszTemporaryDirectory )
+ {
+ printf( "Error: Only one temporary directory may be specified\n" );
+ DisplayUsage( argv[0] );
+ }
+ else
+ {
+ pszTemporaryDirectory = &argv[nArgIndex][nOptionSubIndex+1];
+ fNextArgument = TRUE;
+ }
+
+ if( '\0' == *pszTemporaryDirectory )
+ {
+ printf( "Error: Missing name for temporary directory option\n" );
+ DisplayUsage( argv[0] );
+ exit(1);
+ }
+ break;
+
+ case '?':
+
+ DisplayUsage(argv[0]);
+ exit(1);
+
+ case 'd':
+ case 'D':
+
+ if( NULL != pszFileToDump )
+ {
+ printf( "Error: Only one file may be dumped\n" );
+ DisplayUsage( argv[0] );
+ }
+ else
+ {
+ pszFileToDump = &argv[nArgIndex][nOptionSubIndex+1];
+ fNextArgument = TRUE;
+ }
+
+ if( '\0' == *pszFileToDump )
+ {
+ printf( "Error: Missing filename for dump option\n" );
+ DisplayUsage( argv[0] );
+ exit(1);
+ }
+ break;
+
+ case 'v':
+ case 'V':
+
+ g_fVerbose = TRUE;
+ break;
+
+ default:
+
+ printf( "Option '%c' ignored\n", argv[nArgIndex][nOptionSubIndex] );
+ break;
+
+ } // switch( argv[nArgIndex][1] )
+
+ } // for( int nOptionSubIndex = 1; ...
+ } // if( argv[nArgIndex][0] == '/'
+ else
+ {
+ break;
+ }
+ } // for( ULONG nArgIndex = 2; nArgIndex < argc; nArgIndex++ )
+
+
+ try
+ {
+ OLECHAR ocsDir[MAX_PATH+1], ocsTest[MAX_PATH+1],
+ ocsTest2[MAX_PATH+1], ocsMarshalingTest[MAX_PATH+1],
+ ocsTestOffice[MAX_PATH+1];
+
+ CHAR szDir[ MAX_PATH+1 ];
+ CHAR pszGeneratedTempDir[ MAX_PATH + 1 ];
+
+ HRESULT hr;
+ DWORD dwFileAttributes;
+
+ UNREFERENCED_PARAMETER( dwFileAttributes );
+ UNREFERENCED_PARAMETER( pszGeneratedTempDir );
+
+ ocscpy( ocsDir, OLESTR("") );
+
+ if( fMiscTest )
+ {
+ }
+
+ // Is there a file to dump?
+
+ if( NULL != pszFileToDump )
+ {
+ IStorage *pstg;
+
+ PropTest_mbstoocs( ocsDir, pszFileToDump );
+ Check(S_OK, StgOpenStorage( ocsDir,
+ NULL,
+ STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0L,
+ &pstg ));
+
+ DumpOleStorage( pstg, ocsDir );
+ pstg->Release();
+ return(0);
+ }
+
+
+ // Is there a file to munge?
+
+ if( NULL != pszFileToMunge )
+ {
+ IStorage *pstg;
+
+ PropTest_mbstoocs( ocsDir, pszFileToMunge );
+ Check(S_OK, StgOpenStorage( ocsDir,
+ NULL,
+ STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0L,
+ &pstg ));
+ MungeStorage( pstg );
+ OPRINTF( OLESTR("\"%s\" successfully munged\n"), ocsDir );
+ pstg->Release();
+ return(0);
+ }
+
+
+ // If no temporary directory was specified, generate one.
+ #ifndef _MAC
+ if( NULL == pszTemporaryDirectory )
+ {
+ GetTempPathA(sizeof(pszGeneratedTempDir)/sizeof(pszGeneratedTempDir[0]), pszGeneratedTempDir);
+ pszTemporaryDirectory = pszGeneratedTempDir;
+
+ }
+
+ // If necessary, add a path separator to the end of the
+ // temp directory name.
+
+ {
+ CHAR chLast = pszTemporaryDirectory[ strlen(pszTemporaryDirectory) - 1];
+ if( (CHAR) '\\' != chLast
+ &&
+ (CHAR) ':' != chLast )
+ {
+ strcat( pszTemporaryDirectory, "\\" );
+ }
+ }
+ #endif
+
+ CoInitialize(NULL);
+
+ int i=0;
+
+ #ifndef _MAC
+ // Verify that the user-provided directory path
+ // exists
+
+ dwFileAttributes = GetFileAttributesA( pszTemporaryDirectory );
+
+ if( (DWORD) -1 == dwFileAttributes )
+ {
+ printf( "Error: couldn't open temporary directory: \"%s\"\n", pszTemporaryDirectory );
+ exit(1);
+ }
+ else if( !(dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ printf( "Error: \"%s\" is not a directory\n", pszTemporaryDirectory );
+ exit(1);
+ }
+
+ // Find an new directory name to use for temporary
+ // files ("PrpTstX", where "X" is a number).
+
+ do
+ {
+ // Post-pend a subdirectory name and counter
+ // to the temporary directory name.
+
+ strcpy( szDir, pszTemporaryDirectory );
+ strcat( szDir, "PrpTst" );
+ sprintf( strchr(szDir,0), "%d", i++ );
+
+ }
+ while (!PropTest_CreateDirectory(szDir, NULL));
+
+ printf( "Generated files will be put in \"%s\"\n", szDir );
+ strcat( szDir, "\\" );
+
+ // Convert to an OLESTR.
+ PropTest_mbstoocs( ocsDir, szDir );
+
+ #endif
+
+ // --------------------------------
+ // Create necessary temporary files
+ // --------------------------------
+
+ // If any of the standard or extended tests will be run,
+ // create "testdoc" and "testdoc2".
+
+ if( ulTestOptions )
+ {
+ IPropertySetStorage *pPropSetStg;
+
+ // Create "tesdoc"
+
+ ocscpy(ocsTest, ocsDir);
+ ocscat(ocsTest, OLESTR("testdoc"));
+
+ hr = StgCreateDocfile(ocsTest, STGM_DIRECT | STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0, &_pstgTemp);
+ if (hr != S_OK)
+ {
+ OPRINTF( OLESTR("Can't create %s\n"), ocsTest);
+ exit(1);
+ }
+
+ // Create "testdoc2"
+
+ ocscpy(ocsTest2, ocsDir);
+ ocscat(ocsTest2, OLESTR("testdoc2"));
+
+ hr = StgCreateDocfile(ocsTest2, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0, &_pstgTempCopyTo);
+ if (hr != S_OK)
+ {
+ OPRINTF(OLESTR("Can't create %s\n"), ocsTest2);
+ exit(1);
+ }
+
+ // While we have an IStorage*, let's see if we're running
+ // on a system in which IStorages can be QI-ed for an
+ // IPropertySetStorage
+
+ if( E_NOINTERFACE
+ !=
+ _pstgTemp->QueryInterface( IID_IPropertySetStorage, (void**)&pPropSetStg ) )
+ {
+ pPropSetStg->Release();
+ g_fQIPropertySetStorage = TRUE;
+ }
+ else
+ {
+ PRINTF( "System does not support native IPropertySetStorage in DocFile\n" );
+ }
+
+ } // if( ulTestOptions )
+
+ g_fOFS = FALSE;
+
+ // Indicate what type of marshaling is being used: OLE32 or IPROP.
+
+ DetermineSystemInfo();
+ if( g_SystemInfo.fIPropMarshaling )
+ PRINTF( "Using IPROP.DLL for marshaling\n" );
+ else
+ PRINTF( "Using OLE32.DLL for marshaling\n" );
+
+
+ Check(S_OK, PopulateRGPropVar( g_rgcpropvarAll, g_rgcpropspecAll, _pstgTemp ));
+
+
+ if( ulTestOptions & TEST_QUICK )
+ {
+
+ PRINTF( "\nQuick Tests: " );
+
+ if( g_fVerbose )
+ PRINTF( "\n---------------\n" );
+
+ test_WriteReadAllProperties( ocsDir );
+
+ if( !g_fVerbose )
+ printf( "\n" );
+ PRINTF( "Quick tests PASSED\n" );
+
+ } // if( ulTestOptions & TEST_QUICK )
+
+
+ if( ulTestOptions & TEST_STANDARD )
+ {
+
+ PRINTF( "\nStandard Tests: " );
+
+ if( g_fVerbose )
+ PRINTF( "\n---------------\n" );
+
+ test_WriteReadAllProperties( ocsDir );
+
+ if (!g_fOFS)
+ test_PropertyInterfaces(_pstgTemp);
+
+ test_CodePages( ocsDir );
+ test_PROPSETFLAG_UNBUFFERED( _pstgTemp );
+ test_PropStgNameConversion( _pstgTemp );
+
+#ifdef WINNT
+ test_PropStgNameConversion2( );
+#endif
+
+
+ // Test the IStorage::CopyTo operation, using all combinations of
+ // direct and transacted mode for the base and PropSet storages.
+ // We don't run this test on the Mac because it doesn't have IStorages
+ // which support IPropertySetStorages.
+#if 0 // #ifndef _MAC_NODOC
+ for( int iteration = 0; iteration < 4; iteration++ )
+ {
+ OLECHAR aocStorageName[] = OLESTR( "#0 Test CopyTo" );
+ aocStorageName[1] = (OLECHAR) iteration + OLESTR('0');
+
+ test_CopyTo( _pstgTemp, _pstgTempCopyTo,
+ iteration & 2 ? STGM_TRANSACTED : STGM_DIRECT, // For the base Storage
+ iteration & 1 ? STGM_TRANSACTED : STGM_DIRECT, // For the PropSet Storages
+ aocStorageName );
+ }
+#endif
+
+
+ // Generate the stock ticker property set example
+ // from the OLE programmer's reference spec.
+ test_OLESpecTickerExample( _pstgTemp );
+
+ // Generate Office Property Sets
+
+ ocscpy(ocsTestOffice, ocsDir);
+ ocscat(ocsTestOffice, OLESTR("Office"));
+
+ test_Office( ocsTestOffice );
+
+ // Run Validation tests.
+
+ test_ParameterValidation( _pstgTemp );
+ test_PropVariantValidation( _pstgTemp );
+ test_PropVariantCopy();
+
+
+ if( !g_fVerbose )
+ printf( "\n" );
+ PRINTF( "Standard tests PASSED\n" );
+
+ } // if( ulTestOptions & TEST_STANDARD )
+
+ if( ulTestOptions & ~(TEST_STANDARD | TEST_QUICK) )
+ {
+ PRINTF( "\nExtended Tests: " );
+
+ if( g_fVerbose )
+ PRINTF( "\n---------------\n" );
+
+ if( ulTestOptions & TEST_COFILETIMENOW )
+ test_CoFileTimeNow();
+
+
+ // If requested, test for compatibility with Word 6.0 files.
+
+ if ( ulTestOptions & TEST_WORD6 )
+ test_Word6(_pstgTemp, szDir);
+
+ if ( ulTestOptions & TEST_PERFORMANCE )
+ test_Performance( _pstgTemp );
+
+#ifndef _MAC // No property marshaling support on the Mac.
+
+ if( ulTestOptions & TEST_MARSHALING )
+ {
+ PRINTF( " Marshaling Test\n" );
+
+ ocscpy(ocsMarshalingTest, ocsDir);
+ ocscat(ocsMarshalingTest, OLESTR("Marshal"));
+
+ Check(S_OK, g_cpsmt.Init( ocsMarshalingTest,
+ (PROPVARIANT*) g_rgcpropvarAll,
+ (PROPSPEC*) g_rgcpropspecAll,
+ CPROPERTIES_ALL,
+ CPROPERTIES_ALL_SIMPLE ));
+ Check(S_OK, g_cpsmt.Run());
+
+ }
+#endif
+
+ if( !g_fVerbose )
+ PRINTF( "\n" );
+ PRINTF( "Extended tests PASSED\n" );
+
+ } // if( ulTestOptions )
+ } // try
+
+ catch( CHResult chr )
+ {
+ }
+
+ // Clean up and exit.
+
+ if( _pstgTemp != NULL )
+ _pstgTemp->Release();
+
+ if( _pstgTempCopyTo != NULL )
+ _pstgTempCopyTo->Release();
+
+ CoUninitialize();
+
+#ifdef _MAC
+ UninitOleManager();
+
+ #if DBG
+ FnAssertOn( FALSE );
+ #endif
+
+#endif
+
+ CoFreeUnusedLibraries();
+
+ return 0;
+}
diff --git a/private/ole32/stg/props/utest/proptest.hxx b/private/ole32/stg/props/utest/proptest.hxx
new file mode 100644
index 000000000..bef6a8175
--- /dev/null
+++ b/private/ole32/stg/props/utest/proptest.hxx
@@ -0,0 +1,558 @@
+
+
+//+=================================================================
+//
+// File: PropTest.hxx
+//
+// Description: This file provides macros and constants
+// for the Property Test DRT.
+//
+//+=================================================================
+
+
+#ifndef _PROPTEST_HXX_
+#define _PROPTEST_HXX_
+
+//+----------------------------------------------------------------------------
+//
+// I n c l u d e s
+//
+//+----------------------------------------------------------------------------
+
+#include "propapi.h"
+
+//+----------------------------------------------------------------------------
+//
+// M a c r o s
+//
+//+----------------------------------------------------------------------------
+
+// ------------------------------------------------------------
+// PropTest_* macros to abstract OLE2ANSI and _UNICODE handling
+// ------------------------------------------------------------
+
+
+#ifdef _MAC
+# define PROPTEST_FILE_HANDLE FILE*
+# define PropTest_CreateFile(name) fopen(name, "w+")
+# define PropTest_WriteFile(hFile,buf,cbBuf,pcbWritten) \
+ *pcbWritten = fwrite(buf,1,cbBuf,hFile)
+# define PropTest_CloseHandle(handle) fclose(handle)
+#else
+# define PROPTEST_FILE_HANDLE HANDLE
+# define PropTest_CreateDirectory CreateDirectoryA
+# define PropTest_CreateFile(name) CreateFileA( name, \
+ GENERIC_READ|GENERIC_WRITE, \
+ 0, NULL, CREATE_ALWAYS, \
+ FILE_ATTRIBUTE_NORMAL, \
+ NULL )
+# define PropTest_WriteFile(hFile,buf,cbBuf,pcbWritten) \
+ WriteFile(hFile, buf, cbBuf, pcbWritten, NULL)
+# define PropTest_CloseHandle(handle) CloseHandle(handle)
+#endif
+
+
+// PropTest_towcs: Either copies or converts zero-terminated LPOLESTR
+// to an LPWSTR.
+
+#ifndef OLE2ANSI
+#define PropTest_mbstoocs(ocsDest,szSource) mbstowcs(ocsDest, szSource, strlen(szSource)+1)
+#else
+#define PropTest_mbstoocs(ocsDest,szSource) strcpy( ocsDest, szSource)
+#endif
+
+
+// CodePage macros:
+// We'll set the "good" codepage to 4e5, which is available on
+// NT and installable on Win95. But on the Mac, only 4e4 is
+// available, so this is what we'll use.
+
+#define CODEPAGE_DEFAULT 0x04e4 // US English
+#define CODEPAGE_BAD 0x9999 // Non-existent code page
+
+#ifdef _MAC
+#define CODEPAGE_GOOD 0x04e4
+#else
+#define CODEPAGE_GOOD 0x04e5
+#endif
+
+
+// Defines used by test_CodePage
+
+#define CODEPAGE_TEST_NAMED_PROPERTY OLESTR("Named Property")
+#define CODEPAGE_TEST_UNNAMED_BSTR_PROPID 3
+#define CODEPAGE_TEST_UNNAMED_I4_PROPID 4
+#define CODEPAGE_TEST_VBSTR_PROPID 7
+#define CODEPAGE_TEST_VPROPVAR_BSTR_PROPID 9
+
+
+
+//+----------------------------------------------------------------------------
+//
+// M a c r o s
+//
+//+----------------------------------------------------------------------------
+
+
+#define Check(x,y) _Check((HRESULT)(x),(HRESULT) (y), __FILE__, __LINE__)
+
+#define CCH_MAP (1 << CBIT_CHARMASK) // 32
+#define CHARMASK (CCH_MAP - 1) // 0x1f
+#define CALPHACHARS ('z' - 'a' + 1)
+#define CPROPERTIES 5
+
+// Show the current status, or display a "."
+
+#define STATUS(szMessage) \
+ if( g_fVerbose ) \
+ PRINTF ##szMessage; \
+ else \
+ PRINTF( "." );
+
+// The following macros are used for printf. Both printf
+// and oprintf macros are given (oprintf is assumes that
+// strings are OLECHARs). And for each, there is a normal
+// version, and an "ASYNC" version. The ASYNC version tells the
+// receiver that the string need not be displayed immediately
+// (this improves performance on the Mac).
+//
+// On the Mac, we pass the string to the CDisplay object.
+// On NT, we simple call the corresponding CRT routine.
+
+#ifdef _MAC
+# define PRINTF g_pcDisplay->printf
+# define OPRINTF g_pcDisplay->printf
+# define ASYNC_PRINTF g_pcDisplay->async_printf
+# define ASYNC_OPRINTF g_pcDisplay->async_printf
+#else
+# define PRINTF printf
+# define ASYNC_PRINTF printf
+# define OPRINTF oprintf
+# define ASYNC_OPRINTF oprintf
+#endif
+
+
+
+// -------
+// Globals
+// -------
+
+extern const OLECHAR oszSummaryInformation[];
+extern ULONG cboszSummaryInformation;
+extern const OLECHAR oszDocSummaryInformation[];
+extern ULONG cboszDocSummaryInformation;
+extern const OLECHAR oszGlobalInfo[];
+extern ULONG cboszGlobalInfo;
+extern const OLECHAR oszImageContents[];
+extern ULONG cboszImageContents;
+extern const OLECHAR oszImageInfo[];
+extern ULONG cboszImageInfo;
+
+
+extern const GUID fmtidGlobalInfo;
+extern const FMTID fmtidImageContents;
+extern const FMTID fmtidImageInfo;
+
+
+
+// ---------
+// Constants
+// ---------
+
+#define NUM_WELL_KNOWN_PROPSETS 6
+
+// Property Id's for Summary Info, as defined in OLE 2 Prog. Ref.
+#define PID_TITLE 0x00000002L
+#define PID_SUBJECT 0x00000003L
+#define PID_AUTHOR 0x00000004L
+#define PID_KEYWORDS 0x00000005L
+#define PID_COMMENTS 0x00000006L
+#define PID_TEMPLATE 0x00000007L
+#define PID_LASTAUTHOR 0x00000008L
+#define PID_REVNUMBER 0x00000009L
+#define PID_EDITTIME 0x0000000aL
+#define PID_LASTPRINTED 0x0000000bL
+#define PID_CREATE_DTM 0x0000000cL
+#define PID_LASTSAVE_DTM 0x0000000dL
+#define PID_PAGECOUNT 0x0000000eL
+#define PID_WORDCOUNT 0x0000000fL
+#define PID_CHARCOUNT 0x00000010L
+#define PID_THUMBNAIL 0x00000011L
+#define PID_APPNAME 0x00000012L
+#define PID_DOC_SECURITY 0x00000013L
+
+// Property Id's for Document Summary Info, as define in OLE Property Exchange spec.
+#define PID_CATEGORY 0x00000002L
+#define PID_PRESFORMAT 0x00000003L
+#define PID_BYTECOUNT 0x00000004L
+#define PID_LINECOUNT 0x00000005L
+#define PID_PARACOUNT 0x00000006L
+#define PID_SLIDECOUNT 0x00000007L
+#define PID_NOTECOUNT 0x00000008L
+#define PID_HIDDENCOUNT 0x00000009L
+#define PID_MMCLIPCOUNT 0x0000000aL
+#define PID_SCALE 0x0000000bL
+#define PID_HEADINGPAIR 0x0000000cL
+#define PID_DOCPARTS 0x0000000dL
+#define PID_MANAGER 0x0000000eL
+#define PID_COMPANY 0x0000000fL
+#define PID_LINKSDIRTY 0x00000010L
+
+#define CPROPERTIES_ALL 35
+#define CPROPERTIES_ALL_SIMPLE 33
+
+// --------
+// Typedefs
+// --------
+
+typedef enum tagOSENUM
+{
+ osenumUnknown, osenumWin95, osenumDCOM95,
+ osenumNT3, osenumNT4, osenumMac
+} OSENUM;
+
+typedef struct tagSYSTEMINFO
+{
+ OSENUM osenum;
+ BOOL fIPropMarshaling;
+
+} SYSTEMINFO;
+
+
+//=======================================================
+//
+// TSafeStorage
+//
+// This template creates a "safe pointer" to an IStorage,
+// IStream, IPropertySetStorage, or IPropertyStorage.
+// One constructor receives an IStorage*, which is used
+// when creating a pointer to an IPropertySetStorage.
+//
+// For example:
+//
+// TSafeStorage<IStorage> pstg;
+// StgCreateDocFile( L"Foo", STGM_ ..., 0L, &pstg );
+// TSafeStorage<IPropertySetStorage> psetstg( pstg );
+// pstg->Release();
+// pstg = NULL;
+// pssetstg->Open ...
+//
+//=======================================================
+
+
+template<class STGTYPE> class TSafeStorage
+{
+public:
+ TSafeStorage()
+ {
+ _pstg = NULL;
+ }
+
+ // Special case: Receive an IStorage and query for
+ // an IPropertySetStorage.
+ TSafeStorage(IStorage *pstg)
+ {
+#ifdef WINNT
+ Check(S_OK, StgCreatePropSetStg( pstg, 0L, (IPropertySetStorage**) &_pstg ));
+#else
+ Check(S_OK, pstg->QueryInterface( IID_IPropertySetStorage, (void**)&_pstg ));
+#endif
+ }
+
+ ~TSafeStorage()
+ {
+ if (_pstg != NULL)
+ {
+ _pstg->Release();
+ }
+ }
+
+ STGTYPE * operator -> ()
+ {
+ Check(TRUE, _pstg != NULL);
+ return(_pstg);
+ }
+
+ STGTYPE** operator & ()
+ {
+ return(&_pstg);
+ }
+
+ STGTYPE* operator=( STGTYPE *pstg )
+ {
+ _pstg = pstg;
+ return _pstg;
+ }
+
+ operator STGTYPE *()
+ {
+ return _pstg;
+ }
+
+private:
+ STGTYPE *_pstg;
+};
+
+
+
+//-----------------------------------------------------------------------------
+//
+// P r o t o t y p e s
+//
+//-----------------------------------------------------------------------------
+
+HRESULT OpenDir(
+ WCHAR *path,
+ BOOL fCreate,
+ IStorage **ppistg);
+
+HRESULT OpenFile(
+ WCHAR *path,
+ BOOL fCreate,
+ IStorage **ppistg);
+
+HRESULT OpenJP(
+ WCHAR *path,
+ BOOL fCreate,
+ IStorage **ppistg);
+
+HRESULT OpenSC(
+ WCHAR *path,
+ BOOL fCreate,
+ IStorage **ppistg);
+
+HRESULT OpenStg(
+ WCHAR *path,
+ BOOL fCreate,
+ IStorage **ppistg);
+
+FILETIME operator - ( const FILETIME &ft1, const FILETIME &ft2 );
+FILETIME operator -= ( FILETIME &ft1, const FILETIME &ft2 );
+void CheckTime(const FILETIME &ftStart, const FILETIME &ftPropSet);
+void CheckStat( IPropertyStorage *pPropSet, REFFMTID fmtid,
+ REFCLSID clsid, ULONG PropSetFlag,
+ const FILETIME & ftStart, DWORD dwOSVersion );
+BOOL IsEqualSTATPROPSTG(const STATPROPSTG *p1, const STATPROPSTG *p2);
+void CreateCodePageTestFile( LPOLESTR poszFileName, IStorage **ppStg );
+void ModifyPropSetCodePage( IStorage *pStg, USHORT usCodePage );
+void ModifyOSVersion( IStorage* pStg, DWORD dwOSVersion );
+void _Check(HRESULT hrExpected, HRESULT hrActual, LPCSTR szFile, int line);
+OLECHAR * GetNextTest();
+VOID CleanStat(ULONG celt, STATPROPSTG *psps);
+HRESULT PopulateRGPropVar( CPropVariant rgcpropvar[],
+ CPropSpec rgcpropspec[],
+ IStorage *pstg );
+
+VOID DumpOleStorage( IStorage *pstg, LPOLESTR aocpath );
+
+void test_WriteReadAllProperties( LPOLESTR ocsDir );
+void test_IPropertySetStorage_IUnknown(IStorage *pStorage);
+void test_PropVariantValidation( IStorage *pStg );
+void test_ParameterValidation(IStorage *pStg);
+void test_IPropertySetStorage_CreateOpenDelete(IStorage *pStorage);
+void test_IPropertySetStorage_SummaryInformation(IStorage *pStorage);
+void test_IPropertySetStorage_FailIfThere(IStorage *pStorage);
+void test_IPropertySetStorage_BadThis(IStorage *pIgnored);
+void test_IPropertySetStorage_TransactedMode(IStorage *pStorage);
+void test_IPropertySetStorage_TransactedMode2(IStorage *pStorage);
+void test_IPropertySetStorage_SubPropertySet(IStorage *pStorage);
+void test_IPropertySetStorage_CommitAtRoot(IStorage *pStorage);
+void test_IPropertySetStorage(IStorage *pStorage);
+void test_IEnumSTATPROPSETSTG(IStorage *pStorage);
+void test_IPropertyStorage_Access(IStorage *pStorage);
+void test_IPropertyStorage_Create(IStorage *pStorage);
+void test_IPropertyStorage_Stat(IStorage *pStorage);
+void test_IPropertyStorage_ReadMultiple_Normal(IStorage *pStorage);
+void test_IPropertyStorage_ReadMultiple_Cleanup(IStorage *pStorage);
+void test_IPropertyStorage_ReadMultiple_Inconsistent(IStorage *pStorage);
+void test_IPropertyStorage_ReadMultiple(IStorage *pStorage);
+void test_IPropertyStorage_WriteMultiple_Overwrite1(IStorage *pStgBase);
+void test_IPropertyStorage_WriteMultiple_Overwrite2(IStorage *pStorage);
+void test_IPropertyStorage_WriteMultiple_Overwrite3(IStorage *pStorage);
+void test_IPropertyStorage_Commit(IStorage *pStorage);
+void test_IPropertyStorage_WriteMultiple(IStorage *pStorage);
+void test_IPropertyStorage_DeleteMultiple(IStorage *pStorage);
+void test_IPropertyStorage(IStorage *pStorage);
+void test_Word6(IStorage *pStorage, CHAR *szTemporaryDirectory);
+void test_IEnumSTATPROPSTG(IStorage *pstgTemp);
+void test_MaxPropertyName(IStorage *pstgTemp);
+void test_CodePages( LPOLESTR poszDirectory );
+void test_PropertyInterfaces(IStorage *pstgTemp);
+void test_CopyTo(IStorage *pstgSource, // Source of the CopyTo
+ IStorage *pstgDestination, // Destination of the CopyTo
+ ULONG ulBaseStgTransaction, // Transaction bit for the base storage.
+ ULONG ulPropSetTransaction, // Transaction bit for the property sets.
+ LPOLESTR oszBaseStorageName );
+void test_OLESpecTickerExample( IStorage* pstg );
+void test_Office( LPOLESTR wszTestFile );
+void test_PropVariantCopy( );
+void test_Performance( IStorage *pStg );
+void test_CoFileTimeNow();
+void test_PROPSETFLAG_UNBUFFERED( IStorage *pStg );
+void test_PropStgNameConversion( IStorage *pStg );
+void test_PropStgNameConversion2();
+
+
+extern OLECHAR g_aocMap[];
+extern BOOL g_fVerbose;
+extern BOOL g_fQIPropertySetStorage;
+extern CPropVariant g_rgcpropvarAll[];
+extern CPropSpec g_rgcpropspecAll[];
+extern char g_szPropHeader[];
+extern char g_szEmpty[];
+extern BOOL g_fOFS;
+extern LARGE_INTEGER g_li0;
+extern IStorage *_pstgTemp;
+extern IStorage *_pstgTempCopyTo;
+extern SYSTEMINFO g_SystemInfo;
+
+#ifdef _MAC
+extern CDisplay *g_pcDisplay;
+#endif
+
+
+//+----------------------------------------------------------------------------
+//
+// I n l i n e s
+//
+//+----------------------------------------------------------------------------
+
+__inline OLECHAR
+MapChar(IN ULONG i)
+{
+ return((OLECHAR) g_aocMap[i & CHARMASK]);
+}
+
+inline BOOL operator == ( const FILETIME &ft1, const FILETIME &ft2 )
+{
+ return( ft1.dwHighDateTime == ft2.dwHighDateTime
+ &&
+ ft1.dwLowDateTime == ft2.dwLowDateTime );
+}
+
+inline BOOL operator != ( const FILETIME &ft1, const FILETIME &ft2 )
+{
+ return( ft1.dwHighDateTime != ft2.dwHighDateTime
+ ||
+ ft1.dwLowDateTime != ft2.dwLowDateTime );
+}
+
+
+inline BOOL operator > ( const FILETIME &ft1, const FILETIME &ft2 )
+{
+ return( ft1.dwHighDateTime > ft2.dwHighDateTime
+ ||
+ ft1.dwHighDateTime == ft2.dwHighDateTime
+ &&
+ ft1.dwLowDateTime > ft2.dwLowDateTime );
+}
+
+inline BOOL operator < ( const FILETIME &ft1, const FILETIME &ft2 )
+{
+ return( ft1.dwHighDateTime < ft2.dwHighDateTime
+ ||
+ ft1.dwHighDateTime == ft2.dwHighDateTime
+ &&
+ ft1.dwLowDateTime < ft2.dwLowDateTime );
+}
+
+inline BOOL operator >= ( const FILETIME &ft1, const FILETIME &ft2 )
+{
+ return( ft1 > ft2
+ ||
+ ft1 == ft2 );
+}
+
+inline BOOL operator <= ( const FILETIME &ft1, const FILETIME &ft2 )
+{
+ return( ft1 < ft2
+ ||
+ ft1 == ft2 );
+}
+
+
+
+//+----------------------------------------------------------------------------
+//
+// C l a s s e s
+//
+//+----------------------------------------------------------------------------
+
+enum CreateOpen
+{
+ coCreate, coOpen
+};
+
+class CTempStorage
+{
+public:
+ CTempStorage(DWORD grfMode = STGM_DIRECT | STGM_CREATE)
+ {
+ Check(S_OK, (_pstgTemp->CreateStorage(GetNextTest(), grfMode |
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0,
+ &_pstg)));
+ }
+
+
+ CTempStorage(CreateOpen co, IStorage *pstgParent, OLECHAR *pocsChild, DWORD grfMode = STGM_DIRECT)
+ {
+ if (co == coCreate)
+ Check(S_OK, pstgParent->CreateStorage(pocsChild,
+ grfMode | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0,
+ &_pstg));
+ else
+ Check(S_OK, pstgParent->OpenStorage(pocsChild, NULL,
+ grfMode | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0,
+ &_pstg));
+ }
+
+ ~CTempStorage()
+ {
+ if (_pstg != NULL)
+ _pstg->Release();
+ }
+
+
+ IStorage * operator -> ()
+ {
+ return(_pstg);
+ }
+
+ operator IStorage * ()
+ {
+ return(_pstg);
+ }
+
+ void Release()
+ {
+ if (_pstg != NULL)
+ {
+ _pstg->Release();
+ _pstg = NULL;
+ }
+ }
+
+private:
+ static unsigned int _iName;
+
+ IStorage * _pstg;
+};
+
+
+
+class CGenProps
+{
+public:
+ CGenProps() : _vt((VARENUM)2) {}
+ PROPVARIANT * GetNext(int HowMany, int *pActual, BOOL fWrapOk = FALSE, BOOL fNoNonSimple = TRUE);
+
+private:
+ BOOL _GetNext(PROPVARIANT *pVar, BOOL fWrapOk, BOOL fNoNonSimple);
+ VARENUM _vt;
+
+};
+
+
+
+
+#endif // !_PROPTEST_HXX_
diff --git a/private/ole32/stg/props/utest/proptest.rc b/private/ole32/stg/props/utest/proptest.rc
new file mode 100644
index 000000000..2bf4252a6
--- /dev/null
+++ b/private/ole32/stg/props/utest/proptest.rc
@@ -0,0 +1,9 @@
+
+#include <ntverp.h>
+#include <winver.h>
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Property DRT Tests"
+#define VER_INTERNALNAME_STR "PropTest.exe"
+#define VER_ORIGINALFILENAME_STR "PropTest.exe"
+#include <common.ver>
diff --git a/private/ole32/stg/props/utest/prstgsrv.hxx b/private/ole32/stg/props/utest/prstgsrv.hxx
new file mode 100644
index 000000000..f8272d006
--- /dev/null
+++ b/private/ole32/stg/props/utest/prstgsrv.hxx
@@ -0,0 +1,179 @@
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+/* File created by MIDL compiler version 3.00.39 */
+/* at Wed May 22 10:54:51 1996
+ */
+/* Compiler settings for .\BstrProxy\bstr.idl:
+ Os (OptLev=s), W1, Zp8, env=Win32, ms_ext, c_ext
+ error checks: none
+*/
+//@@MIDL_FILE_HEADING( )
+#include "rpc.h"
+#include "rpcndr.h"
+#ifndef COM_NO_WINDOWS_H
+#include "windows.h"
+#include "ole2.h"
+#endif /*COM_NO_WINDOWS_H*/
+
+#ifndef __bstr_h__
+#define __bstr_h__
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/* Forward Declarations */
+
+#ifndef __IDocFileMarshal_FWD_DEFINED__
+#define __IDocFileMarshal_FWD_DEFINED__
+typedef interface IDocFileMarshal IDocFileMarshal;
+#endif /* __IDocFileMarshal_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#include "objidl.h"
+
+void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
+void __RPC_USER MIDL_user_free( void __RPC_FAR * );
+
+#ifndef __IDocFileMarshal_INTERFACE_DEFINED__
+#define __IDocFileMarshal_INTERFACE_DEFINED__
+
+/****************************************
+ * Generated header for interface: IDocFileMarshal
+ * at Wed May 22 10:54:51 1996
+ * using MIDL 3.00.39
+ ****************************************/
+/* [unique][object][uuid] */
+
+
+
+EXTERN_C const IID IID_IDocFileMarshal;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ interface IDocFileMarshal : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE StgOpenPropStg(
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ REFFMTID fmtid,
+ /* [in] */ DWORD grfMode,
+ /* [out] */ IPropertyStorage __RPC_FAR *__RPC_FAR *pppstg) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StgOpenPropSetStg(
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ DWORD grfMode,
+ /* [out] */ IPropertySetStorage __RPC_FAR *__RPC_FAR *pppsstg) = 0;
+
+ };
+
+#else /* C style interface */
+
+ typedef struct IDocFileMarshalVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
+ IDocFileMarshal __RPC_FAR * This,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
+ IDocFileMarshal __RPC_FAR * This);
+
+ ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
+ IDocFileMarshal __RPC_FAR * This);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *StgOpenPropStg )(
+ IDocFileMarshal __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ REFFMTID fmtid,
+ /* [in] */ DWORD grfMode,
+ /* [out] */ IPropertyStorage __RPC_FAR *__RPC_FAR *pppstg);
+
+ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *StgOpenPropSetStg )(
+ IDocFileMarshal __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ DWORD grfMode,
+ /* [out] */ IPropertySetStorage __RPC_FAR *__RPC_FAR *pppsstg);
+
+ END_INTERFACE
+ } IDocFileMarshalVtbl;
+
+ interface IDocFileMarshal
+ {
+ CONST_VTBL struct IDocFileMarshalVtbl __RPC_FAR *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDocFileMarshal_QueryInterface(This,riid,ppvObject) \
+ (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
+
+#define IDocFileMarshal_AddRef(This) \
+ (This)->lpVtbl -> AddRef(This)
+
+#define IDocFileMarshal_Release(This) \
+ (This)->lpVtbl -> Release(This)
+
+
+#define IDocFileMarshal_StgOpenPropStg(This,pwcsName,fmtid,grfMode,pppstg) \
+ (This)->lpVtbl -> StgOpenPropStg(This,pwcsName,fmtid,grfMode,pppstg)
+
+#define IDocFileMarshal_StgOpenPropSetStg(This,pwcsName,grfMode,pppsstg) \
+ (This)->lpVtbl -> StgOpenPropSetStg(This,pwcsName,grfMode,pppsstg)
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+HRESULT STDMETHODCALLTYPE IDocFileMarshal_StgOpenPropStg_Proxy(
+ IDocFileMarshal __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ REFFMTID fmtid,
+ /* [in] */ DWORD grfMode,
+ /* [out] */ IPropertyStorage __RPC_FAR *__RPC_FAR *pppstg);
+
+
+void __RPC_STUB IDocFileMarshal_StgOpenPropStg_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+HRESULT STDMETHODCALLTYPE IDocFileMarshal_StgOpenPropSetStg_Proxy(
+ IDocFileMarshal __RPC_FAR * This,
+ /* [string][in] */ const OLECHAR __RPC_FAR *pwcsName,
+ /* [in] */ DWORD grfMode,
+ /* [out] */ IPropertySetStorage __RPC_FAR *__RPC_FAR *pppsstg);
+
+
+void __RPC_STUB IDocFileMarshal_StgOpenPropSetStg_Stub(
+ IRpcStubBuffer *This,
+ IRpcChannelBuffer *_pRpcChannelBuffer,
+ PRPC_MESSAGE _pRpcMessage,
+ DWORD *_pdwStubPhase);
+
+
+
+#endif /* __IDocFileMarshal_INTERFACE_DEFINED__ */
+
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/private/ole32/stg/props/utest/pstgserv/daytona/makefile b/private/ole32/stg/props/utest/pstgserv/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/props/utest/pstgserv/daytona/sources b/private/ole32/stg/props/utest/pstgserv/daytona/sources
new file mode 100644
index 000000000..3e311faf7
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/daytona/sources
@@ -0,0 +1,47 @@
+!IF 0
+
+Copyright (c) 1995 Microsoft Corporation
+
+!ENDIF
+
+!include ..\..\..\..\..\daytona.inc
+
+!MESSAGE Disabling Unicode
+C_DEFINES=$(C_DEFINES:UNICODE=NOT_UNICODE)
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+TARGETNAME= PStgServ
+TARGETPATH= obj
+TARGETTYPE= PROGRAM
+
+INCLUDES= .;..;..\..;..\..\..\..\h;..\..\..\..\common;..\..\..\..\..\ih;..\ProxStub\Daytona\obj;..\ProxStub
+
+SOURCES= \
+ ..\PStgServ.rc \
+ ..\PStgServ.cxx \
+ ..\main.cxx \
+ ..\pssClass.cxx
+
+UMTYPE= windows
+UMENTRY= winmain
+UMAPPL=
+UMTEST=
+UMLIBS= $(BASEDIR)\public\sdk\lib\*\iprop.lib\
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib\
+ $(BASEDIR)\public\sdk\lib\*\oleaut32.lib\
+ $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib\
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib
+
+#USE_NOLIBS=0
+#USE_CRTDLL=1
+
+USE_LIBCMT=1
+NOT_UNICODE=1
+
+#!ifndef FREEBUILD
+#DEBUG_CRTS=1
+#!endif
+
+#PRECOMPILED_INCLUDE=..\StdAfx.hxx
+
diff --git a/private/ole32/stg/props/utest/pstgserv/dirs b/private/ole32/stg/props/utest/pstgserv/dirs
new file mode 100644
index 000000000..f501fe4a6
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/dirs
@@ -0,0 +1,2 @@
+dirs=ProxStub
+optional_dirs=daytona
diff --git a/private/ole32/stg/props/utest/pstgserv/main.cxx b/private/ole32/stg/props/utest/pstgserv/main.cxx
new file mode 100644
index 000000000..c1c80579f
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/main.cxx
@@ -0,0 +1,20 @@
+
+
+#include <ole2.h>
+#include <pstgserv.hxx>
+
+CPropertyStorageServerApp cPropStgServerApp;
+
+int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ LPSTR lpszCmdLine, int nCmdShow )
+{
+
+ if( cPropStgServerApp.Init(hInstance, hPrevInstance,
+ lpszCmdLine, nCmdShow) )
+ {
+ return( cPropStgServerApp.Run() );
+ }
+
+ return( 0 );
+}
+
diff --git a/private/ole32/stg/props/utest/pstgserv/proxstub/daytona/makefile b/private/ole32/stg/props/utest/pstgserv/proxstub/daytona/makefile
new file mode 100644
index 000000000..1d3728d41
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/proxstub/daytona/makefile
@@ -0,0 +1,10 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!include $(NTMAKEENV)\makefile.def
+
diff --git a/private/ole32/stg/props/utest/pstgserv/proxstub/daytona/makefile.inc b/private/ole32/stg/props/utest/pstgserv/proxstub/daytona/makefile.inc
new file mode 100644
index 000000000..648bf70e3
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/proxstub/daytona/makefile.inc
@@ -0,0 +1,29 @@
+MIDL = midl.exe
+
+MIDL_FLAGS= \
+ -Zp8 \
+ -I$(INCLUDES) \
+ -Oi \
+ -oldnames \
+ -char unsigned \
+ -error allocation \
+ -error bounds_check \
+ -error stub_data \
+ -ms_ext -c_ext \
+ -DMIDL_PASS \
+ $(C_DEFINES) \
+ -cpp_cmd $(TARGET_CPP) \
+ -DMIDL_PASS $(C_DEFINES) -I$(INCLUDES)
+
+SSWITCH=-prefix sstub _
+
+obj\pstgserv.h: ..\pstgserv.idl
+ $(MIDL) $(MIDL_FLAGS) -header obj\pstgserv.h ..\pstgserv.idl
+
+
+DEST_TREE=daytona
+
+allidl: obj\pstgserv.h
+
+clean:
+ -erase obj\pstgserv.h >NUL 2>NUL
diff --git a/private/ole32/stg/props/utest/pstgserv/proxstub/daytona/sources b/private/ole32/stg/props/utest/pstgserv/proxstub/daytona/sources
new file mode 100644
index 000000000..afb87b364
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/proxstub/daytona/sources
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1995 Microsoft Corporation
+
+!ENDIF
+
+!include ..\..\..\..\..\..\daytona.inc
+
+!MESSAGE Disabling Unicode
+C_DEFINES=$(C_DEFINES:UNICODE=NOT_UNICODE)
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+TARGETNAME= PStgServ
+TARGETPATH= obj
+TARGETTYPE= DYNLINK
+DLLDEF=..\PStgServ.def
+
+INCLUDES= .;..;.\obj;$(BASEDIR)\public\sdk\inc;
+
+SOURCES= \
+ ..\dllmain.cxx \
+ ..\ProxStub.rc \
+ PStgServ_i.c \
+ PStgServ_p.c \
+ dlldata.c
+
+UMTYPE= windows
+UMAPPL=
+UMTEST=
+DLLBASE=@$(BASEDIR)\public\sdk\lib\coffbase.txt,usermode
+LINKLIBS= $(BASEDIR)\public\sdk\lib\*\rpcrt4.lib
+
+#USE_NOLIBS=0
+#USE_CRTDLL=1
+USE_LIBCMT=1
+
+NTTARGETFILE0=allidl
diff --git a/private/ole32/stg/props/utest/pstgserv/proxstub/dirs b/private/ole32/stg/props/utest/pstgserv/proxstub/dirs
new file mode 100644
index 000000000..e87487e64
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/proxstub/dirs
@@ -0,0 +1,2 @@
+dirs=
+optional_dirs=daytona
diff --git a/private/ole32/stg/props/utest/pstgserv/proxstub/dllmain.cxx b/private/ole32/stg/props/utest/pstgserv/proxstub/dllmain.cxx
new file mode 100644
index 000000000..2ee31a298
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/proxstub/dllmain.cxx
@@ -0,0 +1,12 @@
+
+#include <windows.h>
+
+HANDLE g_hInst = NULL;
+
+BOOL WINAPI DllMain (HANDLE hInst,
+ ULONG ul_reason_for_call,
+ LPVOID lpReserved)
+{
+ g_hInst = hInst;
+ return( TRUE );
+}
diff --git a/private/ole32/stg/props/utest/pstgserv/proxstub/proxstub.rc b/private/ole32/stg/props/utest/pstgserv/proxstub/proxstub.rc
new file mode 100644
index 000000000..aef8c653b
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/proxstub/proxstub.rc
@@ -0,0 +1,9 @@
+
+#include <ntverp.h>
+#include <winver.h>
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "IPropertyStorage Server Proxy/Stub"
+#define VER_INTERNALNAME_STR "PStgServ.dll"
+#define VER_ORIGINALFILENAME_STR "PStgServ.dll"
+#include <common.ver>
diff --git a/private/ole32/stg/props/utest/pstgserv/proxstub/pstgserv.def b/private/ole32/stg/props/utest/pstgserv/proxstub/pstgserv.def
new file mode 100644
index 000000000..89ce1559a
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/proxstub/pstgserv.def
@@ -0,0 +1,5 @@
+LIBRARY BSTRPROXY
+EXPORTS
+ DllGetClassObject
+ DllCanUnloadNow
+ GetProxyDllInfo
diff --git a/private/ole32/stg/props/utest/pstgserv/proxstub/pstgserv.idl b/private/ole32/stg/props/utest/pstgserv/proxstub/pstgserv.idl
new file mode 100644
index 000000000..46a4963a4
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/proxstub/pstgserv.idl
@@ -0,0 +1,20 @@
+
+[ uuid(af4ae0d0-a37f-11cf-8d73-00aa004cd01a),
+ object,
+ pointer_default(unique)
+]
+interface IPropertyStorageServer : IUnknown
+{
+ import "objidl.idl";
+
+ HRESULT StgOpenPropStg( [in, string] const OLECHAR *pwcsName,
+ [in] REFFMTID fmtid,
+ [in] DWORD grfMode,
+ [out] IPropertyStorage **pppstg );
+
+ HRESULT StgOpenPropSetStg( [in, string] const OLECHAR *pwcsName,
+ [in] DWORD grfMode,
+ [out] IPropertySetStorage **pppsstg );
+
+ HRESULT MarshalUnknown( [in] IUnknown *punk );
+}
diff --git a/private/ole32/stg/props/utest/pstgserv/pssclass.cxx b/private/ole32/stg/props/utest/pstgserv/pssclass.cxx
new file mode 100644
index 000000000..50f0a4f52
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/pssclass.cxx
@@ -0,0 +1,225 @@
+
+
+#include <ole2.h>
+
+#include "PStgServ.h"
+#include "PStgServ.hxx"
+
+const IID IID_IPropertyStorageServer = {0xaf4ae0d0,0xa37f,0x11cf,{0x8d,0x73,0x00,0xaa,0x00,0x4c,0xd0,0x1a}};
+//const IID IID_IPropertySetStorage = {0x0000013A,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
+
+STDMETHODIMP
+CClassFactory::QueryInterface( REFIID riid, void **ppvObject )
+{
+ IUnknown *pUnk = NULL;
+
+ if( riid == IID_IUnknown
+ ||
+ riid == IID_IClassFactory
+ )
+ {
+ pUnk = this;
+ }
+
+ if( pUnk != NULL )
+ {
+ pUnk->AddRef();
+ *ppvObject = pUnk;
+ return S_OK;
+ }
+
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG)
+CClassFactory::AddRef( void )
+{
+ return( ++m_cRefs );
+}
+
+
+STDMETHODIMP_(ULONG)
+CClassFactory::Release( void )
+{
+ m_cRefs--;
+
+ if( m_cRefs == 0 )
+ {
+ delete this;
+ return( 0 );
+ }
+
+ return( m_cRefs );
+}
+
+
+STDMETHODIMP
+CClassFactory::CreateInstance( IUnknown *pUnkOuter,
+ REFIID riid,
+ void **ppvObject )
+{
+ CPropertyStorageServer *pObj = NULL;
+
+ if( pUnkOuter != NULL )
+ {
+ return( CLASS_E_NOAGGREGATION );
+ }
+
+ pObj = new CPropertyStorageServer( this );
+ if( pObj == NULL )
+ {
+ return( E_OUTOFMEMORY );
+ }
+
+ return pObj->QueryInterface( riid, ppvObject );
+}
+
+
+STDMETHODIMP
+CClassFactory::LockServer( BOOL fLock )
+{
+ if( fLock )
+ {
+ m_cLocks++;
+ }
+ else
+ {
+ m_cLocks--;
+ }
+
+ if( m_cLocks == 0 )
+ {
+ PostMessage( m_hWnd, WM_QUIT, 0, 0 );
+ }
+
+ return S_OK;
+}
+
+
+STDMETHODIMP
+CPropertyStorageServer::QueryInterface( REFIID riid, void **ppvObject )
+{
+ *ppvObject = NULL;
+ IUnknown *pUnk = NULL;
+
+ if( riid == IID_IUnknown
+ ||
+ riid == IID_IPropertyStorageServer
+ )
+ {
+ pUnk = this;
+ }
+
+ if( pUnk != NULL )
+ {
+ pUnk->AddRef();
+ *ppvObject = pUnk;
+ return S_OK;
+ }
+
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG)
+CPropertyStorageServer::AddRef( void )
+{
+ return( ++m_cRefs );
+}
+
+
+STDMETHODIMP_(ULONG)
+CPropertyStorageServer::Release( void )
+{
+ if( --m_cRefs == 0 )
+ {
+ delete this;
+ return( 0 );
+ }
+
+ return( m_cRefs );
+}
+
+
+STDMETHODIMP
+CPropertyStorageServer::StgOpenPropStg( const OLECHAR *pwcsName,
+ REFFMTID fmtid,
+ DWORD grfMode,
+ IPropertyStorage **pppstg )
+{
+ HRESULT hr;
+ IPropertySetStorage *ppsstg = NULL;
+
+ if( m_pstg )
+ {
+ m_pstg->Release();
+ m_pstg = NULL;
+ }
+
+ hr = ::StgOpenStorage( pwcsName, NULL, grfMode, NULL, 0L, &m_pstg );
+ if( FAILED(hr) ) goto Exit;
+
+ hr = StgCreatePropSetStg( m_pstg, 0, &ppsstg );
+ if( FAILED(hr) ) goto Exit;
+
+ hr = ppsstg->Open( fmtid, grfMode, pppstg );
+ if( FAILED(hr) ) goto Exit;
+
+Exit:
+
+ if( FAILED(hr)
+ &&
+ m_pstg != NULL )
+ {
+ m_pstg->Release();
+ m_pstg = NULL;
+ }
+
+ if( ppsstg ) ppsstg->Release();
+
+ return( hr );
+}
+
+STDMETHODIMP
+CPropertyStorageServer:: StgOpenPropSetStg(
+ const OLECHAR *pwcsName,
+ DWORD grfMode,
+ IPropertySetStorage **pppsstg )
+{
+ HRESULT hr;
+
+ if( m_pstg )
+ {
+ m_pstg->Release();
+ m_pstg = NULL;
+ }
+
+ hr = ::StgOpenStorage( pwcsName, NULL, grfMode, NULL, 0L, &m_pstg );
+ if( FAILED(hr) ) goto Exit;
+
+ hr = StgCreatePropSetStg( m_pstg, 0, pppsstg );
+ if( FAILED(hr) ) goto Exit;
+
+Exit:
+
+ if( FAILED(hr)
+ &&
+ m_pstg != NULL )
+ {
+ m_pstg->Release();
+ m_pstg = NULL;
+ }
+
+ return( hr );
+}
+
+STDMETHODIMP
+CPropertyStorageServer:: MarshalUnknown( IUnknown *punk )
+{
+ punk->AddRef();
+ punk->Release();
+
+ return( S_OK );
+}
+
diff --git a/private/ole32/stg/props/utest/pstgserv/pssclass.hxx b/private/ole32/stg/props/utest/pstgserv/pssclass.hxx
new file mode 100644
index 000000000..8b78af450
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/pssclass.hxx
@@ -0,0 +1,90 @@
+
+#ifndef _PSSCLASS_HXX_
+#define _PSSCLASS_HXX_
+
+#include <pstgserv.h> // IDL headers
+
+class CPropertyStorageServer : public IPropertyStorageServer
+{
+public:
+ CPropertyStorageServer( IClassFactory *pcf)
+ {
+ m_cRefs = 0;
+ m_pcf = pcf;
+ m_pcf->LockServer( TRUE );
+ m_pstg = NULL;
+ }
+
+ ~CPropertyStorageServer()
+ {
+ if( m_cRefs > 0 )
+ {
+ CoDisconnectObject( this, 0L );
+ }
+
+ if( m_pstg != NULL )
+ m_pstg->Release();
+
+ m_pcf->LockServer( FALSE );
+ }
+
+ STDMETHODIMP QueryInterface( REFIID riid, void **ppvObj );
+ STDMETHODIMP_(ULONG) AddRef(void);
+ STDMETHODIMP_(ULONG) Release(void);
+
+ STDMETHODIMP StgOpenPropStg( const OLECHAR *pwcsName,
+ REFFMTID fmtid,
+ DWORD grfMode,
+ IPropertyStorage **pppstg );
+
+ STDMETHODIMP StgOpenPropSetStg( const OLECHAR *pwcsName,
+ DWORD grfMode,
+ IPropertySetStorage **pppsstg );
+ STDMETHODIMP MarshalUnknown( IUnknown *punk );
+
+
+private:
+ IStorage * m_pstg;
+ ULONG m_cRefs;
+ IClassFactory *m_pcf;
+};
+
+
+class CClassFactory: public IClassFactory
+{
+public:
+ CClassFactory( HWND hWnd )
+ {
+ m_cRefs = 0;
+ m_cLocks = 0;
+ m_hWnd = hWnd;
+ }
+
+ ~CClassFactory()
+ {
+ if( m_cRefs > 0 )
+ {
+ CoDisconnectObject( this, 0L );
+ }
+
+ SendMessage( m_hWnd, WM_QUIT, 0, 0 );
+ }
+
+public:
+ STDMETHODIMP QueryInterface( REFIID riid, void **ppvObj );
+ STDMETHODIMP_(ULONG) AddRef(void);
+ STDMETHODIMP_(ULONG) Release(void);
+
+ STDMETHODIMP CreateInstance( IUnknown *pUnkOuter,
+ REFIID riid,
+ void **ppvObject );
+ STDMETHODIMP LockServer( BOOL fLock );
+
+private:
+ ULONG m_cLocks;
+ HWND m_hWnd;
+ ULONG m_cRefs;
+
+};
+
+#endif // _PSSCLASS_HXX_
diff --git a/private/ole32/stg/props/utest/pstgserv/pstgserv.cxx b/private/ole32/stg/props/utest/pstgserv/pstgserv.cxx
new file mode 100644
index 000000000..8f4a268a8
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/pstgserv.cxx
@@ -0,0 +1,129 @@
+
+#include <stdio.h>
+#include <ole2.h>
+#include <pstgserv.hxx>
+
+
+HWND CPropertyStorageServerApp::m_hwnd;
+DWORD CPropertyStorageServerApp::m_dwReg;
+CClassFactory *CPropertyStorageServerApp::m_pClassFactory;
+CHAR CPropertyStorageServerApp::m_szAppName[80];
+HINSTANCE CPropertyStorageServerApp::m_hInstance;
+int CPropertyStorageServerApp::m_nCmdShow;
+
+
+
+__declspec(dllexport)
+long FAR PASCAL
+CPropertyStorageServerApp::WndProc (HWND hwnd, UINT message,
+ UINT wParam, LONG lParam)
+{
+
+ switch (message)
+ {
+ case WM_DESTROY :
+
+ CoUninitialize();
+ CoRevokeClassObject( m_dwReg );
+
+ PostQuitMessage (0) ;
+ return 0 ;
+ }
+
+ return DefWindowProc (hwnd, message, wParam, lParam) ;
+}
+
+
+
+BOOL
+CPropertyStorageServerApp::Init( HANDLE hInstance, HANDLE hPrevInstance,
+ LPSTR lpszCmdLine, int nCmdShow )
+{
+ WNDCLASSA wndclass;
+
+ sprintf( m_szAppName, "IPropertyStorage Server" );
+ m_hInstance = (HINSTANCE) hInstance;
+ m_nCmdShow = nCmdShow;
+
+ if( !hPrevInstance )
+ {
+ wndclass.style = CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = CPropertyStorageServerApp::WndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = m_hInstance;
+ wndclass.hIcon = LoadIconA( m_hInstance, m_szAppName );
+ wndclass.hCursor = LoadCursorA( NULL, MAKEINTRESOURCEA(32512) ); // IDC_ARROW
+ wndclass.hbrBackground = (HBRUSH) GetStockObject( WHITE_BRUSH );
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = m_szAppName;
+
+ RegisterClassA( &wndclass );
+ }
+
+ return( TRUE ); // Successful
+}
+
+
+#ifdef CreateWindowA
+#undef CreateWindow
+#endif
+
+WORD
+CPropertyStorageServerApp::Run( void )
+{
+ MSG msg;
+ HRESULT hr;
+ CHAR szErrorMessage[80];
+
+ msg.wParam = 0;
+
+ m_hwnd = CreateWindowA( m_szAppName,
+ "IPropertyStorage Server",
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, NULL, m_hInstance, NULL );
+ if( NULL == m_hwnd )
+ {
+ sprintf( szErrorMessage, "Failed CreateWindowA (%lu)", GetLastError() );
+ goto Exit;
+ }
+
+ ShowWindow( m_hwnd, SW_MINIMIZE );
+ UpdateWindow( m_hwnd );
+
+ if( FAILED( hr = CoInitialize( NULL )))
+ {
+ sprintf( szErrorMessage, "Failed CoInitialize (%08x)", hr );
+ goto Exit;
+ }
+
+ m_pClassFactory = (CClassFactory*) new CClassFactory( m_hwnd );
+ if( m_pClassFactory == NULL )
+ {
+ hr = E_OUTOFMEMORY;
+ sprintf( szErrorMessage, "Couldn't create CClassFactory" );
+ goto Exit;
+ }
+
+ if( FAILED( hr = CoRegisterClassObject( IID_IPropertyStorageServer,
+ m_pClassFactory,
+ CLSCTX_LOCAL_SERVER,
+ REGCLS_MULTIPLEUSE,
+ &m_dwReg )))
+ {
+ sprintf( szErrorMessage, "Couldn't register class object" );
+ goto Exit;
+ }
+
+ while( GetMessage( &msg, NULL, 0, 0 ))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+Exit:
+
+ return( msg.wParam );
+}
diff --git a/private/ole32/stg/props/utest/pstgserv/pstgserv.hxx b/private/ole32/stg/props/utest/pstgserv/pstgserv.hxx
new file mode 100644
index 000000000..95d35f7e3
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/pstgserv.hxx
@@ -0,0 +1,42 @@
+
+#include <pssclass.hxx>
+
+class CPropertyStorageServerApp
+{
+public:
+
+ CPropertyStorageServerApp()
+ {
+ m_hwnd = NULL;
+ m_dwReg = 0;
+ m_pClassFactory = NULL;
+ m_hInstance = NULL;
+ *m_szAppName = '\0';
+ m_nCmdShow = 0;
+ }
+
+ ~CPropertyStorageServerApp() {}
+
+public:
+
+ __declspec(dllexport)
+ static long FAR PASCAL
+ WndProc (HWND hwnd, UINT message, UINT wParam, LONG lParam);
+
+
+ BOOL Init( HANDLE hInstance, HANDLE hPrevInstance,
+ LPSTR lpszCmdLine, int nCmdShow );
+
+ WORD Run( void );
+
+private:
+
+ static HWND m_hwnd;
+ static DWORD m_dwReg;
+ static CClassFactory *m_pClassFactory;
+ static CHAR m_szAppName[80];
+ static HINSTANCE m_hInstance;
+ static int m_nCmdShow;
+
+};
+
diff --git a/private/ole32/stg/props/utest/pstgserv/pstgserv.ico b/private/ole32/stg/props/utest/pstgserv/pstgserv.ico
new file mode 100644
index 000000000..7eef0bcbe
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/pstgserv.ico
Binary files differ
diff --git a/private/ole32/stg/props/utest/pstgserv/pstgserv.rc b/private/ole32/stg/props/utest/pstgserv/pstgserv.rc
new file mode 100644
index 000000000..885d3796f
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/pstgserv.rc
@@ -0,0 +1,50 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include <windows.h>
+#include "resource.h"
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON DISCARDABLE "PStgServ.ico"
+
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+#include <ntverp.h>
+#include <winver.h>
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "IPropertyStorage Server"
+#define VER_INTERNALNAME_STR "PStgServ.exe"
+#define VER_ORIGINALFILENAME_STR "PStgServ.exe"
+
+#include <common.ver>
+
+#endif // !_MAC
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_ABOUTBOX "&About BStrMarshalServer..."
+END
+
diff --git a/private/ole32/stg/props/utest/pstgserv/pstgserv.rc2 b/private/ole32/stg/props/utest/pstgserv/pstgserv.rc2
new file mode 100644
index 000000000..22be8a894
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/pstgserv.rc2
@@ -0,0 +1,13 @@
+//
+// BSTRMARSHALSERVER.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+ #error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/private/ole32/stg/props/utest/pstgserv/pstgserv.reg b/private/ole32/stg/props/utest/pstgserv/pstgserv.reg
new file mode 100644
index 000000000..ff462ef7c
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/pstgserv.reg
@@ -0,0 +1,7 @@
+REGEDIT
+HKEY_CLASSES_ROOT\CLSID\{af4ae0d0-a37f-11cf-8d73-00aa004cd01a} = BStr Marshaling Test
+HKEY_CLASSES_ROOT\CLSID\{af4ae0d0-a37f-11cf-8d73-00aa004cd01a}\LocalServer32 = d:\release\daytona\dump\pstgserv.exe
+HKEY_CLASSES_ROOT\CLSID\{af4ae0d0-a37f-11cf-8d73-00aa004cd01a}\InprocServer32 = d:\release\daytona\dump\pstgserv.dll
+HKEY_CLASSES_ROOT\Interface\{af4ae0d0-a37f-11cf-8d73-00aa004cd01a} = BStr Marshaling Test
+HKEY_CLASSES_ROOT\Interface\{af4ae0d0-a37f-11cf-8d73-00aa004cd01a}\NumMethods = 5
+HKEY_CLASSES_ROOT\Interface\{af4ae0d0-a37f-11cf-8d73-00aa004cd01a}\ProxyStubClsid32 = {af4ae0d0-a37f-11cf-8d73-00aa004cd01a}
diff --git a/private/ole32/stg/props/utest/pstgserv/resource.h b/private/ole32/stg/props/utest/pstgserv/resource.h
new file mode 100644
index 000000000..959c8cb64
--- /dev/null
+++ b/private/ole32/stg/props/utest/pstgserv/resource.h
@@ -0,0 +1,21 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by BStrMarshalServer.rc
+//
+#define IDM_ABOUTBOX 0x0010
+#define IDD_ABOUTBOX 100
+#define IDS_ABOUTBOX 101
+#define IDD_BSTRMARSHALSERVER_DIALOG 102
+#define IDR_MAINFRAME 128
+#define IDC_STRING 1000
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 129
+#define _APS_NEXT_COMMAND_VALUE 32771
+#define _APS_NEXT_CONTROL_VALUE 1004
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/private/ole32/stg/props/utest/rtlstub.cxx b/private/ole32/stg/props/utest/rtlstub.cxx
new file mode 100644
index 000000000..3ad6cfaf9
--- /dev/null
+++ b/private/ole32/stg/props/utest/rtlstub.cxx
@@ -0,0 +1,783 @@
+
+
+//+============================================================================
+//
+// File: RtlStub.cxx
+//
+// Purpose:
+// This file provides some RTL routines which are also implemented
+// in NTDLL. They are duplicated here so that we can build
+// PropTest without linking to NTDLL, which doesn't exist
+// on Win95.
+//
+//+============================================================================
+
+
+
+#include "pch.cxx" // Brings in most other includes/defines/etc.
+
+
+#define BSTRLEN(bstrVal) *((ULONG *) bstrVal - 1)
+
+// we use static array instead of string literals because some systems
+// have 4 bytes string literals, and would not produce the correct result
+// for REF's 2 byte Unicode convention
+//
+OLECHAR aocMap[CCH_MAP + 1] = {'a','b','c','d','e','f','g',
+ 'h','i','j','k','l','m','n',
+ 'o','p','q','r','s','t','u',
+ 'v','w','x','y','z',
+ '0','1','2','3','4','5','\0'};
+
+GUID guidSummary =
+ { 0xf29f85e0,
+ 0x4ff9, 0x1068,
+ { 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9 } };
+
+OLECHAR oszSummary[] = {'S','u','m','m','a','r','y',
+ 'I','n','f','o','r','m','a','t','i','o','n','\0'};
+
+GUID guidDocumentSummary =
+ { 0xd5cdd502,
+ 0x2e9c, 0x101b,
+ { 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae } };
+
+OLECHAR oszDocumentSummary[] = {'D','o','c','u','m','e','n','t',
+ 'S','u','m','m','a','r','y',
+ 'I','n','f','o','r','m','a','t','i','o','n',
+ '\0'};
+
+// Note that user defined properties are placed in section 2 with the below
+// GUID as the FMTID -- alas, we did not expect Office95 to actually use it.
+
+GUID guidDocumentSummarySection2 =
+ { 0xd5cdd505,
+ 0x2e9c, 0x101b,
+ { 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae } };
+
+// *Global Info*
+
+GUID guidGlobalInfo =
+ { 0x56616F00,
+ 0xC154, 0x11ce,
+ { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
+
+// *Image Contents*
+
+GUID guidImageContents =
+ { 0x56616500,
+ 0xC154, 0x11ce,
+ { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
+
+// *Image Info*
+
+GUID guidImageInfo =
+ { 0x56616500,
+ 0xC154, 0x11ce,
+ { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
+
+
+//+--------------------------------------------------------------------------
+// Function: RtlGuidToPropertySetName
+//
+// Synopsis: Map property set GUID to null-terminated UNICODE name string.
+//
+// The awcname parameter is assumed to be a buffer with room for
+// CWC_PROPSETSZ (28) UNICODE characters. The first character
+// is always WC_PROPSET0 (0x05), as specified by the OLE Appendix
+// B documentation. The colon character normally used as an NT
+// stream name separator is not written to the caller's buffer.
+//
+// No error is possible.
+//
+// Arguments: IN GUID *pguid -- pointer to GUID to convert
+// OUT OLECHAR aocname[] -- output string buffer
+//
+// Returns: count of non-NULL characters in the output string buffer
+//---------------------------------------------------------------------------
+
+ULONG PROPSYSAPI PROPAPI
+RtlGuidToPropertySetName(
+ IN GUID const *pguid,
+ OUT OLECHAR aocname[])
+{
+ ULONG cbitRemain = CBIT_BYTE;
+ OLECHAR *poc = aocname;
+
+ BYTE *pb;
+ BYTE *pbEnd;
+
+ *poc++ = OC_PROPSET0;
+
+ // -----------------------
+ // Check for special-cases
+ // -----------------------
+
+ // Note: CCH_PROPSET includes the OC_PROPSET0, and sizeof(osz...)
+ // includes the trailing '\0', so sizeof(osz...) is ok because the
+ // OC_PROPSET0 character compensates for the trailing NULL character.
+
+ // Is this the SummaryInformation propset?
+ PROPASSERT(CCH_PROPSET >= sizeof(oszSummary)/sizeof(OLECHAR));
+
+ if (*pguid == guidSummary)
+ {
+ RtlCopyMemory(poc, oszSummary, sizeof(oszSummary));
+ return(sizeof(oszSummary)/sizeof(OLECHAR));
+ }
+
+ // Is this The DocumentSummaryInformation or User-Defined propset?
+ PROPASSERT(CCH_PROPSET >= sizeof(oszDocumentSummary)/sizeof(OLECHAR));
+
+ if (*pguid == guidDocumentSummary || *pguid == guidDocumentSummarySection2)
+ {
+ RtlCopyMemory(poc, oszDocumentSummary, sizeof(oszDocumentSummary));
+ return(sizeof(oszDocumentSummary)/sizeof(OLECHAR));
+ }
+
+ // Is this the Global Info propset?
+ PROPASSERT(CCH_PROPSET >= sizeof(oszGlobalInfo)/sizeof(OLECHAR));
+ if (*pguid == guidGlobalInfo)
+ {
+ RtlCopyMemory(poc, oszGlobalInfo, cboszGlobalInfo);
+ return(cboszGlobalInfo/sizeof(OLECHAR));
+ }
+
+ // Is this the Image Contents propset?
+ PROPASSERT(CCH_PROPSET >= sizeof(oszImageContents)/sizeof(OLECHAR));
+ if (*pguid == guidImageContents)
+ {
+ RtlCopyMemory(poc, oszImageContents, cboszImageContents);
+ return(cboszImageContents/sizeof(OLECHAR));
+ }
+
+ // Is this the Image Info propset?
+ PROPASSERT(CCH_PROPSET >= sizeof(oszImageInfo)/sizeof(OLECHAR));
+ if (*pguid == guidImageInfo)
+ {
+ RtlCopyMemory(poc, oszImageInfo, cboszImageInfo);
+ return(cboszImageInfo/sizeof(OLECHAR));
+ }
+
+
+ // ------------------------------
+ // Calculate the string-ized GUID
+ // ------------------------------
+
+ // If this is a big-endian system, we need to convert
+ // the GUID to little-endian for the conversion.
+
+#if BIGENDIAN
+ GUID guidByteSwapped = *pguid;
+ PropByteSwap( &guidByteSwapped );
+ pguid = &guidByteSwapped;
+#endif
+
+ // Point to the beginning and ending of the GUID
+ pb = (BYTE*) pguid;
+ pbEnd = pb + sizeof(*pguid);
+
+ // Walk 'pb' through each byte of the GUID.
+
+ while (pb < pbEnd)
+ {
+ ULONG i = *pb >> (CBIT_BYTE - cbitRemain);
+
+ if (cbitRemain >= CBIT_CHARMASK)
+ {
+ *poc = MapChar(i);
+ if (cbitRemain == CBIT_BYTE && *poc >= (OLECHAR)'a'
+ && *poc <= ((OLECHAR)'z'))
+ {
+ *poc += (OLECHAR) ( ((OLECHAR)'A') - ((OLECHAR)'a') );
+ }
+ poc++;
+ cbitRemain -= CBIT_CHARMASK;
+ if (cbitRemain == 0)
+ {
+ pb++;
+ cbitRemain = CBIT_BYTE;
+ }
+ }
+ else
+ {
+ if (++pb < pbEnd)
+ {
+ i |= *pb << cbitRemain;
+ }
+ *poc++ = MapChar(i);
+ cbitRemain += CBIT_BYTE - CBIT_CHARMASK;
+ }
+ } // while (pb < pbEnd)
+
+ *poc = OLESTR( '\0' );
+ return(CCH_PROPSET);
+
+}
+
+
+//+--------------------------------------------------------------------------
+// Function: RtlPropertySetNameToGuid
+//
+// Synopsis: Map non null-terminated UNICODE string to a property set GUID.
+//
+// If the name is not properly formed as per
+// RtlGuidToPropertySetName(), STATUS_INVALID_PARAMETER is
+// returned. The pguid parameter is assumed to point to a buffer
+// with room for a GUID structure.
+//
+// Arguments: IN ULONG cocname -- count of OLECHARs in string to convert
+// IN OLECHAR aocname[] -- input string to convert
+// OUT GUID *pguid -- pointer to buffer for converted GUID
+//
+// Returns: NTSTATUS
+//---------------------------------------------------------------------------
+
+NTSTATUS PROPSYSAPI PROPAPI
+RtlPropertySetNameToGuid(
+ IN ULONG cocname,
+ IN OLECHAR const aocname[],
+ OUT GUID *pguid)
+{
+ NTSTATUS Status = STATUS_INVALID_PARAMETER;
+
+ OLECHAR const *poc = aocname;
+
+ if (poc[0] == OC_PROPSET0)
+ {
+ // -----------------------
+ // Check for Special-Cases
+ // -----------------------
+
+ // Note: cocname includes the OC_PROPSET0, and sizeof(osz...)
+ // includes the trailing OLESTR('\0'), but the comparison excludes both
+ // the leading OC_PROPSET0 and the trailing '\0'.
+
+ // Is this SummaryInformation?
+ if (cocname == sizeof(oszSummary)/sizeof(OLECHAR) &&
+ ocsnicmp(&poc[1], oszSummary, cocname - 1) == 0)
+ {
+ *pguid = guidSummary;
+ return(STATUS_SUCCESS);
+ }
+
+ // Is this DocumentSummaryInformation?
+ if (cocname == sizeof(oszDocumentSummary)/sizeof(OLECHAR) &&
+ ocsnicmp(&poc[1], oszDocumentSummary, cocname - 1) == 0)
+ {
+ *pguid = guidDocumentSummary;
+ return(STATUS_SUCCESS);
+ }
+
+ // Is this Global Info?
+ if (cocname == cboszGlobalInfo/sizeof(OLECHAR) &&
+ ocsnicmp(&poc[1], oszGlobalInfo, cocname - 1) == 0)
+ {
+ *pguid = guidGlobalInfo;
+ return(STATUS_SUCCESS);
+ }
+
+ // Is this Image Info?
+ if (cocname == cboszImageInfo/sizeof(OLECHAR) &&
+ ocsnicmp(&poc[1], oszImageInfo, cocname - 1) == 0)
+ {
+ *pguid = guidImageInfo;
+ return(STATUS_SUCCESS);
+ }
+
+ // Is this Image Contents?
+ if (cocname == cboszImageContents/sizeof(OLECHAR) &&
+ ocsnicmp(&poc[1], oszImageContents, cocname - 1) == 0)
+ {
+ *pguid = guidImageContents;
+ return(STATUS_SUCCESS);
+ }
+
+ // ------------------
+ // Calculate the GUID
+ // ------------------
+
+ // None of the special-cases hit, so we must calculate
+ // the GUID from the name.
+
+ if (cocname == CCH_PROPSET)
+ {
+ ULONG cbit;
+ BYTE *pb = (BYTE *) pguid - 1;
+
+ RtlZeroMemory(pguid, sizeof(*pguid));
+ for (cbit = 0; cbit < CBIT_GUID; cbit += CBIT_CHARMASK)
+ {
+ ULONG cbitUsed = cbit % CBIT_BYTE;
+ ULONG cbitStored;
+ OLECHAR oc;
+
+ if (cbitUsed == 0)
+ {
+ pb++;
+ }
+
+ oc = *++poc - (OLECHAR)'A'; // assume upper case
+ // for wchar (unsigned) -ve values becomes a large number
+ // but for char, which is signed, -ve is -ve
+ if (oc > CALPHACHARS || oc < 0)
+ {
+ // oops, try lower case
+ oc += (OLECHAR) ( ((OLECHAR)'A') - ((OLECHAR)'a'));
+ if (oc > CALPHACHARS || oc < 0)
+ {
+ // must be a digit
+ oc += ((OLECHAR)'a') - ((OLECHAR)'0') + CALPHACHARS;
+ if (oc > CHARMASK)
+ {
+ goto Exit; // invalid character
+ }
+ }
+ }
+ *pb |= (BYTE) (oc << cbitUsed);
+
+ cbitStored = min(CBIT_BYTE - cbitUsed, CBIT_CHARMASK);
+
+ // If the translated bits wouldn't all fit in the current byte
+
+ if (cbitStored < CBIT_CHARMASK)
+ {
+ oc >>= CBIT_BYTE - cbitUsed;
+
+ if (cbit + cbitStored == CBIT_GUID)
+ {
+ if (oc != 0)
+ {
+ goto Exit; // extra bits
+ }
+ break;
+ }
+ pb++;
+
+ *pb |= (BYTE) oc;
+ }
+ } // for (cbit = 0; cbit < CBIT_GUID; cbit += CBIT_CHARMASK)
+
+ Status = STATUS_SUCCESS;
+
+ // If byte-swapping is necessary, do so now on the calculated
+ // GUID.
+
+ PropByteSwap( pguid );
+
+ } // if (cocname == CCH_PROPSET)
+ } // if (poc[0] == OC_PROPSET0)
+
+
+ // ----
+ // Exit
+ // ----
+
+Exit:
+
+ return(Status);
+}
+
+
+
+
+inline BOOLEAN
+_Compare_VT_BOOL(VARIANT_BOOL bool1, VARIANT_BOOL bool2)
+{
+ // Allow any non-zero value to match any non-zero value
+
+ return((bool1 == FALSE) == (bool2 == FALSE));
+}
+
+
+BOOLEAN
+_Compare_VT_CF(CLIPDATA *pclipdata1, CLIPDATA *pclipdata2)
+{
+ BOOLEAN fSame;
+
+ if (pclipdata1 != NULL && pclipdata2 != NULL)
+ {
+ fSame = ( pclipdata1->cbSize == pclipdata2->cbSize
+ &&
+ pclipdata1->ulClipFmt == pclipdata2->ulClipFmt );
+
+ if (fSame)
+ {
+ if (pclipdata1->pClipData != NULL && pclipdata2->pClipData != NULL)
+ {
+ fSame = memcmp(
+ pclipdata1->pClipData,
+ pclipdata2->pClipData,
+ CBPCLIPDATA(*pclipdata1)
+ ) == 0;
+ }
+ else
+ {
+ // They're the same if both are NULL, or if
+ // they have a zero length (if they have a zero
+ // length, either one may or may not be NULL, but they're
+ // still considered the same).
+
+ fSame = pclipdata1->pClipData == pclipdata2->pClipData
+ ||
+ CBPCLIPDATA(*pclipdata1) == 0;
+ }
+ }
+ }
+ else
+ {
+ fSame = pclipdata1 == pclipdata2;
+ }
+ return(fSame);
+}
+
+
+//+---------------------------------------------------------------------------
+// Function: RtlCompareVariants, public
+//
+// Synopsis: Compare two passed PROPVARIANTs -- case sensitive for strings
+//
+// Arguments: [CodePage] -- CodePage
+// [pvar1] -- pointer to PROPVARIANT
+// [pvar2] -- pointer to PROPVARIANT
+//
+// Returns: TRUE if identical, else FALSE
+//---------------------------------------------------------------------------
+
+#ifdef _MAC
+EXTERN_C // The Mac linker doesn't seem to be able to export with C++ decorations
+#endif
+
+BOOLEAN PROPSYSAPI PROPAPI
+RtlCompareVariants(
+ USHORT CodePage,
+ PROPVARIANT const *pvar1,
+ PROPVARIANT const *pvar2)
+{
+ if (pvar1->vt != pvar2->vt)
+ {
+ return(FALSE);
+ }
+
+ BOOLEAN fSame;
+ ULONG i;
+
+ switch (pvar1->vt)
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ fSame = TRUE;
+ break;
+
+#ifdef PROPVAR_VT_I1
+ case VT_I1:
+#endif
+ case VT_UI1:
+ fSame = pvar1->bVal == pvar2->bVal;
+ break;
+
+ case VT_I2:
+ case VT_UI2:
+ fSame = pvar1->iVal == pvar2->iVal;
+ break;
+
+ case VT_BOOL:
+ fSame = _Compare_VT_BOOL(pvar1->boolVal, pvar2->boolVal);
+ break;
+
+ case VT_I4:
+ case VT_UI4:
+ case VT_R4:
+ case VT_ERROR:
+ fSame = pvar1->lVal == pvar2->lVal;
+ break;
+
+ case VT_I8:
+ case VT_UI8:
+ case VT_R8:
+ case VT_CY:
+ case VT_DATE:
+ case VT_FILETIME:
+ fSame = pvar1->hVal.HighPart == pvar2->hVal.HighPart
+ &&
+ pvar1->hVal.LowPart == pvar2->hVal.LowPart;
+ break;
+
+ case VT_CLSID:
+ fSame = memcmp(pvar1->puuid, pvar2->puuid, sizeof(CLSID)) == 0;
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ fSame = ( pvar1->blob.cbSize == pvar2->blob.cbSize );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->blob.pBlobData,
+ pvar2->blob.pBlobData,
+ pvar1->blob.cbSize) == 0;
+ }
+ break;
+
+ case VT_CF:
+ fSame = _Compare_VT_CF(pvar1->pclipdata, pvar2->pclipdata);
+ break;
+
+ case VT_BSTR:
+ if (pvar1->bstrVal != NULL && pvar2->bstrVal != NULL)
+ {
+ fSame = ( BSTRLEN(pvar1->bstrVal) == BSTRLEN(pvar2->bstrVal) );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->bstrVal,
+ pvar2->bstrVal,
+ BSTRLEN(pvar1->bstrVal)) == 0;
+ }
+ }
+ else
+ {
+ fSame = pvar1->bstrVal == pvar2->bstrVal;
+ }
+ break;
+
+ case VT_LPSTR:
+ if (pvar1->pszVal != NULL && pvar2->pszVal != NULL)
+ {
+ fSame = strcmp(pvar1->pszVal, pvar2->pszVal) == 0;
+ }
+ else
+ {
+ fSame = pvar1->pszVal == pvar2->pszVal;
+ }
+ break;
+
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ case VT_LPWSTR:
+ if (pvar1->pwszVal != NULL && pvar2->pwszVal != NULL)
+ {
+ fSame = Prop_wcscmp(pvar1->pwszVal, pvar2->pwszVal) == 0;
+ }
+ else
+ {
+ fSame = pvar1->pwszVal == pvar2->pwszVal;
+ }
+ break;
+
+#ifdef PROPVAR_VT_I1
+ case VT_VECTOR | VT_I1:
+#endif
+ case VT_VECTOR | VT_UI1:
+ fSame = ( pvar1->caub.cElems == pvar2->caub.cElems );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->caub.pElems,
+ pvar2->caub.pElems,
+ pvar1->caub.cElems * sizeof(pvar1->caub.pElems[0])) == 0;
+ }
+ break;
+
+ case VT_VECTOR | VT_I2:
+ case VT_VECTOR | VT_UI2:
+ fSame = ( pvar1->cai.cElems == pvar2->cai.cElems );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->cai.pElems,
+ pvar2->cai.pElems,
+ pvar1->cai.cElems * sizeof(pvar1->cai.pElems[0])) == 0;
+ }
+ break;
+
+ case VT_VECTOR | VT_BOOL:
+ fSame = ( pvar1->cabool.cElems == pvar2->cabool.cElems );
+ if (fSame)
+ {
+ for (i = 0; i < pvar1->cabool.cElems; i++)
+ {
+ fSame = _Compare_VT_BOOL(
+ pvar1->cabool.pElems[i],
+ pvar2->cabool.pElems[i]);
+ if (!fSame)
+ {
+ break;
+ }
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_I4:
+ case VT_VECTOR | VT_UI4:
+ case VT_VECTOR | VT_R4:
+ case VT_VECTOR | VT_ERROR:
+ fSame = ( pvar1->cal.cElems == pvar2->cal.cElems );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->cal.pElems,
+ pvar2->cal.pElems,
+ pvar1->cal.cElems * sizeof(pvar1->cal.pElems[0])) == 0;
+ }
+ break;
+
+ case VT_VECTOR | VT_I8:
+ case VT_VECTOR | VT_UI8:
+ case VT_VECTOR | VT_R8:
+ case VT_VECTOR | VT_CY:
+ case VT_VECTOR | VT_DATE:
+ case VT_VECTOR | VT_FILETIME:
+ fSame = ( pvar1->cah.cElems == pvar2->cah.cElems );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->cah.pElems,
+ pvar2->cah.pElems,
+ pvar1->cah.cElems *
+ sizeof(pvar1->cah.pElems[0])) == 0;
+ }
+ break;
+
+ case VT_VECTOR | VT_CLSID:
+ fSame = ( pvar1->cauuid.cElems == pvar2->cauuid.cElems );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->cauuid.pElems,
+ pvar2->cauuid.pElems,
+ pvar1->cauuid.cElems *
+ sizeof(pvar1->cauuid.pElems[0])) == 0;
+ }
+ break;
+
+ case VT_VECTOR | VT_CF:
+ fSame = ( pvar1->caclipdata.cElems == pvar2->caclipdata.cElems );
+ if (fSame)
+ {
+ for (i = 0; i < pvar1->caclipdata.cElems; i++)
+ {
+ fSame = _Compare_VT_CF(
+ &pvar1->caclipdata.pElems[i],
+ &pvar2->caclipdata.pElems[i]);
+ if (!fSame)
+ {
+ break;
+ }
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_BSTR:
+ fSame = ( pvar1->cabstr.cElems == pvar2->cabstr.cElems );
+ if (fSame)
+ {
+ for (i = 0; i < pvar1->cabstr.cElems; i++)
+ {
+ if (pvar1->cabstr.pElems[i] != NULL &&
+ pvar2->cabstr.pElems[i] != NULL)
+ {
+ fSame = ( BSTRLEN(pvar1->cabstr.pElems[i])
+ ==
+ BSTRLEN(pvar2->cabstr.pElems[i]) );
+ if (fSame)
+ {
+ fSame = memcmp(
+ pvar1->cabstr.pElems[i],
+ pvar2->cabstr.pElems[i],
+ BSTRLEN(pvar1->cabstr.pElems[i])) == 0;
+ }
+ }
+ else
+ {
+ fSame = pvar1->cabstr.pElems[i] == pvar2->cabstr.pElems[i];
+ }
+ if (!fSame)
+ {
+ break;
+ }
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_LPSTR:
+ fSame = ( pvar1->calpstr.cElems == pvar2->calpstr.cElems );
+ if (fSame)
+ {
+ for (i = 0; i < pvar1->calpstr.cElems; i++)
+ {
+ if (pvar1->calpstr.pElems[i] != NULL &&
+ pvar2->calpstr.pElems[i] != NULL)
+ {
+ fSame = strcmp(
+ pvar1->calpstr.pElems[i],
+ pvar2->calpstr.pElems[i]) == 0;
+ }
+ else
+ {
+ fSame = pvar1->calpstr.pElems[i] ==
+ pvar2->calpstr.pElems[i];
+ }
+ if (!fSame)
+ {
+ break;
+ }
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_LPWSTR:
+ fSame = ( pvar1->calpwstr.cElems == pvar2->calpwstr.cElems );
+ if (fSame)
+ {
+ for (i = 0; i < pvar1->calpwstr.cElems; i++)
+ {
+ if (pvar1->calpwstr.pElems[i] != NULL &&
+ pvar2->calpwstr.pElems[i] != NULL)
+ {
+ fSame = Prop_wcscmp(
+ pvar1->calpwstr.pElems[i],
+ pvar2->calpwstr.pElems[i]) == 0;
+ }
+ else
+ {
+ fSame = pvar1->calpwstr.pElems[i] ==
+ pvar2->calpwstr.pElems[i];
+ }
+ if (!fSame)
+ {
+ break;
+ }
+ }
+ }
+ break;
+
+ case VT_VECTOR | VT_VARIANT:
+ fSame = ( pvar1->capropvar.cElems == pvar2->capropvar.cElems );
+ if (fSame)
+ {
+ for (i = 0; i < pvar1->capropvar.cElems; i++)
+ {
+ fSame = RtlCompareVariants(
+ CodePage,
+ &pvar1->capropvar.pElems[i],
+ &pvar2->capropvar.pElems[i]);
+ if (!fSame)
+ {
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ PROPASSERT(!"Invalid type for PROPVARIANT Comparison");
+ fSame = FALSE;
+ break;
+
+ }
+ return(fSame);
+}
+
diff --git a/private/ole32/stg/props/utest/testcase.cxx b/private/ole32/stg/props/utest/testcase.cxx
new file mode 100644
index 000000000..5af6aeb8f
--- /dev/null
+++ b/private/ole32/stg/props/utest/testcase.cxx
@@ -0,0 +1,5165 @@
+
+//+============================================================================
+//
+// File: TestCase.cxx
+//
+// Description:
+// This file provides all of the actual test-cases for the
+// PropTest DRT. Each test is a function, with a "test_"
+// prefix.
+//
+//+============================================================================
+
+#include "pch.cxx"
+
+
+//+---------------------------------------------------------------
+//
+// Function: test_WriteReadAllProperties
+//
+// Synopsis: This test simply creates two new property
+// sets in a new file (one Ansi and one Unicode),
+// writes all the properties in g_rgcpropvarAll,
+// reads them back, and verifies that it reads what
+// it wrote.
+//
+// Inputs: [LPOLESTR] ocsDir (in)
+// The directory in which a file can be created.
+//
+// Outputs: None.
+//
+//+---------------------------------------------------------------
+
+void
+test_WriteReadAllProperties( LPOLESTR ocsDir )
+{
+ OLECHAR ocsFile[ MAX_PATH ];
+ FMTID fmtidAnsi, fmtidUnicode, fmtidStgPropStg, fmtidStgPropSetStg;
+
+ TSafeStorage< IStorage > pstg, psubstg;
+ TSafeStorage< IStream > pstm;
+ TSafeStorage< IPropertySetStorage > ppropsetstg;
+ TSafeStorage< IPropertyStorage > ppropstgAnsi;
+ TSafeStorage< IPropertyStorage > ppropstgUnicode;
+
+ CPropVariant rgcpropvar[ CPROPERTIES_ALL ];
+ CPropVariant rgcpropvarAnsi[ CPROPERTIES_ALL ];
+ CPropVariant rgcpropvarUnicode[ CPROPERTIES_ALL ];
+
+ IPropertySetStorage *pPropSetStg;
+ IPropertyStorage *pPropStg;
+
+ ULONG ulIndex;
+
+ STATUS(( " Simple Write/Read Test\n" ));
+
+ // ----------
+ // Initialize
+ // ----------
+
+ // Generate FMTIDs.
+
+ UuidCreate( &fmtidAnsi );
+ UuidCreate( &fmtidUnicode );
+ UuidCreate( &fmtidStgPropStg );
+ UuidCreate( &fmtidStgPropSetStg );
+
+ // Generate a filename from the directory name.
+
+ ocscpy( ocsFile, ocsDir );
+
+ ocscat( ocsFile, OLESTR( "AllProps.stg" ));
+
+ // Create a Docfile.
+
+ Check( S_OK, StgCreateDocfile( ocsFile,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L,
+ &pstg ));
+
+ if( g_fQIPropertySetStorage )
+ {
+
+ // ---------------------------------
+ // Test DocFile IProperty interfaces
+ // ---------------------------------
+
+ // This tests the IPropertySetStorage & IPropertyStorage
+ // interfaces of the DocFile objects.
+
+ // Get the IPropertySetStorage
+
+ Check( S_OK, pstg->QueryInterface( IID_IPropertySetStorage, (void**)&ppropsetstg ));
+
+ // Create the Property Storages
+
+ Check( S_OK, ppropsetstg->Create( fmtidAnsi,
+ &CLSID_NULL,
+ PROPSETFLAG_NONSIMPLE,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &ppropstgAnsi ));
+
+ Check( S_OK, ppropsetstg->Create( fmtidUnicode,
+ &CLSID_NULL,
+ PROPSETFLAG_ANSI | PROPSETFLAG_NONSIMPLE,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &ppropstgUnicode ));
+
+ // Write to both property sets.
+
+ Check( S_OK, ppropstgAnsi->WriteMultiple( CPROPERTIES_ALL,
+ g_rgcpropspecAll,
+ g_rgcpropvarAll,
+ PID_FIRST_USABLE ));
+
+ Check( S_OK, ppropstgUnicode->WriteMultiple( CPROPERTIES_ALL,
+ g_rgcpropspecAll,
+ g_rgcpropvarAll,
+ PID_FIRST_USABLE ));
+
+ // Read from both property sets
+
+ Check( S_OK, ppropstgAnsi->ReadMultiple( CPROPERTIES_ALL,
+ g_rgcpropspecAll,
+ rgcpropvarAnsi ));
+
+ Check( S_OK, ppropstgUnicode->ReadMultiple( CPROPERTIES_ALL,
+ g_rgcpropspecAll,
+ rgcpropvarUnicode ));
+
+ // Compare the properties
+
+ for( int i = 0; i < (int)CPROPERTIES_ALL; i++ )
+ {
+ Check( TRUE, rgcpropvarAnsi[i] == g_rgcpropvarAll[i]
+ &&
+ rgcpropvarUnicode[i] == g_rgcpropvarAll[i] );
+ }
+
+ } // if( g_fQIPropertySetStorage )
+
+
+ // ---------------------
+ // Test StgCreatePropStg
+ // ---------------------
+
+ // This is similar to the previous test, except that it
+ // creates an IPropertyStorage using the StgCreatePropStg
+ // API.
+
+ // Create a stream for the property set.
+
+#ifdef _MAC
+ Handle hglobal;
+ hglobal = NewHandle( 0 );
+#else
+ HANDLE hglobal;
+ hglobal = GlobalAlloc( GPTR, 0 );
+#endif
+ Check( TRUE, NULL != hglobal );
+
+ Check(S_OK, CreateStreamOnHGlobal( hglobal, TRUE, &pstm ));
+
+ // Create the IPropertyStorage
+
+ Check( S_OK, StgCreatePropStg( (IUnknown*) pstm,
+ fmtidStgPropStg,
+ &CLSID_NULL,
+ PROPSETFLAG_ANSI,
+ 0L, // Reserved
+ &pPropStg ));
+
+
+ // Write to the property set.
+
+ Check( S_OK, pPropStg->WriteMultiple( CPROPERTIES_ALL_SIMPLE,
+ g_rgcpropspecAll,
+ g_rgcpropvarAll,
+ PID_FIRST_USABLE ));
+
+
+ // Read from the property set
+
+ Check( S_OK, pPropStg->ReadMultiple( CPROPERTIES_ALL_SIMPLE,
+ g_rgcpropspecAll,
+ rgcpropvar ));
+
+
+ // Compare the properties
+
+ for( ulIndex = 0; ulIndex < CPROPERTIES_ALL_SIMPLE; ulIndex++ )
+ {
+ Check( TRUE, rgcpropvar[ulIndex] == g_rgcpropvarAll[ulIndex] );
+ rgcpropvar[ulIndex].Clear();
+ }
+
+ pPropStg->Release();
+ pPropStg = NULL;
+
+ // -------------------
+ // Test StgOpenPropStg
+ // -------------------
+
+ // Open the IPropertyStorage
+
+ Check( S_OK, StgOpenPropStg( (IUnknown*) pstm,
+ fmtidStgPropStg,
+ PROPSETFLAG_DEFAULT,
+ 0L, // Reserved
+ &pPropStg ));
+
+
+ // Read from the property set
+
+ Check( S_OK, pPropStg->ReadMultiple( CPROPERTIES_ALL_SIMPLE,
+ g_rgcpropspecAll,
+ rgcpropvar ));
+
+
+ // Compare the properties
+
+ for( ulIndex = 0; ulIndex < CPROPERTIES_ALL_SIMPLE; ulIndex++ )
+ {
+ Check( TRUE, rgcpropvar[ulIndex] == g_rgcpropvarAll[ulIndex] );
+ rgcpropvar[ulIndex].Clear();
+ }
+
+ pPropStg->Release();
+ pPropStg = NULL;
+
+ pstm->Release();
+ pstm = NULL;
+
+ // --------------------------------
+ // Test StgCreatePropSetStg::Create
+ // --------------------------------
+
+ // This is equivalent to the previous tests, but
+ // uses StgCreatePropSetStg to create an IPropertySetStorage,
+ // and uses that to create a property set.
+
+ // Create the IPropertySetStorage
+
+ Check( S_OK, StgCreatePropSetStg( pstg,
+ 0L, // Reserved
+ &pPropSetStg ));
+
+ // Creat an IPropertyStorage
+
+ Check( S_OK, pPropSetStg->Create( fmtidStgPropSetStg,
+ &CLSID_NULL,
+ PROPSETFLAG_DEFAULT | PROPSETFLAG_NONSIMPLE,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPropStg ));
+
+ // Write to the property set.
+
+ Check( S_OK, pPropStg->WriteMultiple( CPROPERTIES_ALL,
+ g_rgcpropspecAll,
+ g_rgcpropvarAll,
+ PID_FIRST_USABLE ));
+
+
+ // Read from the property set
+
+ Check( S_OK, pPropStg->ReadMultiple( CPROPERTIES_ALL,
+ g_rgcpropspecAll,
+ rgcpropvar ));
+
+
+ // Compare the properties
+
+ for( ulIndex = 0; ulIndex < CPROPERTIES_ALL; ulIndex++ )
+ {
+ Check( TRUE, rgcpropvar[ulIndex] == g_rgcpropvarAll[ulIndex] );
+ rgcpropvar[ulIndex].Clear();
+ }
+
+ // Clean up
+
+ pPropStg->Release();
+ pPropStg = NULL;
+
+ pPropSetStg->Release();
+ pPropSetStg = NULL;
+
+
+
+} // test_WriteReadProperties
+
+
+
+
+
+//
+// OFS/DOCFILE -- run all tests on OFS and DocFile
+//
+// IPropertySetStorage tests
+//
+
+void
+test_IPropertySetStorage_IUnknown(IStorage *pStorage)
+{
+ STATUS(( " IPropertySetStorage::IUnknown\n" ));
+
+ // Check ref counting through different interfaces on object
+ //
+ // QI to IPropertySetStorage
+ // QI to IUnknown on IStorage
+ // QI to IUnknown on IPropertySetStorage
+ // QI back to IPropertySetStorage from IUnknown
+ // QI back to IStorage from IPropertySetStorage
+ //
+ // Release all.
+ //
+
+ IStorage *pStorage2;
+ IPropertySetStorage *ppss1, *ppss2, *ppss3;
+ IUnknown *punk1,*punk2;
+
+ Check(S_OK, pStorage->QueryInterface(IID_IPropertySetStorage, (void**)&ppss1));
+ Check(S_OK, pStorage->QueryInterface(IID_IUnknown, (void **)&punk1));
+ Check(S_OK, ppss1->QueryInterface(IID_IUnknown, (void **)&punk2));
+ Check(S_OK, ppss1->QueryInterface(IID_IStorage, (void **)&pStorage2));
+ Check(S_OK, ppss1->QueryInterface(IID_IPropertySetStorage, (void **)&ppss2));
+ Check(S_OK, punk1->QueryInterface(IID_IPropertySetStorage, (void **)&ppss3));
+
+ ppss1->AddRef();
+ ppss1->Release();
+
+ //pStorage.Release();
+ ppss1->Release();
+ punk1->Release();
+ punk2->Release();
+ pStorage2->Release();
+ ppss2->Release();
+// void *pvVirtFuncTable = *(void**)ppss3;
+ ppss3->Release();
+
+
+// Check(STG_E_INVALIDHANDLE, ((IPropertySetStorage*)&pvVirtFuncTable)->QueryInterface(IID_IUnknown, (void**)&punk3));
+}
+
+
+#define INVALID_POINTER ( (void *) 0xFFFFFFFF )
+#define VTABLE_MEMBER_FN(pObj,entry) ( (*(ULONG ***)(pObj))[ (entry) ] )
+
+
+//+---------------------------------------------------------
+//
+// Template: Alloc2PageVector
+//
+// Purpose: This function template allocates two pages
+// of memory, and then sets a vector pointer
+// so that its first element is wholy within
+// the first page, and the second element is
+// wholy within the second. Then, the protection
+// of the second page is set according to the
+// caller-provided parameter.
+//
+//
+// Inputs: [TYPE**] ppBase
+// Points to the beginning of the two pages.
+// [TYPE**] ppVector
+// Points to the beginning of the vector of TYPEs.
+// [DWORD] dwProtect
+// The desired protection on the second page
+// (from the PAGE_* enumeration).
+// [LPWSTR] lpwstr (optional)
+// If not NULL, used to initialize the vector
+// elements.
+//
+// Output: TRUE iff successful.
+//
+//+---------------------------------------------------------
+
+
+template< class TYPE > BOOL Alloc2PageVector( TYPE** ppBase,
+ TYPE** ppVector,
+ DWORD dwProtect,
+ TYPE* pInit )
+{
+ DWORD dwOldProtect;
+ SYSTEM_INFO si;
+
+ GetSystemInfo( &si );
+
+ *ppBase = (TYPE*) VirtualAlloc( NULL, 2 * si.dwPageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
+ if( NULL == *ppBase )
+ return( FALSE );
+
+ *ppVector = (TYPE*) ( (BYTE*) *ppBase + si.dwPageSize - sizeof(TYPE) );
+
+ if( NULL != pInit )
+ {
+ memcpy( &((LPWSTR*)*ppVector)[0], pInit, sizeof(TYPE) );
+ memcpy( &((LPWSTR*)*ppVector)[1], pInit, sizeof(TYPE) );
+ }
+
+ if( !VirtualProtect( (BYTE*) *ppBase + si.dwPageSize, si.dwPageSize, dwProtect, &dwOldProtect ) )
+ return( FALSE );
+
+ return( TRUE );
+}
+
+
+
+void
+test_PropVariantValidation( IStorage *pStg )
+{
+
+ STATUS(( " PropVariant Validation\n" ));
+
+ TSafeStorage< IPropertySetStorage > pPSStg( pStg );
+ TSafeStorage< IPropertyStorage > pPStg;
+
+ CPropVariant cpropvar;
+ CLIPDATA clipdata;
+ PROPSPEC propspec;
+
+ const LPWSTR wszText = L"Unicode Text String";
+
+ FMTID fmtid;
+ UuidCreate( &fmtid );
+
+ Check(S_OK, pPSStg->Create( fmtid,
+ NULL,
+ PROPSETFLAG_DEFAULT,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPStg ));
+
+
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = 2;
+
+ // -------------------------------
+ // Test invalid VT_CF Propvariants
+ // -------------------------------
+
+ // NULL clip format.
+
+ clipdata.cbSize = 4;
+ clipdata.ulClipFmt = (ULONG) -1;
+ clipdata.pClipData = NULL;
+
+ cpropvar = clipdata;
+
+ Check(S_OK, pPStg->WriteMultiple( 1, &propspec, cpropvar, PID_FIRST_USABLE ));
+
+ // Too short cbSize.
+
+ ((PROPVARIANT*)cpropvar)->pclipdata->cbSize = 3;
+ Check(STG_E_INVALIDPARAMETER, pPStg->WriteMultiple( 1, &propspec, cpropvar, PID_FIRST_USABLE ));
+
+ // Too short pClipData (it should be 1 byte, but the pClipData is NULL).
+
+ ((PROPVARIANT*)cpropvar)->pclipdata->cbSize = 5;
+ Check(STG_E_INVALIDPARAMETER, pPStg->WriteMultiple( 1, &propspec, cpropvar, PID_FIRST_USABLE ));
+
+
+}
+
+
+
+
+
+void
+test_ParameterValidation(IStorage *pStg)
+{
+ // We only run this test on WIN32 builds, because we need
+ // the VirtualAlloc routine.
+
+#ifdef WIN32
+
+ STATUS(( " Parameter Validation\n" ));
+
+ TSafeStorage< IPropertySetStorage > pPSStg( pStg );
+ TSafeStorage< IPropertyStorage > pPStg;
+ FMTID fmtid;
+
+ UuidCreate( &fmtid );
+
+ LPFMTID pfmtidNULL = NULL;
+ LPFMTID pfmtidInvalid = (LPFMTID) INVALID_POINTER;
+
+ DWORD dwOldProtect;
+
+ // Define several arrays which will be created with special
+ // protections. For all of this vectors, the first element
+ // will be in a page to which we have all access rights. The
+ // second element will be in a page for which we have no access,
+ // read access, or all access. The variables are named
+ // according to the access rights in the second element.
+ // The '...Base' variables are pointers to the base of
+ // the allocated memory (and must therefore be freed).
+ // The corresponding variables without the "Base" postfix
+ // are the vector pointers.
+
+ PROPSPEC *rgpropspecNoAccessBase, *rgpropspecNoAccess;
+ CPropVariant *rgcpropvarReadAccessBase, *rgcpropvarReadAccess;
+ CPropVariant *rgcpropvarNoAccessBase, *rgcpropvarNoAccess;
+ PROPID *rgpropidNoAccessBase, *rgpropidNoAccess;
+ PROPID *rgpropidReadAccessBase, *rgpropidReadAccess;
+ LPWSTR *rglpwstrNoAccessBase, *rglpwstrNoAccess;
+ LPWSTR *rglpwstrReadAccessBase, *rglpwstrReadAccess;
+ STATPROPSETSTG *rgStatPSStgReadAccessBase, *rgStatPSStgReadAccess;
+ STATPROPSTG *rgStatPStgReadAccessBase, *rgStatPStgReadAccess;
+
+ PROPSPEC rgpropspecAllAccess[1];
+ CPropVariant rgcpropvarAllAccess[1];
+ PROPID rgpropidAllAccess[1];
+ LPWSTR rglpwstrAllAccess[1];
+ LPWSTR rglpwstrInvalid[1];
+ STATPROPSETSTG rgStatPSStgAllAccess[1];
+ STATPROPSTG rgStatPStgAllAccess[1];
+
+ // Allocate memory for the vectors and set the vector
+ // pointers.
+
+ PROPID propidDefault = PID_FIRST_USABLE;
+ LPWSTR lpwstrNameDefault = L"Property Name";
+
+ Check(TRUE, Alloc2PageVector( &rgpropspecNoAccessBase,
+ &rgpropspecNoAccess,
+ (ULONG) PAGE_NOACCESS,
+ (PROPSPEC*) NULL ));
+ Check(TRUE, Alloc2PageVector( &rgcpropvarReadAccessBase,
+ &rgcpropvarReadAccess,
+ (ULONG) PAGE_READONLY,
+ (CPropVariant*) NULL ));
+ Check(TRUE, Alloc2PageVector( &rgcpropvarNoAccessBase,
+ &rgcpropvarNoAccess,
+ (ULONG) PAGE_NOACCESS,
+ (CPropVariant*) NULL ));
+ Check(TRUE, Alloc2PageVector( &rgpropidNoAccessBase,
+ &rgpropidNoAccess,
+ (ULONG) PAGE_NOACCESS,
+ &propidDefault ));
+ Check(TRUE, Alloc2PageVector( &rgpropidReadAccessBase,
+ &rgpropidReadAccess,
+ (ULONG) PAGE_READONLY,
+ &propidDefault ));
+ Check(TRUE, Alloc2PageVector( &rglpwstrNoAccessBase,
+ &rglpwstrNoAccess,
+ (ULONG) PAGE_NOACCESS,
+ &lpwstrNameDefault ));
+ Check(TRUE, Alloc2PageVector( &rglpwstrReadAccessBase,
+ &rglpwstrReadAccess,
+ (ULONG) PAGE_READONLY,
+ &lpwstrNameDefault ));
+ Check(TRUE, Alloc2PageVector( &rgStatPSStgReadAccessBase,
+ &rgStatPSStgReadAccess,
+ (ULONG) PAGE_READONLY,
+ (STATPROPSETSTG*) NULL ));
+ Check(TRUE, Alloc2PageVector( &rgStatPStgReadAccessBase,
+ &rgStatPStgReadAccess,
+ (ULONG) PAGE_READONLY,
+ (STATPROPSTG*) NULL ));
+
+ rglpwstrAllAccess[0] = rglpwstrNoAccess[0] = rglpwstrReadAccess[0] = L"Property Name";
+
+ // Create restricted buffers for misc tests
+
+ BYTE *pbReadOnly = (BYTE*) VirtualAlloc( NULL, 1, MEM_COMMIT, PAGE_READONLY );
+ Check( TRUE, pbReadOnly != NULL );
+
+ BYTE *pbNoAccess = (BYTE*) VirtualAlloc( NULL, 1, MEM_COMMIT, PAGE_NOACCESS );
+
+
+ // ----------------------------------------
+ // Test IPropertySetStorage::QueryInterface
+ // ----------------------------------------
+
+ IUnknown *pUnk;
+
+#if 0
+
+ // This test cannot run because CPropertySetStorage::QueryInterface is a virtual
+ // function, and since CExposedDocFile is derived from CPropertySetStorage,
+ // it is inaccessibl.
+
+ // Invalid REFIID
+
+ Check(E_INVALIDARG, ((CExposedDocFile*)&pPSStg)->CPropertySetStorage::QueryInterface( (REFIID) *pfmtidNULL, (void**)&pUnk ));
+ Check(E_INVALIDARG, pPSStg->QueryInterface( (REFIID) *pfmtidInvalid, (void**)&pUnk ));
+
+ // Invalid IUnknown*
+
+ Check(E_INVALIDARG, pPSStg->QueryInterface( IID_IUnknown, NULL ));
+ Check(E_INVALIDARG, pPSStg->QueryInterface( IID_IUnknown, (void**) INVALID_POINTER ));
+#endif
+
+
+ // --------------------------------
+ // Test IPropertySetStorage::Create
+ // --------------------------------
+
+ // Invalid REFFMTID
+
+ Check(E_INVALIDARG, pPSStg->Create( *pfmtidNULL,
+ NULL,
+ PROPSETFLAG_DEFAULT,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPStg ));
+
+ Check(E_INVALIDARG, pPSStg->Create( *pfmtidInvalid,
+ NULL,
+ PROPSETFLAG_DEFAULT,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPStg ));
+
+ // Invalid Class ID pointer
+
+ Check(E_INVALIDARG, pPSStg->Create( FMTID_NULL,
+ (GUID*) INVALID_POINTER,
+ PROPSETFLAG_DEFAULT,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPStg ));
+
+ // Invalid PropSetFlag
+
+ Check(STG_E_INVALIDFLAG, pPSStg->Create( FMTID_NULL,
+ &CLSID_NULL,
+ PROPSETFLAG_UNBUFFERED, // Only supported in APIs
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPStg ));
+
+ Check(STG_E_INVALIDFLAG, pPSStg->Create( FMTID_NULL,
+ &CLSID_NULL,
+ 0xffffffff,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPStg ));
+
+ // Invalid mode
+
+ Check(STG_E_INVALIDFLAG, pPSStg->Create( FMTID_NULL,
+ &CLSID_NULL,
+ PROPSETFLAG_DEFAULT,
+ STGM_DIRECT | STGM_SHARE_DENY_NONE,
+ &pPStg ));
+
+ // Invalid IPropertyStorage**
+
+ Check(E_INVALIDARG, pPSStg->Create( FMTID_NULL,
+ &CLSID_NULL,
+ PROPSETFLAG_DEFAULT,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ NULL ));
+
+ Check(E_INVALIDARG, pPSStg->Create( FMTID_NULL,
+ &CLSID_NULL,
+ PROPSETFLAG_DEFAULT,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ (IPropertyStorage **) INVALID_POINTER ));
+
+ // ------------------------------
+ // Test IPropertySetStorage::Open
+ // ------------------------------
+
+ // Invalid REFFMTID
+
+ Check(E_INVALIDARG, pPSStg->Open( *pfmtidNULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPStg ));
+
+ Check(E_INVALIDARG, pPSStg->Open( *pfmtidInvalid,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPStg ));
+
+ // Invalid Mode
+
+ Check(STG_E_INVALIDFLAG, pPSStg->Open( FMTID_NULL,
+ STGM_DIRECT | STGM_SHARE_DENY_NONE,
+ &pPStg ));
+
+ // Invalid IPropertyStorage**
+
+ Check(E_INVALIDARG, pPSStg->Open( FMTID_NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ NULL ));
+
+ Check(E_INVALIDARG, pPSStg->Open( FMTID_NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ (IPropertyStorage**) INVALID_POINTER ));
+
+ // --------------------------------
+ // Test IPropertySetStorage::Delete
+ // --------------------------------
+
+ // Invalid REFFMTID.
+
+ Check(E_INVALIDARG, pPSStg->Delete( *pfmtidNULL ));
+ Check(E_INVALIDARG, pPSStg->Delete( (REFFMTID) *pfmtidInvalid ));
+
+ // ------------------------------
+ // Test IPropertySetStorage::Enum
+ // ------------------------------
+
+ // Invalid IEnumSTATPROPSETSTG
+
+ Check(E_INVALIDARG, pPSStg->Enum( (IEnumSTATPROPSETSTG **) NULL ));
+ Check(E_INVALIDARG, pPSStg->Enum( (IEnumSTATPROPSETSTG **) INVALID_POINTER ));
+
+
+ // -------------
+ // Test PROPSPEC
+ // -------------
+
+ // Create a PropertyStorage
+
+ Check(S_OK, pPSStg->Create( fmtid,
+ NULL,
+ PROPSETFLAG_DEFAULT,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPStg ));
+
+
+ // Invalid ulKind
+
+ rgpropspecAllAccess[0].ulKind = (ULONG) -1;
+ rgpropspecAllAccess[0].lpwstr = NULL;
+ Check(E_INVALIDARG, pPStg->ReadMultiple( 1,
+ rgpropspecAllAccess,
+ rgcpropvarAllAccess ));
+ Check(E_INVALIDARG, pPStg->WriteMultiple( 1,
+ rgpropspecAllAccess,
+ rgcpropvarAllAccess,
+ 2 ));
+ Check(E_INVALIDARG, pPStg->DeleteMultiple( 1,
+ rgpropspecAllAccess ));
+
+ // Too short PROPSPEC
+
+ rgpropspecNoAccess[0].ulKind = PRSPEC_PROPID;
+ rgpropspecNoAccess[0].propid = 2;
+
+ Check(E_INVALIDARG, pPStg->ReadMultiple( 2,
+ rgpropspecNoAccess,
+ rgcpropvarAllAccess ));
+
+ Check(E_INVALIDARG, pPStg->WriteMultiple( 2,
+ rgpropspecNoAccess,
+ rgcpropvarAllAccess,
+ 2 ));
+
+ Check(E_INVALIDARG, pPStg->DeleteMultiple( 2,
+ rgpropspecNoAccess ));
+
+
+ // -------------------------------------
+ // Test IPropertyStorage::QueryInterface
+ // -------------------------------------
+
+ // Invalid REFIID
+
+ Check(E_INVALIDARG, pPStg->QueryInterface( (REFIID) *pfmtidNULL, (void**)&pUnk ));
+ Check(E_INVALIDARG, pPStg->QueryInterface( (REFIID) *pfmtidInvalid, (void**)&pUnk ));
+
+ // Invalid IUnknown*
+
+ Check(E_INVALIDARG, pPStg->QueryInterface( IID_IUnknown, NULL ));
+ Check(E_INVALIDARG, pPStg->QueryInterface( IID_IUnknown, (void**) INVALID_POINTER ));
+
+
+ // -----------------------------------
+ // Test IPropertyStorage::ReadMultiple
+ // -----------------------------------
+
+ rgpropspecAllAccess[0].ulKind = PRSPEC_LPWSTR;
+ rgpropspecAllAccess[0].lpwstr = OLESTR("Test Property");
+
+ // Too short count
+
+ Check(S_FALSE, pPStg->ReadMultiple( 0,
+ rgpropspecAllAccess,
+ rgcpropvarAllAccess));
+
+ // Too long a count for the PropVariant
+
+ Check(E_INVALIDARG, pPStg->ReadMultiple( 2,
+ rgpropspecAllAccess,
+ (PROPVARIANT*) (void*) rgcpropvarReadAccess ));
+
+
+ // Invalid PropVariant[]
+
+ Check(E_INVALIDARG, pPStg->ReadMultiple( 1,
+ rgpropspecAllAccess,
+ NULL ));
+ Check(E_INVALIDARG, pPStg->ReadMultiple( 1,
+ rgpropspecAllAccess,
+ (LPPROPVARIANT) INVALID_POINTER ));
+
+ // ------------------------------------
+ // Test IPropertyStorage::WriteMultiple
+ // ------------------------------------
+
+ rgpropspecAllAccess[0].ulKind = PRSPEC_LPWSTR;
+ rgpropspecAllAccess[0].lpwstr = L"Test Property";
+
+ // Too short count
+
+ Check(S_OK, pPStg->WriteMultiple( 0,
+ rgpropspecAllAccess,
+ (PROPVARIANT*)(void*)rgcpropvarAllAccess,
+ 2));
+
+ // Too short PropVariant
+
+ Check(E_INVALIDARG, pPStg->WriteMultiple( 2,
+ rgpropspecAllAccess,
+ (PROPVARIANT*)(void*)rgcpropvarNoAccess,
+ PID_FIRST_USABLE ));
+
+ // Invalid PropVariant[]
+
+ Check(E_INVALIDARG, pPStg->WriteMultiple( 1,
+ rgpropspecAllAccess,
+ NULL,
+ 2));
+ Check(E_INVALIDARG, pPStg->WriteMultiple( 1,
+ rgpropspecAllAccess,
+ (LPPROPVARIANT) INVALID_POINTER,
+ PID_FIRST_USABLE));
+
+ // Read-only PIDs
+
+ rgpropspecAllAccess[0].ulKind = PRSPEC_PROPID;
+ rgpropspecAllAccess[0].propid = PID_DICTIONARY;
+ rgcpropvarAllAccess[0] = "LPSTR Property";
+
+ Check(STG_E_INVALIDPARAMETER, pPStg->WriteMultiple( 1,
+ rgpropspecAllAccess,
+ (PROPVARIANT*)(void*)rgcpropvarAllAccess,
+ PID_FIRST_USABLE));
+
+ rgpropspecAllAccess[0].propid = PID_LOCALE;
+ Check(STG_E_INVALIDPARAMETER, pPStg->WriteMultiple( 1,
+ rgpropspecAllAccess,
+ (PROPVARIANT*)(void*)rgcpropvarAllAccess,
+ PID_FIRST_USABLE));
+
+ rgpropspecAllAccess[0].propid = PID_CODEPAGE;
+ Check(STG_E_INVALIDPARAMETER, pPStg->WriteMultiple( 1,
+ rgpropspecAllAccess,
+ (PROPVARIANT*)(void*)rgcpropvarAllAccess,
+ PID_FIRST_USABLE));
+
+ // -------------------------------------
+ // Test IPropertyStorage::DeleteMultiple
+ // -------------------------------------
+
+
+ // Invalid count
+
+ Check(S_OK, pPStg->DeleteMultiple( 0,
+ rgpropspecAllAccess ));
+
+
+ // ----------------------------------------
+ // Test IPropertyStorage::ReadPropertyNames
+ // ----------------------------------------
+
+ // Create a property with the name we're going to use.
+
+ rgpropspecAllAccess[0].ulKind = PRSPEC_LPWSTR;
+ rgpropspecAllAccess[0].lpwstr = rglpwstrAllAccess[0];
+
+ Check(S_OK, pPStg->WriteMultiple( 1,
+ rgpropspecAllAccess,
+ rgcpropvarAllAccess[0],
+ PID_FIRST_USABLE ));
+
+ // Invalid count
+
+ Check(S_FALSE, pPStg->ReadPropertyNames( 0,
+ rgpropidAllAccess,
+ rglpwstrAllAccess ));
+
+ // Too short PROPID[] or LPWSTR[]
+
+ Check(E_INVALIDARG, pPStg->ReadPropertyNames( 2,
+ rgpropidNoAccess,
+ rglpwstrAllAccess ));
+ Check(E_INVALIDARG, pPStg->ReadPropertyNames( 2,
+ rgpropidAllAccess,
+ rglpwstrReadAccess ));
+
+ // Invalid rgpropid[]
+
+ Check(E_INVALIDARG, pPStg->ReadPropertyNames( 1,
+ NULL,
+ rglpwstrAllAccess ));
+ Check(E_INVALIDARG, pPStg->ReadPropertyNames( 1,
+ (PROPID*) INVALID_POINTER,
+ rglpwstrAllAccess ));
+
+ // Invalid rglpwstr[]
+
+ Check(E_INVALIDARG, pPStg->ReadPropertyNames( 1,
+ rgpropidAllAccess,
+ NULL ));
+ Check(E_INVALIDARG, pPStg->ReadPropertyNames( 1,
+ rgpropidAllAccess,
+ (LPWSTR*) INVALID_POINTER ));
+
+
+ // -----------------------------------------
+ // Test IPropertyStorage::WritePropertyNames
+ // -----------------------------------------
+
+ // Invalid count
+
+ Check(S_OK, pPStg->WritePropertyNames( 0,
+ NULL,
+ rglpwstrAllAccess ));
+
+ // Too short PROPID[] or LPWSTR[]
+
+ Check(E_INVALIDARG, pPStg->WritePropertyNames( 2,
+ rgpropidNoAccess,
+ rglpwstrAllAccess ));
+ Check(E_INVALIDARG, pPStg->WritePropertyNames( 2,
+ rgpropidAllAccess,
+ rglpwstrNoAccess ));
+ Check(S_OK, pPStg->WritePropertyNames( 2,
+ rgpropidAllAccess,
+ rglpwstrReadAccess ));
+
+ // Invalid rgpropid[]
+
+ Check(E_INVALIDARG, pPStg->WritePropertyNames( 1,
+ NULL,
+ rglpwstrAllAccess ));
+ Check(E_INVALIDARG, pPStg->WritePropertyNames( 1,
+ (PROPID*) INVALID_POINTER,
+ rglpwstrAllAccess ));
+
+ // Invalid rglpwstr[]
+
+ Check(E_INVALIDARG, pPStg->WritePropertyNames( 1,
+ rgpropidAllAccess,
+ NULL ));
+ Check(E_INVALIDARG, pPStg->WritePropertyNames( 1,
+ rgpropidAllAccess,
+ (LPWSTR*) INVALID_POINTER ));
+
+ // Invalid name.
+
+ rglpwstrInvalid[0] = NULL;
+ Check(E_INVALIDARG, pPStg->WritePropertyNames( 1,
+ rgpropidAllAccess,
+ rglpwstrInvalid ));
+
+ rglpwstrInvalid[0] = (LPWSTR) INVALID_POINTER;
+ Check(E_INVALIDARG, pPStg->WritePropertyNames( 1,
+ rgpropidAllAccess,
+ rglpwstrInvalid ));
+
+ // ------------------------------------------
+ // Test IPropertyStorage::DeletePropertyNames
+ // ------------------------------------------
+
+ // Invalid count
+
+ Check(S_OK, pPStg->DeletePropertyNames( 0,
+ rgpropidAllAccess ));
+
+ // Too short PROPID[]
+
+ Check(E_INVALIDARG, pPStg->DeletePropertyNames( 2,
+ rgpropidNoAccess ));
+ Check(S_OK, pPStg->DeletePropertyNames( 2,
+ rgpropidReadAccess ));
+
+ // Invalid rgpropid[]
+
+ Check(E_INVALIDARG, pPStg->DeletePropertyNames( 1,
+ NULL ));
+ Check(E_INVALIDARG, pPStg->DeletePropertyNames( 1,
+ (PROPID*) INVALID_POINTER ));
+
+ // ---------------------------
+ // Test IPropertyStorage::Enum
+ // ---------------------------
+
+ // Invalid IEnumSTATPROPSTG
+
+ Check(E_INVALIDARG, pPStg->Enum( NULL ));
+ Check(E_INVALIDARG, pPStg->Enum( (IEnumSTATPROPSTG**) INVALID_POINTER ));
+
+ // --------------------------------------
+ // Test IPropertyStorage::SetElementTimes
+ // --------------------------------------
+
+ Check(E_INVALIDARG, pPStg->SetTimes( (FILETIME*) INVALID_POINTER,
+ NULL, NULL ));
+ Check(E_INVALIDARG, pPStg->SetTimes( NULL,
+ (FILETIME*) INVALID_POINTER,
+ NULL ));
+ Check(E_INVALIDARG, pPStg->SetTimes( NULL, NULL,
+ (FILETIME*) INVALID_POINTER ));
+
+ // -------------------------------
+ // Test IPropertyStorage::SetClass
+ // -------------------------------
+
+ Check(E_INVALIDARG, pPStg->SetClass( (REFCLSID) *pfmtidNULL ));
+ Check(E_INVALIDARG, pPStg->SetClass( (REFCLSID) *pfmtidInvalid ));
+
+ // ---------------------------
+ // Test IPropertyStorage::Stat
+ // ---------------------------
+
+ Check(E_INVALIDARG, pPStg->Stat( NULL ));
+ Check(E_INVALIDARG, pPStg->Stat( (STATPROPSETSTG*) INVALID_POINTER ));
+
+
+ // ------------------------------
+ // Test IEnumSTATPROPSETSTG::Next
+ // ------------------------------
+
+ ULONG cEltFound;
+ TSafeStorage< IEnumSTATPROPSETSTG > pESPSStg;
+ Check(S_OK, pPSStg->Enum( &pESPSStg ));
+
+ // Invalid STATPROPSETSTG*
+
+ Check(E_INVALIDARG, pESPSStg->Next( 1, NULL, &cEltFound ));
+ Check(E_INVALIDARG, pESPSStg->Next( 1, (STATPROPSETSTG*) INVALID_POINTER, &cEltFound ));
+
+ // Invalid pceltFound
+
+ Check(S_OK, pESPSStg->Next( 1, rgStatPSStgAllAccess, NULL ));
+ Check(STG_E_INVALIDPARAMETER, pESPSStg->Next( 2, rgStatPSStgAllAccess, NULL ));
+ Check(E_INVALIDARG, pESPSStg->Next( 2, rgStatPSStgAllAccess, (ULONG*) INVALID_POINTER ));
+
+ // Too short STATPROPSETSTG[]
+
+ Check(E_INVALIDARG, pESPSStg->Next( 2, rgStatPSStgReadAccess, &cEltFound ));
+
+ // -------------------------------
+ // Test IEnumSTATPROPSETSTG::Clone
+ // -------------------------------
+
+ // Invalid IEnumSTATPROPSETSTG**
+
+ Check(E_INVALIDARG, pESPSStg->Clone( NULL ));
+ Check(E_INVALIDARG, pESPSStg->Clone( (IEnumSTATPROPSETSTG**) INVALID_POINTER ));
+
+
+ // ---------------------------
+ // Test IEnumSTATPROPSTG::Next
+ // ---------------------------
+
+ TSafeStorage< IEnumSTATPROPSTG > pESPStg;
+ Check(S_OK, pPStg->Enum( &pESPStg ));
+
+ // Invalid STATPROPSETSTG*
+
+ Check(E_INVALIDARG, pESPStg->Next( 1, NULL, &cEltFound ));
+ Check(E_INVALIDARG, pESPStg->Next( 1, (STATPROPSTG*) INVALID_POINTER, &cEltFound ));
+
+ // Invalid pceltFound
+
+ Check(S_OK, pESPStg->Next( 1, rgStatPStgAllAccess, NULL ));
+ Check(STG_E_INVALIDPARAMETER, pESPStg->Next( 2, rgStatPStgAllAccess, NULL ));
+ Check(E_INVALIDARG, pESPStg->Next( 2, rgStatPStgAllAccess, (ULONG*) INVALID_POINTER ));
+
+ // Too short STATPROPSTG[]
+
+ Check(E_INVALIDARG, pESPStg->Next( 2, rgStatPStgReadAccess, &cEltFound ));
+
+
+ // ----------------------------
+ // Test IEnumSTATPROPSTG::Clone
+ // ----------------------------
+
+ // Invalid IEnumSTATPROPSETSTG**
+
+ Check(E_INVALIDARG, pESPStg->Clone( NULL ));
+ Check(E_INVALIDARG, pESPStg->Clone( (IEnumSTATPROPSTG**) INVALID_POINTER ));
+
+ // --------------------------------------------
+ // Test PropStgNameToFmtId & FmtIdToPropStgName
+ // --------------------------------------------
+
+ // We're done with the IPropertyStorage and IPropertySetStorage
+ // now, but we need the pointers for some calls below, so let's
+ // free them now.
+
+ pPStg->Release();
+ pPStg = NULL;
+
+ pPSStg->Release();
+ pPSStg = NULL;
+
+
+ OLECHAR oszPropStgName[ CCH_MAX_PROPSTG_NAME+1 ];
+
+ // Validate the FMTID parm
+
+ Check( E_INVALIDARG, PropStgNameToFmtId( oszPropStgName, pfmtidNULL ));
+ Check( E_INVALIDARG, PropStgNameToFmtId( oszPropStgName, pfmtidInvalid ));
+ Check( E_INVALIDARG, PropStgNameToFmtId( oszPropStgName, (FMTID*) pbReadOnly ));
+
+ Check( E_INVALIDARG, FmtIdToPropStgName( pfmtidNULL, oszPropStgName ));
+ Check( E_INVALIDARG, FmtIdToPropStgName( pfmtidInvalid, oszPropStgName ));
+ Check( S_OK, FmtIdToPropStgName( (FMTID*) pbReadOnly, oszPropStgName ));
+
+ // Validate the name parameter
+
+ FMTID fmtidPropStgName = FMTID_NULL;
+ Check( STG_E_INVALIDNAME, PropStgNameToFmtId( NULL, &fmtidPropStgName ));
+ Check( STG_E_INVALIDNAME, PropStgNameToFmtId( (LPOLESTR) INVALID_POINTER, &fmtidPropStgName ));
+ Check( STG_E_INVALIDNAME, PropStgNameToFmtId( (LPOLESTR) pbNoAccess, &fmtidPropStgName));
+ Check( S_OK, PropStgNameToFmtId( (LPOLESTR) pbReadOnly, &fmtidPropStgName ));
+
+ Check( E_INVALIDARG, FmtIdToPropStgName( &fmtidPropStgName, NULL ));
+ Check( E_INVALIDARG, FmtIdToPropStgName( &fmtidPropStgName, (LPOLESTR) INVALID_POINTER ));
+ Check( E_INVALIDARG, FmtIdToPropStgName( &fmtidPropStgName, (LPOLESTR) pbReadOnly ));
+
+ // ------------------------------------------
+ // Test StgCreatePropStg, StgOpenPropStg APIs
+ // ------------------------------------------
+
+ TSafeStorage< IStream > pStm;
+
+ // We need a Stream for one of the tests.
+
+ Check( S_OK, pStg->CreateStream( OLESTR( "Parameter Validation" ),
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L, 0L,
+ &pStm ));
+
+ // Test the IUnknown
+
+ Check( E_INVALIDARG, StgCreatePropStg( NULL, fmtidPropStgName, NULL, PROPSETFLAG_DEFAULT, 0, &pPStg ));
+ Check( E_INVALIDARG, StgOpenPropStg( NULL, fmtidPropStgName, PROPSETFLAG_DEFAULT, 0L, &pPStg ));
+
+ // Test the FMTID
+
+ Check( E_INVALIDARG, StgCreatePropStg( (IUnknown*) pStm, *pfmtidNULL, NULL, PROPSETFLAG_DEFAULT, 0, &pPStg ));
+ Check( E_INVALIDARG, StgOpenPropStg( (IUnknown*) pStm, *pfmtidNULL, PROPSETFLAG_DEFAULT, 0, &pPStg ));
+
+ Check( E_INVALIDARG, StgCreatePropStg( (IUnknown*) pStm, *pfmtidInvalid, NULL, PROPSETFLAG_DEFAULT, 0, &pPStg ));
+ Check( E_INVALIDARG, StgOpenPropStg( (IUnknown*) pStm, *pfmtidInvalid, PROPSETFLAG_DEFAULT, 0, &pPStg ));
+
+ // Test the CLSID
+
+ Check( E_INVALIDARG, StgCreatePropStg( (IUnknown*) pStm, fmtidPropStgName, (CLSID*) pfmtidInvalid, PROPSETFLAG_DEFAULT, 0, &pPStg ));
+
+ // Test grfFlags
+
+ Check( STG_E_INVALIDFLAG, StgCreatePropStg( (IUnknown*) pStm, fmtidPropStgName, NULL, 0x8000, 0L, &pPStg ));
+ Check( STG_E_INVALIDFLAG, StgOpenPropStg( (IUnknown*) pStm, fmtidPropStgName, 0x8000, 0L, &pPStg ));
+
+ Check( E_NOINTERFACE, StgCreatePropStg( (IUnknown*) pStm, fmtidPropStgName, NULL, PROPSETFLAG_NONSIMPLE, 0L, &pPStg ));
+ Check( E_NOINTERFACE, StgCreatePropStg( (IUnknown*) pStg, fmtidPropStgName, NULL, PROPSETFLAG_DEFAULT, 0L, &pPStg ));
+ Check( E_NOINTERFACE, StgOpenPropStg( (IUnknown*) pStm, fmtidPropStgName, PROPSETFLAG_NONSIMPLE, 0L, &pPStg ));
+ Check( E_NOINTERFACE, StgOpenPropStg( (IUnknown*) pStg, fmtidPropStgName, PROPSETFLAG_DEFAULT , 0L, &pPStg ));
+
+ // Test IPropertyStorage**
+
+ Check( E_INVALIDARG, StgCreatePropStg( (IUnknown*) pStm, fmtidPropStgName, NULL, PROPSETFLAG_DEFAULT, 0L, NULL ));
+ Check( E_INVALIDARG, StgOpenPropStg( (IUnknown*) pStm, fmtidPropStgName, PROPSETFLAG_DEFAULT, 0L, NULL ));
+
+ Check( E_INVALIDARG, StgCreatePropStg( (IUnknown*) pStm, fmtidPropStgName, NULL, PROPSETFLAG_DEFAULT, 0L, (IPropertyStorage**) INVALID_POINTER ));
+ Check( E_INVALIDARG, StgOpenPropStg( (IUnknown*) pStm, fmtidPropStgName, PROPSETFLAG_DEFAULT, 0L, (IPropertyStorage**) INVALID_POINTER ));
+
+ Check( E_INVALIDARG, StgCreatePropStg( (IUnknown*) pStm, fmtidPropStgName, NULL, PROPSETFLAG_DEFAULT, 0L, (IPropertyStorage**) pbReadOnly ));
+ Check( E_INVALIDARG, StgOpenPropStg( (IUnknown*) pStm, fmtidPropStgName, PROPSETFLAG_DEFAULT, 0L, (IPropertyStorage**) pbReadOnly ));
+
+ // ----------------------------
+ // Test StgCreatePropSetStg API
+ // ----------------------------
+
+ // Test the IStorage*
+
+ Check( E_INVALIDARG, StgCreatePropSetStg( NULL, 0L, &pPSStg ));
+ Check( E_INVALIDARG, StgCreatePropSetStg( (IStorage*) INVALID_POINTER, 0L, &pPSStg ));
+
+ // Test the IPropertySetStorage**
+
+ Check( E_INVALIDARG, StgCreatePropSetStg( pStg, 0L, NULL ));
+ Check( E_INVALIDARG, StgCreatePropSetStg( pStg, 0L, (IPropertySetStorage**) INVALID_POINTER ));
+
+
+ // -------------------------------------------------------------
+ // Test PropVariantCopy, PropVariantClear & FreePropVariantArray
+ // -------------------------------------------------------------
+
+ // PropVariantCopy
+
+ Check( E_INVALIDARG, PropVariantCopy( rgcpropvarAllAccess, NULL ));
+ Check( E_INVALIDARG, PropVariantCopy( rgcpropvarAllAccess, (PROPVARIANT*) INVALID_POINTER ));
+
+ Check( E_INVALIDARG, PropVariantCopy( NULL, rgcpropvarAllAccess ));
+ Check( E_INVALIDARG, PropVariantCopy( (PROPVARIANT*) INVALID_POINTER, rgcpropvarAllAccess ));
+ Check( E_INVALIDARG, PropVariantCopy( (PROPVARIANT*) pbReadOnly, rgcpropvarAllAccess ));
+
+ // PropVariantClear
+
+ Check( S_OK, PropVariantClear( NULL ));
+ Check( E_INVALIDARG, PropVariantClear( (PROPVARIANT*) INVALID_POINTER ));
+ Check( E_INVALIDARG, PropVariantClear( (PROPVARIANT*) pbReadOnly ));
+
+ // FreePropVariantArray
+
+ Check( E_INVALIDARG, FreePropVariantArray( 1, NULL ));
+ Check( E_INVALIDARG, FreePropVariantArray( 1, (PROPVARIANT*) INVALID_POINTER ));
+
+ Check( S_OK, FreePropVariantArray( 1, (PROPVARIANT*) (void*)rgcpropvarReadAccess ));
+ Check( E_INVALIDARG, FreePropVariantArray( 2, (PROPVARIANT*) (void*)rgcpropvarReadAccess ));
+
+
+ // ----
+ // Exit
+ // ----
+
+ VirtualFree( rgpropspecNoAccessBase, 0, MEM_RELEASE );
+ VirtualFree( rgcpropvarReadAccessBase, 0, MEM_RELEASE );
+ VirtualFree( rgcpropvarNoAccessBase, 0, MEM_RELEASE );
+ VirtualFree( rgpropidNoAccessBase, 0, MEM_RELEASE );
+ VirtualFree( rgpropidReadAccessBase, 0, MEM_RELEASE );
+ VirtualFree( rglpwstrNoAccessBase, 0, MEM_RELEASE );
+ VirtualFree( rglpwstrReadAccessBase, 0, MEM_RELEASE );
+ VirtualFree( rgStatPSStgReadAccessBase, 0, MEM_RELEASE );
+ VirtualFree( rgStatPStgReadAccessBase, 0, MEM_RELEASE );
+
+#endif // #ifdef WIN32
+
+} // test_ParameterValidation(IStorage *pStg)
+
+
+
+
+
+// Check creation/open/deletion of property sets (check fmtid and predefined names)
+// Create a property set
+// Try recreate of same
+// Try delete
+// Close the property set
+// Try recreate of same
+// Reopen the property set
+// Try recreate of same
+// Try delete
+// Close the property set
+// Delete the property set
+// Repeat the test once more
+
+void
+test_IPropertySetStorage_CreateOpenDelete(IStorage *pStorage)
+{
+ STATUS(( " IPropertySetStorage::Create/Open/Delete\n" ));
+
+ FMTID fmtid;
+ PROPSPEC propspec;
+
+ UuidCreate(&fmtid);
+
+ for (int i=0; i<4; i++)
+ {
+ if (g_fOFS && ((i&2) != 0))
+ {
+ continue;
+ }
+
+
+ {
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+ IPropertyStorage *PropStg, *PropStg2;
+
+ Check(S_OK, pPropSetStg->Create(fmtid,
+ NULL,
+ (i&2) == 0 ? PROPSETFLAG_DEFAULT : PROPSETFLAG_NONSIMPLE,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &PropStg));
+ if (!g_fOFS) // BUGBUG: OFS truncates streams
+ Check(g_fOFS ? STG_E_SHAREVIOLATION : S_OK, pPropSetStg->Create(fmtid,
+ NULL,
+ (i&2) == 0 ? PROPSETFLAG_DEFAULT : PROPSETFLAG_NONSIMPLE,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &PropStg2));
+
+ Check(g_fOFS ? S_OK : STG_E_REVERTED, PropStg->Commit(0));
+
+ PropStg->Release();
+ if (!g_fOFS) PropStg2->Release();
+ }
+ {
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+ IPropertyStorage *PropStg, *PropStg2;
+
+ // use STGM_FAILIFTHERE
+ Check(STG_E_FILEALREADYEXISTS, pPropSetStg->Create(fmtid,
+ NULL,
+ (i&2) == 0 ? PROPSETFLAG_DEFAULT : PROPSETFLAG_NONSIMPLE,
+ STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &PropStg));
+
+ Check(S_OK, pPropSetStg->Open(fmtid,
+ STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &PropStg));
+
+ Check(g_fOFS ? STG_E_FILEALREADYEXISTS : STG_E_ACCESSDENIED, pPropSetStg->Create(fmtid,
+ NULL,
+ (i&2) == 0 ? PROPSETFLAG_DEFAULT : PROPSETFLAG_NONSIMPLE,
+ STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &PropStg2));
+
+ Check(g_fOFS ? STG_E_SHAREVIOLATION : S_OK /*STG_E_ACCESSDENIED*/, pPropSetStg->Delete(fmtid));
+
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = 1000;
+ PROPVARIANT propvar;
+ propvar.vt = VT_I4;
+ propvar.lVal = 12345;
+ Check(g_fOFS ? S_OK : STG_E_REVERTED, PropStg->WriteMultiple(1, &propspec, &propvar, 2)); // force dirty
+
+ PropStg->Release();
+
+ //Check(S_OK, pPropSetStg->Delete(fmtid));
+ }
+ }
+
+ // --------------------------------------------------------
+ // Test the Create/Delete of the DocumentSummaryInformation
+ // property set (this requires special code because it
+ // has two sections).
+ // --------------------------------------------------------
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+ TSafeStorage< IPropertyStorage> pPropStg1, pPropStg2;
+
+ // Create & Delete a DSI propset with just the first section.
+
+ Check(S_OK, pPropSetStg->Create(FMTID_DocSummaryInformation,
+ NULL,
+ PROPSETFLAG_DEFAULT,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &pPropStg1));
+
+ pPropStg1->Release(); pPropStg1 = NULL;
+ Check(S_OK, pPropSetStg->Delete( FMTID_DocSummaryInformation ));
+
+ // Create & Delete a DSI propset with just the second section
+
+ Check(S_OK, pPropSetStg->Create(FMTID_UserDefinedProperties,
+ NULL,
+ PROPSETFLAG_DEFAULT,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &pPropStg1 ));
+
+ pPropStg1->Release(); pPropStg1 = NULL;
+ Check(S_OK, pPropSetStg->Delete( FMTID_UserDefinedProperties ));
+
+ // Create & Delete a DocumentSummaryInformation propset with both sections.
+ // If you delete the DSI propset first, it should delete both sections.
+ // If you delete the UD propset first, the DSI propset should still
+ // remain. We'll loop twice, trying both combinations.
+
+ for( i = 0; i < 2; i++ )
+ {
+
+ // Create the first section, which implicitely creates
+ // the second section.
+
+ Check(S_OK, pPropSetStg->Create(FMTID_DocSummaryInformation,
+ NULL,
+ PROPSETFLAG_DEFAULT,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &pPropStg1));
+
+ pPropStg1->Release(); pPropStg1 = NULL;
+
+ if( i == 0 )
+ {
+ Check(S_OK, pPropSetStg->Delete( FMTID_UserDefinedProperties ));
+ Check(S_OK, pPropSetStg->Delete( FMTID_DocSummaryInformation ));
+ }
+ else
+ {
+ Check(S_OK, pPropSetStg->Delete( FMTID_DocSummaryInformation ));
+ Check(STG_E_FILENOTFOUND, pPropSetStg->Delete( FMTID_UserDefinedProperties ));
+ }
+ } // for( i = 0; i < 2; i++ )
+
+ // -------------------------------------
+ // Test special properties in DocSumInfo
+ // -------------------------------------
+
+ // This verifies that when we Create a DocSumInfo
+ // property set, and write a Vector or LPSTRs,
+ // we can read it again. We test this because
+ // Vectors of LPSTRs are a special case in the DocSumInfo,
+ // and the Create & Open path are slightly different
+ // in CPropertySetStream::_LoadHeader.
+
+ // Create a new property set.
+
+ Check(S_OK, pPropSetStg->Create(FMTID_DocSummaryInformation,
+ NULL,
+ PROPSETFLAG_DEFAULT,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &pPropStg1));
+
+ // Create a vector of LPSTRs. Make the strings
+ // varying lengths to ensure we get plenty of
+ // opportunity for alignment problems.
+
+ CPropVariant cpropvarWrite, cpropvarRead;
+
+ cpropvarWrite[3] = "12345678";
+ cpropvarWrite[2] = "1234567";
+ cpropvarWrite[1] = "123456";
+ cpropvarWrite[0] = "12345";
+ ASSERT( cpropvarWrite.Count() == 4 );
+
+ // Write the property
+
+ propspec.ulKind = PRSPEC_LPWSTR;
+ propspec.lpwstr = OLESTR("A Vector of LPSTRs");
+
+ Check(S_OK, pPropStg1->WriteMultiple( 1, &propspec, cpropvarWrite, 2 ));
+
+ // Read the property back.
+
+ Check(S_OK, pPropStg1->ReadMultiple( 1, &propspec, cpropvarRead ));
+
+ // Verify that we read what we wrote.
+
+ for( i = 0; i < (int) cpropvarWrite.Count(); i++ )
+ {
+ Check(0, strcmp( (LPSTR) cpropvarWrite[i], (LPSTR) cpropvarRead[i] ));
+ }
+
+}
+
+
+void
+test_IPropertySetStorage_SummaryInformation(IStorage *pStorage)
+{
+ STATUS(( " SummaryInformation\n" ))
+ ;
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+ IPropertyStorage *PropStg;
+ IStream *pstm;
+
+ Check(S_OK, pPropSetStg->Create(FMTID_SummaryInformation,
+ NULL,
+ PROPSETFLAG_DEFAULT, // simple, wide
+ STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &PropStg));
+
+ PropStg->Release();
+
+ Check(S_OK, pStorage->OpenStream(OLESTR("\005SummaryInformation"),
+ NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0,
+ &pstm));
+
+ pstm->Release();
+}
+
+//
+// Check STGM_FAILIFTHERE and ~STGM_FAILIFTHERE in following cases
+// Check overwriting simple with extant non-simple
+// Check overwriting simple with simple
+// Check overwriting non-simple with simple
+// Check overwriting non-simple with non-simple
+
+void
+test_IPropertySetStorage_FailIfThere(IStorage *pStorage)
+{
+ // (Use "fale" instead of "fail" in this printf so the output won't
+ // alarm anyone with the word "fail" uncessarily).
+ STATUS(( " IPropertySetStorage, FaleIfThere\n" ));
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+
+ // Iter 0 1 2 3 4 5 6 7
+ // Create simple nonsimple simple nonsimple simple nonsimple simple nonsimple
+ // ReCreate simple simple nonsimple nonsimple simple simple nonsimple nonsimple
+ // failif failif failif failif overw overw overw overw
+ //
+ // expected exists exists exists exists ok ok ok ok
+
+ for (int i=0; i<8; i++)
+ {
+ FMTID fmtid;
+ IPropertyStorage *PropStg;
+
+ if (g_fOFS && ((i & 2) == 2 || (i & 1) == 1))
+ {
+ continue;
+ }
+
+ UuidCreate(&fmtid);
+
+ Check(S_OK, pPropSetStg->Create(fmtid,
+ NULL,
+ (i & 1) == 1 ? PROPSETFLAG_NONSIMPLE : 0,
+ STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &PropStg));
+
+ PropStg->Release();
+
+ Check((i&4) == 4 ? S_OK : STG_E_FILEALREADYEXISTS,
+ pPropSetStg->Create(fmtid,
+ NULL,
+ (i & 2) == 2 ? PROPSETFLAG_NONSIMPLE : 0,
+ ( (i & 4) == 4 ? STGM_CREATE : STGM_FAILIFTHERE) |
+ STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &PropStg));
+
+ if (PropStg)
+ {
+ PropStg->Release();
+ }
+ }
+}
+
+//
+//
+//
+// Bad this pointer.
+// Call all methods with a bad this pointer, check we get STG_E_INVALIDHANDLE
+//
+
+void
+test_IPropertySetStorage_BadThis(IStorage *pIgnored)
+{
+ STATUS(( " Bad IPropertySetStorage 'this' pointer\n" ));
+
+ IPropertySetStorage *pBad;
+ IID iid;
+ FMTID fmtid;
+ void *pv;
+ IPropertyStorage *pps;
+ IEnumSTATPROPSETSTG *penm;
+
+ {
+ CTempStorage pStorage;
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+ pBad = pPropSetStg.operator -> ();
+ }
+
+ Check(STG_E_INVALIDHANDLE,pBad->QueryInterface(iid, &pv));
+ Check(0, pBad->AddRef());
+ Check(0, pBad->Release());
+ Check(STG_E_INVALIDHANDLE,pBad->Create( fmtid, NULL, 0, 0, &pps));
+ Check(STG_E_INVALIDHANDLE,pBad->Open(fmtid, 0, &pps));
+ Check(STG_E_INVALIDHANDLE,pBad->Delete( fmtid ));
+ Check(STG_E_INVALIDHANDLE,pBad->Enum( &penm ));
+
+}
+
+// Transacted mode
+// Create a non-simple property set with one VT_STREAM child, close it
+// Open it in transacted mode
+// Write another VT_STORAGE child
+// Close and revert
+// Check that the second child does not exist.
+// Repeat and close and commit and check the child exists.
+
+// BUGBUG -- need test of IPropertySetStorage::Revert
+
+void
+test_IPropertySetStorage_TransactedMode(IStorage *pStorage)
+{
+ STATUS(( " Transacted Mode\n" ));
+
+ FMTID fmtid;
+
+ UuidCreate(&fmtid);
+
+ if (g_fOFS)
+ {
+ return;
+ }
+
+ {
+ //
+ // create a substorage "teststg" with a propset
+ // create a stream "src" which is then written via VT_STREAM as propid 7fffffff
+ CTempStorage pSubStorage(coCreate, pStorage, OLESTR("teststg"));
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pSubStorage);
+ IPropertyStorage *pPropSet;
+ IStream *pstm;
+
+ Check(S_OK, pPropSetStg->Create(fmtid, NULL, PROPSETFLAG_NONSIMPLE,
+ STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
+ &pPropSet));
+
+ PROPSPEC ps;
+ ps.ulKind = PRSPEC_PROPID;
+ ps.propid = 0x7ffffffd;
+
+ Check(S_OK, pStorage->CreateStream(OLESTR("src"), STGM_DIRECT|STGM_SHARE_EXCLUSIVE|STGM_READWRITE,
+ 0,0, &pstm));
+ Check(S_OK, pstm->Write(L"billmo", 14, NULL));
+ Check(S_OK, pstm->Seek(g_li0, STREAM_SEEK_SET, NULL));
+
+ PROPVARIANT pv;
+ pv.vt = VT_STREAM;
+ pv.pStream = pstm;
+ Check(S_OK, pPropSet->WriteMultiple(1, &ps, &pv, 2)); // copies the stream in
+
+ pPropSet->Release();
+ pstm->Release();
+ }
+
+ {
+ IPropertyStorage *pPropSet;
+ // Reopen the propset in transacted and add one with id 0x7ffffffe
+ CTempStorage pSubStorage(coOpen, pStorage, OLESTR("teststg"), STGM_TRANSACTED);
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pSubStorage);
+
+ // Create a storage object to copy
+ CTempStorage pstgSrc;
+ CTempStorage pTestChild(coCreate, pstgSrc, OLESTR("testchild"));
+
+ Check(S_OK, pPropSetStg->Open(fmtid,
+ STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
+ &pPropSet));
+
+ // copy in the storage object
+ PROPSPEC ps[2];
+ ps[0].ulKind = PRSPEC_PROPID;
+ ps[0].propid = 0x7ffffffe;
+ ps[1].ulKind = PRSPEC_PROPID;
+ ps[1].propid = 0x7ffffff0;
+
+ PROPVARIANT pv[2];
+ pv[0].vt = VT_STORAGE;
+ pv[0].pStorage = pTestChild;
+ pv[1].vt = VT_I4;
+ pv[1].lVal = 123;
+
+ Check(S_OK, pPropSet->WriteMultiple(2, ps, pv, 2)); // copies the storage in
+
+
+ pSubStorage->Revert(); // throws away the storage
+
+ // check that property set operations return stg_e_reverted
+
+ Check(STG_E_REVERTED, pPropSet->WriteMultiple(2, ps, pv, 2));
+ Check(STG_E_REVERTED, pPropSet->ReadMultiple(1, ps+1, pv+1));
+ Check(STG_E_REVERTED, pPropSet->DeleteMultiple(1, ps+1));
+ LPOLESTR pstr;
+ Check(STG_E_REVERTED, pPropSet->ReadPropertyNames(1, &ps[1].propid, &pstr));
+ Check(STG_E_REVERTED, pPropSet->WritePropertyNames(1, &ps[1].propid, &pstr));
+ Check(STG_E_REVERTED, pPropSet->DeletePropertyNames(1, &ps[1].propid));
+ Check(STG_E_REVERTED, pPropSet->Commit(STGC_DEFAULT));
+ Check(STG_E_REVERTED, pPropSet->Revert());
+ IEnumSTATPROPSTG *penum;
+ Check(STG_E_REVERTED, pPropSet->Enum(&penum));
+ FILETIME ft;
+ Check(STG_E_REVERTED, pPropSet->SetTimes(&ft, &ft, &ft));
+ CLSID clsid;
+ Check(STG_E_REVERTED, pPropSet->SetClass(clsid));
+ STATPROPSETSTG statpropsetstg;
+ Check(STG_E_REVERTED, pPropSet->Stat(&statpropsetstg));
+
+ pPropSet->Release();
+ }
+
+ {
+ IPropertyStorage *pPropSet;
+ // Reopen the propset in direct mode and check that the
+ // second child is not there.
+
+ CTempStorage pSubStorage(coOpen, pStorage, OLESTR("teststg"));
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pSubStorage);
+
+ Check(S_OK, pPropSetStg->Open(fmtid,
+ STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
+ &pPropSet));
+
+ // read out the storage object
+ PROPSPEC aps[2];
+ aps[0].ulKind = PRSPEC_PROPID;
+ aps[0].propid = 0x7ffffffe; // storage not expected
+ aps[1].ulKind = PRSPEC_PROPID;
+ aps[1].propid = 0x7ffffffd; // stream is expected
+
+ PROPVARIANT apv[2];
+ Check(S_FALSE, pPropSet->ReadMultiple(1, aps, apv));
+ Check(S_OK, pPropSet->ReadMultiple(2, aps, apv)); // opens the stream
+ ASSERT(apv[0].vt == VT_EMPTY);
+ ASSERT(apv[1].vt == VT_STREAM);
+ ASSERT(apv[1].pStream != NULL);
+
+
+ WCHAR wcsBillMo[7];
+ Check(S_OK, apv[1].pStream->Read(wcsBillMo, 14, NULL));
+ ASSERT(wcscmp(L"billmo", wcsBillMo) == 0);
+
+ apv[1].pStream->Release();
+ pPropSet->Release();
+ }
+}
+
+//
+// test that the buffer is correctly reverted
+//
+
+void
+test_IPropertySetStorage_TransactedMode2(IStorage *pStorage)
+{
+ STATUS(( " Transacted Mode 2\n" ));
+
+ if (g_fOFS)
+ {
+ return;
+ }
+ //
+ // write and commit a property A
+ // write and revert a property B
+ // write and commit a property C
+ // check that property B does not exist
+
+ FMTID fmtid;
+ PROPSPEC ps;
+ PROPVARIANT pv;
+ IPropertyStorage *pPropStg;
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+
+ UuidCreate(&fmtid);
+
+ // We'll run this test twice, once with a Create and the other
+ // with an Open (this way, we test both of the CPropertyStorage
+ // constructors).
+
+ for( int i = 0; i < 2; i++ )
+ {
+ if( i == 0 )
+ {
+ Check(S_OK, pPropSetStg->Create(fmtid, NULL, PROPSETFLAG_NONSIMPLE,
+ STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, &pPropStg));
+ }
+ else
+ {
+ Check(S_OK, pPropSetStg->Open(fmtid,
+ STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, &pPropStg));
+ }
+
+ ps.ulKind = PRSPEC_PROPID;
+ ps.propid = 6;
+ pv.vt = VT_I4;
+ pv.lVal = 1;
+
+ Check(S_OK, pPropStg->WriteMultiple(1, &ps, &pv, 0x2000));
+ Check(S_OK, pPropStg->Commit(STGC_DEFAULT));
+
+ ps.propid = 7;
+ pv.lVal = 2;
+
+ Check(S_OK, pPropStg->WriteMultiple(1, &ps, &pv, 0x2000));
+ Check(S_OK, pPropStg->Revert());
+
+ ps.propid = 8;
+ pv.lVal = 3;
+
+ Check(S_OK, pPropStg->WriteMultiple(1, &ps, &pv, 0x2000));
+ Check(S_OK, pPropStg->Commit(STGC_DEFAULT));
+
+ ps.propid = 6;
+ Check(S_OK, pPropStg->ReadMultiple(1, &ps, &pv));
+ ASSERT(pv.lVal == 1);
+ ASSERT(pv.vt == VT_I4);
+
+ ps.propid = 7;
+ Check(S_FALSE, pPropStg->ReadMultiple(1, &ps, &pv));
+
+ ps.propid = 8;
+ Check(S_OK, pPropStg->ReadMultiple(1, &ps, &pv));
+ ASSERT(pv.lVal == 3);
+ ASSERT(pv.vt == VT_I4);
+
+ pPropStg->Release();
+
+ } // for( int i = 0; i < 2; i++ )
+}
+
+void
+test_IPropertySetStorage_SubPropertySet(IStorage *pStorage)
+{
+ STATUS(( " Sub Property Set\n" ));
+
+ if (g_fOFS)
+ {
+ return;
+ }
+ FMTID fmtid;
+ PROPSPEC ps;
+ PROPVARIANT pv;
+ IPropertyStorage *pPropStg;
+ IPropertySetStorage *pSubSetStg;
+ IPropertyStorage *pPropStg2;
+
+ for (int i=0; i<2; i++)
+ {
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+
+ UuidCreate(&fmtid);
+
+
+ Check(S_OK, pPropSetStg->Create(fmtid, NULL, PROPSETFLAG_NONSIMPLE,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE, &pPropStg));
+
+ ps.ulKind = PRSPEC_PROPID;
+ ps.propid = 6;
+ pv.vt = VT_STORAGE;
+ pv.pStorage = NULL;
+
+ Check(S_OK, pPropStg->WriteMultiple(1, &ps, &pv, 0x2000));
+
+ Check(S_OK, pPropStg->ReadMultiple(1, &ps, &pv));
+
+
+// Check(S_OK, pv.pStorage->QueryInterface(IID_IPropertySetStorage, (void**)&pSubSetStg));
+ Check(S_OK, StgCreatePropSetStg( pv.pStorage, 0L, &pSubSetStg ));
+
+
+ Check(S_OK, pSubSetStg->Create(fmtid, NULL, i==0 ? PROPSETFLAG_NONSIMPLE : PROPSETFLAG_DEFAULT,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE, &pPropStg2));
+
+ IStorage *pstgTmp = pv.pStorage;
+ pv.pStorage = NULL;
+
+ if (i==1)
+ {
+ pv.vt = VT_I4;
+ }
+
+ Check(S_OK, pPropStg2->WriteMultiple(1, &ps, &pv, 0x2000));
+
+ pPropStg->Release();
+ pstgTmp->Release();
+ pSubSetStg->Release();
+ pPropStg2->Release();
+ }
+}
+
+/*
+The following sequence of operations:
+
+- open transacted docfile
+- open property set inside docfile
+- write properties
+- commit docfile
+- release property set
+
+results in a STG_E_REVERTED error being detected
+*/
+
+void
+test_IPropertySetStorage_CommitAtRoot(IStorage *pStorage)
+{
+ STATUS(( " Commit at root\n" ));
+
+ for (int i=0; i<6; i++)
+ {
+ FMTID fmtid;
+
+ Check(S_OK, StgCreateDocfile(NULL, STGM_CREATE | STGM_DELETEONRELEASE |
+ STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0,
+ &pStorage));
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+
+ UuidCreate(&fmtid);
+
+ IPropertyStorage *pPropStg;
+
+ Check(S_OK, pPropSetStg->Create(fmtid, NULL, PROPSETFLAG_DEFAULT,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE, &pPropStg));
+
+ PROPSPEC propspec;
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = 1000;
+ PROPVARIANT propvar;
+ propvar.vt = VT_I4;
+ propvar.lVal = 12345;
+
+ Check(S_OK, pPropStg->WriteMultiple(1, &propspec, &propvar, 2)); // force dirty
+
+ switch (i)
+ {
+ case 0:
+ Check(S_OK, pStorage->Commit(STGC_DEFAULT));
+ pStorage->Release();
+ pPropStg->Release();
+ break;
+ case 1:
+ Check(S_OK, pStorage->Commit(STGC_DEFAULT));
+ pPropStg->Release();
+ pStorage->Release();
+ break;
+ case 2:
+ pStorage->Release();
+ pPropStg->Release();
+ break;
+ case 3:
+ pPropStg->Commit(STGC_DEFAULT);
+ pPropStg->Release();
+ pStorage->Release();
+ break;
+ case 4:
+ pPropStg->Commit(STGC_DEFAULT);
+ pStorage->Release();
+ pPropStg->Release();
+ break;
+ case 5:
+ pPropStg->Release();
+ pStorage->Release();
+ break;
+ }
+ }
+}
+
+void
+test_IPropertySetStorage(IStorage *pStorage)
+{
+ // Check ref counting through different interfaces on object
+
+ if( g_fQIPropertySetStorage )
+ test_IPropertySetStorage_IUnknown(pStorage);
+ else
+ PRINTF( " Skipping IPropertySetStorage_IUnknown\n" );
+
+ test_IPropertySetStorage_CreateOpenDelete(pStorage);
+ test_IPropertySetStorage_SummaryInformation(pStorage);
+ test_IPropertySetStorage_FailIfThere(pStorage);
+
+ test_IPropertySetStorage_TransactedMode(pStorage);
+ test_IPropertySetStorage_TransactedMode2(pStorage);
+ test_IPropertySetStorage_SubPropertySet(pStorage);
+ test_IPropertySetStorage_CommitAtRoot(pStorage);
+}
+
+
+// IEnumSTATPROPSETSTG
+//
+// Check enumeration of property sets
+//
+// Check refcounting and IUnknown
+//
+// Create some property sets, predefined and not, simple and not, one through IStorage
+// Enumerate them and check
+// (check fmtid, grfFlags)
+// (check when asking for more than there is: S_FALSE, S_OK)
+// Delete one
+// Reset the enumerator
+// Enumerate them and check
+// Delete one
+//
+// Reset the enumeratorA
+// Read one from enumeratorA
+// Clone enumerator -> enumeratorB
+// Loop comparing rest of enumerator contents
+//
+// Reset the enumerator
+// Skip all
+// Check none left
+//
+// Reset the enumerator
+// Skip all but one
+// Check one left
+//
+void test_IEnumSTATPROPSETSTG(IStorage *pStorage)
+{
+ STATUS(( " IEnumSTATPROPSETSTG\n" ));
+
+ FMTID afmtid[8];
+ CLSID aclsid[8];
+ IPropertyStorage *pPropSet;
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+ FILETIME ftStart;
+
+ CoFileTimeNow(&ftStart);
+
+ pPropSetStg->Delete(FMTID_SummaryInformation);
+
+ for (int i=0; i<5; i++)
+ {
+ if (i & 4)
+ afmtid[i] = FMTID_SummaryInformation;
+ else
+ UuidCreate(&afmtid[i]);
+
+ UuidCreate(&aclsid[i]);
+
+ Check(S_OK, pPropSetStg->Create(afmtid[i], aclsid+i,
+ ((i & 1) && !g_fOFS ? PROPSETFLAG_NONSIMPLE : 0) |
+ ((i & 2) ? PROPSETFLAG_ANSI : 0),
+ STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
+ &pPropSet));
+ pPropSet->Release();
+ }
+
+
+ STATPROPSETSTG StatBuffer[6];
+ ULONG celt;
+ IEnumSTATPROPSETSTG *penum, *penum2;
+
+ Check(S_OK, pPropSetStg->Enum(&penum));
+
+ IUnknown *punk, *punk2;
+ IEnumSTATPROPSETSTG *penum3;
+ Check(S_OK, penum->QueryInterface(IID_IUnknown, (void**)&punk));
+ Check(S_OK, punk->QueryInterface(IID_IEnumSTATPROPSETSTG, (void**)&penum3));
+ Check(S_OK, penum->QueryInterface(IID_IEnumSTATPROPSETSTG, (void**)&punk2));
+ ASSERT(punk == punk2);
+ punk->Release();
+ penum3->Release();
+ punk2->Release();
+
+ // test S_FALSE
+ Check(S_FALSE, penum->Next(6, StatBuffer, &celt));
+ ASSERT(celt == 5);
+ penum->Reset();
+
+
+ // test reading half out, then cloning, then comparing
+ // rest of enumeration with other clone.
+
+ Check(S_OK, penum->Next(3, StatBuffer, &celt));
+ ASSERT(celt == 3);
+ celt = 0;
+ Check(S_OK, penum->Clone(&penum2));
+ Check(S_OK, penum->Next(2, StatBuffer, &celt));
+ ASSERT(celt == 2);
+ // check the clone
+ for (int c=0; c<2; c++)
+ {
+ STATPROPSETSTG CloneStat;
+ Check(S_OK, penum2->Next(1, &CloneStat, NULL));
+ Check(TRUE, 0 == memcmp(&CloneStat, StatBuffer+c, sizeof(CloneStat)));
+ Check(TRUE, CloneStat.dwOSVersion == PROPSETHDR_OSVERSION_UNKNOWN);
+ }
+
+ // check both empty
+ celt = 0;
+ Check(S_FALSE, penum->Next(1, StatBuffer, &celt));
+ ASSERT(celt == 0);
+
+ if (!g_fOFS)
+ { // BUGBUG: cloned enumerators don't work in OFS, RAID# 11662
+ Check(S_FALSE, penum2->Next(1, StatBuffer, &celt));
+ ASSERT(celt == 0);
+ }
+
+ penum->Reset();
+
+ //
+ // loop deleting one propset at a time
+ // enumerate the propsets checking that correct ones appear.
+ //
+ for (ULONG d = 0; d<5; d++)
+ {
+ // d is for delete
+
+ BOOL afFound[5];
+
+ Check(S_OK, penum->Next(5-d, StatBuffer, &celt));
+ ASSERT(celt == 5-d);
+ penum->Reset();
+
+ memset(afFound, 0, sizeof(afFound));
+ for (ULONG iPropSet=0; iPropSet<5; iPropSet++)
+ {
+ for (ULONG iSearch=0; iSearch<5-d; iSearch++)
+ {
+ if (0 == memcmp(&StatBuffer[iSearch].fmtid, &afmtid[iPropSet], sizeof(StatBuffer[0].fmtid)))
+ {
+ ASSERT (!afFound[iPropSet]);
+ afFound[iPropSet] = TRUE;
+ break;
+ }
+ }
+ if (iPropSet < d)
+ {
+ ASSERT(!afFound[iPropSet]);
+ }
+ if (iSearch == 5-d)
+ {
+ ASSERT(iPropSet < d);
+ continue;
+ }
+ ASSERT(((StatBuffer[iSearch].grfFlags & PROPSETFLAG_NONSIMPLE) ? 1u : 0u) ==
+ ((!g_fOFS && (iPropSet & 1)) ? 1u : 0u));
+ ASSERT((StatBuffer[iSearch].grfFlags & PROPSETFLAG_ANSI) == 0);
+ if (StatBuffer[iSearch].grfFlags & PROPSETFLAG_NONSIMPLE)
+ {
+ if (!g_fOFS) // BUGBUG: RAID # 13804. CNtEnum::Next does not return the
+ // clsid.
+ ASSERT(StatBuffer[iSearch].clsid == aclsid[iPropSet]);
+ }
+ else
+ {
+ ASSERT(StatBuffer[iSearch].clsid == CLSID_NULL);
+ }
+ CheckTime(ftStart, StatBuffer[iSearch].mtime);
+ CheckTime(ftStart, StatBuffer[iSearch].atime);
+ CheckTime(ftStart, StatBuffer[iSearch].ctime);
+ }
+
+ Check(S_OK, pPropSetStg->Delete(afmtid[d]));
+ Check(S_OK, penum->Reset());
+ }
+
+ penum->Release();
+ penum2->Release();
+
+}
+
+
+// Creation tests
+//
+// Access flags/Valid parameters/Permissions
+// Check readonly cannot be written -
+// WriteProperties, WritePropertyNames
+void
+test_IPropertyStorage_Access(IStorage *pStorage)
+{
+ STATUS(( " IPropertyStorage creation (access) tests\n" ));
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+ FMTID fmtid;
+
+ UuidCreate(&fmtid);
+
+ // check by name
+ IPropertyStorage *pPropStg;
+ Check(S_OK, pPropSetStg->Create(fmtid, NULL, 0,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE, &pPropStg));
+
+// QueryInterface tests
+// QI to IPropertyStorage
+// QI to IUnknown on IPropertyStorage
+// QI back to IPropertyStorage from IUnknown
+//
+// Release all.
+ IPropertyStorage *pPropStg2,*pPropStg3;
+ IUnknown *punk;
+
+ Check(S_OK, pPropStg->QueryInterface(IID_IPropertyStorage,
+ (void**)&pPropStg2));
+ Check(S_OK, pPropStg->QueryInterface(IID_IUnknown,
+ (void**)&punk));
+ Check(S_OK, punk->QueryInterface(IID_IPropertyStorage,
+ (void**)&pPropStg3));
+ pPropStg3->Release();
+ pPropStg2->Release();
+ punk->Release();
+
+ PROPSPEC ps;
+ ps.ulKind = PRSPEC_LPWSTR;
+ ps.lpwstr = OLESTR("testprop");
+ PROPVARIANT pv;
+ pv.vt = VT_LPOLESTR;
+ pv.pszVal = (LPSTR) OLESTR("testval");
+ Check(S_OK, pPropStg->WriteMultiple(1, &ps, &pv, 2));
+ pPropStg->Release();
+ Check(S_OK, pPropSetStg->Open(fmtid, STGM_SHARE_EXCLUSIVE | STGM_READ, &pPropStg));
+ Check(STG_E_ACCESSDENIED, pPropStg->WriteMultiple(1, &ps, &pv, 2));
+ Check(STG_E_ACCESSDENIED, pPropStg->DeleteMultiple(1, &ps));
+ PROPID propid=3;
+ Check(STG_E_ACCESSDENIED, pPropStg->WritePropertyNames(1, &propid, (LPOLESTR*) &pv.pszVal));
+ Check(STG_E_ACCESSDENIED, pPropStg->DeletePropertyNames(1, &propid));
+ FILETIME ft;
+ Check(STG_E_ACCESSDENIED, pPropStg->SetTimes(&ft, &ft, &ft));
+ CLSID clsid;
+ Check(STG_E_ACCESSDENIED, pPropStg->SetClass(clsid));
+
+ pPropStg->Release();
+}
+
+// Creation tests
+// Check VT_STREAM etc not usable with simple.
+// Check VT_STREAM etc usable with non-simple (tested by test transacted mode)
+//
+
+void
+test_IPropertyStorage_Create(IStorage *pStorage)
+{
+ STATUS(( " IPropertyStorage creation (simple/non-simple) tests\n" ));
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+ FMTID fmtid;
+
+ UuidCreate(&fmtid);
+
+ // check by name
+ IPropertyStorage *pPropStg;
+ Check(S_OK, pPropSetStg->Create(fmtid, NULL, 0 /* simple */,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE, &pPropStg));
+ PROPSPEC ps;
+ ps.ulKind = PRSPEC_PROPID;
+ ps.propid = 2;
+ PROPVARIANT pv;
+ pv.vt = VT_STREAM;
+ pv.pStream = NULL;
+ // BUGBUG Check(S_OK, pPropStg->WriteMultiple(1, &ps, &pv, 2000));
+ pPropStg->Release();
+}
+
+//
+//
+// Stat (Create four combinations)
+// Check non-simple/simple flag
+// Check ansi/wide fflag
+// Also test clsid on propset
+
+void test_IPropertyStorage_Stat(IStorage *pStorage)
+{
+ STATUS(( " IPropertyStorage::Stat\n" ));
+
+ DWORD dwOSVersion = 0;
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+ FMTID fmtid;
+ UuidCreate(&fmtid);
+ IPropertyStorage *pPropSet;
+ STATPROPSETSTG StatPropSetStg;
+
+ // Calculate the OS Version
+
+#ifdef _MAC
+ {
+ // Get the Mac System Version (e.g., 7.53).
+
+ OSErr oserr;
+ SysEnvRec theWorld;
+ oserr = SysEnvirons( curSysEnvVers, &theWorld );
+ Check( TRUE, noErr == oserr );
+
+ dwOSVersion = MAKEPSVER( OSKIND_MACINTOSH,
+ HIBYTE(theWorld.systemVersion),
+ LOBYTE(theWorld.systemVersion) );
+
+ }
+#else
+ dwOSVersion = MAKELONG( LOWORD(GetVersion()), OSKIND_WIN32 );
+#endif
+
+
+ for (ULONG i=0; i<4; i++)
+ {
+ FILETIME ftStart;
+ CoFileTimeNow(&ftStart);
+
+ if (g_fOFS && (i&1))
+ {
+ continue;
+ }
+
+ memset(&StatPropSetStg, 0, sizeof(StatPropSetStg));
+ CLSID clsid;
+ UuidCreate(&clsid);
+ if (g_fOFS)
+ UuidCreate(&fmtid);
+ Check(S_OK, pPropSetStg->Create(fmtid, &clsid,
+ ((i & 1) ? PROPSETFLAG_NONSIMPLE : 0) |
+ ((i & 2) ? PROPSETFLAG_ANSI : 0),
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSet));
+
+ CheckStat(pPropSet, fmtid, clsid, ((i & 1) ? PROPSETFLAG_NONSIMPLE : 0) |
+ ((i & 2) ? PROPSETFLAG_ANSI : 0), ftStart, dwOSVersion );
+ pPropSet->Release();
+
+ Check(S_OK, pPropSetStg->Open(fmtid,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSet));
+ CheckStat(pPropSet, fmtid, clsid, ((i & 1) ? PROPSETFLAG_NONSIMPLE : 0) |
+ ((i & 2) ? PROPSETFLAG_ANSI : 0), ftStart, dwOSVersion );
+ // BUGBUG VicH: UuidCreate(&clsid);
+ // BUGBUG VicH: Check(S_OK, pPropSet->SetClass(clsid));
+ pPropSet->Release();
+
+ Check(S_OK, pPropSetStg->Open(fmtid,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSet));
+ CheckStat(pPropSet, fmtid, clsid, ((i & 1) ? PROPSETFLAG_NONSIMPLE : 0) |
+ ((i & 2) ? PROPSETFLAG_ANSI : 0), ftStart, dwOSVersion );
+ pPropSet->Release();
+ }
+}
+
+// ReadMultiple
+// Check none found S_FALSE
+//
+// Success case non-simple readmultiple
+// Create a non-simple property set
+// Create two sub non-simples
+// Close all
+// Open the non-simple
+// Query for the two sub-nonsimples
+// Try writing to them
+// Close all
+// Open the non-simple
+// Query for the two sub-nonsimples
+// Check read back
+// Close all
+void
+test_IPropertyStorage_ReadMultiple_Normal(IStorage *pStorage)
+{
+ STATUS(( " IPropertyStorage::ReadMultiple (normal)\n" ));
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+ FMTID fmtid;
+ UuidCreate(&fmtid);
+ IPropertyStorage *pPropSet;
+
+ if (g_fOFS)
+ {
+ return;
+ }
+
+ Check(S_OK, pPropSetStg->Create(fmtid, NULL,
+ PROPSETFLAG_NONSIMPLE,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSet));
+
+ // none found
+ PROPSPEC ps[2];
+ // BUGBUG VicH fix: ps[0].ulKind = PRSPEC_LPWSTR;
+ // ps[0].lpwstr = L"testname";
+ ps[0].ulKind = PRSPEC_PROPID;
+ ps[0].propid = 500;
+ ps[1].ulKind = PRSPEC_PROPID;
+ ps[1].propid = 1000;
+
+ PROPVARIANT pv[2];
+ PROPVARIANT pvSave[2];
+ PROPVARIANT pvExtra[2];
+
+ Check(S_FALSE, pPropSet->ReadMultiple(2, ps, pv));
+
+ pv[0].vt = VT_STREAM;
+ pv[0].pStream = NULL;
+ pv[1].vt = VT_STORAGE;
+ pv[1].pStorage = NULL;
+
+ memcpy(pvSave, pv, sizeof(pvSave));
+ memcpy(pvExtra, pv, sizeof(pvExtra));
+
+ // write the two sub non-simples
+ Check(S_OK, pPropSet->WriteMultiple(2, ps, pv, 1000));
+
+ // re-open them
+ Check(S_OK, pPropSet->ReadMultiple(2, ps, pv));
+ ASSERT(pv[0].pStream != NULL);
+ ASSERT(pv[1].pStorage != NULL);
+
+ // check status of write when already open
+ Check(g_fOFS ? STG_E_SHAREVIOLATION : S_OK, pPropSet->WriteMultiple(2, ps, pvSave, 1000));
+
+ // On docfile when you revert, you can then open it again.
+ // On OFS it doesn't
+
+ if (!g_fOFS)
+ {
+ Check(STG_E_REVERTED, pv[0].pStream->Commit(0));
+ Check(STG_E_REVERTED, pv[1].pStorage->Commit(0));
+ Check(S_OK, pPropSet->ReadMultiple(2, ps, pvExtra));
+ ASSERT(pvExtra[0].pStream != NULL);
+ ASSERT(pvExtra[1].pStorage != NULL);
+ Check(S_OK, pvExtra[0].pStream->Commit(0));
+ Check(S_OK, pvExtra[1].pStorage->Commit(0));
+
+ pvExtra[0].pStream->Release();
+ pvExtra[1].pStorage->Release();
+ }
+ else
+ {
+ Check(S_OK, pv[0].pStream->Commit(0));
+ Check(S_OK, pv[1].pStorage->Commit(0));
+ }
+
+ pv[0].pStream->Release();
+ pv[1].pStorage->Release();
+
+ Check(S_OK, pPropSet->ReadMultiple(2, ps, pv));
+ ASSERT(pv[0].pStream != NULL);
+ ASSERT(pv[1].pStorage != NULL);
+
+ Check(S_OK, pv[0].pStream->Write("billmotest", sizeof("billmotest"), NULL));
+ IStream *pStm;
+ Check(S_OK, pv[1].pStorage->CreateStream(OLESTR("teststream"),
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0, 0, &pStm));
+ pStm->Release();
+ pv[0].pStream->Release();
+ pv[1].pStorage->Release();
+ pPropSet->Release();
+
+ // re-re-open them
+ Check(S_OK, pPropSetStg->Open(fmtid,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSet));
+ Check(S_OK, pPropSet->ReadMultiple(2, ps, pv));
+ ASSERT(pv[0].pStream != NULL);
+ ASSERT(pv[0].pStorage != NULL);
+
+ // read the stream and storage and check the contents.
+ char szBillMo[32];
+ Check(S_OK, pv[0].pStream->Read(szBillMo, 11, NULL));
+ ASSERT(0 == strcmp(szBillMo, "billmotest"));
+ Check(S_OK, pv[1].pStorage->OpenStream(OLESTR("teststream"), NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStm));
+ pStm->Release();
+ pv[1].pStorage->Release();
+ pv[0].pStream->Release();
+ pPropSet->Release();
+
+}
+
+//
+// CleanupOpenedObjects for ReadMultiple (two iterations one for "VT_STORAGE then VT_STREAM", one for
+// "VT_STREAM then VT_STORAGE")
+// Create property set
+// Create a "VT_STREAM then VT_STORAGE"
+// Open the second one exclusive
+// Formulate a query so that both are read - > will fail but ...
+// Check that the first one is still openable
+//
+
+void
+test_IPropertyStorage_ReadMultiple_Cleanup(IStorage *pStorage)
+{
+ STATUS(( " IPropertyStorage::ReadMultiple (cleanup)\n" ));
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+ FMTID fmtid;
+ UuidCreate(&fmtid);
+
+ if (g_fOFS)
+ {
+ return;
+ }
+
+ for (LONG i=0;i<2;i++)
+ {
+ IPropertyStorage * pPropSet;
+ Check(S_OK, pPropSetStg->Create(fmtid, NULL,
+ PROPSETFLAG_NONSIMPLE,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSet));
+
+ // none found
+ PROPSPEC ps[2];
+ ps[0].ulKind = PRSPEC_PROPID;
+ ps[0].propid = 1000;
+ ps[1].ulKind = PRSPEC_PROPID;
+ ps[1].propid = 2000;
+
+ PROPVARIANT pv[2];
+
+ pv[0].vt = (i == 0) ? VT_STREAM : VT_STORAGE;
+ pv[0].pStream = NULL;
+ pv[1].vt = (i == 1) ? VT_STORAGE : VT_STREAM;
+ pv[1].pStorage = NULL;
+
+ // write the two sub non-simples
+
+ // OFS gives driver internal error when overwriting a stream with a storage.
+ Check(S_OK, pPropSet->WriteMultiple(2, ps, pv, 1000));
+
+ // open both
+ Check(S_OK, pPropSet->ReadMultiple(2, ps, pv)); // **
+
+ // close the first ONLY and reopen both
+
+ PROPVARIANT pv2[2];
+
+ if (i==0)
+ pv[0].pStream->Release();
+ else
+ pv[0].pStorage->Release();
+
+ // reading both should fail because second is still open
+ Check(g_fOFS ? STG_E_SHAREVIOLATION : STG_E_ACCESSDENIED, pPropSet->ReadMultiple(2, ps, pv2));
+ // failure should not prevent this from succeeding
+ Check(S_OK, pPropSet->ReadMultiple(1, ps, pv2)); // ***
+
+ // cleanup from ** and ***
+ if (i==0)
+ {
+ pv2[0].pStream->Release(); // ***
+ pv[1].pStorage->Release(); // **
+ }
+ else
+ {
+ pv2[0].pStorage->Release(); // ***
+ pv[1].pStream->Release(); // **
+ }
+
+ pPropSet->Release();
+ }
+}
+
+// Reading an inconsistent non-simple
+// Create a non-simple
+// Create a sub-stream/storage
+// Close all
+// Delete the actual stream
+// Read the indirect property -> should not exist.
+//
+
+void
+test_IPropertyStorage_ReadMultiple_Inconsistent(IStorage *pStorage)
+{
+ STATUS(( " IPropertyStorage::ReadMultiple (inconsistent test)\n" ));
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+ FMTID fmtid;
+ UuidCreate(&fmtid);
+
+ if (g_fOFS)
+ {
+ return;
+ }
+
+ IPropertyStorage * pPropSet;
+ Check(S_OK, pPropSetStg->Create(fmtid, NULL,
+ PROPSETFLAG_NONSIMPLE,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSet));
+
+ // none found
+ PROPSPEC ps[3];
+ ps[0].ulKind = PRSPEC_PROPID;
+ ps[0].propid = 1000;
+ ps[1].ulKind = PRSPEC_PROPID;
+ ps[1].propid = 2000;
+ ps[2].ulKind = PRSPEC_PROPID;
+ ps[2].propid = 3000;
+
+ PROPVARIANT pv[3];
+
+ pv[0].vt = VT_STREAM;
+ pv[0].pStream = NULL;
+ pv[1].vt = VT_STORAGE;
+ pv[1].pStorage = NULL;
+ pv[2].vt = VT_UI4;
+ pv[2].ulVal = 12345678;
+
+ // write the two sub non-simples
+ Check(S_OK, pPropSet->WriteMultiple(3, ps, pv, 1000));
+ pPropSet->Release();
+ Check(S_OK, pStorage->Commit(STGC_DEFAULT));
+
+ // delete the propsets
+ OLECHAR ocsPropsetName[48];
+
+ // get name of the propset storage
+ RtlGuidToPropertySetName(&fmtid, ocsPropsetName);
+
+ // open it
+ CTempStorage pStgPropSet(coOpen, pStorage, ocsPropsetName);
+
+ // enumerate the non-simple properties.
+ IEnumSTATSTG *penum;
+ STATSTG stat[4];
+ ULONG celt;
+ Check(S_OK, pStgPropSet->EnumElements(0, NULL, 0, &penum));
+ Check(S_OK, penum->Next(3, stat, &celt));
+ penum->Release();
+
+
+ for (ULONG i=0;i<celt;i++)
+ {
+ if (ocscmp(OLESTR("CONTENTS"), stat[i].pwcsName) != 0)
+ pStgPropSet->DestroyElement(stat[i].pwcsName);
+ CoTaskMemFree(stat[i].pwcsName);
+ }
+ pStgPropSet.Release();
+
+ Check(S_OK, pPropSetStg->Open(fmtid,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSet));
+ Check(S_OK, pPropSet->ReadMultiple(3, ps, pv));
+ ASSERT(pv[0].vt == VT_EMPTY);
+ ASSERT(pv[1].vt == VT_EMPTY);
+ ASSERT(pv[2].vt == VT_UI4);
+ ASSERT(pv[2].ulVal == 12345678);
+ pPropSet->Release();
+}
+
+void
+test_IPropertyStorage_ReadMultiple(IStorage *pStorage)
+{
+ test_IPropertyStorage_ReadMultiple_Normal(pStorage);
+ test_IPropertyStorage_ReadMultiple_Cleanup(pStorage);
+ test_IPropertyStorage_ReadMultiple_Inconsistent(pStorage);
+}
+
+
+// Overwrite a non-simple property with a simple in a simple propset
+void
+test_IPropertyStorage_WriteMultiple_Overwrite1(IStorage *pStgBase)
+{
+ STATUS(( " IPropertyStorage::WriteMultiple (overwrite 1)\n" ));
+
+ if (g_fOFS)
+ {
+ return;
+ }
+
+ CTempStorage pStgSimple(coCreate, pStgBase, OLESTR("ov1_simp"));
+ CTempStorage pStorage(coCreate, pStgBase, OLESTR("ov1_stg"));
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+ TSafeStorage< IPropertySetStorage > pPropSetSimpleStg(pStgSimple);
+
+ FMTID fmtid, fmtidSimple;
+ UuidCreate(&fmtid);
+ UuidCreate(&fmtidSimple);
+
+ // create a simple set with a non-simple child by copying the contents
+ // stream a non-simple to a property set stream (simple)
+
+ // create a nonsimple propset (will contain the contents stream)
+ IPropertyStorage * pPropSet;
+ Check(S_OK, pPropSetStg->Create(fmtid, NULL,
+ PROPSETFLAG_NONSIMPLE,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSet));
+ // none found
+ PROPSPEC ps[2];
+ ps[0].ulKind = PRSPEC_PROPID;
+ ps[0].propid = 1000;
+ ps[1].ulKind = PRSPEC_LPWSTR;
+ ps[1].lpwstr = OLESTR("foobar");
+ PROPVARIANT pv[2];
+ pv[0].vt = VT_STREAM;
+ pv[0].pStream = NULL;
+ pv[1].vt = VT_UI1;
+ pv[1].bVal = 66;
+ Check(S_OK, pPropSet->WriteMultiple(2, ps, pv, 100));
+
+ // invalid parameter
+ PROPVARIANT pvInvalid[2];
+ PROPSPEC psInvalid[2];
+
+ psInvalid[0].ulKind = PRSPEC_PROPID;
+ psInvalid[0].propid = 1000;
+ psInvalid[1].ulKind = PRSPEC_PROPID;
+ psInvalid[1].propid = 1001;
+ pvInvalid[0].vt = (VARTYPE)-99;
+ pvInvalid[1].vt = (VARTYPE)-100;
+
+ Check(STG_E_INVALIDPARAMETER, pPropSet->WriteMultiple(1, psInvalid, pvInvalid, 100));
+ Check(STG_E_INVALIDPARAMETER, pPropSet->WriteMultiple(2, psInvalid, pvInvalid, 100));
+
+ pPropSet->Release();
+
+ // create a simple propset (will be overwritten)
+ IPropertyStorage * pPropSetSimple;
+ Check(S_OK, pPropSetSimpleStg->Create(fmtidSimple, NULL,
+ 0,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSetSimple));
+ pPropSetSimple->Release();
+
+ OLECHAR ocsNonSimple[48];
+ OLECHAR ocsSimple[48];
+ // get the name of the simple propset
+ RtlGuidToPropertySetName(&fmtidSimple, ocsSimple);
+ // get the name of the non-simple propset
+ RtlGuidToPropertySetName(&fmtid, ocsNonSimple);
+
+ // open non-simple as a storage (will copy the simple to this)
+ IStorage *pstgPropSet;
+ Check(S_OK, pStorage->OpenStorage(ocsNonSimple, NULL,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE, NULL, 0, &pstgPropSet));
+
+ // copy the contents of the non-simple to the propset of the simple
+ IStream *pstmNonSimple;
+ Check(S_OK, pstgPropSet->OpenStream(OLESTR("CONTENTS"), NULL,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE, 0, &pstmNonSimple));
+
+ IStream *pstmSimple;
+ Check(S_OK, pStgSimple->OpenStream(ocsSimple,
+ NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pstmSimple));
+
+ ULARGE_INTEGER uli;
+ memset(&uli, 0xff, sizeof(uli));
+
+ Check(S_OK, pstmNonSimple->CopyTo(pstmSimple, uli, NULL, NULL));
+ pstmSimple->Release();
+ pstmNonSimple->Release();
+ pstgPropSet->Release();
+
+ // But now the FMTID *in* the simple property set doesn't
+ // match the string-ized FMTID which is the Stream's name. So,
+ // rename the Stream to match the property set's FMTID.
+
+ Check(S_OK, pStgSimple->RenameElement( ocsSimple, ocsNonSimple ));
+
+ // now we have a simple propset with a non-simple VT type
+ Check(S_OK, pPropSetSimpleStg->Open(fmtid, // Use the non-simple FMTID now
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSetSimple));
+
+ Check(S_FALSE, pPropSetSimple->ReadMultiple(1, ps, pv));
+ Check(S_OK, pPropSetSimple->ReadMultiple(2, ps, pv));
+ ASSERT(pv[0].vt == VT_EMPTY);
+ ASSERT(pv[1].vt == VT_UI1);
+ ASSERT(pv[1].bVal == 66);
+
+ pPropSetSimple->Release();
+}
+
+// Overwrite a non-simple with a simple in a non-simple
+// check that the non-simple is actually deleted
+// Delete a non-simple
+// check that the non-simple is actually deleted
+void
+test_IPropertyStorage_WriteMultiple_Overwrite2(IStorage *pStorage)
+{
+ STATUS(( " IPropertyStorage::WriteMultiple (overwrite 2)\n" ));
+
+ if (g_fOFS)
+ {
+ return;
+ }
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+ FMTID fmtid;
+ UuidCreate(&fmtid);
+
+ IPropertyStorage *pPropSet;
+ Check(S_OK, pPropSetStg->Create(fmtid, NULL, PROPSETFLAG_NONSIMPLE,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE, &pPropSet));
+
+ // create the non-simple
+ PROPSPEC ps[5];
+ ps[0].ulKind = PRSPEC_PROPID;
+ ps[0].propid = 1000;
+ ps[1].ulKind = PRSPEC_PROPID;
+ ps[1].propid = 1001;
+ ps[2].ulKind = PRSPEC_PROPID;
+ ps[2].propid = 1002;
+ ps[3].ulKind = PRSPEC_PROPID;
+ ps[3].propid = 1003;
+ ps[4].ulKind = PRSPEC_PROPID;
+ ps[4].propid = 1004;
+ PROPVARIANT pv[5];
+ pv[0].vt = VT_STORAGE;
+ pv[0].pStorage = NULL;
+ pv[1].vt = VT_STREAM;
+ pv[1].pStream = NULL;
+ pv[2].vt = VT_STORAGE;
+ pv[2].pStorage = NULL;
+ pv[3].vt = VT_STREAM;
+ pv[3].pStream = NULL;
+ pv[4].vt = VT_STREAM;
+ pv[4].pStream = NULL;
+
+ Check(S_OK, pPropSet->WriteMultiple(5, ps, pv, 2000));
+ pPropSet->Release();
+
+ // get the name of the propset
+ OLECHAR ocsPropsetName[48];
+ RtlGuidToPropertySetName(&fmtid, ocsPropsetName);
+
+ IStorage *pstgPropSet;
+ Check(S_OK, pStorage->OpenStorage(ocsPropsetName, NULL,
+ STGM_SHARE_EXCLUSIVE|STGM_READWRITE,
+ NULL, 0, &pstgPropSet));
+
+ // get the names of the non-simple property
+ IEnumSTATSTG *penum;
+ STATSTG statProp[6];
+ ULONG celt;
+ Check(S_OK, pstgPropSet->EnumElements(0, NULL, 0, &penum));
+ Check(S_OK, penum->Next(5, statProp, &celt));
+ ASSERT(celt == 5);
+ CoTaskMemFree(statProp[0].pwcsName);
+ CoTaskMemFree(statProp[1].pwcsName);
+ CoTaskMemFree(statProp[2].pwcsName);
+ CoTaskMemFree(statProp[3].pwcsName);
+ CoTaskMemFree(statProp[4].pwcsName);
+ penum->Release();
+
+ // reopen the property set and delete the non-simple
+ pstgPropSet->Release();
+
+ Check(S_OK, pPropSetStg->Open(fmtid, STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSet));
+
+ pv[0].vt = VT_LPWSTR;
+ pv[0].pwszVal = L"Overwrite1";
+ pv[1].vt = VT_LPWSTR;
+ pv[1].pwszVal = L"Overwrite2";
+ pv[2].vt = VT_LPWSTR;
+ pv[2].pwszVal = L"Overwrite3";
+ pv[3].vt = VT_LPWSTR;
+ pv[3].pwszVal = L"Overwrite4";
+ pv[4].vt = VT_LPWSTR;
+ pv[4].pwszVal = L"Overwrite5";
+
+ Check(S_OK, pPropSet->WriteMultiple(2, ps, pv, 2000));
+ Check(S_OK, pPropSet->DeleteMultiple(1, ps+2));
+ Check(S_OK, pPropSet->DeleteMultiple(2, ps+3));
+ pPropSet->Release();
+
+ // open the propset as storage again and check that the VT_STORAGE is gone.
+ Check(S_OK, pStorage->OpenStorage(ocsPropsetName, NULL,
+ STGM_SHARE_EXCLUSIVE|STGM_READWRITE,
+ NULL, 0, &pstgPropSet));
+
+ // check they were removed
+ STATSTG statProp2[5];
+ Check(S_OK, pstgPropSet->EnumElements(0, NULL, 0, &penum));
+ Check(S_FALSE, penum->Next(5, statProp2, &celt));
+ ASSERT(celt == 1); // contents
+ CoTaskMemFree(statProp2[0].pwcsName);
+
+ penum->Release();
+ pstgPropSet->Release();
+}
+
+// Write a VT_STORAGE over a VT_STREAM
+// check for cases: when not already open, when already open(access denied)
+// Write a VT_STREAM over a VT_STORAGE
+// check for cases: when not already open, when already open(access denied)
+void
+test_IPropertyStorage_WriteMultiple_Overwrite3(IStorage *pStorage)
+{
+ STATUS(( " IPropertyStorage::WriteMultiple (overwrite 3)\n" ));
+
+ if (g_fOFS)
+ {
+ return;
+ }
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+
+ FMTID fmtid;
+ UuidCreate(&fmtid);
+
+ IPropertyStorage *pPropSet;
+
+ Check(S_OK, pPropSetStg->Create(fmtid, NULL, PROPSETFLAG_NONSIMPLE,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSet));
+ PROPSPEC ps[2];
+ ps[0].ulKind = PRSPEC_LPWSTR;
+ ps[0].lpwstr = OLESTR("stream_storage");
+ ps[1].ulKind = PRSPEC_LPWSTR;
+ ps[1].lpwstr = OLESTR("storage_stream");
+ PROPVARIANT pv[2];
+ pv[0].vt = VT_STREAMED_OBJECT;
+ pv[0].pStream = NULL;
+ pv[1].vt = VT_STORED_OBJECT;
+ pv[1].pStorage = NULL;
+
+ PROPVARIANT pvSave[2];
+ pvSave[0] = pv[0];
+ pvSave[1] = pv[1];
+
+ Check(S_OK, pPropSet->WriteMultiple(2, ps, pv, 1000));
+
+ // swap them around
+ PROPVARIANT pvTemp;
+ pvTemp = pv[0];
+ pv[0] = pv[1];
+ pv[1] = pvTemp;
+ if (g_fOFS)
+ return;
+ Check(S_OK, pPropSet->WriteMultiple(2, ps, pv, 1000));
+ memset(pv, 0, sizeof(pv));
+ Check(S_OK, pPropSet->ReadMultiple(2, ps, pv));
+ ASSERT(pv[0].vt == VT_STORED_OBJECT);
+ ASSERT(pv[1].vt == VT_STREAMED_OBJECT);
+ ASSERT(pv[0].pStorage != NULL);
+ ASSERT(pv[1].pStream != NULL);
+ STATSTG stat; stat.type = 0;
+ Check(S_OK, pv[0].pStorage->Stat(&stat, STATFLAG_NONAME));
+ ASSERT(stat.type == STGTY_STORAGE);
+ Check(S_OK, pv[1].pStream->Stat(&stat, STATFLAG_NONAME));
+ ASSERT(stat.type == STGTY_STREAM);
+
+ STATSTG stat2; stat2.type = 0;
+ // swap them around again, but this time with access denied
+ Check(S_OK, pPropSet->WriteMultiple(2, ps, pvSave, 1000));
+ Check(STG_E_REVERTED, pv[0].pStorage->Stat(&stat, STATFLAG_NONAME));
+ pv[0].pStorage->Release();
+ Check(S_OK, pPropSet->WriteMultiple(2, ps, pvSave, 1000));
+ Check(STG_E_REVERTED, pv[1].pStream->Stat(&stat, STATFLAG_NONAME));
+ pv[1].pStream->Release();
+
+ pPropSet->Release();
+}
+
+//
+// test using IStorage::Commit to commit the changes in a nested
+// property set
+//
+
+void
+test_IPropertyStorage_Commit(IStorage *pStorage)
+{
+ STATUS(( " IPropertyStorage::Commit\n" ));
+
+ // create another level of storage
+
+ if (g_fOFS)
+ {
+ return;
+ }
+
+ // 8 scenarios: (simple+non-simple) * (direct+transacted) * (release only + commit storage + commit propset)
+ for (int i=0; i<(g_fOFS ? 24 : 32); i++)
+ {
+ CTempStorage pDeeper(coCreate, pStorage, GetNextTest(), (i & 1) ? STGM_TRANSACTED : STGM_DIRECT);
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pDeeper);
+
+ FMTID fmtid;
+ UuidCreate(&fmtid);
+
+ IPropertyStorage *pPropSet;
+
+ Check(S_OK, pPropSetStg->Create(fmtid, NULL, (i&8) ? PROPSETFLAG_NONSIMPLE : PROPSETFLAG_DEFAULT,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE | ((i&16) && (i&8) ? STGM_TRANSACTED : STGM_DIRECT),
+ &pPropSet));
+
+ PROPSPEC ps;
+ ps.ulKind = PRSPEC_PROPID;
+ ps.propid = 100;
+ PROPVARIANT pv;
+ pv.vt = VT_I4;
+ pv.lVal = 1234;
+
+ Check(S_OK, pPropSet->WriteMultiple(1, &ps, &pv, 1000));
+
+ memset(&pv, 0, sizeof(pv));
+ Check(S_OK, pPropSet->ReadMultiple(1, &ps, &pv));
+ ASSERT(pv.lVal == 1234);
+
+ pv.lVal = 2345; // no size changes
+ Check(S_OK, pPropSet->WriteMultiple(1, &ps, &pv, 1000));
+
+ if (i & 4)
+ Check(S_OK, pPropSet->Commit(0));
+ if (i & 2)
+ Check(S_OK, pStorage->Commit(0));
+
+ Check(0, pPropSet->Release()); // implicit commit if i&2 is false
+
+ if (S_OK == pPropSetStg->Open(fmtid, STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSet))
+ {
+ memset(&pv, 0, sizeof(pv));
+ Check( !((i&16) && (i&8)) || (i&0x1c)==0x1c ? S_OK : S_FALSE, pPropSet->ReadMultiple(1, &ps, &pv));
+ if (!((i&16) && (i&8)) || (i&0x1c)==0x1c)
+ ASSERT(pv.lVal == 2345);
+
+ pPropSet->Release();
+ }
+ }
+}
+
+void
+test_IPropertyStorage_WriteMultiple(IStorage *pStorage)
+{
+ test_IPropertyStorage_WriteMultiple_Overwrite1(pStorage);
+ test_IPropertyStorage_WriteMultiple_Overwrite2(pStorage);
+ test_IPropertyStorage_WriteMultiple_Overwrite3(pStorage);
+ test_IPropertyStorage_Commit(pStorage);
+
+}
+
+// this serves as a test for WritePropertyNames, ReadPropertyNames, DeletePropertyNames
+// DeleteMultiple, PropVariantCopy, FreePropVariantArray.
+
+void
+test_IPropertyStorage_DeleteMultiple(IStorage *pStorage)
+{
+ STATUS(( " IPropertyStorage::DeleteMultiple\n" ));
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStorage);
+
+ FMTID fmtid;
+ UuidCreate(&fmtid);
+
+ IPropertyStorage *pPropSet;
+
+ int PropId = 3;
+
+ for (int type=0; type<2; type++)
+ {
+
+ if (g_fOFS && type != 0)
+ {
+ continue;
+ }
+
+ UuidCreate(&fmtid);
+ Check(S_OK, pPropSetStg->Create(fmtid,
+ NULL, type == 0 ? PROPSETFLAG_DEFAULT : PROPSETFLAG_NONSIMPLE,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropSet));
+
+ // create and delete each type.
+
+ PROPVARIANT *pVar;
+
+ for (int AtOnce=1; AtOnce <3; AtOnce++)
+ {
+ CGenProps gp;
+ int Actual;
+ while (pVar = gp.GetNext(AtOnce, &Actual, FALSE, TRUE)) // BUGBUG: test case of non-simple
+ {
+ PROPSPEC ps[3];
+ PROPID rgpropid[3];
+ LPOLESTR rglpostrName[3];
+ OLECHAR aosz[3][16];
+
+ for (int s=0; s<3; s++)
+ {
+ PROPGENPROPERTYNAME( &aosz[s][0], PropId );
+ rgpropid[s] = PropId++;
+ rglpostrName[s] = &aosz[s][0];
+ ps[s].ulKind = PRSPEC_LPWSTR;
+ ps[s].lpwstr = &aosz[s][0];
+ }
+
+ for (int l=1; l<Actual; l++)
+ {
+ PROPVARIANT VarRead[3];
+ Check(S_FALSE, pPropSet->ReadMultiple(l, ps, VarRead));
+ Check(S_OK, pPropSet->WritePropertyNames(l, rgpropid, rglpostrName));
+ Check(S_FALSE, pPropSet->ReadMultiple(l, ps, VarRead));
+
+ Check(S_OK, pPropSet->WriteMultiple(l, ps, pVar, 1000));
+ Check(S_OK, pPropSet->ReadMultiple(l, ps, VarRead));
+ Check(S_OK, FreePropVariantArray(l, VarRead));
+ Check(S_OK, pPropSet->DeleteMultiple(l, ps));
+ Check(S_FALSE, pPropSet->ReadMultiple(l, ps, VarRead));
+ Check(S_OK, FreePropVariantArray(l, VarRead));
+
+ LPOLESTR rglpostrNameCheck[3];
+ Check(S_OK, pPropSet->ReadPropertyNames(l, rgpropid, rglpostrNameCheck));
+ for (int c=0; c<l; c++)
+ {
+ ASSERT(ocscmp(rglpostrNameCheck[c], rglpostrName[c])==0);
+ CoTaskMemFree(rglpostrNameCheck[c]);
+ }
+ Check(S_OK, pPropSet->DeletePropertyNames(l, rgpropid));
+ Check(S_FALSE, pPropSet->ReadPropertyNames(l, rgpropid, rglpostrNameCheck));
+ }
+
+ FreePropVariantArray(Actual, pVar);
+ delete pVar;
+ }
+ }
+ pPropSet->Release();
+ }
+}
+
+void
+test_IPropertyStorage(IStorage *pStorage)
+{
+ test_IPropertyStorage_Access(pStorage);
+ test_IPropertyStorage_Create(pStorage);
+ test_IPropertyStorage_Stat(pStorage);
+ test_IPropertyStorage_ReadMultiple(pStorage);
+ test_IPropertyStorage_WriteMultiple(pStorage);
+ test_IPropertyStorage_DeleteMultiple(pStorage);
+}
+
+
+
+
+
+//
+// Word6.0 summary information
+// Open
+// Read fields
+// Stat
+//
+
+
+void test_Word6(IStorage *pStorage, CHAR *pszTemporaryDirectory)
+{
+
+ STATUS(( " Word 6.0 compatibility test\n" ));
+
+ extern unsigned char g_achTestDoc[];
+ extern unsigned g_cbTestDoc;
+
+ CHAR szTempFile[ MAX_PATH + 1 ];
+ OLECHAR oszTempFile[ MAX_PATH + 1 ];
+
+ strcpy( szTempFile, pszTemporaryDirectory );
+
+ strcat( szTempFile, "word6.doc" );
+
+ PropTest_mbstoocs( oszTempFile, szTempFile );
+ PROPTEST_FILE_HANDLE hFile = PropTest_CreateFile( szTempFile );
+
+#ifdef _MAC
+ ASSERT((PROPTEST_FILE_HANDLE) -1 != hFile);
+#else
+ ASSERT(INVALID_HANDLE_VALUE != hFile);
+#endif
+
+ DWORD cbWritten;
+
+
+ PropTest_WriteFile(hFile, g_achTestDoc, g_cbTestDoc, &cbWritten);
+ ASSERT(cbWritten == g_cbTestDoc);
+
+ PropTest_CloseHandle(hFile);
+
+ IStorage *pStg;
+ Check(S_OK, StgOpenStorage(oszTempFile, NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ NULL, 0, &pStg));
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pStg);
+ IPropertyStorage *pPropStg;
+
+ Check(S_OK, pPropSetStg->Open(FMTID_SummaryInformation,
+ STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READ,
+ &pPropStg));
+
+#define WORDPROPS 18
+
+ static struct tagWordTest {
+ VARENUM vt;
+ void *pv;
+ } avt[WORDPROPS] = {
+ VT_LPSTR, "Title of the document.", // PID_TITLE
+ VT_LPSTR, "Subject of the document.", // PID_SUBJECT
+ VT_LPSTR, "Author of the document.", // PID_AUTHOR
+ VT_LPSTR, "Keywords of the document.", // PID_KEYWORDS
+ VT_LPSTR, "Comments of the document.", // PID_COMMENTS
+ VT_LPSTR, "Normal.dot", // PID_TEMPLATE -- Normal.dot
+ VT_LPSTR, "Bill Morel", // PID_LASTAUTHOR --
+ VT_LPSTR, "3", // PID_REVNUMBER -- '3'
+ VT_EMPTY, 0, // PID_EDITTIME -- 3 Minutes FILETIME
+ VT_EMPTY, 0, // PID_LASTPRINTED -- 04/07/95 12:04 FILETIME
+ VT_EMPTY, 0, // PID_CREATE_DTM
+ VT_EMPTY, 0, // PID_LASTSAVE_DTM
+ VT_I4, (void*) 1, // PID_PAGECOUNT
+ VT_I4, (void*) 7, // PID_WORDCOUNT
+ VT_I4, (void*) 65, // PID_CHARCOUNT
+ VT_EMPTY, 0, // PID_THUMBNAIL
+ VT_LPSTR, "Microsoft Word 6.0", // PID_APPNAME
+ VT_I4, 0 }; // PID_SECURITY
+
+ PROPSPEC propspec[WORDPROPS+2];
+
+ for (int i=2; i<WORDPROPS+2; i++)
+ {
+ propspec[i].ulKind = PRSPEC_PROPID;
+ propspec[i].propid = (PROPID)i;
+ }
+
+ PROPVARIANT propvar[WORDPROPS+2];
+
+ Check(S_OK, pPropStg->ReadMultiple(WORDPROPS, propspec+2, propvar+2));
+
+ for (i=2; i<WORDPROPS+2; i++)
+ {
+ if ( propvar[i].vt != avt[i-2].vt )
+ {
+ PRINTF( " PROPTEST: 0x%x retrieved type 0x%x, expected type 0x%x\n",
+ i, propvar[i].vt, avt[i-2].vt );
+ ASSERT(propvar[i].vt == avt[i-2].vt);
+ }
+
+ switch (propvar[i].vt)
+ {
+ case VT_LPSTR:
+ ASSERT(strcmp(propvar[i].pszVal, (char*)avt[i-2].pv)==0);
+ break;
+ case VT_I4:
+ ASSERT(propvar[i].lVal == (int)avt[i-2].pv);
+ break;
+ }
+ }
+
+ FreePropVariantArray( WORDPROPS, propvar+2 );
+
+ pPropStg->Release();
+ pStg->Release();
+}
+
+
+void
+test_IEnumSTATPROPSTG(IStorage *pstgTemp)
+{
+ STATUS(( " IEnumSTATPROPSTG\n" ));
+
+ PROPID apropid[8];
+ LPOLESTR alpostrName[8];
+ OLECHAR aosz[8][32];
+ PROPID PropId=2;
+ PROPSPEC ps[8];
+
+ FMTID fmtid;
+ IPropertyStorage *pPropStg;
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pstgTemp);
+
+ if (!g_fOFS)
+ UuidCreate(&fmtid);
+
+ for (int setup=0; setup<8; setup++)
+ {
+ alpostrName[setup] = &aosz[setup][0];
+ }
+
+
+ CGenProps gp;
+
+ // simple/non-simple, ansi/wide, named/not named
+ for (int outer=0; outer<8; outer++)
+ {
+ if (g_fOFS)
+ UuidCreate(&fmtid); // BUGBUG: Raid # 19521
+
+ if (g_fOFS && (outer & 4))
+ {
+ continue;
+ }
+
+ Check(S_OK, pPropSetStg->Create(fmtid, NULL,
+ ((outer&4) ? PROPSETFLAG_NONSIMPLE : 0) |
+ ((outer&2) ? PROPSETFLAG_ANSI : 0),
+ STGM_CREATE | STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
+ &pPropStg));
+
+
+ for (int i=0; i<CPROPERTIES; i++)
+ {
+ apropid[i] = PropId++;
+ if (outer & 1)
+ {
+ ps[i].ulKind = PRSPEC_LPWSTR;
+ PROPGENPROPERTYNAME( aosz[i], apropid[i] );
+ ps[i].lpwstr = aosz[i];
+ }
+ else
+ {
+ ps[i].ulKind = PRSPEC_PROPID;
+ ps[i].propid = apropid[i];
+ }
+ }
+
+ if (outer & 1)
+ {
+ Check(S_OK, pPropStg->WritePropertyNames(CPROPERTIES, apropid, alpostrName));
+ }
+
+ PROPVARIANT *pVar = gp.GetNext(CPROPERTIES, NULL, TRUE, (outer&4)==0); // no non-simple
+ ASSERT(pVar != NULL);
+
+ Check(S_OK, pPropStg->WriteMultiple(CPROPERTIES, ps, pVar, 1000));
+ FreePropVariantArray(CPROPERTIES, pVar);
+ delete pVar;
+
+ // Allocate enough STATPROPSTGs for one more than the actual properties
+ // in the set.
+
+ STATPROPSTG StatBuffer[CPROPERTIES+1];
+ ULONG celt;
+ IEnumSTATPROPSTG *penum, *penum2;
+
+ Check(S_OK, pPropStg->Enum(&penum));
+
+ IUnknown *punk, *punk2;
+ IEnumSTATPROPSTG *penum3;
+ Check(S_OK, penum->QueryInterface(IID_IUnknown, (void**)&punk));
+ Check(S_OK, punk->QueryInterface(IID_IEnumSTATPROPSTG, (void**)&penum3));
+ Check(S_OK, penum->QueryInterface(IID_IEnumSTATPROPSTG, (void**)&punk2));
+ ASSERT(punk == punk2);
+ punk->Release();
+ penum3->Release();
+ punk2->Release();
+
+ // test S_FALSE
+ Check(S_FALSE, penum->Next( CPROPERTIES+1, StatBuffer, &celt));
+ ASSERT(celt == CPROPERTIES);
+
+ // BUGBUG: leaks
+
+ CleanStat(celt, StatBuffer);
+
+ penum->Reset();
+
+
+ // test reading half out, then cloning, then comparing
+ // rest of enumeration with other clone.
+
+ Check(S_OK, penum->Next(CPROPERTIES/2, StatBuffer, &celt));
+ ASSERT(celt == CPROPERTIES/2);
+ CleanStat(celt, StatBuffer);
+ celt = 0;
+ Check(S_OK, penum->Clone(&penum2));
+ Check(S_OK, penum->Next(CPROPERTIES - CPROPERTIES/2, StatBuffer, &celt));
+ ASSERT(celt == CPROPERTIES - CPROPERTIES/2);
+ // check the clone
+ for (int c=0; c<CPROPERTIES - CPROPERTIES/2; c++)
+ {
+ STATPROPSTG CloneStat;
+ Check(S_OK, penum2->Next(1, &CloneStat, NULL));
+ ASSERT(IsEqualSTATPROPSTG(&CloneStat, StatBuffer+c));
+ CleanStat(1, &CloneStat);
+ }
+
+ CleanStat(celt, StatBuffer);
+
+ // check both empty
+ celt = 0;
+ Check(S_FALSE, penum->Next(1, StatBuffer, &celt));
+ ASSERT(celt == 0);
+
+ Check(S_FALSE, penum2->Next(1, StatBuffer, &celt));
+ ASSERT(celt == 0);
+
+ penum->Reset();
+
+ //
+ // loop deleting one property at a time
+ // enumerate the propertys checking that correct ones appear.
+ //
+ for (ULONG d = 0; d<CPROPERTIES; d++)
+ {
+ // d is for delete
+
+ BOOL afFound[CPROPERTIES];
+ ULONG cTotal = 0;
+
+ Check(S_OK, penum->Next(CPROPERTIES-d, StatBuffer, &celt));
+ ASSERT(celt == CPROPERTIES-d);
+ penum->Reset();
+
+ memset(afFound, 0, sizeof(afFound));
+
+ for (ULONG iProperty=0; iProperty<CPROPERTIES; iProperty++)
+ {
+
+ // Search the StatBuffer for this property.
+
+ for (ULONG iSearch=0; iSearch<CPROPERTIES-d; iSearch++)
+ {
+
+ // Compare this entry in the StatBuffer to the property for which we're searching.
+ // Use the lpstrName or propid, whichever is appropriate for this pass (indicated
+ // by 'outer').
+
+ if ( ( (outer & 1) == 1 && 0 == ocscmp(StatBuffer[iSearch].lpwstrName, ps[iProperty].lpwstr) )
+ ||
+ ( (outer & 1) == 0 && StatBuffer[iSearch].propid == apropid[iProperty] )
+ )
+ {
+ ASSERT (!afFound[iSearch]);
+ afFound[iSearch] = TRUE;
+ cTotal++;
+ break;
+ }
+ }
+ }
+
+ CleanStat(celt, StatBuffer);
+
+ ASSERT(cTotal == CPROPERTIES-d);
+
+ Check(S_OK, pPropStg->DeleteMultiple(1, ps+d));
+ Check(S_OK, penum->Reset());
+ }
+
+ penum->Release();
+ penum2->Release();
+
+ pPropStg->Release();
+
+ }
+}
+
+void
+test_MaxPropertyName(IStorage *pstgTemp)
+{
+
+ STATUS(( " Max Property Name length\n" ));
+
+ // ----------
+ // Initialize
+ // ----------
+
+ CPropVariant cpropvar;
+
+ // Create a new storage, because we're going to create
+ // well-known property sets, and this way we can be sure
+ // that they don't already exist.
+
+ TSafeStorage< IStorage > pstg;
+
+ Check(S_OK, pstgTemp->CreateStorage( OLESTR("MaxPropNameTest"),
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L, 0L,
+ &pstg ));
+
+ // Generate a new Format ID.
+
+ FMTID fmtid;
+ UuidCreate(&fmtid);
+
+ // Get a IPropertySetStorage from the IStorage.
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pstg);
+ TSafeStorage< IPropertyStorage > pPropStg;
+
+ // ----------------------------------
+ // Test the non-SumInfo property set.
+ // ----------------------------------
+
+ // Create a new PropertyStorage.
+
+ Check(S_OK, pPropSetStg->Create(fmtid,
+ NULL,
+ PROPSETFLAG_DEFAULT,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &pPropStg));
+
+ // Generate a property name which is max+1 characters.
+
+ OLECHAR *poszPropertyName;
+ poszPropertyName = (OLECHAR*) CoTaskMemAlloc( (CCH_MAXPROPNAMESZ+1) * sizeof(OLECHAR) );
+ Check(TRUE, poszPropertyName != NULL );
+
+ for( ULONG ulIndex = 0; ulIndex < CCH_MAXPROPNAMESZ; ulIndex++ )
+ poszPropertyName[ ulIndex ] = OLESTR('a') + (OLECHAR) ( ulIndex % 26 );
+ poszPropertyName[ CCH_MAXPROPNAMESZ ] = OLESTR('\0');
+
+
+ // Write out a property with this max+1 name.
+
+ PROPSPEC propspec;
+
+ propspec.ulKind = PRSPEC_LPWSTR;
+ propspec.lpwstr = poszPropertyName;
+
+ cpropvar = (long) 0x1234;
+
+ Check(STG_E_INVALIDPARAMETER, pPropStg->WriteMultiple( 1, &propspec, cpropvar, PID_FIRST_USABLE ));
+
+ // Write out a property with a max-character name (we create a max-
+ // char name by terminating the previously-used string one character
+ // earlier).
+
+ poszPropertyName[ CCH_MAXPROPNAME ] = OLESTR('\0');
+ Check(S_OK, pPropStg->WriteMultiple( 1, &propspec, cpropvar, PID_FIRST_USABLE ));
+
+ // Write out a property with a minimum-character name.
+
+ propspec.lpwstr = OLESTR("X");
+ Check(S_OK, pPropStg->WriteMultiple( 1, &propspec, cpropvar, PID_FIRST_USABLE ));
+
+ // Write out a property with a below-minimum-character name.
+
+ propspec.lpwstr = OLESTR("");
+ Check(STG_E_INVALIDPARAMETER, pPropStg->WriteMultiple( 1, &propspec, cpropvar, PID_FIRST_USABLE ));
+
+ CoTaskMemFree( poszPropertyName );
+
+ // BUGBUG: Because Check does an exit, we don't free pwszPropertyName.
+}
+
+void
+test_CodePages( LPOLESTR poszDirectory )
+{
+
+ STATUS(( " Code Page compatibility\n" ));
+
+ // --------------
+ // Initialization
+ // --------------
+
+ OLECHAR oszBadFile[ MAX_PATH ];
+ OLECHAR oszGoodFile[ MAX_PATH ];
+ OLECHAR oszUnicodeFile[ MAX_PATH ];
+ OLECHAR oszMacFile[ MAX_PATH ];
+ HRESULT hr = S_OK;
+
+ TSafeStorage< IStorage > pStgBad, pStgGood, pStgUnicode, pStgMac;
+ CPropVariant cpropvarWrite, cpropvarRead;
+
+ Check( TRUE, GetACP() == CODEPAGE_DEFAULT );
+
+ // ------------------------------
+ // Create test ANSI property sets
+ // ------------------------------
+
+ // Create a property set with a bad codepage.
+
+ ocscpy( oszBadFile, poszDirectory );
+ ocscat( oszBadFile, OLESTR( "\\BadCP.stg" ));
+ CreateCodePageTestFile( oszBadFile, &pStgBad );
+ ModifyPropSetCodePage( pStgBad, CODEPAGE_BAD );
+
+ // Create a property set with a good codepage.
+
+ ocscpy( oszGoodFile, poszDirectory );
+ ocscat( oszGoodFile, OLESTR("\\GoodCP.stg") );
+ CreateCodePageTestFile( oszGoodFile, &pStgGood );
+ ModifyPropSetCodePage( pStgGood, CODEPAGE_GOOD );
+
+
+ // Create a property set that has the OS Kind (in the
+ // header) set to "Mac".
+
+ ocscpy( oszMacFile, poszDirectory );
+ ocscat( oszMacFile, OLESTR("\\MacKind.stg") );
+ CreateCodePageTestFile( oszMacFile, &pStgMac );
+ ModifyOSVersion( pStgMac, 0x00010904 );
+
+ // ---------------------------
+ // Open the Ansi property sets
+ // ---------------------------
+
+
+ TSafeStorage< IPropertySetStorage > pPropSetStgBad(pStgBad);
+ TSafeStorage< IPropertySetStorage > pPropSetStgGood(pStgGood);
+ TSafeStorage< IPropertySetStorage > pPropSetStgMac(pStgMac);
+
+ TSafeStorage< IPropertyStorage > pPropStgBad, pPropStgGood, pPropStgMac;
+
+ Check(S_OK, pPropSetStgBad->Open(FMTID_NULL,
+ STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &pPropStgBad));
+
+ Check(S_OK, pPropSetStgGood->Open(FMTID_NULL,
+ STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &pPropStgGood));
+
+ Check(S_OK, pPropSetStgMac->Open(FMTID_NULL,
+ STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &pPropStgMac));
+
+ // ------------------------------------------
+ // Test BSTRs in the three ANSI property sets
+ // ------------------------------------------
+
+ PROPSPEC propspec;
+ PROPVARIANT propvar;
+ PropVariantInit( &propvar );
+
+ // Attempt to read by name.
+
+ propspec.ulKind = PRSPEC_LPWSTR;
+ propspec.lpwstr = CODEPAGE_TEST_NAMED_PROPERTY;
+
+ Check(S_OK,
+ pPropStgMac->ReadMultiple( 1, &propspec, &propvar ));
+ PropVariantClear( &propvar );
+
+#ifndef OLE2ANSI // No error is generated if BSTRs are Ansi
+ Check(
+ HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION),
+ pPropStgBad->ReadMultiple( 1, &propspec, &propvar ));
+#endif
+
+ Check(S_OK,
+ pPropStgGood->ReadMultiple( 1, &propspec, &propvar ));
+
+ // Attempt to write by name. If this test fails, it may be because
+ // the machine doesn't support CODEPAGE_GOOD (this is the case by default
+ // on Win95). To remedy this situation, go to control panel, add/remove
+ // programs, windows setup (tab), check MultiLanguage support, then
+ // click OK. You'll have to restart the computer after this.
+
+ Check(S_OK,
+ pPropStgMac->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE ));
+
+#ifndef OLE2ANSI // No error is generated if BSTRs are Ansi
+ Check(HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION),
+ pPropStgBad->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE ));
+#endif
+
+ Check(S_OK,
+ pPropStgGood->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE ));
+ PropVariantClear( &propvar );
+
+ // Attempt to read the BSTR property
+
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = CODEPAGE_TEST_UNNAMED_BSTR_PROPID;
+
+ Check(S_OK,
+ pPropStgMac->ReadMultiple( 1, &propspec, &propvar ));
+ PropVariantClear( &propvar );
+
+#ifndef OLE2ANSI // No error is generated if BSTRs are Ansi
+ Check(HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION),
+ pPropStgBad->ReadMultiple( 1, &propspec, &propvar ));
+#endif
+
+ Check(S_OK,
+ pPropStgGood->ReadMultiple( 1, &propspec, &propvar ));
+
+ // Attempt to write the BSTR property
+
+ Check(S_OK,
+ pPropStgMac->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE ));
+
+#ifndef OLE2ANSI // No error is generated if BSTRs are Ansi
+ Check(HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION),
+ pPropStgBad->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE ));
+#endif
+
+ Check(S_OK,
+ pPropStgGood->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE ));
+ PropVariantClear( &propvar );
+
+ // Attempt to read the BSTR Vector property
+
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = CODEPAGE_TEST_VBSTR_PROPID;
+
+ Check(S_OK,
+ pPropStgMac->ReadMultiple( 1, &propspec, &propvar ));
+ PropVariantClear( &propvar );
+
+#ifndef OLE2ANSI // No error is generated if BSTRs are Ansi
+ Check(HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION),
+ pPropStgBad->ReadMultiple( 1, &propspec, &propvar ));
+#endif
+
+ Check(S_OK,
+ pPropStgGood->ReadMultiple( 1, &propspec, &propvar ));
+
+ // Attempt to write the BSTR Vector property
+
+ Check(S_OK,
+ pPropStgMac->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE ));
+
+#ifndef OLE2ANSI // No error is generated if BSTRs are Ansi
+ Check(HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION),
+ pPropStgBad->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE ));
+#endif
+ Check(S_OK,
+ pPropStgGood->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE ));
+ PropVariantClear( &propvar );
+
+ // Attempt to read the Variant Vector which has a BSTR
+
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = CODEPAGE_TEST_VPROPVAR_BSTR_PROPID;
+
+ Check(S_OK,
+ pPropStgMac->ReadMultiple( 1, &propspec, &propvar ));
+ PropVariantClear( &propvar );
+
+#ifndef OLE2ANSI // No error is generated if BSTRs are Ansi
+ Check(HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION),
+ pPropStgBad->ReadMultiple( 1, &propspec, &propvar ));
+#endif
+
+ Check(S_OK,
+ pPropStgGood->ReadMultiple( 1, &propspec, &propvar ));
+
+ // Attempt to write the Variant Vector which has a BSTR
+
+ Check(S_OK,
+ pPropStgMac->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE ));
+
+#ifndef OLE2ANSI // No error is generated if BSTRs are Ansi
+ Check(HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION),
+ pPropStgBad->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE ));
+#endif
+
+ Check(S_OK,
+ pPropStgGood->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE ));
+ PropVariantClear( &propvar );
+
+ // Attempt to read the I4 property. Reading the bad property set
+ // takes special handling, because it will return a different result
+ // depending on whether NTDLL is checked or free (the free will work,
+ // the checked generates an error in its validation checking).
+
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = 4;
+
+ Check(S_OK,
+ pPropStgMac->ReadMultiple( 1, &propspec, &propvar ));
+ PropVariantClear( &propvar );
+
+ hr = pPropStgBad->ReadMultiple( 1, &propspec, &propvar );
+ Check(TRUE, S_OK == hr || HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION) == hr );
+ PropVariantClear( &propvar );
+
+ Check(S_OK,
+ pPropStgGood->ReadMultiple( 1, &propspec, &propvar ));
+
+ // Attempt to write the I4 property
+
+ Check(S_OK,
+ pPropStgMac->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE ));
+
+ hr = pPropStgBad->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE );
+ Check(TRUE, S_OK == hr || HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION) == hr );
+
+ Check(S_OK,
+ pPropStgGood->WriteMultiple( 1, &propspec, &propvar, PID_FIRST_USABLE ));
+ PropVariantClear( &propvar );
+
+
+ // ---------------------------------------
+ // Test LPSTRs in the Unicode property set
+ // ---------------------------------------
+
+ // This test doesn't verify that the LPSTRs are actually
+ // written in Unicode. A manual test is required for that.
+
+ // Create a Unicode property set. We'll make it
+ // non-simple so that we can test a VT_STREAM (which
+ // is stored like an LPSTR).
+
+ ocscpy( oszUnicodeFile, poszDirectory );
+ ocscat( oszUnicodeFile, OLESTR("\\UnicodCP.stg") );
+
+ Check(S_OK, StgCreateDocfile(oszUnicodeFile,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ &pStgUnicode));
+
+ TSafeStorage< IPropertySetStorage > pPropSetStgUnicode(pStgUnicode);
+ TSafeStorage< IPropertyStorage > pPropStgUnicode;
+ Check(S_OK, pPropSetStgUnicode->Create(FMTID_NULL,
+ &CLSID_NULL,
+ PROPSETFLAG_NONSIMPLE,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropStgUnicode));
+
+
+ // Write/verify an LPSTR property.
+
+ propspec.ulKind = PRSPEC_LPWSTR;
+ propspec.lpwstr = OLESTR("LPSTR Property");
+
+ cpropvarWrite = "An LPSTR Property";
+
+ Check(S_OK, pPropStgUnicode->WriteMultiple( 1, &propspec, cpropvarWrite, PID_FIRST_USABLE ));
+ Check(S_OK, pPropStgUnicode->ReadMultiple( 1, &propspec, cpropvarRead ));
+
+ Check(0, strcmp( (LPSTR) cpropvarWrite, (LPSTR) cpropvarRead ));
+ cpropvarRead.Clear();
+
+ // Write/verify a vector of LPSTR properties
+
+ propspec.lpwstr = OLESTR("Vector of LPSTR properties");
+
+ cpropvarWrite[1] = "LPSTR Property #1";
+ cpropvarWrite[0] = "LPSTR Property #0";
+
+ Check(S_OK, pPropStgUnicode->WriteMultiple( 1, &propspec, cpropvarWrite, PID_FIRST_USABLE ));
+ Check(S_OK, pPropStgUnicode->ReadMultiple( 1, &propspec, cpropvarRead ));
+
+ Check(0, strcmp( (LPSTR) cpropvarWrite[1], (LPSTR) cpropvarRead[1] ));
+ Check(0, strcmp( (LPSTR) cpropvarWrite[0], (LPSTR) cpropvarRead[0] ));
+ cpropvarRead.Clear();
+
+ // Write/verify a vector of variants which has an LPSTR
+
+ propspec.lpwstr = OLESTR("Variant Vector with an LPSTR");
+
+ cpropvarWrite[1] = (LPPROPVARIANT) CPropVariant("LPSTR in a Variant Vector");
+ cpropvarWrite[0] = (LPPROPVARIANT) CPropVariant((long) 22); // an I4
+ ASSERT( (VT_VECTOR | VT_VARIANT) == cpropvarWrite.VarType() );
+
+ Check(S_OK, pPropStgUnicode->WriteMultiple( 1, &propspec, cpropvarWrite, PID_FIRST_USABLE ));
+ Check(S_OK, pPropStgUnicode->ReadMultiple( 1, &propspec, cpropvarRead ));
+
+ Check(0, strcmp( (LPSTR) cpropvarWrite[1], (LPSTR) cpropvarRead[1] ));
+ cpropvarRead.Clear();
+
+ // Write/verify a Stream.
+
+ cpropvarWrite = (IStream*) NULL;
+ propspec.lpwstr = OLESTR("An IStream");
+
+ Check(S_OK, pPropStgUnicode->WriteMultiple( 1, &propspec, cpropvarWrite, PID_FIRST_USABLE ));
+ Check(S_OK, pPropStgUnicode->ReadMultiple( 1, &propspec, cpropvarRead ));
+ cpropvarRead.Clear();
+
+ // There's nothing more we can check for the VT_STREAM property, a manual
+ // check is required to verify that it was written correctly.
+
+
+}
+
+void
+test_PropertyInterfaces(IStorage *pstgTemp)
+{
+ // this test depends on being first for enumerator
+ test_IEnumSTATPROPSETSTG(pstgTemp);
+
+ test_MaxPropertyName(pstgTemp);
+ test_IPropertyStorage(pstgTemp);
+ test_IPropertySetStorage(pstgTemp);
+ test_IEnumSTATPROPSTG(pstgTemp);
+}
+
+
+//===================================================================
+//
+// Function: test_CopyTo
+//
+// Synopsis: Verify that IStorage::CopyTo copies an
+// un-flushed property set.
+//
+// This test creates and writes to a simple property set,
+// a non-simple property set, and a new Storage & Stream,
+// all within the source (caller-provided) Storage.
+//
+// It then copies the entire source Storage to the
+// destination Storage, and verifies that all commited
+// data in the Source is also in the destination.
+//
+// All new Storages and property sets are created
+// under a new base storage. The caller can specify
+// if this base Storage is direct or transacted, and
+// can specify if the property sets are direct or
+// transacted.
+//
+//===================================================================
+
+void test_CopyTo(IStorage *pstgSource, // Source of the CopyTo
+ IStorage *pstgDestination, // Destination of the CopyTo
+ ULONG ulBaseStgTransaction, // Transaction bit for the base storage.
+ ULONG ulPropSetTransaction, // Transaction bit for the property sets.
+ LPOLESTR oszBaseStorageName )
+{
+ STATUS(( " IStorage::CopyTo (Base Storage is %s, PropSets are %s)\n",
+ ulBaseStgTransaction & STGM_TRANSACTED ? "transacted" : "directed",
+ ulPropSetTransaction & STGM_TRANSACTED ? "transacted" : "directed" ));
+
+
+ // ---------------
+ // Local Variables
+ // ---------------
+
+ OLECHAR const *poszTestSubStorage = OLESTR( "TestStorage" );
+ OLECHAR const *poszTestSubStream = OLESTR( "TestStream" );
+ OLECHAR const *poszTestDataPreCommit = OLESTR( "Test Data (pre-commit)" );
+ OLECHAR const *poszTestDataPostCommit = OLESTR( "Test Data (post-commit)" );
+
+ long lSimplePreCommit = 0x0123;
+ long lSimplePostCommit = 0x4567;
+
+ long lNonSimplePreCommit = 0x89AB;
+ long lNonSimplePostCommit = 0xCDEF;
+
+ BYTE acReadBuffer[ 80 ];
+ ULONG cbRead;
+
+ FMTID fmtidSimple, fmtidNonSimple;
+
+ // Base Storages for the Source & Destination. All
+ // new Streams/Storages/PropSets will be created below here.
+
+ TSafeStorage< IStorage > pstgBaseSource;
+ TSafeStorage< IStorage > pstgBaseDestination;
+
+ TSafeStorage< IStorage > pstgSub; // A sub-storage of the base.
+ TSafeStorage< IStream > pstmSub; // A Stream in the sub-storage (pstgSub)
+
+ PROPSPEC propspec;
+ PROPVARIANT propvarSourceSimple,
+ propvarSourceNonSimple,
+ propvarDestination;
+
+
+ // -----
+ // Begin
+ // -----
+
+ // Create new format IDs
+
+ UuidCreate(&fmtidSimple);
+ UuidCreate(&fmtidNonSimple);
+
+ // -----------------------
+ // Create the base Storage
+ // -----------------------
+
+ // Create a base Storage for the Source. All of this test will be under
+ // that Storage.
+
+ // In the source Storage.
+
+ Check( S_OK, pstgSource->CreateStorage(
+ oszBaseStorageName,
+ STGM_CREATE | ulBaseStgTransaction | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ 0L, 0L,
+ &pstgBaseSource ));
+
+
+ // And in the destination Storage.
+
+ Check( S_OK, pstgDestination->CreateStorage(
+ oszBaseStorageName,
+ STGM_CREATE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ 0L, 0L,
+ &pstgBaseDestination ));
+
+
+
+ // -------------------------------------------
+ // Write data to a new Stream in a new Storage
+ // -------------------------------------------
+
+ // We'll partially verify the CopyTo by checking that this data
+ // makes it into the destination Storage.
+
+
+ // Create a Storage, and then a Stream within it.
+
+ Check( S_OK, pstgBaseSource->CreateStorage(
+ poszTestSubStorage,
+ STGM_CREATE | ulPropSetTransaction | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ 0L, 0L,
+ &pstgSub ));
+
+ Check( S_OK, pstgSub->CreateStream(
+ poszTestSubStream,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L, 0L,
+ &pstmSub ));
+
+ // Write data to the Stream.
+
+ Check( S_OK, pstmSub->Write(
+ poszTestDataPreCommit,
+ ( sizeof(OLECHAR)
+ *
+ (ocslen( poszTestDataPreCommit ) + sizeof(OLECHAR))
+ ),
+ NULL ));
+
+
+ // ---------------------------------------------------------
+ // Write to a new simple property set in the Source storage.
+ // ---------------------------------------------------------
+
+ TSafeStorage< IPropertySetStorage > pPropSetStgSource(pstgBaseSource);
+ TSafeStorage< IPropertyStorage > pPropStgSource1,
+ pPropStgSource2,
+ pPropStgDestination;
+
+ // Create a property set mode.
+
+ Check(S_OK, pPropSetStgSource->Create(fmtidSimple,
+ NULL,
+ PROPSETFLAG_DEFAULT,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropStgSource1));
+
+ // Write the property set name (just to test this functionality).
+
+ PROPID pidDictionary = 0;
+ OLECHAR *poszPropSetName = OLESTR("Property Set for CopyTo Test");
+ ASSERT( CWC_MAXPROPNAMESZ >= ocslen(poszPropSetName) + sizeof(OLECHAR) );
+
+ Check(S_OK, pPropStgSource1->WritePropertyNames( 1, &pidDictionary, &poszPropSetName ));
+
+ // Create a PROPSPEC. We'll use this throughout the rest of the routine.
+
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = 1000;
+
+ // Create a PROPVARIANT for this test of the Simple case.
+
+ propvarSourceSimple.vt = VT_I4;
+ propvarSourceSimple.lVal = lSimplePreCommit;
+
+ // Write the PROPVARIANT to the property set.
+
+ Check(S_OK, pPropStgSource1->WriteMultiple(1, &propspec, &propvarSourceSimple, 2));
+
+
+ // ---------------------------------------------------------------
+ // Write to a new *non-simple* property set in the Source storage.
+ // ---------------------------------------------------------------
+
+
+ // Create a property set.
+
+ Check(S_OK, pPropSetStgSource->Create(fmtidNonSimple,
+ NULL,
+ PROPSETFLAG_NONSIMPLE,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | ulPropSetTransaction | STGM_READWRITE,
+ &pPropStgSource2));
+
+ // Set data in the PROPVARIANT for the non-simple test.
+
+ propvarSourceNonSimple.vt = VT_I4;
+ propvarSourceNonSimple.lVal = lNonSimplePreCommit;
+
+ // Write the PROPVARIANT to the property set.
+
+ Check(S_OK, pPropStgSource2->WriteMultiple(1, &propspec, &propvarSourceNonSimple, 2));
+
+
+ // -------------------------
+ // Commit everything so far.
+ // -------------------------
+
+ // Commit the sub-Storage.
+ Check(S_OK, pstgSub->Commit( STGC_DEFAULT ));
+
+ // Commit the simple property set.
+ Check(S_OK, pPropStgSource1->Commit( STGC_DEFAULT ));
+
+ // Commit the non-simple property set.
+ Check(S_OK, pPropStgSource2->Commit( STGC_DEFAULT ));
+
+ // Commit the base Storage which holds all of the above.
+ Check(S_OK, pstgBaseSource->Commit( STGC_DEFAULT ));
+
+
+ // -------------------------------------------------
+ // Write new data to everything but don't commit it.
+ // -------------------------------------------------
+
+ // Write to the sub-storage.
+ Check(S_OK, pstmSub->Seek(g_li0, STREAM_SEEK_SET, NULL));
+ Check( S_OK, pstmSub->Write(
+ poszTestDataPostCommit,
+ ( sizeof(OLECHAR)
+ *
+ (ocslen( poszTestDataPostCommit ) + sizeof(OLECHAR))
+ ),
+ NULL ));
+
+
+ // Write to the simple property set.
+ propvarSourceSimple.lVal = lSimplePostCommit;
+ Check(S_OK, pPropStgSource1->WriteMultiple(1, &propspec, &propvarSourceSimple, 2));
+
+ // Write to the non-simple property set.
+ propvarSourceNonSimple.lVal = lNonSimplePostCommit;
+ Check(S_OK, pPropStgSource2->WriteMultiple(1, &propspec, &propvarSourceNonSimple, PID_FIRST_USABLE ));
+
+
+ // -------------------------------------------
+ // Copy the source Storage to the destination.
+ // -------------------------------------------
+
+ // Release the sub-Storage (which is below the base Storage, and has
+ // a Stream with data in it), just to test that the CopyTo can
+ // handle it.
+
+ pstgSub->Release();
+ pstgSub = NULL;
+
+ Check(S_OK, pstgBaseSource->CopyTo( 0, NULL, NULL, pstgBaseDestination ));
+
+
+ // ----------------------------------------------------------
+ // Verify the simple property set in the destination Storage.
+ // ----------------------------------------------------------
+
+
+ TSafeStorage< IPropertySetStorage > pPropSetStgDestination(pstgBaseDestination);
+
+ // Open the simple property set.
+
+ Check(S_OK, pPropSetStgDestination->Open(fmtidSimple,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ &pPropStgDestination));
+
+ // Verify the property set name.
+
+ OLECHAR *poszPropSetNameDestination;
+ BOOL bReadPropertyNamePassed = FALSE;
+
+ Check(S_OK, pPropStgDestination->ReadPropertyNames( 1, &pidDictionary,
+ &poszPropSetNameDestination ));
+ if( poszPropSetNameDestination // Did we get a name back?
+ && // If so, was it the correct name?
+ !ocscmp( poszPropSetName, poszPropSetNameDestination )
+ )
+ {
+ bReadPropertyNamePassed = TRUE;
+ }
+ CoTaskMemFree( poszPropSetNameDestination );
+ poszPropSetNameDestination = NULL;
+
+ Check( TRUE, bReadPropertyNamePassed );
+
+ // Read the PROPVARIANT that we wrote earlier.
+
+ Check(S_OK, pPropStgDestination->ReadMultiple(1, &propspec, &propvarDestination));
+
+ // Verify that it's correct.
+
+ Check(TRUE, propvarDestination.vt == propvarSourceSimple.vt );
+ Check(TRUE, propvarDestination.lVal == lSimplePostCommit);
+
+ Check(S_OK, pPropStgDestination->Commit( STGC_DEFAULT ));
+ Check(S_OK, pPropStgDestination->Release());
+ pPropStgDestination = NULL;
+
+
+ // ----------------------------------------------------------------
+ // Verify the *non-simple* property set in the destination Storage.
+ // ----------------------------------------------------------------
+
+ // Open the non-simple property set.
+
+ Check(S_OK,
+ pPropSetStgDestination->Open(fmtidNonSimple,
+ STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &pPropStgDestination));
+
+ // Read the PROPVARIANT that we wrote earlier.
+
+ Check(S_OK, pPropStgDestination->ReadMultiple(1, &propspec, &propvarDestination));
+
+ // Verify that they're the same.
+
+ Check(TRUE, propvarDestination.vt == propvarSourceNonSimple.vt );
+
+ Check(TRUE, propvarDestination.lVal
+ ==
+ ( STGM_TRANSACTED & ulPropSetTransaction
+ ?
+ lNonSimplePreCommit
+ :
+ lNonSimplePostCommit
+ ));
+
+ Check(S_OK, pPropStgDestination->Commit( STGC_DEFAULT ));
+ Check(S_OK, pPropStgDestination->Release());
+ pPropStgDestination = NULL;
+
+ // ------------------------------------------------
+ // Verify the test data in the destination Storage.
+ // ------------------------------------------------
+
+ // Now we can release and re-use the Stream pointer that
+ // currently points to the sub-Stream in the source docfile.
+
+ Check(STG_E_REVERTED, pstmSub->Commit( STGC_DEFAULT ));
+ Check(S_OK, pstmSub->Release());
+ pstmSub = NULL;
+
+ // Get the Storage then the Stream.
+
+ Check( S_OK, pstgBaseDestination->OpenStorage(
+ poszTestSubStorage,
+ NULL,
+ STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0L,
+ &pstgSub ));
+
+ Check( S_OK, pstgSub->OpenStream(
+ poszTestSubStream,
+ NULL,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L,
+ &pstmSub ));
+
+ // Read the data and compare it against what we wrote.
+
+ Check( S_OK, pstmSub->Read(
+ acReadBuffer,
+ sizeof( acReadBuffer ),
+ &cbRead ));
+
+ OLECHAR const *poszTestData = ( STGM_TRANSACTED & ulPropSetTransaction )
+ ?
+ poszTestDataPreCommit
+ :
+ poszTestDataPostCommit;
+
+ Check( TRUE, cbRead == sizeof(OLECHAR)
+ *
+ (ocslen( poszTestData ) + sizeof(OLECHAR))
+ );
+
+ Check( FALSE, ocscmp( poszTestData, (OLECHAR *) acReadBuffer ));
+
+
+ // ----
+ // Exit
+ // ----
+
+ // We're done. Don't bother to release anything;
+ // they'll release themselves in their destructors.
+
+ return;
+
+} // test_CopyTo()
+
+
+
+//--------------------------------------------------------
+//
+// Function: test_OLESpecTickerExample
+//
+// Synopsis: This function generates the ticker property set
+// example that's used in the OLE Programmer's Reference
+// (when describing property ID 0 - the dictionary).
+//
+//--------------------------------------------------------
+
+
+#define PID_SYMBOL 0x7
+#define PID_OPEN 0x3
+#define PID_CLOSE 0x4
+#define PID_HIGH 0x5
+#define PID_LOW 0x6
+#define PID_LAST 0x8
+#define PID_VOLUME 0x9
+
+void test_OLESpecTickerExample( IStorage* pstg )
+{
+ STATUS(( " Generate the Stock Ticker property set example from the OLE Programmer's Ref\n" ));
+
+ // ------
+ // Locals
+ // ------
+
+ FMTID fmtid;
+
+ PROPSPEC propspec;
+
+ LPOLESTR oszPropSetName = OLESTR( "Stock Quote" );
+
+ LPOLESTR oszTickerSymbolName = OLESTR( "Ticker Symbol" );
+ LPOLESTR oszOpenName = OLESTR( "Opening Price" );
+ LPOLESTR oszCloseName = OLESTR( "Last Closing Price" );
+ LPOLESTR oszHighName = OLESTR( "High Price" );
+ LPOLESTR oszLowName = OLESTR( "Low Price" );
+ LPOLESTR oszLastName = OLESTR( "Last Price" );
+ LPOLESTR oszVolumeName = OLESTR( "Volume" );
+
+ // ---------------------------------
+ // Create a new simple property set.
+ // ---------------------------------
+
+ TSafeStorage< IPropertySetStorage > pPropSetStg(pstg);
+ IPropertyStorage *pPropStg;
+
+ UuidCreate( &fmtid );
+
+ Check(S_OK, pPropSetStg->Create(fmtid,
+ NULL,
+ PROPSETFLAG_DEFAULT, // Unicode
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &pPropStg));
+
+
+ // ---------------------------------------------
+ // Fill in the simply property set's dictionary.
+ // ---------------------------------------------
+
+ // Write the property set's name.
+
+ PROPID pidDictionary = 0;
+ Check(S_OK, pPropStg->WritePropertyNames(1, &pidDictionary, &oszPropSetName ));
+
+ // Write the High price, forcing the dictionary to pad.
+
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = PID_HIGH;
+
+ Check(S_OK, pPropStg->WritePropertyNames(1, &propspec.propid, &oszHighName ));
+
+
+ // Write the ticker symbol.
+
+ propspec.propid = PID_SYMBOL;
+ Check(S_OK, pPropStg->WritePropertyNames(1, &propspec.propid, &oszTickerSymbolName));
+
+ // Write the rest of the dictionary.
+
+ propspec.propid = PID_LOW;
+ Check(S_OK, pPropStg->WritePropertyNames(1, &propspec.propid, &oszLowName));
+
+ propspec.propid = PID_OPEN;
+ Check(S_OK, pPropStg->WritePropertyNames(1, &propspec.propid, &oszOpenName));
+
+ propspec.propid = PID_CLOSE;
+ Check(S_OK, pPropStg->WritePropertyNames(1, &propspec.propid, &oszCloseName));
+
+ propspec.propid = PID_LAST;
+ Check(S_OK, pPropStg->WritePropertyNames(1, &propspec.propid, &oszLastName));
+
+ propspec.propid = PID_VOLUME;
+ Check(S_OK, pPropStg->WritePropertyNames(1, &propspec.propid, &oszVolumeName));
+
+
+ // Write out the ticker symbol.
+
+ propspec.propid = PID_SYMBOL;
+
+ PROPVARIANT propvar;
+ propvar.vt = VT_LPWSTR;
+ propvar.pwszVal = L"MSFT";
+
+ Check(S_OK, pPropStg->WriteMultiple(1, &propspec, &propvar, 2));
+
+
+ // ----
+ // Exit
+ // ----
+
+ Check(S_OK, pPropStg->Commit( STGC_DEFAULT ));
+ Check(S_OK, pPropStg->Release());
+ Check(S_OK, pstg->Commit( STGC_DEFAULT ));
+
+ return;
+
+
+} // test_OLESpecTickerExample()
+
+
+void
+test_Office( LPOLESTR wszTestFile )
+{
+ STATUS(( " Generate Office Property Sets\n" ));
+
+ TSafeStorage<IStorage> pStg;
+ TSafeStorage<IPropertyStorage> pPStgSumInfo, pPStgDocSumInfo, pPStgUserDefined;
+
+ PROPVARIANT propvarWrite, propvarRead;
+ PROPSPEC propspec;
+
+ PropVariantInit( &propvarWrite );
+ PropVariantInit( &propvarRead );
+
+ // Create the DocFile
+
+ Check(S_OK, StgCreateDocfile( wszTestFile,
+ STGM_DIRECT | STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0,
+ &pStg));
+
+ // Create the SummaryInformation property set.
+
+ TSafeStorage<IPropertySetStorage> pPSStg( pStg );
+ Check(S_OK, pPSStg->Create( FMTID_SummaryInformation,
+ NULL,
+ PROPSETFLAG_ANSI,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &pPStgSumInfo ));
+
+ // Write a Title to the SumInfo property set.
+
+ PropVariantInit( &propvarWrite );
+ propvarWrite.vt = VT_LPSTR;
+ propvarWrite.pszVal = "Title from PropTest";
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = PID_TITLE;
+
+ Check( S_OK, pPStgSumInfo->WriteMultiple( 1, &propspec, &propvarWrite, PID_FIRST_USABLE ));
+ Check( S_OK, pPStgSumInfo->ReadMultiple( 1, &propspec, &propvarRead ));
+
+ Check( TRUE, propvarWrite.vt == propvarRead.vt );
+ Check( FALSE, strcmp( propvarWrite.pszVal, propvarRead.pszVal ));
+
+ PropVariantClear( &propvarRead );
+ PropVariantInit( &propvarRead );
+ pPStgSumInfo->Release();
+ pPStgSumInfo = NULL;
+
+
+ // Create the DocumentSummaryInformation property set.
+
+ Check(S_OK, pPSStg->Create( FMTID_DocSummaryInformation,
+ NULL,
+ PROPSETFLAG_ANSI,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &pPStgDocSumInfo ));
+
+ // Write a word-count to the DocSumInfo property set.
+
+ PropVariantInit( &propvarWrite );
+ propvarWrite.vt = VT_I4;
+ propvarWrite.lVal = 100;
+ propspec.ulKind = PRSPEC_PROPID;
+ propspec.propid = PID_WORDCOUNT;
+
+ Check( S_OK, pPStgDocSumInfo->WriteMultiple( 1, &propspec, &propvarWrite, PID_FIRST_USABLE ));
+ Check( S_OK, pPStgDocSumInfo->ReadMultiple( 1, &propspec, &propvarRead ));
+
+ Check( TRUE, propvarWrite.vt == propvarRead.vt );
+ Check( TRUE, propvarWrite.lVal == propvarRead.lVal );
+
+ PropVariantClear( &propvarRead );
+ PropVariantInit( &propvarRead );
+ pPStgDocSumInfo->Release();
+ pPStgDocSumInfo = NULL;
+
+
+ // Create the UserDefined property set.
+
+ Check(S_OK, pPSStg->Create( FMTID_UserDefinedProperties,
+ NULL,
+ PROPSETFLAG_ANSI,
+ STGM_CREATE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_READWRITE,
+ &pPStgUserDefined ));
+
+ // Write named string to the UserDefined property set.
+
+ PropVariantInit( &propvarWrite );
+ propvarWrite.vt = VT_LPSTR;
+ propvarWrite.pszVal = "User-Defined string from PropTest";
+ propspec.ulKind = PRSPEC_LPWSTR;
+ propspec.lpwstr = OLESTR("PropTest String");
+
+ Check( S_OK, pPStgUserDefined->WriteMultiple( 1, &propspec, &propvarWrite, PID_FIRST_USABLE ));
+ Check( S_OK, pPStgUserDefined->ReadMultiple( 1, &propspec, &propvarRead ));
+
+ Check( TRUE, propvarWrite.vt == propvarRead.vt );
+ Check( FALSE, strcmp( propvarWrite.pszVal, propvarRead.pszVal ));
+
+ PropVariantClear( &propvarRead );
+ PropVariantInit( &propvarRead );
+ pPStgUserDefined->Release();
+ pPStgUserDefined = NULL;
+
+
+ // And we're done! (Everything releases automatically)
+
+ return;
+
+}
+
+
+void test_PropVariantCopy( )
+{
+ STATUS(( " PropVariantCopy\n" ));
+
+ PROPVARIANT propvarCopy;
+ PropVariantInit( &propvarCopy );
+
+ for( int i = 0; i < CPROPERTIES_ALL; i++ )
+ {
+ Check(S_OK, PropVariantCopy( &propvarCopy, &g_rgcpropvarAll[i] ));
+ Check(S_OK, CPropVariant::Compare( &propvarCopy, &g_rgcpropvarAll[i] ));
+ PropVariantClear( &propvarCopy );
+ }
+
+}
+
+
+
+#define PERFORMANCE_ITERATIONS 300
+#define STABILIZATION_ITERATIONS 10
+
+void
+test_Performance( IStorage *pStg )
+{
+//#ifndef _MAC
+
+ STATUS(( " Performance\n" ));
+
+ CPropVariant rgcpropvar[2];
+ CPropSpec rgpropspec[2];
+
+ TSafeStorage< IPropertySetStorage > pPSStg( pStg );
+ TSafeStorage< IPropertyStorage > pPStg;
+ TSafeStorage< IStream > pStm;
+
+ FMTID fmtid;
+ ULONG ulCount;
+ DWORD dwSumTimes;
+ FILETIME filetimeStart, filetimeEnd;
+
+ BYTE *pPropertyBuffer;
+ ULONG cbPropertyBuffer;
+
+ UuidCreate( &fmtid );
+
+ rgcpropvar[0][0] = L"I wish I were an Oscar Meyer wiener,";
+ rgcpropvar[0][1] = L"That is what I'd truly like to be.";
+ rgcpropvar[1][0] = "For if I were an Oscar Meyer wiener,";
+ rgcpropvar[1][1] = "Everyone would be in love with me.";
+
+ ASSERT( (VT_LPWSTR | VT_VECTOR) == rgcpropvar[0].VarType() );
+ ASSERT( (VT_LPSTR | VT_VECTOR) == rgcpropvar[1].VarType() );
+
+
+ // ----------------
+ // Test an IStorage
+ // ----------------
+
+ // Create a buffer to write which is the same size as
+ // the properties in rgcpropvar.
+
+ cbPropertyBuffer = sizeof(WCHAR)
+ *
+ (2 + wcslen(rgcpropvar[0][0]) + wcslen(rgcpropvar[0][1]));
+
+ cbPropertyBuffer += (2 + strlen(rgcpropvar[1][0]) + strlen(rgcpropvar[1][1]));
+
+ pPropertyBuffer = (BYTE*) CoTaskMemAlloc( cbPropertyBuffer );
+
+ PRINTF( " Docfile CreateStream/Write/Release = " );
+ dwSumTimes = 0;
+
+ // Perform the test iterations
+
+ for( ulCount = 0;
+ ulCount < PERFORMANCE_ITERATIONS + STABILIZATION_ITERATIONS;
+ ulCount++ )
+ {
+ if( ulCount == STABILIZATION_ITERATIONS )
+ CoFileTimeNow( &filetimeStart );
+
+ Check(S_OK, pStg->CreateStream( OLESTR("StoragePerformance"),
+ STGM_CREATE | STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L, 0L,
+ &pStm ));
+
+ Check(S_OK, pStm->Write( pPropertyBuffer, cbPropertyBuffer, NULL ));
+ pStm->Release(); pStm = NULL;
+
+ }
+
+ CoFileTimeNow( &filetimeEnd );
+ filetimeEnd -= filetimeStart;
+ PRINTF( "%4.2f ms\n", (float)filetimeEnd.dwLowDateTime
+ /
+ 10000 // # of 100 nanosec units in 1 ms
+ /
+ PERFORMANCE_ITERATIONS );
+
+ // ------------------------------------------------------
+ // Try Creating a Property Set and writing two properties
+ // ------------------------------------------------------
+
+ rgpropspec[0] = OLESTR("First Property");
+ rgpropspec[1] = OLESTR("Second Property");
+
+ PRINTF( " PropSet Create(Overwrite)/WriteMultiple/Release = " );
+ dwSumTimes = 0;
+
+ for( ulCount = 0;
+ ulCount < PERFORMANCE_ITERATIONS + STABILIZATION_ITERATIONS;
+ ulCount++ )
+ {
+ if( ulCount == STABILIZATION_ITERATIONS )
+ CoFileTimeNow( &filetimeStart) ;
+
+ Check(S_OK, pPSStg->Create( fmtid,
+ NULL,
+ PROPSETFLAG_DEFAULT | PROPSETFLAG_NONSIMPLE,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPStg ));
+
+ Check(S_OK, pPStg->WriteMultiple( 2, rgpropspec, rgcpropvar, PID_FIRST_USABLE ));
+ pPStg->Release(); pPStg = NULL;
+
+ }
+
+ CoFileTimeNow( &filetimeEnd );
+ filetimeEnd -= filetimeStart;
+ PRINTF( "%4.2f ms\n", (float)filetimeEnd.dwLowDateTime
+ /
+ 10000 // 100 ns units to 1 ms units
+ /
+ PERFORMANCE_ITERATIONS );
+
+
+
+ // ------------------------------------------------------
+ // WriteMultiple (with named properties) Performance Test
+ // ------------------------------------------------------
+
+
+ PRINTF( " WriteMultiple (named properties) = " );
+
+ Check(S_OK, pPSStg->Create( fmtid,
+ NULL,
+ PROPSETFLAG_DEFAULT | PROPSETFLAG_NONSIMPLE,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPStg ));
+
+ for( ulCount = 0;
+ ulCount < PERFORMANCE_ITERATIONS + STABILIZATION_ITERATIONS;
+ ulCount++ )
+ {
+ if( ulCount == STABILIZATION_ITERATIONS )
+ CoFileTimeNow( &filetimeStart );
+
+ for( int i = 0; i < CPROPERTIES_ALL; i++ )
+ {
+ Check(S_OK, pPStg->WriteMultiple( 1, &g_rgcpropspecAll[i], &g_rgcpropvarAll[i], PID_FIRST_USABLE ));
+ }
+ }
+
+ CoFileTimeNow( &filetimeEnd );
+ filetimeEnd -= filetimeStart;
+ PRINTF( "%4.2f ms\n", (float) filetimeEnd.dwLowDateTime
+ /
+ 10000 // 100 ns units to 1 ms units
+ /
+ PERFORMANCE_ITERATIONS );
+
+ pPStg->Release();
+ pPStg = NULL;
+
+
+ // --------------------------------------------------------
+ // WriteMultiple (with unnamed properties) Performance Test
+ // --------------------------------------------------------
+
+
+ {
+ CPropSpec rgcpropspecPIDs[ CPROPERTIES_ALL ];
+
+ PRINTF( " WriteMultiple (unnamed properties) = " );
+
+ Check(S_OK, pPSStg->Create( fmtid,
+ NULL,
+ PROPSETFLAG_DEFAULT | PROPSETFLAG_NONSIMPLE,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPStg ));
+
+ for( ulCount = 0; ulCount < CPROPERTIES_ALL; ulCount++ )
+ {
+ rgcpropspecPIDs[ ulCount ] = ulCount + PID_FIRST_USABLE;
+ }
+
+
+ for( ulCount = 0;
+ ulCount < PERFORMANCE_ITERATIONS + STABILIZATION_ITERATIONS;
+ ulCount++ )
+ {
+ if( ulCount == STABILIZATION_ITERATIONS )
+ CoFileTimeNow( &filetimeStart );
+
+ for( int i = 0; i < CPROPERTIES_ALL; i++ )
+ {
+ Check(S_OK, pPStg->WriteMultiple( 1, &rgcpropspecPIDs[i], &g_rgcpropvarAll[i], PID_FIRST_USABLE ));
+ }
+ }
+
+ CoFileTimeNow( &filetimeEnd );
+ filetimeEnd -= filetimeStart;
+ PRINTF( "%4.2f ms\n", (float) filetimeEnd.dwLowDateTime
+ /
+ 10000 // 100 ns units to 1 ms units
+ /
+ PERFORMANCE_ITERATIONS );
+
+ pPStg->Release();
+ pPStg = NULL;
+ }
+
+//#endif // #ifndef _MAC
+
+} // test_Performance()
+
+
+
+
+//
+// Function: test_CoFileTimeNow
+//
+// This function has nothing to do with the property set code,
+// but a property test happenned to expose a bug in it, so this
+// was just as good a place as any to test the fix.
+//
+
+
+void
+test_CoFileTimeNow()
+{
+#ifndef _MAC // No need to test this on the Mac, and we can't
+ // because it doesn't support SYSTEMTIME.
+
+ STATUS(( " CoFileTimeNow " ));
+
+ FILETIME ftCoFileTimeNow;
+ FILETIME ftCalculated;
+ SYSTEMTIME stCalculated;
+
+
+ // Test the input validation
+
+ Check(E_INVALIDARG, CoFileTimeNow( NULL ));
+ Check(E_INVALIDARG, CoFileTimeNow( (FILETIME*) 0x01234567 ));
+
+
+ // The bug in CoFileTimeNow caused it to report a time that was
+ // 900 ms short, 50% of the time. So let's just bounds check
+ // it several times as a verification.
+
+ for( int i = 0; i < 20; i++ )
+ {
+ Check(S_OK, CoFileTimeNow( &ftCoFileTimeNow ));
+ GetSystemTime(&stCalculated);
+ Check(TRUE, SystemTimeToFileTime(&stCalculated, &ftCalculated));
+ Check(TRUE, ftCoFileTimeNow <= ftCalculated );
+
+ Check(S_OK, CoFileTimeNow( &ftCoFileTimeNow ));
+ Check(TRUE, ftCoFileTimeNow >= ftCalculated );
+
+ // The CoFileTimeNow bug caused it to report the correct
+ // time for a second, then the 900 ms short time for a second.
+ // So let's sleep in this loop and ensure that we cover both
+ // seconds.
+
+ if( g_fVerbose )
+ PRINTF( "." );
+
+ Sleep(200);
+ }
+ PRINTF( "\n" );
+
+#endif // #ifndef _MAC
+
+}
+
+
+void
+test_PROPSETFLAG_UNBUFFERED( IStorage *pStg )
+{
+ // ----------
+ // Initialize
+ // ----------
+
+ STATUS(( " PROPSETFLAG_UNBUFFERED\n" ));
+
+ TSafeStorage< IStorage > pStgBase;
+ TSafeStorage< IPropertyStorage > pPropStgUnbuffered, pPropStgBuffered;
+ TSafeStorage< IStream > pstmUnbuffered, pstmBuffered;
+
+ CPropSpec cpropspec;
+ CPropVariant cpropvar;
+
+ FMTID fmtidUnbuffered, fmtidBuffered;
+ OLECHAR oszPropStgNameUnbuffered[ CCH_MAX_PROPSTG_NAME+1 ],
+ oszPropStgNameBuffered[ CCH_MAX_PROPSTG_NAME+1 ];
+
+ // Generate two FMTIDs
+
+ UuidCreate( &fmtidUnbuffered );
+ UuidCreate( &fmtidBuffered );
+
+ // ----------------------------
+ // Create the Property Storages
+ // ----------------------------
+
+ // Create a transacted Storage
+
+ Check( S_OK, pStg->CreateStorage(
+ OLESTR("test_PROPSETFLAG_UNBUFFERED"),
+ STGM_CREATE | STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L, 0L,
+ &pStgBase ));
+
+ // What are the property storages' stream names?
+
+ FmtIdToPropStgName( &fmtidUnbuffered, oszPropStgNameUnbuffered );
+ FmtIdToPropStgName( &fmtidBuffered, oszPropStgNameBuffered );
+
+ // Create Streams for the property storages
+
+ Check( S_OK, pStgBase->CreateStream(
+ oszPropStgNameUnbuffered,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L, 0L,
+ &pstmUnbuffered ));
+
+ Check( S_OK, pStgBase->CreateStream(
+ oszPropStgNameBuffered,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L, 0L,
+ &pstmBuffered ));
+
+
+ // Create two direct-mode IPropertyStorages (one buffered, one not)
+
+ Check( S_OK, StgCreatePropStg( (IUnknown*) pstmUnbuffered,
+ fmtidUnbuffered,
+ &CLSID_NULL,
+ PROPSETFLAG_UNBUFFERED,
+ 0L, // Reserved
+ &pPropStgUnbuffered ));
+ pPropStgUnbuffered->Commit( STGC_DEFAULT );
+ pstmUnbuffered->Release(); pstmUnbuffered = NULL;
+
+ Check( S_OK, StgCreatePropStg( (IUnknown*) pstmBuffered,
+ fmtidBuffered,
+ &CLSID_NULL,
+ PROPSETFLAG_DEFAULT,
+ 0L, // Reserved
+ &pPropStgBuffered ));
+ pPropStgBuffered->Commit( STGC_DEFAULT );
+ pstmBuffered->Release(); pstmBuffered = NULL;
+
+
+ // -------------------------
+ // Write, Commit, and Revert
+ // -------------------------
+
+ // Write to both property storages
+
+ cpropvar = "A Test String";
+ cpropspec = OLESTR("Property Name");
+
+ Check( S_OK, pPropStgUnbuffered->WriteMultiple( 1,
+ cpropspec,
+ cpropvar,
+ PID_FIRST_USABLE ));
+
+ Check( S_OK, pPropStgBuffered->WriteMultiple( 1,
+ cpropspec,
+ cpropvar,
+ PID_FIRST_USABLE ));
+
+ // Commit the base Storage. This should only cause
+ // the Unbuffered property to be commited.
+
+ pStgBase->Commit( STGC_DEFAULT );
+
+ // Revert the base Storage, and release the property storages.
+ // This should cause the property in the buffered property storage
+ // to be lost.
+
+ pStgBase->Revert();
+ pPropStgUnbuffered->Release(); pPropStgUnbuffered = NULL;
+ pPropStgBuffered->Release(); pPropStgBuffered = NULL;
+
+ // -----------------------------
+ // Re-Open the property storages
+ // -----------------------------
+
+ // Open the property storage Streams
+
+ Check( S_OK, pStgBase->OpenStream( oszPropStgNameUnbuffered,
+ 0L,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L,
+ &pstmUnbuffered ));
+
+ Check( S_OK, pStgBase->OpenStream( oszPropStgNameBuffered,
+ 0L,
+ STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0L,
+ &pstmBuffered ));
+
+ // Get IPropertyStorage interfaces
+
+ Check( S_OK, StgOpenPropStg( (IUnknown*) pstmUnbuffered,
+ fmtidUnbuffered,
+ PROPSETFLAG_UNBUFFERED,
+ 0L, // Reserved
+ &pPropStgUnbuffered ));
+ pstmUnbuffered->Release(); pstmUnbuffered = NULL;
+
+ Check( S_OK, StgOpenPropStg( (IUnknown*) pstmBuffered,
+ fmtidBuffered,
+ PROPSETFLAG_DEFAULT,
+ 0L, // Reserved
+ &pPropStgBuffered ));
+ pstmBuffered->Release(); pstmBuffered = NULL;
+
+
+ // --------------------
+ // Validate the results
+ // --------------------
+
+ // We should only find the property in the un-buffered property set.
+
+ cpropvar.Clear();
+ Check( S_OK, pPropStgUnbuffered->ReadMultiple( 1, cpropspec, cpropvar ));
+ cpropvar.Clear();
+ Check( S_FALSE, pPropStgBuffered->ReadMultiple( 1, cpropspec, cpropvar ));
+ cpropvar.Clear();
+
+
+} // test_PROPSETFLAG_UNBUFFERED()
+
+
+void
+test_PropStgNameConversion2()
+{
+ STATUS(( " FmtIdToPropStgName & PropStgNameToFmtId\n" ));
+
+ // ------
+ // Locals
+ // ------
+
+ FMTID fmtidOriginal, fmtidNew;
+ OLECHAR oszPropStgName[ CCH_MAX_PROPSTG_NAME+1 ];
+
+ // ----------------------------------
+ // Do a simple conversion and inverse
+ // ----------------------------------
+
+ UuidCreate( &fmtidOriginal );
+ fmtidNew = FMTID_NULL;
+
+ Check( S_OK, FmtIdToPropStgName( &fmtidOriginal, oszPropStgName ));
+ Check( S_OK, PropStgNameToFmtId( oszPropStgName, &fmtidNew ));
+
+ Check( TRUE, fmtidOriginal == fmtidNew );
+
+ // -----------------------
+ // Check the special-cases
+ // -----------------------
+
+ // Summary Information
+
+ Check( S_OK, FmtIdToPropStgName( &FMTID_SummaryInformation, oszPropStgName ));
+ Check( 0, ocscmp( oszPropStgName, oszSummaryInformation ));
+ Check( S_OK, PropStgNameToFmtId( oszPropStgName, &fmtidNew ));
+ Check( TRUE, FMTID_SummaryInformation == fmtidNew );
+
+ // DocSumInfo (first section)
+
+ Check( S_OK, FmtIdToPropStgName( &FMTID_DocSummaryInformation, oszPropStgName ));
+ Check( 0, ocscmp( oszPropStgName, oszDocSummaryInformation ));
+ Check( S_OK, PropStgNameToFmtId( oszPropStgName, &fmtidNew ));
+ Check( TRUE, FMTID_DocSummaryInformation == fmtidNew );
+
+ // DocSumInfo (second section)
+
+ Check( S_OK, FmtIdToPropStgName( &FMTID_UserDefinedProperties, oszPropStgName ));
+ Check( 0, ocscmp( oszPropStgName, oszDocSummaryInformation ));
+ Check( S_OK, PropStgNameToFmtId( oszPropStgName, &fmtidNew ));
+ Check( TRUE, FMTID_DocSummaryInformation == fmtidNew );
+
+ // GlobalInfo (for PictureIt!)
+
+ Check( S_OK, FmtIdToPropStgName( &fmtidGlobalInfo, oszPropStgName ));
+ Check( 0, ocscmp( oszPropStgName, oszGlobalInfo ));
+ Check( S_OK, PropStgNameToFmtId( oszPropStgName, &fmtidNew ));
+ Check( TRUE, fmtidGlobalInfo == fmtidNew );
+
+ // ImageContents (for PictureIt!)
+
+ Check( S_OK, FmtIdToPropStgName( &fmtidImageContents, oszPropStgName ));
+ Check( 0, ocscmp( oszPropStgName, oszImageContents ));
+ Check( S_OK, PropStgNameToFmtId( oszPropStgName, &fmtidNew ));
+ Check( TRUE, fmtidImageContents == fmtidNew );
+
+ // ImageInfo (for PictureIt!)
+
+ Check( S_OK, FmtIdToPropStgName( &fmtidImageInfo, oszPropStgName ));
+ wprintf( L"Original = %ws, Convert = %ws\n", oszImageInfo, oszPropStgName );
+ Check( 0, ocscmp( oszPropStgName, oszImageInfo ));
+ Check( S_OK, PropStgNameToFmtId( oszPropStgName, &fmtidNew ));
+ Check( TRUE, fmtidImageInfo == fmtidNew );
+
+
+} // test_PropStgNameConversion()
+
+void
+test_PropStgNameConversion( IStorage *pStg )
+{
+ STATUS(( " Special-case property set names\n" ));
+
+ // ------
+ // Locals
+ // ------
+
+ IStorage *pStgSub = NULL;
+ IPropertyStorage *pPropStg = NULL;
+ IPropertySetStorage *pPropSetStg = NULL;
+ IEnumSTATSTG *pEnumStg = NULL;
+ IEnumSTATPROPSETSTG *pEnumPropSet = NULL;
+
+ STATSTG rgstatstg[ NUM_WELL_KNOWN_PROPSETS ];
+ STATPROPSETSTG rgstatpropsetstg[ NUM_WELL_KNOWN_PROPSETS ];
+ UINT i;
+ DWORD cEnum;
+
+ BOOL bSumInfo= FALSE,
+ bDocSumInfo= FALSE,
+ bGlobalInfo= FALSE,
+ bImageContents= FALSE,
+ bImageInfo= FALSE;
+
+
+ // ------------------------------
+ // Create a Storage for this test
+ // ------------------------------
+
+ Check( S_OK, pStg->CreateStorage( OLESTR("Special Cases"),
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ 0, 0,
+ &pStgSub ));
+
+ // And get an IPropertySetStorage
+
+#ifdef WINNT
+ Check( S_OK, pStgSub->QueryInterface( IID_IPropertySetStorage, (void**)&pPropSetStg ));
+#else
+ Check( S_OK, StgCreatePropSetStg( pStgSub, 0, &pPropSetStg ));
+#endif
+
+
+ // --------------------------------------------------
+ // Create one of each of the well-known property sets
+ // --------------------------------------------------
+
+ Check( S_OK, pPropSetStg->Create( FMTID_SummaryInformation,
+ &CLSID_NULL,
+ PROPSETFLAG_ANSI,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPropStg ));
+ RELEASE_INTERFACE( pPropStg );
+
+ Check( S_OK, pPropSetStg->Create( FMTID_DocSummaryInformation,
+ &CLSID_NULL,
+ PROPSETFLAG_ANSI,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPropStg ));
+ RELEASE_INTERFACE( pPropStg );
+
+ Check( S_OK, pPropSetStg->Create( FMTID_UserDefinedProperties,
+ &CLSID_NULL,
+ PROPSETFLAG_ANSI,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPropStg ));
+ RELEASE_INTERFACE( pPropStg );
+
+ Check( S_OK, pPropSetStg->Create( fmtidGlobalInfo,
+ &CLSID_NULL,
+ PROPSETFLAG_ANSI,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPropStg ));
+ RELEASE_INTERFACE( pPropStg );
+
+ Check( S_OK, pPropSetStg->Create( fmtidImageContents,
+ &CLSID_NULL,
+ PROPSETFLAG_ANSI,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPropStg ));
+ RELEASE_INTERFACE( pPropStg );
+
+ Check( S_OK, pPropSetStg->Create( fmtidImageInfo,
+ &CLSID_NULL,
+ PROPSETFLAG_ANSI,
+ STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
+ &pPropStg ));
+ RELEASE_INTERFACE( pPropStg );
+
+
+ // ---------------------------------
+ // Verify the FMTID->Name conversion
+ // ---------------------------------
+
+ // We verify this by enumerating the Storage's streams,
+ // and checking for the expected names (e.g., we should see
+ // "SummaryInformation", "DocumentSummaryInformation", etc.)
+
+ Check( S_OK, pStgSub->EnumElements( 0, NULL, 0, &pEnumStg ));
+
+ // Get all of the names.
+
+ Check( S_FALSE, pEnumStg->Next( NUM_WELL_KNOWN_PROPSETS,
+ rgstatstg,
+ &cEnum ));
+
+ // There should only be WellKnown-1 stream names, since
+ // the UserDefined property set is part of the
+ // DocumentSummaryInformation stream.
+
+ Check( TRUE, cEnum == NUM_WELL_KNOWN_PROPSETS - 1 );
+
+
+ for( i = 0; i < cEnum; i++ )
+ {
+ if( !ocscmp( rgstatstg[i].pwcsName, oszSummaryInformation ))
+ bSumInfo= TRUE;
+ else if( !ocscmp( rgstatstg[i].pwcsName, oszDocSummaryInformation ))
+ bDocSumInfo= TRUE;
+ else if( !ocscmp( rgstatstg[i].pwcsName, oszGlobalInfo ))
+ bGlobalInfo= TRUE;
+ else if( !ocscmp( rgstatstg[i].pwcsName, oszImageContents ))
+ bImageContents= TRUE;
+ else if( !ocscmp( rgstatstg[i].pwcsName, oszImageInfo ))
+ bImageInfo= TRUE;
+
+ CoTaskMemFree( rgstatstg[i].pwcsName );
+ }
+
+ // Verify that we found all the names we expected to find.
+
+ Check( TRUE, bSumInfo && bDocSumInfo
+ && bGlobalInfo && bImageContents && bImageInfo );
+
+
+ RELEASE_INTERFACE( pEnumStg );
+
+ // ---------------------------------
+ // Verify the Name->FMTID Conversion
+ // ---------------------------------
+
+ // We do this by enumerating the property sets with IPropertySetStorage,
+ // and verify that it correctly converts the Stream names to the
+ // expected FMTIDs.
+
+ bSumInfo = bDocSumInfo = bGlobalInfo = bImageContents = bImageInfo = FALSE;
+
+ // Get the enumerator.
+
+ Check( S_OK, pPropSetStg->Enum( &pEnumPropSet ));
+
+ // Get all the property sets.
+
+ Check( S_FALSE, pEnumPropSet->Next( NUM_WELL_KNOWN_PROPSETS,
+ rgstatpropsetstg,
+ &cEnum ));
+ Check( TRUE, cEnum == NUM_WELL_KNOWN_PROPSETS - 1 );
+
+
+ // Look for each of the expected FMTIDs. We only look at WellKnown-1,
+ // because the UserDefined property set doesn't get enumerated.
+
+ for( i = 0; i < NUM_WELL_KNOWN_PROPSETS - 1; i++ )
+ {
+ if( rgstatpropsetstg[i].fmtid == FMTID_SummaryInformation )
+ bSumInfo = TRUE;
+ else if( rgstatpropsetstg[i].fmtid == FMTID_DocSummaryInformation )
+ bDocSumInfo = TRUE;
+ else if( rgstatpropsetstg[i].fmtid == fmtidGlobalInfo )
+ bGlobalInfo = TRUE;
+ else if( rgstatpropsetstg[i].fmtid == fmtidImageContents )
+ bImageContents = TRUE;
+ else if( rgstatpropsetstg[i].fmtid == fmtidImageInfo )
+ bImageInfo = TRUE;
+
+ }
+
+ // NOTE: There is no way(?) to test the name-to-FMTID
+ // conversion for the UserDefined property set without
+ // calling the conversion function directly, but that
+ // function isn't exported on Win95.
+
+
+ // Verify that we found all of the expected FMTIDs
+
+ Check( TRUE, bSumInfo && bDocSumInfo
+ && bGlobalInfo && bImageContents && bImageInfo );
+
+
+ RELEASE_INTERFACE( pEnumPropSet );
+ RELEASE_INTERFACE( pPropSetStg );
+ RELEASE_INTERFACE( pStgSub );
+
+} // test_PropStgNameConversion()
+
diff --git a/private/ole32/stg/props/utest/testdoc.cxx b/private/ole32/stg/props/utest/testdoc.cxx
new file mode 100644
index 000000000..65615a947
--- /dev/null
+++ b/private/ole32/stg/props/utest/testdoc.cxx
@@ -0,0 +1,421 @@
+unsigned char g_achTestDoc[] = {
+ 0xd0,0xcf,0x11,0xe0,0xa1,0xb1,0x1a,0xe1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xfe,0xff,0x09,0x00,//........>.......
+ 0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x03,0x00,0x00,0x00,//................
+ 0x01,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0x52,0x00,0x6f,0x00,0x6f,0x00,0x74,0x00,0x20,0x00,0x45,0x00,0x6e,0x00,0x74,0x00,//R.o.o.t. .E.n.t.
+ 0x72,0x00,0x79,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//r.y.............
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x16,0x00,0x05,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,//................
+ 0x00,0x09,0x02,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,//...............F
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x7f,0xd9,0x7b,//............P..{
+ 0x1a,0x05,0xba,0x01,0x06,0x00,0x00,0x00,0x40,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,//........@.......
+ 0x01,0x00,0x43,0x00,0x6f,0x00,0x6d,0x00,0x70,0x00,0x4f,0x00,0x62,0x00,0x6a,0x00,//..C.o.m.p.O.b.j.
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x12,0x00,0x02,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//........n.......
+ 0x57,0x00,0x6f,0x00,0x72,0x00,0x64,0x00,0x44,0x00,0x6f,0x00,0x63,0x00,0x75,0x00,//W.o.r.d.D.o.c.u.
+ 0x6d,0x00,0x65,0x00,0x6e,0x00,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//m.e.n.t.........
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x1a,0x00,0x02,0x01,0xff,0xff,0xff,0xff,0x04,0x00,0x00,0x00,0xff,0xff,0xff,0xff,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xb5,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x4f,0x00,0x62,0x00,0x6a,0x00,0x65,0x00,0x63,0x00,0x74,0x00,0x50,0x00,0x6f,0x00,//O.b.j.e.c.t.P.o.
+ 0x6f,0x00,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//o.l.............
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x16,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0xff,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x81,0x8f,0x87,0x7a,0x04,0xba,0x01,0x00,0x81,0x8f,0x87,//........z.......
+ 0x7a,0x04,0xba,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//z...............
+ 0x02,0x00,0x00,0x00,0xfd,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,//................
+ 0x07,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x08,0x00,0x00,0x00,//................
+ 0x09,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0x05,0x00,0x53,0x00,0x75,0x00,0x6d,0x00,0x6d,0x00,0x61,0x00,0x72,0x00,0x79,0x00,//..S.u.m.m.a.r.y.
+ 0x49,0x00,0x6e,0x00,0x66,0x00,0x6f,0x00,0x72,0x00,0x6d,0x00,0x61,0x00,0x74,0x00,//I.n.f.o.r.m.a.t.
+ 0x69,0x00,0x6f,0x00,0x6e,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//i.o.n...........
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0x28,0x00,0x02,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//(...............
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0xdd,0x01,0x00,0x00,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0x01,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,//................
+ 0x05,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x08,0x00,0x00,0x00,//................
+ 0x09,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,//................
+ 0x0d,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x17,0x00,0x00,0x00,0x10,0x00,0x00,0x00,//................
+ 0x11,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x13,0x00,0x00,0x00,0x14,0x00,0x00,0x00,//................
+ 0x15,0x00,0x00,0x00,0x16,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x18,0x00,0x00,0x00,//................
+ 0x19,0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,//................
+ 0x1d,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,0x20,0x00,0x00,0x00,//............ ...
+ 0x21,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x24,0x00,0x00,0x00,//!..."...#...$...
+ 0x25,0x00,0x00,0x00,0x26,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x28,0x00,0x00,0x00,//%...&...'...(...
+ 0x29,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x2b,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,//)...*...+...,...
+ 0x2d,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,0x2f,0x00,0x00,0x00,0x30,0x00,0x00,0x00,//-......./...0...
+ 0x31,0x00,0x00,0x00,0x32,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x34,0x00,0x00,0x00,//1...2...3...4...
+ 0x35,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x37,0x00,0x00,0x00,0x38,0x00,0x00,0x00,//5...6...7...8...
+ 0x39,0x00,0x00,0x00,0x3a,0x00,0x00,0x00,0x3b,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,//9...:...;...<...
+ 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0x02,0x00,0x00,0x00,0xab,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0xca,0x00,0x00,0x00,//................
+ 0x05,0x00,0x00,0x00,0xeb,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x0d,0x01,0x00,0x00,//................
+ 0x04,0x00,0x00,0x00,0x2f,0x01,0x00,0x00,0x08,0x00,0x00,0x00,0x4f,0x01,0x00,0x00,//..../.......O...
+ 0x01,0x00,0x00,0x00,0x62,0x01,0x00,0x00,0x0f,0x00,0x00,0x00,0x68,0x01,0x00,0x00,//....b.......h...
+ 0x10,0x00,0x00,0x00,0x70,0x01,0x00,0x00,0x12,0x00,0x00,0x00,0x78,0x01,0x00,0x00,//....p.......x...
+ 0x0e,0x00,0x00,0x00,0x93,0x01,0x00,0x00,0x09,0x00,0x00,0x00,0x9b,0x01,0x00,0x00,//................
+ 0x13,0x00,0x00,0x00,0xa5,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,//................
+ 0x4e,0x6f,0x72,0x6d,0x61,0x6c,0x2e,0x64,0x6f,0x74,0x00,0x1e,0x00,0x00,0x00,0x17,//Normal.dot......
+ 0x00,0x00,0x00,0x54,0x69,0x74,0x6c,0x65,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,//...Title of the
+ 0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x00,0x1e,0x00,0x00,0x00,0x19,0x00,//document........
+ 0x00,0x00,0x53,0x75,0x62,0x6a,0x65,0x63,0x74,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,//..Subject of the
+ 0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x00,0x1e,0x00,0x00,0x00,0x1a,// document.......
+ 0x00,0x00,0x00,0x4b,0x65,0x79,0x77,0x6f,0x72,0x64,0x73,0x20,0x6f,0x66,0x20,0x74,//...Keywords of t
+ 0x68,0x65,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x00,0x1e,0x00,0x00,//he document.....
+ 0x00,0x1a,0x00,0x00,0x00,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x73,0x20,0x6f,0x66,//.....Comments of
+ 0x20,0x74,0x68,0x65,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x00,0x1e,// the document...
+ 0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x41,0x75,0x74,0x68,0x6f,0x72,0x20,0x6f,0x66,//.......Author of
+ 0x20,0x74,0x68,0x65,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x00,0x1e,// the document...
+ 0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x42,0x69,0x6c,0x6c,0x20,0x4d,0x6f,0x72,0x65,//.......Bill More
+ 0x6c,0x00,0x02,0x00,0x00,0x00,0xe4,0x04,0x03,0x00,0x00,0x00,0x07,0x00,0x00,0x00,//l...............
+ 0x03,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x13,0x00,0x00,0x00,//....A...........
+ 0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x57,0x6f,0x72,0x64,0x20,0x36,//Microsoft Word 6
+ 0x2e,0x30,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x02,//.0..............
+ 0x00,0x00,0x00,0x33,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0xcf,0x11,//...3............
+ 0xe0,0xa1,0xb1,0x1a,0xe1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x03,0x00,0xfe,0xff,0x09,0x00,0x06,0x00,0x00,//.....>..........
+ 0x73,0x64,0x66,0x6f,0x69,0x68,0x73,0x64,0x66,0x0d,0xff,0xff,0xff,0xff,0xff,0xff,//sdfoihsdf.......
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x00,0x01,0x00,//................
+ 0x01,0x00,0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x52,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,//..R.............
+ 0x00,0x00,0x6a,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x6a,0x08,0x00,0x00,0x00,0x00,//..j.......j.....
+ 0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x6a,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,//..j.............
+ 0x00,0x00,0x6a,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,//..j.............
+ 0x00,0x00,0x08,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x08,0x00,0x00,0x08,0x00,//..........~.....
+ 0x00,0x00,0x86,0x08,0x00,0x00,0x0e,0x00,0x00,0x00,0x6a,0x08,0x00,0x00,0x00,0x00,//..........j.....
+ 0x00,0x00,0x6a,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x6a,0x08,0x00,0x00,0x00,0x00,//..j.......j.....
+ 0x00,0x00,0x6a,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,//..j.............
+ 0x00,0x00,0x08,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0x08,0x00,0x00,0x2a,0x00,//..............*.
+ 0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x46,0x6f,0x6f,0x20,0x42,0x61,0x72,0x0d,0x0d,0x73,0x64,0x66,0x6b,0x6a,0x68,0x73,//Foo Bar..sdfkjhs
+ 0x64,0x66,0x6b,0x6a,0x68,0x73,0x64,0x66,0x20,0x0d,0x73,0x20,0x64,0x6a,0x6b,0x73,//dfkjhsdf .s djks
+ 0x61,0x66,0x64,0x6c,0x6a,0x73,0x61,0x66,0x64,0x0d,0x73,0x64,0x66,0x6c,0x6b,0x68,//afdljsafd.sdflkh
+ 0x6a,0x73,0x66,0x61,0x64,0x6c,0x68,0x73,0x66,0x61,0x64,0x0d,0x73,0x64,0x66,0x68,//jsfadlhsfad.sdfh
+ 0xfe,0xff,0x00,0x00,0x03,0x33,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//.....3..........
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xe0,0x85,0x9f,0xf2,//................
+ 0xf9,0x4f,0x68,0x10,0xab,0x91,0x08,0x00,0x2b,0x27,0xb3,0xd9,0x30,0x00,0x00,0x00,//.Oh.....+'..0...
+ 0xad,0x01,0x00,0x00,0x0e,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x98,0x00,0x00,0x00,//................
+ 0x01,0x00,0xfe,0xff,0x03,0x0a,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x09,0x02,0x00,//................
+ 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x1c,0x00,0x00,0x00,//...........F....
+ 0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x57,0x6f,0x72,0x64,0x20,0x36,//Microsoft Word 6
+ 0x2e,0x30,0x20,0x44,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x00,0x0a,0x00,0x00,0x00,//.0 Document.....
+ 0x4d,0x53,0x57,0x6f,0x72,0x64,0x44,0x6f,0x63,0x00,0x10,0x00,0x00,0x00,0x57,0x6f,//MSWordDoc.....Wo
+ 0x72,0x64,0x2e,0x44,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x36,0x00,0xf4,0x39,//rd.Document.6..9
+ 0xb2,0x71,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0xcf,//.q..............
+ 0x11,0xe0,0xa1,0xb1,0x1a,0xe1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0xdc,0xa5,0x68,0x00,0x45,0xc0,0x09,0x04,0x00,0x00,0x24,0x00,0x65,0x00,0x00,0x00,//..h.E.....$.e...
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x09,0x03,0x00,0x00,//................
+ 0xb5,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//....J...........
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x6a,0x00,0x00,0x00,//............j...
+ 0x00,0x08,0x00,0x00,0x6a,0x00,0x00,0x00,0x6a,0x08,0x00,0x00,0x00,0x00,0x00,0x00,//....j...j.......
+ 0x6a,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x6a,0x08,0x00,0x00,0x00,0x00,0x00,0x00,//j.......j.......
+ 0x6a,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x6a,0x08,0x00,0x00,0x14,0x00,0x00,0x00,//j.......j.......
+ 0xca,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x08,0x00,0x00,0x36,0x00,0x00,0x00,//............6...
+ 0xca,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xca,0x08,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0xca,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xca,0x08,0x00,0x00,0x0a,0x00,0x00,0x00,//................
+ 0xd4,0x08,0x00,0x00,0x0a,0x00,0x00,0x00,0xca,0x08,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x97,0x0b,0x00,0x00,0x31,0x00,0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,//....1...........
+ 0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0xde,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x09,0x00,0x00,0x02,0x00,0x00,0x00,//................
+ 0x0a,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x09,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x0a,0x09,0x00,0x00,0x52,0x00,0x00,0x00,0x5c,0x09,0x00,0x00,0xec,0x00,0x00,0x00,//....R...\.......
+ 0x48,0x0a,0x00,0x00,0xec,0x00,0x00,0x00,0x34,0x0b,0x00,0x00,0x1e,0x00,0x00,0x00,//H.......4.......
+ 0xc8,0x0b,0x00,0x00,0x58,0x00,0x00,0x00,0x20,0x0c,0x00,0x00,0x95,0x00,0x00,0x00,//....X... .......
+ 0x52,0x0b,0x00,0x00,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//R...E...........
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6a,0x08,0x00,0x00,0x00,0x00,0x00,0x00,//........j.......
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x03,0x00,0x00,0x09,0x03,0x00,0x00,0x19,0x03,0x00,0x00,0x4a,0x03,0x00,0x00,//............J...
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,//................
+ 0x00,0x03,0x00,0x00,0x08,0x03,0x00,0x00,0x09,0x03,0x00,0x00,0x1a,0x03,0x00,0x00,//................
+ 0x2a,0x03,0x00,0x00,0x3c,0x03,0x00,0x00,0x4a,0x03,0x00,0x00,0xfe,0x00,0x01,0xc0,//*...<...J.......
+ 0x21,0xf0,0x00,0xfe,0x00,0x01,0xc0,0x21,0xf0,0x00,0xfe,0x00,0x01,0xc0,0x21,0xf0,//!......!......!.
+ 0x00,0xfe,0x00,0x01,0xc0,0x21,0xf0,0x00,0xfe,0x00,0x01,0xc0,0x21,0xf0,0x00,0xfe,//.....!......!...
+ 0x00,0x01,0xc0,0x21,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//...!............
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x06,//................
+ 0x0e,0x00,0x0f,0x00,0x08,0x00,0x01,0x00,0x4b,0x00,0x0f,0x00,0x00,0x00,0x00,0x00,//........K.......
+ 0x1a,0x00,0x00,0x40,0xf1,0xff,0x02,0x00,0x1a,0x00,0x06,0x4e,0x6f,0x72,0x6d,0x61,//...@.......Norma
+ 0x6c,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x61,0x09,0x04,0x00,0x00,0x00,0x00,0x00,//l.......a.......
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,//..............".
+ 0x41,0x40,0xf2,0xff,0xa1,0x00,0x22,0x00,0x16,0x44,0x65,0x66,0x61,0x75,0x6c,0x74,//A@...."..Default
+ 0x20,0x50,0x61,0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x20,0x46,0x6f,0x6e,0x74,0x00,// Paragraph Font.
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x00,//..............J.
+ 0x00,0x00,0x02,0x00,0xff,0xff,0xff,0xff,0x02,0x00,0xff,0xff,0xff,0xff,0x01,0x00,//................
+ 0x04,0x20,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x00,0x00,//. ........J.....
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x28,0x00,0x00,0x00,//............(...
+ 0x3a,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x00,0x01,0xc0,0x21,//:...H...J......!
+ 0xf0,0x00,0x00,0x01,0xc0,0x21,0xf0,0x00,0x00,0x01,0xc0,0x21,0xf0,0x00,0x00,0x01,//.....!.....!....
+ 0xc0,0x21,0xf0,0x00,0x00,0x01,0xc0,0x21,0xf0,0x00,0x00,0x03,0x00,0x00,0x4a,0x03,//.!.....!......J.
+ 0x00,0x00,0x02,0x00,0x00,0x03,0x00,0x00,0x4a,0x03,0x00,0x00,0x03,0x00,0x2a,0x00,//........J.....*.
+ 0x0a,0x42,0x69,0x6c,0x6c,0x20,0x4d,0x6f,0x72,0x65,0x6c,0x1c,0x43,0x3a,0x5c,0x75,//.Bill Morel.C:\u
+ 0x73,0x65,0x72,0x73,0x5c,0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x5c,0x74,0x65,0x73,//sers\default\tes
+ 0x74,0x64,0x6f,0x63,0x2e,0x64,0x6f,0x63,0xff,0x40,0x5c,0x5c,0x4d,0x53,0x50,0x52,//tdoc.doc.@\\MSPR
+ 0x49,0x4e,0x54,0x33,0x35,0x5c,0x31,0x2f,0x31,0x30,0x34,0x39,0x20,0x43,0x4f,0x52,//INT35\1/1049 COR
+ 0x50,0x41,0x20,0x31,0x34,0x31,0x42,0x39,0x37,0x00,0x4e,0x65,0x30,0x30,0x3a,0x00,//PA 141B97.Ne00:.
+ 0x77,0x69,0x6e,0x73,0x70,0x6f,0x6f,0x6c,0x00,0x48,0x50,0x20,0x4c,0x61,0x73,0x65,//winspool.HP Lase
+ 0x72,0x4a,0x65,0x74,0x20,0x49,0x49,0x49,0x53,0x69,0x20,0x50,0x6f,0x73,0x74,0x53,//rJet IIISi PostS
+ 0x63,0x72,0x69,0x70,0x74,0x20,0x76,0x35,0x32,0x2e,0x33,0x00,0x5c,0x5c,0x4d,0x53,//cript v52.3.\\MS
+ 0x50,0x52,0x49,0x4e,0x54,0x33,0x35,0x5c,0x31,0x2f,0x31,0x30,0x34,0x39,0x20,0x43,//PRINT35\1/1049 C
+ 0x4f,0x52,0x50,0x41,0x20,0x31,0x34,0x31,0x42,0x39,0x37,0x00,0x20,0x03,0x50,0x03,//ORPA 141B97. .P.
+ 0x7c,0x00,0x70,0x00,0x13,0xdd,0x01,0x00,0x01,0x00,0x01,0x00,0xea,0x0a,0x6f,0x08,//|.p...........o.
+ 0x64,0x00,0x01,0x00,0x0f,0x00,0x2c,0x01,0x01,0x00,0x02,0x00,0x00,0x00,0x03,0x00,//d.....,.........
+ 0x00,0x00,0x4c,0x65,0x74,0x74,0x65,0x72,0x00,0x00,0x01,0x00,0xea,0x0a,0x6f,0x08,//..Letter......o.
+ 0x64,0x00,0x01,0x00,0x0f,0x00,0x2c,0x01,0x01,0x00,0x02,0x00,0x00,0x00,0x03,0x00,//d.....,.........
+ 0x00,0x00,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//..L.............
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x52,0x49,0x56,0x20,0x00,0x00,0x00,//........PRIV ...
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x18,0x00,0x00,0x00,0x00,0x00,0x20,0x4e,0x20,0x4e,0x20,0x4e,0x00,0x00,0x10,0x27,//...... N N N...'
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5c,0x5c,0x4d,0x53,0x50,0x52,0x49,0x4e,//........\\MSPRIN
+ 0x54,0x33,0x35,0x5c,0x31,0x2f,0x31,0x30,0x34,0x39,0x20,0x43,0x4f,0x52,0x50,0x41,//T35\1/1049 CORPA
+ 0x20,0x31,0x34,0x31,0x42,0x39,0x37,0x00,0x20,0x03,0x50,0x03,0x7c,0x00,0x70,0x00,// 141B97. .P.|.p.
+ 0x13,0xdd,0x01,0x00,0x01,0x00,0x01,0x00,0xea,0x0a,0x6f,0x08,0x64,0x00,0x01,0x00,//..........o.d...
+ 0x0f,0x00,0x2c,0x01,0x01,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x4c,0x65,//..,...........Le
+ 0x74,0x74,0x65,0x72,0x00,0x00,0x01,0x00,0xea,0x0a,0x6f,0x08,0x64,0x00,0x01,0x00,//tter......o.d...
+ 0x0f,0x00,0x2c,0x01,0x01,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x4c,0x00,//..,...........L.
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x50,0x52,0x49,0x56,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//....PRIV .......
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//................
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,//................
+ 0x00,0x00,0x20,0x4e,0x20,0x4e,0x20,0x4e,0x00,0x00,0x10,0x27,0x00,0x00,0x00,0x00,//.. N N N...'....
+ 0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x00,0x48,0x00,0x00,0x00,0x48,0x00,0x00,0x00,//........H...H...
+ 0x08,0x00,0x01,0x00,0x01,0x00,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x00,//......H.........
+ 0x00,0x00,0x02,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x17,//...@............
+ 0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x49,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x21,//...H...I...J...!
+ 0x00,0x09,0x03,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x20,//.......!.......
+ 0x00,0x19,0x03,0x00,0x00,0x00,0x00,0x20,0x00,0x07,0x03,0x00,0x00,0x00,0x00,0x20,//....... .......
+ 0x00,0x08,0x03,0x00,0x00,0x00,0x00,0x31,0x00,0x15,0x16,0x90,0x01,0x00,0x00,0x54,//.......1.......T
+ 0x69,0x6d,0x65,0x73,0x20,0x4e,0x65,0x77,0x20,0x52,0x6f,0x6d,0x61,0x6e,0x00,0x0c,//imes New Roman..
+ 0x16,0x90,0x01,0x02,0x00,0x53,0x79,0x6d,0x62,0x6f,0x6c,0x00,0x0b,0x26,0x90,0x01,//.....Symbol..&..
+ 0x00,0x00,0x41,0x72,0x69,0x61,0x6c,0x00,0x22,0x00,0x04,0x00,0x31,0x08,0x8a,0x18,//..Arial."...1...
+ 0x00,0x00,0xd0,0x02,0x00,0x00,0x68,0x01,0x00,0x00,0x00,0x00,0x40,0x34,0xf4,0x85,//......h.....@4..
+ 0x05,0x3b,0xf4,0xa5,0x04,0x3b,0xf4,0xa5,0x03,0x00,0x03,0x00,0x00,0x00,0x07,0x00,//.;...;..........
+ 0x00,0x00,0x41,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x83,0x10,//..A.............
+ 0x05,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x01,0x00,0x04,0x00,//........A.......
+ 0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x03,0x00,0x00,0x00,0x00,//..........t.....
+ 0x95,0x00,0x00,0x00,0x16,0x54,0x69,0x74,0x6c,0x65,0x20,0x6f,0x66,0x20,0x74,0x68,//.....Title of th
+ 0x65,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x18,0x53,0x75,0x62,0x6a,//e document..Subj
+ 0x65,0x63,0x74,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x64,0x6f,0x63,0x75,0x6d,//ect of the docum
+ 0x65,0x6e,0x74,0x2e,0x19,0x4b,0x65,0x79,0x77,0x6f,0x72,0x64,0x73,0x20,0x6f,0x66,//ent..Keywords of
+ 0x20,0x74,0x68,0x65,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x19,0x43,// the document..C
+ 0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x64,//omments of the d
+ 0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x17,0x41,0x75,0x74,0x68,0x6f,0x72,0x20,//ocument..Author
+ 0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,//of the document.
+ 0x0a,0x42,0x69,0x6c,0x6c,0x20,0x4d,0x6f,0x72,0x65,0x6c,0x00,0x00,0x00,0x00,0x00,//.Bill Morel.....
+ 0x00,0x00,0x00,0x00,0x00,0xd0,0xcf,0x11,0xe0,0xa1,0xb1,0x1a,0xe1,0x00,0x00,0x00,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,//................
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff //................
+};
+
+unsigned int g_cbTestDoc = sizeof(g_achTestDoc)/sizeof(g_achTestDoc[0]);
+
diff --git a/private/ole32/stg/props/utest/testdoc.doc b/private/ole32/stg/props/utest/testdoc.doc
new file mode 100644
index 000000000..9935e8b6d
--- /dev/null
+++ b/private/ole32/stg/props/utest/testdoc.doc
Binary files differ
diff --git a/private/ole32/stg/props/utils.cxx b/private/ole32/stg/props/utils.cxx
new file mode 100644
index 000000000..68a415d62
--- /dev/null
+++ b/private/ole32/stg/props/utils.cxx
@@ -0,0 +1,1191 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: utils.cxx
+//
+// Contents: Utility classes/functions for property implementation.
+//
+// Classes: CPropSetName -- wraps buffer and conversion of fmtids
+// CStackBuffer -- utility class that allows a small number
+// of items be on stack, but more be on heap.
+//
+// Functions: PropVariantClear
+// FreePropVariantArray
+// AllocAndCopy
+// PropVariantCopy
+// PropSysAllocString
+// PropSysFreeString
+//
+// History: 1-Mar-95 BillMo Created.
+// 22-Feb-96 MikeHill Removed an over-active assert.
+// 22-May-96 MikeHill Handle "unmappable character" in
+// NtStatusToScode.
+// 12-Jun-96 MikeHill - Added PropSysAllocString and PropSysFreeString.
+// - Added VT_I1 support (under ifdef)
+// - Fix PropVarCopy where the input VT_CF
+// has a zero size but a non-NULL pClipData.
+// 29-Jul-96 MikeHill - PropSet names: WCHAR => OLECHAR
+// - Bug in PropVarCopy of 0-length VT_BLOB
+// - Support VT_BSTR_BLOB types (used in IProp.dll)
+//
+// Notes:
+//
+// Codework:
+//
+//--------------------------------------------------------------------------
+
+#include <pch.cxx>
+#include <privoa.h> // Private OleAut32 wrappers
+
+#ifdef _MAC_NODOC
+ASSERTDATA // File-specific data for FnAssert
+#endif
+
+//+-------------------------------------------------------------------
+//
+// Member: CPropSetName::CPropSetName
+//
+// Synopsis: Initialize internal buffer with converted FMTID
+//
+// Arguments: [rfmtid] -- FMTID to convert
+//
+//--------------------------------------------------------------------
+
+CPropSetName::CPropSetName(REFFMTID rfmtid)
+{
+ RtlGuidToPropertySetName(&rfmtid, _oszName);
+}
+
+//+-------------------------------------------------------------------
+//
+// Member: CStackBuffer::Init
+//
+// Synopsis: Determine whether the class derived from this one
+// needs to have additional buffer allocated on the
+// heap and allocate it if neccessary. Otherwise, if
+// there is space, use the internal buffer in the
+// derived class.
+//
+// Arguments: [cElements] -- the number of elements required.
+//
+// Returns: S_OK if buffer available
+// STG_E_INSUFFICIENTMEMORY if stack buffer was not
+// big enough AND heap allocation failed.
+//
+// Notes: To be called directly by client after the derived
+// classes constructor initialized CStackBuffer.
+//
+//--------------------------------------------------------------------
+
+HRESULT CStackBuffer::Init(ULONG cElements)
+{
+ if (cElements > _cStackElements)
+ {
+ _pbHeapBuf = new BYTE[cElements * _cbElementSize];
+ if (_pbHeapBuf == NULL)
+ {
+ return(STG_E_INSUFFICIENTMEMORY);
+ }
+ }
+ return(S_OK);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: PropVariantClear
+//
+// Synopsis: Deallocates the members of the PROPVARIANT that require
+// deallocation.
+//
+// Arguments: [pvarg] - variant to clear
+//
+// Returns: S_OK if successful,
+// STG_E_INVALIDPARAMETER if any part of the variant has
+// an unknown vt type. (In this case, ALL the elements
+// that can be freed, will be freed.)
+//
+// Modifies: [pvarg] - the variant is left with vt = VT_EMPTY
+//
+//--------------------------------------------------------------------------
+
+STDAPI PropVariantClear(PROPVARIANT *pvarg)
+{
+
+ ULONG l;
+ HRESULT hr = S_OK;
+
+ // Is there really anything to clear?
+ if (pvarg == NULL)
+ return(hr);
+
+ // Validate the input
+ VDATEPTROUT( pvarg, PROPVARIANT );
+
+ switch (pvarg->vt)
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ case VT_ILLEGAL:
+
+#ifdef PROPVAR_VT_I1
+ case VT_I1:
+#endif
+ case VT_UI1:
+ case VT_I2:
+ case VT_UI2:
+ case VT_I4:
+ case VT_UI4:
+ case VT_I8:
+ case VT_UI8:
+ case VT_R4:
+ case VT_R8:
+ case VT_CY:
+ case VT_DATE:
+ break;
+
+ case VT_BSTR:
+ if (pvarg->bstrVal != NULL)
+ PrivSysFreeString( pvarg->bstrVal );
+ break;
+
+ case VT_BSTR_BLOB:
+ if (pvarg->bstrblobVal.pData != NULL)
+ CoTaskMemFree( pvarg->bstrblobVal.pData );
+ break;
+ case VT_BOOL:
+ case VT_ERROR:
+ case VT_FILETIME:
+ break;
+
+ case VT_LPSTR:
+ case VT_LPWSTR:
+ case VT_CLSID:
+ DfpAssert((void**)&pvarg->pszVal == (void**)&pvarg->pwszVal);
+ DfpAssert((void**)&pvarg->pszVal == (void**)&pvarg->puuid);
+ CoTaskMemFree(pvarg->pszVal); // ptr at 0
+ break;
+
+ case VT_CF:
+ if (pvarg->pclipdata != NULL)
+ {
+ CoTaskMemFree(pvarg->pclipdata->pClipData); // ptr at 8
+ CoTaskMemFree(pvarg->pclipdata);
+ }
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+ CoTaskMemFree(pvarg->blob.pBlobData); //ptr at 4
+ break;
+
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ if (pvarg->pStream != NULL)
+ pvarg->pStream->Release();
+ break;
+
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ if (pvarg->pStorage != NULL)
+ pvarg->pStorage->Release();
+ break;
+
+#ifdef PROPVAR_VT_I1
+ case (VT_VECTOR | VT_I1):
+#endif
+ case (VT_VECTOR | VT_UI1):
+ case (VT_VECTOR | VT_I2):
+ case (VT_VECTOR | VT_UI2):
+ case (VT_VECTOR | VT_I4):
+ case (VT_VECTOR | VT_UI4):
+ case (VT_VECTOR | VT_I8):
+ case (VT_VECTOR | VT_UI8):
+ case (VT_VECTOR | VT_R4):
+ case (VT_VECTOR | VT_R8):
+ case (VT_VECTOR | VT_CY):
+ case (VT_VECTOR | VT_DATE):
+
+FreeArray:
+ DfpAssert((void**)&pvarg->caub.pElems == (void**)&pvarg->cai.pElems);
+ CoTaskMemFree(pvarg->caub.pElems);
+ break;
+
+ case (VT_VECTOR | VT_BSTR):
+ if (pvarg->cabstr.pElems != NULL)
+ {
+ for (l=0; l< pvarg->cabstr.cElems; l++)
+ {
+ if (pvarg->cabstr.pElems[l] != NULL)
+ {
+ PrivSysFreeString( pvarg->cabstr.pElems[l] );
+ }
+ }
+ }
+ goto FreeArray;
+
+ case (VT_VECTOR | VT_BSTR_BLOB):
+ if (pvarg->cabstrblob.pElems != NULL)
+ {
+ for (l=0; l< pvarg->cabstrblob.cElems; l++)
+ {
+ if (pvarg->cabstrblob.pElems[l].pData != NULL)
+ {
+ CoTaskMemFree( pvarg->cabstrblob.pElems[l].pData );
+ }
+ }
+ }
+ goto FreeArray;
+
+ case (VT_VECTOR | VT_BOOL):
+ case (VT_VECTOR | VT_ERROR):
+ goto FreeArray;
+
+ case (VT_VECTOR | VT_LPSTR):
+ case (VT_VECTOR | VT_LPWSTR):
+ if (pvarg->calpstr.pElems != NULL)
+ for (l=0; l< pvarg->calpstr.cElems; l++)
+ {
+ CoTaskMemFree(pvarg->calpstr.pElems[l]);
+ }
+ goto FreeArray;
+
+ case (VT_VECTOR | VT_FILETIME):
+ case (VT_VECTOR | VT_CLSID):
+ goto FreeArray;
+
+ case (VT_VECTOR | VT_CF):
+ if (pvarg->caclipdata.pElems != NULL)
+ for (l=0; l< pvarg->caclipdata.cElems; l++)
+ {
+ CoTaskMemFree(pvarg->caclipdata.pElems[l].pClipData);
+ }
+ goto FreeArray;
+
+ case (VT_VECTOR | VT_VARIANT):
+ if (pvarg->capropvar.pElems != NULL)
+ hr = FreePropVariantArray(pvarg->capropvar.cElems, pvarg->capropvar.pElems);
+ goto FreeArray;
+
+ default:
+ hr = STG_E_INVALIDPARAMETER;
+ break;
+ }
+
+ // We have all of the important information about the variant, so
+ // let's clear it out.
+ //
+ PropVariantInit(pvarg);
+
+ return (hr);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: FreePropVariantArray, public
+//
+// Synopsis: Frees a value array returned from ReadMultiple
+//
+// Arguments: [cval] - Number of elements
+// [rgvar] - Array
+//
+// Returns: S_OK if all types recognised and all freeable items were freed.
+// STG_E_INVALID_PARAMETER if one or more types were not
+// recognised but all items are freed too.
+//
+// Notes: Even if a vt-type is not understood, all the ones that are
+// understood are freed. The error code will indicate
+// if *any* of the members were illegal types.
+//
+//----------------------------------------------------------------------------
+
+STDAPI FreePropVariantArray (
+ ULONG cVariants,
+ PROPVARIANT *rgvars)
+{
+ HRESULT hr = S_OK;
+
+ VDATESIZEPTROUT_LABEL(rgvars, cVariants * sizeof(PROPVARIANT),
+ Exit, hr );
+
+ if (rgvars != NULL)
+ for ( ULONG I=0; I < cVariants; I++ )
+ if (STG_E_INVALIDPARAMETER == PropVariantClear ( rgvars + I ))
+ hr = STG_E_INVALIDPARAMETER;
+
+Exit:
+
+ return hr;
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: AllocAndCopy
+//
+// Synopsis: Allocates enough memory to copy the passed data into and
+// then copies the data into the new buffer.
+//
+// Arguments: [cb] -- number of bytes of data to allocate and copy
+// [pvData] -- the source of the data to copy
+// [phr] -- optional pointer to an HRESULT set to
+// STG_E_INSUFFICIENTMEMORY if memory could
+// not be allocated.
+//
+//
+// Returns: NULL if no memory could be allocated,
+// Otherwise, pointer to allocated and copied data.
+//
+//--------------------------------------------------------------------
+
+void * AllocAndCopy(ULONG cb, void * pvData, HRESULT *phr = NULL)
+{
+ void * pvNew = CoTaskMemAlloc(cb);
+ if (pvNew != NULL)
+ {
+ memcpy(pvNew, pvData, cb);
+ }
+ else
+ {
+ if (phr != NULL)
+ {
+ *phr = STG_E_INSUFFICIENTMEMORY;
+ }
+ }
+ return(pvNew);
+}
+
+//+-------------------------------------------------------------------
+//
+// Function: PropSysAllocString
+// PropSysFreeString
+//
+// Synopsis: Wrappers for OleAut32 routines.
+//
+// Notes: These PropSys* functions simply forward the call to
+// the PrivSys* routines in OLE32. Those functions
+// will load OleAut32 if necessary, and forward the call.
+//
+// The PrivSys* wrapper functions are provided in order to
+// delay the OleAut32 load. The PropSys* functions below
+// are provided as a mechanism to allow the NTDLL PropSet
+// functions to call the PrivSys* function pointers.
+//
+// The PropSys* functions below are part of the
+// UNICODECALLOUTS structure used by NTDLL.
+// These functions should go away when the property set
+// code is moved from NTDLL to OLE32.
+//
+//--------------------------------------------------------------------
+
+STDAPI_(BSTR)
+PropSysAllocString(OLECHAR FAR* pwsz)
+{
+ return( PrivSysAllocString( pwsz ));
+}
+
+STDAPI_(VOID)
+PropSysFreeString(BSTR bstr)
+{
+ PrivSysFreeString( bstr );
+ return;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CRGTypeSizes (instantiated in g_TypeSizes)
+//
+// Synopsis: This class maintains a table with an entry for
+// each of the VT types. Each entry contains
+// flags and a byte-size for the type (each entry is
+// only a byte).
+//
+// This was implemented as a class so that we could use
+// it like an array (using an overloaded subscript operator),
+// indexed by the VT. An actual array would require
+// 4K entries
+//
+// Internally, this class keeps two tables, each containing
+// a range of VTs (the VTs range from 0 to 31, and 64 to 72).
+// Other values are treated as a special-case.
+//
+//----------------------------------------------------------------------------
+
+// -----------------------
+// Flags for table entries
+// -----------------------
+
+#define BIT_VECTNOALLOC 0x80 // the VT_VECTOR with this type does not
+ // use heap allocation
+
+#define BIT_SIMPNOALLOC 0x40 // the non VT_VECTOR with this type does not
+ // use heap allocation
+
+#define BIT_INVALID 0x20 // marks an invalid type
+
+#define BIT_SIZEMASK 0x1F // mask for size of underlying type
+
+// Dimensions of the internal tables
+
+#define MIN_TYPE_SIZES_A VT_EMPTY // First contiguous range of VTs
+#define MAX_TYPE_SIZES_A VT_LPWSTR
+
+#define MIN_TYPE_SIZES_B VT_FILETIME // Second continuous range of VTs
+#define MAX_TYPE_SIZES_B VT_CLSID
+
+// ----------------
+// class CRTTypeSizes
+// ----------------
+
+class CRGTypeSizes
+{
+
+public:
+
+ // Subscript Operator
+ //
+ // This is the only method on this class. It is used to
+ // read an entry in the table.
+
+ unsigned char operator[]( int nSubscript )
+ {
+ // Is this in the first table?
+ if( MIN_TYPE_SIZES_A <= nSubscript && nSubscript <= MAX_TYPE_SIZES_A )
+ {
+ return( m_ucTypeSizesA[ nSubscript ] );
+ }
+
+ // Or, is it in the second table?
+ else if( MIN_TYPE_SIZES_B<= nSubscript && nSubscript <= MAX_TYPE_SIZES_B )
+ {
+ return( m_ucTypeSizesB[ nSubscript - MIN_TYPE_SIZES_B ] );
+ }
+
+ // Or, is it a special-case value (not in either table)?
+ else
+ if( VT_BSTR_BLOB == nSubscript )
+ {
+ return( sizeof(BSTRBLOB) );
+ }
+
+ // Otherwise, the VT is invalid.
+ return( BIT_INVALID );
+ }
+
+
+private:
+
+ // There are two ranges of supported VTs, so we have
+ // one table for each.
+
+ static const unsigned char m_ucTypeSizesA[];
+ static const unsigned char m_ucTypeSizesB[];
+};
+
+// --------------------------
+// Instantiate the CRGTypeSizes
+// --------------------------
+
+CRGTypeSizes g_TypeSizes;
+
+// ----------------------------
+// Define the CTypeSizes tables
+// ----------------------------
+
+const unsigned char CRGTypeSizes::m_ucTypeSizesA[] =
+ { BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_EMPTY= 0,
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_NULL = 1,
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 2, //VT_I2 = 2,
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 4, //VT_I4 = 3,
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 4, //VT_R4 = 4,
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 8, //VT_R8 = 5,
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(CY), //VT_CY = 6,
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(DATE), //VT_DATE = 7,
+ sizeof(BSTR), //VT_BSTR = 8,
+ BIT_INVALID | 0, //VT_DISPATCH = 9,
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(SCODE), //VT_ERROR = 10,
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(VARIANT_BOOL), //VT_BOOL = 11,
+ sizeof(PROPVARIANT), //VT_VARIANT = 12,
+ BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_UNKNOWN = 13,
+ BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, // 14
+ BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, // 15
+ #ifdef PROPVAR_VT_I1
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 1, //VT_I1 = 16,
+ #else
+ BIT_INVALID /*BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 1,*/ | 0, //VT_I1 = 16,
+ #endif
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 1, //VT_UI1 = 17,
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 2, //VT_UI2 = 18,
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 4, //VT_UI4 = 19,
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 8, //VT_I8 = 20,
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 8, //VT_UI8 = 21,
+ BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_INT = 22,
+ BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_UINT = 23,
+ BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_VOID = 24,
+ BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_HRESULT = 25,
+ BIT_INVALID | 0, //VT_PTR = 26,
+ BIT_INVALID | 0, //VT_SAFEARRAY = 27,
+ BIT_INVALID | 0, //VT_CARRAY = 28,
+ BIT_INVALID | 0, //VT_USERDEFINED = 29,
+ sizeof(LPSTR), //VT_LPSTR = 30,
+ sizeof(LPWSTR) //VT_LPWSTR = 31,
+ };
+
+const unsigned char CRGTypeSizes::m_ucTypeSizesB[] =
+ {
+ // BUGBUG vectors of types marked ** are tbd
+ BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(FILETIME), //VT_FILETIME = 64,
+ 0, //**VT_BLOB = 65,
+ 0, //**VT_STREAM = 66,
+ 0, //**VT_STORAGE = 67,
+ 0, //**VT_STREAMED_OBJECT = 68,
+ 0, //**VT_STORED_OBJECT = 69,
+ 0, //**VT_BLOB_OBJECT = 70,
+ sizeof(CLIPDATA), //VT_CF = 71,
+ BIT_VECTNOALLOC | sizeof(CLSID) //VT_CLSID = 72
+ };
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: PropVariantCopy, public
+//
+// Synopsis: Copies a PROPVARIANT
+//
+// Arguments: [pDest] -- the destination PROPVARIANT
+// [pvarg] - the source PROPVARIANT
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+STDAPI PropVariantCopy ( PROPVARIANT * pDest, const PROPVARIANT * pvarg )
+{
+ HRESULT hr = S_OK;
+ register unsigned char TypeInfo;
+ register int iBaseType;
+ BOOL fInputValidated = FALSE;
+
+ // ----------
+ // Initialize
+ // ----------
+
+ // Validate the inputs
+
+ VDATEREADPTRIN_LABEL( pvarg, PROPVARIANT, errRet, hr );
+ VDATEPTROUT_LABEL( pDest, PROPVARIANT, errRet, hr );
+ fInputValidated = TRUE;
+
+ // Handle the simple types quickly.
+
+ iBaseType = pvarg->vt & ~VT_VECTOR;
+ TypeInfo = g_TypeSizes[ iBaseType ];
+
+ if( (TypeInfo & BIT_INVALID) != 0 )
+ {
+ hr = STG_E_INVALIDPARAMETER;
+ goto errRet;
+ }
+
+ // Duplicate the source propvar to the destination. For types with
+ // no external buffer (e.g. an I4), this will be sufficient. For
+ // types with an external buffer, we'll now have both propvars
+ // pointing to the same buffer. So we'll have to re-allocate
+ // for the destination propvar and copy the data into it.
+
+ *pDest = *pvarg;
+
+ // -----------------------
+ // Handle non-vector types
+ // -----------------------
+
+ if ((pvarg->vt & VT_VECTOR) == 0)
+ {
+
+ // Is this a type which requires an allocation (otherwise there's
+ // nothing to do)?
+
+ if ((TypeInfo & BIT_SIMPNOALLOC) == 0)
+ {
+ // Yes - an allocation is required.
+
+ // Keep a copy of the allocated buffer, so that at the end of
+ // this switch, we can distiguish the out-of-memory condition from
+ // the no-alloc-required condition.
+
+ void * pvAllocated = (void*)-1;
+
+ switch (pvarg->vt)
+ {
+ case VT_BSTR:
+ if( NULL != pvarg->bstrVal )
+ pvAllocated = pDest->bstrVal = PrivSysAllocString( pvarg->bstrVal );
+ break;
+
+ case VT_BSTR_BLOB:
+ if( NULL != pvarg->bstrblobVal.pData )
+ pvAllocated = pDest->bstrblobVal.pData = (BYTE*)
+ AllocAndCopy(pDest->bstrblobVal.cbSize, pvarg->bstrblobVal.pData);
+ break;
+
+ case VT_LPSTR:
+ if (pvarg->pszVal != NULL)
+ pvAllocated = pDest->pszVal = (CHAR *)
+ AllocAndCopy(strlen(pvarg->pszVal)+1, pvarg->pszVal);
+ break;
+ case VT_LPWSTR:
+ if (pvarg->pwszVal != NULL)
+ {
+ ULONG cbString = (Prop_wcslen(pvarg->pwszVal)+1) * sizeof(WCHAR);
+ pvAllocated = pDest->pwszVal = (WCHAR *)
+ AllocAndCopy(cbString, pvarg->pwszVal);
+ }
+ break;
+ case VT_CLSID:
+ if (pvarg->puuid != NULL)
+ pvAllocated = pDest->puuid = (GUID *)
+ AllocAndCopy(sizeof(*(pvarg->puuid)), pvarg->puuid);
+ break;
+
+ case VT_CF:
+ // first check if CLIPDATA is present
+ if (pvarg->pclipdata != NULL)
+ {
+ // yes ... copy the clip data structure
+
+ pvAllocated = pDest->pclipdata = (CLIPDATA*)AllocAndCopy(
+ sizeof(*(pvarg->pclipdata)), pvarg->pclipdata);
+
+ // did we allocate the CLIPDATA ?
+ if (pvAllocated != NULL)
+ {
+ // yes ... initialize the destination.
+ pDest->pclipdata->pClipData = NULL;
+
+ // Is the input valid?
+ if (NULL == pvarg->pclipdata->pClipData
+ &&
+ 0 != CBPCLIPDATA(*pvarg->pclipdata))
+ {
+ // no ... the input is not valid
+ hr = STG_E_INVALIDPARAMETER;
+ CoTaskMemFree( pDest->pclipdata );
+ pvAllocated = pDest->pclipdata = NULL;
+ break;
+ }
+
+ // Copy the actual clip data. Note that if the source
+ // is non-NULL, we copy it, even if the length is 0.
+
+ if( NULL != pvarg->pclipdata->pClipData )
+ {
+ pvAllocated = pDest->pclipdata->pClipData =
+ (BYTE*)AllocAndCopy(CBPCLIPDATA(*pvarg->pclipdata),
+ pvarg->pclipdata->pClipData);
+ }
+
+ } // if (pvAllocated != NULL)
+ } // if (pvarg->pclipdata != NULL)
+ break;
+
+ case VT_BLOB:
+ case VT_BLOB_OBJECT:
+
+ // Is the input valid?
+ if (NULL == pvarg->blob.pBlobData
+ &&
+ 0 != pvarg->blob.cbSize)
+ {
+ // no ... the input is not valid
+ hr = STG_E_INVALIDPARAMETER;
+ goto errRet;
+ }
+
+ // Copy the actual blob. Note that if the source
+ // is non-NULL, we copy it, even if the length is 0.
+
+ if( NULL != pvarg->blob.pBlobData )
+ {
+ pvAllocated = pDest->blob.pBlobData =
+ (BYTE*)AllocAndCopy(pvarg->blob.cbSize,
+ pvarg->blob.pBlobData);
+ }
+
+
+ break;
+
+ case VT_STREAM:
+ case VT_STREAMED_OBJECT:
+ if (pDest->pStream != NULL)
+ pDest->pStream->AddRef();
+ break;
+
+ case VT_STORAGE:
+ case VT_STORED_OBJECT:
+ if (pDest->pStorage != NULL)
+ pDest->pStorage->AddRef();
+ break;
+
+ case VT_VARIANT:
+ // drop through - this merely documents that VT_VARIANT has been thought of.
+ // VT_VARIANT is only supported as part of a vector.
+
+ default:
+ hr = STG_E_INVALIDPARAMETER;
+ goto errRet;
+
+ } // switch (pvarg->vt)
+
+ // If there was an error, we're done.
+ if( FAILED(hr) )
+ goto errRet;
+
+ // pvAllocated was initialized to -1, so if it's NULL now,
+ // there was an alloc failure.
+
+ if (pvAllocated == NULL)
+ {
+ hr = STG_E_INSUFFICIENTMEMORY;
+ goto errRet;
+ }
+
+ } // if ((TypeInfo & BIT_SIMPNOALLOC) == 0)
+ } // if ((pvarg->vt & VT_VECTOR) == 0)
+
+ // -------------------
+ // Handle vector types
+ // -------------------
+
+ else
+ {
+ // What's the byte-size of this type.
+
+ ULONG cbType = TypeInfo & BIT_SIZEMASK;
+ if (cbType == 0)
+ {
+ hr = STG_E_INVALIDPARAMETER;
+ goto errRet;
+ }
+
+ // handle the vector types
+
+ // this depends on the pointer and count being in the same place in
+ // each of CAUI1 CAI2 etc
+
+ // allocate the array for pElems
+ if (pvarg->caub.pElems == NULL || pvarg->caub.cElems == 0)
+ {
+ DfpAssert( hr == S_OK );
+ goto errRet; // not really an error
+ }
+
+ // Allocate the pElems array (the size of which is
+ // type-dependent), and copy the source into it.
+
+ void *pvAllocated = pDest->caub.pElems = (BYTE *)
+ AllocAndCopy(cbType * pvarg->caub.cElems, pvarg->caub.pElems);
+
+ if (pvAllocated == NULL)
+ {
+ hr = STG_E_INSUFFICIENTMEMORY;
+ goto errRet;
+ }
+
+ // If this type doesn't require secondary allocation (e.g.
+ // a VT_VECTOR | VT_I4), then we're done.
+
+ if ((TypeInfo & BIT_VECTNOALLOC) != 0)
+ {
+ // the vector needs no further allocation
+ DfpAssert( hr == S_OK );
+ goto errRet;
+ }
+
+ ULONG l;
+
+ // vector types that require allocation ...
+ // we first zero out the pointers so that we can use PropVariantClear
+ // to clean up in the error case
+
+ switch (pvarg->vt)
+ {
+ case (VT_VECTOR | VT_BSTR):
+ // initialize for error case
+ for (l=0; l< pvarg->cabstr.cElems; l++)
+ {
+ pDest->cabstr.pElems[l] = NULL;
+ }
+ break;
+
+ case (VT_VECTOR | VT_BSTR_BLOB):
+ // initialize for error case
+ for (l=0; l< pvarg->cabstrblob.cElems; l++)
+ {
+ memset( &pDest->cabstrblob.pElems[l], 0, sizeof(BSTRBLOB) );
+ }
+ break;
+
+ case (VT_VECTOR | VT_LPSTR):
+ case (VT_VECTOR | VT_LPWSTR):
+ // initialize for error case
+ for (l=0; l< pvarg->calpstr.cElems; l++)
+ {
+ pDest->calpstr.pElems[l] = NULL;
+ }
+ break;
+
+ case (VT_VECTOR | VT_CF):
+ // initialize for error case
+ for (l=0; l< pvarg->caclipdata.cElems; l++)
+ {
+ pDest->caclipdata.pElems[l].pClipData = NULL;
+ }
+ break;
+
+ case (VT_VECTOR | VT_VARIANT):
+ // initialize for error case
+ for (l=0; l< pvarg->capropvar.cElems; l++)
+ {
+ pDest->capropvar.pElems[l].vt = VT_ILLEGAL;
+ }
+ break;
+
+ default:
+ DfpAssert(!"Internal error: Unexpected type in PropVariantCopy");
+ CoTaskMemFree(pvAllocated);
+ hr = STG_E_INVALIDPARAMETER;
+ goto errRet;
+ }
+
+ // This is a vector type which requires a secondary alloc.
+
+ switch (pvarg->vt)
+ {
+ case (VT_VECTOR | VT_BSTR):
+ for (l=0; l< pvarg->cabstr.cElems; l++)
+ {
+ if (pvarg->cabstr.pElems[l] != NULL)
+ {
+ pDest->cabstr.pElems[l] = PrivSysAllocString( pvarg->cabstr.pElems[l]);
+ if (pDest->cabstr.pElems[l] == NULL)
+ {
+ hr = STG_E_INSUFFICIENTMEMORY;
+ break;
+ }
+ }
+ }
+ break;
+
+ case (VT_VECTOR | VT_BSTR_BLOB):
+ for (l=0; l< pvarg->cabstrblob.cElems; l++)
+ {
+ if (pvarg->cabstrblob.pElems[l].pData != NULL)
+ {
+ pDest->cabstrblob.pElems[l].cbSize
+ = pvarg->cabstrblob.pElems[l].cbSize;
+
+ pDest->cabstrblob.pElems[l].pData = (BYTE*)AllocAndCopy(
+ pvarg->cabstrblob.pElems[l].cbSize,
+ pvarg->cabstrblob.pElems[l].pData,
+ &hr );
+
+ if (hr != S_OK)
+ break;
+ }
+ }
+ break;
+
+ case (VT_VECTOR | VT_LPWSTR):
+ for (l=0; l< pvarg->calpwstr.cElems; l++)
+ {
+ if (pvarg->calpwstr.pElems[l] != NULL)
+ {
+
+ pDest->calpwstr.pElems[l] = (LPWSTR)AllocAndCopy(
+ sizeof(WCHAR)*(Prop_wcslen(pvarg->calpwstr.pElems[l])+1),
+ pvarg->calpwstr.pElems[l],
+ &hr);
+
+ if (hr != S_OK)
+ break;
+ }
+ }
+ break;
+
+ case (VT_VECTOR | VT_LPSTR):
+ for (l=0; l< pvarg->calpstr.cElems; l++)
+ {
+ if (pvarg->calpstr.pElems[l] != NULL)
+ {
+ pDest->calpstr.pElems[l] = (LPSTR)AllocAndCopy(
+ strlen(pvarg->calpstr.pElems[l])+1,
+ pvarg->calpstr.pElems[l],
+ &hr);
+
+ if (hr != S_OK)
+ break;
+ }
+ }
+ break;
+
+ case (VT_VECTOR | VT_CF):
+ for (l=0; l< pvarg->caclipdata.cElems; l++)
+ {
+ // Is the input valid?
+ if (NULL == pvarg->caclipdata.pElems[l].pClipData
+ &&
+ 0 != CBPCLIPDATA(pvarg->caclipdata.pElems[l] ))
+ {
+ hr = STG_E_INVALIDPARAMETER;
+ break;
+ }
+
+ // Is there data to copy?
+ if (NULL != pvarg->caclipdata.pElems[l].pClipData)
+ {
+ pDest->caclipdata.pElems[l].pClipData = (BYTE*)AllocAndCopy(
+ CBPCLIPDATA(pvarg->caclipdata.pElems[l]),
+ pvarg->caclipdata.pElems[l].pClipData,
+ &hr);
+
+ if (hr != S_OK)
+ break;
+ }
+ }
+ break;
+
+ case (VT_VECTOR | VT_VARIANT):
+ for (l=0; l< pvarg->capropvar.cElems; l++)
+ {
+ hr = PropVariantCopy(pDest->capropvar.pElems + l,
+ pvarg->capropvar.pElems + l);
+ if (hr != S_OK)
+ {
+ break;
+ }
+ }
+ break;
+
+ default:
+ DfpAssert(!"Internal error: Unexpected type in PropVariantCopy");
+ CoTaskMemFree(pvAllocated);
+ hr = STG_E_INVALIDPARAMETER;
+ goto errRet;
+
+ } // switch (pvarg->vt)
+ } // if ((pvarg->vt & VT_VECTOR) == 0) ... else
+
+ // ----
+ // Exit
+ // ----
+
+errRet:
+
+ // If there was an error, and it wasn't a caller error
+ // (in which case *pDest may not be writable), clear the
+ // destination propvar.
+
+ if (fInputValidated && hr != S_OK && E_INVALIDARG != hr)
+ {
+ // if *pDest == *pvarg, then we didn't alloc anything, and
+ // nothing need be cleared, so we'll just init *pDest.
+ // We can't free it because it may point to pvarg's buffers.
+
+ if( !memcmp( pDest, pvarg, sizeof(PROPVARIANT) ))
+ PropVariantInit( pDest );
+
+ // Otherwise, we must have done some allocations for *pDest,
+ // and must free them.
+
+ else
+ PropVariantClear( pDest );
+
+ }
+
+ return(hr);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: NtStatusToScode, public
+//
+// Synopsis: Attempts to map an NTSTATUS code to an SCODE
+//
+// Arguments: [nts] - NTSTATUS
+//
+// Returns: Appropriate status code
+//
+// History: 29-Jun-93 DrewB Created
+//
+// Notes: Assumes [nts] is an error code
+// This function is by no means exhaustively complete
+//
+//----------------------------------------------------------------------------
+
+SCODE NtStatusToScode(NTSTATUS nts)
+{
+ SCODE sc;
+
+ PropDbg((DEB_ITRACE, "In NtStatusToScode(%lX)\n", nts));
+
+ switch(nts)
+ {
+ case STATUS_INVALID_PARAMETER:
+ case STATUS_INVALID_PARAMETER_MIX:
+ case STATUS_INVALID_PARAMETER_1:
+ case STATUS_INVALID_PARAMETER_2:
+ case STATUS_INVALID_PARAMETER_3:
+ case STATUS_INVALID_PARAMETER_4:
+ case STATUS_INVALID_PARAMETER_5:
+ case STATUS_INVALID_PARAMETER_6:
+ case STATUS_INVALID_PARAMETER_7:
+ case STATUS_INVALID_PARAMETER_8:
+ case STATUS_INVALID_PARAMETER_9:
+ case STATUS_INVALID_PARAMETER_10:
+ case STATUS_INVALID_PARAMETER_11:
+ case STATUS_INVALID_PARAMETER_12:
+ sc = STG_E_INVALIDPARAMETER;
+ break;
+
+ case STATUS_DUPLICATE_NAME:
+ case STATUS_DUPLICATE_OBJECTID:
+ case STATUS_OBJECTID_EXISTS:
+ case STATUS_OBJECT_NAME_COLLISION:
+ sc = STG_E_FILEALREADYEXISTS;
+ break;
+
+ case STATUS_NO_SUCH_DEVICE:
+ case STATUS_NO_SUCH_FILE:
+ case STATUS_OBJECT_NAME_NOT_FOUND:
+ case STATUS_NOT_A_DIRECTORY:
+ case STATUS_FILE_IS_A_DIRECTORY:
+ case STATUS_PROPSET_NOT_FOUND:
+ case STATUS_NOT_FOUND:
+ case STATUS_OBJECT_TYPE_MISMATCH:
+ sc = STG_E_FILENOTFOUND;
+ break;
+
+ case STATUS_OBJECT_NAME_INVALID:
+ case STATUS_OBJECT_PATH_SYNTAX_BAD:
+ case STATUS_OBJECT_PATH_INVALID:
+ case STATUS_NAME_TOO_LONG:
+ sc = STG_E_INVALIDNAME;
+ break;
+
+ case STATUS_ACCESS_DENIED:
+ sc = STG_E_ACCESSDENIED;
+ break;
+
+ case STATUS_NO_MEMORY:
+ case STATUS_INSUFFICIENT_RESOURCES:
+ sc = STG_E_INSUFFICIENTMEMORY;
+ break;
+
+ case STATUS_INVALID_HANDLE:
+ case STATUS_FILE_INVALID:
+ case STATUS_FILE_FORCED_CLOSED:
+ sc = STG_E_INVALIDHANDLE;
+ break;
+
+ case STATUS_INVALID_DEVICE_REQUEST:
+ case STATUS_INVALID_SYSTEM_SERVICE:
+ case STATUS_NOT_IMPLEMENTED:
+ sc = STG_E_INVALIDFUNCTION;
+ break;
+
+ case STATUS_NO_MEDIA_IN_DEVICE:
+ case STATUS_UNRECOGNIZED_MEDIA:
+ case STATUS_DISK_CORRUPT_ERROR:
+ case STATUS_DATA_ERROR:
+ sc = STG_E_WRITEFAULT;
+ break;
+
+ case STATUS_OBJECT_PATH_NOT_FOUND:
+ sc = STG_E_PATHNOTFOUND;
+ break;
+
+ case STATUS_SHARING_VIOLATION:
+ sc = STG_E_SHAREVIOLATION;
+ break;
+
+ case STATUS_FILE_LOCK_CONFLICT:
+ case STATUS_LOCK_NOT_GRANTED:
+ sc = STG_E_LOCKVIOLATION;
+ break;
+
+ case STATUS_DISK_FULL:
+ sc = STG_E_MEDIUMFULL;
+ break;
+
+ case STATUS_ACCESS_VIOLATION:
+ case STATUS_INVALID_USER_BUFFER:
+ sc = STG_E_INVALIDPOINTER;
+ break;
+
+ case STATUS_TOO_MANY_OPENED_FILES:
+ sc = STG_E_TOOMANYOPENFILES;
+ break;
+
+ case STATUS_DIRECTORY_NOT_EMPTY:
+ sc = HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY);
+ break;
+
+ case STATUS_DELETE_PENDING:
+ sc = STG_E_REVERTED;
+ break;
+
+ case STATUS_INTERNAL_DB_CORRUPTION:
+ sc = STG_E_INVALIDHEADER;
+ break;
+
+ case STATUS_UNSUCCESSFUL:
+ sc = E_FAIL;
+ break;
+
+ case STATUS_UNMAPPABLE_CHARACTER:
+ sc = HRESULT_FROM_WIN32( ERROR_NO_UNICODE_TRANSLATION );
+ break;
+
+ default:
+ PropDbg((DEB_ERROR, "NtStatusToScode: Unknown status %lX\n", nts));
+
+ sc = HRESULT_FROM_NT(nts);
+ break;
+ }
+
+ PropDbg((DEB_ITRACE, "Out NtStatusToScode => %lX\n", sc));
+ return sc;
+}
+
+#if DBG!=0 && !defined(WINNT)
+
+ULONG
+DbgPrint(
+ PCHAR Format,
+ ...
+ )
+{
+ va_list arglist;
+ CHAR Buffer[512];
+ int cb;
+
+ //
+ // Format the output into a buffer and then print it.
+ //
+
+ va_start(arglist, Format);
+ cb = PropVsprintfA(Buffer, Format, arglist);
+ if (cb == -1) { // detect buffer overflow
+ cb = sizeof(Buffer);
+ Buffer[sizeof(Buffer) - 2] = '\n';
+ Buffer[sizeof(Buffer) - 1] = '\0';
+ }
+
+ OutputDebugString(Buffer);
+
+ return 0;
+}
+#endif
+
diff --git a/private/ole32/stg/props/utils.hxx b/private/ole32/stg/props/utils.hxx
new file mode 100644
index 000000000..3d6c59d91
--- /dev/null
+++ b/private/ole32/stg/props/utils.hxx
@@ -0,0 +1,143 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: utils.hxx
+//
+// Contents: Useful classes in implementing properties.
+//
+// Classes: CPropSetName - Buffer which converts fmtids->names
+// CSubPropertyName - Buffer which converts VT_STREAM etc -> name
+//
+// Functions: DfpStatusToHResult - map NTSTATUS to HRESULT
+// VerifyCommitFlags - check transaction flags
+// Probe - probe memory range to generate GP fault.
+//
+// History: 1-Mar-95 BillMo Created.
+//
+// Notes:
+//
+// Codework:
+//
+//--------------------------------------------------------------------------
+
+//+-------------------------------------------------------------------------
+//
+// Misc functions and defines
+//
+//--------------------------------------------------------------------------
+
+#if DBG
+#define STACKELEMS 3
+#else
+#define STACKELEMS 64
+#endif
+
+extern HRESULT NtStatusToScode(NTSTATUS);
+
+inline HRESULT DfpNtStatusToHResult(NTSTATUS nts)
+{
+ if ((nts & 0xF0000000) == 0x80000000)
+ return nts;
+ else
+ return(NtStatusToScode(nts));
+}
+
+#define VerifyCommitFlags(cf) \
+ ((((cf) & ~(STGC_OVERWRITE | STGC_ONLYIFCURRENT | \
+ STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE)) == 0) ? S_OK : \
+ STG_E_INVALIDFLAG)
+
+inline VOID Probe(VOID *pv, ULONG cb)
+{
+ BYTE b = *(BYTE*)pv;
+ b=((BYTE*)pv)[cb-1];
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CPropSetName
+//
+// Purpose: Wrap buffer to convert
+//
+// Interface:
+//
+//
+//
+//
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CPropSetName
+{
+public:
+ CPropSetName(REFFMTID rfmtid);
+ inline const OLECHAR * GetPropSetName()
+ {
+ return(_oszName);
+ }
+private:
+ OLECHAR _oszName[CWCSTORAGENAME];
+};
+
+class CStackBuffer
+{
+public:
+ CStackBuffer(BYTE *pbStackBuf,
+ ULONG ulElementSize,
+ ULONG cStackElements);
+
+ ~CStackBuffer();
+
+ HRESULT Init(ULONG cElements);
+
+protected:
+ BYTE * _pbHeapBuf;
+
+private:
+ BYTE * _pbStackBuf;
+ ULONG _cbElementSize;
+ ULONG _cStackElements;
+};
+
+inline CStackBuffer::CStackBuffer( BYTE *pbStackBuf,
+ ULONG cbElementSize,
+ ULONG cStackElements)
+ : _pbStackBuf(pbStackBuf),
+ _pbHeapBuf(pbStackBuf),
+ _cbElementSize(cbElementSize),
+ _cStackElements(cStackElements)
+{
+}
+
+inline CStackBuffer::~CStackBuffer()
+{
+ if (_pbHeapBuf != _pbStackBuf)
+ {
+ delete [] _pbHeapBuf;
+ }
+}
+
+class CStackPropIdArray : public CStackBuffer
+{
+public:
+ inline CStackPropIdArray();
+ inline PROPID * GetBuf();
+
+private:
+ PROPID _apid[STACKELEMS];
+};
+
+inline CStackPropIdArray::CStackPropIdArray() :
+ CStackBuffer((BYTE*)_apid, sizeof(_apid[0]), sizeof(_apid)/sizeof(_apid[0]))
+{
+}
+
+inline PROPID * CStackPropIdArray::GetBuf()
+{
+ return((PROPID*)_pbHeapBuf);
+}
+
diff --git a/private/ole32/stg/ref/ascii.cxx b/private/ole32/stg/ref/ascii.cxx
new file mode 100644
index 000000000..735efa7aa
--- /dev/null
+++ b/private/ole32/stg/ref/ascii.cxx
@@ -0,0 +1,488 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: ascii.cxx
+//
+// Contents: char to WCHAR conversion layer
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+
+#include <expdf.hxx>
+#include <expiter.hxx>
+#include <expst.hxx>
+#include <ascii.hxx>
+
+// If UNICODE is defined, none of this is necessary
+
+//+--------------------------------------------------------------
+//
+// Function: ValidateSNBA, private
+//
+// Synopsis: Validates a char SNB
+//
+// Arguments: [snb] - SNB
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+static SCODE ValidateSNBA(SNB snb)
+{
+ SCODE sc;
+
+ for (;;)
+ {
+ olChk(ValidatePtrBuffer(snb));
+ if (*snb == NULL)
+ break;
+ olChk(ValidateNameA(*snb, CBMAXPATHCOMPLEN));
+ snb++;
+ }
+ return S_OK;
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: SNBToSNBW, private
+//
+// Synopsis: Converts a char SNB to a WCHAR SNB
+//
+// Arguments: [snbIn] - char SNB
+//
+// Returns: WCHAR SNB or NULL
+//
+//---------------------------------------------------------------
+
+static SNBW SNBToSNBW(SNB snbIn)
+{
+ ULONG cbStrings = 0;
+ SNB snb;
+ ULONG cItems = 0;
+ SNBW snbw, snbwOut;
+ WCHAR *pwcs;
+ BYTE *pb;
+
+ for (snb = snbIn; *snb; snb++, cItems++)
+ cbStrings += (strlen(*snb)+1)*sizeof(WCHAR);
+ cItems++;
+ pb = new BYTE[(size_t)(cbStrings+sizeof(WCHAR *)*cItems)];
+ if (pb == NULL)
+ return NULL;
+ snbwOut = (SNBW)pb;
+ pwcs = (WCHAR *)(pb+sizeof(WCHAR *)*cItems);
+ for (snb = snbIn, snbw = snbwOut; *snb; snb++, snbw++)
+ {
+ *snbw = pwcs;
+ mbstowcs(*snbw, *snb, strlen(*snb)+1);
+ pwcs += wcslen(*snbw)+1;
+ }
+ *snbw = NULL;
+ return snbwOut;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: CheckAName, public
+//
+// Synopsis: Checks name for illegal characters and length
+//
+// Arguments: [pwcsName] - Name
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+#define INVALIDCHARS "\\/:!"
+
+SCODE CheckAName(char const *pwcsName)
+{
+ SCODE sc;
+ olDebugOut((DEB_ITRACE, "In CheckAName(%s)\n", pwcsName));
+ if (FAILED(sc = ValidateNameA(pwcsName, CBMAXPATHCOMPLEN)))
+ return sc;
+ // >= is used because the max len includes the null terminator
+ if (strlen(pwcsName) >= CWCMAXPATHCOMPLEN)
+ return STG_E_INVALIDNAME;
+ for (; *pwcsName; pwcsName++)
+ if (strchr(INVALIDCHARS, *pwcsName))
+ return STG_E_INVALIDNAME;
+ olDebugOut((DEB_ITRACE, "Out CheckAName\n"));
+ return S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::Next, public
+//
+// Synopsis: char version
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedIterator::Next(ULONG celt,
+ STATSTG FAR *rgelt,
+ ULONG *pceltFetched)
+{
+ SCODE sc;
+ ULONG i;
+ ULONG cnt;
+
+ olAssert(sizeof(STATSTG) == sizeof(STATSTGW));
+
+ if (pceltFetched)
+ {
+ olChk(ValidateBuffer(pceltFetched, sizeof(ULONG)));
+ *pceltFetched = 0;
+ }
+ olChk(sc = Next(celt, (STATSTGW *)rgelt, &cnt));
+ for (i = 0; i<cnt; i++)
+ if (rgelt[i].pwcsName)
+ wcstombs(rgelt[i].pwcsName, (WCHAR *)rgelt[i].pwcsName,
+ CWCSTORAGENAME);
+ if (pceltFetched)
+ *pceltFetched = cnt;
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Stat, public
+//
+// Synopsis: char version
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+
+ olAssert(sizeof(STATSTG) == sizeof(STATSTGW));
+
+ olChk(sc = Stat((STATSTGW *)pstatstg, grfStatFlag));
+ if (pstatstg->pwcsName)
+ wcstombs(pstatstg->pwcsName, (WCHAR *)pstatstg->pwcsName,
+ CWCSTORAGENAME);
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::Stat, public
+//
+// Synopsis: char version
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+
+ olAssert(sizeof(STATSTG) == sizeof(STATSTGW));
+
+ olChk(sc = Stat((STATSTGW *)pstatstg, grfStatFlag));
+ if (pstatstg->pwcsName)
+ wcstombs(pstatstg->pwcsName, (WCHAR *)pstatstg->pwcsName,
+ _MAX_PATH);
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CreateStream, public
+//
+// Synopsis: char version
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::CreateStream(char const *pszName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+ WCHAR wcsName[CWCSTORAGENAME];
+
+ olChk(ValidateOutPtrBuffer(ppstm));
+ *ppstm = NULL;
+ olChk(CheckAName(pszName));
+ mbstowcs(wcsName, pszName, CWCSTORAGENAME);
+ sc = CreateStream(wcsName, grfMode, reserved1, reserved2, ppstm);
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::OpenStream, public
+//
+// Synopsis: char version
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::OpenStream(char const *pszName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+ WCHAR wcsName[CWCSTORAGENAME];
+
+ olChk(ValidateOutPtrBuffer(ppstm));
+ *ppstm = NULL;
+ olChk(CheckAName(pszName));
+ mbstowcs(wcsName, pszName, CWCSTORAGENAME);
+ sc = OpenStream(wcsName, reserved1, grfMode, reserved2, ppstm);
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CreateStorage, public
+//
+// Synopsis: char version
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::CreateStorage(char const *pszName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ WCHAR wcsName[CWCSTORAGENAME];
+
+ olChk(ValidateOutPtrBuffer(ppstg));
+ *ppstg = NULL;
+ olChk(CheckAName(pszName));
+ mbstowcs(wcsName, pszName, CWCSTORAGENAME);
+ sc = CreateStorage(wcsName, grfMode, reserved1, reserved2, ppstg);
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::OpenStorage, public
+//
+// Synopsis: char version
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::OpenStorage(char const *pszName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+{
+ SNBW snbw;
+ SCODE sc;
+ WCHAR wcsName[CWCSTORAGENAME];
+
+ olChk(ValidateOutPtrBuffer(ppstg));
+ *ppstg = NULL;
+ olChk(CheckAName(pszName));
+ mbstowcs(wcsName, pszName, CWCSTORAGENAME);
+ if (snbExclude)
+ {
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ }
+ else
+ snbw = NULL;
+ sc = OpenStorage(wcsName, pstgPriority, grfMode, snbw,
+ reserved, ppstg);
+ delete snbw;
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::DestroyElement, public
+//
+// Synopsis: char version
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::DestroyElement(char const *pszName)
+{
+ SCODE sc;
+ WCHAR wcsName[CWCSTORAGENAME];
+
+ olChk(CheckAName(pszName));
+ mbstowcs(wcsName, pszName, CWCSTORAGENAME);
+ sc = DestroyElement(wcsName);
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::RenameElement, public
+//
+// Synopsis: char version
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::RenameElement(char const *pszOldName,
+ char const *pszNewName)
+{
+ SCODE sc;
+ WCHAR wcsOldName[CWCSTORAGENAME], wcsNewName[CWCSTORAGENAME];
+
+ olChk(CheckAName(pszOldName));
+ olChk(CheckAName(pszNewName));
+ mbstowcs(wcsOldName, pszOldName, CWCSTORAGENAME);
+ mbstowcs(wcsNewName, pszNewName, CWCSTORAGENAME);
+ sc = RenameElement(wcsOldName, wcsNewName);
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CopyTo, public
+//
+// Synopsis: ANSI version
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::CopyTo(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest)
+{
+ SNBW snbw;
+ SCODE sc;
+
+ if (snbExclude)
+ {
+ olChk(ValidateSNBA(snbExclude));
+ olMem(snbw = SNBToSNBW(snbExclude));
+ }
+ else
+ snbw = NULL;
+ sc = CopyTo(ciidExclude, rgiidExclude, snbw, pstgDest);
+ delete snbw;
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::MoveElementTo, public
+//
+// Synopsis: ANSI version
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::MoveElementTo(TCHAR const *lpszName,
+ IStorage *pstgDest,
+ TCHAR const *lpszNewName,
+ DWORD grfFlags)
+{
+ SCODE sc;
+ WCHAR wcsName[CWCSTORAGENAME];
+
+ olChk(CheckAName(lpszName));
+ mbstowcs(wcsName, lpszName, CWCSTORAGENAME);
+ sc = MoveElementTo(wcsName, pstgDest, lpszNewName, grfFlags);
+
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::SetElementTimes, public
+//
+// Synopsis: ANSI version
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::SetElementTimes(TCHAR const *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ SCODE sc;
+ WCHAR wcsName[CWCSTORAGENAME];
+
+ olChk(CheckAName(lpszName));
+ mbstowcs(wcsName, lpszName, CWCSTORAGENAME);
+ sc = SetElementTimes(wcsName, pctime, patime, pmtime);
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Function: StgCreateDocfile, public
+//
+// Synopsis: char version
+//
+//---------------------------------------------------------------
+
+STDAPI StgCreateDocfile(char const *pszName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage **ppstgOpen)
+{
+ return ResultFromScode(STG_E_UNIMPLEMENTEDFUNCTION);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Function: DfOpenStorageOnILockBytes, public
+//
+// Synopsis: char version
+//
+//---------------------------------------------------------------
+
+STDAPI DfOpenStorageOnILockBytes(ILockBytes *plkbyt,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstgOpen,
+ CLSID *pcid)
+{
+ SNBW snbw;
+ SCODE sc;
+
+ olChk(ValidatePtrBuffer(ppstgOpen));
+ *ppstgOpen = NULL;
+ if (snbExclude)
+ {
+ olChk(ValidateSNBA(snbExclude));
+ olMem(snbw = SNBToSNBW(snbExclude));
+ }
+ else
+ snbw = NULL;
+ sc = DfOpenStorageOnILockBytesW(plkbyt, pstgPriority, grfMode,
+ snbw, reserved, ppstgOpen, pcid);
+ delete snbw;
+EH_Err:
+ return ResultFromScode(sc);
+}
+
diff --git a/private/ole32/stg/ref/ascii.hxx b/private/ole32/stg/ref/ascii.hxx
new file mode 100644
index 000000000..a1ff18947
--- /dev/null
+++ b/private/ole32/stg/ref/ascii.hxx
@@ -0,0 +1,23 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: ascii.hxx
+//
+// Contents: WCHAR header for ASCII layer
+//
+//---------------------------------------------------------------
+
+#ifndef __ASCII_HXX__
+#define __ASCII_HXX__
+
+SCODE DfOpenStorageOnILockBytesW(ILockBytes *plkbyt,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNBW snbExclude,
+ DWORD reserved,
+ IStorage **ppstgOpen,
+ CLSID *pcid);
+
+#endif // #ifndef __ASCII_HXX__
diff --git a/private/ole32/stg/ref/cdocfile.cxx b/private/ole32/stg/ref/cdocfile.cxx
new file mode 100644
index 000000000..448901e0f
--- /dev/null
+++ b/private/ole32/stg/ref/cdocfile.cxx
@@ -0,0 +1,388 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992
+//
+// File: cdocfile.cxx
+//
+// Contents: Implementation of CDocFile methods for DocFiles
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+
+#include <vectfunc.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: PEntry::_dlBase, static private data
+//
+// Synopsis: luid allocation base
+//
+// Notes: Since DF_NOLUID is 0 and ROOT_LUID is 1 we start
+// issuing at 2.
+//
+//---------------------------------------------------------------
+
+DFLUID PEntry::_dlBase = LUID_BASE;
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::InitFromEntry, public
+//
+// Synopsis: Creation/Instantiation constructor for embeddings
+//
+// Arguments: [pstghParent] - Parent handle
+// [pdfn] - Name
+// [fCreate] - Create/Instantiate
+// [dwType] - Type of entry
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+SCODE CDocFile::InitFromEntry(CStgHandle *pstghParent,
+ CDfName const *pdfn,
+ BOOL const fCreate)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::InitFromEntry(%p, %ws, %d)\n",
+ pstghParent, pdfn, fCreate));
+ if (fCreate)
+ sc = pstghParent->CreateEntry(pdfn, STGTY_STORAGE, &_stgh);
+ else
+ sc = pstghParent->GetEntry(pdfn, STGTY_STORAGE, &_stgh);
+ if (SUCCEEDED(sc))
+ AddRef();
+ olDebugOut((DEB_ITRACE, "Out CDocFile::InitFromEntry\n"));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::CreateDocFile, public
+//
+// Synopsis: Creates a DocFile object in a parent
+//
+// Arguments: [pdfn] - Name of DocFile
+// [df] - Transactioning flags
+// [dlSet] - LUID to set or DF_NOLUID
+// [dwType] - Type of entry
+// [ppdfDocFile] - DocFile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdfDocFile]
+//
+//---------------------------------------------------------------
+
+
+SCODE CDocFile::CreateDocFile(CDfName const *pdfn,
+ DFLAGS const df,
+ DFLUID dlSet,
+ PDocFile **ppdfDocFile)
+{
+ CDocFile *pdf;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::CreateDocFile:%p("
+ "%ws, %X, %lu, %p)\n", this, pdfn, df, dlSet,
+ ppdfDocFile));
+ UNREFERENCED_PARM(df);
+
+ if (dlSet == DF_NOLUID)
+ dlSet = CDocFile::GetNewLuid();
+
+ olMem(pdf = new CDocFile(dlSet, _pilbBase));
+
+ olChkTo(EH_pdf, pdf->InitFromEntry(&_stgh, pdfn, TRUE));
+
+ *ppdfDocFile = pdf;
+ olDebugOut((DEB_ITRACE, "Out CDocFile::CreateDocFile => %p\n",
+ *ppdfDocFile));
+ return S_OK;
+
+EH_pdf:
+ delete pdf;
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::GetDocFile, public
+//
+// Synopsis: Instantiates an existing docfile
+//
+// Arguments: [pdfn] - Name of stream
+// [df] - Transactioning flags
+// [dwType] - Type of entry
+// [ppdfDocFile] - Docfile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdfDocFile]
+//
+//---------------------------------------------------------------
+
+
+SCODE CDocFile::GetDocFile(CDfName const *pdfn,
+ DFLAGS const df,
+ PDocFile **ppdfDocFile)
+{
+ CDocFile *pdf;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::GetDocFile:%p("
+ "%ws, %X, %p)\n", this, pdfn, df, ppdfDocFile));
+ UNREFERENCED_PARM(df);
+
+ DFLUID dl = CDocFile::GetNewLuid();
+ olMem(pdf = new CDocFile(dl, _pilbBase));
+
+ olChkTo(EH_pdf, pdf->InitFromEntry(&_stgh, pdfn, FALSE));
+ *ppdfDocFile = pdf;
+ olDebugOut((DEB_ITRACE, "Out CDocFile::GetDocFile => %p\n",
+ *ppdfDocFile));
+ return S_OK;
+
+EH_pdf:
+ delete pdf;
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::Release, public
+//
+// Synopsis: Release resources for a DocFile
+//
+//---------------------------------------------------------------
+
+
+void CDocFile::Release(void)
+{
+ olDebugOut((DEB_ITRACE, "In CDocFile::Release()\n"));
+ olAssert(_cReferences > 0);
+
+ AtomicDec(&_cReferences);
+ if (_cReferences == 0)
+ delete this;
+ olDebugOut((DEB_ITRACE, "Out CDocFile::Release\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::RenameEntry, public
+//
+// Synopsis: Renames a child
+//
+// Arguments: [pdfnName] - Old name
+// [pdfnNewName] - New name
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+SCODE CDocFile::RenameEntry(CDfName const *pdfnName,
+ CDfName const *pdfnNewName)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::RenameEntry(%ws, %ws)\n",
+ pdfnName, pdfnNewName));
+ sc = _stgh.RenameEntry(pdfnName, pdfnNewName);
+ olDebugOut((DEB_ITRACE, "Out CDocFile::RenameEntry\n"));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::DestroyEntry, public
+//
+// Synopsis: Permanently destroys a child
+//
+// Arguments: [pdfnName] - Name of child
+// [fClean] - Ignored
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+SCODE CDocFile::DestroyEntry(CDfName const *pdfnName,
+ BOOL fClean)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::DestroyEntry:%p(%ws, %d)\n",
+ this, pdfnName, fClean));
+ UNREFERENCED_PARM(fClean);
+ sc = _stgh.DestroyEntry(pdfnName);
+ olDebugOut((DEB_ITRACE, "Out CDocFile::DestroyEntry\n"));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::IsEntry, public
+//
+// Synopsis: Determines whether the given object is a member
+// of the DocFile
+//
+// Arguments: [pdfnName] - Name
+// [peb] - Entry buffer to fill in
+//
+// Returns: Appropriate status code
+//
+// Modifies: [peb]
+//
+//---------------------------------------------------------------
+
+
+SCODE CDocFile::IsEntry(CDfName const *pdfnName,
+ SEntryBuffer *peb)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::IsEntry(%ws, %p)\n",
+ pdfnName, peb));
+ sc = _stgh.IsEntry(pdfnName, peb);
+ olDebugOut((DEB_ITRACE, "Out CDocFile::IsEntry => %lu, %lu, %lu\n",
+ sc, peb->luid, peb->dwType));
+ return sc;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+//---------------------------------------------------------------
+
+void CDocFile::AddRef(void)
+{
+ olDebugOut((DEB_ITRACE, "In CDocFile::AddRef()\n"));
+ AtomicInc(&_cReferences);
+ olDebugOut((DEB_ITRACE, "Out CDocFile::AddRef, %lu\n", _cReferences));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::GetTime, public
+//
+// Synopsis: Gets a time
+//
+// Arguments: [wt] - Which time
+// [ptm] - Time return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ptm]
+//
+//---------------------------------------------------------------
+
+SCODE CDocFile::GetTime(WHICHTIME wt, TIME_T *ptm)
+{
+ return _stgh.GetTime(wt, ptm);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::SetTime, public
+//
+// Synopsis: Sets a time
+//
+// Arguments: [wt] - Which time
+// [tm] - New time
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+SCODE CDocFile::SetTime(WHICHTIME wt, TIME_T tm)
+{
+ return _stgh.SetTime(wt, tm);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::GetClass, public
+//
+// Synopsis: Gets the class ID
+//
+// Arguments: [pclsid] - Class ID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pclsid]
+//
+//----------------------------------------------------------------------------
+
+SCODE CDocFile::GetClass(CLSID *pclsid)
+{
+ return _stgh.GetClass(pclsid);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::SetClass, public
+//
+// Synopsis: Sets the class ID
+//
+// Arguments: [clsid] - New class ID
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+SCODE CDocFile::SetClass(REFCLSID clsid)
+{
+ return _stgh.SetClass(clsid);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::GetStateBits, public
+//
+// Synopsis: Gets the state bits
+//
+// Arguments: [pgrfStateBits] - State bits return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pgrfStateBits]
+//
+//----------------------------------------------------------------------------
+
+SCODE CDocFile::GetStateBits(DWORD *pgrfStateBits)
+{
+ return _stgh.GetStateBits(pgrfStateBits);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::SetStateBits, public
+//
+// Synopsis: Sets the state bits
+//
+// Arguments: [grfStateBits] - Bits to set
+// [grfMask] - Mask
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+SCODE CDocFile::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ return _stgh.SetStateBits(grfStateBits, grfMask);
+}
+
+
diff --git a/private/ole32/stg/ref/chinst.cxx b/private/ole32/stg/ref/chinst.cxx
new file mode 100644
index 000000000..37a00df06
--- /dev/null
+++ b/private/ole32/stg/ref/chinst.cxx
@@ -0,0 +1,219 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992
+//
+// File: chinst.cxx
+//
+// Contents: DocFile child instance management code
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+
+// Permissions checked in the less-restrictive rule
+#define TCANTSET DF_READ
+#define DCANTSET (DF_READ | DF_WRITE)
+#define CANTCLEAR (DF_DENYREAD | DF_DENYWRITE)
+
+//+--------------------------------------------------------------
+//
+// Method: CChildInstanceList::Add, private
+//
+// Synopsis: Registers an instance of a child
+//
+// Arguments: [prv] - Child
+//
+//---------------------------------------------------------------
+
+void CChildInstanceList::Add(PRevertable *prv)
+{
+ olDebugOut((DEB_ITRACE, "In CChildInstanceList::Add(%p)\n", prv));
+ prv->_prvNext = _prvHead;
+ _prvHead = prv;
+ olDebugOut((DEB_ITRACE, "Out CChildInstanceList::Add\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CChildInstanceList::FindByName, private
+//
+// Synopsis: Finds a child instance by name
+//
+// Arguments: [pdfn] - Name
+//
+// Returns: Pointer to instance or NULL
+//
+//----------------------------------------------------------------------------
+
+PRevertable *CChildInstanceList::FindByName(CDfName const *pdfn)
+{
+ PRevertable *prv;
+
+ olDebugOut((DEB_ITRACE, "In CChildInstanceList::FindByName:%p(%ws)\n",
+ this, pdfn->GetBuffer()));
+ for (prv = _prvHead; prv; prv = prv->_prvNext)
+ if (prv->_dfn.IsEqual(pdfn))
+ return prv;
+ olDebugOut((DEB_ITRACE, "Out CChildInstanceList::FindByName\n"));
+ return NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Method: CChildInstanceList::DeleteByName, private
+//
+// Synopsis: Removes an instance from the instance list
+// and reverts it
+//
+// Arguments: [pdfn] - Name or NULL
+//
+// Notes: The entry does not have to exist
+// There can be multiple entries
+// If name is NULL, all entries match
+//
+//---------------------------------------------------------------
+
+void CChildInstanceList::DeleteByName(CDfName const *pdfn)
+{
+ PRevertable **pprv;
+
+ olDebugOut((DEB_ITRACE, "In CChildInstanceList::DeleteByName(%ws)\n",
+ pdfn->GetBuffer()));
+ for (pprv = &_prvHead; *pprv; )
+ if (NULL == pdfn || (*pprv)->_dfn.IsEqual(pdfn))
+ {
+ (*pprv)->RevertFromAbove();
+ *pprv = (*pprv)->_prvNext;
+ }
+ else
+ pprv = &(*pprv)->_prvNext;
+ olDebugOut((DEB_ITRACE, "Out CChildInstanceList::DeleteByName\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Method: CChildInstanceList::RemoveRv, private
+//
+// Synopsis: Removes a specific instance from the instance list
+//
+// Arguments: [prv] - Instance
+//
+// Notes: The entry does not have to exist
+//
+//---------------------------------------------------------------
+
+void CChildInstanceList::RemoveRv(PRevertable *prvRv)
+{
+ PRevertable **prv;
+
+ olDebugOut((DEB_ITRACE, "In CChildInstanceList::RemoveRv(%p)\n", prvRv));
+ for (prv = &_prvHead; *prv; prv = &(*prv)->_prvNext)
+ if (*prv == prvRv)
+ {
+ *prv = (*prv)->_prvNext;
+ break;
+ }
+ olDebugOut((DEB_ITRACE, "Out CChildInstanceList::RemoveRv\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Method: CChildInstanceList::IsDenied, private
+//
+// Synopsis: Checks the parent instantiation list for a previous
+// instance of the given child with DENY flags on
+// Also determines whether child mode flags are
+// less restrictive than the parent's
+//
+// Arguments: [pdfn] - Instance name
+// [dfCheck] - Access modes to check for denial
+// [dfAgainst] - Access modes to check against
+//
+// Returns: Appropriate status code
+//
+// Notes: The instance doesn't have to be in the list.
+// If it isn't, it's not denied
+//
+//---------------------------------------------------------------
+
+SCODE CChildInstanceList::IsDenied(CDfName const *pdfn,
+ DFLAGS const dfCheck,
+ DFLAGS const dfAgainst)
+{
+ PRevertable *prv;
+ SCODE sc = S_OK;
+
+ olDebugOut((DEB_ITRACE, "In CChildInstanceList::IsDenied("
+ "%p, %lX, %lX)\n", pdfn, dfCheck, dfAgainst));
+
+ olAssert(pdfn != NULL && aMsg("IsDenied, null name"));
+
+ // Check to see if permissions are less restrictive than
+ // parent permissions
+ // This checks to see that a child isn't specifying
+ // a permission that its parent doesn't
+ // For example, giving read permission when the parent
+ // doesn't
+ if ((~dfAgainst & dfCheck &
+ (P_TRANSACTED(dfAgainst) ? TCANTSET : DCANTSET)) ||
+ (dfAgainst & ~dfCheck & CANTCLEAR))
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+
+ // Check for DENY_*
+ olAssert((DF_DENYALL >> DF_DENIALSHIFT) == DF_READWRITE);
+ for (prv = _prvHead; prv != NULL; prv = prv->GetNext())
+ {
+ if (prv->_dfn.IsEqual(pdfn))
+ {
+ // Check for existing instance with DENY_* mode
+ if ((((prv->GetDFlags() & DF_DENYALL) >> DF_DENIALSHIFT) &
+ dfCheck) != 0 ||
+ // Check for instance with permission already given that
+ // new instance wants to deny
+ (((dfCheck & DF_DENYALL) >> DF_DENIALSHIFT) &
+ prv->GetDFlags()) != 0)
+ {
+ sc = STG_E_ACCESSDENIED;
+ break;
+ }
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out CChildInstanceList::IsDenied\n"));
+ // Fall through
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Method: CChildInstanceList::RenameChild, public
+//
+// Synopsis: Renames the child
+//
+// Arguments: [pdfn] - old name
+// [pdfnName] - new name
+//
+// Notes: The entry might exist
+//
+//---------------------------------------------------------------
+
+void CChildInstanceList::RenameChild(
+ CDfName const *pdfn,
+ CDfName const *pdfnNewName)
+{
+ PRevertable *prv;
+
+ olDebugOut((DEB_ITRACE, "In CChildInstanceList::RenameChild(%p, %p)\n",
+ pdfn, pdfnNewName));
+ for (prv = _prvHead; prv; prv = prv->_prvNext)
+ {
+ if (prv->_dfn.IsEqual(pdfn))
+ {
+ prv->_dfn.Set(pdfnNewName->GetLength(), pdfnNewName->GetBuffer());
+ break;
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out CChildInstanceList::RenameChild\n"));
+}
diff --git a/private/ole32/stg/ref/depend.mk b/private/ole32/stg/ref/depend.mk
new file mode 100644
index 000000000..c02ec1328
--- /dev/null
+++ b/private/ole32/stg/ref/depend.mk
@@ -0,0 +1,438 @@
+ascii.obj ascii.lst: ascii.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\ascii.hxx .\expdf.hxx \
+ .\expiter.hxx .\expst.hxx .\h\chinst.hxx .\h\dfexcept.hxx \
+ .\h\dfmsp.hxx .\h\difat.hxx .\h\dir.hxx .\h\docfilep.hxx \
+ .\h\entry.hxx .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\header.hxx \
+ .\h\lock.hxx .\h\msf.hxx .\h\ole.hxx .\h\page.hxx .\h\pdocfile.hxx \
+ .\h\piter.hxx .\h\psstream.hxx .\h\pubiter.hxx .\h\publicdf.hxx \
+ .\h\ref.hxx .\h\revert.hxx .\h\storage.h .\h\storagep.h .\h\vect.hxx \
+ .\h\wchar.h .\peiter.hxx exphead.cxx
+
+ascii.obj ascii.lst: ascii.hxx
+
+cdocfile.obj cdocfile.lst: cdocfile.cxx $(CRTINC)\assert.h \
+ $(CRTINC)\malloc.h $(CRTINC)\memory.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ .\h\cdocfile.hxx .\h\chinst.hxx .\h\dfexcept.hxx .\h\dffuncs.hxx \
+ .\h\dfmsp.hxx .\h\difat.hxx .\h\dir.hxx .\h\dirfunc.hxx \
+ .\h\docfilep.hxx .\h\entry.hxx .\h\error.hxx .\h\fat.hxx \
+ .\h\funcs.hxx .\h\handle.hxx .\h\header.hxx .\h\msf.hxx \
+ .\h\msffunc.hxx .\h\ole.hxx .\h\page.hxx .\h\pdocfile.hxx \
+ .\h\piter.hxx .\h\psstream.hxx .\h\publicdf.hxx .\h\ref.hxx \
+ .\h\revert.hxx .\h\sstream.hxx .\h\storage.h .\h\storagep.h \
+ .\h\vect.hxx .\h\vectfunc.hxx .\h\wchar.h dfhead.cxx
+
+chinst.obj chinst.lst: chinst.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\cdocfile.hxx .\h\chinst.hxx \
+ .\h\dfexcept.hxx .\h\dffuncs.hxx .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\docfilep.hxx .\h\entry.hxx \
+ .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\handle.hxx \
+ .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx .\h\ole.hxx .\h\page.hxx \
+ .\h\pdocfile.hxx .\h\piter.hxx .\h\psstream.hxx .\h\publicdf.hxx \
+ .\h\ref.hxx .\h\revert.hxx .\h\sstream.hxx .\h\storage.h \
+ .\h\storagep.h .\h\vect.hxx .\h\wchar.h dfhead.cxx
+
+dffuncs.obj dffuncs.lst: dffuncs.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\cdocfile.hxx .\h\chinst.hxx \
+ .\h\dfexcept.hxx .\h\dffuncs.hxx .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\docfilep.hxx .\h\entry.hxx \
+ .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\handle.hxx \
+ .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx .\h\ole.hxx .\h\page.hxx \
+ .\h\pdocfile.hxx .\h\piter.hxx .\h\psstream.hxx .\h\publicdf.hxx \
+ .\h\ref.hxx .\h\revert.hxx .\h\sstream.hxx .\h\storage.h \
+ .\h\storagep.h .\h\vect.hxx .\h\wchar.h .\iter.hxx dfhead.cxx
+
+dfhead.obj dfhead.lst: dfhead.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\cdocfile.hxx .\h\chinst.hxx \
+ .\h\dfexcept.hxx .\h\dffuncs.hxx .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\docfilep.hxx .\h\entry.hxx \
+ .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\handle.hxx \
+ .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx .\h\ole.hxx .\h\page.hxx \
+ .\h\pdocfile.hxx .\h\piter.hxx .\h\psstream.hxx .\h\publicdf.hxx \
+ .\h\ref.hxx .\h\revert.hxx .\h\sstream.hxx .\h\storage.h \
+ .\h\storagep.h .\h\vect.hxx .\h\wchar.h
+
+dfiter.obj dfiter.lst: dfiter.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\cdocfile.hxx .\h\chinst.hxx \
+ .\h\dfexcept.hxx .\h\dffuncs.hxx .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\docfilep.hxx .\h\entry.hxx \
+ .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\handle.hxx \
+ .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx .\h\msfiter.hxx \
+ .\h\ole.hxx .\h\page.hxx .\h\pdocfile.hxx .\h\piter.hxx \
+ .\h\psstream.hxx .\h\publicdf.hxx .\h\ref.hxx .\h\revert.hxx \
+ .\h\sstream.hxx .\h\storage.h .\h\storagep.h .\h\vect.hxx \
+ .\h\wchar.h .\iter.hxx dfhead.cxx
+
+dfstream.obj dfstream.lst: dfstream.cxx $(CRTINC)\assert.h \
+ $(CRTINC)\malloc.h $(CRTINC)\memory.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ .\h\cdocfile.hxx .\h\chinst.hxx .\h\dfexcept.hxx .\h\dffuncs.hxx \
+ .\h\dfmsp.hxx .\h\difat.hxx .\h\dir.hxx .\h\dirfunc.hxx \
+ .\h\docfilep.hxx .\h\entry.hxx .\h\error.hxx .\h\fat.hxx \
+ .\h\funcs.hxx .\h\handle.hxx .\h\header.hxx .\h\msf.hxx \
+ .\h\msffunc.hxx .\h\ole.hxx .\h\page.hxx .\h\pdocfile.hxx \
+ .\h\piter.hxx .\h\psstream.hxx .\h\publicdf.hxx .\h\ref.hxx \
+ .\h\revert.hxx .\h\sstream.hxx .\h\storage.h .\h\storagep.h \
+ .\h\vect.hxx .\h\wchar.h dfhead.cxx
+
+difat.obj difat.lst: difat.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\entry.hxx .\h\error.hxx .\h\fat.hxx \
+ .\h\handle.hxx .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx \
+ .\h\page.hxx .\h\psstream.hxx .\h\ref.hxx .\h\sstream.hxx \
+ .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\vectfunc.hxx \
+ .\h\wchar.h .\mread.hxx msfhead.cxx
+
+dir.obj dir.lst: dir.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\entry.hxx .\h\error.hxx .\h\fat.hxx \
+ .\h\handle.hxx .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx \
+ .\h\page.hxx .\h\psstream.hxx .\h\ref.hxx .\h\sstream.hxx \
+ .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\vectfunc.hxx \
+ .\h\wchar.h .\mread.hxx msfhead.cxx
+
+dirp.obj dirp.lst: dirp.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\error.hxx .\h\fat.hxx .\h\header.hxx \
+ .\h\msf.hxx .\h\page.hxx .\h\ref.hxx .\h\storage.h .\h\storagep.h \
+ .\h\vect.hxx .\h\vectfunc.hxx .\h\wchar.h msfhead.cxx
+
+docfile.obj docfile.lst: docfile.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\ascii.hxx .\expdf.hxx \
+ .\expst.hxx .\h\chinst.hxx .\h\dfentry.hxx .\h\dfexcept.hxx \
+ .\h\dfmsp.hxx .\h\difat.hxx .\h\dir.hxx .\h\docfilep.hxx \
+ .\h\entry.hxx .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\header.hxx \
+ .\h\lock.hxx .\h\msf.hxx .\h\ole.hxx .\h\page.hxx .\h\pdocfile.hxx \
+ .\h\piter.hxx .\h\psstream.hxx .\h\publicdf.hxx .\h\ref.hxx \
+ .\h\revert.hxx .\h\rpubdf.hxx .\h\storage.h .\h\storagep.h \
+ .\h\vect.hxx .\h\wchar.h .\logfile.hxx exphead.cxx
+
+entry.obj entry.lst: entry.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\cdocfile.hxx .\h\chinst.hxx \
+ .\h\dfexcept.hxx .\h\dffuncs.hxx .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\docfilep.hxx .\h\entry.hxx \
+ .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\handle.hxx \
+ .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx .\h\ole.hxx .\h\page.hxx \
+ .\h\pdocfile.hxx .\h\piter.hxx .\h\psstream.hxx .\h\publicdf.hxx \
+ .\h\ref.hxx .\h\revert.hxx .\h\sstream.hxx .\h\storage.h \
+ .\h\storagep.h .\h\vect.hxx .\h\wchar.h dfhead.cxx
+
+expdf.obj expdf.lst: expdf.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\expdf.hxx .\expiter.hxx \
+ .\expst.hxx .\h\chinst.hxx .\h\dfexcept.hxx .\h\dfmsp.hxx \
+ .\h\difat.hxx .\h\dir.hxx .\h\docfilep.hxx .\h\entry.hxx \
+ .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\header.hxx .\h\lock.hxx \
+ .\h\msf.hxx .\h\ole.hxx .\h\page.hxx .\h\pbstream.hxx \
+ .\h\pdocfile.hxx .\h\piter.hxx .\h\psstream.hxx .\h\pubiter.hxx \
+ .\h\publicdf.hxx .\h\ref.hxx .\h\revert.hxx .\h\rpubdf.hxx \
+ .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\wchar.h .\logfile.hxx \
+ .\peiter.hxx exphead.cxx
+
+expdf.obj expdf.lst: expdf.hxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\entry.hxx .\h\error.hxx .\h\fat.hxx .\h\header.hxx \
+ .\h\msf.hxx .\h\page.hxx .\h\psstream.hxx .\h\ref.hxx .\h\storage.h \
+ .\h\storagep.h .\h\vect.hxx .\h\wchar.h
+
+exphead.obj exphead.lst: exphead.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\chinst.hxx .\h\dfexcept.hxx \
+ .\h\dfmsp.hxx .\h\difat.hxx .\h\dir.hxx .\h\docfilep.hxx \
+ .\h\entry.hxx .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\header.hxx \
+ .\h\msf.hxx .\h\ole.hxx .\h\page.hxx .\h\pdocfile.hxx .\h\piter.hxx \
+ .\h\publicdf.hxx .\h\ref.hxx .\h\revert.hxx .\h\storage.h \
+ .\h\storagep.h .\h\vect.hxx .\h\wchar.h
+
+expiter.obj expiter.lst: expiter.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\expiter.hxx .\h\chinst.hxx \
+ .\h\dfexcept.hxx .\h\dfmsp.hxx .\h\difat.hxx .\h\dir.hxx \
+ .\h\dirfunc.hxx .\h\docfilep.hxx .\h\entry.hxx .\h\error.hxx \
+ .\h\fat.hxx .\h\funcs.hxx .\h\handle.hxx .\h\header.hxx .\h\lock.hxx \
+ .\h\msf.hxx .\h\msffunc.hxx .\h\ole.hxx .\h\page.hxx \
+ .\h\pdocfile.hxx .\h\piter.hxx .\h\psstream.hxx .\h\pubiter.hxx \
+ .\h\publicdf.hxx .\h\ref.hxx .\h\revert.hxx .\h\sstream.hxx \
+ .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\wchar.h .\peiter.hxx \
+ exphead.cxx
+
+expiter.obj expiter.lst: expiter.hxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\chinst.hxx .\h\dfmsp.hxx \
+ .\h\difat.hxx .\h\dir.hxx .\h\entry.hxx .\h\error.hxx .\h\fat.hxx \
+ .\h\header.hxx .\h\lock.hxx .\h\msf.hxx .\h\ole.hxx .\h\page.hxx \
+ .\h\pdocfile.hxx .\h\pubiter.hxx .\h\publicdf.hxx .\h\ref.hxx \
+ .\h\revert.hxx .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\wchar.h \
+ .\peiter.hxx
+
+expst.obj expst.lst: expst.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\expst.hxx .\h\chinst.hxx \
+ .\h\dfexcept.hxx .\h\dfmsp.hxx .\h\difat.hxx .\h\dir.hxx \
+ .\h\docfilep.hxx .\h\entry.hxx .\h\error.hxx .\h\fat.hxx \
+ .\h\funcs.hxx .\h\header.hxx .\h\lock.hxx .\h\msf.hxx .\h\ole.hxx \
+ .\h\page.hxx .\h\pbstream.hxx .\h\pdocfile.hxx .\h\piter.hxx \
+ .\h\psstream.hxx .\h\publicdf.hxx .\h\ref.hxx .\h\revert.hxx \
+ .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\wchar.h .\logfile.hxx \
+ .\seekptr.hxx exphead.cxx
+
+expst.obj expst.lst: expst.hxx $(CRTINC)\memory.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx \
+ .\h\lock.hxx .\h\ref.hxx .\h\storage.h .\h\wchar.h
+
+fat.obj fat.lst: fat.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\entry.hxx .\h\error.hxx .\h\fat.hxx \
+ .\h\handle.hxx .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx \
+ .\h\page.hxx .\h\psstream.hxx .\h\ref.hxx .\h\sstream.hxx \
+ .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\vectfunc.hxx \
+ .\h\wchar.h .\mread.hxx msfhead.cxx
+
+funcs.obj funcs.lst: funcs.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\cdocfile.hxx .\h\chinst.hxx \
+ .\h\dfexcept.hxx .\h\dffuncs.hxx .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\docfilep.hxx .\h\entry.hxx \
+ .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\handle.hxx \
+ .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx .\h\ole.hxx .\h\page.hxx \
+ .\h\pdocfile.hxx .\h\piter.hxx .\h\psstream.hxx .\h\publicdf.hxx \
+ .\h\ref.hxx .\h\revert.hxx .\h\sstream.hxx .\h\storage.h \
+ .\h\storagep.h .\h\vect.hxx .\h\wchar.h dfhead.cxx
+
+header.obj header.lst: header.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx .\h\dfver.h \
+ .\h\difat.hxx .\h\dir.hxx .\h\error.hxx .\h\fat.hxx .\h\header.hxx \
+ .\h\msf.hxx .\h\page.hxx .\h\ref.hxx .\h\storage.h .\h\storagep.h \
+ .\h\vect.hxx .\h\vectfunc.hxx .\h\wchar.h msfhead.cxx
+
+iter.obj iter.lst: iter.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\cdocfile.hxx .\h\chinst.hxx \
+ .\h\dfexcept.hxx .\h\dffuncs.hxx .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\docfilep.hxx .\h\entry.hxx \
+ .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\handle.hxx \
+ .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx .\h\msfiter.hxx \
+ .\h\ole.hxx .\h\page.hxx .\h\pdocfile.hxx .\h\piter.hxx \
+ .\h\psstream.hxx .\h\publicdf.hxx .\h\ref.hxx .\h\revert.hxx \
+ .\h\sstream.hxx .\h\storage.h .\h\storagep.h .\h\vect.hxx \
+ .\h\wchar.h .\iter.hxx dfhead.cxx
+
+iter.obj iter.lst: iter.hxx .\h\piter.hxx
+
+lock.obj lock.lst: lock.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\chinst.hxx .\h\dfexcept.hxx \
+ .\h\dfmsp.hxx .\h\difat.hxx .\h\dir.hxx .\h\docfilep.hxx \
+ .\h\entry.hxx .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\header.hxx \
+ .\h\lock.hxx .\h\msf.hxx .\h\ole.hxx .\h\page.hxx .\h\pdocfile.hxx \
+ .\h\piter.hxx .\h\publicdf.hxx .\h\ref.hxx .\h\revert.hxx \
+ .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\wchar.h exphead.cxx
+
+logfile.obj logfile.lst: logfile.hxx
+
+mread.obj mread.lst: mread.hxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\entry.hxx .\h\error.hxx .\h\fat.hxx \
+ .\h\handle.hxx .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx \
+ .\h\page.hxx .\h\psstream.hxx .\h\ref.hxx .\h\sstream.hxx \
+ .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\wchar.h
+
+msf.obj msf.lst: msf.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\error.hxx .\h\fat.hxx .\h\handle.hxx \
+ .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx .\h\page.hxx .\h\ref.hxx \
+ .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\vectfunc.hxx \
+ .\h\wchar.h msfhead.cxx
+
+msfhead.obj msfhead.lst: msfhead.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\error.hxx .\h\fat.hxx .\h\header.hxx .\h\msf.hxx \
+ .\h\page.hxx .\h\ref.hxx .\h\storage.h .\h\storagep.h .\h\vect.hxx \
+ .\h\vectfunc.hxx .\h\wchar.h
+
+msfiter.obj msfiter.lst: msfiter.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\error.hxx .\h\fat.hxx .\h\header.hxx \
+ .\h\msf.hxx .\h\msfiter.hxx .\h\page.hxx .\h\ref.hxx .\h\storage.h \
+ .\h\storagep.h .\h\vect.hxx .\h\vectfunc.hxx .\h\wchar.h msfhead.cxx
+
+mstream.obj mstream.lst: mstream.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(CRTINC)\time.h .\h\dfmsp.hxx \
+ .\h\difat.hxx .\h\dir.hxx .\h\dirfunc.hxx .\h\docfilep.hxx \
+ .\h\entry.hxx .\h\error.hxx .\h\fat.hxx .\h\handle.hxx \
+ .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx .\h\msfiter.hxx \
+ .\h\page.hxx .\h\psstream.hxx .\h\ref.hxx .\h\sstream.hxx \
+ .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\vectfunc.hxx \
+ .\h\wchar.h .\mread.hxx msfhead.cxx
+
+page.obj page.lst: page.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\entry.hxx .\h\error.hxx .\h\fat.hxx \
+ .\h\handle.hxx .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx \
+ .\h\page.hxx .\h\psstream.hxx .\h\ref.hxx .\h\sstream.hxx \
+ .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\vectfunc.hxx \
+ .\h\wchar.h .\mread.hxx msfhead.cxx
+
+pbstream.obj pbstream.lst: pbstream.cxx $(CRTINC)\assert.h \
+ $(CRTINC)\malloc.h $(CRTINC)\memory.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ .\h\chinst.hxx .\h\dfmsp.hxx .\h\difat.hxx .\h\dir.hxx \
+ .\h\dirfunc.hxx .\h\docfilep.hxx .\h\entry.hxx .\h\error.hxx \
+ .\h\fat.hxx .\h\handle.hxx .\h\header.hxx .\h\msf.hxx \
+ .\h\msffunc.hxx .\h\ole.hxx .\h\page.hxx .\h\pbstream.hxx \
+ .\h\pdocfile.hxx .\h\psstream.hxx .\h\publicdf.hxx .\h\ref.hxx \
+ .\h\revert.hxx .\h\sstream.hxx .\h\storage.h .\h\storagep.h \
+ .\h\vect.hxx .\h\vectfunc.hxx .\h\wchar.h msfhead.cxx
+
+pdffuncs.obj pdffuncs.lst: pdffuncs.cxx $(CRTINC)\assert.h \
+ $(CRTINC)\malloc.h $(CRTINC)\memory.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ .\h\cdocfile.hxx .\h\chinst.hxx .\h\dfexcept.hxx .\h\dffuncs.hxx \
+ .\h\dfmsp.hxx .\h\difat.hxx .\h\dir.hxx .\h\dirfunc.hxx \
+ .\h\docfilep.hxx .\h\entry.hxx .\h\error.hxx .\h\fat.hxx \
+ .\h\funcs.hxx .\h\handle.hxx .\h\header.hxx .\h\msf.hxx \
+ .\h\msffunc.hxx .\h\ole.hxx .\h\page.hxx .\h\pdocfile.hxx \
+ .\h\piter.hxx .\h\psstream.hxx .\h\publicdf.hxx .\h\ref.hxx \
+ .\h\revert.hxx .\h\sstream.hxx .\h\storage.h .\h\storagep.h \
+ .\h\vect.hxx .\h\wchar.h dfhead.cxx
+
+peiter.obj peiter.lst: peiter.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\chinst.hxx .\h\dfexcept.hxx \
+ .\h\dfmsp.hxx .\h\difat.hxx .\h\dir.hxx .\h\docfilep.hxx \
+ .\h\entry.hxx .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\header.hxx \
+ .\h\msf.hxx .\h\ole.hxx .\h\page.hxx .\h\pdocfile.hxx .\h\piter.hxx \
+ .\h\pubiter.hxx .\h\publicdf.hxx .\h\ref.hxx .\h\revert.hxx \
+ .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\wchar.h .\peiter.hxx \
+ exphead.cxx
+
+peiter.obj peiter.lst: peiter.hxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\chinst.hxx .\h\dfmsp.hxx \
+ .\h\difat.hxx .\h\dir.hxx .\h\entry.hxx .\h\error.hxx .\h\fat.hxx \
+ .\h\header.hxx .\h\msf.hxx .\h\ole.hxx .\h\page.hxx .\h\pdocfile.hxx \
+ .\h\pubiter.hxx .\h\publicdf.hxx .\h\ref.hxx .\h\revert.hxx \
+ .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\wchar.h
+
+pubiter.obj pubiter.lst: pubiter.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\cdocfile.hxx .\h\chinst.hxx \
+ .\h\dfexcept.hxx .\h\dffuncs.hxx .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\docfilep.hxx .\h\entry.hxx \
+ .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\handle.hxx \
+ .\h\header.hxx .\h\msf.hxx .\h\msffunc.hxx .\h\ole.hxx .\h\page.hxx \
+ .\h\pdocfile.hxx .\h\piter.hxx .\h\psstream.hxx .\h\pubiter.hxx \
+ .\h\publicdf.hxx .\h\ref.hxx .\h\revert.hxx .\h\sstream.hxx \
+ .\h\storage.h .\h\storagep.h .\h\vect.hxx .\h\wchar.h dfhead.cxx
+
+publicdf.obj publicdf.lst: publicdf.cxx $(CRTINC)\assert.h \
+ $(CRTINC)\malloc.h $(CRTINC)\memory.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\time.h .\h\cdocfile.hxx .\h\chinst.hxx .\h\dfexcept.hxx \
+ .\h\dffuncs.hxx .\h\dfmsp.hxx .\h\difat.hxx .\h\dir.hxx \
+ .\h\dirfunc.hxx .\h\docfilep.hxx .\h\entry.hxx .\h\error.hxx \
+ .\h\fat.hxx .\h\funcs.hxx .\h\handle.hxx .\h\header.hxx .\h\lock.hxx \
+ .\h\msf.hxx .\h\msffunc.hxx .\h\ole.hxx .\h\page.hxx \
+ .\h\pbstream.hxx .\h\pdocfile.hxx .\h\piter.hxx .\h\psstream.hxx \
+ .\h\pubiter.hxx .\h\publicdf.hxx .\h\ref.hxx .\h\revert.hxx \
+ .\h\sstream.hxx .\h\storage.h .\h\storagep.h .\h\vect.hxx \
+ .\h\wchar.h dfhead.cxx
+
+refilb.obj refilb.lst: refilb.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\error.hxx .\h\fat.hxx .\h\header.hxx .\h\msf.hxx \
+ .\h\page.hxx .\h\ref.hxx .\h\refilb.hxx .\h\storage.h .\h\storagep.h \
+ .\h\vect.hxx .\h\vectfunc.hxx .\h\wchar.h msfhead.cxx
+
+reftest.obj reftest.lst: reftest.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\error.hxx .\h\fat.hxx .\h\header.hxx .\h\msf.hxx \
+ .\h\ole.hxx .\h\page.hxx .\h\ref.hxx .\h\refilb.hxx .\h\storage.h \
+ .\h\storagep.h .\h\vect.hxx .\h\wchar.h
+
+rpubdf.obj rpubdf.lst: rpubdf.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\cdocfile.hxx .\h\chinst.hxx \
+ .\h\dfexcept.hxx .\h\dffuncs.hxx .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\dirfunc.hxx .\h\docfilep.hxx .\h\entry.hxx \
+ .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\handle.hxx \
+ .\h\header.hxx .\h\lock.hxx .\h\msf.hxx .\h\msffunc.hxx .\h\ole.hxx \
+ .\h\page.hxx .\h\pdocfile.hxx .\h\piter.hxx .\h\psstream.hxx \
+ .\h\publicdf.hxx .\h\ref.hxx .\h\revert.hxx .\h\rpubdf.hxx \
+ .\h\sstream.hxx .\h\storage.h .\h\storagep.h .\h\vect.hxx \
+ .\h\wchar.h dfhead.cxx
+
+seekptr.obj seekptr.lst: seekptr.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\chinst.hxx .\h\dfexcept.hxx \
+ .\h\dfmsp.hxx .\h\difat.hxx .\h\dir.hxx .\h\docfilep.hxx \
+ .\h\entry.hxx .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\header.hxx \
+ .\h\msf.hxx .\h\ole.hxx .\h\page.hxx .\h\pdocfile.hxx .\h\piter.hxx \
+ .\h\publicdf.hxx .\h\ref.hxx .\h\revert.hxx .\h\storage.h \
+ .\h\storagep.h .\h\vect.hxx .\h\wchar.h .\seekptr.hxx exphead.cxx
+
+seekptr.obj seekptr.lst: seekptr.hxx
+
+sstream.obj sstream.lst: sstream.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(CRTINC)\time.h .\h\dfmsp.hxx \
+ .\h\difat.hxx .\h\dir.hxx .\h\dirfunc.hxx .\h\entry.hxx \
+ .\h\error.hxx .\h\fat.hxx .\h\handle.hxx .\h\header.hxx .\h\msf.hxx \
+ .\h\msffunc.hxx .\h\page.hxx .\h\psstream.hxx .\h\ref.hxx \
+ .\h\sstream.hxx .\h\storage.h .\h\storagep.h .\h\vect.hxx \
+ .\h\vectfunc.hxx .\h\wchar.h .\mread.hxx msfhead.cxx
+
+storage.obj storage.lst: storage.cxx $(CRTINC)\memory.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ .\h\dfentry.hxx .\h\dfexcept.hxx .\h\dfmsp.hxx .\h\ref.hxx \
+ .\h\storage.h .\h\storagep.h .\h\wchar.h
+
+time16.obj time16.lst: time16.cxx $(CRTINC)\assert.h $(CRTINC)\dos.h \
+ $(CRTINC)\malloc.h $(CRTINC)\memory.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(CRTINC)\time.h .\h\chinst.hxx .\h\dfexcept.hxx .\h\dfmsp.hxx \
+ .\h\difat.hxx .\h\dir.hxx .\h\docfilep.hxx .\h\entry.hxx \
+ .\h\error.hxx .\h\fat.hxx .\h\funcs.hxx .\h\header.hxx .\h\msf.hxx \
+ .\h\ole.hxx .\h\page.hxx .\h\pdocfile.hxx .\h\piter.hxx \
+ .\h\publicdf.hxx .\h\ref.hxx .\h\revert.hxx .\h\storage.h \
+ .\h\storagep.h .\h\vect.hxx .\h\wchar.h .\time16.hxx exphead.cxx
+
+time16.obj time16.lst: time16.hxx $(CRTINC)\time.h
+
+vect.obj vect.lst: vect.cxx $(CRTINC)\assert.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h .\h\dfmsp.hxx .\h\difat.hxx \
+ .\h\dir.hxx .\h\error.hxx .\h\fat.hxx .\h\header.hxx .\h\msf.hxx \
+ .\h\page.hxx .\h\ref.hxx .\h\storage.h .\h\storagep.h .\h\vect.hxx \
+ .\h\vectfunc.hxx .\h\wchar.h msfhead.cxx
+
+wcscat.obj wcscat.lst: wcscat.c $(CRTINC)\stdarg.h $(CRTINC)\stdlib.h \
+ .\h\wchar.h
+
+wcslen.obj wcslen.lst: wcslen.c $(CRTINC)\stdarg.h $(CRTINC)\stdlib.h \
+ .\h\wchar.h
+
+wcsnicmp.obj wcsnicmp.lst: wcsnicmp.c $(CRTINC)\stdarg.h $(CRTINC)\stdlib.h \
+ .\h\wchar.h
+
diff --git a/private/ole32/stg/ref/dffuncs.cxx b/private/ole32/stg/ref/dffuncs.cxx
new file mode 100644
index 000000000..d11dde9ab
--- /dev/null
+++ b/private/ole32/stg/ref/dffuncs.cxx
@@ -0,0 +1,160 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992
+//
+// File: dffuncs.cxx
+//
+// Contents: Private support functions for the DocFile code
+//
+// Methods: StartMS
+// DeleteContents
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+
+#include <iter.hxx>
+#include <sstream.hxx>
+
+
+
+//+--------------------------------------------------------------
+//
+// Method: CDocFile::DeleteContents, public
+//
+// Synopsis: Deletes all entries in a DocFile recursing on entries
+// with children
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+SCODE CDocFile::DeleteContents(void)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::DeleteContents()\n"));
+ sc = _stgh.DestroyEntry(NULL);
+ olDebugOut((DEB_ITRACE, "Out CDocFile::DeleteContents\n"));
+ return sc;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::CopyTo, public
+//
+// Synopsis: Copies the contents of one DocFile to another
+//
+// Arguments: [pdfTo] - Destination DocFile
+// [dwFlags] - Control flags
+// [snbExclude] - Partial instantiation list
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+SCODE CDocFile::CopyTo(CDocFile *pdfTo,
+ DWORD dwFlags,
+ SNBW snbExclude)
+{
+ PDocFileIterator *pdfi;
+ SIterBuffer ib;
+ PSStream *psstFrom, *psstTo;
+ CDocFile *pdfFromChild, *pdfToChild;
+ DFLUID dlLUID = DF_NOLUID;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::CopyTo:%p(%p, %lX, %p)\n", this,
+ pdfTo, dwFlags, snbExclude));
+ olChk(GetIterator(&pdfi));
+ for (;;)
+ {
+ if (FAILED(pdfi->BufferGetNext(&ib)))
+ break;
+
+ switch(REAL_STGTY(ib.type))
+ {
+ case STGTY_STORAGE:
+ // Embedded DocFile, create destination and recurse
+
+ olChkTo(EH_pwcsName, GetDocFile(&ib.dfnName, DF_READ, ib.type,
+ (PDocFile **)&pdfFromChild));
+ // Destination must be a direct docfile
+ olChkTo(EH_Reserve, pdfTo->CreateDocFile(&ib.dfnName, DF_WRITE,
+ dlLUID, ib.type,
+ (PDocFile **)&pdfToChild));
+ if (dwFlags & CDF_EXACT)
+ pdfToChild->CopyTimesFrom(pdfFromChild);
+
+ CLSID clsid;
+ olChkTo(EH_Create, pdfFromChild->GetClass(&clsid));
+ olChkTo(EH_Create, pdfToChild->SetClass(clsid));
+
+ DWORD grfStateBits;
+ olChkTo(EH_Create, pdfFromChild->GetStateBits(&grfStateBits));
+ olChkTo(EH_Create, pdfToChild->SetStateBits(grfStateBits,
+ 0xffffffff));
+
+
+ if ((dwFlags & CDF_ENTRIESONLY) == 0 &&
+ !(snbExclude && NameInSNB(&ib.dfnName, snbExclude) ==
+ S_OK))
+ olChkTo(EH_Create,
+ pdfFromChild->CopyTo(pdfToChild, dwFlags, NULL));
+
+ pdfFromChild->Release();
+ pdfToChild->Release();
+ break;
+
+ case STGTY_STREAM:
+ olChkTo(EH_pwcsName, GetStream(&ib.dfnName, DF_READ,
+ ib.type, &psstFrom));
+ // Destination must be a direct docfile
+ olChkTo(EH_Reserve,
+ pdfTo->CreateStream(&ib.dfnName, DF_WRITE, dlLUID,
+ &psstTo));
+ if (dwFlags & CDF_EXACT)
+ psstTo->CopyTimesFrom(psstFrom);
+
+
+ if ((dwFlags & CDF_ENTRIESONLY) == 0 &&
+ !(snbExclude && NameInSNB(&ib.dfnName, snbExclude) ==
+ S_OK))
+ olChkTo(EH_Create, CopySStreamToSStream(psstFrom, psstTo));
+
+ psstFrom->Release();
+ psstTo->Release();
+ break;
+
+ default:
+ olAssert(!aMsg("Unknown entry type in CDocFile::CopyTo"));
+ break;
+ }
+ }
+ pdfi->Release();
+ olDebugOut((DEB_ITRACE, "Out CDocFile::CopyTo\n"));
+ return S_OK;
+
+ EH_Create:
+ if (REAL_STGTY(ib.type))
+ pdfToChild->Release();
+ else
+ psstTo->Release();
+ olAssert(&ib.dfnName);
+ olVerSucc(pdfTo->DestroyEntry(&ib.dfnName, TRUE));
+ goto EH_Get;
+ EH_Reserve:
+ EH_Get:
+ if (REAL_STGTY(ib.type))
+ pdfFromChild->Release();
+ else
+ psstFrom->Release();
+ EH_pwcsName:
+ pdfi->Release();
+ EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/ref/dfhead.cxx b/private/ole32/stg/ref/dfhead.cxx
new file mode 100644
index 000000000..0e8dbc048
--- /dev/null
+++ b/private/ole32/stg/ref/dfhead.cxx
@@ -0,0 +1,31 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dfhead.cxx
+//
+// Contents: Precompiled headers
+//
+//--------------------------------------------------------------------------
+
+
+#include <malloc.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <ref.hxx>
+
+
+#include <msf.hxx>
+
+#include <dfexcept.hxx>
+#include <docfilep.hxx>
+#include <publicdf.hxx>
+#include <psstream.hxx>
+#include <cdocfile.hxx>
+#include <dffuncs.hxx>
+#include <funcs.hxx>
+#include <piter.hxx>
diff --git a/private/ole32/stg/ref/dfiter.cxx b/private/ole32/stg/ref/dfiter.cxx
new file mode 100644
index 000000000..7fdf98dff
--- /dev/null
+++ b/private/ole32/stg/ref/dfiter.cxx
@@ -0,0 +1,50 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: dfiter.cxx
+//
+// Contents: Implementations of CDocFile iterator methods
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+
+#include <msfiter.hxx>
+#include <iter.hxx>
+
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::GetIterator, public
+//
+// Synopsis: Gets a new iterator
+//
+// Arguments: [ppdfi] - Iterator object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdfi]
+//
+//---------------------------------------------------------------
+
+SCODE CDocFile::GetIterator(PDocFileIterator **ppdfi)
+{
+ CDocFileIterator *pdfi;
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::GetIterator(%p)\n", ppdfi));
+ olMem(pdfi = new CDocFileIterator);
+ olChkTo(EH_pdfi, pdfi->Init(&_stgh));
+ *ppdfi = pdfi;
+ olDebugOut((DEB_ITRACE, "Out CDocFile::GetIterator => %p\n", *ppdfi));
+ return S_OK;
+
+EH_pdfi:
+ delete pdfi;
+EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/ref/dfstream.cxx b/private/ole32/stg/ref/dfstream.cxx
new file mode 100644
index 000000000..19fa87dce
--- /dev/null
+++ b/private/ole32/stg/ref/dfstream.cxx
@@ -0,0 +1,108 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: dfstream.cxx
+//
+// Contents: Implementations of CDocFile stream methods
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+
+#include <sstream.hxx>
+
+//+--------------------------------------------------------------
+//
+// Method: CDocFile::CreateStream, public
+//
+// Synopsis: Creates a named stream in a DocFile
+//
+// Arguments: [pwcsName] - Name of the stream
+// [df] - Transactioning flags
+// [dlSet] - LUID to set or DF_NOLUID
+// [dwType] - Type of entry to be created
+// [ppsstStream] - Pointer to storage for the stream pointer
+//
+// Returns: Appropriate error code
+//
+// Modifies: [ppsstStream]
+//
+//---------------------------------------------------------------
+
+
+SCODE CDocFile::CreateStream(CDfName const *pdfn,
+ DFLAGS const df,
+ DFLUID dlSet,
+ PSStream **ppsstStream)
+{
+ SCODE sc;
+ CDirectStream *pstm;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::CreateStream("
+ "%ws, %X, %lu, %p)\n",
+ pdfn, df, dlSet, ppsstStream));
+ UNREFERENCED_PARM(df);
+
+ if (dlSet == DF_NOLUID)
+ dlSet = CDirectStream::GetNewLuid();
+ olMem(pstm = new CDirectStream(dlSet));
+
+ olChkTo(EH_pstm, pstm->Init(&_stgh, pdfn, TRUE));
+
+ *ppsstStream = pstm;
+ olDebugOut((DEB_ITRACE, "Out CDocFile::CreateStream => %p\n",
+ *ppsstStream));
+ return S_OK;
+
+EH_pstm:
+ delete pstm;
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Method: CDocFile::GetStream, public
+//
+// Synopsis: Retrieves an existing stream from a DocFile
+//
+// Arguments: [pwcsName] - Name of the stream
+// [df] - Transactioning flags
+// [dwType] - Type of entry
+// [ppsstStream] - Pointer to storage for the stream pointer
+//
+// Returns: Appropriate error code
+//
+// Modifies: [ppsstStream]
+//
+//---------------------------------------------------------------
+
+
+SCODE CDocFile::GetStream(CDfName const *pdfn,
+ DFLAGS const df,
+ PSStream **ppsstStream)
+{
+ SCODE sc;
+ CDirectStream *pstm;
+
+ olDebugOut((DEB_ITRACE, "In CDocFile::GetStream(%ws, %X, %p)\n",
+ pdfn, df, ppsstStream));
+ UNREFERENCED_PARM(df);
+
+ DFLUID dl = CDirectStream::GetNewLuid();
+ olMem(pstm = new CDirectStream(dl));
+
+ olChkTo(EH_pstm, pstm->Init(&_stgh, pdfn, FALSE));
+ *ppsstStream = pstm;
+ olDebugOut((DEB_ITRACE, "Out CDocFile::GetStream => %p\n",
+ *ppsstStream));
+ return S_OK;
+
+EH_pstm:
+ delete pstm;
+EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/ref/difat.cxx b/private/ole32/stg/ref/difat.cxx
new file mode 100644
index 000000000..1f3e0fa95
--- /dev/null
+++ b/private/ole32/stg/ref/difat.cxx
@@ -0,0 +1,439 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: difat.cxx
+//
+// Contents: Double Indirected Fat Code
+//
+// Classes: None.
+//
+// Functions:
+//
+//--------------------------------------------------------------------------
+
+#include <msfhead.cxx>
+
+
+#include <difat.hxx>
+#include <mread.hxx>
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::CDIFat, public
+//
+// Synopsis: CDIFat constructor
+//
+// Arguments: [pmsParent] -- Pointer to parent CMStream
+//
+//--------------------------------------------------------------------------
+
+CDIFat::CDIFat(USHORT cbSector)
+: _pmsParent(NULL),
+ _fv(SIDDIF,
+ cbSector / sizeof(SECT),
+ (cbSector / sizeof(SECT)) - 1)
+{
+ msfDebugOut((DEB_TRACE,"In CDIFat constructor\n"));
+ _cfsTable = 0;
+ msfDebugOut((DEB_TRACE,"Out CDIFat constructor\n"));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDIFat::Empty, public
+//
+// Synopsis: Empty all the control structures of this instance
+//
+// Arguments: None.
+//
+// Returns: void.
+//
+//----------------------------------------------------------------------------
+
+void CDIFat::Empty(void)
+{
+ _fv.Empty();
+ _pmsParent = NULL;
+ _cfsTable = 0;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CIDFat::Flush, private
+//
+// Synopsis: Flush a sector to disk
+//
+// Arguments: [oSect] -- Indicated which sector to flush
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Write sector up to parent mstream.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE CDIFat::Flush(void)
+{
+ return _fv.Flush();
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::GetFatSect, public
+//
+// Synopsis: Given an offset into the Fat chain, return the sector
+// value for that FatSect.
+//
+// Arguments: [oSect] -- offset in Fat chain
+//
+// Returns: Sector value of FatSect.
+//
+// Algorithm: If sector is stored in the header, retrieve it from
+// there.
+// If not, retrieve it from the FatVector.
+//
+//--------------------------------------------------------------------------
+
+SCODE CDIFat::GetFatSect(const FSINDEX oSect, SECT *psect)
+{
+ SCODE sc = S_OK;
+ SECT sectReturn;
+
+ msfDebugOut((DEB_TRACE,"In CDIFat::GetFatSect(%lu)\n",oSect));
+ if (oSect < CSECTFAT)
+ {
+ msfDebugOut((DEB_ITRACE,"Getting sect from header\n"));
+ sectReturn = _pmsParent->GetHeader()->GetFatSect(oSect);
+ }
+ else
+ {
+ FSINDEX ipfs;
+ FSOFFSET isect;
+
+ SectToPair(oSect,&ipfs,&isect);
+
+ msfAssert(ipfs < _cfsTable);
+
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+ sectReturn = pfs->GetSect(isect);
+ _fv.ReleaseTable(ipfs);
+ }
+
+ msfDebugOut((DEB_TRACE,"Out CDIFat::GetFatSect(%lu)=>%lu\n",oSect,sectReturn));
+ *psect = sectReturn;
+
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::SetFatSect, public
+//
+// Synopsis: Given an offset into the Fat chain, set the sector
+// value.
+//
+// Arguments: [oSect] -- Offset into fat chain
+// [sect] -- New sector value for that offset.
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: If the sector is stored in the header, set it and
+// flush the header.
+// Otherwise, if the sector will not fit in the current
+// CFatVector, resize it.
+// Set the sector in the FatVector and flush it.
+//
+//--------------------------------------------------------------------------
+
+SCODE CDIFat::SetFatSect(const FSINDEX oSect, const SECT sect)
+{
+ msfDebugOut((DEB_TRACE,"In CDIFat::SetFatSect(%lu,%lu)\n",oSect,sect));
+ SCODE sc = S_OK;
+
+ if (oSect < CSECTFAT)
+ {
+ msfDebugOut((DEB_ITRACE,"Setting sect in header: %lu, %lu\n",oSect,sect));
+ _pmsParent->GetHeader()->SetFatSect(oSect, sect);
+ }
+ else
+ {
+ FSINDEX ipfs;
+ FSOFFSET isect;
+
+ SectToPair(oSect,&ipfs,&isect);
+ if (ipfs >= _cfsTable)
+ {
+ msfChk(Resize(_cfsTable + 1));
+ }
+
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_DIRTY, &pfs));
+
+ pfs->SetSect(isect, sect);
+ _fv.ReleaseTable(ipfs);
+
+ msfDebugOut((DEB_TRACE,"In CDIFat::SetFatSect(%lu,%lu)\n",oSect,sect));
+ }
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::GetSect, public
+//
+// Synopsis: Given an offset into the DIFat chain, return the
+// sector value
+//
+// Arguments: [oSect] -- Offset into DIFat chain.
+//
+// Returns: Sector value for given offset.
+//
+// Algorithm: Retrieve the information from the NextFat fields of
+// the CFatVector
+//
+//--------------------------------------------------------------------------
+
+SCODE CDIFat::GetSect(const FSINDEX oSect, SECT *psect)
+{
+ SCODE sc = S_OK;
+
+ SECT sectReturn;
+
+ msfDebugOut((DEB_TRACE,"In CDIFat::GetSect(%lu)\n",oSect));
+ msfAssert(oSect < _cfsTable);
+
+ if (oSect == 0)
+ {
+ sectReturn = _pmsParent->GetHeader()->GetDifStart();
+ }
+ else
+ {
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(oSect - 1, FB_NONE, &pfs));
+
+ sectReturn = pfs->GetNextFat(_fv.GetSectTable());
+ _fv.ReleaseTable(oSect - 1);
+ }
+
+ msfDebugOut((DEB_TRACE,"Out CDIFat::GetSect(%lu)=>%lu\n",oSect,sectReturn));
+ *psect = sectReturn;
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::Init, public
+//
+// Synopsis: Init function for previously stored DIFat.
+//
+// Arguments: [cFatSect] -- Length of DIFat in sectors
+//
+// Returns: S_OK if call completed properly.
+//
+// Algorithm: *Finish This*
+//
+//--------------------------------------------------------------------------
+
+SCODE CDIFat::Init(CMStream MSTREAM_NEAR * pmsParent, const FSINDEX cFatSect)
+{
+ msfDebugOut((DEB_TRACE,"In CDIFat::Init(%lu)\n",cFatSect));
+ SCODE sc;
+
+ _pmsParent = pmsParent;
+
+ msfChk(_fv.Init(_pmsParent, cFatSect));
+
+ _cfsTable = cFatSect;
+
+ msfDebugOut((DEB_TRACE,"Out CDIFat::Init(%lu)\n",cFatSect));
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::InitConvert, public
+//
+// Synopsis: Init function for conversion
+//
+// Arguments: [sectMax] -- Last used sector in existing file
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: *Finish This*
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE CDIFat::InitConvert(CMStream MSTREAM_NEAR *pmsParent, SECT sectMax)
+{
+ msfDebugOut((DEB_TRACE,"In CDIFat::InitConvert(%lu)\n",sectMax));
+ SCODE sc;
+
+ _pmsParent = pmsParent;
+
+ USHORT cbSector = _pmsParent->GetSectorSize();
+ FSOFFSET csectPer = cbSector / sizeof(SECT);
+
+ FSINDEX csectFat = 0;
+ FSINDEX csectFatLast;
+
+ FSINDEX csectDif = 0;
+ FSINDEX csectDifLast;
+ do
+ {
+ //Number of fat sectors needed to represent:
+ // Number of Data Sectors (sectMax) +
+ // Number of Fat Sectors (csectFat) +
+ // Number of DIF sectors (csectDif) +
+ // Number of Directory Sectors (1)
+
+ //We must use a loop here, since the fat must be large
+ // enough to represent itself and the DIFat. See
+ // CFat::InitConvert for a more lengthy discussion of
+ // this method.
+
+ csectFatLast = csectFat;
+
+ csectFat = (sectMax + csectFatLast + csectDif + 1 + csectPer - 1) /
+ csectPer;
+
+ csectDifLast = csectDif;
+
+ if (csectFat < CSECTFAT)
+ {
+ csectDif = 0;
+ }
+ else
+ {
+ FSOFFSET ciSect;
+
+ SectToPair(csectFat, &csectDif, &ciSect);
+ csectDif++;
+ }
+ }
+ while ((csectDif != csectDifLast) || (csectFat != csectFatLast));
+
+
+ _cfsTable = csectDif;
+
+ msfChk(_fv.Init(_pmsParent, _cfsTable));
+
+ _pmsParent->GetHeader()->SetDifLength(_cfsTable);
+
+ if (_cfsTable > 0)
+ {
+ _pmsParent->GetHeader()->SetDifStart(sectMax);
+
+ FSINDEX i;
+ for (i = 0; i < _cfsTable; i++)
+ {
+ CFatSect *pfs;
+
+ msfChk(_fv.GetTable(i, FB_NEW, &pfs));
+ _fv.SetSect(i, sectMax);
+
+ sectMax++;
+ pfs->SetNextFat(_fv.GetSectTable(),sectMax);
+ _fv.ReleaseTable(i);
+ }
+ }
+
+ msfDebugOut((DEB_TRACE,"Out CDIFat::InitConvert()\n"));
+
+Err:
+ return sc;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::Resize, private
+//
+// Synopsis: Resize an existing DIFat.
+//
+// Arguments: [fsiSize] -- New size for object
+//
+// Returns: Nothing right now.
+//
+// Algorithm: *Finish This*
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE CDIFat::Resize(FSINDEX fsiSize)
+{
+ msfDebugOut((DEB_TRACE,"In CDIFat::Resize(%lu)\n",fsiSize));
+ msfAssert(fsiSize == _cfsTable + 1);
+
+ SCODE sc;
+
+ msfChk(_fv.Resize(fsiSize));
+ ULONG ipfs;
+ ipfs = fsiSize - 1;
+
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NEW, &pfs));
+
+ FSINDEX csect;
+ csect = _cfsTable;
+ _cfsTable = fsiSize;
+
+ SECT sectNew;
+
+ msfChk(_pmsParent->GetFat()->GetFree(1, &sectNew));
+ msfChk(_pmsParent->GetFat()->SetNext(sectNew, DIFSECT));
+
+
+
+ _fv.SetSect(ipfs, sectNew);
+ _fv.ReleaseTable(ipfs);
+
+ if (csect == 0)
+ {
+ _pmsParent->GetHeader()->SetDifStart(sectNew);
+ }
+ else
+ {
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(csect - 1, FB_DIRTY, &pfs));
+
+ pfs->SetNextFat(_fv.GetSectTable(),sectNew);
+ _fv.ReleaseTable(csect - 1);
+ }
+
+ _pmsParent->GetHeader()->SetDifLength(_cfsTable);
+
+ msfDebugOut((DEB_TRACE,"Out CDIFat::Resize(%lu)\n",fsiSize));
+
+Err:
+ return sc;
+}
+
+
+
+
diff --git a/private/ole32/stg/ref/dir.cxx b/private/ole32/stg/ref/dir.cxx
new file mode 100644
index 000000000..dd95bb482
--- /dev/null
+++ b/private/ole32/stg/ref/dir.cxx
@@ -0,0 +1,1045 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: dir.cxx
+//
+// Contents: Directory Functions
+//
+//---------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+
+#include <dirfunc.hxx>
+#include <mread.hxx>
+
+#define DEB_DIR (DEB_ITRACE | 0x00040000)
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::KillStream, public
+//
+// Synopsis: Eliminate a given chain
+//
+// Arguments: [sectStart] -- Beginning of chain to eliminate
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: *Finish This*
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline SCODE MSTREAM_NEAR CMStream::KillStream(SECT sectStart, ULONG ulSize)
+{
+ CFat *pfat;
+
+ pfat = (ulSize < MINISTREAMSIZE) ?&_fatMini: &_fat;
+
+ return pfat->SetChainLength(sectStart, 0);
+}
+
+
+
+inline CDirEntry* DIR_NEAR GetNewDirEntryArray(USHORT cbSector)
+{
+ CDirEntry *temp;
+ DIROFFSET cdeEntries = cbSector / sizeof(CDirEntry);
+
+ temp = new CDirEntry[cdeEntries];
+ return temp;
+}
+
+
+inline void DIR_NEAR CDirEntry::Init(MSENTRYFLAGS mse)
+{
+ msfAssert(sizeof(CDirEntry) == DIRENTRYSIZE);
+
+ msfAssert(mse <= 0xff);
+ _mse = (BYTE) mse;
+ _bflags = 0;
+
+ _dfn.Set((WORD)0, (BYTE *)NULL);
+ _sidLeftSib = _sidRightSib = _sidChild = NOSTREAM;
+
+ if (STORAGELIKE(_mse))
+ {
+ _clsId = IID_NULL;
+ _dwUserFlags = 0;
+ }
+ if (STREAMLIKE(_mse))
+ {
+ _sectStart = ENDOFCHAIN;
+ _ulSize = 0;
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirEntry::CDirEntry, public
+//
+// Synopsis: Constructor for CDirEntry class
+//
+// Effects:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+DIR_NEAR CDirEntry::CDirEntry()
+{
+ msfAssert(sizeof(CDirEntry) == DIRENTRYSIZE);
+ Init(STGTY_INVALID);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirSect::Init, public
+//
+// Synopsis: Initializer for directory sectors
+//
+// Arguments: [cdeEntries] -- Number of DirEntries in the sector
+//
+// Returns: S_OK if call completed OK.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirSect::Init(USHORT cbSector)
+{
+ msfDebugOut((DEB_DIR,"Allocating sector with size %u\n",cbSector));
+
+ DIROFFSET cdeEntries = cbSector / sizeof(CDirEntry);
+
+ for (ULONG i = 0; i < cdeEntries; i++)
+ {
+ _adeEntry[i].Init(STGTY_INVALID);
+ }
+
+ return S_OK;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectory::CDirectory
+//
+// Synopsis: Default constructor
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+DIR_NEAR CDirectory::CDirectory(USHORT cbSector)
+ : _pmsParent(NULL),
+ _dv(cbSector)
+{
+ _cdsTable = _cdeEntries = 0;
+ _sidFirstFree = 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirectory::Empty, public
+//
+// Synopsis: Empty all the control structures of this instance
+//
+// Arguments: None.
+//
+// Returns: void.
+//
+//----------------------------------------------------------------------------
+
+void CDirectory::Empty(void)
+{
+ _dv.Empty();
+ _pmsParent = NULL;
+ _cdsTable = 0;
+ _cdeEntries = 0;
+ _sidFirstFree = 0;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::GetFree, public
+//
+// Synposis: Locates a free directory entry
+//
+// Arguments: None.
+//
+// Returns: Stream ID of free directory entry
+//
+// Algorithm: Do a linear search of all available directories.
+// If no free spot is found, resize the directory and
+// perform the search again.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::GetFree(SID * psid)
+{
+ msfDebugOut((DEB_DIR,"In CDirectory::GetFree()\n"));
+
+ SCODE sc = S_OK;
+ SID sidRet = NOSTREAM;
+ CDirSect * pds;
+
+ DIRINDEX ipdsStart;
+ DIROFFSET ideStart;
+
+ SidToPair(_sidFirstFree, &ipdsStart, &ideStart);
+ while (TRUE)
+ {
+ for (DIRINDEX ipds = ipdsStart; ipds < _cdsTable; ipds++)
+ {
+ msfChk(_dv.GetTable(ipds, FB_NONE, &pds));
+ for (DIROFFSET ide = ideStart; ide < _cdeEntries; ide++)
+ {
+ if (pds->GetEntry(ide)->IsFree())
+ {
+ msfDebugOut((DEB_ITRACE,"GetFree found sid %lu\n",
+ PairToSid(ipds,ide)));
+
+ *psid = PairToSid(ipds, ide);
+ _sidFirstFree = *psid + 1;
+ _dv.ReleaseTable(ipds);
+ return S_OK;
+ }
+ }
+ _dv.ReleaseTable(ipds);
+ ideStart = 0;
+ }
+ ipdsStart = ipds;
+ msfChk(Resize(_cdsTable+1));
+ }
+
+ Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::FindGreaterEntry
+//
+// Synopsis: finds next entry (for iteration)
+//
+// Arguments: [sidStart] -- child sid to start looking
+// [pdfn] -- previous entry name
+// [psidResult] -- place holder for returned sid
+//
+// Requires: sidStart != NOSTREAM
+//
+// Returns: S_OK, STG_E_NOMOREFILES, or other error
+//
+// Modifies: psidResult
+//
+// Algorithm: Iterate by returning the sid that has a name larger
+// than the given name.
+//
+// Notes: This method is called recursively
+//
+//--------------------------------------------------------------------------
+
+SCODE CDirectory::FindGreaterEntry(SID sidStart, CDfName const *pdfn, SID *psidResult)
+{
+ SCODE sc;
+ CDirEntry *pde;
+ msfAssert(sidStart != NOSTREAM);
+
+ msfChk(GetDirEntry(sidStart, FB_NONE, &pde));
+
+ int iCmp;
+ iCmp = NameCompare(pdfn, pde->GetName());
+
+ if (iCmp < 0)
+ {
+ // Since the last name returned is less than this name,
+ // the sid to return must either be to our left or this sid
+
+ SID sidLeft = pde->GetLeftSib();
+
+ // We can't hold onto sidStart as we recurse, (because we'll ask for
+ // a page each time we recurse)
+
+ ReleaseEntry(sidStart);
+
+ if ((sidLeft == NOSTREAM) ||
+ (sc = FindGreaterEntry(sidLeft, pdfn, psidResult)) == STG_E_NOMOREFILES)
+ {
+ // There was no left child with a name greater than pdfn, so
+ // we return ourself
+
+ *psidResult = sidStart;
+ sc = S_OK;
+ }
+ }
+ else
+ {
+ // The last name returned is greater than this one, so we've already
+ // returned this sidStart. Look in the right subtree.
+
+ SID sidRight = pde->GetRightSib();
+
+ // We can't hold onto sidStart as we recurse, (because we'll ask for
+ // a page each time we recurse)
+
+ ReleaseEntry(sidStart);
+
+ if (sidRight == NOSTREAM)
+ sc = STG_E_NOMOREFILES;
+ else
+ sc = FindGreaterEntry(sidRight, pdfn, psidResult);
+ }
+Err:
+ return(sc);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectory::SetStart, public
+//
+// Synopsis: Set starting sector for a dir entry
+//
+// Arguments: [sid] -- SID of entry to be modified
+// [sect] -- New starting sector for entry
+//
+// Returns: SID of modified entry
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::SetStart(const SID sid, const SECT sect)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+
+ pde->SetStart(sect);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SetChild, public
+//
+// Synposis: Set the child SID of an entry
+//
+// Effects: Modifies a single directory entry. Causes a one sector
+// stream write.
+//
+// Arguments: [sid] -- Stream ID of entry to be set
+// [sidChild] -- SID of first child of this stream
+//
+// Returns: SID of modified entry
+//
+// Algorithm: Change child field on entry, then write to stream.
+//
+//---------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::SetChild(const SID sid, const SID sidChild)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+
+ pde->SetChild(sidChild);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SetSize, public
+//
+// Synposis: Set the size of an entry
+//
+// Effects: Modifies a single directory entry. Causes a one sector
+// stream write.
+//
+// Arguments: [sid] -- Stream ID of entry to be set
+// [cbSize] -- Size
+//
+// Returns: SID of modified entry
+//
+// Algorithm: Change size field on entry, then write to stream.
+//
+//---------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::SetSize(const SID sid, const ULONG cbSize)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+
+ pde->SetSize(cbSize);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SetTime, public
+//
+// Synposis: Set the time of an entry
+//
+// Effects: Modifies a single directory entry. Causes a one sector
+// stream write.
+//
+// Arguments: [sid] -- Stream ID of entry to be set
+// [tt] - WT_*
+// [nt] - New time
+//
+// Returns: SID of modified entry
+//
+// Algorithm: Change time field on entry, then write to stream.
+//
+//---------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::SetTime(const SID sid, WHICHTIME tt, TIME_T nt)
+{
+ SCODE sc;
+
+ CDirEntry *pde;
+
+ // We don't support ACCESS times, so just ignore sets
+ if (tt == WT_ACCESS)
+ return S_OK;
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+ pde->SetTime(tt, nt);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SetFlags, public
+//
+// Synposis: Set the flags of an entry
+//
+// Effects: Modifies a single directory entry. Causes a one sector
+// stream write.
+//
+// Arguments: [sid] -- Stream ID of entry to be set
+// [mse] - New flags
+//
+// Returns: Status code
+//
+// Algorithm: Change Luid field on entry, then write to stream.
+//
+//---------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::SetFlags(const SID sid, const MSENTRYFLAGS mse)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+ pde->SetFlags(mse);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SetClassId, public
+//
+// Synposis: Set the class ID of an entry
+//
+// Effects: Modifies a single directory entry. Causes a one sector
+// stream write.
+//
+// Arguments: [sid] -- Stream ID of entry to be set
+// [cls] - Class ID
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::SetClassId(const SID sid, const GUID cls)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+ pde->SetClassId(cls);
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SetUserFlags, public
+//
+// Synposis: Set the user flags of an entry
+//
+// Effects: Modifies a single directory entry. Causes a one sector
+// stream write.
+//
+// Arguments: [sid] -- Stream ID of entry to be set
+// [dwUserFlags] - Flags
+// [dwMask] - Mask
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::SetUserFlags(SID const sid,
+ DWORD dwUserFlags,
+ DWORD dwMask)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+ pde->SetUserFlags(dwUserFlags, dwMask);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::resize, private
+//
+// Synposis: Resize a directory.
+//
+// Effects: Reallocates space for directory table, copying over
+// old pointers as necessary. Any new tables needed are
+// created here.
+//
+// Arguments: [uNewsize] -- New size for Directory
+//
+// Returns: void
+//
+// Algorithm: Allocate a new array of pointers of the necessary size.
+// Then, copy over all pointers from old array and allocate
+// new CDirSects for all new tables.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::Resize(DIRINDEX uNewsize)
+{
+ msfDebugOut((DEB_DIR,"In CDirectory::Resize(%i)\n",uNewsize));
+ SCODE sc;
+
+ if (uNewsize == _cdsTable) return S_OK;
+
+ SECT sect;
+ //GetESect call will make sure we have enough Fat space.
+ msfChk(_pmsParent->GetESect(SIDDIR, uNewsize - 1, &sect));
+
+ msfChk(_pmsParent->SetSize());
+
+ msfChk(_dv.Resize(uNewsize));
+
+ ULONG ipds;
+ for (ipds = _cdsTable; ipds < uNewsize; ipds++)
+ {
+ CDirSect *pds;
+ msfChk(_dv.GetTable(ipds, FB_NEW, &pds));
+
+ SECT sect;
+ msfChk(_pmsParent->GetESect(SIDDIR, ipds, &sect));
+ _dv.SetSect(ipds, sect);
+ _dv.ReleaseTable(ipds);
+ }
+
+ _cdsTable = uNewsize;
+
+ Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::Init, public
+//
+// Synposis: Sets up a Directory instance and reads in all tables
+// from the stream
+//
+// Arguments: [cSect] -- Number of sectors in directory
+//
+// Returns: S_OK if call completed OK.
+// STG_E_READFAULT if not enough bytes were read for
+// a DirSector
+// Error code of read if read returned an error.
+//
+// Algorithm: Create array to hold appropriate number of tables.
+// Read in each table from disk.
+//
+//---------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::Init(
+ CMStream MSTREAM_NEAR *pmsParent,
+ DIRINDEX cSect)
+{
+ msfDebugOut((DEB_DIR,"In CDirectory::Init(%lu)\n",cSect));
+ SCODE sc;
+
+ _pmsParent = pmsParent;
+
+ _cdeEntries = _pmsParent->GetSectorSize() / sizeof(CDirEntry);
+
+ msfChk(_dv.Init(_pmsParent, cSect));
+
+ _cdsTable = cSect;
+
+ msfDebugOut((DEB_DIR,"Out CDirectory::Init()\n"));
+
+ Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::InitNew, public
+//
+// Synposis: Sets up a new Directory instance for a new Mstream
+//
+// Arguments: None.
+//
+// Returns: S_OK if call completed OK.
+// STG_E_WRITEFAULT if not enough bytes were written.
+// Error code of write if write failed.
+//
+// Algorithm: Write initial DirSector to disk.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::InitNew(CMStream MSTREAM_NEAR *pmsParent)
+{
+ SCODE sc;
+ CDfName const dfnRoot(L"Root Entry");
+
+ msfDebugOut((DEB_DIR,"In CDirectory::setupnew()\n"));
+ _pmsParent = pmsParent;
+
+ _cdeEntries = _pmsParent->GetSectorSize() / sizeof(CDirEntry);
+
+ msfChk(_dv.Init(_pmsParent, 1));
+
+ CDirSect *pds;
+
+ msfChk(_dv.GetTable(0, FB_NEW, &pds));
+ _dv.SetSect(0, _pmsParent->GetHeader()->GetDirStart());
+ _dv.ReleaseTable(0);
+
+ _cdsTable = 1;
+
+ SID sidRoot;
+
+ msfChk(GetFree(&sidRoot));
+ CDirEntry *pdeTemp;
+
+ msfChk(GetDirEntry(sidRoot, FB_DIRTY, &pdeTemp));
+ pdeTemp->Init(STGTY_ROOT);
+
+ msfAssert(sidRoot == SIDROOT);
+
+ pdeTemp->SetName(&dfnRoot);
+
+ ReleaseEntry(sidRoot);
+
+ msfDebugOut((DEB_DIR,"Exiting CDirectory::setupnew()\n"));
+
+ Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectory::CreateEntry, public
+//
+// Synopsis: Create a new directory entry
+//
+// Arguments: [sidParent] -- SID of parent for new entry
+// [pwcsName] -- Name of new entry
+// [mef] -- Flags for new entry
+// [psidNew] -- Return location for new SID
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Search directory for entry of the same name. If one
+// is found, return STG_E_FILEALREADYEXISTS.
+// If not, create a new entry and return its SID.
+//
+//--------------------------------------------------------------------------
+
+
+SCODE DIR_NEAR CDirectory::CreateEntry(
+ SID sidParent,
+ CDfName const *pdfn,
+ MSENTRYFLAGS mef,
+ SID *psidNew)
+{
+ SCODE sc;
+ SID sidNew;
+ CDirEntry *pdeNew;
+ SEntryBuffer eb;
+
+ sc = IsEntry(sidParent, pdfn, &eb);
+ if (sc != STG_E_FILENOTFOUND)
+ {
+ if (SUCCEEDED(sc))
+ sc = STG_E_FILEALREADYEXISTS;
+
+ return(sc);
+ }
+
+ // Allocate new sid
+
+ msfChk(GetFree(psidNew));
+ sidNew = *psidNew;
+
+ msfChk(GetDirEntry(sidNew, FB_DIRTY, &pdeNew));
+
+ // Initialize new entry
+
+ pdeNew->Init(mef);
+
+ TIME_T timetemp;
+ DfGetTOD(&timetemp);
+
+ pdeNew->SetTime(WT_CREATION, timetemp);
+ pdeNew->SetTime(WT_MODIFICATION, timetemp);
+ pdeNew->SetName(pdfn);
+
+ ReleaseEntry(sidNew);
+
+ // Insert new entry into the tree
+
+ msfChk(InsertEntry(sidParent, sidNew, pdfn));
+
+Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::RenameEntry, public
+//
+// Synopsis: Rename an entry
+//
+// Arguments: [sidParent] -- Sid of parent of entry to be renamed
+// [pwcsName] -- Old name of entry to be renamed
+// [pwcsName] -- New name
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Remove old entry
+// Rename entry
+// Insert as new entry
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+SCODE DIR_NEAR CDirectory::RenameEntry(SID const sidParent,
+ CDfName const *pdfn,
+ CDfName const *pdfnNew)
+{
+ // Make sure new name doesn't already exist
+ SCODE sc;
+ SEntryBuffer eb;
+
+ sc = IsEntry(sidParent, pdfnNew, &eb);
+ if (sc != STG_E_FILENOTFOUND)
+ {
+ if (SUCCEEDED(sc))
+ {
+ // Entry did exist - fail this call
+ sc = STG_E_ACCESSDENIED;
+ }
+
+ return(sc);
+ }
+
+ // We can't just rename in place (because the tree is ordered)
+
+ CDirEntry *pdeRename;
+ SEntryBuffer ebRename;
+
+ msfChk(FindEntry(sidParent, pdfn, DEOP_REMOVE, &ebRename));
+
+ sc = GetDirEntry(ebRename.sid, FB_DIRTY, &pdeRename);
+
+ msfAssert(SUCCEEDED(sc) && aMsg("Could get dir entry to rename"));
+
+ msfChk(sc);
+
+ pdeRename->SetName(pdfnNew);
+
+ ReleaseEntry(ebRename.sid);
+
+ // If this InsertEntry fails, we've potentially lost the entry. This
+ // doesn't matter becase:
+ // a) The only way we could fail is if we couldn't read or write
+ // the disk (hard error)
+ // b) No one's going to call RenameEntry anyways
+ // c) If we're transacted, the whole operation is made robust by
+ // CopyOnWrite mode
+ // d) If we're direct, we already know we can fail in ways that leave
+ // the Docfile corrupt.
+
+ sc = InsertEntry(sidParent, ebRename.sid, pdfnNew);
+
+ msfAssert(SUCCEEDED(sc) && aMsg("Couldn't reinsert renamed dir entry"));
+
+ msfChk(sc);
+
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::DestroyAllChildren
+//
+// Synopsis: destroy all child entries
+//
+// Effects: destroys child tree
+//
+// Arguments: [sidParent] -- storage entry
+//
+// Returns: S_OK or error code
+//
+// Modifies: sidParent's entry
+//
+// Algorithm: While there's a child
+// destroy it
+//
+// Notes: We may want to consider a more efficient implementation
+//
+//--------------------------------------------------------------------------
+
+
+SCODE DIR_NEAR CDirectory::DestroyAllChildren(
+ SID const sidParent)
+{
+ SCODE sc;
+ CDirEntry *pdeParent, *pdeChild;
+ SID sidChild;
+ CDfName dfnChild;
+
+ for (;;)
+ {
+ CDfName dfnChild;
+
+ msfChk(GetDirEntry(sidParent, FB_NONE, &pdeParent));
+ sidChild = pdeParent->GetChild();
+ ReleaseEntry(sidParent);
+
+ if (sidChild == NOSTREAM)
+ break;
+
+ msfChk(GetDirEntry(sidChild, FB_NONE, &pdeChild));
+
+ dfnChild.Set(pdeChild->GetName());
+ ReleaseEntry(sidChild);
+
+ msfChk(DestroyChild(sidParent, &dfnChild));
+ }
+
+Err:
+ return(sc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::DestroyChild
+//
+// Synopsis: destroy a named child
+//
+// Effects: destroys named child's entry
+//
+// Arguments: [sidParent] -- storage entry
+// [pdfn] -- child name
+//
+// Returns: S_OK, STG_E_FILENOTFOUND, or other error code
+//
+// Modifies: child's entry
+//
+// Algorithm: Find and remove child
+// Free child entry
+//
+//--------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::DestroyChild(
+ SID const sidParent,
+ CDfName const *pdfn)
+{
+ SCODE sc;
+ SEntryBuffer ebChild;
+
+ msfAssert(pdfn != NULL);
+
+ // remove the entry from the tree
+
+ msfChk(FindEntry(sidParent, pdfn, DEOP_REMOVE, &ebChild));
+
+ msfAssert(ebChild.sid != NOSTREAM);
+
+ // Before we remove this entry, we need to destroy it (including all
+ // its children). Note that we can't hold onto the entry because it
+ // might have children which get destroyed, which have children which
+ // get destroyed, etc.
+
+ if (STORAGELIKE(ebChild.dwType))
+ {
+ msfChk(DestroyAllChildren(ebChild.sid));
+ }
+
+ CDirEntry *pdeChild;
+ msfChk(GetDirEntry(ebChild.sid, FB_DIRTY, &pdeChild));
+
+ if (STREAMLIKE(ebChild.dwType))
+ {
+ // Deallocate any used streams
+ msfChkTo(EH_Rel, _pmsParent->KillStream(pdeChild->GetStart(),
+ pdeChild->GetSize()));
+ }
+
+ pdeChild->SetFlags(STGTY_INVALID);
+ if (ebChild.sid < _sidFirstFree)
+ {
+ _sidFirstFree = ebChild.sid;
+ }
+
+EH_Rel:
+ ReleaseEntry(ebChild.sid);
+
+Err:
+ return(sc);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectory::StatEntry
+//
+// Synopsis: For a given handle, fill in the Multistream specific
+// information of a STATSTG.
+//
+// Arguments: [sid] -- SID that information is requested on.
+// [pstatstg] -- STATSTG to fill in.
+//
+// Returns: S_OK
+//
+// Algorithm: Fill in time information and size and then return
+//
+//--------------------------------------------------------------------------
+
+
+SCODE DIR_NEAR CDirectory::StatEntry(SID const sid, STATSTG *pstatstg)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+
+ pstatstg->mtime = pde->GetTime(WT_MODIFICATION);
+ pstatstg->ctime = pde->GetTime(WT_CREATION);
+ pstatstg->atime = pstatstg->mtime;
+ ULISet32(pstatstg->cbSize, pde->GetSize());
+
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::GetDirEntry
+//
+// Synopsis: Get a directory entry with given permissions
+//
+// Arguments: [sid] -- SID
+// [dwFlags] -- permissions
+// [ppde] -- placeholder for directory entry
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm:
+//
+//--------------------------------------------------------------------------
+
+
+SCODE DIR_NEAR CDirectory::GetDirEntry(
+ const SID sid,
+ const DWORD dwFlags,
+ CDirEntry **ppde)
+{
+ SCODE sc;
+ CDirSect *pds;
+ DIRINDEX id = sid / _cdeEntries;
+
+ msfChk(_dv.GetTable(id, dwFlags, &pds));
+
+ *ppde = pds->GetEntry((DIROFFSET)(sid % _cdeEntries));
+
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::ReleaseEntry
+//
+// Synopsis: Releases a directory entry
+//
+// Arguments: [sid] -- SID
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm:
+//
+//--------------------------------------------------------------------------
+
+void DIR_NEAR CDirectory::ReleaseEntry(SID sid)
+{
+ _dv.ReleaseTable(sid / _cdeEntries);
+}
diff --git a/private/ole32/stg/ref/dirp.cxx b/private/ole32/stg/ref/dirp.cxx
new file mode 100644
index 000000000..b53ed9ab2
--- /dev/null
+++ b/private/ole32/stg/ref/dirp.cxx
@@ -0,0 +1,871 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: DirP.CXX
+//
+// Contents: Private CDirectory child tree methods
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+
+#include <dirfunc.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::InsertEntry, private
+//
+// Synopsis: insert entry into child tree
+//
+// Arguments: [sidTree] -- storage entry in which to insert entry
+// [sidNew] -- new entry
+// [pdfnNew] -- new entry name
+//
+// Returns: S_OK, STG_E_FILEALREADYEXISTS, or other error
+//
+// Modifies: sidParent's child tree
+//
+// Algorithm: Search down the binary tree to find the leaf node to which
+// to add the new entry (failing if we find the name already
+// exists). Along the way we split nodes where needed to keep
+// the tree balanced.
+//
+//--------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::InsertEntry(
+ SID sidTree,
+ SID sidNew,
+ CDfName const *pdfnNew)
+{
+ SCODE sc;
+
+ // To insert the key and keep the tree balanced, we need to know
+ // the parent, grandparent, and greatgrandparent of the node we're
+ // inserting.
+
+ SID sidChild, sidParent, sidGrandParent, sidGreatGrandParent;
+ CDirEntry *pdeParent;
+ int iCmp;
+
+ // When we're ready to insert, sidParent will be the entry to which we
+ // attach sidNew
+
+ sidParent = sidGrandParent = sidGreatGrandParent = sidTree;
+
+ // Begin the search with the root of the child tree
+
+ msfChk(GetDirEntry(sidTree, FB_NONE, &pdeParent));
+ sidChild = pdeParent->GetChild();
+
+ // Search down the child tree to find the correct leaf entry
+
+ while (sidChild != NOSTREAM)
+ {
+ // The sidParent entry has a child along the search path, so we
+ // move down the tree (letting go of sidParent and taking hold of
+ // its child)
+
+ ReleaseEntry(sidParent);
+
+ // Check to see if we need to split this node (nothing is held)
+
+ do
+ {
+ SID sidLeft, sidRight;
+ BOOL fRed;
+
+ {
+ CDirEntry *pdeChild;
+
+ msfChk(GetDirEntry(sidChild, FB_NONE, &pdeChild));
+
+ msfAssert(((sidTree != sidParent) ||
+ (pdeChild->GetColor() == DE_BLACK)) &&
+ aMsg("Dir tree corrupt - root child not black!"));
+
+ sidLeft = pdeChild->GetLeftSib();
+ sidRight = pdeChild->GetRightSib();
+
+ ReleaseEntry(sidChild);
+ }
+
+ if (sidLeft == NOSTREAM || sidRight == NOSTREAM)
+ break;
+
+ {
+ CDirEntry *pdeLeft;
+
+ msfChk(GetDirEntry(sidLeft, FB_NONE, &pdeLeft));
+ fRed = (pdeLeft->GetColor() == DE_RED);
+ ReleaseEntry(sidLeft);
+ }
+
+ if (!fRed)
+ break;
+
+ {
+ CDirEntry *pdeRight;
+
+ msfChk(GetDirEntry(sidRight, FB_NONE, &pdeRight));
+ fRed = (pdeRight->GetColor() == DE_RED);
+ ReleaseEntry(sidRight);
+ }
+
+ if (fRed)
+ msfChk(SplitEntry(pdfnNew, sidTree, sidGreatGrandParent,
+ sidGrandParent, sidParent, sidChild,
+ &sidChild));
+ }
+ while (FALSE);
+
+ //
+
+ msfAssert(sidChild != NOSTREAM);
+
+ // Advance the search
+
+ sidGreatGrandParent = sidGrandParent;
+ sidGrandParent = sidParent;
+ sidParent = sidChild;
+
+ msfChk(GetDirEntry(sidParent, FB_NONE, &pdeParent));
+
+ iCmp = NameCompare(pdfnNew, pdeParent->GetName());
+
+ if (iCmp == 0)
+ {
+ // The new name exactly matched an existing name. Fail.
+ msfChkTo(EH_RelParent, STG_E_FILEALREADYEXISTS);
+ }
+
+ // Move down the tree, left or right depending on the comparison
+
+ if (iCmp < 0)
+ sidChild = pdeParent->GetLeftSib();
+ else
+ sidChild = pdeParent->GetRightSib();
+ }
+
+ msfAssert(sidChild == NOSTREAM);
+
+ // We've found the position to insert the new entry.
+
+ // We're going to dirty sidParent, so we need to change our holding flags
+ ReleaseEntry(sidParent);
+ msfChk(GetDirEntry(sidParent, FB_DIRTY, &pdeParent));
+
+ if (sidParent == sidTree)
+ {
+ // sidParent never made it past sidTree - we must be inserting the
+ // first child into sidTree
+
+ msfAssert(pdeParent->GetChild() == NOSTREAM);
+
+ // The SplitInsert call below will make sidNew black.
+ pdeParent->SetChild(sidNew);
+ }
+ else
+ {
+ msfAssert(iCmp != 0);
+
+ // Use the comparison to determine which side to insert the new entry
+
+ if (iCmp < 0)
+ {
+ msfAssert(pdeParent->GetLeftSib() == NOSTREAM);
+ msfAssert(NameCompare(pdfnNew, pdeParent->GetName()) < 0);
+
+ pdeParent->SetLeftSib(sidNew);
+ }
+ else
+ {
+ msfAssert(pdeParent->GetRightSib() == NOSTREAM);
+ msfAssert(NameCompare(pdfnNew, pdeParent->GetName()) > 0);
+
+ pdeParent->SetRightSib(sidNew);
+ }
+ }
+
+EH_RelParent:
+ ReleaseEntry(sidParent);
+
+ if (SUCCEEDED(sc))
+ {
+ SID sidTemp;
+ sc = SplitEntry(pdfnNew, sidTree, sidGreatGrandParent, sidGrandParent,
+ sidParent, sidNew, &sidTemp);
+ }
+Err:
+ return(sc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::SplitEntry, private
+//
+// Synopsis: Split 4-node
+//
+// Effects: Passes up red link to parent
+//
+// Arguments: [pdfn] -- search key
+// [sidTree] -- child tree sid
+// [sidGreat] -- greatgrandparent of child to split
+// [sidGrand] -- grandparent of child to split
+// [sidParent] -- parent of child to split
+// [sidChild] -- child to split
+// [psid] -- place holder for tree position
+//
+// Returns: S_OK, or error
+//
+// Modifies: psid, tree
+//
+// Algorithm:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE CDirectory::SplitEntry(
+ CDfName const *pdfn,
+ SID sidTree,
+ SID sidGreat,
+ SID sidGrand,
+ SID sidParent,
+ SID sidChild,
+ SID *psid)
+{
+ SCODE sc;
+ CDirEntry *pdeChild;
+ SID sidLeft, sidRight;
+
+ // pn is a 4-node; start split by moving red link up
+
+ // pn->GetLeft()->SetColor(BLACK);
+
+ msfChk(GetDirEntry(sidChild, FB_DIRTY, &pdeChild));
+ sidLeft = pdeChild->GetLeftSib();
+ sidRight = pdeChild->GetRightSib();
+
+ // The root must always be black; new non-root children are red
+ pdeChild->SetColor((sidParent == sidTree) ? DE_BLACK : DE_RED);
+
+ ReleaseEntry(sidChild);
+
+ if (sidLeft != NOSTREAM)
+ {
+ msfChk(SetColorBlack(sidLeft));
+ }
+
+ // pn->GetRight()->SetColor(BLACK);
+
+ if (sidRight != NOSTREAM)
+ {
+ msfChk(SetColorBlack(sidRight));
+ }
+
+ if (sidParent != sidTree)
+ {
+ CDirEntry *pdeParent;
+ BOOL fRedParent;
+ int iCmpParent;
+
+ msfChk(GetDirEntry(sidParent, FB_NONE, &pdeParent));
+
+ fRedParent = (pdeParent->GetColor() == DE_RED);
+
+ if (fRedParent)
+ iCmpParent = NameCompare(pdfn, pdeParent->GetName());
+
+ ReleaseEntry(sidParent);
+
+ // if (pnp->IsRed())
+
+ if (fRedParent)
+ {
+ int iCmpGrand;
+
+ // parent is red - adjacent red links are not allowed
+
+ // Note - grandparent may be sidTree
+
+ if (sidGrand == sidTree)
+ {
+ iCmpGrand = 1;
+ }
+ else
+ {
+ CDirEntry *pdeGrand;
+ msfChk(GetDirEntry(sidGrand, FB_DIRTY, &pdeGrand));
+
+ iCmpGrand = NameCompare(pdfn, pdeGrand->GetName());
+
+ // png->SetColor(RED);
+ pdeGrand->SetColor(DE_RED);
+
+ ReleaseEntry(sidGrand);
+ }
+
+ // if ((ikey < png->GetKey()) != (ikey < pnp->GetKey()))
+
+ if ((iCmpGrand < 0) != (iCmpParent < 0))
+ {
+ /* two cases:
+ //
+ // | |
+ // g g
+ // / \
+ // p p
+ // \ /
+ // x x
+ //
+ // the red links are oriented differently
+ */
+
+ // pn = Rotate(ikey, png);
+ msfChk(RotateEntry(pdfn, sidTree, sidGrand, &sidChild));
+
+ /*
+ // | |
+ // g g
+ // / \
+ // x x
+ // / \
+ // p p
+ */
+ }
+
+ // the red links are now oriented the same - we balance the tree
+ // by rotating
+
+ // pn = Rotate(ikey, pngg);
+ msfChk(RotateEntry(pdfn, sidTree, sidGreat, &sidChild));
+
+ // pn->SetColor(BLACK);
+ msfAssert(sidChild != sidTree);
+ msfChk(SetColorBlack(sidChild));
+ }
+ }
+
+ // return(pn);
+ *psid = sidChild;
+
+ // The first node's link must always be black.
+#if DBG == 1
+ CDirEntry *pdeTree;
+ msfChk(GetDirEntry(sidTree, FB_NONE, &pdeTree));
+ sidChild = pdeTree->GetChild();
+ ReleaseEntry(sidTree);
+
+ msfChk(GetDirEntry(sidChild, FB_NONE, &pdeChild));
+ msfAssert(pdeChild->GetColor() == DE_BLACK);
+ ReleaseEntry(sidChild);
+#endif
+
+Err:
+ return(sc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::RotateEntry
+//
+// Synopsis: rotation for balancing
+//
+// Effects: rotates localized portion of child tree
+//
+// Arguments: [pdfn] -- search key
+// [sidTree] -- child tree sid
+// [sidParent] -- root of rotation
+// [psid] -- placeholder for root after rotation
+//
+// Returns: S_OK, or error
+//
+// Modifies: child tree
+//
+// Algorithm:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE CDirectory::RotateEntry(
+ CDfName const *pdfn,
+ SID sidTree,
+ SID sidParent,
+ SID *psid)
+{
+ SCODE sc;
+ int iCmp;
+ // PNODE pnc, pngc;
+ SID sidChild, sidGrand;
+
+ // find the child
+
+ CDirEntry *pdeParent, *pdeChild, *pdeGrand;
+ msfChk(GetDirEntry(sidParent, FB_DIRTY, &pdeParent));
+
+ if (sidParent == sidTree)
+ {
+ sidChild = pdeParent->GetChild();
+ }
+ else
+ {
+ iCmp = NameCompare(pdfn, pdeParent->GetName());
+
+ if (iCmp < 0)
+ sidChild = pdeParent->GetLeftSib();
+ else
+ sidChild = pdeParent->GetRightSib();
+ }
+
+ // find the grandchild
+
+ msfChkTo(EH_RelParent, GetDirEntry(sidChild, FB_DIRTY, &pdeChild));
+ msfAssert(sidChild != sidTree);
+
+ iCmp = NameCompare(pdfn, pdeChild->GetName());
+
+ if (iCmp < 0)
+ {
+ // pngc = pnc->GetLeft();
+ sidGrand = pdeChild->GetLeftSib();
+
+ msfChkTo(EH_RelChild, GetDirEntry(sidGrand, FB_DIRTY, &pdeGrand));
+
+ /*
+ // |
+ // c
+ // / \
+ // / \
+ // g X
+ // \
+ // Y
+ */
+
+ // pnc->SetLeft(pngc->GetRight());
+ pdeChild->SetLeftSib(pdeGrand->GetRightSib());
+
+ /*
+ // |
+ // c
+ // / \
+ // | \
+ // g | X
+ // \|
+ // Y
+ */
+
+ // pngc->SetRight(pnc);
+ pdeGrand->SetRightSib(sidChild);
+
+ /*
+ // g
+ // \
+ // \|
+ // c
+ // / \
+ // | \
+ // | X
+ // |
+ // Y
+ */
+ }
+ else
+ {
+ // pngc = pnc->GetRight();
+ sidGrand = pdeChild->GetRightSib();
+
+ msfChkTo(EH_RelChild, GetDirEntry(sidGrand, FB_DIRTY, &pdeGrand));
+
+ // pnc->SetRight(pngc->GetLeft());
+ pdeChild->SetRightSib(pdeGrand->GetLeftSib());
+
+ // pngc->SetLeft(pnc);
+ pdeGrand->SetLeftSib(sidChild);
+ }
+
+
+ // update parent
+
+ if (sidParent == sidTree)
+ {
+ // The root must always be black
+ pdeGrand->SetColor(DE_BLACK);
+ pdeParent->SetChild(sidGrand);
+ }
+ else
+ {
+ iCmp = NameCompare(pdfn, pdeParent->GetName());
+
+ if (iCmp < 0)
+ {
+ // pnp->SetLeft(pngc);
+ pdeParent->SetLeftSib(sidGrand);
+ }
+ else
+ {
+ // pnp->SetRight(pngc);
+ pdeParent->SetRightSib(sidGrand);
+ }
+ }
+
+ ReleaseEntry(sidGrand);
+
+ /*
+ // |
+ // g
+ // \
+ // \
+ // c
+ // / \
+ // | \
+ // | X
+ // |
+ // Y
+ */
+
+ // return(pngc);
+ *psid = sidGrand;
+
+EH_RelChild:
+ ReleaseEntry(sidChild);
+
+EH_RelParent:
+ ReleaseEntry(sidParent);
+
+Err:
+ return(sc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::FindEntry, private
+//
+// Synopsis: find entry info based on name (optionally removing it)
+//
+// Effects: find - none, remove - takes entry out of child list
+//
+// Arguments: [sidParent] -- sid of parent entry to search
+// [pdfn] -- name to search for
+// [deop] -- entry operation (find or remove)
+// [peb] -- entry information buffer
+//
+// Returns: S_OK, STG_E_FILENOTFOUND, or other error
+//
+// Modifies: peb
+//
+// Algorithm: To find the entry we search down the binary tree.
+// To remove the entry, we need to patch the tree to keep it
+// as a valid binary tree.
+//
+//--------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::FindEntry(
+ SID sidParent,
+ CDfName const *pdfn,
+ DIRENTRYOP deop,
+ SEntryBuffer *peb)
+{
+ SCODE sc;
+ SID sidPrev, sidFind;
+ CDirEntry *pdePrev, *pdeFind;
+ int iCmp;
+
+ // Once we've found the right child, sidPrev will be that entry's parent
+ // in the child tree
+
+ sidPrev = sidParent;
+
+ // Begin the search with the root of the child tree
+
+ msfChk(GetDirEntry(sidPrev, FB_NONE, &pdePrev));
+ sidFind = pdePrev->GetChild();
+
+ // sidPrev is held
+
+ for(;;)
+ {
+ if (sidFind == NOSTREAM)
+ {
+ // we didn't find the child. fail.
+ sc = STG_E_FILENOTFOUND;
+ goto EH_RelPrev;
+// Removed this line to supress the debug error print.
+// msfChkTo(EH_RelPrev, STG_E_FILENOTFOUND);
+ }
+
+ msfChkTo(EH_RelPrev, GetDirEntry(sidFind, FB_NONE, &pdeFind));
+
+ // sidPrev and sidFind are held
+
+ int tmpCmp = NameCompare(pdfn, pdeFind->GetName());
+
+ if (tmpCmp == 0)
+ {
+ // We found the entry that matches our search name
+ break;
+ }
+
+ // The names did not match. Advance the search down the tree.
+ ReleaseEntry(sidPrev);
+ pdePrev = pdeFind;
+ sidPrev = sidFind;
+
+ // sidPrev is held
+
+ // remember the comparison with sidPrev so we can use it to insert
+ // an entry when we patch the tree
+
+ iCmp = tmpCmp;
+
+ if (iCmp < 0)
+ sidFind = pdePrev->GetLeftSib();
+ else
+ sidFind = pdePrev->GetRightSib();
+ }
+
+ msfAssert(sidFind != NOSTREAM);
+
+ // sidFind is held
+ // sidPrev is held
+
+ msfAssert(NameCompare(pdfn, pdeFind->GetName()) == 0);
+
+ // fill in entry information
+
+ peb->sid = sidFind;
+ peb->dwType = pdeFind->GetFlags();
+ peb->luid = DF_NOLUID;
+
+ if (deop == DEOP_REMOVE)
+ {
+ ReleaseEntry(sidFind);
+ ReleaseEntry(sidPrev);
+
+ msfChk(GetDirEntry(sidPrev, FB_DIRTY, &pdePrev));
+ msfChkTo(EH_RelPrev, GetDirEntry(sidFind, FB_DIRTY, &pdeFind));
+
+ // Remove the found child from tree (carefully!). We remove it by
+ // finding another entry in the tree with which to replace it.
+ // sidFind is the node we're removing
+ // sidPrev is the parent of sidFind in the child tree
+ // sidInsert is the entry which will replace sidFind
+
+ SID sidInsert = pdeFind->GetRightSib();
+
+ if (sidInsert == NOSTREAM)
+ {
+ // sidFind has no right child, so we can patch the tree by
+ // replacing sidFind with the sidFind's left child
+
+ sidInsert = pdeFind->GetLeftSib();
+
+ // set the inserted to the right color
+ if (sidInsert != NOSTREAM)
+ {
+ // we always set the inserted node to black (since the
+ // parent may not exist (we could be inserting at the
+ // root)
+ msfChkTo(EH_RelPrev, SetColorBlack(sidInsert));
+ }
+ }
+ else
+ {
+ CDirEntry *pdeInsert;
+
+ // The node we're removing has a right child
+
+ msfChkTo(EH_RelFind, GetDirEntry(sidInsert, FB_NONE, &pdeInsert));
+
+ // sidPrev, sidFind, and sidInsert are all held
+
+ if (pdeInsert->GetLeftSib() != NOSTREAM)
+ {
+ // sidFind's right child has a left child.
+ // sidInsert will be the leftmost child of sidFind's right
+ // child (which will keep the tree ordered)
+
+ // sidPreInsert will be the leftmost child's parent int the
+ // child tree
+
+ SID sidPreInsert = sidInsert;
+ CDirEntry *pdePreInsert = pdeInsert;
+
+ // we wait to assign sidInsert so we can clean up
+ msfChkTo(EH_RelIns, GetDirEntry(pdePreInsert->GetLeftSib(),
+ FB_NONE, &pdeInsert));
+
+ sidInsert = pdePreInsert->GetLeftSib();
+
+ // sidPrev, sidFind, sidPreInsert, sidInsert are held
+
+ // find the leftmost child of sidFind's right child
+
+ SID sidLeft;
+ while ((sidLeft = pdeInsert->GetLeftSib()) != NOSTREAM)
+ {
+ ReleaseEntry(sidPreInsert);
+
+ // sidPrev, sidFind, sidInsert are held
+
+ sidPreInsert = sidInsert;
+ pdePreInsert = pdeInsert;
+
+ // we wait to assign sidInsert to we can clean up
+ msfChkTo(EH_RelIns, GetDirEntry(sidLeft,
+ FB_NONE, &pdeInsert));
+
+ sidInsert = sidLeft;
+ }
+
+ msfAssert(pdeInsert->GetLeftSib() == NOSTREAM);
+
+ // sidPrev, sidFind, sidPreInsert, sidInsert are held
+
+ // Remove sidInsert so we can reinsert it in place of sidFind.
+ // We remove sidInsert (which has no left child) by making
+ // sidPreInsert's left child point to sidInsert's right child
+
+ ReleaseEntry(sidPreInsert);
+ msfChkTo(EH_RelIns, GetDirEntry(sidPreInsert, FB_DIRTY,
+ &pdePreInsert));
+
+ pdePreInsert->SetLeftSib(pdeInsert->GetRightSib());
+ ReleaseEntry(sidPreInsert);
+
+ // sidPrev, sidFind, sidInsert is held
+
+ // Begin to replace sidFind with sidInsert by setting the
+ // right child of sidInsert to be the right child of sidFind
+
+ ReleaseEntry(sidInsert);
+ msfChkTo(EH_RelFind, GetDirEntry(sidInsert, FB_DIRTY,
+ &pdeInsert));
+ pdeInsert->SetRightSib(pdeFind->GetRightSib());
+ }
+ else
+ {
+ // sidFind's right child has no left child, so we can patch
+ // the tree by making sidFind's right child's left child
+ // point to sidFind's left child, and then replacing sidFind
+ // with sidFind's right child.
+
+ ReleaseEntry(sidInsert);
+ msfChkTo(EH_RelFind, GetDirEntry(sidInsert, FB_DIRTY,
+ &pdeInsert));
+
+ // fall through to do the work
+ }
+
+ pdeInsert->SetColor(DE_BLACK);
+
+ // Complete sidInsert's patching by setting its left child to be
+ // the left child of sidFind
+
+ pdeInsert->SetLeftSib(pdeFind->GetLeftSib());
+
+EH_RelIns:
+ ReleaseEntry(sidInsert);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ if (sidPrev == sidParent)
+ {
+ // We're removing the first child; update sidParent.
+ // We made sure sidInsert is black (above).
+ pdePrev->SetChild(sidInsert);
+ }
+ else if (iCmp < 0)
+ {
+ pdePrev->SetLeftSib(sidInsert);
+ }
+ else
+ pdePrev->SetRightSib(sidInsert);
+
+ // make sure sidFind is clean
+
+ pdeFind->SetLeftSib(NOSTREAM);
+ pdeFind->SetRightSib(NOSTREAM);
+ }
+ }
+
+EH_RelFind:
+ ReleaseEntry(sidFind);
+
+EH_RelPrev:
+ ReleaseEntry(sidPrev);
+
+Err:
+ return(sc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::NameCompare, private static
+//
+// Synopsis: name ordering function for child tree
+//
+// Arguments: [pdfn1] - name 1
+// [pdfn2] - name 2
+//
+// Requires: One but not both names cannot may have zero length.
+//
+// Returns: <0 if name 1 < name 2
+// 0 if name 1 = name 2
+// >0 if name 1 > name 2
+//
+// Algorithm: To speed the comparision (and to allow zero length names),
+// we first compare the name lengths. (Shorter names are "less"
+// than longer names). If the lengths are equal we compare the
+// strings.
+//
+//--------------------------------------------------------------------------
+
+int CDirectory::NameCompare(CDfName const *pdfn1, CDfName const *pdfn2)
+{
+ int iCmp = pdfn1->GetLength() - pdfn2->GetLength();
+
+ if (iCmp == 0)
+ {
+ msfAssert(pdfn1->GetLength() != 0);
+ iCmp = dfwcsnicmp((WCHAR *)pdfn1->GetBuffer(),
+ (WCHAR *)pdfn2->GetBuffer(), pdfn1->GetLength());
+ }
+
+ return(iCmp);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectory::SetColorBlack, private
+//
+// Synopsis: Sets a directory entry to black
+//
+// Arguments: [sid] -- SID of entry to be modified
+//
+// Returns: S_OK or error
+//
+// Notes: Added to reduce code size
+//
+//--------------------------------------------------------------------------
+
+SCODE DIR_NEAR CDirectory::SetColorBlack(const SID sid)
+{
+ SCODE sc;
+
+ CDirEntry *pde;
+ msfChk(GetDirEntry(sid, FB_DIRTY, &pde));
+
+ pde->SetColor(DE_BLACK);
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
diff --git a/private/ole32/stg/ref/docfile.cxx b/private/ole32/stg/ref/docfile.cxx
new file mode 100644
index 000000000..c084a3886
--- /dev/null
+++ b/private/ole32/stg/ref/docfile.cxx
@@ -0,0 +1,262 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: docfile.c
+//
+// Contents: DocFile root functions (Stg* functions)
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+
+#include <rpubdf.hxx>
+#include <expdf.hxx>
+#include <expst.hxx>
+#include <dfentry.hxx>
+#include <ascii.hxx>
+#include <logfile.hxx>
+
+
+
+
+//+--------------------------------------------------------------
+//
+// Function: DfFromLB, private
+//
+// Synopsis: Starts a root Docfile on an ILockBytes
+//
+// Arguments: [plst] - LStream to start on
+// [df] - Permissions
+// [dwStartFlags] - Startup flags
+// [snbExclude] - Partial instantiation list
+// [ppdfExp] - DocFile return
+// [pcid] - Class ID return for opens
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdfExp]
+// [pcid]
+//
+//---------------------------------------------------------------
+
+
+SCODE DfFromLB(ILockBytes *plst,
+ DFLAGS df,
+ DWORD dwStartFlags,
+ SNBW snbExclude,
+ CExposedDocFile **ppdfExp,
+ CLSID *pcid)
+{
+ SCODE sc, scConv;
+ CRootPubDocFile *prpdf;
+ ULONG ulOpenLock;
+
+ olDebugOut((DEB_ITRACE, "In DfFromLB(%p, %X, %lX, %p, %p, %p)\n",
+ plst, df, dwStartFlags, snbExclude, ppdfExp, pcid));
+
+ // If we're not creating or converting, do a quick check
+ // to make sure that the ILockBytes contains a storage
+ if ((dwStartFlags & (RSF_CREATEFLAGS | RSF_CONVERT)) == 0)
+ olHChk(StgIsStorageILockBytes(plst));
+
+
+ // Make root
+ olMem(prpdf = new CRootPubDocFile);
+ olChkTo(EH_prpdf, scConv = prpdf->InitRoot(plst, dwStartFlags, df,
+ snbExclude, &ulOpenLock));
+
+ olMemTo(EH_ppcInit,
+ *ppdfExp = new CExposedDocFile(prpdf));
+
+ olDebugOut((DEB_ITRACE, "Out DfFromLB => %p\n", *ppdfExp));
+ return scConv;
+
+ EH_ppcInit:
+ if (ulOpenLock > 0)
+ {
+ ReleaseOpen(plst, df, ulOpenLock);
+ }
+
+ // The open lock has now been released (either explicitly or by ppc)
+ ulOpenLock = 0;
+
+ if (ulOpenLock > 0)
+ ReleaseOpen(plst, df, ulOpenLock);
+
+
+ EH_prpdf:
+ prpdf->vRelease();
+ EH_Err:
+ return sc;
+}
+
+
+
+//+--------------------------------------------------------------
+//
+// Function: StgCreateDocfileOnILockBytes, public
+//
+// Synopsis: Creates a root Docfile on an lstream
+//
+// Arguments: [plkbyt] - LStream
+// [grfMode] - Permissions
+// [reserved] - Unused
+// [ppstgOpen] - Docfile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstgOpen]
+//
+//---------------------------------------------------------------
+
+STDAPI StgCreateDocfileOnILockBytes(ILockBytes *plkbyt,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage **ppstgOpen)
+{
+ CExposedDocFile *pdfExp;
+ SCODE sc;
+ DFLAGS df;
+
+ olLog(("--------::In StgCreateDocFileOnILockBytes(%p, %lX, %lu, %p)\n",
+ plkbyt, grfMode, reserved, ppstgOpen));
+
+ olDebugOut((DEB_ITRACE, "In StgCreateDocfileOnILockBytes("
+ "%p, %lX, %lu, %p)\n",
+ plkbyt, grfMode, reserved, ppstgOpen));
+ TRY
+ {
+ olChk(ValidatePtrBuffer(ppstgOpen));
+ *ppstgOpen = NULL;
+ olChk(ValidateInterface(plkbyt, IID_ILockBytes));
+ if (reserved != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if ((grfMode & (STGM_CREATE | STGM_CONVERT)) == 0)
+ olErr(EH_Err, STG_E_FILEALREADYEXISTS);
+ olChk(VerifyPerms(grfMode));
+ if (grfMode & STGM_DELETEONRELEASE)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ df = ModeToDFlags(grfMode);
+ if ((grfMode & (STGM_TRANSACTED | STGM_CONVERT)) ==
+ (STGM_TRANSACTED | STGM_CONVERT))
+ df |= DF_INDEPENDENT;
+ olChkTo(EH_Truncate,
+ sc = DfFromLB(plkbyt, df,
+ RSF_CREATE |
+ ((grfMode & STGM_CREATE) ? RSF_TRUNCATE : 0) |
+ ((grfMode & STGM_CONVERT) ? RSF_CONVERT : 0),
+ NULL, &pdfExp, NULL));
+
+ // Success; since we hold on to the ILockBytes interface,
+ // we must take a reference to it.
+ plkbyt->AddRef();
+
+ *ppstgOpen = pdfExp;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out StgCreateDocfileOnILockBytes => %p\n",
+ *ppstgOpen));
+ EH_Err:
+ olLog(("--------::Out StgCreateDocFileOnILockBytes(). *ppstgOpen == %p, ret == %lx\n",
+ *ppstgOpen, sc));
+ FreeLogFile();
+ return ResultFromScode(sc);
+
+ EH_Truncate:
+ if ((grfMode & STGM_CREATE) && (grfMode & STGM_TRANSACTED) == 0)
+ {
+ ULARGE_INTEGER ulSize;
+
+ ULISet32(ulSize, 0);
+ olHChk(plkbyt->SetSize(ulSize));
+ }
+ goto EH_Err;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Function: DfOpenStorageOnILockBytes, public
+//
+// Synopsis: Instantiates a root Docfile from an LStream,
+// converting if necessary
+//
+// Arguments: [plkbyt] - Source LStream
+// [pstgPriority] - For priority reopens
+// [grfMode] - Permissions
+// [snbExclude] - For priority reopens
+// [reserved]
+// [ppstgOpen] - Docfile return
+// [pcid] - Class ID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstgOpen]
+// [pcid]
+//
+//---------------------------------------------------------------
+
+TSTDAPI(DfOpenStorageOnILockBytes)(ILockBytes *plkbyt,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNBW snbExclude,
+ DWORD reserved,
+ IStorage **ppstgOpen,
+ CLSID *pcid)
+{
+ SCODE sc;
+ CExposedDocFile *pdfExp;
+
+ olLog(("--------::In DfOpenStorageOnILockBytes("
+ "%p, %p, %lX, %p, %lu, %p, %p)\n",
+ plkbyt, pstgPriority, grfMode, snbExclude, reserved, ppstgOpen,
+ pcid));
+ olDebugOut((DEB_ITRACE, "In DfOpenStorageOnILockBytes("
+ "%p, %p, %lX, %p, %lu, %p, %p)\n", plkbyt, pstgPriority,
+ grfMode, snbExclude, reserved, ppstgOpen, pcid));
+ TRY
+ {
+ olChk(ValidateInterface(plkbyt, IID_ILockBytes));
+ if (pstgPriority)
+ olChk(ValidateInterface(pstgPriority, IID_IStorage));
+ olChk(VerifyPerms(grfMode));
+ if (grfMode & STGM_DELETEONRELEASE)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ if (snbExclude)
+ {
+ if ((grfMode & STGM_RDWR) != STGM_READWRITE)
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+ }
+ if (reserved != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ if (FAILED(DllIsMultiStream(plkbyt)))
+ olErr(EH_Err, STG_E_FILENOTFOUND);
+ if (pstgPriority)
+ olChk(pstgPriority->Release());
+ olChk(DfFromLB(plkbyt, ModeToDFlags(grfMode), RSF_OPEN, snbExclude,
+ &pdfExp, pcid));
+
+ // Success; since we hold on to the ILockBytes interface,
+ // we must take a reference to it.
+ plkbyt->AddRef();
+
+ *ppstgOpen = pdfExp;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out DfOpenStorageOnILockBytes => %p\n",
+ *ppstgOpen));
+EH_Err:
+ olLog(("--------::Out DfOpenStorageOnILockBytes(). *ppstgOpen == %p, ret == %lx\n", *ppstgOpen, sc));
+ FreeLogFile();
+ return sc;
+}
diff --git a/private/ole32/stg/ref/entry.cxx b/private/ole32/stg/ref/entry.cxx
new file mode 100644
index 000000000..bc42d006c
--- /dev/null
+++ b/private/ole32/stg/ref/entry.cxx
@@ -0,0 +1,44 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: entry.cxx
+//
+// Contents: Entry implementations
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+
+//+--------------------------------------------------------------
+//
+// Member: PEntry::CopyTimesFrom, public
+//
+// Synopsis: Copies one entries times to another
+//
+// Arguments: [penFrom] - From
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+SCODE PEntry::CopyTimesFrom(PEntry *penFrom)
+{
+ SCODE sc;
+ TIME_T tm;
+
+ olDebugOut((DEB_ITRACE, "In PEntry::CopyTimesFrom(%p)\n",
+ penFrom));
+ olChk(penFrom->GetTime(WT_CREATION, &tm));
+ olChk(SetTime(WT_CREATION, tm));
+ olChk(penFrom->GetTime(WT_MODIFICATION, &tm));
+ olChk(SetTime(WT_MODIFICATION, tm));
+ olChk(penFrom->GetTime(WT_ACCESS, &tm));
+ olChk(SetTime(WT_ACCESS, tm));
+ olDebugOut((DEB_ITRACE, "Out PEntry::CopyTimesFrom\n"));
+ // Fall through
+EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/ref/expdf.cxx b/private/ole32/stg/ref/expdf.cxx
new file mode 100644
index 000000000..63fcd48c5
--- /dev/null
+++ b/private/ole32/stg/ref/expdf.cxx
@@ -0,0 +1,1511 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: expdf.cxx
+//
+// Contents: Exposed DocFile implementation
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+
+#include <expdf.hxx>
+#include <expst.hxx>
+#include <expiter.hxx>
+#include <pbstream.hxx>
+#include <pubiter.hxx>
+#include <lock.hxx>
+#include <logfile.hxx>
+#include <rpubdf.hxx>
+
+// Check for proper single-instance flags
+#define NOT_SINGLE(md) (((md) & STGM_DENY) != STGM_SHARE_EXCLUSIVE)
+
+#define EnforceSingle(mode) (NOT_SINGLE(mode) ? STG_E_INVALIDFUNCTION : S_OK)
+
+extern WCHAR const wcsContents[];
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CExposedDocFile, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [pdf] - Public DocFile
+// [pdfb] - DocFile basis
+// [ppc] - Context
+// [fOwnContext] - Whether this object owns the context
+//
+//---------------------------------------------------------------
+
+
+CExposedDocFile::CExposedDocFile(CPubDocFile *pdf)
+{
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::CExposedDocFile(%p)\n",
+ pdf));
+ _pdf = pdf;
+ _cReferences = 1;
+ _ulAccessLockBase = 0;
+ _sig = CEXPOSEDDOCFILE_SIG;
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::CExposedDocFile\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::~CExposedDocFile, public
+//
+// Synopsis: Destructor
+//
+//---------------------------------------------------------------
+
+
+inline
+CExposedDocFile::~CExposedDocFile(void)
+{
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::~CExposedDocFile\n"));
+ olAssert(_cReferences == 0);
+
+ if (_pdf)
+ {
+
+ _pdf->CPubDocFile::vRelease();
+ }
+ _sig = CEXPOSEDDOCFILE_SIGDEL;
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::~CExposedDocFile\n"));
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::Release, public
+//
+// Synopsis: Releases resources for a CExposedDocFile
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP_(ULONG) CExposedDocFile::Release(void)
+{
+ LONG lRet;
+
+ olLog(("%p::In CExposedDocFile::Release()\n", this));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::Release()\n"));
+ TRY
+ {
+ if (FAILED(Validate()))
+ return 0;
+ olAssert(_cReferences > 0);
+ lRet = AtomicDec(&_cReferences);
+ if (lRet == 0)
+ {
+
+ delete this;
+
+ }
+ else if (lRet < 0)
+ lRet = 0;
+ }
+ CATCH(CException, e)
+ {
+ UNREFERENCED_PARM(e);
+ lRet = 0;
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::Release()\n"));
+ olLog(("%p::Out CExposedDocFile::Release(). ret == %lu\n", this, lRet));
+ FreeLogFile();
+ return (ULONG)lRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CheckCopyTo, private
+//
+// Synopsis: Checks for CopyTo legality
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+inline SCODE CExposedDocFile::CheckCopyTo(void)
+{
+ //REFBUG: This needs to be fixed.
+ return S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::ConvertInternalStream, private
+//
+// Synopsis: Converts an internal stream to a storage
+//
+// Arguments: [pwcsName] - Name
+// [pdfExp] - Destination docfile
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+static WCHAR const wcsIllegalName[] = {'\\', '\0'};
+
+SCODE CExposedDocFile::ConvertInternalStream(CExposedDocFile *pdfExp)
+{
+ CPubStream *pstFrom, *pstTo;
+ SCODE sc;
+ CDfName const dfnIllegal(wcsIllegalName);
+ CDfName const dfnContents(wcsContents);
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::ConvertInternalStream(%p)\n",
+ pdfExp));
+ olChk(_pdf->GetStream(&dfnIllegal, DF_READWRITE | DF_DENYALL,
+ STGTY_STREAM, &pstFrom));
+ olChkTo(EH_pstFrom, pdfExp->GetPub()->CreateStream(&dfnContents,
+ DF_WRITE | DF_DENYALL,
+ STGTY_STREAM, &pstTo));
+ olChkTo(EH_pstTo, CopySStreamToSStream(pstFrom->GetSt(),
+ pstTo->GetSt()));
+ olChkTo(EH_pstTo, _pdf->DestroyEntry(&dfnIllegal, FALSE));
+ sc = S_OK;
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::ConvertInternalStream\n"));
+ // Fall through
+EH_pstTo:
+ pstTo->CPubStream::vRelease();
+EH_pstFrom:
+ pstFrom->CPubStream::vRelease();
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::CreateEntry, private
+//
+// Synopsis: Creates elements, used in CreateStream, CreateStorage and
+// for properties
+//
+// Arguments: [pwcsName] - Name
+// [dwType] - Entry type
+// [grfMode] - Access mode
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+//----------------------------------------------------------------------------
+
+SCODE CExposedDocFile::CreateEntry(WCHAR const *pwcsName,
+ DWORD dwType,
+ DWORD grfMode,
+ void **ppv)
+{
+ SCODE sc;
+ SEntryBuffer eb;
+ CDfName dfn;
+ BOOL fRenamed = FALSE;
+ CPubStream *pst;
+ CExposedStream *pstExp;
+ CPubDocFile *pdf;
+ CExposedDocFile *pdfExp;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::CreateEntry:%p("
+ "%ws, %lX, %lX, %p)\n", this, pwcsName, dwType, grfMode, ppv));
+ olChk(EnforceSingle(grfMode));
+ dfn.Set(pwcsName);
+
+
+ if (grfMode & (STGM_CREATE | STGM_CONVERT))
+ {
+ if (FAILED(sc = _pdf->IsEntry(&dfn, &eb)))
+ {
+ if (sc != STG_E_FILENOTFOUND)
+ olErr(EH_Err, sc);
+ }
+ else if (eb.dwType == dwType && (grfMode & STGM_CREATE))
+ olChk(_pdf->DestroyEntry(&dfn, FALSE));
+ else if (eb.dwType == STGTY_STREAM && (grfMode & STGM_CONVERT) &&
+ dwType == STGTY_STORAGE)
+ {
+ CDfName const dfnIllegal(wcsIllegalName);
+
+ olChk(_pdf->RenameEntry(&dfn, &dfnIllegal));
+ fRenamed = TRUE;
+ }
+ else
+ olErr(EH_Err, STG_E_FILEALREADYEXISTS);
+ }
+ if (REAL_STGTY(dwType) == STGTY_STREAM)
+ {
+ olChk(_pdf->CreateStream(&dfn, ModeToDFlags(grfMode), dwType, &pst));
+ olMemTo(EH_pst, pstExp = new CExposedStream);
+ olChkTo(EH_pstExp, pstExp->Init(pst, NULL));
+ *ppv = pstExp;
+ }
+ else
+ {
+ olAssert(REAL_STGTY(dwType) == STGTY_STORAGE);
+ olChk(_pdf->CreateDocFile(&dfn, ModeToDFlags(grfMode), dwType, &pdf));
+ olMemTo(EH_pdf, pdfExp = new CExposedDocFile(pdf));
+ // If we've renamed the original stream for conversion, convert
+ if (fRenamed)
+ {
+ olChkTo(EH_pdfExpInit, ConvertInternalStream(pdfExp));
+ sc = STG_S_CONVERTED;
+ }
+ *ppv = pdfExp;
+ }
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::CreateEntry\n"));
+ return sc;
+
+ EH_pstExp:
+ delete pstExp;
+ EH_pst:
+ pst->CPubStream::vRelease();
+ goto EH_Del;
+
+ EH_pdfExpInit:
+ pdfExp->Release();
+ goto EH_Del;
+ EH_pdf:
+ pdf->CPubDocFile::vRelease();
+ // Fall through
+ EH_Del:
+ olVerSucc(_pdf->DestroyEntry(&dfn, TRUE));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::OpenEntry, private
+//
+// Synopsis: Opens elements, used in OpenStream, OpenStorage and
+// for properties
+//
+// Arguments: [pwcsName] - Name
+// [dwType] - Entry type
+// [grfMode] - Access mode
+// [ppv] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppv]
+//
+//----------------------------------------------------------------------------
+
+
+SCODE CExposedDocFile::OpenEntry(WCHAR const *pwcsName,
+ DWORD dwType,
+ DWORD grfMode,
+ void **ppv)
+{
+ CDfName dfn;
+ SCODE sc;
+ CPubDocFile *pdf;
+ CExposedDocFile *pdfExp;
+ CPubStream *pst;
+ CExposedStream *pstExp;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::OpenEntry:%p("
+ "%ws, %lX, %lX, %p)\n", this, pwcsName, dwType, grfMode, ppv));
+ olChk(EnforceSingle(grfMode));
+ dfn.Set(pwcsName);
+
+
+ if (REAL_STGTY(dwType) == STGTY_STREAM)
+ {
+ olChk(_pdf->GetStream(&dfn, ModeToDFlags(grfMode), dwType, &pst));
+ olMemTo(EH_pst, pstExp = new CExposedStream);
+ olChkTo(EH_pstExp, pstExp->Init(pst, NULL));
+ *ppv = pstExp;
+ }
+ else
+ {
+ olAssert(REAL_STGTY(dwType) == STGTY_STORAGE);
+ olChk(_pdf->GetDocFile(&dfn, ModeToDFlags(grfMode), dwType, &pdf));
+ olMemTo(EH_pdf, pdfExp = new CExposedDocFile(pdf));
+ *ppv = pdfExp;
+ }
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::OpenEntry\n"));
+ return S_OK;
+
+ EH_pstExp:
+ delete pstExp;
+ // Fall through to clean up CPubStream
+ EH_pst:
+ pst->CPubStream::vRelease();
+ return sc;
+
+ EH_pdf:
+ pdf->CPubDocFile::vRelease();
+ // Fall through
+ EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CreateStream, public
+//
+// Synopsis: Creates a stream
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [reserved1]
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+//---------------------------------------------------------------
+
+
+TSTDMETHODIMP CExposedDocFile::CreateStream(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::CreateStream("
+ "%ws, %lX, %lu, %lu, %p)\n", pwcsName, grfMode, reserved1,
+ reserved2, ppstm));
+ olLog(("%p::In CExposedDocFile::CreateStream(%ws, %lX, %lu, %lu, %p)\n",
+ this, pwcsName, grfMode, reserved1, reserved2, ppstm));
+ TRY
+ {
+ if (reserved1 != 0 || reserved2 != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(VerifyPerms(grfMode));
+ if (grfMode & (STGM_CONVERT | STGM_TRANSACTED | STGM_PRIORITY |
+ STGM_DELETEONRELEASE))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ olChk(Validate());
+ olChk(CheckCopyTo());
+ sc = CreateEntry(pwcsName, STGTY_STREAM, grfMode, (void **)ppstm);
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::CreateStream => %p\n",
+ *ppstm));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::CreateStream(). "
+ "*ppstm == %p, ret == %lx\n", this, *ppstm, sc));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::OpenStream, public
+//
+// Synopsis: Opens an existing stream
+//
+// Arguments: [pwcsName] - Name
+// [reserved1]
+// [grfMode] - Permissions
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+//---------------------------------------------------------------
+
+
+TSTDMETHODIMP CExposedDocFile::OpenStream(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::OpenStream("
+ "%ws, %p, %lX, %lu, %p)\n", pwcsName, reserved1,
+ grfMode, reserved2, ppstm));
+ olLog(("%p::In CExposedDocFile::OpenStream(%ws, %lu %lX, %lu, %p)\n",
+ this, pwcsName, reserved1, grfMode, reserved2, ppstm));
+ TRY
+ {
+ if (reserved1 != NULL || reserved2 != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(VerifyPerms(grfMode));
+ if (grfMode & (STGM_TRANSACTED | STGM_PRIORITY |
+ STGM_DELETEONRELEASE))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ olChk(Validate());
+ sc = OpenEntry(pwcsName, STGTY_STREAM, grfMode, (void **)ppstm);
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::OpenStream => %p\n",
+ *ppstm));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::OpenStream(). "
+ "*ppstm == %p, ret == %lx\n", this, *ppstm, sc));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CreateStorage, public
+//
+// Synopsis: Creates an embedded DocFile
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [reserved1]
+// [reserved2]
+// [ppstg] - New DocFile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+//---------------------------------------------------------------
+
+
+TSTDMETHODIMP CExposedDocFile::CreateStorage(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStorage **ppstg)
+{
+ SCODE sc;
+
+ olLog(("%p::In CExposedDocFile::CreateStorage(%ws, %lX, %lu, %lu, %p)\n",
+ this, pwcsName, grfMode, reserved1, reserved2, ppstg));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::CreateStorage:%p("
+ "%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode,
+ reserved1, reserved2, ppstg));
+ TRY
+ {
+ if (reserved1 != 0 || reserved2 != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(VerifyPerms(grfMode));
+ if (grfMode & (STGM_PRIORITY | STGM_DELETEONRELEASE))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ olChk(Validate());
+ olChk(CheckCopyTo());
+ sc = CreateEntry(pwcsName, STGTY_STORAGE, grfMode, (void **)ppstg);
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::CreateStorage => %p\n",
+ *ppstg));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::CreateStorage(). "
+ "*ppstg == %p, ret == %lX\n", this, *ppstg, sc));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::OpenStorage, public
+//
+// Synopsis: Gets an existing embedded DocFile
+//
+// Arguments: [pwcsName] - Name
+// [pstgPriority] - Priority reopens
+// [grfMode] - Permissions
+// [snbExclude] - Priority reopens
+// [reserved]
+// [ppstg] - DocFile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+//---------------------------------------------------------------
+
+
+TSTDMETHODIMP CExposedDocFile::OpenStorage(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNBW snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+{
+ SCODE sc;
+ CExposedDocFile *pdfExp;
+
+ olLog(("%p::In CExposedDocFile::OpenStorage(%ws, %p, %lX, %p, %lu, %p)\n",
+ this, pwcsName, pstgPriority, grfMode, snbExclude, reserved,
+ ppstg));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::OpenStorage:%p("
+ "%ws, %p, %lX, %p, %lu, %p)\n", this, pwcsName, pstgPriority,
+ grfMode, snbExclude, reserved, ppstg));
+ TRY
+ {
+ if (reserved != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(VerifyPerms(grfMode));
+ if (pstgPriority != NULL ||
+ (grfMode & (STGM_PRIORITY | STGM_DELETEONRELEASE)))
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ olChk(Validate());
+ if (snbExclude != NULL)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(OpenEntry(pwcsName, STGTY_STORAGE, grfMode, (void **)&pdfExp));
+ *ppstg = pdfExp;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::OpenStorage => %p\n",
+ *ppstg));
+ EH_Err:
+ olLog(("%p::Out CExposedDocFile::OpenStorage(). "
+ "*ppstg == %p, ret == %lX\n", this, *ppstg, sc));
+ return sc;
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::MakeCopyFlags, public
+//
+// Synopsis: Translates IID array into bit fields
+//
+// Arguments: [ciidExclude] - Count of IIDs
+// [rgiidExclude] - IIDs not to copy
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+
+DWORD CExposedDocFile::MakeCopyFlags(DWORD ciidExclude,
+ IID const *rgiidExclude)
+{
+ DWORD dwCopyFlags;
+
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::MakeCopyFlags(%lu, %p)\n",
+ ciidExclude, rgiidExclude));
+ // Copy everything by default
+ dwCopyFlags = COPY_ALL;
+ for (; ciidExclude > 0; ciidExclude--, rgiidExclude++)
+ if (IsEqualIID(*rgiidExclude, IID_IStorage))
+ dwCopyFlags &= ~COPY_STORAGES;
+ else if (IsEqualIID(*rgiidExclude, IID_IStream))
+ dwCopyFlags &= ~COPY_STREAMS;
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::MakeCopyFlags\n"));
+ return dwCopyFlags;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::CopyTo, public
+//
+// Synopsis: Makes a copy of a DocFile
+//
+// Arguments: [ciidExclude] - Length of rgiid array
+// [rgiidExclude] - Array of IIDs to exclude
+// [snbExclude] - Names to exclude
+// [pstgDest] - Parent of copy
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+TSTDMETHODIMP CExposedDocFile::CopyTo(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNBW snbExclude,
+ IStorage *pstgDest)
+{
+ SCODE sc;
+ DWORD i;
+
+ olLog(("%p::In CExposedDocFile::CopyTo(%lu, %p, %p, %p)\n",
+ this, ciidExclude, rgiidExclude, snbExclude, pstgDest));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::Copy(%lu, %p, %p, %p)\n",
+ ciidExclude, rgiidExclude, snbExclude, pstgDest));
+
+ TRY
+ {
+ olChk(ValidateInterface(pstgDest, IID_IStorage));
+ if (rgiidExclude)
+ {
+ olAssert(sizeof(IID)*ciidExclude <= 0xffffUL);
+ olChk(ValidateBuffer(rgiidExclude,
+ (size_t)(sizeof(IID)*ciidExclude)));
+ for (i = 0; i<ciidExclude; i++)
+ olChk(ValidateIid(rgiidExclude[i]));
+ }
+ olChk(Validate());
+ olChk(_pdf->CheckReverted());
+
+ // BUGBUG - DeleteContents should really be a method on IStorage
+ // so that we can call pstgDest->DeleteContents() rather than
+ // having to give our own implementation.
+
+ olChk(CopyDocFileToIStorage(_pdf->GetDF(), pstgDest, snbExclude,
+ MakeCopyFlags(ciidExclude, rgiidExclude)));
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::Copy\n"));
+EH_Err:
+ olLog(("%p::Out ExposedDocFile::CopyTo(). ret == %lX\n",this, sc));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::Commit, public
+//
+// Synopsis: Commits transacted changes
+//
+// Arguments: [dwFlags] - DFC_*
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::Commit(DWORD dwFlags)
+{
+ SCODE sc;
+
+ olLog(("%p::In CExposedDocFile::Commit(%lX)\n",this, dwFlags));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::Commit(%lX)\n", dwFlags));
+ TRY
+ {
+ if (!VALID_COMMIT(dwFlags))
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ olChk(Validate());
+ olChk(_pdf->Commit(dwFlags));
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::Commit\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::Commit(). ret == %lx\n",this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::Revert, public
+//
+// Synopsis: Reverts transacted changes
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::Revert(void)
+{
+ SCODE sc;
+
+ olLog(("%p::In CExposedDocFile::Revert()\n", this));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::Revert\n"));
+ TRY
+ {
+ olChk(Validate());
+ olChk(_pdf->Revert());
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::Revert\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::Revert(). ret == %lx\n", this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::EnumElements, public
+//
+// Synopsis: Starts an iterator
+//
+// Arguments: [reserved1]
+// [reserved2]
+// [reserved3]
+// [ppenm] - Enumerator return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::EnumElements(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm)
+{
+ SCODE sc;
+ CPubIter *ppi;
+ CExposedIterator *pdiExp;
+
+ olLog(("%p::In CExposedDocFile::EnumElements(%lu, %p, %lu, %p)\n",
+ this, reserved1, reserved2, reserved3, ppenm));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::EnumElements(%p)\n",
+ ppenm));
+ TRY
+ {
+ olChk(ValidateOutPtrBuffer(ppenm));
+ *ppenm = NULL;
+ if (reserved1 != 0 || reserved2 != NULL || reserved3 != 0)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olChk(Validate());
+ if (!P_READ(_pdf->GetDFlags()))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+ olChk(_pdf->GetIterator(FALSE, &ppi));
+ olMemTo(EH_ppi, pdiExp = new CExposedIterator(ppi, 0));
+ *ppenm = pdiExp;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::EnumElements => %p\n",
+ *ppenm));
+ olLog(("%p::Out CExposedDocFile::EnumElements(). ret == %lx\n",this, sc));
+ return ResultFromScode(sc);
+
+EH_ppi:
+ ppi->CPubIter::vRelease();
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::EnumElements(). ret == %lx\n",this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::DestroyElement, public
+//
+// Synopsis: Permanently deletes an element of a DocFile
+//
+// Arguments: [pwcsName] - Name of element
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+TSTDMETHODIMP CExposedDocFile::DestroyElement(WCHAR const *pwcsName)
+{
+ SCODE sc;
+ CDfName dfn;
+
+ olLog(("%p::In CExposedDocFile::DestroyElement(%ws)\n", this, pwcsName));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::DestroyElement(%ws)\n",
+ pwcsName));
+ TRY
+ {
+ olChk(Validate());
+ dfn.Set(pwcsName);
+ olChk(_pdf->DestroyEntry(&dfn, FALSE));
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::DestroyElement\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::DestroyElement(). ret == %lx\n",
+ this, sc));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::MoveElementTo, public
+//
+// Synopsis: Move an element of a DocFile to an IStorage
+//
+// Arguments: [pwcsName] - Current name
+// [ptcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// Algorithm: Open source as storage or stream (whatever works)
+// Create appropriate destination
+// Copy source to destination
+// Set create time of destination equal to create time of source
+// If appropriate, delete source
+//
+//---------------------------------------------------------------
+
+
+TSTDMETHODIMP CExposedDocFile::MoveElementTo(WCHAR const *pwcsName,
+ IStorage *pstgParent,
+ TCHAR const *ptcsNewName,
+ DWORD grfFlags)
+{
+ IUnknown *punksrc = NULL;
+ SCODE sc;
+
+ olLog(("%p::In CExposedDocFile::MoveElementTo(%ws, %p, %s, %lu)\n",
+ this, pwcsName, pstgParent, ptcsNewName, grfFlags));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::MoveElementTo("
+ "%ws, %p, %s, %lu)\n",
+ pwcsName, pstgParent, ptcsNewName, grfFlags));
+ TRY
+ {
+ IUnknown *punkdst;
+ IStorage *pstgsrc;
+ STATSTG statstg;
+
+ olChk(Validate());
+ olChk(VerifyMoveFlags(grfFlags));
+
+ // determine source type (determine its type)
+
+ sc = OpenStorage(pwcsName, NULL,
+ STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
+ NULL, NULL, &pstgsrc);
+
+ if (SUCCEEDED(sc))
+ {
+ HRESULT hr;
+
+ // It's a storage
+ punksrc = pstgsrc;
+
+ IStorage *pstgdst;
+ olHChkTo(EH_UnkSrc, pstgsrc->Stat(&statstg, STATFLAG_NONAME));
+
+ hr = pstgParent->CreateStorage(ptcsNewName,
+ STGM_DIRECT |
+ STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE
+ | STGM_FAILIFTHERE,
+ 0, 0, &pstgdst);
+ if (DfGetScode(hr) == STG_E_FILEALREADYEXISTS &&
+ grfFlags == STGMOVE_COPY)
+ {
+ hr = pstgParent->OpenStorage(ptcsNewName,
+ NULL,
+ STGM_DIRECT |
+ STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE,
+ NULL,
+ 0, &pstgdst);
+ }
+ olHChkTo(EH_UnkSrc, hr);
+
+ punkdst = pstgdst;
+
+ sc = DfGetScode(pstgsrc->CopyTo(0, NULL, NULL, pstgdst));
+ }
+ else if (sc == STG_E_FILENOTFOUND)
+ {
+ // Try opening it as a stream
+
+ IStream *pstmsrc, *pstmdst;
+ olChk(OpenStream(pwcsName, NULL,
+ STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
+ NULL, &pstmsrc));
+
+ // It's a stream
+ punksrc = pstmsrc;
+
+ olHChkTo(EH_UnkSrc, pstmsrc->Stat(&statstg, STATFLAG_NONAME));
+
+ olHChkTo(EH_UnkSrc,
+ pstgParent->CreateStream(ptcsNewName,
+ STGM_DIRECT |
+ STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE |
+ (grfFlags == STGMOVE_MOVE ?
+ STGM_FAILIFTHERE :
+ STGM_CREATE),
+ 0, 0, &pstmdst));
+
+ punkdst = pstmdst;
+
+ ULARGE_INTEGER cb;
+ ULISetLow (cb, 0xffffffff);
+ ULISetHigh(cb, 0xffffffff);
+ sc = DfGetScode(pstmsrc->CopyTo(pstmdst, cb, NULL, NULL));
+ }
+ else
+ olChk(sc);
+
+ punkdst->Release();
+
+ if (SUCCEEDED(sc))
+ {
+ // Make destination create time match source create time
+ // Note that we don't really care if this call succeeded.
+
+ pstgParent->SetElementTimes(ptcsNewName, &statstg.ctime,
+ NULL, NULL);
+
+ if ((grfFlags & STGMOVE_COPY) == STGMOVE_MOVE)
+ sc = DestroyElement(pwcsName);
+ }
+
+ if (FAILED(sc))
+ {
+ // The copy/move failed, so get rid of the partial result.
+
+ pstgParent->DestroyElement(ptcsNewName);
+ }
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::MoveElementTo\n"));
+ // Fall through
+EH_UnkSrc:
+ if (punksrc)
+ punksrc->Release();
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::MoveElementTo(). ret == %lx\n",
+ this, sc));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::RenameElement, public
+//
+// Synopsis: Renames an element of a DocFile
+//
+// Arguments: [pwcsName] - Current name
+// [pwcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+TSTDMETHODIMP CExposedDocFile::RenameElement(WCHAR const *pwcsName,
+ WCHAR const *pwcsNewName)
+{
+ SCODE sc;
+ CDfName dfnOld, dfnNew;
+
+ olLog(("%p::In CExposedDocFile::RenameElement(%ws, %ws)\n",
+ this, pwcsName, pwcsNewName));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::RenameElement(%ws, %ws)\n",
+ pwcsName, pwcsNewName));
+ TRY
+ {
+ olChk(Validate());
+ dfnOld.Set(pwcsName);
+ dfnNew.Set(pwcsNewName);
+ olChk(_pdf->RenameEntry(&dfnOld, &dfnNew));
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::RenameElement\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::RenameElement(). ret == %lx\n",
+ this, sc));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::SetElementTimes, public
+//
+// Synopsis: Sets element time stamps
+//
+// Arguments: [pwcsName] - Name
+// [pctime] - create time
+// [patime] - access time
+// [pmtime] - modify time
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+TSTDMETHODIMP CExposedDocFile::SetElementTimes(WCHAR const *pwcsName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ SCODE sc;
+ CDfName dfn;
+
+ olLog(("%p::In CExposedDocFile::SetElementTimes(%ws, %p, %p, %p)\n",
+ this, pwcsName, pctime, patime, pmtime));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::SetElementTimes:%p("
+ "%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime));
+ TRY
+ {
+ olChk(Validate());
+ if (pctime)
+ ValidateBuffer(pctime, sizeof(FILETIME));
+ if (patime)
+ ValidateBuffer(patime, sizeof(FILETIME));
+ if (pmtime)
+ ValidateBuffer(pmtime, sizeof(FILETIME));
+ dfn.Set(pwcsName);
+ olChk(_pdf->SetElementTimes(&dfn, pctime, patime, pmtime));
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::SetElementTimes\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::SetElementTimes(). ret == %lx\n",
+ this, sc));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::SetClass, public
+//
+// Synopsis: Sets storage class
+//
+// Arguments: [clsid] - class id
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::SetClass(REFCLSID clsid)
+{
+ SCODE sc;
+
+ olLog(("%p::In CExposedDocFile::SetClass(?)\n", this));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::SetClass:%p(?)\n", this));
+ TRY
+ {
+ olChk(Validate());
+ olChk(ValidateBuffer(&clsid, sizeof(CLSID)));
+ olChk(_pdf->SetClass(clsid));
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::SetClass\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::SetClass(). ret == %lx\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::SetStateBits, public
+//
+// Synopsis: Sets state bits
+//
+// Arguments: [grfStateBits] - state bits
+// [grfMask] - state bits mask
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ SCODE sc;
+
+ olLog(("%p::In CExposedDocFile::SetStateBits(%lu, %lu)\n", this,
+ grfStateBits, grfMask));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::SetStateBits:%p("
+ "%lu, %lu)\n", this, grfStateBits, grfMask));
+ TRY
+ {
+ olChk(Validate());
+ olChk(_pdf->SetStateBits(grfStateBits, grfMask));
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::SetStateBits\n"));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::SetStateBits(). ret == %lx\n",
+ this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::Stat, public
+//
+// Synopsis: Fills in a buffer of information about this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+//---------------------------------------------------------------
+
+
+TSTDMETHODIMP CExposedDocFile::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+
+ olLog(("%p::In CExposedDocFile::Stat(%p)\n", this, pstatstg));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::Stat(%p)\n", pstatstg));
+ TRY
+ {
+ olChkTo(EH_RetSc, ValidateOutBuffer(pstatstg, sizeof(STATSTGW)));
+ olChk(VerifyStatFlag(grfStatFlag));
+ olChk(_pdf->Stat(pstatstg, grfStatFlag));
+ pstatstg->type = STGTY_STORAGE;
+ ULISet32(pstatstg->cbSize, 0);
+ pstatstg->grfLocksSupported = 0;
+ pstatstg->reserved = 0;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::Stat\n"));
+EH_Err:
+ if (FAILED(sc))
+ memset(pstatstg, 0, sizeof(STATSTGW));
+EH_RetSc:
+ olLog(("%p::Out CExposedDocFile::Stat(). *pstatstg == %p ret == %lx\n",
+ this, *pstatstg, sc));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP_(ULONG) CExposedDocFile::AddRef(void)
+{
+ ULONG ulRet;
+
+ olLog(("%p::In CExposedDocFile::AddRef()\n", this));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::AddRef()\n"));
+ TRY
+ {
+ if (FAILED(Validate()))
+ return 0;
+ AtomicInc(&_cReferences);
+ ulRet = _cReferences;
+ }
+ CATCH(CException, e)
+ {
+ UNREFERENCED_PARM(e);
+ ulRet = 0;
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::AddRef\n"));
+ olLog(("%p::Out CExposedDocFile::AddRef(). ret == %lu\n", this, ulRet));
+ return ulRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedDocFile::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ olLog(("%p::In CExposedDocFile::QueryInterface(?, %p)\n",
+ this, ppvObj));
+ olDebugOut((DEB_ITRACE, "In CExposedDocFile::QueryInterface(?, %p)\n",
+ ppvObj));
+ TRY
+ {
+ olChk(ValidateOutPtrBuffer(ppvObj));
+ *ppvObj = NULL;
+ olChk(ValidateIid(iid));
+ olChk(Validate());
+ olChk(_pdf->CheckReverted());
+ if (IsEqualIID(iid, IID_IStorage) || IsEqualIID(iid, IID_IUnknown))
+ {
+ olChk(AddRef());
+ *ppvObj = this;
+ }
+ else
+ olErr(EH_Err, E_NOINTERFACE);
+ sc = S_OK;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedDocFile::QueryInterface => %p\n",
+ ppvObj));
+EH_Err:
+ olLog(("%p::Out CExposedDocFile::QueryInterface(). *ppvObj == %p ret == %lx\n",
+ this, *ppvObj, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Method: CExposedDocFile::CopySStreamToIStream, private
+//
+// Synopsis: Copies a PSStream to an IStream
+//
+// Arguments: [psstFrom] - SStream
+// [pstTo] - IStream
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+SCODE CExposedDocFile::CopySStreamToIStream(PSStream *psstFrom,
+ IStream *pstTo)
+{
+ BYTE *pbBuffer;
+ SCODE sc;
+ ULONG cbRead, cbWritten, cbPos, cbSizeLow;
+ ULARGE_INTEGER cbSize;
+
+ // This is part of CopyTo and therefore we are allowed to
+ // fail with out-of-memory
+ olMem(pbBuffer = new BYTE[STREAMBUFFERSIZE]);
+
+ // Set destination size for contiguity
+ psstFrom->GetSize(&cbSizeLow);
+
+ ULISet32(cbSize, cbSizeLow);
+ // Don't need to SetAccess0 here because pstTo is an IStream
+ olHChk(pstTo->SetSize(cbSize));
+
+ // Copy between streams
+ cbPos = 0;
+ for (;;)
+ {
+ olChk(psstFrom->ReadAt(cbPos, pbBuffer, STREAMBUFFERSIZE,
+ (ULONG STACKBASED *)&cbRead));
+ if (cbRead == 0) // EOF
+ break;
+
+ // Don't need to SetAccess0 here because pstTo is an IStream
+ olHChk(pstTo->Write(pbBuffer, cbRead, &cbWritten));
+ if (cbRead != cbWritten)
+ olErr(EH_Err, STG_E_WRITEFAULT);
+ cbPos += cbWritten;
+ }
+ sc = S_OK;
+
+EH_Err:
+ delete [] pbBuffer;
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Method: CExposedDocFile::CopyDocFileToIStorage, private
+//
+// Synopsis: Copies a docfile's contents to an IStorage
+//
+// Arguments: [pdfFrom] - From
+// [pstgTo] - To
+// [snbExclude] - Names to not copy
+// [dwCopyFlags] - Bitwise flags for types of objects to copy
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+SCODE CExposedDocFile::CopyDocFileToIStorage(PDocFile *pdfFrom,
+ IStorage *pstgTo,
+ SNBW snbExclude,
+ DWORD dwCopyFlags)
+{
+ PDocFileIterator *pdfi;
+ SIterBuffer ib;
+ PSStream *psstFrom;
+ IStream *pstTo;
+ PDocFile *pdfFromChild;
+ IStorage *pstgToChild;
+ SCODE sc;
+ TCHAR atcName[CWCSTORAGENAME];
+ CLSID clsid;
+ DWORD grfStateBits;
+
+ olDebugOut((DEB_ITRACE, "In CopyDocFileToIStorage:%p(%p, %p, %p, %lX)\n",
+ this, pdfFrom, pstgTo, snbExclude, dwCopyFlags));
+
+ olChk(pdfFrom->GetClass(&clsid));
+
+ olHChk(pstgTo->SetClass(clsid));
+
+ olChk(pdfFrom->GetStateBits(&grfStateBits));
+
+ olHChk(pstgTo->SetStateBits(grfStateBits, 0xffffffff));
+
+ olChk(pdfFrom->GetIterator(&pdfi));
+
+ for (;;)
+ {
+ sc = pdfi->BufferGetNext(&ib);
+
+ if (sc == STG_E_NOMOREFILES)
+ break;
+ else if (FAILED(sc))
+ olErr(EH_pdfi, sc);
+
+ if (snbExclude && NameInSNB(&ib.dfnName, snbExclude) == S_OK)
+ continue;
+
+ if ((ib.type == STGTY_STORAGE && (dwCopyFlags & COPY_STORAGES) == 0) ||
+ (ib.type == STGTY_STREAM && (dwCopyFlags & COPY_STREAMS) == 0)
+ )
+ continue;
+
+ switch(ib.type)
+ {
+ case STGTY_STORAGE:
+ // Embedded DocFile, create destination and recurse
+
+ sc = pdfFrom->GetDocFile(&ib.dfnName, DF_READ,
+ ib.type, &pdfFromChild);
+ olChkTo(EH_pdfi, sc);
+ wcstombs(atcName, (WCHAR *)ib.dfnName.GetBuffer(), CWCSTORAGENAME);
+
+ // Don't need to SetAccess0 here because pstgTo is an IStorage.
+
+ sc = DfGetScode(pstgTo->CreateStorage(atcName, STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_FAILIFTHERE,
+ 0, 0, &pstgToChild));
+ if (sc == STG_E_FILEALREADYEXISTS)
+ olHChkTo(EH_Get, pstgTo->OpenStorage(atcName, NULL,
+ STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE,
+ NULL, 0, &pstgToChild));
+ else if (FAILED(sc))
+ olErr(EH_Get, sc);
+ olChkTo(EH_Create,
+ CopyDocFileToIStorage(pdfFromChild, pstgToChild, NULL,
+ dwCopyFlags));
+ pdfFromChild->Release();
+ pstgToChild->Release();
+ break;
+
+ case STGTY_STREAM:
+ sc = pdfFrom->GetStream(&ib.dfnName, DF_READ, ib.type, &psstFrom);
+ olChkTo(EH_pdfi, sc);
+ wcstombs(atcName, (WCHAR *)ib.dfnName.GetBuffer(), CWCSTORAGENAME);
+
+ // Don't need to SetAccess0 here because pstgTo is an IStorage.
+
+ olHChkTo(EH_Get,
+ pstgTo->CreateStream(atcName, STGM_WRITE |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_CREATE,
+ 0, 0, &pstTo));
+ olChkTo(EH_Create, CopySStreamToIStream(psstFrom, pstTo));
+ psstFrom->Release();
+ pstTo->Release();
+ break;
+
+
+ default:
+ olAssert(!aMsg("Unknown type in CopyDocFileToIStorage"));
+ break;
+ }
+ }
+ pdfi->Release();
+ olDebugOut((DEB_ITRACE, "Out CopyDocFileToIStorage\n"));
+ return S_OK;
+
+EH_Create:
+ if (ib.type == STGTY_STORAGE)
+ pstgToChild->Release();
+ else
+ pstTo->Release();
+ olVerSucc(pstgTo->DestroyElement(atcName));
+EH_Get:
+ if (ib.type == STGTY_STORAGE)
+ pdfFromChild->Release();
+ else
+ psstFrom->Release();
+EH_pdfi:
+ pdfi->Release();
+EH_Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExposedDocFile::SwitchToFile, public
+//
+// Synopsis: Switches the underlying file to another file
+//
+// Arguments: [ptcsFile] - New file name
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+
+STDMETHODIMP CExposedDocFile::SwitchToFile(TCHAR *ptcsFile)
+{
+ return ResultFromScode(STG_E_UNIMPLEMENTEDFUNCTION);
+}
+
diff --git a/private/ole32/stg/ref/expdf.hxx b/private/ole32/stg/ref/expdf.hxx
new file mode 100644
index 000000000..7aeb36e86
--- /dev/null
+++ b/private/ole32/stg/ref/expdf.hxx
@@ -0,0 +1,206 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: expdf.hxx
+//
+// Contents: Exposed DocFile header
+//
+// Classes: CExposedDocFile
+//
+//---------------------------------------------------------------
+
+#ifndef __EXPDF_HXX__
+#define __EXPDF_HXX__
+
+#include <dfmsp.hxx>
+#include <psstream.hxx>
+
+
+// CopyDocFileToIStorage flags
+#define COPY_STORAGES 1
+#define COPY_STREAMS 2
+#define COPY_PROPERTIES 4
+#define COPY_ALL (COPY_STORAGES | COPY_STREAMS | COPY_PROPERTIES)
+
+class CPubDocFile;
+class PDocFile;
+
+//+--------------------------------------------------------------
+//
+// Class: CExposedDocFile (df)
+//
+// Purpose: Exposed DocFile class
+//
+// Interface: See IStorage
+//
+//---------------------------------------------------------------
+
+
+interface CExposedDocFile : public IStorage, public IRootStorage
+{
+public:
+ CExposedDocFile(CPubDocFile *pdf);
+ inline
+ ~CExposedDocFile(void);
+
+ // From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+
+ // IStorage
+ STDMETHOD(CreateStream)(TCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(OpenStream)(TCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(CreateStorage)(TCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStorage **ppstg);
+ STDMETHOD(OpenStorage)(TCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg);
+ STDMETHOD(CopyTo)(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest);
+ STDMETHOD(MoveElementTo)(TCHAR const *lpszName,
+ IStorage *pstgDest,
+ TCHAR const *lpszNewName,
+ DWORD grfFlags);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(EnumElements)(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm);
+ STDMETHOD(DestroyElement)(TCHAR const *pwcsName);
+ STDMETHOD(RenameElement)(TCHAR const *pwcsOldName,
+ TCHAR const *pwcsNewName);
+ STDMETHOD(SetElementTimes)(const TCHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+ STDMETHOD(SetClass)(REFCLSID clsid);
+ STDMETHOD(SetStateBits)(DWORD grfStateBits, DWORD grfMask);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+
+ SCODE CreateStream(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm);
+ SCODE OpenStream(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm);
+ SCODE CreateStorage(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStorage **ppstg);
+ SCODE OpenStorage(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNBW snbExclude,
+ DWORD reserved,
+ IStorage **ppstg);
+ SCODE CopyTo(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNBW snbExclude,
+ IStorage *pstgDest);
+ SCODE MoveElementTo(WCHAR const *pwcsName,
+ IStorage *pstgDest,
+ TCHAR const *ptcsNewName,
+ DWORD grfFlags);
+ SCODE DestroyElement(WCHAR const *pwcsName);
+ SCODE RenameElement(WCHAR const *pwcsOldName,
+ WCHAR const *pwcsNewName);
+ SCODE SetElementTimes(WCHAR const *pwcsName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+ SCODE Stat(STATSTGW *pstatstg, DWORD grfStatFlag);
+
+ // IRootStorage
+ STDMETHOD(SwitchToFile)(TCHAR *ptcsFile);
+
+
+ // New methods
+ inline SCODE Validate(void) const;
+ inline CPubDocFile *GetPub(void) const;
+
+
+private:
+ SCODE CreateEntry(WCHAR const *pwcsName,
+ DWORD dwType,
+ DWORD grfMode,
+ void **ppv);
+ SCODE OpenEntry(WCHAR const *pwcsName,
+ DWORD dwType,
+ DWORD grfMode,
+ void **ppv);
+ static DWORD MakeCopyFlags(DWORD ciidExclude,
+ IID const *rgiidExclude);
+ SCODE CopyDocFileToIStorage(PDocFile *pdfFrom,
+ IStorage *pstgTo,
+ SNBW snbExclude,
+ DWORD dwCopyFlags);
+ SCODE CopySStreamToIStream(PSStream *psstFrom, IStream *pstTo);
+ SCODE ConvertInternalStream(CExposedDocFile *pdfExp);
+ inline SCODE CheckCopyTo(void);
+
+ CPubDocFile *_pdf;
+ ULONG _sig;
+ LONG _cReferences;
+ ULONG _ulAccessLockBase;
+};
+
+#define CEXPOSEDDOCFILE_SIG LONGSIG('E', 'D', 'F', 'L')
+#define CEXPOSEDDOCFILE_SIGDEL LONGSIG('E', 'd', 'F', 'l')
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::Validate, public
+//
+// Synopsis: Validates the class signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for failure
+//
+//---------------------------------------------------------------
+
+inline SCODE CExposedDocFile::Validate(void) const
+{
+ return (this == NULL || _sig != CEXPOSEDDOCFILE_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedDocFile::GetPub, public
+//
+// Synopsis: Returns the public
+//
+//---------------------------------------------------------------
+
+inline CPubDocFile *CExposedDocFile::GetPub(void) const
+{
+ return _pdf;
+}
+
+
+#endif
diff --git a/private/ole32/stg/ref/exphead.cxx b/private/ole32/stg/ref/exphead.cxx
new file mode 100644
index 000000000..3c5e2ab6f
--- /dev/null
+++ b/private/ole32/stg/ref/exphead.cxx
@@ -0,0 +1,29 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: exphead.cxx
+//
+// Contents: Precompiled headers
+//
+//--------------------------------------------------------------------------
+
+
+#include <malloc.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <ref.hxx>
+
+
+#include <dfexcept.hxx>
+#include <docfilep.hxx>
+
+#include <msf.hxx>
+
+#include <publicdf.hxx>
+#include <funcs.hxx>
+#include <piter.hxx>
diff --git a/private/ole32/stg/ref/expiter.cxx b/private/ole32/stg/ref/expiter.cxx
new file mode 100644
index 000000000..5588b09dd
--- /dev/null
+++ b/private/ole32/stg/ref/expiter.cxx
@@ -0,0 +1,333 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: expiter.cxx
+//
+// Contents: CExposedIterator implementation
+//
+//---------------------------------------------------------------
+
+#include <exphead.cxx>
+
+#include <expiter.hxx>
+#include <sstream.hxx>
+#include <pubiter.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::CExposedIterator, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [ppi] - Public iterator
+// [ulOffset] - Initial offset
+// [pdfb] - DocFile basis
+// [ppc] - Context
+// [fOwnContext] - Whether this object owns the context
+//
+//---------------------------------------------------------------
+
+CExposedIterator::CExposedIterator(CPubIter *ppi,
+ ULONG ulOffset)
+{
+ olDebugOut((DEB_ITRACE, "In CExposedIterator::CExposedIterator("
+ "%p, %lu)\n", ppi, ulOffset));
+ _ppi = ppi;
+ _ulOffset = ulOffset;
+ _cReferences = 1;
+ _ulAccessLockBase = 0;
+ _sig = CEXPOSEDITER_SIG;
+ olDebugOut((DEB_ITRACE, "Out CExposedIterator::CExposedIterator\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::~CExposedIterator, public
+//
+// Synopsis: Destructor
+//
+//---------------------------------------------------------------
+
+CExposedIterator::~CExposedIterator(void)
+{
+ olDebugOut((DEB_ITRACE, "In CExposedIterator::~CExposedIterator\n"));
+ _sig = CEXPOSEDITER_SIGDEL;
+ olAssert(_cReferences == 0);
+ if (_ppi)
+ _ppi->CPubIter::vRelease();
+ olDebugOut((DEB_ITRACE, "Out CExposedIterator::~CExposedIterator\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::Next, public
+//
+// Synopsis: Gets N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+// [rgelt] - Array for element return
+// [pceltFetched] - If non-NULL, contains the number of
+// elements fetched
+//
+// Returns: Appropriate status code
+//
+// Modifies: [rgelt]
+// [pceltFetched]
+//
+//---------------------------------------------------------------
+
+TSTDMETHODIMP CExposedIterator::Next(ULONG celt,
+ STATSTGW FAR *rgelt,
+ ULONG *pceltFetched)
+{
+ SCODE sc;
+ STATSTGW *pelt = rgelt;
+ ULONG celtDone;
+
+ olDebugOut((DEB_ITRACE, "In CExposedIterator::Next(%lu, %p, %p)\n",
+ celt, rgelt, pceltFetched));
+ TRY
+ {
+ if (pceltFetched == NULL && celt > 1)
+ olErr(EH_Err, STG_E_INVALIDPARAMETER);
+ olAssert(0xffffUL/sizeof(STATSTGW) >= celt);
+ olChkTo(EH_RetSc, ValidateOutBuffer(rgelt,
+ (size_t)(sizeof(STATSTGW)*celt)));
+ memset(rgelt, 0, (size_t)(sizeof(STATSTGW)*celt));
+ olChk(Validate());
+ olChk(_ppi->CheckReverted());
+ for (; pelt<rgelt+celt; pelt++)
+ {
+ sc = _ppi->Next(_ulOffset, pelt);
+ if (sc == S_FALSE || FAILED(sc))
+ break;
+ _ulOffset++;
+ }
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedIterator::Next => %lX\n", sc));
+EH_Err:
+ celtDone = pelt-rgelt;
+ if (FAILED(sc))
+ {
+ ULONG i;
+
+ for (i = 0; i<celtDone; i++)
+ delete[] rgelt[i].pwcsName;
+ memset(rgelt, 0, (size_t)(sizeof(STATSTGW)*celt));
+ }
+ else if (pceltFetched)
+ *pceltFetched = celtDone;
+EH_RetSc:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::Skip, public
+//
+// Synopsis: Skips N entries from an iterator
+//
+// Arguments: [celt] - Count of elements
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedIterator::Skip(ULONG celt)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CExposedIterator::Skip(%lu)\n", celt));
+ TRY
+ {
+ olChk(Validate());
+ sc = hSkip(celt);
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedIterator::Skip\n"));
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::Reset, public
+//
+// Synopsis: Rewinds the iterator
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedIterator::Reset(void)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CExposedIterator::Reset()\n"));
+ TRY
+ {
+ olChk(Validate());
+ sc = hReset();
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedIterator::Reset\n"));
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::Clone, public
+//
+// Synopsis: Clones this iterator
+//
+// Arguments: [ppenm] - Clone return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedIterator::Clone(IEnumSTATSTG **ppenm)
+{
+ SCODE sc;
+ CExposedIterator *piExp;
+
+ olDebugOut((DEB_ITRACE, "In CExposedIterator::Clone(%p)\n", ppenm));
+ TRY
+ {
+ olChk(ValidateOutPtrBuffer(ppenm));
+ *ppenm = NULL;
+ olChk(Validate());
+ olChk(_ppi->CheckReverted());
+ olMem(piExp = new CExposedIterator(_ppi, _ulOffset));
+ _ppi->vAddRef();
+ *ppenm = piExp;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedIterator::Clone => %p\n",
+ *ppenm));
+ // Fall through
+EH_Err:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::Release, public
+//
+// Synopsis: Releases resources for the iterator
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CExposedIterator::Release(void)
+{
+ LONG lRet;
+
+ olDebugOut((DEB_ITRACE, "In CExposedIterator::Release()\n"));
+ TRY
+ {
+ if (FAILED(Validate()))
+ return 0;
+ if ((lRet = hRelease()) == 0)
+ delete this;
+ }
+ CATCH(CException, e)
+ {
+ UNREFERENCED_PARM(e);
+ lRet = 0;
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedIterator::Release\n"));
+ return lRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CExposedIterator::AddRef(void)
+{
+ ULONG ulRet;
+
+ olDebugOut((DEB_ITRACE, "In CExposedIterator::AddRef()\n"));
+ TRY
+ {
+ if (FAILED(Validate()))
+ return 0;
+ ulRet = hAddRef();
+ }
+ CATCH(CException, e)
+ {
+ UNREFERENCED_PARM(e);
+ ulRet = 0;
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedIterator::AddRef\n"));
+ return ulRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedIterator::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CExposedIterator::QueryInterface(?, %p)\n",
+ ppvObj));
+ TRY
+ {
+ olChk(Validate());
+ sc = hQueryInterface(iid, IID_IEnumSTATSTG, ppvObj);
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedIterator::QueryInterface => %p\n",
+ ppvObj));
+EH_Err:
+ return ResultFromScode(sc);
+}
diff --git a/private/ole32/stg/ref/expiter.hxx b/private/ole32/stg/ref/expiter.hxx
new file mode 100644
index 000000000..a47f9d7dd
--- /dev/null
+++ b/private/ole32/stg/ref/expiter.hxx
@@ -0,0 +1,76 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: expiter.hxx
+//
+// Contents: CExposedIterator header file
+//
+// Classes: CExposedIterator
+//
+//---------------------------------------------------------------
+
+#ifndef __EXPITER_HXX__
+#define __EXPITER_HXX__
+
+#include <dfmsp.hxx>
+#include <lock.hxx>
+#include <peiter.hxx>
+
+class CPubIter;
+class CDirectStream;
+
+//+--------------------------------------------------------------
+//
+// Class: CExposedIterator (ei)
+//
+// Purpose: Iterator for wrapped DocFiles
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+interface CExposedIterator
+ : public IEnumSTATSTG, public PExposedIterator
+{
+public:
+ CExposedIterator(CPubIter *ppi, ULONG ulOffset);
+ ~CExposedIterator(void);
+
+ // From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // New methods
+ STDMETHOD(Next)(ULONG celt, STATSTG FAR *rgelt, ULONG *pceltFetched);
+ SCODE Next(ULONG celt, STATSTGW FAR *rgelt, ULONG *pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(IEnumSTATSTG **ppenm);
+
+ inline SCODE Validate(void) const;
+};
+
+// DocFileIter signatures
+#define CEXPOSEDITER_SIG LONGSIG('E', 'D', 'F', 'I')
+#define CEXPOSEDITER_SIGDEL LONGSIG('E', 'd', 'F', 'i')
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedIterator::Validate, public
+//
+// Synopsis: Validates the signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE if the signature doesn't match
+//
+//---------------------------------------------------------------
+
+inline SCODE CExposedIterator::Validate(void) const
+{
+ return (this == NULL || _sig != CEXPOSEDITER_SIG) ? STG_E_INVALIDHANDLE :
+ S_OK;
+}
+
+#endif
diff --git a/private/ole32/stg/ref/expst.cxx b/private/ole32/stg/ref/expst.cxx
new file mode 100644
index 000000000..403dc3ac6
--- /dev/null
+++ b/private/ole32/stg/ref/expst.cxx
@@ -0,0 +1,916 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) 1992, Microsoft Corporation.
+//
+// File: expst.cxx
+//
+// Contents: CExposedStream code
+//
+//--------------------------------------------------------------------------
+
+#include <exphead.cxx>
+
+#include <pbstream.hxx>
+#include <expst.hxx>
+#include <lock.hxx>
+#include <seekptr.hxx>
+#include <logfile.hxx>
+
+// Maximum stream size supported by exposed streams
+// This is MAX_ULONG with one subtracted so that
+// the seek pointer has a spot to sit even at the
+// end of the stream
+#define CBMAXSTREAM 0xfffffffeUL
+// Maximum seek pointer value
+#define CBMAXSEEK (CBMAXSTREAM+1)
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::CExposedStream, public
+//
+// Synopsis: Empty object constructor
+//
+//---------------------------------------------------------------
+
+
+CExposedStream::CExposedStream(void)
+{
+ olDebugOut((DEB_ITRACE, "In CExposedStream::CExposedStream()\n"));
+ _cReferences = 0;
+ _ulAccessLockBase = 0;
+ _psp = NULL;
+ _pst = NULL;
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::CExposedStream\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::InitWithSeekPtr, public
+//
+// Synopsis: Base constructor
+//
+// Arguments: [pst] - Public stream
+// [pdfb] - DocFile basis
+// [ppc] - Context
+// [fOwnContext] - Whether this object owns the context
+// [psp] - Seek pointer or NULL for new seek pointer
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+SCODE CExposedStream::Init(CPubStream *pst,
+ CSeekPointer *psp)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CExposedStream::Init("
+ "%p, %p)\n", pst, psp));
+ if (psp == NULL)
+ olMem(_psp = new CSeekPointer(0));
+ else
+ _psp = psp;
+ _pst = pst;
+ _cReferences = 1;
+ _sig = CEXPOSEDSTREAM_SIG;
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::InitWithSeekPtr\n"));
+ return S_OK;
+
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::~CExposedStream, public
+//
+// Synopsis: Destructor
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+inline
+CExposedStream::~CExposedStream(void)
+{
+ olDebugOut((DEB_ITRACE, "In CExposedStream::~CExposedStream\n"));
+ olAssert(_cReferences == 0);
+ _sig = CEXPOSEDSTREAM_SIGDEL;
+ if (_pst)
+ _pst->CPubStream::vRelease();
+ if (_psp)
+ _psp->CSeekPointer::vRelease();
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::~CExposedStream\n"));
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Read, public
+//
+// Synopsis: Read from a stream
+//
+// Arguments: [pb] - Buffer
+// [cb] - Count of bytes to read
+// [pcbRead] - Return number of bytes read
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::Read(VOID HUGEP *pb, ULONG cb, ULONG *pcbRead)
+{
+ SCODE sc;
+ ULONG cbRead = 0;
+
+ olLog(("%p::In CExposedStream::Read(%p, %lu, %p)\n",
+ this, pb, cb, pcbRead));
+ olDebugOut((DEB_ITRACE, "In CExposedStream::Read(%p, %lu, %p)\n",
+ pb, cb, pcbRead));
+ TRY
+ {
+ if (pcbRead)
+ {
+ olChkTo(EH_BadPtr, ValidateOutBuffer(pcbRead, sizeof(ULONG)));
+ }
+
+ olChk(ValidateHugeOutBuffer(pb, cb));
+ olChk(Validate());
+ sc = _pst->ReadAt(_psp->GetPos(), pb, cb,
+ (ULONG STACKBASED *)&cbRead);
+ olAssert(CBMAXSEEK-_psp->GetPos() >= cbRead);
+ _psp->SetPos(_psp->GetPos()+cbRead);
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::Read => %lu\n", cbRead));
+
+EH_Err:
+ if (pcbRead)
+ {
+ *pcbRead = cbRead;
+ olLog(("%p::Out CExposedStream::Read(). *pcbRead == %lu, ret = %lx\n",
+ this, *pcbRead, sc));
+ }
+ else
+ {
+ olLog(("%p::Out CExposedStream::Read(). ret == %lx\n", this, sc));
+ }
+
+EH_BadPtr:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Write, public
+//
+// Synopsis: Write to a stream
+//
+// Arguments: [pb] - Buffer
+// [cb] - Count of bytes to write
+// [pcbWritten] - Return of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbWritten]
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::Write(
+ VOID const HUGEP *pb,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ SCODE sc;
+ ULONG cbWritten = 0;
+
+ olLog(("%p::In CExposedStream::Write(%p, %lu, %p)\n",
+ this, pb, cb, pcbWritten));
+ olDebugOut((DEB_ITRACE, "In CExposedStream::Write(%p, %lu, %p)\n",
+ pb, cb, pcbWritten));
+ TRY
+ {
+ if (pcbWritten)
+ {
+ olChkTo(EH_BadPtr, ValidateOutBuffer(pcbWritten, sizeof(ULONG)));
+ }
+ olChk(ValidateHugeBuffer(pb, cb));
+ olChk(Validate());
+ sc = _pst->WriteAt(_psp->GetPos(), pb, cb,
+ (ULONG STACKBASED *)&cbWritten);
+ olAssert(CBMAXSEEK-_psp->GetPos() >= cbWritten);
+ _psp->SetPos(_psp->GetPos()+cbWritten);
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::Write => %lu\n",
+ cbWritten));
+EH_Err:
+ if (pcbWritten)
+ {
+ *pcbWritten = cbWritten;
+ olLog(("%p::Out CExposedStream::Write(). *pcbWritten == %lu, ret = %lx\n",
+ this, *pcbWritten, sc));
+ }
+ else
+ {
+ olLog(("%p::Out CExposedStream::Write(). ret == %lx\n",this, sc));
+ }
+
+EH_BadPtr:
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Seek, public
+//
+// Synopsis: Seek to a point in a stream
+//
+// Arguments: [dlibMove] - Offset to move by
+// [dwOrigin] - SEEK_SET, SEEK_CUR, SEEK_END
+// [plibNewPosition] - Return of new offset
+//
+// Returns: Appropriate status code
+//
+// Modifies: [plibNewPosition]
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::Seek(LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition)
+{
+ SCODE sc;
+ LONG lMove;
+ ULARGE_INTEGER ulPos;
+
+ olLog(("%p::In CExposedStream::Seek(%ld, %lu, %p)\n",
+ this, LIGetLow(dlibMove), dwOrigin, plibNewPosition));
+ olDebugOut((DEB_ITRACE, "In CExposedStream::Seek(%ld, %lu, %p)\n",
+ LIGetLow(dlibMove), dwOrigin, plibNewPosition));
+ TRY
+ {
+ if (plibNewPosition)
+ {
+ olChk(ValidateOutBuffer(plibNewPosition, sizeof(ULARGE_INTEGER)));
+ ULISet32(*plibNewPosition, 0);
+ }
+ if (dwOrigin != STREAM_SEEK_SET && dwOrigin != STREAM_SEEK_CUR &&
+ dwOrigin != STREAM_SEEK_END)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+
+ // Truncate dlibMove to 32 bits
+ if (dwOrigin == STREAM_SEEK_SET)
+ {
+ // Make sure we don't seek too far
+ if (LIGetHigh(dlibMove) != 0)
+ LISet32(dlibMove, (LONG)0xffffffff);
+ }
+ else
+ {
+ // High dword must be zero for positive values or -1 for
+ // negative values
+ // Additionally, for negative values, the low dword can't
+ // exceed -0x80000000 because the 32nd bit is the sign
+ // bit
+ if (LIGetHigh(dlibMove) > 0 ||
+ (LIGetHigh(dlibMove) == 0 &&
+ LIGetLow(dlibMove) >= 0x80000000))
+ LISet32(dlibMove, 0x7fffffff);
+ else if (LIGetHigh(dlibMove) < -1 ||
+ (LIGetHigh(dlibMove) == -1 &&
+ LIGetLow(dlibMove) <= 0x7fffffff))
+ LISet32(dlibMove, (LONG)0x80000000);
+ }
+
+ lMove = (LONG)LIGetLow(dlibMove);
+ olChk(Validate());
+ ULISet32(ulPos, _psp->GetPos());
+ switch(dwOrigin)
+ {
+ case STREAM_SEEK_SET:
+ ULISetLow(ulPos, (ULONG)lMove);
+ break;
+ case STREAM_SEEK_END:
+ ULONG cbSize;
+ olChk(_pst->GetSize(&cbSize));
+ if (lMove < 0)
+ {
+ if ((ULONG)(-lMove) > cbSize)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ }
+ else if ((ULONG)lMove > CBMAXSEEK-cbSize)
+ lMove = (LONG)(CBMAXSEEK-cbSize);
+ ULISetLow(ulPos, cbSize+lMove);
+ break;
+ case STREAM_SEEK_CUR:
+ if (lMove < 0)
+ {
+ if ((ULONG)(-lMove) > _psp->GetPos())
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ }
+ else if ((ULONG)lMove > CBMAXSEEK-_psp->GetPos())
+ lMove = (LONG)(CBMAXSEEK-_psp->GetPos());
+ ULISetLow(ulPos, _psp->GetPos()+lMove);
+ break;
+ }
+ _psp->SetPos(ULIGetLow(ulPos));
+ if (plibNewPosition)
+ *plibNewPosition = ulPos;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::Seek => %lu\n",
+ ULIGetLow(ulPos)));
+EH_Err:
+ olLog(("%p::Out CExposedStream::Seek(). ulPos == %lu, ret == %lx\n",
+ this, ULIGetLow(ulPos), sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::SetSize, public
+//
+// Synopsis: Sets the size of a stream
+//
+// Arguments: [ulNewSize] - New size
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedStream::SetSize(ULARGE_INTEGER ulNewSize)
+{
+ SCODE sc;
+
+ olLog(("%p::In CExposedStream::SetSize(%lu)\n",
+ this, ULIGetLow(ulNewSize)));
+ olDebugOut((DEB_ITRACE, "In CExposedStream::SetSize(%lu)\n",
+ ULIGetLow(ulNewSize)));
+ TRY
+ {
+ if (ULIGetHigh(ulNewSize) != 0)
+ olErr(EH_Err, STG_E_INVALIDFUNCTION);
+ olChk(Validate());
+ olChk(_pst->SetSize(ULIGetLow(ulNewSize)));
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::SetSize\n"));
+EH_Err:
+ olLog(("%p::Out CExposedStream::SetSize(). ret == %lx\n", this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::CopyTo, public
+//
+// Synopsis: Copies information from one stream to another
+//
+// Arguments: [pstm] - Destination
+// [cb] - Number of bytes to copy
+// [pcbRead] - Return number of bytes read
+// [pcbWritten] - Return number of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+// [pcbWritten]
+//
+// Notes: We do our best to handle overlap correctly. This allows
+// CopyTo to be used to insert and remove space within a
+// stream.
+//
+// In the error case, we make no gurantees as to the
+// validity of pcbRead, pcbWritten, or either stream's
+// seek position.
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::CopyTo(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten)
+{
+ SCODE sc;
+ ULONG ulCopySize;
+ ULONG ulSrcSize;
+ ULONG ulSrcOrig;
+ ULARGE_INTEGER uliDestOrig;
+ LARGE_INTEGER liDestPos;
+ BYTE *pb = NULL;
+ BOOL fOverlap;
+ ULONG ulBytesCopied = 0;
+
+ olLog(("%p::In CExposedStream::CopyTo(%p, %lu, %p, %p)\n",
+ this, pstm, ULIGetLow(cb), pcbRead, pcbWritten));
+ olDebugOut((DEB_TRACE, "In CExposedStream::CopyTo("
+ "%p, %lu, %p, %p)\n", pstm, ULIGetLow(cb),
+ pcbRead, pcbWritten));
+
+ TRY
+ {
+ if (pcbRead)
+ {
+ olChk(ValidateOutBuffer(pcbRead, sizeof(ULARGE_INTEGER)));
+ ULISet32(*pcbRead, 0);
+ }
+ if (pcbWritten)
+ {
+ olChk(ValidateOutBuffer(pcbWritten, sizeof(ULARGE_INTEGER)));
+ ULISet32(*pcbWritten, 0);
+ }
+
+ olChk(ValidateInterface(pstm, IID_IStream));
+ olChk(Validate());
+
+ // Bound the size of the copy
+ // 1. The maximum we can copy is 0xffffffff
+
+ if (ULIGetHigh(cb) == 0)
+ ulCopySize = ULIGetLow(cb);
+ else
+ ulCopySize = 0xffffffff;
+
+ // 2. We can only copy what's available in the source stream
+
+ sc = _pst->GetSize(&ulSrcSize);
+ olChk(sc);
+
+ ulSrcOrig = _psp->GetPos();
+ if (ulSrcSize < ulSrcOrig)
+ {
+ // Nothing in source to copy
+ ulCopySize = 0;
+ }
+ else if ((ulSrcSize - ulSrcOrig) < ulCopySize)
+ {
+ // Shrink ulCopySize to fit bytes in source
+ ulCopySize = ulSrcSize - ulSrcOrig;
+ }
+
+ // 3. We can only copy what will fit in the destination
+
+ LISet32(liDestPos, 0);
+ olHChk(pstm->Seek(liDestPos, STREAM_SEEK_CUR, &uliDestOrig));
+ olAssert(ULIGetHigh(uliDestOrig) == 0);
+
+ if (ulCopySize > CBMAXSEEK - ULIGetLow(uliDestOrig))
+ ulCopySize = CBMAXSEEK - ULIGetLow(uliDestOrig);
+
+ // We are allowed to fail here with out-of-memory
+ olMem(pb = new BYTE[STREAMBUFFERSIZE]);
+
+ // Since we have no reliable way to determine if the source and
+ // destination represent the same stream, we assume they
+ // do and always handle overlap.
+
+ fOverlap = (ULIGetLow(uliDestOrig) > ulSrcOrig &&
+ ULIGetLow(uliDestOrig) < ulSrcOrig + ulCopySize);
+
+ ULONG ulSrcCopyOffset;
+ ULONG ulDstCopyOffset;
+ if (fOverlap)
+ {
+ // We're going to copy back to front, so determine the
+ // stream end positions
+ ulSrcCopyOffset = ulSrcOrig + ulCopySize;
+
+ // uliDestOrig is the destination starting offset
+ ulDstCopyOffset = ULIGetLow(uliDestOrig) + ulCopySize;
+ }
+
+ while (ulCopySize > 0)
+ {
+ // We can only copy up to STREAMBUFFERSIZE bytes at a time
+ ULONG cbPart = min(ulCopySize, STREAMBUFFERSIZE);
+
+ if (fOverlap)
+ {
+ // We're copying back to front so we need to seek to
+ // set up the streams correctly
+
+ ulSrcCopyOffset -= cbPart;
+ ulDstCopyOffset -= cbPart;
+
+ // Set source stream position
+ _psp->SetPos(ulSrcCopyOffset);
+
+ // Set destination stream position
+ LISet32(liDestPos, ulDstCopyOffset);
+ olHChk(pstm->Seek(liDestPos, STREAM_SEEK_SET, NULL));
+ }
+
+ {
+ ULONG ulRead;
+ olHChk(Read(pb, cbPart, &ulRead));
+ if (cbPart != ulRead)
+ {
+ // There was no error, but we were unable to read cbPart
+ // bytes. Something's wrong (the underlying ILockBytes?)
+ // but we can't control it; just return an error.
+ olErr(EH_Err, STG_E_READFAULT);
+ }
+ }
+
+
+ {
+ ULONG ulWritten;
+ olHChk(pstm->Write(pb, cbPart, &ulWritten));
+ if (cbPart != ulWritten)
+ {
+ // There was no error, but we were unable to write
+ // ulWritten bytes. We can't trust the pstm
+ // implementation, so all we can do here is return
+ // an error.
+ olErr(EH_Err, STG_E_WRITEFAULT);
+ }
+ }
+
+ olAssert(ulCopySize >= cbPart);
+ ulCopySize -= cbPart;
+ ulBytesCopied += cbPart;
+ }
+
+ if (fOverlap)
+ {
+ // Set the seek pointers to the correct location
+ _psp->SetPos(ulSrcOrig + ulBytesCopied);
+
+ LISet32(liDestPos, ULIGetLow(uliDestOrig) + ulBytesCopied);
+ olHChk(pstm->Seek(liDestPos, STREAM_SEEK_SET, NULL));
+ }
+
+ if (pcbRead)
+ ULISet32(*pcbRead, ulBytesCopied);
+ if (pcbWritten)
+ ULISet32(*pcbWritten, ulBytesCopied);
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::CopyTo => %lu, %lu\n",
+ pcbRead ? ULIGetLow(*pcbRead) : 0,
+ pcbWritten ? ULIGetLow(*pcbWritten) : 0));
+ // Fall through
+EH_Err:
+ delete [] pb;
+ olLog(("%p::Out CExposedStream::CopyTo(). "
+ "cbRead == %lu, cbWritten == %lu, ret == %lx\n",
+ this, pcbRead ? ULIGetLow(*pcbRead) : 0,
+ pcbWritten ? ULIGetLow(*pcbWritten) : 0, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Release, public
+//
+// Synopsis: Releases a stream
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP_(ULONG) CExposedStream::Release(void)
+{
+ LONG lRet;
+
+ olLog(("%p::In CExposedStream::Release()\n", this));
+ olDebugOut((DEB_ITRACE, "In CExposedStream::Release()\n"));
+ TRY
+ {
+ if (FAILED(Validate()))
+ return 0;
+ olAssert(_cReferences > 0);
+ lRet = AtomicDec(&_cReferences);
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ lRet = 0;
+ }
+ CATCH(CException, e)
+ {
+ UNREFERENCED_PARM(e);
+ lRet = 0;
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::Release\n"));
+ olLog(("%p::Out CExposedStream::Release(). ret == %lu\n", this, lRet));
+ FreeLogFile();
+ return lRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Stat, public
+//
+// Synopsis: Fills in a buffer of information about this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+//---------------------------------------------------------------
+
+
+TSTDMETHODIMP CExposedStream::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc, scSem = STG_E_INUSE;
+
+ olLog(("%p::In CExposedStream::Stat(%p)\n", this, pstatstg));
+ olDebugOut((DEB_ITRACE, "In CExposedStream::Stat(%p)\n",
+ pstatstg));
+ TRY
+ {
+ olChkTo(EH_RetSc, ValidateOutBuffer(pstatstg, sizeof(STATSTGW)));
+ olChk(VerifyStatFlag(grfStatFlag));
+ olChk(Validate());
+ olChk(_pst->Stat(pstatstg, grfStatFlag));
+ pstatstg->type = STGTY_STREAM;
+ pstatstg->grfLocksSupported = 0;
+ pstatstg->reserved = 0;
+ pstatstg->ctime.dwLowDateTime = pstatstg->ctime.dwHighDateTime = 0;
+ pstatstg->mtime.dwLowDateTime = pstatstg->mtime.dwHighDateTime = 0;
+ pstatstg->atime.dwLowDateTime = pstatstg->atime.dwHighDateTime = 0;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::Stat\n"));
+EH_Err:
+ if (FAILED(sc))
+ memset(pstatstg, 0, sizeof(STATSTGW));
+EH_RetSc:
+ olLog(("%p::Out CExposedStream::Stat(). ret == %lx\n",
+ this, sc));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Clone, public
+//
+// Synopsis: Clones a stream
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::Clone(IStream **ppstm)
+{
+ CExposedStream *pst;
+ CSeekPointer *psp;
+ SCODE sc;
+
+ olLog(("%p::In CExposedStream::Clone(%p)\n", this, ppstm));
+ olDebugOut((DEB_ITRACE, "In CExposedStream::Clone(%p)\n", ppstm));
+ TRY
+ {
+ olChk(ValidateOutPtrBuffer(ppstm));
+ *ppstm = NULL;
+ olChk(Validate());
+ olChk(_pst->CheckReverted());
+ olMem(psp = new CSeekPointer(_psp->GetPos()));
+ olMemTo(EH_psp, pst = new CExposedStream);
+ olChkTo(EH_pst, pst->Init(_pst, psp));
+ _pst->vAddRef();
+ *ppstm = pst;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::Clone => %p\n", *ppstm));
+ return ResultFromScode(sc);
+
+EH_pst:
+ delete pst;
+EH_psp:
+ psp->vRelease();
+EH_Err:
+ olLog(("%p::Out CExposedStream::Clone(). *ppstm == %p, ret == %lx\n",
+ this, *ppstm, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CExposedStream::AddRef(void)
+{
+ ULONG ulRet;
+
+ olLog(("%p::In CExposedStream::AddRef()\n", this));
+ olDebugOut((DEB_ITRACE, "In CExposedStream::AddRef()\n"));
+ TRY
+ {
+ if (FAILED(Validate()))
+ return 0;
+ AtomicInc(&_cReferences);
+ ulRet = _cReferences;
+ }
+ CATCH(CException, e)
+ {
+ UNREFERENCED_PARM(e);
+ ulRet = 0;
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::AddRef\n"));
+ olLog(("%p::Out CExposedStream::AddRef(). ret == %lu\n", this, ulRet));
+ return ulRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::LockRegion, public
+//
+// Synopsis: Nonfunctional
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedStream::LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ olDebugOut((DEB_ITRACE, "In CExposedStream::LockRegion("
+ "%lu, %lu\n", ULIGetLow(cb), dwLockType));
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::LockRegion\n"));
+ olLog(("%p::INVALID CALL TO CExposedStream::LockRegion()\n"));
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::UnlockRegion, public
+//
+// Synopsis: Nonfunctional
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CExposedStream::UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ olDebugOut((DEB_ITRACE, "In CExposedStream::UnlockRegion(%lu, %lu)\n",
+ ULIGetLow(cb), dwLockType));
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::UnlockRegion\n"));
+ olLog(("%p::INVALID CALL TO CExposedStream::UnlockRegion()\n"));
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Commit, public
+//
+// Synopsis: No-op in current implementation
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::Commit(DWORD grfCommitFlags)
+{
+ SCODE sc, scSem = STG_E_INUSE;
+ olDebugOut((DEB_ITRACE, "In CExposedStream::Commit(%lu)\n",
+ grfCommitFlags));
+ olLog(("%p::In CExposedStream::Commit(%lx)\n", this, grfCommitFlags));
+
+ TRY
+ {
+ olChk(Validate());
+ olChk(_pst->Commit(grfCommitFlags));
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::Commit\n"));
+EH_Err:
+ olLog(("%p::Out CExposedStream::Commit(). ret == %lx", this, sc));
+ return ResultFromScode(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Revert, public
+//
+// Synopsis: No-op in current implementation
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::Revert(void)
+{
+ olDebugOut((DEB_ITRACE, "In CExposedStream::Revert()\n"));
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::Revert\n"));
+ olLog(("%p::In CExposedStream::Revert()\n", this));
+ olLog(("%p::Out CExposedStream::Revert(). ret == %lx", this, S_OK));
+
+ return NOERROR;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+//---------------------------------------------------------------
+
+
+STDMETHODIMP CExposedStream::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ olLog(("%p::In CExposedStream::QueryInterface(?, %p)\n",
+ this, ppvObj));
+ olDebugOut((DEB_ITRACE, "In CExposedStream::QueryInterface(?, %p)\n",
+ ppvObj));
+ TRY
+ {
+ olChk(ValidateOutPtrBuffer(ppvObj));
+ *ppvObj = NULL;
+ olChk(ValidateIid(iid));
+ olChk(Validate());
+ olChk(_pst->CheckReverted());
+ if (IsEqualIID(iid, IID_IStream) || IsEqualIID(iid, IID_IUnknown))
+ {
+ olChk(AddRef());
+ *ppvObj = this;
+ }
+ else
+ olErr(EH_Err, E_NOINTERFACE);
+ sc = S_OK;
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out CExposedStream::QueryInterface => %p\n",
+ ppvObj));
+EH_Err:
+ olLog(("%p::Out CExposedStream::QueryInterface(). *ppvObj == %p, ret == %lx\n",
+ this, *ppvObj, sc));
+ return ResultFromScode(sc);
+}
+
+
diff --git a/private/ole32/stg/ref/expst.hxx b/private/ole32/stg/ref/expst.hxx
new file mode 100644
index 000000000..ee1c0ea37
--- /dev/null
+++ b/private/ole32/stg/ref/expst.hxx
@@ -0,0 +1,124 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: expst.hxx
+//
+// Contents: CExposedStream definition
+//
+// Classes: CExposedStream
+//
+// Functions:
+//
+//--------------------------------------------------------------------------
+
+#ifndef __EXPST_HXX__
+#define __EXPST_HXX__
+
+#include <dfmsp.hxx>
+#include "lock.hxx"
+
+class CPubStream;
+interface ILockBytes;
+class CSeekPointer;
+
+//+--------------------------------------------------------------
+//
+// Class: CExposedStream (est)
+//
+// Purpose: Public stream interface
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+
+interface CExposedStream: public IStream
+{
+public:
+ CExposedStream(void);
+ SCODE Init(CPubStream *pst,
+ CSeekPointer *psp);
+ inline
+ ~CExposedStream(void);
+
+ // From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+
+ // New methods
+ STDMETHOD(Read)(VOID HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbRead);
+ STDMETHOD(Write)(VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ STDMETHOD(Seek)(LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition);
+ STDMETHOD(SetSize)(ULARGE_INTEGER cb);
+ STDMETHOD(CopyTo)(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(LockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+ SCODE Stat(STATSTGW *pstatstg, DWORD grfStatFlag);
+ STDMETHOD(Clone)(IStream **ppstm);
+
+ inline SCODE Validate(void) const;
+ inline CPubStream *GetPub(void) const;
+
+
+private:
+
+ CPubStream *_pst;
+ ULONG _ulAccessLockBase;
+ ULONG _sig;
+ LONG _cReferences;
+ CSeekPointer *_psp;
+};
+
+#define CEXPOSEDSTREAM_SIG LONGSIG('E', 'X', 'S', 'T')
+#define CEXPOSEDSTREAM_SIGDEL LONGSIG('E', 'x', 'S', 't')
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::Validate, public
+//
+// Synopsis: Validates the object signature
+//
+// Returns: Returns STG_E_INVALIDHANDLE for bad signatures
+//
+//---------------------------------------------------------------
+
+inline SCODE CExposedStream::Validate(void) const
+{
+ return (this == NULL || _sig != CEXPOSEDSTREAM_SIG) ?
+ STG_E_INVALIDHANDLE : S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CExposedStream::GetPub, public
+//
+// Synopsis: Returns the public
+//
+//---------------------------------------------------------------
+
+inline CPubStream *CExposedStream::GetPub(void) const
+{
+ return _pst;
+}
+
+#endif // #ifndef __EXPST_HXX__
diff --git a/private/ole32/stg/ref/fat.cxx b/private/ole32/stg/ref/fat.cxx
new file mode 100644
index 000000000..cc0d0cf7e
--- /dev/null
+++ b/private/ole32/stg/ref/fat.cxx
@@ -0,0 +1,1414 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: fat.cxx
+//
+// Contents: Allocation functions for MStream
+//
+// Classes: None. (defined in fat.hxx)
+//
+//--------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+
+#include <difat.hxx>
+#include <sstream.hxx>
+#include <mread.hxx>
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFatSect::Init, public
+//
+// Synopsis: CFatSect initialization function
+//
+// Effects: [uEntries] -- Number of entries in sector
+//
+// Algorithm: Allocate an array of SECT with size uEntries from
+// the heap.
+//
+//--------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFatSect::Init(FSOFFSET uEntries)
+{
+ msfDebugOut((DEB_FAT,"In CFatSect constructor\n"));
+
+ //This assumes that FREESECT is always 0xFFFFFFFF
+ memset(_asectEntry, 0xFF, uEntries * sizeof(SECT));
+
+ msfDebugOut((DEB_FAT,"Out CFatSect constructor\n"));
+ return S_OK;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFatSect::InitCopy, public
+//
+// Synopsis: Initialization function for copying FatSects
+//
+// Arguments: [fsOld] -- Reference to FatSect to be copies
+//
+// Returns: S_OK if call completed successfully.
+//
+// Algorithm: Allocate a new array of SECT and copy old
+// information in.
+//
+//--------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFatSect::InitCopy(USHORT uSize, CFatSect& fsOld)
+{
+ msfDebugOut((DEB_FAT,"In CFatSect copy constructor\n"));
+ msfDebugOut((DEB_FAT,"This = %p, fsOld = %p\n",this,&fsOld));
+
+ msfDebugOut((DEB_FAT,"Sector size is %u sectors\n",uSize));
+
+ memcpy(_asectEntry,fsOld._asectEntry,sizeof(SECT)*uSize);
+ msfDebugOut((DEB_FAT,"Out CFatSect copy constructor\n"));
+ return S_OK;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFat::CFat, public
+//
+// Synopsis: CFat constructor.
+//
+// Arguments: [pmsParent] -- Pointer to parent multistream.
+//
+// Algorithm: Set uFatEntries to match parent MS header info.
+// Initialize all member variables.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+FAT_NEAR CFat::CFat(SID sid, USHORT cbSector, USHORT uSectorShift)
+: _fv(
+ sid,
+ cbSector >> 2,
+ cbSector >> 2),
+ _uFatShift(uSectorShift - 2),
+ _uFatMask((cbSector >> 2) - 1),
+ _sid(sid),
+ _pmsParent(NULL),
+ _sectFirstFree(0),
+ _sectMax(ENDOFCHAIN)
+{
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CFat::Empty, public
+//
+// Synopsis: Empty all the control structures of this instance
+//
+// Arguments: None.
+//
+// Returns: void.
+//
+//----------------------------------------------------------------------------
+
+void CFat::Empty(void)
+{
+ _fv.Empty();
+ _pmsParent = NULL;
+ _cfsTable = 0;
+ _ulFreeSects = MAX_ULONG;
+ _sectFirstFree = 0;
+ _sectMax = ENDOFCHAIN;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFat::~CFat, public
+//
+// Synopsis: CFat Destructor
+//
+// Algorithm: delete dynamically allocated storage
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+FAT_NEAR CFat::~CFat()
+{
+ msfDebugOut((DEB_FAT,"In CFat destructor. Size of fat is %lu\n",_cfsTable));
+
+ msfDebugOut((DEB_FAT,"Exiting CFat destructor\n"));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::GetFree, private
+//
+// Synposis: Locate and return a free sector in the FAT
+//
+// Effects: May modify full bit on full sectors
+//
+// Arguments: [psectRet] -- Pointer to return value
+//
+// Returns: S_OK if call completed successfully.
+//
+// Algorithm: Do a linear search of all tables until a free sector is
+// found. If all tables are full, extend the FAT by one
+// sector.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::GetFree(ULONG ulCount, SECT *psectRet)
+{
+ FSINDEX ipfs;
+ FSOFFSET isect;
+ SECT sectRetval;
+ SCODE sc;
+
+ SECT sectLast = ENDOFCHAIN;
+ FSINDEX ipfsLast;
+ FSOFFSET isectLast;
+
+ *psectRet = ENDOFCHAIN;
+
+
+ while (TRUE)
+ {
+ if (_ulFreeSects == MAX_ULONG)
+ {
+ msfChk(CountFree(&_ulFreeSects));
+ }
+#if DBG == 1
+ else
+ {
+ ULONG ulFree;
+ msfChk(CountFree(&ulFree));
+ msfAssert((ulFree == _ulFreeSects) &&
+ aMsg("Free count doesn't match cached value."));
+ }
+#endif
+
+ while (ulCount > _ulFreeSects)
+ {
+#if DBG == 1
+ ULONG ulFree = _ulFreeSects;
+#endif
+
+ msfChk(Resize(_cfsTable +
+ ((ulCount - _ulFreeSects + _fv.GetSectTable() - 1) >>
+ _uFatShift)));
+
+#if DBG == 1
+ msfAssert(_ulFreeSects > ulFree &&
+ aMsg("Number of free sectors didn't increase after Resize."));
+#endif
+ }
+
+ FSOFFSET isectStart;
+ FSINDEX ipfsStart;
+
+ SectToPair(_sectFirstFree, &ipfsStart, &isectStart);
+
+ for (ipfs = ipfsStart; ipfs < _cfsTable; ipfs++)
+ {
+ CVectBits *pfb = _fv.GetBits(ipfs);
+ if ((pfb == NULL) || (!pfb->full))
+ {
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+ if (pfb != NULL)
+ {
+ isectStart = pfb->firstfree;
+ }
+
+ for (isect = isectStart; isect < _fv.GetSectTable(); isect++)
+ {
+ SECT sectCurrent = pfs->GetSect(isect);
+ SECT sectNew = PairToSect(ipfs, isect);
+
+
+ if (sectCurrent == FREESECT)
+ {
+ msfAssert(_ulFreeSects != MAX_ULONG &&
+ aMsg("Free sect count not set"));
+
+ _ulFreeSects--;
+
+ sectRetval = sectNew;
+
+ if (pfb != NULL)
+ {
+ pfb->firstfree = isect + 1;
+ }
+
+ msfAssert(sectRetval >= _sectFirstFree &&
+ aMsg("Found free sector before _sectFirstFree"));
+ _sectFirstFree = sectRetval + 1;
+
+ pfs->SetSect(isect, ENDOFCHAIN);
+ msfChkTo(Err_Rel, _fv.SetDirty(ipfs));
+
+ if (sectLast != ENDOFCHAIN)
+ {
+ if (ipfsLast == ipfs)
+ {
+ pfs->SetSect(isectLast, sectRetval);
+ }
+ else
+ {
+ CFatSect *pfsLast;
+
+ msfChkTo(Err_Rel, _fv.GetTable(
+ ipfsLast,
+ FB_DIRTY,
+ &pfsLast));
+
+ pfsLast->SetSect(isectLast, sectRetval);
+ _fv.ReleaseTable(ipfsLast);
+ }
+ }
+
+ if (*psectRet == ENDOFCHAIN)
+ {
+ *psectRet = sectRetval;
+ }
+
+ ulCount--;
+
+ if (ulCount == 0)
+ {
+ _fv.ReleaseTable(ipfs);
+
+ if (sectRetval >= _sectMax)
+ {
+ _sectMax = sectRetval + 1;
+ }
+ return S_OK;
+ }
+ else
+ {
+ sectLast = sectRetval;
+ ipfsLast = ipfs;
+ isectLast = isect;
+ }
+ }
+ }
+ _fv.ReleaseTable(ipfs);
+ if (pfb != NULL)
+ {
+ pfb->full = TRUE;
+ }
+ }
+ isectStart = 0;
+ }
+ if (sectRetval >= _sectMax)
+ {
+ _sectMax = sectRetval + 1;
+ }
+ }
+ msfAssert(0 &&
+ aMsg("GetFree exited improperly."));
+ sc = STG_E_ABNORMALAPIEXIT;
+
+ Err:
+ return sc;
+
+ Err_Rel:
+ _fv.ReleaseTable(ipfs);
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::GetLength, public
+//
+// Synposis: Return the length of a fat chain.
+//
+// Arguments: [sect] -- Sector to begin count at.
+//
+// Returns: Length of the chain, in sectors
+//
+// Algorithm: Traverse the chain until ENDOFCHAIN is reached.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::GetLength(SECT sect, ULONG * pulRet)
+{
+ msfDebugOut((DEB_FAT,"In CFat::GetLength(%lu)\n",sect));
+ SCODE sc = S_OK;
+
+ ULONG csect = 0;
+
+ while (sect != ENDOFCHAIN)
+ {
+ msfChk(GetNext(sect, &sect));
+ csect++;
+ }
+
+ msfDebugOut((DEB_FAT,"FAT: GetLength returned %u\n",csect));
+ *pulRet = csect;
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::Init, public
+//
+// Synposis: Sets up a FAT, reading data from an existing stream
+//
+// Effects: Changes all _apfsTable entries, _cfsTable, and all
+// flags fields
+//
+// Arguments: None.
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Read size from first FAT in stream.
+// Resize array to necessary size.
+// Read in FAT sectors sequentially.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::Init(CMStream *pmsParent, FSINDEX cFatSect, BOOL fConvert)
+{
+ SCODE sc;
+
+ msfDebugOut((DEB_FAT,"CFat::setup thinks the FAT is size %lu\n",cFatSect));
+
+ _pmsParent = pmsParent;
+
+ msfChk(_fv.Init(_pmsParent, cFatSect));
+
+ _cfsTable = cFatSect;
+
+ USHORT cbSectorSize;
+ cbSectorSize = _pmsParent->GetSectorSize();
+
+ _ulFreeSects = MAX_ULONG;
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFat::InitConvert, public
+//
+// Synopsis: Init function used for conversion
+//
+// Arguments: [sectData] -- number of sectors used by file
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: *Finish This*
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::InitConvert(CMStream *pmsParent, SECT sectData)
+{
+ SCODE sc;
+ msfDebugOut((DEB_FAT,"Doing conversion\n"));
+ _pmsParent = pmsParent;
+
+ msfAssert((sectData != 0) &&
+ aMsg("Attempt to convert zero length file."));
+
+ SECT sectMax = 0;
+ FSINDEX csectFat = 0;
+ FSINDEX csectLast;
+
+ if (_sid == SIDFAT)
+ {
+ SECT sectTotal;
+
+ //Since the fat needs to represent itself, we can't determine
+ // the actual number of sectors needed in one pass. We
+ // therefore loop, factoring in the number of fat sectors
+ // at each iteration, until we reach a stable state.
+ //
+ //As an example, consider the case where each fat sector represents
+ // 128 sectors and the file being converted is 128 sectors long.
+ // There will be no DIFat - therefore, we have 128 sectors needed
+ // on the first pass, which will require 1 fat sector to
+ // represent them. On the second pass, we discover that we
+ // actually need 2 fat sectors, since we now have 129 total
+ // sectors to allocate space for. The third pass will result
+ // in a stable state.
+ do
+ {
+ csectLast = csectFat;
+ sectTotal = sectData + _pmsParent->GetHeader()->GetDifLength() +
+ csectFat + 1;
+ csectFat = (sectTotal + _fv.GetSectTable() - 1) >> _uFatShift;
+ }
+ while (csectLast != csectFat);
+ sectMax = sectData + _pmsParent->GetHeader()->GetDifLength();
+ }
+ else
+ {
+ //The minifat doesn't need to represent itself, so we can
+ // compute the number of sectors needed in one pass.
+ sectMax = sectData;
+ csectFat = (sectMax + _fv.GetSectTable() -1) >> _uFatShift;
+ }
+
+ msfChk(_fv.Init(_pmsParent, csectFat));
+
+ FSINDEX i;
+
+ if (_sid == SIDMINIFAT)
+ {
+ SECT sectFirst;
+ msfChk(_pmsParent->GetFat()->Allocate(csectFat, &sectFirst));
+
+ _pmsParent->GetHeader()->SetMiniFatStart(sectFirst);
+
+ _pmsParent->GetHeader()->SetMiniFatLength(csectFat);
+ }
+
+
+ for (i = 0; i < csectFat; i++)
+ {
+ CFatSect *pfs;
+
+ msfChk(_fv.GetTable(i, FB_NEW, &pfs));
+ if (_sid == SIDFAT)
+ {
+ _fv.SetSect(i, sectMax + i);
+ _pmsParent->GetDIFat()->SetFatSect(i, sectMax + i);
+ }
+ else
+ {
+ SECT sect;
+ msfChk(_pmsParent->GetESect(_sid, i, &sect));
+ _fv.SetSect(i, sect);
+ }
+
+ _fv.ReleaseTable(i);
+ }
+
+
+ _cfsTable = csectFat;
+
+ if (_sid != SIDMINIFAT)
+ {
+
+ _pmsParent->GetHeader()->SetFatLength(_cfsTable);
+
+ SECT sect;
+
+ if (sectData > 1)
+ {
+ for (sect = 0; sect < sectData - 2; sect++)
+ {
+ msfChk(SetNext(sect, sect + 1));
+ }
+
+ msfChk(SetNext(sectData - 2, ENDOFCHAIN));
+ msfChk(SetNext(sectData - 1, 0));
+ }
+ else
+ {
+ //In the event that the file to be converted is less
+ // than one sector long, we don't need to create a
+ // real chain, just a single terminated sector.
+ msfChk(SetNext(0, ENDOFCHAIN));
+ }
+
+
+ for (sect = sectData; sect < sectMax; sect++)
+ {
+ msfChk(SetNext(sect, DIFSECT));
+ }
+
+ for (USHORT i = 0; i < csectFat; i++)
+ {
+ msfChk(SetNext(sectMax + i, FATSECT));
+ }
+
+ //Set up directory chain.
+ msfChk(SetNext(sectMax + i, ENDOFCHAIN));
+
+ _pmsParent->GetHeader()->SetDirStart(sectMax + i);
+
+ _ulFreeSects = (_cfsTable << _uFatShift) - (sectMax + csectFat + 1);
+ }
+ else
+ {
+ for (SECT sect = 0; sect < sectData -1; sect++)
+ {
+ msfChk(SetNext(sect, sect + 1));
+ }
+ msfChk(SetNext(sectData - 1, ENDOFCHAIN));
+ _ulFreeSects = (_cfsTable << _uFatShift) - sectData;
+ }
+
+ msfChk(_pmsParent->SetSize());
+
+Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::InitNew, public
+//
+// Synposis: Sets up a FAT for a newly created multi-strean
+//
+// Effects: Changes all _apfsTable entries, _cfsTable, and all
+// flags fields
+//
+// Arguments: [pmsparent] -- pointer to parent Mstream
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Set parent pointer.
+// Allocate 1 sector for FAT and 1 for Directory.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::InitNew(CMStream *pmsParent)
+{
+ msfDebugOut((DEB_FAT,"In CFat::InitNew()\n"));
+ SCODE sc;
+
+ _pmsParent = pmsParent;
+
+ FSINDEX count;
+ if (SIDMINIFAT == _sid)
+ count = _pmsParent->GetHeader()->GetMiniFatLength();
+ else
+ count = _pmsParent->GetHeader()->GetFatLength();
+
+ msfDebugOut((DEB_FAT,"Setting up Fat of size %lu\n",count));
+
+ msfChk(_fv.Init(_pmsParent, count));
+
+ _cfsTable = count;
+
+ if (SIDFAT == _sid)
+ {
+ FSINDEX ipfs;
+ FSOFFSET isect;
+ CFatSect *pfs;
+
+ SectToPair(_pmsParent->GetHeader()->GetFatStart(), &ipfs, &isect);
+ msfChk(_fv.GetTable(ipfs, FB_NEW, &pfs));
+ _fv.SetSect(ipfs, _pmsParent->GetHeader()->GetFatStart());
+ _fv.ReleaseTable(ipfs);
+
+ msfChk(SetNext(_pmsParent->GetHeader()->GetFatStart(), FATSECT));
+ msfDebugOut((DEB_ITRACE,"Set sector %lu (FAT) to ENDOFCHAIN\n",_pmsParent->GetHeader()->GetFatStart()));
+
+ msfChk(SetNext(_pmsParent->GetHeader()->GetDirStart(), ENDOFCHAIN));
+ msfDebugOut((DEB_ITRACE,"Set sector %lu (DIR) to ENDOFCHAIN\n",_pmsParent->GetHeader()->GetDirStart()));
+ _ulFreeSects = (count << _uFatShift) - 2;
+ }
+ else
+ {
+ _ulFreeSects = 0;
+ }
+
+ msfChk(_pmsParent->SetSize());
+
+ msfDebugOut((DEB_FAT,"Exiting CFat::setupnew()\n"));
+
+Err:
+ return sc;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::Resize, private
+//
+// Synposis: Resize FAT, both in memory and in the file
+//
+// Effects: Modifies _cfsTable, _apfsTable, and all flags fields
+//
+// Arguments: [ulSize] -- New size (in # of tables) for FAT
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Allocate new array of new size.
+// Copy over all old pointers.
+// Allocate new tables for any necessary.
+//
+// Notes: BUGBUG: This routine currently cannot reduce the size of a
+// fat. This functionality needs to be added eventually.
+//
+//---------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::Resize(ULONG ulSize)
+{
+ msfDebugOut((DEB_FAT,"In CFat::Resize(%lu)\n",ulSize));
+ SCODE sc;
+
+ if (ulSize == _cfsTable)
+ {
+ return S_OK;
+ }
+
+ ULONG csect = _cfsTable;
+
+ msfAssert(ulSize > _cfsTable &&
+ aMsg("Attempted to shrink Fat"));
+
+
+ ULONG ipfs;
+ SECT sectNew;
+
+ CFat *pfat = _pmsParent->GetFat();
+
+
+ if (_sid == SIDFAT)
+ {
+
+ //Make sure we have enough space for all of the sectors
+ // to be allocated.
+
+ ULONG csectFat = ulSize - _cfsTable;
+ ULONG csectPerDif = (1 << _uFatShift) - 1;
+ ULONG csectDif = (csectFat + csectPerDif - 1) / csectPerDif;
+
+
+ //Assuming all the free sectors are at the end of the file,
+ // we need a file csectNew sectors long to hold them.
+
+ ULONG csectOld, csectNew;
+
+ msfChk(FindMaxSect(&csectOld));
+
+ csectNew = csectOld + csectFat + csectDif;
+
+ ULARGE_INTEGER cbSize;
+
+ ULISet32(cbSize, ConvertSectOffset(
+ csectNew,
+ 0,
+ _pmsParent->GetSectorShift()));
+
+ msfHChk(_pmsParent->GetILB()->SetSize(cbSize));
+
+ //If we are the fat, we have enough space in the file for
+ // ourselves at this point.
+ }
+ else
+ {
+ if (_cfsTable == 0)
+ {
+ msfChk(pfat->Allocate(ulSize, &sectNew));
+ _pmsParent->GetHeader()->SetMiniFatStart(sectNew);
+ }
+ else
+ {
+ sectNew = _pmsParent->GetHeader()->GetMiniFatStart();
+
+ SECT sectLast;
+ msfChk(pfat->GetESect(sectNew, ulSize - 1, &sectLast));
+
+ }
+
+ msfChk(_pmsParent->SetSize());
+
+
+ msfChk(pfat->GetSect(sectNew, csect, &sectNew));
+
+ //If we are the Minifat, we have enough space in the underlying
+ // file for ourselves at this point.
+ }
+
+
+ _fv.Resize(ulSize);
+
+
+ for (ipfs = csect; ipfs < ulSize; ipfs++)
+ {
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NEW, &pfs));
+ _cfsTable = ipfs + 1;
+ _ulFreeSects += (1 << _uFatShift);
+
+ if (_sid == SIDFAT)
+ {
+ msfChk(pfat->GetFree(1, &sectNew));
+
+ msfChk(_pmsParent->GetDIFat()->SetFatSect(ipfs, sectNew));
+ msfChk(pfat->SetNext(sectNew, FATSECT));
+ }
+
+ msfAssert(sectNew != ENDOFCHAIN &&
+ aMsg("Bad sector returned for fatsect."));
+
+ _fv.SetSect(ipfs, sectNew);
+ _fv.ReleaseTable(ipfs);
+
+ if (_sid == SIDMINIFAT)
+ {
+ msfChk(pfat->GetNext(sectNew, &sectNew));
+ }
+ }
+
+ msfDebugOut((DEB_FAT,"CFat::Resize() - all new objects allocated\n"));
+
+ if (SIDMINIFAT == _sid)
+ _pmsParent->GetHeader()->SetMiniFatLength(_cfsTable);
+ else
+ _pmsParent->GetHeader()->SetFatLength(_cfsTable);
+
+
+ //This setsize should only shrink the file.
+#if DBG == 1
+ STATSTG stat;
+
+ msfHChk(_pmsParent->GetILB()->Stat(&stat, STATFLAG_NONAME));
+#endif
+
+ msfChk(_pmsParent->SetSize());
+
+#if DBG == 1
+ STATSTG statNew;
+
+ msfHChk(_pmsParent->GetILB()->Stat(&statNew, STATFLAG_NONAME));
+
+ msfAssert(ULIGetLow(statNew.cbSize) <= ULIGetLow(stat.cbSize));
+#endif
+
+ msfDebugOut((DEB_FAT,"Out CFat::Resize(%lu)\n",ulSize));
+
+Err:
+ return sc;
+}
+
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::Extend, private
+//
+// Synposis: Increase the size of an existing chain
+//
+// Effects: Modifies ulSize sectors within the fat. Causes one or
+// more sector writes.
+//
+// Arguments: [sect] -- Sector ID of last sector in chain to be extended
+// [ulSize] -- Number of sectors to add to chain
+//
+// Requires: sect must be at the end of a chain.
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Use calls to GetFree to allocate chain.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::Extend(SECT sect, ULONG ulSize)
+{
+ SCODE sc;
+
+ msfDebugOut((DEB_FAT,"In CFat::Extend(%lu,%lu)\n",sect,ulSize));
+ SECT sectTemp;
+
+ msfChk(GetFree(ulSize, &sectTemp));
+ msfChk(SetNext(sect, sectTemp));
+
+ msfDebugOut((DEB_FAT,"Out CFat::Extend()\n"));
+
+Err:
+ return sc;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::GetNext, public
+//
+// Synposis: Returns the next sector in a chain, given a sector
+//
+// Arguments: [sect] -- Sector ID of any sector in a chain.
+//
+// Returns: Sector ID of next sector in chain, ENDOFCHAIN if at end
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::GetNext(const SECT sect, SECT * psRet)
+{
+ SCODE sc;
+
+ FSINDEX ipfs;
+ FSOFFSET isect;
+
+ msfAssert(sect <= MAXREGSECT &&
+ aMsg("Called GetNext() on invalid sector"));
+
+ SectToPair(sect, &ipfs, &isect);
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+
+ *psRet = pfs->GetSect(isect);
+
+ _fv.ReleaseTable(ipfs);
+
+ msfAssert(sect != *psRet &&
+ aMsg("Detected loop in fat chain."));
+ return S_OK;
+
+Err:
+ return sc;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::SetNext, private
+//
+// Synposis: Set the next sector in a chain
+//
+// Effects: Modifies a single entry within the fat.
+//
+// Arguments: [sectFirst] -- Sector ID of first sector
+// [sectNext] -- Sector ID of next sector
+//
+// Returns: void
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+SCODE FAT_NEAR CFat::SetNext(SECT sectFirst, SECT sectNext)
+{
+ FSINDEX ipfs;
+ FSOFFSET isect;
+ SCODE sc;
+
+
+ // creating infinite loops is a no-no
+ msfAssert(sectFirst != sectNext &&
+ aMsg("Attempted to create loop in Fat chain"));
+ msfAssert(sectFirst <= MAXREGSECT &&
+ aMsg("Called SetNext on invalid sector"));
+
+ SectToPair(sectFirst, &ipfs, &isect);
+
+ CFatSect *pfs;
+
+ msfChk(_fv.GetTable(ipfs, FB_DIRTY, &pfs));
+
+ pfs->SetSect(isect,sectNext);
+
+ _fv.ReleaseTable(ipfs);
+
+ if (sectNext == FREESECT)
+ {
+ CVectBits *pfb;
+ pfb = _fv.GetBits(ipfs);
+
+ if ((pfb != NULL) &&
+ ((pfb->full == TRUE) || (isect < pfb->firstfree)))
+ {
+ pfb->full = FALSE;
+ pfb->firstfree = isect;
+ }
+
+ if (sectFirst == _sectMax - 1)
+ {
+ _sectMax = ENDOFCHAIN;
+ }
+ if (sectFirst < _sectFirstFree)
+ {
+ _sectFirstFree = sectFirst;
+ }
+
+ if (_ulFreeSects != MAX_ULONG)
+ {
+ _ulFreeSects++;
+ }
+ }
+
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::CountFree, private
+//
+// Synposis: Count and return the number of free sectors in the Fat
+//
+// Arguments: void.
+//
+// Returns: void.
+//
+// Algorithm: Do a linear search of the Fat, counting free sectors.
+// If a FatSect has its full bit set, it is not necessary
+// to search that FatSect.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::CountFree(ULONG * pulRet)
+{
+ msfDebugOut((DEB_FAT,"In CFat::CountFree()\n"));
+ SCODE sc = S_OK;
+
+ FSINDEX ipfs;
+ ULONG csectFree=0;
+ FSOFFSET isectStart;
+ FSINDEX ipfsStart;
+
+ SectToPair(_sectFirstFree, &ipfsStart, &isectStart);
+
+ for (ipfs = ipfsStart; ipfs < _cfsTable; ipfs++)
+ {
+ CVectBits *pfb = _fv.GetBits(ipfs);
+
+ if ((pfb == NULL) || (!pfb->full))
+ {
+ msfDebugOut((DEB_FAT,"Checking table %lu\n",ipfs));
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+
+ if (pfb != NULL)
+ {
+ isectStart = pfb->firstfree;
+ }
+
+ FSOFFSET isect;
+ for (isect = isectStart; isect < _fv.GetSectTable(); isect++)
+ {
+ SECT sectCurrent = pfs->GetSect(isect);
+ SECT sectNew = PairToSect(ipfs, isect);
+
+
+
+ if (sectCurrent == FREESECT)
+ {
+ csectFree++;
+ }
+ }
+ _fv.ReleaseTable(ipfs);
+ }
+ isectStart = 0;
+ }
+ msfDebugOut((DEB_FAT,"Countfree returned %lu\n",csectFree));
+ *pulRet = csectFree;
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::GetSect, public
+//
+// Synposis: Return the nth sector in a chain
+//
+// Arguments: [sect] -- Sector ID of beginning of chain
+// [uNum] -- indicator of which sector is to be returned
+// [psectReturn] -- Pointer to storage for return value
+//
+// Returns: S_OK.
+//
+// Algorithm: Linearly traverse chain until numth sector
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::GetSect(SECT sect, ULONG ulNum, SECT * psectReturn)
+{
+ msfDebugOut((DEB_FAT,"In CFat::GetSect(%lu,%lu)\n",sect,ulNum));
+
+ SCODE sc = S_OK;
+
+ if (ulNum == 0)
+ {
+ msfDebugOut((DEB_FAT,"Out CFat::GetSect()=>%lu\n",sect));
+ }
+ else if ((SIDFAT == _sid) &&
+ (_pmsParent->GetHeader()->GetFatStart() == sect))
+ {
+ msfChk(_pmsParent->GetDIFat()->GetFatSect(ulNum, &sect));
+ }
+ else for (USHORT i = 0; i < ulNum; i++)
+ {
+ msfChk(GetNext(sect, &sect));
+ if (sect > MAXREGSECT)
+ {
+ //The stream isn't long enough, so stop.
+ msfAssert(sect == ENDOFCHAIN &&
+ aMsg("Found invalid sector in fat chain."));
+ break;
+ }
+ }
+
+ *psectReturn = sect;
+ msfDebugOut((DEB_FAT,"Out CFat::GetSect()=>%lu\n",sect));
+
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::GetESect
+//
+// Synposis: Return the nth sector in a chain, extending the chain
+// if necessary.
+//
+// Effects: Modifies fat (via Extend) if necessary
+//
+// Arguments: [sect] -- Sector ID of beginning of chain
+// [ulNum] -- Indicates which sector is to be returned
+// [psectReturn] -- Pointer to storage for return value
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Linearly search chain until numth sector is found. If
+// the chain terminates early, extend it as necessary.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::GetESect(SECT sect, ULONG ulNum, SECT *psectReturn)
+{
+ msfDebugOut((DEB_FAT,"In CFat::GetESect(%lu,%lu)\n",sect,ulNum));
+
+ SCODE sc = S_OK;
+
+ ULONG i = 0;
+ while (i < ulNum)
+ {
+ SECT temp;
+ msfChk(GetNext(sect, &temp));
+
+ msfAssert(temp != FREESECT &&
+ aMsg("FREESECT found in chain."));
+
+ if (temp == ENDOFCHAIN)
+ {
+
+ //The stream isn't long enough, so extend it somehow.
+ ULONG need = ulNum - i;
+
+ msfAssert((SIDMINIFAT == _sid ||
+ sect != _pmsParent->GetHeader()->GetFatStart()) &&
+ aMsg("Called GetESect on Fat chain"));
+ msfChk(Extend(sect,need));
+ }
+ else
+ {
+ sect = temp;
+ i++;
+ }
+ }
+
+ msfDebugOut((DEB_FAT,"Exiting GetESect with result %lu\n",sect));
+ *psectReturn = sect;
+
+Err:
+ return sc;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::SetChainLength, private
+//
+// Synposis: Set the length of a fat chain. This is used to reduce
+// the length of the chain only. To extend a chain, use
+// Extend or GetESect
+//
+// Effects: Modifies the fat
+//
+// Arguments: [sectStart] -- Sector to begin at (head of chain)
+// [uLength] -- New length for chain
+//
+// Returns: void.
+//
+// Algorithm: Traverse chain until uLength is reached or the chain
+// terminates. If it terminates prematurely, return with
+// no other action. Otherwise, deallocate all remaining
+// sectors in the chain.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::SetChainLength(SECT sectStart, ULONG ulLength)
+{
+ msfDebugOut((DEB_FAT,"In CFat::SetChainLength(%lu,%lu)\n",sectStart,ulLength));
+ SCODE sc;
+
+ if (sectStart == ENDOFCHAIN) return S_OK;
+
+ for (USHORT ui = 0; ui < ulLength; ui++)
+ {
+ msfChk(GetNext(sectStart, &sectStart));
+ if (sectStart == ENDOFCHAIN) return S_OK;
+ }
+
+ msfAssert(sectStart != ENDOFCHAIN &&
+ aMsg("Called SetChainLength is ENDOFCHAIN start"));
+
+ SECT sectEnd;
+ sectEnd = sectStart;
+
+ msfChk(GetNext(sectStart, &sectStart));
+ if (ulLength != 0)
+ {
+ msfChk(SetNext(sectEnd, ENDOFCHAIN));
+ }
+ else
+ {
+ msfChk(SetNext(sectEnd, FREESECT));
+ }
+
+ while (sectStart != ENDOFCHAIN)
+ {
+ SECT sectTemp;
+ msfChk(GetNext(sectStart, &sectTemp));
+ msfChk(SetNext(sectStart, FREESECT));
+ sectStart = sectTemp;
+ }
+ msfDebugOut((DEB_FAT,"Out CFat::SetChainLength()\n"));
+
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFat::FindLast, private
+//
+// Synopsis: Find last used sector in a fat
+//
+// Returns: Location of last used sector
+//
+// Algorithm: Perform a backward linear search until a non-free
+// sector is found.
+//
+// Notes: Used for shadow fats only.
+//
+//--------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::FindLast(SECT * psectRet)
+{
+ SCODE sc = S_OK;
+ FSINDEX ipfs = _cfsTable;
+ SECT sect = 0;
+
+ while (ipfs > 0)
+ {
+ ipfs--;
+
+ FSOFFSET isect = _fv.GetSectTable();
+
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+
+ while (isect > 0)
+ {
+ isect--;
+
+ SECT sectCurrent = pfs->GetSect(isect);
+
+
+ if (sectCurrent != FREESECT)
+ {
+ msfDebugOut((DEB_FAT,"FindLast returns %lu\n",PairToSect(ipfs,isect)));
+ sect = PairToSect(ipfs, isect + 1);
+ break;
+ }
+ }
+
+ _fv.ReleaseTable(ipfs);
+ if (sect != 0)
+ break;
+ }
+
+ *psectRet = sect;
+Err:
+ return sc;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFat::FindMaxSect, private
+//
+// Synopsis: Return last used sector in current Fat.
+//
+// Arguments: None.
+//
+// Returns: Last used sector in current Fat
+//
+//--------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::FindMaxSect(SECT *psectRet)
+{
+ SCODE sc = S_OK;
+
+ if (_sectMax == ENDOFCHAIN)
+ {
+ msfChk(FindLast(psectRet));
+ }
+ else
+ {
+#if DBG == 1
+ SECT sectLast;
+ msfChk(FindLast(&sectLast));
+#endif
+ *psectRet = _sectMax;
+ }
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::Contig, public
+//
+// Synposis: Create contiguous sector table
+//
+// Effects: Creates new CSegment.
+//
+// Arguments: [sect] -- Starting sector for table to begin
+// [ulength] -- Runlength in sectors of table to produce
+//
+// Returns: Pointer to a Segment table
+//
+// Algorithm: Perform calls to CFat::GetNext(). Any call that is
+// 1 higher than the previous represents contiguous blocks.
+// Construct the Segment table on that basis.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+SCODE FAT_NEAR CFat::Contig(
+ SSegment STACKBASED *aseg,
+ SECT sect,
+ ULONG ulLength)
+{
+ msfDebugOut((DEB_ITRACE,"In CFat::Contig(%lu,%lu)\n",sect,ulLength));
+ SCODE sc = S_OK;
+ SECT stemp = sect;
+ ULONG ulCount = 1;
+ USHORT iseg = 0;
+
+ msfAssert(sect != ENDOFCHAIN &&
+ aMsg("Called Contig with ENDOFCHAIN start"));
+
+ aseg[iseg].sectStart = sect;
+ aseg[iseg].cSect = 1;
+
+ while ((ulLength > 1) && (iseg < CSEG))
+ {
+ msfAssert(sect != ENDOFCHAIN &&
+ aMsg("Contig found premature ENDOFCHAIN"));
+
+ FSINDEX ipfs;
+ FSOFFSET isect;
+
+ SectToPair(sect, &ipfs, &isect);
+
+ CFatSect *pfs;
+ msfChk(_fv.GetTable(ipfs, FB_NONE, &pfs));
+ sect = pfs->GetSect(isect);
+ _fv.ReleaseTable(ipfs);
+
+ if (sect == ENDOFCHAIN)
+ {
+ //Allocate new sectors.
+
+ SECT sectNew;
+ msfChk(GetFree(ulLength - 1, &sectNew));
+ msfChk(SetNext(stemp, sectNew));
+ sect = sectNew;
+ }
+
+ if (sect != (stemp + 1))
+ {
+ aseg[iseg].cSect = ulCount;
+ ulCount = 1;
+ iseg++;
+ aseg[iseg].sectStart = sect;
+ stemp = sect;
+ }
+ else
+ {
+ ulCount++;
+ stemp = sect;
+ }
+ ulLength--;
+ }
+
+ if (iseg < CSEG)
+ {
+ aseg[iseg].cSect = ulCount;
+ aseg[iseg + 1].sectStart = ENDOFCHAIN;
+ }
+ else
+ {
+ aseg[iseg].sectStart = FREESECT;
+ }
+
+ msfDebugOut((DEB_ITRACE,"Exiting Contig()\n"));
+
+Err:
+ return sc;
+}
+
diff --git a/private/ole32/stg/ref/funcs.cxx b/private/ole32/stg/ref/funcs.cxx
new file mode 100644
index 000000000..63097f636
--- /dev/null
+++ b/private/ole32/stg/ref/funcs.cxx
@@ -0,0 +1,352 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: funcs.cxx
+//
+// Contents: Generic DocFile support functions
+//
+// Functions: ModeToTFlags
+// CheckName
+// wcsdup
+// VerifyPerms
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+
+//+--------------------------------------------------------------
+//
+// Function: ModeToDFlags, private
+//
+// Synopsis: Translates STGM flags to DF flags
+//
+// Arguments: [dwModeFlags]
+//
+// Returns: DF_*
+//
+//---------------------------------------------------------------
+
+DFLAGS ModeToDFlags(DWORD const dwModeFlags)
+{
+ DFLAGS df;
+
+ olDebugOut((DEB_ITRACE, "In ModeToDFlags(%lX)\n", dwModeFlags));
+ if ((dwModeFlags & STGM_TRANSACTED) == 0)
+ df = DF_DIRECT;
+ else
+ df = DF_TRANSACTED;
+ if ((dwModeFlags & STGM_TRANSACTED) &&
+ (dwModeFlags & STGM_PRIORITY) == 0 &&
+ (dwModeFlags & STGM_DENY) != STGM_SHARE_DENY_WRITE &&
+ (dwModeFlags & STGM_DENY) != STGM_SHARE_EXCLUSIVE)
+ df |= DF_INDEPENDENT;
+ switch(dwModeFlags & STGM_RDWR)
+ {
+ case STGM_READ:
+ df |= DF_READ;
+ break;
+ case STGM_WRITE:
+ df |= DF_WRITE;
+ break;
+ case STGM_READWRITE:
+ df |= DF_READWRITE;
+ break;
+ default:
+ olAssert(FALSE);
+ break;
+ }
+ switch(dwModeFlags & STGM_DENY)
+ {
+ case STGM_SHARE_DENY_READ:
+ df |= DF_DENYREAD;
+ break;
+ case STGM_SHARE_DENY_WRITE:
+ df |= DF_DENYWRITE;
+ break;
+ case STGM_SHARE_EXCLUSIVE:
+ df |= DF_DENYALL;
+ break;
+ // Default is deny none
+ }
+ if (dwModeFlags & STGM_PRIORITY)
+ df |= DF_PRIORITY;
+ olDebugOut((DEB_ITRACE, "Out ModeToDFlags => %lX\n", df));
+ return df;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: DFlagsToMode, private
+//
+// Synopsis: Converts the read/write/denials/transacted/priority
+// to STGM flags
+//
+// Arguments: [df] - DFlags
+//
+// Returns: STGM flags
+//
+//---------------------------------------------------------------
+
+DWORD DFlagsToMode(DFLAGS const df)
+{
+ DWORD dwMode;
+
+ olDebugOut((DEB_ITRACE, "In DFlagsToMode(%X)\n", df));
+ if (P_READ(df))
+ if (P_WRITE(df))
+ dwMode = STGM_READWRITE;
+ else
+ dwMode = STGM_READ;
+ else if (P_WRITE(df))
+ dwMode = STGM_WRITE;
+ // Must have either read or write, so no else
+
+ if (P_DENYREAD(df))
+ if (P_DENYWRITE(df))
+ dwMode |= STGM_SHARE_EXCLUSIVE;
+ else
+ dwMode |= STGM_SHARE_DENY_READ;
+ else if (P_DENYWRITE(df))
+ dwMode |= STGM_SHARE_DENY_WRITE;
+ else
+ dwMode |= STGM_SHARE_DENY_NONE;
+
+ if (P_TRANSACTED(df))
+ dwMode |= STGM_TRANSACTED;
+
+ if (P_PRIORITY(df))
+ dwMode |= STGM_PRIORITY;
+
+ olDebugOut((DEB_ITRACE, "Out DFlagsToMode\n"));
+ return dwMode;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: VerifyPerms, private
+//
+// Synopsis: Checks flags to see if they are valid
+//
+// Arguments: [grfMode] - Permissions
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+SCODE VerifyPerms(DWORD grfMode)
+{
+ SCODE sc = S_OK;
+
+ olDebugOut((DEB_ITRACE, "In VerifyPerms(%lX)\n", grfMode));
+
+ // Check for valid flags
+ if ((grfMode & STGM_RDWR) > STGM_READWRITE ||
+ (grfMode & STGM_DENY) > STGM_SHARE_DENY_NONE ||
+ (grfMode & ~(STGM_RDWR | STGM_DENY | STGM_DIRECT | STGM_TRANSACTED |
+ STGM_PRIORITY | STGM_CREATE | STGM_CONVERT |
+ STGM_FAILIFTHERE | STGM_DELETEONRELEASE)))
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+
+ // If priority is specified...
+ if (grfMode & STGM_PRIORITY)
+ {
+ return STG_E_INVALIDFUNCTION;
+ }
+
+ if (grfMode & STGM_TRANSACTED)
+ {
+ return STG_E_INVALIDFUNCTION;
+ }
+
+ // Check to make sure only one existence flag is specified
+ // FAILIFTHERE is zero so it can't be checked
+ if ((grfMode & (STGM_CREATE | STGM_CONVERT)) ==
+ (STGM_CREATE | STGM_CONVERT))
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+
+ // If not transacted and not priority, you can either be
+ // read-only deny write or read-write deny all
+ if ((grfMode & (STGM_TRANSACTED | STGM_PRIORITY)) == 0)
+ {
+ if ((grfMode & STGM_RDWR) == STGM_READ)
+ {
+ // we're asking for read-only access
+
+ if ((grfMode & STGM_DENY) != STGM_SHARE_EXCLUSIVE &&
+ (grfMode & STGM_DENY) != STGM_SHARE_DENY_WRITE)
+ {
+ // Can't allow others to have write access
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ }
+ }
+ else
+ {
+ // we're asking for write access
+
+ if ((grfMode & STGM_DENY) != STGM_SHARE_EXCLUSIVE)
+ {
+ // Can't allow others to have any access
+ olErr(EH_Err, STG_E_INVALIDFLAG);
+ }
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out VerifyPerms\n"));
+ // Fall through
+EH_Err:
+ return sc;
+}
+
+
+
+//+--------------------------------------------------------------
+//
+// Function: wcsdup, public
+//
+// Synopsis: Duplicates a WCHAR string
+//
+// Arguments: [pwcs] - String
+//
+// Returns: Pointer to new string or Appropriate status code
+//
+//---------------------------------------------------------------
+
+WCHAR * _CRTAPI1 wcsdup(WCHAR const *pwcs)
+{
+ WCHAR *pwcsNew;
+
+ olDebugOut((DEB_ITRACE, "In wcsdup(%ws)\n", pwcs));
+ pwcsNew = new WCHAR[wcslen(pwcs)+1];
+ if (pwcsNew == NULL)
+ return NULL;
+ wcscpy(pwcsNew, pwcs);
+ olDebugOut((DEB_ITRACE, "Out wcsdup => %p\n", pwcsNew));
+ return pwcsNew;
+}
+
+
+
+//+--------------------------------------------------------------
+//
+// Function: ValidateSNB, private
+//
+// Synopsis: Validates SNB memory
+//
+// Arguments: [snb] - SNB
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+SCODE ValidateSNB(SNBW snb)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In ValidateSNB(%p)\n", snb));
+ for (;;)
+ {
+ olChk(ValidatePtrBuffer(snb));
+ if (*snb == NULL)
+ break;
+ olChk(ValidateNameW(*snb, CWCMAXPATHCOMPLEN));
+ snb++;
+ }
+ olDebugOut((DEB_ITRACE, "Out ValidateSNB\n"));
+ return S_OK;
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: CopySStreamToSStream
+//
+// Synopsis: Copies the contents of a stream to another stream
+//
+// Arguments: [psstFrom] - Stream to copy from
+// [psstTo] - Stream to copy to
+//
+// Returns: Appropriate status code
+//
+// Notes: This function may fail due to out of memory. It
+// may not be used by callers who must not fail due
+// to out of memory.
+//
+//---------------------------------------------------------------
+
+SCODE CopySStreamToSStream(PSStream *psstFrom, PSStream *psstTo)
+{
+ BYTE *pbBuffer;
+ SCODE sc;
+ ULONG cbRead, cbWritten, cbSize, cbPos;
+
+ // Set destination size for contiguity
+ psstFrom->GetSize(&cbSize);
+ olChk(psstTo->SetSize(cbSize));
+
+ // We're allowed to fail due to out of memory
+ olMem(pbBuffer = new BYTE[STREAMBUFFERSIZE]);
+
+ // Copy between streams
+ cbPos = 0;
+ for (;;)
+ {
+ olChkTo(EH_pbBuffer,
+ psstFrom->ReadAt(cbPos, pbBuffer, STREAMBUFFERSIZE,
+ (ULONG STACKBASED *)&cbRead));
+ if (cbRead == 0) // EOF
+ break;
+ olChkTo(EH_pbBuffer,
+ psstTo->WriteAt(cbPos, pbBuffer, cbRead,
+ (ULONG STACKBASED *)&cbWritten));
+ if (cbRead != cbWritten)
+ olErr(EH_Err, STG_E_WRITEFAULT);
+ cbPos += cbWritten;
+ }
+ delete pbBuffer;
+ return S_OK;
+
+EH_pbBuffer:
+ delete pbBuffer;
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: NameInSNB, private
+//
+// Synopsis: Determines whether the given name is in the SNB
+//
+// Arguments: [dfn] - Name
+// [snb] - SNB
+//
+// Returns: S_OK or S_FALSE
+//
+//---------------------------------------------------------------
+
+SCODE NameInSNB(CDfName const *dfn, SNBW snb)
+{
+ SCODE sc = S_FALSE;
+
+ olDebugOut((DEB_ITRACE, "In NameInSNB(%ws, %p)\n", dfn, snb));
+ TRY
+ {
+ for (; *snb; snb++)
+ if (dfwcsnicmp((WCHAR *)dfn->GetBuffer(), (WCHAR *)*snb,
+ dfn->GetLength()) == 0)
+ {
+ sc = S_OK;
+ break;
+ }
+ }
+ CATCH(CException, e)
+ {
+ sc = e.GetErrorCode();
+ }
+ END_CATCH
+ olDebugOut((DEB_ITRACE, "Out NameInSNB\n"));
+ return sc;
+}
diff --git a/private/ole32/stg/ref/h/cdocfile.hxx b/private/ole32/stg/ref/h/cdocfile.hxx
new file mode 100644
index 000000000..8d0bcb85e
--- /dev/null
+++ b/private/ole32/stg/ref/h/cdocfile.hxx
@@ -0,0 +1,130 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992
+//
+// File: cdocfile.hxx
+//
+// Contents: CDocFile class header
+//
+// Classes: CDocFile
+//
+//---------------------------------------------------------------
+
+#ifndef __CDOCFILE_HXX__
+#define __CDOCFILE_HXX__
+
+#include <dfmsp.hxx>
+#include <handle.hxx>
+#include <pdocfile.hxx>
+
+interface ILockBytes;
+class PDocFileIterator;
+
+//+--------------------------------------------------------------
+//
+// Class: CDocFile (df)
+//
+// Purpose: DocFile object
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+class CDocFile : public PDocFile
+{
+public:
+ inline CDocFile(DFLUID luid, ILockBytes *pilbBase);
+ inline CDocFile(CMStream MSTREAM_NEAR *pms,
+ SID sid,
+ DFLUID dl,
+ ILockBytes *pilbBase);
+ SCODE InitFromEntry(CStgHandle *pstghParent,
+ CDfName const *dfnName,
+ BOOL const fCreate);
+
+ inline ~CDocFile(void);
+
+ // PDocFile
+ virtual void AddRef(void);
+ inline void DecRef(void);
+ virtual void Release(void);
+
+ virtual SCODE DestroyEntry(CDfName const *dfnName,
+ BOOL fClean);
+ virtual SCODE RenameEntry(CDfName const *dfnName,
+ CDfName const *dfnNewName);
+
+ virtual SCODE GetClass(CLSID *pclsid);
+ virtual SCODE SetClass(REFCLSID clsid);
+ virtual SCODE GetStateBits(DWORD *pgrfStateBits);
+ virtual SCODE SetStateBits(DWORD grfStateBits, DWORD grfMask);
+
+ virtual SCODE CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ PDocFile **ppdfDocFile);
+
+ inline SCODE CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ DWORD const dwType,
+ PDocFile **ppdfDocFile)
+ { return CreateDocFile(pdfnName, df, luidSet, ppdfDocFile); }
+
+ virtual SCODE GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ PDocFile **ppdfDocFile);
+ inline SCODE GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DWORD const dwType,
+ PDocFile **ppdfDocFile)
+ { return GetDocFile(pdfnName, df, ppdfDocFile); }
+ inline void ReturnDocFile(CDocFile *pdf);
+
+ virtual SCODE CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ PSStream **ppsstStream);
+ inline SCODE CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ DWORD const dwType,
+ PSStream **ppsstStream)
+ { return CreateStream(pdfnName, df, luidSet, ppsstStream); }
+ virtual SCODE GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ PSStream **ppsstStream);
+ inline SCODE GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DWORD const dwType,
+ PSStream **ppsstStream)
+ { return GetStream(pdfnName, df, ppsstStream); }
+ inline void ReturnStream(CDirectStream *pstm);
+
+ virtual SCODE GetIterator(PDocFileIterator **ppdfi);
+
+ virtual SCODE IsEntry(CDfName const *dfnName,
+ SEntryBuffer *peb);
+ virtual SCODE DeleteContents(void);
+
+ // PEntry
+ virtual SCODE GetTime(WHICHTIME wt, TIME_T *ptm);
+ virtual SCODE SetTime(WHICHTIME wt, TIME_T tm);
+
+ // New
+ SCODE ApplyChanges(CUpdateList &ulChanged);
+ SCODE CopyTo(CDocFile *pdfTo,
+ DWORD dwFlags,
+ SNBW snbExclude);
+ inline CStgHandle *GetHandle(void);
+
+private:
+ LONG _cReferences;
+ CStgHandle _stgh;
+ ILockBytes *_pilbBase;
+};
+
+// Inline methods are in dffuncs.hxx
+
+#endif
diff --git a/private/ole32/stg/ref/h/chinst.hxx b/private/ole32/stg/ref/h/chinst.hxx
new file mode 100644
index 000000000..46637a3ef
--- /dev/null
+++ b/private/ole32/stg/ref/h/chinst.hxx
@@ -0,0 +1,81 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992
+//
+// File: chinst.hxx
+//
+// Contents: DocFile child object maintenance code header file
+//
+// Classes: CChildInstance
+// CChildInstanceList
+//
+//---------------------------------------------------------------
+
+#ifndef __CHINST_HXX__
+#define __CHINST_HXX__
+
+class PRevertable;
+
+//+--------------------------------------------------------------
+//
+// Class: CChildInstanceList (cil)
+//
+// Purpose: Maintains a list of child instances
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+class CChildInstanceList
+{
+public:
+ inline CChildInstanceList(void);
+ inline ~CChildInstanceList(void);
+
+ void Add(PRevertable *prv);
+ PRevertable *FindByName(CDfName const *pdfn);
+ void DeleteByName(CDfName const *pdfn);
+ void RemoveRv(PRevertable *prv);
+ void Empty(void);
+
+ SCODE IsDenied(CDfName const *pdfn,
+ DFLAGS const dwDFlagsCheck,
+ DFLAGS const dwDFlagsAgainst);
+
+ void RenameChild(CDfName const *pdfn, CDfName const *pdfnNewName);
+
+private:
+ PRevertable *_prvHead;
+};
+
+
+//+--------------------------------------------------------------
+//
+// Member: CChildInstanceList::CChildInstanceList, pubic
+//
+// Synopsis: ctor
+//
+//---------------------------------------------------------------
+
+inline CChildInstanceList::CChildInstanceList(void)
+{
+ _prvHead = NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CChildInstanceList::~CChildInstanceList, public
+//
+// Synopsis: dtor
+//
+//---------------------------------------------------------------
+
+inline CChildInstanceList::~CChildInstanceList(void)
+{
+ msfAssert(_prvHead == NULL);
+}
+
+#endif
+
+
diff --git a/private/ole32/stg/ref/h/dfentry.hxx b/private/ole32/stg/ref/h/dfentry.hxx
new file mode 100644
index 000000000..ffe9cac2f
--- /dev/null
+++ b/private/ole32/stg/ref/h/dfentry.hxx
@@ -0,0 +1,34 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dfentry.hxx
+//
+// Contents: DocFile DLL entry points not in ole2.h
+//
+//---------------------------------------------------------------
+
+#ifndef __DFENTRY_HXX__
+#define __DFENTRY_HXX__
+
+STDAPI DfOpenStorage(const TCHAR *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstgOpen,
+ CLSID *pcid);
+STDAPI DfOpenStorageOnILockBytes(ILockBytes *plkbyt,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstgOpen,
+ CLSID *pcid);
+STDAPI DfUnMarshalInterface(IStream *pstStm,
+ REFIID iid,
+ BOOL fFirst,
+ void **ppvObj);
+
+#endif // #ifndef __DFENTRY_HXX__
diff --git a/private/ole32/stg/ref/h/dfexcept.hxx b/private/ole32/stg/ref/h/dfexcept.hxx
new file mode 100644
index 000000000..0677e5fff
--- /dev/null
+++ b/private/ole32/stg/ref/h/dfexcept.hxx
@@ -0,0 +1,37 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dfexcept.hxx
+//
+// Contents: Macros to make exception code no-ops in 16-bit
+// Includes real exceptions for 32-bit
+//
+//---------------------------------------------------------------
+
+#ifndef __DFEXCEPT_HXX__
+#define __DFEXCEPT_HXX__
+
+
+struct Exception
+{
+ SCODE GetErrorCode(void) { return 0; }
+};
+
+#undef TRY
+#define TRY
+#undef CATCH
+#define CATCH(c, e) if (0) { Exception e;
+#undef AND_CATCH
+#define AND_CATCH(c, e) } else if (0) { Exception e;
+#undef END_CATCH
+#define END_CATCH }
+#undef RETHROW
+#define RETHROW(x)
+
+#endif // ifndef __DFEXCEPT_HXX__
+
+
+
+
diff --git a/private/ole32/stg/ref/h/dffuncs.hxx b/private/ole32/stg/ref/h/dffuncs.hxx
new file mode 100644
index 000000000..07f0c69da
--- /dev/null
+++ b/private/ole32/stg/ref/h/dffuncs.hxx
@@ -0,0 +1,112 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dffuncs.hxx
+//
+// Contents: CDocFile inline functions
+// In a separate file to avoid circular dependencies
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DFFUNCS_HXX__
+#define __DFFUNCS_HXX__
+
+#include <cdocfile.hxx>
+#include <sstream.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::CDocFile, public
+//
+// Synopsis: Empty object ctor
+//
+// Aguments: [dl] - LUID
+// [pdfb] - Basis
+//
+//---------------------------------------------------------------
+
+
+inline CDocFile::CDocFile(DFLUID dl, ILockBytes *pilbBase)
+ : PDocFile(dl)
+{
+ _cReferences = 0;
+ _pilbBase = pilbBase;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::CDocFile, public
+//
+// Synopsis: Handle-setting construction
+//
+// Arguments: [pms] - MultiStream to use
+// [sid] - SID to use
+// [dl] - LUID
+// [pdfb] - Basis
+//
+//---------------------------------------------------------------
+
+inline CDocFile::CDocFile(CMStream MSTREAM_NEAR *pms,
+ SID sid,
+ DFLUID dl,
+ ILockBytes *pilbBase)
+ : PDocFile(dl)
+{
+ _stgh.Init(pms, sid);
+ _cReferences = 0;
+ _pilbBase = pilbBase;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::~CDocFile, public
+//
+// Synopsis: Destructor
+//
+//---------------------------------------------------------------
+
+inline CDocFile::~CDocFile(void)
+{
+ olAssert(_cReferences == 0);
+ if (_stgh.IsValid())
+ {
+ if (_stgh.IsRoot())
+ DllReleaseMultiStream(_stgh.GetMS());
+ }
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFile::GetHandle, public
+//
+// Synopsis: Returns the handle
+//
+//---------------------------------------------------------------
+
+
+inline CStgHandle *CDocFile::GetHandle(void)
+{
+ return &_stgh;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDocFile::DecRef, public
+//
+// Synopsis: Decrements the ref count
+//
+//----------------------------------------------------------------------------
+
+
+inline void CDocFile::DecRef(void)
+{
+ AtomicDec(&_cReferences);
+}
+
+
+
+#endif // #ifndef __DFFUNCS_HXX__
diff --git a/private/ole32/stg/ref/h/dfmsp.hxx b/private/ole32/stg/ref/h/dfmsp.hxx
new file mode 100644
index 000000000..4c64b310a
--- /dev/null
+++ b/private/ole32/stg/ref/h/dfmsp.hxx
@@ -0,0 +1,365 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992
+//
+// File: dfmsp.hxx
+//
+// Contents: DocFile and MultiStream shared private definitions
+//
+//---------------------------------------------------------------
+
+#ifndef __DFMSP_HXX__
+#define __DFMSP_HXX__
+
+#include <ref.hxx>
+#include <wchar.h>
+#include <memory.h>
+#include <string.h>
+
+// Target-dependent things
+
+//
+// x86 16-bit build optimizations
+//
+// Some function parameters are always stack based pointers,
+// so we can let the compiler use near addressing via ss by
+// declaring the parameter stack based.
+//
+
+#define STACKBASED
+
+//
+// x86 16-bit retail build optimizations
+//
+// For the retail build, we group the code segments,
+// allowing us to make many calls near.
+//
+
+#define DF_NEAR
+#define DIR_NEAR
+#define FAT_NEAR
+#define MSTREAM_NEAR
+
+
+// Segmented memory model definitions
+#define HUGEP
+
+#ifndef LISet32
+#define LISet32(li, v) \
+ ((li).HighPart = ((LONG)(v)) < 0 ? -1 : 0, (li).LowPart = (v))
+#endif
+#ifndef ULISet32
+#define ULISet32(li, v) ((li).HighPart = 0, (li).LowPart = (v))
+#endif
+#define LISetLow(li, v) ((li).LowPart = (v))
+#define LISetHigh(li, v) ((li).HighPart = (v))
+#define ULISetLow(li, v) ((li).LowPart = (v))
+#define ULISetHigh(li, v) ((li).HighPart = (v))
+#define LIGetLow(li) ((li).LowPart)
+#define LIGetHigh(li) ((li).HighPart)
+#define ULIGetLow(li) ((li).LowPart)
+#define ULIGetHigh(li) ((li).HighPart)
+
+// Fast safe increment/decrement
+#define AtomicInc(lp) (++*(lp))
+#define AtomicDec(lp) (--*(lp))
+
+
+// Switchable ANSI/Unicode support
+// Conversion routines assume null termination before max characters
+
+#define ATOT(a, t, max) strcpy(t, a)
+#define TTOA(t, a, max) strcpy(a, t)
+#define WTOT(w, t, max) wcstombs(t, w, max)
+#define TTOW(t, w, max) mbstowcs(w, t, max)
+
+#define tcscpy(t, f) strcpy(t, f)
+#define tcslen(t) strlen(t)
+
+#define TSTR(s) s
+
+
+
+
+
+//----------------------------------------------------------------------------
+
+// The name of this function might change, so encapsulate it
+#define DfGetScode(hr) GetScode(hr)
+
+
+
+#define ValidateBuffer(pv, n) S_OK
+#define ValidatePtrBuffer(pv) S_OK
+#define ValidateHugeBuffer(pv, n) S_OK
+#define ValidateOutBuffer(pv, n) S_OK
+#define ValidateOutPtrBuffer(pv) S_OK
+#define ValidateHugeOutBuffer(pv, n) S_OK
+#define ValidateIid(riid) S_OK
+#define ValidateInterface(punk,riid) S_OK
+#define ValidateWcs(pwcs, cwcMax) S_OK
+#define ValidateSz(psz, cchMax) S_OK
+#define ValidateNameW(pwcs, cchMax) S_OK
+#define ValidateNameA(psz, cchMax) S_OK
+// Enumeration for Get/SetTime
+enum WHICHTIME
+{
+ WT_CREATION,
+ WT_MODIFICATION,
+ WT_ACCESS
+};
+
+// Time type
+typedef FILETIME TIME_T;
+
+// Signature for transactioning
+typedef DWORD DFSIGNATURE;
+#define DF_INVALIDSIGNATURE ((DFSIGNATURE)-1)
+
+// Convenience macros for signature creation
+#define LONGSIG(c1, c2, c3, c4) \
+ (((ULONG) (BYTE) (c1)) | \
+ (((ULONG) (BYTE) (c2)) << 8) | \
+ (((ULONG) (BYTE) (c3)) << 16) | \
+ (((ULONG) (BYTE) (c4)) << 24))
+
+#ifndef min
+#define min(a, b) ((a)<(b) ? (a) : (b))
+#endif
+#ifndef max
+#define max(a, b) ((a)>(b) ? (a) : (b))
+#endif
+
+#define DfAllocWC(cwc, ppwcs) (*ppwcs = new WCHAR[cwc],\
+ (*ppwcs != NULL) ? S_OK: STG_E_INSUFFICIENTMEMORY)
+
+#define DfAllocWCS(pwcs, ppwcs) DfAllocWC(wcslen(pwcs)+1, ppwcs)
+
+SCODE DfGetTOD(TIME_T *ptm);
+
+// Docfile locally unique identity
+// Every entry in a multistream has a LUID generated and stored for it
+typedef DWORD DFLUID;
+#define DF_NOLUID 0
+
+typedef WCHAR **SNBW;
+
+typedef struct
+{
+ WCHAR *pwcsName;
+ DWORD type;
+ ULARGE_INTEGER cbSize;
+ FILETIME mtime;
+ FILETIME ctime;
+ FILETIME atime;
+ DWORD grfMode;
+ DWORD grfLocksSupported;
+ CLSID clsid;
+ DWORD grfStateBits;
+ DWORD reserved;
+} STATSTGW;
+
+#define TSTDMETHODIMP SCODE
+#define TSTDAPI(name) SCODE name##W
+
+#define CBSTORAGENAME (CWCSTORAGENAME*sizeof(WCHAR))
+
+// A Unicode case-insensitive compare
+// No such thing really exists so we use our own
+#define dfwcsnicmp(wcsa, wcsb, len) wcsnicmp(wcsa, wcsb, len)
+
+
+// A name for a docfile element
+class CDfName
+{
+private:
+ BYTE _ab[CBSTORAGENAME];
+ WORD _cb;
+
+public:
+ CDfName(void) { _cb = 0; }
+
+ void Set(WORD const cb, BYTE const *pb)
+ {
+ _cb = cb;
+ if (pb)
+ memcpy(_ab, pb, cb);
+ }
+ void Set(WCHAR const *pwcs) { Set((wcslen(pwcs)+1)*sizeof(WCHAR),
+ (BYTE const *)pwcs); }
+ void Set(char const *psz) { Set(strlen(psz)+1, (BYTE const *)psz); }
+
+ // Special method for names with prepended character
+ void Set(WCHAR const wcLead, WCHAR const *pwcs)
+ {
+ _cb = (wcslen(pwcs)+2)*sizeof(WCHAR);
+ *(WCHAR *)_ab = wcLead;
+ wcscpy((WCHAR *)_ab+1, pwcs);
+ }
+
+ inline void Set(CDfName const *pdfn);
+
+ CDfName(WORD const cb, BYTE const *pb) { Set(cb, pb); }
+ CDfName(WCHAR const *pwcs) { Set(pwcs); }
+ CDfName(char const *psz) { Set(psz); }
+
+ WORD GetLength(void) const { return _cb; }
+ BYTE *GetBuffer(void) const { return (BYTE *) _ab; }
+
+ BOOL IsEqual(CDfName const *dfn) const
+ {
+ // This assumes that all DfNames are actually Unicode strings
+ return _cb == dfn->_cb &&
+ dfwcsnicmp((WCHAR *)_ab, (WCHAR *)dfn->GetBuffer(), _cb) == 0;
+ }
+};
+
+inline void CDfName::Set(CDfName const *pdfn)
+{
+ Set(pdfn->GetLength(), pdfn->GetBuffer());
+}
+
+// Fast, fixed space iterator structure
+struct SIterBuffer
+{
+ CDfName dfnName;
+ DWORD type;
+};
+
+//SID is a Stream Identifier
+typedef ULONG SID;
+
+// IsEntry entry information
+struct SEntryBuffer
+{
+ DFLUID luid;
+ DWORD dwType;
+ SID sid;
+};
+
+// Destroy flags
+#define DESTROY_FROM_HANDLE 0
+#define DESTROY_FROM_ENTRY 1
+#define DESTROY_FROM 0x01
+#define DESTROY_SELF 0x40
+#define DESTROY_RECURSIVE 0x80
+
+#define DESTROY_HANDLE (DESTROY_FROM_HANDLE | DESTROY_SELF)
+#define DESTROY_ENTRY (DESTROY_FROM_ENTRY | DESTROY_SELF)
+
+// Root startup flags
+#define RSF_OPEN 0x00
+#define RSF_CONVERT 0x01
+#define RSF_TRUNCATE 0x02
+#define RSF_CREATE 0x04
+#define RSF_DELAY 0x08
+#define RSF_DELETEONRELEASE 0x10
+#define RSF_OPENCREATE 0x20
+#define RSF_RESERVE_HANDLE 0x40
+
+#define RSF_CREATEFLAGS (RSF_CREATE | RSF_TRUNCATE | RSF_OPENCREATE)
+
+// Stream copy buffer size
+ULONG const STREAMBUFFERSIZE = 8192;
+
+// ILockBytes copy buffer size
+ULONG const LOCKBYTESBUFFERSIZE = 16384;
+
+// Docfile flags for permissions and other information kept
+// on streams and docfiles
+typedef WORD DFLAGS;
+
+#define DF_TRANSACTEDSELF 0x0001
+
+#define DF_TRANSACTED 0x0002
+#define DF_DIRECT 0x0000
+
+#define DF_INDEPENDENT 0x0004
+#define DF_DEPENDENT 0x0000
+
+#define DF_COMMIT 0x0008
+#define DF_ABORT 0x0000
+
+#define DF_INVALID 0x0010
+
+#define DF_REVERTED 0x0020
+#define DF_NOTREVERTED 0x0000
+
+#define DF_READ 0x0040
+#define DF_WRITE 0x0080
+#define DF_READWRITE (DF_READ | DF_WRITE)
+
+#define DF_DENYREAD 0x0100
+#define DF_DENYWRITE 0x0200
+#define DF_DENYALL (DF_DENYREAD | DF_DENYWRITE)
+
+#define DF_PRIORITY 0x0400
+#define DF_CREATE 0x0800
+#define DF_CACHE 0x1000
+#define DF_NOUPDATE 0x2000
+
+// Shift required to translate from DF_READWRITE to DF_DENYALL
+#define DF_DENIALSHIFT 2
+
+// Permission abstraction macros
+// These only work with DF_* flags
+#define P_READ(f) ((f) & DF_READ)
+#define P_WRITE(f) ((f) & DF_WRITE)
+#define P_READWRITE(f) (((f) & (DF_READ | DF_WRITE)) == (DF_READ | DF_WRITE))
+#define P_DENYREAD(f) ((f) & DF_DENYREAD)
+#define P_DENYWRITE(f) ((f) & DF_DENYWRITE)
+#define P_DENYALL(f) (((f) & (DF_DENYREAD | DF_DENYWRITE)) == \
+ (DF_DENYREAD | DF_DENYWRITE))
+#define P_PRIORITY(f) ((f) & DF_PRIORITY)
+#define P_TRANSACTED(f) ((f) & DF_TRANSACTED)
+#define P_DIRECT(f) (!P_TRANSACTED(f))
+#define P_INDEPENDENT(f) ((f) & DF_INDEPENDENT)
+#define P_DEPENDENT(f) (!P_INDEPENDENT(f))
+#define P_TSELF(f) ((f) & DF_TRANSACTEDSELF)
+#define P_INVALID(f) ((f) & DF_INVALID)
+#define P_REVERTED(f) ((f) & DF_REVERTED)
+#define P_COMMIT(f) ((f) & DF_COMMIT)
+#define P_ABORT(f) (!P_COMMIT(f))
+#define P_CREATE(f) ((f) & DF_CREATE)
+#define P_CACHE(f) ((f) & DF_CACHE)
+#define P_NOUPDATE(f) ((f) & DF_NOUPDATE)
+
+// Translation functions
+DFLAGS ModeToDFlags(DWORD const dwModeFlags);
+DWORD DFlagsToMode(DFLAGS const df);
+
+// Flags for what state has been dirtied
+#define DIRTY_CREATETIME 0x0001
+#define DIRTY_MODIFYTIME 0x0002
+#define DIRTY_ACCESSTIME 0x0004
+#define DIRTY_CLASS 0x0008
+#define DIRTY_STATEBITS 0x0010
+
+// Allow text in asserts
+#define aMsg(s) ((s) != NULL)
+
+// Indicate that something is a property value
+// This must not conflict with official STGTY_* flags
+#define STGTY_REAL (STGTY_STORAGE | STGTY_STREAM | STGTY_LOCKBYTES)
+
+#define REAL_STGTY(f) (f)
+
+extern void *DfMemAlloc(DWORD dwFlags, size_t size);
+extern void DfMemFree(void *mem);
+
+extern void *TaskMemAlloc(size_t size);
+extern void TaskMemFree(void *mem);
+
+// Buffer management
+#define CB_LARGEBUFFER 32768
+#define CB_PAGEBUFFER 4096
+#define CB_SMALLBUFFER 512
+
+extern SCODE GetBuffer(USHORT cbMin, USHORT cbMax, BYTE **ppb,
+ USHORT *pcbActual);
+extern void GetSafeBuffer(USHORT cbMin, USHORT cbMax, BYTE **ppb,
+ USHORT *pcbActual);
+extern void FreeBuffer(BYTE *pb);
+
+#endif // #ifndef __DFMSP_HXX__
diff --git a/private/ole32/stg/ref/h/dfver.h b/private/ole32/stg/ref/h/dfver.h
new file mode 100644
index 000000000..b87d66d72
--- /dev/null
+++ b/private/ole32/stg/ref/h/dfver.h
@@ -0,0 +1,3 @@
+#define rmj 3
+#define rmm 33
+#define rup 0
diff --git a/private/ole32/stg/ref/h/difat.hxx b/private/ole32/stg/ref/h/difat.hxx
new file mode 100644
index 000000000..1e9f8ba56
--- /dev/null
+++ b/private/ole32/stg/ref/h/difat.hxx
@@ -0,0 +1,131 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: difat.hxx
+//
+// Contents: Double-indirect Fat class headers
+//
+// Classes: CDIFat
+// CDIFatVector
+//
+// Functions:
+//
+//--------------------------------------------------------------------------
+
+#ifndef __DIFAT_HXX__
+#define __DIFAT_HXX__
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDIFat (dif)
+//
+// Purpose: Double Indirect Fat class for MSF
+//
+// Interface: See below.
+//
+//--------------------------------------------------------------------------
+
+class CDIFat
+{
+
+public:
+ CDIFat(USHORT cbSector);
+ inline ~CDIFat();
+
+ VOID Empty(VOID);
+
+
+ SCODE GetFatSect(const FSINDEX oSect, SECT *psect);
+ SCODE SetFatSect(const FSINDEX oSect, const SECT sect);
+
+ SCODE GetSect(const FSINDEX oSect, SECT *psect);
+
+ SCODE Init(CMStream MSTREAM_NEAR *pmsParent, const FSINDEX cFatSect);
+ SCODE InitConvert(CMStream MSTREAM_NEAR *pmsParent, SECT sectMax);
+ inline SCODE InitNew(CMStream MSTREAM_NEAR *pmsParent);
+
+
+ SCODE Flush(void);
+
+ inline void SetParent(CMStream MSTREAM_NEAR *pms);
+private:
+
+ CFatVector _fv;
+ CMStream MSTREAM_NEAR * _pmsParent;
+ FSINDEX _cfsTable;
+
+ SCODE Resize(FSINDEX fsiSize);
+
+ inline VOID SectToPair(
+ SECT sect,
+ FSINDEX *pipfs,
+ FSOFFSET *pisect) const;
+
+ SECT PairToSect(FSINDEX ipfs, FSOFFSET isect) const;
+
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::~CDIFat, public
+//
+// Synopsis: CDIFat destructor
+//
+//--------------------------------------------------------------------------
+
+inline CDIFat::~CDIFat()
+{
+ msfDebugOut((DEB_TRACE,"In CDIFat destructor\n"));
+}
+
+
+inline VOID CDIFat::SectToPair(FSINDEX sect, FSINDEX *pipfs, FSOFFSET *pisect) const
+{
+ msfAssert(sect >= CSECTFAT);
+
+ sect = sect - CSECTFAT;
+ *pipfs = (FSINDEX)(sect / _fv.GetSectTable());
+ *pisect = (FSOFFSET)(sect % _fv.GetSectTable());
+}
+
+inline SECT CDIFat::PairToSect(FSINDEX ipfs, FSOFFSET isect) const
+{
+ return ipfs * _fv.GetSectTable() + isect + CSECTFAT;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDIFat::InitNew, public
+//
+// Synopsis: Init function for new DIFat
+//
+// Arguments: None.
+//
+// Returns: S_OK if call completed successfully.
+//
+// Algorithm: Doesn't do anything at present.
+//
+//--------------------------------------------------------------------------
+
+inline SCODE CDIFat::InitNew(CMStream MSTREAM_NEAR *pmsParent)
+{
+ _pmsParent = pmsParent;
+ _fv.Init(_pmsParent, 0);
+ _cfsTable = 0;
+ return S_OK;
+}
+
+
+inline void CDIFat::SetParent(CMStream MSTREAM_NEAR *pms)
+{
+ _pmsParent = pms;
+ _fv.SetParent(pms);
+}
+
+
+
+
+#endif //__DIFAT_HXX__
diff --git a/private/ole32/stg/ref/h/dir.hxx b/private/ole32/stg/ref/h/dir.hxx
new file mode 100644
index 000000000..503af8a73
--- /dev/null
+++ b/private/ole32/stg/ref/h/dir.hxx
@@ -0,0 +1,358 @@
+//+-------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dir.hxx
+//
+// Contents: Directory header for Mstream project
+//
+// Classes: CDirEntry - Information on a single stream
+// CDirSect - Sector sized array of DirEntry
+// CDirVector - Resizable array of CDirSect
+// CDirectory - Grouping of DirSectors
+//
+// Notes: Properties and storage elements are kept in the same
+// child list so the *ChildProp functions are unused. 1/18/93
+//
+//--------------------------------------------------------------------
+
+
+
+
+#include <msf.hxx>
+#include <wchar.h>
+#include <vect.hxx>
+
+
+#ifndef __DIR_HXX__
+#define __DIR_HXX__
+
+
+#define DIR_HIT 0x01
+
+
+struct SPreDirEntry
+{
+protected:
+ CDfName _dfn; // Name (word-aligned)
+ BYTE _mse; // STGTY_...
+ BYTE _bflags;
+
+ SID _sidLeftSib; // Siblings
+ SID _sidRightSib; // Siblings
+
+ SID _sidChild; // Storage - Child list
+ GUID _clsId; // Storage - Class id
+ DWORD _dwUserFlags; // Storage - User flags
+ TIME_T _time[2]; // Storage - time stamps
+
+ SECT _sectStart; // Stream - start
+ ULONG _ulSize; // Stream - size
+
+ DFPROPTYPE _dptPropType; // Property - type
+};
+
+
+#define STGTY_INVALID 0
+#define STGTY_ROOT 5
+
+// Macros which tell whether a direntry has stream fields,
+// storage fields or property fields
+#define STREAMLIKE(mse) \
+ (((mse) & STGTY_REAL) == STGTY_STREAM || (mse) == STGTY_ROOT)
+#define STORAGELIKE(mse) \
+ (((mse) & STGTY_REAL) == STGTY_STORAGE || (mse) == STGTY_ROOT)
+
+//+----------------------------------------------------------------------
+//
+// Class: CDirEntry (de)
+//
+// Purpose: Holds information on one stream
+//
+// Interface: GetName - returns name of stream
+// GetStart - return first sector for stream
+// GetSize - returns size of stream
+// GetFlags - returns flag byte
+//
+// SetName - sets name
+// SetStart - sets first sector
+// SetSize - sets size
+// SetFlags - sets flag byte
+//
+// IsFree - returns 1 if element is not in use
+// IsEntry - returns 1 is element name matches argument
+//
+// Notes: B-flat,C-sharp
+//
+//-----------------------------------------------------------------------
+const CBDIRPAD = DIRENTRYSIZE - sizeof(SPreDirEntry);
+
+// DirEntry bit flags are used for the following private state
+
+// Usage Bit
+
+#define DECOLORBIT 0x01
+#define DERESERVED 0xfe
+
+typedef enum
+{
+ DE_RED = 0,
+ DE_BLACK = 1
+} DECOLOR;
+
+class CDirEntry: private SPreDirEntry
+{
+
+public:
+ DIR_NEAR CDirEntry();
+
+ inline void DIR_NEAR Init(MSENTRYFLAGS mse);
+
+ inline CDfName const * DIR_NEAR GetName(VOID) const;
+ inline SECT DIR_NEAR GetStart(VOID) const;
+ inline ULONG DIR_NEAR GetSize(VOID) const;
+ inline SID DIR_NEAR GetLeftSib(VOID) const;
+ inline SID DIR_NEAR GetRightSib(VOID) const;
+ inline SID DIR_NEAR GetChild(VOID) const;
+ inline MSENTRYFLAGS DIR_NEAR GetFlags(VOID) const;
+ inline DECOLOR DIR_NEAR GetColor(VOID) const;
+ inline TIME_T DIR_NEAR GetTime(WHICHTIME tt) const;
+ inline GUID DIR_NEAR GetClassId(VOID) const;
+ inline DWORD DIR_NEAR GetUserFlags(VOID) const;
+
+ inline void DIR_NEAR SetName(const CDfName *pdfn);
+ inline void DIR_NEAR SetStart(const SECT);
+ inline void DIR_NEAR SetSize(const ULONG);
+ inline void DIR_NEAR SetLeftSib(const SID);
+ inline void DIR_NEAR SetRightSib(const SID);
+ inline void DIR_NEAR SetChild(const SID);
+ inline void DIR_NEAR SetFlags(const MSENTRYFLAGS mse);
+ inline void DIR_NEAR SetColor(DECOLOR);
+ inline void DIR_NEAR SetTime(WHICHTIME tt, TIME_T nt);
+ inline void DIR_NEAR SetClassId(GUID cls);
+ inline void DIR_NEAR SetUserFlags(DWORD dwUserFlags, DWORD dwMask);
+
+ inline BOOL DIR_NEAR IsFree(VOID) const;
+ inline BOOL DIR_NEAR IsEntry(CDfName const *pdfn) const;
+
+private:
+ inline BYTE DIR_NEAR GetBitFlags(VOID) const;
+ inline void DIR_NEAR SetBitFlags(BYTE bValue, BYTE bMask);
+
+ BYTE _bpad[CBDIRPAD];
+};
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDirSect (ds)
+//
+// Purpose: Provide sector sized block of DirEntries
+//
+// Interface:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+class CDirSect
+{
+public:
+ SCODE DIR_NEAR Init(USHORT cbSector);
+
+ inline CDirEntry* DIR_NEAR GetEntry(DIROFFSET iEntry);
+
+private:
+ CDirEntry _adeEntry[];
+};
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CDirVector (dv)
+//
+// Purpose: Provide resizable array of DirSectors.
+//
+// Interface:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CDirVector: public CPagedVector
+{
+public:
+ inline DIR_NEAR CDirVector(USHORT cbSector);
+
+ inline SCODE DIR_NEAR GetTable(
+ const DIRINDEX iTable,
+ const DWORD dwFlags,
+ CDirSect **ppds);
+
+private:
+ const USHORT _cbSector;
+};
+
+
+//+----------------------------------------------------------------------
+//
+// Class: CDirectory (dir)
+//
+// Purpose: Main interface for directory functionality
+//
+// Interface: GetFree - returns an SID for a free DirEntry
+// Find - finds its argument in the directory list
+// SetEntry - sets up a DirEntry and writes out its sector
+// GetName - returns the name of a DirEntry
+// GetStart - returns the start sector of a DirEntry
+// GetSize - returns the size of a DirEntry
+// GetFlags - returns the flag byte of a DirEntry
+//
+//
+// Notes:
+//
+//-----------------------------------------------------------------------
+
+typedef enum DIRENTRYOP
+{
+ DEOP_FIND = 0,
+ DEOP_REMOVE = 1
+} DIRENTRYOP;
+
+class CDirectory
+{
+public:
+ DIR_NEAR CDirectory(USHORT cbSector);
+
+ VOID DIR_NEAR Empty(VOID);
+
+
+ SCODE DIR_NEAR Init(CMStream MSTREAM_NEAR *pmsParent, DIRINDEX cSect);
+
+
+ SCODE DIR_NEAR InitNew(CMStream MSTREAM_NEAR *pmsParent);
+
+ SCODE DIR_NEAR FindGreaterEntry(
+ SID sidChildRoot,
+ CDfName const *pdfn,
+ SID *psidResult);
+
+ SCODE DIR_NEAR SetStart(const SID sid, const SECT sect);
+ SCODE DIR_NEAR SetTime(const SID sid, WHICHTIME tt, TIME_T nt);
+ SCODE DIR_NEAR SetChild(const SID sid, const SID sidChild);
+ SCODE DIR_NEAR SetSize(const SID sid, const ULONG cbSize);
+ SCODE DIR_NEAR SetClassId(const SID sid, const GUID cls);
+ SCODE DIR_NEAR SetFlags(const SID sid, const MSENTRYFLAGS mse);
+ SCODE DIR_NEAR SetUserFlags(const SID sid,
+ DWORD dwUserFlags,
+ DWORD dwMask);
+
+ inline SCODE DIR_NEAR GetName(const SID sid, CDfName *pdfn);
+ inline SCODE DIR_NEAR GetStart(const SID sid, SECT * psect);
+ inline SCODE DIR_NEAR GetSize(const SID sid, ULONG *pulSize);
+
+ inline SCODE DIR_NEAR GetChild(const SID sid, SID *psid);
+ inline SCODE DIR_NEAR GetFlags(const SID sid, MSENTRYFLAGS *pmse);
+ inline SCODE DIR_NEAR GetClassId(const SID sid, GUID *pcls);
+ inline SCODE DIR_NEAR GetTime(const SID sid, WHICHTIME tt, TIME_T *ptime);
+ inline SCODE DIR_NEAR GetUserFlags(const SID sid, DWORD *pdwUserFlags);
+
+ SCODE DIR_NEAR GetDirEntry(
+ const SID sid,
+ const DWORD dwFlags,
+ CDirEntry **ppde);
+
+ void DIR_NEAR ReleaseEntry(SID sid);
+
+ SCODE DIR_NEAR CreateEntry(
+ SID sidParent,
+ CDfName const *pdfn,
+ MSENTRYFLAGS mef,
+ SID *psidNew);
+
+ SCODE DIR_NEAR RenameEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ CDfName const *pdfnNew);
+
+ inline SCODE DIR_NEAR IsEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ SEntryBuffer *peb);
+
+ SCODE DIR_NEAR DestroyAllChildren(
+ SID const sidParent);
+
+ SCODE DIR_NEAR DestroyChild(
+ SID const sidParent,
+ CDfName const *pdfn);
+
+ SCODE DIR_NEAR StatEntry(
+ SID const sid,
+ STATSTG *pstatstg);
+
+ inline SCODE DIR_NEAR Flush(VOID);
+
+ inline void DIR_NEAR SetParent(CMStream MSTREAM_NEAR * pmsParent);
+
+private:
+
+ CDirVector _dv;
+ DIRINDEX _cdsTable;
+ CMStream MSTREAM_NEAR * _pmsParent;
+ DIROFFSET _cdeEntries;
+
+ SID _sidFirstFree;
+
+ SCODE DIR_NEAR Resize(DIRINDEX);
+ inline DIRINDEX DIR_NEAR SidToTable(SID sid) const;
+ inline SID DIR_NEAR PairToSid(
+ DIRINDEX iTable,
+ DIROFFSET iEntry) const;
+
+ inline SCODE DIR_NEAR SidToPair(
+ SID sid,
+ DIRINDEX* pipds,
+ DIROFFSET* pide) const;
+
+
+ SCODE DIR_NEAR GetFree(SID * psid);
+
+ SCODE DIR_NEAR InsertEntry(
+ SID sidParent,
+ SID sidInsert,
+ CDfName const *pdfnInsert);
+
+ SCODE DIR_NEAR FindEntry(
+ SID sidParent,
+ CDfName const *pdfnFind,
+ DIRENTRYOP deop,
+ SEntryBuffer *peb);
+
+ static int DIR_NEAR NameCompare(
+ CDfName const *pdfn1,
+ CDfName const *pdfn2);
+
+ SCODE SplitEntry(
+ CDfName const *pdfn,
+ SID sidTree,
+ SID sidGreat,
+ SID sidGrand,
+ SID sidParent,
+ SID sidChild,
+ SID *psid);
+
+ SCODE RotateEntry(
+ CDfName const *pdfn,
+ SID sidTree,
+ SID sidParent,
+ SID *psid);
+
+ SCODE DIR_NEAR SetColorBlack(const SID sid);
+};
+
+
+#endif //__DIR_HXX__
diff --git a/private/ole32/stg/ref/h/dirfunc.hxx b/private/ole32/stg/ref/h/dirfunc.hxx
new file mode 100644
index 000000000..3a0fec9ee
--- /dev/null
+++ b/private/ole32/stg/ref/h/dirfunc.hxx
@@ -0,0 +1,409 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: dirfunc.hxx
+//
+// Contents: Inline functions for Directory code
+//
+// Classes:
+//
+// Functions:
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DIRFUNC_HXX__
+#define __DIRFUNC_HXX__
+
+#include <page.hxx>
+
+
+inline BOOL DIR_NEAR CDirEntry::IsFree(VOID) const
+{
+ return _mse == 0;
+}
+
+inline BOOL DIR_NEAR CDirEntry::IsEntry(CDfName const * pdfn) const
+{
+ return !IsFree() && pdfn->IsEqual(&_dfn);
+}
+
+
+inline void DIR_NEAR CDirEntry::SetLeftSib(const SID sid)
+{
+ _sidLeftSib = sid;
+}
+
+inline void DIR_NEAR CDirEntry::SetRightSib(const SID sid)
+{
+ _sidRightSib = sid;
+}
+
+
+inline void DIR_NEAR CDirEntry::SetChild(const SID sid)
+{
+ _sidChild = sid;
+}
+
+inline void DIR_NEAR CDirEntry::SetName(const CDfName *pdfn)
+{
+ _dfn.Set(pdfn->GetLength(), pdfn->GetBuffer());
+}
+
+inline void DIR_NEAR CDirEntry::SetStart(const SECT sect)
+{
+ msfAssert(STREAMLIKE(_mse));
+ _sectStart=sect;
+}
+
+inline void DIR_NEAR CDirEntry::SetSize(const ULONG ulSize)
+{
+ msfAssert(STREAMLIKE(_mse));
+ _ulSize=ulSize;
+}
+
+inline void DIR_NEAR CDirEntry::SetFlags(const MSENTRYFLAGS mse)
+{
+ msfAssert(mse <= 0xff);
+ _mse = (const BYTE) mse;
+}
+
+inline void DIR_NEAR CDirEntry::SetBitFlags(BYTE bValue, BYTE bMask)
+{
+ _bflags = (_bflags & ~bMask) | (bValue & bMask);
+}
+
+inline void DIR_NEAR CDirEntry::SetColor(DECOLOR color)
+{
+ SetBitFlags(color, DECOLORBIT);
+}
+
+inline void DIR_NEAR CDirEntry::SetTime(WHICHTIME tt, TIME_T nt)
+{
+ msfAssert((tt == WT_CREATION) || (tt == WT_MODIFICATION));
+ _time[tt] = nt;
+}
+
+inline void DIR_NEAR CDirEntry::SetClassId(GUID cls)
+{
+ msfAssert(STORAGELIKE(_mse));
+ _clsId = cls;
+}
+
+
+inline void DIR_NEAR CDirEntry::SetUserFlags(DWORD dwUserFlags, DWORD dwMask)
+{
+ msfAssert(STORAGELIKE(_mse));
+ _dwUserFlags = (_dwUserFlags & ~dwMask) | (dwUserFlags & dwMask);
+}
+
+inline SID DIR_NEAR CDirEntry::GetLeftSib(VOID) const
+{
+ return _sidLeftSib;
+}
+
+inline SID DIR_NEAR CDirEntry::GetRightSib(VOID) const
+{
+ return _sidRightSib;
+}
+
+
+inline SID DIR_NEAR CDirEntry::GetChild(VOID) const
+{
+ return _sidChild;
+}
+
+inline GUID DIR_NEAR CDirEntry::GetClassId(VOID) const
+{
+ msfAssert(STORAGELIKE(_mse));
+ return _clsId;
+}
+
+inline CDfName const * DIR_NEAR CDirEntry::GetName(VOID) const
+{
+ return &_dfn;
+}
+
+inline SECT DIR_NEAR CDirEntry::GetStart(VOID) const
+{
+ msfAssert(STREAMLIKE(_mse));
+ return _sectStart;
+}
+
+inline ULONG DIR_NEAR CDirEntry::GetSize(VOID) const
+{
+ msfAssert(STREAMLIKE(_mse));
+ return _ulSize;
+}
+
+
+inline MSENTRYFLAGS DIR_NEAR CDirEntry::GetFlags(VOID) const
+{
+ return (MSENTRYFLAGS) _mse;
+}
+
+inline BYTE DIR_NEAR CDirEntry::GetBitFlags(VOID) const
+{
+ return _bflags;
+}
+
+inline DECOLOR DIR_NEAR CDirEntry::GetColor(VOID) const
+{
+ return((DECOLOR) (GetBitFlags() & DECOLORBIT));
+}
+
+inline TIME_T DIR_NEAR CDirEntry::GetTime(WHICHTIME tt) const
+{
+ msfAssert((tt == WT_CREATION) || (tt == WT_MODIFICATION));
+ return _time[tt];
+}
+
+inline DWORD DIR_NEAR CDirEntry::GetUserFlags(VOID) const
+{
+ msfAssert(STORAGELIKE(_mse));
+ return _dwUserFlags;
+}
+
+inline CDirEntry* DIR_NEAR CDirSect::GetEntry(DIROFFSET iEntry)
+{
+ return &(_adeEntry[iEntry]);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirVector::CDirVector, public
+//
+// Synopsis: Default constructor
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline DIR_NEAR CDirVector::CDirVector(USHORT cbSector)
+ : CPagedVector(SIDDIR),
+ _cbSector(cbSector)
+{
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirVector::GetTable, public
+//
+// Synopsis: Return a pointer to a DirSect for the given index
+// into the vector.
+//
+// Arguments: [iTable] -- index into vector
+//
+// Returns: Pointer to CDirSect indicated by index
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline SCODE DIR_NEAR CDirVector::GetTable(
+ const DIRINDEX iTable,
+ const DWORD dwFlags,
+ CDirSect **ppds)
+{
+ SCODE sc;
+
+ sc = CPagedVector::GetTable(iTable, dwFlags, (void **)ppds);
+
+ if (sc == STG_S_NEWPAGE)
+ {
+ (*ppds)->Init(_cbSector);
+ }
+ return sc;
+}
+
+inline DIRINDEX DIR_NEAR CDirectory::SidToTable(SID sid) const
+{
+ return (DIRINDEX)(sid / _cdeEntries);
+}
+
+inline SCODE DIR_NEAR CDirectory::GetName(const SID sid, CDfName *pdfn)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ *pdfn = *(pde->GetName());
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectory::GetStart, public
+//
+// Synposis: Retrieves the starting sector of a directory entry
+//
+// Arguments: [sid] -- Stream ID of stream in question
+//
+// Returns: Starting sector of stream
+//
+// Algorithm: Return the starting sector of the stream. If the
+// identifier is SIDFAT, return 0. If the identifier
+// is SIDDIR, return 1. Otherwise, return the starting
+// sector of the entry in question.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+inline SCODE DIR_NEAR CDirectory::GetStart(const SID sid, SECT *psect)
+{
+ msfAssert(sid <= MAXREGSID);
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ *psect = pde->GetStart();
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+
+inline SCODE DIR_NEAR CDirectory::GetSize(
+ const SID sid,
+ ULONG * pulSize)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+
+ *pulSize = pde->GetSize();
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+inline SCODE DIR_NEAR CDirectory::GetChild(const SID sid, SID * psid)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ *psid = pde->GetChild();
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+inline SCODE DIR_NEAR CDirectory::GetFlags(
+ const SID sid,
+ MSENTRYFLAGS *pmse)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ *pmse = pde->GetFlags();
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+inline SCODE DIR_NEAR CDirectory::GetClassId(const SID sid, GUID *pcls)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ *pcls = pde->GetClassId();
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+
+inline SCODE DIR_NEAR CDirectory::GetUserFlags(const SID sid,
+ DWORD *pdwUserFlags)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ *pdwUserFlags = pde->GetUserFlags();
+ ReleaseEntry(sid);
+
+ Err:
+ return sc;
+}
+
+inline SCODE DIR_NEAR CDirectory::GetTime(
+ const SID sid,
+ WHICHTIME tt,
+ TIME_T *ptime)
+{
+ SCODE sc;
+ CDirEntry *pde;
+
+ msfChk(GetDirEntry(sid, FB_NONE, &pde));
+ *ptime = pde->GetTime(tt == WT_ACCESS ? WT_MODIFICATION : tt);
+ ReleaseEntry(sid);
+ Err:
+ return sc;
+}
+
+inline SID DIR_NEAR CDirectory::PairToSid(
+ DIRINDEX iTable,
+ DIROFFSET iEntry) const
+{
+ return (SID)((iTable * _cdeEntries) + iEntry);
+}
+
+inline SCODE DIR_NEAR CDirectory::SidToPair(
+ SID sid,
+ DIRINDEX* pipds,
+ DIROFFSET* pide) const
+{
+ *pipds = (DIRINDEX)(sid / _cdeEntries);
+ *pide = (DIROFFSET)(sid % _cdeEntries);
+ return S_OK;
+}
+
+inline void DIR_NEAR CDirectory::SetParent(CMStream MSTREAM_NEAR *pms)
+{
+ _pmsParent = pms;
+ _dv.SetParent(pms);
+}
+
+
+inline SCODE DIR_NEAR CDirectory::IsEntry(SID const sidParent,
+ CDfName const *pdfn,
+ SEntryBuffer *peb)
+{
+ return FindEntry(sidParent, pdfn, DEOP_FIND, peb);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectory::Flush, private
+//
+// Synopsis: Write a dirsector out to the parent
+//
+// Arguments: [sid] -- SID of modified dirEntry
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Convert SID into table number, then write that
+// table out to the parent Multistream
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline SCODE DIR_NEAR CDirectory::Flush(VOID)
+{
+ return _dv.Flush();
+}
+
+
+#endif // #ifndef __DIRFUNC_HXX__
diff --git a/private/ole32/stg/ref/h/docfilep.hxx b/private/ole32/stg/ref/h/docfilep.hxx
new file mode 100644
index 000000000..fd9aa8850
--- /dev/null
+++ b/private/ole32/stg/ref/h/docfilep.hxx
@@ -0,0 +1,40 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: docfilep.hxx
+//
+// Contents: Private DocFile definitions
+//
+//---------------------------------------------------------------
+
+#ifndef __DOCFILEP_HXX__
+#define __DOCFILEP_HXX__
+
+
+
+#define CWCMAXPATHCOMPLEN CWCSTREAMNAME
+#define CBMAXPATHCOMPLEN (CWCMAXPATHCOMPLEN*sizeof(WCHAR))
+
+// Common bundles of STGM flags
+#define STGM_RDWR (STGM_READ | STGM_WRITE | STGM_READWRITE)
+#define STGM_DENY (STGM_SHARE_DENY_NONE | STGM_SHARE_DENY_READ | \
+ STGM_SHARE_DENY_WRITE | STGM_SHARE_EXCLUSIVE)
+
+#define VALID_IFTHERE(it) \
+ ((it) == STG_FAILIFTHERE || (it) == STG_CREATEIFTHERE || \
+ (it) == STG_CONVERTIFTHERE)
+
+#define VALID_COMMIT(cf) \
+ (((cf) & ~(STGC_OVERWRITE | STGC_ONLYIFCURRENT | \
+ STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE)) == 0)
+
+#define VALID_LOCKTYPE(lt) \
+ ((lt) == LOCK_WRITE || (lt) == LOCK_EXCLUSIVE || \
+ (lt) == LOCK_ONLYONCE)
+
+#define FLUSH_CACHE(cf) \
+ ((cf & STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE) == 0)
+
+#endif
diff --git a/private/ole32/stg/ref/h/entry.hxx b/private/ole32/stg/ref/h/entry.hxx
new file mode 100644
index 000000000..7ed08b4aa
--- /dev/null
+++ b/private/ole32/stg/ref/h/entry.hxx
@@ -0,0 +1,148 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: entry.hxx
+//
+// Contents: Entry management classes
+//
+// Classes: PEntry
+// CDirectEntry
+// CTransactedEntry
+//
+//---------------------------------------------------------------
+
+#ifndef __ENTRY_HXX__
+#define __ENTRY_HXX__
+
+#include <msf.hxx>
+
+//+--------------------------------------------------------------
+//
+// Class: PEntry (en)
+//
+// Purpose: Entry management
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+#define ROOT_LUID 1
+#define MINISTREAM_LUID 2
+#define ITERATOR_LUID 3
+#define LUID_BASE 4
+
+class PEntry
+{
+public:
+ inline DFLUID GetLuid(void);
+ virtual SCODE GetTime(WHICHTIME wt, TIME_T *ptm) = 0;
+ virtual SCODE SetTime(WHICHTIME wt, TIME_T tm) = 0;
+
+ SCODE CopyTimesFrom(PEntry *penFrom);
+
+ static inline DFLUID GetNewLuid(void);
+
+protected:
+ PEntry(DFLUID dl);
+
+private:
+ static DFLUID _dlBase;
+
+ const DFLUID _dl;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: PEntry::GetNewLuid, public
+//
+// Synopsis: Returns a new luid
+//
+//---------------------------------------------------------------
+
+inline DFLUID PEntry::GetNewLuid(void)
+{
+ DFLUID dl = _dlBase;
+ AtomicInc((long *)&_dlBase);
+ return dl;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PEntry::PEntry, protected
+//
+// Synopsis: Constructor, sets luid
+//
+//---------------------------------------------------------------
+
+inline PEntry::PEntry(DFLUID dl)
+: _dl(dl)
+{
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PEntry::GetLuid, public
+//
+// Synopsis: Returns the luid
+//
+//---------------------------------------------------------------
+
+inline DFLUID PEntry::GetLuid(void)
+{
+ return _dl;
+}
+
+//+--------------------------------------------------------------
+//
+// Class: CTransactedEntry (ten)
+//
+// Purpose: Transacted entry management
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+class CTransactedEntry
+{
+public:
+ inline void GetTime(WHICHTIME wt, TIME_T *ptm);
+ inline void SetTime(WHICHTIME wt, TIME_T tm);
+
+private:
+ TIME_T _tt[3];
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedEntry::GetTime, public
+//
+// Synopsis: Returns the time
+//
+//---------------------------------------------------------------
+
+inline void CTransactedEntry::GetTime(WHICHTIME wt, TIME_T *ptm)
+{
+ msfAssert(wt >= 0 && wt < 3);
+ *ptm = _tt[wt];
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CTransactedEntry::SetTime, public
+//
+// Synopsis: Sets the time
+//
+//---------------------------------------------------------------
+
+inline void CTransactedEntry::SetTime(WHICHTIME wt, TIME_T tm)
+{
+ msfAssert(wt >= 0 && wt < 3);
+ _tt[wt] = tm;
+}
+
+
+
+
+#endif // #ifndef __ENTRY_HXX__
diff --git a/private/ole32/stg/ref/h/error.hxx b/private/ole32/stg/ref/h/error.hxx
new file mode 100644
index 000000000..3c8f9e832
--- /dev/null
+++ b/private/ole32/stg/ref/h/error.hxx
@@ -0,0 +1,31 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992
+//
+// File: error.hxx
+//
+// Contents: Error code handler routines
+//
+//---------------------------------------------------------------
+
+#ifndef __ERROR_HXX__
+#define __ERROR_HXX__
+
+#if DBG == 1
+#define ErrJmp(comp, label, errval, var) \
+{\
+ comp##DebugOut((DEB_IERROR, "Error %lX at %s:%d\n",\
+ (unsigned long)errval, __FILE__, __LINE__));\
+ var = errval;\
+ goto label;\
+}
+#else
+#define ErrJmp(comp, label, errval, var) \
+{\
+ var = errval;\
+ goto label;\
+}
+#endif
+
+#endif // #ifndef __ERROR_HXX__
diff --git a/private/ole32/stg/ref/h/fat.hxx b/private/ole32/stg/ref/h/fat.hxx
new file mode 100644
index 000000000..a017b6fa0
--- /dev/null
+++ b/private/ole32/stg/ref/h/fat.hxx
@@ -0,0 +1,417 @@
+//+-------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: fat.hxx
+//
+// Contents: Header file for fat classes
+//
+// Classes: CFatSect - sector sized array of sector info
+// CFatVector - resizable array of CFatSect
+// CFat - Grouping of FatSect
+//
+//--------------------------------------------------------------------
+
+
+
+#ifndef __FAT_HXX__
+#define __FAT_HXX__
+
+#include <vect.hxx>
+
+#define DEB_FAT (DEB_ITRACE|0x00010000)
+
+
+//+----------------------------------------------------------------------
+//
+// Class: CFatSect (fs)
+//
+// Purpose: Holds one sector worth of FAT data
+//
+// Interface: getsize - Returns the size of the FAT (in sectors)
+// contents - Returns contents of any given FAT entry
+//
+// Notes:
+//
+//-----------------------------------------------------------------------
+
+
+class CFatSect
+{
+public:
+ SCODE FAT_NEAR Init(FSOFFSET uEntries);
+ SCODE FAT_NEAR InitCopy(USHORT uSize, CFatSect& fsOld);
+
+ inline SECT FAT_NEAR GetSect(const FSOFFSET sect) const;
+ inline void FAT_NEAR SetSect(const FSOFFSET sect,const SECT sectNew);
+
+ inline SECT FAT_NEAR GetNextFat(USHORT uSize) const;
+ inline void FAT_NEAR SetNextFat(USHORT uSize, const SECT sect);
+
+private:
+ SECT _asectEntry[];
+};
+
+
+
+inline SECT FAT_NEAR CFatSect::GetSect(const FSOFFSET sect) const
+{
+ return _asectEntry[sect];
+}
+
+inline void FAT_NEAR CFatSect::SetSect(const FSOFFSET sect, const SECT sectNew)
+{
+ _asectEntry[sect] = sectNew;
+}
+
+inline SECT FAT_NEAR CFatSect::GetNextFat(USHORT uSize) const
+{
+ return _asectEntry[uSize];
+}
+
+inline void FAT_NEAR CFatSect::SetNextFat(USHORT uSize, const SECT sect)
+{
+ _asectEntry[uSize] = sect;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CFatVector (fv)
+//
+// Purpose: *Finish This*
+//
+// Interface:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CFatVector: public CPagedVector
+{
+public:
+ inline FAT_NEAR CFatVector(
+ const SID sid,
+ FSOFFSET csectBlock,
+ FSOFFSET csectTable);
+
+ SCODE FAT_NEAR InitPage(FSINDEX iPage);
+
+ inline FSOFFSET GetSectBlock() const;
+ inline FSOFFSET GetSectTable() const;
+
+ inline SCODE FAT_NEAR GetTable(
+ const FSINDEX iTable,
+ const DWORD dwFlags,
+ CFatSect **pfs);
+
+private:
+ FSOFFSET const _csectTable;
+ FSOFFSET const _csectBlock;
+
+};
+
+
+inline FAT_NEAR CFatVector::CFatVector(
+ const SID sid,
+ FSOFFSET csectBlock,
+ FSOFFSET csectTable)
+ : CPagedVector(sid),
+ _csectTable(csectTable),
+ _csectBlock(csectBlock)
+{
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFatVector::GetSectTable, public
+//
+// Synopsis: Returns count of sector entries per table
+//
+// Returns: count of sector entries per table
+//
+//--------------------------------------------------------------------------
+
+inline FSOFFSET CFatVector::GetSectTable() const
+{
+ return _csectTable;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFatVector::GetSectTable, public
+//
+// Synopsis: Returns count of sector entries per block
+//
+// Returns: count of sector entries per block
+//
+//--------------------------------------------------------------------------
+
+inline FSOFFSET CFatVector::GetSectBlock() const
+{
+ return _csectBlock;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CFatVector::GetTable, public
+//
+// Synopsis: Return a pointer to a FatSect for the given index
+// into the vector.
+//
+// Arguments: [iTable] -- index into vector
+//
+// Returns: Pointer to CFatSect indicated by index
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline SCODE FAT_NEAR CFatVector::GetTable(
+ const FSINDEX iTable,
+ const DWORD dwFlags,
+ CFatSect **ppfs)
+{
+ SCODE sc;
+
+ sc = CPagedVector::GetTable(iTable, dwFlags, (void **)ppfs);
+
+ if (sc == STG_S_NEWPAGE)
+ {
+ (*ppfs)->Init(_csectBlock);
+ }
+
+ return sc;
+}
+
+
+
+
+//CSEG determines the maximum number of segments that will be
+//returned by a single Contig call.
+
+#define CSEG 32
+
+//+-------------------------------------------------------------------------
+//
+// Class: SSegment (seg)
+//
+// Purpose: Used for contiguity tables for multi-sector reads and
+// writes.
+//
+// Interface: None.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+struct SSegment {
+public:
+
+ SECT sectStart;
+ ULONG cSect;
+};
+
+class MSTREAM_NEAR CMStream;
+
+
+
+
+//+----------------------------------------------------------------------
+//
+// Class: CFat (fat)
+//
+// Purpose: Main interface to allocation routines
+//
+// Interface: Allocate - allocates new chain in the FAT
+// Extend - Extends an existing FAT chain
+// GetNext - Returns next sector in a chain
+// GetSect - Returns nth sector in a chain
+// GetESect - Returns nth sector in a chain, extending
+// if necessary
+// GetLength - Returns the # of sectors in a chain
+// setup - Initializes for an existing stream
+// setupnew - Initializes for a new stream
+//
+// checksanity - Debugging routine
+//
+// Notes:
+//
+//-----------------------------------------------------------------------
+
+class CFat
+{
+public:
+
+ FAT_NEAR CFat(SID sid, USHORT cbSector, USHORT uSectorShift);
+ FAT_NEAR ~CFat();
+
+ VOID FAT_NEAR Empty(VOID);
+
+ inline SCODE FAT_NEAR Allocate(ULONG ulSize, SECT *psectFirst);
+ SCODE FAT_NEAR GetNext(const SECT sect, SECT * psRet);
+
+ SCODE FAT_NEAR GetSect(
+ SECT sectStart,
+ ULONG ulOffset,
+ SECT *psectReturn);
+
+ SCODE FAT_NEAR GetESect(
+ SECT sectStart,
+ ULONG ulOffset,
+ SECT *psectReturn);
+
+ SCODE FAT_NEAR SetNext(SECT sectFirst, SECT sectNext);
+ SCODE FAT_NEAR GetFree(ULONG ulCount, SECT *sect);
+
+ SCODE FAT_NEAR GetLength(SECT sect, ULONG * pulRet);
+
+ SCODE FAT_NEAR SetChainLength(SECT,ULONG);
+
+ SCODE FAT_NEAR Init(
+ CMStream MSTREAM_NEAR *pmsParent,
+ FSINDEX cFatSect,
+ BOOL fConvert);
+
+
+ SCODE FAT_NEAR InitNew(CMStream MSTREAM_NEAR *pmsParent);
+ SCODE FAT_NEAR InitConvert(
+ CMStream MSTREAM_NEAR *pmsParent,
+ ULONG cbSize);
+
+
+ SCODE FAT_NEAR FindLast(SECT *psectRet);
+ SCODE FAT_NEAR FindMaxSect(SECT *psectRet);
+ inline SCODE FAT_NEAR GetMaxSect(SECT *psectRet);
+
+ SCODE FAT_NEAR Contig(
+ SSegment STACKBASED *aseg,
+ SECT sect,
+ ULONG ulLength);
+
+ inline SCODE FAT_NEAR Flush(VOID);
+
+ inline void FAT_NEAR SetParent(CMStream MSTREAM_NEAR *pms);
+
+
+private:
+
+ CFatVector _fv;
+ CMStream MSTREAM_NEAR * _pmsParent;
+ const SID _sid;
+
+
+ const USHORT _uFatShift;
+ const USHORT _uFatMask;
+
+ FSINDEX _cfsTable;
+ ULONG _ulFreeSects;
+
+
+ SECT _sectFirstFree;
+
+ SECT _sectMax;
+
+ SCODE FAT_NEAR CountFree(ULONG * ulRet);
+ SCODE FAT_NEAR Resize(ULONG);
+ SCODE FAT_NEAR Extend(SECT,ULONG);
+
+ inline VOID FAT_NEAR SectToPair(
+ SECT sect,
+ FSINDEX *pipfs,
+ FSOFFSET *pisect) const;
+
+ inline SECT FAT_NEAR PairToSect(FSINDEX ipfs, FSOFFSET isect) const;
+
+ friend class CDIFat;
+};
+
+
+
+
+inline VOID FAT_NEAR CFat::SectToPair(SECT sect,FSINDEX *pipfs,FSOFFSET *pisect) const
+{
+ *pipfs = (FSINDEX)(sect >> _uFatShift);
+ *pisect = (FSOFFSET)(sect & _uFatMask);
+}
+
+inline SECT FAT_NEAR CFat::PairToSect(FSINDEX ipfs, FSOFFSET isect) const
+{
+ return (ipfs << _uFatShift) + isect;
+}
+
+inline SCODE FAT_NEAR CFat::GetMaxSect(SECT *psectRet)
+{
+ SCODE sc;
+ msfChk(FindMaxSect(&_sectMax));
+ *psectRet = _sectMax;
+ Err:
+ return sc;
+}
+
+
+
+
+
+inline void FAT_NEAR CFat::SetParent(CMStream MSTREAM_NEAR *pms)
+{
+ _pmsParent = pms;
+ _fv.SetParent(pms);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::Flush, public
+//
+// Synposis: Write all modified FatSects out to stream
+//
+// Effects: Resets all dirty bit fields on FatSects
+//
+// Arguments: Void
+//
+// Returns: S_OK if call completed OK.
+// Error code of parent write otherwise.
+//
+// Algorithm: Linearly scan through FatSects, writing any sector
+// that has the dirty bit set. Reset all dirty bits.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+inline SCODE FAT_NEAR CFat::Flush(VOID)
+{
+ return _fv.Flush();
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CFat::Allocate, public
+//
+// Synposis: Allocates a chain within a FAT
+//
+// Effects: Modifies a single sector within the fat. Causes a
+// one sector stream write.
+//
+// Arguments: [ulSize] -- Number of sectors to allocate in chain
+//
+// Returns: Sector ID of first sector in chain
+//
+// Algorithm: Use repetitive calls to GetFree to construct a new chain
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+inline SCODE FAT_NEAR CFat::Allocate(ULONG ulSize, SECT * psectFirst)
+{
+ return GetFree(ulSize, psectFirst);
+}
+
+#endif //__FAT_HXX__
diff --git a/private/ole32/stg/ref/h/funcs.hxx b/private/ole32/stg/ref/h/funcs.hxx
new file mode 100644
index 000000000..390b583c5
--- /dev/null
+++ b/private/ole32/stg/ref/h/funcs.hxx
@@ -0,0 +1,73 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: funcs.hxx
+//
+// Contents: Header for funcs.cxx
+//
+//---------------------------------------------------------------
+
+#ifndef __FUNCS_HXX__
+#define __FUNCS_HXX__
+
+#include <dfmsp.hxx>
+
+class PSStream;
+
+SCODE VerifyPerms(DWORD grfMode);
+WCHAR * _CRTAPI1 wcsdup(WCHAR const *pwcs);
+SCODE DeleteIStorageContents(IStorage *pstg);
+SCODE ValidateSNB(SNBW snb);
+SCODE CopySStreamToSStream(PSStream *pstFrom, PSStream *pstTo);
+SCODE NameInSNB(CDfName const *dfn, SNBW snb);
+
+
+// For non-Unicode builds, we verify strings before converting them
+// to wide character strings, so there's no need to recheck them.
+
+# define CheckName(pwcsName) S_OK
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: VerifyStatFlag
+//
+// Synopsis: verify Stat flag
+//
+// Arguments: [grfStatFlag] - stat flag
+//
+// Returns: S_OK or STG_E_INVALIDFLAG
+//
+//--------------------------------------------------------------------------
+
+inline SCODE VerifyStatFlag(DWORD grfStatFlag)
+{
+ SCODE sc = S_OK;
+ if ((grfStatFlag & ~STATFLAG_NONAME) != 0)
+ sc = STG_E_INVALIDFLAG;
+ return(sc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: VerifyMoveFlags
+//
+// Synopsis: verify Move flag
+//
+// Arguments: [grfMoveFlag] - stat flag
+//
+// Returns: S_OK or STG_E_INVALIDFLAG
+//
+//--------------------------------------------------------------------------
+
+inline SCODE VerifyMoveFlags(DWORD grfMoveFlag)
+{
+ SCODE sc = S_OK;
+ if ((grfMoveFlag & ~STGMOVE_COPY) != 0)
+ sc = STG_E_INVALIDFLAG;
+ return(sc);
+}
+
+#endif
diff --git a/private/ole32/stg/ref/h/handle.hxx b/private/ole32/stg/ref/h/handle.hxx
new file mode 100644
index 000000000..8c97a28c5
--- /dev/null
+++ b/private/ole32/stg/ref/h/handle.hxx
@@ -0,0 +1,402 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992
+//
+// File: handle.hxx
+//
+// Contents: Defines CHandle
+//
+// Classes: CHandle
+// CStgHandle
+// CStmHandle
+//
+//---------------------------------------------------------------
+
+#ifndef __HANDLE_HXX__
+#define __HANDLE_HXX__
+
+#include <msf.hxx>
+#include <msffunc.hxx>
+
+//+--------------------------------------------------------------
+//
+// Class: CHandle (h)
+//
+// Purpose: An opaque handle to a directory entry-based object
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+class CStgHandle;
+class CStmHandle;
+
+class CHandle
+{
+public:
+ inline CHandle(void);
+
+ inline void Init(CMStream MSTREAM_NEAR *pms,
+ SID sid);
+
+ inline BOOL IsRoot(void) const;
+ inline BOOL IsValid(void) const;
+
+ inline SCODE GetTime(WHICHTIME wt, TIME_T *ptm);
+ inline SCODE SetTime(WHICHTIME wt, TIME_T tm);
+
+ inline SCODE DestroyEntry(CDfName const *pdfn);
+
+
+ inline CMStream MSTREAM_NEAR *GetMS(void) const;
+ inline SID GetSid(void) const;
+
+private:
+ friend class CStgHandle;
+ friend class CStmHandle;
+
+ CMStream MSTREAM_NEAR *_pms;
+ SID _sid;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::CHandle, public
+//
+// Synopsis: NULL constructor
+//
+//---------------------------------------------------------------
+
+inline CHandle::CHandle(void)
+{
+ _pms = NULL;
+ _sid = NOSTREAM;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::Init, public
+//
+// Synopsis: Sets internal data members
+//
+// Arguments: [pms] - Multistream
+// [sid] - SID
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+inline void CHandle::Init(CMStream MSTREAM_NEAR *pms,
+ SID sid)
+{
+ _pms = pms;
+ _sid = sid;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::IsRoot, public
+//
+// Synopsis: Whether this is a root handle or not
+//
+//---------------------------------------------------------------
+
+inline BOOL CHandle::IsRoot(void) const
+{
+ return _sid == SIDROOT;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::IsValid, public
+//
+// Synopsis: Whether this handle has been initialized
+//
+//---------------------------------------------------------------
+
+inline BOOL CHandle::IsValid(void) const
+{
+ return _pms != NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::GetTime, public
+//
+// Synopsis: Returns the time
+//
+//---------------------------------------------------------------
+
+inline SCODE CHandle::GetTime(WHICHTIME wt, TIME_T *ptm)
+{
+ return _pms->GetTime(_sid, wt, ptm);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::SetTime, public
+//
+// Synopsis: Sets the time
+//
+//---------------------------------------------------------------
+
+inline SCODE CHandle::SetTime(WHICHTIME wt, TIME_T tm)
+{
+ return _pms->SetTime(_sid, wt, tm);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::DestroyEntry, public
+//
+// Synopsis: Destroys this entry
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+inline SCODE CHandle::DestroyEntry(CDfName const *pdfn)
+{
+ return _pms->DestroyEntry(_sid, pdfn);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::GetMS, public
+//
+// Synopsis: Returns the multistream
+//
+//---------------------------------------------------------------
+
+inline CMStream MSTREAM_NEAR *CHandle::GetMS(void) const
+{
+ return _pms;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CHandle::GetSid, public
+//
+// Synopsis: Returns the sid
+//
+//---------------------------------------------------------------
+
+inline SID CHandle::GetSid(void) const
+{
+ return _sid;
+}
+
+//+--------------------------------------------------------------
+//
+// Class: CStgHandle, (stgh)
+//
+// Purpose: An opaque handle for Multistream directories
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+class CMSFIterator;
+
+class CStgHandle : public CHandle
+{
+public:
+ inline SCODE CreateEntry(CDfName const *pdfnName,
+ MSENTRYFLAGS const mefFlags,
+ CHandle *ph);
+ inline SCODE GetEntry(CDfName const *pdfnName,
+ MSENTRYFLAGS const mefFlags,
+ CHandle *ph);
+ inline SCODE RenameEntry(CDfName const *pdfnName,
+ CDfName const *pdfnNewName);
+ inline SCODE IsEntry(CDfName const *pdfnName,
+ SEntryBuffer *peb);
+ inline SCODE GetIterator(CMSFIterator **ppi);
+ inline SCODE GetClass(CLSID *pclsid);
+ inline SCODE SetClass(REFCLSID clsid);
+ inline SCODE GetStateBits(DWORD *pgrfStateBits);
+ inline SCODE SetStateBits(DWORD grfStateBits, DWORD grfMask);
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CStgHandle::CreateEntry, public
+//
+// Synopsis: Creates an entry
+//
+//---------------------------------------------------------------
+
+
+inline SCODE CStgHandle::CreateEntry(CDfName const *pdfnName,
+ MSENTRYFLAGS const mefFlags,
+ CHandle *ph)
+{
+ ph->_pms = _pms;
+ return _pms->CreateEntry(_sid, pdfnName, mefFlags, &ph->_sid);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStgHandle::GetEntry, public
+//
+// Synopsis: Gets an entry
+//
+//---------------------------------------------------------------
+
+
+inline SCODE CStgHandle::GetEntry(CDfName const *pdfnName,
+ MSENTRYFLAGS const mefFlags,
+ CHandle *ph)
+{
+ SCODE sc;
+ SEntryBuffer eb;
+
+ ph->_pms = _pms;
+
+ sc = _pms->IsEntry(_sid, pdfnName, &eb);
+ if (SUCCEEDED(sc))
+ {
+ msfAssert(eb.sid != NOSTREAM);
+ // entry exists but it may be the wrong type
+
+ if ((mefFlags != MEF_ANY) && (mefFlags != eb.dwType))
+ {
+ sc = STG_E_FILENOTFOUND;
+ }
+ else
+ ph->_sid = eb.sid;
+ }
+ return(sc);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStgHandle::RenameEntry, public
+//
+// Synopsis: Renames an entry
+//
+//---------------------------------------------------------------
+
+
+inline SCODE CStgHandle::RenameEntry(CDfName const *pdfnName,
+ CDfName const *pdfnNewName)
+{
+ return _pms->RenameEntry(_sid, pdfnName, pdfnNewName);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStgHandle::IsEntry, public
+//
+// Synopsis: Gets entry info and checks for existence
+//
+//---------------------------------------------------------------
+
+inline SCODE CStgHandle::IsEntry(CDfName const *pdfnName,
+ SEntryBuffer *peb)
+{
+ return _pms->IsEntry(_sid, pdfnName, peb);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CStgHandle::GetIterator, public
+//
+// Synopsis: Gets an iterator
+//
+//---------------------------------------------------------------
+
+inline SCODE CStgHandle::GetIterator(CMSFIterator **ppi)
+{
+ return _pms->GetIterator(_sid, ppi);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStgHandle::GetClass, public
+//
+// Synopsis: Gets the class ID
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CStgHandle::GetClass(CLSID *pclsid)
+{
+ return _pms->GetClass(_sid, pclsid);
+
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStgHandle::SetClass, public
+//
+// Synopsis: Sets the class ID
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CStgHandle::SetClass(REFCLSID clsid)
+{
+ return _pms->SetClass(_sid, clsid);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStgHandle::GetStateBits, public
+//
+// Synopsis: Gets state bits
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CStgHandle::GetStateBits(DWORD *pgrfStateBits)
+{
+ return _pms->GetStateBits(_sid, pgrfStateBits);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStgHandle::SetStateBits, public
+//
+// Synopsis: Sets state bits
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CStgHandle::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ return _pms->SetStateBits(_sid, grfStateBits, grfMask);
+}
+
+//+--------------------------------------------------------------
+//
+// Class: CStmHandle, (stmh)
+//
+// Purpose: An opaque handle for Multistream streams
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+class CDirectStream;
+
+class CStmHandle : public CHandle
+{
+public:
+ inline SCODE GetSize(ULONG *pcbSize);
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CStmHandle::GetSize, public
+//
+// Synopsis: Gets the stream size
+//
+//---------------------------------------------------------------
+
+inline SCODE CStmHandle::GetSize(ULONG *pcbSize)
+{
+ return _pms->GetEntrySize(_sid, pcbSize);
+}
+
+#endif // #ifndef __HANDLE_HXX__
+
diff --git a/private/ole32/stg/ref/h/header.hxx b/private/ole32/stg/ref/h/header.hxx
new file mode 100644
index 000000000..a64a934cb
--- /dev/null
+++ b/private/ole32/stg/ref/h/header.hxx
@@ -0,0 +1,276 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: header.hxx
+//
+// Contents: MSF header class
+//
+// Classes: CMSFHeader
+//
+//--------------------------------------------------------------------------
+
+#ifndef __HEADER_HXX__
+#define __HEADER_HXX__
+
+#include <msf.hxx>
+#include <storagep.h>
+
+#define HDR_NOFORCE 0x0000
+#define HDR_FORCE 0x0001
+#define HDR_ALL 0x0002
+
+struct SPreHeader : protected SStorageFile
+{
+protected:
+ USHORT _uMinorVersion;
+ USHORT _uDllVersion;
+ USHORT _uByteOrder;
+
+ USHORT _uSectorShift;
+ USHORT _uMiniSectorShift;
+
+ USHORT _usReserved;
+ ULONG _ulReserved1;
+ ULONG _ulReserved2;
+
+ FSINDEX _csectFat;
+ SECT _sectDirStart;
+
+ DFSIGNATURE _signature;
+
+ ULONG _ulMiniSectorCutoff;
+
+ SECT _sectMiniFatStart;
+ FSINDEX _csectMiniFat;
+
+ SECT _sectDifStart;
+ FSINDEX _csectDif;
+};
+
+
+const USHORT CSECTFATREAL = (HEADERSIZE - sizeof(SPreHeader)) / sizeof(SECT);
+
+const USHORT CSECTFAT = CSECTFATREAL;
+
+class CMSFHeader: private SPreHeader
+{
+ public:
+
+ CMSFHeader(USHORT uSectorShift);
+
+ SCODE Validate(VOID) const;
+
+ inline USHORT GetMinorVersion(VOID) const;
+ inline USHORT GetDllVersion(VOID) const;
+
+ inline SCODE SetFatLength(const FSINDEX cFatSect);
+ inline FSINDEX GetFatLength(VOID) const;
+
+ inline SCODE SetMiniFatLength(const FSINDEX cFatSect);
+ inline FSINDEX GetMiniFatLength(VOID) const;
+
+ inline SCODE SetDirStart(const SECT sect);
+ inline SECT GetDirStart(VOID) const;
+
+ inline SCODE SetFatStart(const SECT sect);
+ inline SECT GetFatStart(VOID) const;
+
+ inline SCODE SetMiniFatStart(const SECT sect);
+ inline SECT GetMiniFatStart(VOID) const;
+
+ inline SCODE SetDifStart(const SECT sect);
+ inline SECT GetDifStart(VOID) const;
+
+ inline SCODE SetDifLength(const FSINDEX cFatSect);
+ inline FSINDEX GetDifLength(VOID) const;
+
+ inline SECT GetFatSect(const FSINDEX oSect) const;
+ inline SCODE SetFatSect(const FSINDEX oSect, const SECT sect);
+
+ inline USHORT GetSectorShift(VOID) const;
+ inline USHORT GetMiniSectorShift(VOID) const;
+
+ inline ULONG GetMiniSectorCutoff(VOID) const;
+
+ inline DFSIGNATURE GetCommitSig(VOID) const;
+ inline void SetCommitSig(const DFSIGNATURE sig);
+
+ private:
+ SECT _sectFat[CSECTFAT];
+
+ SCODE SetSig(const BYTE *pbSig);
+};
+
+
+inline SCODE CMSFHeader::SetFatLength(const FSINDEX cFatSect)
+{
+ msfDebugOut((DEB_TRACE,"In CMSFHeader::SetFatLength(%lu)\n",cFatSect));
+ _csectFat = cFatSect;
+ msfDebugOut((DEB_TRACE,"Out CMSFHeader::SetFatLength()\n"));
+ return S_OK;
+}
+
+inline FSINDEX CMSFHeader::GetFatLength(VOID) const
+{
+ return _csectFat;
+}
+
+inline SCODE CMSFHeader::SetMiniFatLength(const FSINDEX cFatSect)
+{
+ msfDebugOut((DEB_TRACE,"In CMSFHeader::SetMiniFatLength(%lu)\n",cFatSect));
+ _csectMiniFat = cFatSect;
+ msfDebugOut((DEB_TRACE,"Out CMSFHeader::SetMiniFatLength()\n"));
+ return S_OK;
+}
+
+inline FSINDEX CMSFHeader::GetMiniFatLength(VOID) const
+{
+ return(_csectMiniFat);
+}
+
+inline SCODE CMSFHeader::SetDirStart(const SECT sectNew)
+{
+ _sectDirStart = sectNew;
+ return S_OK;
+}
+
+inline SECT CMSFHeader::GetDirStart(VOID) const
+{
+ return _sectDirStart;
+}
+
+inline SCODE CMSFHeader::SetFatStart(const SECT sectNew)
+{
+ _sectFat[0] = sectNew;
+ return S_OK;
+}
+
+inline SECT CMSFHeader::GetFatStart(VOID) const
+{
+ return _sectFat[0];
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMSFHeader::SetMiniFatStart
+//
+// Synopsis: Sets minifat's first sector's index
+//
+// Arguments: [sectNew] -- sector index
+//
+// Returns: S_OK (necessary?)
+//
+// Modifies: _sectMiniFatStart
+//
+//--------------------------------------------------------------------------
+
+inline SCODE CMSFHeader::SetMiniFatStart(const SECT sectNew)
+{
+ _sectMiniFatStart = sectNew;
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMSFHeader::GetMiniFatStart
+//
+// Synopsis: Gets minifat's first sector's index
+//
+// Returns: minifat's first sector's index
+//
+//--------------------------------------------------------------------------
+
+inline SECT CMSFHeader::GetMiniFatStart(VOID) const
+{
+ return(_sectMiniFatStart);
+}
+
+inline SCODE CMSFHeader::SetDifStart(const SECT sectNew)
+{
+ _sectDifStart = sectNew;
+ return S_OK;
+}
+
+inline SECT CMSFHeader::GetDifStart(VOID) const
+{
+ return _sectDifStart;
+}
+
+inline SECT CMSFHeader::GetFatSect(const FSINDEX oSect) const
+{
+ msfAssert(oSect < CSECTFAT);
+ return _sectFat[oSect];
+}
+
+inline SCODE CMSFHeader::SetFatSect(const FSINDEX oSect, const SECT sect)
+{
+ msfAssert(oSect < CSECTFAT);
+ _sectFat[oSect] = sect;
+ return S_OK;
+}
+
+inline SCODE CMSFHeader::SetDifLength(const FSINDEX cFatSect)
+{
+ _csectDif = cFatSect;
+ return S_OK;
+}
+
+
+inline FSINDEX CMSFHeader::GetDifLength(VOID) const
+{
+ return _csectDif;
+}
+
+
+inline USHORT CMSFHeader::GetSectorShift(VOID) const
+{
+ return _uSectorShift;
+}
+
+
+inline DFSIGNATURE CMSFHeader::GetCommitSig(VOID) const
+{
+ return _signature;
+}
+
+inline void CMSFHeader::SetCommitSig(const DFSIGNATURE sig)
+{
+ _signature = sig;
+}
+
+inline USHORT CMSFHeader::GetMiniSectorShift(VOID) const
+{
+ return _uMiniSectorShift;
+}
+
+inline ULONG CMSFHeader::GetMiniSectorCutoff(VOID) const
+{
+ return _ulMiniSectorCutoff;
+}
+
+inline USHORT CMSFHeader::GetMinorVersion(VOID) const
+{
+ return _uMinorVersion;
+}
+
+inline USHORT CMSFHeader::GetDllVersion(VOID) const
+{
+ return _uDllVersion;
+}
+
+
+const ULONG OACCESS = 0xFFFFFF00;
+const ULONG OREADLOCK = OACCESS + 1;
+const ULONG CREADLOCKS = 16;
+const ULONG OUPDATE = OREADLOCK + CREADLOCKS + 1;
+const ULONG OOPENLOCK = OUPDATE + 1;
+const ULONG COPENLOCKS = 20;
+const ULONG OOPENREADLOCK = OOPENLOCK;
+const ULONG OOPENWRITELOCK = OOPENLOCK + COPENLOCKS;
+const ULONG OOPENDENYREADLOCK = OOPENWRITELOCK + COPENLOCKS;
+const ULONG OOPENDENYWRITELOCK = OOPENDENYREADLOCK + COPENLOCKS;
+
+
+#endif //__HEADER_HXX__
diff --git a/private/ole32/stg/ref/h/lock.hxx b/private/ole32/stg/ref/h/lock.hxx
new file mode 100644
index 000000000..89de72f4e
--- /dev/null
+++ b/private/ole32/stg/ref/h/lock.hxx
@@ -0,0 +1,24 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: lock.hxx
+//
+// Contents: Function definitions for remote exclusion functions
+//
+//--------------------------------------------------------------------------
+
+#ifndef __LOCK_HXX__
+#define __LOCK_HXX__
+
+#define NOLOCK 0x0
+
+SCODE GetAccess(ILockBytes *plst, DFLAGS df, ULONG *poReturn);
+void ReleaseAccess(ILockBytes *plst, DFLAGS df, ULONG offset);
+SCODE GetOpen(ILockBytes *plst, DFLAGS df, BOOL fCheck, ULONG *puReturn);
+void ReleaseOpen(ILockBytes *plst, DFLAGS df, ULONG offset);
+
+#define REMOTE
+
+#endif // #ifndef __LOCK_HXX__
diff --git a/private/ole32/stg/ref/h/msf.hxx b/private/ole32/stg/ref/h/msf.hxx
new file mode 100644
index 000000000..04a430c31
--- /dev/null
+++ b/private/ole32/stg/ref/h/msf.hxx
@@ -0,0 +1,512 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: msf.hxx
+//
+// Contents: Header for MSF for external use
+//
+// Classes: CMStream - Main multi-stream object
+//
+//--------------------------------------------------------------------------
+
+#ifndef __MSF_HXX__
+#define __MSF_HXX__
+
+#include <ref.hxx>
+#include <dfmsp.hxx>
+#include <error.hxx>
+
+#define SECURE
+
+#define msfErr(l, e) ErrJmp(msf, l, e, sc)
+#define msfChkTo(l, e) if (FAILED(sc = (e))) msfErr(l, sc) else 1
+#define msfHChkTo(l, e) if (FAILED(sc = GetScode(e))) msfErr(l, sc) else 1
+#define msfChk(e) msfChkTo(Err, e)
+#define msfHChk(e) msfHChkTo(Err, e)
+#define msfMemTo(l, e) if ((e) == NULL) msfErr(l, STG_E_INSUFFICIENTMEMORY) else 1
+#define msfMem(e) msfMemTo(Err, e)
+
+#if DEVL == 1
+
+DECLARE_DEBUG(msf);
+
+#endif
+
+#if DBG == 1
+
+#define msfDebugOut(x) msfInlineDebugOut x
+#include <assert.h>
+#define msfAssert(e) assert(e)
+#define msfVerify(e) assert(e)
+
+#else
+
+#define msfDebugOut(x)
+#define msfAssert(e)
+#define msfVerify(e) (e)
+
+#endif
+
+
+// MSF entry flags type
+typedef DWORD MSENTRYFLAGS;
+
+// MEF_ANY refers to all entries regardless of type
+const MSENTRYFLAGS MEF_ANY = 255;
+
+//CWCSTREAMNAME is the maximum length (in wide characters) of
+// a stream name.
+const USHORT CWCSTREAMNAME = 32;
+
+//OFFSET and SECT are used to determine positions within
+//a file.
+typedef SHORT OFFSET;
+typedef ULONG SECT;
+
+#define MAXINDEXTYPE ULONG
+
+//FSINDEX and FSOFFSET are used to determine the position of a sector
+//within the Fat.
+typedef ULONG FSINDEX;
+typedef USHORT FSOFFSET;
+
+// DIRINDEX and DIROFFSET and used to index directory tables
+typedef ULONG DIRINDEX;
+typedef USHORT DIROFFSET;
+
+//Size of a mini sector in bytes.
+const USHORT MINISECTORSHIFT = 6;
+const USHORT MINISECTORSIZE = 1 << MINISECTORSHIFT; //64
+
+//Maximum size of a ministream.
+const USHORT MINISTREAMSIZE=4096;
+
+//Size of a single sector in bytes.
+const USHORT SECTORSHIFT = 9;
+const USHORT SECTORSIZE = 1 << SECTORSHIFT; //512
+
+//Size of header.
+const USHORT HEADERSIZE = SECTORSIZE;
+
+//Size of single DirEntry
+const USHORT DIRENTRYSIZE = SECTORSIZE / 4;
+
+
+const ULONG MAX_ULONG = 0xFFFFFFFF;
+
+
+//
+// Predefined Sector Indices
+//
+
+const SECT MAXREGSECT = 0xFFFFFFFB;
+const SECT DIFSECT=0xFFFFFFFC;
+const SECT FATSECT=0xFFFFFFFD;
+const SECT ENDOFCHAIN=0xFFFFFFFE;
+const SECT FREESECT=0xFFFFFFFF;
+
+
+//Start of Fat chain
+const SECT SECTFAT = 0;
+
+//Start of directory chain
+const SECT SECTDIR = 1;
+
+//
+// Predefined Stream ID's
+//
+
+//Return code for Directory
+//Used to signal a 'Stream Not Found' condition
+const SID NOSTREAM=0xFFFFFFFF;
+
+//Stream ID of FAT chain
+const SID SIDFAT=0xFFFFFFFE;
+
+//Stream ID of Directory chain
+const SID SIDDIR=0xFFFFFFFD;
+
+//SID for root level object
+const SID SIDROOT = 0;
+
+//SID of MiniFat
+const SID SIDMINIFAT = 0xFFFFFFFC;
+
+//SID of Double-indirect Fat
+const SID SIDDIF = 0xFFFFFFFB;
+
+//Stream ID for MiniStream chain
+const SID SIDMINISTREAM = SIDROOT;
+
+//SID of the largest regular (non-control) SID
+const SID MAXREGSID = 0xFFFFFFFA;
+
+
+class MSTREAM_NEAR CMStream;
+
+class PSStream;
+class CDirectStream;
+class CMSFIterator;
+class CMSFPageTable;
+
+class CStreamCache;
+
+#define FLUSH_ILB TRUE
+
+#include <header.hxx>
+#include <fat.hxx>
+#include <dir.hxx>
+#include <difat.hxx>
+
+
+
+//+----------------------------------------------------------------------
+//
+// Class: CMStream (ms)
+//
+// Purpose: Main interface to multi-streams
+//
+// Interface: See below
+//
+// Notes:
+//
+//-----------------------------------------------------------------------
+
+class MSTREAM_NEAR CMStream
+{
+public:
+
+ MSTREAM_NEAR CMStream(
+ ILockBytes **pplstParent,
+ USHORT uSectorShift);
+
+
+ MSTREAM_NEAR ~CMStream();
+
+ SCODE MSTREAM_NEAR Init(VOID);
+
+
+ SCODE InitNew(VOID);
+
+ SCODE InitConvert(VOID);
+
+
+ void Empty(void);
+
+ inline SCODE MSTREAM_NEAR CreateEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ MSENTRYFLAGS const mefFlags,
+ SID *psid);
+
+ // No implementation, currently unused, placeholder
+ void MSTREAM_NEAR ReleaseEntry(SID const sid);
+
+ inline SCODE MSTREAM_NEAR DestroyEntry(
+ SID const sidParent,
+ CDfName const *pdfn);
+
+ inline SCODE MSTREAM_NEAR KillStream(SECT sectStart, ULONG ulSize);
+
+ inline SCODE MSTREAM_NEAR RenameEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ CDfName const *pdfnNew);
+
+ inline SCODE MSTREAM_NEAR IsEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ SEntryBuffer *peb);
+
+ inline SCODE MSTREAM_NEAR StatEntry(
+ SID const sid,
+ STATSTG *pstatstg);
+
+ inline SCODE MSTREAM_NEAR GetTime(
+ SID const sid,
+ WHICHTIME const tt,
+ TIME_T *pnt);
+
+ inline SCODE MSTREAM_NEAR SetTime(
+ SID const sid,
+ WHICHTIME const tt,
+ TIME_T nt);
+
+ inline SCODE MSTREAM_NEAR GetClass(SID const sid,
+ CLSID *pclsid);
+
+ inline SCODE MSTREAM_NEAR SetClass(SID const sid,
+ REFCLSID clsid);
+
+ inline SCODE MSTREAM_NEAR GetStateBits(SID const sid,
+ DWORD *pgrfStateBits);
+
+ inline SCODE MSTREAM_NEAR SetStateBits(SID const sid,
+ DWORD grfStateBits,
+ DWORD grfMask);
+
+
+ inline SCODE MSTREAM_NEAR GetEntrySize(
+ SID const sid,
+ ULONG *pcbSize);
+
+ SCODE MSTREAM_NEAR GetIterator(
+ SID const sidParent,
+ CMSFIterator **pit);
+
+
+ inline SCODE MSTREAM_NEAR SetSize(VOID);
+ inline SCODE MSTREAM_NEAR SetMiniSize(VOID);
+
+
+ SCODE MSTREAM_NEAR MWrite(
+ SID sid,
+ BOOL fIsMiniStream,
+ ULONG ulOffset,
+ VOID const HUGEP *pBuffer,
+ ULONG ulCount,
+ CStreamCache *pstmc,
+ ULONG *pulRetVal);
+
+
+ SCODE MSTREAM_NEAR GetName(SID const sid, CDfName *pdfn);
+
+ inline CMSFHeader * MSTREAM_NEAR GetHeader(VOID) const;
+ inline CFat * MSTREAM_NEAR GetFat(VOID) const;
+ inline CFat * MSTREAM_NEAR GetMiniFat(VOID) const;
+ inline CDIFat * MSTREAM_NEAR GetDIFat(VOID) const;
+ inline CDirectory * MSTREAM_NEAR GetDir(VOID) const;
+ inline CMSFPageTable * MSTREAM_NEAR GetPageTable(VOID) const;
+
+ inline USHORT GetSectorSize(VOID) const;
+ inline USHORT GetSectorShift(VOID) const;
+ inline USHORT GetSectorMask(VOID) const;
+
+ SCODE MSTREAM_NEAR Flush(BOOL fFlushILB);
+
+ SCODE MSTREAM_NEAR FlushHeader(USHORT uForce);
+
+
+ inline CDirectStream * MSTREAM_NEAR GetMiniStream(VOID) const;
+ inline ILockBytes * MSTREAM_NEAR GetILB(VOID) const;
+
+ inline SCODE GetSect(SID sid, SECT sect, SECT *psect);
+ inline SCODE GetESect(SID sid, SECT sect, SECT *psect);
+
+ SCODE SecureSect(
+ const SECT sect,
+ const ULONG ulSize,
+ const BOOL fIsMini);
+
+private:
+
+ ILockBytes **_pplstParent;
+ CMSFHeader _hdr;
+
+ CMSFPageTable *_pmpt;
+
+ CDirectory _dir;
+ CFat _fat;
+ CDIFat _fatDif;
+ CFat _fatMini;
+
+ CDirectStream * _pdsministream;
+
+
+
+ USHORT _uSectorSize;
+ USHORT _uSectorShift;
+ USHORT _uSectorMask;
+
+
+ SCODE MSTREAM_NEAR InitCommon(VOID);
+
+ SECT MSTREAM_NEAR GetStart(SID sid) const;
+
+
+ SCODE MSTREAM_NEAR ConvertILB(SECT sectMax);
+
+ friend SCODE DllGetScratchMultiStream(
+ CMStream MSTREAM_NEAR **ppms,
+ ILockBytes **pplstStream,
+ CMStream MSTREAM_NEAR *pmsMaster);
+};
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetSectorSize, public
+//
+// Synopsis: Returns the current sector size
+//
+//--------------------------------------------------------------------------
+
+inline USHORT CMStream::GetSectorSize(VOID) const
+{
+ return _uSectorSize;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetSectorShift, public
+//
+// Synopsis: Returns the current shift for sector math
+//
+//--------------------------------------------------------------------------
+
+inline USHORT CMStream::GetSectorShift(VOID) const
+{
+ return _uSectorShift;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetSectorMask, public
+//
+// Synopsis: Returns the current mask for sector math
+//
+//--------------------------------------------------------------------------
+
+inline USHORT CMStream::GetSectorMask(VOID) const
+{
+ return _uSectorMask;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetHeader, public
+//
+// Synopsis: Returns a pointer to the current header.
+//
+//--------------------------------------------------------------------------
+
+inline CMSFHeader * MSTREAM_NEAR CMStream::GetHeader(VOID) const
+{
+ return (CMSFHeader *)(&_hdr);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetFat, public
+//
+// Synopsis: Returns a pointer to the current Fat
+//
+//--------------------------------------------------------------------------
+
+inline CFat * MSTREAM_NEAR CMStream::GetFat(VOID) const
+{
+ return (CFat *)&_fat;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::GetMiniFat
+//
+// Synopsis: Returns a pointer to the current minifat
+//
+//--------------------------------------------------------------------------
+
+inline CFat * MSTREAM_NEAR CMStream::GetMiniFat(VOID) const
+{
+ return (CFat *)&_fatMini;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetDIFat, public
+//
+// Synopsis: Returns pointer to the current Double Indirect Fat
+//
+//--------------------------------------------------------------------------
+
+inline CDIFat * MSTREAM_NEAR CMStream::GetDIFat(VOID) const
+{
+ return (CDIFat *)&_fatDif;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::GetDir
+//
+// Synopsis: Returns a pointer to the current directory
+//
+//--------------------------------------------------------------------------
+
+inline CDirectory * MSTREAM_NEAR CMStream::GetDir(VOID) const
+{
+ return (CDirectory *)&_dir;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::GetMiniStream
+//
+// Synopsis: Returns pointer to the current ministream
+//
+//--------------------------------------------------------------------------
+
+inline CDirectStream * MSTREAM_NEAR CMStream::GetMiniStream(VOID) const
+{
+ return(_pdsministream);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::GetILB
+//
+// Synopsis: Returns a pointer to the current parent ILockBytes
+//
+//--------------------------------------------------------------------------
+
+inline ILockBytes * MSTREAM_NEAR CMStream::GetILB(VOID) const
+{
+ return(*_pplstParent);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::GetPageTable
+//
+// Synopsis: Returns a pointer to the current page table
+//
+//--------------------------------------------------------------------------
+
+inline CMSFPageTable * MSTREAM_NEAR CMStream::GetPageTable(VOID) const
+{
+ return _pmpt;
+}
+
+
+extern SCODE DllMultiStreamFromStream(
+ CMStream MSTREAM_NEAR **ppms,
+ ILockBytes **pplstStream,
+ DWORD dwFlags);
+
+extern SCODE DllMultiStreamFromCorruptedStream(
+ CMStream MSTREAM_NEAR **ppms,
+ ILockBytes **pplstStream,
+ DWORD dwFlags);
+
+extern void DllReleaseMultiStream(CMStream MSTREAM_NEAR *pms);
+
+
+extern SCODE DllIsMultiStream(ILockBytes *plstStream);
+
+extern SCODE DllGetCommitSig(ILockBytes *plst, DFSIGNATURE *psig);
+
+extern SCODE DllSetCommitSig(ILockBytes *plst, DFSIGNATURE sig);
+
+#if DEVL == 1
+extern VOID SetInfoLevel(ULONG x);
+#endif
+
+#endif //__MSF_HXX__
diff --git a/private/ole32/stg/ref/h/msffunc.hxx b/private/ole32/stg/ref/h/msffunc.hxx
new file mode 100644
index 000000000..cb64ba4a1
--- /dev/null
+++ b/private/ole32/stg/ref/h/msffunc.hxx
@@ -0,0 +1,311 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: msffunc.hxx
+//
+// Contents: Multistream inline functions
+//
+// Classes: None.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __MSFFUNC_HXX__
+#define __MSFFUNC_HXX__
+
+#include <msf.hxx>
+#include <dir.hxx>
+#include <dirfunc.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::RenameEntry, public
+//
+// Synposis: Rename an entry.
+//
+// Arguments: [sidParent] - Parent SID
+// [pdfn] - Old name
+// [pdfnNew] -- New name
+//
+// Returns: S_OK otherwise
+//
+// Algorithm: Call through to CDirectory::RenameEntry
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+
+inline SCODE MSTREAM_NEAR CMStream::RenameEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ CDfName const *pdfnNew)
+{
+ return _dir.RenameEntry(sidParent, pdfn, pdfnNew);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::IsEntry, public
+//
+// Synposis: Determine if a given entry is present in a multistream
+//
+// Arguments: [sidParent] - Parent SID
+// [pdfn] -- Name of entry to be located
+// [peb] - Entry block to fill in
+//
+// Returns: S_OK if entry exists.
+// STG_E_FILENOTFOUND if it doesn't.
+//
+//---------------------------------------------------------------------------
+
+
+inline SCODE MSTREAM_NEAR CMStream::IsEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ SEntryBuffer *peb)
+{
+ return _dir.IsEntry(sidParent, pdfn, peb);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::CreateEntry, public
+//
+// Synposis: Allows creation of new entries
+//
+// Arguments: [sidParent] -- SID of parent entry
+// [pdfn] -- Name of new entry
+// [mefFlags] -- Flags to be set on new entry
+// [psid] -- Location for return SID
+//
+// Returns: S_OK if call completed OK.
+// STG_E_FILEALREADYEXISTS if stream already exists
+//
+//---------------------------------------------------------------------------
+
+
+inline SCODE MSTREAM_NEAR CMStream::CreateEntry(
+ SID const sidParent,
+ CDfName const *pdfn,
+ MSENTRYFLAGS const mefFlags,
+ SID *psid)
+{
+ return _dir.CreateEntry(sidParent, pdfn, mefFlags, psid);
+}
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::StatEntry
+//
+// Synopsis: For a given handle, fill in the Multistream specific
+// information of a STATSTG.
+//
+// Arguments: [sid] -- SID that information is requested on.
+// [pstatstg] -- STATSTG to fill in.
+//
+// Returns: S_OK
+//
+//--------------------------------------------------------------------------
+
+
+inline SCODE MSTREAM_NEAR CMStream::StatEntry(SID const sid, STATSTG *pstatstg)
+{
+ return _dir.StatEntry(sid, pstatstg);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetTime, public
+//
+// Synopsis: Get the time for a given handle
+//
+// Arguments: [sid] -- SID to retrieve time for
+// [tt] -- Timestamp requested (WT_CREATION, WT_MODIFICATION,
+// WT_ACCESS)
+// [pnt] -- Pointer to return location
+//
+// Returns: S_OK if call completed OK.
+//
+//--------------------------------------------------------------------------
+
+
+inline SCODE MSTREAM_NEAR CMStream::GetTime(SID const sid,
+ WHICHTIME const tt,
+ TIME_T *pnt)
+{
+ return _dir.GetTime(sid, tt, pnt);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::SetTime, public
+//
+// Synopsis: Set the time for a given handle
+//
+// Arguments: [sid] -- SID to retrieve time for
+// [tt] -- Timestamp requested (WT_CREATION, WT_MODIFICATION,
+// WT_ACCESS)
+// [nt] -- New timestamp
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Call through to directory
+//
+//--------------------------------------------------------------------------
+
+inline SCODE MSTREAM_NEAR CMStream::SetTime(SID const sid,
+ WHICHTIME const tt,
+ TIME_T nt)
+{
+ return _dir.SetTime(sid, tt, nt);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::GetClass, public
+//
+// Synopsis: Gets the class ID
+//
+// Arguments: [pclsid] - Class ID return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pclsid]
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CMStream::GetClass(SID const sid,
+ CLSID *pclsid)
+{
+ return _dir.GetClassId(sid, pclsid);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::SetClass, public
+//
+// Synopsis: Sets the class ID
+//
+// Arguments: [clsid] - Class ID
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CMStream::SetClass(SID const sid,
+ REFCLSID clsid)
+{
+ return _dir.SetClassId(sid, clsid);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::GetStateBits, public
+//
+// Synopsis: Gets state bits
+//
+// Arguments: [pgrfStateBits] - State bits return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pgrfStateBits]
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CMStream::GetStateBits(SID const sid,
+ DWORD *pgrfStateBits)
+{
+ return _dir.GetUserFlags(sid, pgrfStateBits);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::SetStateBits, public
+//
+// Synopsis: Sets state bits
+//
+// Arguments: [grfStateBits] - State bits
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CMStream::SetStateBits(SID const sid,
+ DWORD grfStateBits,
+ DWORD grfMask)
+{
+ return _dir.SetUserFlags(sid, grfStateBits, grfMask);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetEntrySize, public
+//
+// Synopsis: Return the size of an entry
+//
+// Arguments: [sid] - SID of entry
+// [pcbSize] -- Location for return of size
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Ask directory for size
+//
+//--------------------------------------------------------------------------
+
+inline SCODE MSTREAM_NEAR CMStream::GetEntrySize(SID const sid,
+ ULONG *pcbSize)
+{
+ return _dir.GetSize(sid, pcbSize);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::DestroyEntry
+//
+// Synposis: Delete a directory entry from a multi-stream.
+//
+// Effects: Modifies directory.
+//
+// Arguments: [sidParent] - Parent SID
+// [pdfn] - Name of entry
+//
+// Returns: S_OK if operation completed successfully.
+//
+// Algorithm: Set information on entry to default "free" case.
+// Return S_OK
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+
+inline SCODE MSTREAM_NEAR CMStream::DestroyEntry(SID const sidParent,
+ CDfName const *pdfn)
+{
+ SCODE sc;
+
+ msfDebugOut((DEB_TRACE,"In CMStream::DestroyEntry()\n"));
+
+ // Two cases:
+ // pdfn == NULL - destroy all children of sidParent
+ // pdfn != NULL - destroy the named child of sidParent
+
+ if (pdfn == NULL)
+ sc = _dir.DestroyAllChildren(sidParent);
+ else
+ sc = _dir.DestroyChild(sidParent, pdfn);
+
+ msfDebugOut((DEB_TRACE,"Leaving CMStream::DestroyEntry()\n"));
+
+ return sc;
+}
+
+
+#endif //__MSFFUNC_HXX__
diff --git a/private/ole32/stg/ref/h/msfiter.hxx b/private/ole32/stg/ref/h/msfiter.hxx
new file mode 100644
index 000000000..73511c542
--- /dev/null
+++ b/private/ole32/stg/ref/h/msfiter.hxx
@@ -0,0 +1,96 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: msfiter.hxx
+//
+// Contents: Definitions for iterator objects
+//
+// Classes: CMSFIterator - Main iterator class for MSF
+//
+// Functions: None.
+//
+//--------------------------------------------------------------------------
+
+#ifndef __MSFITER_HXX__
+#define __MSFITER_HXX__
+
+#include <msf.hxx>
+
+class CDirectory;
+
+//+-------------------------------------------------------------------------
+//
+// Class: CMSFIterator
+//
+// Purpose: Iterator object provided by multi-stream
+//
+// Interface: See below
+//
+//--------------------------------------------------------------------------
+
+class CMSFIterator
+{
+ public:
+ inline CMSFIterator(CDirectory *pdir, SID sidChild);
+ SCODE GetNext(STATSTGW *pstat);
+ SCODE BufferGetNext(SIterBuffer *pib);
+ inline SCODE Rewind(VOID);
+
+ inline void Release(VOID);
+
+ private:
+ CDirectory *_pdir;
+ SID _sidChildRoot;
+ CDfName _dfnCurrent;
+};
+
+inline CMSFIterator::CMSFIterator(CDirectory *pdir, SID sidChild)
+{
+ _pdir = pdir;
+ _sidChildRoot = sidChild;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMSFIterator::Rewind, public
+//
+// Synposis: Reset iterator to first position.
+//
+// Effects: Modifies _sidCurrent
+//
+// Arguments: Void.
+//
+// Returns: S_OK
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+inline SCODE CMSFIterator::Rewind(VOID)
+{
+ msfDebugOut((DEB_TRACE,"In CMSFIterator::Rewind()\n"));
+ _dfnCurrent.Set((WORD)0, (BYTE *)NULL);
+ msfDebugOut((DEB_TRACE,"Leaving CMSFIterator::Rewind()\n"));
+ return S_OK;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMSFIterator::Release, public
+//
+// Synopsis: Release this MSFIterator instance
+//
+// Arguments: None.
+//
+// Returns: Void.
+//
+//--------------------------------------------------------------------------
+
+inline void CMSFIterator::Release(VOID)
+{
+ delete this;
+}
+
+#endif //__MSFITER_HXX__
diff --git a/private/ole32/stg/ref/h/ole.hxx b/private/ole32/stg/ref/h/ole.hxx
new file mode 100644
index 000000000..6d3e1a0be
--- /dev/null
+++ b/private/ole32/stg/ref/h/ole.hxx
@@ -0,0 +1,57 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: ole.hxx
+//
+// Contents: OLE Project Header File
+//
+//----------------------------------------------------------------------------
+
+#ifndef __OLE_HXX__
+#define __OLE_HXX__
+
+#include <error.hxx>
+
+#define olErr(l, e) ErrJmp(ol, l, e, sc)
+#define olChkTo(l, e) if (FAILED(sc = (e))) olErr(l, sc) else 1
+#define olHChkTo(l, e) if (FAILED(sc = DfGetScode(e))) olErr(l, sc) else 1
+#define olChk(e) olChkTo(EH_Err, e)
+#define olHChk(e) olHChkTo(EH_Err, e)
+#define olMemTo(l, e) \
+ if ((e) == NULL) olErr(l, STG_E_INSUFFICIENTMEMORY) else 1
+#define olMem(e) olMemTo(EH_Err, e)
+
+#include <ref.hxx>
+
+#if DEVL == 1
+
+DECLARE_DEBUG(ol);
+
+#endif
+
+#if DBG == 1
+
+#define olDebugOut(x) olInlineDebugOut x
+#include <assert.h>
+#define olAssert(e) assert(e)
+#define olVerify(e) assert(e)
+#define olAssSucc(e) assert(SUCCEEDED(e))
+#define olVerSucc(e) assert(SUCCEEDED(e))
+#define olHVerSucc(e) assert(SUCCEEDED(DfGetScode(e)))
+
+
+#else
+
+#define olDebugOut(x)
+#define olAssert(e)
+#define olVerify(e) (e)
+#define olAssSucc(e)
+#define olVerSucc(e) (e)
+#define olHVerSucc(e) (e)
+
+#endif
+
+
+#endif
diff --git a/private/ole32/stg/ref/h/page.hxx b/private/ole32/stg/ref/h/page.hxx
new file mode 100644
index 000000000..09eb06642
--- /dev/null
+++ b/private/ole32/stg/ref/h/page.hxx
@@ -0,0 +1,552 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: page.hxx
+//
+// Contents: Paging classes for MSF
+//
+// Classes: CMSFPage
+// CMSFPageTable
+//
+// Functions:
+//
+//----------------------------------------------------------------------------
+
+#ifndef __PAGE_HXX__
+#define __PAGE_HXX__
+
+class CPagedVector;
+
+#define STG_S_NEWPAGE \
+ MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_STORAGE, 0x2FF)
+
+#define FB_NONE 0x00000000
+#define FB_DIRTY 0x00000001
+#define FB_NEW 0x00000002
+#define FB_TOUCHED 0x10000000
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CMSFPage (mp)
+//
+// Purpose: Contain MSF data in a form that is swappable to disk
+//
+// Interface: See below.
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+
+class CMSFPage
+{
+public:
+ void * operator new(size_t size, size_t sizeData);
+
+ CMSFPage(CMSFPage *pmpNext);
+ inline ~CMSFPage();
+
+ inline void AddRef(void);
+ inline void Release(void);
+
+ inline CMSFPage *GetNext(void) const;
+ inline CMSFPage *GetPrev(void) const;
+ inline SID GetSid(void) const;
+ inline ULONG GetOffset(void) const;
+ inline SECT GetSect(void) const;
+ inline void *GetData(void) const;
+ inline DWORD GetFlags(void) const;
+ inline CPagedVector * GetVector(void) const;
+
+ inline void SetChain(CMSFPage *const pmpPrev, CMSFPage *const pmpNext);
+ inline void SetPrev(CMSFPage *const pmpPrev);
+ inline void SetNext(CMSFPage *const pmpNext);
+
+ inline void SetSid(const SID sid);
+ inline void SetOffset(const ULONG ulOffset);
+ inline void SetSect(const SECT sect);
+ inline void SetFlags(const DWORD dwFlags);
+ inline void SetVector(CPagedVector *ppv);
+
+ inline void SetDirty(void);
+ inline void ResetDirty(void);
+ inline BOOL IsDirty(void) const;
+
+ inline BOOL IsInUse(void) const;
+private:
+ CMSFPage *_pmpNext;
+ CMSFPage *_pmpPrev;
+
+ SID _sid;
+ ULONG _ulOffset;
+ CPagedVector *_ppv;
+ SECT _sect;
+ DWORD _dwFlags;
+ LONG _cReferences;
+ BYTE _ab[];
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::~CMSFPage, public
+//
+// Synopsis: Destructor
+//
+//----------------------------------------------------------------------------
+
+inline CMSFPage::~CMSFPage()
+{
+ msfAssert(_cReferences == 0);
+
+ _pmpPrev->SetNext(_pmpNext);
+ _pmpNext->SetPrev(_pmpPrev);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::operator new, public
+//
+// Synopsis: Overloaded new operator for CMSFPage.
+//
+// Arguments: [size] -- Default size field
+// [sizeData] -- Size of byte array to allocate.
+//
+// Returns: Pointer to new CMSFPage object
+//
+// Notes: *Finish This*
+//
+//----------------------------------------------------------------------------
+
+inline void * CMSFPage::operator new(size_t size, size_t sizeData)
+{
+ msfAssert(size == sizeof(CMSFPage));
+ return ::new BYTE[sizeData + sizeof(CMSFPage)];
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetNext, public
+//
+// Synopsis: Returns the next page in the list
+//
+//----------------------------------------------------------------------------
+
+inline CMSFPage * CMSFPage::GetNext(void) const
+{
+ return _pmpNext;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetPrev, public
+//
+// Synopsis: Returns the next page in the list
+//
+//----------------------------------------------------------------------------
+
+inline CMSFPage * CMSFPage::GetPrev(void) const
+{
+ return _pmpPrev;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetSid, public
+//
+// Synopsis: Returns the SID for this page
+//
+//----------------------------------------------------------------------------
+
+inline SID CMSFPage::GetSid(void) const
+{
+ return _sid;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetOffset, public
+//
+// Synopsis: Returns the array offset for this page
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CMSFPage::GetOffset(void) const
+{
+ return _ulOffset;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetSect, public
+//
+// Synopsis: Returns the SECT for this page
+//
+//----------------------------------------------------------------------------
+
+inline SECT CMSFPage::GetSect(void) const
+{
+ return _sect;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetFlags, public
+//
+// Synopsis: Returns the flags for this page
+//
+//----------------------------------------------------------------------------
+
+inline DWORD CMSFPage::GetFlags(void) const
+{
+ return _dwFlags;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetData, public
+//
+// Synopsis: Returns a pointer to the page storage for this page
+//
+//----------------------------------------------------------------------------
+
+inline void * CMSFPage::GetData(void) const
+{
+ return (void *) _ab;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::GetVector, public
+//
+// Synopsis: Returns a pointer to the vector holding this page
+//
+//----------------------------------------------------------------------------
+
+inline CPagedVector * CMSFPage::GetVector(void) const
+{
+ return _ppv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetChain, public
+//
+// Synopsis: Sets the chain pointers for this page
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetChain(
+ CMSFPage *const pmpPrev,
+ CMSFPage *const pmpNext)
+{
+ _pmpPrev = pmpPrev;
+ _pmpNext = pmpNext;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetPrev, public
+//
+// Synopsis: Sets the prev pointer for this page
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetPrev(CMSFPage *const pmpPrev)
+{
+ _pmpPrev = pmpPrev;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetNext, public
+//
+// Synopsis: Sets the next pointer for this page
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetNext(CMSFPage *const pmpNext)
+{
+ _pmpNext = pmpNext;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetSid, public
+//
+// Synopsis: Sets the SID for this page
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetSid(const SID sid)
+{
+ _sid = sid;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetOffset, public
+//
+// Synopsis: Sets the offset for this page
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetOffset(const ULONG ulOffset)
+{
+ _ulOffset = ulOffset;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetSect, public
+//
+// Synopsis: Sets the SECT for this page
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetSect(const SECT sect)
+{
+ _sect = sect;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetSect, public
+//
+// Synopsis: Sets the SECT for this page
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetFlags(const DWORD dwFlags)
+{
+ _dwFlags = dwFlags;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetVector, public
+//
+// Synopsis: Sets the pointer to the vector holding this page
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetVector(CPagedVector *ppv)
+{
+ _ppv = ppv;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::SetDirty, public
+//
+// Synopsis: Sets the dirty bit for this page
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::SetDirty(void)
+{
+ _dwFlags = _dwFlags | FB_DIRTY;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::ResetDirty, public
+//
+// Synopsis: Resets the dirty bit for this page
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::ResetDirty(void)
+{
+ _dwFlags = _dwFlags & ~FB_DIRTY;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::IsDirty, public
+//
+// Synopsis: Returns TRUE if the dirty bit is set on this page
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CMSFPage::IsDirty(void) const
+{
+ return (_dwFlags & FB_DIRTY) != 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::IsInUse, public
+//
+// Synopsis: Returns TRUE if the page is currently in use
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CMSFPage::IsInUse(void) const
+{
+ return (_cReferences != 0);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::AddRef, public
+//
+// Synopsis: Increment the reference count
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::AddRef(void)
+{
+ msfAssert(_cReferences >= 0);
+ AtomicInc(&_cReferences);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::Release, public
+//
+// Synopsis: Decrement the reference count
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPage::Release(void)
+{
+ msfAssert(_cReferences > 0);
+ AtomicDec(&_cReferences);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Class: CMSFPageTable
+//
+// Purpose: Page allocator and handler for MSF
+//
+// Interface: See below
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+class CMSFPageTable
+{
+public:
+ CMSFPageTable(
+ CMStream MSTREAM_NEAR *const pmsParent,
+ const ULONG _cMinPages,
+ const ULONG _cMaxPages);
+ ~CMSFPageTable();
+
+ inline void AddRef();
+ inline void Release();
+
+ SCODE Init(void);
+ SCODE GetPage(
+ CPagedVector *ppv,
+ SID sid,
+ ULONG ulOffset,
+ CMSFPage **ppmp);
+
+
+ SCODE FindPage(
+ CPagedVector *ppv,
+ SID sid,
+ ULONG ulOffset,
+ CMSFPage **ppmp);
+
+ SCODE GetFreePage(CMSFPage **ppmp);
+
+ void ReleasePage(CPagedVector *ppv, SID sid, ULONG ulOffset);
+
+ void FreePages(CPagedVector *ppv);
+
+ SCODE Flush(void);
+ SCODE FlushPage(CMSFPage *pmp);
+
+ inline void SetParent(CMStream *pms);
+
+private:
+ inline CMSFPage * GetNewPage(void);
+ CMSFPage * FindSwapPage(void);
+
+ CMStream * _pmsParent;
+ const ULONG _cbSector;
+ const ULONG _cMinPages;
+ const ULONG _cMaxPages;
+
+ ULONG _cActivePages;
+ ULONG _cPages;
+ CMSFPage *_pmpCurrent;
+
+ LONG _cReferences;
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::GetNewPage, private
+//
+// Synopsis: Insert a new page into the list and return a pointer to it.
+//
+// Arguments: None.
+//
+// Returns: Pointer to new page. Null if there was an allocation error.
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+inline CMSFPage * CMSFPageTable::GetNewPage(void)
+{
+ return new((size_t)_cbSector) CMSFPage(_pmpCurrent);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::AddRef, public
+//
+// Synopsis: Increment the ref coutn
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPageTable::AddRef(void)
+{
+ AtomicInc(&_cReferences);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::Release, public
+//
+// Synopsis: Decrement the ref count, delete if necessary
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPageTable::Release(void)
+{
+ msfAssert(_cReferences > 0);
+ AtomicDec(&_cReferences);
+ if (_cReferences == 0)
+ {
+ delete this;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::SetParent, public
+//
+// Synopsis: Set the parent of this page table
+//
+// Arguments: [pms] -- Pointer to new parent
+//
+//----------------------------------------------------------------------------
+
+inline void CMSFPageTable::SetParent(CMStream *pms)
+{
+ _pmsParent = pms;
+}
+
+#endif // #ifndef __PAGE_HXX__
diff --git a/private/ole32/stg/ref/h/pbstream.hxx b/private/ole32/stg/ref/h/pbstream.hxx
new file mode 100644
index 000000000..2bfb94c73
--- /dev/null
+++ b/private/ole32/stg/ref/h/pbstream.hxx
@@ -0,0 +1,274 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: pbstream.hxx
+//
+// Contents: CPubStream definition
+//
+// Classes: CPubStream
+//
+//--------------------------------------------------------------------------
+
+
+#ifndef __PBSTREAM_HXX__
+#define __PBSTREAM_HXX__
+
+#include <msf.hxx>
+#include <revert.hxx>
+#include <psstream.hxx>
+
+class CPubDocFile;
+
+//+--------------------------------------------------------------
+//
+// Class: CPubStream
+//
+// Purpose: Public stream interface
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+class CPubStream : public PRevertable
+{
+public:
+
+ CPubStream(CPubDocFile *ppdf,
+ DFLAGS df,
+ CDfName const *pdfn);
+ ~CPubStream();
+
+ void Init(PSStream *psParent,
+ DFLUID dlLUID);
+ inline void vAddRef(void);
+ void vRelease(void);
+
+ // PRevertable
+ virtual void RevertFromAbove(void);
+
+ SCODE Stat(STATSTGW *pstatstg, DWORD grfStatFlag);
+ inline SCODE ReadAt(ULONG ulOffset,
+ VOID *pb,
+ ULONG cb,
+ ULONG STACKBASED *pcbRead);
+ inline SCODE WriteAt(ULONG ulOffset,
+ VOID const HUGEP *pb,
+ ULONG cb,
+ ULONG STACKBASED *pcbWritten);
+ inline SCODE GetSize(ULONG *pcb);
+ inline SCODE SetSize(ULONG cb);
+
+
+ inline PSStream *GetSt(void) const;
+
+ inline SCODE CheckReverted(void) const;
+
+ inline void SetClean(void);
+ inline void SetDirty(void);
+
+ SCODE Commit(DWORD dwFlags);
+private:
+ PSStream *_psParent;
+ CPubDocFile *_ppdfParent;
+ BOOL _fDirty;
+ LONG _cReferences;
+};
+
+
+//+--------------------------------------------------------------
+//
+// Member: CPubStream::CheckReverted, public
+//
+// Synopsis: Returns revertedness
+//
+//---------------------------------------------------------------
+
+
+inline SCODE CPubStream::CheckReverted(void) const
+{
+ return P_REVERTED(_df) ? STG_E_REVERTED : S_OK;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CPubStream::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+//---------------------------------------------------------------
+
+inline void CPubStream::vAddRef(void)
+{
+ AtomicInc(&_cReferences);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubStream::GetSt, public
+//
+// Synopsis: Returns _psParent
+//
+//---------------------------------------------------------------
+
+inline PSStream *CPubStream::GetSt(void) const
+{
+ return _psParent;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubStream::SetClean, public
+//
+// Synopsis: Resets the dirty flag
+//
+//----------------------------------------------------------------------------
+
+inline void CPubStream::SetClean(void)
+{
+ _fDirty = FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubStream::SetDirty, public
+//
+// Synopsis: Sets the dirty flag
+//
+//----------------------------------------------------------------------------
+
+inline void CPubStream::SetDirty(void)
+{
+ _fDirty = TRUE;
+ _ppdfParent->SetDirty();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPubStream::ReadAt, public
+//
+// Synopsis: Read from a stream
+//
+// Arguments: [ulOffset] - Byte offset to read from
+// [pb] - Buffer
+// [cb] - Count of bytes to read
+// [pcbRead] - Return number of bytes actually read
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+//
+//--------------------------------------------------------------------------
+
+
+inline SCODE CPubStream::ReadAt(ULONG ulOffset,
+ VOID *pb,
+ ULONG cb,
+ ULONG STACKBASED *pcbRead)
+{
+ SCODE sc;
+
+ if (SUCCEEDED(sc = CheckReverted()))
+ if (!P_READ(_df))
+ sc = STG_E_ACCESSDENIED;
+ else
+ sc = _psParent->ReadAt(ulOffset,pb,cb,pcbRead);
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPubStream::WriteAt, public
+//
+// Synopsis: Write to a stream
+//
+// Arguments: [ulOffset] - Byte offset to write at
+// [pb] - Buffer
+// [cb] - Count of bytes to write
+// [pcbWritten] - Return number of bytes actually written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbWritten]
+//
+//--------------------------------------------------------------------------
+
+
+inline SCODE CPubStream::WriteAt(ULONG ulOffset,
+ VOID const HUGEP *pb,
+ ULONG cb,
+ ULONG STACKBASED *pcbWritten)
+{
+ SCODE sc;
+
+ if (SUCCEEDED(sc = CheckReverted()))
+ if (!P_WRITE(_df))
+ sc = STG_E_ACCESSDENIED;
+ else
+ {
+ sc = _psParent->WriteAt(ulOffset,pb,cb,pcbWritten);
+ if (SUCCEEDED(sc))
+ SetDirty();
+ }
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubStream::GetSize, public
+//
+// Synopsis: Gets the size of the stream
+//
+// Arguments: [pcb] - Stream size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcb]
+//
+//---------------------------------------------------------------
+
+
+inline SCODE CPubStream::GetSize(ULONG *pcb)
+{
+ SCODE sc;
+
+ if (SUCCEEDED(sc = CheckReverted()))
+ _psParent->GetSize(pcb);
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CPubStream::SetSize, public
+//
+// Synposis: Set the size of a linear stream
+//
+// Arguments: [ulNewSize] -- New size for stream
+//
+// Returns: Error code returned by MStream call.
+//
+// Algorithm: Pass call up to parent.
+//
+//---------------------------------------------------------------------------
+
+
+inline SCODE CPubStream::SetSize(ULONG ulNewSize)
+{
+ SCODE sc;
+
+ if (SUCCEEDED(sc = CheckReverted()))
+ if (!P_WRITE(_df))
+ sc = STG_E_ACCESSDENIED;
+ else
+ {
+ sc = _psParent->SetSize(ulNewSize);
+ if (SUCCEEDED(sc))
+ SetDirty();
+ }
+ return sc;
+}
+
+
+#endif //__PBSTREAM_HXX__
diff --git a/private/ole32/stg/ref/h/pdocfile.hxx b/private/ole32/stg/ref/h/pdocfile.hxx
new file mode 100644
index 000000000..949d9ebb0
--- /dev/null
+++ b/private/ole32/stg/ref/h/pdocfile.hxx
@@ -0,0 +1,110 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: pdocfile.hxx
+//
+// Contents: DocFile protocol header
+//
+// Classes: PDocFile
+//
+//---------------------------------------------------------------
+
+#ifndef __PDOCFILE_HXX__
+#define __PDOCFILE_HXX__
+
+#include <dfmsp.hxx>
+#include <entry.hxx>
+
+class CDocFile;
+class PDocFileIterator;
+class PSStream;
+class CUpdateList;
+class CWrappedDocFile;
+
+// CopyDocFileToDocFile flags
+#define CDF_NORMAL 0 // Normal copy
+#define CDF_EXACT 1 // Exact dir entry match
+#define CDF_REMAP 2 // Remap handles
+#define CDF_ENTRIESONLY 4 // Don't copy contents
+
+//+--------------------------------------------------------------
+//
+// Class: PDocFile (df)
+//
+// Purpose: DocFile protocol
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+class PDocFile : public PEntry
+{
+public:
+ virtual void AddRef(void) = 0;
+ virtual void Release(void) = 0;
+
+ virtual SCODE DestroyEntry(CDfName const *pdfnName,
+ BOOL fClean) = 0;
+ virtual SCODE RenameEntry(CDfName const *pdfnName,
+ CDfName const *pdfnNewName) = 0;
+
+ virtual SCODE GetClass(CLSID *pclsid) = 0;
+ virtual SCODE SetClass(REFCLSID clsid) = 0;
+ virtual SCODE GetStateBits(DWORD *pgrfStateBits) = 0;
+ virtual SCODE SetStateBits(DWORD grfStateBits, DWORD grfMask) = 0;
+
+ virtual SCODE CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ PDocFile **ppdfDocFile) = 0;
+ inline SCODE CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ DWORD const dwType,
+ PDocFile **ppdfDocFile)
+ { return CreateDocFile(pdfnName, df, luidSet, ppdfDocFile); }
+
+ virtual SCODE GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ PDocFile **ppdfDocFile) = 0;
+ inline SCODE GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DWORD const dwType,
+ PDocFile **ppdfDocFile)
+ { return GetDocFile(pdfnName, df, ppdfDocFile); }
+
+ virtual SCODE CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ PSStream **ppsstStream) = 0;
+ inline SCODE CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DFLUID luidSet,
+ DWORD const dwType,
+ PSStream **ppsstStream)
+ { return CreateStream(pdfnName, df, luidSet, ppsstStream); }
+ virtual SCODE GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ PSStream **ppsstStream) = 0;
+ inline SCODE GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DWORD const dwType,
+ PSStream **ppsstStream)
+ { return GetStream(pdfnName, df, ppsstStream); }
+
+ virtual SCODE GetIterator(PDocFileIterator **ppdfi) = 0;
+
+
+ virtual SCODE IsEntry(CDfName const *pdfnName,
+ SEntryBuffer *peb) = 0;
+ virtual SCODE DeleteContents(void) = 0;
+
+ static SCODE ExcludeEntries(PDocFile *pdf, SNBW snbExclude);
+
+protected:
+ inline PDocFile(DFLUID dl) : PEntry(dl) {}
+};
+
+#endif
diff --git a/private/ole32/stg/ref/h/piter.hxx b/private/ole32/stg/ref/h/piter.hxx
new file mode 100644
index 000000000..09794cef6
--- /dev/null
+++ b/private/ole32/stg/ref/h/piter.hxx
@@ -0,0 +1,35 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: piter.hxx
+//
+// Contents: PDocFileIterator header file
+//
+// Classes: PDocFileIterator
+//
+//---------------------------------------------------------------
+
+#ifndef __PITER_HXX__
+#define __PITER_HXX__
+
+//+--------------------------------------------------------------
+//
+// Class: PDocFileIterator (dfi)
+//
+// Purpose: DocFile iterator protocol
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+class PDocFileIterator
+{
+public:
+ virtual SCODE GetNext(STATSTGW *pstatstg) = 0;
+ virtual SCODE BufferGetNext(SIterBuffer *pib) = 0;
+ virtual void Release(void) = 0;
+};
+
+#endif
diff --git a/private/ole32/stg/ref/h/psstream.hxx b/private/ole32/stg/ref/h/psstream.hxx
new file mode 100644
index 000000000..c02f65b9c
--- /dev/null
+++ b/private/ole32/stg/ref/h/psstream.hxx
@@ -0,0 +1,49 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: psstream.hxx
+//
+// Contents: Internal stream base class
+//
+// Classes: PSStream
+//
+//--------------------------------------------------------------------------
+
+#ifndef __PSSTREAM_HXX__
+#define __PSSTREAM_HXX__
+
+#include <entry.hxx>
+
+class CDirectStream;
+
+class PSStream: public PEntry
+{
+
+ public:
+
+ virtual void AddRef(void) = 0;
+ virtual void Release(void) = 0;
+
+ virtual SCODE ReadAt(
+ ULONG ulOffset,
+ VOID HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval) = 0;
+
+ virtual SCODE WriteAt(
+ ULONG ulOffset,
+ VOID const HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval) = 0;
+
+ virtual SCODE SetSize(ULONG ulNewSize) = 0;
+
+ virtual void GetSize(ULONG *pulSize) = 0;
+
+protected:
+ inline PSStream(DFLUID dl) : PEntry(dl) {}
+};
+
+#endif //__PSSTREAM_HXX__
diff --git a/private/ole32/stg/ref/h/pubiter.hxx b/private/ole32/stg/ref/h/pubiter.hxx
new file mode 100644
index 000000000..ff0ffb76d
--- /dev/null
+++ b/private/ole32/stg/ref/h/pubiter.hxx
@@ -0,0 +1,120 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: pubiter.hxx
+//
+// Contents: CPubIter header
+//
+// Classes: CPubIter
+// CSnapshotEntry
+//
+//---------------------------------------------------------------
+
+#ifndef __PUBITER_HXX__
+#define __PUBITER_HXX__
+
+#include <revert.hxx>
+#include <publicdf.hxx>
+
+//+--------------------------------------------------------------
+//
+// Class: CSnapshotEntry (se)
+//
+// Purpose: Holds information about an iterated object
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+class CSnapshotEntry
+{
+public:
+ DWORD dwType;
+ WCHAR wcsName[CWCSTREAMNAME];
+ TIME_T atime;
+ TIME_T mtime;
+ TIME_T ctime;
+ ULARGE_INTEGER cbSize;
+};
+
+class CDirectStream;
+
+//+--------------------------------------------------------------
+//
+// Class: CPubIter
+//
+// Purpose: Revertable iterator backup for exposed iterators
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+class CPubIter : public PRevertable
+{
+public:
+ CPubIter(CPubDocFile *pdf);
+ ~CPubIter(void);
+
+ inline void vAddRef(void);
+ void vRelease(void);
+
+ // PRevertable
+ virtual void RevertFromAbove(void);
+
+ SCODE Next(ULONG ulOffset, STATSTGW *pstatstg);
+
+ inline DFLAGS GetDFlags(void) const;
+ inline SCODE CheckReverted(void) const;
+
+private:
+ SCODE Snapshot(void);
+
+ CPubDocFile *_pdf;
+ ILockBytes *_pds;
+ CDfName _dfnScratch;
+ LONG _cReferences;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CPubIter::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+//---------------------------------------------------------------
+
+inline void CPubIter::vAddRef(void)
+{
+ AtomicInc(&_cReferences);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubIter::GetDFlags, public
+//
+// Synopsis: Returns the flags for the public docfile for this iterator
+//
+//----------------------------------------------------------------------------
+
+inline DFLAGS CPubIter::GetDFlags(void) const
+{
+ return _pdf->GetDFlags();
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubIter::CheckReverted, private
+//
+// Synopsis: Returns STG_E_REVERTED if reverted
+//
+//---------------------------------------------------------------
+
+inline SCODE CPubIter::CheckReverted(void) const
+{
+ return P_REVERTED(_df) ? STG_E_REVERTED : S_OK;
+}
+
+#endif // #ifndef __PUBITER_HXX__
diff --git a/private/ole32/stg/ref/h/publicdf.hxx b/private/ole32/stg/ref/h/publicdf.hxx
new file mode 100644
index 000000000..65efcc5df
--- /dev/null
+++ b/private/ole32/stg/ref/h/publicdf.hxx
@@ -0,0 +1,478 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: publicdf.hxx
+//
+// Contents: Public DocFile header
+//
+// Classes: CPubDocFile
+//
+//---------------------------------------------------------------
+
+#ifndef __PUBDF_HXX__
+#define __PUBDF_HXX__
+
+#include <dfmsp.hxx>
+#include <chinst.hxx>
+#include <ole.hxx>
+#include <revert.hxx>
+#include <pdocfile.hxx>
+#include <ref.hxx>
+
+class PDocFile;
+class CPubStream;
+class CPubIter;
+
+
+// Class signatures for object validation
+#define CPUBDOCFILE_SIG LONGSIG('P', 'B', 'D', 'F')
+#define CPUBDOCFILE_SIGDEL LONGSIG('P', 'b', 'D', 'f')
+
+//+--------------------------------------------------------------
+//
+// Class: CPubDocFile (df)
+//
+// Purpose: Public DocFile class
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+class CPubDocFile : public PRevertable
+{
+public:
+ CPubDocFile(CPubDocFile *pdfParent,
+ PDocFile *pdf,
+ DFLAGS const df,
+ DFLUID luid,
+ ILockBytes *pilbBase,
+ CDfName const *pdfn,
+ CMStream MSTREAM_NEAR *pmsBase);
+
+ // C700 - Virtual destructors aren't working properly so explicitly
+ // declare one
+ virtual void vdtor(void);
+
+ inline void vAddRef(void);
+ void vRelease(void);
+
+ // PRevertable
+ virtual void RevertFromAbove(void);
+
+ virtual SCODE Stat(STATSTGW *pstatstg, DWORD grfStatFlag);
+
+ SCODE Commit(DWORD const dwFlags);
+ SCODE Revert(void);
+ SCODE DestroyEntry(CDfName const *pdfnName,
+ BOOL fClean);
+ SCODE RenameEntry(CDfName const *pdfnName,
+ CDfName const *pdfnNewName);
+ SCODE SetElementTimes(CDfName const *pdfnName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+ SCODE SetClass(REFCLSID clsid);
+ SCODE SetStateBits(DWORD grfStateBits, DWORD grfMask);
+ SCODE CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubDocFile **ppdfDocFile);
+ SCODE GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubDocFile **ppdfDocFile);
+ SCODE CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubStream **ppdstStream);
+ SCODE GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubStream **ppdstStream);
+ SCODE GetIterator(CPubIter **pppiIterator);
+
+ inline SCODE CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DWORD const dwType,
+ CPubDocFile **ppdfDocFile)
+ { return CreateDocFile(pdfnName, df, ppdfDocFile); }
+ inline SCODE GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ DWORD const dwType,
+ CPubDocFile **ppdfDocFile)
+ { return GetDocFile(pdfnName, df, ppdfDocFile); }
+ inline SCODE CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DWORD const dwType,
+ CPubStream **ppdstStream)
+ { return CreateStream(pdfnName, df, ppdstStream); }
+ inline SCODE GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ DWORD const dwType,
+ CPubStream **ppdstStream)
+ { return GetStream(pdfnName, df, ppdstStream); }
+ inline SCODE GetIterator(BOOL fProperties,
+ CPubIter **pppiIterator)
+ { return GetIterator(pppiIterator); }
+
+ void AddChild(PRevertable *prv);
+ void ReleaseChild(PRevertable *prv);
+ SCODE IsEntry(CDfName const *pdfnName, SEntryBuffer *peb);
+ BOOL IsAtOrAbove(CPubDocFile *pdf);
+
+
+ inline BOOL IsRoot(void) const;
+ inline CPubDocFile *GetParent(void) const;
+ inline LONG GetRefCount(void) const;
+
+ inline PDocFile *GetDF(void) const;
+ inline void SetDF(PDocFile *pdf);
+
+ inline SCODE CreateScratchStream(ILockBytes **ppsst, CDfName *pdfn);
+ inline void DeleteScratchStream(CDfName *pdfn);
+
+ inline SCODE CheckReverted(void) const;
+ inline void SetClean(void);
+ inline BOOL IsDirty(void) const;
+ inline void SetDirty(void);
+ inline void SetDirtyBit(void);
+
+ inline CMStream MSTREAM_NEAR * GetBaseMS(void);
+
+ static SCODE Validate(CPubDocFile *pdf);
+
+
+protected:
+ static SCODE CopyLStreamToLStream(ILockBytes *plstFrom,
+ ILockBytes *plstTo);
+
+ CPubDocFile *_pdfParent;
+ PDocFile *_pdf;
+ CChildInstanceList _cilChildren;
+ BOOL _fDirty;
+ CMStream MSTREAM_NEAR *_pmsBase;
+ DFSIGNATURE _sigMSF;
+ ULONG _sig;
+
+ LONG _cReferences;
+ ILockBytes *_pilbBase;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::GetDF, public
+//
+// Synopsis: Returns _pdf
+//
+//---------------------------------------------------------------
+
+
+inline PDocFile *CPubDocFile::GetDF(void) const
+{
+ return _pdf;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::SetDF, public
+//
+// Synopsis: Sets _pdf
+//
+//---------------------------------------------------------------
+
+inline void CPubDocFile::SetDF(PDocFile *pdf)
+{
+ _pdf = pdf;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::AddRef, public
+//
+// Synopsis: Changes the ref count
+//
+//---------------------------------------------------------------
+
+inline void CPubDocFile::vAddRef(void)
+{
+ AtomicInc(&_cReferences);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::IsRoot, public
+//
+// Synopsis: Returns _pdfParent == NULL
+//
+//---------------------------------------------------------------
+
+inline BOOL CPubDocFile::IsRoot(void) const
+{
+ return _pdfParent == NULL;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::GetParent, public
+//
+// Synopsis: Returns _pdfParent
+//
+//---------------------------------------------------------------
+
+inline CPubDocFile *CPubDocFile::GetParent(void) const
+{
+ return _pdfParent;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::GetRefCount, public
+//
+// Synopsis: Returns the ref count
+//
+//---------------------------------------------------------------
+
+inline LONG CPubDocFile::GetRefCount(void) const
+{
+ return _cReferences;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::SetClean, public
+//
+// Synopsis: Resets the dirty flag
+//
+//----------------------------------------------------------------------------
+
+inline void CPubDocFile::SetClean(void)
+{
+ _fDirty = FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::IsDirty, public
+//
+// Synopsis: Returns the dirty flag
+//
+//----------------------------------------------------------------------------
+
+inline BOOL CPubDocFile::IsDirty(void) const
+{
+ return _fDirty;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::SetDirty, public
+//
+// Synopsis: Sets the dirty flag and all parents' dirty flags
+//
+//----------------------------------------------------------------------------
+
+inline void CPubDocFile::SetDirty(void)
+{
+ CPubDocFile *ppdf = this;
+
+ olAssert((this != NULL) && aMsg("Attempted to dirty parent of root"));
+
+ do
+ {
+ ppdf->SetDirtyBit();
+
+ ppdf = ppdf->GetParent();
+ } while (ppdf != NULL);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::SetDirtyBit, public
+//
+// Synopsis: Sets the dirty flag
+//
+//----------------------------------------------------------------------------
+
+inline void CPubDocFile::SetDirtyBit(void)
+{
+ _fDirty = TRUE;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::Revert, public
+//
+// Synopsis: Reverts transacted changes
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+inline SCODE CPubDocFile::Revert(void)
+{
+ return S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::ReleaseChild, private
+//
+// Synopsis: Releases a child instance
+//
+// Arguments: [prv] - Child instance
+//
+//---------------------------------------------------------------
+
+
+inline void CPubDocFile::ReleaseChild(PRevertable *prv)
+{
+ olAssert(SUCCEEDED(CheckReverted()));
+ _cilChildren.RemoveRv(prv);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::AddChild, public
+//
+// Synopsis: Adds a child instance
+//
+// Arguments: [prv] - Child
+//
+//---------------------------------------------------------------
+
+inline void CPubDocFile::AddChild(PRevertable *prv)
+{
+ olAssert(SUCCEEDED(CheckReverted()));
+ _cilChildren.Add(prv);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::IsEntry, public
+//
+// Synopsis: Checks whether the given name is an entry or not
+//
+// Arguments: [dfnName] - Name of element
+// [peb] - Entry buffer to fill in
+//
+// Returns: Appropriate status code
+//
+// Modifies: [peb]
+//
+//---------------------------------------------------------------
+
+inline SCODE CPubDocFile::IsEntry(CDfName const *dfnName,
+ SEntryBuffer *peb)
+{
+ SCODE sc;
+
+ if (SUCCEEDED(sc = CheckReverted()))
+ sc = _pdf->IsEntry(dfnName, peb);
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::IsAtOrAbove, public
+//
+// Synopsis: Determines whether the given public is an ancestor
+// of this public
+//
+// Arguments: [pdf] - Docfile to check
+//
+// Returns: TRUE or FALSE
+//
+//---------------------------------------------------------------
+
+inline BOOL CPubDocFile::IsAtOrAbove(CPubDocFile *pdf)
+{
+ CPubDocFile *pdfPar = this;
+
+ olAssert(SUCCEEDED(CheckReverted()));
+ // MAC compiler can't support natural form with two returns
+ do
+ {
+ if (pdfPar == pdf)
+ break;
+ }
+ while (pdfPar = pdfPar->_pdfParent);
+ return pdfPar == pdf;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::CreateScratchStream, public
+//
+// Synopsis: Asks the TL for a scratch stream
+//
+// Arguments: [ppsst] - Stream return
+// [pdfn] - Stream name return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppsst]
+// [*pdfn]
+//
+//---------------------------------------------------------------
+
+inline SCODE CPubDocFile::CreateScratchStream(
+ ILockBytes **ppsst,
+ CDfName *pdfn)
+{
+ SCODE sc;
+
+ if (SUCCEEDED(sc = CheckReverted()))
+ sc = CreateFileStream(ppsst, pdfn);
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::DeleteScratchStream, public
+//
+// Synopsis: Delete a scratch stream
+//
+// Arguments: [pdfn] - Stream to delete
+//
+//---------------------------------------------------------------
+
+inline void CPubDocFile::DeleteScratchStream(CDfName *pdfn)
+{
+ DeleteFileStream(pdfn);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::CheckReverted, private
+//
+// Synopsis: Returns STG_E_REVERTED if reverted
+//
+//---------------------------------------------------------------
+
+inline SCODE CPubDocFile::CheckReverted(void) const
+{
+ return P_REVERTED(_df) ? STG_E_REVERTED : S_OK;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::GetBaseMS, public
+//
+// Synopsis: Return pointer to base multistream
+//
+//----------------------------------------------------------------------------
+
+inline CMStream MSTREAM_NEAR * CPubDocFile::GetBaseMS(void)
+{
+ return _pmsBase;
+}
+
+
+
+
+#endif
+
diff --git a/private/ole32/stg/ref/h/ref.hxx b/private/ole32/stg/ref/h/ref.hxx
new file mode 100644
index 000000000..1eeed0e68
--- /dev/null
+++ b/private/ole32/stg/ref/h/ref.hxx
@@ -0,0 +1,194 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: ref.hxx
+//
+// Contents: Reference implementation stuff
+//
+// Classes:
+//
+// Functions:
+//
+//----------------------------------------------------------------------------
+
+#ifndef __REF_HXX__
+#define __REF_HXX__
+
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#define FARSTRUCT
+#define interface struct
+#define DECLARE_INTERFACE(iface) interface iface
+#define DECLARE_INTERFACE_(iface, baseiface) interface iface: public baseiface
+
+typedef long SCODE;
+typedef void * HRESULT;
+
+#define NOERROR 0
+
+
+#define PURE = 0
+
+#define STDMETHODIMP HRESULT
+#define STDMETHODIMP_(type) type
+#define STDMETHOD(method) virtual HRESULT method
+#define STDMETHOD_(type, method) virtual type method
+#define STDAPI HRESULT
+#define STDAPI_(type) type
+#define THIS_
+#define THIS void
+#define FAR
+
+typedef int BOOL;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned int UINT;
+typedef long LONG;
+typedef unsigned long DWORD;
+typedef short SHORT;
+typedef unsigned short USHORT;
+typedef DWORD ULONG;
+typedef void VOID;
+typedef WORD WCHAR;
+
+typedef void * LPVOID;
+typedef char * LPSTR;
+typedef char * LPCSTR;
+
+#define TRUE 1
+#define FALSE 0
+
+
+typedef struct _ULARGE_INTEGER {
+ DWORD LowPart;
+ DWORD HighPart;
+} ULARGE_INTEGER, *PULARGE_INTEGER;
+#define ULISet32(li, v) ((li).HighPart = 0, (li).LowPart = (v))
+
+typedef struct _LARGE_INTEGER {
+ DWORD LowPart;
+ LONG HighPart;
+} LARGE_INTEGER, *PLARGE_INTEGER;
+#define LISet32(li, v) ((li).HighPart = ((LONG)(v)) < 0 ? -1 : 0, (li).LowPart = (v))
+
+struct GUID
+{
+ DWORD Data1;
+ WORD Data2;
+ WORD Data3;
+ BYTE Data4[8];
+};
+
+typedef GUID CLSID;
+typedef GUID IID;
+
+#define REFGUID const GUID &
+#define REFIID const IID &
+#define REFCLSID const CLSID &
+
+
+
+
+DECLARE_INTERFACE(IUnknown)
+{
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+};
+
+
+#include <storage.h>
+
+#define S_OK 0L
+#define MAKE_SCODE(sev,fac,code) \
+ ((SCODE) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
+#define SEVERITY_SUCCESS 0
+#define SEVERITY_ERROR 1
+#define FACILITY_STORAGE 0x0003 // storage errors (STG_E_*)
+#define FACILITY_NULL 0x0000
+#define S_TRUE 0L
+#define S_FALSE MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, 1)
+#define E_NOINTERFACE MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 4)
+#define E_OUTOFMEMORY MAKE_SCODE(SEVERITY_ERROR, FACILITY_NULL, 2)
+#define SUCCEEDED(Status) ((SCODE)(Status) >= 0)
+#define FAILED(Status) ((SCODE)(Status)<0)
+#define GetScode(hr) ((SCODE)(hr) & 0x800FFFFF)
+#define ResultFromScode(sc) ((HRESULT)((SCODE)(sc) & 0x800FFFFF))
+
+#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
+ const GUID name
+#define DEFINE_OLEGUID(name, l, w1, w2) \
+ DEFINE_GUID(name, l, w1, w2, 0xC0,0,0,0,0,0,0,0x46)
+
+//REFBUG: This GUID won't be properly initialized by this macro.
+DEFINE_GUID(GUID_NULL, 0L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+/* storage related interfaces */
+DEFINE_OLEGUID(IID_IUnknown, 0x00000000L, 0, 0);
+DEFINE_OLEGUID(IID_IRootStorage, 0x00000012L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved1, 0x00000013L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved2, 0x00000014L, 0, 0);
+DEFINE_OLEGUID(IID_IDfReserved3, 0x00000015L, 0, 0);
+DEFINE_OLEGUID(IID_ILockBytes, 0x0000000aL, 0, 0);
+DEFINE_OLEGUID(IID_IStorage, 0x0000000bL, 0, 0);
+DEFINE_OLEGUID(IID_IStream, 0x0000000cL, 0, 0);
+DEFINE_OLEGUID(IID_IEnumSTATSTG, 0x0000000dL, 0, 0);
+
+STDAPI_(BOOL) IsEqualGUID(REFGUID rguid1, REFGUID rguid2);
+#define IsEqualIID(x, y) IsEqualGUID(x, y)
+#define IsEqualCLSID(x, y) IsEqualGUID(x, y)
+
+#define IID_NULL GUID_NULL
+#define CLSID_NULL GUID_NULL
+
+
+#define UNIMPLEMENTED_PARM(x) (x)
+
+#define UNREFERENCED_PARM(x) (x)
+
+#define DEB_ERROR 0x00000001 // exported error paths
+#define DEB_TRACE 0x00000004 // exported trace messages
+
+#define DEB_IERROR 0x00000100 // internal error paths
+#define DEB_ITRACE 0x00000400 // internal trace messages
+
+
+#if DBG == 1
+
+//When this gets built into an exe, the macro below should include
+// vprintf((const char *)pszfmt, vstart) in the if block.
+#define DECLARE_DEBUG(comp) \
+extern "C" unsigned long comp##InfoLevel; \
+extern "C" char *comp##InfoLevelString; \
+_inline void \
+comp##InlineDebugOut(unsigned long fDebugMask, char const *pszfmt, ...) \
+{ \
+ va_list vstart; \
+ va_start(vstart, pszfmt); \
+ if (comp##InfoLevel & fDebugMask) \
+ { \
+ } \
+}
+
+#define DECLARE_INFOLEVEL(comp) \
+extern "C" unsigned long comp##InfoLevel = DEB_ERROR; \
+extern "C" char *comp##InfoLevelString = #comp;
+
+#else
+#define DECLARE_DEBUG(comp)
+#define DECLARE_INFOLEVEL(comp)
+#endif
+
+
+class ILockBytes;
+class CDfName;
+
+SCODE CreateFileStream(ILockBytes **ppilb, CDfName *pdfn);
+SCODE DeleteFileStream(CDfName *pdfn);
+
+
+#endif // #ifndef __REF_HXX__
diff --git a/private/ole32/stg/ref/h/refilb.hxx b/private/ole32/stg/ref/h/refilb.hxx
new file mode 100644
index 000000000..7ff9be7d6
--- /dev/null
+++ b/private/ole32/stg/ref/h/refilb.hxx
@@ -0,0 +1,57 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: fileilb.hxx
+//
+// Contents:
+//
+// Classes:
+//
+// Functions:
+//
+//----------------------------------------------------------------------------
+
+#ifndef __FILEILB_HXX__
+#define __FILEILB_HXX__
+
+#include <storage.h>
+
+class CFileILB: public ILockBytes
+{
+public:
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS);
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ // *** ILockBytes methods ***
+ STDMETHOD(ReadAt) (THIS_ ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbRead);
+ STDMETHOD(WriteAt) (THIS_ ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten);
+ STDMETHOD(Flush) (THIS);
+ STDMETHOD(SetSize) (THIS_ ULARGE_INTEGER cb);
+ STDMETHOD(LockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag);
+
+ CFileILB(char *pszName);
+ ~CFileILB();
+
+private:
+ FILE * _f;
+ ULONG _ulRef;
+ char *_pszName;
+ BOOL _fDelete;
+};
+
+#endif // #ifndef __FILEILB_HXX__
diff --git a/private/ole32/stg/ref/h/revert.hxx b/private/ole32/stg/ref/h/revert.hxx
new file mode 100644
index 000000000..e6855e84d
--- /dev/null
+++ b/private/ole32/stg/ref/h/revert.hxx
@@ -0,0 +1,84 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: revert.hxx
+//
+// Contents: PRevertable definition
+//
+// Classes: PRevertable
+//
+// Notes: This class forms the root of all objects in the
+// transaction tree that understand reversion.
+// It allows lists of them to be formed.
+//
+//---------------------------------------------------------------
+
+#ifndef __REVERT_HXX__
+#define __REVERT_HXX__
+
+#include <dfmsp.hxx>
+
+class CChildInstanceList;
+
+class PRevertable
+{
+public:
+ virtual void RevertFromAbove(void) = 0;
+
+ inline DFLUID GetLuid(void) const;
+ inline DFLAGS GetDFlags(void) const;
+ inline PRevertable *GetNext(void) const;
+
+ friend class CChildInstanceList;
+
+protected:
+ DFLUID _luid;
+ DFLAGS _df;
+ CDfName _dfn;
+
+private:
+ PRevertable *_prvNext;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: PRevertable::GetLuid, public
+//
+// Synopsis: Returns the LUID
+//
+//---------------------------------------------------------------
+
+inline DFLUID PRevertable::GetLuid(void) const
+{
+ return _luid;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PRevertable::GetDFlags, public
+//
+// Synopsis: Returns the flags
+//
+//---------------------------------------------------------------
+
+inline DFLAGS PRevertable::GetDFlags(void) const
+{
+ return _df;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: PRevertable::GetNext, public
+//
+// Synopsis: Returns the next revertable
+//
+//---------------------------------------------------------------
+
+inline PRevertable *PRevertable::GetNext(void) const
+{
+ return _prvNext;
+}
+
+#endif // #ifndef __REVERT_HXX__
diff --git a/private/ole32/stg/ref/h/rpubdf.hxx b/private/ole32/stg/ref/h/rpubdf.hxx
new file mode 100644
index 000000000..9f510bb57
--- /dev/null
+++ b/private/ole32/stg/ref/h/rpubdf.hxx
@@ -0,0 +1,49 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: rpubdf.hxx
+//
+// Contents: Root public docfile header
+//
+// Classes: CRootPubDocFile
+//
+//---------------------------------------------------------------
+
+#ifndef __RPUBDF_HXX__
+#define __RPUBDF_HXX__
+
+#include <publicdf.hxx>
+
+//+--------------------------------------------------------------
+//
+// Class: CRootPubDocFile (rpdf)
+//
+// Purpose: Root form of the public docfile
+//
+// Interface: See below
+//
+//---------------------------------------------------------------
+
+class CRootPubDocFile : public CPubDocFile
+{
+public:
+ CRootPubDocFile(void);
+ SCODE InitRoot(ILockBytes *plstBase,
+ DWORD const dwStartFlags,
+ DFLAGS const df,
+ SNBW snbExclude,
+ ULONG *pulOpenLock);
+ virtual void vdtor(void);
+
+ virtual SCODE Stat(STATSTGW *pstatstg, DWORD grfStatFlag);
+
+
+private:
+ SCODE Init(ILockBytes *plstBase,
+ SNBW snbExclude,
+ DWORD const dwStartFlags);
+};
+
+#endif // #ifndef __RPUBDF_HXX__
diff --git a/private/ole32/stg/ref/h/sstream.hxx b/private/ole32/stg/ref/h/sstream.hxx
new file mode 100644
index 000000000..7ea4578fe
--- /dev/null
+++ b/private/ole32/stg/ref/h/sstream.hxx
@@ -0,0 +1,200 @@
+//+-------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: stream.hxx
+//
+// Contents: Stream header for mstream project
+//
+// Classes: CSStream - single linear stream for MSF
+//
+//--------------------------------------------------------------------
+
+
+
+#ifndef __STREAM_HXX__
+#define __STREAM_HXX__
+
+#include <msf.hxx>
+#include <handle.hxx>
+#include <psstream.hxx>
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CStreamCache (stmc)
+//
+// Purpose: Cache for stream optimization
+//
+// Interface: See below.
+//
+//----------------------------------------------------------------------------
+
+class CStreamCache
+{
+public:
+ inline CStreamCache();
+
+ inline void SetCache(ULONG ulOffset, SECT sect);
+ inline ULONG GetOffset(void) const;
+ inline SECT GetSect(void) const;
+
+private:
+ ULONG _ulOffset;
+ SECT _sect;
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStreamCache::CStreamCache, public
+//
+// Synopsis: CStreamCache constructor
+//
+//----------------------------------------------------------------------------
+
+inline CStreamCache::CStreamCache()
+{
+ _ulOffset = MAX_ULONG;
+ _sect = ENDOFCHAIN;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStreamCache::SetCache, public
+//
+// Synopsis: Set the cache information
+//
+// Arguments: [ulOffset] -- Offset into chain
+// [sect] -- Sect at that offset
+//
+//----------------------------------------------------------------------------
+
+inline void CStreamCache::SetCache(ULONG ulOffset, SECT sect)
+{
+ _ulOffset = ulOffset;
+ _sect = sect;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStreamCache::GetOffset, public
+//
+// Synopsis: Return offset
+//
+//----------------------------------------------------------------------------
+
+inline ULONG CStreamCache::GetOffset(void) const
+{
+ return _ulOffset;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CStreamCache::GetSect, public
+//
+// Synopsis: Return sect
+//
+//----------------------------------------------------------------------------
+
+inline SECT CStreamCache::GetSect(void) const
+{
+ return _sect;
+}
+
+
+//+----------------------------------------------------------------------
+//
+// Class: CDirectStream (ds)
+//
+// Purpose: Direct stream class
+//
+// Notes:
+//
+//-----------------------------------------------------------------------
+
+class CDirectStream: public PSStream
+{
+
+ public:
+ CDirectStream(DFLUID dl);
+ void InitSystem(CMStream MSTREAM_NEAR *pms,
+ SID sid,
+ ULONG cbSize);
+ SCODE Init(CStgHandle *pstgh,
+ CDfName const *pdfn,
+ BOOL const fCreate);
+ ~CDirectStream();
+
+ virtual void AddRef(VOID);
+
+ inline void DecRef(VOID);
+
+ virtual void Release(VOID);
+
+
+ virtual SCODE ReadAt(
+ ULONG ulOffset,
+ VOID HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval);
+
+ virtual SCODE WriteAt(
+ ULONG ulOffset,
+ VOID const HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval);
+
+ virtual SCODE SetSize(ULONG ulNewSize);
+
+ virtual void GetSize(ULONG *pulSize);
+
+ // PEntry
+ virtual SCODE GetTime(WHICHTIME wt, TIME_T *ptm);
+ virtual SCODE SetTime(WHICHTIME wt, TIME_T tm);
+
+
+ inline CStmHandle *GetHandle(void);
+
+ private:
+ CStmHandle _stmh;
+ CStreamCache _stmc;
+ ULONG _ulSize;
+ ULONG _ulOldSize;
+
+ LONG _cReferences;
+
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirectStream::GetHandle, public
+//
+// Synopsis: Returns a pointer to the stream handle
+//
+//----------------------------------------------------------------------------
+
+inline CStmHandle *CDirectStream::GetHandle(void)
+{
+ return &_stmh;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirectStream::DecRef, public
+//
+// Synopsis: Decrements the ref count
+//
+//----------------------------------------------------------------------------
+
+inline void CDirectStream::DecRef(void)
+{
+ AtomicDec(&_cReferences);
+}
+
+#endif //__SSTREAM_HXX__
+
+
diff --git a/private/ole32/stg/ref/h/storage.h b/private/ole32/stg/ref/h/storage.h
new file mode 100644
index 000000000..b504b404a
--- /dev/null
+++ b/private/ole32/stg/ref/h/storage.h
@@ -0,0 +1,433 @@
+// storage.h -
+
+#if !defined( _STORAGE_H_ )
+#define _STORAGE_H_
+
+
+
+
+/****** Storage Error Codes *************************************************/
+
+/* DOS-based error codes */
+#define STG_E_INVALIDFUNCTION \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x01)
+
+#define STG_E_FILENOTFOUND \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x02)
+
+#define STG_E_PATHNOTFOUND \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x03)
+
+#define STG_E_TOOMANYOPENFILES \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x04)
+
+#define STG_E_ACCESSDENIED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x05)
+
+#define STG_E_INVALIDHANDLE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x06)
+
+#define STG_E_INSUFFICIENTMEMORY \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x08)
+
+#define STG_E_INVALIDPOINTER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x09)
+
+#define STG_E_NOMOREFILES \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x12)
+
+#define STG_E_DISKISWRITEPROTECTED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x13)
+
+#define STG_E_SEEKERROR \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x19)
+
+#define STG_E_WRITEFAULT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x1d)
+
+#define STG_E_READFAULT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x1e)
+
+#define STG_E_LOCKVIOLATION \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x21)
+
+#define STG_E_FILEALREADYEXISTS \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x50)
+
+#define STG_E_INVALIDPARAMETER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x57)
+
+#define STG_E_MEDIUMFULL \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x70)
+
+#define STG_E_ABNORMALAPIEXIT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfa)
+
+#define STG_E_INVALIDHEADER \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfb)
+
+#define STG_E_INVALIDNAME \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfc)
+
+#define STG_E_UNKNOWN \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfd)
+
+#define STG_E_UNIMPLEMENTEDFUNCTION\
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xfe)
+
+#define STG_E_INVALIDFLAG \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0xff)
+
+/* Standard storage error codes */
+#define STG_E_INUSE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x100)
+
+#define STG_E_NOTCURRENT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x101)
+
+#define STG_E_REVERTED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x102)
+
+#define STG_E_CANTSAVE \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x103)
+
+#define STG_E_OLDFORMAT \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x104)
+
+#define STG_E_OLDDLL \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x105)
+
+#define STG_E_SHAREREQUIRED \
+ MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, 0x106)
+
+/* Information returns */
+#define STG_S_CONVERTED \
+ MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_STORAGE, 0x200)
+
+#define STG_S_BUFFEROVERFLOW \
+ MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_STORAGE, 0x201)
+
+#define STG_S_TRYOVERWRITE \
+ MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_STORAGE, 0x202)
+
+
+/****** Storage types *******************************************************/
+
+typedef char TCHAR;
+#ifndef HUGEP
+#define HUGEP
+#endif
+
+#define CWCSTORAGENAME 32
+
+/* Storage instantiation modes */
+#define STGM_DIRECT 0x00000000L
+#define STGM_TRANSACTED 0x00010000L
+
+#define STGM_READ 0x00000000L
+#define STGM_WRITE 0x00000001L
+#define STGM_READWRITE 0x00000002L
+
+#define STGM_SHARE_DENY_NONE 0x00000040L
+#define STGM_SHARE_DENY_READ 0x00000030L
+#define STGM_SHARE_DENY_WRITE 0x00000020L
+#define STGM_SHARE_EXCLUSIVE 0x00000010L
+
+#define STGM_PRIORITY 0x00040000L
+#define STGM_DELETEONRELEASE 0x04000000L
+
+#define STGM_CREATE 0x00001000L
+#define STGM_CONVERT 0x00020000L
+#define STGM_FAILIFTHERE 0x00000000L
+
+/* Storage commit types */
+typedef enum tagSTGC
+{
+ STGC_DEFAULT = 0,
+ STGC_OVERWRITE = 1,
+ STGC_ONLYIFCURRENT = 2,
+ STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4
+} STGC;
+
+/* Stream name block definitions */
+typedef char FAR * FAR *SNB;
+
+
+#ifndef _WINDOWS_
+#ifndef _FILETIME_
+#define _FILETIME_
+typedef struct FARSTRUCT tagFILETIME
+{
+ DWORD dwLowDateTime;
+ DWORD dwHighDateTime;
+} FILETIME;
+#endif
+#endif
+
+
+/* Storage stat buffer */
+
+typedef struct FARSTRUCT tagSTATSTG
+{
+ char FAR* pwcsName;
+ DWORD type;
+ ULARGE_INTEGER cbSize;
+ FILETIME mtime;
+ FILETIME ctime;
+ FILETIME atime;
+ DWORD grfMode;
+ DWORD grfLocksSupported;
+ CLSID clsid;
+ DWORD grfStateBits;
+ DWORD reserved;
+} STATSTG;
+
+
+/* Storage element types */
+typedef enum tagSTGTY
+{
+ STGTY_STORAGE = 1,
+ STGTY_STREAM = 2,
+ STGTY_LOCKBYTES = 3,
+ STGTY_PROPERTY = 4
+} STGTY;
+
+typedef enum tagSTREAM_SEEK
+{
+ STREAM_SEEK_SET = 0,
+ STREAM_SEEK_CUR = 1,
+ STREAM_SEEK_END = 2
+} STREAM_SEEK;
+
+typedef enum tagLOCKTYPE
+{
+ LOCK_WRITE = 1,
+ LOCK_EXCLUSIVE = 2,
+ LOCK_ONLYONCE = 4
+} LOCKTYPE;
+
+typedef enum tagSTGMOVE
+{
+ STGMOVE_MOVE = 0,
+ STGMOVE_COPY = 1
+} STGMOVE;
+
+typedef enum tagSTATFLAG
+{
+ STATFLAG_DEFAULT = 0,
+ STATFLAG_NONAME = 1
+} STATFLAG;
+
+
+/****** Storage Enumerators *************************************************/
+
+#define LPENUMSTATSTG IEnumSTATSTG FAR*
+
+#undef INTERFACE
+#define INTERFACE IEnumSTATSTG
+
+DECLARE_INTERFACE_(IEnumSTATSTG, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IENUMSTATSTG methods ***
+ STDMETHOD(Next) (THIS_ ULONG celt, STATSTG FAR * rgelt, ULONG FAR *pceltFetched) PURE;
+ STDMETHOD(Skip) (THIS_ ULONG celt) PURE;
+ STDMETHOD(Reset) (THIS) PURE;
+ STDMETHOD(Clone) (THIS_ IEnumSTATSTG FAR *FAR *ppenm) PURE;
+};
+
+
+/****** ILockBytes Interface ************************************************/
+
+#define LPLOCKBYTES ILockBytes FAR*
+
+#undef INTERFACE
+#define INTERFACE ILockBytes
+
+DECLARE_INTERFACE_(ILockBytes, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** ILockBytes methods ***
+ STDMETHOD(ReadAt) (THIS_ ULARGE_INTEGER ulOffset,
+ VOID HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbRead) PURE;
+ STDMETHOD(WriteAt) (THIS_ ULARGE_INTEGER ulOffset,
+ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten) PURE;
+ STDMETHOD(Flush) (THIS) PURE;
+ STDMETHOD(SetSize) (THIS_ ULARGE_INTEGER cb) PURE;
+ STDMETHOD(LockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(UnlockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+};
+
+
+/****** IStream Interface ***************************************************/
+
+
+#define LPSTREAM IStream FAR*
+
+#undef INTERFACE
+#define INTERFACE IStream
+
+DECLARE_INTERFACE_(IStream, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IStream methods ***
+ STDMETHOD(Read) (THIS_ VOID HUGEP *pv,
+ ULONG cb, ULONG FAR *pcbRead) PURE;
+ STDMETHOD(Write) (THIS_ VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG FAR *pcbWritten) PURE;
+ STDMETHOD(Seek) (THIS_ LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER FAR *plibNewPosition) PURE;
+ STDMETHOD(SetSize) (THIS_ ULARGE_INTEGER libNewSize) PURE;
+ STDMETHOD(CopyTo) (THIS_ IStream FAR *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER FAR *pcbRead,
+ ULARGE_INTEGER FAR *pcbWritten) PURE;
+ STDMETHOD(Commit) (THIS_ DWORD grfCommitFlags) PURE;
+ STDMETHOD(Revert) (THIS) PURE;
+ STDMETHOD(LockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(UnlockRegion) (THIS_ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+ STDMETHOD(Clone)(THIS_ IStream FAR * FAR *ppstm) PURE;
+};
+
+
+/****** IStorage Interface **************************************************/
+
+#define LPSTORAGE IStorage FAR*
+
+#undef INTERFACE
+#define INTERFACE IStorage
+
+DECLARE_INTERFACE_(IStorage, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IStorage methods ***
+ STDMETHOD(CreateStream) (THIS_ const char FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream FAR *FAR *ppstm) PURE;
+ STDMETHOD(OpenStream) (THIS_ const char FAR* pwcsName,
+ void FAR *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream FAR *FAR *ppstm) PURE;
+ STDMETHOD(CreateStorage) (THIS_ const char FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStorage FAR *FAR *ppstg) PURE;
+ STDMETHOD(OpenStorage) (THIS_ const char FAR* pwcsName,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR *FAR *ppstg) PURE;
+ STDMETHOD(CopyTo) (THIS_ DWORD ciidExclude,
+ IID const FAR *rgiidExclude,
+ SNB snbExclude,
+ IStorage FAR *pstgDest) PURE;
+ STDMETHOD(MoveElementTo) (THIS_ char const FAR* lpszName,
+ IStorage FAR *pstgDest,
+ char const FAR* lpszNewName,
+ DWORD grfFlags) PURE;
+ STDMETHOD(Commit) (THIS_ DWORD grfCommitFlags) PURE;
+ STDMETHOD(Revert) (THIS) PURE;
+ STDMETHOD(EnumElements) (THIS_ DWORD reserved1,
+ void FAR *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG FAR *FAR *ppenm) PURE;
+ STDMETHOD(DestroyElement) (THIS_ const char FAR* pwcsName) PURE;
+ STDMETHOD(RenameElement) (THIS_ const char FAR* pwcsOldName,
+ const char FAR* pwcsNewName) PURE;
+ STDMETHOD(SetElementTimes) (THIS_ const char FAR *lpszName,
+ FILETIME const FAR *pctime,
+ FILETIME const FAR *patime,
+ FILETIME const FAR *pmtime) PURE;
+ STDMETHOD(SetClass) (THIS_ REFCLSID clsid) PURE;
+ STDMETHOD(SetStateBits) (THIS_ DWORD grfStateBits, DWORD grfMask) PURE;
+ STDMETHOD(Stat) (THIS_ STATSTG FAR *pstatstg, DWORD grfStatFlag) PURE;
+};
+
+
+/****** IRootStorage Interface **********************************************/
+
+#define LPROOTSTORAGE IRootStorage FAR*
+
+#undef INTERFACE
+#define INTERFACE IRootStorage
+
+DECLARE_INTERFACE_(IRootStorage, IUnknown)
+{
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ // *** IRootStorage methods ***
+ STDMETHOD(SwitchToFile) (THIS_ LPSTR lpstrFile) PURE;
+};
+
+
+/****** Storage API Prototypes ********************************************/
+
+STDAPI StgCreateDocfile(const char FAR* pwcsName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgCreateDocfileOnILockBytes(ILockBytes FAR *plkbyt,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgOpenStorage(const char FAR* pwcsName,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgOpenStorageOnILockBytes(ILockBytes FAR *plkbyt,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+STDAPI StgIsStorageFile(const char FAR* pwcsName);
+STDAPI StgIsStorageILockBytes(ILockBytes FAR* plkbyt);
+
+STDAPI StgSetTimes(char const FAR* lpszName,
+ FILETIME const FAR* pctime,
+ FILETIME const FAR* patime,
+ FILETIME const FAR* pmtime);
+
+#endif
diff --git a/private/ole32/stg/ref/h/storagep.h b/private/ole32/stg/ref/h/storagep.h
new file mode 100644
index 000000000..48e3b6dcd
--- /dev/null
+++ b/private/ole32/stg/ref/h/storagep.h
@@ -0,0 +1,29 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: storagep.h
+//
+// Contents: Internal storage information
+//
+//--------------------------------------------------------------------------
+
+#ifndef __STORAGEP_H__
+#define __STORAGEP_H__
+
+// The byte combination that identifies that a file is a storage of
+// some kind
+
+const BYTE SIGSTG[] = {0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1};
+const BYTE CBSIGSTG = sizeof(SIGSTG);
+
+// The first portion of a storage file
+struct SStorageFile
+{
+ BYTE abSig[CBSIGSTG]; // Signature
+ CLSID _clid; // Class Id
+};
+
+#endif
+
diff --git a/private/ole32/stg/ref/h/vect.hxx b/private/ole32/stg/ref/h/vect.hxx
new file mode 100644
index 000000000..b0e141cf1
--- /dev/null
+++ b/private/ole32/stg/ref/h/vect.hxx
@@ -0,0 +1,146 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: vect.hxx
+//
+// Contents: Vector common types
+//
+// Classes: CVectBits -- Bit fields for vectors
+//
+//--------------------------------------------------------------------------
+
+#ifndef __VECT_HXX__
+#define __VECT_HXX__
+
+#include <malloc.h>
+#include <page.hxx>
+
+#define VECT_NEAR
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CVectBits (vb)
+//
+// Purpose: Structure for Vector flags.
+//
+// Interface:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+struct CVectBits
+{
+ BYTE full:1;
+ USHORT firstfree;
+
+ inline CVectBits();
+};
+
+//+-------------------------------------------------------------------------
+//
+// Method: CVectBits::CVectBits, public
+//
+// Synopsis: CVectBits default constructor.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline CVectBits::CVectBits()
+{
+ full = 0;
+ firstfree = 0;
+}
+
+
+inline CVectBits * GetNewVectBits(ULONG ulSize)
+{
+ msfAssert(ulSize > 0);
+ CVectBits *pfb = NULL;
+
+ if (ulSize <= (_HEAP_MAXREQ / sizeof(CVectBits)))
+ {
+ pfb = new CVectBits[(MAXINDEXTYPE)ulSize];
+ }
+ return pfb;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CPagedVector (pv)
+//
+// Purpose: *Finish This*
+//
+// Interface:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CPagedVector
+{
+public:
+ inline VECT_NEAR CPagedVector(const SID sid);
+
+ SCODE VECT_NEAR Init(CMStream MSTREAM_NEAR *pms, ULONG ulSize);
+
+ VECT_NEAR ~CPagedVector();
+
+ void Empty(void);
+
+
+ SCODE VECT_NEAR Resize(ULONG ulSize);
+
+ SCODE Flush(void);
+
+ SCODE GetTable(const ULONG iTable, DWORD dwFlags, void **ppmp);
+ inline void ReleaseTable(const ULONG iTable);
+
+ inline void SetSect(const ULONG iTable, const SECT sect);
+
+ inline CVectBits * GetBits(const ULONG iTable);
+
+ inline void ResetBits(void);
+
+ SCODE SetDirty(ULONG iTable);
+ inline void ResetDirty(ULONG iTable);
+
+ inline void FreeTable(ULONG iTable);
+
+ inline CMStream MSTREAM_NEAR * GetParent(void) const;
+ inline void SetParent(CMStream MSTREAM_NEAR *pms);
+
+private:
+ CMSFPageTable * _pmpt;
+ const SID _sid;
+
+ ULONG _ulSize; // Amount in use
+ ULONG _ulAllocSize; // Amount allocated
+
+ CMStream MSTREAM_NEAR *_pmsParent;
+
+ CMSFPage **_amp;
+ CVectBits *_avb;
+};
+
+
+
+inline VECT_NEAR CPagedVector::CPagedVector(const SID sid)
+: _sid(sid),
+ _pmpt(NULL),
+ _amp(NULL),
+ _avb(NULL),
+ _pmsParent(NULL)
+{
+ _ulSize = 0;
+ _ulAllocSize = 0;
+}
+
+
+#endif //__VECT_HXX__
diff --git a/private/ole32/stg/ref/h/vectfunc.hxx b/private/ole32/stg/ref/h/vectfunc.hxx
new file mode 100644
index 000000000..1cf50a4aa
--- /dev/null
+++ b/private/ole32/stg/ref/h/vectfunc.hxx
@@ -0,0 +1,239 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: vectfunc.hxx
+//
+// Contents: CPagedVector inline functions
+//
+// Classes:
+//
+// Functions:
+//
+//----------------------------------------------------------------------------
+
+#ifndef __VECTFUNC_HXX__
+#define __VECTFUNC_HXX__
+
+#define STG_S_FOUND MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_STORAGE, 0x400)
+
+
+inline CMSFPage ** FAT_NEAR GetNewPageArray(ULONG ulSize)
+{
+ msfAssert(ulSize > 0);
+ if (ulSize > (_HEAP_MAXREQ / sizeof(CMSFPage *)))
+ {
+ return NULL;
+ }
+
+ return new CMSFPage *[(MAXINDEXTYPE)ulSize];
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPagedVector::ReleaseTable, public
+//
+// Synopsis: Release a table that is no longer needed.
+//
+// Arguments: [iTable] -- index into vector
+//
+// Returns: S_OK if call completed OK.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+inline void VECT_NEAR CPagedVector::ReleaseTable(const FSINDEX iTable)
+{
+ if ((_amp == NULL) || (_amp[iTable] == NULL))
+ {
+ _pmpt->ReleasePage(this, _sid, iTable);
+ }
+ else
+ {
+ _amp[iTable]->Release();
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPagedVector::GetBits, public
+//
+// Synopsis: Return CVectBits for a given table
+//
+// Arguments: [iTable] -- Index of table to get bits for
+//
+// Returns: Pointer to CVectBits associated with table
+//
+//--------------------------------------------------------------------------
+
+inline CVectBits * CPagedVector::GetBits(const ULONG iTable)
+{
+ msfAssert(iTable < _ulSize);
+
+ return (_avb == NULL) ? NULL : &_avb[iTable];
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::ResetDirty, public
+//
+// Synopsis: Reset the dirty bit on the specified page
+//
+// Arguments: [iTable] -- Table to reset bit on
+//
+// Notes: This function is always called on a page with an
+// open reference. Therefore, the page is
+// guaranteed to be in the page table, and that
+// FindPage call should never return an error.
+//
+//----------------------------------------------------------------------------
+
+inline void CPagedVector::ResetDirty(ULONG iTable)
+{
+ SCODE sc;
+ if (_amp == NULL)
+ {
+ CMSFPage *pmp;
+
+ msfChk(_pmpt->FindPage(this, _sid, iTable, &pmp));
+ msfAssert(sc == STG_S_FOUND);
+ msfAssert(pmp->IsInUse() &&
+ aMsg("Called ResetDirty on page not in use."));
+ pmp->ResetDirty();
+ }
+ else
+ {
+ msfAssert(_amp != NULL);
+ msfAssert(_amp[iTable] != NULL);
+
+ _amp[iTable]->ResetDirty();
+ }
+ Err:
+ return;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::SetSect, public
+//
+// Synopsis: Set the sector location of a page
+//
+// Arguments: [iTable] -- Table to set page for
+// [sect] -- Sector location of page
+//
+// Notes: This function is always called on a page with an
+// open reference. Therefore, the page is
+// guaranteed to be in the page table, and that
+// FindPage call should never return an error.
+//
+//----------------------------------------------------------------------------
+
+inline void CPagedVector::SetSect(const ULONG iTable, const SECT sect)
+{
+ SCODE sc;
+ if (_amp == NULL)
+ {
+ CMSFPage *pmp;
+
+ msfChk(_pmpt->FindPage(this, _sid, iTable, &pmp));
+ msfAssert(sc == STG_S_FOUND);
+ msfAssert(pmp->IsInUse() &&
+ aMsg("Called SetSect on page not in use."));
+ pmp->SetSect(sect);
+ }
+ else
+ {
+ msfAssert(_amp != NULL);
+ msfAssert(_amp[iTable] != NULL);
+
+ _amp[iTable]->SetSect(sect);
+ }
+Err:
+ return;
+}
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::FreeTable, public
+//
+// Synopsis: Free a given table (NULL its pointer)
+//
+// Arguments: [iTable] -- Table to free
+//
+//----------------------------------------------------------------------------
+
+inline void CPagedVector::FreeTable(ULONG iTable)
+{
+ if ((_amp != NULL) && (_amp[iTable] != NULL))
+ {
+ msfAssert(_amp[iTable]->GetVector() == this);
+ _amp[iTable] = NULL;
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::SetParent, public
+//
+// Synopsis: Set the parent of this page table
+//
+// Arguments: [pms] -- Pointer to new parent
+//
+//----------------------------------------------------------------------------
+
+inline void CPagedVector::SetParent(CMStream MSTREAM_NEAR *pms)
+{
+ _pmsParent = pms;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::GetParent, public
+//
+// Synopsis: Return the parent MS pointer of a vector
+//
+//----------------------------------------------------------------------------
+
+inline CMStream MSTREAM_NEAR * CPagedVector::GetParent(void) const
+{
+ return _pmsParent;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::ResetBits, public
+//
+// Synopsis: Reset all the optimization bits in the vector
+//
+//----------------------------------------------------------------------------
+
+void CPagedVector::ResetBits(void)
+{
+ if (_avb != NULL)
+ {
+ for (ULONG i = 0; i < _ulSize; i++)
+ {
+ _avb[i].full = FALSE;
+ _avb[i].firstfree = 0;
+ }
+ }
+}
+
+
+#endif // #ifndef __VECTFUNC_HXX__
diff --git a/private/ole32/stg/ref/h/wchar.h b/private/ole32/stg/ref/h/wchar.h
new file mode 100644
index 000000000..6760f3a6f
--- /dev/null
+++ b/private/ole32/stg/ref/h/wchar.h
@@ -0,0 +1,62 @@
+//+---------------------------------------------------------------------------
+//
+// File: WChar.h
+//
+// Contents: Defines wide character equivalents for standard functions
+// usually in strings.h and ctypes.h
+//
+//----------------------------------------------------------------------------
+
+#ifndef __WCHAR_H__
+#define __WCHAR_H__
+
+#include <stdlib.h>
+
+#if !defined(FLAT) || defined(OLE32)
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Unicode Byte Order Mark (BOM) for Unicode text files
+#define BOM 0xFEFF
+
+// Padding constant and macro for localized buffer allocation
+#define INTL_PADDING_VALUE 3
+#define INTL_PADDING(cb) (INTL_PADDING_VALUE * (cb))
+
+
+long _CRTAPI1 wcsatol(const wchar_t *wsz);
+int _CRTAPI1 wcsatoi(const wchar_t *wsz);
+wchar_t * _CRTAPI1 wcscat(wchar_t *wsz1, const wchar_t *wsz2);
+wchar_t * _CRTAPI1 wcschr(const wchar_t *wsz1, wchar_t character);
+int _CRTAPI1 wcscmp(const wchar_t *wsz1, const wchar_t *wsz2);
+int _CRTAPI1 wcsicmp(const wchar_t *wsz1, const wchar_t *wsz2);
+int _CRTAPI1 wcscoll(const wchar_t * wsz1, const wchar_t * wsz2);
+wchar_t * _CRTAPI1 wcscpy(wchar_t *wsz1, wchar_t const *wsz2);
+wchar_t * _CRTAPI1 wcsitoa(int ival, wchar_t *wsz, int radix);
+size_t _CRTAPI1 wcslen(wchar_t const *wsz);
+wchar_t * _CRTAPI1 wcsltoa(long lval, wchar_t *wsz, int radix);
+wchar_t * _CRTAPI1 wcslwr(wchar_t *wsz);
+int _CRTAPI1 wcsncmp(const wchar_t *wsz1, const wchar_t *wsz2, size_t count);
+int _CRTAPI1 wcsnicmp(const wchar_t *wsz1, const wchar_t *wsz2, size_t count);
+wchar_t * _CRTAPI1 wcsncpy(wchar_t *wsz1, const wchar_t *wsz2, size_t count);
+wchar_t * _CRTAPI1 wcsrchr(const wchar_t * wcs, wchar_t wc);
+wchar_t * _CRTAPI1 wcsupr(wchar_t *wsz);
+wchar_t * _CRTAPI1 wcswcs(const wchar_t *wsz1, const wchar_t *wsz2);
+
+// sprintf support now included in misc.lib
+
+extern int _CRTAPI1 w4sprintf(char *pszout, const char *pszfmt, ...);
+extern int _CRTAPI1 w4vsprintf(char *pszout, const char *pszfmt, va_list arglist);
+extern int _CRTAPI1 w4wcsprintf(wchar_t *pwzout, const char *pszfmt, ...);
+extern int _CRTAPI1 w4vwcsprintf(wchar_t *pwzout, const char *pszfmt, va_list arglist);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // !defined(FLAT) || defined(OLE32)
+
+#endif /* __WCHAR_H__ */
diff --git a/private/ole32/stg/ref/header.cxx b/private/ole32/stg/ref/header.cxx
new file mode 100644
index 000000000..cfd00a1a3
--- /dev/null
+++ b/private/ole32/stg/ref/header.cxx
@@ -0,0 +1,93 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: header.cxx
+//
+// Contents: Code to manage MSF header
+//
+// Classes: Defined in header.hxx
+//
+//--------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+
+#include <dfver.h>
+
+CMSFHeader::CMSFHeader(USHORT uSectorShift)
+{
+ msfAssert((CSECTFATREAL != CSECTFAT) || (sizeof(CMSFHeader) == HEADERSIZE));
+ _uSectorShift = uSectorShift;
+ _uMiniSectorShift = MINISECTORSHIFT;
+ _ulMiniSectorCutoff = MINISTREAMSIZE;
+
+ _clid = IID_NULL;
+
+ _uByteOrder = 0xFFFE;
+
+ _uMinorVersion = rmm;
+ _uDllVersion = rmj;
+
+ for (SECT sect = 0; sect < CSECTFAT; sect ++)
+ {
+ _sectFat[sect] = FREESECT;
+ }
+
+ SetDifLength(0);
+ SetDifStart(ENDOFCHAIN);
+
+ SetFatLength(1);
+ SetFatStart(SECTFAT);
+ SetDirStart(SECTDIR);
+
+ SetMiniFatLength(0);
+ SetMiniFatStart(ENDOFCHAIN);
+
+ _signature = 0;
+ _usReserved = 0;
+ _ulReserved1 = _ulReserved2 = 0;
+
+ // Write DocFile signature
+ memcpy(abSig, SIGSTG, CBSIGSTG);
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMSFHeader::Validate, public
+//
+// Synopsis: Validate a header.
+//
+// Returns: S_OK if header is valid.
+//
+//--------------------------------------------------------------------------
+
+
+//Identifier for first bytes of Beta 2 Docfiles
+const BYTE SIGSTG_B2[] = {0x0e, 0x11, 0xfc, 0x0d, 0xd0, 0xcf, 0x11, 0xe0};
+const BYTE CBSIGSTG_B2 = sizeof(SIGSTG_B2);
+
+SCODE CMSFHeader::Validate(VOID) const
+{
+ // Check for ship Docfile signature first
+
+ if (memcmp((void *)abSig, SIGSTG, CBSIGSTG) == 0)
+ {
+ // Check file format verson number
+ if (GetDllVersion() <= rmj)
+ return(S_OK);
+
+ return(STG_E_OLDDLL);
+ }
+
+ // Check for Beta 2 Docfile signature
+
+ if (memcmp((void *) abSig, SIGSTG_B2, CBSIGSTG_B2) == 0)
+ return S_OK;
+
+
+ return(STG_E_INVALIDHEADER);
+}
diff --git a/private/ole32/stg/ref/iter.cxx b/private/ole32/stg/ref/iter.cxx
new file mode 100644
index 000000000..0c35c82a6
--- /dev/null
+++ b/private/ole32/stg/ref/iter.cxx
@@ -0,0 +1,157 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: iter.cxx
+//
+// Contents: CDocFileIterator implementation
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+
+#include <msfiter.hxx>
+#include <iter.hxx>
+
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFileIterator::CDocFileIterator, public
+//
+// Synopsis: Empty object ctor
+//
+//---------------------------------------------------------------
+
+CDocFileIterator::CDocFileIterator(void)
+{
+ olDebugOut((DEB_ITRACE, "In CDocFileIterator::CDocFileIterator()\n"));
+ _pi = NULL;
+ olDebugOut((DEB_ITRACE, "Out CDocFileIterator::CDocFileIterator\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFileIterator::Init
+//
+// Synopsis: Constructor
+//
+// Arguments: [ph] - Multistream handle
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+SCODE CDocFileIterator::Init(CStgHandle *ph)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFileIterator::Init(%p)\n", ph));
+ if (FAILED(sc = ph->GetIterator(&_pi)))
+ _pi = NULL;
+ olDebugOut((DEB_ITRACE, "Out CDocFileIterator::Init\n"));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFileIterator::~CDocFileIterator
+//
+// Synopsis: Destructor
+//
+//---------------------------------------------------------------
+
+CDocFileIterator::~CDocFileIterator(void)
+{
+ olDebugOut((DEB_ITRACE, "In CDocFileIterator::~CDocFileIterator\n"));
+ if (_pi)
+ _pi->Release();
+ olDebugOut((DEB_ITRACE, "Out CDocFileIterator::~CDocFileIterator\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFileIterator::GetNext
+//
+// Synopsis: Get the next entry
+//
+// Arguments: [pstatstg] - Buffer to return information in
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+//---------------------------------------------------------------
+
+
+SCODE CDocFileIterator::GetNext(STATSTGW *pstatstg)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CDocFileIterator::GetNext(%p)\n", pstatstg));
+ // Eliminate properties from non-property builds
+ for (;;)
+ {
+ if (FAILED(sc = _pi->GetNext(pstatstg)))
+ {
+#if DEVL == 1
+ // Null the name to clean up some debug prints
+ pstatstg->pwcsName = NULL;
+#endif
+ break;
+ }
+ else
+ break;
+ }
+ olDebugOut((DEB_ITRACE, "Out CDocFileIterator::GetNext => %ws, %ld\n",
+ pstatstg->pwcsName, pstatstg->type));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFileIterator::BufferGetNext, public
+//
+// Synopsis: Fast, fixed-space version of GetNext
+//
+// Arguments: [pib] - Buffer to fill in
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pib]
+//
+//---------------------------------------------------------------
+
+
+SCODE CDocFileIterator::BufferGetNext(SIterBuffer *pib)
+{
+ SCODE sc;
+
+ // Eliminate properties from non-property builds
+ for (;;)
+ {
+ if (FAILED(sc = _pi->BufferGetNext(pib)))
+ break;
+ }
+ return sc;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDocFileIterator::Release, public
+//
+// Synopsis: Releases resources for an iterator
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+void CDocFileIterator::Release(void)
+{
+ olDebugOut((DEB_ITRACE, "In CDocFileIterator::Release()\n"));
+ delete this;
+ olDebugOut((DEB_ITRACE, "Out CDocFileIterator::Release\n"));
+}
diff --git a/private/ole32/stg/ref/iter.hxx b/private/ole32/stg/ref/iter.hxx
new file mode 100644
index 000000000..7fd00d8f8
--- /dev/null
+++ b/private/ole32/stg/ref/iter.hxx
@@ -0,0 +1,48 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: iter.hxx
+//
+// Contents: CDocFileIterator header file
+//
+// Classes: CDocFileIterator
+//
+//---------------------------------------------------------------
+
+#ifndef __ITER_HXX__
+#define __ITER_HXX__
+
+#include "piter.hxx"
+
+class CMSFIterator;
+class CStgHandle;
+
+//+--------------------------------------------------------------
+//
+// Class: CDocFileIterator (dfi)
+//
+// Purpose: Derive a new iterator that remembers what DocFile it
+// came from
+//
+// Interface: Same as PDocFileIterator
+//
+//---------------------------------------------------------------
+
+class CDocFileIterator : public PDocFileIterator
+{
+public:
+ CDocFileIterator(void);
+ SCODE Init(CStgHandle *ph);
+ ~CDocFileIterator(void);
+
+ virtual SCODE GetNext(STATSTGW *pstatstg);
+ virtual SCODE BufferGetNext(SIterBuffer *pib);
+ virtual void Release(void);
+
+private:
+ CMSFIterator *_pi;
+};
+
+#endif
diff --git a/private/ole32/stg/ref/lock.cxx b/private/ole32/stg/ref/lock.cxx
new file mode 100644
index 000000000..aee1453af
--- /dev/null
+++ b/private/ole32/stg/ref/lock.cxx
@@ -0,0 +1,313 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: lock.cxx
+//
+// Contents: Remote exclusion stuff for docfile
+//
+// Functions: GetAccess
+// ReleaseAccess
+// GetOpen
+// ReleaseOpen
+//
+//--------------------------------------------------------------------------
+
+#include <exphead.cxx>
+
+#include <header.hxx>
+#include <lock.hxx>
+
+// Offset to next lock group from a particular group
+#define OLOCKGROUP 1
+
+//+--------------------------------------------------------------
+//
+// Function: GetAccess, public
+//
+// Synopsis: Takes appropriate access locks on an LStream
+//
+// Arguments: [plst] - LStream
+// [df] - Permissions needed
+// [poReturn] - Index of lock taken
+//
+// Returns: Appropriate status code
+//
+// Modifies: [poReturn]
+//
+//---------------------------------------------------------------
+
+SCODE GetAccess(ILockBytes *plst, DFLAGS df, ULONG *poReturn)
+{
+ SCODE sc;
+ ULARGE_INTEGER ulOffset, cbLength;
+
+ olDebugOut((DEB_ITRACE, "In GetAccess(%p, %X, %p)\n",
+ plst, df, poReturn));
+ *poReturn = NOLOCK;
+ ULISet32(ulOffset, OACCESS);
+ if (P_READ(df))
+ {
+ ULISet32(cbLength, 1);
+ olHChk(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ for (USHORT i = 0; i < CREADLOCKS; i++)
+ {
+ ULISetLow(ulOffset, OREADLOCK+i);
+ sc = DfGetScode(plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ if (SUCCEEDED(sc))
+ {
+ *poReturn = OREADLOCK + i;
+ break;
+ }
+ }
+ ULISetLow(ulOffset, OACCESS);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ if (i == CREADLOCKS)
+ olErr(EH_Err, STG_E_TOOMANYOPENFILES);
+ }
+ else if (P_WRITE(df))
+ {
+ olAssert((OACCESS + 1 == OREADLOCK) && aMsg("Bad lock dependency"));
+ ULISet32(cbLength, 1 + CREADLOCKS);
+ olChk(DfGetScode(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE)));
+ *poReturn = 0xFFFFFFFF;
+ }
+ olDebugOut((DEB_ITRACE, "Out GetAccess => %lu\n", *poReturn));
+ return S_OK;
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: ReleaseAccess, public
+//
+// Synopsis: Releases access locks
+//
+// Arguments: [plst] - LStream that is locked
+// [df] - Permission to release
+// [offset] - Offset of locks taken
+//
+//---------------------------------------------------------------
+
+void ReleaseAccess(ILockBytes *plst, DFLAGS df, ULONG offset)
+{
+ ULARGE_INTEGER ulOffset, cbLength;
+
+ olDebugOut((DEB_ITRACE, "In ReleaseAccess(%p, %lX, %lu)\n",
+ plst, df, offset));
+ if (offset == NOLOCK)
+ return;
+ if (P_READ(df))
+ {
+ ULISet32(ulOffset, offset);
+ ULISet32(cbLength, 1);
+ olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))) &&
+ aMsg("Non-fatal (Removable media?)"));
+ }
+ else if (P_WRITE(df))
+ {
+ olAssert((OACCESS + 1 == OREADLOCK) && aMsg("Bad lock dependency"));
+ ULISet32(ulOffset, OACCESS);
+ ULISet32(cbLength, 1 + CREADLOCKS);
+ olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))) &&
+ aMsg("Non-fatal (Removable media?)"));
+ }
+ olDebugOut((DEB_ITRACE, "Out ReleaseAccess\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Function: GetOpen, public
+//
+// Synopsis: Gets locks on an LStream during opening
+//
+// Arguments: [plst] - LStream
+// [df] - Permissions to take
+// [fCheck] - Whether to check for existing locks or not
+// [puReturn] - Index of lock taken
+//
+// Returns: Appropriate status code
+//
+// Modifies: [puReturn]
+//
+//---------------------------------------------------------------
+
+SCODE GetOpen(ILockBytes *plst,
+ DFLAGS df,
+ BOOL fCheck,
+ ULONG *puReturn)
+{
+ SCODE sc;
+ ULONG i;
+ ULARGE_INTEGER ulOffset, cbLength;
+
+ olDebugOut((DEB_ITRACE, "In GetOpen(%p, %lX, %d, %p)\n",
+ plst, df, fCheck, puReturn));
+ *puReturn = NOLOCK;
+
+ ULISet32(ulOffset, OUPDATE);
+ ULISet32(cbLength, 1);
+ olHChk(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ if (fCheck)
+ {
+ ULISetLow(cbLength, COPENLOCKS);
+ if (P_DENYREAD(df))
+ {
+ ULISetLow(ulOffset, OOPENREADLOCK);
+ olHChkTo(EH_UnlockUpdate, plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+ if (P_DENYWRITE(df))
+ {
+ ULISetLow(ulOffset, OOPENWRITELOCK);
+ olHChkTo(EH_UnlockUpdate, plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+ if (P_READ(df))
+ {
+ ULISetLow(ulOffset, OOPENDENYREADLOCK);
+ olHChkTo(EH_UnlockUpdate, plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+ if (P_WRITE(df))
+ {
+ ULISetLow(ulOffset, OOPENDENYWRITELOCK);
+ olHChkTo(EH_UnlockUpdate, plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+ }
+
+ ULISetLow(cbLength, 1);
+ for (i = 0; i < COPENLOCKS; i = i + OLOCKGROUP)
+ {
+ ULISetLow(ulOffset, OOPENREADLOCK+i);
+ olHChkTo(EH_Loop, plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ ULISetLow(ulOffset, OOPENWRITELOCK+i);
+ olHChkTo(EH_UnlockR, plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ ULISetLow(ulOffset, OOPENDENYREADLOCK+i);
+ olHChkTo(EH_UnlockW, plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE));
+ ULISetLow(ulOffset, OOPENDENYWRITELOCK+i);
+ if (SUCCEEDED(DfGetScode(plst->LockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))))
+ break;
+ ULISetLow(ulOffset, OOPENDENYREADLOCK+i);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ EH_UnlockW:
+ ULISetLow(ulOffset, OOPENWRITELOCK+i);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ EH_UnlockR:
+ ULISetLow(ulOffset, OOPENREADLOCK+i);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ EH_Loop:
+ ;
+ }
+ if (i >= COPENLOCKS)
+ olErr(EH_UnlockUpdate, STG_E_TOOMANYOPENFILES);
+ if (!P_READ(df))
+ {
+ ULISetLow(ulOffset, OOPENREADLOCK+i);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+ if (!P_WRITE(df))
+ {
+ ULISetLow(ulOffset, OOPENWRITELOCK+i);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+ if (!P_DENYREAD(df))
+ {
+ ULISetLow(ulOffset, OOPENDENYREADLOCK+i);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+ if (!P_DENYWRITE(df))
+ {
+ ULISetLow(ulOffset, OOPENDENYWRITELOCK+i);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+ }
+ ULISetLow(ulOffset, OUPDATE);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+
+ // 0 <= i < COPENLOCKS, but 0 is the invalid value, so increment
+ // on the way out
+ *puReturn = i + 1;
+
+ olDebugOut((DEB_ITRACE, "Out GetOpen => %lu\n", *puReturn));
+ return S_OK;
+EH_UnlockUpdate:
+ ULISetLow(ulOffset, OUPDATE);
+ ULISetLow(cbLength, 1);
+ olHVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Function: ReleaseOpen, public
+//
+// Synopsis: Releases opening locks
+//
+// Arguments: [plst] - LStream
+// [df] - Locks taken
+// [offset] - Index of locks
+//
+// Requires: offset != NOLOCK
+//
+//---------------------------------------------------------------
+
+void ReleaseOpen(ILockBytes *plst, DFLAGS df, ULONG offset)
+{
+ ULARGE_INTEGER ulOffset, cbLength;
+
+ olDebugOut((DEB_ITRACE, "In ReleaseOpen(%p, %lX, %lu)\n",
+ plst, df, offset));
+
+ olAssert(offset != NOLOCK);
+
+ // we incremented at the end of GetOpen, so we decrement here
+ // to restore the proper lock index
+ offset--;
+
+ ULISetHigh(ulOffset, 0);
+ ULISet32(cbLength, 1);
+ if (P_READ(df))
+ {
+ ULISetLow(ulOffset, OOPENREADLOCK+offset);
+ olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))) &&
+ aMsg("Non-fatal (Removable media?)"));
+ }
+ if (P_WRITE(df))
+ {
+ ULISetLow(ulOffset, OOPENWRITELOCK+offset);
+ olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))) &&
+ aMsg("Non-fatal (Removable media?)"));
+ }
+ if (P_DENYREAD(df))
+ {
+ ULISetLow(ulOffset, OOPENDENYREADLOCK+offset);
+ olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))) &&
+ aMsg("Non-fatal (Removable media?)"));
+ }
+ if (P_DENYWRITE(df))
+ {
+ ULISetLow(ulOffset, OOPENDENYWRITELOCK+offset);
+ olVerify(SUCCEEDED(DfGetScode(plst->UnlockRegion(ulOffset, cbLength,
+ LOCK_ONLYONCE))) &&
+ aMsg("Non-fatal (Removable media?)"));
+ }
+ olDebugOut((DEB_ITRACE, "Out ReleaseOpen\n"));
+}
diff --git a/private/ole32/stg/ref/logfile.hxx b/private/ole32/stg/ref/logfile.hxx
new file mode 100644
index 000000000..f1b970030
--- /dev/null
+++ b/private/ole32/stg/ref/logfile.hxx
@@ -0,0 +1,2 @@
+#define olLog(x)
+#define FreeLogFile() S_OK
diff --git a/private/ole32/stg/ref/makefile b/private/ole32/stg/ref/makefile
new file mode 100644
index 000000000..30fa632ac
--- /dev/null
+++ b/private/ole32/stg/ref/makefile
@@ -0,0 +1,109 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1993 **
+#********************************************************************
+
+
+# Put compiler specific flags on the first line
+CFLAGS = -c -G2s -Zile -AL -W3 -D_CRTAPI1=_cdecl
+
+# Put the name and path of the linker here.
+LINKER = \win40\import\c700\bin\link
+
+# Put linker specific flags here.
+LFLAGS = /nod /noe /map:0 /SE:256
+
+# CRTINC is the location of the C runtime header files
+CRTINC = \win40\import\c700\h
+
+# OSINC is the location of any operating system specific header files.
+# This reference implementation doesn't require any in its
+# unmodified form.
+OSINC = .
+
+CINC = -I$(CRTINC) -I$(OSINC)
+CINC = -I. -I.\h $(CINC)
+
+
+# EXELIBS should contain the names of any libraries required.
+# The reference implementation needs a C runtime library
+EXELIBS = \win40\import\c700\lib\llibcewq.lib\
+ \win40\import\win31\lib\libw.lib
+
+OBJDIR = obj
+
+CXXFILES = \
+ .\msf.cxx\
+ .\dir.cxx\
+ .\dirp.cxx\
+ .\fat.cxx\
+ .\mstream.cxx\
+ .\sstream.cxx\
+ .\msfiter.cxx\
+ .\header.cxx\
+ .\pbstream.cxx\
+ .\difat.cxx\
+ .\page.cxx\
+ .\vect.cxx\
+ .\refilb.cxx\
+ .\funcs.cxx\
+ .\chinst.cxx\
+ .\entry.cxx\
+ .\pdffuncs.cxx\
+ .\dffuncs.cxx\
+ .\dfstream.cxx\
+ .\dfiter.cxx\
+ .\iter.cxx\
+ .\cdocfile.cxx\
+ .\pubiter.cxx\
+ .\publicdf.cxx\
+ .\rpubdf.cxx\
+ .\time16.cxx\
+ .\docfile.cxx\
+ .\ascii.cxx\
+ .\lock.cxx\
+ .\seekptr.cxx\
+ .\expst.cxx\
+ .\peiter.cxx\
+ .\expiter.cxx\
+ .\expdf.cxx\
+ .\storage.cxx\
+ .\reftest.cxx\
+ .\wcslen.c\
+ .\wcsnicmp.c\
+ .\wcscat.c
+
+CXX_OBJS=$(CXXFILES:.cxx=.obj)
+CXX_OBJS=$(CXX_OBJS:.c=.obj)
+
+# The obj\ in the following line should be replaced with $(OBJDIR) for
+# versions of make that can handle it.
+CXX_OBJS=$(CXX_OBJS:.\=obj\)
+
+
+
+default: $(OBJDIR)\storage.exe
+
+$(OBJDIR)\storage.exe: $(CXX_OBJS)
+ $(LINKER) @<<$*.lnk
+$(LFLAGS) +
+$(CXX_OBJS: = +^
+)
+$*.exe
+$*.map
+$(EXELIBS: = +^
+)
+storage.def
+<<NOKEEP
+
+.c{$(OBJDIR)}.obj:
+ @-md $(OBJDIR)
+ cl -nologo $(CFLAGS) $(CINC) -Fo$*.obj $(MAKEDIR)\$<
+
+.cxx{$(OBJDIR)}.obj:
+ @-md $(OBJDIR)
+ cl -nologo $(CFLAGS) $(CINC) -Fo$*.obj $(MAKEDIR)\$<
+
+
+
+!include .\depend.mk
diff --git a/private/ole32/stg/ref/mread.hxx b/private/ole32/stg/ref/mread.hxx
new file mode 100644
index 000000000..48f563597
--- /dev/null
+++ b/private/ole32/stg/ref/mread.hxx
@@ -0,0 +1,259 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: mread.hxx
+//
+// Contents: Multistream inline functions
+//
+// Classes: None.
+//
+// Functions: None
+//
+//--------------------------------------------------------------------------
+
+#ifndef __MREAD_HXX__
+#define __MREAD_HXX__
+
+#include <difat.hxx>
+#include <sstream.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Function: ConvertSectAndOffset
+//
+// Synopsis: Convert a sector and offset into a byte offset in
+// a stream.
+//
+// Arguments: [sect] -- Sector
+// [off] -- Offset
+// [uShift] -- Shift count for sectorsize
+//
+// Returns: Byte offset into stream.
+//
+// Algorithm: The byte offset is sect left-shifted uShift times,
+// plus the offset, plus SECTORSIZE bytes for the
+// header.
+//
+//--------------------------------------------------------------------------
+
+
+inline ULONG MSTREAM_NEAR ConvertSectOffset(SECT sect, OFFSET off, USHORT uShift)
+{
+ ULONG ulTemp = ((ULONG)sect << uShift) + HEADERSIZE +
+ (ULONG)off;
+ msfDebugOut((DEB_ITRACE,"Convert got %lu\n",ulTemp));
+ return ulTemp;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetStart, private
+//
+// Synopsis: Given an SID, return the starting sector
+//
+// Arguments: [sid] -- Sid to find start for
+//
+// Returns: Starting sector for given SID.
+//
+// Notes: This function only works for controls structures,
+// not for ordinary streams.
+//
+//--------------------------------------------------------------------------
+
+inline SECT MSTREAM_NEAR CMStream::GetStart(SID sid) const
+{
+ SECT sectRet;
+ msfAssert(sid > MAXREGSID);
+
+ if (SIDFAT == sid)
+ {
+ sectRet = _hdr.GetFatStart();
+ }
+ else if (SIDDIR == sid)
+ {
+ sectRet = _hdr.GetDirStart();
+ }
+ else if (SIDDIF == sid)
+ {
+ sectRet = _hdr.GetDifStart();
+ }
+ else
+ {
+ msfAssert(SIDMINIFAT == sid);
+ sectRet = _hdr.GetMiniFatStart();
+ }
+ return sectRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::GetSect, private
+//
+// Synopsis: For a given SID and sect, return the location of that
+// sector in the multistream.
+//
+// Arguments: [sid] -- SID of sector to locate
+// [sect] -- Offset into chain to locate
+// [psect] -- Pointer to return location.
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CMStream::GetSect(SID sid, SECT sect, SECT *psect)
+{
+ SCODE sc;
+ SECT start;
+
+ if (sid == SIDFAT)
+ {
+ msfChk(_fatDif.GetFatSect(sect, &start));
+ }
+ else if (sid == SIDDIF)
+ {
+ msfChk(_fatDif.GetSect(sect, &start));
+ }
+ else
+ {
+ start = GetStart(sid);
+ msfChk(_fat.GetSect(start, sect, &start));
+ }
+
+ *psect = start;
+Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::GetESect, private
+//
+// Synopsis: For a given SID and sect, return the location of that
+// sector in the multistream.
+//
+// Arguments: [sid] -- SID of sector to locate
+// [sect] -- Offset into chain to locate
+// [psect] -- Pointer to return location.
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+inline SCODE CMStream::GetESect(SID sid, SECT sect, SECT *psect)
+{
+ SCODE sc = S_OK;
+
+ SECT start;
+
+ if (sid == SIDFAT)
+ {
+ msfChk(_fatDif.GetFatSect(sect, &start));
+ }
+ else if (sid == SIDDIF)
+ {
+ msfChk(_fatDif.GetSect(sect, &start));
+ }
+ else
+ {
+ start = GetStart(sid);
+ msfChk(_fat.GetESect(start, sect, &start));
+ }
+
+ *psect = start;
+Err:
+ return sc;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::SetSize, public
+//
+// Synposis: Sets the size of the parent LStream to match
+// current Fat information.
+//
+// Arguments: None.
+//
+// Returns: Error code from call to parent LStream SetSize()
+//
+// Algorithm: Query the Fat for the last sector used.
+// Convert that sector into a byte offset.
+// Call SetSize on the parent LStream.
+//
+//---------------------------------------------------------------------------
+
+
+inline SCODE MSTREAM_NEAR CMStream::SetSize(VOID)
+{
+ SCODE sc = S_OK;
+ ULONG ulSize;
+
+ ULARGE_INTEGER cbSize;
+
+ msfDebugOut((DEB_TRACE,"In CMStream::SetSize()\n"));
+
+ SECT sectMax;
+
+ msfChk(_fat.GetMaxSect(&sectMax));
+ ulSize = ConvertSectOffset(sectMax, 0, GetSectorShift());
+
+ ULISet32(cbSize, ulSize);
+ msfHChk((*_pplstParent)->SetSize(cbSize));
+
+ msfDebugOut((DEB_ITRACE,"Exiting CMStream::SetSize()\n"));
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::SetMiniSize, public
+//
+// Synposis: Sets the size of the MiniFat storage stream to match
+// current Fat information.
+//
+// Arguments: None.
+//
+// Returns: Error code from call to stream SetSize()
+//
+// Algorithm: Query the Fat for the last sector used.
+// Convert that sector into a byte offset.
+// Call SetSize on the Minifat storage stream.
+//
+//---------------------------------------------------------------------------
+
+
+inline SCODE MSTREAM_NEAR CMStream::SetMiniSize(VOID)
+{
+ SCODE sc;
+ ULONG ulNewSize;
+
+ SECT sectMax;
+ msfChk(_fatMini.GetMaxSect(&sectMax));
+ ulNewSize = sectMax << MINISECTORSHIFT;
+ msfChk(_pdsministream->CDirectStream::SetSize(ulNewSize));
+
+Err:
+ return sc;
+}
+
+
+#endif //__MREAD_HXX__
+
diff --git a/private/ole32/stg/ref/msf.cxx b/private/ole32/stg/ref/msf.cxx
new file mode 100644
index 000000000..b23af9056
--- /dev/null
+++ b/private/ole32/stg/ref/msf.cxx
@@ -0,0 +1,289 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: msf.cxx
+//
+// Contents: Entry points for MSF DLL
+//
+// Classes: None.
+//
+// Functions: DllMuliStreamFromStream
+// DllConvertStreamToMultiStream
+// DllReleaseMultiStream
+// DllGetScratchMultiStream
+// DllIsMultiStream
+//
+//--------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+
+#include <handle.hxx>
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllMultiStreamFromStream
+//
+// Synopsis: Create a new multistream instance from an existing stream.
+// This is used to reopen a stored multi-stream.
+//
+// Effects: Creates a new CMStream instance
+//
+// Arguments: [ppms] -- Pointer to storage for return of multistream
+// [pplstStream] -- Stream to be used by multi-stream for
+// reads and writes
+// [dwFlags] - Startup flags
+//
+// Returns: STG_E_INVALIDHEADER if signature on pStream does not
+// match.
+// STG_E_UNKNOWN if there was a problem in setup.
+// S_OK if call completed OK.
+//
+// Algorithm: Check the signature on the pStream and on the contents
+// of the pStream. If either is a mismatch, return
+// STG_E_INVALIDHEADER.
+// Create a new CMStream instance and run the setup function.
+// If the setup function fails, return STG_E_UNKNOWN.
+// Otherwise, return S_OK.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE DllMultiStreamFromStream(CMStream MSTREAM_NEAR **ppms,
+ ILockBytes **pplstStream,
+ DWORD dwFlags)
+{
+ SCODE sc;
+ CMStream MSTREAM_NEAR *temp;
+
+
+ BOOL fConvert = ((dwFlags & RSF_CONVERT) != 0);
+ BOOL fTruncate = ((dwFlags & RSF_TRUNCATE) != 0);
+ BOOL fCreate = ((dwFlags & RSF_CREATE) != 0);
+
+
+ msfDebugOut((DEB_ITRACE,"In DllMultiStreamFromStream\n"));
+
+ msfMem(temp = new CMStream(pplstStream, SECTORSHIFT));
+
+ STATSTG stat;
+ (*pplstStream)->Stat(&stat, STATFLAG_NONAME);
+ msfAssert(ULIGetHigh(stat.cbSize) == 0);
+ msfDebugOut((DEB_ITRACE,"Size is: %lu\n",ULIGetLow(stat.cbSize)));
+
+ do
+ {
+ if ((ULIGetLow(stat.cbSize) != 0) && (fConvert))
+ {
+ msfChk(temp->InitConvert());
+ break;
+ }
+
+ if (((ULIGetLow(stat.cbSize) == 0) && fCreate) || (fTruncate))
+ {
+ msfChk(temp->InitNew());
+ break;
+ }
+ msfChk(temp->Init());
+ }
+ while (FALSE);
+
+ *ppms = temp;
+
+ msfDebugOut((DEB_ITRACE,"Leaving DllMultiStreamFromStream\n"));
+
+ if (fConvert && ULIGetLow(stat.cbSize))
+ {
+ return STG_S_CONVERTED;
+ }
+
+ return S_OK;
+
+Err:
+ delete temp;
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllReleaseMultiStream
+//
+// Synopsis: Release a CMStream instance
+//
+// Effects: Deletes a multi-stream instance
+//
+// Arguments: [pms] -- pointer to object to be deleted
+//
+// Returns: S_OK.
+//
+// Modifies: Deletes the object pointed to by pMultiStream
+//
+// Algorithm: Delete the passed in pointer.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+void DllReleaseMultiStream(CMStream MSTREAM_NEAR *pms)
+{
+ msfDebugOut((DEB_TRACE,"In DllReleaseMultiStream(%p)\n",pms));
+ delete pms;
+ msfDebugOut((DEB_TRACE,"Out DllReleaseMultiStream()\n"));
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllIsMultiStream
+//
+// Synopsis: Check a given Lstream to determine if it is a valid
+// multistream.
+//
+// Arguments: [plst] -- Pointer to lstream to check
+//
+// Returns: S_OK if lstream is a valid multistream
+// STG_E_UNKNOWN otherwise
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE DllIsMultiStream(ILockBytes *plst)
+{
+ SCODE sc;
+ CMSFHeader *phdr;
+
+ msfMem(phdr = new CMSFHeader(SECTORSHIFT));
+
+ ULONG ulTemp;
+
+ ULARGE_INTEGER ulOffset;
+ ULISet32(ulOffset, 0);
+ msfHChk(plst->ReadAt(ulOffset, phdr, sizeof(CMSFHeader), &ulTemp));
+
+ if (ulTemp != sizeof(CMSFHeader))
+ {
+ msfErr(Err, STG_E_UNKNOWN);
+ }
+
+ msfChk(phdr->Validate());
+
+Err:
+ delete phdr;
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllSetCommitSig
+//
+// Synopsis: Set the commit signature on a given lstream, for use
+// in OnlyIfCurrent support
+//
+// Arguments: [plst] -- Pointer to the LStream to modify.
+// [sig] -- New signature
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE DllSetCommitSig(ILockBytes *plst, DFSIGNATURE sig)
+{
+ SCODE sc;
+ CMSFHeader *phdr;
+
+ msfMem(phdr = new CMSFHeader(SECTORSHIFT));
+
+ ULONG ulTemp;
+
+ ULARGE_INTEGER ulOffset;
+ ULISet32(ulOffset, 0);
+ msfHChk(plst->ReadAt(ulOffset, phdr, sizeof(CMSFHeader), &ulTemp));
+
+ if (ulTemp != sizeof(CMSFHeader))
+ {
+ msfErr(Err, STG_E_UNKNOWN);
+ }
+
+ msfChk(phdr->Validate());
+
+ phdr->SetCommitSig(sig);
+
+ msfHChk(plst->WriteAt(ulOffset, phdr, sizeof(CMSFHeader), &ulTemp));
+
+ if (ulTemp != sizeof(CMSFHeader))
+ {
+ msfErr(Err,STG_E_UNKNOWN);
+ }
+
+Err:
+ delete phdr;
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllGetCommitSig
+//
+// Synopsis: Get the commit signature from an lstream
+//
+// Arguments: [plst] -- Pointer to lstream to be operated on
+// [psig] -- Storage place for signature return
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm:
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE DllGetCommitSig(ILockBytes *plst, DFSIGNATURE *psig)
+{
+ CMSFHeader *phdr;
+ SCODE sc;
+
+ msfMem(phdr = new CMSFHeader(SECTORSHIFT));
+
+ ULONG ulTemp;
+
+ ULARGE_INTEGER ulOffset;
+ ULISet32(ulOffset, 0);
+ msfHChk(plst->ReadAt(ulOffset, phdr, sizeof(CMSFHeader), &ulTemp));
+
+ if (ulTemp != sizeof(CMSFHeader))
+ {
+ msfErr(Err, STG_E_UNKNOWN);
+ }
+ msfChk(phdr->Validate());
+ *psig = phdr->GetCommitSig();
+
+Err:
+ delete phdr;
+ return sc;
+}
+
+
+#if DEVL == 1
+
+//The following is a private function so I can set the debug level easily.
+VOID SetInfoLevel(ULONG x)
+{
+ msfInfoLevel=x;
+}
+
+#endif
diff --git a/private/ole32/stg/ref/msfhead.cxx b/private/ole32/stg/ref/msfhead.cxx
new file mode 100644
index 000000000..721976689
--- /dev/null
+++ b/private/ole32/stg/ref/msfhead.cxx
@@ -0,0 +1,20 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: msfhead.cxx
+//
+// Contents: Precompiled headers
+//
+//--------------------------------------------------------------------------
+
+
+
+#include <msf.hxx>
+#include <header.hxx>
+#include <vect.hxx>
+#include <page.hxx>
+#include <vectfunc.hxx>
+#include <fat.hxx>
+#include <dir.hxx>
diff --git a/private/ole32/stg/ref/msfiter.cxx b/private/ole32/stg/ref/msfiter.cxx
new file mode 100644
index 000000000..f536702d3
--- /dev/null
+++ b/private/ole32/stg/ref/msfiter.cxx
@@ -0,0 +1,138 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: msfiter.cxx
+//
+// Contents: Iterator code for MSF
+//
+// Classes: None. (Defined in iter.hxx)
+//
+//--------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+
+#include <dirfunc.hxx>
+#include <msfiter.hxx>
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMSFIterator::GetNext, public
+//
+// Synposis: Fill in a stat buffer for the next iteration entry
+//
+// Effects: Modifies _sidCurrent
+//
+// Arguments: [pstat] - Stat buffer
+//
+// Returns: S_OK if call completed OK.
+// STG_E_NOMOREFILES if no next entry was found.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+
+SCODE CMSFIterator::GetNext(STATSTGW *pstat)
+{
+ SCODE sc;
+ SID sidNext;
+ msfDebugOut((DEB_TRACE,"In CMSFIterator::GetNext()\n"));
+
+ if (_sidChildRoot == NOSTREAM)
+ msfChk(STG_E_NOMOREFILES);
+
+ msfChk(_pdir->FindGreaterEntry(_sidChildRoot, &_dfnCurrent, &sidNext));
+
+ // We found another child
+ CDirEntry *pde;
+
+ msfChk(_pdir->GetDirEntry(sidNext, FB_NONE, &pde));
+ pstat->type = pde->GetFlags();
+
+ //Note: The casting below assumes that DfName is always a
+ // wide character string. If we at some point in
+ // the future convert to a system where this is not
+ // true, this code needs to be updated.
+
+ msfChk(DfAllocWCS((WCHAR *)pde->GetName()->GetBuffer(), &pstat->pwcsName));
+ wcscpy(pstat->pwcsName, (WCHAR *)pde->GetName()->GetBuffer());
+
+ pstat->ctime = pde->GetTime(WT_CREATION);
+ pstat->mtime = pde->GetTime(WT_MODIFICATION);
+
+ //Don't currently keep access times
+ pstat->atime = pstat->mtime;
+
+
+ // Don't use REAL_STGTY here because we want this
+ // to function properly for both property and non-property builds
+ if ((pstat->type & STGTY_REAL) == STGTY_STORAGE)
+ {
+ ULISet32(pstat->cbSize, 0);
+ pstat->clsid = pde->GetClassId();
+ pstat->grfStateBits = pde->GetUserFlags();
+ }
+ else
+ {
+ ULISet32(pstat->cbSize, pde->GetSize());
+ pstat->clsid = CLSID_NULL;
+ pstat->grfStateBits = 0;
+ }
+
+ // update our iterator
+ _dfnCurrent.Set(pde->GetName());
+
+ _pdir->ReleaseEntry(sidNext);
+
+ msfDebugOut((DEB_TRACE,"Leaving CMSFIterator::GetNext()\n"));
+ // Fall through
+Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CMSFIterator::BufferGetNext, public
+//
+// Synopsis: Fast, fixed-size buffer version of GetNext
+// for iterations that don't care about having
+// full stat info and an allocated name
+//
+// Arguments: [pib] - Buffer to fill in
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pib]
+//
+//---------------------------------------------------------------
+
+
+SCODE CMSFIterator::BufferGetNext(SIterBuffer *pib)
+{
+ SCODE sc;
+ SID sidNext;
+ CDirEntry *pdeNext;
+
+ msfDebugOut((DEB_ITRACE, "In CMSFIterator::BufferGetNext(%p)\n", pib));
+
+ if (_sidChildRoot == NOSTREAM)
+ msfChk(STG_E_NOMOREFILES);
+
+ msfChk(_pdir->FindGreaterEntry(_sidChildRoot, &_dfnCurrent, &sidNext));
+
+ msfChk(_pdir->GetDirEntry(sidNext, FB_NONE, &pdeNext));
+ pib->type = pdeNext->GetFlags();
+ pib->dfnName = *(pdeNext->GetName());
+
+ // update our iterator
+ _dfnCurrent.Set(pdeNext->GetName());
+
+ _pdir->ReleaseEntry(sidNext);
+ msfDebugOut((DEB_ITRACE, "Out CMSFIterator::BufferGetNext\n"));
+ // Fall through
+Err:
+ return sc;
+}
diff --git a/private/ole32/stg/ref/mstream.cxx b/private/ole32/stg/ref/mstream.cxx
new file mode 100644
index 000000000..41db994c9
--- /dev/null
+++ b/private/ole32/stg/ref/mstream.cxx
@@ -0,0 +1,1006 @@
+//+-------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: mstream.cxx
+//
+// Contents: Mstream operations
+//
+// Classes: None. (defined in mstream.hxx)
+//
+//--------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+
+#include <dirfunc.hxx>
+#include <sstream.hxx>
+#include <difat.hxx>
+#include <msfiter.hxx>
+#include <time.h>
+#include <mread.hxx>
+#include <docfilep.hxx>
+
+
+#if DEVL == 1
+
+DECLARE_INFOLEVEL(msf)
+
+#endif
+
+#define MINPAGES 6
+#define MAXPAGES 12
+
+
+extern WCHAR const wcsContents[] = {'C','O','N','T','E','N','T','S','\0'};
+extern CDfName const dfnContents(wcsContents);
+
+SCODE ILBFlush(ILockBytes *pilb, BOOL fFlushCache);
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetBuffer, public
+//
+// Synopsis: Gets a chunk of memory to use as a buffer
+//
+// Arguments: [cbMin] - Minimum size for buffer
+// [cbMax] - Maximum size for buffer
+// [ppb] - Buffer pointer return
+// [pcbActual] - Actual buffer size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppb]
+// [pcbActual]
+//
+// Algorithm: Attempt to dynamically allocate [cbMax] bytes
+// If that fails, halve allocation size and retry
+// If allocation size falls below [cbMin], fail
+//
+// Notes: Buffer should be released with FreeBuffer
+//
+//----------------------------------------------------------------------------
+
+SCODE GetBuffer(USHORT cbMin, USHORT cbMax, BYTE **ppb, USHORT *pcbActual)
+{
+ USHORT cbSize;
+ BYTE *pb;
+
+ msfDebugOut((DEB_ITRACE, "In GetBuffer(%hu, %hu, %p, %p)\n",
+ cbMin, cbMax, ppb, pcbActual));
+ msfAssert(cbMin > 0);
+ msfAssert(cbMax >= cbMin);
+ msfAssert(ppb != NULL);
+ msfAssert(pcbActual != NULL);
+
+ cbSize = cbMax;
+ for (;;)
+ {
+ pb = new BYTE[cbSize];
+ if (pb == NULL)
+ {
+ cbSize >>= 1;
+ if (cbSize < cbMin)
+ break;
+ }
+ else
+ {
+ *pcbActual = cbSize;
+ break;
+ }
+ }
+
+ *ppb = pb;
+
+ msfDebugOut((DEB_ITRACE, "Out GetBuffer => %p, %hu\n", *ppb, *pcbActual));
+ return pb == NULL ? STG_E_INSUFFICIENTMEMORY : S_OK;
+}
+
+// Define the safe buffer size
+#define SCRATCHBUFFERSIZE 4096
+static BYTE s_buf[SCRATCHBUFFERSIZE];
+static LONG s_bufRef = 0;
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: GetSafeBuffer, public
+//
+// Synopsis: Gets a buffer by first trying GetBuffer and if that fails,
+// returning a pointer to statically allocated storage.
+// Guaranteed to return a pointer to some storage.
+//
+// Arguments: [cbMin] - Minimum buffer size
+// [cbMax] - Maximum buffer size
+// [ppb] - Buffer pointer return
+// [pcbActual] - Actual buffer size return
+//
+// Modifies: [ppb]
+// [pcbActual]
+//
+//----------------------------------------------------------------------------
+
+void GetSafeBuffer(USHORT cbMin, USHORT cbMax, BYTE **ppb, USHORT *pcbActual)
+{
+ msfAssert(cbMin > 0);
+ msfAssert(cbMin <= SCRATCHBUFFERSIZE &&
+ aMsg("Minimum too large for GetSafeBuffer"));
+ msfAssert(cbMax >= cbMin);
+ msfAssert(ppb != NULL);
+ msfAssert(s_bufRef == 0 &&
+ aMsg("Tried to use scratch buffer twice"));
+
+ if (cbMax <= SCRATCHBUFFERSIZE ||
+ FAILED(GetBuffer(cbMin, cbMax, ppb, pcbActual)))
+ {
+ s_bufRef = 1;
+ *ppb = s_buf;
+ *pcbActual = min(cbMax, SCRATCHBUFFERSIZE);
+ }
+ msfAssert(*ppb != NULL);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: FreeBuffer, public
+//
+// Synopsis: Releases a buffer allocated by GetBuffer or GetSafeBuffer
+//
+// Arguments: [pb] - Buffer
+//
+//----------------------------------------------------------------------------
+
+void FreeBuffer(BYTE *pb)
+{
+ if (pb == s_buf)
+ {
+ msfAssert((s_bufRef == 1) && aMsg("Bad safe buffer ref count"));
+ s_bufRef = 0;
+ }
+ else
+ delete [] pb;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::CMStream, public
+//
+// Synopsis: CMStream constructor
+//
+// Arguments: [pplstParent] -- Pointer to ILockBytes pointer of parent
+// [plGen] -- Pointer to LUID Generator to use.
+// Note: May be NULL, in which case a new
+// [uSectorShift] -- Sector shift for this MStream
+//
+//--------------------------------------------------------------------------
+
+
+MSTREAM_NEAR CMStream::CMStream(
+ ILockBytes **pplstParent,
+ USHORT uSectorShift)
+:_uSectorShift(uSectorShift),
+ _uSectorSize(1 << uSectorShift),
+ _uSectorMask(_uSectorSize - 1),
+ _pplstParent(pplstParent),
+ _hdr(uSectorShift),
+ _fatDif(1 << uSectorShift),
+ _fat(SIDFAT, 1 << uSectorShift, uSectorShift),
+ _dir(1 << uSectorShift),
+ _fatMini(SIDMINIFAT, 1 << uSectorShift, uSectorShift)
+{
+
+ _pdsministream = NULL;
+ _pmpt = NULL;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::InitCommon, private
+//
+// Synopsis: Common code for initialization routines.
+//
+// Arguments: None.
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: *Finish This*
+//
+//--------------------------------------------------------------------------
+
+SCODE MSTREAM_NEAR CMStream::InitCommon(VOID)
+{
+ msfDebugOut((DEB_ITRACE,"In CMStream InitCommon()\n"));
+ SCODE sc = S_OK;
+
+ msfMem(_pmpt = new CMSFPageTable(this, MINPAGES, MAXPAGES));
+ msfChk(_pmpt->Init());
+
+
+ msfDebugOut((DEB_ITRACE,"Leaving CMStream InitCommon()\n"));
+
+Err:
+ return sc;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::Empty, public
+//
+// Synopsis: Empty all of the control structures of this CMStream
+//
+// Arguments: None.
+//
+// Returns: void.
+//
+//----------------------------------------------------------------------------
+
+
+void CMStream::Empty(void)
+{
+ _fat.Empty();
+ _fatMini.Empty();
+ _fatDif.Empty();
+ _dir.Empty();
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::~CMStream, public
+//
+// Synopsis: CMStream destructor
+//
+//--------------------------------------------------------------------------
+
+MSTREAM_NEAR CMStream::~CMStream()
+{
+
+ msfDebugOut((DEB_ITRACE,"In CMStream destructor\n"));
+
+
+ if (_pdsministream != NULL)
+ {
+ _pdsministream->Release();
+ }
+
+ if (_pmpt != NULL)
+ {
+ _pmpt->Release();
+ }
+
+ msfDebugOut((DEB_ITRACE,"Leaving CMStream destructor\n"));
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::GetIterator, public
+//
+// Synposis: Create a new iterator for a given handle.
+//
+// Effects: Creates a new CMSFIterator
+//
+// Arguments: [sidParent] -- SID of entry to iterate over
+// [ppitRetval] -- Location for return of iterator pointer
+//
+// Returns: S_OK
+//
+// Algorithm: Create new iterator with parent of 'this' and nsi as given
+// by handle.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+
+SCODE MSTREAM_NEAR CMStream::GetIterator(
+ SID const sidParent,
+ CMSFIterator **ppitRetval)
+{
+ SCODE sc;
+
+ msfDebugOut((DEB_TRACE,"In CMStream::GetIterator()\n"));
+
+ SID sidChild;
+ msfChk(_dir.GetChild(sidParent, &sidChild));
+
+ msfDebugOut((DEB_ITRACE, "Getting an iterator for SID = %lu, "
+ "sidChild is %lu\n", sidParent, sidChild));
+ msfMem(*ppitRetval = new CMSFIterator(GetDir(), sidChild));
+ msfDebugOut((DEB_TRACE,"Leaving CMStream::GetIterator()\n"));
+
+Err:
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::Init, public
+//
+// Synposis: Set up an mstream instance from an existing stream
+//
+// Effects: Modifies Fat and Directory
+//
+// Arguments: void.
+//
+// Returns: S_OK if call completed OK.
+// Error of Fat or Dir setup otherwise.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+
+SCODE MSTREAM_NEAR CMStream::Init(VOID)
+{
+ ULONG ulTemp;
+ SCODE sc;
+ ULARGE_INTEGER ulOffset;
+
+
+ msfDebugOut((DEB_ITRACE,"In CMStream::Init()\n"));
+
+
+ msfChk(InitCommon());
+
+
+ ULISet32(ulOffset, 0);
+ msfHChk((*_pplstParent)->ReadAt(ulOffset, (BYTE *)(&_hdr),
+ sizeof(CMSFHeader), &ulTemp));
+
+ _uSectorShift = _hdr.GetSectorShift();
+ _uSectorSize = 1 << _uSectorShift;
+ _uSectorMask = _uSectorSize - 1;
+
+ if (ulTemp != sizeof(CMSFHeader))
+ {
+ msfErr(Err,STG_E_INVALIDHEADER);
+ }
+
+ msfChk(_hdr.Validate());
+
+ msfChk(_fatDif.Init(this, _hdr.GetDifLength()));
+ msfChk(_fat.Init(this, _hdr.GetFatLength(), 0));
+
+ FSINDEX fsiLen;
+ msfChk(_fat.GetLength(_hdr.GetDirStart(), &fsiLen));
+ msfChk(_dir.Init(this, fsiLen));
+
+ msfChk(_fatMini.Init(this, _hdr.GetMiniFatLength(), 0));
+
+ ULONG ulSize;
+ msfChk(_dir.GetSize(SIDMINISTREAM, &ulSize));
+ msfMem(_pdsministream = new CDirectStream(MINISTREAM_LUID));
+ _pdsministream->InitSystem(this, SIDMINISTREAM, ulSize);
+
+ msfDebugOut((DEB_TRACE,"Out CMStream::Init()\n"));
+
+Err:
+ return sc;
+}
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::InitNew, public
+//
+// Synposis: Set up a brand new mstream instance
+//
+// Effects: Modifies FAT and Directory
+//
+// Arguments: [fDelay] -- If TRUE, then the parent LStream
+// will be truncated at the time of first
+// entrance to COW, and no writes to the
+// LStream will happen before then.
+//
+// Returns: S_OK if call completed OK.
+//
+//---------------------------------------------------------------------------
+
+SCODE CMStream::InitNew(VOID)
+{
+ SCODE sc;
+
+ msfDebugOut((DEB_ITRACE,"In CMStream::InitNew()\n"));
+
+
+ msfChk(InitCommon());
+
+ ULARGE_INTEGER ulTmp;
+
+ ULISet32(ulTmp, 0);
+ (*_pplstParent)->SetSize(ulTmp);
+
+ msfChk(_fatDif.InitNew(this));
+ msfChk(_fat.InitNew(this));
+ msfChk(_dir.InitNew(this));
+
+ msfChk(_fatMini.InitNew(this));
+
+ ULONG ulSize;
+ msfChk(_dir.GetSize(SIDMINISTREAM, &ulSize));
+
+ msfMem(_pdsministream = new CDirectStream(MINISTREAM_LUID));
+ _pdsministream->InitSystem(this, SIDMINISTREAM, ulSize);
+
+
+ msfChk(Flush(0));
+
+
+ msfDebugOut((DEB_TRACE,"Out CMStream::InitNew()\n"));
+ return S_OK;
+
+Err:
+ Empty();
+
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::ConvertILB, private
+//
+// Synopsis: Copy the first sector of the underlying ILockBytes
+// out to the end.
+//
+// Arguments: [sectMax] -- Total number of sectors in the ILockBytes
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+SCODE MSTREAM_NEAR CMStream::ConvertILB(SECT sectMax)
+{
+ SCODE sc;
+ BYTE *pb;
+ USHORT cbNull;
+
+ GetSafeBuffer(GetSectorSize(), GetSectorSize(), &pb, &cbNull);
+
+ ULONG ulTemp;
+
+ ULARGE_INTEGER ulTmp;
+ ULISet32(ulTmp, 0);
+
+ msfHChk((*_pplstParent)->ReadAt(ulTmp, pb, GetSectorSize(), &ulTemp));
+
+ ULARGE_INTEGER ulNewPos;
+ ULISet32(ulNewPos, sectMax << GetSectorShift());
+
+ msfDebugOut((DEB_ITRACE,"Copying first sector out to %lu\n",
+ ULIGetLow(ulNewPos)));
+
+ msfHChk((*_pplstParent)->WriteAt(
+ ulNewPos,
+ pb,
+ GetSectorSize(),
+ &ulTemp));
+
+Err:
+ FreeBuffer(pb);
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::InitConvert, public
+//
+// Synopsis: Init function used in conversion of files to multi
+// streams.
+//
+// Arguments: [fDelayConvert] -- If true, the actual file is not
+// touched until a BeginCopyOnWrite()
+//
+// Returns: S_OK if everything completed OK.
+//
+// Algorithm: *Finish This*
+//
+// Notes: We are allowed to fail here in low memory
+//
+//--------------------------------------------------------------------------
+
+SCODE CMStream::InitConvert(VOID)
+{
+ ULONG sc;
+
+ SECT sectMax;
+
+
+ msfChk(InitCommon());
+
+ STATSTG stat;
+ (*_pplstParent)->Stat(&stat, STATFLAG_NONAME);
+ msfAssert(ULIGetHigh(stat.cbSize) == 0);
+ msfDebugOut((DEB_ITRACE,"Size is: %lu\n",ULIGetLow(stat.cbSize)));
+
+
+ sectMax = (ULIGetLow(stat.cbSize) + GetSectorSize() - 1) >>
+ GetSectorShift();
+
+ SECT sectMaxMini;
+ BOOL fIsMini;
+ fIsMini = FALSE;
+
+ //If the CONTENTS stream will be in the Minifat, compute
+ // the number of Minifat sectors needed.
+ if (ULIGetLow(stat.cbSize) < MINISTREAMSIZE)
+ {
+ sectMaxMini = (ULIGetLow(stat.cbSize) + MINISECTORSIZE - 1) >>
+ MINISECTORSHIFT;
+ fIsMini = TRUE;
+ }
+
+
+ msfChk(_fatDif.InitConvert(this, sectMax));
+ msfChk(_fat.InitConvert(this, sectMax));
+ msfChk(_dir.InitNew(this));
+ msfChk(fIsMini ? _fatMini.InitConvert(this, sectMaxMini)
+ : _fatMini.InitNew(this));
+
+
+ SID sid;
+
+ msfChk(CreateEntry(SIDROOT, &dfnContents, STGTY_STREAM, &sid));
+ msfChk(_dir.SetSize(sid, ULIGetLow(stat.cbSize)));
+
+ if (!fIsMini)
+ msfChk(_dir.SetStart(sid, sectMax - 1));
+ else
+ {
+ msfChk(_dir.SetStart(sid, 0));
+ msfChk(_dir.SetStart(SIDMINISTREAM, sectMax - 1));
+ msfChk(_dir.SetSize(SIDMINISTREAM, ULIGetLow(stat.cbSize)));
+ }
+
+ ULONG ulMiniSize;
+ msfChk(_dir.GetSize(SIDMINISTREAM, &ulMiniSize));
+
+ msfMem(_pdsministream = new CDirectStream(MINISTREAM_LUID));
+
+ _pdsministream->InitSystem(this, SIDMINISTREAM, ulMiniSize);
+
+ msfChk(ConvertILB(sectMax));
+
+ msfChk(Flush(0));
+
+ return S_OK;
+
+Err:
+ Empty();
+
+ return sc;
+}
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::GetName, public
+//
+// Synopsis: Given a handle, return the current name of that entry
+//
+// Arguments: [sid] -- SID to find name for.
+//
+// Returns: Pointer to name.
+//
+//--------------------------------------------------------------------------
+
+
+SCODE MSTREAM_NEAR CMStream::GetName(SID const sid, CDfName *pdfn)
+{
+ return _dir.GetName(sid, pdfn);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CMStream::FlushHeader, public
+//
+// Synopsis: Flush the header to the LStream.
+//
+// Arguments: [uForce] -- Flag to determine if header should be
+// flushed while in copy on write mode.
+//
+// Returns: S_OK if call completed OK.
+// S_OK if the MStream is in copy on write mode or
+// is Unconverted and the header was not flushed.
+//
+// Algorithm: Write the complete header out to the 0th position of
+// the LStream.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE MSTREAM_NEAR CMStream::FlushHeader(USHORT uForce)
+{
+ ULONG ulTemp;
+ SCODE sc;
+
+ msfDebugOut((DEB_ITRACE,"In CMStream::FlushHeader()\n"));
+
+
+ ULARGE_INTEGER ulOffset;
+ ULISet32(ulOffset, 0);
+ sc = DfGetScode((*_pplstParent)->WriteAt(ulOffset, (BYTE *)(&_hdr),
+ sizeof(CMSFHeader), &ulTemp));
+ msfDebugOut((DEB_ITRACE,"Out CMStream::FlushHeader()\n"));
+ return sc;
+}
+
+
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CMStream::MWrite, public
+//
+// Synposis: Do multiple sector writes
+//
+// Effects: Causes multiple stream writes. Modifies fat and directory
+//
+// Arguments: [ph] -- Handle of stream doing write
+// [start] -- Starting sector to write
+// [oStart] -- offset into sector to begin write at
+// [end] -- Last sector to write
+// [oEnd] -- offset into last sector to write to
+// [buffer] -- Pointer to buffer into which data will be written
+// [ulRetVal] -- location to return number of bytes written
+//
+// Returns: Error code of any failed call to parent write
+// S_OK if call completed OK.
+//
+// Modifies: ulRetVal returns the number of bytes written
+//
+// Algorithm: Using a segment table, perform writes on parent stream
+// until call is completed.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+
+
+SCODE MSTREAM_NEAR CMStream::MWrite(
+ SID sid,
+ BOOL fIsMini,
+ ULONG ulOffset,
+ VOID const HUGEP *pvBuffer,
+ ULONG ulCount,
+ CStreamCache *pstmc,
+ ULONG *pulRetval)
+{
+ SCODE sc;
+ BYTE const HUGEP *pbBuffer = (BYTE const HUGEP *) pvBuffer;
+
+ USHORT cbSector = GetSectorSize();
+ CFat *pfat = &_fat;
+ USHORT uShift = GetSectorShift();
+ ULONG ulLastBytes = 0;
+
+ ULARGE_INTEGER ulOff;
+ ULISetHigh(ulOff, 0);
+
+ ULONG ulOldSize = 0;
+
+ // Check if it's a small stream and whether this is a real or
+ // scratch multistream.
+
+ if ((fIsMini) &&
+ (SIDMINISTREAM != sid))
+ {
+ msfAssert(sid <= MAXREGSID &&
+ aMsg("Invalid SID in MWrite"));
+ // This stream is stored in the ministream
+
+ cbSector = MINISECTORSIZE;
+ uShift = MINISECTORSHIFT;
+ pfat = GetMiniFat();
+ }
+
+ USHORT uMask = cbSector - 1;
+
+ SECT start = (SECT)(ulOffset >> uShift);
+ OFFSET oStart = (OFFSET)(ulOffset & uMask);
+
+ SECT end = (SECT)((ulOffset + ulCount - 1) >> uShift);
+ OFFSET oEnd = (OFFSET)((ulOffset + ulCount - 1) & uMask);
+
+ msfDebugOut((DEB_ITRACE,"In CMStream::MWrite(%lu,%u,%lu,%u)\n",
+ start,oStart,end,oEnd));
+
+ ULONG bytecount;
+ ULONG total = 0;
+
+ msfChk(_dir.GetSize(sid, &ulOldSize));
+
+
+
+ msfAssert(end != 0xffffffffL);
+
+ if (end < start)
+ {
+ *pulRetval = total + ulLastBytes;
+ goto Err;
+ }
+
+ ULONG ulRunLength;
+ ulRunLength = end - start + 1;
+ SECT sectSidStart;
+
+ USHORT offset;
+ offset = oStart;
+
+ while (TRUE)
+ {
+ SSegment segtab[CSEG + 1];
+ SECT sect;
+
+ if (start > pstmc->GetOffset())
+ {
+ msfChk(pfat->GetESect(
+ pstmc->GetSect(),
+ start - pstmc->GetOffset(),
+ &sect));
+ }
+ else if (start == pstmc->GetOffset())
+ {
+ sect = pstmc->GetSect();
+ }
+ else
+ {
+ msfChk(_dir.GetStart(sid, &sectSidStart));
+ msfChk(pfat->GetESect(sectSidStart, start, &sect));
+ }
+
+ msfChk(pfat->Contig(
+ (SSegment STACKBASED *) segtab,
+ sect,
+ ulRunLength));
+
+ USHORT oend = cbSector - 1;
+ ULONG i;
+ SECT sectStart;
+ for (USHORT iseg = 0; iseg < CSEG;)
+ {
+ sectStart = segtab[iseg].sectStart;
+ i = segtab[iseg].cSect;
+ ulRunLength -= i;
+ start += i;
+
+ iseg++;
+ if (segtab[iseg].sectStart == ENDOFCHAIN)
+ oend = oEnd;
+
+ ULONG ulSize = ((i - 1) << uShift) - offset + oend + 1;
+
+ msfDebugOut((
+ DEB_ITRACE,
+ "Calling lstream WriteAt(%lu,%p,%lu)\n",
+ ConvertSectOffset(sectStart,offset,uShift),
+ pbBuffer,
+ ulSize));
+
+ if (GetMiniFat() == pfat)
+ {
+ sc = _pdsministream->CDirectStream::WriteAt(
+ (sectStart << uShift) + offset,
+ pbBuffer, ulSize,
+ (ULONG STACKBASED *)&bytecount);
+ }
+ else
+ {
+ ULISetLow(ulOff, ConvertSectOffset(sectStart, offset,
+ uShift));
+ sc = DfGetScode((*_pplstParent)->WriteAt(ulOff, pbBuffer,
+ ulSize, &bytecount));
+ }
+
+ total += bytecount;
+
+ //Check if this write is the last one in the stream,
+ // and that the stream ends as a partial sector.
+ //If so, fill out the remainder of the sector with
+ // something.
+ if ((0 == ulRunLength) && (total + ulOffset > ulOldSize) &&
+ (((total + ulOffset) & (GetSectorSize() - 1)) != 0))
+ {
+ //This is the last sector and the stream has grown.
+ ULONG csectOld = (ulOldSize + GetSectorSize() - 1) >>
+ GetSectorShift();
+
+ ULONG csectNew = (total + ulOffset + GetSectorSize() - 1) >>
+ GetSectorShift();
+
+ if (csectNew > csectOld)
+ {
+ msfAssert(!fIsMini &&
+ aMsg("Small stream grew in MWrite"));
+
+ SECT sectLast = sectStart + i - 1;
+
+ msfVerify(SUCCEEDED(SecureSect(
+ sectLast,
+ total + ulOffset,
+ FALSE)));
+ }
+ }
+
+ if (0 == ulRunLength || FAILED(sc))
+ {
+ break;
+ }
+
+ pbBuffer = pbBuffer + bytecount;
+ offset = 0;
+ }
+
+ pstmc->SetCache(start -1, sectStart + i - 1);
+
+ if (0 == ulRunLength || FAILED(sc))
+ {
+ *pulRetval = total + ulLastBytes;
+ msfDebugOut((
+ DEB_TRACE,
+ "Out CMStream::MWrite()=>%lu, retval = %lu\n",
+ sc,
+ total));
+ break;
+ }
+ }
+
+ Err:
+ // We need this flush of the directory structures because we may have
+ // remapped the first sector in a chain.
+
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::Flush, public
+//
+// Synopsis: Flush control structures.
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+
+SCODE CMStream::Flush(BOOL fFlushCache)
+{
+ SCODE sc = S_OK;
+
+ msfChk(_dir.Flush());
+ msfChk(_fatMini.Flush());
+ msfChk(_fat.Flush());
+ msfChk(_fatDif.Flush());
+
+ msfChk(FlushHeader(HDR_NOFORCE));
+ msfChk(ILBFlush(*_pplstParent, fFlushCache));
+Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: ILBFlush
+//
+// Synopsis: Flush as thoroughly as possible
+//
+// Effects: Flushes ILockBytes
+//
+// Arguments: [pilb] - ILockBytes to flush
+// [fFlushCache] - Flush thoroughly iff TRUE
+//
+// Returns: SCODE
+//
+// Algorithm:
+//
+//--------------------------------------------------------------------------
+
+SCODE ILBFlush(ILockBytes *pilb, BOOL fFlushCache)
+{
+ SCODE sc;
+
+ msfDebugOut((DEB_ITRACE, "In ILBFlushCache(%p)\n", pilb));
+
+ sc = DfGetScode(pilb->Flush());
+
+ msfDebugOut((DEB_ITRACE, "Out ILBFlushCache()\n"));
+
+ return(sc);
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMStream::SecureSect, public
+//
+// Synopsis: Zero out the unused portion of a sector
+//
+// Arguments: [sect] -- Sector to zero out
+// [ulSize] -- Size of stream
+// [fIsMini] -- TRUE if stream is in ministream
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE CMStream::SecureSect(
+ const SECT sect,
+ const ULONG ulSize,
+ const BOOL fIsMini)
+{
+ SCODE sc = S_OK;
+ BYTE *pb = NULL;
+
+ ULONG cbSect = fIsMini ? MINISECTORSIZE : GetSectorSize();
+
+ msfAssert(ulSize != 0);
+
+ ULONG ulOffset = ((ulSize - 1) % cbSect) + 1;
+
+ ULONG cb = cbSect - ulOffset;
+
+ msfAssert(cb != 0);
+
+ //We can use any initialized block of memory here. The header
+ // is available and is the correct size, so we use that.
+ pb = (BYTE *)&_hdr;
+
+ ULONG cbWritten;
+
+ if (!fIsMini)
+ {
+ ULARGE_INTEGER ulOff;
+ ULISet32(ulOff, ConvertSectOffset(
+ sect,
+ ulOffset,
+ GetSectorShift()));
+
+ msfChk(DfGetScode((*_pplstParent)->WriteAt(
+ ulOff,
+ pb,
+ cb,
+ &cbWritten)));
+ }
+ else
+ {
+ msfChk(_pdsministream->WriteAt(
+ (sect << MINISECTORSHIFT) + ulOffset,
+ pb,
+ cb,
+ (ULONG STACKBASED *)&cbWritten));
+ }
+
+ if (cbWritten != cb)
+ {
+ sc = STG_E_WRITEFAULT;
+ }
+
+Err:
+
+ return sc;
+}
diff --git a/private/ole32/stg/ref/page.cxx b/private/ole32/stg/ref/page.cxx
new file mode 100644
index 000000000..eee29034e
--- /dev/null
+++ b/private/ole32/stg/ref/page.cxx
@@ -0,0 +1,554 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: page.cxx
+//
+// Contents: Paging code for MSF
+//
+// Classes: Defined in page.hxx
+//
+// Functions:
+//
+//----------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+
+
+#include <mread.hxx>
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::CMSFPageTable, public
+//
+// Synopsis: CMSFPageTable constructor.
+//
+// Arguments: [pmsParent] -- Pointer to multistream for this page table.
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+CMSFPageTable::CMSFPageTable(
+ CMStream MSTREAM_NEAR *const pmsParent,
+ const ULONG cMinPages,
+ const ULONG cMaxPages)
+ : _pmsParent(pmsParent), _cActivePages(0), _cPages(0),
+ _pmpCurrent(NULL),
+ _cbSector(pmsParent->GetSectorSize()),
+ _cMinPages(cMinPages), _cMaxPages(cMaxPages),
+ _cReferences(1)
+
+{
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPage::CMSFPage, public
+//
+// Synopsis: CMSFPage default constructor
+//
+//----------------------------------------------------------------------------
+
+CMSFPage::CMSFPage(CMSFPage *pmp)
+{
+ if (pmp == NULL)
+ {
+ SetChain(this, this);
+ }
+ else
+ {
+ SetChain(pmp->GetPrev(), pmp);
+ GetPrev()->SetNext(this);
+ GetNext()->SetPrev(this);
+ }
+
+ SetSid(NOSTREAM);
+ SetOffset(0);
+ SetSect(ENDOFCHAIN);
+ SetFlags(0);
+ SetVector(NULL);
+ _cReferences = 0;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::~CMSFPageTable, public
+//
+// Synopsis: CMSFPageTable destructor
+//
+//----------------------------------------------------------------------------
+
+CMSFPageTable::~CMSFPageTable()
+{
+ if (_pmpCurrent != NULL)
+ {
+ CMSFPage *pmp = _pmpCurrent;
+ CMSFPage *pmpNext;
+
+ while (pmp != pmp->GetNext())
+ {
+ pmpNext = pmp->GetNext();
+#if DBG == 1
+ msfAssert(!pmp->IsInUse() &&
+ aMsg("Active page left at page table destruct time."));
+
+#endif
+ delete pmp;
+ pmp = pmpNext;
+ }
+ delete pmp;
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::Init, public
+//
+// Synopsis: Initialize a CMSFPageTable
+//
+// Arguments: [cPages] -- Number of pages to preallocate.
+//
+// Returns: Appropriate status code
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE CMSFPageTable::Init(void)
+{
+ SCODE sc = S_OK;
+
+ msfDebugOut((DEB_ITRACE, "In CMSFPageTable::Init:%p()\n", this));
+
+ for (ULONG i = 0; i < _cMinPages; i++)
+ {
+ CMSFPage *pmp;
+
+ msfMem(pmp = GetNewPage());
+ _pmpCurrent = pmp;
+ }
+ _cPages = _cMinPages;
+ _cActivePages = 0;
+
+ msfDebugOut((DEB_ITRACE, "Out CMSFPageTable::Init\n"));
+
+ Err:
+
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::FlushPage, public
+//
+// Synopsis: Flush a page
+//
+// Arguments: [pmp] -- Pointer to page to flush
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+SCODE CMSFPageTable::FlushPage(CMSFPage *pmp)
+{
+ SCODE sc = S_OK;
+
+ pmp->AddRef();
+
+ CMStream *pms;
+ pms = pmp->GetVector()->GetParent();
+
+ //Flush the page, reset the dirty bit.
+
+ msfAssert((pmp->GetSect() != ENDOFCHAIN) &&
+ aMsg("Page location not set - don't know where to flush to."));
+
+ ULONG ulRet;
+
+ ILockBytes *pilb;
+ ULARGE_INTEGER ul;
+ ULISet32(ul, ConvertSectOffset(
+ pmp->GetSect(),
+ 0,
+ pms->GetSectorShift()));
+
+ pilb = pms->GetILB();
+
+
+ msfHChk(pilb->WriteAt(
+ ul,
+ (BYTE *)(pmp->GetData()),
+ _cbSector,
+ &ulRet));
+
+ pmp->ResetDirty();
+
+ Err:
+ pmp->Release();
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::GetFreePage, public
+//
+// Synopsis: Return a pointer to a free page.
+//
+// Arguments: [ppmp] -- Pointer to storage for return pointer
+//
+// Returns: Appropriate status code
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE CMSFPageTable::GetFreePage(CMSFPage **ppmp)
+{
+ SCODE sc = S_OK;
+ CMSFPage *pmp;
+ if (_cPages > _cActivePages)
+ {
+ //We have some unused page already allocated. Find and return it.
+ pmp = _pmpCurrent;
+
+ do
+ {
+ pmp = pmp->GetNext();
+ }
+ while ((pmp != _pmpCurrent) && (pmp->GetSid() != NOSTREAM));
+
+ msfAssert((pmp->GetSid() == NOSTREAM) &&
+ aMsg("Expected empty page, none found."));
+
+ *ppmp = pmp;
+ _cActivePages++;
+ }
+ else if (_cPages == _cMaxPages)
+ {
+ msfMem(pmp = FindSwapPage());
+ msfDebugOut((DEB_IERROR, "Got swap page %p\n",pmp));
+
+ msfAssert((pmp->GetVector() != NULL) &&
+ aMsg("FindSwapPage returned unowned page."));
+
+ msfDebugOut((DEB_IERROR, "Freeing page %lu from vector %p\n",
+ pmp->GetOffset(), pmp->GetVector()));
+
+
+ if (pmp->IsDirty())
+ {
+ msfChk(FlushPage(pmp));
+ msfAssert(!pmp->IsDirty() &&
+ aMsg("Page remained dirty after flush call"));
+ }
+
+ pmp->GetVector()->FreeTable(pmp->GetOffset());
+#if DBG == 1
+ pmp->SetVector(NULL);
+#endif
+ *ppmp = pmp;
+ }
+ else
+ {
+ //Create a new page and return it.
+ pmp = GetNewPage();
+ if (pmp != NULL)
+ {
+ *ppmp = pmp;
+ _cActivePages++;
+ _cPages++;
+ }
+ else
+ {
+ msfMem(pmp = FindSwapPage());
+ if (pmp->IsDirty())
+ {
+ msfChk(FlushPage(pmp));
+ msfAssert(!pmp->IsDirty() &&
+ aMsg("Page remained dirty after flush call"));
+ }
+ pmp->GetVector()->FreeTable(pmp->GetOffset());
+#if DBG == 1
+ pmp->SetVector(NULL);
+#endif
+ *ppmp = pmp;
+ }
+ }
+
+ Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::FindPage, public
+//
+// Synopsis: Find and return a given page
+//
+// Arguments: [ppv] -- Pointer to vector of page to return
+// [sid] -- SID of page to return
+// [ulOffset] -- Offset of page to return
+// [ppmp] -- Location to return pointer
+//
+// Returns: Appropriate status code
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE CMSFPageTable::FindPage(
+ CPagedVector *ppv,
+ SID sid,
+ ULONG ulOffset,
+ CMSFPage **ppmp)
+{
+ SCODE sc;
+ CMSFPage *pmp = _pmpCurrent;
+
+ do
+ {
+ if ((pmp->GetVector() == ppv) && (pmp->GetOffset() == ulOffset))
+ {
+ //Bingo!
+
+ *ppmp = pmp;
+ return STG_S_FOUND;
+ }
+
+ pmp = pmp->GetNext();
+ }
+ while (pmp != _pmpCurrent);
+
+ //The page isn't currently in memory. Get a free page and
+ //bring it into memory.
+
+ msfChk(GetFreePage(&pmp));
+
+ msfAssert((pmp->GetVector() == NULL) &&
+ aMsg("Attempting to reassign owned page."));
+ pmp->SetVector(ppv);
+ pmp->SetSid(sid);
+ pmp->SetOffset(ulOffset);
+ pmp->SetSect(ENDOFCHAIN);
+
+ *ppmp = pmp;
+
+ Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::GetPage, public
+//
+// Synopsis: Find and return a given page
+//
+// Arguments: [sid] -- SID of page to return
+// [ulOffset] -- Offset of page to return
+// [ppmp] -- Location to return pointer
+//
+// Returns: Appropriate status code
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE CMSFPageTable::GetPage(
+ CPagedVector *ppv,
+ SID sid,
+ ULONG ulOffset,
+ CMSFPage **ppmp)
+{
+ SCODE sc;
+
+ *ppmp = NULL;
+ msfChk(FindPage(ppv, sid, ulOffset, ppmp));
+
+ (*ppmp)->AddRef();
+
+ if (sc != STG_S_FOUND)
+ {
+ ULONG ulRet;
+ SECT sect;
+
+ msfChk(ppv->GetParent()->GetSect(sid, ulOffset, &sect));
+ (*ppmp)->SetSect(sect);
+
+ CMStream *pms = (*ppmp)->GetVector()->GetParent();
+
+ ULARGE_INTEGER ul;
+ ULISet32(ul, ConvertSectOffset(
+ (*ppmp)->GetSect(),
+ 0,
+ pms->GetSectorShift()));
+
+ msfAssert(pms->GetILB() != NULL &&
+ aMsg("NULL ILockBytes - missing SetAccess?"));
+
+ msfHChk(pms->GetILB()->ReadAt(ul, (BYTE *)((*ppmp)->GetData()),
+ _cbSector, &ulRet));
+ }
+
+ Err:
+ if (*ppmp != NULL)
+ {
+ (*ppmp)->Release();
+ }
+
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::ReleasePage, public
+//
+// Synopsis: Release a given page
+//
+// Arguments: [sid] -- SID of page to release
+// [ulOffset] -- Offset of page to release
+//
+//----------------------------------------------------------------------------
+
+void CMSFPageTable::ReleasePage(CPagedVector *ppv, SID sid, ULONG ulOffset)
+{
+ SCODE sc;
+ CMSFPage *pmp;
+
+ sc = FindPage(ppv, sid, ulOffset, &pmp);
+
+ if (SUCCEEDED(sc))
+ {
+ pmp->Release();
+ }
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::Flush, public
+//
+// Synopsis: Flush dirty pages to disk
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+SCODE CMSFPageTable::Flush(void)
+{
+ SCODE sc = S_OK;
+
+ CMSFPage *pmp = _pmpCurrent;
+
+ //We use pmpLast in case FlushPage changes _pmpCurrent.
+ CMSFPage *pmpLast = _pmpCurrent;
+
+ do
+ {
+ if ((pmp->IsDirty()) && !(pmp->IsInUse()))
+ {
+ msfChk(FlushPage(pmp));
+ }
+
+ pmp = pmp->GetNext();
+
+ }
+ while (pmp != pmpLast);
+
+ Err:
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::FreePages, public
+//
+// Synopsis: Free all the pages associated with a vector.
+//
+// Arguments: [ppv] -- Pointer to vector to free pages for.
+//
+//----------------------------------------------------------------------------
+
+void CMSFPageTable::FreePages(CPagedVector *ppv)
+{
+ CMSFPage *pmp = _pmpCurrent;
+
+ do
+ {
+ if (pmp->GetVector() == ppv)
+ {
+ pmp->SetSid(NOSTREAM);
+ pmp->SetVector(NULL);
+ pmp->ResetDirty();
+ _cActivePages--;
+ }
+ pmp = pmp->GetNext();
+ }
+ while (pmp != _pmpCurrent);
+
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CMSFPageTable::FindSwapPage, private
+//
+// Synopsis: Find a page to swap out.
+//
+// Arguments: None.
+//
+// Returns: Pointer to page to swap out.
+//
+//----------------------------------------------------------------------------
+
+CMSFPage * CMSFPageTable::FindSwapPage(void)
+{
+#if DBG == 1
+ ULONG cpInUse = 0;
+#endif
+
+ while (TRUE)
+ {
+ if (!_pmpCurrent->IsInUse())
+ {
+ DWORD dwFlags;
+
+ dwFlags = _pmpCurrent->GetFlags();
+ _pmpCurrent->SetFlags(dwFlags & ~FB_TOUCHED);
+ _pmpCurrent = _pmpCurrent->GetNext();
+
+ if (!(dwFlags & FB_TOUCHED))
+ {
+ return _pmpCurrent->GetPrev();
+ }
+ }
+ else
+ {
+ _pmpCurrent = _pmpCurrent->GetNext();
+ }
+#if DBG == 1
+ cpInUse++;
+ msfAssert((cpInUse < 3 * _cPages) &&
+ aMsg("No swappable pages."));
+#endif
+
+ }
+}
+
+
+
diff --git a/private/ole32/stg/ref/pbstream.cxx b/private/ole32/stg/ref/pbstream.cxx
new file mode 100644
index 000000000..966fc1407
--- /dev/null
+++ b/private/ole32/stg/ref/pbstream.cxx
@@ -0,0 +1,221 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: pbstream.cxx
+//
+// Contents: CPubStream code
+//
+// Classes:
+//
+// Functions:
+//
+//--------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+
+#include <sstream.hxx>
+#include <publicdf.hxx>
+#include <pbstream.hxx>
+#include <docfilep.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubStream::CPubStream, public
+//
+// Synopsis: Constructor
+//
+//----------------------------------------------------------------------------
+
+CPubStream::CPubStream(CPubDocFile *ppdf,
+ DFLAGS df,
+ CDfName const *pdfn)
+{
+ _psParent = NULL;
+ _df = df;
+ _ppdfParent = ppdf;
+ _cReferences = 1;
+ _dfn.Set(pdfn->GetLength(), pdfn->GetBuffer());
+ _ppdfParent->AddChild(this);
+ _fDirty = FALSE;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubStream::Init, public
+//
+// Synopsis: Init function
+//
+// Arguments: [psParent] - Stream in transaction set
+// [dlLUID] - LUID
+//
+//----------------------------------------------------------------------------
+
+void CPubStream::Init(PSStream *psParent,
+ DFLUID dlLUID)
+{
+ _psParent = psParent;
+ _luid = dlLUID;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubStream::~CPubStream, public
+//
+// Synopsis: Destructor
+//
+//----------------------------------------------------------------------------
+
+CPubStream::~CPubStream()
+{
+ msfAssert(_cReferences == 0);
+
+ if (SUCCEEDED(CheckReverted()))
+ {
+ if (_ppdfParent != NULL)
+ _ppdfParent->ReleaseChild(this);
+ if (_psParent)
+ {
+ _psParent->Release();
+ }
+ }
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPubStream::Release, public
+//
+// Synopsis: Release a pubstream object
+//
+// Arguments: None.
+//
+// Returns: S_OK if call completed OK.
+//
+// Algorithm: Delete 'this' - all real work done by destructor.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+
+void CPubStream::vRelease(VOID)
+{
+ msfDebugOut((DEB_TRACE,"In CPubStream::Release()\n"));
+ msfAssert(_cReferences > 0);
+ AtomicDec(&_cReferences);
+
+
+ Commit(STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE);
+
+ if (_cReferences == 0)
+ {
+ delete this;
+ }
+ msfDebugOut((DEB_TRACE,"Out CPubStream::Release()\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubStream::Stat, public
+//
+// Synopsis: Fills in a stat buffer
+//
+// Arguments: [pstatstg] - Buffer
+// [grfStatFlag] - stat flags
+//
+// Returns: S_OK or error code
+//
+// Modifies: [pstatstg]
+//
+//---------------------------------------------------------------
+
+
+SCODE CPubStream::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc = S_OK;
+
+ msfDebugOut((DEB_ITRACE, "In CPubStream::Stat(%p)\n", pstatstg));
+ msfChk(CheckReverted());
+
+ msfAssert(_ppdfParent != NULL);
+ pstatstg->grfMode = DFlagsToMode(_df);
+
+ msfChk(_psParent->GetTime(WT_CREATION,&pstatstg->ctime));
+ msfChk(_psParent->GetTime(WT_MODIFICATION,&pstatstg->mtime));
+ pstatstg->atime = pstatstg->mtime;
+ pstatstg->clsid = CLSID_NULL;
+ pstatstg->grfStateBits = 0;
+
+ pstatstg->pwcsName = NULL;
+ if ((grfStatFlag & STATFLAG_NONAME) == 0)
+ {
+ msfChk(DfAllocWCS((WCHAR *)_dfn.GetBuffer(), &pstatstg->pwcsName));
+ wcscpy(pstatstg->pwcsName, (WCHAR *)_dfn.GetBuffer());
+ }
+
+ ULONG cbSize;
+ _psParent->GetSize(&cbSize);
+ ULISet32(pstatstg->cbSize, cbSize);
+ msfDebugOut((DEB_ITRACE, "Out CPubStream::Stat\n"));
+
+Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubStream::RevertFromAbove, public
+//
+// Synopsis: Parent has asked for reversion
+//
+//---------------------------------------------------------------
+
+
+void CPubStream::RevertFromAbove(void)
+{
+ msfDebugOut((DEB_ITRACE, "In CPubStream::RevertFromAbove:%p()\n", this));
+ _df |= DF_REVERTED;
+ _psParent->Release();
+#if DBG == 1
+ _psParent = NULL;
+#endif
+ msfDebugOut((DEB_ITRACE, "Out CPubStream::RevertFromAbove\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubStream::Commit, public
+//
+// Synopsis: Flush stream changes to disk in the direct case.
+//
+// Arguments: None
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+
+SCODE CPubStream::Commit(DWORD dwFlags)
+{
+ SCODE sc = S_OK;
+ msfDebugOut((DEB_ITRACE, "In CPubStream::Commit:%p()\n", this));
+
+ if (SUCCEEDED(CheckReverted()))
+ {
+ if (_fDirty)
+ {
+
+ // We're a stream so we must have a parent
+ // Here we dirty all parents up to the next transacted storage
+ _ppdfParent->SetDirty();
+
+
+ sc = _ppdfParent->GetBaseMS()->Flush(FLUSH_CACHE(dwFlags));
+ }
+ }
+ msfDebugOut((DEB_ITRACE, "Out CPubStream::Commit\n"));
+ return sc;
+}
diff --git a/private/ole32/stg/ref/pdffuncs.cxx b/private/ole32/stg/ref/pdffuncs.cxx
new file mode 100644
index 000000000..73848369d
--- /dev/null
+++ b/private/ole32/stg/ref/pdffuncs.cxx
@@ -0,0 +1,79 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: pdffuncs.cxx
+//
+// Contents: PDocFile static member functions
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+
+
+
+//+--------------------------------------------------------------
+//
+// Member: PDocFile::ExcludeEntries, public
+//
+// Synopsis: Excludes the given entries
+//
+// Arguments: [snbExclude] - Entries to exclude
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+SCODE PDocFile::ExcludeEntries(PDocFile *pdf,
+ SNBW snbExclude)
+{
+ PDocFileIterator *pdfi;
+ PSStream *psstChild;
+ PDocFile *pdfChild;
+ SCODE sc;
+ SIterBuffer ib;
+
+ olDebugOut((DEB_ITRACE, "In PDocFile::ExcludeEntries(%p)\n",
+ snbExclude));
+ olChk(pdf->GetIterator(&pdfi));
+ for (;;)
+ {
+ if (FAILED(pdfi->BufferGetNext(&ib)))
+ break;
+ if (NameInSNB(&ib.dfnName, snbExclude) == S_OK)
+ {
+ switch(REAL_STGTY(ib.type))
+ {
+ case STGTY_STORAGE:
+ olChkTo(EH_pwcsName, pdf->GetDocFile(&ib.dfnName, DF_READ |
+ DF_WRITE, ib.type,
+ &pdfChild));
+ olChkTo(EH_Get, pdfChild->DeleteContents());
+ pdfChild->Release();
+ break;
+ case STGTY_STREAM:
+ olChkTo(EH_pwcsName, pdf->GetStream(&ib.dfnName, DF_WRITE,
+ ib.type, &psstChild));
+ olChkTo(EH_Get, psstChild->SetSize(0));
+ psstChild->Release();
+ break;
+ }
+ }
+ }
+ pdfi->Release();
+ olDebugOut((DEB_ITRACE, "Out ExcludeEntries\n"));
+ return S_OK;
+
+EH_Get:
+ if (REAL_STGTY(ib.type))
+ pdfChild->Release();
+ else
+ psstChild->Release();
+EH_pwcsName:
+ pdfi->Release();
+EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/ref/peiter.cxx b/private/ole32/stg/ref/peiter.cxx
new file mode 100644
index 000000000..351f0b1d2
--- /dev/null
+++ b/private/ole32/stg/ref/peiter.cxx
@@ -0,0 +1,103 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: peiter.cxx
+//
+// Contents: Implementation of PExposedIterator
+//
+//----------------------------------------------------------------------------
+
+#include <exphead.cxx>
+
+#include <peiter.hxx>
+#include <pubiter.hxx>
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: PExposedIterator::hSkip, public
+//
+// Synopsis: Enumerator skip helper function
+//
+//----------------------------------------------------------------------------
+
+SCODE PExposedIterator::hSkip(ULONG celt)
+{
+ SCODE sc;
+ STATSTGW stat;
+
+ olDebugOut((DEB_ITRACE, "In PExposedIterator::hSkip:%p(%lu)\n",
+ this, celt));
+ olChk(_ppi->CheckReverted());
+ for (; celt>0; celt--)
+ {
+ sc = _ppi->Next(_ulOffset, &stat);
+ if (sc == S_FALSE)
+ break;
+ else if (FAILED(sc))
+ olErr(EH_Err, sc);
+ delete stat.pwcsName;
+ _ulOffset++;
+ }
+ olDebugOut((DEB_ITRACE, "Out PExposedIterator::hSkip\n"));
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: PExposedIterator::hRelease, public
+//
+// Synopsis: Release helper
+//
+//----------------------------------------------------------------------------
+
+LONG PExposedIterator::hRelease(void)
+{
+ LONG lRet;
+
+ olDebugOut((DEB_ITRACE, "In PExposedIterator::hRelease:%p()\n", this));
+ olAssert(_cReferences > 0);
+ lRet = AtomicDec(&_cReferences);
+ if (lRet == 0)
+ {
+ }
+ else if (lRet < 0)
+ lRet = 0;
+ olDebugOut((DEB_ITRACE, "Out PExposedIterator::hRelease\n"));
+ return S_OK;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: PExposedIterator::hQueryInterface, public
+//
+// Synopsis: QueryInterface helper
+//
+//----------------------------------------------------------------------------
+
+SCODE PExposedIterator::hQueryInterface(REFIID iid,
+ REFIID riidSelf,
+ void **ppv)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In PExposedIterator::hQueryInterface:%p("
+ "riid, riidSelf, %p)\n", this, ppv));
+ olChk(ValidateOutPtrBuffer(ppv));
+ *ppv = NULL;
+ olChk(ValidateIid(iid));
+ if (IsEqualIID(iid, riidSelf) || IsEqualIID(iid, IID_IUnknown))
+ {
+ hAddRef();
+ *ppv = this;
+ }
+ else
+ olErr(EH_Err, E_NOINTERFACE);
+ sc = S_OK;
+ olDebugOut((DEB_ITRACE, "Out PExposedIterator::hQueryInterface\n"));
+ EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/ref/peiter.hxx b/private/ole32/stg/ref/peiter.hxx
new file mode 100644
index 000000000..139867b4d
--- /dev/null
+++ b/private/ole32/stg/ref/peiter.hxx
@@ -0,0 +1,76 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: peiter.hxx
+//
+// Contents: PExposedIterator class
+//
+// Classes: PExposedIterator
+//
+// Notes: PExposedIterator is a partial exposed iterator
+// implementation used by both CExposedIterator
+// and CExposedPropertyIterator
+//
+//----------------------------------------------------------------------------
+
+#ifndef __PEITER_HXX__
+#define __PEITER_HXX__
+
+#include <pubiter.hxx>
+
+interface PExposedIterator
+{
+public:
+ SCODE hSkip(ULONG celt);
+ inline SCODE hReset(void);
+ inline LONG hAddRef(void);
+ LONG hRelease(void);
+ SCODE hQueryInterface(REFIID iid, REFIID riidSelf, void **ppv);
+
+protected:
+
+ CPubIter *_ppi;
+ ULONG _ulOffset;
+ LONG _cReferences;
+ ULONG _ulAccessLockBase;
+ ULONG _sig;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: PExposedIterator::hReset, public
+//
+// Synopsis: Reset help
+//
+//----------------------------------------------------------------------------
+
+SCODE PExposedIterator::hReset(void)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In PExposedIterator::hReset:%p()\n", this));
+ if (SUCCEEDED(sc = _ppi->CheckReverted()))
+ _ulOffset = 0;
+ olDebugOut((DEB_ITRACE, "Out PExposedIterator::hReset\n"));
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: PExposedIterator::hAddRef, public
+//
+// Synopsis: AddRef helper
+//
+//----------------------------------------------------------------------------
+
+LONG PExposedIterator::hAddRef(void)
+{
+ olDebugOut((DEB_ITRACE, "In PExposedIterator::hAddRef:%p()\n", this));
+ AtomicInc(&_cReferences);
+ olDebugOut((DEB_ITRACE, "Out PExposedIterator::hAddRef\n"));
+ return _cReferences;
+}
+
+#endif // #ifndef __PEITER_HXX__
diff --git a/private/ole32/stg/ref/pubiter.cxx b/private/ole32/stg/ref/pubiter.cxx
new file mode 100644
index 000000000..42e2aaca2
--- /dev/null
+++ b/private/ole32/stg/ref/pubiter.cxx
@@ -0,0 +1,231 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: pubiter.cxx
+//
+// Contents: CPubIter code
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+
+#include <sstream.hxx>
+#include <pubiter.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: CPubIter::CPubIter, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [pdf] - Public docfile for this iterator
+// [fProperties] - Iterate properties or not
+//
+//---------------------------------------------------------------
+
+CPubIter::CPubIter(CPubDocFile *pdf)
+{
+ olDebugOut((DEB_ITRACE, "In CPubIter::CPubIter:%p(%p)\n",
+ this, pdf));
+ _pdf = pdf;
+ _pds = NULL;
+ _cReferences = 1;
+ _df = 0;
+ _luid = ITERATOR_LUID;
+ _pdf->AddChild(this);
+ olDebugOut((DEB_ITRACE, "Out CPubIter::CPubIter\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubIter::~CPubIter, public
+//
+// Synopsis: Destructor
+//
+//---------------------------------------------------------------
+
+CPubIter::~CPubIter(void)
+{
+ olDebugOut((DEB_ITRACE, "In CPubIter::~CPubIter:%p()\n", this));
+ olAssert(_cReferences == 0);
+ if (SUCCEEDED(CheckReverted()))
+ {
+ if (_pdf)
+ {
+ _pdf->ReleaseChild(this);
+ }
+ if (_pds)
+ {
+ _pds->Release();
+ _pdf->DeleteScratchStream(&_dfnScratch);
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out CPubIter::~CPubIter\n"));
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CPubIter::Release, public
+//
+// Synopsis: Releases resources for a CPubIter
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+void CPubIter::vRelease(void)
+{
+ olDebugOut((DEB_TRACE,"In CPubIter::Release()\n"));
+ olAssert(_cReferences > 0);
+ AtomicDec(&_cReferences);
+ if (_cReferences == 0)
+ delete this;
+ olDebugOut((DEB_TRACE,"Out CPubIter::Release()\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubIter::Next, public
+//
+// Synopsis: Returns the iteration entry at the given offset
+//
+// Arguments: [ulOffset] - Offset
+// [pstatstg] - Entry to fill in
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+//---------------------------------------------------------------
+
+SCODE CPubIter::Next(ULONG ulOffset, STATSTGW *pstatstg)
+{
+ SCODE sc;
+ ULONG ulRead;
+ CSnapshotEntry se;
+
+ olDebugOut((DEB_ITRACE, "In CPubIter::ReadEntry:%p(%lu, %p)\n",
+ this, ulOffset, pstatstg));
+ if (_pds == NULL)
+ olChk(Snapshot());
+ ULARGE_INTEGER ul;
+ ULISet32(ul, ulOffset * sizeof(CSnapshotEntry));
+
+ olHChk(_pds->ReadAt(
+ ul,
+ &se,
+ sizeof(CSnapshotEntry),
+ &ulRead));
+ if (ulRead == 0)
+ sc = S_FALSE;
+ else if (ulRead != sizeof(CSnapshotEntry))
+ {
+ olErr(EH_Err, STG_E_READFAULT);
+ }
+ else
+ {
+ olChk(DfAllocWCS(se.wcsName, &pstatstg->pwcsName));
+ wcscpy(pstatstg->pwcsName, se.wcsName);
+ pstatstg->type = se.dwType;
+ pstatstg->cbSize = se.cbSize;
+ pstatstg->mtime = se.mtime;
+ pstatstg->ctime = se.ctime;
+ pstatstg->atime = se.atime;
+ pstatstg->grfMode = 0;
+ pstatstg->grfLocksSupported = 0;
+ sc = S_OK;
+ }
+ olDebugOut((DEB_ITRACE, "Out CPubIter::ReadEntry => %lX\n", sc));
+ // Fall through
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubIter::RevertFromAbove, public
+//
+// Synopsis: Revert a public iterator
+//
+//---------------------------------------------------------------
+
+void CPubIter::RevertFromAbove(void)
+{
+ olDebugOut((DEB_ITRACE, "In CPubIter::RevertFromAbove:%p()\n", this));
+ _df |= DF_REVERTED;
+ if (_pds)
+ {
+ _pds->Release();
+ _pdf->DeleteScratchStream(&_dfnScratch);
+#if DBG == 1
+ _pds = NULL;
+#endif
+ }
+ olDebugOut((DEB_ITRACE, "Out CPubIter::RevertFromAbove\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubIter::Snapshot, private
+//
+// Synopsis: Snapshots a docfile for an iterator
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+SCODE CPubIter::Snapshot(void)
+{
+ SCODE sc;
+ PDocFileIterator *pdfi;
+ CSnapshotEntry se;
+ ULONG ulWritten;
+ STATSTGW sstg;
+ ULONG ulOffset;
+
+ olDebugOut((DEB_ITRACE, "In CPubIter::Snapshot()\n"));
+ olAssert(_pds == NULL);
+
+ olChk(_pdf->CreateScratchStream(&_pds, &_dfnScratch));
+
+ olChkTo(EH__pds, _pdf->GetDF()->GetIterator(&pdfi));
+ ulOffset = 0;
+ for (;;)
+ {
+ sc = pdfi->GetNext(&sstg);
+ if (sc == STG_E_NOMOREFILES)
+ break;
+ else if (FAILED(sc))
+ olErr(EH_pdfi, sc);
+ wcscpy(se.wcsName, sstg.pwcsName);
+ delete[] sstg.pwcsName;
+ se.dwType = sstg.type;
+ se.atime = sstg.atime;
+ se.mtime = sstg.mtime;
+ se.ctime = sstg.ctime;
+ se.cbSize = sstg.cbSize;
+ ULARGE_INTEGER ulTmp;
+ ULISet32(ulTmp, ulOffset);
+ olHChkTo(EH_pdfi, _pds->WriteAt(ulTmp, &se, sizeof(se), &ulWritten));
+
+ if (ulWritten != sizeof(se))
+ olErr(EH_pdfi, STG_E_WRITEFAULT);
+ ulOffset += ulWritten;
+ }
+ pdfi->Release();
+ olDebugOut((DEB_ITRACE, "Out CPubIter::Snapshot\n"));
+ return S_OK;
+
+EH_pdfi:
+ pdfi->Release();
+EH__pds:
+ _pds->Release();
+ _pdf->DeleteScratchStream(&_dfnScratch);
+ _pds = NULL;
+EH_Err:
+ return sc;
+}
diff --git a/private/ole32/stg/ref/publicdf.cxx b/private/ole32/stg/ref/publicdf.cxx
new file mode 100644
index 000000000..09c94ff02
--- /dev/null
+++ b/private/ole32/stg/ref/publicdf.cxx
@@ -0,0 +1,772 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: publicdf.cxx
+//
+// Contents: Public DocFile implementation
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+
+#include <time.h>
+#include <pbstream.hxx>
+#include <pubiter.hxx>
+#include <sstream.hxx>
+#include <lock.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::CPubDocFile, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [pdfParent] - Parent PubDocFile
+// [pdf] - DocFile basis
+// [df] - Permissions
+// [luid] - LUID
+// [pdfb] - Basis
+// [pdfn] - name
+// [cTransactedDepth] - Number of transacted parents
+// [pmsBase] - Base multistream
+//
+//---------------------------------------------------------------
+
+
+CPubDocFile::CPubDocFile(CPubDocFile *pdfParent,
+ PDocFile *pdf,
+ DFLAGS const df,
+ DFLUID luid,
+ ILockBytes *pilbBase,
+ CDfName const *pdfn,
+ CMStream MSTREAM_NEAR *pmsBase)
+{
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::CPubDocFile("
+ "%p, %p, %X, %lu, %p, %p, %p)\n",
+ pdfParent, pdf, df, luid, pilbBase, pdfn, pmsBase));
+ _pdfParent = pdfParent;
+ _pdf = pdf;
+ _df = df;
+ _luid = luid;
+ _pilbBase = pilbBase;
+
+ _fDirty = FALSE;
+ _pmsBase = pmsBase;
+ _cReferences = 1;
+ if (pdfn)
+ {
+ _dfn.Set(pdfn->GetLength(), pdfn->GetBuffer());
+ }
+ else
+ {
+ _dfn.Set((WORD)0, (BYTE *)NULL);
+ }
+
+ if (!IsRoot())
+ _pdfParent->AddChild(this);
+
+ _sig = CPUBDOCFILE_SIG;
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::CPubDocFile\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::~CPubDocFile, public
+//
+// Synopsis: Destructor
+//
+//---------------------------------------------------------------
+
+
+void CPubDocFile::vdtor(void)
+{
+ olAssert(_cReferences == 0);
+
+ _sig = CPUBDOCFILE_SIGDEL;
+
+ if (SUCCEEDED(CheckReverted()))
+ {
+ olAssert(!IsRoot());
+ _pdfParent->ReleaseChild(this);
+
+ _cilChildren.DeleteByName(NULL);
+
+ if (_pdf)
+ _pdf->Release();
+ }
+ delete this;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::Release, public
+//
+// Synopsis: Releases resources for a CPubDocFile
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+void CPubDocFile::vRelease(void)
+{
+ olDebugOut((DEB_TRACE,"In CPubDocFile::Release()\n"));
+ olAssert(_cReferences > 0);
+ AtomicDec(&_cReferences);
+ if (_pdf && !P_TRANSACTED(_df) && SUCCEEDED(CheckReverted()))
+ {
+ TIME_T tm;
+
+ if (IsDirty())
+ {
+ olVerSucc(DfGetTOD(&tm));
+ olVerSucc(_pdf->SetTime(WT_MODIFICATION, tm));
+ if (!IsRoot())
+ _pdfParent->SetDirty();
+ msfAssert(P_WRITE(_df) &&
+ aMsg("Dirty & Direct but no write access"));
+ olVerSucc(_pmsBase->Flush(0));
+ }
+ SetClean();
+ }
+
+ if (_cReferences == 0)
+ vdtor();
+ olDebugOut((DEB_TRACE,"Out CPubDocFile::Release()\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Method: CPubDocFile::CopyLStreamToLStream, private static
+//
+// Synopsis: Copies the contents of a stream to another stream
+//
+// Arguments: [plstFrom] - Stream to copy from
+// [plstTo] - Stream to copy to
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+SCODE CPubDocFile::CopyLStreamToLStream(ILockBytes *plstFrom,
+ ILockBytes *plstTo)
+{
+ BYTE *pbBuffer;
+ USHORT cbBuffer;
+ SCODE sc;
+ ULONG cbRead, cbWritten;
+ ULARGE_INTEGER cbPos;
+ STATSTG stat;
+
+ GetSafeBuffer(CB_SMALLBUFFER, CB_LARGEBUFFER, &pbBuffer, &cbBuffer);
+ olAssert((pbBuffer != NULL) && aMsg("Couldn't get scratch buffer"));
+
+ // Set destination size for contiguity
+ olHChk(plstFrom->Stat(&stat, STATFLAG_NONAME));
+ olHChk(plstTo->SetSize(stat.cbSize));
+
+ // Copy between streams
+ ULISet32(cbPos, 0);
+ for (;;)
+ {
+ olHChk(plstFrom->ReadAt(cbPos, pbBuffer, cbBuffer, &cbRead));
+ if (cbRead == 0) // EOF
+ break;
+ olHChk(plstTo->WriteAt(cbPos, pbBuffer, cbRead, &cbWritten));
+ if (cbRead != cbWritten)
+ olErr(EH_Err, STG_E_WRITEFAULT);
+ olAssert(0xFFFFFFFF-ULIGetLow(cbPos) > cbWritten);
+ ULISetLow(cbPos, ULIGetLow(cbPos)+cbWritten);
+ }
+ // Fall through
+EH_Err:
+ FreeBuffer(pbBuffer);
+ return sc;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::Commit, public
+//
+// Synopsis: Commits transacted changes
+//
+// Arguments: [dwFlags] - DFC_*
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+SCODE CPubDocFile::Commit(DWORD const dwFlags)
+{
+ SCODE sc;
+ TIME_T tm;
+
+ BOOL fFlush = FLUSH_CACHE(dwFlags);
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::Commit:%p(%lX)\n",
+ this, dwFlags));
+ olChk(CheckReverted());
+ if (!P_WRITE(_df))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ if (IsDirty())
+ {
+ olChk(DfGetTOD(&tm));
+ olChk(_pdf->SetTime(WT_MODIFICATION, tm));
+ }
+
+
+
+ if (IsDirty())
+ {
+ // We're dirty and direct all the way
+ olChk(_pmsBase->Flush(fFlush));
+ if (!IsRoot())
+ _pdfParent->SetDirty();
+ SetClean();
+ }
+ return S_OK;
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::DestroyEntry, public
+//
+// Synopsis: Permanently deletes an element of a DocFile
+//
+// Arguments: [pdfnName] - Name of element
+// [fClean] - Whether this was invoked as cleanup or not
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+SCODE CPubDocFile::DestroyEntry(CDfName const *pdfnName,
+ BOOL fClean)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::DestroyEntry:%p(%ws, %d)\n",
+ this, pdfnName, fClean));
+ olChk(CheckReverted());
+ if (!P_TRANSACTED(_df) && !P_WRITE(_df))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ olChk(_pdf->DestroyEntry(pdfnName, fClean));
+ _cilChildren.DeleteByName(pdfnName);
+ SetDirty();
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::DestroyEntry\n"));
+ // Fall through
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::RenameEntry, public
+//
+// Synopsis: Renames an element of a DocFile
+//
+// Arguments: [pdfnName] - Current name
+// [pdfnNewName] - New name
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+
+SCODE CPubDocFile::RenameEntry(CDfName const *pdfnName,
+ CDfName const *pdfnNewName)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::RenameEntry(%ws, %ws)\n",
+ pdfnName, pdfnNewName));
+ olChk(CheckReverted());
+ if (!P_TRANSACTED(_df) && !P_WRITE(_df))
+ sc = STG_E_ACCESSDENIED;
+ else
+ {
+ sc = _pdf->RenameEntry(pdfnName, pdfnNewName);
+ if (SUCCEEDED(sc))
+ {
+ _cilChildren.RenameChild(pdfnName, pdfnNewName);
+ SetDirty();
+ }
+ }
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::RenameEntry\n"));
+ // Fall through
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::CreateDocFile, public
+//
+// Synopsis: Creates an embedded DocFile
+//
+// Arguments: [pdfnName] - Name
+// [df] - Permissions
+// [dwType] - Type of entry
+// [ppdfDocFile] - New DocFile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdfDocFile]
+//
+//---------------------------------------------------------------
+
+
+SCODE CPubDocFile::CreateDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubDocFile **ppdfDocFile)
+{
+ PDocFile *pdf;
+ SCODE sc;
+ SEntryBuffer eb;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::CreateDocFile:%p("
+ "%ws, %X, %p)\n", this, pdfnName, df, ppdfDocFile));
+ olChk(CheckReverted());
+ if (!P_WRITE(_df))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ olChk(_cilChildren.IsDenied(pdfnName, df, _df));
+
+ olChkTo(EH_Reserve, _pdf->CreateDocFile(pdfnName, df, DF_NOLUID,
+ &pdf));
+
+ // As soon as we have a base we dirty ourself (in case
+ // we get an error later) so that we'll flush properly.
+ SetDirty();
+
+ eb.luid = pdf->GetLuid();
+ olAssert(eb.luid != DF_NOLUID && aMsg("DocFile id is DF_NOLUID!"));
+ olMemTo(EH_pdf,
+ *ppdfDocFile = new CPubDocFile(this, pdf, df, eb.luid,
+ _pilbBase, pdfnName, _pmsBase));
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::CreateDocFile\n"));
+ return S_OK;
+
+ EH_pdf:
+ pdf->Release();
+ olVerSucc(_pdf->DestroyEntry(pdfnName, TRUE));
+ return sc;
+ EH_Reserve:
+ EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::GetDocFile, public
+//
+// Synopsis: Gets an existing embedded DocFile
+//
+// Arguments: [pdfnName] - Name
+// [df] - Permissions
+// [dwType] - Type of entry
+// [ppdfDocFile] - DocFile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdfDocFile]
+//
+//---------------------------------------------------------------
+
+
+SCODE CPubDocFile::GetDocFile(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubDocFile **ppdfDocFile)
+{
+ PDocFile *pdf;
+ SCODE sc;
+ SEntryBuffer eb;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::GetDocFile:%p("
+ "%ws, %X, %p)\n",
+ this, pdfnName, df, ppdfDocFile));
+ olChk(CheckReverted());
+ if (!P_READ(_df))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ // Check to see if an instance with DENY_* exists
+ olChk(_cilChildren.IsDenied(pdfnName, df, _df));
+
+ olChk(_pdf->GetDocFile(pdfnName, df, &pdf));
+ eb.luid = pdf->GetLuid();
+ olAssert(eb.luid != DF_NOLUID && aMsg("DocFile id is DF_NOLUID!"));
+ olMemTo(EH_pdf,
+ *ppdfDocFile = new CPubDocFile(this, pdf, df, eb.luid,
+ _pilbBase, pdfnName, _pmsBase));
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::GetDocFile\n"));
+ return S_OK;
+
+ (*ppdfDocFile)->vRelease();
+ return sc;
+EH_pdf:
+ pdf->Release();
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::CreateStream, public
+//
+// Synopsis: Creates a stream
+//
+// Arguments: [pdfnName] - Name
+// [df] - Permissions
+// [ppdstStream] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdstStream]
+//
+//---------------------------------------------------------------
+
+
+SCODE CPubDocFile::CreateStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubStream **ppdstStream)
+{
+ PSStream *psst;
+ SCODE sc;
+ SEntryBuffer eb;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::CreateStream:%p("
+ "%ws, %X, %p)\n", this, pdfnName, df, ppdstStream));
+ olChk(CheckReverted());
+ if (!P_WRITE(_df))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ olChk(_cilChildren.IsDenied(pdfnName, df, _df));
+
+ olChkTo(EH_Reserve,
+ _pdf->CreateStream(pdfnName, df, DF_NOLUID, &psst));
+
+ // As soon as we have a base we dirty ourself (in case
+ // we get an error later) so that we'll flush properly.
+ SetDirty();
+
+ eb.luid = psst->GetLuid();
+ olAssert(eb.luid != DF_NOLUID && aMsg("Stream id is DF_NOLUID!"));
+
+ olMemTo(EH_Create, *ppdstStream = new CPubStream(this, df, pdfnName));
+ (*ppdstStream)->Init(psst, eb.luid);
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::CreateStream\n"));
+ return S_OK;
+
+ EH_Create:
+ psst->Release();
+ olVerSucc(_pdf->DestroyEntry(pdfnName, TRUE));
+ return sc;
+ EH_Reserve:
+ EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::GetStream, public
+//
+// Synopsis: Gets an existing stream
+//
+// Arguments: [pdfnName] - Name
+// [df] - Permissions
+// [ppdstStream] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdstStream]
+//
+//---------------------------------------------------------------
+
+
+SCODE CPubDocFile::GetStream(CDfName const *pdfnName,
+ DFLAGS const df,
+ CPubStream **ppdstStream)
+{
+ PSStream *psst;
+ SCODE sc;
+ SEntryBuffer eb;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::GetStream(%ws, %X, %p)\n",
+ pdfnName, df, ppdstStream));
+ olChk(CheckReverted());
+ if (!P_READ(_df))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ // Check permissions
+ olChk(_cilChildren.IsDenied(pdfnName, df, _df));
+
+ olChk(_pdf->GetStream(pdfnName, df, &psst));
+ eb.luid = psst->GetLuid();
+ olAssert(eb.luid != DF_NOLUID && aMsg("Stream id is DF_NOLUID!"));
+
+ olMemTo(EH_Get, *ppdstStream = new CPubStream(this, df, pdfnName));
+
+
+ (*ppdstStream)->Init(psst, eb.luid);
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::GetStream\n"));
+ return S_OK;
+
+EH_Get:
+ psst->Release();
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::GetIterator, public
+//
+// Synopsis: Starts an iterator
+//
+// Arguments: [fProperties] - Iterate properties or not
+// [pppiIterator] - Iterator return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pppiIterator]
+//
+//---------------------------------------------------------------
+
+
+SCODE CPubDocFile::GetIterator(CPubIter **pppiIterator)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::GetIterator:%p(%p)\n",
+ this, pppiIterator));
+ olChk(CheckReverted());
+ if (!P_READ(_df))
+ return STG_E_ACCESSDENIED;
+
+ olMem(*pppiIterator = new CPubIter(this));
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::GetIterator\n"));
+ return S_OK;
+
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::Stat, public
+//
+// Synopsis: Fills in a stat buffer
+//
+// Arguments: [pstatstg] - Buffer
+// [grfStatFlag] - Stat flags
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+//---------------------------------------------------------------
+
+
+SCODE CPubDocFile::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::Stat(%p, %lu)\n",
+ pstatstg, grfStatFlag));
+ olAssert(SUCCEEDED(VerifyStatFlag(grfStatFlag)));
+ olChk(CheckReverted());
+ olChk(_pdf->GetTime(WT_CREATION, &pstatstg->ctime));
+ olChk(_pdf->GetTime(WT_MODIFICATION, &pstatstg->mtime));
+ pstatstg->atime.dwLowDateTime = pstatstg->atime.dwHighDateTime = 0;
+ olChk(_pdf->GetClass(&pstatstg->clsid));
+ olChk(_pdf->GetStateBits(&pstatstg->grfStateBits));
+ olAssert(!IsRoot());
+
+ pstatstg->pwcsName = NULL;
+ if ((grfStatFlag & STATFLAG_NONAME) == 0)
+ {
+ olChk(DfAllocWCS((WCHAR *)_dfn.GetBuffer(), &pstatstg->pwcsName));
+ wcscpy(pstatstg->pwcsName, (WCHAR *)_dfn.GetBuffer());
+ }
+
+ pstatstg->grfMode = DFlagsToMode(_df);
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::Stat\n"));
+ // Fall through
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CPubDocFile::RevertFromAbove, public
+//
+// Synopsis: Parent has asked for reversion
+//
+//---------------------------------------------------------------
+
+
+void CPubDocFile::RevertFromAbove(void)
+{
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::RevertFromAbove:%p()\n", this));
+ _df |= DF_REVERTED;
+
+ _cilChildren.DeleteByName(NULL);
+
+ _pdf->Release();
+#if DBG == 1
+ _pdf = NULL;
+#endif
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::RevertFromAbove\n"));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::SetElementTimes, public
+//
+// Synopsis: Sets the times for an element
+//
+// Arguments: [pdfnName] - Name
+// [pctime] - Create time
+// [patime] - Access time
+// [pmtime] - Modify time
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+SCODE CPubDocFile::SetElementTimes(CDfName const *pdfnName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ SCODE sc;
+ PDocFile *pdf;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::SetElementTimes:%p("
+ "%ws, %p, %p, %p)\n", this, pdfnName, pctime,
+ patime, pmtime));
+ olChk(CheckReverted());
+ if ((!P_WRITE(_df)) ||
+ _cilChildren.FindByName(pdfnName) != NULL)
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ olChk(_pdf->GetDocFile(pdfnName, DF_WRITE, &pdf));
+
+ if (pctime)
+ olChkTo(EH_pdf, pdf->SetTime(WT_CREATION, *pctime));
+ if (pmtime)
+ olChkTo(EH_pdf, pdf->SetTime(WT_MODIFICATION, *pmtime));
+ if (patime)
+ olChkTo(EH_pdf, pdf->SetTime(WT_ACCESS, *patime));
+
+ SetDirty();
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::SetElementTimes\n"));
+ // Fall through
+ EH_pdf:
+ pdf->Release();
+EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::SetClass, public
+//
+// Synopsis: Sets the class ID
+//
+// Arguments: [clsid] - Class ID
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+SCODE CPubDocFile::SetClass(REFCLSID clsid)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::SetClass:%p(?)\n", this));
+ olChk(CheckReverted());
+ if (!P_WRITE(_df))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ sc = _pdf->SetClass(clsid);
+
+ SetDirty();
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::SetClass\n"));
+ // Fall through
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::SetStateBits, public
+//
+// Synopsis: Sets the state bits
+//
+// Arguments: [grfStateBits] - State bits
+// [grfMask] - Mask
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+SCODE CPubDocFile::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CPubDocFile::SetStateBits:%p(%lu, %lu)\n",
+ this, grfStateBits, grfMask));
+ olChk(CheckReverted());
+ if (!P_WRITE(_df))
+ olErr(EH_Err, STG_E_ACCESSDENIED);
+
+ sc = _pdf->SetStateBits(grfStateBits, grfMask);
+
+ SetDirty();
+
+ olDebugOut((DEB_ITRACE, "Out CPubDocFile::SetStateBits\n"));
+ // Fall through
+ EH_Err:
+ return sc;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPubDocFile::Validate, public static
+//
+// Synopsis: Validates a possibly invalid public docfile pointer
+//
+// Arguments: [pdf] - Memory to check
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+SCODE CPubDocFile::Validate(CPubDocFile *pdf)
+{
+ if (FAILED(ValidateBuffer(pdf, sizeof(CPubDocFile))) ||
+ pdf->_sig != CPUBDOCFILE_SIG)
+ {
+ return STG_E_INVALIDHANDLE;
+ }
+ return S_OK;
+}
diff --git a/private/ole32/stg/ref/refilb.cxx b/private/ole32/stg/ref/refilb.cxx
new file mode 100644
index 000000000..1cb845f68
--- /dev/null
+++ b/private/ole32/stg/ref/refilb.cxx
@@ -0,0 +1,190 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: refilb.cxx
+//
+// Contents: Reference ILockBytes class
+//
+// Classes:
+//
+// Functions:
+//
+//----------------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+#include <refilb.hxx>
+#include <stdio.h>
+#include <stdlib.h>
+
+static int filenum = 0;
+
+char * GetTempFileName(void)
+{
+ char *psz = new char[20];
+ strcpy(psz, "dft");
+
+ _itoa(filenum, psz + 3, 10);
+ filenum++;
+ return psz;
+}
+
+CFileILB::CFileILB(char *pszName)
+{
+ _pszName = new char[_MAX_PATH + 1];
+
+ if (pszName == NULL)
+ {
+ _pszName = GetTempFileName();
+ _fDelete = TRUE;
+ }
+ else
+ {
+ strcpy(_pszName, pszName);
+ _fDelete = FALSE;
+ }
+
+ _f = fopen(_pszName, "r+b");
+ if (_f == NULL)
+ {
+ _f = fopen(_pszName, "w+b");
+ }
+ _ulRef = 1;
+}
+
+CFileILB::~CFileILB()
+{
+ fclose(_f);
+ if (_fDelete)
+ {
+ _unlink(_pszName);
+ }
+
+ delete _pszName;
+}
+
+STDMETHODIMP CFileILB::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
+{
+ *ppvObj = NULL;
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+STDMETHODIMP_(ULONG) CFileILB::AddRef(void)
+{
+ AtomicInc(&_ulRef);
+ return(_ulRef);
+}
+
+STDMETHODIMP_(ULONG) CFileILB::Release(void)
+{
+ AtomicDec(&_ulRef);
+
+ if (_ulRef > 0)
+ {
+ return(_ulRef);
+ }
+
+ delete this;
+
+ return(0);
+}
+
+STDMETHODIMP CFileILB::ReadAt(ULARGE_INTEGER ulPosition,
+ VOID HUGEP *pb,
+ ULONG cb,
+ ULONG *pcbRead)
+{
+ fseek(_f, ULIGetLow(ulPosition), SEEK_SET);
+
+ *pcbRead = fread(pb, 1, cb, _f);
+ return NOERROR;
+}
+
+STDMETHODIMP CFileILB::WriteAt(ULARGE_INTEGER ulPosition,
+ VOID const HUGEP *pb,
+ ULONG cb,
+ ULONG FAR *pcbWritten)
+{
+ fseek(_f, ULIGetLow(ulPosition), SEEK_SET);
+
+ *pcbWritten = fwrite(pb, 1, cb, _f);
+ return NOERROR;
+}
+
+STDMETHODIMP CFileILB::Flush(void)
+{
+ return NOERROR;
+}
+
+STDMETHODIMP CFileILB::SetSize(ULARGE_INTEGER cb)
+{
+ fseek(_f, ULIGetLow(cb), SEEK_SET);
+
+ fwrite(NULL, 0, 0, _f);
+ return NOERROR;
+}
+
+STDMETHODIMP CFileILB::LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+
+STDMETHODIMP CFileILB::UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+
+STDMETHODIMP CFileILB::Stat(STATSTG FAR *pstatstg, DWORD grfStatFlag)
+{
+ memset(pstatstg, 0, sizeof(STATSTG));
+
+ if ((grfStatFlag & STATFLAG_NONAME) == 0)
+ {
+ pstatstg->pwcsName = new char[strlen(_pszName)];
+ strcpy(pstatstg->pwcsName, _pszName);
+ }
+
+ pstatstg->type = STGTY_LOCKBYTES;
+
+ ULISetHigh(pstatstg->cbSize, 0);
+
+ fseek(_f, 0, SEEK_END);
+ ULISetLow(pstatstg->cbSize, ftell(_f));
+
+ pstatstg->grfMode = STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE;
+
+ return NOERROR;
+}
+
+
+SCODE CreateFileStream(ILockBytes **ppilb, CDfName *pdfn)
+{
+ *ppilb = new CFileILB(NULL);
+ return S_OK;
+}
+
+SCODE DeleteFileStream(CDfName *pdfn)
+{
+ return S_OK;
+}
+
+STDAPI_(BOOL) IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
+{
+ return (memcmp(&rguid1, &rguid2, sizeof(GUID)) == 0);
+}
+
+STDAPI_(BOOL) CoDosDateTimeToFileTime(
+ WORD nDosDate, WORD nDosTime, FILETIME FAR* lpFileTime)
+{
+ return TRUE;
+}
+
+
diff --git a/private/ole32/stg/ref/reftest.cxx b/private/ole32/stg/ref/reftest.cxx
new file mode 100644
index 000000000..ab3c8ccfc
--- /dev/null
+++ b/private/ole32/stg/ref/reftest.cxx
@@ -0,0 +1,549 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: reftest.cxx
+//
+// Contents: Reference tests
+//
+// Classes:
+//
+// Functions:
+//
+//----------------------------------------------------------------------------
+
+
+#include <ref.hxx>
+#include <storage.h>
+#include <refilb.hxx>
+#include <ole.hxx>
+#include <msf.hxx>
+#include <stdlib.h>
+
+
+#define STR(x) x
+#define STGP(x) STGM_SHARE_EXCLUSIVE | x
+#define STMP(x) STGM_SHARE_EXCLUSIVE | x
+#define ROOTP(x) STGP(x)
+
+
+#define EXIT_BADSC 1
+
+void error(int code, char *fmt, ...)
+{
+ va_list args;
+
+ args = va_start(args, fmt);
+ fprintf(stderr, "** Fatal error **: ");
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ exit(code);
+}
+
+
+BOOL IsEqualTime(FILETIME ttTime, FILETIME ttCheck)
+{
+ return ttTime.dwLowDateTime == ttCheck.dwLowDateTime &&
+ ttTime.dwHighDateTime == ttCheck.dwHighDateTime;
+}
+
+
+SCODE t_create(void)
+{
+ IStorage *pstgRoot, *pstgChild, *pstgChild2;
+ IStream *pstm;
+ SCODE sc;
+
+ ILockBytes *pilb = new CFileILB("drt.dfl");
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ olHChk(StgCreateDocfileOnILockBytes(
+ pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstgRoot));
+
+ olHChk(pstgRoot->CreateStorage(STR("Child"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+
+ olHChk(pstgChild->CreateStorage(STR("Child2"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild2));
+
+ olHChk(pstgChild2->CreateStream(STR("Stream"), STMP(STGM_READWRITE), 0, 0,
+ &pstm));
+
+ pstm->Release();
+ olHChk(pstgChild2->Commit(0));
+ pstgChild2->Release();
+
+ olHChk(pstgChild->Commit(0));
+ pstgChild->Release();
+
+ pstgRoot->Release();
+ pilb->Release();
+
+ EH_Err:
+ return sc;
+}
+
+SCODE t_open(void)
+{
+ SCODE sc;
+ IStorage *pstgRoot, *pstgChild, *pstgChild2;
+ IStream *pstm;
+
+ ILockBytes *pilb = new CFileILB("drt.dfl");
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ olHChk(StgCreateDocfileOnILockBytes(pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstgRoot));
+
+ olHChk(pstgRoot->CreateStorage(STR("Child"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ olHChk(pstgChild->CreateStorage(STR("Child2"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild2));
+ olHChk(pstgChild2->CreateStream(STR("Stream"), STMP(STGM_READWRITE), 0, 0,
+ &pstm));
+ pstm->Release();
+ pstgChild2->Release();
+ pstgChild->Release();
+
+
+ olHChk(pstgRoot->Commit(0));
+ pstgRoot->Release();
+
+ olHChk(StgOpenStorageOnILockBytes(
+ pilb,
+ NULL,
+ ROOTP(STGM_READWRITE),
+ NULL,
+ 0,
+ &pstgRoot));
+
+ olHChk(pstgRoot->OpenStorage(
+ STR("Child"),
+ NULL,
+ STGP(STGM_READWRITE),
+ NULL,
+ 0,
+ &pstgChild));
+
+ olHChk(pstgChild->OpenStorage(
+ STR("Child2"),
+ NULL,
+ STGP(STGM_READWRITE),
+ NULL,
+ 0,
+ &pstgChild2));
+
+ olHChk(pstgChild2->OpenStream(
+ STR("Stream"),
+ NULL,
+ STMP(STGM_READWRITE),
+ 0,
+ &pstm));
+
+ pstm->Release();
+ pstgChild2->Release();
+ pstgChild->Release();
+ pstgRoot->Release();
+ pilb->Release();
+
+ EH_Err:
+ return sc;
+}
+
+
+SCODE t_addref(void)
+{
+ SCODE sc;
+ IStorage *pstg;
+ IStream *pstm;
+ ULONG ul;
+
+ ILockBytes *pilb = new CFileILB("drt.dfl");
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ olHChk(StgCreateDocfileOnILockBytes(pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstg));
+
+ olHChk(pstg->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+
+ if ((ul = pstm->AddRef()) != 2)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+ if ((ul = pstm->Release()) != 1)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+ pstm->Release();
+ if ((ul = pstg->AddRef()) != 2)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+ if ((ul = pstg->Release()) != 1)
+ error(EXIT_BADSC, "Wrong reference count - %lu\n", ul);
+
+ pstg->Release();
+ pilb->Release();
+EH_Err:
+ return sc;
+}
+
+
+SCODE t_dmodify(void)
+{
+ SCODE sc;
+ IStorage *pstgRoot, *pstgChild, *pstgChild2;
+ IStream *pstm;
+
+ ILockBytes *pilb = new CFileILB("drt.dfl");
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ olHChk(StgCreateDocfileOnILockBytes(pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstgRoot));
+
+ olHChk(pstgRoot->CreateStorage(STR("Child"), STGP(STGM_READWRITE), 0,
+ 0, &pstgChild));
+ olHChk(pstgChild->CreateStorage(STR("Child2"), STGP(STGM_READWRITE), 0,
+ 0, &pstgChild2));
+ olHChk(pstgChild2->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+ pstm->Release();
+
+ // Test renaming a closed stream
+ olHChk(pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream")));
+
+ // Test destroying a stream
+ olHChk(pstgChild2->DestroyElement(STR("RenamedStream")));
+
+ // Test renaming an open stream
+ olHChk(pstgChild2->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+
+ olHChk(pstgChild2->RenameElement(STR("Stream"), STR("RenamedStream")));
+
+ olHChk(pstgChild2->DestroyElement(STR("RenamedStream")));
+ pstm->Release();
+
+ pstgChild2->Release();
+
+ // Test renaming a storage
+ olHChk(pstgChild->RenameElement(STR("Child2"), STR("RenamedChild")));
+
+ olHChk(pstgChild->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+
+ pstm->Release();
+ olHChk(pstgChild->DestroyElement(STR("Stream")));
+
+ // Test SetElementTimes
+ FILETIME tm;
+ STATSTG stat;
+
+ tm.dwLowDateTime = 0x12345678;
+ tm.dwHighDateTime = 0x9abcdef0;
+
+ // Set when element not open
+ olHChk(pstgChild->SetElementTimes(STR("RenamedChild"), &tm, NULL, NULL));
+ olHChk(pstgChild->SetElementTimes(STR("RenamedChild"), NULL, &tm, NULL));
+ olHChk(pstgChild->SetElementTimes(STR("RenamedChild"), NULL, NULL, &tm));
+
+ olHChk(pstgChild->OpenStorage(
+ STR("RenamedChild"),
+ NULL,
+ STMP(STGM_READWRITE),
+ NULL,
+ 0,
+ &pstgChild2));
+ olHChk(pstgChild2->Stat(&stat, STATFLAG_NONAME));
+ if (!IsEqualTime(stat.ctime, tm) ||
+ !IsEqualTime(stat.mtime, tm))
+ error(EXIT_BADSC, "Times don't match those set by SetElementTimes\n");
+
+ // Test SetClass and SetStateBits
+ olHChk(pstgChild2->SetClass(IID_IStorage));
+ olHChk(pstgChild2->SetStateBits(0xff00ff00, 0xffffffff));
+ olHChk(pstgChild2->SetStateBits(0x00880088, 0xeeeeeeee));
+ olHChk(pstgChild2->Stat(&stat, STATFLAG_NONAME));
+ if (!IsEqualCLSID(stat.clsid, IID_IStorage))
+ error(EXIT_BADSC, "Class ID set improperly\n");
+ if (stat.grfStateBits != 0x11881188)
+ error(EXIT_BADSC, "State bits set improperly: has %lX vs. %lX\n",
+ stat.grfStateBits, 0x11881188);
+ pstgChild2->Release();
+
+ pstgChild->Release();
+
+ olHChk(pstgRoot->Revert());
+
+ olHChk(pstgRoot->Commit(0));
+
+ olHChk(pstgRoot->DestroyElement(STR("Child")));
+
+ olHChk(pstgRoot->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+
+ ULARGE_INTEGER ulSize;
+ ULISet32(ulSize, 65536);
+
+ olHChk(pstm->SetSize(ulSize));
+ pstm->Release();
+ olHChk(pstgRoot->DestroyElement(STR("Stream")));
+ olHChk(pstgRoot->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+
+ olHChk(pstm->SetSize(ulSize));
+ pstm->Release();
+
+ pstgRoot->Release();
+
+ pilb->Release();
+ pilb = new CFileILB(NULL);
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ olHChk(StgCreateDocfileOnILockBytes(pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstgRoot));
+
+ // removal cases
+ // 1) no right child
+
+ olHChk(pstgRoot->CreateStorage(STR("64"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+ olHChk(pstgRoot->CreateStorage(STR("32"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+
+ olHChk(pstgRoot->DestroyElement(STR("64")));
+
+ // 2) right child has no left child
+
+ olHChk(pstgRoot->CreateStorage(STR("64"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+ olHChk(pstgRoot->DestroyElement(STR("32")));
+
+ // 3) right child has left child
+
+ olHChk(pstgRoot->CreateStorage(STR("96"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+ olHChk(pstgRoot->CreateStorage(STR("80"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+
+ olHChk(pstgRoot->DestroyElement(STR("64")));
+
+ // 4) right child's left child has children
+
+ olHChk(pstgRoot->CreateStorage(STR("88"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+ olHChk(pstgRoot->CreateStorage(STR("84"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+ olHChk(pstgRoot->CreateStorage(STR("92"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ pstgChild->Release();
+ olHChk(pstgRoot->DestroyElement(STR("80")));
+
+ pstgRoot->Release();
+
+ pilb->Release();
+EH_Err:
+ return sc;
+}
+
+
+SCODE t_stat(void)
+{
+ SCODE sc;
+ IStorage *pstgRoot, *pstgChild;
+ IStream *pstm;
+ STATSTG stat;
+
+ ILockBytes *pilb = new CFileILB("drt.dfl");
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ olHChk(StgCreateDocfileOnILockBytes(pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstgRoot));
+
+ olHChk(pstgRoot->CreateStorage(STR("Child"), STGP(STGM_READWRITE), 0, 0,
+ &pstgChild));
+ olHChk(pstgChild->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+
+ olHChk(pstm->Stat(&stat, 0));
+ delete [] stat.pwcsName;
+
+ olHChk(pstm->Stat(&stat, STATFLAG_NONAME));
+
+ pstm->Release();
+
+ olHChk(pstgChild->Stat(&stat, 0));
+ delete [] stat.pwcsName;
+
+ olHChk(pstgChild->Stat(&stat, STATFLAG_NONAME));
+
+ pstgChild->Release();
+
+ olHChk(pstgRoot->Stat(&stat, 0));
+
+ delete[] stat.pwcsName;
+
+ olHChk(pstgRoot->Stat(&stat, STATFLAG_NONAME));
+
+ pstgRoot->Release();
+ pilb->Release();
+EH_Err:
+ return sc;
+}
+
+static char NUMBERS[] = "12345678901234567890123456789012345678901234567890";
+
+SCODE t_stream(void)
+{
+ SCODE sc;
+ IStorage *pstg;
+ IStream *pstm, *pstmC;
+ char buf[sizeof(NUMBERS)*2];
+ ULONG cb;
+ ULARGE_INTEGER ulPos, ulSize;
+ LARGE_INTEGER lPos;
+
+ ILockBytes *pilb = new CFileILB("drt.dfl");
+ if (pilb == NULL)
+ error(EXIT_BADSC, "Unable to allocate an ILockBytes\n");
+
+ // create a storage on the ILockBytes
+
+ olHChk(StgCreateDocfileOnILockBytes(pilb,
+ STGM_READWRITE |
+ STGM_CREATE |
+ STGM_SHARE_EXCLUSIVE,
+ 0, &pstg));
+
+ olHChk(pstg->CreateStream(
+ STR("Stream"),
+ STMP(STGM_READWRITE),
+ 0,
+ 0,
+ &pstm));
+ olHChk(pstm->Write(NUMBERS, sizeof(NUMBERS), &cb));
+ olHChk(pstm->Commit(0));
+ ULISet32(lPos, 0);
+
+ olHChk(pstm->Seek(lPos, STREAM_SEEK_SET, &ulPos));
+ if (ULIGetLow(ulPos) != 0)
+ error(EXIT_BADSC, "Incorrect seek, ptr is %lu\n", ULIGetLow(ulPos));
+ olHChk(pstm->Read(buf, sizeof(NUMBERS), &cb));
+ if (strcmp(buf, NUMBERS))
+ error(EXIT_BADSC, "Incorrect stream contents\n");
+
+ ULISet32(ulSize, sizeof(NUMBERS)/2);
+ olHChk(pstm->SetSize(ulSize));
+ olHChk(pstm->Seek(lPos, STREAM_SEEK_SET, NULL));
+
+ olHChk(pstm->Read(buf, sizeof(NUMBERS), &cb));
+
+ if (cb != sizeof(NUMBERS)/2)
+ error(EXIT_BADSC, "SetSize failed to size stream properly\n");
+ if (memcmp(buf, NUMBERS, sizeof(NUMBERS)/2))
+ error(EXIT_BADSC, "SetSize corrupted contents\n");
+ olHChk(pstm->Clone(&pstmC));
+ olHChk(pstm->Seek(lPos, STREAM_SEEK_SET, NULL));
+ olHChk(pstm->CopyTo(pstmC, ulSize, NULL, NULL));
+ olHChk(pstm->Seek(lPos, STREAM_SEEK_SET, NULL));
+
+ ULISet32(ulSize, sizeof(NUMBERS)&~1);
+ olHChk(pstm->CopyTo(pstmC, ulSize, NULL, NULL));
+ olHChk(pstm->Seek(lPos, STREAM_SEEK_SET, NULL));
+ olHChk(pstm->Read(buf, (sizeof(NUMBERS)&~1)*2, &cb));
+ if (memcmp(buf, NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+sizeof(NUMBERS)/2, NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+(sizeof(NUMBERS)&~1), NUMBERS, sizeof(NUMBERS)/2) ||
+ memcmp(buf+3*(sizeof(NUMBERS)/2), NUMBERS, sizeof(NUMBERS)/2))
+ error(EXIT_BADSC, "Stream contents incorrect\n");
+ pstmC->Release();
+ pstm->Release();
+ pstg->Release();
+ pilb->Release();
+EH_Err:
+ return sc;
+}
+
+
+void main()
+{
+ SCODE sc;
+
+ olChk(t_create());
+ olChk(t_open());
+ olChk(t_addref());
+ olChk(t_dmodify());
+ printf("Tests passed successfully.\n");
+ exit(0);
+EH_Err:
+ printf("Tests failed with error %lX\n",sc);
+ exit(EXIT_BADSC);
+}
diff --git a/private/ole32/stg/ref/rpubdf.cxx b/private/ole32/stg/ref/rpubdf.cxx
new file mode 100644
index 000000000..35f8ab7af
--- /dev/null
+++ b/private/ole32/stg/ref/rpubdf.cxx
@@ -0,0 +1,245 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: rpubdf.cxx
+//
+// Contents: CRootPubDocFile implementation
+//
+//---------------------------------------------------------------
+
+#include <dfhead.cxx>
+
+
+#include <header.hxx>
+#include <rpubdf.hxx>
+#include <lock.hxx>
+
+// Priority mode lock permissions
+#define PRIORITY_PERMS DF_READ
+
+//+--------------------------------------------------------------
+//
+// Member: CRootPubDocFile::CRootPubDocFile, public
+//
+// Synopsis: Ctor - Initializes empty object
+//
+//---------------------------------------------------------------
+
+
+CRootPubDocFile::CRootPubDocFile(void) :
+ CPubDocFile(NULL, NULL, 0, ROOT_LUID, NULL, NULL, NULL)
+{
+ olDebugOut((DEB_ITRACE, "In CRootPubDocFile::CRootPubDocFile()\n"));
+ olDebugOut((DEB_ITRACE, "Out CRootPubDocFile::CRootPubDocFile\n"));
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CRootPubDocFile::InitNotInd, private
+//
+// Synopsis: Dependent root initialization
+//
+// Arguments: [plstBase] - Base
+// [snbExclude] - Limited instantiation exclusions
+// [dwStartFlags] - Startup flags
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+SCODE CRootPubDocFile::Init(ILockBytes *plstBase,
+ SNBW snbExclude,
+ DWORD const dwStartFlags)
+{
+ CDocFile *pdf;
+ SCODE sc;
+ CMStream MSTREAM_NEAR *pms;
+
+ olDebugOut((DEB_ITRACE, "In CRootPubDocFile::InitNotInd()\n"));
+ if (snbExclude)
+ {
+ olChk(DllMultiStreamFromStream(&pms, &plstBase, dwStartFlags));
+ olMemTo(EH_pms,
+ pdf = new CDocFile(pms, SIDROOT, ROOT_LUID, _pilbBase));
+ pdf->AddRef();
+ olChkTo(EH_pdf, PDocFile::ExcludeEntries(pdf, snbExclude));
+ olChkTo(EH_pdf, pms->Flush(0));
+ pdf->Release();
+ }
+ _pilbBase = plstBase;
+ olDebugOut((DEB_ITRACE, "Out CRootPubDocFile::InitNotInd\n"));
+ return S_OK;
+
+EH_pdf:
+ pdf->Release();
+EH_pms:
+ DllReleaseMultiStream(pms);
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CRootPubDocFile::InitRoot, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [plstBase] - Base LStream
+// [dwStartFlags] - How to start things
+// [df] - Transactioning flags
+// [snbExclude] - Parital instantiation list
+// [ppdfb] - Basis pointer return
+// [pulOpenLock] - Open lock index return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppdfb]
+// [pulOpenLock]
+//
+//---------------------------------------------------------------
+
+SCODE CRootPubDocFile::InitRoot(ILockBytes *plstBase,
+ DWORD const dwStartFlags,
+ DFLAGS const df,
+ SNBW snbExclude,
+ ULONG *pulOpenLock)
+{
+ CDocFile *pdfBase;
+ SCODE sc, scConv = S_OK;
+ STATSTG statstg;
+
+ olDebugOut((DEB_ITRACE, "In CRootPubDocFile::InitRoot("
+ "%p, %lX, %lX, %p)\n",
+ plstBase, dwStartFlags, df, snbExclude));
+
+ // Exclusion only works with a plain open
+ olAssert(snbExclude == NULL ||
+ (dwStartFlags & (RSF_CREATEFLAGS | RSF_CONVERT)) == 0);
+
+ olHChk(plstBase->Stat(&statstg, STATFLAG_NONAME));
+
+ *pulOpenLock = 0;
+ if (statstg.grfLocksSupported & LOCK_ONLYONCE)
+ olChk(GetOpen(plstBase, df, TRUE, pulOpenLock));
+
+ olChkTo(EH_GetPriority,
+ Init(plstBase, snbExclude, dwStartFlags));
+
+ scConv = DllMultiStreamFromStream(&_pmsBase, &_pilbBase,
+ dwStartFlags);
+ if (scConv == STG_E_INVALIDHEADER)
+ scConv = STG_E_FILEALREADYEXISTS;
+ olChkTo(EH_pfstScratchInit, scConv);
+
+ olMemTo(EH_pmsBase,
+ pdfBase = new CDocFile(_pmsBase, SIDROOT, ROOT_LUID, _pilbBase));
+
+ pdfBase->AddRef();
+
+ _pdf = pdfBase;
+ _df = df;
+ olDebugOut((DEB_ITRACE, "Out CRootPubDocFile::InitRoot\n"));
+ return scConv;
+
+
+EH_pmsBase:
+ DllReleaseMultiStream(_pmsBase);
+
+EH_pfstScratchInit:
+ olVerSucc(_pilbBase->Release());
+EH_GetPriority:
+EH_GetOpen:
+ if (*pulOpenLock != 0)
+ {
+ olAssert(statstg.grfLocksSupported & LOCK_ONLYONCE);
+ ReleaseOpen(plstBase, df, *pulOpenLock);
+ *pulOpenLock = 0;
+ }
+EH_Err:
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CRootPubDocFile::~CRootPubDocFile, public
+//
+// Synopsis: dtor
+//
+//---------------------------------------------------------------
+
+
+void CRootPubDocFile::vdtor(void)
+{
+ olDebugOut((DEB_ITRACE, "In CRootPubDocFile::~CRootPubDocFile\n"));
+
+ olAssert(_cReferences == 0);
+
+ // We can't rely on CPubDocFile::~CPubDocFile to do this since
+ // we're using a virtual destructor
+ _sig = CPUBDOCFILE_SIGDEL;
+
+ if (SUCCEEDED(CheckReverted()))
+ {
+ _cilChildren.DeleteByName(NULL);
+
+ if (_pdf)
+ _pdf->Release();
+ if (_pilbBase)
+ _pilbBase->Release();
+ }
+ olDebugOut((DEB_ITRACE, "Out CRootPubDocFile::~CRootPubDocFile\n"));
+ delete this;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CRootPubDocFile::Stat, public
+//
+// Synopsis: Fills in a stat buffer from the base LStream
+//
+// Arguments: [pstatstg] - Stat buffer
+// [grfStatFlag] - Stat flags
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+//---------------------------------------------------------------
+
+
+SCODE CRootPubDocFile::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ SCODE sc;
+
+ olDebugOut((DEB_ITRACE, "In CRootPubDocFile::Stat(%p, %lu)\n",
+ pstatstg, grfStatFlag));
+ olChk(CheckReverted());
+ olHChk(_pilbBase->Stat((STATSTG *)pstatstg, grfStatFlag));
+ if (pstatstg->pwcsName)
+ {
+ WCHAR *pwcs;
+
+ olChkTo(EH_pwcsName,
+ DfAllocWC(strlen((char *)pstatstg->pwcsName)+1, &pwcs));
+ mbstowcs(pwcs, (char *)pstatstg->pwcsName,
+ strlen((char *)pstatstg->pwcsName)+1);
+ delete[] pstatstg->pwcsName;
+ pstatstg->pwcsName = pwcs;
+ }
+ pstatstg->grfMode = DFlagsToMode(_df);
+ olChkTo(EH_pwcsName, _pdf->GetClass(&pstatstg->clsid));
+ olChkTo(EH_pwcsName, _pdf->GetStateBits(&pstatstg->grfStateBits));
+ olDebugOut((DEB_ITRACE, "Out CRootPubDocFile::Stat\n"));
+ return S_OK;
+
+EH_pwcsName:
+ if (pstatstg->pwcsName)
+ delete[] pstatstg->pwcsName;
+EH_Err:
+ return sc;
+}
+
+
diff --git a/private/ole32/stg/ref/seekptr.cxx b/private/ole32/stg/ref/seekptr.cxx
new file mode 100644
index 000000000..a9e3ebd94
--- /dev/null
+++ b/private/ole32/stg/ref/seekptr.cxx
@@ -0,0 +1,32 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: seekptr.cxx
+//
+// Contents: Seek pointer non-inline implementation
+//
+//--------------------------------------------------------------------------
+#include <exphead.cxx>
+
+#include <seekptr.hxx>
+
+//+--------------------------------------------------------------
+//
+// Member: CSeekPointer::Release, public
+//
+// Synopsis: Decrements _cReferences and delete's on noref
+//
+//---------------------------------------------------------------
+
+void CSeekPointer::vRelease(void)
+{
+ olDebugOut((DEB_TRACE,"In CSeekPointer::Release()\n"));
+ olAssert(_cReferences > 0);
+ AtomicDec(&_cReferences);
+ if (_cReferences == 0)
+ delete this;
+ olDebugOut((DEB_TRACE,"Out CSeekPointer::Release()\n"));
+}
+
diff --git a/private/ole32/stg/ref/seekptr.hxx b/private/ole32/stg/ref/seekptr.hxx
new file mode 100644
index 000000000..e4a035859
--- /dev/null
+++ b/private/ole32/stg/ref/seekptr.hxx
@@ -0,0 +1,113 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: seekptr.hxx
+//
+// Contents: CSeekPointer header
+//
+// Classes: CSeekPointer
+//
+//---------------------------------------------------------------
+
+#ifndef __SEEKPTR_HXX__
+#define __SEEKPTR_HXX__
+
+
+//+--------------------------------------------------------------
+//
+// Class: CSeekPointer
+//
+// Purpose: Contains a seek pointer to share between exposed
+// streams
+//
+// Interface: See below.
+//
+//---------------------------------------------------------------
+
+class CSeekPointer
+{
+public:
+ inline CSeekPointer(ULONG ulPos);
+ inline ~CSeekPointer(void);
+
+ inline ULONG GetPos(void) const;
+ inline void SetPos(ULONG ulPos);
+ inline void vAddRef(void);
+ void vRelease(void);
+
+private:
+ ULONG _ulPos;
+ LONG _cReferences;
+};
+
+//+--------------------------------------------------------------
+//
+// Member: CSeekPointer::CSeekPointer, public
+//
+// Synopsis: Ctor
+//
+// Arguments: [ulPos] - Initial position
+//
+//---------------------------------------------------------------
+
+inline CSeekPointer::CSeekPointer(ULONG ulPos)
+{
+ _ulPos = ulPos;
+ _cReferences = 1;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSeekPointer::~CSeekPointer, public
+//
+// Synopsis: Dtor
+//
+//---------------------------------------------------------------
+
+inline CSeekPointer::~CSeekPointer(void)
+{
+ olAssert(_cReferences == 0);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSeekPointer::GetPos, public
+//
+// Synopsis: Returns _ulPos
+//
+//---------------------------------------------------------------
+
+inline ULONG CSeekPointer::GetPos(void) const
+{
+ return _ulPos;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSeekPointer::SetPos, public
+//
+// Synopsis: Assigns _ulPos
+//
+//---------------------------------------------------------------
+
+inline void CSeekPointer::SetPos(ULONG ulPos)
+{
+ _ulPos = ulPos;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSeekPointer::AddRef, public
+//
+// Synopsis: Increments _cReferences
+//
+//---------------------------------------------------------------
+
+inline void CSeekPointer::vAddRef(void)
+{
+ AtomicInc(&_cReferences);
+}
+
+#endif // #ifndef __SEEKPTR_HXX__
diff --git a/private/ole32/stg/ref/sstream.cxx b/private/ole32/stg/ref/sstream.cxx
new file mode 100644
index 000000000..b9c721c12
--- /dev/null
+++ b/private/ole32/stg/ref/sstream.cxx
@@ -0,0 +1,710 @@
+//+-------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: sstream.cxx
+//
+// Contents: Stream operations for Mstream project
+//
+// Classes: None. (defined in sstream.hxx)
+//
+//--------------------------------------------------------------------
+
+#include "msfhead.cxx"
+
+
+#include <dirfunc.hxx>
+#include <sstream.hxx>
+#include <time.h>
+#include <mread.hxx>
+
+#define DEB_STREAM (DEB_ITRACE | 0x00020000)
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDirectStream::CDirectStream, public
+//
+// Synopsis: Empty object constructor
+//
+// Arguments: [dl] - LUID
+//
+//---------------------------------------------------------------
+
+CDirectStream::CDirectStream(DFLUID dl)
+: PSStream(dl)
+{
+ _cReferences = 0;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CDirectStream::InitSystem, public
+//
+// Synopsis: Initializes special system streams like the ministream
+//
+// Arguments: [pms] - Multistream
+// [sid] - SID
+// [cbSize] - size
+//
+//---------------------------------------------------------------
+
+void CDirectStream::InitSystem(CMStream MSTREAM_NEAR *pms,
+ SID sid,
+ ULONG cbSize)
+{
+ _stmh.Init(pms, sid);
+ _ulSize = _ulOldSize = cbSize;
+ AddRef();
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectStream::Init, public
+//
+// Synopsis: CDirectStream constructor
+//
+// Arguments: [pstgh] - Parent
+// [pdfn] - Name of entry
+// [fCreate] - Create or get
+//
+// Returns: Appropriate status code
+//
+//--------------------------------------------------------------------------
+
+SCODE CDirectStream::Init(
+ CStgHandle *pstgh,
+ CDfName const *pdfn,
+ BOOL const fCreate)
+{
+ SCODE sc;
+
+ if (fCreate)
+ sc = pstgh->CreateEntry(pdfn, STGTY_STREAM, &_stmh);
+ else
+ sc = pstgh->GetEntry(pdfn, STGTY_STREAM, &_stmh);
+ if (SUCCEEDED(sc))
+ {
+ sc = _stmh.GetSize(&_ulSize);
+ _ulOldSize = _ulSize;
+ if (SUCCEEDED(sc))
+ AddRef();
+ }
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CDirectStream::~CDirectStream, public
+//
+// Synopsis: CDirectStream destructor
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CDirectStream::~CDirectStream()
+{
+ msfAssert(_cReferences == 0);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectStream::ReadAt, public
+//
+// Synposis: Reads binary data from a linear single stream
+//
+// Arguments: [ulOffset] -- Position to be read from
+//
+// [pBuffer] -- Pointer to the area into which the data
+// will be read.
+// [ulCount] -- Indicates the number of bytes to be read
+// [pulRetval] -- Area into which return value will be stored
+//
+// Returns: Error Code of parent MStream call
+//
+// Algorithm: Calculate start and end sectors and offsets, then
+// pass call up to parent MStream.
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+
+SCODE CDirectStream::ReadAt(
+ ULONG ulOffset,
+ VOID HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval)
+{
+ msfDebugOut((DEB_TRACE,"In CDirectStream::ReadAt(%lu,%p,%lu)\n",
+ ulOffset,pBuffer,ulCount));
+
+ SCODE sc = S_OK;
+
+ CMStream MSTREAM_NEAR *pms = _stmh.GetMS();
+
+
+ // Check for offset beyond stream size and zero count
+
+ if ((ulOffset >= _ulSize) || (0 == ulCount))
+ {
+ *pulRetval = 0;
+ return S_OK;
+ }
+
+ if (ulOffset + ulCount > _ulSize)
+ {
+ msfDebugOut((DEB_ITRACE,"Truncating Read: ulOffset = %lu, ulCount = %lu, _ulSize = %lu\n",
+ ulOffset,ulCount,_ulSize));
+ ulCount = _ulSize - ulOffset;
+ }
+
+
+ // Stream is stored in ministream if size < MINISTREAMSIZE
+ // and this is not a scratch stream.
+
+
+ SID sid = _stmh.GetSid();
+ CFat *pfat = pms->GetFat();
+ USHORT cbSector = pms->GetSectorSize();
+ USHORT uShift = pms->GetSectorShift();
+ USHORT uMask = pms->GetSectorMask();
+
+
+
+ if ((_ulSize < MINISTREAMSIZE) &&
+ (sid != SIDMINISTREAM))
+ {
+ msfAssert(sid <= MAXREGSID);
+
+ // This stream is stored in the ministream
+
+ cbSector = MINISECTORSIZE;
+ uShift = MINISECTORSHIFT;
+ uMask = cbSector - 1;
+ pfat = pms->GetMiniFat();
+ }
+
+ SECT start = (SECT)(ulOffset >> uShift);
+ OFFSET oStart = (OFFSET)(ulOffset & uMask);
+
+ SECT end = (SECT)((ulOffset + ulCount - 1) >> uShift);
+ OFFSET oEnd = (OFFSET)((ulOffset + ulCount - 1) & uMask);
+
+ ULONG total = 0;
+
+ ULONG cSect = end - start + 1;
+
+ SECT sectSidStart;
+
+ USHORT offset;
+ offset = oStart;
+
+ while (TRUE)
+ {
+ SECT sect;
+
+ if (start > _stmc.GetOffset())
+ {
+ msfChk(pfat->GetSect(
+ _stmc.GetSect(),
+ start - _stmc.GetOffset(),
+ &sect));
+ }
+ else if (start == _stmc.GetOffset())
+ {
+ sect = _stmc.GetSect();
+ }
+ else
+ {
+ msfChk(pms->GetDir()->GetStart(sid, &sectSidStart));
+ msfChk(pfat->GetSect(sectSidStart, start, &sect));
+ }
+
+ SSegment segtab[CSEG + 1];
+
+ msfChk(pfat->Contig(
+ (SSegment STACKBASED *) segtab,
+ sect,
+ cSect));
+
+ USHORT oend = cbSector - 1;
+ for (USHORT iseg = 0; iseg < CSEG;)
+ {
+ msfDebugOut((DEB_ITRACE,"Segment: (%lu,%lu)\n",segtab[iseg].sectStart,segtab[iseg].cSect));
+ SECT sectStart = segtab[iseg].sectStart;
+ ULONG i = segtab[iseg].cSect;
+ cSect -= i;
+ start += i;
+
+ iseg++;
+ if (segtab[iseg].sectStart == ENDOFCHAIN)
+ oend = oEnd;
+
+ ULONG ulSize = ((i - 1) << uShift) - offset + oend + 1;
+
+ ULONG bytecount;
+ SCODE sc;
+
+ if (pms->GetMiniFat() == pfat)
+ {
+ sc = pms->GetMiniStream()->CDirectStream::ReadAt(
+ (sectStart << uShift) + offset,
+ pBuffer, ulSize,
+ (ULONG STACKBASED *)&bytecount);
+ }
+ else
+ {
+ ULARGE_INTEGER ulOffset;
+ ULISet32(ulOffset, ConvertSectOffset(sectStart,offset,uShift));
+ sc = DfGetScode(pms->GetILB()->ReadAt(ulOffset,
+ (BYTE *)pBuffer, ulSize,
+ &bytecount));
+ }
+
+ total += bytecount;
+ if ((0 == cSect) || (FAILED(sc)))
+ {
+ _stmc.SetCache(start - 1, sectStart + i - 1);
+ *pulRetval = total;
+ msfDebugOut((DEB_TRACE,
+ "Leaving CDirectStream::ReadAt()=>%lu, ret is %lu\n",
+ sc,*pulRetval));
+ return sc;
+ }
+
+ pBuffer = (BYTE HUGEP *)pBuffer + bytecount;
+ offset = 0;
+ }
+ }
+
+ msfDebugOut((DEB_ERROR,"In CDirectStream::ReadAt - reached end of function\n"));
+Err:
+ return sc;
+}
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectStream::Write, public
+//
+// Synposis: Writes binary data from a linear single stream
+//
+// Effects: Modifies _ulSeekPos. May cause modification in parent
+// MStream.
+//
+// Arguments: [pBuffer] -- Pointer to the area from which the data
+// will be written.
+// [ulCount] -- Indicates the number of bytes to be written
+// [pulRetval] -- Pointer to area in which number of bytes
+// will be returned
+//
+// Returns: Error code of MStream call.
+//
+// Algorithm: Calculate sector and offset for beginning and end of
+// write, then pass call up to MStream.
+//
+//
+// Notes:
+//
+//---------------------------------------------------------------------------
+
+
+SCODE CDirectStream::WriteAt(
+ ULONG ulOffset,
+ VOID const HUGEP *pBuffer,
+ ULONG ulCount,
+ ULONG STACKBASED *pulRetval)
+{
+ msfDebugOut((DEB_TRACE,"In CDirectStream::WriteAt(%lu,%p,%lu)\n",ulOffset,pBuffer,ulCount));
+
+ *pulRetval = 0;
+
+ if (0 == ulCount)
+ return S_OK;
+
+ SCODE sc;
+
+ if (ulOffset + ulCount > _ulSize)
+ {
+ if (_ulSize > MINISTREAMSIZE)
+ {
+ }
+ else
+ {
+ msfChk(SetSize(ulOffset + ulCount));
+ }
+ }
+
+ CMStream MSTREAM_NEAR *pms;
+ pms = _stmh.GetMS();
+ msfAssert(pms != NULL);
+
+ // This should be an inline call to MWrite
+
+ msfChk(pms->MWrite(
+ _stmh.GetSid(),
+ (_ulSize < MINISTREAMSIZE),
+ ulOffset,
+ pBuffer,
+ ulCount,
+ &_stmc,
+ pulRetval));
+
+ msfAssert(*pulRetval == ulCount);
+
+ msfDebugOut((DEB_TRACE,"Leaving CDirectStream::WriteAt()==>%lu, ret is %lu\n",sc,*pulRetval));
+
+Err:
+ if (ulOffset + *pulRetval > _ulSize)
+ {
+ SCODE scSet;
+
+ _ulSize = ulOffset + *pulRetval;
+ scSet = pms->GetDir()->SetSize(_stmh.GetSid(), _ulSize);
+ if (SUCCEEDED(sc) && FAILED(scSet))
+ {
+ sc = scSet;
+ }
+ }
+
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Member: CDirectStream::SetSize, public
+//
+// Synposis: Set the size of a linear stream
+//
+// Effects: Modifies _ulSize. May cause change in parent MStream.
+//
+// Arguments: [ulNewSize] -- New size for stream
+//
+// Returns: Error code returned by MStream call.
+//
+// Algorithm: Pass call up to parent.
+//
+// Notes: When changing the size of a stream, we need to be concerned
+// with the cases where each stream is either zero length,
+// stored in the ministream, or stored in a regular stream. The following
+// grid shows the actions that we must perform in each case:
+//
+// New Sector Count (Cn)
+//
+// 0 S L
+// O ------------------------------------------------
+// l | same size | allocate Cn | allocate Cn
+// d 0 | (fast out) | small sectors | large sectors
+// ------------------------------------------------
+// S | small | Co > Cn: | cbCopy = cbOld
+// e S | setchain(Cn) | small | large allocate Cn
+// c | | setchain(Cn)| copy bytes
+// t | | Cn > Co: | small setchain(0)
+// o | | extend small | copy data
+// r ------------------------------------------------
+// L | large | cbCopy = cbNew| Co > Cn:
+// C | setchain(Cn) | small | large setchain(Cn)
+// o | | allocate Cn | Cn > Co:
+// u | | copy bytes | extend large
+// n | | large |
+// t | | setchain(0) |
+// | | copy data |
+// (Co) ------------------------------------------------
+//
+// where S indicates small sectors, L indicates large sectors, and Cx
+// represents count of sectors. For example, the middle box represents
+// doing a setsize on a stream which is currently stored in a small
+// stream in Co small sectors and which will end up in a large stream
+// with Cn sectors.
+//
+//---------------------------------------------------------------------------
+
+
+SCODE CDirectStream::SetSize(ULONG cbNewSize)
+{
+ msfDebugOut((DEB_TRACE,"In CDirectStream::SetSize(%lu)\n",cbNewSize));
+
+ SCODE sc = S_OK;
+ BYTE *pBuf = NULL;
+ SID sid = _stmh.GetSid();
+ CMStream MSTREAM_NEAR *pms = _stmh.GetMS();
+ msfAssert(sid <= MAXREGSID);
+ CDirectory *pdir = pms->GetDir();
+ SECT sectOldStart;
+
+ if (_ulSize == cbNewSize)
+ {
+ return S_OK;
+ }
+
+ USHORT cbpsOld = pms->GetSectorSize();
+ // Count of Bytes Per Sector
+ USHORT cbpsNew = cbpsOld;
+ CFat *pfatOld = pms->GetFat();
+ CFat *pfatNew = pfatOld;
+
+ if (SIDMINISTREAM != sid)
+ {
+
+ if (cbNewSize < MINISTREAMSIZE)
+ {
+ cbpsNew = MINISECTORSIZE;
+ pfatNew = pms->GetMiniFat();
+ }
+
+ if (_ulSize < MINISTREAMSIZE)
+ {
+ cbpsOld = MINISECTORSIZE;
+ pfatOld = pms->GetMiniFat();
+ }
+ }
+
+ ULONG csectOld = (ULONG)(_ulSize + cbpsOld - 1) / (ULONG) cbpsOld;
+ ULONG csectNew = (ULONG)(cbNewSize + cbpsNew - 1) / (ULONG) cbpsNew;
+
+ msfAssert(sid <= MAXREGSID);
+ SECT sectstart;
+ msfChk(pdir->GetStart(sid, &sectstart));
+
+ msfDebugOut((DEB_ITRACE,"pdbOld size is %lu\n\tSid is %lu\n\tStart is %lu\n",
+ _ulSize,sid,sectstart));
+ msfDebugOut((DEB_ITRACE,"CMStream::SetSize() needs %lu %u byte sectors\n",
+ csectNew, cbpsNew));
+ msfDebugOut((DEB_ITRACE,"SetSize() currently has %lu %u byte sectors\n",
+ csectOld, cbpsOld));
+
+ USHORT cbCopy;
+ cbCopy = 0;
+ if (cbpsOld != cbpsNew)
+ {
+ // Sector sizes are different, so we'll copy the data
+ msfAssert((cbNewSize > _ulSize ? _ulSize : cbNewSize) < 0x10000);
+ cbCopy =(USHORT)(cbNewSize > _ulSize ? _ulSize : cbNewSize);
+ }
+
+
+ if (cbCopy > 0)
+ {
+ msfDebugOut((DEB_ITRACE,"Copying between fat and minifat\n"));
+ GetSafeBuffer(cbCopy, cbCopy, &pBuf, &cbCopy);
+ msfAssert((pBuf != NULL) && aMsg("Couldn't get scratch buffer"));
+
+ ULONG ulRetVal;
+ sc = ReadAt(0, pBuf, cbCopy, (ULONG STACKBASED *)&ulRetVal);
+ if ((FAILED(sc)) ||
+ ((ulRetVal != cbCopy) ? (sc = STG_E_UNKNOWN) : 0))
+ {
+ msfErr(Err, sc);
+ }
+
+ //The cache is no longer valid, so empty it.
+ _stmc.SetCache(MAX_ULONG, ENDOFCHAIN);
+
+ //Save start sector so we can free it later.
+ sectOldStart = sectstart;
+
+ msfChk(pfatNew->Allocate(csectNew, &sectstart));
+ }
+ else
+ {
+ SECT dummy;
+
+ if ((csectOld > csectNew))
+ {
+ msfChk(pfatOld->SetChainLength(sectstart, csectNew));
+ if (0 == csectNew)
+ {
+ sectstart = ENDOFCHAIN;
+ }
+
+ //If this turns out to be a common case, we can
+ // sometimes keep the cache valid here.
+ _stmc.SetCache(MAX_ULONG, ENDOFCHAIN);
+ }
+ else if (0 == csectOld)
+ {
+ msfAssert(_stmc.GetOffset() == MAX_ULONG);
+ msfChk(pfatNew->Allocate(csectNew, &sectstart));
+ }
+ else if (csectNew > csectOld)
+ {
+ ULONG start = csectNew - 1;
+
+ if (start > _stmc.GetOffset())
+ {
+ msfChk(pfatNew->GetESect(
+ _stmc.GetSect(),
+ start - _stmc.GetOffset(),
+ &dummy));
+ }
+ else if (start != _stmc.GetOffset())
+ {
+ msfChk(pfatNew->GetESect(sectstart, start, &dummy));
+ }
+ }
+ }
+
+
+ // Resize the ministream, if necessary
+ if (((MINISECTORSIZE == cbpsOld) && (csectOld > 0)) ||
+ ((MINISECTORSIZE == cbpsNew) && (csectNew > 0)))
+ {
+ msfChk(pms->SetMiniSize());
+ }
+
+ msfChk(pms->SetSize());
+
+ //If we fail on either of these operations and cbCopy != 0,
+ // we will have data loss. Ick.
+ msfChk(pdir->SetStart(sid, sectstart));
+
+ //If we fail here, we're screwed.
+ msfChk(pdir->SetSize(sid, cbNewSize));
+
+ _ulSize = cbNewSize;
+
+ if (cbCopy > 0)
+ {
+ // now copy the data
+ ULONG ulRetVal;
+
+ msfAssert(cbCopy <= _ulSize);
+ msfChk(WriteAt(0, pBuf, cbCopy, (ULONG STACKBASED *)&ulRetVal));
+
+ if (ulRetVal != cbCopy)
+ {
+ msfErr(Err, STG_E_UNKNOWN);
+ }
+
+ msfChk(pfatOld->SetChainLength(sectOldStart, 0));
+ msfChk(pms->SetMiniSize());
+ msfChk(pms->SetSize());
+ }
+
+ if (((csectNew > csectOld) || (cbCopy > 0)) &&
+ ((cbNewSize & (cbpsNew - 1)) != 0))
+ {
+ SECT sectLast;
+ if (csectNew - 1 > _stmc.GetOffset())
+ {
+ msfChk(pfatNew->GetSect(
+ _stmc.GetSect(),
+ (csectNew - 1) - _stmc.GetOffset(),
+ &sectLast));
+ }
+ else
+ {
+ msfChk(pfatNew->GetSect(sectstart, csectNew - 1, &sectLast));
+ }
+
+ msfVerify(SUCCEEDED(pms->SecureSect(
+ sectLast,
+ cbNewSize,
+ (cbNewSize < MINISTREAMSIZE) && (sid != SIDMINISTREAM))));
+ }
+Err:
+ FreeBuffer(pBuf);
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirectStream::Release, public
+//
+// Synopsis: Decrements the ref count and frees if necessary
+//
+//----------------------------------------------------------------------------
+
+
+void CDirectStream::Release(VOID)
+{
+ msfDebugOut((DEB_TRACE,"In CDirectStream::Release()\n"));
+ msfAssert(_cReferences > 0);
+
+ AtomicDec(&_cReferences);
+ if (_cReferences == 0)
+ delete this;
+ msfDebugOut((DEB_TRACE,"Out CDirectStream::Release()\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDirectStream::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+//---------------------------------------------------------------
+
+
+void CDirectStream::AddRef(void)
+{
+ msfDebugOut((DEB_ITRACE, "In CDirectStream::AddRef()\n"));
+ AtomicInc(&_cReferences);
+ msfDebugOut((DEB_ITRACE, "Out CDirectStream::AddRef, %lu\n",
+ _cReferences));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CDirectStream::GetSize, public
+//
+// Synopsis: Gets the size of the stream
+//
+// Arguments: [pulSize] - Size return
+//
+// Modifies: [pulSize]
+//
+//----------------------------------------------------------------------------
+
+void CDirectStream::GetSize(ULONG *pulSize)
+{
+ *pulSize = _ulSize;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDirectStream::GetTime, public
+//
+// Synopsis: Gets a time
+//
+// Arguments: [wt] - Which time
+// [ptm] - Time return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ptm]
+//
+//---------------------------------------------------------------
+
+SCODE CDirectStream::GetTime(WHICHTIME wt, TIME_T *ptm)
+{
+ return _stmh.GetTime(wt, ptm);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CDirectStream::SetTime, public
+//
+// Synopsis: Sets a time
+//
+// Arguments: [wt] - Which time
+// [tm] - New time
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+SCODE CDirectStream::SetTime(WHICHTIME wt, TIME_T tm)
+{
+ return _stmh.SetTime(wt, tm);
+}
+
+
diff --git a/private/ole32/stg/ref/storage.cxx b/private/ole32/stg/ref/storage.cxx
new file mode 100644
index 000000000..d9d8fc29c
--- /dev/null
+++ b/private/ole32/stg/ref/storage.cxx
@@ -0,0 +1,173 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: storage.cxx
+//
+// Contents: Contains generic storage APIs
+//
+//---------------------------------------------------------------
+
+
+#include <ref.hxx>
+#include <dfexcept.hxx>
+#include <dfentry.hxx>
+#include <storagep.h>
+#include <dfmsp.hxx>
+
+#define MAKE_ERR(c) MAKE_SCODE(SEVERITY_ERROR, FACILITY_STORAGE, c)
+
+//+--------------------------------------------------------------
+//
+// Function: StgOpenStorage, public
+//
+// Synopsis: Instantiates a root storage from a file
+// by binding to the appropriate implementation
+// and starting things up
+//
+// Arguments: [pwcsName] - Name
+// [pstgPriority] - Priority mode reopen IStorage
+// [grfMode] - Permissions
+// [snbExclude] - Exclusions for priority reopen
+// [reserved]
+// [ppstgOpen] - Docfile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstgOpen]
+//
+//---------------------------------------------------------------
+
+STDAPI StgOpenStorage(TCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstgOpen)
+{
+ return ResultFromScode(STG_E_UNIMPLEMENTEDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Function: StgOpenStorageOnILockBytes, public
+//
+// Synopsis: Instantiates a root storage from an ILockBytes
+// by binding to the appropriate implementation
+// and starting things up
+//
+// Arguments: [plkbyt] - Source ILockBytes
+// [pstgPriority] - For priority reopens
+// [grfMode] - Permissions
+// [snbExclude] - For priority reopens
+// [reserved]
+// [ppstgOpen] - Docfile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstgOpen]
+//
+//---------------------------------------------------------------
+
+STDAPI StgOpenStorageOnILockBytes(ILockBytes *plkbyt,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstgOpen)
+{
+ CLSID cid;
+
+ return DfOpenStorageOnILockBytes(plkbyt, pstgPriority, grfMode,
+ snbExclude, reserved, ppstgOpen,
+ &cid);
+}
+
+//+--------------------------------------------------------------
+//
+// Function: StgIsStorageFile, public
+//
+// Synopsis: Determines whether the named file is a storage or not
+//
+// Arguments: [pwcsName] - Filename
+//
+// Returns: S_OK, S_FALSE or error codes
+//
+//---------------------------------------------------------------
+
+//Identifier for first bytes of Beta 2 Docfiles
+const BYTE SIGSTG_B2[] = {0x0e, 0x11, 0xfc, 0x0d, 0xd0, 0xcf, 0x11, 0xe0};
+const BYTE CBSIGSTG_B2 = sizeof(SIGSTG_B2);
+
+STDAPI StgIsStorageFile(TCHAR const *pwcsName)
+{
+ return ResultFromScode(STG_E_UNIMPLEMENTEDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Function: StgIsStorageILockBytes, public
+//
+// Synopsis: Determines whether the ILockBytes is a storage or not
+//
+// Arguments: [plkbyt] - The ILockBytes
+//
+// Returns: S_OK, S_FALSE or error codes
+//
+//---------------------------------------------------------------
+
+STDAPI StgIsStorageILockBytes(ILockBytes *plkbyt)
+{
+ HRESULT hr;
+ SCODE sc;
+ SStorageFile stgfile;
+ ULONG cbRead;
+ ULARGE_INTEGER ulOffset;
+
+ TRY
+ {
+ if (FAILED(sc = ValidateInterface(plkbyt, IID_ILockBytes)))
+ return ResultFromScode(sc);
+ ULISet32(ulOffset, 0);
+ hr = plkbyt->ReadAt(ulOffset, &stgfile, sizeof(stgfile), &cbRead);
+ if (FAILED(GetScode(hr)))
+ return hr;
+ }
+ CATCH(CException, e)
+ {
+ return ResultFromScode(e.GetErrorCode());
+ }
+ END_CATCH
+
+ if (cbRead == sizeof(stgfile))
+ {
+ if ((memcmp((void *)stgfile.abSig, SIGSTG, CBSIGSTG) == 0) ||
+ (memcmp((void *)stgfile.abSig, SIGSTG_B2, CBSIGSTG_B2) == 0))
+ return ResultFromScode(S_OK);
+ }
+ return ResultFromScode(S_FALSE);
+}
+
+//+--------------------------------------------------------------
+//
+// Function: StgSetTimes
+//
+// Synopsis: Sets file time stamps
+//
+// Arguments: [lpszName] - Name
+// [pctime] - create time
+// [patime] - access time
+// [pmtime] - modify time
+//
+// Returns: Appropriate status code
+//
+//---------------------------------------------------------------
+
+STDAPI StgSetTimes(TCHAR const *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ return ResultFromScode(STG_E_UNIMPLEMENTEDFUNCTION);
+}
diff --git a/private/ole32/stg/ref/storage.def b/private/ole32/stg/ref/storage.def
new file mode 100644
index 000000000..9c43688ef
--- /dev/null
+++ b/private/ole32/stg/ref/storage.def
@@ -0,0 +1,7 @@
+EXETYPE WINDOWS
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 16384
+STACKSIZE 8192
diff --git a/private/ole32/stg/ref/time16.cxx b/private/ole32/stg/ref/time16.cxx
new file mode 100644
index 000000000..08bc8c1ad
--- /dev/null
+++ b/private/ole32/stg/ref/time16.cxx
@@ -0,0 +1,25 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: Time16.CXX
+//
+// Contents: Time conversion routines (16-bit only)
+//
+// Functions: DfGetTOD
+//
+// Notes: These functions come from NT - time.c
+//
+//--------------------------------------------------------------------------
+#include <exphead.cxx>
+
+#include <time16.hxx>
+#include <dos.h>
+
+SCODE DfGetTOD(TIME_T *pft)
+{
+ //REFBUG: A time of day function needs to be provided for any port of this
+ // code.
+ return S_OK;
+}
diff --git a/private/ole32/stg/ref/time16.hxx b/private/ole32/stg/ref/time16.hxx
new file mode 100644
index 000000000..719b02ae4
--- /dev/null
+++ b/private/ole32/stg/ref/time16.hxx
@@ -0,0 +1,19 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: time16.hxx
+//
+// Contents: DocFile Time support (16-bit only)
+//
+//--------------------------------------------------------------------------
+
+#ifndef __TIME16_HXX__
+#define __TIME16_HXX__
+
+#include <time.h>
+
+BOOL tmToFileTime(struct tm *ptm, FILETIME *pft);
+
+#endif
diff --git a/private/ole32/stg/ref/vect.cxx b/private/ole32/stg/ref/vect.cxx
new file mode 100644
index 000000000..4664c7fcf
--- /dev/null
+++ b/private/ole32/stg/ref/vect.cxx
@@ -0,0 +1,456 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: vect.cxx
+//
+// Contents: Vector common code.
+//
+// Classes:
+//
+// Functions:
+//
+//----------------------------------------------------------------------------
+
+#include <msfhead.cxx>
+
+
+#include <vect.hxx>
+
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPagedVector::Init, public
+//
+// Synopsis: CPagedVector initialization function
+//
+// Arguments: [ulSize] -- size of vector
+// [uFatEntries] -- number of entries in each table
+//
+// Algorithm: Allocate an array of pointer of size ulSize
+// For each cell in the array, allocate a CFatSect
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE VECT_NEAR CPagedVector::Init(CMStream *pmsParent, ULONG ulSize)
+{
+ msfDebugOut((DEB_ITRACE,"In CPagedVector::CPagedVector(%lu)\n",ulSize));
+ SCODE sc = S_OK;
+ _pmsParent = pmsParent;
+ _pmpt = _pmsParent->GetPageTable();
+
+ msfAssert(_pmpt != NULL);
+
+ USHORT i;
+
+ // We don't bother allocating more than necessary here
+ _ulAllocSize = _ulSize = ulSize;
+
+ if (_ulSize > 0)
+ {
+
+ msfMem(_amp = GetNewPageArray(ulSize));
+ for (i = 0; i < _ulSize; i++)
+ {
+ _amp[i] = NULL;
+ }
+ msfMem(_avb = GetNewVectBits(ulSize));
+ }
+
+ msfDebugOut((DEB_ITRACE,"Out CPagedVector::CPagedVector()\n"));
+ return S_OK;
+
+Err:
+ //In the error case, discard whatever vectors we were able to allocate
+ // and return S_OK.
+ delete [] _amp;
+ _amp = NULL;
+
+ delete [] _avb;
+ _avb = NULL;
+
+ return S_OK;
+
+}
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPagedVector::~CPagedVector, public
+//
+// Synopsis: CPagedVector constructor
+//
+// Algorithm: Delete the pointer array.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+VECT_NEAR CPagedVector::~CPagedVector()
+{
+ delete [] _amp;
+ delete [] _avb;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::Empty, public
+//
+// Synopsis: Discard the storage associated with this vector.
+//
+// Arguments: None.
+//
+// Returns: void.
+//
+//----------------------------------------------------------------------------
+
+void CPagedVector::Empty(void)
+{
+ if (_pmpt != NULL)
+ {
+ _pmpt->FreePages(this);
+ }
+ delete [] _amp;
+ delete [] _avb;
+ _amp = NULL;
+ _avb = NULL;
+ _pmpt = NULL;
+ _ulAllocSize = _ulSize = 0;
+ _pmsParent = NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::Flush, public
+//
+// Synopsis: Flush the dirty pages for this vector
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+//----------------------------------------------------------------------------
+
+SCODE CPagedVector::Flush(void)
+{
+ SCODE sc;
+ SCODE scRet = S_OK;
+
+ if (_ulSize > 0)
+ {
+ if (_amp != NULL)
+ {
+ for (USHORT i = 0; i < _ulSize; i++)
+ {
+ if ((_amp[i] != NULL) && (_amp[i]->IsDirty()))
+ {
+ sc = _pmpt->FlushPage(_amp[i]);
+ if ((FAILED(sc)) && (SUCCEEDED(scRet)))
+ {
+ scRet = sc;
+ }
+ }
+ }
+ }
+ else
+ {
+ scRet = _pmpt->Flush();
+ }
+ }
+
+ return scRet;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPagedVector::GetTable, public
+//
+// Synopsis: Return a pointer to a page for the given index
+// into the vector.
+//
+// Arguments: [iTable] -- index into vector
+// [ppmp] -- Pointer to return location
+//
+// Returns: S_OK if call completed OK.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE VECT_NEAR CPagedVector::GetTable(
+ const FSINDEX iTable,
+ DWORD dwFlags,
+ void **ppmp)
+{
+ SCODE sc = S_OK;
+ CMSFPage *pmp;
+
+ msfAssert((_pmsParent->GetILB() != NULL) &&
+ aMsg("Null ILB found on GetTable - need SetAccess call?"));
+
+ if ((_amp == NULL) || (_amp[iTable] == NULL))
+ {
+ if (dwFlags & FB_NEW)
+ {
+ //We know that the page isn't in the page table,
+ // so we can just get a free page an allocate it
+ // ourselves.
+
+ msfChk(_pmpt->GetFreePage(&pmp));
+
+ pmp->SetVector(this);
+ pmp->SetSid(_sid);
+ pmp->SetOffset(iTable);
+ pmp->SetSect(ENDOFCHAIN);
+
+ sc = STG_S_NEWPAGE;
+ dwFlags = (dwFlags & ~FB_NEW) | FB_DIRTY;
+ }
+ else
+ {
+ msfChk(_pmpt->GetPage(this, _sid, iTable, &pmp));
+ msfAssert((pmp->GetVector() == this) &&
+ aMsg("GetPage returned wrong page."));
+ }
+
+
+ if (_amp != NULL)
+ {
+ _amp[iTable] = pmp;
+ }
+
+ }
+ else
+ {
+ pmp = _amp[iTable];
+ msfAssert((pmp->GetVector() == this) &&
+ aMsg("Cached page has wrong vector pointer"));
+ }
+
+ pmp->AddRef();
+
+ if (((dwFlags & FB_DIRTY) && !(pmp->IsDirty())) &&
+ (sc != STG_S_NEWPAGE))
+ {
+ //If we are not a newly created page, and we are being
+ // dirtied for the first time, make sure that our
+ // _sect field is correct.
+ //
+ //Newly created pages have to have their sect set manually
+ // _before_ being released. This is very important.
+
+ pmp->SetSect(ENDOFCHAIN);
+
+ SECT sect;
+ msfChkTo(Err_Rel, _pmsParent->GetESect(
+ pmp->GetSid(),
+ pmp->GetOffset(),
+ &sect));
+
+ pmp->SetSect(sect);
+ }
+
+ pmp->SetFlags(pmp->GetFlags() | dwFlags | FB_TOUCHED);
+ msfAssert((pmp->GetVector() == this) &&
+ aMsg("GetTable returned wrong page."));
+ *ppmp = pmp->GetData();
+
+Err:
+ return sc;
+
+Err_Rel:
+ pmp->Release();
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CPagedVector::SetDirty, public
+//
+// Synopsis: Set the dirty bit on the specified page
+//
+// Arguments: [iTable] -- Table to set bit on
+//
+// Notes: This function is always called on a page with an
+// open reference. Therefore, the page is
+// guaranteed to be in the page table, and that
+// FindPage call should never return an error.
+//
+//----------------------------------------------------------------------------
+
+SCODE CPagedVector::SetDirty(ULONG iTable)
+{
+ SCODE sc = S_OK;
+ CMSFPage *pmp;
+
+
+ if (_amp == NULL)
+ {
+
+ msfChk(_pmpt->FindPage(this, _sid, iTable, &pmp));
+ msfAssert(sc == STG_S_FOUND);
+ msfAssert(pmp->IsInUse() &&
+ aMsg("Called SetDirty on page not in use."));
+ }
+ else
+ {
+ msfAssert(_amp != NULL);
+ msfAssert(_amp[iTable] != NULL);
+ pmp = _amp[iTable];
+ }
+
+ if (!pmp->IsDirty())
+ {
+ //We are not a newly created page, and we are being
+ // dirtied for the first time, make sure that our
+ // _sect field is correct.
+ //
+
+ pmp->AddRef();
+
+ pmp->SetSect(ENDOFCHAIN);
+
+ SECT sect;
+ msfChkTo(Err_Rel, _pmsParent->GetESect(
+ pmp->GetSid(),
+ pmp->GetOffset(),
+ &sect));
+
+ pmp->SetSect(sect);
+
+ pmp->Release();
+ }
+
+ pmp->SetDirty();
+
+ Err:
+ return sc;
+
+ Err_Rel:
+ pmp->Release();
+ return sc;
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Method: CPagedVector::Resize, public
+//
+// Synopsis: Resize a CPagedVector
+//
+// Arguments: [ulSize] -- Size of new vector
+//
+// Algorithm: Create new pointer array of size ulSize.
+// For each entry in old array, copy the pointer over.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+#define LARGETHRESHOLD 1024
+#define VECTORBLOCK 1024 // Must be power of 2
+
+SCODE VECT_NEAR CPagedVector::Resize(FSINDEX ulSize)
+{
+ msfDebugOut((DEB_ITRACE,"In CPagedVector::CPagedVector(%lu)\n",ulSize));
+
+ msfAssert(ulSize >= _ulSize);
+ msfAssert(_ulSize <= _ulAllocSize);
+ msfAssert(((VECTORBLOCK & (VECTORBLOCK - 1)) == 0) &&
+ aMsg("VECTORBLOCK must be power of 2"));
+
+ msfAssert(!((_amp == NULL) && (_avb != NULL)) &&
+ aMsg("Resize precondition failed."));
+
+ if (ulSize > _ulAllocSize)
+ {
+ // We don't have room in the existing vector; grow it
+ ULONG ulNewAllocSize = ulSize;
+
+ if (ulNewAllocSize > LARGETHRESHOLD)
+ {
+ // We're dealing with a large vector; grow it a VECTORBLOCK
+ // at a time
+ ulNewAllocSize = (ulNewAllocSize + VECTORBLOCK - 1) &
+ ~(VECTORBLOCK - 1);
+ }
+
+ CMSFPage **amp = GetNewPageArray(ulNewAllocSize);
+ CVectBits *avb = GetNewVectBits(ulNewAllocSize);
+
+ // Can't fail after this point
+
+ _ulAllocSize = ulNewAllocSize;
+
+ // Copy over the old entries
+
+
+ if ((amp != NULL) && (avb != NULL))
+ {
+ if ((_amp != NULL) && (_avb != NULL))
+ {
+ // Both allocations succeeded
+ for (ULONG iamp = 0; iamp < _ulSize; iamp++)
+ {
+ amp[iamp] = _amp[iamp];
+ avb[iamp] = _avb[iamp];
+ }
+ }
+ else if (_amp != NULL)
+ {
+ for (ULONG iamp = 0; iamp < _ulSize; iamp++)
+ {
+ amp[iamp] = _amp[iamp];
+ }
+ }
+ else
+ {
+ for (ULONG iamp = 0; iamp < _ulSize; iamp++)
+ {
+ amp[iamp] = NULL;
+ }
+ }
+ }
+ else
+ {
+ // At least one of the allocations failed
+ delete [] avb;
+ avb = NULL;
+
+ delete [] amp;
+ amp = NULL;
+ }
+
+ // Delete the old vector and put in the new one (if any).
+ // In the error case, throw away the vectors we are currently
+ // holding (since they are of insufficient size) and return S_OK.
+
+ delete [] _amp;
+ _amp = amp;
+
+ delete [] _avb;
+ _avb = avb;
+ }
+
+ if (_amp != NULL)
+ {
+ // Initialize the new elements in the vector
+
+ for (ULONG iamp = _ulSize; iamp < ulSize; iamp++)
+ _amp[iamp] = NULL;
+ }
+
+ _ulSize = ulSize;
+
+ msfDebugOut((DEB_ITRACE,"Out CPagedVector resize constructor\n"));
+ return S_OK;
+}
+
+
+
diff --git a/private/ole32/stg/ref/wcscat.c b/private/ole32/stg/ref/wcscat.c
new file mode 100644
index 000000000..28e683ded
--- /dev/null
+++ b/private/ole32/stg/ref/wcscat.c
@@ -0,0 +1,77 @@
+/***
+*wcscat.c - contains wcscat() and wcscpy()
+*
+* Copyright (c) 1985-1988, Microsoft Corporation. All Rights Reserved.
+*
+*Purpose:
+* wcscpy() copies one wide character string onto another.
+*
+* Wcscat() concatenates (appends) a copy of the source wide character
+* string to the end of the destination wide character string, returning
+* the destination wide character string.
+*
+*Revision History:
+*
+*******************************************************************************/
+
+#include <wchar.h>
+
+/***
+*wchar_t *wcscat(dst, src) - concatenate (append) one wide character string
+* to another
+*
+*Purpose:
+* Concatenates src onto the end of dest. Assumes enough
+* space in dest.
+*
+*Entry:
+* wchar_t *dst - wide character string to which "src" is to be appended
+* const wchar_t *src - wide character string to append to end of "dst"
+*
+*Exit:
+* The address of "dst"
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CRTAPI1 wcscat(wchar_t * dst, const wchar_t * src)
+{
+ wchar_t * cp = dst;
+
+ while( *cp )
+ ++cp; /* Find end of dst */
+
+ wcscpy(cp,src); /* Copy src to end of dst */
+
+ return dst; /* return dst */
+
+}
+
+
+/***
+*wchar_t *wcscpy(dst, src) - copy one wide character string over another
+*
+*Purpose:
+* Copies the wide character string src into the spot specified by
+* dest; assumes enough room.
+*
+*Entry:
+* wchar_t * dst - wide character string over which "src" is to be copied
+* const wchar_t * src - string to be copied over "dst"
+*
+*Exit:
+* The address of "dst"
+*
+*Exceptions:
+*******************************************************************************/
+
+wchar_t * _CRTAPI1 wcscpy(wchar_t * dst, const wchar_t * src)
+{
+ wchar_t * cp = dst;
+
+ while( *cp++ = *src++ )
+ ; /* Copy src over dst */
+
+ return dst;
+}
diff --git a/private/ole32/stg/ref/wcslen.c b/private/ole32/stg/ref/wcslen.c
new file mode 100644
index 000000000..333b34128
--- /dev/null
+++ b/private/ole32/stg/ref/wcslen.c
@@ -0,0 +1,39 @@
+/***
+*wcslen.c - contains wcslen() routine
+*
+* Copyright (c) 1985-1988, Microsoft Corporation. All Rights Reserved.
+*
+*Purpose:
+* wcslen returns the length of a null-terminated string in number of
+* wide characters, not including the null wide character itself.
+*
+*******************************************************************************/
+
+#include <wchar.h>
+
+/***
+*wcslen - return the length of a null-terminated string
+*
+*Purpose:
+* Finds the number of wide characters in the given wide character
+* string, not including the final null character.
+*
+*Entry:
+* const wchat_t * str - string whose length is to be computed
+*
+*Exit:
+* length of the string "str", exclusive of the final null wide character
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CRTAPI1 wcslen(const wchar_t * str)
+{
+ wchar_t *string = (wchar_t *) str;
+
+ while( *string )
+ string++;
+
+ return string - str;
+}
diff --git a/private/ole32/stg/ref/wcsnicmp.c b/private/ole32/stg/ref/wcsnicmp.c
new file mode 100644
index 000000000..856330ac2
--- /dev/null
+++ b/private/ole32/stg/ref/wcsnicmp.c
@@ -0,0 +1,64 @@
+/***
+*wcsnicmp.c - compare first n characters of two wide character strings with
+* case insensitivity
+*
+* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsnicmp() - compare first n characters of two wide character
+* strings for lexical order with case insensitivity.
+*
+*Revision History:
+*
+*******************************************************************************/
+
+#include <wchar.h>
+/***
+*wchar_t wcUp(wc) - upper case wide character
+*
+*/
+
+static wchar_t wcUp(wchar_t wc)
+{
+ if ('a' <= wc && wc <= 'z')
+ wc += (wchar_t)('A' - 'a');
+
+ return(wc);
+}
+
+/***
+*int wcsnicmp(first, last, count) - compare first count wide characters of wide
+* character strings with case insensitivity.
+*
+*Purpose:
+* Compares two wide character strings for lexical order. The comparison
+* stops after: (1) a difference between the strings is found, (2) the end
+* of the strings is reached, or (3) count characters have been
+* compared.
+*
+*Entry:
+* char *first, *last - wide character strings to compare
+* unsigned count - maximum number of wide characters to compare
+*
+*Exit:
+* returns <0 if first < last
+* returns 0 if first == last
+* returns >0 if first > last
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 wcsnicmp(const wchar_t * first, const wchar_t * last, size_t count)
+{
+ if (!count)
+ return 0;
+
+ while (--count && *first && wcUp(*first) == wcUp(*last))
+ {
+ first++;
+ last++;
+ }
+
+ return wcUp(*first) - wcUp(*last);
+}
diff --git a/private/ole32/stg/segments.asm b/private/ole32/stg/segments.asm
new file mode 100644
index 000000000..d64570bfd
--- /dev/null
+++ b/private/ole32/stg/segments.asm
@@ -0,0 +1,72 @@
+;//+-------------------------------------------------------------------------
+;//
+;// Microsoft Windows
+;// Copyright (C) Microsoft Corporation, 1992 - 1992.
+;//
+;// File: segments.asm
+;//
+;// Contents: grouping definitions for segments
+;//
+;// History: 06-May-92 AlexT Created
+;//
+;//--------------------------------------------------------------------------
+
+.386
+
+EndMac macro
+ end
+endm
+
+GenSeg macro segname,segalign,segcombine,segtype,segclass,groupname,seglabel
+ segname segment segalign segcombine segtype segclass
+ ifnb <seglabel>
+ public seglabel
+ seglabel label byte
+ endif
+ segname ends
+ ifnb <groupname>
+ groupname group segname
+ endif
+endm
+
+; New segmentation scheme
+
+GenSeg Common0_TEXT word public use16 'CODE' ICOMMON0GROUP
+; Note: COMDAT_SEG1 has virtual function tables
+GenSeg COMDAT_SEG1 word public use16 'CODE' ICOMMON0GROUP
+GenSeg _TEXT word public use16 'CODE' ICOMMON0GROUP
+GenSeg GUID_TEXT word public use16 'CODE' ICOMMON0GROUP
+GenSeg WCSCAT_TEXT word public use16 'CODE' ICOMMON0GROUP
+GenSeg WCSLEN_TEXT word public use16 'CODE' ICOMMON0GROUP
+GenSeg WCSNICMP_TEXT word public use16 'CODE' ICOMMON0GROUP
+
+GenSeg Common1_TEXT word public use16 'CODE' ICOMMON1GROUP
+
+GenSeg Common2_TEXT word public use16 'CODE' ICOMMON2GROUP
+
+GenSeg Boot_TEXT word public use16 'CODE' IBOOTGROUP
+GenSeg BootSave_TEXT word public use16 'CODE' IBOOTGROUP
+GenSeg Save_TEXT word public use16 'CODE' IBOOTGROUP
+
+GenSeg OpenSave0_TEXT word public use16 'CODE' IOPENSAVE0GROUP
+GenSeg OpenSave1_TEXT word public use16 'CODE' IOPENSAVE0GROUP
+GenSeg WEP_TEXT word public use16 'CODE' IOPENSAVE0GROUP
+
+GenSeg Open_TEXT word public use16 'CODE' IOPENGROUP
+GenSeg TransD_TEXT word public use16 'CODE' IOPENGROUP
+GenSeg UnassignedH_TEXT word public use16 'CODE' IOPENGROUP
+
+GenSeg Marshal_TEXT word public use16 'CODE' ICOMMITGROUP
+GenSeg Commit_TEXT word public use16 'CODE' ICOMMITGROUP
+
+GenSeg TransM_TEXT word public use16 'CODE' ITRANSGROUP
+GenSeg UnassignedD_TEXT word public use16 'CODE' ITRANSGROUP
+
+GenSeg UnassignedE_TEXT word public use16 'CODE' IMISC0GROUP
+GenSeg Common3_TEXT word public use16 'CODE' IMISC0GROUP
+GenSeg RareM_TEXT word public use16 'CODE' IMISC0GROUP
+
+GenSeg UnassignedM_TEXT word public use16 'CODE' IMISC1GROUP
+GenSeg RareE_TEXT word public use16 'CODE' IMISC1GROUP
+
+ EndMac
diff --git a/private/ole32/stg/setole2.mk b/private/ole32/stg/setole2.mk
new file mode 100644
index 000000000..44b3e7e9d
--- /dev/null
+++ b/private/ole32/stg/setole2.mk
@@ -0,0 +1,35 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1993 **
+#********************************************************************
+
+!ifndef OLE2H
+! if "$(OPSYS)" == "NT"
+OLE2H = $(COMMON)\types
+! else
+NOCOMMONTYPES = TRUE
+! if "$(PLATFORM)" == "i286"
+OLE2H = $(CAIROLE)\stg\ole2h
+! elseif "$(OPSYS)" == "DOS" || "$(OPSYS)" == "WIN16" || "$(OPSYS)" == "NT1X"
+OLE2H = $(CAIROLE)\h\export
+! endif
+! endif
+!else
+! if "$(OPSYS)" == "NT"
+! error OLE2H cannot be defined for Cairo
+! endif
+! if "$(HOST)" == "DOS"
+# OLE2 project prefixes object directories with L
+ODL = L
+! endif
+!endif
+
+!ifndef OLE2BIN
+! if "$(PLATFORM)" == "i286"
+OLE2BIN = $(CAIROLE)\stg\ole2h
+! endif
+!else
+! if "$(OPSYS)" == "NT"
+! error OLE2BIN cannot be defined for Cairo
+! endif
+!endif
diff --git a/private/ole32/stg/simp/daytona/makefile b/private/ole32/stg/simp/daytona/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ole32/stg/simp/daytona/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/stg/simp/daytona/sources b/private/ole32/stg/simp/daytona/sources
new file mode 100644
index 000000000..c8995eb8c
--- /dev/null
+++ b/private/ole32/stg/simp/daytona/sources
@@ -0,0 +1,82 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= simp
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= LIBRARY
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES=..\..\..\ih;..\..\..\common\daytona;..\..\h;..
+
+
+C_DEFINES= \
+ $(C_DEFINES) \
+
+SOURCES= \
+ ..\simpdf.cxx \
+ ..\simpstg.cxx \
+ ..\simpstm.cxx
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+UMLIBS=
+
+PRECOMPILED_INCLUDE= ..\simphead.cxx
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
diff --git a/private/ole32/stg/simp/dfnlist.hxx b/private/ole32/stg/simp/dfnlist.hxx
new file mode 100644
index 000000000..ba18a13dc
--- /dev/null
+++ b/private/ole32/stg/simp/dfnlist.hxx
@@ -0,0 +1,107 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: dfnlist.hxx
+//
+// Contents: CDfName class
+//
+// Classes:
+//
+// Functions:
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __DFNLIST_HXX__
+#define __DFNLIST_HXX__
+
+#include <dfname.hxx>
+
+//+---------------------------------------------------------------------------
+//
+// Class: CDfNameList
+//
+// Purpose: Linked list of DfNames
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+class CDfNameList
+{
+public:
+ inline CDfName * GetName(void);
+ inline SECT GetStart(void);
+ inline ULONG GetSize(void);
+ inline CDfNameList *GetNext(void);
+
+ inline void SetName(WCHAR const *pwcs);
+ inline void SetStart(SECT sectStart);
+ inline void SetSize(ULONG ulSize);
+
+ inline void Insert(CDfNameList **ppdflStart,
+ CDfNameList *pdflPrev,
+ CDfNameList *pdflNext);
+private:
+ CDfName _df;
+ SECT _sectStart;
+ ULONG _ulSize;
+
+ CDfNameList *_pdflNext;
+};
+
+inline CDfName * CDfNameList::GetName(void)
+{
+ return &_df;
+}
+
+inline SECT CDfNameList::GetStart(void)
+{
+ return _sectStart;
+}
+
+inline ULONG CDfNameList::GetSize(void)
+{
+ return _ulSize;
+}
+
+inline CDfNameList * CDfNameList::GetNext(void)
+{
+ return _pdflNext;
+}
+
+inline void CDfNameList::SetName(WCHAR const *pwcs)
+{
+ _df.Set(pwcs);
+}
+
+inline void CDfNameList::SetStart(SECT sectStart)
+{
+ _sectStart = sectStart;
+}
+
+inline void CDfNameList::SetSize(ULONG ulSize)
+{
+ _ulSize = ulSize;
+}
+
+inline void CDfNameList::Insert(CDfNameList **ppdflStart,
+ CDfNameList *pdflPrev,
+ CDfNameList *pdflNext)
+{
+ if (pdflPrev == NULL)
+ {
+ *ppdflStart = this;
+ }
+ else
+ {
+ pdflPrev->_pdflNext = this;
+ }
+ _pdflNext = pdflNext;
+}
+
+#endif // #ifndef __DFNLIST_HXX__
+
diff --git a/private/ole32/stg/simp/dirs b/private/ole32/stg/simp/dirs
new file mode 100644
index 000000000..4c50c7cc4
--- /dev/null
+++ b/private/ole32/stg/simp/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/stg/simp/makefile b/private/ole32/stg/simp/makefile
new file mode 100644
index 000000000..1bf10bce3
--- /dev/null
+++ b/private/ole32/stg/simp/makefile
@@ -0,0 +1,21 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1994 **
+#********************************************************************
+
+!ifdef NTMAKEENV
+
+all:
+ echo $(BUILDMSG)
+
+clean: all
+
+!else
+
+default: all
+!include filelist.mk
+
+!include $(COMMON)\src\win40.mk
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/stg/simp/simpdf.cxx b/private/ole32/stg/simp/simpdf.cxx
new file mode 100644
index 000000000..de7772aa1
--- /dev/null
+++ b/private/ole32/stg/simp/simpdf.cxx
@@ -0,0 +1,76 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: simpdf.cxx
+//
+// Contents: StdDocfile implementation
+//
+// Classes:
+//
+// Functions:
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "simphead.cxx"
+#include <ole2sp.h>
+#include <ole2com.h>
+#pragma hdrstop
+
+
+#if DBG == 1
+DECLARE_INFOLEVEL(simp)
+#endif
+
+//+---------------------------------------------------------------------------
+//
+// Function: DfCreateSimpDocfile, private
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE DfCreateSimpDocfile(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage **ppstgOpen)
+{
+ SCODE sc;
+ CSimpStorage *pstg;
+
+ if (grfMode !=
+ (STGM_SIMPLE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE))
+ return STG_E_INVALIDFLAG;
+
+
+ pstg = new CSimpStorage;
+ if (pstg == NULL)
+ {
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ sc = pstg->Init(pwcsName, NULL);
+
+ if (FAILED(sc))
+ {
+ pstg->Release();
+ pstg = NULL;
+ }
+
+ *ppstgOpen = pstg;
+ CALLHOOKOBJECTCREATE(S_OK,CLSID_NULL,IID_IStorage,(IUnknown **)ppstgOpen);
+ return sc;
+}
diff --git a/private/ole32/stg/simp/simpdf.hxx b/private/ole32/stg/simp/simpdf.hxx
new file mode 100644
index 000000000..75bf0f020
--- /dev/null
+++ b/private/ole32/stg/simp/simpdf.hxx
@@ -0,0 +1,248 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: simpdf.hxx
+//
+// Contents: Headers for SimpDocfile
+//
+// Classes:
+//
+// Functions:
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __SIMPDF_HXX__
+#define __SIMPDF_HXX__
+
+#include <dfnlist.hxx>
+#include <header.hxx>
+
+#if DBG == 1
+DECLARE_DEBUG(simp);
+#endif
+
+#if DBG == 1
+
+#define simpDebugOut(x) simpInlineDebugOut x
+#ifndef REF
+#define simpAssert(e) Win4Assert(e)
+#define simpVerify(e) Win4Assert(e)
+#else
+#include <assert.h>
+#define simpAssert(e) assert(e)
+#define simpVerify(e) assert(e)
+#endif //!REF
+
+#else
+
+#define simpDebugOut(x)
+#define simpAssert(e)
+#define simpVerify(e) (e)
+
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Struct: SSimpDocfileHints
+//
+// Purpose: Hints for SimpDocfile
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+struct SSimpDocfileHints
+{
+ ULONG cStreams;
+ ULONG ulSize;
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSimpStorage
+//
+// Purpose:
+//
+// Interface:
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+interface CSimpStorage:
+ public IStorage,
+ public IMarshal
+{
+public:
+
+ inline CSimpStorage();
+ inline ~CSimpStorage();
+
+ SCODE Init(WCHAR const *pwcsName, SSimpDocfileHints *psdh);
+
+#ifdef SECURE_SIMPLE_MODE
+ void ReleaseCurrentStream(ULONG ulHighWater);
+#else
+ void ReleaseCurrentStream(void);
+#endif
+
+ // From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+
+ // IStorage
+ STDMETHOD(CreateStream)(OLECHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(OpenStream)(OLECHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm);
+ STDMETHOD(CreateStorage)(OLECHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ LPSTGSECURITY reserved2,
+ IStorage **ppstg);
+ STDMETHOD(OpenStorage)(OLECHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg);
+ STDMETHOD(CopyTo)(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNB snbExclude,
+ IStorage *pstgDest);
+ STDMETHOD(MoveElementTo)(OLECHAR const *lpszName,
+ IStorage *pstgDest,
+ OLECHAR const *lpszNewName,
+ DWORD grfFlags);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(EnumElements)(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm);
+ STDMETHOD(DestroyElement)(OLECHAR const *pwcsName);
+ STDMETHOD(RenameElement)(OLECHAR const *pwcsOldName,
+ OLECHAR const *pwcsNewName);
+ STDMETHOD(SetElementTimes)(const OLECHAR *lpszName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime);
+ STDMETHOD(SetClass)(REFCLSID clsid);
+ STDMETHOD(SetStateBits)(DWORD grfStateBits, DWORD grfMask);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+
+ // IMarshal
+ STDMETHOD(GetUnmarshalClass)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID *ppv);
+ STDMETHOD(ReleaseMarshalData)(IStream *pStm);
+ STDMETHOD(DisconnectObject)(DWORD dwReserved);
+private:
+
+ SID BuildTree(CDirEntry *ade, SID sidStart, ULONG cStreams);
+
+ LONG _cReferences;
+
+ HANDLE _hFile;
+ BOOL _fDirty;
+ CMSFHeader _hdr;
+ BYTE *_pbBuf;
+ SECT _sectMax;
+ CLSID _clsid;
+
+ CDfNameList *_pdfl;
+
+ CDfNameList *_pdflCurrent;
+ ULONG _cStreams;
+};
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSimpStorage::CSimpStorage, public
+//
+// Synopsis: Constructor
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CSimpStorage::CSimpStorage()
+ : _hdr(SECTORSHIFT)
+{
+ _cReferences = 0;
+
+ _pbBuf = NULL;
+ _sectMax = 0;
+ _pdfl = NULL;
+ _hFile = NULL;
+ _fDirty = FALSE;
+ _pdflCurrent = NULL;
+ _cStreams = 0;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSimpStorage::~CSimpStorage, public
+//
+// Synopsis: Destructor
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CSimpStorage::~CSimpStorage()
+{
+ delete _pbBuf;
+ //Clean up name list.
+}
+
+
+SCODE DfCreateSimpDocfile(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage **pstgOpen);
+
+
+
+
+#endif // #ifndef __SIMPDF_HXX__
+
+
+
diff --git a/private/ole32/stg/simp/simphead.cxx b/private/ole32/stg/simp/simphead.cxx
new file mode 100644
index 000000000..76bec60a5
--- /dev/null
+++ b/private/ole32/stg/simp/simphead.cxx
@@ -0,0 +1,39 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: simphead.cxx
+//
+// Contents: Precompiled headers
+//
+// History: 04-Aug-94 PhilipLa Created.
+//
+//--------------------------------------------------------------------------
+
+#include <memory.h>
+
+#ifndef REF
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windef.h>
+}
+#include <ole2.h>
+#endif //!REF
+
+#if defined(_CHICAGO_)
+#include <widewrap.h>
+#endif
+
+#include <msf.hxx>
+#include <header.hxx>
+#include <fat.hxx>
+#include <dir.hxx>
+#include <dirfunc.hxx>
+#include <simpdf.hxx>
+#include <simpstm.hxx>
+#include <dfnlist.hxx>
+
diff --git a/private/ole32/stg/simp/simpstg.cxx b/private/ole32/stg/simp/simpstg.cxx
new file mode 100644
index 000000000..d4792a5a0
--- /dev/null
+++ b/private/ole32/stg/simp/simpstg.cxx
@@ -0,0 +1,1187 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: simpstg.cxx
+//
+// Contents: SimpStorage class implementation
+//
+// Classes:
+//
+// Functions:
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "simphead.cxx"
+#pragma hdrstop
+
+#include <ole.hxx>
+#include <logfile.hxx>
+
+#ifdef SECURE_BUFFER
+BYTE s_bufSecure[MINISTREAMSIZE];
+#endif
+
+
+ULONG ConvertSect(SECT sect)
+{
+ return (ULONG)(sect << SECTORSHIFT) + SECTORSIZE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSimpStorage::Init, public
+//
+// Synopsis: Init function
+//
+// Arguments: [psdh] -- Pointer to hints structure
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CSimpStorage::Init(WCHAR const * pwcsName, SSimpDocfileHints *psdh)
+{
+ simpDebugOut((DEB_ITRACE,
+ "In CSimpStorage::Init:%p(%ws)\n", this, pwcsName));
+
+
+#ifdef UNICODE
+ TCHAR const *atcPath = pwcsName;
+#else
+ TCHAR atcPath[_MAX_PATH+1];
+
+ UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
+
+ if (!WideCharToMultiByte(
+ uCodePage,
+ 0,
+ pwcsName,
+ -1,
+ atcPath,
+ _MAX_PATH + 1,
+ NULL,
+ NULL))
+ {
+ return STG_E_INVALIDNAME;
+ }
+#endif
+
+ _hFile = CreateFileT(atcPath,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (_hFile == INVALID_HANDLE_VALUE)
+ {
+ return STG_SCODE(GetLastError());
+ }
+
+ _sectMax = 0;
+ //From this point on, we need to try to produce a docfile.
+ _fDirty = TRUE;
+ _cReferences = 1;
+ _clsid = IID_NULL;
+
+#ifdef SECURE_SIMPLE_MODE
+ memset(s_bufSecure, SECURECHAR, MINISTREAMSIZE);
+#endif
+
+ simpDebugOut((DEB_ITRACE, "Out CSimpStorage::Init\n"));
+ return S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::Release, public
+//
+// Synopsis: Releases resources for a CSimpStorage
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CSimpStorage::Release(void)
+{
+ LONG lRet;
+
+ olLog(("%p::In CSimpStorage::Release()\n", this));
+ simpDebugOut((DEB_TRACE, "In CSimpStorage::Release()\n"));
+
+ simpAssert(_cReferences > 0);
+ lRet = AtomicDec(&_cReferences);
+ if (lRet == 0)
+ {
+ //Clean up
+ if (_fDirty)
+ Commit(STGC_DEFAULT);
+ CloseHandle(_hFile);
+ delete this;
+ }
+
+ simpDebugOut((DEB_TRACE, "Out CSimpStorage::Release()\n"));
+ olLog(("%p::Out CSimpStorage::Release(). ret == %lu\n", this, lRet));
+ FreeLogFile();
+ return (ULONG)lRet;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::CreateStream, public
+//
+// Synopsis: Creates a stream
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [reserved1]
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+_OLESTDMETHODIMP CSimpStorage::CreateStream(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ SCODE sc;
+ CSimpStream *pstm;
+ CDfNameList *pdfl, *pdflPrev = NULL;
+ CDfNameList *pdflLoop = _pdfl;
+ int iCmp;
+
+ olLog(("%p::In CSimpStorage::CreateStream(%ws, %lX, %lu, %lu, %p)\n",
+ this, pwcsName, grfMode, reserved1, reserved2, ppstm));
+
+ if (_pdflCurrent != NULL)
+ {
+ return STG_E_INVALIDFUNCTION;
+ }
+
+ if (grfMode != (STGM_READWRITE | STGM_SHARE_EXCLUSIVE))
+ return STG_E_INVALIDFLAG;
+
+ //Check the name. If it isn't already in the list, create a new
+ // CDfNameList object (in pdfl), and create a new stream object for it.
+
+ pdfl = new CDfNameList;
+ if (pdfl == NULL)
+ {
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ pstm = new CSimpStream;
+ if (pstm == NULL)
+ {
+ delete pdfl;
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ pdfl->SetName(pwcsName);
+ pdfl->SetStart(_sectMax);
+ pdfl->SetSize(0);
+
+ while (pdflLoop != NULL)
+ {
+ iCmp = CDirectory::NameCompare(pdfl->GetName(), pdflLoop->GetName());
+ if (iCmp == 0)
+ {
+ //Already have a stream of this name.
+ delete pdfl;
+ delete pstm;
+ return STG_E_FILEALREADYEXISTS;
+ }
+
+ if (iCmp < 0)
+ {
+ //We found the right spot.
+ break;
+ }
+
+ pdflPrev = pdflLoop;
+ pdflLoop = pdflLoop->GetNext();
+ }
+
+ if (FAILED(sc = pstm->Init(this, _hFile, ConvertSect(_sectMax))))
+ {
+ delete pdfl;
+ delete pstm;
+ return sc;
+ }
+
+ //Insert pdfl into list.
+ pdfl->Insert(&_pdfl, pdflPrev, pdflLoop);
+
+ _pdflCurrent = pdfl;
+ _fDirty = TRUE;
+ _cStreams++;
+ *ppstm = pstm;
+
+ olLog(("%p::Out CSimpStorage::CreateStream(). "
+ "*ppstm == %p, ret == %lx\n", this, *ppstm, S_OK));
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSimpStorage::ReleaseCurrentStream, public
+//
+// Synopsis: Signal release of the current open stream
+//
+// Arguments: None.
+//
+// Returns: void.
+//
+// History: 05-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifdef SECURE_SIMPLE_MODE
+void CSimpStorage::ReleaseCurrentStream(ULONG ulHighWater)
+#else
+void CSimpStorage::ReleaseCurrentStream(void)
+#endif
+{
+ simpDebugOut((DEB_ITRACE,
+ "In CSimpStorage::ReleaseCurrentStream:%p()\n", this));
+
+ ULONG cbSize;
+ ULONG ulEndOfFile;
+
+ ulEndOfFile = GetFileSize(_hFile, NULL);
+
+ cbSize = ulEndOfFile - ConvertSect(_sectMax);
+ cbSize = max(cbSize, MINISTREAMSIZE);
+
+ _pdflCurrent->SetSize(cbSize);
+
+ ULONG sectUsed;
+ sectUsed = (cbSize + SECTORSIZE - 1) / SECTORSIZE;
+
+#ifdef SECURE_SIMPLE_MODE
+ ULONG cbBytesToWrite = ConvertSect(sectUsed + _sectMax) - ulHighWater;
+ simpAssert(ConvertSect(sectUsed + _sectMax) >= ulHighWater);
+
+ ULONG cbWritten;
+
+ if ((cbBytesToWrite > 0) &&
+ (SetFilePointer(_hFile, ulHighWater, NULL, FILE_BEGIN) != 0xFFFFFFFF))
+ {
+ while (cbBytesToWrite > 0)
+ {
+ if (!WriteFile(_hFile,
+ s_bufSecure,
+ min(MINISTREAMSIZE, cbBytesToWrite),
+ &cbWritten,
+ NULL))
+ {
+ break;
+ }
+ cbBytesToWrite -= cbWritten;
+ }
+ }
+#endif
+ _sectMax += sectUsed;
+ _pdflCurrent = NULL;
+
+ simpDebugOut((DEB_ITRACE, "Out CSimpStorage::ReleaseCurrentStream\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::OpenStream, public
+//
+// Synopsis: Opens an existing stream
+//
+// Arguments: [pwcsName] - Name
+// [reserved1]
+// [grfMode] - Permissions
+// [reserved2]
+// [ppstm] - Stream return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstm]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+_OLESTDMETHODIMP CSimpStorage::OpenStream(WCHAR const *pwcsName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::CreateStorage, public
+//
+// Synopsis: Creates an embedded DocFile
+//
+// Arguments: [pwcsName] - Name
+// [grfMode] - Permissions
+// [reserved1]
+// [reserved2]
+// [ppstg] - New DocFile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+_OLESTDMETHODIMP CSimpStorage::CreateStorage(WCHAR const *pwcsName,
+ DWORD grfMode,
+ DWORD reserved1,
+ LPSTGSECURITY reserved2,
+ IStorage **ppstg)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::OpenStorage, public
+//
+// Synopsis: Gets an existing embedded DocFile
+//
+// Arguments: [pwcsName] - Name
+// [pstgPriority] - Priority reopens
+// [grfMode] - Permissions
+// [snbExclude] - Priority reopens
+// [reserved]
+// [ppstg] - DocFile return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppstg]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+_OLESTDMETHODIMP CSimpStorage::OpenStorage(WCHAR const *pwcsName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNBW snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::CopyTo, public
+//
+// Synopsis: Makes a copy of a DocFile
+//
+// Arguments: [ciidExclude] - Length of rgiid array
+// [rgiidExclude] - Array of IIDs to exclude
+// [snbExclude] - Names to exclude
+// [pstgDest] - Parent of copy
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+_OLESTDMETHODIMP CSimpStorage::CopyTo(DWORD ciidExclude,
+ IID const *rgiidExclude,
+ SNBW snbExclude,
+ IStorage *pstgDest)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSimpStorage::BuildTree, private
+//
+// Synopsis: Construct the btree given the sorted array of entries.
+//
+// Arguments: [ade] -- Array of CDirEntry to operate on. These are
+// already sorted.
+// [sidStart] -- SID of first entry on this segment
+// [cStreams] -- Length of segment to process
+//
+// Returns: SID of root of tree
+//
+// History: 09-Aug-94 PhilipLa Created
+//
+// Notes: This is a recursive function. Yes, I know...
+//
+//----------------------------------------------------------------------------
+
+SID CSimpStorage::BuildTree(CDirEntry *ade, SID sidStart, ULONG cStreams)
+{
+ simpDebugOut((DEB_ITRACE, "In CSimpStorage::BuildTree:%p()\n", this));
+
+ if (cStreams > 3)
+ {
+ SID sidSplit;
+
+ sidSplit = sidStart + (cStreams / 2);
+
+ simpAssert(cStreams == 1 + (sidSplit - sidStart) +
+ (cStreams + sidStart - 1) - sidSplit);
+
+ ade[sidSplit].SetLeftSib(BuildTree(ade,
+ sidStart,
+ sidSplit - sidStart));
+ ade[sidSplit].SetRightSib(BuildTree(ade,
+ sidSplit + 1,
+ (cStreams + sidStart - 1) -
+ sidSplit));
+
+ return sidSplit;
+ }
+ //Base cases:
+ // cStreams == 1 -- return sidStart
+ // cStreams == 2 -- Left child of sidStart + 1 == sidStart, return
+ // sidStart + 1
+ // cStreams == 3 -- Root is sidStart + 1, with children sidStart and
+ // sidStart + 2
+
+ if (cStreams == 1)
+ {
+ return sidStart;
+ }
+
+ if (cStreams == 3)
+ ade[sidStart + 1].SetRightSib(sidStart + 2);
+
+ ade[sidStart + 1].SetLeftSib(sidStart);
+ return sidStart + 1;
+
+ simpDebugOut((DEB_ITRACE, "Out CSimpStorage::BuildTree\n"));
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::Commit, public
+//
+// Synopsis: Commits transacted changes
+//
+// Arguments: [dwFlags] - DFC_*
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStorage::Commit(DWORD dwFlags)
+{
+ CDfName const dfnRoot(L"Root Entry");
+
+ olLog(("%p::In CSimpStorage::Commit(%lX)\n",this, dwFlags));
+
+ //BUGBUG: This should invalidate the child instead of returning an error.
+ if (_pdflCurrent != NULL)
+ return STG_E_INVALIDFUNCTION;
+
+ if (!_fDirty)
+ return S_OK;
+
+ //Allocate a buffer big enough for all the control structures.
+ const USHORT cdePerSect = SECTORSIZE / sizeof(CDirEntry);
+ const USHORT cSectPerFat = SECTORSIZE / sizeof(SECT);
+
+ ULONG cDifSect = 0;
+ ULONG cFatSect = 0;
+ ULONG cFatSectOld = (ULONG)-1;
+ ULONG cDifSectOld = (ULONG)-1;
+ ULONG cDirSect;
+ ULONG cSect;
+ ULONG cbSize;
+
+ cDirSect = (_cStreams + 1 + cdePerSect - 1) / cdePerSect;
+ cSect = _sectMax + cDirSect;
+
+ //At this point, csect is the number of sectors needed to hold
+ // everything but the fat itself (and the DIFat, if necessary).
+
+
+ while ((cFatSect != cFatSectOld) || (cDifSect != cDifSectOld))
+ {
+ //Now, compute the number of fat sectors needed to hold everything.
+
+ cFatSectOld = cFatSect;
+ cFatSect = (cSect + cFatSect + cDifSect + cSectPerFat - 1) /
+ cSectPerFat;
+
+ cDifSectOld = cDifSect;
+ if (cFatSect >= CSECTFAT)
+ {
+ cDifSect = (cFatSect - CSECTFAT + cSectPerFat - 2)
+ / (cSectPerFat - 1);
+ }
+ }
+
+ //At this point, we know how big the buffer needs to be. Allocate
+ // it.
+
+ _pbBuf = new BYTE[(cFatSect + cDirSect + cDifSect) * SECTORSIZE];
+
+ if (_pbBuf == NULL)
+ {
+ return STG_E_INSUFFICIENTMEMORY;
+ }
+
+ //The fat is placed in the buffer first, followed by the directory.
+ SECT sect;
+ SECT *asectFat;
+ SECT *asectDif;
+ CDirEntry *adeDir;
+
+ SECT sectDifStart = _sectMax;
+ SECT sectFatStart = _sectMax + cDifSect;
+ SECT sectDirStart = _sectMax + cDifSect + cFatSect;
+
+ asectDif = (SECT *)_pbBuf;
+ asectFat = (SECT *)(_pbBuf + (cDifSect * SECTORSIZE));
+ adeDir = (CDirEntry *)(_pbBuf + ((cFatSect + cDifSect) * SECTORSIZE));
+ //asectFat and adeDir can be used as arrays.
+
+ //Need to get the buffer to a correct 'empty' state.
+ // 1) Initialize fat and difat to all 0xff.
+ memset(asectDif, 0xff, cDifSect * SECTORSIZE);
+ memset(asectFat, 0xff, cFatSect * SECTORSIZE);
+
+ // 2) Initialize dir to all empty state
+ for (USHORT i = 0; i < cDirSect * cdePerSect; i++)
+ {
+ adeDir[i].Init(STGTY_INVALID);
+ simpAssert((BYTE *)&adeDir[i] <
+ _pbBuf + ((cFatSect + cDifSect + cDirSect) * SECTORSIZE));
+ }
+
+
+ if (cDifSect > 0)
+ {
+ //Put dif into fat.
+ for (sect = sectDifStart; sect < sectFatStart; sect++)
+ {
+ asectFat[sect] = DIFSECT;
+ simpAssert((BYTE *)&asectFat[sect] < (BYTE *)adeDir);
+
+ ULONG ulOffset = sect - sectDifStart;
+
+ asectDif[ulOffset * cSectPerFat + (cSectPerFat - 1)] = sect + 1;
+ }
+ asectDif[((cDifSect - 1) * cSectPerFat) + (cSectPerFat - 1)] =
+ ENDOFCHAIN;
+ _hdr.SetDifStart(sectDifStart);
+ _hdr.SetDifLength(cDifSect);
+ }
+
+ for (sect = sectFatStart;
+ sect < sectDirStart;
+ sect++)
+ {
+ asectFat[sect] = FATSECT;
+ simpAssert((BYTE *)&asectFat[sect] < (BYTE *)adeDir);
+
+ ULONG ulOffset = sect - sectFatStart;
+
+ if (ulOffset < CSECTFAT)
+ {
+ _hdr.SetFatSect(ulOffset, sect);
+ }
+ else
+ {
+ ulOffset -= CSECTFAT;
+ asectDif[(ulOffset / (cSectPerFat - 1)) * cSectPerFat +
+ (ulOffset % (cSectPerFat - 1))] = sect;
+ }
+ }
+
+ for (sect = sectDirStart;
+ sect < sectDirStart + cDirSect;
+ sect++)
+ {
+ asectFat[sect] = sect + 1;
+ simpAssert((BYTE *)&asectFat[sect] < (BYTE *)adeDir);
+ }
+ asectFat[sectDirStart + cDirSect - 1] = ENDOFCHAIN;
+ simpAssert((BYTE *)&asectFat[sectDirStart + cDirSect - 1] <
+ (BYTE *)adeDir);
+
+ _hdr.SetDirStart(sectDirStart);
+ _hdr.SetFatLength(cFatSect);
+
+ //Fat, directory, and header are set up. Woowoo.
+
+ //Walk name list and construct directory and fat structures for
+ // user streams.
+ //Write them out, then write out header.
+
+ CDfNameList *pdfl;
+ SID sid;
+ pdfl = _pdfl;
+ sid = 1;
+
+ while (pdfl != NULL)
+ {
+ //Set up fat chain.
+ SECT sectStart = pdfl->GetStart();
+ ULONG cSect = (pdfl->GetSize() + SECTORSIZE - 1) / SECTORSIZE;
+
+ for (sect = sectStart; sect < sectStart + cSect; sect++)
+ {
+ asectFat[sect] = sect + 1;
+ simpAssert((BYTE *)&asectFat[sect] < (BYTE *)adeDir);
+ }
+ asectFat[sectStart + cSect - 1] = ENDOFCHAIN;
+ simpAssert((BYTE *)&asectFat[sectStart + cSect - 1] < (BYTE *)adeDir);
+
+ adeDir[sid].SetFlags(STGTY_STREAM);
+ adeDir[sid].SetName(pdfl->GetName());
+ adeDir[sid].SetStart(pdfl->GetStart());
+ adeDir[sid].SetSize(pdfl->GetSize());
+ adeDir[sid].SetColor(DE_BLACK);
+ simpAssert((BYTE *)&adeDir[sid] <
+ _pbBuf + ((cFatSect + cDifSect + cDirSect) * SECTORSIZE));
+ pdfl = pdfl->GetNext();
+ sid++;
+ }
+
+ //Set up root entry.
+ adeDir[0].Init(STGTY_ROOT);
+ adeDir[0].SetName(&dfnRoot);
+ adeDir[0].SetClassId(_clsid);
+ adeDir[0].SetColor(DE_BLACK);
+
+ //This recursively builds the btree and sets the root in the child
+ // of the root entry.
+ adeDir[0].SetChild(BuildTree(adeDir, 1, _cStreams));
+
+
+ //Write out buffer
+ ULONG cbWritten;
+
+ SetFilePointer(_hFile, ConvertSect(_sectMax), NULL, FILE_BEGIN);
+ BOOL f= WriteFile(_hFile,
+ _pbBuf,
+ (cFatSect + cDifSect + cDirSect) * SECTORSIZE,
+ &cbWritten,
+ NULL);
+ if (!f)
+ {
+ delete _pbBuf;
+ _pbBuf = NULL;
+ return STG_SCODE(GetLastError());
+ }
+
+ //Write out header
+ DWORD dwErr;
+ dwErr= SetFilePointer(_hFile, 0, NULL, FILE_BEGIN);
+ if (dwErr == 0xFFFFFFFF)
+ {
+ delete _pbBuf;
+ _pbBuf = NULL;
+ return STG_SCODE(GetLastError());
+ }
+
+ f= WriteFile(_hFile,
+ _hdr.GetData(),
+ sizeof(CMSFHeaderData),
+ &cbWritten,
+ NULL);
+ if (!f)
+ {
+ delete _pbBuf;
+ _pbBuf = NULL;
+ return STG_SCODE(GetLastError());
+ }
+
+
+ delete _pbBuf;
+ _pbBuf = NULL;
+
+ _fDirty = FALSE;
+
+ olLog(("%p::Out CSimpStorage::Commit(). ret == %lx\n",this, S_OK));
+ return S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::Revert, public
+//
+// Synopsis: Reverts transacted changes
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStorage::Revert(void)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::EnumElements, public
+//
+// Synopsis: Starts an iterator
+//
+// Arguments: [reserved1]
+// [reserved2]
+// [reserved3]
+// [ppenm] - Enumerator return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppenm]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStorage::EnumElements(DWORD reserved1,
+ void *reserved2,
+ DWORD reserved3,
+ IEnumSTATSTG **ppenm)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::DestroyElement, public
+//
+// Synopsis: Permanently deletes an element of a DocFile
+//
+// Arguments: [pwcsName] - Name of element
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+_OLESTDMETHODIMP CSimpStorage::DestroyElement(WCHAR const *pwcsName)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::MoveElementTo, public
+//
+// Synopsis: Move an element of a DocFile to an IStorage
+//
+// Arguments: [pwcsName] - Current name
+// [ptcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// Algorithm: Open source as storage or stream (whatever works)
+// Create appropriate destination
+// Copy source to destination
+// Set create time of destination equal to create time of source
+// If appropriate, delete source
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+_OLESTDMETHODIMP CSimpStorage::MoveElementTo(WCHAR const *pwcsName,
+ IStorage *pstgParent,
+ OLECHAR const *ptcsNewName,
+ DWORD grfFlags)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::RenameElement, public
+//
+// Synopsis: Renames an element of a DocFile
+//
+// Arguments: [pwcsName] - Current name
+// [pwcsNewName] - New name
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+_OLESTDMETHODIMP CSimpStorage::RenameElement(WCHAR const *pwcsName,
+ WCHAR const *pwcsNewName)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::SetElementTimes, public
+//
+// Synopsis: Sets element time stamps
+//
+// Arguments: [pwcsName] - Name
+// [pctime] - create time
+// [patime] - access time
+// [pmtime] - modify time
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+_OLESTDMETHODIMP CSimpStorage::SetElementTimes(WCHAR const *pwcsName,
+ FILETIME const *pctime,
+ FILETIME const *patime,
+ FILETIME const *pmtime)
+{
+ olLog(("%p::In CSimpStorage::SetElementTimes(%ws, %p, %p, %p)\n",
+ this, pwcsName, pctime, patime, pmtime));
+
+ if (pwcsName != NULL)
+ return STG_E_INVALIDFUNCTION;
+
+ if (!SetFileTime(_hFile,
+ pctime,
+ patime,
+ pmtime))
+ {
+ return STG_SCODE(GetLastError());
+ }
+ olLog(("%p::Out CSimpStorage::SetElementTimes(). ret == %lx\n",
+ this, S_OK));
+ return S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::SetClass, public
+//
+// Synopsis: Sets storage class
+//
+// Arguments: [clsid] - class id
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStorage::SetClass(REFCLSID rclsid)
+{
+ olLog(("%p::In CSimpStorage::SetClass(?)\n", this));
+ _clsid = rclsid;
+ olLog(("%p::Out CSimpStorage::SetClass(). ret == %lx\n",
+ this, S_OK));
+ return S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::SetStateBits, public
+//
+// Synopsis: Sets state bits
+//
+// Arguments: [grfStateBits] - state bits
+// [grfMask] - state bits mask
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStorage::SetStateBits(DWORD grfStateBits, DWORD grfMask)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::Stat, public
+//
+// Synopsis: Fills in a buffer of information about this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+_OLESTDMETHODIMP CSimpStorage::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CSimpStorage::AddRef(void)
+{
+ ULONG ulRet;
+
+ olLog(("%p::In CSimpStorage::AddRef()\n", this));
+ simpDebugOut((DEB_TRACE, "In CSimpStorage::AddRef()\n"));
+
+ AtomicInc(&_cReferences);
+ ulRet = _cReferences;
+
+ simpDebugOut((DEB_TRACE, "Out CSimpStorage::AddRef\n"));
+ olLog(("%p::Out CSimpStorage::AddRef(). ret == %lu\n", this, ulRet));
+ return ulRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStorage::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ olLog(("%p::In CSimpStorage::QueryInterface(?, %p)\n",
+ this, ppvObj));
+ simpDebugOut((DEB_TRACE, "In CSimpStorage::QueryInterface(?, %p)\n",
+ ppvObj));
+
+ *ppvObj = NULL;
+
+ sc = S_OK;
+ if (IsEqualIID(iid, IID_IStorage) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IStorage *)this;
+ CSimpStorage::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IMarshal))
+ {
+ *ppvObj = (IMarshal *)this;
+ CSimpStorage::AddRef();
+ }
+ else
+ sc = E_NOINTERFACE;
+
+ olLog(("%p::Out CSimpStorage::QueryInterface(). "
+ "*ppvObj == %p ret == %lx\n", this, *ppvObj, sc));
+ simpDebugOut((DEB_TRACE, "Out CSimpStorage::QueryInterface => %p\n",
+ ppvObj));
+ return ResultFromScode(sc);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::GetUnmarshalClass, public
+//
+// Synopsis: Returns the class ID
+//
+// Arguments: [riid] - IID of object
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+// [pcid] - CLSID return
+//
+// Returns: Invalid function.
+//
+// Modifies: [pcid]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStorage::GetUnmarshalClass(REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pcid)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::GetMarshalSizeMax, public
+//
+// Synopsis: Returns the size needed for the marshal buffer
+//
+// Arguments: [riid] - IID of object being marshaled
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+// [pcbSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbSize]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStorage::GetMarshalSizeMax(REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pcbSize)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::MarshalInterface, public
+//
+// Synopsis: Marshals a given object
+//
+// Arguments: [pstStm] - Stream to write marshal data into
+// [riid] - Interface to marshal
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStorage::MarshalInterface(IStream *pstStm,
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::UnmarshalInterface, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [pstStm] -
+// [riid] -
+// [ppvObj] -
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStorage::UnmarshalInterface(IStream *pstStm,
+ REFIID riid,
+ void **ppvObj)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::ReleaseMarshalData, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [pstStm] -
+//
+// Returns: Appropriate status code
+//
+// History: 18-Sep-92 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStorage::ReleaseMarshalData(IStream *pstStm)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStorage::DisconnectObject, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [dwRevserved] -
+//
+// Returns: Appropriate status code
+//
+// History: 18-Sep-92 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStorage::DisconnectObject(DWORD dwReserved)
+{
+ return STG_E_INVALIDFUNCTION;
+}
diff --git a/private/ole32/stg/simp/simpstm.cxx b/private/ole32/stg/simp/simpstm.cxx
new file mode 100644
index 000000000..ef4e94deb
--- /dev/null
+++ b/private/ole32/stg/simp/simpstm.cxx
@@ -0,0 +1,925 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: simpstm.cxx
+//
+// Contents: CStdStream implementation
+//
+// Classes:
+//
+// Functions:
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "simphead.cxx"
+#pragma hdrstop
+
+#include <ole.hxx>
+#include <logfile.hxx>
+
+#if DBG == 1 && defined(SECURE_SIMPLE_MODE)
+void CSimpStream::CheckSeekPointer(void)
+{
+ LONG lHighChk;
+ ULONG ulLowChk;
+ lHighChk = 0;
+ ulLowChk = SetFilePointer(_hFile, 0, &lHighChk, FILE_CURRENT);
+ if (ulLowChk == 0xFFFFFFFF)
+ {
+ //An error occurred while checking.
+ simpDebugOut((DEB_ERROR, "SetFilePointer call failed with %lu\n",
+ GetLastError()));
+ }
+ else if ((ulLowChk != _ulSeekPos) || (lHighChk != 0))
+ {
+ simpDebugOut((DEB_ERROR, "Seek pointer mismatch."
+ " Cached = %lu, Real = %lu, High = %lu\n",
+ _ulSeekPos, ulLowChk, lHighChk));
+ simpAssert((ulLowChk == _ulSeekPos) && (lHighChk == 0));
+ }
+}
+#define CheckSeek() CheckSeekPointer()
+#else
+#define CheckSeek()
+#endif // DBG == 1 && defined(SECURE_SIMPLE_MODE)
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSimpStream::Init, public
+//
+// Synopsis: Initialize stream object
+//
+// Arguments: [pstgParent] -- Pointer to parent
+// [hFile] -- File handle for writes
+// [ulSeekStart] -- Beginning seek pointer
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+SCODE CSimpStream::Init(
+ CSimpStorage *pstgParent,
+ HANDLE hFile,
+ ULONG ulSeekStart)
+{
+ simpDebugOut((DEB_ITRACE, "In CSimpStream::Init:%p()\n", this));
+ _ulSeekStart = ulSeekStart;
+ _hFile = hFile;
+ _pstgParent = pstgParent;
+ _cReferences = 1;
+
+#ifdef SECURE_SIMPLE_MODE
+ _ulHighWater = ulSeekStart;
+ _ulSeekPos = ulSeekStart;
+#endif
+
+ if (SetFilePointer(_hFile, ulSeekStart, NULL, FILE_BEGIN) == 0xFFFFFFFF)
+ {
+ return STG_SCODE(GetLastError());
+ }
+
+ CheckSeek();
+
+ if (!SetEndOfFile(_hFile))
+ {
+ return STG_SCODE(GetLastError());
+ }
+
+ simpDebugOut((DEB_ITRACE, "Out CSimpStream::Init\n"));
+ return S_OK;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::Read, public
+//
+// Synopsis: Read from a stream
+//
+// Arguments: [pb] - Buffer
+// [cb] - Count of bytes to read
+// [pcbRead] - Return number of bytes read
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::Read(VOID HUGEP *pb, ULONG cb, ULONG *pcbRead)
+{
+ ULONG cbRead;
+ ULONG *pcb;
+ SCODE sc;
+
+ olLog(("%p::In CSimpStream::Read(%p, %lu, %p)\n",
+ this, pb, cb, pcbRead));
+
+ pcb = (pcbRead != NULL) ? pcbRead : &cbRead;
+
+#ifdef SECURE_SIMPLE_MODE
+ if (_ulSeekPos + cb > _ulHighWater)
+ {
+ ULONG cbTotalSize;
+ cbTotalSize = GetFileSize(_hFile, NULL);
+
+ if (_ulSeekPos + cb > cbTotalSize)
+ {
+ //Truncate.
+ cb = (_ulSeekPos > cbTotalSize) ? 0 : cbTotalSize - _ulSeekPos;
+ }
+
+ //Part of this read would come from uninitialized space, so
+ // we need to return zeroes instead.
+ if (_ulSeekPos > _ulHighWater)
+ {
+ if (SetFilePointer(_hFile,
+ _ulSeekPos + cb,
+ NULL,
+ FILE_BEGIN) == 0xFFFFFFFF)
+ {
+ //We can't get the seek pointer where it will need to
+ // end up, so return zero bytes and be done with it.
+ *pcb = 0;
+ return S_OK;
+ }
+
+ //Actually, the whole thing is coming from uninitialized
+ // space. Why someone would do this is a mystery, but
+ // let's return zeroes anyway.
+ memset(pb, SECURECHAR, cb);
+ *pcb = cb;
+
+ _ulSeekPos += cb;
+ }
+ else
+ {
+ ULONG cbBytesToRead = _ulHighWater - _ulSeekPos;
+
+ if (FAILED(sc = Read(pb, cbBytesToRead, pcb)))
+ {
+ CheckSeek();
+ return sc;
+ }
+
+ cb -= *pcb;
+
+ if ((*pcb != cbBytesToRead) ||
+ (SetFilePointer(_hFile,
+ _ulSeekPos + cb,
+ NULL,
+ FILE_BEGIN) == 0xFFFFFFFF))
+ {
+ //Either the Read call returned a weird number of bytes,
+ // Or
+ //We can't actually get the seek pointer where we need
+ // it, so return fewer bytes than we normally would,
+ // with a success code.
+ CheckSeek();
+ return S_OK;
+ }
+
+ //Zero the rest of the buffer.
+ memset((BYTE *)pb + *pcb, SECURECHAR, cb);
+ *pcb += cb;
+ _ulSeekPos += cb;
+ }
+ CheckSeek();
+ return S_OK;
+ }
+#endif
+
+ //Maps directly to ReadFile call
+ BOOL f = ReadFile(_hFile,
+ pb,
+ cb,
+ pcb,
+ NULL);
+
+#ifdef SECURE_SIMPLE_MODE
+ _ulSeekPos += *pcb;
+#endif
+
+ CheckSeek();
+
+ if (!f)
+ return STG_SCODE(GetLastError());
+
+ olLog(("%p::Out CSimpStream::Read(). *pcbRead == %lu, ret = %lx\n",
+ this, *pcb, S_OK));
+ return S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::Write, public
+//
+// Synopsis: Write to a stream
+//
+// Arguments: [pb] - Buffer
+// [cb] - Count of bytes to write
+// [pcbWritten] - Return of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbWritten]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::Write(
+ VOID const HUGEP *pb,
+ ULONG cb,
+ ULONG *pcbWritten)
+{
+ ULONG cbWritten;
+ ULONG *pcb;
+ BOOL f = TRUE;
+ SCODE sc = S_OK;
+
+ olLog(("%p::In CSimpStream::Write(%p, %lu, %p)\n",
+ this, pb, cb, pcbWritten));
+
+ pcb = (pcbWritten != NULL) ? pcbWritten : &cbWritten;
+
+#ifdef SECURE_SIMPLE_MODE
+ if (_ulSeekPos > _ulHighWater)
+ {
+ //We're leaving a gap in the file, so we need to fill in that
+ // gap. Sad but true.
+ ULONG cbBytesToWrite = _ulSeekPos - _ulHighWater;
+
+ ULONG cbWrittenSecure;
+
+ if (SetFilePointer(_hFile,
+ _ulHighWater,
+ NULL,
+ FILE_BEGIN) != 0xFFFFFFFF)
+ {
+ while (cbBytesToWrite > 0)
+ {
+ if (!(f = WriteFile(_hFile,
+ s_bufSecure,
+ min(MINISTREAMSIZE, cbBytesToWrite),
+ &cbWrittenSecure,
+ NULL)))
+ {
+ break;
+ }
+ cbBytesToWrite -= cbWrittenSecure;
+ }
+ if ((!f) && (SetFilePointer(_hFile,
+ _ulSeekPos,
+ NULL,
+ FILE_BEGIN) == 0xFFFFFFFF))
+ {
+ return STG_SCODE(GetLastError());
+ }
+ }
+ CheckSeek();
+ }
+#endif
+ //Maps directly to WriteFile call
+ f = WriteFile(_hFile,
+ pb,
+ cb,
+ pcb,
+ NULL);
+
+#ifdef SECURE_SIMPLE_MODE
+ _ulSeekPos += *pcb;
+ if (_ulSeekPos > _ulHighWater)
+ _ulHighWater = _ulSeekPos;
+#endif
+
+ if (!f)
+ {
+ sc = STG_SCODE(GetLastError());
+ }
+
+ CheckSeek();
+ olLog(("%p::Out CSimpStream::Write(). "
+ "*pcbWritten == %lu, ret = %lx\n",
+ this, *pcb, sc));
+
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::Seek, public
+//
+// Synopsis: Seek to a point in a stream
+//
+// Arguments: [dlibMove] - Offset to move by
+// [dwOrigin] - SEEK_SET, SEEK_CUR, SEEK_END
+// [plibNewPosition] - Return of new offset
+//
+// Returns: Appropriate status code
+//
+// Modifies: [plibNewPosition]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::Seek(LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition)
+{
+ SCODE sc = S_OK;
+ LONG lMove;
+ ULONG ulPos;
+
+ simpAssert((dwOrigin == STREAM_SEEK_SET) || (dwOrigin == STREAM_SEEK_CUR) ||
+ (dwOrigin == STREAM_SEEK_END));
+
+ olLog(("%p::In CSimpStream::Seek(%ld, %lu, %p)\n",
+ this, LIGetLow(dlibMove), dwOrigin, plibNewPosition));
+
+ // Truncate dlibMove to 32 bits
+ if (dwOrigin == STREAM_SEEK_SET)
+ {
+ // Make sure we don't seek too far
+ if (LIGetHigh(dlibMove) != 0)
+ LISet32(dlibMove, 0xffffffff);
+ }
+ else
+ {
+ // High dword must be zero for positive values or -1 for
+ // negative values
+ // Additionally, for negative values, the low dword can't
+ // exceed -0x80000000 because the 32nd bit is the sign
+ // bit
+ if (LIGetHigh(dlibMove) > 0 ||
+ (LIGetHigh(dlibMove) == 0 &&
+ LIGetLow(dlibMove) >= 0x80000000))
+ LISet32(dlibMove, 0x7fffffff);
+ else if (LIGetHigh(dlibMove) < -1 ||
+ (LIGetHigh(dlibMove) == -1 &&
+ LIGetLow(dlibMove) <= 0x7fffffff))
+ LISet32(dlibMove, 0x80000000);
+ }
+
+ lMove = (LONG)LIGetLow(dlibMove);
+
+ switch(dwOrigin)
+ {
+ case STREAM_SEEK_SET:
+ ulPos = _ulSeekStart + lMove;
+ break;
+
+ case STREAM_SEEK_END:
+ ULONG cbSize;
+ cbSize = GetFileSize(_hFile, NULL);
+
+ if (lMove < 0)
+ {
+ if ((ULONG)(-lMove) > (cbSize - _ulSeekStart))
+ return STG_E_INVALIDFUNCTION;
+ }
+ ulPos = cbSize+lMove;
+ break;
+
+ case STREAM_SEEK_CUR:
+ ulPos = SetFilePointer(_hFile, 0, NULL, FILE_CURRENT);
+
+ if (lMove < 0)
+ {
+ if ((ULONG)(-lMove) > (ulPos - _ulSeekStart))
+ return STG_E_INVALIDFUNCTION;
+ }
+ ulPos += lMove;
+ break;
+ }
+
+ ulPos = SetFilePointer(_hFile,
+ ulPos,
+ NULL,
+ FILE_BEGIN);
+
+ if (plibNewPosition != NULL)
+ {
+ ULISet32(*plibNewPosition, ulPos - _ulSeekStart);
+ }
+#ifdef SECURE_SIMPLE_MODE
+ _ulSeekPos = ulPos;
+#endif
+
+ CheckSeek();
+
+ olLog(("%p::Out CSimpStream::Seek(). ulPos == %lu, ret == %lx\n",
+ this, ulPos, sc));
+ return sc;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::SetSize, public
+//
+// Synopsis: Sets the size of a stream
+//
+// Arguments: [ulNewSize] - New size
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::SetSize(ULARGE_INTEGER ulNewSize)
+{
+ ULONG ulCurrentPos;
+
+ olLog(("%p::In CSimpStream::SetSize(%lu)\n",
+ this, ULIGetLow(ulNewSize)));
+
+ ulCurrentPos = SetFilePointer(_hFile, 0, NULL, FILE_CURRENT);
+
+ if (ulCurrentPos == 0xFFFFFFFF)
+ {
+ return STG_SCODE(GetLastError());
+ }
+
+ if (SetFilePointer(_hFile,
+ ULIGetLow(ulNewSize) + _ulSeekStart,
+ NULL,
+ FILE_BEGIN) == 0xFFFFFFFF)
+ {
+ CheckSeek();
+ return STG_SCODE(GetLastError());
+ }
+
+ if (!SetEndOfFile(_hFile))
+ {
+ SetFilePointer(_hFile, ulCurrentPos, NULL, FILE_BEGIN);
+
+ CheckSeek();
+ return STG_SCODE(GetLastError());
+ }
+
+#ifdef SECURE_SIMPLE_MODE
+ if (ULIGetLow(ulNewSize) + _ulSeekStart < _ulHighWater)
+ {
+ _ulHighWater = ULIGetLow(ulNewSize) + _ulSeekStart;
+ }
+#endif
+
+ if (SetFilePointer(_hFile, ulCurrentPos, NULL, FILE_BEGIN) == 0xFFFFFFFF)
+ {
+#ifdef SECURE_SIMPLE_MODE
+ _ulSeekPos = ULIGetLow(ulNewSize) + _ulSeekStart;
+#endif
+ CheckSeek();
+ return STG_SCODE(GetLastError());
+ }
+
+ CheckSeek();
+ olLog(("%p::Out CSimpStream::SetSize(). ret == %lx\n", this, S_OK));
+ return S_OK;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::CopyTo, public
+//
+// Synopsis: Copies information from one stream to another
+//
+// Arguments: [pstm] - Destination
+// [cb] - Number of bytes to copy
+// [pcbRead] - Return number of bytes read
+// [pcbWritten] - Return number of bytes written
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbRead]
+// [pcbWritten]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::CopyTo(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten)
+{
+ simpDebugOut((DEB_TRACE, "In CSimpStream::CopyTo("
+ "%p, %lu, %p, %p)\n", pstm, ULIGetLow(cb),
+ pcbRead, pcbWritten));
+ simpDebugOut((DEB_TRACE, "Out CSimpStream::CopyTo\n"));
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::Release, public
+//
+// Synopsis: Releases a stream
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CSimpStream::Release(void)
+{
+ LONG lRet;
+
+ olLog(("%p::In CSimpStream::Release()\n", this));
+ simpDebugOut((DEB_TRACE, "In CSimpStream::Release()\n"));
+
+ simpAssert(_cReferences > 0);
+ lRet = AtomicDec(&_cReferences);
+ if (lRet == 0)
+ {
+#ifdef SECURE_SIMPLE_MODE
+ _pstgParent->ReleaseCurrentStream(_ulHighWater);
+#else
+ _pstgParent->ReleaseCurrentStream();
+#endif
+
+ delete this;
+ }
+ else if (lRet < 0)
+ lRet = 0;
+
+ simpDebugOut((DEB_TRACE, "Out CSimpStream::Release\n"));
+ olLog(("%p::Out CSimpStream::Release(). ret == %lu\n", this, lRet));
+ FreeLogFile();
+ return lRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::Stat, public
+//
+// Synopsis: Fills in a buffer of information about this object
+//
+// Arguments: [pstatstg] - Buffer
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pstatstg]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+_OLESTDMETHODIMP CSimpStream::Stat(STATSTGW *pstatstg, DWORD grfStatFlag)
+{
+ simpDebugOut((DEB_TRACE, "In CSimpStream::Stat(%p, %lu)\n",
+ pstatstg, grfStatFlag));
+ simpDebugOut((DEB_TRACE, "Out CSimpStream::Stat\n"));
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::Clone, public
+//
+// Synopsis: Clones a stream
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::Clone(IStream **ppstm)
+{
+ simpDebugOut((DEB_TRACE, "In CSimpStream::Clone(%p)\n",
+ ppstm));
+ simpDebugOut((DEB_TRACE, "Out CSimpStream::Clone\n"));
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::AddRef, public
+//
+// Synopsis: Increments the ref count
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CSimpStream::AddRef(void)
+{
+ ULONG ulRet;
+
+ olLog(("%p::In CSimpStream::AddRef()\n", this));
+ simpDebugOut((DEB_TRACE, "In CSimpStream::AddRef()\n"));
+
+ AtomicInc(&_cReferences);
+ ulRet = _cReferences;
+
+ simpDebugOut((DEB_TRACE, "Out CSimpStream::AddRef\n"));
+ olLog(("%p::Out CSimpStream::AddRef(). ret == %lu\n", this, ulRet));
+ return ulRet;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::LockRegion, public
+//
+// Synopsis: Nonfunctional
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::LockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ simpDebugOut((DEB_TRACE, "In CSimpStream::LockRegion("
+ "%lu, %lu\n", ULIGetLow(cb), dwLockType));
+ simpDebugOut((DEB_TRACE, "Out CSimpStream::LockRegion\n"));
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::UnlockRegion, public
+//
+// Synopsis: Nonfunctional
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::UnlockRegion(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ simpDebugOut((DEB_TRACE, "In CSimpStream::UnlockRegion(%lu, %lu)\n",
+ ULIGetLow(cb), dwLockType));
+ simpDebugOut((DEB_TRACE, "Out CSimpStream::UnlockRegion\n"));
+ return ResultFromScode(STG_E_INVALIDFUNCTION);
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::Commit, public
+//
+// Synopsis: No-op in current implementation
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::Commit(DWORD grfCommitFlags)
+{
+ simpDebugOut((DEB_TRACE, "In CSimpStream::Commit(%lu)\n",
+ grfCommitFlags));
+ simpDebugOut((DEB_TRACE, "Out CSimpStream::Commit\n"));
+ return STG_E_UNIMPLEMENTEDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::Revert, public
+//
+// Synopsis: No-op in current implementation
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::Revert(void)
+{
+ simpDebugOut((DEB_TRACE, "In CSimpStream::Revert()\n"));
+ simpDebugOut((DEB_TRACE, "Out CSimpStream::Revert\n"));
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::QueryInterface, public
+//
+// Synopsis: Returns an object for the requested interface
+//
+// Arguments: [iid] - Interface ID
+// [ppvObj] - Object return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc;
+
+ olLog(("%p::In CSimpStream::QueryInterface(?, %p)\n",
+ this, ppvObj));
+ simpDebugOut((DEB_TRACE, "In CSimpStream::QueryInterface(?, %p)\n",
+ ppvObj));
+
+ *ppvObj = NULL;
+
+ sc = S_OK;
+ if (IsEqualIID(iid, IID_IStream) || IsEqualIID(iid, IID_IUnknown))
+ {
+ *ppvObj = (IStream *)this;
+ CSimpStream::AddRef();
+ }
+ else if (IsEqualIID(iid, IID_IMarshal))
+ {
+ *ppvObj = (IMarshal *)this;
+ CSimpStream::AddRef();
+ }
+ else
+ sc = E_NOINTERFACE;
+
+ simpDebugOut((DEB_TRACE, "Out CSimpStream::QueryInterface => %p\n",
+ ppvObj));
+ olLog(("%p::Out CSimpStream::QueryInterface(). "
+ "*ppvObj == %p, ret == %lx\n", this, *ppvObj, sc));
+ return ResultFromScode(sc);
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::GetUnmarshalClass, public
+//
+// Synopsis: Returns the class ID
+//
+// Arguments: [riid] - IID of object
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+// [pcid] - CLSID return
+//
+// Returns: Invalid function.
+//
+// Modifies: [pcid]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::GetUnmarshalClass(REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pcid)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::GetMarshalSizeMax, public
+//
+// Synopsis: Returns the size needed for the marshal buffer
+//
+// Arguments: [riid] - IID of object being marshaled
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+// [pcbSize] - Size return
+//
+// Returns: Appropriate status code
+//
+// Modifies: [pcbSize]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::GetMarshalSizeMax(REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pcbSize)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::MarshalInterface, public
+//
+// Synopsis: Marshals a given object
+//
+// Arguments: [pstStm] - Stream to write marshal data into
+// [riid] - Interface to marshal
+// [pv] - Unreferenced
+// [dwDestContext] - Unreferenced
+// [pvDestContext] - Unreferenced
+// [mshlflags] - Unreferenced
+//
+// Returns: Appropriate status code
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::MarshalInterface(IStream *pstStm,
+ REFIID riid,
+ void *pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::UnmarshalInterface, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [pstStm] -
+// [riid] -
+// [ppvObj] -
+//
+// Returns: Appropriate status code
+//
+// Modifies: [ppvObj]
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::UnmarshalInterface(IStream *pstStm,
+ REFIID riid,
+ void **ppvObj)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::ReleaseMarshalData, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [pstStm] -
+//
+// Returns: Appropriate status code
+//
+// History: 18-Sep-92 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::ReleaseMarshalData(IStream *pstStm)
+{
+ return STG_E_INVALIDFUNCTION;
+}
+
+//+--------------------------------------------------------------
+//
+// Member: CSimpStream::DisconnectObject, public
+//
+// Synopsis: Non-functional
+//
+// Arguments: [dwRevserved] -
+//
+// Returns: Appropriate status code
+//
+// History: 18-Sep-92 PhilipLa Created
+//
+//---------------------------------------------------------------
+
+STDMETHODIMP CSimpStream::DisconnectObject(DWORD dwReserved)
+{
+ return STG_E_INVALIDFUNCTION;
+}
diff --git a/private/ole32/stg/simp/simpstm.hxx b/private/ole32/stg/simp/simpstm.hxx
new file mode 100644
index 000000000..2016290ac
--- /dev/null
+++ b/private/ole32/stg/simp/simpstm.hxx
@@ -0,0 +1,151 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: simpstm.hxx
+//
+// Contents: CSimpStream class
+//
+// Classes:
+//
+// Functions:
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __SIMPSTM_HXX__
+#define __SIMPSTM_HXX__
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSimpStream
+//
+// Purpose:
+//
+// Interface:
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+interface CSimpStream: public IStream
+{
+public:
+ inline CSimpStream();
+ inline ~CSimpStream();
+
+ SCODE Init(CSimpStorage *pstgParent, HANDLE hFile, ULONG ulSeekStart);
+
+ // From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ // New methods
+ STDMETHOD(Read)(VOID HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbRead);
+ STDMETHOD(Write)(VOID const HUGEP *pv,
+ ULONG cb,
+ ULONG *pcbWritten);
+ STDMETHOD(Seek)(LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER *plibNewPosition);
+ STDMETHOD(SetSize)(ULARGE_INTEGER cb);
+ STDMETHOD(CopyTo)(IStream *pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER *pcbRead,
+ ULARGE_INTEGER *pcbWritten);
+ STDMETHOD(Commit)(DWORD grfCommitFlags);
+ STDMETHOD(Revert)(void);
+ STDMETHOD(LockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(UnlockRegion)(ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType);
+ STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag);
+ STDMETHOD(Clone)(IStream **ppstm);
+
+ // IMarshal
+ STDMETHOD(GetUnmarshalClass)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPCLSID pCid);
+ STDMETHOD(GetMarshalSizeMax)(REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags,
+ LPDWORD pSize);
+ STDMETHOD(MarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID pv,
+ DWORD dwDestContext,
+ LPVOID pvDestContext,
+ DWORD mshlflags);
+ STDMETHOD(UnmarshalInterface)(IStream *pStm,
+ REFIID riid,
+ LPVOID *ppv);
+ STDMETHOD(ReleaseMarshalData)(IStream *pStm);
+ STDMETHOD(DisconnectObject)(DWORD dwReserved);
+
+private:
+ LONG _cReferences;
+ LONG _ulSeekStart;
+
+#ifdef SECURE_SIMPLE_MODE
+ ULONG _ulSeekPos;
+ ULONG _ulHighWater;
+
+#if DBG == 1
+ void CheckSeekPointer(void);
+#endif // DBG
+#endif // SECURE_SIMPLE_MODE
+
+ CSimpStorage *_pstgParent;
+ HANDLE _hFile;
+};
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSimpStream::CSimpStream, public
+//
+// Synopsis: Constructor
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CSimpStream::CSimpStream()
+{
+ _cReferences = 0;
+ _ulSeekStart = 0;
+ _pstgParent = NULL;
+ _hFile = NULL;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CSimpStream::~CSimpStream, public
+//
+// Synopsis: Destructor
+//
+// History: 04-Aug-94 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+inline CSimpStream::~CSimpStream()
+{
+}
+
+
+#endif // #ifndef __SIMPSTM_HXX__
diff --git a/private/ole32/stg/storage.def b/private/ole32/stg/storage.def
new file mode 100644
index 000000000..b36f88dd7
--- /dev/null
+++ b/private/ole32/stg/storage.def
@@ -0,0 +1,59 @@
+;//+-------------------------------------------------------------------------
+;//
+;// Microsoft Windows
+;// Copyright (C) Microsoft Corporation, 1992 - 1993.
+;//
+;// File: storage.def
+;//
+;// Contents: storage.dll module definition file
+;//
+;// History: 23-Sep-92 DrewB Created from multiple def files
+;// 09-Oct-92 AlexT Added HEAPSIZE to 16-bit definitions
+;// 03-Feb-93 DrewB Changed docfile.def to storage.def
+;//
+;// Note: $(OLE)\storage.def is used for 16-bit builds
+;// $(OLE)\storag32.def is used for non-Cairo 32-bit builds
+;// $(COMMON)\ilib\storag32.def is used for Cairo 32-bit builds
+;//
+;//--------------------------------------------------------------------------
+
+LIBRARY STORAGE
+DESCRIPTION 'Storage DLL'
+#ifndef WIN32
+EXETYPE WINDOWS 3.1
+
+CODE DISCARDABLE LOADONCALL MOVABLE SHARED
+DATA LOADONCALL SINGLE MOVABLE
+
+; HEAPSIZE is required for RETAIL 16-bit builds where
+; we do some local allocations.
+
+#if DBG == 0
+HEAPSIZE 0
+#else
+HEAPSIZE 1024
+#endif
+
+EXPORTS
+ WEP @0 RESIDENTNAME
+
+ STGCREATEDOCFILE @1
+ STGCREATEDOCFILEONILOCKBYTES @2
+ STGOPENSTORAGE @3
+ STGOPENSTORAGEONILOCKBYTES @4
+ STGISSTORAGEFILE @5
+ STGISSTORAGEILOCKBYTES @6
+ STGSETTIMES @7
+
+ DLLGETCLASSOBJECT @103
+
+#if DBG == 1
+ DFDEBUG @300
+ DFSETRESLIMIT @310
+ DFGETRESLIMIT @311
+ DFGETMEMALLOCED @302
+ DFPRINTALLOCS @303
+#endif
+#else
+#error storage.def should only be used for 16-bit builds
+#endif
diff --git a/private/ole32/stg/utils/chkdsk/chkdsk.cxx b/private/ole32/stg/utils/chkdsk/chkdsk.cxx
new file mode 100644
index 000000000..a4e7719f5
--- /dev/null
+++ b/private/ole32/stg/utils/chkdsk/chkdsk.cxx
@@ -0,0 +1,374 @@
+//-----------------------------------------------------------------------
+//
+// File: chkdsk.cxx
+//
+// Contents: Sanity checking and recovery mechanism for multistream files
+//
+// Argument:
+//
+// History: 9-July-92 t-chrisy Created.
+//------------------------------------------------------------------------
+
+#include "chkdsk.hxx"
+
+// Global variables, declared as so for convenience.
+CMSFHeader *pheader;
+CFat *pFat;
+CFat *pMiniFat;
+CDirectory *pDir;
+CDIFat *pDIFat;
+BOOL fixdf;
+CFatVector *pfvFat, *pfvMiniFat;
+wchar_t pwcsDocfile[_MAX_PATH];
+DFLAGS df = DF_READWRITE | DF_DENYWRITE;
+
+extern SCODE DllMultiStreamFromCorruptedStream(CMStream MSTREAM_NEAR **ppms,
+ ILockBytes **pplstStream,
+ DWORD dwFlags);
+
+// Function Prototypes
+void BuildFatTables();
+void MarkFatTables();
+void TreeWalk(CDirEntry *pde, SID sid);
+BOOL GetOption(int argc, char *argv[]);
+void Usage(char *pszProgName);
+void DIFTable();
+
+void main(int argc, char *argv[])
+{
+ CFileStream *pfilestr;
+ CMStream MSTREAM_NEAR *pms;
+ SCODE scRc;
+ ILockBytes *pilb;
+
+ // if fixdf returns yes, open docfile without a copy;
+ // otherwise, open docfile with a copy and operate on the copy.
+ fixdf = GetOption(argc,argv);
+ pfilestr = new CFileStream;
+
+ // creating ILockBytes implementation for the given file
+ // Note: When a docfile is corrupted, the chkdsk utility
+ // calls the original CFileStream::Init. If any objects
+ // fail to instantiate, the approach is to call an
+ // alternative Init routine, which can force the instantiation
+ // of Directory and MiniFat objects.
+
+ if (fixdf==TRUE) // -f specified, write allowed.
+ {
+ df &= ~0x03;
+ df |= DF_WRITE;
+ printf("Trying to open file...\n");
+ scRc = pfilestr->Init(pwcsDocfile,RSF_OPEN,df);
+ if (FAILED(scRc))
+ {
+ printf("Error creating ILockBytes.\n");
+ exit(FAIL_CREATE_ILB);
+ }
+ }
+ else // open a read-only copy of filestream
+ {
+ df &= ~0x300; // clear access bits
+ df |= DF_DENYWRITE;
+ printf("Trying to open file...\n");
+ scRc = pfilestr->Init(pwcsDocfile,RSF_OPEN,df);
+ if (FAILED(scRc))
+ {
+ printf("Error creating ILockBytes.\n");
+ exit(FAIL_CREATE_ILB);
+ }
+ else printf("Successfully created ILockBytes.\n");
+ }
+
+ scRc = pfilestr->Validate();
+ if (scRc == STG_E_INVALIDHANDLE)
+ {
+ printf("Filestream signature is not valid.\n");
+ exit(INVALID_DOCFILE);
+ }
+
+ // CFileStream is essentially equivalent to ILockBytes.
+ pilb = (ILockBytes *) pfilestr;
+ scRc = DllMultiStreamFromStream(&pms,&pilb,0);
+
+ if (FAILED(scRc))
+ if (FAILED(scRc = DllMultiStreamFromCorruptedStream
+ (&pms,&pilb,0)))
+ {
+ exit(FAIL_CREATE_MULTISTREAM);
+ printf("Error creating a multistream.\n");
+ }
+
+
+ // When an multi-stream is instantiated, the following control structures
+ // are automatically instantiated.
+ pheader = pms->GetHeader();
+ pDir = pms->GetDir();
+ pFat = pms->GetFat();
+ pMiniFat = pms->GetMiniFat();
+ pDIFat = pms->GetDIFat();
+
+ printf("\tBuilding fat tables...\n");
+ BuildFatTables();
+ printf("\tExamining the DIFat...\n");
+ DIFTable();
+ printf("\tExamining Fat and MiniFat chains...\n");
+ MarkFatTables();
+ printf("\tChecking completed.\n");
+ delete(pfvFat);
+ delete(pfvMiniFat);
+ pfilestr->Release();
+ printf("Memory blocks freed.\n");
+}
+
+void BuildFatTables()
+{
+ // Build two tables: one for Fat sectors, the other for Minifat sectors.
+
+ FSINDEX FatLen,MiniFatLen;
+ FatLen = pheader->GetFatLength();
+ MiniFatLen = pheader->GetMiniFatLength();
+ pfvFat = new CFatVector(TABLE_SIZE);
+ pfvFat->Init(FatLen);
+ if (MiniFatLen == 0)
+ printf("No MiniFat to be checked.\n");
+ else
+ {
+ pfvMiniFat = new CFatVector(TABLE_SIZE);
+ pfvMiniFat->Init(MiniFatLen);
+ }
+}
+
+void MarkFatTables()
+{
+ CDirEntry *pde;
+
+ // Walk through all the fat chains and mark the new table with the
+ // first SID number encountered.
+
+ pDir->SidToEntry(SIDROOT,&pde);
+ TreeWalk(pde,SIDROOT); // pde points to the root entry now
+}
+
+void TreeWalk(CDirEntry *pde, SID sid)
+{
+ CDirEntry *pchild, *pnext;
+ SID childsid, nextsid;
+ SCODE scRc,scRcM;
+ FSINDEX fitable,fioffset;
+ SECT sectentry, sect;
+ CFatSect *pfsec;
+ CFatVector *pfv;
+ CFat *pf;
+ ULONG uldesize;
+
+ pDir->GetStart(sid,&sect);
+ uldesize = pde->GetSize();
+
+ if (uldesize >= MINISTREAMSIZE) // storage is in FAT
+ {
+ pfv = pfvFat;
+ pf = pFat;
+ }
+ else
+ {
+ pfv = pfvMiniFat;
+ pf = pMiniFat;
+ }
+
+ // Check if LUID exceeds MaxLUID. If so, report the error.
+ if (pde->GetLuid() > pheader->GetLuid())
+ printf("LUID for dir entry #%lu exceeds MAXLuid.\n",sid);
+
+ while (sect < MAXREGSECT)
+ {
+ if (sid == SIDROOT)
+ break; // nothing should be in root stream
+ // Use fitable and fioffset to index into the fat (or minifat)
+ // table and mark the field with visited.
+ // at the same time, check for loops or crosslinks.
+
+ //Note: 3 cases
+ fitable = sect / (TABLE_SIZE);
+ fioffset = sect % (TABLE_SIZE);
+ pfv->GetTable(fitable,&pfsec); // pfsec = ptr to CFatSect
+ sectentry = pfsec->GetSect(fioffset);
+
+// printf("\tsect = %lu \t \t sectentry = %lu \t stream_size = %lu\n",
+// sect,sectentry, uldesize);
+ // Mark the FatTables as well as fixing the multistream.
+ // Right now, the routine only marks the FatTables.
+ //Note: 3 cases...but the last two cases may not
+ // be handled the same.
+ if (sectentry > MAXREGSECT)
+ pfsec->SetSect(fioffset,sid);
+ else if (sectentry == sid)
+ {
+ // discontinue the current stream chain by marking
+ // current SECT as ENDOFCHAIN.
+ pf->SetNext(sect,ENDOFCHAIN);
+ pfsec->SetSect(fioffset,ENDOFCHAIN);
+ printf("Loop detected at fat SECT %ul\n",sectentry);
+ }
+ else
+ {
+ pf->SetNext(sect,ENDOFCHAIN);
+ pfsec->SetSect(fioffset,ENDOFCHAIN);
+ printf("Crosslink detected at Fat SECT %lu with stream #%lu\n",
+ sect,sid);
+ }
+ // get the next sector to be examined
+ // !!!!! Need to use the Fat object to track down next sector
+ pf->GetNext(sect,&sect);
+ }
+
+ // Recursively go down the tree
+ // pchild and pnext must point to the original tree for
+ // efficiency purposes.
+
+ childsid = pde->GetChild();
+ if (childsid != NOSTREAM)
+ {
+ pDir->SidToEntry(childsid,&pchild);
+ TreeWalk(pchild,childsid);
+ }
+ nextsid = pde->GetNext();
+ if (nextsid != NOSTREAM)
+ {
+ pDir->SidToEntry(nextsid,&pnext);
+ TreeWalk(pnext,nextsid);
+ }
+
+ if (fixdf==TRUE)
+ {
+ scRc = pFat->Flush();
+ scRcM = pMiniFat->Flush();
+ if (FAILED(scRc) || FAILED(scRcM))
+ printf("Failed to write all modified FatSects out to stream.\n");
+ }
+}
+
+BOOL GetOption(int argc, char *argv[])
+{
+ char *pszArg, *pszProgName;
+ BOOL ArgsOK = FALSE, Fix = FALSE;
+ pszProgName = *argv++;
+
+ while ((pszArg = *argv++) != NULL)
+ {
+ if (*pszArg == '-' || *pszArg == '/')
+ {
+ switch (tolower(*(++pszArg)))
+ {
+ case 'f': // fix the errors.
+ Fix = TRUE; // open file with read-only without a copy.
+ break;
+ case 'n': // name of the docfile to be opened.
+ // path of the filename.
+ mbstowcs(pwcsDocfile,++pszArg,_MAX_PATH);
+ Fix = FALSE;
+ ArgsOK = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ else ArgsOK = FALSE;
+ }
+ if (ArgsOK == FALSE)
+ {
+ printf("0 argument or invalid command line argument.\n");
+ Usage(pszProgName);
+ exit(INVALID_ARG);
+ }
+ return Fix;
+}
+
+void Usage(char *pszProgName)
+{
+ printf("Usage: %s\n", pszProgName);
+ printf(" -f fix requested by user.\n");
+ printf(" -n <name of docfile>\n");
+ printf("The -n option must be specified.\n");
+}
+
+
+void DIFTable() // August 11, 1992
+{
+ // Walk through each DIF sector array to detect loops and
+ // crosslinks.
+ SCODE scRc;
+ BOOL FatOK = TRUE;
+ SECT sect, sectentry;
+ FSINDEX diflen, fatlen, fitable, fioffset, index, minifatlen,uldif,ulr;
+ CFatSect *pfsec;
+
+ diflen = pheader->GetDifLength();
+ fatlen = pheader->GetFatLength();
+ minifatlen = pheader->GetMiniFatLength();
+
+ // testing the validity of pheader->GetDifLength
+ if (fatlen > CSECTFAT) // diflen > 0
+ {
+ ulr = ( ((fatlen - CSECTFAT)%TABLE_SIZE) > 0 )? 1: 0;
+ uldif = CSECTFAT + (fatlen-CSECTFAT)/TABLE_SIZE + ulr;
+ }
+ else uldif = 0;
+ if (diflen!=uldif)
+ printf("DIFLEN in header is inconsistent with FatLEN.\n");
+
+ for (index=0; index<fatlen; index++)
+ {
+ pDIFat->GetFatSect(index,&sect);
+ if (sect < MAXREGSECT)
+ {
+ fitable = sect / TABLE_SIZE;
+ fioffset = sect % TABLE_SIZE;
+ pfvFat->GetTable(fitable,&pfsec); // pfsec = ptr to CFatSect
+ sectentry = pfsec->GetSect(fioffset);
+
+ if (sectentry > MAXREGSECT)
+ pfsec->SetSect(fioffset,SIDFAT);
+ else
+ {
+ printf("Crosslink! DIF index #%u points\n",index);
+ printf(" to the same location %u.\n", sect);
+ FatOK = FALSE;
+ }
+ }
+ pDIFat->GetFatSect(index+1,&sect);
+ }
+
+ if (FatOK == TRUE)
+ printf("No errors found in DIFat.\n");
+
+ // Walk through the terminating cells in each sector array to check
+ // the correctness of chaining.
+ printf("\tWalking through DIFTable chain.\n");
+ for (index = 0; index<diflen; index++)
+ {
+ pDIFat->GetSect(index,&sect);
+ fitable = sect/TABLE_SIZE;
+ fioffset = sect%TABLE_SIZE;
+ pfvFat->GetTable(fitable,&pfsec); // pfsec = ptr to CFatSect
+ sectentry = pfsec->GetSect(fioffset);
+ if ((sectentry!=ENDOFCHAIN) && (index == diflen-1))
+ printf("ERROR! ENDOFCHAIN expected at the end of DIFat.\n.");
+ pDIFat->SetFatSect(fioffset,SIDDIF);
+ pfsec->SetSect(fioffset,SIDDIF);
+ }
+ if (fixdf==TRUE)
+ {
+ scRc = pDIFat->FlushAll();
+ if (FAILED(scRc))
+ printf("Failed to write all modified FatSects out to stream.\n");
+ }
+}
+
+
+
+
+
+
+
+
+
diff --git a/private/ole32/stg/utils/chkdsk/chkdsk.def b/private/ole32/stg/utils/chkdsk/chkdsk.def
new file mode 100644
index 000000000..7783c57d0
--- /dev/null
+++ b/private/ole32/stg/utils/chkdsk/chkdsk.def
@@ -0,0 +1,21 @@
+NAME CHKDSK
+#ifndef FLAT
+EXETYPE WINDOWS
+//STUB 'WINSTUB.EXE'
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 16384
+STACKSIZE 8192
+#else
+EXETYPE NT
+SUBSYSTEM WINDOWSCHAR
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 16384
+STACKSIZE 8192
+#endif
+
diff --git a/private/ole32/stg/utils/chkdsk/chkdsk.hxx b/private/ole32/stg/utils/chkdsk/chkdsk.hxx
new file mode 100644
index 000000000..e7660618f
--- /dev/null
+++ b/private/ole32/stg/utils/chkdsk/chkdsk.hxx
@@ -0,0 +1,116 @@
+//-----------------------------------------------------------------------
+//
+// File: chkdsk.cxx
+//
+// Contents: Sanity checking and recovery mechanism for multistream files
+//
+// Argument:
+//
+// History: August-21-92 t-chrisy Created.
+//------------------------------------------------------------------------
+#include <stdlib.h>
+#include <stdio.h>
+#include <msf.hxx>
+#include <filest.hxx>
+#include <header.hxx>
+#include <fat.hxx>
+#include <wchar.h>
+#include <handle.hxx>
+#include <dfmsp.hxx>
+#include <dir.hxx>
+
+#define INVALID_DOCFILE 1
+#define FAIL_CREATE_MULTISTREAM 2
+#define INVALID_ARG 3
+#define FAIL_CREATE_ILB 4
+#define NONE 0
+
+#define TABLE_SIZE (SECTORSIZE/sizeof(SECT))
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: DllMultiStreamFromCorruptedStream
+//
+// Synopsis: Create a new multistream instance from an existing stream.
+// This is used to reopen a stored multi-stream.
+//
+// Effects: Creates a new CMStream instance
+//
+// Arguments: [ppms] -- Pointer to storage for return of multistream
+// [pplstStream] -- Stream to be used by multi-stream for
+// reads and writes
+// [dwFlags] - Startup flags
+//
+// Returns: STG_E_INVALIDHEADER if signature on pStream does not
+// match.
+// STG_E_UNKNOWN if there was a problem in setup.
+// S_OK if call completed OK.
+//
+// Algorithm: Check the signature on the pStream and on the contents
+// of the pStream. If either is a mismatch, return
+// STG_E_INVALIDHEADER.
+// Create a new CMStream instance and run the setup function.
+// If the setup function fails, return STG_E_UNKNOWN.
+// Otherwise, return S_OK.
+//
+// History: 17-Aug-91 PhilipLa Created.
+// 26-Aug-92 t-chrisy modifed to reduce ErrJmp
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+SCODE DllMultiStreamFromCorruptedStream(CMStream MSTREAM_NEAR **ppms,
+ ILockBytes **pplstStream,
+ DWORD dwFlags)
+{
+ SCODE sc;
+ CMStream MSTREAM_NEAR *temp;
+
+ BOOL fConvert = ((dwFlags & RSF_CONVERT) != 0);
+ BOOL fDelay = ((dwFlags & RSF_DELAY) != 0);
+ BOOL fTruncate = ((dwFlags & RSF_TRUNCATE) != 0);
+
+ msfDebugOut((DEB_ITRACE,"In DllMultiStreamFromStream\n"));
+
+ msfMem(temp = new CMStream(pplstStream, NULL, SECTORSHIFT));
+
+ ULARGE_INTEGER ulSize;
+ (*pplstStream)->GetSize(&ulSize);
+ msfAssert(ULIGetHigh(ulSize) == 0);
+ msfDebugOut((DEB_ITRACE,"Size is: %lu\n",ULIGetLow(ulSize)));
+
+ do
+ {
+ if ((ULIGetLow(ulSize) != 0) && (fConvert))
+ {
+ msfChk(temp->InitConvert(fDelay));
+ break;
+ }
+
+ if ((ULIGetLow(ulSize) == 0) || (fTruncate))
+ {
+ msfChk(temp->InitNew(fDelay));
+ break;
+ }
+ msfChk(temp->Init());
+ if (FAILED(sc))
+ msfDebugOut((DEB_ITRACE,"Fail to initialize multistream.\n"));
+ }
+ while (FALSE);
+
+ *ppms = temp;
+
+ msfDebugOut((DEB_ITRACE,"Leaving DllMultiStreamFromStream\n"));
+
+ if (fConvert && ULIGetLow(ulSize) && !fDelay)
+ return STG_I_CONVERTED;
+
+ return S_OK;
+
+Err:
+ delete temp;
+ return sc;
+}
+
+
diff --git a/private/ole32/stg/utils/chkdsk/depend.mk9 b/private/ole32/stg/utils/chkdsk/depend.mk9
new file mode 100644
index 000000000..891c908d5
--- /dev/null
+++ b/private/ole32/stg/utils/chkdsk/depend.mk9
@@ -0,0 +1,16 @@
+#
+# Source files
+#
+
+$(OBJDIR)\chkdsk.obj $(OBJDIR)\chkdsk.lst: chkdsk.cxx \
+ $(COMMON)\H\WIN40\scode.h $(COMMON)\H\WIN40\w4crt.h \
+ $(COMMON)\iH\debnot.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE)\h\dblink.hxx $(OLE)\h\dfmsp.hxx $(OLE)\h\dir.hxx \
+ $(OLE)\h\error.hxx $(OLE)\h\filest.hxx $(OLE)\h\handle.hxx \
+ $(OLE)\h\header.hxx $(OLE)\h\luid.hxx $(OLE)\h\msf.hxx \
+ $(OLE)\h\msffunc.hxx $(OLE)\h\ole.hxx $(OLE)\h\publist.hxx \
+ $(OLE)\h\vect.hxx $(OLE)\h\wchar.h $(OLE)\msf\fat.hxx \
+ $(OLE2H)\dvobj.h $(OLE2H)\iid.h $(OLE2H)\moniker.h $(OLE2H)\ole2.h \
+ $(OLE2H)\stdobj.h $(OLE2H)\storage.h chkdsk.hxx
+
diff --git a/private/ole32/stg/utils/chkdsk/makefile b/private/ole32/stg/utils/chkdsk/makefile
new file mode 100644
index 000000000..25c75020e
--- /dev/null
+++ b/private/ole32/stg/utils/chkdsk/makefile
@@ -0,0 +1,106 @@
+##########################################################################
+#
+# Copyright (C) 1992 - 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+EXENAME = chkdsk
+
+#
+# Set up include directories and roots for includes.exe
+#
+
+CFLAGS = -DCHKDSK
+CINC = $(CINC) -I$(COMMON)\h -I$(OLE)\h -I$(OLE2H) -I$(OLE)\msf
+INCLUDES_ROOTS = -P$$(OLE2H)=$(OLE2H) -P$$(OLE)=$(OLE)
+
+#
+# Default OLE2 paths
+#
+
+!ifndef OLE2H
+!if "$(OPSYS)" == "NT"
+OLE2H = $(OLE)\ole2flat
+!else
+OLE2H = $(OLE)\ole2h
+!endif
+!endif
+!ifndef OLE2BIN
+!if "$(OPSYS)" == "NT"
+OLE2BIN = $(OLE)\ole2flat
+!else
+OLE2BIN = $(OLE)\ole2h
+!endif
+!endif
+
+#
+# Defining NO_WINMAIN suppresses linking with astartw.obj
+#
+
+NO_WINMAIN = 1
+
+#
+# Copy built exes to this directory
+#
+
+EXECOPY = $(OLETARGET)\$(OBJDIR)
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = $(EXENAME).exe
+RELEASE =
+
+#
+# C compiler flags
+#
+
+!if "$(OPSYS)" == "NT"
+
+
+CFLAGS = -DUL64
+!endif
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES = .\$(EXENAME).cxx
+
+#
+# Libraries and other object files to link.
+#
+
+LIBS = $(DFLIB)\
+!if "$(OPSYS)" != "NT"
+ $(OLE)\common\$(OBJDIR)\dfcommon.lib\
+ $(OLE)\msf\$(OBJDIR)\msf.lib\
+ $(COMMON)\ilib\$(OBJDIR)\misc.lib\
+ $(OLE)\docfile\$(OBJDIR)\docfile.lib\
+ $(OLE)\wclib\$(OBJDIR)\wclib.lib\
+ $(RTLIBEXEQ)\
+ $(OSLIBDIR)\toolhelp.lib\
+ $(OLE2BIN)\stdobj.lib\
+!else
+ $(CAIROLIB)\
+!endif
+
+
+OBJFILES = \
+!if "$(OPSYS)" != "NT"
+ $(OLE2BIN)\stdalloc.obj\
+!endif
+ $(OLE2BIN)\iid.obj
+
+#
+# Set MULTIDEPEND to support multiple build targets
+#
+
+MULTIDEPEND = 1
+
+!include $(COMMON)\src\win40.mk
+!include $(DEPENDFILE)
diff --git a/private/ole32/stg/utils/compob32/compob32.cxx b/private/ole32/stg/utils/compob32/compob32.cxx
new file mode 100644
index 000000000..45106ad6f
--- /dev/null
+++ b/private/ole32/stg/utils/compob32/compob32.cxx
@@ -0,0 +1,162 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: compob32.cxx
+//
+// Contents: Stub compobj for Chicago
+//
+// History: 09-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include "pch.cxx"
+#pragma hdrstop
+
+#include <malloc.h>
+
+// Bind GUID definitions in
+#include <initguid.h>
+#include <coguid.h>
+
+typedef void *LPCOCS;
+
+class CMalloc : public IMalloc
+{
+public:
+ // *** IUnknown methods ***
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj);
+ STDMETHOD_(ULONG,AddRef) (THIS) ;
+ STDMETHOD_(ULONG,Release) (THIS);
+
+ // *** IMalloc methods ***
+ STDMETHOD_(void FAR*, Alloc) (THIS_ ULONG cb);
+ STDMETHOD_(void FAR*, Realloc) (THIS_ void FAR* pv, ULONG cb);
+ STDMETHOD_(void, Free) (THIS_ void FAR* pv);
+ STDMETHOD_(ULONG, GetSize) (THIS_ void FAR* pv);
+ STDMETHOD_(int, DidAlloc) (THIS_ void FAR* pv);
+ STDMETHOD_(void, HeapMinimize) (THIS);
+};
+
+STDMETHODIMP CMalloc::QueryInterface(REFIID riid, void **ppv)
+{
+ if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IMalloc))
+ {
+ *ppv = (IMalloc *)this;
+ CMalloc::AddRef();
+ return NOERROR;
+ }
+ *ppv = NULL;
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+STDMETHODIMP_(ULONG) CMalloc::AddRef(void)
+{
+ return 1;
+}
+
+STDMETHODIMP_(ULONG) CMalloc::Release(void)
+{
+ return 0;
+}
+
+STDMETHODIMP_(void FAR*) CMalloc::Alloc(THIS_ ULONG cb)
+{
+ return malloc(cb);
+}
+
+STDMETHODIMP_(void FAR*) CMalloc::Realloc(THIS_ void FAR* pv, ULONG cb)
+{
+ return realloc(pv, cb);
+}
+
+STDMETHODIMP_(void) CMalloc::Free(THIS_ void FAR* pv)
+{
+ free(pv);
+}
+
+STDMETHODIMP_(ULONG) CMalloc::GetSize(THIS_ void FAR* pv)
+{
+ return _msize(pv);
+}
+
+STDMETHODIMP_(int) CMalloc::DidAlloc(THIS_ void FAR* pv)
+{
+ return TRUE;
+}
+
+STDMETHODIMP_(void) CMalloc::HeapMinimize(THIS)
+{
+}
+
+static CMalloc _cm;
+
+STDAPI CoInitialize(IMalloc *pm)
+{
+ return NOERROR;
+}
+
+STDAPI_(void) CoUninitialize(void)
+{
+}
+
+STDAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC FAR* ppMalloc)
+{
+ *ppMalloc = (IMalloc *)&_cm;
+ return NOERROR;
+}
+
+STDAPI_(BOOL) IsValidPtrIn( const void FAR* pv, UINT cb )
+{
+ return pv == NULL || !IsBadReadPtr(pv, cb);
+}
+
+STDAPI_(BOOL) IsValidPtrOut( void FAR* pv, UINT cb )
+{
+ return !IsBadWritePtr(pv, cb);
+}
+
+STDAPI_(BOOL) IsValidInterface( void FAR* pv )
+{
+ return !IsBadReadPtr(pv, sizeof(void *)) &&
+ !IsBadReadPtr(*(void **)pv, sizeof(void *)) &&
+ !IsBadCodePtr(**(FARPROC **)pv);
+}
+
+STDAPI_(BOOL) IsValidIid( REFIID riid )
+{
+ return !IsBadReadPtr(&riid, sizeof(IID));
+}
+
+STDAPI_(BOOL) IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
+{
+ return memcmp(&rguid1, &rguid2, sizeof(GUID)) == 0;
+}
+
+STDAPI_(void *) SharedMemAlloc(ULONG cNeeded, DWORD dwReserved)
+{
+ return malloc(cNeeded);
+}
+
+STDAPI_(void) SharedMemFree(void *pmem, DWORD dwReserved)
+{
+ free(pmem);
+}
+
+STDAPI_(DWORD) CoGetCurrentProcess(void)
+{
+ return 1;
+}
+
+STDAPI CoMarshalInterface(LPSTREAM pStm, REFIID riid, LPUNKNOWN pUnk,
+ DWORD dwDestContext, LPVOID pvDestContext,
+ DWORD mshlflags)
+{
+ return ResultFromScode(E_UNEXPECTED);
+}
+
+STDAPI CoUnmarshalInterface(LPSTREAM pStm, REFIID riid, LPVOID FAR* ppv)
+{
+ return ResultFromScode(E_UNEXPECTED);
+}
diff --git a/private/ole32/stg/utils/compob32/compob32.def b/private/ole32/stg/utils/compob32/compob32.def
new file mode 100644
index 000000000..240b6bc80
--- /dev/null
+++ b/private/ole32/stg/utils/compob32/compob32.def
@@ -0,0 +1,27 @@
+;//+-------------------------------------------------------------------------
+;//
+;// Microsoft Windows
+;// Copyright (C) Microsoft Corporation, 1992 - 1993.
+;//
+;// File: compob32.def
+;//
+;// Contents: compob32.dll module definition file
+;//
+;//--------------------------------------------------------------------------
+
+LIBRARY COMPOB32
+DESCRIPTION 'Compob32 DLL'
+EXPORTS
+ CoInitialize@4 @1
+ CoUninitialize@0 @2
+ CoGetMalloc@8 @3
+ IsValidPtrOut@8 @4
+ IsEqualGUID@8 @5
+ IsValidIid@4 @6
+ IsValidInterface@4 @7
+ SharedMemAlloc@8 @8
+ SharedMemFree@8 @9
+ IsValidPtrIn@8 @10
+ CoGetCurrentProcess@0 @15
+ CoMarshalInterface@24 @16
+ CoUnmarshalInterface@12 @17
diff --git a/private/ole32/stg/utils/compob32/depend.mk3 b/private/ole32/stg/utils/compob32/depend.mk3
new file mode 100644
index 000000000..12b63f97b
--- /dev/null
+++ b/private/ole32/stg/utils/compob32/depend.mk3
@@ -0,0 +1,69 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\compob32.obj $(OBJDIR)\compob32.lst: .\compob32.cxx \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\malloc.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\pch.cxx
+
+$(OBJDIR)\dllentry.obj $(OBJDIR)\dllentry.lst: .\dllentry.c \
+ $(CRTINC)\stdio.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\initguid.h $(OLE2H)\compobj.h $(OLE2H)\dvobj.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\pch.pxh $(PCHDIR)\$(OBJDIR)\pch.lst: \
+ $(OLE)\utils\compob32\pch.cxx $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\string.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\dvobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\moniker.h $(OLE2H)\ole2.h $(OLE2H)\oleguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h
+
+.\$(OBJDIR)\compob32.obj : $(PCHDIR)\$(OBJDIR)\pch.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/utils/compob32/dllentry.c b/private/ole32/stg/utils/compob32/dllentry.c
new file mode 100644
index 000000000..1a9d52836
--- /dev/null
+++ b/private/ole32/stg/utils/compob32/dllentry.c
@@ -0,0 +1,33 @@
+#include <stdio.h>
+#include <windows.h>
+
+BOOL WINAPI _CRT_INIT (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
+
+#ifdef HAS_LIBMAIN
+BOOL _CRTAPI1 LibMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
+#else
+#define LibMain(h, d, l) TRUE
+#endif
+
+BOOL __stdcall DllEntryPoint (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
+{
+ BOOL fRc;
+// char msg[80];
+
+ switch(dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+// DebugBreak();
+ break;
+ }
+ if (fRc = _CRT_INIT(hDll, dwReason, lpReserved))
+ fRc = LibMain(hDll, dwReason, lpReserved);
+ switch(dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+// sprintf(msg, "Compob32 returning %d on attach\r\n", fRc);
+// OutputDebugStringA(msg);
+ break;
+ }
+ return fRc;
+}
diff --git a/private/ole32/stg/utils/compob32/makefile b/private/ole32/stg/utils/compob32/makefile
new file mode 100644
index 000000000..2e01640e8
--- /dev/null
+++ b/private/ole32/stg/utils/compob32/makefile
@@ -0,0 +1,24 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1992 **
+#********************************************************************
+
+default: all
+
+TARGET = compob32.dll
+
+TARGET_DESCRIPTION = "OLE 2.0 Component Object Model Core Code"
+
+CXXFILES = .\compob32.cxx
+CFILES = .\dllentry.c
+
+PXXFILE = .\pch.cxx
+
+CINC = $(CINC) -I$(OLE2H)
+INCLUDES_ROOTS = $(INCLUDES_ROOTS) -P$$(OLE2H)=$(OLE2H)
+
+COFFBASE = usermode
+MULTIDEPEND = MERGED
+
+!include $(COMMON)\src\win40.mk
+!include $(DEPENDFILE)
diff --git a/private/ole32/stg/utils/compob32/pch.cxx b/private/ole32/stg/utils/compob32/pch.cxx
new file mode 100644
index 000000000..c3b736d02
--- /dev/null
+++ b/private/ole32/stg/utils/compob32/pch.cxx
@@ -0,0 +1,13 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: pch.cxx
+//
+// History: 09-Sep-93 DrewB Created
+//
+//----------------------------------------------------------------------------
+
+#include <windows.h>
+#include <compobj.h>
diff --git a/private/ole32/stg/utils/df2t/depend.mk1 b/private/ole32/stg/utils/df2t/depend.mk1
new file mode 100644
index 000000000..10ae76652
--- /dev/null
+++ b/private/ole32/stg/utils/df2t/depend.mk1
@@ -0,0 +1,58 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\df2t.obj $(OBJDIR)\df2t.lst: .\df2t.cxx $(COMMON)\ih\Base32K.hxx \
+ $(COMMON)\ih\types.h $(COMMON)\ih\winnot.h $(CRTINC)\assert.h \
+ $(CRTINC)\ctype.h $(CRTINC)\direct.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\io.h $(CRTINC)\limits.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE)\h\dfdeb.hxx \
+ $(OLE)\h\wchar.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\idltyps.h $(OLE2H)\itabls.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oletyp.h $(OLE2H)\prspec.h $(OLE2H)\querys.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\w4ctsupp.hxx
+
+$(OBJDIR)\w4ctsupp.obj $(OBJDIR)\w4ctsupp.lst: .\w4ctsupp.cxx \
+ $(COMMON)\ih\Base32K.hxx $(COMMON)\ih\types.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\time.h $(CRTINC)\assert.h $(CRTINC)\ctype.h \
+ $(CRTINC)\direct.h $(CRTINC)\excpt.h $(CRTINC)\io.h \
+ $(CRTINC)\limits.h $(CRTINC)\memory.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdio.h $(CRTINC)\stdlib.h $(CRTINC)\string.h \
+ $(OLE)\h\dfdeb.hxx $(OLE)\h\wchar.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\prspec.h $(OLE2H)\varnt.h $(OLE2H)\wtypes.h \
+ $(OLE2H)\baseole.h $(OLE2H)\basetyps.h $(OLE2H)\cguid.h \
+ $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h $(OLE2H)\dispatch.h \
+ $(OLE2H)\disptype.h $(OLE2H)\dsbase.h $(OLE2H)\idltyps.h \
+ $(OLE2H)\itabls.h $(OLE2H)\ole2.h $(OLE2H)\oletyp.h $(OLE2H)\prspec.h \
+ $(OLE2H)\querys.h $(OLE2H)\scode.h $(OLE2H)\shtyps.h \
+ $(OLE2H)\stgprop.h $(OLE2H)\varnt.h $(OLE2H)\winole.h \
+ $(OLE2H)\wtypes.h $(OSINC)\rpc.h $(OSINC)\cderr.h $(OSINC)\commdlg.h \
+ $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\w4ctsupp.hxx
+
diff --git a/private/ole32/stg/utils/df2t/depend.mk9 b/private/ole32/stg/utils/df2t/depend.mk9
new file mode 100644
index 000000000..fedcee6e1
--- /dev/null
+++ b/private/ole32/stg/utils/df2t/depend.mk9
@@ -0,0 +1,19 @@
+#
+# Source files
+#
+
+$(OBJDIR)\df2t.obj $(OBJDIR)\df2t.lst: .\df2t.cxx $(CRTINC)\assert.h \
+ $(CRTINC)\direct.h $(CRTINC)\dos.h $(CRTINC)\io.h $(CRTINC)\limits.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE)\h\dfdeb.hxx \
+ $(OLE)\h\wchar.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OSINC)\windows.h .\w4ctsupp.hxx
+
+$(OBJDIR)\w4ctsupp.obj $(OBJDIR)\w4ctsupp.lst: .\w4ctsupp.cxx \
+ $(CRTINC)\assert.h $(CRTINC)\ctype.h $(CRTINC)\direct.h \
+ $(CRTINC)\io.h $(CRTINC)\limits.h $(CRTINC)\memory.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\time.h $(OLE)\h\dfdeb.hxx \
+ $(OLE)\h\wchar.h $(OLE2H)\coguid.h $(OLE2H)\compobj.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OSINC)\windows.h .\w4ctsupp.hxx
+
diff --git a/private/ole32/stg/utils/df2t/df2t.cxx b/private/ole32/stg/utils/df2t/df2t.cxx
new file mode 100644
index 000000000..d48b77761
--- /dev/null
+++ b/private/ole32/stg/utils/df2t/df2t.cxx
@@ -0,0 +1,696 @@
+//+----------------------------------------------------------------------------// File: DF2T.CXX
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// Contents: utility program for converting a Docfile to a directory tree.
+// Given a Docfile,it is walked with an enumerator and each
+// embedded IStorage creates a directory in the specified
+// destination tree while each IStream creates a file within
+// the appropriate directory. Finally, a tree compare is
+// performed on the source and destination trees.
+//
+// Classes: IStorage - Container class
+// IStream - Contained stream class
+// IEnumSTATSTG - Enumerator class for IStorages
+//
+// Command line: df2c -f/-b -(n)ameofDocfile -(s)rcTree -(d)estTree -T -W
+// -f forward conversion (docfile --> tree)
+// -b backward conversion (tree --> docfile)
+// -n name for root docfile
+// -s name of the source directory tree
+// -d name of the destination directory tree
+// -t specifies STGM_TRANSACTED mode
+// -w specifies STGM_SHARE_DENY_WRITE mode for root docfile
+//
+// -f and -b cannot be both specified in one command.
+//
+// The default conversion is from Docfile to tree.
+// Therefore, -n and -d(est) must be specified when forward
+// conversion -f is used. Otherwise, -b should be accompanied
+// by -s(rc) and -n(doc).
+//
+// This utility defaults to running in DIRECT mode so that all
+// operations at all levels are performed immediately on the
+// base copy of the root docfile.
+//
+// With the -T switch, this runs in STGM_TRANSACTED mode for
+// all IStorage creation and instantiation so that scratch
+// streams are created and committed, but only made permanent
+// in the persistent version by Commit of the root docfile.
+//
+// With the -W switch, this runs in STGM_TRANSACTED mode
+// with STGM_SHARE_DENY_WRITE for root docfile creation and
+// instantiation so that operations are performed on the base
+// copy of the docfile.
+//
+// Requires: Windows 3.x. MSF.DLL and DOCFILE.DLL should be in same dir
+// as executable or in \windows\system
+//
+// Returns: 0 if successful, exits with error code otherwise
+//
+// Notes: uses whcar and 'mbtowcs' conversions for wide char support
+// returns STG_E_NOTCURRENT if docfile-to-be-created
+// already exists.
+//
+// Created: RichE, January 13, 1992 Original program
+// Revised: t-chrisy, June 25, 1992 convert the test program to a utility
+// dftc.cxx --> df2t.cxx
+//-----------------------------------------------------------------------------
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <dos.h>
+#include <direct.h>
+
+#include "w4ctsupp.hxx"
+
+#define WILD_CARD "\\*.*"
+#define BACK_SLASH "\\"
+#define NS_INCL (STGTY_STORAGE | STGTY_STREAM)
+#define FIND_ATTRS _A_SUBDIR | _A_NORMAL | _A_RDONLY | _A_HIDDEN
+#define FILE_BUF_SIZE 32768 // msf is optimized for file size of 4K or 512bytes
+#define DOCTOTREE 0
+#define TREETODOC 1
+
+//function prototypes
+void CopyTreeToDocfile(IStorage *pstgParent);
+void CopyDocfileToTree(IStorage *pstgParent, TCHAR *ptcsDFName);
+void CopyFileToStream(IStorage *pstgParent, char *FileName);
+void CopyStreamToFile(IStorage *pstgParent, TCHAR *ptcsStreamName);
+int GetOptions(int argc, char *argv[]);
+void Usage(char *pszProgName);
+
+//buffers for file/dir path calls and docfile name (default assignments)
+char szDestDocfile[_MAX_PATH + 1] = "";
+char szSrcPath[_MAX_PATH + 1] = "";
+char szDestPath[_MAX_PATH + 1] = "";
+int iSrcPathEnd = sizeof(_MAX_PATH); //length minus terminating '\0'
+int iDestPathEnd = sizeof(_MAX_PATH);
+
+//buffers for converting to/from wide characters
+TCHAR wcsWideName[_MAX_PATH + 1];
+char szName[_MAX_PATH + 1];
+
+//modifiers to flags for root and child docfiles (GetOptions may modify)
+DWORD dwRootFlags = STGM_READWRITE | STGM_SHARE_DENY_WRITE;
+DWORD dwChildFlags = STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
+
+void utMemFree(void *pv)
+{
+ IMalloc FAR* pMalloc;
+ if (SUCCEEDED(GetScode(CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ pMalloc->Free(pv);
+ pMalloc->Release();
+ }
+}
+
+//+----------------------------------------------------------------------------
+// Function: main, public
+//
+// Synopsis: main body of program, controls overall flow
+//
+// Effects: initialize. Depending on the direction of converionsn,
+// call functions to create a tree, given a DocFile;
+// call functions to create a DocFile, given a tree.
+//
+// Created: RichE January 13, 1992 original program
+// Revised: t-chrisy June 25, 1992 modified to convert docfile to tree;
+// and vice versa.
+//
+//-----------------------------------------------------------------------------
+
+void main(int argc, char *argv[])
+{
+ IStorage *pstgDest = NULL;
+ SCODE scRc;
+ short ret;
+
+#if WIN32 == 300
+ if (FAILED(scRc = GetScode(CoInitializeEx(NULL, COINIT_MULTITHREADED))))
+#else
+ if (FAILED(scRc = GetScode(CoInitialize(NULL))))
+#endif
+ {
+ fprintf(stderr, "CoInitialize failed with sc = %lx\n", scRc);
+ exit(1);
+ }
+
+ ret=GetOptions(argc, argv);
+ if (ret==DOCTOTREE)
+ {
+ tprintf(bDestOut, "Converting Docfile to tree....\n");
+ if ((!strcmp(szDestDocfile,"\0"))||(!strcmp(szDestPath,"\0")))
+ {
+ tprintf(bDestOut, "Invalid switches used.\n");
+ tprintf(bDestOut,
+ "If -f is indicated, -n and -d must also be specified.\n");
+ exit(1);
+ }
+ }
+ else
+ {
+ tprintf(bDestOut, "Converting a directory tree to Docfile....\n");
+ if ((!strcmp(szDestDocfile,"\0")||(!strcmp(szSrcPath,"\0"))))
+ {
+ tprintf(bDestOut, "Invalid switches used.\n");
+ tprintf(bDestOut,
+ "If -b is chosen, -s and -n must also be specified.\n");
+ exit(1);
+ }
+ }
+
+ if (dwRootFlags & STGM_TRANSACTED)
+ {
+ tprintf(bDestOut, "STGM_TRANSACTED mode ");
+ if ((dwRootFlags & 0x70) == STGM_SHARE_EXCLUSIVE)
+ {
+ tprintf(bDestOut, "with STGM_SHARE_EXCLUSIVE");
+ }
+ else
+ {
+ tprintf(bDestOut, "without STGM_SHARE_EXCLUSIVE");
+ }
+ }
+ else
+ {
+ tprintf(bDestOut, "STGM_DIRECT mode (with STGM_SHARE_EXCLUSIVE)");
+ }
+ tprintf(bDestOut, " operation\n");
+
+ MakeWide(wcsWideName, szDestDocfile);
+
+ if (ret==DOCTOTREE) // Docfile to tree...
+ {
+ MakePath(szDestPath);
+ CopyDocfileToTree((IStorage *) NULL, wcsWideName);
+ }
+ else
+ {
+ // Create root docfile with specified mode, nuke if already exists
+ tprintf(bDestOut, "Create root docfile %s\n", szDestDocfile);
+ scRc = GetScode(StgCreateDocfile(wcsWideName,
+ dwRootFlags | STGM_CREATE, 0,
+ &pstgDest));
+ tprintf(bDestOut, "Returned %lu\n", scRc);
+ tprintf(bDestOut, "Root docfile %s %s, pointer %p\n", szDestDocfile,
+ pstgDest == NULL ? "FALSE" : "TRUE", pstgDest);
+ if (pstgDest == NULL || FAILED(scRc))
+ {
+ ErrExit(DEST_LOG, scRc, "Error creating root docfile %s\n",
+ szDestDocfile);
+ }
+ CopyTreeToDocfile(pstgDest);
+ }
+}
+
+//+----------------------------------------------------------------------------
+// Function: CopyTreeToDocfile, private
+//
+// Synopsis: traverses and reads source tree and creates docfile image
+//
+// Effects: for each directory in source tree, an IStorage is created, for each
+// file, a contained stream is created. this function is recursive.
+//
+// Arguments: [pstgParent] - current parent IStorage for new containees
+//
+// Created: RichE, January 13, 1992
+// Revised: RichE March 5, 1992 Df APIs to method calls
+// Revised: RichE March 6, 1992 TRANSACTED mode operation
+// Revised: RichE March 17, 1992 convert to OLE interfaces
+//-----------------------------------------------------------------------------
+
+void CopyTreeToDocfile(IStorage *pstgParent)
+{
+ struct find_t FileInfo;
+ SCODE scRc;
+ USHORT usEndOfBasePath;
+ IStorage *pstgChild;
+
+ // Save pointer to base of pure path at this level
+ usEndOfBasePath = strlen(szSrcPath) + 1;
+
+ scRc = _dos_findfirst(strcat(szSrcPath, WILD_CARD), FIND_ATTRS, &FileInfo);
+
+ while (scRc==0)
+ {
+ // If not '.' or '..' directories
+ if (FileInfo.name[0] != '.')
+ {
+ // Restore pure path and add current file/dir name to it
+ szSrcPath[usEndOfBasePath] = NIL;
+ strcat(szSrcPath, FileInfo.name);
+ if (FileInfo.attrib == _A_SUBDIR)
+ {
+ MakeWide(wcsWideName, FileInfo.name);
+ // Create new IStorage inside current one,
+ // use dir name for name
+ tprintf(bDestOut,
+ "Create embedded DF %s inside pstgParent %p\n",
+ szSrcPath, pstgParent);
+ scRc = GetScode(pstgParent->CreateStorage(wcsWideName,
+ dwChildFlags |
+ STGM_FAILIFTHERE,
+ 0, 0,
+ &pstgChild));
+ tprintf(bDestOut, "Returned: %lu, pointer = %p\n",
+ scRc, pstgChild);
+
+ if (pstgChild == NULL || FAILED(scRc))
+ {
+ ErrExit(DEST_LOG, scRc,
+ "Error creating child IStorage %s\n",
+ FileInfo.name);
+ }
+ CopyTreeToDocfile(pstgChild);
+ }
+ else
+ {
+ CopyFileToStream(pstgParent, FileInfo.name);
+ }
+ }
+ scRc = _dos_findnext(&FileInfo);
+ }
+ if (dwRootFlags & STGM_TRANSACTED)
+ {
+ tprintf(bDestOut, "Committing pstgParent %p\n", pstgParent);
+ if (scRc = GetScode(pstgParent->Commit(STGC_ONLYIFCURRENT)))
+ {
+ ErrExit(DEST_LOG, scRc, "Error committing IStorage %p\n",
+ pstgParent);
+ }
+ }
+ tprintf(bDestOut, "Releasing pstgParent %p\n", pstgParent);
+ pstgParent->Release();
+}
+
+//+----------------------------------------------------------------------------
+// Function: CopyFileToStream, private
+//
+// Synopsis: copies supplied file to stream inside of parent IStorage
+//
+// Arguments: [pstgParent] - parent IStorage for stream created
+// [FileName] - name of source file to copy to stream
+//
+// Created: RichE, January 13, 1992
+// Revised: RichE March 5, 1992 Df APIs to method calls
+// Revised: RichE March 6, 1992 TRANSACTED mode operation
+// Revised: RichE March 15, 1992 streams no longer TRANSACTED
+// Revised: RichE March 17, 1992 convert to OLE interfaces
+//-----------------------------------------------------------------------------
+
+void CopyFileToStream(IStorage *pstgParent, char *FileName)
+{
+ IStream *pstmStream = NULL;
+ FILE *FileToCopy;
+ SCODE scRc;
+ ULONG cNumRead;
+ ULONG cNumWritten;
+ BYTE *FileBuf;
+
+ tprintf(bDestOut, " File %s\n", szSrcPath);
+ FileToCopy = fopen(szSrcPath, "rb");
+ if (FileToCopy == NULL)
+ {
+ ErrExit(DEST_LOG, ERR, "Cannot open file %s\n", szSrcPath);
+ }
+
+ MakeWide(wcsWideName, FileName);
+
+ // Create a stream inside parent IStorage
+ tprintf(bDestOut,
+ "Create embedded stream inside parent pstgParent = %p\n",
+ pstgParent);
+ scRc = GetScode(pstgParent->CreateStream(wcsWideName, STGM_STREAM |
+ STGM_FAILIFTHERE, 0, 0,
+ &pstmStream));
+ tprintf(bDestOut, "Returned: %lu, pointer = %p\n", scRc, pstmStream);
+ if (pstmStream == NULL || FAILED(scRc))
+ {
+ ErrExit(DEST_LOG, scRc, "Error creating stream %s\n", szSrcPath);
+ }
+
+ FileBuf = (BYTE * ) Allocate(FILE_BUF_SIZE * sizeof(BYTE));
+
+ //while still reading from source file, write what was just read to Stream
+ while (cNumRead = fread(FileBuf, 1, FILE_BUF_SIZE, FileToCopy))
+ {
+ if (ferror(FileToCopy))
+ {
+ ErrExit(DEST_LOG, ERR, "Error during stream read of %s\n",
+ szSrcPath);
+ }
+
+ tprintf(bDestOut, "Try Stream write of %lu bytes on stream %p\n",
+ cNumRead, pstmStream);
+ scRc = GetScode(pstmStream->Write(FileBuf, cNumRead, &cNumWritten));
+ tprintf(bDestOut, "Returned: %lu, bytes written %lu\n",
+ scRc, cNumWritten);
+ if (cNumWritten != cNumRead)
+ {
+ tprintf(bDestOut, "Write: scRc = %lu, cNumWritten = %lu, ",
+ scRc, cNumWritten);
+ tprintf(bDestOut, "cNumRead = %lu\n", cNumRead);
+ }
+
+ if (FAILED(scRc))
+ {
+ ErrExit(DEST_LOG, ERR, "Error writing stream %p\n", pstmStream);
+ }
+ }
+
+ tprintf(bDestOut, "Releasing stream %p\n", pstmStream);
+ pstmStream->Release();
+
+ fclose(FileToCopy);
+ free(FileBuf);
+}
+
+//+----------------------------------------------------------------------------// Function: CopyDocfileToTree, private
+//
+// Synopsis: enumerates and reads docfile and creates directory tree
+//
+// Effects: for each child IStorage in the root docfile, a subdir is created,
+// for each child stream, a file is created. this function is
+// recursive.
+//
+// Arguments: [pstgParent] - current parent IStorage for reading containees
+// [ptcsDFName] - name of IStorage to instantiate
+//
+// Created: RichE, January 13, 1992
+// Revised: RichE March 5, 1992 Df APIs to method calls
+// Revised: RichE March 6, 1992 TRANSACTED mode operation
+// Revised: RichE March 17, 1992 convert to OLE interfaces
+// Revised: t-chrisy June 30, 1992 removed the section on unlinking docfile
+//-----------------------------------------------------------------------------
+
+void CopyDocfileToTree(IStorage *pstgParent, TCHAR *ptcsDFName)
+{
+ IStorage *pstgSrc = NULL;
+ IEnumSTATSTG *penmWalk;
+ USHORT usEndOfBasePath;
+ SCODE scRc;
+ STATSTG sstg;
+ int iRc;
+
+ // Add back slash & save pointer to base of pure path at this level
+ strcat(szDestPath, BACK_SLASH);
+ usEndOfBasePath = strlen(szDestPath);
+
+ MakeSingle(szName, ptcsDFName);
+
+ // If not first call (parent != NULL) then instantiate child IStorage with
+ // method call, else instantiate root docfile via Df API call
+ if (pstgParent != NULL)
+ {
+ tprintf(bDestOut, "Get embedded IStorage %s in parent %p\n",
+ szName, pstgParent);
+ scRc = GetScode(pstgParent->OpenStorage(ptcsDFName, NULL, dwChildFlags,
+ NULL, 0, &pstgSrc));
+ }
+ else
+ {
+ tprintf(bDestOut, "Instantiate root docfile %s\n", szName);
+ dwRootFlags |= STGM_READ;
+ scRc = GetScode(StgOpenStorage(ptcsDFName, NULL, dwRootFlags, NULL,
+ 0, &pstgSrc));
+ }
+
+ tprintf(bDestOut, "Return code: %lu, IStorage pointer %p\n",
+ scRc, pstgSrc);
+ if (pstgSrc == NULL || FAILED(scRc))
+ {
+ ErrExit(DEST_LOG, scRc, "Error instantiating IStorage %s\n", szName);
+ }
+
+ // Get an enumerator on the IStorage we just instantiated
+ scRc = GetScode(pstgSrc->EnumElements(0, NULL, 0, &penmWalk));
+ tprintf(bDestOut, "Got enumerator %p on IStorage %p, returned %lu\n",
+ penmWalk, pstgSrc, scRc);
+ if (penmWalk == NULL || FAILED(scRc))
+ {
+ ErrExit(DEST_LOG, scRc,
+ "Error obtaining enumerator for IStorage %p\n", pstgSrc);
+ }
+
+ // Loop until GetNext returns other than S_OK, then break out of loop
+ while (TRUE)
+ {
+ if (GetScode(penmWalk->Next(1, &sstg, NULL)) != S_OK)
+ {
+ tprintf(bDestOut, "No more to enumerate with enumerator %p\n",
+ penmWalk);
+ break;
+ }
+ else
+ {
+ MakeSingle(szName, sstg.pwcsName);
+ tprintf(bDestOut, "Got item type %lu, Name %s, w/enumerator %p\n",
+ sstg.type, szName, penmWalk);
+
+ // Restore to path + BACK_SLASH and add file/dir name to DestPath
+ szDestPath[usEndOfBasePath] = NIL;
+ strcat(szDestPath, szName);
+ tprintf(bDestOut, "Path Name: %s is ", szDestPath);
+ if (sstg.type == STGTY_STORAGE)
+ {
+ tprintf(bDestOut, "STGTY_STORAGE\n");
+ iRc = _mkdir(szDestPath);
+ tprintf(bDestOut,
+ "Trying to make directory %s, returned %d\n",
+ szDestPath, iRc);
+ CopyDocfileToTree(pstgSrc, sstg.pwcsName);
+ }
+ else
+ {
+ tprintf(bDestOut, "STGTY_STREAM\n");
+ CopyStreamToFile(pstgSrc, sstg.pwcsName);
+ }
+ }
+
+ utMemFree(sstg.pwcsName);
+ }
+
+ tprintf(bDestOut, "Releasing enumerator %p\n", penmWalk);
+ penmWalk->Release();
+}
+
+
+//+----------------------------------------------------------------------------
+// Function: CopyStreamToFile, private
+//
+// Synopsis: copies supplied embedded stream to file in current dubdir
+//
+// Arguments: [pstgParent] - parent IStorage for stream to copy
+// [ptcsStreamName] - name of stream to copy to file
+//
+// Created: RichE, January 13, 1992
+// Revised: RichE March 5, 1992 Df APIs to method calls
+// Revised: RichE March 6, 1992 TRANSACTED mode operation
+// Revised: RichE March 15, 1992 streams no longer TRANSACTED
+// Revised: RichE March 17, 1992 convert to OLE interfaces
+//-----------------------------------------------------------------------------
+
+void CopyStreamToFile(IStorage *pstgParent, TCHAR *ptcsStreamName)
+{
+ IStream *pstmStream = NULL;
+ FILE *FileToWrite;
+ ULONG cNumRead = 1;
+ ULONG cNumWritten;
+ BYTE *FileBuf;
+ SCODE scRc;
+
+ tprintf(bDestOut, "Copying embedded stream to file %s\n", szDestPath);
+
+ // Instantiate named stream within parent IStorage
+ tprintf(bDestOut, "Get stream in parent %p\n", pstgParent);
+ scRc = GetScode(pstgParent->OpenStream(ptcsStreamName, NULL, STGM_STREAM,
+ 0, &pstmStream));
+ tprintf(bDestOut, "Returned: %lu, stream pointer %p\n", scRc, pstmStream);
+ if (pstmStream == NULL || FAILED(scRc))
+ {
+ ErrExit(DEST_LOG, scRc, "Error opening stream %s\n", szDestPath);
+ }
+
+ FileToWrite = fopen(szDestPath, "wb");
+ if (FileToWrite == NULL)
+ {
+ ErrExit(DEST_LOG, ERR, "Cannot open file %s\n", szDestPath);
+ }
+
+ FileBuf = (BYTE * ) Allocate(FILE_BUF_SIZE * sizeof(BYTE));
+
+ // While still reading Stream, write what was just read to file.
+ tprintf(bDestOut, "Starting to read stream %p\n", pstmStream);
+ while (cNumRead > 0)
+ {
+ scRc = GetScode(pstmStream->Read(FileBuf, FILE_BUF_SIZE, &cNumRead));
+ tprintf(bDestOut, "Read %lu bytes from stream %p, returned %lu\n",
+ cNumRead, pstmStream, scRc);
+ if (FAILED(scRc))
+ {
+ ErrExit(DEST_LOG, scRc, "Error reading stream %p\n", pstmStream);
+ }
+ cNumWritten = (ULONG)fwrite(FileBuf, 1, (size_t)cNumRead, FileToWrite);
+ if (ferror(FileToWrite))
+ {
+ ErrExit(DEST_LOG, ERR, "Error writing to file %s\n", szDestPath);
+ }
+
+ if (cNumWritten != cNumRead)
+ {
+ tprintf(bDestOut, "Fwrite: cNumRead = %lu, cNumWritten = %lu\n",
+ cNumRead, cNumWritten);
+ }
+ }
+
+ tprintf(bDestOut, "Attempting to release stream %p in IStorage %p\n",
+ pstmStream, pstgParent);
+ pstmStream->Release();
+
+ fclose(FileToWrite);
+ free(FileBuf);
+}
+
+
+//+----------------------------------------------------------------------------
+// Function: GetOptions, private
+// Returns: DOCTOTREE or TREETODOC to indicate the direction of conversion.
+//
+// Synopsis: parses command line and sets global program options/variables
+//
+// Arguments: [argc] and [**argv] passed from main() function
+//
+// Modifies: [szSrcPath, szDestPath, szDestDocfile]
+//
+// Created: RichE, January 13, 1992
+// Revised: RichE, March 15, 1992 added -T and -W switches
+// Revised: RichE, March 19, 1992 fixed bug displaying error usage
+// Revised: t-chrisy, June 25, 1992 added -f and -b switches
+//-----------------------------------------------------------------------------
+
+int GetOptions(int argc, char *argv[])
+{
+ char *pszArg;
+ char *pszProgName;
+ BOOL ArgsOK = TRUE;
+ short ret=DOCTOTREE;
+
+ // Bump past command name (argv[0])
+ pszProgName = *argv++;
+
+ // For each command line arg, if it begins with a '-' or '/' check the
+ // next letter for a valid argument. return error for invalid args
+
+ while ((pszArg = *argv++) != NULL)
+ {
+ if (*pszArg == '-' || *pszArg == '/')
+ {
+ switch (tolower(*(++pszArg)))
+ {
+ case 'w':
+ dwRootFlags |= STGM_TRANSACTED;
+ dwChildFlags |= STGM_TRANSACTED;
+ break;
+ case 't':
+ dwRootFlags |= STGM_TRANSACTED;
+ dwChildFlags |= STGM_TRANSACTED;
+ break;
+
+ case 's':
+ strcpy(szSrcPath, ++pszArg);
+ iSrcPathEnd = strlen(pszArg);
+ break;
+
+ case 'd':
+ strcpy(szDestPath, ++pszArg);
+ iDestPathEnd = strlen(pszArg);
+ break;
+
+ case 'z':
+ LogFile(++pszArg,LOG_INIT);
+ break;
+
+ case 'y':
+ SetDebugMode(tolower(*(++pszArg)));
+ break;
+
+ case 'n':
+ if (strlen(++pszArg) <= _MAX_PATH)
+ {
+ strcpy(szDestDocfile, pszArg);
+ }
+ else
+ {
+ tprintf(DEST_LOG, "Dest DocFile Name too long: %s\n",
+ pszArg);
+ tprintf(DEST_LOG, "Max len = %d\n", _MAX_PATH);
+ tprintf(DEST_LOG, "Specified len = %d\n", strlen(pszArg));
+ ArgsOK = FALSE;
+ }
+ break;
+
+ case 'f':
+ // Docfile to tree
+ dwRootFlags &= ~0x03; // clear access bits
+ dwRootFlags |= STGM_READ;
+ ret=DOCTOTREE;
+ break;
+
+ case 'b':
+ // Tree to docfile
+ dwRootFlags &= ~0x70;
+ dwRootFlags |= STGM_SHARE_EXCLUSIVE;
+ ret=TREETODOC;
+ break;
+
+ default:
+ ArgsOK = FALSE;
+ break;
+ }
+ }
+ else
+ ArgsOK = FALSE;
+
+ if (ArgsOK == FALSE)
+ {
+ tprintf(DEST_LOG,
+ "Invalid command line argument: %s\n", --pszArg);
+ Usage(pszProgName);
+ }
+ }
+ return ret;
+}
+
+
+//+----------------------------------------------------------------------------
+// Function: Usage, private
+//
+// Synopsis: displays program syntax and example and exits with error
+//
+// Arguments: [pszProgramName] - name of this executable file for error usage
+//
+// Created: RichE, January 15, 1992
+// Revised: t-chrisy, June 30, 1992 Added -f and -b options.
+//+----------------------------------------------------------------------------
+
+void Usage(char *pszProgName)
+{
+
+ tprintf(DEST_ERR, "Usage: %s\n", pszProgName);
+ tprintf(DEST_ERR, " [-f] - forward conversion"
+ "(docfile-->tree) DEFAULT\n");
+ tprintf(DEST_ERR, " -n and -d must be specified.");
+ tprintf(DEST_ERR, " [-b] - backward conversion"
+ "(tree-->docfile)\n");
+ tprintf(DEST_ERR, " -s and -n must be specified.");
+ tprintf(DEST_ERR, " [-sSRCDIR] \n");
+ tprintf(DEST_ERR, " [-nDOCFILENAME] \n");
+ tprintf(DEST_ERR, " [-dDESTDIR] \n");
+ tprintf(DEST_ERR, " [-t] - for transacted mode\n");
+ tprintf(DEST_ERR, " [-w] - for deny write mode\n");
+ ErrExit(DEST_ERR, ERR, " ex: %df2t -b -sc:\\dos -nd:\\docfile.dfl\n",
+ pszProgName);
+}
diff --git a/private/ole32/stg/utils/df2t/df2t.def b/private/ole32/stg/utils/df2t/df2t.def
new file mode 100644
index 000000000..a02484512
--- /dev/null
+++ b/private/ole32/stg/utils/df2t/df2t.def
@@ -0,0 +1,21 @@
+NAME DF2T
+#ifndef FLAT
+EXETYPE WINDOWS
+//STUB 'WINSTUB.EXE'
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 16384
+STACKSIZE 8192
+#else
+EXETYPE NT
+SUBSYSTEM WINDOWSCHAR
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 16384
+STACKSIZE 8192
+#endif
+
diff --git a/private/ole32/stg/utils/df2t/makefile b/private/ole32/stg/utils/df2t/makefile
new file mode 100644
index 000000000..b63071db3
--- /dev/null
+++ b/private/ole32/stg/utils/df2t/makefile
@@ -0,0 +1,28 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1994.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+all:
+ echo $(BUILDMSG)
+
+clean: all
+
+!else
+
+default: all
+
+EXENAME = df2t
+
+CXXFILES = .\w4ctsupp.cxx
+
+!include $(OLE)\utils\util.mk
+!include $(COMMON)\src\win40.mk
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/stg/utils/df2t/read.me b/private/ole32/stg/utils/df2t/read.me
new file mode 100644
index 000000000..3ee4511aa
--- /dev/null
+++ b/private/ole32/stg/utils/df2t/read.me
@@ -0,0 +1,13 @@
+Command line: df2c -f/-b -(n)ameofDocfile -(s)rcTree -(d)estTree -T -W
+ -f forward conversion (docfile --> tree)
+ -b backward conversion (tree --> docfile)
+ -n name for root docfile
+ -s name of the source directory tree
+ -d name of the destination directory tree
+ -t specifies STGM_TRANSACTED mode
+ -w specifies STGM_DENY_WRITE mode for root docfile
+ (-f and -b cannot be both specified in one command.)
+
+ Examples: df2t -f -nc:\ole\docfile -dc:\ole\testdir
+ or df2t -b -sc:\storage -nc:\ole\testdir\docfile
+
diff --git a/private/ole32/stg/utils/df2t/w4ctsupp.cxx b/private/ole32/stg/utils/df2t/w4ctsupp.cxx
new file mode 100644
index 000000000..ac59a8ccc
--- /dev/null
+++ b/private/ole32/stg/utils/df2t/w4ctsupp.cxx
@@ -0,0 +1,589 @@
+//############################################################################
+//#
+//# Microsoft Windows
+//# Copyright (C) Microsoft Corporation, 1992 - 1992.
+//# All rights reserved.
+//#
+//############################################################################
+//
+//+----------------------------------------------------------------------------
+// File: W4CTSUPP.CXX
+//
+// Contents: Contains support functions for docfile testing
+//
+// Command line: N/A
+//
+// Requires: must be linked with program containing function main()
+//
+// Notes: Compiled to create W4CTSUPP.LIB
+//
+// Created: RichE March 1992
+//-----------------------------------------------------------------------------
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <direct.h>
+#include <ctype.h>
+#include <time.h>
+
+#define __CRC32__
+#include "w4ctsupp.hxx"
+
+#include <dfdeb.hxx>
+
+//char for separating FAT file name from extension
+#define FILE_NAME_SEPARATOR '.'
+
+//global array of interesting file sizes for IStream read/writes
+USHORT ausSIZE_ARRAY[] = {0,1,2,255,256,257,511,512,513,2047,2048,2049,4095,4096,4097};
+
+//test logging file pointer
+static FILE *fileLogFile = NULL;
+
+//should log be closed after every log write, modified by SetDebugMode()
+static BOOL fCloseLogAfterWrite = FALSE;
+
+//test name string for ErrExit and application use
+char szTestName[MAX_TEST_NAME_LEN + 1] = "No Test Name Specified";
+
+//random number seed used by test apps
+USHORT usRandomSeed = 0;
+
+//routing variable for standard out in tprintf and ErrExit calls
+//can be changed from default of DEST_OUT
+BYTE bDestOut = DEST_OUT;
+
+//+----------------------------------------------------------------------------
+// Function: Allocate, public
+//
+// Synopsis: allocate memory, exit with error if malloc failes
+//
+// Arguments: [cbBytesToAllocate] - size of memory block to allocate
+//
+// Returns: void pointer to block of memory allocated
+//
+// Created: RichE March 1992
+//-----------------------------------------------------------------------------
+
+void *Allocate(size_t cbBytesToAllocate)
+{
+ void *pvMemPtr;
+
+ pvMemPtr = (void *) malloc(cbBytesToAllocate);
+ if(pvMemPtr == NULL)
+ {
+ ErrExit(DEST_ERR, ERR, "Unable to allocate %u bytes of memory\n",
+ cbBytesToAllocate);
+ }
+
+ return pvMemPtr;
+}
+
+//+----------------------------------------------------------------------------
+// Function: MakePath, public
+//
+// Synopsis: makes a sub-directory at end of specified path
+//
+// Effects: For each char in pszDirToMake, if it's a '\', make the destination
+// directory at the level accumulated in pszPathBuf, else append
+// the next letter of the dest path to pszPathBuf. After the loop,
+// attempt to _mkdir a final time (since the path probably won't
+// end with a '\').
+//
+// Arguments: [pszDirToMake] - full directory path name to make
+//
+// Returns: TRUE if all directories in path were made OK, otherwise FALSE
+//
+// Created: RichE January 1992
+//-----------------------------------------------------------------------------
+
+BOOL MakePath(char *pszDirToMake)
+{
+#ifdef DBCS
+ char *pszDirToMakeSav = pszDirToMake;
+#endif
+ char *pcDestPathSoFar;
+ char *pszPathBuf;
+ int iRc;
+
+ pszPathBuf = (char *) Allocate(_MAX_PATH + 1);
+ pcDestPathSoFar = pszPathBuf;
+
+ //
+ //while not at end of path string, if this char is a back slash, make
+ //the directory up to the slash. in either case, copy the next char
+ //into the accumulated path buffer.
+ //
+
+ while (*pszDirToMake)
+ {
+ if (*pszDirToMake == '\\')
+ {
+ *pcDestPathSoFar = NIL;
+ iRc = _mkdir(pszPathBuf);
+ tprintf(bDestOut, "Trying to make directory %s, returned %d\n",
+ pszPathBuf, iRc);
+ }
+#ifdef DBCS
+ #ifdef _MAC
+ if (iskanji (*pszDirToMake)) // iskanji is in dbcsutil.cpp
+ #else
+ if (IsDBCSLeadbyte (*pszDirToMake))
+ #endif
+ *pcDestPathSoFar++ = *pszDirToMake++;
+#endif
+ *pcDestPathSoFar++ = *pszDirToMake++;
+ }
+
+ //
+ //if the last char wasn't a back slash, the last part of the path hasn't
+ //been made so make it.
+ //
+#ifdef DBCS
+ #ifdef _MAC
+ DecLpch (pszDirToMakeSav, pszDirToMake);
+ #else
+ pszDirToMake = AnsiPrev (pszDirToMakeSav, pszDirToMake);
+ #endif // MAC
+ if (*pszDirToMake != '\\')
+#else
+ if (*(--pszDirToMake) != '\\')
+#endif
+ {
+ *pcDestPathSoFar = NIL;
+ iRc = _mkdir(pszPathBuf);
+ tprintf(bDestOut, "Trying to make directory %s, returned %d\n",
+ pszPathBuf, iRc);
+ }
+
+ free(pszPathBuf);
+
+ return (iRc == 0) ? TRUE : FALSE;
+}
+
+
+
+//+----------------------------------------------------------------------------
+// Function: SetDebugMode, public
+//
+// Synopsis: sets debugging mode and program exit control and tprintf routing
+//
+// Effects: Sets exit control to 'no exit when complete.' depending upon
+// the char passed, in calls debug macro to set appropriate
+// debug mode. If no debug is specified, sets program exit
+// control to 'exit when complete' and sets flag to close log
+// file after every log write. If a debug mode other than
+// none is specified, redirects default output destination to
+// DEST_LOG instead of DEST_OUT. Also sets capture buffer to
+// unlimited size
+//
+// Arguments: [DebugMode] - single character representing desired mode
+//
+// Modifiles: [fCloseLogAfterWrite] - if running in non-debug mode, close
+// log file after every write
+//
+// Created: RichE April 1992
+//-----------------------------------------------------------------------------
+
+void SetDebugMode(char DebugMode)
+{
+ SET_DISPLAY_BUF_SIZE;
+
+ NO_EXIT_WHEN_DONE;
+
+ switch(DebugMode)
+ {
+ case 'a':
+ DEBUG_ALL;
+ bDestOut = DEST_LOG;
+ break;
+
+ case 'n':
+ DEBUG_NONE;
+ EXIT_WHEN_DONE;
+ //fCloseLogAfterWrite = TRUE;
+ break;
+
+ case 'd':
+ DEBUG_DOCFILE;
+ bDestOut = DEST_LOG;
+ break;
+
+ case 'm':
+ DEBUG_MSF;
+ bDestOut = DEST_LOG;
+ break;
+
+ case 'i':
+ default:
+ DEBUG_INTERNAL_ERRORS;
+ bDestOut = DEST_LOG;
+ break;
+
+ }
+}
+
+
+
+//+----------------------------------------------------------------------------
+// Function: ErrExit, public
+//
+// Synopsis: allows error output to any combo of stdout, stderr, and logfile
+//
+// Effects: depending upon flags passed in, will display (via vfprintf)
+// error output to any combination of stdout, stderr, and a user-
+// supplied log file. if output destination is a log file,
+// will open the log file if not already open and set
+// all output to the error output destination as well.
+// prints docfile error message based on error code, or
+// generic error message is error is undefined. prints error
+// return code, prints FAIL message using extern global [szTestName]
+// (defined in calling test) and exits with error code.
+//
+// Arguments: [bOutputDest] - bit flags specifying where output goes
+// valid flags defined in W4CTSUPP.HXX
+// [ErrCode] - error code to use in exit() function
+// [fmt] - vfprintf formatting string
+// [...] - parameters to vfprintf function
+//
+// Created: RichE March 1992
+//-----------------------------------------------------------------------------
+
+void ErrExit(BYTE bOutputDest, SCODE ErrCode, char *fmt, ...)
+{
+ USHORT iErrIndex = 0;
+
+ struct
+ {
+ SCODE scErrCode;
+ char *pszErrMessage;
+ } aszErrMessages[] = {S_FALSE, "S_FALSE",
+ STG_E_INVALIDFUNCTION, "STG_E_INVALIDFUNCTION",
+ STG_E_FILENOTFOUND, "STG_E_FILENOTFOUND",
+ STG_E_TOOMANYOPENFILES, "STG_E_TOOMANYOPENFILES",
+ STG_E_ACCESSDENIED, "STG_E_ACCESSDENIED",
+ STG_E_INVALIDHANDLE, "STG_E_INVALIDHANDLE",
+ STG_E_INSUFFICIENTMEMORY, "STG_E_INSUFFICIENTMEMORY",
+ STG_E_INVALIDPOINTER, "STG_E_INVALIDPOINTER",
+ STG_E_NOMOREFILES, "STG_E_NOMOREFILES",
+ STG_E_WRITEFAULT, "STG_E_WRITEFAULT",
+ STG_E_READFAULT, "STG_E_READFAULT",
+ STG_E_LOCKVIOLATION, "STG_E_LOCKVIOLATION",
+ STG_E_FILEALREADYEXISTS, "STG_E_FILEALREADYEXISTS",
+ STG_E_INVALIDPARAMETER, "STG_E_INVALIDPARAMETER",
+ STG_E_MEDIUMFULL, "STG_E_MEDIUMFULL",
+ STG_E_ABNORMALAPIEXIT, "STG_E_ABNORMALAPIEXIT",
+ STG_E_INVALIDHEADER, "STG_E_INVALIDHEADER",
+ STG_E_INVALIDNAME, "STG_E_INVALIDNAME",
+ STG_E_UNKNOWN, "STG_E_UNKNOWN",
+ STG_E_UNIMPLEMENTEDFUNCTION, "STG_E_UNIMPLEMENTEDFUNCTION",
+ STG_E_INVALIDFLAG, "STG_E_INVALIDFLAG",
+ STG_E_INUSE, "STG_E_INUSE",
+ STG_E_NOTCURRENT, "STG_E_NOTCURRENT",
+ STG_E_REVERTED, "STG_E_REVERTED",
+ STG_S_CONVERTED, "STG_S_CONVERTED",
+ ERR, "GENERIC_ERROR"
+ };
+
+ va_list args;
+
+ va_start(args, fmt);
+
+ //if dest is log file, open log file if not already open
+ //and set all output to DEST_ERR as well.
+ if (bOutputDest & DEST_LOG)
+ {
+ bOutputDest |= DEST_ERR;
+
+ if (fileLogFile == NULL)
+ {
+ LogFile(NULL, LOG_OPEN);
+ }
+
+ vfprintf(fileLogFile, fmt, args);
+
+ if (fCloseLogAfterWrite == TRUE)
+ {
+ LogFile(NULL, LOG_CLOSE);
+ }
+ }
+
+ if (bOutputDest & DEST_OUT)
+ {
+ vfprintf(stdout, fmt, args);
+ }
+
+ if (bOutputDest & DEST_ERR)
+ {
+ vfprintf(stderr, fmt, args);
+ }
+
+ va_end(args);
+
+ tprintf(bOutputDest, "Return code %lu (0x%08lX), ", ErrCode, ErrCode);
+
+ //lookup error in struct table and print error message
+ while (aszErrMessages[iErrIndex].scErrCode != ErrCode)
+ {
+ if (aszErrMessages[iErrIndex].scErrCode == ERR)
+ {
+ break;
+ }
+ else
+ {
+ iErrIndex++;
+ }
+ }
+
+ tprintf(bOutputDest, "%s\n", aszErrMessages[iErrIndex].pszErrMessage);
+
+ tprintf(bOutputDest, "FAIL: %s\n", szTestName);
+
+ exit((int) ErrCode);
+}
+
+
+
+//+----------------------------------------------------------------------------
+// Function: tprintf, public
+//
+// Synopsis: allows output to any combo of stdout, stderr, and logfile
+//
+// Effects: depending upon flags passed in, will display (via vfprintf)
+// output to any combination of stdout, stderr, and a user-
+// supplied log file. if output destination is a log file,
+// will open the log file if not already open and set
+// all output to the error output destination as well.
+//
+// Arguments: [bOutputDest] - bit flags specifying where output goes
+// valid flags defined in W4CTSUPP.HXX
+// [fmt] - vfprintf formatting string
+// [...] - parameters to vfprintf function
+//
+// Created: RichE March 1992
+//-----------------------------------------------------------------------------
+
+void tprintf(BYTE bOutputDest, char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+
+ //if dest is log file, open log file if not already open
+ //and set all output to DEST_ERR as well.
+ if (bOutputDest & DEST_LOG)
+ {
+ bOutputDest |= DEST_ERR;
+
+ if (fileLogFile == NULL)
+ {
+ LogFile(NULL, LOG_OPEN);
+ }
+
+ vfprintf(fileLogFile, fmt, args);
+
+ if (fCloseLogAfterWrite == TRUE)
+ {
+ LogFile(NULL, LOG_CLOSE);
+ }
+ }
+
+ if (bOutputDest & DEST_OUT)
+ {
+ vfprintf(stdout, fmt, args);
+ }
+
+ if (bOutputDest & DEST_ERR)
+ {
+ vfprintf(stderr, fmt, args);
+ }
+
+ va_end(args);
+}
+
+
+
+//+----------------------------------------------------------------------------
+// Function: LogFile, public
+//
+// Synopsis: opens or closed specified file for logging via tprintf and errexit
+//
+// Effects: the specfied file is opened via fopen for logging purposes when
+// [bLogFileAction] = LOG_OPEN and closed for LOG_CLOSE. The
+// calling application should open the LogFile via a LOG_INIT
+// call which will define the routine to call to ensure that the
+// log file is closed upon completion and set the log file name.
+//
+// Modifies: [fileLogFile] - the global variable defined at top of this file
+// will contain a pointer to the log file stream on exit.
+//
+// Arguments: [pszLogFileName] - pathname of file for logging purposes
+// [bLogFileAction] - whether to open or close the log file
+//
+// Notes: [pszLogReOpenName] is the filename to use for opening the log
+// file. In non-debug runs, the log file is closed after every
+// log write and re-opened before the next write.
+//
+// Created: RichE March 1992
+//-----------------------------------------------------------------------------
+
+void LogFile(char *pszLogFileName, BYTE bLogFileAction)
+{
+ static char *pszLogReOpenName = NULL;
+ static BOOL fFirstInitCall = FALSE;
+ char *pszTestDataDir;
+
+ switch (bLogFileAction)
+ {
+ case LOG_INIT:
+ if (pszLogFileName == NULL)
+ {
+ ErrExit(DEST_ERR, ERR, "No filename specified for LOG_INIT\n");
+ }
+
+ if (fileLogFile != NULL)
+ {
+ fclose(fileLogFile);
+ free(pszLogReOpenName);
+ }
+
+ pszLogReOpenName = (char *) Allocate(strlen(pszLogFileName)+1);
+ strcpy(pszLogReOpenName, pszLogFileName);
+
+ if (fFirstInitCall == FALSE)
+ {
+ //register function to call on program exit
+ //
+
+ atexit(MakeSureThatLogIsClosed);
+ fFirstInitCall = TRUE;
+
+ //
+ //change to dir specified by DFDATA env variable, if it's set
+ //
+
+ if (pszTestDataDir = getenv("DFDATA"))
+ {
+ _chdir(pszTestDataDir);
+ }
+ }
+
+ break;
+
+ case LOG_OPEN:
+ if (fileLogFile != NULL)
+ {
+ ErrExit(DEST_ERR,ERR,"Can't open log file %s, log is already open!",
+ pszLogReOpenName);
+ }
+
+ if (pszLogReOpenName == NULL)
+ {
+ pszLogReOpenName = (char *) Allocate(strlen(LOG_DEFAULT_NAME)+1);
+ strcpy(pszLogReOpenName, LOG_DEFAULT_NAME);
+ }
+
+ if ((fileLogFile = fopen(pszLogReOpenName, "w")) == NULL)
+ {
+ ErrExit(DEST_ERR, ERR, "Error opening log file %s\n",
+ pszLogReOpenName);
+ }
+
+ break;
+
+ case LOG_CLOSE:
+ if (fileLogFile != NULL)
+ {
+ fflush(fileLogFile);
+ fclose(fileLogFile);
+ }
+ else
+ {
+ tprintf(DEST_ERR,"Warning: can't close log file %s, log isn't open!",
+ pszLogReOpenName);
+ }
+
+ break;
+
+ default:
+ ErrExit(DEST_ERR,ERR,"Invalid parameter to LogFile() function!");
+ }
+}
+
+
+
+//+----------------------------------------------------------------------------
+// Function: MakeSureThatLogFileIsClosed
+//
+// Synopsis: closes log file on exit
+//
+// Effects: immediately flushes all file buffers, and then calls Logfile to
+// close the test log file. upon abnormal exit (GP fault), this saves most
+// of the log information.
+//
+// Created: RichE March 1992
+//-----------------------------------------------------------------------------
+
+void MakeSureThatLogIsClosed(void)
+{
+ //fflush(fileLogFile);
+ LogFile(NULL, LOG_CLOSE);
+
+}
+
+//+----------------------------------------------------------------------------
+// Function: MakeSingle, public
+//
+// Synopsis: converts TCHAR string to single character string
+//
+// Arguments: [pszSingleName] - pointer to TCHAR string
+// [ptcsWideName] - buffer to hold returned single-wide string
+//
+// Modifies: [pszSingleName] - on exit holds single-wide character string
+//
+// Created: RichE March 1992
+//-----------------------------------------------------------------------------
+
+void MakeSingle(char *pszSingleName, TCHAR *ptcsWideName)
+{
+#ifdef UNICODE
+ USHORT cusBufLen = (tcslen(ptcsWideName)+1) * sizeof(TCHAR);
+
+ if (_fwcstombs(pszSingleName, ptcsWideName, cusBufLen) == -1)
+ {
+ ErrExit(DEST_LOG, ERR, "Error converting TCHAR string to single wide\n");
+ }
+#else
+ strcpy(pszSingleName, ptcsWideName);
+#endif
+}
+
+
+
+//+----------------------------------------------------------------------------
+// Function: MakeWide, public
+//
+// Synopsis: converts single character string to multi-byte (TCHAR) string
+//
+// Arguments: [ptcsWideName] - buffer to hold returned TCHAR string
+// [pszSingleName] - pointer to single wide string
+//
+// Modifies: [ptcsWideName] - on exit holds wide character string
+//
+// Created: RichE March 1992
+//-----------------------------------------------------------------------------
+
+void MakeWide(TCHAR *ptcsWideName, char *pszSingleName)
+{
+#ifdef UNICODE
+ USHORT cusBufLen = (strlen(pszSingleName)+1) * sizeof(TCHAR);
+
+ if (_fmbstowcs(ptcsWideName, pszSingleName, cusBufLen) == -1)
+ {
+ ErrExit(DEST_LOG, ERR, "Error converting name %s to TCHAR string\n", pszSingleName);
+ }
+#else
+ strcpy(ptcsWideName, pszSingleName);
+#endif
+}
diff --git a/private/ole32/stg/utils/df2t/w4ctsupp.hxx b/private/ole32/stg/utils/df2t/w4ctsupp.hxx
new file mode 100644
index 000000000..0ce67eca0
--- /dev/null
+++ b/private/ole32/stg/utils/df2t/w4ctsupp.hxx
@@ -0,0 +1,172 @@
+//############################################################################
+//#
+//# Microsoft Windows
+//# Copyright (C) Microsoft Corporation, 1992 - 1992.
+//# All rights reserved.
+//#
+//############################################################################
+//
+//+----------------------------------------------------------------------------
+// File: W4CTSUPP.HXX
+//
+// Contents: defines, macros, and prototypes for functions in w4ctsupp.cxx
+//
+// Created: RichE March 1992
+// Modified: added STGM_STREAM declaration t-chrisy 7/30/92
+//-----------------------------------------------------------------------------
+
+#ifndef __W4CTSUPP_HXX__
+#define __W4CTSUPP_HXX__
+
+extern "C"
+{
+ #include <memory.h>
+ #include <stdio.h>
+ #include <limits.h>
+ #include <io.h>
+ #include <assert.h>
+}
+
+#include <windows.h>
+#include <storage.h>
+#include <dfdeb.hxx>
+
+#define STGM_STREAM (STGM_READWRITE|STGM_SHARE_EXCLUSIVE)
+
+#ifdef UNICODE
+ #define tcslen wcslen
+ #define tsccpy wcscpy
+ #define tcscmp wcscmp
+ #define MAX_STG_NAME_LEN CWCSTORAGENAME
+ #define TCHAR_NIL (wchar_t)'\0'
+ #include <wchar.h>
+#else
+ #define tcslen strlen
+ #define tcscpy strcpy
+ #define tcscmp strcmp
+ #define TCHAR_NIL '\0'
+ #define MAX_STG_NAME_LEN (CWCSTORAGENAME * 2)
+#endif
+
+//
+// set debugging macros used by 'SetDebugMode' in w4ctsupp.cxx
+// DBG is set for debug builds, not set for retail builds
+//
+
+#if DBG == 1
+ STDAPI_(void) DfDebug(ULONG ulLevel, ULONG ulMSFLevel);
+ #define DEBUG_ALL DfDebug(0xffffffff,0xffffffff)
+ #define DEBUG_NONE DfDebug(0x00000000,0x00000000)
+ #define DEBUG_INTERNAL_ERRORS DfDebug(0x00000101,0x00000101)
+ #define DEBUG_DOCFILE DfDebug(0xffffffff,0x00000000)
+ #define DEBUG_MSF DfDebug(0x00000000,0xffffffff)
+#else
+ #define DEBUG_ALL ;
+ #define DEBUG_NONE ;
+ #define DEBUG_INTERNAL_ERRORS ;
+ #define DEBUG_DOCFILE ;
+ #define DEBUG_MSF ;
+#endif
+
+
+
+//
+//define QuickWin calls to tell program what to do upon completion
+//and to set up an 'infinite' size output capture buffer
+//
+
+#define EXIT_WHEN_DONE _wsetexit(_WINEXITNOPERSIST)
+#define NO_EXIT_WHEN_DONE _wsetexit(_WINEXITPERSIST)
+#define SET_DISPLAY_BUF_SIZE _wsetscreenbuf(_fileno(stdout), _WINBUFINF)
+#define _YIELD _wyield()
+
+//
+//global defines and size macros
+//
+
+#define NIL '\0'
+#define ERR (SCODE) ~0
+#define MAX_IO (ULONG) 256000
+#define MAX_TEST_NAME_LEN 40
+#define MAX_BYTE UCHAR_MAX
+#define MAX_USHORT USHRT_MAX
+#define MAX_SHORT SHRT_MAX
+#define MAX_ULONG ULONG_MAX
+#define MAX_LONG LONG_MAX
+
+
+//
+//defines for logging, tprintf, and ErrExit functions
+//
+
+#define LOG_DEFAULT_NAME "OLETEST.LOG"
+#define DEST_LOG 1
+#define DEST_OUT 2
+#define DEST_ERR 4
+#define DEST_ALL 8
+#define LOG_INIT 16
+#define LOG_OPEN 32
+#define LOG_CLOSE 64
+
+
+
+//
+//32 bit CRC declarations and macro definitions. The logic was taken from
+//the book 'C Programmer's Guide to Netbios'.
+//
+
+#ifdef __CRC32__
+ extern BYTE ibCrcIndex;
+ extern ULONG aulCrc[];
+ #define CRC_INIT(X) X = 0xFFFFFFFFL
+ #define CRC_CALC(X,Y) ibCrcIndex = (BYTE) ((X ^ Y) & 0x000000FFL); \
+ X = ((X >> 8) & 0x00FFFFFFL) ^ aulCrc[ibCrcIndex]
+ #define CRC_GOOD(X) (X == 0xDEBB20E3L) ? TRUE : FALSE
+#endif
+
+
+
+//
+//interesting docfile specific defines
+//
+
+#define STG_CONVERTED_NAME "CONTENTS"
+#define MAX_FILE_SYS_NAME_LEN 8
+#define MAX_LEVELS 6
+#define MIN_OBJS 18
+#define MIN_SIZE 394000L
+#define MAX_SIZE_ARRAY 14
+#define MAX_SIZE_MULTIPLIER 15
+
+
+
+//
+//extern global declarations
+//
+
+extern char szTestName[];
+extern BYTE bDestOut;
+extern USHORT usRandomSeed;
+extern USHORT ausSIZE_ARRAY[];
+
+
+
+//
+//function prototypes in order of appearance in w4ctsupp.cxx
+//
+
+void *Allocate(size_t cbBytesToAllocate);
+ULONG GenerateNewName(char **pszNewName, BOOL fIsFileSysName);
+BOOL MakePath(char *pszDirToMake);
+void SetDebugMode(char DebugMode);
+
+void ErrExit(BYTE OutputDest, SCODE ErrCode, char *fmt, ...);
+void tprintf(BYTE OutputDest, char *fmt, ...);
+
+void LogFile(char *pszLogFileName, BYTE bLogFileAction);
+void MakeSureThatLogIsClosed(void);
+
+void MakeSingle(char *pszSingleName, TCHAR *ptcsWideName);
+void MakeWide(TCHAR *ptcsWideName, char *pszSingleName);
+
+#endif
diff --git a/private/ole32/stg/utils/fail/depend.mk9 b/private/ole32/stg/utils/fail/depend.mk9
new file mode 100644
index 000000000..78f15a788
--- /dev/null
+++ b/private/ole32/stg/utils/fail/depend.mk9
@@ -0,0 +1,61 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\sift.obj $(OBJDIR)\sift.lst: .\sift.cxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\io.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE)\h\dfdeb.hxx \
+ $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx \
+ $(OLE)\h\ref.hxx $(OLE)\h\wchar.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\headers.cxx \
+ .\sift.hxx
+
+$(OBJDIR)\fail.obj $(OBJDIR)\fail.lst: .\fail.cxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\io.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE)\h\dfdeb.hxx \
+ $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx \
+ $(OLE)\h\ref.hxx $(OLE)\h\wchar.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\headers.cxx \
+ .\sift.hxx
+
+$(OBJDIR)\supp.obj $(OBJDIR)\supp.lst: .\supp.cxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\io.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE)\h\dfdeb.hxx \
+ $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx \
+ $(OLE)\h\ref.hxx $(OLE)\h\wchar.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h .\headers.cxx \
+ .\sift.hxx
+
+#
+# Precompiled C++ header
+#
+
+!ifdef PXXFILE
+$(PCHDIR)\$(OBJDIR)\headers.pxh $(PCHDIR)\$(OBJDIR)\headers.lst: \
+ $(OLE)\utils\fail\headers.cxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\io.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OLE)\h\dfdeb.hxx \
+ $(OLE)\h\dfmem.hxx $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx \
+ $(OLE)\h\ref.hxx $(OLE)\h\wchar.h $(OLE2H)\coguid.h \
+ $(OLE2H)\compobj.h $(OLE2H)\initguid.h $(OLE2H)\scode.h \
+ $(OLE2H)\storage.h $(OLE2H)\valid.h $(OSINC)\windows.h
+
+.\$(OBJDIR)\sift.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+.\$(OBJDIR)\fail.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+
+.\$(OBJDIR)\supp.obj : $(PCHDIR)\$(OBJDIR)\headers.pxh
+
+!endif # PXXFILE
+
+
diff --git a/private/ole32/stg/utils/fail/fail.cxx b/private/ole32/stg/utils/fail/fail.cxx
new file mode 100644
index 000000000..03505335d
--- /dev/null
+++ b/private/ole32/stg/utils/fail/fail.cxx
@@ -0,0 +1,2666 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: Fail.CXX
+//
+// Contents: Docfile Failure Test
+//
+// History: 21-Jan-93 AlexT Created
+//
+// Notes: This test cycles through all failure points for each call,
+// verifying that we clean up correctly.
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+
+#pragma hdrstop
+
+#include <sift.hxx>
+
+#if DBG != 1
+#error FAIL.EXE requires DBG == 1
+#endif
+
+// #define BREADTHTEST // Comment out for depth testing (just most recent tests)
+
+//+-------------------------------------------------------------------------
+//
+// Function: VerifyDisk
+//
+// Synopsis: verify that disk file does or does not exist
+//
+// Arguments: [fExist] -- TRUE if file should exist, else FALSE
+// [iteration] -- iteration number
+//
+// History: 22-Jan-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+void VerifyDisk(BOOL fExist, LONG iteration)
+{
+ if (_access("c:\\testfail.dfl", 0) == 0)
+ {
+ if (!fExist)
+ {
+ printf("..Iteration %ld, file still exists\n", iteration);
+ }
+ }
+ else
+ {
+ if (fExist)
+ {
+ printf("..Iteration %ld, file doesn't exist\n", iteration);
+ }
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: VerifyMemory
+//
+// Arguments: [iteration] -- iteration number
+//
+// Requires: Caller should expect 0 memory to be allocated
+//
+// History: 22-Jan-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+void VerifyMemory(LONG iteration)
+{
+ if (DfGetMemAlloced() > 0L)
+ {
+ printf("..Iteration %ld - memory allocated\n", iteration);
+ DfPrintAllocs();
+ }
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: VerifyClean
+//
+// Synopsis: checks disk, memory
+//
+// Arguments: [sc] -- status code
+// [dwMode] -- Docfile mode
+// [iteration] -- iteration
+//
+// History: 22-Jan-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+void VerifyClean(SCODE sc, DWORD dwMode, LONG iteration)
+{
+ VerifyDisk(SUCCEEDED(sc) &&
+ !(dwMode & STGM_DELETEONRELEASE), iteration);
+ VerifyMemory(iteration);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: CreateWorkingDocfile
+//
+// Synopsis: create and verify the test Docfile
+//
+// Arguments: [dwMode] -- Docfile creation mode
+// [ppstg] -- placeholder for IStorage
+// [iteration] -- iteration number
+//
+// Returns: SCODE
+//
+// Modifies: ppstg
+//
+// History: 22-Jan-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+SCODE CreateWorkingDocfile(DWORD dwMode, IStorage **ppstg, LONG iteration)
+{
+ SCODE sc;
+
+ // Make sample call
+ remove("c:\\testfail.dfl");
+ sc = DfGetScode(StgCreateDocfile(
+ "c:\\testfail.dfl",
+ dwMode,
+ 0,
+ ppstg));
+
+ if (FAILED(sc))
+ {
+ if (iteration == 0)
+ {
+ // This was a prep call. Prep calls aren't supposed to fail
+ if (sc == STG_E_INVALIDFLAG)
+ {
+ // Probably a bad combination of mode flags
+ printf("..Iteration %ld, sc = STG_E_INVALIDFLAG (OK)\n",
+ iteration);
+ }
+ else if (FAILED(sc))
+ {
+ // Something unexpected
+ printf("..Iteration %ld failed - sc = 0x%lX\n",
+ iteration, sc);
+ }
+ }
+ else // iteration != 0
+ {
+ if (sc == STG_E_INSUFFICIENTMEMORY || sc == STG_E_MEDIUMFULL)
+ {
+ // we expected these failures; do nothing
+ ;
+ }
+ else
+ {
+ printf("..Iteration %ld failed - sc = 0x%lX (??)\n",
+ iteration, sc);
+ }
+ }
+ }
+
+ return(sc);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestStgCreate
+//
+// Purpose: Test StgCreateDocfile
+//
+// Interface: CTestCase
+//
+// History: 26-Jan-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestStgCreate : public CTestCase
+{
+private:
+ SCODE _sc;
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestStgCreate::Init(void)
+{
+ printf("SIFT StgCreateDocfile\n");
+ _mdf.Init();
+ return(TRUE);
+}
+
+SCODE CTestStgCreate::Prep(LONG iteration)
+{
+ // inherit this?
+ return(NOERROR);
+}
+
+SCODE CTestStgCreate::Call(LONG iteration)
+{
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX\n", _mdf.GetMode());
+
+ _sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, iteration);
+
+ return(_sc);
+}
+
+void CTestStgCreate::EndCall(LONG iteration)
+{
+ _pstg->Release();
+}
+
+void CTestStgCreate::CallVerify(LONG iteration)
+{
+ VerifyClean(_sc, _mdf.GetMode(), iteration);
+}
+
+void CTestStgCreate::EndPrep(LONG iteration)
+{
+ // inherit this?
+}
+
+void CTestStgCreate::EndVerify(LONG iteration)
+{
+ VerifyClean(_sc, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestStgCreate::Next(void)
+{
+ if (!_mdf.Next())
+ return FALSE;
+
+ return(TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestCreateStorage
+//
+// Purpose: Test IStorage::CreateStorage
+//
+// Interface: CTestCase
+//
+// History: 26-Jan-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestCreateStorage : public CTestCase
+{
+private:
+ SCODE _sc;
+
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+ CModeStg _mstg;
+ IStorage *_pstgChild;
+
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestCreateStorage::Init(void)
+{
+ printf("SIFT IStorage::CreateStorage\n");
+ _mdf.Init();
+ _mstg.Init();
+ return(TRUE);
+}
+
+SCODE CTestCreateStorage::Prep(LONG iteration)
+{
+ _sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ return(_sc);
+}
+
+SCODE CTestCreateStorage::Call(LONG iteration)
+{
+ SCODE sc;
+
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX, Child Storage Mode 0x%lX\n",
+ _mdf.GetMode(), _mstg.GetMode());
+
+ sc = DfGetScode(_pstg->CreateStorage(
+ "TestFail Storage",
+ _mstg.GetMode(),
+ 0,
+ 0,
+ &_pstgChild));
+
+ return(sc);
+}
+
+void CTestCreateStorage::EndCall(LONG iteration)
+{
+ _pstgChild->Release();
+}
+
+void CTestCreateStorage::CallVerify(LONG iteration)
+{
+}
+
+void CTestCreateStorage::EndPrep(LONG iteration)
+{
+ _pstg->Release();
+}
+
+void CTestCreateStorage::EndVerify(LONG iteration)
+{
+ VerifyClean(_sc, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestCreateStorage::Next(void)
+{
+ if (!_mstg.Next())
+ {
+ _mstg.Init();
+ if (!_mdf.Next())
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestCreateStream
+//
+// Purpose: Test IStorage::CreateStream
+//
+// Interface: CTestCase
+//
+// History: 26-Jan-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestCreateStream : public CTestCase
+{
+private:
+ SCODE _sc;
+
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+ CModeStm _mstm;
+ IStream *_pstmChild;
+
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestCreateStream::Init(void)
+{
+ printf("SIFT IStorage::CreateStream\n");
+ _mdf.Init();
+ _mstm.Init();
+ return(TRUE);
+}
+
+SCODE CTestCreateStream::Prep(LONG iteration)
+{
+ _sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ return(_sc);
+}
+
+SCODE CTestCreateStream::Call(LONG iteration)
+{
+ SCODE sc;
+
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX, Child Stream Mode 0x%lX\n",
+ _mdf.GetMode(), _mstm.GetMode());
+
+ sc = DfGetScode(_pstg->CreateStream(
+ "TestFail Stream",
+ _mstm.GetMode(),
+ 0,
+ 0,
+ &_pstmChild));
+
+ return(sc);
+}
+
+void CTestCreateStream::EndCall(LONG iteration)
+{
+ _pstmChild->Release();
+}
+
+void CTestCreateStream::CallVerify(LONG iteration)
+{
+}
+
+void CTestCreateStream::EndPrep(LONG iteration)
+{
+ _pstg->Release();
+}
+
+void CTestCreateStream::EndVerify(LONG iteration)
+{
+ VerifyClean(_sc, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestCreateStream::Next(void)
+{
+ if (!_mstm.Next())
+ {
+ _mstm.Init();
+ if (!_mdf.Next())
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestWrite
+//
+// Purpose: Test IStream::Write
+//
+// Interface: CTestCase
+//
+// History: 26-Jan-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestWrite : public CTestCase
+{
+private:
+ SCODE _sc;
+
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+ CModeStm _mstm;
+ IStream *_pstmChild;
+
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestWrite::Init(void)
+{
+ printf("SIFT IStream::Write\n");
+ _mdf.Init();
+ _mstm.Init();
+ return(TRUE);
+}
+
+SCODE CTestWrite::Prep(LONG iteration)
+{
+ _sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ if (SUCCEEDED(_sc))
+ {
+ _sc = DfGetScode(_pstg->CreateStream(
+ "TestFail Stream",
+ _mstm.GetMode(),
+ 0,
+ 0,
+ &_pstmChild));
+
+ if (FAILED(_sc))
+ _pstg->Release();
+ }
+ return(_sc);
+}
+
+SCODE CTestWrite::Call(LONG iteration)
+{
+ SCODE sc;
+ ULONG cb = 1;
+ char c = 'X';
+ ULONG cbWritten;
+
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX, Stream Mode 0x%lX, Write %ld bytes\n",
+ _mdf.GetMode(), _mstm.GetMode(), cb);
+
+ sc = DfGetScode(_pstmChild->Write(&c, cb, &cbWritten));
+
+ if (FAILED(sc))
+ {
+ if (sc != STG_E_MEDIUMFULL)
+ printf("..Iteration %ld - failed - sc = 0x%lX\n",
+ iteration, sc);
+ }
+ return(sc);
+}
+
+void CTestWrite::EndCall(LONG iteration)
+{
+}
+
+void CTestWrite::CallVerify(LONG iteration)
+{
+}
+
+void CTestWrite::EndPrep(LONG iteration)
+{
+ _pstmChild->Release();
+ _pstg->Release();
+}
+
+void CTestWrite::EndVerify(LONG iteration)
+{
+ VerifyClean(_sc, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestWrite::Next(void)
+{
+ if (!_mstm.Next())
+ {
+ _mstm.Init();
+ if (!_mdf.Next())
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestOpenStream
+//
+// Purpose: Test IStorage::OpenStream
+//
+// Interface: CTestCase
+//
+// History: 26-Jan-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestOpenStream : public CTestCase
+{
+private:
+ SCODE _sc;
+
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+ CModeStm _mstm;
+ IStream *_pstm;
+
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestOpenStream::Init(void)
+{
+ printf("SIFT IStorage::OpenStream\n");
+ _mdf.Init();
+ _mstm.Init();
+ return(TRUE);
+}
+
+SCODE CTestOpenStream::Prep(LONG iteration)
+{
+ _sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ if (SUCCEEDED(_sc))
+ {
+ _sc = DfGetScode(_pstg->CreateStream(
+ "TestFail Stream",
+ _mstm.GetMode(),
+ 0,
+ 0,
+ &_pstm));
+
+ if (FAILED(_sc))
+ _pstg->Release();
+ else
+ _pstm->Release();
+ }
+ return(_sc);
+}
+
+SCODE CTestOpenStream::Call(LONG iteration)
+{
+ SCODE sc;
+
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX, Stream Mode 0x%lX\n",
+ _mdf.GetMode(), _mstm.GetMode());
+
+ sc = DfGetScode(_pstg->OpenStream(
+ "TestFail Stream",
+ 0,
+ _mstm.GetMode(),
+ 0,
+ &_pstm));
+
+ return(sc);
+}
+
+void CTestOpenStream::EndCall(LONG iteration)
+{
+ _pstm->Release();
+}
+
+void CTestOpenStream::CallVerify(LONG iteration)
+{
+}
+
+void CTestOpenStream::EndPrep(LONG iteration)
+{
+ _pstg->Release();
+}
+
+void CTestOpenStream::EndVerify(LONG iteration)
+{
+ VerifyClean(_sc, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestOpenStream::Next(void)
+{
+ if (!_mstm.Next())
+ {
+ _mstm.Init();
+ if (!_mdf.Next())
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestOpenStorage
+//
+// Purpose: Test IStorage::OpenStorage
+//
+// Interface: CTestCase
+//
+// History: 26-Jan-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestOpenStorage : public CTestCase
+{
+private:
+ SCODE _sc;
+
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+ CModeStg _mstg;
+ IStorage *_pstgChild;
+
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestOpenStorage::Init(void)
+{
+ printf("SIFT IStorage::OpenStorage\n");
+ _mdf.Init();
+ _mstg.Init();
+ return(TRUE);
+}
+
+SCODE CTestOpenStorage::Prep(LONG iteration)
+{
+ _sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ if (SUCCEEDED(_sc))
+ {
+ _sc = DfGetScode(_pstg->CreateStorage(
+ "TestFail Storage",
+ _mstg.GetMode(),
+ 0,
+ 0,
+ &_pstgChild));
+
+ if (FAILED(_sc))
+ _pstg->Release();
+ else
+ _pstgChild->Release();
+ }
+ return(_sc);
+}
+
+SCODE CTestOpenStorage::Call(LONG iteration)
+{
+ SCODE sc;
+
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX, Storage Mode 0x%lX\n",
+ _mdf.GetMode(), _mstg.GetMode());
+
+ sc = DfGetScode(_pstg->OpenStorage("TestFail Storage", 0,
+ _mstg.GetMode(), 0, 0, &_pstgChild));
+
+ return(sc);
+}
+
+void CTestOpenStorage::EndCall(LONG iteration)
+{
+ _pstgChild->Release();
+}
+
+void CTestOpenStorage::CallVerify(LONG iteration)
+{
+}
+
+void CTestOpenStorage::EndPrep(LONG iteration)
+{
+ _pstg->Release();
+}
+
+void CTestOpenStorage::EndVerify(LONG iteration)
+{
+ VerifyClean(_sc, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestOpenStorage::Next(void)
+{
+ if (!_mstg.Next())
+ {
+ _mstg.Init();
+ if (!_mdf.Next())
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestCommit
+//
+// Purpose: Test IStream::Write
+//
+// Interface: CTestCase
+//
+// History: 26-Jan-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestCommit : public CTestCase
+{
+private:
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+ CModeStg _mstg;
+ IStorage *_pstgChild;
+
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestCommit::Init(void)
+{
+ printf("SIFT IStorage::Commit\n");
+ _mdf.Init();
+ _mstg.Init();
+ return(TRUE);
+}
+
+SCODE CTestCommit::Prep(LONG iteration)
+{
+ SCODE sc;
+
+ sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ if (SUCCEEDED(sc))
+ {
+ sc = DfGetScode(_pstg->CreateStorage(
+ "TestFail Storage",
+ _mstg.GetMode(),
+ 0,
+ 0,
+ &_pstgChild));
+
+ if (FAILED(sc))
+ _pstg->Release();
+ }
+ return(sc);
+}
+
+SCODE CTestCommit::Call(LONG iteration)
+{
+ SCODE sc;
+
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX, Storage Mode 0x%lX\n",
+ _mdf.GetMode(), _mstg.GetMode());
+
+ sc = DfGetScode(_pstgChild->Commit(0));
+
+ if (FAILED(sc))
+ {
+ if (sc != STG_E_MEDIUMFULL)
+ printf("..Iteration %ld - STG_E_MEDIUMFULL\n", iteration);
+ else
+ printf("..Iteration %ld - failed - sc = 0x%lX\n",
+ iteration, sc);
+ }
+ return(sc);
+}
+
+void CTestCommit::EndCall(LONG iteration)
+{
+}
+
+void CTestCommit::CallVerify(LONG iteration)
+{
+}
+
+void CTestCommit::EndPrep(LONG iteration)
+{
+ _pstgChild->Release();
+ _pstg->Release();
+}
+
+void CTestCommit::EndVerify(LONG iteration)
+{
+ VerifyClean(S_OK, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestCommit::Next(void)
+{
+ if (!_mstg.Next())
+ {
+ _mstg.Init();
+ if (!_mdf.Next())
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestCommit2
+//
+// Purpose: Test IStorage::Commit
+//
+// Interface: CTestCase
+//
+// History: 26-Jan-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestCommit2 : public CTestCase
+{
+private:
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+ CModeStg _mstg;
+ IStorage *_pstgChild;
+
+ IStream *_pstmChild;
+
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestCommit2::Init(void)
+{
+ printf("SIFT IStorage::Commit\n");
+ _mdf.Init();
+ _mstg.Init();
+ return(TRUE);
+}
+
+SCODE CTestCommit2::Prep(LONG iteration)
+{
+ SCODE sc;
+ ULONG cb = 1;
+ char c = 'X';
+ ULONG cbWritten;
+
+ sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ if (SUCCEEDED(sc))
+ {
+ sc = DfGetScode(_pstg->CreateStorage(
+ "TestFail Storage",
+ _mstg.GetMode(),
+ 0,
+ 0,
+ &_pstgChild));
+
+ if (FAILED(sc))
+ _pstg->Release();
+ else
+ {
+ sc = DfGetScode(_pstgChild->CreateStream(
+ "TestFail Stream",
+ STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ 0,
+ 0,
+ &_pstmChild));
+
+ if (FAILED(sc))
+ {
+ _pstgChild->Release();
+ _pstg->Release();
+ }
+ else
+ {
+ sc = DfGetScode(_pstmChild->Write(&c, cb, &cbWritten));
+ if (FAILED(sc))
+ {
+ _pstmChild->Release();
+ _pstgChild->Release();
+ _pstg->Release();
+ }
+ }
+ }
+ }
+ return(sc);
+}
+
+SCODE CTestCommit2::Call(LONG iteration)
+{
+ SCODE sc;
+
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX, Storage Mode 0x%lX\n",
+ _mdf.GetMode(), _mstg.GetMode());
+
+ sc = DfGetScode(_pstgChild->Commit(0));
+
+ if (FAILED(sc))
+ {
+ if (sc == STG_E_MEDIUMFULL)
+ printf("..Iteration %ld - STG_E_MEDIUMFULL\n", iteration);
+ else
+ printf("..Iteration %ld - failed - sc = 0x%lX\n",
+ iteration, sc);
+ }
+ return(sc);
+}
+
+void CTestCommit2::EndCall(LONG iteration)
+{
+}
+
+void CTestCommit2::CallVerify(LONG iteration)
+{
+}
+
+void CTestCommit2::EndPrep(LONG iteration)
+{
+ _pstmChild->Release();
+ _pstgChild->Release();
+ _pstg->Release();
+}
+
+void CTestCommit2::EndVerify(LONG iteration)
+{
+ VerifyClean(S_OK, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestCommit2::Next(void)
+{
+ if (!_mstg.Next())
+ {
+ _mstg.Init();
+ if (!_mdf.Next())
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestCommit3
+//
+// Purpose: Test IStorage::Commit
+//
+// Interface: CTestCase
+//
+// History: 26-Jan-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestCommit3 : public CTestCase
+{
+private:
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestCommit3::Init(void)
+{
+ printf("SIFT IStorage::Commit\n");
+ _mdf.Init();
+ return(TRUE);
+}
+
+SCODE CTestCommit3::Prep(LONG iteration)
+{
+ SCODE sc;
+ ULONG cb = 1;
+ char c = 'X';
+
+ sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+
+ if (FAILED(sc))
+ return(sc);
+
+ IStream *pstm;
+ sc = DfGetScode(_pstg->CreateStream(
+ "PP40",
+ STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ 0,
+ 0,
+ &pstm));
+ pstm->Release();
+
+ IStorage *pstgChild;
+ sc = DfGetScode(_pstg->CreateStorage(
+ "TestFail Storage",
+ STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ 0,
+ 0,
+ &pstgChild));
+
+ sc = DfGetScode(pstgChild->CreateStream(
+ "One",
+ STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ 0,
+ 0,
+ &pstm));
+ pstm->Release();
+ sc = DfGetScode(pstgChild->CreateStream(
+ "Two",
+ STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ 0,
+ 0,
+ &pstm));
+ pstm->Release();
+ sc = DfGetScode(pstgChild->CreateStream(
+ "Three",
+ STGM_DIRECT | STGM_SHARE_EXCLUSIVE | STGM_READWRITE,
+ 0,
+ 0,
+ &pstm));
+ pstm->Release();
+
+ sc = DfGetScode(pstgChild->Commit(0));
+ pstgChild->Release();
+
+ return(sc);
+}
+
+SCODE CTestCommit3::Call(LONG iteration)
+{
+ SCODE sc;
+
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX\n",
+ _mdf.GetMode());
+
+ sc = DfGetScode(_pstg->Commit(0));
+
+ if (FAILED(sc))
+ {
+ if (sc == STG_E_MEDIUMFULL)
+ printf("..Iteration %ld - STG_E_MEDIUMFULL\n", iteration);
+ else
+ printf("..Iteration %ld - failed - sc = 0x%lX\n",
+ iteration, sc);
+ }
+ return(sc);
+}
+
+void CTestCommit3::EndCall(LONG iteration)
+{
+}
+
+void CTestCommit3::CallVerify(LONG iteration)
+{
+}
+
+void CTestCommit3::EndPrep(LONG iteration)
+{
+ _pstg->Release();
+}
+
+void CTestCommit3::EndVerify(LONG iteration)
+{
+ VerifyClean(S_OK, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestCommit3::Next(void)
+{
+ if (!_mdf.Next())
+ return(FALSE);
+
+ return(TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestCommit4
+//
+// Purpose: Test IStorage::Commit with resized streams
+//
+// Interface: CTestCase
+//
+// History: 08-Sep-93 DrewB Created
+//
+//--------------------------------------------------------------------------
+
+class CTestCommit4 : public CTestCase
+{
+private:
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestCommit4::Init(void)
+{
+ printf("SIFT IStorage::Commit\n");
+ _mdf.Init();
+ return(TRUE);
+}
+
+#define LARGE_SIZE 4097
+#define SMALL_SIZE 4095
+
+SCODE CTestCommit4::Prep(LONG iteration)
+{
+ SCODE sc;
+ IStream *pstm;
+ ULARGE_INTEGER uli;
+
+ sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ if (FAILED(sc))
+ goto EH_Err;
+ sc = DfGetScode(_pstg->CreateStream("Test",
+ STGM_DIRECT | STGM_SHARE_EXCLUSIVE |
+ STGM_READWRITE, 0, 0, &pstm));
+ if (FAILED(sc))
+ goto EH_pstg;
+ uli.HighPart = 0;
+ uli.LowPart = LARGE_SIZE;
+ sc = DfGetScode(pstm->SetSize(uli));
+ if (FAILED(sc))
+ goto EH_pstm;
+ sc = DfGetScode(_pstg->Commit(0));
+ if (FAILED(sc))
+ goto EH_pstm;
+ uli.LowPart = SMALL_SIZE;
+ sc = DfGetScode(pstm->SetSize(uli));
+ if (FAILED(sc))
+ goto EH_pstm;
+ pstm->Release();
+ return sc;
+
+ EH_pstm:
+ pstm->Release();
+ EH_pstg:
+ _pstg->Release();
+ EH_Err:
+ return sc;
+}
+
+SCODE CTestCommit4::Call(LONG iteration)
+{
+ SCODE sc;
+
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX\n",
+ _mdf.GetMode());
+
+ sc = DfGetScode(_pstg->Commit(0));
+
+ if (FAILED(sc))
+ {
+ if (sc == STG_E_MEDIUMFULL)
+ printf("..Iteration %ld - STG_E_MEDIUMFULL\n", iteration);
+ else
+ printf("..Iteration %ld - failed - sc = 0x%lX\n",
+ iteration, sc);
+ }
+ return(sc);
+}
+
+void CTestCommit4::EndCall(LONG iteration)
+{
+}
+
+void CTestCommit4::CallVerify(LONG iteration)
+{
+ IStream *pstm;
+ SCODE sc;
+ STATSTG stat;
+
+ sc = DfGetScode(_pstg->OpenStream("Test", NULL, STGM_DIRECT |
+ STGM_SHARE_EXCLUSIVE, 0, &pstm));
+ if (FAILED(sc))
+ {
+ printf("Can't open stream - %lX\n", sc);
+ return;
+ }
+ sc = DfGetScode(pstm->Stat(&stat, STATFLAG_NONAME));
+ pstm->Release();
+ if (FAILED(sc))
+ {
+ printf("Can't stat stream - %lX\n", sc);
+ return;
+ }
+ if (stat.cbSize.LowPart != SMALL_SIZE)
+ {
+ printf("Stream length is %lu rather than %d\n",
+ stat.cbSize.LowPart, SMALL_SIZE);
+ return;
+ }
+}
+
+void CTestCommit4::EndPrep(LONG iteration)
+{
+ _pstg->Release();
+}
+
+void CTestCommit4::EndVerify(LONG iteration)
+{
+ VerifyClean(S_OK, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestCommit4::Next(void)
+{
+ if (!_mdf.Next())
+ return(FALSE);
+
+ return(TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestStgOpen
+//
+// Purpose: Test StgOpenStorage
+//
+// Interface: CTestCase
+//
+// History: 28-Jan-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestStgOpen : public CTestCase
+{
+private:
+ SCODE _sc;
+
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestStgOpen::Init(void)
+{
+ printf("SIFT StgOpenStorage\n");
+ _mdf.Init();
+ return(TRUE);
+}
+
+SCODE CTestStgOpen::Prep(LONG iteration)
+{
+ SCODE sc;
+ DWORD dwMode = STGM_DIRECT |
+ STGM_READWRITE |
+ STGM_SHARE_EXCLUSIVE |
+ STGM_FAILIFTHERE;
+ IStorage *pstg, *pstgChild;
+ IStream *pstmChild;
+
+ sc = CreateWorkingDocfile(dwMode, &pstg, 0);
+ if (SUCCEEDED(sc))
+ {
+ sc = DfGetScode(pstg->CreateStorage(
+ "TestFail Storage",
+ dwMode,
+ 0,
+ 0,
+ &pstgChild));
+
+ if (SUCCEEDED(sc))
+ {
+ sc = DfGetScode(pstgChild->CreateStream(
+ "TestFail Stream",
+ dwMode,
+ 0,
+ 0,
+ &pstmChild));
+
+ if (SUCCEEDED(sc))
+ pstmChild->Release();
+
+ pstgChild->Release();
+ }
+
+ pstg->Release();
+ }
+ return(sc);
+}
+
+SCODE CTestStgOpen::Call(LONG iteration)
+{
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX\n", _mdf.GetMode());
+
+ _sc = DfGetScode(StgOpenStorage("c:\\testfail.dfl",
+ NULL,
+ _mdf.GetMode(),
+ NULL,
+ 0,
+ &_pstg));
+
+ if (FAILED(_sc))
+ {
+ if (iteration == 0 && _sc == STG_E_INVALIDFLAG)
+ {
+ printf("..STG_E_INVALIDFLAG\n");
+ // Must have been a bad combination of flags - we
+ // ignore these for now.
+ }
+ else if (iteration > 0 && _sc == STG_E_INSUFFICIENTMEMORY)
+ {
+ // Do nothing (expected failure)
+ }
+ else if (iteration > 0 && _sc == STG_E_MEDIUMFULL)
+ {
+ // Do nothing (expected failure)
+ }
+ else
+ printf("..Iteration %ld, call failed - sc = 0x%lX\n",
+ iteration, _sc);
+ }
+ return(_sc);
+}
+
+void CTestStgOpen::EndCall(LONG iteration)
+{
+ _pstg->Release();
+}
+
+void CTestStgOpen::CallVerify(LONG iteration)
+{
+}
+
+void CTestStgOpen::EndPrep(LONG iteration)
+{
+}
+
+void CTestStgOpen::EndVerify(LONG iteration)
+{
+ // If the call failed, the file should still exist.
+ // If the call succeeded
+ // If mode was delete on release,
+ // file should not exist
+ // else file should exist
+
+ VerifyDisk((SUCCEEDED(_sc) && (!(_mdf.GetMode() & STGM_DELETEONRELEASE))) ||
+ FAILED(_sc), iteration);
+ VerifyMemory(iteration);
+}
+
+BOOL CTestStgOpen::Next(void)
+{
+ if (!_mdf.Next())
+ return(FALSE);
+
+ return(TRUE);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestWrite2
+//
+// Purpose: Test IStream::Write for largish writes
+//
+// Interface: CTestCase
+//
+// History: 16-Feb-93 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestWrite2 : public CTestCase
+{
+private:
+ SCODE _sc;
+
+ BYTE *_pb;
+
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+ CModeStm _mstm;
+ IStream *_pstmChild;
+
+ ULONG _cb;
+ ULONG _cBlock;
+
+ ULONG _cbSize;
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestWrite2::Init(void)
+{
+ printf("SIFT IStream::Write2 - large writes without Setsize\n");
+ _mdf.Init();
+ _mstm.Init();
+
+ _cb = 8192;
+ _cBlock = 8;
+
+ _pb = NULL;
+ return(TRUE);
+}
+
+SCODE CTestWrite2::Prep(LONG iteration)
+{
+
+ _pb = new BYTE[8192];
+ memset(_pb, 'X', 8192);
+
+ _sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ if (SUCCEEDED(_sc))
+ {
+ _sc = DfGetScode(_pstg->CreateStream(
+ "TestFail Stream",
+ _mstm.GetMode(),
+ 0,
+ 0,
+ &_pstmChild));
+
+ _cbSize = 0;
+ if (FAILED(_sc))
+ _pstg->Release();
+
+ }
+ return(_sc);
+}
+
+SCODE CTestWrite2::Call(LONG iteration)
+{
+ SCODE sc;
+ ULONG cbWritten;
+
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX, Stream Mode 0x%lX, Write %ld bytes\n",
+ _mdf.GetMode(), _mstm.GetMode(), _cb * _cBlock);
+
+ for (ULONG i = 0; i < _cBlock; i++)
+ {
+ sc = DfGetScode(_pstmChild->Write(_pb, _cb, &cbWritten));
+ _cbSize += cbWritten;
+
+ if (FAILED(sc))
+ {
+ if (sc != STG_E_MEDIUMFULL)
+ printf("..Iteration %ld, block %lu - failed - sc = 0x%lX\n",
+ iteration, i + 1, sc);
+ break;
+ }
+ }
+ return(sc);
+}
+
+void CTestWrite2::EndCall(LONG iteration)
+{
+ STATSTG stat;
+
+ _pstmChild->Stat(&stat, STATFLAG_NONAME);
+
+ if (ULIGetLow(stat.cbSize) != _cbSize)
+ {
+ printf("..Iteration %lu - Size of stream is %lu. Expected %lu\n",
+ iteration, ULIGetLow(stat.cbSize), _cbSize);
+ }
+}
+
+void CTestWrite2::CallVerify(LONG iteration)
+{
+ STATSTG stat;
+
+ _pstmChild->Stat(&stat, STATFLAG_NONAME);
+
+ if (ULIGetLow(stat.cbSize) != _cbSize)
+ {
+ printf("..Iteration %lu - Size of stream is %lu. Expected %lu\n",
+ iteration, ULIGetLow(stat.cbSize), _cbSize);
+ }
+
+}
+
+void CTestWrite2::EndPrep(LONG iteration)
+{
+ delete _pb;
+ _pb = NULL;
+
+ _pstmChild->Release();
+ _pstg->Release();
+}
+
+void CTestWrite2::EndVerify(LONG iteration)
+{
+ VerifyClean(_sc, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestWrite2::Next(void)
+{
+ if (!_mstm.Next())
+ {
+ _mstm.Init();
+ if (!_mdf.Next())
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestWrite3
+//
+// Purpose: Test IStream::Write for largish writes
+//
+// Interface: CTestCase
+//
+// History: 16-Feb-93 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestWrite3 : public CTestCase
+{
+private:
+ SCODE _sc;
+
+ BYTE *_pb;
+
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+ CModeStm _mstm;
+ IStream *_pstmChild;
+
+ ULONG _cb;
+ ULONG _cBlock;
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestWrite3::Init(void)
+{
+ printf("SIFT IStream::Write3 - large writes with prior Setsize\n");
+ _mdf.Init();
+ _mstm.Init();
+
+ _cb = 8192;
+ _cBlock = 8;
+
+ _pb = NULL;
+ return(TRUE);
+}
+
+SCODE CTestWrite3::Prep(LONG iteration)
+{
+
+ _pb = new BYTE[8192];
+ memset(_pb, 'X', 8192);
+
+ _sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ if (SUCCEEDED(_sc))
+ {
+ _sc = DfGetScode(_pstg->CreateStream(
+ "TestFail Stream",
+ _mstm.GetMode(),
+ 0,
+ 0,
+ &_pstmChild));
+
+ if (FAILED(_sc))
+ _pstg->Release();
+ else
+ {
+ ULARGE_INTEGER cbSize;
+
+ ULISet32(cbSize, _cb * _cBlock);
+
+ _sc = DfGetScode(_pstmChild->SetSize(cbSize));
+
+ if (FAILED(_sc))
+ {
+ _pstmChild->Release();
+ _pstg->Release();
+ }
+ }
+ }
+ return(_sc);
+}
+
+SCODE CTestWrite3::Call(LONG iteration)
+{
+ SCODE sc;
+ ULONG cbWritten;
+
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX, Stream Mode 0x%lX, Write %ld bytes\n",
+ _mdf.GetMode(), _mstm.GetMode(), _cb * _cBlock);
+ else
+ printf("ERROR - shouldn't hit iteration %lu\n", iteration);
+
+ for (ULONG i = 0; i < _cBlock; i++)
+ {
+ sc = DfGetScode(_pstmChild->Write(_pb, _cb, &cbWritten));
+ if (FAILED(sc))
+ {
+ if (sc != STG_E_MEDIUMFULL)
+ printf("..Iteration %ld, block %lu - failed - sc = 0x%lX\n",
+ iteration, i + 1, sc);
+ break;
+ }
+ }
+ return(sc);
+}
+
+void CTestWrite3::EndCall(LONG iteration)
+{
+}
+
+void CTestWrite3::CallVerify(LONG iteration)
+{
+}
+
+void CTestWrite3::EndPrep(LONG iteration)
+{
+ delete _pb;
+ _pb = NULL;
+
+ _pstmChild->Release();
+ _pstg->Release();
+}
+
+void CTestWrite3::EndVerify(LONG iteration)
+{
+ VerifyClean(_sc, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestWrite3::Next(void)
+{
+ if (!_mstm.Next())
+ {
+ _mstm.Init();
+ if (!_mdf.Next())
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestSetsize
+//
+// Purpose: Test IStream::Write for largish writes
+//
+// Interface: CTestCase
+//
+// History: 16-Feb-93 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestSetsize : public CTestCase
+{
+private:
+ SCODE _sc;
+
+ BYTE *_pb;
+
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+ CModeStm _mstm;
+ IStream *_pstmChild;
+
+ ULONG _cb;
+ ULONG _cBlock;
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestSetsize::Init(void)
+{
+ printf("SIFT IStream::Setsize\n");
+ _mdf.Init();
+ _mstm.Init();
+
+ _cb = 8192;
+ _cBlock = 9;
+
+ _pb = NULL;
+ return(TRUE);
+}
+
+SCODE CTestSetsize::Prep(LONG iteration)
+{
+
+ _pb = new BYTE[8192];
+ memset(_pb, 'X', 8192);
+
+ _sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ if (SUCCEEDED(_sc))
+ {
+ _sc = DfGetScode(_pstg->CreateStream(
+ "TestFail Stream",
+ _mstm.GetMode(),
+ 0,
+ 0,
+ &_pstmChild));
+
+ if (FAILED(_sc))
+ _pstg->Release();
+ }
+ return(_sc);
+}
+
+SCODE CTestSetsize::Call(LONG iteration)
+{
+ SCODE sc;
+ ULONG cbWritten;
+
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX, Stream Mode 0x%lX, Write %ld bytes\n",
+ _mdf.GetMode(), _mstm.GetMode(), _cb * _cBlock);
+
+ ULARGE_INTEGER cbSize;
+
+ ULISet32(cbSize, _cb * _cBlock);
+
+ sc = DfGetScode(_pstmChild->SetSize(cbSize));
+
+
+ if (FAILED(sc))
+ {
+ if (sc != STG_E_MEDIUMFULL)
+ printf("..Iteration %ld - failed - sc = 0x%lX\n", iteration, sc);
+ }
+ else
+ {
+ for (ULONG i = 0; i < _cBlock; i++)
+ {
+ sc = DfGetScode(_pstmChild->Write(_pb, _cb, &cbWritten));
+ if (FAILED(sc))
+ {
+ printf("..Iteration %ld, Write %lu failed - sc == 0x%lX\n",
+ iteration, i + 1, sc);
+ break;
+ }
+ }
+ }
+ return(sc);
+}
+
+void CTestSetsize::EndCall(LONG iteration)
+{
+ STATSTG stat;
+
+ _pstmChild->Stat(&stat, STATFLAG_NONAME);
+
+ if (ULIGetLow(stat.cbSize) != _cb * _cBlock)
+ {
+ printf("..Iteration %lu - Size of stream is %lu, expected %lu\n",
+ iteration, ULIGetLow(stat.cbSize), _cb * _cBlock);
+ }
+
+}
+
+void CTestSetsize::CallVerify(LONG iteration)
+{
+ STATSTG stat;
+
+ _pstmChild->Stat(&stat, STATFLAG_NONAME);
+
+ if (ULIGetLow(stat.cbSize) != 0)
+ {
+ printf("..Iteration %lu - Size of stream is %lu, expected 0\n",
+ iteration, ULIGetLow(stat.cbSize));
+ }
+}
+
+void CTestSetsize::EndPrep(LONG iteration)
+{
+ delete _pb;
+ _pb = NULL;
+
+ _pstmChild->Release();
+ _pstg->Release();
+}
+
+void CTestSetsize::EndVerify(LONG iteration)
+{
+ VerifyClean(_sc, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestSetsize::Next(void)
+{
+ if (!_mstm.Next())
+ {
+ _mstm.Init();
+ if (!_mdf.Next())
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestCreateStream2
+//
+// Purpose: Test IStorage::CreateStream2
+//
+// Interface: CTestCase
+//
+// History: 26-Jan-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestCreateStream2 : public CTestCase
+{
+private:
+ SCODE _sc;
+
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+ CModeStm _mstm;
+ IStream *_pstmChild;
+
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestCreateStream2::Init(void)
+{
+ printf("SIFT IStorage::CreateStream2\n");
+ _mdf.Init();
+ _mstm.Init();
+ return(TRUE);
+}
+
+SCODE CTestCreateStream2::Prep(LONG iteration)
+{
+ _sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ return(_sc);
+}
+
+SCODE CTestCreateStream2::Call(LONG iteration)
+{
+ SCODE sc;
+ ULONG cStream = 8;
+
+ char * pszName = "XTestFail Stream";
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX, Child Stream Mode 0x%lX\n",
+ _mdf.GetMode(), _mstm.GetMode());
+
+ for (ULONG i = 0; i < cStream; i++)
+ {
+ pszName[0] = ((char)i) + '0';
+
+ sc = DfGetScode(_pstg->CreateStream(
+ pszName,
+ _mstm.GetMode(),
+ 0,
+ 0,
+ &_pstmChild));
+
+ if (FAILED(sc))
+ {
+ if ((sc == STG_E_MEDIUMFULL) || (sc == STG_E_INSUFFICIENTMEMORY))
+ {
+ //Do nothing. We expected these.
+ }
+ else printf("..Iteration %ld, stream %lu - failed - sc = 0x%lX\n",
+ iteration, i + 1, sc);
+ break;
+ }
+ _pstmChild->Release();
+ }
+
+ return(sc);
+}
+
+void CTestCreateStream2::EndCall(LONG iteration)
+{
+}
+
+void CTestCreateStream2::CallVerify(LONG iteration)
+{
+}
+
+void CTestCreateStream2::EndPrep(LONG iteration)
+{
+ _pstg->Release();
+}
+
+void CTestCreateStream2::EndVerify(LONG iteration)
+{
+ VerifyClean(_sc, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestCreateStream2::Next(void)
+{
+ if (!_mstm.Next())
+ {
+ _mstm.Init();
+ if (!_mdf.Next())
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestDestroyElement
+//
+// Purpose: Test IStorage::DestroyElement
+//
+// Interface: CTestCase
+//
+// History: 26-Jan-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestDestroyElement : public CTestCase
+{
+private:
+ SCODE _sc;
+
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+ CModeStg _mstg;
+ IStorage *_pstgChild;
+
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestDestroyElement::Init(void)
+{
+ printf("SIFT IStorage::DestroyElement\n");
+ _mdf.Init();
+ _mstg.Init();
+ return(TRUE);
+}
+
+SCODE CTestDestroyElement::Prep(LONG iteration)
+{
+ _sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ if (SUCCEEDED(_sc))
+ {
+ _sc = DfGetScode(_pstg->CreateStorage(
+ "TestFail Storage",
+ _mstg.GetMode(),
+ 0,
+ 0,
+ &_pstgChild));
+
+ _pstgChild->Release();
+ }
+
+
+ return(_sc);
+}
+
+SCODE CTestDestroyElement::Call(LONG iteration)
+{
+ SCODE sc;
+
+ if (iteration == 0)
+ printf("Docfile Mode 0x%lX, Child Storage Mode 0x%lX\n",
+ _mdf.GetMode(), _mstg.GetMode());
+
+ sc = DfGetScode(_pstg->DestroyElement("TestFail Storage"));
+
+ if (FAILED(sc))
+ {
+ if ((sc == STG_E_MEDIUMFULL) || (sc == STG_E_INSUFFICIENTMEMORY))
+ {
+ //We expected these - do nothing.
+ }
+ else
+ printf("..Iteration %ld - failed - sc = 0x%lX\n",
+ iteration, sc);
+ }
+
+ return(sc);
+}
+
+void CTestDestroyElement::EndCall(LONG iteration)
+{
+ SCODE sc;
+
+ sc = DfGetScode(_pstg->OpenStorage(
+ "TestFail Storage",
+ 0,
+ _mstg.GetMode(),
+ 0,
+ 0,
+ &_pstgChild));
+
+ if (sc != STG_E_FILENOTFOUND)
+ {
+ printf("..Iteration %ld - open failed with 0x%lX, expected STG_E_FILENOTFOUND\n",
+ iteration,
+ sc);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ _pstgChild->Release();
+ }
+}
+
+void CTestDestroyElement::CallVerify(LONG iteration)
+{
+ SCODE sc;
+
+ sc = DfGetScode(_pstg->OpenStorage(
+ "TestFail Storage",
+ 0,
+ _mstg.GetMode(),
+ 0,
+ 0,
+ &_pstgChild));
+
+ if (FAILED(sc))
+ {
+ printf("..Iteration %ld - open failed with 0x%lX, expected success.\n",
+ iteration,
+ sc);
+ }
+ else
+ {
+ _pstgChild->Release();
+ }
+
+}
+
+void CTestDestroyElement::EndPrep(LONG iteration)
+{
+ _pstg->Release();
+}
+
+void CTestDestroyElement::EndVerify(LONG iteration)
+{
+ VerifyClean(_sc, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestDestroyElement::Next(void)
+{
+ if (!_mstg.Next())
+ {
+ _mstg.Init();
+ if (!_mdf.Next())
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestSetsize2
+//
+// Purpose: Test IStream::Write for largish writes
+//
+// Interface: CTestCase
+//
+// History: 16-Feb-93 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestSetsize2 : public CTestCase
+{
+private:
+ SCODE _sc;
+
+ BYTE *_pb;
+
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+ CModeStm _mstm;
+ IStream *_pstmChild;
+
+ ULONG _cb;
+ ULONG _cBlock;
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestSetsize2::Init(void)
+{
+ printf("SIFT IStream::Setsize2\n");
+ _mdf.Init();
+ _mstm.Init();
+
+ _cb = 8192;
+ _cBlock = 9;
+
+ _pb = NULL;
+ return(TRUE);
+}
+
+SCODE CTestSetsize2::Prep(LONG iteration)
+{
+
+ _pb = new BYTE[8192];
+ memset(_pb, 'X', 8192);
+
+ _sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ if (SUCCEEDED(_sc))
+ {
+ _sc = DfGetScode(_pstg->CreateStream(
+ "TestFail Stream",
+ _mstm.GetMode(),
+ 0,
+ 0,
+ &_pstmChild));
+
+ if (FAILED(_sc))
+ _pstg->Release();
+ else
+ {
+ ULARGE_INTEGER ulSize;
+ ULISet32(ulSize, _cb * _cBlock);
+
+ _sc = DfGetScode(_pstmChild->SetSize(ulSize));
+ if (FAILED(_sc))
+ printf("Setsize failed in Prep()\n");
+ else
+ {
+ for (ULONG i = 0; i < _cBlock; i++)
+ {
+ ULONG cbWritten;
+
+ _sc = DfGetScode(_pstmChild->Write(_pb, _cb, &cbWritten));
+ if (FAILED(_sc))
+ break;
+ }
+ }
+ }
+ }
+ return(_sc);
+}
+
+SCODE CTestSetsize2::Call(LONG iteration)
+{
+ SCODE sc;
+
+ ULARGE_INTEGER ulSize;
+ ULISet32(ulSize, 2048L);
+
+ sc = DfGetScode(_pstmChild->SetSize(ulSize));
+
+ return(sc);
+}
+
+void CTestSetsize2::EndCall(LONG iteration)
+{
+
+ STATSTG stat;
+
+ _pstmChild->Stat(&stat, STATFLAG_NONAME);
+
+ if (ULIGetLow(stat.cbSize) != 2048L)
+ {
+ printf("..Iteration %lu - Size of stream is %lu, expected %lu\n",
+ iteration, ULIGetLow(stat.cbSize), 2048L);
+ }
+
+ LARGE_INTEGER newPos;
+ ULISet32(newPos, 0);
+ ULARGE_INTEGER dummy;
+
+ _pstmChild->Seek(newPos, STREAM_SEEK_SET, &dummy);
+ ULONG cbRead;
+
+ _pstmChild->Read(_pb, 2048, &cbRead);
+ if (cbRead != 2048)
+ {
+ printf("Unknown error - read %lu bytes, expected 2048\n");
+ }
+ else
+ {
+ for (ULONG i = 0; i < 2048; i ++)
+ {
+ if (_pb[i] != 'X')
+ {
+ printf("Error in buffer data.\n");
+ break;
+ }
+ }
+ }
+
+}
+
+
+void CTestSetsize2::CallVerify(LONG iteration)
+{
+
+ STATSTG stat;
+
+ _pstmChild->Stat(&stat, STATFLAG_NONAME);
+
+ if (ULIGetLow(stat.cbSize) != _cb * _cBlock)
+ {
+ printf("..Iteration %lu - Size of stream is %lu, expected %lu\n",
+ iteration, ULIGetLow(stat.cbSize), _cb * _cBlock);
+ }
+ else
+ {
+ LARGE_INTEGER newPos;
+ ULISet32(newPos, 0);
+ ULARGE_INTEGER dummy;
+
+ _pstmChild->Seek(newPos, STREAM_SEEK_SET, &dummy);
+
+ for (ULONG i = 0; i < _cBlock; i++)
+ {
+ ULONG cbRead;
+
+ _sc = DfGetScode(_pstmChild->Read(_pb, _cb, &cbRead));
+ if (FAILED(_sc))
+ {
+ printf("Read failed with %lX\n", _sc);
+ break;
+ }
+ if (cbRead != _cb)
+ {
+ printf("Read %lu bytes, expected %lu\n",cbRead,_cb);
+ break;
+ }
+ for (ULONG j = 0; j < _cb; j++)
+ {
+ if (_pb[j] != 'X')
+ {
+ printf("Data mismatch at byte %lu, block %lu\n",j,i);
+ break;
+ }
+ }
+ }
+ }
+}
+
+void CTestSetsize2::EndPrep(LONG iteration)
+{
+ delete _pb;
+ _pb = NULL;
+
+ _pstmChild->Release();
+ _pstg->Release();
+}
+
+void CTestSetsize2::EndVerify(LONG iteration)
+{
+ VerifyClean(_sc, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestSetsize2::Next(void)
+{
+ if (!_mstm.Next())
+ {
+ _mstm.Init();
+ if (!_mdf.Next())
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Class: CTestSwitchToFile
+//
+// Purpose: Test SwitchToFile
+//
+// Interface: CTestCase
+//
+// History: 18-Jun-93 PhilipLa Created.
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+class CTestSwitchToFile : public CTestCase
+{
+private:
+ SCODE _sc;
+
+ CModeDf _mdf;
+ IStorage *_pstg;
+
+public:
+ virtual BOOL Init(void);
+ virtual SCODE Prep(LONG iteration);
+ virtual SCODE Call(LONG iteration);
+ virtual void EndCall(LONG iteration);
+ virtual void CallVerify(LONG iteration);
+ virtual void EndPrep(LONG iteration);
+ virtual void EndVerify(LONG iteration);
+ virtual BOOL Next(void);
+};
+
+BOOL CTestSwitchToFile::Init(void)
+{
+ printf("SIFT IStream::SwitchToFile\n");
+ _mdf.Init();
+ return(TRUE);
+}
+
+SCODE CTestSwitchToFile::Prep(LONG iteration)
+{
+ IStream *pstm;
+ _unlink("c:\\tmp\\stf.dfl");
+
+ _sc = CreateWorkingDocfile(_mdf.GetMode(), &_pstg, 0);
+ if (SUCCEEDED(_sc))
+ {
+ _sc = DfGetScode(_pstg->CreateStream(
+ "TestFail Stream",
+ STGM_DIRECT|STGM_READWRITE|STGM_SHARE_EXCLUSIVE,
+ 0,
+ 0,
+ &pstm));
+
+ if (FAILED(_sc))
+ _pstg->Release();
+ else
+ {
+ ULARGE_INTEGER ul;
+
+ ULISet32(ul, 80000);
+
+ _sc = DfGetScode(pstm->SetSize(ul));
+ pstm->Release();
+
+ if (FAILED(_sc))
+ {
+ _pstg->Release();
+ }
+ }
+ }
+ return(_sc);
+}
+
+SCODE CTestSwitchToFile::Call(LONG iteration)
+{
+ SCODE sc;
+ IRootStorage *pstgRoot;
+
+ sc = DfGetScode(_pstg->QueryInterface(
+ IID_IRootStorage,
+ (void **)&pstgRoot));
+
+ if (FAILED(sc))
+ return sc;
+
+ sc = DfGetScode(pstgRoot->SwitchToFile("c:\\tmp\\stf.dfl"));
+
+ pstgRoot->Release();
+
+ if (FAILED(sc))
+ return sc;
+
+
+ sc = DfGetScode(_pstg->Commit(STGC_OVERWRITE));
+
+ if (FAILED(sc))
+ {
+ printf("... Commit with overwrite failed.\n");
+ }
+ else
+ {
+ printf("... Commit succeeded.\n");
+ }
+
+ return(sc);
+}
+
+void CTestSwitchToFile::EndCall(LONG iteration)
+{
+}
+
+
+void CTestSwitchToFile::CallVerify(LONG iteration)
+{
+}
+
+void CTestSwitchToFile::EndPrep(LONG iteration)
+{
+ _pstg->Release();
+ _unlink("c:\\tmp\\stf.dfl");
+}
+
+void CTestSwitchToFile::EndVerify(LONG iteration)
+{
+ VerifyClean(_sc, _mdf.GetMode(), iteration);
+}
+
+BOOL CTestSwitchToFile::Next(void)
+{
+ do
+ {
+ if (!_mdf.Next())
+ return FALSE;
+ }
+ while (((_mdf.GetMode() & 0x70) == STGM_SHARE_DENY_READ) ||
+ (_mdf.GetMode() & 0x70) == STGM_SHARE_DENY_NONE);
+
+ return(TRUE);
+}
+
+
+//+-------------------------------------------------------------------------
+//
+// Function: TestCount, TestItem
+//
+// Synopsis:
+//
+// Effects:
+//
+// Arguments:
+//
+// Returns:
+//
+// History: 26-Jan-93 AlexT Created
+//
+// Notes:
+//
+//--------------------------------------------------------------------------
+
+CTestStgCreate tstStgCreate;
+CTestCreateStorage tstCreateStorage;
+CTestCreateStream tstCreateStream;
+CTestWrite tstWrite;
+CTestOpenStorage tstOpenStorage;
+CTestOpenStream tstOpenStream;
+CTestCommit tstCommit;
+CTestCommit2 tstCommit2;
+CTestStgOpen tstStgOpen;
+CTestWrite2 tstWrite2;
+CTestWrite3 tstWrite3;
+CTestSetsize tstSetsize;
+CTestSetsize2 tstSetsize2;
+CTestCreateStream2 tstCreateStream2;
+CTestDestroyElement tstDestroyElement;
+CTestSwitchToFile tstSwitchToFile;
+CTestCommit3 tstCommit3;
+CTestCommit4 tstCommit4;
+
+CTestCase *atst[] =
+{
+#if defined(BREADTHTEST)
+ &tstStgCreate,
+ &tstStgOpen,
+ &tstCreateStorage,
+ &tstCreateStream,
+ &tstWrite,
+ &tstCommit,
+ &tstCommit2,
+ &tstOpenStream,
+ &tstOpenStorage,
+ &tstWrite2,
+ &tstWrite3,
+ &tstSetsize,
+ &tstCreateStream2,
+ &tstDestroyElement,
+ &tstSetsize2,
+ &tstSwitchToFile,
+ &tstCommit3,
+#endif
+ &tstCommit4
+};
+
+int TestCount(void)
+{
+ return(sizeof(atst)/sizeof(CTestCase *));
+}
+
+CTestCase *TestItem(int iTest)
+{
+ return(atst[iTest]);
+}
diff --git a/private/ole32/stg/utils/fail/headers.cxx b/private/ole32/stg/utils/fail/headers.cxx
new file mode 100644
index 000000000..69efd1aff
--- /dev/null
+++ b/private/ole32/stg/utils/fail/headers.cxx
@@ -0,0 +1,28 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: headers.cxx
+//
+// Contents: Precompiled headers
+//
+// History: 21-Jan-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#if DBG != 1
+#error FAIL.EXE requires DBG == 1
+#endif
+
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <windows.h>
+#include <memory.h>
+#include <storage.h>
+
+#include <debnot.h>
+#include <dfdeb.hxx>
+#include <dfmsp.hxx>
diff --git a/private/ole32/stg/utils/fail/makefile b/private/ole32/stg/utils/fail/makefile
new file mode 100644
index 000000000..3ea8eda39
--- /dev/null
+++ b/private/ole32/stg/utils/fail/makefile
@@ -0,0 +1,27 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1992.
+# All rights reserved.
+#
+############################################################################
+
+default: all
+
+EXENAME = sift
+
+CXXFILES = .\fail.cxx \
+ .\supp.cxx
+
+# Precompiled headers debug info
+!if "$(PLATFORM)" != "MAC"
+CFLAGS=$(CFLAGS) -Yd
+!endif
+
+!if "$(PLATFORM)" != "MAC"
+PXXFILE = .\headers.cxx
+!endif
+
+!include $(OLE)\utils\util.mk
+!include $(COMMON)\src\win40.mk
+!include $(DEPENDFILE)
diff --git a/private/ole32/stg/utils/fail/sift.cxx b/private/ole32/stg/utils/fail/sift.cxx
new file mode 100644
index 000000000..cfb9f1676
--- /dev/null
+++ b/private/ole32/stg/utils/fail/sift.cxx
@@ -0,0 +1,143 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: SIFT.cxx
+//
+// Contents: Simulated Iterated Failure Testing Harness
+//
+// Functions: Sift
+//
+// History: 25-Jan-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+
+#pragma hdrstop
+
+#if DBG != 1
+#error FAIL.EXE requires DBG == 1
+#endif
+
+#include <sift.hxx>
+
+#define SET_DISPLAY_BUF_SIZE _wsetscreenbuf(_fileno(stdout), _WINBUFINF)
+
+void main (int argc, char *argv[])
+{
+ int i;
+ int cTests = TestCount();
+
+ SiftInit();
+
+ SET_DISPLAY_BUF_SIZE; //set QuickWin buffer size to infinite
+
+ printf("SIFT %d tests.\n", cTests);
+
+ for (i = 0; i < cTests; i++)
+ {
+ SiftDriver(TestItem(i));
+ }
+
+ // Be a good citizen and leave the Docfile clean
+ SetFailLimit(0L);
+
+ CoUninitialize();
+
+ printf("SIFT complete.\n");
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: Initialize
+//
+// Synopsis: Standard initialization
+//
+// History: 21-Jan-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+void SiftInit(void)
+{
+ SCODE sc;
+
+#if WIN32 == 300
+ if (FAILED(sc = DfGetScode(CoInitializeEx(NULL, COINIT_MULTITHREADED))))
+#else
+ if (FAILED(sc = DfGetScode(CoInitialize(NULL))))
+#endif
+ printf("SIFT: Unable to CoInitialize, sc = 0x%lX\n", sc);
+
+ DfDebug(0x00100101, 0x101);
+}
+
+void SiftDriver(CTestCase *ptc)
+{
+ SCODE sc;
+
+ if (!ptc->Init())
+ {
+ // Test's obligation to display failure message
+ return;
+ }
+
+ do
+ {
+ LONG iteration, lcf = 0;
+ for (iteration = 0; iteration <= lcf; iteration++)
+ {
+ SetFailLimit(0L);
+
+ sc = ptc->Prep(iteration);
+ if (FAILED(sc))
+ continue;
+
+ SetFailLimit(iteration);
+ sc = ptc->Call(iteration);
+
+ if (SUCCEEDED(sc))
+ {
+ if (iteration == 0)
+ {
+ lcf = DfGetResLimit(DBR_FAILCOUNT);
+ printf("%ld failure points\n", lcf);
+ }
+ else
+ {
+ // Shouldn't have succeeded
+ printf("..Iteration %ld succeeded!\n", iteration);
+ }
+ SetFailLimit(0L);
+ ptc->EndCall(iteration);
+ }
+ else
+ {
+ SetFailLimit(0L);
+ ptc->CallVerify(iteration);
+ }
+
+ ptc->EndPrep(iteration);
+ ptc->EndVerify(iteration);
+ }
+ } while (ptc->Next());
+}
+
+//+-------------------------------------------------------------------------
+//
+// Function: SetFailLimit
+//
+// Synopsis: clear count, set limit
+//
+// Arguments: [limit] -- failure limit
+//
+// History: 22-Jan-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+void SetFailLimit(LONG limit)
+{
+ DfSetResLimit(DBR_FAILCOUNT, 0);
+ DfSetResLimit(DBR_FAILLIMIT, limit);
+}
diff --git a/private/ole32/stg/utils/fail/sift.def b/private/ole32/stg/utils/fail/sift.def
new file mode 100644
index 000000000..97b2c0aa5
--- /dev/null
+++ b/private/ole32/stg/utils/fail/sift.def
@@ -0,0 +1,19 @@
+#ifndef FLAT
+EXETYPE WINDOWS
+//STUB 'WINSTUB.EXE'
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 16384
+STACKSIZE 8192
+#else
+EXETYPE NT
+SUBSYSTEM WINDOWSCHAR
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 16384
+STACKSIZE 8192
+#endif
diff --git a/private/ole32/stg/utils/fail/sift.hxx b/private/ole32/stg/utils/fail/sift.hxx
new file mode 100644
index 000000000..6c5988ca0
--- /dev/null
+++ b/private/ole32/stg/utils/fail/sift.hxx
@@ -0,0 +1,125 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: SIFT.hxx
+//
+// Contents: Simulated Iterated Failure Testing Header
+//
+// History: 25-Jan-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+class CTestCase
+{
+protected:
+ inline CTestCase(void) {}
+
+public:
+ virtual BOOL Init(void) = 0;
+ virtual SCODE Prep(LONG iteration) = 0;
+ virtual SCODE Call(LONG iteration) = 0;
+ virtual void EndCall(LONG iteration) = 0;
+ virtual void CallVerify(LONG iteration) = 0;
+ virtual void EndPrep(LONG iteration) = 0;
+ virtual void EndVerify(LONG iteration) = 0;
+ virtual BOOL Next(void) = 0;
+};
+
+/* Template
+
+BOOL CTestCase::Init(void)
+{
+
+}
+
+SCODE CTestCase::Prep(LONG iteration)
+{
+
+}
+
+SCODE CTestCase::Call(LONG iteration)
+{
+
+}
+
+void CTestCase::EndCall(LONG iteration)
+{
+
+}
+
+void CTestCase::CallVerify(LONG iteration)
+{
+
+}
+
+void CTestCase::EndPrep(LONG iteration)
+{
+
+}
+
+void CTestCase::EndVerify(LONG iteration)
+{
+
+}
+
+BOOL CTestCase::Next(void)
+{
+
+}
+
+*/
+
+// The following functions are provided by the individual test
+
+int TestCount(void);
+CTestCase *TestItem(int iTest);
+
+// The following are provided by sift.cxx
+
+void SiftInit(void);
+void SiftDriver(CTestCase *);
+void SetFailLimit(LONG limit);
+
+class CModeDf
+{
+private:
+ int _it, _ia, _is, _id, _ic; // Docfile mode component indices
+ DWORD _dwMode;
+
+ void CalcMode(void);
+
+public:
+ void Init(void);
+ DWORD GetMode(void) const {return _dwMode;}
+ BOOL Next(void);
+};
+
+class CModeStg
+{
+private:
+ int _it, _ia; // Storage mode component indices
+ DWORD _dwMode;
+
+ void CalcMode(void);
+
+public:
+ void Init(void);
+ DWORD GetMode(void) const {return _dwMode;}
+ BOOL Next(void);
+};
+
+class CModeStm
+{
+private:
+ int _ia; // Stream mode component indices
+ DWORD _dwMode;
+
+ void CalcMode(void);
+
+public:
+ void Init(void);
+ DWORD GetMode(void) const {return _dwMode;}
+ BOOL Next(void);
+};
diff --git a/private/ole32/stg/utils/fail/supp.cxx b/private/ole32/stg/utils/fail/supp.cxx
new file mode 100644
index 000000000..54bfc7a37
--- /dev/null
+++ b/private/ole32/stg/utils/fail/supp.cxx
@@ -0,0 +1,193 @@
+//+-------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1992.
+//
+// File: Supp.cxx
+//
+// Contents: Supplementary classes
+//
+// Classes: CModeDf - Docfile creation modes
+//
+// History: 25-Jan-93 AlexT Created
+//
+//--------------------------------------------------------------------------
+
+#include <headers.cxx>
+
+#pragma hdrstop
+
+#include <sift.hxx>
+
+#if DBG != 1
+#error FAIL.EXE requires DBG == 1
+#endif
+
+// #define DEPTHTEST // Uncomment out for depth testing (long time)
+
+//+-------------------------------------------------------------------------
+//
+// Notes: Mode combinations for StgCreateDocfile
+//
+//--------------------------------------------------------------------------
+
+DWORD adwTransactionModes[] = {
+ STGM_DIRECT,
+ STGM_TRANSACTED
+};
+
+#define TMODES (sizeof(adwTransactionModes) / sizeof(DWORD))
+
+DWORD adwAccessModes[] = {
+ STGM_READWRITE,
+ STGM_WRITE,
+ STGM_READ
+};
+
+#if defined(DEPTHTEST)
+# define AMODES (sizeof(adwAccessModes) / sizeof(DWORD))
+#else
+# define AMODES 1
+#endif
+
+DWORD adwShareModes[] = {
+ STGM_SHARE_DENY_NONE,
+ STGM_SHARE_EXCLUSIVE,
+ STGM_SHARE_DENY_READ,
+ STGM_SHARE_DENY_WRITE
+};
+
+#if defined(DEPTHTEST)
+# define SMODES (sizeof(adwShareModes) / sizeof(DWORD))
+#else
+# define SMODES 2
+#endif
+
+DWORD adwDeleteModes[] = {
+ 0,
+ STGM_DELETEONRELEASE
+};
+
+#if defined(DEPTHTEST)
+# define DMODES (sizeof(adwDeleteModes) / sizeof(DWORD))
+#else
+# define DMODES 1
+#endif
+
+DWORD adwCreateModes[] = {
+ STGM_FAILIFTHERE,
+ STGM_CREATE,
+ STGM_CONVERT
+};
+
+#if defined(DEPTHTEST)
+# define CMODES (sizeof(adwCreateModes) / sizeof(DWORD))
+#else
+# define CMODES 1
+#endif
+
+void CModeDf::Init(void)
+{
+ _it = _ia = _is = _id = _ic = 0;
+ CalcMode();
+}
+
+void CModeDf::CalcMode(void)
+{
+ _dwMode = adwTransactionModes[_it] |
+ adwAccessModes[_ia] |
+ adwShareModes[_is] |
+ adwDeleteModes[_id] |
+ adwCreateModes[_ic];
+}
+
+BOOL CModeDf::Next(void)
+{
+ BOOL f = TRUE;
+
+ if (++_ic >= CMODES)
+ {
+ _ic = 0;
+ if (++_id >= DMODES)
+ {
+ _id = 0;
+ if (++_is >= SMODES)
+ {
+ _is = 0;
+ if (++_ia >= AMODES)
+ {
+ _ia = 0;
+ if (++_it >= TMODES)
+ {
+ f = FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ if (f)
+ CalcMode();
+
+ return(f);
+}
+
+void CModeStg::Init(void)
+{
+ _it = _ia = 0;
+ CalcMode();
+}
+
+void CModeStg::CalcMode(void)
+{
+ _dwMode = adwTransactionModes[_it] |
+ adwAccessModes[_ia] |
+ STGM_SHARE_EXCLUSIVE;
+}
+
+BOOL CModeStg::Next(void)
+{
+ BOOL f = TRUE;
+
+ if (++_ia >= AMODES)
+ {
+ _ia = 0;
+ if (++_it >= TMODES)
+ {
+ f = FALSE;
+ }
+ }
+
+ if (f)
+ CalcMode();
+
+ return(f);
+}
+
+void CModeStm::Init(void)
+{
+ _ia = 0;
+ CalcMode();
+}
+
+void CModeStm::CalcMode(void)
+{
+ _dwMode = STGM_DIRECT |
+ adwAccessModes[_ia] |
+ STGM_SHARE_EXCLUSIVE;
+}
+
+BOOL CModeStm::Next(void)
+{
+ BOOL f = TRUE;
+
+ if (++_ia >= AMODES)
+ {
+ f = FALSE;
+ }
+
+ if (f)
+ CalcMode();
+
+ return(f);
+}
diff --git a/private/ole32/stg/utils/makefile b/private/ole32/stg/utils/makefile
new file mode 100644
index 000000000..bddca1260
--- /dev/null
+++ b/private/ole32/stg/utils/makefile
@@ -0,0 +1,21 @@
+#********************************************************************
+#** Microsoft Windows **
+#** Copyright(c) Microsoft Corp., 1992 - 1994 **
+#********************************************************************
+
+!ifdef NTMAKEENV
+
+all:
+ echo $(BUILDMSG)
+
+clean: all
+
+!else
+
+!if "$(HOST)" != "DOS"
+SUBDIRS = stgview df2t
+!endif
+
+!include $(COMMON)\src\win40.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/stg/utils/stgview/daytona/makefile b/private/ole32/stg/utils/stgview/daytona/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/ole32/stg/utils/stgview/daytona/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/ole32/stg/utils/stgview/daytona/sources b/private/ole32/stg/utils/stgview/daytona/sources
new file mode 100644
index 000000000..7eaafd157
--- /dev/null
+++ b/private/ole32/stg/utils/stgview/daytona/sources
@@ -0,0 +1,87 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ David Plummer (davepl) 19-Mar-94
+
+ Modifed by via awk to include global project include file
+ and to wrap precompiled header line within a conditional
+ that can be set in this include file.
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+MAJORCOMP= cairole
+MINORCOMP= stg
+
+#
+# This is the name of the target built from the source files specified
+# below. The name should include neither the path nor the file extension.
+#
+
+TARGETNAME= stgview
+
+#
+# This specifies where the target is to be built. A private target of
+# type LIBRARY or DYNLINK should go to obj, whereas a public target of
+# type LIBRARY or DYNLINK should go to $(BASEDIR)\public\sdk\lib.
+#
+
+TARGETPATH= obj
+
+#
+# This specifies the type of the target, such as PROGRAM, DYNLINK, LIBRARY,
+# etc.
+#
+
+TARGETTYPE= PROGRAM
+
+
+#
+# The following includes a global include file defined at the
+# base of the project for all components
+#
+
+!include ..\..\..\daytona.inc
+
+INCLUDES=..\..\..\h;..\..\..\ih;..\..\..\common\daytona;..\..\h;..
+
+
+C_DEFINES= \
+ $(C_DEFINES) \
+ -D_MT \
+ -D_DLL \
+
+SOURCES= \
+ ..\stgview.cxx
+
+UMTYPE= console
+UMAPPL=
+UMTEST=
+UMLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\compob32.lib\
+ $(BASEDIR)\public\sdk\lib\*\storag32.lib\
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib\
+ $(BASEDIR)\public\sdk\lib\*\user32.lib\
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib
+
+PRECOMPILED_INCLUDE=
+
+PRECOMPILED_OPTION=
+PRECOMPILED_TARGET=
+PRECOMPILED_CXX=
diff --git a/private/ole32/stg/utils/stgview/depend.mk1 b/private/ole32/stg/utils/stgview/depend.mk1
new file mode 100644
index 000000000..64081ca0b
--- /dev/null
+++ b/private/ole32/stg/utils/stgview/depend.mk1
@@ -0,0 +1,34 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\stgview.obj $(OBJDIR)\stgview.lst: .\stgview.cxx \
+ $(COMMON)\ih\Base32K.hxx $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\types.h $(COMMON)\ih\winnot.h \
+ $(CRTINC)\ctype.h $(CRTINC)\excpt.h $(CRTINC)\memory.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\stdio.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(CRTINC)\time.h $(OLE)\h\dfmem.hxx \
+ $(OLE)\h\dfmsp.hxx $(OLE)\h\dfname.hxx $(OLE)\h\ref.hxx \
+ $(OLE)\h\wchar.h $(OLE2H)\baseole.h $(OLE2H)\basetyps.h \
+ $(OLE2H)\cguid.h $(OLE2H)\cobjerr.h $(OLE2H)\dfsh.h \
+ $(OLE2H)\dispatch.h $(OLE2H)\disptype.h $(OLE2H)\dsbase.h \
+ $(OLE2H)\idltyps.h $(OLE2H)\itabls.h $(OLE2H)\ole2.h \
+ $(OLE2H)\oletyp.h $(OLE2H)\prspec.h $(OLE2H)\querys.h \
+ $(OLE2H)\scode.h $(OLE2H)\shtyps.h $(OLE2H)\stgprop.h \
+ $(OLE2H)\valid.h $(OLE2H)\varnt.h $(OLE2H)\winole.h $(OLE2H)\wtypes.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcndr.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnsip.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h
+
diff --git a/private/ole32/stg/utils/stgview/depend.mk9 b/private/ole32/stg/utils/stgview/depend.mk9
new file mode 100644
index 000000000..7f1bffc2c
--- /dev/null
+++ b/private/ole32/stg/utils/stgview/depend.mk9
@@ -0,0 +1,19 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\stgview.obj $(OBJDIR)\stgview.lst: .\stgview.cxx \
+ $(CAIROLE)\stg\h\dfmem.hxx $(CAIROLE)\stg\h\dfmsp.hxx \
+ $(CAIROLE)\stg\h\dfname.hxx $(CAIROLE)\stg\h\ref.hxx \
+ $(CAIROLE)\stg\h\wchar.h $(COMMON)\ih\dbgpoint.hxx \
+ $(COMMON)\ih\debnot.h $(COMMON)\ih\winnot.h $(CRTINC)\ctype.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdio.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(CRTINC)\time.h \
+ $(OLE2H)\coguid.h $(OLE2H)\compobj.h $(OLE2H)\initguid.h \
+ $(OLE2H)\scode.h $(OLE2H)\storage.h $(OLE2H)\valid.h \
+ $(OSINC)\windows.h
+
diff --git a/private/ole32/stg/utils/stgview/dirs b/private/ole32/stg/utils/stgview/dirs
new file mode 100644
index 000000000..4c50c7cc4
--- /dev/null
+++ b/private/ole32/stg/utils/stgview/dirs
@@ -0,0 +1,38 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+ \
+ daytona
diff --git a/private/ole32/stg/utils/stgview/makefile b/private/ole32/stg/utils/stgview/makefile
new file mode 100644
index 000000000..cbea271f1
--- /dev/null
+++ b/private/ole32/stg/utils/stgview/makefile
@@ -0,0 +1,21 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1994.
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+!include $(NTMAKEENV)\makefile.def
+!else
+
+default: all
+
+EXENAME = stgview
+
+!include $(CAIROLE)\stg\utils\util.mk
+!include $(COMMON)\src\win40.mk
+!include $(DEPENDFILE)
+
+!endif # NTMAKEENV
diff --git a/private/ole32/stg/utils/stgview/stgview.cxx b/private/ole32/stg/utils/stgview/stgview.cxx
new file mode 100644
index 000000000..bbbbe6e57
--- /dev/null
+++ b/private/ole32/stg/utils/stgview/stgview.cxx
@@ -0,0 +1,411 @@
+//+--------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: stgview.cxx
+//
+// Contents: Storage viewer utility
+//
+// History: 10-Dec-91 DrewB Created
+//
+//---------------------------------------------------------------
+
+#include <memory.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+#include <windows.h>
+#if WIN32 != 300
+#include <storage.h>
+#endif
+#include <wchar.h>
+#include <dfmsp.hxx>
+
+#define FLG_RECURSIVE 0x00000001
+#define FLG_STREAMS 0x00000002
+#define FLG_VERBOSE 0x00000004
+
+#define DFTOUCH
+
+#ifdef DFTOUCH
+#define CB_BUFFER 1024
+#else
+#define CB_BUFFER 16
+#endif
+BYTE abBuffer[CB_BUFFER];
+
+char *szTypes[] =
+{
+ "", "IStorage", "IStream", "ILockBytes"
+};
+
+void utMemFree(void *pv)
+{
+ IMalloc FAR* pMalloc;
+ if (SUCCEEDED(GetScode(CoGetMalloc(MEMCTX_TASK, &pMalloc))))
+ {
+ pMalloc->Free(pv);
+ pMalloc->Release();
+ }
+}
+
+void LevSpace(int iLevel)
+{
+ int i;
+
+ for (i = 0; i<iLevel; i++)
+ printf(" ");
+}
+
+void PrintStat(STATSTG *psstg, ULONG flOptions, int iLevel)
+{
+ LevSpace(iLevel);
+ if (flOptions & FLG_VERBOSE)
+ {
+#ifdef UNICODE
+ wprintf(L"%s:%hs =>\n", psstg->pwcsName, szTypes[psstg->type]);
+#else
+ printf("%s:%s =>\n", psstg->pwcsName, szTypes[psstg->type]);
+#endif
+
+#ifdef FLAT
+ SYSTEMTIME systime;
+ struct tm stime;
+
+ LevSpace(iLevel+1);
+ if (((psstg->ctime.dwHighDateTime != 0) ||
+ (psstg->ctime.dwLowDateTime != 0 )) &&
+ FileTimeToSystemTime(&psstg->ctime, &systime))
+ {
+ stime.tm_sec = systime.wSecond;
+ stime.tm_min = systime.wMinute;
+ stime.tm_hour = systime.wHour;
+ stime.tm_mday = systime.wDay;
+ stime.tm_mon = systime.wMonth - 1;
+ stime.tm_year = systime.wYear - 1900;
+ stime.tm_wday = systime.wDayOfWeek;
+ stime.tm_yday = 0;
+ stime.tm_isdst = 0;
+
+ printf("Created : %s", asctime(&stime));
+ }
+ else
+ printf("Created : %lx %lx (conversion unavailable)\n",
+ psstg->ctime.dwHighDateTime, psstg->ctime.dwLowDateTime);
+
+ LevSpace(iLevel+1);
+ if (((psstg->mtime.dwHighDateTime != 0) ||
+ (psstg->mtime.dwLowDateTime != 0 )) &&
+ FileTimeToSystemTime(&psstg->mtime, &systime))
+ {
+ stime.tm_sec = systime.wSecond;
+ stime.tm_min = systime.wMinute;
+ stime.tm_hour = systime.wHour;
+ stime.tm_mday = systime.wDay;
+ stime.tm_mon = systime.wMonth - 1;
+ stime.tm_year = systime.wYear - 1900;
+ stime.tm_wday = systime.wDayOfWeek;
+ stime.tm_yday = 0;
+ stime.tm_isdst = 0;
+
+ printf("Modified : %s", asctime(&stime));
+ }
+ else
+ printf("Modified : %lx %lx (conversion unavailable)\n",
+ psstg->ctime.dwHighDateTime, psstg->ctime.dwLowDateTime);
+
+ LevSpace(iLevel+1);
+ if (((psstg->atime.dwHighDateTime != 0) ||
+ (psstg->atime.dwLowDateTime != 0 )) &&
+ FileTimeToSystemTime(&psstg->mtime, &systime))
+ {
+ stime.tm_sec = systime.wSecond;
+ stime.tm_min = systime.wMinute;
+ stime.tm_hour = systime.wHour;
+ stime.tm_mday = systime.wDay;
+ stime.tm_mon = systime.wMonth - 1;
+ stime.tm_year = systime.wYear - 1900;
+ stime.tm_wday = systime.wDayOfWeek;
+ stime.tm_yday = 0;
+ stime.tm_isdst = 0;
+
+ printf("Accessed : %s", asctime(&stime));
+ }
+ else
+ printf("Accessed : %lx %lx (conversion unavailable)\n",
+ psstg->ctime.dwHighDateTime, psstg->ctime.dwLowDateTime);
+#else
+ LevSpace(iLevel+1);
+ printf("Created : %lx %lx (conversion unavailable)\n",
+ psstg->ctime.dwHighDateTime, psstg->ctime.dwLowDateTime);
+ LevSpace(iLevel+1);
+ printf("Modified : %lx %lx (conversion unavailable)\n",
+ psstg->mtime.dwHighDateTime, psstg->mtime.dwLowDateTime);
+ LevSpace(iLevel+1);
+ printf("Accessed : %lx %lx (conversion unavailable)\n",
+ psstg->atime.dwHighDateTime, psstg->atime.dwLowDateTime);
+#endif
+
+ if (psstg->type == STGTY_STREAM || psstg->type == STGTY_LOCKBYTES)
+ {
+ LevSpace(iLevel+1);
+ printf("Size: %lu:%lu\n", ULIGetHigh(psstg->cbSize),
+ ULIGetLow(psstg->cbSize));
+ }
+ }
+ else
+#ifdef UNICODE
+ wprintf(L"%s\n", psstg->pwcsName);
+#else
+ printf("%s\n", psstg->pwcsName);
+#endif
+}
+
+// ctype doesn't work properly
+#define dfisprint(c) ((c) >= ' ' && (c) < 127)
+
+void Stream(IStream *pstm, ULONG flOptions, int iLevel)
+{
+ ULONG cbRead;
+#ifdef DFTOUCH
+ ULONG cbTotal = 0;
+#endif
+ SCODE sc;
+
+ sc = GetScode(pstm->Read(abBuffer, CB_BUFFER, &cbRead));
+ while (SUCCEEDED(sc) && (cbRead > 0))
+ {
+ LevSpace(iLevel);
+#ifdef DFTOUCH
+ cbTotal += cbRead;
+ printf("Read %lu bytes\n", cbTotal);
+#else
+ for (ULONG ib = 0; ib < cbRead; ib++)
+ {
+ printf("%.2X", (int)abBuffer[ib]);
+ }
+ for (ib = ib; ib < CB_BUFFER + 1; ib++)
+ {
+ printf(" ");
+ }
+
+ for (ib = 0; ib < cbRead; ib++)
+ {
+ printf("%c", dfisprint(abBuffer[ib]) ? abBuffer[ib] : '.');
+ }
+ printf("\n");
+#endif
+
+ sc = GetScode(pstm->Read(abBuffer, CB_BUFFER, &cbRead));
+ }
+ if (FAILED(sc))
+ printf("Read failed with 0x%lX\n", sc);
+}
+
+void Contents(IStorage *pdf, ULONG flOptions, int iLevel)
+{
+ IEnumSTATSTG *pdfi;
+ SCODE sc;
+ IStorage *pdfChild;
+ IStream *pstmChild;
+ STATSTG sstg;
+
+ if (FAILED(pdf->EnumElements(0, NULL, 0, &pdfi)))
+ {
+ fprintf(stderr, "Unable to create iterator\n");
+ return;
+ }
+ for (;;)
+ {
+ sc = GetScode(pdfi->Next(1, &sstg, NULL));
+ if (sc != S_OK)
+ break;
+ PrintStat(&sstg, flOptions, iLevel);
+ if ((sstg.type == STGTY_STORAGE) && (flOptions & FLG_RECURSIVE))
+ {
+ if (SUCCEEDED(pdf->OpenStorage(sstg.pwcsName, NULL,
+ STGM_READ | STGM_SHARE_EXCLUSIVE,
+ NULL, 0, &pdfChild)))
+ {
+ Contents(pdfChild, flOptions, iLevel+1);
+ pdfChild->Release();
+ }
+ else
+ fprintf(stderr, "%s: Unable to recurse\n", sstg.pwcsName);
+ }
+ else
+ if ((sstg.type == STGTY_STREAM) && (flOptions & FLG_STREAMS))
+ {
+ if (SUCCEEDED(pdf->OpenStream(sstg.pwcsName, NULL,
+ STGM_READ | STGM_SHARE_EXCLUSIVE,
+ 0, &pstmChild)))
+ {
+ Stream(pstmChild, flOptions, iLevel+1);
+ pstmChild->Release();
+ }
+ else
+ fprintf(stderr, "%s: Unable to open\n", sstg.pwcsName);
+ }
+ utMemFree(sstg.pwcsName);
+ }
+ pdfi->Release();
+ if (FAILED(sc))
+ printf("Enumeration failed with 0x%lX\n", sc);
+}
+
+void Descend(IStorage *pdf, char *pszPath, IStorage **ppdf)
+{
+ IStorage *pdfNext;
+ char *pszNext = pszPath;
+ char *pszEnd = strchr(pszNext, '\\');
+ TCHAR atcName[CWCSTORAGENAME];
+
+ while (pszNext != NULL)
+ {
+ if (pszEnd != NULL)
+ {
+ *pszEnd = '\0';
+ }
+
+#ifdef UNICODE
+ if (mbstowcs(atcName, pszNext, CWCSTORAGENAME) == (size_t)-1)
+ {
+ pdf = NULL;
+
+ fprintf(stderr, "Unable to convert '%s' to Unicode\n", pszNext);
+ break;
+ }
+#else
+ strcpy(atcName, pszNext);
+#endif
+ if (SUCCEEDED(pdf->OpenStorage(atcName, NULL,
+ STGM_READ | STGM_SHARE_EXCLUSIVE,
+ NULL, 0, &pdfNext)))
+ {
+ pdf = pdfNext;
+
+ if (pszEnd != NULL)
+ {
+ *pszEnd = '\\';
+
+ pszNext = pszEnd + 1;
+ pszEnd = strchr(pszNext, '\\');
+ }
+ else
+ {
+ pszNext = NULL;
+ }
+ }
+ else
+ {
+ pdf = NULL;
+
+ fprintf(stderr, "Unable to open '%s' in docfile\n", pszPath);
+ break;
+ }
+ }
+
+ *ppdf = pdf;
+}
+
+void _CRTAPI1 main(int argc, char **argv)
+{
+ ULONG flOptions = 0;
+ IStorage *pdf;
+ IStorage *pdfRoot;
+ STATSTG sstg;
+
+ argc--;
+ argv++;
+ while ((argc > 0) && ((*argv)[0] == '-'))
+ {
+ for (int ich = 1; (*argv)[ich] != '\0'; ich++)
+ {
+ switch((*argv)[ich])
+ {
+ case 's':
+ flOptions |= FLG_STREAMS;
+ break;
+ case 'v':
+ flOptions |= FLG_VERBOSE;
+ break;
+ case 'r':
+ flOptions |= FLG_RECURSIVE;
+ break;
+ default:
+ fprintf(stderr, "Unknown switch '%c'\n", (*argv)[ich]);
+ break;
+ }
+ }
+
+ argc--;
+ argv++;
+ }
+
+ if ((argc != 1) && (argc != 2))
+ {
+ printf("Usage: stgview [-v] [-s] [-r] docfile [path]\n");
+ exit(1);
+ }
+
+ SCODE sc;
+
+#if WIN32 == 300
+ if (FAILED(sc = GetScode(CoInitializeEx(NULL, COINIT_MULTITHREADED))))
+#else
+ if (FAILED(sc = GetScode(CoInitialize(NULL))))
+#endif
+ {
+ fprintf(stderr, "CoInitialize failed with sc = %lx\n", sc);
+ exit(1);
+ }
+
+ TCHAR atcName[_MAX_PATH];
+#ifdef UNICODE
+ if (mbstowcs(atcName, *argv, _MAX_PATH) == (size_t)-1)
+ {
+ fprintf(stderr, "Unable to convert '%s' to Unicode\n", *argv);
+ exit(1);
+ }
+#else
+ strcpy(atcName, *argv);
+#endif
+ if (FAILED(StgOpenStorage(atcName, NULL, STGM_READ | STGM_SHARE_DENY_WRITE,
+ NULL, 0, &pdf)))
+ {
+ fprintf(stderr, "Unable to open '%s'\n", *argv);
+ exit(1);
+ }
+ else
+ {
+ if (argc == 2)
+ {
+ Descend(pdf, *(argv + 1), &pdfRoot);
+ }
+ else
+ {
+ pdf->AddRef();
+ pdfRoot = pdf;
+ }
+
+ if (pdfRoot != NULL)
+ {
+ if (FAILED(pdfRoot->Stat(&sstg, 0)))
+ fprintf(stderr, "Unable to stat root\n");
+ else
+ {
+ PrintStat(&sstg, flOptions, 0);
+ utMemFree(sstg.pwcsName);
+ }
+ Contents(pdfRoot, flOptions, 1);
+ pdfRoot->Release();
+ }
+ pdf->Release();
+ }
+
+ CoUninitialize();
+}
diff --git a/private/ole32/stg/utils/stgview/stgview.def b/private/ole32/stg/utils/stgview/stgview.def
new file mode 100644
index 000000000..f6828e0e5
--- /dev/null
+++ b/private/ole32/stg/utils/stgview/stgview.def
@@ -0,0 +1,21 @@
+NAME STGVIEW
+#ifndef FLAT
+EXETYPE WINDOWS
+//STUB 'WINSTUB.EXE'
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 16384
+STACKSIZE 8192
+#else
+EXETYPE NT
+SUBSYSTEM WINDOWSCHAR
+
+CODE MOVABLE
+DATA MULTIPLE MOVABLE
+
+HEAPSIZE 16384
+STACKSIZE 8192
+#endif
+
diff --git a/private/ole32/stg/utils/util.mk b/private/ole32/stg/utils/util.mk
new file mode 100644
index 000000000..3053400fe
--- /dev/null
+++ b/private/ole32/stg/utils/util.mk
@@ -0,0 +1,80 @@
+############################################################################
+#
+# Copyright (C) 1992, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+#
+# Set up include directories and roots for includes.exe
+#
+
+CINC = -I$(OLE2H) $(CINC) -I$(CAIROLE)\stg\h
+INCLUDES_ROOTS = -P$$(OLE2H)=$(OLE2H) -P$$(CAIROLE)=$(CAIROLE)
+
+#
+# Default OLE2 paths
+#
+
+!include $(CAIROLE)\stg\setole2.mk
+
+#
+# Defining NO_WINMAIN suppresses linking with astartw.obj
+#
+
+NO_WINMAIN = 1
+
+#
+# Copy built exes to this directory
+#
+
+!ifdef OLETARGET
+EXECOPY = $(OLETARGET)\$(ODL)$(TGTDIR)
+!endif
+
+#
+# Define libraries
+#
+
+!if "$(PLATFORM)" == "i286"
+DFLIB = $(CAIROLE)\stg\$(OBJDIR)\storage.lib
+!else
+DFLIB = $(CAIROLE)\stg\$(OBJDIR)\storag32.lib
+!endif
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = $(EXENAME).exe
+RELEASE =
+
+#
+# C compiler flags
+#
+
+CFLAGS = $(CFLAGS) -DUL64
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES = \
+ .\$(EXENAME).cxx\
+ $(CXXFILES)
+
+#
+# Libraries and other object files to link.
+#
+
+!include $(CAIROLE)\stg\dflibs.mk
+
+LIBS = $(LIBS) $(DFLIB) $(RTLIBEXEQ)
+
+#
+# Set MULTIDEPEND to support multiple build targets
+#
+
+MULTIDEPEND = MERGED
diff --git a/private/ole32/stg/wclib/depend.mk b/private/ole32/stg/wclib/depend.mk
new file mode 100644
index 000000000..e25a09706
--- /dev/null
+++ b/private/ole32/stg/wclib/depend.mk
@@ -0,0 +1,32 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\wcschr.obj $(OBJDIR)\wcschr.lst: .\wcschr.c \
+ $(CAIROLE)\STG\wclib\wcstr.h $(CRTINC)\stddef.h $(CRTINC)\stdlib.h
+
+$(OBJDIR)\wcscpy.obj $(OBJDIR)\wcscpy.lst: .\wcscpy.c \
+ $(CAIROLE)\STG\wclib\wcstr.h $(CRTINC)\stdlib.h
+
+$(OBJDIR)\wcscmp.obj $(OBJDIR)\wcscmp.lst: .\wcscmp.c \
+ $(CAIROLE)\STG\wclib\wcstr.h $(CRTINC)\stdlib.h
+
+$(OBJDIR)\wcslen.obj $(OBJDIR)\wcslen.lst: .\wcslen.c \
+ $(CAIROLE)\STG\wclib\wcstr.h $(CRTINC)\stdlib.h
+
+$(OBJDIR)\wcsicmp.obj $(OBJDIR)\wcsicmp.lst: .\wcsicmp.c \
+ $(CAIROLE)\STG\wclib\wcstr.h $(CRTINC)\stdlib.h
+
+$(OBJDIR)\wcsncmp.obj $(OBJDIR)\wcsncmp.lst: .\wcsncmp.c \
+ $(CAIROLE)\STG\wclib\wcstr.h $(CRTINC)\stdlib.h
+
+$(OBJDIR)\wcsnicmp.obj $(OBJDIR)\wcsnicmp.lst: .\wcsnicmp.c \
+ $(CAIROLE)\STG\wclib\wcstr.h $(CRTINC)\stdlib.h
+
+$(OBJDIR)\wcsrchr.obj $(OBJDIR)\wcsrchr.lst: .\wcsrchr.c \
+ $(CAIROLE)\STG\wclib\wcstr.h $(CRTINC)\stddef.h $(CRTINC)\stdlib.h
+
diff --git a/private/ole32/stg/wclib/dirs b/private/ole32/stg/wclib/dirs
new file mode 100644
index 000000000..283264bb9
--- /dev/null
+++ b/private/ole32/stg/wclib/dirs
@@ -0,0 +1,36 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+
diff --git a/private/ole32/stg/wclib/filelist.mk b/private/ole32/stg/wclib/filelist.mk
new file mode 100644
index 000000000..2de1eb2f8
--- /dev/null
+++ b/private/ole32/stg/wclib/filelist.mk
@@ -0,0 +1,34 @@
+############################################################################
+#
+# Copyright (C) 1992-1993, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+
+# Only used for non-NT builds since NT has WCHAR support in the CRT
+!if "$(OPSYS)" == "NT" || "$(OPSYS)" == "NT1X"
+!error $(OLE)\wclib used for NT
+!endif
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = wclib.lib
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CXXFILES =
+CFILES = .\wcschr.c \
+ .\wcscpy.c \
+ .\wcscmp.c \
+ .\wcslen.c \
+ .\wcsncmp.c \
+ .\wcsicmp.c \
+ .\wcsnicmp.c \
+ .\wcsrchr.c
diff --git a/private/ole32/stg/wclib/makefile b/private/ole32/stg/wclib/makefile
new file mode 100644
index 000000000..00ab1a16a
--- /dev/null
+++ b/private/ole32/stg/wclib/makefile
@@ -0,0 +1,23 @@
+############################################################################
+#
+# Copyright (C) 1992-1994, Microsoft Corporation.
+#
+# All rights reserved.
+#
+############################################################################
+
+!ifdef NTMAKEENV
+
+all:
+ echo $(BUILDMSG)
+
+clean: all
+
+!else
+
+default: all
+!include filelist.mk
+!include $(COMMON)\src\win40.mk
+!include depend.mk
+
+!endif # NTMAKEENV
diff --git a/private/ole32/stg/wclib/wcschr.c b/private/ole32/stg/wclib/wcschr.c
new file mode 100644
index 000000000..c7e94966e
--- /dev/null
+++ b/private/ole32/stg/wclib/wcschr.c
@@ -0,0 +1,44 @@
+/***
+*wcschr.c - search a wide character string for a given wide character
+*
+* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcschr() - search a wide character string for a wide character
+*
+*Revision History:
+* 04-07-91 IanJa C version created.
+*
+*******************************************************************************/
+
+#include <stddef.h>
+#include <stdlib.h>
+
+/***
+*char *wcschr(string, c) - search a wide character string for a wide character
+*
+*Purpose:
+* Searches a wide character string for a given wide character, which may
+* be the null character L'\0'.
+*
+*Entry:
+* wchar_t *string - string to search in
+* wchar_t c - character to search for
+*
+*Exit:
+* returns pointer to the first occurence of c in string
+* returns NULL if c does not occur in string
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+wchar_t * _CRTAPI1 wcschr(const wchar_t * string, wchar_t ch)
+{
+ while (*string && *string != ch)
+ string++;
+
+ if (*string == ch)
+ return (wchar_t *)string;
+ return NULL;
+}
diff --git a/private/ole32/stg/wclib/wcscmp.c b/private/ole32/stg/wclib/wcscmp.c
new file mode 100644
index 000000000..f4c796912
--- /dev/null
+++ b/private/ole32/stg/wclib/wcscmp.c
@@ -0,0 +1,54 @@
+/***
+*wcscmp.c - routine to compare 2 wide character strings (equal/less/greater)
+*
+* Copyright (c) 1985-1988, Microsoft Corporation. All Rights Reserved.
+*
+*Purpose:
+* Compares two wide character strings, determining their lexical order.
+*
+*Revision History:
+* 04-07-91 IanJa C version created.
+*
+*******************************************************************************/
+
+#include <stdlib.h>
+
+/***
+*wcscmp - compare two wide character strings, returning less than, equal to,
+* or greater than
+*
+*Purpose:
+* WCSCMP compares two wide character strings and returns an integer
+* to indicate whether the first is less than the second, the two are
+* equal, or whether the first is greater than the second.
+*
+* Comparison is done byte by byte on an UNSIGNED basis, which is to
+* say that Null (0) is less than any other character (1-0xffff).
+*
+*Entry:
+* const wchar_t * src - string for left-hand side of comparison
+* const wchar_t * dst - string for right-hand side of comparison
+*
+*Exit:
+* returns -1 if src < dst
+* returns 0 if src == dst
+* returns +1 if src > dst
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 wcscmp(const wchar_t * src, const wchar_t * dst)
+{
+ int ret = 0 ;
+
+ while( ! (ret = *src - *dst) && *dst)
+ ++src, ++dst;
+
+ if ( ret < 0 )
+ ret = -1 ;
+ else if ( ret > 0 )
+ ret = 1 ;
+
+ return ret;
+}
diff --git a/private/ole32/stg/wclib/wcscpy.c b/private/ole32/stg/wclib/wcscpy.c
new file mode 100644
index 000000000..91424e62d
--- /dev/null
+++ b/private/ole32/stg/wclib/wcscpy.c
@@ -0,0 +1,41 @@
+/***
+*wcscpy.c - contains wcscpy()
+*
+* Copyright (c) 1985-1988, Microsoft Corporation. All Rights Reserved.
+*
+*Purpose:
+* wcscpy() copies one wide character string onto another.
+*
+*Revision History:
+* 04-07-91 IanJa C version created.
+*
+*******************************************************************************/
+
+#include <stdlib.h>
+
+/***
+*wchar_t *wcscpy(dst, src) - copy one wide character string over another
+*
+*Purpose:
+* Copies the wide character string src into the spot specified by
+* dest; assumes enough room.
+*
+*Entry:
+* wchar_t * dst - wide character string over which "src" is to be copied
+* const wchar_t * src - string to be copied over "dst"
+*
+*Exit:
+* The address of "dst"
+*
+*Exceptions:
+*******************************************************************************/
+
+wchar_t * _CRTAPI1 wcscpy(wchar_t * dst, const wchar_t * src)
+{
+ wchar_t * cp = dst;
+
+ while( *cp++ = *src++ )
+ ; /* Copy src over dst */
+
+ return dst;
+}
diff --git a/private/ole32/stg/wclib/wcsicmp.c b/private/ole32/stg/wclib/wcsicmp.c
new file mode 100644
index 000000000..157263aca
--- /dev/null
+++ b/private/ole32/stg/wclib/wcsicmp.c
@@ -0,0 +1,77 @@
+/***
+*wcsicmp.c - compares two wide character strings with case insensitivity
+*
+* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsicmp() - compares two wide character strings for lexical
+* order with case insensitivity.
+*
+*Revision History:
+* 11-Mar-92 CarlH Created.
+*
+*******************************************************************************/
+
+
+#include <stdlib.h>
+
+
+/***
+*wchar_t wcUp(wc) - upper case wide character
+*
+*Notes:
+* This was copied from AlexT's version of wcsnicmp.c from the Win4
+* common project.
+*/
+
+static wchar_t wcUp(wchar_t wc)
+{
+ if ('a' <= wc && wc <= 'z')
+ wc += (wchar_t)('A' - 'a');
+
+ return(wc);
+}
+
+
+/***
+*wcsicmp - compare two wide character strings with case insensitivity,
+* returning less than, equal to, or greater than
+*
+*Purpose:
+* WCSICMP compares two wide character strings with case insensitivity
+* and returns an integer to indicate whether the first is less than
+* the second, the two are equal, or whether the first is greater than
+* the second.
+*
+* Comparison is done byte by byte on an UNSIGNED basis with lower to
+* upper case mapping by wcUp. Null (0) is less than any other
+* character (1-0xffff).
+*
+*Entry:
+* const wchar_t * src - string for left-hand side of comparison
+* const wchar_t * dst - string for right-hand side of comparison
+*
+*Exit:
+* returns -1 if src < dst
+* returns 0 if src == dst
+* returns +1 if src > dst
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 wcsicmp(const wchar_t * src, const wchar_t * dst)
+{
+ int ret = 0 ;
+
+ while( ! (ret = wcUp(*src) - wcUp(*dst)) && *dst)
+ ++src, ++dst;
+
+ if ( ret < 0 )
+ ret = -1 ;
+ else if ( ret > 0 )
+ ret = 1 ;
+
+ return ret;
+}
+
diff --git a/private/ole32/stg/wclib/wcslen.c b/private/ole32/stg/wclib/wcslen.c
new file mode 100644
index 000000000..beaac2091
--- /dev/null
+++ b/private/ole32/stg/wclib/wcslen.c
@@ -0,0 +1,42 @@
+/***
+*wcslen.c - contains wcslen() routine
+*
+* Copyright (c) 1985-1988, Microsoft Corporation. All Rights Reserved.
+*
+*Purpose:
+* wcslen returns the length of a null-terminated string in number of
+* wide characters, not including the null wide character itself.
+*
+*Revision History:
+* 04-07-91 IanJa C version created.
+*
+*******************************************************************************/
+
+#include <stdlib.h>
+
+/***
+*wcslen - return the length of a null-terminated string
+*
+*Purpose:
+* Finds the number of wide characters in the given wide character
+* string, not including the final null character.
+*
+*Entry:
+* const wchat_t * str - string whose length is to be computed
+*
+*Exit:
+* length of the string "str", exclusive of the final null wide character
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+size_t _CRTAPI1 wcslen(const wchar_t * str)
+{
+ wchar_t *string = (wchar_t *) str;
+
+ while( *string )
+ string++;
+
+ return string - str;
+}
diff --git a/private/ole32/stg/wclib/wcsncmp.c b/private/ole32/stg/wclib/wcsncmp.c
new file mode 100644
index 000000000..b0afc8b50
--- /dev/null
+++ b/private/ole32/stg/wclib/wcsncmp.c
@@ -0,0 +1,52 @@
+/***
+*wcsncmp.c - compare first n characters of two wide character strings
+*
+* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsncmp() - compare first n characters of two wide character
+* strings for lexical order.
+*
+*Revision History:
+* 04-07-91 IanJa C version created.
+*
+*******************************************************************************/
+
+#include <stdlib.h>
+
+/***
+*int wcsncmp(first, last, count) - compare first count wide characters of wide
+* character strings
+*
+*Purpose:
+* Compares two wide character strings for lexical order. The comparison
+* stops after: (1) a difference between the strings is found, (2) the end
+* of the strings is reached, or (3) count characters have been
+* compared.
+*
+*Entry:
+* char *first, *last - wide character strings to compare
+* unsigned count - maximum number of wide characters to compare
+*
+*Exit:
+* returns <0 if first < last
+* returns 0 if first == last
+* returns >0 if first > last
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 wcsncmp(const wchar_t * first, const wchar_t * last, size_t count)
+{
+ if (!count)
+ return 0;
+
+ while (--count && *first && *first == *last)
+ {
+ first++;
+ last++;
+ }
+
+ return *first - *last;
+}
diff --git a/private/ole32/stg/wclib/wcsnicmp.c b/private/ole32/stg/wclib/wcsnicmp.c
new file mode 100644
index 000000000..e984e723c
--- /dev/null
+++ b/private/ole32/stg/wclib/wcsnicmp.c
@@ -0,0 +1,63 @@
+/***
+*wcsnicmp.c - compare first n characters of two wide character strings with
+* case insensitivity
+*
+* Copyright (c) 1985-1988, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* defines wcsnicmp() - compare first n characters of two wide character
+* strings for lexical order with case insensitivity.
+*
+*Revision History:
+* 04-07-91 IanJa C version created.
+* 11-25-91 AlexT Modified from wcsncmp.c
+* 04-Mar-92 ChrisMay fixed signed/unsigned warning in wcUP()
+* 12-Mar-92 Fixed bug in wcsnicmp (used to return *first - *last)
+*
+*******************************************************************************/
+
+#include <stdlib.h>
+/***
+*wchar_t wcUp(wc) - upper case wide character
+*
+*/
+
+#define wcUp(wc) (('a' <= (wchar_t) (wc) && (wchar_t) (wc) <= 'z') ? \
+ (wchar_t) (wc) + (wchar_t)('A' - 'a') : (wchar_t) (wc))
+
+/***
+*int wcsnicmp(first, last, count) - compare first count wide characters of wide
+* character strings with case insensitivity.
+*
+*Purpose:
+* Compares two wide character strings for lexical order. The comparison
+* stops after: (1) a difference between the strings is found, (2) the end
+* of the strings is reached, or (3) count characters have been
+* compared.
+*
+*Entry:
+* char *first, *last - wide character strings to compare
+* unsigned count - maximum number of wide characters to compare
+*
+*Exit:
+* returns <0 if first < last
+* returns 0 if first == last
+* returns >0 if first > last
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int _CRTAPI1 wcsnicmp(const wchar_t * first, const wchar_t * last, size_t count)
+{
+ if (!count)
+ return 0;
+
+ while (--count && *first && wcUp(*first) == wcUp(*last))
+ {
+ first++;
+ last++;
+ }
+
+ return wcUp(*first) - wcUp(*last);
+}
diff --git a/private/ole32/stg/wclib/wcsrchr.c b/private/ole32/stg/wclib/wcsrchr.c
new file mode 100644
index 000000000..ba7ee2e86
--- /dev/null
+++ b/private/ole32/stg/wclib/wcsrchr.c
@@ -0,0 +1,49 @@
+//+---------------------------------------------------------------------------
+//
+// File: wcsrchr.c
+//
+// Contents: This file contains the src for the wcsrchr() function.
+//
+// Classes: none
+//
+// History: 09-Oct-91 chrismay created
+//
+//----------------------------------------------------------------------------
+
+#include <stddef.h>
+#include <stdlib.h>
+
+//+---------------------------------------------------------------------------
+//
+// Function: wcsrchr()
+//
+// Synopsis: This function finds the last occurrence of the specified wide
+// character in a wide-character string.
+//
+// Arguments: wsz - wide character string, zero terminated
+// wc - wide character to be found in wsz
+//
+// Returns: returns a pointer to the beginning of the substring that
+// begins with the last occurrence of the character if found,
+// else returns NULL.
+//
+// Warnings: only works on wide-character ASCII
+//
+// History: 15-Oct-91 chrismay created
+//
+//----------------------------------------------------------------------------
+
+wchar_t *_CRTAPI1 wcsrchr(const wchar_t *wcs, wchar_t wc)
+{
+ wchar_t *start = (wchar_t *)wcs;
+
+ while (*wcs++) /* find end of string */
+ ;
+ /* search towards front */
+ while (--wcs != start && *wcs != wc)
+ ;
+
+ if (*wcs == wc) /* character found ? */
+ return (wchar_t *)wcs;
+ return NULL;
+}
diff --git a/private/ole32/stg/wclib/wcstr.h b/private/ole32/stg/wclib/wcstr.h
new file mode 100644
index 000000000..943f03e0b
--- /dev/null
+++ b/private/ole32/stg/wclib/wcstr.h
@@ -0,0 +1,51 @@
+/***
+* wcstr.h - declarations for wide character string manipulation functions
+*
+* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* This file contains the function declarations for the string
+* manipulation functions.
+* [UNICODE/ISO]
+*
+****/
+
+#ifndef _INC_WCSTR
+
+#include <stdlib.h>
+
+/* function prototypes */
+
+#ifndef _CRTAPI1
+#define _CRTAPI1 _cdecl
+#endif
+
+long _CRTAPI1 wcsatol(const wchar_t *string);
+int _CRTAPI1 wcsatoi(const wchar_t *string);
+wchar_t *_CRTAPI1 wcscat(wchar_t *string1, const wchar_t *string2);
+wchar_t *_CRTAPI1 wcschr(const wchar_t *string1, wchar_t character);
+int _CRTAPI1 wcscmp(const wchar_t *string1, const wchar_t *string2);
+int _CRTAPI1 wcsicmp(const wchar_t *string1, const wchar_t *string2);
+wchar_t *_CRTAPI1 wcscpy(wchar_t *string1, const wchar_t *string2);
+size_t _CRTAPI1 wcscspn(const wchar_t *string1, const wchar_t *string2);
+wchar_t *_CRTAPI1 wcsitoa(int ival, wchar_t *string, int radix);
+size_t _CRTAPI1 wcslen(const wchar_t *string);
+wchar_t *_CRTAPI1 wcsltoa(long lval, wchar_t *string, int radix);
+wchar_t *_CRTAPI1 wcsncat(wchar_t *string1, const wchar_t *string2, size_t count);
+int _CRTAPI1 wcsncmp(const wchar_t *string1, const wchar_t *string2, size_t count);
+int _CRTAPI1 wcsnicmp(const wchar_t *string1, const wchar_t *string2, size_t count);
+wchar_t *_CRTAPI1 wcsncpy(wchar_t *string1, const wchar_t *string2, size_t count);
+wchar_t *_CRTAPI1 wcspbrk(const wchar_t *string1, const wchar_t *string2);
+wchar_t *_CRTAPI1 wcsrchr(const wchar_t *string, wchar_t character);
+size_t _CRTAPI1 wcsspn(const wchar_t *string1, const wchar_t *string2);
+wchar_t *_CRTAPI1 wcswcs(const wchar_t *string1, const wchar_t *string2);
+int _CRTAPI1 wcstomb(char *string, wchar_t character);
+size_t _CRTAPI1 wcstombs(char *dest, const wchar_t *string, size_t count);
+
+int _CRTAPI1 wcscoll(const wchar_t *wsz1, const wchar_t *wsz2);
+wchar_t *_CRTAPI1 wcslwr(wchar_t *wsz);
+wchar_t *_CRTAPI1 wcsupr(wchar_t *wsz);
+
+#define _INC_WCSTR
+
+#endif /* _INC_WCSTR */
diff --git a/private/ole32/stg/xact/coord.cxx b/private/ole32/stg/xact/coord.cxx
new file mode 100644
index 000000000..9e7b5680b
--- /dev/null
+++ b/private/ole32/stg/xact/coord.cxx
@@ -0,0 +1,1694 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: coord.cxx
+//
+// Contents: Transaction Coordinator implementation
+//
+// Classes:
+//
+// Functions:
+//
+// History: 03-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "xacthead.cxx"
+#pragma hdrstop
+
+#include <process.h>
+#include "coord.hxx"
+#include "enlist.hxx"
+#include "xactenum.hxx"
+#include "xactdisp.hxx"
+
+#if 0
+//Instantiate so we can make sure that all the methods are
+// properly declared.
+
+//CTransactionCoordinator tcFoo;
+#endif
+
+//BUGBUG: GetLock macro should return a unique error code when it detects
+// the busy condition, but we don't have one defined yet.
+#define GetLock() EnterCriticalSection(&_cs); \
+ if (_dwLockCount != 0) \
+ { \
+ if (GetCurrentThreadId() != _dwThread) \
+ { \
+ LeaveCriticalSection(&_cs); \
+ return STG_E_INUSE; \
+ } \
+ else \
+ { \
+ _dwLockCount++; \
+ } \
+ } \
+ else \
+ { \
+ _dwLockCount = 1; \
+ _dwThread = GetCurrentThreadId(); \
+ } \
+ LeaveCriticalSection(&_cs);
+
+#define ReleaseLock() EnterCriticalSection(&_cs); \
+ if (--_dwLockCount == 0) \
+ { \
+ _dwThread = 0; \
+ } \
+ LeaveCriticalSection(&_cs);
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::CConnectionPoint, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [type] -- Type supported by connection point
+//
+// History: 28-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CConnectionPoint::CConnectionPoint()
+{
+ xactDebugOut((DEB_ITRACE, "In CConnectionPoint::CConnectionPoint:%p()\n", this));
+ _cReferences = 1;
+ _dwCookie = 0;
+ _pxlHead = NULL;
+ xactDebugOut((DEB_ITRACE, "Out CConnectionPoint::CConnectionPoint\n"));
+}
+
+
+void CConnectionPoint::Init(XACTTYPE type, CTransactionCoordinator *ptc)
+{
+ _type = type;
+ _ptc = ptc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::QueryInterface, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CConnectionPoint::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc = S_OK;
+ xactDebugOut((DEB_TRACE,
+ "In CConnectionPoint::QueryInterface:%p()\n",
+ this));
+
+ *ppvObj = NULL;
+
+ if ((IsEqualIID(iid, IID_IUnknown)) ||
+ (IsEqualIID(iid, IID_IConnectionPoint)))
+ {
+ *ppvObj = (IConnectionPoint *)this;
+ CConnectionPoint::AddRef();
+ }
+ else
+ {
+ return E_NOINTERFACE;
+ }
+
+ xactDebugOut((DEB_TRACE, "Out CConnectionPoint::QueryInterface\n"));
+ return ResultFromScode(sc);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::AddRef, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CConnectionPoint::AddRef(void)
+{
+ ULONG ulRet;
+ xactDebugOut((DEB_TRACE,
+ "In CConnectionPoint::AddRef:%p()\n",
+ this));
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+
+ xactDebugOut((DEB_TRACE, "Out CConnectionPoint::AddRef\n"));
+ return ulRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::Release, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CConnectionPoint::Release(void)
+{
+ LONG lRet;
+ xactDebugOut((DEB_TRACE,
+ "In CConnectionPoint::Release:%p()\n",
+ this));
+
+ xactAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+ xactAssert((lRet > 0) && "Connection point released too many times.");
+ }
+ else if (lRet < 0)
+ lRet = 0;
+
+ xactDebugOut((DEB_TRACE, "Out CConnectionPoint::Release\n"));
+ return (ULONG)lRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::GetConnectionInterface, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 24-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CConnectionPoint::GetConnectionInterface(IID *pIID)
+{
+ xactDebugOut((DEB_ITRACE,
+ "In CConnectionPoint::GetConnectionInterface:%p()\n",
+ this));
+
+ if (_type == Adjust)
+ {
+ *pIID = IID_ITransactionAdjustEvents;
+ }
+ else if (_type == Veto)
+ {
+ *pIID = IID_ITransactionVetoEvents;
+ }
+ else
+ {
+ *pIID = IID_ITransactionOutcomeEvents;
+ }
+
+ xactDebugOut((DEB_ITRACE, "Out CConnectionPoint::GetConnectionInterface\n"));
+ return S_OK;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::GetConnectionPointContainer, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 24-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CConnectionPoint::GetConnectionPointContainer(
+ IConnectionPointContainer ** ppCPC)
+{
+ xactDebugOut((DEB_ITRACE,
+ "In CConnectionPoint::GetConnectionPointContainer:%p()\n",
+ this));
+
+ *ppCPC = (IConnectionPointContainer *)_ptc;
+ _ptc->AddRef();
+
+ xactDebugOut((DEB_ITRACE,
+ "Out CConnectionPoint::GetConnectionPointContainer\n"));
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::Advise, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 24-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CConnectionPoint::Advise(IUnknown *pUnkSink,
+ DWORD *pdwCookie)
+{
+ SCODE sc;
+ CXactList *pxlTemp = NULL;
+ CXactList **ppxlHead = NULL;
+ void *pv = NULL;
+
+ xactDebugOut((DEB_ITRACE, "In CConnectionPoint::Advise:%p()\n", this));
+ ITransactionAdjustEvents *pAdjust;
+ ITransactionVetoEvents *pVeto;
+ ITransactionOutcomeEvents *pOutcome;
+
+ //BUGBUG: Multithread access
+ xactMem(pxlTemp = new CXactList);
+
+ //Note: The QueryInterface will give us a reference to hold on to.
+ if (_type == Adjust)
+ {
+ xactChk(pUnkSink->QueryInterface(IID_ITransactionAdjustEvents, &pv));
+ pxlTemp->SetAdjust((ITransactionAdjustEvents *)pv);
+ }
+ else if (_type == Veto)
+ {
+ xactChk(pUnkSink->QueryInterface(IID_ITransactionVetoEvents, &pv));
+ pxlTemp->SetVeto((ITransactionVetoEvents *)pv);
+ }
+ else
+ {
+ xactChk(pUnkSink->QueryInterface(IID_ITransactionOutcomeEvents, &pv));
+ pxlTemp->SetOutcome((ITransactionOutcomeEvents *)pv);
+ }
+
+ pxlTemp->SetNext(_pxlHead);
+
+ *pdwCookie = ++_dwCookie;
+ pxlTemp->SetFlags(*pdwCookie);
+
+ _pxlHead = pxlTemp;
+
+ xactDebugOut((DEB_ITRACE, "Out CConnectionPoint::Advise\n"));
+ return sc;
+Err:
+ delete pxlTemp;
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::Unadvise, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 24-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CConnectionPoint::Unadvise(DWORD dwCookie)
+{
+ CXactList *pxlTemp;
+ CXactList *pxlPrev;
+ xactDebugOut((DEB_ITRACE, "In CConnectionPoint::Unadvise:%p()\n", this));
+
+ pxlTemp = _pxlHead;
+ pxlPrev = NULL;
+
+ while ((pxlTemp != NULL) && (pxlTemp->GetFlags() != dwCookie))
+ {
+ pxlPrev = pxlTemp;
+ pxlTemp = pxlTemp->GetNext();
+ }
+
+ if (pxlTemp != NULL)
+ {
+ //Found the sink. Delete it from the list.
+ if (pxlPrev != NULL)
+ {
+ pxlPrev->SetNext(pxlTemp->GetNext());
+ }
+ else
+ {
+ _pxlHead = pxlTemp->GetNext();
+ }
+
+ if (_type == Adjust)
+ {
+ pxlTemp->GetAdjust()->Release();
+ }
+ else if (_type == Veto)
+ {
+ pxlTemp->GetVeto()->Release();
+ }
+ else
+ {
+ pxlTemp->GetOutcome()->Release();
+ }
+ delete pxlTemp;
+ }
+ else
+ //Client passed in unknown cookie.
+ return E_UNEXPECTED;
+
+ xactDebugOut((DEB_ITRACE, "Out CConnectionPoint::Unadvise\n"));
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::EnumConnections, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 24-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CConnectionPoint::EnumConnections(
+ IEnumConnections **ppEnum)
+{
+ xactDebugOut((DEB_ITRACE, "In CConnectionPoint::EnumConnections:%p()\n", this));
+ xactDebugOut((DEB_ITRACE, "Out CConnectionPoint::EnumConnections\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CConnectionPoint::CloseConnections, public
+//
+// Synopsis: Close all connections
+//
+// Arguments: none
+//
+// Returns: void
+//
+// History: 31-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+void CConnectionPoint::CloseConnections(void)
+{
+ xactDebugOut((DEB_ITRACE, "In CConnectionPoint::CloseConnections:%p()\n", this));
+
+ CXactList *pxlTemp = _pxlHead;
+ CXactList *pxlPrev;
+
+ while (pxlTemp != NULL)
+ {
+ pxlPrev = pxlTemp;
+ if (_type == Adjust)
+ {
+ pxlTemp->GetAdjust()->Release();
+ }
+ else if (_type == Veto)
+ {
+ pxlTemp->GetVeto()->Release();
+ }
+ else
+ {
+ pxlTemp->GetOutcome()->Release();
+ }
+ pxlTemp = pxlTemp->GetNext();
+ delete pxlPrev;
+ }
+ _pxlHead = NULL;
+
+ xactDebugOut((DEB_ITRACE, "Out CConnectionPoint::CloseConnections\n"));
+}
+
+
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::CTransactionCoordinator, public
+//
+// Synopsis: Default constructor
+//
+// Returns: Appropriate status code
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CTransactionCoordinator::CTransactionCoordinator(CTransactionDispenser *ptd,
+ IUnknown *punkOuter,
+ ISOLEVEL isoLevel,
+ ULONG isoFlags,
+ ULONG ulTimeout)
+{
+ _cReferences = 1;
+ _punkOuter = punkOuter;
+ _ptd = ptd;
+ _ptd->AddRef();
+
+ _cpAdjust.Init(Adjust, this);
+ _cpVeto.Init(Veto, this);
+ _cpOutcome.Init(Outcome, this);
+ //BUGBUG: This is a HACK. It works only because
+ // ITransactionCompletionEvents is identical to
+ // ITransactionOutcomeEvents
+ _cpCompletion.Init(Outcome, this);
+
+ _pxlResources = NULL;
+ _pxlSinglePhase = NULL;
+
+ _cPreventCommit = 0;
+
+ _xactInfo.uow = BOID_NULL;
+
+ //BUGBUG: grfTCSupported should include async when we do async.
+ _xactInfo.grfTCSupported = XACTTC_DONTAUTOABORT | XACTTC_TRYALLRESOURCES;
+ _xactInfo.grfRMSupported = 0;
+
+ _xactInfo.grfTCSupportedRetaining = _xactInfo.grfTCSupported;
+ _xactInfo.grfRMSupportedRetaining = _xactInfo.grfRMSupported;
+
+ _xactInfo.isoLevel = isoLevel;
+ _xactInfo.isoFlags = isoFlags;
+
+ _fValidTransaction = FALSE;
+ _ulTimeout = ulTimeout;
+
+ InitializeCriticalSection(&_cs);
+ _dwLockCount = 0;
+ _dwThread = 0;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::~CTransactionCoordinator, public
+//
+// Synopsis: Destructor
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CTransactionCoordinator::~CTransactionCoordinator()
+{
+ CloseTransaction();
+ _ptd->Defect(this);
+ _ptd->Release();
+ DeleteCriticalSection(&_cs);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::Init, public
+//
+// Synopsis: Initialize coordinator instance
+//
+// Returns: Appropriate status code
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CTransactionCoordinator::Init(void)
+{
+ SCODE sc;
+ xactDebugOut((DEB_ITRACE, "In CTransactionCoordinator::Init:%p()\n", this));
+ sc = CoCreateGuid((GUID *)&(_xactInfo.uow));
+
+ if (SUCCEEDED(sc))
+ {
+ _fValidTransaction = TRUE;
+ }
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionCoordinator::Init\n"));
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::QueryInterface, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionCoordinator::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc = S_OK;
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionCoordinator::QueryInterface:%p()\n",
+ this));
+
+ *ppvObj = NULL;
+
+ if ((IsEqualIID(iid, IID_IUnknown)) || (IsEqualIID(iid, IID_ITransaction)))
+ {
+ *ppvObj = (ITransaction *)this;
+ }
+ else if (IsEqualIID(iid, IID_ITransactionNested))
+ {
+ *ppvObj = (ITransactionNested *)this;
+ }
+ else if (IsEqualIID(iid, IID_ITransactionCoordinator))
+ {
+ *ppvObj = (ITransactionCoordinator *)this;
+ }
+ else if (IsEqualIID(iid, IID_ITransactionControl))
+ {
+ *ppvObj = (ITransactionControl *)this;
+ }
+ else if (IsEqualIID(iid, IID_IConnectionPointContainer))
+ {
+ *ppvObj = (IConnectionPointContainer *)this;
+ }
+ else
+ {
+ return _punkOuter->QueryInterface(iid, ppvObj);
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ CTransactionCoordinator::AddRef();
+ }
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionCoordinator::QueryInterface\n"));
+ return ResultFromScode(sc);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::AddRef, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CTransactionCoordinator::AddRef(void)
+{
+ ULONG ulRet;
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionCoordinator::AddRef:%p()\n",
+ this));
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionCoordinator::AddRef\n"));
+ return ulRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::Release, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CTransactionCoordinator::Release(void)
+{
+ LONG lRet;
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionCoordinator::Release:%p()\n",
+ this));
+
+ xactAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ lRet = 0;
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionCoordinator::Release\n"));
+ return (ULONG)lRet;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::CloseTransaction, private
+//
+// Synopsis: Close the current transaction, defecting all resources.
+//
+// Arguments: None.
+//
+// Returns: Appropriate status code
+//
+// History: 25-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CTransactionCoordinator::CloseTransaction(void)
+{
+ SCODE sc;
+
+ xactDebugOut((DEB_ITRACE, "In CTransactionCoordinator::CloseTransaction:%p()\n", this));
+
+ _fValidTransaction = FALSE;
+
+ CXactList *pxlTemp = _pxlResources;
+ CXactList *pxlLast;
+ while (pxlTemp != NULL)
+ {
+ pxlLast = pxlTemp;
+ sc = pxlTemp->GetResource()->Defect(FALSE);
+
+ if (FAILED(sc))
+ {
+ //BUGBUG: Do what? We don't want to stop defecting.
+ }
+ pxlTemp->GetEnlistment()->Release();
+
+ pxlTemp = pxlTemp->GetNext();
+ delete pxlLast;
+ }
+ _pxlResources = NULL;
+
+ if (_pxlSinglePhase != NULL)
+ {
+ _pxlSinglePhase->GetTransaction()->Release();
+ }
+ _pxlSinglePhase = NULL;
+
+ _cpAdjust.CloseConnections();
+ _cpVeto.CloseConnections();
+ _cpOutcome.CloseConnections();
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionCoordinator::CloseTransaction\n"));
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::Phase1Worker, public
+//
+// Synopsis: Worker function for phase 1 of a commit call
+//
+// Arguments: [psc] -- Pointer to commit struct containing parameters.
+//
+// Returns: Appropriate status code
+//
+// History: 27-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CTransactionCoordinator::Phase1Worker(SCommitStruct *pcs)
+{
+ SCODE sc;
+ SCODE scErr = S_OK;
+
+ xactDebugOut((DEB_ITRACE,
+ "In CTransactionCoordinator::Phase1Worker:%p()\n",
+ this));
+
+ //Note: This function does not release the lock in the success case.
+ // It relies of Phase2Worker to release it.
+ GetLock();
+
+ CXactList *pxlTemp = _cpAdjust.GetHead();
+
+ if (!IsValid())
+ {
+ xactErr(Err, XACT_E_NOTRANSACTION);
+ }
+
+ if (_cPreventCommit != 0)
+ {
+ xactErr(Err, XACT_E_COMMITPREVENTED);
+ }
+
+ //Update statistics on dispenser to indicate that we're now committing.
+ InterlockedIncrement((LONG *)&(_ptd->GetStats()->cCommitting));
+
+ //1) For each sink registered for ITransactionAdjustEvents, call
+ // OnPrePrepareAdjust()
+ while (pxlTemp != NULL)
+ {
+ xactChk(pxlTemp->GetAdjust()->OnPrePrepareAdjust(pcs->fRetaining));
+ pxlTemp = pxlTemp->GetNext();
+ }
+
+ //2) If all succeeded, then for each sink registered for
+ // ITransactionVetoEvents, call OnPrePrepare.
+ pxlTemp = _cpVeto.GetHead();
+ while (pxlTemp != NULL)
+ {
+ xactChk(pxlTemp->GetVeto()->OnPrePrepare(pcs->fRetaining));
+ pxlTemp = pxlTemp->GetNext();
+ }
+
+ //3) Prepare each resource.
+ pxlTemp = _pxlResources;
+ while (pxlTemp != NULL)
+ {
+ XACTSTAT xactstat = pxlTemp->GetState();
+
+ if ((xactstat == XACTSTAT_OPEN) || (xactstat == XACTSTAT_PREPARED))
+ {
+ sc = pxlTemp->GetResource()->Prepare(pcs->fRetaining,
+ 0,
+ FALSE,
+ //BUGBUG: Get moniker back.
+ // for recovery.
+ NULL,
+ NULL);
+
+ if (SUCCEEDED(sc))
+ {
+ pxlTemp->SetState(XACTSTAT_PREPARED);
+ }
+ }
+ else if ((xactstat == XACTSTAT_HEURISTIC_DAMAGE) ||
+ (xactstat == XACTSTAT_HEURISTIC_DANGER))
+ {
+ sc = XACT_E_HEURISTICDAMAGE;
+ }
+
+ if (FAILED(sc) && !(pcs->grfTC & XACTTC_TRYALLRESOURCES))
+ {
+ xactChk(sc);
+ }
+ else if (FAILED(sc))
+ {
+ scErr = sc;
+ }
+ pxlTemp = pxlTemp->GetNext();
+ }
+ sc = scErr;
+ xactChk(sc);
+
+ xactChk(CoCreateGuid((GUID *)&(pcs->uowNew)));
+
+ //All the prepares succeeded. Commit the single phase guy, if there
+ // if one.
+
+ if (_pxlSinglePhase != NULL)
+ {
+ xactChk(_pxlSinglePhase->GetTransaction()->Commit(pcs->fRetaining,
+ pcs->grfTC,
+ pcs->grfRM));
+ }
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionCoordinator::Phase1Worker\n"));
+
+ return sc;
+
+Err:
+ if (!(pcs->grfTC & XACTTC_DONTAUTOABORT))
+ {
+ //The user didn't specify auto-abort, so we abort the transaction.
+ // Note that the retaining semantics are still specified by the
+ // user.
+ CTransactionCoordinator::Abort(NULL,
+ pcs->fRetaining,
+ FALSE);
+ }
+ delete pcs;
+
+ ReleaseLock();
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::Phase2Worker, public
+//
+// Synopsis: Worker function for phase 2 of a commit
+//
+// Arguments: [pcs] -- Pointer to commitstruct containing parameters
+//
+// Returns: Appropriate status code
+//
+// History: 27-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CTransactionCoordinator::Phase2Worker(SCommitStruct *pcs)
+{
+ //Note: This function does not call GetLock(). It relies on Phase1Worker
+ // to call it.
+
+ SCODE sc;
+ xactDebugOut((DEB_ITRACE, "In CTransactionCoordinator::Phase2Worker:%p()\n", this));
+
+ //For each sink registered for OutcomeEvents, call OnCommit
+ CXactList *pxlTemp = _cpOutcome.GetHead();
+ while (pxlTemp != NULL)
+ {
+ sc = pxlTemp->GetOutcome()->OnCommit(pcs->fRetaining,
+ (pcs->fRetaining) ? &(pcs->uowNew)
+ : NULL,
+ S_OK);
+ pxlTemp = pxlTemp->GetNext();
+ }
+
+ pxlTemp = _pxlResources;
+ while (pxlTemp != NULL)
+ {
+ sc = pxlTemp->GetResource()->Commit(pcs->grfRM,
+ (pcs->fRetaining) ? &(pcs->uowNew)
+ : NULL);
+
+ xactAssert(SUCCEEDED(sc));
+ pxlTemp->SetState(XACTSTAT_COMMITTED);
+ pxlTemp = pxlTemp->GetNext();
+ }
+
+ //For each sink registered for CompletionEvents, call OnCommit
+ //BUGBUG: Only works because OutcomeEvents and CompletionEvents
+ // are identical.
+ pxlTemp = _cpCompletion.GetHead();
+ while (pxlTemp != NULL)
+ {
+ sc = pxlTemp->GetOutcome()->OnCommit(pcs->fRetaining,
+ (pcs->fRetaining) ? &(pcs->uowNew)
+ : NULL,
+ sc);
+ pxlTemp = pxlTemp->GetNext();
+ }
+ //Update statistics to indicate that we are no longer committing, but
+ // have successfully committed.
+ InterlockedDecrement((LONG *)&(_ptd->GetStats()->cCommitting));
+ InterlockedIncrement((LONG *)&(_ptd->GetStats()->cCommitted));
+
+
+ if (!pcs->fRetaining)
+ {
+ CloseTransaction();
+ }
+ else
+ {
+ pxlTemp = _pxlResources;
+ while (pxlTemp != NULL)
+ {
+ pxlTemp->SetState(XACTSTAT_OPEN);
+ pxlTemp = pxlTemp->GetNext();
+ }
+ _xactInfo.uow = pcs->uowNew;
+ }
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionCoordinator::Phase2Worker\n"));
+ delete pcs;
+
+ ReleaseLock();
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::Commit, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionCoordinator::Commit(BOOL fRetaining,
+ DWORD grfTC,
+ DWORD grfRM)
+{
+ SCODE sc = S_OK;
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionCoordinator::Commit:%p()\n",
+ this));
+
+ SCommitStruct *pcs;
+ xactMem(pcs = new SCommitStruct);
+ pcs->fRetaining = fRetaining;
+ pcs->grfTC = grfTC;
+ pcs->grfRM = grfRM;
+
+ if (grfTC & XACTTC_ASYNC)
+ {
+ ULONG h;
+
+ //Spawn thread. We use _beginthread because the code in the resources
+ // may use the C runtime.
+ h = _beginthread(Phase1WorkerThreadEntryPoint,
+ 0,
+ pcs);
+
+ if (h == -1)
+ {
+ grfTC = grfTC & ~XACTTC_ASYNC;
+ }
+ else
+ {
+ return XACT_S_ASYNC;
+ }
+ }
+
+ if (!(grfTC & XACTTC_ASYNC))
+ {
+ xactChk(Phase1Worker(pcs));
+ }
+
+ if (grfTC & XACTTC_SYNC_PHASEONE)
+ {
+ //Spawn thread.
+ ULONG h = _beginthread(Phase2WorkerThreadEntryPoint,
+ 0,
+ pcs);
+ if (h == -1)
+ {
+ grfTC = grfTC & ~XACTTC_SYNC_PHASEONE;
+ }
+ else
+ {
+ return sc;
+ }
+ }
+
+ if (!(grfTC & XACTTC_SYNC_PHASEONE))
+ {
+ xactChk(Phase2Worker(pcs));
+ }
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionCoordinator::Commit\n"));
+Err:
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::Abort, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionCoordinator::Abort(BOID *pboidReason,
+ BOOL fRetaining,
+ BOOL fAsync)
+{
+ //BUGBUG: This need to do something different for retaining aborts,
+ // since we can't really support them in docfile. We need to gracefully
+ // handle resources that cannot support fRetaining == TRUE.
+
+ SCODE sc = S_OK;
+
+ GetLock();
+
+ if (!IsValid())
+ {
+ ReleaseLock();
+ return XACT_E_NOTRANSACTION;
+ }
+
+ //BUGBUG: Handle Async
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionCoordinator::Abort:%p()\n",
+ this));
+ CXactList *pxlTemp;
+ XACTUOW uow;
+
+ //Update statistics to show that we're aborting.
+ InterlockedIncrement((LONG *)&(_ptd->GetStats()->cAborting));
+
+ if (fRetaining)
+ {
+ sc = CoCreateGuid((GUID *)&uow);
+ if (FAILED(sc))
+ return sc;
+ }
+
+ pxlTemp = _pxlResources;
+ while (pxlTemp != NULL)
+ {
+ pxlTemp->GetResource()->Abort(
+ pboidReason,
+ fRetaining,
+ (fRetaining) ? &uow : NULL);
+
+ pxlTemp->SetState(XACTSTAT_OPEN);
+ pxlTemp = pxlTemp->GetNext();
+ }
+
+ pxlTemp = _cpOutcome.GetHead();
+ while (pxlTemp != NULL)
+ {
+ pxlTemp->GetOutcome()->OnAbort(pboidReason,
+ fRetaining,
+ (fRetaining) ? &uow : NULL,
+ S_OK);
+
+ pxlTemp = pxlTemp->GetNext();
+ }
+
+ //BUGBUG: Only works because Outcome and Completion events are
+ // identical.
+ pxlTemp = _cpCompletion.GetHead();
+ while (pxlTemp != NULL)
+ {
+ pxlTemp->GetOutcome()->OnAbort(pboidReason,
+ fRetaining,
+ (fRetaining) ? &uow : NULL,
+ S_OK);
+
+ pxlTemp = pxlTemp->GetNext();
+ }
+
+ //Now we're no longer aborting, so update statistics.
+ InterlockedDecrement((LONG *)&(_ptd->GetStats()->cAborting));
+ InterlockedIncrement((LONG *)&(_ptd->GetStats()->cAborted));
+
+
+ if (!fRetaining)
+ {
+ CloseTransaction();
+ }
+
+ _xactInfo.uow = uow;
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionCoordinator::Abort\n"));
+ ReleaseLock();
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::GetTransactionInfo, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionCoordinator::GetTransactionInfo(XACTTRANSINFO *pinfo)
+{
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionCoordinator::GetTransactionInfo:%p()\n",
+ this));
+ if (!IsValid())
+ {
+ return XACT_E_NOTRANSACTION;
+ }
+
+ *pinfo = _xactInfo;
+ xactDebugOut((DEB_TRACE,
+ "Out CTransactionCoordinator::GetTransactionInfo\n"));
+ return S_OK;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::GetParent, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionCoordinator::GetParent(REFIID iid, void **ppvParent)
+{
+ xactDebugOut((DEB_TRACE, "In CTransactionCoordinator::GetParent:%p()\n", this));
+ xactDebugOut((DEB_TRACE, "Out CTransactionCoordinator::GetParent\n"));
+
+ //We don't currently support nesting this coordinator, so always return
+ // E_FAIL to indicate no parent transaction.
+ return E_FAIL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::Enlist, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionCoordinator::Enlist(IUnknown *pResource,
+ DWORD grfRMTC,
+ XACTRMGRID *prmgrid,
+ XACTTRANSINFO *pinfo,
+ DWORD *pgrfTCRMENLIST,
+ ITransactionEnlistment **ppEnlist)
+{
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionCoordinator::Enlist:%p()\n", this));
+
+ SCODE sc;
+ CXactList *pxl = NULL;
+ CTransactionEnlistment *pte = NULL;
+ ITransactionResource *ptr = NULL;
+
+ GetLock();
+
+ if (!IsValid())
+ {
+ xactErr(Err, XACT_E_NOTRANSACTION);
+ }
+
+ xactChkTo(Err_QI, pResource->QueryInterface(IID_ITransactionResource,
+ (void **)&ptr));
+
+ xactMem(pxl = new CXactList);
+ xactMem(pte = new CTransactionEnlistment(pxl, this));
+
+ pxl->SetNext(_pxlResources);
+ _pxlResources = pxl;
+ pxl->SetResource(ptr);
+ pxl->SetFlags(grfRMTC);
+ pxl->SetRMGRID(prmgrid);
+ pxl->SetEnlistment(pte);
+
+ *ppEnlist = pte;
+
+ //We are always active recovering.
+ *pgrfTCRMENLIST = XACTTCRMENLIST_IAMACTIVE;
+
+ *pinfo = _xactInfo;
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionCoordinator::Enlist\n"));
+ ReleaseLock();
+
+ return S_OK;
+
+Err:
+ delete pxl;
+ delete pte;
+Err_QI:
+ if (ptr != NULL)
+ ptr->Release();
+ ReleaseLock();
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::EnlistSinglePhase, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionCoordinator::EnlistSinglePhase(
+ ITransaction *pResource,
+ DWORD grfRMTC,
+ XACTRMGRID *prmgrid,
+ XACTTRANSINFO *pinfo,
+ DWORD *pgrfTCRMENLIST,
+ ITransactionEnlistment **ppEnlist)
+{
+ xactDebugOut((DEB_TRACE, "In CTransactionCoordinator::EnlistSinglePhase:%p()\n", this));
+
+ SCODE sc;
+ CXactList *pxl = NULL;
+ CTransactionEnlistment *pte = NULL;
+
+ GetLock();
+
+ if (!IsValid())
+ {
+ xactErr(Err, XACT_E_NOTRANSACTION);
+ }
+
+ if (_pxlSinglePhase != NULL)
+ {
+ xactErr(Err, XACT_E_ALREADYOTHERSINGLEPHASE);
+ }
+
+ xactMem(pxl = new CXactList);
+ xactMem(pte = new CTransactionEnlistment(pxl, this));
+
+ _pxlSinglePhase = pxl;
+ pxl->SetTransaction(pResource);
+ pxl->SetFlags(grfRMTC);
+ pxl->SetRMGRID(prmgrid);
+ pxl->SetEnlistment(pte);
+
+ *ppEnlist = pte;
+
+ //We are always active recovering.
+ *pgrfTCRMENLIST = XACTTCRMENLIST_IAMACTIVE;
+
+ *pinfo = _xactInfo;
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionCoordinator::EnlistSinglePhase\n"));
+ ReleaseLock();
+
+ return S_OK;
+Err:
+ delete pxl;
+ delete pte;
+
+ ReleaseLock();
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::EnumResources, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionCoordinator::EnumResources(IEnumXACTRE **ppenum)
+{
+ SCODE sc;
+ xactDebugOut((DEB_TRACE, "In CTransactionCoordinator::EnumResources:%p()\n", this));
+ if (!IsValid())
+ {
+ return XACT_E_NOTRANSACTION;
+ }
+
+ xactMem(*ppenum = new CResourceEnum(this));
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionCoordinator::EnumResources\n"));
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::GetStatus, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 15-Aug-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionCoordinator::GetStatus(DWORD *pdwStatus)
+{
+ xactDebugOut((DEB_ITRACE, "In CTransactionCoordinator::GetStatus:%p()\n", this));
+ xactDebugOut((DEB_ITRACE, "Out CTransactionCoordinator::GetStatus\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::SetTimeout, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionCoordinator::SetTimeout(ULONG ulTimeout)
+{
+ xactDebugOut((DEB_TRACE, "In CTransactionCoordinator::SetTimeout:%p()\n", this));
+ if (!IsValid())
+ {
+ return XACT_E_NOTRANSACTION;
+ }
+ _ulTimeout = ulTimeout;
+ xactDebugOut((DEB_TRACE, "Out CTransactionCoordinator::SetTimeout\n"));
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::PreventCommit, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionCoordinator::PreventCommit(BOOL fPrevent)
+{
+ xactDebugOut((DEB_TRACE, "In CTransactionCoordinator::PreventCommit:%p()\n", this));
+
+ GetLock();
+
+ if (!IsValid())
+ {
+ ReleaseLock();
+ return XACT_E_NOTRANSACTION;
+ }
+
+ _cPreventCommit += (fPrevent) ? 1 : -1;
+ ReleaseLock();
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionCoordinator::PreventCommit\n"));
+ return S_OK;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::DefectResource, public
+//
+// Synopsis: Internal method used to remove resources from resource
+// list.
+//
+// Arguments: [pxlResource] -- Pointer to resource to defect.
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CTransactionCoordinator::DefectResource(CXactList *pxlResource)
+{
+ xactDebugOut((DEB_ITRACE, "In CTransactionCoordinator::DefectResource:%p()\n", this));
+
+ //First find the resource in the list, as well as the previous resource.
+ CXactList *pxlPrev = NULL;
+
+ GetLock();
+
+ CXactList *pxlTemp = _pxlResources;
+
+ while (pxlTemp != pxlResource)
+ {
+ pxlPrev = pxlTemp;
+ pxlTemp = pxlTemp->GetNext();
+ }
+
+ xactAssert(pxlTemp != NULL);
+
+ //Now remove it from the list.
+ if (pxlPrev == NULL)
+ {
+ _pxlResources = pxlTemp->GetNext();
+ }
+ else
+ {
+ pxlPrev->SetNext(pxlTemp->GetNext());
+ }
+
+ pxlTemp->GetEnlistment()->Release();
+ delete pxlTemp;
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionCoordinator::DefectResource\n"));
+ ReleaseLock();
+
+ return S_OK;
+}
+
+
+
+
+void _cdecl Phase1WorkerThreadEntryPoint(void *pcs)
+{
+ SCODE sc = ((SCommitStruct *)pcs)->ptc->Phase1Worker((SCommitStruct *)pcs);
+ if (SUCCEEDED(sc))
+ {
+ ((SCommitStruct *)pcs)->ptc->Phase2Worker((SCommitStruct *)pcs);
+ }
+}
+
+void _cdecl Phase2WorkerThreadEntryPoint(void *pcs)
+{
+ ((SCommitStruct *)pcs)->ptc->Phase2Worker((SCommitStruct *)pcs);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::EnumConnectionPoints, public
+//
+// Synopsis: Return enumerator on connection points
+//
+// Arguments: [ppEnum] -- Return pointer of enumerator
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionCoordinator::EnumConnectionPoints(
+ IEnumConnectionPoints **ppEnum)
+{
+ xactDebugOut((DEB_ITRACE,
+ "In CTransactionCoordinator::EnumConnectionPoints:%p()\n",
+ this));
+ xactDebugOut((DEB_ITRACE,
+ "Out CTransactionCoordinator::EnumConnectionPoints\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionCoordinator::FindConnectionPoint, public
+//
+// Synopsis: Return a connection point given an IID
+//
+// Arguments: [iid] -- IID to return connection point for
+// [ppCP] -- Return location for pointer
+//
+// Returns: Appropriate status code
+//
+// History: 28-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionCoordinator::FindConnectionPoint(
+ REFIID iid,
+ IConnectionPoint **ppCP)
+{
+ xactDebugOut((DEB_ITRACE,
+ "In CTransactionCoordinator::FindConnectionPoint:%p()\n",
+ this));
+
+ CConnectionPoint *pcp;
+
+ if (IsEqualIID(iid, IID_ITransactionAdjustEvents))
+ {
+ pcp = &_cpAdjust;
+ }
+ else if (IsEqualIID(iid, IID_ITransactionVetoEvents))
+ {
+ pcp = &_cpVeto;
+ }
+ else if (IsEqualIID(iid, IID_ITransactionOutcomeEvents))
+ {
+ pcp = &_cpOutcome;
+ }
+ else
+ {
+ *ppCP = NULL;
+ return E_NOINTERFACE;
+ }
+
+ pcp->AddRef();
+ *ppCP = pcp;
+
+ xactDebugOut((DEB_ITRACE,
+ "Out CTransactionCoordinator::FindConnectionPoint\n"));
+ return S_OK;
+}
diff --git a/private/ole32/stg/xact/coord.hxx b/private/ole32/stg/xact/coord.hxx
new file mode 100644
index 000000000..f32b5b99e
--- /dev/null
+++ b/private/ole32/stg/xact/coord.hxx
@@ -0,0 +1,207 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: coord.hxx
+//
+// Contents: Transaction coordinator header file
+//
+// Classes:
+//
+// Functions:
+//
+// History: 03-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __COORD_HXX__
+#define __COORD_HXX__
+
+#include "xactlist.hxx"
+
+class CResourceEnum;
+class CTransactionDispenser;
+class CTransactionCoordinator;
+
+struct SCommitStruct
+{
+public:
+ BOOL fRetaining;
+ DWORD grfTC;
+ DWORD grfRM;
+
+ CTransactionCoordinator *ptc;
+ DWORD dwFlags;
+ XACTUOW uowNew;
+};
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CConnectionPoint
+//
+// Purpose:
+//
+// Interface:
+//
+// History: 28-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+class CConnectionPoint: public IConnectionPoint
+{
+public:
+ CConnectionPoint();
+ void Init(XACTTYPE type, CTransactionCoordinator *ptc);
+
+ //From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ //From IConnectionPoint
+ STDMETHOD(GetConnectionInterface)(IID *pIID);
+ STDMETHOD(GetConnectionPointContainer)
+ (IConnectionPointContainer ** ppCPC);
+ STDMETHOD(Advise)(IUnknown *pUnkSink, DWORD *pdwCookie);
+ STDMETHOD(Unadvise)(DWORD dwCookie);
+ STDMETHOD(EnumConnections)(IEnumConnections **ppEnum);
+
+ inline CXactList *GetHead(void);
+ void CloseConnections(void);
+
+private:
+ DWORD _dwCookie;
+ LONG _cReferences;
+ XACTTYPE _type;
+ CXactList *_pxlHead;
+ CTransactionCoordinator *_ptc;
+};
+
+
+inline CXactList * CConnectionPoint::GetHead(void)
+{
+ return _pxlHead;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Class: CTransactionCoordinator
+//
+// Purpose: Transaction coordinator object
+//
+// History: 28-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+//Note: ITransaction is pulled in by ITransactionNested
+class CTransactionCoordinator:
+ public ITransactionNested,
+ public ITransactionCoordinator,
+ public ITransactionControl,
+ public IConnectionPointContainer
+{
+public:
+ CTransactionCoordinator(CTransactionDispenser *ptd,
+ IUnknown *punkOuter,
+ ISOLEVEL isoLevel,
+ ULONG isoFlags,
+ ULONG ulTimeout);
+ ~CTransactionCoordinator();
+
+ SCODE Init(void);
+
+ SCODE CloseTransaction(void);
+
+ //From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ //From ITransaction
+ STDMETHOD(Commit)(BOOL fRetaining,
+ DWORD grfTC,
+ DWORD grfRM);
+ SCODE Phase1Worker(SCommitStruct *pcs);
+ SCODE Phase2Worker(SCommitStruct *pcs);
+
+ STDMETHOD(Abort)(BOID * pboidReason,
+ BOOL fRetaining,
+ BOOL fAsync);
+ STDMETHOD(GetTransactionInfo)(XACTTRANSINFO * pinfo);
+
+ //From ITransactionNested
+ STDMETHOD(GetParent)(REFIID iid, void ** ppvParent);
+
+ //From ITransactionCoordinator
+ STDMETHOD(Enlist)(IUnknown *pResource,
+ DWORD grfRMTC,
+ XACTRMGRID *prmgrid,
+ XACTTRANSINFO *pinfo,
+ DWORD *pgrfTCRMENLIST,
+ ITransactionEnlistment **ppEnlist);
+ STDMETHOD(EnlistSinglePhase)(ITransaction *pResource,
+ DWORD grfRMTC,
+ XACTRMGRID *prmgrid,
+ XACTTRANSINFO *pinfo,
+ DWORD *pgrfTCRMENLIST,
+ ITransactionEnlistment **ppEnlist);
+ STDMETHOD(EnumResources)(IEnumXACTRE **ppenum);
+
+ //From ITransactionControl
+ STDMETHOD(GetStatus)(DWORD *pdwStatus);
+ STDMETHOD(SetTimeout)(ULONG ulTimeout);
+ STDMETHOD(PreventCommit)(BOOL fPrevent);
+
+ //From IConnectionPointContainer
+ STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum);
+ STDMETHOD(FindConnectionPoint)(REFIID iid, IConnectionPoint **ppCP);
+
+ //Internal methods
+ SCODE DefectResource(CXactList *pxlResource);
+
+ inline BOOL IsValid(void);
+private:
+ LONG _cReferences;
+ IUnknown *_punkOuter;
+ CTransactionDispenser *_ptd;
+
+ CXactList *_pxlResources;
+ CXactList *_pxlSinglePhase;
+
+ LONG _cPreventCommit;
+ BOOL _fValidTransaction;
+ ULONG _ulTimeout;
+
+ XACTTRANSINFO _xactInfo;
+
+ CRITICAL_SECTION _cs;
+ DWORD _dwThread;
+ DWORD _dwLockCount;
+
+ CConnectionPoint _cpAdjust;
+ CConnectionPoint _cpVeto;
+ CConnectionPoint _cpOutcome;
+ CConnectionPoint _cpCompletion;
+ //BUGBUG: Need to do ITransactionInProgress events also.
+
+ friend CResourceEnum;
+ friend CConnectionPoint;
+};
+
+
+
+
+inline BOOL CTransactionCoordinator::IsValid(void)
+{
+ return _fValidTransaction;
+}
+
+void _cdecl Phase1WorkerThreadEntryPoint(void *pcs);
+void _cdecl Phase2WorkerThreadEntryPoint(void *pcs);
+
+#endif // #ifndef __COORD_HXX__
diff --git a/private/ole32/stg/xact/dirs b/private/ole32/stg/xact/dirs
new file mode 100644
index 000000000..a84cc58a7
--- /dev/null
+++ b/private/ole32/stg/xact/dirs
@@ -0,0 +1,37 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Drew Bliss (DrewB) 21-Dec-1993
+
+!ENDIF
+
+#
+# This is a list of all subdirectories that build required components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+DIRS=
+
+#
+# This is a list of all subdirectories that build optional components.
+# Each subdirectory name should appear on a line by itself. The build
+# follows the order in which the subdirectories are specified.
+#
+
+OPTIONAL_DIRS= \
+ \
+# daytona
diff --git a/private/ole32/stg/xact/enlist.cxx b/private/ole32/stg/xact/enlist.cxx
new file mode 100644
index 000000000..47ff15a85
--- /dev/null
+++ b/private/ole32/stg/xact/enlist.cxx
@@ -0,0 +1,564 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: enlist.cxx
+//
+// Contents: CTransactionEnlistment implementation
+//
+// Classes:
+//
+// Functions:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "xacthead.cxx"
+#pragma hdrstop
+
+
+#include "enlist.hxx"
+#include "coord.hxx"
+#include "xactlist.hxx"
+
+
+#if 0
+//Instantiate so we can make sure that all the methods are
+// properly declared.
+
+CTransactionEnlistment teFoo(NULL, NULL);
+#endif
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::CTransactionEnlistment, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [pxl] -- Pointer to resource
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CTransactionEnlistment::CTransactionEnlistment(CXactList *pxl,
+ CTransactionCoordinator *ptc)
+{
+ xactDebugOut((DEB_ITRACE,
+ "In CTransactionEnlistment::CTransactionEnlistment:%p()\n",
+ this));
+
+ _pxlResource = pxl;
+ _cReferences = 1;
+ _ptc = ptc;
+
+ xactDebugOut((DEB_ITRACE,
+ "Out CTransactionEnlistment::CTransactionEnlistment\n"));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::~CTransactionEnlistment, public
+//
+// Synopsis: Destructor
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CTransactionEnlistment::~CTransactionEnlistment()
+{
+ xactDebugOut((DEB_ITRACE,
+ "In CTransactionEnlistment::~CTransactionEnlistment:%p()\n",
+ this));
+
+ xactDebugOut((DEB_ITRACE,
+ "Out CTransactionEnlistment::~CTransactionEnlistment\n"));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::QueryInterface, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnlistment::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc = S_OK;
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnlistment::QueryInterface:%p()\n",
+ this));
+
+ *ppvObj = NULL;
+
+ if ((IsEqualIID(iid, IID_IUnknown)) ||
+ (IsEqualIID(iid, IID_ITransactionEnlistment)))
+ {
+ *ppvObj = (ITransactionEnlistment *)this;
+ }
+ else if (IsEqualIID(iid, IID_ITransactionEnlistmentRecover))
+ {
+ *ppvObj = (ITransactionEnlistmentRecover *)this;
+ }
+ else if (IsEqualIID(iid, IID_ITransactionEnlistmentAsync))
+ {
+ *ppvObj = (ITransactionEnlistmentAsync *)this;
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ CTransactionEnlistment::AddRef();
+ }
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionEnlistment::QueryInterface\n"));
+ return sc;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::AddRef, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CTransactionEnlistment::AddRef(void)
+{
+ ULONG ulRet;
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnlistment::AddRef:%p()\n",
+ this));
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+ xactDebugOut((DEB_TRACE, "Out CTransactionEnlistment::AddRef\n"));
+ return _cReferences;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::Release, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CTransactionEnlistment::Release(void)
+{
+ LONG lRet;
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnlistment::Release:%p()\n",
+ this));
+
+ xactAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ lRet = 0;
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionEnlistment::Release\n"));
+ return (ULONG)lRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::GetTransaction, public
+//
+// Synopsis: Return a pointer to the tranasction object of this enlistment.
+//
+// Arguments: [ppTransaction] -- Return location for pointer
+//
+// Returns: S_OK
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnlistment::GetTransaction(
+ ITransaction **ppTransaction)
+{
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnlistment::GetTransaction:%p()\n",
+ this));
+
+ *ppTransaction = (ITransaction *)_ptc;
+ _ptc->AddRef();
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionEnlistment::GetTransaction\n"));
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::EarlyVote, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnlistment::EarlyVote(BOOL fVote, BOID *pboidReason)
+{
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnlistment::EarlyVote:%p()\n",
+ this));
+
+ if (!_ptc->IsValid())
+ {
+ return XACT_E_NOTRANSACTION;
+ }
+
+ //The coordinator is going to ignore early votes for the time being.
+ //BUGBUG: Consider implementing this later.
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionEnlistment::EarlyVote\n"));
+ return E_FAIL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::HeuristicDecision, public
+//
+// Synopsis: Allows a resource to make a heuristic decision
+//
+// Arguments: [dwDecision] -- Heuristic decision being made
+// [pboidReason] -- Reason for decision (ignored)
+// [fDefecting] -- TRUE if resource wishes to defect as a
+// side effect of making this call
+//
+// Returns: Appropriate status code
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnlistment::HeuristicDecision(DWORD dwDecision,
+ BOID *pboidReason,
+ BOOL fDefecting)
+{
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnlistment::HeuristicDecision:%p()\n",
+ this));
+
+ XACTSTAT xactNewState;
+
+ if (!_ptc->IsValid())
+ {
+ return XACT_E_NOTRANSACTION;
+ }
+
+ if (dwDecision == XACTHEURISTIC_ABORT)
+ {
+ xactNewState = XACTSTAT_HEURISTIC_ABORT;
+ }
+ else if (dwDecision == XACTHEURISTIC_COMMIT)
+ {
+ xactNewState = XACTSTAT_HEURISTIC_COMMIT;
+ }
+ else if (dwDecision == XACTHEURISTIC_DAMAGE)
+ {
+ xactNewState = XACTSTAT_HEURISTIC_DAMAGE;
+ }
+ else if (dwDecision == XACTHEURISTIC_DANGER)
+ {
+ xactNewState = XACTSTAT_HEURISTIC_DANGER;
+ }
+ else
+ {
+ return E_INVALIDARG;
+ }
+
+ _pxlResource->SetState(xactNewState);
+
+ if (fDefecting)
+ {
+ return CTransactionEnlistment::Defect();
+ }
+
+ xactDebugOut((DEB_TRACE,
+ "Out CTransactionEnlistment::HeuristicDecision\n"));
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::Defect, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnlistment::Defect(void)
+{
+ SCODE sc;
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnlistment::Defect:%p()\n",
+ this));
+
+ if (_pxlResource != NULL)
+ {
+ sc = _ptc->DefectResource(_pxlResource);
+ if (SUCCEEDED(sc))
+ {
+ _pxlResource = NULL;
+ }
+ }
+ else
+ {
+ return XACT_E_NORESOURCE;
+ }
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionEnlistment::Defect\n"));
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::GetMoniker, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnlistment::GetMoniker(IMoniker **ppmk)
+{
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnlistment::GetMoniker:%p()\n",
+ this));
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionEnlistment::GetMoniker\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::ReEnlist, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnlistment::ReEnlist(
+ ITransactionResource *pUnkResource,
+ XACTUOW *pUOWExpeCTransactionEnlistmentd,
+ XACTRMGRID *prmgrid)
+{
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnlistment::ReEnlist:%p()\n",
+ this));
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionEnlistment::ReEnlist\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::RecoveryComplete, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnlistment::RecoveryComplete(XACTRMGRID *prmgrid)
+{
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnlistment::RecoveryComplete:%p()\n",
+ this));
+
+ xactDebugOut((DEB_TRACE,
+ "Out CTransactionEnlistment::RecoveryComplete\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::PrepareRequestDone, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnlistment::PrepareRequestDone(HRESULT hr,
+ IMoniker *pmk,
+ BOID *pboidReason)
+{
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnlistment::PrepareRequestDone:%p()\n",
+ this));
+ xactDebugOut((DEB_TRACE,
+ "Out CTransactionEnlistment::PrepareRequestDone\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::CommitRequestDone, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnlistment::CommitRequestDone(HRESULT hr)
+{
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnlistment::CommitRequestDone:%p()\n",
+ this));
+ xactDebugOut((DEB_TRACE,
+ "Out CTransactionEnlistment::CommitRequestDone\n"));
+ return E_NOTIMPL;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnlistment::AbortRequestDone, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnlistment::AbortRequestDone(HRESULT hr)
+{
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnlistment::AbortRequestDone:%p()\n",
+ this));
+ xactDebugOut((DEB_TRACE,
+ "Out CTransactionEnlistment::AbortRequestDone\n"));
+ return E_NOTIMPL;
+}
diff --git a/private/ole32/stg/xact/enlist.hxx b/private/ole32/stg/xact/enlist.hxx
new file mode 100644
index 000000000..9a5d2f814
--- /dev/null
+++ b/private/ole32/stg/xact/enlist.hxx
@@ -0,0 +1,68 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: enlist.hxx
+//
+// Contents: CTransactionEnlistment definition
+//
+// Classes:
+//
+// Functions:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __ENLIST_HXX__
+#define __ENLIST_HXX__
+
+class CTransactionCoordinator;
+class CXactList;
+
+class CTransactionEnlistment:
+ public ITransactionEnlistment,
+ public ITransactionEnlistmentRecover,
+ public ITransactionEnlistmentAsync
+{
+public:
+ CTransactionEnlistment(CXactList *pxl, CTransactionCoordinator *ptc);
+ ~CTransactionEnlistment();
+
+ //From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ //From ITransactionEnlistment
+ STDMETHOD(GetTransaction)(ITransaction **ppTransaction);
+ STDMETHOD(EarlyVote)(BOOL fVote, BOID *pboidReason);
+ STDMETHOD(HeuristicDecision)(
+ DWORD dwDecision,
+ BOID *pboidReason,
+ BOOL fDefecting);
+ STDMETHOD(Defect)(VOID);
+
+ //From ITransactionEnlistmentRecover
+ STDMETHOD(GetMoniker)(IMoniker **ppmk);
+ STDMETHOD(ReEnlist)(ITransactionResource *pUnkResource,
+ XACTUOW *pUOWExpected,
+ XACTRMGRID *prmgrid);
+ STDMETHOD(RecoveryComplete)(XACTRMGRID *prmgrid);
+
+ //From ITransactionEnlistmentAsync
+ STDMETHOD(PrepareRequestDone)(HRESULT hr,
+ IMoniker *pmk,
+ BOID *pboidReason);
+ STDMETHOD(CommitRequestDone)(HRESULT hr);
+ STDMETHOD(AbortRequestDone)(HRESULT hr);
+
+private:
+ LONG _cReferences;
+
+ CXactList *_pxlResource;
+ CTransactionCoordinator * _ptc;
+};
+
+#endif // #ifndef __ENLIST_HXX__
diff --git a/private/ole32/stg/xact/xact.cxx b/private/ole32/stg/xact/xact.cxx
new file mode 100644
index 000000000..8aefe3a58
--- /dev/null
+++ b/private/ole32/stg/xact/xact.cxx
@@ -0,0 +1,24 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: xact.cxx
+//
+// Contents: Transactioning common code
+//
+// Classes:
+//
+// Functions:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "xacthead.cxx"
+#pragma hdrstop
+
+
+#if DBG == 1
+DECLARE_INFOLEVEL(xact)
+#endif
diff --git a/private/ole32/stg/xact/xact.hxx b/private/ole32/stg/xact/xact.hxx
new file mode 100644
index 000000000..d5d96e326
--- /dev/null
+++ b/private/ole32/stg/xact/xact.hxx
@@ -0,0 +1,47 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: xact.hxx
+//
+// Contents: Transaction common stuff
+//
+// Classes:
+//
+// Functions:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __XACT_HXX__
+#define __XACT_HXX__
+
+
+#include <error.hxx>
+
+
+
+#if DBG == 1
+DECLARE_DEBUG(xact);
+#define xactDebugOut(x) xactInlineDebugOut x
+#define xactAssert(e) Win4Assert(e)
+#define xactVerify(e) Win4Assert(e)
+#else
+#define xactDebugOut(x)
+#define xactAssert(e)
+#define xactVerify(e) (e)
+#endif //DBG == 1
+
+#define xactErr(l, e) ErrJmp(xact, l, e, sc)
+#define xactChkTo(l, e) if (FAILED(sc = (e))) xactErr(l, sc) else 1
+#define xactHChkTo(l, e) if (FAILED(sc = GetScode(e))) xactErr(l, sc) else 1
+#define xactChk(e) xactChkTo(Err, e)
+#define xactHChk(e) xactHChkTo(Err, e)
+#define xactMemTo(l, e) if ((e) == NULL) xactErr(l, STG_E_INSUFFICIENTMEMORY) else 1
+#define xactMem(e) xactMemTo(Err, e)
+
+
+#endif // #ifndef __XACT_HXX__
+
diff --git a/private/ole32/stg/xact/xactdisp.cxx b/private/ole32/stg/xact/xactdisp.cxx
new file mode 100644
index 000000000..5c1c19f31
--- /dev/null
+++ b/private/ole32/stg/xact/xactdisp.cxx
@@ -0,0 +1,383 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: xactdisp.cxx
+//
+// Contents: CTransactionDispenser implementation
+//
+// Classes:
+//
+// Functions:
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "xacthead.cxx"
+#pragma hdrstop
+
+#include "xactdisp.hxx"
+#include "coord.hxx"
+#include "xactenum.hxx"
+
+
+CTransactionDispenser g_tdOleDispenser;
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionDispenser::CTransactionDispenser, public
+//
+// Synopsis: Constructor
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CTransactionDispenser::CTransactionDispenser()
+{
+ xactDebugOut((DEB_ITRACE, "In CTransactionDispenser::CTransactionDispenser:%p()\n", this));
+ _cReferences = 1;
+ _xstat.cOpen = 0;
+ _xstat.cCommitting = 0;
+ _xstat.cCommitted = 0;
+ _xstat.cAborting = 0;
+ _xstat.cAborted = 0;
+ _xstat.cInDoubt = 0;
+ _xstat.cHeuristicDecision = 0;
+
+ GetSystemTimeAsFileTime(&_xstat.timeTransactionsUp);
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionDispenser::CTransactionDispenser\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionDispenser::QueryInterface, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionDispenser::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc = S_OK;
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionDispenser::QueryInterface:%p()\n",
+ this));
+
+ *ppvObj = NULL;
+
+ if ((IsEqualIID(iid, IID_IUnknown)) ||
+ (IsEqualIID(iid, IID_ITransactionDispenser)))
+ {
+ *ppvObj = (ITransactionDispenser *)this;
+ }
+ else if (IsEqualIID(iid, IID_ITransactionDispenserAdmin))
+ {
+ *ppvObj = (ITransactionDispenserAdmin *)this;
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ if (SUCCEEDED(sc))
+ {
+ CTransactionDispenser::AddRef();
+ }
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionDispenser::QueryInterface\n"));
+ return ResultFromScode(sc);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionDispenser::AddRef, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CTransactionDispenser::AddRef(void)
+{
+ ULONG ulRet;
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionDispenser::AddRef:%p()\n",
+ this));
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionDispenser::AddRef\n"));
+ return ulRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionDispenser::Release, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CTransactionDispenser::Release(void)
+{
+ LONG lRet;
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionDispenser::Release:%p()\n",
+ this));
+
+ xactAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+ xactAssert(FALSE &&
+ "Refcount on OLE transaction dispenser went to 0.");
+ //We don't delete the object, since we're static. A refcount of
+ // zero indicates someone released too many times.
+// delete this;
+ }
+ else if (lRet < 0)
+ lRet = 0;
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionDispenser::Release\n"));
+ return (ULONG)lRet;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionDispenser::BeginTransaction, public
+//
+// Synopsis: Begin a new coordinated transaction
+//
+// Arguments: [punkOuter] -- Pointer to controlling unknown for ITransaction
+// [isoLevel] -- Desired isolation level
+// [isoFlags] -- From ISOFLAG enumeration
+// [ulTimeout] -- Amount of time before transaction is
+// automatically aborted.
+// [punkTransactionCoord] -- Pointer to enclosing transaction
+// [ppTransaction] -- Return of ITransaction pointer
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionDispenser::BeginTransaction(
+ IUnknown *punkOuter,
+ ISOLEVEL isoLevel,
+ ULONG isoFlags,
+ ULONG ulTimeout,
+ IUnknown *punkTransactionCoord,
+ ITransaction **ppTransaction)
+{
+ xactDebugOut((DEB_ITRACE,
+ "In CTransactionDispenser::BeginTransaction:%p()\n",
+ this));
+ SCODE sc;
+ CTransactionCoordinator *ptc = NULL;
+ CXactList *pxl;
+
+ if (punkTransactionCoord != NULL)
+ {
+ //We don't support nesting these things yet.
+ //BUGBUG: Do we want to support this?
+ return XACT_E_NOENLIST;
+ }
+
+ if (isoLevel > ISOLATIONLEVEL_READUNCOMMITTED)
+ {
+ //Can we really support higher isolation levels with this coordinator?
+ // Is the read-uncommitted requirement really part of the docfile/OFS
+ // resource manager, and not that of the coordinator?
+ return XACT_E_ISOLATIONLEVEL;
+ }
+
+ //BUGBUG: Check ISOFLAGS
+
+ xactMem(pxl = new CXactList);
+ xactMem(ptc = new CTransactionCoordinator(this,
+ punkOuter,
+ isoLevel,
+ isoFlags,
+ ulTimeout));
+ xactChk(ptc->Init());
+ pxl->SetNext(_pxlTransactions);
+ _pxlTransactions = pxl;
+ pxl->SetTransaction((ITransaction *)ptc);
+
+ *ppTransaction = (ITransaction *)ptc;
+ _xstat.cOpen++;
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionDispenser::BeginTransaction\n"));
+ return sc;
+
+Err:
+ delete ptc;
+ delete pxl;
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionDispenser::EnumTransactions, public
+//
+// Synopsis: Get enumerator on current transactions
+//
+// Arguments: [ppenum] -- Return location for IEnumTransaction object
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionDispenser::EnumTransactions(IEnumTransaction **ppenum)
+{
+ SCODE sc;
+ xactDebugOut((DEB_ITRACE,
+ "In CTransactionDispenser::EnumTransactions:%p()\n",
+ this));
+
+ xactMem(*ppenum = new CTransactionEnum(this));
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionDispenser::EnumTransactions\n"));
+Err:
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionDispenser::GetStatistics, public
+//
+// Synopsis: Return statistics
+//
+// Arguments: [pStatistics] -- Return location for statistics
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionDispenser::GetStatistics(XACTSTATS *pStatistics)
+{
+ xactDebugOut((DEB_ITRACE,
+ "In CTransactionDispenser::GetStatistics:%p()\n",
+ this));
+
+ *pStatistics = _xstat;
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionDispenser::GetStatistics\n"));
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionDispenser::Defect, public
+//
+// Synopsis: Defect a transaction from the list.
+//
+// Arguments: [pt] -- Pointer to transaction to defect
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+SCODE CTransactionDispenser::Defect(ITransaction *pt)
+{
+ xactDebugOut((DEB_ITRACE, "In CTransactionDispenser::Defect:%p()\n", this));
+ CXactList *pxlPrev = NULL;
+ CXactList *pxlTemp = _pxlTransactions;
+
+ while (pxlTemp->GetTransaction() != pt)
+ {
+ pxlPrev = pxlTemp;
+ pxlTemp = pxlTemp->GetNext();
+ xactAssert(pxlTemp != NULL);
+ }
+
+ if (pxlPrev == NULL)
+ {
+ _pxlTransactions = _pxlTransactions->GetNext();
+ }
+ else
+ {
+ pxlPrev->SetNext(pxlTemp->GetNext());
+ }
+ delete pxlTemp;
+ _xstat.cOpen--;
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionDispenser::Defect\n"));
+ return S_OK;
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleGetTransactionDispenser, public
+//
+// Synopsis: Return a pointer to the OLE default transaction dispenser
+//
+// Arguments: [pptd] -- Return location
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+HRESULT OleGetTransactionDispenser(ITransactionDispenser **pptd)
+{
+ xactDebugOut((DEB_ITRACE, "In OleGetTransactionDispenser()\n"));
+
+ *pptd = &g_tdOleDispenser;
+ g_tdOleDispenser.AddRef();
+
+ xactDebugOut((DEB_ITRACE, "Out OleGetTransactionDispenser\n"));
+ return S_OK;
+}
diff --git a/private/ole32/stg/xact/xactdisp.hxx b/private/ole32/stg/xact/xactdisp.hxx
new file mode 100644
index 000000000..214a61725
--- /dev/null
+++ b/private/ole32/stg/xact/xactdisp.hxx
@@ -0,0 +1,64 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: xactdisp.hxx
+//
+// Contents: CTransactionDispenser class
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __XACTDISP_HXX__
+#define __XACTDISP_HXX__
+
+class CTransactionEnum;
+class CXactList;
+
+//ITransactionDispenser inherited through ITransactionDispenserAdmin
+class CTransactionDispenser: public ITransactionDispenserAdmin
+{
+public:
+ CTransactionDispenser();
+
+ //From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ //From ITransactionDispenser
+ STDMETHOD(BeginTransaction)(IUnknown *punkOuter,
+ ISOLEVEL isoLevel,
+ ULONG isoFlags,
+ ULONG ulTimeout,
+ IUnknown *punkTransactionCoord,
+ ITransaction **ppTransaction);
+
+ //From ITransactionDispenserAdmin
+ STDMETHOD(EnumTransactions)(IEnumTransaction **ppenum);
+ STDMETHOD(GetStatistics)(XACTSTATS *pStatistics);
+
+ //Internal methods
+ inline XACTSTATS * GetStats(void);
+ SCODE Defect(ITransaction *pt);
+
+private:
+ LONG _cReferences;
+
+ XACTSTATS _xstat;
+
+ CXactList *_pxlTransactions;
+
+ friend CTransactionEnum;
+};
+
+inline XACTSTATS * CTransactionDispenser::GetStats(void)
+{
+ return &_xstat;
+}
+
+HRESULT OleGetTransactionDispenser(ITransactionDispenser **pptd);
+
+#endif // #ifndef __XACTDISP_HXX__
diff --git a/private/ole32/stg/xact/xactenum.cxx b/private/ole32/stg/xact/xactenum.cxx
new file mode 100644
index 000000000..2f78c5441
--- /dev/null
+++ b/private/ole32/stg/xact/xactenum.cxx
@@ -0,0 +1,679 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: xactenum.cxx
+//
+// Contents: CResourceEnum implementation
+//
+// Classes:
+//
+// Functions:
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#include "xacthead.cxx"
+#pragma hdrstop
+
+#include "xactenum.hxx"
+#include "coord.hxx"
+#include "xactlist.hxx"
+#include "xactdisp.hxx"
+
+#if 0
+//Instantiate so we can make sure that all the methods are
+// properly declared.
+
+CResourceEnum teFoo(NULL);
+#endif
+
+
+//BUGBUG: This code is generally not safe in the face of resources
+// defecting while an enumeration is going on. This needs to
+// be fixed.
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CResourceEnum::CResourceEnum, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [ptc] -- Pointer to transaction coordinator
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CResourceEnum::CResourceEnum(CTransactionCoordinator *ptc)
+{
+ xactDebugOut((DEB_ITRACE, "In CResourceEnum::CResourceEnum:%p()\n", this));
+ _ptc = ptc;
+ _ptc->AddRef();
+
+ Reset();
+
+ xactDebugOut((DEB_ITRACE, "Out CResourceEnum::CResourceEnum\n"));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CResourceEnum::~CResourceEnum, public
+//
+// Synopsis: Destructor
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CResourceEnum::~CResourceEnum()
+{
+ xactDebugOut((DEB_ITRACE, "In CResourceEnum::~CResourceEnum:%p()\n", this));
+ _ptc->Release();
+
+ xactDebugOut((DEB_ITRACE, "Out CResourceEnum::~CResourceEnum\n"));
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CResourceEnum::QueryInterface, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CResourceEnum::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc = S_OK;
+ xactDebugOut((DEB_TRACE,
+ "In CResourceEnum::QueryInterface:%p()\n",
+ this));
+
+ *ppvObj = NULL;
+
+ if ((IsEqualIID(iid, IID_IUnknown)) || (IsEqualIID(iid, IID_IEnumXACTRE)))
+ {
+ *ppvObj = (IEnumXACTRE *)this;
+ CResourceEnum::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ xactDebugOut((DEB_TRACE, "Out CResourceEnum::QueryInterface\n"));
+ return ResultFromScode(sc);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CResourceEnum::AddRef, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CResourceEnum::AddRef(void)
+{
+ ULONG ulRet;
+ xactDebugOut((DEB_TRACE,
+ "In CResourceEnum::AddRef:%p()\n",
+ this));
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+
+ xactDebugOut((DEB_TRACE, "Out CResourceEnum::AddRef\n"));
+ return ulRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CResourceEnum::Release, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CResourceEnum::Release(void)
+{
+ LONG lRet;
+ xactDebugOut((DEB_TRACE,
+ "In CResourceEnum::Release:%p()\n",
+ this));
+
+ xactAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ lRet = 0;
+
+ xactDebugOut((DEB_TRACE, "Out CResourceEnum::Release\n"));
+ return (ULONG)lRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CResourceEnum::Next, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CResourceEnum::Next(ULONG celt,
+ XACTRE *rgelt,
+ ULONG *pceltFetched)
+{
+ xactDebugOut((DEB_ITRACE, "In CResourceEnum::Next:%p()\n", this));
+
+ SCODE sc = S_OK;
+
+ ULONG cFetched = 0;
+ XACTRE *pxCurrent = rgelt;
+
+ for (ULONG i = 0; (_pxlCurrent != NULL) && (i < celt); i++)
+ {
+ IUnknown *punk;
+
+ if (!_fSinglePhaseReturned)
+ {
+ _fSinglePhaseReturned = TRUE;
+ xactChk(_ptc->_pxlSinglePhase->GetTransaction()->
+ QueryInterface(IID_IUnknown,
+ (void **)&punk));
+ pxCurrent->type = XACTRETY_ONEPHASE;
+ pxCurrent->status = _ptc->_pxlSinglePhase->GetState();
+ pxCurrent->grfRMTC = _ptc->_pxlSinglePhase->GetFlags();
+ pxCurrent->rmgrid = *(_ptc->_pxlSinglePhase->GetRMGRID());
+
+ }
+ else
+ {
+ xactChk(_pxlCurrent->GetResource()->QueryInterface(IID_IUnknown,
+ (void **)&punk));
+ pxCurrent->type = XACTRETY_TWOPHASE;
+ pxCurrent->status = _pxlCurrent->GetState();
+ pxCurrent->grfRMTC = _pxlCurrent->GetFlags();
+ pxCurrent->rmgrid = *(_pxlCurrent->GetRMGRID());
+
+ _pxlCurrent = _pxlCurrent->GetNext();
+ }
+
+ pxCurrent->pResource = punk;
+ //Note: We don't release punk, since we want to return a reference
+ // to the caller.
+
+ cFetched++;
+ pxCurrent++;
+ }
+
+ if (pceltFetched != NULL)
+ {
+ *pceltFetched = cFetched;
+ }
+
+ xactDebugOut((DEB_ITRACE, "Out CResourceEnum::Next\n"));
+
+ return (cFetched == celt) ? S_OK : S_FALSE;
+Err:
+ if (pceltFetched != NULL)
+ {
+ *pceltFetched = cFetched;
+ }
+
+ return sc;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CResourceEnum::Skip, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CResourceEnum::Skip(ULONG celt)
+{
+ xactDebugOut((DEB_ITRACE, "In CResourceEnum::Skip:%p()\n", this));
+
+ for (ULONG i = 0; (_pxlCurrent != NULL) && (i < celt); i++)
+ {
+ _pxlCurrent = _pxlCurrent->GetNext();
+ }
+
+ xactDebugOut((DEB_ITRACE, "Out CResourceEnum::Skip\n"));
+
+ return (i == celt) ? S_OK : S_FALSE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CResourceEnum::Reset, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CResourceEnum::Reset(void)
+{
+ xactDebugOut((DEB_ITRACE, "In CResourceEnum::Reset:%p()\n", this));
+ _pxlCurrent = _ptc->_pxlResources;
+ _fSinglePhaseReturned = FALSE;
+ xactDebugOut((DEB_ITRACE, "Out CResourceEnum::Reset\n"));
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CResourceEnum::Clone, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CResourceEnum::Clone(IEnumXACTRE **ppenum)
+{
+ SCODE sc;
+
+ xactDebugOut((DEB_ITRACE, "In CResourceEnum::Clone:%p()\n", this));
+ CResourceEnum *pre;
+
+ xactMem(*ppenum = new CResourceEnum(_ptc));
+ ((CResourceEnum *)(*ppenum))->_pxlCurrent = _pxlCurrent;
+
+ xactDebugOut((DEB_ITRACE, "Out CResourceEnum::Clone\n"));
+
+Err:
+ return sc;
+}
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnum::CTransactionEnum, public
+//
+// Synopsis: Constructor
+//
+// Arguments: [ptc] -- Pointer to transaction coordinator
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CTransactionEnum::CTransactionEnum(CTransactionDispenser *ptd)
+{
+ xactDebugOut((DEB_ITRACE, "In CTransactionEnum::CTransactionEnum:%p()\n", this));
+ _ptd = ptd;
+ _ptd->AddRef();
+
+ Reset();
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionEnum::CTransactionEnum\n"));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnum::~CTransactionEnum, public
+//
+// Synopsis: Destructor
+//
+// Returns: Appropriate status code
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+CTransactionEnum::~CTransactionEnum()
+{
+ xactDebugOut((DEB_ITRACE, "In CTransactionEnum::~CTransactionEnum:%p()\n", this));
+ _ptd->Release();
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionEnum::~CTransactionEnum\n"));
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnum::QueryInterface, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnum::QueryInterface(REFIID iid, void **ppvObj)
+{
+ SCODE sc = S_OK;
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnum::QueryInterface:%p()\n",
+ this));
+
+ *ppvObj = NULL;
+
+ if ((IsEqualIID(iid, IID_IUnknown)) || (IsEqualIID(iid, IID_IEnumTransaction)))
+ {
+ *ppvObj = (IEnumTransaction *)this;
+ CTransactionEnum::AddRef();
+ }
+ else
+ {
+ sc = E_NOINTERFACE;
+ }
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionEnum::QueryInterface\n"));
+ return ResultFromScode(sc);
+}
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnum::AddRef, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CTransactionEnum::AddRef(void)
+{
+ ULONG ulRet;
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnum::AddRef:%p()\n",
+ this));
+ InterlockedIncrement(&_cReferences);
+ ulRet = _cReferences;
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionEnum::AddRef\n"));
+ return ulRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnum::Release, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 05-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP_(ULONG) CTransactionEnum::Release(void)
+{
+ LONG lRet;
+ xactDebugOut((DEB_TRACE,
+ "In CTransactionEnum::Release:%p()\n",
+ this));
+
+ xactAssert(_cReferences > 0);
+ lRet = InterlockedDecrement(&_cReferences);
+ if (lRet == 0)
+ {
+ delete this;
+ }
+ else if (lRet < 0)
+ lRet = 0;
+
+ xactDebugOut((DEB_TRACE, "Out CTransactionEnum::Release\n"));
+ return (ULONG)lRet;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnum::Next, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnum::Next(ULONG celt,
+ ITransaction **rgelt,
+ ULONG *pceltFetched)
+{
+ xactDebugOut((DEB_ITRACE, "In CTransactionEnum::Next:%p()\n", this));
+
+ ULONG cFetched = 0;
+ ITransaction **ptCurrent = rgelt;
+
+ for (ULONG i = 0; (_pxlCurrent != NULL) && (i < celt); i++)
+ {
+ *ptCurrent = _pxlCurrent->GetTransaction();
+ _pxlCurrent->GetTransaction()->AddRef();
+
+ cFetched++;
+ _pxlCurrent = _pxlCurrent->GetNext();
+ ptCurrent++;
+ }
+
+ if (pceltFetched != NULL)
+ {
+ *pceltFetched = cFetched;
+ }
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionEnum::Next\n"));
+
+ return (cFetched == celt) ? S_OK : S_FALSE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnum::Skip, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnum::Skip(ULONG celt)
+{
+ xactDebugOut((DEB_ITRACE, "In CTransactionEnum::Skip:%p()\n", this));
+
+ for (ULONG i = 0; (_pxlCurrent != NULL) && (i < celt); i++)
+ {
+ _pxlCurrent = _pxlCurrent->GetNext();
+ }
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionEnum::Skip\n"));
+
+ return (i == celt) ? S_OK : S_FALSE;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnum::Reset, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnum::Reset(void)
+{
+ xactDebugOut((DEB_ITRACE, "In CTransactionEnum::Reset:%p()\n", this));
+
+ _pxlCurrent = _ptd->_pxlTransactions;
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionEnum::Reset\n"));
+
+ return S_OK;
+}
+
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTransactionEnum::Clone, public
+//
+// Synopsis:
+//
+// Arguments:
+//
+// Returns: Appropriate status code
+//
+// Modifies:
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+STDMETHODIMP CTransactionEnum::Clone(IEnumTransaction **ppenum)
+{
+ SCODE sc;
+
+ xactDebugOut((DEB_ITRACE, "In CTransactionEnum::Clone:%p()\n", this));
+
+ xactMem(*ppenum = new CTransactionEnum(_ptd));
+ ((CTransactionEnum *)(*ppenum))->_pxlCurrent = _pxlCurrent;
+
+ xactDebugOut((DEB_ITRACE, "Out CTransactionEnum::Clone\n"));
+Err:
+ return sc;
+}
diff --git a/private/ole32/stg/xact/xactenum.hxx b/private/ole32/stg/xact/xactenum.hxx
new file mode 100644
index 000000000..8e5c8a13c
--- /dev/null
+++ b/private/ole32/stg/xact/xactenum.hxx
@@ -0,0 +1,98 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: xactenum.hxx
+//
+// Contents: IEnumXACTRE implementation
+//
+// Classes: CTransactionEnum
+//
+// Functions:
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __XACTENUM_HXX__
+#define __XACTENUM_HXX__
+
+class CTransactionCoordinator;
+class CXactList;
+class CTransactionDispenser;
+
+//+---------------------------------------------------------------------------
+//
+// Class: CTransactionEnum
+//
+// Purpose: Enumerator over transactions from a dispenser
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+class CTransactionEnum: public IEnumTransaction
+{
+public:
+ CTransactionEnum(CTransactionDispenser *ptd);
+ ~CTransactionEnum();
+
+ //From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ //From IEnumTransaction
+ STDMETHOD(Next)(ULONG celt, ITransaction **rgelt, ULONG *pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(IEnumTransaction **ppenum);
+
+private:
+ LONG _cReferences;
+ CTransactionDispenser *_ptd;
+
+ CXactList *_pxlCurrent;
+};
+
+
+
+
+//+---------------------------------------------------------------------------
+//
+// Class: CResourceEnum
+//
+// Purpose: Enumerator over resources in a transaction
+//
+// History: 26-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+
+class CResourceEnum: public IEnumXACTRE
+{
+public:
+ CResourceEnum(CTransactionCoordinator *ptc);
+ ~CResourceEnum();
+
+ //From IUnknown
+ STDMETHOD(QueryInterface)(REFIID iid, void **ppvObj);
+ STDMETHOD_(ULONG,AddRef)(void);
+ STDMETHOD_(ULONG,Release)(void);
+
+ //From IEnumXACTRE
+ STDMETHOD(Next)(ULONG celt, XACTRE *rgelt, ULONG *pceltFetched);
+ STDMETHOD(Skip)(ULONG celt);
+ STDMETHOD(Reset)(void);
+ STDMETHOD(Clone)(IEnumXACTRE **ppenum);
+
+private:
+ LONG _cReferences;
+ BOOL _fSinglePhaseReturned;
+ CTransactionCoordinator *_ptc;
+
+ CXactList *_pxlCurrent;
+};
+
+#endif // #ifndef __XACTENUM_HXX__
diff --git a/private/ole32/stg/xact/xacthead.cxx b/private/ole32/stg/xact/xacthead.cxx
new file mode 100644
index 000000000..787556014
--- /dev/null
+++ b/private/ole32/stg/xact/xacthead.cxx
@@ -0,0 +1,23 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1993.
+//
+// File: xacthead.cxx
+//
+// Contents: Precompiled header file
+//
+// History: 22-Jun-95 PhilipLa Created.
+//
+//----------------------------------------------------------------------------
+
+#include <windows.h>
+
+#include <valid.h>
+#include <debnot.h>
+
+#include <oledb.h>
+
+#include <transact.h>
+
+#include "xact.hxx"
diff --git a/private/ole32/stg/xact/xactlist.hxx b/private/ole32/stg/xact/xactlist.hxx
new file mode 100644
index 000000000..f4f93047c
--- /dev/null
+++ b/private/ole32/stg/xact/xactlist.hxx
@@ -0,0 +1,223 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1992 - 1994.
+//
+// File: xactlist.hxx
+//
+// Contents: Linked list class
+//
+// Classes:
+//
+// Functions:
+//
+// History: 24-Jul-95 PhilipLa Created
+//
+//----------------------------------------------------------------------------
+
+#ifndef __XACTLIST_HXX__
+#define __XACTLIST_HXX__
+
+typedef enum XACTTYPETAG
+{
+ Empty,
+ Resource,
+ Adjust,
+ Veto,
+ Outcome,
+ Transaction
+} XACTTYPE;
+
+//+---------------------------------------------------------------------------
+//
+// Class: CXactList
+//
+// Purpose: Generic linked list class for use by transaction coordinator
+//
+// Interface:
+//
+// History: 24-Jul-95 PhilipLa Created
+//
+// Notes:
+//
+//----------------------------------------------------------------------------
+
+class CXactList
+{
+public:
+ inline CXactList();
+
+ inline CXactList *GetNext(void);
+ inline void SetNext(CXactList *pxl);
+
+ inline DWORD GetFlags(void);
+ inline void SetFlags(DWORD dwFlags);
+
+ inline XACTSTAT GetState(void);
+ inline void SetState(XACTSTAT xactstat);
+
+ inline ITransactionResource *GetResource(void);
+ inline void SetResource(ITransactionResource *ptr);
+
+ inline ITransactionAdjustEvents *GetAdjust(void);
+ inline void SetAdjust(ITransactionAdjustEvents *padj);
+
+ inline ITransactionVetoEvents *GetVeto(void);
+ inline void SetVeto(ITransactionVetoEvents *pveto);
+
+ inline ITransactionOutcomeEvents *GetOutcome(void);
+ inline void SetOutcome(ITransactionOutcomeEvents *pout);
+
+ inline ITransaction *GetTransaction(void);
+ inline void SetTransaction(ITransaction *pout);
+
+ inline ITransactionEnlistment *GetEnlistment(void);
+ inline void SetEnlistment(ITransactionEnlistment *pte);
+
+ inline XACTRMGRID * GetRMGRID(void);
+ inline void SetRMGRID(XACTRMGRID * prmgrid);
+
+private:
+ union {
+ ITransactionResource *_ptr;
+ ITransactionAdjustEvents *_padj;
+ ITransactionVetoEvents *_pveto;
+ ITransactionOutcomeEvents *_pout;
+ ITransaction *_ptrans;
+ };
+ ITransactionEnlistment *_pte;
+ DWORD _dwFlags;
+ XACTSTAT _xactstat;
+ XACTRMGRID _rmgrid;
+ XACTTYPE _etype;
+
+ CXactList *_pxlNext;
+};
+
+
+inline CXactList::CXactList()
+{
+ _ptr = NULL;
+ _dwFlags = 0;
+ _pxlNext = NULL;
+ _etype = Empty;
+ _xactstat = XACTSTAT_ALL;
+ _rmgrid = BOID_NULL;
+}
+
+inline CXactList * CXactList::GetNext(void)
+{
+ return _pxlNext;
+}
+
+inline void CXactList::SetNext(CXactList *pxl)
+{
+ _pxlNext = pxl;
+}
+
+inline DWORD CXactList::GetFlags(void)
+{
+ return _dwFlags;
+}
+
+inline void CXactList::SetFlags(DWORD dwFlags)
+{
+ _dwFlags = dwFlags;
+}
+
+inline XACTRMGRID * CXactList::GetRMGRID(void)
+{
+ return &_rmgrid;
+}
+
+inline void CXactList::SetRMGRID(XACTRMGRID *prmgrid)
+{
+ if (prmgrid != NULL)
+ _rmgrid = *prmgrid;
+}
+
+inline XACTSTAT CXactList::GetState(void)
+{
+ return _xactstat;
+}
+
+inline void CXactList::SetState(XACTSTAT xactstat)
+{
+ _xactstat = xactstat;
+}
+
+inline ITransactionResource *CXactList::GetResource(void)
+{
+ xactAssert(_etype = Resource);
+ return _ptr;
+}
+
+inline void CXactList::SetResource(ITransactionResource *ptr)
+{
+ _ptr = ptr;
+ _etype = Resource;
+ _xactstat = XACTSTAT_OPEN;
+}
+
+inline ITransactionAdjustEvents *CXactList::GetAdjust(void)
+{
+ xactAssert(_etype = Adjust);
+ return _padj;
+}
+
+inline void CXactList::SetAdjust(ITransactionAdjustEvents *padj)
+{
+ _padj = padj;
+ _etype = Adjust;
+}
+
+inline ITransactionVetoEvents *CXactList::GetVeto(void)
+{
+ xactAssert(_etype = Veto);
+ return _pveto;
+}
+
+inline void CXactList::SetVeto(ITransactionVetoEvents *pveto)
+{
+ _pveto = pveto;
+ _etype = Veto;
+}
+
+inline ITransactionOutcomeEvents *CXactList::GetOutcome(void)
+{
+ xactAssert(_etype = Outcome);
+ return _pout;
+}
+
+inline void CXactList::SetOutcome(ITransactionOutcomeEvents *pout)
+{
+ _pout = pout;
+ _etype = Outcome;
+}
+
+inline ITransaction *CXactList::GetTransaction(void)
+{
+ xactAssert(_etype = Transaction);
+ return _ptrans;
+}
+
+inline void CXactList::SetTransaction(ITransaction *ptrans)
+{
+ _ptrans = ptrans;
+ _etype = Transaction;
+ _xactstat = XACTSTAT_OPEN;
+}
+
+inline ITransactionEnlistment *CXactList::GetEnlistment(void)
+{
+ return _pte;
+}
+
+inline void CXactList::SetEnlistment(ITransactionEnlistment *pte)
+{
+ _pte = pte;
+}
+
+#endif // #ifndef __XACTLIST_HXX__
+
+